diff --git a/Makefile.am b/Makefile.am index 5afacfa7fc..aaffb9842b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -4,18 +4,17 @@ AM_CFLAGS = $(WERROR_CFLAGS) MONOTOUCH_SUBDIRS = $(libgc_dir) eglib/src mono +# Some tools might not build when cross-compiling if CROSS_COMPILING -SUBDIRS = po $(libgc_dir) eglib mono $(ikvm_native_dir) support data runtime scripts man samples msvc $(docs_dir) acceptance-tests -# Keep in sync with SUBDIRS -## 'tools' is not normally built -DIST_SUBDIRS = m4 po $(libgc_dir) eglib mono ikvm-native support data runtime scripts man samples tools msvc docs acceptance-tests +tools_dir = else -SUBDIRS = po $(libgc_dir) eglib mono $(ikvm_native_dir) support data runtime scripts man samples msvc $(docs_dir) acceptance-tests -# Keep in sync with SUBDIRS -## 'tools' is not normally built -DIST_SUBDIRS = m4 po $(libgc_dir) eglib mono ikvm-native support data runtime scripts man samples tools msvc docs acceptance-tests +tools_dir = tools endif +SUBDIRS = po $(libgc_dir) eglib mono $(ikvm_native_dir) support data runtime scripts man samples $(tools_dir) msvc $(docs_dir) acceptance-tests llvm +# Keep in sync with SUBDIRS +DIST_SUBDIRS = m4 po $(libgc_dir) eglib mono ikvm-native support data runtime scripts man samples tools msvc docs acceptance-tests llvm + all: update_submodules SUBMODULE_ERROR='Could not recursively update all git submodules. You may experience compilation problems if some submodules are out of date' @@ -68,6 +67,14 @@ get-monolite-latest: cd $(mcslib) && { (wget -O- $(monolite_url) || curl $(monolite_url)) | gzip -d | tar xf - ; } cd $(mcslib) && mv -f monolite-* monolite +if BITCODE +BITCODE_CHECK=yes +endif + +.PHONY: check-ci +check-ci: + MONO_LLVMONLY=$(BITCODE_CHECK) $(srcdir)/scripts/ci/run-test-$(TEST_PROFILE).sh + .PHONY: validate do-build-mono-mcs mcs-do-clean mcs-do-tests validate: do-build-mono-mcs $(MAKE) mcs-do-tests @@ -153,6 +160,7 @@ package-inputs: read libou; echo " $$libou"; \ read fx_ver; echo " $$fx_ver"; \ read profile; echo " $$profile"; \ + read resxt; echo " $$resxt"; \ read resp; echo " $$resp"; \ echo " ") >> msvc/scripts/order.xml; \ done diff --git a/Makefile.in b/Makefile.in index 060e2374c9..152dedfc88 100644 --- a/Makefile.in +++ b/Makefile.in @@ -205,6 +205,8 @@ distcleancheck_listfiles = find . -type f -print ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AOT_BUILD_FLAGS = @AOT_BUILD_FLAGS@ +AOT_RUN_FLAGS = @AOT_RUN_FLAGS@ API_VER = @API_VER@ AR = @AR@ AS = @AS@ @@ -213,6 +215,11 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOEHM_DEFINES = @BOEHM_DEFINES@ +BTLS_ARCH = @BTLS_ARCH@ +BTLS_CFLAGS = @BTLS_CFLAGS@ +BTLS_CMAKE_ARGS = @BTLS_CMAKE_ARGS@ +BTLS_PLATFORM = @BTLS_PLATFORM@ +BTLS_ROOT = @BTLS_ROOT@ BUILD_EXEEXT = @BUILD_EXEEXT@ CC = @CC@ CCAS = @CCAS@ @@ -222,6 +229,7 @@ CCDEPMODE = @CCDEPMODE@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMAKE = @CMAKE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ @@ -242,7 +250,6 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_PERF_EVENTS = @ENABLE_PERF_EVENTS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDKX11 = @GDKX11@ @@ -257,10 +264,12 @@ HAVE_MSGFMT = @HAVE_MSGFMT@ HOST_CC = @HOST_CC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MOBILE_STATIC = @INSTALL_MOBILE_STATIC@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTL = @INTL@ +INVARIANT_AOT_OPTIONS = @INVARIANT_AOT_OPTIONS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBC = @LIBC@ @@ -307,6 +316,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ +PLATFORM_AOT_SUFFIX = @PLATFORM_AOT_SUFFIX@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -316,6 +326,7 @@ SHELL = @SHELL@ SQLITE = @SQLITE@ SQLITE3 = @SQLITE3@ STRIP = @STRIP@ +TEST_PROFILE = @TEST_PROFILE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VTUNE_CFLAGS = @VTUNE_CFLAGS@ @@ -407,12 +418,13 @@ top_srcdir = @top_srcdir@ ACLOCAL_AMFLAGS = -I m4 AM_CFLAGS = $(WERROR_CFLAGS) MONOTOUCH_SUBDIRS = $(libgc_dir) eglib/src mono -@CROSS_COMPILING_FALSE@SUBDIRS = po $(libgc_dir) eglib mono $(ikvm_native_dir) support data runtime scripts man samples msvc $(docs_dir) acceptance-tests -@CROSS_COMPILING_TRUE@SUBDIRS = po $(libgc_dir) eglib mono $(ikvm_native_dir) support data runtime scripts man samples msvc $(docs_dir) acceptance-tests +@CROSS_COMPILING_FALSE@tools_dir = tools + +# Some tools might not build when cross-compiling +@CROSS_COMPILING_TRUE@tools_dir = +SUBDIRS = po $(libgc_dir) eglib mono $(ikvm_native_dir) support data runtime scripts man samples $(tools_dir) msvc $(docs_dir) acceptance-tests llvm # Keep in sync with SUBDIRS -@CROSS_COMPILING_FALSE@DIST_SUBDIRS = m4 po $(libgc_dir) eglib mono ikvm-native support data runtime scripts man samples tools msvc docs acceptance-tests -# Keep in sync with SUBDIRS -@CROSS_COMPILING_TRUE@DIST_SUBDIRS = m4 po $(libgc_dir) eglib mono ikvm-native support data runtime scripts man samples tools msvc docs acceptance-tests +DIST_SUBDIRS = m4 po $(libgc_dir) eglib mono ikvm-native support data runtime scripts man samples tools msvc docs acceptance-tests llvm SUBMODULE_ERROR = 'Could not recursively update all git submodules. You may experience compilation problems if some submodules are out of date' EXTRA_DIST = \ README.md \ @@ -437,6 +449,7 @@ mcslib = $(mcs_topdir)/class/lib monolite = $(mcslib)/monolite mono_corlib_version = $(shell sed -n "s/\#define MONO_CORLIB_VERSION //p" $(srcdir)/mono/metadata/appdomain.c) monolite_url = http://download.mono-project.com/monolite/monolite-$(mono_corlib_version)-latest.tar.gz +@BITCODE_TRUE@BITCODE_CHECK = yes all: config.h $(MAKE) $(AM_MAKEFLAGS) all-recursive @@ -949,6 +962,10 @@ get-monolite-latest: cd $(mcslib) && { (wget -O- $(monolite_url) || curl $(monolite_url)) | gzip -d | tar xf - ; } cd $(mcslib) && mv -f monolite-* monolite +.PHONY: check-ci +check-ci: + MONO_LLVMONLY=$(BITCODE_CHECK) $(srcdir)/scripts/ci/run-test-$(TEST_PROFILE).sh + .PHONY: validate do-build-mono-mcs mcs-do-clean mcs-do-tests validate: do-build-mono-mcs $(MAKE) mcs-do-tests @@ -1031,6 +1048,7 @@ package-inputs: read libou; echo " $$libou"; \ read fx_ver; echo " $$fx_ver"; \ read profile; echo " $$profile"; \ + read resxt; echo " $$resxt"; \ read resp; echo " $$resp"; \ echo " ") >> msvc/scripts/order.xml; \ done diff --git a/acceptance-tests/Makefile.am b/acceptance-tests/Makefile.am index 522cb36c9e..c03adcc0c4 100644 --- a/acceptance-tests/Makefile.am +++ b/acceptance-tests/Makefile.am @@ -1,4 +1,5 @@ ACCEPTANCE_TESTS_PATH=external +BENCHMARKER_PATH=$(ACCEPTANCE_TESTS_PATH)/benchmarker ROSLYN_PATH=$(ACCEPTANCE_TESTS_PATH)/roslyn CORECLR_PATH=$(ACCEPTANCE_TESTS_PATH)/coreclr MSTESTSUITE_PATH=$(ACCEPTANCE_TESTS_PATH)/ms-test-suite @@ -14,10 +15,11 @@ MCS = $(RUNTIME) $(mcs_topdir)/class/lib/build/mcs.exe ILASM = $(RUNTIME) $(CLASS)/ilasm.exe include versions.mk +include profiler-stress.mk include roslyn.mk include coreclr.mk include ms-test-suite.mk -check-full: check-roslyn check-coreclr check-ms-test-suite +check-full: check-profiler-stress check-roslyn check-coreclr check-ms-test-suite clean-local: clean-local-coreclr diff --git a/acceptance-tests/Makefile.in.REMOVED.git-id b/acceptance-tests/Makefile.in.REMOVED.git-id index c147f722f7..1e5f706790 100644 --- a/acceptance-tests/Makefile.in.REMOVED.git-id +++ b/acceptance-tests/Makefile.in.REMOVED.git-id @@ -1 +1 @@ -32956102bf8b153420545562e9066c249e538001 \ No newline at end of file +61a884697b79e16cc9e036de2b08a7e79166e5ac \ No newline at end of file diff --git a/acceptance-tests/SUBMODULES.json b/acceptance-tests/SUBMODULES.json index 7fcac6c3e9..01faee39c9 100644 --- a/acceptance-tests/SUBMODULES.json +++ b/acceptance-tests/SUBMODULES.json @@ -18,9 +18,17 @@ { "name": "ms-test-suite", "url": "git@github.com:xamarin/ms-test-suite.git", - "rev": "840653918efed24f00f5e166094f06354cae7255", + "rev": "eb7cd709549bffe170653a50805f1593d66ea81e", "remote-branch": "origin/master", "branch": "master", "directory": "ms-test-suite" + }, + { + "name": "benchmarker", + "url": "git://github.com/xamarin/benchmarker.git", + "rev": "97f618cd585af549dd861b7c142656c496f6a89b", + "remote-branch": "origin/master", + "branch": "master", + "directory": "benchmarker" } -] \ No newline at end of file +] diff --git a/acceptance-tests/coreclr.mk.REMOVED.git-id b/acceptance-tests/coreclr.mk.REMOVED.git-id index 816e6b2a14..e8a38be67e 100644 --- a/acceptance-tests/coreclr.mk.REMOVED.git-id +++ b/acceptance-tests/coreclr.mk.REMOVED.git-id @@ -1 +1 @@ -8f75b05470fe46685d232f3a35933dbc1080fc59 \ No newline at end of file +1f4be3d1e8fbc9cefb15d72648b5068298d01356 \ No newline at end of file diff --git a/acceptance-tests/ms-test-suite.mk b/acceptance-tests/ms-test-suite.mk index c1c1619948..bd85bd494b 100644 --- a/acceptance-tests/ms-test-suite.mk +++ b/acceptance-tests/ms-test-suite.mk @@ -1,10 +1,10 @@ check-ms-test-suite: @if $(MAKE) validate-ms-test-suite RESET_VERSIONS=1; then \ - $(MAKE) -C $(MSTESTSUITE_PATH)/conformance build MCS="$(MCS) -t:library -warn:1 -r:nunit.framework" && \ + $(MAKE) -C $(MSTESTSUITE_PATH)/conformance build MCS="$(MCS) -debug -t:library -warn:1 -r:nunit.framework" && \ $(MAKE) -C $(MSTESTSUITE_PATH)/conformance run NUNIT-CONSOLE="$(RUNTIME) $(CLASS)/nunit-console.exe -nologo -exclude=MonoBug,BadTest" NUNIT_XML_RESULT=$(abs_top_builddir)/acceptance-tests/TestResult-ms-test-suite-conformance.xml || EXIT_CODE=1; \ $(MAKE) -C $(MSTESTSUITE_PATH)/systemruntimebringup build MCS="$(MCS) -debug -warn:1" && \ $(MAKE) -C $(MSTESTSUITE_PATH)/systemruntimebringup run MONO="$(RUNTIME)" || EXIT_CODE=1; \ exit $$EXIT_CODE; \ else \ echo "*** [ms-test-suite] Getting the repository failed, you probably don't have access to this Xamarin-internal resource. Skipping."; \ - fi \ No newline at end of file + fi diff --git a/acceptance-tests/profiler-stress.mk b/acceptance-tests/profiler-stress.mk new file mode 100644 index 0000000000..ff67772a1d --- /dev/null +++ b/acceptance-tests/profiler-stress.mk @@ -0,0 +1,13 @@ +SYS_REFS = \ + System.dll \ + System.Core.dll \ + System.Data.dll \ + System.Runtime.Serialization.dll \ + System.Xml.dll \ + System.Xml.Linq.dll \ + Mono.Posix.dll + +check-profiler-stress: + @$(MAKE) validate-benchmarker RESET_VERSIONS=1 + cd profiler-stress && $(MCS) -target:exe $(addprefix -r:, $(SYS_REFS)) -out:runner.exe @runner.exe.sources + cd profiler-stress && $(RUNTIME) runner.exe diff --git a/acceptance-tests/roslyn.mk b/acceptance-tests/roslyn.mk index fbfa2760ec..a91c68d986 100644 --- a/acceptance-tests/roslyn.mk +++ b/acceptance-tests/roslyn.mk @@ -4,17 +4,11 @@ check-roslyn: sed -i -e 's/\\4.5-api"/\\4.5"/g' $$PREFIX/lib/mono/xbuild-frameworks/.NETFramework/v4.5/RedistList/FrameworkList.xml; \ export MSBuildExtensionsPath=$$PREFIX/lib/mono/xbuild; \ MONO_DOTNET_PORTABLE_DIR=$$PREFIX/lib/mono/xbuild-frameworks/.NETPortable/; \ - MONO_NUGET_TARGETS_DIR=$$PREFIX/lib/mono/xbuild/Microsoft/NuGet/; \ - MONO_PORTABLE_TARGETS_DIR=$$PREFIX/lib/mono/xbuild/Microsoft/Portable/v5.0; \ - if [ ! -d "$$MONO_DOTNET_PORTABLE_DIR/v5.0" ]; then \ + if [ ! -d "$$MONO_DOTNET_PORTABLE_DIR/v4.6" ]; then \ mkdir -p $$MONO_DOTNET_PORTABLE_DIR; \ - mkdir -p $$MONO_NUGET_TARGETS_DIR; \ - mkdir -p $$MONO_PORTABLE_TARGETS_DIR; \ curl -SL "http://download.mono-project.com/third-party/RoslynBuildDependencies.zip" > /tmp/RoslynBuildDependencies.zip; \ unzip -o /tmp/RoslynBuildDependencies.zip -d /tmp/RoslynBuildDependencies; \ cp -r /tmp/RoslynBuildDependencies/PortableReferenceAssemblies/* $$MONO_DOTNET_PORTABLE_DIR; \ - cp /tmp/RoslynBuildDependencies/NuGetTargets/* $$MONO_NUGET_TARGETS_DIR; \ - cp /tmp/RoslynBuildDependencies/PortableTargets/* $$MONO_PORTABLE_TARGETS_DIR; \ fi; \ cd $(ROSLYN_PATH); \ sed -i -e 'N; s/bootstrapArg=".*\n.*"/bootstrapArg=""/g' cibuild.sh; \ diff --git a/acceptance-tests/versions.mk b/acceptance-tests/versions.mk index 84b4f85c6c..0c070a0f11 100644 --- a/acceptance-tests/versions.mk +++ b/acceptance-tests/versions.mk @@ -3,28 +3,35 @@ SUBMODULES_CONFIG_FILE = $(top_srcdir)/acceptance-tests/SUBMODULES.json include $(top_srcdir)/scripts/submodules/versions.mk +$(eval $(call ValidateVersionTemplate,benchmarker,BENCHMARKER)) $(eval $(call ValidateVersionTemplate,roslyn,ROSLYN)) $(eval $(call ValidateVersionTemplate,coreclr,CORECLR)) $(eval $(call ValidateVersionTemplate,ms-test-suite,MSTESTSUITE)) # Bump the given submodule to the revision given by the REV make variable # If COMMIT is 1, commit the change +bump-benchmarker: __bump-benchmarker bump-roslyn: __bump-version-roslyn bump-coreclr: __bump-version-coreclr bump-ms-test-suite: __bump-version-ms-test-suite # Bump the given submodule to the branch given by the BRANCH/REMOTE_BRANCH make variables # If COMMIT is 1, commit the change +bump-branch-benchmarker: __bump-branch-benchmarker bump-branch-roslyn: __bump-branch-roslyn bump-branch-coreclr: __bump-branch-coreclr bump-branch-ms-test-suite: __bump-branch-ms-test-suite # Bump the given submodule to its current GIT version # If COMMIT is 1, commit the change +bump-current-benchmarker: __bump-current-benchmarker bump-current-roslyn: __bump-current-version-roslyn bump-current-coreclr: __bump-current-version-coreclr bump-current-ms-test-suite: __bump-current-version-ms-test-suite +commit-bump-benchmarker: + $(MAKE) bump-benchmarker COMMIT=1 + commit-bump-roslyn: $(MAKE) bump-roslyn COMMIT=1 @@ -34,6 +41,9 @@ commit-bump-coreclr: commit-bump-ms-test-suite: $(MAKE) bump-ms-test-suite COMMIT=1 +commit-bump-current-benchmarker: + $(MAKE) bump-current-benchmarker COMMIT=1 + commit-bump-current-roslyn: $(MAKE) bump-current-roslyn COMMIT=1 diff --git a/autogen.sh b/autogen.sh index 5607051074..2fe9281e8d 100755 --- a/autogen.sh +++ b/autogen.sh @@ -160,8 +160,9 @@ if test -d $srcdir/eglib; then echo Done running eglib/autogen.sh ... fi - -echo "MONO_EXTRA_CONFIGURE_FLAGS is $MONO_EXTRA_CONFIGURE_FLAGS" +if test x$MONO_EXTRA_CONFIGURE_FLAGS != x; then + echo "MONO_EXTRA_CONFIGURE_FLAGS is $MONO_EXTRA_CONFIGURE_FLAGS" +fi conf_flags="$MONO_EXTRA_CONFIGURE_FLAGS --enable-maintainer-mode --enable-compile-warnings" #--enable-iso-c diff --git a/config.h.in b/config.h.in index f2bcdd2b43..3784a123c9 100644 --- a/config.h.in +++ b/config.h.in @@ -142,9 +142,6 @@ /* Runtime support code for llvm enabled */ #undef ENABLE_LLVM_RUNTIME -/* Enable using `perf` for profiling on Linux */ -#undef ENABLE_PERF_EVENTS - /* Have GLIBC_BEFORE_2_3_4_SCHED_SETAFFINITY */ #undef GLIBC_BEFORE_2_3_4_SCHED_SETAFFINITY @@ -187,6 +184,9 @@ /* Define to 1 if the system has the type `blksize_t'. */ #undef HAVE_BLKSIZE_T +/* BoringTls is supported */ +#undef HAVE_BTLS + /* Define to 1 if you have the header file. */ #undef HAVE_CHECKLIST_H @@ -257,6 +257,9 @@ /* dlopen-based dynamic loader available */ #undef HAVE_DL_LOADER +/* BTLS in a shared libraty */ +#undef HAVE_DYNAMIC_BTLS + /* Define to 1 if you have the header file. */ #undef HAVE_ELF_H diff --git a/configure.REMOVED.git-id b/configure.REMOVED.git-id index bea139836e..1c7887c91f 100644 --- a/configure.REMOVED.git-id +++ b/configure.REMOVED.git-id @@ -1 +1 @@ -e8e55390c7a19b75beced76b13cba26115783992 \ No newline at end of file +ce2dd70081b10fc07545b674f66612013c842eb7 \ No newline at end of file diff --git a/configure.ac.REMOVED.git-id b/configure.ac.REMOVED.git-id index d6f664fe20..dc73251f27 100644 --- a/configure.ac.REMOVED.git-id +++ b/configure.ac.REMOVED.git-id @@ -1 +1 @@ -249f69974e9846cf3b2f1ea6d1abcb79faff896f \ No newline at end of file +fa5977bb752c6bb7aa22669e6857d309df993ed3 \ No newline at end of file diff --git a/data/Makefile.in b/data/Makefile.in index 7a8842532c..16bda6b6e2 100644 --- a/data/Makefile.in +++ b/data/Makefile.in @@ -228,6 +228,8 @@ am__relativize = \ ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AOT_BUILD_FLAGS = @AOT_BUILD_FLAGS@ +AOT_RUN_FLAGS = @AOT_RUN_FLAGS@ API_VER = @API_VER@ AR = @AR@ AS = @AS@ @@ -236,6 +238,11 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOEHM_DEFINES = @BOEHM_DEFINES@ +BTLS_ARCH = @BTLS_ARCH@ +BTLS_CFLAGS = @BTLS_CFLAGS@ +BTLS_CMAKE_ARGS = @BTLS_CMAKE_ARGS@ +BTLS_PLATFORM = @BTLS_PLATFORM@ +BTLS_ROOT = @BTLS_ROOT@ BUILD_EXEEXT = @BUILD_EXEEXT@ CC = @CC@ CCAS = @CCAS@ @@ -245,6 +252,7 @@ CCDEPMODE = @CCDEPMODE@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMAKE = @CMAKE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ @@ -265,7 +273,6 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_PERF_EVENTS = @ENABLE_PERF_EVENTS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDKX11 = @GDKX11@ @@ -280,10 +287,12 @@ HAVE_MSGFMT = @HAVE_MSGFMT@ HOST_CC = @HOST_CC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MOBILE_STATIC = @INSTALL_MOBILE_STATIC@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTL = @INTL@ +INVARIANT_AOT_OPTIONS = @INVARIANT_AOT_OPTIONS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBC = @LIBC@ @@ -330,6 +339,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ +PLATFORM_AOT_SUFFIX = @PLATFORM_AOT_SUFFIX@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -339,6 +349,7 @@ SHELL = @SHELL@ SQLITE = @SQLITE@ SQLITE3 = @SQLITE3@ STRIP = @STRIP@ +TEST_PROFILE = @TEST_PROFILE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VTUNE_CFLAGS = @VTUNE_CFLAGS@ diff --git a/data/config.in b/data/config.in index b4b7243ecf..be83151429 100644 --- a/data/config.in +++ b/data/config.in @@ -11,6 +11,7 @@ + diff --git a/data/net_2_0/Browsers/Makefile.in b/data/net_2_0/Browsers/Makefile.in index 337423c49e..b514be21f8 100644 --- a/data/net_2_0/Browsers/Makefile.in +++ b/data/net_2_0/Browsers/Makefile.in @@ -150,6 +150,8 @@ DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AOT_BUILD_FLAGS = @AOT_BUILD_FLAGS@ +AOT_RUN_FLAGS = @AOT_RUN_FLAGS@ API_VER = @API_VER@ AR = @AR@ AS = @AS@ @@ -158,6 +160,11 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOEHM_DEFINES = @BOEHM_DEFINES@ +BTLS_ARCH = @BTLS_ARCH@ +BTLS_CFLAGS = @BTLS_CFLAGS@ +BTLS_CMAKE_ARGS = @BTLS_CMAKE_ARGS@ +BTLS_PLATFORM = @BTLS_PLATFORM@ +BTLS_ROOT = @BTLS_ROOT@ BUILD_EXEEXT = @BUILD_EXEEXT@ CC = @CC@ CCAS = @CCAS@ @@ -167,6 +174,7 @@ CCDEPMODE = @CCDEPMODE@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMAKE = @CMAKE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ @@ -187,7 +195,6 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_PERF_EVENTS = @ENABLE_PERF_EVENTS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDKX11 = @GDKX11@ @@ -202,10 +209,12 @@ HAVE_MSGFMT = @HAVE_MSGFMT@ HOST_CC = @HOST_CC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MOBILE_STATIC = @INSTALL_MOBILE_STATIC@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTL = @INTL@ +INVARIANT_AOT_OPTIONS = @INVARIANT_AOT_OPTIONS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBC = @LIBC@ @@ -252,6 +261,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ +PLATFORM_AOT_SUFFIX = @PLATFORM_AOT_SUFFIX@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -261,6 +271,7 @@ SHELL = @SHELL@ SQLITE = @SQLITE@ SQLITE3 = @SQLITE3@ STRIP = @STRIP@ +TEST_PROFILE = @TEST_PROFILE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VTUNE_CFLAGS = @VTUNE_CFLAGS@ diff --git a/data/net_2_0/Makefile.in b/data/net_2_0/Makefile.in index ac2dc9dcfd..fa6361a8d9 100644 --- a/data/net_2_0/Makefile.in +++ b/data/net_2_0/Makefile.in @@ -210,6 +210,8 @@ am__relativize = \ ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AOT_BUILD_FLAGS = @AOT_BUILD_FLAGS@ +AOT_RUN_FLAGS = @AOT_RUN_FLAGS@ API_VER = @API_VER@ AR = @AR@ AS = @AS@ @@ -218,6 +220,11 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOEHM_DEFINES = @BOEHM_DEFINES@ +BTLS_ARCH = @BTLS_ARCH@ +BTLS_CFLAGS = @BTLS_CFLAGS@ +BTLS_CMAKE_ARGS = @BTLS_CMAKE_ARGS@ +BTLS_PLATFORM = @BTLS_PLATFORM@ +BTLS_ROOT = @BTLS_ROOT@ BUILD_EXEEXT = @BUILD_EXEEXT@ CC = @CC@ CCAS = @CCAS@ @@ -227,6 +234,7 @@ CCDEPMODE = @CCDEPMODE@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMAKE = @CMAKE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ @@ -247,7 +255,6 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_PERF_EVENTS = @ENABLE_PERF_EVENTS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDKX11 = @GDKX11@ @@ -262,10 +269,12 @@ HAVE_MSGFMT = @HAVE_MSGFMT@ HOST_CC = @HOST_CC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MOBILE_STATIC = @INSTALL_MOBILE_STATIC@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTL = @INTL@ +INVARIANT_AOT_OPTIONS = @INVARIANT_AOT_OPTIONS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBC = @LIBC@ @@ -312,6 +321,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ +PLATFORM_AOT_SUFFIX = @PLATFORM_AOT_SUFFIX@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -321,6 +331,7 @@ SHELL = @SHELL@ SQLITE = @SQLITE@ SQLITE3 = @SQLITE3@ STRIP = @STRIP@ +TEST_PROFILE = @TEST_PROFILE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VTUNE_CFLAGS = @VTUNE_CFLAGS@ diff --git a/data/net_4_0/Browsers/Makefile.in b/data/net_4_0/Browsers/Makefile.in index 7a00977e8c..eb112e758b 100644 --- a/data/net_4_0/Browsers/Makefile.in +++ b/data/net_4_0/Browsers/Makefile.in @@ -150,6 +150,8 @@ DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AOT_BUILD_FLAGS = @AOT_BUILD_FLAGS@ +AOT_RUN_FLAGS = @AOT_RUN_FLAGS@ API_VER = @API_VER@ AR = @AR@ AS = @AS@ @@ -158,6 +160,11 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOEHM_DEFINES = @BOEHM_DEFINES@ +BTLS_ARCH = @BTLS_ARCH@ +BTLS_CFLAGS = @BTLS_CFLAGS@ +BTLS_CMAKE_ARGS = @BTLS_CMAKE_ARGS@ +BTLS_PLATFORM = @BTLS_PLATFORM@ +BTLS_ROOT = @BTLS_ROOT@ BUILD_EXEEXT = @BUILD_EXEEXT@ CC = @CC@ CCAS = @CCAS@ @@ -167,6 +174,7 @@ CCDEPMODE = @CCDEPMODE@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMAKE = @CMAKE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ @@ -187,7 +195,6 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_PERF_EVENTS = @ENABLE_PERF_EVENTS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDKX11 = @GDKX11@ @@ -202,10 +209,12 @@ HAVE_MSGFMT = @HAVE_MSGFMT@ HOST_CC = @HOST_CC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MOBILE_STATIC = @INSTALL_MOBILE_STATIC@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTL = @INTL@ +INVARIANT_AOT_OPTIONS = @INVARIANT_AOT_OPTIONS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBC = @LIBC@ @@ -252,6 +261,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ +PLATFORM_AOT_SUFFIX = @PLATFORM_AOT_SUFFIX@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -261,6 +271,7 @@ SHELL = @SHELL@ SQLITE = @SQLITE@ SQLITE3 = @SQLITE3@ STRIP = @STRIP@ +TEST_PROFILE = @TEST_PROFILE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VTUNE_CFLAGS = @VTUNE_CFLAGS@ diff --git a/data/net_4_0/Makefile.in b/data/net_4_0/Makefile.in index da4d0e9404..23828d4665 100644 --- a/data/net_4_0/Makefile.in +++ b/data/net_4_0/Makefile.in @@ -210,6 +210,8 @@ am__relativize = \ ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AOT_BUILD_FLAGS = @AOT_BUILD_FLAGS@ +AOT_RUN_FLAGS = @AOT_RUN_FLAGS@ API_VER = @API_VER@ AR = @AR@ AS = @AS@ @@ -218,6 +220,11 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOEHM_DEFINES = @BOEHM_DEFINES@ +BTLS_ARCH = @BTLS_ARCH@ +BTLS_CFLAGS = @BTLS_CFLAGS@ +BTLS_CMAKE_ARGS = @BTLS_CMAKE_ARGS@ +BTLS_PLATFORM = @BTLS_PLATFORM@ +BTLS_ROOT = @BTLS_ROOT@ BUILD_EXEEXT = @BUILD_EXEEXT@ CC = @CC@ CCAS = @CCAS@ @@ -227,6 +234,7 @@ CCDEPMODE = @CCDEPMODE@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMAKE = @CMAKE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ @@ -247,7 +255,6 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_PERF_EVENTS = @ENABLE_PERF_EVENTS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDKX11 = @GDKX11@ @@ -262,10 +269,12 @@ HAVE_MSGFMT = @HAVE_MSGFMT@ HOST_CC = @HOST_CC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MOBILE_STATIC = @INSTALL_MOBILE_STATIC@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTL = @INTL@ +INVARIANT_AOT_OPTIONS = @INVARIANT_AOT_OPTIONS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBC = @LIBC@ @@ -312,6 +321,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ +PLATFORM_AOT_SUFFIX = @PLATFORM_AOT_SUFFIX@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -321,6 +331,7 @@ SHELL = @SHELL@ SQLITE = @SQLITE@ SQLITE3 = @SQLITE3@ STRIP = @STRIP@ +TEST_PROFILE = @TEST_PROFILE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VTUNE_CFLAGS = @VTUNE_CFLAGS@ diff --git a/data/net_4_5/Browsers/Makefile.in b/data/net_4_5/Browsers/Makefile.in index ea0e8ac234..f39432d05d 100644 --- a/data/net_4_5/Browsers/Makefile.in +++ b/data/net_4_5/Browsers/Makefile.in @@ -150,6 +150,8 @@ DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AOT_BUILD_FLAGS = @AOT_BUILD_FLAGS@ +AOT_RUN_FLAGS = @AOT_RUN_FLAGS@ API_VER = @API_VER@ AR = @AR@ AS = @AS@ @@ -158,6 +160,11 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOEHM_DEFINES = @BOEHM_DEFINES@ +BTLS_ARCH = @BTLS_ARCH@ +BTLS_CFLAGS = @BTLS_CFLAGS@ +BTLS_CMAKE_ARGS = @BTLS_CMAKE_ARGS@ +BTLS_PLATFORM = @BTLS_PLATFORM@ +BTLS_ROOT = @BTLS_ROOT@ BUILD_EXEEXT = @BUILD_EXEEXT@ CC = @CC@ CCAS = @CCAS@ @@ -167,6 +174,7 @@ CCDEPMODE = @CCDEPMODE@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMAKE = @CMAKE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ @@ -187,7 +195,6 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_PERF_EVENTS = @ENABLE_PERF_EVENTS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDKX11 = @GDKX11@ @@ -202,10 +209,12 @@ HAVE_MSGFMT = @HAVE_MSGFMT@ HOST_CC = @HOST_CC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MOBILE_STATIC = @INSTALL_MOBILE_STATIC@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTL = @INTL@ +INVARIANT_AOT_OPTIONS = @INVARIANT_AOT_OPTIONS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBC = @LIBC@ @@ -252,6 +261,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ +PLATFORM_AOT_SUFFIX = @PLATFORM_AOT_SUFFIX@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -261,6 +271,7 @@ SHELL = @SHELL@ SQLITE = @SQLITE@ SQLITE3 = @SQLITE3@ STRIP = @STRIP@ +TEST_PROFILE = @TEST_PROFILE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VTUNE_CFLAGS = @VTUNE_CFLAGS@ diff --git a/data/net_4_5/Makefile.in b/data/net_4_5/Makefile.in index f62c70b756..e68780a1ca 100644 --- a/data/net_4_5/Makefile.in +++ b/data/net_4_5/Makefile.in @@ -210,6 +210,8 @@ am__relativize = \ ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AOT_BUILD_FLAGS = @AOT_BUILD_FLAGS@ +AOT_RUN_FLAGS = @AOT_RUN_FLAGS@ API_VER = @API_VER@ AR = @AR@ AS = @AS@ @@ -218,6 +220,11 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOEHM_DEFINES = @BOEHM_DEFINES@ +BTLS_ARCH = @BTLS_ARCH@ +BTLS_CFLAGS = @BTLS_CFLAGS@ +BTLS_CMAKE_ARGS = @BTLS_CMAKE_ARGS@ +BTLS_PLATFORM = @BTLS_PLATFORM@ +BTLS_ROOT = @BTLS_ROOT@ BUILD_EXEEXT = @BUILD_EXEEXT@ CC = @CC@ CCAS = @CCAS@ @@ -227,6 +234,7 @@ CCDEPMODE = @CCDEPMODE@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMAKE = @CMAKE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ @@ -247,7 +255,6 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_PERF_EVENTS = @ENABLE_PERF_EVENTS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDKX11 = @GDKX11@ @@ -262,10 +269,12 @@ HAVE_MSGFMT = @HAVE_MSGFMT@ HOST_CC = @HOST_CC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MOBILE_STATIC = @INSTALL_MOBILE_STATIC@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTL = @INTL@ +INVARIANT_AOT_OPTIONS = @INVARIANT_AOT_OPTIONS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBC = @LIBC@ @@ -312,6 +321,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ +PLATFORM_AOT_SUFFIX = @PLATFORM_AOT_SUFFIX@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -321,6 +331,7 @@ SHELL = @SHELL@ SQLITE = @SQLITE@ SQLITE3 = @SQLITE3@ STRIP = @STRIP@ +TEST_PROFILE = @TEST_PROFILE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VTUNE_CFLAGS = @VTUNE_CFLAGS@ diff --git a/docs/Makefile.in b/docs/Makefile.in index 5aa48f48d0..5e461cfcd6 100644 --- a/docs/Makefile.in +++ b/docs/Makefile.in @@ -150,6 +150,8 @@ DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AOT_BUILD_FLAGS = @AOT_BUILD_FLAGS@ +AOT_RUN_FLAGS = @AOT_RUN_FLAGS@ API_VER = @API_VER@ AR = @AR@ AS = @AS@ @@ -158,6 +160,11 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOEHM_DEFINES = @BOEHM_DEFINES@ +BTLS_ARCH = @BTLS_ARCH@ +BTLS_CFLAGS = @BTLS_CFLAGS@ +BTLS_CMAKE_ARGS = @BTLS_CMAKE_ARGS@ +BTLS_PLATFORM = @BTLS_PLATFORM@ +BTLS_ROOT = @BTLS_ROOT@ BUILD_EXEEXT = @BUILD_EXEEXT@ CC = @CC@ CCAS = @CCAS@ @@ -167,6 +174,7 @@ CCDEPMODE = @CCDEPMODE@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMAKE = @CMAKE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ @@ -187,7 +195,6 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_PERF_EVENTS = @ENABLE_PERF_EVENTS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDKX11 = @GDKX11@ @@ -202,10 +209,12 @@ HAVE_MSGFMT = @HAVE_MSGFMT@ HOST_CC = @HOST_CC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MOBILE_STATIC = @INSTALL_MOBILE_STATIC@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTL = @INTL@ +INVARIANT_AOT_OPTIONS = @INVARIANT_AOT_OPTIONS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBC = @LIBC@ @@ -252,6 +261,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ +PLATFORM_AOT_SUFFIX = @PLATFORM_AOT_SUFFIX@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -261,6 +271,7 @@ SHELL = @SHELL@ SQLITE = @SQLITE@ SQLITE3 = @SQLITE3@ STRIP = @STRIP@ +TEST_PROFILE = @TEST_PROFILE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VTUNE_CFLAGS = @VTUNE_CFLAGS@ diff --git a/docs/deploy/mono-api-gc.html b/docs/deploy/mono-api-gc.html index 9b85a5194b..e51976f564 100644 --- a/docs/deploy/mono-api-gc.html +++ b/docs/deploy/mono-api-gc.html @@ -498,9 +498,8 @@ mono_gc_reference_queue_new (mono_reference_queue_callback callback)

The output of the SCC analysis is passed to the `cross_references()` callback. It is expected to set the `is_alive` flag on those strongly connected components that it - wishes to be kept alive. Only bridged objects will be - reported to the callback, i.e., non-bridged objects are - removed from the callback graph. + wishes to be kept alive. The value of `is_alive` will be + ignored on any SCCs which lack bridges.

In monodroid each bridged object has a corresponding Java mirror object. In the bridge callback it reifies the Mono @@ -521,7 +520,7 @@ mono_gc_reference_queue_new (mono_reference_queue_callback callback)

enum { - SGEN_BRIDGE_VERSION = 4 + SGEN_BRIDGE_VERSION = 5 }; typedef enum { diff --git a/docs/deploy/mono-api-internal.html b/docs/deploy/mono-api-internal.html index 7e94ca2974..48d4f690f9 100644 --- a/docs/deploy/mono-api-internal.html +++ b/docs/deploy/mono-api-internal.html @@ -532,8 +532,7 @@ mono_marshal_get_native_wrapper (MonoMethod *method, gboolean check_exceptions,
method The MonoMethod to wrap.
check_exceptions Whenever to check for pending exceptions
Description

generates IL code for the pinvoke wrapper (the generated method - calls the unmanaged code in piinfo->addr) - The wrapper info for the wrapper is a WrapperInfo structure.

+ calls the unmanaged code in piinfo->addr)
@@ -570,8 +569,7 @@ mono_marshal_get_ptr_to_struct (MonoClass *klass)
Parameters
klass
Description

- generates IL code for PtrToStructure (IntPtr src, object structure) - The wrapper info for the wrapper is a WrapperInfo structure.

+ generates IL code for PtrToStructure (IntPtr src, object structure) @@ -698,8 +696,7 @@ mono_marshal_get_struct_to_ptr (MonoClass *klass)
Parameters
klass
Description

- generates IL code for StructureToPtr (object structure, IntPtr ptr, bool fDeleteOld) - The wrapper info for the wrapper is a WrapperInfo structure.

+ generates IL code for StructureToPtr (object structure, IntPtr ptr, bool fDeleteOld) diff --git a/docs/deploy/mono-api-unsorted.html b/docs/deploy/mono-api-unsorted.html index a2a1496a6b..b7d320d32a 100644 --- a/docs/deploy/mono-api-unsorted.html +++ b/docs/deploy/mono-api-unsorted.html @@ -293,7 +293,7 @@ mono_dllmap_insert (MonoImage *assembly, const char *dll, const char *func, cons

Parameters
-
assembly if NULL, this is a global mapping, otherwise the remapping of the dynamic library will only apply to the specified assembly
dll The name of the external library, as it would be found in the DllImport declaration. If prefixed with 'i:' the matching of the library name is done without case sensitivity
func if not null, the mapping will only applied to the named function (the value of EntryPoint)
tdll The name of the library to map the specified dll if it matches.
tfunc if func is not NULL, the name of the function that replaces the invocation
Description
+
assembly if NULL, this is a global mapping, otherwise the remapping of the dynamic library will only apply to the specified assembly
dll The name of the external library, as it would be found in the DllImport declaration. If prefixed with 'i:' the matching of the library name is done without case sensitivity
func if not null, the mapping will only applied to the named function (the value of EntryPoint)
tdll The name of the library to map the specified dll if it matches.
tfunc The name of the function that replaces the invocation. If NULL, it is replaced with a copy of func.
Description

LOCKING: Acquires the loader lock.

diff --git a/docs/deploy/mono-api-wapi.html.REMOVED.git-id b/docs/deploy/mono-api-wapi.html.REMOVED.git-id index e32914e3b5..4b5116790f 100644 --- a/docs/deploy/mono-api-wapi.html.REMOVED.git-id +++ b/docs/deploy/mono-api-wapi.html.REMOVED.git-id @@ -1 +1 @@ -3e44f606f7cee10fd72df9399ead2393fe7e824c \ No newline at end of file +dc9f5d8b06210d860035b42ede58f35b8e7c32bd \ No newline at end of file diff --git a/docs/sources/mono-api-gc.html b/docs/sources/mono-api-gc.html index 20d6cb9dc9..cddef0364c 100644 --- a/docs/sources/mono-api-gc.html +++ b/docs/sources/mono-api-gc.html @@ -40,9 +40,8 @@

The output of the SCC analysis is passed to the `cross_references()` callback. It is expected to set the `is_alive` flag on those strongly connected components that it - wishes to be kept alive. Only bridged objects will be - reported to the callback, i.e., non-bridged objects are - removed from the callback graph. + wishes to be kept alive. The value of `is_alive` will be + ignored on any SCCs which lack bridges.

In monodroid each bridged object has a corresponding Java mirror object. In the bridge callback it reifies the Mono @@ -63,7 +62,7 @@

enum { - SGEN_BRIDGE_VERSION = 4 + SGEN_BRIDGE_VERSION = 5 }; typedef enum { diff --git a/eglib/config.h.in b/eglib/config.h.in index 983d93f90c..101a0b179a 100644 --- a/eglib/config.h.in +++ b/eglib/config.h.in @@ -3,6 +3,9 @@ /* Define if building universal (internal helper macro) */ #undef AC_APPLE_UNIVERSAL_BUILD +/* Overridable allocator support enabled */ +#undef ENABLE_OVERRIDABLE_ALLOCATORS + /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H diff --git a/eglib/configure.REMOVED.git-id b/eglib/configure.REMOVED.git-id index 438fece81b..55fa39a2b8 100644 --- a/eglib/configure.REMOVED.git-id +++ b/eglib/configure.REMOVED.git-id @@ -1 +1 @@ -e6c748208dd33485e04939f7cbb59545aa05f3a3 \ No newline at end of file +801fdd9c4cde828e7e92456ad7de345487765e0b \ No newline at end of file diff --git a/eglib/configure.ac b/eglib/configure.ac index 7622701ef4..a33dcb846b 100644 --- a/eglib/configure.ac +++ b/eglib/configure.ac @@ -138,6 +138,15 @@ AC_CHECK_FUNCS(strlcpy stpcpy strtok_r rewinddir vasprintf) AC_CHECK_FUNCS(getrlimit) AC_CHECK_FUNCS(fork execv execve) +AC_ARG_WITH([overridable-allocators], [ --with-overridable-allocators allow g_*alloc/g_free to call custom allocators set via g_mem_set_vtable]) + +if test x$with_overridable_allocators = xyes; then + AC_DEFINE(ENABLE_OVERRIDABLE_ALLOCATORS,1,[Overridable allocator support enabled]) + AC_MSG_NOTICE([Overridable allocator support enabled]) +else + AC_MSG_NOTICE([Overridable allocator support disabled]) +fi + # # Mono currently supports 10.6, but strndup is not available prior to 10.7; avoiding # the detection of strndup on OS X so Mono built on 10.7+ still runs on 10.6. This can be @@ -151,7 +160,7 @@ elif test x$target_ios = xno; then AC_CHECK_FUNCS(strndup getpwuid_r) fi -AM_CONDITIONAL(NEED_VASPRINTF, test x$ac_cv_func_vasprintf = xno ) +AM_CONDITIONAL(NEED_VASPRINTF, test x$ac_cv_func_vasprintf = xno || test x$with_overridable_allocators = xyes) AM_ICONV() AC_SEARCH_LIBS(sqrtf, m) diff --git a/eglib/src/Makefile.am b/eglib/src/Makefile.am index 31771dfd9a..1527ba26d3 100644 --- a/eglib/src/Makefile.am +++ b/eglib/src/Makefile.am @@ -11,14 +11,6 @@ unix_files = \ gdate-unix.c gdir-unix.c gfile-unix.c gmisc-unix.c \ gmodule-unix.c gtimer-unix.c -# some unices and windows do not have an implementation of vasprintf -# used by eglib, use provided implementation instead -if NEED_VASPRINTF -vasprintf_files = vasprintf.c -else -vaprinttf_files = foo.c -endif - if HOST_WIN32 os_files = $(win_files) else @@ -32,7 +24,6 @@ libeglib_la_SOURCES = \ garray.c \ gbytearray.c \ gerror.c \ - vasprintf.h \ ghashtable.c \ giconv.c \ gmem.c \ @@ -55,8 +46,7 @@ libeglib_la_SOURCES = \ gutf8.c \ gunicode.c \ unicode-data.h \ - $(os_files) \ - $(vasprintf_files) + $(os_files) libeglib_la_CFLAGS = -g -Wall -D_FORTIFY_SOURCE=2 diff --git a/eglib/src/Makefile.in b/eglib/src/Makefile.in index ba0d1db216..61edfd331a 100644 --- a/eglib/src/Makefile.in +++ b/eglib/src/Makefile.in @@ -100,14 +100,14 @@ LTLIBRARIES = $(noinst_LTLIBRARIES) am__DEPENDENCIES_1 = @HOST_WIN32_TRUE@libeglib_la_DEPENDENCIES = $(am__DEPENDENCIES_1) am__libeglib_la_SOURCES_DIST = eglib-remap.h sort.frag.h glib.h \ - garray.c gbytearray.c gerror.c vasprintf.h ghashtable.c \ - giconv.c gmem.c gmodule.h goutput.c gqsort.c gstr.c gslist.c \ - gstring.c gptrarray.c glist.c gqueue.c gpath.c gshell.c \ - gspawn.c gfile.c gfile-posix.c gpattern.c gmarkup.c gutf8.c \ - gunicode.c unicode-data.h gdate-unix.c gdir-unix.c \ - gfile-unix.c gmisc-unix.c gmodule-unix.c gtimer-unix.c \ - eglib-config.hw gdate-win32.c gdir-win32.c gfile-win32.c \ - gmisc-win32.c gmodule-win32.c gtimer-win32.c vasprintf.c + garray.c gbytearray.c gerror.c ghashtable.c giconv.c gmem.c \ + gmodule.h goutput.c gqsort.c gstr.c gslist.c gstring.c \ + gptrarray.c glist.c gqueue.c gpath.c gshell.c gspawn.c gfile.c \ + gfile-posix.c gpattern.c gmarkup.c gutf8.c gunicode.c \ + unicode-data.h gdate-unix.c gdir-unix.c gfile-unix.c \ + gmisc-unix.c gmodule-unix.c gtimer-unix.c eglib-config.hw \ + gdate-win32.c gdir-win32.c gfile-win32.c gmisc-win32.c \ + gmodule-win32.c gtimer-win32.c am__objects_1 = libeglib_la-gdate-unix.lo libeglib_la-gdir-unix.lo \ libeglib_la-gfile-unix.lo libeglib_la-gmisc-unix.lo \ libeglib_la-gmodule-unix.lo libeglib_la-gtimer-unix.lo @@ -116,7 +116,6 @@ am__objects_2 = libeglib_la-gdate-win32.lo libeglib_la-gdir-win32.lo \ libeglib_la-gmodule-win32.lo libeglib_la-gtimer-win32.lo @HOST_WIN32_FALSE@am__objects_3 = $(am__objects_1) @HOST_WIN32_TRUE@am__objects_3 = $(am__objects_2) -@NEED_VASPRINTF_TRUE@am__objects_4 = libeglib_la-vasprintf.lo am_libeglib_la_OBJECTS = libeglib_la-garray.lo \ libeglib_la-gbytearray.lo libeglib_la-gerror.lo \ libeglib_la-ghashtable.lo libeglib_la-giconv.lo \ @@ -128,8 +127,7 @@ am_libeglib_la_OBJECTS = libeglib_la-garray.lo \ libeglib_la-gshell.lo libeglib_la-gspawn.lo \ libeglib_la-gfile.lo libeglib_la-gfile-posix.lo \ libeglib_la-gpattern.lo libeglib_la-gmarkup.lo \ - libeglib_la-gutf8.lo libeglib_la-gunicode.lo $(am__objects_3) \ - $(am__objects_4) + libeglib_la-gutf8.lo libeglib_la-gunicode.lo $(am__objects_3) libeglib_la_OBJECTS = $(am_libeglib_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) @@ -353,11 +351,6 @@ unix_files = \ gdate-unix.c gdir-unix.c gfile-unix.c gmisc-unix.c \ gmodule-unix.c gtimer-unix.c - -# some unices and windows do not have an implementation of vasprintf -# used by eglib, use provided implementation instead -@NEED_VASPRINTF_TRUE@vasprintf_files = vasprintf.c -@NEED_VASPRINTF_FALSE@vaprinttf_files = foo.c @HOST_WIN32_FALSE@os_files = $(unix_files) @HOST_WIN32_TRUE@os_files = $(win_files) libeglib_la_SOURCES = \ @@ -367,7 +360,6 @@ libeglib_la_SOURCES = \ garray.c \ gbytearray.c \ gerror.c \ - vasprintf.h \ ghashtable.c \ giconv.c \ gmem.c \ @@ -390,8 +382,7 @@ libeglib_la_SOURCES = \ gutf8.c \ gunicode.c \ unicode-data.h \ - $(os_files) \ - $(vasprintf_files) + $(os_files) libeglib_la_CFLAGS = -g -Wall -D_FORTIFY_SOURCE=2 AM_CPPFLAGS = -I$(srcdir) @@ -491,7 +482,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeglib_la-gtimer-win32.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeglib_la-gunicode.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeglib_la-gutf8.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeglib_la-vasprintf.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @@ -759,13 +749,6 @@ libeglib_la-gtimer-win32.lo: gtimer-win32.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeglib_la_CFLAGS) $(CFLAGS) -c -o libeglib_la-gtimer-win32.lo `test -f 'gtimer-win32.c' || echo '$(srcdir)/'`gtimer-win32.c -libeglib_la-vasprintf.lo: vasprintf.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeglib_la_CFLAGS) $(CFLAGS) -MT libeglib_la-vasprintf.lo -MD -MP -MF $(DEPDIR)/libeglib_la-vasprintf.Tpo -c -o libeglib_la-vasprintf.lo `test -f 'vasprintf.c' || echo '$(srcdir)/'`vasprintf.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeglib_la-vasprintf.Tpo $(DEPDIR)/libeglib_la-vasprintf.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vasprintf.c' object='libeglib_la-vasprintf.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeglib_la_CFLAGS) $(CFLAGS) -c -o libeglib_la-vasprintf.lo `test -f 'vasprintf.c' || echo '$(srcdir)/'`vasprintf.c - mostlyclean-libtool: -rm -f *.lo diff --git a/eglib/src/gerror.c b/eglib/src/gerror.c index 2ec089c995..43fef97cc4 100644 --- a/eglib/src/gerror.c +++ b/eglib/src/gerror.c @@ -28,10 +28,8 @@ #include #include #include +#include #include - -#include "vasprintf.h" - GError * g_error_new (gpointer domain, gint code, const char *format, ...) { @@ -42,7 +40,7 @@ g_error_new (gpointer domain, gint code, const char *format, ...) err->code = code; va_start (args, format); - if (vasprintf (&err->message, format, args) == -1) + if (g_vasprintf (&err->message, format, args) == -1) err->message = g_strdup_printf ("internal: invalid format string %s", format); va_end (args); @@ -57,7 +55,7 @@ g_error_vnew (gpointer domain, gint code, const char *format, va_list ap) err->domain = domain; err->code = code; - if (vasprintf (&err->message, format, ap) == -1) + if (g_vasprintf (&err->message, format, ap) == -1) err->message = g_strdup_printf ("internal: invalid format string %s", format); return err; @@ -77,7 +75,7 @@ g_error_free (GError *error) { g_return_if_fail (error != NULL); - free (error->message); + g_free (error->message); g_free (error); } diff --git a/eglib/src/gfile-win32.c b/eglib/src/gfile-win32.c index 2dde793dfe..61e23cbe44 100644 --- a/eglib/src/gfile-win32.c +++ b/eglib/src/gfile-win32.c @@ -35,6 +35,7 @@ #include #include #include +#include #ifdef G_OS_WIN32 #include @@ -68,6 +69,26 @@ int mkstemp (char *tmp_template) return fd; } +gchar * +g_mkdtemp (char *tmp_template) +{ + gunichar2* utf16_template; + + utf16_template = u8to16 (tmp_template); + + utf16_template = _wmktemp(utf16_template); + if (utf16_template && *utf16_template) { + if (_wmkdir (utf16_template) == 0){ + char *ret = u16to8 (utf16_template); + g_free (utf16_template); + return ret; + } + } + + g_free (utf16_template); + return NULL; +} + #ifdef _MSC_VER #pragma warning(disable:4701) #endif diff --git a/eglib/src/giconv.c b/eglib/src/giconv.c index a6f222dfe8..c7723fef5b 100644 --- a/eglib/src/giconv.c +++ b/eglib/src/giconv.c @@ -199,8 +199,11 @@ g_iconv (GIConv cd, gchar **inbytes, gsize *inbytesleft, } else { outleftptr = NULL; } - +#if defined(__NetBSD__) + return iconv (cd->cd, (const gchar **)inbytes, inleftptr, outbytes, outleftptr); +#else return iconv (cd->cd, inbytes, inleftptr, outbytes, outleftptr); +#endif } #endif diff --git a/eglib/src/glib.h b/eglib/src/glib.h index 84ab1ee3f8..d7173264c1 100644 --- a/eglib/src/glib.h +++ b/eglib/src/glib.h @@ -1,6 +1,5 @@ #ifndef __GLIB_H #define __GLIB_H - #include #include #include @@ -9,6 +8,7 @@ #include #include + #ifdef _MSC_VER #pragma include_alias(, ) #endif @@ -126,6 +126,7 @@ void g_free (void *ptr); gpointer g_realloc (gpointer obj, gsize size); gpointer g_malloc (gsize x); gpointer g_malloc0 (gsize x); +gpointer g_calloc (gsize n, gsize x); gpointer g_try_malloc (gsize x); gpointer g_try_realloc (gpointer obj, gsize size); @@ -138,7 +139,7 @@ gpointer g_try_realloc (gpointer obj, gsize size); #define g_alloca(size) alloca (size) gpointer g_memdup (gconstpointer mem, guint byte_size); -static inline gchar *g_strdup (const gchar *str) { if (str) {return strdup (str);} return NULL; } +static inline gchar *g_strdup (const gchar *str) { if (str) { return (gchar*) g_memdup (str, (guint)strlen (str) + 1); } return NULL; } gchar **g_strdupv (gchar **str_array); typedef struct { @@ -146,11 +147,9 @@ typedef struct { gpointer (*realloc) (gpointer mem, gsize n_bytes); void (*free) (gpointer mem); gpointer (*calloc) (gsize n_blocks, gsize n_block_bytes); - gpointer (*try_malloc) (gsize n_bytes); - gpointer (*try_realloc) (gpointer mem, gsize n_bytes); } GMemVTable; -#define g_mem_set_vtable(x) +void g_mem_set_vtable (GMemVTable* vtable); struct _GMemChunk { guint alloc_size; @@ -223,11 +222,11 @@ gint g_printf (gchar const *format, ...); gint g_fprintf (FILE *file, gchar const *format, ...); gint g_sprintf (gchar *string, gchar const *format, ...); gint g_snprintf (gchar *string, gulong n, gchar const *format, ...); +gint g_vasprintf (gchar **ret, const gchar *fmt, va_list ap); #define g_vprintf vprintf #define g_vfprintf vfprintf #define g_vsprintf vsprintf #define g_vsnprintf vsnprintf -#define g_vasprintf vasprintf gsize g_strlcpy (gchar *dest, const gchar *src, gsize dest_size); gchar *g_stpcpy (gchar *dest, const char *src); @@ -888,6 +887,12 @@ gboolean g_file_test (const gchar *filename, GFileTest test); #define g_ascii_strtod strtod #define g_ascii_isalnum isalnum +#ifdef WIN32 +gchar *g_mkdtemp (gchar *tmpl); +#else +#define g_mkdtemp mkdtemp +#endif + /* * Pattern matching */ diff --git a/eglib/src/gmarkup.c b/eglib/src/gmarkup.c index 6a0b246a95..4e6c6641fe 100644 --- a/eglib/src/gmarkup.c +++ b/eglib/src/gmarkup.c @@ -367,7 +367,7 @@ g_markup_parse_context_parse (GMarkupParseContext *context, if (context->parser.end_element != NULL && context->state == START_ELEMENT){ context->parser.end_element (context, ename, context->user_data, error); if (error != NULL && *error != NULL){ - free (ename); + g_free (ename); goto fail; } } diff --git a/eglib/src/gmem.c b/eglib/src/gmem.c index 565239d1cb..eff478dcbf 100644 --- a/eglib/src/gmem.c +++ b/eglib/src/gmem.c @@ -25,15 +25,45 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#include #include #include #include +#if defined (ENABLE_OVERRIDABLE_ALLOCATORS) + +static GMemVTable sGMemVTable = { malloc, realloc, free, calloc }; + +void +g_mem_set_vtable (GMemVTable* vtable) +{ + sGMemVTable.calloc = vtable->calloc ? vtable->calloc : calloc; + sGMemVTable.realloc = vtable->realloc ? vtable->realloc : realloc; + sGMemVTable.malloc = vtable->malloc ? vtable->malloc : malloc; + sGMemVTable.free = vtable->free ? vtable->free : free; +} + +#define G_FREE_INTERNAL sGMemVTable.free +#define G_REALLOC_INTERNAL sGMemVTable.realloc +#define G_CALLOC_INTERNAL sGMemVTable.calloc +#define G_MALLOC_INTERNAL sGMemVTable.malloc +#else + +void +g_mem_set_vtable (GMemVTable* vtable) +{ +} + +#define G_FREE_INTERNAL free +#define G_REALLOC_INTERNAL realloc +#define G_CALLOC_INTERNAL calloc +#define G_MALLOC_INTERNAL malloc +#endif void g_free (void *ptr) { if (ptr != NULL) - free (ptr); + G_FREE_INTERNAL (ptr); } gpointer @@ -58,7 +88,7 @@ gpointer g_realloc (gpointer obj, gsize size) g_free (obj); return 0; } - ptr = realloc (obj, size); + ptr = G_REALLOC_INTERNAL (obj, size); if (ptr) return ptr; g_error ("Could not allocate %i bytes", size); @@ -70,27 +100,31 @@ g_malloc (gsize x) gpointer ptr; if (!x) return 0; - ptr = malloc (x); + ptr = G_MALLOC_INTERNAL (x); if (ptr) return ptr; g_error ("Could not allocate %i bytes", x); } +gpointer g_calloc (gsize n, gsize x) +{ + gpointer ptr; + if (!x || !n) + return 0; + ptr = G_CALLOC_INTERNAL (n, x); + if (ptr) + return ptr; + g_error ("Could not allocate %i (%i * %i) bytes", x*n, n, x); +} gpointer g_malloc0 (gsize x) { - gpointer ptr; - if (!x) - return 0; - ptr = calloc(1,x); - if (ptr) - return ptr; - g_error ("Could not allocate %i bytes", x); + return g_calloc (1,x); } gpointer g_try_malloc (gsize x) { if (x) - return malloc (x); + return G_MALLOC_INTERNAL (x); return 0; } @@ -98,8 +132,8 @@ gpointer g_try_malloc (gsize x) gpointer g_try_realloc (gpointer obj, gsize size) { if (!size) { - g_free (obj); + G_FREE_INTERNAL (obj); return 0; } - return realloc (obj, size); + return G_REALLOC_INTERNAL (obj, size); } diff --git a/eglib/src/gmisc-win32.c b/eglib/src/gmisc-win32.c index f89f37c220..5baec653c3 100644 --- a/eglib/src/gmisc-win32.c +++ b/eglib/src/gmisc-win32.c @@ -30,6 +30,9 @@ #include #include +#ifdef _MSC_VER +#include +#endif #include #include @@ -89,10 +92,10 @@ g_win32_getlocale(void) { LCID lcid = GetThreadLocale(); gchar buf[19]; - gint ccBuf = GetLocaleInfo(lcid, LOCALE_SISO639LANGNAME, buf, 9); + gint ccBuf = GetLocaleInfoA(lcid, LOCALE_SISO639LANGNAME, buf, 9); buf[ccBuf - 1] = '-'; - ccBuf += GetLocaleInfo(lcid, LOCALE_SISO3166CTRYNAME, buf + ccBuf, 9); - return strdup(buf); + ccBuf += GetLocaleInfoA(lcid, LOCALE_SISO3166CTRYNAME, buf + ccBuf, 9); + return g_strdup (buf); } gboolean @@ -116,16 +119,33 @@ g_path_is_absolute (const char *filename) const gchar * g_get_home_dir (void) { - /* FIXME */ - const gchar *drive = g_getenv ("HOMEDRIVE"); - const gchar *path = g_getenv ("HOMEPATH"); gchar *home_dir = NULL; - - if (drive && path) { - home_dir = g_malloc(strlen(drive) + strlen(path) +1); - if (home_dir) { - sprintf(home_dir, "%s%s", drive, path); + +#ifdef _MSC_VER + PWSTR profile_path = NULL; + HRESULT hr = SHGetKnownFolderPath (&FOLDERID_Profile, KF_FLAG_DEFAULT, NULL, &profile_path); + if (SUCCEEDED(hr)) { + home_dir = u16to8 (profile_path); + CoTaskMemFree (profile_path); + } +#endif + + if (!home_dir) { + home_dir = (gchar *) g_getenv ("USERPROFILE"); + } + + if (!home_dir) { + const gchar *drive = g_getenv ("HOMEDRIVE"); + const gchar *path = g_getenv ("HOMEPATH"); + + if (drive && path) { + home_dir = g_malloc (strlen (drive) + strlen (path) + 1); + if (home_dir) { + sprintf (home_dir, "%s%s", drive, path); + } } + g_free (drive); + g_free (path); } return home_dir; diff --git a/eglib/src/goutput.c b/eglib/src/goutput.c index 779ca96fd2..ef80cff034 100644 --- a/eglib/src/goutput.c +++ b/eglib/src/goutput.c @@ -31,8 +31,6 @@ #include #include -#include "vasprintf.h" - /* The current fatal levels, error is always fatal */ static GLogLevelFlags fatal = G_LOG_LEVEL_ERROR; static GLogFunc default_log_func; @@ -49,7 +47,7 @@ g_print (const gchar *format, ...) va_list args; va_start (args, format); - if (vasprintf (&msg, format, args) < 0) + if (g_vasprintf (&msg, format, args) < 0) return; va_end (args); @@ -57,7 +55,7 @@ g_print (const gchar *format, ...) stdout_handler = default_stdout_handler; stdout_handler (msg); - free (msg); + g_free (msg); } void @@ -67,7 +65,7 @@ g_printerr (const gchar *format, ...) va_list args; va_start (args, format); - if (vasprintf (&msg, format, args) < 0) + if (g_vasprintf (&msg, format, args) < 0) return; va_end (args); @@ -75,7 +73,7 @@ g_printerr (const gchar *format, ...) stderr_handler = default_stderr_handler; stderr_handler (msg); - free (msg); + g_free (msg); } GLogLevelFlags @@ -107,11 +105,11 @@ g_logv (const gchar *log_domain, GLogLevelFlags log_level, const gchar *format, if (!default_log_func) default_log_func = g_log_default_handler; - if (vasprintf (&msg, format, args) < 0) + if (g_vasprintf (&msg, format, args) < 0) return; default_log_func (log_domain, log_level, msg, default_log_func_user_data); - free (msg); + g_free (msg); } void diff --git a/eglib/src/gstr.c b/eglib/src/gstr.c index 3e976c5a2e..8b64da572f 100644 --- a/eglib/src/gstr.c +++ b/eglib/src/gstr.c @@ -32,13 +32,17 @@ #include #include -#include "vasprintf.h" +/* + * g_strndup and g_vasprintf need to allocate memory with g_malloc if + * ENABLE_OVERRIDABLE_ALLOCATORS is defined so that it can be safely freed with g_free + * rather than free. + */ /* This is not a macro, because I dont want to put _GNU_SOURCE in the glib.h header */ gchar * g_strndup (const gchar *str, gsize n) { -#ifdef HAVE_STRNDUP +#if defined (HAVE_STRNDUP) && !defined (ENABLE_OVERRIDABLE_ALLOCATORS) return strndup (str, n); #else if (str) { @@ -52,6 +56,37 @@ g_strndup (const gchar *str, gsize n) #endif } +gint g_vasprintf (gchar **ret, const gchar *fmt, va_list ap) +{ +#if defined (HAVE_VASPRINTF) && !defined (ENABLE_OVERRIDABLE_ALLOCATORS) + return vasprintf (ret, fmt, ap); +#else + char *buf; + int len; + size_t buflen; + va_list ap2; + +#if defined(_MSC_VER) || defined(__MINGW64_VERSION_MAJOR) + ap2 = ap; + len = _vscprintf(fmt, ap2); // NOTE MS specific extension ( :-( ) +#else + va_copy(ap2, ap); + len = vsnprintf(NULL, 0, fmt, ap2); +#endif + + if (len >= 0 && (buf = g_malloc ((buflen = (size_t) (len + 1)))) != NULL) { + len = vsnprintf(buf, buflen, fmt, ap); + *ret = buf; + } else { + *ret = NULL; + len = -1; + } + + va_end(ap2); + return len; +#endif +} + void g_strfreev (gchar **str_array) { @@ -133,7 +168,7 @@ g_strdup_vprintf (const gchar *format, va_list args) int n; char *ret; - n = vasprintf (&ret, format, args); + n = g_vasprintf (&ret, format, args); if (n == -1) return NULL; @@ -148,7 +183,7 @@ g_strdup_printf (const gchar *format, ...) int n; va_start (args, format); - n = vasprintf (&ret, format, args); + n = g_vasprintf (&ret, format, args); va_end (args); if (n == -1) return NULL; diff --git a/eglib/src/vasprintf.c b/eglib/src/vasprintf.c deleted file mode 100644 index 3c21ca4dc0..0000000000 --- a/eglib/src/vasprintf.c +++ /dev/null @@ -1,31 +0,0 @@ -#include -#include -#include - -int vasprintf(char **ret, const char *fmt, va_list ap) -{ - char *buf; - int len; - size_t buflen; - va_list ap2; - -#if defined(_MSC_VER) || defined(__MINGW64_VERSION_MAJOR) - ap2 = ap; - len = _vscprintf(fmt, ap2); // NOTE MS specific extension ( :-( ) -#else - va_copy(ap2, ap); - len = vsnprintf(NULL, 0, fmt, ap2); -#endif - - if (len >= 0 && (buf = malloc ((buflen = (size_t) (len + 1)))) != NULL) { - len = vsnprintf(buf, buflen, fmt, ap); - *ret = buf; - } else { - *ret = NULL; - len = -1; - } - - va_end(ap2); - return len; -} - diff --git a/eglib/src/vasprintf.h b/eglib/src/vasprintf.h deleted file mode 100644 index 3d294541a5..0000000000 --- a/eglib/src/vasprintf.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef __VASPRINTF_H -#define __VASPRINTF_H - -#include -#include - -#ifndef HAVE_VASPRINTF -int vasprintf(char **ret, const char *fmt, va_list ap); -#endif - -#endif /* __VASPRINTF_H */ diff --git a/eglib/test/test.c b/eglib/test/test.c index 6dd7bf4746..7c870e9c76 100644 --- a/eglib/test/test.c +++ b/eglib/test/test.c @@ -46,13 +46,6 @@ #include "test.h" extern gint global_passed, global_tests; - -#ifndef HAVE_VASPRINTF - /* systen does not provide a vasprintf function, use the one - provided within eglib itself */ -extern int vasprintf(char **ret, const char *format, va_list ap); -#endif - static gchar *last_result = NULL; gboolean @@ -183,7 +176,7 @@ FAILED(const gchar *format, ...) return NULL; #else va_start(args, format); - n = vasprintf(&ret, format, args); + n = g_vasprintf(&ret, format, args); va_end(args); if(n == -1) { diff --git a/external/boringssl/.clang-format b/external/boringssl/.clang-format new file mode 100644 index 0000000000..5865a7068d --- /dev/null +++ b/external/boringssl/.clang-format @@ -0,0 +1,7 @@ +BasedOnStyle: Google +MaxEmptyLinesToKeep: 3 +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +DerivePointerAlignment: false +PointerAlignment: Right + diff --git a/external/boringssl/.github/PULL_REQUEST_TEMPLATE b/external/boringssl/.github/PULL_REQUEST_TEMPLATE new file mode 100644 index 0000000000..6c101eabca --- /dev/null +++ b/external/boringssl/.github/PULL_REQUEST_TEMPLATE @@ -0,0 +1,7 @@ +Please do not send pull requests to the BoringSSL repository. + +We do, however, take contributions gladly. + +See https://boringssl.googlesource.com/boringssl/+/master/CONTRIBUTING.md + +Thanks! diff --git a/external/boringssl/.gitignore b/external/boringssl/.gitignore new file mode 100644 index 0000000000..a2e3ed2a15 --- /dev/null +++ b/external/boringssl/.gitignore @@ -0,0 +1,6 @@ +build/ +ssl/test/runner/runner +*.swp +*.swo +doc/*.html +doc/doc.css diff --git a/external/boringssl/BUILDING.md b/external/boringssl/BUILDING.md new file mode 100644 index 0000000000..5631ded848 --- /dev/null +++ b/external/boringssl/BUILDING.md @@ -0,0 +1,145 @@ +# Building BoringSSL + +## Build Prerequisites + + * [CMake](https://cmake.org/download/) 2.8.8 or later is required. + + * Perl 5.6.1 or later is required. On Windows, + [Active State Perl](http://www.activestate.com/activeperl/) has been + reported to work, as has MSYS Perl. + [Strawberry Perl](http://strawberryperl.com/) also works but it adds GCC + to `PATH`, which can confuse some build tools when identifying the compiler + (removing `C:\Strawberry\c\bin` from `PATH` should resolve any problems). + If Perl is not found by CMake, it may be configured explicitly by setting + `PERL_EXECUTABLE`. + + * On Windows you currently must use [Ninja](https://ninja-build.org/) + to build; on other platforms, it is not required, but recommended, because + it makes builds faster. + + * If you need to build Ninja from source, then a recent version of + [Python](https://www.python.org/downloads/) is required (Python 2.7.5 works). + + * On Windows only, [Yasm](http://yasm.tortall.net/) is required. If not found + by CMake, it may be configured explicitly by setting + `CMAKE_ASM_NASM_COMPILER`. + + * A C compiler is required. On Windows, MSVC 14 (Visual Studio 2015) or later + with Platform SDK 8.1 or later are supported. Recent versions of GCC (4.8+) + and Clang should work on non-Windows platforms, and maybe on Windows too. + To build the tests, you also need a C++ compiler with C++11 support. + + * [Go](https://golang.org/dl/) is required. If not found by CMake, the go + executable may be configured explicitly by setting `GO_EXECUTABLE`. + + * To build the x86 and x86\_64 assembly, your assembler must support AVX2 + instructions. If using GNU binutils, you must have 2.22 or later. + +## Building + +Using Ninja (note the 'N' is capitalized in the cmake invocation): + + mkdir build + cd build + cmake -GNinja .. + ninja + +Using Make (does not work on Windows): + + mkdir build + cd build + cmake .. + make + +You usually don't need to run `cmake` again after changing `CMakeLists.txt` +files because the build scripts will detect changes to them and rebuild +themselves automatically. + +Note that the default build flags in the top-level `CMakeLists.txt` are for +debugging—optimisation isn't enabled. Pass `-DCMAKE_BUILD_TYPE=Release` to +`cmake` to configure a release build. + +If you want to cross-compile then there is an example toolchain file for 32-bit +Intel in `util/`. Wipe out the build directory, recreate it and run `cmake` like +this: + + cmake -DCMAKE_TOOLCHAIN_FILE=../util/32-bit-toolchain.cmake -GNinja .. + +If you want to build as a shared library, pass `-DBUILD_SHARED_LIBS=1`. On +Windows, where functions need to be tagged with `dllimport` when coming from a +shared library, define `BORINGSSL_SHARED_LIBRARY` in any code which `#include`s +the BoringSSL headers. + +In order to serve environments where code-size is important as well as those +where performance is the overriding concern, `OPENSSL_SMALL` can be defined to +remove some code that is especially large. + +See [CMake's documentation](https://cmake.org/cmake/help/v3.4/manual/cmake-variables.7.html) +for other variables which may be used to configure the build. + +### Building for Android + +It's possible to build BoringSSL with the Android NDK using CMake. This has +been tested with version 10d of the NDK. + +Unpack the Android NDK somewhere and export `ANDROID_NDK` to point to the +directory. Then make a build directory as above and run CMake like this: + + cmake -DANDROID_ABI=armeabi-v7a \ + -DCMAKE_TOOLCHAIN_FILE=../third_party/android-cmake/android.toolchain.cmake \ + -DANDROID_NATIVE_API_LEVEL=16 \ + -GNinja .. + +Once you've run that, Ninja should produce Android-compatible binaries. You +can replace `armeabi-v7a` in the above with `arm64-v8a` and use API level 21 or +higher to build aarch64 binaries. + +For other options, see [android-cmake's documentation](./third_party/android-cmake/README.md). + +## Known Limitations on Windows + + * Versions of CMake since 3.0.2 have a bug in its Ninja generator that causes + yasm to output warnings + + yasm: warning: can open only one input file, only the last file will be processed + + These warnings can be safely ignored. The cmake bug is + http://www.cmake.org/Bug/view.php?id=15253. + + * CMake can generate Visual Studio projects, but the generated project files + don't have steps for assembling the assembly language source files, so they + currently cannot be used to build BoringSSL. + +## Embedded ARM + +ARM, unlike Intel, does not have an instruction that allows applications to +discover the capabilities of the processor. Instead, the capability information +has to be provided by the operating system somehow. + +BoringSSL will try to use `getauxval` to discover the capabilities and, failing +that, will probe for NEON support by executing a NEON instruction and handling +any illegal-instruction signal. But some environments don't support that sort +of thing and, for them, it's possible to configure the CPU capabilities +at compile time. + +If you define `OPENSSL_STATIC_ARMCAP` then you can define any of the following +to enabling the corresponding ARM feature. + + * `OPENSSL_STATIC_ARMCAP_NEON` or `__ARM_NEON__` (note that the latter is set by compilers when NEON support is enabled). + * `OPENSSL_STATIC_ARMCAP_AES` + * `OPENSSL_STATIC_ARMCAP_SHA1` + * `OPENSSL_STATIC_ARMCAP_SHA256` + * `OPENSSL_STATIC_ARMCAP_PMULL` + +Note that if a feature is enabled in this way, but not actually supported at +run-time, BoringSSL will likely crash. + +# Running tests + +There are two sets of tests: the C/C++ tests and the blackbox tests. For former +are built by Ninja and can be run from the top-level directory with `go run +util/all_tests.go`. The latter have to be run separately by running `go test` +from within `ssl/test/runner`. + +Both sets of tests may also be run with `ninja -C build run_tests`, but CMake +3.2 or later is required to avoid Ninja's output buffering. diff --git a/external/boringssl/CMakeLists.txt b/external/boringssl/CMakeLists.txt new file mode 100644 index 0000000000..4e63c89fbb --- /dev/null +++ b/external/boringssl/CMakeLists.txt @@ -0,0 +1,232 @@ +cmake_minimum_required (VERSION 2.8.10) + +# Defer enabling C and CXX languages. +project (BoringSSL NONE) + +if(WIN32) + # On Windows, prefer cl over gcc if both are available. By default most of + # the CMake generators prefer gcc, even on Windows. + set(CMAKE_GENERATOR_CC cl) +endif() + +enable_language(C) +enable_language(CXX) + +if(ANDROID) + # Android-NDK CMake files reconfigure the path and so Go and Perl won't be + # found. However, ninja will still find them in $PATH if we just name them. + set(PERL_EXECUTABLE "perl") + # set(GO_EXECUTABLE "go") +else() + find_package(Perl REQUIRED) + # find_program(GO_EXECUTABLE go) +endif() + +#if (NOT GO_EXECUTABLE) +# message(FATAL_ERROR "Could not find Go") +#endif() + +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + set(C_CXX_FLAGS "-Wall -Wformat=2 -Wsign-compare -Wmissing-field-initializers -ggdb -fvisibility=hidden") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_CXX_FLAGS}") + if(ANDROID) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x ${C_CXX_FLAGS}") + elseif(CMAKE_COMPILER_IS_GNUCXX) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 ${C_CXX_FLAGS}") + else() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -stdlib=libc++ ${C_CXX_FLAGS}") + endif() +elseif(MSVC) + set(MSVC_DISABLED_WARNINGS_LIST + "C4100" # 'exarg' : unreferenced formal parameter + "C4127" # conditional expression is constant + "C4200" # nonstandard extension used : zero-sized array in + # struct/union. + "C4242" # 'function' : conversion from 'int' to 'uint8_t', + # possible loss of data + "C4244" # 'function' : conversion from 'int' to 'uint8_t', + # possible loss of data + "C4245" # 'initializing' : conversion from 'long' to + # 'unsigned long', signed/unsigned mismatch + "C4267" # conversion from 'size_t' to 'int', possible loss of data + "C4371" # layout of class may have changed from a previous version of the + # compiler due to better packing of member '...' + "C4388" # signed/unsigned mismatch + "C4296" # '>=' : expression is always true + "C4350" # behavior change: 'std::_Wrap_alloc...' + "C4365" # '=' : conversion from 'size_t' to 'int', + # signed/unsigned mismatch + "C4389" # '!=' : signed/unsigned mismatch + "C4464" # relative include path contains '..' + "C4510" # 'argument' : default constructor could not be generated + "C4512" # 'argument' : assignment operator could not be generated + "C4514" # 'function': unreferenced inline function has been removed + "C4548" # expression before comma has no effect; expected expression with + # side-effect" caused by FD_* macros. + "C4610" # struct 'argument' can never be instantiated - user defined + # constructor required. + "C4623" # default constructor was implicitly defined as deleted + "C4625" # copy constructor could not be generated because a base class + # copy constructor is inaccessible or deleted + "C4626" # assignment operator could not be generated because a base class + # assignment operator is inaccessible or deleted + "C4706" # assignment within conditional expression + "C4710" # 'function': function not inlined + "C4711" # function 'function' selected for inline expansion + "C4800" # 'int' : forcing value to bool 'true' or 'false' + # (performance warning) + "C4820" # 'bytes' bytes padding added after construct 'member_name' + "C5027" # move assignment operator was implicitly defined as deleted + ) + set(MSVC_LEVEL4_WARNINGS_LIST + # See https://connect.microsoft.com/VisualStudio/feedback/details/1217660/warning-c4265-when-using-functional-header + "C4265" # class has virtual functions, but destructor is not virtual + ) + string(REPLACE "C" " -wd" MSVC_DISABLED_WARNINGS_STR + ${MSVC_DISABLED_WARNINGS_LIST}) + string(REPLACE "C" " -w4" MSVC_LEVEL4_WARNINGS_STR + ${MSVC_LEVEL4_WARNINGS_LIST}) + set(CMAKE_C_FLAGS "-Wall -WX ${MSVC_DISABLED_WARNINGS_STR} ${MSVC_LEVEL4_WARNINGS_STR}") + set(CMAKE_CXX_FLAGS "-Wall -WX ${MSVC_DISABLED_WARNINGS_STR} ${MSVC_LEVEL4_WARNINGS_STR}") + add_definitions(-D_HAS_EXCEPTIONS=0) + add_definitions(-DWIN32_LEAN_AND_MEAN) + add_definitions(-DNOMINMAX) + add_definitions(-D_CRT_SECURE_NO_WARNINGS) # Allow use of fopen +endif() + +if((CMAKE_COMPILER_IS_GNUCXX AND CMAKE_C_COMPILER_VERSION VERSION_GREATER "4.7.99") OR + CMAKE_CXX_COMPILER_ID MATCHES "Clang") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wshadow") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wshadow") +endif() + +if(CMAKE_COMPILER_IS_GNUCXX) + if ((CMAKE_C_COMPILER_VERSION VERSION_GREATER "4.8.99") OR + CMAKE_CXX_COMPILER_ID MATCHES "Clang") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11") + else() + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99") + endif() +endif() + +# pthread_rwlock_t requires a feature flag. +if(NOT WIN32) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_XOPEN_SOURCE=700") +endif() + +if(FUZZ) + if(!CMAKE_CXX_COMPILER_ID MATCHES "Clang") + message("You need to build with Clang for fuzzing to work") + endif() + + add_definitions(-DBORINGSSL_UNSAFE_FUZZER_MODE) + set(RUNNER_ARGS "-fuzzer") + + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fsanitize-coverage=edge,indirect-calls,8bit-counters") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fsanitize-coverage=edge,indirect-calls,8bit-counters") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address") + link_directories(.) +endif() + +add_definitions(-DBORINGSSL_IMPLEMENTATION) + +if (BUILD_SHARED_LIBS) + add_definitions(-DBORINGSSL_SHARED_LIBRARY) + # Enable position-independent code globally. This is needed because + # some library targets are OBJECT libraries. + set(CMAKE_POSITION_INDEPENDENT_CODE TRUE) +endif() + +if (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "x86_64") + set(ARCH "x86_64") +elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "amd64") + set(ARCH "x86_64") +elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "AMD64") + # cmake reports AMD64 on Windows, but we might be building for 32-bit. + if (CMAKE_CL_64) + set(ARCH "x86_64") + else() + set(ARCH "x86") + endif() +elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "x86") + set(ARCH "x86") +elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "i386") + set(ARCH "x86") +elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "i686") + set(ARCH "x86") +elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "arm") + set(ARCH "arm") +elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "armv5te") + set(ARCH "arm") +elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "armv6") + set(ARCH "arm") +elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "armv7-a") + set(ARCH "arm") +elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "aarch64") + set(ARCH "aarch64") +else() + message(FATAL_ERROR "Unknown processor:" ${CMAKE_SYSTEM_PROCESSOR}) +endif() + +if (ANDROID AND ${ARCH} STREQUAL "arm") + # The Android-NDK CMake files somehow fail to set the -march flag for + # assembly files. Without this flag, the compiler believes that it's + # building for ARMv5. + set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -march=${CMAKE_SYSTEM_PROCESSOR}") +endif() + +# if (${ARCH} STREQUAL "x86" AND APPLE) + # With CMake 2.8.x, ${CMAKE_SYSTEM_PROCESSOR} evalutes to i386 on OS X, + # but clang defaults to 64-bit builds on OS X unless otherwise told. + # Set ARCH to x86_64 so clang and CMake agree. This is fixed in CMake 3. +# set(ARCH "x86_64") +#endif() + +if (OPENSSL_NO_ASM) + add_definitions(-DOPENSSL_NO_ASM) + set(ARCH "generic") +endif() + +# Declare a dummy target to build all unit tests. Test targets should inject +# themselves as dependencies next to the target definition. +if(ENABLE_TESTS) +add_custom_target(all_tests) +endif() + +add_subdirectory(crypto) +add_subdirectory(ssl) +if(ENABLE_TESTS) +add_subdirectory(ssl/test) +endif() +add_subdirectory(tool) +if(ENABLE_DECREPIT) +add_subdirectory(decrepit) +endif() + +if(FUZZ) + add_subdirectory(fuzz) +endif() + +if (NOT ${CMAKE_VERSION} VERSION_LESS "3.2") + # USES_TERMINAL is only available in CMake 3.2 or later. + set(MAYBE_USES_TERMINAL USES_TERMINAL) +endif() + +set ( + BORINGSSL_OBJECTS + $ + ${crypto_objects_dependencies} + $ + ${ssl_objects_dependencies} + PARENT_SCOPE +) + +# add_custom_target( +# run_tests +# COMMAND ${GO_EXECUTABLE} run util/all_tests.go -build-dir +# ${CMAKE_BINARY_DIR} +# COMMAND cd ssl/test/runner +# COMMAND ${GO_EXECUTABLE} test -shim-path $ +# WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} +# DEPENDS all_tests bssl_shim +# ${MAYBE_USES_TERMINAL}) diff --git a/external/boringssl/CONTRIBUTING.md b/external/boringssl/CONTRIBUTING.md new file mode 100644 index 0000000000..8907cc98cb --- /dev/null +++ b/external/boringssl/CONTRIBUTING.md @@ -0,0 +1,49 @@ +Want to contribute? Great! First, read this page (including the small print at the end). + +### Before you contribute +Before we can use your code, you must sign the +[Google Individual Contributor License Agreement](https://cla.developers.google.com/about/google-individual) +(CLA), which you can do online. The CLA is necessary mainly because you own the +copyright to your changes, even after your contribution becomes part of our +codebase, so we need your permission to use and distribute your code. We also +need to be sure of various other things—for instance that you'll tell us if you +know that your code infringes on other people's patents. You don't have to sign +the CLA until after you've submitted your code for review and a member has +approved it, but you must do it before we can put your code into our codebase. +Before you start working on a larger contribution, you should get in touch with +us first via email with your idea so that we can help out and possibly guide +you. Coordinating up front makes it much easier to avoid frustration later on. + +### Code reviews +All submissions, including submissions by project members, require review. We +use [Gerrit](https://boringssl-review.googlesource.com) for this purpose. + +#### Setup +If you have not done so on this machine, you will need to set up a password for +Gerrit. Sign in with a Google account, visit +[this link](https://boringssl.googlesource.com/), and click the "Generate +Password" link in the top right. You will also need to prepare your checkout to +[add Change-Ids](https://gerrit-review.googlesource.com/Documentation/cmd-hook-commit-msg.html) +on commit. Run: + + curl -Lo .git/hooks/commit-msg https://boringssl-review.googlesource.com/tools/hooks/commit-msg + chmod u+x .git/hooks/commit-msg + +#### Uploading changes +To upload a change, push it to the special `refs/for/master` target: + + git push origin HEAD:refs/for/master + +The output will then give you a link to the change. Add `agl@google.com` and +`davidben@google.com` as reviewers. + +Pushing a commit with the same Change-Id as an existing change will upload a new +version of it. (Use the `git rebase` or `git commit --amend` commands.) + +For more detailed instructions, see the +[Gerrit User Guide](https://gerrit-review.googlesource.com/Documentation/intro-user.html). + +### The small print +Contributions made by corporations are covered by a different agreement than +the one above, the +[Software Grant and Corporate Contributor License Agreement](https://cla.developers.google.com/about/google-corporate). diff --git a/external/boringssl/FUZZING.md b/external/boringssl/FUZZING.md new file mode 100644 index 0000000000..9f4edef195 --- /dev/null +++ b/external/boringssl/FUZZING.md @@ -0,0 +1,63 @@ +# Fuzz testing + +Modern fuzz testers are very effective and we wish to use them to ensure that no silly bugs creep into BoringSSL. + +We primarily use Clang's [libFuzzer](http://llvm.org/docs/LibFuzzer.html) for fuzz testing and there are a number of fuzz testing functions in `fuzz/`. They are not built by default because they require libFuzzer at build time. + +In order to build the fuzz tests you will need at least Clang 3.7. Pass `-DFUZZ=1` on the CMake command line to enable building BoringSSL with coverage and AddressSanitizer, and to build the fuzz test binaries. You'll probably need to set the `CC` and `CXX` environment variables too, like this: + +``` +CC=clang CXX=clang++ cmake -GNinja -DFUZZ=1 .. +``` + +In order for the fuzz tests to link, the linker needs to find libFuzzer. This is not commonly provided and you may need to download the [Clang source code](http://llvm.org/releases/download.html) and do the following: + +``` +svn co http://llvm.org/svn/llvm-project/llvm/trunk/lib/Fuzzer +clang++ -c -g -O2 -std=c++11 Fuzzer/*.cpp -IFuzzer +ar ruv libFuzzer.a Fuzzer*.o +``` + +Then copy `libFuzzer.a` to the top-level of your BoringSSL source directory. + +From the `build/` directory, you can then run the fuzzers. For example: + +``` +./fuzz/cert -max_len=3072 -jobs=32 -workers=32 ../fuzz/cert_corpus/ +``` + +The arguments to `jobs` and `workers` should be the number of cores that you wish to dedicate to fuzzing. By default, libFuzzer uses the largest test in the corpus (or 64 if empty) as the maximum test case length. The `max_len` argument overrides this. + +The recommended values of `max_len` for each test are: + +| Test | `max_len` value | +|------------|-----------------| +| `cert` | 3072 | +| `client` | 20000 | +| `pkcs8` | 2048 | +| `privkey` | 2048 | +| `server` | 4096 | +| `spki` | 1024 | +| `read_pem` | 512 | + +These were determined by rounding up the length of the largest case in the corpus. + +There are directories in `fuzz/` for each of the fuzzing tests which contain seed files for fuzzing. Some of the seed files were generated manually but many of them are “interesting†results generated by the fuzzing itself. (Where “interesting†means that it triggered a previously unknown path in the code.) + +## Minimising the corpuses + +When a large number of new seeds are available, it's a good idea to minimise the corpus so that different seeds that trigger the same code paths can be deduplicated. + +In order to minimise all the corpuses, build for fuzzing and run `./fuzz/minimise_corpuses.sh`. Note that minimisation is, oddly, often not idempotent for unknown reasons. + +## Fuzzer mode + +When `-DFUZZ=1` is passed into CMake, BoringSSL builds with `BORINGSSL_UNSAFE_FUZZER_MODE` defined. This modifies the library, particularly the TLS stack, to be more friendly to fuzzers. It will: + +* Replace `RAND_bytes` with a deterministic PRNG. Call `RAND_reset_for_fuzzing()` at the start of fuzzers which use `RAND_bytes` to reset the PRNG state. + +* Modify the TLS stack to perform all signature checks (CertificateVerify and ServerKeyExchange) and the Finished check, but always act as if the check succeeded. + +* Treat every cipher as the NULL cipher. + +This is to prevent the fuzzer from getting stuck at a cryptographic invariant in the protocol. diff --git a/external/boringssl/INCORPORATING.md b/external/boringssl/INCORPORATING.md new file mode 100644 index 0000000000..d53f2b5298 --- /dev/null +++ b/external/boringssl/INCORPORATING.md @@ -0,0 +1,90 @@ +# Incorporating BoringSSL into a project + +**Note**: if your target project is not a Google project then first read the +[main README](/README.md) about the purpose of BoringSSL. + +## Directory layout + +Typically projects create a `third_party/boringssl` directory to put +BoringSSL-specific files into. The source code of BoringSSL itself goes into +`third_party/boringssl/src`, either by copying or as a +[submodule](https://git-scm.com/docs/git-submodule). + +It's generally a mistake to put BoringSSL's source code into +`third_party/boringssl` directly because pre-built files and custom build files +need to go somewhere and merging these with the BoringSSL source code makes +updating things more complex. + +## Build support + +BoringSSL is designed to work with many different build systems. Currently, +different projects use [GYP](https://gyp.gsrc.io/), +[GN](https://chromium.googlesource.com/chromium/src/+/master/tools/gn/docs/quick_start.md), +[Bazel](http://bazel.io/) and [Make](https://www.gnu.org/software/make/) to +build BoringSSL, without too much pain. + +The development build system is CMake and the CMake build knows how to +automatically generate the intermediate files that BoringSSL needs. However, +outside of the CMake environment, these intermediates are generated once and +checked into the incorporating project's source repository. This avoids +incorporating projects needing to support Perl and Go in their build systems. + +The script [`util/generate_build_files.py`](/util/generate_build_files.py) +expects to be run from the `third_party/boringssl` directory and to find the +BoringSSL source code in `src/`. You should pass it a single argument: the name +of the build system that you're using. If you don't use any of the supported +build systems then you should augment `generate_build_files.py` with support +for it. + +The script will pregenerate the intermediate files (see +[BUILDING.md](/BUILDING.md) for details about which tools will need to be +installed) and output helper files for that build system. It doesn't generate a +complete build script, just file and test lists, which change often. For +example, see the +[file](https://code.google.com/p/chromium/codesearch#chromium/src/third_party/boringssl/BUILD.generated.gni) +and +[test](https://code.google.com/p/chromium/codesearch#chromium/src/third_party/boringssl/BUILD.generated_tests.gni) +lists generated for GN in Chromium. + +Generally one checks in these generated files alongside the hand-written build +files. Periodically an engineer updates the BoringSSL revision, regenerates +these files and checks in the updated result. As an example, see how this is +done [in Chromium](https://code.google.com/p/chromium/codesearch#chromium/src/third_party/boringssl/). + +## Defines + +BoringSSL does not present a lot of configurability in order to reduce the +number of configurations that need to be tested. But there are a couple of +\#defines that you may wish to set: + +`OPENSSL_NO_ASM` prevents the use of assembly code (although it's up to you to +ensure that the build system doesn't link it in if you wish to reduce binary +size). This will have a significant performance impact but can be useful if you +wish to use tools like +[AddressSanitizer](http://clang.llvm.org/docs/AddressSanitizer.html) that +interact poorly with assembly code. + +`OPENSSL_SMALL` removes some code that is especially large at some performance +cost. + +## Symbols + +You cannot link multiple versions of BoringSSL or OpenSSL into a single binary +without dealing with symbol conflicts. If you are statically linking multiple +versions together, there's not a lot that can be done because C doesn't have a +module system. + +If you are using multiple versions in a single binary, in different shared +objects, ensure you build BoringSSL with `-fvisibility=hidden` and do not +export any of BoringSSL's symbols. This will prevent any collisions with other +verisons that may be included in other shared objects. Note that this requires +that all callers of BoringSSL APIs live in the same shared object as BoringSSL. + +If you require that BoringSSL APIs be used across shared object boundaries, +continue to build with `-fvisibility=hidden` but define +`BORINGSSL_SHARED_LIBRARY` in both BoringSSL and consumers. BoringSSL's own +source files (but *not* consumers' source files) must also build with +`BORINGSSL_IMPLEMENTATION` defined. This will export BoringSSL's public symbols +in the resulting shared object while hiding private symbols. However note that, +as with a static link, this precludes dynamically linking with another version +of BoringSSL or OpenSSL. diff --git a/external/boringssl/LICENSE b/external/boringssl/LICENSE new file mode 100644 index 0000000000..a25996f720 --- /dev/null +++ b/external/boringssl/LICENSE @@ -0,0 +1,192 @@ +BoringSSL is a fork of OpenSSL. As such, large parts of it fall under OpenSSL +licensing. Files that are completely new have a Google copyright and an ISC +license. This license is reproduced at the bottom of this file. + +Contributors to BoringSSL are required to follow the CLA rules for Chromium: +https://cla.developers.google.com/clas + +Some files from Intel are under yet another license, which is also included +underneath. + +The OpenSSL toolkit stays under a dual license, i.e. both the conditions of the +OpenSSL License and the original SSLeay license apply to the toolkit. See below +for the actual license texts. Actually both licenses are BSD-style Open Source +licenses. In case of any license issues related to OpenSSL please contact +openssl-core@openssl.org. + +The following are Google-internal bug numbers where explicit permission from +some authors is recorded for use of their work. (This is purely for our own +record keeping.) + 27287199 + 27287880 + 27287883 + + OpenSSL License + --------------- + +/* ==================================================================== + * Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + + Original SSLeay License + ----------------------- + +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + + +ISC license used for completely new code in BoringSSL: + +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + + +Some files from Intel carry the following license: + +# Copyright (c) 2012, Intel Corporation +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of the Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# +# THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION ""AS IS"" AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/external/boringssl/PORTING.md b/external/boringssl/PORTING.md new file mode 100644 index 0000000000..f953e746d5 --- /dev/null +++ b/external/boringssl/PORTING.md @@ -0,0 +1,187 @@ +# Porting from OpenSSL to BoringSSL + +BoringSSL is an OpenSSL derivative and is mostly source-compatible, for the +subset of OpenSSL retained. Libraries ideally need little to no changes for +BoringSSL support, provided they do not use removed APIs. In general, see if the +library compiles and, on failure, consult the documentation in the header files +and see if problematic features can be removed. + +In some cases, BoringSSL-specific code may be necessary. In that case, the +`OPENSSL_IS_BORINGSSL` preprocessor macro may be used in `#ifdef`s. This macro +should also be used in lieu of the presence of any particular function to detect +OpenSSL vs BoringSSL in configure scripts, etc., where those are necessary. + +For convenience, BoringSSL defines upstream's `OPENSSL_NO_*` feature macros +corresponding to removed features. These may also be used to disable code which +uses a removed feature. + +Note: BoringSSL does *not* have a stable API or ABI. It must be updated with its +consumers. It is not suitable for, say, a system library in a traditional Linux +distribution. For instance, Chromium statically links the specific revision of +BoringSSL it was built against. Likewise, Android's system-internal copy of +BoringSSL is not exposed by the NDK and must not be used by third-party +applications. + + +## Major API changes + +### Integer types + +Some APIs have been converted to use `size_t` for consistency and to avoid +integer overflows at the API boundary. (Existing logic uses a mismash of `int`, +`long`, and `unsigned`.) For the most part, implicit casts mean that existing +code continues to compile. In some cases, this may require BoringSSL-specific +code, particularly to avoid compiler warnings. + +Most notably, the `STACK_OF(T)` types have all been converted to use `size_t` +instead of `int` for indices and lengths. + +### Reference counts + +Some external consumers increment reference counts directly by calling +`CRYPTO_add` with the corresponding `CRYPTO_LOCK_*` value. + +These APIs no longer exist in BoringSSL. Instead, code which increments +reference counts should call the corresponding `FOO_up_ref` function, such as +`EVP_PKEY_up_ref`. Note that not all of these APIs are present in OpenSSL and +may require `#ifdef`s. + +### Error codes + +OpenSSL's errors are extremely specific, leaking internals of the library, +including even a function code for the function which emitted the error! As some +logic in BoringSSL has been rewritten, code which conditions on the error may +break (grep for `ERR_GET_REASON` and `ERR_GET_FUNC`). This danger also exists +when upgrading OpenSSL versions. + +Where possible, avoid conditioning on the exact error reason. Otherwise, a +BoringSSL `#ifdef` may be necessary. Exactly how best to resolve this issue is +still being determined. It's possible some new APIs will be added in the future. + +Function codes have been completely removed. Remove code which conditions on +these as it will break with the slightest change in the library, OpenSSL or +BoringSSL. + +### `*_ctrl` functions + +Some OpenSSL APIs are implemented with `ioctl`-style functions such as +`SSL_ctrl` and `EVP_PKEY_CTX_ctrl`, combined with convenience macros, such as + + # define SSL_CTX_set_mode(ctx,op) \ + SSL_CTX_ctrl((ctx),SSL_CTRL_MODE,(op),NULL) + +In BoringSSL, these macros have been replaced with proper functions. The +underlying `_ctrl` functions have been removed. + +For convenience, `SSL_CTRL_*` values are retained as macros to `doesnt_exist` so +existing code which uses them (or the wrapper macros) in `#ifdef` expressions +will continue to function. However, the macros themselves will not work. + +Switch any `*_ctrl` callers to the macro/function versions. This works in both +OpenSSL and BoringSSL. Note that BoringSSL's function versions will be +type-checked and may require more care with types. + +### HMAC `EVP_PKEY`s + +`EVP_PKEY_HMAC` is removed. Use the `HMAC_*` functions in `hmac.h` instead. This +is compatible with OpenSSL. + +### DSA `EVP_PKEY`s + +`EVP_PKEY_DSA` is deprecated. It is currently still possible to parse DER into a +DSA `EVP_PKEY`, but signing or verifying with those objects will not work. + +### DES + +The `DES_cblock` type has been switched from an array to a struct to avoid the +pitfalls around array types in C. Where features which require DES cannot be +disabled, BoringSSL-specific codepaths may be necessary. + +### TLS renegotiation + +OpenSSL enables TLS renegotiation by default and accepts renegotiation requests +from the peer transparently. Renegotiation is an extremely problematic protocol +feature, so BoringSSL rejects peer renegotiations by default. + +To enable renegotiation, call `SSL_set_renegotiate_mode` and set it to +`ssl_renegotiate_once` or `ssl_renegotiate_freely`. Renegotiation is only +supported as a client in SSL3/TLS and the HelloRequest must be received at a +quiet point in the application protocol. This is sufficient to support the +common use of requesting a new client certificate between an HTTP request and +response in (unpipelined) HTTP/1.1. + +Things which do not work: + +* There is no support for renegotiation as a server. + +* There is no support for renegotiation in DTLS. + +* There is no support for initiating renegotiation; `SSL_renegotiate` always + fails and `SSL_set_state` does nothing. + +* Interleaving application data with the new handshake is forbidden. + +* If a HelloRequest is received while `SSL_write` has unsent application data, + the renegotiation is rejected. + +### Lowercase hexadecimal + +BoringSSL's `BN_bn2hex` function uses lowercase hexadecimal digits instead of +uppercase. Some code may require changes to avoid being sensitive to this +difference. + +### Legacy ASN.1 functions + +OpenSSL's ASN.1 stack uses `d2i` functions for parsing. They have the form: + + RSA *d2i_RSAPrivateKey(RSA **out, const uint8_t **inp, long len); + +In addition to returning the result, OpenSSL places it in `*out` if `out` is +not `NULL`. On input, if `*out` is not `NULL`, OpenSSL will usually (but not +always) reuse that object rather than allocating a new one. In BoringSSL, these +functions are compatibility wrappers over a newer ASN.1 stack. Even if `*out` +is not `NULL`, these wrappers will always allocate a new object and free the +previous one. + +Ensure that callers do not rely on this object reuse behavior. It is +recommended to avoid the `out` parameter completely and always pass in `NULL`. +Note that less error-prone APIs are available for BoringSSL-specific code (see +below). + +## Optional BoringSSL-specific simplifications + +BoringSSL makes some changes to OpenSSL which simplify the API but remain +compatible with OpenSSL consumers. In general, consult the BoringSSL +documentation for any functions in new BoringSSL-only code. + +### Return values + +Most OpenSSL APIs return 1 on success and either 0 or -1 on failure. BoringSSL +has narrowed most of these to 1 on success and 0 on failure. BoringSSL-specific +code may take advantage of the less error-prone APIs and use `!` to check for +errors. + +### Initialization + +OpenSSL has a number of different initialization functions for setting up error +strings and loading algorithms, etc. All of these functions still exist in +BoringSSL for convenience, but they do nothing and are not necessary. + +The one exception is `CRYPTO_library_init`. In `BORINGSSL_NO_STATIC_INITIALIZER` +builds, it must be called to query CPU capabitilies before the rest of the +library. In the default configuration, this is done with a static initializer +and is also unnecessary. + +### Threading + +OpenSSL provides a number of APIs to configure threading callbacks and set up +locks. Without initializing these, the library is not thread-safe. Configuring +these does nothing in BoringSSL. Instead, BoringSSL calls pthreads and the +corresponding Windows APIs internally and is always thread-safe where the API +guarantees it. + +### ASN.1 + +BoringSSL is in the process of deprecating OpenSSL's `d2i` and `i2d` in favor of +new functions using the much less error-prone `CBS` and `CBB` types. +BoringSSL-only code should use those functions where available. diff --git a/external/boringssl/README.md b/external/boringssl/README.md new file mode 100644 index 0000000000..4caedb76a8 --- /dev/null +++ b/external/boringssl/README.md @@ -0,0 +1,32 @@ +# BoringSSL + +BoringSSL is a fork of OpenSSL that is designed to meet Google's needs. + +Although BoringSSL is an open source project, it is not intended for general +use, as OpenSSL is. We don't recommend that third parties depend upon it. Doing +so is likely to be frustrating because there are no guarantees of API or ABI +stability. + +Programs ship their own copies of BoringSSL when they use it and we update +everything as needed when deciding to make API changes. This allows us to +mostly avoid compromises in the name of compatibility. It works for us, but it +may not work for you. + +BoringSSL arose because Google used OpenSSL for many years in various ways and, +over time, built up a large number of patches that were maintained while +tracking upstream OpenSSL. As Google's product portfolio became more complex, +more copies of OpenSSL sprung up and the effort involved in maintaining all +these patches in multiple places was growing steadily. + +Currently BoringSSL is the SSL library in Chrome/Chromium, Android (but it's +not part of the NDK) and a number of other apps/programs. + +There are other files in this directory which might be helpful: + + * [PORTING.md](/PORTING.md): how to port OpenSSL-using code to BoringSSL. + * [BUILDING.md](/BUILDING.md): how to build BoringSSL + * [INCORPORATING.md](/INCORPORATING.md): how to incorporate BoringSSL into a project. + * [STYLE.md](/STYLE.md): rules and guidelines for coding style. + * include/openssl: public headers with API documentation in comments. Also [available online](https://commondatastorage.googleapis.com/chromium-boringssl-docs/headers.html). + * [FUZZING.md](/FUZZING.md): information about fuzzing BoringSSL. + * [CONTRIBUTING.md](/CONTRIBUTING.md): how to contribute to BoringSSL. diff --git a/external/boringssl/STYLE.md b/external/boringssl/STYLE.md new file mode 100644 index 0000000000..17295b4f6d --- /dev/null +++ b/external/boringssl/STYLE.md @@ -0,0 +1,197 @@ +# BoringSSL Style Guide + +BoringSSL usually follows the +[Google C++ style guide](https://google.github.io/styleguide/cppguide.html), +The rest of this document describes differences and clarifications on +top of the base guide. + + +## Legacy code + +As a derivative of OpenSSL, BoringSSL contains a lot of legacy code that +does not follow this style guide. Particularly where public API is +concerned, balance consistency within a module with the benefits of a +given rule. Module-wide deviations on naming should be respected while +integer and return value conventions take precedence over consistency. + +Modules from OpenSSL's legacy ASN.1 and X.509 stack are retained for +compatibility and left largely unmodified. To ease importing patches from +upstream, they match OpenSSL's new indentation style. For Emacs, +`doc/openssl-c-indent.el` from OpenSSL may be helpful in this. + + +## Language + +The majority of the project is in C, so C++-specific rules in the +Google style guide do not apply. Support for C99 features depends on +our target platforms. Typically, Chromium's target MSVC is the most +restrictive. + +Variable declarations in the middle of a function are allowed. + +Comments should be `/* C-style */` for consistency. + +When declaration pointer types, `*` should be placed next to the variable +name, not the type. So + + uint8_t *ptr; + +not + + uint8_t* ptr; + +Rather than `malloc()` and `free()`, use the wrappers `OPENSSL_malloc()` +and `OPENSSL_free()`. Use the standard C `assert()` function freely. + +For new constants, prefer enums when the values are sequential and typed +constants for flags. If adding values to an existing set of `#define`s, +continue with `#define`. + + +## Formatting + +Single-statement blocks are not allowed. All conditions and loops must +use braces: + + if (foo) { + do_something(); + } + +not + + if (foo) + do_something(); + + +## Integers + +Prefer using explicitly-sized integers where appropriate rather than +generic C ones. For instance, to represent a byte, use `uint8_t`, not +`unsigned char`. Likewise, represent a two-byte field as `uint16_t`, not +`unsigned short`. + +Sizes are represented as `size_t`. + +Within a struct that is retained across the lifetime of an SSL +connection, if bounds of a size are known and it's easy, use a smaller +integer type like `uint8_t`. This is a "free" connection footprint +optimization for servers. Don't make code significantly more complex for +it, and do still check the bounds when passing in and out of the +struct. This narrowing should not propagate to local variables and +function parameters. + +When doing arithmetic, account for overflow conditions. + +Except with platform APIs, do not use `ssize_t`. MSVC lacks it, and +prefer out-of-band error signaling for `size_t` (see Return values). + + +## Naming + +Follow Google naming conventions in C++ files. In C files, use the +following naming conventions for consistency with existing OpenSSL and C +styles: + +Define structs with typedef named `TYPE_NAME`. The corresponding struct +should be named `struct type_name_st`. + +Name public functions as `MODULE_function_name`, unless the module +already uses a different naming scheme for legacy reasons. The module +name should be a type name if the function is a method of a particular +type. + +Some types are allocated within the library while others are initialized +into a struct allocated by the caller, often on the stack. Name these +functions `TYPE_NAME_new`/`TYPE_NAME_free` and +`TYPE_NAME_init`/`TYPE_NAME_cleanup`, respectively. All `TYPE_NAME_free` +functions must do nothing on `NULL` input. + +If a variable is the length of a pointer value, it has the suffix +`_len`. An output parameter is named `out` or has an `out_` prefix. For +instance, For instance: + + uint8_t *out, + size_t *out_len, + const uint8_t *in, + size_t in_len, + +Name public headers like `include/openssl/evp.h` with header guards like +`OPENSSL_HEADER_EVP_H`. Name internal headers like +`crypto/ec/internal.h` with header guards like +`OPENSSL_HEADER_EC_INTERNAL_H`. + +Name enums like `enum unix_hacker_t`. For instance: + + enum should_free_handshake_buffer_t { + free_handshake_buffer, + dont_free_handshake_buffer, + }; + + +## Return values + +As even `malloc` may fail in BoringSSL, the vast majority of functions +will have a failure case. Functions should return `int` with one on +success and zero on error. Do not overload the return value to both +signal success/failure and output an integer. For example: + + OPENSSL_EXPORT int CBS_get_u16(CBS *cbs, uint16_t *out); + +If a function needs more than a true/false result code, define an enum +rather than arbitrarily assigning meaning to int values. + +If a function outputs a pointer to an object on success and there are no +other outputs, return the pointer directly and `NULL` on error. + + +## Parameters + +Where not constrained by legacy code, parameter order should be: + +1. context parameters +2. output parameters +3. input parameters + +For example, + + /* CBB_add_asn sets |*out_contents| to a |CBB| into which the contents of an + * ASN.1 object can be written. The |tag| argument will be used as the tag for + * the object. It returns one on success or zero on error. */ + OPENSSL_EXPORT int CBB_add_asn1(CBB *cbb, CBB *out_contents, uint8_t tag); + + +## Documentation + +All public symbols must have a documentation comment in their header +file. The style is based on that of Go. The first sentence begins with +the symbol name, optionally prefixed with "A" or "An". Apart from the +initial mention of symbol, references to other symbols or parameter +names should be surrounded by |pipes|. + +Documentation should be concise but completely describe the exposed +behavior of the function. Pay special note to success/failure behaviors +and caller obligations on object lifetimes. If this sacrifices +conciseness, consider simplifying the function's behavior. + + /* EVP_DigestVerifyUpdate appends |len| bytes from |data| to the data which + * will be verified by |EVP_DigestVerifyFinal|. It returns one on success and + * zero otherwise. */ + OPENSSL_EXPORT int EVP_DigestVerifyUpdate(EVP_MD_CTX *ctx, const void *data, + size_t len); + +Explicitly mention any surprising edge cases or deviations from common +return value patterns in legacy functions. + + /* RSA_private_encrypt encrypts |flen| bytes from |from| with the private key in + * |rsa| and writes the encrypted data to |to|. The |to| buffer must have at + * least |RSA_size| bytes of space. It returns the number of bytes written, or + * -1 on error. The |padding| argument must be one of the |RSA_*_PADDING| + * values. If in doubt, |RSA_PKCS1_PADDING| is the most common. + * + * WARNING: this function is dangerous because it breaks the usual return value + * convention. Use |RSA_sign_raw| instead. */ + OPENSSL_EXPORT int RSA_private_encrypt(int flen, const uint8_t *from, + uint8_t *to, RSA *rsa, int padding); + +Document private functions in their `internal.h` header or, if static, +where defined. diff --git a/external/boringssl/codereview.settings b/external/boringssl/codereview.settings new file mode 100644 index 0000000000..1e123a1912 --- /dev/null +++ b/external/boringssl/codereview.settings @@ -0,0 +1,4 @@ +# This file is used by gcl to get repository specific information. +GERRIT_HOST: True +GERRIT_PORT: True +CODE_REVIEW_SERVER: https://boringssl-review.googlesource.com diff --git a/external/boringssl/crypto/CMakeLists.txt b/external/boringssl/crypto/CMakeLists.txt new file mode 100644 index 0000000000..94e47ea1f5 --- /dev/null +++ b/external/boringssl/crypto/CMakeLists.txt @@ -0,0 +1,277 @@ +include_directories(../include) + +if(APPLE) + if (${ARCH} STREQUAL "x86") + set(PERLASM_FLAGS "-fPIC -DOPENSSL_IA32_SSE2") + endif() + set(PERLASM_STYLE macosx) + set(ASM_EXT S) + enable_language(ASM) +elseif(UNIX) + if (${ARCH} STREQUAL "aarch64") + # The "armx" Perl scripts look for "64" in the style argument + # in order to decide whether to generate 32- or 64-bit asm. + set(PERLASM_STYLE linux64) + elseif (${ARCH} STREQUAL "arm") + set(PERLASM_STYLE linux32) + elseif (${ARCH} STREQUAL "x86") + set(PERLASM_FLAGS "-fPIC -DOPENSSL_IA32_SSE2") + set(PERLASM_STYLE elf) + else() + set(PERLASM_STYLE elf) + endif() + set(ASM_EXT S) + enable_language(ASM) + set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -Wa,--noexecstack") +else() + if (CMAKE_CL_64) + message("Using nasm") + set(PERLASM_STYLE nasm) + else() + message("Using win32n") + set(PERLASM_STYLE win32n) + set(PERLASM_FLAGS "-DOPENSSL_IA32_SSE2") + endif() + + # On Windows, we use the NASM output, specifically built with Yasm. + set(ASM_EXT asm) + enable_language(ASM_NASM) +endif() + +function(perlasm dest src) + add_custom_command( + OUTPUT ${dest} + COMMAND ${PERL_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/${src} ${PERLASM_STYLE} ${PERLASM_FLAGS} ${ARGN} > ${dest} + DEPENDS + ${src} + ${PROJECT_SOURCE_DIR}/crypto/perlasm/arm-xlate.pl + ${PROJECT_SOURCE_DIR}/crypto/perlasm/x86_64-xlate.pl + ${PROJECT_SOURCE_DIR}/crypto/perlasm/x86asm.pl + ${PROJECT_SOURCE_DIR}/crypto/perlasm/x86gas.pl + ${PROJECT_SOURCE_DIR}/crypto/perlasm/x86masm.pl + ${PROJECT_SOURCE_DIR}/crypto/perlasm/x86nasm.pl + WORKING_DIRECTORY . + ) +endfunction() + +# Level 0.1 - depends on nothing outside this set. +add_subdirectory(stack) +add_subdirectory(lhash) +add_subdirectory(err) +add_subdirectory(buf) +add_subdirectory(base64) +add_subdirectory(bytestring) + +# Level 0.2 - depends on nothing but itself +add_subdirectory(sha) +add_subdirectory(md4) +add_subdirectory(md5) +add_subdirectory(modes) +add_subdirectory(aes) +add_subdirectory(des) +add_subdirectory(rc4) +add_subdirectory(conf) +add_subdirectory(chacha) +add_subdirectory(poly1305) +add_subdirectory(curve25519) +add_subdirectory(newhope) + +# Level 1, depends only on 0.* +add_subdirectory(digest) +add_subdirectory(cipher) +add_subdirectory(rand) +add_subdirectory(bio) +add_subdirectory(bn) +add_subdirectory(obj) +add_subdirectory(asn1) + +# Level 2 +add_subdirectory(engine) +add_subdirectory(dh) +add_subdirectory(dsa) +add_subdirectory(rsa) +add_subdirectory(ec) +add_subdirectory(ecdh) +add_subdirectory(ecdsa) +add_subdirectory(hmac) + +# Level 3 +add_subdirectory(cmac) +add_subdirectory(evp) +add_subdirectory(hkdf) +add_subdirectory(pem) +add_subdirectory(x509) +add_subdirectory(x509v3) + +# Level 4 +add_subdirectory(pkcs8) + +# Test support code +if(ENABLE_TESTS) +add_subdirectory(test) +endif() + +set( + crypto_objects_dependencies + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + PARENT_SCOPE +) + +add_library( + crypto-objects OBJECT + + cpu-aarch64-linux.c + cpu-arm.c + cpu-arm-linux.c + cpu-intel.c + crypto.c + ex_data.c + mem.c + refcount_c11.c + refcount_lock.c + thread.c + thread_none.c + thread_pthread.c + thread_win.c + time_support.c + + ${CRYPTO_ARCH_SOURCES} +) + + + +add_library( + crypto + + cpu-aarch64-linux.c + cpu-arm.c + cpu-arm-linux.c + cpu-intel.c + crypto.c + ex_data.c + mem.c + refcount_c11.c + refcount_lock.c + thread.c + thread_none.c + thread_pthread.c + thread_win.c + time_support.c + + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ +) + +if(NOT MSVC AND NOT ANDROID) + target_link_libraries(crypto pthread) +endif() + +if(ENABLE_TESTS) +add_executable( + constant_time_test + + constant_time_test.c + + $ +) + +target_link_libraries(constant_time_test crypto) +add_dependencies(all_tests constant_time_test) + +add_executable( + thread_test + + thread_test.c + + $ +) + +target_link_libraries(thread_test crypto) +add_dependencies(all_tests thread_test) + +add_executable( + refcount_test + + refcount_test.c +) + +target_link_libraries(refcount_test crypto) +add_dependencies(all_tests refcount_test) +endif() diff --git a/external/boringssl/crypto/aes/CMakeLists.txt b/external/boringssl/crypto/aes/CMakeLists.txt new file mode 100644 index 0000000000..0470585696 --- /dev/null +++ b/external/boringssl/crypto/aes/CMakeLists.txt @@ -0,0 +1,74 @@ +include_directories(../../include) + +if (${ARCH} STREQUAL "x86_64") + set( + AES_ARCH_SOURCES + + aes-x86_64.${ASM_EXT} + aesni-x86_64.${ASM_EXT} + bsaes-x86_64.${ASM_EXT} + vpaes-x86_64.${ASM_EXT} + ) +endif() + +if (${ARCH} STREQUAL "x86") + set( + AES_ARCH_SOURCES + + aes-586.${ASM_EXT} + vpaes-x86.${ASM_EXT} + aesni-x86.${ASM_EXT} + ) +endif() + +if (${ARCH} STREQUAL "arm") + set( + AES_ARCH_SOURCES + + aes-armv4.${ASM_EXT} + bsaes-armv7.${ASM_EXT} + aesv8-armx.${ASM_EXT} + ) +endif() + +if (${ARCH} STREQUAL "aarch64") + set( + AES_ARCH_SOURCES + + aesv8-armx.${ASM_EXT} + ) +endif() + +add_library( + aes + + OBJECT + + aes.c + mode_wrappers.c + + ${AES_ARCH_SOURCES} +) + +perlasm(aes-x86_64.${ASM_EXT} asm/aes-x86_64.pl) +perlasm(aesni-x86_64.${ASM_EXT} asm/aesni-x86_64.pl) +perlasm(bsaes-x86_64.${ASM_EXT} asm/bsaes-x86_64.pl) +perlasm(vpaes-x86_64.${ASM_EXT} asm/vpaes-x86_64.pl) +perlasm(aes-586.${ASM_EXT} asm/aes-586.pl) +perlasm(vpaes-x86.${ASM_EXT} asm/vpaes-x86.pl) +perlasm(aesni-x86.${ASM_EXT} asm/aesni-x86.pl) +perlasm(aes-armv4.${ASM_EXT} asm/aes-armv4.pl) +perlasm(bsaes-armv7.${ASM_EXT} asm/bsaes-armv7.pl) +perlasm(aesv8-armx.${ASM_EXT} asm/aesv8-armx.pl) + +if(ENABLE_TESTS) +add_executable( + aes_test + + aes_test.cc + $ +) + +target_link_libraries(aes_test crypto) +add_dependencies(all_tests aes_test) +endif() diff --git a/external/boringssl/crypto/aes/aes.c b/external/boringssl/crypto/aes/aes.c new file mode 100644 index 0000000000..882391986d --- /dev/null +++ b/external/boringssl/crypto/aes/aes.c @@ -0,0 +1,1142 @@ +/* ==================================================================== + * Copyright (c) 2002-2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== */ + +#include + +#include +#include + +#include + +#include "internal.h" + + +#if defined(OPENSSL_NO_ASM) || \ + (!defined(OPENSSL_X86) && !defined(OPENSSL_X86_64) && !defined(OPENSSL_ARM)) + +/* Te0[x] = S [x].[02, 01, 01, 03]; + * Te1[x] = S [x].[03, 02, 01, 01]; + * Te2[x] = S [x].[01, 03, 02, 01]; + * Te3[x] = S [x].[01, 01, 03, 02]; + * + * Td0[x] = Si[x].[0e, 09, 0d, 0b]; + * Td1[x] = Si[x].[0b, 0e, 09, 0d]; + * Td2[x] = Si[x].[0d, 0b, 0e, 09]; + * Td3[x] = Si[x].[09, 0d, 0b, 0e]; + * Td4[x] = Si[x].[01]; */ + +static const uint32_t Te0[256] = { + 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU, 0xfff2f20dU, + 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U, 0x60303050U, 0x02010103U, + 0xce6767a9U, 0x562b2b7dU, 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, + 0xec76769aU, 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U, + 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU, 0x41adadecU, + 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU, 0x239c9cbfU, 0x53a4a4f7U, + 0xe4727296U, 0x9bc0c05bU, 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, + 0x4c26266aU, 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU, + 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U, 0xe2717193U, + 0xabd8d873U, 0x62313153U, 0x2a15153fU, 0x0804040cU, 0x95c7c752U, + 0x46232365U, 0x9dc3c35eU, 0x30181828U, 0x379696a1U, 0x0a05050fU, + 0x2f9a9ab5U, 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU, + 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU, 0x1209091bU, + 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU, 0x361b1b2dU, 0xdc6e6eb2U, + 0xb45a5aeeU, 0x5ba0a0fbU, 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, + 0x7db3b3ceU, 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U, + 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU, 0x40202060U, + 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU, 0xd46a6abeU, 0x8dcbcb46U, + 0x67bebed9U, 0x7239394bU, 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, + 0x85cfcf4aU, 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U, + 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U, 0x8a4545cfU, + 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U, 0xa05050f0U, 0x783c3c44U, + 0x259f9fbaU, 0x4ba8a8e3U, 0xa25151f3U, 0x5da3a3feU, 0x804040c0U, + 0x058f8f8aU, 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U, + 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U, 0x20101030U, + 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU, 0x81cdcd4cU, 0x180c0c14U, + 0x26131335U, 0xc3ecec2fU, 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, + 0x2e171739U, 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U, + 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U, 0xc06060a0U, + 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU, 0x44222266U, 0x542a2a7eU, + 0x3b9090abU, 0x0b888883U, 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, + 0x2814143cU, 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U, + 0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU, 0x924949dbU, + 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U, 0x9fc2c25dU, 0xbdd3d36eU, + 0x43acacefU, 0xc46262a6U, 0x399191a8U, 0x319595a4U, 0xd3e4e437U, + 0xf279798bU, 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U, + 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U, 0xd86c6cb4U, + 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U, 0xca6565afU, 0xf47a7a8eU, + 0x47aeaee9U, 0x10080818U, 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, + 0x5c2e2e72U, 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U, + 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U, 0x964b4bddU, + 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U, 0xe0707090U, 0x7c3e3e42U, + 0x71b5b5c4U, 0xcc6666aaU, 0x904848d8U, 0x06030305U, 0xf7f6f601U, + 0x1c0e0e12U, 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U, + 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U, 0xd9e1e138U, + 0xebf8f813U, 0x2b9898b3U, 0x22111133U, 0xd26969bbU, 0xa9d9d970U, + 0x078e8e89U, 0x339494a7U, 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, + 0xc9e9e920U, 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU, + 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U, 0x65bfbfdaU, + 0xd7e6e631U, 0x844242c6U, 0xd06868b8U, 0x824141c3U, 0x299999b0U, + 0x5a2d2d77U, 0x1e0f0f11U, 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, + 0x2c16163aU, }; + +static const uint32_t Te1[256] = { + 0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU, 0x0dfff2f2U, + 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U, 0x50603030U, 0x03020101U, + 0xa9ce6767U, 0x7d562b2bU, 0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, + 0x9aec7676U, 0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU, + 0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U, 0xec41adadU, + 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU, 0xbf239c9cU, 0xf753a4a4U, + 0x96e47272U, 0x5b9bc0c0U, 0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, + 0x6a4c2626U, 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU, + 0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U, 0x93e27171U, + 0x73abd8d8U, 0x53623131U, 0x3f2a1515U, 0x0c080404U, 0x5295c7c7U, + 0x65462323U, 0x5e9dc3c3U, 0x28301818U, 0xa1379696U, 0x0f0a0505U, + 0xb52f9a9aU, 0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U, + 0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U, 0x1b120909U, + 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU, 0x2d361b1bU, 0xb2dc6e6eU, + 0xeeb45a5aU, 0xfb5ba0a0U, 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, + 0xce7db3b3U, 0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U, + 0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU, 0x60402020U, + 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU, 0xbed46a6aU, 0x468dcbcbU, + 0xd967bebeU, 0x4b723939U, 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, + 0x4a85cfcfU, 0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU, + 0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U, 0xcf8a4545U, + 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU, 0xf0a05050U, 0x44783c3cU, + 0xba259f9fU, 0xe34ba8a8U, 0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, + 0x8a058f8fU, 0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U, + 0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U, 0x30201010U, + 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U, 0x4c81cdcdU, 0x14180c0cU, + 0x35261313U, 0x2fc3ececU, 0xe1be5f5fU, 0xa2359797U, 0xcc884444U, + 0x392e1717U, 0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU, + 0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U, 0xa0c06060U, + 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU, 0x66442222U, 0x7e542a2aU, + 0xab3b9090U, 0x830b8888U, 0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, + 0x3c281414U, 0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU, + 0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU, 0xdb924949U, + 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU, 0x5d9fc2c2U, 0x6ebdd3d3U, + 0xef43acacU, 0xa6c46262U, 0xa8399191U, 0xa4319595U, 0x37d3e4e4U, + 0x8bf27979U, 0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU, + 0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U, 0xb4d86c6cU, + 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU, 0xafca6565U, 0x8ef47a7aU, + 0xe947aeaeU, 0x18100808U, 0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, + 0x725c2e2eU, 0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U, + 0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU, 0xdd964b4bU, + 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU, 0x90e07070U, 0x427c3e3eU, + 0xc471b5b5U, 0xaacc6666U, 0xd8904848U, 0x05060303U, 0x01f7f6f6U, + 0x121c0e0eU, 0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U, + 0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU, 0x38d9e1e1U, + 0x13ebf8f8U, 0xb32b9898U, 0x33221111U, 0xbbd26969U, 0x70a9d9d9U, + 0x89078e8eU, 0xa7339494U, 0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, + 0x20c9e9e9U, 0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU, + 0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU, 0xda65bfbfU, + 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U, 0xc3824141U, 0xb0299999U, + 0x775a2d2dU, 0x111e0f0fU, 0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, + 0x3a2c1616U, }; + +static const uint32_t Te2[256] = { + 0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU, 0xf20dfff2U, + 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U, 0x30506030U, 0x01030201U, + 0x67a9ce67U, 0x2b7d562bU, 0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, + 0x769aec76U, 0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU, + 0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U, 0xadec41adU, + 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU, 0x9cbf239cU, 0xa4f753a4U, + 0x7296e472U, 0xc05b9bc0U, 0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, + 0x266a4c26U, 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU, + 0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U, 0x7193e271U, + 0xd873abd8U, 0x31536231U, 0x153f2a15U, 0x040c0804U, 0xc75295c7U, + 0x23654623U, 0xc35e9dc3U, 0x18283018U, 0x96a13796U, 0x050f0a05U, + 0x9ab52f9aU, 0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U, + 0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U, 0x091b1209U, + 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU, 0x1b2d361bU, 0x6eb2dc6eU, + 0x5aeeb45aU, 0xa0fb5ba0U, 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, + 0xb3ce7db3U, 0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U, + 0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU, 0x20604020U, + 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU, 0x6abed46aU, 0xcb468dcbU, + 0xbed967beU, 0x394b7239U, 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, + 0xcf4a85cfU, 0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU, + 0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U, 0x45cf8a45U, + 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU, 0x50f0a050U, 0x3c44783cU, + 0x9fba259fU, 0xa8e34ba8U, 0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, + 0x8f8a058fU, 0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U, + 0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U, 0x10302010U, + 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U, 0xcd4c81cdU, 0x0c14180cU, + 0x13352613U, 0xec2fc3ecU, 0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, + 0x17392e17U, 0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU, + 0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U, 0x60a0c060U, + 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU, 0x22664422U, 0x2a7e542aU, + 0x90ab3b90U, 0x88830b88U, 0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, + 0x143c2814U, 0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU, + 0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU, 0x49db9249U, + 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU, 0xc25d9fc2U, 0xd36ebdd3U, + 0xacef43acU, 0x62a6c462U, 0x91a83991U, 0x95a43195U, 0xe437d3e4U, + 0x798bf279U, 0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU, + 0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U, 0x6cb4d86cU, + 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU, 0x65afca65U, 0x7a8ef47aU, + 0xaee947aeU, 0x08181008U, 0xbad56fbaU, 0x7888f078U, 0x256f4a25U, + 0x2e725c2eU, 0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U, + 0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU, 0x4bdd964bU, + 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU, 0x7090e070U, 0x3e427c3eU, + 0xb5c471b5U, 0x66aacc66U, 0x48d89048U, 0x03050603U, 0xf601f7f6U, + 0x0e121c0eU, 0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U, + 0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU, 0xe138d9e1U, + 0xf813ebf8U, 0x98b32b98U, 0x11332211U, 0x69bbd269U, 0xd970a9d9U, + 0x8e89078eU, 0x94a73394U, 0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, + 0xe920c9e9U, 0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU, + 0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU, 0xbfda65bfU, + 0xe631d7e6U, 0x42c68442U, 0x68b8d068U, 0x41c38241U, 0x99b02999U, + 0x2d775a2dU, 0x0f111e0fU, 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, + 0x163a2c16U, }; + +static const uint32_t Te3[256] = { + 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U, 0xf2f20dffU, + 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U, 0x30305060U, 0x01010302U, + 0x6767a9ceU, 0x2b2b7d56U, 0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, + 0x76769aecU, 0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU, + 0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU, 0xadadec41U, + 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U, 0x9c9cbf23U, 0xa4a4f753U, + 0x727296e4U, 0xc0c05b9bU, 0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, + 0x26266a4cU, 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U, + 0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U, 0x717193e2U, + 0xd8d873abU, 0x31315362U, 0x15153f2aU, 0x04040c08U, 0xc7c75295U, + 0x23236546U, 0xc3c35e9dU, 0x18182830U, 0x9696a137U, 0x05050f0aU, + 0x9a9ab52fU, 0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU, + 0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU, 0x09091b12U, + 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U, 0x1b1b2d36U, 0x6e6eb2dcU, + 0x5a5aeeb4U, 0xa0a0fb5bU, 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, + 0xb3b3ce7dU, 0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U, + 0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U, 0x20206040U, + 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U, 0x6a6abed4U, 0xcbcb468dU, + 0xbebed967U, 0x39394b72U, 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, + 0xcfcf4a85U, 0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU, + 0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U, 0x4545cf8aU, + 0xf9f910e9U, 0x02020604U, 0x7f7f81feU, 0x5050f0a0U, 0x3c3c4478U, + 0x9f9fba25U, 0xa8a8e34bU, 0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, + 0x8f8f8a05U, 0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U, + 0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U, 0x10103020U, + 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU, 0xcdcd4c81U, 0x0c0c1418U, + 0x13133526U, 0xecec2fc3U, 0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, + 0x1717392eU, 0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU, + 0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U, 0x6060a0c0U, + 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U, 0x22226644U, 0x2a2a7e54U, + 0x9090ab3bU, 0x8888830bU, 0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, + 0x14143c28U, 0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU, + 0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U, 0x4949db92U, + 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U, 0xc2c25d9fU, 0xd3d36ebdU, + 0xacacef43U, 0x6262a6c4U, 0x9191a839U, 0x9595a431U, 0xe4e437d3U, + 0x79798bf2U, 0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU, + 0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U, 0x6c6cb4d8U, + 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU, 0x6565afcaU, 0x7a7a8ef4U, + 0xaeaee947U, 0x08081810U, 0xbabad56fU, 0x787888f0U, 0x25256f4aU, + 0x2e2e725cU, 0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U, + 0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU, 0x4b4bdd96U, + 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU, 0x707090e0U, 0x3e3e427cU, + 0xb5b5c471U, 0x6666aaccU, 0x4848d890U, 0x03030506U, 0xf6f601f7U, + 0x0e0e121cU, 0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U, + 0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U, 0xe1e138d9U, + 0xf8f813ebU, 0x9898b32bU, 0x11113322U, 0x6969bbd2U, 0xd9d970a9U, + 0x8e8e8907U, 0x9494a733U, 0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, + 0xe9e920c9U, 0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U, + 0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU, 0xbfbfda65U, + 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U, 0x4141c382U, 0x9999b029U, + 0x2d2d775aU, 0x0f0f111eU, 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, + 0x16163a2cU, }; + +static const uint32_t Td0[256] = { + 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U, 0x3bab6bcbU, + 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U, 0x2030fa55U, 0xad766df6U, + 0x88cc7691U, 0xf5024c25U, 0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, + 0xb562a38fU, 0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U, + 0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U, 0x038f5fe7U, + 0x15929c95U, 0xbf6d7aebU, 0x955259daU, 0xd4be832dU, 0x587421d3U, + 0x49e06929U, 0x8ec9c844U, 0x75c2896aU, 0xf48e7978U, 0x99583e6bU, + 0x27b971ddU, 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U, + 0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U, 0xb16477e0U, + 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U, 0x70486858U, 0x8f45fd19U, + 0x94de6c87U, 0x527bf8b7U, 0xab73d323U, 0x724b02e2U, 0xe31f8f57U, + 0x6655ab2aU, 0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U, + 0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU, 0x8acf1c2bU, + 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U, 0x65daf4cdU, 0x0605bed5U, + 0xd134621fU, 0xc4a6fe8aU, 0x342e539dU, 0xa2f355a0U, 0x058ae132U, + 0xa4f6eb75U, 0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U, + 0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U, 0x91548db5U, + 0x71c45d05U, 0x0406d46fU, 0x605015ffU, 0x1998fb24U, 0xd6bde997U, + 0x894043ccU, 0x67d99e77U, 0xb0e842bdU, 0x07898b88U, 0xe7195b38U, + 0x79c8eedbU, 0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U, + 0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU, 0xfd0efffbU, + 0x0f853856U, 0x3daed51eU, 0x362d3927U, 0x0a0fd964U, 0x685ca621U, + 0x9b5b54d1U, 0x24362e3aU, 0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, + 0x1b9b919eU, 0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U, + 0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU, 0x0e090d0bU, + 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U, 0x57f11985U, 0xaf75074cU, + 0xee99ddbbU, 0xa37f60fdU, 0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, + 0x5bfb7e34U, 0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U, + 0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U, 0x854a247dU, + 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU, 0x1d9e2f4bU, 0xdcb230f3U, + 0x0d8652ecU, 0x77c1e3d0U, 0x2bb3166cU, 0xa970b999U, 0x119448faU, + 0x47e96422U, 0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU, + 0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U, 0xa6f581cfU, + 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U, 0x2c3a9de4U, 0x5078920dU, + 0x6a5fcc9bU, 0x547e4662U, 0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, + 0x82c3aff5U, 0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U, + 0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU, 0xcd267809U, + 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U, 0xe6956e65U, 0xaaffe67eU, + 0x21bccf08U, 0xef15e8e6U, 0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, + 0x29b07cd6U, 0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U, + 0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U, 0xf104984aU, + 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU, 0x764dd68dU, 0x43efb04dU, + 0xccaa4d54U, 0xe49604dfU, 0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, + 0x4665517fU, 0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU, + 0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U, 0x9ad7618cU, + 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U, 0xcea927eeU, 0xb761c935U, + 0xe11ce5edU, 0x7a47b13cU, 0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, + 0x73c737bfU, 0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U, + 0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU, 0x161dc372U, + 0xbce2250cU, 0x283c498bU, 0xff0d9541U, 0x39a80171U, 0x080cb3deU, + 0xd8b4e49cU, 0x6456c190U, 0x7bcb8461U, 0xd532b670U, 0x486c5c74U, + 0xd0b85742U, }; + +static const uint32_t Td1[256] = { + 0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU, 0xcb3bab6bU, + 0xf11f9d45U, 0xabacfa58U, 0x934be303U, 0x552030faU, 0xf6ad766dU, + 0x9188cc76U, 0x25f5024cU, 0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, + 0x8fb562a3U, 0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U, + 0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U, 0xe7038f5fU, + 0x9515929cU, 0xebbf6d7aU, 0xda955259U, 0x2dd4be83U, 0xd3587421U, + 0x2949e069U, 0x448ec9c8U, 0x6a75c289U, 0x78f48e79U, 0x6b99583eU, + 0xdd27b971U, 0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU, + 0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU, 0xe0b16477U, + 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU, 0x58704868U, 0x198f45fdU, + 0x8794de6cU, 0xb7527bf8U, 0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, + 0x2a6655abU, 0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U, + 0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U, 0x2b8acf1cU, + 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U, 0xcd65daf4U, 0xd50605beU, + 0x1fd13462U, 0x8ac4a6feU, 0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, + 0x75a4f6ebU, 0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U, + 0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU, 0xb591548dU, + 0x0571c45dU, 0x6f0406d4U, 0xff605015U, 0x241998fbU, 0x97d6bde9U, + 0xcc894043U, 0x7767d99eU, 0xbdb0e842U, 0x8807898bU, 0x38e7195bU, + 0xdb79c8eeU, 0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U, + 0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U, 0xfbfd0effU, + 0x560f8538U, 0x1e3daed5U, 0x27362d39U, 0x640a0fd9U, 0x21685ca6U, + 0xd19b5b54U, 0x3a24362eU, 0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, + 0x9e1b9b91U, 0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU, + 0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U, 0x0b0e090dU, + 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U, 0x8557f119U, 0x4caf7507U, + 0xbbee99ddU, 0xfda37f60U, 0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, + 0x345bfb7eU, 0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U, + 0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U, 0x7d854a24U, + 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U, 0x4b1d9e2fU, 0xf3dcb230U, + 0xec0d8652U, 0xd077c1e3U, 0x6c2bb316U, 0x99a970b9U, 0xfa119448U, + 0x2247e964U, 0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U, + 0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU, 0xcfa6f581U, + 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU, 0xe42c3a9dU, 0x0d507892U, + 0x9b6a5fccU, 0x62547e46U, 0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, + 0xf582c3afU, 0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U, + 0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU, 0x09cd2678U, + 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU, 0x65e6956eU, 0x7eaaffe6U, + 0x0821bccfU, 0xe6ef15e8U, 0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, + 0xd629b07cU, 0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U, + 0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U, 0x4af10498U, + 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U, 0x8d764dd6U, 0x4d43efb0U, + 0x54ccaa4dU, 0xdfe49604U, 0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, + 0x7f466551U, 0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U, + 0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U, 0x8c9ad761U, + 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU, 0xeecea927U, 0x35b761c9U, + 0xede11ce5U, 0x3c7a47b1U, 0x599cd2dfU, 0x3f55f273U, 0x791814ceU, + 0xbf73c737U, 0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU, + 0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U, 0x72161dc3U, + 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U, 0x7139a801U, 0xde080cb3U, + 0x9cd8b4e4U, 0x906456c1U, 0x617bcb84U, 0x70d532b6U, 0x74486c5cU, + 0x42d0b857U, }; + +static const uint32_t Td2[256] = { + 0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U, 0x6bcb3babU, + 0x45f11f9dU, 0x58abacfaU, 0x03934be3U, 0xfa552030U, 0x6df6ad76U, + 0x769188ccU, 0x4c25f502U, 0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, + 0xa38fb562U, 0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU, + 0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U, 0x5fe7038fU, + 0x9c951592U, 0x7aebbf6dU, 0x59da9552U, 0x832dd4beU, 0x21d35874U, + 0x692949e0U, 0xc8448ec9U, 0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, + 0x71dd27b9U, 0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU, + 0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U, 0x77e0b164U, + 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U, 0x68587048U, 0xfd198f45U, + 0x6c8794deU, 0xf8b7527bU, 0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, + 0xab2a6655U, 0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U, + 0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U, 0x1c2b8acfU, + 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U, 0xf4cd65daU, 0xbed50605U, + 0x621fd134U, 0xfe8ac4a6U, 0x539d342eU, 0x55a0a2f3U, 0xe132058aU, + 0xeb75a4f6U, 0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU, + 0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U, 0x8db59154U, + 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U, 0xfb241998U, 0xe997d6bdU, + 0x43cc8940U, 0x9e7767d9U, 0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, + 0xeedb79c8U, 0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U, + 0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU, 0xfffbfd0eU, + 0x38560f85U, 0xd51e3daeU, 0x3927362dU, 0xd9640a0fU, 0xa621685cU, + 0x54d19b5bU, 0x2e3a2436U, 0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, + 0x919e1b9bU, 0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U, + 0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU, 0x0d0b0e09U, + 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU, 0x198557f1U, 0x074caf75U, + 0xddbbee99U, 0x60fda37fU, 0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, + 0x7e345bfbU, 0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U, + 0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U, 0x247d854aU, + 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U, 0x2f4b1d9eU, 0x30f3dcb2U, + 0x52ec0d86U, 0xe3d077c1U, 0x166c2bb3U, 0xb999a970U, 0x48fa1194U, + 0x642247e9U, 0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U, + 0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U, 0x81cfa6f5U, + 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU, 0x9de42c3aU, 0x920d5078U, + 0xcc9b6a5fU, 0x4662547eU, 0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, + 0xaff582c3U, 0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U, + 0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU, 0x7809cd26U, + 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU, 0x6e65e695U, 0xe67eaaffU, + 0xcf0821bcU, 0xe8e6ef15U, 0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, + 0x7cd629b0U, 0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U, + 0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U, 0x984af104U, + 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U, 0xd68d764dU, 0xb04d43efU, + 0x4d54ccaaU, 0x04dfe496U, 0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, + 0x517f4665U, 0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU, + 0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U, 0x618c9ad7U, + 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U, 0x27eecea9U, 0xc935b761U, + 0xe5ede11cU, 0xb13c7a47U, 0xdf599cd2U, 0x733f55f2U, 0xce791814U, + 0x37bf73c7U, 0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U, + 0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U, 0xc372161dU, + 0x250cbce2U, 0x498b283cU, 0x9541ff0dU, 0x017139a8U, 0xb3de080cU, + 0xe49cd8b4U, 0xc1906456U, 0x84617bcbU, 0xb670d532U, 0x5c74486cU, + 0x5742d0b8U, }; + +static const uint32_t Td3[256] = { + 0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU, 0xab6bcb3bU, + 0x9d45f11fU, 0xfa58abacU, 0xe303934bU, 0x30fa5520U, 0x766df6adU, + 0xcc769188U, 0x024c25f5U, 0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, + 0x62a38fb5U, 0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU, + 0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU, 0x8f5fe703U, + 0x929c9515U, 0x6d7aebbfU, 0x5259da95U, 0xbe832dd4U, 0x7421d358U, + 0xe0692949U, 0xc9c8448eU, 0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, + 0xb971dd27U, 0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU, + 0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U, 0x6477e0b1U, + 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U, 0x48685870U, 0x45fd198fU, + 0xde6c8794U, 0x7bf8b752U, 0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, + 0x55ab2a66U, 0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U, + 0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU, 0xcf1c2b8aU, + 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU, 0xdaf4cd65U, 0x05bed506U, + 0x34621fd1U, 0xa6fe8ac4U, 0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, + 0xf6eb75a4U, 0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU, + 0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU, 0x548db591U, + 0xc45d0571U, 0x06d46f04U, 0x5015ff60U, 0x98fb2419U, 0xbde997d6U, + 0x4043cc89U, 0xd99e7767U, 0xe842bdb0U, 0x898b8807U, 0x195b38e7U, + 0xc8eedb79U, 0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U, + 0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU, 0x0efffbfdU, + 0x8538560fU, 0xaed51e3dU, 0x2d392736U, 0x0fd9640aU, 0x5ca62168U, + 0x5b54d19bU, 0x362e3a24U, 0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, + 0x9b919e1bU, 0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU, + 0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U, 0x090d0b0eU, + 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U, 0xf1198557U, 0x75074cafU, + 0x99ddbbeeU, 0x7f60fda3U, 0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, + 0xfb7e345bU, 0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U, + 0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U, 0x4a247d85U, + 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U, 0x9e2f4b1dU, 0xb230f3dcU, + 0x8652ec0dU, 0xc1e3d077U, 0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, + 0xe9642247U, 0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U, + 0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U, 0xf581cfa6U, + 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU, 0x3a9de42cU, 0x78920d50U, + 0x5fcc9b6aU, 0x7e466254U, 0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, + 0xc3aff582U, 0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU, + 0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU, 0x267809cdU, + 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U, 0x956e65e6U, 0xffe67eaaU, + 0xbccf0821U, 0x15e8e6efU, 0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, + 0xb07cd629U, 0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U, + 0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U, 0x04984af1U, + 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U, 0x4dd68d76U, 0xefb04d43U, + 0xaa4d54ccU, 0x9604dfe4U, 0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, + 0x65517f46U, 0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU, + 0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU, 0xd7618c9aU, + 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU, 0xa927eeceU, 0x61c935b7U, + 0x1ce5ede1U, 0x47b13c7aU, 0xd2df599cU, 0xf2733f55U, 0x14ce7918U, + 0xc737bf73U, 0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U, + 0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U, 0x1dc37216U, + 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU, 0xa8017139U, 0x0cb3de08U, + 0xb4e49cd8U, 0x56c19064U, 0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, + 0xb85742d0U, }; + +static const uint8_t Td4[256] = { + 0x52U, 0x09U, 0x6aU, 0xd5U, 0x30U, 0x36U, 0xa5U, 0x38U, 0xbfU, 0x40U, 0xa3U, + 0x9eU, 0x81U, 0xf3U, 0xd7U, 0xfbU, 0x7cU, 0xe3U, 0x39U, 0x82U, 0x9bU, 0x2fU, + 0xffU, 0x87U, 0x34U, 0x8eU, 0x43U, 0x44U, 0xc4U, 0xdeU, 0xe9U, 0xcbU, 0x54U, + 0x7bU, 0x94U, 0x32U, 0xa6U, 0xc2U, 0x23U, 0x3dU, 0xeeU, 0x4cU, 0x95U, 0x0bU, + 0x42U, 0xfaU, 0xc3U, 0x4eU, 0x08U, 0x2eU, 0xa1U, 0x66U, 0x28U, 0xd9U, 0x24U, + 0xb2U, 0x76U, 0x5bU, 0xa2U, 0x49U, 0x6dU, 0x8bU, 0xd1U, 0x25U, 0x72U, 0xf8U, + 0xf6U, 0x64U, 0x86U, 0x68U, 0x98U, 0x16U, 0xd4U, 0xa4U, 0x5cU, 0xccU, 0x5dU, + 0x65U, 0xb6U, 0x92U, 0x6cU, 0x70U, 0x48U, 0x50U, 0xfdU, 0xedU, 0xb9U, 0xdaU, + 0x5eU, 0x15U, 0x46U, 0x57U, 0xa7U, 0x8dU, 0x9dU, 0x84U, 0x90U, 0xd8U, 0xabU, + 0x00U, 0x8cU, 0xbcU, 0xd3U, 0x0aU, 0xf7U, 0xe4U, 0x58U, 0x05U, 0xb8U, 0xb3U, + 0x45U, 0x06U, 0xd0U, 0x2cU, 0x1eU, 0x8fU, 0xcaU, 0x3fU, 0x0fU, 0x02U, 0xc1U, + 0xafU, 0xbdU, 0x03U, 0x01U, 0x13U, 0x8aU, 0x6bU, 0x3aU, 0x91U, 0x11U, 0x41U, + 0x4fU, 0x67U, 0xdcU, 0xeaU, 0x97U, 0xf2U, 0xcfU, 0xceU, 0xf0U, 0xb4U, 0xe6U, + 0x73U, 0x96U, 0xacU, 0x74U, 0x22U, 0xe7U, 0xadU, 0x35U, 0x85U, 0xe2U, 0xf9U, + 0x37U, 0xe8U, 0x1cU, 0x75U, 0xdfU, 0x6eU, 0x47U, 0xf1U, 0x1aU, 0x71U, 0x1dU, + 0x29U, 0xc5U, 0x89U, 0x6fU, 0xb7U, 0x62U, 0x0eU, 0xaaU, 0x18U, 0xbeU, 0x1bU, + 0xfcU, 0x56U, 0x3eU, 0x4bU, 0xc6U, 0xd2U, 0x79U, 0x20U, 0x9aU, 0xdbU, 0xc0U, + 0xfeU, 0x78U, 0xcdU, 0x5aU, 0xf4U, 0x1fU, 0xddU, 0xa8U, 0x33U, 0x88U, 0x07U, + 0xc7U, 0x31U, 0xb1U, 0x12U, 0x10U, 0x59U, 0x27U, 0x80U, 0xecU, 0x5fU, 0x60U, + 0x51U, 0x7fU, 0xa9U, 0x19U, 0xb5U, 0x4aU, 0x0dU, 0x2dU, 0xe5U, 0x7aU, 0x9fU, + 0x93U, 0xc9U, 0x9cU, 0xefU, 0xa0U, 0xe0U, 0x3bU, 0x4dU, 0xaeU, 0x2aU, 0xf5U, + 0xb0U, 0xc8U, 0xebU, 0xbbU, 0x3cU, 0x83U, 0x53U, 0x99U, 0x61U, 0x17U, 0x2bU, + 0x04U, 0x7eU, 0xbaU, 0x77U, 0xd6U, 0x26U, 0xe1U, 0x69U, 0x14U, 0x63U, 0x55U, + 0x21U, 0x0cU, 0x7dU, }; + +static const uint32_t rcon[] = { + 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, + 0x20000000, 0x40000000, 0x80000000, 0x1B000000, 0x36000000, + /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ +}; + +int AES_set_encrypt_key(const uint8_t *key, unsigned bits, AES_KEY *aeskey) { + uint32_t *rk; + int i = 0; + uint32_t temp; + + if (!key || !aeskey) { + return -1; + } + + switch (bits) { + case 128: + aeskey->rounds = 10; + break; + case 192: + aeskey->rounds = 12; + break; + case 256: + aeskey->rounds = 14; + break; + default: + return -2; + } + + rk = aeskey->rd_key; + + rk[0] = GETU32(key); + rk[1] = GETU32(key + 4); + rk[2] = GETU32(key + 8); + rk[3] = GETU32(key + 12); + if (bits == 128) { + while (1) { + temp = rk[3]; + rk[4] = rk[0] ^ (Te2[(temp >> 16) & 0xff] & 0xff000000) ^ + (Te3[(temp >> 8) & 0xff] & 0x00ff0000) ^ + (Te0[(temp) & 0xff] & 0x0000ff00) ^ + (Te1[(temp >> 24)] & 0x000000ff) ^ rcon[i]; + rk[5] = rk[1] ^ rk[4]; + rk[6] = rk[2] ^ rk[5]; + rk[7] = rk[3] ^ rk[6]; + if (++i == 10) { + return 0; + } + rk += 4; + } + } + rk[4] = GETU32(key + 16); + rk[5] = GETU32(key + 20); + if (bits == 192) { + while (1) { + temp = rk[5]; + rk[6] = rk[0] ^ (Te2[(temp >> 16) & 0xff] & 0xff000000) ^ + (Te3[(temp >> 8) & 0xff] & 0x00ff0000) ^ + (Te0[(temp) & 0xff] & 0x0000ff00) ^ + (Te1[(temp >> 24)] & 0x000000ff) ^ rcon[i]; + rk[7] = rk[1] ^ rk[6]; + rk[8] = rk[2] ^ rk[7]; + rk[9] = rk[3] ^ rk[8]; + if (++i == 8) { + return 0; + } + rk[10] = rk[4] ^ rk[9]; + rk[11] = rk[5] ^ rk[10]; + rk += 6; + } + } + rk[6] = GETU32(key + 24); + rk[7] = GETU32(key + 28); + if (bits == 256) { + while (1) { + temp = rk[7]; + rk[8] = rk[0] ^ (Te2[(temp >> 16) & 0xff] & 0xff000000) ^ + (Te3[(temp >> 8) & 0xff] & 0x00ff0000) ^ + (Te0[(temp) & 0xff] & 0x0000ff00) ^ + (Te1[(temp >> 24)] & 0x000000ff) ^ rcon[i]; + rk[9] = rk[1] ^ rk[8]; + rk[10] = rk[2] ^ rk[9]; + rk[11] = rk[3] ^ rk[10]; + if (++i == 7) { + return 0; + } + temp = rk[11]; + rk[12] = rk[4] ^ (Te2[(temp >> 24)] & 0xff000000) ^ + (Te3[(temp >> 16) & 0xff] & 0x00ff0000) ^ + (Te0[(temp >> 8) & 0xff] & 0x0000ff00) ^ + (Te1[(temp) & 0xff] & 0x000000ff); + rk[13] = rk[5] ^ rk[12]; + rk[14] = rk[6] ^ rk[13]; + rk[15] = rk[7] ^ rk[14]; + + rk += 8; + } + } + return 0; +} + +int AES_set_decrypt_key(const uint8_t *key, unsigned bits, AES_KEY *aeskey) { + uint32_t *rk; + int i, j, status; + uint32_t temp; + + /* first, start with an encryption schedule */ + status = AES_set_encrypt_key(key, bits, aeskey); + if (status < 0) { + return status; + } + + rk = aeskey->rd_key; + + /* invert the order of the round keys: */ + for (i = 0, j = 4 * aeskey->rounds; i < j; i += 4, j -= 4) { + temp = rk[i]; + rk[i] = rk[j]; + rk[j] = temp; + temp = rk[i + 1]; + rk[i + 1] = rk[j + 1]; + rk[j + 1] = temp; + temp = rk[i + 2]; + rk[i + 2] = rk[j + 2]; + rk[j + 2] = temp; + temp = rk[i + 3]; + rk[i + 3] = rk[j + 3]; + rk[j + 3] = temp; + } + /* apply the inverse MixColumn transform to all round keys but the first and + * the last: */ + for (i = 1; i < (int)aeskey->rounds; i++) { + rk += 4; + rk[0] = + Td0[Te1[(rk[0] >> 24)] & 0xff] ^ Td1[Te1[(rk[0] >> 16) & 0xff] & 0xff] ^ + Td2[Te1[(rk[0] >> 8) & 0xff] & 0xff] ^ Td3[Te1[(rk[0]) & 0xff] & 0xff]; + rk[1] = + Td0[Te1[(rk[1] >> 24)] & 0xff] ^ Td1[Te1[(rk[1] >> 16) & 0xff] & 0xff] ^ + Td2[Te1[(rk[1] >> 8) & 0xff] & 0xff] ^ Td3[Te1[(rk[1]) & 0xff] & 0xff]; + rk[2] = + Td0[Te1[(rk[2] >> 24)] & 0xff] ^ Td1[Te1[(rk[2] >> 16) & 0xff] & 0xff] ^ + Td2[Te1[(rk[2] >> 8) & 0xff] & 0xff] ^ Td3[Te1[(rk[2]) & 0xff] & 0xff]; + rk[3] = + Td0[Te1[(rk[3] >> 24)] & 0xff] ^ Td1[Te1[(rk[3] >> 16) & 0xff] & 0xff] ^ + Td2[Te1[(rk[3] >> 8) & 0xff] & 0xff] ^ Td3[Te1[(rk[3]) & 0xff] & 0xff]; + } + return 0; +} + +void AES_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) { + const uint32_t *rk; + uint32_t s0, s1, s2, s3, t0, t1, t2, t3; +#ifndef FULL_UNROLL + int r; +#endif /* ?FULL_UNROLL */ + + assert(in && out && key); + rk = key->rd_key; + + /* map byte array block to cipher state + * and add initial round key: */ + s0 = GETU32(in) ^ rk[0]; + s1 = GETU32(in + 4) ^ rk[1]; + s2 = GETU32(in + 8) ^ rk[2]; + s3 = GETU32(in + 12) ^ rk[3]; +#ifdef FULL_UNROLL + /* round 1: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ + Te3[s3 & 0xff] ^ rk[4]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ + Te3[s0 & 0xff] ^ rk[5]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ + Te3[s1 & 0xff] ^ rk[6]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ + Te3[s2 & 0xff] ^ rk[7]; + /* round 2: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ + Te3[t3 & 0xff] ^ rk[8]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ + Te3[t0 & 0xff] ^ rk[9]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ + Te3[t1 & 0xff] ^ rk[10]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ + Te3[t2 & 0xff] ^ rk[11]; + /* round 3: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ + Te3[s3 & 0xff] ^ rk[12]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ + Te3[s0 & 0xff] ^ rk[13]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ + Te3[s1 & 0xff] ^ rk[14]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ + Te3[s2 & 0xff] ^ rk[15]; + /* round 4: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ + Te3[t3 & 0xff] ^ rk[16]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ + Te3[t0 & 0xff] ^ rk[17]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ + Te3[t1 & 0xff] ^ rk[18]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ + Te3[t2 & 0xff] ^ rk[19]; + /* round 5: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ + Te3[s3 & 0xff] ^ rk[20]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ + Te3[s0 & 0xff] ^ rk[21]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ + Te3[s1 & 0xff] ^ rk[22]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ + Te3[s2 & 0xff] ^ rk[23]; + /* round 6: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ + Te3[t3 & 0xff] ^ rk[24]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ + Te3[t0 & 0xff] ^ rk[25]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ + Te3[t1 & 0xff] ^ rk[26]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ + Te3[t2 & 0xff] ^ rk[27]; + /* round 7: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ + Te3[s3 & 0xff] ^ rk[28]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ + Te3[s0 & 0xff] ^ rk[29]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ + Te3[s1 & 0xff] ^ rk[30]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ + Te3[s2 & 0xff] ^ rk[31]; + /* round 8: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ + Te3[t3 & 0xff] ^ rk[32]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ + Te3[t0 & 0xff] ^ rk[33]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ + Te3[t1 & 0xff] ^ rk[34]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ + Te3[t2 & 0xff] ^ rk[35]; + /* round 9: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ + Te3[s3 & 0xff] ^ rk[36]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ + Te3[s0 & 0xff] ^ rk[37]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ + Te3[s1 & 0xff] ^ rk[38]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ + Te3[s2 & 0xff] ^ rk[39]; + if (key->rounds > 10) { + /* round 10: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ + Te3[t3 & 0xff] ^ rk[40]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ + Te3[t0 & 0xff] ^ rk[41]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ + Te3[t1 & 0xff] ^ rk[42]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ + Te3[t2 & 0xff] ^ rk[43]; + /* round 11: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ + Te3[s3 & 0xff] ^ rk[44]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ + Te3[s0 & 0xff] ^ rk[45]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ + Te3[s1 & 0xff] ^ rk[46]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ + Te3[s2 & 0xff] ^ rk[47]; + if (key->rounds > 12) { + /* round 12: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ + Te3[t3 & 0xff] ^ rk[48]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ + Te3[t0 & 0xff] ^ rk[49]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ + Te3[t1 & 0xff] ^ rk[50]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ + Te3[t2 & 0xff] ^ rk[51]; + /* round 13: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ + Te3[s3 & 0xff] ^ rk[52]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ + Te3[s0 & 0xff] ^ rk[53]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ + Te3[s1 & 0xff] ^ rk[54]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ + Te3[s2 & 0xff] ^ rk[55]; + } + } + rk += key->rounds << 2; +#else /* !FULL_UNROLL */ + /* + * Nr - 1 full rounds: + */ + r = key->rounds >> 1; + for (;;) { + t0 = Te0[(s0 >> 24)] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ + Te3[(s3) & 0xff] ^ rk[4]; + t1 = Te0[(s1 >> 24)] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ + Te3[(s0) & 0xff] ^ rk[5]; + t2 = Te0[(s2 >> 24)] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ + Te3[(s1) & 0xff] ^ rk[6]; + t3 = Te0[(s3 >> 24)] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ + Te3[(s2) & 0xff] ^ rk[7]; + + rk += 8; + if (--r == 0) { + break; + } + + s0 = Te0[(t0 >> 24)] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ + Te3[(t3) & 0xff] ^ rk[0]; + s1 = Te0[(t1 >> 24)] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ + Te3[(t0) & 0xff] ^ rk[1]; + s2 = Te0[(t2 >> 24)] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ + Te3[(t1) & 0xff] ^ rk[2]; + s3 = Te0[(t3 >> 24)] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ + Te3[(t2) & 0xff] ^ rk[3]; + } +#endif /* ?FULL_UNROLL */ + /* apply last round and map cipher state to byte array block: */ + s0 = (Te2[(t0 >> 24)] & 0xff000000) ^ (Te3[(t1 >> 16) & 0xff] & 0x00ff0000) ^ + (Te0[(t2 >> 8) & 0xff] & 0x0000ff00) ^ (Te1[(t3) & 0xff] & 0x000000ff) ^ + rk[0]; + PUTU32(out, s0); + s1 = (Te2[(t1 >> 24)] & 0xff000000) ^ (Te3[(t2 >> 16) & 0xff] & 0x00ff0000) ^ + (Te0[(t3 >> 8) & 0xff] & 0x0000ff00) ^ (Te1[(t0) & 0xff] & 0x000000ff) ^ + rk[1]; + PUTU32(out + 4, s1); + s2 = (Te2[(t2 >> 24)] & 0xff000000) ^ (Te3[(t3 >> 16) & 0xff] & 0x00ff0000) ^ + (Te0[(t0 >> 8) & 0xff] & 0x0000ff00) ^ (Te1[(t1) & 0xff] & 0x000000ff) ^ + rk[2]; + PUTU32(out + 8, s2); + s3 = (Te2[(t3 >> 24)] & 0xff000000) ^ (Te3[(t0 >> 16) & 0xff] & 0x00ff0000) ^ + (Te0[(t1 >> 8) & 0xff] & 0x0000ff00) ^ (Te1[(t2) & 0xff] & 0x000000ff) ^ + rk[3]; + PUTU32(out + 12, s3); +} + +void AES_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) { + const uint32_t *rk; + uint32_t s0, s1, s2, s3, t0, t1, t2, t3; +#ifndef FULL_UNROLL + int r; +#endif /* ?FULL_UNROLL */ + + assert(in && out && key); + rk = key->rd_key; + + /* map byte array block to cipher state + * and add initial round key: */ + s0 = GETU32(in) ^ rk[0]; + s1 = GETU32(in + 4) ^ rk[1]; + s2 = GETU32(in + 8) ^ rk[2]; + s3 = GETU32(in + 12) ^ rk[3]; +#ifdef FULL_UNROLL + /* round 1: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ + Td3[s1 & 0xff] ^ rk[4]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ + Td3[s2 & 0xff] ^ rk[5]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ + Td3[s3 & 0xff] ^ rk[6]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ + Td3[s0 & 0xff] ^ rk[7]; + /* round 2: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ + Td3[t1 & 0xff] ^ rk[8]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ + Td3[t2 & 0xff] ^ rk[9]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ + Td3[t3 & 0xff] ^ rk[10]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ + Td3[t0 & 0xff] ^ rk[11]; + /* round 3: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ + Td3[s1 & 0xff] ^ rk[12]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ + Td3[s2 & 0xff] ^ rk[13]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ + Td3[s3 & 0xff] ^ rk[14]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ + Td3[s0 & 0xff] ^ rk[15]; + /* round 4: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ + Td3[t1 & 0xff] ^ rk[16]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ + Td3[t2 & 0xff] ^ rk[17]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ + Td3[t3 & 0xff] ^ rk[18]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ + Td3[t0 & 0xff] ^ rk[19]; + /* round 5: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ + Td3[s1 & 0xff] ^ rk[20]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ + Td3[s2 & 0xff] ^ rk[21]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ + Td3[s3 & 0xff] ^ rk[22]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ + Td3[s0 & 0xff] ^ rk[23]; + /* round 6: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ + Td3[t1 & 0xff] ^ rk[24]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ + Td3[t2 & 0xff] ^ rk[25]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ + Td3[t3 & 0xff] ^ rk[26]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ + Td3[t0 & 0xff] ^ rk[27]; + /* round 7: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ + Td3[s1 & 0xff] ^ rk[28]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ + Td3[s2 & 0xff] ^ rk[29]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ + Td3[s3 & 0xff] ^ rk[30]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ + Td3[s0 & 0xff] ^ rk[31]; + /* round 8: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ + Td3[t1 & 0xff] ^ rk[32]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ + Td3[t2 & 0xff] ^ rk[33]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ + Td3[t3 & 0xff] ^ rk[34]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ + Td3[t0 & 0xff] ^ rk[35]; + /* round 9: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ + Td3[s1 & 0xff] ^ rk[36]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ + Td3[s2 & 0xff] ^ rk[37]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ + Td3[s3 & 0xff] ^ rk[38]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ + Td3[s0 & 0xff] ^ rk[39]; + if (key->rounds > 10) { + /* round 10: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ + Td3[t1 & 0xff] ^ rk[40]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ + Td3[t2 & 0xff] ^ rk[41]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ + Td3[t3 & 0xff] ^ rk[42]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ + Td3[t0 & 0xff] ^ rk[43]; + /* round 11: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ + Td3[s1 & 0xff] ^ rk[44]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ + Td3[s2 & 0xff] ^ rk[45]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ + Td3[s3 & 0xff] ^ rk[46]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ + Td3[s0 & 0xff] ^ rk[47]; + if (key->rounds > 12) { + /* round 12: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ + Td3[t1 & 0xff] ^ rk[48]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ + Td3[t2 & 0xff] ^ rk[49]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ + Td3[t3 & 0xff] ^ rk[50]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ + Td3[t0 & 0xff] ^ rk[51]; + /* round 13: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ + Td3[s1 & 0xff] ^ rk[52]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ + Td3[s2 & 0xff] ^ rk[53]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ + Td3[s3 & 0xff] ^ rk[54]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ + Td3[s0 & 0xff] ^ rk[55]; + } + } + rk += key->rounds << 2; +#else /* !FULL_UNROLL */ + /* + * Nr - 1 full rounds: + */ + r = key->rounds >> 1; + for (;;) { + t0 = Td0[(s0 >> 24)] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ + Td3[(s1) & 0xff] ^ rk[4]; + t1 = Td0[(s1 >> 24)] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ + Td3[(s2) & 0xff] ^ rk[5]; + t2 = Td0[(s2 >> 24)] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ + Td3[(s3) & 0xff] ^ rk[6]; + t3 = Td0[(s3 >> 24)] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ + Td3[(s0) & 0xff] ^ rk[7]; + + rk += 8; + if (--r == 0) { + break; + } + + s0 = Td0[(t0 >> 24)] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ + Td3[(t1) & 0xff] ^ rk[0]; + s1 = Td0[(t1 >> 24)] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ + Td3[(t2) & 0xff] ^ rk[1]; + s2 = Td0[(t2 >> 24)] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ + Td3[(t3) & 0xff] ^ rk[2]; + s3 = Td0[(t3 >> 24)] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ + Td3[(t0) & 0xff] ^ rk[3]; + } +#endif /* ?FULL_UNROLL */ + /* apply last round and + * map cipher state to byte array block: */ + s0 = ((uint32_t)Td4[(t0 >> 24)] << 24) ^ + ((uint32_t)Td4[(t3 >> 16) & 0xff] << 16) ^ + ((uint32_t)Td4[(t2 >> 8) & 0xff] << 8) ^ + ((uint32_t)Td4[(t1) & 0xff]) ^ rk[0]; + PUTU32(out, s0); + s1 = ((uint32_t)Td4[(t1 >> 24)] << 24) ^ + ((uint32_t)Td4[(t0 >> 16) & 0xff] << 16) ^ + ((uint32_t)Td4[(t3 >> 8) & 0xff] << 8) ^ + ((uint32_t)Td4[(t2) & 0xff]) ^ rk[1]; + PUTU32(out + 4, s1); + s2 = ((uint32_t)Td4[(t2 >> 24)] << 24) ^ + ((uint32_t)Td4[(t1 >> 16) & 0xff] << 16) ^ + ((uint32_t)Td4[(t0 >> 8) & 0xff] << 8) ^ + ((uint32_t)Td4[(t3) & 0xff]) ^ rk[2]; + PUTU32(out + 8, s2); + s3 = ((uint32_t)Td4[(t3 >> 24)] << 24) ^ + ((uint32_t)Td4[(t2 >> 16) & 0xff] << 16) ^ + ((uint32_t)Td4[(t1 >> 8) & 0xff] << 8) ^ + ((uint32_t)Td4[(t0) & 0xff]) ^ rk[3]; + PUTU32(out + 12, s3); +} + +#else + +#if defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64) + +static int hwaes_capable(void) { + return CRYPTO_is_ARMv8_AES_capable(); +} + +int aes_v8_set_encrypt_key(const uint8_t *user_key, const int bits, + AES_KEY *key); +int aes_v8_set_decrypt_key(const uint8_t *user_key, const int bits, + AES_KEY *key); +void aes_v8_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key); +void aes_v8_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key); + +#else + +static int hwaes_capable(void) { + return 0; +} + +static int aes_v8_set_encrypt_key(const uint8_t *user_key, int bits, AES_KEY *key) { + abort(); +} + +static int aes_v8_set_decrypt_key(const uint8_t *user_key, int bits, AES_KEY *key) { + abort(); +} + +static void aes_v8_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) { + abort(); +} + +static void aes_v8_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) { + abort(); +} + +#endif + + +/* In this case several functions are provided by asm code. However, one cannot + * control asm symbol visibility with command line flags and such so they are + * always hidden and wrapped by these C functions, which can be so + * controlled. */ + +void asm_AES_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key); +void AES_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) { + if (hwaes_capable()) { + aes_v8_encrypt(in, out, key); + } else { + asm_AES_encrypt(in, out, key); + } +} + +void asm_AES_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key); +void AES_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) { + if (hwaes_capable()) { + aes_v8_decrypt(in, out, key); + } else { + asm_AES_decrypt(in, out, key); + } +} + +int asm_AES_set_encrypt_key(const uint8_t *key, unsigned bits, AES_KEY *aeskey); +int AES_set_encrypt_key(const uint8_t *key, unsigned bits, AES_KEY *aeskey) { + if (hwaes_capable()) { + return aes_v8_set_encrypt_key(key, bits, aeskey); + } else { + return asm_AES_set_encrypt_key(key, bits, aeskey); + } +} + +int asm_AES_set_decrypt_key(const uint8_t *key, unsigned bits, AES_KEY *aeskey); +int AES_set_decrypt_key(const uint8_t *key, unsigned bits, AES_KEY *aeskey) { + if (hwaes_capable()) { + return aes_v8_set_decrypt_key(key, bits, aeskey); + } else { + return asm_AES_set_decrypt_key(key, bits, aeskey); + } +} + +#endif /* OPENSSL_NO_ASM || (!OPENSSL_X86 && !OPENSSL_X86_64 && !OPENSSL_ARM) */ diff --git a/external/boringssl/crypto/aes/aes_test.cc b/external/boringssl/crypto/aes/aes_test.cc new file mode 100644 index 0000000000..e488d81d11 --- /dev/null +++ b/external/boringssl/crypto/aes/aes_test.cc @@ -0,0 +1,102 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include + +#include +#include + + +static bool TestAES(const uint8_t *key, size_t key_len, + const uint8_t plaintext[AES_BLOCK_SIZE], + const uint8_t ciphertext[AES_BLOCK_SIZE]) { + AES_KEY aes_key; + if (AES_set_encrypt_key(key, key_len * 8, &aes_key) != 0) { + fprintf(stderr, "AES_set_encrypt_key failed\n"); + return false; + } + + // Test encryption. + uint8_t block[AES_BLOCK_SIZE]; + AES_encrypt(plaintext, block, &aes_key); + if (memcmp(block, ciphertext, AES_BLOCK_SIZE) != 0) { + fprintf(stderr, "AES_encrypt gave the wrong output\n"); + return false; + } + + // Test in-place encryption. + memcpy(block, plaintext, AES_BLOCK_SIZE); + AES_encrypt(block, block, &aes_key); + if (memcmp(block, ciphertext, AES_BLOCK_SIZE) != 0) { + fprintf(stderr, "AES_encrypt gave the wrong output\n"); + return false; + } + + if (AES_set_decrypt_key(key, key_len * 8, &aes_key) != 0) { + fprintf(stderr, "AES_set_decrypt_key failed\n"); + return false; + } + + // Test decryption. + AES_decrypt(ciphertext, block, &aes_key); + if (memcmp(block, plaintext, AES_BLOCK_SIZE) != 0) { + fprintf(stderr, "AES_decrypt gave the wrong output\n"); + return false; + } + + // Test in-place decryption. + memcpy(block, ciphertext, AES_BLOCK_SIZE); + AES_decrypt(block, block, &aes_key); + if (memcmp(block, plaintext, AES_BLOCK_SIZE) != 0) { + fprintf(stderr, "AES_decrypt gave the wrong output\n"); + return false; + } + return true; +} + +int main() { + CRYPTO_library_init(); + + // Test vectors from FIPS-197, Appendix C. + if (!TestAES((const uint8_t *)"\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + 128 / 8, + (const uint8_t *)"\x00\x11\x22\x33\x44\x55\x66\x77" + "\x88\x99\xaa\xbb\xcc\xdd\xee\xff", + (const uint8_t *)"\x69\xc4\xe0\xd8\x6a\x7b\x04\x30" + "\xd8\xcd\xb7\x80\x70\xb4\xc5\x5a") || + !TestAES((const uint8_t *)"\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17", + 192 / 8, + (const uint8_t *)"\x00\x11\x22\x33\x44\x55\x66\x77" + "\x88\x99\xaa\xbb\xcc\xdd\xee\xff", + (const uint8_t *)"\xdd\xa9\x7c\xa4\x86\x4c\xdf\xe0" + "\x6e\xaf\x70\xa0\xec\x0d\x71\x91") || + !TestAES((const uint8_t *)"\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17" + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", + 256 / 8, + (const uint8_t *)"\x00\x11\x22\x33\x44\x55\x66\x77" + "\x88\x99\xaa\xbb\xcc\xdd\xee\xff", + (const uint8_t *)"\x8e\xa2\xb7\xca\x51\x67\x45\xbf" + "\xea\xfc\x49\x90\x4b\x49\x60\x89")) { + return false; + } + + printf("PASS\n"); + return 0; +} diff --git a/external/boringssl/crypto/aes/asm/aes-586.pl.REMOVED.git-id b/external/boringssl/crypto/aes/asm/aes-586.pl.REMOVED.git-id new file mode 100644 index 0000000000..f65bf1199c --- /dev/null +++ b/external/boringssl/crypto/aes/asm/aes-586.pl.REMOVED.git-id @@ -0,0 +1 @@ +6e8a6a806c460f62e0e156242c5a48e712a3d676 \ No newline at end of file diff --git a/external/boringssl/crypto/aes/asm/aes-armv4.pl b/external/boringssl/crypto/aes/asm/aes-armv4.pl new file mode 100644 index 0000000000..a60ed4cfa0 --- /dev/null +++ b/external/boringssl/crypto/aes/asm/aes-armv4.pl @@ -0,0 +1,1244 @@ +#!/usr/bin/env perl + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== + +# AES for ARMv4 + +# January 2007. +# +# Code uses single 1K S-box and is >2 times faster than code generated +# by gcc-3.4.1. This is thanks to unique feature of ARMv4 ISA, which +# allows to merge logical or arithmetic operation with shift or rotate +# in one instruction and emit combined result every cycle. The module +# is endian-neutral. The performance is ~42 cycles/byte for 128-bit +# key [on single-issue Xscale PXA250 core]. + +# May 2007. +# +# AES_set_[en|de]crypt_key is added. + +# July 2010. +# +# Rescheduling for dual-issue pipeline resulted in 12% improvement on +# Cortex A8 core and ~25 cycles per byte processed with 128-bit key. + +# February 2011. +# +# Profiler-assisted and platform-specific optimization resulted in 16% +# improvement on Cortex A8 core and ~21.5 cycles per byte. + +$flavour = shift; +if ($flavour=~/^\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; } +else { while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {} } + +if ($flavour && $flavour ne "void") { + $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; + ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or + ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or + die "can't locate arm-xlate.pl"; + + open STDOUT,"| \"$^X\" $xlate $flavour $output"; +} else { + open STDOUT,">$output"; +} + +$s0="r0"; +$s1="r1"; +$s2="r2"; +$s3="r3"; +$t1="r4"; +$t2="r5"; +$t3="r6"; +$i1="r7"; +$i2="r8"; +$i3="r9"; + +$tbl="r10"; +$key="r11"; +$rounds="r12"; + +$code=<<___; +#if defined(__arm__) +#ifndef __KERNEL__ +# include +#else +# define __ARM_ARCH__ __LINUX_ARM_ARCH__ +#endif + +.text +#if __ARM_ARCH__<7 +.code 32 +#else +.syntax unified +# if defined(__thumb2__) && !defined(__APPLE__) +.thumb +# else +.code 32 +# endif +#endif + +.type AES_Te,%object +.align 5 +AES_Te: +.word 0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d +.word 0xfff2f20d, 0xd66b6bbd, 0xde6f6fb1, 0x91c5c554 +.word 0x60303050, 0x02010103, 0xce6767a9, 0x562b2b7d +.word 0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a +.word 0x8fcaca45, 0x1f82829d, 0x89c9c940, 0xfa7d7d87 +.word 0xeffafa15, 0xb25959eb, 0x8e4747c9, 0xfbf0f00b +.word 0x41adadec, 0xb3d4d467, 0x5fa2a2fd, 0x45afafea +.word 0x239c9cbf, 0x53a4a4f7, 0xe4727296, 0x9bc0c05b +.word 0x75b7b7c2, 0xe1fdfd1c, 0x3d9393ae, 0x4c26266a +.word 0x6c36365a, 0x7e3f3f41, 0xf5f7f702, 0x83cccc4f +.word 0x6834345c, 0x51a5a5f4, 0xd1e5e534, 0xf9f1f108 +.word 0xe2717193, 0xabd8d873, 0x62313153, 0x2a15153f +.word 0x0804040c, 0x95c7c752, 0x46232365, 0x9dc3c35e +.word 0x30181828, 0x379696a1, 0x0a05050f, 0x2f9a9ab5 +.word 0x0e070709, 0x24121236, 0x1b80809b, 0xdfe2e23d +.word 0xcdebeb26, 0x4e272769, 0x7fb2b2cd, 0xea75759f +.word 0x1209091b, 0x1d83839e, 0x582c2c74, 0x341a1a2e +.word 0x361b1b2d, 0xdc6e6eb2, 0xb45a5aee, 0x5ba0a0fb +.word 0xa45252f6, 0x763b3b4d, 0xb7d6d661, 0x7db3b3ce +.word 0x5229297b, 0xdde3e33e, 0x5e2f2f71, 0x13848497 +.word 0xa65353f5, 0xb9d1d168, 0x00000000, 0xc1eded2c +.word 0x40202060, 0xe3fcfc1f, 0x79b1b1c8, 0xb65b5bed +.word 0xd46a6abe, 0x8dcbcb46, 0x67bebed9, 0x7239394b +.word 0x944a4ade, 0x984c4cd4, 0xb05858e8, 0x85cfcf4a +.word 0xbbd0d06b, 0xc5efef2a, 0x4faaaae5, 0xedfbfb16 +.word 0x864343c5, 0x9a4d4dd7, 0x66333355, 0x11858594 +.word 0x8a4545cf, 0xe9f9f910, 0x04020206, 0xfe7f7f81 +.word 0xa05050f0, 0x783c3c44, 0x259f9fba, 0x4ba8a8e3 +.word 0xa25151f3, 0x5da3a3fe, 0x804040c0, 0x058f8f8a +.word 0x3f9292ad, 0x219d9dbc, 0x70383848, 0xf1f5f504 +.word 0x63bcbcdf, 0x77b6b6c1, 0xafdada75, 0x42212163 +.word 0x20101030, 0xe5ffff1a, 0xfdf3f30e, 0xbfd2d26d +.word 0x81cdcd4c, 0x180c0c14, 0x26131335, 0xc3ecec2f +.word 0xbe5f5fe1, 0x359797a2, 0x884444cc, 0x2e171739 +.word 0x93c4c457, 0x55a7a7f2, 0xfc7e7e82, 0x7a3d3d47 +.word 0xc86464ac, 0xba5d5de7, 0x3219192b, 0xe6737395 +.word 0xc06060a0, 0x19818198, 0x9e4f4fd1, 0xa3dcdc7f +.word 0x44222266, 0x542a2a7e, 0x3b9090ab, 0x0b888883 +.word 0x8c4646ca, 0xc7eeee29, 0x6bb8b8d3, 0x2814143c +.word 0xa7dede79, 0xbc5e5ee2, 0x160b0b1d, 0xaddbdb76 +.word 0xdbe0e03b, 0x64323256, 0x743a3a4e, 0x140a0a1e +.word 0x924949db, 0x0c06060a, 0x4824246c, 0xb85c5ce4 +.word 0x9fc2c25d, 0xbdd3d36e, 0x43acacef, 0xc46262a6 +.word 0x399191a8, 0x319595a4, 0xd3e4e437, 0xf279798b +.word 0xd5e7e732, 0x8bc8c843, 0x6e373759, 0xda6d6db7 +.word 0x018d8d8c, 0xb1d5d564, 0x9c4e4ed2, 0x49a9a9e0 +.word 0xd86c6cb4, 0xac5656fa, 0xf3f4f407, 0xcfeaea25 +.word 0xca6565af, 0xf47a7a8e, 0x47aeaee9, 0x10080818 +.word 0x6fbabad5, 0xf0787888, 0x4a25256f, 0x5c2e2e72 +.word 0x381c1c24, 0x57a6a6f1, 0x73b4b4c7, 0x97c6c651 +.word 0xcbe8e823, 0xa1dddd7c, 0xe874749c, 0x3e1f1f21 +.word 0x964b4bdd, 0x61bdbddc, 0x0d8b8b86, 0x0f8a8a85 +.word 0xe0707090, 0x7c3e3e42, 0x71b5b5c4, 0xcc6666aa +.word 0x904848d8, 0x06030305, 0xf7f6f601, 0x1c0e0e12 +.word 0xc26161a3, 0x6a35355f, 0xae5757f9, 0x69b9b9d0 +.word 0x17868691, 0x99c1c158, 0x3a1d1d27, 0x279e9eb9 +.word 0xd9e1e138, 0xebf8f813, 0x2b9898b3, 0x22111133 +.word 0xd26969bb, 0xa9d9d970, 0x078e8e89, 0x339494a7 +.word 0x2d9b9bb6, 0x3c1e1e22, 0x15878792, 0xc9e9e920 +.word 0x87cece49, 0xaa5555ff, 0x50282878, 0xa5dfdf7a +.word 0x038c8c8f, 0x59a1a1f8, 0x09898980, 0x1a0d0d17 +.word 0x65bfbfda, 0xd7e6e631, 0x844242c6, 0xd06868b8 +.word 0x824141c3, 0x299999b0, 0x5a2d2d77, 0x1e0f0f11 +.word 0x7bb0b0cb, 0xa85454fc, 0x6dbbbbd6, 0x2c16163a +@ Te4[256] +.byte 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5 +.byte 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76 +.byte 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0 +.byte 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0 +.byte 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc +.byte 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15 +.byte 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a +.byte 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75 +.byte 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0 +.byte 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84 +.byte 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b +.byte 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf +.byte 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85 +.byte 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8 +.byte 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5 +.byte 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2 +.byte 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17 +.byte 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73 +.byte 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88 +.byte 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb +.byte 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c +.byte 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79 +.byte 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9 +.byte 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08 +.byte 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6 +.byte 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a +.byte 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e +.byte 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e +.byte 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94 +.byte 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf +.byte 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68 +.byte 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 +@ rcon[] +.word 0x01000000, 0x02000000, 0x04000000, 0x08000000 +.word 0x10000000, 0x20000000, 0x40000000, 0x80000000 +.word 0x1B000000, 0x36000000, 0, 0, 0, 0, 0, 0 +.size AES_Te,.-AES_Te + +@ void asm_AES_encrypt(const unsigned char *in, unsigned char *out, +@ const AES_KEY *key) { +.global asm_AES_encrypt +.type asm_AES_encrypt,%function +.align 5 +asm_AES_encrypt: +#if __ARM_ARCH__<7 + sub r3,pc,#8 @ asm_AES_encrypt +#else + adr r3,asm_AES_encrypt +#endif + stmdb sp!,{r1,r4-r12,lr} +#ifdef __APPLE__ + adr $tbl,AES_Te +#else + sub $tbl,r3,#asm_AES_encrypt-AES_Te @ Te +#endif + mov $rounds,r0 @ inp + mov $key,r2 +#if __ARM_ARCH__<7 + ldrb $s0,[$rounds,#3] @ load input data in endian-neutral + ldrb $t1,[$rounds,#2] @ manner... + ldrb $t2,[$rounds,#1] + ldrb $t3,[$rounds,#0] + orr $s0,$s0,$t1,lsl#8 + ldrb $s1,[$rounds,#7] + orr $s0,$s0,$t2,lsl#16 + ldrb $t1,[$rounds,#6] + orr $s0,$s0,$t3,lsl#24 + ldrb $t2,[$rounds,#5] + ldrb $t3,[$rounds,#4] + orr $s1,$s1,$t1,lsl#8 + ldrb $s2,[$rounds,#11] + orr $s1,$s1,$t2,lsl#16 + ldrb $t1,[$rounds,#10] + orr $s1,$s1,$t3,lsl#24 + ldrb $t2,[$rounds,#9] + ldrb $t3,[$rounds,#8] + orr $s2,$s2,$t1,lsl#8 + ldrb $s3,[$rounds,#15] + orr $s2,$s2,$t2,lsl#16 + ldrb $t1,[$rounds,#14] + orr $s2,$s2,$t3,lsl#24 + ldrb $t2,[$rounds,#13] + ldrb $t3,[$rounds,#12] + orr $s3,$s3,$t1,lsl#8 + orr $s3,$s3,$t2,lsl#16 + orr $s3,$s3,$t3,lsl#24 +#else + ldr $s0,[$rounds,#0] + ldr $s1,[$rounds,#4] + ldr $s2,[$rounds,#8] + ldr $s3,[$rounds,#12] +#ifdef __ARMEL__ + rev $s0,$s0 + rev $s1,$s1 + rev $s2,$s2 + rev $s3,$s3 +#endif +#endif + bl _armv4_AES_encrypt + + ldr $rounds,[sp],#4 @ pop out +#if __ARM_ARCH__>=7 +#ifdef __ARMEL__ + rev $s0,$s0 + rev $s1,$s1 + rev $s2,$s2 + rev $s3,$s3 +#endif + str $s0,[$rounds,#0] + str $s1,[$rounds,#4] + str $s2,[$rounds,#8] + str $s3,[$rounds,#12] +#else + mov $t1,$s0,lsr#24 @ write output in endian-neutral + mov $t2,$s0,lsr#16 @ manner... + mov $t3,$s0,lsr#8 + strb $t1,[$rounds,#0] + strb $t2,[$rounds,#1] + mov $t1,$s1,lsr#24 + strb $t3,[$rounds,#2] + mov $t2,$s1,lsr#16 + strb $s0,[$rounds,#3] + mov $t3,$s1,lsr#8 + strb $t1,[$rounds,#4] + strb $t2,[$rounds,#5] + mov $t1,$s2,lsr#24 + strb $t3,[$rounds,#6] + mov $t2,$s2,lsr#16 + strb $s1,[$rounds,#7] + mov $t3,$s2,lsr#8 + strb $t1,[$rounds,#8] + strb $t2,[$rounds,#9] + mov $t1,$s3,lsr#24 + strb $t3,[$rounds,#10] + mov $t2,$s3,lsr#16 + strb $s2,[$rounds,#11] + mov $t3,$s3,lsr#8 + strb $t1,[$rounds,#12] + strb $t2,[$rounds,#13] + strb $t3,[$rounds,#14] + strb $s3,[$rounds,#15] +#endif +#if __ARM_ARCH__>=5 + ldmia sp!,{r4-r12,pc} +#else + ldmia sp!,{r4-r12,lr} + tst lr,#1 + moveq pc,lr @ be binary compatible with V4, yet + bx lr @ interoperable with Thumb ISA:-) +#endif +.size asm_AES_encrypt,.-asm_AES_encrypt + +.type _armv4_AES_encrypt,%function +.align 2 +_armv4_AES_encrypt: + str lr,[sp,#-4]! @ push lr + ldmia $key!,{$t1-$i1} + eor $s0,$s0,$t1 + ldr $rounds,[$key,#240-16] + eor $s1,$s1,$t2 + eor $s2,$s2,$t3 + eor $s3,$s3,$i1 + sub $rounds,$rounds,#1 + mov lr,#255 + + and $i1,lr,$s0 + and $i2,lr,$s0,lsr#8 + and $i3,lr,$s0,lsr#16 + mov $s0,$s0,lsr#24 +.Lenc_loop: + ldr $t1,[$tbl,$i1,lsl#2] @ Te3[s0>>0] + and $i1,lr,$s1,lsr#16 @ i0 + ldr $t2,[$tbl,$i2,lsl#2] @ Te2[s0>>8] + and $i2,lr,$s1 + ldr $t3,[$tbl,$i3,lsl#2] @ Te1[s0>>16] + and $i3,lr,$s1,lsr#8 + ldr $s0,[$tbl,$s0,lsl#2] @ Te0[s0>>24] + mov $s1,$s1,lsr#24 + + ldr $i1,[$tbl,$i1,lsl#2] @ Te1[s1>>16] + ldr $i2,[$tbl,$i2,lsl#2] @ Te3[s1>>0] + ldr $i3,[$tbl,$i3,lsl#2] @ Te2[s1>>8] + eor $s0,$s0,$i1,ror#8 + ldr $s1,[$tbl,$s1,lsl#2] @ Te0[s1>>24] + and $i1,lr,$s2,lsr#8 @ i0 + eor $t2,$t2,$i2,ror#8 + and $i2,lr,$s2,lsr#16 @ i1 + eor $t3,$t3,$i3,ror#8 + and $i3,lr,$s2 + ldr $i1,[$tbl,$i1,lsl#2] @ Te2[s2>>8] + eor $s1,$s1,$t1,ror#24 + ldr $i2,[$tbl,$i2,lsl#2] @ Te1[s2>>16] + mov $s2,$s2,lsr#24 + + ldr $i3,[$tbl,$i3,lsl#2] @ Te3[s2>>0] + eor $s0,$s0,$i1,ror#16 + ldr $s2,[$tbl,$s2,lsl#2] @ Te0[s2>>24] + and $i1,lr,$s3 @ i0 + eor $s1,$s1,$i2,ror#8 + and $i2,lr,$s3,lsr#8 @ i1 + eor $t3,$t3,$i3,ror#16 + and $i3,lr,$s3,lsr#16 @ i2 + ldr $i1,[$tbl,$i1,lsl#2] @ Te3[s3>>0] + eor $s2,$s2,$t2,ror#16 + ldr $i2,[$tbl,$i2,lsl#2] @ Te2[s3>>8] + mov $s3,$s3,lsr#24 + + ldr $i3,[$tbl,$i3,lsl#2] @ Te1[s3>>16] + eor $s0,$s0,$i1,ror#24 + ldr $i1,[$key],#16 + eor $s1,$s1,$i2,ror#16 + ldr $s3,[$tbl,$s3,lsl#2] @ Te0[s3>>24] + eor $s2,$s2,$i3,ror#8 + ldr $t1,[$key,#-12] + eor $s3,$s3,$t3,ror#8 + + ldr $t2,[$key,#-8] + eor $s0,$s0,$i1 + ldr $t3,[$key,#-4] + and $i1,lr,$s0 + eor $s1,$s1,$t1 + and $i2,lr,$s0,lsr#8 + eor $s2,$s2,$t2 + and $i3,lr,$s0,lsr#16 + eor $s3,$s3,$t3 + mov $s0,$s0,lsr#24 + + subs $rounds,$rounds,#1 + bne .Lenc_loop + + add $tbl,$tbl,#2 + + ldrb $t1,[$tbl,$i1,lsl#2] @ Te4[s0>>0] + and $i1,lr,$s1,lsr#16 @ i0 + ldrb $t2,[$tbl,$i2,lsl#2] @ Te4[s0>>8] + and $i2,lr,$s1 + ldrb $t3,[$tbl,$i3,lsl#2] @ Te4[s0>>16] + and $i3,lr,$s1,lsr#8 + ldrb $s0,[$tbl,$s0,lsl#2] @ Te4[s0>>24] + mov $s1,$s1,lsr#24 + + ldrb $i1,[$tbl,$i1,lsl#2] @ Te4[s1>>16] + ldrb $i2,[$tbl,$i2,lsl#2] @ Te4[s1>>0] + ldrb $i3,[$tbl,$i3,lsl#2] @ Te4[s1>>8] + eor $s0,$i1,$s0,lsl#8 + ldrb $s1,[$tbl,$s1,lsl#2] @ Te4[s1>>24] + and $i1,lr,$s2,lsr#8 @ i0 + eor $t2,$i2,$t2,lsl#8 + and $i2,lr,$s2,lsr#16 @ i1 + eor $t3,$i3,$t3,lsl#8 + and $i3,lr,$s2 + ldrb $i1,[$tbl,$i1,lsl#2] @ Te4[s2>>8] + eor $s1,$t1,$s1,lsl#24 + ldrb $i2,[$tbl,$i2,lsl#2] @ Te4[s2>>16] + mov $s2,$s2,lsr#24 + + ldrb $i3,[$tbl,$i3,lsl#2] @ Te4[s2>>0] + eor $s0,$i1,$s0,lsl#8 + ldrb $s2,[$tbl,$s2,lsl#2] @ Te4[s2>>24] + and $i1,lr,$s3 @ i0 + eor $s1,$s1,$i2,lsl#16 + and $i2,lr,$s3,lsr#8 @ i1 + eor $t3,$i3,$t3,lsl#8 + and $i3,lr,$s3,lsr#16 @ i2 + ldrb $i1,[$tbl,$i1,lsl#2] @ Te4[s3>>0] + eor $s2,$t2,$s2,lsl#24 + ldrb $i2,[$tbl,$i2,lsl#2] @ Te4[s3>>8] + mov $s3,$s3,lsr#24 + + ldrb $i3,[$tbl,$i3,lsl#2] @ Te4[s3>>16] + eor $s0,$i1,$s0,lsl#8 + ldr $i1,[$key,#0] + ldrb $s3,[$tbl,$s3,lsl#2] @ Te4[s3>>24] + eor $s1,$s1,$i2,lsl#8 + ldr $t1,[$key,#4] + eor $s2,$s2,$i3,lsl#16 + ldr $t2,[$key,#8] + eor $s3,$t3,$s3,lsl#24 + ldr $t3,[$key,#12] + + eor $s0,$s0,$i1 + eor $s1,$s1,$t1 + eor $s2,$s2,$t2 + eor $s3,$s3,$t3 + + sub $tbl,$tbl,#2 + ldr pc,[sp],#4 @ pop and return +.size _armv4_AES_encrypt,.-_armv4_AES_encrypt + +.global asm_AES_set_encrypt_key +.type asm_AES_set_encrypt_key,%function +.align 5 +asm_AES_set_encrypt_key: +_armv4_AES_set_encrypt_key: +#if __ARM_ARCH__<7 + sub r3,pc,#8 @ asm_AES_set_encrypt_key +#else + adr r3,asm_AES_set_encrypt_key +#endif + teq r0,#0 +#if __ARM_ARCH__>=7 + itt eq @ Thumb2 thing, sanity check in ARM +#endif + moveq r0,#-1 + beq .Labrt + teq r2,#0 +#if __ARM_ARCH__>=7 + itt eq @ Thumb2 thing, sanity check in ARM +#endif + moveq r0,#-1 + beq .Labrt + + teq r1,#128 + beq .Lok + teq r1,#192 + beq .Lok + teq r1,#256 +#if __ARM_ARCH__>=7 + itt ne @ Thumb2 thing, sanity check in ARM +#endif + movne r0,#-1 + bne .Labrt + +.Lok: stmdb sp!,{r4-r12,lr} + mov $rounds,r0 @ inp + mov lr,r1 @ bits + mov $key,r2 @ key + +#ifdef __APPLE__ + adr $tbl,AES_Te+1024 @ Te4 +#else + sub $tbl,r3,#_armv4_AES_set_encrypt_key-AES_Te-1024 @ Te4 +#endif + +#if __ARM_ARCH__<7 + ldrb $s0,[$rounds,#3] @ load input data in endian-neutral + ldrb $t1,[$rounds,#2] @ manner... + ldrb $t2,[$rounds,#1] + ldrb $t3,[$rounds,#0] + orr $s0,$s0,$t1,lsl#8 + ldrb $s1,[$rounds,#7] + orr $s0,$s0,$t2,lsl#16 + ldrb $t1,[$rounds,#6] + orr $s0,$s0,$t3,lsl#24 + ldrb $t2,[$rounds,#5] + ldrb $t3,[$rounds,#4] + orr $s1,$s1,$t1,lsl#8 + ldrb $s2,[$rounds,#11] + orr $s1,$s1,$t2,lsl#16 + ldrb $t1,[$rounds,#10] + orr $s1,$s1,$t3,lsl#24 + ldrb $t2,[$rounds,#9] + ldrb $t3,[$rounds,#8] + orr $s2,$s2,$t1,lsl#8 + ldrb $s3,[$rounds,#15] + orr $s2,$s2,$t2,lsl#16 + ldrb $t1,[$rounds,#14] + orr $s2,$s2,$t3,lsl#24 + ldrb $t2,[$rounds,#13] + ldrb $t3,[$rounds,#12] + orr $s3,$s3,$t1,lsl#8 + str $s0,[$key],#16 + orr $s3,$s3,$t2,lsl#16 + str $s1,[$key,#-12] + orr $s3,$s3,$t3,lsl#24 + str $s2,[$key,#-8] + str $s3,[$key,#-4] +#else + ldr $s0,[$rounds,#0] + ldr $s1,[$rounds,#4] + ldr $s2,[$rounds,#8] + ldr $s3,[$rounds,#12] +#ifdef __ARMEL__ + rev $s0,$s0 + rev $s1,$s1 + rev $s2,$s2 + rev $s3,$s3 +#endif + str $s0,[$key],#16 + str $s1,[$key,#-12] + str $s2,[$key,#-8] + str $s3,[$key,#-4] +#endif + + teq lr,#128 + bne .Lnot128 + mov $rounds,#10 + str $rounds,[$key,#240-16] + add $t3,$tbl,#256 @ rcon + mov lr,#255 + +.L128_loop: + and $t2,lr,$s3,lsr#24 + and $i1,lr,$s3,lsr#16 + ldrb $t2,[$tbl,$t2] + and $i2,lr,$s3,lsr#8 + ldrb $i1,[$tbl,$i1] + and $i3,lr,$s3 + ldrb $i2,[$tbl,$i2] + orr $t2,$t2,$i1,lsl#24 + ldrb $i3,[$tbl,$i3] + orr $t2,$t2,$i2,lsl#16 + ldr $t1,[$t3],#4 @ rcon[i++] + orr $t2,$t2,$i3,lsl#8 + eor $t2,$t2,$t1 + eor $s0,$s0,$t2 @ rk[4]=rk[0]^... + eor $s1,$s1,$s0 @ rk[5]=rk[1]^rk[4] + str $s0,[$key],#16 + eor $s2,$s2,$s1 @ rk[6]=rk[2]^rk[5] + str $s1,[$key,#-12] + eor $s3,$s3,$s2 @ rk[7]=rk[3]^rk[6] + str $s2,[$key,#-8] + subs $rounds,$rounds,#1 + str $s3,[$key,#-4] + bne .L128_loop + sub r2,$key,#176 + b .Ldone + +.Lnot128: +#if __ARM_ARCH__<7 + ldrb $i2,[$rounds,#19] + ldrb $t1,[$rounds,#18] + ldrb $t2,[$rounds,#17] + ldrb $t3,[$rounds,#16] + orr $i2,$i2,$t1,lsl#8 + ldrb $i3,[$rounds,#23] + orr $i2,$i2,$t2,lsl#16 + ldrb $t1,[$rounds,#22] + orr $i2,$i2,$t3,lsl#24 + ldrb $t2,[$rounds,#21] + ldrb $t3,[$rounds,#20] + orr $i3,$i3,$t1,lsl#8 + orr $i3,$i3,$t2,lsl#16 + str $i2,[$key],#8 + orr $i3,$i3,$t3,lsl#24 + str $i3,[$key,#-4] +#else + ldr $i2,[$rounds,#16] + ldr $i3,[$rounds,#20] +#ifdef __ARMEL__ + rev $i2,$i2 + rev $i3,$i3 +#endif + str $i2,[$key],#8 + str $i3,[$key,#-4] +#endif + + teq lr,#192 + bne .Lnot192 + mov $rounds,#12 + str $rounds,[$key,#240-24] + add $t3,$tbl,#256 @ rcon + mov lr,#255 + mov $rounds,#8 + +.L192_loop: + and $t2,lr,$i3,lsr#24 + and $i1,lr,$i3,lsr#16 + ldrb $t2,[$tbl,$t2] + and $i2,lr,$i3,lsr#8 + ldrb $i1,[$tbl,$i1] + and $i3,lr,$i3 + ldrb $i2,[$tbl,$i2] + orr $t2,$t2,$i1,lsl#24 + ldrb $i3,[$tbl,$i3] + orr $t2,$t2,$i2,lsl#16 + ldr $t1,[$t3],#4 @ rcon[i++] + orr $t2,$t2,$i3,lsl#8 + eor $i3,$t2,$t1 + eor $s0,$s0,$i3 @ rk[6]=rk[0]^... + eor $s1,$s1,$s0 @ rk[7]=rk[1]^rk[6] + str $s0,[$key],#24 + eor $s2,$s2,$s1 @ rk[8]=rk[2]^rk[7] + str $s1,[$key,#-20] + eor $s3,$s3,$s2 @ rk[9]=rk[3]^rk[8] + str $s2,[$key,#-16] + subs $rounds,$rounds,#1 + str $s3,[$key,#-12] +#if __ARM_ARCH__>=7 + itt eq @ Thumb2 thing, sanity check in ARM +#endif + subeq r2,$key,#216 + beq .Ldone + + ldr $i1,[$key,#-32] + ldr $i2,[$key,#-28] + eor $i1,$i1,$s3 @ rk[10]=rk[4]^rk[9] + eor $i3,$i2,$i1 @ rk[11]=rk[5]^rk[10] + str $i1,[$key,#-8] + str $i3,[$key,#-4] + b .L192_loop + +.Lnot192: +#if __ARM_ARCH__<7 + ldrb $i2,[$rounds,#27] + ldrb $t1,[$rounds,#26] + ldrb $t2,[$rounds,#25] + ldrb $t3,[$rounds,#24] + orr $i2,$i2,$t1,lsl#8 + ldrb $i3,[$rounds,#31] + orr $i2,$i2,$t2,lsl#16 + ldrb $t1,[$rounds,#30] + orr $i2,$i2,$t3,lsl#24 + ldrb $t2,[$rounds,#29] + ldrb $t3,[$rounds,#28] + orr $i3,$i3,$t1,lsl#8 + orr $i3,$i3,$t2,lsl#16 + str $i2,[$key],#8 + orr $i3,$i3,$t3,lsl#24 + str $i3,[$key,#-4] +#else + ldr $i2,[$rounds,#24] + ldr $i3,[$rounds,#28] +#ifdef __ARMEL__ + rev $i2,$i2 + rev $i3,$i3 +#endif + str $i2,[$key],#8 + str $i3,[$key,#-4] +#endif + + mov $rounds,#14 + str $rounds,[$key,#240-32] + add $t3,$tbl,#256 @ rcon + mov lr,#255 + mov $rounds,#7 + +.L256_loop: + and $t2,lr,$i3,lsr#24 + and $i1,lr,$i3,lsr#16 + ldrb $t2,[$tbl,$t2] + and $i2,lr,$i3,lsr#8 + ldrb $i1,[$tbl,$i1] + and $i3,lr,$i3 + ldrb $i2,[$tbl,$i2] + orr $t2,$t2,$i1,lsl#24 + ldrb $i3,[$tbl,$i3] + orr $t2,$t2,$i2,lsl#16 + ldr $t1,[$t3],#4 @ rcon[i++] + orr $t2,$t2,$i3,lsl#8 + eor $i3,$t2,$t1 + eor $s0,$s0,$i3 @ rk[8]=rk[0]^... + eor $s1,$s1,$s0 @ rk[9]=rk[1]^rk[8] + str $s0,[$key],#32 + eor $s2,$s2,$s1 @ rk[10]=rk[2]^rk[9] + str $s1,[$key,#-28] + eor $s3,$s3,$s2 @ rk[11]=rk[3]^rk[10] + str $s2,[$key,#-24] + subs $rounds,$rounds,#1 + str $s3,[$key,#-20] +#if __ARM_ARCH__>=7 + itt eq @ Thumb2 thing, sanity check in ARM +#endif + subeq r2,$key,#256 + beq .Ldone + + and $t2,lr,$s3 + and $i1,lr,$s3,lsr#8 + ldrb $t2,[$tbl,$t2] + and $i2,lr,$s3,lsr#16 + ldrb $i1,[$tbl,$i1] + and $i3,lr,$s3,lsr#24 + ldrb $i2,[$tbl,$i2] + orr $t2,$t2,$i1,lsl#8 + ldrb $i3,[$tbl,$i3] + orr $t2,$t2,$i2,lsl#16 + ldr $t1,[$key,#-48] + orr $t2,$t2,$i3,lsl#24 + + ldr $i1,[$key,#-44] + ldr $i2,[$key,#-40] + eor $t1,$t1,$t2 @ rk[12]=rk[4]^... + ldr $i3,[$key,#-36] + eor $i1,$i1,$t1 @ rk[13]=rk[5]^rk[12] + str $t1,[$key,#-16] + eor $i2,$i2,$i1 @ rk[14]=rk[6]^rk[13] + str $i1,[$key,#-12] + eor $i3,$i3,$i2 @ rk[15]=rk[7]^rk[14] + str $i2,[$key,#-8] + str $i3,[$key,#-4] + b .L256_loop + +.align 2 +.Ldone: mov r0,#0 + ldmia sp!,{r4-r12,lr} +.Labrt: +#if __ARM_ARCH__>=5 + ret @ bx lr +#else + tst lr,#1 + moveq pc,lr @ be binary compatible with V4, yet + bx lr @ interoperable with Thumb ISA:-) +#endif +.size asm_AES_set_encrypt_key,.-asm_AES_set_encrypt_key + +.global asm_AES_set_decrypt_key +.type asm_AES_set_decrypt_key,%function +.align 5 +asm_AES_set_decrypt_key: + str lr,[sp,#-4]! @ push lr + bl _armv4_AES_set_encrypt_key + teq r0,#0 + ldr lr,[sp],#4 @ pop lr + bne .Labrt + + mov r0,r2 @ asm_AES_set_encrypt_key preserves r2, + mov r1,r2 @ which is AES_KEY *key + b _armv4_AES_set_enc2dec_key +.size asm_AES_set_decrypt_key,.-asm_AES_set_decrypt_key + +@ void AES_set_enc2dec_key(const AES_KEY *inp,AES_KEY *out) +.global AES_set_enc2dec_key +.type AES_set_enc2dec_key,%function +.align 5 +AES_set_enc2dec_key: +_armv4_AES_set_enc2dec_key: + stmdb sp!,{r4-r12,lr} + + ldr $rounds,[r0,#240] + mov $i1,r0 @ input + add $i2,r0,$rounds,lsl#4 + mov $key,r1 @ ouput + add $tbl,r1,$rounds,lsl#4 + str $rounds,[r1,#240] + +.Linv: ldr $s0,[$i1],#16 + ldr $s1,[$i1,#-12] + ldr $s2,[$i1,#-8] + ldr $s3,[$i1,#-4] + ldr $t1,[$i2],#-16 + ldr $t2,[$i2,#16+4] + ldr $t3,[$i2,#16+8] + ldr $i3,[$i2,#16+12] + str $s0,[$tbl],#-16 + str $s1,[$tbl,#16+4] + str $s2,[$tbl,#16+8] + str $s3,[$tbl,#16+12] + str $t1,[$key],#16 + str $t2,[$key,#-12] + str $t3,[$key,#-8] + str $i3,[$key,#-4] + teq $i1,$i2 + bne .Linv + + ldr $s0,[$i1] + ldr $s1,[$i1,#4] + ldr $s2,[$i1,#8] + ldr $s3,[$i1,#12] + str $s0,[$key] + str $s1,[$key,#4] + str $s2,[$key,#8] + str $s3,[$key,#12] + sub $key,$key,$rounds,lsl#3 +___ +$mask80=$i1; +$mask1b=$i2; +$mask7f=$i3; +$code.=<<___; + ldr $s0,[$key,#16]! @ prefetch tp1 + mov $mask80,#0x80 + mov $mask1b,#0x1b + orr $mask80,$mask80,#0x8000 + orr $mask1b,$mask1b,#0x1b00 + orr $mask80,$mask80,$mask80,lsl#16 + orr $mask1b,$mask1b,$mask1b,lsl#16 + sub $rounds,$rounds,#1 + mvn $mask7f,$mask80 + mov $rounds,$rounds,lsl#2 @ (rounds-1)*4 + +.Lmix: and $t1,$s0,$mask80 + and $s1,$s0,$mask7f + sub $t1,$t1,$t1,lsr#7 + and $t1,$t1,$mask1b + eor $s1,$t1,$s1,lsl#1 @ tp2 + + and $t1,$s1,$mask80 + and $s2,$s1,$mask7f + sub $t1,$t1,$t1,lsr#7 + and $t1,$t1,$mask1b + eor $s2,$t1,$s2,lsl#1 @ tp4 + + and $t1,$s2,$mask80 + and $s3,$s2,$mask7f + sub $t1,$t1,$t1,lsr#7 + and $t1,$t1,$mask1b + eor $s3,$t1,$s3,lsl#1 @ tp8 + + eor $t1,$s1,$s2 + eor $t2,$s0,$s3 @ tp9 + eor $t1,$t1,$s3 @ tpe + eor $t1,$t1,$s1,ror#24 + eor $t1,$t1,$t2,ror#24 @ ^= ROTATE(tpb=tp9^tp2,8) + eor $t1,$t1,$s2,ror#16 + eor $t1,$t1,$t2,ror#16 @ ^= ROTATE(tpd=tp9^tp4,16) + eor $t1,$t1,$t2,ror#8 @ ^= ROTATE(tp9,24) + + ldr $s0,[$key,#4] @ prefetch tp1 + str $t1,[$key],#4 + subs $rounds,$rounds,#1 + bne .Lmix + + mov r0,#0 +#if __ARM_ARCH__>=5 + ldmia sp!,{r4-r12,pc} +#else + ldmia sp!,{r4-r12,lr} + tst lr,#1 + moveq pc,lr @ be binary compatible with V4, yet + bx lr @ interoperable with Thumb ISA:-) +#endif +.size AES_set_enc2dec_key,.-AES_set_enc2dec_key + +.type AES_Td,%object +.align 5 +AES_Td: +.word 0x51f4a750, 0x7e416553, 0x1a17a4c3, 0x3a275e96 +.word 0x3bab6bcb, 0x1f9d45f1, 0xacfa58ab, 0x4be30393 +.word 0x2030fa55, 0xad766df6, 0x88cc7691, 0xf5024c25 +.word 0x4fe5d7fc, 0xc52acbd7, 0x26354480, 0xb562a38f +.word 0xdeb15a49, 0x25ba1b67, 0x45ea0e98, 0x5dfec0e1 +.word 0xc32f7502, 0x814cf012, 0x8d4697a3, 0x6bd3f9c6 +.word 0x038f5fe7, 0x15929c95, 0xbf6d7aeb, 0x955259da +.word 0xd4be832d, 0x587421d3, 0x49e06929, 0x8ec9c844 +.word 0x75c2896a, 0xf48e7978, 0x99583e6b, 0x27b971dd +.word 0xbee14fb6, 0xf088ad17, 0xc920ac66, 0x7dce3ab4 +.word 0x63df4a18, 0xe51a3182, 0x97513360, 0x62537f45 +.word 0xb16477e0, 0xbb6bae84, 0xfe81a01c, 0xf9082b94 +.word 0x70486858, 0x8f45fd19, 0x94de6c87, 0x527bf8b7 +.word 0xab73d323, 0x724b02e2, 0xe31f8f57, 0x6655ab2a +.word 0xb2eb2807, 0x2fb5c203, 0x86c57b9a, 0xd33708a5 +.word 0x302887f2, 0x23bfa5b2, 0x02036aba, 0xed16825c +.word 0x8acf1c2b, 0xa779b492, 0xf307f2f0, 0x4e69e2a1 +.word 0x65daf4cd, 0x0605bed5, 0xd134621f, 0xc4a6fe8a +.word 0x342e539d, 0xa2f355a0, 0x058ae132, 0xa4f6eb75 +.word 0x0b83ec39, 0x4060efaa, 0x5e719f06, 0xbd6e1051 +.word 0x3e218af9, 0x96dd063d, 0xdd3e05ae, 0x4de6bd46 +.word 0x91548db5, 0x71c45d05, 0x0406d46f, 0x605015ff +.word 0x1998fb24, 0xd6bde997, 0x894043cc, 0x67d99e77 +.word 0xb0e842bd, 0x07898b88, 0xe7195b38, 0x79c8eedb +.word 0xa17c0a47, 0x7c420fe9, 0xf8841ec9, 0x00000000 +.word 0x09808683, 0x322bed48, 0x1e1170ac, 0x6c5a724e +.word 0xfd0efffb, 0x0f853856, 0x3daed51e, 0x362d3927 +.word 0x0a0fd964, 0x685ca621, 0x9b5b54d1, 0x24362e3a +.word 0x0c0a67b1, 0x9357e70f, 0xb4ee96d2, 0x1b9b919e +.word 0x80c0c54f, 0x61dc20a2, 0x5a774b69, 0x1c121a16 +.word 0xe293ba0a, 0xc0a02ae5, 0x3c22e043, 0x121b171d +.word 0x0e090d0b, 0xf28bc7ad, 0x2db6a8b9, 0x141ea9c8 +.word 0x57f11985, 0xaf75074c, 0xee99ddbb, 0xa37f60fd +.word 0xf701269f, 0x5c72f5bc, 0x44663bc5, 0x5bfb7e34 +.word 0x8b432976, 0xcb23c6dc, 0xb6edfc68, 0xb8e4f163 +.word 0xd731dcca, 0x42638510, 0x13972240, 0x84c61120 +.word 0x854a247d, 0xd2bb3df8, 0xaef93211, 0xc729a16d +.word 0x1d9e2f4b, 0xdcb230f3, 0x0d8652ec, 0x77c1e3d0 +.word 0x2bb3166c, 0xa970b999, 0x119448fa, 0x47e96422 +.word 0xa8fc8cc4, 0xa0f03f1a, 0x567d2cd8, 0x223390ef +.word 0x87494ec7, 0xd938d1c1, 0x8ccaa2fe, 0x98d40b36 +.word 0xa6f581cf, 0xa57ade28, 0xdab78e26, 0x3fadbfa4 +.word 0x2c3a9de4, 0x5078920d, 0x6a5fcc9b, 0x547e4662 +.word 0xf68d13c2, 0x90d8b8e8, 0x2e39f75e, 0x82c3aff5 +.word 0x9f5d80be, 0x69d0937c, 0x6fd52da9, 0xcf2512b3 +.word 0xc8ac993b, 0x10187da7, 0xe89c636e, 0xdb3bbb7b +.word 0xcd267809, 0x6e5918f4, 0xec9ab701, 0x834f9aa8 +.word 0xe6956e65, 0xaaffe67e, 0x21bccf08, 0xef15e8e6 +.word 0xbae79bd9, 0x4a6f36ce, 0xea9f09d4, 0x29b07cd6 +.word 0x31a4b2af, 0x2a3f2331, 0xc6a59430, 0x35a266c0 +.word 0x744ebc37, 0xfc82caa6, 0xe090d0b0, 0x33a7d815 +.word 0xf104984a, 0x41ecdaf7, 0x7fcd500e, 0x1791f62f +.word 0x764dd68d, 0x43efb04d, 0xccaa4d54, 0xe49604df +.word 0x9ed1b5e3, 0x4c6a881b, 0xc12c1fb8, 0x4665517f +.word 0x9d5eea04, 0x018c355d, 0xfa877473, 0xfb0b412e +.word 0xb3671d5a, 0x92dbd252, 0xe9105633, 0x6dd64713 +.word 0x9ad7618c, 0x37a10c7a, 0x59f8148e, 0xeb133c89 +.word 0xcea927ee, 0xb761c935, 0xe11ce5ed, 0x7a47b13c +.word 0x9cd2df59, 0x55f2733f, 0x1814ce79, 0x73c737bf +.word 0x53f7cdea, 0x5ffdaa5b, 0xdf3d6f14, 0x7844db86 +.word 0xcaaff381, 0xb968c43e, 0x3824342c, 0xc2a3405f +.word 0x161dc372, 0xbce2250c, 0x283c498b, 0xff0d9541 +.word 0x39a80171, 0x080cb3de, 0xd8b4e49c, 0x6456c190 +.word 0x7bcb8461, 0xd532b670, 0x486c5c74, 0xd0b85742 +@ Td4[256] +.byte 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38 +.byte 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb +.byte 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87 +.byte 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb +.byte 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d +.byte 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e +.byte 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2 +.byte 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25 +.byte 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16 +.byte 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92 +.byte 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda +.byte 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84 +.byte 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a +.byte 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06 +.byte 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02 +.byte 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b +.byte 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea +.byte 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73 +.byte 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85 +.byte 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e +.byte 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89 +.byte 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b +.byte 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20 +.byte 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4 +.byte 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31 +.byte 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f +.byte 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d +.byte 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef +.byte 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0 +.byte 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61 +.byte 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26 +.byte 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d +.size AES_Td,.-AES_Td + +@ void asm_AES_decrypt(const unsigned char *in, unsigned char *out, +@ const AES_KEY *key) { +.global asm_AES_decrypt +.type asm_AES_decrypt,%function +.align 5 +asm_AES_decrypt: +#if __ARM_ARCH__<7 + sub r3,pc,#8 @ asm_AES_decrypt +#else + adr r3,asm_AES_decrypt +#endif + stmdb sp!,{r1,r4-r12,lr} +#ifdef __APPLE__ + adr $tbl,AES_Td +#else + sub $tbl,r3,#asm_AES_decrypt-AES_Td @ Td +#endif + mov $rounds,r0 @ inp + mov $key,r2 +#if __ARM_ARCH__<7 + ldrb $s0,[$rounds,#3] @ load input data in endian-neutral + ldrb $t1,[$rounds,#2] @ manner... + ldrb $t2,[$rounds,#1] + ldrb $t3,[$rounds,#0] + orr $s0,$s0,$t1,lsl#8 + ldrb $s1,[$rounds,#7] + orr $s0,$s0,$t2,lsl#16 + ldrb $t1,[$rounds,#6] + orr $s0,$s0,$t3,lsl#24 + ldrb $t2,[$rounds,#5] + ldrb $t3,[$rounds,#4] + orr $s1,$s1,$t1,lsl#8 + ldrb $s2,[$rounds,#11] + orr $s1,$s1,$t2,lsl#16 + ldrb $t1,[$rounds,#10] + orr $s1,$s1,$t3,lsl#24 + ldrb $t2,[$rounds,#9] + ldrb $t3,[$rounds,#8] + orr $s2,$s2,$t1,lsl#8 + ldrb $s3,[$rounds,#15] + orr $s2,$s2,$t2,lsl#16 + ldrb $t1,[$rounds,#14] + orr $s2,$s2,$t3,lsl#24 + ldrb $t2,[$rounds,#13] + ldrb $t3,[$rounds,#12] + orr $s3,$s3,$t1,lsl#8 + orr $s3,$s3,$t2,lsl#16 + orr $s3,$s3,$t3,lsl#24 +#else + ldr $s0,[$rounds,#0] + ldr $s1,[$rounds,#4] + ldr $s2,[$rounds,#8] + ldr $s3,[$rounds,#12] +#ifdef __ARMEL__ + rev $s0,$s0 + rev $s1,$s1 + rev $s2,$s2 + rev $s3,$s3 +#endif +#endif + bl _armv4_AES_decrypt + + ldr $rounds,[sp],#4 @ pop out +#if __ARM_ARCH__>=7 +#ifdef __ARMEL__ + rev $s0,$s0 + rev $s1,$s1 + rev $s2,$s2 + rev $s3,$s3 +#endif + str $s0,[$rounds,#0] + str $s1,[$rounds,#4] + str $s2,[$rounds,#8] + str $s3,[$rounds,#12] +#else + mov $t1,$s0,lsr#24 @ write output in endian-neutral + mov $t2,$s0,lsr#16 @ manner... + mov $t3,$s0,lsr#8 + strb $t1,[$rounds,#0] + strb $t2,[$rounds,#1] + mov $t1,$s1,lsr#24 + strb $t3,[$rounds,#2] + mov $t2,$s1,lsr#16 + strb $s0,[$rounds,#3] + mov $t3,$s1,lsr#8 + strb $t1,[$rounds,#4] + strb $t2,[$rounds,#5] + mov $t1,$s2,lsr#24 + strb $t3,[$rounds,#6] + mov $t2,$s2,lsr#16 + strb $s1,[$rounds,#7] + mov $t3,$s2,lsr#8 + strb $t1,[$rounds,#8] + strb $t2,[$rounds,#9] + mov $t1,$s3,lsr#24 + strb $t3,[$rounds,#10] + mov $t2,$s3,lsr#16 + strb $s2,[$rounds,#11] + mov $t3,$s3,lsr#8 + strb $t1,[$rounds,#12] + strb $t2,[$rounds,#13] + strb $t3,[$rounds,#14] + strb $s3,[$rounds,#15] +#endif +#if __ARM_ARCH__>=5 + ldmia sp!,{r4-r12,pc} +#else + ldmia sp!,{r4-r12,lr} + tst lr,#1 + moveq pc,lr @ be binary compatible with V4, yet + bx lr @ interoperable with Thumb ISA:-) +#endif +.size asm_AES_decrypt,.-asm_AES_decrypt + +.type _armv4_AES_decrypt,%function +.align 2 +_armv4_AES_decrypt: + str lr,[sp,#-4]! @ push lr + ldmia $key!,{$t1-$i1} + eor $s0,$s0,$t1 + ldr $rounds,[$key,#240-16] + eor $s1,$s1,$t2 + eor $s2,$s2,$t3 + eor $s3,$s3,$i1 + sub $rounds,$rounds,#1 + mov lr,#255 + + and $i1,lr,$s0,lsr#16 + and $i2,lr,$s0,lsr#8 + and $i3,lr,$s0 + mov $s0,$s0,lsr#24 +.Ldec_loop: + ldr $t1,[$tbl,$i1,lsl#2] @ Td1[s0>>16] + and $i1,lr,$s1 @ i0 + ldr $t2,[$tbl,$i2,lsl#2] @ Td2[s0>>8] + and $i2,lr,$s1,lsr#16 + ldr $t3,[$tbl,$i3,lsl#2] @ Td3[s0>>0] + and $i3,lr,$s1,lsr#8 + ldr $s0,[$tbl,$s0,lsl#2] @ Td0[s0>>24] + mov $s1,$s1,lsr#24 + + ldr $i1,[$tbl,$i1,lsl#2] @ Td3[s1>>0] + ldr $i2,[$tbl,$i2,lsl#2] @ Td1[s1>>16] + ldr $i3,[$tbl,$i3,lsl#2] @ Td2[s1>>8] + eor $s0,$s0,$i1,ror#24 + ldr $s1,[$tbl,$s1,lsl#2] @ Td0[s1>>24] + and $i1,lr,$s2,lsr#8 @ i0 + eor $t2,$i2,$t2,ror#8 + and $i2,lr,$s2 @ i1 + eor $t3,$i3,$t3,ror#8 + and $i3,lr,$s2,lsr#16 + ldr $i1,[$tbl,$i1,lsl#2] @ Td2[s2>>8] + eor $s1,$s1,$t1,ror#8 + ldr $i2,[$tbl,$i2,lsl#2] @ Td3[s2>>0] + mov $s2,$s2,lsr#24 + + ldr $i3,[$tbl,$i3,lsl#2] @ Td1[s2>>16] + eor $s0,$s0,$i1,ror#16 + ldr $s2,[$tbl,$s2,lsl#2] @ Td0[s2>>24] + and $i1,lr,$s3,lsr#16 @ i0 + eor $s1,$s1,$i2,ror#24 + and $i2,lr,$s3,lsr#8 @ i1 + eor $t3,$i3,$t3,ror#8 + and $i3,lr,$s3 @ i2 + ldr $i1,[$tbl,$i1,lsl#2] @ Td1[s3>>16] + eor $s2,$s2,$t2,ror#8 + ldr $i2,[$tbl,$i2,lsl#2] @ Td2[s3>>8] + mov $s3,$s3,lsr#24 + + ldr $i3,[$tbl,$i3,lsl#2] @ Td3[s3>>0] + eor $s0,$s0,$i1,ror#8 + ldr $i1,[$key],#16 + eor $s1,$s1,$i2,ror#16 + ldr $s3,[$tbl,$s3,lsl#2] @ Td0[s3>>24] + eor $s2,$s2,$i3,ror#24 + + ldr $t1,[$key,#-12] + eor $s0,$s0,$i1 + ldr $t2,[$key,#-8] + eor $s3,$s3,$t3,ror#8 + ldr $t3,[$key,#-4] + and $i1,lr,$s0,lsr#16 + eor $s1,$s1,$t1 + and $i2,lr,$s0,lsr#8 + eor $s2,$s2,$t2 + and $i3,lr,$s0 + eor $s3,$s3,$t3 + mov $s0,$s0,lsr#24 + + subs $rounds,$rounds,#1 + bne .Ldec_loop + + add $tbl,$tbl,#1024 + + ldr $t2,[$tbl,#0] @ prefetch Td4 + ldr $t3,[$tbl,#32] + ldr $t1,[$tbl,#64] + ldr $t2,[$tbl,#96] + ldr $t3,[$tbl,#128] + ldr $t1,[$tbl,#160] + ldr $t2,[$tbl,#192] + ldr $t3,[$tbl,#224] + + ldrb $s0,[$tbl,$s0] @ Td4[s0>>24] + ldrb $t1,[$tbl,$i1] @ Td4[s0>>16] + and $i1,lr,$s1 @ i0 + ldrb $t2,[$tbl,$i2] @ Td4[s0>>8] + and $i2,lr,$s1,lsr#16 + ldrb $t3,[$tbl,$i3] @ Td4[s0>>0] + and $i3,lr,$s1,lsr#8 + + add $s1,$tbl,$s1,lsr#24 + ldrb $i1,[$tbl,$i1] @ Td4[s1>>0] + ldrb $s1,[$s1] @ Td4[s1>>24] + ldrb $i2,[$tbl,$i2] @ Td4[s1>>16] + eor $s0,$i1,$s0,lsl#24 + ldrb $i3,[$tbl,$i3] @ Td4[s1>>8] + eor $s1,$t1,$s1,lsl#8 + and $i1,lr,$s2,lsr#8 @ i0 + eor $t2,$t2,$i2,lsl#8 + and $i2,lr,$s2 @ i1 + ldrb $i1,[$tbl,$i1] @ Td4[s2>>8] + eor $t3,$t3,$i3,lsl#8 + ldrb $i2,[$tbl,$i2] @ Td4[s2>>0] + and $i3,lr,$s2,lsr#16 + + add $s2,$tbl,$s2,lsr#24 + ldrb $s2,[$s2] @ Td4[s2>>24] + eor $s0,$s0,$i1,lsl#8 + ldrb $i3,[$tbl,$i3] @ Td4[s2>>16] + eor $s1,$i2,$s1,lsl#16 + and $i1,lr,$s3,lsr#16 @ i0 + eor $s2,$t2,$s2,lsl#16 + and $i2,lr,$s3,lsr#8 @ i1 + ldrb $i1,[$tbl,$i1] @ Td4[s3>>16] + eor $t3,$t3,$i3,lsl#16 + ldrb $i2,[$tbl,$i2] @ Td4[s3>>8] + and $i3,lr,$s3 @ i2 + + add $s3,$tbl,$s3,lsr#24 + ldrb $i3,[$tbl,$i3] @ Td4[s3>>0] + ldrb $s3,[$s3] @ Td4[s3>>24] + eor $s0,$s0,$i1,lsl#16 + ldr $i1,[$key,#0] + eor $s1,$s1,$i2,lsl#8 + ldr $t1,[$key,#4] + eor $s2,$i3,$s2,lsl#8 + ldr $t2,[$key,#8] + eor $s3,$t3,$s3,lsl#24 + ldr $t3,[$key,#12] + + eor $s0,$s0,$i1 + eor $s1,$s1,$t1 + eor $s2,$s2,$t2 + eor $s3,$s3,$t3 + + sub $tbl,$tbl,#1024 + ldr pc,[sp],#4 @ pop and return +.size _armv4_AES_decrypt,.-_armv4_AES_decrypt +.asciz "AES for ARMv4, CRYPTOGAMS by " +.align 2 + +#endif +___ + +$code =~ s/\bbx\s+lr\b/.word\t0xe12fff1e/gm; # make it possible to compile with -march=armv4 +$code =~ s/\bret\b/bx\tlr/gm; + +open SELF,$0; +while() { + next if (/^#!/); + last if (!s/^#/@/ and !/^$/); + print; +} +close SELF; + +print $code; +close STDOUT; # enforce flush diff --git a/external/boringssl/crypto/aes/asm/aes-x86_64.pl b/external/boringssl/crypto/aes/asm/aes-x86_64.pl new file mode 100644 index 0000000000..4b6e1b440f --- /dev/null +++ b/external/boringssl/crypto/aes/asm/aes-x86_64.pl @@ -0,0 +1,2805 @@ +#!/usr/bin/env perl +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# Version 2.1. +# +# aes-*-cbc benchmarks are improved by >70% [compared to gcc 3.3.2 on +# Opteron 240 CPU] plus all the bells-n-whistles from 32-bit version +# [you'll notice a lot of resemblance], such as compressed S-boxes +# in little-endian byte order, prefetch of these tables in CBC mode, +# as well as avoiding L1 cache aliasing between stack frame and key +# schedule and already mentioned tables, compressed Td4... +# +# Performance in number of cycles per processed byte for 128-bit key: +# +# ECB encrypt ECB decrypt CBC large chunk +# AMD64 33 43 13.0 +# EM64T 38 56 18.6(*) +# Core 2 30 42 14.5(*) +# Atom 65 86 32.1(*) +# +# (*) with hyper-threading off + +$flavour = shift; +$output = shift; +if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } + +$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or +die "can't locate x86_64-xlate.pl"; + +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; + +$verticalspin=1; # unlike 32-bit version $verticalspin performs + # ~15% better on both AMD and Intel cores +$speed_limit=512; # see aes-586.pl for details + +$code=".text\n"; + +$s0="%eax"; +$s1="%ebx"; +$s2="%ecx"; +$s3="%edx"; +$acc0="%esi"; $mask80="%rsi"; +$acc1="%edi"; $maskfe="%rdi"; +$acc2="%ebp"; $mask1b="%rbp"; +$inp="%r8"; +$out="%r9"; +$t0="%r10d"; +$t1="%r11d"; +$t2="%r12d"; +$rnds="%r13d"; +$sbox="%r14"; +$key="%r15"; + +sub hi() { my $r=shift; $r =~ s/%[er]([a-d])x/%\1h/; $r; } +sub lo() { my $r=shift; $r =~ s/%[er]([a-d])x/%\1l/; + $r =~ s/%[er]([sd]i)/%\1l/; + $r =~ s/%(r[0-9]+)[d]?/%\1b/; $r; } +sub LO() { my $r=shift; $r =~ s/%r([a-z]+)/%e\1/; + $r =~ s/%r([0-9]+)/%r\1d/; $r; } +sub _data_word() +{ my $i; + while(defined($i=shift)) { $code.=sprintf".long\t0x%08x,0x%08x\n",$i,$i; } +} +sub data_word() +{ my $i; + my $last=pop(@_); + $code.=".long\t"; + while(defined($i=shift)) { $code.=sprintf"0x%08x,",$i; } + $code.=sprintf"0x%08x\n",$last; +} + +sub data_byte() +{ my $i; + my $last=pop(@_); + $code.=".byte\t"; + while(defined($i=shift)) { $code.=sprintf"0x%02x,",$i&0xff; } + $code.=sprintf"0x%02x\n",$last&0xff; +} + +sub encvert() +{ my $t3="%r8d"; # zaps $inp! + +$code.=<<___; + # favor 3-way issue Opteron pipeline... + movzb `&lo("$s0")`,$acc0 + movzb `&lo("$s1")`,$acc1 + movzb `&lo("$s2")`,$acc2 + mov 0($sbox,$acc0,8),$t0 + mov 0($sbox,$acc1,8),$t1 + mov 0($sbox,$acc2,8),$t2 + + movzb `&hi("$s1")`,$acc0 + movzb `&hi("$s2")`,$acc1 + movzb `&lo("$s3")`,$acc2 + xor 3($sbox,$acc0,8),$t0 + xor 3($sbox,$acc1,8),$t1 + mov 0($sbox,$acc2,8),$t3 + + movzb `&hi("$s3")`,$acc0 + shr \$16,$s2 + movzb `&hi("$s0")`,$acc2 + xor 3($sbox,$acc0,8),$t2 + shr \$16,$s3 + xor 3($sbox,$acc2,8),$t3 + + shr \$16,$s1 + lea 16($key),$key + shr \$16,$s0 + + movzb `&lo("$s2")`,$acc0 + movzb `&lo("$s3")`,$acc1 + movzb `&lo("$s0")`,$acc2 + xor 2($sbox,$acc0,8),$t0 + xor 2($sbox,$acc1,8),$t1 + xor 2($sbox,$acc2,8),$t2 + + movzb `&hi("$s3")`,$acc0 + movzb `&hi("$s0")`,$acc1 + movzb `&lo("$s1")`,$acc2 + xor 1($sbox,$acc0,8),$t0 + xor 1($sbox,$acc1,8),$t1 + xor 2($sbox,$acc2,8),$t3 + + mov 12($key),$s3 + movzb `&hi("$s1")`,$acc1 + movzb `&hi("$s2")`,$acc2 + mov 0($key),$s0 + xor 1($sbox,$acc1,8),$t2 + xor 1($sbox,$acc2,8),$t3 + + mov 4($key),$s1 + mov 8($key),$s2 + xor $t0,$s0 + xor $t1,$s1 + xor $t2,$s2 + xor $t3,$s3 +___ +} + +sub enclastvert() +{ my $t3="%r8d"; # zaps $inp! + +$code.=<<___; + movzb `&lo("$s0")`,$acc0 + movzb `&lo("$s1")`,$acc1 + movzb `&lo("$s2")`,$acc2 + movzb 2($sbox,$acc0,8),$t0 + movzb 2($sbox,$acc1,8),$t1 + movzb 2($sbox,$acc2,8),$t2 + + movzb `&lo("$s3")`,$acc0 + movzb `&hi("$s1")`,$acc1 + movzb `&hi("$s2")`,$acc2 + movzb 2($sbox,$acc0,8),$t3 + mov 0($sbox,$acc1,8),$acc1 #$t0 + mov 0($sbox,$acc2,8),$acc2 #$t1 + + and \$0x0000ff00,$acc1 + and \$0x0000ff00,$acc2 + + xor $acc1,$t0 + xor $acc2,$t1 + shr \$16,$s2 + + movzb `&hi("$s3")`,$acc0 + movzb `&hi("$s0")`,$acc1 + shr \$16,$s3 + mov 0($sbox,$acc0,8),$acc0 #$t2 + mov 0($sbox,$acc1,8),$acc1 #$t3 + + and \$0x0000ff00,$acc0 + and \$0x0000ff00,$acc1 + shr \$16,$s1 + xor $acc0,$t2 + xor $acc1,$t3 + shr \$16,$s0 + + movzb `&lo("$s2")`,$acc0 + movzb `&lo("$s3")`,$acc1 + movzb `&lo("$s0")`,$acc2 + mov 0($sbox,$acc0,8),$acc0 #$t0 + mov 0($sbox,$acc1,8),$acc1 #$t1 + mov 0($sbox,$acc2,8),$acc2 #$t2 + + and \$0x00ff0000,$acc0 + and \$0x00ff0000,$acc1 + and \$0x00ff0000,$acc2 + + xor $acc0,$t0 + xor $acc1,$t1 + xor $acc2,$t2 + + movzb `&lo("$s1")`,$acc0 + movzb `&hi("$s3")`,$acc1 + movzb `&hi("$s0")`,$acc2 + mov 0($sbox,$acc0,8),$acc0 #$t3 + mov 2($sbox,$acc1,8),$acc1 #$t0 + mov 2($sbox,$acc2,8),$acc2 #$t1 + + and \$0x00ff0000,$acc0 + and \$0xff000000,$acc1 + and \$0xff000000,$acc2 + + xor $acc0,$t3 + xor $acc1,$t0 + xor $acc2,$t1 + + movzb `&hi("$s1")`,$acc0 + movzb `&hi("$s2")`,$acc1 + mov 16+12($key),$s3 + mov 2($sbox,$acc0,8),$acc0 #$t2 + mov 2($sbox,$acc1,8),$acc1 #$t3 + mov 16+0($key),$s0 + + and \$0xff000000,$acc0 + and \$0xff000000,$acc1 + + xor $acc0,$t2 + xor $acc1,$t3 + + mov 16+4($key),$s1 + mov 16+8($key),$s2 + xor $t0,$s0 + xor $t1,$s1 + xor $t2,$s2 + xor $t3,$s3 +___ +} + +sub encstep() +{ my ($i,@s) = @_; + my $tmp0=$acc0; + my $tmp1=$acc1; + my $tmp2=$acc2; + my $out=($t0,$t1,$t2,$s[0])[$i]; + + if ($i==3) { + $tmp0=$s[1]; + $tmp1=$s[2]; + $tmp2=$s[3]; + } + $code.=" movzb ".&lo($s[0]).",$out\n"; + $code.=" mov $s[2],$tmp1\n" if ($i!=3); + $code.=" lea 16($key),$key\n" if ($i==0); + + $code.=" movzb ".&hi($s[1]).",$tmp0\n"; + $code.=" mov 0($sbox,$out,8),$out\n"; + + $code.=" shr \$16,$tmp1\n"; + $code.=" mov $s[3],$tmp2\n" if ($i!=3); + $code.=" xor 3($sbox,$tmp0,8),$out\n"; + + $code.=" movzb ".&lo($tmp1).",$tmp1\n"; + $code.=" shr \$24,$tmp2\n"; + $code.=" xor 4*$i($key),$out\n"; + + $code.=" xor 2($sbox,$tmp1,8),$out\n"; + $code.=" xor 1($sbox,$tmp2,8),$out\n"; + + $code.=" mov $t0,$s[1]\n" if ($i==3); + $code.=" mov $t1,$s[2]\n" if ($i==3); + $code.=" mov $t2,$s[3]\n" if ($i==3); + $code.="\n"; +} + +sub enclast() +{ my ($i,@s)=@_; + my $tmp0=$acc0; + my $tmp1=$acc1; + my $tmp2=$acc2; + my $out=($t0,$t1,$t2,$s[0])[$i]; + + if ($i==3) { + $tmp0=$s[1]; + $tmp1=$s[2]; + $tmp2=$s[3]; + } + $code.=" movzb ".&lo($s[0]).",$out\n"; + $code.=" mov $s[2],$tmp1\n" if ($i!=3); + + $code.=" mov 2($sbox,$out,8),$out\n"; + $code.=" shr \$16,$tmp1\n"; + $code.=" mov $s[3],$tmp2\n" if ($i!=3); + + $code.=" and \$0x000000ff,$out\n"; + $code.=" movzb ".&hi($s[1]).",$tmp0\n"; + $code.=" movzb ".&lo($tmp1).",$tmp1\n"; + $code.=" shr \$24,$tmp2\n"; + + $code.=" mov 0($sbox,$tmp0,8),$tmp0\n"; + $code.=" mov 0($sbox,$tmp1,8),$tmp1\n"; + $code.=" mov 2($sbox,$tmp2,8),$tmp2\n"; + + $code.=" and \$0x0000ff00,$tmp0\n"; + $code.=" and \$0x00ff0000,$tmp1\n"; + $code.=" and \$0xff000000,$tmp2\n"; + + $code.=" xor $tmp0,$out\n"; + $code.=" mov $t0,$s[1]\n" if ($i==3); + $code.=" xor $tmp1,$out\n"; + $code.=" mov $t1,$s[2]\n" if ($i==3); + $code.=" xor $tmp2,$out\n"; + $code.=" mov $t2,$s[3]\n" if ($i==3); + $code.="\n"; +} + +$code.=<<___; +.type _x86_64_AES_encrypt,\@abi-omnipotent +.align 16 +_x86_64_AES_encrypt: + xor 0($key),$s0 # xor with key + xor 4($key),$s1 + xor 8($key),$s2 + xor 12($key),$s3 + + mov 240($key),$rnds # load key->rounds + sub \$1,$rnds + jmp .Lenc_loop +.align 16 +.Lenc_loop: +___ + if ($verticalspin) { &encvert(); } + else { &encstep(0,$s0,$s1,$s2,$s3); + &encstep(1,$s1,$s2,$s3,$s0); + &encstep(2,$s2,$s3,$s0,$s1); + &encstep(3,$s3,$s0,$s1,$s2); + } +$code.=<<___; + sub \$1,$rnds + jnz .Lenc_loop +___ + if ($verticalspin) { &enclastvert(); } + else { &enclast(0,$s0,$s1,$s2,$s3); + &enclast(1,$s1,$s2,$s3,$s0); + &enclast(2,$s2,$s3,$s0,$s1); + &enclast(3,$s3,$s0,$s1,$s2); + $code.=<<___; + xor 16+0($key),$s0 # xor with key + xor 16+4($key),$s1 + xor 16+8($key),$s2 + xor 16+12($key),$s3 +___ + } +$code.=<<___; + .byte 0xf3,0xc3 # rep ret +.size _x86_64_AES_encrypt,.-_x86_64_AES_encrypt +___ + +# it's possible to implement this by shifting tN by 8, filling least +# significant byte with byte load and finally bswap-ing at the end, +# but such partial register load kills Core 2... +sub enccompactvert() +{ my ($t3,$t4,$t5)=("%r8d","%r9d","%r13d"); + +$code.=<<___; + movzb `&lo("$s0")`,$t0 + movzb `&lo("$s1")`,$t1 + movzb `&lo("$s2")`,$t2 + movzb `&lo("$s3")`,$t3 + movzb `&hi("$s1")`,$acc0 + movzb `&hi("$s2")`,$acc1 + shr \$16,$s2 + movzb `&hi("$s3")`,$acc2 + movzb ($sbox,$t0,1),$t0 + movzb ($sbox,$t1,1),$t1 + movzb ($sbox,$t2,1),$t2 + movzb ($sbox,$t3,1),$t3 + + movzb ($sbox,$acc0,1),$t4 #$t0 + movzb `&hi("$s0")`,$acc0 + movzb ($sbox,$acc1,1),$t5 #$t1 + movzb `&lo("$s2")`,$acc1 + movzb ($sbox,$acc2,1),$acc2 #$t2 + movzb ($sbox,$acc0,1),$acc0 #$t3 + + shl \$8,$t4 + shr \$16,$s3 + shl \$8,$t5 + xor $t4,$t0 + shr \$16,$s0 + movzb `&lo("$s3")`,$t4 + shr \$16,$s1 + xor $t5,$t1 + shl \$8,$acc2 + movzb `&lo("$s0")`,$t5 + movzb ($sbox,$acc1,1),$acc1 #$t0 + xor $acc2,$t2 + + shl \$8,$acc0 + movzb `&lo("$s1")`,$acc2 + shl \$16,$acc1 + xor $acc0,$t3 + movzb ($sbox,$t4,1),$t4 #$t1 + movzb `&hi("$s3")`,$acc0 + movzb ($sbox,$t5,1),$t5 #$t2 + xor $acc1,$t0 + + shr \$8,$s2 + movzb `&hi("$s0")`,$acc1 + shl \$16,$t4 + shr \$8,$s1 + shl \$16,$t5 + xor $t4,$t1 + movzb ($sbox,$acc2,1),$acc2 #$t3 + movzb ($sbox,$acc0,1),$acc0 #$t0 + movzb ($sbox,$acc1,1),$acc1 #$t1 + movzb ($sbox,$s2,1),$s3 #$t3 + movzb ($sbox,$s1,1),$s2 #$t2 + + shl \$16,$acc2 + xor $t5,$t2 + shl \$24,$acc0 + xor $acc2,$t3 + shl \$24,$acc1 + xor $acc0,$t0 + shl \$24,$s3 + xor $acc1,$t1 + shl \$24,$s2 + mov $t0,$s0 + mov $t1,$s1 + xor $t2,$s2 + xor $t3,$s3 +___ +} + +sub enctransform_ref() +{ my $sn = shift; + my ($acc,$r2,$tmp)=("%r8d","%r9d","%r13d"); + +$code.=<<___; + mov $sn,$acc + and \$0x80808080,$acc + mov $acc,$tmp + shr \$7,$tmp + lea ($sn,$sn),$r2 + sub $tmp,$acc + and \$0xfefefefe,$r2 + and \$0x1b1b1b1b,$acc + mov $sn,$tmp + xor $acc,$r2 + + xor $r2,$sn + rol \$24,$sn + xor $r2,$sn + ror \$16,$tmp + xor $tmp,$sn + ror \$8,$tmp + xor $tmp,$sn +___ +} + +# unlike decrypt case it does not pay off to parallelize enctransform +sub enctransform() +{ my ($t3,$r20,$r21)=($acc2,"%r8d","%r9d"); + +$code.=<<___; + mov \$0x80808080,$t0 + mov \$0x80808080,$t1 + and $s0,$t0 + and $s1,$t1 + mov $t0,$acc0 + mov $t1,$acc1 + shr \$7,$t0 + lea ($s0,$s0),$r20 + shr \$7,$t1 + lea ($s1,$s1),$r21 + sub $t0,$acc0 + sub $t1,$acc1 + and \$0xfefefefe,$r20 + and \$0xfefefefe,$r21 + and \$0x1b1b1b1b,$acc0 + and \$0x1b1b1b1b,$acc1 + mov $s0,$t0 + mov $s1,$t1 + xor $acc0,$r20 + xor $acc1,$r21 + + xor $r20,$s0 + xor $r21,$s1 + mov \$0x80808080,$t2 + rol \$24,$s0 + mov \$0x80808080,$t3 + rol \$24,$s1 + and $s2,$t2 + and $s3,$t3 + xor $r20,$s0 + xor $r21,$s1 + mov $t2,$acc0 + ror \$16,$t0 + mov $t3,$acc1 + ror \$16,$t1 + lea ($s2,$s2),$r20 + shr \$7,$t2 + xor $t0,$s0 + shr \$7,$t3 + xor $t1,$s1 + ror \$8,$t0 + lea ($s3,$s3),$r21 + ror \$8,$t1 + sub $t2,$acc0 + sub $t3,$acc1 + xor $t0,$s0 + xor $t1,$s1 + + and \$0xfefefefe,$r20 + and \$0xfefefefe,$r21 + and \$0x1b1b1b1b,$acc0 + and \$0x1b1b1b1b,$acc1 + mov $s2,$t2 + mov $s3,$t3 + xor $acc0,$r20 + xor $acc1,$r21 + + ror \$16,$t2 + xor $r20,$s2 + ror \$16,$t3 + xor $r21,$s3 + rol \$24,$s2 + mov 0($sbox),$acc0 # prefetch Te4 + rol \$24,$s3 + xor $r20,$s2 + mov 64($sbox),$acc1 + xor $r21,$s3 + mov 128($sbox),$r20 + xor $t2,$s2 + ror \$8,$t2 + xor $t3,$s3 + ror \$8,$t3 + xor $t2,$s2 + mov 192($sbox),$r21 + xor $t3,$s3 +___ +} + +$code.=<<___; +.type _x86_64_AES_encrypt_compact,\@abi-omnipotent +.align 16 +_x86_64_AES_encrypt_compact: + lea 128($sbox),$inp # size optimization + mov 0-128($inp),$acc1 # prefetch Te4 + mov 32-128($inp),$acc2 + mov 64-128($inp),$t0 + mov 96-128($inp),$t1 + mov 128-128($inp),$acc1 + mov 160-128($inp),$acc2 + mov 192-128($inp),$t0 + mov 224-128($inp),$t1 + jmp .Lenc_loop_compact +.align 16 +.Lenc_loop_compact: + xor 0($key),$s0 # xor with key + xor 4($key),$s1 + xor 8($key),$s2 + xor 12($key),$s3 + lea 16($key),$key +___ + &enccompactvert(); +$code.=<<___; + cmp 16(%rsp),$key + je .Lenc_compact_done +___ + &enctransform(); +$code.=<<___; + jmp .Lenc_loop_compact +.align 16 +.Lenc_compact_done: + xor 0($key),$s0 + xor 4($key),$s1 + xor 8($key),$s2 + xor 12($key),$s3 + .byte 0xf3,0xc3 # rep ret +.size _x86_64_AES_encrypt_compact,.-_x86_64_AES_encrypt_compact +___ + +# void asm_AES_encrypt (const void *inp,void *out,const AES_KEY *key); +$code.=<<___; +.align 16 +.globl asm_AES_encrypt +.type asm_AES_encrypt,\@function,3 +.hidden asm_AES_encrypt +asm_AES_encrypt: + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + + # allocate frame "above" key schedule + mov %rsp,%r10 + lea -63(%rdx),%rcx # %rdx is key argument + and \$-64,%rsp + sub %rsp,%rcx + neg %rcx + and \$0x3c0,%rcx + sub %rcx,%rsp + sub \$32,%rsp + + mov %rsi,16(%rsp) # save out + mov %r10,24(%rsp) # save real stack pointer +.Lenc_prologue: + + mov %rdx,$key + mov 240($key),$rnds # load rounds + + mov 0(%rdi),$s0 # load input vector + mov 4(%rdi),$s1 + mov 8(%rdi),$s2 + mov 12(%rdi),$s3 + + shl \$4,$rnds + lea ($key,$rnds),%rbp + mov $key,(%rsp) # key schedule + mov %rbp,8(%rsp) # end of key schedule + + # pick Te4 copy which can't "overlap" with stack frame or key schedule + lea .LAES_Te+2048(%rip),$sbox + lea 768(%rsp),%rbp + sub $sbox,%rbp + and \$0x300,%rbp + lea ($sbox,%rbp),$sbox + + call _x86_64_AES_encrypt_compact + + mov 16(%rsp),$out # restore out + mov 24(%rsp),%rsi # restore saved stack pointer + mov $s0,0($out) # write output vector + mov $s1,4($out) + mov $s2,8($out) + mov $s3,12($out) + + mov (%rsi),%r15 + mov 8(%rsi),%r14 + mov 16(%rsi),%r13 + mov 24(%rsi),%r12 + mov 32(%rsi),%rbp + mov 40(%rsi),%rbx + lea 48(%rsi),%rsp +.Lenc_epilogue: + ret +.size asm_AES_encrypt,.-asm_AES_encrypt +___ + +#------------------------------------------------------------------# + +sub decvert() +{ my $t3="%r8d"; # zaps $inp! + +$code.=<<___; + # favor 3-way issue Opteron pipeline... + movzb `&lo("$s0")`,$acc0 + movzb `&lo("$s1")`,$acc1 + movzb `&lo("$s2")`,$acc2 + mov 0($sbox,$acc0,8),$t0 + mov 0($sbox,$acc1,8),$t1 + mov 0($sbox,$acc2,8),$t2 + + movzb `&hi("$s3")`,$acc0 + movzb `&hi("$s0")`,$acc1 + movzb `&lo("$s3")`,$acc2 + xor 3($sbox,$acc0,8),$t0 + xor 3($sbox,$acc1,8),$t1 + mov 0($sbox,$acc2,8),$t3 + + movzb `&hi("$s1")`,$acc0 + shr \$16,$s0 + movzb `&hi("$s2")`,$acc2 + xor 3($sbox,$acc0,8),$t2 + shr \$16,$s3 + xor 3($sbox,$acc2,8),$t3 + + shr \$16,$s1 + lea 16($key),$key + shr \$16,$s2 + + movzb `&lo("$s2")`,$acc0 + movzb `&lo("$s3")`,$acc1 + movzb `&lo("$s0")`,$acc2 + xor 2($sbox,$acc0,8),$t0 + xor 2($sbox,$acc1,8),$t1 + xor 2($sbox,$acc2,8),$t2 + + movzb `&hi("$s1")`,$acc0 + movzb `&hi("$s2")`,$acc1 + movzb `&lo("$s1")`,$acc2 + xor 1($sbox,$acc0,8),$t0 + xor 1($sbox,$acc1,8),$t1 + xor 2($sbox,$acc2,8),$t3 + + movzb `&hi("$s3")`,$acc0 + mov 12($key),$s3 + movzb `&hi("$s0")`,$acc2 + xor 1($sbox,$acc0,8),$t2 + mov 0($key),$s0 + xor 1($sbox,$acc2,8),$t3 + + xor $t0,$s0 + mov 4($key),$s1 + mov 8($key),$s2 + xor $t2,$s2 + xor $t1,$s1 + xor $t3,$s3 +___ +} + +sub declastvert() +{ my $t3="%r8d"; # zaps $inp! + +$code.=<<___; + lea 2048($sbox),$sbox # size optimization + movzb `&lo("$s0")`,$acc0 + movzb `&lo("$s1")`,$acc1 + movzb `&lo("$s2")`,$acc2 + movzb ($sbox,$acc0,1),$t0 + movzb ($sbox,$acc1,1),$t1 + movzb ($sbox,$acc2,1),$t2 + + movzb `&lo("$s3")`,$acc0 + movzb `&hi("$s3")`,$acc1 + movzb `&hi("$s0")`,$acc2 + movzb ($sbox,$acc0,1),$t3 + movzb ($sbox,$acc1,1),$acc1 #$t0 + movzb ($sbox,$acc2,1),$acc2 #$t1 + + shl \$8,$acc1 + shl \$8,$acc2 + + xor $acc1,$t0 + xor $acc2,$t1 + shr \$16,$s3 + + movzb `&hi("$s1")`,$acc0 + movzb `&hi("$s2")`,$acc1 + shr \$16,$s0 + movzb ($sbox,$acc0,1),$acc0 #$t2 + movzb ($sbox,$acc1,1),$acc1 #$t3 + + shl \$8,$acc0 + shl \$8,$acc1 + shr \$16,$s1 + xor $acc0,$t2 + xor $acc1,$t3 + shr \$16,$s2 + + movzb `&lo("$s2")`,$acc0 + movzb `&lo("$s3")`,$acc1 + movzb `&lo("$s0")`,$acc2 + movzb ($sbox,$acc0,1),$acc0 #$t0 + movzb ($sbox,$acc1,1),$acc1 #$t1 + movzb ($sbox,$acc2,1),$acc2 #$t2 + + shl \$16,$acc0 + shl \$16,$acc1 + shl \$16,$acc2 + + xor $acc0,$t0 + xor $acc1,$t1 + xor $acc2,$t2 + + movzb `&lo("$s1")`,$acc0 + movzb `&hi("$s1")`,$acc1 + movzb `&hi("$s2")`,$acc2 + movzb ($sbox,$acc0,1),$acc0 #$t3 + movzb ($sbox,$acc1,1),$acc1 #$t0 + movzb ($sbox,$acc2,1),$acc2 #$t1 + + shl \$16,$acc0 + shl \$24,$acc1 + shl \$24,$acc2 + + xor $acc0,$t3 + xor $acc1,$t0 + xor $acc2,$t1 + + movzb `&hi("$s3")`,$acc0 + movzb `&hi("$s0")`,$acc1 + mov 16+12($key),$s3 + movzb ($sbox,$acc0,1),$acc0 #$t2 + movzb ($sbox,$acc1,1),$acc1 #$t3 + mov 16+0($key),$s0 + + shl \$24,$acc0 + shl \$24,$acc1 + + xor $acc0,$t2 + xor $acc1,$t3 + + mov 16+4($key),$s1 + mov 16+8($key),$s2 + lea -2048($sbox),$sbox + xor $t0,$s0 + xor $t1,$s1 + xor $t2,$s2 + xor $t3,$s3 +___ +} + +sub decstep() +{ my ($i,@s) = @_; + my $tmp0=$acc0; + my $tmp1=$acc1; + my $tmp2=$acc2; + my $out=($t0,$t1,$t2,$s[0])[$i]; + + $code.=" mov $s[0],$out\n" if ($i!=3); + $tmp1=$s[2] if ($i==3); + $code.=" mov $s[2],$tmp1\n" if ($i!=3); + $code.=" and \$0xFF,$out\n"; + + $code.=" mov 0($sbox,$out,8),$out\n"; + $code.=" shr \$16,$tmp1\n"; + $tmp2=$s[3] if ($i==3); + $code.=" mov $s[3],$tmp2\n" if ($i!=3); + + $tmp0=$s[1] if ($i==3); + $code.=" movzb ".&hi($s[1]).",$tmp0\n"; + $code.=" and \$0xFF,$tmp1\n"; + $code.=" shr \$24,$tmp2\n"; + + $code.=" xor 3($sbox,$tmp0,8),$out\n"; + $code.=" xor 2($sbox,$tmp1,8),$out\n"; + $code.=" xor 1($sbox,$tmp2,8),$out\n"; + + $code.=" mov $t2,$s[1]\n" if ($i==3); + $code.=" mov $t1,$s[2]\n" if ($i==3); + $code.=" mov $t0,$s[3]\n" if ($i==3); + $code.="\n"; +} + +sub declast() +{ my ($i,@s)=@_; + my $tmp0=$acc0; + my $tmp1=$acc1; + my $tmp2=$acc2; + my $out=($t0,$t1,$t2,$s[0])[$i]; + + $code.=" mov $s[0],$out\n" if ($i!=3); + $tmp1=$s[2] if ($i==3); + $code.=" mov $s[2],$tmp1\n" if ($i!=3); + $code.=" and \$0xFF,$out\n"; + + $code.=" movzb 2048($sbox,$out,1),$out\n"; + $code.=" shr \$16,$tmp1\n"; + $tmp2=$s[3] if ($i==3); + $code.=" mov $s[3],$tmp2\n" if ($i!=3); + + $tmp0=$s[1] if ($i==3); + $code.=" movzb ".&hi($s[1]).",$tmp0\n"; + $code.=" and \$0xFF,$tmp1\n"; + $code.=" shr \$24,$tmp2\n"; + + $code.=" movzb 2048($sbox,$tmp0,1),$tmp0\n"; + $code.=" movzb 2048($sbox,$tmp1,1),$tmp1\n"; + $code.=" movzb 2048($sbox,$tmp2,1),$tmp2\n"; + + $code.=" shl \$8,$tmp0\n"; + $code.=" shl \$16,$tmp1\n"; + $code.=" shl \$24,$tmp2\n"; + + $code.=" xor $tmp0,$out\n"; + $code.=" mov $t2,$s[1]\n" if ($i==3); + $code.=" xor $tmp1,$out\n"; + $code.=" mov $t1,$s[2]\n" if ($i==3); + $code.=" xor $tmp2,$out\n"; + $code.=" mov $t0,$s[3]\n" if ($i==3); + $code.="\n"; +} + +$code.=<<___; +.type _x86_64_AES_decrypt,\@abi-omnipotent +.align 16 +_x86_64_AES_decrypt: + xor 0($key),$s0 # xor with key + xor 4($key),$s1 + xor 8($key),$s2 + xor 12($key),$s3 + + mov 240($key),$rnds # load key->rounds + sub \$1,$rnds + jmp .Ldec_loop +.align 16 +.Ldec_loop: +___ + if ($verticalspin) { &decvert(); } + else { &decstep(0,$s0,$s3,$s2,$s1); + &decstep(1,$s1,$s0,$s3,$s2); + &decstep(2,$s2,$s1,$s0,$s3); + &decstep(3,$s3,$s2,$s1,$s0); + $code.=<<___; + lea 16($key),$key + xor 0($key),$s0 # xor with key + xor 4($key),$s1 + xor 8($key),$s2 + xor 12($key),$s3 +___ + } +$code.=<<___; + sub \$1,$rnds + jnz .Ldec_loop +___ + if ($verticalspin) { &declastvert(); } + else { &declast(0,$s0,$s3,$s2,$s1); + &declast(1,$s1,$s0,$s3,$s2); + &declast(2,$s2,$s1,$s0,$s3); + &declast(3,$s3,$s2,$s1,$s0); + $code.=<<___; + xor 16+0($key),$s0 # xor with key + xor 16+4($key),$s1 + xor 16+8($key),$s2 + xor 16+12($key),$s3 +___ + } +$code.=<<___; + .byte 0xf3,0xc3 # rep ret +.size _x86_64_AES_decrypt,.-_x86_64_AES_decrypt +___ + +sub deccompactvert() +{ my ($t3,$t4,$t5)=("%r8d","%r9d","%r13d"); + +$code.=<<___; + movzb `&lo("$s0")`,$t0 + movzb `&lo("$s1")`,$t1 + movzb `&lo("$s2")`,$t2 + movzb `&lo("$s3")`,$t3 + movzb `&hi("$s3")`,$acc0 + movzb `&hi("$s0")`,$acc1 + shr \$16,$s3 + movzb `&hi("$s1")`,$acc2 + movzb ($sbox,$t0,1),$t0 + movzb ($sbox,$t1,1),$t1 + movzb ($sbox,$t2,1),$t2 + movzb ($sbox,$t3,1),$t3 + + movzb ($sbox,$acc0,1),$t4 #$t0 + movzb `&hi("$s2")`,$acc0 + movzb ($sbox,$acc1,1),$t5 #$t1 + movzb ($sbox,$acc2,1),$acc2 #$t2 + movzb ($sbox,$acc0,1),$acc0 #$t3 + + shr \$16,$s2 + shl \$8,$t5 + shl \$8,$t4 + movzb `&lo("$s2")`,$acc1 + shr \$16,$s0 + xor $t4,$t0 + shr \$16,$s1 + movzb `&lo("$s3")`,$t4 + + shl \$8,$acc2 + xor $t5,$t1 + shl \$8,$acc0 + movzb `&lo("$s0")`,$t5 + movzb ($sbox,$acc1,1),$acc1 #$t0 + xor $acc2,$t2 + movzb `&lo("$s1")`,$acc2 + + shl \$16,$acc1 + xor $acc0,$t3 + movzb ($sbox,$t4,1),$t4 #$t1 + movzb `&hi("$s1")`,$acc0 + movzb ($sbox,$acc2,1),$acc2 #$t3 + xor $acc1,$t0 + movzb ($sbox,$t5,1),$t5 #$t2 + movzb `&hi("$s2")`,$acc1 + + shl \$16,$acc2 + shl \$16,$t4 + shl \$16,$t5 + xor $acc2,$t3 + movzb `&hi("$s3")`,$acc2 + xor $t4,$t1 + shr \$8,$s0 + xor $t5,$t2 + + movzb ($sbox,$acc0,1),$acc0 #$t0 + movzb ($sbox,$acc1,1),$s1 #$t1 + movzb ($sbox,$acc2,1),$s2 #$t2 + movzb ($sbox,$s0,1),$s3 #$t3 + + mov $t0,$s0 + shl \$24,$acc0 + shl \$24,$s1 + shl \$24,$s2 + xor $acc0,$s0 + shl \$24,$s3 + xor $t1,$s1 + xor $t2,$s2 + xor $t3,$s3 +___ +} + +# parallelized version! input is pair of 64-bit values: %rax=s1.s0 +# and %rcx=s3.s2, output is four 32-bit values in %eax=s0, %ebx=s1, +# %ecx=s2 and %edx=s3. +sub dectransform() +{ my ($tp10,$tp20,$tp40,$tp80,$acc0)=("%rax","%r8", "%r9", "%r10","%rbx"); + my ($tp18,$tp28,$tp48,$tp88,$acc8)=("%rcx","%r11","%r12","%r13","%rdx"); + my $prefetch = shift; + +$code.=<<___; + mov $mask80,$tp40 + mov $mask80,$tp48 + and $tp10,$tp40 + and $tp18,$tp48 + mov $tp40,$acc0 + mov $tp48,$acc8 + shr \$7,$tp40 + lea ($tp10,$tp10),$tp20 + shr \$7,$tp48 + lea ($tp18,$tp18),$tp28 + sub $tp40,$acc0 + sub $tp48,$acc8 + and $maskfe,$tp20 + and $maskfe,$tp28 + and $mask1b,$acc0 + and $mask1b,$acc8 + xor $acc0,$tp20 + xor $acc8,$tp28 + mov $mask80,$tp80 + mov $mask80,$tp88 + + and $tp20,$tp80 + and $tp28,$tp88 + mov $tp80,$acc0 + mov $tp88,$acc8 + shr \$7,$tp80 + lea ($tp20,$tp20),$tp40 + shr \$7,$tp88 + lea ($tp28,$tp28),$tp48 + sub $tp80,$acc0 + sub $tp88,$acc8 + and $maskfe,$tp40 + and $maskfe,$tp48 + and $mask1b,$acc0 + and $mask1b,$acc8 + xor $acc0,$tp40 + xor $acc8,$tp48 + mov $mask80,$tp80 + mov $mask80,$tp88 + + and $tp40,$tp80 + and $tp48,$tp88 + mov $tp80,$acc0 + mov $tp88,$acc8 + shr \$7,$tp80 + xor $tp10,$tp20 # tp2^=tp1 + shr \$7,$tp88 + xor $tp18,$tp28 # tp2^=tp1 + sub $tp80,$acc0 + sub $tp88,$acc8 + lea ($tp40,$tp40),$tp80 + lea ($tp48,$tp48),$tp88 + xor $tp10,$tp40 # tp4^=tp1 + xor $tp18,$tp48 # tp4^=tp1 + and $maskfe,$tp80 + and $maskfe,$tp88 + and $mask1b,$acc0 + and $mask1b,$acc8 + xor $acc0,$tp80 + xor $acc8,$tp88 + + xor $tp80,$tp10 # tp1^=tp8 + xor $tp88,$tp18 # tp1^=tp8 + xor $tp80,$tp20 # tp2^tp1^=tp8 + xor $tp88,$tp28 # tp2^tp1^=tp8 + mov $tp10,$acc0 + mov $tp18,$acc8 + xor $tp80,$tp40 # tp4^tp1^=tp8 + shr \$32,$acc0 + xor $tp88,$tp48 # tp4^tp1^=tp8 + shr \$32,$acc8 + xor $tp20,$tp80 # tp8^=tp8^tp2^tp1=tp2^tp1 + rol \$8,`&LO("$tp10")` # ROTATE(tp1^tp8,8) + xor $tp28,$tp88 # tp8^=tp8^tp2^tp1=tp2^tp1 + rol \$8,`&LO("$tp18")` # ROTATE(tp1^tp8,8) + xor $tp40,$tp80 # tp2^tp1^=tp8^tp4^tp1=tp8^tp4^tp2 + rol \$8,`&LO("$acc0")` # ROTATE(tp1^tp8,8) + xor $tp48,$tp88 # tp2^tp1^=tp8^tp4^tp1=tp8^tp4^tp2 + + rol \$8,`&LO("$acc8")` # ROTATE(tp1^tp8,8) + xor `&LO("$tp80")`,`&LO("$tp10")` + shr \$32,$tp80 + xor `&LO("$tp88")`,`&LO("$tp18")` + shr \$32,$tp88 + xor `&LO("$tp80")`,`&LO("$acc0")` + xor `&LO("$tp88")`,`&LO("$acc8")` + + mov $tp20,$tp80 + rol \$24,`&LO("$tp20")` # ROTATE(tp2^tp1^tp8,24) + mov $tp28,$tp88 + rol \$24,`&LO("$tp28")` # ROTATE(tp2^tp1^tp8,24) + shr \$32,$tp80 + xor `&LO("$tp20")`,`&LO("$tp10")` + shr \$32,$tp88 + xor `&LO("$tp28")`,`&LO("$tp18")` + rol \$24,`&LO("$tp80")` # ROTATE(tp2^tp1^tp8,24) + mov $tp40,$tp20 + rol \$24,`&LO("$tp88")` # ROTATE(tp2^tp1^tp8,24) + mov $tp48,$tp28 + shr \$32,$tp20 + xor `&LO("$tp80")`,`&LO("$acc0")` + shr \$32,$tp28 + xor `&LO("$tp88")`,`&LO("$acc8")` + + `"mov 0($sbox),$mask80" if ($prefetch)` + rol \$16,`&LO("$tp40")` # ROTATE(tp4^tp1^tp8,16) + `"mov 64($sbox),$maskfe" if ($prefetch)` + rol \$16,`&LO("$tp48")` # ROTATE(tp4^tp1^tp8,16) + `"mov 128($sbox),$mask1b" if ($prefetch)` + rol \$16,`&LO("$tp20")` # ROTATE(tp4^tp1^tp8,16) + `"mov 192($sbox),$tp80" if ($prefetch)` + xor `&LO("$tp40")`,`&LO("$tp10")` + rol \$16,`&LO("$tp28")` # ROTATE(tp4^tp1^tp8,16) + xor `&LO("$tp48")`,`&LO("$tp18")` + `"mov 256($sbox),$tp88" if ($prefetch)` + xor `&LO("$tp20")`,`&LO("$acc0")` + xor `&LO("$tp28")`,`&LO("$acc8")` +___ +} + +$code.=<<___; +.type _x86_64_AES_decrypt_compact,\@abi-omnipotent +.align 16 +_x86_64_AES_decrypt_compact: + lea 128($sbox),$inp # size optimization + mov 0-128($inp),$acc1 # prefetch Td4 + mov 32-128($inp),$acc2 + mov 64-128($inp),$t0 + mov 96-128($inp),$t1 + mov 128-128($inp),$acc1 + mov 160-128($inp),$acc2 + mov 192-128($inp),$t0 + mov 224-128($inp),$t1 + jmp .Ldec_loop_compact + +.align 16 +.Ldec_loop_compact: + xor 0($key),$s0 # xor with key + xor 4($key),$s1 + xor 8($key),$s2 + xor 12($key),$s3 + lea 16($key),$key +___ + &deccompactvert(); +$code.=<<___; + cmp 16(%rsp),$key + je .Ldec_compact_done + + mov 256+0($sbox),$mask80 + shl \$32,%rbx + shl \$32,%rdx + mov 256+8($sbox),$maskfe + or %rbx,%rax + or %rdx,%rcx + mov 256+16($sbox),$mask1b +___ + &dectransform(1); +$code.=<<___; + jmp .Ldec_loop_compact +.align 16 +.Ldec_compact_done: + xor 0($key),$s0 + xor 4($key),$s1 + xor 8($key),$s2 + xor 12($key),$s3 + .byte 0xf3,0xc3 # rep ret +.size _x86_64_AES_decrypt_compact,.-_x86_64_AES_decrypt_compact +___ + +# void asm_AES_decrypt (const void *inp,void *out,const AES_KEY *key); +$code.=<<___; +.align 16 +.globl asm_AES_decrypt +.type asm_AES_decrypt,\@function,3 +.hidden asm_AES_decrypt +asm_AES_decrypt: + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + + # allocate frame "above" key schedule + mov %rsp,%r10 + lea -63(%rdx),%rcx # %rdx is key argument + and \$-64,%rsp + sub %rsp,%rcx + neg %rcx + and \$0x3c0,%rcx + sub %rcx,%rsp + sub \$32,%rsp + + mov %rsi,16(%rsp) # save out + mov %r10,24(%rsp) # save real stack pointer +.Ldec_prologue: + + mov %rdx,$key + mov 240($key),$rnds # load rounds + + mov 0(%rdi),$s0 # load input vector + mov 4(%rdi),$s1 + mov 8(%rdi),$s2 + mov 12(%rdi),$s3 + + shl \$4,$rnds + lea ($key,$rnds),%rbp + mov $key,(%rsp) # key schedule + mov %rbp,8(%rsp) # end of key schedule + + # pick Td4 copy which can't "overlap" with stack frame or key schedule + lea .LAES_Td+2048(%rip),$sbox + lea 768(%rsp),%rbp + sub $sbox,%rbp + and \$0x300,%rbp + lea ($sbox,%rbp),$sbox + shr \$3,%rbp # recall "magic" constants! + add %rbp,$sbox + + call _x86_64_AES_decrypt_compact + + mov 16(%rsp),$out # restore out + mov 24(%rsp),%rsi # restore saved stack pointer + mov $s0,0($out) # write output vector + mov $s1,4($out) + mov $s2,8($out) + mov $s3,12($out) + + mov (%rsi),%r15 + mov 8(%rsi),%r14 + mov 16(%rsi),%r13 + mov 24(%rsi),%r12 + mov 32(%rsi),%rbp + mov 40(%rsi),%rbx + lea 48(%rsi),%rsp +.Ldec_epilogue: + ret +.size asm_AES_decrypt,.-asm_AES_decrypt +___ +#------------------------------------------------------------------# + +sub enckey() +{ +$code.=<<___; + movz %dl,%esi # rk[i]>>0 + movzb -128(%rbp,%rsi),%ebx + movz %dh,%esi # rk[i]>>8 + shl \$24,%ebx + xor %ebx,%eax + + movzb -128(%rbp,%rsi),%ebx + shr \$16,%edx + movz %dl,%esi # rk[i]>>16 + xor %ebx,%eax + + movzb -128(%rbp,%rsi),%ebx + movz %dh,%esi # rk[i]>>24 + shl \$8,%ebx + xor %ebx,%eax + + movzb -128(%rbp,%rsi),%ebx + shl \$16,%ebx + xor %ebx,%eax + + xor 1024-128(%rbp,%rcx,4),%eax # rcon +___ +} + +# int asm_AES_set_encrypt_key(const unsigned char *userKey, const int bits, AES_KEY *key) +$code.=<<___; +.align 16 +.globl asm_AES_set_encrypt_key +.type asm_AES_set_encrypt_key,\@function,3 +asm_AES_set_encrypt_key: + push %rbx + push %rbp + push %r12 # redundant, but allows to share + push %r13 # exception handler... + push %r14 + push %r15 + sub \$8,%rsp +.Lenc_key_prologue: + + call _x86_64_AES_set_encrypt_key + + mov 40(%rsp),%rbp + mov 48(%rsp),%rbx + add \$56,%rsp +.Lenc_key_epilogue: + ret +.size asm_AES_set_encrypt_key,.-asm_AES_set_encrypt_key + +.type _x86_64_AES_set_encrypt_key,\@abi-omnipotent +.align 16 +_x86_64_AES_set_encrypt_key: + mov %esi,%ecx # %ecx=bits + mov %rdi,%rsi # %rsi=userKey + mov %rdx,%rdi # %rdi=key + + test \$-1,%rsi + jz .Lbadpointer + test \$-1,%rdi + jz .Lbadpointer + + lea .LAES_Te(%rip),%rbp + lea 2048+128(%rbp),%rbp + + # prefetch Te4 + mov 0-128(%rbp),%eax + mov 32-128(%rbp),%ebx + mov 64-128(%rbp),%r8d + mov 96-128(%rbp),%edx + mov 128-128(%rbp),%eax + mov 160-128(%rbp),%ebx + mov 192-128(%rbp),%r8d + mov 224-128(%rbp),%edx + + cmp \$128,%ecx + je .L10rounds + cmp \$192,%ecx + je .L12rounds + cmp \$256,%ecx + je .L14rounds + mov \$-2,%rax # invalid number of bits + jmp .Lexit + +.L10rounds: + mov 0(%rsi),%rax # copy first 4 dwords + mov 8(%rsi),%rdx + mov %rax,0(%rdi) + mov %rdx,8(%rdi) + + shr \$32,%rdx + xor %ecx,%ecx + jmp .L10shortcut +.align 4 +.L10loop: + mov 0(%rdi),%eax # rk[0] + mov 12(%rdi),%edx # rk[3] +.L10shortcut: +___ + &enckey (); +$code.=<<___; + mov %eax,16(%rdi) # rk[4] + xor 4(%rdi),%eax + mov %eax,20(%rdi) # rk[5] + xor 8(%rdi),%eax + mov %eax,24(%rdi) # rk[6] + xor 12(%rdi),%eax + mov %eax,28(%rdi) # rk[7] + add \$1,%ecx + lea 16(%rdi),%rdi + cmp \$10,%ecx + jl .L10loop + + movl \$10,80(%rdi) # setup number of rounds + xor %rax,%rax + jmp .Lexit + +.L12rounds: + mov 0(%rsi),%rax # copy first 6 dwords + mov 8(%rsi),%rbx + mov 16(%rsi),%rdx + mov %rax,0(%rdi) + mov %rbx,8(%rdi) + mov %rdx,16(%rdi) + + shr \$32,%rdx + xor %ecx,%ecx + jmp .L12shortcut +.align 4 +.L12loop: + mov 0(%rdi),%eax # rk[0] + mov 20(%rdi),%edx # rk[5] +.L12shortcut: +___ + &enckey (); +$code.=<<___; + mov %eax,24(%rdi) # rk[6] + xor 4(%rdi),%eax + mov %eax,28(%rdi) # rk[7] + xor 8(%rdi),%eax + mov %eax,32(%rdi) # rk[8] + xor 12(%rdi),%eax + mov %eax,36(%rdi) # rk[9] + + cmp \$7,%ecx + je .L12break + add \$1,%ecx + + xor 16(%rdi),%eax + mov %eax,40(%rdi) # rk[10] + xor 20(%rdi),%eax + mov %eax,44(%rdi) # rk[11] + + lea 24(%rdi),%rdi + jmp .L12loop +.L12break: + movl \$12,72(%rdi) # setup number of rounds + xor %rax,%rax + jmp .Lexit + +.L14rounds: + mov 0(%rsi),%rax # copy first 8 dwords + mov 8(%rsi),%rbx + mov 16(%rsi),%rcx + mov 24(%rsi),%rdx + mov %rax,0(%rdi) + mov %rbx,8(%rdi) + mov %rcx,16(%rdi) + mov %rdx,24(%rdi) + + shr \$32,%rdx + xor %ecx,%ecx + jmp .L14shortcut +.align 4 +.L14loop: + mov 0(%rdi),%eax # rk[0] + mov 28(%rdi),%edx # rk[4] +.L14shortcut: +___ + &enckey (); +$code.=<<___; + mov %eax,32(%rdi) # rk[8] + xor 4(%rdi),%eax + mov %eax,36(%rdi) # rk[9] + xor 8(%rdi),%eax + mov %eax,40(%rdi) # rk[10] + xor 12(%rdi),%eax + mov %eax,44(%rdi) # rk[11] + + cmp \$6,%ecx + je .L14break + add \$1,%ecx + + mov %eax,%edx + mov 16(%rdi),%eax # rk[4] + movz %dl,%esi # rk[11]>>0 + movzb -128(%rbp,%rsi),%ebx + movz %dh,%esi # rk[11]>>8 + xor %ebx,%eax + + movzb -128(%rbp,%rsi),%ebx + shr \$16,%edx + shl \$8,%ebx + movz %dl,%esi # rk[11]>>16 + xor %ebx,%eax + + movzb -128(%rbp,%rsi),%ebx + movz %dh,%esi # rk[11]>>24 + shl \$16,%ebx + xor %ebx,%eax + + movzb -128(%rbp,%rsi),%ebx + shl \$24,%ebx + xor %ebx,%eax + + mov %eax,48(%rdi) # rk[12] + xor 20(%rdi),%eax + mov %eax,52(%rdi) # rk[13] + xor 24(%rdi),%eax + mov %eax,56(%rdi) # rk[14] + xor 28(%rdi),%eax + mov %eax,60(%rdi) # rk[15] + + lea 32(%rdi),%rdi + jmp .L14loop +.L14break: + movl \$14,48(%rdi) # setup number of rounds + xor %rax,%rax + jmp .Lexit + +.Lbadpointer: + mov \$-1,%rax +.Lexit: + .byte 0xf3,0xc3 # rep ret +.size _x86_64_AES_set_encrypt_key,.-_x86_64_AES_set_encrypt_key +___ + +sub deckey_ref() +{ my ($i,$ptr,$te,$td) = @_; + my ($tp1,$tp2,$tp4,$tp8,$acc)=("%eax","%ebx","%edi","%edx","%r8d"); +$code.=<<___; + mov $i($ptr),$tp1 + mov $tp1,$acc + and \$0x80808080,$acc + mov $acc,$tp4 + shr \$7,$tp4 + lea 0($tp1,$tp1),$tp2 + sub $tp4,$acc + and \$0xfefefefe,$tp2 + and \$0x1b1b1b1b,$acc + xor $tp2,$acc + mov $acc,$tp2 + + and \$0x80808080,$acc + mov $acc,$tp8 + shr \$7,$tp8 + lea 0($tp2,$tp2),$tp4 + sub $tp8,$acc + and \$0xfefefefe,$tp4 + and \$0x1b1b1b1b,$acc + xor $tp1,$tp2 # tp2^tp1 + xor $tp4,$acc + mov $acc,$tp4 + + and \$0x80808080,$acc + mov $acc,$tp8 + shr \$7,$tp8 + sub $tp8,$acc + lea 0($tp4,$tp4),$tp8 + xor $tp1,$tp4 # tp4^tp1 + and \$0xfefefefe,$tp8 + and \$0x1b1b1b1b,$acc + xor $acc,$tp8 + + xor $tp8,$tp1 # tp1^tp8 + rol \$8,$tp1 # ROTATE(tp1^tp8,8) + xor $tp8,$tp2 # tp2^tp1^tp8 + xor $tp8,$tp4 # tp4^tp1^tp8 + xor $tp2,$tp8 + xor $tp4,$tp8 # tp8^(tp8^tp4^tp1)^(tp8^tp2^tp1)=tp8^tp4^tp2 + + xor $tp8,$tp1 + rol \$24,$tp2 # ROTATE(tp2^tp1^tp8,24) + xor $tp2,$tp1 + rol \$16,$tp4 # ROTATE(tp4^tp1^tp8,16) + xor $tp4,$tp1 + + mov $tp1,$i($ptr) +___ +} + +# int asm_AES_set_decrypt_key(const unsigned char *userKey, const int bits, AES_KEY *key) +$code.=<<___; +.align 16 +.globl asm_AES_set_decrypt_key +.type asm_AES_set_decrypt_key,\@function,3 +asm_AES_set_decrypt_key: + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + push %rdx # save key schedule +.Ldec_key_prologue: + + call _x86_64_AES_set_encrypt_key + mov (%rsp),%r8 # restore key schedule + cmp \$0,%eax + jne .Labort + + mov 240(%r8),%r14d # pull number of rounds + xor %rdi,%rdi + lea (%rdi,%r14d,4),%rcx + mov %r8,%rsi + lea (%r8,%rcx,4),%rdi # pointer to last chunk +.align 4 +.Linvert: + mov 0(%rsi),%rax + mov 8(%rsi),%rbx + mov 0(%rdi),%rcx + mov 8(%rdi),%rdx + mov %rax,0(%rdi) + mov %rbx,8(%rdi) + mov %rcx,0(%rsi) + mov %rdx,8(%rsi) + lea 16(%rsi),%rsi + lea -16(%rdi),%rdi + cmp %rsi,%rdi + jne .Linvert + + lea .LAES_Te+2048+1024(%rip),%rax # rcon + + mov 40(%rax),$mask80 + mov 48(%rax),$maskfe + mov 56(%rax),$mask1b + + mov %r8,$key + sub \$1,%r14d +.align 4 +.Lpermute: + lea 16($key),$key + mov 0($key),%rax + mov 8($key),%rcx +___ + &dectransform (); +$code.=<<___; + mov %eax,0($key) + mov %ebx,4($key) + mov %ecx,8($key) + mov %edx,12($key) + sub \$1,%r14d + jnz .Lpermute + + xor %rax,%rax +.Labort: + mov 8(%rsp),%r15 + mov 16(%rsp),%r14 + mov 24(%rsp),%r13 + mov 32(%rsp),%r12 + mov 40(%rsp),%rbp + mov 48(%rsp),%rbx + add \$56,%rsp +.Ldec_key_epilogue: + ret +.size asm_AES_set_decrypt_key,.-asm_AES_set_decrypt_key +___ + +# void asm_AES_cbc_encrypt (const void char *inp, unsigned char *out, +# size_t length, const AES_KEY *key, +# unsigned char *ivp,const int enc); +{ +# stack frame layout +# -8(%rsp) return address +my $keyp="0(%rsp)"; # one to pass as $key +my $keyend="8(%rsp)"; # &(keyp->rd_key[4*keyp->rounds]) +my $_rsp="16(%rsp)"; # saved %rsp +my $_inp="24(%rsp)"; # copy of 1st parameter, inp +my $_out="32(%rsp)"; # copy of 2nd parameter, out +my $_len="40(%rsp)"; # copy of 3rd parameter, length +my $_key="48(%rsp)"; # copy of 4th parameter, key +my $_ivp="56(%rsp)"; # copy of 5th parameter, ivp +my $ivec="64(%rsp)"; # ivec[16] +my $aes_key="80(%rsp)"; # copy of aes_key +my $mark="80+240(%rsp)"; # copy of aes_key->rounds + +$code.=<<___; +.align 16 +.globl asm_AES_cbc_encrypt +.type asm_AES_cbc_encrypt,\@function,6 +.extern OPENSSL_ia32cap_P +.hidden asm_AES_cbc_encrypt +asm_AES_cbc_encrypt: + cmp \$0,%rdx # check length + je .Lcbc_epilogue + pushfq + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 +.Lcbc_prologue: + + cld + mov %r9d,%r9d # clear upper half of enc + + lea .LAES_Te(%rip),$sbox + cmp \$0,%r9 + jne .Lcbc_picked_te + lea .LAES_Td(%rip),$sbox +.Lcbc_picked_te: + + mov OPENSSL_ia32cap_P(%rip),%r10d + cmp \$$speed_limit,%rdx + jb .Lcbc_slow_prologue + test \$15,%rdx + jnz .Lcbc_slow_prologue + bt \$28,%r10d + jc .Lcbc_slow_prologue + + # allocate aligned stack frame... + lea -88-248(%rsp),$key + and \$-64,$key + + # ... and make sure it doesn't alias with AES_T[ed] modulo 4096 + mov $sbox,%r10 + lea 2304($sbox),%r11 + mov $key,%r12 + and \$0xFFF,%r10 # s = $sbox&0xfff + and \$0xFFF,%r11 # e = ($sbox+2048)&0xfff + and \$0xFFF,%r12 # p = %rsp&0xfff + + cmp %r11,%r12 # if (p=>e) %rsp =- (p-e); + jb .Lcbc_te_break_out + sub %r11,%r12 + sub %r12,$key + jmp .Lcbc_te_ok +.Lcbc_te_break_out: # else %rsp -= (p-s)&0xfff + framesz + sub %r10,%r12 + and \$0xFFF,%r12 + add \$320,%r12 + sub %r12,$key +.align 4 +.Lcbc_te_ok: + + xchg %rsp,$key + #add \$8,%rsp # reserve for return address! + mov $key,$_rsp # save %rsp +.Lcbc_fast_body: + mov %rdi,$_inp # save copy of inp + mov %rsi,$_out # save copy of out + mov %rdx,$_len # save copy of len + mov %rcx,$_key # save copy of key + mov %r8,$_ivp # save copy of ivp + movl \$0,$mark # copy of aes_key->rounds = 0; + mov %r8,%rbp # rearrange input arguments + mov %r9,%rbx + mov %rsi,$out + mov %rdi,$inp + mov %rcx,$key + + mov 240($key),%eax # key->rounds + # do we copy key schedule to stack? + mov $key,%r10 + sub $sbox,%r10 + and \$0xfff,%r10 + cmp \$2304,%r10 + jb .Lcbc_do_ecopy + cmp \$4096-248,%r10 + jb .Lcbc_skip_ecopy +.align 4 +.Lcbc_do_ecopy: + mov $key,%rsi + lea $aes_key,%rdi + lea $aes_key,$key + mov \$240/8,%ecx + .long 0x90A548F3 # rep movsq + mov %eax,(%rdi) # copy aes_key->rounds +.Lcbc_skip_ecopy: + mov $key,$keyp # save key pointer + + mov \$18,%ecx +.align 4 +.Lcbc_prefetch_te: + mov 0($sbox),%r10 + mov 32($sbox),%r11 + mov 64($sbox),%r12 + mov 96($sbox),%r13 + lea 128($sbox),$sbox + sub \$1,%ecx + jnz .Lcbc_prefetch_te + lea -2304($sbox),$sbox + + cmp \$0,%rbx + je .LFAST_DECRYPT + +#----------------------------- ENCRYPT -----------------------------# + mov 0(%rbp),$s0 # load iv + mov 4(%rbp),$s1 + mov 8(%rbp),$s2 + mov 12(%rbp),$s3 + +.align 4 +.Lcbc_fast_enc_loop: + xor 0($inp),$s0 + xor 4($inp),$s1 + xor 8($inp),$s2 + xor 12($inp),$s3 + mov $keyp,$key # restore key + mov $inp,$_inp # if ($verticalspin) save inp + + call _x86_64_AES_encrypt + + mov $_inp,$inp # if ($verticalspin) restore inp + mov $_len,%r10 + mov $s0,0($out) + mov $s1,4($out) + mov $s2,8($out) + mov $s3,12($out) + + lea 16($inp),$inp + lea 16($out),$out + sub \$16,%r10 + test \$-16,%r10 + mov %r10,$_len + jnz .Lcbc_fast_enc_loop + mov $_ivp,%rbp # restore ivp + mov $s0,0(%rbp) # save ivec + mov $s1,4(%rbp) + mov $s2,8(%rbp) + mov $s3,12(%rbp) + + jmp .Lcbc_fast_cleanup + +#----------------------------- DECRYPT -----------------------------# +.align 16 +.LFAST_DECRYPT: + cmp $inp,$out + je .Lcbc_fast_dec_in_place + + mov %rbp,$ivec +.align 4 +.Lcbc_fast_dec_loop: + mov 0($inp),$s0 # read input + mov 4($inp),$s1 + mov 8($inp),$s2 + mov 12($inp),$s3 + mov $keyp,$key # restore key + mov $inp,$_inp # if ($verticalspin) save inp + + call _x86_64_AES_decrypt + + mov $ivec,%rbp # load ivp + mov $_inp,$inp # if ($verticalspin) restore inp + mov $_len,%r10 # load len + xor 0(%rbp),$s0 # xor iv + xor 4(%rbp),$s1 + xor 8(%rbp),$s2 + xor 12(%rbp),$s3 + mov $inp,%rbp # current input, next iv + + sub \$16,%r10 + mov %r10,$_len # update len + mov %rbp,$ivec # update ivp + + mov $s0,0($out) # write output + mov $s1,4($out) + mov $s2,8($out) + mov $s3,12($out) + + lea 16($inp),$inp + lea 16($out),$out + jnz .Lcbc_fast_dec_loop + mov $_ivp,%r12 # load user ivp + mov 0(%rbp),%r10 # load iv + mov 8(%rbp),%r11 + mov %r10,0(%r12) # copy back to user + mov %r11,8(%r12) + jmp .Lcbc_fast_cleanup + +.align 16 +.Lcbc_fast_dec_in_place: + mov 0(%rbp),%r10 # copy iv to stack + mov 8(%rbp),%r11 + mov %r10,0+$ivec + mov %r11,8+$ivec +.align 4 +.Lcbc_fast_dec_in_place_loop: + mov 0($inp),$s0 # load input + mov 4($inp),$s1 + mov 8($inp),$s2 + mov 12($inp),$s3 + mov $keyp,$key # restore key + mov $inp,$_inp # if ($verticalspin) save inp + + call _x86_64_AES_decrypt + + mov $_inp,$inp # if ($verticalspin) restore inp + mov $_len,%r10 + xor 0+$ivec,$s0 + xor 4+$ivec,$s1 + xor 8+$ivec,$s2 + xor 12+$ivec,$s3 + + mov 0($inp),%r11 # load input + mov 8($inp),%r12 + sub \$16,%r10 + jz .Lcbc_fast_dec_in_place_done + + mov %r11,0+$ivec # copy input to iv + mov %r12,8+$ivec + + mov $s0,0($out) # save output [zaps input] + mov $s1,4($out) + mov $s2,8($out) + mov $s3,12($out) + + lea 16($inp),$inp + lea 16($out),$out + mov %r10,$_len + jmp .Lcbc_fast_dec_in_place_loop +.Lcbc_fast_dec_in_place_done: + mov $_ivp,%rdi + mov %r11,0(%rdi) # copy iv back to user + mov %r12,8(%rdi) + + mov $s0,0($out) # save output [zaps input] + mov $s1,4($out) + mov $s2,8($out) + mov $s3,12($out) + +.align 4 +.Lcbc_fast_cleanup: + cmpl \$0,$mark # was the key schedule copied? + lea $aes_key,%rdi + je .Lcbc_exit + mov \$240/8,%ecx + xor %rax,%rax + .long 0x90AB48F3 # rep stosq + + jmp .Lcbc_exit + +#--------------------------- SLOW ROUTINE ---------------------------# +.align 16 +.Lcbc_slow_prologue: + # allocate aligned stack frame... + lea -88(%rsp),%rbp + and \$-64,%rbp + # ... just "above" key schedule + lea -88-63(%rcx),%r10 + sub %rbp,%r10 + neg %r10 + and \$0x3c0,%r10 + sub %r10,%rbp + + xchg %rsp,%rbp + #add \$8,%rsp # reserve for return address! + mov %rbp,$_rsp # save %rsp +.Lcbc_slow_body: + #mov %rdi,$_inp # save copy of inp + #mov %rsi,$_out # save copy of out + #mov %rdx,$_len # save copy of len + #mov %rcx,$_key # save copy of key + mov %r8,$_ivp # save copy of ivp + mov %r8,%rbp # rearrange input arguments + mov %r9,%rbx + mov %rsi,$out + mov %rdi,$inp + mov %rcx,$key + mov %rdx,%r10 + + mov 240($key),%eax + mov $key,$keyp # save key pointer + shl \$4,%eax + lea ($key,%rax),%rax + mov %rax,$keyend + + # pick Te4 copy which can't "overlap" with stack frame or key scdedule + lea 2048($sbox),$sbox + lea 768-8(%rsp),%rax + sub $sbox,%rax + and \$0x300,%rax + lea ($sbox,%rax),$sbox + + cmp \$0,%rbx + je .LSLOW_DECRYPT + +#--------------------------- SLOW ENCRYPT ---------------------------# + test \$-16,%r10 # check upon length + mov 0(%rbp),$s0 # load iv + mov 4(%rbp),$s1 + mov 8(%rbp),$s2 + mov 12(%rbp),$s3 + jz .Lcbc_slow_enc_tail # short input... + +.align 4 +.Lcbc_slow_enc_loop: + xor 0($inp),$s0 + xor 4($inp),$s1 + xor 8($inp),$s2 + xor 12($inp),$s3 + mov $keyp,$key # restore key + mov $inp,$_inp # save inp + mov $out,$_out # save out + mov %r10,$_len # save len + + call _x86_64_AES_encrypt_compact + + mov $_inp,$inp # restore inp + mov $_out,$out # restore out + mov $_len,%r10 # restore len + mov $s0,0($out) + mov $s1,4($out) + mov $s2,8($out) + mov $s3,12($out) + + lea 16($inp),$inp + lea 16($out),$out + sub \$16,%r10 + test \$-16,%r10 + jnz .Lcbc_slow_enc_loop + test \$15,%r10 + jnz .Lcbc_slow_enc_tail + mov $_ivp,%rbp # restore ivp + mov $s0,0(%rbp) # save ivec + mov $s1,4(%rbp) + mov $s2,8(%rbp) + mov $s3,12(%rbp) + + jmp .Lcbc_exit + +.align 4 +.Lcbc_slow_enc_tail: + mov %rax,%r11 + mov %rcx,%r12 + mov %r10,%rcx + mov $inp,%rsi + mov $out,%rdi + .long 0x9066A4F3 # rep movsb + mov \$16,%rcx # zero tail + sub %r10,%rcx + xor %rax,%rax + .long 0x9066AAF3 # rep stosb + mov $out,$inp # this is not a mistake! + mov \$16,%r10 # len=16 + mov %r11,%rax + mov %r12,%rcx + jmp .Lcbc_slow_enc_loop # one more spin... +#--------------------------- SLOW DECRYPT ---------------------------# +.align 16 +.LSLOW_DECRYPT: + shr \$3,%rax + add %rax,$sbox # recall "magic" constants! + + mov 0(%rbp),%r11 # copy iv to stack + mov 8(%rbp),%r12 + mov %r11,0+$ivec + mov %r12,8+$ivec + +.align 4 +.Lcbc_slow_dec_loop: + mov 0($inp),$s0 # load input + mov 4($inp),$s1 + mov 8($inp),$s2 + mov 12($inp),$s3 + mov $keyp,$key # restore key + mov $inp,$_inp # save inp + mov $out,$_out # save out + mov %r10,$_len # save len + + call _x86_64_AES_decrypt_compact + + mov $_inp,$inp # restore inp + mov $_out,$out # restore out + mov $_len,%r10 + xor 0+$ivec,$s0 + xor 4+$ivec,$s1 + xor 8+$ivec,$s2 + xor 12+$ivec,$s3 + + mov 0($inp),%r11 # load input + mov 8($inp),%r12 + sub \$16,%r10 + jc .Lcbc_slow_dec_partial + jz .Lcbc_slow_dec_done + + mov %r11,0+$ivec # copy input to iv + mov %r12,8+$ivec + + mov $s0,0($out) # save output [can zap input] + mov $s1,4($out) + mov $s2,8($out) + mov $s3,12($out) + + lea 16($inp),$inp + lea 16($out),$out + jmp .Lcbc_slow_dec_loop +.Lcbc_slow_dec_done: + mov $_ivp,%rdi + mov %r11,0(%rdi) # copy iv back to user + mov %r12,8(%rdi) + + mov $s0,0($out) # save output [can zap input] + mov $s1,4($out) + mov $s2,8($out) + mov $s3,12($out) + + jmp .Lcbc_exit + +.align 4 +.Lcbc_slow_dec_partial: + mov $_ivp,%rdi + mov %r11,0(%rdi) # copy iv back to user + mov %r12,8(%rdi) + + mov $s0,0+$ivec # save output to stack + mov $s1,4+$ivec + mov $s2,8+$ivec + mov $s3,12+$ivec + + mov $out,%rdi + lea $ivec,%rsi + lea 16(%r10),%rcx + .long 0x9066A4F3 # rep movsb + jmp .Lcbc_exit + +.align 16 +.Lcbc_exit: + mov $_rsp,%rsi + mov (%rsi),%r15 + mov 8(%rsi),%r14 + mov 16(%rsi),%r13 + mov 24(%rsi),%r12 + mov 32(%rsi),%rbp + mov 40(%rsi),%rbx + lea 48(%rsi),%rsp +.Lcbc_popfq: + popfq +.Lcbc_epilogue: + ret +.size asm_AES_cbc_encrypt,.-asm_AES_cbc_encrypt +___ +} + +$code.=<<___; +.align 64 +.LAES_Te: +___ + &_data_word(0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6); + &_data_word(0x0df2f2ff, 0xbd6b6bd6, 0xb16f6fde, 0x54c5c591); + &_data_word(0x50303060, 0x03010102, 0xa96767ce, 0x7d2b2b56); + &_data_word(0x19fefee7, 0x62d7d7b5, 0xe6abab4d, 0x9a7676ec); + &_data_word(0x45caca8f, 0x9d82821f, 0x40c9c989, 0x877d7dfa); + &_data_word(0x15fafaef, 0xeb5959b2, 0xc947478e, 0x0bf0f0fb); + &_data_word(0xecadad41, 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45); + &_data_word(0xbf9c9c23, 0xf7a4a453, 0x967272e4, 0x5bc0c09b); + &_data_word(0xc2b7b775, 0x1cfdfde1, 0xae93933d, 0x6a26264c); + &_data_word(0x5a36366c, 0x413f3f7e, 0x02f7f7f5, 0x4fcccc83); + &_data_word(0x5c343468, 0xf4a5a551, 0x34e5e5d1, 0x08f1f1f9); + &_data_word(0x937171e2, 0x73d8d8ab, 0x53313162, 0x3f15152a); + &_data_word(0x0c040408, 0x52c7c795, 0x65232346, 0x5ec3c39d); + &_data_word(0x28181830, 0xa1969637, 0x0f05050a, 0xb59a9a2f); + &_data_word(0x0907070e, 0x36121224, 0x9b80801b, 0x3de2e2df); + &_data_word(0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea); + &_data_word(0x1b090912, 0x9e83831d, 0x742c2c58, 0x2e1a1a34); + &_data_word(0x2d1b1b36, 0xb26e6edc, 0xee5a5ab4, 0xfba0a05b); + &_data_word(0xf65252a4, 0x4d3b3b76, 0x61d6d6b7, 0xceb3b37d); + &_data_word(0x7b292952, 0x3ee3e3dd, 0x712f2f5e, 0x97848413); + &_data_word(0xf55353a6, 0x68d1d1b9, 0x00000000, 0x2cededc1); + &_data_word(0x60202040, 0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6); + &_data_word(0xbe6a6ad4, 0x46cbcb8d, 0xd9bebe67, 0x4b393972); + &_data_word(0xde4a4a94, 0xd44c4c98, 0xe85858b0, 0x4acfcf85); + &_data_word(0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed); + &_data_word(0xc5434386, 0xd74d4d9a, 0x55333366, 0x94858511); + &_data_word(0xcf45458a, 0x10f9f9e9, 0x06020204, 0x817f7ffe); + &_data_word(0xf05050a0, 0x443c3c78, 0xba9f9f25, 0xe3a8a84b); + &_data_word(0xf35151a2, 0xfea3a35d, 0xc0404080, 0x8a8f8f05); + &_data_word(0xad92923f, 0xbc9d9d21, 0x48383870, 0x04f5f5f1); + &_data_word(0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142); + &_data_word(0x30101020, 0x1affffe5, 0x0ef3f3fd, 0x6dd2d2bf); + &_data_word(0x4ccdcd81, 0x140c0c18, 0x35131326, 0x2fececc3); + &_data_word(0xe15f5fbe, 0xa2979735, 0xcc444488, 0x3917172e); + &_data_word(0x57c4c493, 0xf2a7a755, 0x827e7efc, 0x473d3d7a); + &_data_word(0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6); + &_data_word(0xa06060c0, 0x98818119, 0xd14f4f9e, 0x7fdcdca3); + &_data_word(0x66222244, 0x7e2a2a54, 0xab90903b, 0x8388880b); + &_data_word(0xca46468c, 0x29eeeec7, 0xd3b8b86b, 0x3c141428); + &_data_word(0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad); + &_data_word(0x3be0e0db, 0x56323264, 0x4e3a3a74, 0x1e0a0a14); + &_data_word(0xdb494992, 0x0a06060c, 0x6c242448, 0xe45c5cb8); + &_data_word(0x5dc2c29f, 0x6ed3d3bd, 0xefacac43, 0xa66262c4); + &_data_word(0xa8919139, 0xa4959531, 0x37e4e4d3, 0x8b7979f2); + &_data_word(0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda); + &_data_word(0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949); + &_data_word(0xb46c6cd8, 0xfa5656ac, 0x07f4f4f3, 0x25eaeacf); + &_data_word(0xaf6565ca, 0x8e7a7af4, 0xe9aeae47, 0x18080810); + &_data_word(0xd5baba6f, 0x887878f0, 0x6f25254a, 0x722e2e5c); + &_data_word(0x241c1c38, 0xf1a6a657, 0xc7b4b473, 0x51c6c697); + &_data_word(0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e); + &_data_word(0xdd4b4b96, 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f); + &_data_word(0x907070e0, 0x423e3e7c, 0xc4b5b571, 0xaa6666cc); + &_data_word(0xd8484890, 0x05030306, 0x01f6f6f7, 0x120e0e1c); + &_data_word(0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969); + &_data_word(0x91868617, 0x58c1c199, 0x271d1d3a, 0xb99e9e27); + &_data_word(0x38e1e1d9, 0x13f8f8eb, 0xb398982b, 0x33111122); + &_data_word(0xbb6969d2, 0x70d9d9a9, 0x898e8e07, 0xa7949433); + &_data_word(0xb69b9b2d, 0x221e1e3c, 0x92878715, 0x20e9e9c9); + &_data_word(0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5); + &_data_word(0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a); + &_data_word(0xdabfbf65, 0x31e6e6d7, 0xc6424284, 0xb86868d0); + &_data_word(0xc3414182, 0xb0999929, 0x772d2d5a, 0x110f0f1e); + &_data_word(0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d, 0x3a16162c); + +#Te4 # four copies of Te4 to choose from to avoid L1 aliasing + &data_byte(0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5); + &data_byte(0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76); + &data_byte(0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0); + &data_byte(0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0); + &data_byte(0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc); + &data_byte(0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15); + &data_byte(0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a); + &data_byte(0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75); + &data_byte(0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0); + &data_byte(0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84); + &data_byte(0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b); + &data_byte(0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf); + &data_byte(0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85); + &data_byte(0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8); + &data_byte(0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5); + &data_byte(0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2); + &data_byte(0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17); + &data_byte(0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73); + &data_byte(0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88); + &data_byte(0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb); + &data_byte(0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c); + &data_byte(0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79); + &data_byte(0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9); + &data_byte(0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08); + &data_byte(0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6); + &data_byte(0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a); + &data_byte(0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e); + &data_byte(0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e); + &data_byte(0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94); + &data_byte(0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf); + &data_byte(0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68); + &data_byte(0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16); + + &data_byte(0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5); + &data_byte(0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76); + &data_byte(0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0); + &data_byte(0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0); + &data_byte(0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc); + &data_byte(0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15); + &data_byte(0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a); + &data_byte(0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75); + &data_byte(0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0); + &data_byte(0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84); + &data_byte(0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b); + &data_byte(0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf); + &data_byte(0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85); + &data_byte(0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8); + &data_byte(0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5); + &data_byte(0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2); + &data_byte(0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17); + &data_byte(0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73); + &data_byte(0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88); + &data_byte(0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb); + &data_byte(0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c); + &data_byte(0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79); + &data_byte(0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9); + &data_byte(0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08); + &data_byte(0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6); + &data_byte(0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a); + &data_byte(0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e); + &data_byte(0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e); + &data_byte(0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94); + &data_byte(0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf); + &data_byte(0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68); + &data_byte(0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16); + + &data_byte(0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5); + &data_byte(0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76); + &data_byte(0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0); + &data_byte(0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0); + &data_byte(0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc); + &data_byte(0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15); + &data_byte(0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a); + &data_byte(0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75); + &data_byte(0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0); + &data_byte(0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84); + &data_byte(0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b); + &data_byte(0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf); + &data_byte(0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85); + &data_byte(0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8); + &data_byte(0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5); + &data_byte(0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2); + &data_byte(0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17); + &data_byte(0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73); + &data_byte(0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88); + &data_byte(0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb); + &data_byte(0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c); + &data_byte(0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79); + &data_byte(0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9); + &data_byte(0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08); + &data_byte(0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6); + &data_byte(0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a); + &data_byte(0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e); + &data_byte(0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e); + &data_byte(0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94); + &data_byte(0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf); + &data_byte(0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68); + &data_byte(0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16); + + &data_byte(0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5); + &data_byte(0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76); + &data_byte(0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0); + &data_byte(0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0); + &data_byte(0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc); + &data_byte(0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15); + &data_byte(0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a); + &data_byte(0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75); + &data_byte(0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0); + &data_byte(0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84); + &data_byte(0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b); + &data_byte(0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf); + &data_byte(0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85); + &data_byte(0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8); + &data_byte(0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5); + &data_byte(0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2); + &data_byte(0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17); + &data_byte(0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73); + &data_byte(0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88); + &data_byte(0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb); + &data_byte(0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c); + &data_byte(0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79); + &data_byte(0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9); + &data_byte(0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08); + &data_byte(0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6); + &data_byte(0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a); + &data_byte(0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e); + &data_byte(0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e); + &data_byte(0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94); + &data_byte(0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf); + &data_byte(0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68); + &data_byte(0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16); +#rcon: +$code.=<<___; + .long 0x00000001, 0x00000002, 0x00000004, 0x00000008 + .long 0x00000010, 0x00000020, 0x00000040, 0x00000080 + .long 0x0000001b, 0x00000036, 0x80808080, 0x80808080 + .long 0xfefefefe, 0xfefefefe, 0x1b1b1b1b, 0x1b1b1b1b +___ +$code.=<<___; +.align 64 +.LAES_Td: +___ + &_data_word(0x50a7f451, 0x5365417e, 0xc3a4171a, 0x965e273a); + &_data_word(0xcb6bab3b, 0xf1459d1f, 0xab58faac, 0x9303e34b); + &_data_word(0x55fa3020, 0xf66d76ad, 0x9176cc88, 0x254c02f5); + &_data_word(0xfcd7e54f, 0xd7cb2ac5, 0x80443526, 0x8fa362b5); + &_data_word(0x495ab1de, 0x671bba25, 0x980eea45, 0xe1c0fe5d); + &_data_word(0x02752fc3, 0x12f04c81, 0xa397468d, 0xc6f9d36b); + &_data_word(0xe75f8f03, 0x959c9215, 0xeb7a6dbf, 0xda595295); + &_data_word(0x2d83bed4, 0xd3217458, 0x2969e049, 0x44c8c98e); + &_data_word(0x6a89c275, 0x78798ef4, 0x6b3e5899, 0xdd71b927); + &_data_word(0xb64fe1be, 0x17ad88f0, 0x66ac20c9, 0xb43ace7d); + &_data_word(0x184adf63, 0x82311ae5, 0x60335197, 0x457f5362); + &_data_word(0xe07764b1, 0x84ae6bbb, 0x1ca081fe, 0x942b08f9); + &_data_word(0x58684870, 0x19fd458f, 0x876cde94, 0xb7f87b52); + &_data_word(0x23d373ab, 0xe2024b72, 0x578f1fe3, 0x2aab5566); + &_data_word(0x0728ebb2, 0x03c2b52f, 0x9a7bc586, 0xa50837d3); + &_data_word(0xf2872830, 0xb2a5bf23, 0xba6a0302, 0x5c8216ed); + &_data_word(0x2b1ccf8a, 0x92b479a7, 0xf0f207f3, 0xa1e2694e); + &_data_word(0xcdf4da65, 0xd5be0506, 0x1f6234d1, 0x8afea6c4); + &_data_word(0x9d532e34, 0xa055f3a2, 0x32e18a05, 0x75ebf6a4); + &_data_word(0x39ec830b, 0xaaef6040, 0x069f715e, 0x51106ebd); + &_data_word(0xf98a213e, 0x3d06dd96, 0xae053edd, 0x46bde64d); + &_data_word(0xb58d5491, 0x055dc471, 0x6fd40604, 0xff155060); + &_data_word(0x24fb9819, 0x97e9bdd6, 0xcc434089, 0x779ed967); + &_data_word(0xbd42e8b0, 0x888b8907, 0x385b19e7, 0xdbeec879); + &_data_word(0x470a7ca1, 0xe90f427c, 0xc91e84f8, 0x00000000); + &_data_word(0x83868009, 0x48ed2b32, 0xac70111e, 0x4e725a6c); + &_data_word(0xfbff0efd, 0x5638850f, 0x1ed5ae3d, 0x27392d36); + &_data_word(0x64d90f0a, 0x21a65c68, 0xd1545b9b, 0x3a2e3624); + &_data_word(0xb1670a0c, 0x0fe75793, 0xd296eeb4, 0x9e919b1b); + &_data_word(0x4fc5c080, 0xa220dc61, 0x694b775a, 0x161a121c); + &_data_word(0x0aba93e2, 0xe52aa0c0, 0x43e0223c, 0x1d171b12); + &_data_word(0x0b0d090e, 0xadc78bf2, 0xb9a8b62d, 0xc8a91e14); + &_data_word(0x8519f157, 0x4c0775af, 0xbbdd99ee, 0xfd607fa3); + &_data_word(0x9f2601f7, 0xbcf5725c, 0xc53b6644, 0x347efb5b); + &_data_word(0x7629438b, 0xdcc623cb, 0x68fcedb6, 0x63f1e4b8); + &_data_word(0xcadc31d7, 0x10856342, 0x40229713, 0x2011c684); + &_data_word(0x7d244a85, 0xf83dbbd2, 0x1132f9ae, 0x6da129c7); + &_data_word(0x4b2f9e1d, 0xf330b2dc, 0xec52860d, 0xd0e3c177); + &_data_word(0x6c16b32b, 0x99b970a9, 0xfa489411, 0x2264e947); + &_data_word(0xc48cfca8, 0x1a3ff0a0, 0xd82c7d56, 0xef903322); + &_data_word(0xc74e4987, 0xc1d138d9, 0xfea2ca8c, 0x360bd498); + &_data_word(0xcf81f5a6, 0x28de7aa5, 0x268eb7da, 0xa4bfad3f); + &_data_word(0xe49d3a2c, 0x0d927850, 0x9bcc5f6a, 0x62467e54); + &_data_word(0xc2138df6, 0xe8b8d890, 0x5ef7392e, 0xf5afc382); + &_data_word(0xbe805d9f, 0x7c93d069, 0xa92dd56f, 0xb31225cf); + &_data_word(0x3b99acc8, 0xa77d1810, 0x6e639ce8, 0x7bbb3bdb); + &_data_word(0x097826cd, 0xf418596e, 0x01b79aec, 0xa89a4f83); + &_data_word(0x656e95e6, 0x7ee6ffaa, 0x08cfbc21, 0xe6e815ef); + &_data_word(0xd99be7ba, 0xce366f4a, 0xd4099fea, 0xd67cb029); + &_data_word(0xafb2a431, 0x31233f2a, 0x3094a5c6, 0xc066a235); + &_data_word(0x37bc4e74, 0xa6ca82fc, 0xb0d090e0, 0x15d8a733); + &_data_word(0x4a9804f1, 0xf7daec41, 0x0e50cd7f, 0x2ff69117); + &_data_word(0x8dd64d76, 0x4db0ef43, 0x544daacc, 0xdf0496e4); + &_data_word(0xe3b5d19e, 0x1b886a4c, 0xb81f2cc1, 0x7f516546); + &_data_word(0x04ea5e9d, 0x5d358c01, 0x737487fa, 0x2e410bfb); + &_data_word(0x5a1d67b3, 0x52d2db92, 0x335610e9, 0x1347d66d); + &_data_word(0x8c61d79a, 0x7a0ca137, 0x8e14f859, 0x893c13eb); + &_data_word(0xee27a9ce, 0x35c961b7, 0xede51ce1, 0x3cb1477a); + &_data_word(0x59dfd29c, 0x3f73f255, 0x79ce1418, 0xbf37c773); + &_data_word(0xeacdf753, 0x5baafd5f, 0x146f3ddf, 0x86db4478); + &_data_word(0x81f3afca, 0x3ec468b9, 0x2c342438, 0x5f40a3c2); + &_data_word(0x72c31d16, 0x0c25e2bc, 0x8b493c28, 0x41950dff); + &_data_word(0x7101a839, 0xdeb30c08, 0x9ce4b4d8, 0x90c15664); + &_data_word(0x6184cb7b, 0x70b632d5, 0x745c6c48, 0x4257b8d0); + +#Td4: # four copies of Td4 to choose from to avoid L1 aliasing + &data_byte(0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38); + &data_byte(0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb); + &data_byte(0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87); + &data_byte(0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb); + &data_byte(0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d); + &data_byte(0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e); + &data_byte(0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2); + &data_byte(0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25); + &data_byte(0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16); + &data_byte(0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92); + &data_byte(0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda); + &data_byte(0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84); + &data_byte(0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a); + &data_byte(0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06); + &data_byte(0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02); + &data_byte(0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b); + &data_byte(0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea); + &data_byte(0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73); + &data_byte(0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85); + &data_byte(0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e); + &data_byte(0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89); + &data_byte(0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b); + &data_byte(0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20); + &data_byte(0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4); + &data_byte(0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31); + &data_byte(0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f); + &data_byte(0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d); + &data_byte(0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef); + &data_byte(0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0); + &data_byte(0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61); + &data_byte(0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26); + &data_byte(0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d); +$code.=<<___; + .long 0x80808080, 0x80808080, 0xfefefefe, 0xfefefefe + .long 0x1b1b1b1b, 0x1b1b1b1b, 0, 0 +___ + &data_byte(0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38); + &data_byte(0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb); + &data_byte(0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87); + &data_byte(0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb); + &data_byte(0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d); + &data_byte(0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e); + &data_byte(0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2); + &data_byte(0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25); + &data_byte(0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16); + &data_byte(0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92); + &data_byte(0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda); + &data_byte(0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84); + &data_byte(0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a); + &data_byte(0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06); + &data_byte(0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02); + &data_byte(0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b); + &data_byte(0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea); + &data_byte(0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73); + &data_byte(0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85); + &data_byte(0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e); + &data_byte(0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89); + &data_byte(0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b); + &data_byte(0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20); + &data_byte(0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4); + &data_byte(0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31); + &data_byte(0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f); + &data_byte(0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d); + &data_byte(0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef); + &data_byte(0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0); + &data_byte(0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61); + &data_byte(0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26); + &data_byte(0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d); +$code.=<<___; + .long 0x80808080, 0x80808080, 0xfefefefe, 0xfefefefe + .long 0x1b1b1b1b, 0x1b1b1b1b, 0, 0 +___ + &data_byte(0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38); + &data_byte(0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb); + &data_byte(0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87); + &data_byte(0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb); + &data_byte(0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d); + &data_byte(0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e); + &data_byte(0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2); + &data_byte(0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25); + &data_byte(0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16); + &data_byte(0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92); + &data_byte(0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda); + &data_byte(0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84); + &data_byte(0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a); + &data_byte(0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06); + &data_byte(0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02); + &data_byte(0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b); + &data_byte(0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea); + &data_byte(0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73); + &data_byte(0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85); + &data_byte(0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e); + &data_byte(0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89); + &data_byte(0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b); + &data_byte(0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20); + &data_byte(0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4); + &data_byte(0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31); + &data_byte(0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f); + &data_byte(0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d); + &data_byte(0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef); + &data_byte(0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0); + &data_byte(0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61); + &data_byte(0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26); + &data_byte(0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d); +$code.=<<___; + .long 0x80808080, 0x80808080, 0xfefefefe, 0xfefefefe + .long 0x1b1b1b1b, 0x1b1b1b1b, 0, 0 +___ + &data_byte(0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38); + &data_byte(0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb); + &data_byte(0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87); + &data_byte(0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb); + &data_byte(0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d); + &data_byte(0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e); + &data_byte(0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2); + &data_byte(0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25); + &data_byte(0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16); + &data_byte(0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92); + &data_byte(0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda); + &data_byte(0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84); + &data_byte(0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a); + &data_byte(0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06); + &data_byte(0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02); + &data_byte(0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b); + &data_byte(0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea); + &data_byte(0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73); + &data_byte(0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85); + &data_byte(0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e); + &data_byte(0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89); + &data_byte(0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b); + &data_byte(0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20); + &data_byte(0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4); + &data_byte(0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31); + &data_byte(0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f); + &data_byte(0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d); + &data_byte(0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef); + &data_byte(0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0); + &data_byte(0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61); + &data_byte(0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26); + &data_byte(0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d); +$code.=<<___; + .long 0x80808080, 0x80808080, 0xfefefefe, 0xfefefefe + .long 0x1b1b1b1b, 0x1b1b1b1b, 0, 0 +.asciz "AES for x86_64, CRYPTOGAMS by " +.align 64 +___ + +# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame, +# CONTEXT *context,DISPATCHER_CONTEXT *disp) +if ($win64) { +$rec="%rcx"; +$frame="%rdx"; +$context="%r8"; +$disp="%r9"; + +$code.=<<___; +.extern __imp_RtlVirtualUnwind +.type block_se_handler,\@abi-omnipotent +.align 16 +block_se_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + mov 8($disp),%rsi # disp->ImageBase + mov 56($disp),%r11 # disp->HandlerData + + mov 0(%r11),%r10d # HandlerData[0] + lea (%rsi,%r10),%r10 # prologue label + cmp %r10,%rbx # context->RipRsp + + mov 4(%r11),%r10d # HandlerData[1] + lea (%rsi,%r10),%r10 # epilogue label + cmp %r10,%rbx # context->Rip>=epilogue label + jae .Lin_block_prologue + + mov 24(%rax),%rax # pull saved real stack pointer + lea 48(%rax),%rax # adjust... + + mov -8(%rax),%rbx + mov -16(%rax),%rbp + mov -24(%rax),%r12 + mov -32(%rax),%r13 + mov -40(%rax),%r14 + mov -48(%rax),%r15 + mov %rbx,144($context) # restore context->Rbx + mov %rbp,160($context) # restore context->Rbp + mov %r12,216($context) # restore context->R12 + mov %r13,224($context) # restore context->R13 + mov %r14,232($context) # restore context->R14 + mov %r15,240($context) # restore context->R15 + +.Lin_block_prologue: + mov 8(%rax),%rdi + mov 16(%rax),%rsi + mov %rax,152($context) # restore context->Rsp + mov %rsi,168($context) # restore context->Rsi + mov %rdi,176($context) # restore context->Rdi + + jmp .Lcommon_seh_exit +.size block_se_handler,.-block_se_handler + +.type key_se_handler,\@abi-omnipotent +.align 16 +key_se_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + mov 8($disp),%rsi # disp->ImageBase + mov 56($disp),%r11 # disp->HandlerData + + mov 0(%r11),%r10d # HandlerData[0] + lea (%rsi,%r10),%r10 # prologue label + cmp %r10,%rbx # context->RipRsp + + mov 4(%r11),%r10d # HandlerData[1] + lea (%rsi,%r10),%r10 # epilogue label + cmp %r10,%rbx # context->Rip>=epilogue label + jae .Lin_key_prologue + + lea 56(%rax),%rax + + mov -8(%rax),%rbx + mov -16(%rax),%rbp + mov -24(%rax),%r12 + mov -32(%rax),%r13 + mov -40(%rax),%r14 + mov -48(%rax),%r15 + mov %rbx,144($context) # restore context->Rbx + mov %rbp,160($context) # restore context->Rbp + mov %r12,216($context) # restore context->R12 + mov %r13,224($context) # restore context->R13 + mov %r14,232($context) # restore context->R14 + mov %r15,240($context) # restore context->R15 + +.Lin_key_prologue: + mov 8(%rax),%rdi + mov 16(%rax),%rsi + mov %rax,152($context) # restore context->Rsp + mov %rsi,168($context) # restore context->Rsi + mov %rdi,176($context) # restore context->Rdi + + jmp .Lcommon_seh_exit +.size key_se_handler,.-key_se_handler + +.type cbc_se_handler,\@abi-omnipotent +.align 16 +cbc_se_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + lea .Lcbc_prologue(%rip),%r10 + cmp %r10,%rbx # context->Rip<.Lcbc_prologue + jb .Lin_cbc_prologue + + lea .Lcbc_fast_body(%rip),%r10 + cmp %r10,%rbx # context->Rip<.Lcbc_fast_body + jb .Lin_cbc_frame_setup + + lea .Lcbc_slow_prologue(%rip),%r10 + cmp %r10,%rbx # context->Rip<.Lcbc_slow_prologue + jb .Lin_cbc_body + + lea .Lcbc_slow_body(%rip),%r10 + cmp %r10,%rbx # context->Rip<.Lcbc_slow_body + jb .Lin_cbc_frame_setup + +.Lin_cbc_body: + mov 152($context),%rax # pull context->Rsp + + lea .Lcbc_epilogue(%rip),%r10 + cmp %r10,%rbx # context->Rip>=.Lcbc_epilogue + jae .Lin_cbc_prologue + + lea 8(%rax),%rax + + lea .Lcbc_popfq(%rip),%r10 + cmp %r10,%rbx # context->Rip>=.Lcbc_popfq + jae .Lin_cbc_prologue + + mov `16-8`(%rax),%rax # biased $_rsp + lea 56(%rax),%rax + +.Lin_cbc_frame_setup: + mov -16(%rax),%rbx + mov -24(%rax),%rbp + mov -32(%rax),%r12 + mov -40(%rax),%r13 + mov -48(%rax),%r14 + mov -56(%rax),%r15 + mov %rbx,144($context) # restore context->Rbx + mov %rbp,160($context) # restore context->Rbp + mov %r12,216($context) # restore context->R12 + mov %r13,224($context) # restore context->R13 + mov %r14,232($context) # restore context->R14 + mov %r15,240($context) # restore context->R15 + +.Lin_cbc_prologue: + mov 8(%rax),%rdi + mov 16(%rax),%rsi + mov %rax,152($context) # restore context->Rsp + mov %rsi,168($context) # restore context->Rsi + mov %rdi,176($context) # restore context->Rdi + +.Lcommon_seh_exit: + + mov 40($disp),%rdi # disp->ContextRecord + mov $context,%rsi # context + mov \$`1232/8`,%ecx # sizeof(CONTEXT) + .long 0xa548f3fc # cld; rep movsq + + mov $disp,%rsi + xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER + mov 8(%rsi),%rdx # arg2, disp->ImageBase + mov 0(%rsi),%r8 # arg3, disp->ControlPc + mov 16(%rsi),%r9 # arg4, disp->FunctionEntry + mov 40(%rsi),%r10 # disp->ContextRecord + lea 56(%rsi),%r11 # &disp->HandlerData + lea 24(%rsi),%r12 # &disp->EstablisherFrame + mov %r10,32(%rsp) # arg5 + mov %r11,40(%rsp) # arg6 + mov %r12,48(%rsp) # arg7 + mov %rcx,56(%rsp) # arg8, (NULL) + call *__imp_RtlVirtualUnwind(%rip) + + mov \$1,%eax # ExceptionContinueSearch + add \$64,%rsp + popfq + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + pop %rdi + pop %rsi + ret +.size cbc_se_handler,.-cbc_se_handler + +.section .pdata +.align 4 + .rva .LSEH_begin_asm_AES_encrypt + .rva .LSEH_end_asm_AES_encrypt + .rva .LSEH_info_asm_AES_encrypt + + .rva .LSEH_begin_asm_AES_decrypt + .rva .LSEH_end_asm_AES_decrypt + .rva .LSEH_info_asm_AES_decrypt + + .rva .LSEH_begin_asm_AES_set_encrypt_key + .rva .LSEH_end_asm_AES_set_encrypt_key + .rva .LSEH_info_asm_AES_set_encrypt_key + + .rva .LSEH_begin_asm_AES_set_decrypt_key + .rva .LSEH_end_asm_AES_set_decrypt_key + .rva .LSEH_info_asm_AES_set_decrypt_key + + .rva .LSEH_begin_asm_AES_cbc_encrypt + .rva .LSEH_end_asm_AES_cbc_encrypt + .rva .LSEH_info_asm_AES_cbc_encrypt + +.section .xdata +.align 8 +.LSEH_info_asm_AES_encrypt: + .byte 9,0,0,0 + .rva block_se_handler + .rva .Lenc_prologue,.Lenc_epilogue # HandlerData[] +.LSEH_info_asm_AES_decrypt: + .byte 9,0,0,0 + .rva block_se_handler + .rva .Ldec_prologue,.Ldec_epilogue # HandlerData[] +.LSEH_info_asm_AES_set_encrypt_key: + .byte 9,0,0,0 + .rva key_se_handler + .rva .Lenc_key_prologue,.Lenc_key_epilogue # HandlerData[] +.LSEH_info_asm_AES_set_decrypt_key: + .byte 9,0,0,0 + .rva key_se_handler + .rva .Ldec_key_prologue,.Ldec_key_epilogue # HandlerData[] +.LSEH_info_asm_AES_cbc_encrypt: + .byte 9,0,0,0 + .rva cbc_se_handler +___ +} + +$code =~ s/\`([^\`]*)\`/eval($1)/gem; + +print $code; + +close STDOUT; diff --git a/external/boringssl/crypto/aes/asm/aesni-x86.pl b/external/boringssl/crypto/aes/asm/aesni-x86.pl new file mode 100644 index 0000000000..9b2e37aafb --- /dev/null +++ b/external/boringssl/crypto/aes/asm/aesni-x86.pl @@ -0,0 +1,2525 @@ +#!/usr/bin/env perl + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# This module implements support for Intel AES-NI extension. In +# OpenSSL context it's used with Intel engine, but can also be used as +# drop-in replacement for crypto/aes/asm/aes-586.pl [see below for +# details]. +# +# Performance. +# +# To start with see corresponding paragraph in aesni-x86_64.pl... +# Instead of filling table similar to one found there I've chosen to +# summarize *comparison* results for raw ECB, CTR and CBC benchmarks. +# The simplified table below represents 32-bit performance relative +# to 64-bit one in every given point. Ratios vary for different +# encryption modes, therefore interval values. +# +# 16-byte 64-byte 256-byte 1-KB 8-KB +# 53-67% 67-84% 91-94% 95-98% 97-99.5% +# +# Lower ratios for smaller block sizes are perfectly understandable, +# because function call overhead is higher in 32-bit mode. Largest +# 8-KB block performance is virtually same: 32-bit code is less than +# 1% slower for ECB, CBC and CCM, and ~3% slower otherwise. + +# January 2011 +# +# See aesni-x86_64.pl for details. Unlike x86_64 version this module +# interleaves at most 6 aes[enc|dec] instructions, because there are +# not enough registers for 8x interleave [which should be optimal for +# Sandy Bridge]. Actually, performance results for 6x interleave +# factor presented in aesni-x86_64.pl (except for CTR) are for this +# module. + +# April 2011 +# +# Add aesni_xts_[en|de]crypt. Westmere spends 1.50 cycles processing +# one byte out of 8KB with 128-bit key, Sandy Bridge - 1.09. + +###################################################################### +# Current large-block performance in cycles per byte processed with +# 128-bit key (less is better). +# +# CBC en-/decrypt CTR XTS ECB +# Westmere 3.77/1.37 1.37 1.52 1.27 +# * Bridge 5.07/0.98 0.99 1.09 0.91 +# Haswell 4.44/0.80 0.97 1.03 0.72 +# Silvermont 5.77/3.56 3.67 4.03 3.46 +# Bulldozer 5.80/0.98 1.05 1.24 0.93 + +$PREFIX="aesni"; # if $PREFIX is set to "AES", the script + # generates drop-in replacement for + # crypto/aes/asm/aes-586.pl:-) +$inline=1; # inline _aesni_[en|de]crypt + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +push(@INC,"${dir}","${dir}../../perlasm"); +require "x86asm.pl"; + +&asm_init($ARGV[0],$0); + +&external_label("OPENSSL_ia32cap_P"); +&static_label("key_const"); + +if ($PREFIX eq "aesni") { $movekey=\&movups; } +else { $movekey=\&movups; } + +$len="eax"; +$rounds="ecx"; +$key="edx"; +$inp="esi"; +$out="edi"; +$rounds_="ebx"; # backup copy for $rounds +$key_="ebp"; # backup copy for $key + +$rndkey0="xmm0"; +$rndkey1="xmm1"; +$inout0="xmm2"; +$inout1="xmm3"; +$inout2="xmm4"; +$inout3="xmm5"; $in1="xmm5"; +$inout4="xmm6"; $in0="xmm6"; +$inout5="xmm7"; $ivec="xmm7"; + +# AESNI extension +sub aeskeygenassist +{ my($dst,$src,$imm)=@_; + if ("$dst:$src" =~ /xmm([0-7]):xmm([0-7])/) + { &data_byte(0x66,0x0f,0x3a,0xdf,0xc0|($1<<3)|$2,$imm); } +} +sub aescommon +{ my($opcodelet,$dst,$src)=@_; + if ("$dst:$src" =~ /xmm([0-7]):xmm([0-7])/) + { &data_byte(0x66,0x0f,0x38,$opcodelet,0xc0|($1<<3)|$2);} +} +sub aesimc { aescommon(0xdb,@_); } +sub aesenc { aescommon(0xdc,@_); } +sub aesenclast { aescommon(0xdd,@_); } +sub aesdec { aescommon(0xde,@_); } +sub aesdeclast { aescommon(0xdf,@_); } + +# Inline version of internal aesni_[en|de]crypt1 +{ my $sn; +sub aesni_inline_generate1 +{ my ($p,$inout,$ivec)=@_; $inout=$inout0 if (!defined($inout)); + $sn++; + + &$movekey ($rndkey0,&QWP(0,$key)); + &$movekey ($rndkey1,&QWP(16,$key)); + &xorps ($ivec,$rndkey0) if (defined($ivec)); + &lea ($key,&DWP(32,$key)); + &xorps ($inout,$ivec) if (defined($ivec)); + &xorps ($inout,$rndkey0) if (!defined($ivec)); + &set_label("${p}1_loop_$sn"); + eval"&aes${p} ($inout,$rndkey1)"; + &dec ($rounds); + &$movekey ($rndkey1,&QWP(0,$key)); + &lea ($key,&DWP(16,$key)); + &jnz (&label("${p}1_loop_$sn")); + eval"&aes${p}last ($inout,$rndkey1)"; +}} + +sub aesni_generate1 # fully unrolled loop +{ my ($p,$inout)=@_; $inout=$inout0 if (!defined($inout)); + + &function_begin_B("_aesni_${p}rypt1"); + &movups ($rndkey0,&QWP(0,$key)); + &$movekey ($rndkey1,&QWP(0x10,$key)); + &xorps ($inout,$rndkey0); + &$movekey ($rndkey0,&QWP(0x20,$key)); + &lea ($key,&DWP(0x30,$key)); + &cmp ($rounds,11); + &jb (&label("${p}128")); + &lea ($key,&DWP(0x20,$key)); + &je (&label("${p}192")); + &lea ($key,&DWP(0x20,$key)); + eval"&aes${p} ($inout,$rndkey1)"; + &$movekey ($rndkey1,&QWP(-0x40,$key)); + eval"&aes${p} ($inout,$rndkey0)"; + &$movekey ($rndkey0,&QWP(-0x30,$key)); + &set_label("${p}192"); + eval"&aes${p} ($inout,$rndkey1)"; + &$movekey ($rndkey1,&QWP(-0x20,$key)); + eval"&aes${p} ($inout,$rndkey0)"; + &$movekey ($rndkey0,&QWP(-0x10,$key)); + &set_label("${p}128"); + eval"&aes${p} ($inout,$rndkey1)"; + &$movekey ($rndkey1,&QWP(0,$key)); + eval"&aes${p} ($inout,$rndkey0)"; + &$movekey ($rndkey0,&QWP(0x10,$key)); + eval"&aes${p} ($inout,$rndkey1)"; + &$movekey ($rndkey1,&QWP(0x20,$key)); + eval"&aes${p} ($inout,$rndkey0)"; + &$movekey ($rndkey0,&QWP(0x30,$key)); + eval"&aes${p} ($inout,$rndkey1)"; + &$movekey ($rndkey1,&QWP(0x40,$key)); + eval"&aes${p} ($inout,$rndkey0)"; + &$movekey ($rndkey0,&QWP(0x50,$key)); + eval"&aes${p} ($inout,$rndkey1)"; + &$movekey ($rndkey1,&QWP(0x60,$key)); + eval"&aes${p} ($inout,$rndkey0)"; + &$movekey ($rndkey0,&QWP(0x70,$key)); + eval"&aes${p} ($inout,$rndkey1)"; + eval"&aes${p}last ($inout,$rndkey0)"; + &ret(); + &function_end_B("_aesni_${p}rypt1"); +} + +# void $PREFIX_encrypt (const void *inp,void *out,const AES_KEY *key); +&aesni_generate1("enc") if (!$inline); +&function_begin_B("${PREFIX}_encrypt"); + &mov ("eax",&wparam(0)); + &mov ($key,&wparam(2)); + &movups ($inout0,&QWP(0,"eax")); + &mov ($rounds,&DWP(240,$key)); + &mov ("eax",&wparam(1)); + if ($inline) + { &aesni_inline_generate1("enc"); } + else + { &call ("_aesni_encrypt1"); } + &pxor ($rndkey0,$rndkey0); # clear register bank + &pxor ($rndkey1,$rndkey1); + &movups (&QWP(0,"eax"),$inout0); + &pxor ($inout0,$inout0); + &ret (); +&function_end_B("${PREFIX}_encrypt"); + +# void $PREFIX_decrypt (const void *inp,void *out,const AES_KEY *key); +&aesni_generate1("dec") if(!$inline); +&function_begin_B("${PREFIX}_decrypt"); + &mov ("eax",&wparam(0)); + &mov ($key,&wparam(2)); + &movups ($inout0,&QWP(0,"eax")); + &mov ($rounds,&DWP(240,$key)); + &mov ("eax",&wparam(1)); + if ($inline) + { &aesni_inline_generate1("dec"); } + else + { &call ("_aesni_decrypt1"); } + &pxor ($rndkey0,$rndkey0); # clear register bank + &pxor ($rndkey1,$rndkey1); + &movups (&QWP(0,"eax"),$inout0); + &pxor ($inout0,$inout0); + &ret (); +&function_end_B("${PREFIX}_decrypt"); + +# _aesni_[en|de]cryptN are private interfaces, N denotes interleave +# factor. Why 3x subroutine were originally used in loops? Even though +# aes[enc|dec] latency was originally 6, it could be scheduled only +# every *2nd* cycle. Thus 3x interleave was the one providing optimal +# utilization, i.e. when subroutine's throughput is virtually same as +# of non-interleaved subroutine [for number of input blocks up to 3]. +# This is why it originally made no sense to implement 2x subroutine. +# But times change and it became appropriate to spend extra 192 bytes +# on 2x subroutine on Atom Silvermont account. For processors that +# can schedule aes[enc|dec] every cycle optimal interleave factor +# equals to corresponding instructions latency. 8x is optimal for +# * Bridge, but it's unfeasible to accommodate such implementation +# in XMM registers addreassable in 32-bit mode and therefore maximum +# of 6x is used instead... + +sub aesni_generate2 +{ my $p=shift; + + &function_begin_B("_aesni_${p}rypt2"); + &$movekey ($rndkey0,&QWP(0,$key)); + &shl ($rounds,4); + &$movekey ($rndkey1,&QWP(16,$key)); + &xorps ($inout0,$rndkey0); + &pxor ($inout1,$rndkey0); + &$movekey ($rndkey0,&QWP(32,$key)); + &lea ($key,&DWP(32,$key,$rounds)); + &neg ($rounds); + &add ($rounds,16); + + &set_label("${p}2_loop"); + eval"&aes${p} ($inout0,$rndkey1)"; + eval"&aes${p} ($inout1,$rndkey1)"; + &$movekey ($rndkey1,&QWP(0,$key,$rounds)); + &add ($rounds,32); + eval"&aes${p} ($inout0,$rndkey0)"; + eval"&aes${p} ($inout1,$rndkey0)"; + &$movekey ($rndkey0,&QWP(-16,$key,$rounds)); + &jnz (&label("${p}2_loop")); + eval"&aes${p} ($inout0,$rndkey1)"; + eval"&aes${p} ($inout1,$rndkey1)"; + eval"&aes${p}last ($inout0,$rndkey0)"; + eval"&aes${p}last ($inout1,$rndkey0)"; + &ret(); + &function_end_B("_aesni_${p}rypt2"); +} + +sub aesni_generate3 +{ my $p=shift; + + &function_begin_B("_aesni_${p}rypt3"); + &$movekey ($rndkey0,&QWP(0,$key)); + &shl ($rounds,4); + &$movekey ($rndkey1,&QWP(16,$key)); + &xorps ($inout0,$rndkey0); + &pxor ($inout1,$rndkey0); + &pxor ($inout2,$rndkey0); + &$movekey ($rndkey0,&QWP(32,$key)); + &lea ($key,&DWP(32,$key,$rounds)); + &neg ($rounds); + &add ($rounds,16); + + &set_label("${p}3_loop"); + eval"&aes${p} ($inout0,$rndkey1)"; + eval"&aes${p} ($inout1,$rndkey1)"; + eval"&aes${p} ($inout2,$rndkey1)"; + &$movekey ($rndkey1,&QWP(0,$key,$rounds)); + &add ($rounds,32); + eval"&aes${p} ($inout0,$rndkey0)"; + eval"&aes${p} ($inout1,$rndkey0)"; + eval"&aes${p} ($inout2,$rndkey0)"; + &$movekey ($rndkey0,&QWP(-16,$key,$rounds)); + &jnz (&label("${p}3_loop")); + eval"&aes${p} ($inout0,$rndkey1)"; + eval"&aes${p} ($inout1,$rndkey1)"; + eval"&aes${p} ($inout2,$rndkey1)"; + eval"&aes${p}last ($inout0,$rndkey0)"; + eval"&aes${p}last ($inout1,$rndkey0)"; + eval"&aes${p}last ($inout2,$rndkey0)"; + &ret(); + &function_end_B("_aesni_${p}rypt3"); +} + +# 4x interleave is implemented to improve small block performance, +# most notably [and naturally] 4 block by ~30%. One can argue that one +# should have implemented 5x as well, but improvement would be <20%, +# so it's not worth it... +sub aesni_generate4 +{ my $p=shift; + + &function_begin_B("_aesni_${p}rypt4"); + &$movekey ($rndkey0,&QWP(0,$key)); + &$movekey ($rndkey1,&QWP(16,$key)); + &shl ($rounds,4); + &xorps ($inout0,$rndkey0); + &pxor ($inout1,$rndkey0); + &pxor ($inout2,$rndkey0); + &pxor ($inout3,$rndkey0); + &$movekey ($rndkey0,&QWP(32,$key)); + &lea ($key,&DWP(32,$key,$rounds)); + &neg ($rounds); + &data_byte (0x0f,0x1f,0x40,0x00); + &add ($rounds,16); + + &set_label("${p}4_loop"); + eval"&aes${p} ($inout0,$rndkey1)"; + eval"&aes${p} ($inout1,$rndkey1)"; + eval"&aes${p} ($inout2,$rndkey1)"; + eval"&aes${p} ($inout3,$rndkey1)"; + &$movekey ($rndkey1,&QWP(0,$key,$rounds)); + &add ($rounds,32); + eval"&aes${p} ($inout0,$rndkey0)"; + eval"&aes${p} ($inout1,$rndkey0)"; + eval"&aes${p} ($inout2,$rndkey0)"; + eval"&aes${p} ($inout3,$rndkey0)"; + &$movekey ($rndkey0,&QWP(-16,$key,$rounds)); + &jnz (&label("${p}4_loop")); + + eval"&aes${p} ($inout0,$rndkey1)"; + eval"&aes${p} ($inout1,$rndkey1)"; + eval"&aes${p} ($inout2,$rndkey1)"; + eval"&aes${p} ($inout3,$rndkey1)"; + eval"&aes${p}last ($inout0,$rndkey0)"; + eval"&aes${p}last ($inout1,$rndkey0)"; + eval"&aes${p}last ($inout2,$rndkey0)"; + eval"&aes${p}last ($inout3,$rndkey0)"; + &ret(); + &function_end_B("_aesni_${p}rypt4"); +} + +sub aesni_generate6 +{ my $p=shift; + + &function_begin_B("_aesni_${p}rypt6"); + &static_label("_aesni_${p}rypt6_enter"); + &$movekey ($rndkey0,&QWP(0,$key)); + &shl ($rounds,4); + &$movekey ($rndkey1,&QWP(16,$key)); + &xorps ($inout0,$rndkey0); + &pxor ($inout1,$rndkey0); # pxor does better here + &pxor ($inout2,$rndkey0); + eval"&aes${p} ($inout0,$rndkey1)"; + &pxor ($inout3,$rndkey0); + &pxor ($inout4,$rndkey0); + eval"&aes${p} ($inout1,$rndkey1)"; + &lea ($key,&DWP(32,$key,$rounds)); + &neg ($rounds); + eval"&aes${p} ($inout2,$rndkey1)"; + &pxor ($inout5,$rndkey0); + &$movekey ($rndkey0,&QWP(0,$key,$rounds)); + &add ($rounds,16); + &jmp (&label("_aesni_${p}rypt6_inner")); + + &set_label("${p}6_loop",16); + eval"&aes${p} ($inout0,$rndkey1)"; + eval"&aes${p} ($inout1,$rndkey1)"; + eval"&aes${p} ($inout2,$rndkey1)"; + &set_label("_aesni_${p}rypt6_inner"); + eval"&aes${p} ($inout3,$rndkey1)"; + eval"&aes${p} ($inout4,$rndkey1)"; + eval"&aes${p} ($inout5,$rndkey1)"; + &set_label("_aesni_${p}rypt6_enter"); + &$movekey ($rndkey1,&QWP(0,$key,$rounds)); + &add ($rounds,32); + eval"&aes${p} ($inout0,$rndkey0)"; + eval"&aes${p} ($inout1,$rndkey0)"; + eval"&aes${p} ($inout2,$rndkey0)"; + eval"&aes${p} ($inout3,$rndkey0)"; + eval"&aes${p} ($inout4,$rndkey0)"; + eval"&aes${p} ($inout5,$rndkey0)"; + &$movekey ($rndkey0,&QWP(-16,$key,$rounds)); + &jnz (&label("${p}6_loop")); + + eval"&aes${p} ($inout0,$rndkey1)"; + eval"&aes${p} ($inout1,$rndkey1)"; + eval"&aes${p} ($inout2,$rndkey1)"; + eval"&aes${p} ($inout3,$rndkey1)"; + eval"&aes${p} ($inout4,$rndkey1)"; + eval"&aes${p} ($inout5,$rndkey1)"; + eval"&aes${p}last ($inout0,$rndkey0)"; + eval"&aes${p}last ($inout1,$rndkey0)"; + eval"&aes${p}last ($inout2,$rndkey0)"; + eval"&aes${p}last ($inout3,$rndkey0)"; + eval"&aes${p}last ($inout4,$rndkey0)"; + eval"&aes${p}last ($inout5,$rndkey0)"; + &ret(); + &function_end_B("_aesni_${p}rypt6"); +} +&aesni_generate2("enc") if ($PREFIX eq "aesni"); +&aesni_generate2("dec"); +&aesni_generate3("enc") if ($PREFIX eq "aesni"); +&aesni_generate3("dec"); +&aesni_generate4("enc") if ($PREFIX eq "aesni"); +&aesni_generate4("dec"); +&aesni_generate6("enc") if ($PREFIX eq "aesni"); +&aesni_generate6("dec"); + +if ($PREFIX eq "aesni") { +###################################################################### +# void aesni_ecb_encrypt (const void *in, void *out, +# size_t length, const AES_KEY *key, +# int enc); +&function_begin("aesni_ecb_encrypt"); + &mov ($inp,&wparam(0)); + &mov ($out,&wparam(1)); + &mov ($len,&wparam(2)); + &mov ($key,&wparam(3)); + &mov ($rounds_,&wparam(4)); + &and ($len,-16); + &jz (&label("ecb_ret")); + &mov ($rounds,&DWP(240,$key)); + &test ($rounds_,$rounds_); + &jz (&label("ecb_decrypt")); + + &mov ($key_,$key); # backup $key + &mov ($rounds_,$rounds); # backup $rounds + &cmp ($len,0x60); + &jb (&label("ecb_enc_tail")); + + &movdqu ($inout0,&QWP(0,$inp)); + &movdqu ($inout1,&QWP(0x10,$inp)); + &movdqu ($inout2,&QWP(0x20,$inp)); + &movdqu ($inout3,&QWP(0x30,$inp)); + &movdqu ($inout4,&QWP(0x40,$inp)); + &movdqu ($inout5,&QWP(0x50,$inp)); + &lea ($inp,&DWP(0x60,$inp)); + &sub ($len,0x60); + &jmp (&label("ecb_enc_loop6_enter")); + +&set_label("ecb_enc_loop6",16); + &movups (&QWP(0,$out),$inout0); + &movdqu ($inout0,&QWP(0,$inp)); + &movups (&QWP(0x10,$out),$inout1); + &movdqu ($inout1,&QWP(0x10,$inp)); + &movups (&QWP(0x20,$out),$inout2); + &movdqu ($inout2,&QWP(0x20,$inp)); + &movups (&QWP(0x30,$out),$inout3); + &movdqu ($inout3,&QWP(0x30,$inp)); + &movups (&QWP(0x40,$out),$inout4); + &movdqu ($inout4,&QWP(0x40,$inp)); + &movups (&QWP(0x50,$out),$inout5); + &lea ($out,&DWP(0x60,$out)); + &movdqu ($inout5,&QWP(0x50,$inp)); + &lea ($inp,&DWP(0x60,$inp)); +&set_label("ecb_enc_loop6_enter"); + + &call ("_aesni_encrypt6"); + + &mov ($key,$key_); # restore $key + &mov ($rounds,$rounds_); # restore $rounds + &sub ($len,0x60); + &jnc (&label("ecb_enc_loop6")); + + &movups (&QWP(0,$out),$inout0); + &movups (&QWP(0x10,$out),$inout1); + &movups (&QWP(0x20,$out),$inout2); + &movups (&QWP(0x30,$out),$inout3); + &movups (&QWP(0x40,$out),$inout4); + &movups (&QWP(0x50,$out),$inout5); + &lea ($out,&DWP(0x60,$out)); + &add ($len,0x60); + &jz (&label("ecb_ret")); + +&set_label("ecb_enc_tail"); + &movups ($inout0,&QWP(0,$inp)); + &cmp ($len,0x20); + &jb (&label("ecb_enc_one")); + &movups ($inout1,&QWP(0x10,$inp)); + &je (&label("ecb_enc_two")); + &movups ($inout2,&QWP(0x20,$inp)); + &cmp ($len,0x40); + &jb (&label("ecb_enc_three")); + &movups ($inout3,&QWP(0x30,$inp)); + &je (&label("ecb_enc_four")); + &movups ($inout4,&QWP(0x40,$inp)); + &xorps ($inout5,$inout5); + &call ("_aesni_encrypt6"); + &movups (&QWP(0,$out),$inout0); + &movups (&QWP(0x10,$out),$inout1); + &movups (&QWP(0x20,$out),$inout2); + &movups (&QWP(0x30,$out),$inout3); + &movups (&QWP(0x40,$out),$inout4); + jmp (&label("ecb_ret")); + +&set_label("ecb_enc_one",16); + if ($inline) + { &aesni_inline_generate1("enc"); } + else + { &call ("_aesni_encrypt1"); } + &movups (&QWP(0,$out),$inout0); + &jmp (&label("ecb_ret")); + +&set_label("ecb_enc_two",16); + &call ("_aesni_encrypt2"); + &movups (&QWP(0,$out),$inout0); + &movups (&QWP(0x10,$out),$inout1); + &jmp (&label("ecb_ret")); + +&set_label("ecb_enc_three",16); + &call ("_aesni_encrypt3"); + &movups (&QWP(0,$out),$inout0); + &movups (&QWP(0x10,$out),$inout1); + &movups (&QWP(0x20,$out),$inout2); + &jmp (&label("ecb_ret")); + +&set_label("ecb_enc_four",16); + &call ("_aesni_encrypt4"); + &movups (&QWP(0,$out),$inout0); + &movups (&QWP(0x10,$out),$inout1); + &movups (&QWP(0x20,$out),$inout2); + &movups (&QWP(0x30,$out),$inout3); + &jmp (&label("ecb_ret")); +###################################################################### +&set_label("ecb_decrypt",16); + &mov ($key_,$key); # backup $key + &mov ($rounds_,$rounds); # backup $rounds + &cmp ($len,0x60); + &jb (&label("ecb_dec_tail")); + + &movdqu ($inout0,&QWP(0,$inp)); + &movdqu ($inout1,&QWP(0x10,$inp)); + &movdqu ($inout2,&QWP(0x20,$inp)); + &movdqu ($inout3,&QWP(0x30,$inp)); + &movdqu ($inout4,&QWP(0x40,$inp)); + &movdqu ($inout5,&QWP(0x50,$inp)); + &lea ($inp,&DWP(0x60,$inp)); + &sub ($len,0x60); + &jmp (&label("ecb_dec_loop6_enter")); + +&set_label("ecb_dec_loop6",16); + &movups (&QWP(0,$out),$inout0); + &movdqu ($inout0,&QWP(0,$inp)); + &movups (&QWP(0x10,$out),$inout1); + &movdqu ($inout1,&QWP(0x10,$inp)); + &movups (&QWP(0x20,$out),$inout2); + &movdqu ($inout2,&QWP(0x20,$inp)); + &movups (&QWP(0x30,$out),$inout3); + &movdqu ($inout3,&QWP(0x30,$inp)); + &movups (&QWP(0x40,$out),$inout4); + &movdqu ($inout4,&QWP(0x40,$inp)); + &movups (&QWP(0x50,$out),$inout5); + &lea ($out,&DWP(0x60,$out)); + &movdqu ($inout5,&QWP(0x50,$inp)); + &lea ($inp,&DWP(0x60,$inp)); +&set_label("ecb_dec_loop6_enter"); + + &call ("_aesni_decrypt6"); + + &mov ($key,$key_); # restore $key + &mov ($rounds,$rounds_); # restore $rounds + &sub ($len,0x60); + &jnc (&label("ecb_dec_loop6")); + + &movups (&QWP(0,$out),$inout0); + &movups (&QWP(0x10,$out),$inout1); + &movups (&QWP(0x20,$out),$inout2); + &movups (&QWP(0x30,$out),$inout3); + &movups (&QWP(0x40,$out),$inout4); + &movups (&QWP(0x50,$out),$inout5); + &lea ($out,&DWP(0x60,$out)); + &add ($len,0x60); + &jz (&label("ecb_ret")); + +&set_label("ecb_dec_tail"); + &movups ($inout0,&QWP(0,$inp)); + &cmp ($len,0x20); + &jb (&label("ecb_dec_one")); + &movups ($inout1,&QWP(0x10,$inp)); + &je (&label("ecb_dec_two")); + &movups ($inout2,&QWP(0x20,$inp)); + &cmp ($len,0x40); + &jb (&label("ecb_dec_three")); + &movups ($inout3,&QWP(0x30,$inp)); + &je (&label("ecb_dec_four")); + &movups ($inout4,&QWP(0x40,$inp)); + &xorps ($inout5,$inout5); + &call ("_aesni_decrypt6"); + &movups (&QWP(0,$out),$inout0); + &movups (&QWP(0x10,$out),$inout1); + &movups (&QWP(0x20,$out),$inout2); + &movups (&QWP(0x30,$out),$inout3); + &movups (&QWP(0x40,$out),$inout4); + &jmp (&label("ecb_ret")); + +&set_label("ecb_dec_one",16); + if ($inline) + { &aesni_inline_generate1("dec"); } + else + { &call ("_aesni_decrypt1"); } + &movups (&QWP(0,$out),$inout0); + &jmp (&label("ecb_ret")); + +&set_label("ecb_dec_two",16); + &call ("_aesni_decrypt2"); + &movups (&QWP(0,$out),$inout0); + &movups (&QWP(0x10,$out),$inout1); + &jmp (&label("ecb_ret")); + +&set_label("ecb_dec_three",16); + &call ("_aesni_decrypt3"); + &movups (&QWP(0,$out),$inout0); + &movups (&QWP(0x10,$out),$inout1); + &movups (&QWP(0x20,$out),$inout2); + &jmp (&label("ecb_ret")); + +&set_label("ecb_dec_four",16); + &call ("_aesni_decrypt4"); + &movups (&QWP(0,$out),$inout0); + &movups (&QWP(0x10,$out),$inout1); + &movups (&QWP(0x20,$out),$inout2); + &movups (&QWP(0x30,$out),$inout3); + +&set_label("ecb_ret"); + &pxor ("xmm0","xmm0"); # clear register bank + &pxor ("xmm1","xmm1"); + &pxor ("xmm2","xmm2"); + &pxor ("xmm3","xmm3"); + &pxor ("xmm4","xmm4"); + &pxor ("xmm5","xmm5"); + &pxor ("xmm6","xmm6"); + &pxor ("xmm7","xmm7"); +&function_end("aesni_ecb_encrypt"); + +###################################################################### +# void aesni_ccm64_[en|de]crypt_blocks (const void *in, void *out, +# size_t blocks, const AES_KEY *key, +# const char *ivec,char *cmac); +# +# Handles only complete blocks, operates on 64-bit counter and +# does not update *ivec! Nor does it finalize CMAC value +# (see engine/eng_aesni.c for details) +# +{ my $cmac=$inout1; +&function_begin("aesni_ccm64_encrypt_blocks"); + &mov ($inp,&wparam(0)); + &mov ($out,&wparam(1)); + &mov ($len,&wparam(2)); + &mov ($key,&wparam(3)); + &mov ($rounds_,&wparam(4)); + &mov ($rounds,&wparam(5)); + &mov ($key_,"esp"); + &sub ("esp",60); + &and ("esp",-16); # align stack + &mov (&DWP(48,"esp"),$key_); + + &movdqu ($ivec,&QWP(0,$rounds_)); # load ivec + &movdqu ($cmac,&QWP(0,$rounds)); # load cmac + &mov ($rounds,&DWP(240,$key)); + + # compose byte-swap control mask for pshufb on stack + &mov (&DWP(0,"esp"),0x0c0d0e0f); + &mov (&DWP(4,"esp"),0x08090a0b); + &mov (&DWP(8,"esp"),0x04050607); + &mov (&DWP(12,"esp"),0x00010203); + + # compose counter increment vector on stack + &mov ($rounds_,1); + &xor ($key_,$key_); + &mov (&DWP(16,"esp"),$rounds_); + &mov (&DWP(20,"esp"),$key_); + &mov (&DWP(24,"esp"),$key_); + &mov (&DWP(28,"esp"),$key_); + + &shl ($rounds,4); + &mov ($rounds_,16); + &lea ($key_,&DWP(0,$key)); + &movdqa ($inout3,&QWP(0,"esp")); + &movdqa ($inout0,$ivec); + &lea ($key,&DWP(32,$key,$rounds)); + &sub ($rounds_,$rounds); + &pshufb ($ivec,$inout3); + +&set_label("ccm64_enc_outer"); + &$movekey ($rndkey0,&QWP(0,$key_)); + &mov ($rounds,$rounds_); + &movups ($in0,&QWP(0,$inp)); + + &xorps ($inout0,$rndkey0); + &$movekey ($rndkey1,&QWP(16,$key_)); + &xorps ($rndkey0,$in0); + &xorps ($cmac,$rndkey0); # cmac^=inp + &$movekey ($rndkey0,&QWP(32,$key_)); + +&set_label("ccm64_enc2_loop"); + &aesenc ($inout0,$rndkey1); + &aesenc ($cmac,$rndkey1); + &$movekey ($rndkey1,&QWP(0,$key,$rounds)); + &add ($rounds,32); + &aesenc ($inout0,$rndkey0); + &aesenc ($cmac,$rndkey0); + &$movekey ($rndkey0,&QWP(-16,$key,$rounds)); + &jnz (&label("ccm64_enc2_loop")); + &aesenc ($inout0,$rndkey1); + &aesenc ($cmac,$rndkey1); + &paddq ($ivec,&QWP(16,"esp")); + &dec ($len); + &aesenclast ($inout0,$rndkey0); + &aesenclast ($cmac,$rndkey0); + + &lea ($inp,&DWP(16,$inp)); + &xorps ($in0,$inout0); # inp^=E(ivec) + &movdqa ($inout0,$ivec); + &movups (&QWP(0,$out),$in0); # save output + &pshufb ($inout0,$inout3); + &lea ($out,&DWP(16,$out)); + &jnz (&label("ccm64_enc_outer")); + + &mov ("esp",&DWP(48,"esp")); + &mov ($out,&wparam(5)); + &movups (&QWP(0,$out),$cmac); + + &pxor ("xmm0","xmm0"); # clear register bank + &pxor ("xmm1","xmm1"); + &pxor ("xmm2","xmm2"); + &pxor ("xmm3","xmm3"); + &pxor ("xmm4","xmm4"); + &pxor ("xmm5","xmm5"); + &pxor ("xmm6","xmm6"); + &pxor ("xmm7","xmm7"); +&function_end("aesni_ccm64_encrypt_blocks"); + +&function_begin("aesni_ccm64_decrypt_blocks"); + &mov ($inp,&wparam(0)); + &mov ($out,&wparam(1)); + &mov ($len,&wparam(2)); + &mov ($key,&wparam(3)); + &mov ($rounds_,&wparam(4)); + &mov ($rounds,&wparam(5)); + &mov ($key_,"esp"); + &sub ("esp",60); + &and ("esp",-16); # align stack + &mov (&DWP(48,"esp"),$key_); + + &movdqu ($ivec,&QWP(0,$rounds_)); # load ivec + &movdqu ($cmac,&QWP(0,$rounds)); # load cmac + &mov ($rounds,&DWP(240,$key)); + + # compose byte-swap control mask for pshufb on stack + &mov (&DWP(0,"esp"),0x0c0d0e0f); + &mov (&DWP(4,"esp"),0x08090a0b); + &mov (&DWP(8,"esp"),0x04050607); + &mov (&DWP(12,"esp"),0x00010203); + + # compose counter increment vector on stack + &mov ($rounds_,1); + &xor ($key_,$key_); + &mov (&DWP(16,"esp"),$rounds_); + &mov (&DWP(20,"esp"),$key_); + &mov (&DWP(24,"esp"),$key_); + &mov (&DWP(28,"esp"),$key_); + + &movdqa ($inout3,&QWP(0,"esp")); # bswap mask + &movdqa ($inout0,$ivec); + + &mov ($key_,$key); + &mov ($rounds_,$rounds); + + &pshufb ($ivec,$inout3); + if ($inline) + { &aesni_inline_generate1("enc"); } + else + { &call ("_aesni_encrypt1"); } + &shl ($rounds_,4); + &mov ($rounds,16); + &movups ($in0,&QWP(0,$inp)); # load inp + &paddq ($ivec,&QWP(16,"esp")); + &lea ($inp,&QWP(16,$inp)); + &sub ($rounds,$rounds_); + &lea ($key,&DWP(32,$key_,$rounds_)); + &mov ($rounds_,$rounds); + &jmp (&label("ccm64_dec_outer")); + +&set_label("ccm64_dec_outer",16); + &xorps ($in0,$inout0); # inp ^= E(ivec) + &movdqa ($inout0,$ivec); + &movups (&QWP(0,$out),$in0); # save output + &lea ($out,&DWP(16,$out)); + &pshufb ($inout0,$inout3); + + &sub ($len,1); + &jz (&label("ccm64_dec_break")); + + &$movekey ($rndkey0,&QWP(0,$key_)); + &mov ($rounds,$rounds_); + &$movekey ($rndkey1,&QWP(16,$key_)); + &xorps ($in0,$rndkey0); + &xorps ($inout0,$rndkey0); + &xorps ($cmac,$in0); # cmac^=out + &$movekey ($rndkey0,&QWP(32,$key_)); + +&set_label("ccm64_dec2_loop"); + &aesenc ($inout0,$rndkey1); + &aesenc ($cmac,$rndkey1); + &$movekey ($rndkey1,&QWP(0,$key,$rounds)); + &add ($rounds,32); + &aesenc ($inout0,$rndkey0); + &aesenc ($cmac,$rndkey0); + &$movekey ($rndkey0,&QWP(-16,$key,$rounds)); + &jnz (&label("ccm64_dec2_loop")); + &movups ($in0,&QWP(0,$inp)); # load inp + &paddq ($ivec,&QWP(16,"esp")); + &aesenc ($inout0,$rndkey1); + &aesenc ($cmac,$rndkey1); + &aesenclast ($inout0,$rndkey0); + &aesenclast ($cmac,$rndkey0); + &lea ($inp,&QWP(16,$inp)); + &jmp (&label("ccm64_dec_outer")); + +&set_label("ccm64_dec_break",16); + &mov ($rounds,&DWP(240,$key_)); + &mov ($key,$key_); + if ($inline) + { &aesni_inline_generate1("enc",$cmac,$in0); } + else + { &call ("_aesni_encrypt1",$cmac); } + + &mov ("esp",&DWP(48,"esp")); + &mov ($out,&wparam(5)); + &movups (&QWP(0,$out),$cmac); + + &pxor ("xmm0","xmm0"); # clear register bank + &pxor ("xmm1","xmm1"); + &pxor ("xmm2","xmm2"); + &pxor ("xmm3","xmm3"); + &pxor ("xmm4","xmm4"); + &pxor ("xmm5","xmm5"); + &pxor ("xmm6","xmm6"); + &pxor ("xmm7","xmm7"); +&function_end("aesni_ccm64_decrypt_blocks"); +} + +###################################################################### +# void aesni_ctr32_encrypt_blocks (const void *in, void *out, +# size_t blocks, const AES_KEY *key, +# const char *ivec); +# +# Handles only complete blocks, operates on 32-bit counter and +# does not update *ivec! (see crypto/modes/ctr128.c for details) +# +# stack layout: +# 0 pshufb mask +# 16 vector addend: 0,6,6,6 +# 32 counter-less ivec +# 48 1st triplet of counter vector +# 64 2nd triplet of counter vector +# 80 saved %esp + +&function_begin("aesni_ctr32_encrypt_blocks"); + &mov ($inp,&wparam(0)); + &mov ($out,&wparam(1)); + &mov ($len,&wparam(2)); + &mov ($key,&wparam(3)); + &mov ($rounds_,&wparam(4)); + &mov ($key_,"esp"); + &sub ("esp",88); + &and ("esp",-16); # align stack + &mov (&DWP(80,"esp"),$key_); + + &cmp ($len,1); + &je (&label("ctr32_one_shortcut")); + + &movdqu ($inout5,&QWP(0,$rounds_)); # load ivec + + # compose byte-swap control mask for pshufb on stack + &mov (&DWP(0,"esp"),0x0c0d0e0f); + &mov (&DWP(4,"esp"),0x08090a0b); + &mov (&DWP(8,"esp"),0x04050607); + &mov (&DWP(12,"esp"),0x00010203); + + # compose counter increment vector on stack + &mov ($rounds,6); + &xor ($key_,$key_); + &mov (&DWP(16,"esp"),$rounds); + &mov (&DWP(20,"esp"),$rounds); + &mov (&DWP(24,"esp"),$rounds); + &mov (&DWP(28,"esp"),$key_); + + &pextrd ($rounds_,$inout5,3); # pull 32-bit counter + &pinsrd ($inout5,$key_,3); # wipe 32-bit counter + + &mov ($rounds,&DWP(240,$key)); # key->rounds + + # compose 2 vectors of 3x32-bit counters + &bswap ($rounds_); + &pxor ($rndkey0,$rndkey0); + &pxor ($rndkey1,$rndkey1); + &movdqa ($inout0,&QWP(0,"esp")); # load byte-swap mask + &pinsrd ($rndkey0,$rounds_,0); + &lea ($key_,&DWP(3,$rounds_)); + &pinsrd ($rndkey1,$key_,0); + &inc ($rounds_); + &pinsrd ($rndkey0,$rounds_,1); + &inc ($key_); + &pinsrd ($rndkey1,$key_,1); + &inc ($rounds_); + &pinsrd ($rndkey0,$rounds_,2); + &inc ($key_); + &pinsrd ($rndkey1,$key_,2); + &movdqa (&QWP(48,"esp"),$rndkey0); # save 1st triplet + &pshufb ($rndkey0,$inout0); # byte swap + &movdqu ($inout4,&QWP(0,$key)); # key[0] + &movdqa (&QWP(64,"esp"),$rndkey1); # save 2nd triplet + &pshufb ($rndkey1,$inout0); # byte swap + + &pshufd ($inout0,$rndkey0,3<<6); # place counter to upper dword + &pshufd ($inout1,$rndkey0,2<<6); + &cmp ($len,6); + &jb (&label("ctr32_tail")); + &pxor ($inout5,$inout4); # counter-less ivec^key[0] + &shl ($rounds,4); + &mov ($rounds_,16); + &movdqa (&QWP(32,"esp"),$inout5); # save counter-less ivec^key[0] + &mov ($key_,$key); # backup $key + &sub ($rounds_,$rounds); # backup twisted $rounds + &lea ($key,&DWP(32,$key,$rounds)); + &sub ($len,6); + &jmp (&label("ctr32_loop6")); + +&set_label("ctr32_loop6",16); + # inlining _aesni_encrypt6's prologue gives ~6% improvement... + &pshufd ($inout2,$rndkey0,1<<6); + &movdqa ($rndkey0,&QWP(32,"esp")); # pull counter-less ivec + &pshufd ($inout3,$rndkey1,3<<6); + &pxor ($inout0,$rndkey0); # merge counter-less ivec + &pshufd ($inout4,$rndkey1,2<<6); + &pxor ($inout1,$rndkey0); + &pshufd ($inout5,$rndkey1,1<<6); + &$movekey ($rndkey1,&QWP(16,$key_)); + &pxor ($inout2,$rndkey0); + &pxor ($inout3,$rndkey0); + &aesenc ($inout0,$rndkey1); + &pxor ($inout4,$rndkey0); + &pxor ($inout5,$rndkey0); + &aesenc ($inout1,$rndkey1); + &$movekey ($rndkey0,&QWP(32,$key_)); + &mov ($rounds,$rounds_); + &aesenc ($inout2,$rndkey1); + &aesenc ($inout3,$rndkey1); + &aesenc ($inout4,$rndkey1); + &aesenc ($inout5,$rndkey1); + + &call (&label("_aesni_encrypt6_enter")); + + &movups ($rndkey1,&QWP(0,$inp)); + &movups ($rndkey0,&QWP(0x10,$inp)); + &xorps ($inout0,$rndkey1); + &movups ($rndkey1,&QWP(0x20,$inp)); + &xorps ($inout1,$rndkey0); + &movups (&QWP(0,$out),$inout0); + &movdqa ($rndkey0,&QWP(16,"esp")); # load increment + &xorps ($inout2,$rndkey1); + &movdqa ($rndkey1,&QWP(64,"esp")); # load 2nd triplet + &movups (&QWP(0x10,$out),$inout1); + &movups (&QWP(0x20,$out),$inout2); + + &paddd ($rndkey1,$rndkey0); # 2nd triplet increment + &paddd ($rndkey0,&QWP(48,"esp")); # 1st triplet increment + &movdqa ($inout0,&QWP(0,"esp")); # load byte swap mask + + &movups ($inout1,&QWP(0x30,$inp)); + &movups ($inout2,&QWP(0x40,$inp)); + &xorps ($inout3,$inout1); + &movups ($inout1,&QWP(0x50,$inp)); + &lea ($inp,&DWP(0x60,$inp)); + &movdqa (&QWP(48,"esp"),$rndkey0); # save 1st triplet + &pshufb ($rndkey0,$inout0); # byte swap + &xorps ($inout4,$inout2); + &movups (&QWP(0x30,$out),$inout3); + &xorps ($inout5,$inout1); + &movdqa (&QWP(64,"esp"),$rndkey1); # save 2nd triplet + &pshufb ($rndkey1,$inout0); # byte swap + &movups (&QWP(0x40,$out),$inout4); + &pshufd ($inout0,$rndkey0,3<<6); + &movups (&QWP(0x50,$out),$inout5); + &lea ($out,&DWP(0x60,$out)); + + &pshufd ($inout1,$rndkey0,2<<6); + &sub ($len,6); + &jnc (&label("ctr32_loop6")); + + &add ($len,6); + &jz (&label("ctr32_ret")); + &movdqu ($inout5,&QWP(0,$key_)); + &mov ($key,$key_); + &pxor ($inout5,&QWP(32,"esp")); # restore count-less ivec + &mov ($rounds,&DWP(240,$key_)); # restore $rounds + +&set_label("ctr32_tail"); + &por ($inout0,$inout5); + &cmp ($len,2); + &jb (&label("ctr32_one")); + + &pshufd ($inout2,$rndkey0,1<<6); + &por ($inout1,$inout5); + &je (&label("ctr32_two")); + + &pshufd ($inout3,$rndkey1,3<<6); + &por ($inout2,$inout5); + &cmp ($len,4); + &jb (&label("ctr32_three")); + + &pshufd ($inout4,$rndkey1,2<<6); + &por ($inout3,$inout5); + &je (&label("ctr32_four")); + + &por ($inout4,$inout5); + &call ("_aesni_encrypt6"); + &movups ($rndkey1,&QWP(0,$inp)); + &movups ($rndkey0,&QWP(0x10,$inp)); + &xorps ($inout0,$rndkey1); + &movups ($rndkey1,&QWP(0x20,$inp)); + &xorps ($inout1,$rndkey0); + &movups ($rndkey0,&QWP(0x30,$inp)); + &xorps ($inout2,$rndkey1); + &movups ($rndkey1,&QWP(0x40,$inp)); + &xorps ($inout3,$rndkey0); + &movups (&QWP(0,$out),$inout0); + &xorps ($inout4,$rndkey1); + &movups (&QWP(0x10,$out),$inout1); + &movups (&QWP(0x20,$out),$inout2); + &movups (&QWP(0x30,$out),$inout3); + &movups (&QWP(0x40,$out),$inout4); + &jmp (&label("ctr32_ret")); + +&set_label("ctr32_one_shortcut",16); + &movups ($inout0,&QWP(0,$rounds_)); # load ivec + &mov ($rounds,&DWP(240,$key)); + +&set_label("ctr32_one"); + if ($inline) + { &aesni_inline_generate1("enc"); } + else + { &call ("_aesni_encrypt1"); } + &movups ($in0,&QWP(0,$inp)); + &xorps ($in0,$inout0); + &movups (&QWP(0,$out),$in0); + &jmp (&label("ctr32_ret")); + +&set_label("ctr32_two",16); + &call ("_aesni_encrypt2"); + &movups ($inout3,&QWP(0,$inp)); + &movups ($inout4,&QWP(0x10,$inp)); + &xorps ($inout0,$inout3); + &xorps ($inout1,$inout4); + &movups (&QWP(0,$out),$inout0); + &movups (&QWP(0x10,$out),$inout1); + &jmp (&label("ctr32_ret")); + +&set_label("ctr32_three",16); + &call ("_aesni_encrypt3"); + &movups ($inout3,&QWP(0,$inp)); + &movups ($inout4,&QWP(0x10,$inp)); + &xorps ($inout0,$inout3); + &movups ($inout5,&QWP(0x20,$inp)); + &xorps ($inout1,$inout4); + &movups (&QWP(0,$out),$inout0); + &xorps ($inout2,$inout5); + &movups (&QWP(0x10,$out),$inout1); + &movups (&QWP(0x20,$out),$inout2); + &jmp (&label("ctr32_ret")); + +&set_label("ctr32_four",16); + &call ("_aesni_encrypt4"); + &movups ($inout4,&QWP(0,$inp)); + &movups ($inout5,&QWP(0x10,$inp)); + &movups ($rndkey1,&QWP(0x20,$inp)); + &xorps ($inout0,$inout4); + &movups ($rndkey0,&QWP(0x30,$inp)); + &xorps ($inout1,$inout5); + &movups (&QWP(0,$out),$inout0); + &xorps ($inout2,$rndkey1); + &movups (&QWP(0x10,$out),$inout1); + &xorps ($inout3,$rndkey0); + &movups (&QWP(0x20,$out),$inout2); + &movups (&QWP(0x30,$out),$inout3); + +&set_label("ctr32_ret"); + &pxor ("xmm0","xmm0"); # clear register bank + &pxor ("xmm1","xmm1"); + &pxor ("xmm2","xmm2"); + &pxor ("xmm3","xmm3"); + &pxor ("xmm4","xmm4"); + &movdqa (&QWP(32,"esp"),"xmm0"); # clear stack + &pxor ("xmm5","xmm5"); + &movdqa (&QWP(48,"esp"),"xmm0"); + &pxor ("xmm6","xmm6"); + &movdqa (&QWP(64,"esp"),"xmm0"); + &pxor ("xmm7","xmm7"); + &mov ("esp",&DWP(80,"esp")); +&function_end("aesni_ctr32_encrypt_blocks"); + +###################################################################### +# void aesni_xts_[en|de]crypt(const char *inp,char *out,size_t len, +# const AES_KEY *key1, const AES_KEY *key2 +# const unsigned char iv[16]); +# +{ my ($tweak,$twtmp,$twres,$twmask)=($rndkey1,$rndkey0,$inout0,$inout1); + +&function_begin("aesni_xts_encrypt"); + &mov ($key,&wparam(4)); # key2 + &mov ($inp,&wparam(5)); # clear-text tweak + + &mov ($rounds,&DWP(240,$key)); # key2->rounds + &movups ($inout0,&QWP(0,$inp)); + if ($inline) + { &aesni_inline_generate1("enc"); } + else + { &call ("_aesni_encrypt1"); } + + &mov ($inp,&wparam(0)); + &mov ($out,&wparam(1)); + &mov ($len,&wparam(2)); + &mov ($key,&wparam(3)); # key1 + + &mov ($key_,"esp"); + &sub ("esp",16*7+8); + &mov ($rounds,&DWP(240,$key)); # key1->rounds + &and ("esp",-16); # align stack + + &mov (&DWP(16*6+0,"esp"),0x87); # compose the magic constant + &mov (&DWP(16*6+4,"esp"),0); + &mov (&DWP(16*6+8,"esp"),1); + &mov (&DWP(16*6+12,"esp"),0); + &mov (&DWP(16*7+0,"esp"),$len); # save original $len + &mov (&DWP(16*7+4,"esp"),$key_); # save original %esp + + &movdqa ($tweak,$inout0); + &pxor ($twtmp,$twtmp); + &movdqa ($twmask,&QWP(6*16,"esp")); # 0x0...010...87 + &pcmpgtd($twtmp,$tweak); # broadcast upper bits + + &and ($len,-16); + &mov ($key_,$key); # backup $key + &mov ($rounds_,$rounds); # backup $rounds + &sub ($len,16*6); + &jc (&label("xts_enc_short")); + + &shl ($rounds,4); + &mov ($rounds_,16); + &sub ($rounds_,$rounds); + &lea ($key,&DWP(32,$key,$rounds)); + &jmp (&label("xts_enc_loop6")); + +&set_label("xts_enc_loop6",16); + for ($i=0;$i<4;$i++) { + &pshufd ($twres,$twtmp,0x13); + &pxor ($twtmp,$twtmp); + &movdqa (&QWP(16*$i,"esp"),$tweak); + &paddq ($tweak,$tweak); # &psllq($tweak,1); + &pand ($twres,$twmask); # isolate carry and residue + &pcmpgtd ($twtmp,$tweak); # broadcast upper bits + &pxor ($tweak,$twres); + } + &pshufd ($inout5,$twtmp,0x13); + &movdqa (&QWP(16*$i++,"esp"),$tweak); + &paddq ($tweak,$tweak); # &psllq($tweak,1); + &$movekey ($rndkey0,&QWP(0,$key_)); + &pand ($inout5,$twmask); # isolate carry and residue + &movups ($inout0,&QWP(0,$inp)); # load input + &pxor ($inout5,$tweak); + + # inline _aesni_encrypt6 prologue and flip xor with tweak and key[0] + &mov ($rounds,$rounds_); # restore $rounds + &movdqu ($inout1,&QWP(16*1,$inp)); + &xorps ($inout0,$rndkey0); # input^=rndkey[0] + &movdqu ($inout2,&QWP(16*2,$inp)); + &pxor ($inout1,$rndkey0); + &movdqu ($inout3,&QWP(16*3,$inp)); + &pxor ($inout2,$rndkey0); + &movdqu ($inout4,&QWP(16*4,$inp)); + &pxor ($inout3,$rndkey0); + &movdqu ($rndkey1,&QWP(16*5,$inp)); + &pxor ($inout4,$rndkey0); + &lea ($inp,&DWP(16*6,$inp)); + &pxor ($inout0,&QWP(16*0,"esp")); # input^=tweak + &movdqa (&QWP(16*$i,"esp"),$inout5); # save last tweak + &pxor ($inout5,$rndkey1); + + &$movekey ($rndkey1,&QWP(16,$key_)); + &pxor ($inout1,&QWP(16*1,"esp")); + &pxor ($inout2,&QWP(16*2,"esp")); + &aesenc ($inout0,$rndkey1); + &pxor ($inout3,&QWP(16*3,"esp")); + &pxor ($inout4,&QWP(16*4,"esp")); + &aesenc ($inout1,$rndkey1); + &pxor ($inout5,$rndkey0); + &$movekey ($rndkey0,&QWP(32,$key_)); + &aesenc ($inout2,$rndkey1); + &aesenc ($inout3,$rndkey1); + &aesenc ($inout4,$rndkey1); + &aesenc ($inout5,$rndkey1); + &call (&label("_aesni_encrypt6_enter")); + + &movdqa ($tweak,&QWP(16*5,"esp")); # last tweak + &pxor ($twtmp,$twtmp); + &xorps ($inout0,&QWP(16*0,"esp")); # output^=tweak + &pcmpgtd ($twtmp,$tweak); # broadcast upper bits + &xorps ($inout1,&QWP(16*1,"esp")); + &movups (&QWP(16*0,$out),$inout0); # write output + &xorps ($inout2,&QWP(16*2,"esp")); + &movups (&QWP(16*1,$out),$inout1); + &xorps ($inout3,&QWP(16*3,"esp")); + &movups (&QWP(16*2,$out),$inout2); + &xorps ($inout4,&QWP(16*4,"esp")); + &movups (&QWP(16*3,$out),$inout3); + &xorps ($inout5,$tweak); + &movups (&QWP(16*4,$out),$inout4); + &pshufd ($twres,$twtmp,0x13); + &movups (&QWP(16*5,$out),$inout5); + &lea ($out,&DWP(16*6,$out)); + &movdqa ($twmask,&QWP(16*6,"esp")); # 0x0...010...87 + + &pxor ($twtmp,$twtmp); + &paddq ($tweak,$tweak); # &psllq($tweak,1); + &pand ($twres,$twmask); # isolate carry and residue + &pcmpgtd($twtmp,$tweak); # broadcast upper bits + &pxor ($tweak,$twres); + + &sub ($len,16*6); + &jnc (&label("xts_enc_loop6")); + + &mov ($rounds,&DWP(240,$key_)); # restore $rounds + &mov ($key,$key_); # restore $key + &mov ($rounds_,$rounds); + +&set_label("xts_enc_short"); + &add ($len,16*6); + &jz (&label("xts_enc_done6x")); + + &movdqa ($inout3,$tweak); # put aside previous tweak + &cmp ($len,0x20); + &jb (&label("xts_enc_one")); + + &pshufd ($twres,$twtmp,0x13); + &pxor ($twtmp,$twtmp); + &paddq ($tweak,$tweak); # &psllq($tweak,1); + &pand ($twres,$twmask); # isolate carry and residue + &pcmpgtd($twtmp,$tweak); # broadcast upper bits + &pxor ($tweak,$twres); + &je (&label("xts_enc_two")); + + &pshufd ($twres,$twtmp,0x13); + &pxor ($twtmp,$twtmp); + &movdqa ($inout4,$tweak); # put aside previous tweak + &paddq ($tweak,$tweak); # &psllq($tweak,1); + &pand ($twres,$twmask); # isolate carry and residue + &pcmpgtd($twtmp,$tweak); # broadcast upper bits + &pxor ($tweak,$twres); + &cmp ($len,0x40); + &jb (&label("xts_enc_three")); + + &pshufd ($twres,$twtmp,0x13); + &pxor ($twtmp,$twtmp); + &movdqa ($inout5,$tweak); # put aside previous tweak + &paddq ($tweak,$tweak); # &psllq($tweak,1); + &pand ($twres,$twmask); # isolate carry and residue + &pcmpgtd($twtmp,$tweak); # broadcast upper bits + &pxor ($tweak,$twres); + &movdqa (&QWP(16*0,"esp"),$inout3); + &movdqa (&QWP(16*1,"esp"),$inout4); + &je (&label("xts_enc_four")); + + &movdqa (&QWP(16*2,"esp"),$inout5); + &pshufd ($inout5,$twtmp,0x13); + &movdqa (&QWP(16*3,"esp"),$tweak); + &paddq ($tweak,$tweak); # &psllq($inout0,1); + &pand ($inout5,$twmask); # isolate carry and residue + &pxor ($inout5,$tweak); + + &movdqu ($inout0,&QWP(16*0,$inp)); # load input + &movdqu ($inout1,&QWP(16*1,$inp)); + &movdqu ($inout2,&QWP(16*2,$inp)); + &pxor ($inout0,&QWP(16*0,"esp")); # input^=tweak + &movdqu ($inout3,&QWP(16*3,$inp)); + &pxor ($inout1,&QWP(16*1,"esp")); + &movdqu ($inout4,&QWP(16*4,$inp)); + &pxor ($inout2,&QWP(16*2,"esp")); + &lea ($inp,&DWP(16*5,$inp)); + &pxor ($inout3,&QWP(16*3,"esp")); + &movdqa (&QWP(16*4,"esp"),$inout5); # save last tweak + &pxor ($inout4,$inout5); + + &call ("_aesni_encrypt6"); + + &movaps ($tweak,&QWP(16*4,"esp")); # last tweak + &xorps ($inout0,&QWP(16*0,"esp")); # output^=tweak + &xorps ($inout1,&QWP(16*1,"esp")); + &xorps ($inout2,&QWP(16*2,"esp")); + &movups (&QWP(16*0,$out),$inout0); # write output + &xorps ($inout3,&QWP(16*3,"esp")); + &movups (&QWP(16*1,$out),$inout1); + &xorps ($inout4,$tweak); + &movups (&QWP(16*2,$out),$inout2); + &movups (&QWP(16*3,$out),$inout3); + &movups (&QWP(16*4,$out),$inout4); + &lea ($out,&DWP(16*5,$out)); + &jmp (&label("xts_enc_done")); + +&set_label("xts_enc_one",16); + &movups ($inout0,&QWP(16*0,$inp)); # load input + &lea ($inp,&DWP(16*1,$inp)); + &xorps ($inout0,$inout3); # input^=tweak + if ($inline) + { &aesni_inline_generate1("enc"); } + else + { &call ("_aesni_encrypt1"); } + &xorps ($inout0,$inout3); # output^=tweak + &movups (&QWP(16*0,$out),$inout0); # write output + &lea ($out,&DWP(16*1,$out)); + + &movdqa ($tweak,$inout3); # last tweak + &jmp (&label("xts_enc_done")); + +&set_label("xts_enc_two",16); + &movaps ($inout4,$tweak); # put aside last tweak + + &movups ($inout0,&QWP(16*0,$inp)); # load input + &movups ($inout1,&QWP(16*1,$inp)); + &lea ($inp,&DWP(16*2,$inp)); + &xorps ($inout0,$inout3); # input^=tweak + &xorps ($inout1,$inout4); + + &call ("_aesni_encrypt2"); + + &xorps ($inout0,$inout3); # output^=tweak + &xorps ($inout1,$inout4); + &movups (&QWP(16*0,$out),$inout0); # write output + &movups (&QWP(16*1,$out),$inout1); + &lea ($out,&DWP(16*2,$out)); + + &movdqa ($tweak,$inout4); # last tweak + &jmp (&label("xts_enc_done")); + +&set_label("xts_enc_three",16); + &movaps ($inout5,$tweak); # put aside last tweak + &movups ($inout0,&QWP(16*0,$inp)); # load input + &movups ($inout1,&QWP(16*1,$inp)); + &movups ($inout2,&QWP(16*2,$inp)); + &lea ($inp,&DWP(16*3,$inp)); + &xorps ($inout0,$inout3); # input^=tweak + &xorps ($inout1,$inout4); + &xorps ($inout2,$inout5); + + &call ("_aesni_encrypt3"); + + &xorps ($inout0,$inout3); # output^=tweak + &xorps ($inout1,$inout4); + &xorps ($inout2,$inout5); + &movups (&QWP(16*0,$out),$inout0); # write output + &movups (&QWP(16*1,$out),$inout1); + &movups (&QWP(16*2,$out),$inout2); + &lea ($out,&DWP(16*3,$out)); + + &movdqa ($tweak,$inout5); # last tweak + &jmp (&label("xts_enc_done")); + +&set_label("xts_enc_four",16); + &movaps ($inout4,$tweak); # put aside last tweak + + &movups ($inout0,&QWP(16*0,$inp)); # load input + &movups ($inout1,&QWP(16*1,$inp)); + &movups ($inout2,&QWP(16*2,$inp)); + &xorps ($inout0,&QWP(16*0,"esp")); # input^=tweak + &movups ($inout3,&QWP(16*3,$inp)); + &lea ($inp,&DWP(16*4,$inp)); + &xorps ($inout1,&QWP(16*1,"esp")); + &xorps ($inout2,$inout5); + &xorps ($inout3,$inout4); + + &call ("_aesni_encrypt4"); + + &xorps ($inout0,&QWP(16*0,"esp")); # output^=tweak + &xorps ($inout1,&QWP(16*1,"esp")); + &xorps ($inout2,$inout5); + &movups (&QWP(16*0,$out),$inout0); # write output + &xorps ($inout3,$inout4); + &movups (&QWP(16*1,$out),$inout1); + &movups (&QWP(16*2,$out),$inout2); + &movups (&QWP(16*3,$out),$inout3); + &lea ($out,&DWP(16*4,$out)); + + &movdqa ($tweak,$inout4); # last tweak + &jmp (&label("xts_enc_done")); + +&set_label("xts_enc_done6x",16); # $tweak is pre-calculated + &mov ($len,&DWP(16*7+0,"esp")); # restore original $len + &and ($len,15); + &jz (&label("xts_enc_ret")); + &movdqa ($inout3,$tweak); + &mov (&DWP(16*7+0,"esp"),$len); # save $len%16 + &jmp (&label("xts_enc_steal")); + +&set_label("xts_enc_done",16); + &mov ($len,&DWP(16*7+0,"esp")); # restore original $len + &pxor ($twtmp,$twtmp); + &and ($len,15); + &jz (&label("xts_enc_ret")); + + &pcmpgtd($twtmp,$tweak); # broadcast upper bits + &mov (&DWP(16*7+0,"esp"),$len); # save $len%16 + &pshufd ($inout3,$twtmp,0x13); + &paddq ($tweak,$tweak); # &psllq($tweak,1); + &pand ($inout3,&QWP(16*6,"esp")); # isolate carry and residue + &pxor ($inout3,$tweak); + +&set_label("xts_enc_steal"); + &movz ($rounds,&BP(0,$inp)); + &movz ($key,&BP(-16,$out)); + &lea ($inp,&DWP(1,$inp)); + &mov (&BP(-16,$out),&LB($rounds)); + &mov (&BP(0,$out),&LB($key)); + &lea ($out,&DWP(1,$out)); + &sub ($len,1); + &jnz (&label("xts_enc_steal")); + + &sub ($out,&DWP(16*7+0,"esp")); # rewind $out + &mov ($key,$key_); # restore $key + &mov ($rounds,$rounds_); # restore $rounds + + &movups ($inout0,&QWP(-16,$out)); # load input + &xorps ($inout0,$inout3); # input^=tweak + if ($inline) + { &aesni_inline_generate1("enc"); } + else + { &call ("_aesni_encrypt1"); } + &xorps ($inout0,$inout3); # output^=tweak + &movups (&QWP(-16,$out),$inout0); # write output + +&set_label("xts_enc_ret"); + &pxor ("xmm0","xmm0"); # clear register bank + &pxor ("xmm1","xmm1"); + &pxor ("xmm2","xmm2"); + &movdqa (&QWP(16*0,"esp"),"xmm0"); # clear stack + &pxor ("xmm3","xmm3"); + &movdqa (&QWP(16*1,"esp"),"xmm0"); + &pxor ("xmm4","xmm4"); + &movdqa (&QWP(16*2,"esp"),"xmm0"); + &pxor ("xmm5","xmm5"); + &movdqa (&QWP(16*3,"esp"),"xmm0"); + &pxor ("xmm6","xmm6"); + &movdqa (&QWP(16*4,"esp"),"xmm0"); + &pxor ("xmm7","xmm7"); + &movdqa (&QWP(16*5,"esp"),"xmm0"); + &mov ("esp",&DWP(16*7+4,"esp")); # restore %esp +&function_end("aesni_xts_encrypt"); + +&function_begin("aesni_xts_decrypt"); + &mov ($key,&wparam(4)); # key2 + &mov ($inp,&wparam(5)); # clear-text tweak + + &mov ($rounds,&DWP(240,$key)); # key2->rounds + &movups ($inout0,&QWP(0,$inp)); + if ($inline) + { &aesni_inline_generate1("enc"); } + else + { &call ("_aesni_encrypt1"); } + + &mov ($inp,&wparam(0)); + &mov ($out,&wparam(1)); + &mov ($len,&wparam(2)); + &mov ($key,&wparam(3)); # key1 + + &mov ($key_,"esp"); + &sub ("esp",16*7+8); + &and ("esp",-16); # align stack + + &xor ($rounds_,$rounds_); # if(len%16) len-=16; + &test ($len,15); + &setnz (&LB($rounds_)); + &shl ($rounds_,4); + &sub ($len,$rounds_); + + &mov (&DWP(16*6+0,"esp"),0x87); # compose the magic constant + &mov (&DWP(16*6+4,"esp"),0); + &mov (&DWP(16*6+8,"esp"),1); + &mov (&DWP(16*6+12,"esp"),0); + &mov (&DWP(16*7+0,"esp"),$len); # save original $len + &mov (&DWP(16*7+4,"esp"),$key_); # save original %esp + + &mov ($rounds,&DWP(240,$key)); # key1->rounds + &mov ($key_,$key); # backup $key + &mov ($rounds_,$rounds); # backup $rounds + + &movdqa ($tweak,$inout0); + &pxor ($twtmp,$twtmp); + &movdqa ($twmask,&QWP(6*16,"esp")); # 0x0...010...87 + &pcmpgtd($twtmp,$tweak); # broadcast upper bits + + &and ($len,-16); + &sub ($len,16*6); + &jc (&label("xts_dec_short")); + + &shl ($rounds,4); + &mov ($rounds_,16); + &sub ($rounds_,$rounds); + &lea ($key,&DWP(32,$key,$rounds)); + &jmp (&label("xts_dec_loop6")); + +&set_label("xts_dec_loop6",16); + for ($i=0;$i<4;$i++) { + &pshufd ($twres,$twtmp,0x13); + &pxor ($twtmp,$twtmp); + &movdqa (&QWP(16*$i,"esp"),$tweak); + &paddq ($tweak,$tweak); # &psllq($tweak,1); + &pand ($twres,$twmask); # isolate carry and residue + &pcmpgtd ($twtmp,$tweak); # broadcast upper bits + &pxor ($tweak,$twres); + } + &pshufd ($inout5,$twtmp,0x13); + &movdqa (&QWP(16*$i++,"esp"),$tweak); + &paddq ($tweak,$tweak); # &psllq($tweak,1); + &$movekey ($rndkey0,&QWP(0,$key_)); + &pand ($inout5,$twmask); # isolate carry and residue + &movups ($inout0,&QWP(0,$inp)); # load input + &pxor ($inout5,$tweak); + + # inline _aesni_encrypt6 prologue and flip xor with tweak and key[0] + &mov ($rounds,$rounds_); + &movdqu ($inout1,&QWP(16*1,$inp)); + &xorps ($inout0,$rndkey0); # input^=rndkey[0] + &movdqu ($inout2,&QWP(16*2,$inp)); + &pxor ($inout1,$rndkey0); + &movdqu ($inout3,&QWP(16*3,$inp)); + &pxor ($inout2,$rndkey0); + &movdqu ($inout4,&QWP(16*4,$inp)); + &pxor ($inout3,$rndkey0); + &movdqu ($rndkey1,&QWP(16*5,$inp)); + &pxor ($inout4,$rndkey0); + &lea ($inp,&DWP(16*6,$inp)); + &pxor ($inout0,&QWP(16*0,"esp")); # input^=tweak + &movdqa (&QWP(16*$i,"esp"),$inout5); # save last tweak + &pxor ($inout5,$rndkey1); + + &$movekey ($rndkey1,&QWP(16,$key_)); + &pxor ($inout1,&QWP(16*1,"esp")); + &pxor ($inout2,&QWP(16*2,"esp")); + &aesdec ($inout0,$rndkey1); + &pxor ($inout3,&QWP(16*3,"esp")); + &pxor ($inout4,&QWP(16*4,"esp")); + &aesdec ($inout1,$rndkey1); + &pxor ($inout5,$rndkey0); + &$movekey ($rndkey0,&QWP(32,$key_)); + &aesdec ($inout2,$rndkey1); + &aesdec ($inout3,$rndkey1); + &aesdec ($inout4,$rndkey1); + &aesdec ($inout5,$rndkey1); + &call (&label("_aesni_decrypt6_enter")); + + &movdqa ($tweak,&QWP(16*5,"esp")); # last tweak + &pxor ($twtmp,$twtmp); + &xorps ($inout0,&QWP(16*0,"esp")); # output^=tweak + &pcmpgtd ($twtmp,$tweak); # broadcast upper bits + &xorps ($inout1,&QWP(16*1,"esp")); + &movups (&QWP(16*0,$out),$inout0); # write output + &xorps ($inout2,&QWP(16*2,"esp")); + &movups (&QWP(16*1,$out),$inout1); + &xorps ($inout3,&QWP(16*3,"esp")); + &movups (&QWP(16*2,$out),$inout2); + &xorps ($inout4,&QWP(16*4,"esp")); + &movups (&QWP(16*3,$out),$inout3); + &xorps ($inout5,$tweak); + &movups (&QWP(16*4,$out),$inout4); + &pshufd ($twres,$twtmp,0x13); + &movups (&QWP(16*5,$out),$inout5); + &lea ($out,&DWP(16*6,$out)); + &movdqa ($twmask,&QWP(16*6,"esp")); # 0x0...010...87 + + &pxor ($twtmp,$twtmp); + &paddq ($tweak,$tweak); # &psllq($tweak,1); + &pand ($twres,$twmask); # isolate carry and residue + &pcmpgtd($twtmp,$tweak); # broadcast upper bits + &pxor ($tweak,$twres); + + &sub ($len,16*6); + &jnc (&label("xts_dec_loop6")); + + &mov ($rounds,&DWP(240,$key_)); # restore $rounds + &mov ($key,$key_); # restore $key + &mov ($rounds_,$rounds); + +&set_label("xts_dec_short"); + &add ($len,16*6); + &jz (&label("xts_dec_done6x")); + + &movdqa ($inout3,$tweak); # put aside previous tweak + &cmp ($len,0x20); + &jb (&label("xts_dec_one")); + + &pshufd ($twres,$twtmp,0x13); + &pxor ($twtmp,$twtmp); + &paddq ($tweak,$tweak); # &psllq($tweak,1); + &pand ($twres,$twmask); # isolate carry and residue + &pcmpgtd($twtmp,$tweak); # broadcast upper bits + &pxor ($tweak,$twres); + &je (&label("xts_dec_two")); + + &pshufd ($twres,$twtmp,0x13); + &pxor ($twtmp,$twtmp); + &movdqa ($inout4,$tweak); # put aside previous tweak + &paddq ($tweak,$tweak); # &psllq($tweak,1); + &pand ($twres,$twmask); # isolate carry and residue + &pcmpgtd($twtmp,$tweak); # broadcast upper bits + &pxor ($tweak,$twres); + &cmp ($len,0x40); + &jb (&label("xts_dec_three")); + + &pshufd ($twres,$twtmp,0x13); + &pxor ($twtmp,$twtmp); + &movdqa ($inout5,$tweak); # put aside previous tweak + &paddq ($tweak,$tweak); # &psllq($tweak,1); + &pand ($twres,$twmask); # isolate carry and residue + &pcmpgtd($twtmp,$tweak); # broadcast upper bits + &pxor ($tweak,$twres); + &movdqa (&QWP(16*0,"esp"),$inout3); + &movdqa (&QWP(16*1,"esp"),$inout4); + &je (&label("xts_dec_four")); + + &movdqa (&QWP(16*2,"esp"),$inout5); + &pshufd ($inout5,$twtmp,0x13); + &movdqa (&QWP(16*3,"esp"),$tweak); + &paddq ($tweak,$tweak); # &psllq($inout0,1); + &pand ($inout5,$twmask); # isolate carry and residue + &pxor ($inout5,$tweak); + + &movdqu ($inout0,&QWP(16*0,$inp)); # load input + &movdqu ($inout1,&QWP(16*1,$inp)); + &movdqu ($inout2,&QWP(16*2,$inp)); + &pxor ($inout0,&QWP(16*0,"esp")); # input^=tweak + &movdqu ($inout3,&QWP(16*3,$inp)); + &pxor ($inout1,&QWP(16*1,"esp")); + &movdqu ($inout4,&QWP(16*4,$inp)); + &pxor ($inout2,&QWP(16*2,"esp")); + &lea ($inp,&DWP(16*5,$inp)); + &pxor ($inout3,&QWP(16*3,"esp")); + &movdqa (&QWP(16*4,"esp"),$inout5); # save last tweak + &pxor ($inout4,$inout5); + + &call ("_aesni_decrypt6"); + + &movaps ($tweak,&QWP(16*4,"esp")); # last tweak + &xorps ($inout0,&QWP(16*0,"esp")); # output^=tweak + &xorps ($inout1,&QWP(16*1,"esp")); + &xorps ($inout2,&QWP(16*2,"esp")); + &movups (&QWP(16*0,$out),$inout0); # write output + &xorps ($inout3,&QWP(16*3,"esp")); + &movups (&QWP(16*1,$out),$inout1); + &xorps ($inout4,$tweak); + &movups (&QWP(16*2,$out),$inout2); + &movups (&QWP(16*3,$out),$inout3); + &movups (&QWP(16*4,$out),$inout4); + &lea ($out,&DWP(16*5,$out)); + &jmp (&label("xts_dec_done")); + +&set_label("xts_dec_one",16); + &movups ($inout0,&QWP(16*0,$inp)); # load input + &lea ($inp,&DWP(16*1,$inp)); + &xorps ($inout0,$inout3); # input^=tweak + if ($inline) + { &aesni_inline_generate1("dec"); } + else + { &call ("_aesni_decrypt1"); } + &xorps ($inout0,$inout3); # output^=tweak + &movups (&QWP(16*0,$out),$inout0); # write output + &lea ($out,&DWP(16*1,$out)); + + &movdqa ($tweak,$inout3); # last tweak + &jmp (&label("xts_dec_done")); + +&set_label("xts_dec_two",16); + &movaps ($inout4,$tweak); # put aside last tweak + + &movups ($inout0,&QWP(16*0,$inp)); # load input + &movups ($inout1,&QWP(16*1,$inp)); + &lea ($inp,&DWP(16*2,$inp)); + &xorps ($inout0,$inout3); # input^=tweak + &xorps ($inout1,$inout4); + + &call ("_aesni_decrypt2"); + + &xorps ($inout0,$inout3); # output^=tweak + &xorps ($inout1,$inout4); + &movups (&QWP(16*0,$out),$inout0); # write output + &movups (&QWP(16*1,$out),$inout1); + &lea ($out,&DWP(16*2,$out)); + + &movdqa ($tweak,$inout4); # last tweak + &jmp (&label("xts_dec_done")); + +&set_label("xts_dec_three",16); + &movaps ($inout5,$tweak); # put aside last tweak + &movups ($inout0,&QWP(16*0,$inp)); # load input + &movups ($inout1,&QWP(16*1,$inp)); + &movups ($inout2,&QWP(16*2,$inp)); + &lea ($inp,&DWP(16*3,$inp)); + &xorps ($inout0,$inout3); # input^=tweak + &xorps ($inout1,$inout4); + &xorps ($inout2,$inout5); + + &call ("_aesni_decrypt3"); + + &xorps ($inout0,$inout3); # output^=tweak + &xorps ($inout1,$inout4); + &xorps ($inout2,$inout5); + &movups (&QWP(16*0,$out),$inout0); # write output + &movups (&QWP(16*1,$out),$inout1); + &movups (&QWP(16*2,$out),$inout2); + &lea ($out,&DWP(16*3,$out)); + + &movdqa ($tweak,$inout5); # last tweak + &jmp (&label("xts_dec_done")); + +&set_label("xts_dec_four",16); + &movaps ($inout4,$tweak); # put aside last tweak + + &movups ($inout0,&QWP(16*0,$inp)); # load input + &movups ($inout1,&QWP(16*1,$inp)); + &movups ($inout2,&QWP(16*2,$inp)); + &xorps ($inout0,&QWP(16*0,"esp")); # input^=tweak + &movups ($inout3,&QWP(16*3,$inp)); + &lea ($inp,&DWP(16*4,$inp)); + &xorps ($inout1,&QWP(16*1,"esp")); + &xorps ($inout2,$inout5); + &xorps ($inout3,$inout4); + + &call ("_aesni_decrypt4"); + + &xorps ($inout0,&QWP(16*0,"esp")); # output^=tweak + &xorps ($inout1,&QWP(16*1,"esp")); + &xorps ($inout2,$inout5); + &movups (&QWP(16*0,$out),$inout0); # write output + &xorps ($inout3,$inout4); + &movups (&QWP(16*1,$out),$inout1); + &movups (&QWP(16*2,$out),$inout2); + &movups (&QWP(16*3,$out),$inout3); + &lea ($out,&DWP(16*4,$out)); + + &movdqa ($tweak,$inout4); # last tweak + &jmp (&label("xts_dec_done")); + +&set_label("xts_dec_done6x",16); # $tweak is pre-calculated + &mov ($len,&DWP(16*7+0,"esp")); # restore original $len + &and ($len,15); + &jz (&label("xts_dec_ret")); + &mov (&DWP(16*7+0,"esp"),$len); # save $len%16 + &jmp (&label("xts_dec_only_one_more")); + +&set_label("xts_dec_done",16); + &mov ($len,&DWP(16*7+0,"esp")); # restore original $len + &pxor ($twtmp,$twtmp); + &and ($len,15); + &jz (&label("xts_dec_ret")); + + &pcmpgtd($twtmp,$tweak); # broadcast upper bits + &mov (&DWP(16*7+0,"esp"),$len); # save $len%16 + &pshufd ($twres,$twtmp,0x13); + &pxor ($twtmp,$twtmp); + &movdqa ($twmask,&QWP(16*6,"esp")); + &paddq ($tweak,$tweak); # &psllq($tweak,1); + &pand ($twres,$twmask); # isolate carry and residue + &pcmpgtd($twtmp,$tweak); # broadcast upper bits + &pxor ($tweak,$twres); + +&set_label("xts_dec_only_one_more"); + &pshufd ($inout3,$twtmp,0x13); + &movdqa ($inout4,$tweak); # put aside previous tweak + &paddq ($tweak,$tweak); # &psllq($tweak,1); + &pand ($inout3,$twmask); # isolate carry and residue + &pxor ($inout3,$tweak); + + &mov ($key,$key_); # restore $key + &mov ($rounds,$rounds_); # restore $rounds + + &movups ($inout0,&QWP(0,$inp)); # load input + &xorps ($inout0,$inout3); # input^=tweak + if ($inline) + { &aesni_inline_generate1("dec"); } + else + { &call ("_aesni_decrypt1"); } + &xorps ($inout0,$inout3); # output^=tweak + &movups (&QWP(0,$out),$inout0); # write output + +&set_label("xts_dec_steal"); + &movz ($rounds,&BP(16,$inp)); + &movz ($key,&BP(0,$out)); + &lea ($inp,&DWP(1,$inp)); + &mov (&BP(0,$out),&LB($rounds)); + &mov (&BP(16,$out),&LB($key)); + &lea ($out,&DWP(1,$out)); + &sub ($len,1); + &jnz (&label("xts_dec_steal")); + + &sub ($out,&DWP(16*7+0,"esp")); # rewind $out + &mov ($key,$key_); # restore $key + &mov ($rounds,$rounds_); # restore $rounds + + &movups ($inout0,&QWP(0,$out)); # load input + &xorps ($inout0,$inout4); # input^=tweak + if ($inline) + { &aesni_inline_generate1("dec"); } + else + { &call ("_aesni_decrypt1"); } + &xorps ($inout0,$inout4); # output^=tweak + &movups (&QWP(0,$out),$inout0); # write output + +&set_label("xts_dec_ret"); + &pxor ("xmm0","xmm0"); # clear register bank + &pxor ("xmm1","xmm1"); + &pxor ("xmm2","xmm2"); + &movdqa (&QWP(16*0,"esp"),"xmm0"); # clear stack + &pxor ("xmm3","xmm3"); + &movdqa (&QWP(16*1,"esp"),"xmm0"); + &pxor ("xmm4","xmm4"); + &movdqa (&QWP(16*2,"esp"),"xmm0"); + &pxor ("xmm5","xmm5"); + &movdqa (&QWP(16*3,"esp"),"xmm0"); + &pxor ("xmm6","xmm6"); + &movdqa (&QWP(16*4,"esp"),"xmm0"); + &pxor ("xmm7","xmm7"); + &movdqa (&QWP(16*5,"esp"),"xmm0"); + &mov ("esp",&DWP(16*7+4,"esp")); # restore %esp +&function_end("aesni_xts_decrypt"); +} +} + +###################################################################### +# void $PREFIX_cbc_encrypt (const void *inp, void *out, +# size_t length, const AES_KEY *key, +# unsigned char *ivp,const int enc); +&function_begin("${PREFIX}_cbc_encrypt"); + &mov ($inp,&wparam(0)); + &mov ($rounds_,"esp"); + &mov ($out,&wparam(1)); + &sub ($rounds_,24); + &mov ($len,&wparam(2)); + &and ($rounds_,-16); + &mov ($key,&wparam(3)); + &mov ($key_,&wparam(4)); + &test ($len,$len); + &jz (&label("cbc_abort")); + + &cmp (&wparam(5),0); + &xchg ($rounds_,"esp"); # alloca + &movups ($ivec,&QWP(0,$key_)); # load IV + &mov ($rounds,&DWP(240,$key)); + &mov ($key_,$key); # backup $key + &mov (&DWP(16,"esp"),$rounds_); # save original %esp + &mov ($rounds_,$rounds); # backup $rounds + &je (&label("cbc_decrypt")); + + &movaps ($inout0,$ivec); + &cmp ($len,16); + &jb (&label("cbc_enc_tail")); + &sub ($len,16); + &jmp (&label("cbc_enc_loop")); + +&set_label("cbc_enc_loop",16); + &movups ($ivec,&QWP(0,$inp)); # input actually + &lea ($inp,&DWP(16,$inp)); + if ($inline) + { &aesni_inline_generate1("enc",$inout0,$ivec); } + else + { &xorps($inout0,$ivec); &call("_aesni_encrypt1"); } + &mov ($rounds,$rounds_); # restore $rounds + &mov ($key,$key_); # restore $key + &movups (&QWP(0,$out),$inout0); # store output + &lea ($out,&DWP(16,$out)); + &sub ($len,16); + &jnc (&label("cbc_enc_loop")); + &add ($len,16); + &jnz (&label("cbc_enc_tail")); + &movaps ($ivec,$inout0); + &pxor ($inout0,$inout0); + &jmp (&label("cbc_ret")); + +&set_label("cbc_enc_tail"); + &mov ("ecx",$len); # zaps $rounds + &data_word(0xA4F3F689); # rep movsb + &mov ("ecx",16); # zero tail + &sub ("ecx",$len); + &xor ("eax","eax"); # zaps $len + &data_word(0xAAF3F689); # rep stosb + &lea ($out,&DWP(-16,$out)); # rewind $out by 1 block + &mov ($rounds,$rounds_); # restore $rounds + &mov ($inp,$out); # $inp and $out are the same + &mov ($key,$key_); # restore $key + &jmp (&label("cbc_enc_loop")); +###################################################################### +&set_label("cbc_decrypt",16); + &cmp ($len,0x50); + &jbe (&label("cbc_dec_tail")); + &movaps (&QWP(0,"esp"),$ivec); # save IV + &sub ($len,0x50); + &jmp (&label("cbc_dec_loop6_enter")); + +&set_label("cbc_dec_loop6",16); + &movaps (&QWP(0,"esp"),$rndkey0); # save IV + &movups (&QWP(0,$out),$inout5); + &lea ($out,&DWP(0x10,$out)); +&set_label("cbc_dec_loop6_enter"); + &movdqu ($inout0,&QWP(0,$inp)); + &movdqu ($inout1,&QWP(0x10,$inp)); + &movdqu ($inout2,&QWP(0x20,$inp)); + &movdqu ($inout3,&QWP(0x30,$inp)); + &movdqu ($inout4,&QWP(0x40,$inp)); + &movdqu ($inout5,&QWP(0x50,$inp)); + + &call ("_aesni_decrypt6"); + + &movups ($rndkey1,&QWP(0,$inp)); + &movups ($rndkey0,&QWP(0x10,$inp)); + &xorps ($inout0,&QWP(0,"esp")); # ^=IV + &xorps ($inout1,$rndkey1); + &movups ($rndkey1,&QWP(0x20,$inp)); + &xorps ($inout2,$rndkey0); + &movups ($rndkey0,&QWP(0x30,$inp)); + &xorps ($inout3,$rndkey1); + &movups ($rndkey1,&QWP(0x40,$inp)); + &xorps ($inout4,$rndkey0); + &movups ($rndkey0,&QWP(0x50,$inp)); # IV + &xorps ($inout5,$rndkey1); + &movups (&QWP(0,$out),$inout0); + &movups (&QWP(0x10,$out),$inout1); + &lea ($inp,&DWP(0x60,$inp)); + &movups (&QWP(0x20,$out),$inout2); + &mov ($rounds,$rounds_); # restore $rounds + &movups (&QWP(0x30,$out),$inout3); + &mov ($key,$key_); # restore $key + &movups (&QWP(0x40,$out),$inout4); + &lea ($out,&DWP(0x50,$out)); + &sub ($len,0x60); + &ja (&label("cbc_dec_loop6")); + + &movaps ($inout0,$inout5); + &movaps ($ivec,$rndkey0); + &add ($len,0x50); + &jle (&label("cbc_dec_clear_tail_collected")); + &movups (&QWP(0,$out),$inout0); + &lea ($out,&DWP(0x10,$out)); +&set_label("cbc_dec_tail"); + &movups ($inout0,&QWP(0,$inp)); + &movaps ($in0,$inout0); + &cmp ($len,0x10); + &jbe (&label("cbc_dec_one")); + + &movups ($inout1,&QWP(0x10,$inp)); + &movaps ($in1,$inout1); + &cmp ($len,0x20); + &jbe (&label("cbc_dec_two")); + + &movups ($inout2,&QWP(0x20,$inp)); + &cmp ($len,0x30); + &jbe (&label("cbc_dec_three")); + + &movups ($inout3,&QWP(0x30,$inp)); + &cmp ($len,0x40); + &jbe (&label("cbc_dec_four")); + + &movups ($inout4,&QWP(0x40,$inp)); + &movaps (&QWP(0,"esp"),$ivec); # save IV + &movups ($inout0,&QWP(0,$inp)); + &xorps ($inout5,$inout5); + &call ("_aesni_decrypt6"); + &movups ($rndkey1,&QWP(0,$inp)); + &movups ($rndkey0,&QWP(0x10,$inp)); + &xorps ($inout0,&QWP(0,"esp")); # ^= IV + &xorps ($inout1,$rndkey1); + &movups ($rndkey1,&QWP(0x20,$inp)); + &xorps ($inout2,$rndkey0); + &movups ($rndkey0,&QWP(0x30,$inp)); + &xorps ($inout3,$rndkey1); + &movups ($ivec,&QWP(0x40,$inp)); # IV + &xorps ($inout4,$rndkey0); + &movups (&QWP(0,$out),$inout0); + &movups (&QWP(0x10,$out),$inout1); + &pxor ($inout1,$inout1); + &movups (&QWP(0x20,$out),$inout2); + &pxor ($inout2,$inout2); + &movups (&QWP(0x30,$out),$inout3); + &pxor ($inout3,$inout3); + &lea ($out,&DWP(0x40,$out)); + &movaps ($inout0,$inout4); + &pxor ($inout4,$inout4); + &sub ($len,0x50); + &jmp (&label("cbc_dec_tail_collected")); + +&set_label("cbc_dec_one",16); + if ($inline) + { &aesni_inline_generate1("dec"); } + else + { &call ("_aesni_decrypt1"); } + &xorps ($inout0,$ivec); + &movaps ($ivec,$in0); + &sub ($len,0x10); + &jmp (&label("cbc_dec_tail_collected")); + +&set_label("cbc_dec_two",16); + &call ("_aesni_decrypt2"); + &xorps ($inout0,$ivec); + &xorps ($inout1,$in0); + &movups (&QWP(0,$out),$inout0); + &movaps ($inout0,$inout1); + &pxor ($inout1,$inout1); + &lea ($out,&DWP(0x10,$out)); + &movaps ($ivec,$in1); + &sub ($len,0x20); + &jmp (&label("cbc_dec_tail_collected")); + +&set_label("cbc_dec_three",16); + &call ("_aesni_decrypt3"); + &xorps ($inout0,$ivec); + &xorps ($inout1,$in0); + &xorps ($inout2,$in1); + &movups (&QWP(0,$out),$inout0); + &movaps ($inout0,$inout2); + &pxor ($inout2,$inout2); + &movups (&QWP(0x10,$out),$inout1); + &pxor ($inout1,$inout1); + &lea ($out,&DWP(0x20,$out)); + &movups ($ivec,&QWP(0x20,$inp)); + &sub ($len,0x30); + &jmp (&label("cbc_dec_tail_collected")); + +&set_label("cbc_dec_four",16); + &call ("_aesni_decrypt4"); + &movups ($rndkey1,&QWP(0x10,$inp)); + &movups ($rndkey0,&QWP(0x20,$inp)); + &xorps ($inout0,$ivec); + &movups ($ivec,&QWP(0x30,$inp)); + &xorps ($inout1,$in0); + &movups (&QWP(0,$out),$inout0); + &xorps ($inout2,$rndkey1); + &movups (&QWP(0x10,$out),$inout1); + &pxor ($inout1,$inout1); + &xorps ($inout3,$rndkey0); + &movups (&QWP(0x20,$out),$inout2); + &pxor ($inout2,$inout2); + &lea ($out,&DWP(0x30,$out)); + &movaps ($inout0,$inout3); + &pxor ($inout3,$inout3); + &sub ($len,0x40); + &jmp (&label("cbc_dec_tail_collected")); + +&set_label("cbc_dec_clear_tail_collected",16); + &pxor ($inout1,$inout1); + &pxor ($inout2,$inout2); + &pxor ($inout3,$inout3); + &pxor ($inout4,$inout4); +&set_label("cbc_dec_tail_collected"); + &and ($len,15); + &jnz (&label("cbc_dec_tail_partial")); + &movups (&QWP(0,$out),$inout0); + &pxor ($rndkey0,$rndkey0); + &jmp (&label("cbc_ret")); + +&set_label("cbc_dec_tail_partial",16); + &movaps (&QWP(0,"esp"),$inout0); + &pxor ($rndkey0,$rndkey0); + &mov ("ecx",16); + &mov ($inp,"esp"); + &sub ("ecx",$len); + &data_word(0xA4F3F689); # rep movsb + &movdqa (&QWP(0,"esp"),$inout0); + +&set_label("cbc_ret"); + &mov ("esp",&DWP(16,"esp")); # pull original %esp + &mov ($key_,&wparam(4)); + &pxor ($inout0,$inout0); + &pxor ($rndkey1,$rndkey1); + &movups (&QWP(0,$key_),$ivec); # output IV + &pxor ($ivec,$ivec); +&set_label("cbc_abort"); +&function_end("${PREFIX}_cbc_encrypt"); + +###################################################################### +# Mechanical port from aesni-x86_64.pl. +# +# _aesni_set_encrypt_key is private interface, +# input: +# "eax" const unsigned char *userKey +# $rounds int bits +# $key AES_KEY *key +# output: +# "eax" return code +# $round rounds + +&function_begin_B("_aesni_set_encrypt_key"); + &push ("ebp"); + &push ("ebx"); + &test ("eax","eax"); + &jz (&label("bad_pointer")); + &test ($key,$key); + &jz (&label("bad_pointer")); + + &call (&label("pic")); +&set_label("pic"); + &blindpop("ebx"); + &lea ("ebx",&DWP(&label("key_const")."-".&label("pic"),"ebx")); + + &picmeup("ebp","OPENSSL_ia32cap_P","ebx",&label("key_const")); + &movups ("xmm0",&QWP(0,"eax")); # pull first 128 bits of *userKey + &xorps ("xmm4","xmm4"); # low dword of xmm4 is assumed 0 + &mov ("ebp",&DWP(4,"ebp")); + &lea ($key,&DWP(16,$key)); + &and ("ebp",1<<28|1<<11); # AVX and XOP bits + &cmp ($rounds,256); + &je (&label("14rounds")); + &cmp ($rounds,192); + &je (&label("12rounds")); + &cmp ($rounds,128); + &jne (&label("bad_keybits")); + +&set_label("10rounds",16); + &cmp ("ebp",1<<28); + &je (&label("10rounds_alt")); + + &mov ($rounds,9); + &$movekey (&QWP(-16,$key),"xmm0"); # round 0 + &aeskeygenassist("xmm1","xmm0",0x01); # round 1 + &call (&label("key_128_cold")); + &aeskeygenassist("xmm1","xmm0",0x2); # round 2 + &call (&label("key_128")); + &aeskeygenassist("xmm1","xmm0",0x04); # round 3 + &call (&label("key_128")); + &aeskeygenassist("xmm1","xmm0",0x08); # round 4 + &call (&label("key_128")); + &aeskeygenassist("xmm1","xmm0",0x10); # round 5 + &call (&label("key_128")); + &aeskeygenassist("xmm1","xmm0",0x20); # round 6 + &call (&label("key_128")); + &aeskeygenassist("xmm1","xmm0",0x40); # round 7 + &call (&label("key_128")); + &aeskeygenassist("xmm1","xmm0",0x80); # round 8 + &call (&label("key_128")); + &aeskeygenassist("xmm1","xmm0",0x1b); # round 9 + &call (&label("key_128")); + &aeskeygenassist("xmm1","xmm0",0x36); # round 10 + &call (&label("key_128")); + &$movekey (&QWP(0,$key),"xmm0"); + &mov (&DWP(80,$key),$rounds); + + &jmp (&label("good_key")); + +&set_label("key_128",16); + &$movekey (&QWP(0,$key),"xmm0"); + &lea ($key,&DWP(16,$key)); +&set_label("key_128_cold"); + &shufps ("xmm4","xmm0",0b00010000); + &xorps ("xmm0","xmm4"); + &shufps ("xmm4","xmm0",0b10001100); + &xorps ("xmm0","xmm4"); + &shufps ("xmm1","xmm1",0b11111111); # critical path + &xorps ("xmm0","xmm1"); + &ret(); + +&set_label("10rounds_alt",16); + &movdqa ("xmm5",&QWP(0x00,"ebx")); + &mov ($rounds,8); + &movdqa ("xmm4",&QWP(0x20,"ebx")); + &movdqa ("xmm2","xmm0"); + &movdqu (&QWP(-16,$key),"xmm0"); + +&set_label("loop_key128"); + &pshufb ("xmm0","xmm5"); + &aesenclast ("xmm0","xmm4"); + &pslld ("xmm4",1); + &lea ($key,&DWP(16,$key)); + + &movdqa ("xmm3","xmm2"); + &pslldq ("xmm2",4); + &pxor ("xmm3","xmm2"); + &pslldq ("xmm2",4); + &pxor ("xmm3","xmm2"); + &pslldq ("xmm2",4); + &pxor ("xmm2","xmm3"); + + &pxor ("xmm0","xmm2"); + &movdqu (&QWP(-16,$key),"xmm0"); + &movdqa ("xmm2","xmm0"); + + &dec ($rounds); + &jnz (&label("loop_key128")); + + &movdqa ("xmm4",&QWP(0x30,"ebx")); + + &pshufb ("xmm0","xmm5"); + &aesenclast ("xmm0","xmm4"); + &pslld ("xmm4",1); + + &movdqa ("xmm3","xmm2"); + &pslldq ("xmm2",4); + &pxor ("xmm3","xmm2"); + &pslldq ("xmm2",4); + &pxor ("xmm3","xmm2"); + &pslldq ("xmm2",4); + &pxor ("xmm2","xmm3"); + + &pxor ("xmm0","xmm2"); + &movdqu (&QWP(0,$key),"xmm0"); + + &movdqa ("xmm2","xmm0"); + &pshufb ("xmm0","xmm5"); + &aesenclast ("xmm0","xmm4"); + + &movdqa ("xmm3","xmm2"); + &pslldq ("xmm2",4); + &pxor ("xmm3","xmm2"); + &pslldq ("xmm2",4); + &pxor ("xmm3","xmm2"); + &pslldq ("xmm2",4); + &pxor ("xmm2","xmm3"); + + &pxor ("xmm0","xmm2"); + &movdqu (&QWP(16,$key),"xmm0"); + + &mov ($rounds,9); + &mov (&DWP(96,$key),$rounds); + + &jmp (&label("good_key")); + +&set_label("12rounds",16); + &movq ("xmm2",&QWP(16,"eax")); # remaining 1/3 of *userKey + &cmp ("ebp",1<<28); + &je (&label("12rounds_alt")); + + &mov ($rounds,11); + &$movekey (&QWP(-16,$key),"xmm0"); # round 0 + &aeskeygenassist("xmm1","xmm2",0x01); # round 1,2 + &call (&label("key_192a_cold")); + &aeskeygenassist("xmm1","xmm2",0x02); # round 2,3 + &call (&label("key_192b")); + &aeskeygenassist("xmm1","xmm2",0x04); # round 4,5 + &call (&label("key_192a")); + &aeskeygenassist("xmm1","xmm2",0x08); # round 5,6 + &call (&label("key_192b")); + &aeskeygenassist("xmm1","xmm2",0x10); # round 7,8 + &call (&label("key_192a")); + &aeskeygenassist("xmm1","xmm2",0x20); # round 8,9 + &call (&label("key_192b")); + &aeskeygenassist("xmm1","xmm2",0x40); # round 10,11 + &call (&label("key_192a")); + &aeskeygenassist("xmm1","xmm2",0x80); # round 11,12 + &call (&label("key_192b")); + &$movekey (&QWP(0,$key),"xmm0"); + &mov (&DWP(48,$key),$rounds); + + &jmp (&label("good_key")); + +&set_label("key_192a",16); + &$movekey (&QWP(0,$key),"xmm0"); + &lea ($key,&DWP(16,$key)); +&set_label("key_192a_cold",16); + &movaps ("xmm5","xmm2"); +&set_label("key_192b_warm"); + &shufps ("xmm4","xmm0",0b00010000); + &movdqa ("xmm3","xmm2"); + &xorps ("xmm0","xmm4"); + &shufps ("xmm4","xmm0",0b10001100); + &pslldq ("xmm3",4); + &xorps ("xmm0","xmm4"); + &pshufd ("xmm1","xmm1",0b01010101); # critical path + &pxor ("xmm2","xmm3"); + &pxor ("xmm0","xmm1"); + &pshufd ("xmm3","xmm0",0b11111111); + &pxor ("xmm2","xmm3"); + &ret(); + +&set_label("key_192b",16); + &movaps ("xmm3","xmm0"); + &shufps ("xmm5","xmm0",0b01000100); + &$movekey (&QWP(0,$key),"xmm5"); + &shufps ("xmm3","xmm2",0b01001110); + &$movekey (&QWP(16,$key),"xmm3"); + &lea ($key,&DWP(32,$key)); + &jmp (&label("key_192b_warm")); + +&set_label("12rounds_alt",16); + &movdqa ("xmm5",&QWP(0x10,"ebx")); + &movdqa ("xmm4",&QWP(0x20,"ebx")); + &mov ($rounds,8); + &movdqu (&QWP(-16,$key),"xmm0"); + +&set_label("loop_key192"); + &movq (&QWP(0,$key),"xmm2"); + &movdqa ("xmm1","xmm2"); + &pshufb ("xmm2","xmm5"); + &aesenclast ("xmm2","xmm4"); + &pslld ("xmm4",1); + &lea ($key,&DWP(24,$key)); + + &movdqa ("xmm3","xmm0"); + &pslldq ("xmm0",4); + &pxor ("xmm3","xmm0"); + &pslldq ("xmm0",4); + &pxor ("xmm3","xmm0"); + &pslldq ("xmm0",4); + &pxor ("xmm0","xmm3"); + + &pshufd ("xmm3","xmm0",0xff); + &pxor ("xmm3","xmm1"); + &pslldq ("xmm1",4); + &pxor ("xmm3","xmm1"); + + &pxor ("xmm0","xmm2"); + &pxor ("xmm2","xmm3"); + &movdqu (&QWP(-16,$key),"xmm0"); + + &dec ($rounds); + &jnz (&label("loop_key192")); + + &mov ($rounds,11); + &mov (&DWP(32,$key),$rounds); + + &jmp (&label("good_key")); + +&set_label("14rounds",16); + &movups ("xmm2",&QWP(16,"eax")); # remaining half of *userKey + &lea ($key,&DWP(16,$key)); + &cmp ("ebp",1<<28); + &je (&label("14rounds_alt")); + + &mov ($rounds,13); + &$movekey (&QWP(-32,$key),"xmm0"); # round 0 + &$movekey (&QWP(-16,$key),"xmm2"); # round 1 + &aeskeygenassist("xmm1","xmm2",0x01); # round 2 + &call (&label("key_256a_cold")); + &aeskeygenassist("xmm1","xmm0",0x01); # round 3 + &call (&label("key_256b")); + &aeskeygenassist("xmm1","xmm2",0x02); # round 4 + &call (&label("key_256a")); + &aeskeygenassist("xmm1","xmm0",0x02); # round 5 + &call (&label("key_256b")); + &aeskeygenassist("xmm1","xmm2",0x04); # round 6 + &call (&label("key_256a")); + &aeskeygenassist("xmm1","xmm0",0x04); # round 7 + &call (&label("key_256b")); + &aeskeygenassist("xmm1","xmm2",0x08); # round 8 + &call (&label("key_256a")); + &aeskeygenassist("xmm1","xmm0",0x08); # round 9 + &call (&label("key_256b")); + &aeskeygenassist("xmm1","xmm2",0x10); # round 10 + &call (&label("key_256a")); + &aeskeygenassist("xmm1","xmm0",0x10); # round 11 + &call (&label("key_256b")); + &aeskeygenassist("xmm1","xmm2",0x20); # round 12 + &call (&label("key_256a")); + &aeskeygenassist("xmm1","xmm0",0x20); # round 13 + &call (&label("key_256b")); + &aeskeygenassist("xmm1","xmm2",0x40); # round 14 + &call (&label("key_256a")); + &$movekey (&QWP(0,$key),"xmm0"); + &mov (&DWP(16,$key),$rounds); + &xor ("eax","eax"); + + &jmp (&label("good_key")); + +&set_label("key_256a",16); + &$movekey (&QWP(0,$key),"xmm2"); + &lea ($key,&DWP(16,$key)); +&set_label("key_256a_cold"); + &shufps ("xmm4","xmm0",0b00010000); + &xorps ("xmm0","xmm4"); + &shufps ("xmm4","xmm0",0b10001100); + &xorps ("xmm0","xmm4"); + &shufps ("xmm1","xmm1",0b11111111); # critical path + &xorps ("xmm0","xmm1"); + &ret(); + +&set_label("key_256b",16); + &$movekey (&QWP(0,$key),"xmm0"); + &lea ($key,&DWP(16,$key)); + + &shufps ("xmm4","xmm2",0b00010000); + &xorps ("xmm2","xmm4"); + &shufps ("xmm4","xmm2",0b10001100); + &xorps ("xmm2","xmm4"); + &shufps ("xmm1","xmm1",0b10101010); # critical path + &xorps ("xmm2","xmm1"); + &ret(); + +&set_label("14rounds_alt",16); + &movdqa ("xmm5",&QWP(0x00,"ebx")); + &movdqa ("xmm4",&QWP(0x20,"ebx")); + &mov ($rounds,7); + &movdqu (&QWP(-32,$key),"xmm0"); + &movdqa ("xmm1","xmm2"); + &movdqu (&QWP(-16,$key),"xmm2"); + +&set_label("loop_key256"); + &pshufb ("xmm2","xmm5"); + &aesenclast ("xmm2","xmm4"); + + &movdqa ("xmm3","xmm0"); + &pslldq ("xmm0",4); + &pxor ("xmm3","xmm0"); + &pslldq ("xmm0",4); + &pxor ("xmm3","xmm0"); + &pslldq ("xmm0",4); + &pxor ("xmm0","xmm3"); + &pslld ("xmm4",1); + + &pxor ("xmm0","xmm2"); + &movdqu (&QWP(0,$key),"xmm0"); + + &dec ($rounds); + &jz (&label("done_key256")); + + &pshufd ("xmm2","xmm0",0xff); + &pxor ("xmm3","xmm3"); + &aesenclast ("xmm2","xmm3"); + + &movdqa ("xmm3","xmm1") + &pslldq ("xmm1",4); + &pxor ("xmm3","xmm1"); + &pslldq ("xmm1",4); + &pxor ("xmm3","xmm1"); + &pslldq ("xmm1",4); + &pxor ("xmm1","xmm3"); + + &pxor ("xmm2","xmm1"); + &movdqu (&QWP(16,$key),"xmm2"); + &lea ($key,&DWP(32,$key)); + &movdqa ("xmm1","xmm2"); + &jmp (&label("loop_key256")); + +&set_label("done_key256"); + &mov ($rounds,13); + &mov (&DWP(16,$key),$rounds); + +&set_label("good_key"); + &pxor ("xmm0","xmm0"); + &pxor ("xmm1","xmm1"); + &pxor ("xmm2","xmm2"); + &pxor ("xmm3","xmm3"); + &pxor ("xmm4","xmm4"); + &pxor ("xmm5","xmm5"); + &xor ("eax","eax"); + &pop ("ebx"); + &pop ("ebp"); + &ret (); + +&set_label("bad_pointer",4); + &mov ("eax",-1); + &pop ("ebx"); + &pop ("ebp"); + &ret (); +&set_label("bad_keybits",4); + &pxor ("xmm0","xmm0"); + &mov ("eax",-2); + &pop ("ebx"); + &pop ("ebp"); + &ret (); +&function_end_B("_aesni_set_encrypt_key"); + +# int $PREFIX_set_encrypt_key (const unsigned char *userKey, int bits, +# AES_KEY *key) +&function_begin_B("${PREFIX}_set_encrypt_key"); + &mov ("eax",&wparam(0)); + &mov ($rounds,&wparam(1)); + &mov ($key,&wparam(2)); + &call ("_aesni_set_encrypt_key"); + &ret (); +&function_end_B("${PREFIX}_set_encrypt_key"); + +# int $PREFIX_set_decrypt_key (const unsigned char *userKey, int bits, +# AES_KEY *key) +&function_begin_B("${PREFIX}_set_decrypt_key"); + &mov ("eax",&wparam(0)); + &mov ($rounds,&wparam(1)); + &mov ($key,&wparam(2)); + &call ("_aesni_set_encrypt_key"); + &mov ($key,&wparam(2)); + &shl ($rounds,4); # rounds-1 after _aesni_set_encrypt_key + &test ("eax","eax"); + &jnz (&label("dec_key_ret")); + &lea ("eax",&DWP(16,$key,$rounds)); # end of key schedule + + &$movekey ("xmm0",&QWP(0,$key)); # just swap + &$movekey ("xmm1",&QWP(0,"eax")); + &$movekey (&QWP(0,"eax"),"xmm0"); + &$movekey (&QWP(0,$key),"xmm1"); + &lea ($key,&DWP(16,$key)); + &lea ("eax",&DWP(-16,"eax")); + +&set_label("dec_key_inverse"); + &$movekey ("xmm0",&QWP(0,$key)); # swap and inverse + &$movekey ("xmm1",&QWP(0,"eax")); + &aesimc ("xmm0","xmm0"); + &aesimc ("xmm1","xmm1"); + &lea ($key,&DWP(16,$key)); + &lea ("eax",&DWP(-16,"eax")); + &$movekey (&QWP(16,"eax"),"xmm0"); + &$movekey (&QWP(-16,$key),"xmm1"); + &cmp ("eax",$key); + &ja (&label("dec_key_inverse")); + + &$movekey ("xmm0",&QWP(0,$key)); # inverse middle + &aesimc ("xmm0","xmm0"); + &$movekey (&QWP(0,$key),"xmm0"); + + &pxor ("xmm0","xmm0"); + &pxor ("xmm1","xmm1"); + &xor ("eax","eax"); # return success +&set_label("dec_key_ret"); + &ret (); +&function_end_B("${PREFIX}_set_decrypt_key"); + +&set_label("key_const",64); +&data_word(0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d); +&data_word(0x04070605,0x04070605,0x04070605,0x04070605); +&data_word(1,1,1,1); +&data_word(0x1b,0x1b,0x1b,0x1b); +&asciz("AES for Intel AES-NI, CRYPTOGAMS by "); + +&asm_finish(); diff --git a/external/boringssl/crypto/aes/asm/aesni-x86_64.pl.REMOVED.git-id b/external/boringssl/crypto/aes/asm/aesni-x86_64.pl.REMOVED.git-id new file mode 100644 index 0000000000..42ccd3e88c --- /dev/null +++ b/external/boringssl/crypto/aes/asm/aesni-x86_64.pl.REMOVED.git-id @@ -0,0 +1 @@ +25ca574f6a2f90b04dccc0a7726df86772bcb996 \ No newline at end of file diff --git a/external/boringssl/crypto/aes/asm/aesv8-armx.pl b/external/boringssl/crypto/aes/asm/aesv8-armx.pl new file mode 100644 index 0000000000..121154a4b6 --- /dev/null +++ b/external/boringssl/crypto/aes/asm/aesv8-armx.pl @@ -0,0 +1,1001 @@ +#!/usr/bin/env perl +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# This module implements support for ARMv8 AES instructions. The +# module is endian-agnostic in sense that it supports both big- and +# little-endian cases. As does it support both 32- and 64-bit modes +# of operation. Latter is achieved by limiting amount of utilized +# registers to 16, which implies additional NEON load and integer +# instructions. This has no effect on mighty Apple A7, where results +# are literally equal to the theoretical estimates based on AES +# instruction latencies and issue rates. On Cortex-A53, an in-order +# execution core, this costs up to 10-15%, which is partially +# compensated by implementing dedicated code path for 128-bit +# CBC encrypt case. On Cortex-A57 parallelizable mode performance +# seems to be limited by sheer amount of NEON instructions... +# +# Performance in cycles per byte processed with 128-bit key: +# +# CBC enc CBC dec CTR +# Apple A7 2.39 1.20 1.20 +# Cortex-A53 1.32 1.29 1.46 +# Cortex-A57(*) 1.95 0.85 0.93 +# Denver 1.96 0.86 0.80 +# +# (*) original 3.64/1.34/1.32 results were for r0p0 revision +# and are still same even for updated module; + +$flavour = shift; +$output = shift; + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or +die "can't locate arm-xlate.pl"; + +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; + +$prefix="aes_v8"; + +$code=<<___; +#include + +#if __ARM_MAX_ARCH__>=7 +.text +___ +$code.=<<___ if ($flavour =~ /64/); +#if !defined(__clang__) +.arch armv8-a+crypto +#endif +___ +$code.=".arch armv7-a\n.fpu neon\n.code 32\n" if ($flavour !~ /64/); + #^^^^^^ this is done to simplify adoption by not depending + # on latest binutils. + +# Assembler mnemonics are an eclectic mix of 32- and 64-bit syntax, +# NEON is mostly 32-bit mnemonics, integer - mostly 64. Goal is to +# maintain both 32- and 64-bit codes within single module and +# transliterate common code to either flavour with regex vodoo. +# +{{{ +my ($inp,$bits,$out,$ptr,$rounds)=("x0","w1","x2","x3","w12"); +my ($zero,$rcon,$mask,$in0,$in1,$tmp,$key)= + $flavour=~/64/? map("q$_",(0..6)) : map("q$_",(0..3,8..10)); + + +$code.=<<___; +.align 5 +.Lrcon: +.long 0x01,0x01,0x01,0x01 +.long 0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d // rotate-n-splat +.long 0x1b,0x1b,0x1b,0x1b + +.globl ${prefix}_set_encrypt_key +.type ${prefix}_set_encrypt_key,%function +.align 5 +${prefix}_set_encrypt_key: +.Lenc_key: +___ +$code.=<<___ if ($flavour =~ /64/); + stp x29,x30,[sp,#-16]! + add x29,sp,#0 +___ +$code.=<<___; + mov $ptr,#-1 + cmp $inp,#0 + b.eq .Lenc_key_abort + cmp $out,#0 + b.eq .Lenc_key_abort + mov $ptr,#-2 + cmp $bits,#128 + b.lt .Lenc_key_abort + cmp $bits,#256 + b.gt .Lenc_key_abort + tst $bits,#0x3f + b.ne .Lenc_key_abort + + adr $ptr,.Lrcon + cmp $bits,#192 + + veor $zero,$zero,$zero + vld1.8 {$in0},[$inp],#16 + mov $bits,#8 // reuse $bits + vld1.32 {$rcon,$mask},[$ptr],#32 + + b.lt .Loop128 + b.eq .L192 + b .L256 + +.align 4 +.Loop128: + vtbl.8 $key,{$in0},$mask + vext.8 $tmp,$zero,$in0,#12 + vst1.32 {$in0},[$out],#16 + aese $key,$zero + subs $bits,$bits,#1 + + veor $in0,$in0,$tmp + vext.8 $tmp,$zero,$tmp,#12 + veor $in0,$in0,$tmp + vext.8 $tmp,$zero,$tmp,#12 + veor $key,$key,$rcon + veor $in0,$in0,$tmp + vshl.u8 $rcon,$rcon,#1 + veor $in0,$in0,$key + b.ne .Loop128 + + vld1.32 {$rcon},[$ptr] + + vtbl.8 $key,{$in0},$mask + vext.8 $tmp,$zero,$in0,#12 + vst1.32 {$in0},[$out],#16 + aese $key,$zero + + veor $in0,$in0,$tmp + vext.8 $tmp,$zero,$tmp,#12 + veor $in0,$in0,$tmp + vext.8 $tmp,$zero,$tmp,#12 + veor $key,$key,$rcon + veor $in0,$in0,$tmp + vshl.u8 $rcon,$rcon,#1 + veor $in0,$in0,$key + + vtbl.8 $key,{$in0},$mask + vext.8 $tmp,$zero,$in0,#12 + vst1.32 {$in0},[$out],#16 + aese $key,$zero + + veor $in0,$in0,$tmp + vext.8 $tmp,$zero,$tmp,#12 + veor $in0,$in0,$tmp + vext.8 $tmp,$zero,$tmp,#12 + veor $key,$key,$rcon + veor $in0,$in0,$tmp + veor $in0,$in0,$key + vst1.32 {$in0},[$out] + add $out,$out,#0x50 + + mov $rounds,#10 + b .Ldone + +.align 4 +.L192: + vld1.8 {$in1},[$inp],#8 + vmov.i8 $key,#8 // borrow $key + vst1.32 {$in0},[$out],#16 + vsub.i8 $mask,$mask,$key // adjust the mask + +.Loop192: + vtbl.8 $key,{$in1},$mask + vext.8 $tmp,$zero,$in0,#12 + vst1.32 {$in1},[$out],#8 + aese $key,$zero + subs $bits,$bits,#1 + + veor $in0,$in0,$tmp + vext.8 $tmp,$zero,$tmp,#12 + veor $in0,$in0,$tmp + vext.8 $tmp,$zero,$tmp,#12 + veor $in0,$in0,$tmp + + vdup.32 $tmp,${in0}[3] + veor $tmp,$tmp,$in1 + veor $key,$key,$rcon + vext.8 $in1,$zero,$in1,#12 + vshl.u8 $rcon,$rcon,#1 + veor $in1,$in1,$tmp + veor $in0,$in0,$key + veor $in1,$in1,$key + vst1.32 {$in0},[$out],#16 + b.ne .Loop192 + + mov $rounds,#12 + add $out,$out,#0x20 + b .Ldone + +.align 4 +.L256: + vld1.8 {$in1},[$inp] + mov $bits,#7 + mov $rounds,#14 + vst1.32 {$in0},[$out],#16 + +.Loop256: + vtbl.8 $key,{$in1},$mask + vext.8 $tmp,$zero,$in0,#12 + vst1.32 {$in1},[$out],#16 + aese $key,$zero + subs $bits,$bits,#1 + + veor $in0,$in0,$tmp + vext.8 $tmp,$zero,$tmp,#12 + veor $in0,$in0,$tmp + vext.8 $tmp,$zero,$tmp,#12 + veor $key,$key,$rcon + veor $in0,$in0,$tmp + vshl.u8 $rcon,$rcon,#1 + veor $in0,$in0,$key + vst1.32 {$in0},[$out],#16 + b.eq .Ldone + + vdup.32 $key,${in0}[3] // just splat + vext.8 $tmp,$zero,$in1,#12 + aese $key,$zero + + veor $in1,$in1,$tmp + vext.8 $tmp,$zero,$tmp,#12 + veor $in1,$in1,$tmp + vext.8 $tmp,$zero,$tmp,#12 + veor $in1,$in1,$tmp + + veor $in1,$in1,$key + b .Loop256 + +.Ldone: + str $rounds,[$out] + mov $ptr,#0 + +.Lenc_key_abort: + mov x0,$ptr // return value + `"ldr x29,[sp],#16" if ($flavour =~ /64/)` + ret +.size ${prefix}_set_encrypt_key,.-${prefix}_set_encrypt_key + +.globl ${prefix}_set_decrypt_key +.type ${prefix}_set_decrypt_key,%function +.align 5 +${prefix}_set_decrypt_key: +___ +$code.=<<___ if ($flavour =~ /64/); + stp x29,x30,[sp,#-16]! + add x29,sp,#0 +___ +$code.=<<___ if ($flavour !~ /64/); + stmdb sp!,{r4,lr} +___ +$code.=<<___; + bl .Lenc_key + + cmp x0,#0 + b.ne .Ldec_key_abort + + sub $out,$out,#240 // restore original $out + mov x4,#-16 + add $inp,$out,x12,lsl#4 // end of key schedule + + vld1.32 {v0.16b},[$out] + vld1.32 {v1.16b},[$inp] + vst1.32 {v0.16b},[$inp],x4 + vst1.32 {v1.16b},[$out],#16 + +.Loop_imc: + vld1.32 {v0.16b},[$out] + vld1.32 {v1.16b},[$inp] + aesimc v0.16b,v0.16b + aesimc v1.16b,v1.16b + vst1.32 {v0.16b},[$inp],x4 + vst1.32 {v1.16b},[$out],#16 + cmp $inp,$out + b.hi .Loop_imc + + vld1.32 {v0.16b},[$out] + aesimc v0.16b,v0.16b + vst1.32 {v0.16b},[$inp] + + eor x0,x0,x0 // return value +.Ldec_key_abort: +___ +$code.=<<___ if ($flavour !~ /64/); + ldmia sp!,{r4,pc} +___ +$code.=<<___ if ($flavour =~ /64/); + ldp x29,x30,[sp],#16 + ret +___ +$code.=<<___; +.size ${prefix}_set_decrypt_key,.-${prefix}_set_decrypt_key +___ +}}} +{{{ +sub gen_block () { +my $dir = shift; +my ($e,$mc) = $dir eq "en" ? ("e","mc") : ("d","imc"); +my ($inp,$out,$key)=map("x$_",(0..2)); +my $rounds="w3"; +my ($rndkey0,$rndkey1,$inout)=map("q$_",(0..3)); + +$code.=<<___; +.globl ${prefix}_${dir}crypt +.type ${prefix}_${dir}crypt,%function +.align 5 +${prefix}_${dir}crypt: + ldr $rounds,[$key,#240] + vld1.32 {$rndkey0},[$key],#16 + vld1.8 {$inout},[$inp] + sub $rounds,$rounds,#2 + vld1.32 {$rndkey1},[$key],#16 + +.Loop_${dir}c: + aes$e $inout,$rndkey0 + aes$mc $inout,$inout + vld1.32 {$rndkey0},[$key],#16 + subs $rounds,$rounds,#2 + aes$e $inout,$rndkey1 + aes$mc $inout,$inout + vld1.32 {$rndkey1},[$key],#16 + b.gt .Loop_${dir}c + + aes$e $inout,$rndkey0 + aes$mc $inout,$inout + vld1.32 {$rndkey0},[$key] + aes$e $inout,$rndkey1 + veor $inout,$inout,$rndkey0 + + vst1.8 {$inout},[$out] + ret +.size ${prefix}_${dir}crypt,.-${prefix}_${dir}crypt +___ +} +&gen_block("en"); +&gen_block("de"); +}}} +{{{ +my ($inp,$out,$len,$key,$ivp)=map("x$_",(0..4)); my $enc="w5"; +my ($rounds,$cnt,$key_,$step,$step1)=($enc,"w6","x7","x8","x12"); +my ($dat0,$dat1,$in0,$in1,$tmp0,$tmp1,$ivec,$rndlast)=map("q$_",(0..7)); + +my ($dat,$tmp,$rndzero_n_last)=($dat0,$tmp0,$tmp1); +my ($key4,$key5,$key6,$key7)=("x6","x12","x14",$key); + +### q8-q15 preloaded key schedule + +$code.=<<___; +.globl ${prefix}_cbc_encrypt +.type ${prefix}_cbc_encrypt,%function +.align 5 +${prefix}_cbc_encrypt: +___ +$code.=<<___ if ($flavour =~ /64/); + stp x29,x30,[sp,#-16]! + add x29,sp,#0 +___ +$code.=<<___ if ($flavour !~ /64/); + mov ip,sp + stmdb sp!,{r4-r8,lr} + vstmdb sp!,{d8-d15} @ ABI specification says so + ldmia ip,{r4-r5} @ load remaining args +___ +$code.=<<___; + subs $len,$len,#16 + mov $step,#16 + b.lo .Lcbc_abort + cclr $step,eq + + cmp $enc,#0 // en- or decrypting? + ldr $rounds,[$key,#240] + and $len,$len,#-16 + vld1.8 {$ivec},[$ivp] + vld1.8 {$dat},[$inp],$step + + vld1.32 {q8-q9},[$key] // load key schedule... + sub $rounds,$rounds,#6 + add $key_,$key,x5,lsl#4 // pointer to last 7 round keys + sub $rounds,$rounds,#2 + vld1.32 {q10-q11},[$key_],#32 + vld1.32 {q12-q13},[$key_],#32 + vld1.32 {q14-q15},[$key_],#32 + vld1.32 {$rndlast},[$key_] + + add $key_,$key,#32 + mov $cnt,$rounds + b.eq .Lcbc_dec + + cmp $rounds,#2 + veor $dat,$dat,$ivec + veor $rndzero_n_last,q8,$rndlast + b.eq .Lcbc_enc128 + + vld1.32 {$in0-$in1},[$key_] + add $key_,$key,#16 + add $key4,$key,#16*4 + add $key5,$key,#16*5 + aese $dat,q8 + aesmc $dat,$dat + add $key6,$key,#16*6 + add $key7,$key,#16*7 + b .Lenter_cbc_enc + +.align 4 +.Loop_cbc_enc: + aese $dat,q8 + aesmc $dat,$dat + vst1.8 {$ivec},[$out],#16 +.Lenter_cbc_enc: + aese $dat,q9 + aesmc $dat,$dat + aese $dat,$in0 + aesmc $dat,$dat + vld1.32 {q8},[$key4] + cmp $rounds,#4 + aese $dat,$in1 + aesmc $dat,$dat + vld1.32 {q9},[$key5] + b.eq .Lcbc_enc192 + + aese $dat,q8 + aesmc $dat,$dat + vld1.32 {q8},[$key6] + aese $dat,q9 + aesmc $dat,$dat + vld1.32 {q9},[$key7] + nop + +.Lcbc_enc192: + aese $dat,q8 + aesmc $dat,$dat + subs $len,$len,#16 + aese $dat,q9 + aesmc $dat,$dat + cclr $step,eq + aese $dat,q10 + aesmc $dat,$dat + aese $dat,q11 + aesmc $dat,$dat + vld1.8 {q8},[$inp],$step + aese $dat,q12 + aesmc $dat,$dat + veor q8,q8,$rndzero_n_last + aese $dat,q13 + aesmc $dat,$dat + vld1.32 {q9},[$key_] // re-pre-load rndkey[1] + aese $dat,q14 + aesmc $dat,$dat + aese $dat,q15 + veor $ivec,$dat,$rndlast + b.hs .Loop_cbc_enc + + vst1.8 {$ivec},[$out],#16 + b .Lcbc_done + +.align 5 +.Lcbc_enc128: + vld1.32 {$in0-$in1},[$key_] + aese $dat,q8 + aesmc $dat,$dat + b .Lenter_cbc_enc128 +.Loop_cbc_enc128: + aese $dat,q8 + aesmc $dat,$dat + vst1.8 {$ivec},[$out],#16 +.Lenter_cbc_enc128: + aese $dat,q9 + aesmc $dat,$dat + subs $len,$len,#16 + aese $dat,$in0 + aesmc $dat,$dat + cclr $step,eq + aese $dat,$in1 + aesmc $dat,$dat + aese $dat,q10 + aesmc $dat,$dat + aese $dat,q11 + aesmc $dat,$dat + vld1.8 {q8},[$inp],$step + aese $dat,q12 + aesmc $dat,$dat + aese $dat,q13 + aesmc $dat,$dat + aese $dat,q14 + aesmc $dat,$dat + veor q8,q8,$rndzero_n_last + aese $dat,q15 + veor $ivec,$dat,$rndlast + b.hs .Loop_cbc_enc128 + + vst1.8 {$ivec},[$out],#16 + b .Lcbc_done +___ +{ +my ($dat2,$in2,$tmp2)=map("q$_",(10,11,9)); +$code.=<<___; +.align 5 +.Lcbc_dec: + vld1.8 {$dat2},[$inp],#16 + subs $len,$len,#32 // bias + add $cnt,$rounds,#2 + vorr $in1,$dat,$dat + vorr $dat1,$dat,$dat + vorr $in2,$dat2,$dat2 + b.lo .Lcbc_dec_tail + + vorr $dat1,$dat2,$dat2 + vld1.8 {$dat2},[$inp],#16 + vorr $in0,$dat,$dat + vorr $in1,$dat1,$dat1 + vorr $in2,$dat2,$dat2 + +.Loop3x_cbc_dec: + aesd $dat0,q8 + aesimc $dat0,$dat0 + aesd $dat1,q8 + aesimc $dat1,$dat1 + aesd $dat2,q8 + aesimc $dat2,$dat2 + vld1.32 {q8},[$key_],#16 + subs $cnt,$cnt,#2 + aesd $dat0,q9 + aesimc $dat0,$dat0 + aesd $dat1,q9 + aesimc $dat1,$dat1 + aesd $dat2,q9 + aesimc $dat2,$dat2 + vld1.32 {q9},[$key_],#16 + b.gt .Loop3x_cbc_dec + + aesd $dat0,q8 + aesimc $dat0,$dat0 + aesd $dat1,q8 + aesimc $dat1,$dat1 + aesd $dat2,q8 + aesimc $dat2,$dat2 + veor $tmp0,$ivec,$rndlast + subs $len,$len,#0x30 + veor $tmp1,$in0,$rndlast + mov.lo x6,$len // x6, $cnt, is zero at this point + aesd $dat0,q9 + aesimc $dat0,$dat0 + aesd $dat1,q9 + aesimc $dat1,$dat1 + aesd $dat2,q9 + aesimc $dat2,$dat2 + veor $tmp2,$in1,$rndlast + add $inp,$inp,x6 // $inp is adjusted in such way that + // at exit from the loop $dat1-$dat2 + // are loaded with last "words" + vorr $ivec,$in2,$in2 + mov $key_,$key + aesd $dat0,q12 + aesimc $dat0,$dat0 + aesd $dat1,q12 + aesimc $dat1,$dat1 + aesd $dat2,q12 + aesimc $dat2,$dat2 + vld1.8 {$in0},[$inp],#16 + aesd $dat0,q13 + aesimc $dat0,$dat0 + aesd $dat1,q13 + aesimc $dat1,$dat1 + aesd $dat2,q13 + aesimc $dat2,$dat2 + vld1.8 {$in1},[$inp],#16 + aesd $dat0,q14 + aesimc $dat0,$dat0 + aesd $dat1,q14 + aesimc $dat1,$dat1 + aesd $dat2,q14 + aesimc $dat2,$dat2 + vld1.8 {$in2},[$inp],#16 + aesd $dat0,q15 + aesd $dat1,q15 + aesd $dat2,q15 + vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0] + add $cnt,$rounds,#2 + veor $tmp0,$tmp0,$dat0 + veor $tmp1,$tmp1,$dat1 + veor $dat2,$dat2,$tmp2 + vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1] + vst1.8 {$tmp0},[$out],#16 + vorr $dat0,$in0,$in0 + vst1.8 {$tmp1},[$out],#16 + vorr $dat1,$in1,$in1 + vst1.8 {$dat2},[$out],#16 + vorr $dat2,$in2,$in2 + b.hs .Loop3x_cbc_dec + + cmn $len,#0x30 + b.eq .Lcbc_done + nop + +.Lcbc_dec_tail: + aesd $dat1,q8 + aesimc $dat1,$dat1 + aesd $dat2,q8 + aesimc $dat2,$dat2 + vld1.32 {q8},[$key_],#16 + subs $cnt,$cnt,#2 + aesd $dat1,q9 + aesimc $dat1,$dat1 + aesd $dat2,q9 + aesimc $dat2,$dat2 + vld1.32 {q9},[$key_],#16 + b.gt .Lcbc_dec_tail + + aesd $dat1,q8 + aesimc $dat1,$dat1 + aesd $dat2,q8 + aesimc $dat2,$dat2 + aesd $dat1,q9 + aesimc $dat1,$dat1 + aesd $dat2,q9 + aesimc $dat2,$dat2 + aesd $dat1,q12 + aesimc $dat1,$dat1 + aesd $dat2,q12 + aesimc $dat2,$dat2 + cmn $len,#0x20 + aesd $dat1,q13 + aesimc $dat1,$dat1 + aesd $dat2,q13 + aesimc $dat2,$dat2 + veor $tmp1,$ivec,$rndlast + aesd $dat1,q14 + aesimc $dat1,$dat1 + aesd $dat2,q14 + aesimc $dat2,$dat2 + veor $tmp2,$in1,$rndlast + aesd $dat1,q15 + aesd $dat2,q15 + b.eq .Lcbc_dec_one + veor $tmp1,$tmp1,$dat1 + veor $tmp2,$tmp2,$dat2 + vorr $ivec,$in2,$in2 + vst1.8 {$tmp1},[$out],#16 + vst1.8 {$tmp2},[$out],#16 + b .Lcbc_done + +.Lcbc_dec_one: + veor $tmp1,$tmp1,$dat2 + vorr $ivec,$in2,$in2 + vst1.8 {$tmp1},[$out],#16 + +.Lcbc_done: + vst1.8 {$ivec},[$ivp] +.Lcbc_abort: +___ +} +$code.=<<___ if ($flavour !~ /64/); + vldmia sp!,{d8-d15} + ldmia sp!,{r4-r8,pc} +___ +$code.=<<___ if ($flavour =~ /64/); + ldr x29,[sp],#16 + ret +___ +$code.=<<___; +.size ${prefix}_cbc_encrypt,.-${prefix}_cbc_encrypt +___ +}}} +{{{ +my ($inp,$out,$len,$key,$ivp)=map("x$_",(0..4)); +my ($rounds,$cnt,$key_)=("w5","w6","x7"); +my ($ctr,$tctr0,$tctr1,$tctr2)=map("w$_",(8..10,12)); +my $step="x12"; # aliases with $tctr2 + +my ($dat0,$dat1,$in0,$in1,$tmp0,$tmp1,$ivec,$rndlast)=map("q$_",(0..7)); +my ($dat2,$in2,$tmp2)=map("q$_",(10,11,9)); + +my ($dat,$tmp)=($dat0,$tmp0); + +### q8-q15 preloaded key schedule + +$code.=<<___; +.globl ${prefix}_ctr32_encrypt_blocks +.type ${prefix}_ctr32_encrypt_blocks,%function +.align 5 +${prefix}_ctr32_encrypt_blocks: +___ +$code.=<<___ if ($flavour =~ /64/); + stp x29,x30,[sp,#-16]! + add x29,sp,#0 +___ +$code.=<<___ if ($flavour !~ /64/); + mov ip,sp + stmdb sp!,{r4-r10,lr} + vstmdb sp!,{d8-d15} @ ABI specification says so + ldr r4, [ip] @ load remaining arg +___ +$code.=<<___; + ldr $rounds,[$key,#240] + + ldr $ctr, [$ivp, #12] + vld1.32 {$dat0},[$ivp] + + vld1.32 {q8-q9},[$key] // load key schedule... + sub $rounds,$rounds,#4 + mov $step,#16 + cmp $len,#2 + add $key_,$key,x5,lsl#4 // pointer to last 5 round keys + sub $rounds,$rounds,#2 + vld1.32 {q12-q13},[$key_],#32 + vld1.32 {q14-q15},[$key_],#32 + vld1.32 {$rndlast},[$key_] + add $key_,$key,#32 + mov $cnt,$rounds + cclr $step,lo +#ifndef __ARMEB__ + rev $ctr, $ctr +#endif + vorr $dat1,$dat0,$dat0 + add $tctr1, $ctr, #1 + vorr $dat2,$dat0,$dat0 + add $ctr, $ctr, #2 + vorr $ivec,$dat0,$dat0 + rev $tctr1, $tctr1 + vmov.32 ${dat1}[3],$tctr1 + b.ls .Lctr32_tail + rev $tctr2, $ctr + sub $len,$len,#3 // bias + vmov.32 ${dat2}[3],$tctr2 + b .Loop3x_ctr32 + +.align 4 +.Loop3x_ctr32: + aese $dat0,q8 + aesmc $dat0,$dat0 + aese $dat1,q8 + aesmc $dat1,$dat1 + aese $dat2,q8 + aesmc $dat2,$dat2 + vld1.32 {q8},[$key_],#16 + subs $cnt,$cnt,#2 + aese $dat0,q9 + aesmc $dat0,$dat0 + aese $dat1,q9 + aesmc $dat1,$dat1 + aese $dat2,q9 + aesmc $dat2,$dat2 + vld1.32 {q9},[$key_],#16 + b.gt .Loop3x_ctr32 + + aese $dat0,q8 + aesmc $tmp0,$dat0 + aese $dat1,q8 + aesmc $tmp1,$dat1 + vld1.8 {$in0},[$inp],#16 + vorr $dat0,$ivec,$ivec + aese $dat2,q8 + aesmc $dat2,$dat2 + vld1.8 {$in1},[$inp],#16 + vorr $dat1,$ivec,$ivec + aese $tmp0,q9 + aesmc $tmp0,$tmp0 + aese $tmp1,q9 + aesmc $tmp1,$tmp1 + vld1.8 {$in2},[$inp],#16 + mov $key_,$key + aese $dat2,q9 + aesmc $tmp2,$dat2 + vorr $dat2,$ivec,$ivec + add $tctr0,$ctr,#1 + aese $tmp0,q12 + aesmc $tmp0,$tmp0 + aese $tmp1,q12 + aesmc $tmp1,$tmp1 + veor $in0,$in0,$rndlast + add $tctr1,$ctr,#2 + aese $tmp2,q12 + aesmc $tmp2,$tmp2 + veor $in1,$in1,$rndlast + add $ctr,$ctr,#3 + aese $tmp0,q13 + aesmc $tmp0,$tmp0 + aese $tmp1,q13 + aesmc $tmp1,$tmp1 + veor $in2,$in2,$rndlast + rev $tctr0,$tctr0 + aese $tmp2,q13 + aesmc $tmp2,$tmp2 + vmov.32 ${dat0}[3], $tctr0 + rev $tctr1,$tctr1 + aese $tmp0,q14 + aesmc $tmp0,$tmp0 + aese $tmp1,q14 + aesmc $tmp1,$tmp1 + vmov.32 ${dat1}[3], $tctr1 + rev $tctr2,$ctr + aese $tmp2,q14 + aesmc $tmp2,$tmp2 + vmov.32 ${dat2}[3], $tctr2 + subs $len,$len,#3 + aese $tmp0,q15 + aese $tmp1,q15 + aese $tmp2,q15 + + veor $in0,$in0,$tmp0 + vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0] + vst1.8 {$in0},[$out],#16 + veor $in1,$in1,$tmp1 + mov $cnt,$rounds + vst1.8 {$in1},[$out],#16 + veor $in2,$in2,$tmp2 + vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1] + vst1.8 {$in2},[$out],#16 + b.hs .Loop3x_ctr32 + + adds $len,$len,#3 + b.eq .Lctr32_done + cmp $len,#1 + mov $step,#16 + cclr $step,eq + +.Lctr32_tail: + aese $dat0,q8 + aesmc $dat0,$dat0 + aese $dat1,q8 + aesmc $dat1,$dat1 + vld1.32 {q8},[$key_],#16 + subs $cnt,$cnt,#2 + aese $dat0,q9 + aesmc $dat0,$dat0 + aese $dat1,q9 + aesmc $dat1,$dat1 + vld1.32 {q9},[$key_],#16 + b.gt .Lctr32_tail + + aese $dat0,q8 + aesmc $dat0,$dat0 + aese $dat1,q8 + aesmc $dat1,$dat1 + aese $dat0,q9 + aesmc $dat0,$dat0 + aese $dat1,q9 + aesmc $dat1,$dat1 + vld1.8 {$in0},[$inp],$step + aese $dat0,q12 + aesmc $dat0,$dat0 + aese $dat1,q12 + aesmc $dat1,$dat1 + vld1.8 {$in1},[$inp] + aese $dat0,q13 + aesmc $dat0,$dat0 + aese $dat1,q13 + aesmc $dat1,$dat1 + veor $in0,$in0,$rndlast + aese $dat0,q14 + aesmc $dat0,$dat0 + aese $dat1,q14 + aesmc $dat1,$dat1 + veor $in1,$in1,$rndlast + aese $dat0,q15 + aese $dat1,q15 + + cmp $len,#1 + veor $in0,$in0,$dat0 + veor $in1,$in1,$dat1 + vst1.8 {$in0},[$out],#16 + b.eq .Lctr32_done + vst1.8 {$in1},[$out] + +.Lctr32_done: +___ +$code.=<<___ if ($flavour !~ /64/); + vldmia sp!,{d8-d15} + ldmia sp!,{r4-r10,pc} +___ +$code.=<<___ if ($flavour =~ /64/); + ldr x29,[sp],#16 + ret +___ +$code.=<<___; +.size ${prefix}_ctr32_encrypt_blocks,.-${prefix}_ctr32_encrypt_blocks +___ +}}} +$code.=<<___; +#endif +___ +######################################## +if ($flavour =~ /64/) { ######## 64-bit code + my %opcode = ( + "aesd" => 0x4e285800, "aese" => 0x4e284800, + "aesimc"=> 0x4e287800, "aesmc" => 0x4e286800 ); + + local *unaes = sub { + my ($mnemonic,$arg)=@_; + + $arg =~ m/[qv]([0-9]+)[^,]*,\s*[qv]([0-9]+)/o && + sprintf ".inst\t0x%08x\t//%s %s", + $opcode{$mnemonic}|$1|($2<<5), + $mnemonic,$arg; + }; + + foreach(split("\n",$code)) { + s/\`([^\`]*)\`/eval($1)/geo; + + s/\bq([0-9]+)\b/"v".($1<8?$1:$1+8).".16b"/geo; # old->new registers + s/@\s/\/\//o; # old->new style commentary + + #s/[v]?(aes\w+)\s+([qv].*)/unaes($1,$2)/geo or + s/cclr\s+([wx])([^,]+),\s*([a-z]+)/csel $1$2,$1zr,$1$2,$3/o or + s/mov\.([a-z]+)\s+([wx][0-9]+),\s*([wx][0-9]+)/csel $2,$3,$2,$1/o or + s/vmov\.i8/movi/o or # fix up legacy mnemonics + s/vext\.8/ext/o or + s/vrev32\.8/rev32/o or + s/vtst\.8/cmtst/o or + s/vshr/ushr/o or + s/^(\s+)v/$1/o or # strip off v prefix + s/\bbx\s+lr\b/ret/o; + + # fix up remainig legacy suffixes + s/\.[ui]?8//o; + m/\],#8/o and s/\.16b/\.8b/go; + s/\.[ui]?32//o and s/\.16b/\.4s/go; + s/\.[ui]?64//o and s/\.16b/\.2d/go; + s/\.[42]([sd])\[([0-3])\]/\.$1\[$2\]/o; + + print $_,"\n"; + } +} else { ######## 32-bit code + my %opcode = ( + "aesd" => 0xf3b00340, "aese" => 0xf3b00300, + "aesimc"=> 0xf3b003c0, "aesmc" => 0xf3b00380 ); + + local *unaes = sub { + my ($mnemonic,$arg)=@_; + + if ($arg =~ m/[qv]([0-9]+)[^,]*,\s*[qv]([0-9]+)/o) { + my $word = $opcode{$mnemonic}|(($1&7)<<13)|(($1&8)<<19) + |(($2&7)<<1) |(($2&8)<<2); + # since ARMv7 instructions are always encoded little-endian. + # correct solution is to use .inst directive, but older + # assemblers don't implement it:-( + sprintf ".byte\t0x%02x,0x%02x,0x%02x,0x%02x\t@ %s %s", + $word&0xff,($word>>8)&0xff, + ($word>>16)&0xff,($word>>24)&0xff, + $mnemonic,$arg; + } + }; + + sub unvtbl { + my $arg=shift; + + $arg =~ m/q([0-9]+),\s*\{q([0-9]+)\},\s*q([0-9]+)/o && + sprintf "vtbl.8 d%d,{q%d},d%d\n\t". + "vtbl.8 d%d,{q%d},d%d", 2*$1,$2,2*$3, 2*$1+1,$2,2*$3+1; + } + + sub unvdup32 { + my $arg=shift; + + $arg =~ m/q([0-9]+),\s*q([0-9]+)\[([0-3])\]/o && + sprintf "vdup.32 q%d,d%d[%d]",$1,2*$2+($3>>1),$3&1; + } + + sub unvmov32 { + my $arg=shift; + + $arg =~ m/q([0-9]+)\[([0-3])\],(.*)/o && + sprintf "vmov.32 d%d[%d],%s",2*$1+($2>>1),$2&1,$3; + } + + foreach(split("\n",$code)) { + s/\`([^\`]*)\`/eval($1)/geo; + + s/\b[wx]([0-9]+)\b/r$1/go; # new->old registers + s/\bv([0-9])\.[12468]+[bsd]\b/q$1/go; # new->old registers + s/\/\/\s?/@ /o; # new->old style commentary + + # fix up remainig new-style suffixes + s/\{q([0-9]+)\},\s*\[(.+)\],#8/sprintf "{d%d},[$2]!",2*$1/eo or + s/\],#[0-9]+/]!/o; + + s/[v]?(aes\w+)\s+([qv].*)/unaes($1,$2)/geo or + s/cclr\s+([^,]+),\s*([a-z]+)/mov$2 $1,#0/o or + s/vtbl\.8\s+(.*)/unvtbl($1)/geo or + s/vdup\.32\s+(.*)/unvdup32($1)/geo or + s/vmov\.32\s+(.*)/unvmov32($1)/geo or + s/^(\s+)b\./$1b/o or + s/^(\s+)mov\./$1mov/o or + s/^(\s+)ret/$1bx\tlr/o; + + print $_,"\n"; + } +} + +close STDOUT; diff --git a/external/boringssl/crypto/aes/asm/bsaes-armv7.pl b/external/boringssl/crypto/aes/asm/bsaes-armv7.pl new file mode 100644 index 0000000000..22362f515d --- /dev/null +++ b/external/boringssl/crypto/aes/asm/bsaes-armv7.pl @@ -0,0 +1,2505 @@ +#!/usr/bin/env perl + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# +# Specific modes and adaptation for Linux kernel by Ard Biesheuvel +# . Permission to use under GPL terms is +# granted. +# ==================================================================== + +# Bit-sliced AES for ARM NEON +# +# February 2012. +# +# This implementation is direct adaptation of bsaes-x86_64 module for +# ARM NEON. Except that this module is endian-neutral [in sense that +# it can be compiled for either endianness] by courtesy of vld1.8's +# neutrality. Initial version doesn't implement interface to OpenSSL, +# only low-level primitives and unsupported entry points, just enough +# to collect performance results, which for Cortex-A8 core are: +# +# encrypt 19.5 cycles per byte processed with 128-bit key +# decrypt 22.1 cycles per byte processed with 128-bit key +# key conv. 440 cycles per 128-bit key/0.18 of 8x block +# +# Snapdragon S4 encrypts byte in 17.6 cycles and decrypts in 19.7, +# which is [much] worse than anticipated (for further details see +# http://www.openssl.org/~appro/Snapdragon-S4.html). +# +# Cortex-A15 manages in 14.2/16.1 cycles [when integer-only code +# manages in 20.0 cycles]. +# +# When comparing to x86_64 results keep in mind that NEON unit is +# [mostly] single-issue and thus can't [fully] benefit from +# instruction-level parallelism. And when comparing to aes-armv4 +# results keep in mind key schedule conversion overhead (see +# bsaes-x86_64.pl for further details)... +# +# + +# April-August 2013 +# +# Add CBC, CTR and XTS subroutines, adapt for kernel use. +# +# + +$flavour = shift; +if ($flavour=~/^\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; } +else { while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {} } + +if ($flavour && $flavour ne "void") { + $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; + ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or + ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or + die "can't locate arm-xlate.pl"; + + open STDOUT,"| \"$^X\" $xlate $flavour $output"; +} else { + open STDOUT,">$output"; +} + +my ($inp,$out,$len,$key)=("r0","r1","r2","r3"); +my @XMM=map("q$_",(0..15)); + +{ +my ($key,$rounds,$const)=("r4","r5","r6"); + +sub Dlo() { shift=~m|q([1]?[0-9])|?"d".($1*2):""; } +sub Dhi() { shift=~m|q([1]?[0-9])|?"d".($1*2+1):""; } + +sub Sbox { +# input in lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb +# output in lsb > [b0, b1, b4, b6, b3, b7, b2, b5] < msb +my @b=@_[0..7]; +my @t=@_[8..11]; +my @s=@_[12..15]; + &InBasisChange (@b); + &Inv_GF256 (@b[6,5,0,3,7,1,4,2],@t,@s); + &OutBasisChange (@b[7,1,4,2,6,5,0,3]); +} + +sub InBasisChange { +# input in lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb +# output in lsb > [b6, b5, b0, b3, b7, b1, b4, b2] < msb +my @b=@_[0..7]; +$code.=<<___; + veor @b[2], @b[2], @b[1] + veor @b[5], @b[5], @b[6] + veor @b[3], @b[3], @b[0] + veor @b[6], @b[6], @b[2] + veor @b[5], @b[5], @b[0] + + veor @b[6], @b[6], @b[3] + veor @b[3], @b[3], @b[7] + veor @b[7], @b[7], @b[5] + veor @b[3], @b[3], @b[4] + veor @b[4], @b[4], @b[5] + + veor @b[2], @b[2], @b[7] + veor @b[3], @b[3], @b[1] + veor @b[1], @b[1], @b[5] +___ +} + +sub OutBasisChange { +# input in lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb +# output in lsb > [b6, b1, b2, b4, b7, b0, b3, b5] < msb +my @b=@_[0..7]; +$code.=<<___; + veor @b[0], @b[0], @b[6] + veor @b[1], @b[1], @b[4] + veor @b[4], @b[4], @b[6] + veor @b[2], @b[2], @b[0] + veor @b[6], @b[6], @b[1] + + veor @b[1], @b[1], @b[5] + veor @b[5], @b[5], @b[3] + veor @b[3], @b[3], @b[7] + veor @b[7], @b[7], @b[5] + veor @b[2], @b[2], @b[5] + + veor @b[4], @b[4], @b[7] +___ +} + +sub InvSbox { +# input in lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb +# output in lsb > [b0, b1, b6, b4, b2, b7, b3, b5] < msb +my @b=@_[0..7]; +my @t=@_[8..11]; +my @s=@_[12..15]; + &InvInBasisChange (@b); + &Inv_GF256 (@b[5,1,2,6,3,7,0,4],@t,@s); + &InvOutBasisChange (@b[3,7,0,4,5,1,2,6]); +} + +sub InvInBasisChange { # OutBasisChange in reverse (with twist) +my @b=@_[5,1,2,6,3,7,0,4]; +$code.=<<___ + veor @b[1], @b[1], @b[7] + veor @b[4], @b[4], @b[7] + + veor @b[7], @b[7], @b[5] + veor @b[1], @b[1], @b[3] + veor @b[2], @b[2], @b[5] + veor @b[3], @b[3], @b[7] + + veor @b[6], @b[6], @b[1] + veor @b[2], @b[2], @b[0] + veor @b[5], @b[5], @b[3] + veor @b[4], @b[4], @b[6] + veor @b[0], @b[0], @b[6] + veor @b[1], @b[1], @b[4] +___ +} + +sub InvOutBasisChange { # InBasisChange in reverse +my @b=@_[2,5,7,3,6,1,0,4]; +$code.=<<___; + veor @b[1], @b[1], @b[5] + veor @b[2], @b[2], @b[7] + + veor @b[3], @b[3], @b[1] + veor @b[4], @b[4], @b[5] + veor @b[7], @b[7], @b[5] + veor @b[3], @b[3], @b[4] + veor @b[5], @b[5], @b[0] + veor @b[3], @b[3], @b[7] + veor @b[6], @b[6], @b[2] + veor @b[2], @b[2], @b[1] + veor @b[6], @b[6], @b[3] + + veor @b[3], @b[3], @b[0] + veor @b[5], @b[5], @b[6] +___ +} + +sub Mul_GF4 { +#;************************************************************* +#;* Mul_GF4: Input x0-x1,y0-y1 Output x0-x1 Temp t0 (8) * +#;************************************************************* +my ($x0,$x1,$y0,$y1,$t0,$t1)=@_; +$code.=<<___; + veor $t0, $y0, $y1 + vand $t0, $t0, $x0 + veor $x0, $x0, $x1 + vand $t1, $x1, $y0 + vand $x0, $x0, $y1 + veor $x1, $t1, $t0 + veor $x0, $x0, $t1 +___ +} + +sub Mul_GF4_N { # not used, see next subroutine +# multiply and scale by N +my ($x0,$x1,$y0,$y1,$t0)=@_; +$code.=<<___; + veor $t0, $y0, $y1 + vand $t0, $t0, $x0 + veor $x0, $x0, $x1 + vand $x1, $x1, $y0 + vand $x0, $x0, $y1 + veor $x1, $x1, $x0 + veor $x0, $x0, $t0 +___ +} + +sub Mul_GF4_N_GF4 { +# interleaved Mul_GF4_N and Mul_GF4 +my ($x0,$x1,$y0,$y1,$t0, + $x2,$x3,$y2,$y3,$t1)=@_; +$code.=<<___; + veor $t0, $y0, $y1 + veor $t1, $y2, $y3 + vand $t0, $t0, $x0 + vand $t1, $t1, $x2 + veor $x0, $x0, $x1 + veor $x2, $x2, $x3 + vand $x1, $x1, $y0 + vand $x3, $x3, $y2 + vand $x0, $x0, $y1 + vand $x2, $x2, $y3 + veor $x1, $x1, $x0 + veor $x2, $x2, $x3 + veor $x0, $x0, $t0 + veor $x3, $x3, $t1 +___ +} +sub Mul_GF16_2 { +my @x=@_[0..7]; +my @y=@_[8..11]; +my @t=@_[12..15]; +$code.=<<___; + veor @t[0], @x[0], @x[2] + veor @t[1], @x[1], @x[3] +___ + &Mul_GF4 (@x[0], @x[1], @y[0], @y[1], @t[2..3]); +$code.=<<___; + veor @y[0], @y[0], @y[2] + veor @y[1], @y[1], @y[3] +___ + Mul_GF4_N_GF4 (@t[0], @t[1], @y[0], @y[1], @t[3], + @x[2], @x[3], @y[2], @y[3], @t[2]); +$code.=<<___; + veor @x[0], @x[0], @t[0] + veor @x[2], @x[2], @t[0] + veor @x[1], @x[1], @t[1] + veor @x[3], @x[3], @t[1] + + veor @t[0], @x[4], @x[6] + veor @t[1], @x[5], @x[7] +___ + &Mul_GF4_N_GF4 (@t[0], @t[1], @y[0], @y[1], @t[3], + @x[6], @x[7], @y[2], @y[3], @t[2]); +$code.=<<___; + veor @y[0], @y[0], @y[2] + veor @y[1], @y[1], @y[3] +___ + &Mul_GF4 (@x[4], @x[5], @y[0], @y[1], @t[2..3]); +$code.=<<___; + veor @x[4], @x[4], @t[0] + veor @x[6], @x[6], @t[0] + veor @x[5], @x[5], @t[1] + veor @x[7], @x[7], @t[1] +___ +} +sub Inv_GF256 { +#;******************************************************************** +#;* Inv_GF256: Input x0-x7 Output x0-x7 Temp t0-t3,s0-s3 (144) * +#;******************************************************************** +my @x=@_[0..7]; +my @t=@_[8..11]; +my @s=@_[12..15]; +# direct optimizations from hardware +$code.=<<___; + veor @t[3], @x[4], @x[6] + veor @t[2], @x[5], @x[7] + veor @t[1], @x[1], @x[3] + veor @s[1], @x[7], @x[6] + vmov @t[0], @t[2] + veor @s[0], @x[0], @x[2] + + vorr @t[2], @t[2], @t[1] + veor @s[3], @t[3], @t[0] + vand @s[2], @t[3], @s[0] + vorr @t[3], @t[3], @s[0] + veor @s[0], @s[0], @t[1] + vand @t[0], @t[0], @t[1] + veor @t[1], @x[3], @x[2] + vand @s[3], @s[3], @s[0] + vand @s[1], @s[1], @t[1] + veor @t[1], @x[4], @x[5] + veor @s[0], @x[1], @x[0] + veor @t[3], @t[3], @s[1] + veor @t[2], @t[2], @s[1] + vand @s[1], @t[1], @s[0] + vorr @t[1], @t[1], @s[0] + veor @t[3], @t[3], @s[3] + veor @t[0], @t[0], @s[1] + veor @t[2], @t[2], @s[2] + veor @t[1], @t[1], @s[3] + veor @t[0], @t[0], @s[2] + vand @s[0], @x[7], @x[3] + veor @t[1], @t[1], @s[2] + vand @s[1], @x[6], @x[2] + vand @s[2], @x[5], @x[1] + vorr @s[3], @x[4], @x[0] + veor @t[3], @t[3], @s[0] + veor @t[1], @t[1], @s[2] + veor @t[0], @t[0], @s[3] + veor @t[2], @t[2], @s[1] + + @ Inv_GF16 \t0, \t1, \t2, \t3, \s0, \s1, \s2, \s3 + + @ new smaller inversion + + vand @s[2], @t[3], @t[1] + vmov @s[0], @t[0] + + veor @s[1], @t[2], @s[2] + veor @s[3], @t[0], @s[2] + veor @s[2], @t[0], @s[2] @ @s[2]=@s[3] + + vbsl @s[1], @t[1], @t[0] + vbsl @s[3], @t[3], @t[2] + veor @t[3], @t[3], @t[2] + + vbsl @s[0], @s[1], @s[2] + vbsl @t[0], @s[2], @s[1] + + vand @s[2], @s[0], @s[3] + veor @t[1], @t[1], @t[0] + + veor @s[2], @s[2], @t[3] +___ +# output in s3, s2, s1, t1 + +# Mul_GF16_2 \x0, \x1, \x2, \x3, \x4, \x5, \x6, \x7, \t2, \t3, \t0, \t1, \s0, \s1, \s2, \s3 + +# Mul_GF16_2 \x0, \x1, \x2, \x3, \x4, \x5, \x6, \x7, \s3, \s2, \s1, \t1, \s0, \t0, \t2, \t3 + &Mul_GF16_2(@x,@s[3,2,1],@t[1],@s[0],@t[0,2,3]); + +### output msb > [x3,x2,x1,x0,x7,x6,x5,x4] < lsb +} + +# AES linear components + +sub ShiftRows { +my @x=@_[0..7]; +my @t=@_[8..11]; +my $mask=pop; +$code.=<<___; + vldmia $key!, {@t[0]-@t[3]} + veor @t[0], @t[0], @x[0] + veor @t[1], @t[1], @x[1] + vtbl.8 `&Dlo(@x[0])`, {@t[0]}, `&Dlo($mask)` + vtbl.8 `&Dhi(@x[0])`, {@t[0]}, `&Dhi($mask)` + vldmia $key!, {@t[0]} + veor @t[2], @t[2], @x[2] + vtbl.8 `&Dlo(@x[1])`, {@t[1]}, `&Dlo($mask)` + vtbl.8 `&Dhi(@x[1])`, {@t[1]}, `&Dhi($mask)` + vldmia $key!, {@t[1]} + veor @t[3], @t[3], @x[3] + vtbl.8 `&Dlo(@x[2])`, {@t[2]}, `&Dlo($mask)` + vtbl.8 `&Dhi(@x[2])`, {@t[2]}, `&Dhi($mask)` + vldmia $key!, {@t[2]} + vtbl.8 `&Dlo(@x[3])`, {@t[3]}, `&Dlo($mask)` + vtbl.8 `&Dhi(@x[3])`, {@t[3]}, `&Dhi($mask)` + vldmia $key!, {@t[3]} + veor @t[0], @t[0], @x[4] + veor @t[1], @t[1], @x[5] + vtbl.8 `&Dlo(@x[4])`, {@t[0]}, `&Dlo($mask)` + vtbl.8 `&Dhi(@x[4])`, {@t[0]}, `&Dhi($mask)` + veor @t[2], @t[2], @x[6] + vtbl.8 `&Dlo(@x[5])`, {@t[1]}, `&Dlo($mask)` + vtbl.8 `&Dhi(@x[5])`, {@t[1]}, `&Dhi($mask)` + veor @t[3], @t[3], @x[7] + vtbl.8 `&Dlo(@x[6])`, {@t[2]}, `&Dlo($mask)` + vtbl.8 `&Dhi(@x[6])`, {@t[2]}, `&Dhi($mask)` + vtbl.8 `&Dlo(@x[7])`, {@t[3]}, `&Dlo($mask)` + vtbl.8 `&Dhi(@x[7])`, {@t[3]}, `&Dhi($mask)` +___ +} + +sub MixColumns { +# modified to emit output in order suitable for feeding back to aesenc[last] +my @x=@_[0..7]; +my @t=@_[8..15]; +my $inv=@_[16]; # optional +$code.=<<___; + vext.8 @t[0], @x[0], @x[0], #12 @ x0 <<< 32 + vext.8 @t[1], @x[1], @x[1], #12 + veor @x[0], @x[0], @t[0] @ x0 ^ (x0 <<< 32) + vext.8 @t[2], @x[2], @x[2], #12 + veor @x[1], @x[1], @t[1] + vext.8 @t[3], @x[3], @x[3], #12 + veor @x[2], @x[2], @t[2] + vext.8 @t[4], @x[4], @x[4], #12 + veor @x[3], @x[3], @t[3] + vext.8 @t[5], @x[5], @x[5], #12 + veor @x[4], @x[4], @t[4] + vext.8 @t[6], @x[6], @x[6], #12 + veor @x[5], @x[5], @t[5] + vext.8 @t[7], @x[7], @x[7], #12 + veor @x[6], @x[6], @t[6] + + veor @t[1], @t[1], @x[0] + veor @x[7], @x[7], @t[7] + vext.8 @x[0], @x[0], @x[0], #8 @ (x0 ^ (x0 <<< 32)) <<< 64) + veor @t[2], @t[2], @x[1] + veor @t[0], @t[0], @x[7] + veor @t[1], @t[1], @x[7] + vext.8 @x[1], @x[1], @x[1], #8 + veor @t[5], @t[5], @x[4] + veor @x[0], @x[0], @t[0] + veor @t[6], @t[6], @x[5] + veor @x[1], @x[1], @t[1] + vext.8 @t[0], @x[4], @x[4], #8 + veor @t[4], @t[4], @x[3] + vext.8 @t[1], @x[5], @x[5], #8 + veor @t[7], @t[7], @x[6] + vext.8 @x[4], @x[3], @x[3], #8 + veor @t[3], @t[3], @x[2] + vext.8 @x[5], @x[7], @x[7], #8 + veor @t[4], @t[4], @x[7] + vext.8 @x[3], @x[6], @x[6], #8 + veor @t[3], @t[3], @x[7] + vext.8 @x[6], @x[2], @x[2], #8 + veor @x[7], @t[1], @t[5] +___ +$code.=<<___ if (!$inv); + veor @x[2], @t[0], @t[4] + veor @x[4], @x[4], @t[3] + veor @x[5], @x[5], @t[7] + veor @x[3], @x[3], @t[6] + @ vmov @x[2], @t[0] + veor @x[6], @x[6], @t[2] + @ vmov @x[7], @t[1] +___ +$code.=<<___ if ($inv); + veor @t[3], @t[3], @x[4] + veor @x[5], @x[5], @t[7] + veor @x[2], @x[3], @t[6] + veor @x[3], @t[0], @t[4] + veor @x[4], @x[6], @t[2] + vmov @x[6], @t[3] + @ vmov @x[7], @t[1] +___ +} + +sub InvMixColumns_orig { +my @x=@_[0..7]; +my @t=@_[8..15]; + +$code.=<<___; + @ multiplication by 0x0e + vext.8 @t[7], @x[7], @x[7], #12 + vmov @t[2], @x[2] + veor @x[2], @x[2], @x[5] @ 2 5 + veor @x[7], @x[7], @x[5] @ 7 5 + vext.8 @t[0], @x[0], @x[0], #12 + vmov @t[5], @x[5] + veor @x[5], @x[5], @x[0] @ 5 0 [1] + veor @x[0], @x[0], @x[1] @ 0 1 + vext.8 @t[1], @x[1], @x[1], #12 + veor @x[1], @x[1], @x[2] @ 1 25 + veor @x[0], @x[0], @x[6] @ 01 6 [2] + vext.8 @t[3], @x[3], @x[3], #12 + veor @x[1], @x[1], @x[3] @ 125 3 [4] + veor @x[2], @x[2], @x[0] @ 25 016 [3] + veor @x[3], @x[3], @x[7] @ 3 75 + veor @x[7], @x[7], @x[6] @ 75 6 [0] + vext.8 @t[6], @x[6], @x[6], #12 + vmov @t[4], @x[4] + veor @x[6], @x[6], @x[4] @ 6 4 + veor @x[4], @x[4], @x[3] @ 4 375 [6] + veor @x[3], @x[3], @x[7] @ 375 756=36 + veor @x[6], @x[6], @t[5] @ 64 5 [7] + veor @x[3], @x[3], @t[2] @ 36 2 + vext.8 @t[5], @t[5], @t[5], #12 + veor @x[3], @x[3], @t[4] @ 362 4 [5] +___ + my @y = @x[7,5,0,2,1,3,4,6]; +$code.=<<___; + @ multiplication by 0x0b + veor @y[1], @y[1], @y[0] + veor @y[0], @y[0], @t[0] + vext.8 @t[2], @t[2], @t[2], #12 + veor @y[1], @y[1], @t[1] + veor @y[0], @y[0], @t[5] + vext.8 @t[4], @t[4], @t[4], #12 + veor @y[1], @y[1], @t[6] + veor @y[0], @y[0], @t[7] + veor @t[7], @t[7], @t[6] @ clobber t[7] + + veor @y[3], @y[3], @t[0] + veor @y[1], @y[1], @y[0] + vext.8 @t[0], @t[0], @t[0], #12 + veor @y[2], @y[2], @t[1] + veor @y[4], @y[4], @t[1] + vext.8 @t[1], @t[1], @t[1], #12 + veor @y[2], @y[2], @t[2] + veor @y[3], @y[3], @t[2] + veor @y[5], @y[5], @t[2] + veor @y[2], @y[2], @t[7] + vext.8 @t[2], @t[2], @t[2], #12 + veor @y[3], @y[3], @t[3] + veor @y[6], @y[6], @t[3] + veor @y[4], @y[4], @t[3] + veor @y[7], @y[7], @t[4] + vext.8 @t[3], @t[3], @t[3], #12 + veor @y[5], @y[5], @t[4] + veor @y[7], @y[7], @t[7] + veor @t[7], @t[7], @t[5] @ clobber t[7] even more + veor @y[3], @y[3], @t[5] + veor @y[4], @y[4], @t[4] + + veor @y[5], @y[5], @t[7] + vext.8 @t[4], @t[4], @t[4], #12 + veor @y[6], @y[6], @t[7] + veor @y[4], @y[4], @t[7] + + veor @t[7], @t[7], @t[5] + vext.8 @t[5], @t[5], @t[5], #12 + + @ multiplication by 0x0d + veor @y[4], @y[4], @y[7] + veor @t[7], @t[7], @t[6] @ restore t[7] + veor @y[7], @y[7], @t[4] + vext.8 @t[6], @t[6], @t[6], #12 + veor @y[2], @y[2], @t[0] + veor @y[7], @y[7], @t[5] + vext.8 @t[7], @t[7], @t[7], #12 + veor @y[2], @y[2], @t[2] + + veor @y[3], @y[3], @y[1] + veor @y[1], @y[1], @t[1] + veor @y[0], @y[0], @t[0] + veor @y[3], @y[3], @t[0] + veor @y[1], @y[1], @t[5] + veor @y[0], @y[0], @t[5] + vext.8 @t[0], @t[0], @t[0], #12 + veor @y[1], @y[1], @t[7] + veor @y[0], @y[0], @t[6] + veor @y[3], @y[3], @y[1] + veor @y[4], @y[4], @t[1] + vext.8 @t[1], @t[1], @t[1], #12 + + veor @y[7], @y[7], @t[7] + veor @y[4], @y[4], @t[2] + veor @y[5], @y[5], @t[2] + veor @y[2], @y[2], @t[6] + veor @t[6], @t[6], @t[3] @ clobber t[6] + vext.8 @t[2], @t[2], @t[2], #12 + veor @y[4], @y[4], @y[7] + veor @y[3], @y[3], @t[6] + + veor @y[6], @y[6], @t[6] + veor @y[5], @y[5], @t[5] + vext.8 @t[5], @t[5], @t[5], #12 + veor @y[6], @y[6], @t[4] + vext.8 @t[4], @t[4], @t[4], #12 + veor @y[5], @y[5], @t[6] + veor @y[6], @y[6], @t[7] + vext.8 @t[7], @t[7], @t[7], #12 + veor @t[6], @t[6], @t[3] @ restore t[6] + vext.8 @t[3], @t[3], @t[3], #12 + + @ multiplication by 0x09 + veor @y[4], @y[4], @y[1] + veor @t[1], @t[1], @y[1] @ t[1]=y[1] + veor @t[0], @t[0], @t[5] @ clobber t[0] + vext.8 @t[6], @t[6], @t[6], #12 + veor @t[1], @t[1], @t[5] + veor @y[3], @y[3], @t[0] + veor @t[0], @t[0], @y[0] @ t[0]=y[0] + veor @t[1], @t[1], @t[6] + veor @t[6], @t[6], @t[7] @ clobber t[6] + veor @y[4], @y[4], @t[1] + veor @y[7], @y[7], @t[4] + veor @y[6], @y[6], @t[3] + veor @y[5], @y[5], @t[2] + veor @t[4], @t[4], @y[4] @ t[4]=y[4] + veor @t[3], @t[3], @y[3] @ t[3]=y[3] + veor @t[5], @t[5], @y[5] @ t[5]=y[5] + veor @t[2], @t[2], @y[2] @ t[2]=y[2] + veor @t[3], @t[3], @t[7] + veor @XMM[5], @t[5], @t[6] + veor @XMM[6], @t[6], @y[6] @ t[6]=y[6] + veor @XMM[2], @t[2], @t[6] + veor @XMM[7], @t[7], @y[7] @ t[7]=y[7] + + vmov @XMM[0], @t[0] + vmov @XMM[1], @t[1] + @ vmov @XMM[2], @t[2] + vmov @XMM[3], @t[3] + vmov @XMM[4], @t[4] + @ vmov @XMM[5], @t[5] + @ vmov @XMM[6], @t[6] + @ vmov @XMM[7], @t[7] +___ +} + +sub InvMixColumns { +my @x=@_[0..7]; +my @t=@_[8..15]; + +# Thanks to Jussi Kivilinna for providing pointer to +# +# | 0e 0b 0d 09 | | 02 03 01 01 | | 05 00 04 00 | +# | 09 0e 0b 0d | = | 01 02 03 01 | x | 00 05 00 04 | +# | 0d 09 0e 0b | | 01 01 02 03 | | 04 00 05 00 | +# | 0b 0d 09 0e | | 03 01 01 02 | | 00 04 00 05 | + +$code.=<<___; + @ multiplication by 0x05-0x00-0x04-0x00 + vext.8 @t[0], @x[0], @x[0], #8 + vext.8 @t[6], @x[6], @x[6], #8 + vext.8 @t[7], @x[7], @x[7], #8 + veor @t[0], @t[0], @x[0] + vext.8 @t[1], @x[1], @x[1], #8 + veor @t[6], @t[6], @x[6] + vext.8 @t[2], @x[2], @x[2], #8 + veor @t[7], @t[7], @x[7] + vext.8 @t[3], @x[3], @x[3], #8 + veor @t[1], @t[1], @x[1] + vext.8 @t[4], @x[4], @x[4], #8 + veor @t[2], @t[2], @x[2] + vext.8 @t[5], @x[5], @x[5], #8 + veor @t[3], @t[3], @x[3] + veor @t[4], @t[4], @x[4] + veor @t[5], @t[5], @x[5] + + veor @x[0], @x[0], @t[6] + veor @x[1], @x[1], @t[6] + veor @x[2], @x[2], @t[0] + veor @x[4], @x[4], @t[2] + veor @x[3], @x[3], @t[1] + veor @x[1], @x[1], @t[7] + veor @x[2], @x[2], @t[7] + veor @x[4], @x[4], @t[6] + veor @x[5], @x[5], @t[3] + veor @x[3], @x[3], @t[6] + veor @x[6], @x[6], @t[4] + veor @x[4], @x[4], @t[7] + veor @x[5], @x[5], @t[7] + veor @x[7], @x[7], @t[5] +___ + &MixColumns (@x,@t,1); # flipped 2<->3 and 4<->6 +} + +sub swapmove { +my ($a,$b,$n,$mask,$t)=@_; +$code.=<<___; + vshr.u64 $t, $b, #$n + veor $t, $t, $a + vand $t, $t, $mask + veor $a, $a, $t + vshl.u64 $t, $t, #$n + veor $b, $b, $t +___ +} +sub swapmove2x { +my ($a0,$b0,$a1,$b1,$n,$mask,$t0,$t1)=@_; +$code.=<<___; + vshr.u64 $t0, $b0, #$n + vshr.u64 $t1, $b1, #$n + veor $t0, $t0, $a0 + veor $t1, $t1, $a1 + vand $t0, $t0, $mask + vand $t1, $t1, $mask + veor $a0, $a0, $t0 + vshl.u64 $t0, $t0, #$n + veor $a1, $a1, $t1 + vshl.u64 $t1, $t1, #$n + veor $b0, $b0, $t0 + veor $b1, $b1, $t1 +___ +} + +sub bitslice { +my @x=reverse(@_[0..7]); +my ($t0,$t1,$t2,$t3)=@_[8..11]; +$code.=<<___; + vmov.i8 $t0,#0x55 @ compose .LBS0 + vmov.i8 $t1,#0x33 @ compose .LBS1 +___ + &swapmove2x(@x[0,1,2,3],1,$t0,$t2,$t3); + &swapmove2x(@x[4,5,6,7],1,$t0,$t2,$t3); +$code.=<<___; + vmov.i8 $t0,#0x0f @ compose .LBS2 +___ + &swapmove2x(@x[0,2,1,3],2,$t1,$t2,$t3); + &swapmove2x(@x[4,6,5,7],2,$t1,$t2,$t3); + + &swapmove2x(@x[0,4,1,5],4,$t0,$t2,$t3); + &swapmove2x(@x[2,6,3,7],4,$t0,$t2,$t3); +} + +$code.=<<___; +#ifndef __KERNEL__ +# include + +# define VFP_ABI_PUSH vstmdb sp!,{d8-d15} +# define VFP_ABI_POP vldmia sp!,{d8-d15} +# define VFP_ABI_FRAME 0x40 +#else +# define VFP_ABI_PUSH +# define VFP_ABI_POP +# define VFP_ABI_FRAME 0 +# define BSAES_ASM_EXTENDED_KEY +# define XTS_CHAIN_TWEAK +# define __ARM_ARCH__ __LINUX_ARM_ARCH__ +# define __ARM_MAX_ARCH__ 7 +#endif + +#ifdef __thumb__ +# define adrl adr +#endif + +#if __ARM_MAX_ARCH__>=7 +.arch armv7-a +.fpu neon + +.text +.syntax unified @ ARMv7-capable assembler is expected to handle this +#if defined(__thumb2__) && !defined(__APPLE__) +.thumb +#else +.code 32 +#endif + +.type _bsaes_decrypt8,%function +.align 4 +_bsaes_decrypt8: + adr $const,_bsaes_decrypt8 + vldmia $key!, {@XMM[9]} @ round 0 key +#ifdef __APPLE__ + adr $const,.LM0ISR +#else + add $const,$const,#.LM0ISR-_bsaes_decrypt8 +#endif + + vldmia $const!, {@XMM[8]} @ .LM0ISR + veor @XMM[10], @XMM[0], @XMM[9] @ xor with round0 key + veor @XMM[11], @XMM[1], @XMM[9] + vtbl.8 `&Dlo(@XMM[0])`, {@XMM[10]}, `&Dlo(@XMM[8])` + vtbl.8 `&Dhi(@XMM[0])`, {@XMM[10]}, `&Dhi(@XMM[8])` + veor @XMM[12], @XMM[2], @XMM[9] + vtbl.8 `&Dlo(@XMM[1])`, {@XMM[11]}, `&Dlo(@XMM[8])` + vtbl.8 `&Dhi(@XMM[1])`, {@XMM[11]}, `&Dhi(@XMM[8])` + veor @XMM[13], @XMM[3], @XMM[9] + vtbl.8 `&Dlo(@XMM[2])`, {@XMM[12]}, `&Dlo(@XMM[8])` + vtbl.8 `&Dhi(@XMM[2])`, {@XMM[12]}, `&Dhi(@XMM[8])` + veor @XMM[14], @XMM[4], @XMM[9] + vtbl.8 `&Dlo(@XMM[3])`, {@XMM[13]}, `&Dlo(@XMM[8])` + vtbl.8 `&Dhi(@XMM[3])`, {@XMM[13]}, `&Dhi(@XMM[8])` + veor @XMM[15], @XMM[5], @XMM[9] + vtbl.8 `&Dlo(@XMM[4])`, {@XMM[14]}, `&Dlo(@XMM[8])` + vtbl.8 `&Dhi(@XMM[4])`, {@XMM[14]}, `&Dhi(@XMM[8])` + veor @XMM[10], @XMM[6], @XMM[9] + vtbl.8 `&Dlo(@XMM[5])`, {@XMM[15]}, `&Dlo(@XMM[8])` + vtbl.8 `&Dhi(@XMM[5])`, {@XMM[15]}, `&Dhi(@XMM[8])` + veor @XMM[11], @XMM[7], @XMM[9] + vtbl.8 `&Dlo(@XMM[6])`, {@XMM[10]}, `&Dlo(@XMM[8])` + vtbl.8 `&Dhi(@XMM[6])`, {@XMM[10]}, `&Dhi(@XMM[8])` + vtbl.8 `&Dlo(@XMM[7])`, {@XMM[11]}, `&Dlo(@XMM[8])` + vtbl.8 `&Dhi(@XMM[7])`, {@XMM[11]}, `&Dhi(@XMM[8])` +___ + &bitslice (@XMM[0..7, 8..11]); +$code.=<<___; + sub $rounds,$rounds,#1 + b .Ldec_sbox +.align 4 +.Ldec_loop: +___ + &ShiftRows (@XMM[0..7, 8..12]); +$code.=".Ldec_sbox:\n"; + &InvSbox (@XMM[0..7, 8..15]); +$code.=<<___; + subs $rounds,$rounds,#1 + bcc .Ldec_done +___ + &InvMixColumns (@XMM[0,1,6,4,2,7,3,5, 8..15]); +$code.=<<___; + vldmia $const, {@XMM[12]} @ .LISR + ite eq @ Thumb2 thing, sanity check in ARM + addeq $const,$const,#0x10 + bne .Ldec_loop + vldmia $const, {@XMM[12]} @ .LISRM0 + b .Ldec_loop +.align 4 +.Ldec_done: +___ + &bitslice (@XMM[0,1,6,4,2,7,3,5, 8..11]); +$code.=<<___; + vldmia $key, {@XMM[8]} @ last round key + veor @XMM[6], @XMM[6], @XMM[8] + veor @XMM[4], @XMM[4], @XMM[8] + veor @XMM[2], @XMM[2], @XMM[8] + veor @XMM[7], @XMM[7], @XMM[8] + veor @XMM[3], @XMM[3], @XMM[8] + veor @XMM[5], @XMM[5], @XMM[8] + veor @XMM[0], @XMM[0], @XMM[8] + veor @XMM[1], @XMM[1], @XMM[8] + bx lr +.size _bsaes_decrypt8,.-_bsaes_decrypt8 + +.type _bsaes_const,%object +.align 6 +_bsaes_const: +.LM0ISR: @ InvShiftRows constants + .quad 0x0a0e0206070b0f03, 0x0004080c0d010509 +.LISR: + .quad 0x0504070602010003, 0x0f0e0d0c080b0a09 +.LISRM0: + .quad 0x01040b0e0205080f, 0x0306090c00070a0d +.LM0SR: @ ShiftRows constants + .quad 0x0a0e02060f03070b, 0x0004080c05090d01 +.LSR: + .quad 0x0504070600030201, 0x0f0e0d0c0a09080b +.LSRM0: + .quad 0x0304090e00050a0f, 0x01060b0c0207080d +.LM0: + .quad 0x02060a0e03070b0f, 0x0004080c0105090d +.LREVM0SR: + .quad 0x090d01050c000408, 0x03070b0f060a0e02 +.asciz "Bit-sliced AES for NEON, CRYPTOGAMS by " +.align 6 +.size _bsaes_const,.-_bsaes_const + +.type _bsaes_encrypt8,%function +.align 4 +_bsaes_encrypt8: + adr $const,_bsaes_encrypt8 + vldmia $key!, {@XMM[9]} @ round 0 key +#ifdef __APPLE__ + adr $const,.LM0SR +#else + sub $const,$const,#_bsaes_encrypt8-.LM0SR +#endif + + vldmia $const!, {@XMM[8]} @ .LM0SR +_bsaes_encrypt8_alt: + veor @XMM[10], @XMM[0], @XMM[9] @ xor with round0 key + veor @XMM[11], @XMM[1], @XMM[9] + vtbl.8 `&Dlo(@XMM[0])`, {@XMM[10]}, `&Dlo(@XMM[8])` + vtbl.8 `&Dhi(@XMM[0])`, {@XMM[10]}, `&Dhi(@XMM[8])` + veor @XMM[12], @XMM[2], @XMM[9] + vtbl.8 `&Dlo(@XMM[1])`, {@XMM[11]}, `&Dlo(@XMM[8])` + vtbl.8 `&Dhi(@XMM[1])`, {@XMM[11]}, `&Dhi(@XMM[8])` + veor @XMM[13], @XMM[3], @XMM[9] + vtbl.8 `&Dlo(@XMM[2])`, {@XMM[12]}, `&Dlo(@XMM[8])` + vtbl.8 `&Dhi(@XMM[2])`, {@XMM[12]}, `&Dhi(@XMM[8])` + veor @XMM[14], @XMM[4], @XMM[9] + vtbl.8 `&Dlo(@XMM[3])`, {@XMM[13]}, `&Dlo(@XMM[8])` + vtbl.8 `&Dhi(@XMM[3])`, {@XMM[13]}, `&Dhi(@XMM[8])` + veor @XMM[15], @XMM[5], @XMM[9] + vtbl.8 `&Dlo(@XMM[4])`, {@XMM[14]}, `&Dlo(@XMM[8])` + vtbl.8 `&Dhi(@XMM[4])`, {@XMM[14]}, `&Dhi(@XMM[8])` + veor @XMM[10], @XMM[6], @XMM[9] + vtbl.8 `&Dlo(@XMM[5])`, {@XMM[15]}, `&Dlo(@XMM[8])` + vtbl.8 `&Dhi(@XMM[5])`, {@XMM[15]}, `&Dhi(@XMM[8])` + veor @XMM[11], @XMM[7], @XMM[9] + vtbl.8 `&Dlo(@XMM[6])`, {@XMM[10]}, `&Dlo(@XMM[8])` + vtbl.8 `&Dhi(@XMM[6])`, {@XMM[10]}, `&Dhi(@XMM[8])` + vtbl.8 `&Dlo(@XMM[7])`, {@XMM[11]}, `&Dlo(@XMM[8])` + vtbl.8 `&Dhi(@XMM[7])`, {@XMM[11]}, `&Dhi(@XMM[8])` +_bsaes_encrypt8_bitslice: +___ + &bitslice (@XMM[0..7, 8..11]); +$code.=<<___; + sub $rounds,$rounds,#1 + b .Lenc_sbox +.align 4 +.Lenc_loop: +___ + &ShiftRows (@XMM[0..7, 8..12]); +$code.=".Lenc_sbox:\n"; + &Sbox (@XMM[0..7, 8..15]); +$code.=<<___; + subs $rounds,$rounds,#1 + bcc .Lenc_done +___ + &MixColumns (@XMM[0,1,4,6,3,7,2,5, 8..15]); +$code.=<<___; + vldmia $const, {@XMM[12]} @ .LSR + ite eq @ Thumb2 thing, samity check in ARM + addeq $const,$const,#0x10 + bne .Lenc_loop + vldmia $const, {@XMM[12]} @ .LSRM0 + b .Lenc_loop +.align 4 +.Lenc_done: +___ + # output in lsb > [t0, t1, t4, t6, t3, t7, t2, t5] < msb + &bitslice (@XMM[0,1,4,6,3,7,2,5, 8..11]); +$code.=<<___; + vldmia $key, {@XMM[8]} @ last round key + veor @XMM[4], @XMM[4], @XMM[8] + veor @XMM[6], @XMM[6], @XMM[8] + veor @XMM[3], @XMM[3], @XMM[8] + veor @XMM[7], @XMM[7], @XMM[8] + veor @XMM[2], @XMM[2], @XMM[8] + veor @XMM[5], @XMM[5], @XMM[8] + veor @XMM[0], @XMM[0], @XMM[8] + veor @XMM[1], @XMM[1], @XMM[8] + bx lr +.size _bsaes_encrypt8,.-_bsaes_encrypt8 +___ +} +{ +my ($out,$inp,$rounds,$const)=("r12","r4","r5","r6"); + +sub bitslice_key { +my @x=reverse(@_[0..7]); +my ($bs0,$bs1,$bs2,$t2,$t3)=@_[8..12]; + + &swapmove (@x[0,1],1,$bs0,$t2,$t3); +$code.=<<___; + @ &swapmove(@x[2,3],1,$t0,$t2,$t3); + vmov @x[2], @x[0] + vmov @x[3], @x[1] +___ + #&swapmove2x(@x[4,5,6,7],1,$t0,$t2,$t3); + + &swapmove2x (@x[0,2,1,3],2,$bs1,$t2,$t3); +$code.=<<___; + @ &swapmove2x(@x[4,6,5,7],2,$t1,$t2,$t3); + vmov @x[4], @x[0] + vmov @x[6], @x[2] + vmov @x[5], @x[1] + vmov @x[7], @x[3] +___ + &swapmove2x (@x[0,4,1,5],4,$bs2,$t2,$t3); + &swapmove2x (@x[2,6,3,7],4,$bs2,$t2,$t3); +} + +$code.=<<___; +.type _bsaes_key_convert,%function +.align 4 +_bsaes_key_convert: + adr $const,_bsaes_key_convert + vld1.8 {@XMM[7]}, [$inp]! @ load round 0 key +#ifdef __APPLE__ + adr $const,.LM0 +#else + sub $const,$const,#_bsaes_key_convert-.LM0 +#endif + vld1.8 {@XMM[15]}, [$inp]! @ load round 1 key + + vmov.i8 @XMM[8], #0x01 @ bit masks + vmov.i8 @XMM[9], #0x02 + vmov.i8 @XMM[10], #0x04 + vmov.i8 @XMM[11], #0x08 + vmov.i8 @XMM[12], #0x10 + vmov.i8 @XMM[13], #0x20 + vldmia $const, {@XMM[14]} @ .LM0 + +#ifdef __ARMEL__ + vrev32.8 @XMM[7], @XMM[7] + vrev32.8 @XMM[15], @XMM[15] +#endif + sub $rounds,$rounds,#1 + vstmia $out!, {@XMM[7]} @ save round 0 key + b .Lkey_loop + +.align 4 +.Lkey_loop: + vtbl.8 `&Dlo(@XMM[7])`,{@XMM[15]},`&Dlo(@XMM[14])` + vtbl.8 `&Dhi(@XMM[7])`,{@XMM[15]},`&Dhi(@XMM[14])` + vmov.i8 @XMM[6], #0x40 + vmov.i8 @XMM[15], #0x80 + + vtst.8 @XMM[0], @XMM[7], @XMM[8] + vtst.8 @XMM[1], @XMM[7], @XMM[9] + vtst.8 @XMM[2], @XMM[7], @XMM[10] + vtst.8 @XMM[3], @XMM[7], @XMM[11] + vtst.8 @XMM[4], @XMM[7], @XMM[12] + vtst.8 @XMM[5], @XMM[7], @XMM[13] + vtst.8 @XMM[6], @XMM[7], @XMM[6] + vtst.8 @XMM[7], @XMM[7], @XMM[15] + vld1.8 {@XMM[15]}, [$inp]! @ load next round key + vmvn @XMM[0], @XMM[0] @ "pnot" + vmvn @XMM[1], @XMM[1] + vmvn @XMM[5], @XMM[5] + vmvn @XMM[6], @XMM[6] +#ifdef __ARMEL__ + vrev32.8 @XMM[15], @XMM[15] +#endif + subs $rounds,$rounds,#1 + vstmia $out!,{@XMM[0]-@XMM[7]} @ write bit-sliced round key + bne .Lkey_loop + + vmov.i8 @XMM[7],#0x63 @ compose .L63 + @ don't save last round key + bx lr +.size _bsaes_key_convert,.-_bsaes_key_convert +___ +} + +if (0) { # following four functions are unsupported interface + # used for benchmarking... +$code.=<<___; +.globl bsaes_enc_key_convert +.type bsaes_enc_key_convert,%function +.align 4 +bsaes_enc_key_convert: + stmdb sp!,{r4-r6,lr} + vstmdb sp!,{d8-d15} @ ABI specification says so + + ldr r5,[$inp,#240] @ pass rounds + mov r4,$inp @ pass key + mov r12,$out @ pass key schedule + bl _bsaes_key_convert + veor @XMM[7],@XMM[7],@XMM[15] @ fix up last round key + vstmia r12, {@XMM[7]} @ save last round key + + vldmia sp!,{d8-d15} + ldmia sp!,{r4-r6,pc} +.size bsaes_enc_key_convert,.-bsaes_enc_key_convert + +.globl bsaes_encrypt_128 +.type bsaes_encrypt_128,%function +.align 4 +bsaes_encrypt_128: + stmdb sp!,{r4-r6,lr} + vstmdb sp!,{d8-d15} @ ABI specification says so +.Lenc128_loop: + vld1.8 {@XMM[0]-@XMM[1]}, [$inp]! @ load input + vld1.8 {@XMM[2]-@XMM[3]}, [$inp]! + mov r4,$key @ pass the key + vld1.8 {@XMM[4]-@XMM[5]}, [$inp]! + mov r5,#10 @ pass rounds + vld1.8 {@XMM[6]-@XMM[7]}, [$inp]! + + bl _bsaes_encrypt8 + + vst1.8 {@XMM[0]-@XMM[1]}, [$out]! @ write output + vst1.8 {@XMM[4]}, [$out]! + vst1.8 {@XMM[6]}, [$out]! + vst1.8 {@XMM[3]}, [$out]! + vst1.8 {@XMM[7]}, [$out]! + vst1.8 {@XMM[2]}, [$out]! + subs $len,$len,#0x80 + vst1.8 {@XMM[5]}, [$out]! + bhi .Lenc128_loop + + vldmia sp!,{d8-d15} + ldmia sp!,{r4-r6,pc} +.size bsaes_encrypt_128,.-bsaes_encrypt_128 + +.globl bsaes_dec_key_convert +.type bsaes_dec_key_convert,%function +.align 4 +bsaes_dec_key_convert: + stmdb sp!,{r4-r6,lr} + vstmdb sp!,{d8-d15} @ ABI specification says so + + ldr r5,[$inp,#240] @ pass rounds + mov r4,$inp @ pass key + mov r12,$out @ pass key schedule + bl _bsaes_key_convert + vldmia $out, {@XMM[6]} + vstmia r12, {@XMM[15]} @ save last round key + veor @XMM[7], @XMM[7], @XMM[6] @ fix up round 0 key + vstmia $out, {@XMM[7]} + + vldmia sp!,{d8-d15} + ldmia sp!,{r4-r6,pc} +.size bsaes_dec_key_convert,.-bsaes_dec_key_convert + +.globl bsaes_decrypt_128 +.type bsaes_decrypt_128,%function +.align 4 +bsaes_decrypt_128: + stmdb sp!,{r4-r6,lr} + vstmdb sp!,{d8-d15} @ ABI specification says so +.Ldec128_loop: + vld1.8 {@XMM[0]-@XMM[1]}, [$inp]! @ load input + vld1.8 {@XMM[2]-@XMM[3]}, [$inp]! + mov r4,$key @ pass the key + vld1.8 {@XMM[4]-@XMM[5]}, [$inp]! + mov r5,#10 @ pass rounds + vld1.8 {@XMM[6]-@XMM[7]}, [$inp]! + + bl _bsaes_decrypt8 + + vst1.8 {@XMM[0]-@XMM[1]}, [$out]! @ write output + vst1.8 {@XMM[6]}, [$out]! + vst1.8 {@XMM[4]}, [$out]! + vst1.8 {@XMM[2]}, [$out]! + vst1.8 {@XMM[7]}, [$out]! + vst1.8 {@XMM[3]}, [$out]! + subs $len,$len,#0x80 + vst1.8 {@XMM[5]}, [$out]! + bhi .Ldec128_loop + + vldmia sp!,{d8-d15} + ldmia sp!,{r4-r6,pc} +.size bsaes_decrypt_128,.-bsaes_decrypt_128 +___ +} +{ +my ($inp,$out,$len,$key, $ivp,$fp,$rounds)=map("r$_",(0..3,8..10)); +my ($keysched)=("sp"); + +$code.=<<___; +.extern AES_cbc_encrypt +.extern AES_decrypt + +.global bsaes_cbc_encrypt +.type bsaes_cbc_encrypt,%function +.align 5 +bsaes_cbc_encrypt: +#ifndef __KERNEL__ + cmp $len, #128 +#ifndef __thumb__ + blo AES_cbc_encrypt +#else + bhs 1f + b AES_cbc_encrypt +1: +#endif +#endif + + @ it is up to the caller to make sure we are called with enc == 0 + + mov ip, sp + stmdb sp!, {r4-r10, lr} + VFP_ABI_PUSH + ldr $ivp, [ip] @ IV is 1st arg on the stack + mov $len, $len, lsr#4 @ len in 16 byte blocks + sub sp, #0x10 @ scratch space to carry over the IV + mov $fp, sp @ save sp + + ldr $rounds, [$key, #240] @ get # of rounds +#ifndef BSAES_ASM_EXTENDED_KEY + @ allocate the key schedule on the stack + sub r12, sp, $rounds, lsl#7 @ 128 bytes per inner round key + add r12, #`128-32` @ sifze of bit-slices key schedule + + @ populate the key schedule + mov r4, $key @ pass key + mov r5, $rounds @ pass # of rounds + mov sp, r12 @ sp is $keysched + bl _bsaes_key_convert + vldmia $keysched, {@XMM[6]} + vstmia r12, {@XMM[15]} @ save last round key + veor @XMM[7], @XMM[7], @XMM[6] @ fix up round 0 key + vstmia $keysched, {@XMM[7]} +#else + ldr r12, [$key, #244] + eors r12, #1 + beq 0f + + @ populate the key schedule + str r12, [$key, #244] + mov r4, $key @ pass key + mov r5, $rounds @ pass # of rounds + add r12, $key, #248 @ pass key schedule + bl _bsaes_key_convert + add r4, $key, #248 + vldmia r4, {@XMM[6]} + vstmia r12, {@XMM[15]} @ save last round key + veor @XMM[7], @XMM[7], @XMM[6] @ fix up round 0 key + vstmia r4, {@XMM[7]} + +.align 2 +0: +#endif + + vld1.8 {@XMM[15]}, [$ivp] @ load IV + b .Lcbc_dec_loop + +.align 4 +.Lcbc_dec_loop: + subs $len, $len, #0x8 + bmi .Lcbc_dec_loop_finish + + vld1.8 {@XMM[0]-@XMM[1]}, [$inp]! @ load input + vld1.8 {@XMM[2]-@XMM[3]}, [$inp]! +#ifndef BSAES_ASM_EXTENDED_KEY + mov r4, $keysched @ pass the key +#else + add r4, $key, #248 +#endif + vld1.8 {@XMM[4]-@XMM[5]}, [$inp]! + mov r5, $rounds + vld1.8 {@XMM[6]-@XMM[7]}, [$inp] + sub $inp, $inp, #0x60 + vstmia $fp, {@XMM[15]} @ put aside IV + + bl _bsaes_decrypt8 + + vldmia $fp, {@XMM[14]} @ reload IV + vld1.8 {@XMM[8]-@XMM[9]}, [$inp]! @ reload input + veor @XMM[0], @XMM[0], @XMM[14] @ ^= IV + vld1.8 {@XMM[10]-@XMM[11]}, [$inp]! + veor @XMM[1], @XMM[1], @XMM[8] + veor @XMM[6], @XMM[6], @XMM[9] + vld1.8 {@XMM[12]-@XMM[13]}, [$inp]! + veor @XMM[4], @XMM[4], @XMM[10] + veor @XMM[2], @XMM[2], @XMM[11] + vld1.8 {@XMM[14]-@XMM[15]}, [$inp]! + veor @XMM[7], @XMM[7], @XMM[12] + vst1.8 {@XMM[0]-@XMM[1]}, [$out]! @ write output + veor @XMM[3], @XMM[3], @XMM[13] + vst1.8 {@XMM[6]}, [$out]! + veor @XMM[5], @XMM[5], @XMM[14] + vst1.8 {@XMM[4]}, [$out]! + vst1.8 {@XMM[2]}, [$out]! + vst1.8 {@XMM[7]}, [$out]! + vst1.8 {@XMM[3]}, [$out]! + vst1.8 {@XMM[5]}, [$out]! + + b .Lcbc_dec_loop + +.Lcbc_dec_loop_finish: + adds $len, $len, #8 + beq .Lcbc_dec_done + + vld1.8 {@XMM[0]}, [$inp]! @ load input + cmp $len, #2 + blo .Lcbc_dec_one + vld1.8 {@XMM[1]}, [$inp]! +#ifndef BSAES_ASM_EXTENDED_KEY + mov r4, $keysched @ pass the key +#else + add r4, $key, #248 +#endif + mov r5, $rounds + vstmia $fp, {@XMM[15]} @ put aside IV + beq .Lcbc_dec_two + vld1.8 {@XMM[2]}, [$inp]! + cmp $len, #4 + blo .Lcbc_dec_three + vld1.8 {@XMM[3]}, [$inp]! + beq .Lcbc_dec_four + vld1.8 {@XMM[4]}, [$inp]! + cmp $len, #6 + blo .Lcbc_dec_five + vld1.8 {@XMM[5]}, [$inp]! + beq .Lcbc_dec_six + vld1.8 {@XMM[6]}, [$inp]! + sub $inp, $inp, #0x70 + + bl _bsaes_decrypt8 + + vldmia $fp, {@XMM[14]} @ reload IV + vld1.8 {@XMM[8]-@XMM[9]}, [$inp]! @ reload input + veor @XMM[0], @XMM[0], @XMM[14] @ ^= IV + vld1.8 {@XMM[10]-@XMM[11]}, [$inp]! + veor @XMM[1], @XMM[1], @XMM[8] + veor @XMM[6], @XMM[6], @XMM[9] + vld1.8 {@XMM[12]-@XMM[13]}, [$inp]! + veor @XMM[4], @XMM[4], @XMM[10] + veor @XMM[2], @XMM[2], @XMM[11] + vld1.8 {@XMM[15]}, [$inp]! + veor @XMM[7], @XMM[7], @XMM[12] + vst1.8 {@XMM[0]-@XMM[1]}, [$out]! @ write output + veor @XMM[3], @XMM[3], @XMM[13] + vst1.8 {@XMM[6]}, [$out]! + vst1.8 {@XMM[4]}, [$out]! + vst1.8 {@XMM[2]}, [$out]! + vst1.8 {@XMM[7]}, [$out]! + vst1.8 {@XMM[3]}, [$out]! + b .Lcbc_dec_done +.align 4 +.Lcbc_dec_six: + sub $inp, $inp, #0x60 + bl _bsaes_decrypt8 + vldmia $fp,{@XMM[14]} @ reload IV + vld1.8 {@XMM[8]-@XMM[9]}, [$inp]! @ reload input + veor @XMM[0], @XMM[0], @XMM[14] @ ^= IV + vld1.8 {@XMM[10]-@XMM[11]}, [$inp]! + veor @XMM[1], @XMM[1], @XMM[8] + veor @XMM[6], @XMM[6], @XMM[9] + vld1.8 {@XMM[12]}, [$inp]! + veor @XMM[4], @XMM[4], @XMM[10] + veor @XMM[2], @XMM[2], @XMM[11] + vld1.8 {@XMM[15]}, [$inp]! + veor @XMM[7], @XMM[7], @XMM[12] + vst1.8 {@XMM[0]-@XMM[1]}, [$out]! @ write output + vst1.8 {@XMM[6]}, [$out]! + vst1.8 {@XMM[4]}, [$out]! + vst1.8 {@XMM[2]}, [$out]! + vst1.8 {@XMM[7]}, [$out]! + b .Lcbc_dec_done +.align 4 +.Lcbc_dec_five: + sub $inp, $inp, #0x50 + bl _bsaes_decrypt8 + vldmia $fp, {@XMM[14]} @ reload IV + vld1.8 {@XMM[8]-@XMM[9]}, [$inp]! @ reload input + veor @XMM[0], @XMM[0], @XMM[14] @ ^= IV + vld1.8 {@XMM[10]-@XMM[11]}, [$inp]! + veor @XMM[1], @XMM[1], @XMM[8] + veor @XMM[6], @XMM[6], @XMM[9] + vld1.8 {@XMM[15]}, [$inp]! + veor @XMM[4], @XMM[4], @XMM[10] + vst1.8 {@XMM[0]-@XMM[1]}, [$out]! @ write output + veor @XMM[2], @XMM[2], @XMM[11] + vst1.8 {@XMM[6]}, [$out]! + vst1.8 {@XMM[4]}, [$out]! + vst1.8 {@XMM[2]}, [$out]! + b .Lcbc_dec_done +.align 4 +.Lcbc_dec_four: + sub $inp, $inp, #0x40 + bl _bsaes_decrypt8 + vldmia $fp, {@XMM[14]} @ reload IV + vld1.8 {@XMM[8]-@XMM[9]}, [$inp]! @ reload input + veor @XMM[0], @XMM[0], @XMM[14] @ ^= IV + vld1.8 {@XMM[10]}, [$inp]! + veor @XMM[1], @XMM[1], @XMM[8] + veor @XMM[6], @XMM[6], @XMM[9] + vld1.8 {@XMM[15]}, [$inp]! + veor @XMM[4], @XMM[4], @XMM[10] + vst1.8 {@XMM[0]-@XMM[1]}, [$out]! @ write output + vst1.8 {@XMM[6]}, [$out]! + vst1.8 {@XMM[4]}, [$out]! + b .Lcbc_dec_done +.align 4 +.Lcbc_dec_three: + sub $inp, $inp, #0x30 + bl _bsaes_decrypt8 + vldmia $fp, {@XMM[14]} @ reload IV + vld1.8 {@XMM[8]-@XMM[9]}, [$inp]! @ reload input + veor @XMM[0], @XMM[0], @XMM[14] @ ^= IV + vld1.8 {@XMM[15]}, [$inp]! + veor @XMM[1], @XMM[1], @XMM[8] + veor @XMM[6], @XMM[6], @XMM[9] + vst1.8 {@XMM[0]-@XMM[1]}, [$out]! @ write output + vst1.8 {@XMM[6]}, [$out]! + b .Lcbc_dec_done +.align 4 +.Lcbc_dec_two: + sub $inp, $inp, #0x20 + bl _bsaes_decrypt8 + vldmia $fp, {@XMM[14]} @ reload IV + vld1.8 {@XMM[8]}, [$inp]! @ reload input + veor @XMM[0], @XMM[0], @XMM[14] @ ^= IV + vld1.8 {@XMM[15]}, [$inp]! @ reload input + veor @XMM[1], @XMM[1], @XMM[8] + vst1.8 {@XMM[0]-@XMM[1]}, [$out]! @ write output + b .Lcbc_dec_done +.align 4 +.Lcbc_dec_one: + sub $inp, $inp, #0x10 + mov $rounds, $out @ save original out pointer + mov $out, $fp @ use the iv scratch space as out buffer + mov r2, $key + vmov @XMM[4],@XMM[15] @ just in case ensure that IV + vmov @XMM[5],@XMM[0] @ and input are preserved + bl AES_decrypt + vld1.8 {@XMM[0]}, [$fp,:64] @ load result + veor @XMM[0], @XMM[0], @XMM[4] @ ^= IV + vmov @XMM[15], @XMM[5] @ @XMM[5] holds input + vst1.8 {@XMM[0]}, [$rounds] @ write output + +.Lcbc_dec_done: +#ifndef BSAES_ASM_EXTENDED_KEY + vmov.i32 q0, #0 + vmov.i32 q1, #0 +.Lcbc_dec_bzero: @ wipe key schedule [if any] + vstmia $keysched!, {q0-q1} + cmp $keysched, $fp + bne .Lcbc_dec_bzero +#endif + + mov sp, $fp + add sp, #0x10 @ add sp,$fp,#0x10 is no good for thumb + vst1.8 {@XMM[15]}, [$ivp] @ return IV + VFP_ABI_POP + ldmia sp!, {r4-r10, pc} +.size bsaes_cbc_encrypt,.-bsaes_cbc_encrypt +___ +} +{ +my ($inp,$out,$len,$key, $ctr,$fp,$rounds)=(map("r$_",(0..3,8..10))); +my $const = "r6"; # shared with _bsaes_encrypt8_alt +my $keysched = "sp"; + +$code.=<<___; +.extern AES_encrypt +.global bsaes_ctr32_encrypt_blocks +.type bsaes_ctr32_encrypt_blocks,%function +.align 5 +bsaes_ctr32_encrypt_blocks: + cmp $len, #8 @ use plain AES for + blo .Lctr_enc_short @ small sizes + + mov ip, sp + stmdb sp!, {r4-r10, lr} + VFP_ABI_PUSH + ldr $ctr, [ip] @ ctr is 1st arg on the stack + sub sp, sp, #0x10 @ scratch space to carry over the ctr + mov $fp, sp @ save sp + + ldr $rounds, [$key, #240] @ get # of rounds +#ifndef BSAES_ASM_EXTENDED_KEY + @ allocate the key schedule on the stack + sub r12, sp, $rounds, lsl#7 @ 128 bytes per inner round key + add r12, #`128-32` @ size of bit-sliced key schedule + + @ populate the key schedule + mov r4, $key @ pass key + mov r5, $rounds @ pass # of rounds + mov sp, r12 @ sp is $keysched + bl _bsaes_key_convert + veor @XMM[7],@XMM[7],@XMM[15] @ fix up last round key + vstmia r12, {@XMM[7]} @ save last round key + + vld1.8 {@XMM[0]}, [$ctr] @ load counter +#ifdef __APPLE__ + mov $ctr, #:lower16:(.LREVM0SR-.LM0) + add $ctr, $const, $ctr +#else + add $ctr, $const, #.LREVM0SR-.LM0 @ borrow $ctr +#endif + vldmia $keysched, {@XMM[4]} @ load round0 key +#else + ldr r12, [$key, #244] + eors r12, #1 + beq 0f + + @ populate the key schedule + str r12, [$key, #244] + mov r4, $key @ pass key + mov r5, $rounds @ pass # of rounds + add r12, $key, #248 @ pass key schedule + bl _bsaes_key_convert + veor @XMM[7],@XMM[7],@XMM[15] @ fix up last round key + vstmia r12, {@XMM[7]} @ save last round key + +.align 2 +0: add r12, $key, #248 + vld1.8 {@XMM[0]}, [$ctr] @ load counter + adrl $ctr, .LREVM0SR @ borrow $ctr + vldmia r12, {@XMM[4]} @ load round0 key + sub sp, #0x10 @ place for adjusted round0 key +#endif + + vmov.i32 @XMM[8],#1 @ compose 1<<96 + veor @XMM[9],@XMM[9],@XMM[9] + vrev32.8 @XMM[0],@XMM[0] + vext.8 @XMM[8],@XMM[9],@XMM[8],#4 + vrev32.8 @XMM[4],@XMM[4] + vadd.u32 @XMM[9],@XMM[8],@XMM[8] @ compose 2<<96 + vstmia $keysched, {@XMM[4]} @ save adjusted round0 key + b .Lctr_enc_loop + +.align 4 +.Lctr_enc_loop: + vadd.u32 @XMM[10], @XMM[8], @XMM[9] @ compose 3<<96 + vadd.u32 @XMM[1], @XMM[0], @XMM[8] @ +1 + vadd.u32 @XMM[2], @XMM[0], @XMM[9] @ +2 + vadd.u32 @XMM[3], @XMM[0], @XMM[10] @ +3 + vadd.u32 @XMM[4], @XMM[1], @XMM[10] + vadd.u32 @XMM[5], @XMM[2], @XMM[10] + vadd.u32 @XMM[6], @XMM[3], @XMM[10] + vadd.u32 @XMM[7], @XMM[4], @XMM[10] + vadd.u32 @XMM[10], @XMM[5], @XMM[10] @ next counter + + @ Borrow prologue from _bsaes_encrypt8 to use the opportunity + @ to flip byte order in 32-bit counter + + vldmia $keysched, {@XMM[9]} @ load round0 key +#ifndef BSAES_ASM_EXTENDED_KEY + add r4, $keysched, #0x10 @ pass next round key +#else + add r4, $key, #`248+16` +#endif + vldmia $ctr, {@XMM[8]} @ .LREVM0SR + mov r5, $rounds @ pass rounds + vstmia $fp, {@XMM[10]} @ save next counter +#ifdef __APPLE__ + mov $const, #:lower16:(.LREVM0SR-.LSR) + sub $const, $ctr, $const +#else + sub $const, $ctr, #.LREVM0SR-.LSR @ pass constants +#endif + + bl _bsaes_encrypt8_alt + + subs $len, $len, #8 + blo .Lctr_enc_loop_done + + vld1.8 {@XMM[8]-@XMM[9]}, [$inp]! @ load input + vld1.8 {@XMM[10]-@XMM[11]}, [$inp]! + veor @XMM[0], @XMM[8] + veor @XMM[1], @XMM[9] + vld1.8 {@XMM[12]-@XMM[13]}, [$inp]! + veor @XMM[4], @XMM[10] + veor @XMM[6], @XMM[11] + vld1.8 {@XMM[14]-@XMM[15]}, [$inp]! + veor @XMM[3], @XMM[12] + vst1.8 {@XMM[0]-@XMM[1]}, [$out]! @ write output + veor @XMM[7], @XMM[13] + veor @XMM[2], @XMM[14] + vst1.8 {@XMM[4]}, [$out]! + veor @XMM[5], @XMM[15] + vst1.8 {@XMM[6]}, [$out]! + vmov.i32 @XMM[8], #1 @ compose 1<<96 + vst1.8 {@XMM[3]}, [$out]! + veor @XMM[9], @XMM[9], @XMM[9] + vst1.8 {@XMM[7]}, [$out]! + vext.8 @XMM[8], @XMM[9], @XMM[8], #4 + vst1.8 {@XMM[2]}, [$out]! + vadd.u32 @XMM[9],@XMM[8],@XMM[8] @ compose 2<<96 + vst1.8 {@XMM[5]}, [$out]! + vldmia $fp, {@XMM[0]} @ load counter + + bne .Lctr_enc_loop + b .Lctr_enc_done + +.align 4 +.Lctr_enc_loop_done: + add $len, $len, #8 + vld1.8 {@XMM[8]}, [$inp]! @ load input + veor @XMM[0], @XMM[8] + vst1.8 {@XMM[0]}, [$out]! @ write output + cmp $len, #2 + blo .Lctr_enc_done + vld1.8 {@XMM[9]}, [$inp]! + veor @XMM[1], @XMM[9] + vst1.8 {@XMM[1]}, [$out]! + beq .Lctr_enc_done + vld1.8 {@XMM[10]}, [$inp]! + veor @XMM[4], @XMM[10] + vst1.8 {@XMM[4]}, [$out]! + cmp $len, #4 + blo .Lctr_enc_done + vld1.8 {@XMM[11]}, [$inp]! + veor @XMM[6], @XMM[11] + vst1.8 {@XMM[6]}, [$out]! + beq .Lctr_enc_done + vld1.8 {@XMM[12]}, [$inp]! + veor @XMM[3], @XMM[12] + vst1.8 {@XMM[3]}, [$out]! + cmp $len, #6 + blo .Lctr_enc_done + vld1.8 {@XMM[13]}, [$inp]! + veor @XMM[7], @XMM[13] + vst1.8 {@XMM[7]}, [$out]! + beq .Lctr_enc_done + vld1.8 {@XMM[14]}, [$inp] + veor @XMM[2], @XMM[14] + vst1.8 {@XMM[2]}, [$out]! + +.Lctr_enc_done: + vmov.i32 q0, #0 + vmov.i32 q1, #0 +#ifndef BSAES_ASM_EXTENDED_KEY +.Lctr_enc_bzero: @ wipe key schedule [if any] + vstmia $keysched!, {q0-q1} + cmp $keysched, $fp + bne .Lctr_enc_bzero +#else + vstmia $keysched, {q0-q1} +#endif + + mov sp, $fp + add sp, #0x10 @ add sp,$fp,#0x10 is no good for thumb + VFP_ABI_POP + ldmia sp!, {r4-r10, pc} @ return + +.align 4 +.Lctr_enc_short: + ldr ip, [sp] @ ctr pointer is passed on stack + stmdb sp!, {r4-r8, lr} + + mov r4, $inp @ copy arguments + mov r5, $out + mov r6, $len + mov r7, $key + ldr r8, [ip, #12] @ load counter LSW + vld1.8 {@XMM[1]}, [ip] @ load whole counter value +#ifdef __ARMEL__ + rev r8, r8 +#endif + sub sp, sp, #0x10 + vst1.8 {@XMM[1]}, [sp] @ copy counter value + sub sp, sp, #0x10 + +.Lctr_enc_short_loop: + add r0, sp, #0x10 @ input counter value + mov r1, sp @ output on the stack + mov r2, r7 @ key + + bl AES_encrypt + + vld1.8 {@XMM[0]}, [r4]! @ load input + vld1.8 {@XMM[1]}, [sp] @ load encrypted counter + add r8, r8, #1 +#ifdef __ARMEL__ + rev r0, r8 + str r0, [sp, #0x1c] @ next counter value +#else + str r8, [sp, #0x1c] @ next counter value +#endif + veor @XMM[0],@XMM[0],@XMM[1] + vst1.8 {@XMM[0]}, [r5]! @ store output + subs r6, r6, #1 + bne .Lctr_enc_short_loop + + vmov.i32 q0, #0 + vmov.i32 q1, #0 + vstmia sp!, {q0-q1} + + ldmia sp!, {r4-r8, pc} +.size bsaes_ctr32_encrypt_blocks,.-bsaes_ctr32_encrypt_blocks +___ +} +{ +###################################################################### +# void bsaes_xts_[en|de]crypt(const char *inp,char *out,size_t len, +# const AES_KEY *key1, const AES_KEY *key2, +# const unsigned char iv[16]); +# +my ($inp,$out,$len,$key,$rounds,$magic,$fp)=(map("r$_",(7..10,1..3))); +my $const="r6"; # returned by _bsaes_key_convert +my $twmask=@XMM[5]; +my @T=@XMM[6..7]; + +$code.=<<___; +.globl bsaes_xts_encrypt +.type bsaes_xts_encrypt,%function +.align 4 +bsaes_xts_encrypt: + mov ip, sp + stmdb sp!, {r4-r10, lr} @ 0x20 + VFP_ABI_PUSH + mov r6, sp @ future $fp + + mov $inp, r0 + mov $out, r1 + mov $len, r2 + mov $key, r3 + + sub r0, sp, #0x10 @ 0x10 + bic r0, #0xf @ align at 16 bytes + mov sp, r0 + +#ifdef XTS_CHAIN_TWEAK + ldr r0, [ip] @ pointer to input tweak +#else + @ generate initial tweak + ldr r0, [ip, #4] @ iv[] + mov r1, sp + ldr r2, [ip, #0] @ key2 + bl AES_encrypt + mov r0,sp @ pointer to initial tweak +#endif + + ldr $rounds, [$key, #240] @ get # of rounds + mov $fp, r6 +#ifndef BSAES_ASM_EXTENDED_KEY + @ allocate the key schedule on the stack + sub r12, sp, $rounds, lsl#7 @ 128 bytes per inner round key + @ add r12, #`128-32` @ size of bit-sliced key schedule + sub r12, #`32+16` @ place for tweak[9] + + @ populate the key schedule + mov r4, $key @ pass key + mov r5, $rounds @ pass # of rounds + mov sp, r12 + add r12, #0x90 @ pass key schedule + bl _bsaes_key_convert + veor @XMM[7], @XMM[7], @XMM[15] @ fix up last round key + vstmia r12, {@XMM[7]} @ save last round key +#else + ldr r12, [$key, #244] + eors r12, #1 + beq 0f + + str r12, [$key, #244] + mov r4, $key @ pass key + mov r5, $rounds @ pass # of rounds + add r12, $key, #248 @ pass key schedule + bl _bsaes_key_convert + veor @XMM[7], @XMM[7], @XMM[15] @ fix up last round key + vstmia r12, {@XMM[7]} + +.align 2 +0: sub sp, #0x90 @ place for tweak[9] +#endif + + vld1.8 {@XMM[8]}, [r0] @ initial tweak + adr $magic, .Lxts_magic + + subs $len, #0x80 + blo .Lxts_enc_short + b .Lxts_enc_loop + +.align 4 +.Lxts_enc_loop: + vldmia $magic, {$twmask} @ load XTS magic + vshr.s64 @T[0], @XMM[8], #63 + mov r0, sp + vand @T[0], @T[0], $twmask +___ +for($i=9;$i<16;$i++) { +$code.=<<___; + vadd.u64 @XMM[$i], @XMM[$i-1], @XMM[$i-1] + vst1.64 {@XMM[$i-1]}, [r0,:128]! + vswp `&Dhi("@T[0]")`,`&Dlo("@T[0]")` + vshr.s64 @T[1], @XMM[$i], #63 + veor @XMM[$i], @XMM[$i], @T[0] + vand @T[1], @T[1], $twmask +___ + @T=reverse(@T); + +$code.=<<___ if ($i>=10); + vld1.8 {@XMM[$i-10]}, [$inp]! +___ +$code.=<<___ if ($i>=11); + veor @XMM[$i-11], @XMM[$i-11], @XMM[$i-3] +___ +} +$code.=<<___; + vadd.u64 @XMM[8], @XMM[15], @XMM[15] + vst1.64 {@XMM[15]}, [r0,:128]! + vswp `&Dhi("@T[0]")`,`&Dlo("@T[0]")` + veor @XMM[8], @XMM[8], @T[0] + vst1.64 {@XMM[8]}, [r0,:128] @ next round tweak + + vld1.8 {@XMM[6]-@XMM[7]}, [$inp]! + veor @XMM[5], @XMM[5], @XMM[13] +#ifndef BSAES_ASM_EXTENDED_KEY + add r4, sp, #0x90 @ pass key schedule +#else + add r4, $key, #248 @ pass key schedule +#endif + veor @XMM[6], @XMM[6], @XMM[14] + mov r5, $rounds @ pass rounds + veor @XMM[7], @XMM[7], @XMM[15] + mov r0, sp + + bl _bsaes_encrypt8 + + vld1.64 {@XMM[ 8]-@XMM[ 9]}, [r0,:128]! + vld1.64 {@XMM[10]-@XMM[11]}, [r0,:128]! + veor @XMM[0], @XMM[0], @XMM[ 8] + vld1.64 {@XMM[12]-@XMM[13]}, [r0,:128]! + veor @XMM[1], @XMM[1], @XMM[ 9] + veor @XMM[8], @XMM[4], @XMM[10] + vst1.8 {@XMM[0]-@XMM[1]}, [$out]! + veor @XMM[9], @XMM[6], @XMM[11] + vld1.64 {@XMM[14]-@XMM[15]}, [r0,:128]! + veor @XMM[10], @XMM[3], @XMM[12] + vst1.8 {@XMM[8]-@XMM[9]}, [$out]! + veor @XMM[11], @XMM[7], @XMM[13] + veor @XMM[12], @XMM[2], @XMM[14] + vst1.8 {@XMM[10]-@XMM[11]}, [$out]! + veor @XMM[13], @XMM[5], @XMM[15] + vst1.8 {@XMM[12]-@XMM[13]}, [$out]! + + vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak + + subs $len, #0x80 + bpl .Lxts_enc_loop + +.Lxts_enc_short: + adds $len, #0x70 + bmi .Lxts_enc_done + + vldmia $magic, {$twmask} @ load XTS magic + vshr.s64 @T[0], @XMM[8], #63 + mov r0, sp + vand @T[0], @T[0], $twmask +___ +for($i=9;$i<16;$i++) { +$code.=<<___; + vadd.u64 @XMM[$i], @XMM[$i-1], @XMM[$i-1] + vst1.64 {@XMM[$i-1]}, [r0,:128]! + vswp `&Dhi("@T[0]")`,`&Dlo("@T[0]")` + vshr.s64 @T[1], @XMM[$i], #63 + veor @XMM[$i], @XMM[$i], @T[0] + vand @T[1], @T[1], $twmask +___ + @T=reverse(@T); + +$code.=<<___ if ($i>=10); + vld1.8 {@XMM[$i-10]}, [$inp]! + subs $len, #0x10 + bmi .Lxts_enc_`$i-9` +___ +$code.=<<___ if ($i>=11); + veor @XMM[$i-11], @XMM[$i-11], @XMM[$i-3] +___ +} +$code.=<<___; + sub $len, #0x10 + vst1.64 {@XMM[15]}, [r0,:128] @ next round tweak + + vld1.8 {@XMM[6]}, [$inp]! + veor @XMM[5], @XMM[5], @XMM[13] +#ifndef BSAES_ASM_EXTENDED_KEY + add r4, sp, #0x90 @ pass key schedule +#else + add r4, $key, #248 @ pass key schedule +#endif + veor @XMM[6], @XMM[6], @XMM[14] + mov r5, $rounds @ pass rounds + mov r0, sp + + bl _bsaes_encrypt8 + + vld1.64 {@XMM[ 8]-@XMM[ 9]}, [r0,:128]! + vld1.64 {@XMM[10]-@XMM[11]}, [r0,:128]! + veor @XMM[0], @XMM[0], @XMM[ 8] + vld1.64 {@XMM[12]-@XMM[13]}, [r0,:128]! + veor @XMM[1], @XMM[1], @XMM[ 9] + veor @XMM[8], @XMM[4], @XMM[10] + vst1.8 {@XMM[0]-@XMM[1]}, [$out]! + veor @XMM[9], @XMM[6], @XMM[11] + vld1.64 {@XMM[14]}, [r0,:128]! + veor @XMM[10], @XMM[3], @XMM[12] + vst1.8 {@XMM[8]-@XMM[9]}, [$out]! + veor @XMM[11], @XMM[7], @XMM[13] + veor @XMM[12], @XMM[2], @XMM[14] + vst1.8 {@XMM[10]-@XMM[11]}, [$out]! + vst1.8 {@XMM[12]}, [$out]! + + vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak + b .Lxts_enc_done +.align 4 +.Lxts_enc_6: + vst1.64 {@XMM[14]}, [r0,:128] @ next round tweak + + veor @XMM[4], @XMM[4], @XMM[12] +#ifndef BSAES_ASM_EXTENDED_KEY + add r4, sp, #0x90 @ pass key schedule +#else + add r4, $key, #248 @ pass key schedule +#endif + veor @XMM[5], @XMM[5], @XMM[13] + mov r5, $rounds @ pass rounds + mov r0, sp + + bl _bsaes_encrypt8 + + vld1.64 {@XMM[ 8]-@XMM[ 9]}, [r0,:128]! + vld1.64 {@XMM[10]-@XMM[11]}, [r0,:128]! + veor @XMM[0], @XMM[0], @XMM[ 8] + vld1.64 {@XMM[12]-@XMM[13]}, [r0,:128]! + veor @XMM[1], @XMM[1], @XMM[ 9] + veor @XMM[8], @XMM[4], @XMM[10] + vst1.8 {@XMM[0]-@XMM[1]}, [$out]! + veor @XMM[9], @XMM[6], @XMM[11] + veor @XMM[10], @XMM[3], @XMM[12] + vst1.8 {@XMM[8]-@XMM[9]}, [$out]! + veor @XMM[11], @XMM[7], @XMM[13] + vst1.8 {@XMM[10]-@XMM[11]}, [$out]! + + vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak + b .Lxts_enc_done + +@ put this in range for both ARM and Thumb mode adr instructions +.align 5 +.Lxts_magic: + .quad 1, 0x87 + +.align 5 +.Lxts_enc_5: + vst1.64 {@XMM[13]}, [r0,:128] @ next round tweak + + veor @XMM[3], @XMM[3], @XMM[11] +#ifndef BSAES_ASM_EXTENDED_KEY + add r4, sp, #0x90 @ pass key schedule +#else + add r4, $key, #248 @ pass key schedule +#endif + veor @XMM[4], @XMM[4], @XMM[12] + mov r5, $rounds @ pass rounds + mov r0, sp + + bl _bsaes_encrypt8 + + vld1.64 {@XMM[ 8]-@XMM[ 9]}, [r0,:128]! + vld1.64 {@XMM[10]-@XMM[11]}, [r0,:128]! + veor @XMM[0], @XMM[0], @XMM[ 8] + vld1.64 {@XMM[12]}, [r0,:128]! + veor @XMM[1], @XMM[1], @XMM[ 9] + veor @XMM[8], @XMM[4], @XMM[10] + vst1.8 {@XMM[0]-@XMM[1]}, [$out]! + veor @XMM[9], @XMM[6], @XMM[11] + veor @XMM[10], @XMM[3], @XMM[12] + vst1.8 {@XMM[8]-@XMM[9]}, [$out]! + vst1.8 {@XMM[10]}, [$out]! + + vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak + b .Lxts_enc_done +.align 4 +.Lxts_enc_4: + vst1.64 {@XMM[12]}, [r0,:128] @ next round tweak + + veor @XMM[2], @XMM[2], @XMM[10] +#ifndef BSAES_ASM_EXTENDED_KEY + add r4, sp, #0x90 @ pass key schedule +#else + add r4, $key, #248 @ pass key schedule +#endif + veor @XMM[3], @XMM[3], @XMM[11] + mov r5, $rounds @ pass rounds + mov r0, sp + + bl _bsaes_encrypt8 + + vld1.64 {@XMM[ 8]-@XMM[ 9]}, [r0,:128]! + vld1.64 {@XMM[10]-@XMM[11]}, [r0,:128]! + veor @XMM[0], @XMM[0], @XMM[ 8] + veor @XMM[1], @XMM[1], @XMM[ 9] + veor @XMM[8], @XMM[4], @XMM[10] + vst1.8 {@XMM[0]-@XMM[1]}, [$out]! + veor @XMM[9], @XMM[6], @XMM[11] + vst1.8 {@XMM[8]-@XMM[9]}, [$out]! + + vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak + b .Lxts_enc_done +.align 4 +.Lxts_enc_3: + vst1.64 {@XMM[11]}, [r0,:128] @ next round tweak + + veor @XMM[1], @XMM[1], @XMM[9] +#ifndef BSAES_ASM_EXTENDED_KEY + add r4, sp, #0x90 @ pass key schedule +#else + add r4, $key, #248 @ pass key schedule +#endif + veor @XMM[2], @XMM[2], @XMM[10] + mov r5, $rounds @ pass rounds + mov r0, sp + + bl _bsaes_encrypt8 + + vld1.64 {@XMM[8]-@XMM[9]}, [r0,:128]! + vld1.64 {@XMM[10]}, [r0,:128]! + veor @XMM[0], @XMM[0], @XMM[ 8] + veor @XMM[1], @XMM[1], @XMM[ 9] + veor @XMM[8], @XMM[4], @XMM[10] + vst1.8 {@XMM[0]-@XMM[1]}, [$out]! + vst1.8 {@XMM[8]}, [$out]! + + vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak + b .Lxts_enc_done +.align 4 +.Lxts_enc_2: + vst1.64 {@XMM[10]}, [r0,:128] @ next round tweak + + veor @XMM[0], @XMM[0], @XMM[8] +#ifndef BSAES_ASM_EXTENDED_KEY + add r4, sp, #0x90 @ pass key schedule +#else + add r4, $key, #248 @ pass key schedule +#endif + veor @XMM[1], @XMM[1], @XMM[9] + mov r5, $rounds @ pass rounds + mov r0, sp + + bl _bsaes_encrypt8 + + vld1.64 {@XMM[8]-@XMM[9]}, [r0,:128]! + veor @XMM[0], @XMM[0], @XMM[ 8] + veor @XMM[1], @XMM[1], @XMM[ 9] + vst1.8 {@XMM[0]-@XMM[1]}, [$out]! + + vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak + b .Lxts_enc_done +.align 4 +.Lxts_enc_1: + mov r0, sp + veor @XMM[0], @XMM[8] + mov r1, sp + vst1.8 {@XMM[0]}, [sp,:128] + mov r2, $key + mov r4, $fp @ preserve fp + + bl AES_encrypt + + vld1.8 {@XMM[0]}, [sp,:128] + veor @XMM[0], @XMM[0], @XMM[8] + vst1.8 {@XMM[0]}, [$out]! + mov $fp, r4 + + vmov @XMM[8], @XMM[9] @ next round tweak + +.Lxts_enc_done: +#ifndef XTS_CHAIN_TWEAK + adds $len, #0x10 + beq .Lxts_enc_ret + sub r6, $out, #0x10 + +.Lxts_enc_steal: + ldrb r0, [$inp], #1 + ldrb r1, [$out, #-0x10] + strb r0, [$out, #-0x10] + strb r1, [$out], #1 + + subs $len, #1 + bhi .Lxts_enc_steal + + vld1.8 {@XMM[0]}, [r6] + mov r0, sp + veor @XMM[0], @XMM[0], @XMM[8] + mov r1, sp + vst1.8 {@XMM[0]}, [sp,:128] + mov r2, $key + mov r4, $fp @ preserve fp + + bl AES_encrypt + + vld1.8 {@XMM[0]}, [sp,:128] + veor @XMM[0], @XMM[0], @XMM[8] + vst1.8 {@XMM[0]}, [r6] + mov $fp, r4 +#endif + +.Lxts_enc_ret: + bic r0, $fp, #0xf + vmov.i32 q0, #0 + vmov.i32 q1, #0 +#ifdef XTS_CHAIN_TWEAK + ldr r1, [$fp, #0x20+VFP_ABI_FRAME] @ chain tweak +#endif +.Lxts_enc_bzero: @ wipe key schedule [if any] + vstmia sp!, {q0-q1} + cmp sp, r0 + bne .Lxts_enc_bzero + + mov sp, $fp +#ifdef XTS_CHAIN_TWEAK + vst1.8 {@XMM[8]}, [r1] +#endif + VFP_ABI_POP + ldmia sp!, {r4-r10, pc} @ return + +.size bsaes_xts_encrypt,.-bsaes_xts_encrypt + +.globl bsaes_xts_decrypt +.type bsaes_xts_decrypt,%function +.align 4 +bsaes_xts_decrypt: + mov ip, sp + stmdb sp!, {r4-r10, lr} @ 0x20 + VFP_ABI_PUSH + mov r6, sp @ future $fp + + mov $inp, r0 + mov $out, r1 + mov $len, r2 + mov $key, r3 + + sub r0, sp, #0x10 @ 0x10 + bic r0, #0xf @ align at 16 bytes + mov sp, r0 + +#ifdef XTS_CHAIN_TWEAK + ldr r0, [ip] @ pointer to input tweak +#else + @ generate initial tweak + ldr r0, [ip, #4] @ iv[] + mov r1, sp + ldr r2, [ip, #0] @ key2 + bl AES_encrypt + mov r0, sp @ pointer to initial tweak +#endif + + ldr $rounds, [$key, #240] @ get # of rounds + mov $fp, r6 +#ifndef BSAES_ASM_EXTENDED_KEY + @ allocate the key schedule on the stack + sub r12, sp, $rounds, lsl#7 @ 128 bytes per inner round key + @ add r12, #`128-32` @ size of bit-sliced key schedule + sub r12, #`32+16` @ place for tweak[9] + + @ populate the key schedule + mov r4, $key @ pass key + mov r5, $rounds @ pass # of rounds + mov sp, r12 + add r12, #0x90 @ pass key schedule + bl _bsaes_key_convert + add r4, sp, #0x90 + vldmia r4, {@XMM[6]} + vstmia r12, {@XMM[15]} @ save last round key + veor @XMM[7], @XMM[7], @XMM[6] @ fix up round 0 key + vstmia r4, {@XMM[7]} +#else + ldr r12, [$key, #244] + eors r12, #1 + beq 0f + + str r12, [$key, #244] + mov r4, $key @ pass key + mov r5, $rounds @ pass # of rounds + add r12, $key, #248 @ pass key schedule + bl _bsaes_key_convert + add r4, $key, #248 + vldmia r4, {@XMM[6]} + vstmia r12, {@XMM[15]} @ save last round key + veor @XMM[7], @XMM[7], @XMM[6] @ fix up round 0 key + vstmia r4, {@XMM[7]} + +.align 2 +0: sub sp, #0x90 @ place for tweak[9] +#endif + vld1.8 {@XMM[8]}, [r0] @ initial tweak + adr $magic, .Lxts_magic + +#ifndef XTS_CHAIN_TWEAK + tst $len, #0xf @ if not multiple of 16 + it ne @ Thumb2 thing, sanity check in ARM + subne $len, #0x10 @ subtract another 16 bytes +#endif + subs $len, #0x80 + + blo .Lxts_dec_short + b .Lxts_dec_loop + +.align 4 +.Lxts_dec_loop: + vldmia $magic, {$twmask} @ load XTS magic + vshr.s64 @T[0], @XMM[8], #63 + mov r0, sp + vand @T[0], @T[0], $twmask +___ +for($i=9;$i<16;$i++) { +$code.=<<___; + vadd.u64 @XMM[$i], @XMM[$i-1], @XMM[$i-1] + vst1.64 {@XMM[$i-1]}, [r0,:128]! + vswp `&Dhi("@T[0]")`,`&Dlo("@T[0]")` + vshr.s64 @T[1], @XMM[$i], #63 + veor @XMM[$i], @XMM[$i], @T[0] + vand @T[1], @T[1], $twmask +___ + @T=reverse(@T); + +$code.=<<___ if ($i>=10); + vld1.8 {@XMM[$i-10]}, [$inp]! +___ +$code.=<<___ if ($i>=11); + veor @XMM[$i-11], @XMM[$i-11], @XMM[$i-3] +___ +} +$code.=<<___; + vadd.u64 @XMM[8], @XMM[15], @XMM[15] + vst1.64 {@XMM[15]}, [r0,:128]! + vswp `&Dhi("@T[0]")`,`&Dlo("@T[0]")` + veor @XMM[8], @XMM[8], @T[0] + vst1.64 {@XMM[8]}, [r0,:128] @ next round tweak + + vld1.8 {@XMM[6]-@XMM[7]}, [$inp]! + veor @XMM[5], @XMM[5], @XMM[13] +#ifndef BSAES_ASM_EXTENDED_KEY + add r4, sp, #0x90 @ pass key schedule +#else + add r4, $key, #248 @ pass key schedule +#endif + veor @XMM[6], @XMM[6], @XMM[14] + mov r5, $rounds @ pass rounds + veor @XMM[7], @XMM[7], @XMM[15] + mov r0, sp + + bl _bsaes_decrypt8 + + vld1.64 {@XMM[ 8]-@XMM[ 9]}, [r0,:128]! + vld1.64 {@XMM[10]-@XMM[11]}, [r0,:128]! + veor @XMM[0], @XMM[0], @XMM[ 8] + vld1.64 {@XMM[12]-@XMM[13]}, [r0,:128]! + veor @XMM[1], @XMM[1], @XMM[ 9] + veor @XMM[8], @XMM[6], @XMM[10] + vst1.8 {@XMM[0]-@XMM[1]}, [$out]! + veor @XMM[9], @XMM[4], @XMM[11] + vld1.64 {@XMM[14]-@XMM[15]}, [r0,:128]! + veor @XMM[10], @XMM[2], @XMM[12] + vst1.8 {@XMM[8]-@XMM[9]}, [$out]! + veor @XMM[11], @XMM[7], @XMM[13] + veor @XMM[12], @XMM[3], @XMM[14] + vst1.8 {@XMM[10]-@XMM[11]}, [$out]! + veor @XMM[13], @XMM[5], @XMM[15] + vst1.8 {@XMM[12]-@XMM[13]}, [$out]! + + vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak + + subs $len, #0x80 + bpl .Lxts_dec_loop + +.Lxts_dec_short: + adds $len, #0x70 + bmi .Lxts_dec_done + + vldmia $magic, {$twmask} @ load XTS magic + vshr.s64 @T[0], @XMM[8], #63 + mov r0, sp + vand @T[0], @T[0], $twmask +___ +for($i=9;$i<16;$i++) { +$code.=<<___; + vadd.u64 @XMM[$i], @XMM[$i-1], @XMM[$i-1] + vst1.64 {@XMM[$i-1]}, [r0,:128]! + vswp `&Dhi("@T[0]")`,`&Dlo("@T[0]")` + vshr.s64 @T[1], @XMM[$i], #63 + veor @XMM[$i], @XMM[$i], @T[0] + vand @T[1], @T[1], $twmask +___ + @T=reverse(@T); + +$code.=<<___ if ($i>=10); + vld1.8 {@XMM[$i-10]}, [$inp]! + subs $len, #0x10 + bmi .Lxts_dec_`$i-9` +___ +$code.=<<___ if ($i>=11); + veor @XMM[$i-11], @XMM[$i-11], @XMM[$i-3] +___ +} +$code.=<<___; + sub $len, #0x10 + vst1.64 {@XMM[15]}, [r0,:128] @ next round tweak + + vld1.8 {@XMM[6]}, [$inp]! + veor @XMM[5], @XMM[5], @XMM[13] +#ifndef BSAES_ASM_EXTENDED_KEY + add r4, sp, #0x90 @ pass key schedule +#else + add r4, $key, #248 @ pass key schedule +#endif + veor @XMM[6], @XMM[6], @XMM[14] + mov r5, $rounds @ pass rounds + mov r0, sp + + bl _bsaes_decrypt8 + + vld1.64 {@XMM[ 8]-@XMM[ 9]}, [r0,:128]! + vld1.64 {@XMM[10]-@XMM[11]}, [r0,:128]! + veor @XMM[0], @XMM[0], @XMM[ 8] + vld1.64 {@XMM[12]-@XMM[13]}, [r0,:128]! + veor @XMM[1], @XMM[1], @XMM[ 9] + veor @XMM[8], @XMM[6], @XMM[10] + vst1.8 {@XMM[0]-@XMM[1]}, [$out]! + veor @XMM[9], @XMM[4], @XMM[11] + vld1.64 {@XMM[14]}, [r0,:128]! + veor @XMM[10], @XMM[2], @XMM[12] + vst1.8 {@XMM[8]-@XMM[9]}, [$out]! + veor @XMM[11], @XMM[7], @XMM[13] + veor @XMM[12], @XMM[3], @XMM[14] + vst1.8 {@XMM[10]-@XMM[11]}, [$out]! + vst1.8 {@XMM[12]}, [$out]! + + vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak + b .Lxts_dec_done +.align 4 +.Lxts_dec_6: + vst1.64 {@XMM[14]}, [r0,:128] @ next round tweak + + veor @XMM[4], @XMM[4], @XMM[12] +#ifndef BSAES_ASM_EXTENDED_KEY + add r4, sp, #0x90 @ pass key schedule +#else + add r4, $key, #248 @ pass key schedule +#endif + veor @XMM[5], @XMM[5], @XMM[13] + mov r5, $rounds @ pass rounds + mov r0, sp + + bl _bsaes_decrypt8 + + vld1.64 {@XMM[ 8]-@XMM[ 9]}, [r0,:128]! + vld1.64 {@XMM[10]-@XMM[11]}, [r0,:128]! + veor @XMM[0], @XMM[0], @XMM[ 8] + vld1.64 {@XMM[12]-@XMM[13]}, [r0,:128]! + veor @XMM[1], @XMM[1], @XMM[ 9] + veor @XMM[8], @XMM[6], @XMM[10] + vst1.8 {@XMM[0]-@XMM[1]}, [$out]! + veor @XMM[9], @XMM[4], @XMM[11] + veor @XMM[10], @XMM[2], @XMM[12] + vst1.8 {@XMM[8]-@XMM[9]}, [$out]! + veor @XMM[11], @XMM[7], @XMM[13] + vst1.8 {@XMM[10]-@XMM[11]}, [$out]! + + vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak + b .Lxts_dec_done +.align 4 +.Lxts_dec_5: + vst1.64 {@XMM[13]}, [r0,:128] @ next round tweak + + veor @XMM[3], @XMM[3], @XMM[11] +#ifndef BSAES_ASM_EXTENDED_KEY + add r4, sp, #0x90 @ pass key schedule +#else + add r4, $key, #248 @ pass key schedule +#endif + veor @XMM[4], @XMM[4], @XMM[12] + mov r5, $rounds @ pass rounds + mov r0, sp + + bl _bsaes_decrypt8 + + vld1.64 {@XMM[ 8]-@XMM[ 9]}, [r0,:128]! + vld1.64 {@XMM[10]-@XMM[11]}, [r0,:128]! + veor @XMM[0], @XMM[0], @XMM[ 8] + vld1.64 {@XMM[12]}, [r0,:128]! + veor @XMM[1], @XMM[1], @XMM[ 9] + veor @XMM[8], @XMM[6], @XMM[10] + vst1.8 {@XMM[0]-@XMM[1]}, [$out]! + veor @XMM[9], @XMM[4], @XMM[11] + veor @XMM[10], @XMM[2], @XMM[12] + vst1.8 {@XMM[8]-@XMM[9]}, [$out]! + vst1.8 {@XMM[10]}, [$out]! + + vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak + b .Lxts_dec_done +.align 4 +.Lxts_dec_4: + vst1.64 {@XMM[12]}, [r0,:128] @ next round tweak + + veor @XMM[2], @XMM[2], @XMM[10] +#ifndef BSAES_ASM_EXTENDED_KEY + add r4, sp, #0x90 @ pass key schedule +#else + add r4, $key, #248 @ pass key schedule +#endif + veor @XMM[3], @XMM[3], @XMM[11] + mov r5, $rounds @ pass rounds + mov r0, sp + + bl _bsaes_decrypt8 + + vld1.64 {@XMM[ 8]-@XMM[ 9]}, [r0,:128]! + vld1.64 {@XMM[10]-@XMM[11]}, [r0,:128]! + veor @XMM[0], @XMM[0], @XMM[ 8] + veor @XMM[1], @XMM[1], @XMM[ 9] + veor @XMM[8], @XMM[6], @XMM[10] + vst1.8 {@XMM[0]-@XMM[1]}, [$out]! + veor @XMM[9], @XMM[4], @XMM[11] + vst1.8 {@XMM[8]-@XMM[9]}, [$out]! + + vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak + b .Lxts_dec_done +.align 4 +.Lxts_dec_3: + vst1.64 {@XMM[11]}, [r0,:128] @ next round tweak + + veor @XMM[1], @XMM[1], @XMM[9] +#ifndef BSAES_ASM_EXTENDED_KEY + add r4, sp, #0x90 @ pass key schedule +#else + add r4, $key, #248 @ pass key schedule +#endif + veor @XMM[2], @XMM[2], @XMM[10] + mov r5, $rounds @ pass rounds + mov r0, sp + + bl _bsaes_decrypt8 + + vld1.64 {@XMM[8]-@XMM[9]}, [r0,:128]! + vld1.64 {@XMM[10]}, [r0,:128]! + veor @XMM[0], @XMM[0], @XMM[ 8] + veor @XMM[1], @XMM[1], @XMM[ 9] + veor @XMM[8], @XMM[6], @XMM[10] + vst1.8 {@XMM[0]-@XMM[1]}, [$out]! + vst1.8 {@XMM[8]}, [$out]! + + vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak + b .Lxts_dec_done +.align 4 +.Lxts_dec_2: + vst1.64 {@XMM[10]}, [r0,:128] @ next round tweak + + veor @XMM[0], @XMM[0], @XMM[8] +#ifndef BSAES_ASM_EXTENDED_KEY + add r4, sp, #0x90 @ pass key schedule +#else + add r4, $key, #248 @ pass key schedule +#endif + veor @XMM[1], @XMM[1], @XMM[9] + mov r5, $rounds @ pass rounds + mov r0, sp + + bl _bsaes_decrypt8 + + vld1.64 {@XMM[8]-@XMM[9]}, [r0,:128]! + veor @XMM[0], @XMM[0], @XMM[ 8] + veor @XMM[1], @XMM[1], @XMM[ 9] + vst1.8 {@XMM[0]-@XMM[1]}, [$out]! + + vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak + b .Lxts_dec_done +.align 4 +.Lxts_dec_1: + mov r0, sp + veor @XMM[0], @XMM[8] + mov r1, sp + vst1.8 {@XMM[0]}, [sp,:128] + mov r2, $key + mov r4, $fp @ preserve fp + mov r5, $magic @ preserve magic + + bl AES_decrypt + + vld1.8 {@XMM[0]}, [sp,:128] + veor @XMM[0], @XMM[0], @XMM[8] + vst1.8 {@XMM[0]}, [$out]! + mov $fp, r4 + mov $magic, r5 + + vmov @XMM[8], @XMM[9] @ next round tweak + +.Lxts_dec_done: +#ifndef XTS_CHAIN_TWEAK + adds $len, #0x10 + beq .Lxts_dec_ret + + @ calculate one round of extra tweak for the stolen ciphertext + vldmia $magic, {$twmask} + vshr.s64 @XMM[6], @XMM[8], #63 + vand @XMM[6], @XMM[6], $twmask + vadd.u64 @XMM[9], @XMM[8], @XMM[8] + vswp `&Dhi("@XMM[6]")`,`&Dlo("@XMM[6]")` + veor @XMM[9], @XMM[9], @XMM[6] + + @ perform the final decryption with the last tweak value + vld1.8 {@XMM[0]}, [$inp]! + mov r0, sp + veor @XMM[0], @XMM[0], @XMM[9] + mov r1, sp + vst1.8 {@XMM[0]}, [sp,:128] + mov r2, $key + mov r4, $fp @ preserve fp + + bl AES_decrypt + + vld1.8 {@XMM[0]}, [sp,:128] + veor @XMM[0], @XMM[0], @XMM[9] + vst1.8 {@XMM[0]}, [$out] + + mov r6, $out +.Lxts_dec_steal: + ldrb r1, [$out] + ldrb r0, [$inp], #1 + strb r1, [$out, #0x10] + strb r0, [$out], #1 + + subs $len, #1 + bhi .Lxts_dec_steal + + vld1.8 {@XMM[0]}, [r6] + mov r0, sp + veor @XMM[0], @XMM[8] + mov r1, sp + vst1.8 {@XMM[0]}, [sp,:128] + mov r2, $key + + bl AES_decrypt + + vld1.8 {@XMM[0]}, [sp,:128] + veor @XMM[0], @XMM[0], @XMM[8] + vst1.8 {@XMM[0]}, [r6] + mov $fp, r4 +#endif + +.Lxts_dec_ret: + bic r0, $fp, #0xf + vmov.i32 q0, #0 + vmov.i32 q1, #0 +#ifdef XTS_CHAIN_TWEAK + ldr r1, [$fp, #0x20+VFP_ABI_FRAME] @ chain tweak +#endif +.Lxts_dec_bzero: @ wipe key schedule [if any] + vstmia sp!, {q0-q1} + cmp sp, r0 + bne .Lxts_dec_bzero + + mov sp, $fp +#ifdef XTS_CHAIN_TWEAK + vst1.8 {@XMM[8]}, [r1] +#endif + VFP_ABI_POP + ldmia sp!, {r4-r10, pc} @ return + +.size bsaes_xts_decrypt,.-bsaes_xts_decrypt +___ +} +$code.=<<___; +#endif +___ + +$code =~ s/\`([^\`]*)\`/eval($1)/gem; + +open SELF,$0; +while() { + next if (/^#!/); + last if (!s/^#/@/ and !/^$/); + print; +} +close SELF; + +print $code; + +close STDOUT; diff --git a/external/boringssl/crypto/aes/asm/bsaes-x86_64.pl b/external/boringssl/crypto/aes/asm/bsaes-x86_64.pl new file mode 100644 index 0000000000..3f7d33c45b --- /dev/null +++ b/external/boringssl/crypto/aes/asm/bsaes-x86_64.pl @@ -0,0 +1,3102 @@ +#!/usr/bin/env perl + +################################################################### +### AES-128 [originally in CTR mode] ### +### bitsliced implementation for Intel Core 2 processors ### +### requires support of SSE extensions up to SSSE3 ### +### Author: Emilia Käsper and Peter Schwabe ### +### Date: 2009-03-19 ### +### Public domain ### +### ### +### See http://homes.esat.kuleuven.be/~ekasper/#software for ### +### further information. ### +################################################################### +# +# September 2011. +# +# Started as transliteration to "perlasm" the original code has +# undergone following changes: +# +# - code was made position-independent; +# - rounds were folded into a loop resulting in >5x size reduction +# from 12.5KB to 2.2KB; +# - above was possibile thanks to mixcolumns() modification that +# allowed to feed its output back to aesenc[last], this was +# achieved at cost of two additional inter-registers moves; +# - some instruction reordering and interleaving; +# - this module doesn't implement key setup subroutine, instead it +# relies on conversion of "conventional" key schedule as returned +# by AES_set_encrypt_key (see discussion below); +# - first and last round keys are treated differently, which allowed +# to skip one shiftrows(), reduce bit-sliced key schedule and +# speed-up conversion by 22%; +# - support for 192- and 256-bit keys was added; +# +# Resulting performance in CPU cycles spent to encrypt one byte out +# of 4096-byte buffer with 128-bit key is: +# +# Emilia's this(*) difference +# +# Core 2 9.30 8.69 +7% +# Nehalem(**) 7.63 6.88 +11% +# Atom 17.1 16.4 +4% +# Silvermont - 12.9 +# +# (*) Comparison is not completely fair, because "this" is ECB, +# i.e. no extra processing such as counter values calculation +# and xor-ing input as in Emilia's CTR implementation is +# performed. However, the CTR calculations stand for not more +# than 1% of total time, so comparison is *rather* fair. +# +# (**) Results were collected on Westmere, which is considered to +# be equivalent to Nehalem for this code. +# +# As for key schedule conversion subroutine. Interface to OpenSSL +# relies on per-invocation on-the-fly conversion. This naturally +# has impact on performance, especially for short inputs. Conversion +# time in CPU cycles and its ratio to CPU cycles spent in 8x block +# function is: +# +# conversion conversion/8x block +# Core 2 240 0.22 +# Nehalem 180 0.20 +# Atom 430 0.20 +# +# The ratio values mean that 128-byte blocks will be processed +# 16-18% slower, 256-byte blocks - 9-10%, 384-byte blocks - 6-7%, +# etc. Then keep in mind that input sizes not divisible by 128 are +# *effectively* slower, especially shortest ones, e.g. consecutive +# 144-byte blocks are processed 44% slower than one would expect, +# 272 - 29%, 400 - 22%, etc. Yet, despite all these "shortcomings" +# it's still faster than ["hyper-threading-safe" code path in] +# aes-x86_64.pl on all lengths above 64 bytes... +# +# October 2011. +# +# Add decryption procedure. Performance in CPU cycles spent to decrypt +# one byte out of 4096-byte buffer with 128-bit key is: +# +# Core 2 9.98 +# Nehalem 7.80 +# Atom 17.9 +# Silvermont 14.0 +# +# November 2011. +# +# Add bsaes_xts_[en|de]crypt. Less-than-80-bytes-block performance is +# suboptimal, but XTS is meant to be used with larger blocks... +# +# + +$flavour = shift; +$output = shift; +if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } + +$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or +die "can't locate x86_64-xlate.pl"; + +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; + +my ($inp,$out,$len,$key,$ivp)=("%rdi","%rsi","%rdx","%rcx"); +my @XMM=map("%xmm$_",(15,0..14)); # best on Atom, +10% over (0..15) +my $ecb=0; # suppress unreferenced ECB subroutines, spare some space... + +{ +my ($key,$rounds,$const)=("%rax","%r10d","%r11"); + +sub Sbox { +# input in lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb +# output in lsb > [b0, b1, b4, b6, b3, b7, b2, b5] < msb +my @b=@_[0..7]; +my @t=@_[8..11]; +my @s=@_[12..15]; + &InBasisChange (@b); + &Inv_GF256 (@b[6,5,0,3,7,1,4,2],@t,@s); + &OutBasisChange (@b[7,1,4,2,6,5,0,3]); +} + +sub InBasisChange { +# input in lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb +# output in lsb > [b6, b5, b0, b3, b7, b1, b4, b2] < msb +my @b=@_[0..7]; +$code.=<<___; + pxor @b[6], @b[5] + pxor @b[1], @b[2] + pxor @b[0], @b[3] + pxor @b[2], @b[6] + pxor @b[0], @b[5] + + pxor @b[3], @b[6] + pxor @b[7], @b[3] + pxor @b[5], @b[7] + pxor @b[4], @b[3] + pxor @b[5], @b[4] + pxor @b[1], @b[3] + + pxor @b[7], @b[2] + pxor @b[5], @b[1] +___ +} + +sub OutBasisChange { +# input in lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb +# output in lsb > [b6, b1, b2, b4, b7, b0, b3, b5] < msb +my @b=@_[0..7]; +$code.=<<___; + pxor @b[6], @b[0] + pxor @b[4], @b[1] + pxor @b[0], @b[2] + pxor @b[6], @b[4] + pxor @b[1], @b[6] + + pxor @b[5], @b[1] + pxor @b[3], @b[5] + pxor @b[7], @b[3] + pxor @b[5], @b[7] + pxor @b[5], @b[2] + + pxor @b[7], @b[4] +___ +} + +sub InvSbox { +# input in lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb +# output in lsb > [b0, b1, b6, b4, b2, b7, b3, b5] < msb +my @b=@_[0..7]; +my @t=@_[8..11]; +my @s=@_[12..15]; + &InvInBasisChange (@b); + &Inv_GF256 (@b[5,1,2,6,3,7,0,4],@t,@s); + &InvOutBasisChange (@b[3,7,0,4,5,1,2,6]); +} + +sub InvInBasisChange { # OutBasisChange in reverse +my @b=@_[5,1,2,6,3,7,0,4]; +$code.=<<___ + pxor @b[7], @b[4] + + pxor @b[5], @b[7] + pxor @b[5], @b[2] + pxor @b[7], @b[3] + pxor @b[3], @b[5] + pxor @b[5], @b[1] + + pxor @b[1], @b[6] + pxor @b[0], @b[2] + pxor @b[6], @b[4] + pxor @b[6], @b[0] + pxor @b[4], @b[1] +___ +} + +sub InvOutBasisChange { # InBasisChange in reverse +my @b=@_[2,5,7,3,6,1,0,4]; +$code.=<<___; + pxor @b[5], @b[1] + pxor @b[7], @b[2] + + pxor @b[1], @b[3] + pxor @b[5], @b[4] + pxor @b[5], @b[7] + pxor @b[4], @b[3] + pxor @b[0], @b[5] + pxor @b[7], @b[3] + pxor @b[2], @b[6] + pxor @b[1], @b[2] + pxor @b[3], @b[6] + + pxor @b[0], @b[3] + pxor @b[6], @b[5] +___ +} + +sub Mul_GF4 { +#;************************************************************* +#;* Mul_GF4: Input x0-x1,y0-y1 Output x0-x1 Temp t0 (8) * +#;************************************************************* +my ($x0,$x1,$y0,$y1,$t0)=@_; +$code.=<<___; + movdqa $y0, $t0 + pxor $y1, $t0 + pand $x0, $t0 + pxor $x1, $x0 + pand $y0, $x1 + pand $y1, $x0 + pxor $x1, $x0 + pxor $t0, $x1 +___ +} + +sub Mul_GF4_N { # not used, see next subroutine +# multiply and scale by N +my ($x0,$x1,$y0,$y1,$t0)=@_; +$code.=<<___; + movdqa $y0, $t0 + pxor $y1, $t0 + pand $x0, $t0 + pxor $x1, $x0 + pand $y0, $x1 + pand $y1, $x0 + pxor $x0, $x1 + pxor $t0, $x0 +___ +} + +sub Mul_GF4_N_GF4 { +# interleaved Mul_GF4_N and Mul_GF4 +my ($x0,$x1,$y0,$y1,$t0, + $x2,$x3,$y2,$y3,$t1)=@_; +$code.=<<___; + movdqa $y0, $t0 + movdqa $y2, $t1 + pxor $y1, $t0 + pxor $y3, $t1 + pand $x0, $t0 + pand $x2, $t1 + pxor $x1, $x0 + pxor $x3, $x2 + pand $y0, $x1 + pand $y2, $x3 + pand $y1, $x0 + pand $y3, $x2 + pxor $x0, $x1 + pxor $x3, $x2 + pxor $t0, $x0 + pxor $t1, $x3 +___ +} +sub Mul_GF16_2 { +my @x=@_[0..7]; +my @y=@_[8..11]; +my @t=@_[12..15]; +$code.=<<___; + movdqa @x[0], @t[0] + movdqa @x[1], @t[1] +___ + &Mul_GF4 (@x[0], @x[1], @y[0], @y[1], @t[2]); +$code.=<<___; + pxor @x[2], @t[0] + pxor @x[3], @t[1] + pxor @y[2], @y[0] + pxor @y[3], @y[1] +___ + Mul_GF4_N_GF4 (@t[0], @t[1], @y[0], @y[1], @t[3], + @x[2], @x[3], @y[2], @y[3], @t[2]); +$code.=<<___; + pxor @t[0], @x[0] + pxor @t[0], @x[2] + pxor @t[1], @x[1] + pxor @t[1], @x[3] + + movdqa @x[4], @t[0] + movdqa @x[5], @t[1] + pxor @x[6], @t[0] + pxor @x[7], @t[1] +___ + &Mul_GF4_N_GF4 (@t[0], @t[1], @y[0], @y[1], @t[3], + @x[6], @x[7], @y[2], @y[3], @t[2]); +$code.=<<___; + pxor @y[2], @y[0] + pxor @y[3], @y[1] +___ + &Mul_GF4 (@x[4], @x[5], @y[0], @y[1], @t[3]); +$code.=<<___; + pxor @t[0], @x[4] + pxor @t[0], @x[6] + pxor @t[1], @x[5] + pxor @t[1], @x[7] +___ +} +sub Inv_GF256 { +#;******************************************************************** +#;* Inv_GF256: Input x0-x7 Output x0-x7 Temp t0-t3,s0-s3 (144) * +#;******************************************************************** +my @x=@_[0..7]; +my @t=@_[8..11]; +my @s=@_[12..15]; +# direct optimizations from hardware +$code.=<<___; + movdqa @x[4], @t[3] + movdqa @x[5], @t[2] + movdqa @x[1], @t[1] + movdqa @x[7], @s[1] + movdqa @x[0], @s[0] + + pxor @x[6], @t[3] + pxor @x[7], @t[2] + pxor @x[3], @t[1] + movdqa @t[3], @s[2] + pxor @x[6], @s[1] + movdqa @t[2], @t[0] + pxor @x[2], @s[0] + movdqa @t[3], @s[3] + + por @t[1], @t[2] + por @s[0], @t[3] + pxor @t[0], @s[3] + pand @s[0], @s[2] + pxor @t[1], @s[0] + pand @t[1], @t[0] + pand @s[0], @s[3] + movdqa @x[3], @s[0] + pxor @x[2], @s[0] + pand @s[0], @s[1] + pxor @s[1], @t[3] + pxor @s[1], @t[2] + movdqa @x[4], @s[1] + movdqa @x[1], @s[0] + pxor @x[5], @s[1] + pxor @x[0], @s[0] + movdqa @s[1], @t[1] + pand @s[0], @s[1] + por @s[0], @t[1] + pxor @s[1], @t[0] + pxor @s[3], @t[3] + pxor @s[2], @t[2] + pxor @s[3], @t[1] + movdqa @x[7], @s[0] + pxor @s[2], @t[0] + movdqa @x[6], @s[1] + pxor @s[2], @t[1] + movdqa @x[5], @s[2] + pand @x[3], @s[0] + movdqa @x[4], @s[3] + pand @x[2], @s[1] + pand @x[1], @s[2] + por @x[0], @s[3] + pxor @s[0], @t[3] + pxor @s[1], @t[2] + pxor @s[2], @t[1] + pxor @s[3], @t[0] + + #Inv_GF16 \t0, \t1, \t2, \t3, \s0, \s1, \s2, \s3 + + # new smaller inversion + + movdqa @t[3], @s[0] + pand @t[1], @t[3] + pxor @t[2], @s[0] + + movdqa @t[0], @s[2] + movdqa @s[0], @s[3] + pxor @t[3], @s[2] + pand @s[2], @s[3] + + movdqa @t[1], @s[1] + pxor @t[2], @s[3] + pxor @t[0], @s[1] + + pxor @t[2], @t[3] + + pand @t[3], @s[1] + + movdqa @s[2], @t[2] + pxor @t[0], @s[1] + + pxor @s[1], @t[2] + pxor @s[1], @t[1] + + pand @t[0], @t[2] + + pxor @t[2], @s[2] + pxor @t[2], @t[1] + + pand @s[3], @s[2] + + pxor @s[0], @s[2] +___ +# output in s3, s2, s1, t1 + +# Mul_GF16_2 \x0, \x1, \x2, \x3, \x4, \x5, \x6, \x7, \t2, \t3, \t0, \t1, \s0, \s1, \s2, \s3 + +# Mul_GF16_2 \x0, \x1, \x2, \x3, \x4, \x5, \x6, \x7, \s3, \s2, \s1, \t1, \s0, \t0, \t2, \t3 + &Mul_GF16_2(@x,@s[3,2,1],@t[1],@s[0],@t[0,2,3]); + +### output msb > [x3,x2,x1,x0,x7,x6,x5,x4] < lsb +} + +# AES linear components + +sub ShiftRows { +my @x=@_[0..7]; +my $mask=pop; +$code.=<<___; + pxor 0x00($key),@x[0] + pxor 0x10($key),@x[1] + pxor 0x20($key),@x[2] + pxor 0x30($key),@x[3] + pshufb $mask,@x[0] + pshufb $mask,@x[1] + pxor 0x40($key),@x[4] + pxor 0x50($key),@x[5] + pshufb $mask,@x[2] + pshufb $mask,@x[3] + pxor 0x60($key),@x[6] + pxor 0x70($key),@x[7] + pshufb $mask,@x[4] + pshufb $mask,@x[5] + pshufb $mask,@x[6] + pshufb $mask,@x[7] + lea 0x80($key),$key +___ +} + +sub MixColumns { +# modified to emit output in order suitable for feeding back to aesenc[last] +my @x=@_[0..7]; +my @t=@_[8..15]; +my $inv=@_[16]; # optional +$code.=<<___; + pshufd \$0x93, @x[0], @t[0] # x0 <<< 32 + pshufd \$0x93, @x[1], @t[1] + pxor @t[0], @x[0] # x0 ^ (x0 <<< 32) + pshufd \$0x93, @x[2], @t[2] + pxor @t[1], @x[1] + pshufd \$0x93, @x[3], @t[3] + pxor @t[2], @x[2] + pshufd \$0x93, @x[4], @t[4] + pxor @t[3], @x[3] + pshufd \$0x93, @x[5], @t[5] + pxor @t[4], @x[4] + pshufd \$0x93, @x[6], @t[6] + pxor @t[5], @x[5] + pshufd \$0x93, @x[7], @t[7] + pxor @t[6], @x[6] + pxor @t[7], @x[7] + + pxor @x[0], @t[1] + pxor @x[7], @t[0] + pxor @x[7], @t[1] + pshufd \$0x4E, @x[0], @x[0] # (x0 ^ (x0 <<< 32)) <<< 64) + pxor @x[1], @t[2] + pshufd \$0x4E, @x[1], @x[1] + pxor @x[4], @t[5] + pxor @t[0], @x[0] + pxor @x[5], @t[6] + pxor @t[1], @x[1] + pxor @x[3], @t[4] + pshufd \$0x4E, @x[4], @t[0] + pxor @x[6], @t[7] + pshufd \$0x4E, @x[5], @t[1] + pxor @x[2], @t[3] + pshufd \$0x4E, @x[3], @x[4] + pxor @x[7], @t[3] + pshufd \$0x4E, @x[7], @x[5] + pxor @x[7], @t[4] + pshufd \$0x4E, @x[6], @x[3] + pxor @t[4], @t[0] + pshufd \$0x4E, @x[2], @x[6] + pxor @t[5], @t[1] +___ +$code.=<<___ if (!$inv); + pxor @t[3], @x[4] + pxor @t[7], @x[5] + pxor @t[6], @x[3] + movdqa @t[0], @x[2] + pxor @t[2], @x[6] + movdqa @t[1], @x[7] +___ +$code.=<<___ if ($inv); + pxor @x[4], @t[3] + pxor @t[7], @x[5] + pxor @x[3], @t[6] + movdqa @t[0], @x[3] + pxor @t[2], @x[6] + movdqa @t[6], @x[2] + movdqa @t[1], @x[7] + movdqa @x[6], @x[4] + movdqa @t[3], @x[6] +___ +} + +sub InvMixColumns_orig { +my @x=@_[0..7]; +my @t=@_[8..15]; + +$code.=<<___; + # multiplication by 0x0e + pshufd \$0x93, @x[7], @t[7] + movdqa @x[2], @t[2] + pxor @x[5], @x[7] # 7 5 + pxor @x[5], @x[2] # 2 5 + pshufd \$0x93, @x[0], @t[0] + movdqa @x[5], @t[5] + pxor @x[0], @x[5] # 5 0 [1] + pxor @x[1], @x[0] # 0 1 + pshufd \$0x93, @x[1], @t[1] + pxor @x[2], @x[1] # 1 25 + pxor @x[6], @x[0] # 01 6 [2] + pxor @x[3], @x[1] # 125 3 [4] + pshufd \$0x93, @x[3], @t[3] + pxor @x[0], @x[2] # 25 016 [3] + pxor @x[7], @x[3] # 3 75 + pxor @x[6], @x[7] # 75 6 [0] + pshufd \$0x93, @x[6], @t[6] + movdqa @x[4], @t[4] + pxor @x[4], @x[6] # 6 4 + pxor @x[3], @x[4] # 4 375 [6] + pxor @x[7], @x[3] # 375 756=36 + pxor @t[5], @x[6] # 64 5 [7] + pxor @t[2], @x[3] # 36 2 + pxor @t[4], @x[3] # 362 4 [5] + pshufd \$0x93, @t[5], @t[5] +___ + my @y = @x[7,5,0,2,1,3,4,6]; +$code.=<<___; + # multiplication by 0x0b + pxor @y[0], @y[1] + pxor @t[0], @y[0] + pxor @t[1], @y[1] + pshufd \$0x93, @t[2], @t[2] + pxor @t[5], @y[0] + pxor @t[6], @y[1] + pxor @t[7], @y[0] + pshufd \$0x93, @t[4], @t[4] + pxor @t[6], @t[7] # clobber t[7] + pxor @y[0], @y[1] + + pxor @t[0], @y[3] + pshufd \$0x93, @t[0], @t[0] + pxor @t[1], @y[2] + pxor @t[1], @y[4] + pxor @t[2], @y[2] + pshufd \$0x93, @t[1], @t[1] + pxor @t[2], @y[3] + pxor @t[2], @y[5] + pxor @t[7], @y[2] + pshufd \$0x93, @t[2], @t[2] + pxor @t[3], @y[3] + pxor @t[3], @y[6] + pxor @t[3], @y[4] + pshufd \$0x93, @t[3], @t[3] + pxor @t[4], @y[7] + pxor @t[4], @y[5] + pxor @t[7], @y[7] + pxor @t[5], @y[3] + pxor @t[4], @y[4] + pxor @t[5], @t[7] # clobber t[7] even more + + pxor @t[7], @y[5] + pshufd \$0x93, @t[4], @t[4] + pxor @t[7], @y[6] + pxor @t[7], @y[4] + + pxor @t[5], @t[7] + pshufd \$0x93, @t[5], @t[5] + pxor @t[6], @t[7] # restore t[7] + + # multiplication by 0x0d + pxor @y[7], @y[4] + pxor @t[4], @y[7] + pshufd \$0x93, @t[6], @t[6] + pxor @t[0], @y[2] + pxor @t[5], @y[7] + pxor @t[2], @y[2] + pshufd \$0x93, @t[7], @t[7] + + pxor @y[1], @y[3] + pxor @t[1], @y[1] + pxor @t[0], @y[0] + pxor @t[0], @y[3] + pxor @t[5], @y[1] + pxor @t[5], @y[0] + pxor @t[7], @y[1] + pshufd \$0x93, @t[0], @t[0] + pxor @t[6], @y[0] + pxor @y[1], @y[3] + pxor @t[1], @y[4] + pshufd \$0x93, @t[1], @t[1] + + pxor @t[7], @y[7] + pxor @t[2], @y[4] + pxor @t[2], @y[5] + pshufd \$0x93, @t[2], @t[2] + pxor @t[6], @y[2] + pxor @t[3], @t[6] # clobber t[6] + pxor @y[7], @y[4] + pxor @t[6], @y[3] + + pxor @t[6], @y[6] + pxor @t[5], @y[5] + pxor @t[4], @y[6] + pshufd \$0x93, @t[4], @t[4] + pxor @t[6], @y[5] + pxor @t[7], @y[6] + pxor @t[3], @t[6] # restore t[6] + + pshufd \$0x93, @t[5], @t[5] + pshufd \$0x93, @t[6], @t[6] + pshufd \$0x93, @t[7], @t[7] + pshufd \$0x93, @t[3], @t[3] + + # multiplication by 0x09 + pxor @y[1], @y[4] + pxor @y[1], @t[1] # t[1]=y[1] + pxor @t[5], @t[0] # clobber t[0] + pxor @t[5], @t[1] + pxor @t[0], @y[3] + pxor @y[0], @t[0] # t[0]=y[0] + pxor @t[6], @t[1] + pxor @t[7], @t[6] # clobber t[6] + pxor @t[1], @y[4] + pxor @t[4], @y[7] + pxor @y[4], @t[4] # t[4]=y[4] + pxor @t[3], @y[6] + pxor @y[3], @t[3] # t[3]=y[3] + pxor @t[2], @y[5] + pxor @y[2], @t[2] # t[2]=y[2] + pxor @t[7], @t[3] + pxor @y[5], @t[5] # t[5]=y[5] + pxor @t[6], @t[2] + pxor @t[6], @t[5] + pxor @y[6], @t[6] # t[6]=y[6] + pxor @y[7], @t[7] # t[7]=y[7] + + movdqa @t[0],@XMM[0] + movdqa @t[1],@XMM[1] + movdqa @t[2],@XMM[2] + movdqa @t[3],@XMM[3] + movdqa @t[4],@XMM[4] + movdqa @t[5],@XMM[5] + movdqa @t[6],@XMM[6] + movdqa @t[7],@XMM[7] +___ +} + +sub InvMixColumns { +my @x=@_[0..7]; +my @t=@_[8..15]; + +# Thanks to Jussi Kivilinna for providing pointer to +# +# | 0e 0b 0d 09 | | 02 03 01 01 | | 05 00 04 00 | +# | 09 0e 0b 0d | = | 01 02 03 01 | x | 00 05 00 04 | +# | 0d 09 0e 0b | | 01 01 02 03 | | 04 00 05 00 | +# | 0b 0d 09 0e | | 03 01 01 02 | | 00 04 00 05 | + +$code.=<<___; + # multiplication by 0x05-0x00-0x04-0x00 + pshufd \$0x4E, @x[0], @t[0] + pshufd \$0x4E, @x[6], @t[6] + pxor @x[0], @t[0] + pshufd \$0x4E, @x[7], @t[7] + pxor @x[6], @t[6] + pshufd \$0x4E, @x[1], @t[1] + pxor @x[7], @t[7] + pshufd \$0x4E, @x[2], @t[2] + pxor @x[1], @t[1] + pshufd \$0x4E, @x[3], @t[3] + pxor @x[2], @t[2] + pxor @t[6], @x[0] + pxor @t[6], @x[1] + pshufd \$0x4E, @x[4], @t[4] + pxor @x[3], @t[3] + pxor @t[0], @x[2] + pxor @t[1], @x[3] + pshufd \$0x4E, @x[5], @t[5] + pxor @x[4], @t[4] + pxor @t[7], @x[1] + pxor @t[2], @x[4] + pxor @x[5], @t[5] + + pxor @t[7], @x[2] + pxor @t[6], @x[3] + pxor @t[6], @x[4] + pxor @t[3], @x[5] + pxor @t[4], @x[6] + pxor @t[7], @x[4] + pxor @t[7], @x[5] + pxor @t[5], @x[7] +___ + &MixColumns (@x,@t,1); # flipped 2<->3 and 4<->6 +} + +sub aesenc { # not used +my @b=@_[0..7]; +my @t=@_[8..15]; +$code.=<<___; + movdqa 0x30($const),@t[0] # .LSR +___ + &ShiftRows (@b,@t[0]); + &Sbox (@b,@t); + &MixColumns (@b[0,1,4,6,3,7,2,5],@t); +} + +sub aesenclast { # not used +my @b=@_[0..7]; +my @t=@_[8..15]; +$code.=<<___; + movdqa 0x40($const),@t[0] # .LSRM0 +___ + &ShiftRows (@b,@t[0]); + &Sbox (@b,@t); +$code.=<<___ + pxor 0x00($key),@b[0] + pxor 0x10($key),@b[1] + pxor 0x20($key),@b[4] + pxor 0x30($key),@b[6] + pxor 0x40($key),@b[3] + pxor 0x50($key),@b[7] + pxor 0x60($key),@b[2] + pxor 0x70($key),@b[5] +___ +} + +sub swapmove { +my ($a,$b,$n,$mask,$t)=@_; +$code.=<<___; + movdqa $b,$t + psrlq \$$n,$b + pxor $a,$b + pand $mask,$b + pxor $b,$a + psllq \$$n,$b + pxor $t,$b +___ +} +sub swapmove2x { +my ($a0,$b0,$a1,$b1,$n,$mask,$t0,$t1)=@_; +$code.=<<___; + movdqa $b0,$t0 + psrlq \$$n,$b0 + movdqa $b1,$t1 + psrlq \$$n,$b1 + pxor $a0,$b0 + pxor $a1,$b1 + pand $mask,$b0 + pand $mask,$b1 + pxor $b0,$a0 + psllq \$$n,$b0 + pxor $b1,$a1 + psllq \$$n,$b1 + pxor $t0,$b0 + pxor $t1,$b1 +___ +} + +sub bitslice { +my @x=reverse(@_[0..7]); +my ($t0,$t1,$t2,$t3)=@_[8..11]; +$code.=<<___; + movdqa 0x00($const),$t0 # .LBS0 + movdqa 0x10($const),$t1 # .LBS1 +___ + &swapmove2x(@x[0,1,2,3],1,$t0,$t2,$t3); + &swapmove2x(@x[4,5,6,7],1,$t0,$t2,$t3); +$code.=<<___; + movdqa 0x20($const),$t0 # .LBS2 +___ + &swapmove2x(@x[0,2,1,3],2,$t1,$t2,$t3); + &swapmove2x(@x[4,6,5,7],2,$t1,$t2,$t3); + + &swapmove2x(@x[0,4,1,5],4,$t0,$t2,$t3); + &swapmove2x(@x[2,6,3,7],4,$t0,$t2,$t3); +} + +$code.=<<___; +.text + +.extern asm_AES_encrypt +.extern asm_AES_decrypt + +.type _bsaes_encrypt8,\@abi-omnipotent +.align 64 +_bsaes_encrypt8: + lea .LBS0(%rip), $const # constants table + + movdqa ($key), @XMM[9] # round 0 key + lea 0x10($key), $key + movdqa 0x50($const), @XMM[8] # .LM0SR + pxor @XMM[9], @XMM[0] # xor with round0 key + pxor @XMM[9], @XMM[1] + pxor @XMM[9], @XMM[2] + pxor @XMM[9], @XMM[3] + pshufb @XMM[8], @XMM[0] + pshufb @XMM[8], @XMM[1] + pxor @XMM[9], @XMM[4] + pxor @XMM[9], @XMM[5] + pshufb @XMM[8], @XMM[2] + pshufb @XMM[8], @XMM[3] + pxor @XMM[9], @XMM[6] + pxor @XMM[9], @XMM[7] + pshufb @XMM[8], @XMM[4] + pshufb @XMM[8], @XMM[5] + pshufb @XMM[8], @XMM[6] + pshufb @XMM[8], @XMM[7] +_bsaes_encrypt8_bitslice: +___ + &bitslice (@XMM[0..7, 8..11]); +$code.=<<___; + dec $rounds + jmp .Lenc_sbox +.align 16 +.Lenc_loop: +___ + &ShiftRows (@XMM[0..7, 8]); +$code.=".Lenc_sbox:\n"; + &Sbox (@XMM[0..7, 8..15]); +$code.=<<___; + dec $rounds + jl .Lenc_done +___ + &MixColumns (@XMM[0,1,4,6,3,7,2,5, 8..15]); +$code.=<<___; + movdqa 0x30($const), @XMM[8] # .LSR + jnz .Lenc_loop + movdqa 0x40($const), @XMM[8] # .LSRM0 + jmp .Lenc_loop +.align 16 +.Lenc_done: +___ + # output in lsb > [t0, t1, t4, t6, t3, t7, t2, t5] < msb + &bitslice (@XMM[0,1,4,6,3,7,2,5, 8..11]); +$code.=<<___; + movdqa ($key), @XMM[8] # last round key + pxor @XMM[8], @XMM[4] + pxor @XMM[8], @XMM[6] + pxor @XMM[8], @XMM[3] + pxor @XMM[8], @XMM[7] + pxor @XMM[8], @XMM[2] + pxor @XMM[8], @XMM[5] + pxor @XMM[8], @XMM[0] + pxor @XMM[8], @XMM[1] + ret +.size _bsaes_encrypt8,.-_bsaes_encrypt8 + +.type _bsaes_decrypt8,\@abi-omnipotent +.align 64 +_bsaes_decrypt8: + lea .LBS0(%rip), $const # constants table + + movdqa ($key), @XMM[9] # round 0 key + lea 0x10($key), $key + movdqa -0x30($const), @XMM[8] # .LM0ISR + pxor @XMM[9], @XMM[0] # xor with round0 key + pxor @XMM[9], @XMM[1] + pxor @XMM[9], @XMM[2] + pxor @XMM[9], @XMM[3] + pshufb @XMM[8], @XMM[0] + pshufb @XMM[8], @XMM[1] + pxor @XMM[9], @XMM[4] + pxor @XMM[9], @XMM[5] + pshufb @XMM[8], @XMM[2] + pshufb @XMM[8], @XMM[3] + pxor @XMM[9], @XMM[6] + pxor @XMM[9], @XMM[7] + pshufb @XMM[8], @XMM[4] + pshufb @XMM[8], @XMM[5] + pshufb @XMM[8], @XMM[6] + pshufb @XMM[8], @XMM[7] +___ + &bitslice (@XMM[0..7, 8..11]); +$code.=<<___; + dec $rounds + jmp .Ldec_sbox +.align 16 +.Ldec_loop: +___ + &ShiftRows (@XMM[0..7, 8]); +$code.=".Ldec_sbox:\n"; + &InvSbox (@XMM[0..7, 8..15]); +$code.=<<___; + dec $rounds + jl .Ldec_done +___ + &InvMixColumns (@XMM[0,1,6,4,2,7,3,5, 8..15]); +$code.=<<___; + movdqa -0x10($const), @XMM[8] # .LISR + jnz .Ldec_loop + movdqa -0x20($const), @XMM[8] # .LISRM0 + jmp .Ldec_loop +.align 16 +.Ldec_done: +___ + &bitslice (@XMM[0,1,6,4,2,7,3,5, 8..11]); +$code.=<<___; + movdqa ($key), @XMM[8] # last round key + pxor @XMM[8], @XMM[6] + pxor @XMM[8], @XMM[4] + pxor @XMM[8], @XMM[2] + pxor @XMM[8], @XMM[7] + pxor @XMM[8], @XMM[3] + pxor @XMM[8], @XMM[5] + pxor @XMM[8], @XMM[0] + pxor @XMM[8], @XMM[1] + ret +.size _bsaes_decrypt8,.-_bsaes_decrypt8 +___ +} +{ +my ($out,$inp,$rounds,$const)=("%rax","%rcx","%r10d","%r11"); + +sub bitslice_key { +my @x=reverse(@_[0..7]); +my ($bs0,$bs1,$bs2,$t2,$t3)=@_[8..12]; + + &swapmove (@x[0,1],1,$bs0,$t2,$t3); +$code.=<<___; + #&swapmove(@x[2,3],1,$t0,$t2,$t3); + movdqa @x[0], @x[2] + movdqa @x[1], @x[3] +___ + #&swapmove2x(@x[4,5,6,7],1,$t0,$t2,$t3); + + &swapmove2x (@x[0,2,1,3],2,$bs1,$t2,$t3); +$code.=<<___; + #&swapmove2x(@x[4,6,5,7],2,$t1,$t2,$t3); + movdqa @x[0], @x[4] + movdqa @x[2], @x[6] + movdqa @x[1], @x[5] + movdqa @x[3], @x[7] +___ + &swapmove2x (@x[0,4,1,5],4,$bs2,$t2,$t3); + &swapmove2x (@x[2,6,3,7],4,$bs2,$t2,$t3); +} + +$code.=<<___; +.type _bsaes_key_convert,\@abi-omnipotent +.align 16 +_bsaes_key_convert: + lea .Lmasks(%rip), $const + movdqu ($inp), %xmm7 # load round 0 key + lea 0x10($inp), $inp + movdqa 0x00($const), %xmm0 # 0x01... + movdqa 0x10($const), %xmm1 # 0x02... + movdqa 0x20($const), %xmm2 # 0x04... + movdqa 0x30($const), %xmm3 # 0x08... + movdqa 0x40($const), %xmm4 # .LM0 + pcmpeqd %xmm5, %xmm5 # .LNOT + + movdqu ($inp), %xmm6 # load round 1 key + movdqa %xmm7, ($out) # save round 0 key + lea 0x10($out), $out + dec $rounds + jmp .Lkey_loop +.align 16 +.Lkey_loop: + pshufb %xmm4, %xmm6 # .LM0 + + movdqa %xmm0, %xmm8 + movdqa %xmm1, %xmm9 + + pand %xmm6, %xmm8 + pand %xmm6, %xmm9 + movdqa %xmm2, %xmm10 + pcmpeqb %xmm0, %xmm8 + psllq \$4, %xmm0 # 0x10... + movdqa %xmm3, %xmm11 + pcmpeqb %xmm1, %xmm9 + psllq \$4, %xmm1 # 0x20... + + pand %xmm6, %xmm10 + pand %xmm6, %xmm11 + movdqa %xmm0, %xmm12 + pcmpeqb %xmm2, %xmm10 + psllq \$4, %xmm2 # 0x40... + movdqa %xmm1, %xmm13 + pcmpeqb %xmm3, %xmm11 + psllq \$4, %xmm3 # 0x80... + + movdqa %xmm2, %xmm14 + movdqa %xmm3, %xmm15 + pxor %xmm5, %xmm8 # "pnot" + pxor %xmm5, %xmm9 + + pand %xmm6, %xmm12 + pand %xmm6, %xmm13 + movdqa %xmm8, 0x00($out) # write bit-sliced round key + pcmpeqb %xmm0, %xmm12 + psrlq \$4, %xmm0 # 0x01... + movdqa %xmm9, 0x10($out) + pcmpeqb %xmm1, %xmm13 + psrlq \$4, %xmm1 # 0x02... + lea 0x10($inp), $inp + + pand %xmm6, %xmm14 + pand %xmm6, %xmm15 + movdqa %xmm10, 0x20($out) + pcmpeqb %xmm2, %xmm14 + psrlq \$4, %xmm2 # 0x04... + movdqa %xmm11, 0x30($out) + pcmpeqb %xmm3, %xmm15 + psrlq \$4, %xmm3 # 0x08... + movdqu ($inp), %xmm6 # load next round key + + pxor %xmm5, %xmm13 # "pnot" + pxor %xmm5, %xmm14 + movdqa %xmm12, 0x40($out) + movdqa %xmm13, 0x50($out) + movdqa %xmm14, 0x60($out) + movdqa %xmm15, 0x70($out) + lea 0x80($out),$out + dec $rounds + jnz .Lkey_loop + + movdqa 0x50($const), %xmm7 # .L63 + #movdqa %xmm6, ($out) # don't save last round key + ret +.size _bsaes_key_convert,.-_bsaes_key_convert +___ +} + +if (0 && !$win64) { # following four functions are unsupported interface + # used for benchmarking... +$code.=<<___; +.globl bsaes_enc_key_convert +.type bsaes_enc_key_convert,\@function,2 +.align 16 +bsaes_enc_key_convert: + mov 240($inp),%r10d # pass rounds + mov $inp,%rcx # pass key + mov $out,%rax # pass key schedule + call _bsaes_key_convert + pxor %xmm6,%xmm7 # fix up last round key + movdqa %xmm7,(%rax) # save last round key + ret +.size bsaes_enc_key_convert,.-bsaes_enc_key_convert + +.globl bsaes_encrypt_128 +.type bsaes_encrypt_128,\@function,4 +.align 16 +bsaes_encrypt_128: +.Lenc128_loop: + movdqu 0x00($inp), @XMM[0] # load input + movdqu 0x10($inp), @XMM[1] + movdqu 0x20($inp), @XMM[2] + movdqu 0x30($inp), @XMM[3] + movdqu 0x40($inp), @XMM[4] + movdqu 0x50($inp), @XMM[5] + movdqu 0x60($inp), @XMM[6] + movdqu 0x70($inp), @XMM[7] + mov $key, %rax # pass the $key + lea 0x80($inp), $inp + mov \$10,%r10d + + call _bsaes_encrypt8 + + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[4], 0x20($out) + movdqu @XMM[6], 0x30($out) + movdqu @XMM[3], 0x40($out) + movdqu @XMM[7], 0x50($out) + movdqu @XMM[2], 0x60($out) + movdqu @XMM[5], 0x70($out) + lea 0x80($out), $out + sub \$0x80,$len + ja .Lenc128_loop + ret +.size bsaes_encrypt_128,.-bsaes_encrypt_128 + +.globl bsaes_dec_key_convert +.type bsaes_dec_key_convert,\@function,2 +.align 16 +bsaes_dec_key_convert: + mov 240($inp),%r10d # pass rounds + mov $inp,%rcx # pass key + mov $out,%rax # pass key schedule + call _bsaes_key_convert + pxor ($out),%xmm7 # fix up round 0 key + movdqa %xmm6,(%rax) # save last round key + movdqa %xmm7,($out) + ret +.size bsaes_dec_key_convert,.-bsaes_dec_key_convert + +.globl bsaes_decrypt_128 +.type bsaes_decrypt_128,\@function,4 +.align 16 +bsaes_decrypt_128: +.Ldec128_loop: + movdqu 0x00($inp), @XMM[0] # load input + movdqu 0x10($inp), @XMM[1] + movdqu 0x20($inp), @XMM[2] + movdqu 0x30($inp), @XMM[3] + movdqu 0x40($inp), @XMM[4] + movdqu 0x50($inp), @XMM[5] + movdqu 0x60($inp), @XMM[6] + movdqu 0x70($inp), @XMM[7] + mov $key, %rax # pass the $key + lea 0x80($inp), $inp + mov \$10,%r10d + + call _bsaes_decrypt8 + + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[6], 0x20($out) + movdqu @XMM[4], 0x30($out) + movdqu @XMM[2], 0x40($out) + movdqu @XMM[7], 0x50($out) + movdqu @XMM[3], 0x60($out) + movdqu @XMM[5], 0x70($out) + lea 0x80($out), $out + sub \$0x80,$len + ja .Ldec128_loop + ret +.size bsaes_decrypt_128,.-bsaes_decrypt_128 +___ +} +{ +###################################################################### +# +# OpenSSL interface +# +my ($arg1,$arg2,$arg3,$arg4,$arg5,$arg6)=$win64 ? ("%rcx","%rdx","%r8","%r9","%r10","%r11d") + : ("%rdi","%rsi","%rdx","%rcx","%r8","%r9d"); +my ($inp,$out,$len,$key)=("%r12","%r13","%r14","%r15"); + +if ($ecb) { +$code.=<<___; +.globl bsaes_ecb_encrypt_blocks +.type bsaes_ecb_encrypt_blocks,\@abi-omnipotent +.align 16 +bsaes_ecb_encrypt_blocks: + mov %rsp, %rax +.Lecb_enc_prologue: + push %rbp + push %rbx + push %r12 + push %r13 + push %r14 + push %r15 + lea -0x48(%rsp),%rsp +___ +$code.=<<___ if ($win64); + lea -0xa0(%rsp), %rsp + movaps %xmm6, 0x40(%rsp) + movaps %xmm7, 0x50(%rsp) + movaps %xmm8, 0x60(%rsp) + movaps %xmm9, 0x70(%rsp) + movaps %xmm10, 0x80(%rsp) + movaps %xmm11, 0x90(%rsp) + movaps %xmm12, 0xa0(%rsp) + movaps %xmm13, 0xb0(%rsp) + movaps %xmm14, 0xc0(%rsp) + movaps %xmm15, 0xd0(%rsp) +.Lecb_enc_body: +___ +$code.=<<___; + mov %rsp,%rbp # backup %rsp + mov 240($arg4),%eax # rounds + mov $arg1,$inp # backup arguments + mov $arg2,$out + mov $arg3,$len + mov $arg4,$key + cmp \$8,$arg3 + jb .Lecb_enc_short + + mov %eax,%ebx # backup rounds + shl \$7,%rax # 128 bytes per inner round key + sub \$`128-32`,%rax # size of bit-sliced key schedule + sub %rax,%rsp + mov %rsp,%rax # pass key schedule + mov $key,%rcx # pass key + mov %ebx,%r10d # pass rounds + call _bsaes_key_convert + pxor %xmm6,%xmm7 # fix up last round key + movdqa %xmm7,(%rax) # save last round key + + sub \$8,$len +.Lecb_enc_loop: + movdqu 0x00($inp), @XMM[0] # load input + movdqu 0x10($inp), @XMM[1] + movdqu 0x20($inp), @XMM[2] + movdqu 0x30($inp), @XMM[3] + movdqu 0x40($inp), @XMM[4] + movdqu 0x50($inp), @XMM[5] + mov %rsp, %rax # pass key schedule + movdqu 0x60($inp), @XMM[6] + mov %ebx,%r10d # pass rounds + movdqu 0x70($inp), @XMM[7] + lea 0x80($inp), $inp + + call _bsaes_encrypt8 + + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[4], 0x20($out) + movdqu @XMM[6], 0x30($out) + movdqu @XMM[3], 0x40($out) + movdqu @XMM[7], 0x50($out) + movdqu @XMM[2], 0x60($out) + movdqu @XMM[5], 0x70($out) + lea 0x80($out), $out + sub \$8,$len + jnc .Lecb_enc_loop + + add \$8,$len + jz .Lecb_enc_done + + movdqu 0x00($inp), @XMM[0] # load input + mov %rsp, %rax # pass key schedule + mov %ebx,%r10d # pass rounds + cmp \$2,$len + jb .Lecb_enc_one + movdqu 0x10($inp), @XMM[1] + je .Lecb_enc_two + movdqu 0x20($inp), @XMM[2] + cmp \$4,$len + jb .Lecb_enc_three + movdqu 0x30($inp), @XMM[3] + je .Lecb_enc_four + movdqu 0x40($inp), @XMM[4] + cmp \$6,$len + jb .Lecb_enc_five + movdqu 0x50($inp), @XMM[5] + je .Lecb_enc_six + movdqu 0x60($inp), @XMM[6] + call _bsaes_encrypt8 + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[4], 0x20($out) + movdqu @XMM[6], 0x30($out) + movdqu @XMM[3], 0x40($out) + movdqu @XMM[7], 0x50($out) + movdqu @XMM[2], 0x60($out) + jmp .Lecb_enc_done +.align 16 +.Lecb_enc_six: + call _bsaes_encrypt8 + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[4], 0x20($out) + movdqu @XMM[6], 0x30($out) + movdqu @XMM[3], 0x40($out) + movdqu @XMM[7], 0x50($out) + jmp .Lecb_enc_done +.align 16 +.Lecb_enc_five: + call _bsaes_encrypt8 + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[4], 0x20($out) + movdqu @XMM[6], 0x30($out) + movdqu @XMM[3], 0x40($out) + jmp .Lecb_enc_done +.align 16 +.Lecb_enc_four: + call _bsaes_encrypt8 + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[4], 0x20($out) + movdqu @XMM[6], 0x30($out) + jmp .Lecb_enc_done +.align 16 +.Lecb_enc_three: + call _bsaes_encrypt8 + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[4], 0x20($out) + jmp .Lecb_enc_done +.align 16 +.Lecb_enc_two: + call _bsaes_encrypt8 + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + jmp .Lecb_enc_done +.align 16 +.Lecb_enc_one: + call _bsaes_encrypt8 + movdqu @XMM[0], 0x00($out) # write output + jmp .Lecb_enc_done +.align 16 +.Lecb_enc_short: + lea ($inp), $arg1 + lea ($out), $arg2 + lea ($key), $arg3 + call asm_AES_encrypt + lea 16($inp), $inp + lea 16($out), $out + dec $len + jnz .Lecb_enc_short + +.Lecb_enc_done: + lea (%rsp),%rax + pxor %xmm0, %xmm0 +.Lecb_enc_bzero: # wipe key schedule [if any] + movdqa %xmm0, 0x00(%rax) + movdqa %xmm0, 0x10(%rax) + lea 0x20(%rax), %rax + cmp %rax, %rbp + jb .Lecb_enc_bzero + + lea (%rbp),%rsp # restore %rsp +___ +$code.=<<___ if ($win64); + movaps 0x40(%rbp), %xmm6 + movaps 0x50(%rbp), %xmm7 + movaps 0x60(%rbp), %xmm8 + movaps 0x70(%rbp), %xmm9 + movaps 0x80(%rbp), %xmm10 + movaps 0x90(%rbp), %xmm11 + movaps 0xa0(%rbp), %xmm12 + movaps 0xb0(%rbp), %xmm13 + movaps 0xc0(%rbp), %xmm14 + movaps 0xd0(%rbp), %xmm15 + lea 0xa0(%rbp), %rsp +___ +$code.=<<___; + mov 0x48(%rsp), %r15 + mov 0x50(%rsp), %r14 + mov 0x58(%rsp), %r13 + mov 0x60(%rsp), %r12 + mov 0x68(%rsp), %rbx + mov 0x70(%rsp), %rax + lea 0x78(%rsp), %rsp + mov %rax, %rbp +.Lecb_enc_epilogue: + ret +.size bsaes_ecb_encrypt_blocks,.-bsaes_ecb_encrypt_blocks + +.globl bsaes_ecb_decrypt_blocks +.type bsaes_ecb_decrypt_blocks,\@abi-omnipotent +.align 16 +bsaes_ecb_decrypt_blocks: + mov %rsp, %rax +.Lecb_dec_prologue: + push %rbp + push %rbx + push %r12 + push %r13 + push %r14 + push %r15 + lea -0x48(%rsp),%rsp +___ +$code.=<<___ if ($win64); + lea -0xa0(%rsp), %rsp + movaps %xmm6, 0x40(%rsp) + movaps %xmm7, 0x50(%rsp) + movaps %xmm8, 0x60(%rsp) + movaps %xmm9, 0x70(%rsp) + movaps %xmm10, 0x80(%rsp) + movaps %xmm11, 0x90(%rsp) + movaps %xmm12, 0xa0(%rsp) + movaps %xmm13, 0xb0(%rsp) + movaps %xmm14, 0xc0(%rsp) + movaps %xmm15, 0xd0(%rsp) +.Lecb_dec_body: +___ +$code.=<<___; + mov %rsp,%rbp # backup %rsp + mov 240($arg4),%eax # rounds + mov $arg1,$inp # backup arguments + mov $arg2,$out + mov $arg3,$len + mov $arg4,$key + cmp \$8,$arg3 + jb .Lecb_dec_short + + mov %eax,%ebx # backup rounds + shl \$7,%rax # 128 bytes per inner round key + sub \$`128-32`,%rax # size of bit-sliced key schedule + sub %rax,%rsp + mov %rsp,%rax # pass key schedule + mov $key,%rcx # pass key + mov %ebx,%r10d # pass rounds + call _bsaes_key_convert + pxor (%rsp),%xmm7 # fix up 0 round key + movdqa %xmm6,(%rax) # save last round key + movdqa %xmm7,(%rsp) + + sub \$8,$len +.Lecb_dec_loop: + movdqu 0x00($inp), @XMM[0] # load input + movdqu 0x10($inp), @XMM[1] + movdqu 0x20($inp), @XMM[2] + movdqu 0x30($inp), @XMM[3] + movdqu 0x40($inp), @XMM[4] + movdqu 0x50($inp), @XMM[5] + mov %rsp, %rax # pass key schedule + movdqu 0x60($inp), @XMM[6] + mov %ebx,%r10d # pass rounds + movdqu 0x70($inp), @XMM[7] + lea 0x80($inp), $inp + + call _bsaes_decrypt8 + + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[6], 0x20($out) + movdqu @XMM[4], 0x30($out) + movdqu @XMM[2], 0x40($out) + movdqu @XMM[7], 0x50($out) + movdqu @XMM[3], 0x60($out) + movdqu @XMM[5], 0x70($out) + lea 0x80($out), $out + sub \$8,$len + jnc .Lecb_dec_loop + + add \$8,$len + jz .Lecb_dec_done + + movdqu 0x00($inp), @XMM[0] # load input + mov %rsp, %rax # pass key schedule + mov %ebx,%r10d # pass rounds + cmp \$2,$len + jb .Lecb_dec_one + movdqu 0x10($inp), @XMM[1] + je .Lecb_dec_two + movdqu 0x20($inp), @XMM[2] + cmp \$4,$len + jb .Lecb_dec_three + movdqu 0x30($inp), @XMM[3] + je .Lecb_dec_four + movdqu 0x40($inp), @XMM[4] + cmp \$6,$len + jb .Lecb_dec_five + movdqu 0x50($inp), @XMM[5] + je .Lecb_dec_six + movdqu 0x60($inp), @XMM[6] + call _bsaes_decrypt8 + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[6], 0x20($out) + movdqu @XMM[4], 0x30($out) + movdqu @XMM[2], 0x40($out) + movdqu @XMM[7], 0x50($out) + movdqu @XMM[3], 0x60($out) + jmp .Lecb_dec_done +.align 16 +.Lecb_dec_six: + call _bsaes_decrypt8 + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[6], 0x20($out) + movdqu @XMM[4], 0x30($out) + movdqu @XMM[2], 0x40($out) + movdqu @XMM[7], 0x50($out) + jmp .Lecb_dec_done +.align 16 +.Lecb_dec_five: + call _bsaes_decrypt8 + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[6], 0x20($out) + movdqu @XMM[4], 0x30($out) + movdqu @XMM[2], 0x40($out) + jmp .Lecb_dec_done +.align 16 +.Lecb_dec_four: + call _bsaes_decrypt8 + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[6], 0x20($out) + movdqu @XMM[4], 0x30($out) + jmp .Lecb_dec_done +.align 16 +.Lecb_dec_three: + call _bsaes_decrypt8 + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[6], 0x20($out) + jmp .Lecb_dec_done +.align 16 +.Lecb_dec_two: + call _bsaes_decrypt8 + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + jmp .Lecb_dec_done +.align 16 +.Lecb_dec_one: + call _bsaes_decrypt8 + movdqu @XMM[0], 0x00($out) # write output + jmp .Lecb_dec_done +.align 16 +.Lecb_dec_short: + lea ($inp), $arg1 + lea ($out), $arg2 + lea ($key), $arg3 + call asm_AES_decrypt + lea 16($inp), $inp + lea 16($out), $out + dec $len + jnz .Lecb_dec_short + +.Lecb_dec_done: + lea (%rsp),%rax + pxor %xmm0, %xmm0 +.Lecb_dec_bzero: # wipe key schedule [if any] + movdqa %xmm0, 0x00(%rax) + movdqa %xmm0, 0x10(%rax) + lea 0x20(%rax), %rax + cmp %rax, %rbp + jb .Lecb_dec_bzero + + lea (%rbp),%rsp # restore %rsp +___ +$code.=<<___ if ($win64); + movaps 0x40(%rbp), %xmm6 + movaps 0x50(%rbp), %xmm7 + movaps 0x60(%rbp), %xmm8 + movaps 0x70(%rbp), %xmm9 + movaps 0x80(%rbp), %xmm10 + movaps 0x90(%rbp), %xmm11 + movaps 0xa0(%rbp), %xmm12 + movaps 0xb0(%rbp), %xmm13 + movaps 0xc0(%rbp), %xmm14 + movaps 0xd0(%rbp), %xmm15 + lea 0xa0(%rbp), %rsp +___ +$code.=<<___; + mov 0x48(%rsp), %r15 + mov 0x50(%rsp), %r14 + mov 0x58(%rsp), %r13 + mov 0x60(%rsp), %r12 + mov 0x68(%rsp), %rbx + mov 0x70(%rsp), %rax + lea 0x78(%rsp), %rsp + mov %rax, %rbp +.Lecb_dec_epilogue: + ret +.size bsaes_ecb_decrypt_blocks,.-bsaes_ecb_decrypt_blocks +___ +} +$code.=<<___; +.extern asm_AES_cbc_encrypt +.globl bsaes_cbc_encrypt +.type bsaes_cbc_encrypt,\@abi-omnipotent +.align 16 +bsaes_cbc_encrypt: +___ +$code.=<<___ if ($win64); + mov 48(%rsp),$arg6 # pull direction flag +___ +$code.=<<___; + cmp \$0,$arg6 + jne asm_AES_cbc_encrypt + cmp \$128,$arg3 + jb asm_AES_cbc_encrypt + + mov %rsp, %rax +.Lcbc_dec_prologue: + push %rbp + push %rbx + push %r12 + push %r13 + push %r14 + push %r15 + lea -0x48(%rsp), %rsp +___ +$code.=<<___ if ($win64); + mov 0xa0(%rsp),$arg5 # pull ivp + lea -0xa0(%rsp), %rsp + movaps %xmm6, 0x40(%rsp) + movaps %xmm7, 0x50(%rsp) + movaps %xmm8, 0x60(%rsp) + movaps %xmm9, 0x70(%rsp) + movaps %xmm10, 0x80(%rsp) + movaps %xmm11, 0x90(%rsp) + movaps %xmm12, 0xa0(%rsp) + movaps %xmm13, 0xb0(%rsp) + movaps %xmm14, 0xc0(%rsp) + movaps %xmm15, 0xd0(%rsp) +.Lcbc_dec_body: +___ +$code.=<<___; + mov %rsp, %rbp # backup %rsp + mov 240($arg4), %eax # rounds + mov $arg1, $inp # backup arguments + mov $arg2, $out + mov $arg3, $len + mov $arg4, $key + mov $arg5, %rbx + shr \$4, $len # bytes to blocks + + mov %eax, %edx # rounds + shl \$7, %rax # 128 bytes per inner round key + sub \$`128-32`, %rax # size of bit-sliced key schedule + sub %rax, %rsp + + mov %rsp, %rax # pass key schedule + mov $key, %rcx # pass key + mov %edx, %r10d # pass rounds + call _bsaes_key_convert + pxor (%rsp),%xmm7 # fix up 0 round key + movdqa %xmm6,(%rax) # save last round key + movdqa %xmm7,(%rsp) + + movdqu (%rbx), @XMM[15] # load IV + sub \$8,$len +.Lcbc_dec_loop: + movdqu 0x00($inp), @XMM[0] # load input + movdqu 0x10($inp), @XMM[1] + movdqu 0x20($inp), @XMM[2] + movdqu 0x30($inp), @XMM[3] + movdqu 0x40($inp), @XMM[4] + movdqu 0x50($inp), @XMM[5] + mov %rsp, %rax # pass key schedule + movdqu 0x60($inp), @XMM[6] + mov %edx,%r10d # pass rounds + movdqu 0x70($inp), @XMM[7] + movdqa @XMM[15], 0x20(%rbp) # put aside IV + + call _bsaes_decrypt8 + + pxor 0x20(%rbp), @XMM[0] # ^= IV + movdqu 0x00($inp), @XMM[8] # re-load input + movdqu 0x10($inp), @XMM[9] + pxor @XMM[8], @XMM[1] + movdqu 0x20($inp), @XMM[10] + pxor @XMM[9], @XMM[6] + movdqu 0x30($inp), @XMM[11] + pxor @XMM[10], @XMM[4] + movdqu 0x40($inp), @XMM[12] + pxor @XMM[11], @XMM[2] + movdqu 0x50($inp), @XMM[13] + pxor @XMM[12], @XMM[7] + movdqu 0x60($inp), @XMM[14] + pxor @XMM[13], @XMM[3] + movdqu 0x70($inp), @XMM[15] # IV + pxor @XMM[14], @XMM[5] + movdqu @XMM[0], 0x00($out) # write output + lea 0x80($inp), $inp + movdqu @XMM[1], 0x10($out) + movdqu @XMM[6], 0x20($out) + movdqu @XMM[4], 0x30($out) + movdqu @XMM[2], 0x40($out) + movdqu @XMM[7], 0x50($out) + movdqu @XMM[3], 0x60($out) + movdqu @XMM[5], 0x70($out) + lea 0x80($out), $out + sub \$8,$len + jnc .Lcbc_dec_loop + + add \$8,$len + jz .Lcbc_dec_done + + movdqu 0x00($inp), @XMM[0] # load input + mov %rsp, %rax # pass key schedule + mov %edx, %r10d # pass rounds + cmp \$2,$len + jb .Lcbc_dec_one + movdqu 0x10($inp), @XMM[1] + je .Lcbc_dec_two + movdqu 0x20($inp), @XMM[2] + cmp \$4,$len + jb .Lcbc_dec_three + movdqu 0x30($inp), @XMM[3] + je .Lcbc_dec_four + movdqu 0x40($inp), @XMM[4] + cmp \$6,$len + jb .Lcbc_dec_five + movdqu 0x50($inp), @XMM[5] + je .Lcbc_dec_six + movdqu 0x60($inp), @XMM[6] + movdqa @XMM[15], 0x20(%rbp) # put aside IV + call _bsaes_decrypt8 + pxor 0x20(%rbp), @XMM[0] # ^= IV + movdqu 0x00($inp), @XMM[8] # re-load input + movdqu 0x10($inp), @XMM[9] + pxor @XMM[8], @XMM[1] + movdqu 0x20($inp), @XMM[10] + pxor @XMM[9], @XMM[6] + movdqu 0x30($inp), @XMM[11] + pxor @XMM[10], @XMM[4] + movdqu 0x40($inp), @XMM[12] + pxor @XMM[11], @XMM[2] + movdqu 0x50($inp), @XMM[13] + pxor @XMM[12], @XMM[7] + movdqu 0x60($inp), @XMM[15] # IV + pxor @XMM[13], @XMM[3] + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[6], 0x20($out) + movdqu @XMM[4], 0x30($out) + movdqu @XMM[2], 0x40($out) + movdqu @XMM[7], 0x50($out) + movdqu @XMM[3], 0x60($out) + jmp .Lcbc_dec_done +.align 16 +.Lcbc_dec_six: + movdqa @XMM[15], 0x20(%rbp) # put aside IV + call _bsaes_decrypt8 + pxor 0x20(%rbp), @XMM[0] # ^= IV + movdqu 0x00($inp), @XMM[8] # re-load input + movdqu 0x10($inp), @XMM[9] + pxor @XMM[8], @XMM[1] + movdqu 0x20($inp), @XMM[10] + pxor @XMM[9], @XMM[6] + movdqu 0x30($inp), @XMM[11] + pxor @XMM[10], @XMM[4] + movdqu 0x40($inp), @XMM[12] + pxor @XMM[11], @XMM[2] + movdqu 0x50($inp), @XMM[15] # IV + pxor @XMM[12], @XMM[7] + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[6], 0x20($out) + movdqu @XMM[4], 0x30($out) + movdqu @XMM[2], 0x40($out) + movdqu @XMM[7], 0x50($out) + jmp .Lcbc_dec_done +.align 16 +.Lcbc_dec_five: + movdqa @XMM[15], 0x20(%rbp) # put aside IV + call _bsaes_decrypt8 + pxor 0x20(%rbp), @XMM[0] # ^= IV + movdqu 0x00($inp), @XMM[8] # re-load input + movdqu 0x10($inp), @XMM[9] + pxor @XMM[8], @XMM[1] + movdqu 0x20($inp), @XMM[10] + pxor @XMM[9], @XMM[6] + movdqu 0x30($inp), @XMM[11] + pxor @XMM[10], @XMM[4] + movdqu 0x40($inp), @XMM[15] # IV + pxor @XMM[11], @XMM[2] + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[6], 0x20($out) + movdqu @XMM[4], 0x30($out) + movdqu @XMM[2], 0x40($out) + jmp .Lcbc_dec_done +.align 16 +.Lcbc_dec_four: + movdqa @XMM[15], 0x20(%rbp) # put aside IV + call _bsaes_decrypt8 + pxor 0x20(%rbp), @XMM[0] # ^= IV + movdqu 0x00($inp), @XMM[8] # re-load input + movdqu 0x10($inp), @XMM[9] + pxor @XMM[8], @XMM[1] + movdqu 0x20($inp), @XMM[10] + pxor @XMM[9], @XMM[6] + movdqu 0x30($inp), @XMM[15] # IV + pxor @XMM[10], @XMM[4] + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[6], 0x20($out) + movdqu @XMM[4], 0x30($out) + jmp .Lcbc_dec_done +.align 16 +.Lcbc_dec_three: + movdqa @XMM[15], 0x20(%rbp) # put aside IV + call _bsaes_decrypt8 + pxor 0x20(%rbp), @XMM[0] # ^= IV + movdqu 0x00($inp), @XMM[8] # re-load input + movdqu 0x10($inp), @XMM[9] + pxor @XMM[8], @XMM[1] + movdqu 0x20($inp), @XMM[15] # IV + pxor @XMM[9], @XMM[6] + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[6], 0x20($out) + jmp .Lcbc_dec_done +.align 16 +.Lcbc_dec_two: + movdqa @XMM[15], 0x20(%rbp) # put aside IV + call _bsaes_decrypt8 + pxor 0x20(%rbp), @XMM[0] # ^= IV + movdqu 0x00($inp), @XMM[8] # re-load input + movdqu 0x10($inp), @XMM[15] # IV + pxor @XMM[8], @XMM[1] + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + jmp .Lcbc_dec_done +.align 16 +.Lcbc_dec_one: + lea ($inp), $arg1 + lea 0x20(%rbp), $arg2 # buffer output + lea ($key), $arg3 + call asm_AES_decrypt # doesn't touch %xmm + pxor 0x20(%rbp), @XMM[15] # ^= IV + movdqu @XMM[15], ($out) # write output + movdqa @XMM[0], @XMM[15] # IV + +.Lcbc_dec_done: + movdqu @XMM[15], (%rbx) # return IV + lea (%rsp), %rax + pxor %xmm0, %xmm0 +.Lcbc_dec_bzero: # wipe key schedule [if any] + movdqa %xmm0, 0x00(%rax) + movdqa %xmm0, 0x10(%rax) + lea 0x20(%rax), %rax + cmp %rax, %rbp + ja .Lcbc_dec_bzero + + lea (%rbp),%rsp # restore %rsp +___ +$code.=<<___ if ($win64); + movaps 0x40(%rbp), %xmm6 + movaps 0x50(%rbp), %xmm7 + movaps 0x60(%rbp), %xmm8 + movaps 0x70(%rbp), %xmm9 + movaps 0x80(%rbp), %xmm10 + movaps 0x90(%rbp), %xmm11 + movaps 0xa0(%rbp), %xmm12 + movaps 0xb0(%rbp), %xmm13 + movaps 0xc0(%rbp), %xmm14 + movaps 0xd0(%rbp), %xmm15 + lea 0xa0(%rbp), %rsp +___ +$code.=<<___; + mov 0x48(%rsp), %r15 + mov 0x50(%rsp), %r14 + mov 0x58(%rsp), %r13 + mov 0x60(%rsp), %r12 + mov 0x68(%rsp), %rbx + mov 0x70(%rsp), %rax + lea 0x78(%rsp), %rsp + mov %rax, %rbp +.Lcbc_dec_epilogue: + ret +.size bsaes_cbc_encrypt,.-bsaes_cbc_encrypt + +.globl bsaes_ctr32_encrypt_blocks +.type bsaes_ctr32_encrypt_blocks,\@abi-omnipotent +.align 16 +bsaes_ctr32_encrypt_blocks: + mov %rsp, %rax +.Lctr_enc_prologue: + push %rbp + push %rbx + push %r12 + push %r13 + push %r14 + push %r15 + lea -0x48(%rsp), %rsp +___ +$code.=<<___ if ($win64); + mov 0xa0(%rsp),$arg5 # pull ivp + lea -0xa0(%rsp), %rsp + movaps %xmm6, 0x40(%rsp) + movaps %xmm7, 0x50(%rsp) + movaps %xmm8, 0x60(%rsp) + movaps %xmm9, 0x70(%rsp) + movaps %xmm10, 0x80(%rsp) + movaps %xmm11, 0x90(%rsp) + movaps %xmm12, 0xa0(%rsp) + movaps %xmm13, 0xb0(%rsp) + movaps %xmm14, 0xc0(%rsp) + movaps %xmm15, 0xd0(%rsp) +.Lctr_enc_body: +___ +$code.=<<___; + mov %rsp, %rbp # backup %rsp + movdqu ($arg5), %xmm0 # load counter + mov 240($arg4), %eax # rounds + mov $arg1, $inp # backup arguments + mov $arg2, $out + mov $arg3, $len + mov $arg4, $key + movdqa %xmm0, 0x20(%rbp) # copy counter + cmp \$8, $arg3 + jb .Lctr_enc_short + + mov %eax, %ebx # rounds + shl \$7, %rax # 128 bytes per inner round key + sub \$`128-32`, %rax # size of bit-sliced key schedule + sub %rax, %rsp + + mov %rsp, %rax # pass key schedule + mov $key, %rcx # pass key + mov %ebx, %r10d # pass rounds + call _bsaes_key_convert + pxor %xmm6,%xmm7 # fix up last round key + movdqa %xmm7,(%rax) # save last round key + + movdqa (%rsp), @XMM[9] # load round0 key + lea .LADD1(%rip), %r11 + movdqa 0x20(%rbp), @XMM[0] # counter copy + movdqa -0x20(%r11), @XMM[8] # .LSWPUP + pshufb @XMM[8], @XMM[9] # byte swap upper part + pshufb @XMM[8], @XMM[0] + movdqa @XMM[9], (%rsp) # save adjusted round0 key + jmp .Lctr_enc_loop +.align 16 +.Lctr_enc_loop: + movdqa @XMM[0], 0x20(%rbp) # save counter + movdqa @XMM[0], @XMM[1] # prepare 8 counter values + movdqa @XMM[0], @XMM[2] + paddd 0x00(%r11), @XMM[1] # .LADD1 + movdqa @XMM[0], @XMM[3] + paddd 0x10(%r11), @XMM[2] # .LADD2 + movdqa @XMM[0], @XMM[4] + paddd 0x20(%r11), @XMM[3] # .LADD3 + movdqa @XMM[0], @XMM[5] + paddd 0x30(%r11), @XMM[4] # .LADD4 + movdqa @XMM[0], @XMM[6] + paddd 0x40(%r11), @XMM[5] # .LADD5 + movdqa @XMM[0], @XMM[7] + paddd 0x50(%r11), @XMM[6] # .LADD6 + paddd 0x60(%r11), @XMM[7] # .LADD7 + + # Borrow prologue from _bsaes_encrypt8 to use the opportunity + # to flip byte order in 32-bit counter + movdqa (%rsp), @XMM[9] # round 0 key + lea 0x10(%rsp), %rax # pass key schedule + movdqa -0x10(%r11), @XMM[8] # .LSWPUPM0SR + pxor @XMM[9], @XMM[0] # xor with round0 key + pxor @XMM[9], @XMM[1] + pxor @XMM[9], @XMM[2] + pxor @XMM[9], @XMM[3] + pshufb @XMM[8], @XMM[0] + pshufb @XMM[8], @XMM[1] + pxor @XMM[9], @XMM[4] + pxor @XMM[9], @XMM[5] + pshufb @XMM[8], @XMM[2] + pshufb @XMM[8], @XMM[3] + pxor @XMM[9], @XMM[6] + pxor @XMM[9], @XMM[7] + pshufb @XMM[8], @XMM[4] + pshufb @XMM[8], @XMM[5] + pshufb @XMM[8], @XMM[6] + pshufb @XMM[8], @XMM[7] + lea .LBS0(%rip), %r11 # constants table + mov %ebx,%r10d # pass rounds + + call _bsaes_encrypt8_bitslice + + sub \$8,$len + jc .Lctr_enc_loop_done + + movdqu 0x00($inp), @XMM[8] # load input + movdqu 0x10($inp), @XMM[9] + movdqu 0x20($inp), @XMM[10] + movdqu 0x30($inp), @XMM[11] + movdqu 0x40($inp), @XMM[12] + movdqu 0x50($inp), @XMM[13] + movdqu 0x60($inp), @XMM[14] + movdqu 0x70($inp), @XMM[15] + lea 0x80($inp),$inp + pxor @XMM[0], @XMM[8] + movdqa 0x20(%rbp), @XMM[0] # load counter + pxor @XMM[9], @XMM[1] + movdqu @XMM[8], 0x00($out) # write output + pxor @XMM[10], @XMM[4] + movdqu @XMM[1], 0x10($out) + pxor @XMM[11], @XMM[6] + movdqu @XMM[4], 0x20($out) + pxor @XMM[12], @XMM[3] + movdqu @XMM[6], 0x30($out) + pxor @XMM[13], @XMM[7] + movdqu @XMM[3], 0x40($out) + pxor @XMM[14], @XMM[2] + movdqu @XMM[7], 0x50($out) + pxor @XMM[15], @XMM[5] + movdqu @XMM[2], 0x60($out) + lea .LADD1(%rip), %r11 + movdqu @XMM[5], 0x70($out) + lea 0x80($out), $out + paddd 0x70(%r11), @XMM[0] # .LADD8 + jnz .Lctr_enc_loop + + jmp .Lctr_enc_done +.align 16 +.Lctr_enc_loop_done: + add \$8, $len + movdqu 0x00($inp), @XMM[8] # load input + pxor @XMM[8], @XMM[0] + movdqu @XMM[0], 0x00($out) # write output + cmp \$2,$len + jb .Lctr_enc_done + movdqu 0x10($inp), @XMM[9] + pxor @XMM[9], @XMM[1] + movdqu @XMM[1], 0x10($out) + je .Lctr_enc_done + movdqu 0x20($inp), @XMM[10] + pxor @XMM[10], @XMM[4] + movdqu @XMM[4], 0x20($out) + cmp \$4,$len + jb .Lctr_enc_done + movdqu 0x30($inp), @XMM[11] + pxor @XMM[11], @XMM[6] + movdqu @XMM[6], 0x30($out) + je .Lctr_enc_done + movdqu 0x40($inp), @XMM[12] + pxor @XMM[12], @XMM[3] + movdqu @XMM[3], 0x40($out) + cmp \$6,$len + jb .Lctr_enc_done + movdqu 0x50($inp), @XMM[13] + pxor @XMM[13], @XMM[7] + movdqu @XMM[7], 0x50($out) + je .Lctr_enc_done + movdqu 0x60($inp), @XMM[14] + pxor @XMM[14], @XMM[2] + movdqu @XMM[2], 0x60($out) + jmp .Lctr_enc_done + +.align 16 +.Lctr_enc_short: + lea 0x20(%rbp), $arg1 + lea 0x30(%rbp), $arg2 + lea ($key), $arg3 + call asm_AES_encrypt + movdqu ($inp), @XMM[1] + lea 16($inp), $inp + mov 0x2c(%rbp), %eax # load 32-bit counter + bswap %eax + pxor 0x30(%rbp), @XMM[1] + inc %eax # increment + movdqu @XMM[1], ($out) + bswap %eax + lea 16($out), $out + mov %eax, 0x2c(%rsp) # save 32-bit counter + dec $len + jnz .Lctr_enc_short + +.Lctr_enc_done: + lea (%rsp), %rax + pxor %xmm0, %xmm0 +.Lctr_enc_bzero: # wipe key schedule [if any] + movdqa %xmm0, 0x00(%rax) + movdqa %xmm0, 0x10(%rax) + lea 0x20(%rax), %rax + cmp %rax, %rbp + ja .Lctr_enc_bzero + + lea (%rbp),%rsp # restore %rsp +___ +$code.=<<___ if ($win64); + movaps 0x40(%rbp), %xmm6 + movaps 0x50(%rbp), %xmm7 + movaps 0x60(%rbp), %xmm8 + movaps 0x70(%rbp), %xmm9 + movaps 0x80(%rbp), %xmm10 + movaps 0x90(%rbp), %xmm11 + movaps 0xa0(%rbp), %xmm12 + movaps 0xb0(%rbp), %xmm13 + movaps 0xc0(%rbp), %xmm14 + movaps 0xd0(%rbp), %xmm15 + lea 0xa0(%rbp), %rsp +___ +$code.=<<___; + mov 0x48(%rsp), %r15 + mov 0x50(%rsp), %r14 + mov 0x58(%rsp), %r13 + mov 0x60(%rsp), %r12 + mov 0x68(%rsp), %rbx + mov 0x70(%rsp), %rax + lea 0x78(%rsp), %rsp + mov %rax, %rbp +.Lctr_enc_epilogue: + ret +.size bsaes_ctr32_encrypt_blocks,.-bsaes_ctr32_encrypt_blocks +___ +###################################################################### +# void bsaes_xts_[en|de]crypt(const char *inp,char *out,size_t len, +# const AES_KEY *key1, const AES_KEY *key2, +# const unsigned char iv[16]); +# +my ($twmask,$twres,$twtmp)=@XMM[13..15]; +$arg6=~s/d$//; + +$code.=<<___; +.globl bsaes_xts_encrypt +.type bsaes_xts_encrypt,\@abi-omnipotent +.align 16 +bsaes_xts_encrypt: + mov %rsp, %rax +.Lxts_enc_prologue: + push %rbp + push %rbx + push %r12 + push %r13 + push %r14 + push %r15 + lea -0x48(%rsp), %rsp +___ +$code.=<<___ if ($win64); + mov 0xa0(%rsp),$arg5 # pull key2 + mov 0xa8(%rsp),$arg6 # pull ivp + lea -0xa0(%rsp), %rsp + movaps %xmm6, 0x40(%rsp) + movaps %xmm7, 0x50(%rsp) + movaps %xmm8, 0x60(%rsp) + movaps %xmm9, 0x70(%rsp) + movaps %xmm10, 0x80(%rsp) + movaps %xmm11, 0x90(%rsp) + movaps %xmm12, 0xa0(%rsp) + movaps %xmm13, 0xb0(%rsp) + movaps %xmm14, 0xc0(%rsp) + movaps %xmm15, 0xd0(%rsp) +.Lxts_enc_body: +___ +$code.=<<___; + mov %rsp, %rbp # backup %rsp + mov $arg1, $inp # backup arguments + mov $arg2, $out + mov $arg3, $len + mov $arg4, $key + + lea ($arg6), $arg1 + lea 0x20(%rbp), $arg2 + lea ($arg5), $arg3 + call asm_AES_encrypt # generate initial tweak + + mov 240($key), %eax # rounds + mov $len, %rbx # backup $len + + mov %eax, %edx # rounds + shl \$7, %rax # 128 bytes per inner round key + sub \$`128-32`, %rax # size of bit-sliced key schedule + sub %rax, %rsp + + mov %rsp, %rax # pass key schedule + mov $key, %rcx # pass key + mov %edx, %r10d # pass rounds + call _bsaes_key_convert + pxor %xmm6, %xmm7 # fix up last round key + movdqa %xmm7, (%rax) # save last round key + + and \$-16, $len + sub \$0x80, %rsp # place for tweak[8] + movdqa 0x20(%rbp), @XMM[7] # initial tweak + + pxor $twtmp, $twtmp + movdqa .Lxts_magic(%rip), $twmask + pcmpgtd @XMM[7], $twtmp # broadcast upper bits + + sub \$0x80, $len + jc .Lxts_enc_short + jmp .Lxts_enc_loop + +.align 16 +.Lxts_enc_loop: +___ + for ($i=0;$i<7;$i++) { + $code.=<<___; + pshufd \$0x13, $twtmp, $twres + pxor $twtmp, $twtmp + movdqa @XMM[7], @XMM[$i] + movdqa @XMM[7], `0x10*$i`(%rsp)# save tweak[$i] + paddq @XMM[7], @XMM[7] # psllq 1,$tweak + pand $twmask, $twres # isolate carry and residue + pcmpgtd @XMM[7], $twtmp # broadcast upper bits + pxor $twres, @XMM[7] +___ + $code.=<<___ if ($i>=1); + movdqu `0x10*($i-1)`($inp), @XMM[8+$i-1] +___ + $code.=<<___ if ($i>=2); + pxor @XMM[8+$i-2], @XMM[$i-2]# input[] ^ tweak[] +___ + } +$code.=<<___; + movdqu 0x60($inp), @XMM[8+6] + pxor @XMM[8+5], @XMM[5] + movdqu 0x70($inp), @XMM[8+7] + lea 0x80($inp), $inp + movdqa @XMM[7], 0x70(%rsp) + pxor @XMM[8+6], @XMM[6] + lea 0x80(%rsp), %rax # pass key schedule + pxor @XMM[8+7], @XMM[7] + mov %edx, %r10d # pass rounds + + call _bsaes_encrypt8 + + pxor 0x00(%rsp), @XMM[0] # ^= tweak[] + pxor 0x10(%rsp), @XMM[1] + movdqu @XMM[0], 0x00($out) # write output + pxor 0x20(%rsp), @XMM[4] + movdqu @XMM[1], 0x10($out) + pxor 0x30(%rsp), @XMM[6] + movdqu @XMM[4], 0x20($out) + pxor 0x40(%rsp), @XMM[3] + movdqu @XMM[6], 0x30($out) + pxor 0x50(%rsp), @XMM[7] + movdqu @XMM[3], 0x40($out) + pxor 0x60(%rsp), @XMM[2] + movdqu @XMM[7], 0x50($out) + pxor 0x70(%rsp), @XMM[5] + movdqu @XMM[2], 0x60($out) + movdqu @XMM[5], 0x70($out) + lea 0x80($out), $out + + movdqa 0x70(%rsp), @XMM[7] # prepare next iteration tweak + pxor $twtmp, $twtmp + movdqa .Lxts_magic(%rip), $twmask + pcmpgtd @XMM[7], $twtmp + pshufd \$0x13, $twtmp, $twres + pxor $twtmp, $twtmp + paddq @XMM[7], @XMM[7] # psllq 1,$tweak + pand $twmask, $twres # isolate carry and residue + pcmpgtd @XMM[7], $twtmp # broadcast upper bits + pxor $twres, @XMM[7] + + sub \$0x80,$len + jnc .Lxts_enc_loop + +.Lxts_enc_short: + add \$0x80, $len + jz .Lxts_enc_done +___ + for ($i=0;$i<7;$i++) { + $code.=<<___; + pshufd \$0x13, $twtmp, $twres + pxor $twtmp, $twtmp + movdqa @XMM[7], @XMM[$i] + movdqa @XMM[7], `0x10*$i`(%rsp)# save tweak[$i] + paddq @XMM[7], @XMM[7] # psllq 1,$tweak + pand $twmask, $twres # isolate carry and residue + pcmpgtd @XMM[7], $twtmp # broadcast upper bits + pxor $twres, @XMM[7] +___ + $code.=<<___ if ($i>=1); + movdqu `0x10*($i-1)`($inp), @XMM[8+$i-1] + cmp \$`0x10*$i`,$len + je .Lxts_enc_$i +___ + $code.=<<___ if ($i>=2); + pxor @XMM[8+$i-2], @XMM[$i-2]# input[] ^ tweak[] +___ + } +$code.=<<___; + movdqu 0x60($inp), @XMM[8+6] + pxor @XMM[8+5], @XMM[5] + movdqa @XMM[7], 0x70(%rsp) + lea 0x70($inp), $inp + pxor @XMM[8+6], @XMM[6] + lea 0x80(%rsp), %rax # pass key schedule + mov %edx, %r10d # pass rounds + + call _bsaes_encrypt8 + + pxor 0x00(%rsp), @XMM[0] # ^= tweak[] + pxor 0x10(%rsp), @XMM[1] + movdqu @XMM[0], 0x00($out) # write output + pxor 0x20(%rsp), @XMM[4] + movdqu @XMM[1], 0x10($out) + pxor 0x30(%rsp), @XMM[6] + movdqu @XMM[4], 0x20($out) + pxor 0x40(%rsp), @XMM[3] + movdqu @XMM[6], 0x30($out) + pxor 0x50(%rsp), @XMM[7] + movdqu @XMM[3], 0x40($out) + pxor 0x60(%rsp), @XMM[2] + movdqu @XMM[7], 0x50($out) + movdqu @XMM[2], 0x60($out) + lea 0x70($out), $out + + movdqa 0x70(%rsp), @XMM[7] # next iteration tweak + jmp .Lxts_enc_done +.align 16 +.Lxts_enc_6: + pxor @XMM[8+4], @XMM[4] + lea 0x60($inp), $inp + pxor @XMM[8+5], @XMM[5] + lea 0x80(%rsp), %rax # pass key schedule + mov %edx, %r10d # pass rounds + + call _bsaes_encrypt8 + + pxor 0x00(%rsp), @XMM[0] # ^= tweak[] + pxor 0x10(%rsp), @XMM[1] + movdqu @XMM[0], 0x00($out) # write output + pxor 0x20(%rsp), @XMM[4] + movdqu @XMM[1], 0x10($out) + pxor 0x30(%rsp), @XMM[6] + movdqu @XMM[4], 0x20($out) + pxor 0x40(%rsp), @XMM[3] + movdqu @XMM[6], 0x30($out) + pxor 0x50(%rsp), @XMM[7] + movdqu @XMM[3], 0x40($out) + movdqu @XMM[7], 0x50($out) + lea 0x60($out), $out + + movdqa 0x60(%rsp), @XMM[7] # next iteration tweak + jmp .Lxts_enc_done +.align 16 +.Lxts_enc_5: + pxor @XMM[8+3], @XMM[3] + lea 0x50($inp), $inp + pxor @XMM[8+4], @XMM[4] + lea 0x80(%rsp), %rax # pass key schedule + mov %edx, %r10d # pass rounds + + call _bsaes_encrypt8 + + pxor 0x00(%rsp), @XMM[0] # ^= tweak[] + pxor 0x10(%rsp), @XMM[1] + movdqu @XMM[0], 0x00($out) # write output + pxor 0x20(%rsp), @XMM[4] + movdqu @XMM[1], 0x10($out) + pxor 0x30(%rsp), @XMM[6] + movdqu @XMM[4], 0x20($out) + pxor 0x40(%rsp), @XMM[3] + movdqu @XMM[6], 0x30($out) + movdqu @XMM[3], 0x40($out) + lea 0x50($out), $out + + movdqa 0x50(%rsp), @XMM[7] # next iteration tweak + jmp .Lxts_enc_done +.align 16 +.Lxts_enc_4: + pxor @XMM[8+2], @XMM[2] + lea 0x40($inp), $inp + pxor @XMM[8+3], @XMM[3] + lea 0x80(%rsp), %rax # pass key schedule + mov %edx, %r10d # pass rounds + + call _bsaes_encrypt8 + + pxor 0x00(%rsp), @XMM[0] # ^= tweak[] + pxor 0x10(%rsp), @XMM[1] + movdqu @XMM[0], 0x00($out) # write output + pxor 0x20(%rsp), @XMM[4] + movdqu @XMM[1], 0x10($out) + pxor 0x30(%rsp), @XMM[6] + movdqu @XMM[4], 0x20($out) + movdqu @XMM[6], 0x30($out) + lea 0x40($out), $out + + movdqa 0x40(%rsp), @XMM[7] # next iteration tweak + jmp .Lxts_enc_done +.align 16 +.Lxts_enc_3: + pxor @XMM[8+1], @XMM[1] + lea 0x30($inp), $inp + pxor @XMM[8+2], @XMM[2] + lea 0x80(%rsp), %rax # pass key schedule + mov %edx, %r10d # pass rounds + + call _bsaes_encrypt8 + + pxor 0x00(%rsp), @XMM[0] # ^= tweak[] + pxor 0x10(%rsp), @XMM[1] + movdqu @XMM[0], 0x00($out) # write output + pxor 0x20(%rsp), @XMM[4] + movdqu @XMM[1], 0x10($out) + movdqu @XMM[4], 0x20($out) + lea 0x30($out), $out + + movdqa 0x30(%rsp), @XMM[7] # next iteration tweak + jmp .Lxts_enc_done +.align 16 +.Lxts_enc_2: + pxor @XMM[8+0], @XMM[0] + lea 0x20($inp), $inp + pxor @XMM[8+1], @XMM[1] + lea 0x80(%rsp), %rax # pass key schedule + mov %edx, %r10d # pass rounds + + call _bsaes_encrypt8 + + pxor 0x00(%rsp), @XMM[0] # ^= tweak[] + pxor 0x10(%rsp), @XMM[1] + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + lea 0x20($out), $out + + movdqa 0x20(%rsp), @XMM[7] # next iteration tweak + jmp .Lxts_enc_done +.align 16 +.Lxts_enc_1: + pxor @XMM[0], @XMM[8] + lea 0x10($inp), $inp + movdqa @XMM[8], 0x20(%rbp) + lea 0x20(%rbp), $arg1 + lea 0x20(%rbp), $arg2 + lea ($key), $arg3 + call asm_AES_encrypt # doesn't touch %xmm + pxor 0x20(%rbp), @XMM[0] # ^= tweak[] + #pxor @XMM[8], @XMM[0] + #lea 0x80(%rsp), %rax # pass key schedule + #mov %edx, %r10d # pass rounds + #call _bsaes_encrypt8 + #pxor 0x00(%rsp), @XMM[0] # ^= tweak[] + movdqu @XMM[0], 0x00($out) # write output + lea 0x10($out), $out + + movdqa 0x10(%rsp), @XMM[7] # next iteration tweak + +.Lxts_enc_done: + and \$15, %ebx + jz .Lxts_enc_ret + mov $out, %rdx + +.Lxts_enc_steal: + movzb ($inp), %eax + movzb -16(%rdx), %ecx + lea 1($inp), $inp + mov %al, -16(%rdx) + mov %cl, 0(%rdx) + lea 1(%rdx), %rdx + sub \$1,%ebx + jnz .Lxts_enc_steal + + movdqu -16($out), @XMM[0] + lea 0x20(%rbp), $arg1 + pxor @XMM[7], @XMM[0] + lea 0x20(%rbp), $arg2 + movdqa @XMM[0], 0x20(%rbp) + lea ($key), $arg3 + call asm_AES_encrypt # doesn't touch %xmm + pxor 0x20(%rbp), @XMM[7] + movdqu @XMM[7], -16($out) + +.Lxts_enc_ret: + lea (%rsp), %rax + pxor %xmm0, %xmm0 +.Lxts_enc_bzero: # wipe key schedule [if any] + movdqa %xmm0, 0x00(%rax) + movdqa %xmm0, 0x10(%rax) + lea 0x20(%rax), %rax + cmp %rax, %rbp + ja .Lxts_enc_bzero + + lea (%rbp),%rsp # restore %rsp +___ +$code.=<<___ if ($win64); + movaps 0x40(%rbp), %xmm6 + movaps 0x50(%rbp), %xmm7 + movaps 0x60(%rbp), %xmm8 + movaps 0x70(%rbp), %xmm9 + movaps 0x80(%rbp), %xmm10 + movaps 0x90(%rbp), %xmm11 + movaps 0xa0(%rbp), %xmm12 + movaps 0xb0(%rbp), %xmm13 + movaps 0xc0(%rbp), %xmm14 + movaps 0xd0(%rbp), %xmm15 + lea 0xa0(%rbp), %rsp +___ +$code.=<<___; + mov 0x48(%rsp), %r15 + mov 0x50(%rsp), %r14 + mov 0x58(%rsp), %r13 + mov 0x60(%rsp), %r12 + mov 0x68(%rsp), %rbx + mov 0x70(%rsp), %rax + lea 0x78(%rsp), %rsp + mov %rax, %rbp +.Lxts_enc_epilogue: + ret +.size bsaes_xts_encrypt,.-bsaes_xts_encrypt + +.globl bsaes_xts_decrypt +.type bsaes_xts_decrypt,\@abi-omnipotent +.align 16 +bsaes_xts_decrypt: + mov %rsp, %rax +.Lxts_dec_prologue: + push %rbp + push %rbx + push %r12 + push %r13 + push %r14 + push %r15 + lea -0x48(%rsp), %rsp +___ +$code.=<<___ if ($win64); + mov 0xa0(%rsp),$arg5 # pull key2 + mov 0xa8(%rsp),$arg6 # pull ivp + lea -0xa0(%rsp), %rsp + movaps %xmm6, 0x40(%rsp) + movaps %xmm7, 0x50(%rsp) + movaps %xmm8, 0x60(%rsp) + movaps %xmm9, 0x70(%rsp) + movaps %xmm10, 0x80(%rsp) + movaps %xmm11, 0x90(%rsp) + movaps %xmm12, 0xa0(%rsp) + movaps %xmm13, 0xb0(%rsp) + movaps %xmm14, 0xc0(%rsp) + movaps %xmm15, 0xd0(%rsp) +.Lxts_dec_body: +___ +$code.=<<___; + mov %rsp, %rbp # backup %rsp + mov $arg1, $inp # backup arguments + mov $arg2, $out + mov $arg3, $len + mov $arg4, $key + + lea ($arg6), $arg1 + lea 0x20(%rbp), $arg2 + lea ($arg5), $arg3 + call asm_AES_encrypt # generate initial tweak + + mov 240($key), %eax # rounds + mov $len, %rbx # backup $len + + mov %eax, %edx # rounds + shl \$7, %rax # 128 bytes per inner round key + sub \$`128-32`, %rax # size of bit-sliced key schedule + sub %rax, %rsp + + mov %rsp, %rax # pass key schedule + mov $key, %rcx # pass key + mov %edx, %r10d # pass rounds + call _bsaes_key_convert + pxor (%rsp), %xmm7 # fix up round 0 key + movdqa %xmm6, (%rax) # save last round key + movdqa %xmm7, (%rsp) + + xor %eax, %eax # if ($len%16) len-=16; + and \$-16, $len + test \$15, %ebx + setnz %al + shl \$4, %rax + sub %rax, $len + + sub \$0x80, %rsp # place for tweak[8] + movdqa 0x20(%rbp), @XMM[7] # initial tweak + + pxor $twtmp, $twtmp + movdqa .Lxts_magic(%rip), $twmask + pcmpgtd @XMM[7], $twtmp # broadcast upper bits + + sub \$0x80, $len + jc .Lxts_dec_short + jmp .Lxts_dec_loop + +.align 16 +.Lxts_dec_loop: +___ + for ($i=0;$i<7;$i++) { + $code.=<<___; + pshufd \$0x13, $twtmp, $twres + pxor $twtmp, $twtmp + movdqa @XMM[7], @XMM[$i] + movdqa @XMM[7], `0x10*$i`(%rsp)# save tweak[$i] + paddq @XMM[7], @XMM[7] # psllq 1,$tweak + pand $twmask, $twres # isolate carry and residue + pcmpgtd @XMM[7], $twtmp # broadcast upper bits + pxor $twres, @XMM[7] +___ + $code.=<<___ if ($i>=1); + movdqu `0x10*($i-1)`($inp), @XMM[8+$i-1] +___ + $code.=<<___ if ($i>=2); + pxor @XMM[8+$i-2], @XMM[$i-2]# input[] ^ tweak[] +___ + } +$code.=<<___; + movdqu 0x60($inp), @XMM[8+6] + pxor @XMM[8+5], @XMM[5] + movdqu 0x70($inp), @XMM[8+7] + lea 0x80($inp), $inp + movdqa @XMM[7], 0x70(%rsp) + pxor @XMM[8+6], @XMM[6] + lea 0x80(%rsp), %rax # pass key schedule + pxor @XMM[8+7], @XMM[7] + mov %edx, %r10d # pass rounds + + call _bsaes_decrypt8 + + pxor 0x00(%rsp), @XMM[0] # ^= tweak[] + pxor 0x10(%rsp), @XMM[1] + movdqu @XMM[0], 0x00($out) # write output + pxor 0x20(%rsp), @XMM[6] + movdqu @XMM[1], 0x10($out) + pxor 0x30(%rsp), @XMM[4] + movdqu @XMM[6], 0x20($out) + pxor 0x40(%rsp), @XMM[2] + movdqu @XMM[4], 0x30($out) + pxor 0x50(%rsp), @XMM[7] + movdqu @XMM[2], 0x40($out) + pxor 0x60(%rsp), @XMM[3] + movdqu @XMM[7], 0x50($out) + pxor 0x70(%rsp), @XMM[5] + movdqu @XMM[3], 0x60($out) + movdqu @XMM[5], 0x70($out) + lea 0x80($out), $out + + movdqa 0x70(%rsp), @XMM[7] # prepare next iteration tweak + pxor $twtmp, $twtmp + movdqa .Lxts_magic(%rip), $twmask + pcmpgtd @XMM[7], $twtmp + pshufd \$0x13, $twtmp, $twres + pxor $twtmp, $twtmp + paddq @XMM[7], @XMM[7] # psllq 1,$tweak + pand $twmask, $twres # isolate carry and residue + pcmpgtd @XMM[7], $twtmp # broadcast upper bits + pxor $twres, @XMM[7] + + sub \$0x80,$len + jnc .Lxts_dec_loop + +.Lxts_dec_short: + add \$0x80, $len + jz .Lxts_dec_done +___ + for ($i=0;$i<7;$i++) { + $code.=<<___; + pshufd \$0x13, $twtmp, $twres + pxor $twtmp, $twtmp + movdqa @XMM[7], @XMM[$i] + movdqa @XMM[7], `0x10*$i`(%rsp)# save tweak[$i] + paddq @XMM[7], @XMM[7] # psllq 1,$tweak + pand $twmask, $twres # isolate carry and residue + pcmpgtd @XMM[7], $twtmp # broadcast upper bits + pxor $twres, @XMM[7] +___ + $code.=<<___ if ($i>=1); + movdqu `0x10*($i-1)`($inp), @XMM[8+$i-1] + cmp \$`0x10*$i`,$len + je .Lxts_dec_$i +___ + $code.=<<___ if ($i>=2); + pxor @XMM[8+$i-2], @XMM[$i-2]# input[] ^ tweak[] +___ + } +$code.=<<___; + movdqu 0x60($inp), @XMM[8+6] + pxor @XMM[8+5], @XMM[5] + movdqa @XMM[7], 0x70(%rsp) + lea 0x70($inp), $inp + pxor @XMM[8+6], @XMM[6] + lea 0x80(%rsp), %rax # pass key schedule + mov %edx, %r10d # pass rounds + + call _bsaes_decrypt8 + + pxor 0x00(%rsp), @XMM[0] # ^= tweak[] + pxor 0x10(%rsp), @XMM[1] + movdqu @XMM[0], 0x00($out) # write output + pxor 0x20(%rsp), @XMM[6] + movdqu @XMM[1], 0x10($out) + pxor 0x30(%rsp), @XMM[4] + movdqu @XMM[6], 0x20($out) + pxor 0x40(%rsp), @XMM[2] + movdqu @XMM[4], 0x30($out) + pxor 0x50(%rsp), @XMM[7] + movdqu @XMM[2], 0x40($out) + pxor 0x60(%rsp), @XMM[3] + movdqu @XMM[7], 0x50($out) + movdqu @XMM[3], 0x60($out) + lea 0x70($out), $out + + movdqa 0x70(%rsp), @XMM[7] # next iteration tweak + jmp .Lxts_dec_done +.align 16 +.Lxts_dec_6: + pxor @XMM[8+4], @XMM[4] + lea 0x60($inp), $inp + pxor @XMM[8+5], @XMM[5] + lea 0x80(%rsp), %rax # pass key schedule + mov %edx, %r10d # pass rounds + + call _bsaes_decrypt8 + + pxor 0x00(%rsp), @XMM[0] # ^= tweak[] + pxor 0x10(%rsp), @XMM[1] + movdqu @XMM[0], 0x00($out) # write output + pxor 0x20(%rsp), @XMM[6] + movdqu @XMM[1], 0x10($out) + pxor 0x30(%rsp), @XMM[4] + movdqu @XMM[6], 0x20($out) + pxor 0x40(%rsp), @XMM[2] + movdqu @XMM[4], 0x30($out) + pxor 0x50(%rsp), @XMM[7] + movdqu @XMM[2], 0x40($out) + movdqu @XMM[7], 0x50($out) + lea 0x60($out), $out + + movdqa 0x60(%rsp), @XMM[7] # next iteration tweak + jmp .Lxts_dec_done +.align 16 +.Lxts_dec_5: + pxor @XMM[8+3], @XMM[3] + lea 0x50($inp), $inp + pxor @XMM[8+4], @XMM[4] + lea 0x80(%rsp), %rax # pass key schedule + mov %edx, %r10d # pass rounds + + call _bsaes_decrypt8 + + pxor 0x00(%rsp), @XMM[0] # ^= tweak[] + pxor 0x10(%rsp), @XMM[1] + movdqu @XMM[0], 0x00($out) # write output + pxor 0x20(%rsp), @XMM[6] + movdqu @XMM[1], 0x10($out) + pxor 0x30(%rsp), @XMM[4] + movdqu @XMM[6], 0x20($out) + pxor 0x40(%rsp), @XMM[2] + movdqu @XMM[4], 0x30($out) + movdqu @XMM[2], 0x40($out) + lea 0x50($out), $out + + movdqa 0x50(%rsp), @XMM[7] # next iteration tweak + jmp .Lxts_dec_done +.align 16 +.Lxts_dec_4: + pxor @XMM[8+2], @XMM[2] + lea 0x40($inp), $inp + pxor @XMM[8+3], @XMM[3] + lea 0x80(%rsp), %rax # pass key schedule + mov %edx, %r10d # pass rounds + + call _bsaes_decrypt8 + + pxor 0x00(%rsp), @XMM[0] # ^= tweak[] + pxor 0x10(%rsp), @XMM[1] + movdqu @XMM[0], 0x00($out) # write output + pxor 0x20(%rsp), @XMM[6] + movdqu @XMM[1], 0x10($out) + pxor 0x30(%rsp), @XMM[4] + movdqu @XMM[6], 0x20($out) + movdqu @XMM[4], 0x30($out) + lea 0x40($out), $out + + movdqa 0x40(%rsp), @XMM[7] # next iteration tweak + jmp .Lxts_dec_done +.align 16 +.Lxts_dec_3: + pxor @XMM[8+1], @XMM[1] + lea 0x30($inp), $inp + pxor @XMM[8+2], @XMM[2] + lea 0x80(%rsp), %rax # pass key schedule + mov %edx, %r10d # pass rounds + + call _bsaes_decrypt8 + + pxor 0x00(%rsp), @XMM[0] # ^= tweak[] + pxor 0x10(%rsp), @XMM[1] + movdqu @XMM[0], 0x00($out) # write output + pxor 0x20(%rsp), @XMM[6] + movdqu @XMM[1], 0x10($out) + movdqu @XMM[6], 0x20($out) + lea 0x30($out), $out + + movdqa 0x30(%rsp), @XMM[7] # next iteration tweak + jmp .Lxts_dec_done +.align 16 +.Lxts_dec_2: + pxor @XMM[8+0], @XMM[0] + lea 0x20($inp), $inp + pxor @XMM[8+1], @XMM[1] + lea 0x80(%rsp), %rax # pass key schedule + mov %edx, %r10d # pass rounds + + call _bsaes_decrypt8 + + pxor 0x00(%rsp), @XMM[0] # ^= tweak[] + pxor 0x10(%rsp), @XMM[1] + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + lea 0x20($out), $out + + movdqa 0x20(%rsp), @XMM[7] # next iteration tweak + jmp .Lxts_dec_done +.align 16 +.Lxts_dec_1: + pxor @XMM[0], @XMM[8] + lea 0x10($inp), $inp + movdqa @XMM[8], 0x20(%rbp) + lea 0x20(%rbp), $arg1 + lea 0x20(%rbp), $arg2 + lea ($key), $arg3 + call asm_AES_decrypt # doesn't touch %xmm + pxor 0x20(%rbp), @XMM[0] # ^= tweak[] + #pxor @XMM[8], @XMM[0] + #lea 0x80(%rsp), %rax # pass key schedule + #mov %edx, %r10d # pass rounds + #call _bsaes_decrypt8 + #pxor 0x00(%rsp), @XMM[0] # ^= tweak[] + movdqu @XMM[0], 0x00($out) # write output + lea 0x10($out), $out + + movdqa 0x10(%rsp), @XMM[7] # next iteration tweak + +.Lxts_dec_done: + and \$15, %ebx + jz .Lxts_dec_ret + + pxor $twtmp, $twtmp + movdqa .Lxts_magic(%rip), $twmask + pcmpgtd @XMM[7], $twtmp + pshufd \$0x13, $twtmp, $twres + movdqa @XMM[7], @XMM[6] + paddq @XMM[7], @XMM[7] # psllq 1,$tweak + pand $twmask, $twres # isolate carry and residue + movdqu ($inp), @XMM[0] + pxor $twres, @XMM[7] + + lea 0x20(%rbp), $arg1 + pxor @XMM[7], @XMM[0] + lea 0x20(%rbp), $arg2 + movdqa @XMM[0], 0x20(%rbp) + lea ($key), $arg3 + call asm_AES_decrypt # doesn't touch %xmm + pxor 0x20(%rbp), @XMM[7] + mov $out, %rdx + movdqu @XMM[7], ($out) + +.Lxts_dec_steal: + movzb 16($inp), %eax + movzb (%rdx), %ecx + lea 1($inp), $inp + mov %al, (%rdx) + mov %cl, 16(%rdx) + lea 1(%rdx), %rdx + sub \$1,%ebx + jnz .Lxts_dec_steal + + movdqu ($out), @XMM[0] + lea 0x20(%rbp), $arg1 + pxor @XMM[6], @XMM[0] + lea 0x20(%rbp), $arg2 + movdqa @XMM[0], 0x20(%rbp) + lea ($key), $arg3 + call asm_AES_decrypt # doesn't touch %xmm + pxor 0x20(%rbp), @XMM[6] + movdqu @XMM[6], ($out) + +.Lxts_dec_ret: + lea (%rsp), %rax + pxor %xmm0, %xmm0 +.Lxts_dec_bzero: # wipe key schedule [if any] + movdqa %xmm0, 0x00(%rax) + movdqa %xmm0, 0x10(%rax) + lea 0x20(%rax), %rax + cmp %rax, %rbp + ja .Lxts_dec_bzero + + lea (%rbp),%rsp # restore %rsp +___ +$code.=<<___ if ($win64); + movaps 0x40(%rbp), %xmm6 + movaps 0x50(%rbp), %xmm7 + movaps 0x60(%rbp), %xmm8 + movaps 0x70(%rbp), %xmm9 + movaps 0x80(%rbp), %xmm10 + movaps 0x90(%rbp), %xmm11 + movaps 0xa0(%rbp), %xmm12 + movaps 0xb0(%rbp), %xmm13 + movaps 0xc0(%rbp), %xmm14 + movaps 0xd0(%rbp), %xmm15 + lea 0xa0(%rbp), %rsp +___ +$code.=<<___; + mov 0x48(%rsp), %r15 + mov 0x50(%rsp), %r14 + mov 0x58(%rsp), %r13 + mov 0x60(%rsp), %r12 + mov 0x68(%rsp), %rbx + mov 0x70(%rsp), %rax + lea 0x78(%rsp), %rsp + mov %rax, %rbp +.Lxts_dec_epilogue: + ret +.size bsaes_xts_decrypt,.-bsaes_xts_decrypt +___ +} +$code.=<<___; +.type _bsaes_const,\@object +.align 64 +_bsaes_const: +.LM0ISR: # InvShiftRows constants + .quad 0x0a0e0206070b0f03, 0x0004080c0d010509 +.LISRM0: + .quad 0x01040b0e0205080f, 0x0306090c00070a0d +.LISR: + .quad 0x0504070602010003, 0x0f0e0d0c080b0a09 +.LBS0: # bit-slice constants + .quad 0x5555555555555555, 0x5555555555555555 +.LBS1: + .quad 0x3333333333333333, 0x3333333333333333 +.LBS2: + .quad 0x0f0f0f0f0f0f0f0f, 0x0f0f0f0f0f0f0f0f +.LSR: # shiftrows constants + .quad 0x0504070600030201, 0x0f0e0d0c0a09080b +.LSRM0: + .quad 0x0304090e00050a0f, 0x01060b0c0207080d +.LM0SR: + .quad 0x0a0e02060f03070b, 0x0004080c05090d01 +.LSWPUP: # byte-swap upper dword + .quad 0x0706050403020100, 0x0c0d0e0f0b0a0908 +.LSWPUPM0SR: + .quad 0x0a0d02060c03070b, 0x0004080f05090e01 +.LADD1: # counter increment constants + .quad 0x0000000000000000, 0x0000000100000000 +.LADD2: + .quad 0x0000000000000000, 0x0000000200000000 +.LADD3: + .quad 0x0000000000000000, 0x0000000300000000 +.LADD4: + .quad 0x0000000000000000, 0x0000000400000000 +.LADD5: + .quad 0x0000000000000000, 0x0000000500000000 +.LADD6: + .quad 0x0000000000000000, 0x0000000600000000 +.LADD7: + .quad 0x0000000000000000, 0x0000000700000000 +.LADD8: + .quad 0x0000000000000000, 0x0000000800000000 +.Lxts_magic: + .long 0x87,0,1,0 +.Lmasks: + .quad 0x0101010101010101, 0x0101010101010101 + .quad 0x0202020202020202, 0x0202020202020202 + .quad 0x0404040404040404, 0x0404040404040404 + .quad 0x0808080808080808, 0x0808080808080808 +.LM0: + .quad 0x02060a0e03070b0f, 0x0004080c0105090d +.L63: + .quad 0x6363636363636363, 0x6363636363636363 +.asciz "Bit-sliced AES for x86_64/SSSE3, Emilia Käsper, Peter Schwabe, Andy Polyakov" +.align 64 +.size _bsaes_const,.-_bsaes_const +___ + +# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame, +# CONTEXT *context,DISPATCHER_CONTEXT *disp) +if ($win64) { +$rec="%rcx"; +$frame="%rdx"; +$context="%r8"; +$disp="%r9"; + +$code.=<<___; +.extern __imp_RtlVirtualUnwind +.type se_handler,\@abi-omnipotent +.align 16 +se_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + mov 8($disp),%rsi # disp->ImageBase + mov 56($disp),%r11 # disp->HandlerData + + mov 0(%r11),%r10d # HandlerData[0] + lea (%rsi,%r10),%r10 # prologue label + cmp %r10,%rbx # context->RipRsp + + mov 4(%r11),%r10d # HandlerData[1] + lea (%rsi,%r10),%r10 # epilogue label + cmp %r10,%rbx # context->Rip>=epilogue label + jae .Lin_prologue + + mov 160($context),%rax # pull context->Rbp + + lea 0x40(%rax),%rsi # %xmm save area + lea 512($context),%rdi # &context.Xmm6 + mov \$20,%ecx # 10*sizeof(%xmm0)/sizeof(%rax) + .long 0xa548f3fc # cld; rep movsq + lea 0xa0(%rax),%rax # adjust stack pointer + + mov 0x70(%rax),%rbp + mov 0x68(%rax),%rbx + mov 0x60(%rax),%r12 + mov 0x58(%rax),%r13 + mov 0x50(%rax),%r14 + mov 0x48(%rax),%r15 + lea 0x78(%rax),%rax # adjust stack pointer + mov %rbx,144($context) # restore context->Rbx + mov %rbp,160($context) # restore context->Rbp + mov %r12,216($context) # restore context->R12 + mov %r13,224($context) # restore context->R13 + mov %r14,232($context) # restore context->R14 + mov %r15,240($context) # restore context->R15 + +.Lin_prologue: + mov %rax,152($context) # restore context->Rsp + + mov 40($disp),%rdi # disp->ContextRecord + mov $context,%rsi # context + mov \$`1232/8`,%ecx # sizeof(CONTEXT) + .long 0xa548f3fc # cld; rep movsq + + mov $disp,%rsi + xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER + mov 8(%rsi),%rdx # arg2, disp->ImageBase + mov 0(%rsi),%r8 # arg3, disp->ControlPc + mov 16(%rsi),%r9 # arg4, disp->FunctionEntry + mov 40(%rsi),%r10 # disp->ContextRecord + lea 56(%rsi),%r11 # &disp->HandlerData + lea 24(%rsi),%r12 # &disp->EstablisherFrame + mov %r10,32(%rsp) # arg5 + mov %r11,40(%rsp) # arg6 + mov %r12,48(%rsp) # arg7 + mov %rcx,56(%rsp) # arg8, (NULL) + call *__imp_RtlVirtualUnwind(%rip) + + mov \$1,%eax # ExceptionContinueSearch + add \$64,%rsp + popfq + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + pop %rdi + pop %rsi + ret +.size se_handler,.-se_handler + +.section .pdata +.align 4 +___ +$code.=<<___ if ($ecb); + .rva .Lecb_enc_prologue + .rva .Lecb_enc_epilogue + .rva .Lecb_enc_info + + .rva .Lecb_dec_prologue + .rva .Lecb_dec_epilogue + .rva .Lecb_dec_info +___ +$code.=<<___; + .rva .Lcbc_dec_prologue + .rva .Lcbc_dec_epilogue + .rva .Lcbc_dec_info + + .rva .Lctr_enc_prologue + .rva .Lctr_enc_epilogue + .rva .Lctr_enc_info + + .rva .Lxts_enc_prologue + .rva .Lxts_enc_epilogue + .rva .Lxts_enc_info + + .rva .Lxts_dec_prologue + .rva .Lxts_dec_epilogue + .rva .Lxts_dec_info + +.section .xdata +.align 8 +___ +$code.=<<___ if ($ecb); +.Lecb_enc_info: + .byte 9,0,0,0 + .rva se_handler + .rva .Lecb_enc_body,.Lecb_enc_epilogue # HandlerData[] +.Lecb_dec_info: + .byte 9,0,0,0 + .rva se_handler + .rva .Lecb_dec_body,.Lecb_dec_epilogue # HandlerData[] +___ +$code.=<<___; +.Lcbc_dec_info: + .byte 9,0,0,0 + .rva se_handler + .rva .Lcbc_dec_body,.Lcbc_dec_epilogue # HandlerData[] +.Lctr_enc_info: + .byte 9,0,0,0 + .rva se_handler + .rva .Lctr_enc_body,.Lctr_enc_epilogue # HandlerData[] +.Lxts_enc_info: + .byte 9,0,0,0 + .rva se_handler + .rva .Lxts_enc_body,.Lxts_enc_epilogue # HandlerData[] +.Lxts_dec_info: + .byte 9,0,0,0 + .rva se_handler + .rva .Lxts_dec_body,.Lxts_dec_epilogue # HandlerData[] +___ +} + +$code =~ s/\`([^\`]*)\`/eval($1)/gem; + +print $code; + +close STDOUT; diff --git a/external/boringssl/crypto/aes/asm/vpaes-x86.pl b/external/boringssl/crypto/aes/asm/vpaes-x86.pl new file mode 100644 index 0000000000..2ba149c3f9 --- /dev/null +++ b/external/boringssl/crypto/aes/asm/vpaes-x86.pl @@ -0,0 +1,903 @@ +#!/usr/bin/env perl + +###################################################################### +## Constant-time SSSE3 AES core implementation. +## version 0.1 +## +## By Mike Hamburg (Stanford University), 2009 +## Public domain. +## +## For details see http://shiftleft.org/papers/vector_aes/ and +## http://crypto.stanford.edu/vpaes/. + +###################################################################### +# September 2011. +# +# Port vpaes-x86_64.pl as 32-bit "almost" drop-in replacement for +# aes-586.pl. "Almost" refers to the fact that AES_cbc_encrypt +# doesn't handle partial vectors (doesn't have to if called from +# EVP only). "Drop-in" implies that this module doesn't share key +# schedule structure with the original nor does it make assumption +# about its alignment... +# +# Performance summary. aes-586.pl column lists large-block CBC +# encrypt/decrypt/with-hyper-threading-off(*) results in cycles per +# byte processed with 128-bit key, and vpaes-x86.pl column - [also +# large-block CBC] encrypt/decrypt. +# +# aes-586.pl vpaes-x86.pl +# +# Core 2(**) 28.1/41.4/18.3 21.9/25.2(***) +# Nehalem 27.9/40.4/18.1 10.2/11.9 +# Atom 70.7/92.1/60.1 61.1/75.4(***) +# Silvermont 45.4/62.9/24.1 49.2/61.1(***) +# +# (*) "Hyper-threading" in the context refers rather to cache shared +# among multiple cores, than to specifically Intel HTT. As vast +# majority of contemporary cores share cache, slower code path +# is common place. In other words "with-hyper-threading-off" +# results are presented mostly for reference purposes. +# +# (**) "Core 2" refers to initial 65nm design, a.k.a. Conroe. +# +# (***) Less impressive improvement on Core 2 and Atom is due to slow +# pshufb, yet it's respectable +28%/64% improvement on Core 2 +# and +15% on Atom (as implied, over "hyper-threading-safe" +# code path). +# +# + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +push(@INC,"${dir}","${dir}../../perlasm"); +require "x86asm.pl"; + +&asm_init($ARGV[0],"vpaes-x86.pl",$x86only = $ARGV[$#ARGV] eq "386"); + +$PREFIX="vpaes"; + +my ($round, $base, $magic, $key, $const, $inp, $out)= + ("eax", "ebx", "ecx", "edx","ebp", "esi","edi"); + +&static_label("_vpaes_consts"); +&static_label("_vpaes_schedule_low_round"); + +&set_label("_vpaes_consts",64); +$k_inv=-0x30; # inv, inva + &data_word(0x0D080180,0x0E05060F,0x0A0B0C02,0x04070309); + &data_word(0x0F0B0780,0x01040A06,0x02050809,0x030D0E0C); + +$k_s0F=-0x10; # s0F + &data_word(0x0F0F0F0F,0x0F0F0F0F,0x0F0F0F0F,0x0F0F0F0F); + +$k_ipt=0x00; # input transform (lo, hi) + &data_word(0x5A2A7000,0xC2B2E898,0x52227808,0xCABAE090); + &data_word(0x317C4D00,0x4C01307D,0xB0FDCC81,0xCD80B1FC); + +$k_sb1=0x20; # sb1u, sb1t + &data_word(0xCB503E00,0xB19BE18F,0x142AF544,0xA5DF7A6E); + &data_word(0xFAE22300,0x3618D415,0x0D2ED9EF,0x3BF7CCC1); +$k_sb2=0x40; # sb2u, sb2t + &data_word(0x0B712400,0xE27A93C6,0xBC982FCD,0x5EB7E955); + &data_word(0x0AE12900,0x69EB8840,0xAB82234A,0xC2A163C8); +$k_sbo=0x60; # sbou, sbot + &data_word(0x6FBDC700,0xD0D26D17,0xC502A878,0x15AABF7A); + &data_word(0x5FBB6A00,0xCFE474A5,0x412B35FA,0x8E1E90D1); + +$k_mc_forward=0x80; # mc_forward + &data_word(0x00030201,0x04070605,0x080B0A09,0x0C0F0E0D); + &data_word(0x04070605,0x080B0A09,0x0C0F0E0D,0x00030201); + &data_word(0x080B0A09,0x0C0F0E0D,0x00030201,0x04070605); + &data_word(0x0C0F0E0D,0x00030201,0x04070605,0x080B0A09); + +$k_mc_backward=0xc0; # mc_backward + &data_word(0x02010003,0x06050407,0x0A09080B,0x0E0D0C0F); + &data_word(0x0E0D0C0F,0x02010003,0x06050407,0x0A09080B); + &data_word(0x0A09080B,0x0E0D0C0F,0x02010003,0x06050407); + &data_word(0x06050407,0x0A09080B,0x0E0D0C0F,0x02010003); + +$k_sr=0x100; # sr + &data_word(0x03020100,0x07060504,0x0B0A0908,0x0F0E0D0C); + &data_word(0x0F0A0500,0x030E0904,0x07020D08,0x0B06010C); + &data_word(0x0B020900,0x0F060D04,0x030A0108,0x070E050C); + &data_word(0x070A0D00,0x0B0E0104,0x0F020508,0x0306090C); + +$k_rcon=0x140; # rcon + &data_word(0xAF9DEEB6,0x1F8391B9,0x4D7C7D81,0x702A9808); + +$k_s63=0x150; # s63: all equal to 0x63 transformed + &data_word(0x5B5B5B5B,0x5B5B5B5B,0x5B5B5B5B,0x5B5B5B5B); + +$k_opt=0x160; # output transform + &data_word(0xD6B66000,0xFF9F4929,0xDEBE6808,0xF7974121); + &data_word(0x50BCEC00,0x01EDBD51,0xB05C0CE0,0xE10D5DB1); + +$k_deskew=0x180; # deskew tables: inverts the sbox's "skew" + &data_word(0x47A4E300,0x07E4A340,0x5DBEF91A,0x1DFEB95A); + &data_word(0x83EA6900,0x5F36B5DC,0xF49D1E77,0x2841C2AB); +## +## Decryption stuff +## Key schedule constants +## +$k_dksd=0x1a0; # decryption key schedule: invskew x*D + &data_word(0xA3E44700,0xFEB91A5D,0x5A1DBEF9,0x0740E3A4); + &data_word(0xB5368300,0x41C277F4,0xAB289D1E,0x5FDC69EA); +$k_dksb=0x1c0; # decryption key schedule: invskew x*B + &data_word(0x8550D500,0x9A4FCA1F,0x1CC94C99,0x03D65386); + &data_word(0xB6FC4A00,0x115BEDA7,0x7E3482C8,0xD993256F); +$k_dkse=0x1e0; # decryption key schedule: invskew x*E + 0x63 + &data_word(0x1FC9D600,0xD5031CCA,0x994F5086,0x53859A4C); + &data_word(0x4FDC7BE8,0xA2319605,0x20B31487,0xCD5EF96A); +$k_dks9=0x200; # decryption key schedule: invskew x*9 + &data_word(0x7ED9A700,0xB6116FC8,0x82255BFC,0x4AED9334); + &data_word(0x27143300,0x45765162,0xE9DAFDCE,0x8BB89FAC); + +## +## Decryption stuff +## Round function constants +## +$k_dipt=0x220; # decryption input transform + &data_word(0x0B545F00,0x0F505B04,0x114E451A,0x154A411E); + &data_word(0x60056500,0x86E383E6,0xF491F194,0x12771772); + +$k_dsb9=0x240; # decryption sbox output *9*u, *9*t + &data_word(0x9A86D600,0x851C0353,0x4F994CC9,0xCAD51F50); + &data_word(0xECD74900,0xC03B1789,0xB2FBA565,0x725E2C9E); +$k_dsbd=0x260; # decryption sbox output *D*u, *D*t + &data_word(0xE6B1A200,0x7D57CCDF,0x882A4439,0xF56E9B13); + &data_word(0x24C6CB00,0x3CE2FAF7,0x15DEEFD3,0x2931180D); +$k_dsbb=0x280; # decryption sbox output *B*u, *B*t + &data_word(0x96B44200,0xD0226492,0xB0F2D404,0x602646F6); + &data_word(0xCD596700,0xC19498A6,0x3255AA6B,0xF3FF0C3E); +$k_dsbe=0x2a0; # decryption sbox output *E*u, *E*t + &data_word(0x26D4D000,0x46F29296,0x64B4F6B0,0x22426004); + &data_word(0xFFAAC100,0x0C55A6CD,0x98593E32,0x9467F36B); +$k_dsbo=0x2c0; # decryption sbox final output + &data_word(0x7EF94000,0x1387EA53,0xD4943E2D,0xC7AA6DB9); + &data_word(0x93441D00,0x12D7560F,0xD8C58E9C,0xCA4B8159); +&asciz ("Vector Permutation AES for x86/SSSE3, Mike Hamburg (Stanford University)"); +&align (64); + +&function_begin_B("_vpaes_preheat"); + &add ($const,&DWP(0,"esp")); + &movdqa ("xmm7",&QWP($k_inv,$const)); + &movdqa ("xmm6",&QWP($k_s0F,$const)); + &ret (); +&function_end_B("_vpaes_preheat"); + +## +## _aes_encrypt_core +## +## AES-encrypt %xmm0. +## +## Inputs: +## %xmm0 = input +## %xmm6-%xmm7 as in _vpaes_preheat +## (%edx) = scheduled keys +## +## Output in %xmm0 +## Clobbers %xmm1-%xmm5, %eax, %ebx, %ecx, %edx +## +## +&function_begin_B("_vpaes_encrypt_core"); + &mov ($magic,16); + &mov ($round,&DWP(240,$key)); + &movdqa ("xmm1","xmm6") + &movdqa ("xmm2",&QWP($k_ipt,$const)); + &pandn ("xmm1","xmm0"); + &pand ("xmm0","xmm6"); + &movdqu ("xmm5",&QWP(0,$key)); + &pshufb ("xmm2","xmm0"); + &movdqa ("xmm0",&QWP($k_ipt+16,$const)); + &pxor ("xmm2","xmm5"); + &psrld ("xmm1",4); + &add ($key,16); + &pshufb ("xmm0","xmm1"); + &lea ($base,&DWP($k_mc_backward,$const)); + &pxor ("xmm0","xmm2"); + &jmp (&label("enc_entry")); + + +&set_label("enc_loop",16); + # middle of middle round + &movdqa ("xmm4",&QWP($k_sb1,$const)); # 4 : sb1u + &movdqa ("xmm0",&QWP($k_sb1+16,$const));# 0 : sb1t + &pshufb ("xmm4","xmm2"); # 4 = sb1u + &pshufb ("xmm0","xmm3"); # 0 = sb1t + &pxor ("xmm4","xmm5"); # 4 = sb1u + k + &movdqa ("xmm5",&QWP($k_sb2,$const)); # 4 : sb2u + &pxor ("xmm0","xmm4"); # 0 = A + &movdqa ("xmm1",&QWP(-0x40,$base,$magic));# .Lk_mc_forward[] + &pshufb ("xmm5","xmm2"); # 4 = sb2u + &movdqa ("xmm2",&QWP($k_sb2+16,$const));# 2 : sb2t + &movdqa ("xmm4",&QWP(0,$base,$magic)); # .Lk_mc_backward[] + &pshufb ("xmm2","xmm3"); # 2 = sb2t + &movdqa ("xmm3","xmm0"); # 3 = A + &pxor ("xmm2","xmm5"); # 2 = 2A + &pshufb ("xmm0","xmm1"); # 0 = B + &add ($key,16); # next key + &pxor ("xmm0","xmm2"); # 0 = 2A+B + &pshufb ("xmm3","xmm4"); # 3 = D + &add ($magic,16); # next mc + &pxor ("xmm3","xmm0"); # 3 = 2A+B+D + &pshufb ("xmm0","xmm1"); # 0 = 2B+C + &and ($magic,0x30); # ... mod 4 + &sub ($round,1); # nr-- + &pxor ("xmm0","xmm3"); # 0 = 2A+3B+C+D + +&set_label("enc_entry"); + # top of round + &movdqa ("xmm1","xmm6"); # 1 : i + &movdqa ("xmm5",&QWP($k_inv+16,$const));# 2 : a/k + &pandn ("xmm1","xmm0"); # 1 = i<<4 + &psrld ("xmm1",4); # 1 = i + &pand ("xmm0","xmm6"); # 0 = k + &pshufb ("xmm5","xmm0"); # 2 = a/k + &movdqa ("xmm3","xmm7"); # 3 : 1/i + &pxor ("xmm0","xmm1"); # 0 = j + &pshufb ("xmm3","xmm1"); # 3 = 1/i + &movdqa ("xmm4","xmm7"); # 4 : 1/j + &pxor ("xmm3","xmm5"); # 3 = iak = 1/i + a/k + &pshufb ("xmm4","xmm0"); # 4 = 1/j + &movdqa ("xmm2","xmm7"); # 2 : 1/iak + &pxor ("xmm4","xmm5"); # 4 = jak = 1/j + a/k + &pshufb ("xmm2","xmm3"); # 2 = 1/iak + &movdqa ("xmm3","xmm7"); # 3 : 1/jak + &pxor ("xmm2","xmm0"); # 2 = io + &pshufb ("xmm3","xmm4"); # 3 = 1/jak + &movdqu ("xmm5",&QWP(0,$key)); + &pxor ("xmm3","xmm1"); # 3 = jo + &jnz (&label("enc_loop")); + + # middle of last round + &movdqa ("xmm4",&QWP($k_sbo,$const)); # 3 : sbou .Lk_sbo + &movdqa ("xmm0",&QWP($k_sbo+16,$const));# 3 : sbot .Lk_sbo+16 + &pshufb ("xmm4","xmm2"); # 4 = sbou + &pxor ("xmm4","xmm5"); # 4 = sb1u + k + &pshufb ("xmm0","xmm3"); # 0 = sb1t + &movdqa ("xmm1",&QWP(0x40,$base,$magic));# .Lk_sr[] + &pxor ("xmm0","xmm4"); # 0 = A + &pshufb ("xmm0","xmm1"); + &ret (); +&function_end_B("_vpaes_encrypt_core"); + +## +## Decryption core +## +## Same API as encryption core. +## +&function_begin_B("_vpaes_decrypt_core"); + &lea ($base,&DWP($k_dsbd,$const)); + &mov ($round,&DWP(240,$key)); + &movdqa ("xmm1","xmm6"); + &movdqa ("xmm2",&QWP($k_dipt-$k_dsbd,$base)); + &pandn ("xmm1","xmm0"); + &mov ($magic,$round); + &psrld ("xmm1",4) + &movdqu ("xmm5",&QWP(0,$key)); + &shl ($magic,4); + &pand ("xmm0","xmm6"); + &pshufb ("xmm2","xmm0"); + &movdqa ("xmm0",&QWP($k_dipt-$k_dsbd+16,$base)); + &xor ($magic,0x30); + &pshufb ("xmm0","xmm1"); + &and ($magic,0x30); + &pxor ("xmm2","xmm5"); + &movdqa ("xmm5",&QWP($k_mc_forward+48,$const)); + &pxor ("xmm0","xmm2"); + &add ($key,16); + &lea ($magic,&DWP($k_sr-$k_dsbd,$base,$magic)); + &jmp (&label("dec_entry")); + +&set_label("dec_loop",16); +## +## Inverse mix columns +## + &movdqa ("xmm4",&QWP(-0x20,$base)); # 4 : sb9u + &movdqa ("xmm1",&QWP(-0x10,$base)); # 0 : sb9t + &pshufb ("xmm4","xmm2"); # 4 = sb9u + &pshufb ("xmm1","xmm3"); # 0 = sb9t + &pxor ("xmm0","xmm4"); + &movdqa ("xmm4",&QWP(0,$base)); # 4 : sbdu + &pxor ("xmm0","xmm1"); # 0 = ch + &movdqa ("xmm1",&QWP(0x10,$base)); # 0 : sbdt + + &pshufb ("xmm4","xmm2"); # 4 = sbdu + &pshufb ("xmm0","xmm5"); # MC ch + &pshufb ("xmm1","xmm3"); # 0 = sbdt + &pxor ("xmm0","xmm4"); # 4 = ch + &movdqa ("xmm4",&QWP(0x20,$base)); # 4 : sbbu + &pxor ("xmm0","xmm1"); # 0 = ch + &movdqa ("xmm1",&QWP(0x30,$base)); # 0 : sbbt + + &pshufb ("xmm4","xmm2"); # 4 = sbbu + &pshufb ("xmm0","xmm5"); # MC ch + &pshufb ("xmm1","xmm3"); # 0 = sbbt + &pxor ("xmm0","xmm4"); # 4 = ch + &movdqa ("xmm4",&QWP(0x40,$base)); # 4 : sbeu + &pxor ("xmm0","xmm1"); # 0 = ch + &movdqa ("xmm1",&QWP(0x50,$base)); # 0 : sbet + + &pshufb ("xmm4","xmm2"); # 4 = sbeu + &pshufb ("xmm0","xmm5"); # MC ch + &pshufb ("xmm1","xmm3"); # 0 = sbet + &pxor ("xmm0","xmm4"); # 4 = ch + &add ($key,16); # next round key + &palignr("xmm5","xmm5",12); + &pxor ("xmm0","xmm1"); # 0 = ch + &sub ($round,1); # nr-- + +&set_label("dec_entry"); + # top of round + &movdqa ("xmm1","xmm6"); # 1 : i + &movdqa ("xmm2",&QWP($k_inv+16,$const));# 2 : a/k + &pandn ("xmm1","xmm0"); # 1 = i<<4 + &pand ("xmm0","xmm6"); # 0 = k + &psrld ("xmm1",4); # 1 = i + &pshufb ("xmm2","xmm0"); # 2 = a/k + &movdqa ("xmm3","xmm7"); # 3 : 1/i + &pxor ("xmm0","xmm1"); # 0 = j + &pshufb ("xmm3","xmm1"); # 3 = 1/i + &movdqa ("xmm4","xmm7"); # 4 : 1/j + &pxor ("xmm3","xmm2"); # 3 = iak = 1/i + a/k + &pshufb ("xmm4","xmm0"); # 4 = 1/j + &pxor ("xmm4","xmm2"); # 4 = jak = 1/j + a/k + &movdqa ("xmm2","xmm7"); # 2 : 1/iak + &pshufb ("xmm2","xmm3"); # 2 = 1/iak + &movdqa ("xmm3","xmm7"); # 3 : 1/jak + &pxor ("xmm2","xmm0"); # 2 = io + &pshufb ("xmm3","xmm4"); # 3 = 1/jak + &movdqu ("xmm0",&QWP(0,$key)); + &pxor ("xmm3","xmm1"); # 3 = jo + &jnz (&label("dec_loop")); + + # middle of last round + &movdqa ("xmm4",&QWP(0x60,$base)); # 3 : sbou + &pshufb ("xmm4","xmm2"); # 4 = sbou + &pxor ("xmm4","xmm0"); # 4 = sb1u + k + &movdqa ("xmm0",&QWP(0x70,$base)); # 0 : sbot + &movdqa ("xmm2",&QWP(0,$magic)); + &pshufb ("xmm0","xmm3"); # 0 = sb1t + &pxor ("xmm0","xmm4"); # 0 = A + &pshufb ("xmm0","xmm2"); + &ret (); +&function_end_B("_vpaes_decrypt_core"); + +######################################################## +## ## +## AES key schedule ## +## ## +######################################################## +&function_begin_B("_vpaes_schedule_core"); + &add ($const,&DWP(0,"esp")); + &movdqu ("xmm0",&QWP(0,$inp)); # load key (unaligned) + &movdqa ("xmm2",&QWP($k_rcon,$const)); # load rcon + + # input transform + &movdqa ("xmm3","xmm0"); + &lea ($base,&DWP($k_ipt,$const)); + &movdqa (&QWP(4,"esp"),"xmm2"); # xmm8 + &call ("_vpaes_schedule_transform"); + &movdqa ("xmm7","xmm0"); + + &test ($out,$out); + &jnz (&label("schedule_am_decrypting")); + + # encrypting, output zeroth round key after transform + &movdqu (&QWP(0,$key),"xmm0"); + &jmp (&label("schedule_go")); + +&set_label("schedule_am_decrypting"); + # decrypting, output zeroth round key after shiftrows + &movdqa ("xmm1",&QWP($k_sr,$const,$magic)); + &pshufb ("xmm3","xmm1"); + &movdqu (&QWP(0,$key),"xmm3"); + &xor ($magic,0x30); + +&set_label("schedule_go"); + &cmp ($round,192); + &ja (&label("schedule_256")); + &je (&label("schedule_192")); + # 128: fall though + +## +## .schedule_128 +## +## 128-bit specific part of key schedule. +## +## This schedule is really simple, because all its parts +## are accomplished by the subroutines. +## +&set_label("schedule_128"); + &mov ($round,10); + +&set_label("loop_schedule_128"); + &call ("_vpaes_schedule_round"); + &dec ($round); + &jz (&label("schedule_mangle_last")); + &call ("_vpaes_schedule_mangle"); # write output + &jmp (&label("loop_schedule_128")); + +## +## .aes_schedule_192 +## +## 192-bit specific part of key schedule. +## +## The main body of this schedule is the same as the 128-bit +## schedule, but with more smearing. The long, high side is +## stored in %xmm7 as before, and the short, low side is in +## the high bits of %xmm6. +## +## This schedule is somewhat nastier, however, because each +## round produces 192 bits of key material, or 1.5 round keys. +## Therefore, on each cycle we do 2 rounds and produce 3 round +## keys. +## +&set_label("schedule_192",16); + &movdqu ("xmm0",&QWP(8,$inp)); # load key part 2 (very unaligned) + &call ("_vpaes_schedule_transform"); # input transform + &movdqa ("xmm6","xmm0"); # save short part + &pxor ("xmm4","xmm4"); # clear 4 + &movhlps("xmm6","xmm4"); # clobber low side with zeros + &mov ($round,4); + +&set_label("loop_schedule_192"); + &call ("_vpaes_schedule_round"); + &palignr("xmm0","xmm6",8); + &call ("_vpaes_schedule_mangle"); # save key n + &call ("_vpaes_schedule_192_smear"); + &call ("_vpaes_schedule_mangle"); # save key n+1 + &call ("_vpaes_schedule_round"); + &dec ($round); + &jz (&label("schedule_mangle_last")); + &call ("_vpaes_schedule_mangle"); # save key n+2 + &call ("_vpaes_schedule_192_smear"); + &jmp (&label("loop_schedule_192")); + +## +## .aes_schedule_256 +## +## 256-bit specific part of key schedule. +## +## The structure here is very similar to the 128-bit +## schedule, but with an additional "low side" in +## %xmm6. The low side's rounds are the same as the +## high side's, except no rcon and no rotation. +## +&set_label("schedule_256",16); + &movdqu ("xmm0",&QWP(16,$inp)); # load key part 2 (unaligned) + &call ("_vpaes_schedule_transform"); # input transform + &mov ($round,7); + +&set_label("loop_schedule_256"); + &call ("_vpaes_schedule_mangle"); # output low result + &movdqa ("xmm6","xmm0"); # save cur_lo in xmm6 + + # high round + &call ("_vpaes_schedule_round"); + &dec ($round); + &jz (&label("schedule_mangle_last")); + &call ("_vpaes_schedule_mangle"); + + # low round. swap xmm7 and xmm6 + &pshufd ("xmm0","xmm0",0xFF); + &movdqa (&QWP(20,"esp"),"xmm7"); + &movdqa ("xmm7","xmm6"); + &call ("_vpaes_schedule_low_round"); + &movdqa ("xmm7",&QWP(20,"esp")); + + &jmp (&label("loop_schedule_256")); + +## +## .aes_schedule_mangle_last +## +## Mangler for last round of key schedule +## Mangles %xmm0 +## when encrypting, outputs out(%xmm0) ^ 63 +## when decrypting, outputs unskew(%xmm0) +## +## Always called right before return... jumps to cleanup and exits +## +&set_label("schedule_mangle_last",16); + # schedule last round key from xmm0 + &lea ($base,&DWP($k_deskew,$const)); + &test ($out,$out); + &jnz (&label("schedule_mangle_last_dec")); + + # encrypting + &movdqa ("xmm1",&QWP($k_sr,$const,$magic)); + &pshufb ("xmm0","xmm1"); # output permute + &lea ($base,&DWP($k_opt,$const)); # prepare to output transform + &add ($key,32); + +&set_label("schedule_mangle_last_dec"); + &add ($key,-16); + &pxor ("xmm0",&QWP($k_s63,$const)); + &call ("_vpaes_schedule_transform"); # output transform + &movdqu (&QWP(0,$key),"xmm0"); # save last key + + # cleanup + &pxor ("xmm0","xmm0"); + &pxor ("xmm1","xmm1"); + &pxor ("xmm2","xmm2"); + &pxor ("xmm3","xmm3"); + &pxor ("xmm4","xmm4"); + &pxor ("xmm5","xmm5"); + &pxor ("xmm6","xmm6"); + &pxor ("xmm7","xmm7"); + &ret (); +&function_end_B("_vpaes_schedule_core"); + +## +## .aes_schedule_192_smear +## +## Smear the short, low side in the 192-bit key schedule. +## +## Inputs: +## %xmm7: high side, b a x y +## %xmm6: low side, d c 0 0 +## %xmm13: 0 +## +## Outputs: +## %xmm6: b+c+d b+c 0 0 +## %xmm0: b+c+d b+c b a +## +&function_begin_B("_vpaes_schedule_192_smear"); + &pshufd ("xmm1","xmm6",0x80); # d c 0 0 -> c 0 0 0 + &pshufd ("xmm0","xmm7",0xFE); # b a _ _ -> b b b a + &pxor ("xmm6","xmm1"); # -> c+d c 0 0 + &pxor ("xmm1","xmm1"); + &pxor ("xmm6","xmm0"); # -> b+c+d b+c b a + &movdqa ("xmm0","xmm6"); + &movhlps("xmm6","xmm1"); # clobber low side with zeros + &ret (); +&function_end_B("_vpaes_schedule_192_smear"); + +## +## .aes_schedule_round +## +## Runs one main round of the key schedule on %xmm0, %xmm7 +## +## Specifically, runs subbytes on the high dword of %xmm0 +## then rotates it by one byte and xors into the low dword of +## %xmm7. +## +## Adds rcon from low byte of %xmm8, then rotates %xmm8 for +## next rcon. +## +## Smears the dwords of %xmm7 by xoring the low into the +## second low, result into third, result into highest. +## +## Returns results in %xmm7 = %xmm0. +## Clobbers %xmm1-%xmm5. +## +&function_begin_B("_vpaes_schedule_round"); + # extract rcon from xmm8 + &movdqa ("xmm2",&QWP(8,"esp")); # xmm8 + &pxor ("xmm1","xmm1"); + &palignr("xmm1","xmm2",15); + &palignr("xmm2","xmm2",15); + &pxor ("xmm7","xmm1"); + + # rotate + &pshufd ("xmm0","xmm0",0xFF); + &palignr("xmm0","xmm0",1); + + # fall through... + &movdqa (&QWP(8,"esp"),"xmm2"); # xmm8 + + # low round: same as high round, but no rotation and no rcon. +&set_label("_vpaes_schedule_low_round"); + # smear xmm7 + &movdqa ("xmm1","xmm7"); + &pslldq ("xmm7",4); + &pxor ("xmm7","xmm1"); + &movdqa ("xmm1","xmm7"); + &pslldq ("xmm7",8); + &pxor ("xmm7","xmm1"); + &pxor ("xmm7",&QWP($k_s63,$const)); + + # subbyte + &movdqa ("xmm4",&QWP($k_s0F,$const)); + &movdqa ("xmm5",&QWP($k_inv,$const)); # 4 : 1/j + &movdqa ("xmm1","xmm4"); + &pandn ("xmm1","xmm0"); + &psrld ("xmm1",4); # 1 = i + &pand ("xmm0","xmm4"); # 0 = k + &movdqa ("xmm2",&QWP($k_inv+16,$const));# 2 : a/k + &pshufb ("xmm2","xmm0"); # 2 = a/k + &pxor ("xmm0","xmm1"); # 0 = j + &movdqa ("xmm3","xmm5"); # 3 : 1/i + &pshufb ("xmm3","xmm1"); # 3 = 1/i + &pxor ("xmm3","xmm2"); # 3 = iak = 1/i + a/k + &movdqa ("xmm4","xmm5"); # 4 : 1/j + &pshufb ("xmm4","xmm0"); # 4 = 1/j + &pxor ("xmm4","xmm2"); # 4 = jak = 1/j + a/k + &movdqa ("xmm2","xmm5"); # 2 : 1/iak + &pshufb ("xmm2","xmm3"); # 2 = 1/iak + &pxor ("xmm2","xmm0"); # 2 = io + &movdqa ("xmm3","xmm5"); # 3 : 1/jak + &pshufb ("xmm3","xmm4"); # 3 = 1/jak + &pxor ("xmm3","xmm1"); # 3 = jo + &movdqa ("xmm4",&QWP($k_sb1,$const)); # 4 : sbou + &pshufb ("xmm4","xmm2"); # 4 = sbou + &movdqa ("xmm0",&QWP($k_sb1+16,$const));# 0 : sbot + &pshufb ("xmm0","xmm3"); # 0 = sb1t + &pxor ("xmm0","xmm4"); # 0 = sbox output + + # add in smeared stuff + &pxor ("xmm0","xmm7"); + &movdqa ("xmm7","xmm0"); + &ret (); +&function_end_B("_vpaes_schedule_round"); + +## +## .aes_schedule_transform +## +## Linear-transform %xmm0 according to tables at (%ebx) +## +## Output in %xmm0 +## Clobbers %xmm1, %xmm2 +## +&function_begin_B("_vpaes_schedule_transform"); + &movdqa ("xmm2",&QWP($k_s0F,$const)); + &movdqa ("xmm1","xmm2"); + &pandn ("xmm1","xmm0"); + &psrld ("xmm1",4); + &pand ("xmm0","xmm2"); + &movdqa ("xmm2",&QWP(0,$base)); + &pshufb ("xmm2","xmm0"); + &movdqa ("xmm0",&QWP(16,$base)); + &pshufb ("xmm0","xmm1"); + &pxor ("xmm0","xmm2"); + &ret (); +&function_end_B("_vpaes_schedule_transform"); + +## +## .aes_schedule_mangle +## +## Mangle xmm0 from (basis-transformed) standard version +## to our version. +## +## On encrypt, +## xor with 0x63 +## multiply by circulant 0,1,1,1 +## apply shiftrows transform +## +## On decrypt, +## xor with 0x63 +## multiply by "inverse mixcolumns" circulant E,B,D,9 +## deskew +## apply shiftrows transform +## +## +## Writes out to (%edx), and increments or decrements it +## Keeps track of round number mod 4 in %ecx +## Preserves xmm0 +## Clobbers xmm1-xmm5 +## +&function_begin_B("_vpaes_schedule_mangle"); + &movdqa ("xmm4","xmm0"); # save xmm0 for later + &movdqa ("xmm5",&QWP($k_mc_forward,$const)); + &test ($out,$out); + &jnz (&label("schedule_mangle_dec")); + + # encrypting + &add ($key,16); + &pxor ("xmm4",&QWP($k_s63,$const)); + &pshufb ("xmm4","xmm5"); + &movdqa ("xmm3","xmm4"); + &pshufb ("xmm4","xmm5"); + &pxor ("xmm3","xmm4"); + &pshufb ("xmm4","xmm5"); + &pxor ("xmm3","xmm4"); + + &jmp (&label("schedule_mangle_both")); + +&set_label("schedule_mangle_dec",16); + # inverse mix columns + &movdqa ("xmm2",&QWP($k_s0F,$const)); + &lea ($inp,&DWP($k_dksd,$const)); + &movdqa ("xmm1","xmm2"); + &pandn ("xmm1","xmm4"); + &psrld ("xmm1",4); # 1 = hi + &pand ("xmm4","xmm2"); # 4 = lo + + &movdqa ("xmm2",&QWP(0,$inp)); + &pshufb ("xmm2","xmm4"); + &movdqa ("xmm3",&QWP(0x10,$inp)); + &pshufb ("xmm3","xmm1"); + &pxor ("xmm3","xmm2"); + &pshufb ("xmm3","xmm5"); + + &movdqa ("xmm2",&QWP(0x20,$inp)); + &pshufb ("xmm2","xmm4"); + &pxor ("xmm2","xmm3"); + &movdqa ("xmm3",&QWP(0x30,$inp)); + &pshufb ("xmm3","xmm1"); + &pxor ("xmm3","xmm2"); + &pshufb ("xmm3","xmm5"); + + &movdqa ("xmm2",&QWP(0x40,$inp)); + &pshufb ("xmm2","xmm4"); + &pxor ("xmm2","xmm3"); + &movdqa ("xmm3",&QWP(0x50,$inp)); + &pshufb ("xmm3","xmm1"); + &pxor ("xmm3","xmm2"); + &pshufb ("xmm3","xmm5"); + + &movdqa ("xmm2",&QWP(0x60,$inp)); + &pshufb ("xmm2","xmm4"); + &pxor ("xmm2","xmm3"); + &movdqa ("xmm3",&QWP(0x70,$inp)); + &pshufb ("xmm3","xmm1"); + &pxor ("xmm3","xmm2"); + + &add ($key,-16); + +&set_label("schedule_mangle_both"); + &movdqa ("xmm1",&QWP($k_sr,$const,$magic)); + &pshufb ("xmm3","xmm1"); + &add ($magic,-16); + &and ($magic,0x30); + &movdqu (&QWP(0,$key),"xmm3"); + &ret (); +&function_end_B("_vpaes_schedule_mangle"); + +# +# Interface to OpenSSL +# +&function_begin("${PREFIX}_set_encrypt_key"); + &mov ($inp,&wparam(0)); # inp + &lea ($base,&DWP(-56,"esp")); + &mov ($round,&wparam(1)); # bits + &and ($base,-16); + &mov ($key,&wparam(2)); # key + &xchg ($base,"esp"); # alloca + &mov (&DWP(48,"esp"),$base); + + &mov ($base,$round); + &shr ($base,5); + &add ($base,5); + &mov (&DWP(240,$key),$base); # AES_KEY->rounds = nbits/32+5; + &mov ($magic,0x30); + &mov ($out,0); + + &lea ($const,&DWP(&label("_vpaes_consts")."+0x30-".&label("pic_point"))); + &call ("_vpaes_schedule_core"); +&set_label("pic_point"); + + &mov ("esp",&DWP(48,"esp")); + &xor ("eax","eax"); +&function_end("${PREFIX}_set_encrypt_key"); + +&function_begin("${PREFIX}_set_decrypt_key"); + &mov ($inp,&wparam(0)); # inp + &lea ($base,&DWP(-56,"esp")); + &mov ($round,&wparam(1)); # bits + &and ($base,-16); + &mov ($key,&wparam(2)); # key + &xchg ($base,"esp"); # alloca + &mov (&DWP(48,"esp"),$base); + + &mov ($base,$round); + &shr ($base,5); + &add ($base,5); + &mov (&DWP(240,$key),$base); # AES_KEY->rounds = nbits/32+5; + &shl ($base,4); + &lea ($key,&DWP(16,$key,$base)); + + &mov ($out,1); + &mov ($magic,$round); + &shr ($magic,1); + &and ($magic,32); + &xor ($magic,32); # nbist==192?0:32; + + &lea ($const,&DWP(&label("_vpaes_consts")."+0x30-".&label("pic_point"))); + &call ("_vpaes_schedule_core"); +&set_label("pic_point"); + + &mov ("esp",&DWP(48,"esp")); + &xor ("eax","eax"); +&function_end("${PREFIX}_set_decrypt_key"); + +&function_begin("${PREFIX}_encrypt"); + &lea ($const,&DWP(&label("_vpaes_consts")."+0x30-".&label("pic_point"))); + &call ("_vpaes_preheat"); +&set_label("pic_point"); + &mov ($inp,&wparam(0)); # inp + &lea ($base,&DWP(-56,"esp")); + &mov ($out,&wparam(1)); # out + &and ($base,-16); + &mov ($key,&wparam(2)); # key + &xchg ($base,"esp"); # alloca + &mov (&DWP(48,"esp"),$base); + + &movdqu ("xmm0",&QWP(0,$inp)); + &call ("_vpaes_encrypt_core"); + &movdqu (&QWP(0,$out),"xmm0"); + + &mov ("esp",&DWP(48,"esp")); +&function_end("${PREFIX}_encrypt"); + +&function_begin("${PREFIX}_decrypt"); + &lea ($const,&DWP(&label("_vpaes_consts")."+0x30-".&label("pic_point"))); + &call ("_vpaes_preheat"); +&set_label("pic_point"); + &mov ($inp,&wparam(0)); # inp + &lea ($base,&DWP(-56,"esp")); + &mov ($out,&wparam(1)); # out + &and ($base,-16); + &mov ($key,&wparam(2)); # key + &xchg ($base,"esp"); # alloca + &mov (&DWP(48,"esp"),$base); + + &movdqu ("xmm0",&QWP(0,$inp)); + &call ("_vpaes_decrypt_core"); + &movdqu (&QWP(0,$out),"xmm0"); + + &mov ("esp",&DWP(48,"esp")); +&function_end("${PREFIX}_decrypt"); + +&function_begin("${PREFIX}_cbc_encrypt"); + &mov ($inp,&wparam(0)); # inp + &mov ($out,&wparam(1)); # out + &mov ($round,&wparam(2)); # len + &mov ($key,&wparam(3)); # key + &sub ($round,16); + &jc (&label("cbc_abort")); + &lea ($base,&DWP(-56,"esp")); + &mov ($const,&wparam(4)); # ivp + &and ($base,-16); + &mov ($magic,&wparam(5)); # enc + &xchg ($base,"esp"); # alloca + &movdqu ("xmm1",&QWP(0,$const)); # load IV + &sub ($out,$inp); + &mov (&DWP(48,"esp"),$base); + + &mov (&DWP(0,"esp"),$out); # save out + &mov (&DWP(4,"esp"),$key) # save key + &mov (&DWP(8,"esp"),$const); # save ivp + &mov ($out,$round); # $out works as $len + + &lea ($const,&DWP(&label("_vpaes_consts")."+0x30-".&label("pic_point"))); + &call ("_vpaes_preheat"); +&set_label("pic_point"); + &cmp ($magic,0); + &je (&label("cbc_dec_loop")); + &jmp (&label("cbc_enc_loop")); + +&set_label("cbc_enc_loop",16); + &movdqu ("xmm0",&QWP(0,$inp)); # load input + &pxor ("xmm0","xmm1"); # inp^=iv + &call ("_vpaes_encrypt_core"); + &mov ($base,&DWP(0,"esp")); # restore out + &mov ($key,&DWP(4,"esp")); # restore key + &movdqa ("xmm1","xmm0"); + &movdqu (&QWP(0,$base,$inp),"xmm0"); # write output + &lea ($inp,&DWP(16,$inp)); + &sub ($out,16); + &jnc (&label("cbc_enc_loop")); + &jmp (&label("cbc_done")); + +&set_label("cbc_dec_loop",16); + &movdqu ("xmm0",&QWP(0,$inp)); # load input + &movdqa (&QWP(16,"esp"),"xmm1"); # save IV + &movdqa (&QWP(32,"esp"),"xmm0"); # save future IV + &call ("_vpaes_decrypt_core"); + &mov ($base,&DWP(0,"esp")); # restore out + &mov ($key,&DWP(4,"esp")); # restore key + &pxor ("xmm0",&QWP(16,"esp")); # out^=iv + &movdqa ("xmm1",&QWP(32,"esp")); # load next IV + &movdqu (&QWP(0,$base,$inp),"xmm0"); # write output + &lea ($inp,&DWP(16,$inp)); + &sub ($out,16); + &jnc (&label("cbc_dec_loop")); + +&set_label("cbc_done"); + &mov ($base,&DWP(8,"esp")); # restore ivp + &mov ("esp",&DWP(48,"esp")); + &movdqu (&QWP(0,$base),"xmm1"); # write IV +&set_label("cbc_abort"); +&function_end("${PREFIX}_cbc_encrypt"); + +&asm_finish(); diff --git a/external/boringssl/crypto/aes/asm/vpaes-x86_64.pl b/external/boringssl/crypto/aes/asm/vpaes-x86_64.pl new file mode 100644 index 0000000000..f2ef318fae --- /dev/null +++ b/external/boringssl/crypto/aes/asm/vpaes-x86_64.pl @@ -0,0 +1,1207 @@ +#!/usr/bin/env perl + +###################################################################### +## Constant-time SSSE3 AES core implementation. +## version 0.1 +## +## By Mike Hamburg (Stanford University), 2009 +## Public domain. +## +## For details see http://shiftleft.org/papers/vector_aes/ and +## http://crypto.stanford.edu/vpaes/. + +###################################################################### +# September 2011. +# +# Interface to OpenSSL as "almost" drop-in replacement for +# aes-x86_64.pl. "Almost" refers to the fact that AES_cbc_encrypt +# doesn't handle partial vectors (doesn't have to if called from +# EVP only). "Drop-in" implies that this module doesn't share key +# schedule structure with the original nor does it make assumption +# about its alignment... +# +# Performance summary. aes-x86_64.pl column lists large-block CBC +# encrypt/decrypt/with-hyper-threading-off(*) results in cycles per +# byte processed with 128-bit key, and vpaes-x86_64.pl column - +# [also large-block CBC] encrypt/decrypt. +# +# aes-x86_64.pl vpaes-x86_64.pl +# +# Core 2(**) 29.6/41.1/14.3 21.9/25.2(***) +# Nehalem 29.6/40.3/14.6 10.0/11.8 +# Atom 57.3/74.2/32.1 60.9/77.2(***) +# Silvermont 52.7/64.0/19.5 48.8/60.8(***) +# +# (*) "Hyper-threading" in the context refers rather to cache shared +# among multiple cores, than to specifically Intel HTT. As vast +# majority of contemporary cores share cache, slower code path +# is common place. In other words "with-hyper-threading-off" +# results are presented mostly for reference purposes. +# +# (**) "Core 2" refers to initial 65nm design, a.k.a. Conroe. +# +# (***) Less impressive improvement on Core 2 and Atom is due to slow +# pshufb, yet it's respectable +36%/62% improvement on Core 2 +# (as implied, over "hyper-threading-safe" code path). +# +# + +$flavour = shift; +$output = shift; +if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } + +$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or +die "can't locate x86_64-xlate.pl"; + +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; + +$PREFIX="vpaes"; + +$code.=<<___; +.text + +## +## _aes_encrypt_core +## +## AES-encrypt %xmm0. +## +## Inputs: +## %xmm0 = input +## %xmm9-%xmm15 as in _vpaes_preheat +## (%rdx) = scheduled keys +## +## Output in %xmm0 +## Clobbers %xmm1-%xmm5, %r9, %r10, %r11, %rax +## Preserves %xmm6 - %xmm8 so you get some local vectors +## +## +.type _vpaes_encrypt_core,\@abi-omnipotent +.align 16 +_vpaes_encrypt_core: + mov %rdx, %r9 + mov \$16, %r11 + mov 240(%rdx),%eax + movdqa %xmm9, %xmm1 + movdqa .Lk_ipt(%rip), %xmm2 # iptlo + pandn %xmm0, %xmm1 + movdqu (%r9), %xmm5 # round0 key + psrld \$4, %xmm1 + pand %xmm9, %xmm0 + pshufb %xmm0, %xmm2 + movdqa .Lk_ipt+16(%rip), %xmm0 # ipthi + pshufb %xmm1, %xmm0 + pxor %xmm5, %xmm2 + add \$16, %r9 + pxor %xmm2, %xmm0 + lea .Lk_mc_backward(%rip),%r10 + jmp .Lenc_entry + +.align 16 +.Lenc_loop: + # middle of middle round + movdqa %xmm13, %xmm4 # 4 : sb1u + movdqa %xmm12, %xmm0 # 0 : sb1t + pshufb %xmm2, %xmm4 # 4 = sb1u + pshufb %xmm3, %xmm0 # 0 = sb1t + pxor %xmm5, %xmm4 # 4 = sb1u + k + movdqa %xmm15, %xmm5 # 4 : sb2u + pxor %xmm4, %xmm0 # 0 = A + movdqa -0x40(%r11,%r10), %xmm1 # .Lk_mc_forward[] + pshufb %xmm2, %xmm5 # 4 = sb2u + movdqa (%r11,%r10), %xmm4 # .Lk_mc_backward[] + movdqa %xmm14, %xmm2 # 2 : sb2t + pshufb %xmm3, %xmm2 # 2 = sb2t + movdqa %xmm0, %xmm3 # 3 = A + pxor %xmm5, %xmm2 # 2 = 2A + pshufb %xmm1, %xmm0 # 0 = B + add \$16, %r9 # next key + pxor %xmm2, %xmm0 # 0 = 2A+B + pshufb %xmm4, %xmm3 # 3 = D + add \$16, %r11 # next mc + pxor %xmm0, %xmm3 # 3 = 2A+B+D + pshufb %xmm1, %xmm0 # 0 = 2B+C + and \$0x30, %r11 # ... mod 4 + sub \$1,%rax # nr-- + pxor %xmm3, %xmm0 # 0 = 2A+3B+C+D + +.Lenc_entry: + # top of round + movdqa %xmm9, %xmm1 # 1 : i + movdqa %xmm11, %xmm5 # 2 : a/k + pandn %xmm0, %xmm1 # 1 = i<<4 + psrld \$4, %xmm1 # 1 = i + pand %xmm9, %xmm0 # 0 = k + pshufb %xmm0, %xmm5 # 2 = a/k + movdqa %xmm10, %xmm3 # 3 : 1/i + pxor %xmm1, %xmm0 # 0 = j + pshufb %xmm1, %xmm3 # 3 = 1/i + movdqa %xmm10, %xmm4 # 4 : 1/j + pxor %xmm5, %xmm3 # 3 = iak = 1/i + a/k + pshufb %xmm0, %xmm4 # 4 = 1/j + movdqa %xmm10, %xmm2 # 2 : 1/iak + pxor %xmm5, %xmm4 # 4 = jak = 1/j + a/k + pshufb %xmm3, %xmm2 # 2 = 1/iak + movdqa %xmm10, %xmm3 # 3 : 1/jak + pxor %xmm0, %xmm2 # 2 = io + pshufb %xmm4, %xmm3 # 3 = 1/jak + movdqu (%r9), %xmm5 + pxor %xmm1, %xmm3 # 3 = jo + jnz .Lenc_loop + + # middle of last round + movdqa -0x60(%r10), %xmm4 # 3 : sbou .Lk_sbo + movdqa -0x50(%r10), %xmm0 # 0 : sbot .Lk_sbo+16 + pshufb %xmm2, %xmm4 # 4 = sbou + pxor %xmm5, %xmm4 # 4 = sb1u + k + pshufb %xmm3, %xmm0 # 0 = sb1t + movdqa 0x40(%r11,%r10), %xmm1 # .Lk_sr[] + pxor %xmm4, %xmm0 # 0 = A + pshufb %xmm1, %xmm0 + ret +.size _vpaes_encrypt_core,.-_vpaes_encrypt_core + +## +## Decryption core +## +## Same API as encryption core. +## +.type _vpaes_decrypt_core,\@abi-omnipotent +.align 16 +_vpaes_decrypt_core: + mov %rdx, %r9 # load key + mov 240(%rdx),%eax + movdqa %xmm9, %xmm1 + movdqa .Lk_dipt(%rip), %xmm2 # iptlo + pandn %xmm0, %xmm1 + mov %rax, %r11 + psrld \$4, %xmm1 + movdqu (%r9), %xmm5 # round0 key + shl \$4, %r11 + pand %xmm9, %xmm0 + pshufb %xmm0, %xmm2 + movdqa .Lk_dipt+16(%rip), %xmm0 # ipthi + xor \$0x30, %r11 + lea .Lk_dsbd(%rip),%r10 + pshufb %xmm1, %xmm0 + and \$0x30, %r11 + pxor %xmm5, %xmm2 + movdqa .Lk_mc_forward+48(%rip), %xmm5 + pxor %xmm2, %xmm0 + add \$16, %r9 + add %r10, %r11 + jmp .Ldec_entry + +.align 16 +.Ldec_loop: +## +## Inverse mix columns +## + movdqa -0x20(%r10),%xmm4 # 4 : sb9u + movdqa -0x10(%r10),%xmm1 # 0 : sb9t + pshufb %xmm2, %xmm4 # 4 = sb9u + pshufb %xmm3, %xmm1 # 0 = sb9t + pxor %xmm4, %xmm0 + movdqa 0x00(%r10),%xmm4 # 4 : sbdu + pxor %xmm1, %xmm0 # 0 = ch + movdqa 0x10(%r10),%xmm1 # 0 : sbdt + + pshufb %xmm2, %xmm4 # 4 = sbdu + pshufb %xmm5, %xmm0 # MC ch + pshufb %xmm3, %xmm1 # 0 = sbdt + pxor %xmm4, %xmm0 # 4 = ch + movdqa 0x20(%r10),%xmm4 # 4 : sbbu + pxor %xmm1, %xmm0 # 0 = ch + movdqa 0x30(%r10),%xmm1 # 0 : sbbt + + pshufb %xmm2, %xmm4 # 4 = sbbu + pshufb %xmm5, %xmm0 # MC ch + pshufb %xmm3, %xmm1 # 0 = sbbt + pxor %xmm4, %xmm0 # 4 = ch + movdqa 0x40(%r10),%xmm4 # 4 : sbeu + pxor %xmm1, %xmm0 # 0 = ch + movdqa 0x50(%r10),%xmm1 # 0 : sbet + + pshufb %xmm2, %xmm4 # 4 = sbeu + pshufb %xmm5, %xmm0 # MC ch + pshufb %xmm3, %xmm1 # 0 = sbet + pxor %xmm4, %xmm0 # 4 = ch + add \$16, %r9 # next round key + palignr \$12, %xmm5, %xmm5 + pxor %xmm1, %xmm0 # 0 = ch + sub \$1,%rax # nr-- + +.Ldec_entry: + # top of round + movdqa %xmm9, %xmm1 # 1 : i + pandn %xmm0, %xmm1 # 1 = i<<4 + movdqa %xmm11, %xmm2 # 2 : a/k + psrld \$4, %xmm1 # 1 = i + pand %xmm9, %xmm0 # 0 = k + pshufb %xmm0, %xmm2 # 2 = a/k + movdqa %xmm10, %xmm3 # 3 : 1/i + pxor %xmm1, %xmm0 # 0 = j + pshufb %xmm1, %xmm3 # 3 = 1/i + movdqa %xmm10, %xmm4 # 4 : 1/j + pxor %xmm2, %xmm3 # 3 = iak = 1/i + a/k + pshufb %xmm0, %xmm4 # 4 = 1/j + pxor %xmm2, %xmm4 # 4 = jak = 1/j + a/k + movdqa %xmm10, %xmm2 # 2 : 1/iak + pshufb %xmm3, %xmm2 # 2 = 1/iak + movdqa %xmm10, %xmm3 # 3 : 1/jak + pxor %xmm0, %xmm2 # 2 = io + pshufb %xmm4, %xmm3 # 3 = 1/jak + movdqu (%r9), %xmm0 + pxor %xmm1, %xmm3 # 3 = jo + jnz .Ldec_loop + + # middle of last round + movdqa 0x60(%r10), %xmm4 # 3 : sbou + pshufb %xmm2, %xmm4 # 4 = sbou + pxor %xmm0, %xmm4 # 4 = sb1u + k + movdqa 0x70(%r10), %xmm0 # 0 : sbot + movdqa -0x160(%r11), %xmm2 # .Lk_sr-.Lk_dsbd=-0x160 + pshufb %xmm3, %xmm0 # 0 = sb1t + pxor %xmm4, %xmm0 # 0 = A + pshufb %xmm2, %xmm0 + ret +.size _vpaes_decrypt_core,.-_vpaes_decrypt_core + +######################################################## +## ## +## AES key schedule ## +## ## +######################################################## +.type _vpaes_schedule_core,\@abi-omnipotent +.align 16 +_vpaes_schedule_core: + # rdi = key + # rsi = size in bits + # rdx = buffer + # rcx = direction. 0=encrypt, 1=decrypt + + call _vpaes_preheat # load the tables + movdqa .Lk_rcon(%rip), %xmm8 # load rcon + movdqu (%rdi), %xmm0 # load key (unaligned) + + # input transform + movdqa %xmm0, %xmm3 + lea .Lk_ipt(%rip), %r11 + call _vpaes_schedule_transform + movdqa %xmm0, %xmm7 + + lea .Lk_sr(%rip),%r10 + test %rcx, %rcx + jnz .Lschedule_am_decrypting + + # encrypting, output zeroth round key after transform + movdqu %xmm0, (%rdx) + jmp .Lschedule_go + +.Lschedule_am_decrypting: + # decrypting, output zeroth round key after shiftrows + movdqa (%r8,%r10),%xmm1 + pshufb %xmm1, %xmm3 + movdqu %xmm3, (%rdx) + xor \$0x30, %r8 + +.Lschedule_go: + cmp \$192, %esi + ja .Lschedule_256 + je .Lschedule_192 + # 128: fall though + +## +## .schedule_128 +## +## 128-bit specific part of key schedule. +## +## This schedule is really simple, because all its parts +## are accomplished by the subroutines. +## +.Lschedule_128: + mov \$10, %esi + +.Loop_schedule_128: + call _vpaes_schedule_round + dec %rsi + jz .Lschedule_mangle_last + call _vpaes_schedule_mangle # write output + jmp .Loop_schedule_128 + +## +## .aes_schedule_192 +## +## 192-bit specific part of key schedule. +## +## The main body of this schedule is the same as the 128-bit +## schedule, but with more smearing. The long, high side is +## stored in %xmm7 as before, and the short, low side is in +## the high bits of %xmm6. +## +## This schedule is somewhat nastier, however, because each +## round produces 192 bits of key material, or 1.5 round keys. +## Therefore, on each cycle we do 2 rounds and produce 3 round +## keys. +## +.align 16 +.Lschedule_192: + movdqu 8(%rdi),%xmm0 # load key part 2 (very unaligned) + call _vpaes_schedule_transform # input transform + movdqa %xmm0, %xmm6 # save short part + pxor %xmm4, %xmm4 # clear 4 + movhlps %xmm4, %xmm6 # clobber low side with zeros + mov \$4, %esi + +.Loop_schedule_192: + call _vpaes_schedule_round + palignr \$8,%xmm6,%xmm0 + call _vpaes_schedule_mangle # save key n + call _vpaes_schedule_192_smear + call _vpaes_schedule_mangle # save key n+1 + call _vpaes_schedule_round + dec %rsi + jz .Lschedule_mangle_last + call _vpaes_schedule_mangle # save key n+2 + call _vpaes_schedule_192_smear + jmp .Loop_schedule_192 + +## +## .aes_schedule_256 +## +## 256-bit specific part of key schedule. +## +## The structure here is very similar to the 128-bit +## schedule, but with an additional "low side" in +## %xmm6. The low side's rounds are the same as the +## high side's, except no rcon and no rotation. +## +.align 16 +.Lschedule_256: + movdqu 16(%rdi),%xmm0 # load key part 2 (unaligned) + call _vpaes_schedule_transform # input transform + mov \$7, %esi + +.Loop_schedule_256: + call _vpaes_schedule_mangle # output low result + movdqa %xmm0, %xmm6 # save cur_lo in xmm6 + + # high round + call _vpaes_schedule_round + dec %rsi + jz .Lschedule_mangle_last + call _vpaes_schedule_mangle + + # low round. swap xmm7 and xmm6 + pshufd \$0xFF, %xmm0, %xmm0 + movdqa %xmm7, %xmm5 + movdqa %xmm6, %xmm7 + call _vpaes_schedule_low_round + movdqa %xmm5, %xmm7 + + jmp .Loop_schedule_256 + + +## +## .aes_schedule_mangle_last +## +## Mangler for last round of key schedule +## Mangles %xmm0 +## when encrypting, outputs out(%xmm0) ^ 63 +## when decrypting, outputs unskew(%xmm0) +## +## Always called right before return... jumps to cleanup and exits +## +.align 16 +.Lschedule_mangle_last: + # schedule last round key from xmm0 + lea .Lk_deskew(%rip),%r11 # prepare to deskew + test %rcx, %rcx + jnz .Lschedule_mangle_last_dec + + # encrypting + movdqa (%r8,%r10),%xmm1 + pshufb %xmm1, %xmm0 # output permute + lea .Lk_opt(%rip), %r11 # prepare to output transform + add \$32, %rdx + +.Lschedule_mangle_last_dec: + add \$-16, %rdx + pxor .Lk_s63(%rip), %xmm0 + call _vpaes_schedule_transform # output transform + movdqu %xmm0, (%rdx) # save last key + + # cleanup + pxor %xmm0, %xmm0 + pxor %xmm1, %xmm1 + pxor %xmm2, %xmm2 + pxor %xmm3, %xmm3 + pxor %xmm4, %xmm4 + pxor %xmm5, %xmm5 + pxor %xmm6, %xmm6 + pxor %xmm7, %xmm7 + ret +.size _vpaes_schedule_core,.-_vpaes_schedule_core + +## +## .aes_schedule_192_smear +## +## Smear the short, low side in the 192-bit key schedule. +## +## Inputs: +## %xmm7: high side, b a x y +## %xmm6: low side, d c 0 0 +## %xmm13: 0 +## +## Outputs: +## %xmm6: b+c+d b+c 0 0 +## %xmm0: b+c+d b+c b a +## +.type _vpaes_schedule_192_smear,\@abi-omnipotent +.align 16 +_vpaes_schedule_192_smear: + pshufd \$0x80, %xmm6, %xmm1 # d c 0 0 -> c 0 0 0 + pshufd \$0xFE, %xmm7, %xmm0 # b a _ _ -> b b b a + pxor %xmm1, %xmm6 # -> c+d c 0 0 + pxor %xmm1, %xmm1 + pxor %xmm0, %xmm6 # -> b+c+d b+c b a + movdqa %xmm6, %xmm0 + movhlps %xmm1, %xmm6 # clobber low side with zeros + ret +.size _vpaes_schedule_192_smear,.-_vpaes_schedule_192_smear + +## +## .aes_schedule_round +## +## Runs one main round of the key schedule on %xmm0, %xmm7 +## +## Specifically, runs subbytes on the high dword of %xmm0 +## then rotates it by one byte and xors into the low dword of +## %xmm7. +## +## Adds rcon from low byte of %xmm8, then rotates %xmm8 for +## next rcon. +## +## Smears the dwords of %xmm7 by xoring the low into the +## second low, result into third, result into highest. +## +## Returns results in %xmm7 = %xmm0. +## Clobbers %xmm1-%xmm4, %r11. +## +.type _vpaes_schedule_round,\@abi-omnipotent +.align 16 +_vpaes_schedule_round: + # extract rcon from xmm8 + pxor %xmm1, %xmm1 + palignr \$15, %xmm8, %xmm1 + palignr \$15, %xmm8, %xmm8 + pxor %xmm1, %xmm7 + + # rotate + pshufd \$0xFF, %xmm0, %xmm0 + palignr \$1, %xmm0, %xmm0 + + # fall through... + + # low round: same as high round, but no rotation and no rcon. +_vpaes_schedule_low_round: + # smear xmm7 + movdqa %xmm7, %xmm1 + pslldq \$4, %xmm7 + pxor %xmm1, %xmm7 + movdqa %xmm7, %xmm1 + pslldq \$8, %xmm7 + pxor %xmm1, %xmm7 + pxor .Lk_s63(%rip), %xmm7 + + # subbytes + movdqa %xmm9, %xmm1 + pandn %xmm0, %xmm1 + psrld \$4, %xmm1 # 1 = i + pand %xmm9, %xmm0 # 0 = k + movdqa %xmm11, %xmm2 # 2 : a/k + pshufb %xmm0, %xmm2 # 2 = a/k + pxor %xmm1, %xmm0 # 0 = j + movdqa %xmm10, %xmm3 # 3 : 1/i + pshufb %xmm1, %xmm3 # 3 = 1/i + pxor %xmm2, %xmm3 # 3 = iak = 1/i + a/k + movdqa %xmm10, %xmm4 # 4 : 1/j + pshufb %xmm0, %xmm4 # 4 = 1/j + pxor %xmm2, %xmm4 # 4 = jak = 1/j + a/k + movdqa %xmm10, %xmm2 # 2 : 1/iak + pshufb %xmm3, %xmm2 # 2 = 1/iak + pxor %xmm0, %xmm2 # 2 = io + movdqa %xmm10, %xmm3 # 3 : 1/jak + pshufb %xmm4, %xmm3 # 3 = 1/jak + pxor %xmm1, %xmm3 # 3 = jo + movdqa %xmm13, %xmm4 # 4 : sbou + pshufb %xmm2, %xmm4 # 4 = sbou + movdqa %xmm12, %xmm0 # 0 : sbot + pshufb %xmm3, %xmm0 # 0 = sb1t + pxor %xmm4, %xmm0 # 0 = sbox output + + # add in smeared stuff + pxor %xmm7, %xmm0 + movdqa %xmm0, %xmm7 + ret +.size _vpaes_schedule_round,.-_vpaes_schedule_round + +## +## .aes_schedule_transform +## +## Linear-transform %xmm0 according to tables at (%r11) +## +## Requires that %xmm9 = 0x0F0F... as in preheat +## Output in %xmm0 +## Clobbers %xmm1, %xmm2 +## +.type _vpaes_schedule_transform,\@abi-omnipotent +.align 16 +_vpaes_schedule_transform: + movdqa %xmm9, %xmm1 + pandn %xmm0, %xmm1 + psrld \$4, %xmm1 + pand %xmm9, %xmm0 + movdqa (%r11), %xmm2 # lo + pshufb %xmm0, %xmm2 + movdqa 16(%r11), %xmm0 # hi + pshufb %xmm1, %xmm0 + pxor %xmm2, %xmm0 + ret +.size _vpaes_schedule_transform,.-_vpaes_schedule_transform + +## +## .aes_schedule_mangle +## +## Mangle xmm0 from (basis-transformed) standard version +## to our version. +## +## On encrypt, +## xor with 0x63 +## multiply by circulant 0,1,1,1 +## apply shiftrows transform +## +## On decrypt, +## xor with 0x63 +## multiply by "inverse mixcolumns" circulant E,B,D,9 +## deskew +## apply shiftrows transform +## +## +## Writes out to (%rdx), and increments or decrements it +## Keeps track of round number mod 4 in %r8 +## Preserves xmm0 +## Clobbers xmm1-xmm5 +## +.type _vpaes_schedule_mangle,\@abi-omnipotent +.align 16 +_vpaes_schedule_mangle: + movdqa %xmm0, %xmm4 # save xmm0 for later + movdqa .Lk_mc_forward(%rip),%xmm5 + test %rcx, %rcx + jnz .Lschedule_mangle_dec + + # encrypting + add \$16, %rdx + pxor .Lk_s63(%rip),%xmm4 + pshufb %xmm5, %xmm4 + movdqa %xmm4, %xmm3 + pshufb %xmm5, %xmm4 + pxor %xmm4, %xmm3 + pshufb %xmm5, %xmm4 + pxor %xmm4, %xmm3 + + jmp .Lschedule_mangle_both +.align 16 +.Lschedule_mangle_dec: + # inverse mix columns + lea .Lk_dksd(%rip),%r11 + movdqa %xmm9, %xmm1 + pandn %xmm4, %xmm1 + psrld \$4, %xmm1 # 1 = hi + pand %xmm9, %xmm4 # 4 = lo + + movdqa 0x00(%r11), %xmm2 + pshufb %xmm4, %xmm2 + movdqa 0x10(%r11), %xmm3 + pshufb %xmm1, %xmm3 + pxor %xmm2, %xmm3 + pshufb %xmm5, %xmm3 + + movdqa 0x20(%r11), %xmm2 + pshufb %xmm4, %xmm2 + pxor %xmm3, %xmm2 + movdqa 0x30(%r11), %xmm3 + pshufb %xmm1, %xmm3 + pxor %xmm2, %xmm3 + pshufb %xmm5, %xmm3 + + movdqa 0x40(%r11), %xmm2 + pshufb %xmm4, %xmm2 + pxor %xmm3, %xmm2 + movdqa 0x50(%r11), %xmm3 + pshufb %xmm1, %xmm3 + pxor %xmm2, %xmm3 + pshufb %xmm5, %xmm3 + + movdqa 0x60(%r11), %xmm2 + pshufb %xmm4, %xmm2 + pxor %xmm3, %xmm2 + movdqa 0x70(%r11), %xmm3 + pshufb %xmm1, %xmm3 + pxor %xmm2, %xmm3 + + add \$-16, %rdx + +.Lschedule_mangle_both: + movdqa (%r8,%r10),%xmm1 + pshufb %xmm1,%xmm3 + add \$-16, %r8 + and \$0x30, %r8 + movdqu %xmm3, (%rdx) + ret +.size _vpaes_schedule_mangle,.-_vpaes_schedule_mangle + +# +# Interface to OpenSSL +# +.globl ${PREFIX}_set_encrypt_key +.type ${PREFIX}_set_encrypt_key,\@function,3 +.align 16 +${PREFIX}_set_encrypt_key: +___ +$code.=<<___ if ($win64); + lea -0xb8(%rsp),%rsp + movaps %xmm6,0x10(%rsp) + movaps %xmm7,0x20(%rsp) + movaps %xmm8,0x30(%rsp) + movaps %xmm9,0x40(%rsp) + movaps %xmm10,0x50(%rsp) + movaps %xmm11,0x60(%rsp) + movaps %xmm12,0x70(%rsp) + movaps %xmm13,0x80(%rsp) + movaps %xmm14,0x90(%rsp) + movaps %xmm15,0xa0(%rsp) +.Lenc_key_body: +___ +$code.=<<___; + mov %esi,%eax + shr \$5,%eax + add \$5,%eax + mov %eax,240(%rdx) # AES_KEY->rounds = nbits/32+5; + + mov \$0,%ecx + mov \$0x30,%r8d + call _vpaes_schedule_core +___ +$code.=<<___ if ($win64); + movaps 0x10(%rsp),%xmm6 + movaps 0x20(%rsp),%xmm7 + movaps 0x30(%rsp),%xmm8 + movaps 0x40(%rsp),%xmm9 + movaps 0x50(%rsp),%xmm10 + movaps 0x60(%rsp),%xmm11 + movaps 0x70(%rsp),%xmm12 + movaps 0x80(%rsp),%xmm13 + movaps 0x90(%rsp),%xmm14 + movaps 0xa0(%rsp),%xmm15 + lea 0xb8(%rsp),%rsp +.Lenc_key_epilogue: +___ +$code.=<<___; + xor %eax,%eax + ret +.size ${PREFIX}_set_encrypt_key,.-${PREFIX}_set_encrypt_key + +.globl ${PREFIX}_set_decrypt_key +.type ${PREFIX}_set_decrypt_key,\@function,3 +.align 16 +${PREFIX}_set_decrypt_key: +___ +$code.=<<___ if ($win64); + lea -0xb8(%rsp),%rsp + movaps %xmm6,0x10(%rsp) + movaps %xmm7,0x20(%rsp) + movaps %xmm8,0x30(%rsp) + movaps %xmm9,0x40(%rsp) + movaps %xmm10,0x50(%rsp) + movaps %xmm11,0x60(%rsp) + movaps %xmm12,0x70(%rsp) + movaps %xmm13,0x80(%rsp) + movaps %xmm14,0x90(%rsp) + movaps %xmm15,0xa0(%rsp) +.Ldec_key_body: +___ +$code.=<<___; + mov %esi,%eax + shr \$5,%eax + add \$5,%eax + mov %eax,240(%rdx) # AES_KEY->rounds = nbits/32+5; + shl \$4,%eax + lea 16(%rdx,%rax),%rdx + + mov \$1,%ecx + mov %esi,%r8d + shr \$1,%r8d + and \$32,%r8d + xor \$32,%r8d # nbits==192?0:32 + call _vpaes_schedule_core +___ +$code.=<<___ if ($win64); + movaps 0x10(%rsp),%xmm6 + movaps 0x20(%rsp),%xmm7 + movaps 0x30(%rsp),%xmm8 + movaps 0x40(%rsp),%xmm9 + movaps 0x50(%rsp),%xmm10 + movaps 0x60(%rsp),%xmm11 + movaps 0x70(%rsp),%xmm12 + movaps 0x80(%rsp),%xmm13 + movaps 0x90(%rsp),%xmm14 + movaps 0xa0(%rsp),%xmm15 + lea 0xb8(%rsp),%rsp +.Ldec_key_epilogue: +___ +$code.=<<___; + xor %eax,%eax + ret +.size ${PREFIX}_set_decrypt_key,.-${PREFIX}_set_decrypt_key + +.globl ${PREFIX}_encrypt +.type ${PREFIX}_encrypt,\@function,3 +.align 16 +${PREFIX}_encrypt: +___ +$code.=<<___ if ($win64); + lea -0xb8(%rsp),%rsp + movaps %xmm6,0x10(%rsp) + movaps %xmm7,0x20(%rsp) + movaps %xmm8,0x30(%rsp) + movaps %xmm9,0x40(%rsp) + movaps %xmm10,0x50(%rsp) + movaps %xmm11,0x60(%rsp) + movaps %xmm12,0x70(%rsp) + movaps %xmm13,0x80(%rsp) + movaps %xmm14,0x90(%rsp) + movaps %xmm15,0xa0(%rsp) +.Lenc_body: +___ +$code.=<<___; + movdqu (%rdi),%xmm0 + call _vpaes_preheat + call _vpaes_encrypt_core + movdqu %xmm0,(%rsi) +___ +$code.=<<___ if ($win64); + movaps 0x10(%rsp),%xmm6 + movaps 0x20(%rsp),%xmm7 + movaps 0x30(%rsp),%xmm8 + movaps 0x40(%rsp),%xmm9 + movaps 0x50(%rsp),%xmm10 + movaps 0x60(%rsp),%xmm11 + movaps 0x70(%rsp),%xmm12 + movaps 0x80(%rsp),%xmm13 + movaps 0x90(%rsp),%xmm14 + movaps 0xa0(%rsp),%xmm15 + lea 0xb8(%rsp),%rsp +.Lenc_epilogue: +___ +$code.=<<___; + ret +.size ${PREFIX}_encrypt,.-${PREFIX}_encrypt + +.globl ${PREFIX}_decrypt +.type ${PREFIX}_decrypt,\@function,3 +.align 16 +${PREFIX}_decrypt: +___ +$code.=<<___ if ($win64); + lea -0xb8(%rsp),%rsp + movaps %xmm6,0x10(%rsp) + movaps %xmm7,0x20(%rsp) + movaps %xmm8,0x30(%rsp) + movaps %xmm9,0x40(%rsp) + movaps %xmm10,0x50(%rsp) + movaps %xmm11,0x60(%rsp) + movaps %xmm12,0x70(%rsp) + movaps %xmm13,0x80(%rsp) + movaps %xmm14,0x90(%rsp) + movaps %xmm15,0xa0(%rsp) +.Ldec_body: +___ +$code.=<<___; + movdqu (%rdi),%xmm0 + call _vpaes_preheat + call _vpaes_decrypt_core + movdqu %xmm0,(%rsi) +___ +$code.=<<___ if ($win64); + movaps 0x10(%rsp),%xmm6 + movaps 0x20(%rsp),%xmm7 + movaps 0x30(%rsp),%xmm8 + movaps 0x40(%rsp),%xmm9 + movaps 0x50(%rsp),%xmm10 + movaps 0x60(%rsp),%xmm11 + movaps 0x70(%rsp),%xmm12 + movaps 0x80(%rsp),%xmm13 + movaps 0x90(%rsp),%xmm14 + movaps 0xa0(%rsp),%xmm15 + lea 0xb8(%rsp),%rsp +.Ldec_epilogue: +___ +$code.=<<___; + ret +.size ${PREFIX}_decrypt,.-${PREFIX}_decrypt +___ +{ +my ($inp,$out,$len,$key,$ivp,$enc)=("%rdi","%rsi","%rdx","%rcx","%r8","%r9"); +# void AES_cbc_encrypt (const void char *inp, unsigned char *out, +# size_t length, const AES_KEY *key, +# unsigned char *ivp,const int enc); +$code.=<<___; +.globl ${PREFIX}_cbc_encrypt +.type ${PREFIX}_cbc_encrypt,\@function,6 +.align 16 +${PREFIX}_cbc_encrypt: + xchg $key,$len +___ +($len,$key)=($key,$len); +$code.=<<___; + sub \$16,$len + jc .Lcbc_abort +___ +$code.=<<___ if ($win64); + lea -0xb8(%rsp),%rsp + movaps %xmm6,0x10(%rsp) + movaps %xmm7,0x20(%rsp) + movaps %xmm8,0x30(%rsp) + movaps %xmm9,0x40(%rsp) + movaps %xmm10,0x50(%rsp) + movaps %xmm11,0x60(%rsp) + movaps %xmm12,0x70(%rsp) + movaps %xmm13,0x80(%rsp) + movaps %xmm14,0x90(%rsp) + movaps %xmm15,0xa0(%rsp) +.Lcbc_body: +___ +$code.=<<___; + movdqu ($ivp),%xmm6 # load IV + sub $inp,$out + call _vpaes_preheat + cmp \$0,${enc}d + je .Lcbc_dec_loop + jmp .Lcbc_enc_loop +.align 16 +.Lcbc_enc_loop: + movdqu ($inp),%xmm0 + pxor %xmm6,%xmm0 + call _vpaes_encrypt_core + movdqa %xmm0,%xmm6 + movdqu %xmm0,($out,$inp) + lea 16($inp),$inp + sub \$16,$len + jnc .Lcbc_enc_loop + jmp .Lcbc_done +.align 16 +.Lcbc_dec_loop: + movdqu ($inp),%xmm0 + movdqa %xmm0,%xmm7 + call _vpaes_decrypt_core + pxor %xmm6,%xmm0 + movdqa %xmm7,%xmm6 + movdqu %xmm0,($out,$inp) + lea 16($inp),$inp + sub \$16,$len + jnc .Lcbc_dec_loop +.Lcbc_done: + movdqu %xmm6,($ivp) # save IV +___ +$code.=<<___ if ($win64); + movaps 0x10(%rsp),%xmm6 + movaps 0x20(%rsp),%xmm7 + movaps 0x30(%rsp),%xmm8 + movaps 0x40(%rsp),%xmm9 + movaps 0x50(%rsp),%xmm10 + movaps 0x60(%rsp),%xmm11 + movaps 0x70(%rsp),%xmm12 + movaps 0x80(%rsp),%xmm13 + movaps 0x90(%rsp),%xmm14 + movaps 0xa0(%rsp),%xmm15 + lea 0xb8(%rsp),%rsp +.Lcbc_epilogue: +___ +$code.=<<___; +.Lcbc_abort: + ret +.size ${PREFIX}_cbc_encrypt,.-${PREFIX}_cbc_encrypt +___ +} +$code.=<<___; +## +## _aes_preheat +## +## Fills register %r10 -> .aes_consts (so you can -fPIC) +## and %xmm9-%xmm15 as specified below. +## +.type _vpaes_preheat,\@abi-omnipotent +.align 16 +_vpaes_preheat: + lea .Lk_s0F(%rip), %r10 + movdqa -0x20(%r10), %xmm10 # .Lk_inv + movdqa -0x10(%r10), %xmm11 # .Lk_inv+16 + movdqa 0x00(%r10), %xmm9 # .Lk_s0F + movdqa 0x30(%r10), %xmm13 # .Lk_sb1 + movdqa 0x40(%r10), %xmm12 # .Lk_sb1+16 + movdqa 0x50(%r10), %xmm15 # .Lk_sb2 + movdqa 0x60(%r10), %xmm14 # .Lk_sb2+16 + ret +.size _vpaes_preheat,.-_vpaes_preheat +######################################################## +## ## +## Constants ## +## ## +######################################################## +.type _vpaes_consts,\@object +.align 64 +_vpaes_consts: +.Lk_inv: # inv, inva + .quad 0x0E05060F0D080180, 0x040703090A0B0C02 + .quad 0x01040A060F0B0780, 0x030D0E0C02050809 + +.Lk_s0F: # s0F + .quad 0x0F0F0F0F0F0F0F0F, 0x0F0F0F0F0F0F0F0F + +.Lk_ipt: # input transform (lo, hi) + .quad 0xC2B2E8985A2A7000, 0xCABAE09052227808 + .quad 0x4C01307D317C4D00, 0xCD80B1FCB0FDCC81 + +.Lk_sb1: # sb1u, sb1t + .quad 0xB19BE18FCB503E00, 0xA5DF7A6E142AF544 + .quad 0x3618D415FAE22300, 0x3BF7CCC10D2ED9EF +.Lk_sb2: # sb2u, sb2t + .quad 0xE27A93C60B712400, 0x5EB7E955BC982FCD + .quad 0x69EB88400AE12900, 0xC2A163C8AB82234A +.Lk_sbo: # sbou, sbot + .quad 0xD0D26D176FBDC700, 0x15AABF7AC502A878 + .quad 0xCFE474A55FBB6A00, 0x8E1E90D1412B35FA + +.Lk_mc_forward: # mc_forward + .quad 0x0407060500030201, 0x0C0F0E0D080B0A09 + .quad 0x080B0A0904070605, 0x000302010C0F0E0D + .quad 0x0C0F0E0D080B0A09, 0x0407060500030201 + .quad 0x000302010C0F0E0D, 0x080B0A0904070605 + +.Lk_mc_backward:# mc_backward + .quad 0x0605040702010003, 0x0E0D0C0F0A09080B + .quad 0x020100030E0D0C0F, 0x0A09080B06050407 + .quad 0x0E0D0C0F0A09080B, 0x0605040702010003 + .quad 0x0A09080B06050407, 0x020100030E0D0C0F + +.Lk_sr: # sr + .quad 0x0706050403020100, 0x0F0E0D0C0B0A0908 + .quad 0x030E09040F0A0500, 0x0B06010C07020D08 + .quad 0x0F060D040B020900, 0x070E050C030A0108 + .quad 0x0B0E0104070A0D00, 0x0306090C0F020508 + +.Lk_rcon: # rcon + .quad 0x1F8391B9AF9DEEB6, 0x702A98084D7C7D81 + +.Lk_s63: # s63: all equal to 0x63 transformed + .quad 0x5B5B5B5B5B5B5B5B, 0x5B5B5B5B5B5B5B5B + +.Lk_opt: # output transform + .quad 0xFF9F4929D6B66000, 0xF7974121DEBE6808 + .quad 0x01EDBD5150BCEC00, 0xE10D5DB1B05C0CE0 + +.Lk_deskew: # deskew tables: inverts the sbox's "skew" + .quad 0x07E4A34047A4E300, 0x1DFEB95A5DBEF91A + .quad 0x5F36B5DC83EA6900, 0x2841C2ABF49D1E77 + +## +## Decryption stuff +## Key schedule constants +## +.Lk_dksd: # decryption key schedule: invskew x*D + .quad 0xFEB91A5DA3E44700, 0x0740E3A45A1DBEF9 + .quad 0x41C277F4B5368300, 0x5FDC69EAAB289D1E +.Lk_dksb: # decryption key schedule: invskew x*B + .quad 0x9A4FCA1F8550D500, 0x03D653861CC94C99 + .quad 0x115BEDA7B6FC4A00, 0xD993256F7E3482C8 +.Lk_dkse: # decryption key schedule: invskew x*E + 0x63 + .quad 0xD5031CCA1FC9D600, 0x53859A4C994F5086 + .quad 0xA23196054FDC7BE8, 0xCD5EF96A20B31487 +.Lk_dks9: # decryption key schedule: invskew x*9 + .quad 0xB6116FC87ED9A700, 0x4AED933482255BFC + .quad 0x4576516227143300, 0x8BB89FACE9DAFDCE + +## +## Decryption stuff +## Round function constants +## +.Lk_dipt: # decryption input transform + .quad 0x0F505B040B545F00, 0x154A411E114E451A + .quad 0x86E383E660056500, 0x12771772F491F194 + +.Lk_dsb9: # decryption sbox output *9*u, *9*t + .quad 0x851C03539A86D600, 0xCAD51F504F994CC9 + .quad 0xC03B1789ECD74900, 0x725E2C9EB2FBA565 +.Lk_dsbd: # decryption sbox output *D*u, *D*t + .quad 0x7D57CCDFE6B1A200, 0xF56E9B13882A4439 + .quad 0x3CE2FAF724C6CB00, 0x2931180D15DEEFD3 +.Lk_dsbb: # decryption sbox output *B*u, *B*t + .quad 0xD022649296B44200, 0x602646F6B0F2D404 + .quad 0xC19498A6CD596700, 0xF3FF0C3E3255AA6B +.Lk_dsbe: # decryption sbox output *E*u, *E*t + .quad 0x46F2929626D4D000, 0x2242600464B4F6B0 + .quad 0x0C55A6CDFFAAC100, 0x9467F36B98593E32 +.Lk_dsbo: # decryption sbox final output + .quad 0x1387EA537EF94000, 0xC7AA6DB9D4943E2D + .quad 0x12D7560F93441D00, 0xCA4B8159D8C58E9C +.asciz "Vector Permutation AES for x86_64/SSSE3, Mike Hamburg (Stanford University)" +.align 64 +.size _vpaes_consts,.-_vpaes_consts +___ + +if ($win64) { +# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame, +# CONTEXT *context,DISPATCHER_CONTEXT *disp) +$rec="%rcx"; +$frame="%rdx"; +$context="%r8"; +$disp="%r9"; + +$code.=<<___; +.extern __imp_RtlVirtualUnwind +.type se_handler,\@abi-omnipotent +.align 16 +se_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + mov 8($disp),%rsi # disp->ImageBase + mov 56($disp),%r11 # disp->HandlerData + + mov 0(%r11),%r10d # HandlerData[0] + lea (%rsi,%r10),%r10 # prologue label + cmp %r10,%rbx # context->RipRsp + + mov 4(%r11),%r10d # HandlerData[1] + lea (%rsi,%r10),%r10 # epilogue label + cmp %r10,%rbx # context->Rip>=epilogue label + jae .Lin_prologue + + lea 16(%rax),%rsi # %xmm save area + lea 512($context),%rdi # &context.Xmm6 + mov \$20,%ecx # 10*sizeof(%xmm0)/sizeof(%rax) + .long 0xa548f3fc # cld; rep movsq + lea 0xb8(%rax),%rax # adjust stack pointer + +.Lin_prologue: + mov 8(%rax),%rdi + mov 16(%rax),%rsi + mov %rax,152($context) # restore context->Rsp + mov %rsi,168($context) # restore context->Rsi + mov %rdi,176($context) # restore context->Rdi + + mov 40($disp),%rdi # disp->ContextRecord + mov $context,%rsi # context + mov \$`1232/8`,%ecx # sizeof(CONTEXT) + .long 0xa548f3fc # cld; rep movsq + + mov $disp,%rsi + xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER + mov 8(%rsi),%rdx # arg2, disp->ImageBase + mov 0(%rsi),%r8 # arg3, disp->ControlPc + mov 16(%rsi),%r9 # arg4, disp->FunctionEntry + mov 40(%rsi),%r10 # disp->ContextRecord + lea 56(%rsi),%r11 # &disp->HandlerData + lea 24(%rsi),%r12 # &disp->EstablisherFrame + mov %r10,32(%rsp) # arg5 + mov %r11,40(%rsp) # arg6 + mov %r12,48(%rsp) # arg7 + mov %rcx,56(%rsp) # arg8, (NULL) + call *__imp_RtlVirtualUnwind(%rip) + + mov \$1,%eax # ExceptionContinueSearch + add \$64,%rsp + popfq + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + pop %rdi + pop %rsi + ret +.size se_handler,.-se_handler + +.section .pdata +.align 4 + .rva .LSEH_begin_${PREFIX}_set_encrypt_key + .rva .LSEH_end_${PREFIX}_set_encrypt_key + .rva .LSEH_info_${PREFIX}_set_encrypt_key + + .rva .LSEH_begin_${PREFIX}_set_decrypt_key + .rva .LSEH_end_${PREFIX}_set_decrypt_key + .rva .LSEH_info_${PREFIX}_set_decrypt_key + + .rva .LSEH_begin_${PREFIX}_encrypt + .rva .LSEH_end_${PREFIX}_encrypt + .rva .LSEH_info_${PREFIX}_encrypt + + .rva .LSEH_begin_${PREFIX}_decrypt + .rva .LSEH_end_${PREFIX}_decrypt + .rva .LSEH_info_${PREFIX}_decrypt + + .rva .LSEH_begin_${PREFIX}_cbc_encrypt + .rva .LSEH_end_${PREFIX}_cbc_encrypt + .rva .LSEH_info_${PREFIX}_cbc_encrypt + +.section .xdata +.align 8 +.LSEH_info_${PREFIX}_set_encrypt_key: + .byte 9,0,0,0 + .rva se_handler + .rva .Lenc_key_body,.Lenc_key_epilogue # HandlerData[] +.LSEH_info_${PREFIX}_set_decrypt_key: + .byte 9,0,0,0 + .rva se_handler + .rva .Ldec_key_body,.Ldec_key_epilogue # HandlerData[] +.LSEH_info_${PREFIX}_encrypt: + .byte 9,0,0,0 + .rva se_handler + .rva .Lenc_body,.Lenc_epilogue # HandlerData[] +.LSEH_info_${PREFIX}_decrypt: + .byte 9,0,0,0 + .rva se_handler + .rva .Ldec_body,.Ldec_epilogue # HandlerData[] +.LSEH_info_${PREFIX}_cbc_encrypt: + .byte 9,0,0,0 + .rva se_handler + .rva .Lcbc_body,.Lcbc_epilogue # HandlerData[] +___ +} + +$code =~ s/\`([^\`]*)\`/eval($1)/gem; + +print $code; + +close STDOUT; diff --git a/external/boringssl/crypto/aes/internal.h b/external/boringssl/crypto/aes/internal.h new file mode 100644 index 0000000000..3dc5c6379c --- /dev/null +++ b/external/boringssl/crypto/aes/internal.h @@ -0,0 +1,87 @@ +/* ==================================================================== + * Copyright (c) 2002-2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== */ + +#ifndef OPENSSL_HEADER_AES_INTERNAL_H +#define OPENSSL_HEADER_AES_INTERNAL_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +#if defined(_MSC_VER) && \ + (defined(_M_IX86) || defined(_M_AMD64) || defined(_M_X64)) +#define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00) +#define GETU32(p) SWAP(*((uint32_t *)(p))) +#define PUTU32(ct, st) \ + { *((uint32_t *)(ct)) = SWAP((st)); } +#else +#define GETU32(pt) \ + (((uint32_t)(pt)[0] << 24) ^ ((uint32_t)(pt)[1] << 16) ^ \ + ((uint32_t)(pt)[2] << 8) ^ ((uint32_t)(pt)[3])) +#define PUTU32(ct, st) \ + { \ + (ct)[0] = (uint8_t)((st) >> 24); \ + (ct)[1] = (uint8_t)((st) >> 16); \ + (ct)[2] = (uint8_t)((st) >> 8); \ + (ct)[3] = (uint8_t)(st); \ + } +#endif + +#define MAXKC (256 / 32) +#define MAXKB (256 / 8) +#define MAXNR 14 + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_AES_INTERNAL_H */ diff --git a/external/boringssl/crypto/aes/mode_wrappers.c b/external/boringssl/crypto/aes/mode_wrappers.c new file mode 100644 index 0000000000..4929920f00 --- /dev/null +++ b/external/boringssl/crypto/aes/mode_wrappers.c @@ -0,0 +1,112 @@ +/* ==================================================================== + * Copyright (c) 2002-2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== */ + +#include + +#include + +#include "../modes/internal.h" + + +void AES_ctr128_encrypt(const uint8_t *in, uint8_t *out, size_t len, + const AES_KEY *key, uint8_t ivec[AES_BLOCK_SIZE], + uint8_t ecount_buf[AES_BLOCK_SIZE], unsigned int *num) { + CRYPTO_ctr128_encrypt(in, out, len, key, ivec, ecount_buf, num, + (block128_f)AES_encrypt); +} + +void AES_ecb_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key, + const int enc) { + assert(in && out && key); + assert((AES_ENCRYPT == enc) || (AES_DECRYPT == enc)); + + if (AES_ENCRYPT == enc) { + AES_encrypt(in, out, key); + } else { + AES_decrypt(in, out, key); + } +} + +#if defined(OPENSSL_NO_ASM) || \ + (!defined(OPENSSL_X86_64) && !defined(OPENSSL_X86)) +void AES_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t len, + const AES_KEY *key, uint8_t *ivec, const int enc) { + + if (enc) { + CRYPTO_cbc128_encrypt(in, out, len, key, ivec, (block128_f)AES_encrypt); + } else { + CRYPTO_cbc128_decrypt(in, out, len, key, ivec, (block128_f)AES_decrypt); + } +} +#else + +void asm_AES_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t len, + const AES_KEY *key, uint8_t *ivec, const int enc); +void AES_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t len, + const AES_KEY *key, uint8_t *ivec, const int enc) { + asm_AES_cbc_encrypt(in, out, len, key, ivec, enc); +} + +#endif /* OPENSSL_NO_ASM || (!OPENSSL_X86_64 && !OPENSSL_X86) */ + +void AES_ofb128_encrypt(const uint8_t *in, uint8_t *out, size_t length, + const AES_KEY *key, uint8_t *ivec, int *num) { + unsigned num_u = (unsigned)(*num); + CRYPTO_ofb128_encrypt(in, out, length, key, ivec, &num_u, + (block128_f)AES_encrypt); + *num = (int)num_u; +} + +void AES_cfb128_encrypt(const uint8_t *in, uint8_t *out, size_t length, + const AES_KEY *key, uint8_t *ivec, int *num, + int enc) { + unsigned num_u = (unsigned)(*num); + CRYPTO_cfb128_encrypt(in, out, length, key, ivec, &num_u, enc, + (block128_f)AES_encrypt); + *num = (int)num_u; +} diff --git a/external/boringssl/crypto/asn1/CMakeLists.txt b/external/boringssl/crypto/asn1/CMakeLists.txt new file mode 100644 index 0000000000..90fe01f5ea --- /dev/null +++ b/external/boringssl/crypto/asn1/CMakeLists.txt @@ -0,0 +1,54 @@ +include_directories(../../include) + +add_library( + asn1 + + OBJECT + + a_bitstr.c + a_bool.c + a_bytes.c + a_d2i_fp.c + a_dup.c + a_enum.c + a_gentm.c + a_i2d_fp.c + a_int.c + a_mbstr.c + a_object.c + a_octet.c + a_print.c + a_strnid.c + a_time.c + a_type.c + a_utctm.c + a_utf8.c + asn1_lib.c + asn1_par.c + asn_pack.c + f_enum.c + f_int.c + f_string.c + t_bitst.c + tasn_dec.c + tasn_enc.c + tasn_fre.c + tasn_new.c + tasn_typ.c + tasn_utl.c + x_bignum.c + x_long.c +) + +if(ENABLE_TESTS) +add_executable( + asn1_test + + asn1_test.cc + + $ +) + +target_link_libraries(asn1_test crypto) +add_dependencies(all_tests asn1_test) +endif() diff --git a/external/boringssl/crypto/asn1/a_bitstr.c b/external/boringssl/crypto/asn1/a_bitstr.c new file mode 100644 index 0000000000..2705ea5687 --- /dev/null +++ b/external/boringssl/crypto/asn1/a_bitstr.c @@ -0,0 +1,263 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include +#include + +int ASN1_BIT_STRING_set(ASN1_BIT_STRING *x, unsigned char *d, int len) +{ + return M_ASN1_BIT_STRING_set(x, d, len); +} + +int i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **pp) +{ + int ret, j, bits, len; + unsigned char *p, *d; + + if (a == NULL) + return (0); + + len = a->length; + + if (len > 0) { + if (a->flags & ASN1_STRING_FLAG_BITS_LEFT) { + bits = (int)a->flags & 0x07; + } else { + for (; len > 0; len--) { + if (a->data[len - 1]) + break; + } + j = a->data[len - 1]; + if (j & 0x01) + bits = 0; + else if (j & 0x02) + bits = 1; + else if (j & 0x04) + bits = 2; + else if (j & 0x08) + bits = 3; + else if (j & 0x10) + bits = 4; + else if (j & 0x20) + bits = 5; + else if (j & 0x40) + bits = 6; + else if (j & 0x80) + bits = 7; + else + bits = 0; /* should not happen */ + } + } else + bits = 0; + + ret = 1 + len; + if (pp == NULL) + return (ret); + + p = *pp; + + *(p++) = (unsigned char)bits; + d = a->data; + memcpy(p, d, len); + p += len; + if (len > 0) + p[-1] &= (0xff << bits); + *pp = p; + return (ret); +} + +ASN1_BIT_STRING *c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a, + const unsigned char **pp, long len) +{ + ASN1_BIT_STRING *ret = NULL; + const unsigned char *p; + unsigned char *s; + int padding; + + if (len < 1) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_SHORT); + goto err; + } + + if ((a == NULL) || ((*a) == NULL)) { + if ((ret = M_ASN1_BIT_STRING_new()) == NULL) + return (NULL); + } else + ret = (*a); + + p = *pp; + padding = *(p++); + if (padding > 7) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_BIT_STRING_BITS_LEFT); + goto err; + } + + /* + * We do this to preserve the settings. If we modify the settings, via + * the _set_bit function, we will recalculate on output + */ + ret->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); /* clear */ + ret->flags |= (ASN1_STRING_FLAG_BITS_LEFT | padding); /* set */ + + if (len-- > 1) { /* using one because of the bits left byte */ + s = (unsigned char *)OPENSSL_malloc((int)len); + if (s == NULL) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + goto err; + } + memcpy(s, p, (int)len); + s[len - 1] &= (0xff << padding); + p += len; + } else + s = NULL; + + ret->length = (int)len; + if (ret->data != NULL) + OPENSSL_free(ret->data); + ret->data = s; + ret->type = V_ASN1_BIT_STRING; + if (a != NULL) + (*a) = ret; + *pp = p; + return (ret); + err: + if ((ret != NULL) && ((a == NULL) || (*a != ret))) + M_ASN1_BIT_STRING_free(ret); + return (NULL); +} + +/* + * These next 2 functions from Goetz Babin-Ebell + */ +int ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int value) +{ + int w, v, iv; + unsigned char *c; + + w = n / 8; + v = 1 << (7 - (n & 0x07)); + iv = ~v; + if (!value) + v = 0; + + if (a == NULL) + return 0; + + a->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); /* clear, set on write */ + + if ((a->length < (w + 1)) || (a->data == NULL)) { + if (!value) + return (1); /* Don't need to set */ + if (a->data == NULL) + c = (unsigned char *)OPENSSL_malloc(w + 1); + else + c = (unsigned char *)OPENSSL_realloc_clean(a->data, + a->length, w + 1); + if (c == NULL) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + return 0; + } + if (w + 1 - a->length > 0) + memset(c + a->length, 0, w + 1 - a->length); + a->data = c; + a->length = w + 1; + } + a->data[w] = ((a->data[w]) & iv) | v; + while ((a->length > 0) && (a->data[a->length - 1] == 0)) + a->length--; + return (1); +} + +int ASN1_BIT_STRING_get_bit(ASN1_BIT_STRING *a, int n) +{ + int w, v; + + w = n / 8; + v = 1 << (7 - (n & 0x07)); + if ((a == NULL) || (a->length < (w + 1)) || (a->data == NULL)) + return (0); + return ((a->data[w] & v) != 0); +} + +/* + * Checks if the given bit string contains only bits specified by + * the flags vector. Returns 0 if there is at least one bit set in 'a' + * which is not specified in 'flags', 1 otherwise. + * 'len' is the length of 'flags'. + */ +int ASN1_BIT_STRING_check(ASN1_BIT_STRING *a, + unsigned char *flags, int flags_len) +{ + int i, ok; + /* Check if there is one bit set at all. */ + if (!a || !a->data) + return 1; + + /* + * Check each byte of the internal representation of the bit string. + */ + ok = 1; + for (i = 0; i < a->length && ok; ++i) { + unsigned char mask = i < flags_len ? ~flags[i] : 0xff; + /* We are done if there is an unneeded bit set. */ + ok = (a->data[i] & mask) == 0; + } + return ok; +} diff --git a/external/boringssl/crypto/asn1/a_bool.c b/external/boringssl/crypto/asn1/a_bool.c new file mode 100644 index 0000000000..64a079ec4b --- /dev/null +++ b/external/boringssl/crypto/asn1/a_bool.c @@ -0,0 +1,110 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +int i2d_ASN1_BOOLEAN(int a, unsigned char **pp) +{ + int r; + unsigned char *p; + + r = ASN1_object_size(0, 1, V_ASN1_BOOLEAN); + if (pp == NULL) + return (r); + p = *pp; + + ASN1_put_object(&p, 0, 1, V_ASN1_BOOLEAN, V_ASN1_UNIVERSAL); + *(p++) = (unsigned char)a; + *pp = p; + return (r); +} + +int d2i_ASN1_BOOLEAN(int *a, const unsigned char **pp, long length) +{ + int ret = -1; + const unsigned char *p; + long len; + int inf, tag, xclass; + int i = 0; + + p = *pp; + inf = ASN1_get_object(&p, &len, &tag, &xclass, length); + if (inf & 0x80) { + i = ASN1_R_BAD_OBJECT_HEADER; + goto err; + } + + if (tag != V_ASN1_BOOLEAN) { + i = ASN1_R_EXPECTING_A_BOOLEAN; + goto err; + } + + if (len != 1) { + i = ASN1_R_BOOLEAN_IS_WRONG_LENGTH; + goto err; + } + ret = (int)*(p++); + if (a != NULL) + (*a) = ret; + *pp = p; + return (ret); + err: + OPENSSL_PUT_ERROR(ASN1, i); + return (ret); +} diff --git a/external/boringssl/crypto/asn1/a_bytes.c b/external/boringssl/crypto/asn1/a_bytes.c new file mode 100644 index 0000000000..e6b2f2e9a1 --- /dev/null +++ b/external/boringssl/crypto/asn1/a_bytes.c @@ -0,0 +1,308 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include +#include +#include + +static int asn1_collate_primitive(ASN1_STRING *a, ASN1_const_CTX *c); +/* + * type is a 'bitmap' of acceptable string types. + */ +ASN1_STRING *d2i_ASN1_type_bytes(ASN1_STRING **a, const unsigned char **pp, + long length, int type) +{ + ASN1_STRING *ret = NULL; + const unsigned char *p; + unsigned char *s; + long len; + int inf, tag, xclass; + int i = 0; + + p = *pp; + inf = ASN1_get_object(&p, &len, &tag, &xclass, length); + if (inf & 0x80) + goto err; + + if (tag >= 32) { + i = ASN1_R_TAG_VALUE_TOO_HIGH; + goto err; + } + if (!(ASN1_tag2bit(tag) & type)) { + i = ASN1_R_WRONG_TYPE; + goto err; + } + + /* If a bit-string, exit early */ + if (tag == V_ASN1_BIT_STRING) + return (d2i_ASN1_BIT_STRING(a, pp, length)); + + if ((a == NULL) || ((*a) == NULL)) { + if ((ret = ASN1_STRING_new()) == NULL) + return (NULL); + } else + ret = (*a); + + if (len != 0) { + s = (unsigned char *)OPENSSL_malloc((int)len + 1); + if (s == NULL) { + i = ERR_R_MALLOC_FAILURE; + goto err; + } + memcpy(s, p, (int)len); + s[len] = '\0'; + p += len; + } else + s = NULL; + + if (ret->data != NULL) + OPENSSL_free(ret->data); + ret->length = (int)len; + ret->data = s; + ret->type = tag; + if (a != NULL) + (*a) = ret; + *pp = p; + return (ret); + err: + OPENSSL_PUT_ERROR(ASN1, i); + if ((ret != NULL) && ((a == NULL) || (*a != ret))) + ASN1_STRING_free(ret); + return (NULL); +} + +int i2d_ASN1_bytes(ASN1_STRING *a, unsigned char **pp, int tag, int xclass) +{ + int ret, r, constructed; + unsigned char *p; + + if (a == NULL) + return (0); + + if (tag == V_ASN1_BIT_STRING) + return (i2d_ASN1_BIT_STRING(a, pp)); + + ret = a->length; + r = ASN1_object_size(0, ret, tag); + if (pp == NULL) + return (r); + p = *pp; + + if ((tag == V_ASN1_SEQUENCE) || (tag == V_ASN1_SET)) + constructed = 1; + else + constructed = 0; + ASN1_put_object(&p, constructed, ret, tag, xclass); + memcpy(p, a->data, a->length); + p += a->length; + *pp = p; + return (r); +} + +ASN1_STRING *d2i_ASN1_bytes(ASN1_STRING **a, const unsigned char **pp, + long length, int Ptag, int Pclass) +{ + ASN1_STRING *ret = NULL; + const unsigned char *p; + unsigned char *s; + long len; + int inf, tag, xclass; + int i = 0; + + if ((a == NULL) || ((*a) == NULL)) { + if ((ret = ASN1_STRING_new()) == NULL) + return (NULL); + } else + ret = (*a); + + p = *pp; + inf = ASN1_get_object(&p, &len, &tag, &xclass, length); + if (inf & 0x80) { + i = ASN1_R_BAD_OBJECT_HEADER; + goto err; + } + + if (tag != Ptag) { + i = ASN1_R_WRONG_TAG; + goto err; + } + + if (inf & V_ASN1_CONSTRUCTED) { + ASN1_const_CTX c; + + c.pp = pp; + c.p = p; + c.inf = inf; + c.slen = len; + c.tag = Ptag; + c.xclass = Pclass; + c.max = (length == 0) ? 0 : (p + length); + if (!asn1_collate_primitive(ret, &c)) + goto err; + else { + p = c.p; + } + } else { + if (len != 0) { + if ((ret->length < len) || (ret->data == NULL)) { + s = (unsigned char *)OPENSSL_malloc((int)len + 1); + if (s == NULL) { + i = ERR_R_MALLOC_FAILURE; + goto err; + } + if (ret->data != NULL) + OPENSSL_free(ret->data); + } else + s = ret->data; + memcpy(s, p, (int)len); + s[len] = '\0'; + p += len; + } else { + s = NULL; + if (ret->data != NULL) + OPENSSL_free(ret->data); + } + + ret->length = (int)len; + ret->data = s; + ret->type = Ptag; + } + + if (a != NULL) + (*a) = ret; + *pp = p; + return (ret); + err: + if ((ret != NULL) && ((a == NULL) || (*a != ret))) + ASN1_STRING_free(ret); + OPENSSL_PUT_ERROR(ASN1, i); + return (NULL); +} + +/* + * We are about to parse 0..n d2i_ASN1_bytes objects, we are to collapse them + * into the one structure that is then returned + */ +/* + * There have been a few bug fixes for this function from Paul Keogh + * , many thanks to him + */ +static int asn1_collate_primitive(ASN1_STRING *a, ASN1_const_CTX *c) +{ + ASN1_STRING *os = NULL; + BUF_MEM b; + int num; + + b.length = 0; + b.max = 0; + b.data = NULL; + + if (a == NULL) { + c->error = ERR_R_PASSED_NULL_PARAMETER; + goto err; + } + + num = 0; + for (;;) { + if (c->inf & 1) { + c->eos = ASN1_const_check_infinite_end(&c->p, + (long)(c->max - c->p)); + if (c->eos) + break; + } else { + if (c->slen <= 0) + break; + } + + c->q = c->p; + if (d2i_ASN1_bytes(&os, &c->p, c->max - c->p, c->tag, c->xclass) + == NULL) { + c->error = ERR_R_ASN1_LIB; + goto err; + } + + if (!BUF_MEM_grow_clean(&b, num + os->length)) { + c->error = ERR_R_BUF_LIB; + goto err; + } + memcpy(&(b.data[num]), os->data, os->length); + if (!(c->inf & 1)) + c->slen -= (c->p - c->q); + num += os->length; + } + + if (!asn1_const_Finish(c)) + goto err; + + a->length = num; + if (a->data != NULL) + OPENSSL_free(a->data); + a->data = (unsigned char *)b.data; + if (os != NULL) + ASN1_STRING_free(os); + return (1); + err: + OPENSSL_PUT_ERROR(ASN1, c->error); + if (os != NULL) + ASN1_STRING_free(os); + if (b.data != NULL) + OPENSSL_free(b.data); + return (0); +} diff --git a/external/boringssl/crypto/asn1/a_d2i_fp.c b/external/boringssl/crypto/asn1/a_d2i_fp.c new file mode 100644 index 0000000000..b544971911 --- /dev/null +++ b/external/boringssl/crypto/asn1/a_d2i_fp.c @@ -0,0 +1,282 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include +#include +#include + +static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb); + +#ifndef NO_OLD_ASN1 +# ifndef OPENSSL_NO_FP_API + +void *ASN1_d2i_fp(void *(*xnew) (void), d2i_of_void *d2i, FILE *in, void **x) +{ + BIO *b; + void *ret; + + if ((b = BIO_new(BIO_s_file())) == NULL) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB); + return (NULL); + } + BIO_set_fp(b, in, BIO_NOCLOSE); + ret = ASN1_d2i_bio(xnew, d2i, b, x); + BIO_free(b); + return (ret); +} +# endif + +void *ASN1_d2i_bio(void *(*xnew) (void), d2i_of_void *d2i, BIO *in, void **x) +{ + BUF_MEM *b = NULL; + const unsigned char *p; + void *ret = NULL; + int len; + + len = asn1_d2i_read_bio(in, &b); + if (len < 0) + goto err; + + p = (unsigned char *)b->data; + ret = d2i(x, &p, len); + err: + if (b != NULL) + BUF_MEM_free(b); + return (ret); +} + +#endif + +void *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x) +{ + BUF_MEM *b = NULL; + const unsigned char *p; + void *ret = NULL; + int len; + + len = asn1_d2i_read_bio(in, &b); + if (len < 0) + goto err; + + p = (const unsigned char *)b->data; + ret = ASN1_item_d2i(x, &p, len, it); + err: + if (b != NULL) + BUF_MEM_free(b); + return (ret); +} + +#ifndef OPENSSL_NO_FP_API +void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x) +{ + BIO *b; + char *ret; + + if ((b = BIO_new(BIO_s_file())) == NULL) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB); + return (NULL); + } + BIO_set_fp(b, in, BIO_NOCLOSE); + ret = ASN1_item_d2i_bio(it, b, x); + BIO_free(b); + return (ret); +} +#endif + +#define HEADER_SIZE 8 +#define ASN1_CHUNK_INITIAL_SIZE (16 * 1024) +static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb) +{ + BUF_MEM *b; + unsigned char *p; + int i; + ASN1_const_CTX c; + size_t want = HEADER_SIZE; + int eos = 0; + size_t off = 0; + size_t len = 0; + + b = BUF_MEM_new(); + if (b == NULL) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + return -1; + } + + ERR_clear_error(); + for (;;) { + if (want >= (len - off)) { + want -= (len - off); + + if (len + want < len || !BUF_MEM_grow_clean(b, len + want)) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + goto err; + } + i = BIO_read(in, &(b->data[len]), want); + if ((i < 0) && ((len - off) == 0)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_NOT_ENOUGH_DATA); + goto err; + } + if (i > 0) { + if (len + i < len) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG); + goto err; + } + len += i; + } + } + /* else data already loaded */ + + p = (unsigned char *)&(b->data[off]); + c.p = p; + c.inf = ASN1_get_object(&(c.p), &(c.slen), &(c.tag), &(c.xclass), + len - off); + if (c.inf & 0x80) { + uint32_t e; + + e = ERR_GET_REASON(ERR_peek_error()); + if (e != ASN1_R_TOO_LONG) + goto err; + else + ERR_clear_error(); /* clear error */ + } + i = c.p - p; /* header length */ + off += i; /* end of data */ + + if (c.inf & 1) { + /* no data body so go round again */ + eos++; + if (eos < 0) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_HEADER_TOO_LONG); + goto err; + } + want = HEADER_SIZE; + } else if (eos && (c.slen == 0) && (c.tag == V_ASN1_EOC)) { + /* eos value, so go back and read another header */ + eos--; + if (eos <= 0) + break; + else + want = HEADER_SIZE; + } else { + /* suck in c.slen bytes of data */ + want = c.slen; + if (want > (len - off)) { + size_t chunk_max = ASN1_CHUNK_INITIAL_SIZE; + want -= (len - off); + if (want > INT_MAX /* BIO_read takes an int length */ || + len + want < len) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG); + goto err; + } + while (want > 0) { + /* + * Read content in chunks of increasing size + * so we can return an error for EOF without + * having to allocate the entire content length + * in one go. + */ + size_t chunk = want > chunk_max ? chunk_max : want; + + if (!BUF_MEM_grow_clean(b, len + chunk)) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + goto err; + } + want -= chunk; + while (chunk > 0) { + i = BIO_read(in, &(b->data[len]), chunk); + if (i <= 0) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_NOT_ENOUGH_DATA); + goto err; + } + /* + * This can't overflow because |len+want| didn't + * overflow. + */ + len += i; + chunk -= i; + } + if (chunk_max < INT_MAX/2) + chunk_max *= 2; + } + } + if (off + c.slen < off) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG); + goto err; + } + off += c.slen; + if (eos <= 0) { + break; + } else + want = HEADER_SIZE; + } + } + + if (off > INT_MAX) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG); + goto err; + } + + *pb = b; + return off; + err: + if (b != NULL) + BUF_MEM_free(b); + return -1; +} diff --git a/external/boringssl/crypto/asn1/a_dup.c b/external/boringssl/crypto/asn1/a_dup.c new file mode 100644 index 0000000000..57394f58c4 --- /dev/null +++ b/external/boringssl/crypto/asn1/a_dup.c @@ -0,0 +1,111 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +void *ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, void *x) +{ + unsigned char *b, *p; + const unsigned char *p2; + int i; + char *ret; + + if (x == NULL) + return (NULL); + + i = i2d(x, NULL); + b = OPENSSL_malloc(i + 10); + if (b == NULL) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + return (NULL); + } + p = b; + i = i2d(x, &p); + p2 = b; + ret = d2i(NULL, &p2, i); + OPENSSL_free(b); + return (ret); +} + +/* + * ASN1_ITEM version of dup: this follows the model above except we don't + * need to allocate the buffer. At some point this could be rewritten to + * directly dup the underlying structure instead of doing and encode and + * decode. + */ +void *ASN1_item_dup(const ASN1_ITEM *it, void *x) +{ + unsigned char *b = NULL; + const unsigned char *p; + long i; + void *ret; + + if (x == NULL) + return (NULL); + + i = ASN1_item_i2d(x, &b, it); + if (b == NULL) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + return (NULL); + } + p = b; + ret = ASN1_item_d2i(NULL, &p, i, it); + OPENSSL_free(b); + return (ret); +} diff --git a/external/boringssl/crypto/asn1/a_enum.c b/external/boringssl/crypto/asn1/a_enum.c new file mode 100644 index 0000000000..0b95fc95e8 --- /dev/null +++ b/external/boringssl/crypto/asn1/a_enum.c @@ -0,0 +1,181 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include +#include + +/* + * Code for ENUMERATED type: identical to INTEGER apart from a different tag. + * for comments on encoding see a_int.c + */ + +int ASN1_ENUMERATED_set(ASN1_ENUMERATED *a, long v) +{ + int j, k; + unsigned int i; + unsigned char buf[sizeof(long) + 1]; + long d; + + a->type = V_ASN1_ENUMERATED; + if (a->length < (int)(sizeof(long) + 1)) { + if (a->data != NULL) + OPENSSL_free(a->data); + if ((a->data = + (unsigned char *)OPENSSL_malloc(sizeof(long) + 1)) != NULL) + memset((char *)a->data, 0, sizeof(long) + 1); + } + if (a->data == NULL) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + return (0); + } + d = v; + if (d < 0) { + d = -d; + a->type = V_ASN1_NEG_ENUMERATED; + } + + for (i = 0; i < sizeof(long); i++) { + if (d == 0) + break; + buf[i] = (int)d & 0xff; + d >>= 8; + } + j = 0; + for (k = i - 1; k >= 0; k--) + a->data[j++] = buf[k]; + a->length = j; + return (1); +} + +long ASN1_ENUMERATED_get(ASN1_ENUMERATED *a) +{ + int neg = 0, i; + long r = 0; + + if (a == NULL) + return (0L); + i = a->type; + if (i == V_ASN1_NEG_ENUMERATED) + neg = 1; + else if (i != V_ASN1_ENUMERATED) + return -1; + + if (a->length > (int)sizeof(long)) { + /* hmm... a bit ugly */ + return (0xffffffffL); + } + if (a->data == NULL) + return 0; + + for (i = 0; i < a->length; i++) { + r <<= 8; + r |= (unsigned char)a->data[i]; + } + if (neg) + r = -r; + return (r); +} + +ASN1_ENUMERATED *BN_to_ASN1_ENUMERATED(BIGNUM *bn, ASN1_ENUMERATED *ai) +{ + ASN1_ENUMERATED *ret; + int len, j; + + if (ai == NULL) + ret = M_ASN1_ENUMERATED_new(); + else + ret = ai; + if (ret == NULL) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); + goto err; + } + if (BN_is_negative(bn)) + ret->type = V_ASN1_NEG_ENUMERATED; + else + ret->type = V_ASN1_ENUMERATED; + j = BN_num_bits(bn); + len = ((j == 0) ? 0 : ((j / 8) + 1)); + if (ret->length < len + 4) { + unsigned char *new_data = OPENSSL_realloc(ret->data, len + 4); + if (!new_data) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + goto err; + } + ret->data = new_data; + } + + ret->length = BN_bn2bin(bn, ret->data); + return (ret); + err: + if (ret != ai) + M_ASN1_ENUMERATED_free(ret); + return (NULL); +} + +BIGNUM *ASN1_ENUMERATED_to_BN(ASN1_ENUMERATED *ai, BIGNUM *bn) +{ + BIGNUM *ret; + + if ((ret = BN_bin2bn(ai->data, ai->length, bn)) == NULL) + OPENSSL_PUT_ERROR(ASN1, ASN1_R_BN_LIB); + else if (ai->type == V_ASN1_NEG_ENUMERATED) + BN_set_negative(ret, 1); + return (ret); +} diff --git a/external/boringssl/crypto/asn1/a_gentm.c b/external/boringssl/crypto/asn1/a_gentm.c new file mode 100644 index 0000000000..ee6b3db54c --- /dev/null +++ b/external/boringssl/crypto/asn1/a_gentm.c @@ -0,0 +1,256 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +#include +#include +#include + +#include "asn1_locl.h" + +int asn1_generalizedtime_to_tm(struct tm *tm, const ASN1_GENERALIZEDTIME *d) +{ + static const int min[9] = { 0, 0, 1, 1, 0, 0, 0, 0, 0 }; + static const int max[9] = { 99, 99, 12, 31, 23, 59, 59, 12, 59 }; + char *a; + int n, i, l, o; + + if (d->type != V_ASN1_GENERALIZEDTIME) + return (0); + l = d->length; + a = (char *)d->data; + o = 0; + /* + * GENERALIZEDTIME is similar to UTCTIME except the year is represented + * as YYYY. This stuff treats everything as a two digit field so make + * first two fields 00 to 99 + */ + if (l < 13) + goto err; + for (i = 0; i < 7; i++) { + if ((i == 6) && ((a[o] == 'Z') || (a[o] == '+') || (a[o] == '-'))) { + i++; + if (tm) + tm->tm_sec = 0; + break; + } + if ((a[o] < '0') || (a[o] > '9')) + goto err; + n = a[o] - '0'; + if (++o > l) + goto err; + + if ((a[o] < '0') || (a[o] > '9')) + goto err; + n = (n * 10) + a[o] - '0'; + if (++o > l) + goto err; + + if ((n < min[i]) || (n > max[i])) + goto err; + if (tm) { + switch (i) { + case 0: + tm->tm_year = n * 100 - 1900; + break; + case 1: + tm->tm_year += n; + break; + case 2: + tm->tm_mon = n - 1; + break; + case 3: + tm->tm_mday = n; + break; + case 4: + tm->tm_hour = n; + break; + case 5: + tm->tm_min = n; + break; + case 6: + tm->tm_sec = n; + break; + } + } + } + /* + * Optional fractional seconds: decimal point followed by one or more + * digits. + */ + if (a[o] == '.') { + if (++o > l) + goto err; + i = o; + while ((a[o] >= '0') && (a[o] <= '9') && (o <= l)) + o++; + /* Must have at least one digit after decimal point */ + if (i == o) + goto err; + } + + if (a[o] == 'Z') + o++; + else if ((a[o] == '+') || (a[o] == '-')) { + int offsign = a[o] == '-' ? -1 : 1, offset = 0; + o++; + if (o + 4 > l) + goto err; + for (i = 7; i < 9; i++) { + if ((a[o] < '0') || (a[o] > '9')) + goto err; + n = a[o] - '0'; + o++; + if ((a[o] < '0') || (a[o] > '9')) + goto err; + n = (n * 10) + a[o] - '0'; + if ((n < min[i]) || (n > max[i])) + goto err; + if (tm) { + if (i == 7) + offset = n * 3600; + else if (i == 8) + offset += n * 60; + } + o++; + } + if (offset && !OPENSSL_gmtime_adj(tm, 0, offset * offsign)) + return 0; + } else if (a[o]) { + /* Missing time zone information. */ + goto err; + } + return (o == l); + err: + return (0); +} + +int ASN1_GENERALIZEDTIME_check(const ASN1_GENERALIZEDTIME *d) +{ + return asn1_generalizedtime_to_tm(NULL, d); +} + +int ASN1_GENERALIZEDTIME_set_string(ASN1_GENERALIZEDTIME *s, const char *str) +{ + ASN1_GENERALIZEDTIME t; + + t.type = V_ASN1_GENERALIZEDTIME; + t.length = strlen(str); + t.data = (unsigned char *)str; + if (ASN1_GENERALIZEDTIME_check(&t)) { + if (s != NULL) { + if (!ASN1_STRING_set((ASN1_STRING *)s, + (unsigned char *)str, t.length)) + return 0; + s->type = V_ASN1_GENERALIZEDTIME; + } + return (1); + } else + return (0); +} + +ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_set(ASN1_GENERALIZEDTIME *s, + time_t t) +{ + return ASN1_GENERALIZEDTIME_adj(s, t, 0, 0); +} + +ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_adj(ASN1_GENERALIZEDTIME *s, + time_t t, int offset_day, + long offset_sec) +{ + char *p; + struct tm *ts; + struct tm data; + size_t len = 20; + + if (s == NULL) + s = M_ASN1_GENERALIZEDTIME_new(); + if (s == NULL) + return (NULL); + + ts = OPENSSL_gmtime(&t, &data); + if (ts == NULL) + return (NULL); + + if (offset_day || offset_sec) { + if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec)) + return NULL; + } + + p = (char *)s->data; + if ((p == NULL) || ((size_t)s->length < len)) { + p = OPENSSL_malloc(len); + if (p == NULL) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + return (NULL); + } + if (s->data != NULL) + OPENSSL_free(s->data); + s->data = (unsigned char *)p; + } + + BIO_snprintf(p, len, "%04d%02d%02d%02d%02d%02dZ", ts->tm_year + 1900, + ts->tm_mon + 1, ts->tm_mday, ts->tm_hour, ts->tm_min, + ts->tm_sec); + s->length = strlen(p); + s->type = V_ASN1_GENERALIZEDTIME; + return (s); +} diff --git a/external/boringssl/crypto/asn1/a_i2d_fp.c b/external/boringssl/crypto/asn1/a_i2d_fp.c new file mode 100644 index 0000000000..486207ed2e --- /dev/null +++ b/external/boringssl/crypto/asn1/a_i2d_fp.c @@ -0,0 +1,147 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +int ASN1_i2d_fp(i2d_of_void *i2d, FILE *out, void *x) +{ + BIO *b; + int ret; + + if ((b = BIO_new(BIO_s_file())) == NULL) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB); + return (0); + } + BIO_set_fp(b, out, BIO_NOCLOSE); + ret = ASN1_i2d_bio(i2d, b, x); + BIO_free(b); + return (ret); +} + +int ASN1_i2d_bio(i2d_of_void *i2d, BIO *out, void *x) +{ + char *b; + unsigned char *p; + int i, j = 0, n, ret = 1; + + n = i2d(x, NULL); + b = (char *)OPENSSL_malloc(n); + if (b == NULL) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + return (0); + } + + p = (unsigned char *)b; + i2d(x, &p); + + for (;;) { + i = BIO_write(out, &(b[j]), n); + if (i == n) + break; + if (i <= 0) { + ret = 0; + break; + } + j += i; + n -= i; + } + OPENSSL_free(b); + return (ret); +} + +int ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out, void *x) +{ + BIO *b; + int ret; + + if ((b = BIO_new(BIO_s_file())) == NULL) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB); + return (0); + } + BIO_set_fp(b, out, BIO_NOCLOSE); + ret = ASN1_item_i2d_bio(it, b, x); + BIO_free(b); + return (ret); +} + +int ASN1_item_i2d_bio(const ASN1_ITEM *it, BIO *out, void *x) +{ + unsigned char *b = NULL; + int i, j = 0, n, ret = 1; + + n = ASN1_item_i2d(x, &b, it); + if (b == NULL) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + return (0); + } + + for (;;) { + i = BIO_write(out, &(b[j]), n); + if (i == n) + break; + if (i <= 0) { + ret = 0; + break; + } + j += i; + n -= i; + } + OPENSSL_free(b); + return (ret); +} diff --git a/external/boringssl/crypto/asn1/a_int.c b/external/boringssl/crypto/asn1/a_int.c new file mode 100644 index 0000000000..38a01bcb88 --- /dev/null +++ b/external/boringssl/crypto/asn1/a_int.c @@ -0,0 +1,460 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include +#include + +ASN1_INTEGER *ASN1_INTEGER_dup(const ASN1_INTEGER *x) +{ + return M_ASN1_INTEGER_dup(x); +} + +int ASN1_INTEGER_cmp(const ASN1_INTEGER *x, const ASN1_INTEGER *y) +{ + int neg, ret; + /* Compare signs */ + neg = x->type & V_ASN1_NEG; + if (neg != (y->type & V_ASN1_NEG)) { + if (neg) + return -1; + else + return 1; + } + + ret = ASN1_STRING_cmp(x, y); + + if (neg) + return -ret; + else + return ret; +} + +/* + * This converts an ASN1 INTEGER into its content encoding. + * The internal representation is an ASN1_STRING whose data is a big endian + * representation of the value, ignoring the sign. The sign is determined by + * the type: V_ASN1_INTEGER for positive and V_ASN1_NEG_INTEGER for negative. + * + * Positive integers are no problem: they are almost the same as the DER + * encoding, except if the first byte is >= 0x80 we need to add a zero pad. + * + * Negative integers are a bit trickier... + * The DER representation of negative integers is in 2s complement form. + * The internal form is converted by complementing each octet and finally + * adding one to the result. This can be done less messily with a little trick. + * If the internal form has trailing zeroes then they will become FF by the + * complement and 0 by the add one (due to carry) so just copy as many trailing + * zeros to the destination as there are in the source. The carry will add one + * to the last none zero octet: so complement this octet and add one and finally + * complement any left over until you get to the start of the string. + * + * Padding is a little trickier too. If the first bytes is > 0x80 then we pad + * with 0xff. However if the first byte is 0x80 and one of the following bytes + * is non-zero we pad with 0xff. The reason for this distinction is that 0x80 + * followed by optional zeros isn't padded. + */ + +int i2c_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **pp) +{ + int pad = 0, ret, i, neg; + unsigned char *p, *n, pb = 0; + + if (a == NULL) + return (0); + neg = a->type & V_ASN1_NEG; + if (a->length == 0) + ret = 1; + else { + ret = a->length; + i = a->data[0]; + if (ret == 1 && i == 0) + neg = 0; + if (!neg && (i > 127)) { + pad = 1; + pb = 0; + } else if (neg) { + if (i > 128) { + pad = 1; + pb = 0xFF; + } else if (i == 128) { + /* + * Special case: if any other bytes non zero we pad: + * otherwise we don't. + */ + for (i = 1; i < a->length; i++) + if (a->data[i]) { + pad = 1; + pb = 0xFF; + break; + } + } + } + ret += pad; + } + if (pp == NULL) + return (ret); + p = *pp; + + if (pad) + *(p++) = pb; + if (a->length == 0) + *(p++) = 0; + else if (!neg) + memcpy(p, a->data, (unsigned int)a->length); + else { + /* Begin at the end of the encoding */ + n = a->data + a->length - 1; + p += a->length - 1; + i = a->length; + /* Copy zeros to destination as long as source is zero */ + while (!*n && i > 1) { + *(p--) = 0; + n--; + i--; + } + /* Complement and increment next octet */ + *(p--) = ((*(n--)) ^ 0xff) + 1; + i--; + /* Complement any octets left */ + for (; i > 0; i--) + *(p--) = *(n--) ^ 0xff; + } + + *pp += ret; + return (ret); +} + +/* Convert just ASN1 INTEGER content octets to ASN1_INTEGER structure */ + +ASN1_INTEGER *c2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **pp, + long len) +{ + ASN1_INTEGER *ret = NULL; + const unsigned char *p, *pend; + unsigned char *to, *s; + int i; + + if ((a == NULL) || ((*a) == NULL)) { + if ((ret = M_ASN1_INTEGER_new()) == NULL) + return (NULL); + ret->type = V_ASN1_INTEGER; + } else + ret = (*a); + + p = *pp; + pend = p + len; + + /* + * We must OPENSSL_malloc stuff, even for 0 bytes otherwise it signifies + * a missing NULL parameter. + */ + s = (unsigned char *)OPENSSL_malloc((int)len + 1); + if (s == NULL) { + i = ERR_R_MALLOC_FAILURE; + goto err; + } + to = s; + if (!len) { + /* + * Strictly speaking this is an illegal INTEGER but we tolerate it. + */ + ret->type = V_ASN1_INTEGER; + } else if (*p & 0x80) { /* a negative number */ + ret->type = V_ASN1_NEG_INTEGER; + if ((*p == 0xff) && (len != 1)) { + p++; + len--; + } + i = len; + p += i - 1; + to += i - 1; + while ((!*p) && i) { + *(to--) = 0; + i--; + p--; + } + /* + * Special case: if all zeros then the number will be of the form FF + * followed by n zero bytes: this corresponds to 1 followed by n zero + * bytes. We've already written n zeros so we just append an extra + * one and set the first byte to a 1. This is treated separately + * because it is the only case where the number of bytes is larger + * than len. + */ + if (!i) { + *s = 1; + s[len] = 0; + len++; + } else { + *(to--) = (*(p--) ^ 0xff) + 1; + i--; + for (; i > 0; i--) + *(to--) = *(p--) ^ 0xff; + } + } else { + ret->type = V_ASN1_INTEGER; + if ((*p == 0) && (len != 1)) { + p++; + len--; + } + memcpy(s, p, (int)len); + } + + if (ret->data != NULL) + OPENSSL_free(ret->data); + ret->data = s; + ret->length = (int)len; + if (a != NULL) + (*a) = ret; + *pp = pend; + return (ret); + err: + OPENSSL_PUT_ERROR(ASN1, i); + if ((ret != NULL) && ((a == NULL) || (*a != ret))) + M_ASN1_INTEGER_free(ret); + return (NULL); +} + +/* + * This is a version of d2i_ASN1_INTEGER that ignores the sign bit of ASN1 + * integers: some broken software can encode a positive INTEGER with its MSB + * set as negative (it doesn't add a padding zero). + */ + +ASN1_INTEGER *d2i_ASN1_UINTEGER(ASN1_INTEGER **a, const unsigned char **pp, + long length) +{ + ASN1_INTEGER *ret = NULL; + const unsigned char *p; + unsigned char *s; + long len; + int inf, tag, xclass; + int i; + + if ((a == NULL) || ((*a) == NULL)) { + if ((ret = M_ASN1_INTEGER_new()) == NULL) + return (NULL); + ret->type = V_ASN1_INTEGER; + } else + ret = (*a); + + p = *pp; + inf = ASN1_get_object(&p, &len, &tag, &xclass, length); + if (inf & 0x80) { + i = ASN1_R_BAD_OBJECT_HEADER; + goto err; + } + + if (tag != V_ASN1_INTEGER) { + i = ASN1_R_EXPECTING_AN_INTEGER; + goto err; + } + + /* + * We must OPENSSL_malloc stuff, even for 0 bytes otherwise it signifies + * a missing NULL parameter. + */ + s = (unsigned char *)OPENSSL_malloc((int)len + 1); + if (s == NULL) { + i = ERR_R_MALLOC_FAILURE; + goto err; + } + ret->type = V_ASN1_INTEGER; + if (len) { + if ((*p == 0) && (len != 1)) { + p++; + len--; + } + memcpy(s, p, (int)len); + p += len; + } + + if (ret->data != NULL) + OPENSSL_free(ret->data); + ret->data = s; + ret->length = (int)len; + if (a != NULL) + (*a) = ret; + *pp = p; + return (ret); + err: + OPENSSL_PUT_ERROR(ASN1, i); + if ((ret != NULL) && ((a == NULL) || (*a != ret))) + M_ASN1_INTEGER_free(ret); + return (NULL); +} + +int ASN1_INTEGER_set(ASN1_INTEGER *a, long v) +{ + int j, k; + unsigned int i; + unsigned char buf[sizeof(long) + 1]; + long d; + + a->type = V_ASN1_INTEGER; + if (a->length < (int)(sizeof(long) + 1)) { + if (a->data != NULL) + OPENSSL_free(a->data); + if ((a->data = + (unsigned char *)OPENSSL_malloc(sizeof(long) + 1)) != NULL) + memset((char *)a->data, 0, sizeof(long) + 1); + } + if (a->data == NULL) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + return (0); + } + d = v; + if (d < 0) { + d = -d; + a->type = V_ASN1_NEG_INTEGER; + } + + for (i = 0; i < sizeof(long); i++) { + if (d == 0) + break; + buf[i] = (int)d & 0xff; + d >>= 8; + } + j = 0; + for (k = i - 1; k >= 0; k--) + a->data[j++] = buf[k]; + a->length = j; + return (1); +} + +long ASN1_INTEGER_get(const ASN1_INTEGER *a) +{ + int neg = 0, i; + long r = 0; + + if (a == NULL) + return (0L); + i = a->type; + if (i == V_ASN1_NEG_INTEGER) + neg = 1; + else if (i != V_ASN1_INTEGER) + return -1; + + if (a->length > (int)sizeof(long)) { + /* hmm... a bit ugly, return all ones */ + return -1; + } + if (a->data == NULL) + return 0; + + for (i = 0; i < a->length; i++) { + r <<= 8; + r |= (unsigned char)a->data[i]; + } + if (neg) + r = -r; + return (r); +} + +ASN1_INTEGER *BN_to_ASN1_INTEGER(const BIGNUM *bn, ASN1_INTEGER *ai) +{ + ASN1_INTEGER *ret; + int len, j; + + if (ai == NULL) + ret = M_ASN1_INTEGER_new(); + else + ret = ai; + if (ret == NULL) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); + goto err; + } + if (BN_is_negative(bn) && !BN_is_zero(bn)) + ret->type = V_ASN1_NEG_INTEGER; + else + ret->type = V_ASN1_INTEGER; + j = BN_num_bits(bn); + len = ((j == 0) ? 0 : ((j / 8) + 1)); + if (ret->length < len + 4) { + unsigned char *new_data = OPENSSL_realloc(ret->data, len + 4); + if (!new_data) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + goto err; + } + ret->data = new_data; + } + ret->length = BN_bn2bin(bn, ret->data); + /* Correct zero case */ + if (!ret->length) { + ret->data[0] = 0; + ret->length = 1; + } + return (ret); + err: + if (ret != ai) + M_ASN1_INTEGER_free(ret); + return (NULL); +} + +BIGNUM *ASN1_INTEGER_to_BN(const ASN1_INTEGER *ai, BIGNUM *bn) +{ + BIGNUM *ret; + + if ((ret = BN_bin2bn(ai->data, ai->length, bn)) == NULL) + OPENSSL_PUT_ERROR(ASN1, ASN1_R_BN_LIB); + else if (ai->type == V_ASN1_NEG_INTEGER) + BN_set_negative(ret, 1); + return (ret); +} diff --git a/external/boringssl/crypto/asn1/a_mbstr.c b/external/boringssl/crypto/asn1/a_mbstr.c new file mode 100644 index 0000000000..30fff82a7f --- /dev/null +++ b/external/boringssl/crypto/asn1/a_mbstr.c @@ -0,0 +1,409 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include +#include + +static int traverse_string(const unsigned char *p, int len, int inform, + int (*rfunc) (unsigned long value, void *in), + void *arg); +static int in_utf8(unsigned long value, void *arg); +static int out_utf8(unsigned long value, void *arg); +static int type_str(unsigned long value, void *arg); +static int cpy_asc(unsigned long value, void *arg); +static int cpy_bmp(unsigned long value, void *arg); +static int cpy_univ(unsigned long value, void *arg); +static int cpy_utf8(unsigned long value, void *arg); +static int is_printable(unsigned long value); + +/* + * These functions take a string in UTF8, ASCII or multibyte form and a mask + * of permissible ASN1 string types. It then works out the minimal type + * (using the order Printable < IA5 < T61 < BMP < Universal < UTF8) and + * creates a string of the correct type with the supplied data. Yes this is + * horrible: it has to be :-( The 'ncopy' form checks minimum and maximum + * size limits too. + */ + +int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len, + int inform, unsigned long mask) +{ + return ASN1_mbstring_ncopy(out, in, len, inform, mask, 0, 0); +} + +int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len, + int inform, unsigned long mask, + long minsize, long maxsize) +{ + int str_type; + int ret; + char free_out; + int outform, outlen = 0; + ASN1_STRING *dest; + unsigned char *p; + int nchar; + char strbuf[32]; + int (*cpyfunc) (unsigned long, void *) = NULL; + if (len == -1) + len = strlen((const char *)in); + if (!mask) + mask = DIRSTRING_TYPE; + + /* First do a string check and work out the number of characters */ + switch (inform) { + + case MBSTRING_BMP: + if (len & 1) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_BMPSTRING_LENGTH); + return -1; + } + nchar = len >> 1; + break; + + case MBSTRING_UNIV: + if (len & 3) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_UNIVERSALSTRING_LENGTH); + return -1; + } + nchar = len >> 2; + break; + + case MBSTRING_UTF8: + nchar = 0; + /* This counts the characters and does utf8 syntax checking */ + ret = traverse_string(in, len, MBSTRING_UTF8, in_utf8, &nchar); + if (ret < 0) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_UTF8STRING); + return -1; + } + break; + + case MBSTRING_ASC: + nchar = len; + break; + + default: + OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_FORMAT); + return -1; + } + + if ((minsize > 0) && (nchar < minsize)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_SHORT); + BIO_snprintf(strbuf, sizeof strbuf, "%ld", minsize); + ERR_add_error_data(2, "minsize=", strbuf); + return -1; + } + + if ((maxsize > 0) && (nchar > maxsize)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_LONG); + BIO_snprintf(strbuf, sizeof strbuf, "%ld", maxsize); + ERR_add_error_data(2, "maxsize=", strbuf); + return -1; + } + + /* Now work out minimal type (if any) */ + if (traverse_string(in, len, inform, type_str, &mask) < 0) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_CHARACTERS); + return -1; + } + + /* Now work out output format and string type */ + outform = MBSTRING_ASC; + if (mask & B_ASN1_PRINTABLESTRING) + str_type = V_ASN1_PRINTABLESTRING; + else if (mask & B_ASN1_IA5STRING) + str_type = V_ASN1_IA5STRING; + else if (mask & B_ASN1_T61STRING) + str_type = V_ASN1_T61STRING; + else if (mask & B_ASN1_BMPSTRING) { + str_type = V_ASN1_BMPSTRING; + outform = MBSTRING_BMP; + } else if (mask & B_ASN1_UNIVERSALSTRING) { + str_type = V_ASN1_UNIVERSALSTRING; + outform = MBSTRING_UNIV; + } else { + str_type = V_ASN1_UTF8STRING; + outform = MBSTRING_UTF8; + } + if (!out) + return str_type; + if (*out) { + free_out = 0; + dest = *out; + if (dest->data) { + dest->length = 0; + OPENSSL_free(dest->data); + dest->data = NULL; + } + dest->type = str_type; + } else { + free_out = 1; + dest = ASN1_STRING_type_new(str_type); + if (!dest) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + return -1; + } + *out = dest; + } + /* If both the same type just copy across */ + if (inform == outform) { + if (!ASN1_STRING_set(dest, in, len)) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + return -1; + } + return str_type; + } + + /* Work out how much space the destination will need */ + switch (outform) { + case MBSTRING_ASC: + outlen = nchar; + cpyfunc = cpy_asc; + break; + + case MBSTRING_BMP: + outlen = nchar << 1; + cpyfunc = cpy_bmp; + break; + + case MBSTRING_UNIV: + outlen = nchar << 2; + cpyfunc = cpy_univ; + break; + + case MBSTRING_UTF8: + outlen = 0; + traverse_string(in, len, inform, out_utf8, &outlen); + cpyfunc = cpy_utf8; + break; + } + if (!(p = OPENSSL_malloc(outlen + 1))) { + if (free_out) + ASN1_STRING_free(dest); + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + return -1; + } + dest->length = outlen; + dest->data = p; + p[outlen] = 0; + traverse_string(in, len, inform, cpyfunc, &p); + return str_type; +} + +/* + * This function traverses a string and passes the value of each character to + * an optional function along with a void * argument. + */ + +static int traverse_string(const unsigned char *p, int len, int inform, + int (*rfunc) (unsigned long value, void *in), + void *arg) +{ + unsigned long value; + int ret; + while (len) { + if (inform == MBSTRING_ASC) { + value = *p++; + len--; + } else if (inform == MBSTRING_BMP) { + value = *p++ << 8; + value |= *p++; + len -= 2; + } else if (inform == MBSTRING_UNIV) { + value = ((unsigned long)*p++) << 24; + value |= ((unsigned long)*p++) << 16; + value |= *p++ << 8; + value |= *p++; + len -= 4; + } else { + ret = UTF8_getc(p, len, &value); + if (ret < 0) + return -1; + len -= ret; + p += ret; + } + if (rfunc) { + ret = rfunc(value, arg); + if (ret <= 0) + return ret; + } + } + return 1; +} + +/* Various utility functions for traverse_string */ + +/* Just count number of characters */ + +static int in_utf8(unsigned long value, void *arg) +{ + int *nchar; + nchar = arg; + (*nchar)++; + return 1; +} + +/* Determine size of output as a UTF8 String */ + +static int out_utf8(unsigned long value, void *arg) +{ + int *outlen; + outlen = arg; + *outlen += UTF8_putc(NULL, -1, value); + return 1; +} + +/* + * Determine the "type" of a string: check each character against a supplied + * "mask". + */ + +static int type_str(unsigned long value, void *arg) +{ + unsigned long types; + types = *((unsigned long *)arg); + if ((types & B_ASN1_PRINTABLESTRING) && !is_printable(value)) + types &= ~B_ASN1_PRINTABLESTRING; + if ((types & B_ASN1_IA5STRING) && (value > 127)) + types &= ~B_ASN1_IA5STRING; + if ((types & B_ASN1_T61STRING) && (value > 0xff)) + types &= ~B_ASN1_T61STRING; + if ((types & B_ASN1_BMPSTRING) && (value > 0xffff)) + types &= ~B_ASN1_BMPSTRING; + if (!types) + return -1; + *((unsigned long *)arg) = types; + return 1; +} + +/* Copy one byte per character ASCII like strings */ + +static int cpy_asc(unsigned long value, void *arg) +{ + unsigned char **p, *q; + p = arg; + q = *p; + *q = (unsigned char)value; + (*p)++; + return 1; +} + +/* Copy two byte per character BMPStrings */ + +static int cpy_bmp(unsigned long value, void *arg) +{ + unsigned char **p, *q; + p = arg; + q = *p; + *q++ = (unsigned char)((value >> 8) & 0xff); + *q = (unsigned char)(value & 0xff); + *p += 2; + return 1; +} + +/* Copy four byte per character UniversalStrings */ + +static int cpy_univ(unsigned long value, void *arg) +{ + unsigned char **p, *q; + p = arg; + q = *p; + *q++ = (unsigned char)((value >> 24) & 0xff); + *q++ = (unsigned char)((value >> 16) & 0xff); + *q++ = (unsigned char)((value >> 8) & 0xff); + *q = (unsigned char)(value & 0xff); + *p += 4; + return 1; +} + +/* Copy to a UTF8String */ + +static int cpy_utf8(unsigned long value, void *arg) +{ + unsigned char **p; + int ret; + p = arg; + /* We already know there is enough room so pass 0xff as the length */ + ret = UTF8_putc(*p, 0xff, value); + *p += ret; + return 1; +} + +/* Return 1 if the character is permitted in a PrintableString */ +static int is_printable(unsigned long value) +{ + int ch; + if (value > 0x7f) + return 0; + ch = (int)value; + /* + * Note: we can't use 'isalnum' because certain accented characters may + * count as alphanumeric in some environments. + */ + if ((ch >= 'a') && (ch <= 'z')) + return 1; + if ((ch >= 'A') && (ch <= 'Z')) + return 1; + if ((ch >= '0') && (ch <= '9')) + return 1; + if ((ch == ' ') || strchr("'()+,-./:=?", ch)) + return 1; + return 0; +} diff --git a/external/boringssl/crypto/asn1/a_object.c b/external/boringssl/crypto/asn1/a_object.c new file mode 100644 index 0000000000..10f3839876 --- /dev/null +++ b/external/boringssl/crypto/asn1/a_object.c @@ -0,0 +1,396 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +#include +#include +#include + +int i2d_ASN1_OBJECT(ASN1_OBJECT *a, unsigned char **pp) +{ + unsigned char *p; + int objsize; + + if ((a == NULL) || (a->data == NULL)) + return (0); + + objsize = ASN1_object_size(0, a->length, V_ASN1_OBJECT); + if (pp == NULL) + return objsize; + + p = *pp; + ASN1_put_object(&p, 0, a->length, V_ASN1_OBJECT, V_ASN1_UNIVERSAL); + memcpy(p, a->data, a->length); + p += a->length; + + *pp = p; + return (objsize); +} + +int a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num) +{ + int i, first, len = 0, c, use_bn; + char ftmp[24], *tmp = ftmp; + int tmpsize = sizeof ftmp; + const char *p; + unsigned long l; + BIGNUM *bl = NULL; + + if (num == 0) + return (0); + else if (num == -1) + num = strlen(buf); + + p = buf; + c = *(p++); + num--; + if ((c >= '0') && (c <= '2')) { + first = c - '0'; + } else { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_FIRST_NUM_TOO_LARGE); + goto err; + } + + if (num <= 0) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_SECOND_NUMBER); + goto err; + } + c = *(p++); + num--; + for (;;) { + if (num <= 0) + break; + if ((c != '.') && (c != ' ')) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_SEPARATOR); + goto err; + } + l = 0; + use_bn = 0; + for (;;) { + if (num <= 0) + break; + num--; + c = *(p++); + if ((c == ' ') || (c == '.')) + break; + if ((c < '0') || (c > '9')) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_DIGIT); + goto err; + } + if (!use_bn && l >= ((ULONG_MAX - 80) / 10L)) { + use_bn = 1; + if (!bl) + bl = BN_new(); + if (!bl || !BN_set_word(bl, l)) + goto err; + } + if (use_bn) { + if (!BN_mul_word(bl, 10L) + || !BN_add_word(bl, c - '0')) + goto err; + } else + l = l * 10L + (long)(c - '0'); + } + if (len == 0) { + if ((first < 2) && (l >= 40)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_SECOND_NUMBER_TOO_LARGE); + goto err; + } + if (use_bn) { + if (!BN_add_word(bl, first * 40)) + goto err; + } else + l += (long)first *40; + } + i = 0; + if (use_bn) { + int blsize; + blsize = BN_num_bits(bl); + blsize = (blsize + 6) / 7; + if (blsize > tmpsize) { + if (tmp != ftmp) + OPENSSL_free(tmp); + tmpsize = blsize + 32; + tmp = OPENSSL_malloc(tmpsize); + if (!tmp) + goto err; + } + while (blsize--) + tmp[i++] = (unsigned char)BN_div_word(bl, 0x80L); + } else { + + for (;;) { + tmp[i++] = (unsigned char)l & 0x7f; + l >>= 7L; + if (l == 0L) + break; + } + + } + if (out != NULL) { + if (len + i > olen) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_BUFFER_TOO_SMALL); + goto err; + } + while (--i > 0) + out[len++] = tmp[i] | 0x80; + out[len++] = tmp[0]; + } else + len += i; + } + if (tmp != ftmp) + OPENSSL_free(tmp); + if (bl) + BN_free(bl); + return (len); + err: + if (tmp != ftmp) + OPENSSL_free(tmp); + if (bl) + BN_free(bl); + return (0); +} + +int i2t_ASN1_OBJECT(char *buf, int buf_len, ASN1_OBJECT *a) +{ + return OBJ_obj2txt(buf, buf_len, a, 0); +} + +int i2a_ASN1_OBJECT(BIO *bp, ASN1_OBJECT *a) +{ + char buf[80], *p = buf; + int i; + + if ((a == NULL) || (a->data == NULL)) + return (BIO_write(bp, "NULL", 4)); + i = i2t_ASN1_OBJECT(buf, sizeof buf, a); + if (i > (int)(sizeof(buf) - 1)) { + p = OPENSSL_malloc(i + 1); + if (!p) + return -1; + i2t_ASN1_OBJECT(p, i + 1, a); + } + if (i <= 0) + return BIO_write(bp, "", 9); + BIO_write(bp, p, i); + if (p != buf) + OPENSSL_free(p); + return (i); +} + +ASN1_OBJECT *d2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp, + long length) +{ + const unsigned char *p; + long len; + int tag, xclass; + int inf, i; + ASN1_OBJECT *ret = NULL; + p = *pp; + inf = ASN1_get_object(&p, &len, &tag, &xclass, length); + if (inf & 0x80) { + i = ASN1_R_BAD_OBJECT_HEADER; + goto err; + } + + if (tag != V_ASN1_OBJECT) { + i = ASN1_R_EXPECTING_AN_OBJECT; + goto err; + } + ret = c2i_ASN1_OBJECT(a, &p, len); + if (ret) + *pp = p; + return ret; + err: + OPENSSL_PUT_ERROR(ASN1, i); + return (NULL); +} + +ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp, + long len) +{ + ASN1_OBJECT *ret = NULL; + const unsigned char *p; + unsigned char *data; + int i, length; + + /* + * Sanity check OID encoding. Need at least one content octet. MSB must + * be clear in the last octet. can't have leading 0x80 in subidentifiers, + * see: X.690 8.19.2 + */ + if (len <= 0 || len > INT_MAX || pp == NULL || (p = *pp) == NULL || + p[len - 1] & 0x80) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_OBJECT_ENCODING); + return NULL; + } + /* Now 0 < len <= INT_MAX, so the cast is safe. */ + length = (int)len; + for (i = 0; i < length; i++, p++) { + if (*p == 0x80 && (!i || !(p[-1] & 0x80))) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_OBJECT_ENCODING); + return NULL; + } + } + + /* + * only the ASN1_OBJECTs from the 'table' will have values for ->sn or + * ->ln + */ + if ((a == NULL) || ((*a) == NULL) || + !((*a)->flags & ASN1_OBJECT_FLAG_DYNAMIC)) { + if ((ret = ASN1_OBJECT_new()) == NULL) + return (NULL); + } else + ret = (*a); + + p = *pp; + /* detach data from object */ + data = (unsigned char *)ret->data; + ret->data = NULL; + /* once detached we can change it */ + if ((data == NULL) || (ret->length < length)) { + ret->length = 0; + if (data != NULL) + OPENSSL_free(data); + data = (unsigned char *)OPENSSL_malloc(length); + if (data == NULL) { + i = ERR_R_MALLOC_FAILURE; + goto err; + } + ret->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA; + } + memcpy(data, p, length); + /* reattach data to object, after which it remains const */ + ret->data = data; + ret->length = length; + ret->sn = NULL; + ret->ln = NULL; + /* ret->flags=ASN1_OBJECT_FLAG_DYNAMIC; we know it is dynamic */ + p += length; + + if (a != NULL) + (*a) = ret; + *pp = p; + return (ret); + err: + OPENSSL_PUT_ERROR(ASN1, i); + if ((ret != NULL) && ((a == NULL) || (*a != ret))) + ASN1_OBJECT_free(ret); + return (NULL); +} + +ASN1_OBJECT *ASN1_OBJECT_new(void) +{ + ASN1_OBJECT *ret; + + ret = (ASN1_OBJECT *)OPENSSL_malloc(sizeof(ASN1_OBJECT)); + if (ret == NULL) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + return (NULL); + } + ret->length = 0; + ret->data = NULL; + ret->nid = 0; + ret->sn = NULL; + ret->ln = NULL; + ret->flags = ASN1_OBJECT_FLAG_DYNAMIC; + return (ret); +} + +void ASN1_OBJECT_free(ASN1_OBJECT *a) +{ + if (a == NULL) + return; + if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_STRINGS) { +#ifndef CONST_STRICT /* disable purely for compile-time strict + * const checking. Doing this on a "real" + * compile will cause memory leaks */ + if (a->sn != NULL) + OPENSSL_free((void *)a->sn); + if (a->ln != NULL) + OPENSSL_free((void *)a->ln); +#endif + a->sn = a->ln = NULL; + } + if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_DATA) { + if (a->data != NULL) + OPENSSL_free((void *)a->data); + a->data = NULL; + a->length = 0; + } + if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC) + OPENSSL_free(a); +} + +ASN1_OBJECT *ASN1_OBJECT_create(int nid, unsigned char *data, int len, + const char *sn, const char *ln) +{ + ASN1_OBJECT o; + + o.sn = sn; + o.ln = ln; + o.data = data; + o.nid = nid; + o.length = len; + o.flags = ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS | + ASN1_OBJECT_FLAG_DYNAMIC_DATA; + return (OBJ_dup(&o)); +} diff --git a/external/boringssl/crypto/asn1/a_octet.c b/external/boringssl/crypto/asn1/a_octet.c new file mode 100644 index 0000000000..2e74d6bfdf --- /dev/null +++ b/external/boringssl/crypto/asn1/a_octet.c @@ -0,0 +1,77 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +ASN1_OCTET_STRING *ASN1_OCTET_STRING_dup(const ASN1_OCTET_STRING *x) +{ + return M_ASN1_OCTET_STRING_dup(x); +} + +int ASN1_OCTET_STRING_cmp(const ASN1_OCTET_STRING *a, + const ASN1_OCTET_STRING *b) +{ + return M_ASN1_OCTET_STRING_cmp(a, b); +} + +int ASN1_OCTET_STRING_set(ASN1_OCTET_STRING *x, const unsigned char *d, + int len) +{ + return M_ASN1_OCTET_STRING_set(x, d, len); +} diff --git a/external/boringssl/crypto/asn1/a_print.c b/external/boringssl/crypto/asn1/a_print.c new file mode 100644 index 0000000000..aee54fa496 --- /dev/null +++ b/external/boringssl/crypto/asn1/a_print.c @@ -0,0 +1,121 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +int ASN1_PRINTABLE_type(const unsigned char *s, int len) +{ + int c; + int ia5 = 0; + int t61 = 0; + + if (len <= 0) + len = -1; + if (s == NULL) + return (V_ASN1_PRINTABLESTRING); + + while ((*s) && (len-- != 0)) { + c = *(s++); + if (!(((c >= 'a') && (c <= 'z')) || + ((c >= 'A') && (c <= 'Z')) || + (c == ' ') || + ((c >= '0') && (c <= '9')) || + (c == ' ') || (c == '\'') || + (c == '(') || (c == ')') || + (c == '+') || (c == ',') || + (c == '-') || (c == '.') || + (c == '/') || (c == ':') || (c == '=') || (c == '?'))) + ia5 = 1; + if (c & 0x80) + t61 = 1; + } + if (t61) + return (V_ASN1_T61STRING); + if (ia5) + return (V_ASN1_IA5STRING); + return (V_ASN1_PRINTABLESTRING); +} + +int ASN1_UNIVERSALSTRING_to_string(ASN1_UNIVERSALSTRING *s) +{ + int i; + unsigned char *p; + + if (s->type != V_ASN1_UNIVERSALSTRING) + return (0); + if ((s->length % 4) != 0) + return (0); + p = s->data; + for (i = 0; i < s->length; i += 4) { + if ((p[0] != '\0') || (p[1] != '\0') || (p[2] != '\0')) + break; + else + p += 4; + } + if (i < s->length) + return (0); + p = s->data; + for (i = 3; i < s->length; i += 4) { + *(p++) = s->data[i]; + } + *(p) = '\0'; + s->length /= 4; + s->type = ASN1_PRINTABLE_type(s->data, s->length); + return (1); +} diff --git a/external/boringssl/crypto/asn1/a_strnid.c b/external/boringssl/crypto/asn1/a_strnid.c new file mode 100644 index 0000000000..c558bce6c1 --- /dev/null +++ b/external/boringssl/crypto/asn1/a_strnid.c @@ -0,0 +1,309 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include /* For bsearch */ +#include + +#include +#include +#include + +static STACK_OF(ASN1_STRING_TABLE) *stable = NULL; +static void st_free(ASN1_STRING_TABLE *tbl); + +/* + * This is the global mask for the mbstring functions: this is use to mask + * out certain types (such as BMPString and UTF8String) because certain + * software (e.g. Netscape) has problems with them. + */ + +static unsigned long global_mask = B_ASN1_UTF8STRING; + +void ASN1_STRING_set_default_mask(unsigned long mask) +{ + global_mask = mask; +} + +unsigned long ASN1_STRING_get_default_mask(void) +{ + return global_mask; +} + +/* + * This function sets the default to various "flavours" of configuration. + * based on an ASCII string. Currently this is: MASK:XXXX : a numerical mask + * value. nobmp : Don't use BMPStrings (just Printable, T61). pkix : PKIX + * recommendation in RFC2459. utf8only : only use UTF8Strings (RFC2459 + * recommendation for 2004). default: the default value, Printable, T61, BMP. + */ + +int ASN1_STRING_set_default_mask_asc(const char *p) +{ + unsigned long mask; + char *end; + if (!strncmp(p, "MASK:", 5)) { + if (!p[5]) + return 0; + mask = strtoul(p + 5, &end, 0); + if (*end) + return 0; + } else if (!strcmp(p, "nombstr")) + mask = ~((unsigned long)(B_ASN1_BMPSTRING | B_ASN1_UTF8STRING)); + else if (!strcmp(p, "pkix")) + mask = ~((unsigned long)B_ASN1_T61STRING); + else if (!strcmp(p, "utf8only")) + mask = B_ASN1_UTF8STRING; + else if (!strcmp(p, "default")) + mask = 0xFFFFFFFFL; + else + return 0; + ASN1_STRING_set_default_mask(mask); + return 1; +} + +/* + * The following function generates an ASN1_STRING based on limits in a + * table. Frequently the types and length of an ASN1_STRING are restricted by + * a corresponding OID. For example certificates and certificate requests. + */ + +ASN1_STRING *ASN1_STRING_set_by_NID(ASN1_STRING **out, + const unsigned char *in, int inlen, + int inform, int nid) +{ + ASN1_STRING_TABLE *tbl; + ASN1_STRING *str = NULL; + unsigned long mask; + int ret; + if (!out) + out = &str; + tbl = ASN1_STRING_TABLE_get(nid); + if (tbl) { + mask = tbl->mask; + if (!(tbl->flags & STABLE_NO_MASK)) + mask &= global_mask; + ret = ASN1_mbstring_ncopy(out, in, inlen, inform, mask, + tbl->minsize, tbl->maxsize); + } else + ret = + ASN1_mbstring_copy(out, in, inlen, inform, + DIRSTRING_TYPE & global_mask); + if (ret <= 0) + return NULL; + return *out; +} + +/* + * Now the tables and helper functions for the string table: + */ + +/* size limits: this stuff is taken straight from RFC3280 */ + +#define ub_name 32768 +#define ub_common_name 64 +#define ub_locality_name 128 +#define ub_state_name 128 +#define ub_organization_name 64 +#define ub_organization_unit_name 64 +#define ub_title 64 +#define ub_email_address 128 +#define ub_serial_number 64 + +/* This table must be kept in NID order */ + +static const ASN1_STRING_TABLE tbl_standard[] = { + {NID_commonName, 1, ub_common_name, DIRSTRING_TYPE, 0}, + {NID_countryName, 2, 2, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK}, + {NID_localityName, 1, ub_locality_name, DIRSTRING_TYPE, 0}, + {NID_stateOrProvinceName, 1, ub_state_name, DIRSTRING_TYPE, 0}, + {NID_organizationName, 1, ub_organization_name, DIRSTRING_TYPE, 0}, + {NID_organizationalUnitName, 1, ub_organization_unit_name, DIRSTRING_TYPE, + 0}, + {NID_pkcs9_emailAddress, 1, ub_email_address, B_ASN1_IA5STRING, + STABLE_NO_MASK}, + {NID_pkcs9_unstructuredName, 1, -1, PKCS9STRING_TYPE, 0}, + {NID_pkcs9_challengePassword, 1, -1, PKCS9STRING_TYPE, 0}, + {NID_pkcs9_unstructuredAddress, 1, -1, DIRSTRING_TYPE, 0}, + {NID_givenName, 1, ub_name, DIRSTRING_TYPE, 0}, + {NID_surname, 1, ub_name, DIRSTRING_TYPE, 0}, + {NID_initials, 1, ub_name, DIRSTRING_TYPE, 0}, + {NID_serialNumber, 1, ub_serial_number, B_ASN1_PRINTABLESTRING, + STABLE_NO_MASK}, + {NID_friendlyName, -1, -1, B_ASN1_BMPSTRING, STABLE_NO_MASK}, + {NID_name, 1, ub_name, DIRSTRING_TYPE, 0}, + {NID_dnQualifier, -1, -1, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK}, + {NID_domainComponent, 1, -1, B_ASN1_IA5STRING, STABLE_NO_MASK}, + {NID_ms_csp_name, -1, -1, B_ASN1_BMPSTRING, STABLE_NO_MASK} +}; + +static int sk_table_cmp(const ASN1_STRING_TABLE **a, + const ASN1_STRING_TABLE **b) +{ + return (*a)->nid - (*b)->nid; +} + +static int table_cmp(const void *in_a, const void *in_b) +{ + const ASN1_STRING_TABLE *a = in_a; + const ASN1_STRING_TABLE *b = in_b; + return a->nid - b->nid; +} + +ASN1_STRING_TABLE *ASN1_STRING_TABLE_get(int nid) +{ + int found; + size_t idx; + ASN1_STRING_TABLE *ttmp; + ASN1_STRING_TABLE fnd; + fnd.nid = nid; + + ttmp = + bsearch(&fnd, tbl_standard, + sizeof(tbl_standard) / sizeof(ASN1_STRING_TABLE), + sizeof(ASN1_STRING_TABLE), table_cmp); + if (ttmp) + return ttmp; + if (!stable) + return NULL; + found = sk_ASN1_STRING_TABLE_find(stable, &idx, &fnd); + if (!found) + return NULL; + return sk_ASN1_STRING_TABLE_value(stable, idx); +} + +int ASN1_STRING_TABLE_add(int nid, + long minsize, long maxsize, unsigned long mask, + unsigned long flags) +{ + ASN1_STRING_TABLE *tmp; + char new_nid = 0; + flags &= ~STABLE_FLAGS_MALLOC; + if (!stable) + stable = sk_ASN1_STRING_TABLE_new(sk_table_cmp); + if (!stable) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + return 0; + } + if (!(tmp = ASN1_STRING_TABLE_get(nid))) { + tmp = OPENSSL_malloc(sizeof(ASN1_STRING_TABLE)); + if (!tmp) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + return 0; + } + tmp->flags = flags | STABLE_FLAGS_MALLOC; + tmp->nid = nid; + tmp->minsize = tmp->maxsize = -1; + new_nid = 1; + } else + tmp->flags = (tmp->flags & STABLE_FLAGS_MALLOC) | flags; + if (minsize != -1) + tmp->minsize = minsize; + if (maxsize != -1) + tmp->maxsize = maxsize; + tmp->mask = mask; + if (new_nid) + sk_ASN1_STRING_TABLE_push(stable, tmp); + return 1; +} + +void ASN1_STRING_TABLE_cleanup(void) +{ + STACK_OF(ASN1_STRING_TABLE) *tmp; + tmp = stable; + if (!tmp) + return; + stable = NULL; + sk_ASN1_STRING_TABLE_pop_free(tmp, st_free); +} + +static void st_free(ASN1_STRING_TABLE *tbl) +{ + if (tbl->flags & STABLE_FLAGS_MALLOC) + OPENSSL_free(tbl); +} + +#ifdef STRING_TABLE_TEST + +int main(void) +{ + ASN1_STRING_TABLE *tmp; + int i, last_nid = -1; + + for (tmp = tbl_standard, i = 0; + i < sizeof(tbl_standard) / sizeof(ASN1_STRING_TABLE); i++, tmp++) { + if (tmp->nid < last_nid) { + last_nid = 0; + break; + } + last_nid = tmp->nid; + } + + if (last_nid != 0) { + printf("Table order OK\n"); + exit(0); + } + + for (tmp = tbl_standard, i = 0; + i < sizeof(tbl_standard) / sizeof(ASN1_STRING_TABLE); i++, tmp++) + printf("Index %d, NID %d, Name=%s\n", i, tmp->nid, + OBJ_nid2ln(tmp->nid)); + + return 0; +} + +#endif diff --git a/external/boringssl/crypto/asn1/a_time.c b/external/boringssl/crypto/asn1/a_time.c new file mode 100644 index 0000000000..4391092ac1 --- /dev/null +++ b/external/boringssl/crypto/asn1/a_time.c @@ -0,0 +1,217 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include "asn1_locl.h" + +/* + * This is an implementation of the ASN1 Time structure which is: Time ::= + * CHOICE { utcTime UTCTime, generalTime GeneralizedTime } written by Steve + * Henson. + */ + +IMPLEMENT_ASN1_MSTRING(ASN1_TIME, B_ASN1_TIME) + +IMPLEMENT_ASN1_FUNCTIONS(ASN1_TIME) + +#if 0 +int i2d_ASN1_TIME(ASN1_TIME *a, unsigned char **pp) +{ + if (a->type == V_ASN1_UTCTIME || a->type == V_ASN1_GENERALIZEDTIME) + return (i2d_ASN1_bytes((ASN1_STRING *)a, pp, + a->type, V_ASN1_UNIVERSAL)); + OPENSSL_PUT_ERROR(ASN1, ASN1_R_EXPECTING_A_TIME); + return -1; +} +#endif + +ASN1_TIME *ASN1_TIME_set(ASN1_TIME *s, time_t t) +{ + return ASN1_TIME_adj(s, t, 0, 0); +} + +ASN1_TIME *ASN1_TIME_adj(ASN1_TIME *s, time_t t, + int offset_day, long offset_sec) +{ + struct tm *ts; + struct tm data; + + ts = OPENSSL_gmtime(&t, &data); + if (ts == NULL) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_ERROR_GETTING_TIME); + return NULL; + } + if (offset_day || offset_sec) { + if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec)) + return NULL; + } + if ((ts->tm_year >= 50) && (ts->tm_year < 150)) + return ASN1_UTCTIME_adj(s, t, offset_day, offset_sec); + return ASN1_GENERALIZEDTIME_adj(s, t, offset_day, offset_sec); +} + +int ASN1_TIME_check(ASN1_TIME *t) +{ + if (t->type == V_ASN1_GENERALIZEDTIME) + return ASN1_GENERALIZEDTIME_check(t); + else if (t->type == V_ASN1_UTCTIME) + return ASN1_UTCTIME_check(t); + return 0; +} + +/* Convert an ASN1_TIME structure to GeneralizedTime */ +ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *t, + ASN1_GENERALIZEDTIME **out) +{ + ASN1_GENERALIZEDTIME *ret; + char *str; + int newlen; + + if (!ASN1_TIME_check(t)) + return NULL; + + if (!out || !*out) { + if (!(ret = ASN1_GENERALIZEDTIME_new())) + return NULL; + if (out) + *out = ret; + } else + ret = *out; + + /* If already GeneralizedTime just copy across */ + if (t->type == V_ASN1_GENERALIZEDTIME) { + if (!ASN1_STRING_set(ret, t->data, t->length)) + return NULL; + return ret; + } + + /* grow the string */ + if (!ASN1_STRING_set(ret, NULL, t->length + 2)) + return NULL; + /* ASN1_STRING_set() allocated 'len + 1' bytes. */ + newlen = t->length + 2 + 1; + str = (char *)ret->data; + /* Work out the century and prepend */ + if (t->data[0] >= '5') + BUF_strlcpy(str, "19", newlen); + else + BUF_strlcpy(str, "20", newlen); + + BUF_strlcat(str, (char *)t->data, newlen); + + return ret; +} + +int ASN1_TIME_set_string(ASN1_TIME *s, const char *str) +{ + ASN1_TIME t; + + t.length = strlen(str); + t.data = (unsigned char *)str; + t.flags = 0; + + t.type = V_ASN1_UTCTIME; + + if (!ASN1_TIME_check(&t)) { + t.type = V_ASN1_GENERALIZEDTIME; + if (!ASN1_TIME_check(&t)) + return 0; + } + + if (s && !ASN1_STRING_copy((ASN1_STRING *)s, (ASN1_STRING *)&t)) + return 0; + + return 1; +} + +static int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *t) +{ + if (t == NULL) { + time_t now_t; + time(&now_t); + if (OPENSSL_gmtime(&now_t, tm)) + return 1; + return 0; + } + + if (t->type == V_ASN1_UTCTIME) + return asn1_utctime_to_tm(tm, t); + else if (t->type == V_ASN1_GENERALIZEDTIME) + return asn1_generalizedtime_to_tm(tm, t); + + return 0; +} + +int ASN1_TIME_diff(int *pday, int *psec, + const ASN1_TIME *from, const ASN1_TIME *to) +{ + struct tm tm_from, tm_to; + if (!asn1_time_to_tm(&tm_from, from)) + return 0; + if (!asn1_time_to_tm(&tm_to, to)) + return 0; + return OPENSSL_gmtime_diff(pday, psec, &tm_from, &tm_to); +} diff --git a/external/boringssl/crypto/asn1/a_type.c b/external/boringssl/crypto/asn1/a_type.c new file mode 100644 index 0000000000..734ff8b4d4 --- /dev/null +++ b/external/boringssl/crypto/asn1/a_type.c @@ -0,0 +1,151 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include +#include +#include + +int ASN1_TYPE_get(ASN1_TYPE *a) +{ + if ((a->value.ptr != NULL) || (a->type == V_ASN1_NULL)) + return (a->type); + else + return (0); +} + +void ASN1_TYPE_set(ASN1_TYPE *a, int type, void *value) +{ + if (a->value.ptr != NULL) { + ASN1_TYPE **tmp_a = &a; + ASN1_primitive_free((ASN1_VALUE **)tmp_a, NULL); + } + a->type = type; + if (type == V_ASN1_BOOLEAN) + a->value.boolean = value ? 0xff : 0; + else + a->value.ptr = value; +} + +int ASN1_TYPE_set1(ASN1_TYPE *a, int type, const void *value) +{ + if (!value || (type == V_ASN1_BOOLEAN)) { + void *p = (void *)value; + ASN1_TYPE_set(a, type, p); + } else if (type == V_ASN1_OBJECT) { + ASN1_OBJECT *odup; + odup = OBJ_dup(value); + if (!odup) + return 0; + ASN1_TYPE_set(a, type, odup); + } else { + ASN1_STRING *sdup; + sdup = ASN1_STRING_dup(value); + if (!sdup) + return 0; + ASN1_TYPE_set(a, type, sdup); + } + return 1; +} + +/* Returns 0 if they are equal, != 0 otherwise. */ +int ASN1_TYPE_cmp(const ASN1_TYPE *a, const ASN1_TYPE *b) +{ + int result = -1; + + if (!a || !b || a->type != b->type) + return -1; + + switch (a->type) { + case V_ASN1_OBJECT: + result = OBJ_cmp(a->value.object, b->value.object); + break; + case V_ASN1_NULL: + result = 0; /* They do not have content. */ + break; + case V_ASN1_BOOLEAN: + result = a->value.boolean - b->value.boolean; + break; + case V_ASN1_INTEGER: + case V_ASN1_ENUMERATED: + case V_ASN1_BIT_STRING: + case V_ASN1_OCTET_STRING: + case V_ASN1_SEQUENCE: + case V_ASN1_SET: + case V_ASN1_NUMERICSTRING: + case V_ASN1_PRINTABLESTRING: + case V_ASN1_T61STRING: + case V_ASN1_VIDEOTEXSTRING: + case V_ASN1_IA5STRING: + case V_ASN1_UTCTIME: + case V_ASN1_GENERALIZEDTIME: + case V_ASN1_GRAPHICSTRING: + case V_ASN1_VISIBLESTRING: + case V_ASN1_GENERALSTRING: + case V_ASN1_UNIVERSALSTRING: + case V_ASN1_BMPSTRING: + case V_ASN1_UTF8STRING: + case V_ASN1_OTHER: + default: + result = ASN1_STRING_cmp((ASN1_STRING *)a->value.ptr, + (ASN1_STRING *)b->value.ptr); + break; + } + + return result; +} diff --git a/external/boringssl/crypto/asn1/a_utctm.c b/external/boringssl/crypto/asn1/a_utctm.c new file mode 100644 index 0000000000..5a55bd24df --- /dev/null +++ b/external/boringssl/crypto/asn1/a_utctm.c @@ -0,0 +1,335 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +#include +#include +#include + +#include "asn1_locl.h" + +#if 0 +int i2d_ASN1_UTCTIME(ASN1_UTCTIME *a, unsigned char **pp) +{ + return (i2d_ASN1_bytes((ASN1_STRING *)a, pp, + V_ASN1_UTCTIME, V_ASN1_UNIVERSAL)); +} + +ASN1_UTCTIME *d2i_ASN1_UTCTIME(ASN1_UTCTIME **a, unsigned char **pp, + long length) +{ + ASN1_UTCTIME *ret = NULL; + + ret = (ASN1_UTCTIME *)d2i_ASN1_bytes((ASN1_STRING **)a, pp, length, + V_ASN1_UTCTIME, V_ASN1_UNIVERSAL); + if (ret == NULL) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_NESTED_ASN1_ERROR); + return (NULL); + } + if (!ASN1_UTCTIME_check(ret)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_TIME_FORMAT); + goto err; + } + + return (ret); + err: + if ((ret != NULL) && ((a == NULL) || (*a != ret))) + M_ASN1_UTCTIME_free(ret); + return (NULL); +} + +#endif + +int asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d) +{ + static const int min[8] = { 0, 1, 1, 0, 0, 0, 0, 0 }; + static const int max[8] = { 99, 12, 31, 23, 59, 59, 12, 59 }; + char *a; + int n, i, l, o; + + if (d->type != V_ASN1_UTCTIME) + return (0); + l = d->length; + a = (char *)d->data; + o = 0; + + if (l < 11) + goto err; + for (i = 0; i < 6; i++) { + if ((i == 5) && ((a[o] == 'Z') || (a[o] == '+') || (a[o] == '-'))) { + i++; + if (tm) + tm->tm_sec = 0; + break; + } + if ((a[o] < '0') || (a[o] > '9')) + goto err; + n = a[o] - '0'; + if (++o > l) + goto err; + + if ((a[o] < '0') || (a[o] > '9')) + goto err; + n = (n * 10) + a[o] - '0'; + if (++o > l) + goto err; + + if ((n < min[i]) || (n > max[i])) + goto err; + if (tm) { + switch (i) { + case 0: + tm->tm_year = n < 50 ? n + 100 : n; + break; + case 1: + tm->tm_mon = n - 1; + break; + case 2: + tm->tm_mday = n; + break; + case 3: + tm->tm_hour = n; + break; + case 4: + tm->tm_min = n; + break; + case 5: + tm->tm_sec = n; + break; + } + } + } + if (a[o] == 'Z') + o++; + else if ((a[o] == '+') || (a[o] == '-')) { + int offsign = a[o] == '-' ? -1 : 1, offset = 0; + o++; + if (o + 4 > l) + goto err; + for (i = 6; i < 8; i++) { + if ((a[o] < '0') || (a[o] > '9')) + goto err; + n = a[o] - '0'; + o++; + if ((a[o] < '0') || (a[o] > '9')) + goto err; + n = (n * 10) + a[o] - '0'; + if ((n < min[i]) || (n > max[i])) + goto err; + if (tm) { + if (i == 6) + offset = n * 3600; + else if (i == 7) + offset += n * 60; + } + o++; + } + if (offset && !OPENSSL_gmtime_adj(tm, 0, offset * offsign)) + return 0; + } + return o == l; + err: + return 0; +} + +int ASN1_UTCTIME_check(const ASN1_UTCTIME *d) +{ + return asn1_utctime_to_tm(NULL, d); +} + +int ASN1_UTCTIME_set_string(ASN1_UTCTIME *s, const char *str) +{ + ASN1_UTCTIME t; + + t.type = V_ASN1_UTCTIME; + t.length = strlen(str); + t.data = (unsigned char *)str; + if (ASN1_UTCTIME_check(&t)) { + if (s != NULL) { + if (!ASN1_STRING_set((ASN1_STRING *)s, + (unsigned char *)str, t.length)) + return 0; + s->type = V_ASN1_UTCTIME; + } + return (1); + } else + return (0); +} + +ASN1_UTCTIME *ASN1_UTCTIME_set(ASN1_UTCTIME *s, time_t t) +{ + return ASN1_UTCTIME_adj(s, t, 0, 0); +} + +ASN1_UTCTIME *ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t, + int offset_day, long offset_sec) +{ + char *p; + struct tm *ts; + struct tm data; + size_t len = 20; + int free_s = 0; + + if (s == NULL) { + free_s = 1; + s = M_ASN1_UTCTIME_new(); + } + if (s == NULL) + goto err; + + ts = OPENSSL_gmtime(&t, &data); + if (ts == NULL) + goto err; + + if (offset_day || offset_sec) { + if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec)) + goto err; + } + + if ((ts->tm_year < 50) || (ts->tm_year >= 150)) + goto err; + + p = (char *)s->data; + if ((p == NULL) || ((size_t)s->length < len)) { + p = OPENSSL_malloc(len); + if (p == NULL) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + goto err; + } + if (s->data != NULL) + OPENSSL_free(s->data); + s->data = (unsigned char *)p; + } + + BIO_snprintf(p, len, "%02d%02d%02d%02d%02d%02dZ", ts->tm_year % 100, + ts->tm_mon + 1, ts->tm_mday, ts->tm_hour, ts->tm_min, + ts->tm_sec); + s->length = strlen(p); + s->type = V_ASN1_UTCTIME; + return (s); + err: + if (free_s && s) + M_ASN1_UTCTIME_free(s); + return NULL; +} + +int ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t) +{ + struct tm stm, ttm; + int day, sec; + + if (!asn1_utctime_to_tm(&stm, s)) + return -2; + + if (!OPENSSL_gmtime(&t, &ttm)) + return -2; + + if (!OPENSSL_gmtime_diff(&day, &sec, &ttm, &stm)) + return -2; + + if (day > 0) + return 1; + if (day < 0) + return -1; + if (sec > 0) + return 1; + if (sec < 0) + return -1; + return 0; +} + +#if 0 +time_t ASN1_UTCTIME_get(const ASN1_UTCTIME *s) +{ + struct tm tm; + int offset; + + memset(&tm, '\0', sizeof tm); + +# define g2(p) (((p)[0]-'0')*10+(p)[1]-'0') + tm.tm_year = g2(s->data); + if (tm.tm_year < 50) + tm.tm_year += 100; + tm.tm_mon = g2(s->data + 2) - 1; + tm.tm_mday = g2(s->data + 4); + tm.tm_hour = g2(s->data + 6); + tm.tm_min = g2(s->data + 8); + tm.tm_sec = g2(s->data + 10); + if (s->data[12] == 'Z') + offset = 0; + else { + offset = g2(s->data + 13) * 60 + g2(s->data + 15); + if (s->data[12] == '-') + offset = -offset; + } +# undef g2 + + return mktime(&tm) - offset * 60; /* FIXME: mktime assumes the current + * timezone instead of UTC, and unless + * we rewrite OpenSSL in Lisp we cannot + * locally change the timezone without + * possibly interfering with other + * parts of the program. timegm, which + * uses UTC, is non-standard. Also + * time_t is inappropriate for general + * UTC times because it may a 32 bit + * type. */ +} +#endif diff --git a/external/boringssl/crypto/asn1/a_utf8.c b/external/boringssl/crypto/asn1/a_utf8.c new file mode 100644 index 0000000000..1702768668 --- /dev/null +++ b/external/boringssl/crypto/asn1/a_utf8.c @@ -0,0 +1,234 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +/* UTF8 utilities */ + +/* + * This parses a UTF8 string one character at a time. It is passed a pointer + * to the string and the length of the string. It sets 'value' to the value + * of the current character. It returns the number of characters read or a + * negative error code: -1 = string too short -2 = illegal character -3 = + * subsequent characters not of the form 10xxxxxx -4 = character encoded + * incorrectly (not minimal length). + */ + +int UTF8_getc(const unsigned char *str, int len, unsigned long *val) +{ + const unsigned char *p; + unsigned long value; + int ret; + if (len <= 0) + return 0; + p = str; + + /* Check syntax and work out the encoded value (if correct) */ + if ((*p & 0x80) == 0) { + value = *p++ & 0x7f; + ret = 1; + } else if ((*p & 0xe0) == 0xc0) { + if (len < 2) + return -1; + if ((p[1] & 0xc0) != 0x80) + return -3; + value = (*p++ & 0x1f) << 6; + value |= *p++ & 0x3f; + if (value < 0x80) + return -4; + ret = 2; + } else if ((*p & 0xf0) == 0xe0) { + if (len < 3) + return -1; + if (((p[1] & 0xc0) != 0x80) + || ((p[2] & 0xc0) != 0x80)) + return -3; + value = (*p++ & 0xf) << 12; + value |= (*p++ & 0x3f) << 6; + value |= *p++ & 0x3f; + if (value < 0x800) + return -4; + ret = 3; + } else if ((*p & 0xf8) == 0xf0) { + if (len < 4) + return -1; + if (((p[1] & 0xc0) != 0x80) + || ((p[2] & 0xc0) != 0x80) + || ((p[3] & 0xc0) != 0x80)) + return -3; + value = ((unsigned long)(*p++ & 0x7)) << 18; + value |= (*p++ & 0x3f) << 12; + value |= (*p++ & 0x3f) << 6; + value |= *p++ & 0x3f; + if (value < 0x10000) + return -4; + ret = 4; + } else if ((*p & 0xfc) == 0xf8) { + if (len < 5) + return -1; + if (((p[1] & 0xc0) != 0x80) + || ((p[2] & 0xc0) != 0x80) + || ((p[3] & 0xc0) != 0x80) + || ((p[4] & 0xc0) != 0x80)) + return -3; + value = ((unsigned long)(*p++ & 0x3)) << 24; + value |= ((unsigned long)(*p++ & 0x3f)) << 18; + value |= ((unsigned long)(*p++ & 0x3f)) << 12; + value |= (*p++ & 0x3f) << 6; + value |= *p++ & 0x3f; + if (value < 0x200000) + return -4; + ret = 5; + } else if ((*p & 0xfe) == 0xfc) { + if (len < 6) + return -1; + if (((p[1] & 0xc0) != 0x80) + || ((p[2] & 0xc0) != 0x80) + || ((p[3] & 0xc0) != 0x80) + || ((p[4] & 0xc0) != 0x80) + || ((p[5] & 0xc0) != 0x80)) + return -3; + value = ((unsigned long)(*p++ & 0x1)) << 30; + value |= ((unsigned long)(*p++ & 0x3f)) << 24; + value |= ((unsigned long)(*p++ & 0x3f)) << 18; + value |= ((unsigned long)(*p++ & 0x3f)) << 12; + value |= (*p++ & 0x3f) << 6; + value |= *p++ & 0x3f; + if (value < 0x4000000) + return -4; + ret = 6; + } else + return -2; + *val = value; + return ret; +} + +/* + * This takes a character 'value' and writes the UTF8 encoded value in 'str' + * where 'str' is a buffer containing 'len' characters. Returns the number of + * characters written or -1 if 'len' is too small. 'str' can be set to NULL + * in which case it just returns the number of characters. It will need at + * most 6 characters. + */ + +int UTF8_putc(unsigned char *str, int len, unsigned long value) +{ + if (!str) + len = 6; /* Maximum we will need */ + else if (len <= 0) + return -1; + if (value < 0x80) { + if (str) + *str = (unsigned char)value; + return 1; + } + if (value < 0x800) { + if (len < 2) + return -1; + if (str) { + *str++ = (unsigned char)(((value >> 6) & 0x1f) | 0xc0); + *str = (unsigned char)((value & 0x3f) | 0x80); + } + return 2; + } + if (value < 0x10000) { + if (len < 3) + return -1; + if (str) { + *str++ = (unsigned char)(((value >> 12) & 0xf) | 0xe0); + *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80); + *str = (unsigned char)((value & 0x3f) | 0x80); + } + return 3; + } + if (value < 0x200000) { + if (len < 4) + return -1; + if (str) { + *str++ = (unsigned char)(((value >> 18) & 0x7) | 0xf0); + *str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80); + *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80); + *str = (unsigned char)((value & 0x3f) | 0x80); + } + return 4; + } + if (value < 0x4000000) { + if (len < 5) + return -1; + if (str) { + *str++ = (unsigned char)(((value >> 24) & 0x3) | 0xf8); + *str++ = (unsigned char)(((value >> 18) & 0x3f) | 0x80); + *str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80); + *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80); + *str = (unsigned char)((value & 0x3f) | 0x80); + } + return 5; + } + if (len < 6) + return -1; + if (str) { + *str++ = (unsigned char)(((value >> 30) & 0x1) | 0xfc); + *str++ = (unsigned char)(((value >> 24) & 0x3f) | 0x80); + *str++ = (unsigned char)(((value >> 18) & 0x3f) | 0x80); + *str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80); + *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80); + *str = (unsigned char)((value & 0x3f) | 0x80); + } + return 6; +} diff --git a/external/boringssl/crypto/asn1/asn1_lib.c b/external/boringssl/crypto/asn1/asn1_lib.c new file mode 100644 index 0000000000..b637e795b0 --- /dev/null +++ b/external/boringssl/crypto/asn1/asn1_lib.c @@ -0,0 +1,505 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +#include +#include +#include + +/* Cross-module errors from crypto/x509/i2d_pr.c. */ +OPENSSL_DECLARE_ERROR_REASON(ASN1, UNSUPPORTED_PUBLIC_KEY_TYPE); + +/* Cross-module errors from crypto/x509/algorithm.c. */ +OPENSSL_DECLARE_ERROR_REASON(ASN1, CONTEXT_NOT_INITIALISED); +OPENSSL_DECLARE_ERROR_REASON(ASN1, DIGEST_AND_KEY_TYPE_NOT_SUPPORTED); +OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_MESSAGE_DIGEST_ALGORITHM); +OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_SIGNATURE_ALGORITHM); +OPENSSL_DECLARE_ERROR_REASON(ASN1, WRONG_PUBLIC_KEY_TYPE); +/* + * Cross-module errors from crypto/x509/asn1_gen.c. TODO(davidben): Remove + * these once asn1_gen.c is gone. + */ +OPENSSL_DECLARE_ERROR_REASON(ASN1, DEPTH_EXCEEDED); +OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_BITSTRING_FORMAT); +OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_BOOLEAN); +OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_FORMAT); +OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_HEX); +OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_IMPLICIT_TAG); +OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_INTEGER); +OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_NESTED_TAGGING); +OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_NULL_VALUE); +OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_OBJECT); +OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_TIME_VALUE); +OPENSSL_DECLARE_ERROR_REASON(ASN1, INTEGER_NOT_ASCII_FORMAT); +OPENSSL_DECLARE_ERROR_REASON(ASN1, INVALID_MODIFIER); +OPENSSL_DECLARE_ERROR_REASON(ASN1, INVALID_NUMBER); +OPENSSL_DECLARE_ERROR_REASON(ASN1, LIST_ERROR); +OPENSSL_DECLARE_ERROR_REASON(ASN1, MISSING_VALUE); +OPENSSL_DECLARE_ERROR_REASON(ASN1, NOT_ASCII_FORMAT); +OPENSSL_DECLARE_ERROR_REASON(ASN1, OBJECT_NOT_ASCII_FORMAT); +OPENSSL_DECLARE_ERROR_REASON(ASN1, SEQUENCE_OR_SET_NEEDS_CONFIG); +OPENSSL_DECLARE_ERROR_REASON(ASN1, TIME_NOT_ASCII_FORMAT); +OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_FORMAT); +OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_TAG); +OPENSSL_DECLARE_ERROR_REASON(ASN1, UNSUPPORTED_TYPE); + +static int asn1_get_length(const unsigned char **pp, int *inf, long *rl, + long max); +static void asn1_put_length(unsigned char **pp, int length); + +static int _asn1_check_infinite_end(const unsigned char **p, long len) +{ + /* + * If there is 0 or 1 byte left, the length check should pick things up + */ + if (len <= 0) + return (1); + else if ((len >= 2) && ((*p)[0] == 0) && ((*p)[1] == 0)) { + (*p) += 2; + return (1); + } + return (0); +} + +int ASN1_check_infinite_end(unsigned char **p, long len) +{ + return _asn1_check_infinite_end((const unsigned char **)p, len); +} + +int ASN1_const_check_infinite_end(const unsigned char **p, long len) +{ + return _asn1_check_infinite_end(p, len); +} + +int ASN1_get_object(const unsigned char **pp, long *plength, int *ptag, + int *pclass, long omax) +{ + int i, ret; + long l; + const unsigned char *p = *pp; + int tag, xclass, inf; + long max = omax; + + if (!max) + goto err; + ret = (*p & V_ASN1_CONSTRUCTED); + xclass = (*p & V_ASN1_PRIVATE); + i = *p & V_ASN1_PRIMITIVE_TAG; + if (i == V_ASN1_PRIMITIVE_TAG) { /* high-tag */ + p++; + if (--max == 0) + goto err; + l = 0; + while (*p & 0x80) { + l <<= 7L; + l |= *(p++) & 0x7f; + if (--max == 0) + goto err; + if (l > (INT_MAX >> 7L)) + goto err; + } + l <<= 7L; + l |= *(p++) & 0x7f; + tag = (int)l; + if (--max == 0) + goto err; + } else { + tag = i; + p++; + if (--max == 0) + goto err; + } + + /* To avoid ambiguity with V_ASN1_NEG, impose a limit on universal tags. */ + if (xclass == V_ASN1_UNIVERSAL && tag > V_ASN1_MAX_UNIVERSAL) + goto err; + + *ptag = tag; + *pclass = xclass; + if (!asn1_get_length(&p, &inf, plength, max)) + goto err; + + if (inf && !(ret & V_ASN1_CONSTRUCTED)) + goto err; + +#if 0 + fprintf(stderr, "p=%d + *plength=%ld > omax=%ld + *pp=%d (%d > %d)\n", + (int)p, *plength, omax, (int)*pp, (int)(p + *plength), + (int)(omax + *pp)); + +#endif + if (*plength > (omax - (p - *pp))) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG); + /* + * Set this so that even if things are not long enough the values are + * set correctly + */ + ret |= 0x80; + } + *pp = p; + return (ret | inf); + err: + OPENSSL_PUT_ERROR(ASN1, ASN1_R_HEADER_TOO_LONG); + return (0x80); +} + +static int asn1_get_length(const unsigned char **pp, int *inf, long *rl, + long max) +{ + const unsigned char *p = *pp; + unsigned long ret = 0; + unsigned long i; + + if (max-- < 1) + return 0; + if (*p == 0x80) { + *inf = 1; + ret = 0; + p++; + } else { + *inf = 0; + i = *p & 0x7f; + if (*(p++) & 0x80) { + if (i > sizeof(ret) || max < (long)i) + return 0; + while (i-- > 0) { + ret <<= 8L; + ret |= *(p++); + } + } else + ret = i; + } + if (ret > LONG_MAX) + return 0; + *pp = p; + *rl = (long)ret; + return 1; +} + +/* + * class 0 is constructed constructed == 2 for indefinite length constructed + */ +void ASN1_put_object(unsigned char **pp, int constructed, int length, int tag, + int xclass) +{ + unsigned char *p = *pp; + int i, ttag; + + i = (constructed) ? V_ASN1_CONSTRUCTED : 0; + i |= (xclass & V_ASN1_PRIVATE); + if (tag < 31) + *(p++) = i | (tag & V_ASN1_PRIMITIVE_TAG); + else { + *(p++) = i | V_ASN1_PRIMITIVE_TAG; + for (i = 0, ttag = tag; ttag > 0; i++) + ttag >>= 7; + ttag = i; + while (i-- > 0) { + p[i] = tag & 0x7f; + if (i != (ttag - 1)) + p[i] |= 0x80; + tag >>= 7; + } + p += ttag; + } + if (constructed == 2) + *(p++) = 0x80; + else + asn1_put_length(&p, length); + *pp = p; +} + +int ASN1_put_eoc(unsigned char **pp) +{ + unsigned char *p = *pp; + *p++ = 0; + *p++ = 0; + *pp = p; + return 2; +} + +static void asn1_put_length(unsigned char **pp, int length) +{ + unsigned char *p = *pp; + int i, l; + if (length <= 127) + *(p++) = (unsigned char)length; + else { + l = length; + for (i = 0; l > 0; i++) + l >>= 8; + *(p++) = i | 0x80; + l = i; + while (i-- > 0) { + p[i] = length & 0xff; + length >>= 8; + } + p += l; + } + *pp = p; +} + +int ASN1_object_size(int constructed, int length, int tag) +{ + int ret; + + ret = length; + ret++; + if (tag >= 31) { + while (tag > 0) { + tag >>= 7; + ret++; + } + } + if (constructed == 2) + return ret + 3; + ret++; + if (length > 127) { + while (length > 0) { + length >>= 8; + ret++; + } + } + return (ret); +} + +static int _asn1_Finish(ASN1_const_CTX *c) +{ + if ((c->inf == (1 | V_ASN1_CONSTRUCTED)) && (!c->eos)) { + if (!ASN1_const_check_infinite_end(&c->p, c->slen)) { + c->error = ASN1_R_MISSING_ASN1_EOS; + return (0); + } + } + if (((c->slen != 0) && !(c->inf & 1)) || ((c->slen < 0) && (c->inf & 1))) { + c->error = ASN1_R_ASN1_LENGTH_MISMATCH; + return (0); + } + return (1); +} + +int asn1_Finish(ASN1_CTX *c) +{ + return _asn1_Finish((ASN1_const_CTX *)c); +} + +int asn1_const_Finish(ASN1_const_CTX *c) +{ + return _asn1_Finish(c); +} + +int asn1_GetSequence(ASN1_const_CTX *c, long *length) +{ + const unsigned char *q; + + q = c->p; + c->inf = ASN1_get_object(&(c->p), &(c->slen), &(c->tag), &(c->xclass), + *length); + if (c->inf & 0x80) { + c->error = ASN1_R_BAD_GET_ASN1_OBJECT_CALL; + return (0); + } + if (c->tag != V_ASN1_SEQUENCE) { + c->error = ASN1_R_EXPECTING_AN_ASN1_SEQUENCE; + return (0); + } + (*length) -= (c->p - q); + if (c->max && (*length < 0)) { + c->error = ASN1_R_ASN1_LENGTH_MISMATCH; + return (0); + } + if (c->inf == (1 | V_ASN1_CONSTRUCTED)) + c->slen = *length + *(c->pp) - c->p; + c->eos = 0; + return (1); +} + +int ASN1_STRING_copy(ASN1_STRING *dst, const ASN1_STRING *str) +{ + if (str == NULL) + return 0; + dst->type = str->type; + if (!ASN1_STRING_set(dst, str->data, str->length)) + return 0; + dst->flags = str->flags; + return 1; +} + +ASN1_STRING *ASN1_STRING_dup(const ASN1_STRING *str) +{ + ASN1_STRING *ret; + if (!str) + return NULL; + ret = ASN1_STRING_new(); + if (!ret) + return NULL; + if (!ASN1_STRING_copy(ret, str)) { + ASN1_STRING_free(ret); + return NULL; + } + return ret; +} + +int ASN1_STRING_set(ASN1_STRING *str, const void *_data, int len) +{ + unsigned char *c; + const char *data = _data; + + if (len < 0) { + if (data == NULL) + return (0); + else + len = strlen(data); + } + if ((str->length < len) || (str->data == NULL)) { + c = str->data; + if (c == NULL) + str->data = OPENSSL_malloc(len + 1); + else + str->data = OPENSSL_realloc(c, len + 1); + + if (str->data == NULL) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + str->data = c; + return (0); + } + } + str->length = len; + if (data != NULL) { + memcpy(str->data, data, len); + /* an allowance for strings :-) */ + str->data[len] = '\0'; + } + return (1); +} + +void ASN1_STRING_set0(ASN1_STRING *str, void *data, int len) +{ + if (str->data) + OPENSSL_free(str->data); + str->data = data; + str->length = len; +} + +ASN1_STRING *ASN1_STRING_new(void) +{ + return (ASN1_STRING_type_new(V_ASN1_OCTET_STRING)); +} + +ASN1_STRING *ASN1_STRING_type_new(int type) +{ + ASN1_STRING *ret; + + ret = (ASN1_STRING *)OPENSSL_malloc(sizeof(ASN1_STRING)); + if (ret == NULL) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + return (NULL); + } + ret->length = 0; + ret->type = type; + ret->data = NULL; + ret->flags = 0; + return (ret); +} + +void ASN1_STRING_free(ASN1_STRING *a) +{ + if (a == NULL) + return; + if (a->data && !(a->flags & ASN1_STRING_FLAG_NDEF)) + OPENSSL_free(a->data); + OPENSSL_free(a); +} + +int ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b) +{ + int i; + + i = (a->length - b->length); + if (i == 0) { + i = memcmp(a->data, b->data, a->length); + if (i == 0) + return (a->type - b->type); + else + return (i); + } else + return (i); +} + +int ASN1_STRING_length(const ASN1_STRING *x) +{ + return M_ASN1_STRING_length(x); +} + +void ASN1_STRING_length_set(ASN1_STRING *x, int len) +{ + M_ASN1_STRING_length_set(x, len); + return; +} + +int ASN1_STRING_type(ASN1_STRING *x) +{ + return M_ASN1_STRING_type(x); +} + +unsigned char *ASN1_STRING_data(ASN1_STRING *x) +{ + return M_ASN1_STRING_data(x); +} diff --git a/external/boringssl/crypto/asn1/asn1_locl.h b/external/boringssl/crypto/asn1/asn1_locl.h new file mode 100644 index 0000000000..982bfd6036 --- /dev/null +++ b/external/boringssl/crypto/asn1/asn1_locl.h @@ -0,0 +1,63 @@ +/* asn1t.h */ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project + * 2006. + */ +/* ==================================================================== + * Copyright (c) 2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +/* Internal ASN1 structures and functions: not for application use */ + +int asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d); +int asn1_generalizedtime_to_tm(struct tm *tm, const ASN1_GENERALIZEDTIME *d); diff --git a/external/boringssl/crypto/asn1/asn1_par.c b/external/boringssl/crypto/asn1/asn1_par.c new file mode 100644 index 0000000000..b1a01edaee --- /dev/null +++ b/external/boringssl/crypto/asn1/asn1_par.c @@ -0,0 +1,80 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + + +const char *ASN1_tag2str(int tag) +{ + static const char *const tag2str[] = { + "EOC", "BOOLEAN", "INTEGER", "BIT STRING", "OCTET STRING", /* 0-4 */ + "NULL", "OBJECT", "OBJECT DESCRIPTOR", "EXTERNAL", "REAL", /* 5-9 */ + "ENUMERATED", "", "UTF8STRING", "", /* 10-13 */ + "", "", "SEQUENCE", "SET", /* 15-17 */ + "NUMERICSTRING", "PRINTABLESTRING", "T61STRING", /* 18-20 */ + "VIDEOTEXSTRING", "IA5STRING", "UTCTIME", "GENERALIZEDTIME", /* 21-24 + */ + "GRAPHICSTRING", "VISIBLESTRING", "GENERALSTRING", /* 25-27 */ + "UNIVERSALSTRING", "", "BMPSTRING" /* 28-30 */ + }; + + if ((tag == V_ASN1_NEG_INTEGER) || (tag == V_ASN1_NEG_ENUMERATED)) + tag &= ~0x100; + + if (tag < 0 || tag > 30) + return "(unknown)"; + return tag2str[tag]; +} diff --git a/external/boringssl/crypto/asn1/asn1_test.cc b/external/boringssl/crypto/asn1/asn1_test.cc new file mode 100644 index 0000000000..8b024427a2 --- /dev/null +++ b/external/boringssl/crypto/asn1/asn1_test.cc @@ -0,0 +1,81 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include +#include +#include + +#include "../test/scoped_types.h" + + +// kTag128 is an ASN.1 structure with a universal tag with number 128. +static const uint8_t kTag128[] = { + 0x1f, 0x81, 0x00, 0x01, 0x00, +}; + +// kTag258 is an ASN.1 structure with a universal tag with number 258. +static const uint8_t kTag258[] = { + 0x1f, 0x82, 0x02, 0x01, 0x00, +}; + +static_assert(V_ASN1_NEG_INTEGER == 258, + "V_ASN1_NEG_INTEGER changed. Update kTag258 to collide with it."); + +// kTagOverflow is an ASN.1 structure with a universal tag with number 2^35-1, +// which will not fit in an int. +static const uint8_t kTagOverflow[] = { + 0x1f, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x01, 0x00, +}; + +static bool TestLargeTags() { + const uint8_t *p = kTag258; + ScopedASN1_TYPE obj(d2i_ASN1_TYPE(NULL, &p, sizeof(kTag258))); + if (obj) { + fprintf(stderr, "Parsed value with illegal tag (type = %d).\n", obj->type); + return false; + } + ERR_clear_error(); + + p = kTagOverflow; + obj.reset(d2i_ASN1_TYPE(NULL, &p, sizeof(kTagOverflow))); + if (obj) { + fprintf(stderr, "Parsed value with tag overflow (type = %d).\n", obj->type); + return false; + } + ERR_clear_error(); + + p = kTag128; + obj.reset(d2i_ASN1_TYPE(NULL, &p, sizeof(kTag128))); + if (!obj || obj->type != 128 || obj->value.asn1_string->length != 1 || + obj->value.asn1_string->data[0] != 0) { + fprintf(stderr, "Failed to parse value with tag 128.\n"); + ERR_print_errors_fp(stderr); + return false; + } + + return true; +} + +int main() { + CRYPTO_library_init(); + + if (!TestLargeTags()) { + return 1; + } + + printf("PASS\n"); + return 0; +} diff --git a/external/boringssl/crypto/asn1/asn_pack.c b/external/boringssl/crypto/asn1/asn_pack.c new file mode 100644 index 0000000000..eff54e55c6 --- /dev/null +++ b/external/boringssl/crypto/asn1/asn_pack.c @@ -0,0 +1,105 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +/* ASN1_ITEM versions of the above */ + +ASN1_STRING *ASN1_item_pack(void *obj, const ASN1_ITEM *it, ASN1_STRING **oct) +{ + ASN1_STRING *octmp; + + if (!oct || !*oct) { + if (!(octmp = ASN1_STRING_new())) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + return NULL; + } + if (oct) + *oct = octmp; + } else + octmp = *oct; + + if (octmp->data) { + OPENSSL_free(octmp->data); + octmp->data = NULL; + } + + if (!(octmp->length = ASN1_item_i2d(obj, &octmp->data, it))) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_ENCODE_ERROR); + return NULL; + } + if (!octmp->data) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + return NULL; + } + return octmp; +} + +/* Extract an ASN1 object from an ASN1_STRING */ + +void *ASN1_item_unpack(ASN1_STRING *oct, const ASN1_ITEM *it) +{ + const unsigned char *p; + void *ret; + + p = oct->data; + if (!(ret = ASN1_item_d2i(NULL, &p, oct->length, it))) + OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); + return ret; +} diff --git a/external/boringssl/crypto/asn1/charmap.pl b/external/boringssl/crypto/asn1/charmap.pl new file mode 100644 index 0000000000..71bc7b8bd7 --- /dev/null +++ b/external/boringssl/crypto/asn1/charmap.pl @@ -0,0 +1,135 @@ +#!/usr/local/bin/perl -w + +# Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project +# 2000. +# +# ==================================================================== +# Copyright (c) 2000 The OpenSSL Project. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# 3. All advertising materials mentioning features or use of this +# software must display the following acknowledgment: +# "This product includes software developed by the OpenSSL Project +# for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" +# +# 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to +# endorse or promote products derived from this software without +# prior written permission. For written permission, please contact +# licensing@OpenSSL.org. +# +# 5. Products derived from this software may not be called "OpenSSL" +# nor may "OpenSSL" appear in their names without prior written +# permission of the OpenSSL Project. +# +# 6. Redistributions of any form whatsoever must retain the following +# acknowledgment: +# "This product includes software developed by the OpenSSL Project +# for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" +# +# THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY +# EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR +# ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +# OF THE POSSIBILITY OF SUCH DAMAGE. +# ==================================================================== +# +# This product includes cryptographic software written by Eric Young +# (eay@cryptsoft.com). This product includes software written by Tim +# Hudson (tjh@cryptsoft.com). + +use strict; + +my ($i, @arr); + +# Set up an array with the type of ASCII characters +# Each set bit represents a character property. + +# RFC2253 character properties +my $RFC2253_ESC = 1; # Character escaped with \ +my $ESC_CTRL = 2; # Escaped control character +# These are used with RFC1779 quoting using " +my $NOESC_QUOTE = 8; # Not escaped if quoted +my $PSTRING_CHAR = 0x10; # Valid PrintableString character +my $RFC2253_FIRST_ESC = 0x20; # Escaped with \ if first character +my $RFC2253_LAST_ESC = 0x40; # Escaped with \ if last character + +for($i = 0; $i < 128; $i++) { + # Set the RFC2253 escape characters (control) + $arr[$i] = 0; + if(($i < 32) || ($i > 126)) { + $arr[$i] |= $ESC_CTRL; + } + + # Some PrintableString characters + if( ( ( $i >= ord("a")) && ( $i <= ord("z")) ) + || ( ( $i >= ord("A")) && ( $i <= ord("Z")) ) + || ( ( $i >= ord("0")) && ( $i <= ord("9")) ) ) { + $arr[$i] |= $PSTRING_CHAR; + } +} + +# Now setup the rest + +# Remaining RFC2253 escaped characters + +$arr[ord(" ")] |= $NOESC_QUOTE | $RFC2253_FIRST_ESC | $RFC2253_LAST_ESC; +$arr[ord("#")] |= $NOESC_QUOTE | $RFC2253_FIRST_ESC; + +$arr[ord(",")] |= $NOESC_QUOTE | $RFC2253_ESC; +$arr[ord("+")] |= $NOESC_QUOTE | $RFC2253_ESC; +$arr[ord("\"")] |= $RFC2253_ESC; +$arr[ord("\\")] |= $RFC2253_ESC; +$arr[ord("<")] |= $NOESC_QUOTE | $RFC2253_ESC; +$arr[ord(">")] |= $NOESC_QUOTE | $RFC2253_ESC; +$arr[ord(";")] |= $NOESC_QUOTE | $RFC2253_ESC; + +# Remaining PrintableString characters + +$arr[ord(" ")] |= $PSTRING_CHAR; +$arr[ord("'")] |= $PSTRING_CHAR; +$arr[ord("(")] |= $PSTRING_CHAR; +$arr[ord(")")] |= $PSTRING_CHAR; +$arr[ord("+")] |= $PSTRING_CHAR; +$arr[ord(",")] |= $PSTRING_CHAR; +$arr[ord("-")] |= $PSTRING_CHAR; +$arr[ord(".")] |= $PSTRING_CHAR; +$arr[ord("/")] |= $PSTRING_CHAR; +$arr[ord(":")] |= $PSTRING_CHAR; +$arr[ord("=")] |= $PSTRING_CHAR; +$arr[ord("?")] |= $PSTRING_CHAR; + +# Now generate the C code + +print < + +#include +#include + +/* Based on a_int.c: equivalent ENUMERATED functions */ + +int i2a_ASN1_ENUMERATED(BIO *bp, ASN1_ENUMERATED *a) +{ + int i, n = 0; + static const char *h = "0123456789ABCDEF"; + char buf[2]; + + if (a == NULL) + return (0); + + if (a->length == 0) { + if (BIO_write(bp, "00", 2) != 2) + goto err; + n = 2; + } else { + for (i = 0; i < a->length; i++) { + if ((i != 0) && (i % 35 == 0)) { + if (BIO_write(bp, "\\\n", 2) != 2) + goto err; + n += 2; + } + buf[0] = h[((unsigned char)a->data[i] >> 4) & 0x0f]; + buf[1] = h[((unsigned char)a->data[i]) & 0x0f]; + if (BIO_write(bp, buf, 2) != 2) + goto err; + n += 2; + } + } + return (n); + err: + return (-1); +} + +int a2i_ASN1_ENUMERATED(BIO *bp, ASN1_ENUMERATED *bs, char *buf, int size) +{ + int ret = 0; + int i, j, k, m, n, again, bufsize; + unsigned char *s = NULL, *sp; + unsigned char *bufp; + int num = 0, slen = 0, first = 1; + + bs->type = V_ASN1_ENUMERATED; + + bufsize = BIO_gets(bp, buf, size); + for (;;) { + if (bufsize < 1) + goto err_sl; + i = bufsize; + if (buf[i - 1] == '\n') + buf[--i] = '\0'; + if (i == 0) + goto err_sl; + if (buf[i - 1] == '\r') + buf[--i] = '\0'; + if (i == 0) + goto err_sl; + again = (buf[i - 1] == '\\'); + + for (j = 0; j < i; j++) { + if (!(((buf[j] >= '0') && (buf[j] <= '9')) || + ((buf[j] >= 'a') && (buf[j] <= 'f')) || + ((buf[j] >= 'A') && (buf[j] <= 'F')))) { + i = j; + break; + } + } + buf[i] = '\0'; + /* + * We have now cleared all the crap off the end of the line + */ + if (i < 2) + goto err_sl; + + bufp = (unsigned char *)buf; + if (first) { + first = 0; + if ((bufp[0] == '0') && (buf[1] == '0')) { + bufp += 2; + i -= 2; + } + } + k = 0; + i -= again; + if (i % 2 != 0) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_ODD_NUMBER_OF_CHARS); + goto err; + } + i /= 2; + if (num + i > slen) { + if (s == NULL) + sp = (unsigned char *)OPENSSL_malloc((unsigned int)num + + i * 2); + else + sp = (unsigned char *)OPENSSL_realloc(s, + (unsigned int)num + + i * 2); + if (sp == NULL) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + goto err; + } + s = sp; + slen = num + i * 2; + } + for (j = 0; j < i; j++, k += 2) { + for (n = 0; n < 2; n++) { + m = bufp[k + n]; + if ((m >= '0') && (m <= '9')) + m -= '0'; + else if ((m >= 'a') && (m <= 'f')) + m = m - 'a' + 10; + else if ((m >= 'A') && (m <= 'F')) + m = m - 'A' + 10; + else { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_NON_HEX_CHARACTERS); + goto err; + } + s[num + j] <<= 4; + s[num + j] |= m; + } + } + num += i; + if (again) + bufsize = BIO_gets(bp, buf, size); + else + break; + } + bs->length = num; + bs->data = s; + ret = 1; + err: + if (0) { + err_sl: + OPENSSL_PUT_ERROR(ASN1, ASN1_R_SHORT_LINE); + } + if (s != NULL) + OPENSSL_free(s); + return (ret); +} diff --git a/external/boringssl/crypto/asn1/f_int.c b/external/boringssl/crypto/asn1/f_int.c new file mode 100644 index 0000000000..60c0f2f2be --- /dev/null +++ b/external/boringssl/crypto/asn1/f_int.c @@ -0,0 +1,202 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +int i2a_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *a) +{ + int i, n = 0; + static const char *h = "0123456789ABCDEF"; + char buf[2]; + + if (a == NULL) + return (0); + + if (a->type & V_ASN1_NEG) { + if (BIO_write(bp, "-", 1) != 1) + goto err; + n = 1; + } + + if (a->length == 0) { + if (BIO_write(bp, "00", 2) != 2) + goto err; + n += 2; + } else { + for (i = 0; i < a->length; i++) { + if ((i != 0) && (i % 35 == 0)) { + if (BIO_write(bp, "\\\n", 2) != 2) + goto err; + n += 2; + } + buf[0] = h[((unsigned char)a->data[i] >> 4) & 0x0f]; + buf[1] = h[((unsigned char)a->data[i]) & 0x0f]; + if (BIO_write(bp, buf, 2) != 2) + goto err; + n += 2; + } + } + return (n); + err: + return (-1); +} + +int a2i_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *bs, char *buf, int size) +{ + int ret = 0; + int i, j, k, m, n, again, bufsize; + unsigned char *s = NULL, *sp; + unsigned char *bufp; + int num = 0, slen = 0, first = 1; + + bs->type = V_ASN1_INTEGER; + + bufsize = BIO_gets(bp, buf, size); + for (;;) { + if (bufsize < 1) + goto err_sl; + i = bufsize; + if (buf[i - 1] == '\n') + buf[--i] = '\0'; + if (i == 0) + goto err_sl; + if (buf[i - 1] == '\r') + buf[--i] = '\0'; + if (i == 0) + goto err_sl; + again = (buf[i - 1] == '\\'); + + for (j = 0; j < i; j++) { + if (!(((buf[j] >= '0') && (buf[j] <= '9')) || + ((buf[j] >= 'a') && (buf[j] <= 'f')) || + ((buf[j] >= 'A') && (buf[j] <= 'F')))) { + i = j; + break; + } + } + buf[i] = '\0'; + /* + * We have now cleared all the crap off the end of the line + */ + if (i < 2) + goto err_sl; + + bufp = (unsigned char *)buf; + if (first) { + first = 0; + if ((bufp[0] == '0') && (buf[1] == '0')) { + bufp += 2; + i -= 2; + } + } + k = 0; + i -= again; + if (i % 2 != 0) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_ODD_NUMBER_OF_CHARS); + goto err; + } + i /= 2; + if (num + i > slen) { + if (s == NULL) + sp = (unsigned char *)OPENSSL_malloc((unsigned int)num + + i * 2); + else + sp = OPENSSL_realloc_clean(s, slen, num + i * 2); + if (sp == NULL) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + goto err; + } + s = sp; + slen = num + i * 2; + } + for (j = 0; j < i; j++, k += 2) { + for (n = 0; n < 2; n++) { + m = bufp[k + n]; + if ((m >= '0') && (m <= '9')) + m -= '0'; + else if ((m >= 'a') && (m <= 'f')) + m = m - 'a' + 10; + else if ((m >= 'A') && (m <= 'F')) + m = m - 'A' + 10; + else { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_NON_HEX_CHARACTERS); + goto err; + } + s[num + j] <<= 4; + s[num + j] |= m; + } + } + num += i; + if (again) + bufsize = BIO_gets(bp, buf, size); + else + break; + } + bs->length = num; + bs->data = s; + ret = 1; + err: + if (0) { + err_sl: + OPENSSL_PUT_ERROR(ASN1, ASN1_R_SHORT_LINE); + } + if (s != NULL) + OPENSSL_free(s); + return (ret); +} diff --git a/external/boringssl/crypto/asn1/f_string.c b/external/boringssl/crypto/asn1/f_string.c new file mode 100644 index 0000000000..ec9cb83d17 --- /dev/null +++ b/external/boringssl/crypto/asn1/f_string.c @@ -0,0 +1,196 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +int i2a_ASN1_STRING(BIO *bp, ASN1_STRING *a, int type) +{ + int i, n = 0; + static const char *h = "0123456789ABCDEF"; + char buf[2]; + + if (a == NULL) + return (0); + + if (a->length == 0) { + if (BIO_write(bp, "0", 1) != 1) + goto err; + n = 1; + } else { + for (i = 0; i < a->length; i++) { + if ((i != 0) && (i % 35 == 0)) { + if (BIO_write(bp, "\\\n", 2) != 2) + goto err; + n += 2; + } + buf[0] = h[((unsigned char)a->data[i] >> 4) & 0x0f]; + buf[1] = h[((unsigned char)a->data[i]) & 0x0f]; + if (BIO_write(bp, buf, 2) != 2) + goto err; + n += 2; + } + } + return (n); + err: + return (-1); +} + +int a2i_ASN1_STRING(BIO *bp, ASN1_STRING *bs, char *buf, int size) +{ + int ret = 0; + int i, j, k, m, n, again, bufsize; + unsigned char *s = NULL, *sp; + unsigned char *bufp; + int num = 0, slen = 0, first = 1; + + bufsize = BIO_gets(bp, buf, size); + for (;;) { + if (bufsize < 1) { + if (first) + break; + else + goto err_sl; + } + first = 0; + + i = bufsize; + if (buf[i - 1] == '\n') + buf[--i] = '\0'; + if (i == 0) + goto err_sl; + if (buf[i - 1] == '\r') + buf[--i] = '\0'; + if (i == 0) + goto err_sl; + again = (buf[i - 1] == '\\'); + + for (j = i - 1; j > 0; j--) { + if (!(((buf[j] >= '0') && (buf[j] <= '9')) || + ((buf[j] >= 'a') && (buf[j] <= 'f')) || + ((buf[j] >= 'A') && (buf[j] <= 'F')))) { + i = j; + break; + } + } + buf[i] = '\0'; + /* + * We have now cleared all the crap off the end of the line + */ + if (i < 2) + goto err_sl; + + bufp = (unsigned char *)buf; + + k = 0; + i -= again; + if (i % 2 != 0) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_ODD_NUMBER_OF_CHARS); + goto err; + } + i /= 2; + if (num + i > slen) { + if (s == NULL) + sp = (unsigned char *)OPENSSL_malloc((unsigned int)num + + i * 2); + else + sp = (unsigned char *)OPENSSL_realloc(s, + (unsigned int)num + + i * 2); + if (sp == NULL) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + goto err; + } + s = sp; + slen = num + i * 2; + } + for (j = 0; j < i; j++, k += 2) { + for (n = 0; n < 2; n++) { + m = bufp[k + n]; + if ((m >= '0') && (m <= '9')) + m -= '0'; + else if ((m >= 'a') && (m <= 'f')) + m = m - 'a' + 10; + else if ((m >= 'A') && (m <= 'F')) + m = m - 'A' + 10; + else { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_NON_HEX_CHARACTERS); + goto err; + } + s[num + j] <<= 4; + s[num + j] |= m; + } + } + num += i; + if (again) + bufsize = BIO_gets(bp, buf, size); + else + break; + } + bs->length = num; + bs->data = s; + ret = 1; + err: + if (0) { + err_sl: + OPENSSL_PUT_ERROR(ASN1, ASN1_R_SHORT_LINE); + } + if (s != NULL) + OPENSSL_free(s); + return (ret); +} diff --git a/external/boringssl/crypto/asn1/t_bitst.c b/external/boringssl/crypto/asn1/t_bitst.c new file mode 100644 index 0000000000..e754ca73a9 --- /dev/null +++ b/external/boringssl/crypto/asn1/t_bitst.c @@ -0,0 +1,103 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include + +int ASN1_BIT_STRING_name_print(BIO *out, ASN1_BIT_STRING *bs, + BIT_STRING_BITNAME *tbl, int indent) +{ + BIT_STRING_BITNAME *bnam; + char first = 1; + BIO_printf(out, "%*s", indent, ""); + for (bnam = tbl; bnam->lname; bnam++) { + if (ASN1_BIT_STRING_get_bit(bs, bnam->bitnum)) { + if (!first) + BIO_puts(out, ", "); + BIO_puts(out, bnam->lname); + first = 0; + } + } + BIO_puts(out, "\n"); + return 1; +} + +int ASN1_BIT_STRING_set_asc(ASN1_BIT_STRING *bs, char *name, int value, + BIT_STRING_BITNAME *tbl) +{ + int bitnum; + bitnum = ASN1_BIT_STRING_num_asc(name, tbl); + if (bitnum < 0) + return 0; + if (bs) { + if (!ASN1_BIT_STRING_set_bit(bs, bitnum, value)) + return 0; + } + return 1; +} + +int ASN1_BIT_STRING_num_asc(char *name, BIT_STRING_BITNAME *tbl) +{ + BIT_STRING_BITNAME *bnam; + for (bnam = tbl; bnam->lname; bnam++) { + if (!strcmp(bnam->sname, name) || !strcmp(bnam->lname, name)) + return bnam->bitnum; + } + return -1; +} diff --git a/external/boringssl/crypto/asn1/tasn_dec.c b/external/boringssl/crypto/asn1/tasn_dec.c new file mode 100644 index 0000000000..616b587c37 --- /dev/null +++ b/external/boringssl/crypto/asn1/tasn_dec.c @@ -0,0 +1,1219 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include +#include +#include +#include + +#include "../internal.h" + +static int asn1_check_eoc(const unsigned char **in, long len); +static int asn1_find_end(const unsigned char **in, long len, char inf); + +static int asn1_collect(BUF_MEM *buf, const unsigned char **in, long len, + char inf, int tag, int aclass, int depth); + +static int collect_data(BUF_MEM *buf, const unsigned char **p, long plen); + +static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass, + char *inf, char *cst, + const unsigned char **in, long len, + int exptag, int expclass, char opt, ASN1_TLC *ctx); + +static int asn1_template_ex_d2i(ASN1_VALUE **pval, + const unsigned char **in, long len, + const ASN1_TEMPLATE *tt, char opt, + ASN1_TLC *ctx); +static int asn1_template_noexp_d2i(ASN1_VALUE **val, + const unsigned char **in, long len, + const ASN1_TEMPLATE *tt, char opt, + ASN1_TLC *ctx); +static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, + const unsigned char **in, long len, + const ASN1_ITEM *it, + int tag, int aclass, char opt, + ASN1_TLC *ctx); + +/* Table to convert tags to bit values, used for MSTRING type */ +static const unsigned long tag2bit[32] = { + 0, 0, 0, B_ASN1_BIT_STRING, /* tags 0 - 3 */ + B_ASN1_OCTET_STRING, 0, 0, B_ASN1_UNKNOWN, /* tags 4- 7 */ + B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, /* tags + * 8-11 */ + B_ASN1_UTF8STRING, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, /* tags + * 12-15 + */ + B_ASN1_SEQUENCE, 0, B_ASN1_NUMERICSTRING, B_ASN1_PRINTABLESTRING, /* tags + * 16-19 + */ + B_ASN1_T61STRING, B_ASN1_VIDEOTEXSTRING, B_ASN1_IA5STRING, /* tags 20-22 */ + B_ASN1_UTCTIME, B_ASN1_GENERALIZEDTIME, /* tags 23-24 */ + B_ASN1_GRAPHICSTRING, B_ASN1_ISO64STRING, B_ASN1_GENERALSTRING, /* tags + * 25-27 */ + B_ASN1_UNIVERSALSTRING, B_ASN1_UNKNOWN, B_ASN1_BMPSTRING, B_ASN1_UNKNOWN, /* tags + * 28-31 + */ +}; + +unsigned long ASN1_tag2bit(int tag) +{ + if ((tag < 0) || (tag > 30)) + return 0; + return tag2bit[tag]; +} + +/* Macro to initialize and invalidate the cache */ + +#define asn1_tlc_clear(c) if (c) (c)->valid = 0 +/* Version to avoid compiler warning about 'c' always non-NULL */ +#define asn1_tlc_clear_nc(c) (c)->valid = 0 + +/* + * Decode an ASN1 item, this currently behaves just like a standard 'd2i' + * function. 'in' points to a buffer to read the data from, in future we + * will have more advanced versions that can input data a piece at a time and + * this will simply be a special case. + */ + +ASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **pval, + const unsigned char **in, long len, + const ASN1_ITEM *it) +{ + ASN1_TLC c; + ASN1_VALUE *ptmpval = NULL; + if (!pval) + pval = &ptmpval; + asn1_tlc_clear_nc(&c); + if (ASN1_item_ex_d2i(pval, in, len, it, -1, 0, 0, &c) > 0) + return *pval; + return NULL; +} + +int ASN1_template_d2i(ASN1_VALUE **pval, + const unsigned char **in, long len, + const ASN1_TEMPLATE *tt) +{ + ASN1_TLC c; + asn1_tlc_clear_nc(&c); + return asn1_template_ex_d2i(pval, in, len, tt, 0, &c); +} + +/* + * Decode an item, taking care of IMPLICIT tagging, if any. If 'opt' set and + * tag mismatch return -1 to handle OPTIONAL + */ + +int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, + const ASN1_ITEM *it, + int tag, int aclass, char opt, ASN1_TLC *ctx) +{ + const ASN1_TEMPLATE *tt, *errtt = NULL; + const ASN1_COMPAT_FUNCS *cf; + const ASN1_EXTERN_FUNCS *ef; + const ASN1_AUX *aux = it->funcs; + ASN1_aux_cb *asn1_cb; + const unsigned char *p = NULL, *q; + unsigned char *wp = NULL; /* BIG FAT WARNING! BREAKS CONST WHERE USED */ + unsigned char imphack = 0, oclass; + char seq_eoc, seq_nolen, cst, isopt; + long tmplen; + int i; + int otag; + int ret = 0; + ASN1_VALUE **pchptr, *ptmpval; + int combine = aclass & ASN1_TFLG_COMBINE; + if (!pval) + return 0; + if (aux && aux->asn1_cb) + asn1_cb = aux->asn1_cb; + else + asn1_cb = 0; + + switch (it->itype) { + case ASN1_ITYPE_PRIMITIVE: + if (it->templates) { + /* + * tagging or OPTIONAL is currently illegal on an item template + * because the flags can't get passed down. In practice this + * isn't a problem: we include the relevant flags from the item + * template in the template itself. + */ + if ((tag != -1) || opt) { + OPENSSL_PUT_ERROR(ASN1, + ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE); + goto err; + } + return asn1_template_ex_d2i(pval, in, len, + it->templates, opt, ctx); + } + return asn1_d2i_ex_primitive(pval, in, len, it, + tag, aclass, opt, ctx); + break; + + case ASN1_ITYPE_MSTRING: + p = *in; + /* Just read in tag and class */ + ret = asn1_check_tlen(NULL, &otag, &oclass, NULL, NULL, + &p, len, -1, 0, 1, ctx); + if (!ret) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); + goto err; + } + + /* Must be UNIVERSAL class */ + if (oclass != V_ASN1_UNIVERSAL) { + /* If OPTIONAL, assume this is OK */ + if (opt) + return -1; + OPENSSL_PUT_ERROR(ASN1, ASN1_R_MSTRING_NOT_UNIVERSAL); + goto err; + } + /* Check tag matches bit map */ + if (!(ASN1_tag2bit(otag) & it->utype)) { + /* If OPTIONAL, assume this is OK */ + if (opt) + return -1; + OPENSSL_PUT_ERROR(ASN1, ASN1_R_MSTRING_WRONG_TAG); + goto err; + } + return asn1_d2i_ex_primitive(pval, in, len, it, otag, 0, 0, ctx); + + case ASN1_ITYPE_EXTERN: + /* Use new style d2i */ + ef = it->funcs; + return ef->asn1_ex_d2i(pval, in, len, it, tag, aclass, opt, ctx); + + case ASN1_ITYPE_COMPAT: + /* we must resort to old style evil hackery */ + cf = it->funcs; + + /* If OPTIONAL see if it is there */ + if (opt) { + int exptag; + p = *in; + if (tag == -1) + exptag = it->utype; + else + exptag = tag; + /* + * Don't care about anything other than presence of expected tag + */ + + ret = asn1_check_tlen(NULL, NULL, NULL, NULL, NULL, + &p, len, exptag, aclass, 1, ctx); + if (!ret) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); + goto err; + } + if (ret == -1) + return -1; + } + + /* + * This is the old style evil hack IMPLICIT handling: since the + * underlying code is expecting a tag and class other than the one + * present we change the buffer temporarily then change it back + * afterwards. This doesn't and never did work for tags > 30. Yes + * this is *horrible* but it is only needed for old style d2i which + * will hopefully not be around for much longer. FIXME: should copy + * the buffer then modify it so the input buffer can be const: we + * should *always* copy because the old style d2i might modify the + * buffer. + */ + + if (tag != -1) { + wp = *(unsigned char **)in; + imphack = *wp; + if (p == NULL) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); + goto err; + } + *wp = (unsigned char)((*p & V_ASN1_CONSTRUCTED) + | it->utype); + } + + ptmpval = cf->asn1_d2i(pval, in, len); + + if (tag != -1) + *wp = imphack; + + if (ptmpval) + return 1; + + OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); + goto err; + + case ASN1_ITYPE_CHOICE: + if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it, NULL)) + goto auxerr; + + if (*pval) { + /* Free up and zero CHOICE value if initialised */ + i = asn1_get_choice_selector(pval, it); + if ((i >= 0) && (i < it->tcount)) { + tt = it->templates + i; + pchptr = asn1_get_field_ptr(pval, tt); + ASN1_template_free(pchptr, tt); + asn1_set_choice_selector(pval, -1, it); + } + } else if (!ASN1_item_ex_new(pval, it)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); + goto err; + } + /* CHOICE type, try each possibility in turn */ + p = *in; + for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) { + pchptr = asn1_get_field_ptr(pval, tt); + /* + * We mark field as OPTIONAL so its absence can be recognised. + */ + ret = asn1_template_ex_d2i(pchptr, &p, len, tt, 1, ctx); + /* If field not present, try the next one */ + if (ret == -1) + continue; + /* If positive return, read OK, break loop */ + if (ret > 0) + break; + /* Otherwise must be an ASN1 parsing error */ + errtt = tt; + OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); + goto err; + } + + /* Did we fall off the end without reading anything? */ + if (i == it->tcount) { + /* If OPTIONAL, this is OK */ + if (opt) { + /* Free and zero it */ + ASN1_item_ex_free(pval, it); + return -1; + } + OPENSSL_PUT_ERROR(ASN1, ASN1_R_NO_MATCHING_CHOICE_TYPE); + goto err; + } + + asn1_set_choice_selector(pval, i, it); + if (asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it, NULL)) + goto auxerr; + *in = p; + return 1; + + case ASN1_ITYPE_NDEF_SEQUENCE: + case ASN1_ITYPE_SEQUENCE: + p = *in; + tmplen = len; + + /* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */ + if (tag == -1) { + tag = V_ASN1_SEQUENCE; + aclass = V_ASN1_UNIVERSAL; + } + /* Get SEQUENCE length and update len, p */ + ret = asn1_check_tlen(&len, NULL, NULL, &seq_eoc, &cst, + &p, len, tag, aclass, opt, ctx); + if (!ret) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); + goto err; + } else if (ret == -1) + return -1; + if (aux && (aux->flags & ASN1_AFLG_BROKEN)) { + len = tmplen - (p - *in); + seq_nolen = 1; + } + /* If indefinite we don't do a length check */ + else + seq_nolen = seq_eoc; + if (!cst) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_SEQUENCE_NOT_CONSTRUCTED); + goto err; + } + + if (!*pval && !ASN1_item_ex_new(pval, it)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); + goto err; + } + + if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it, NULL)) + goto auxerr; + + /* Free up and zero any ADB found */ + for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) { + if (tt->flags & ASN1_TFLG_ADB_MASK) { + const ASN1_TEMPLATE *seqtt; + ASN1_VALUE **pseqval; + seqtt = asn1_do_adb(pval, tt, 1); + pseqval = asn1_get_field_ptr(pval, seqtt); + ASN1_template_free(pseqval, seqtt); + } + } + + /* Get each field entry */ + for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) { + const ASN1_TEMPLATE *seqtt; + ASN1_VALUE **pseqval; + seqtt = asn1_do_adb(pval, tt, 1); + if (!seqtt) + goto err; + pseqval = asn1_get_field_ptr(pval, seqtt); + /* Have we ran out of data? */ + if (!len) + break; + q = p; + if (asn1_check_eoc(&p, len)) { + if (!seq_eoc) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNEXPECTED_EOC); + goto err; + } + len -= p - q; + seq_eoc = 0; + q = p; + break; + } + /* + * This determines the OPTIONAL flag value. The field cannot be + * omitted if it is the last of a SEQUENCE and there is still + * data to be read. This isn't strictly necessary but it + * increases efficiency in some cases. + */ + if (i == (it->tcount - 1)) + isopt = 0; + else + isopt = (char)(seqtt->flags & ASN1_TFLG_OPTIONAL); + /* + * attempt to read in field, allowing each to be OPTIONAL + */ + + ret = asn1_template_ex_d2i(pseqval, &p, len, seqtt, isopt, ctx); + if (!ret) { + errtt = seqtt; + goto err; + } else if (ret == -1) { + /* + * OPTIONAL component absent. Free and zero the field. + */ + ASN1_template_free(pseqval, seqtt); + continue; + } + /* Update length */ + len -= p - q; + } + + /* Check for EOC if expecting one */ + if (seq_eoc && !asn1_check_eoc(&p, len)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_EOC); + goto err; + } + /* Check all data read */ + if (!seq_nolen && len) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_SEQUENCE_LENGTH_MISMATCH); + goto err; + } + + /* + * If we get here we've got no more data in the SEQUENCE, however we + * may not have read all fields so check all remaining are OPTIONAL + * and clear any that are. + */ + for (; i < it->tcount; tt++, i++) { + const ASN1_TEMPLATE *seqtt; + seqtt = asn1_do_adb(pval, tt, 1); + if (!seqtt) + goto err; + if (seqtt->flags & ASN1_TFLG_OPTIONAL) { + ASN1_VALUE **pseqval; + pseqval = asn1_get_field_ptr(pval, seqtt); + ASN1_template_free(pseqval, seqtt); + } else { + errtt = seqtt; + OPENSSL_PUT_ERROR(ASN1, ASN1_R_FIELD_MISSING); + goto err; + } + } + /* Save encoding */ + if (!asn1_enc_save(pval, *in, p - *in, it)) + goto auxerr; + if (asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it, NULL)) + goto auxerr; + *in = p; + return 1; + + default: + return 0; + } + auxerr: + OPENSSL_PUT_ERROR(ASN1, ASN1_R_AUX_ERROR); + err: + if (combine == 0) + ASN1_item_ex_free(pval, it); + if (errtt) + ERR_add_error_data(4, "Field=", errtt->field_name, + ", Type=", it->sname); + else + ERR_add_error_data(2, "Type=", it->sname); + return 0; +} + +/* + * Templates are handled with two separate functions. One handles any + * EXPLICIT tag and the other handles the rest. + */ + +static int asn1_template_ex_d2i(ASN1_VALUE **val, + const unsigned char **in, long inlen, + const ASN1_TEMPLATE *tt, char opt, + ASN1_TLC *ctx) +{ + int flags, aclass; + int ret; + long len; + const unsigned char *p, *q; + char exp_eoc; + if (!val) + return 0; + flags = tt->flags; + aclass = flags & ASN1_TFLG_TAG_CLASS; + + p = *in; + + /* Check if EXPLICIT tag expected */ + if (flags & ASN1_TFLG_EXPTAG) { + char cst; + /* + * Need to work out amount of data available to the inner content and + * where it starts: so read in EXPLICIT header to get the info. + */ + ret = asn1_check_tlen(&len, NULL, NULL, &exp_eoc, &cst, + &p, inlen, tt->tag, aclass, opt, ctx); + q = p; + if (!ret) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); + return 0; + } else if (ret == -1) + return -1; + if (!cst) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED); + return 0; + } + /* We've found the field so it can't be OPTIONAL now */ + ret = asn1_template_noexp_d2i(val, &p, len, tt, 0, ctx); + if (!ret) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); + return 0; + } + /* We read the field in OK so update length */ + len -= p - q; + if (exp_eoc) { + /* If NDEF we must have an EOC here */ + if (!asn1_check_eoc(&p, len)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_EOC); + goto err; + } + } else { + /* + * Otherwise we must hit the EXPLICIT tag end or its an error + */ + if (len) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_EXPLICIT_LENGTH_MISMATCH); + goto err; + } + } + } else + return asn1_template_noexp_d2i(val, in, inlen, tt, opt, ctx); + + *in = p; + return 1; + + err: + ASN1_template_free(val, tt); + return 0; +} + +static int asn1_template_noexp_d2i(ASN1_VALUE **val, + const unsigned char **in, long len, + const ASN1_TEMPLATE *tt, char opt, + ASN1_TLC *ctx) +{ + int flags, aclass; + int ret; + const unsigned char *p; + if (!val) + return 0; + flags = tt->flags; + aclass = flags & ASN1_TFLG_TAG_CLASS; + + p = *in; + + if (flags & ASN1_TFLG_SK_MASK) { + /* SET OF, SEQUENCE OF */ + int sktag, skaclass; + char sk_eoc; + /* First work out expected inner tag value */ + if (flags & ASN1_TFLG_IMPTAG) { + sktag = tt->tag; + skaclass = aclass; + } else { + skaclass = V_ASN1_UNIVERSAL; + if (flags & ASN1_TFLG_SET_OF) + sktag = V_ASN1_SET; + else + sktag = V_ASN1_SEQUENCE; + } + /* Get the tag */ + ret = asn1_check_tlen(&len, NULL, NULL, &sk_eoc, NULL, + &p, len, sktag, skaclass, opt, ctx); + if (!ret) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); + return 0; + } else if (ret == -1) + return -1; + if (!*val) + *val = (ASN1_VALUE *)sk_new_null(); + else { + /* + * We've got a valid STACK: free up any items present + */ + STACK_OF(ASN1_VALUE) *sktmp = (STACK_OF(ASN1_VALUE) *)*val; + ASN1_VALUE *vtmp; + while (sk_ASN1_VALUE_num(sktmp) > 0) { + vtmp = sk_ASN1_VALUE_pop(sktmp); + ASN1_item_ex_free(&vtmp, ASN1_ITEM_ptr(tt->item)); + } + } + + if (!*val) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + goto err; + } + + /* Read as many items as we can */ + while (len > 0) { + ASN1_VALUE *skfield; + const unsigned char *q = p; + /* See if EOC found */ + if (asn1_check_eoc(&p, len)) { + if (!sk_eoc) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNEXPECTED_EOC); + goto err; + } + len -= p - q; + sk_eoc = 0; + break; + } + skfield = NULL; + if (!ASN1_item_ex_d2i(&skfield, &p, len, + ASN1_ITEM_ptr(tt->item), -1, 0, 0, ctx)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); + goto err; + } + len -= p - q; + if (!sk_ASN1_VALUE_push((STACK_OF(ASN1_VALUE) *)*val, skfield)) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + goto err; + } + } + if (sk_eoc) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_EOC); + goto err; + } + } else if (flags & ASN1_TFLG_IMPTAG) { + /* IMPLICIT tagging */ + ret = ASN1_item_ex_d2i(val, &p, len, + ASN1_ITEM_ptr(tt->item), tt->tag, aclass, opt, + ctx); + if (!ret) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); + goto err; + } else if (ret == -1) + return -1; + } else { + /* Nothing special */ + ret = ASN1_item_ex_d2i(val, &p, len, ASN1_ITEM_ptr(tt->item), + -1, tt->flags & ASN1_TFLG_COMBINE, opt, ctx); + if (!ret) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); + goto err; + } else if (ret == -1) + return -1; + } + + *in = p; + return 1; + + err: + ASN1_template_free(val, tt); + return 0; +} + +static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, + const unsigned char **in, long inlen, + const ASN1_ITEM *it, + int tag, int aclass, char opt, ASN1_TLC *ctx) +{ + int ret = 0, utype; + long plen; + char cst, inf, free_cont = 0; + const unsigned char *p; + BUF_MEM buf = {0, NULL, 0 }; + const unsigned char *cont = NULL; + long len; + if (!pval) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_NULL); + return 0; /* Should never happen */ + } + + if (it->itype == ASN1_ITYPE_MSTRING) { + utype = tag; + tag = -1; + } else + utype = it->utype; + + if (utype == V_ASN1_ANY) { + /* If type is ANY need to figure out type from tag */ + unsigned char oclass; + if (tag >= 0) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_TAGGED_ANY); + return 0; + } + if (opt) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_OPTIONAL_ANY); + return 0; + } + p = *in; + ret = asn1_check_tlen(NULL, &utype, &oclass, NULL, NULL, + &p, inlen, -1, 0, 0, ctx); + if (!ret) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); + return 0; + } + if (oclass != V_ASN1_UNIVERSAL) + utype = V_ASN1_OTHER; + } + if (tag == -1) { + tag = utype; + aclass = V_ASN1_UNIVERSAL; + } + p = *in; + /* Check header */ + ret = asn1_check_tlen(&plen, NULL, NULL, &inf, &cst, + &p, inlen, tag, aclass, opt, ctx); + if (!ret) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); + return 0; + } else if (ret == -1) + return -1; + ret = 0; + /* SEQUENCE, SET and "OTHER" are left in encoded form */ + if ((utype == V_ASN1_SEQUENCE) + || (utype == V_ASN1_SET) || (utype == V_ASN1_OTHER)) { + /* + * Clear context cache for type OTHER because the auto clear when we + * have a exact match wont work + */ + if (utype == V_ASN1_OTHER) { + asn1_tlc_clear(ctx); + } + /* SEQUENCE and SET must be constructed */ + else if (!cst) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_TYPE_NOT_CONSTRUCTED); + return 0; + } + + cont = *in; + /* If indefinite length constructed find the real end */ + if (inf) { + if (!asn1_find_end(&p, plen, inf)) + goto err; + len = p - cont; + } else { + len = p - cont + plen; + p += plen; + } + } else if (cst) { + if (utype == V_ASN1_NULL || utype == V_ASN1_BOOLEAN + || utype == V_ASN1_OBJECT || utype == V_ASN1_INTEGER + || utype == V_ASN1_ENUMERATED) { + /* These types only have primitive encodings. */ + OPENSSL_PUT_ERROR(ASN1, ASN1_R_TYPE_NOT_PRIMITIVE); + return 0; + } + + /* Free any returned 'buf' content */ + free_cont = 1; + /* + * Should really check the internal tags are correct but some things + * may get this wrong. The relevant specs say that constructed string + * types should be OCTET STRINGs internally irrespective of the type. + * So instead just check for UNIVERSAL class and ignore the tag. + */ + if (!asn1_collect(&buf, &p, plen, inf, -1, V_ASN1_UNIVERSAL, 0)) { + goto err; + } + len = buf.length; + /* Append a final null to string */ + if (!BUF_MEM_grow_clean(&buf, len + 1)) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + goto err; + } + buf.data[len] = 0; + cont = (const unsigned char *)buf.data; + } else { + cont = p; + len = plen; + p += plen; + } + + /* We now have content length and type: translate into a structure */ + /* asn1_ex_c2i may reuse allocated buffer, and so sets free_cont to 0 */ + if (!asn1_ex_c2i(pval, cont, len, utype, &free_cont, it)) + goto err; + + *in = p; + ret = 1; + err: + if (free_cont && buf.data) + OPENSSL_free(buf.data); + return ret; +} + +/* Translate ASN1 content octets into a structure */ + +int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, + int utype, char *free_cont, const ASN1_ITEM *it) +{ + ASN1_VALUE **opval = NULL; + ASN1_STRING *stmp; + ASN1_TYPE *typ = NULL; + int ret = 0; + const ASN1_PRIMITIVE_FUNCS *pf; + ASN1_INTEGER **tint; + pf = it->funcs; + + if (pf && pf->prim_c2i) + return pf->prim_c2i(pval, cont, len, utype, free_cont, it); + /* If ANY type clear type and set pointer to internal value */ + if (it->utype == V_ASN1_ANY) { + if (!*pval) { + typ = ASN1_TYPE_new(); + if (typ == NULL) + goto err; + *pval = (ASN1_VALUE *)typ; + } else + typ = (ASN1_TYPE *)*pval; + + if (utype != typ->type) + ASN1_TYPE_set(typ, utype, NULL); + opval = pval; + pval = &typ->value.asn1_value; + } + switch (utype) { + case V_ASN1_OBJECT: + if (!c2i_ASN1_OBJECT((ASN1_OBJECT **)pval, &cont, len)) + goto err; + break; + + case V_ASN1_NULL: + if (len) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_NULL_IS_WRONG_LENGTH); + goto err; + } + *pval = (ASN1_VALUE *)1; + break; + + case V_ASN1_BOOLEAN: + if (len != 1) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_BOOLEAN_IS_WRONG_LENGTH); + goto err; + } else { + ASN1_BOOLEAN *tbool; + tbool = (ASN1_BOOLEAN *)pval; + *tbool = *cont; + } + break; + + case V_ASN1_BIT_STRING: + if (!c2i_ASN1_BIT_STRING((ASN1_BIT_STRING **)pval, &cont, len)) + goto err; + break; + + case V_ASN1_INTEGER: + case V_ASN1_ENUMERATED: + tint = (ASN1_INTEGER **)pval; + if (!c2i_ASN1_INTEGER(tint, &cont, len)) + goto err; + /* Fixup type to match the expected form */ + (*tint)->type = utype | ((*tint)->type & V_ASN1_NEG); + break; + + case V_ASN1_OCTET_STRING: + case V_ASN1_NUMERICSTRING: + case V_ASN1_PRINTABLESTRING: + case V_ASN1_T61STRING: + case V_ASN1_VIDEOTEXSTRING: + case V_ASN1_IA5STRING: + case V_ASN1_UTCTIME: + case V_ASN1_GENERALIZEDTIME: + case V_ASN1_GRAPHICSTRING: + case V_ASN1_VISIBLESTRING: + case V_ASN1_GENERALSTRING: + case V_ASN1_UNIVERSALSTRING: + case V_ASN1_BMPSTRING: + case V_ASN1_UTF8STRING: + case V_ASN1_OTHER: + case V_ASN1_SET: + case V_ASN1_SEQUENCE: + default: + if (utype == V_ASN1_BMPSTRING && (len & 1)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_BMPSTRING_IS_WRONG_LENGTH); + goto err; + } + if (utype == V_ASN1_UNIVERSALSTRING && (len & 3)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH); + goto err; + } + /* All based on ASN1_STRING and handled the same */ + if (!*pval) { + stmp = ASN1_STRING_type_new(utype); + if (!stmp) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + goto err; + } + *pval = (ASN1_VALUE *)stmp; + } else { + stmp = (ASN1_STRING *)*pval; + stmp->type = utype; + } + /* If we've already allocated a buffer use it */ + if (*free_cont) { + if (stmp->data) + OPENSSL_free(stmp->data); + stmp->data = (unsigned char *)cont; /* UGLY CAST! RL */ + stmp->length = len; + *free_cont = 0; + } else { + if (!ASN1_STRING_set(stmp, cont, len)) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + ASN1_STRING_free(stmp); + *pval = NULL; + goto err; + } + } + break; + } + /* If ASN1_ANY and NULL type fix up value */ + if (typ && (utype == V_ASN1_NULL)) + typ->value.ptr = NULL; + + ret = 1; + err: + if (!ret) { + ASN1_TYPE_free(typ); + if (opval) + *opval = NULL; + } + return ret; +} + +/* + * This function finds the end of an ASN1 structure when passed its maximum + * length, whether it is indefinite length and a pointer to the content. This + * is more efficient than calling asn1_collect because it does not recurse on + * each indefinite length header. + */ + +static int asn1_find_end(const unsigned char **in, long len, char inf) +{ + int expected_eoc; + long plen; + const unsigned char *p = *in, *q; + /* If not indefinite length constructed just add length */ + if (inf == 0) { + *in += len; + return 1; + } + expected_eoc = 1; + /* + * Indefinite length constructed form. Find the end when enough EOCs are + * found. If more indefinite length constructed headers are encountered + * increment the expected eoc count otherwise just skip to the end of the + * data. + */ + while (len > 0) { + if (asn1_check_eoc(&p, len)) { + expected_eoc--; + if (expected_eoc == 0) + break; + len -= 2; + continue; + } + q = p; + /* Just read in a header: only care about the length */ + if (!asn1_check_tlen(&plen, NULL, NULL, &inf, NULL, &p, len, + -1, 0, 0, NULL)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); + return 0; + } + if (inf) + expected_eoc++; + else + p += plen; + len -= p - q; + } + if (expected_eoc) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_EOC); + return 0; + } + *in = p; + return 1; +} + +/* + * This function collects the asn1 data from a constructred string type into + * a buffer. The values of 'in' and 'len' should refer to the contents of the + * constructed type and 'inf' should be set if it is indefinite length. + */ + +#ifndef ASN1_MAX_STRING_NEST +/* + * This determines how many levels of recursion are permitted in ASN1 string + * types. If it is not limited stack overflows can occur. If set to zero no + * recursion is allowed at all. Although zero should be adequate examples + * exist that require a value of 1. So 5 should be more than enough. + */ +# define ASN1_MAX_STRING_NEST 5 +#endif + +static int asn1_collect(BUF_MEM *buf, const unsigned char **in, long len, + char inf, int tag, int aclass, int depth) +{ + const unsigned char *p, *q; + long plen; + char cst, ininf; + p = *in; + inf &= 1; + /* + * If no buffer and not indefinite length constructed just pass over the + * encoded data + */ + if (!buf && !inf) { + *in += len; + return 1; + } + while (len > 0) { + q = p; + /* Check for EOC */ + if (asn1_check_eoc(&p, len)) { + /* + * EOC is illegal outside indefinite length constructed form + */ + if (!inf) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNEXPECTED_EOC); + return 0; + } + inf = 0; + break; + } + + if (!asn1_check_tlen(&plen, NULL, NULL, &ininf, &cst, &p, + len, tag, aclass, 0, NULL)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); + return 0; + } + + /* If indefinite length constructed update max length */ + if (cst) { + if (depth >= ASN1_MAX_STRING_NEST) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_STRING); + return 0; + } + if (!asn1_collect(buf, &p, plen, ininf, tag, aclass, depth + 1)) + return 0; + } else if (plen && !collect_data(buf, &p, plen)) + return 0; + len -= p - q; + } + if (inf) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_EOC); + return 0; + } + *in = p; + return 1; +} + +static int collect_data(BUF_MEM *buf, const unsigned char **p, long plen) +{ + int len; + if (buf) { + len = buf->length; + if (!BUF_MEM_grow_clean(buf, len + plen)) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + return 0; + } + memcpy(buf->data + len, *p, plen); + } + *p += plen; + return 1; +} + +/* Check for ASN1 EOC and swallow it if found */ + +static int asn1_check_eoc(const unsigned char **in, long len) +{ + const unsigned char *p; + if (len < 2) + return 0; + p = *in; + if (!p[0] && !p[1]) { + *in += 2; + return 1; + } + return 0; +} + +/* + * Check an ASN1 tag and length: a bit like ASN1_get_object but it sets the + * length for indefinite length constructed form, we don't know the exact + * length but we can set an upper bound to the amount of data available minus + * the header length just read. + */ + +static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass, + char *inf, char *cst, + const unsigned char **in, long len, + int exptag, int expclass, char opt, ASN1_TLC *ctx) +{ + int i; + int ptag, pclass; + long plen; + const unsigned char *p, *q; + p = *in; + q = p; + + if (ctx && ctx->valid) { + i = ctx->ret; + plen = ctx->plen; + pclass = ctx->pclass; + ptag = ctx->ptag; + p += ctx->hdrlen; + } else { + i = ASN1_get_object(&p, &plen, &ptag, &pclass, len); + if (ctx) { + ctx->ret = i; + ctx->plen = plen; + ctx->pclass = pclass; + ctx->ptag = ptag; + ctx->hdrlen = p - q; + ctx->valid = 1; + /* + * If definite length, and no error, length + header can't exceed + * total amount of data available. + */ + if (!(i & 0x81) && ((plen + ctx->hdrlen) > len)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG); + asn1_tlc_clear(ctx); + return 0; + } + } + } + + if (i & 0x80) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_OBJECT_HEADER); + asn1_tlc_clear(ctx); + return 0; + } + if (exptag >= 0) { + if ((exptag != ptag) || (expclass != pclass)) { + /* + * If type is OPTIONAL, not an error: indicate missing type. + */ + if (opt) + return -1; + asn1_tlc_clear(ctx); + OPENSSL_PUT_ERROR(ASN1, ASN1_R_WRONG_TAG); + return 0; + } + /* + * We have a tag and class match: assume we are going to do something + * with it + */ + asn1_tlc_clear(ctx); + } + + if (i & 1) + plen = len - (p - q); + + if (inf) + *inf = i & 1; + + if (cst) + *cst = i & V_ASN1_CONSTRUCTED; + + if (olen) + *olen = plen; + + if (oclass) + *oclass = pclass; + + if (otag) + *otag = ptag; + + *in = p; + return 1; +} diff --git a/external/boringssl/crypto/asn1/tasn_enc.c b/external/boringssl/crypto/asn1/tasn_enc.c new file mode 100644 index 0000000000..409d1388b2 --- /dev/null +++ b/external/boringssl/crypto/asn1/tasn_enc.c @@ -0,0 +1,657 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include +#include + +static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out, + const ASN1_ITEM *it, int tag, int aclass); +static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out, + int skcontlen, const ASN1_ITEM *item, + int do_sort, int iclass); +static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out, + const ASN1_TEMPLATE *tt, int tag, int aclass); +static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out, + const ASN1_ITEM *it, int flags); + +/* + * Top level i2d equivalents: the 'ndef' variant instructs the encoder to use + * indefinite length constructed encoding, where appropriate + */ + +int ASN1_item_ndef_i2d(ASN1_VALUE *val, unsigned char **out, + const ASN1_ITEM *it) +{ + return asn1_item_flags_i2d(val, out, it, ASN1_TFLG_NDEF); +} + +int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it) +{ + return asn1_item_flags_i2d(val, out, it, 0); +} + +/* + * Encode an ASN1 item, this is use by the standard 'i2d' function. 'out' + * points to a buffer to output the data to. The new i2d has one additional + * feature. If the output buffer is NULL (i.e. *out == NULL) then a buffer is + * allocated and populated with the encoding. + */ + +static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out, + const ASN1_ITEM *it, int flags) +{ + if (out && !*out) { + unsigned char *p, *buf; + int len; + len = ASN1_item_ex_i2d(&val, NULL, it, -1, flags); + if (len <= 0) + return len; + buf = OPENSSL_malloc(len); + if (!buf) + return -1; + p = buf; + ASN1_item_ex_i2d(&val, &p, it, -1, flags); + *out = buf; + return len; + } + + return ASN1_item_ex_i2d(&val, out, it, -1, flags); +} + +/* + * Encode an item, taking care of IMPLICIT tagging (if any). This function + * performs the normal item handling: it can be used in external types. + */ + +int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out, + const ASN1_ITEM *it, int tag, int aclass) +{ + const ASN1_TEMPLATE *tt = NULL; + unsigned char *p = NULL; + int i, seqcontlen, seqlen, ndef = 1; + const ASN1_COMPAT_FUNCS *cf; + const ASN1_EXTERN_FUNCS *ef; + const ASN1_AUX *aux = it->funcs; + ASN1_aux_cb *asn1_cb = 0; + + if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval) + return 0; + + if (aux && aux->asn1_cb) + asn1_cb = aux->asn1_cb; + + switch (it->itype) { + + case ASN1_ITYPE_PRIMITIVE: + if (it->templates) + return asn1_template_ex_i2d(pval, out, it->templates, + tag, aclass); + return asn1_i2d_ex_primitive(pval, out, it, tag, aclass); + break; + + case ASN1_ITYPE_MSTRING: + return asn1_i2d_ex_primitive(pval, out, it, -1, aclass); + + case ASN1_ITYPE_CHOICE: + if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL)) + return 0; + i = asn1_get_choice_selector(pval, it); + if ((i >= 0) && (i < it->tcount)) { + ASN1_VALUE **pchval; + const ASN1_TEMPLATE *chtt; + chtt = it->templates + i; + pchval = asn1_get_field_ptr(pval, chtt); + return asn1_template_ex_i2d(pchval, out, chtt, -1, aclass); + } + /* Fixme: error condition if selector out of range */ + if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL)) + return 0; + break; + + case ASN1_ITYPE_EXTERN: + /* If new style i2d it does all the work */ + ef = it->funcs; + return ef->asn1_ex_i2d(pval, out, it, tag, aclass); + + case ASN1_ITYPE_COMPAT: + /* old style hackery... */ + cf = it->funcs; + if (out) + p = *out; + i = cf->asn1_i2d(*pval, out); + /* + * Fixup for IMPLICIT tag: note this messes up for tags > 30, but so + * did the old code. Tags > 30 are very rare anyway. + */ + if (out && (tag != -1)) + *p = aclass | tag | (*p & V_ASN1_CONSTRUCTED); + return i; + + case ASN1_ITYPE_NDEF_SEQUENCE: + /* Use indefinite length constructed if requested */ + if (aclass & ASN1_TFLG_NDEF) + ndef = 2; + /* fall through */ + + case ASN1_ITYPE_SEQUENCE: + i = asn1_enc_restore(&seqcontlen, out, pval, it); + /* An error occurred */ + if (i < 0) + return 0; + /* We have a valid cached encoding... */ + if (i > 0) + return seqcontlen; + /* Otherwise carry on */ + seqcontlen = 0; + /* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */ + if (tag == -1) { + tag = V_ASN1_SEQUENCE; + /* Retain any other flags in aclass */ + aclass = (aclass & ~ASN1_TFLG_TAG_CLASS) + | V_ASN1_UNIVERSAL; + } + if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL)) + return 0; + /* First work out sequence content length */ + for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) { + const ASN1_TEMPLATE *seqtt; + ASN1_VALUE **pseqval; + seqtt = asn1_do_adb(pval, tt, 1); + if (!seqtt) + return 0; + pseqval = asn1_get_field_ptr(pval, seqtt); + /* FIXME: check for errors in enhanced version */ + seqcontlen += asn1_template_ex_i2d(pseqval, NULL, seqtt, + -1, aclass); + } + + seqlen = ASN1_object_size(ndef, seqcontlen, tag); + if (!out) + return seqlen; + /* Output SEQUENCE header */ + ASN1_put_object(out, ndef, seqcontlen, tag, aclass); + for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) { + const ASN1_TEMPLATE *seqtt; + ASN1_VALUE **pseqval; + seqtt = asn1_do_adb(pval, tt, 1); + if (!seqtt) + return 0; + pseqval = asn1_get_field_ptr(pval, seqtt); + /* FIXME: check for errors in enhanced version */ + asn1_template_ex_i2d(pseqval, out, seqtt, -1, aclass); + } + if (ndef == 2) + ASN1_put_eoc(out); + if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL)) + return 0; + return seqlen; + + default: + return 0; + + } + return 0; +} + +int ASN1_template_i2d(ASN1_VALUE **pval, unsigned char **out, + const ASN1_TEMPLATE *tt) +{ + return asn1_template_ex_i2d(pval, out, tt, -1, 0); +} + +static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out, + const ASN1_TEMPLATE *tt, int tag, int iclass) +{ + int i, ret, flags, ttag, tclass, ndef; + size_t j; + flags = tt->flags; + /* + * Work out tag and class to use: tagging may come either from the + * template or the arguments, not both because this would create + * ambiguity. Additionally the iclass argument may contain some + * additional flags which should be noted and passed down to other + * levels. + */ + if (flags & ASN1_TFLG_TAG_MASK) { + /* Error if argument and template tagging */ + if (tag != -1) + /* FIXME: error code here */ + return -1; + /* Get tagging from template */ + ttag = tt->tag; + tclass = flags & ASN1_TFLG_TAG_CLASS; + } else if (tag != -1) { + /* No template tagging, get from arguments */ + ttag = tag; + tclass = iclass & ASN1_TFLG_TAG_CLASS; + } else { + ttag = -1; + tclass = 0; + } + /* + * Remove any class mask from iflag. + */ + iclass &= ~ASN1_TFLG_TAG_CLASS; + + /* + * At this point 'ttag' contains the outer tag to use, 'tclass' is the + * class and iclass is any flags passed to this function. + */ + + /* if template and arguments require ndef, use it */ + if ((flags & ASN1_TFLG_NDEF) && (iclass & ASN1_TFLG_NDEF)) + ndef = 2; + else + ndef = 1; + + if (flags & ASN1_TFLG_SK_MASK) { + /* SET OF, SEQUENCE OF */ + STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval; + int isset, sktag, skaclass; + int skcontlen, sklen; + ASN1_VALUE *skitem; + + if (!*pval) + return 0; + + if (flags & ASN1_TFLG_SET_OF) { + isset = 1; + /* 2 means we reorder */ + if (flags & ASN1_TFLG_SEQUENCE_OF) + isset = 2; + } else + isset = 0; + + /* + * Work out inner tag value: if EXPLICIT or no tagging use underlying + * type. + */ + if ((ttag != -1) && !(flags & ASN1_TFLG_EXPTAG)) { + sktag = ttag; + skaclass = tclass; + } else { + skaclass = V_ASN1_UNIVERSAL; + if (isset) + sktag = V_ASN1_SET; + else + sktag = V_ASN1_SEQUENCE; + } + + /* Determine total length of items */ + skcontlen = 0; + for (j = 0; j < sk_ASN1_VALUE_num(sk); j++) { + skitem = sk_ASN1_VALUE_value(sk, j); + skcontlen += ASN1_item_ex_i2d(&skitem, NULL, + ASN1_ITEM_ptr(tt->item), + -1, iclass); + } + sklen = ASN1_object_size(ndef, skcontlen, sktag); + /* If EXPLICIT need length of surrounding tag */ + if (flags & ASN1_TFLG_EXPTAG) + ret = ASN1_object_size(ndef, sklen, ttag); + else + ret = sklen; + + if (!out) + return ret; + + /* Now encode this lot... */ + /* EXPLICIT tag */ + if (flags & ASN1_TFLG_EXPTAG) + ASN1_put_object(out, ndef, sklen, ttag, tclass); + /* SET or SEQUENCE and IMPLICIT tag */ + ASN1_put_object(out, ndef, skcontlen, sktag, skaclass); + /* And the stuff itself */ + asn1_set_seq_out(sk, out, skcontlen, ASN1_ITEM_ptr(tt->item), + isset, iclass); + if (ndef == 2) { + ASN1_put_eoc(out); + if (flags & ASN1_TFLG_EXPTAG) + ASN1_put_eoc(out); + } + + return ret; + } + + if (flags & ASN1_TFLG_EXPTAG) { + /* EXPLICIT tagging */ + /* Find length of tagged item */ + i = ASN1_item_ex_i2d(pval, NULL, ASN1_ITEM_ptr(tt->item), -1, iclass); + if (!i) + return 0; + /* Find length of EXPLICIT tag */ + ret = ASN1_object_size(ndef, i, ttag); + if (out) { + /* Output tag and item */ + ASN1_put_object(out, ndef, i, ttag, tclass); + ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item), -1, iclass); + if (ndef == 2) + ASN1_put_eoc(out); + } + return ret; + } + + /* Either normal or IMPLICIT tagging: combine class and flags */ + return ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item), + ttag, tclass | iclass); + +} + +/* Temporary structure used to hold DER encoding of items for SET OF */ + +typedef struct { + unsigned char *data; + int length; + ASN1_VALUE *field; +} DER_ENC; + +static int der_cmp(const void *a, const void *b) +{ + const DER_ENC *d1 = a, *d2 = b; + int cmplen, i; + cmplen = (d1->length < d2->length) ? d1->length : d2->length; + i = memcmp(d1->data, d2->data, cmplen); + if (i) + return i; + return d1->length - d2->length; +} + +/* Output the content octets of SET OF or SEQUENCE OF */ + +static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out, + int skcontlen, const ASN1_ITEM *item, + int do_sort, int iclass) +{ + size_t i; + ASN1_VALUE *skitem; + unsigned char *tmpdat = NULL, *p = NULL; + DER_ENC *derlst = NULL, *tder; + if (do_sort) { + /* Don't need to sort less than 2 items */ + if (sk_ASN1_VALUE_num(sk) < 2) + do_sort = 0; + else { + derlst = OPENSSL_malloc(sk_ASN1_VALUE_num(sk) + * sizeof(*derlst)); + if (!derlst) + return 0; + tmpdat = OPENSSL_malloc(skcontlen); + if (!tmpdat) { + OPENSSL_free(derlst); + return 0; + } + } + } + /* If not sorting just output each item */ + if (!do_sort) { + for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) { + skitem = sk_ASN1_VALUE_value(sk, i); + ASN1_item_ex_i2d(&skitem, out, item, -1, iclass); + } + return 1; + } + p = tmpdat; + + /* Doing sort: build up a list of each member's DER encoding */ + for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) { + skitem = sk_ASN1_VALUE_value(sk, i); + tder->data = p; + tder->length = ASN1_item_ex_i2d(&skitem, &p, item, -1, iclass); + tder->field = skitem; + } + + /* Now sort them */ + qsort(derlst, sk_ASN1_VALUE_num(sk), sizeof(*derlst), der_cmp); + /* Output sorted DER encoding */ + p = *out; + for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) { + memcpy(p, tder->data, tder->length); + p += tder->length; + } + *out = p; + /* If do_sort is 2 then reorder the STACK */ + if (do_sort == 2) { + for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) + (void)sk_ASN1_VALUE_set(sk, i, tder->field); + } + OPENSSL_free(derlst); + OPENSSL_free(tmpdat); + return 1; +} + +static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out, + const ASN1_ITEM *it, int tag, int aclass) +{ + int len; + int utype; + int usetag; + int ndef = 0; + + utype = it->utype; + + /* + * Get length of content octets and maybe find out the underlying type. + */ + + len = asn1_ex_i2c(pval, NULL, &utype, it); + + /* + * If SEQUENCE, SET or OTHER then header is included in pseudo content + * octets so don't include tag+length. We need to check here because the + * call to asn1_ex_i2c() could change utype. + */ + if ((utype == V_ASN1_SEQUENCE) || (utype == V_ASN1_SET) || + (utype == V_ASN1_OTHER)) + usetag = 0; + else + usetag = 1; + + /* -1 means omit type */ + + if (len == -1) + return 0; + + /* -2 return is special meaning use ndef */ + if (len == -2) { + ndef = 2; + len = 0; + } + + /* If not implicitly tagged get tag from underlying type */ + if (tag == -1) + tag = utype; + + /* Output tag+length followed by content octets */ + if (out) { + if (usetag) + ASN1_put_object(out, ndef, len, tag, aclass); + asn1_ex_i2c(pval, *out, &utype, it); + if (ndef) + ASN1_put_eoc(out); + else + *out += len; + } + + if (usetag) + return ASN1_object_size(ndef, len, tag); + return len; +} + +/* Produce content octets from a structure */ + +int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype, + const ASN1_ITEM *it) +{ + ASN1_BOOLEAN *tbool = NULL; + ASN1_STRING *strtmp; + ASN1_OBJECT *otmp; + int utype; + const unsigned char *cont; + unsigned char c; + int len; + const ASN1_PRIMITIVE_FUNCS *pf; + pf = it->funcs; + if (pf && pf->prim_i2c) + return pf->prim_i2c(pval, cout, putype, it); + + /* Should type be omitted? */ + if ((it->itype != ASN1_ITYPE_PRIMITIVE) + || (it->utype != V_ASN1_BOOLEAN)) { + if (!*pval) + return -1; + } + + if (it->itype == ASN1_ITYPE_MSTRING) { + /* If MSTRING type set the underlying type */ + strtmp = (ASN1_STRING *)*pval; + utype = strtmp->type; + *putype = utype; + } else if (it->utype == V_ASN1_ANY) { + /* If ANY set type and pointer to value */ + ASN1_TYPE *typ; + typ = (ASN1_TYPE *)*pval; + utype = typ->type; + *putype = utype; + pval = &typ->value.asn1_value; + } else + utype = *putype; + + switch (utype) { + case V_ASN1_OBJECT: + otmp = (ASN1_OBJECT *)*pval; + cont = otmp->data; + len = otmp->length; + break; + + case V_ASN1_NULL: + cont = NULL; + len = 0; + break; + + case V_ASN1_BOOLEAN: + tbool = (ASN1_BOOLEAN *)pval; + if (*tbool == -1) + return -1; + if (it->utype != V_ASN1_ANY) { + /* + * Default handling if value == size field then omit + */ + if (*tbool && (it->size > 0)) + return -1; + if (!*tbool && !it->size) + return -1; + } + c = (unsigned char)*tbool; + cont = &c; + len = 1; + break; + + case V_ASN1_BIT_STRING: + return i2c_ASN1_BIT_STRING((ASN1_BIT_STRING *)*pval, + cout ? &cout : NULL); + break; + + case V_ASN1_INTEGER: + case V_ASN1_ENUMERATED: + /* + * These are all have the same content format as ASN1_INTEGER + */ + return i2c_ASN1_INTEGER((ASN1_INTEGER *)*pval, cout ? &cout : NULL); + break; + + case V_ASN1_OCTET_STRING: + case V_ASN1_NUMERICSTRING: + case V_ASN1_PRINTABLESTRING: + case V_ASN1_T61STRING: + case V_ASN1_VIDEOTEXSTRING: + case V_ASN1_IA5STRING: + case V_ASN1_UTCTIME: + case V_ASN1_GENERALIZEDTIME: + case V_ASN1_GRAPHICSTRING: + case V_ASN1_VISIBLESTRING: + case V_ASN1_GENERALSTRING: + case V_ASN1_UNIVERSALSTRING: + case V_ASN1_BMPSTRING: + case V_ASN1_UTF8STRING: + case V_ASN1_SEQUENCE: + case V_ASN1_SET: + default: + /* All based on ASN1_STRING and handled the same */ + strtmp = (ASN1_STRING *)*pval; + /* Special handling for NDEF */ + if ((it->size == ASN1_TFLG_NDEF) + && (strtmp->flags & ASN1_STRING_FLAG_NDEF)) { + if (cout) { + strtmp->data = cout; + strtmp->length = 0; + } + /* Special return code */ + return -2; + } + cont = strtmp->data; + len = strtmp->length; + + break; + + } + if (cout && len) + memcpy(cout, cont, len); + return len; +} diff --git a/external/boringssl/crypto/asn1/tasn_fre.c b/external/boringssl/crypto/asn1/tasn_fre.c new file mode 100644 index 0000000000..609cb9f987 --- /dev/null +++ b/external/boringssl/crypto/asn1/tasn_fre.c @@ -0,0 +1,246 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +static void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it, + int combine); + +/* Free up an ASN1 structure */ + +void ASN1_item_free(ASN1_VALUE *val, const ASN1_ITEM *it) +{ + asn1_item_combine_free(&val, it, 0); +} + +void ASN1_item_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + asn1_item_combine_free(pval, it, 0); +} + +static void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it, + int combine) +{ + const ASN1_TEMPLATE *tt = NULL, *seqtt; + const ASN1_EXTERN_FUNCS *ef; + const ASN1_COMPAT_FUNCS *cf; + const ASN1_AUX *aux = it->funcs; + ASN1_aux_cb *asn1_cb; + int i; + if (!pval) + return; + if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval) + return; + if (aux && aux->asn1_cb) + asn1_cb = aux->asn1_cb; + else + asn1_cb = 0; + + switch (it->itype) { + + case ASN1_ITYPE_PRIMITIVE: + if (it->templates) + ASN1_template_free(pval, it->templates); + else + ASN1_primitive_free(pval, it); + break; + + case ASN1_ITYPE_MSTRING: + ASN1_primitive_free(pval, it); + break; + + case ASN1_ITYPE_CHOICE: + if (asn1_cb) { + i = asn1_cb(ASN1_OP_FREE_PRE, pval, it, NULL); + if (i == 2) + return; + } + i = asn1_get_choice_selector(pval, it); + if ((i >= 0) && (i < it->tcount)) { + ASN1_VALUE **pchval; + tt = it->templates + i; + pchval = asn1_get_field_ptr(pval, tt); + ASN1_template_free(pchval, tt); + } + if (asn1_cb) + asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL); + if (!combine) { + OPENSSL_free(*pval); + *pval = NULL; + } + break; + + case ASN1_ITYPE_COMPAT: + cf = it->funcs; + if (cf && cf->asn1_free) + cf->asn1_free(*pval); + break; + + case ASN1_ITYPE_EXTERN: + ef = it->funcs; + if (ef && ef->asn1_ex_free) + ef->asn1_ex_free(pval, it); + break; + + case ASN1_ITYPE_NDEF_SEQUENCE: + case ASN1_ITYPE_SEQUENCE: + if (!asn1_refcount_dec_and_test_zero(pval, it)) + return; + if (asn1_cb) { + i = asn1_cb(ASN1_OP_FREE_PRE, pval, it, NULL); + if (i == 2) + return; + } + asn1_enc_free(pval, it); + /* + * If we free up as normal we will invalidate any ANY DEFINED BY + * field and we wont be able to determine the type of the field it + * defines. So free up in reverse order. + */ + tt = it->templates + it->tcount - 1; + for (i = 0; i < it->tcount; tt--, i++) { + ASN1_VALUE **pseqval; + seqtt = asn1_do_adb(pval, tt, 0); + if (!seqtt) + continue; + pseqval = asn1_get_field_ptr(pval, seqtt); + ASN1_template_free(pseqval, seqtt); + } + if (asn1_cb) + asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL); + if (!combine) { + OPENSSL_free(*pval); + *pval = NULL; + } + break; + } +} + +void ASN1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) +{ + size_t i; + if (tt->flags & ASN1_TFLG_SK_MASK) { + STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval; + for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) { + ASN1_VALUE *vtmp; + vtmp = sk_ASN1_VALUE_value(sk, i); + asn1_item_combine_free(&vtmp, ASN1_ITEM_ptr(tt->item), 0); + } + sk_ASN1_VALUE_free(sk); + *pval = NULL; + } else + asn1_item_combine_free(pval, ASN1_ITEM_ptr(tt->item), + tt->flags & ASN1_TFLG_COMBINE); +} + +void ASN1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + int utype; + if (it) { + const ASN1_PRIMITIVE_FUNCS *pf; + pf = it->funcs; + if (pf && pf->prim_free) { + pf->prim_free(pval, it); + return; + } + } + /* Special case: if 'it' is NULL free contents of ASN1_TYPE */ + if (!it) { + ASN1_TYPE *typ = (ASN1_TYPE *)*pval; + utype = typ->type; + pval = &typ->value.asn1_value; + if (!*pval) + return; + } else if (it->itype == ASN1_ITYPE_MSTRING) { + utype = -1; + if (!*pval) + return; + } else { + utype = it->utype; + if ((utype != V_ASN1_BOOLEAN) && !*pval) + return; + } + + switch (utype) { + case V_ASN1_OBJECT: + ASN1_OBJECT_free((ASN1_OBJECT *)*pval); + break; + + case V_ASN1_BOOLEAN: + if (it) + *(ASN1_BOOLEAN *)pval = it->size; + else + *(ASN1_BOOLEAN *)pval = -1; + return; + + case V_ASN1_NULL: + break; + + case V_ASN1_ANY: + ASN1_primitive_free(pval, NULL); + OPENSSL_free(*pval); + break; + + default: + ASN1_STRING_free((ASN1_STRING *)*pval); + *pval = NULL; + break; + } + *pval = NULL; +} diff --git a/external/boringssl/crypto/asn1/tasn_new.c b/external/boringssl/crypto/asn1/tasn_new.c new file mode 100644 index 0000000000..232fe46aaa --- /dev/null +++ b/external/boringssl/crypto/asn1/tasn_new.c @@ -0,0 +1,381 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include +#include +#include +#include + +static int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it, + int combine); +static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it); +static void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt); +static void asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it); + +ASN1_VALUE *ASN1_item_new(const ASN1_ITEM *it) +{ + ASN1_VALUE *ret = NULL; + if (ASN1_item_ex_new(&ret, it) > 0) + return ret; + return NULL; +} + +/* Allocate an ASN1 structure */ + +int ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + return asn1_item_ex_combine_new(pval, it, 0); +} + +static int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it, + int combine) +{ + const ASN1_TEMPLATE *tt = NULL; + const ASN1_COMPAT_FUNCS *cf; + const ASN1_EXTERN_FUNCS *ef; + const ASN1_AUX *aux = it->funcs; + ASN1_aux_cb *asn1_cb; + ASN1_VALUE **pseqval; + int i; + if (aux && aux->asn1_cb) + asn1_cb = aux->asn1_cb; + else + asn1_cb = 0; + +#ifdef CRYPTO_MDEBUG + if (it->sname) + CRYPTO_push_info(it->sname); +#endif + + switch (it->itype) { + + case ASN1_ITYPE_EXTERN: + ef = it->funcs; + if (ef && ef->asn1_ex_new) { + if (!ef->asn1_ex_new(pval, it)) + goto memerr; + } + break; + + case ASN1_ITYPE_COMPAT: + cf = it->funcs; + if (cf && cf->asn1_new) { + *pval = cf->asn1_new(); + if (!*pval) + goto memerr; + } + break; + + case ASN1_ITYPE_PRIMITIVE: + if (it->templates) { + if (!ASN1_template_new(pval, it->templates)) + goto memerr; + } else if (!ASN1_primitive_new(pval, it)) + goto memerr; + break; + + case ASN1_ITYPE_MSTRING: + if (!ASN1_primitive_new(pval, it)) + goto memerr; + break; + + case ASN1_ITYPE_CHOICE: + if (asn1_cb) { + i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL); + if (!i) + goto auxerr; + if (i == 2) { +#ifdef CRYPTO_MDEBUG + if (it->sname) + CRYPTO_pop_info(); +#endif + return 1; + } + } + if (!combine) { + *pval = OPENSSL_malloc(it->size); + if (!*pval) + goto memerr; + memset(*pval, 0, it->size); + } + asn1_set_choice_selector(pval, -1, it); + if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL)) + goto auxerr; + break; + + case ASN1_ITYPE_NDEF_SEQUENCE: + case ASN1_ITYPE_SEQUENCE: + if (asn1_cb) { + i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL); + if (!i) + goto auxerr; + if (i == 2) { +#ifdef CRYPTO_MDEBUG + if (it->sname) + CRYPTO_pop_info(); +#endif + return 1; + } + } + if (!combine) { + *pval = OPENSSL_malloc(it->size); + if (!*pval) + goto memerr; + memset(*pval, 0, it->size); + asn1_refcount_set_one(pval, it); + asn1_enc_init(pval, it); + } + for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) { + pseqval = asn1_get_field_ptr(pval, tt); + if (!ASN1_template_new(pseqval, tt)) + goto memerr; + } + if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL)) + goto auxerr; + break; + } +#ifdef CRYPTO_MDEBUG + if (it->sname) + CRYPTO_pop_info(); +#endif + return 1; + + memerr: + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + ASN1_item_ex_free(pval, it); +#ifdef CRYPTO_MDEBUG + if (it->sname) + CRYPTO_pop_info(); +#endif + return 0; + + auxerr: + OPENSSL_PUT_ERROR(ASN1, ASN1_R_AUX_ERROR); + ASN1_item_ex_free(pval, it); +#ifdef CRYPTO_MDEBUG + if (it->sname) + CRYPTO_pop_info(); +#endif + return 0; + +} + +static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + const ASN1_EXTERN_FUNCS *ef; + + switch (it->itype) { + + case ASN1_ITYPE_EXTERN: + ef = it->funcs; + if (ef && ef->asn1_ex_clear) + ef->asn1_ex_clear(pval, it); + else + *pval = NULL; + break; + + case ASN1_ITYPE_PRIMITIVE: + if (it->templates) + asn1_template_clear(pval, it->templates); + else + asn1_primitive_clear(pval, it); + break; + + case ASN1_ITYPE_MSTRING: + asn1_primitive_clear(pval, it); + break; + + case ASN1_ITYPE_COMPAT: + case ASN1_ITYPE_CHOICE: + case ASN1_ITYPE_SEQUENCE: + case ASN1_ITYPE_NDEF_SEQUENCE: + *pval = NULL; + break; + } +} + +int ASN1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) +{ + const ASN1_ITEM *it = ASN1_ITEM_ptr(tt->item); + int ret; + if (tt->flags & ASN1_TFLG_OPTIONAL) { + asn1_template_clear(pval, tt); + return 1; + } + /* If ANY DEFINED BY nothing to do */ + + if (tt->flags & ASN1_TFLG_ADB_MASK) { + *pval = NULL; + return 1; + } +#ifdef CRYPTO_MDEBUG + if (tt->field_name) + CRYPTO_push_info(tt->field_name); +#endif + /* If SET OF or SEQUENCE OF, its a STACK */ + if (tt->flags & ASN1_TFLG_SK_MASK) { + STACK_OF(ASN1_VALUE) *skval; + skval = sk_ASN1_VALUE_new_null(); + if (!skval) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + ret = 0; + goto done; + } + *pval = (ASN1_VALUE *)skval; + ret = 1; + goto done; + } + /* Otherwise pass it back to the item routine */ + ret = asn1_item_ex_combine_new(pval, it, tt->flags & ASN1_TFLG_COMBINE); + done: +#ifdef CRYPTO_MDEBUG + if (it->sname) + CRYPTO_pop_info(); +#endif + return ret; +} + +static void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) +{ + /* If ADB or STACK just NULL the field */ + if (tt->flags & (ASN1_TFLG_ADB_MASK | ASN1_TFLG_SK_MASK)) + *pval = NULL; + else + asn1_item_clear(pval, ASN1_ITEM_ptr(tt->item)); +} + +/* + * NB: could probably combine most of the real XXX_new() behaviour and junk + * all the old functions. + */ + +int ASN1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + ASN1_TYPE *typ; + ASN1_STRING *str; + int utype; + + if (!it) + return 0; + + if (it->funcs) { + const ASN1_PRIMITIVE_FUNCS *pf = it->funcs; + if (pf->prim_new) + return pf->prim_new(pval, it); + } + + if (it->itype == ASN1_ITYPE_MSTRING) + utype = -1; + else + utype = it->utype; + switch (utype) { + case V_ASN1_OBJECT: + *pval = (ASN1_VALUE *)OBJ_nid2obj(NID_undef); + return 1; + + case V_ASN1_BOOLEAN: + *(ASN1_BOOLEAN *)pval = it->size; + return 1; + + case V_ASN1_NULL: + *pval = (ASN1_VALUE *)1; + return 1; + + case V_ASN1_ANY: + typ = OPENSSL_malloc(sizeof(ASN1_TYPE)); + if (!typ) + return 0; + typ->value.ptr = NULL; + typ->type = -1; + *pval = (ASN1_VALUE *)typ; + break; + + default: + str = ASN1_STRING_type_new(utype); + if (it->itype == ASN1_ITYPE_MSTRING && str) + str->flags |= ASN1_STRING_FLAG_MSTRING; + *pval = (ASN1_VALUE *)str; + break; + } + if (*pval) + return 1; + return 0; +} + +static void asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + int utype; + if (it && it->funcs) { + const ASN1_PRIMITIVE_FUNCS *pf = it->funcs; + if (pf->prim_clear) + pf->prim_clear(pval, it); + else + *pval = NULL; + return; + } + if (!it || (it->itype == ASN1_ITYPE_MSTRING)) + utype = -1; + else + utype = it->utype; + if (utype == V_ASN1_BOOLEAN) + *(ASN1_BOOLEAN *)pval = it->size; + else + *pval = NULL; +} diff --git a/external/boringssl/crypto/asn1/tasn_typ.c b/external/boringssl/crypto/asn1/tasn_typ.c new file mode 100644 index 0000000000..daf02eae93 --- /dev/null +++ b/external/boringssl/crypto/asn1/tasn_typ.c @@ -0,0 +1,144 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +/* Declarations for string types */ + +#define IMPLEMENT_ASN1_STRING_FUNCTIONS(sname) \ + IMPLEMENT_ASN1_TYPE(sname) \ + IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(sname, sname, sname) \ + sname *sname##_new(void) \ + { \ + return ASN1_STRING_type_new(V_##sname); \ + } \ + void sname##_free(sname *x) \ + { \ + ASN1_STRING_free(x); \ + } + +IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_OCTET_STRING) +IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_INTEGER) +IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_ENUMERATED) +IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_BIT_STRING) +IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_UTF8STRING) +IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_PRINTABLESTRING) +IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_T61STRING) +IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_IA5STRING) +IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_GENERALSTRING) +IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_UTCTIME) +IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_GENERALIZEDTIME) +IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_VISIBLESTRING) +IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_UNIVERSALSTRING) +IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_BMPSTRING) + +IMPLEMENT_ASN1_TYPE(ASN1_NULL); +IMPLEMENT_ASN1_FUNCTIONS(ASN1_NULL); + +IMPLEMENT_ASN1_TYPE(ASN1_OBJECT); + +IMPLEMENT_ASN1_TYPE(ASN1_ANY); + +/* + * Just swallow an ASN1_SEQUENCE in an ASN1_STRING + */ ; +IMPLEMENT_ASN1_TYPE(ASN1_SEQUENCE); + +IMPLEMENT_ASN1_FUNCTIONS_fname(ASN1_TYPE, ASN1_ANY, ASN1_TYPE); + +/* + * Multistring types + */ ; + +IMPLEMENT_ASN1_MSTRING(ASN1_PRINTABLE, B_ASN1_PRINTABLE); +IMPLEMENT_ASN1_FUNCTIONS_name(ASN1_STRING, ASN1_PRINTABLE); + +IMPLEMENT_ASN1_MSTRING(DISPLAYTEXT, B_ASN1_DISPLAYTEXT); +IMPLEMENT_ASN1_FUNCTIONS_name(ASN1_STRING, DISPLAYTEXT); + +IMPLEMENT_ASN1_MSTRING(DIRECTORYSTRING, B_ASN1_DIRECTORYSTRING); +IMPLEMENT_ASN1_FUNCTIONS_name(ASN1_STRING, DIRECTORYSTRING); + +/* + * Three separate BOOLEAN type: normal, DEFAULT TRUE and DEFAULT FALSE + */ ; +IMPLEMENT_ASN1_TYPE_ex(ASN1_BOOLEAN, ASN1_BOOLEAN, -1); +IMPLEMENT_ASN1_TYPE_ex(ASN1_TBOOLEAN, ASN1_BOOLEAN, 1); +IMPLEMENT_ASN1_TYPE_ex(ASN1_FBOOLEAN, ASN1_BOOLEAN, 0); + +/* + * Special, OCTET STRING with indefinite length constructed support + */ ; + +IMPLEMENT_ASN1_TYPE_ex(ASN1_OCTET_STRING_NDEF, ASN1_OCTET_STRING, +ASN1_TFLG_NDEF); + +ASN1_ITEM_TEMPLATE(ASN1_SEQUENCE_ANY) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, ASN1_SEQUENCE_ANY, + ASN1_ANY); +ASN1_ITEM_TEMPLATE_END(ASN1_SEQUENCE_ANY); + +ASN1_ITEM_TEMPLATE(ASN1_SET_ANY) = ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SET_OF, 0, + ASN1_SET_ANY, + ASN1_ANY); +ASN1_ITEM_TEMPLATE_END(ASN1_SET_ANY); + +IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(ASN1_SEQUENCE_ANY, +ASN1_SEQUENCE_ANY, ASN1_SEQUENCE_ANY); +IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(ASN1_SEQUENCE_ANY, ASN1_SET_ANY, +ASN1_SET_ANY); diff --git a/external/boringssl/crypto/asn1/tasn_utl.c b/external/boringssl/crypto/asn1/tasn_utl.c new file mode 100644 index 0000000000..960cdbb7a5 --- /dev/null +++ b/external/boringssl/crypto/asn1/tasn_utl.c @@ -0,0 +1,266 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include +#include +#include +#include +#include + +#include "../internal.h" + + +/* Utility functions for manipulating fields and offsets */ + +/* Add 'offset' to 'addr' */ +#define offset2ptr(addr, offset) (void *)(((char *) addr) + offset) + +/* Given an ASN1_ITEM CHOICE type return the selector value */ +int asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it) { + int *sel = offset2ptr(*pval, it->utype); + return *sel; +} + +/* Given an ASN1_ITEM CHOICE type set the selector value, return old value. */ +int asn1_set_choice_selector(ASN1_VALUE **pval, int value, + const ASN1_ITEM *it) { + int *sel, ret; + sel = offset2ptr(*pval, it->utype); + ret = *sel; + *sel = value; + return ret; +} + +static CRYPTO_refcount_t *asn1_get_references(ASN1_VALUE **pval, + const ASN1_ITEM *it) { + if (it->itype != ASN1_ITYPE_SEQUENCE && + it->itype != ASN1_ITYPE_NDEF_SEQUENCE) { + return NULL; + } + const ASN1_AUX *aux = it->funcs; + if (!aux || !(aux->flags & ASN1_AFLG_REFCOUNT)) { + return NULL; + } + return offset2ptr(*pval, aux->ref_offset); +} + +void asn1_refcount_set_one(ASN1_VALUE **pval, const ASN1_ITEM *it) { + CRYPTO_refcount_t *references = asn1_get_references(pval, it); + if (references != NULL) { + *references = 1; + } +} + +int asn1_refcount_dec_and_test_zero(ASN1_VALUE **pval, const ASN1_ITEM *it) { + CRYPTO_refcount_t *references = asn1_get_references(pval, it); + if (references != NULL) { + return CRYPTO_refcount_dec_and_test_zero(references); + } + return 1; +} + +static ASN1_ENCODING *asn1_get_enc_ptr(ASN1_VALUE **pval, const ASN1_ITEM *it) { + const ASN1_AUX *aux; + if (!pval || !*pval) { + return NULL; + } + aux = it->funcs; + if (!aux || !(aux->flags & ASN1_AFLG_ENCODING)) { + return NULL; + } + return offset2ptr(*pval, aux->enc_offset); +} + +void asn1_enc_init(ASN1_VALUE **pval, const ASN1_ITEM *it) { + ASN1_ENCODING *enc; + enc = asn1_get_enc_ptr(pval, it); + if (enc) { + enc->enc = NULL; + enc->len = 0; + enc->modified = 1; + } +} + +void asn1_enc_free(ASN1_VALUE **pval, const ASN1_ITEM *it) { + ASN1_ENCODING *enc; + enc = asn1_get_enc_ptr(pval, it); + if (enc) { + if (enc->enc) { + OPENSSL_free(enc->enc); + } + enc->enc = NULL; + enc->len = 0; + enc->modified = 1; + } +} + +int asn1_enc_save(ASN1_VALUE **pval, const unsigned char *in, int inlen, + const ASN1_ITEM *it) { + ASN1_ENCODING *enc; + enc = asn1_get_enc_ptr(pval, it); + if (!enc) { + return 1; + } + + if (enc->enc) { + OPENSSL_free(enc->enc); + } + enc->enc = OPENSSL_malloc(inlen); + if (!enc->enc) { + return 0; + } + memcpy(enc->enc, in, inlen); + enc->len = inlen; + enc->modified = 0; + + return 1; +} + +int asn1_enc_restore(int *len, unsigned char **out, ASN1_VALUE **pval, + const ASN1_ITEM *it) { + ASN1_ENCODING *enc; + enc = asn1_get_enc_ptr(pval, it); + if (!enc || enc->modified) { + return 0; + } + if (out) { + memcpy(*out, enc->enc, enc->len); + *out += enc->len; + } + if (len) { + *len = enc->len; + } + return 1; +} + +/* Given an ASN1_TEMPLATE get a pointer to a field */ +ASN1_VALUE **asn1_get_field_ptr(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) { + ASN1_VALUE **pvaltmp; + if (tt->flags & ASN1_TFLG_COMBINE) { + return pval; + } + pvaltmp = offset2ptr(*pval, tt->offset); + /* NOTE for BOOLEAN types the field is just a plain int so we can't return + * int **, so settle for (int *). */ + return pvaltmp; +} + +/* Handle ANY DEFINED BY template, find the selector, look up the relevant + * ASN1_TEMPLATE in the table and return it. */ +const ASN1_TEMPLATE *asn1_do_adb(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt, + int nullerr) { + const ASN1_ADB *adb; + const ASN1_ADB_TABLE *atbl; + long selector; + ASN1_VALUE **sfld; + int i; + if (!(tt->flags & ASN1_TFLG_ADB_MASK)) { + return tt; + } + + /* Else ANY DEFINED BY ... get the table */ + adb = ASN1_ADB_ptr(tt->item); + + /* Get the selector field */ + sfld = offset2ptr(*pval, adb->offset); + + /* Check if NULL */ + if (!sfld) { + if (!adb->null_tt) { + goto err; + } + return adb->null_tt; + } + + /* Convert type to a long: + * NB: don't check for NID_undef here because it + * might be a legitimate value in the table */ + if (tt->flags & ASN1_TFLG_ADB_OID) { + selector = OBJ_obj2nid((ASN1_OBJECT *)*sfld); + } else { + selector = ASN1_INTEGER_get((ASN1_INTEGER *)*sfld); + } + + /* Try to find matching entry in table Maybe should check application types + * first to allow application override? Might also be useful to have a flag + * which indicates table is sorted and we can do a binary search. For now + * stick to a linear search. */ + + for (atbl = adb->tbl, i = 0; i < adb->tblcount; i++, atbl++) { + if (atbl->value == selector) { + return &atbl->tt; + } + } + + /* FIXME: need to search application table too */ + + /* No match, return default type */ + if (!adb->default_tt) { + goto err; + } + return adb->default_tt; + +err: + /* FIXME: should log the value or OID of unsupported type */ + if (nullerr) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE); + } + return NULL; +} diff --git a/external/boringssl/crypto/asn1/x_bignum.c b/external/boringssl/crypto/asn1/x_bignum.c new file mode 100644 index 0000000000..585d9d4a43 --- /dev/null +++ b/external/boringssl/crypto/asn1/x_bignum.c @@ -0,0 +1,153 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +/* + * Custom primitive type for BIGNUM handling. This reads in an ASN1_INTEGER + * as a BIGNUM directly. Currently it ignores the sign which isn't a problem + * since all BIGNUMs used are non negative and anything that looks negative + * is normally due to an encoding error. + */ + +#define BN_SENSITIVE 1 + +static int bn_new(ASN1_VALUE **pval, const ASN1_ITEM *it); +static void bn_free(ASN1_VALUE **pval, const ASN1_ITEM *it); + +static int bn_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, + const ASN1_ITEM *it); +static int bn_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, + int utype, char *free_cont, const ASN1_ITEM *it); + +static const ASN1_PRIMITIVE_FUNCS bignum_pf = { + NULL, 0, + bn_new, + bn_free, + 0, + bn_c2i, + bn_i2c, + NULL /* prim_print */ , +}; + +ASN1_ITEM_start(BIGNUM) + ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &bignum_pf, 0, "BIGNUM" +ASN1_ITEM_end(BIGNUM) + +ASN1_ITEM_start(CBIGNUM) + ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &bignum_pf, BN_SENSITIVE, "BIGNUM" +ASN1_ITEM_end(CBIGNUM) + +static int bn_new(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + *pval = (ASN1_VALUE *)BN_new(); + if (*pval) + return 1; + else + return 0; +} + +static void bn_free(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + if (!*pval) + return; + if (it->size & BN_SENSITIVE) + BN_clear_free((BIGNUM *)*pval); + else + BN_free((BIGNUM *)*pval); + *pval = NULL; +} + +static int bn_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, + const ASN1_ITEM *it) +{ + BIGNUM *bn; + int pad; + if (!*pval) + return -1; + bn = (BIGNUM *)*pval; + /* If MSB set in an octet we need a padding byte */ + if (BN_num_bits(bn) & 0x7) + pad = 0; + else + pad = 1; + if (cont) { + if (pad) + *cont++ = 0; + BN_bn2bin(bn, cont); + } + return pad + BN_num_bytes(bn); +} + +static int bn_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, + int utype, char *free_cont, const ASN1_ITEM *it) +{ + BIGNUM *bn; + if (!*pval) { + if (!bn_new(pval, it)) { + return 0; + } + } + bn = (BIGNUM *)*pval; + if (!BN_bin2bn(cont, len, bn)) { + bn_free(pval, it); + return 0; + } + return 1; +} diff --git a/external/boringssl/crypto/asn1/x_long.c b/external/boringssl/crypto/asn1/x_long.c new file mode 100644 index 0000000000..bc4d27518f --- /dev/null +++ b/external/boringssl/crypto/asn1/x_long.c @@ -0,0 +1,197 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include +#include +#include +#include + +/* + * Custom primitive type for long handling. This converts between an + * ASN1_INTEGER and a long directly. + */ + +static int long_new(ASN1_VALUE **pval, const ASN1_ITEM *it); +static void long_free(ASN1_VALUE **pval, const ASN1_ITEM *it); + +static int long_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, + const ASN1_ITEM *it); +static int long_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, + int utype, char *free_cont, const ASN1_ITEM *it); +static int long_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it, + int indent, const ASN1_PCTX *pctx); + +static const ASN1_PRIMITIVE_FUNCS long_pf = { + NULL, 0, + long_new, + long_free, + long_free, /* Clear should set to initial value */ + long_c2i, + long_i2c, + long_print +}; + +ASN1_ITEM_start(LONG) + ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &long_pf, ASN1_LONG_UNDEF, "LONG" +ASN1_ITEM_end(LONG) + +ASN1_ITEM_start(ZLONG) + ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &long_pf, 0, "ZLONG" +ASN1_ITEM_end(ZLONG) + +static int long_new(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + *(long *)pval = it->size; + return 1; +} + +static void long_free(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + *(long *)pval = it->size; +} + +static int long_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, + const ASN1_ITEM *it) +{ + long ltmp; + unsigned long utmp; + int clen, pad, i; + /* this exists to bypass broken gcc optimization */ + char *cp = (char *)pval; + + /* use memcpy, because we may not be long aligned */ + memcpy(<mp, cp, sizeof(long)); + + if (ltmp == it->size) + return -1; + /* + * Convert the long to positive: we subtract one if negative so we can + * cleanly handle the padding if only the MSB of the leading octet is + * set. + */ + if (ltmp < 0) + utmp = -ltmp - 1; + else + utmp = ltmp; + clen = BN_num_bits_word(utmp); + /* If MSB of leading octet set we need to pad */ + if (!(clen & 0x7)) + pad = 1; + else + pad = 0; + + /* Convert number of bits to number of octets */ + clen = (clen + 7) >> 3; + + if (cont) { + if (pad) + *cont++ = (ltmp < 0) ? 0xff : 0; + for (i = clen - 1; i >= 0; i--) { + cont[i] = (unsigned char)(utmp & 0xff); + if (ltmp < 0) + cont[i] ^= 0xff; + utmp >>= 8; + } + } + return clen + pad; +} + +static int long_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, + int utype, char *free_cont, const ASN1_ITEM *it) +{ + int neg, i; + long ltmp; + unsigned long utmp = 0; + char *cp = (char *)pval; + if (len > (int)sizeof(long)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG); + return 0; + } + /* Is it negative? */ + if (len && (cont[0] & 0x80)) + neg = 1; + else + neg = 0; + utmp = 0; + for (i = 0; i < len; i++) { + utmp <<= 8; + if (neg) + utmp |= cont[i] ^ 0xff; + else + utmp |= cont[i]; + } + ltmp = (long)utmp; + if (neg) { + ltmp++; + ltmp = -ltmp; + } + if (ltmp == it->size) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG); + return 0; + } + memcpy(cp, <mp, sizeof(long)); + return 1; +} + +static int long_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it, + int indent, const ASN1_PCTX *pctx) +{ + return BIO_printf(out, "%ld\n", *(long *)pval); +} diff --git a/external/boringssl/crypto/base64/CMakeLists.txt b/external/boringssl/crypto/base64/CMakeLists.txt new file mode 100644 index 0000000000..affcb48265 --- /dev/null +++ b/external/boringssl/crypto/base64/CMakeLists.txt @@ -0,0 +1,22 @@ +include_directories(../../include) + +add_library( + base64 + + OBJECT + + base64.c +) + +if(ENABLE_TESTS) +add_executable( + base64_test + + base64_test.cc + + $ +) + +target_link_libraries(base64_test crypto) +add_dependencies(all_tests base64_test) +endif() diff --git a/external/boringssl/crypto/base64/base64.c b/external/boringssl/crypto/base64/base64.c new file mode 100644 index 0000000000..0763a3e402 --- /dev/null +++ b/external/boringssl/crypto/base64/base64.c @@ -0,0 +1,438 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include +#include + +#include + + +/* Encoding. */ + +static const unsigned char data_bin2ascii[65] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +#define conv_bin2ascii(a) (data_bin2ascii[(a) & 0x3f]) + +OPENSSL_COMPILE_ASSERT(sizeof(((EVP_ENCODE_CTX *)(NULL))->data) % 3 == 0, + data_length_must_be_multiple_of_base64_chunk_size); + +int EVP_EncodedLength(size_t *out_len, size_t len) { + if (len + 2 < len) { + return 0; + } + len += 2; + len /= 3; + + if (((len << 2) >> 2) != len) { + return 0; + } + len <<= 2; + + if (len + 1 < len) { + return 0; + } + len++; + + *out_len = len; + return 1; +} + +void EVP_EncodeInit(EVP_ENCODE_CTX *ctx) { + memset(ctx, 0, sizeof(EVP_ENCODE_CTX)); +} + +void EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len, + const uint8_t *in, size_t in_len) { + size_t total = 0; + + *out_len = 0; + if (in_len == 0) { + return; + } + + assert(ctx->data_used < sizeof(ctx->data)); + + if (sizeof(ctx->data) - ctx->data_used > in_len) { + memcpy(&ctx->data[ctx->data_used], in, in_len); + ctx->data_used += in_len; + return; + } + + if (ctx->data_used != 0) { + const size_t todo = sizeof(ctx->data) - ctx->data_used; + memcpy(&ctx->data[ctx->data_used], in, todo); + in += todo; + in_len -= todo; + + size_t encoded = EVP_EncodeBlock(out, ctx->data, sizeof(ctx->data)); + ctx->data_used = 0; + + out += encoded; + *(out++) = '\n'; + *out = '\0'; + + total = encoded + 1; + } + + while (in_len >= sizeof(ctx->data)) { + size_t encoded = EVP_EncodeBlock(out, in, sizeof(ctx->data)); + in += sizeof(ctx->data); + in_len -= sizeof(ctx->data); + + out += encoded; + *(out++) = '\n'; + *out = '\0'; + + if (total + encoded + 1 < total) { + *out_len = 0; + return; + } + + total += encoded + 1; + } + + if (in_len != 0) { + memcpy(ctx->data, in, in_len); + } + + ctx->data_used = in_len; + + if (total > INT_MAX) { + /* We cannot signal an error, but we can at least avoid making *out_len + * negative. */ + total = 0; + } + *out_len = total; +} + +void EVP_EncodeFinal(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len) { + if (ctx->data_used == 0) { + *out_len = 0; + return; + } + + size_t encoded = EVP_EncodeBlock(out, ctx->data, ctx->data_used); + out[encoded++] = '\n'; + out[encoded] = '\0'; + ctx->data_used = 0; + *out_len = encoded; +} + +size_t EVP_EncodeBlock(uint8_t *dst, const uint8_t *src, size_t src_len) { + uint32_t l; + size_t remaining = src_len, ret = 0; + + while (remaining) { + if (remaining >= 3) { + l = (((uint32_t)src[0]) << 16L) | (((uint32_t)src[1]) << 8L) | src[2]; + *(dst++) = conv_bin2ascii(l >> 18L); + *(dst++) = conv_bin2ascii(l >> 12L); + *(dst++) = conv_bin2ascii(l >> 6L); + *(dst++) = conv_bin2ascii(l); + remaining -= 3; + } else { + l = ((uint32_t)src[0]) << 16L; + if (remaining == 2) { + l |= ((uint32_t)src[1] << 8L); + } + + *(dst++) = conv_bin2ascii(l >> 18L); + *(dst++) = conv_bin2ascii(l >> 12L); + *(dst++) = (remaining == 1) ? '=' : conv_bin2ascii(l >> 6L); + *(dst++) = '='; + remaining = 0; + } + ret += 4; + src += 3; + } + + *dst = '\0'; + return ret; +} + + +/* Decoding. */ + +int EVP_DecodedLength(size_t *out_len, size_t len) { + if (len % 4 != 0) { + return 0; + } + + *out_len = (len / 4) * 3; + return 1; +} + +void EVP_DecodeInit(EVP_ENCODE_CTX *ctx) { + memset(ctx, 0, sizeof(EVP_ENCODE_CTX)); +} + +/* kBase64ASCIIToBinData maps characters (c < 128) to their base64 value, or + * else 0xff if they are invalid. As a special case, the padding character + * ('=') is mapped to zero. */ +static const uint8_t kBase64ASCIIToBinData[128] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f, + 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff, 0xff, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, + 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, + 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, + 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, + 0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, +}; + +static uint8_t base64_ascii_to_bin(uint8_t a) { + if (a >= 128) { + return 0xFF; + } + + return kBase64ASCIIToBinData[a]; +} + +/* base64_decode_quad decodes a single “quad†(i.e. four characters) of base64 + * data and writes up to three bytes to |out|. It sets |*out_num_bytes| to the + * number of bytes written, which will be less than three if the quad ended + * with padding. It returns one on success or zero on error. */ +static int base64_decode_quad(uint8_t *out, size_t *out_num_bytes, + const uint8_t *in) { + const uint8_t a = base64_ascii_to_bin(in[0]); + const uint8_t b = base64_ascii_to_bin(in[1]); + const uint8_t c = base64_ascii_to_bin(in[2]); + const uint8_t d = base64_ascii_to_bin(in[3]); + if (a == 0xff || b == 0xff || c == 0xff || d == 0xff) { + return 0; + } + + const uint32_t v = ((uint32_t)a) << 18 | ((uint32_t)b) << 12 | + ((uint32_t)c) << 6 | (uint32_t)d; + + const unsigned padding_pattern = (in[0] == '=') << 3 | + (in[1] == '=') << 2 | + (in[2] == '=') << 1 | + (in[3] == '='); + + switch (padding_pattern) { + case 0: + /* The common case of no padding. */ + *out_num_bytes = 3; + out[0] = v >> 16; + out[1] = v >> 8; + out[2] = v; + break; + + case 1: /* xxx= */ + *out_num_bytes = 2; + out[0] = v >> 16; + out[1] = v >> 8; + break; + + case 3: /* xx== */ + *out_num_bytes = 1; + out[0] = v >> 16; + break; + + default: + return 0; + } + + return 1; +} + +int EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len, + const uint8_t *in, size_t in_len) { + *out_len = 0; + + if (ctx->error_encountered) { + return -1; + } + + size_t bytes_out = 0, i; + for (i = 0; i < in_len; i++) { + const char c = in[i]; + switch (c) { + case ' ': + case '\t': + case '\r': + case '\n': + continue; + } + + if (base64_ascii_to_bin(c) == 0xff || ctx->eof_seen) { + ctx->error_encountered = 1; + return -1; + } + + ctx->data[ctx->data_used++] = c; + if (ctx->data_used == 4) { + size_t num_bytes_resulting; + if (!base64_decode_quad(out, &num_bytes_resulting, ctx->data)) { + ctx->error_encountered = 1; + return -1; + } + + ctx->data_used = 0; + bytes_out += num_bytes_resulting; + out += num_bytes_resulting; + + if (num_bytes_resulting < 3) { + ctx->eof_seen = 1; + } + } + } + + if (bytes_out > INT_MAX) { + ctx->error_encountered = 1; + *out_len = 0; + return -1; + } + *out_len = bytes_out; + + if (ctx->eof_seen) { + return 0; + } + + return 1; +} + +int EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len) { + *out_len = 0; + if (ctx->error_encountered || ctx->data_used != 0) { + return -1; + } + + return 1; +} + +int EVP_DecodeBase64(uint8_t *out, size_t *out_len, size_t max_out, + const uint8_t *in, size_t in_len) { + *out_len = 0; + + if (in_len % 4 != 0) { + return 0; + } + + size_t max_len; + if (!EVP_DecodedLength(&max_len, in_len) || + max_out < max_len) { + return 0; + } + + size_t i, bytes_out = 0; + for (i = 0; i < in_len; i += 4) { + size_t num_bytes_resulting; + + if (!base64_decode_quad(out, &num_bytes_resulting, &in[i])) { + return 0; + } + + bytes_out += num_bytes_resulting; + out += num_bytes_resulting; + if (num_bytes_resulting != 3 && i != in_len - 4) { + return 0; + } + } + + *out_len = bytes_out; + return 1; +} + +int EVP_DecodeBlock(uint8_t *dst, const uint8_t *src, size_t src_len) { + /* Trim spaces and tabs from the beginning of the input. */ + while (src_len > 0) { + if (src[0] != ' ' && src[0] != '\t') { + break; + } + + src++; + src_len--; + } + + /* Trim newlines, spaces and tabs from the end of the line. */ + while (src_len > 0) { + switch (src[src_len-1]) { + case ' ': + case '\t': + case '\r': + case '\n': + src_len--; + continue; + } + + break; + } + + size_t dst_len; + if (!EVP_DecodedLength(&dst_len, src_len) || + dst_len > INT_MAX || + !EVP_DecodeBase64(dst, &dst_len, dst_len, src, src_len)) { + return -1; + } + + /* EVP_DecodeBlock does not take padding into account, so put the + * NULs back in... so the caller can strip them back out. */ + while (dst_len % 3 != 0) { + dst[dst_len++] = '\0'; + } + assert(dst_len <= INT_MAX); + + return dst_len; +} diff --git a/external/boringssl/crypto/base64/base64_test.cc b/external/boringssl/crypto/base64/base64_test.cc new file mode 100644 index 0000000000..a608773213 --- /dev/null +++ b/external/boringssl/crypto/base64/base64_test.cc @@ -0,0 +1,393 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include + +#include +#include + +#include +#include +#include + + +enum encoding_relation { + // canonical indicates that the encoding is the expected encoding of the + // input. + canonical, + // valid indicates that the encoding is /a/ valid encoding of the input, but + // need not be the canonical one. + valid, + // invalid indicates that the encoded data is valid. + invalid, +}; + +struct TestVector { + enum encoding_relation relation; + const char *decoded; + const char *encoded; +}; + +// Test vectors from RFC 4648. +static const TestVector kTestVectors[] = { + {canonical, "", ""}, + {canonical, "f", "Zg==\n"}, + {canonical, "fo", "Zm8=\n"}, + {canonical, "foo", "Zm9v\n"}, + {canonical, "foob", "Zm9vYg==\n"}, + {canonical, "fooba", "Zm9vYmE=\n"}, + {canonical, "foobar", "Zm9vYmFy\n"}, + {valid, "foobar", "Zm9vYmFy\n\n"}, + {valid, "foobar", " Zm9vYmFy\n\n"}, + {valid, "foobar", " Z m 9 v Y m F y\n\n"}, + {invalid, "", "Zm9vYmFy=\n"}, + {invalid, "", "Zm9vYmFy==\n"}, + {invalid, "", "Zm9vYmFy===\n"}, + {invalid, "", "Z"}, + {invalid, "", "Z\n"}, + {invalid, "", "ab!c"}, + {invalid, "", "ab=c"}, + {invalid, "", "abc"}, + + {canonical, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", + "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eA==\n"}, + {valid, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", + "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eA\n==\n"}, + {valid, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", + "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eA=\n=\n"}, + {invalid, "", + "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eA=\n==\n"}, + {canonical, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", + "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4\neHh4eHh" + "4eHh4eHh4\n"}, + {canonical, + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", + "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4\neHh4eHh" + "4eHh4eHh4eHh4eA==\n"}, + {valid, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", + "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh\n4eHh4eHh" + "4eHh4eHh4eHh4eA==\n"}, + {valid, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", + "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4e" + "Hh4eHh4eHh4eA==\n"}, + {invalid, "", + "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eA==" + "\neHh4eHh4eHh4eHh4eHh4eHh4\n"}, + + // A '-' has traditionally been treated as the end of the data by OpenSSL + // and anything following would be ignored. BoringSSL does not accept this + // non-standard extension. + {invalid, "", "Zm9vYmFy-anythinggoes"}, + {invalid, "", "Zm9vYmFy\n-anythinggoes"}, + + // CVE-2015-0292 + {invalid, "", + "ZW5jb2RlIG1lCg===========================================================" + "=======\n"}, +}; + +static const size_t kNumTests = sizeof(kTestVectors) / sizeof(kTestVectors[0]); + +// RemoveNewlines returns a copy of |in| with all '\n' characters removed. +static std::string RemoveNewlines(const char *in) { + std::string ret; + const size_t in_len = strlen(in); + + size_t i; + for (i = 0; i < in_len; i++) { + if (in[i] != '\n') { + ret.push_back(in[i]); + } + } + + return ret; +} + +static bool TestEncodeBlock() { + for (unsigned i = 0; i < kNumTests; i++) { + const TestVector *t = &kTestVectors[i]; + if (t->relation != canonical) { + continue; + } + + const size_t decoded_len = strlen(t->decoded); + size_t max_encoded_len; + if (!EVP_EncodedLength(&max_encoded_len, decoded_len)) { + fprintf(stderr, "#%u: EVP_EncodedLength failed\n", i); + return false; + } + + std::vector out_vec(max_encoded_len); + uint8_t *out = out_vec.data(); + size_t len = EVP_EncodeBlock(out, (const uint8_t *)t->decoded, decoded_len); + + std::string encoded(RemoveNewlines(t->encoded)); + if (len != encoded.size() || + memcmp(out, encoded.data(), len) != 0) { + fprintf(stderr, "encode(\"%s\") = \"%.*s\", want \"%s\"\n", + t->decoded, (int)len, (const char*)out, encoded.c_str()); + return false; + } + } + + return true; +} + +static bool TestDecodeBase64() { + size_t len; + + for (unsigned i = 0; i < kNumTests; i++) { + const TestVector *t = &kTestVectors[i]; + + if (t->relation == valid) { + // The non-canonical encodings will generally have odd whitespace etc + // that |EVP_DecodeBase64| will reject. + continue; + } + + const std::string encoded(RemoveNewlines(t->encoded)); + std::vector out_vec(encoded.size()); + uint8_t *out = out_vec.data(); + + int ok = EVP_DecodeBase64(out, &len, out_vec.size(), + (const uint8_t *)encoded.data(), encoded.size()); + + if (t->relation == invalid) { + if (ok) { + fprintf(stderr, "decode(\"%s\") didn't fail but should have\n", + encoded.c_str()); + return false; + } + } else if (t->relation == canonical) { + if (!ok) { + fprintf(stderr, "decode(\"%s\") failed\n", encoded.c_str()); + return false; + } + + if (len != strlen(t->decoded) || + memcmp(out, t->decoded, len) != 0) { + fprintf(stderr, "decode(\"%s\") = \"%.*s\", want \"%s\"\n", + encoded.c_str(), (int)len, (const char*)out, t->decoded); + return false; + } + } + } + + return true; +} + +static bool TestDecodeBlock() { + for (unsigned i = 0; i < kNumTests; i++) { + const TestVector *t = &kTestVectors[i]; + if (t->relation != canonical) { + continue; + } + + std::string encoded(RemoveNewlines(t->encoded)); + + std::vector out_vec(encoded.size()); + uint8_t *out = out_vec.data(); + + // Test that the padding behavior of the deprecated API is preserved. + int ret = + EVP_DecodeBlock(out, (const uint8_t *)encoded.data(), encoded.size()); + if (ret < 0) { + fprintf(stderr, "EVP_DecodeBlock(\"%s\") failed\n", t->encoded); + return false; + } + if (ret % 3 != 0) { + fprintf(stderr, "EVP_DecodeBlock did not ignore padding\n"); + return false; + } + size_t expected_len = strlen(t->decoded); + if (expected_len % 3 != 0) { + ret -= 3 - (expected_len % 3); + } + if (static_cast(ret) != strlen(t->decoded) || + memcmp(out, t->decoded, ret) != 0) { + fprintf(stderr, "decode(\"%s\") = \"%.*s\", want \"%s\"\n", + t->encoded, ret, (const char*)out, t->decoded); + return false; + } + } + + return true; +} + +static bool TestEncodeDecode() { + for (unsigned test_num = 0; test_num < kNumTests; test_num++) { + const TestVector *t = &kTestVectors[test_num]; + + EVP_ENCODE_CTX ctx; + const size_t decoded_len = strlen(t->decoded); + + if (t->relation == canonical) { + size_t max_encoded_len; + if (!EVP_EncodedLength(&max_encoded_len, decoded_len)) { + fprintf(stderr, "#%u: EVP_EncodedLength failed\n", test_num); + return false; + } + + // EVP_EncodeUpdate will output new lines every 64 bytes of output so we + // need slightly more than |EVP_EncodedLength| returns. */ + max_encoded_len += (max_encoded_len + 63) >> 6; + std::vector out_vec(max_encoded_len); + uint8_t *out = out_vec.data(); + + EVP_EncodeInit(&ctx); + + int out_len; + EVP_EncodeUpdate(&ctx, out, &out_len, + reinterpret_cast(t->decoded), + decoded_len); + size_t total = out_len; + + EVP_EncodeFinal(&ctx, out + total, &out_len); + total += out_len; + + if (total != strlen(t->encoded) || memcmp(out, t->encoded, total) != 0) { + fprintf(stderr, "#%u: EVP_EncodeUpdate produced different output: '%s' (%u)\n", + test_num, out, static_cast(total)); + return false; + } + } + + std::vector out_vec(strlen(t->encoded)); + uint8_t *out = out_vec.data(); + + EVP_DecodeInit(&ctx); + int out_len; + size_t total = 0; + int ret = EVP_DecodeUpdate(&ctx, out, &out_len, + reinterpret_cast(t->encoded), + strlen(t->encoded)); + if (ret != -1) { + total = out_len; + ret = EVP_DecodeFinal(&ctx, out + total, &out_len); + total += out_len; + } + + switch (t->relation) { + case canonical: + case valid: + if (ret == -1) { + fprintf(stderr, "#%u: EVP_DecodeUpdate failed\n", test_num); + return false; + } + if (total != decoded_len || memcmp(out, t->decoded, decoded_len)) { + fprintf(stderr, "#%u: EVP_DecodeUpdate produced incorrect output\n", + test_num); + return false; + } + break; + + case invalid: + if (ret != -1) { + fprintf(stderr, "#%u: EVP_DecodeUpdate was successful but shouldn't have been\n", test_num); + return false; + } + break; + } + } + + return true; +} + +static bool TestDecodeUpdateStreaming() { + for (unsigned test_num = 0; test_num < kNumTests; test_num++) { + const TestVector *t = &kTestVectors[test_num]; + if (t->relation == invalid) { + continue; + } + + const size_t encoded_len = strlen(t->encoded); + + std::vector out(encoded_len); + + for (size_t chunk_size = 1; chunk_size <= encoded_len; chunk_size++) { + size_t out_len = 0; + EVP_ENCODE_CTX ctx; + EVP_DecodeInit(&ctx); + + for (size_t i = 0; i < encoded_len;) { + size_t todo = encoded_len - i; + if (todo > chunk_size) { + todo = chunk_size; + } + + int bytes_written; + int ret = EVP_DecodeUpdate( + &ctx, out.data() + out_len, &bytes_written, + reinterpret_cast(t->encoded + i), todo); + i += todo; + + switch (ret) { + case -1: + fprintf(stderr, "#%u: EVP_DecodeUpdate returned error\n", test_num); + return 0; + case 0: + out_len += bytes_written; + if (i == encoded_len || + (i + 1 == encoded_len && t->encoded[i] == '\n') || + /* If there was an '-' in the input (which means “EOFâ€) then + * this loop will continue to test that |EVP_DecodeUpdate| will + * ignore the remainder of the input. */ + strchr(t->encoded, '-') != nullptr) { + break; + } + + fprintf(stderr, + "#%u: EVP_DecodeUpdate returned zero before end of " + "encoded data\n", + test_num); + return 0; + default: + out_len += bytes_written; + } + } + + int bytes_written; + int ret = EVP_DecodeFinal(&ctx, out.data() + out_len, &bytes_written); + if (ret == -1) { + fprintf(stderr, "#%u: EVP_DecodeFinal returned error\n", test_num); + return 0; + } + out_len += bytes_written; + + if (out_len != strlen(t->decoded) || + memcmp(out.data(), t->decoded, out_len) != 0) { + fprintf(stderr, "#%u: incorrect output\n", test_num); + return 0; + } + } + } + + return true; +} + +int main(void) { + CRYPTO_library_init(); + + if (!TestEncodeBlock() || + !TestDecodeBase64() || + !TestDecodeBlock() || + !TestDecodeUpdateStreaming() || + !TestEncodeDecode()) { + return 1; + } + + printf("PASS\n"); + return 0; +} diff --git a/external/boringssl/crypto/bio/CMakeLists.txt b/external/boringssl/crypto/bio/CMakeLists.txt new file mode 100644 index 0000000000..c5766dddc3 --- /dev/null +++ b/external/boringssl/crypto/bio/CMakeLists.txt @@ -0,0 +1,35 @@ +include_directories(../../include) + +add_library( + bio + + OBJECT + + bio.c + bio_mem.c + buffer.c + connect.c + fd.c + file.c + hexdump.c + pair.c + printf.c + socket.c + socket_helper.c +) + +if(ENABLE_TESTS) +add_executable( + bio_test + + bio_test.cc + + $ +) + +target_link_libraries(bio_test crypto) +if (WIN32) + target_link_libraries(bio_test ws2_32) +endif() +add_dependencies(all_tests bio_test) +endif() diff --git a/external/boringssl/crypto/bio/bio.c b/external/boringssl/crypto/bio/bio.c new file mode 100644 index 0000000000..7a1a9e3b9e --- /dev/null +++ b/external/boringssl/crypto/bio/bio.c @@ -0,0 +1,608 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include "../internal.h" + + +/* BIO_set initialises a BIO structure to have the given type and sets the + * reference count to one. It returns one on success or zero on error. */ +static int bio_set(BIO *bio, const BIO_METHOD *method) { + /* This function can be called with a stack allocated |BIO| so we have to + * assume that the contents of |BIO| are arbitary. This also means that it'll + * leak memory if you call |BIO_set| twice on the same BIO. */ + memset(bio, 0, sizeof(BIO)); + + bio->method = method; + bio->shutdown = 1; + bio->references = 1; + + if (method->create != NULL && !method->create(bio)) { + return 0; + } + + return 1; +} + +BIO *BIO_new(const BIO_METHOD *method) { + BIO *ret = OPENSSL_malloc(sizeof(BIO)); + if (ret == NULL) { + OPENSSL_PUT_ERROR(BIO, ERR_R_MALLOC_FAILURE); + return NULL; + } + + if (!bio_set(ret, method)) { + OPENSSL_free(ret); + ret = NULL; + } + + return ret; +} + +int BIO_free(BIO *bio) { + BIO *next_bio; + + for (; bio != NULL; bio = next_bio) { + if (!CRYPTO_refcount_dec_and_test_zero(&bio->references)) { + return 0; + } + + if (bio->callback != NULL) { + int i = (int)bio->callback(bio, BIO_CB_FREE, NULL, 0, 0, 1); + if (i <= 0) { + return i; + } + } + + next_bio = BIO_pop(bio); + + if (bio->method != NULL && bio->method->destroy != NULL) { + bio->method->destroy(bio); + } + + OPENSSL_free(bio); + } + return 1; +} + +BIO *BIO_up_ref(BIO *bio) { + CRYPTO_refcount_inc(&bio->references); + return bio; +} + +void BIO_vfree(BIO *bio) { + BIO_free(bio); +} + +void BIO_free_all(BIO *bio) { + BIO_free(bio); +} + +static int bio_io(BIO *bio, void *buf, int len, size_t method_offset, + int callback_flags, size_t *num) { + int i; + typedef int (*io_func_t)(BIO *, char *, int); + io_func_t io_func = NULL; + + if (bio != NULL && bio->method != NULL) { + io_func = + *((const io_func_t *)(((const uint8_t *)bio->method) + method_offset)); + } + + if (io_func == NULL) { + OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD); + return -2; + } + + if (bio->callback != NULL) { + i = (int) bio->callback(bio, callback_flags, buf, len, 0L, 1L); + if (i <= 0) { + return i; + } + } + + if (!bio->init) { + OPENSSL_PUT_ERROR(BIO, BIO_R_UNINITIALIZED); + return -2; + } + + i = 0; + if (buf != NULL && len > 0) { + i = io_func(bio, buf, len); + } + + if (i > 0) { + *num += i; + } + + if (bio->callback != NULL) { + i = (int)(bio->callback(bio, callback_flags | BIO_CB_RETURN, buf, len, 0L, + (long)i)); + } + + return i; +} + +int BIO_read(BIO *bio, void *buf, int len) { + return bio_io(bio, buf, len, offsetof(BIO_METHOD, bread), BIO_CB_READ, + &bio->num_read); +} + +int BIO_gets(BIO *bio, char *buf, int len) { + return bio_io(bio, buf, len, offsetof(BIO_METHOD, bgets), BIO_CB_GETS, + &bio->num_read); +} + +int BIO_write(BIO *bio, const void *in, int inl) { + return bio_io(bio, (char *)in, inl, offsetof(BIO_METHOD, bwrite), + BIO_CB_WRITE, &bio->num_write); +} + +int BIO_puts(BIO *bio, const char *in) { + return BIO_write(bio, in, strlen(in)); +} + +int BIO_flush(BIO *bio) { + return BIO_ctrl(bio, BIO_CTRL_FLUSH, 0, NULL); +} + +long BIO_ctrl(BIO *bio, int cmd, long larg, void *parg) { + long ret; + + if (bio == NULL) { + return 0; + } + + if (bio->method == NULL || bio->method->ctrl == NULL) { + OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD); + return -2; + } + + if (bio->callback != NULL) { + ret = bio->callback(bio, BIO_CB_CTRL, parg, cmd, larg, 1); + if (ret <= 0) { + return ret; + } + } + + ret = bio->method->ctrl(bio, cmd, larg, parg); + + if (bio->callback != NULL) { + ret = bio->callback(bio, BIO_CB_CTRL | BIO_CB_RETURN, parg, cmd, larg, ret); + } + + return ret; +} + +char *BIO_ptr_ctrl(BIO *b, int cmd, long larg) { + char *p = NULL; + + if (BIO_ctrl(b, cmd, larg, (void *)&p) <= 0) { + return NULL; + } + + return p; +} + +long BIO_int_ctrl(BIO *b, int cmd, long larg, int iarg) { + int i = iarg; + + return BIO_ctrl(b, cmd, larg, (void *)&i); +} + +int BIO_reset(BIO *bio) { + return BIO_ctrl(bio, BIO_CTRL_RESET, 0, NULL); +} + +void BIO_set_flags(BIO *bio, int flags) { + bio->flags |= flags; +} + +int BIO_test_flags(const BIO *bio, int flags) { + return bio->flags & flags; +} + +int BIO_should_read(const BIO *bio) { + return BIO_test_flags(bio, BIO_FLAGS_READ); +} + +int BIO_should_write(const BIO *bio) { + return BIO_test_flags(bio, BIO_FLAGS_WRITE); +} + +int BIO_should_retry(const BIO *bio) { + return BIO_test_flags(bio, BIO_FLAGS_SHOULD_RETRY); +} + +int BIO_should_io_special(const BIO *bio) { + return BIO_test_flags(bio, BIO_FLAGS_IO_SPECIAL); +} + +int BIO_get_retry_reason(const BIO *bio) { return bio->retry_reason; } + +void BIO_clear_flags(BIO *bio, int flags) { + bio->flags &= ~flags; +} + +void BIO_set_retry_read(BIO *bio) { + bio->flags |= BIO_FLAGS_READ | BIO_FLAGS_SHOULD_RETRY; +} + +void BIO_set_retry_write(BIO *bio) { + bio->flags |= BIO_FLAGS_WRITE | BIO_FLAGS_SHOULD_RETRY; +} + +static const int kRetryFlags = BIO_FLAGS_RWS | BIO_FLAGS_SHOULD_RETRY; + +int BIO_get_retry_flags(BIO *bio) { + return bio->flags & kRetryFlags; +} + +void BIO_clear_retry_flags(BIO *bio) { + bio->flags &= ~kRetryFlags; + bio->retry_reason = 0; +} + +int BIO_method_type(const BIO *bio) { return bio->method->type; } + +void BIO_copy_next_retry(BIO *bio) { + BIO_clear_retry_flags(bio); + BIO_set_flags(bio, BIO_get_retry_flags(bio->next_bio)); + bio->retry_reason = bio->next_bio->retry_reason; +} + +long BIO_callback_ctrl(BIO *bio, int cmd, bio_info_cb fp) { + long ret; + bio_info_cb cb; + + if (bio == NULL) { + return 0; + } + + if (bio->method == NULL || bio->method->callback_ctrl == NULL) { + OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD); + return 0; + } + + cb = bio->callback; + + if (cb != NULL) { + ret = cb(bio, BIO_CB_CTRL, (void *)&fp, cmd, 0, 1L); + if (ret <= 0) { + return ret; + } + } + + ret = bio->method->callback_ctrl(bio, cmd, fp); + + if (cb != NULL) { + ret = cb(bio, BIO_CB_CTRL | BIO_CB_RETURN, (void *)&fp, cmd, 0, ret); + } + + return ret; +} + +size_t BIO_pending(const BIO *bio) { + return BIO_ctrl((BIO *) bio, BIO_CTRL_PENDING, 0, NULL); +} + +size_t BIO_ctrl_pending(const BIO *bio) { + return BIO_pending(bio); +} + +size_t BIO_wpending(const BIO *bio) { + return BIO_ctrl((BIO *) bio, BIO_CTRL_WPENDING, 0, NULL); +} + +int BIO_set_close(BIO *bio, int close_flag) { + return BIO_ctrl(bio, BIO_CTRL_SET_CLOSE, close_flag, NULL); +} + +void BIO_set_callback(BIO *bio, bio_info_cb callback_func) { + bio->callback = callback_func; +} + +void BIO_set_callback_arg(BIO *bio, char *arg) { + bio->cb_arg = arg; +} + +char *BIO_get_callback_arg(const BIO *bio) { + return bio->cb_arg; +} + +OPENSSL_EXPORT size_t BIO_number_read(const BIO *bio) { + return bio->num_read; +} + +OPENSSL_EXPORT size_t BIO_number_written(const BIO *bio) { + return bio->num_write; +} + +BIO *BIO_push(BIO *bio, BIO *appended_bio) { + BIO *last_bio; + + if (bio == NULL) { + return bio; + } + + last_bio = bio; + while (last_bio->next_bio != NULL) { + last_bio = last_bio->next_bio; + } + + last_bio->next_bio = appended_bio; + return bio; +} + +BIO *BIO_pop(BIO *bio) { + BIO *ret; + + if (bio == NULL) { + return NULL; + } + ret = bio->next_bio; + bio->next_bio = NULL; + return ret; +} + +BIO *BIO_next(BIO *bio) { + if (!bio) { + return NULL; + } + return bio->next_bio; +} + +BIO *BIO_find_type(BIO *bio, int type) { + int method_type, mask; + + if (!bio) { + return NULL; + } + mask = type & 0xff; + + do { + if (bio->method != NULL) { + method_type = bio->method->type; + + if (!mask) { + if (method_type & type) { + return bio; + } + } else if (method_type == type) { + return bio; + } + } + bio = bio->next_bio; + } while (bio != NULL); + + return NULL; +} + +int BIO_indent(BIO *bio, unsigned indent, unsigned max_indent) { + if (indent > max_indent) { + indent = max_indent; + } + + while (indent--) { + if (BIO_puts(bio, " ") != 1) { + return 0; + } + } + return 1; +} + +static int print_bio(const char *str, size_t len, void *bio) { + return BIO_write((BIO *)bio, str, len); +} + +void BIO_print_errors(BIO *bio) { + ERR_print_errors_cb(print_bio, bio); +} + +void ERR_print_errors(BIO *bio) { + BIO_print_errors(bio); +} + +/* bio_read_all reads everything from |bio| and prepends |prefix| to it. On + * success, |*out| is set to an allocated buffer (which should be freed with + * |OPENSSL_free|), |*out_len| is set to its length and one is returned. The + * buffer will contain |prefix| followed by the contents of |bio|. On failure, + * zero is returned. + * + * The function will fail if the size of the output would equal or exceed + * |max_len|. */ +static int bio_read_all(BIO *bio, uint8_t **out, size_t *out_len, + const uint8_t *prefix, size_t prefix_len, + size_t max_len) { + static const size_t kChunkSize = 4096; + + size_t len = prefix_len + kChunkSize; + if (len > max_len) { + len = max_len; + } + if (len < prefix_len) { + return 0; + } + *out = OPENSSL_malloc(len); + if (*out == NULL) { + return 0; + } + memcpy(*out, prefix, prefix_len); + size_t done = prefix_len; + + for (;;) { + if (done == len) { + OPENSSL_free(*out); + return 0; + } + const size_t todo = len - done; + assert(todo < INT_MAX); + const int n = BIO_read(bio, *out + done, todo); + if (n == 0) { + *out_len = done; + return 1; + } else if (n == -1) { + OPENSSL_free(*out); + return 0; + } + + done += n; + if (len < max_len && len - done < kChunkSize / 2) { + len += kChunkSize; + if (len < kChunkSize || len > max_len) { + len = max_len; + } + uint8_t *new_buf = OPENSSL_realloc(*out, len); + if (new_buf == NULL) { + OPENSSL_free(*out); + return 0; + } + *out = new_buf; + } + } +} + +int BIO_read_asn1(BIO *bio, uint8_t **out, size_t *out_len, size_t max_len) { + uint8_t header[6]; + + static const size_t kInitialHeaderLen = 2; + if (BIO_read(bio, header, kInitialHeaderLen) != (int) kInitialHeaderLen) { + return 0; + } + + const uint8_t tag = header[0]; + const uint8_t length_byte = header[1]; + + if ((tag & 0x1f) == 0x1f) { + /* Long form tags are not supported. */ + return 0; + } + + size_t len, header_len; + if ((length_byte & 0x80) == 0) { + /* Short form length. */ + len = length_byte; + header_len = kInitialHeaderLen; + } else { + const size_t num_bytes = length_byte & 0x7f; + + if ((tag & 0x20 /* constructed */) != 0 && num_bytes == 0) { + /* indefinite length. */ + return bio_read_all(bio, out, out_len, header, kInitialHeaderLen, + max_len); + } + + if (num_bytes == 0 || num_bytes > 4) { + return 0; + } + + if (BIO_read(bio, header + kInitialHeaderLen, num_bytes) != + (int)num_bytes) { + return 0; + } + header_len = kInitialHeaderLen + num_bytes; + + uint32_t len32 = 0; + unsigned i; + for (i = 0; i < num_bytes; i++) { + len32 <<= 8; + len32 |= header[kInitialHeaderLen + i]; + } + + if (len32 < 128) { + /* Length should have used short-form encoding. */ + return 0; + } + + if ((len32 >> ((num_bytes-1)*8)) == 0) { + /* Length should have been at least one byte shorter. */ + return 0; + } + + len = len32; + } + + if (len + header_len < len || + len + header_len > max_len || + len > INT_MAX) { + return 0; + } + len += header_len; + *out_len = len; + + *out = OPENSSL_malloc(len); + if (*out == NULL) { + return 0; + } + memcpy(*out, header, header_len); + if (BIO_read(bio, (*out) + header_len, len - header_len) != + (int) (len - header_len)) { + OPENSSL_free(*out); + return 0; + } + + return 1; +} diff --git a/external/boringssl/crypto/bio/bio_mem.c b/external/boringssl/crypto/bio/bio_mem.c new file mode 100644 index 0000000000..844fba7e3e --- /dev/null +++ b/external/boringssl/crypto/bio/bio_mem.c @@ -0,0 +1,328 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +#include +#include +#include + + +BIO *BIO_new_mem_buf(const void *buf, int len) { + BIO *ret; + BUF_MEM *b; + const size_t size = len < 0 ? strlen((char *)buf) : (size_t)len; + + if (!buf && len != 0) { + OPENSSL_PUT_ERROR(BIO, BIO_R_NULL_PARAMETER); + return NULL; + } + + ret = BIO_new(BIO_s_mem()); + if (ret == NULL) { + return NULL; + } + + b = (BUF_MEM *)ret->ptr; + /* BIO_FLAGS_MEM_RDONLY ensures |b->data| is not written to. */ + b->data = (void *)buf; + b->length = size; + b->max = size; + + ret->flags |= BIO_FLAGS_MEM_RDONLY; + + /* |num| is used to store the value that this BIO will return when it runs + * out of data. If it's negative then the retry flags will also be set. Since + * this is static data, retrying wont help */ + ret->num = 0; + + return ret; +} + +static int mem_new(BIO *bio) { + BUF_MEM *b; + + b = BUF_MEM_new(); + if (b == NULL) { + return 0; + } + + /* |shutdown| is used to store the close flag: whether the BIO has ownership + * of the BUF_MEM. */ + bio->shutdown = 1; + bio->init = 1; + bio->num = -1; + bio->ptr = (char *)b; + + return 1; +} + +static int mem_free(BIO *bio) { + BUF_MEM *b; + + if (bio == NULL) { + return 0; + } + + if (!bio->shutdown || !bio->init || bio->ptr == NULL) { + return 1; + } + + b = (BUF_MEM *)bio->ptr; + if (bio->flags & BIO_FLAGS_MEM_RDONLY) { + b->data = NULL; + } + BUF_MEM_free(b); + bio->ptr = NULL; + return 1; +} + +static int mem_read(BIO *bio, char *out, int outl) { + int ret; + BUF_MEM *b = (BUF_MEM*) bio->ptr; + + BIO_clear_retry_flags(bio); + ret = outl; + if (b->length < INT_MAX && ret > (int)b->length) { + ret = b->length; + } + + if (ret > 0) { + memcpy(out, b->data, ret); + b->length -= ret; + if (bio->flags & BIO_FLAGS_MEM_RDONLY) { + b->data += ret; + } else { + memmove(b->data, &b->data[ret], b->length); + } + } else if (b->length == 0) { + ret = bio->num; + if (ret != 0) { + BIO_set_retry_read(bio); + } + } + return ret; +} + +static int mem_write(BIO *bio, const char *in, int inl) { + int ret = -1; + int blen; + BUF_MEM *b; + + b = (BUF_MEM *)bio->ptr; + + if (bio->flags & BIO_FLAGS_MEM_RDONLY) { + OPENSSL_PUT_ERROR(BIO, BIO_R_WRITE_TO_READ_ONLY_BIO); + goto err; + } + + BIO_clear_retry_flags(bio); + blen = b->length; + if (INT_MAX - blen < inl) { + goto err; + } + if (BUF_MEM_grow_clean(b, blen + inl) != ((size_t) blen) + inl) { + goto err; + } + memcpy(&b->data[blen], in, inl); + ret = inl; + +err: + return ret; +} + +static int mem_puts(BIO *bp, const char *str) { + return mem_write(bp, str, strlen(str)); +} + +static int mem_gets(BIO *bio, char *buf, int size) { + int i, j; + char *p; + BUF_MEM *b = (BUF_MEM *)bio->ptr; + + BIO_clear_retry_flags(bio); + j = b->length; + if (size - 1 < j) { + j = size - 1; + } + if (j <= 0) { + if (size > 0) { + *buf = 0; + } + return 0; + } + + p = b->data; + for (i = 0; i < j; i++) { + if (p[i] == '\n') { + i++; + break; + } + } + + /* i is now the max num of bytes to copy, either j or up to and including the + * first newline */ + + i = mem_read(bio, buf, i); + if (i > 0) { + buf[i] = '\0'; + } + return i; +} + +static long mem_ctrl(BIO *bio, int cmd, long num, void *ptr) { + long ret = 1; + char **pptr; + + BUF_MEM *b = (BUF_MEM *)bio->ptr; + + switch (cmd) { + case BIO_CTRL_RESET: + if (b->data != NULL) { + /* For read only case reset to the start again */ + if (bio->flags & BIO_FLAGS_MEM_RDONLY) { + b->data -= b->max - b->length; + b->length = b->max; + } else { + memset(b->data, 0, b->max); + b->length = 0; + } + } + break; + case BIO_CTRL_EOF: + ret = (long)(b->length == 0); + break; + case BIO_C_SET_BUF_MEM_EOF_RETURN: + bio->num = (int)num; + break; + case BIO_CTRL_INFO: + ret = (long)b->length; + if (ptr != NULL) { + pptr = (char **)ptr; + *pptr = (char *)&b->data[0]; + } + break; + case BIO_C_SET_BUF_MEM: + mem_free(bio); + bio->shutdown = (int)num; + bio->ptr = ptr; + break; + case BIO_C_GET_BUF_MEM_PTR: + if (ptr != NULL) { + pptr = (char **)ptr; + *pptr = (char *)b; + } + break; + case BIO_CTRL_GET_CLOSE: + ret = (long)bio->shutdown; + break; + case BIO_CTRL_SET_CLOSE: + bio->shutdown = (int)num; + break; + + case BIO_CTRL_WPENDING: + ret = 0L; + break; + case BIO_CTRL_PENDING: + ret = (long)b->length; + break; + case BIO_CTRL_FLUSH: + ret = 1; + break; + default: + ret = 0; + break; + } + return ret; +} + +static const BIO_METHOD mem_method = { + BIO_TYPE_MEM, "memory buffer", mem_write, mem_read, mem_puts, + mem_gets, mem_ctrl, mem_new, mem_free, NULL, }; + +const BIO_METHOD *BIO_s_mem(void) { return &mem_method; } + +int BIO_mem_contents(const BIO *bio, const uint8_t **out_contents, + size_t *out_len) { + const BUF_MEM *b; + if (bio->method != &mem_method) { + return 0; + } + + b = (BUF_MEM *)bio->ptr; + *out_contents = (uint8_t *)b->data; + *out_len = b->length; + return 1; +} + +long BIO_get_mem_data(BIO *bio, char **contents) { + return BIO_ctrl(bio, BIO_CTRL_INFO, 0, (char *) contents); +} + +int BIO_get_mem_ptr(BIO *bio, BUF_MEM **out) { + return BIO_ctrl(bio, BIO_C_GET_BUF_MEM_PTR, 0, (char *) out); +} + +int BIO_set_mem_buf(BIO *bio, BUF_MEM *b, int take_ownership) { + return BIO_ctrl(bio, BIO_C_SET_BUF_MEM, take_ownership, (char *) b); +} + +int BIO_set_mem_eof_return(BIO *bio, int eof_value) { + return BIO_ctrl(bio, BIO_C_SET_BUF_MEM_EOF_RETURN, eof_value, NULL); +} diff --git a/external/boringssl/crypto/bio/bio_test.cc b/external/boringssl/crypto/bio/bio_test.cc new file mode 100644 index 0000000000..f2eb20bab1 --- /dev/null +++ b/external/boringssl/crypto/bio/bio_test.cc @@ -0,0 +1,440 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#if !defined(_POSIX_C_SOURCE) +#define _POSIX_C_SOURCE 201410L +#endif + +#include + +#if !defined(OPENSSL_WINDOWS) +#include +#include +#include +#include +#include +#include +#else +#include +OPENSSL_MSVC_PRAGMA(warning(push, 3)) +#include +#include +OPENSSL_MSVC_PRAGMA(warning(pop)) +#endif + +#include +#include +#include +#include + +#include + +#include "../test/scoped_types.h" + + +#if !defined(OPENSSL_WINDOWS) +static int closesocket(int sock) { + return close(sock); +} + +static void PrintSocketError(const char *func) { + perror(func); +} +#else +static void PrintSocketError(const char *func) { + fprintf(stderr, "%s: %d\n", func, WSAGetLastError()); +} +#endif + +class ScopedSocket { + public: + ScopedSocket(int sock) : sock_(sock) {} + ~ScopedSocket() { + closesocket(sock_); + } + + private: + const int sock_; +}; + +static bool TestSocketConnect() { + static const char kTestMessage[] = "test"; + + int listening_sock = socket(AF_INET, SOCK_STREAM, 0); + if (listening_sock == -1) { + PrintSocketError("socket"); + return false; + } + ScopedSocket listening_sock_closer(listening_sock); + + struct sockaddr_in sin; + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + if (!inet_pton(AF_INET, "127.0.0.1", &sin.sin_addr)) { + PrintSocketError("inet_pton"); + return false; + } + if (bind(listening_sock, (struct sockaddr *)&sin, sizeof(sin)) != 0) { + PrintSocketError("bind"); + return false; + } + if (listen(listening_sock, 1)) { + PrintSocketError("listen"); + return false; + } + socklen_t sockaddr_len = sizeof(sin); + if (getsockname(listening_sock, (struct sockaddr *)&sin, &sockaddr_len) || + sockaddr_len != sizeof(sin)) { + PrintSocketError("getsockname"); + return false; + } + + char hostname[80]; + BIO_snprintf(hostname, sizeof(hostname), "%s:%d", "127.0.0.1", + ntohs(sin.sin_port)); + ScopedBIO bio(BIO_new_connect(hostname)); + if (!bio) { + fprintf(stderr, "BIO_new_connect failed.\n"); + return false; + } + + if (BIO_write(bio.get(), kTestMessage, sizeof(kTestMessage)) != + sizeof(kTestMessage)) { + fprintf(stderr, "BIO_write failed.\n"); + ERR_print_errors_fp(stderr); + return false; + } + + int sock = accept(listening_sock, (struct sockaddr *) &sin, &sockaddr_len); + if (sock == -1) { + PrintSocketError("accept"); + return false; + } + ScopedSocket sock_closer(sock); + + char buf[5]; + if (recv(sock, buf, sizeof(buf), 0) != sizeof(kTestMessage)) { + PrintSocketError("read"); + return false; + } + if (memcmp(buf, kTestMessage, sizeof(kTestMessage))) { + return false; + } + + return true; +} + + +// BioReadZeroCopyWrapper is a wrapper around the zero-copy APIs to make +// testing easier. +static size_t BioReadZeroCopyWrapper(BIO *bio, uint8_t *data, size_t len) { + uint8_t *read_buf; + size_t read_buf_offset; + size_t available_bytes; + size_t len_read = 0; + + do { + if (!BIO_zero_copy_get_read_buf(bio, &read_buf, &read_buf_offset, + &available_bytes)) { + return 0; + } + + available_bytes = std::min(available_bytes, len - len_read); + memmove(data + len_read, read_buf + read_buf_offset, available_bytes); + + BIO_zero_copy_get_read_buf_done(bio, available_bytes); + + len_read += available_bytes; + } while (len - len_read > 0 && available_bytes > 0); + + return len_read; +} + +// BioWriteZeroCopyWrapper is a wrapper around the zero-copy APIs to make +// testing easier. +static size_t BioWriteZeroCopyWrapper(BIO *bio, const uint8_t *data, + size_t len) { + uint8_t *write_buf; + size_t write_buf_offset; + size_t available_bytes; + size_t len_written = 0; + + do { + if (!BIO_zero_copy_get_write_buf(bio, &write_buf, &write_buf_offset, + &available_bytes)) { + return 0; + } + + available_bytes = std::min(available_bytes, len - len_written); + memmove(write_buf + write_buf_offset, data + len_written, available_bytes); + + BIO_zero_copy_get_write_buf_done(bio, available_bytes); + + len_written += available_bytes; + } while (len - len_written > 0 && available_bytes > 0); + + return len_written; +} + +static bool TestZeroCopyBioPairs() { + // Test read and write, especially triggering the ring buffer wrap-around. + uint8_t bio1_application_send_buffer[1024]; + uint8_t bio2_application_recv_buffer[1024]; + + const size_t kLengths[] = {254, 255, 256, 257, 510, 511, 512, 513}; + + // These trigger ring buffer wrap around. + const size_t kPartialLengths[] = {0, 1, 2, 3, 128, 255, 256, 257, 511, 512}; + + static const size_t kBufferSize = 512; + + srand(1); + for (size_t i = 0; i < sizeof(bio1_application_send_buffer); i++) { + bio1_application_send_buffer[i] = rand() & 255; + } + + // Transfer bytes from bio1_application_send_buffer to + // bio2_application_recv_buffer in various ways. + for (size_t i = 0; i < sizeof(kLengths) / sizeof(kLengths[0]); i++) { + for (size_t j = 0; j < sizeof(kPartialLengths) / sizeof(kPartialLengths[0]); + j++) { + size_t total_write = 0; + size_t total_read = 0; + + BIO *bio1, *bio2; + if (!BIO_new_bio_pair(&bio1, kBufferSize, &bio2, kBufferSize)) { + return false; + } + ScopedBIO bio1_scoper(bio1); + ScopedBIO bio2_scoper(bio2); + + total_write += BioWriteZeroCopyWrapper( + bio1, bio1_application_send_buffer, kLengths[i]); + + // This tests interleaved read/write calls. Do a read between zero copy + // write calls. + uint8_t *write_buf; + size_t write_buf_offset; + size_t available_bytes; + if (!BIO_zero_copy_get_write_buf(bio1, &write_buf, &write_buf_offset, + &available_bytes)) { + return false; + } + + // Free kPartialLengths[j] bytes in the beginning of bio1 write buffer. + // This enables ring buffer wrap around for the next write. + total_read += BIO_read(bio2, bio2_application_recv_buffer + total_read, + kPartialLengths[j]); + + size_t interleaved_write_len = std::min(kPartialLengths[j], + available_bytes); + + // Write the data for the interleaved write call. If the buffer becomes + // empty after a read, the write offset is normally set to 0. Check that + // this does not happen for interleaved read/write and that + // |write_buf_offset| is still valid. + memcpy(write_buf + write_buf_offset, + bio1_application_send_buffer + total_write, interleaved_write_len); + if (BIO_zero_copy_get_write_buf_done(bio1, interleaved_write_len)) { + total_write += interleaved_write_len; + } + + // Do another write in case |write_buf_offset| was wrapped. + total_write += BioWriteZeroCopyWrapper( + bio1, bio1_application_send_buffer + total_write, + kPartialLengths[j] - interleaved_write_len); + + // Drain the rest. + size_t bytes_left = BIO_pending(bio2); + total_read += BioReadZeroCopyWrapper( + bio2, bio2_application_recv_buffer + total_read, bytes_left); + + if (total_read != total_write) { + fprintf(stderr, "Lengths not equal in round (%u, %u)\n", (unsigned)i, + (unsigned)j); + return false; + } + if (total_read > kLengths[i] + kPartialLengths[j]) { + fprintf(stderr, "Bad lengths in round (%u, %u)\n", (unsigned)i, + (unsigned)j); + return false; + } + if (memcmp(bio1_application_send_buffer, bio2_application_recv_buffer, + total_read) != 0) { + fprintf(stderr, "Buffers not equal in round (%u, %u)\n", (unsigned)i, + (unsigned)j); + return false; + } + } + } + + return true; +} + +static bool TestPrintf() { + // Test a short output, a very long one, and various sizes around + // 256 (the size of the buffer) to ensure edge cases are correct. + static const size_t kLengths[] = { 5, 250, 251, 252, 253, 254, 1023 }; + + ScopedBIO bio(BIO_new(BIO_s_mem())); + if (!bio) { + fprintf(stderr, "BIO_new failed\n"); + return false; + } + + for (size_t i = 0; i < sizeof(kLengths) / sizeof(kLengths[0]); i++) { + char string[1024]; + if (kLengths[i] >= sizeof(string)) { + fprintf(stderr, "Bad test string length\n"); + return false; + } + memset(string, 'a', sizeof(string)); + string[kLengths[i]] = '\0'; + + int ret = BIO_printf(bio.get(), "test %s", string); + if (ret < 0 || static_cast(ret) != 5 + kLengths[i]) { + fprintf(stderr, "BIO_printf failed: %d\n", ret); + return false; + } + const uint8_t *contents; + size_t len; + if (!BIO_mem_contents(bio.get(), &contents, &len)) { + fprintf(stderr, "BIO_mem_contents failed\n"); + return false; + } + if (len != 5 + kLengths[i] || + strncmp((const char *)contents, "test ", 5) != 0 || + strncmp((const char *)contents + 5, string, kLengths[i]) != 0) { + fprintf(stderr, "Contents did not match: %.*s\n", (int)len, contents); + return false; + } + + if (!BIO_reset(bio.get())) { + fprintf(stderr, "BIO_reset failed\n"); + return false; + } + } + + return true; +} + +static bool ReadASN1(bool should_succeed, const uint8_t *data, size_t data_len, + size_t expected_len, size_t max_len) { + ScopedBIO bio(BIO_new_mem_buf(data, data_len)); + + uint8_t *out; + size_t out_len; + int ok = BIO_read_asn1(bio.get(), &out, &out_len, max_len); + if (!ok) { + out = nullptr; + } + ScopedOpenSSLBytes out_storage(out); + + if (should_succeed != (ok == 1)) { + return false; + } + + if (should_succeed && + (out_len != expected_len || memcmp(data, out, expected_len) != 0)) { + return false; + } + + return true; +} + +static bool TestASN1() { + static const uint8_t kData1[] = {0x30, 2, 1, 2, 0, 0}; + static const uint8_t kData2[] = {0x30, 3, 1, 2}; /* truncated */ + static const uint8_t kData3[] = {0x30, 0x81, 1, 1}; /* should be short len */ + static const uint8_t kData4[] = {0x30, 0x82, 0, 1, 1}; /* zero padded. */ + + if (!ReadASN1(true, kData1, sizeof(kData1), 4, 100) || + !ReadASN1(false, kData2, sizeof(kData2), 0, 100) || + !ReadASN1(false, kData3, sizeof(kData3), 0, 100) || + !ReadASN1(false, kData4, sizeof(kData4), 0, 100)) { + return false; + } + + static const size_t kLargePayloadLen = 8000; + static const uint8_t kLargePrefix[] = {0x30, 0x82, kLargePayloadLen >> 8, + kLargePayloadLen & 0xff}; + ScopedOpenSSLBytes large(reinterpret_cast( + OPENSSL_malloc(sizeof(kLargePrefix) + kLargePayloadLen))); + if (!large) { + return false; + } + memset(large.get() + sizeof(kLargePrefix), 0, kLargePayloadLen); + memcpy(large.get(), kLargePrefix, sizeof(kLargePrefix)); + + if (!ReadASN1(true, large.get(), sizeof(kLargePrefix) + kLargePayloadLen, + sizeof(kLargePrefix) + kLargePayloadLen, + kLargePayloadLen * 2)) { + fprintf(stderr, "Large payload test failed.\n"); + return false; + } + + if (!ReadASN1(false, large.get(), sizeof(kLargePrefix) + kLargePayloadLen, + sizeof(kLargePrefix) + kLargePayloadLen, + kLargePayloadLen - 1)) { + fprintf(stderr, "max_len test failed.\n"); + return false; + } + + static const uint8_t kIndefPrefix[] = {0x30, 0x80}; + memcpy(large.get(), kIndefPrefix, sizeof(kIndefPrefix)); + if (!ReadASN1(true, large.get(), sizeof(kLargePrefix) + kLargePayloadLen, + sizeof(kLargePrefix) + kLargePayloadLen, + kLargePayloadLen*2)) { + fprintf(stderr, "indefinite length test failed.\n"); + return false; + } + + if (!ReadASN1(false, large.get(), sizeof(kLargePrefix) + kLargePayloadLen, + sizeof(kLargePrefix) + kLargePayloadLen, + kLargePayloadLen-1)) { + fprintf(stderr, "indefinite length, max_len test failed.\n"); + return false; + } + + return true; +} + +int main(void) { + CRYPTO_library_init(); + +#if defined(OPENSSL_WINDOWS) + // Initialize Winsock. + WORD wsa_version = MAKEWORD(2, 2); + WSADATA wsa_data; + int wsa_err = WSAStartup(wsa_version, &wsa_data); + if (wsa_err != 0) { + fprintf(stderr, "WSAStartup failed: %d\n", wsa_err); + return 1; + } + if (wsa_data.wVersion != wsa_version) { + fprintf(stderr, "Didn't get expected version: %x\n", wsa_data.wVersion); + return 1; + } +#endif + + if (!TestSocketConnect() || + !TestPrintf() || + !TestZeroCopyBioPairs() || + !TestASN1()) { + return 1; + } + + printf("PASS\n"); + return 0; +} diff --git a/external/boringssl/crypto/bio/buffer.c b/external/boringssl/crypto/bio/buffer.c new file mode 100644 index 0000000000..15574510c1 --- /dev/null +++ b/external/boringssl/crypto/bio/buffer.c @@ -0,0 +1,496 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include +#include +#include + + +#define DEFAULT_BUFFER_SIZE 4096 + +typedef struct bio_f_buffer_ctx_struct { + /* Buffers are setup like this: + * + * <---------------------- size -----------------------> + * +---------------------------------------------------+ + * | consumed | remaining | free space | + * +---------------------------------------------------+ + * <-- off --><------- len -------> + */ + + int ibuf_size; /* how big is the input buffer */ + int obuf_size; /* how big is the output buffer */ + + char *ibuf; /* the char array */ + int ibuf_len; /* how many bytes are in it */ + int ibuf_off; /* write/read offset */ + + char *obuf; /* the char array */ + int obuf_len; /* how many bytes are in it */ + int obuf_off; /* write/read offset */ +} BIO_F_BUFFER_CTX; + +static int buffer_new(BIO *bio) { + BIO_F_BUFFER_CTX *ctx; + + ctx = OPENSSL_malloc(sizeof(BIO_F_BUFFER_CTX)); + if (ctx == NULL) { + return 0; + } + memset(ctx, 0, sizeof(BIO_F_BUFFER_CTX)); + + ctx->ibuf = OPENSSL_malloc(DEFAULT_BUFFER_SIZE); + if (ctx->ibuf == NULL) { + goto err1; + } + ctx->obuf = OPENSSL_malloc(DEFAULT_BUFFER_SIZE); + if (ctx->obuf == NULL) { + goto err2; + } + ctx->ibuf_size = DEFAULT_BUFFER_SIZE; + ctx->obuf_size = DEFAULT_BUFFER_SIZE; + + bio->init = 1; + bio->ptr = (char *)ctx; + return 1; + +err2: + OPENSSL_free(ctx->ibuf); + +err1: + OPENSSL_free(ctx); + return 0; +} + +static int buffer_free(BIO *bio) { + BIO_F_BUFFER_CTX *ctx; + + if (bio == NULL || bio->ptr == NULL) { + return 0; + } + + ctx = (BIO_F_BUFFER_CTX *)bio->ptr; + OPENSSL_free(ctx->ibuf); + OPENSSL_free(ctx->obuf); + OPENSSL_free(bio->ptr); + + bio->ptr = NULL; + bio->init = 0; + bio->flags = 0; + + return 1; +} + +static int buffer_read(BIO *bio, char *out, int outl) { + int i, num = 0; + BIO_F_BUFFER_CTX *ctx; + + ctx = (BIO_F_BUFFER_CTX *)bio->ptr; + + if (ctx == NULL || bio->next_bio == NULL) { + return 0; + } + + num = 0; + BIO_clear_retry_flags(bio); + + for (;;) { + i = ctx->ibuf_len; + /* If there is stuff left over, grab it */ + if (i != 0) { + if (i > outl) { + i = outl; + } + memcpy(out, &ctx->ibuf[ctx->ibuf_off], i); + ctx->ibuf_off += i; + ctx->ibuf_len -= i; + num += i; + if (outl == i) { + return num; + } + outl -= i; + out += i; + } + + /* We may have done a partial read. Try to do more. We have nothing in the + * buffer. If we get an error and have read some data, just return it and + * let them retry to get the error again. Copy direct to parent address + * space */ + if (outl > ctx->ibuf_size) { + for (;;) { + i = BIO_read(bio->next_bio, out, outl); + if (i <= 0) { + BIO_copy_next_retry(bio); + if (i < 0) { + return (num > 0) ? num : i; + } + return num; + } + num += i; + if (outl == i) { + return num; + } + out += i; + outl -= i; + } + } + /* else */ + + /* we are going to be doing some buffering */ + i = BIO_read(bio->next_bio, ctx->ibuf, ctx->ibuf_size); + if (i <= 0) { + BIO_copy_next_retry(bio); + if (i < 0) { + return (num > 0) ? num : i; + } + return num; + } + ctx->ibuf_off = 0; + ctx->ibuf_len = i; + } +} + +static int buffer_write(BIO *b, const char *in, int inl) { + int i, num = 0; + BIO_F_BUFFER_CTX *ctx; + + ctx = (BIO_F_BUFFER_CTX *)b->ptr; + if (ctx == NULL || b->next_bio == NULL) { + return 0; + } + + BIO_clear_retry_flags(b); + + for (;;) { + i = ctx->obuf_size - (ctx->obuf_off + ctx->obuf_len); + /* add to buffer and return */ + if (i >= inl) { + memcpy(&ctx->obuf[ctx->obuf_off + ctx->obuf_len], in, inl); + ctx->obuf_len += inl; + return num + inl; + } + /* else */ + /* stuff already in buffer, so add to it first, then flush */ + if (ctx->obuf_len != 0) { + if (i > 0) { + memcpy(&ctx->obuf[ctx->obuf_off + ctx->obuf_len], in, i); + in += i; + inl -= i; + num += i; + ctx->obuf_len += i; + } + + /* we now have a full buffer needing flushing */ + for (;;) { + i = BIO_write(b->next_bio, &ctx->obuf[ctx->obuf_off], ctx->obuf_len); + if (i <= 0) { + BIO_copy_next_retry(b); + + if (i < 0) { + return (num > 0) ? num : i; + } + return num; + } + ctx->obuf_off += i; + ctx->obuf_len -= i; + if (ctx->obuf_len == 0) { + break; + } + } + } + + /* we only get here if the buffer has been flushed and we + * still have stuff to write */ + ctx->obuf_off = 0; + + /* we now have inl bytes to write */ + while (inl >= ctx->obuf_size) { + i = BIO_write(b->next_bio, in, inl); + if (i <= 0) { + BIO_copy_next_retry(b); + if (i < 0) { + return (num > 0) ? num : i; + } + return num; + } + num += i; + in += i; + inl -= i; + if (inl == 0) { + return num; + } + } + + /* copy the rest into the buffer since we have only a small + * amount left */ + } +} + +static long buffer_ctrl(BIO *b, int cmd, long num, void *ptr) { + BIO_F_BUFFER_CTX *ctx; + long ret = 1; + char *p1, *p2; + int r, *ip; + int ibs, obs; + + ctx = (BIO_F_BUFFER_CTX *)b->ptr; + + switch (cmd) { + case BIO_CTRL_RESET: + ctx->ibuf_off = 0; + ctx->ibuf_len = 0; + ctx->obuf_off = 0; + ctx->obuf_len = 0; + if (b->next_bio == NULL) { + return 0; + } + ret = BIO_ctrl(b->next_bio, cmd, num, ptr); + break; + + case BIO_CTRL_INFO: + ret = ctx->obuf_len; + break; + + case BIO_CTRL_WPENDING: + ret = (long)ctx->obuf_len; + if (ret == 0) { + if (b->next_bio == NULL) { + return 0; + } + ret = BIO_ctrl(b->next_bio, cmd, num, ptr); + } + break; + + case BIO_CTRL_PENDING: + ret = (long)ctx->ibuf_len; + if (ret == 0) { + if (b->next_bio == NULL) { + return 0; + } + ret = BIO_ctrl(b->next_bio, cmd, num, ptr); + } + break; + + case BIO_C_SET_BUFF_SIZE: + ip = (int *)ptr; + if (*ip == 0) { + ibs = (int)num; + obs = ctx->obuf_size; + } else /* if (*ip == 1) */ { + ibs = ctx->ibuf_size; + obs = (int)num; + } + p1 = ctx->ibuf; + p2 = ctx->obuf; + if (ibs > DEFAULT_BUFFER_SIZE && ibs != ctx->ibuf_size) { + p1 = OPENSSL_malloc(ibs); + if (p1 == NULL) { + goto malloc_error; + } + } + if (obs > DEFAULT_BUFFER_SIZE && obs != ctx->obuf_size) { + p2 = OPENSSL_malloc(obs); + if (p2 == NULL) { + if (p1 != ctx->ibuf) { + OPENSSL_free(p1); + } + goto malloc_error; + } + } + + if (ctx->ibuf != p1) { + OPENSSL_free(ctx->ibuf); + ctx->ibuf = p1; + ctx->ibuf_size = ibs; + } + ctx->ibuf_off = 0; + ctx->ibuf_len = 0; + + if (ctx->obuf != p2) { + OPENSSL_free(ctx->obuf); + ctx->obuf = p2; + ctx->obuf_size = obs; + } + ctx->obuf_off = 0; + ctx->obuf_len = 0; + break; + + case BIO_CTRL_FLUSH: + if (b->next_bio == NULL) { + return 0; + } + + while (ctx->obuf_len > 0) { + BIO_clear_retry_flags(b); + r = BIO_write(b->next_bio, &(ctx->obuf[ctx->obuf_off]), + ctx->obuf_len); + BIO_copy_next_retry(b); + if (r <= 0) { + return r; + } + ctx->obuf_off += r; + ctx->obuf_len -= r; + } + + ctx->obuf_len = 0; + ctx->obuf_off = 0; + ret = BIO_ctrl(b->next_bio, cmd, num, ptr); + break; + + default: + if (b->next_bio == NULL) { + return 0; + } + BIO_clear_retry_flags(b); + ret = BIO_ctrl(b->next_bio, cmd, num, ptr); + BIO_copy_next_retry(b); + break; + } + return ret; + +malloc_error: + OPENSSL_PUT_ERROR(BIO, ERR_R_MALLOC_FAILURE); + return 0; +} + +static long buffer_callback_ctrl(BIO *b, int cmd, bio_info_cb fp) { + long ret = 1; + + if (b->next_bio == NULL) { + return 0; + } + + switch (cmd) { + default: + ret = BIO_callback_ctrl(b->next_bio, cmd, fp); + break; + } + return ret; +} + +static int buffer_gets(BIO *b, char *buf, int size) { + BIO_F_BUFFER_CTX *ctx; + int num = 0, i, flag; + char *p; + + ctx = (BIO_F_BUFFER_CTX *)b->ptr; + if (buf == NULL || size <= 0) { + return 0; + } + + size--; /* reserve space for a '\0' */ + BIO_clear_retry_flags(b); + + for (;;) { + if (ctx->ibuf_len > 0) { + p = &ctx->ibuf[ctx->ibuf_off]; + flag = 0; + for (i = 0; (i < ctx->ibuf_len) && (i < size); i++) { + *(buf++) = p[i]; + if (p[i] == '\n') { + flag = 1; + i++; + break; + } + } + num += i; + size -= i; + ctx->ibuf_len -= i; + ctx->ibuf_off += i; + if (flag || size == 0) { + *buf = '\0'; + return num; + } + } else /* read another chunk */ + { + i = BIO_read(b->next_bio, ctx->ibuf, ctx->ibuf_size); + if (i <= 0) { + BIO_copy_next_retry(b); + *buf = '\0'; + if (i < 0) { + return (num > 0) ? num : i; + } + return num; + } + ctx->ibuf_len = i; + ctx->ibuf_off = 0; + } + } +} + +static int buffer_puts(BIO *b, const char *str) { + return buffer_write(b, str, strlen(str)); +} + +static const BIO_METHOD methods_buffer = { + BIO_TYPE_BUFFER, "buffer", buffer_write, buffer_read, + buffer_puts, buffer_gets, buffer_ctrl, buffer_new, + buffer_free, buffer_callback_ctrl, +}; + +const BIO_METHOD *BIO_f_buffer(void) { return &methods_buffer; } + +int BIO_set_read_buffer_size(BIO *bio, int buffer_size) { + return BIO_int_ctrl(bio, BIO_C_SET_BUFF_SIZE, buffer_size, 0); +} + +int BIO_set_write_buffer_size(BIO *bio, int buffer_size) { + return BIO_int_ctrl(bio, BIO_C_SET_BUFF_SIZE, buffer_size, 1); +} diff --git a/external/boringssl/crypto/bio/connect.c b/external/boringssl/crypto/bio/connect.c new file mode 100644 index 0000000000..7e544474dd --- /dev/null +++ b/external/boringssl/crypto/bio/connect.c @@ -0,0 +1,553 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include +#include + +#if !defined(OPENSSL_WINDOWS) +#include +#include +#include +#include +#else +OPENSSL_MSVC_PRAGMA(warning(push, 3)) +#include +#include +OPENSSL_MSVC_PRAGMA(warning(pop)) +#endif + +#include +#include +#include + +#include "internal.h" + + +enum { + BIO_CONN_S_BEFORE, + BIO_CONN_S_BLOCKED_CONNECT, + BIO_CONN_S_OK, +}; + +typedef struct bio_connect_st { + int state; + + char *param_hostname; + char *param_port; + int nbio; + + unsigned short port; + + struct sockaddr_storage them; + socklen_t them_length; + + /* the file descriptor is kept in bio->num in order to match the socket + * BIO. */ + + /* info_callback is called when the connection is initially made + * callback(BIO,state,ret); The callback should return 'ret', state is for + * compatibility with the SSL info_callback. */ + int (*info_callback)(const BIO *bio, int state, int ret); +} BIO_CONNECT; + +#if !defined(OPENSSL_WINDOWS) +static int closesocket(int sock) { + return close(sock); +} +#endif + +/* split_host_and_port sets |*out_host| and |*out_port| to the host and port + * parsed from |name|. It returns one on success or zero on error. Even when + * successful, |*out_port| may be NULL on return if no port was specified. */ +static int split_host_and_port(char **out_host, char **out_port, const char *name) { + const char *host, *port = NULL; + size_t host_len = 0; + + *out_host = NULL; + *out_port = NULL; + + if (name[0] == '[') { /* bracketed IPv6 address */ + const char *close = strchr(name, ']'); + if (close == NULL) { + return 0; + } + host = name + 1; + host_len = close - host; + if (close[1] == ':') { /* [IP]:port */ + port = close + 2; + } else if (close[1] != 0) { + return 0; + } + } else { + const char *colon = strchr(name, ':'); + if (colon == NULL || strchr(colon + 1, ':') != NULL) { /* IPv6 address */ + host = name; + host_len = strlen(name); + } else { /* host:port */ + host = name; + host_len = colon - name; + port = colon + 1; + } + } + + *out_host = BUF_strndup(host, host_len); + if (*out_host == NULL) { + return 0; + } + if (port == NULL) { + *out_port = NULL; + return 1; + } + *out_port = OPENSSL_strdup(port); + if (*out_port == NULL) { + OPENSSL_free(*out_host); + *out_host = NULL; + return 0; + } + return 1; +} + +static int conn_state(BIO *bio, BIO_CONNECT *c) { + int ret = -1, i; + int (*cb)(const BIO *, int, int) = NULL; + + if (c->info_callback != NULL) { + cb = c->info_callback; + } + + for (;;) { + switch (c->state) { + case BIO_CONN_S_BEFORE: + /* If there's a hostname and a port, assume that both are + * exactly what they say. If there is only a hostname, try + * (just once) to split it into a hostname and port. */ + + if (c->param_hostname == NULL) { + OPENSSL_PUT_ERROR(BIO, BIO_R_NO_HOSTNAME_SPECIFIED); + goto exit_loop; + } + + if (c->param_port == NULL) { + char *host, *port; + if (!split_host_and_port(&host, &port, c->param_hostname) || + port == NULL) { + OPENSSL_free(host); + OPENSSL_free(port); + OPENSSL_PUT_ERROR(BIO, BIO_R_NO_PORT_SPECIFIED); + ERR_add_error_data(2, "host=", c->param_hostname); + goto exit_loop; + } + + OPENSSL_free(c->param_port); + c->param_port = port; + OPENSSL_free(c->param_hostname); + c->param_hostname = host; + } + + if (!bio_ip_and_port_to_socket_and_addr( + &bio->num, &c->them, &c->them_length, c->param_hostname, + c->param_port)) { + OPENSSL_PUT_ERROR(BIO, BIO_R_UNABLE_TO_CREATE_SOCKET); + ERR_add_error_data(4, "host=", c->param_hostname, ":", c->param_port); + goto exit_loop; + } + + if (c->nbio) { + if (!bio_socket_nbio(bio->num, 1)) { + OPENSSL_PUT_ERROR(BIO, BIO_R_ERROR_SETTING_NBIO); + ERR_add_error_data(4, "host=", c->param_hostname, ":", + c->param_port); + goto exit_loop; + } + } + + i = 1; + ret = setsockopt(bio->num, SOL_SOCKET, SO_KEEPALIVE, (char *)&i, + sizeof(i)); + if (ret < 0) { + OPENSSL_PUT_SYSTEM_ERROR(); + OPENSSL_PUT_ERROR(BIO, BIO_R_KEEPALIVE); + ERR_add_error_data(4, "host=", c->param_hostname, ":", c->param_port); + goto exit_loop; + } + + BIO_clear_retry_flags(bio); + ret = connect(bio->num, (struct sockaddr*) &c->them, c->them_length); + if (ret < 0) { + if (bio_fd_should_retry(ret)) { + BIO_set_flags(bio, (BIO_FLAGS_IO_SPECIAL | BIO_FLAGS_SHOULD_RETRY)); + c->state = BIO_CONN_S_BLOCKED_CONNECT; + bio->retry_reason = BIO_RR_CONNECT; + } else { + OPENSSL_PUT_SYSTEM_ERROR(); + OPENSSL_PUT_ERROR(BIO, BIO_R_CONNECT_ERROR); + ERR_add_error_data(4, "host=", c->param_hostname, ":", + c->param_port); + } + goto exit_loop; + } else { + c->state = BIO_CONN_S_OK; + } + break; + + case BIO_CONN_S_BLOCKED_CONNECT: + i = bio_sock_error(bio->num); + if (i) { + if (bio_fd_should_retry(ret)) { + BIO_set_flags(bio, (BIO_FLAGS_IO_SPECIAL | BIO_FLAGS_SHOULD_RETRY)); + c->state = BIO_CONN_S_BLOCKED_CONNECT; + bio->retry_reason = BIO_RR_CONNECT; + ret = -1; + } else { + BIO_clear_retry_flags(bio); + OPENSSL_PUT_SYSTEM_ERROR(); + OPENSSL_PUT_ERROR(BIO, BIO_R_NBIO_CONNECT_ERROR); + ERR_add_error_data(4, "host=", c->param_hostname, ":", c->param_port); + ret = 0; + } + goto exit_loop; + } else { + c->state = BIO_CONN_S_OK; + } + break; + + case BIO_CONN_S_OK: + ret = 1; + goto exit_loop; + default: + assert(0); + goto exit_loop; + } + + if (cb != NULL) { + ret = cb((BIO *)bio, c->state, ret); + if (ret == 0) { + goto end; + } + } + } + +exit_loop: + if (cb != NULL) { + ret = cb((BIO *)bio, c->state, ret); + } + +end: + return ret; +} + +static BIO_CONNECT *BIO_CONNECT_new(void) { + BIO_CONNECT *ret = OPENSSL_malloc(sizeof(BIO_CONNECT)); + + if (ret == NULL) { + return NULL; + } + memset(ret, 0, sizeof(BIO_CONNECT)); + + ret->state = BIO_CONN_S_BEFORE; + return ret; +} + +static void BIO_CONNECT_free(BIO_CONNECT *c) { + if (c == NULL) { + return; + } + + OPENSSL_free(c->param_hostname); + OPENSSL_free(c->param_port); + OPENSSL_free(c); +} + +static int conn_new(BIO *bio) { + bio->init = 0; + bio->num = -1; + bio->flags = 0; + bio->ptr = (char *)BIO_CONNECT_new(); + return bio->ptr != NULL; +} + +static void conn_close_socket(BIO *bio) { + BIO_CONNECT *c = (BIO_CONNECT *) bio->ptr; + + if (bio->num == -1) { + return; + } + + /* Only do a shutdown if things were established */ + if (c->state == BIO_CONN_S_OK) { + shutdown(bio->num, 2); + } + closesocket(bio->num); + bio->num = -1; +} + +static int conn_free(BIO *bio) { + if (bio == NULL) { + return 0; + } + + if (bio->shutdown) { + conn_close_socket(bio); + } + + BIO_CONNECT_free((BIO_CONNECT*) bio->ptr); + + return 1; +} + +static int conn_read(BIO *bio, char *out, int out_len) { + int ret = 0; + BIO_CONNECT *data; + + data = (BIO_CONNECT *)bio->ptr; + if (data->state != BIO_CONN_S_OK) { + ret = conn_state(bio, data); + if (ret <= 0) { + return ret; + } + } + + bio_clear_socket_error(); + ret = recv(bio->num, out, out_len, 0); + BIO_clear_retry_flags(bio); + if (ret <= 0) { + if (bio_fd_should_retry(ret)) { + BIO_set_retry_read(bio); + } + } + + return ret; +} + +static int conn_write(BIO *bio, const char *in, int in_len) { + int ret; + BIO_CONNECT *data; + + data = (BIO_CONNECT *)bio->ptr; + if (data->state != BIO_CONN_S_OK) { + ret = conn_state(bio, data); + if (ret <= 0) { + return ret; + } + } + + bio_clear_socket_error(); + ret = send(bio->num, in, in_len, 0); + BIO_clear_retry_flags(bio); + if (ret <= 0) { + if (bio_fd_should_retry(ret)) { + BIO_set_retry_write(bio); + } + } + + return ret; +} + +static long conn_ctrl(BIO *bio, int cmd, long num, void *ptr) { + int *ip; + long ret = 1; + BIO_CONNECT *data; + + data = (BIO_CONNECT *)bio->ptr; + + switch (cmd) { + case BIO_CTRL_RESET: + ret = 0; + data->state = BIO_CONN_S_BEFORE; + conn_close_socket(bio); + bio->flags = 0; + break; + case BIO_C_DO_STATE_MACHINE: + /* use this one to start the connection */ + if (data->state != BIO_CONN_S_OK) { + ret = (long)conn_state(bio, data); + } else { + ret = 1; + } + break; + case BIO_C_SET_CONNECT: + if (ptr != NULL) { + bio->init = 1; + if (num == 0) { + OPENSSL_free(data->param_hostname); + data->param_hostname = BUF_strdup(ptr); + if (data->param_hostname == NULL) { + ret = 0; + } + } else if (num == 1) { + OPENSSL_free(data->param_port); + data->param_port = BUF_strdup(ptr); + if (data->param_port == NULL) { + ret = 0; + } + } else { + ret = 0; + } + } + break; + case BIO_C_SET_NBIO: + data->nbio = (int)num; + break; + case BIO_C_GET_FD: + if (bio->init) { + ip = (int *)ptr; + if (ip != NULL) { + *ip = bio->num; + } + ret = bio->num; + } else { + ret = -1; + } + break; + case BIO_CTRL_GET_CLOSE: + ret = bio->shutdown; + break; + case BIO_CTRL_SET_CLOSE: + bio->shutdown = (int)num; + break; + case BIO_CTRL_PENDING: + case BIO_CTRL_WPENDING: + ret = 0; + break; + case BIO_CTRL_FLUSH: + break; + case BIO_CTRL_SET_CALLBACK: { +#if 0 /* FIXME: Should this be used? -- Richard Levitte */ + OPENSSL_PUT_ERROR(BIO, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + ret = -1; +#else + ret = 0; +#endif + } break; + case BIO_CTRL_GET_CALLBACK: { + int (**fptr)(const BIO *bio, int state, int xret); + fptr = (int (**)(const BIO *bio, int state, int xret))ptr; + *fptr = data->info_callback; + } break; + default: + ret = 0; + break; + } + return (ret); +} + +static long conn_callback_ctrl(BIO *bio, int cmd, bio_info_cb fp) { + long ret = 1; + BIO_CONNECT *data; + + data = (BIO_CONNECT *)bio->ptr; + + switch (cmd) { + case BIO_CTRL_SET_CALLBACK: { + data->info_callback = (int (*)(const struct bio_st *, int, int))fp; + } break; + default: + ret = 0; + break; + } + return ret; +} + +static int conn_puts(BIO *bp, const char *str) { + return conn_write(bp, str, strlen(str)); +} + +BIO *BIO_new_connect(const char *hostname) { + BIO *ret; + + ret = BIO_new(BIO_s_connect()); + if (ret == NULL) { + return NULL; + } + if (!BIO_set_conn_hostname(ret, hostname)) { + BIO_free(ret); + return NULL; + } + return ret; +} + +static const BIO_METHOD methods_connectp = { + BIO_TYPE_CONNECT, "socket connect", conn_write, conn_read, + conn_puts, NULL /* connect_gets, */, conn_ctrl, conn_new, + conn_free, conn_callback_ctrl, +}; + +const BIO_METHOD *BIO_s_connect(void) { return &methods_connectp; } + +int BIO_set_conn_hostname(BIO *bio, const char *name) { + return BIO_ctrl(bio, BIO_C_SET_CONNECT, 0, (void*) name); +} + +int BIO_set_conn_port(BIO *bio, const char *port_str) { + return BIO_ctrl(bio, BIO_C_SET_CONNECT, 1, (void*) port_str); +} + +int BIO_set_conn_int_port(BIO *bio, const int *port) { + char buf[DECIMAL_SIZE(int) + 1]; + BIO_snprintf(buf, sizeof(buf), "%d", *port); + return BIO_set_conn_port(bio, buf); +} + +int BIO_set_nbio(BIO *bio, int on) { + return BIO_ctrl(bio, BIO_C_SET_NBIO, on, NULL); +} + +int BIO_do_connect(BIO *bio) { + return BIO_ctrl(bio, BIO_C_DO_STATE_MACHINE, 0, NULL); +} diff --git a/external/boringssl/crypto/bio/fd.c b/external/boringssl/crypto/bio/fd.c new file mode 100644 index 0000000000..13833df569 --- /dev/null +++ b/external/boringssl/crypto/bio/fd.c @@ -0,0 +1,277 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +#if !defined(OPENSSL_WINDOWS) +#include +#else +#include +OPENSSL_MSVC_PRAGMA(warning(push, 3)) +#include +OPENSSL_MSVC_PRAGMA(warning(pop)) +#endif + +#include +#include +#include + +#include "internal.h" + + +static int bio_fd_non_fatal_error(int err) { + if ( +#ifdef EWOULDBLOCK + err == EWOULDBLOCK || +#endif +#ifdef WSAEWOULDBLOCK + err == WSAEWOULDBLOCK || +#endif +#ifdef ENOTCONN + err == ENOTCONN || +#endif +#ifdef EINTR + err == EINTR || +#endif +#ifdef EAGAIN + err == EAGAIN || +#endif +#ifdef EPROTO + err == EPROTO || +#endif +#ifdef EINPROGRESS + err == EINPROGRESS || +#endif +#ifdef EALREADY + err == EALREADY || +#endif + 0) { + return 1; + } + return 0; +} + +#if defined(OPENSSL_WINDOWS) + #define BORINGSSL_ERRNO (int)GetLastError() + #define BORINGSSL_CLOSE _close + #define BORINGSSL_LSEEK _lseek + #define BORINGSSL_READ _read + #define BORINGSSL_WRITE _write +#else + #define BORINGSSL_ERRNO errno + #define BORINGSSL_CLOSE close + #define BORINGSSL_LSEEK lseek + #define BORINGSSL_READ read + #define BORINGSSL_WRITE write +#endif + +int bio_fd_should_retry(int i) { + if (i == -1) { + return bio_fd_non_fatal_error(BORINGSSL_ERRNO); + } + return 0; +} + +BIO *BIO_new_fd(int fd, int close_flag) { + BIO *ret = BIO_new(BIO_s_fd()); + if (ret == NULL) { + return NULL; + } + BIO_set_fd(ret, fd, close_flag); + return ret; +} + +static int fd_new(BIO *bio) { + /* num is used to store the file descriptor. */ + bio->num = -1; + return 1; +} + +static int fd_free(BIO *bio) { + if (bio == NULL) { + return 0; + } + + if (bio->shutdown) { + if (bio->init) { + BORINGSSL_CLOSE(bio->num); + } + bio->init = 0; + } + return 1; +} + +static int fd_read(BIO *b, char *out, int outl) { + int ret = 0; + + ret = BORINGSSL_READ(b->num, out, outl); + BIO_clear_retry_flags(b); + if (ret <= 0) { + if (bio_fd_should_retry(ret)) { + BIO_set_retry_read(b); + } + } + + return ret; +} + +static int fd_write(BIO *b, const char *in, int inl) { + int ret = BORINGSSL_WRITE(b->num, in, inl); + BIO_clear_retry_flags(b); + if (ret <= 0) { + if (bio_fd_should_retry(ret)) { + BIO_set_retry_write(b); + } + } + + return ret; +} + +static long fd_ctrl(BIO *b, int cmd, long num, void *ptr) { + long ret = 1; + int *ip; + + switch (cmd) { + case BIO_CTRL_RESET: + num = 0; + case BIO_C_FILE_SEEK: + ret = 0; + if (b->init) { + ret = (long)BORINGSSL_LSEEK(b->num, num, SEEK_SET); + } + break; + case BIO_C_FILE_TELL: + case BIO_CTRL_INFO: + ret = 0; + if (b->init) { + ret = (long)BORINGSSL_LSEEK(b->num, 0, SEEK_CUR); + } + break; + case BIO_C_SET_FD: + fd_free(b); + b->num = *((int *)ptr); + b->shutdown = (int)num; + b->init = 1; + break; + case BIO_C_GET_FD: + if (b->init) { + ip = (int *)ptr; + if (ip != NULL) { + *ip = b->num; + } + return b->num; + } else { + ret = -1; + } + break; + case BIO_CTRL_GET_CLOSE: + ret = b->shutdown; + break; + case BIO_CTRL_SET_CLOSE: + b->shutdown = (int)num; + break; + case BIO_CTRL_PENDING: + case BIO_CTRL_WPENDING: + ret = 0; + break; + case BIO_CTRL_FLUSH: + ret = 1; + break; + default: + ret = 0; + break; + } + + return ret; +} + +static int fd_puts(BIO *bp, const char *str) { + return fd_write(bp, str, strlen(str)); +} + +static int fd_gets(BIO *bp, char *buf, int size) { + char *ptr = buf; + char *end = buf + size - 1; + + if (size <= 0) { + return 0; + } + + while (ptr < end && fd_read(bp, ptr, 1) > 0 && ptr[0] != '\n') { + ptr++; + } + + ptr[0] = '\0'; + + return ptr - buf; +} + +static const BIO_METHOD methods_fdp = { + BIO_TYPE_FD, "file descriptor", fd_write, fd_read, fd_puts, + fd_gets, fd_ctrl, fd_new, fd_free, NULL, }; + +const BIO_METHOD *BIO_s_fd(void) { return &methods_fdp; } + +int BIO_set_fd(BIO *bio, int fd, int close_flag) { + return BIO_int_ctrl(bio, BIO_C_SET_FD, close_flag, fd); +} + +int BIO_get_fd(BIO *bio, int *out_fd) { + return BIO_ctrl(bio, BIO_C_GET_FD, 0, (char *) out_fd); +} diff --git a/external/boringssl/crypto/bio/file.c b/external/boringssl/crypto/bio/file.c new file mode 100644 index 0000000000..b903bc28b9 --- /dev/null +++ b/external/boringssl/crypto/bio/file.c @@ -0,0 +1,313 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#if defined(__linux) || defined(__sun) || defined(__hpux) +/* Following definition aliases fopen to fopen64 on above mentioned + * platforms. This makes it possible to open and sequentially access + * files larger than 2GB from 32-bit application. It does not allow to + * traverse them beyond 2GB with fseek/ftell, but on the other hand *no* + * 32-bit platform permits that, not with fseek/ftell. Not to mention + * that breaking 2GB limit for seeking would require surgery to *our* + * API. But sequential access suffices for practical cases when you + * can run into large files, such as fingerprinting, so we can let API + * alone. For reference, the list of 32-bit platforms which allow for + * sequential access of large files without extra "magic" comprise *BSD, + * Darwin, IRIX... + */ +#ifndef _FILE_OFFSET_BITS +#define _FILE_OFFSET_BITS 64 +#endif +#endif + +#include + +#include +#include +#include + +#include +#include +#include + + +#define BIO_FP_READ 0x02 +#define BIO_FP_WRITE 0x04 +#define BIO_FP_APPEND 0x08 + +BIO *BIO_new_file(const char *filename, const char *mode) { + BIO *ret; + FILE *file; + + file = fopen(filename, mode); + if (file == NULL) { + OPENSSL_PUT_SYSTEM_ERROR(); + + ERR_add_error_data(5, "fopen('", filename, "','", mode, "')"); + if (errno == ENOENT) { + OPENSSL_PUT_ERROR(BIO, BIO_R_NO_SUCH_FILE); + } else { + OPENSSL_PUT_ERROR(BIO, BIO_R_SYS_LIB); + } + return NULL; + } + + ret = BIO_new(BIO_s_file()); + if (ret == NULL) { + fclose(file); + return NULL; + } + + BIO_set_fp(ret, file, BIO_CLOSE); + return ret; +} + +BIO *BIO_new_fp(FILE *stream, int close_flag) { + BIO *ret = BIO_new(BIO_s_file()); + + if (ret == NULL) { + return NULL; + } + + BIO_set_fp(ret, stream, close_flag); + return ret; +} + +static int file_new(BIO *bio) { return 1; } + +static int file_free(BIO *bio) { + if (bio == NULL) { + return 0; + } + + if (!bio->shutdown) { + return 1; + } + + if (bio->init && bio->ptr != NULL) { + fclose(bio->ptr); + bio->ptr = NULL; + } + bio->init = 0; + + return 1; +} + +static int file_read(BIO *b, char *out, int outl) { + if (!b->init) { + return 0; + } + + size_t ret = fread(out, 1, outl, (FILE *)b->ptr); + if (ret == 0 && ferror((FILE *)b->ptr)) { + OPENSSL_PUT_SYSTEM_ERROR(); + OPENSSL_PUT_ERROR(BIO, ERR_R_SYS_LIB); + return -1; + } + + /* fread reads at most |outl| bytes, so |ret| fits in an int. */ + return (int)ret; +} + +static int file_write(BIO *b, const char *in, int inl) { + int ret = 0; + + if (!b->init) { + return 0; + } + + ret = fwrite(in, inl, 1, (FILE *)b->ptr); + if (ret > 0) { + ret = inl; + } + return ret; +} + +static long file_ctrl(BIO *b, int cmd, long num, void *ptr) { + long ret = 1; + FILE *fp = (FILE *)b->ptr; + FILE **fpp; + char p[4]; + + switch (cmd) { + case BIO_CTRL_RESET: + num = 0; + case BIO_C_FILE_SEEK: + ret = (long)fseek(fp, num, 0); + break; + case BIO_CTRL_EOF: + ret = (long)feof(fp); + break; + case BIO_C_FILE_TELL: + case BIO_CTRL_INFO: + ret = ftell(fp); + break; + case BIO_C_SET_FILE_PTR: + file_free(b); + b->shutdown = (int)num & BIO_CLOSE; + b->ptr = ptr; + b->init = 1; + break; + case BIO_C_SET_FILENAME: + file_free(b); + b->shutdown = (int)num & BIO_CLOSE; + if (num & BIO_FP_APPEND) { + if (num & BIO_FP_READ) { + BUF_strlcpy(p, "a+", sizeof(p)); + } else { + BUF_strlcpy(p, "a", sizeof(p)); + } + } else if ((num & BIO_FP_READ) && (num & BIO_FP_WRITE)) { + BUF_strlcpy(p, "r+", sizeof(p)); + } else if (num & BIO_FP_WRITE) { + BUF_strlcpy(p, "w", sizeof(p)); + } else if (num & BIO_FP_READ) { + BUF_strlcpy(p, "r", sizeof(p)); + } else { + OPENSSL_PUT_ERROR(BIO, BIO_R_BAD_FOPEN_MODE); + ret = 0; + break; + } + fp = fopen(ptr, p); + if (fp == NULL) { + OPENSSL_PUT_SYSTEM_ERROR(); + ERR_add_error_data(5, "fopen('", ptr, "','", p, "')"); + OPENSSL_PUT_ERROR(BIO, ERR_R_SYS_LIB); + ret = 0; + break; + } + b->ptr = fp; + b->init = 1; + break; + case BIO_C_GET_FILE_PTR: + /* the ptr parameter is actually a FILE ** in this case. */ + if (ptr != NULL) { + fpp = (FILE **)ptr; + *fpp = (FILE *)b->ptr; + } + break; + case BIO_CTRL_GET_CLOSE: + ret = (long)b->shutdown; + break; + case BIO_CTRL_SET_CLOSE: + b->shutdown = (int)num; + break; + case BIO_CTRL_FLUSH: + ret = 0 == fflush((FILE *)b->ptr); + break; + case BIO_CTRL_WPENDING: + case BIO_CTRL_PENDING: + default: + ret = 0; + break; + } + return ret; +} + +static int file_gets(BIO *bp, char *buf, int size) { + int ret = 0; + + if (size == 0) { + return 0; + } + + if (!fgets(buf, size, (FILE *)bp->ptr)) { + buf[0] = 0; + goto err; + } + ret = strlen(buf); + +err: + return ret; +} + +static int file_puts(BIO *bp, const char *str) { + return file_write(bp, str, strlen(str)); +} + +static const BIO_METHOD methods_filep = { + BIO_TYPE_FILE, "FILE pointer", file_write, file_read, file_puts, + file_gets, file_ctrl, file_new, file_free, NULL, }; + +const BIO_METHOD *BIO_s_file(void) { return &methods_filep; } + + +int BIO_get_fp(BIO *bio, FILE **out_file) { + return BIO_ctrl(bio, BIO_C_GET_FILE_PTR, 0, (char*) out_file); +} + +int BIO_set_fp(BIO *bio, FILE *file, int close_flag) { + return BIO_ctrl(bio, BIO_C_SET_FILE_PTR, close_flag, (char *) file); +} + +int BIO_read_filename(BIO *bio, const char *filename) { + return BIO_ctrl(bio, BIO_C_SET_FILENAME, BIO_CLOSE | BIO_FP_READ, + (char *)filename); +} + +int BIO_write_filename(BIO *bio, const char *filename) { + return BIO_ctrl(bio, BIO_C_SET_FILENAME, BIO_CLOSE | BIO_FP_WRITE, + (char *)filename); +} + +int BIO_append_filename(BIO *bio, const char *filename) { + return BIO_ctrl(bio, BIO_C_SET_FILENAME, BIO_CLOSE | BIO_FP_APPEND, + (char *)filename); +} + +int BIO_rw_filename(BIO *bio, const char *filename) { + return BIO_ctrl(bio, BIO_C_SET_FILENAME, + BIO_CLOSE | BIO_FP_READ | BIO_FP_WRITE, (char *)filename); +} diff --git a/external/boringssl/crypto/bio/hexdump.c b/external/boringssl/crypto/bio/hexdump.c new file mode 100644 index 0000000000..17f55183f0 --- /dev/null +++ b/external/boringssl/crypto/bio/hexdump.c @@ -0,0 +1,192 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + + +/* hexdump_ctx contains the state of a hexdump. */ +struct hexdump_ctx { + BIO *bio; + char right_chars[18]; /* the contents of the right-hand side, ASCII dump. */ + unsigned used; /* number of bytes in the current line. */ + size_t n; /* number of bytes total. */ + unsigned indent; +}; + +static void hexbyte(char *out, uint8_t b) { + static const char hextable[] = "0123456789abcdef"; + out[0] = hextable[b>>4]; + out[1] = hextable[b&0x0f]; +} + +static char to_char(uint8_t b) { + if (b < 32 || b > 126) { + return '.'; + } + return b; +} + +/* hexdump_write adds |len| bytes of |data| to the current hex dump described by + * |ctx|. */ +static int hexdump_write(struct hexdump_ctx *ctx, const uint8_t *data, + size_t len) { + size_t i; + char buf[10]; + unsigned l; + + /* Output lines look like: + * 00000010 2e 2f 30 31 32 33 34 35 36 37 38 ... 3c 3d // |./0123456789:;<=| + * ^ offset ^ extra space ^ ASCII of line + */ + + for (i = 0; i < len; i++) { + if (ctx->used == 0) { + /* The beginning of a line. */ + BIO_indent(ctx->bio, ctx->indent, UINT_MAX); + + hexbyte(&buf[0], ctx->n >> 24); + hexbyte(&buf[2], ctx->n >> 16); + hexbyte(&buf[4], ctx->n >> 8); + hexbyte(&buf[6], ctx->n); + buf[8] = buf[9] = ' '; + if (BIO_write(ctx->bio, buf, 10) < 0) { + return 0; + } + } + + hexbyte(buf, data[i]); + buf[2] = ' '; + l = 3; + if (ctx->used == 7) { + /* There's an additional space after the 8th byte. */ + buf[3] = ' '; + l = 4; + } else if (ctx->used == 15) { + /* At the end of the line there's an extra space and the bar for the + * right column. */ + buf[3] = ' '; + buf[4] = '|'; + l = 5; + } + + if (BIO_write(ctx->bio, buf, l) < 0) { + return 0; + } + ctx->right_chars[ctx->used] = to_char(data[i]); + ctx->used++; + ctx->n++; + if (ctx->used == 16) { + ctx->right_chars[16] = '|'; + ctx->right_chars[17] = '\n'; + if (BIO_write(ctx->bio, ctx->right_chars, sizeof(ctx->right_chars)) < 0) { + return 0; + } + ctx->used = 0; + } + } + + return 1; +} + +/* finish flushes any buffered data in |ctx|. */ +static int finish(struct hexdump_ctx *ctx) { + /* See the comments in |hexdump| for the details of this format. */ + const unsigned n_bytes = ctx->used; + unsigned l; + char buf[5]; + + if (n_bytes == 0) { + return 1; + } + + memset(buf, ' ', 4); + buf[4] = '|'; + + for (; ctx->used < 16; ctx->used++) { + l = 3; + if (ctx->used == 7) { + l = 4; + } else if (ctx->used == 15) { + l = 5; + } + if (BIO_write(ctx->bio, buf, l) < 0) { + return 0; + } + } + + ctx->right_chars[n_bytes] = '|'; + ctx->right_chars[n_bytes + 1] = '\n'; + if (BIO_write(ctx->bio, ctx->right_chars, n_bytes + 2) < 0) { + return 0; + } + return 1; +} + +int BIO_hexdump(BIO *bio, const uint8_t *data, size_t len, unsigned indent) { + struct hexdump_ctx ctx; + memset(&ctx, 0, sizeof(ctx)); + ctx.bio = bio; + ctx.indent = indent; + + if (!hexdump_write(&ctx, data, len) || !finish(&ctx)) { + return 0; + } + + return 1; +} diff --git a/external/boringssl/crypto/bio/internal.h b/external/boringssl/crypto/bio/internal.h new file mode 100644 index 0000000000..4ec77fadb6 --- /dev/null +++ b/external/boringssl/crypto/bio/internal.h @@ -0,0 +1,111 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_BIO_INTERNAL_H +#define OPENSSL_HEADER_BIO_INTERNAL_H + +#include + +#if !defined(OPENSSL_WINDOWS) +#if defined(OPENSSL_PNACL) +/* newlib uses u_short in socket.h without defining it. */ +typedef unsigned short u_short; +#endif +#include +#include +#else +OPENSSL_MSVC_PRAGMA(warning(push, 3)) +#include +OPENSSL_MSVC_PRAGMA(warning(pop)) +typedef int socklen_t; +#endif + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* BIO_ip_and_port_to_socket_and_addr creates a socket and fills in |*out_addr| + * and |*out_addr_length| with the correct values for connecting to |hostname| + * on |port_str|. It returns one on success or zero on error. */ +int bio_ip_and_port_to_socket_and_addr(int *out_sock, + struct sockaddr_storage *out_addr, + socklen_t *out_addr_length, + const char *hostname, + const char *port_str); + +/* BIO_socket_nbio sets whether |sock| is non-blocking. It returns one on + * success and zero otherwise. */ +int bio_socket_nbio(int sock, int on); + +/* BIO_clear_socket_error clears the last system socket error. + * + * TODO(fork): remove all callers of this. */ +void bio_clear_socket_error(void); + +/* BIO_sock_error returns the last socket error on |sock|. */ +int bio_sock_error(int sock); + +/* BIO_fd_should_retry returns non-zero if |return_value| indicates an error + * and |errno| indicates that it's non-fatal. */ +int bio_fd_should_retry(int return_value); + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_BIO_INTERNAL_H */ diff --git a/external/boringssl/crypto/bio/pair.c b/external/boringssl/crypto/bio/pair.c new file mode 100644 index 0000000000..2da2d20337 --- /dev/null +++ b/external/boringssl/crypto/bio/pair.c @@ -0,0 +1,803 @@ +/* ==================================================================== + * Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include + +#include +#include +#include + + +struct bio_bio_st { + BIO *peer; /* NULL if buf == NULL. + * If peer != NULL, then peer->ptr is also a bio_bio_st, + * and its "peer" member points back to us. + * peer != NULL iff init != 0 in the BIO. */ + + /* This is for what we write (i.e. reading uses peer's struct): */ + int closed; /* valid iff peer != NULL */ + size_t len; /* valid iff buf != NULL; 0 if peer == NULL */ + size_t offset; /* valid iff buf != NULL; 0 if len == 0 */ + size_t size; + uint8_t *buf; /* "size" elements (if != NULL) */ + char buf_externally_allocated; /* true iff buf was externally allocated. */ + + char zero_copy_read_lock; /* true iff a zero copy read operation + * is in progress. */ + char zero_copy_write_lock; /* true iff a zero copy write operation + * is in progress. */ + + size_t request; /* valid iff peer != NULL; 0 if len != 0, + * otherwise set by peer to number of bytes + * it (unsuccessfully) tried to read, + * never more than buffer space (size-len) warrants. */ +}; + +static int bio_new(BIO *bio) { + struct bio_bio_st *b; + + b = OPENSSL_malloc(sizeof *b); + if (b == NULL) { + return 0; + } + memset(b, 0, sizeof(struct bio_bio_st)); + + b->size = 17 * 1024; /* enough for one TLS record (just a default) */ + bio->ptr = b; + return 1; +} + +static void bio_destroy_pair(BIO *bio) { + struct bio_bio_st *b = bio->ptr; + BIO *peer_bio; + struct bio_bio_st *peer_b; + + if (b == NULL) { + return; + } + + peer_bio = b->peer; + if (peer_bio == NULL) { + return; + } + + peer_b = peer_bio->ptr; + + assert(peer_b != NULL); + assert(peer_b->peer == bio); + + peer_b->peer = NULL; + peer_bio->init = 0; + assert(peer_b->buf != NULL); + peer_b->len = 0; + peer_b->offset = 0; + + b->peer = NULL; + bio->init = 0; + assert(b->buf != NULL); + b->len = 0; + b->offset = 0; +} + +static int bio_free(BIO *bio) { + struct bio_bio_st *b; + + if (bio == NULL) { + return 0; + } + b = bio->ptr; + + assert(b != NULL); + + if (b->peer) { + bio_destroy_pair(bio); + } + + if (!b->buf_externally_allocated) { + OPENSSL_free(b->buf); + } + + OPENSSL_free(b); + + return 1; +} + +static size_t bio_zero_copy_get_read_buf(struct bio_bio_st* peer_b, + uint8_t** out_read_buf, + size_t* out_buf_offset) { + size_t max_available; + if (peer_b->len > peer_b->size - peer_b->offset) { + /* Only the first half of the ring buffer can be read. */ + max_available = peer_b->size - peer_b->offset; + } else { + max_available = peer_b->len; + } + + *out_read_buf = peer_b->buf; + *out_buf_offset = peer_b->offset; + return max_available; +} + +int BIO_zero_copy_get_read_buf(BIO* bio, uint8_t** out_read_buf, + size_t* out_buf_offset, + size_t* out_available_bytes) { + struct bio_bio_st* b; + struct bio_bio_st* peer_b; + size_t max_available; + *out_available_bytes = 0; + + BIO_clear_retry_flags(bio); + + if (!bio->init) { + OPENSSL_PUT_ERROR(BIO, BIO_R_UNINITIALIZED); + return 0; + } + + b = bio->ptr; + + if (!b || !b->peer) { + OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD); + return 0; + } + + peer_b = b->peer->ptr; + if (!peer_b || !peer_b->peer || peer_b->peer->ptr != b) { + OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD); + return 0; + } + + if (peer_b->zero_copy_read_lock) { + OPENSSL_PUT_ERROR(BIO, BIO_R_INVALID_ARGUMENT); + return 0; + } + + peer_b->request = 0; /* Is not used by zero-copy API. */ + + max_available = + bio_zero_copy_get_read_buf(peer_b, out_read_buf, out_buf_offset); + + assert(peer_b->buf != NULL); + if (max_available > 0) { + peer_b->zero_copy_read_lock = 1; + } + + *out_available_bytes = max_available; + return 1; +} + +int BIO_zero_copy_get_read_buf_done(BIO* bio, size_t bytes_read) { + struct bio_bio_st* b; + struct bio_bio_st* peer_b; + size_t max_available; + size_t dummy_read_offset; + uint8_t* dummy_read_buf; + + assert(BIO_get_retry_flags(bio) == 0); + + if (!bio->init) { + OPENSSL_PUT_ERROR(BIO, BIO_R_UNINITIALIZED); + return 0; + } + + b = bio->ptr; + + if (!b || !b->peer) { + OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD); + return 0; + } + + peer_b = b->peer->ptr; + if (!peer_b || !peer_b->peer || peer_b->peer->ptr != b) { + OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD); + return 0; + } + + if (!peer_b->zero_copy_read_lock) { + OPENSSL_PUT_ERROR(BIO, BIO_R_INVALID_ARGUMENT); + return 0; + } + + max_available = + bio_zero_copy_get_read_buf(peer_b, &dummy_read_buf, &dummy_read_offset); + if (bytes_read > max_available) { + OPENSSL_PUT_ERROR(BIO, BIO_R_INVALID_ARGUMENT); + return 0; + } + + assert(peer_b->len >= bytes_read); + peer_b->len -= bytes_read; + assert(peer_b->offset + bytes_read <= peer_b->size); + + /* Move read offset. If zero_copy_write_lock == 1 we must advance the + * offset even if buffer becomes empty, to make sure + * write_offset = (offset + len) mod size does not change. */ + if (peer_b->offset + bytes_read == peer_b->size || + (!peer_b->zero_copy_write_lock && peer_b->len == 0)) { + peer_b->offset = 0; + } else { + peer_b->offset += bytes_read; + } + + bio->num_read += bytes_read; + peer_b->zero_copy_read_lock = 0; + return 1; +} + +static size_t bio_zero_copy_get_write_buf(struct bio_bio_st* b, + uint8_t** out_write_buf, + size_t* out_buf_offset) { + size_t write_offset; + size_t max_available; + + assert(b->len <= b->size); + + write_offset = b->offset + b->len; + + if (write_offset >= b->size) { + /* Only the first half of the ring buffer can be written to. */ + write_offset -= b->size; + /* write up to the start of the ring buffer. */ + max_available = b->offset - write_offset; + } else { + /* write up to the end the buffer. */ + max_available = b->size - write_offset; + } + + *out_write_buf = b->buf; + *out_buf_offset = write_offset; + return max_available; +} + +int BIO_zero_copy_get_write_buf(BIO* bio, uint8_t** out_write_buf, + size_t* out_buf_offset, + size_t* out_available_bytes) { + struct bio_bio_st* b; + struct bio_bio_st* peer_b; + size_t max_available; + + *out_available_bytes = 0; + BIO_clear_retry_flags(bio); + + if (!bio->init) { + OPENSSL_PUT_ERROR(BIO, BIO_R_UNINITIALIZED); + return 0; + } + + b = bio->ptr; + + if (!b || !b->buf || !b->peer) { + OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD); + return 0; + } + peer_b = b->peer->ptr; + if (!peer_b || !peer_b->peer || peer_b->peer->ptr != b) { + OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD); + return 0; + } + + assert(b->buf != NULL); + + if (b->zero_copy_write_lock) { + OPENSSL_PUT_ERROR(BIO, BIO_R_INVALID_ARGUMENT); + return 0; + } + + b->request = 0; + if (b->closed) { + /* Bio is already closed. */ + OPENSSL_PUT_ERROR(BIO, BIO_R_BROKEN_PIPE); + return 0; + } + + max_available = bio_zero_copy_get_write_buf(b, out_write_buf, out_buf_offset); + + if (max_available > 0) { + b->zero_copy_write_lock = 1; + } + + *out_available_bytes = max_available; + return 1; +} + +int BIO_zero_copy_get_write_buf_done(BIO* bio, size_t bytes_written) { + struct bio_bio_st* b; + struct bio_bio_st* peer_b; + + size_t rest; + size_t dummy_write_offset; + uint8_t* dummy_write_buf; + + if (!bio->init) { + OPENSSL_PUT_ERROR(BIO, BIO_R_UNINITIALIZED); + return 0; + } + + b = bio->ptr; + + if (!b || !b->buf || !b->peer) { + OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD); + return 0; + } + peer_b = b->peer->ptr; + if (!peer_b || !peer_b->peer || peer_b->peer->ptr != b) { + OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD); + return 0; + } + + b->request = 0; + if (b->closed) { + /* BIO is already closed. */ + OPENSSL_PUT_ERROR(BIO, BIO_R_BROKEN_PIPE); + return 0; + } + + if (!b->zero_copy_write_lock) { + OPENSSL_PUT_ERROR(BIO, BIO_R_INVALID_ARGUMENT); + return 0; + } + + rest = bio_zero_copy_get_write_buf(b, &dummy_write_buf, &dummy_write_offset); + + if (bytes_written > rest) { + OPENSSL_PUT_ERROR(BIO, BIO_R_INVALID_ARGUMENT); + return 0; + } + + bio->num_write += bytes_written; + /* Move write offset. */ + b->len += bytes_written; + b->zero_copy_write_lock = 0; + return 1; +} + +static int bio_read(BIO *bio, char *buf, int size_) { + size_t size = size_; + size_t rest; + struct bio_bio_st *b, *peer_b; + + BIO_clear_retry_flags(bio); + + if (!bio->init) { + return 0; + } + + b = bio->ptr; + assert(b != NULL); + assert(b->peer != NULL); + peer_b = b->peer->ptr; + assert(peer_b != NULL); + assert(peer_b->buf != NULL); + + peer_b->request = 0; /* will be set in "retry_read" situation */ + + if (buf == NULL || size == 0 || peer_b->zero_copy_read_lock) { + return 0; + } + + if (peer_b->len == 0) { + if (peer_b->closed) { + return 0; /* writer has closed, and no data is left */ + } else { + BIO_set_retry_read(bio); /* buffer is empty */ + if (size <= peer_b->size) { + peer_b->request = size; + } else { + /* don't ask for more than the peer can + * deliver in one write */ + peer_b->request = peer_b->size; + } + return -1; + } + } + + /* we can read */ + if (peer_b->len < size) { + size = peer_b->len; + } + + /* now read "size" bytes */ + rest = size; + + assert(rest > 0); + /* one or two iterations */ + do { + size_t chunk; + + assert(rest <= peer_b->len); + if (peer_b->offset + rest <= peer_b->size) { + chunk = rest; + } else { + /* wrap around ring buffer */ + chunk = peer_b->size - peer_b->offset; + } + assert(peer_b->offset + chunk <= peer_b->size); + + memcpy(buf, peer_b->buf + peer_b->offset, chunk); + + peer_b->len -= chunk; + /* If zero_copy_write_lock == 1 we must advance the offset even if buffer + * becomes empty, to make sure write_offset = (offset + len) % size + * does not change. */ + if (peer_b->len || peer_b->zero_copy_write_lock) { + peer_b->offset += chunk; + assert(peer_b->offset <= peer_b->size); + if (peer_b->offset == peer_b->size) { + peer_b->offset = 0; + } + buf += chunk; + } else { + /* buffer now empty, no need to advance "buf" */ + assert(chunk == rest); + peer_b->offset = 0; + } + rest -= chunk; + } while (rest); + + return size; +} + +static int bio_write(BIO *bio, const char *buf, int num_) { + size_t num = num_; + size_t rest; + struct bio_bio_st *b; + + BIO_clear_retry_flags(bio); + + if (!bio->init || buf == NULL || num == 0) { + return 0; + } + + b = bio->ptr; + assert(b != NULL); + assert(b->peer != NULL); + assert(b->buf != NULL); + + if (b->zero_copy_write_lock) { + return 0; + } + + b->request = 0; + if (b->closed) { + /* we already closed */ + OPENSSL_PUT_ERROR(BIO, BIO_R_BROKEN_PIPE); + return -1; + } + + assert(b->len <= b->size); + + if (b->len == b->size) { + BIO_set_retry_write(bio); /* buffer is full */ + return -1; + } + + /* we can write */ + if (num > b->size - b->len) { + num = b->size - b->len; + } + + /* now write "num" bytes */ + rest = num; + + assert(rest > 0); + /* one or two iterations */ + do { + size_t write_offset; + size_t chunk; + + assert(b->len + rest <= b->size); + + write_offset = b->offset + b->len; + if (write_offset >= b->size) { + write_offset -= b->size; + } + /* b->buf[write_offset] is the first byte we can write to. */ + + if (write_offset + rest <= b->size) { + chunk = rest; + } else { + /* wrap around ring buffer */ + chunk = b->size - write_offset; + } + + memcpy(b->buf + write_offset, buf, chunk); + + b->len += chunk; + + assert(b->len <= b->size); + + rest -= chunk; + buf += chunk; + } while (rest); + + return num; +} + +static int bio_make_pair(BIO* bio1, BIO* bio2, + size_t writebuf1_len, uint8_t* ext_writebuf1, + size_t writebuf2_len, uint8_t* ext_writebuf2) { + struct bio_bio_st *b1, *b2; + + assert(bio1 != NULL); + assert(bio2 != NULL); + + b1 = bio1->ptr; + b2 = bio2->ptr; + + if (b1->peer != NULL || b2->peer != NULL) { + OPENSSL_PUT_ERROR(BIO, BIO_R_IN_USE); + return 0; + } + + assert(b1->buf_externally_allocated == 0); + assert(b2->buf_externally_allocated == 0); + + if (b1->buf == NULL) { + if (writebuf1_len) { + b1->size = writebuf1_len; + } + if (!ext_writebuf1) { + b1->buf_externally_allocated = 0; + b1->buf = OPENSSL_malloc(b1->size); + if (b1->buf == NULL) { + OPENSSL_PUT_ERROR(BIO, ERR_R_MALLOC_FAILURE); + return 0; + } + } else { + b1->buf = ext_writebuf1; + b1->buf_externally_allocated = 1; + } + b1->len = 0; + b1->offset = 0; + } + + if (b2->buf == NULL) { + if (writebuf2_len) { + b2->size = writebuf2_len; + } + if (!ext_writebuf2) { + b2->buf_externally_allocated = 0; + b2->buf = OPENSSL_malloc(b2->size); + if (b2->buf == NULL) { + OPENSSL_PUT_ERROR(BIO, ERR_R_MALLOC_FAILURE); + return 0; + } + } else { + b2->buf = ext_writebuf2; + b2->buf_externally_allocated = 1; + } + b2->len = 0; + b2->offset = 0; + } + + b1->peer = bio2; + b1->closed = 0; + b1->request = 0; + b1->zero_copy_read_lock = 0; + b1->zero_copy_write_lock = 0; + b2->peer = bio1; + b2->closed = 0; + b2->request = 0; + b2->zero_copy_read_lock = 0; + b2->zero_copy_write_lock = 0; + + bio1->init = 1; + bio2->init = 1; + + return 1; +} + +static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr) { + long ret; + struct bio_bio_st *b = bio->ptr; + + assert(b != NULL); + + switch (cmd) { + /* specific CTRL codes */ + + case BIO_C_GET_WRITE_BUF_SIZE: + ret = (long)b->size; + break; + + case BIO_C_GET_WRITE_GUARANTEE: + /* How many bytes can the caller feed to the next write + * without having to keep any? */ + if (b->peer == NULL || b->closed) { + ret = 0; + } else { + ret = (long)b->size - b->len; + } + break; + + case BIO_C_GET_READ_REQUEST: + /* If the peer unsuccessfully tried to read, how many bytes + * were requested? (As with BIO_CTRL_PENDING, that number + * can usually be treated as boolean.) */ + ret = (long)b->request; + break; + + case BIO_C_RESET_READ_REQUEST: + /* Reset request. (Can be useful after read attempts + * at the other side that are meant to be non-blocking, + * e.g. when probing SSL_read to see if any data is + * available.) */ + b->request = 0; + ret = 1; + break; + + case BIO_C_SHUTDOWN_WR: + /* similar to shutdown(..., SHUT_WR) */ + b->closed = 1; + ret = 1; + break; + + /* standard CTRL codes follow */ + + case BIO_CTRL_GET_CLOSE: + ret = bio->shutdown; + break; + + case BIO_CTRL_SET_CLOSE: + bio->shutdown = (int)num; + ret = 1; + break; + + case BIO_CTRL_PENDING: + if (b->peer != NULL) { + struct bio_bio_st *peer_b = b->peer->ptr; + ret = (long)peer_b->len; + } else { + ret = 0; + } + break; + + case BIO_CTRL_WPENDING: + ret = 0; + if (b->buf != NULL) { + ret = (long)b->len; + } + break; + + case BIO_CTRL_FLUSH: + ret = 1; + break; + + case BIO_CTRL_EOF: { + BIO *other_bio = ptr; + + if (other_bio) { + struct bio_bio_st *other_b = other_bio->ptr; + assert(other_b != NULL); + ret = other_b->len == 0 && other_b->closed; + } else { + ret = 1; + } + } break; + + default: + ret = 0; + } + return ret; +} + +static int bio_puts(BIO *bio, const char *str) { + return bio_write(bio, str, strlen(str)); +} + +static const BIO_METHOD methods_biop = { + BIO_TYPE_BIO, "BIO pair", bio_write, bio_read, + bio_puts, NULL /* no bio_gets */, bio_ctrl, bio_new, + bio_free, NULL /* no bio_callback_ctrl */ +}; + +static const BIO_METHOD *bio_s_bio(void) { return &methods_biop; } + +int BIO_new_bio_pair(BIO** bio1_p, size_t writebuf1, + BIO** bio2_p, size_t writebuf2) { + return BIO_new_bio_pair_external_buf(bio1_p, writebuf1, NULL, bio2_p, + writebuf2, NULL); +} + +int BIO_new_bio_pair_external_buf(BIO** bio1_p, size_t writebuf1_len, + uint8_t* ext_writebuf1, + BIO** bio2_p, size_t writebuf2_len, + uint8_t* ext_writebuf2) { + BIO *bio1 = NULL, *bio2 = NULL; + int ret = 0; + + /* External buffers must have sizes greater than 0. */ + if ((ext_writebuf1 && !writebuf1_len) || (ext_writebuf2 && !writebuf2_len)) { + goto err; + } + + bio1 = BIO_new(bio_s_bio()); + if (bio1 == NULL) { + goto err; + } + bio2 = BIO_new(bio_s_bio()); + if (bio2 == NULL) { + goto err; + } + + if (!bio_make_pair(bio1, bio2, writebuf1_len, ext_writebuf1, writebuf2_len, + ext_writebuf2)) { + goto err; + } + ret = 1; + +err: + if (ret == 0) { + BIO_free(bio1); + bio1 = NULL; + BIO_free(bio2); + bio2 = NULL; + } + + *bio1_p = bio1; + *bio2_p = bio2; + return ret; +} + +size_t BIO_ctrl_get_read_request(BIO *bio) { + return BIO_ctrl(bio, BIO_C_GET_READ_REQUEST, 0, NULL); +} + +size_t BIO_ctrl_get_write_guarantee(BIO *bio) { + return BIO_ctrl(bio, BIO_C_GET_WRITE_GUARANTEE, 0, NULL); +} + +int BIO_shutdown_wr(BIO *bio) { + return BIO_ctrl(bio, BIO_C_SHUTDOWN_WR, 0, NULL); +} diff --git a/external/boringssl/crypto/bio/printf.c b/external/boringssl/crypto/bio/printf.c new file mode 100644 index 0000000000..3709fcb2b3 --- /dev/null +++ b/external/boringssl/crypto/bio/printf.c @@ -0,0 +1,119 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#if !defined(_POSIX_C_SOURCE) +#define _POSIX_C_SOURCE 201410L /* for snprintf, vprintf etc */ +#endif + +#include + +#include +#include +#include + +#include +#include + +int BIO_printf(BIO *bio, const char *format, ...) { + va_list args; + char buf[256], *out, out_malloced = 0; + int out_len, ret; + + va_start(args, format); + out_len = vsnprintf(buf, sizeof(buf), format, args); + va_end(args); + +#if defined(OPENSSL_WINDOWS) + /* On Windows, vsnprintf returns -1 rather than the requested length on + * truncation */ + if (out_len < 0) { + va_start(args, format); + out_len = _vscprintf(format, args); + va_end(args); + assert(out_len >= sizeof(buf)); + } +#endif + + if (out_len < 0) { + return -1; + } + + if ((size_t) out_len >= sizeof(buf)) { + const int requested_len = out_len; + /* The output was truncated. Note that vsnprintf's return value + * does not include a trailing NUL, but the buffer must be sized + * for it. */ + out = OPENSSL_malloc(requested_len + 1); + out_malloced = 1; + if (out == NULL) { + OPENSSL_PUT_ERROR(BIO, ERR_R_MALLOC_FAILURE); + return -1; + } + va_start(args, format); + out_len = vsnprintf(out, requested_len + 1, format, args); + va_end(args); + assert(out_len == requested_len); + } else { + out = buf; + } + + ret = BIO_write(bio, out, out_len); + if (out_malloced) { + OPENSSL_free(out); + } + + return ret; +} diff --git a/external/boringssl/crypto/bio/socket.c b/external/boringssl/crypto/bio/socket.c new file mode 100644 index 0000000000..0520c3e830 --- /dev/null +++ b/external/boringssl/crypto/bio/socket.c @@ -0,0 +1,203 @@ +/* crypto/bio/bss_sock.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +#if !defined(OPENSSL_WINDOWS) +#include +#else +OPENSSL_MSVC_PRAGMA(warning(push, 3)) +#include +OPENSSL_MSVC_PRAGMA(warning(pop)) + +#pragma comment(lib, "Ws2_32.lib") +#endif + +#include "internal.h" + + +#if !defined(OPENSSL_WINDOWS) +static int closesocket(int sock) { + return close(sock); +} +#endif + +static int sock_new(BIO *bio) { + bio->init = 0; + bio->num = 0; + bio->ptr = NULL; + bio->flags = 0; + return 1; +} + +static int sock_free(BIO *bio) { + if (bio == NULL) { + return 0; + } + + if (bio->shutdown) { + if (bio->init) { + closesocket(bio->num); + } + bio->init = 0; + bio->flags = 0; + } + return 1; +} + +static int sock_read(BIO *b, char *out, int outl) { + int ret = 0; + + if (out == NULL) { + return 0; + } + + bio_clear_socket_error(); +#if defined(OPENSSL_WINDOWS) + ret = recv(b->num, out, outl, 0); +#else + ret = read(b->num, out, outl); +#endif + BIO_clear_retry_flags(b); + if (ret <= 0) { + if (bio_fd_should_retry(ret)) { + BIO_set_retry_read(b); + } + } + return ret; +} + +static int sock_write(BIO *b, const char *in, int inl) { + int ret; + + bio_clear_socket_error(); +#if defined(OPENSSL_WINDOWS) + ret = send(b->num, in, inl, 0); +#else + ret = write(b->num, in, inl); +#endif + BIO_clear_retry_flags(b); + if (ret <= 0) { + if (bio_fd_should_retry(ret)) { + BIO_set_retry_write(b); + } + } + return ret; +} + +static int sock_puts(BIO *bp, const char *str) { + return sock_write(bp, str, strlen(str)); +} + +static long sock_ctrl(BIO *b, int cmd, long num, void *ptr) { + long ret = 1; + int *ip; + + switch (cmd) { + case BIO_C_SET_FD: + sock_free(b); + b->num = *((int *)ptr); + b->shutdown = (int)num; + b->init = 1; + break; + case BIO_C_GET_FD: + if (b->init) { + ip = (int *)ptr; + if (ip != NULL) { + *ip = b->num; + } + ret = b->num; + } else { + ret = -1; + } + break; + case BIO_CTRL_GET_CLOSE: + ret = b->shutdown; + break; + case BIO_CTRL_SET_CLOSE: + b->shutdown = (int)num; + break; + case BIO_CTRL_FLUSH: + ret = 1; + break; + default: + ret = 0; + break; + } + return ret; +} + +static const BIO_METHOD methods_sockp = { + BIO_TYPE_SOCKET, "socket", sock_write, sock_read, sock_puts, + NULL /* gets, */, sock_ctrl, sock_new, sock_free, NULL, +}; + +const BIO_METHOD *BIO_s_socket(void) { return &methods_sockp; } + +BIO *BIO_new_socket(int fd, int close_flag) { + BIO *ret; + + ret = BIO_new(BIO_s_socket()); + if (ret == NULL) { + return NULL; + } + BIO_set_fd(ret, fd, close_flag); + return ret; +} diff --git a/external/boringssl/crypto/bio/socket_helper.c b/external/boringssl/crypto/bio/socket_helper.c new file mode 100644 index 0000000000..950078845a --- /dev/null +++ b/external/boringssl/crypto/bio/socket_helper.c @@ -0,0 +1,113 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#undef _POSIX_C_SOURCE +#define _POSIX_C_SOURCE 200112L + +#include +#include + +#include +#include +#include + +#if !defined(OPENSSL_WINDOWS) +#include +#include +#else +OPENSSL_MSVC_PRAGMA(warning(push, 3)) +#include +#include +OPENSSL_MSVC_PRAGMA(warning(pop)) +#endif + +#include "internal.h" + + +int bio_ip_and_port_to_socket_and_addr(int *out_sock, + struct sockaddr_storage *out_addr, + socklen_t *out_addr_length, + const char *hostname, + const char *port_str) { + struct addrinfo hint, *result, *cur; + int ret; + + *out_sock = -1; + + memset(&hint, 0, sizeof(hint)); + hint.ai_family = AF_UNSPEC; + hint.ai_socktype = SOCK_STREAM; + + ret = getaddrinfo(hostname, port_str, &hint, &result); + if (ret != 0) { + OPENSSL_PUT_ERROR(SYS, 0); + ERR_add_error_data(1, gai_strerror(ret)); + return 0; + } + + ret = 0; + + for (cur = result; cur; cur = cur->ai_next) { + if ((size_t) cur->ai_addrlen > sizeof(struct sockaddr_storage)) { + continue; + } + memset(out_addr, 0, sizeof(struct sockaddr_storage)); + memcpy(out_addr, cur->ai_addr, cur->ai_addrlen); + *out_addr_length = cur->ai_addrlen; + + *out_sock = socket(cur->ai_family, cur->ai_socktype, cur->ai_protocol); + if (*out_sock < 0) { + OPENSSL_PUT_SYSTEM_ERROR(); + goto out; + } + + ret = 1; + break; + } + +out: + freeaddrinfo(result); + return ret; +} + +int bio_socket_nbio(int sock, int on) { +#if defined(OPENSSL_WINDOWS) + u_long arg = on; + + return 0 == ioctlsocket(sock, FIONBIO, &arg); +#else + int flags = fcntl(sock, F_GETFL, 0); + if (flags < 0) { + return 0; + } + if (!on) { + flags &= ~O_NONBLOCK; + } else { + flags |= O_NONBLOCK; + } + return fcntl(sock, F_SETFL, flags) == 0; +#endif +} + +void bio_clear_socket_error(void) {} + +int bio_sock_error(int sock) { + int error; + socklen_t error_size = sizeof(error); + + if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (char *)&error, &error_size) < 0) { + return 1; + } + return error; +} diff --git a/external/boringssl/crypto/bn/CMakeLists.txt b/external/boringssl/crypto/bn/CMakeLists.txt new file mode 100644 index 0000000000..81bca4d2e1 --- /dev/null +++ b/external/boringssl/crypto/bn/CMakeLists.txt @@ -0,0 +1,90 @@ +include_directories(../../include) + +if (${ARCH} STREQUAL "x86_64") + set( + BN_ARCH_SOURCES + + x86_64-mont.${ASM_EXT} + x86_64-mont5.${ASM_EXT} + rsaz-x86_64.${ASM_EXT} + rsaz-avx2.${ASM_EXT} + + rsaz_exp.c + ) +endif() + +if (${ARCH} STREQUAL "x86") + set( + BN_ARCH_SOURCES + + bn-586.${ASM_EXT} + co-586.${ASM_EXT} + x86-mont.${ASM_EXT} + ) +endif() + +if (${ARCH} STREQUAL "arm") + set( + BN_ARCH_SOURCES + + armv4-mont.${ASM_EXT} + ) +endif() + +if (${ARCH} STREQUAL "aarch64") + set( + BN_ARCH_SOURCES + + armv8-mont.${ASM_EXT} + ) +endif() + +add_library( + bn + + OBJECT + + add.c + asm/x86_64-gcc.c + bn.c + bn_asn1.c + cmp.c + convert.c + ctx.c + div.c + exponentiation.c + generic.c + gcd.c + kronecker.c + montgomery.c + mul.c + prime.c + random.c + shift.c + sqrt.c + + ${BN_ARCH_SOURCES} +) + +perlasm(x86_64-mont.${ASM_EXT} asm/x86_64-mont.pl) +perlasm(x86_64-mont5.${ASM_EXT} asm/x86_64-mont5.pl) +perlasm(rsaz-x86_64.${ASM_EXT} asm/rsaz-x86_64.pl) +perlasm(rsaz-avx2.${ASM_EXT} asm/rsaz-avx2.pl) +perlasm(bn-586.${ASM_EXT} asm/bn-586.pl) +perlasm(co-586.${ASM_EXT} asm/co-586.pl) +perlasm(x86-mont.${ASM_EXT} asm/x86-mont.pl) +perlasm(armv4-mont.${ASM_EXT} asm/armv4-mont.pl) +perlasm(armv8-mont.${ASM_EXT} asm/armv8-mont.pl) + +if(ENABLE_TESTS) +add_executable( + bn_test + + bn_test.cc + + $ +) + +target_link_libraries(bn_test crypto) +add_dependencies(all_tests bn_test) +endif() diff --git a/external/boringssl/crypto/bn/add.c b/external/boringssl/crypto/bn/add.c new file mode 100644 index 0000000000..23f9f802ce --- /dev/null +++ b/external/boringssl/crypto/bn/add.c @@ -0,0 +1,377 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include +#include + +#include "internal.h" + + +int BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) { + const BIGNUM *tmp; + int a_neg = a->neg, ret; + + /* a + b a+b + * a + -b a-b + * -a + b b-a + * -a + -b -(a+b) + */ + if (a_neg ^ b->neg) { + /* only one is negative */ + if (a_neg) { + tmp = a; + a = b; + b = tmp; + } + + /* we are now a - b */ + if (BN_ucmp(a, b) < 0) { + if (!BN_usub(r, b, a)) { + return 0; + } + r->neg = 1; + } else { + if (!BN_usub(r, a, b)) { + return 0; + } + r->neg = 0; + } + return 1; + } + + ret = BN_uadd(r, a, b); + r->neg = a_neg; + return ret; +} + +int BN_uadd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) { + int max, min, dif; + BN_ULONG *ap, *bp, *rp, carry, t1, t2; + const BIGNUM *tmp; + + if (a->top < b->top) { + tmp = a; + a = b; + b = tmp; + } + max = a->top; + min = b->top; + dif = max - min; + + if (bn_wexpand(r, max + 1) == NULL) { + return 0; + } + + r->top = max; + + ap = a->d; + bp = b->d; + rp = r->d; + + carry = bn_add_words(rp, ap, bp, min); + rp += min; + ap += min; + bp += min; + + if (carry) { + while (dif) { + dif--; + t1 = *(ap++); + t2 = (t1 + 1) & BN_MASK2; + *(rp++) = t2; + if (t2) { + carry = 0; + break; + } + } + if (carry) { + /* carry != 0 => dif == 0 */ + *rp = 1; + r->top++; + } + } + + if (dif && rp != ap) { + while (dif--) { + /* copy remaining words if ap != rp */ + *(rp++) = *(ap++); + } + } + + r->neg = 0; + return 1; +} + +int BN_add_word(BIGNUM *a, BN_ULONG w) { + BN_ULONG l; + int i; + + w &= BN_MASK2; + + /* degenerate case: w is zero */ + if (!w) { + return 1; + } + + /* degenerate case: a is zero */ + if (BN_is_zero(a)) { + return BN_set_word(a, w); + } + + /* handle 'a' when negative */ + if (a->neg) { + a->neg = 0; + i = BN_sub_word(a, w); + if (!BN_is_zero(a)) { + a->neg = !(a->neg); + } + return i; + } + + for (i = 0; w != 0 && i < a->top; i++) { + a->d[i] = l = (a->d[i] + w) & BN_MASK2; + w = (w > l) ? 1 : 0; + } + + if (w && i == a->top) { + if (bn_wexpand(a, a->top + 1) == NULL) { + return 0; + } + a->top++; + a->d[i] = w; + } + + return 1; +} + +int BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) { + int max; + int add = 0, neg = 0; + const BIGNUM *tmp; + + /* a - b a-b + * a - -b a+b + * -a - b -(a+b) + * -a - -b b-a + */ + if (a->neg) { + if (b->neg) { + tmp = a; + a = b; + b = tmp; + } else { + add = 1; + neg = 1; + } + } else { + if (b->neg) { + add = 1; + neg = 0; + } + } + + if (add) { + if (!BN_uadd(r, a, b)) { + return 0; + } + + r->neg = neg; + return 1; + } + + /* We are actually doing a - b :-) */ + + max = (a->top > b->top) ? a->top : b->top; + if (bn_wexpand(r, max) == NULL) { + return 0; + } + + if (BN_ucmp(a, b) < 0) { + if (!BN_usub(r, b, a)) { + return 0; + } + r->neg = 1; + } else { + if (!BN_usub(r, a, b)) { + return 0; + } + r->neg = 0; + } + + return 1; +} + +int BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) { + int max, min, dif; + register BN_ULONG t1, t2, *ap, *bp, *rp; + int i, carry; + + max = a->top; + min = b->top; + dif = max - min; + + if (dif < 0) /* hmm... should not be happening */ + { + OPENSSL_PUT_ERROR(BN, BN_R_ARG2_LT_ARG3); + return 0; + } + + if (bn_wexpand(r, max) == NULL) { + return 0; + } + + ap = a->d; + bp = b->d; + rp = r->d; + + carry = 0; + for (i = min; i != 0; i--) { + t1 = *(ap++); + t2 = *(bp++); + if (carry) { + carry = (t1 <= t2); + t1 = (t1 - t2 - 1) & BN_MASK2; + } else { + carry = (t1 < t2); + t1 = (t1 - t2) & BN_MASK2; + } + *(rp++) = t1 & BN_MASK2; + } + + if (carry) /* subtracted */ + { + if (!dif) { + /* error: a < b */ + return 0; + } + + while (dif) { + dif--; + t1 = *(ap++); + t2 = (t1 - 1) & BN_MASK2; + *(rp++) = t2; + if (t1) { + break; + } + } + } + + if (dif > 0 && rp != ap) { + memcpy(rp, ap, sizeof(*rp) * dif); + } + + r->top = max; + r->neg = 0; + bn_correct_top(r); + + return 1; +} + +int BN_sub_word(BIGNUM *a, BN_ULONG w) { + int i; + + w &= BN_MASK2; + + /* degenerate case: w is zero */ + if (!w) { + return 1; + } + + /* degenerate case: a is zero */ + if (BN_is_zero(a)) { + i = BN_set_word(a, w); + if (i != 0) { + BN_set_negative(a, 1); + } + return i; + } + + /* handle 'a' when negative */ + if (a->neg) { + a->neg = 0; + i = BN_add_word(a, w); + a->neg = 1; + return i; + } + + if ((a->top == 1) && (a->d[0] < w)) { + a->d[0] = w - a->d[0]; + a->neg = 1; + return 1; + } + + i = 0; + for (;;) { + if (a->d[i] >= w) { + a->d[i] -= w; + break; + } else { + a->d[i] = (a->d[i] - w) & BN_MASK2; + i++; + w = 1; + } + } + + if ((a->d[i] == 0) && (i == (a->top - 1))) { + a->top--; + } + + return 1; +} diff --git a/external/boringssl/crypto/bn/asm/armv4-mont.pl b/external/boringssl/crypto/bn/asm/armv4-mont.pl new file mode 100644 index 0000000000..b75111288f --- /dev/null +++ b/external/boringssl/crypto/bn/asm/armv4-mont.pl @@ -0,0 +1,693 @@ +#!/usr/bin/env perl + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== + +# January 2007. + +# Montgomery multiplication for ARMv4. +# +# Performance improvement naturally varies among CPU implementations +# and compilers. The code was observed to provide +65-35% improvement +# [depending on key length, less for longer keys] on ARM920T, and +# +115-80% on Intel IXP425. This is compared to pre-bn_mul_mont code +# base and compiler generated code with in-lined umull and even umlal +# instructions. The latter means that this code didn't really have an +# "advantage" of utilizing some "secret" instruction. +# +# The code is interoperable with Thumb ISA and is rather compact, less +# than 1/2KB. Windows CE port would be trivial, as it's exclusively +# about decorations, ABI and instruction syntax are identical. + +# November 2013 +# +# Add NEON code path, which handles lengths divisible by 8. RSA/DSA +# performance improvement on Cortex-A8 is ~45-100% depending on key +# length, more for longer keys. On Cortex-A15 the span is ~10-105%. +# On Snapdragon S4 improvement was measured to vary from ~70% to +# incredible ~380%, yes, 4.8x faster, for RSA4096 sign. But this is +# rather because original integer-only code seems to perform +# suboptimally on S4. Situation on Cortex-A9 is unfortunately +# different. It's being looked into, but the trouble is that +# performance for vectors longer than 256 bits is actually couple +# of percent worse than for integer-only code. The code is chosen +# for execution on all NEON-capable processors, because gain on +# others outweighs the marginal loss on Cortex-A9. + +$flavour = shift; +if ($flavour=~/^\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; } +else { while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {} } + +if ($flavour && $flavour ne "void") { + $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; + ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or + ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or + die "can't locate arm-xlate.pl"; + + open STDOUT,"| \"$^X\" $xlate $flavour $output"; +} else { + open STDOUT,">$output"; +} + +$num="r0"; # starts as num argument, but holds &tp[num-1] +$ap="r1"; +$bp="r2"; $bi="r2"; $rp="r2"; +$np="r3"; +$tp="r4"; +$aj="r5"; +$nj="r6"; +$tj="r7"; +$n0="r8"; +########### # r9 is reserved by ELF as platform specific, e.g. TLS pointer +$alo="r10"; # sl, gcc uses it to keep @GOT +$ahi="r11"; # fp +$nlo="r12"; # ip +########### # r13 is stack pointer +$nhi="r14"; # lr +########### # r15 is program counter + +#### argument block layout relative to &tp[num-1], a.k.a. $num +$_rp="$num,#12*4"; +# ap permanently resides in r1 +$_bp="$num,#13*4"; +# np permanently resides in r3 +$_n0="$num,#14*4"; +$_num="$num,#15*4"; $_bpend=$_num; + +$code=<<___; +#include + +.text +.code 32 + +#if __ARM_MAX_ARCH__>=7 +.align 5 +.LOPENSSL_armcap: +.word OPENSSL_armcap_P-.Lbn_mul_mont +#endif + +.global bn_mul_mont +.type bn_mul_mont,%function + +.align 5 +bn_mul_mont: +.Lbn_mul_mont: + ldr ip,[sp,#4] @ load num + stmdb sp!,{r0,r2} @ sp points at argument block +#if __ARM_MAX_ARCH__>=7 + tst ip,#7 + bne .Lialu + adr r0,bn_mul_mont + ldr r2,.LOPENSSL_armcap + ldr r0,[r0,r2] +#ifdef __APPLE__ + ldr r0,[r0] +#endif + tst r0,#ARMV7_NEON @ NEON available? + ldmia sp, {r0,r2} + beq .Lialu + add sp,sp,#8 + b bn_mul8x_mont_neon +.align 4 +.Lialu: +#endif + cmp ip,#2 + mov $num,ip @ load num + movlt r0,#0 + addlt sp,sp,#2*4 + blt .Labrt + + stmdb sp!,{r4-r12,lr} @ save 10 registers + + mov $num,$num,lsl#2 @ rescale $num for byte count + sub sp,sp,$num @ alloca(4*num) + sub sp,sp,#4 @ +extra dword + sub $num,$num,#4 @ "num=num-1" + add $tp,$bp,$num @ &bp[num-1] + + add $num,sp,$num @ $num to point at &tp[num-1] + ldr $n0,[$_n0] @ &n0 + ldr $bi,[$bp] @ bp[0] + ldr $aj,[$ap],#4 @ ap[0],ap++ + ldr $nj,[$np],#4 @ np[0],np++ + ldr $n0,[$n0] @ *n0 + str $tp,[$_bpend] @ save &bp[num] + + umull $alo,$ahi,$aj,$bi @ ap[0]*bp[0] + str $n0,[$_n0] @ save n0 value + mul $n0,$alo,$n0 @ "tp[0]"*n0 + mov $nlo,#0 + umlal $alo,$nlo,$nj,$n0 @ np[0]*n0+"t[0]" + mov $tp,sp + +.L1st: + ldr $aj,[$ap],#4 @ ap[j],ap++ + mov $alo,$ahi + ldr $nj,[$np],#4 @ np[j],np++ + mov $ahi,#0 + umlal $alo,$ahi,$aj,$bi @ ap[j]*bp[0] + mov $nhi,#0 + umlal $nlo,$nhi,$nj,$n0 @ np[j]*n0 + adds $nlo,$nlo,$alo + str $nlo,[$tp],#4 @ tp[j-1]=,tp++ + adc $nlo,$nhi,#0 + cmp $tp,$num + bne .L1st + + adds $nlo,$nlo,$ahi + ldr $tp,[$_bp] @ restore bp + mov $nhi,#0 + ldr $n0,[$_n0] @ restore n0 + adc $nhi,$nhi,#0 + str $nlo,[$num] @ tp[num-1]= + str $nhi,[$num,#4] @ tp[num]= + +.Louter: + sub $tj,$num,sp @ "original" $num-1 value + sub $ap,$ap,$tj @ "rewind" ap to &ap[1] + ldr $bi,[$tp,#4]! @ *(++bp) + sub $np,$np,$tj @ "rewind" np to &np[1] + ldr $aj,[$ap,#-4] @ ap[0] + ldr $alo,[sp] @ tp[0] + ldr $nj,[$np,#-4] @ np[0] + ldr $tj,[sp,#4] @ tp[1] + + mov $ahi,#0 + umlal $alo,$ahi,$aj,$bi @ ap[0]*bp[i]+tp[0] + str $tp,[$_bp] @ save bp + mul $n0,$alo,$n0 + mov $nlo,#0 + umlal $alo,$nlo,$nj,$n0 @ np[0]*n0+"tp[0]" + mov $tp,sp + +.Linner: + ldr $aj,[$ap],#4 @ ap[j],ap++ + adds $alo,$ahi,$tj @ +=tp[j] + ldr $nj,[$np],#4 @ np[j],np++ + mov $ahi,#0 + umlal $alo,$ahi,$aj,$bi @ ap[j]*bp[i] + mov $nhi,#0 + umlal $nlo,$nhi,$nj,$n0 @ np[j]*n0 + adc $ahi,$ahi,#0 + ldr $tj,[$tp,#8] @ tp[j+1] + adds $nlo,$nlo,$alo + str $nlo,[$tp],#4 @ tp[j-1]=,tp++ + adc $nlo,$nhi,#0 + cmp $tp,$num + bne .Linner + + adds $nlo,$nlo,$ahi + mov $nhi,#0 + ldr $tp,[$_bp] @ restore bp + adc $nhi,$nhi,#0 + ldr $n0,[$_n0] @ restore n0 + adds $nlo,$nlo,$tj + ldr $tj,[$_bpend] @ restore &bp[num] + adc $nhi,$nhi,#0 + str $nlo,[$num] @ tp[num-1]= + str $nhi,[$num,#4] @ tp[num]= + + cmp $tp,$tj + bne .Louter + + ldr $rp,[$_rp] @ pull rp + add $num,$num,#4 @ $num to point at &tp[num] + sub $aj,$num,sp @ "original" num value + mov $tp,sp @ "rewind" $tp + mov $ap,$tp @ "borrow" $ap + sub $np,$np,$aj @ "rewind" $np to &np[0] + + subs $tj,$tj,$tj @ "clear" carry flag +.Lsub: ldr $tj,[$tp],#4 + ldr $nj,[$np],#4 + sbcs $tj,$tj,$nj @ tp[j]-np[j] + str $tj,[$rp],#4 @ rp[j]= + teq $tp,$num @ preserve carry + bne .Lsub + sbcs $nhi,$nhi,#0 @ upmost carry + mov $tp,sp @ "rewind" $tp + sub $rp,$rp,$aj @ "rewind" $rp + + and $ap,$tp,$nhi + bic $np,$rp,$nhi + orr $ap,$ap,$np @ ap=borrow?tp:rp + +.Lcopy: ldr $tj,[$ap],#4 @ copy or in-place refresh + str sp,[$tp],#4 @ zap tp + str $tj,[$rp],#4 + cmp $tp,$num + bne .Lcopy + + add sp,$num,#4 @ skip over tp[num+1] + ldmia sp!,{r4-r12,lr} @ restore registers + add sp,sp,#2*4 @ skip over {r0,r2} + mov r0,#1 +.Labrt: +#if __ARM_ARCH__>=5 + ret @ bx lr +#else + tst lr,#1 + moveq pc,lr @ be binary compatible with V4, yet + bx lr @ interoperable with Thumb ISA:-) +#endif +.size bn_mul_mont,.-bn_mul_mont +___ +{ +sub Dlo() { shift=~m|q([1]?[0-9])|?"d".($1*2):""; } +sub Dhi() { shift=~m|q([1]?[0-9])|?"d".($1*2+1):""; } + +my ($A0,$A1,$A2,$A3)=map("d$_",(0..3)); +my ($N0,$N1,$N2,$N3)=map("d$_",(4..7)); +my ($Z,$Temp)=("q4","q5"); +my ($A0xB,$A1xB,$A2xB,$A3xB,$A4xB,$A5xB,$A6xB,$A7xB)=map("q$_",(6..13)); +my ($Bi,$Ni,$M0)=map("d$_",(28..31)); +my $zero=&Dlo($Z); +my $temp=&Dlo($Temp); + +my ($rptr,$aptr,$bptr,$nptr,$n0,$num)=map("r$_",(0..5)); +my ($tinptr,$toutptr,$inner,$outer)=map("r$_",(6..9)); + +$code.=<<___; +#if __ARM_MAX_ARCH__>=7 +.arch armv7-a +.fpu neon + +.type bn_mul8x_mont_neon,%function +.align 5 +bn_mul8x_mont_neon: + mov ip,sp + stmdb sp!,{r4-r11} + vstmdb sp!,{d8-d15} @ ABI specification says so + ldmia ip,{r4-r5} @ load rest of parameter block + + sub $toutptr,sp,#16 + vld1.32 {${Bi}[0]}, [$bptr,:32]! + sub $toutptr,$toutptr,$num,lsl#4 + vld1.32 {$A0-$A3}, [$aptr]! @ can't specify :32 :-( + and $toutptr,$toutptr,#-64 + vld1.32 {${M0}[0]}, [$n0,:32] + mov sp,$toutptr @ alloca + veor $zero,$zero,$zero + subs $inner,$num,#8 + vzip.16 $Bi,$zero + + vmull.u32 $A0xB,$Bi,${A0}[0] + vmull.u32 $A1xB,$Bi,${A0}[1] + vmull.u32 $A2xB,$Bi,${A1}[0] + vshl.i64 $temp,`&Dhi("$A0xB")`,#16 + vmull.u32 $A3xB,$Bi,${A1}[1] + + vadd.u64 $temp,$temp,`&Dlo("$A0xB")` + veor $zero,$zero,$zero + vmul.u32 $Ni,$temp,$M0 + + vmull.u32 $A4xB,$Bi,${A2}[0] + vld1.32 {$N0-$N3}, [$nptr]! + vmull.u32 $A5xB,$Bi,${A2}[1] + vmull.u32 $A6xB,$Bi,${A3}[0] + vzip.16 $Ni,$zero + vmull.u32 $A7xB,$Bi,${A3}[1] + + bne .LNEON_1st + + @ special case for num=8, everything is in register bank... + + vmlal.u32 $A0xB,$Ni,${N0}[0] + sub $outer,$num,#1 + vmlal.u32 $A1xB,$Ni,${N0}[1] + vmlal.u32 $A2xB,$Ni,${N1}[0] + vmlal.u32 $A3xB,$Ni,${N1}[1] + + vmlal.u32 $A4xB,$Ni,${N2}[0] + vmov $Temp,$A0xB + vmlal.u32 $A5xB,$Ni,${N2}[1] + vmov $A0xB,$A1xB + vmlal.u32 $A6xB,$Ni,${N3}[0] + vmov $A1xB,$A2xB + vmlal.u32 $A7xB,$Ni,${N3}[1] + vmov $A2xB,$A3xB + vmov $A3xB,$A4xB + vshr.u64 $temp,$temp,#16 + vmov $A4xB,$A5xB + vmov $A5xB,$A6xB + vadd.u64 $temp,$temp,`&Dhi("$Temp")` + vmov $A6xB,$A7xB + veor $A7xB,$A7xB + vshr.u64 $temp,$temp,#16 + + b .LNEON_outer8 + +.align 4 +.LNEON_outer8: + vld1.32 {${Bi}[0]}, [$bptr,:32]! + veor $zero,$zero,$zero + vzip.16 $Bi,$zero + vadd.u64 `&Dlo("$A0xB")`,`&Dlo("$A0xB")`,$temp + + vmlal.u32 $A0xB,$Bi,${A0}[0] + vmlal.u32 $A1xB,$Bi,${A0}[1] + vmlal.u32 $A2xB,$Bi,${A1}[0] + vshl.i64 $temp,`&Dhi("$A0xB")`,#16 + vmlal.u32 $A3xB,$Bi,${A1}[1] + + vadd.u64 $temp,$temp,`&Dlo("$A0xB")` + veor $zero,$zero,$zero + subs $outer,$outer,#1 + vmul.u32 $Ni,$temp,$M0 + + vmlal.u32 $A4xB,$Bi,${A2}[0] + vmlal.u32 $A5xB,$Bi,${A2}[1] + vmlal.u32 $A6xB,$Bi,${A3}[0] + vzip.16 $Ni,$zero + vmlal.u32 $A7xB,$Bi,${A3}[1] + + vmlal.u32 $A0xB,$Ni,${N0}[0] + vmlal.u32 $A1xB,$Ni,${N0}[1] + vmlal.u32 $A2xB,$Ni,${N1}[0] + vmlal.u32 $A3xB,$Ni,${N1}[1] + + vmlal.u32 $A4xB,$Ni,${N2}[0] + vmov $Temp,$A0xB + vmlal.u32 $A5xB,$Ni,${N2}[1] + vmov $A0xB,$A1xB + vmlal.u32 $A6xB,$Ni,${N3}[0] + vmov $A1xB,$A2xB + vmlal.u32 $A7xB,$Ni,${N3}[1] + vmov $A2xB,$A3xB + vmov $A3xB,$A4xB + vshr.u64 $temp,$temp,#16 + vmov $A4xB,$A5xB + vmov $A5xB,$A6xB + vadd.u64 $temp,$temp,`&Dhi("$Temp")` + vmov $A6xB,$A7xB + veor $A7xB,$A7xB + vshr.u64 $temp,$temp,#16 + + bne .LNEON_outer8 + + vadd.u64 `&Dlo("$A0xB")`,`&Dlo("$A0xB")`,$temp + mov $toutptr,sp + vshr.u64 $temp,`&Dlo("$A0xB")`,#16 + mov $inner,$num + vadd.u64 `&Dhi("$A0xB")`,`&Dhi("$A0xB")`,$temp + add $tinptr,sp,#16 + vshr.u64 $temp,`&Dhi("$A0xB")`,#16 + vzip.16 `&Dlo("$A0xB")`,`&Dhi("$A0xB")` + + b .LNEON_tail2 + +.align 4 +.LNEON_1st: + vmlal.u32 $A0xB,$Ni,${N0}[0] + vld1.32 {$A0-$A3}, [$aptr]! + vmlal.u32 $A1xB,$Ni,${N0}[1] + subs $inner,$inner,#8 + vmlal.u32 $A2xB,$Ni,${N1}[0] + vmlal.u32 $A3xB,$Ni,${N1}[1] + + vmlal.u32 $A4xB,$Ni,${N2}[0] + vld1.32 {$N0-$N1}, [$nptr]! + vmlal.u32 $A5xB,$Ni,${N2}[1] + vst1.64 {$A0xB-$A1xB}, [$toutptr,:256]! + vmlal.u32 $A6xB,$Ni,${N3}[0] + vmlal.u32 $A7xB,$Ni,${N3}[1] + vst1.64 {$A2xB-$A3xB}, [$toutptr,:256]! + + vmull.u32 $A0xB,$Bi,${A0}[0] + vld1.32 {$N2-$N3}, [$nptr]! + vmull.u32 $A1xB,$Bi,${A0}[1] + vst1.64 {$A4xB-$A5xB}, [$toutptr,:256]! + vmull.u32 $A2xB,$Bi,${A1}[0] + vmull.u32 $A3xB,$Bi,${A1}[1] + vst1.64 {$A6xB-$A7xB}, [$toutptr,:256]! + + vmull.u32 $A4xB,$Bi,${A2}[0] + vmull.u32 $A5xB,$Bi,${A2}[1] + vmull.u32 $A6xB,$Bi,${A3}[0] + vmull.u32 $A7xB,$Bi,${A3}[1] + + bne .LNEON_1st + + vmlal.u32 $A0xB,$Ni,${N0}[0] + add $tinptr,sp,#16 + vmlal.u32 $A1xB,$Ni,${N0}[1] + sub $aptr,$aptr,$num,lsl#2 @ rewind $aptr + vmlal.u32 $A2xB,$Ni,${N1}[0] + vld1.64 {$Temp}, [sp,:128] + vmlal.u32 $A3xB,$Ni,${N1}[1] + sub $outer,$num,#1 + + vmlal.u32 $A4xB,$Ni,${N2}[0] + vst1.64 {$A0xB-$A1xB}, [$toutptr,:256]! + vmlal.u32 $A5xB,$Ni,${N2}[1] + vshr.u64 $temp,$temp,#16 + vld1.64 {$A0xB}, [$tinptr, :128]! + vmlal.u32 $A6xB,$Ni,${N3}[0] + vst1.64 {$A2xB-$A3xB}, [$toutptr,:256]! + vmlal.u32 $A7xB,$Ni,${N3}[1] + + vst1.64 {$A4xB-$A5xB}, [$toutptr,:256]! + vadd.u64 $temp,$temp,`&Dhi("$Temp")` + veor $Z,$Z,$Z + vst1.64 {$A6xB-$A7xB}, [$toutptr,:256]! + vld1.64 {$A1xB-$A2xB}, [$tinptr, :256]! + vst1.64 {$Z}, [$toutptr,:128] + vshr.u64 $temp,$temp,#16 + + b .LNEON_outer + +.align 4 +.LNEON_outer: + vld1.32 {${Bi}[0]}, [$bptr,:32]! + sub $nptr,$nptr,$num,lsl#2 @ rewind $nptr + vld1.32 {$A0-$A3}, [$aptr]! + veor $zero,$zero,$zero + mov $toutptr,sp + vzip.16 $Bi,$zero + sub $inner,$num,#8 + vadd.u64 `&Dlo("$A0xB")`,`&Dlo("$A0xB")`,$temp + + vmlal.u32 $A0xB,$Bi,${A0}[0] + vld1.64 {$A3xB-$A4xB},[$tinptr,:256]! + vmlal.u32 $A1xB,$Bi,${A0}[1] + vmlal.u32 $A2xB,$Bi,${A1}[0] + vld1.64 {$A5xB-$A6xB},[$tinptr,:256]! + vmlal.u32 $A3xB,$Bi,${A1}[1] + + vshl.i64 $temp,`&Dhi("$A0xB")`,#16 + veor $zero,$zero,$zero + vadd.u64 $temp,$temp,`&Dlo("$A0xB")` + vld1.64 {$A7xB},[$tinptr,:128]! + vmul.u32 $Ni,$temp,$M0 + + vmlal.u32 $A4xB,$Bi,${A2}[0] + vld1.32 {$N0-$N3}, [$nptr]! + vmlal.u32 $A5xB,$Bi,${A2}[1] + vmlal.u32 $A6xB,$Bi,${A3}[0] + vzip.16 $Ni,$zero + vmlal.u32 $A7xB,$Bi,${A3}[1] + +.LNEON_inner: + vmlal.u32 $A0xB,$Ni,${N0}[0] + vld1.32 {$A0-$A3}, [$aptr]! + vmlal.u32 $A1xB,$Ni,${N0}[1] + subs $inner,$inner,#8 + vmlal.u32 $A2xB,$Ni,${N1}[0] + vmlal.u32 $A3xB,$Ni,${N1}[1] + vst1.64 {$A0xB-$A1xB}, [$toutptr,:256]! + + vmlal.u32 $A4xB,$Ni,${N2}[0] + vld1.64 {$A0xB}, [$tinptr, :128]! + vmlal.u32 $A5xB,$Ni,${N2}[1] + vst1.64 {$A2xB-$A3xB}, [$toutptr,:256]! + vmlal.u32 $A6xB,$Ni,${N3}[0] + vld1.64 {$A1xB-$A2xB}, [$tinptr, :256]! + vmlal.u32 $A7xB,$Ni,${N3}[1] + vst1.64 {$A4xB-$A5xB}, [$toutptr,:256]! + + vmlal.u32 $A0xB,$Bi,${A0}[0] + vld1.64 {$A3xB-$A4xB}, [$tinptr, :256]! + vmlal.u32 $A1xB,$Bi,${A0}[1] + vst1.64 {$A6xB-$A7xB}, [$toutptr,:256]! + vmlal.u32 $A2xB,$Bi,${A1}[0] + vld1.64 {$A5xB-$A6xB}, [$tinptr, :256]! + vmlal.u32 $A3xB,$Bi,${A1}[1] + vld1.32 {$N0-$N3}, [$nptr]! + + vmlal.u32 $A4xB,$Bi,${A2}[0] + vld1.64 {$A7xB}, [$tinptr, :128]! + vmlal.u32 $A5xB,$Bi,${A2}[1] + vmlal.u32 $A6xB,$Bi,${A3}[0] + vmlal.u32 $A7xB,$Bi,${A3}[1] + + bne .LNEON_inner + + vmlal.u32 $A0xB,$Ni,${N0}[0] + add $tinptr,sp,#16 + vmlal.u32 $A1xB,$Ni,${N0}[1] + sub $aptr,$aptr,$num,lsl#2 @ rewind $aptr + vmlal.u32 $A2xB,$Ni,${N1}[0] + vld1.64 {$Temp}, [sp,:128] + vmlal.u32 $A3xB,$Ni,${N1}[1] + subs $outer,$outer,#1 + + vmlal.u32 $A4xB,$Ni,${N2}[0] + vst1.64 {$A0xB-$A1xB}, [$toutptr,:256]! + vmlal.u32 $A5xB,$Ni,${N2}[1] + vld1.64 {$A0xB}, [$tinptr, :128]! + vshr.u64 $temp,$temp,#16 + vst1.64 {$A2xB-$A3xB}, [$toutptr,:256]! + vmlal.u32 $A6xB,$Ni,${N3}[0] + vld1.64 {$A1xB-$A2xB}, [$tinptr, :256]! + vmlal.u32 $A7xB,$Ni,${N3}[1] + + vst1.64 {$A4xB-$A5xB}, [$toutptr,:256]! + vadd.u64 $temp,$temp,`&Dhi("$Temp")` + vst1.64 {$A6xB-$A7xB}, [$toutptr,:256]! + vshr.u64 $temp,$temp,#16 + + bne .LNEON_outer + + mov $toutptr,sp + mov $inner,$num + +.LNEON_tail: + vadd.u64 `&Dlo("$A0xB")`,`&Dlo("$A0xB")`,$temp + vld1.64 {$A3xB-$A4xB}, [$tinptr, :256]! + vshr.u64 $temp,`&Dlo("$A0xB")`,#16 + vadd.u64 `&Dhi("$A0xB")`,`&Dhi("$A0xB")`,$temp + vld1.64 {$A5xB-$A6xB}, [$tinptr, :256]! + vshr.u64 $temp,`&Dhi("$A0xB")`,#16 + vld1.64 {$A7xB}, [$tinptr, :128]! + vzip.16 `&Dlo("$A0xB")`,`&Dhi("$A0xB")` + +.LNEON_tail2: + vadd.u64 `&Dlo("$A1xB")`,`&Dlo("$A1xB")`,$temp + vst1.32 {`&Dlo("$A0xB")`[0]}, [$toutptr, :32]! + vshr.u64 $temp,`&Dlo("$A1xB")`,#16 + vadd.u64 `&Dhi("$A1xB")`,`&Dhi("$A1xB")`,$temp + vshr.u64 $temp,`&Dhi("$A1xB")`,#16 + vzip.16 `&Dlo("$A1xB")`,`&Dhi("$A1xB")` + + vadd.u64 `&Dlo("$A2xB")`,`&Dlo("$A2xB")`,$temp + vst1.32 {`&Dlo("$A1xB")`[0]}, [$toutptr, :32]! + vshr.u64 $temp,`&Dlo("$A2xB")`,#16 + vadd.u64 `&Dhi("$A2xB")`,`&Dhi("$A2xB")`,$temp + vshr.u64 $temp,`&Dhi("$A2xB")`,#16 + vzip.16 `&Dlo("$A2xB")`,`&Dhi("$A2xB")` + + vadd.u64 `&Dlo("$A3xB")`,`&Dlo("$A3xB")`,$temp + vst1.32 {`&Dlo("$A2xB")`[0]}, [$toutptr, :32]! + vshr.u64 $temp,`&Dlo("$A3xB")`,#16 + vadd.u64 `&Dhi("$A3xB")`,`&Dhi("$A3xB")`,$temp + vshr.u64 $temp,`&Dhi("$A3xB")`,#16 + vzip.16 `&Dlo("$A3xB")`,`&Dhi("$A3xB")` + + vadd.u64 `&Dlo("$A4xB")`,`&Dlo("$A4xB")`,$temp + vst1.32 {`&Dlo("$A3xB")`[0]}, [$toutptr, :32]! + vshr.u64 $temp,`&Dlo("$A4xB")`,#16 + vadd.u64 `&Dhi("$A4xB")`,`&Dhi("$A4xB")`,$temp + vshr.u64 $temp,`&Dhi("$A4xB")`,#16 + vzip.16 `&Dlo("$A4xB")`,`&Dhi("$A4xB")` + + vadd.u64 `&Dlo("$A5xB")`,`&Dlo("$A5xB")`,$temp + vst1.32 {`&Dlo("$A4xB")`[0]}, [$toutptr, :32]! + vshr.u64 $temp,`&Dlo("$A5xB")`,#16 + vadd.u64 `&Dhi("$A5xB")`,`&Dhi("$A5xB")`,$temp + vshr.u64 $temp,`&Dhi("$A5xB")`,#16 + vzip.16 `&Dlo("$A5xB")`,`&Dhi("$A5xB")` + + vadd.u64 `&Dlo("$A6xB")`,`&Dlo("$A6xB")`,$temp + vst1.32 {`&Dlo("$A5xB")`[0]}, [$toutptr, :32]! + vshr.u64 $temp,`&Dlo("$A6xB")`,#16 + vadd.u64 `&Dhi("$A6xB")`,`&Dhi("$A6xB")`,$temp + vld1.64 {$A0xB}, [$tinptr, :128]! + vshr.u64 $temp,`&Dhi("$A6xB")`,#16 + vzip.16 `&Dlo("$A6xB")`,`&Dhi("$A6xB")` + + vadd.u64 `&Dlo("$A7xB")`,`&Dlo("$A7xB")`,$temp + vst1.32 {`&Dlo("$A6xB")`[0]}, [$toutptr, :32]! + vshr.u64 $temp,`&Dlo("$A7xB")`,#16 + vadd.u64 `&Dhi("$A7xB")`,`&Dhi("$A7xB")`,$temp + vld1.64 {$A1xB-$A2xB}, [$tinptr, :256]! + vshr.u64 $temp,`&Dhi("$A7xB")`,#16 + vzip.16 `&Dlo("$A7xB")`,`&Dhi("$A7xB")` + subs $inner,$inner,#8 + vst1.32 {`&Dlo("$A7xB")`[0]}, [$toutptr, :32]! + + bne .LNEON_tail + + vst1.32 {${temp}[0]}, [$toutptr, :32] @ top-most bit + sub $nptr,$nptr,$num,lsl#2 @ rewind $nptr + subs $aptr,sp,#0 @ clear carry flag + add $bptr,sp,$num,lsl#2 + +.LNEON_sub: + ldmia $aptr!, {r4-r7} + ldmia $nptr!, {r8-r11} + sbcs r8, r4,r8 + sbcs r9, r5,r9 + sbcs r10,r6,r10 + sbcs r11,r7,r11 + teq $aptr,$bptr @ preserves carry + stmia $rptr!, {r8-r11} + bne .LNEON_sub + + ldr r10, [$aptr] @ load top-most bit + veor q0,q0,q0 + sub r11,$bptr,sp @ this is num*4 + veor q1,q1,q1 + mov $aptr,sp + sub $rptr,$rptr,r11 @ rewind $rptr + mov $nptr,$bptr @ second 3/4th of frame + sbcs r10,r10,#0 @ result is carry flag + +.LNEON_copy_n_zap: + ldmia $aptr!, {r4-r7} + ldmia $rptr, {r8-r11} + movcc r8, r4 + vst1.64 {q0-q1}, [$nptr,:256]! @ wipe + movcc r9, r5 + movcc r10,r6 + vst1.64 {q0-q1}, [$nptr,:256]! @ wipe + movcc r11,r7 + ldmia $aptr, {r4-r7} + stmia $rptr!, {r8-r11} + sub $aptr,$aptr,#16 + ldmia $rptr, {r8-r11} + movcc r8, r4 + vst1.64 {q0-q1}, [$aptr,:256]! @ wipe + movcc r9, r5 + movcc r10,r6 + vst1.64 {q0-q1}, [$nptr,:256]! @ wipe + movcc r11,r7 + teq $aptr,$bptr @ preserves carry + stmia $rptr!, {r8-r11} + bne .LNEON_copy_n_zap + + sub sp,ip,#96 + vldmia sp!,{d8-d15} + ldmia sp!,{r4-r11} + ret @ bx lr +.size bn_mul8x_mont_neon,.-bn_mul8x_mont_neon +#endif +___ +} +$code.=<<___; +.asciz "Montgomery multiplication for ARMv4/NEON, CRYPTOGAMS by " +.align 2 +#if __ARM_MAX_ARCH__>=7 +.comm OPENSSL_armcap_P,4,4 +.hidden OPENSSL_armcap_P +#endif +___ + +$code =~ s/\`([^\`]*)\`/eval $1/gem; +$code =~ s/\bbx\s+lr\b/.word\t0xe12fff1e/gm; # make it possible to compile with -march=armv4 +$code =~ s/\bret\b/bx lr/gm; +print $code; +close STDOUT; diff --git a/external/boringssl/crypto/bn/asm/armv8-mont.pl b/external/boringssl/crypto/bn/asm/armv8-mont.pl new file mode 100644 index 0000000000..f04aab16bc --- /dev/null +++ b/external/boringssl/crypto/bn/asm/armv8-mont.pl @@ -0,0 +1,1503 @@ +#!/usr/bin/env perl + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== + +# March 2015 +# +# "Teaser" Montgomery multiplication module for ARMv8. Needs more +# work. While it does improve RSA sign performance by 20-30% (less for +# longer keys) on most processors, for some reason RSA2048 is not +# faster and RSA4096 goes 15-20% slower on Cortex-A57. Multiplication +# instruction issue rate is limited on processor in question, meaning +# that dedicated squaring procedure is a must. Well, actually all +# contemporary AArch64 processors seem to have limited multiplication +# issue rate, i.e. they can't issue multiplication every cycle, which +# explains moderate improvement coefficients in comparison to +# compiler-generated code. Recall that compiler is instructed to use +# umulh and therefore uses same amount of multiplication instructions +# to do the job. Assembly's edge is to minimize number of "collateral" +# instructions and of course instruction scheduling. +# +# April 2015 +# +# Squaring procedure that handles lengths divisible by 8 improves +# RSA/DSA performance by 25-40-60% depending on processor and key +# length. Overall improvement coefficients are always positive in +# comparison to compiler-generated code. On Cortex-A57 improvement +# is still modest on longest key lengths, while others exhibit e.g. +# 50-70% improvement for RSA4096 sign. RSA2048 sign is ~25% faster +# on Cortex-A57 and ~60-100% faster on others. + +$flavour = shift; +$output = shift; + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or +die "can't locate arm-xlate.pl"; + +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; + +($lo0,$hi0,$aj,$m0,$alo,$ahi, + $lo1,$hi1,$nj,$m1,$nlo,$nhi, + $ovf, $i,$j,$tp,$tj) = map("x$_",6..17,19..24); + +# int bn_mul_mont( +$rp="x0"; # BN_ULONG *rp, +$ap="x1"; # const BN_ULONG *ap, +$bp="x2"; # const BN_ULONG *bp, +$np="x3"; # const BN_ULONG *np, +$n0="x4"; # const BN_ULONG *n0, +$num="x5"; # int num); + +$code.=<<___; +.text + +.globl bn_mul_mont +.type bn_mul_mont,%function +.align 5 +bn_mul_mont: + tst $num,#7 + b.eq __bn_sqr8x_mont + tst $num,#3 + b.eq __bn_mul4x_mont +.Lmul_mont: + stp x29,x30,[sp,#-64]! + add x29,sp,#0 + stp x19,x20,[sp,#16] + stp x21,x22,[sp,#32] + stp x23,x24,[sp,#48] + + ldr $m0,[$bp],#8 // bp[0] + sub $tp,sp,$num,lsl#3 + ldp $hi0,$aj,[$ap],#16 // ap[0..1] + lsl $num,$num,#3 + ldr $n0,[$n0] // *n0 + and $tp,$tp,#-16 // ABI says so + ldp $hi1,$nj,[$np],#16 // np[0..1] + + mul $lo0,$hi0,$m0 // ap[0]*bp[0] + sub $j,$num,#16 // j=num-2 + umulh $hi0,$hi0,$m0 + mul $alo,$aj,$m0 // ap[1]*bp[0] + umulh $ahi,$aj,$m0 + + mul $m1,$lo0,$n0 // "tp[0]"*n0 + mov sp,$tp // alloca + + // (*) mul $lo1,$hi1,$m1 // np[0]*m1 + umulh $hi1,$hi1,$m1 + mul $nlo,$nj,$m1 // np[1]*m1 + // (*) adds $lo1,$lo1,$lo0 // discarded + // (*) As for removal of first multiplication and addition + // instructions. The outcome of first addition is + // guaranteed to be zero, which leaves two computationally + // significant outcomes: it either carries or not. Then + // question is when does it carry? Is there alternative + // way to deduce it? If you follow operations, you can + // observe that condition for carry is quite simple: + // $lo0 being non-zero. So that carry can be calculated + // by adding -1 to $lo0. That's what next instruction does. + subs xzr,$lo0,#1 // (*) + umulh $nhi,$nj,$m1 + adc $hi1,$hi1,xzr + cbz $j,.L1st_skip + +.L1st: + ldr $aj,[$ap],#8 + adds $lo0,$alo,$hi0 + sub $j,$j,#8 // j-- + adc $hi0,$ahi,xzr + + ldr $nj,[$np],#8 + adds $lo1,$nlo,$hi1 + mul $alo,$aj,$m0 // ap[j]*bp[0] + adc $hi1,$nhi,xzr + umulh $ahi,$aj,$m0 + + adds $lo1,$lo1,$lo0 + mul $nlo,$nj,$m1 // np[j]*m1 + adc $hi1,$hi1,xzr + umulh $nhi,$nj,$m1 + str $lo1,[$tp],#8 // tp[j-1] + cbnz $j,.L1st + +.L1st_skip: + adds $lo0,$alo,$hi0 + sub $ap,$ap,$num // rewind $ap + adc $hi0,$ahi,xzr + + adds $lo1,$nlo,$hi1 + sub $np,$np,$num // rewind $np + adc $hi1,$nhi,xzr + + adds $lo1,$lo1,$lo0 + sub $i,$num,#8 // i=num-1 + adcs $hi1,$hi1,$hi0 + + adc $ovf,xzr,xzr // upmost overflow bit + stp $lo1,$hi1,[$tp] + +.Louter: + ldr $m0,[$bp],#8 // bp[i] + ldp $hi0,$aj,[$ap],#16 + ldr $tj,[sp] // tp[0] + add $tp,sp,#8 + + mul $lo0,$hi0,$m0 // ap[0]*bp[i] + sub $j,$num,#16 // j=num-2 + umulh $hi0,$hi0,$m0 + ldp $hi1,$nj,[$np],#16 + mul $alo,$aj,$m0 // ap[1]*bp[i] + adds $lo0,$lo0,$tj + umulh $ahi,$aj,$m0 + adc $hi0,$hi0,xzr + + mul $m1,$lo0,$n0 + sub $i,$i,#8 // i-- + + // (*) mul $lo1,$hi1,$m1 // np[0]*m1 + umulh $hi1,$hi1,$m1 + mul $nlo,$nj,$m1 // np[1]*m1 + // (*) adds $lo1,$lo1,$lo0 + subs xzr,$lo0,#1 // (*) + umulh $nhi,$nj,$m1 + cbz $j,.Linner_skip + +.Linner: + ldr $aj,[$ap],#8 + adc $hi1,$hi1,xzr + ldr $tj,[$tp],#8 // tp[j] + adds $lo0,$alo,$hi0 + sub $j,$j,#8 // j-- + adc $hi0,$ahi,xzr + + adds $lo1,$nlo,$hi1 + ldr $nj,[$np],#8 + adc $hi1,$nhi,xzr + + mul $alo,$aj,$m0 // ap[j]*bp[i] + adds $lo0,$lo0,$tj + umulh $ahi,$aj,$m0 + adc $hi0,$hi0,xzr + + mul $nlo,$nj,$m1 // np[j]*m1 + adds $lo1,$lo1,$lo0 + umulh $nhi,$nj,$m1 + str $lo1,[$tp,#-16] // tp[j-1] + cbnz $j,.Linner + +.Linner_skip: + ldr $tj,[$tp],#8 // tp[j] + adc $hi1,$hi1,xzr + adds $lo0,$alo,$hi0 + sub $ap,$ap,$num // rewind $ap + adc $hi0,$ahi,xzr + + adds $lo1,$nlo,$hi1 + sub $np,$np,$num // rewind $np + adcs $hi1,$nhi,$ovf + adc $ovf,xzr,xzr + + adds $lo0,$lo0,$tj + adc $hi0,$hi0,xzr + + adds $lo1,$lo1,$lo0 + adcs $hi1,$hi1,$hi0 + adc $ovf,$ovf,xzr // upmost overflow bit + stp $lo1,$hi1,[$tp,#-16] + + cbnz $i,.Louter + + // Final step. We see if result is larger than modulus, and + // if it is, subtract the modulus. But comparison implies + // subtraction. So we subtract modulus, see if it borrowed, + // and conditionally copy original value. + ldr $tj,[sp] // tp[0] + add $tp,sp,#8 + ldr $nj,[$np],#8 // np[0] + subs $j,$num,#8 // j=num-1 and clear borrow + mov $ap,$rp +.Lsub: + sbcs $aj,$tj,$nj // tp[j]-np[j] + ldr $tj,[$tp],#8 + sub $j,$j,#8 // j-- + ldr $nj,[$np],#8 + str $aj,[$ap],#8 // rp[j]=tp[j]-np[j] + cbnz $j,.Lsub + + sbcs $aj,$tj,$nj + sbcs $ovf,$ovf,xzr // did it borrow? + str $aj,[$ap],#8 // rp[num-1] + + ldr $tj,[sp] // tp[0] + add $tp,sp,#8 + ldr $aj,[$rp],#8 // rp[0] + sub $num,$num,#8 // num-- + nop +.Lcond_copy: + sub $num,$num,#8 // num-- + csel $nj,$tj,$aj,lo // did it borrow? + ldr $tj,[$tp],#8 + ldr $aj,[$rp],#8 + str xzr,[$tp,#-16] // wipe tp + str $nj,[$rp,#-16] + cbnz $num,.Lcond_copy + + csel $nj,$tj,$aj,lo + str xzr,[$tp,#-8] // wipe tp + str $nj,[$rp,#-8] + + ldp x19,x20,[x29,#16] + mov sp,x29 + ldp x21,x22,[x29,#32] + mov x0,#1 + ldp x23,x24,[x29,#48] + ldr x29,[sp],#64 + ret +.size bn_mul_mont,.-bn_mul_mont +___ +{ +######################################################################## +# Following is ARMv8 adaptation of sqrx8x_mont from x86_64-mont5 module. + +my ($a0,$a1,$a2,$a3,$a4,$a5,$a6,$a7)=map("x$_",(6..13)); +my ($t0,$t1,$t2,$t3)=map("x$_",(14..17)); +my ($acc0,$acc1,$acc2,$acc3,$acc4,$acc5,$acc6,$acc7)=map("x$_",(19..26)); +my ($cnt,$carry,$topmost)=("x27","x28","x30"); +my ($tp,$ap_end,$na0)=($bp,$np,$carry); + +$code.=<<___; +.type __bn_sqr8x_mont,%function +.align 5 +__bn_sqr8x_mont: + cmp $ap,$bp + b.ne __bn_mul4x_mont +.Lsqr8x_mont: + stp x29,x30,[sp,#-128]! + add x29,sp,#0 + stp x19,x20,[sp,#16] + stp x21,x22,[sp,#32] + stp x23,x24,[sp,#48] + stp x25,x26,[sp,#64] + stp x27,x28,[sp,#80] + stp $rp,$np,[sp,#96] // offload rp and np + + ldp $a0,$a1,[$ap,#8*0] + ldp $a2,$a3,[$ap,#8*2] + ldp $a4,$a5,[$ap,#8*4] + ldp $a6,$a7,[$ap,#8*6] + + sub $tp,sp,$num,lsl#4 + lsl $num,$num,#3 + ldr $n0,[$n0] // *n0 + mov sp,$tp // alloca + sub $cnt,$num,#8*8 + b .Lsqr8x_zero_start + +.Lsqr8x_zero: + sub $cnt,$cnt,#8*8 + stp xzr,xzr,[$tp,#8*0] + stp xzr,xzr,[$tp,#8*2] + stp xzr,xzr,[$tp,#8*4] + stp xzr,xzr,[$tp,#8*6] +.Lsqr8x_zero_start: + stp xzr,xzr,[$tp,#8*8] + stp xzr,xzr,[$tp,#8*10] + stp xzr,xzr,[$tp,#8*12] + stp xzr,xzr,[$tp,#8*14] + add $tp,$tp,#8*16 + cbnz $cnt,.Lsqr8x_zero + + add $ap_end,$ap,$num + add $ap,$ap,#8*8 + mov $acc0,xzr + mov $acc1,xzr + mov $acc2,xzr + mov $acc3,xzr + mov $acc4,xzr + mov $acc5,xzr + mov $acc6,xzr + mov $acc7,xzr + mov $tp,sp + str $n0,[x29,#112] // offload n0 + + // Multiply everything but a[i]*a[i] +.align 4 +.Lsqr8x_outer_loop: + // a[1]a[0] (i) + // a[2]a[0] + // a[3]a[0] + // a[4]a[0] + // a[5]a[0] + // a[6]a[0] + // a[7]a[0] + // a[2]a[1] (ii) + // a[3]a[1] + // a[4]a[1] + // a[5]a[1] + // a[6]a[1] + // a[7]a[1] + // a[3]a[2] (iii) + // a[4]a[2] + // a[5]a[2] + // a[6]a[2] + // a[7]a[2] + // a[4]a[3] (iv) + // a[5]a[3] + // a[6]a[3] + // a[7]a[3] + // a[5]a[4] (v) + // a[6]a[4] + // a[7]a[4] + // a[6]a[5] (vi) + // a[7]a[5] + // a[7]a[6] (vii) + + mul $t0,$a1,$a0 // lo(a[1..7]*a[0]) (i) + mul $t1,$a2,$a0 + mul $t2,$a3,$a0 + mul $t3,$a4,$a0 + adds $acc1,$acc1,$t0 // t[1]+lo(a[1]*a[0]) + mul $t0,$a5,$a0 + adcs $acc2,$acc2,$t1 + mul $t1,$a6,$a0 + adcs $acc3,$acc3,$t2 + mul $t2,$a7,$a0 + adcs $acc4,$acc4,$t3 + umulh $t3,$a1,$a0 // hi(a[1..7]*a[0]) + adcs $acc5,$acc5,$t0 + umulh $t0,$a2,$a0 + adcs $acc6,$acc6,$t1 + umulh $t1,$a3,$a0 + adcs $acc7,$acc7,$t2 + umulh $t2,$a4,$a0 + stp $acc0,$acc1,[$tp],#8*2 // t[0..1] + adc $acc0,xzr,xzr // t[8] + adds $acc2,$acc2,$t3 // t[2]+lo(a[1]*a[0]) + umulh $t3,$a5,$a0 + adcs $acc3,$acc3,$t0 + umulh $t0,$a6,$a0 + adcs $acc4,$acc4,$t1 + umulh $t1,$a7,$a0 + adcs $acc5,$acc5,$t2 + mul $t2,$a2,$a1 // lo(a[2..7]*a[1]) (ii) + adcs $acc6,$acc6,$t3 + mul $t3,$a3,$a1 + adcs $acc7,$acc7,$t0 + mul $t0,$a4,$a1 + adc $acc0,$acc0,$t1 + + mul $t1,$a5,$a1 + adds $acc3,$acc3,$t2 + mul $t2,$a6,$a1 + adcs $acc4,$acc4,$t3 + mul $t3,$a7,$a1 + adcs $acc5,$acc5,$t0 + umulh $t0,$a2,$a1 // hi(a[2..7]*a[1]) + adcs $acc6,$acc6,$t1 + umulh $t1,$a3,$a1 + adcs $acc7,$acc7,$t2 + umulh $t2,$a4,$a1 + adcs $acc0,$acc0,$t3 + umulh $t3,$a5,$a1 + stp $acc2,$acc3,[$tp],#8*2 // t[2..3] + adc $acc1,xzr,xzr // t[9] + adds $acc4,$acc4,$t0 + umulh $t0,$a6,$a1 + adcs $acc5,$acc5,$t1 + umulh $t1,$a7,$a1 + adcs $acc6,$acc6,$t2 + mul $t2,$a3,$a2 // lo(a[3..7]*a[2]) (iii) + adcs $acc7,$acc7,$t3 + mul $t3,$a4,$a2 + adcs $acc0,$acc0,$t0 + mul $t0,$a5,$a2 + adc $acc1,$acc1,$t1 + + mul $t1,$a6,$a2 + adds $acc5,$acc5,$t2 + mul $t2,$a7,$a2 + adcs $acc6,$acc6,$t3 + umulh $t3,$a3,$a2 // hi(a[3..7]*a[2]) + adcs $acc7,$acc7,$t0 + umulh $t0,$a4,$a2 + adcs $acc0,$acc0,$t1 + umulh $t1,$a5,$a2 + adcs $acc1,$acc1,$t2 + umulh $t2,$a6,$a2 + stp $acc4,$acc5,[$tp],#8*2 // t[4..5] + adc $acc2,xzr,xzr // t[10] + adds $acc6,$acc6,$t3 + umulh $t3,$a7,$a2 + adcs $acc7,$acc7,$t0 + mul $t0,$a4,$a3 // lo(a[4..7]*a[3]) (iv) + adcs $acc0,$acc0,$t1 + mul $t1,$a5,$a3 + adcs $acc1,$acc1,$t2 + mul $t2,$a6,$a3 + adc $acc2,$acc2,$t3 + + mul $t3,$a7,$a3 + adds $acc7,$acc7,$t0 + umulh $t0,$a4,$a3 // hi(a[4..7]*a[3]) + adcs $acc0,$acc0,$t1 + umulh $t1,$a5,$a3 + adcs $acc1,$acc1,$t2 + umulh $t2,$a6,$a3 + adcs $acc2,$acc2,$t3 + umulh $t3,$a7,$a3 + stp $acc6,$acc7,[$tp],#8*2 // t[6..7] + adc $acc3,xzr,xzr // t[11] + adds $acc0,$acc0,$t0 + mul $t0,$a5,$a4 // lo(a[5..7]*a[4]) (v) + adcs $acc1,$acc1,$t1 + mul $t1,$a6,$a4 + adcs $acc2,$acc2,$t2 + mul $t2,$a7,$a4 + adc $acc3,$acc3,$t3 + + umulh $t3,$a5,$a4 // hi(a[5..7]*a[4]) + adds $acc1,$acc1,$t0 + umulh $t0,$a6,$a4 + adcs $acc2,$acc2,$t1 + umulh $t1,$a7,$a4 + adcs $acc3,$acc3,$t2 + mul $t2,$a6,$a5 // lo(a[6..7]*a[5]) (vi) + adc $acc4,xzr,xzr // t[12] + adds $acc2,$acc2,$t3 + mul $t3,$a7,$a5 + adcs $acc3,$acc3,$t0 + umulh $t0,$a6,$a5 // hi(a[6..7]*a[5]) + adc $acc4,$acc4,$t1 + + umulh $t1,$a7,$a5 + adds $acc3,$acc3,$t2 + mul $t2,$a7,$a6 // lo(a[7]*a[6]) (vii) + adcs $acc4,$acc4,$t3 + umulh $t3,$a7,$a6 // hi(a[7]*a[6]) + adc $acc5,xzr,xzr // t[13] + adds $acc4,$acc4,$t0 + sub $cnt,$ap_end,$ap // done yet? + adc $acc5,$acc5,$t1 + + adds $acc5,$acc5,$t2 + sub $t0,$ap_end,$num // rewinded ap + adc $acc6,xzr,xzr // t[14] + add $acc6,$acc6,$t3 + + cbz $cnt,.Lsqr8x_outer_break + + mov $n0,$a0 + ldp $a0,$a1,[$tp,#8*0] + ldp $a2,$a3,[$tp,#8*2] + ldp $a4,$a5,[$tp,#8*4] + ldp $a6,$a7,[$tp,#8*6] + adds $acc0,$acc0,$a0 + adcs $acc1,$acc1,$a1 + ldp $a0,$a1,[$ap,#8*0] + adcs $acc2,$acc2,$a2 + adcs $acc3,$acc3,$a3 + ldp $a2,$a3,[$ap,#8*2] + adcs $acc4,$acc4,$a4 + adcs $acc5,$acc5,$a5 + ldp $a4,$a5,[$ap,#8*4] + adcs $acc6,$acc6,$a6 + mov $rp,$ap + adcs $acc7,xzr,$a7 + ldp $a6,$a7,[$ap,#8*6] + add $ap,$ap,#8*8 + //adc $carry,xzr,xzr // moved below + mov $cnt,#-8*8 + + // a[8]a[0] + // a[9]a[0] + // a[a]a[0] + // a[b]a[0] + // a[c]a[0] + // a[d]a[0] + // a[e]a[0] + // a[f]a[0] + // a[8]a[1] + // a[f]a[1]........................ + // a[8]a[2] + // a[f]a[2]........................ + // a[8]a[3] + // a[f]a[3]........................ + // a[8]a[4] + // a[f]a[4]........................ + // a[8]a[5] + // a[f]a[5]........................ + // a[8]a[6] + // a[f]a[6]........................ + // a[8]a[7] + // a[f]a[7]........................ +.Lsqr8x_mul: + mul $t0,$a0,$n0 + adc $carry,xzr,xzr // carry bit, modulo-scheduled + mul $t1,$a1,$n0 + add $cnt,$cnt,#8 + mul $t2,$a2,$n0 + mul $t3,$a3,$n0 + adds $acc0,$acc0,$t0 + mul $t0,$a4,$n0 + adcs $acc1,$acc1,$t1 + mul $t1,$a5,$n0 + adcs $acc2,$acc2,$t2 + mul $t2,$a6,$n0 + adcs $acc3,$acc3,$t3 + mul $t3,$a7,$n0 + adcs $acc4,$acc4,$t0 + umulh $t0,$a0,$n0 + adcs $acc5,$acc5,$t1 + umulh $t1,$a1,$n0 + adcs $acc6,$acc6,$t2 + umulh $t2,$a2,$n0 + adcs $acc7,$acc7,$t3 + umulh $t3,$a3,$n0 + adc $carry,$carry,xzr + str $acc0,[$tp],#8 + adds $acc0,$acc1,$t0 + umulh $t0,$a4,$n0 + adcs $acc1,$acc2,$t1 + umulh $t1,$a5,$n0 + adcs $acc2,$acc3,$t2 + umulh $t2,$a6,$n0 + adcs $acc3,$acc4,$t3 + umulh $t3,$a7,$n0 + ldr $n0,[$rp,$cnt] + adcs $acc4,$acc5,$t0 + adcs $acc5,$acc6,$t1 + adcs $acc6,$acc7,$t2 + adcs $acc7,$carry,$t3 + //adc $carry,xzr,xzr // moved above + cbnz $cnt,.Lsqr8x_mul + // note that carry flag is guaranteed + // to be zero at this point + cmp $ap,$ap_end // done yet? + b.eq .Lsqr8x_break + + ldp $a0,$a1,[$tp,#8*0] + ldp $a2,$a3,[$tp,#8*2] + ldp $a4,$a5,[$tp,#8*4] + ldp $a6,$a7,[$tp,#8*6] + adds $acc0,$acc0,$a0 + ldr $n0,[$rp,#-8*8] + adcs $acc1,$acc1,$a1 + ldp $a0,$a1,[$ap,#8*0] + adcs $acc2,$acc2,$a2 + adcs $acc3,$acc3,$a3 + ldp $a2,$a3,[$ap,#8*2] + adcs $acc4,$acc4,$a4 + adcs $acc5,$acc5,$a5 + ldp $a4,$a5,[$ap,#8*4] + adcs $acc6,$acc6,$a6 + mov $cnt,#-8*8 + adcs $acc7,$acc7,$a7 + ldp $a6,$a7,[$ap,#8*6] + add $ap,$ap,#8*8 + //adc $carry,xzr,xzr // moved above + b .Lsqr8x_mul + +.align 4 +.Lsqr8x_break: + ldp $a0,$a1,[$rp,#8*0] + add $ap,$rp,#8*8 + ldp $a2,$a3,[$rp,#8*2] + sub $t0,$ap_end,$ap // is it last iteration? + ldp $a4,$a5,[$rp,#8*4] + sub $t1,$tp,$t0 + ldp $a6,$a7,[$rp,#8*6] + cbz $t0,.Lsqr8x_outer_loop + + stp $acc0,$acc1,[$tp,#8*0] + ldp $acc0,$acc1,[$t1,#8*0] + stp $acc2,$acc3,[$tp,#8*2] + ldp $acc2,$acc3,[$t1,#8*2] + stp $acc4,$acc5,[$tp,#8*4] + ldp $acc4,$acc5,[$t1,#8*4] + stp $acc6,$acc7,[$tp,#8*6] + mov $tp,$t1 + ldp $acc6,$acc7,[$t1,#8*6] + b .Lsqr8x_outer_loop + +.align 4 +.Lsqr8x_outer_break: + // Now multiply above result by 2 and add a[n-1]*a[n-1]|...|a[0]*a[0] + ldp $a1,$a3,[$t0,#8*0] // recall that $t0 is &a[0] + ldp $t1,$t2,[sp,#8*1] + ldp $a5,$a7,[$t0,#8*2] + add $ap,$t0,#8*4 + ldp $t3,$t0,[sp,#8*3] + + stp $acc0,$acc1,[$tp,#8*0] + mul $acc0,$a1,$a1 + stp $acc2,$acc3,[$tp,#8*2] + umulh $a1,$a1,$a1 + stp $acc4,$acc5,[$tp,#8*4] + mul $a2,$a3,$a3 + stp $acc6,$acc7,[$tp,#8*6] + mov $tp,sp + umulh $a3,$a3,$a3 + adds $acc1,$a1,$t1,lsl#1 + extr $t1,$t2,$t1,#63 + sub $cnt,$num,#8*4 + +.Lsqr4x_shift_n_add: + adcs $acc2,$a2,$t1 + extr $t2,$t3,$t2,#63 + sub $cnt,$cnt,#8*4 + adcs $acc3,$a3,$t2 + ldp $t1,$t2,[$tp,#8*5] + mul $a4,$a5,$a5 + ldp $a1,$a3,[$ap],#8*2 + umulh $a5,$a5,$a5 + mul $a6,$a7,$a7 + umulh $a7,$a7,$a7 + extr $t3,$t0,$t3,#63 + stp $acc0,$acc1,[$tp,#8*0] + adcs $acc4,$a4,$t3 + extr $t0,$t1,$t0,#63 + stp $acc2,$acc3,[$tp,#8*2] + adcs $acc5,$a5,$t0 + ldp $t3,$t0,[$tp,#8*7] + extr $t1,$t2,$t1,#63 + adcs $acc6,$a6,$t1 + extr $t2,$t3,$t2,#63 + adcs $acc7,$a7,$t2 + ldp $t1,$t2,[$tp,#8*9] + mul $a0,$a1,$a1 + ldp $a5,$a7,[$ap],#8*2 + umulh $a1,$a1,$a1 + mul $a2,$a3,$a3 + umulh $a3,$a3,$a3 + stp $acc4,$acc5,[$tp,#8*4] + extr $t3,$t0,$t3,#63 + stp $acc6,$acc7,[$tp,#8*6] + add $tp,$tp,#8*8 + adcs $acc0,$a0,$t3 + extr $t0,$t1,$t0,#63 + adcs $acc1,$a1,$t0 + ldp $t3,$t0,[$tp,#8*3] + extr $t1,$t2,$t1,#63 + cbnz $cnt,.Lsqr4x_shift_n_add +___ +my ($np,$np_end)=($ap,$ap_end); +$code.=<<___; + ldp $np,$n0,[x29,#104] // pull np and n0 + + adcs $acc2,$a2,$t1 + extr $t2,$t3,$t2,#63 + adcs $acc3,$a3,$t2 + ldp $t1,$t2,[$tp,#8*5] + mul $a4,$a5,$a5 + umulh $a5,$a5,$a5 + stp $acc0,$acc1,[$tp,#8*0] + mul $a6,$a7,$a7 + umulh $a7,$a7,$a7 + stp $acc2,$acc3,[$tp,#8*2] + extr $t3,$t0,$t3,#63 + adcs $acc4,$a4,$t3 + extr $t0,$t1,$t0,#63 + ldp $acc0,$acc1,[sp,#8*0] + adcs $acc5,$a5,$t0 + extr $t1,$t2,$t1,#63 + ldp $a0,$a1,[$np,#8*0] + adcs $acc6,$a6,$t1 + extr $t2,xzr,$t2,#63 + ldp $a2,$a3,[$np,#8*2] + adc $acc7,$a7,$t2 + ldp $a4,$a5,[$np,#8*4] + + // Reduce by 512 bits per iteration + mul $na0,$n0,$acc0 // t[0]*n0 + ldp $a6,$a7,[$np,#8*6] + add $np_end,$np,$num + ldp $acc2,$acc3,[sp,#8*2] + stp $acc4,$acc5,[$tp,#8*4] + ldp $acc4,$acc5,[sp,#8*4] + stp $acc6,$acc7,[$tp,#8*6] + ldp $acc6,$acc7,[sp,#8*6] + add $np,$np,#8*8 + mov $topmost,xzr // initial top-most carry + mov $tp,sp + mov $cnt,#8 + +.Lsqr8x_reduction: + // (*) mul $t0,$a0,$na0 // lo(n[0-7])*lo(t[0]*n0) + mul $t1,$a1,$na0 + sub $cnt,$cnt,#1 + mul $t2,$a2,$na0 + str $na0,[$tp],#8 // put aside t[0]*n0 for tail processing + mul $t3,$a3,$na0 + // (*) adds xzr,$acc0,$t0 + subs xzr,$acc0,#1 // (*) + mul $t0,$a4,$na0 + adcs $acc0,$acc1,$t1 + mul $t1,$a5,$na0 + adcs $acc1,$acc2,$t2 + mul $t2,$a6,$na0 + adcs $acc2,$acc3,$t3 + mul $t3,$a7,$na0 + adcs $acc3,$acc4,$t0 + umulh $t0,$a0,$na0 // hi(n[0-7])*lo(t[0]*n0) + adcs $acc4,$acc5,$t1 + umulh $t1,$a1,$na0 + adcs $acc5,$acc6,$t2 + umulh $t2,$a2,$na0 + adcs $acc6,$acc7,$t3 + umulh $t3,$a3,$na0 + adc $acc7,xzr,xzr + adds $acc0,$acc0,$t0 + umulh $t0,$a4,$na0 + adcs $acc1,$acc1,$t1 + umulh $t1,$a5,$na0 + adcs $acc2,$acc2,$t2 + umulh $t2,$a6,$na0 + adcs $acc3,$acc3,$t3 + umulh $t3,$a7,$na0 + mul $na0,$n0,$acc0 // next t[0]*n0 + adcs $acc4,$acc4,$t0 + adcs $acc5,$acc5,$t1 + adcs $acc6,$acc6,$t2 + adc $acc7,$acc7,$t3 + cbnz $cnt,.Lsqr8x_reduction + + ldp $t0,$t1,[$tp,#8*0] + ldp $t2,$t3,[$tp,#8*2] + mov $rp,$tp + sub $cnt,$np_end,$np // done yet? + adds $acc0,$acc0,$t0 + adcs $acc1,$acc1,$t1 + ldp $t0,$t1,[$tp,#8*4] + adcs $acc2,$acc2,$t2 + adcs $acc3,$acc3,$t3 + ldp $t2,$t3,[$tp,#8*6] + adcs $acc4,$acc4,$t0 + adcs $acc5,$acc5,$t1 + adcs $acc6,$acc6,$t2 + adcs $acc7,$acc7,$t3 + //adc $carry,xzr,xzr // moved below + cbz $cnt,.Lsqr8x8_post_condition + + ldr $n0,[$tp,#-8*8] + ldp $a0,$a1,[$np,#8*0] + ldp $a2,$a3,[$np,#8*2] + ldp $a4,$a5,[$np,#8*4] + mov $cnt,#-8*8 + ldp $a6,$a7,[$np,#8*6] + add $np,$np,#8*8 + +.Lsqr8x_tail: + mul $t0,$a0,$n0 + adc $carry,xzr,xzr // carry bit, modulo-scheduled + mul $t1,$a1,$n0 + add $cnt,$cnt,#8 + mul $t2,$a2,$n0 + mul $t3,$a3,$n0 + adds $acc0,$acc0,$t0 + mul $t0,$a4,$n0 + adcs $acc1,$acc1,$t1 + mul $t1,$a5,$n0 + adcs $acc2,$acc2,$t2 + mul $t2,$a6,$n0 + adcs $acc3,$acc3,$t3 + mul $t3,$a7,$n0 + adcs $acc4,$acc4,$t0 + umulh $t0,$a0,$n0 + adcs $acc5,$acc5,$t1 + umulh $t1,$a1,$n0 + adcs $acc6,$acc6,$t2 + umulh $t2,$a2,$n0 + adcs $acc7,$acc7,$t3 + umulh $t3,$a3,$n0 + adc $carry,$carry,xzr + str $acc0,[$tp],#8 + adds $acc0,$acc1,$t0 + umulh $t0,$a4,$n0 + adcs $acc1,$acc2,$t1 + umulh $t1,$a5,$n0 + adcs $acc2,$acc3,$t2 + umulh $t2,$a6,$n0 + adcs $acc3,$acc4,$t3 + umulh $t3,$a7,$n0 + ldr $n0,[$rp,$cnt] + adcs $acc4,$acc5,$t0 + adcs $acc5,$acc6,$t1 + adcs $acc6,$acc7,$t2 + adcs $acc7,$carry,$t3 + //adc $carry,xzr,xzr // moved above + cbnz $cnt,.Lsqr8x_tail + // note that carry flag is guaranteed + // to be zero at this point + ldp $a0,$a1,[$tp,#8*0] + sub $cnt,$np_end,$np // done yet? + sub $t2,$np_end,$num // rewinded np + ldp $a2,$a3,[$tp,#8*2] + ldp $a4,$a5,[$tp,#8*4] + ldp $a6,$a7,[$tp,#8*6] + cbz $cnt,.Lsqr8x_tail_break + + ldr $n0,[$rp,#-8*8] + adds $acc0,$acc0,$a0 + adcs $acc1,$acc1,$a1 + ldp $a0,$a1,[$np,#8*0] + adcs $acc2,$acc2,$a2 + adcs $acc3,$acc3,$a3 + ldp $a2,$a3,[$np,#8*2] + adcs $acc4,$acc4,$a4 + adcs $acc5,$acc5,$a5 + ldp $a4,$a5,[$np,#8*4] + adcs $acc6,$acc6,$a6 + mov $cnt,#-8*8 + adcs $acc7,$acc7,$a7 + ldp $a6,$a7,[$np,#8*6] + add $np,$np,#8*8 + //adc $carry,xzr,xzr // moved above + b .Lsqr8x_tail + +.align 4 +.Lsqr8x_tail_break: + ldr $n0,[x29,#112] // pull n0 + add $cnt,$tp,#8*8 // end of current t[num] window + + subs xzr,$topmost,#1 // "move" top-most carry to carry bit + adcs $t0,$acc0,$a0 + adcs $t1,$acc1,$a1 + ldp $acc0,$acc1,[$rp,#8*0] + adcs $acc2,$acc2,$a2 + ldp $a0,$a1,[$t2,#8*0] // recall that $t2 is &n[0] + adcs $acc3,$acc3,$a3 + ldp $a2,$a3,[$t2,#8*2] + adcs $acc4,$acc4,$a4 + adcs $acc5,$acc5,$a5 + ldp $a4,$a5,[$t2,#8*4] + adcs $acc6,$acc6,$a6 + adcs $acc7,$acc7,$a7 + ldp $a6,$a7,[$t2,#8*6] + add $np,$t2,#8*8 + adc $topmost,xzr,xzr // top-most carry + mul $na0,$n0,$acc0 + stp $t0,$t1,[$tp,#8*0] + stp $acc2,$acc3,[$tp,#8*2] + ldp $acc2,$acc3,[$rp,#8*2] + stp $acc4,$acc5,[$tp,#8*4] + ldp $acc4,$acc5,[$rp,#8*4] + cmp $cnt,x29 // did we hit the bottom? + stp $acc6,$acc7,[$tp,#8*6] + mov $tp,$rp // slide the window + ldp $acc6,$acc7,[$rp,#8*6] + mov $cnt,#8 + b.ne .Lsqr8x_reduction + + // Final step. We see if result is larger than modulus, and + // if it is, subtract the modulus. But comparison implies + // subtraction. So we subtract modulus, see if it borrowed, + // and conditionally copy original value. + ldr $rp,[x29,#96] // pull rp + add $tp,$tp,#8*8 + subs $t0,$acc0,$a0 + sbcs $t1,$acc1,$a1 + sub $cnt,$num,#8*8 + mov $ap_end,$rp // $rp copy + +.Lsqr8x_sub: + sbcs $t2,$acc2,$a2 + ldp $a0,$a1,[$np,#8*0] + sbcs $t3,$acc3,$a3 + stp $t0,$t1,[$rp,#8*0] + sbcs $t0,$acc4,$a4 + ldp $a2,$a3,[$np,#8*2] + sbcs $t1,$acc5,$a5 + stp $t2,$t3,[$rp,#8*2] + sbcs $t2,$acc6,$a6 + ldp $a4,$a5,[$np,#8*4] + sbcs $t3,$acc7,$a7 + ldp $a6,$a7,[$np,#8*6] + add $np,$np,#8*8 + ldp $acc0,$acc1,[$tp,#8*0] + sub $cnt,$cnt,#8*8 + ldp $acc2,$acc3,[$tp,#8*2] + ldp $acc4,$acc5,[$tp,#8*4] + ldp $acc6,$acc7,[$tp,#8*6] + add $tp,$tp,#8*8 + stp $t0,$t1,[$rp,#8*4] + sbcs $t0,$acc0,$a0 + stp $t2,$t3,[$rp,#8*6] + add $rp,$rp,#8*8 + sbcs $t1,$acc1,$a1 + cbnz $cnt,.Lsqr8x_sub + + sbcs $t2,$acc2,$a2 + mov $tp,sp + add $ap,sp,$num + ldp $a0,$a1,[$ap_end,#8*0] + sbcs $t3,$acc3,$a3 + stp $t0,$t1,[$rp,#8*0] + sbcs $t0,$acc4,$a4 + ldp $a2,$a3,[$ap_end,#8*2] + sbcs $t1,$acc5,$a5 + stp $t2,$t3,[$rp,#8*2] + sbcs $t2,$acc6,$a6 + ldp $acc0,$acc1,[$ap,#8*0] + sbcs $t3,$acc7,$a7 + ldp $acc2,$acc3,[$ap,#8*2] + sbcs xzr,$topmost,xzr // did it borrow? + ldr x30,[x29,#8] // pull return address + stp $t0,$t1,[$rp,#8*4] + stp $t2,$t3,[$rp,#8*6] + + sub $cnt,$num,#8*4 +.Lsqr4x_cond_copy: + sub $cnt,$cnt,#8*4 + csel $t0,$acc0,$a0,lo + stp xzr,xzr,[$tp,#8*0] + csel $t1,$acc1,$a1,lo + ldp $a0,$a1,[$ap_end,#8*4] + ldp $acc0,$acc1,[$ap,#8*4] + csel $t2,$acc2,$a2,lo + stp xzr,xzr,[$tp,#8*2] + add $tp,$tp,#8*4 + csel $t3,$acc3,$a3,lo + ldp $a2,$a3,[$ap_end,#8*6] + ldp $acc2,$acc3,[$ap,#8*6] + add $ap,$ap,#8*4 + stp $t0,$t1,[$ap_end,#8*0] + stp $t2,$t3,[$ap_end,#8*2] + add $ap_end,$ap_end,#8*4 + stp xzr,xzr,[$ap,#8*0] + stp xzr,xzr,[$ap,#8*2] + cbnz $cnt,.Lsqr4x_cond_copy + + csel $t0,$acc0,$a0,lo + stp xzr,xzr,[$tp,#8*0] + csel $t1,$acc1,$a1,lo + stp xzr,xzr,[$tp,#8*2] + csel $t2,$acc2,$a2,lo + csel $t3,$acc3,$a3,lo + stp $t0,$t1,[$ap_end,#8*0] + stp $t2,$t3,[$ap_end,#8*2] + + b .Lsqr8x_done + +.align 4 +.Lsqr8x8_post_condition: + adc $carry,xzr,xzr + ldr x30,[x29,#8] // pull return address + // $acc0-7,$carry hold result, $a0-7 hold modulus + subs $a0,$acc0,$a0 + ldr $ap,[x29,#96] // pull rp + sbcs $a1,$acc1,$a1 + stp xzr,xzr,[sp,#8*0] + sbcs $a2,$acc2,$a2 + stp xzr,xzr,[sp,#8*2] + sbcs $a3,$acc3,$a3 + stp xzr,xzr,[sp,#8*4] + sbcs $a4,$acc4,$a4 + stp xzr,xzr,[sp,#8*6] + sbcs $a5,$acc5,$a5 + stp xzr,xzr,[sp,#8*8] + sbcs $a6,$acc6,$a6 + stp xzr,xzr,[sp,#8*10] + sbcs $a7,$acc7,$a7 + stp xzr,xzr,[sp,#8*12] + sbcs $carry,$carry,xzr // did it borrow? + stp xzr,xzr,[sp,#8*14] + + // $a0-7 hold result-modulus + csel $a0,$acc0,$a0,lo + csel $a1,$acc1,$a1,lo + csel $a2,$acc2,$a2,lo + csel $a3,$acc3,$a3,lo + stp $a0,$a1,[$ap,#8*0] + csel $a4,$acc4,$a4,lo + csel $a5,$acc5,$a5,lo + stp $a2,$a3,[$ap,#8*2] + csel $a6,$acc6,$a6,lo + csel $a7,$acc7,$a7,lo + stp $a4,$a5,[$ap,#8*4] + stp $a6,$a7,[$ap,#8*6] + +.Lsqr8x_done: + ldp x19,x20,[x29,#16] + mov sp,x29 + ldp x21,x22,[x29,#32] + mov x0,#1 + ldp x23,x24,[x29,#48] + ldp x25,x26,[x29,#64] + ldp x27,x28,[x29,#80] + ldr x29,[sp],#128 + ret +.size __bn_sqr8x_mont,.-__bn_sqr8x_mont +___ +} + +{ +######################################################################## +# Even though this might look as ARMv8 adaptation of mulx4x_mont from +# x86_64-mont5 module, it's different in sense that it performs +# reduction 256 bits at a time. + +my ($a0,$a1,$a2,$a3, + $t0,$t1,$t2,$t3, + $m0,$m1,$m2,$m3, + $acc0,$acc1,$acc2,$acc3,$acc4, + $bi,$mi,$tp,$ap_end,$cnt) = map("x$_",(6..17,19..28)); +my $bp_end=$rp; +my ($carry,$topmost) = ($rp,"x30"); + +$code.=<<___; +.type __bn_mul4x_mont,%function +.align 5 +__bn_mul4x_mont: + stp x29,x30,[sp,#-128]! + add x29,sp,#0 + stp x19,x20,[sp,#16] + stp x21,x22,[sp,#32] + stp x23,x24,[sp,#48] + stp x25,x26,[sp,#64] + stp x27,x28,[sp,#80] + + sub $tp,sp,$num,lsl#3 + lsl $num,$num,#3 + ldr $n0,[$n0] // *n0 + sub sp,$tp,#8*4 // alloca + + add $t0,$bp,$num + add $ap_end,$ap,$num + stp $rp,$t0,[x29,#96] // offload rp and &b[num] + + ldr $bi,[$bp,#8*0] // b[0] + ldp $a0,$a1,[$ap,#8*0] // a[0..3] + ldp $a2,$a3,[$ap,#8*2] + add $ap,$ap,#8*4 + mov $acc0,xzr + mov $acc1,xzr + mov $acc2,xzr + mov $acc3,xzr + ldp $m0,$m1,[$np,#8*0] // n[0..3] + ldp $m2,$m3,[$np,#8*2] + adds $np,$np,#8*4 // clear carry bit + mov $carry,xzr + mov $cnt,#0 + mov $tp,sp + +.Loop_mul4x_1st_reduction: + mul $t0,$a0,$bi // lo(a[0..3]*b[0]) + adc $carry,$carry,xzr // modulo-scheduled + mul $t1,$a1,$bi + add $cnt,$cnt,#8 + mul $t2,$a2,$bi + and $cnt,$cnt,#31 + mul $t3,$a3,$bi + adds $acc0,$acc0,$t0 + umulh $t0,$a0,$bi // hi(a[0..3]*b[0]) + adcs $acc1,$acc1,$t1 + mul $mi,$acc0,$n0 // t[0]*n0 + adcs $acc2,$acc2,$t2 + umulh $t1,$a1,$bi + adcs $acc3,$acc3,$t3 + umulh $t2,$a2,$bi + adc $acc4,xzr,xzr + umulh $t3,$a3,$bi + ldr $bi,[$bp,$cnt] // next b[i] (or b[0]) + adds $acc1,$acc1,$t0 + // (*) mul $t0,$m0,$mi // lo(n[0..3]*t[0]*n0) + str $mi,[$tp],#8 // put aside t[0]*n0 for tail processing + adcs $acc2,$acc2,$t1 + mul $t1,$m1,$mi + adcs $acc3,$acc3,$t2 + mul $t2,$m2,$mi + adc $acc4,$acc4,$t3 // can't overflow + mul $t3,$m3,$mi + // (*) adds xzr,$acc0,$t0 + subs xzr,$acc0,#1 // (*) + umulh $t0,$m0,$mi // hi(n[0..3]*t[0]*n0) + adcs $acc0,$acc1,$t1 + umulh $t1,$m1,$mi + adcs $acc1,$acc2,$t2 + umulh $t2,$m2,$mi + adcs $acc2,$acc3,$t3 + umulh $t3,$m3,$mi + adcs $acc3,$acc4,$carry + adc $carry,xzr,xzr + adds $acc0,$acc0,$t0 + sub $t0,$ap_end,$ap + adcs $acc1,$acc1,$t1 + adcs $acc2,$acc2,$t2 + adcs $acc3,$acc3,$t3 + //adc $carry,$carry,xzr + cbnz $cnt,.Loop_mul4x_1st_reduction + + cbz $t0,.Lmul4x4_post_condition + + ldp $a0,$a1,[$ap,#8*0] // a[4..7] + ldp $a2,$a3,[$ap,#8*2] + add $ap,$ap,#8*4 + ldr $mi,[sp] // a[0]*n0 + ldp $m0,$m1,[$np,#8*0] // n[4..7] + ldp $m2,$m3,[$np,#8*2] + add $np,$np,#8*4 + +.Loop_mul4x_1st_tail: + mul $t0,$a0,$bi // lo(a[4..7]*b[i]) + adc $carry,$carry,xzr // modulo-scheduled + mul $t1,$a1,$bi + add $cnt,$cnt,#8 + mul $t2,$a2,$bi + and $cnt,$cnt,#31 + mul $t3,$a3,$bi + adds $acc0,$acc0,$t0 + umulh $t0,$a0,$bi // hi(a[4..7]*b[i]) + adcs $acc1,$acc1,$t1 + umulh $t1,$a1,$bi + adcs $acc2,$acc2,$t2 + umulh $t2,$a2,$bi + adcs $acc3,$acc3,$t3 + umulh $t3,$a3,$bi + adc $acc4,xzr,xzr + ldr $bi,[$bp,$cnt] // next b[i] (or b[0]) + adds $acc1,$acc1,$t0 + mul $t0,$m0,$mi // lo(n[4..7]*a[0]*n0) + adcs $acc2,$acc2,$t1 + mul $t1,$m1,$mi + adcs $acc3,$acc3,$t2 + mul $t2,$m2,$mi + adc $acc4,$acc4,$t3 // can't overflow + mul $t3,$m3,$mi + adds $acc0,$acc0,$t0 + umulh $t0,$m0,$mi // hi(n[4..7]*a[0]*n0) + adcs $acc1,$acc1,$t1 + umulh $t1,$m1,$mi + adcs $acc2,$acc2,$t2 + umulh $t2,$m2,$mi + adcs $acc3,$acc3,$t3 + adcs $acc4,$acc4,$carry + umulh $t3,$m3,$mi + adc $carry,xzr,xzr + ldr $mi,[sp,$cnt] // next t[0]*n0 + str $acc0,[$tp],#8 // result!!! + adds $acc0,$acc1,$t0 + sub $t0,$ap_end,$ap // done yet? + adcs $acc1,$acc2,$t1 + adcs $acc2,$acc3,$t2 + adcs $acc3,$acc4,$t3 + //adc $carry,$carry,xzr + cbnz $cnt,.Loop_mul4x_1st_tail + + sub $t1,$ap_end,$num // rewinded $ap + cbz $t0,.Lmul4x_proceed + + ldp $a0,$a1,[$ap,#8*0] + ldp $a2,$a3,[$ap,#8*2] + add $ap,$ap,#8*4 + ldp $m0,$m1,[$np,#8*0] + ldp $m2,$m3,[$np,#8*2] + add $np,$np,#8*4 + b .Loop_mul4x_1st_tail + +.align 5 +.Lmul4x_proceed: + ldr $bi,[$bp,#8*4]! // *++b + adc $topmost,$carry,xzr + ldp $a0,$a1,[$t1,#8*0] // a[0..3] + sub $np,$np,$num // rewind np + ldp $a2,$a3,[$t1,#8*2] + add $ap,$t1,#8*4 + + stp $acc0,$acc1,[$tp,#8*0] // result!!! + ldp $acc0,$acc1,[sp,#8*4] // t[0..3] + stp $acc2,$acc3,[$tp,#8*2] // result!!! + ldp $acc2,$acc3,[sp,#8*6] + + ldp $m0,$m1,[$np,#8*0] // n[0..3] + mov $tp,sp + ldp $m2,$m3,[$np,#8*2] + adds $np,$np,#8*4 // clear carry bit + mov $carry,xzr + +.align 4 +.Loop_mul4x_reduction: + mul $t0,$a0,$bi // lo(a[0..3]*b[4]) + adc $carry,$carry,xzr // modulo-scheduled + mul $t1,$a1,$bi + add $cnt,$cnt,#8 + mul $t2,$a2,$bi + and $cnt,$cnt,#31 + mul $t3,$a3,$bi + adds $acc0,$acc0,$t0 + umulh $t0,$a0,$bi // hi(a[0..3]*b[4]) + adcs $acc1,$acc1,$t1 + mul $mi,$acc0,$n0 // t[0]*n0 + adcs $acc2,$acc2,$t2 + umulh $t1,$a1,$bi + adcs $acc3,$acc3,$t3 + umulh $t2,$a2,$bi + adc $acc4,xzr,xzr + umulh $t3,$a3,$bi + ldr $bi,[$bp,$cnt] // next b[i] + adds $acc1,$acc1,$t0 + // (*) mul $t0,$m0,$mi + str $mi,[$tp],#8 // put aside t[0]*n0 for tail processing + adcs $acc2,$acc2,$t1 + mul $t1,$m1,$mi // lo(n[0..3]*t[0]*n0 + adcs $acc3,$acc3,$t2 + mul $t2,$m2,$mi + adc $acc4,$acc4,$t3 // can't overflow + mul $t3,$m3,$mi + // (*) adds xzr,$acc0,$t0 + subs xzr,$acc0,#1 // (*) + umulh $t0,$m0,$mi // hi(n[0..3]*t[0]*n0 + adcs $acc0,$acc1,$t1 + umulh $t1,$m1,$mi + adcs $acc1,$acc2,$t2 + umulh $t2,$m2,$mi + adcs $acc2,$acc3,$t3 + umulh $t3,$m3,$mi + adcs $acc3,$acc4,$carry + adc $carry,xzr,xzr + adds $acc0,$acc0,$t0 + adcs $acc1,$acc1,$t1 + adcs $acc2,$acc2,$t2 + adcs $acc3,$acc3,$t3 + //adc $carry,$carry,xzr + cbnz $cnt,.Loop_mul4x_reduction + + adc $carry,$carry,xzr + ldp $t0,$t1,[$tp,#8*4] // t[4..7] + ldp $t2,$t3,[$tp,#8*6] + ldp $a0,$a1,[$ap,#8*0] // a[4..7] + ldp $a2,$a3,[$ap,#8*2] + add $ap,$ap,#8*4 + adds $acc0,$acc0,$t0 + adcs $acc1,$acc1,$t1 + adcs $acc2,$acc2,$t2 + adcs $acc3,$acc3,$t3 + //adc $carry,$carry,xzr + + ldr $mi,[sp] // t[0]*n0 + ldp $m0,$m1,[$np,#8*0] // n[4..7] + ldp $m2,$m3,[$np,#8*2] + add $np,$np,#8*4 + +.align 4 +.Loop_mul4x_tail: + mul $t0,$a0,$bi // lo(a[4..7]*b[4]) + adc $carry,$carry,xzr // modulo-scheduled + mul $t1,$a1,$bi + add $cnt,$cnt,#8 + mul $t2,$a2,$bi + and $cnt,$cnt,#31 + mul $t3,$a3,$bi + adds $acc0,$acc0,$t0 + umulh $t0,$a0,$bi // hi(a[4..7]*b[4]) + adcs $acc1,$acc1,$t1 + umulh $t1,$a1,$bi + adcs $acc2,$acc2,$t2 + umulh $t2,$a2,$bi + adcs $acc3,$acc3,$t3 + umulh $t3,$a3,$bi + adc $acc4,xzr,xzr + ldr $bi,[$bp,$cnt] // next b[i] + adds $acc1,$acc1,$t0 + mul $t0,$m0,$mi // lo(n[4..7]*t[0]*n0) + adcs $acc2,$acc2,$t1 + mul $t1,$m1,$mi + adcs $acc3,$acc3,$t2 + mul $t2,$m2,$mi + adc $acc4,$acc4,$t3 // can't overflow + mul $t3,$m3,$mi + adds $acc0,$acc0,$t0 + umulh $t0,$m0,$mi // hi(n[4..7]*t[0]*n0) + adcs $acc1,$acc1,$t1 + umulh $t1,$m1,$mi + adcs $acc2,$acc2,$t2 + umulh $t2,$m2,$mi + adcs $acc3,$acc3,$t3 + umulh $t3,$m3,$mi + adcs $acc4,$acc4,$carry + ldr $mi,[sp,$cnt] // next a[0]*n0 + adc $carry,xzr,xzr + str $acc0,[$tp],#8 // result!!! + adds $acc0,$acc1,$t0 + sub $t0,$ap_end,$ap // done yet? + adcs $acc1,$acc2,$t1 + adcs $acc2,$acc3,$t2 + adcs $acc3,$acc4,$t3 + //adc $carry,$carry,xzr + cbnz $cnt,.Loop_mul4x_tail + + sub $t1,$np,$num // rewinded np? + adc $carry,$carry,xzr + cbz $t0,.Loop_mul4x_break + + ldp $t0,$t1,[$tp,#8*4] + ldp $t2,$t3,[$tp,#8*6] + ldp $a0,$a1,[$ap,#8*0] + ldp $a2,$a3,[$ap,#8*2] + add $ap,$ap,#8*4 + adds $acc0,$acc0,$t0 + adcs $acc1,$acc1,$t1 + adcs $acc2,$acc2,$t2 + adcs $acc3,$acc3,$t3 + //adc $carry,$carry,xzr + ldp $m0,$m1,[$np,#8*0] + ldp $m2,$m3,[$np,#8*2] + add $np,$np,#8*4 + b .Loop_mul4x_tail + +.align 4 +.Loop_mul4x_break: + ldp $t2,$t3,[x29,#96] // pull rp and &b[num] + adds $acc0,$acc0,$topmost + add $bp,$bp,#8*4 // bp++ + adcs $acc1,$acc1,xzr + sub $ap,$ap,$num // rewind ap + adcs $acc2,$acc2,xzr + stp $acc0,$acc1,[$tp,#8*0] // result!!! + adcs $acc3,$acc3,xzr + ldp $acc0,$acc1,[sp,#8*4] // t[0..3] + adc $topmost,$carry,xzr + stp $acc2,$acc3,[$tp,#8*2] // result!!! + cmp $bp,$t3 // done yet? + ldp $acc2,$acc3,[sp,#8*6] + ldp $m0,$m1,[$t1,#8*0] // n[0..3] + ldp $m2,$m3,[$t1,#8*2] + add $np,$t1,#8*4 + b.eq .Lmul4x_post + + ldr $bi,[$bp] + ldp $a0,$a1,[$ap,#8*0] // a[0..3] + ldp $a2,$a3,[$ap,#8*2] + adds $ap,$ap,#8*4 // clear carry bit + mov $carry,xzr + mov $tp,sp + b .Loop_mul4x_reduction + +.align 4 +.Lmul4x_post: + // Final step. We see if result is larger than modulus, and + // if it is, subtract the modulus. But comparison implies + // subtraction. So we subtract modulus, see if it borrowed, + // and conditionally copy original value. + mov $rp,$t2 + mov $ap_end,$t2 // $rp copy + subs $t0,$acc0,$m0 + add $tp,sp,#8*8 + sbcs $t1,$acc1,$m1 + sub $cnt,$num,#8*4 + +.Lmul4x_sub: + sbcs $t2,$acc2,$m2 + ldp $m0,$m1,[$np,#8*0] + sub $cnt,$cnt,#8*4 + ldp $acc0,$acc1,[$tp,#8*0] + sbcs $t3,$acc3,$m3 + ldp $m2,$m3,[$np,#8*2] + add $np,$np,#8*4 + ldp $acc2,$acc3,[$tp,#8*2] + add $tp,$tp,#8*4 + stp $t0,$t1,[$rp,#8*0] + sbcs $t0,$acc0,$m0 + stp $t2,$t3,[$rp,#8*2] + add $rp,$rp,#8*4 + sbcs $t1,$acc1,$m1 + cbnz $cnt,.Lmul4x_sub + + sbcs $t2,$acc2,$m2 + mov $tp,sp + add $ap,sp,#8*4 + ldp $a0,$a1,[$ap_end,#8*0] + sbcs $t3,$acc3,$m3 + stp $t0,$t1,[$rp,#8*0] + ldp $a2,$a3,[$ap_end,#8*2] + stp $t2,$t3,[$rp,#8*2] + ldp $acc0,$acc1,[$ap,#8*0] + ldp $acc2,$acc3,[$ap,#8*2] + sbcs xzr,$topmost,xzr // did it borrow? + ldr x30,[x29,#8] // pull return address + + sub $cnt,$num,#8*4 +.Lmul4x_cond_copy: + sub $cnt,$cnt,#8*4 + csel $t0,$acc0,$a0,lo + stp xzr,xzr,[$tp,#8*0] + csel $t1,$acc1,$a1,lo + ldp $a0,$a1,[$ap_end,#8*4] + ldp $acc0,$acc1,[$ap,#8*4] + csel $t2,$acc2,$a2,lo + stp xzr,xzr,[$tp,#8*2] + add $tp,$tp,#8*4 + csel $t3,$acc3,$a3,lo + ldp $a2,$a3,[$ap_end,#8*6] + ldp $acc2,$acc3,[$ap,#8*6] + add $ap,$ap,#8*4 + stp $t0,$t1,[$ap_end,#8*0] + stp $t2,$t3,[$ap_end,#8*2] + add $ap_end,$ap_end,#8*4 + cbnz $cnt,.Lmul4x_cond_copy + + csel $t0,$acc0,$a0,lo + stp xzr,xzr,[$tp,#8*0] + csel $t1,$acc1,$a1,lo + stp xzr,xzr,[$tp,#8*2] + csel $t2,$acc2,$a2,lo + stp xzr,xzr,[$tp,#8*3] + csel $t3,$acc3,$a3,lo + stp xzr,xzr,[$tp,#8*4] + stp $t0,$t1,[$ap_end,#8*0] + stp $t2,$t3,[$ap_end,#8*2] + + b .Lmul4x_done + +.align 4 +.Lmul4x4_post_condition: + adc $carry,$carry,xzr + ldr $ap,[x29,#96] // pull rp + // $acc0-3,$carry hold result, $m0-7 hold modulus + subs $a0,$acc0,$m0 + ldr x30,[x29,#8] // pull return address + sbcs $a1,$acc1,$m1 + stp xzr,xzr,[sp,#8*0] + sbcs $a2,$acc2,$m2 + stp xzr,xzr,[sp,#8*2] + sbcs $a3,$acc3,$m3 + stp xzr,xzr,[sp,#8*4] + sbcs xzr,$carry,xzr // did it borrow? + stp xzr,xzr,[sp,#8*6] + + // $a0-3 hold result-modulus + csel $a0,$acc0,$a0,lo + csel $a1,$acc1,$a1,lo + csel $a2,$acc2,$a2,lo + csel $a3,$acc3,$a3,lo + stp $a0,$a1,[$ap,#8*0] + stp $a2,$a3,[$ap,#8*2] + +.Lmul4x_done: + ldp x19,x20,[x29,#16] + mov sp,x29 + ldp x21,x22,[x29,#32] + mov x0,#1 + ldp x23,x24,[x29,#48] + ldp x25,x26,[x29,#64] + ldp x27,x28,[x29,#80] + ldr x29,[sp],#128 + ret +.size __bn_mul4x_mont,.-__bn_mul4x_mont +___ +} +$code.=<<___; +.asciz "Montgomery Multiplication for ARMv8, CRYPTOGAMS by " +.align 4 +___ + +print $code; + +close STDOUT; diff --git a/external/boringssl/crypto/bn/asm/bn-586.pl b/external/boringssl/crypto/bn/asm/bn-586.pl new file mode 100644 index 0000000000..26d9bcbb09 --- /dev/null +++ b/external/boringssl/crypto/bn/asm/bn-586.pl @@ -0,0 +1,774 @@ +#!/usr/bin/env perl + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +push(@INC,"${dir}","${dir}../../perlasm"); +require "x86asm.pl"; + +&asm_init($ARGV[0],$0); + +$sse2=0; +for (@ARGV) { $sse2=1 if (/-DOPENSSL_IA32_SSE2/); } + +&external_label("OPENSSL_ia32cap_P") if ($sse2); + +&bn_mul_add_words("bn_mul_add_words"); +&bn_mul_words("bn_mul_words"); +&bn_sqr_words("bn_sqr_words"); +&bn_div_words("bn_div_words"); +&bn_add_words("bn_add_words"); +&bn_sub_words("bn_sub_words"); +&bn_sub_part_words("bn_sub_part_words"); + +&asm_finish(); + +sub bn_mul_add_words + { + local($name)=@_; + + &function_begin_B($name,$sse2?"EXTRN\t_OPENSSL_ia32cap_P:DWORD":""); + + $r="eax"; + $a="edx"; + $c="ecx"; + + if ($sse2) { + &picmeup("eax","OPENSSL_ia32cap_P"); + &bt(&DWP(0,"eax"),26); + &jnc(&label("maw_non_sse2")); + + &mov($r,&wparam(0)); + &mov($a,&wparam(1)); + &mov($c,&wparam(2)); + &movd("mm0",&wparam(3)); # mm0 = w + &pxor("mm1","mm1"); # mm1 = carry_in + &jmp(&label("maw_sse2_entry")); + + &set_label("maw_sse2_unrolled",16); + &movd("mm3",&DWP(0,$r,"",0)); # mm3 = r[0] + &paddq("mm1","mm3"); # mm1 = carry_in + r[0] + &movd("mm2",&DWP(0,$a,"",0)); # mm2 = a[0] + &pmuludq("mm2","mm0"); # mm2 = w*a[0] + &movd("mm4",&DWP(4,$a,"",0)); # mm4 = a[1] + &pmuludq("mm4","mm0"); # mm4 = w*a[1] + &movd("mm6",&DWP(8,$a,"",0)); # mm6 = a[2] + &pmuludq("mm6","mm0"); # mm6 = w*a[2] + &movd("mm7",&DWP(12,$a,"",0)); # mm7 = a[3] + &pmuludq("mm7","mm0"); # mm7 = w*a[3] + &paddq("mm1","mm2"); # mm1 = carry_in + r[0] + w*a[0] + &movd("mm3",&DWP(4,$r,"",0)); # mm3 = r[1] + &paddq("mm3","mm4"); # mm3 = r[1] + w*a[1] + &movd("mm5",&DWP(8,$r,"",0)); # mm5 = r[2] + &paddq("mm5","mm6"); # mm5 = r[2] + w*a[2] + &movd("mm4",&DWP(12,$r,"",0)); # mm4 = r[3] + &paddq("mm7","mm4"); # mm7 = r[3] + w*a[3] + &movd(&DWP(0,$r,"",0),"mm1"); + &movd("mm2",&DWP(16,$a,"",0)); # mm2 = a[4] + &pmuludq("mm2","mm0"); # mm2 = w*a[4] + &psrlq("mm1",32); # mm1 = carry0 + &movd("mm4",&DWP(20,$a,"",0)); # mm4 = a[5] + &pmuludq("mm4","mm0"); # mm4 = w*a[5] + &paddq("mm1","mm3"); # mm1 = carry0 + r[1] + w*a[1] + &movd("mm6",&DWP(24,$a,"",0)); # mm6 = a[6] + &pmuludq("mm6","mm0"); # mm6 = w*a[6] + &movd(&DWP(4,$r,"",0),"mm1"); + &psrlq("mm1",32); # mm1 = carry1 + &movd("mm3",&DWP(28,$a,"",0)); # mm3 = a[7] + &add($a,32); + &pmuludq("mm3","mm0"); # mm3 = w*a[7] + &paddq("mm1","mm5"); # mm1 = carry1 + r[2] + w*a[2] + &movd("mm5",&DWP(16,$r,"",0)); # mm5 = r[4] + &paddq("mm2","mm5"); # mm2 = r[4] + w*a[4] + &movd(&DWP(8,$r,"",0),"mm1"); + &psrlq("mm1",32); # mm1 = carry2 + &paddq("mm1","mm7"); # mm1 = carry2 + r[3] + w*a[3] + &movd("mm5",&DWP(20,$r,"",0)); # mm5 = r[5] + &paddq("mm4","mm5"); # mm4 = r[5] + w*a[5] + &movd(&DWP(12,$r,"",0),"mm1"); + &psrlq("mm1",32); # mm1 = carry3 + &paddq("mm1","mm2"); # mm1 = carry3 + r[4] + w*a[4] + &movd("mm5",&DWP(24,$r,"",0)); # mm5 = r[6] + &paddq("mm6","mm5"); # mm6 = r[6] + w*a[6] + &movd(&DWP(16,$r,"",0),"mm1"); + &psrlq("mm1",32); # mm1 = carry4 + &paddq("mm1","mm4"); # mm1 = carry4 + r[5] + w*a[5] + &movd("mm5",&DWP(28,$r,"",0)); # mm5 = r[7] + &paddq("mm3","mm5"); # mm3 = r[7] + w*a[7] + &movd(&DWP(20,$r,"",0),"mm1"); + &psrlq("mm1",32); # mm1 = carry5 + &paddq("mm1","mm6"); # mm1 = carry5 + r[6] + w*a[6] + &movd(&DWP(24,$r,"",0),"mm1"); + &psrlq("mm1",32); # mm1 = carry6 + &paddq("mm1","mm3"); # mm1 = carry6 + r[7] + w*a[7] + &movd(&DWP(28,$r,"",0),"mm1"); + &lea($r,&DWP(32,$r)); + &psrlq("mm1",32); # mm1 = carry_out + + &sub($c,8); + &jz(&label("maw_sse2_exit")); + &set_label("maw_sse2_entry"); + &test($c,0xfffffff8); + &jnz(&label("maw_sse2_unrolled")); + + &set_label("maw_sse2_loop",4); + &movd("mm2",&DWP(0,$a)); # mm2 = a[i] + &movd("mm3",&DWP(0,$r)); # mm3 = r[i] + &pmuludq("mm2","mm0"); # a[i] *= w + &lea($a,&DWP(4,$a)); + &paddq("mm1","mm3"); # carry += r[i] + &paddq("mm1","mm2"); # carry += a[i]*w + &movd(&DWP(0,$r),"mm1"); # r[i] = carry_low + &sub($c,1); + &psrlq("mm1",32); # carry = carry_high + &lea($r,&DWP(4,$r)); + &jnz(&label("maw_sse2_loop")); + &set_label("maw_sse2_exit"); + &movd("eax","mm1"); # c = carry_out + &emms(); + &ret(); + + &set_label("maw_non_sse2",16); + } + + # function_begin prologue + &push("ebp"); + &push("ebx"); + &push("esi"); + &push("edi"); + + &comment(""); + $Low="eax"; + $High="edx"; + $a="ebx"; + $w="ebp"; + $r="edi"; + $c="esi"; + + &xor($c,$c); # clear carry + &mov($r,&wparam(0)); # + + &mov("ecx",&wparam(2)); # + &mov($a,&wparam(1)); # + + &and("ecx",0xfffffff8); # num / 8 + &mov($w,&wparam(3)); # + + &push("ecx"); # Up the stack for a tmp variable + + &jz(&label("maw_finish")); + + &set_label("maw_loop",16); + + for ($i=0; $i<32; $i+=4) + { + &comment("Round $i"); + + &mov("eax",&DWP($i,$a)); # *a + &mul($w); # *a * w + &add("eax",$c); # L(t)+= c + &adc("edx",0); # H(t)+=carry + &add("eax",&DWP($i,$r)); # L(t)+= *r + &adc("edx",0); # H(t)+=carry + &mov(&DWP($i,$r),"eax"); # *r= L(t); + &mov($c,"edx"); # c= H(t); + } + + &comment(""); + &sub("ecx",8); + &lea($a,&DWP(32,$a)); + &lea($r,&DWP(32,$r)); + &jnz(&label("maw_loop")); + + &set_label("maw_finish",0); + &mov("ecx",&wparam(2)); # get num + &and("ecx",7); + &jnz(&label("maw_finish2")); # helps branch prediction + &jmp(&label("maw_end")); + + &set_label("maw_finish2",1); + for ($i=0; $i<7; $i++) + { + &comment("Tail Round $i"); + &mov("eax",&DWP($i*4,$a)); # *a + &mul($w); # *a * w + &add("eax",$c); # L(t)+=c + &adc("edx",0); # H(t)+=carry + &add("eax",&DWP($i*4,$r)); # L(t)+= *r + &adc("edx",0); # H(t)+=carry + &dec("ecx") if ($i != 7-1); + &mov(&DWP($i*4,$r),"eax"); # *r= L(t); + &mov($c,"edx"); # c= H(t); + &jz(&label("maw_end")) if ($i != 7-1); + } + &set_label("maw_end",0); + &mov("eax",$c); + + &pop("ecx"); # clear variable from + + &function_end($name); + } + +sub bn_mul_words + { + local($name)=@_; + + &function_begin_B($name,$sse2?"EXTRN\t_OPENSSL_ia32cap_P:DWORD":""); + + $r="eax"; + $a="edx"; + $c="ecx"; + + if ($sse2) { + &picmeup("eax","OPENSSL_ia32cap_P"); + &bt(&DWP(0,"eax"),26); + &jnc(&label("mw_non_sse2")); + + &mov($r,&wparam(0)); + &mov($a,&wparam(1)); + &mov($c,&wparam(2)); + &movd("mm0",&wparam(3)); # mm0 = w + &pxor("mm1","mm1"); # mm1 = carry = 0 + + &set_label("mw_sse2_loop",16); + &movd("mm2",&DWP(0,$a)); # mm2 = a[i] + &pmuludq("mm2","mm0"); # a[i] *= w + &lea($a,&DWP(4,$a)); + &paddq("mm1","mm2"); # carry += a[i]*w + &movd(&DWP(0,$r),"mm1"); # r[i] = carry_low + &sub($c,1); + &psrlq("mm1",32); # carry = carry_high + &lea($r,&DWP(4,$r)); + &jnz(&label("mw_sse2_loop")); + + &movd("eax","mm1"); # return carry + &emms(); + &ret(); + &set_label("mw_non_sse2",16); + } + + # function_begin prologue + &push("ebp"); + &push("ebx"); + &push("esi"); + &push("edi"); + + &comment(""); + $Low="eax"; + $High="edx"; + $a="ebx"; + $w="ecx"; + $r="edi"; + $c="esi"; + $num="ebp"; + + &xor($c,$c); # clear carry + &mov($r,&wparam(0)); # + &mov($a,&wparam(1)); # + &mov($num,&wparam(2)); # + &mov($w,&wparam(3)); # + + &and($num,0xfffffff8); # num / 8 + &jz(&label("mw_finish")); + + &set_label("mw_loop",0); + for ($i=0; $i<32; $i+=4) + { + &comment("Round $i"); + + &mov("eax",&DWP($i,$a,"",0)); # *a + &mul($w); # *a * w + &add("eax",$c); # L(t)+=c + # XXX + + &adc("edx",0); # H(t)+=carry + &mov(&DWP($i,$r,"",0),"eax"); # *r= L(t); + + &mov($c,"edx"); # c= H(t); + } + + &comment(""); + &add($a,32); + &add($r,32); + &sub($num,8); + &jz(&label("mw_finish")); + &jmp(&label("mw_loop")); + + &set_label("mw_finish",0); + &mov($num,&wparam(2)); # get num + &and($num,7); + &jnz(&label("mw_finish2")); + &jmp(&label("mw_end")); + + &set_label("mw_finish2",1); + for ($i=0; $i<7; $i++) + { + &comment("Tail Round $i"); + &mov("eax",&DWP($i*4,$a,"",0));# *a + &mul($w); # *a * w + &add("eax",$c); # L(t)+=c + # XXX + &adc("edx",0); # H(t)+=carry + &mov(&DWP($i*4,$r,"",0),"eax");# *r= L(t); + &mov($c,"edx"); # c= H(t); + &dec($num) if ($i != 7-1); + &jz(&label("mw_end")) if ($i != 7-1); + } + &set_label("mw_end",0); + &mov("eax",$c); + + &function_end($name); + } + +sub bn_sqr_words + { + local($name)=@_; + + &function_begin_B($name,$sse2?"EXTRN\t_OPENSSL_ia32cap_P:DWORD":""); + + $r="eax"; + $a="edx"; + $c="ecx"; + + if ($sse2) { + &picmeup("eax","OPENSSL_ia32cap_P"); + &bt(&DWP(0,"eax"),26); + &jnc(&label("sqr_non_sse2")); + + &mov($r,&wparam(0)); + &mov($a,&wparam(1)); + &mov($c,&wparam(2)); + + &set_label("sqr_sse2_loop",16); + &movd("mm0",&DWP(0,$a)); # mm0 = a[i] + &pmuludq("mm0","mm0"); # a[i] *= a[i] + &lea($a,&DWP(4,$a)); # a++ + &movq(&QWP(0,$r),"mm0"); # r[i] = a[i]*a[i] + &sub($c,1); + &lea($r,&DWP(8,$r)); # r += 2 + &jnz(&label("sqr_sse2_loop")); + + &emms(); + &ret(); + &set_label("sqr_non_sse2",16); + } + + # function_begin prologue + &push("ebp"); + &push("ebx"); + &push("esi"); + &push("edi"); + + &comment(""); + $r="esi"; + $a="edi"; + $num="ebx"; + + &mov($r,&wparam(0)); # + &mov($a,&wparam(1)); # + &mov($num,&wparam(2)); # + + &and($num,0xfffffff8); # num / 8 + &jz(&label("sw_finish")); + + &set_label("sw_loop",0); + for ($i=0; $i<32; $i+=4) + { + &comment("Round $i"); + &mov("eax",&DWP($i,$a,"",0)); # *a + # XXX + &mul("eax"); # *a * *a + &mov(&DWP($i*2,$r,"",0),"eax"); # + &mov(&DWP($i*2+4,$r,"",0),"edx");# + } + + &comment(""); + &add($a,32); + &add($r,64); + &sub($num,8); + &jnz(&label("sw_loop")); + + &set_label("sw_finish",0); + &mov($num,&wparam(2)); # get num + &and($num,7); + &jz(&label("sw_end")); + + for ($i=0; $i<7; $i++) + { + &comment("Tail Round $i"); + &mov("eax",&DWP($i*4,$a,"",0)); # *a + # XXX + &mul("eax"); # *a * *a + &mov(&DWP($i*8,$r,"",0),"eax"); # + &dec($num) if ($i != 7-1); + &mov(&DWP($i*8+4,$r,"",0),"edx"); + &jz(&label("sw_end")) if ($i != 7-1); + } + &set_label("sw_end",0); + + &function_end($name); + } + +sub bn_div_words + { + local($name)=@_; + + &function_begin_B($name,""); + &mov("edx",&wparam(0)); # + &mov("eax",&wparam(1)); # + &mov("ecx",&wparam(2)); # + &div("ecx"); + &ret(); + &function_end_B($name); + } + +sub bn_add_words + { + local($name)=@_; + + &function_begin($name,""); + + &comment(""); + $a="esi"; + $b="edi"; + $c="eax"; + $r="ebx"; + $tmp1="ecx"; + $tmp2="edx"; + $num="ebp"; + + &mov($r,&wparam(0)); # get r + &mov($a,&wparam(1)); # get a + &mov($b,&wparam(2)); # get b + &mov($num,&wparam(3)); # get num + &xor($c,$c); # clear carry + &and($num,0xfffffff8); # num / 8 + + &jz(&label("aw_finish")); + + &set_label("aw_loop",0); + for ($i=0; $i<8; $i++) + { + &comment("Round $i"); + + &mov($tmp1,&DWP($i*4,$a,"",0)); # *a + &mov($tmp2,&DWP($i*4,$b,"",0)); # *b + &add($tmp1,$c); + &mov($c,0); + &adc($c,$c); + &add($tmp1,$tmp2); + &adc($c,0); + &mov(&DWP($i*4,$r,"",0),$tmp1); # *r + } + + &comment(""); + &add($a,32); + &add($b,32); + &add($r,32); + &sub($num,8); + &jnz(&label("aw_loop")); + + &set_label("aw_finish",0); + &mov($num,&wparam(3)); # get num + &and($num,7); + &jz(&label("aw_end")); + + for ($i=0; $i<7; $i++) + { + &comment("Tail Round $i"); + &mov($tmp1,&DWP($i*4,$a,"",0)); # *a + &mov($tmp2,&DWP($i*4,$b,"",0));# *b + &add($tmp1,$c); + &mov($c,0); + &adc($c,$c); + &add($tmp1,$tmp2); + &adc($c,0); + &dec($num) if ($i != 6); + &mov(&DWP($i*4,$r,"",0),$tmp1); # *r + &jz(&label("aw_end")) if ($i != 6); + } + &set_label("aw_end",0); + +# &mov("eax",$c); # $c is "eax" + + &function_end($name); + } + +sub bn_sub_words + { + local($name)=@_; + + &function_begin($name,""); + + &comment(""); + $a="esi"; + $b="edi"; + $c="eax"; + $r="ebx"; + $tmp1="ecx"; + $tmp2="edx"; + $num="ebp"; + + &mov($r,&wparam(0)); # get r + &mov($a,&wparam(1)); # get a + &mov($b,&wparam(2)); # get b + &mov($num,&wparam(3)); # get num + &xor($c,$c); # clear carry + &and($num,0xfffffff8); # num / 8 + + &jz(&label("aw_finish")); + + &set_label("aw_loop",0); + for ($i=0; $i<8; $i++) + { + &comment("Round $i"); + + &mov($tmp1,&DWP($i*4,$a,"",0)); # *a + &mov($tmp2,&DWP($i*4,$b,"",0)); # *b + &sub($tmp1,$c); + &mov($c,0); + &adc($c,$c); + &sub($tmp1,$tmp2); + &adc($c,0); + &mov(&DWP($i*4,$r,"",0),$tmp1); # *r + } + + &comment(""); + &add($a,32); + &add($b,32); + &add($r,32); + &sub($num,8); + &jnz(&label("aw_loop")); + + &set_label("aw_finish",0); + &mov($num,&wparam(3)); # get num + &and($num,7); + &jz(&label("aw_end")); + + for ($i=0; $i<7; $i++) + { + &comment("Tail Round $i"); + &mov($tmp1,&DWP($i*4,$a,"",0)); # *a + &mov($tmp2,&DWP($i*4,$b,"",0));# *b + &sub($tmp1,$c); + &mov($c,0); + &adc($c,$c); + &sub($tmp1,$tmp2); + &adc($c,0); + &dec($num) if ($i != 6); + &mov(&DWP($i*4,$r,"",0),$tmp1); # *r + &jz(&label("aw_end")) if ($i != 6); + } + &set_label("aw_end",0); + +# &mov("eax",$c); # $c is "eax" + + &function_end($name); + } + +sub bn_sub_part_words + { + local($name)=@_; + + &function_begin($name,""); + + &comment(""); + $a="esi"; + $b="edi"; + $c="eax"; + $r="ebx"; + $tmp1="ecx"; + $tmp2="edx"; + $num="ebp"; + + &mov($r,&wparam(0)); # get r + &mov($a,&wparam(1)); # get a + &mov($b,&wparam(2)); # get b + &mov($num,&wparam(3)); # get num + &xor($c,$c); # clear carry + &and($num,0xfffffff8); # num / 8 + + &jz(&label("aw_finish")); + + &set_label("aw_loop",0); + for ($i=0; $i<8; $i++) + { + &comment("Round $i"); + + &mov($tmp1,&DWP($i*4,$a,"",0)); # *a + &mov($tmp2,&DWP($i*4,$b,"",0)); # *b + &sub($tmp1,$c); + &mov($c,0); + &adc($c,$c); + &sub($tmp1,$tmp2); + &adc($c,0); + &mov(&DWP($i*4,$r,"",0),$tmp1); # *r + } + + &comment(""); + &add($a,32); + &add($b,32); + &add($r,32); + &sub($num,8); + &jnz(&label("aw_loop")); + + &set_label("aw_finish",0); + &mov($num,&wparam(3)); # get num + &and($num,7); + &jz(&label("aw_end")); + + for ($i=0; $i<7; $i++) + { + &comment("Tail Round $i"); + &mov($tmp1,&DWP(0,$a,"",0)); # *a + &mov($tmp2,&DWP(0,$b,"",0));# *b + &sub($tmp1,$c); + &mov($c,0); + &adc($c,$c); + &sub($tmp1,$tmp2); + &adc($c,0); + &mov(&DWP(0,$r,"",0),$tmp1); # *r + &add($a, 4); + &add($b, 4); + &add($r, 4); + &dec($num) if ($i != 6); + &jz(&label("aw_end")) if ($i != 6); + } + &set_label("aw_end",0); + + &cmp(&wparam(4),0); + &je(&label("pw_end")); + + &mov($num,&wparam(4)); # get dl + &cmp($num,0); + &je(&label("pw_end")); + &jge(&label("pw_pos")); + + &comment("pw_neg"); + &mov($tmp2,0); + &sub($tmp2,$num); + &mov($num,$tmp2); + &and($num,0xfffffff8); # num / 8 + &jz(&label("pw_neg_finish")); + + &set_label("pw_neg_loop",0); + for ($i=0; $i<8; $i++) + { + &comment("dl<0 Round $i"); + + &mov($tmp1,0); + &mov($tmp2,&DWP($i*4,$b,"",0)); # *b + &sub($tmp1,$c); + &mov($c,0); + &adc($c,$c); + &sub($tmp1,$tmp2); + &adc($c,0); + &mov(&DWP($i*4,$r,"",0),$tmp1); # *r + } + + &comment(""); + &add($b,32); + &add($r,32); + &sub($num,8); + &jnz(&label("pw_neg_loop")); + + &set_label("pw_neg_finish",0); + &mov($tmp2,&wparam(4)); # get dl + &mov($num,0); + &sub($num,$tmp2); + &and($num,7); + &jz(&label("pw_end")); + + for ($i=0; $i<7; $i++) + { + &comment("dl<0 Tail Round $i"); + &mov($tmp1,0); + &mov($tmp2,&DWP($i*4,$b,"",0));# *b + &sub($tmp1,$c); + &mov($c,0); + &adc($c,$c); + &sub($tmp1,$tmp2); + &adc($c,0); + &dec($num) if ($i != 6); + &mov(&DWP($i*4,$r,"",0),$tmp1); # *r + &jz(&label("pw_end")) if ($i != 6); + } + + &jmp(&label("pw_end")); + + &set_label("pw_pos",0); + + &and($num,0xfffffff8); # num / 8 + &jz(&label("pw_pos_finish")); + + &set_label("pw_pos_loop",0); + + for ($i=0; $i<8; $i++) + { + &comment("dl>0 Round $i"); + + &mov($tmp1,&DWP($i*4,$a,"",0)); # *a + &sub($tmp1,$c); + &mov(&DWP($i*4,$r,"",0),$tmp1); # *r + &jnc(&label("pw_nc".$i)); + } + + &comment(""); + &add($a,32); + &add($r,32); + &sub($num,8); + &jnz(&label("pw_pos_loop")); + + &set_label("pw_pos_finish",0); + &mov($num,&wparam(4)); # get dl + &and($num,7); + &jz(&label("pw_end")); + + for ($i=0; $i<7; $i++) + { + &comment("dl>0 Tail Round $i"); + &mov($tmp1,&DWP($i*4,$a,"",0)); # *a + &sub($tmp1,$c); + &mov(&DWP($i*4,$r,"",0),$tmp1); # *r + &jnc(&label("pw_tail_nc".$i)); + &dec($num) if ($i != 6); + &jz(&label("pw_end")) if ($i != 6); + } + &mov($c,1); + &jmp(&label("pw_end")); + + &set_label("pw_nc_loop",0); + for ($i=0; $i<8; $i++) + { + &mov($tmp1,&DWP($i*4,$a,"",0)); # *a + &mov(&DWP($i*4,$r,"",0),$tmp1); # *r + &set_label("pw_nc".$i,0); + } + + &comment(""); + &add($a,32); + &add($r,32); + &sub($num,8); + &jnz(&label("pw_nc_loop")); + + &mov($num,&wparam(4)); # get dl + &and($num,7); + &jz(&label("pw_nc_end")); + + for ($i=0; $i<7; $i++) + { + &mov($tmp1,&DWP($i*4,$a,"",0)); # *a + &mov(&DWP($i*4,$r,"",0),$tmp1); # *r + &set_label("pw_tail_nc".$i,0); + &dec($num) if ($i != 6); + &jz(&label("pw_nc_end")) if ($i != 6); + } + + &set_label("pw_nc_end",0); + &mov($c,0); + + &set_label("pw_end",0); + +# &mov("eax",$c); # $c is "eax" + + &function_end($name); + } + diff --git a/external/boringssl/crypto/bn/asm/co-586.pl b/external/boringssl/crypto/bn/asm/co-586.pl new file mode 100644 index 0000000000..57101a6bd7 --- /dev/null +++ b/external/boringssl/crypto/bn/asm/co-586.pl @@ -0,0 +1,287 @@ +#!/usr/local/bin/perl + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +push(@INC,"${dir}","${dir}../../perlasm"); +require "x86asm.pl"; + +&asm_init($ARGV[0],$0); + +&bn_mul_comba("bn_mul_comba8",8); +&bn_mul_comba("bn_mul_comba4",4); +&bn_sqr_comba("bn_sqr_comba8",8); +&bn_sqr_comba("bn_sqr_comba4",4); + +&asm_finish(); + +sub mul_add_c + { + local($a,$ai,$b,$bi,$c0,$c1,$c2,$pos,$i,$na,$nb)=@_; + + # pos == -1 if eax and edx are pre-loaded, 0 to load from next + # words, and 1 if load return value + + &comment("mul a[$ai]*b[$bi]"); + + # "eax" and "edx" will always be pre-loaded. + # &mov("eax",&DWP($ai*4,$a,"",0)) ; + # &mov("edx",&DWP($bi*4,$b,"",0)); + + &mul("edx"); + &add($c0,"eax"); + &mov("eax",&DWP(($na)*4,$a,"",0)) if $pos == 0; # laod next a + &mov("eax",&wparam(0)) if $pos > 0; # load r[] + ### + &adc($c1,"edx"); + &mov("edx",&DWP(($nb)*4,$b,"",0)) if $pos == 0; # laod next b + &mov("edx",&DWP(($nb)*4,$b,"",0)) if $pos == 1; # laod next b + ### + &adc($c2,0); + # is pos > 1, it means it is the last loop + &mov(&DWP($i*4,"eax","",0),$c0) if $pos > 0; # save r[]; + &mov("eax",&DWP(($na)*4,$a,"",0)) if $pos == 1; # laod next a + } + +sub sqr_add_c + { + local($r,$a,$ai,$bi,$c0,$c1,$c2,$pos,$i,$na,$nb)=@_; + + # pos == -1 if eax and edx are pre-loaded, 0 to load from next + # words, and 1 if load return value + + &comment("sqr a[$ai]*a[$bi]"); + + # "eax" and "edx" will always be pre-loaded. + # &mov("eax",&DWP($ai*4,$a,"",0)) ; + # &mov("edx",&DWP($bi*4,$b,"",0)); + + if ($ai == $bi) + { &mul("eax");} + else + { &mul("edx");} + &add($c0,"eax"); + &mov("eax",&DWP(($na)*4,$a,"",0)) if $pos == 0; # load next a + ### + &adc($c1,"edx"); + &mov("edx",&DWP(($nb)*4,$a,"",0)) if ($pos == 1) && ($na != $nb); + ### + &adc($c2,0); + # is pos > 1, it means it is the last loop + &mov(&DWP($i*4,$r,"",0),$c0) if $pos > 0; # save r[]; + &mov("eax",&DWP(($na)*4,$a,"",0)) if $pos == 1; # load next b + } + +sub sqr_add_c2 + { + local($r,$a,$ai,$bi,$c0,$c1,$c2,$pos,$i,$na,$nb)=@_; + + # pos == -1 if eax and edx are pre-loaded, 0 to load from next + # words, and 1 if load return value + + &comment("sqr a[$ai]*a[$bi]"); + + # "eax" and "edx" will always be pre-loaded. + # &mov("eax",&DWP($ai*4,$a,"",0)) ; + # &mov("edx",&DWP($bi*4,$a,"",0)); + + if ($ai == $bi) + { &mul("eax");} + else + { &mul("edx");} + &add("eax","eax"); + ### + &adc("edx","edx"); + ### + &adc($c2,0); + &add($c0,"eax"); + &adc($c1,"edx"); + &mov("eax",&DWP(($na)*4,$a,"",0)) if $pos == 0; # load next a + &mov("eax",&DWP(($na)*4,$a,"",0)) if $pos == 1; # load next b + &adc($c2,0); + &mov(&DWP($i*4,$r,"",0),$c0) if $pos > 0; # save r[]; + &mov("edx",&DWP(($nb)*4,$a,"",0)) if ($pos <= 1) && ($na != $nb); + ### + } + +sub bn_mul_comba + { + local($name,$num)=@_; + local($a,$b,$c0,$c1,$c2); + local($i,$as,$ae,$bs,$be,$ai,$bi); + local($tot,$end); + + &function_begin_B($name,""); + + $c0="ebx"; + $c1="ecx"; + $c2="ebp"; + $a="esi"; + $b="edi"; + + $as=0; + $ae=0; + $bs=0; + $be=0; + $tot=$num+$num-1; + + &push("esi"); + &mov($a,&wparam(1)); + &push("edi"); + &mov($b,&wparam(2)); + &push("ebp"); + &push("ebx"); + + &xor($c0,$c0); + &mov("eax",&DWP(0,$a,"",0)); # load the first word + &xor($c1,$c1); + &mov("edx",&DWP(0,$b,"",0)); # load the first second + + for ($i=0; $i<$tot; $i++) + { + $ai=$as; + $bi=$bs; + $end=$be+1; + + &comment("################## Calculate word $i"); + + for ($j=$bs; $j<$end; $j++) + { + &xor($c2,$c2) if ($j == $bs); + if (($j+1) == $end) + { + $v=1; + $v=2 if (($i+1) == $tot); + } + else + { $v=0; } + if (($j+1) != $end) + { + $na=($ai-1); + $nb=($bi+1); + } + else + { + $na=$as+($i < ($num-1)); + $nb=$bs+($i >= ($num-1)); + } +#printf STDERR "[$ai,$bi] -> [$na,$nb]\n"; + &mul_add_c($a,$ai,$b,$bi,$c0,$c1,$c2,$v,$i,$na,$nb); + if ($v) + { + &comment("saved r[$i]"); + # &mov("eax",&wparam(0)); + # &mov(&DWP($i*4,"eax","",0),$c0); + ($c0,$c1,$c2)=($c1,$c2,$c0); + } + $ai--; + $bi++; + } + $as++ if ($i < ($num-1)); + $ae++ if ($i >= ($num-1)); + + $bs++ if ($i >= ($num-1)); + $be++ if ($i < ($num-1)); + } + &comment("save r[$i]"); + # &mov("eax",&wparam(0)); + &mov(&DWP($i*4,"eax","",0),$c0); + + &pop("ebx"); + &pop("ebp"); + &pop("edi"); + &pop("esi"); + &ret(); + &function_end_B($name); + } + +sub bn_sqr_comba + { + local($name,$num)=@_; + local($r,$a,$c0,$c1,$c2)=@_; + local($i,$as,$ae,$bs,$be,$ai,$bi); + local($b,$tot,$end,$half); + + &function_begin_B($name,""); + + $c0="ebx"; + $c1="ecx"; + $c2="ebp"; + $a="esi"; + $r="edi"; + + &push("esi"); + &push("edi"); + &push("ebp"); + &push("ebx"); + &mov($r,&wparam(0)); + &mov($a,&wparam(1)); + &xor($c0,$c0); + &xor($c1,$c1); + &mov("eax",&DWP(0,$a,"",0)); # load the first word + + $as=0; + $ae=0; + $bs=0; + $be=0; + $tot=$num+$num-1; + + for ($i=0; $i<$tot; $i++) + { + $ai=$as; + $bi=$bs; + $end=$be+1; + + &comment("############### Calculate word $i"); + for ($j=$bs; $j<$end; $j++) + { + &xor($c2,$c2) if ($j == $bs); + if (($ai-1) < ($bi+1)) + { + $v=1; + $v=2 if ($i+1) == $tot; + } + else + { $v=0; } + if (!$v) + { + $na=$ai-1; + $nb=$bi+1; + } + else + { + $na=$as+($i < ($num-1)); + $nb=$bs+($i >= ($num-1)); + } + if ($ai == $bi) + { + &sqr_add_c($r,$a,$ai,$bi, + $c0,$c1,$c2,$v,$i,$na,$nb); + } + else + { + &sqr_add_c2($r,$a,$ai,$bi, + $c0,$c1,$c2,$v,$i,$na,$nb); + } + if ($v) + { + &comment("saved r[$i]"); + #&mov(&DWP($i*4,$r,"",0),$c0); + ($c0,$c1,$c2)=($c1,$c2,$c0); + last; + } + $ai--; + $bi++; + } + $as++ if ($i < ($num-1)); + $ae++ if ($i >= ($num-1)); + + $bs++ if ($i >= ($num-1)); + $be++ if ($i < ($num-1)); + } + &mov(&DWP($i*4,$r,"",0),$c0); + &pop("ebx"); + &pop("ebp"); + &pop("edi"); + &pop("esi"); + &ret(); + &function_end_B($name); + } diff --git a/external/boringssl/crypto/bn/asm/rsaz-avx2.pl b/external/boringssl/crypto/bn/asm/rsaz-avx2.pl new file mode 100755 index 0000000000..6b57bd0b67 --- /dev/null +++ b/external/boringssl/crypto/bn/asm/rsaz-avx2.pl @@ -0,0 +1,1945 @@ +#!/usr/bin/env perl + +############################################################################## +# # +# Copyright (c) 2012, Intel Corporation # +# # +# All rights reserved. # +# # +# Redistribution and use in source and binary forms, with or without # +# modification, are permitted provided that the following conditions are # +# met: # +# # +# * Redistributions of source code must retain the above copyright # +# notice, this list of conditions and the following disclaimer. # +# # +# * Redistributions in binary form must reproduce the above copyright # +# notice, this list of conditions and the following disclaimer in the # +# documentation and/or other materials provided with the # +# distribution. # +# # +# * Neither the name of the Intel Corporation nor the names of its # +# contributors may be used to endorse or promote products derived from # +# this software without specific prior written permission. # +# # +# # +# THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION ""AS IS"" AND ANY # +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR # +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, # +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, # +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR # +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF # +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING # +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # +# # +############################################################################## +# Developers and authors: # +# Shay Gueron (1, 2), and Vlad Krasnov (1) # +# (1) Intel Corporation, Israel Development Center, Haifa, Israel # +# (2) University of Haifa, Israel # +############################################################################## +# Reference: # +# [1] S. Gueron, V. Krasnov: "Software Implementation of Modular # +# Exponentiation, Using Advanced Vector Instructions Architectures", # +# F. Ozbudak and F. Rodriguez-Henriquez (Eds.): WAIFI 2012, LNCS 7369, # +# pp. 119?135, 2012. Springer-Verlag Berlin Heidelberg 2012 # +# [2] S. Gueron: "Efficient Software Implementations of Modular # +# Exponentiation", Journal of Cryptographic Engineering 2:31-43 (2012). # +# [3] S. Gueron, V. Krasnov: "Speeding up Big-numbers Squaring",IEEE # +# Proceedings of 9th International Conference on Information Technology: # +# New Generations (ITNG 2012), pp.821-823 (2012) # +# [4] S. Gueron, V. Krasnov: "[PATCH] Efficient and side channel analysis # +# resistant 1024-bit modular exponentiation, for optimizing RSA2048 # +# on AVX2 capable x86_64 platforms", # +# http://rt.openssl.org/Ticket/Display.html?id=2850&user=guest&pass=guest# +############################################################################## +# +# +13% improvement over original submission by +# +# rsa2048 sign/sec OpenSSL 1.0.1 scalar(*) this +# 2.3GHz Haswell 621 765/+23% 1113/+79% +# 2.3GHz Broadwell(**) 688 1200(***)/+74% 1120/+63% +# +# (*) if system doesn't support AVX2, for reference purposes; +# (**) scaled to 2.3GHz to simplify comparison; +# (***) scalar AD*X code is faster than AVX2 and is preferred code +# path for Broadwell; + +$flavour = shift; +$output = shift; +if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } + +$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or +die "can't locate x86_64-xlate.pl"; + +# In upstream, this is controlled by shelling out to the compiler to check +# versions, but BoringSSL is intended to be used with pre-generated perlasm +# output, so this isn't useful anyway. +# +# TODO(davidben): Enable these after testing. $avx goes up to 2 and $addx to 1. +$avx = 0; +$addx = 0; + +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT = *OUT; + +if ($avx>1) {{{ +{ # void AMS_WW( +my $rp="%rdi"; # BN_ULONG *rp, +my $ap="%rsi"; # const BN_ULONG *ap, +my $np="%rdx"; # const BN_ULONG *np, +my $n0="%ecx"; # const BN_ULONG n0, +my $rep="%r8d"; # int repeat); + +# The registers that hold the accumulated redundant result +# The AMM works on 1024 bit operands, and redundant word size is 29 +# Therefore: ceil(1024/29)/4 = 9 +my $ACC0="%ymm0"; +my $ACC1="%ymm1"; +my $ACC2="%ymm2"; +my $ACC3="%ymm3"; +my $ACC4="%ymm4"; +my $ACC5="%ymm5"; +my $ACC6="%ymm6"; +my $ACC7="%ymm7"; +my $ACC8="%ymm8"; +my $ACC9="%ymm9"; +# Registers that hold the broadcasted words of bp, currently used +my $B1="%ymm10"; +my $B2="%ymm11"; +# Registers that hold the broadcasted words of Y, currently used +my $Y1="%ymm12"; +my $Y2="%ymm13"; +# Helper registers +my $TEMP1="%ymm14"; +my $AND_MASK="%ymm15"; +# alu registers that hold the first words of the ACC +my $r0="%r9"; +my $r1="%r10"; +my $r2="%r11"; +my $r3="%r12"; + +my $i="%r14d"; # loop counter +my $tmp = "%r15"; + +my $FrameSize=32*18+32*8; # place for A^2 and 2*A + +my $aap=$r0; +my $tp0="%rbx"; +my $tp1=$r3; +my $tpa=$tmp; + +$np="%r13"; # reassigned argument + +$code.=<<___; +.text + +.globl rsaz_1024_sqr_avx2 +.type rsaz_1024_sqr_avx2,\@function,5 +.align 64 +rsaz_1024_sqr_avx2: # 702 cycles, 14% faster than rsaz_1024_mul_avx2 + lea (%rsp), %rax + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + vzeroupper +___ +$code.=<<___ if ($win64); + lea -0xa8(%rsp),%rsp + vmovaps %xmm6,-0xd8(%rax) + vmovaps %xmm7,-0xc8(%rax) + vmovaps %xmm8,-0xb8(%rax) + vmovaps %xmm9,-0xa8(%rax) + vmovaps %xmm10,-0x98(%rax) + vmovaps %xmm11,-0x88(%rax) + vmovaps %xmm12,-0x78(%rax) + vmovaps %xmm13,-0x68(%rax) + vmovaps %xmm14,-0x58(%rax) + vmovaps %xmm15,-0x48(%rax) +.Lsqr_1024_body: +___ +$code.=<<___; + mov %rax,%rbp + mov %rdx, $np # reassigned argument + sub \$$FrameSize, %rsp + mov $np, $tmp + sub \$-128, $rp # size optimization + sub \$-128, $ap + sub \$-128, $np + + and \$4095, $tmp # see if $np crosses page + add \$32*10, $tmp + shr \$12, $tmp + vpxor $ACC9,$ACC9,$ACC9 + jz .Lsqr_1024_no_n_copy + + # unaligned 256-bit load that crosses page boundary can + # cause >2x performance degradation here, so if $np does + # cross page boundary, copy it to stack and make sure stack + # frame doesn't... + sub \$32*10,%rsp + vmovdqu 32*0-128($np), $ACC0 + and \$-2048, %rsp + vmovdqu 32*1-128($np), $ACC1 + vmovdqu 32*2-128($np), $ACC2 + vmovdqu 32*3-128($np), $ACC3 + vmovdqu 32*4-128($np), $ACC4 + vmovdqu 32*5-128($np), $ACC5 + vmovdqu 32*6-128($np), $ACC6 + vmovdqu 32*7-128($np), $ACC7 + vmovdqu 32*8-128($np), $ACC8 + lea $FrameSize+128(%rsp),$np + vmovdqu $ACC0, 32*0-128($np) + vmovdqu $ACC1, 32*1-128($np) + vmovdqu $ACC2, 32*2-128($np) + vmovdqu $ACC3, 32*3-128($np) + vmovdqu $ACC4, 32*4-128($np) + vmovdqu $ACC5, 32*5-128($np) + vmovdqu $ACC6, 32*6-128($np) + vmovdqu $ACC7, 32*7-128($np) + vmovdqu $ACC8, 32*8-128($np) + vmovdqu $ACC9, 32*9-128($np) # $ACC9 is zero + +.Lsqr_1024_no_n_copy: + and \$-1024, %rsp + + vmovdqu 32*1-128($ap), $ACC1 + vmovdqu 32*2-128($ap), $ACC2 + vmovdqu 32*3-128($ap), $ACC3 + vmovdqu 32*4-128($ap), $ACC4 + vmovdqu 32*5-128($ap), $ACC5 + vmovdqu 32*6-128($ap), $ACC6 + vmovdqu 32*7-128($ap), $ACC7 + vmovdqu 32*8-128($ap), $ACC8 + + lea 192(%rsp), $tp0 # 64+128=192 + vpbroadcastq .Land_mask(%rip), $AND_MASK + jmp .LOOP_GRANDE_SQR_1024 + +.align 32 +.LOOP_GRANDE_SQR_1024: + lea 32*18+128(%rsp), $aap # size optimization + lea 448(%rsp), $tp1 # 64+128+256=448 + + # the squaring is performed as described in Variant B of + # "Speeding up Big-Number Squaring", so start by calculating + # the A*2=A+A vector + vpaddq $ACC1, $ACC1, $ACC1 + vpbroadcastq 32*0-128($ap), $B1 + vpaddq $ACC2, $ACC2, $ACC2 + vmovdqa $ACC1, 32*0-128($aap) + vpaddq $ACC3, $ACC3, $ACC3 + vmovdqa $ACC2, 32*1-128($aap) + vpaddq $ACC4, $ACC4, $ACC4 + vmovdqa $ACC3, 32*2-128($aap) + vpaddq $ACC5, $ACC5, $ACC5 + vmovdqa $ACC4, 32*3-128($aap) + vpaddq $ACC6, $ACC6, $ACC6 + vmovdqa $ACC5, 32*4-128($aap) + vpaddq $ACC7, $ACC7, $ACC7 + vmovdqa $ACC6, 32*5-128($aap) + vpaddq $ACC8, $ACC8, $ACC8 + vmovdqa $ACC7, 32*6-128($aap) + vpxor $ACC9, $ACC9, $ACC9 + vmovdqa $ACC8, 32*7-128($aap) + + vpmuludq 32*0-128($ap), $B1, $ACC0 + vpbroadcastq 32*1-128($ap), $B2 + vmovdqu $ACC9, 32*9-192($tp0) # zero upper half + vpmuludq $B1, $ACC1, $ACC1 + vmovdqu $ACC9, 32*10-448($tp1) + vpmuludq $B1, $ACC2, $ACC2 + vmovdqu $ACC9, 32*11-448($tp1) + vpmuludq $B1, $ACC3, $ACC3 + vmovdqu $ACC9, 32*12-448($tp1) + vpmuludq $B1, $ACC4, $ACC4 + vmovdqu $ACC9, 32*13-448($tp1) + vpmuludq $B1, $ACC5, $ACC5 + vmovdqu $ACC9, 32*14-448($tp1) + vpmuludq $B1, $ACC6, $ACC6 + vmovdqu $ACC9, 32*15-448($tp1) + vpmuludq $B1, $ACC7, $ACC7 + vmovdqu $ACC9, 32*16-448($tp1) + vpmuludq $B1, $ACC8, $ACC8 + vpbroadcastq 32*2-128($ap), $B1 + vmovdqu $ACC9, 32*17-448($tp1) + + mov $ap, $tpa + mov \$4, $i + jmp .Lsqr_entry_1024 +___ +$TEMP0=$Y1; +$TEMP2=$Y2; +$code.=<<___; +.align 32 +.LOOP_SQR_1024: + vpbroadcastq 32*1-128($tpa), $B2 + vpmuludq 32*0-128($ap), $B1, $ACC0 + vpaddq 32*0-192($tp0), $ACC0, $ACC0 + vpmuludq 32*0-128($aap), $B1, $ACC1 + vpaddq 32*1-192($tp0), $ACC1, $ACC1 + vpmuludq 32*1-128($aap), $B1, $ACC2 + vpaddq 32*2-192($tp0), $ACC2, $ACC2 + vpmuludq 32*2-128($aap), $B1, $ACC3 + vpaddq 32*3-192($tp0), $ACC3, $ACC3 + vpmuludq 32*3-128($aap), $B1, $ACC4 + vpaddq 32*4-192($tp0), $ACC4, $ACC4 + vpmuludq 32*4-128($aap), $B1, $ACC5 + vpaddq 32*5-192($tp0), $ACC5, $ACC5 + vpmuludq 32*5-128($aap), $B1, $ACC6 + vpaddq 32*6-192($tp0), $ACC6, $ACC6 + vpmuludq 32*6-128($aap), $B1, $ACC7 + vpaddq 32*7-192($tp0), $ACC7, $ACC7 + vpmuludq 32*7-128($aap), $B1, $ACC8 + vpbroadcastq 32*2-128($tpa), $B1 + vpaddq 32*8-192($tp0), $ACC8, $ACC8 +.Lsqr_entry_1024: + vmovdqu $ACC0, 32*0-192($tp0) + vmovdqu $ACC1, 32*1-192($tp0) + + vpmuludq 32*1-128($ap), $B2, $TEMP0 + vpaddq $TEMP0, $ACC2, $ACC2 + vpmuludq 32*1-128($aap), $B2, $TEMP1 + vpaddq $TEMP1, $ACC3, $ACC3 + vpmuludq 32*2-128($aap), $B2, $TEMP2 + vpaddq $TEMP2, $ACC4, $ACC4 + vpmuludq 32*3-128($aap), $B2, $TEMP0 + vpaddq $TEMP0, $ACC5, $ACC5 + vpmuludq 32*4-128($aap), $B2, $TEMP1 + vpaddq $TEMP1, $ACC6, $ACC6 + vpmuludq 32*5-128($aap), $B2, $TEMP2 + vpaddq $TEMP2, $ACC7, $ACC7 + vpmuludq 32*6-128($aap), $B2, $TEMP0 + vpaddq $TEMP0, $ACC8, $ACC8 + vpmuludq 32*7-128($aap), $B2, $ACC0 + vpbroadcastq 32*3-128($tpa), $B2 + vpaddq 32*9-192($tp0), $ACC0, $ACC0 + + vmovdqu $ACC2, 32*2-192($tp0) + vmovdqu $ACC3, 32*3-192($tp0) + + vpmuludq 32*2-128($ap), $B1, $TEMP2 + vpaddq $TEMP2, $ACC4, $ACC4 + vpmuludq 32*2-128($aap), $B1, $TEMP0 + vpaddq $TEMP0, $ACC5, $ACC5 + vpmuludq 32*3-128($aap), $B1, $TEMP1 + vpaddq $TEMP1, $ACC6, $ACC6 + vpmuludq 32*4-128($aap), $B1, $TEMP2 + vpaddq $TEMP2, $ACC7, $ACC7 + vpmuludq 32*5-128($aap), $B1, $TEMP0 + vpaddq $TEMP0, $ACC8, $ACC8 + vpmuludq 32*6-128($aap), $B1, $TEMP1 + vpaddq $TEMP1, $ACC0, $ACC0 + vpmuludq 32*7-128($aap), $B1, $ACC1 + vpbroadcastq 32*4-128($tpa), $B1 + vpaddq 32*10-448($tp1), $ACC1, $ACC1 + + vmovdqu $ACC4, 32*4-192($tp0) + vmovdqu $ACC5, 32*5-192($tp0) + + vpmuludq 32*3-128($ap), $B2, $TEMP0 + vpaddq $TEMP0, $ACC6, $ACC6 + vpmuludq 32*3-128($aap), $B2, $TEMP1 + vpaddq $TEMP1, $ACC7, $ACC7 + vpmuludq 32*4-128($aap), $B2, $TEMP2 + vpaddq $TEMP2, $ACC8, $ACC8 + vpmuludq 32*5-128($aap), $B2, $TEMP0 + vpaddq $TEMP0, $ACC0, $ACC0 + vpmuludq 32*6-128($aap), $B2, $TEMP1 + vpaddq $TEMP1, $ACC1, $ACC1 + vpmuludq 32*7-128($aap), $B2, $ACC2 + vpbroadcastq 32*5-128($tpa), $B2 + vpaddq 32*11-448($tp1), $ACC2, $ACC2 + + vmovdqu $ACC6, 32*6-192($tp0) + vmovdqu $ACC7, 32*7-192($tp0) + + vpmuludq 32*4-128($ap), $B1, $TEMP0 + vpaddq $TEMP0, $ACC8, $ACC8 + vpmuludq 32*4-128($aap), $B1, $TEMP1 + vpaddq $TEMP1, $ACC0, $ACC0 + vpmuludq 32*5-128($aap), $B1, $TEMP2 + vpaddq $TEMP2, $ACC1, $ACC1 + vpmuludq 32*6-128($aap), $B1, $TEMP0 + vpaddq $TEMP0, $ACC2, $ACC2 + vpmuludq 32*7-128($aap), $B1, $ACC3 + vpbroadcastq 32*6-128($tpa), $B1 + vpaddq 32*12-448($tp1), $ACC3, $ACC3 + + vmovdqu $ACC8, 32*8-192($tp0) + vmovdqu $ACC0, 32*9-192($tp0) + lea 8($tp0), $tp0 + + vpmuludq 32*5-128($ap), $B2, $TEMP2 + vpaddq $TEMP2, $ACC1, $ACC1 + vpmuludq 32*5-128($aap), $B2, $TEMP0 + vpaddq $TEMP0, $ACC2, $ACC2 + vpmuludq 32*6-128($aap), $B2, $TEMP1 + vpaddq $TEMP1, $ACC3, $ACC3 + vpmuludq 32*7-128($aap), $B2, $ACC4 + vpbroadcastq 32*7-128($tpa), $B2 + vpaddq 32*13-448($tp1), $ACC4, $ACC4 + + vmovdqu $ACC1, 32*10-448($tp1) + vmovdqu $ACC2, 32*11-448($tp1) + + vpmuludq 32*6-128($ap), $B1, $TEMP0 + vpaddq $TEMP0, $ACC3, $ACC3 + vpmuludq 32*6-128($aap), $B1, $TEMP1 + vpbroadcastq 32*8-128($tpa), $ACC0 # borrow $ACC0 for $B1 + vpaddq $TEMP1, $ACC4, $ACC4 + vpmuludq 32*7-128($aap), $B1, $ACC5 + vpbroadcastq 32*0+8-128($tpa), $B1 # for next iteration + vpaddq 32*14-448($tp1), $ACC5, $ACC5 + + vmovdqu $ACC3, 32*12-448($tp1) + vmovdqu $ACC4, 32*13-448($tp1) + lea 8($tpa), $tpa + + vpmuludq 32*7-128($ap), $B2, $TEMP0 + vpaddq $TEMP0, $ACC5, $ACC5 + vpmuludq 32*7-128($aap), $B2, $ACC6 + vpaddq 32*15-448($tp1), $ACC6, $ACC6 + + vpmuludq 32*8-128($ap), $ACC0, $ACC7 + vmovdqu $ACC5, 32*14-448($tp1) + vpaddq 32*16-448($tp1), $ACC7, $ACC7 + vmovdqu $ACC6, 32*15-448($tp1) + vmovdqu $ACC7, 32*16-448($tp1) + lea 8($tp1), $tp1 + + dec $i + jnz .LOOP_SQR_1024 +___ +$ZERO = $ACC9; +$TEMP0 = $B1; +$TEMP2 = $B2; +$TEMP3 = $Y1; +$TEMP4 = $Y2; +$code.=<<___; + # we need to fix indices 32-39 to avoid overflow + vmovdqu 32*8(%rsp), $ACC8 # 32*8-192($tp0), + vmovdqu 32*9(%rsp), $ACC1 # 32*9-192($tp0) + vmovdqu 32*10(%rsp), $ACC2 # 32*10-192($tp0) + lea 192(%rsp), $tp0 # 64+128=192 + + vpsrlq \$29, $ACC8, $TEMP1 + vpand $AND_MASK, $ACC8, $ACC8 + vpsrlq \$29, $ACC1, $TEMP2 + vpand $AND_MASK, $ACC1, $ACC1 + + vpermq \$0x93, $TEMP1, $TEMP1 + vpxor $ZERO, $ZERO, $ZERO + vpermq \$0x93, $TEMP2, $TEMP2 + + vpblendd \$3, $ZERO, $TEMP1, $TEMP0 + vpblendd \$3, $TEMP1, $TEMP2, $TEMP1 + vpaddq $TEMP0, $ACC8, $ACC8 + vpblendd \$3, $TEMP2, $ZERO, $TEMP2 + vpaddq $TEMP1, $ACC1, $ACC1 + vpaddq $TEMP2, $ACC2, $ACC2 + vmovdqu $ACC1, 32*9-192($tp0) + vmovdqu $ACC2, 32*10-192($tp0) + + mov (%rsp), %rax + mov 8(%rsp), $r1 + mov 16(%rsp), $r2 + mov 24(%rsp), $r3 + vmovdqu 32*1(%rsp), $ACC1 + vmovdqu 32*2-192($tp0), $ACC2 + vmovdqu 32*3-192($tp0), $ACC3 + vmovdqu 32*4-192($tp0), $ACC4 + vmovdqu 32*5-192($tp0), $ACC5 + vmovdqu 32*6-192($tp0), $ACC6 + vmovdqu 32*7-192($tp0), $ACC7 + + mov %rax, $r0 + imull $n0, %eax + and \$0x1fffffff, %eax + vmovd %eax, $Y1 + + mov %rax, %rdx + imulq -128($np), %rax + vpbroadcastq $Y1, $Y1 + add %rax, $r0 + mov %rdx, %rax + imulq 8-128($np), %rax + shr \$29, $r0 + add %rax, $r1 + mov %rdx, %rax + imulq 16-128($np), %rax + add $r0, $r1 + add %rax, $r2 + imulq 24-128($np), %rdx + add %rdx, $r3 + + mov $r1, %rax + imull $n0, %eax + and \$0x1fffffff, %eax + + mov \$9, $i + jmp .LOOP_REDUCE_1024 + +.align 32 +.LOOP_REDUCE_1024: + vmovd %eax, $Y2 + vpbroadcastq $Y2, $Y2 + + vpmuludq 32*1-128($np), $Y1, $TEMP0 + mov %rax, %rdx + imulq -128($np), %rax + vpaddq $TEMP0, $ACC1, $ACC1 + add %rax, $r1 + vpmuludq 32*2-128($np), $Y1, $TEMP1 + mov %rdx, %rax + imulq 8-128($np), %rax + vpaddq $TEMP1, $ACC2, $ACC2 + vpmuludq 32*3-128($np), $Y1, $TEMP2 + .byte 0x67 + add %rax, $r2 + .byte 0x67 + mov %rdx, %rax + imulq 16-128($np), %rax + shr \$29, $r1 + vpaddq $TEMP2, $ACC3, $ACC3 + vpmuludq 32*4-128($np), $Y1, $TEMP0 + add %rax, $r3 + add $r1, $r2 + vpaddq $TEMP0, $ACC4, $ACC4 + vpmuludq 32*5-128($np), $Y1, $TEMP1 + mov $r2, %rax + imull $n0, %eax + vpaddq $TEMP1, $ACC5, $ACC5 + vpmuludq 32*6-128($np), $Y1, $TEMP2 + and \$0x1fffffff, %eax + vpaddq $TEMP2, $ACC6, $ACC6 + vpmuludq 32*7-128($np), $Y1, $TEMP0 + vpaddq $TEMP0, $ACC7, $ACC7 + vpmuludq 32*8-128($np), $Y1, $TEMP1 + vmovd %eax, $Y1 + #vmovdqu 32*1-8-128($np), $TEMP2 # moved below + vpaddq $TEMP1, $ACC8, $ACC8 + #vmovdqu 32*2-8-128($np), $TEMP0 # moved below + vpbroadcastq $Y1, $Y1 + + vpmuludq 32*1-8-128($np), $Y2, $TEMP2 # see above + vmovdqu 32*3-8-128($np), $TEMP1 + mov %rax, %rdx + imulq -128($np), %rax + vpaddq $TEMP2, $ACC1, $ACC1 + vpmuludq 32*2-8-128($np), $Y2, $TEMP0 # see above + vmovdqu 32*4-8-128($np), $TEMP2 + add %rax, $r2 + mov %rdx, %rax + imulq 8-128($np), %rax + vpaddq $TEMP0, $ACC2, $ACC2 + add $r3, %rax + shr \$29, $r2 + vpmuludq $Y2, $TEMP1, $TEMP1 + vmovdqu 32*5-8-128($np), $TEMP0 + add $r2, %rax + vpaddq $TEMP1, $ACC3, $ACC3 + vpmuludq $Y2, $TEMP2, $TEMP2 + vmovdqu 32*6-8-128($np), $TEMP1 + .byte 0x67 + mov %rax, $r3 + imull $n0, %eax + vpaddq $TEMP2, $ACC4, $ACC4 + vpmuludq $Y2, $TEMP0, $TEMP0 + .byte 0xc4,0x41,0x7e,0x6f,0x9d,0x58,0x00,0x00,0x00 # vmovdqu 32*7-8-128($np), $TEMP2 + and \$0x1fffffff, %eax + vpaddq $TEMP0, $ACC5, $ACC5 + vpmuludq $Y2, $TEMP1, $TEMP1 + vmovdqu 32*8-8-128($np), $TEMP0 + vpaddq $TEMP1, $ACC6, $ACC6 + vpmuludq $Y2, $TEMP2, $TEMP2 + vmovdqu 32*9-8-128($np), $ACC9 + vmovd %eax, $ACC0 # borrow ACC0 for Y2 + imulq -128($np), %rax + vpaddq $TEMP2, $ACC7, $ACC7 + vpmuludq $Y2, $TEMP0, $TEMP0 + vmovdqu 32*1-16-128($np), $TEMP1 + vpbroadcastq $ACC0, $ACC0 + vpaddq $TEMP0, $ACC8, $ACC8 + vpmuludq $Y2, $ACC9, $ACC9 + vmovdqu 32*2-16-128($np), $TEMP2 + add %rax, $r3 + +___ +($ACC0,$Y2)=($Y2,$ACC0); +$code.=<<___; + vmovdqu 32*1-24-128($np), $ACC0 + vpmuludq $Y1, $TEMP1, $TEMP1 + vmovdqu 32*3-16-128($np), $TEMP0 + vpaddq $TEMP1, $ACC1, $ACC1 + vpmuludq $Y2, $ACC0, $ACC0 + vpmuludq $Y1, $TEMP2, $TEMP2 + .byte 0xc4,0x41,0x7e,0x6f,0xb5,0xf0,0xff,0xff,0xff # vmovdqu 32*4-16-128($np), $TEMP1 + vpaddq $ACC1, $ACC0, $ACC0 + vpaddq $TEMP2, $ACC2, $ACC2 + vpmuludq $Y1, $TEMP0, $TEMP0 + vmovdqu 32*5-16-128($np), $TEMP2 + .byte 0x67 + vmovq $ACC0, %rax + vmovdqu $ACC0, (%rsp) # transfer $r0-$r3 + vpaddq $TEMP0, $ACC3, $ACC3 + vpmuludq $Y1, $TEMP1, $TEMP1 + vmovdqu 32*6-16-128($np), $TEMP0 + vpaddq $TEMP1, $ACC4, $ACC4 + vpmuludq $Y1, $TEMP2, $TEMP2 + vmovdqu 32*7-16-128($np), $TEMP1 + vpaddq $TEMP2, $ACC5, $ACC5 + vpmuludq $Y1, $TEMP0, $TEMP0 + vmovdqu 32*8-16-128($np), $TEMP2 + vpaddq $TEMP0, $ACC6, $ACC6 + vpmuludq $Y1, $TEMP1, $TEMP1 + shr \$29, $r3 + vmovdqu 32*9-16-128($np), $TEMP0 + add $r3, %rax + vpaddq $TEMP1, $ACC7, $ACC7 + vpmuludq $Y1, $TEMP2, $TEMP2 + #vmovdqu 32*2-24-128($np), $TEMP1 # moved below + mov %rax, $r0 + imull $n0, %eax + vpaddq $TEMP2, $ACC8, $ACC8 + vpmuludq $Y1, $TEMP0, $TEMP0 + and \$0x1fffffff, %eax + vmovd %eax, $Y1 + vmovdqu 32*3-24-128($np), $TEMP2 + .byte 0x67 + vpaddq $TEMP0, $ACC9, $ACC9 + vpbroadcastq $Y1, $Y1 + + vpmuludq 32*2-24-128($np), $Y2, $TEMP1 # see above + vmovdqu 32*4-24-128($np), $TEMP0 + mov %rax, %rdx + imulq -128($np), %rax + mov 8(%rsp), $r1 + vpaddq $TEMP1, $ACC2, $ACC1 + vpmuludq $Y2, $TEMP2, $TEMP2 + vmovdqu 32*5-24-128($np), $TEMP1 + add %rax, $r0 + mov %rdx, %rax + imulq 8-128($np), %rax + .byte 0x67 + shr \$29, $r0 + mov 16(%rsp), $r2 + vpaddq $TEMP2, $ACC3, $ACC2 + vpmuludq $Y2, $TEMP0, $TEMP0 + vmovdqu 32*6-24-128($np), $TEMP2 + add %rax, $r1 + mov %rdx, %rax + imulq 16-128($np), %rax + vpaddq $TEMP0, $ACC4, $ACC3 + vpmuludq $Y2, $TEMP1, $TEMP1 + vmovdqu 32*7-24-128($np), $TEMP0 + imulq 24-128($np), %rdx # future $r3 + add %rax, $r2 + lea ($r0,$r1), %rax + vpaddq $TEMP1, $ACC5, $ACC4 + vpmuludq $Y2, $TEMP2, $TEMP2 + vmovdqu 32*8-24-128($np), $TEMP1 + mov %rax, $r1 + imull $n0, %eax + vpmuludq $Y2, $TEMP0, $TEMP0 + vpaddq $TEMP2, $ACC6, $ACC5 + vmovdqu 32*9-24-128($np), $TEMP2 + and \$0x1fffffff, %eax + vpaddq $TEMP0, $ACC7, $ACC6 + vpmuludq $Y2, $TEMP1, $TEMP1 + add 24(%rsp), %rdx + vpaddq $TEMP1, $ACC8, $ACC7 + vpmuludq $Y2, $TEMP2, $TEMP2 + vpaddq $TEMP2, $ACC9, $ACC8 + vmovq $r3, $ACC9 + mov %rdx, $r3 + + dec $i + jnz .LOOP_REDUCE_1024 +___ +($ACC0,$Y2)=($Y2,$ACC0); +$code.=<<___; + lea 448(%rsp), $tp1 # size optimization + vpaddq $ACC9, $Y2, $ACC0 + vpxor $ZERO, $ZERO, $ZERO + + vpaddq 32*9-192($tp0), $ACC0, $ACC0 + vpaddq 32*10-448($tp1), $ACC1, $ACC1 + vpaddq 32*11-448($tp1), $ACC2, $ACC2 + vpaddq 32*12-448($tp1), $ACC3, $ACC3 + vpaddq 32*13-448($tp1), $ACC4, $ACC4 + vpaddq 32*14-448($tp1), $ACC5, $ACC5 + vpaddq 32*15-448($tp1), $ACC6, $ACC6 + vpaddq 32*16-448($tp1), $ACC7, $ACC7 + vpaddq 32*17-448($tp1), $ACC8, $ACC8 + + vpsrlq \$29, $ACC0, $TEMP1 + vpand $AND_MASK, $ACC0, $ACC0 + vpsrlq \$29, $ACC1, $TEMP2 + vpand $AND_MASK, $ACC1, $ACC1 + vpsrlq \$29, $ACC2, $TEMP3 + vpermq \$0x93, $TEMP1, $TEMP1 + vpand $AND_MASK, $ACC2, $ACC2 + vpsrlq \$29, $ACC3, $TEMP4 + vpermq \$0x93, $TEMP2, $TEMP2 + vpand $AND_MASK, $ACC3, $ACC3 + vpermq \$0x93, $TEMP3, $TEMP3 + + vpblendd \$3, $ZERO, $TEMP1, $TEMP0 + vpermq \$0x93, $TEMP4, $TEMP4 + vpblendd \$3, $TEMP1, $TEMP2, $TEMP1 + vpaddq $TEMP0, $ACC0, $ACC0 + vpblendd \$3, $TEMP2, $TEMP3, $TEMP2 + vpaddq $TEMP1, $ACC1, $ACC1 + vpblendd \$3, $TEMP3, $TEMP4, $TEMP3 + vpaddq $TEMP2, $ACC2, $ACC2 + vpblendd \$3, $TEMP4, $ZERO, $TEMP4 + vpaddq $TEMP3, $ACC3, $ACC3 + vpaddq $TEMP4, $ACC4, $ACC4 + + vpsrlq \$29, $ACC0, $TEMP1 + vpand $AND_MASK, $ACC0, $ACC0 + vpsrlq \$29, $ACC1, $TEMP2 + vpand $AND_MASK, $ACC1, $ACC1 + vpsrlq \$29, $ACC2, $TEMP3 + vpermq \$0x93, $TEMP1, $TEMP1 + vpand $AND_MASK, $ACC2, $ACC2 + vpsrlq \$29, $ACC3, $TEMP4 + vpermq \$0x93, $TEMP2, $TEMP2 + vpand $AND_MASK, $ACC3, $ACC3 + vpermq \$0x93, $TEMP3, $TEMP3 + + vpblendd \$3, $ZERO, $TEMP1, $TEMP0 + vpermq \$0x93, $TEMP4, $TEMP4 + vpblendd \$3, $TEMP1, $TEMP2, $TEMP1 + vpaddq $TEMP0, $ACC0, $ACC0 + vpblendd \$3, $TEMP2, $TEMP3, $TEMP2 + vpaddq $TEMP1, $ACC1, $ACC1 + vmovdqu $ACC0, 32*0-128($rp) + vpblendd \$3, $TEMP3, $TEMP4, $TEMP3 + vpaddq $TEMP2, $ACC2, $ACC2 + vmovdqu $ACC1, 32*1-128($rp) + vpblendd \$3, $TEMP4, $ZERO, $TEMP4 + vpaddq $TEMP3, $ACC3, $ACC3 + vmovdqu $ACC2, 32*2-128($rp) + vpaddq $TEMP4, $ACC4, $ACC4 + vmovdqu $ACC3, 32*3-128($rp) +___ +$TEMP5=$ACC0; +$code.=<<___; + vpsrlq \$29, $ACC4, $TEMP1 + vpand $AND_MASK, $ACC4, $ACC4 + vpsrlq \$29, $ACC5, $TEMP2 + vpand $AND_MASK, $ACC5, $ACC5 + vpsrlq \$29, $ACC6, $TEMP3 + vpermq \$0x93, $TEMP1, $TEMP1 + vpand $AND_MASK, $ACC6, $ACC6 + vpsrlq \$29, $ACC7, $TEMP4 + vpermq \$0x93, $TEMP2, $TEMP2 + vpand $AND_MASK, $ACC7, $ACC7 + vpsrlq \$29, $ACC8, $TEMP5 + vpermq \$0x93, $TEMP3, $TEMP3 + vpand $AND_MASK, $ACC8, $ACC8 + vpermq \$0x93, $TEMP4, $TEMP4 + + vpblendd \$3, $ZERO, $TEMP1, $TEMP0 + vpermq \$0x93, $TEMP5, $TEMP5 + vpblendd \$3, $TEMP1, $TEMP2, $TEMP1 + vpaddq $TEMP0, $ACC4, $ACC4 + vpblendd \$3, $TEMP2, $TEMP3, $TEMP2 + vpaddq $TEMP1, $ACC5, $ACC5 + vpblendd \$3, $TEMP3, $TEMP4, $TEMP3 + vpaddq $TEMP2, $ACC6, $ACC6 + vpblendd \$3, $TEMP4, $TEMP5, $TEMP4 + vpaddq $TEMP3, $ACC7, $ACC7 + vpaddq $TEMP4, $ACC8, $ACC8 + + vpsrlq \$29, $ACC4, $TEMP1 + vpand $AND_MASK, $ACC4, $ACC4 + vpsrlq \$29, $ACC5, $TEMP2 + vpand $AND_MASK, $ACC5, $ACC5 + vpsrlq \$29, $ACC6, $TEMP3 + vpermq \$0x93, $TEMP1, $TEMP1 + vpand $AND_MASK, $ACC6, $ACC6 + vpsrlq \$29, $ACC7, $TEMP4 + vpermq \$0x93, $TEMP2, $TEMP2 + vpand $AND_MASK, $ACC7, $ACC7 + vpsrlq \$29, $ACC8, $TEMP5 + vpermq \$0x93, $TEMP3, $TEMP3 + vpand $AND_MASK, $ACC8, $ACC8 + vpermq \$0x93, $TEMP4, $TEMP4 + + vpblendd \$3, $ZERO, $TEMP1, $TEMP0 + vpermq \$0x93, $TEMP5, $TEMP5 + vpblendd \$3, $TEMP1, $TEMP2, $TEMP1 + vpaddq $TEMP0, $ACC4, $ACC4 + vpblendd \$3, $TEMP2, $TEMP3, $TEMP2 + vpaddq $TEMP1, $ACC5, $ACC5 + vmovdqu $ACC4, 32*4-128($rp) + vpblendd \$3, $TEMP3, $TEMP4, $TEMP3 + vpaddq $TEMP2, $ACC6, $ACC6 + vmovdqu $ACC5, 32*5-128($rp) + vpblendd \$3, $TEMP4, $TEMP5, $TEMP4 + vpaddq $TEMP3, $ACC7, $ACC7 + vmovdqu $ACC6, 32*6-128($rp) + vpaddq $TEMP4, $ACC8, $ACC8 + vmovdqu $ACC7, 32*7-128($rp) + vmovdqu $ACC8, 32*8-128($rp) + + mov $rp, $ap + dec $rep + jne .LOOP_GRANDE_SQR_1024 + + vzeroall + mov %rbp, %rax +___ +$code.=<<___ if ($win64); + movaps -0xd8(%rax),%xmm6 + movaps -0xc8(%rax),%xmm7 + movaps -0xb8(%rax),%xmm8 + movaps -0xa8(%rax),%xmm9 + movaps -0x98(%rax),%xmm10 + movaps -0x88(%rax),%xmm11 + movaps -0x78(%rax),%xmm12 + movaps -0x68(%rax),%xmm13 + movaps -0x58(%rax),%xmm14 + movaps -0x48(%rax),%xmm15 +___ +$code.=<<___; + mov -48(%rax),%r15 + mov -40(%rax),%r14 + mov -32(%rax),%r13 + mov -24(%rax),%r12 + mov -16(%rax),%rbp + mov -8(%rax),%rbx + lea (%rax),%rsp # restore %rsp +.Lsqr_1024_epilogue: + ret +.size rsaz_1024_sqr_avx2,.-rsaz_1024_sqr_avx2 +___ +} + +{ # void AMM_WW( +my $rp="%rdi"; # BN_ULONG *rp, +my $ap="%rsi"; # const BN_ULONG *ap, +my $bp="%rdx"; # const BN_ULONG *bp, +my $np="%rcx"; # const BN_ULONG *np, +my $n0="%r8d"; # unsigned int n0); + +# The registers that hold the accumulated redundant result +# The AMM works on 1024 bit operands, and redundant word size is 29 +# Therefore: ceil(1024/29)/4 = 9 +my $ACC0="%ymm0"; +my $ACC1="%ymm1"; +my $ACC2="%ymm2"; +my $ACC3="%ymm3"; +my $ACC4="%ymm4"; +my $ACC5="%ymm5"; +my $ACC6="%ymm6"; +my $ACC7="%ymm7"; +my $ACC8="%ymm8"; +my $ACC9="%ymm9"; + +# Registers that hold the broadcasted words of multiplier, currently used +my $Bi="%ymm10"; +my $Yi="%ymm11"; + +# Helper registers +my $TEMP0=$ACC0; +my $TEMP1="%ymm12"; +my $TEMP2="%ymm13"; +my $ZERO="%ymm14"; +my $AND_MASK="%ymm15"; + +# alu registers that hold the first words of the ACC +my $r0="%r9"; +my $r1="%r10"; +my $r2="%r11"; +my $r3="%r12"; + +my $i="%r14d"; +my $tmp="%r15"; + +$bp="%r13"; # reassigned argument + +$code.=<<___; +.globl rsaz_1024_mul_avx2 +.type rsaz_1024_mul_avx2,\@function,5 +.align 64 +rsaz_1024_mul_avx2: + lea (%rsp), %rax + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 +___ +$code.=<<___ if ($win64); + vzeroupper + lea -0xa8(%rsp),%rsp + vmovaps %xmm6,-0xd8(%rax) + vmovaps %xmm7,-0xc8(%rax) + vmovaps %xmm8,-0xb8(%rax) + vmovaps %xmm9,-0xa8(%rax) + vmovaps %xmm10,-0x98(%rax) + vmovaps %xmm11,-0x88(%rax) + vmovaps %xmm12,-0x78(%rax) + vmovaps %xmm13,-0x68(%rax) + vmovaps %xmm14,-0x58(%rax) + vmovaps %xmm15,-0x48(%rax) +.Lmul_1024_body: +___ +$code.=<<___; + mov %rax,%rbp + vzeroall + mov %rdx, $bp # reassigned argument + sub \$64,%rsp + + # unaligned 256-bit load that crosses page boundary can + # cause severe performance degradation here, so if $ap does + # cross page boundary, swap it with $bp [meaning that caller + # is advised to lay down $ap and $bp next to each other, so + # that only one can cross page boundary]. + .byte 0x67,0x67 + mov $ap, $tmp + and \$4095, $tmp + add \$32*10, $tmp + shr \$12, $tmp + mov $ap, $tmp + cmovnz $bp, $ap + cmovnz $tmp, $bp + + mov $np, $tmp + sub \$-128,$ap # size optimization + sub \$-128,$np + sub \$-128,$rp + + and \$4095, $tmp # see if $np crosses page + add \$32*10, $tmp + .byte 0x67,0x67 + shr \$12, $tmp + jz .Lmul_1024_no_n_copy + + # unaligned 256-bit load that crosses page boundary can + # cause severe performance degradation here, so if $np does + # cross page boundary, copy it to stack and make sure stack + # frame doesn't... + sub \$32*10,%rsp + vmovdqu 32*0-128($np), $ACC0 + and \$-512, %rsp + vmovdqu 32*1-128($np), $ACC1 + vmovdqu 32*2-128($np), $ACC2 + vmovdqu 32*3-128($np), $ACC3 + vmovdqu 32*4-128($np), $ACC4 + vmovdqu 32*5-128($np), $ACC5 + vmovdqu 32*6-128($np), $ACC6 + vmovdqu 32*7-128($np), $ACC7 + vmovdqu 32*8-128($np), $ACC8 + lea 64+128(%rsp),$np + vmovdqu $ACC0, 32*0-128($np) + vpxor $ACC0, $ACC0, $ACC0 + vmovdqu $ACC1, 32*1-128($np) + vpxor $ACC1, $ACC1, $ACC1 + vmovdqu $ACC2, 32*2-128($np) + vpxor $ACC2, $ACC2, $ACC2 + vmovdqu $ACC3, 32*3-128($np) + vpxor $ACC3, $ACC3, $ACC3 + vmovdqu $ACC4, 32*4-128($np) + vpxor $ACC4, $ACC4, $ACC4 + vmovdqu $ACC5, 32*5-128($np) + vpxor $ACC5, $ACC5, $ACC5 + vmovdqu $ACC6, 32*6-128($np) + vpxor $ACC6, $ACC6, $ACC6 + vmovdqu $ACC7, 32*7-128($np) + vpxor $ACC7, $ACC7, $ACC7 + vmovdqu $ACC8, 32*8-128($np) + vmovdqa $ACC0, $ACC8 + vmovdqu $ACC9, 32*9-128($np) # $ACC9 is zero after vzeroall +.Lmul_1024_no_n_copy: + and \$-64,%rsp + + mov ($bp), %rbx + vpbroadcastq ($bp), $Bi + vmovdqu $ACC0, (%rsp) # clear top of stack + xor $r0, $r0 + .byte 0x67 + xor $r1, $r1 + xor $r2, $r2 + xor $r3, $r3 + + vmovdqu .Land_mask(%rip), $AND_MASK + mov \$9, $i + vmovdqu $ACC9, 32*9-128($rp) # $ACC9 is zero after vzeroall + jmp .Loop_mul_1024 + +.align 32 +.Loop_mul_1024: + vpsrlq \$29, $ACC3, $ACC9 # correct $ACC3(*) + mov %rbx, %rax + imulq -128($ap), %rax + add $r0, %rax + mov %rbx, $r1 + imulq 8-128($ap), $r1 + add 8(%rsp), $r1 + + mov %rax, $r0 + imull $n0, %eax + and \$0x1fffffff, %eax + + mov %rbx, $r2 + imulq 16-128($ap), $r2 + add 16(%rsp), $r2 + + mov %rbx, $r3 + imulq 24-128($ap), $r3 + add 24(%rsp), $r3 + vpmuludq 32*1-128($ap),$Bi,$TEMP0 + vmovd %eax, $Yi + vpaddq $TEMP0,$ACC1,$ACC1 + vpmuludq 32*2-128($ap),$Bi,$TEMP1 + vpbroadcastq $Yi, $Yi + vpaddq $TEMP1,$ACC2,$ACC2 + vpmuludq 32*3-128($ap),$Bi,$TEMP2 + vpand $AND_MASK, $ACC3, $ACC3 # correct $ACC3 + vpaddq $TEMP2,$ACC3,$ACC3 + vpmuludq 32*4-128($ap),$Bi,$TEMP0 + vpaddq $TEMP0,$ACC4,$ACC4 + vpmuludq 32*5-128($ap),$Bi,$TEMP1 + vpaddq $TEMP1,$ACC5,$ACC5 + vpmuludq 32*6-128($ap),$Bi,$TEMP2 + vpaddq $TEMP2,$ACC6,$ACC6 + vpmuludq 32*7-128($ap),$Bi,$TEMP0 + vpermq \$0x93, $ACC9, $ACC9 # correct $ACC3 + vpaddq $TEMP0,$ACC7,$ACC7 + vpmuludq 32*8-128($ap),$Bi,$TEMP1 + vpbroadcastq 8($bp), $Bi + vpaddq $TEMP1,$ACC8,$ACC8 + + mov %rax,%rdx + imulq -128($np),%rax + add %rax,$r0 + mov %rdx,%rax + imulq 8-128($np),%rax + add %rax,$r1 + mov %rdx,%rax + imulq 16-128($np),%rax + add %rax,$r2 + shr \$29, $r0 + imulq 24-128($np),%rdx + add %rdx,$r3 + add $r0, $r1 + + vpmuludq 32*1-128($np),$Yi,$TEMP2 + vmovq $Bi, %rbx + vpaddq $TEMP2,$ACC1,$ACC1 + vpmuludq 32*2-128($np),$Yi,$TEMP0 + vpaddq $TEMP0,$ACC2,$ACC2 + vpmuludq 32*3-128($np),$Yi,$TEMP1 + vpaddq $TEMP1,$ACC3,$ACC3 + vpmuludq 32*4-128($np),$Yi,$TEMP2 + vpaddq $TEMP2,$ACC4,$ACC4 + vpmuludq 32*5-128($np),$Yi,$TEMP0 + vpaddq $TEMP0,$ACC5,$ACC5 + vpmuludq 32*6-128($np),$Yi,$TEMP1 + vpaddq $TEMP1,$ACC6,$ACC6 + vpmuludq 32*7-128($np),$Yi,$TEMP2 + vpblendd \$3, $ZERO, $ACC9, $ACC9 # correct $ACC3 + vpaddq $TEMP2,$ACC7,$ACC7 + vpmuludq 32*8-128($np),$Yi,$TEMP0 + vpaddq $ACC9, $ACC3, $ACC3 # correct $ACC3 + vpaddq $TEMP0,$ACC8,$ACC8 + + mov %rbx, %rax + imulq -128($ap),%rax + add %rax,$r1 + vmovdqu -8+32*1-128($ap),$TEMP1 + mov %rbx, %rax + imulq 8-128($ap),%rax + add %rax,$r2 + vmovdqu -8+32*2-128($ap),$TEMP2 + + mov $r1, %rax + imull $n0, %eax + and \$0x1fffffff, %eax + + imulq 16-128($ap),%rbx + add %rbx,$r3 + vpmuludq $Bi,$TEMP1,$TEMP1 + vmovd %eax, $Yi + vmovdqu -8+32*3-128($ap),$TEMP0 + vpaddq $TEMP1,$ACC1,$ACC1 + vpmuludq $Bi,$TEMP2,$TEMP2 + vpbroadcastq $Yi, $Yi + vmovdqu -8+32*4-128($ap),$TEMP1 + vpaddq $TEMP2,$ACC2,$ACC2 + vpmuludq $Bi,$TEMP0,$TEMP0 + vmovdqu -8+32*5-128($ap),$TEMP2 + vpaddq $TEMP0,$ACC3,$ACC3 + vpmuludq $Bi,$TEMP1,$TEMP1 + vmovdqu -8+32*6-128($ap),$TEMP0 + vpaddq $TEMP1,$ACC4,$ACC4 + vpmuludq $Bi,$TEMP2,$TEMP2 + vmovdqu -8+32*7-128($ap),$TEMP1 + vpaddq $TEMP2,$ACC5,$ACC5 + vpmuludq $Bi,$TEMP0,$TEMP0 + vmovdqu -8+32*8-128($ap),$TEMP2 + vpaddq $TEMP0,$ACC6,$ACC6 + vpmuludq $Bi,$TEMP1,$TEMP1 + vmovdqu -8+32*9-128($ap),$ACC9 + vpaddq $TEMP1,$ACC7,$ACC7 + vpmuludq $Bi,$TEMP2,$TEMP2 + vpaddq $TEMP2,$ACC8,$ACC8 + vpmuludq $Bi,$ACC9,$ACC9 + vpbroadcastq 16($bp), $Bi + + mov %rax,%rdx + imulq -128($np),%rax + add %rax,$r1 + vmovdqu -8+32*1-128($np),$TEMP0 + mov %rdx,%rax + imulq 8-128($np),%rax + add %rax,$r2 + vmovdqu -8+32*2-128($np),$TEMP1 + shr \$29, $r1 + imulq 16-128($np),%rdx + add %rdx,$r3 + add $r1, $r2 + + vpmuludq $Yi,$TEMP0,$TEMP0 + vmovq $Bi, %rbx + vmovdqu -8+32*3-128($np),$TEMP2 + vpaddq $TEMP0,$ACC1,$ACC1 + vpmuludq $Yi,$TEMP1,$TEMP1 + vmovdqu -8+32*4-128($np),$TEMP0 + vpaddq $TEMP1,$ACC2,$ACC2 + vpmuludq $Yi,$TEMP2,$TEMP2 + vmovdqu -8+32*5-128($np),$TEMP1 + vpaddq $TEMP2,$ACC3,$ACC3 + vpmuludq $Yi,$TEMP0,$TEMP0 + vmovdqu -8+32*6-128($np),$TEMP2 + vpaddq $TEMP0,$ACC4,$ACC4 + vpmuludq $Yi,$TEMP1,$TEMP1 + vmovdqu -8+32*7-128($np),$TEMP0 + vpaddq $TEMP1,$ACC5,$ACC5 + vpmuludq $Yi,$TEMP2,$TEMP2 + vmovdqu -8+32*8-128($np),$TEMP1 + vpaddq $TEMP2,$ACC6,$ACC6 + vpmuludq $Yi,$TEMP0,$TEMP0 + vmovdqu -8+32*9-128($np),$TEMP2 + vpaddq $TEMP0,$ACC7,$ACC7 + vpmuludq $Yi,$TEMP1,$TEMP1 + vpaddq $TEMP1,$ACC8,$ACC8 + vpmuludq $Yi,$TEMP2,$TEMP2 + vpaddq $TEMP2,$ACC9,$ACC9 + + vmovdqu -16+32*1-128($ap),$TEMP0 + mov %rbx,%rax + imulq -128($ap),%rax + add $r2,%rax + + vmovdqu -16+32*2-128($ap),$TEMP1 + mov %rax,$r2 + imull $n0, %eax + and \$0x1fffffff, %eax + + imulq 8-128($ap),%rbx + add %rbx,$r3 + vpmuludq $Bi,$TEMP0,$TEMP0 + vmovd %eax, $Yi + vmovdqu -16+32*3-128($ap),$TEMP2 + vpaddq $TEMP0,$ACC1,$ACC1 + vpmuludq $Bi,$TEMP1,$TEMP1 + vpbroadcastq $Yi, $Yi + vmovdqu -16+32*4-128($ap),$TEMP0 + vpaddq $TEMP1,$ACC2,$ACC2 + vpmuludq $Bi,$TEMP2,$TEMP2 + vmovdqu -16+32*5-128($ap),$TEMP1 + vpaddq $TEMP2,$ACC3,$ACC3 + vpmuludq $Bi,$TEMP0,$TEMP0 + vmovdqu -16+32*6-128($ap),$TEMP2 + vpaddq $TEMP0,$ACC4,$ACC4 + vpmuludq $Bi,$TEMP1,$TEMP1 + vmovdqu -16+32*7-128($ap),$TEMP0 + vpaddq $TEMP1,$ACC5,$ACC5 + vpmuludq $Bi,$TEMP2,$TEMP2 + vmovdqu -16+32*8-128($ap),$TEMP1 + vpaddq $TEMP2,$ACC6,$ACC6 + vpmuludq $Bi,$TEMP0,$TEMP0 + vmovdqu -16+32*9-128($ap),$TEMP2 + vpaddq $TEMP0,$ACC7,$ACC7 + vpmuludq $Bi,$TEMP1,$TEMP1 + vpaddq $TEMP1,$ACC8,$ACC8 + vpmuludq $Bi,$TEMP2,$TEMP2 + vpbroadcastq 24($bp), $Bi + vpaddq $TEMP2,$ACC9,$ACC9 + + vmovdqu -16+32*1-128($np),$TEMP0 + mov %rax,%rdx + imulq -128($np),%rax + add %rax,$r2 + vmovdqu -16+32*2-128($np),$TEMP1 + imulq 8-128($np),%rdx + add %rdx,$r3 + shr \$29, $r2 + + vpmuludq $Yi,$TEMP0,$TEMP0 + vmovq $Bi, %rbx + vmovdqu -16+32*3-128($np),$TEMP2 + vpaddq $TEMP0,$ACC1,$ACC1 + vpmuludq $Yi,$TEMP1,$TEMP1 + vmovdqu -16+32*4-128($np),$TEMP0 + vpaddq $TEMP1,$ACC2,$ACC2 + vpmuludq $Yi,$TEMP2,$TEMP2 + vmovdqu -16+32*5-128($np),$TEMP1 + vpaddq $TEMP2,$ACC3,$ACC3 + vpmuludq $Yi,$TEMP0,$TEMP0 + vmovdqu -16+32*6-128($np),$TEMP2 + vpaddq $TEMP0,$ACC4,$ACC4 + vpmuludq $Yi,$TEMP1,$TEMP1 + vmovdqu -16+32*7-128($np),$TEMP0 + vpaddq $TEMP1,$ACC5,$ACC5 + vpmuludq $Yi,$TEMP2,$TEMP2 + vmovdqu -16+32*8-128($np),$TEMP1 + vpaddq $TEMP2,$ACC6,$ACC6 + vpmuludq $Yi,$TEMP0,$TEMP0 + vmovdqu -16+32*9-128($np),$TEMP2 + vpaddq $TEMP0,$ACC7,$ACC7 + vpmuludq $Yi,$TEMP1,$TEMP1 + vmovdqu -24+32*1-128($ap),$TEMP0 + vpaddq $TEMP1,$ACC8,$ACC8 + vpmuludq $Yi,$TEMP2,$TEMP2 + vmovdqu -24+32*2-128($ap),$TEMP1 + vpaddq $TEMP2,$ACC9,$ACC9 + + add $r2, $r3 + imulq -128($ap),%rbx + add %rbx,$r3 + + mov $r3, %rax + imull $n0, %eax + and \$0x1fffffff, %eax + + vpmuludq $Bi,$TEMP0,$TEMP0 + vmovd %eax, $Yi + vmovdqu -24+32*3-128($ap),$TEMP2 + vpaddq $TEMP0,$ACC1,$ACC1 + vpmuludq $Bi,$TEMP1,$TEMP1 + vpbroadcastq $Yi, $Yi + vmovdqu -24+32*4-128($ap),$TEMP0 + vpaddq $TEMP1,$ACC2,$ACC2 + vpmuludq $Bi,$TEMP2,$TEMP2 + vmovdqu -24+32*5-128($ap),$TEMP1 + vpaddq $TEMP2,$ACC3,$ACC3 + vpmuludq $Bi,$TEMP0,$TEMP0 + vmovdqu -24+32*6-128($ap),$TEMP2 + vpaddq $TEMP0,$ACC4,$ACC4 + vpmuludq $Bi,$TEMP1,$TEMP1 + vmovdqu -24+32*7-128($ap),$TEMP0 + vpaddq $TEMP1,$ACC5,$ACC5 + vpmuludq $Bi,$TEMP2,$TEMP2 + vmovdqu -24+32*8-128($ap),$TEMP1 + vpaddq $TEMP2,$ACC6,$ACC6 + vpmuludq $Bi,$TEMP0,$TEMP0 + vmovdqu -24+32*9-128($ap),$TEMP2 + vpaddq $TEMP0,$ACC7,$ACC7 + vpmuludq $Bi,$TEMP1,$TEMP1 + vpaddq $TEMP1,$ACC8,$ACC8 + vpmuludq $Bi,$TEMP2,$TEMP2 + vpbroadcastq 32($bp), $Bi + vpaddq $TEMP2,$ACC9,$ACC9 + add \$32, $bp # $bp++ + + vmovdqu -24+32*1-128($np),$TEMP0 + imulq -128($np),%rax + add %rax,$r3 + shr \$29, $r3 + + vmovdqu -24+32*2-128($np),$TEMP1 + vpmuludq $Yi,$TEMP0,$TEMP0 + vmovq $Bi, %rbx + vmovdqu -24+32*3-128($np),$TEMP2 + vpaddq $TEMP0,$ACC1,$ACC0 # $ACC0==$TEMP0 + vpmuludq $Yi,$TEMP1,$TEMP1 + vmovdqu $ACC0, (%rsp) # transfer $r0-$r3 + vpaddq $TEMP1,$ACC2,$ACC1 + vmovdqu -24+32*4-128($np),$TEMP0 + vpmuludq $Yi,$TEMP2,$TEMP2 + vmovdqu -24+32*5-128($np),$TEMP1 + vpaddq $TEMP2,$ACC3,$ACC2 + vpmuludq $Yi,$TEMP0,$TEMP0 + vmovdqu -24+32*6-128($np),$TEMP2 + vpaddq $TEMP0,$ACC4,$ACC3 + vpmuludq $Yi,$TEMP1,$TEMP1 + vmovdqu -24+32*7-128($np),$TEMP0 + vpaddq $TEMP1,$ACC5,$ACC4 + vpmuludq $Yi,$TEMP2,$TEMP2 + vmovdqu -24+32*8-128($np),$TEMP1 + vpaddq $TEMP2,$ACC6,$ACC5 + vpmuludq $Yi,$TEMP0,$TEMP0 + vmovdqu -24+32*9-128($np),$TEMP2 + mov $r3, $r0 + vpaddq $TEMP0,$ACC7,$ACC6 + vpmuludq $Yi,$TEMP1,$TEMP1 + add (%rsp), $r0 + vpaddq $TEMP1,$ACC8,$ACC7 + vpmuludq $Yi,$TEMP2,$TEMP2 + vmovq $r3, $TEMP1 + vpaddq $TEMP2,$ACC9,$ACC8 + + dec $i + jnz .Loop_mul_1024 +___ + +# (*) Original implementation was correcting ACC1-ACC3 for overflow +# after 7 loop runs, or after 28 iterations, or 56 additions. +# But as we underutilize resources, it's possible to correct in +# each iteration with marginal performance loss. But then, as +# we do it in each iteration, we can correct less digits, and +# avoid performance penalties completely. Also note that we +# correct only three digits out of four. This works because +# most significant digit is subjected to less additions. + +$TEMP0 = $ACC9; +$TEMP3 = $Bi; +$TEMP4 = $Yi; +$code.=<<___; + vpermq \$0, $AND_MASK, $AND_MASK + vpaddq (%rsp), $TEMP1, $ACC0 + + vpsrlq \$29, $ACC0, $TEMP1 + vpand $AND_MASK, $ACC0, $ACC0 + vpsrlq \$29, $ACC1, $TEMP2 + vpand $AND_MASK, $ACC1, $ACC1 + vpsrlq \$29, $ACC2, $TEMP3 + vpermq \$0x93, $TEMP1, $TEMP1 + vpand $AND_MASK, $ACC2, $ACC2 + vpsrlq \$29, $ACC3, $TEMP4 + vpermq \$0x93, $TEMP2, $TEMP2 + vpand $AND_MASK, $ACC3, $ACC3 + + vpblendd \$3, $ZERO, $TEMP1, $TEMP0 + vpermq \$0x93, $TEMP3, $TEMP3 + vpblendd \$3, $TEMP1, $TEMP2, $TEMP1 + vpermq \$0x93, $TEMP4, $TEMP4 + vpaddq $TEMP0, $ACC0, $ACC0 + vpblendd \$3, $TEMP2, $TEMP3, $TEMP2 + vpaddq $TEMP1, $ACC1, $ACC1 + vpblendd \$3, $TEMP3, $TEMP4, $TEMP3 + vpaddq $TEMP2, $ACC2, $ACC2 + vpblendd \$3, $TEMP4, $ZERO, $TEMP4 + vpaddq $TEMP3, $ACC3, $ACC3 + vpaddq $TEMP4, $ACC4, $ACC4 + + vpsrlq \$29, $ACC0, $TEMP1 + vpand $AND_MASK, $ACC0, $ACC0 + vpsrlq \$29, $ACC1, $TEMP2 + vpand $AND_MASK, $ACC1, $ACC1 + vpsrlq \$29, $ACC2, $TEMP3 + vpermq \$0x93, $TEMP1, $TEMP1 + vpand $AND_MASK, $ACC2, $ACC2 + vpsrlq \$29, $ACC3, $TEMP4 + vpermq \$0x93, $TEMP2, $TEMP2 + vpand $AND_MASK, $ACC3, $ACC3 + vpermq \$0x93, $TEMP3, $TEMP3 + + vpblendd \$3, $ZERO, $TEMP1, $TEMP0 + vpermq \$0x93, $TEMP4, $TEMP4 + vpblendd \$3, $TEMP1, $TEMP2, $TEMP1 + vpaddq $TEMP0, $ACC0, $ACC0 + vpblendd \$3, $TEMP2, $TEMP3, $TEMP2 + vpaddq $TEMP1, $ACC1, $ACC1 + vpblendd \$3, $TEMP3, $TEMP4, $TEMP3 + vpaddq $TEMP2, $ACC2, $ACC2 + vpblendd \$3, $TEMP4, $ZERO, $TEMP4 + vpaddq $TEMP3, $ACC3, $ACC3 + vpaddq $TEMP4, $ACC4, $ACC4 + + vmovdqu $ACC0, 0-128($rp) + vmovdqu $ACC1, 32-128($rp) + vmovdqu $ACC2, 64-128($rp) + vmovdqu $ACC3, 96-128($rp) +___ + +$TEMP5=$ACC0; +$code.=<<___; + vpsrlq \$29, $ACC4, $TEMP1 + vpand $AND_MASK, $ACC4, $ACC4 + vpsrlq \$29, $ACC5, $TEMP2 + vpand $AND_MASK, $ACC5, $ACC5 + vpsrlq \$29, $ACC6, $TEMP3 + vpermq \$0x93, $TEMP1, $TEMP1 + vpand $AND_MASK, $ACC6, $ACC6 + vpsrlq \$29, $ACC7, $TEMP4 + vpermq \$0x93, $TEMP2, $TEMP2 + vpand $AND_MASK, $ACC7, $ACC7 + vpsrlq \$29, $ACC8, $TEMP5 + vpermq \$0x93, $TEMP3, $TEMP3 + vpand $AND_MASK, $ACC8, $ACC8 + vpermq \$0x93, $TEMP4, $TEMP4 + + vpblendd \$3, $ZERO, $TEMP1, $TEMP0 + vpermq \$0x93, $TEMP5, $TEMP5 + vpblendd \$3, $TEMP1, $TEMP2, $TEMP1 + vpaddq $TEMP0, $ACC4, $ACC4 + vpblendd \$3, $TEMP2, $TEMP3, $TEMP2 + vpaddq $TEMP1, $ACC5, $ACC5 + vpblendd \$3, $TEMP3, $TEMP4, $TEMP3 + vpaddq $TEMP2, $ACC6, $ACC6 + vpblendd \$3, $TEMP4, $TEMP5, $TEMP4 + vpaddq $TEMP3, $ACC7, $ACC7 + vpaddq $TEMP4, $ACC8, $ACC8 + + vpsrlq \$29, $ACC4, $TEMP1 + vpand $AND_MASK, $ACC4, $ACC4 + vpsrlq \$29, $ACC5, $TEMP2 + vpand $AND_MASK, $ACC5, $ACC5 + vpsrlq \$29, $ACC6, $TEMP3 + vpermq \$0x93, $TEMP1, $TEMP1 + vpand $AND_MASK, $ACC6, $ACC6 + vpsrlq \$29, $ACC7, $TEMP4 + vpermq \$0x93, $TEMP2, $TEMP2 + vpand $AND_MASK, $ACC7, $ACC7 + vpsrlq \$29, $ACC8, $TEMP5 + vpermq \$0x93, $TEMP3, $TEMP3 + vpand $AND_MASK, $ACC8, $ACC8 + vpermq \$0x93, $TEMP4, $TEMP4 + + vpblendd \$3, $ZERO, $TEMP1, $TEMP0 + vpermq \$0x93, $TEMP5, $TEMP5 + vpblendd \$3, $TEMP1, $TEMP2, $TEMP1 + vpaddq $TEMP0, $ACC4, $ACC4 + vpblendd \$3, $TEMP2, $TEMP3, $TEMP2 + vpaddq $TEMP1, $ACC5, $ACC5 + vpblendd \$3, $TEMP3, $TEMP4, $TEMP3 + vpaddq $TEMP2, $ACC6, $ACC6 + vpblendd \$3, $TEMP4, $TEMP5, $TEMP4 + vpaddq $TEMP3, $ACC7, $ACC7 + vpaddq $TEMP4, $ACC8, $ACC8 + + vmovdqu $ACC4, 128-128($rp) + vmovdqu $ACC5, 160-128($rp) + vmovdqu $ACC6, 192-128($rp) + vmovdqu $ACC7, 224-128($rp) + vmovdqu $ACC8, 256-128($rp) + vzeroupper + + mov %rbp, %rax +___ +$code.=<<___ if ($win64); + movaps -0xd8(%rax),%xmm6 + movaps -0xc8(%rax),%xmm7 + movaps -0xb8(%rax),%xmm8 + movaps -0xa8(%rax),%xmm9 + movaps -0x98(%rax),%xmm10 + movaps -0x88(%rax),%xmm11 + movaps -0x78(%rax),%xmm12 + movaps -0x68(%rax),%xmm13 + movaps -0x58(%rax),%xmm14 + movaps -0x48(%rax),%xmm15 +___ +$code.=<<___; + mov -48(%rax),%r15 + mov -40(%rax),%r14 + mov -32(%rax),%r13 + mov -24(%rax),%r12 + mov -16(%rax),%rbp + mov -8(%rax),%rbx + lea (%rax),%rsp # restore %rsp +.Lmul_1024_epilogue: + ret +.size rsaz_1024_mul_avx2,.-rsaz_1024_mul_avx2 +___ +} +{ +my ($out,$inp) = $win64 ? ("%rcx","%rdx") : ("%rdi","%rsi"); +my @T = map("%r$_",(8..11)); + +$code.=<<___; +.globl rsaz_1024_red2norm_avx2 +.type rsaz_1024_red2norm_avx2,\@abi-omnipotent +.align 32 +rsaz_1024_red2norm_avx2: + sub \$-128,$inp # size optimization + xor %rax,%rax +___ + +for ($j=0,$i=0; $i<16; $i++) { + my $k=0; + while (29*$j<64*($i+1)) { # load data till boundary + $code.=" mov `8*$j-128`($inp), @T[0]\n"; + $j++; $k++; push(@T,shift(@T)); + } + $l=$k; + while ($k>1) { # shift loaded data but last value + $code.=" shl \$`29*($j-$k)`,@T[-$k]\n"; + $k--; + } + $code.=<<___; # shift last value + mov @T[-1], @T[0] + shl \$`29*($j-1)`, @T[-1] + shr \$`-29*($j-1)`, @T[0] +___ + while ($l) { # accumulate all values + $code.=" add @T[-$l], %rax\n"; + $l--; + } + $code.=<<___; + adc \$0, @T[0] # consume eventual carry + mov %rax, 8*$i($out) + mov @T[0], %rax +___ + push(@T,shift(@T)); +} +$code.=<<___; + ret +.size rsaz_1024_red2norm_avx2,.-rsaz_1024_red2norm_avx2 + +.globl rsaz_1024_norm2red_avx2 +.type rsaz_1024_norm2red_avx2,\@abi-omnipotent +.align 32 +rsaz_1024_norm2red_avx2: + sub \$-128,$out # size optimization + mov ($inp),@T[0] + mov \$0x1fffffff,%eax +___ +for ($j=0,$i=0; $i<16; $i++) { + $code.=" mov `8*($i+1)`($inp),@T[1]\n" if ($i<15); + $code.=" xor @T[1],@T[1]\n" if ($i==15); + my $k=1; + while (29*($j+1)<64*($i+1)) { + $code.=<<___; + mov @T[0],@T[-$k] + shr \$`29*$j`,@T[-$k] + and %rax,@T[-$k] # &0x1fffffff + mov @T[-$k],`8*$j-128`($out) +___ + $j++; $k++; + } + $code.=<<___; + shrd \$`29*$j`,@T[1],@T[0] + and %rax,@T[0] + mov @T[0],`8*$j-128`($out) +___ + $j++; + push(@T,shift(@T)); +} +$code.=<<___; + mov @T[0],`8*$j-128`($out) # zero + mov @T[0],`8*($j+1)-128`($out) + mov @T[0],`8*($j+2)-128`($out) + mov @T[0],`8*($j+3)-128`($out) + ret +.size rsaz_1024_norm2red_avx2,.-rsaz_1024_norm2red_avx2 +___ +} +{ +my ($out,$inp,$power) = $win64 ? ("%rcx","%rdx","%r8d") : ("%rdi","%rsi","%edx"); + +$code.=<<___; +.globl rsaz_1024_scatter5_avx2 +.type rsaz_1024_scatter5_avx2,\@abi-omnipotent +.align 32 +rsaz_1024_scatter5_avx2: + vzeroupper + vmovdqu .Lscatter_permd(%rip),%ymm5 + shl \$4,$power + lea ($out,$power),$out + mov \$9,%eax + jmp .Loop_scatter_1024 + +.align 32 +.Loop_scatter_1024: + vmovdqu ($inp),%ymm0 + lea 32($inp),$inp + vpermd %ymm0,%ymm5,%ymm0 + vmovdqu %xmm0,($out) + lea 16*32($out),$out + dec %eax + jnz .Loop_scatter_1024 + + vzeroupper + ret +.size rsaz_1024_scatter5_avx2,.-rsaz_1024_scatter5_avx2 + +.globl rsaz_1024_gather5_avx2 +.type rsaz_1024_gather5_avx2,\@abi-omnipotent +.align 32 +rsaz_1024_gather5_avx2: + vzeroupper + mov %rsp,%r11 +___ +$code.=<<___ if ($win64); + lea -0x88(%rsp),%rax +.LSEH_begin_rsaz_1024_gather5: + # I can't trust assembler to use specific encoding:-( + .byte 0x48,0x8d,0x60,0xe0 # lea -0x20(%rax),%rsp + .byte 0xc5,0xf8,0x29,0x70,0xe0 # vmovaps %xmm6,-0x20(%rax) + .byte 0xc5,0xf8,0x29,0x78,0xf0 # vmovaps %xmm7,-0x10(%rax) + .byte 0xc5,0x78,0x29,0x40,0x00 # vmovaps %xmm8,0(%rax) + .byte 0xc5,0x78,0x29,0x48,0x10 # vmovaps %xmm9,0x10(%rax) + .byte 0xc5,0x78,0x29,0x50,0x20 # vmovaps %xmm10,0x20(%rax) + .byte 0xc5,0x78,0x29,0x58,0x30 # vmovaps %xmm11,0x30(%rax) + .byte 0xc5,0x78,0x29,0x60,0x40 # vmovaps %xmm12,0x40(%rax) + .byte 0xc5,0x78,0x29,0x68,0x50 # vmovaps %xmm13,0x50(%rax) + .byte 0xc5,0x78,0x29,0x70,0x60 # vmovaps %xmm14,0x60(%rax) + .byte 0xc5,0x78,0x29,0x78,0x70 # vmovaps %xmm15,0x70(%rax) +___ +$code.=<<___; + lea -0x100(%rsp),%rsp + and \$-32, %rsp + lea .Linc(%rip), %r10 + lea -128(%rsp),%rax # control u-op density + + vmovd $power, %xmm4 + vmovdqa (%r10),%ymm0 + vmovdqa 32(%r10),%ymm1 + vmovdqa 64(%r10),%ymm5 + vpbroadcastd %xmm4,%ymm4 + + vpaddd %ymm5, %ymm0, %ymm2 + vpcmpeqd %ymm4, %ymm0, %ymm0 + vpaddd %ymm5, %ymm1, %ymm3 + vpcmpeqd %ymm4, %ymm1, %ymm1 + vmovdqa %ymm0, 32*0+128(%rax) + vpaddd %ymm5, %ymm2, %ymm0 + vpcmpeqd %ymm4, %ymm2, %ymm2 + vmovdqa %ymm1, 32*1+128(%rax) + vpaddd %ymm5, %ymm3, %ymm1 + vpcmpeqd %ymm4, %ymm3, %ymm3 + vmovdqa %ymm2, 32*2+128(%rax) + vpaddd %ymm5, %ymm0, %ymm2 + vpcmpeqd %ymm4, %ymm0, %ymm0 + vmovdqa %ymm3, 32*3+128(%rax) + vpaddd %ymm5, %ymm1, %ymm3 + vpcmpeqd %ymm4, %ymm1, %ymm1 + vmovdqa %ymm0, 32*4+128(%rax) + vpaddd %ymm5, %ymm2, %ymm8 + vpcmpeqd %ymm4, %ymm2, %ymm2 + vmovdqa %ymm1, 32*5+128(%rax) + vpaddd %ymm5, %ymm3, %ymm9 + vpcmpeqd %ymm4, %ymm3, %ymm3 + vmovdqa %ymm2, 32*6+128(%rax) + vpaddd %ymm5, %ymm8, %ymm10 + vpcmpeqd %ymm4, %ymm8, %ymm8 + vmovdqa %ymm3, 32*7+128(%rax) + vpaddd %ymm5, %ymm9, %ymm11 + vpcmpeqd %ymm4, %ymm9, %ymm9 + vpaddd %ymm5, %ymm10, %ymm12 + vpcmpeqd %ymm4, %ymm10, %ymm10 + vpaddd %ymm5, %ymm11, %ymm13 + vpcmpeqd %ymm4, %ymm11, %ymm11 + vpaddd %ymm5, %ymm12, %ymm14 + vpcmpeqd %ymm4, %ymm12, %ymm12 + vpaddd %ymm5, %ymm13, %ymm15 + vpcmpeqd %ymm4, %ymm13, %ymm13 + vpcmpeqd %ymm4, %ymm14, %ymm14 + vpcmpeqd %ymm4, %ymm15, %ymm15 + + vmovdqa -32(%r10),%ymm7 # .Lgather_permd + lea 128($inp), $inp + mov \$9,$power + +.Loop_gather_1024: + vmovdqa 32*0-128($inp), %ymm0 + vmovdqa 32*1-128($inp), %ymm1 + vmovdqa 32*2-128($inp), %ymm2 + vmovdqa 32*3-128($inp), %ymm3 + vpand 32*0+128(%rax), %ymm0, %ymm0 + vpand 32*1+128(%rax), %ymm1, %ymm1 + vpand 32*2+128(%rax), %ymm2, %ymm2 + vpor %ymm0, %ymm1, %ymm4 + vpand 32*3+128(%rax), %ymm3, %ymm3 + vmovdqa 32*4-128($inp), %ymm0 + vmovdqa 32*5-128($inp), %ymm1 + vpor %ymm2, %ymm3, %ymm5 + vmovdqa 32*6-128($inp), %ymm2 + vmovdqa 32*7-128($inp), %ymm3 + vpand 32*4+128(%rax), %ymm0, %ymm0 + vpand 32*5+128(%rax), %ymm1, %ymm1 + vpand 32*6+128(%rax), %ymm2, %ymm2 + vpor %ymm0, %ymm4, %ymm4 + vpand 32*7+128(%rax), %ymm3, %ymm3 + vpand 32*8-128($inp), %ymm8, %ymm0 + vpor %ymm1, %ymm5, %ymm5 + vpand 32*9-128($inp), %ymm9, %ymm1 + vpor %ymm2, %ymm4, %ymm4 + vpand 32*10-128($inp),%ymm10, %ymm2 + vpor %ymm3, %ymm5, %ymm5 + vpand 32*11-128($inp),%ymm11, %ymm3 + vpor %ymm0, %ymm4, %ymm4 + vpand 32*12-128($inp),%ymm12, %ymm0 + vpor %ymm1, %ymm5, %ymm5 + vpand 32*13-128($inp),%ymm13, %ymm1 + vpor %ymm2, %ymm4, %ymm4 + vpand 32*14-128($inp),%ymm14, %ymm2 + vpor %ymm3, %ymm5, %ymm5 + vpand 32*15-128($inp),%ymm15, %ymm3 + lea 32*16($inp), $inp + vpor %ymm0, %ymm4, %ymm4 + vpor %ymm1, %ymm5, %ymm5 + vpor %ymm2, %ymm4, %ymm4 + vpor %ymm3, %ymm5, %ymm5 + + vpor %ymm5, %ymm4, %ymm4 + vextracti128 \$1, %ymm4, %xmm5 # upper half is cleared + vpor %xmm4, %xmm5, %xmm5 + vpermd %ymm5,%ymm7,%ymm5 + vmovdqu %ymm5,($out) + lea 32($out),$out + dec $power + jnz .Loop_gather_1024 + + vpxor %ymm0,%ymm0,%ymm0 + vmovdqu %ymm0,($out) + vzeroupper +___ +$code.=<<___ if ($win64); + movaps -0xa8(%r11),%xmm6 + movaps -0x98(%r11),%xmm7 + movaps -0x88(%r11),%xmm8 + movaps -0x78(%r11),%xmm9 + movaps -0x68(%r11),%xmm10 + movaps -0x58(%r11),%xmm11 + movaps -0x48(%r11),%xmm12 + movaps -0x38(%r11),%xmm13 + movaps -0x28(%r11),%xmm14 + movaps -0x18(%r11),%xmm15 +.LSEH_end_rsaz_1024_gather5: +___ +$code.=<<___; + lea (%r11),%rsp + ret +.size rsaz_1024_gather5_avx2,.-rsaz_1024_gather5_avx2 +___ +} + +$code.=<<___; +.extern OPENSSL_ia32cap_P +.globl rsaz_avx2_eligible +.type rsaz_avx2_eligible,\@abi-omnipotent +.align 32 +rsaz_avx2_eligible: + mov OPENSSL_ia32cap_P+8(%rip),%eax +___ +$code.=<<___ if ($addx); + mov \$`1<<8|1<<19`,%ecx + mov \$0,%edx + and %eax,%ecx + cmp \$`1<<8|1<<19`,%ecx # check for BMI2+AD*X + cmove %edx,%eax +___ +$code.=<<___; + and \$`1<<5`,%eax + shr \$5,%eax + ret +.size rsaz_avx2_eligible,.-rsaz_avx2_eligible + +.align 64 +.Land_mask: + .quad 0x1fffffff,0x1fffffff,0x1fffffff,-1 +.Lscatter_permd: + .long 0,2,4,6,7,7,7,7 +.Lgather_permd: + .long 0,7,1,7,2,7,3,7 +.Linc: + .long 0,0,0,0, 1,1,1,1 + .long 2,2,2,2, 3,3,3,3 + .long 4,4,4,4, 4,4,4,4 +.align 64 +___ + +if ($win64) { +$rec="%rcx"; +$frame="%rdx"; +$context="%r8"; +$disp="%r9"; + +$code.=<<___ +.extern __imp_RtlVirtualUnwind +.type rsaz_se_handler,\@abi-omnipotent +.align 16 +rsaz_se_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + mov 8($disp),%rsi # disp->ImageBase + mov 56($disp),%r11 # disp->HandlerData + + mov 0(%r11),%r10d # HandlerData[0] + lea (%rsi,%r10),%r10 # prologue label + cmp %r10,%rbx # context->RipRsp + + mov 4(%r11),%r10d # HandlerData[1] + lea (%rsi,%r10),%r10 # epilogue label + cmp %r10,%rbx # context->Rip>=epilogue label + jae .Lcommon_seh_tail + + mov 160($context),%rax # pull context->Rbp + + mov -48(%rax),%r15 + mov -40(%rax),%r14 + mov -32(%rax),%r13 + mov -24(%rax),%r12 + mov -16(%rax),%rbp + mov -8(%rax),%rbx + mov %r15,240($context) + mov %r14,232($context) + mov %r13,224($context) + mov %r12,216($context) + mov %rbp,160($context) + mov %rbx,144($context) + + lea -0xd8(%rax),%rsi # %xmm save area + lea 512($context),%rdi # & context.Xmm6 + mov \$20,%ecx # 10*sizeof(%xmm0)/sizeof(%rax) + .long 0xa548f3fc # cld; rep movsq + +.Lcommon_seh_tail: + mov 8(%rax),%rdi + mov 16(%rax),%rsi + mov %rax,152($context) # restore context->Rsp + mov %rsi,168($context) # restore context->Rsi + mov %rdi,176($context) # restore context->Rdi + + mov 40($disp),%rdi # disp->ContextRecord + mov $context,%rsi # context + mov \$154,%ecx # sizeof(CONTEXT) + .long 0xa548f3fc # cld; rep movsq + + mov $disp,%rsi + xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER + mov 8(%rsi),%rdx # arg2, disp->ImageBase + mov 0(%rsi),%r8 # arg3, disp->ControlPc + mov 16(%rsi),%r9 # arg4, disp->FunctionEntry + mov 40(%rsi),%r10 # disp->ContextRecord + lea 56(%rsi),%r11 # &disp->HandlerData + lea 24(%rsi),%r12 # &disp->EstablisherFrame + mov %r10,32(%rsp) # arg5 + mov %r11,40(%rsp) # arg6 + mov %r12,48(%rsp) # arg7 + mov %rcx,56(%rsp) # arg8, (NULL) + call *__imp_RtlVirtualUnwind(%rip) + + mov \$1,%eax # ExceptionContinueSearch + add \$64,%rsp + popfq + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + pop %rdi + pop %rsi + ret +.size rsaz_se_handler,.-rsaz_se_handler + +.section .pdata +.align 4 + .rva .LSEH_begin_rsaz_1024_sqr_avx2 + .rva .LSEH_end_rsaz_1024_sqr_avx2 + .rva .LSEH_info_rsaz_1024_sqr_avx2 + + .rva .LSEH_begin_rsaz_1024_mul_avx2 + .rva .LSEH_end_rsaz_1024_mul_avx2 + .rva .LSEH_info_rsaz_1024_mul_avx2 + + .rva .LSEH_begin_rsaz_1024_gather5 + .rva .LSEH_end_rsaz_1024_gather5 + .rva .LSEH_info_rsaz_1024_gather5 +.section .xdata +.align 8 +.LSEH_info_rsaz_1024_sqr_avx2: + .byte 9,0,0,0 + .rva rsaz_se_handler + .rva .Lsqr_1024_body,.Lsqr_1024_epilogue +.LSEH_info_rsaz_1024_mul_avx2: + .byte 9,0,0,0 + .rva rsaz_se_handler + .rva .Lmul_1024_body,.Lmul_1024_epilogue +.LSEH_info_rsaz_1024_gather5: + .byte 0x01,0x36,0x17,0x0b + .byte 0x36,0xf8,0x09,0x00 # vmovaps 0x90(rsp),xmm15 + .byte 0x31,0xe8,0x08,0x00 # vmovaps 0x80(rsp),xmm14 + .byte 0x2c,0xd8,0x07,0x00 # vmovaps 0x70(rsp),xmm13 + .byte 0x27,0xc8,0x06,0x00 # vmovaps 0x60(rsp),xmm12 + .byte 0x22,0xb8,0x05,0x00 # vmovaps 0x50(rsp),xmm11 + .byte 0x1d,0xa8,0x04,0x00 # vmovaps 0x40(rsp),xmm10 + .byte 0x18,0x98,0x03,0x00 # vmovaps 0x30(rsp),xmm9 + .byte 0x13,0x88,0x02,0x00 # vmovaps 0x20(rsp),xmm8 + .byte 0x0e,0x78,0x01,0x00 # vmovaps 0x10(rsp),xmm7 + .byte 0x09,0x68,0x00,0x00 # vmovaps 0x00(rsp),xmm6 + .byte 0x04,0x01,0x15,0x00 # sub rsp,0xa8 + .byte 0x00,0xb3,0x00,0x00 # set_frame r11 +___ +} + +foreach (split("\n",$code)) { + s/\`([^\`]*)\`/eval($1)/ge; + + s/\b(sh[rl]d?\s+\$)(-?[0-9]+)/$1.$2%64/ge or + + s/\b(vmov[dq])\b(.+)%ymm([0-9]+)/$1$2%xmm$3/go or + s/\b(vmovdqu)\b(.+)%x%ymm([0-9]+)/$1$2%xmm$3/go or + s/\b(vpinsr[qd])\b(.+)%ymm([0-9]+)/$1$2%xmm$3/go or + s/\b(vpextr[qd])\b(.+)%ymm([0-9]+)/$1$2%xmm$3/go or + s/\b(vpbroadcast[qd]\s+)%ymm([0-9]+)/$1%xmm$2/go; + print $_,"\n"; +} + +}}} else {{{ +print <<___; # assembler is too old +.text + +.globl rsaz_avx2_eligible +.type rsaz_avx2_eligible,\@abi-omnipotent +rsaz_avx2_eligible: + xor %eax,%eax + ret +.size rsaz_avx2_eligible,.-rsaz_avx2_eligible + +.globl rsaz_1024_sqr_avx2 +.globl rsaz_1024_mul_avx2 +.globl rsaz_1024_norm2red_avx2 +.globl rsaz_1024_red2norm_avx2 +.globl rsaz_1024_scatter5_avx2 +.globl rsaz_1024_gather5_avx2 +.type rsaz_1024_sqr_avx2,\@abi-omnipotent +rsaz_1024_sqr_avx2: +rsaz_1024_mul_avx2: +rsaz_1024_norm2red_avx2: +rsaz_1024_red2norm_avx2: +rsaz_1024_scatter5_avx2: +rsaz_1024_gather5_avx2: + .byte 0x0f,0x0b # ud2 + ret +.size rsaz_1024_sqr_avx2,.-rsaz_1024_sqr_avx2 +___ +}}} + +close STDOUT; diff --git a/external/boringssl/crypto/bn/asm/rsaz-x86_64.pl b/external/boringssl/crypto/bn/asm/rsaz-x86_64.pl new file mode 100755 index 0000000000..c38bde95a3 --- /dev/null +++ b/external/boringssl/crypto/bn/asm/rsaz-x86_64.pl @@ -0,0 +1,2338 @@ +#!/usr/bin/env perl + +############################################################################## +# # +# Copyright (c) 2012, Intel Corporation # +# # +# All rights reserved. # +# # +# Redistribution and use in source and binary forms, with or without # +# modification, are permitted provided that the following conditions are # +# met: # +# # +# * Redistributions of source code must retain the above copyright # +# notice, this list of conditions and the following disclaimer. # +# # +# * Redistributions in binary form must reproduce the above copyright # +# notice, this list of conditions and the following disclaimer in the # +# documentation and/or other materials provided with the # +# distribution. # +# # +# * Neither the name of the Intel Corporation nor the names of its # +# contributors may be used to endorse or promote products derived from # +# this software without specific prior written permission. # +# # +# # +# THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION ""AS IS"" AND ANY # +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR # +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, # +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, # +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR # +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF # +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING # +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # +# # +############################################################################## +# Developers and authors: # +# Shay Gueron (1, 2), and Vlad Krasnov (1) # +# (1) Intel Architecture Group, Microprocessor and Chipset Development, # +# Israel Development Center, Haifa, Israel # +# (2) University of Haifa # +############################################################################## +# Reference: # +# [1] S. Gueron, "Efficient Software Implementations of Modular # +# Exponentiation", http://eprint.iacr.org/2011/239 # +# [2] S. Gueron, V. Krasnov. "Speeding up Big-Numbers Squaring". # +# IEEE Proceedings of 9th International Conference on Information # +# Technology: New Generations (ITNG 2012), 821-823 (2012). # +# [3] S. Gueron, Efficient Software Implementations of Modular Exponentiation# +# Journal of Cryptographic Engineering 2:31-43 (2012). # +# [4] S. Gueron, V. Krasnov: "[PATCH] Efficient and side channel analysis # +# resistant 512-bit and 1024-bit modular exponentiation for optimizing # +# RSA1024 and RSA2048 on x86_64 platforms", # +# http://rt.openssl.org/Ticket/Display.html?id=2582&user=guest&pass=guest# +############################################################################## + +# While original submission covers 512- and 1024-bit exponentiation, +# this module is limited to 512-bit version only (and as such +# accelerates RSA1024 sign). This is because improvement for longer +# keys is not high enough to justify the effort, highest measured +# was ~5% on Westmere. [This is relative to OpenSSL 1.0.2, upcoming +# for the moment of this writing!] Nor does this module implement +# "monolithic" complete exponentiation jumbo-subroutine, but adheres +# to more modular mixture of C and assembly. And it's optimized even +# for processors other than Intel Core family (see table below for +# improvement coefficients). +# +# +# RSA1024 sign/sec this/original |this/rsax(*) this/fips(*) +# ----------------+--------------------------- +# Opteron +13% |+5% +20% +# Bulldozer -0% |-1% +10% +# P4 +11% |+7% +8% +# Westmere +5% |+14% +17% +# Sandy Bridge +2% |+12% +29% +# Ivy Bridge +1% |+11% +35% +# Haswell(**) -0% |+12% +39% +# Atom +13% |+11% +4% +# VIA Nano +70% |+9% +25% +# +# (*) rsax engine and fips numbers are presented for reference +# purposes; +# (**) MULX was attempted, but found to give only marginal improvement; + +$flavour = shift; +$output = shift; +if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } + +$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or +die "can't locate x86_64-xlate.pl"; + +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; + +# In upstream, this is controlled by shelling out to the compiler to check +# versions, but BoringSSL is intended to be used with pre-generated perlasm +# output, so this isn't useful anyway. +# +# TODO(davidben): Enable this after testing. $addx goes up to 1. +$addx = 0; + +($out, $inp, $mod) = ("%rdi", "%rsi", "%rbp"); # common internal API +{ +my ($out,$inp,$mod,$n0,$times) = ("%rdi","%rsi","%rdx","%rcx","%r8d"); + +$code.=<<___; +.text + +.extern OPENSSL_ia32cap_P + +.globl rsaz_512_sqr +.type rsaz_512_sqr,\@function,5 +.align 32 +rsaz_512_sqr: # 25-29% faster than rsaz_512_mul + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + + subq \$128+24, %rsp +.Lsqr_body: + movq $mod, %rbp # common argument + movq ($inp), %rdx + movq 8($inp), %rax + movq $n0, 128(%rsp) +___ +$code.=<<___ if ($addx); + movl \$0x80100,%r11d + andl OPENSSL_ia32cap_P+8(%rip),%r11d + cmpl \$0x80100,%r11d # check for MULX and ADO/CX + je .Loop_sqrx +___ +$code.=<<___; + jmp .Loop_sqr + +.align 32 +.Loop_sqr: + movl $times,128+8(%rsp) +#first iteration + movq %rdx, %rbx + mulq %rdx + movq %rax, %r8 + movq 16($inp), %rax + movq %rdx, %r9 + + mulq %rbx + addq %rax, %r9 + movq 24($inp), %rax + movq %rdx, %r10 + adcq \$0, %r10 + + mulq %rbx + addq %rax, %r10 + movq 32($inp), %rax + movq %rdx, %r11 + adcq \$0, %r11 + + mulq %rbx + addq %rax, %r11 + movq 40($inp), %rax + movq %rdx, %r12 + adcq \$0, %r12 + + mulq %rbx + addq %rax, %r12 + movq 48($inp), %rax + movq %rdx, %r13 + adcq \$0, %r13 + + mulq %rbx + addq %rax, %r13 + movq 56($inp), %rax + movq %rdx, %r14 + adcq \$0, %r14 + + mulq %rbx + addq %rax, %r14 + movq %rbx, %rax + movq %rdx, %r15 + adcq \$0, %r15 + + addq %r8, %r8 #shlq \$1, %r8 + movq %r9, %rcx + adcq %r9, %r9 #shld \$1, %r8, %r9 + + mulq %rax + movq %rax, (%rsp) + addq %rdx, %r8 + adcq \$0, %r9 + + movq %r8, 8(%rsp) + shrq \$63, %rcx + +#second iteration + movq 8($inp), %r8 + movq 16($inp), %rax + mulq %r8 + addq %rax, %r10 + movq 24($inp), %rax + movq %rdx, %rbx + adcq \$0, %rbx + + mulq %r8 + addq %rax, %r11 + movq 32($inp), %rax + adcq \$0, %rdx + addq %rbx, %r11 + movq %rdx, %rbx + adcq \$0, %rbx + + mulq %r8 + addq %rax, %r12 + movq 40($inp), %rax + adcq \$0, %rdx + addq %rbx, %r12 + movq %rdx, %rbx + adcq \$0, %rbx + + mulq %r8 + addq %rax, %r13 + movq 48($inp), %rax + adcq \$0, %rdx + addq %rbx, %r13 + movq %rdx, %rbx + adcq \$0, %rbx + + mulq %r8 + addq %rax, %r14 + movq 56($inp), %rax + adcq \$0, %rdx + addq %rbx, %r14 + movq %rdx, %rbx + adcq \$0, %rbx + + mulq %r8 + addq %rax, %r15 + movq %r8, %rax + adcq \$0, %rdx + addq %rbx, %r15 + movq %rdx, %r8 + movq %r10, %rdx + adcq \$0, %r8 + + add %rdx, %rdx + lea (%rcx,%r10,2), %r10 #shld \$1, %rcx, %r10 + movq %r11, %rbx + adcq %r11, %r11 #shld \$1, %r10, %r11 + + mulq %rax + addq %rax, %r9 + adcq %rdx, %r10 + adcq \$0, %r11 + + movq %r9, 16(%rsp) + movq %r10, 24(%rsp) + shrq \$63, %rbx + +#third iteration + movq 16($inp), %r9 + movq 24($inp), %rax + mulq %r9 + addq %rax, %r12 + movq 32($inp), %rax + movq %rdx, %rcx + adcq \$0, %rcx + + mulq %r9 + addq %rax, %r13 + movq 40($inp), %rax + adcq \$0, %rdx + addq %rcx, %r13 + movq %rdx, %rcx + adcq \$0, %rcx + + mulq %r9 + addq %rax, %r14 + movq 48($inp), %rax + adcq \$0, %rdx + addq %rcx, %r14 + movq %rdx, %rcx + adcq \$0, %rcx + + mulq %r9 + movq %r12, %r10 + lea (%rbx,%r12,2), %r12 #shld \$1, %rbx, %r12 + addq %rax, %r15 + movq 56($inp), %rax + adcq \$0, %rdx + addq %rcx, %r15 + movq %rdx, %rcx + adcq \$0, %rcx + + mulq %r9 + shrq \$63, %r10 + addq %rax, %r8 + movq %r9, %rax + adcq \$0, %rdx + addq %rcx, %r8 + movq %rdx, %r9 + adcq \$0, %r9 + + movq %r13, %rcx + leaq (%r10,%r13,2), %r13 #shld \$1, %r12, %r13 + + mulq %rax + addq %rax, %r11 + adcq %rdx, %r12 + adcq \$0, %r13 + + movq %r11, 32(%rsp) + movq %r12, 40(%rsp) + shrq \$63, %rcx + +#fourth iteration + movq 24($inp), %r10 + movq 32($inp), %rax + mulq %r10 + addq %rax, %r14 + movq 40($inp), %rax + movq %rdx, %rbx + adcq \$0, %rbx + + mulq %r10 + addq %rax, %r15 + movq 48($inp), %rax + adcq \$0, %rdx + addq %rbx, %r15 + movq %rdx, %rbx + adcq \$0, %rbx + + mulq %r10 + movq %r14, %r12 + leaq (%rcx,%r14,2), %r14 #shld \$1, %rcx, %r14 + addq %rax, %r8 + movq 56($inp), %rax + adcq \$0, %rdx + addq %rbx, %r8 + movq %rdx, %rbx + adcq \$0, %rbx + + mulq %r10 + shrq \$63, %r12 + addq %rax, %r9 + movq %r10, %rax + adcq \$0, %rdx + addq %rbx, %r9 + movq %rdx, %r10 + adcq \$0, %r10 + + movq %r15, %rbx + leaq (%r12,%r15,2),%r15 #shld \$1, %r14, %r15 + + mulq %rax + addq %rax, %r13 + adcq %rdx, %r14 + adcq \$0, %r15 + + movq %r13, 48(%rsp) + movq %r14, 56(%rsp) + shrq \$63, %rbx + +#fifth iteration + movq 32($inp), %r11 + movq 40($inp), %rax + mulq %r11 + addq %rax, %r8 + movq 48($inp), %rax + movq %rdx, %rcx + adcq \$0, %rcx + + mulq %r11 + addq %rax, %r9 + movq 56($inp), %rax + adcq \$0, %rdx + movq %r8, %r12 + leaq (%rbx,%r8,2), %r8 #shld \$1, %rbx, %r8 + addq %rcx, %r9 + movq %rdx, %rcx + adcq \$0, %rcx + + mulq %r11 + shrq \$63, %r12 + addq %rax, %r10 + movq %r11, %rax + adcq \$0, %rdx + addq %rcx, %r10 + movq %rdx, %r11 + adcq \$0, %r11 + + movq %r9, %rcx + leaq (%r12,%r9,2), %r9 #shld \$1, %r8, %r9 + + mulq %rax + addq %rax, %r15 + adcq %rdx, %r8 + adcq \$0, %r9 + + movq %r15, 64(%rsp) + movq %r8, 72(%rsp) + shrq \$63, %rcx + +#sixth iteration + movq 40($inp), %r12 + movq 48($inp), %rax + mulq %r12 + addq %rax, %r10 + movq 56($inp), %rax + movq %rdx, %rbx + adcq \$0, %rbx + + mulq %r12 + addq %rax, %r11 + movq %r12, %rax + movq %r10, %r15 + leaq (%rcx,%r10,2), %r10 #shld \$1, %rcx, %r10 + adcq \$0, %rdx + shrq \$63, %r15 + addq %rbx, %r11 + movq %rdx, %r12 + adcq \$0, %r12 + + movq %r11, %rbx + leaq (%r15,%r11,2), %r11 #shld \$1, %r10, %r11 + + mulq %rax + addq %rax, %r9 + adcq %rdx, %r10 + adcq \$0, %r11 + + movq %r9, 80(%rsp) + movq %r10, 88(%rsp) + +#seventh iteration + movq 48($inp), %r13 + movq 56($inp), %rax + mulq %r13 + addq %rax, %r12 + movq %r13, %rax + movq %rdx, %r13 + adcq \$0, %r13 + + xorq %r14, %r14 + shlq \$1, %rbx + adcq %r12, %r12 #shld \$1, %rbx, %r12 + adcq %r13, %r13 #shld \$1, %r12, %r13 + adcq %r14, %r14 #shld \$1, %r13, %r14 + + mulq %rax + addq %rax, %r11 + adcq %rdx, %r12 + adcq \$0, %r13 + + movq %r11, 96(%rsp) + movq %r12, 104(%rsp) + +#eighth iteration + movq 56($inp), %rax + mulq %rax + addq %rax, %r13 + adcq \$0, %rdx + + addq %rdx, %r14 + + movq %r13, 112(%rsp) + movq %r14, 120(%rsp) + + movq (%rsp), %r8 + movq 8(%rsp), %r9 + movq 16(%rsp), %r10 + movq 24(%rsp), %r11 + movq 32(%rsp), %r12 + movq 40(%rsp), %r13 + movq 48(%rsp), %r14 + movq 56(%rsp), %r15 + + call __rsaz_512_reduce + + addq 64(%rsp), %r8 + adcq 72(%rsp), %r9 + adcq 80(%rsp), %r10 + adcq 88(%rsp), %r11 + adcq 96(%rsp), %r12 + adcq 104(%rsp), %r13 + adcq 112(%rsp), %r14 + adcq 120(%rsp), %r15 + sbbq %rcx, %rcx + + call __rsaz_512_subtract + + movq %r8, %rdx + movq %r9, %rax + movl 128+8(%rsp), $times + movq $out, $inp + + decl $times + jnz .Loop_sqr +___ +if ($addx) { +$code.=<<___; + jmp .Lsqr_tail + +.align 32 +.Loop_sqrx: + movl $times,128+8(%rsp) + movq $out, %xmm0 # off-load + movq %rbp, %xmm1 # off-load +#first iteration + mulx %rax, %r8, %r9 + + mulx 16($inp), %rcx, %r10 + xor %rbp, %rbp # cf=0, of=0 + + mulx 24($inp), %rax, %r11 + adcx %rcx, %r9 + + mulx 32($inp), %rcx, %r12 + adcx %rax, %r10 + + mulx 40($inp), %rax, %r13 + adcx %rcx, %r11 + + .byte 0xc4,0x62,0xf3,0xf6,0xb6,0x30,0x00,0x00,0x00 # mulx 48($inp), %rcx, %r14 + adcx %rax, %r12 + adcx %rcx, %r13 + + .byte 0xc4,0x62,0xfb,0xf6,0xbe,0x38,0x00,0x00,0x00 # mulx 56($inp), %rax, %r15 + adcx %rax, %r14 + adcx %rbp, %r15 # %rbp is 0 + + mov %r9, %rcx + shld \$1, %r8, %r9 + shl \$1, %r8 + + xor %ebp, %ebp + mulx %rdx, %rax, %rdx + adcx %rdx, %r8 + mov 8($inp), %rdx + adcx %rbp, %r9 + + mov %rax, (%rsp) + mov %r8, 8(%rsp) + +#second iteration + mulx 16($inp), %rax, %rbx + adox %rax, %r10 + adcx %rbx, %r11 + + .byte 0xc4,0x62,0xc3,0xf6,0x86,0x18,0x00,0x00,0x00 # mulx 24($inp), $out, %r8 + adox $out, %r11 + adcx %r8, %r12 + + mulx 32($inp), %rax, %rbx + adox %rax, %r12 + adcx %rbx, %r13 + + mulx 40($inp), $out, %r8 + adox $out, %r13 + adcx %r8, %r14 + + .byte 0xc4,0xe2,0xfb,0xf6,0x9e,0x30,0x00,0x00,0x00 # mulx 48($inp), %rax, %rbx + adox %rax, %r14 + adcx %rbx, %r15 + + .byte 0xc4,0x62,0xc3,0xf6,0x86,0x38,0x00,0x00,0x00 # mulx 56($inp), $out, %r8 + adox $out, %r15 + adcx %rbp, %r8 + adox %rbp, %r8 + + mov %r11, %rbx + shld \$1, %r10, %r11 + shld \$1, %rcx, %r10 + + xor %ebp,%ebp + mulx %rdx, %rax, %rcx + mov 16($inp), %rdx + adcx %rax, %r9 + adcx %rcx, %r10 + adcx %rbp, %r11 + + mov %r9, 16(%rsp) + .byte 0x4c,0x89,0x94,0x24,0x18,0x00,0x00,0x00 # mov %r10, 24(%rsp) + +#third iteration + .byte 0xc4,0x62,0xc3,0xf6,0x8e,0x18,0x00,0x00,0x00 # mulx 24($inp), $out, %r9 + adox $out, %r12 + adcx %r9, %r13 + + mulx 32($inp), %rax, %rcx + adox %rax, %r13 + adcx %rcx, %r14 + + mulx 40($inp), $out, %r9 + adox $out, %r14 + adcx %r9, %r15 + + .byte 0xc4,0xe2,0xfb,0xf6,0x8e,0x30,0x00,0x00,0x00 # mulx 48($inp), %rax, %rcx + adox %rax, %r15 + adcx %rcx, %r8 + + .byte 0xc4,0x62,0xc3,0xf6,0x8e,0x38,0x00,0x00,0x00 # mulx 56($inp), $out, %r9 + adox $out, %r8 + adcx %rbp, %r9 + adox %rbp, %r9 + + mov %r13, %rcx + shld \$1, %r12, %r13 + shld \$1, %rbx, %r12 + + xor %ebp, %ebp + mulx %rdx, %rax, %rdx + adcx %rax, %r11 + adcx %rdx, %r12 + mov 24($inp), %rdx + adcx %rbp, %r13 + + mov %r11, 32(%rsp) + .byte 0x4c,0x89,0xa4,0x24,0x28,0x00,0x00,0x00 # mov %r12, 40(%rsp) + +#fourth iteration + .byte 0xc4,0xe2,0xfb,0xf6,0x9e,0x20,0x00,0x00,0x00 # mulx 32($inp), %rax, %rbx + adox %rax, %r14 + adcx %rbx, %r15 + + mulx 40($inp), $out, %r10 + adox $out, %r15 + adcx %r10, %r8 + + mulx 48($inp), %rax, %rbx + adox %rax, %r8 + adcx %rbx, %r9 + + mulx 56($inp), $out, %r10 + adox $out, %r9 + adcx %rbp, %r10 + adox %rbp, %r10 + + .byte 0x66 + mov %r15, %rbx + shld \$1, %r14, %r15 + shld \$1, %rcx, %r14 + + xor %ebp, %ebp + mulx %rdx, %rax, %rdx + adcx %rax, %r13 + adcx %rdx, %r14 + mov 32($inp), %rdx + adcx %rbp, %r15 + + mov %r13, 48(%rsp) + mov %r14, 56(%rsp) + +#fifth iteration + .byte 0xc4,0x62,0xc3,0xf6,0x9e,0x28,0x00,0x00,0x00 # mulx 40($inp), $out, %r11 + adox $out, %r8 + adcx %r11, %r9 + + mulx 48($inp), %rax, %rcx + adox %rax, %r9 + adcx %rcx, %r10 + + mulx 56($inp), $out, %r11 + adox $out, %r10 + adcx %rbp, %r11 + adox %rbp, %r11 + + mov %r9, %rcx + shld \$1, %r8, %r9 + shld \$1, %rbx, %r8 + + xor %ebp, %ebp + mulx %rdx, %rax, %rdx + adcx %rax, %r15 + adcx %rdx, %r8 + mov 40($inp), %rdx + adcx %rbp, %r9 + + mov %r15, 64(%rsp) + mov %r8, 72(%rsp) + +#sixth iteration + .byte 0xc4,0xe2,0xfb,0xf6,0x9e,0x30,0x00,0x00,0x00 # mulx 48($inp), %rax, %rbx + adox %rax, %r10 + adcx %rbx, %r11 + + .byte 0xc4,0x62,0xc3,0xf6,0xa6,0x38,0x00,0x00,0x00 # mulx 56($inp), $out, %r12 + adox $out, %r11 + adcx %rbp, %r12 + adox %rbp, %r12 + + mov %r11, %rbx + shld \$1, %r10, %r11 + shld \$1, %rcx, %r10 + + xor %ebp, %ebp + mulx %rdx, %rax, %rdx + adcx %rax, %r9 + adcx %rdx, %r10 + mov 48($inp), %rdx + adcx %rbp, %r11 + + mov %r9, 80(%rsp) + mov %r10, 88(%rsp) + +#seventh iteration + .byte 0xc4,0x62,0xfb,0xf6,0xae,0x38,0x00,0x00,0x00 # mulx 56($inp), %rax, %r13 + adox %rax, %r12 + adox %rbp, %r13 + + xor %r14, %r14 + shld \$1, %r13, %r14 + shld \$1, %r12, %r13 + shld \$1, %rbx, %r12 + + xor %ebp, %ebp + mulx %rdx, %rax, %rdx + adcx %rax, %r11 + adcx %rdx, %r12 + mov 56($inp), %rdx + adcx %rbp, %r13 + + .byte 0x4c,0x89,0x9c,0x24,0x60,0x00,0x00,0x00 # mov %r11, 96(%rsp) + .byte 0x4c,0x89,0xa4,0x24,0x68,0x00,0x00,0x00 # mov %r12, 104(%rsp) + +#eighth iteration + mulx %rdx, %rax, %rdx + adox %rax, %r13 + adox %rbp, %rdx + + .byte 0x66 + add %rdx, %r14 + + movq %r13, 112(%rsp) + movq %r14, 120(%rsp) + movq %xmm0, $out + movq %xmm1, %rbp + + movq 128(%rsp), %rdx # pull $n0 + movq (%rsp), %r8 + movq 8(%rsp), %r9 + movq 16(%rsp), %r10 + movq 24(%rsp), %r11 + movq 32(%rsp), %r12 + movq 40(%rsp), %r13 + movq 48(%rsp), %r14 + movq 56(%rsp), %r15 + + call __rsaz_512_reducex + + addq 64(%rsp), %r8 + adcq 72(%rsp), %r9 + adcq 80(%rsp), %r10 + adcq 88(%rsp), %r11 + adcq 96(%rsp), %r12 + adcq 104(%rsp), %r13 + adcq 112(%rsp), %r14 + adcq 120(%rsp), %r15 + sbbq %rcx, %rcx + + call __rsaz_512_subtract + + movq %r8, %rdx + movq %r9, %rax + movl 128+8(%rsp), $times + movq $out, $inp + + decl $times + jnz .Loop_sqrx + +.Lsqr_tail: +___ +} +$code.=<<___; + + leaq 128+24+48(%rsp), %rax + movq -48(%rax), %r15 + movq -40(%rax), %r14 + movq -32(%rax), %r13 + movq -24(%rax), %r12 + movq -16(%rax), %rbp + movq -8(%rax), %rbx + leaq (%rax), %rsp +.Lsqr_epilogue: + ret +.size rsaz_512_sqr,.-rsaz_512_sqr +___ +} +{ +my ($out,$ap,$bp,$mod,$n0) = ("%rdi","%rsi","%rdx","%rcx","%r8"); +$code.=<<___; +.globl rsaz_512_mul +.type rsaz_512_mul,\@function,5 +.align 32 +rsaz_512_mul: + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + + subq \$128+24, %rsp +.Lmul_body: + movq $out, %xmm0 # off-load arguments + movq $mod, %xmm1 + movq $n0, 128(%rsp) +___ +$code.=<<___ if ($addx); + movl \$0x80100,%r11d + andl OPENSSL_ia32cap_P+8(%rip),%r11d + cmpl \$0x80100,%r11d # check for MULX and ADO/CX + je .Lmulx +___ +$code.=<<___; + movq ($bp), %rbx # pass b[0] + movq $bp, %rbp # pass argument + call __rsaz_512_mul + + movq %xmm0, $out + movq %xmm1, %rbp + + movq (%rsp), %r8 + movq 8(%rsp), %r9 + movq 16(%rsp), %r10 + movq 24(%rsp), %r11 + movq 32(%rsp), %r12 + movq 40(%rsp), %r13 + movq 48(%rsp), %r14 + movq 56(%rsp), %r15 + + call __rsaz_512_reduce +___ +$code.=<<___ if ($addx); + jmp .Lmul_tail + +.align 32 +.Lmulx: + movq $bp, %rbp # pass argument + movq ($bp), %rdx # pass b[0] + call __rsaz_512_mulx + + movq %xmm0, $out + movq %xmm1, %rbp + + movq 128(%rsp), %rdx # pull $n0 + movq (%rsp), %r8 + movq 8(%rsp), %r9 + movq 16(%rsp), %r10 + movq 24(%rsp), %r11 + movq 32(%rsp), %r12 + movq 40(%rsp), %r13 + movq 48(%rsp), %r14 + movq 56(%rsp), %r15 + + call __rsaz_512_reducex +.Lmul_tail: +___ +$code.=<<___; + addq 64(%rsp), %r8 + adcq 72(%rsp), %r9 + adcq 80(%rsp), %r10 + adcq 88(%rsp), %r11 + adcq 96(%rsp), %r12 + adcq 104(%rsp), %r13 + adcq 112(%rsp), %r14 + adcq 120(%rsp), %r15 + sbbq %rcx, %rcx + + call __rsaz_512_subtract + + leaq 128+24+48(%rsp), %rax + movq -48(%rax), %r15 + movq -40(%rax), %r14 + movq -32(%rax), %r13 + movq -24(%rax), %r12 + movq -16(%rax), %rbp + movq -8(%rax), %rbx + leaq (%rax), %rsp +.Lmul_epilogue: + ret +.size rsaz_512_mul,.-rsaz_512_mul +___ +} +{ +my ($out,$ap,$bp,$mod,$n0,$pwr) = ("%rdi","%rsi","%rdx","%rcx","%r8","%r9d"); +$code.=<<___; +.globl rsaz_512_mul_gather4 +.type rsaz_512_mul_gather4,\@function,6 +.align 32 +rsaz_512_mul_gather4: + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + + subq \$`128+24+($win64?0xb0:0)`, %rsp +___ +$code.=<<___ if ($win64); + movaps %xmm6,0xa0(%rsp) + movaps %xmm7,0xb0(%rsp) + movaps %xmm8,0xc0(%rsp) + movaps %xmm9,0xd0(%rsp) + movaps %xmm10,0xe0(%rsp) + movaps %xmm11,0xf0(%rsp) + movaps %xmm12,0x100(%rsp) + movaps %xmm13,0x110(%rsp) + movaps %xmm14,0x120(%rsp) + movaps %xmm15,0x130(%rsp) +___ +$code.=<<___; +.Lmul_gather4_body: + movd $pwr,%xmm8 + movdqa .Linc+16(%rip),%xmm1 # 00000002000000020000000200000002 + movdqa .Linc(%rip),%xmm0 # 00000001000000010000000000000000 + + pshufd \$0,%xmm8,%xmm8 # broadcast $power + movdqa %xmm1,%xmm7 + movdqa %xmm1,%xmm2 +___ +######################################################################## +# calculate mask by comparing 0..15 to $power +# +for($i=0;$i<4;$i++) { +$code.=<<___; + paddd %xmm`$i`,%xmm`$i+1` + pcmpeqd %xmm8,%xmm`$i` + movdqa %xmm7,%xmm`$i+3` +___ +} +for(;$i<7;$i++) { +$code.=<<___; + paddd %xmm`$i`,%xmm`$i+1` + pcmpeqd %xmm8,%xmm`$i` +___ +} +$code.=<<___; + pcmpeqd %xmm8,%xmm7 + + movdqa 16*0($bp),%xmm8 + movdqa 16*1($bp),%xmm9 + movdqa 16*2($bp),%xmm10 + movdqa 16*3($bp),%xmm11 + pand %xmm0,%xmm8 + movdqa 16*4($bp),%xmm12 + pand %xmm1,%xmm9 + movdqa 16*5($bp),%xmm13 + pand %xmm2,%xmm10 + movdqa 16*6($bp),%xmm14 + pand %xmm3,%xmm11 + movdqa 16*7($bp),%xmm15 + leaq 128($bp), %rbp + pand %xmm4,%xmm12 + pand %xmm5,%xmm13 + pand %xmm6,%xmm14 + pand %xmm7,%xmm15 + por %xmm10,%xmm8 + por %xmm11,%xmm9 + por %xmm12,%xmm8 + por %xmm13,%xmm9 + por %xmm14,%xmm8 + por %xmm15,%xmm9 + + por %xmm9,%xmm8 + pshufd \$0x4e,%xmm8,%xmm9 + por %xmm9,%xmm8 +___ +$code.=<<___ if ($addx); + movl \$0x80100,%r11d + andl OPENSSL_ia32cap_P+8(%rip),%r11d + cmpl \$0x80100,%r11d # check for MULX and ADO/CX + je .Lmulx_gather +___ +$code.=<<___; + movq %xmm8,%rbx + + movq $n0, 128(%rsp) # off-load arguments + movq $out, 128+8(%rsp) + movq $mod, 128+16(%rsp) + + movq ($ap), %rax + movq 8($ap), %rcx + mulq %rbx # 0 iteration + movq %rax, (%rsp) + movq %rcx, %rax + movq %rdx, %r8 + + mulq %rbx + addq %rax, %r8 + movq 16($ap), %rax + movq %rdx, %r9 + adcq \$0, %r9 + + mulq %rbx + addq %rax, %r9 + movq 24($ap), %rax + movq %rdx, %r10 + adcq \$0, %r10 + + mulq %rbx + addq %rax, %r10 + movq 32($ap), %rax + movq %rdx, %r11 + adcq \$0, %r11 + + mulq %rbx + addq %rax, %r11 + movq 40($ap), %rax + movq %rdx, %r12 + adcq \$0, %r12 + + mulq %rbx + addq %rax, %r12 + movq 48($ap), %rax + movq %rdx, %r13 + adcq \$0, %r13 + + mulq %rbx + addq %rax, %r13 + movq 56($ap), %rax + movq %rdx, %r14 + adcq \$0, %r14 + + mulq %rbx + addq %rax, %r14 + movq ($ap), %rax + movq %rdx, %r15 + adcq \$0, %r15 + + leaq 8(%rsp), %rdi + movl \$7, %ecx + jmp .Loop_mul_gather + +.align 32 +.Loop_mul_gather: + movdqa 16*0(%rbp),%xmm8 + movdqa 16*1(%rbp),%xmm9 + movdqa 16*2(%rbp),%xmm10 + movdqa 16*3(%rbp),%xmm11 + pand %xmm0,%xmm8 + movdqa 16*4(%rbp),%xmm12 + pand %xmm1,%xmm9 + movdqa 16*5(%rbp),%xmm13 + pand %xmm2,%xmm10 + movdqa 16*6(%rbp),%xmm14 + pand %xmm3,%xmm11 + movdqa 16*7(%rbp),%xmm15 + leaq 128(%rbp), %rbp + pand %xmm4,%xmm12 + pand %xmm5,%xmm13 + pand %xmm6,%xmm14 + pand %xmm7,%xmm15 + por %xmm10,%xmm8 + por %xmm11,%xmm9 + por %xmm12,%xmm8 + por %xmm13,%xmm9 + por %xmm14,%xmm8 + por %xmm15,%xmm9 + + por %xmm9,%xmm8 + pshufd \$0x4e,%xmm8,%xmm9 + por %xmm9,%xmm8 + movq %xmm8,%rbx + + mulq %rbx + addq %rax, %r8 + movq 8($ap), %rax + movq %r8, (%rdi) + movq %rdx, %r8 + adcq \$0, %r8 + + mulq %rbx + addq %rax, %r9 + movq 16($ap), %rax + adcq \$0, %rdx + addq %r9, %r8 + movq %rdx, %r9 + adcq \$0, %r9 + + mulq %rbx + addq %rax, %r10 + movq 24($ap), %rax + adcq \$0, %rdx + addq %r10, %r9 + movq %rdx, %r10 + adcq \$0, %r10 + + mulq %rbx + addq %rax, %r11 + movq 32($ap), %rax + adcq \$0, %rdx + addq %r11, %r10 + movq %rdx, %r11 + adcq \$0, %r11 + + mulq %rbx + addq %rax, %r12 + movq 40($ap), %rax + adcq \$0, %rdx + addq %r12, %r11 + movq %rdx, %r12 + adcq \$0, %r12 + + mulq %rbx + addq %rax, %r13 + movq 48($ap), %rax + adcq \$0, %rdx + addq %r13, %r12 + movq %rdx, %r13 + adcq \$0, %r13 + + mulq %rbx + addq %rax, %r14 + movq 56($ap), %rax + adcq \$0, %rdx + addq %r14, %r13 + movq %rdx, %r14 + adcq \$0, %r14 + + mulq %rbx + addq %rax, %r15 + movq ($ap), %rax + adcq \$0, %rdx + addq %r15, %r14 + movq %rdx, %r15 + adcq \$0, %r15 + + leaq 8(%rdi), %rdi + + decl %ecx + jnz .Loop_mul_gather + + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq %r12, 32(%rdi) + movq %r13, 40(%rdi) + movq %r14, 48(%rdi) + movq %r15, 56(%rdi) + + movq 128+8(%rsp), $out + movq 128+16(%rsp), %rbp + + movq (%rsp), %r8 + movq 8(%rsp), %r9 + movq 16(%rsp), %r10 + movq 24(%rsp), %r11 + movq 32(%rsp), %r12 + movq 40(%rsp), %r13 + movq 48(%rsp), %r14 + movq 56(%rsp), %r15 + + call __rsaz_512_reduce +___ +$code.=<<___ if ($addx); + jmp .Lmul_gather_tail + +.align 32 +.Lmulx_gather: + movq %xmm8,%rdx + + mov $n0, 128(%rsp) # off-load arguments + mov $out, 128+8(%rsp) + mov $mod, 128+16(%rsp) + + mulx ($ap), %rbx, %r8 # 0 iteration + mov %rbx, (%rsp) + xor %edi, %edi # cf=0, of=0 + + mulx 8($ap), %rax, %r9 + + mulx 16($ap), %rbx, %r10 + adcx %rax, %r8 + + mulx 24($ap), %rax, %r11 + adcx %rbx, %r9 + + mulx 32($ap), %rbx, %r12 + adcx %rax, %r10 + + mulx 40($ap), %rax, %r13 + adcx %rbx, %r11 + + mulx 48($ap), %rbx, %r14 + adcx %rax, %r12 + + mulx 56($ap), %rax, %r15 + adcx %rbx, %r13 + adcx %rax, %r14 + .byte 0x67 + mov %r8, %rbx + adcx %rdi, %r15 # %rdi is 0 + + mov \$-7, %rcx + jmp .Loop_mulx_gather + +.align 32 +.Loop_mulx_gather: + movdqa 16*0(%rbp),%xmm8 + movdqa 16*1(%rbp),%xmm9 + movdqa 16*2(%rbp),%xmm10 + movdqa 16*3(%rbp),%xmm11 + pand %xmm0,%xmm8 + movdqa 16*4(%rbp),%xmm12 + pand %xmm1,%xmm9 + movdqa 16*5(%rbp),%xmm13 + pand %xmm2,%xmm10 + movdqa 16*6(%rbp),%xmm14 + pand %xmm3,%xmm11 + movdqa 16*7(%rbp),%xmm15 + leaq 128(%rbp), %rbp + pand %xmm4,%xmm12 + pand %xmm5,%xmm13 + pand %xmm6,%xmm14 + pand %xmm7,%xmm15 + por %xmm10,%xmm8 + por %xmm11,%xmm9 + por %xmm12,%xmm8 + por %xmm13,%xmm9 + por %xmm14,%xmm8 + por %xmm15,%xmm9 + + por %xmm9,%xmm8 + pshufd \$0x4e,%xmm8,%xmm9 + por %xmm9,%xmm8 + movq %xmm8,%rdx + + .byte 0xc4,0x62,0xfb,0xf6,0x86,0x00,0x00,0x00,0x00 # mulx ($ap), %rax, %r8 + adcx %rax, %rbx + adox %r9, %r8 + + mulx 8($ap), %rax, %r9 + adcx %rax, %r8 + adox %r10, %r9 + + mulx 16($ap), %rax, %r10 + adcx %rax, %r9 + adox %r11, %r10 + + .byte 0xc4,0x62,0xfb,0xf6,0x9e,0x18,0x00,0x00,0x00 # mulx 24($ap), %rax, %r11 + adcx %rax, %r10 + adox %r12, %r11 + + mulx 32($ap), %rax, %r12 + adcx %rax, %r11 + adox %r13, %r12 + + mulx 40($ap), %rax, %r13 + adcx %rax, %r12 + adox %r14, %r13 + + .byte 0xc4,0x62,0xfb,0xf6,0xb6,0x30,0x00,0x00,0x00 # mulx 48($ap), %rax, %r14 + adcx %rax, %r13 + .byte 0x67 + adox %r15, %r14 + + mulx 56($ap), %rax, %r15 + mov %rbx, 64(%rsp,%rcx,8) + adcx %rax, %r14 + adox %rdi, %r15 + mov %r8, %rbx + adcx %rdi, %r15 # cf=0 + + inc %rcx # of=0 + jnz .Loop_mulx_gather + + mov %r8, 64(%rsp) + mov %r9, 64+8(%rsp) + mov %r10, 64+16(%rsp) + mov %r11, 64+24(%rsp) + mov %r12, 64+32(%rsp) + mov %r13, 64+40(%rsp) + mov %r14, 64+48(%rsp) + mov %r15, 64+56(%rsp) + + mov 128(%rsp), %rdx # pull arguments + mov 128+8(%rsp), $out + mov 128+16(%rsp), %rbp + + mov (%rsp), %r8 + mov 8(%rsp), %r9 + mov 16(%rsp), %r10 + mov 24(%rsp), %r11 + mov 32(%rsp), %r12 + mov 40(%rsp), %r13 + mov 48(%rsp), %r14 + mov 56(%rsp), %r15 + + call __rsaz_512_reducex + +.Lmul_gather_tail: +___ +$code.=<<___; + addq 64(%rsp), %r8 + adcq 72(%rsp), %r9 + adcq 80(%rsp), %r10 + adcq 88(%rsp), %r11 + adcq 96(%rsp), %r12 + adcq 104(%rsp), %r13 + adcq 112(%rsp), %r14 + adcq 120(%rsp), %r15 + sbbq %rcx, %rcx + + call __rsaz_512_subtract + + leaq 128+24+48(%rsp), %rax +___ +$code.=<<___ if ($win64); + movaps 0xa0-0xc8(%rax),%xmm6 + movaps 0xb0-0xc8(%rax),%xmm7 + movaps 0xc0-0xc8(%rax),%xmm8 + movaps 0xd0-0xc8(%rax),%xmm9 + movaps 0xe0-0xc8(%rax),%xmm10 + movaps 0xf0-0xc8(%rax),%xmm11 + movaps 0x100-0xc8(%rax),%xmm12 + movaps 0x110-0xc8(%rax),%xmm13 + movaps 0x120-0xc8(%rax),%xmm14 + movaps 0x130-0xc8(%rax),%xmm15 + lea 0xb0(%rax),%rax +___ +$code.=<<___; + movq -48(%rax), %r15 + movq -40(%rax), %r14 + movq -32(%rax), %r13 + movq -24(%rax), %r12 + movq -16(%rax), %rbp + movq -8(%rax), %rbx + leaq (%rax), %rsp +.Lmul_gather4_epilogue: + ret +.size rsaz_512_mul_gather4,.-rsaz_512_mul_gather4 +___ +} +{ +my ($out,$ap,$mod,$n0,$tbl,$pwr) = ("%rdi","%rsi","%rdx","%rcx","%r8","%r9d"); +$code.=<<___; +.globl rsaz_512_mul_scatter4 +.type rsaz_512_mul_scatter4,\@function,6 +.align 32 +rsaz_512_mul_scatter4: + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + + mov $pwr, $pwr + subq \$128+24, %rsp +.Lmul_scatter4_body: + leaq ($tbl,$pwr,8), $tbl + movq $out, %xmm0 # off-load arguments + movq $mod, %xmm1 + movq $tbl, %xmm2 + movq $n0, 128(%rsp) + + movq $out, %rbp +___ +$code.=<<___ if ($addx); + movl \$0x80100,%r11d + andl OPENSSL_ia32cap_P+8(%rip),%r11d + cmpl \$0x80100,%r11d # check for MULX and ADO/CX + je .Lmulx_scatter +___ +$code.=<<___; + movq ($out),%rbx # pass b[0] + call __rsaz_512_mul + + movq %xmm0, $out + movq %xmm1, %rbp + + movq (%rsp), %r8 + movq 8(%rsp), %r9 + movq 16(%rsp), %r10 + movq 24(%rsp), %r11 + movq 32(%rsp), %r12 + movq 40(%rsp), %r13 + movq 48(%rsp), %r14 + movq 56(%rsp), %r15 + + call __rsaz_512_reduce +___ +$code.=<<___ if ($addx); + jmp .Lmul_scatter_tail + +.align 32 +.Lmulx_scatter: + movq ($out), %rdx # pass b[0] + call __rsaz_512_mulx + + movq %xmm0, $out + movq %xmm1, %rbp + + movq 128(%rsp), %rdx # pull $n0 + movq (%rsp), %r8 + movq 8(%rsp), %r9 + movq 16(%rsp), %r10 + movq 24(%rsp), %r11 + movq 32(%rsp), %r12 + movq 40(%rsp), %r13 + movq 48(%rsp), %r14 + movq 56(%rsp), %r15 + + call __rsaz_512_reducex + +.Lmul_scatter_tail: +___ +$code.=<<___; + addq 64(%rsp), %r8 + adcq 72(%rsp), %r9 + adcq 80(%rsp), %r10 + adcq 88(%rsp), %r11 + adcq 96(%rsp), %r12 + adcq 104(%rsp), %r13 + adcq 112(%rsp), %r14 + adcq 120(%rsp), %r15 + movq %xmm2, $inp + sbbq %rcx, %rcx + + call __rsaz_512_subtract + + movq %r8, 128*0($inp) # scatter + movq %r9, 128*1($inp) + movq %r10, 128*2($inp) + movq %r11, 128*3($inp) + movq %r12, 128*4($inp) + movq %r13, 128*5($inp) + movq %r14, 128*6($inp) + movq %r15, 128*7($inp) + + leaq 128+24+48(%rsp), %rax + movq -48(%rax), %r15 + movq -40(%rax), %r14 + movq -32(%rax), %r13 + movq -24(%rax), %r12 + movq -16(%rax), %rbp + movq -8(%rax), %rbx + leaq (%rax), %rsp +.Lmul_scatter4_epilogue: + ret +.size rsaz_512_mul_scatter4,.-rsaz_512_mul_scatter4 +___ +} +{ +my ($out,$inp,$mod,$n0) = ("%rdi","%rsi","%rdx","%rcx"); +$code.=<<___; +.globl rsaz_512_mul_by_one +.type rsaz_512_mul_by_one,\@function,4 +.align 32 +rsaz_512_mul_by_one: + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + + subq \$128+24, %rsp +.Lmul_by_one_body: +___ +$code.=<<___ if ($addx); + movl OPENSSL_ia32cap_P+8(%rip),%eax +___ +$code.=<<___; + movq $mod, %rbp # reassign argument + movq $n0, 128(%rsp) + + movq ($inp), %r8 + pxor %xmm0, %xmm0 + movq 8($inp), %r9 + movq 16($inp), %r10 + movq 24($inp), %r11 + movq 32($inp), %r12 + movq 40($inp), %r13 + movq 48($inp), %r14 + movq 56($inp), %r15 + + movdqa %xmm0, (%rsp) + movdqa %xmm0, 16(%rsp) + movdqa %xmm0, 32(%rsp) + movdqa %xmm0, 48(%rsp) + movdqa %xmm0, 64(%rsp) + movdqa %xmm0, 80(%rsp) + movdqa %xmm0, 96(%rsp) +___ +$code.=<<___ if ($addx); + andl \$0x80100,%eax + cmpl \$0x80100,%eax # check for MULX and ADO/CX + je .Lby_one_callx +___ +$code.=<<___; + call __rsaz_512_reduce +___ +$code.=<<___ if ($addx); + jmp .Lby_one_tail +.align 32 +.Lby_one_callx: + movq 128(%rsp), %rdx # pull $n0 + call __rsaz_512_reducex +.Lby_one_tail: +___ +$code.=<<___; + movq %r8, ($out) + movq %r9, 8($out) + movq %r10, 16($out) + movq %r11, 24($out) + movq %r12, 32($out) + movq %r13, 40($out) + movq %r14, 48($out) + movq %r15, 56($out) + + leaq 128+24+48(%rsp), %rax + movq -48(%rax), %r15 + movq -40(%rax), %r14 + movq -32(%rax), %r13 + movq -24(%rax), %r12 + movq -16(%rax), %rbp + movq -8(%rax), %rbx + leaq (%rax), %rsp +.Lmul_by_one_epilogue: + ret +.size rsaz_512_mul_by_one,.-rsaz_512_mul_by_one +___ +} +{ # __rsaz_512_reduce + # + # input: %r8-%r15, %rbp - mod, 128(%rsp) - n0 + # output: %r8-%r15 + # clobbers: everything except %rbp and %rdi +$code.=<<___; +.type __rsaz_512_reduce,\@abi-omnipotent +.align 32 +__rsaz_512_reduce: + movq %r8, %rbx + imulq 128+8(%rsp), %rbx + movq 0(%rbp), %rax + movl \$8, %ecx + jmp .Lreduction_loop + +.align 32 +.Lreduction_loop: + mulq %rbx + movq 8(%rbp), %rax + negq %r8 + movq %rdx, %r8 + adcq \$0, %r8 + + mulq %rbx + addq %rax, %r9 + movq 16(%rbp), %rax + adcq \$0, %rdx + addq %r9, %r8 + movq %rdx, %r9 + adcq \$0, %r9 + + mulq %rbx + addq %rax, %r10 + movq 24(%rbp), %rax + adcq \$0, %rdx + addq %r10, %r9 + movq %rdx, %r10 + adcq \$0, %r10 + + mulq %rbx + addq %rax, %r11 + movq 32(%rbp), %rax + adcq \$0, %rdx + addq %r11, %r10 + movq 128+8(%rsp), %rsi + #movq %rdx, %r11 + #adcq \$0, %r11 + adcq \$0, %rdx + movq %rdx, %r11 + + mulq %rbx + addq %rax, %r12 + movq 40(%rbp), %rax + adcq \$0, %rdx + imulq %r8, %rsi + addq %r12, %r11 + movq %rdx, %r12 + adcq \$0, %r12 + + mulq %rbx + addq %rax, %r13 + movq 48(%rbp), %rax + adcq \$0, %rdx + addq %r13, %r12 + movq %rdx, %r13 + adcq \$0, %r13 + + mulq %rbx + addq %rax, %r14 + movq 56(%rbp), %rax + adcq \$0, %rdx + addq %r14, %r13 + movq %rdx, %r14 + adcq \$0, %r14 + + mulq %rbx + movq %rsi, %rbx + addq %rax, %r15 + movq 0(%rbp), %rax + adcq \$0, %rdx + addq %r15, %r14 + movq %rdx, %r15 + adcq \$0, %r15 + + decl %ecx + jne .Lreduction_loop + + ret +.size __rsaz_512_reduce,.-__rsaz_512_reduce +___ +} +if ($addx) { + # __rsaz_512_reducex + # + # input: %r8-%r15, %rbp - mod, 128(%rsp) - n0 + # output: %r8-%r15 + # clobbers: everything except %rbp and %rdi +$code.=<<___; +.type __rsaz_512_reducex,\@abi-omnipotent +.align 32 +__rsaz_512_reducex: + #movq 128+8(%rsp), %rdx # pull $n0 + imulq %r8, %rdx + xorq %rsi, %rsi # cf=0,of=0 + movl \$8, %ecx + jmp .Lreduction_loopx + +.align 32 +.Lreduction_loopx: + mov %r8, %rbx + mulx 0(%rbp), %rax, %r8 + adcx %rbx, %rax + adox %r9, %r8 + + mulx 8(%rbp), %rax, %r9 + adcx %rax, %r8 + adox %r10, %r9 + + mulx 16(%rbp), %rbx, %r10 + adcx %rbx, %r9 + adox %r11, %r10 + + mulx 24(%rbp), %rbx, %r11 + adcx %rbx, %r10 + adox %r12, %r11 + + .byte 0xc4,0x62,0xe3,0xf6,0xa5,0x20,0x00,0x00,0x00 # mulx 32(%rbp), %rbx, %r12 + mov %rdx, %rax + mov %r8, %rdx + adcx %rbx, %r11 + adox %r13, %r12 + + mulx 128+8(%rsp), %rbx, %rdx + mov %rax, %rdx + + mulx 40(%rbp), %rax, %r13 + adcx %rax, %r12 + adox %r14, %r13 + + .byte 0xc4,0x62,0xfb,0xf6,0xb5,0x30,0x00,0x00,0x00 # mulx 48(%rbp), %rax, %r14 + adcx %rax, %r13 + adox %r15, %r14 + + mulx 56(%rbp), %rax, %r15 + mov %rbx, %rdx + adcx %rax, %r14 + adox %rsi, %r15 # %rsi is 0 + adcx %rsi, %r15 # cf=0 + + decl %ecx # of=0 + jne .Lreduction_loopx + + ret +.size __rsaz_512_reducex,.-__rsaz_512_reducex +___ +} +{ # __rsaz_512_subtract + # input: %r8-%r15, %rdi - $out, %rbp - $mod, %rcx - mask + # output: + # clobbers: everything but %rdi, %rsi and %rbp +$code.=<<___; +.type __rsaz_512_subtract,\@abi-omnipotent +.align 32 +__rsaz_512_subtract: + movq %r8, ($out) + movq %r9, 8($out) + movq %r10, 16($out) + movq %r11, 24($out) + movq %r12, 32($out) + movq %r13, 40($out) + movq %r14, 48($out) + movq %r15, 56($out) + + movq 0($mod), %r8 + movq 8($mod), %r9 + negq %r8 + notq %r9 + andq %rcx, %r8 + movq 16($mod), %r10 + andq %rcx, %r9 + notq %r10 + movq 24($mod), %r11 + andq %rcx, %r10 + notq %r11 + movq 32($mod), %r12 + andq %rcx, %r11 + notq %r12 + movq 40($mod), %r13 + andq %rcx, %r12 + notq %r13 + movq 48($mod), %r14 + andq %rcx, %r13 + notq %r14 + movq 56($mod), %r15 + andq %rcx, %r14 + notq %r15 + andq %rcx, %r15 + + addq ($out), %r8 + adcq 8($out), %r9 + adcq 16($out), %r10 + adcq 24($out), %r11 + adcq 32($out), %r12 + adcq 40($out), %r13 + adcq 48($out), %r14 + adcq 56($out), %r15 + + movq %r8, ($out) + movq %r9, 8($out) + movq %r10, 16($out) + movq %r11, 24($out) + movq %r12, 32($out) + movq %r13, 40($out) + movq %r14, 48($out) + movq %r15, 56($out) + + ret +.size __rsaz_512_subtract,.-__rsaz_512_subtract +___ +} +{ # __rsaz_512_mul + # + # input: %rsi - ap, %rbp - bp + # ouput: + # clobbers: everything +my ($ap,$bp) = ("%rsi","%rbp"); +$code.=<<___; +.type __rsaz_512_mul,\@abi-omnipotent +.align 32 +__rsaz_512_mul: + leaq 8(%rsp), %rdi + + movq ($ap), %rax + mulq %rbx + movq %rax, (%rdi) + movq 8($ap), %rax + movq %rdx, %r8 + + mulq %rbx + addq %rax, %r8 + movq 16($ap), %rax + movq %rdx, %r9 + adcq \$0, %r9 + + mulq %rbx + addq %rax, %r9 + movq 24($ap), %rax + movq %rdx, %r10 + adcq \$0, %r10 + + mulq %rbx + addq %rax, %r10 + movq 32($ap), %rax + movq %rdx, %r11 + adcq \$0, %r11 + + mulq %rbx + addq %rax, %r11 + movq 40($ap), %rax + movq %rdx, %r12 + adcq \$0, %r12 + + mulq %rbx + addq %rax, %r12 + movq 48($ap), %rax + movq %rdx, %r13 + adcq \$0, %r13 + + mulq %rbx + addq %rax, %r13 + movq 56($ap), %rax + movq %rdx, %r14 + adcq \$0, %r14 + + mulq %rbx + addq %rax, %r14 + movq ($ap), %rax + movq %rdx, %r15 + adcq \$0, %r15 + + leaq 8($bp), $bp + leaq 8(%rdi), %rdi + + movl \$7, %ecx + jmp .Loop_mul + +.align 32 +.Loop_mul: + movq ($bp), %rbx + mulq %rbx + addq %rax, %r8 + movq 8($ap), %rax + movq %r8, (%rdi) + movq %rdx, %r8 + adcq \$0, %r8 + + mulq %rbx + addq %rax, %r9 + movq 16($ap), %rax + adcq \$0, %rdx + addq %r9, %r8 + movq %rdx, %r9 + adcq \$0, %r9 + + mulq %rbx + addq %rax, %r10 + movq 24($ap), %rax + adcq \$0, %rdx + addq %r10, %r9 + movq %rdx, %r10 + adcq \$0, %r10 + + mulq %rbx + addq %rax, %r11 + movq 32($ap), %rax + adcq \$0, %rdx + addq %r11, %r10 + movq %rdx, %r11 + adcq \$0, %r11 + + mulq %rbx + addq %rax, %r12 + movq 40($ap), %rax + adcq \$0, %rdx + addq %r12, %r11 + movq %rdx, %r12 + adcq \$0, %r12 + + mulq %rbx + addq %rax, %r13 + movq 48($ap), %rax + adcq \$0, %rdx + addq %r13, %r12 + movq %rdx, %r13 + adcq \$0, %r13 + + mulq %rbx + addq %rax, %r14 + movq 56($ap), %rax + adcq \$0, %rdx + addq %r14, %r13 + movq %rdx, %r14 + leaq 8($bp), $bp + adcq \$0, %r14 + + mulq %rbx + addq %rax, %r15 + movq ($ap), %rax + adcq \$0, %rdx + addq %r15, %r14 + movq %rdx, %r15 + adcq \$0, %r15 + + leaq 8(%rdi), %rdi + + decl %ecx + jnz .Loop_mul + + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq %r12, 32(%rdi) + movq %r13, 40(%rdi) + movq %r14, 48(%rdi) + movq %r15, 56(%rdi) + + ret +.size __rsaz_512_mul,.-__rsaz_512_mul +___ +} +if ($addx) { + # __rsaz_512_mulx + # + # input: %rsi - ap, %rbp - bp + # ouput: + # clobbers: everything +my ($ap,$bp,$zero) = ("%rsi","%rbp","%rdi"); +$code.=<<___; +.type __rsaz_512_mulx,\@abi-omnipotent +.align 32 +__rsaz_512_mulx: + mulx ($ap), %rbx, %r8 # initial %rdx preloaded by caller + mov \$-6, %rcx + + mulx 8($ap), %rax, %r9 + movq %rbx, 8(%rsp) + + mulx 16($ap), %rbx, %r10 + adc %rax, %r8 + + mulx 24($ap), %rax, %r11 + adc %rbx, %r9 + + mulx 32($ap), %rbx, %r12 + adc %rax, %r10 + + mulx 40($ap), %rax, %r13 + adc %rbx, %r11 + + mulx 48($ap), %rbx, %r14 + adc %rax, %r12 + + mulx 56($ap), %rax, %r15 + mov 8($bp), %rdx + adc %rbx, %r13 + adc %rax, %r14 + adc \$0, %r15 + + xor $zero, $zero # cf=0,of=0 + jmp .Loop_mulx + +.align 32 +.Loop_mulx: + movq %r8, %rbx + mulx ($ap), %rax, %r8 + adcx %rax, %rbx + adox %r9, %r8 + + mulx 8($ap), %rax, %r9 + adcx %rax, %r8 + adox %r10, %r9 + + mulx 16($ap), %rax, %r10 + adcx %rax, %r9 + adox %r11, %r10 + + mulx 24($ap), %rax, %r11 + adcx %rax, %r10 + adox %r12, %r11 + + .byte 0x3e,0xc4,0x62,0xfb,0xf6,0xa6,0x20,0x00,0x00,0x00 # mulx 32($ap), %rax, %r12 + adcx %rax, %r11 + adox %r13, %r12 + + mulx 40($ap), %rax, %r13 + adcx %rax, %r12 + adox %r14, %r13 + + mulx 48($ap), %rax, %r14 + adcx %rax, %r13 + adox %r15, %r14 + + mulx 56($ap), %rax, %r15 + movq 64($bp,%rcx,8), %rdx + movq %rbx, 8+64-8(%rsp,%rcx,8) + adcx %rax, %r14 + adox $zero, %r15 + adcx $zero, %r15 # cf=0 + + inc %rcx # of=0 + jnz .Loop_mulx + + movq %r8, %rbx + mulx ($ap), %rax, %r8 + adcx %rax, %rbx + adox %r9, %r8 + + .byte 0xc4,0x62,0xfb,0xf6,0x8e,0x08,0x00,0x00,0x00 # mulx 8($ap), %rax, %r9 + adcx %rax, %r8 + adox %r10, %r9 + + .byte 0xc4,0x62,0xfb,0xf6,0x96,0x10,0x00,0x00,0x00 # mulx 16($ap), %rax, %r10 + adcx %rax, %r9 + adox %r11, %r10 + + mulx 24($ap), %rax, %r11 + adcx %rax, %r10 + adox %r12, %r11 + + mulx 32($ap), %rax, %r12 + adcx %rax, %r11 + adox %r13, %r12 + + mulx 40($ap), %rax, %r13 + adcx %rax, %r12 + adox %r14, %r13 + + .byte 0xc4,0x62,0xfb,0xf6,0xb6,0x30,0x00,0x00,0x00 # mulx 48($ap), %rax, %r14 + adcx %rax, %r13 + adox %r15, %r14 + + .byte 0xc4,0x62,0xfb,0xf6,0xbe,0x38,0x00,0x00,0x00 # mulx 56($ap), %rax, %r15 + adcx %rax, %r14 + adox $zero, %r15 + adcx $zero, %r15 + + mov %rbx, 8+64-8(%rsp) + mov %r8, 8+64(%rsp) + mov %r9, 8+64+8(%rsp) + mov %r10, 8+64+16(%rsp) + mov %r11, 8+64+24(%rsp) + mov %r12, 8+64+32(%rsp) + mov %r13, 8+64+40(%rsp) + mov %r14, 8+64+48(%rsp) + mov %r15, 8+64+56(%rsp) + + ret +.size __rsaz_512_mulx,.-__rsaz_512_mulx +___ +} +{ +my ($out,$inp,$power)= $win64 ? ("%rcx","%rdx","%r8d") : ("%rdi","%rsi","%edx"); +$code.=<<___; +.globl rsaz_512_scatter4 +.type rsaz_512_scatter4,\@abi-omnipotent +.align 16 +rsaz_512_scatter4: + leaq ($out,$power,8), $out + movl \$8, %r9d + jmp .Loop_scatter +.align 16 +.Loop_scatter: + movq ($inp), %rax + leaq 8($inp), $inp + movq %rax, ($out) + leaq 128($out), $out + decl %r9d + jnz .Loop_scatter + ret +.size rsaz_512_scatter4,.-rsaz_512_scatter4 + +.globl rsaz_512_gather4 +.type rsaz_512_gather4,\@abi-omnipotent +.align 16 +rsaz_512_gather4: +___ +$code.=<<___ if ($win64); +.LSEH_begin_rsaz_512_gather4: + .byte 0x48,0x81,0xec,0xa8,0x00,0x00,0x00 # sub $0xa8,%rsp + .byte 0x0f,0x29,0x34,0x24 # movaps %xmm6,(%rsp) + .byte 0x0f,0x29,0x7c,0x24,0x10 # movaps %xmm7,0x10(%rsp) + .byte 0x44,0x0f,0x29,0x44,0x24,0x20 # movaps %xmm8,0x20(%rsp) + .byte 0x44,0x0f,0x29,0x4c,0x24,0x30 # movaps %xmm9,0x30(%rsp) + .byte 0x44,0x0f,0x29,0x54,0x24,0x40 # movaps %xmm10,0x40(%rsp) + .byte 0x44,0x0f,0x29,0x5c,0x24,0x50 # movaps %xmm11,0x50(%rsp) + .byte 0x44,0x0f,0x29,0x64,0x24,0x60 # movaps %xmm12,0x60(%rsp) + .byte 0x44,0x0f,0x29,0x6c,0x24,0x70 # movaps %xmm13,0x70(%rsp) + .byte 0x44,0x0f,0x29,0xb4,0x24,0x80,0,0,0 # movaps %xmm14,0x80(%rsp) + .byte 0x44,0x0f,0x29,0xbc,0x24,0x90,0,0,0 # movaps %xmm15,0x90(%rsp) +___ +$code.=<<___; + movd $power,%xmm8 + movdqa .Linc+16(%rip),%xmm1 # 00000002000000020000000200000002 + movdqa .Linc(%rip),%xmm0 # 00000001000000010000000000000000 + + pshufd \$0,%xmm8,%xmm8 # broadcast $power + movdqa %xmm1,%xmm7 + movdqa %xmm1,%xmm2 +___ +######################################################################## +# calculate mask by comparing 0..15 to $power +# +for($i=0;$i<4;$i++) { +$code.=<<___; + paddd %xmm`$i`,%xmm`$i+1` + pcmpeqd %xmm8,%xmm`$i` + movdqa %xmm7,%xmm`$i+3` +___ +} +for(;$i<7;$i++) { +$code.=<<___; + paddd %xmm`$i`,%xmm`$i+1` + pcmpeqd %xmm8,%xmm`$i` +___ +} +$code.=<<___; + pcmpeqd %xmm8,%xmm7 + movl \$8, %r9d + jmp .Loop_gather +.align 16 +.Loop_gather: + movdqa 16*0($inp),%xmm8 + movdqa 16*1($inp),%xmm9 + movdqa 16*2($inp),%xmm10 + movdqa 16*3($inp),%xmm11 + pand %xmm0,%xmm8 + movdqa 16*4($inp),%xmm12 + pand %xmm1,%xmm9 + movdqa 16*5($inp),%xmm13 + pand %xmm2,%xmm10 + movdqa 16*6($inp),%xmm14 + pand %xmm3,%xmm11 + movdqa 16*7($inp),%xmm15 + leaq 128($inp), $inp + pand %xmm4,%xmm12 + pand %xmm5,%xmm13 + pand %xmm6,%xmm14 + pand %xmm7,%xmm15 + por %xmm10,%xmm8 + por %xmm11,%xmm9 + por %xmm12,%xmm8 + por %xmm13,%xmm9 + por %xmm14,%xmm8 + por %xmm15,%xmm9 + + por %xmm9,%xmm8 + pshufd \$0x4e,%xmm8,%xmm9 + por %xmm9,%xmm8 + movq %xmm8,($out) + leaq 8($out), $out + decl %r9d + jnz .Loop_gather +___ +$code.=<<___ if ($win64); + movaps 0x00(%rsp),%xmm6 + movaps 0x10(%rsp),%xmm7 + movaps 0x20(%rsp),%xmm8 + movaps 0x30(%rsp),%xmm9 + movaps 0x40(%rsp),%xmm10 + movaps 0x50(%rsp),%xmm11 + movaps 0x60(%rsp),%xmm12 + movaps 0x70(%rsp),%xmm13 + movaps 0x80(%rsp),%xmm14 + movaps 0x90(%rsp),%xmm15 + add \$0xa8,%rsp +___ +$code.=<<___; + ret +.LSEH_end_rsaz_512_gather4: +.size rsaz_512_gather4,.-rsaz_512_gather4 + +.align 64 +.Linc: + .long 0,0, 1,1 + .long 2,2, 2,2 +___ +} + +# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame, +# CONTEXT *context,DISPATCHER_CONTEXT *disp) +if ($win64) { +$rec="%rcx"; +$frame="%rdx"; +$context="%r8"; +$disp="%r9"; + +$code.=<<___; +.extern __imp_RtlVirtualUnwind +.type se_handler,\@abi-omnipotent +.align 16 +se_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + mov 8($disp),%rsi # disp->ImageBase + mov 56($disp),%r11 # disp->HandlerData + + mov 0(%r11),%r10d # HandlerData[0] + lea (%rsi,%r10),%r10 # end of prologue label + cmp %r10,%rbx # context->RipRsp + + mov 4(%r11),%r10d # HandlerData[1] + lea (%rsi,%r10),%r10 # epilogue label + cmp %r10,%rbx # context->Rip>=epilogue label + jae .Lcommon_seh_tail + + lea 128+24+48(%rax),%rax + + lea .Lmul_gather4_epilogue(%rip),%rbx + cmp %r10,%rbx + jne .Lse_not_in_mul_gather4 + + lea 0xb0(%rax),%rax + + lea -48-0xa8(%rax),%rsi + lea 512($context),%rdi + mov \$20,%ecx + .long 0xa548f3fc # cld; rep movsq + +.Lse_not_in_mul_gather4: + mov -8(%rax),%rbx + mov -16(%rax),%rbp + mov -24(%rax),%r12 + mov -32(%rax),%r13 + mov -40(%rax),%r14 + mov -48(%rax),%r15 + mov %rbx,144($context) # restore context->Rbx + mov %rbp,160($context) # restore context->Rbp + mov %r12,216($context) # restore context->R12 + mov %r13,224($context) # restore context->R13 + mov %r14,232($context) # restore context->R14 + mov %r15,240($context) # restore context->R15 + +.Lcommon_seh_tail: + mov 8(%rax),%rdi + mov 16(%rax),%rsi + mov %rax,152($context) # restore context->Rsp + mov %rsi,168($context) # restore context->Rsi + mov %rdi,176($context) # restore context->Rdi + + mov 40($disp),%rdi # disp->ContextRecord + mov $context,%rsi # context + mov \$154,%ecx # sizeof(CONTEXT) + .long 0xa548f3fc # cld; rep movsq + + mov $disp,%rsi + xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER + mov 8(%rsi),%rdx # arg2, disp->ImageBase + mov 0(%rsi),%r8 # arg3, disp->ControlPc + mov 16(%rsi),%r9 # arg4, disp->FunctionEntry + mov 40(%rsi),%r10 # disp->ContextRecord + lea 56(%rsi),%r11 # &disp->HandlerData + lea 24(%rsi),%r12 # &disp->EstablisherFrame + mov %r10,32(%rsp) # arg5 + mov %r11,40(%rsp) # arg6 + mov %r12,48(%rsp) # arg7 + mov %rcx,56(%rsp) # arg8, (NULL) + call *__imp_RtlVirtualUnwind(%rip) + + mov \$1,%eax # ExceptionContinueSearch + add \$64,%rsp + popfq + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + pop %rdi + pop %rsi + ret +.size se_handler,.-se_handler + +.section .pdata +.align 4 + .rva .LSEH_begin_rsaz_512_sqr + .rva .LSEH_end_rsaz_512_sqr + .rva .LSEH_info_rsaz_512_sqr + + .rva .LSEH_begin_rsaz_512_mul + .rva .LSEH_end_rsaz_512_mul + .rva .LSEH_info_rsaz_512_mul + + .rva .LSEH_begin_rsaz_512_mul_gather4 + .rva .LSEH_end_rsaz_512_mul_gather4 + .rva .LSEH_info_rsaz_512_mul_gather4 + + .rva .LSEH_begin_rsaz_512_mul_scatter4 + .rva .LSEH_end_rsaz_512_mul_scatter4 + .rva .LSEH_info_rsaz_512_mul_scatter4 + + .rva .LSEH_begin_rsaz_512_mul_by_one + .rva .LSEH_end_rsaz_512_mul_by_one + .rva .LSEH_info_rsaz_512_mul_by_one + + .rva .LSEH_begin_rsaz_512_gather4 + .rva .LSEH_end_rsaz_512_gather4 + .rva .LSEH_info_rsaz_512_gather4 + +.section .xdata +.align 8 +.LSEH_info_rsaz_512_sqr: + .byte 9,0,0,0 + .rva se_handler + .rva .Lsqr_body,.Lsqr_epilogue # HandlerData[] +.LSEH_info_rsaz_512_mul: + .byte 9,0,0,0 + .rva se_handler + .rva .Lmul_body,.Lmul_epilogue # HandlerData[] +.LSEH_info_rsaz_512_mul_gather4: + .byte 9,0,0,0 + .rva se_handler + .rva .Lmul_gather4_body,.Lmul_gather4_epilogue # HandlerData[] +.LSEH_info_rsaz_512_mul_scatter4: + .byte 9,0,0,0 + .rva se_handler + .rva .Lmul_scatter4_body,.Lmul_scatter4_epilogue # HandlerData[] +.LSEH_info_rsaz_512_mul_by_one: + .byte 9,0,0,0 + .rva se_handler + .rva .Lmul_by_one_body,.Lmul_by_one_epilogue # HandlerData[] +.LSEH_info_rsaz_512_gather4: + .byte 0x01,0x46,0x16,0x00 + .byte 0x46,0xf8,0x09,0x00 # vmovaps 0x90(rsp),xmm15 + .byte 0x3d,0xe8,0x08,0x00 # vmovaps 0x80(rsp),xmm14 + .byte 0x34,0xd8,0x07,0x00 # vmovaps 0x70(rsp),xmm13 + .byte 0x2e,0xc8,0x06,0x00 # vmovaps 0x60(rsp),xmm12 + .byte 0x28,0xb8,0x05,0x00 # vmovaps 0x50(rsp),xmm11 + .byte 0x22,0xa8,0x04,0x00 # vmovaps 0x40(rsp),xmm10 + .byte 0x1c,0x98,0x03,0x00 # vmovaps 0x30(rsp),xmm9 + .byte 0x16,0x88,0x02,0x00 # vmovaps 0x20(rsp),xmm8 + .byte 0x10,0x78,0x01,0x00 # vmovaps 0x10(rsp),xmm7 + .byte 0x0b,0x68,0x00,0x00 # vmovaps 0x00(rsp),xmm6 + .byte 0x07,0x01,0x15,0x00 # sub rsp,0xa8 +___ +} + +$code =~ s/\`([^\`]*)\`/eval $1/gem; +print $code; +close STDOUT; diff --git a/external/boringssl/crypto/bn/asm/x86-mont.pl b/external/boringssl/crypto/bn/asm/x86-mont.pl new file mode 100644 index 0000000000..0626b487f8 --- /dev/null +++ b/external/boringssl/crypto/bn/asm/x86-mont.pl @@ -0,0 +1,592 @@ +#!/usr/bin/env perl + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== + +# October 2005 +# +# This is a "teaser" code, as it can be improved in several ways... +# First of all non-SSE2 path should be implemented (yes, for now it +# performs Montgomery multiplication/convolution only on SSE2-capable +# CPUs such as P4, others fall down to original code). Then inner loop +# can be unrolled and modulo-scheduled to improve ILP and possibly +# moved to 128-bit XMM register bank (though it would require input +# rearrangement and/or increase bus bandwidth utilization). Dedicated +# squaring procedure should give further performance improvement... +# Yet, for being draft, the code improves rsa512 *sign* benchmark by +# 110%(!), rsa1024 one - by 70% and rsa4096 - by 20%:-) + +# December 2006 +# +# Modulo-scheduling SSE2 loops results in further 15-20% improvement. +# Integer-only code [being equipped with dedicated squaring procedure] +# gives ~40% on rsa512 sign benchmark... + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +push(@INC,"${dir}","${dir}../../perlasm"); +require "x86asm.pl"; + +&asm_init($ARGV[0],$0); + +$sse2=0; +for (@ARGV) { $sse2=1 if (/-DOPENSSL_IA32_SSE2/); } + +&external_label("OPENSSL_ia32cap_P") if ($sse2); + +&function_begin("bn_mul_mont"); + +$i="edx"; +$j="ecx"; +$ap="esi"; $tp="esi"; # overlapping variables!!! +$rp="edi"; $bp="edi"; # overlapping variables!!! +$np="ebp"; +$num="ebx"; + +$_num=&DWP(4*0,"esp"); # stack top layout +$_rp=&DWP(4*1,"esp"); +$_ap=&DWP(4*2,"esp"); +$_bp=&DWP(4*3,"esp"); +$_np=&DWP(4*4,"esp"); +$_n0=&DWP(4*5,"esp"); $_n0q=&QWP(4*5,"esp"); +$_sp=&DWP(4*6,"esp"); +$_bpend=&DWP(4*7,"esp"); +$frame=32; # size of above frame rounded up to 16n + + &xor ("eax","eax"); + &mov ("edi",&wparam(5)); # int num + &cmp ("edi",4); + &jl (&label("just_leave")); + + &lea ("esi",&wparam(0)); # put aside pointer to argument block + &lea ("edx",&wparam(1)); # load ap + &mov ("ebp","esp"); # saved stack pointer! + &add ("edi",2); # extra two words on top of tp + &neg ("edi"); + &lea ("esp",&DWP(-$frame,"esp","edi",4)); # alloca($frame+4*(num+2)) + &neg ("edi"); + + # minimize cache contention by arraning 2K window between stack + # pointer and ap argument [np is also position sensitive vector, + # but it's assumed to be near ap, as it's allocated at ~same + # time]. + &mov ("eax","esp"); + &sub ("eax","edx"); + &and ("eax",2047); + &sub ("esp","eax"); # this aligns sp and ap modulo 2048 + + &xor ("edx","esp"); + &and ("edx",2048); + &xor ("edx",2048); + &sub ("esp","edx"); # this splits them apart modulo 4096 + + &and ("esp",-64); # align to cache line + + ################################# load argument block... + &mov ("eax",&DWP(0*4,"esi"));# BN_ULONG *rp + &mov ("ebx",&DWP(1*4,"esi"));# const BN_ULONG *ap + &mov ("ecx",&DWP(2*4,"esi"));# const BN_ULONG *bp + &mov ("edx",&DWP(3*4,"esi"));# const BN_ULONG *np + &mov ("esi",&DWP(4*4,"esi"));# const BN_ULONG *n0 + #&mov ("edi",&DWP(5*4,"esi"));# int num + + &mov ("esi",&DWP(0,"esi")); # pull n0[0] + &mov ($_rp,"eax"); # ... save a copy of argument block + &mov ($_ap,"ebx"); + &mov ($_bp,"ecx"); + &mov ($_np,"edx"); + &mov ($_n0,"esi"); + &lea ($num,&DWP(-3,"edi")); # num=num-1 to assist modulo-scheduling + #&mov ($_num,$num); # redundant as $num is not reused + &mov ($_sp,"ebp"); # saved stack pointer! + +if($sse2) { +$acc0="mm0"; # mmx register bank layout +$acc1="mm1"; +$car0="mm2"; +$car1="mm3"; +$mul0="mm4"; +$mul1="mm5"; +$temp="mm6"; +$mask="mm7"; + + &picmeup("eax","OPENSSL_ia32cap_P"); + &bt (&DWP(0,"eax"),26); + &jnc (&label("non_sse2")); + + &mov ("eax",-1); + &movd ($mask,"eax"); # mask 32 lower bits + + &mov ($ap,$_ap); # load input pointers + &mov ($bp,$_bp); + &mov ($np,$_np); + + &xor ($i,$i); # i=0 + &xor ($j,$j); # j=0 + + &movd ($mul0,&DWP(0,$bp)); # bp[0] + &movd ($mul1,&DWP(0,$ap)); # ap[0] + &movd ($car1,&DWP(0,$np)); # np[0] + + &pmuludq($mul1,$mul0); # ap[0]*bp[0] + &movq ($car0,$mul1); + &movq ($acc0,$mul1); # I wish movd worked for + &pand ($acc0,$mask); # inter-register transfers + + &pmuludq($mul1,$_n0q); # *=n0 + + &pmuludq($car1,$mul1); # "t[0]"*np[0]*n0 + &paddq ($car1,$acc0); + + &movd ($acc1,&DWP(4,$np)); # np[1] + &movd ($acc0,&DWP(4,$ap)); # ap[1] + + &psrlq ($car0,32); + &psrlq ($car1,32); + + &inc ($j); # j++ +&set_label("1st",16); + &pmuludq($acc0,$mul0); # ap[j]*bp[0] + &pmuludq($acc1,$mul1); # np[j]*m1 + &paddq ($car0,$acc0); # +=c0 + &paddq ($car1,$acc1); # +=c1 + + &movq ($acc0,$car0); + &pand ($acc0,$mask); + &movd ($acc1,&DWP(4,$np,$j,4)); # np[j+1] + &paddq ($car1,$acc0); # +=ap[j]*bp[0]; + &movd ($acc0,&DWP(4,$ap,$j,4)); # ap[j+1] + &psrlq ($car0,32); + &movd (&DWP($frame-4,"esp",$j,4),$car1); # tp[j-1]= + &psrlq ($car1,32); + + &lea ($j,&DWP(1,$j)); + &cmp ($j,$num); + &jl (&label("1st")); + + &pmuludq($acc0,$mul0); # ap[num-1]*bp[0] + &pmuludq($acc1,$mul1); # np[num-1]*m1 + &paddq ($car0,$acc0); # +=c0 + &paddq ($car1,$acc1); # +=c1 + + &movq ($acc0,$car0); + &pand ($acc0,$mask); + &paddq ($car1,$acc0); # +=ap[num-1]*bp[0]; + &movd (&DWP($frame-4,"esp",$j,4),$car1); # tp[num-2]= + + &psrlq ($car0,32); + &psrlq ($car1,32); + + &paddq ($car1,$car0); + &movq (&QWP($frame,"esp",$num,4),$car1); # tp[num].tp[num-1] + + &inc ($i); # i++ +&set_label("outer"); + &xor ($j,$j); # j=0 + + &movd ($mul0,&DWP(0,$bp,$i,4)); # bp[i] + &movd ($mul1,&DWP(0,$ap)); # ap[0] + &movd ($temp,&DWP($frame,"esp")); # tp[0] + &movd ($car1,&DWP(0,$np)); # np[0] + &pmuludq($mul1,$mul0); # ap[0]*bp[i] + + &paddq ($mul1,$temp); # +=tp[0] + &movq ($acc0,$mul1); + &movq ($car0,$mul1); + &pand ($acc0,$mask); + + &pmuludq($mul1,$_n0q); # *=n0 + + &pmuludq($car1,$mul1); + &paddq ($car1,$acc0); + + &movd ($temp,&DWP($frame+4,"esp")); # tp[1] + &movd ($acc1,&DWP(4,$np)); # np[1] + &movd ($acc0,&DWP(4,$ap)); # ap[1] + + &psrlq ($car0,32); + &psrlq ($car1,32); + &paddq ($car0,$temp); # +=tp[1] + + &inc ($j); # j++ + &dec ($num); +&set_label("inner"); + &pmuludq($acc0,$mul0); # ap[j]*bp[i] + &pmuludq($acc1,$mul1); # np[j]*m1 + &paddq ($car0,$acc0); # +=c0 + &paddq ($car1,$acc1); # +=c1 + + &movq ($acc0,$car0); + &movd ($temp,&DWP($frame+4,"esp",$j,4));# tp[j+1] + &pand ($acc0,$mask); + &movd ($acc1,&DWP(4,$np,$j,4)); # np[j+1] + &paddq ($car1,$acc0); # +=ap[j]*bp[i]+tp[j] + &movd ($acc0,&DWP(4,$ap,$j,4)); # ap[j+1] + &psrlq ($car0,32); + &movd (&DWP($frame-4,"esp",$j,4),$car1);# tp[j-1]= + &psrlq ($car1,32); + &paddq ($car0,$temp); # +=tp[j+1] + + &dec ($num); + &lea ($j,&DWP(1,$j)); # j++ + &jnz (&label("inner")); + + &mov ($num,$j); + &pmuludq($acc0,$mul0); # ap[num-1]*bp[i] + &pmuludq($acc1,$mul1); # np[num-1]*m1 + &paddq ($car0,$acc0); # +=c0 + &paddq ($car1,$acc1); # +=c1 + + &movq ($acc0,$car0); + &pand ($acc0,$mask); + &paddq ($car1,$acc0); # +=ap[num-1]*bp[i]+tp[num-1] + &movd (&DWP($frame-4,"esp",$j,4),$car1); # tp[num-2]= + &psrlq ($car0,32); + &psrlq ($car1,32); + + &movd ($temp,&DWP($frame+4,"esp",$num,4)); # += tp[num] + &paddq ($car1,$car0); + &paddq ($car1,$temp); + &movq (&QWP($frame,"esp",$num,4),$car1); # tp[num].tp[num-1] + + &lea ($i,&DWP(1,$i)); # i++ + &cmp ($i,$num); + &jle (&label("outer")); + + &emms (); # done with mmx bank + &jmp (&label("common_tail")); + +&set_label("non_sse2",16); +} + +if (0) { + &mov ("esp",$_sp); + &xor ("eax","eax"); # signal "not fast enough [yet]" + &jmp (&label("just_leave")); + # While the below code provides competitive performance for + # all key lengthes on modern Intel cores, it's still more + # than 10% slower for 4096-bit key elsewhere:-( "Competitive" + # means compared to the original integer-only assembler. + # 512-bit RSA sign is better by ~40%, but that's about all + # one can say about all CPUs... +} else { +$inp="esi"; # integer path uses these registers differently +$word="edi"; +$carry="ebp"; + + &mov ($inp,$_ap); + &lea ($carry,&DWP(1,$num)); + &mov ($word,$_bp); + &xor ($j,$j); # j=0 + &mov ("edx",$inp); + &and ($carry,1); # see if num is even + &sub ("edx",$word); # see if ap==bp + &lea ("eax",&DWP(4,$word,$num,4)); # &bp[num] + &or ($carry,"edx"); + &mov ($word,&DWP(0,$word)); # bp[0] + &jz (&label("bn_sqr_mont")); + &mov ($_bpend,"eax"); + &mov ("eax",&DWP(0,$inp)); + &xor ("edx","edx"); + +&set_label("mull",16); + &mov ($carry,"edx"); + &mul ($word); # ap[j]*bp[0] + &add ($carry,"eax"); + &lea ($j,&DWP(1,$j)); + &adc ("edx",0); + &mov ("eax",&DWP(0,$inp,$j,4)); # ap[j+1] + &cmp ($j,$num); + &mov (&DWP($frame-4,"esp",$j,4),$carry); # tp[j]= + &jl (&label("mull")); + + &mov ($carry,"edx"); + &mul ($word); # ap[num-1]*bp[0] + &mov ($word,$_n0); + &add ("eax",$carry); + &mov ($inp,$_np); + &adc ("edx",0); + &imul ($word,&DWP($frame,"esp")); # n0*tp[0] + + &mov (&DWP($frame,"esp",$num,4),"eax"); # tp[num-1]= + &xor ($j,$j); + &mov (&DWP($frame+4,"esp",$num,4),"edx"); # tp[num]= + &mov (&DWP($frame+8,"esp",$num,4),$j); # tp[num+1]= + + &mov ("eax",&DWP(0,$inp)); # np[0] + &mul ($word); # np[0]*m + &add ("eax",&DWP($frame,"esp")); # +=tp[0] + &mov ("eax",&DWP(4,$inp)); # np[1] + &adc ("edx",0); + &inc ($j); + + &jmp (&label("2ndmadd")); + +&set_label("1stmadd",16); + &mov ($carry,"edx"); + &mul ($word); # ap[j]*bp[i] + &add ($carry,&DWP($frame,"esp",$j,4)); # +=tp[j] + &lea ($j,&DWP(1,$j)); + &adc ("edx",0); + &add ($carry,"eax"); + &mov ("eax",&DWP(0,$inp,$j,4)); # ap[j+1] + &adc ("edx",0); + &cmp ($j,$num); + &mov (&DWP($frame-4,"esp",$j,4),$carry); # tp[j]= + &jl (&label("1stmadd")); + + &mov ($carry,"edx"); + &mul ($word); # ap[num-1]*bp[i] + &add ("eax",&DWP($frame,"esp",$num,4)); # +=tp[num-1] + &mov ($word,$_n0); + &adc ("edx",0); + &mov ($inp,$_np); + &add ($carry,"eax"); + &adc ("edx",0); + &imul ($word,&DWP($frame,"esp")); # n0*tp[0] + + &xor ($j,$j); + &add ("edx",&DWP($frame+4,"esp",$num,4)); # carry+=tp[num] + &mov (&DWP($frame,"esp",$num,4),$carry); # tp[num-1]= + &adc ($j,0); + &mov ("eax",&DWP(0,$inp)); # np[0] + &mov (&DWP($frame+4,"esp",$num,4),"edx"); # tp[num]= + &mov (&DWP($frame+8,"esp",$num,4),$j); # tp[num+1]= + + &mul ($word); # np[0]*m + &add ("eax",&DWP($frame,"esp")); # +=tp[0] + &mov ("eax",&DWP(4,$inp)); # np[1] + &adc ("edx",0); + &mov ($j,1); + +&set_label("2ndmadd",16); + &mov ($carry,"edx"); + &mul ($word); # np[j]*m + &add ($carry,&DWP($frame,"esp",$j,4)); # +=tp[j] + &lea ($j,&DWP(1,$j)); + &adc ("edx",0); + &add ($carry,"eax"); + &mov ("eax",&DWP(0,$inp,$j,4)); # np[j+1] + &adc ("edx",0); + &cmp ($j,$num); + &mov (&DWP($frame-8,"esp",$j,4),$carry); # tp[j-1]= + &jl (&label("2ndmadd")); + + &mov ($carry,"edx"); + &mul ($word); # np[j]*m + &add ($carry,&DWP($frame,"esp",$num,4)); # +=tp[num-1] + &adc ("edx",0); + &add ($carry,"eax"); + &adc ("edx",0); + &mov (&DWP($frame-4,"esp",$num,4),$carry); # tp[num-2]= + + &xor ("eax","eax"); + &mov ($j,$_bp); # &bp[i] + &add ("edx",&DWP($frame+4,"esp",$num,4)); # carry+=tp[num] + &adc ("eax",&DWP($frame+8,"esp",$num,4)); # +=tp[num+1] + &lea ($j,&DWP(4,$j)); + &mov (&DWP($frame,"esp",$num,4),"edx"); # tp[num-1]= + &cmp ($j,$_bpend); + &mov (&DWP($frame+4,"esp",$num,4),"eax"); # tp[num]= + &je (&label("common_tail")); + + &mov ($word,&DWP(0,$j)); # bp[i+1] + &mov ($inp,$_ap); + &mov ($_bp,$j); # &bp[++i] + &xor ($j,$j); + &xor ("edx","edx"); + &mov ("eax",&DWP(0,$inp)); + &jmp (&label("1stmadd")); + +&set_label("bn_sqr_mont",16); +$sbit=$num; + &mov ($_num,$num); + &mov ($_bp,$j); # i=0 + + &mov ("eax",$word); # ap[0] + &mul ($word); # ap[0]*ap[0] + &mov (&DWP($frame,"esp"),"eax"); # tp[0]= + &mov ($sbit,"edx"); + &shr ("edx",1); + &and ($sbit,1); + &inc ($j); +&set_label("sqr",16); + &mov ("eax",&DWP(0,$inp,$j,4)); # ap[j] + &mov ($carry,"edx"); + &mul ($word); # ap[j]*ap[0] + &add ("eax",$carry); + &lea ($j,&DWP(1,$j)); + &adc ("edx",0); + &lea ($carry,&DWP(0,$sbit,"eax",2)); + &shr ("eax",31); + &cmp ($j,$_num); + &mov ($sbit,"eax"); + &mov (&DWP($frame-4,"esp",$j,4),$carry); # tp[j]= + &jl (&label("sqr")); + + &mov ("eax",&DWP(0,$inp,$j,4)); # ap[num-1] + &mov ($carry,"edx"); + &mul ($word); # ap[num-1]*ap[0] + &add ("eax",$carry); + &mov ($word,$_n0); + &adc ("edx",0); + &mov ($inp,$_np); + &lea ($carry,&DWP(0,$sbit,"eax",2)); + &imul ($word,&DWP($frame,"esp")); # n0*tp[0] + &shr ("eax",31); + &mov (&DWP($frame,"esp",$j,4),$carry); # tp[num-1]= + + &lea ($carry,&DWP(0,"eax","edx",2)); + &mov ("eax",&DWP(0,$inp)); # np[0] + &shr ("edx",31); + &mov (&DWP($frame+4,"esp",$j,4),$carry); # tp[num]= + &mov (&DWP($frame+8,"esp",$j,4),"edx"); # tp[num+1]= + + &mul ($word); # np[0]*m + &add ("eax",&DWP($frame,"esp")); # +=tp[0] + &mov ($num,$j); + &adc ("edx",0); + &mov ("eax",&DWP(4,$inp)); # np[1] + &mov ($j,1); + +&set_label("3rdmadd",16); + &mov ($carry,"edx"); + &mul ($word); # np[j]*m + &add ($carry,&DWP($frame,"esp",$j,4)); # +=tp[j] + &adc ("edx",0); + &add ($carry,"eax"); + &mov ("eax",&DWP(4,$inp,$j,4)); # np[j+1] + &adc ("edx",0); + &mov (&DWP($frame-4,"esp",$j,4),$carry); # tp[j-1]= + + &mov ($carry,"edx"); + &mul ($word); # np[j+1]*m + &add ($carry,&DWP($frame+4,"esp",$j,4)); # +=tp[j+1] + &lea ($j,&DWP(2,$j)); + &adc ("edx",0); + &add ($carry,"eax"); + &mov ("eax",&DWP(0,$inp,$j,4)); # np[j+2] + &adc ("edx",0); + &cmp ($j,$num); + &mov (&DWP($frame-8,"esp",$j,4),$carry); # tp[j]= + &jl (&label("3rdmadd")); + + &mov ($carry,"edx"); + &mul ($word); # np[j]*m + &add ($carry,&DWP($frame,"esp",$num,4)); # +=tp[num-1] + &adc ("edx",0); + &add ($carry,"eax"); + &adc ("edx",0); + &mov (&DWP($frame-4,"esp",$num,4),$carry); # tp[num-2]= + + &mov ($j,$_bp); # i + &xor ("eax","eax"); + &mov ($inp,$_ap); + &add ("edx",&DWP($frame+4,"esp",$num,4)); # carry+=tp[num] + &adc ("eax",&DWP($frame+8,"esp",$num,4)); # +=tp[num+1] + &mov (&DWP($frame,"esp",$num,4),"edx"); # tp[num-1]= + &cmp ($j,$num); + &mov (&DWP($frame+4,"esp",$num,4),"eax"); # tp[num]= + &je (&label("common_tail")); + + &mov ($word,&DWP(4,$inp,$j,4)); # ap[i] + &lea ($j,&DWP(1,$j)); + &mov ("eax",$word); + &mov ($_bp,$j); # ++i + &mul ($word); # ap[i]*ap[i] + &add ("eax",&DWP($frame,"esp",$j,4)); # +=tp[i] + &adc ("edx",0); + &mov (&DWP($frame,"esp",$j,4),"eax"); # tp[i]= + &xor ($carry,$carry); + &cmp ($j,$num); + &lea ($j,&DWP(1,$j)); + &je (&label("sqrlast")); + + &mov ($sbit,"edx"); # zaps $num + &shr ("edx",1); + &and ($sbit,1); +&set_label("sqradd",16); + &mov ("eax",&DWP(0,$inp,$j,4)); # ap[j] + &mov ($carry,"edx"); + &mul ($word); # ap[j]*ap[i] + &add ("eax",$carry); + &lea ($carry,&DWP(0,"eax","eax")); + &adc ("edx",0); + &shr ("eax",31); + &add ($carry,&DWP($frame,"esp",$j,4)); # +=tp[j] + &lea ($j,&DWP(1,$j)); + &adc ("eax",0); + &add ($carry,$sbit); + &adc ("eax",0); + &cmp ($j,$_num); + &mov (&DWP($frame-4,"esp",$j,4),$carry); # tp[j]= + &mov ($sbit,"eax"); + &jle (&label("sqradd")); + + &mov ($carry,"edx"); + &add ("edx","edx"); + &shr ($carry,31); + &add ("edx",$sbit); + &adc ($carry,0); +&set_label("sqrlast"); + &mov ($word,$_n0); + &mov ($inp,$_np); + &imul ($word,&DWP($frame,"esp")); # n0*tp[0] + + &add ("edx",&DWP($frame,"esp",$j,4)); # +=tp[num] + &mov ("eax",&DWP(0,$inp)); # np[0] + &adc ($carry,0); + &mov (&DWP($frame,"esp",$j,4),"edx"); # tp[num]= + &mov (&DWP($frame+4,"esp",$j,4),$carry); # tp[num+1]= + + &mul ($word); # np[0]*m + &add ("eax",&DWP($frame,"esp")); # +=tp[0] + &lea ($num,&DWP(-1,$j)); + &adc ("edx",0); + &mov ($j,1); + &mov ("eax",&DWP(4,$inp)); # np[1] + + &jmp (&label("3rdmadd")); +} + +&set_label("common_tail",16); + &mov ($np,$_np); # load modulus pointer + &mov ($rp,$_rp); # load result pointer + &lea ($tp,&DWP($frame,"esp")); # [$ap and $bp are zapped] + + &mov ("eax",&DWP(0,$tp)); # tp[0] + &mov ($j,$num); # j=num-1 + &xor ($i,$i); # i=0 and clear CF! + +&set_label("sub",16); + &sbb ("eax",&DWP(0,$np,$i,4)); + &mov (&DWP(0,$rp,$i,4),"eax"); # rp[i]=tp[i]-np[i] + &dec ($j); # doesn't affect CF! + &mov ("eax",&DWP(4,$tp,$i,4)); # tp[i+1] + &lea ($i,&DWP(1,$i)); # i++ + &jge (&label("sub")); + + &sbb ("eax",0); # handle upmost overflow bit + +&set_label("copy",16); # copy or in-place refresh + &mov ("edx",&DWP(0,$tp,$num,4)); + &mov ($np,&DWP(0,$rp,$num,4)); + &xor ("edx",$np); # conditional select + &and ("edx","eax"); + &xor ("edx",$np); + &mov (&DWP(0,$tp,$num,4),$j) # zap temporary vector + &mov (&DWP(0,$rp,$num,4),"edx"); # rp[i]=tp[i] + &dec ($num); + &jge (&label("copy")); + + &mov ("esp",$_sp); # pull saved stack pointer + &mov ("eax",1); +&set_label("just_leave"); +&function_end("bn_mul_mont"); + +&asciz("Montgomery Multiplication for x86, CRYPTOGAMS by "); + +&asm_finish(); diff --git a/external/boringssl/crypto/bn/asm/x86_64-gcc.c b/external/boringssl/crypto/bn/asm/x86_64-gcc.c new file mode 100644 index 0000000000..214c12af88 --- /dev/null +++ b/external/boringssl/crypto/bn/asm/x86_64-gcc.c @@ -0,0 +1,531 @@ +/* x86_64 BIGNUM accelerator version 0.1, December 2002. + * + * Implemented by Andy Polyakov for the OpenSSL + * project. + * + * Rights for redistribution and usage in source and binary forms are + * granted according to the OpenSSL license. Warranty of any kind is + * disclaimed. + * + * Q. Version 0.1? It doesn't sound like Andy, he used to assign real + * versions, like 1.0... + * A. Well, that's because this code is basically a quick-n-dirty + * proof-of-concept hack. As you can see it's implemented with + * inline assembler, which means that you're bound to GCC and that + * there might be enough room for further improvement. + * + * Q. Why inline assembler? + * A. x86_64 features own ABI which I'm not familiar with. This is + * why I decided to let the compiler take care of subroutine + * prologue/epilogue as well as register allocation. For reference. + * Win64 implements different ABI for AMD64, different from Linux. + * + * Q. How much faster does it get? + * A. 'apps/openssl speed rsa dsa' output with no-asm: + * + * sign verify sign/s verify/s + * rsa 512 bits 0.0006s 0.0001s 1683.8 18456.2 + * rsa 1024 bits 0.0028s 0.0002s 356.0 6407.0 + * rsa 2048 bits 0.0172s 0.0005s 58.0 1957.8 + * rsa 4096 bits 0.1155s 0.0018s 8.7 555.6 + * sign verify sign/s verify/s + * dsa 512 bits 0.0005s 0.0006s 2100.8 1768.3 + * dsa 1024 bits 0.0014s 0.0018s 692.3 559.2 + * dsa 2048 bits 0.0049s 0.0061s 204.7 165.0 + * + * 'apps/openssl speed rsa dsa' output with this module: + * + * sign verify sign/s verify/s + * rsa 512 bits 0.0004s 0.0000s 2767.1 33297.9 + * rsa 1024 bits 0.0012s 0.0001s 867.4 14674.7 + * rsa 2048 bits 0.0061s 0.0002s 164.0 5270.0 + * rsa 4096 bits 0.0384s 0.0006s 26.1 1650.8 + * sign verify sign/s verify/s + * dsa 512 bits 0.0002s 0.0003s 4442.2 3786.3 + * dsa 1024 bits 0.0005s 0.0007s 1835.1 1497.4 + * dsa 2048 bits 0.0016s 0.0020s 620.4 504.6 + * + * For the reference. IA-32 assembler implementation performs + * very much like 64-bit code compiled with no-asm on the same + * machine. + */ + +#include + +/* TODO(davidben): Get this file working on Windows x64. */ +#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && defined(__GNUC__) + +#include "../internal.h" + + +#undef mul +#undef mul_add + +#define asm __asm__ + +/* + * "m"(a), "+m"(r) is the way to favor DirectPath µ-code; + * "g"(0) let the compiler to decide where does it + * want to keep the value of zero; + */ +#define mul_add(r, a, word, carry) \ + do { \ + register BN_ULONG high, low; \ + asm("mulq %3" : "=a"(low), "=d"(high) : "a"(word), "m"(a) : "cc"); \ + asm("addq %2,%0; adcq %3,%1" \ + : "+r"(carry), "+d"(high) \ + : "a"(low), "g"(0) \ + : "cc"); \ + asm("addq %2,%0; adcq %3,%1" \ + : "+m"(r), "+d"(high) \ + : "r"(carry), "g"(0) \ + : "cc"); \ + carry = high; \ + } while (0) + +#define mul(r, a, word, carry) \ + do { \ + register BN_ULONG high, low; \ + asm("mulq %3" : "=a"(low), "=d"(high) : "a"(word), "g"(a) : "cc"); \ + asm("addq %2,%0; adcq %3,%1" \ + : "+r"(carry), "+d"(high) \ + : "a"(low), "g"(0) \ + : "cc"); \ + (r) = carry, carry = high; \ + } while (0) +#undef sqr +#define sqr(r0, r1, a) asm("mulq %2" : "=a"(r0), "=d"(r1) : "a"(a) : "cc"); + +BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num, + BN_ULONG w) { + BN_ULONG c1 = 0; + + if (num <= 0) { + return (c1); + } + + while (num & ~3) { + mul_add(rp[0], ap[0], w, c1); + mul_add(rp[1], ap[1], w, c1); + mul_add(rp[2], ap[2], w, c1); + mul_add(rp[3], ap[3], w, c1); + ap += 4; + rp += 4; + num -= 4; + } + if (num) { + mul_add(rp[0], ap[0], w, c1); + if (--num == 0) { + return c1; + } + mul_add(rp[1], ap[1], w, c1); + if (--num == 0) { + return c1; + } + mul_add(rp[2], ap[2], w, c1); + return c1; + } + + return c1; +} + +BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w) { + BN_ULONG c1 = 0; + + if (num <= 0) { + return c1; + } + + while (num & ~3) { + mul(rp[0], ap[0], w, c1); + mul(rp[1], ap[1], w, c1); + mul(rp[2], ap[2], w, c1); + mul(rp[3], ap[3], w, c1); + ap += 4; + rp += 4; + num -= 4; + } + if (num) { + mul(rp[0], ap[0], w, c1); + if (--num == 0) { + return c1; + } + mul(rp[1], ap[1], w, c1); + if (--num == 0) { + return c1; + } + mul(rp[2], ap[2], w, c1); + } + return c1; +} + +void bn_sqr_words(BN_ULONG *r, const BN_ULONG *a, int n) { + if (n <= 0) { + return; + } + + while (n & ~3) { + sqr(r[0], r[1], a[0]); + sqr(r[2], r[3], a[1]); + sqr(r[4], r[5], a[2]); + sqr(r[6], r[7], a[3]); + a += 4; + r += 8; + n -= 4; + } + if (n) { + sqr(r[0], r[1], a[0]); + if (--n == 0) { + return; + } + sqr(r[2], r[3], a[1]); + if (--n == 0) { + return; + } + sqr(r[4], r[5], a[2]); + } +} + +BN_ULONG bn_add_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, + int n) { + BN_ULONG ret; + size_t i = 0; + + if (n <= 0) { + return 0; + } + + asm volatile ( + " subq %0,%0 \n" /* clear carry */ + " jmp 1f \n" + ".p2align 4 \n" + "1: movq (%4,%2,8),%0 \n" + " adcq (%5,%2,8),%0 \n" + " movq %0,(%3,%2,8) \n" + " lea 1(%2),%2 \n" + " loop 1b \n" + " sbbq %0,%0 \n" + : "=&r"(ret), "+c"(n), "+r"(i) + : "r"(rp), "r"(ap), "r"(bp) + : "cc", "memory"); + + return ret & 1; +} + +BN_ULONG bn_sub_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, + int n) { + BN_ULONG ret; + size_t i = 0; + + if (n <= 0) { + return 0; + } + + asm volatile ( + " subq %0,%0 \n" /* clear borrow */ + " jmp 1f \n" + ".p2align 4 \n" + "1: movq (%4,%2,8),%0 \n" + " sbbq (%5,%2,8),%0 \n" + " movq %0,(%3,%2,8) \n" + " lea 1(%2),%2 \n" + " loop 1b \n" + " sbbq %0,%0 \n" + : "=&r"(ret), "+c"(n), "+r"(i) + : "r"(rp), "r"(ap), "r"(bp) + : "cc", "memory"); + + return ret & 1; +} + +/* mul_add_c(a,b,c0,c1,c2) -- c+=a*b for three word number c=(c2,c1,c0) */ +/* mul_add_c2(a,b,c0,c1,c2) -- c+=2*a*b for three word number c=(c2,c1,c0) */ +/* sqr_add_c(a,i,c0,c1,c2) -- c+=a[i]^2 for three word number c=(c2,c1,c0) */ +/* sqr_add_c2(a,i,c0,c1,c2) -- c+=2*a[i]*a[j] for three word number c=(c2,c1,c0) + */ + +/* Keep in mind that carrying into high part of multiplication result can not + * overflow, because it cannot be all-ones. */ +#define mul_add_c(a, b, c0, c1, c2) \ + do { \ + BN_ULONG t1, t2; \ + asm("mulq %3" : "=a"(t1), "=d"(t2) : "a"(a), "m"(b) : "cc"); \ + asm("addq %3,%0; adcq %4,%1; adcq %5,%2" \ + : "+r"(c0), "+r"(c1), "+r"(c2) \ + : "r"(t1), "r"(t2), "g"(0) \ + : "cc"); \ + } while (0) + +#define sqr_add_c(a, i, c0, c1, c2) \ + do { \ + BN_ULONG t1, t2; \ + asm("mulq %2" : "=a"(t1), "=d"(t2) : "a"(a[i]) : "cc"); \ + asm("addq %3,%0; adcq %4,%1; adcq %5,%2" \ + : "+r"(c0), "+r"(c1), "+r"(c2) \ + : "r"(t1), "r"(t2), "g"(0) \ + : "cc"); \ + } while (0) + +#define mul_add_c2(a, b, c0, c1, c2) \ + do { \ + BN_ULONG t1, t2; \ + asm("mulq %3" : "=a"(t1), "=d"(t2) : "a"(a), "m"(b) : "cc"); \ + asm("addq %3,%0; adcq %4,%1; adcq %5,%2" \ + : "+r"(c0), "+r"(c1), "+r"(c2) \ + : "r"(t1), "r"(t2), "g"(0) \ + : "cc"); \ + asm("addq %3,%0; adcq %4,%1; adcq %5,%2" \ + : "+r"(c0), "+r"(c1), "+r"(c2) \ + : "r"(t1), "r"(t2), "g"(0) \ + : "cc"); \ + } while (0) + +#define sqr_add_c2(a, i, j, c0, c1, c2) mul_add_c2((a)[i], (a)[j], c0, c1, c2) + +void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) { + BN_ULONG c1, c2, c3; + + c1 = 0; + c2 = 0; + c3 = 0; + mul_add_c(a[0], b[0], c1, c2, c3); + r[0] = c1; + c1 = 0; + mul_add_c(a[0], b[1], c2, c3, c1); + mul_add_c(a[1], b[0], c2, c3, c1); + r[1] = c2; + c2 = 0; + mul_add_c(a[2], b[0], c3, c1, c2); + mul_add_c(a[1], b[1], c3, c1, c2); + mul_add_c(a[0], b[2], c3, c1, c2); + r[2] = c3; + c3 = 0; + mul_add_c(a[0], b[3], c1, c2, c3); + mul_add_c(a[1], b[2], c1, c2, c3); + mul_add_c(a[2], b[1], c1, c2, c3); + mul_add_c(a[3], b[0], c1, c2, c3); + r[3] = c1; + c1 = 0; + mul_add_c(a[4], b[0], c2, c3, c1); + mul_add_c(a[3], b[1], c2, c3, c1); + mul_add_c(a[2], b[2], c2, c3, c1); + mul_add_c(a[1], b[3], c2, c3, c1); + mul_add_c(a[0], b[4], c2, c3, c1); + r[4] = c2; + c2 = 0; + mul_add_c(a[0], b[5], c3, c1, c2); + mul_add_c(a[1], b[4], c3, c1, c2); + mul_add_c(a[2], b[3], c3, c1, c2); + mul_add_c(a[3], b[2], c3, c1, c2); + mul_add_c(a[4], b[1], c3, c1, c2); + mul_add_c(a[5], b[0], c3, c1, c2); + r[5] = c3; + c3 = 0; + mul_add_c(a[6], b[0], c1, c2, c3); + mul_add_c(a[5], b[1], c1, c2, c3); + mul_add_c(a[4], b[2], c1, c2, c3); + mul_add_c(a[3], b[3], c1, c2, c3); + mul_add_c(a[2], b[4], c1, c2, c3); + mul_add_c(a[1], b[5], c1, c2, c3); + mul_add_c(a[0], b[6], c1, c2, c3); + r[6] = c1; + c1 = 0; + mul_add_c(a[0], b[7], c2, c3, c1); + mul_add_c(a[1], b[6], c2, c3, c1); + mul_add_c(a[2], b[5], c2, c3, c1); + mul_add_c(a[3], b[4], c2, c3, c1); + mul_add_c(a[4], b[3], c2, c3, c1); + mul_add_c(a[5], b[2], c2, c3, c1); + mul_add_c(a[6], b[1], c2, c3, c1); + mul_add_c(a[7], b[0], c2, c3, c1); + r[7] = c2; + c2 = 0; + mul_add_c(a[7], b[1], c3, c1, c2); + mul_add_c(a[6], b[2], c3, c1, c2); + mul_add_c(a[5], b[3], c3, c1, c2); + mul_add_c(a[4], b[4], c3, c1, c2); + mul_add_c(a[3], b[5], c3, c1, c2); + mul_add_c(a[2], b[6], c3, c1, c2); + mul_add_c(a[1], b[7], c3, c1, c2); + r[8] = c3; + c3 = 0; + mul_add_c(a[2], b[7], c1, c2, c3); + mul_add_c(a[3], b[6], c1, c2, c3); + mul_add_c(a[4], b[5], c1, c2, c3); + mul_add_c(a[5], b[4], c1, c2, c3); + mul_add_c(a[6], b[3], c1, c2, c3); + mul_add_c(a[7], b[2], c1, c2, c3); + r[9] = c1; + c1 = 0; + mul_add_c(a[7], b[3], c2, c3, c1); + mul_add_c(a[6], b[4], c2, c3, c1); + mul_add_c(a[5], b[5], c2, c3, c1); + mul_add_c(a[4], b[6], c2, c3, c1); + mul_add_c(a[3], b[7], c2, c3, c1); + r[10] = c2; + c2 = 0; + mul_add_c(a[4], b[7], c3, c1, c2); + mul_add_c(a[5], b[6], c3, c1, c2); + mul_add_c(a[6], b[5], c3, c1, c2); + mul_add_c(a[7], b[4], c3, c1, c2); + r[11] = c3; + c3 = 0; + mul_add_c(a[7], b[5], c1, c2, c3); + mul_add_c(a[6], b[6], c1, c2, c3); + mul_add_c(a[5], b[7], c1, c2, c3); + r[12] = c1; + c1 = 0; + mul_add_c(a[6], b[7], c2, c3, c1); + mul_add_c(a[7], b[6], c2, c3, c1); + r[13] = c2; + c2 = 0; + mul_add_c(a[7], b[7], c3, c1, c2); + r[14] = c3; + r[15] = c1; +} + +void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) { + BN_ULONG c1, c2, c3; + + c1 = 0; + c2 = 0; + c3 = 0; + mul_add_c(a[0], b[0], c1, c2, c3); + r[0] = c1; + c1 = 0; + mul_add_c(a[0], b[1], c2, c3, c1); + mul_add_c(a[1], b[0], c2, c3, c1); + r[1] = c2; + c2 = 0; + mul_add_c(a[2], b[0], c3, c1, c2); + mul_add_c(a[1], b[1], c3, c1, c2); + mul_add_c(a[0], b[2], c3, c1, c2); + r[2] = c3; + c3 = 0; + mul_add_c(a[0], b[3], c1, c2, c3); + mul_add_c(a[1], b[2], c1, c2, c3); + mul_add_c(a[2], b[1], c1, c2, c3); + mul_add_c(a[3], b[0], c1, c2, c3); + r[3] = c1; + c1 = 0; + mul_add_c(a[3], b[1], c2, c3, c1); + mul_add_c(a[2], b[2], c2, c3, c1); + mul_add_c(a[1], b[3], c2, c3, c1); + r[4] = c2; + c2 = 0; + mul_add_c(a[2], b[3], c3, c1, c2); + mul_add_c(a[3], b[2], c3, c1, c2); + r[5] = c3; + c3 = 0; + mul_add_c(a[3], b[3], c1, c2, c3); + r[6] = c1; + r[7] = c2; +} + +void bn_sqr_comba8(BN_ULONG *r, const BN_ULONG *a) { + BN_ULONG c1, c2, c3; + + c1 = 0; + c2 = 0; + c3 = 0; + sqr_add_c(a, 0, c1, c2, c3); + r[0] = c1; + c1 = 0; + sqr_add_c2(a, 1, 0, c2, c3, c1); + r[1] = c2; + c2 = 0; + sqr_add_c(a, 1, c3, c1, c2); + sqr_add_c2(a, 2, 0, c3, c1, c2); + r[2] = c3; + c3 = 0; + sqr_add_c2(a, 3, 0, c1, c2, c3); + sqr_add_c2(a, 2, 1, c1, c2, c3); + r[3] = c1; + c1 = 0; + sqr_add_c(a, 2, c2, c3, c1); + sqr_add_c2(a, 3, 1, c2, c3, c1); + sqr_add_c2(a, 4, 0, c2, c3, c1); + r[4] = c2; + c2 = 0; + sqr_add_c2(a, 5, 0, c3, c1, c2); + sqr_add_c2(a, 4, 1, c3, c1, c2); + sqr_add_c2(a, 3, 2, c3, c1, c2); + r[5] = c3; + c3 = 0; + sqr_add_c(a, 3, c1, c2, c3); + sqr_add_c2(a, 4, 2, c1, c2, c3); + sqr_add_c2(a, 5, 1, c1, c2, c3); + sqr_add_c2(a, 6, 0, c1, c2, c3); + r[6] = c1; + c1 = 0; + sqr_add_c2(a, 7, 0, c2, c3, c1); + sqr_add_c2(a, 6, 1, c2, c3, c1); + sqr_add_c2(a, 5, 2, c2, c3, c1); + sqr_add_c2(a, 4, 3, c2, c3, c1); + r[7] = c2; + c2 = 0; + sqr_add_c(a, 4, c3, c1, c2); + sqr_add_c2(a, 5, 3, c3, c1, c2); + sqr_add_c2(a, 6, 2, c3, c1, c2); + sqr_add_c2(a, 7, 1, c3, c1, c2); + r[8] = c3; + c3 = 0; + sqr_add_c2(a, 7, 2, c1, c2, c3); + sqr_add_c2(a, 6, 3, c1, c2, c3); + sqr_add_c2(a, 5, 4, c1, c2, c3); + r[9] = c1; + c1 = 0; + sqr_add_c(a, 5, c2, c3, c1); + sqr_add_c2(a, 6, 4, c2, c3, c1); + sqr_add_c2(a, 7, 3, c2, c3, c1); + r[10] = c2; + c2 = 0; + sqr_add_c2(a, 7, 4, c3, c1, c2); + sqr_add_c2(a, 6, 5, c3, c1, c2); + r[11] = c3; + c3 = 0; + sqr_add_c(a, 6, c1, c2, c3); + sqr_add_c2(a, 7, 5, c1, c2, c3); + r[12] = c1; + c1 = 0; + sqr_add_c2(a, 7, 6, c2, c3, c1); + r[13] = c2; + c2 = 0; + sqr_add_c(a, 7, c3, c1, c2); + r[14] = c3; + r[15] = c1; +} + +void bn_sqr_comba4(BN_ULONG *r, const BN_ULONG *a) { + BN_ULONG c1, c2, c3; + + c1 = 0; + c2 = 0; + c3 = 0; + sqr_add_c(a, 0, c1, c2, c3); + r[0] = c1; + c1 = 0; + sqr_add_c2(a, 1, 0, c2, c3, c1); + r[1] = c2; + c2 = 0; + sqr_add_c(a, 1, c3, c1, c2); + sqr_add_c2(a, 2, 0, c3, c1, c2); + r[2] = c3; + c3 = 0; + sqr_add_c2(a, 3, 0, c1, c2, c3); + sqr_add_c2(a, 2, 1, c1, c2, c3); + r[3] = c1; + c1 = 0; + sqr_add_c(a, 2, c2, c3, c1); + sqr_add_c2(a, 3, 1, c2, c3, c1); + r[4] = c2; + c2 = 0; + sqr_add_c2(a, 3, 2, c3, c1, c2); + r[5] = c3; + c3 = 0; + sqr_add_c(a, 3, c1, c2, c3); + r[6] = c1; + r[7] = c2; +} + +#endif /* !NO_ASM && X86_64 && __GNUC__ */ diff --git a/external/boringssl/crypto/bn/asm/x86_64-mont.pl b/external/boringssl/crypto/bn/asm/x86_64-mont.pl new file mode 100755 index 0000000000..1ca2b1efc0 --- /dev/null +++ b/external/boringssl/crypto/bn/asm/x86_64-mont.pl @@ -0,0 +1,1430 @@ +#!/usr/bin/env perl + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== + +# October 2005. +# +# Montgomery multiplication routine for x86_64. While it gives modest +# 9% improvement of rsa4096 sign on Opteron, rsa512 sign runs more +# than twice, >2x, as fast. Most common rsa1024 sign is improved by +# respectful 50%. It remains to be seen if loop unrolling and +# dedicated squaring routine can provide further improvement... + +# July 2011. +# +# Add dedicated squaring procedure. Performance improvement varies +# from platform to platform, but in average it's ~5%/15%/25%/33% +# for 512-/1024-/2048-/4096-bit RSA *sign* benchmarks respectively. + +# August 2011. +# +# Unroll and modulo-schedule inner loops in such manner that they +# are "fallen through" for input lengths of 8, which is critical for +# 1024-bit RSA *sign*. Average performance improvement in comparison +# to *initial* version of this module from 2005 is ~0%/30%/40%/45% +# for 512-/1024-/2048-/4096-bit RSA *sign* benchmarks respectively. + +# June 2013. +# +# Optimize reduction in squaring procedure and improve 1024+-bit RSA +# sign performance by 10-16% on Intel Sandy Bridge and later +# (virtually same on non-Intel processors). + +# August 2013. +# +# Add MULX/ADOX/ADCX code path. + +$flavour = shift; +$output = shift; +if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } + +$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or +die "can't locate x86_64-xlate.pl"; + +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; + +# In upstream, this is controlled by shelling out to the compiler to check +# versions, but BoringSSL is intended to be used with pre-generated perlasm +# output, so this isn't useful anyway. +# +# TODO(davidben): Enable this option after testing. $addx goes up to 1. +$addx = 0; + +# int bn_mul_mont( +$rp="%rdi"; # BN_ULONG *rp, +$ap="%rsi"; # const BN_ULONG *ap, +$bp="%rdx"; # const BN_ULONG *bp, +$np="%rcx"; # const BN_ULONG *np, +$n0="%r8"; # const BN_ULONG *n0, +$num="%r9"; # int num); +$lo0="%r10"; +$hi0="%r11"; +$hi1="%r13"; +$i="%r14"; +$j="%r15"; +$m0="%rbx"; +$m1="%rbp"; + +$code=<<___; +.text + +.extern OPENSSL_ia32cap_P + +.globl bn_mul_mont +.type bn_mul_mont,\@function,6 +.align 16 +bn_mul_mont: + test \$3,${num}d + jnz .Lmul_enter + cmp \$8,${num}d + jb .Lmul_enter +___ +$code.=<<___ if ($addx); + mov OPENSSL_ia32cap_P+8(%rip),%r11d +___ +$code.=<<___; + cmp $ap,$bp + jne .Lmul4x_enter + test \$7,${num}d + jz .Lsqr8x_enter + jmp .Lmul4x_enter + +.align 16 +.Lmul_enter: + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + + mov ${num}d,${num}d + lea 2($num),%r10 + mov %rsp,%r11 + neg %r10 + lea (%rsp,%r10,8),%rsp # tp=alloca(8*(num+2)) + and \$-1024,%rsp # minimize TLB usage + + mov %r11,8(%rsp,$num,8) # tp[num+1]=%rsp +.Lmul_body: + mov $bp,%r12 # reassign $bp +___ + $bp="%r12"; +$code.=<<___; + mov ($n0),$n0 # pull n0[0] value + mov ($bp),$m0 # m0=bp[0] + mov ($ap),%rax + + xor $i,$i # i=0 + xor $j,$j # j=0 + + mov $n0,$m1 + mulq $m0 # ap[0]*bp[0] + mov %rax,$lo0 + mov ($np),%rax + + imulq $lo0,$m1 # "tp[0]"*n0 + mov %rdx,$hi0 + + mulq $m1 # np[0]*m1 + add %rax,$lo0 # discarded + mov 8($ap),%rax + adc \$0,%rdx + mov %rdx,$hi1 + + lea 1($j),$j # j++ + jmp .L1st_enter + +.align 16 +.L1st: + add %rax,$hi1 + mov ($ap,$j,8),%rax + adc \$0,%rdx + add $hi0,$hi1 # np[j]*m1+ap[j]*bp[0] + mov $lo0,$hi0 + adc \$0,%rdx + mov $hi1,-16(%rsp,$j,8) # tp[j-1] + mov %rdx,$hi1 + +.L1st_enter: + mulq $m0 # ap[j]*bp[0] + add %rax,$hi0 + mov ($np,$j,8),%rax + adc \$0,%rdx + lea 1($j),$j # j++ + mov %rdx,$lo0 + + mulq $m1 # np[j]*m1 + cmp $num,$j + jne .L1st + + add %rax,$hi1 + mov ($ap),%rax # ap[0] + adc \$0,%rdx + add $hi0,$hi1 # np[j]*m1+ap[j]*bp[0] + adc \$0,%rdx + mov $hi1,-16(%rsp,$j,8) # tp[j-1] + mov %rdx,$hi1 + mov $lo0,$hi0 + + xor %rdx,%rdx + add $hi0,$hi1 + adc \$0,%rdx + mov $hi1,-8(%rsp,$num,8) + mov %rdx,(%rsp,$num,8) # store upmost overflow bit + + lea 1($i),$i # i++ + jmp .Louter +.align 16 +.Louter: + mov ($bp,$i,8),$m0 # m0=bp[i] + xor $j,$j # j=0 + mov $n0,$m1 + mov (%rsp),$lo0 + mulq $m0 # ap[0]*bp[i] + add %rax,$lo0 # ap[0]*bp[i]+tp[0] + mov ($np),%rax + adc \$0,%rdx + + imulq $lo0,$m1 # tp[0]*n0 + mov %rdx,$hi0 + + mulq $m1 # np[0]*m1 + add %rax,$lo0 # discarded + mov 8($ap),%rax + adc \$0,%rdx + mov 8(%rsp),$lo0 # tp[1] + mov %rdx,$hi1 + + lea 1($j),$j # j++ + jmp .Linner_enter + +.align 16 +.Linner: + add %rax,$hi1 + mov ($ap,$j,8),%rax + adc \$0,%rdx + add $lo0,$hi1 # np[j]*m1+ap[j]*bp[i]+tp[j] + mov (%rsp,$j,8),$lo0 + adc \$0,%rdx + mov $hi1,-16(%rsp,$j,8) # tp[j-1] + mov %rdx,$hi1 + +.Linner_enter: + mulq $m0 # ap[j]*bp[i] + add %rax,$hi0 + mov ($np,$j,8),%rax + adc \$0,%rdx + add $hi0,$lo0 # ap[j]*bp[i]+tp[j] + mov %rdx,$hi0 + adc \$0,$hi0 + lea 1($j),$j # j++ + + mulq $m1 # np[j]*m1 + cmp $num,$j + jne .Linner + + add %rax,$hi1 + mov ($ap),%rax # ap[0] + adc \$0,%rdx + add $lo0,$hi1 # np[j]*m1+ap[j]*bp[i]+tp[j] + mov (%rsp,$j,8),$lo0 + adc \$0,%rdx + mov $hi1,-16(%rsp,$j,8) # tp[j-1] + mov %rdx,$hi1 + + xor %rdx,%rdx + add $hi0,$hi1 + adc \$0,%rdx + add $lo0,$hi1 # pull upmost overflow bit + adc \$0,%rdx + mov $hi1,-8(%rsp,$num,8) + mov %rdx,(%rsp,$num,8) # store upmost overflow bit + + lea 1($i),$i # i++ + cmp $num,$i + jb .Louter + + xor $i,$i # i=0 and clear CF! + mov (%rsp),%rax # tp[0] + lea (%rsp),$ap # borrow ap for tp + mov $num,$j # j=num + jmp .Lsub +.align 16 +.Lsub: sbb ($np,$i,8),%rax + mov %rax,($rp,$i,8) # rp[i]=tp[i]-np[i] + mov 8($ap,$i,8),%rax # tp[i+1] + lea 1($i),$i # i++ + dec $j # doesn't affect CF! + jnz .Lsub + + sbb \$0,%rax # handle upmost overflow bit + xor $i,$i + mov $num,$j # j=num +.align 16 +.Lcopy: # copy or in-place refresh + mov (%rsp,$i,8),$ap + mov ($rp,$i,8),$np + xor $np,$ap # conditional select: + and %rax,$ap # ((ap ^ np) & %rax) ^ np + xor $np,$ap # ap = borrow?tp:rp + mov $i,(%rsp,$i,8) # zap temporary vector + mov $ap,($rp,$i,8) # rp[i]=tp[i] + lea 1($i),$i + sub \$1,$j + jnz .Lcopy + + mov 8(%rsp,$num,8),%rsi # restore %rsp + mov \$1,%rax + mov (%rsi),%r15 + mov 8(%rsi),%r14 + mov 16(%rsi),%r13 + mov 24(%rsi),%r12 + mov 32(%rsi),%rbp + mov 40(%rsi),%rbx + lea 48(%rsi),%rsp +.Lmul_epilogue: + ret +.size bn_mul_mont,.-bn_mul_mont +___ +{{{ +my @A=("%r10","%r11"); +my @N=("%r13","%rdi"); +$code.=<<___; +.type bn_mul4x_mont,\@function,6 +.align 16 +bn_mul4x_mont: +.Lmul4x_enter: +___ +$code.=<<___ if ($addx); + and \$0x80100,%r11d + cmp \$0x80100,%r11d + je .Lmulx4x_enter +___ +$code.=<<___; + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + + mov ${num}d,${num}d + lea 4($num),%r10 + mov %rsp,%r11 + neg %r10 + lea (%rsp,%r10,8),%rsp # tp=alloca(8*(num+4)) + and \$-1024,%rsp # minimize TLB usage + + mov %r11,8(%rsp,$num,8) # tp[num+1]=%rsp +.Lmul4x_body: + mov $rp,16(%rsp,$num,8) # tp[num+2]=$rp + mov %rdx,%r12 # reassign $bp +___ + $bp="%r12"; +$code.=<<___; + mov ($n0),$n0 # pull n0[0] value + mov ($bp),$m0 # m0=bp[0] + mov ($ap),%rax + + xor $i,$i # i=0 + xor $j,$j # j=0 + + mov $n0,$m1 + mulq $m0 # ap[0]*bp[0] + mov %rax,$A[0] + mov ($np),%rax + + imulq $A[0],$m1 # "tp[0]"*n0 + mov %rdx,$A[1] + + mulq $m1 # np[0]*m1 + add %rax,$A[0] # discarded + mov 8($ap),%rax + adc \$0,%rdx + mov %rdx,$N[1] + + mulq $m0 + add %rax,$A[1] + mov 8($np),%rax + adc \$0,%rdx + mov %rdx,$A[0] + + mulq $m1 + add %rax,$N[1] + mov 16($ap),%rax + adc \$0,%rdx + add $A[1],$N[1] + lea 4($j),$j # j++ + adc \$0,%rdx + mov $N[1],(%rsp) + mov %rdx,$N[0] + jmp .L1st4x +.align 16 +.L1st4x: + mulq $m0 # ap[j]*bp[0] + add %rax,$A[0] + mov -16($np,$j,8),%rax + adc \$0,%rdx + mov %rdx,$A[1] + + mulq $m1 # np[j]*m1 + add %rax,$N[0] + mov -8($ap,$j,8),%rax + adc \$0,%rdx + add $A[0],$N[0] # np[j]*m1+ap[j]*bp[0] + adc \$0,%rdx + mov $N[0],-24(%rsp,$j,8) # tp[j-1] + mov %rdx,$N[1] + + mulq $m0 # ap[j]*bp[0] + add %rax,$A[1] + mov -8($np,$j,8),%rax + adc \$0,%rdx + mov %rdx,$A[0] + + mulq $m1 # np[j]*m1 + add %rax,$N[1] + mov ($ap,$j,8),%rax + adc \$0,%rdx + add $A[1],$N[1] # np[j]*m1+ap[j]*bp[0] + adc \$0,%rdx + mov $N[1],-16(%rsp,$j,8) # tp[j-1] + mov %rdx,$N[0] + + mulq $m0 # ap[j]*bp[0] + add %rax,$A[0] + mov ($np,$j,8),%rax + adc \$0,%rdx + mov %rdx,$A[1] + + mulq $m1 # np[j]*m1 + add %rax,$N[0] + mov 8($ap,$j,8),%rax + adc \$0,%rdx + add $A[0],$N[0] # np[j]*m1+ap[j]*bp[0] + adc \$0,%rdx + mov $N[0],-8(%rsp,$j,8) # tp[j-1] + mov %rdx,$N[1] + + mulq $m0 # ap[j]*bp[0] + add %rax,$A[1] + mov 8($np,$j,8),%rax + adc \$0,%rdx + lea 4($j),$j # j++ + mov %rdx,$A[0] + + mulq $m1 # np[j]*m1 + add %rax,$N[1] + mov -16($ap,$j,8),%rax + adc \$0,%rdx + add $A[1],$N[1] # np[j]*m1+ap[j]*bp[0] + adc \$0,%rdx + mov $N[1],-32(%rsp,$j,8) # tp[j-1] + mov %rdx,$N[0] + cmp $num,$j + jb .L1st4x + + mulq $m0 # ap[j]*bp[0] + add %rax,$A[0] + mov -16($np,$j,8),%rax + adc \$0,%rdx + mov %rdx,$A[1] + + mulq $m1 # np[j]*m1 + add %rax,$N[0] + mov -8($ap,$j,8),%rax + adc \$0,%rdx + add $A[0],$N[0] # np[j]*m1+ap[j]*bp[0] + adc \$0,%rdx + mov $N[0],-24(%rsp,$j,8) # tp[j-1] + mov %rdx,$N[1] + + mulq $m0 # ap[j]*bp[0] + add %rax,$A[1] + mov -8($np,$j,8),%rax + adc \$0,%rdx + mov %rdx,$A[0] + + mulq $m1 # np[j]*m1 + add %rax,$N[1] + mov ($ap),%rax # ap[0] + adc \$0,%rdx + add $A[1],$N[1] # np[j]*m1+ap[j]*bp[0] + adc \$0,%rdx + mov $N[1],-16(%rsp,$j,8) # tp[j-1] + mov %rdx,$N[0] + + xor $N[1],$N[1] + add $A[0],$N[0] + adc \$0,$N[1] + mov $N[0],-8(%rsp,$j,8) + mov $N[1],(%rsp,$j,8) # store upmost overflow bit + + lea 1($i),$i # i++ +.align 4 +.Louter4x: + mov ($bp,$i,8),$m0 # m0=bp[i] + xor $j,$j # j=0 + mov (%rsp),$A[0] + mov $n0,$m1 + mulq $m0 # ap[0]*bp[i] + add %rax,$A[0] # ap[0]*bp[i]+tp[0] + mov ($np),%rax + adc \$0,%rdx + + imulq $A[0],$m1 # tp[0]*n0 + mov %rdx,$A[1] + + mulq $m1 # np[0]*m1 + add %rax,$A[0] # "$N[0]", discarded + mov 8($ap),%rax + adc \$0,%rdx + mov %rdx,$N[1] + + mulq $m0 # ap[j]*bp[i] + add %rax,$A[1] + mov 8($np),%rax + adc \$0,%rdx + add 8(%rsp),$A[1] # +tp[1] + adc \$0,%rdx + mov %rdx,$A[0] + + mulq $m1 # np[j]*m1 + add %rax,$N[1] + mov 16($ap),%rax + adc \$0,%rdx + add $A[1],$N[1] # np[j]*m1+ap[j]*bp[i]+tp[j] + lea 4($j),$j # j+=2 + adc \$0,%rdx + mov $N[1],(%rsp) # tp[j-1] + mov %rdx,$N[0] + jmp .Linner4x +.align 16 +.Linner4x: + mulq $m0 # ap[j]*bp[i] + add %rax,$A[0] + mov -16($np,$j,8),%rax + adc \$0,%rdx + add -16(%rsp,$j,8),$A[0] # ap[j]*bp[i]+tp[j] + adc \$0,%rdx + mov %rdx,$A[1] + + mulq $m1 # np[j]*m1 + add %rax,$N[0] + mov -8($ap,$j,8),%rax + adc \$0,%rdx + add $A[0],$N[0] + adc \$0,%rdx + mov $N[0],-24(%rsp,$j,8) # tp[j-1] + mov %rdx,$N[1] + + mulq $m0 # ap[j]*bp[i] + add %rax,$A[1] + mov -8($np,$j,8),%rax + adc \$0,%rdx + add -8(%rsp,$j,8),$A[1] + adc \$0,%rdx + mov %rdx,$A[0] + + mulq $m1 # np[j]*m1 + add %rax,$N[1] + mov ($ap,$j,8),%rax + adc \$0,%rdx + add $A[1],$N[1] + adc \$0,%rdx + mov $N[1],-16(%rsp,$j,8) # tp[j-1] + mov %rdx,$N[0] + + mulq $m0 # ap[j]*bp[i] + add %rax,$A[0] + mov ($np,$j,8),%rax + adc \$0,%rdx + add (%rsp,$j,8),$A[0] # ap[j]*bp[i]+tp[j] + adc \$0,%rdx + mov %rdx,$A[1] + + mulq $m1 # np[j]*m1 + add %rax,$N[0] + mov 8($ap,$j,8),%rax + adc \$0,%rdx + add $A[0],$N[0] + adc \$0,%rdx + mov $N[0],-8(%rsp,$j,8) # tp[j-1] + mov %rdx,$N[1] + + mulq $m0 # ap[j]*bp[i] + add %rax,$A[1] + mov 8($np,$j,8),%rax + adc \$0,%rdx + add 8(%rsp,$j,8),$A[1] + adc \$0,%rdx + lea 4($j),$j # j++ + mov %rdx,$A[0] + + mulq $m1 # np[j]*m1 + add %rax,$N[1] + mov -16($ap,$j,8),%rax + adc \$0,%rdx + add $A[1],$N[1] + adc \$0,%rdx + mov $N[1],-32(%rsp,$j,8) # tp[j-1] + mov %rdx,$N[0] + cmp $num,$j + jb .Linner4x + + mulq $m0 # ap[j]*bp[i] + add %rax,$A[0] + mov -16($np,$j,8),%rax + adc \$0,%rdx + add -16(%rsp,$j,8),$A[0] # ap[j]*bp[i]+tp[j] + adc \$0,%rdx + mov %rdx,$A[1] + + mulq $m1 # np[j]*m1 + add %rax,$N[0] + mov -8($ap,$j,8),%rax + adc \$0,%rdx + add $A[0],$N[0] + adc \$0,%rdx + mov $N[0],-24(%rsp,$j,8) # tp[j-1] + mov %rdx,$N[1] + + mulq $m0 # ap[j]*bp[i] + add %rax,$A[1] + mov -8($np,$j,8),%rax + adc \$0,%rdx + add -8(%rsp,$j,8),$A[1] + adc \$0,%rdx + lea 1($i),$i # i++ + mov %rdx,$A[0] + + mulq $m1 # np[j]*m1 + add %rax,$N[1] + mov ($ap),%rax # ap[0] + adc \$0,%rdx + add $A[1],$N[1] + adc \$0,%rdx + mov $N[1],-16(%rsp,$j,8) # tp[j-1] + mov %rdx,$N[0] + + xor $N[1],$N[1] + add $A[0],$N[0] + adc \$0,$N[1] + add (%rsp,$num,8),$N[0] # pull upmost overflow bit + adc \$0,$N[1] + mov $N[0],-8(%rsp,$j,8) + mov $N[1],(%rsp,$j,8) # store upmost overflow bit + + cmp $num,$i + jb .Louter4x +___ +{ +my @ri=("%rax","%rdx",$m0,$m1); +$code.=<<___; + mov 16(%rsp,$num,8),$rp # restore $rp + mov 0(%rsp),@ri[0] # tp[0] + mov 8(%rsp),@ri[1] # tp[1] + shr \$2,$num # num/=4 + lea (%rsp),$ap # borrow ap for tp + xor $i,$i # i=0 and clear CF! + + sub 0($np),@ri[0] + mov 16($ap),@ri[2] # tp[2] + mov 24($ap),@ri[3] # tp[3] + sbb 8($np),@ri[1] + lea -1($num),$j # j=num/4-1 + jmp .Lsub4x +.align 16 +.Lsub4x: + mov @ri[0],0($rp,$i,8) # rp[i]=tp[i]-np[i] + mov @ri[1],8($rp,$i,8) # rp[i]=tp[i]-np[i] + sbb 16($np,$i,8),@ri[2] + mov 32($ap,$i,8),@ri[0] # tp[i+1] + mov 40($ap,$i,8),@ri[1] + sbb 24($np,$i,8),@ri[3] + mov @ri[2],16($rp,$i,8) # rp[i]=tp[i]-np[i] + mov @ri[3],24($rp,$i,8) # rp[i]=tp[i]-np[i] + sbb 32($np,$i,8),@ri[0] + mov 48($ap,$i,8),@ri[2] + mov 56($ap,$i,8),@ri[3] + sbb 40($np,$i,8),@ri[1] + lea 4($i),$i # i++ + dec $j # doesnn't affect CF! + jnz .Lsub4x + + mov @ri[0],0($rp,$i,8) # rp[i]=tp[i]-np[i] + mov 32($ap,$i,8),@ri[0] # load overflow bit + sbb 16($np,$i,8),@ri[2] + mov @ri[1],8($rp,$i,8) # rp[i]=tp[i]-np[i] + sbb 24($np,$i,8),@ri[3] + mov @ri[2],16($rp,$i,8) # rp[i]=tp[i]-np[i] + + sbb \$0,@ri[0] # handle upmost overflow bit + mov @ri[0],%xmm0 + punpcklqdq %xmm0,%xmm0 # extend mask to 128 bits + mov @ri[3],24($rp,$i,8) # rp[i]=tp[i]-np[i] + xor $i,$i # i=0 + + mov $num,$j + pxor %xmm5,%xmm5 + jmp .Lcopy4x +.align 16 +.Lcopy4x: # copy or in-place refresh + movdqu (%rsp,$i),%xmm2 + movdqu 16(%rsp,$i),%xmm4 + movdqu ($rp,$i),%xmm1 + movdqu 16($rp,$i),%xmm3 + pxor %xmm1,%xmm2 # conditional select + pxor %xmm3,%xmm4 + pand %xmm0,%xmm2 + pand %xmm0,%xmm4 + pxor %xmm1,%xmm2 + pxor %xmm3,%xmm4 + movdqu %xmm2,($rp,$i) + movdqu %xmm4,16($rp,$i) + movdqa %xmm5,(%rsp,$i) # zap temporary vectors + movdqa %xmm5,16(%rsp,$i) + + lea 32($i),$i + dec $j + jnz .Lcopy4x + + shl \$2,$num +___ +} +$code.=<<___; + mov 8(%rsp,$num,8),%rsi # restore %rsp + mov \$1,%rax + mov (%rsi),%r15 + mov 8(%rsi),%r14 + mov 16(%rsi),%r13 + mov 24(%rsi),%r12 + mov 32(%rsi),%rbp + mov 40(%rsi),%rbx + lea 48(%rsi),%rsp +.Lmul4x_epilogue: + ret +.size bn_mul4x_mont,.-bn_mul4x_mont +___ +}}} + {{{ +###################################################################### +# void bn_sqr8x_mont( +my $rptr="%rdi"; # const BN_ULONG *rptr, +my $aptr="%rsi"; # const BN_ULONG *aptr, +my $bptr="%rdx"; # not used +my $nptr="%rcx"; # const BN_ULONG *nptr, +my $n0 ="%r8"; # const BN_ULONG *n0); +my $num ="%r9"; # int num, has to be divisible by 8 + +my ($i,$j,$tptr)=("%rbp","%rcx",$rptr); +my @A0=("%r10","%r11"); +my @A1=("%r12","%r13"); +my ($a0,$a1,$ai)=("%r14","%r15","%rbx"); + +$code.=<<___ if ($addx); +.extern bn_sqrx8x_internal # see x86_64-mont5 module +___ +$code.=<<___; +.extern bn_sqr8x_internal # see x86_64-mont5 module + +.type bn_sqr8x_mont,\@function,6 +.align 32 +bn_sqr8x_mont: +.Lsqr8x_enter: + mov %rsp,%rax + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + + mov ${num}d,%r10d + shl \$3,${num}d # convert $num to bytes + shl \$3+2,%r10 # 4*$num + neg $num + + ############################################################## + # ensure that stack frame doesn't alias with $aptr modulo + # 4096. this is done to allow memory disambiguation logic + # do its job. + # + lea -64(%rsp,$num,2),%r11 + mov ($n0),$n0 # *n0 + sub $aptr,%r11 + and \$4095,%r11 + cmp %r11,%r10 + jb .Lsqr8x_sp_alt + sub %r11,%rsp # align with $aptr + lea -64(%rsp,$num,2),%rsp # alloca(frame+2*$num) + jmp .Lsqr8x_sp_done + +.align 32 +.Lsqr8x_sp_alt: + lea 4096-64(,$num,2),%r10 # 4096-frame-2*$num + lea -64(%rsp,$num,2),%rsp # alloca(frame+2*$num) + sub %r10,%r11 + mov \$0,%r10 + cmovc %r10,%r11 + sub %r11,%rsp +.Lsqr8x_sp_done: + and \$-64,%rsp + mov $num,%r10 + neg $num + + mov $n0, 32(%rsp) + mov %rax, 40(%rsp) # save original %rsp +.Lsqr8x_body: + + movq $nptr, %xmm2 # save pointer to modulus + pxor %xmm0,%xmm0 + movq $rptr,%xmm1 # save $rptr + movq %r10, %xmm3 # -$num +___ +$code.=<<___ if ($addx); + mov OPENSSL_ia32cap_P+8(%rip),%eax + and \$0x80100,%eax + cmp \$0x80100,%eax + jne .Lsqr8x_nox + + call bn_sqrx8x_internal # see x86_64-mont5 module + # %rax top-most carry + # %rbp nptr + # %rcx -8*num + # %r8 end of tp[2*num] + lea (%r8,%rcx),%rbx + mov %rcx,$num + mov %rcx,%rdx + movq %xmm1,$rptr + sar \$3+2,%rcx # %cf=0 + jmp .Lsqr8x_sub + +.align 32 +.Lsqr8x_nox: +___ +$code.=<<___; + call bn_sqr8x_internal # see x86_64-mont5 module + # %rax top-most carry + # %rbp nptr + # %r8 -8*num + # %rdi end of tp[2*num] + lea (%rdi,$num),%rbx + mov $num,%rcx + mov $num,%rdx + movq %xmm1,$rptr + sar \$3+2,%rcx # %cf=0 + jmp .Lsqr8x_sub + +.align 32 +.Lsqr8x_sub: + mov 8*0(%rbx),%r12 + mov 8*1(%rbx),%r13 + mov 8*2(%rbx),%r14 + mov 8*3(%rbx),%r15 + lea 8*4(%rbx),%rbx + sbb 8*0(%rbp),%r12 + sbb 8*1(%rbp),%r13 + sbb 8*2(%rbp),%r14 + sbb 8*3(%rbp),%r15 + lea 8*4(%rbp),%rbp + mov %r12,8*0($rptr) + mov %r13,8*1($rptr) + mov %r14,8*2($rptr) + mov %r15,8*3($rptr) + lea 8*4($rptr),$rptr + inc %rcx # preserves %cf + jnz .Lsqr8x_sub + + sbb \$0,%rax # top-most carry + lea (%rbx,$num),%rbx # rewind + lea ($rptr,$num),$rptr # rewind + + movq %rax,%xmm1 + pxor %xmm0,%xmm0 + pshufd \$0,%xmm1,%xmm1 + mov 40(%rsp),%rsi # restore %rsp + jmp .Lsqr8x_cond_copy + +.align 32 +.Lsqr8x_cond_copy: + movdqa 16*0(%rbx),%xmm2 + movdqa 16*1(%rbx),%xmm3 + lea 16*2(%rbx),%rbx + movdqu 16*0($rptr),%xmm4 + movdqu 16*1($rptr),%xmm5 + lea 16*2($rptr),$rptr + movdqa %xmm0,-16*2(%rbx) # zero tp + movdqa %xmm0,-16*1(%rbx) + movdqa %xmm0,-16*2(%rbx,%rdx) + movdqa %xmm0,-16*1(%rbx,%rdx) + pcmpeqd %xmm1,%xmm0 + pand %xmm1,%xmm2 + pand %xmm1,%xmm3 + pand %xmm0,%xmm4 + pand %xmm0,%xmm5 + pxor %xmm0,%xmm0 + por %xmm2,%xmm4 + por %xmm3,%xmm5 + movdqu %xmm4,-16*2($rptr) + movdqu %xmm5,-16*1($rptr) + add \$32,$num + jnz .Lsqr8x_cond_copy + + mov \$1,%rax + mov -48(%rsi),%r15 + mov -40(%rsi),%r14 + mov -32(%rsi),%r13 + mov -24(%rsi),%r12 + mov -16(%rsi),%rbp + mov -8(%rsi),%rbx + lea (%rsi),%rsp +.Lsqr8x_epilogue: + ret +.size bn_sqr8x_mont,.-bn_sqr8x_mont +___ +}}} + +if ($addx) {{{ +my $bp="%rdx"; # original value + +$code.=<<___; +.type bn_mulx4x_mont,\@function,6 +.align 32 +bn_mulx4x_mont: +.Lmulx4x_enter: + mov %rsp,%rax + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + + shl \$3,${num}d # convert $num to bytes + .byte 0x67 + xor %r10,%r10 + sub $num,%r10 # -$num + mov ($n0),$n0 # *n0 + lea -72(%rsp,%r10),%rsp # alloca(frame+$num+8) + lea ($bp,$num),%r10 + and \$-128,%rsp + ############################################################## + # Stack layout + # +0 num + # +8 off-loaded &b[i] + # +16 end of b[num] + # +24 saved n0 + # +32 saved rp + # +40 saved %rsp + # +48 inner counter + # +56 + # +64 tmp[num+1] + # + mov $num,0(%rsp) # save $num + shr \$5,$num + mov %r10,16(%rsp) # end of b[num] + sub \$1,$num + mov $n0, 24(%rsp) # save *n0 + mov $rp, 32(%rsp) # save $rp + mov %rax,40(%rsp) # save original %rsp + mov $num,48(%rsp) # inner counter + jmp .Lmulx4x_body + +.align 32 +.Lmulx4x_body: +___ +my ($aptr, $bptr, $nptr, $tptr, $mi, $bi, $zero, $num)= + ("%rsi","%rdi","%rcx","%rbx","%r8","%r9","%rbp","%rax"); +my $rptr=$bptr; +$code.=<<___; + lea 8($bp),$bptr + mov ($bp),%rdx # b[0], $bp==%rdx actually + lea 64+32(%rsp),$tptr + mov %rdx,$bi + + mulx 0*8($aptr),$mi,%rax # a[0]*b[0] + mulx 1*8($aptr),%r11,%r14 # a[1]*b[0] + add %rax,%r11 + mov $bptr,8(%rsp) # off-load &b[i] + mulx 2*8($aptr),%r12,%r13 # ... + adc %r14,%r12 + adc \$0,%r13 + + mov $mi,$bptr # borrow $bptr + imulq 24(%rsp),$mi # "t[0]"*n0 + xor $zero,$zero # cf=0, of=0 + + mulx 3*8($aptr),%rax,%r14 + mov $mi,%rdx + lea 4*8($aptr),$aptr + adcx %rax,%r13 + adcx $zero,%r14 # cf=0 + + mulx 0*8($nptr),%rax,%r10 + adcx %rax,$bptr # discarded + adox %r11,%r10 + mulx 1*8($nptr),%rax,%r11 + adcx %rax,%r10 + adox %r12,%r11 + .byte 0xc4,0x62,0xfb,0xf6,0xa1,0x10,0x00,0x00,0x00 # mulx 2*8($nptr),%rax,%r12 + mov 48(%rsp),$bptr # counter value + mov %r10,-4*8($tptr) + adcx %rax,%r11 + adox %r13,%r12 + mulx 3*8($nptr),%rax,%r15 + mov $bi,%rdx + mov %r11,-3*8($tptr) + adcx %rax,%r12 + adox $zero,%r15 # of=0 + lea 4*8($nptr),$nptr + mov %r12,-2*8($tptr) + + jmp .Lmulx4x_1st + +.align 32 +.Lmulx4x_1st: + adcx $zero,%r15 # cf=0, modulo-scheduled + mulx 0*8($aptr),%r10,%rax # a[4]*b[0] + adcx %r14,%r10 + mulx 1*8($aptr),%r11,%r14 # a[5]*b[0] + adcx %rax,%r11 + mulx 2*8($aptr),%r12,%rax # ... + adcx %r14,%r12 + mulx 3*8($aptr),%r13,%r14 + .byte 0x67,0x67 + mov $mi,%rdx + adcx %rax,%r13 + adcx $zero,%r14 # cf=0 + lea 4*8($aptr),$aptr + lea 4*8($tptr),$tptr + + adox %r15,%r10 + mulx 0*8($nptr),%rax,%r15 + adcx %rax,%r10 + adox %r15,%r11 + mulx 1*8($nptr),%rax,%r15 + adcx %rax,%r11 + adox %r15,%r12 + mulx 2*8($nptr),%rax,%r15 + mov %r10,-5*8($tptr) + adcx %rax,%r12 + mov %r11,-4*8($tptr) + adox %r15,%r13 + mulx 3*8($nptr),%rax,%r15 + mov $bi,%rdx + mov %r12,-3*8($tptr) + adcx %rax,%r13 + adox $zero,%r15 + lea 4*8($nptr),$nptr + mov %r13,-2*8($tptr) + + dec $bptr # of=0, pass cf + jnz .Lmulx4x_1st + + mov 0(%rsp),$num # load num + mov 8(%rsp),$bptr # re-load &b[i] + adc $zero,%r15 # modulo-scheduled + add %r15,%r14 + sbb %r15,%r15 # top-most carry + mov %r14,-1*8($tptr) + jmp .Lmulx4x_outer + +.align 32 +.Lmulx4x_outer: + mov ($bptr),%rdx # b[i] + lea 8($bptr),$bptr # b++ + sub $num,$aptr # rewind $aptr + mov %r15,($tptr) # save top-most carry + lea 64+4*8(%rsp),$tptr + sub $num,$nptr # rewind $nptr + + mulx 0*8($aptr),$mi,%r11 # a[0]*b[i] + xor %ebp,%ebp # xor $zero,$zero # cf=0, of=0 + mov %rdx,$bi + mulx 1*8($aptr),%r14,%r12 # a[1]*b[i] + adox -4*8($tptr),$mi + adcx %r14,%r11 + mulx 2*8($aptr),%r15,%r13 # ... + adox -3*8($tptr),%r11 + adcx %r15,%r12 + adox $zero,%r12 + adcx $zero,%r13 + + mov $bptr,8(%rsp) # off-load &b[i] + .byte 0x67 + mov $mi,%r15 + imulq 24(%rsp),$mi # "t[0]"*n0 + xor %ebp,%ebp # xor $zero,$zero # cf=0, of=0 + + mulx 3*8($aptr),%rax,%r14 + mov $mi,%rdx + adox -2*8($tptr),%r12 + adcx %rax,%r13 + adox -1*8($tptr),%r13 + adcx $zero,%r14 + lea 4*8($aptr),$aptr + adox $zero,%r14 + + mulx 0*8($nptr),%rax,%r10 + adcx %rax,%r15 # discarded + adox %r11,%r10 + mulx 1*8($nptr),%rax,%r11 + adcx %rax,%r10 + adox %r12,%r11 + mulx 2*8($nptr),%rax,%r12 + mov %r10,-4*8($tptr) + adcx %rax,%r11 + adox %r13,%r12 + mulx 3*8($nptr),%rax,%r15 + mov $bi,%rdx + mov %r11,-3*8($tptr) + lea 4*8($nptr),$nptr + adcx %rax,%r12 + adox $zero,%r15 # of=0 + mov 48(%rsp),$bptr # counter value + mov %r12,-2*8($tptr) + + jmp .Lmulx4x_inner + +.align 32 +.Lmulx4x_inner: + mulx 0*8($aptr),%r10,%rax # a[4]*b[i] + adcx $zero,%r15 # cf=0, modulo-scheduled + adox %r14,%r10 + mulx 1*8($aptr),%r11,%r14 # a[5]*b[i] + adcx 0*8($tptr),%r10 + adox %rax,%r11 + mulx 2*8($aptr),%r12,%rax # ... + adcx 1*8($tptr),%r11 + adox %r14,%r12 + mulx 3*8($aptr),%r13,%r14 + mov $mi,%rdx + adcx 2*8($tptr),%r12 + adox %rax,%r13 + adcx 3*8($tptr),%r13 + adox $zero,%r14 # of=0 + lea 4*8($aptr),$aptr + lea 4*8($tptr),$tptr + adcx $zero,%r14 # cf=0 + + adox %r15,%r10 + mulx 0*8($nptr),%rax,%r15 + adcx %rax,%r10 + adox %r15,%r11 + mulx 1*8($nptr),%rax,%r15 + adcx %rax,%r11 + adox %r15,%r12 + mulx 2*8($nptr),%rax,%r15 + mov %r10,-5*8($tptr) + adcx %rax,%r12 + adox %r15,%r13 + mulx 3*8($nptr),%rax,%r15 + mov $bi,%rdx + mov %r11,-4*8($tptr) + mov %r12,-3*8($tptr) + adcx %rax,%r13 + adox $zero,%r15 + lea 4*8($nptr),$nptr + mov %r13,-2*8($tptr) + + dec $bptr # of=0, pass cf + jnz .Lmulx4x_inner + + mov 0(%rsp),$num # load num + mov 8(%rsp),$bptr # re-load &b[i] + adc $zero,%r15 # modulo-scheduled + sub 0*8($tptr),$zero # pull top-most carry + adc %r15,%r14 + sbb %r15,%r15 # top-most carry + mov %r14,-1*8($tptr) + + cmp 16(%rsp),$bptr + jne .Lmulx4x_outer + + lea 64(%rsp),$tptr + sub $num,$nptr # rewind $nptr + neg %r15 + mov $num,%rdx + shr \$3+2,$num # %cf=0 + mov 32(%rsp),$rptr # restore rp + jmp .Lmulx4x_sub + +.align 32 +.Lmulx4x_sub: + mov 8*0($tptr),%r11 + mov 8*1($tptr),%r12 + mov 8*2($tptr),%r13 + mov 8*3($tptr),%r14 + lea 8*4($tptr),$tptr + sbb 8*0($nptr),%r11 + sbb 8*1($nptr),%r12 + sbb 8*2($nptr),%r13 + sbb 8*3($nptr),%r14 + lea 8*4($nptr),$nptr + mov %r11,8*0($rptr) + mov %r12,8*1($rptr) + mov %r13,8*2($rptr) + mov %r14,8*3($rptr) + lea 8*4($rptr),$rptr + dec $num # preserves %cf + jnz .Lmulx4x_sub + + sbb \$0,%r15 # top-most carry + lea 64(%rsp),$tptr + sub %rdx,$rptr # rewind + + movq %r15,%xmm1 + pxor %xmm0,%xmm0 + pshufd \$0,%xmm1,%xmm1 + mov 40(%rsp),%rsi # restore %rsp + jmp .Lmulx4x_cond_copy + +.align 32 +.Lmulx4x_cond_copy: + movdqa 16*0($tptr),%xmm2 + movdqa 16*1($tptr),%xmm3 + lea 16*2($tptr),$tptr + movdqu 16*0($rptr),%xmm4 + movdqu 16*1($rptr),%xmm5 + lea 16*2($rptr),$rptr + movdqa %xmm0,-16*2($tptr) # zero tp + movdqa %xmm0,-16*1($tptr) + pcmpeqd %xmm1,%xmm0 + pand %xmm1,%xmm2 + pand %xmm1,%xmm3 + pand %xmm0,%xmm4 + pand %xmm0,%xmm5 + pxor %xmm0,%xmm0 + por %xmm2,%xmm4 + por %xmm3,%xmm5 + movdqu %xmm4,-16*2($rptr) + movdqu %xmm5,-16*1($rptr) + sub \$32,%rdx + jnz .Lmulx4x_cond_copy + + mov %rdx,($tptr) + + mov \$1,%rax + mov -48(%rsi),%r15 + mov -40(%rsi),%r14 + mov -32(%rsi),%r13 + mov -24(%rsi),%r12 + mov -16(%rsi),%rbp + mov -8(%rsi),%rbx + lea (%rsi),%rsp +.Lmulx4x_epilogue: + ret +.size bn_mulx4x_mont,.-bn_mulx4x_mont +___ +}}} +$code.=<<___; +.asciz "Montgomery Multiplication for x86_64, CRYPTOGAMS by " +.align 16 +___ + +# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame, +# CONTEXT *context,DISPATCHER_CONTEXT *disp) +if ($win64) { +$rec="%rcx"; +$frame="%rdx"; +$context="%r8"; +$disp="%r9"; + +$code.=<<___; +.extern __imp_RtlVirtualUnwind +.type mul_handler,\@abi-omnipotent +.align 16 +mul_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + mov 8($disp),%rsi # disp->ImageBase + mov 56($disp),%r11 # disp->HandlerData + + mov 0(%r11),%r10d # HandlerData[0] + lea (%rsi,%r10),%r10 # end of prologue label + cmp %r10,%rbx # context->RipRsp + + mov 4(%r11),%r10d # HandlerData[1] + lea (%rsi,%r10),%r10 # epilogue label + cmp %r10,%rbx # context->Rip>=epilogue label + jae .Lcommon_seh_tail + + mov 192($context),%r10 # pull $num + mov 8(%rax,%r10,8),%rax # pull saved stack pointer + lea 48(%rax),%rax + + mov -8(%rax),%rbx + mov -16(%rax),%rbp + mov -24(%rax),%r12 + mov -32(%rax),%r13 + mov -40(%rax),%r14 + mov -48(%rax),%r15 + mov %rbx,144($context) # restore context->Rbx + mov %rbp,160($context) # restore context->Rbp + mov %r12,216($context) # restore context->R12 + mov %r13,224($context) # restore context->R13 + mov %r14,232($context) # restore context->R14 + mov %r15,240($context) # restore context->R15 + + jmp .Lcommon_seh_tail +.size mul_handler,.-mul_handler + +.type sqr_handler,\@abi-omnipotent +.align 16 +sqr_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + mov 8($disp),%rsi # disp->ImageBase + mov 56($disp),%r11 # disp->HandlerData + + mov 0(%r11),%r10d # HandlerData[0] + lea (%rsi,%r10),%r10 # end of prologue label + cmp %r10,%rbx # context->Rip<.Lsqr_body + jb .Lcommon_seh_tail + + mov 152($context),%rax # pull context->Rsp + + mov 4(%r11),%r10d # HandlerData[1] + lea (%rsi,%r10),%r10 # epilogue label + cmp %r10,%rbx # context->Rip>=.Lsqr_epilogue + jae .Lcommon_seh_tail + + mov 40(%rax),%rax # pull saved stack pointer + + mov -8(%rax),%rbx + mov -16(%rax),%rbp + mov -24(%rax),%r12 + mov -32(%rax),%r13 + mov -40(%rax),%r14 + mov -48(%rax),%r15 + mov %rbx,144($context) # restore context->Rbx + mov %rbp,160($context) # restore context->Rbp + mov %r12,216($context) # restore context->R12 + mov %r13,224($context) # restore context->R13 + mov %r14,232($context) # restore context->R14 + mov %r15,240($context) # restore context->R15 + +.Lcommon_seh_tail: + mov 8(%rax),%rdi + mov 16(%rax),%rsi + mov %rax,152($context) # restore context->Rsp + mov %rsi,168($context) # restore context->Rsi + mov %rdi,176($context) # restore context->Rdi + + mov 40($disp),%rdi # disp->ContextRecord + mov $context,%rsi # context + mov \$154,%ecx # sizeof(CONTEXT) + .long 0xa548f3fc # cld; rep movsq + + mov $disp,%rsi + xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER + mov 8(%rsi),%rdx # arg2, disp->ImageBase + mov 0(%rsi),%r8 # arg3, disp->ControlPc + mov 16(%rsi),%r9 # arg4, disp->FunctionEntry + mov 40(%rsi),%r10 # disp->ContextRecord + lea 56(%rsi),%r11 # &disp->HandlerData + lea 24(%rsi),%r12 # &disp->EstablisherFrame + mov %r10,32(%rsp) # arg5 + mov %r11,40(%rsp) # arg6 + mov %r12,48(%rsp) # arg7 + mov %rcx,56(%rsp) # arg8, (NULL) + call *__imp_RtlVirtualUnwind(%rip) + + mov \$1,%eax # ExceptionContinueSearch + add \$64,%rsp + popfq + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + pop %rdi + pop %rsi + ret +.size sqr_handler,.-sqr_handler + +.section .pdata +.align 4 + .rva .LSEH_begin_bn_mul_mont + .rva .LSEH_end_bn_mul_mont + .rva .LSEH_info_bn_mul_mont + + .rva .LSEH_begin_bn_mul4x_mont + .rva .LSEH_end_bn_mul4x_mont + .rva .LSEH_info_bn_mul4x_mont + + .rva .LSEH_begin_bn_sqr8x_mont + .rva .LSEH_end_bn_sqr8x_mont + .rva .LSEH_info_bn_sqr8x_mont +___ +$code.=<<___ if ($addx); + .rva .LSEH_begin_bn_mulx4x_mont + .rva .LSEH_end_bn_mulx4x_mont + .rva .LSEH_info_bn_mulx4x_mont +___ +$code.=<<___; +.section .xdata +.align 8 +.LSEH_info_bn_mul_mont: + .byte 9,0,0,0 + .rva mul_handler + .rva .Lmul_body,.Lmul_epilogue # HandlerData[] +.LSEH_info_bn_mul4x_mont: + .byte 9,0,0,0 + .rva mul_handler + .rva .Lmul4x_body,.Lmul4x_epilogue # HandlerData[] +.LSEH_info_bn_sqr8x_mont: + .byte 9,0,0,0 + .rva sqr_handler + .rva .Lsqr8x_body,.Lsqr8x_epilogue # HandlerData[] +___ +$code.=<<___ if ($addx); +.LSEH_info_bn_mulx4x_mont: + .byte 9,0,0,0 + .rva sqr_handler + .rva .Lmulx4x_body,.Lmulx4x_epilogue # HandlerData[] +___ +} + +print $code; +close STDOUT; diff --git a/external/boringssl/crypto/bn/asm/x86_64-mont5.pl b/external/boringssl/crypto/bn/asm/x86_64-mont5.pl new file mode 100755 index 0000000000..ced3acba51 --- /dev/null +++ b/external/boringssl/crypto/bn/asm/x86_64-mont5.pl @@ -0,0 +1,3669 @@ +#!/usr/bin/env perl + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== + +# August 2011. +# +# Companion to x86_64-mont.pl that optimizes cache-timing attack +# countermeasures. The subroutines are produced by replacing bp[i] +# references in their x86_64-mont.pl counterparts with cache-neutral +# references to powers table computed in BN_mod_exp_mont_consttime. +# In addition subroutine that scatters elements of the powers table +# is implemented, so that scatter-/gathering can be tuned without +# bn_exp.c modifications. + +# August 2013. +# +# Add MULX/AD*X code paths and additional interfaces to optimize for +# branch prediction unit. For input lengths that are multiples of 8 +# the np argument is not just modulus value, but one interleaved +# with 0. This is to optimize post-condition... + +$flavour = shift; +$output = shift; +if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } + +$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or +die "can't locate x86_64-xlate.pl"; + +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; + +# In upstream, this is controlled by shelling out to the compiler to check +# versions, but BoringSSL is intended to be used with pre-generated perlasm +# output, so this isn't useful anyway. +# +# TODO(davidben): Enable this after testing. $addx goes up to 1. +$addx = 0; + +# int bn_mul_mont_gather5( +$rp="%rdi"; # BN_ULONG *rp, +$ap="%rsi"; # const BN_ULONG *ap, +$bp="%rdx"; # const BN_ULONG *bp, +$np="%rcx"; # const BN_ULONG *np, +$n0="%r8"; # const BN_ULONG *n0, +$num="%r9"; # int num, + # int idx); # 0 to 2^5-1, "index" in $bp holding + # pre-computed powers of a', interlaced + # in such manner that b[0] is $bp[idx], + # b[1] is [2^5+idx], etc. +$lo0="%r10"; +$hi0="%r11"; +$hi1="%r13"; +$i="%r14"; +$j="%r15"; +$m0="%rbx"; +$m1="%rbp"; + +$code=<<___; +.text + +.extern OPENSSL_ia32cap_P + +.globl bn_mul_mont_gather5 +.type bn_mul_mont_gather5,\@function,6 +.align 64 +bn_mul_mont_gather5: + test \$7,${num}d + jnz .Lmul_enter +___ +$code.=<<___ if ($addx); + mov OPENSSL_ia32cap_P+8(%rip),%r11d +___ +$code.=<<___; + jmp .Lmul4x_enter + +.align 16 +.Lmul_enter: + mov ${num}d,${num}d + mov %rsp,%rax + movd `($win64?56:8)`(%rsp),%xmm5 # load 7th argument + lea .Linc(%rip),%r10 + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + + lea 2($num),%r11 + neg %r11 + lea -264(%rsp,%r11,8),%rsp # tp=alloca(8*(num+2)+256+8) + and \$-1024,%rsp # minimize TLB usage + + mov %rax,8(%rsp,$num,8) # tp[num+1]=%rsp +.Lmul_body: + lea 128($bp),%r12 # reassign $bp (+size optimization) +___ + $bp="%r12"; + $STRIDE=2**5*8; # 5 is "window size" + $N=$STRIDE/4; # should match cache line size +$code.=<<___; + movdqa 0(%r10),%xmm0 # 00000001000000010000000000000000 + movdqa 16(%r10),%xmm1 # 00000002000000020000000200000002 + lea 24-112(%rsp,$num,8),%r10# place the mask after tp[num+3] (+ICache optimization) + and \$-16,%r10 + + pshufd \$0,%xmm5,%xmm5 # broadcast index + movdqa %xmm1,%xmm4 + movdqa %xmm1,%xmm2 +___ +######################################################################## +# calculate mask by comparing 0..31 to index and save result to stack +# +$code.=<<___; + paddd %xmm0,%xmm1 + pcmpeqd %xmm5,%xmm0 # compare to 1,0 + .byte 0x67 + movdqa %xmm4,%xmm3 +___ +for($k=0;$k<$STRIDE/16-4;$k+=4) { +$code.=<<___; + paddd %xmm1,%xmm2 + pcmpeqd %xmm5,%xmm1 # compare to 3,2 + movdqa %xmm0,`16*($k+0)+112`(%r10) + movdqa %xmm4,%xmm0 + + paddd %xmm2,%xmm3 + pcmpeqd %xmm5,%xmm2 # compare to 5,4 + movdqa %xmm1,`16*($k+1)+112`(%r10) + movdqa %xmm4,%xmm1 + + paddd %xmm3,%xmm0 + pcmpeqd %xmm5,%xmm3 # compare to 7,6 + movdqa %xmm2,`16*($k+2)+112`(%r10) + movdqa %xmm4,%xmm2 + + paddd %xmm0,%xmm1 + pcmpeqd %xmm5,%xmm0 + movdqa %xmm3,`16*($k+3)+112`(%r10) + movdqa %xmm4,%xmm3 +___ +} +$code.=<<___; # last iteration can be optimized + paddd %xmm1,%xmm2 + pcmpeqd %xmm5,%xmm1 + movdqa %xmm0,`16*($k+0)+112`(%r10) + + paddd %xmm2,%xmm3 + .byte 0x67 + pcmpeqd %xmm5,%xmm2 + movdqa %xmm1,`16*($k+1)+112`(%r10) + + pcmpeqd %xmm5,%xmm3 + movdqa %xmm2,`16*($k+2)+112`(%r10) + pand `16*($k+0)-128`($bp),%xmm0 # while it's still in register + + pand `16*($k+1)-128`($bp),%xmm1 + pand `16*($k+2)-128`($bp),%xmm2 + movdqa %xmm3,`16*($k+3)+112`(%r10) + pand `16*($k+3)-128`($bp),%xmm3 + por %xmm2,%xmm0 + por %xmm3,%xmm1 +___ +for($k=0;$k<$STRIDE/16-4;$k+=4) { +$code.=<<___; + movdqa `16*($k+0)-128`($bp),%xmm4 + movdqa `16*($k+1)-128`($bp),%xmm5 + movdqa `16*($k+2)-128`($bp),%xmm2 + pand `16*($k+0)+112`(%r10),%xmm4 + movdqa `16*($k+3)-128`($bp),%xmm3 + pand `16*($k+1)+112`(%r10),%xmm5 + por %xmm4,%xmm0 + pand `16*($k+2)+112`(%r10),%xmm2 + por %xmm5,%xmm1 + pand `16*($k+3)+112`(%r10),%xmm3 + por %xmm2,%xmm0 + por %xmm3,%xmm1 +___ +} +$code.=<<___; + por %xmm1,%xmm0 + pshufd \$0x4e,%xmm0,%xmm1 + por %xmm1,%xmm0 + lea $STRIDE($bp),$bp + movq %xmm0,$m0 # m0=bp[0] + + mov ($n0),$n0 # pull n0[0] value + mov ($ap),%rax + + xor $i,$i # i=0 + xor $j,$j # j=0 + + mov $n0,$m1 + mulq $m0 # ap[0]*bp[0] + mov %rax,$lo0 + mov ($np),%rax + + imulq $lo0,$m1 # "tp[0]"*n0 + mov %rdx,$hi0 + + mulq $m1 # np[0]*m1 + add %rax,$lo0 # discarded + mov 8($ap),%rax + adc \$0,%rdx + mov %rdx,$hi1 + + lea 1($j),$j # j++ + jmp .L1st_enter + +.align 16 +.L1st: + add %rax,$hi1 + mov ($ap,$j,8),%rax + adc \$0,%rdx + add $hi0,$hi1 # np[j]*m1+ap[j]*bp[0] + mov $lo0,$hi0 + adc \$0,%rdx + mov $hi1,-16(%rsp,$j,8) # tp[j-1] + mov %rdx,$hi1 + +.L1st_enter: + mulq $m0 # ap[j]*bp[0] + add %rax,$hi0 + mov ($np,$j,8),%rax + adc \$0,%rdx + lea 1($j),$j # j++ + mov %rdx,$lo0 + + mulq $m1 # np[j]*m1 + cmp $num,$j + jne .L1st # note that upon exit $j==$num, so + # they can be used interchangeably + + add %rax,$hi1 + adc \$0,%rdx + add $hi0,$hi1 # np[j]*m1+ap[j]*bp[0] + adc \$0,%rdx + mov $hi1,-16(%rsp,$num,8) # tp[num-1] + mov %rdx,$hi1 + mov $lo0,$hi0 + + xor %rdx,%rdx + add $hi0,$hi1 + adc \$0,%rdx + mov $hi1,-8(%rsp,$num,8) + mov %rdx,(%rsp,$num,8) # store upmost overflow bit + + lea 1($i),$i # i++ + jmp .Louter +.align 16 +.Louter: + lea 24+128(%rsp,$num,8),%rdx # where 256-byte mask is (+size optimization) + and \$-16,%rdx + pxor %xmm4,%xmm4 + pxor %xmm5,%xmm5 +___ +for($k=0;$k<$STRIDE/16;$k+=4) { +$code.=<<___; + movdqa `16*($k+0)-128`($bp),%xmm0 + movdqa `16*($k+1)-128`($bp),%xmm1 + movdqa `16*($k+2)-128`($bp),%xmm2 + movdqa `16*($k+3)-128`($bp),%xmm3 + pand `16*($k+0)-128`(%rdx),%xmm0 + pand `16*($k+1)-128`(%rdx),%xmm1 + por %xmm0,%xmm4 + pand `16*($k+2)-128`(%rdx),%xmm2 + por %xmm1,%xmm5 + pand `16*($k+3)-128`(%rdx),%xmm3 + por %xmm2,%xmm4 + por %xmm3,%xmm5 +___ +} +$code.=<<___; + por %xmm5,%xmm4 + pshufd \$0x4e,%xmm4,%xmm0 + por %xmm4,%xmm0 + lea $STRIDE($bp),$bp + + mov ($ap),%rax # ap[0] + movq %xmm0,$m0 # m0=bp[i] + + xor $j,$j # j=0 + mov $n0,$m1 + mov (%rsp),$lo0 + + mulq $m0 # ap[0]*bp[i] + add %rax,$lo0 # ap[0]*bp[i]+tp[0] + mov ($np),%rax + adc \$0,%rdx + + imulq $lo0,$m1 # tp[0]*n0 + mov %rdx,$hi0 + + mulq $m1 # np[0]*m1 + add %rax,$lo0 # discarded + mov 8($ap),%rax + adc \$0,%rdx + mov 8(%rsp),$lo0 # tp[1] + mov %rdx,$hi1 + + lea 1($j),$j # j++ + jmp .Linner_enter + +.align 16 +.Linner: + add %rax,$hi1 + mov ($ap,$j,8),%rax + adc \$0,%rdx + add $lo0,$hi1 # np[j]*m1+ap[j]*bp[i]+tp[j] + mov (%rsp,$j,8),$lo0 + adc \$0,%rdx + mov $hi1,-16(%rsp,$j,8) # tp[j-1] + mov %rdx,$hi1 + +.Linner_enter: + mulq $m0 # ap[j]*bp[i] + add %rax,$hi0 + mov ($np,$j,8),%rax + adc \$0,%rdx + add $hi0,$lo0 # ap[j]*bp[i]+tp[j] + mov %rdx,$hi0 + adc \$0,$hi0 + lea 1($j),$j # j++ + + mulq $m1 # np[j]*m1 + cmp $num,$j + jne .Linner # note that upon exit $j==$num, so + # they can be used interchangeably + add %rax,$hi1 + adc \$0,%rdx + add $lo0,$hi1 # np[j]*m1+ap[j]*bp[i]+tp[j] + mov (%rsp,$num,8),$lo0 + adc \$0,%rdx + mov $hi1,-16(%rsp,$num,8) # tp[num-1] + mov %rdx,$hi1 + + xor %rdx,%rdx + add $hi0,$hi1 + adc \$0,%rdx + add $lo0,$hi1 # pull upmost overflow bit + adc \$0,%rdx + mov $hi1,-8(%rsp,$num,8) + mov %rdx,(%rsp,$num,8) # store upmost overflow bit + + lea 1($i),$i # i++ + cmp $num,$i + jb .Louter + + xor $i,$i # i=0 and clear CF! + mov (%rsp),%rax # tp[0] + lea (%rsp),$ap # borrow ap for tp + mov $num,$j # j=num + jmp .Lsub +.align 16 +.Lsub: sbb ($np,$i,8),%rax + mov %rax,($rp,$i,8) # rp[i]=tp[i]-np[i] + mov 8($ap,$i,8),%rax # tp[i+1] + lea 1($i),$i # i++ + dec $j # doesnn't affect CF! + jnz .Lsub + + sbb \$0,%rax # handle upmost overflow bit + xor $i,$i + mov $num,$j # j=num +.align 16 +.Lcopy: # copy or in-place refresh + mov (%rsp,$i,8),$ap + mov ($rp,$i,8),$np + xor $np,$ap # conditional select: + and %rax,$ap # ((ap ^ np) & %rax) ^ np + xor $np,$ap # ap = borrow?tp:rp + mov $i,(%rsp,$i,8) # zap temporary vector + mov $ap,($rp,$i,8) # rp[i]=tp[i] + lea 1($i),$i + sub \$1,$j + jnz .Lcopy + + mov 8(%rsp,$num,8),%rsi # restore %rsp + mov \$1,%rax + + mov -48(%rsi),%r15 + mov -40(%rsi),%r14 + mov -32(%rsi),%r13 + mov -24(%rsi),%r12 + mov -16(%rsi),%rbp + mov -8(%rsi),%rbx + lea (%rsi),%rsp +.Lmul_epilogue: + ret +.size bn_mul_mont_gather5,.-bn_mul_mont_gather5 +___ +{{{ +my @A=("%r10","%r11"); +my @N=("%r13","%rdi"); +$code.=<<___; +.type bn_mul4x_mont_gather5,\@function,6 +.align 32 +bn_mul4x_mont_gather5: +.Lmul4x_enter: +___ +$code.=<<___ if ($addx); + and \$0x80108,%r11d + cmp \$0x80108,%r11d # check for AD*X+BMI2+BMI1 + je .Lmulx4x_enter +___ +$code.=<<___; + .byte 0x67 + mov %rsp,%rax + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + + .byte 0x67 + shl \$3,${num}d # convert $num to bytes + lea ($num,$num,2),%r10 # 3*$num in bytes + neg $num # -$num + + ############################################################## + # Ensure that stack frame doesn't alias with $rptr+3*$num + # modulo 4096, which covers ret[num], am[num] and n[num] + # (see bn_exp.c). This is done to allow memory disambiguation + # logic do its magic. [Extra [num] is allocated in order + # to align with bn_power5's frame, which is cleansed after + # completing exponentiation. Extra 256 bytes is for power mask + # calculated from 7th argument, the index.] + # + lea -320(%rsp,$num,2),%r11 + sub $rp,%r11 + and \$4095,%r11 + cmp %r11,%r10 + jb .Lmul4xsp_alt + sub %r11,%rsp # align with $rp + lea -320(%rsp,$num,2),%rsp # alloca(frame+2*num*8+256) + jmp .Lmul4xsp_done + +.align 32 +.Lmul4xsp_alt: + lea 4096-320(,$num,2),%r10 + lea -320(%rsp,$num,2),%rsp # alloca(frame+2*num*8+256) + sub %r10,%r11 + mov \$0,%r10 + cmovc %r10,%r11 + sub %r11,%rsp +.Lmul4xsp_done: + and \$-64,%rsp + neg $num + + mov %rax,40(%rsp) +.Lmul4x_body: + + call mul4x_internal + + mov 40(%rsp),%rsi # restore %rsp + mov \$1,%rax + + mov -48(%rsi),%r15 + mov -40(%rsi),%r14 + mov -32(%rsi),%r13 + mov -24(%rsi),%r12 + mov -16(%rsi),%rbp + mov -8(%rsi),%rbx + lea (%rsi),%rsp +.Lmul4x_epilogue: + ret +.size bn_mul4x_mont_gather5,.-bn_mul4x_mont_gather5 + +.type mul4x_internal,\@abi-omnipotent +.align 32 +mul4x_internal: + shl \$5,$num # $num was in bytes + movd `($win64?56:8)`(%rax),%xmm5 # load 7th argument, index + lea .Linc(%rip),%rax + lea 128(%rdx,$num),%r13 # end of powers table (+size optimization) + shr \$5,$num # restore $num +___ + $bp="%r12"; + $STRIDE=2**5*8; # 5 is "window size" + $N=$STRIDE/4; # should match cache line size + $tp=$i; +$code.=<<___; + movdqa 0(%rax),%xmm0 # 00000001000000010000000000000000 + movdqa 16(%rax),%xmm1 # 00000002000000020000000200000002 + lea 88-112(%rsp,$num),%r10 # place the mask after tp[num+1] (+ICache optimization) + lea 128(%rdx),$bp # size optimization + + pshufd \$0,%xmm5,%xmm5 # broadcast index + movdqa %xmm1,%xmm4 + .byte 0x67,0x67 + movdqa %xmm1,%xmm2 +___ +######################################################################## +# calculate mask by comparing 0..31 to index and save result to stack +# +$code.=<<___; + paddd %xmm0,%xmm1 + pcmpeqd %xmm5,%xmm0 # compare to 1,0 + .byte 0x67 + movdqa %xmm4,%xmm3 +___ +for($i=0;$i<$STRIDE/16-4;$i+=4) { +$code.=<<___; + paddd %xmm1,%xmm2 + pcmpeqd %xmm5,%xmm1 # compare to 3,2 + movdqa %xmm0,`16*($i+0)+112`(%r10) + movdqa %xmm4,%xmm0 + + paddd %xmm2,%xmm3 + pcmpeqd %xmm5,%xmm2 # compare to 5,4 + movdqa %xmm1,`16*($i+1)+112`(%r10) + movdqa %xmm4,%xmm1 + + paddd %xmm3,%xmm0 + pcmpeqd %xmm5,%xmm3 # compare to 7,6 + movdqa %xmm2,`16*($i+2)+112`(%r10) + movdqa %xmm4,%xmm2 + + paddd %xmm0,%xmm1 + pcmpeqd %xmm5,%xmm0 + movdqa %xmm3,`16*($i+3)+112`(%r10) + movdqa %xmm4,%xmm3 +___ +} +$code.=<<___; # last iteration can be optimized + paddd %xmm1,%xmm2 + pcmpeqd %xmm5,%xmm1 + movdqa %xmm0,`16*($i+0)+112`(%r10) + + paddd %xmm2,%xmm3 + .byte 0x67 + pcmpeqd %xmm5,%xmm2 + movdqa %xmm1,`16*($i+1)+112`(%r10) + + pcmpeqd %xmm5,%xmm3 + movdqa %xmm2,`16*($i+2)+112`(%r10) + pand `16*($i+0)-128`($bp),%xmm0 # while it's still in register + + pand `16*($i+1)-128`($bp),%xmm1 + pand `16*($i+2)-128`($bp),%xmm2 + movdqa %xmm3,`16*($i+3)+112`(%r10) + pand `16*($i+3)-128`($bp),%xmm3 + por %xmm2,%xmm0 + por %xmm3,%xmm1 +___ +for($i=0;$i<$STRIDE/16-4;$i+=4) { +$code.=<<___; + movdqa `16*($i+0)-128`($bp),%xmm4 + movdqa `16*($i+1)-128`($bp),%xmm5 + movdqa `16*($i+2)-128`($bp),%xmm2 + pand `16*($i+0)+112`(%r10),%xmm4 + movdqa `16*($i+3)-128`($bp),%xmm3 + pand `16*($i+1)+112`(%r10),%xmm5 + por %xmm4,%xmm0 + pand `16*($i+2)+112`(%r10),%xmm2 + por %xmm5,%xmm1 + pand `16*($i+3)+112`(%r10),%xmm3 + por %xmm2,%xmm0 + por %xmm3,%xmm1 +___ +} +$code.=<<___; + por %xmm1,%xmm0 + pshufd \$0x4e,%xmm0,%xmm1 + por %xmm1,%xmm0 + lea $STRIDE($bp),$bp + movq %xmm0,$m0 # m0=bp[0] + + mov %r13,16+8(%rsp) # save end of b[num] + mov $rp, 56+8(%rsp) # save $rp + + mov ($n0),$n0 # pull n0[0] value + mov ($ap),%rax + lea ($ap,$num),$ap # end of a[num] + neg $num + + mov $n0,$m1 + mulq $m0 # ap[0]*bp[0] + mov %rax,$A[0] + mov ($np),%rax + + imulq $A[0],$m1 # "tp[0]"*n0 + lea 64+8(%rsp),$tp + mov %rdx,$A[1] + + mulq $m1 # np[0]*m1 + add %rax,$A[0] # discarded + mov 8($ap,$num),%rax + adc \$0,%rdx + mov %rdx,$N[1] + + mulq $m0 + add %rax,$A[1] + mov 8*1($np),%rax + adc \$0,%rdx + mov %rdx,$A[0] + + mulq $m1 + add %rax,$N[1] + mov 16($ap,$num),%rax + adc \$0,%rdx + add $A[1],$N[1] + lea 4*8($num),$j # j=4 + lea 8*4($np),$np + adc \$0,%rdx + mov $N[1],($tp) + mov %rdx,$N[0] + jmp .L1st4x + +.align 32 +.L1st4x: + mulq $m0 # ap[j]*bp[0] + add %rax,$A[0] + mov -8*2($np),%rax + lea 32($tp),$tp + adc \$0,%rdx + mov %rdx,$A[1] + + mulq $m1 # np[j]*m1 + add %rax,$N[0] + mov -8($ap,$j),%rax + adc \$0,%rdx + add $A[0],$N[0] # np[j]*m1+ap[j]*bp[0] + adc \$0,%rdx + mov $N[0],-24($tp) # tp[j-1] + mov %rdx,$N[1] + + mulq $m0 # ap[j]*bp[0] + add %rax,$A[1] + mov -8*1($np),%rax + adc \$0,%rdx + mov %rdx,$A[0] + + mulq $m1 # np[j]*m1 + add %rax,$N[1] + mov ($ap,$j),%rax + adc \$0,%rdx + add $A[1],$N[1] # np[j]*m1+ap[j]*bp[0] + adc \$0,%rdx + mov $N[1],-16($tp) # tp[j-1] + mov %rdx,$N[0] + + mulq $m0 # ap[j]*bp[0] + add %rax,$A[0] + mov 8*0($np),%rax + adc \$0,%rdx + mov %rdx,$A[1] + + mulq $m1 # np[j]*m1 + add %rax,$N[0] + mov 8($ap,$j),%rax + adc \$0,%rdx + add $A[0],$N[0] # np[j]*m1+ap[j]*bp[0] + adc \$0,%rdx + mov $N[0],-8($tp) # tp[j-1] + mov %rdx,$N[1] + + mulq $m0 # ap[j]*bp[0] + add %rax,$A[1] + mov 8*1($np),%rax + adc \$0,%rdx + mov %rdx,$A[0] + + mulq $m1 # np[j]*m1 + add %rax,$N[1] + mov 16($ap,$j),%rax + adc \$0,%rdx + add $A[1],$N[1] # np[j]*m1+ap[j]*bp[0] + lea 8*4($np),$np + adc \$0,%rdx + mov $N[1],($tp) # tp[j-1] + mov %rdx,$N[0] + + add \$32,$j # j+=4 + jnz .L1st4x + + mulq $m0 # ap[j]*bp[0] + add %rax,$A[0] + mov -8*2($np),%rax + lea 32($tp),$tp + adc \$0,%rdx + mov %rdx,$A[1] + + mulq $m1 # np[j]*m1 + add %rax,$N[0] + mov -8($ap),%rax + adc \$0,%rdx + add $A[0],$N[0] # np[j]*m1+ap[j]*bp[0] + adc \$0,%rdx + mov $N[0],-24($tp) # tp[j-1] + mov %rdx,$N[1] + + mulq $m0 # ap[j]*bp[0] + add %rax,$A[1] + mov -8*1($np),%rax + adc \$0,%rdx + mov %rdx,$A[0] + + mulq $m1 # np[j]*m1 + add %rax,$N[1] + mov ($ap,$num),%rax # ap[0] + adc \$0,%rdx + add $A[1],$N[1] # np[j]*m1+ap[j]*bp[0] + adc \$0,%rdx + mov $N[1],-16($tp) # tp[j-1] + mov %rdx,$N[0] + + lea ($np,$num),$np # rewind $np + + xor $N[1],$N[1] + add $A[0],$N[0] + adc \$0,$N[1] + mov $N[0],-8($tp) + + jmp .Louter4x + +.align 32 +.Louter4x: + lea 16+128($tp),%rdx # where 256-byte mask is (+size optimization) + pxor %xmm4,%xmm4 + pxor %xmm5,%xmm5 +___ +for($i=0;$i<$STRIDE/16;$i+=4) { +$code.=<<___; + movdqa `16*($i+0)-128`($bp),%xmm0 + movdqa `16*($i+1)-128`($bp),%xmm1 + movdqa `16*($i+2)-128`($bp),%xmm2 + movdqa `16*($i+3)-128`($bp),%xmm3 + pand `16*($i+0)-128`(%rdx),%xmm0 + pand `16*($i+1)-128`(%rdx),%xmm1 + por %xmm0,%xmm4 + pand `16*($i+2)-128`(%rdx),%xmm2 + por %xmm1,%xmm5 + pand `16*($i+3)-128`(%rdx),%xmm3 + por %xmm2,%xmm4 + por %xmm3,%xmm5 +___ +} +$code.=<<___; + por %xmm5,%xmm4 + pshufd \$0x4e,%xmm4,%xmm0 + por %xmm4,%xmm0 + lea $STRIDE($bp),$bp + movq %xmm0,$m0 # m0=bp[i] + + mov ($tp,$num),$A[0] + mov $n0,$m1 + mulq $m0 # ap[0]*bp[i] + add %rax,$A[0] # ap[0]*bp[i]+tp[0] + mov ($np),%rax + adc \$0,%rdx + + imulq $A[0],$m1 # tp[0]*n0 + mov %rdx,$A[1] + mov $N[1],($tp) # store upmost overflow bit + + lea ($tp,$num),$tp # rewind $tp + + mulq $m1 # np[0]*m1 + add %rax,$A[0] # "$N[0]", discarded + mov 8($ap,$num),%rax + adc \$0,%rdx + mov %rdx,$N[1] + + mulq $m0 # ap[j]*bp[i] + add %rax,$A[1] + mov 8*1($np),%rax + adc \$0,%rdx + add 8($tp),$A[1] # +tp[1] + adc \$0,%rdx + mov %rdx,$A[0] + + mulq $m1 # np[j]*m1 + add %rax,$N[1] + mov 16($ap,$num),%rax + adc \$0,%rdx + add $A[1],$N[1] # np[j]*m1+ap[j]*bp[i]+tp[j] + lea 4*8($num),$j # j=4 + lea 8*4($np),$np + adc \$0,%rdx + mov %rdx,$N[0] + jmp .Linner4x + +.align 32 +.Linner4x: + mulq $m0 # ap[j]*bp[i] + add %rax,$A[0] + mov -8*2($np),%rax + adc \$0,%rdx + add 16($tp),$A[0] # ap[j]*bp[i]+tp[j] + lea 32($tp),$tp + adc \$0,%rdx + mov %rdx,$A[1] + + mulq $m1 # np[j]*m1 + add %rax,$N[0] + mov -8($ap,$j),%rax + adc \$0,%rdx + add $A[0],$N[0] + adc \$0,%rdx + mov $N[1],-32($tp) # tp[j-1] + mov %rdx,$N[1] + + mulq $m0 # ap[j]*bp[i] + add %rax,$A[1] + mov -8*1($np),%rax + adc \$0,%rdx + add -8($tp),$A[1] + adc \$0,%rdx + mov %rdx,$A[0] + + mulq $m1 # np[j]*m1 + add %rax,$N[1] + mov ($ap,$j),%rax + adc \$0,%rdx + add $A[1],$N[1] + adc \$0,%rdx + mov $N[0],-24($tp) # tp[j-1] + mov %rdx,$N[0] + + mulq $m0 # ap[j]*bp[i] + add %rax,$A[0] + mov 8*0($np),%rax + adc \$0,%rdx + add ($tp),$A[0] # ap[j]*bp[i]+tp[j] + adc \$0,%rdx + mov %rdx,$A[1] + + mulq $m1 # np[j]*m1 + add %rax,$N[0] + mov 8($ap,$j),%rax + adc \$0,%rdx + add $A[0],$N[0] + adc \$0,%rdx + mov $N[1],-16($tp) # tp[j-1] + mov %rdx,$N[1] + + mulq $m0 # ap[j]*bp[i] + add %rax,$A[1] + mov 8*1($np),%rax + adc \$0,%rdx + add 8($tp),$A[1] + adc \$0,%rdx + mov %rdx,$A[0] + + mulq $m1 # np[j]*m1 + add %rax,$N[1] + mov 16($ap,$j),%rax + adc \$0,%rdx + add $A[1],$N[1] + lea 8*4($np),$np + adc \$0,%rdx + mov $N[0],-8($tp) # tp[j-1] + mov %rdx,$N[0] + + add \$32,$j # j+=4 + jnz .Linner4x + + mulq $m0 # ap[j]*bp[i] + add %rax,$A[0] + mov -8*2($np),%rax + adc \$0,%rdx + add 16($tp),$A[0] # ap[j]*bp[i]+tp[j] + lea 32($tp),$tp + adc \$0,%rdx + mov %rdx,$A[1] + + mulq $m1 # np[j]*m1 + add %rax,$N[0] + mov -8($ap),%rax + adc \$0,%rdx + add $A[0],$N[0] + adc \$0,%rdx + mov $N[1],-32($tp) # tp[j-1] + mov %rdx,$N[1] + + mulq $m0 # ap[j]*bp[i] + add %rax,$A[1] + mov $m1,%rax + mov -8*1($np),$m1 + adc \$0,%rdx + add -8($tp),$A[1] + adc \$0,%rdx + mov %rdx,$A[0] + + mulq $m1 # np[j]*m1 + add %rax,$N[1] + mov ($ap,$num),%rax # ap[0] + adc \$0,%rdx + add $A[1],$N[1] + adc \$0,%rdx + mov $N[0],-24($tp) # tp[j-1] + mov %rdx,$N[0] + + mov $N[1],-16($tp) # tp[j-1] + lea ($np,$num),$np # rewind $np + + xor $N[1],$N[1] + add $A[0],$N[0] + adc \$0,$N[1] + add ($tp),$N[0] # pull upmost overflow bit + adc \$0,$N[1] # upmost overflow bit + mov $N[0],-8($tp) + + cmp 16+8(%rsp),$bp + jb .Louter4x +___ +if (1) { +$code.=<<___; + xor %rax,%rax + sub $N[0],$m1 # compare top-most words + adc $j,$j # $j is zero + or $j,$N[1] + sub $N[1],%rax # %rax=-$N[1] + lea ($tp,$num),%rbx # tptr in .sqr4x_sub + mov ($np),%r12 + lea ($np),%rbp # nptr in .sqr4x_sub + mov %r9,%rcx + sar \$3+2,%rcx + mov 56+8(%rsp),%rdi # rptr in .sqr4x_sub + dec %r12 # so that after 'not' we get -n[0] + xor %r10,%r10 + mov 8*1(%rbp),%r13 + mov 8*2(%rbp),%r14 + mov 8*3(%rbp),%r15 + jmp .Lsqr4x_sub_entry +___ +} else { +my @ri=("%rax",$bp,$m0,$m1); +my $rp="%rdx"; +$code.=<<___ + xor \$1,$N[1] + lea ($tp,$num),$tp # rewind $tp + sar \$5,$num # cf=0 + lea ($np,$N[1],8),$np + mov 56+8(%rsp),$rp # restore $rp + jmp .Lsub4x + +.align 32 +.Lsub4x: + .byte 0x66 + mov 8*0($tp),@ri[0] + mov 8*1($tp),@ri[1] + .byte 0x66 + sbb 16*0($np),@ri[0] + mov 8*2($tp),@ri[2] + sbb 16*1($np),@ri[1] + mov 3*8($tp),@ri[3] + lea 4*8($tp),$tp + sbb 16*2($np),@ri[2] + mov @ri[0],8*0($rp) + sbb 16*3($np),@ri[3] + lea 16*4($np),$np + mov @ri[1],8*1($rp) + mov @ri[2],8*2($rp) + mov @ri[3],8*3($rp) + lea 8*4($rp),$rp + + inc $num + jnz .Lsub4x + + ret +___ +} +$code.=<<___; +.size mul4x_internal,.-mul4x_internal +___ +}}} + {{{ +###################################################################### +# void bn_power5( +my $rptr="%rdi"; # BN_ULONG *rptr, +my $aptr="%rsi"; # const BN_ULONG *aptr, +my $bptr="%rdx"; # const void *table, +my $nptr="%rcx"; # const BN_ULONG *nptr, +my $n0 ="%r8"; # const BN_ULONG *n0); +my $num ="%r9"; # int num, has to be divisible by 8 + # int pwr + +my ($i,$j,$tptr)=("%rbp","%rcx",$rptr); +my @A0=("%r10","%r11"); +my @A1=("%r12","%r13"); +my ($a0,$a1,$ai)=("%r14","%r15","%rbx"); + +$code.=<<___; +.globl bn_power5 +.type bn_power5,\@function,6 +.align 32 +bn_power5: +___ +$code.=<<___ if ($addx); + mov OPENSSL_ia32cap_P+8(%rip),%r11d + and \$0x80108,%r11d + cmp \$0x80108,%r11d # check for AD*X+BMI2+BMI1 + je .Lpowerx5_enter +___ +$code.=<<___; + mov %rsp,%rax + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + + shl \$3,${num}d # convert $num to bytes + lea ($num,$num,2),%r10d # 3*$num + neg $num + mov ($n0),$n0 # *n0 + + ############################################################## + # Ensure that stack frame doesn't alias with $rptr+3*$num + # modulo 4096, which covers ret[num], am[num] and n[num] + # (see bn_exp.c). This is done to allow memory disambiguation + # logic do its magic. [Extra 256 bytes is for power mask + # calculated from 7th argument, the index.] + # + lea -320(%rsp,$num,2),%r11 + sub $rptr,%r11 + and \$4095,%r11 + cmp %r11,%r10 + jb .Lpwr_sp_alt + sub %r11,%rsp # align with $aptr + lea -320(%rsp,$num,2),%rsp # alloca(frame+2*num*8+256) + jmp .Lpwr_sp_done + +.align 32 +.Lpwr_sp_alt: + lea 4096-320(,$num,2),%r10 + lea -320(%rsp,$num,2),%rsp # alloca(frame+2*num*8+256) + sub %r10,%r11 + mov \$0,%r10 + cmovc %r10,%r11 + sub %r11,%rsp +.Lpwr_sp_done: + and \$-64,%rsp + mov $num,%r10 + neg $num + + ############################################################## + # Stack layout + # + # +0 saved $num, used in reduction section + # +8 &t[2*$num], used in reduction section + # +32 saved *n0 + # +40 saved %rsp + # +48 t[2*$num] + # + mov $n0, 32(%rsp) + mov %rax, 40(%rsp) # save original %rsp +.Lpower5_body: + movq $rptr,%xmm1 # save $rptr, used in sqr8x + movq $nptr,%xmm2 # save $nptr + movq %r10, %xmm3 # -$num, used in sqr8x + movq $bptr,%xmm4 + + call __bn_sqr8x_internal + call __bn_post4x_internal + call __bn_sqr8x_internal + call __bn_post4x_internal + call __bn_sqr8x_internal + call __bn_post4x_internal + call __bn_sqr8x_internal + call __bn_post4x_internal + call __bn_sqr8x_internal + call __bn_post4x_internal + + movq %xmm2,$nptr + movq %xmm4,$bptr + mov $aptr,$rptr + mov 40(%rsp),%rax + lea 32(%rsp),$n0 + + call mul4x_internal + + mov 40(%rsp),%rsi # restore %rsp + mov \$1,%rax + mov -48(%rsi),%r15 + mov -40(%rsi),%r14 + mov -32(%rsi),%r13 + mov -24(%rsi),%r12 + mov -16(%rsi),%rbp + mov -8(%rsi),%rbx + lea (%rsi),%rsp +.Lpower5_epilogue: + ret +.size bn_power5,.-bn_power5 + +.globl bn_sqr8x_internal +.hidden bn_sqr8x_internal +.type bn_sqr8x_internal,\@abi-omnipotent +.align 32 +bn_sqr8x_internal: +__bn_sqr8x_internal: + ############################################################## + # Squaring part: + # + # a) multiply-n-add everything but a[i]*a[i]; + # b) shift result of a) by 1 to the left and accumulate + # a[i]*a[i] products; + # + ############################################################## + # a[1]a[0] + # a[2]a[0] + # a[3]a[0] + # a[2]a[1] + # a[4]a[0] + # a[3]a[1] + # a[5]a[0] + # a[4]a[1] + # a[3]a[2] + # a[6]a[0] + # a[5]a[1] + # a[4]a[2] + # a[7]a[0] + # a[6]a[1] + # a[5]a[2] + # a[4]a[3] + # a[7]a[1] + # a[6]a[2] + # a[5]a[3] + # a[7]a[2] + # a[6]a[3] + # a[5]a[4] + # a[7]a[3] + # a[6]a[4] + # a[7]a[4] + # a[6]a[5] + # a[7]a[5] + # a[7]a[6] + # a[1]a[0] + # a[2]a[0] + # a[3]a[0] + # a[4]a[0] + # a[5]a[0] + # a[6]a[0] + # a[7]a[0] + # a[2]a[1] + # a[3]a[1] + # a[4]a[1] + # a[5]a[1] + # a[6]a[1] + # a[7]a[1] + # a[3]a[2] + # a[4]a[2] + # a[5]a[2] + # a[6]a[2] + # a[7]a[2] + # a[4]a[3] + # a[5]a[3] + # a[6]a[3] + # a[7]a[3] + # a[5]a[4] + # a[6]a[4] + # a[7]a[4] + # a[6]a[5] + # a[7]a[5] + # a[7]a[6] + # a[0]a[0] + # a[1]a[1] + # a[2]a[2] + # a[3]a[3] + # a[4]a[4] + # a[5]a[5] + # a[6]a[6] + # a[7]a[7] + + lea 32(%r10),$i # $i=-($num-32) + lea ($aptr,$num),$aptr # end of a[] buffer, ($aptr,$i)=&ap[2] + + mov $num,$j # $j=$num + + # comments apply to $num==8 case + mov -32($aptr,$i),$a0 # a[0] + lea 48+8(%rsp,$num,2),$tptr # end of tp[] buffer, &tp[2*$num] + mov -24($aptr,$i),%rax # a[1] + lea -32($tptr,$i),$tptr # end of tp[] window, &tp[2*$num-"$i"] + mov -16($aptr,$i),$ai # a[2] + mov %rax,$a1 + + mul $a0 # a[1]*a[0] + mov %rax,$A0[0] # a[1]*a[0] + mov $ai,%rax # a[2] + mov %rdx,$A0[1] + mov $A0[0],-24($tptr,$i) # t[1] + + mul $a0 # a[2]*a[0] + add %rax,$A0[1] + mov $ai,%rax + adc \$0,%rdx + mov $A0[1],-16($tptr,$i) # t[2] + mov %rdx,$A0[0] + + + mov -8($aptr,$i),$ai # a[3] + mul $a1 # a[2]*a[1] + mov %rax,$A1[0] # a[2]*a[1]+t[3] + mov $ai,%rax + mov %rdx,$A1[1] + + lea ($i),$j + mul $a0 # a[3]*a[0] + add %rax,$A0[0] # a[3]*a[0]+a[2]*a[1]+t[3] + mov $ai,%rax + mov %rdx,$A0[1] + adc \$0,$A0[1] + add $A1[0],$A0[0] + adc \$0,$A0[1] + mov $A0[0],-8($tptr,$j) # t[3] + jmp .Lsqr4x_1st + +.align 32 +.Lsqr4x_1st: + mov ($aptr,$j),$ai # a[4] + mul $a1 # a[3]*a[1] + add %rax,$A1[1] # a[3]*a[1]+t[4] + mov $ai,%rax + mov %rdx,$A1[0] + adc \$0,$A1[0] + + mul $a0 # a[4]*a[0] + add %rax,$A0[1] # a[4]*a[0]+a[3]*a[1]+t[4] + mov $ai,%rax # a[3] + mov 8($aptr,$j),$ai # a[5] + mov %rdx,$A0[0] + adc \$0,$A0[0] + add $A1[1],$A0[1] + adc \$0,$A0[0] + + + mul $a1 # a[4]*a[3] + add %rax,$A1[0] # a[4]*a[3]+t[5] + mov $ai,%rax + mov $A0[1],($tptr,$j) # t[4] + mov %rdx,$A1[1] + adc \$0,$A1[1] + + mul $a0 # a[5]*a[2] + add %rax,$A0[0] # a[5]*a[2]+a[4]*a[3]+t[5] + mov $ai,%rax + mov 16($aptr,$j),$ai # a[6] + mov %rdx,$A0[1] + adc \$0,$A0[1] + add $A1[0],$A0[0] + adc \$0,$A0[1] + + mul $a1 # a[5]*a[3] + add %rax,$A1[1] # a[5]*a[3]+t[6] + mov $ai,%rax + mov $A0[0],8($tptr,$j) # t[5] + mov %rdx,$A1[0] + adc \$0,$A1[0] + + mul $a0 # a[6]*a[2] + add %rax,$A0[1] # a[6]*a[2]+a[5]*a[3]+t[6] + mov $ai,%rax # a[3] + mov 24($aptr,$j),$ai # a[7] + mov %rdx,$A0[0] + adc \$0,$A0[0] + add $A1[1],$A0[1] + adc \$0,$A0[0] + + + mul $a1 # a[6]*a[5] + add %rax,$A1[0] # a[6]*a[5]+t[7] + mov $ai,%rax + mov $A0[1],16($tptr,$j) # t[6] + mov %rdx,$A1[1] + adc \$0,$A1[1] + lea 32($j),$j + + mul $a0 # a[7]*a[4] + add %rax,$A0[0] # a[7]*a[4]+a[6]*a[5]+t[6] + mov $ai,%rax + mov %rdx,$A0[1] + adc \$0,$A0[1] + add $A1[0],$A0[0] + adc \$0,$A0[1] + mov $A0[0],-8($tptr,$j) # t[7] + + cmp \$0,$j + jne .Lsqr4x_1st + + mul $a1 # a[7]*a[5] + add %rax,$A1[1] + lea 16($i),$i + adc \$0,%rdx + add $A0[1],$A1[1] + adc \$0,%rdx + + mov $A1[1],($tptr) # t[8] + mov %rdx,$A1[0] + mov %rdx,8($tptr) # t[9] + jmp .Lsqr4x_outer + +.align 32 +.Lsqr4x_outer: # comments apply to $num==6 case + mov -32($aptr,$i),$a0 # a[0] + lea 48+8(%rsp,$num,2),$tptr # end of tp[] buffer, &tp[2*$num] + mov -24($aptr,$i),%rax # a[1] + lea -32($tptr,$i),$tptr # end of tp[] window, &tp[2*$num-"$i"] + mov -16($aptr,$i),$ai # a[2] + mov %rax,$a1 + + mul $a0 # a[1]*a[0] + mov -24($tptr,$i),$A0[0] # t[1] + add %rax,$A0[0] # a[1]*a[0]+t[1] + mov $ai,%rax # a[2] + adc \$0,%rdx + mov $A0[0],-24($tptr,$i) # t[1] + mov %rdx,$A0[1] + + mul $a0 # a[2]*a[0] + add %rax,$A0[1] + mov $ai,%rax + adc \$0,%rdx + add -16($tptr,$i),$A0[1] # a[2]*a[0]+t[2] + mov %rdx,$A0[0] + adc \$0,$A0[0] + mov $A0[1],-16($tptr,$i) # t[2] + + xor $A1[0],$A1[0] + + mov -8($aptr,$i),$ai # a[3] + mul $a1 # a[2]*a[1] + add %rax,$A1[0] # a[2]*a[1]+t[3] + mov $ai,%rax + adc \$0,%rdx + add -8($tptr,$i),$A1[0] + mov %rdx,$A1[1] + adc \$0,$A1[1] + + mul $a0 # a[3]*a[0] + add %rax,$A0[0] # a[3]*a[0]+a[2]*a[1]+t[3] + mov $ai,%rax + adc \$0,%rdx + add $A1[0],$A0[0] + mov %rdx,$A0[1] + adc \$0,$A0[1] + mov $A0[0],-8($tptr,$i) # t[3] + + lea ($i),$j + jmp .Lsqr4x_inner + +.align 32 +.Lsqr4x_inner: + mov ($aptr,$j),$ai # a[4] + mul $a1 # a[3]*a[1] + add %rax,$A1[1] # a[3]*a[1]+t[4] + mov $ai,%rax + mov %rdx,$A1[0] + adc \$0,$A1[0] + add ($tptr,$j),$A1[1] + adc \$0,$A1[0] + + .byte 0x67 + mul $a0 # a[4]*a[0] + add %rax,$A0[1] # a[4]*a[0]+a[3]*a[1]+t[4] + mov $ai,%rax # a[3] + mov 8($aptr,$j),$ai # a[5] + mov %rdx,$A0[0] + adc \$0,$A0[0] + add $A1[1],$A0[1] + adc \$0,$A0[0] + + mul $a1 # a[4]*a[3] + add %rax,$A1[0] # a[4]*a[3]+t[5] + mov $A0[1],($tptr,$j) # t[4] + mov $ai,%rax + mov %rdx,$A1[1] + adc \$0,$A1[1] + add 8($tptr,$j),$A1[0] + lea 16($j),$j # j++ + adc \$0,$A1[1] + + mul $a0 # a[5]*a[2] + add %rax,$A0[0] # a[5]*a[2]+a[4]*a[3]+t[5] + mov $ai,%rax + adc \$0,%rdx + add $A1[0],$A0[0] + mov %rdx,$A0[1] + adc \$0,$A0[1] + mov $A0[0],-8($tptr,$j) # t[5], "preloaded t[1]" below + + cmp \$0,$j + jne .Lsqr4x_inner + + .byte 0x67 + mul $a1 # a[5]*a[3] + add %rax,$A1[1] + adc \$0,%rdx + add $A0[1],$A1[1] + adc \$0,%rdx + + mov $A1[1],($tptr) # t[6], "preloaded t[2]" below + mov %rdx,$A1[0] + mov %rdx,8($tptr) # t[7], "preloaded t[3]" below + + add \$16,$i + jnz .Lsqr4x_outer + + # comments apply to $num==4 case + mov -32($aptr),$a0 # a[0] + lea 48+8(%rsp,$num,2),$tptr # end of tp[] buffer, &tp[2*$num] + mov -24($aptr),%rax # a[1] + lea -32($tptr,$i),$tptr # end of tp[] window, &tp[2*$num-"$i"] + mov -16($aptr),$ai # a[2] + mov %rax,$a1 + + mul $a0 # a[1]*a[0] + add %rax,$A0[0] # a[1]*a[0]+t[1], preloaded t[1] + mov $ai,%rax # a[2] + mov %rdx,$A0[1] + adc \$0,$A0[1] + + mul $a0 # a[2]*a[0] + add %rax,$A0[1] + mov $ai,%rax + mov $A0[0],-24($tptr) # t[1] + mov %rdx,$A0[0] + adc \$0,$A0[0] + add $A1[1],$A0[1] # a[2]*a[0]+t[2], preloaded t[2] + mov -8($aptr),$ai # a[3] + adc \$0,$A0[0] + + mul $a1 # a[2]*a[1] + add %rax,$A1[0] # a[2]*a[1]+t[3], preloaded t[3] + mov $ai,%rax + mov $A0[1],-16($tptr) # t[2] + mov %rdx,$A1[1] + adc \$0,$A1[1] + + mul $a0 # a[3]*a[0] + add %rax,$A0[0] # a[3]*a[0]+a[2]*a[1]+t[3] + mov $ai,%rax + mov %rdx,$A0[1] + adc \$0,$A0[1] + add $A1[0],$A0[0] + adc \$0,$A0[1] + mov $A0[0],-8($tptr) # t[3] + + mul $a1 # a[3]*a[1] + add %rax,$A1[1] + mov -16($aptr),%rax # a[2] + adc \$0,%rdx + add $A0[1],$A1[1] + adc \$0,%rdx + + mov $A1[1],($tptr) # t[4] + mov %rdx,$A1[0] + mov %rdx,8($tptr) # t[5] + + mul $ai # a[2]*a[3] +___ +{ +my ($shift,$carry)=($a0,$a1); +my @S=(@A1,$ai,$n0); +$code.=<<___; + add \$16,$i + xor $shift,$shift + sub $num,$i # $i=16-$num + xor $carry,$carry + + add $A1[0],%rax # t[5] + adc \$0,%rdx + mov %rax,8($tptr) # t[5] + mov %rdx,16($tptr) # t[6] + mov $carry,24($tptr) # t[7] + + mov -16($aptr,$i),%rax # a[0] + lea 48+8(%rsp),$tptr + xor $A0[0],$A0[0] # t[0] + mov 8($tptr),$A0[1] # t[1] + + lea ($shift,$A0[0],2),$S[0] # t[2*i]<<1 | shift + shr \$63,$A0[0] + lea ($j,$A0[1],2),$S[1] # t[2*i+1]<<1 | + shr \$63,$A0[1] + or $A0[0],$S[1] # | t[2*i]>>63 + mov 16($tptr),$A0[0] # t[2*i+2] # prefetch + mov $A0[1],$shift # shift=t[2*i+1]>>63 + mul %rax # a[i]*a[i] + neg $carry # mov $carry,cf + mov 24($tptr),$A0[1] # t[2*i+2+1] # prefetch + adc %rax,$S[0] + mov -8($aptr,$i),%rax # a[i+1] # prefetch + mov $S[0],($tptr) + adc %rdx,$S[1] + + lea ($shift,$A0[0],2),$S[2] # t[2*i]<<1 | shift + mov $S[1],8($tptr) + sbb $carry,$carry # mov cf,$carry + shr \$63,$A0[0] + lea ($j,$A0[1],2),$S[3] # t[2*i+1]<<1 | + shr \$63,$A0[1] + or $A0[0],$S[3] # | t[2*i]>>63 + mov 32($tptr),$A0[0] # t[2*i+2] # prefetch + mov $A0[1],$shift # shift=t[2*i+1]>>63 + mul %rax # a[i]*a[i] + neg $carry # mov $carry,cf + mov 40($tptr),$A0[1] # t[2*i+2+1] # prefetch + adc %rax,$S[2] + mov 0($aptr,$i),%rax # a[i+1] # prefetch + mov $S[2],16($tptr) + adc %rdx,$S[3] + lea 16($i),$i + mov $S[3],24($tptr) + sbb $carry,$carry # mov cf,$carry + lea 64($tptr),$tptr + jmp .Lsqr4x_shift_n_add + +.align 32 +.Lsqr4x_shift_n_add: + lea ($shift,$A0[0],2),$S[0] # t[2*i]<<1 | shift + shr \$63,$A0[0] + lea ($j,$A0[1],2),$S[1] # t[2*i+1]<<1 | + shr \$63,$A0[1] + or $A0[0],$S[1] # | t[2*i]>>63 + mov -16($tptr),$A0[0] # t[2*i+2] # prefetch + mov $A0[1],$shift # shift=t[2*i+1]>>63 + mul %rax # a[i]*a[i] + neg $carry # mov $carry,cf + mov -8($tptr),$A0[1] # t[2*i+2+1] # prefetch + adc %rax,$S[0] + mov -8($aptr,$i),%rax # a[i+1] # prefetch + mov $S[0],-32($tptr) + adc %rdx,$S[1] + + lea ($shift,$A0[0],2),$S[2] # t[2*i]<<1 | shift + mov $S[1],-24($tptr) + sbb $carry,$carry # mov cf,$carry + shr \$63,$A0[0] + lea ($j,$A0[1],2),$S[3] # t[2*i+1]<<1 | + shr \$63,$A0[1] + or $A0[0],$S[3] # | t[2*i]>>63 + mov 0($tptr),$A0[0] # t[2*i+2] # prefetch + mov $A0[1],$shift # shift=t[2*i+1]>>63 + mul %rax # a[i]*a[i] + neg $carry # mov $carry,cf + mov 8($tptr),$A0[1] # t[2*i+2+1] # prefetch + adc %rax,$S[2] + mov 0($aptr,$i),%rax # a[i+1] # prefetch + mov $S[2],-16($tptr) + adc %rdx,$S[3] + + lea ($shift,$A0[0],2),$S[0] # t[2*i]<<1 | shift + mov $S[3],-8($tptr) + sbb $carry,$carry # mov cf,$carry + shr \$63,$A0[0] + lea ($j,$A0[1],2),$S[1] # t[2*i+1]<<1 | + shr \$63,$A0[1] + or $A0[0],$S[1] # | t[2*i]>>63 + mov 16($tptr),$A0[0] # t[2*i+2] # prefetch + mov $A0[1],$shift # shift=t[2*i+1]>>63 + mul %rax # a[i]*a[i] + neg $carry # mov $carry,cf + mov 24($tptr),$A0[1] # t[2*i+2+1] # prefetch + adc %rax,$S[0] + mov 8($aptr,$i),%rax # a[i+1] # prefetch + mov $S[0],0($tptr) + adc %rdx,$S[1] + + lea ($shift,$A0[0],2),$S[2] # t[2*i]<<1 | shift + mov $S[1],8($tptr) + sbb $carry,$carry # mov cf,$carry + shr \$63,$A0[0] + lea ($j,$A0[1],2),$S[3] # t[2*i+1]<<1 | + shr \$63,$A0[1] + or $A0[0],$S[3] # | t[2*i]>>63 + mov 32($tptr),$A0[0] # t[2*i+2] # prefetch + mov $A0[1],$shift # shift=t[2*i+1]>>63 + mul %rax # a[i]*a[i] + neg $carry # mov $carry,cf + mov 40($tptr),$A0[1] # t[2*i+2+1] # prefetch + adc %rax,$S[2] + mov 16($aptr,$i),%rax # a[i+1] # prefetch + mov $S[2],16($tptr) + adc %rdx,$S[3] + mov $S[3],24($tptr) + sbb $carry,$carry # mov cf,$carry + lea 64($tptr),$tptr + add \$32,$i + jnz .Lsqr4x_shift_n_add + + lea ($shift,$A0[0],2),$S[0] # t[2*i]<<1 | shift + .byte 0x67 + shr \$63,$A0[0] + lea ($j,$A0[1],2),$S[1] # t[2*i+1]<<1 | + shr \$63,$A0[1] + or $A0[0],$S[1] # | t[2*i]>>63 + mov -16($tptr),$A0[0] # t[2*i+2] # prefetch + mov $A0[1],$shift # shift=t[2*i+1]>>63 + mul %rax # a[i]*a[i] + neg $carry # mov $carry,cf + mov -8($tptr),$A0[1] # t[2*i+2+1] # prefetch + adc %rax,$S[0] + mov -8($aptr),%rax # a[i+1] # prefetch + mov $S[0],-32($tptr) + adc %rdx,$S[1] + + lea ($shift,$A0[0],2),$S[2] # t[2*i]<<1|shift + mov $S[1],-24($tptr) + sbb $carry,$carry # mov cf,$carry + shr \$63,$A0[0] + lea ($j,$A0[1],2),$S[3] # t[2*i+1]<<1 | + shr \$63,$A0[1] + or $A0[0],$S[3] # | t[2*i]>>63 + mul %rax # a[i]*a[i] + neg $carry # mov $carry,cf + adc %rax,$S[2] + adc %rdx,$S[3] + mov $S[2],-16($tptr) + mov $S[3],-8($tptr) +___ +} +###################################################################### +# Montgomery reduction part, "word-by-word" algorithm. +# +# This new path is inspired by multiple submissions from Intel, by +# Shay Gueron, Vlad Krasnov, Erdinc Ozturk, James Guilford, +# Vinodh Gopal... +{ +my ($nptr,$tptr,$carry,$m0)=("%rbp","%rdi","%rsi","%rbx"); + +$code.=<<___; + movq %xmm2,$nptr +__bn_sqr8x_reduction: + xor %rax,%rax + lea ($nptr,$num),%rcx # end of n[] + lea 48+8(%rsp,$num,2),%rdx # end of t[] buffer + mov %rcx,0+8(%rsp) + lea 48+8(%rsp,$num),$tptr # end of initial t[] window + mov %rdx,8+8(%rsp) + neg $num + jmp .L8x_reduction_loop + +.align 32 +.L8x_reduction_loop: + lea ($tptr,$num),$tptr # start of current t[] window + .byte 0x66 + mov 8*0($tptr),$m0 + mov 8*1($tptr),%r9 + mov 8*2($tptr),%r10 + mov 8*3($tptr),%r11 + mov 8*4($tptr),%r12 + mov 8*5($tptr),%r13 + mov 8*6($tptr),%r14 + mov 8*7($tptr),%r15 + mov %rax,(%rdx) # store top-most carry bit + lea 8*8($tptr),$tptr + + .byte 0x67 + mov $m0,%r8 + imulq 32+8(%rsp),$m0 # n0*a[0] + mov 8*0($nptr),%rax # n[0] + mov \$8,%ecx + jmp .L8x_reduce + +.align 32 +.L8x_reduce: + mulq $m0 + mov 8*1($nptr),%rax # n[1] + neg %r8 + mov %rdx,%r8 + adc \$0,%r8 + + mulq $m0 + add %rax,%r9 + mov 8*2($nptr),%rax + adc \$0,%rdx + add %r9,%r8 + mov $m0,48-8+8(%rsp,%rcx,8) # put aside n0*a[i] + mov %rdx,%r9 + adc \$0,%r9 + + mulq $m0 + add %rax,%r10 + mov 8*3($nptr),%rax + adc \$0,%rdx + add %r10,%r9 + mov 32+8(%rsp),$carry # pull n0, borrow $carry + mov %rdx,%r10 + adc \$0,%r10 + + mulq $m0 + add %rax,%r11 + mov 8*4($nptr),%rax + adc \$0,%rdx + imulq %r8,$carry # modulo-scheduled + add %r11,%r10 + mov %rdx,%r11 + adc \$0,%r11 + + mulq $m0 + add %rax,%r12 + mov 8*5($nptr),%rax + adc \$0,%rdx + add %r12,%r11 + mov %rdx,%r12 + adc \$0,%r12 + + mulq $m0 + add %rax,%r13 + mov 8*6($nptr),%rax + adc \$0,%rdx + add %r13,%r12 + mov %rdx,%r13 + adc \$0,%r13 + + mulq $m0 + add %rax,%r14 + mov 8*7($nptr),%rax + adc \$0,%rdx + add %r14,%r13 + mov %rdx,%r14 + adc \$0,%r14 + + mulq $m0 + mov $carry,$m0 # n0*a[i] + add %rax,%r15 + mov 8*0($nptr),%rax # n[0] + adc \$0,%rdx + add %r15,%r14 + mov %rdx,%r15 + adc \$0,%r15 + + dec %ecx + jnz .L8x_reduce + + lea 8*8($nptr),$nptr + xor %rax,%rax + mov 8+8(%rsp),%rdx # pull end of t[] + cmp 0+8(%rsp),$nptr # end of n[]? + jae .L8x_no_tail + + .byte 0x66 + add 8*0($tptr),%r8 + adc 8*1($tptr),%r9 + adc 8*2($tptr),%r10 + adc 8*3($tptr),%r11 + adc 8*4($tptr),%r12 + adc 8*5($tptr),%r13 + adc 8*6($tptr),%r14 + adc 8*7($tptr),%r15 + sbb $carry,$carry # top carry + + mov 48+56+8(%rsp),$m0 # pull n0*a[0] + mov \$8,%ecx + mov 8*0($nptr),%rax + jmp .L8x_tail + +.align 32 +.L8x_tail: + mulq $m0 + add %rax,%r8 + mov 8*1($nptr),%rax + mov %r8,($tptr) # save result + mov %rdx,%r8 + adc \$0,%r8 + + mulq $m0 + add %rax,%r9 + mov 8*2($nptr),%rax + adc \$0,%rdx + add %r9,%r8 + lea 8($tptr),$tptr # $tptr++ + mov %rdx,%r9 + adc \$0,%r9 + + mulq $m0 + add %rax,%r10 + mov 8*3($nptr),%rax + adc \$0,%rdx + add %r10,%r9 + mov %rdx,%r10 + adc \$0,%r10 + + mulq $m0 + add %rax,%r11 + mov 8*4($nptr),%rax + adc \$0,%rdx + add %r11,%r10 + mov %rdx,%r11 + adc \$0,%r11 + + mulq $m0 + add %rax,%r12 + mov 8*5($nptr),%rax + adc \$0,%rdx + add %r12,%r11 + mov %rdx,%r12 + adc \$0,%r12 + + mulq $m0 + add %rax,%r13 + mov 8*6($nptr),%rax + adc \$0,%rdx + add %r13,%r12 + mov %rdx,%r13 + adc \$0,%r13 + + mulq $m0 + add %rax,%r14 + mov 8*7($nptr),%rax + adc \$0,%rdx + add %r14,%r13 + mov %rdx,%r14 + adc \$0,%r14 + + mulq $m0 + mov 48-16+8(%rsp,%rcx,8),$m0# pull n0*a[i] + add %rax,%r15 + adc \$0,%rdx + add %r15,%r14 + mov 8*0($nptr),%rax # pull n[0] + mov %rdx,%r15 + adc \$0,%r15 + + dec %ecx + jnz .L8x_tail + + lea 8*8($nptr),$nptr + mov 8+8(%rsp),%rdx # pull end of t[] + cmp 0+8(%rsp),$nptr # end of n[]? + jae .L8x_tail_done # break out of loop + + mov 48+56+8(%rsp),$m0 # pull n0*a[0] + neg $carry + mov 8*0($nptr),%rax # pull n[0] + adc 8*0($tptr),%r8 + adc 8*1($tptr),%r9 + adc 8*2($tptr),%r10 + adc 8*3($tptr),%r11 + adc 8*4($tptr),%r12 + adc 8*5($tptr),%r13 + adc 8*6($tptr),%r14 + adc 8*7($tptr),%r15 + sbb $carry,$carry # top carry + + mov \$8,%ecx + jmp .L8x_tail + +.align 32 +.L8x_tail_done: + add (%rdx),%r8 # can this overflow? + adc \$0,%r9 + adc \$0,%r10 + adc \$0,%r11 + adc \$0,%r12 + adc \$0,%r13 + adc \$0,%r14 + adc \$0,%r15 # can't overflow, because we + # started with "overhung" part + # of multiplication + xor %rax,%rax + + neg $carry +.L8x_no_tail: + adc 8*0($tptr),%r8 + adc 8*1($tptr),%r9 + adc 8*2($tptr),%r10 + adc 8*3($tptr),%r11 + adc 8*4($tptr),%r12 + adc 8*5($tptr),%r13 + adc 8*6($tptr),%r14 + adc 8*7($tptr),%r15 + adc \$0,%rax # top-most carry + mov -8($nptr),%rcx # np[num-1] + xor $carry,$carry + + movq %xmm2,$nptr # restore $nptr + + mov %r8,8*0($tptr) # store top 512 bits + mov %r9,8*1($tptr) + movq %xmm3,$num # $num is %r9, can't be moved upwards + mov %r10,8*2($tptr) + mov %r11,8*3($tptr) + mov %r12,8*4($tptr) + mov %r13,8*5($tptr) + mov %r14,8*6($tptr) + mov %r15,8*7($tptr) + lea 8*8($tptr),$tptr + + cmp %rdx,$tptr # end of t[]? + jb .L8x_reduction_loop + ret +.size bn_sqr8x_internal,.-bn_sqr8x_internal +___ +} +############################################################## +# Post-condition, 4x unrolled +# +{ +my ($tptr,$nptr)=("%rbx","%rbp"); +$code.=<<___; +.type __bn_post4x_internal,\@abi-omnipotent +.align 32 +__bn_post4x_internal: + mov 8*0($nptr),%r12 + lea (%rdi,$num),$tptr # %rdi was $tptr above + mov $num,%rcx + movq %xmm1,$rptr # restore $rptr + neg %rax + movq %xmm1,$aptr # prepare for back-to-back call + sar \$3+2,%rcx + dec %r12 # so that after 'not' we get -n[0] + xor %r10,%r10 + mov 8*1($nptr),%r13 + mov 8*2($nptr),%r14 + mov 8*3($nptr),%r15 + jmp .Lsqr4x_sub_entry + +.align 16 +.Lsqr4x_sub: + mov 8*0($nptr),%r12 + mov 8*1($nptr),%r13 + mov 8*2($nptr),%r14 + mov 8*3($nptr),%r15 +.Lsqr4x_sub_entry: + lea 8*4($nptr),$nptr + not %r12 + not %r13 + not %r14 + not %r15 + and %rax,%r12 + and %rax,%r13 + and %rax,%r14 + and %rax,%r15 + + neg %r10 # mov %r10,%cf + adc 8*0($tptr),%r12 + adc 8*1($tptr),%r13 + adc 8*2($tptr),%r14 + adc 8*3($tptr),%r15 + mov %r12,8*0($rptr) + lea 8*4($tptr),$tptr + mov %r13,8*1($rptr) + sbb %r10,%r10 # mov %cf,%r10 + mov %r14,8*2($rptr) + mov %r15,8*3($rptr) + lea 8*4($rptr),$rptr + + inc %rcx # pass %cf + jnz .Lsqr4x_sub + + mov $num,%r10 # prepare for back-to-back call + neg $num # restore $num + ret +.size __bn_post4x_internal,.-__bn_post4x_internal +___ +} +{ +$code.=<<___; +.globl bn_from_montgomery +.type bn_from_montgomery,\@abi-omnipotent +.align 32 +bn_from_montgomery: + testl \$7,`($win64?"48(%rsp)":"%r9d")` + jz bn_from_mont8x + xor %eax,%eax + ret +.size bn_from_montgomery,.-bn_from_montgomery + +.type bn_from_mont8x,\@function,6 +.align 32 +bn_from_mont8x: + .byte 0x67 + mov %rsp,%rax + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + + shl \$3,${num}d # convert $num to bytes + lea ($num,$num,2),%r10 # 3*$num in bytes + neg $num + mov ($n0),$n0 # *n0 + + ############################################################## + # Ensure that stack frame doesn't alias with $rptr+3*$num + # modulo 4096, which covers ret[num], am[num] and n[num] + # (see bn_exp.c). The stack is allocated to aligned with + # bn_power5's frame, and as bn_from_montgomery happens to be + # last operation, we use the opportunity to cleanse it. + # + lea -320(%rsp,$num,2),%r11 + sub $rptr,%r11 + and \$4095,%r11 + cmp %r11,%r10 + jb .Lfrom_sp_alt + sub %r11,%rsp # align with $aptr + lea -320(%rsp,$num,2),%rsp # alloca(frame+2*$num*8+256) + jmp .Lfrom_sp_done + +.align 32 +.Lfrom_sp_alt: + lea 4096-320(,$num,2),%r10 + lea -320(%rsp,$num,2),%rsp # alloca(frame+2*$num*8+256) + sub %r10,%r11 + mov \$0,%r10 + cmovc %r10,%r11 + sub %r11,%rsp +.Lfrom_sp_done: + and \$-64,%rsp + mov $num,%r10 + neg $num + + ############################################################## + # Stack layout + # + # +0 saved $num, used in reduction section + # +8 &t[2*$num], used in reduction section + # +32 saved *n0 + # +40 saved %rsp + # +48 t[2*$num] + # + mov $n0, 32(%rsp) + mov %rax, 40(%rsp) # save original %rsp +.Lfrom_body: + mov $num,%r11 + lea 48(%rsp),%rax + pxor %xmm0,%xmm0 + jmp .Lmul_by_1 + +.align 32 +.Lmul_by_1: + movdqu ($aptr),%xmm1 + movdqu 16($aptr),%xmm2 + movdqu 32($aptr),%xmm3 + movdqa %xmm0,(%rax,$num) + movdqu 48($aptr),%xmm4 + movdqa %xmm0,16(%rax,$num) + .byte 0x48,0x8d,0xb6,0x40,0x00,0x00,0x00 # lea 64($aptr),$aptr + movdqa %xmm1,(%rax) + movdqa %xmm0,32(%rax,$num) + movdqa %xmm2,16(%rax) + movdqa %xmm0,48(%rax,$num) + movdqa %xmm3,32(%rax) + movdqa %xmm4,48(%rax) + lea 64(%rax),%rax + sub \$64,%r11 + jnz .Lmul_by_1 + + movq $rptr,%xmm1 + movq $nptr,%xmm2 + .byte 0x67 + mov $nptr,%rbp + movq %r10, %xmm3 # -num +___ +$code.=<<___ if ($addx); + mov OPENSSL_ia32cap_P+8(%rip),%r11d + and \$0x80108,%r11d + cmp \$0x80108,%r11d # check for AD*X+BMI2+BMI1 + jne .Lfrom_mont_nox + + lea (%rax,$num),$rptr + call __bn_sqrx8x_reduction + call __bn_postx4x_internal + + pxor %xmm0,%xmm0 + lea 48(%rsp),%rax + mov 40(%rsp),%rsi # restore %rsp + jmp .Lfrom_mont_zero + +.align 32 +.Lfrom_mont_nox: +___ +$code.=<<___; + call __bn_sqr8x_reduction + call __bn_post4x_internal + + pxor %xmm0,%xmm0 + lea 48(%rsp),%rax + mov 40(%rsp),%rsi # restore %rsp + jmp .Lfrom_mont_zero + +.align 32 +.Lfrom_mont_zero: + movdqa %xmm0,16*0(%rax) + movdqa %xmm0,16*1(%rax) + movdqa %xmm0,16*2(%rax) + movdqa %xmm0,16*3(%rax) + lea 16*4(%rax),%rax + sub \$32,$num + jnz .Lfrom_mont_zero + + mov \$1,%rax + mov -48(%rsi),%r15 + mov -40(%rsi),%r14 + mov -32(%rsi),%r13 + mov -24(%rsi),%r12 + mov -16(%rsi),%rbp + mov -8(%rsi),%rbx + lea (%rsi),%rsp +.Lfrom_epilogue: + ret +.size bn_from_mont8x,.-bn_from_mont8x +___ +} +}}} + +if ($addx) {{{ +my $bp="%rdx"; # restore original value + +$code.=<<___; +.type bn_mulx4x_mont_gather5,\@function,6 +.align 32 +bn_mulx4x_mont_gather5: +.Lmulx4x_enter: + mov %rsp,%rax + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + + shl \$3,${num}d # convert $num to bytes + lea ($num,$num,2),%r10 # 3*$num in bytes + neg $num # -$num + mov ($n0),$n0 # *n0 + + ############################################################## + # Ensure that stack frame doesn't alias with $rptr+3*$num + # modulo 4096, which covers ret[num], am[num] and n[num] + # (see bn_exp.c). This is done to allow memory disambiguation + # logic do its magic. [Extra [num] is allocated in order + # to align with bn_power5's frame, which is cleansed after + # completing exponentiation. Extra 256 bytes is for power mask + # calculated from 7th argument, the index.] + # + lea -320(%rsp,$num,2),%r11 + sub $rp,%r11 + and \$4095,%r11 + cmp %r11,%r10 + jb .Lmulx4xsp_alt + sub %r11,%rsp # align with $aptr + lea -320(%rsp,$num,2),%rsp # alloca(frame+2*$num*8+256) + jmp .Lmulx4xsp_done + +.Lmulx4xsp_alt: + lea 4096-320(,$num,2),%r10 + lea -320(%rsp,$num,2),%rsp # alloca(frame+2*$num*8+256) + sub %r10,%r11 + mov \$0,%r10 + cmovc %r10,%r11 + sub %r11,%rsp +.Lmulx4xsp_done: + and \$-64,%rsp # ensure alignment + ############################################################## + # Stack layout + # +0 -num + # +8 off-loaded &b[i] + # +16 end of b[num] + # +24 inner counter + # +32 saved n0 + # +40 saved %rsp + # +48 + # +56 saved rp + # +64 tmp[num+1] + # + mov $n0, 32(%rsp) # save *n0 + mov %rax,40(%rsp) # save original %rsp +.Lmulx4x_body: + call mulx4x_internal + + mov 40(%rsp),%rsi # restore %rsp + mov \$1,%rax + + mov -48(%rsi),%r15 + mov -40(%rsi),%r14 + mov -32(%rsi),%r13 + mov -24(%rsi),%r12 + mov -16(%rsi),%rbp + mov -8(%rsi),%rbx + lea (%rsi),%rsp +.Lmulx4x_epilogue: + ret +.size bn_mulx4x_mont_gather5,.-bn_mulx4x_mont_gather5 + +.type mulx4x_internal,\@abi-omnipotent +.align 32 +mulx4x_internal: + mov $num,8(%rsp) # save -$num (it was in bytes) + mov $num,%r10 + neg $num # restore $num + shl \$5,$num + neg %r10 # restore $num + lea 128($bp,$num),%r13 # end of powers table (+size optimization) + shr \$5+5,$num + movd `($win64?56:8)`(%rax),%xmm5 # load 7th argument + sub \$1,$num + lea .Linc(%rip),%rax + mov %r13,16+8(%rsp) # end of b[num] + mov $num,24+8(%rsp) # inner counter + mov $rp, 56+8(%rsp) # save $rp +___ +my ($aptr, $bptr, $nptr, $tptr, $mi, $bi, $zero, $num)= + ("%rsi","%rdi","%rcx","%rbx","%r8","%r9","%rbp","%rax"); +my $rptr=$bptr; +my $STRIDE=2**5*8; # 5 is "window size" +my $N=$STRIDE/4; # should match cache line size +$code.=<<___; + movdqa 0(%rax),%xmm0 # 00000001000000010000000000000000 + movdqa 16(%rax),%xmm1 # 00000002000000020000000200000002 + lea 88-112(%rsp,%r10),%r10 # place the mask after tp[num+1] (+ICache optimizaton) + lea 128($bp),$bptr # size optimization + + pshufd \$0,%xmm5,%xmm5 # broadcast index + movdqa %xmm1,%xmm4 + .byte 0x67 + movdqa %xmm1,%xmm2 +___ +######################################################################## +# calculate mask by comparing 0..31 to index and save result to stack +# +$code.=<<___; + .byte 0x67 + paddd %xmm0,%xmm1 + pcmpeqd %xmm5,%xmm0 # compare to 1,0 + movdqa %xmm4,%xmm3 +___ +for($i=0;$i<$STRIDE/16-4;$i+=4) { +$code.=<<___; + paddd %xmm1,%xmm2 + pcmpeqd %xmm5,%xmm1 # compare to 3,2 + movdqa %xmm0,`16*($i+0)+112`(%r10) + movdqa %xmm4,%xmm0 + + paddd %xmm2,%xmm3 + pcmpeqd %xmm5,%xmm2 # compare to 5,4 + movdqa %xmm1,`16*($i+1)+112`(%r10) + movdqa %xmm4,%xmm1 + + paddd %xmm3,%xmm0 + pcmpeqd %xmm5,%xmm3 # compare to 7,6 + movdqa %xmm2,`16*($i+2)+112`(%r10) + movdqa %xmm4,%xmm2 + + paddd %xmm0,%xmm1 + pcmpeqd %xmm5,%xmm0 + movdqa %xmm3,`16*($i+3)+112`(%r10) + movdqa %xmm4,%xmm3 +___ +} +$code.=<<___; # last iteration can be optimized + .byte 0x67 + paddd %xmm1,%xmm2 + pcmpeqd %xmm5,%xmm1 + movdqa %xmm0,`16*($i+0)+112`(%r10) + + paddd %xmm2,%xmm3 + pcmpeqd %xmm5,%xmm2 + movdqa %xmm1,`16*($i+1)+112`(%r10) + + pcmpeqd %xmm5,%xmm3 + movdqa %xmm2,`16*($i+2)+112`(%r10) + + pand `16*($i+0)-128`($bptr),%xmm0 # while it's still in register + pand `16*($i+1)-128`($bptr),%xmm1 + pand `16*($i+2)-128`($bptr),%xmm2 + movdqa %xmm3,`16*($i+3)+112`(%r10) + pand `16*($i+3)-128`($bptr),%xmm3 + por %xmm2,%xmm0 + por %xmm3,%xmm1 +___ +for($i=0;$i<$STRIDE/16-4;$i+=4) { +$code.=<<___; + movdqa `16*($i+0)-128`($bptr),%xmm4 + movdqa `16*($i+1)-128`($bptr),%xmm5 + movdqa `16*($i+2)-128`($bptr),%xmm2 + pand `16*($i+0)+112`(%r10),%xmm4 + movdqa `16*($i+3)-128`($bptr),%xmm3 + pand `16*($i+1)+112`(%r10),%xmm5 + por %xmm4,%xmm0 + pand `16*($i+2)+112`(%r10),%xmm2 + por %xmm5,%xmm1 + pand `16*($i+3)+112`(%r10),%xmm3 + por %xmm2,%xmm0 + por %xmm3,%xmm1 +___ +} +$code.=<<___; + pxor %xmm1,%xmm0 + pshufd \$0x4e,%xmm0,%xmm1 + por %xmm1,%xmm0 + lea $STRIDE($bptr),$bptr + movq %xmm0,%rdx # bp[0] + lea 64+8*4+8(%rsp),$tptr + + mov %rdx,$bi + mulx 0*8($aptr),$mi,%rax # a[0]*b[0] + mulx 1*8($aptr),%r11,%r12 # a[1]*b[0] + add %rax,%r11 + mulx 2*8($aptr),%rax,%r13 # ... + adc %rax,%r12 + adc \$0,%r13 + mulx 3*8($aptr),%rax,%r14 + + mov $mi,%r15 + imulq 32+8(%rsp),$mi # "t[0]"*n0 + xor $zero,$zero # cf=0, of=0 + mov $mi,%rdx + + mov $bptr,8+8(%rsp) # off-load &b[i] + + lea 4*8($aptr),$aptr + adcx %rax,%r13 + adcx $zero,%r14 # cf=0 + + mulx 0*8($nptr),%rax,%r10 + adcx %rax,%r15 # discarded + adox %r11,%r10 + mulx 1*8($nptr),%rax,%r11 + adcx %rax,%r10 + adox %r12,%r11 + mulx 2*8($nptr),%rax,%r12 + mov 24+8(%rsp),$bptr # counter value + mov %r10,-8*4($tptr) + adcx %rax,%r11 + adox %r13,%r12 + mulx 3*8($nptr),%rax,%r15 + mov $bi,%rdx + mov %r11,-8*3($tptr) + adcx %rax,%r12 + adox $zero,%r15 # of=0 + lea 4*8($nptr),$nptr + mov %r12,-8*2($tptr) + jmp .Lmulx4x_1st + +.align 32 +.Lmulx4x_1st: + adcx $zero,%r15 # cf=0, modulo-scheduled + mulx 0*8($aptr),%r10,%rax # a[4]*b[0] + adcx %r14,%r10 + mulx 1*8($aptr),%r11,%r14 # a[5]*b[0] + adcx %rax,%r11 + mulx 2*8($aptr),%r12,%rax # ... + adcx %r14,%r12 + mulx 3*8($aptr),%r13,%r14 + .byte 0x67,0x67 + mov $mi,%rdx + adcx %rax,%r13 + adcx $zero,%r14 # cf=0 + lea 4*8($aptr),$aptr + lea 4*8($tptr),$tptr + + adox %r15,%r10 + mulx 0*8($nptr),%rax,%r15 + adcx %rax,%r10 + adox %r15,%r11 + mulx 1*8($nptr),%rax,%r15 + adcx %rax,%r11 + adox %r15,%r12 + mulx 2*8($nptr),%rax,%r15 + mov %r10,-5*8($tptr) + adcx %rax,%r12 + mov %r11,-4*8($tptr) + adox %r15,%r13 + mulx 3*8($nptr),%rax,%r15 + mov $bi,%rdx + mov %r12,-3*8($tptr) + adcx %rax,%r13 + adox $zero,%r15 + lea 4*8($nptr),$nptr + mov %r13,-2*8($tptr) + + dec $bptr # of=0, pass cf + jnz .Lmulx4x_1st + + mov 8(%rsp),$num # load -num + adc $zero,%r15 # modulo-scheduled + lea ($aptr,$num),$aptr # rewind $aptr + add %r15,%r14 + mov 8+8(%rsp),$bptr # re-load &b[i] + adc $zero,$zero # top-most carry + mov %r14,-1*8($tptr) + jmp .Lmulx4x_outer + +.align 32 +.Lmulx4x_outer: + lea 16-256($tptr),%r10 # where 256-byte mask is (+density control) + pxor %xmm4,%xmm4 + .byte 0x67,0x67 + pxor %xmm5,%xmm5 +___ +for($i=0;$i<$STRIDE/16;$i+=4) { +$code.=<<___; + movdqa `16*($i+0)-128`($bptr),%xmm0 + movdqa `16*($i+1)-128`($bptr),%xmm1 + movdqa `16*($i+2)-128`($bptr),%xmm2 + pand `16*($i+0)+256`(%r10),%xmm0 + movdqa `16*($i+3)-128`($bptr),%xmm3 + pand `16*($i+1)+256`(%r10),%xmm1 + por %xmm0,%xmm4 + pand `16*($i+2)+256`(%r10),%xmm2 + por %xmm1,%xmm5 + pand `16*($i+3)+256`(%r10),%xmm3 + por %xmm2,%xmm4 + por %xmm3,%xmm5 +___ +} +$code.=<<___; + por %xmm5,%xmm4 + pshufd \$0x4e,%xmm4,%xmm0 + por %xmm4,%xmm0 + lea $STRIDE($bptr),$bptr + movq %xmm0,%rdx # m0=bp[i] + + mov $zero,($tptr) # save top-most carry + lea 4*8($tptr,$num),$tptr # rewind $tptr + mulx 0*8($aptr),$mi,%r11 # a[0]*b[i] + xor $zero,$zero # cf=0, of=0 + mov %rdx,$bi + mulx 1*8($aptr),%r14,%r12 # a[1]*b[i] + adox -4*8($tptr),$mi # +t[0] + adcx %r14,%r11 + mulx 2*8($aptr),%r15,%r13 # ... + adox -3*8($tptr),%r11 + adcx %r15,%r12 + mulx 3*8($aptr),%rdx,%r14 + adox -2*8($tptr),%r12 + adcx %rdx,%r13 + lea ($nptr,$num),$nptr # rewind $nptr + lea 4*8($aptr),$aptr + adox -1*8($tptr),%r13 + adcx $zero,%r14 + adox $zero,%r14 + + mov $mi,%r15 + imulq 32+8(%rsp),$mi # "t[0]"*n0 + + mov $mi,%rdx + xor $zero,$zero # cf=0, of=0 + mov $bptr,8+8(%rsp) # off-load &b[i] + + mulx 0*8($nptr),%rax,%r10 + adcx %rax,%r15 # discarded + adox %r11,%r10 + mulx 1*8($nptr),%rax,%r11 + adcx %rax,%r10 + adox %r12,%r11 + mulx 2*8($nptr),%rax,%r12 + adcx %rax,%r11 + adox %r13,%r12 + mulx 3*8($nptr),%rax,%r15 + mov $bi,%rdx + mov 24+8(%rsp),$bptr # counter value + mov %r10,-8*4($tptr) + adcx %rax,%r12 + mov %r11,-8*3($tptr) + adox $zero,%r15 # of=0 + mov %r12,-8*2($tptr) + lea 4*8($nptr),$nptr + jmp .Lmulx4x_inner + +.align 32 +.Lmulx4x_inner: + mulx 0*8($aptr),%r10,%rax # a[4]*b[i] + adcx $zero,%r15 # cf=0, modulo-scheduled + adox %r14,%r10 + mulx 1*8($aptr),%r11,%r14 # a[5]*b[i] + adcx 0*8($tptr),%r10 + adox %rax,%r11 + mulx 2*8($aptr),%r12,%rax # ... + adcx 1*8($tptr),%r11 + adox %r14,%r12 + mulx 3*8($aptr),%r13,%r14 + mov $mi,%rdx + adcx 2*8($tptr),%r12 + adox %rax,%r13 + adcx 3*8($tptr),%r13 + adox $zero,%r14 # of=0 + lea 4*8($aptr),$aptr + lea 4*8($tptr),$tptr + adcx $zero,%r14 # cf=0 + + adox %r15,%r10 + mulx 0*8($nptr),%rax,%r15 + adcx %rax,%r10 + adox %r15,%r11 + mulx 1*8($nptr),%rax,%r15 + adcx %rax,%r11 + adox %r15,%r12 + mulx 2*8($nptr),%rax,%r15 + mov %r10,-5*8($tptr) + adcx %rax,%r12 + adox %r15,%r13 + mov %r11,-4*8($tptr) + mulx 3*8($nptr),%rax,%r15 + mov $bi,%rdx + lea 4*8($nptr),$nptr + mov %r12,-3*8($tptr) + adcx %rax,%r13 + adox $zero,%r15 + mov %r13,-2*8($tptr) + + dec $bptr # of=0, pass cf + jnz .Lmulx4x_inner + + mov 0+8(%rsp),$num # load -num + adc $zero,%r15 # modulo-scheduled + sub 0*8($tptr),$bptr # pull top-most carry to %cf + mov 8+8(%rsp),$bptr # re-load &b[i] + mov 16+8(%rsp),%r10 + adc %r15,%r14 + lea ($aptr,$num),$aptr # rewind $aptr + adc $zero,$zero # top-most carry + mov %r14,-1*8($tptr) + + cmp %r10,$bptr + jb .Lmulx4x_outer + + mov -8($nptr),%r10 + mov $zero,%r8 + mov ($nptr,$num),%r12 + lea ($nptr,$num),%rbp # rewind $nptr + mov $num,%rcx + lea ($tptr,$num),%rdi # rewind $tptr + xor %eax,%eax + xor %r15,%r15 + sub %r14,%r10 # compare top-most words + adc %r15,%r15 + or %r15,%r8 + sar \$3+2,%rcx + sub %r8,%rax # %rax=-%r8 + mov 56+8(%rsp),%rdx # restore rp + dec %r12 # so that after 'not' we get -n[0] + mov 8*1(%rbp),%r13 + xor %r8,%r8 + mov 8*2(%rbp),%r14 + mov 8*3(%rbp),%r15 + jmp .Lsqrx4x_sub_entry # common post-condition +.size mulx4x_internal,.-mulx4x_internal +___ +} { +###################################################################### +# void bn_power5( +my $rptr="%rdi"; # BN_ULONG *rptr, +my $aptr="%rsi"; # const BN_ULONG *aptr, +my $bptr="%rdx"; # const void *table, +my $nptr="%rcx"; # const BN_ULONG *nptr, +my $n0 ="%r8"; # const BN_ULONG *n0); +my $num ="%r9"; # int num, has to be divisible by 8 + # int pwr); + +my ($i,$j,$tptr)=("%rbp","%rcx",$rptr); +my @A0=("%r10","%r11"); +my @A1=("%r12","%r13"); +my ($a0,$a1,$ai)=("%r14","%r15","%rbx"); + +$code.=<<___; +.type bn_powerx5,\@function,6 +.align 32 +bn_powerx5: +.Lpowerx5_enter: + mov %rsp,%rax + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + + shl \$3,${num}d # convert $num to bytes + lea ($num,$num,2),%r10 # 3*$num in bytes + neg $num + mov ($n0),$n0 # *n0 + + ############################################################## + # Ensure that stack frame doesn't alias with $rptr+3*$num + # modulo 4096, which covers ret[num], am[num] and n[num] + # (see bn_exp.c). This is done to allow memory disambiguation + # logic do its magic. [Extra 256 bytes is for power mask + # calculated from 7th argument, the index.] + # + lea -320(%rsp,$num,2),%r11 + sub $rptr,%r11 + and \$4095,%r11 + cmp %r11,%r10 + jb .Lpwrx_sp_alt + sub %r11,%rsp # align with $aptr + lea -320(%rsp,$num,2),%rsp # alloca(frame+2*$num*8+256) + jmp .Lpwrx_sp_done + +.align 32 +.Lpwrx_sp_alt: + lea 4096-320(,$num,2),%r10 + lea -320(%rsp,$num,2),%rsp # alloca(frame+2*$num*8+256) + sub %r10,%r11 + mov \$0,%r10 + cmovc %r10,%r11 + sub %r11,%rsp +.Lpwrx_sp_done: + and \$-64,%rsp + mov $num,%r10 + neg $num + + ############################################################## + # Stack layout + # + # +0 saved $num, used in reduction section + # +8 &t[2*$num], used in reduction section + # +16 intermediate carry bit + # +24 top-most carry bit, used in reduction section + # +32 saved *n0 + # +40 saved %rsp + # +48 t[2*$num] + # + pxor %xmm0,%xmm0 + movq $rptr,%xmm1 # save $rptr + movq $nptr,%xmm2 # save $nptr + movq %r10, %xmm3 # -$num + movq $bptr,%xmm4 + mov $n0, 32(%rsp) + mov %rax, 40(%rsp) # save original %rsp +.Lpowerx5_body: + + call __bn_sqrx8x_internal + call __bn_postx4x_internal + call __bn_sqrx8x_internal + call __bn_postx4x_internal + call __bn_sqrx8x_internal + call __bn_postx4x_internal + call __bn_sqrx8x_internal + call __bn_postx4x_internal + call __bn_sqrx8x_internal + call __bn_postx4x_internal + + mov %r10,$num # -num + mov $aptr,$rptr + movq %xmm2,$nptr + movq %xmm4,$bptr + mov 40(%rsp),%rax + + call mulx4x_internal + + mov 40(%rsp),%rsi # restore %rsp + mov \$1,%rax + + mov -48(%rsi),%r15 + mov -40(%rsi),%r14 + mov -32(%rsi),%r13 + mov -24(%rsi),%r12 + mov -16(%rsi),%rbp + mov -8(%rsi),%rbx + lea (%rsi),%rsp +.Lpowerx5_epilogue: + ret +.size bn_powerx5,.-bn_powerx5 + +.globl bn_sqrx8x_internal +.hidden bn_sqrx8x_internal +.type bn_sqrx8x_internal,\@abi-omnipotent +.align 32 +bn_sqrx8x_internal: +__bn_sqrx8x_internal: + ################################################################## + # Squaring part: + # + # a) multiply-n-add everything but a[i]*a[i]; + # b) shift result of a) by 1 to the left and accumulate + # a[i]*a[i] products; + # + ################################################################## + # a[7]a[7]a[6]a[6]a[5]a[5]a[4]a[4]a[3]a[3]a[2]a[2]a[1]a[1]a[0]a[0] + # a[1]a[0] + # a[2]a[0] + # a[3]a[0] + # a[2]a[1] + # a[3]a[1] + # a[3]a[2] + # + # a[4]a[0] + # a[5]a[0] + # a[6]a[0] + # a[7]a[0] + # a[4]a[1] + # a[5]a[1] + # a[6]a[1] + # a[7]a[1] + # a[4]a[2] + # a[5]a[2] + # a[6]a[2] + # a[7]a[2] + # a[4]a[3] + # a[5]a[3] + # a[6]a[3] + # a[7]a[3] + # + # a[5]a[4] + # a[6]a[4] + # a[7]a[4] + # a[6]a[5] + # a[7]a[5] + # a[7]a[6] + # a[7]a[7]a[6]a[6]a[5]a[5]a[4]a[4]a[3]a[3]a[2]a[2]a[1]a[1]a[0]a[0] +___ +{ +my ($zero,$carry)=("%rbp","%rcx"); +my $aaptr=$zero; +$code.=<<___; + lea 48+8(%rsp),$tptr + lea ($aptr,$num),$aaptr + mov $num,0+8(%rsp) # save $num + mov $aaptr,8+8(%rsp) # save end of $aptr + jmp .Lsqr8x_zero_start + +.align 32 +.byte 0x66,0x66,0x66,0x2e,0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00 +.Lsqrx8x_zero: + .byte 0x3e + movdqa %xmm0,0*8($tptr) + movdqa %xmm0,2*8($tptr) + movdqa %xmm0,4*8($tptr) + movdqa %xmm0,6*8($tptr) +.Lsqr8x_zero_start: # aligned at 32 + movdqa %xmm0,8*8($tptr) + movdqa %xmm0,10*8($tptr) + movdqa %xmm0,12*8($tptr) + movdqa %xmm0,14*8($tptr) + lea 16*8($tptr),$tptr + sub \$64,$num + jnz .Lsqrx8x_zero + + mov 0*8($aptr),%rdx # a[0], modulo-scheduled + #xor %r9,%r9 # t[1], ex-$num, zero already + xor %r10,%r10 + xor %r11,%r11 + xor %r12,%r12 + xor %r13,%r13 + xor %r14,%r14 + xor %r15,%r15 + lea 48+8(%rsp),$tptr + xor $zero,$zero # cf=0, cf=0 + jmp .Lsqrx8x_outer_loop + +.align 32 +.Lsqrx8x_outer_loop: + mulx 1*8($aptr),%r8,%rax # a[1]*a[0] + adcx %r9,%r8 # a[1]*a[0]+=t[1] + adox %rax,%r10 + mulx 2*8($aptr),%r9,%rax # a[2]*a[0] + adcx %r10,%r9 + adox %rax,%r11 + .byte 0xc4,0xe2,0xab,0xf6,0x86,0x18,0x00,0x00,0x00 # mulx 3*8($aptr),%r10,%rax # ... + adcx %r11,%r10 + adox %rax,%r12 + .byte 0xc4,0xe2,0xa3,0xf6,0x86,0x20,0x00,0x00,0x00 # mulx 4*8($aptr),%r11,%rax + adcx %r12,%r11 + adox %rax,%r13 + mulx 5*8($aptr),%r12,%rax + adcx %r13,%r12 + adox %rax,%r14 + mulx 6*8($aptr),%r13,%rax + adcx %r14,%r13 + adox %r15,%rax + mulx 7*8($aptr),%r14,%r15 + mov 1*8($aptr),%rdx # a[1] + adcx %rax,%r14 + adox $zero,%r15 + adc 8*8($tptr),%r15 + mov %r8,1*8($tptr) # t[1] + mov %r9,2*8($tptr) # t[2] + sbb $carry,$carry # mov %cf,$carry + xor $zero,$zero # cf=0, of=0 + + + mulx 2*8($aptr),%r8,%rbx # a[2]*a[1] + mulx 3*8($aptr),%r9,%rax # a[3]*a[1] + adcx %r10,%r8 + adox %rbx,%r9 + mulx 4*8($aptr),%r10,%rbx # ... + adcx %r11,%r9 + adox %rax,%r10 + .byte 0xc4,0xe2,0xa3,0xf6,0x86,0x28,0x00,0x00,0x00 # mulx 5*8($aptr),%r11,%rax + adcx %r12,%r10 + adox %rbx,%r11 + .byte 0xc4,0xe2,0x9b,0xf6,0x9e,0x30,0x00,0x00,0x00 # mulx 6*8($aptr),%r12,%rbx + adcx %r13,%r11 + adox %r14,%r12 + .byte 0xc4,0x62,0x93,0xf6,0xb6,0x38,0x00,0x00,0x00 # mulx 7*8($aptr),%r13,%r14 + mov 2*8($aptr),%rdx # a[2] + adcx %rax,%r12 + adox %rbx,%r13 + adcx %r15,%r13 + adox $zero,%r14 # of=0 + adcx $zero,%r14 # cf=0 + + mov %r8,3*8($tptr) # t[3] + mov %r9,4*8($tptr) # t[4] + + mulx 3*8($aptr),%r8,%rbx # a[3]*a[2] + mulx 4*8($aptr),%r9,%rax # a[4]*a[2] + adcx %r10,%r8 + adox %rbx,%r9 + mulx 5*8($aptr),%r10,%rbx # ... + adcx %r11,%r9 + adox %rax,%r10 + .byte 0xc4,0xe2,0xa3,0xf6,0x86,0x30,0x00,0x00,0x00 # mulx 6*8($aptr),%r11,%rax + adcx %r12,%r10 + adox %r13,%r11 + .byte 0xc4,0x62,0x9b,0xf6,0xae,0x38,0x00,0x00,0x00 # mulx 7*8($aptr),%r12,%r13 + .byte 0x3e + mov 3*8($aptr),%rdx # a[3] + adcx %rbx,%r11 + adox %rax,%r12 + adcx %r14,%r12 + mov %r8,5*8($tptr) # t[5] + mov %r9,6*8($tptr) # t[6] + mulx 4*8($aptr),%r8,%rax # a[4]*a[3] + adox $zero,%r13 # of=0 + adcx $zero,%r13 # cf=0 + + mulx 5*8($aptr),%r9,%rbx # a[5]*a[3] + adcx %r10,%r8 + adox %rax,%r9 + mulx 6*8($aptr),%r10,%rax # ... + adcx %r11,%r9 + adox %r12,%r10 + mulx 7*8($aptr),%r11,%r12 + mov 4*8($aptr),%rdx # a[4] + mov 5*8($aptr),%r14 # a[5] + adcx %rbx,%r10 + adox %rax,%r11 + mov 6*8($aptr),%r15 # a[6] + adcx %r13,%r11 + adox $zero,%r12 # of=0 + adcx $zero,%r12 # cf=0 + + mov %r8,7*8($tptr) # t[7] + mov %r9,8*8($tptr) # t[8] + + mulx %r14,%r9,%rax # a[5]*a[4] + mov 7*8($aptr),%r8 # a[7] + adcx %r10,%r9 + mulx %r15,%r10,%rbx # a[6]*a[4] + adox %rax,%r10 + adcx %r11,%r10 + mulx %r8,%r11,%rax # a[7]*a[4] + mov %r14,%rdx # a[5] + adox %rbx,%r11 + adcx %r12,%r11 + #adox $zero,%rax # of=0 + adcx $zero,%rax # cf=0 + + mulx %r15,%r14,%rbx # a[6]*a[5] + mulx %r8,%r12,%r13 # a[7]*a[5] + mov %r15,%rdx # a[6] + lea 8*8($aptr),$aptr + adcx %r14,%r11 + adox %rbx,%r12 + adcx %rax,%r12 + adox $zero,%r13 + + .byte 0x67,0x67 + mulx %r8,%r8,%r14 # a[7]*a[6] + adcx %r8,%r13 + adcx $zero,%r14 + + cmp 8+8(%rsp),$aptr + je .Lsqrx8x_outer_break + + neg $carry # mov $carry,%cf + mov \$-8,%rcx + mov $zero,%r15 + mov 8*8($tptr),%r8 + adcx 9*8($tptr),%r9 # +=t[9] + adcx 10*8($tptr),%r10 # ... + adcx 11*8($tptr),%r11 + adc 12*8($tptr),%r12 + adc 13*8($tptr),%r13 + adc 14*8($tptr),%r14 + adc 15*8($tptr),%r15 + lea ($aptr),$aaptr + lea 2*64($tptr),$tptr + sbb %rax,%rax # mov %cf,$carry + + mov -64($aptr),%rdx # a[0] + mov %rax,16+8(%rsp) # offload $carry + mov $tptr,24+8(%rsp) + + #lea 8*8($tptr),$tptr # see 2*8*8($tptr) above + xor %eax,%eax # cf=0, of=0 + jmp .Lsqrx8x_loop + +.align 32 +.Lsqrx8x_loop: + mov %r8,%rbx + mulx 0*8($aaptr),%rax,%r8 # a[8]*a[i] + adcx %rax,%rbx # +=t[8] + adox %r9,%r8 + + mulx 1*8($aaptr),%rax,%r9 # ... + adcx %rax,%r8 + adox %r10,%r9 + + mulx 2*8($aaptr),%rax,%r10 + adcx %rax,%r9 + adox %r11,%r10 + + mulx 3*8($aaptr),%rax,%r11 + adcx %rax,%r10 + adox %r12,%r11 + + .byte 0xc4,0x62,0xfb,0xf6,0xa5,0x20,0x00,0x00,0x00 # mulx 4*8($aaptr),%rax,%r12 + adcx %rax,%r11 + adox %r13,%r12 + + mulx 5*8($aaptr),%rax,%r13 + adcx %rax,%r12 + adox %r14,%r13 + + mulx 6*8($aaptr),%rax,%r14 + mov %rbx,($tptr,%rcx,8) # store t[8+i] + mov \$0,%ebx + adcx %rax,%r13 + adox %r15,%r14 + + .byte 0xc4,0x62,0xfb,0xf6,0xbd,0x38,0x00,0x00,0x00 # mulx 7*8($aaptr),%rax,%r15 + mov 8($aptr,%rcx,8),%rdx # a[i] + adcx %rax,%r14 + adox %rbx,%r15 # %rbx is 0, of=0 + adcx %rbx,%r15 # cf=0 + + .byte 0x67 + inc %rcx # of=0 + jnz .Lsqrx8x_loop + + lea 8*8($aaptr),$aaptr + mov \$-8,%rcx + cmp 8+8(%rsp),$aaptr # done? + je .Lsqrx8x_break + + sub 16+8(%rsp),%rbx # mov 16(%rsp),%cf + .byte 0x66 + mov -64($aptr),%rdx + adcx 0*8($tptr),%r8 + adcx 1*8($tptr),%r9 + adc 2*8($tptr),%r10 + adc 3*8($tptr),%r11 + adc 4*8($tptr),%r12 + adc 5*8($tptr),%r13 + adc 6*8($tptr),%r14 + adc 7*8($tptr),%r15 + lea 8*8($tptr),$tptr + .byte 0x67 + sbb %rax,%rax # mov %cf,%rax + xor %ebx,%ebx # cf=0, of=0 + mov %rax,16+8(%rsp) # offload carry + jmp .Lsqrx8x_loop + +.align 32 +.Lsqrx8x_break: + sub 16+8(%rsp),%r8 # consume last carry + mov 24+8(%rsp),$carry # initial $tptr, borrow $carry + mov 0*8($aptr),%rdx # a[8], modulo-scheduled + xor %ebp,%ebp # xor $zero,$zero + mov %r8,0*8($tptr) + cmp $carry,$tptr # cf=0, of=0 + je .Lsqrx8x_outer_loop + + mov %r9,1*8($tptr) + mov 1*8($carry),%r9 + mov %r10,2*8($tptr) + mov 2*8($carry),%r10 + mov %r11,3*8($tptr) + mov 3*8($carry),%r11 + mov %r12,4*8($tptr) + mov 4*8($carry),%r12 + mov %r13,5*8($tptr) + mov 5*8($carry),%r13 + mov %r14,6*8($tptr) + mov 6*8($carry),%r14 + mov %r15,7*8($tptr) + mov 7*8($carry),%r15 + mov $carry,$tptr + jmp .Lsqrx8x_outer_loop + +.align 32 +.Lsqrx8x_outer_break: + mov %r9,9*8($tptr) # t[9] + movq %xmm3,%rcx # -$num + mov %r10,10*8($tptr) # ... + mov %r11,11*8($tptr) + mov %r12,12*8($tptr) + mov %r13,13*8($tptr) + mov %r14,14*8($tptr) +___ +} { +my $i="%rcx"; +$code.=<<___; + lea 48+8(%rsp),$tptr + mov ($aptr,$i),%rdx # a[0] + + mov 8($tptr),$A0[1] # t[1] + xor $A0[0],$A0[0] # t[0], of=0, cf=0 + mov 0+8(%rsp),$num # restore $num + adox $A0[1],$A0[1] + mov 16($tptr),$A1[0] # t[2] # prefetch + mov 24($tptr),$A1[1] # t[3] # prefetch + #jmp .Lsqrx4x_shift_n_add # happens to be aligned + +.align 32 +.Lsqrx4x_shift_n_add: + mulx %rdx,%rax,%rbx + adox $A1[0],$A1[0] + adcx $A0[0],%rax + .byte 0x48,0x8b,0x94,0x0e,0x08,0x00,0x00,0x00 # mov 8($aptr,$i),%rdx # a[i+1] # prefetch + .byte 0x4c,0x8b,0x97,0x20,0x00,0x00,0x00 # mov 32($tptr),$A0[0] # t[2*i+4] # prefetch + adox $A1[1],$A1[1] + adcx $A0[1],%rbx + mov 40($tptr),$A0[1] # t[2*i+4+1] # prefetch + mov %rax,0($tptr) + mov %rbx,8($tptr) + + mulx %rdx,%rax,%rbx + adox $A0[0],$A0[0] + adcx $A1[0],%rax + mov 16($aptr,$i),%rdx # a[i+2] # prefetch + mov 48($tptr),$A1[0] # t[2*i+6] # prefetch + adox $A0[1],$A0[1] + adcx $A1[1],%rbx + mov 56($tptr),$A1[1] # t[2*i+6+1] # prefetch + mov %rax,16($tptr) + mov %rbx,24($tptr) + + mulx %rdx,%rax,%rbx + adox $A1[0],$A1[0] + adcx $A0[0],%rax + mov 24($aptr,$i),%rdx # a[i+3] # prefetch + lea 32($i),$i + mov 64($tptr),$A0[0] # t[2*i+8] # prefetch + adox $A1[1],$A1[1] + adcx $A0[1],%rbx + mov 72($tptr),$A0[1] # t[2*i+8+1] # prefetch + mov %rax,32($tptr) + mov %rbx,40($tptr) + + mulx %rdx,%rax,%rbx + adox $A0[0],$A0[0] + adcx $A1[0],%rax + jrcxz .Lsqrx4x_shift_n_add_break + .byte 0x48,0x8b,0x94,0x0e,0x00,0x00,0x00,0x00 # mov 0($aptr,$i),%rdx # a[i+4] # prefetch + adox $A0[1],$A0[1] + adcx $A1[1],%rbx + mov 80($tptr),$A1[0] # t[2*i+10] # prefetch + mov 88($tptr),$A1[1] # t[2*i+10+1] # prefetch + mov %rax,48($tptr) + mov %rbx,56($tptr) + lea 64($tptr),$tptr + nop + jmp .Lsqrx4x_shift_n_add + +.align 32 +.Lsqrx4x_shift_n_add_break: + adcx $A1[1],%rbx + mov %rax,48($tptr) + mov %rbx,56($tptr) + lea 64($tptr),$tptr # end of t[] buffer +___ +} +###################################################################### +# Montgomery reduction part, "word-by-word" algorithm. +# +# This new path is inspired by multiple submissions from Intel, by +# Shay Gueron, Vlad Krasnov, Erdinc Ozturk, James Guilford, +# Vinodh Gopal... +{ +my ($nptr,$carry,$m0)=("%rbp","%rsi","%rdx"); + +$code.=<<___; + movq %xmm2,$nptr +__bn_sqrx8x_reduction: + xor %eax,%eax # initial top-most carry bit + mov 32+8(%rsp),%rbx # n0 + mov 48+8(%rsp),%rdx # "%r8", 8*0($tptr) + lea -8*8($nptr,$num),%rcx # end of n[] + #lea 48+8(%rsp,$num,2),$tptr # end of t[] buffer + mov %rcx, 0+8(%rsp) # save end of n[] + mov $tptr,8+8(%rsp) # save end of t[] + + lea 48+8(%rsp),$tptr # initial t[] window + jmp .Lsqrx8x_reduction_loop + +.align 32 +.Lsqrx8x_reduction_loop: + mov 8*1($tptr),%r9 + mov 8*2($tptr),%r10 + mov 8*3($tptr),%r11 + mov 8*4($tptr),%r12 + mov %rdx,%r8 + imulq %rbx,%rdx # n0*a[i] + mov 8*5($tptr),%r13 + mov 8*6($tptr),%r14 + mov 8*7($tptr),%r15 + mov %rax,24+8(%rsp) # store top-most carry bit + + lea 8*8($tptr),$tptr + xor $carry,$carry # cf=0,of=0 + mov \$-8,%rcx + jmp .Lsqrx8x_reduce + +.align 32 +.Lsqrx8x_reduce: + mov %r8, %rbx + mulx 8*0($nptr),%rax,%r8 # n[0] + adcx %rbx,%rax # discarded + adox %r9,%r8 + + mulx 8*1($nptr),%rbx,%r9 # n[1] + adcx %rbx,%r8 + adox %r10,%r9 + + mulx 8*2($nptr),%rbx,%r10 + adcx %rbx,%r9 + adox %r11,%r10 + + mulx 8*3($nptr),%rbx,%r11 + adcx %rbx,%r10 + adox %r12,%r11 + + .byte 0xc4,0x62,0xe3,0xf6,0xa5,0x20,0x00,0x00,0x00 # mulx 8*4($nptr),%rbx,%r12 + mov %rdx,%rax + mov %r8,%rdx + adcx %rbx,%r11 + adox %r13,%r12 + + mulx 32+8(%rsp),%rbx,%rdx # %rdx discarded + mov %rax,%rdx + mov %rax,64+48+8(%rsp,%rcx,8) # put aside n0*a[i] + + mulx 8*5($nptr),%rax,%r13 + adcx %rax,%r12 + adox %r14,%r13 + + mulx 8*6($nptr),%rax,%r14 + adcx %rax,%r13 + adox %r15,%r14 + + mulx 8*7($nptr),%rax,%r15 + mov %rbx,%rdx + adcx %rax,%r14 + adox $carry,%r15 # $carry is 0 + adcx $carry,%r15 # cf=0 + + .byte 0x67,0x67,0x67 + inc %rcx # of=0 + jnz .Lsqrx8x_reduce + + mov $carry,%rax # xor %rax,%rax + cmp 0+8(%rsp),$nptr # end of n[]? + jae .Lsqrx8x_no_tail + + mov 48+8(%rsp),%rdx # pull n0*a[0] + add 8*0($tptr),%r8 + lea 8*8($nptr),$nptr + mov \$-8,%rcx + adcx 8*1($tptr),%r9 + adcx 8*2($tptr),%r10 + adc 8*3($tptr),%r11 + adc 8*4($tptr),%r12 + adc 8*5($tptr),%r13 + adc 8*6($tptr),%r14 + adc 8*7($tptr),%r15 + lea 8*8($tptr),$tptr + sbb %rax,%rax # top carry + + xor $carry,$carry # of=0, cf=0 + mov %rax,16+8(%rsp) + jmp .Lsqrx8x_tail + +.align 32 +.Lsqrx8x_tail: + mov %r8,%rbx + mulx 8*0($nptr),%rax,%r8 + adcx %rax,%rbx + adox %r9,%r8 + + mulx 8*1($nptr),%rax,%r9 + adcx %rax,%r8 + adox %r10,%r9 + + mulx 8*2($nptr),%rax,%r10 + adcx %rax,%r9 + adox %r11,%r10 + + mulx 8*3($nptr),%rax,%r11 + adcx %rax,%r10 + adox %r12,%r11 + + .byte 0xc4,0x62,0xfb,0xf6,0xa5,0x20,0x00,0x00,0x00 # mulx 8*4($nptr),%rax,%r12 + adcx %rax,%r11 + adox %r13,%r12 + + mulx 8*5($nptr),%rax,%r13 + adcx %rax,%r12 + adox %r14,%r13 + + mulx 8*6($nptr),%rax,%r14 + adcx %rax,%r13 + adox %r15,%r14 + + mulx 8*7($nptr),%rax,%r15 + mov 72+48+8(%rsp,%rcx,8),%rdx # pull n0*a[i] + adcx %rax,%r14 + adox $carry,%r15 + mov %rbx,($tptr,%rcx,8) # save result + mov %r8,%rbx + adcx $carry,%r15 # cf=0 + + inc %rcx # of=0 + jnz .Lsqrx8x_tail + + cmp 0+8(%rsp),$nptr # end of n[]? + jae .Lsqrx8x_tail_done # break out of loop + + sub 16+8(%rsp),$carry # mov 16(%rsp),%cf + mov 48+8(%rsp),%rdx # pull n0*a[0] + lea 8*8($nptr),$nptr + adc 8*0($tptr),%r8 + adc 8*1($tptr),%r9 + adc 8*2($tptr),%r10 + adc 8*3($tptr),%r11 + adc 8*4($tptr),%r12 + adc 8*5($tptr),%r13 + adc 8*6($tptr),%r14 + adc 8*7($tptr),%r15 + lea 8*8($tptr),$tptr + sbb %rax,%rax + sub \$8,%rcx # mov \$-8,%rcx + + xor $carry,$carry # of=0, cf=0 + mov %rax,16+8(%rsp) + jmp .Lsqrx8x_tail + +.align 32 +.Lsqrx8x_tail_done: + add 24+8(%rsp),%r8 # can this overflow? + adc \$0,%r9 + adc \$0,%r10 + adc \$0,%r11 + adc \$0,%r12 + adc \$0,%r13 + adc \$0,%r14 + adc \$0,%r15 # can't overflow, because we + # started with "overhung" part + # of multiplication + mov $carry,%rax # xor %rax,%rax + + sub 16+8(%rsp),$carry # mov 16(%rsp),%cf +.Lsqrx8x_no_tail: # %cf is 0 if jumped here + adc 8*0($tptr),%r8 + movq %xmm3,%rcx + adc 8*1($tptr),%r9 + mov 8*7($nptr),$carry + movq %xmm2,$nptr # restore $nptr + adc 8*2($tptr),%r10 + adc 8*3($tptr),%r11 + adc 8*4($tptr),%r12 + adc 8*5($tptr),%r13 + adc 8*6($tptr),%r14 + adc 8*7($tptr),%r15 + adc %rax,%rax # top-most carry + + mov 32+8(%rsp),%rbx # n0 + mov 8*8($tptr,%rcx),%rdx # modulo-scheduled "%r8" + + mov %r8,8*0($tptr) # store top 512 bits + lea 8*8($tptr),%r8 # borrow %r8 + mov %r9,8*1($tptr) + mov %r10,8*2($tptr) + mov %r11,8*3($tptr) + mov %r12,8*4($tptr) + mov %r13,8*5($tptr) + mov %r14,8*6($tptr) + mov %r15,8*7($tptr) + + lea 8*8($tptr,%rcx),$tptr # start of current t[] window + cmp 8+8(%rsp),%r8 # end of t[]? + jb .Lsqrx8x_reduction_loop + ret +.size bn_sqrx8x_internal,.-bn_sqrx8x_internal +___ +} +############################################################## +# Post-condition, 4x unrolled +# +{ +my ($rptr,$nptr)=("%rdx","%rbp"); +$code.=<<___; +.align 32 +__bn_postx4x_internal: + mov 8*0($nptr),%r12 + mov %rcx,%r10 # -$num + mov %rcx,%r9 # -$num + neg %rax + sar \$3+2,%rcx + #lea 48+8(%rsp,%r9),$tptr + movq %xmm1,$rptr # restore $rptr + movq %xmm1,$aptr # prepare for back-to-back call + dec %r12 # so that after 'not' we get -n[0] + mov 8*1($nptr),%r13 + xor %r8,%r8 + mov 8*2($nptr),%r14 + mov 8*3($nptr),%r15 + jmp .Lsqrx4x_sub_entry + +.align 16 +.Lsqrx4x_sub: + mov 8*0($nptr),%r12 + mov 8*1($nptr),%r13 + mov 8*2($nptr),%r14 + mov 8*3($nptr),%r15 +.Lsqrx4x_sub_entry: + andn %rax,%r12,%r12 + lea 8*4($nptr),$nptr + andn %rax,%r13,%r13 + andn %rax,%r14,%r14 + andn %rax,%r15,%r15 + + neg %r8 # mov %r8,%cf + adc 8*0($tptr),%r12 + adc 8*1($tptr),%r13 + adc 8*2($tptr),%r14 + adc 8*3($tptr),%r15 + mov %r12,8*0($rptr) + lea 8*4($tptr),$tptr + mov %r13,8*1($rptr) + sbb %r8,%r8 # mov %cf,%r8 + mov %r14,8*2($rptr) + mov %r15,8*3($rptr) + lea 8*4($rptr),$rptr + + inc %rcx + jnz .Lsqrx4x_sub + + neg %r9 # restore $num + + ret +.size __bn_postx4x_internal,.-__bn_postx4x_internal +___ +} +}}} +{ +my ($inp,$num,$tbl,$idx)=$win64?("%rcx","%edx","%r8", "%r9d") : # Win64 order + ("%rdi","%esi","%rdx","%ecx"); # Unix order +my $out=$inp; +my $STRIDE=2**5*8; +my $N=$STRIDE/4; + +$code.=<<___; +.globl bn_scatter5 +.type bn_scatter5,\@abi-omnipotent +.align 16 +bn_scatter5: + cmp \$0, $num + jz .Lscatter_epilogue + lea ($tbl,$idx,8),$tbl +.Lscatter: + mov ($inp),%rax + lea 8($inp),$inp + mov %rax,($tbl) + lea 32*8($tbl),$tbl + sub \$1,$num + jnz .Lscatter +.Lscatter_epilogue: + ret +.size bn_scatter5,.-bn_scatter5 + +.globl bn_gather5 +.type bn_gather5,\@abi-omnipotent +.align 32 +bn_gather5: +.LSEH_begin_bn_gather5: # Win64 thing, but harmless in other cases + # I can't trust assembler to use specific encoding:-( + .byte 0x4c,0x8d,0x14,0x24 #lea (%rsp),%r10 + .byte 0x48,0x81,0xec,0x08,0x01,0x00,0x00 #sub $0x108,%rsp + lea .Linc(%rip),%rax + and \$-16,%rsp # shouldn't be formally required + + movd $idx,%xmm5 + movdqa 0(%rax),%xmm0 # 00000001000000010000000000000000 + movdqa 16(%rax),%xmm1 # 00000002000000020000000200000002 + lea 128($tbl),%r11 # size optimization + lea 128(%rsp),%rax # size optimization + + pshufd \$0,%xmm5,%xmm5 # broadcast $idx + movdqa %xmm1,%xmm4 + movdqa %xmm1,%xmm2 +___ +######################################################################## +# calculate mask by comparing 0..31 to $idx and save result to stack +# +for($i=0;$i<$STRIDE/16;$i+=4) { +$code.=<<___; + paddd %xmm0,%xmm1 + pcmpeqd %xmm5,%xmm0 # compare to 1,0 +___ +$code.=<<___ if ($i); + movdqa %xmm3,`16*($i-1)-128`(%rax) +___ +$code.=<<___; + movdqa %xmm4,%xmm3 + + paddd %xmm1,%xmm2 + pcmpeqd %xmm5,%xmm1 # compare to 3,2 + movdqa %xmm0,`16*($i+0)-128`(%rax) + movdqa %xmm4,%xmm0 + + paddd %xmm2,%xmm3 + pcmpeqd %xmm5,%xmm2 # compare to 5,4 + movdqa %xmm1,`16*($i+1)-128`(%rax) + movdqa %xmm4,%xmm1 + + paddd %xmm3,%xmm0 + pcmpeqd %xmm5,%xmm3 # compare to 7,6 + movdqa %xmm2,`16*($i+2)-128`(%rax) + movdqa %xmm4,%xmm2 +___ +} +$code.=<<___; + movdqa %xmm3,`16*($i-1)-128`(%rax) + jmp .Lgather + +.align 32 +.Lgather: + pxor %xmm4,%xmm4 + pxor %xmm5,%xmm5 +___ +for($i=0;$i<$STRIDE/16;$i+=4) { +$code.=<<___; + movdqa `16*($i+0)-128`(%r11),%xmm0 + movdqa `16*($i+1)-128`(%r11),%xmm1 + movdqa `16*($i+2)-128`(%r11),%xmm2 + pand `16*($i+0)-128`(%rax),%xmm0 + movdqa `16*($i+3)-128`(%r11),%xmm3 + pand `16*($i+1)-128`(%rax),%xmm1 + por %xmm0,%xmm4 + pand `16*($i+2)-128`(%rax),%xmm2 + por %xmm1,%xmm5 + pand `16*($i+3)-128`(%rax),%xmm3 + por %xmm2,%xmm4 + por %xmm3,%xmm5 +___ +} +$code.=<<___; + por %xmm5,%xmm4 + lea $STRIDE(%r11),%r11 + pshufd \$0x4e,%xmm4,%xmm0 + por %xmm4,%xmm0 + movq %xmm0,($out) # m0=bp[0] + lea 8($out),$out + sub \$1,$num + jnz .Lgather + + lea (%r10),%rsp + ret +.LSEH_end_bn_gather5: +.size bn_gather5,.-bn_gather5 +___ +} +$code.=<<___; +.align 64 +.Linc: + .long 0,0, 1,1 + .long 2,2, 2,2 +.asciz "Montgomery Multiplication with scatter/gather for x86_64, CRYPTOGAMS by " +___ + +# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame, +# CONTEXT *context,DISPATCHER_CONTEXT *disp) +if ($win64) { +$rec="%rcx"; +$frame="%rdx"; +$context="%r8"; +$disp="%r9"; + +$code.=<<___; +.extern __imp_RtlVirtualUnwind +.type mul_handler,\@abi-omnipotent +.align 16 +mul_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + mov 8($disp),%rsi # disp->ImageBase + mov 56($disp),%r11 # disp->HandlerData + + mov 0(%r11),%r10d # HandlerData[0] + lea (%rsi,%r10),%r10 # end of prologue label + cmp %r10,%rbx # context->RipRsp + + mov 4(%r11),%r10d # HandlerData[1] + lea (%rsi,%r10),%r10 # epilogue label + cmp %r10,%rbx # context->Rip>=epilogue label + jae .Lcommon_seh_tail + + lea .Lmul_epilogue(%rip),%r10 + cmp %r10,%rbx + ja .Lbody_40 + + mov 192($context),%r10 # pull $num + mov 8(%rax,%r10,8),%rax # pull saved stack pointer + + jmp .Lbody_proceed + +.Lbody_40: + mov 40(%rax),%rax # pull saved stack pointer +.Lbody_proceed: + mov -8(%rax),%rbx + mov -16(%rax),%rbp + mov -24(%rax),%r12 + mov -32(%rax),%r13 + mov -40(%rax),%r14 + mov -48(%rax),%r15 + mov %rbx,144($context) # restore context->Rbx + mov %rbp,160($context) # restore context->Rbp + mov %r12,216($context) # restore context->R12 + mov %r13,224($context) # restore context->R13 + mov %r14,232($context) # restore context->R14 + mov %r15,240($context) # restore context->R15 + +.Lcommon_seh_tail: + mov 8(%rax),%rdi + mov 16(%rax),%rsi + mov %rax,152($context) # restore context->Rsp + mov %rsi,168($context) # restore context->Rsi + mov %rdi,176($context) # restore context->Rdi + + mov 40($disp),%rdi # disp->ContextRecord + mov $context,%rsi # context + mov \$154,%ecx # sizeof(CONTEXT) + .long 0xa548f3fc # cld; rep movsq + + mov $disp,%rsi + xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER + mov 8(%rsi),%rdx # arg2, disp->ImageBase + mov 0(%rsi),%r8 # arg3, disp->ControlPc + mov 16(%rsi),%r9 # arg4, disp->FunctionEntry + mov 40(%rsi),%r10 # disp->ContextRecord + lea 56(%rsi),%r11 # &disp->HandlerData + lea 24(%rsi),%r12 # &disp->EstablisherFrame + mov %r10,32(%rsp) # arg5 + mov %r11,40(%rsp) # arg6 + mov %r12,48(%rsp) # arg7 + mov %rcx,56(%rsp) # arg8, (NULL) + call *__imp_RtlVirtualUnwind(%rip) + + mov \$1,%eax # ExceptionContinueSearch + add \$64,%rsp + popfq + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + pop %rdi + pop %rsi + ret +.size mul_handler,.-mul_handler + +.section .pdata +.align 4 + .rva .LSEH_begin_bn_mul_mont_gather5 + .rva .LSEH_end_bn_mul_mont_gather5 + .rva .LSEH_info_bn_mul_mont_gather5 + + .rva .LSEH_begin_bn_mul4x_mont_gather5 + .rva .LSEH_end_bn_mul4x_mont_gather5 + .rva .LSEH_info_bn_mul4x_mont_gather5 + + .rva .LSEH_begin_bn_power5 + .rva .LSEH_end_bn_power5 + .rva .LSEH_info_bn_power5 + + .rva .LSEH_begin_bn_from_mont8x + .rva .LSEH_end_bn_from_mont8x + .rva .LSEH_info_bn_from_mont8x +___ +$code.=<<___ if ($addx); + .rva .LSEH_begin_bn_mulx4x_mont_gather5 + .rva .LSEH_end_bn_mulx4x_mont_gather5 + .rva .LSEH_info_bn_mulx4x_mont_gather5 + + .rva .LSEH_begin_bn_powerx5 + .rva .LSEH_end_bn_powerx5 + .rva .LSEH_info_bn_powerx5 +___ +$code.=<<___; + .rva .LSEH_begin_bn_gather5 + .rva .LSEH_end_bn_gather5 + .rva .LSEH_info_bn_gather5 + +.section .xdata +.align 8 +.LSEH_info_bn_mul_mont_gather5: + .byte 9,0,0,0 + .rva mul_handler + .rva .Lmul_body,.Lmul_epilogue # HandlerData[] +.align 8 +.LSEH_info_bn_mul4x_mont_gather5: + .byte 9,0,0,0 + .rva mul_handler + .rva .Lmul4x_body,.Lmul4x_epilogue # HandlerData[] +.align 8 +.LSEH_info_bn_power5: + .byte 9,0,0,0 + .rva mul_handler + .rva .Lpower5_body,.Lpower5_epilogue # HandlerData[] +.align 8 +.LSEH_info_bn_from_mont8x: + .byte 9,0,0,0 + .rva mul_handler + .rva .Lfrom_body,.Lfrom_epilogue # HandlerData[] +___ +$code.=<<___ if ($addx); +.align 8 +.LSEH_info_bn_mulx4x_mont_gather5: + .byte 9,0,0,0 + .rva mul_handler + .rva .Lmulx4x_body,.Lmulx4x_epilogue # HandlerData[] +.align 8 +.LSEH_info_bn_powerx5: + .byte 9,0,0,0 + .rva mul_handler + .rva .Lpowerx5_body,.Lpowerx5_epilogue # HandlerData[] +___ +$code.=<<___; +.align 8 +.LSEH_info_bn_gather5: + .byte 0x01,0x0b,0x03,0x0a + .byte 0x0b,0x01,0x21,0x00 # sub rsp,0x108 + .byte 0x04,0xa3,0x00,0x00 # lea r10,(rsp) +.align 8 +___ +} + +$code =~ s/\`([^\`]*)\`/eval($1)/gem; + +print $code; +close STDOUT; diff --git a/external/boringssl/crypto/bn/bn.c b/external/boringssl/crypto/bn/bn.c new file mode 100644 index 0000000000..0ecaf8252d --- /dev/null +++ b/external/boringssl/crypto/bn/bn.c @@ -0,0 +1,353 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +#include +#include + +#include "internal.h" + + +BIGNUM *BN_new(void) { + BIGNUM *bn = OPENSSL_malloc(sizeof(BIGNUM)); + + if (bn == NULL) { + OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE); + return NULL; + } + + memset(bn, 0, sizeof(BIGNUM)); + bn->flags = BN_FLG_MALLOCED; + + return bn; +} + +void BN_init(BIGNUM *bn) { + memset(bn, 0, sizeof(BIGNUM)); +} + +void BN_free(BIGNUM *bn) { + if (bn == NULL) { + return; + } + + if ((bn->flags & BN_FLG_STATIC_DATA) == 0) { + OPENSSL_free(bn->d); + } + + if (bn->flags & BN_FLG_MALLOCED) { + OPENSSL_free(bn); + } else { + bn->d = NULL; + } +} + +void BN_clear_free(BIGNUM *bn) { + char should_free; + + if (bn == NULL) { + return; + } + + if (bn->d != NULL) { + OPENSSL_cleanse(bn->d, bn->dmax * sizeof(bn->d[0])); + if ((bn->flags & BN_FLG_STATIC_DATA) == 0) { + OPENSSL_free(bn->d); + } + } + + should_free = (bn->flags & BN_FLG_MALLOCED) != 0; + OPENSSL_cleanse(bn, sizeof(BIGNUM)); + if (should_free) { + OPENSSL_free(bn); + } +} + +BIGNUM *BN_dup(const BIGNUM *src) { + BIGNUM *copy; + + if (src == NULL) { + return NULL; + } + + copy = BN_new(); + if (copy == NULL) { + return NULL; + } + + if (!BN_copy(copy, src)) { + BN_free(copy); + return NULL; + } + + return copy; +} + +BIGNUM *BN_copy(BIGNUM *dest, const BIGNUM *src) { + if (src == dest) { + return dest; + } + + if (bn_wexpand(dest, src->top) == NULL) { + return NULL; + } + + memcpy(dest->d, src->d, sizeof(src->d[0]) * src->top); + + dest->top = src->top; + dest->neg = src->neg; + return dest; +} + +void BN_clear(BIGNUM *bn) { + if (bn->d != NULL) { + memset(bn->d, 0, bn->dmax * sizeof(bn->d[0])); + } + + bn->top = 0; + bn->neg = 0; +} + +const BIGNUM *BN_value_one(void) { + static const BN_ULONG kOneLimbs[1] = { 1 }; + static const BIGNUM kOne = STATIC_BIGNUM(kOneLimbs); + + return &kOne; +} + +void BN_with_flags(BIGNUM *out, const BIGNUM *in, int flags) { + memcpy(out, in, sizeof(BIGNUM)); + out->flags &= ~BN_FLG_MALLOCED; + out->flags |= BN_FLG_STATIC_DATA | flags; +} + +/* BN_num_bits_word returns the minimum number of bits needed to represent the + * value in |l|. */ +unsigned BN_num_bits_word(BN_ULONG l) { + static const unsigned char bits[256] = { + 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}; + +#if defined(OPENSSL_64_BIT) + if (l & 0xffffffff00000000L) { + if (l & 0xffff000000000000L) { + if (l & 0xff00000000000000L) { + return (bits[(int)(l >> 56)] + 56); + } else { + return (bits[(int)(l >> 48)] + 48); + } + } else { + if (l & 0x0000ff0000000000L) { + return (bits[(int)(l >> 40)] + 40); + } else { + return (bits[(int)(l >> 32)] + 32); + } + } + } else +#endif + { + if (l & 0xffff0000L) { + if (l & 0xff000000L) { + return (bits[(int)(l >> 24L)] + 24); + } else { + return (bits[(int)(l >> 16L)] + 16); + } + } else { + if (l & 0xff00L) { + return (bits[(int)(l >> 8)] + 8); + } else { + return (bits[(int)(l)]); + } + } + } +} + +unsigned BN_num_bits(const BIGNUM *bn) { + const int max = bn->top - 1; + + if (BN_is_zero(bn)) { + return 0; + } + + return max*BN_BITS2 + BN_num_bits_word(bn->d[max]); +} + +unsigned BN_num_bytes(const BIGNUM *bn) { + return (BN_num_bits(bn) + 7) / 8; +} + +void BN_zero(BIGNUM *bn) { + bn->top = bn->neg = 0; +} + +int BN_one(BIGNUM *bn) { + return BN_set_word(bn, 1); +} + +int BN_set_word(BIGNUM *bn, BN_ULONG value) { + if (value == 0) { + BN_zero(bn); + return 1; + } + + if (bn_wexpand(bn, 1) == NULL) { + return 0; + } + + bn->neg = 0; + bn->d[0] = value; + bn->top = 1; + return 1; +} + +int bn_set_words(BIGNUM *bn, const BN_ULONG *words, size_t num) { + if (bn_wexpand(bn, num) == NULL) { + return 0; + } + memmove(bn->d, words, num * sizeof(BN_ULONG)); + /* |bn_wexpand| verified that |num| isn't too large. */ + bn->top = (int)num; + bn_correct_top(bn); + bn->neg = 0; + return 1; +} + +int BN_is_negative(const BIGNUM *bn) { + return bn->neg != 0; +} + +void BN_set_negative(BIGNUM *bn, int sign) { + if (sign && !BN_is_zero(bn)) { + bn->neg = 1; + } else { + bn->neg = 0; + } +} + +BIGNUM *bn_wexpand(BIGNUM *bn, size_t words) { + BN_ULONG *a; + + if (words <= (size_t)bn->dmax) { + return bn; + } + + if (words > (INT_MAX / (4 * BN_BITS2))) { + OPENSSL_PUT_ERROR(BN, BN_R_BIGNUM_TOO_LONG); + return NULL; + } + + if (bn->flags & BN_FLG_STATIC_DATA) { + OPENSSL_PUT_ERROR(BN, BN_R_EXPAND_ON_STATIC_BIGNUM_DATA); + return NULL; + } + + a = OPENSSL_malloc(sizeof(BN_ULONG) * words); + if (a == NULL) { + OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE); + return NULL; + } + + memcpy(a, bn->d, sizeof(BN_ULONG) * bn->top); + + OPENSSL_free(bn->d); + bn->d = a; + bn->dmax = (int)words; + + return bn; +} + +BIGNUM *bn_expand(BIGNUM *bn, size_t bits) { + if (bits + BN_BITS2 - 1 < bits) { + OPENSSL_PUT_ERROR(BN, BN_R_BIGNUM_TOO_LONG); + return NULL; + } + return bn_wexpand(bn, (bits+BN_BITS2-1)/BN_BITS2); +} + +void bn_correct_top(BIGNUM *bn) { + BN_ULONG *ftl; + int tmp_top = bn->top; + + if (tmp_top > 0) { + for (ftl = &(bn->d[tmp_top - 1]); tmp_top > 0; tmp_top--) { + if (*(ftl--)) { + break; + } + } + bn->top = tmp_top; + } +} + +int BN_get_flags(const BIGNUM *bn, int flags) { + return bn->flags & flags; +} + +void BN_set_flags(BIGNUM *bn, int flags) { + bn->flags |= flags; +} diff --git a/external/boringssl/crypto/bn/bn_asn1.c b/external/boringssl/crypto/bn/bn_asn1.c new file mode 100644 index 0000000000..efb23355b9 --- /dev/null +++ b/external/boringssl/crypto/bn/bn_asn1.c @@ -0,0 +1,80 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include +#include + + +int BN_parse_asn1_unsigned(CBS *cbs, BIGNUM *ret) { + CBS child; + if (!CBS_get_asn1(cbs, &child, CBS_ASN1_INTEGER) || + CBS_len(&child) == 0) { + OPENSSL_PUT_ERROR(BN, BN_R_BAD_ENCODING); + return 0; + } + + if (CBS_data(&child)[0] & 0x80) { + OPENSSL_PUT_ERROR(BN, BN_R_NEGATIVE_NUMBER); + return 0; + } + + /* INTEGERs must be minimal. */ + if (CBS_data(&child)[0] == 0x00 && + CBS_len(&child) > 1 && + !(CBS_data(&child)[1] & 0x80)) { + OPENSSL_PUT_ERROR(BN, BN_R_BAD_ENCODING); + return 0; + } + + return BN_bin2bn(CBS_data(&child), CBS_len(&child), ret) != NULL; +} + +int BN_parse_asn1_unsigned_buggy(CBS *cbs, BIGNUM *ret) { + CBS child; + if (!CBS_get_asn1(cbs, &child, CBS_ASN1_INTEGER) || + CBS_len(&child) == 0) { + OPENSSL_PUT_ERROR(BN, BN_R_BAD_ENCODING); + return 0; + } + + /* This function intentionally does not reject negative numbers or non-minimal + * encodings. Estonian IDs issued between September 2014 to September 2015 are + * broken. See https://crbug.com/532048 and https://crbug.com/534766. + * + * TODO(davidben): Remove this code and callers in March 2016. */ + return BN_bin2bn(CBS_data(&child), CBS_len(&child), ret) != NULL; +} + +int BN_marshal_asn1(CBB *cbb, const BIGNUM *bn) { + /* Negative numbers are unsupported. */ + if (BN_is_negative(bn)) { + OPENSSL_PUT_ERROR(BN, BN_R_NEGATIVE_NUMBER); + return 0; + } + + CBB child; + if (!CBB_add_asn1(cbb, &child, CBS_ASN1_INTEGER) || + /* The number must be padded with a leading zero if the high bit would + * otherwise be set or if |bn| is zero. */ + (BN_num_bits(bn) % 8 == 0 && !CBB_add_u8(&child, 0x00)) || + !BN_bn2cbb_padded(&child, BN_num_bytes(bn), bn) || + !CBB_flush(cbb)) { + OPENSSL_PUT_ERROR(BN, BN_R_ENCODE_ERROR); + return 0; + } + + return 1; +} diff --git a/external/boringssl/crypto/bn/bn_test.cc b/external/boringssl/crypto/bn/bn_test.cc new file mode 100644 index 0000000000..d909ee2803 --- /dev/null +++ b/external/boringssl/crypto/bn/bn_test.cc @@ -0,0 +1,1943 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * + * Portions of the attached software ("Contribution") are developed by + * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. + * + * The Contribution is licensed pursuant to the Eric Young open source + * license provided above. + * + * The binary polynomial arithmetic software is originally written by + * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems + * Laboratories. */ + +/* For BIGNUM format macros. */ +#if !defined(__STDC_FORMAT_MACROS) +#define __STDC_FORMAT_MACROS +#endif + +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include "../crypto/test/scoped_types.h" +#include "../crypto/test/test_util.h" + + +// This program tests the BIGNUM implementation. It takes an optional -bc +// argument to write a transcript compatible with the UNIX bc utility. +// +// TODO(davidben): Rather than generate random inputs and depend on bc to check +// the results, most of these tests should use known answers. + +static const int num0 = 100; // number of tests +static const int num1 = 50; // additional tests for some functions +static const int num2 = 5; // number of tests for slow functions + +static bool test_add(FILE *fp); +static bool test_sub(FILE *fp); +static bool test_lshift1(FILE *fp); +static bool test_lshift(FILE *fp, BN_CTX *ctx, ScopedBIGNUM a); +static bool test_rshift1(FILE *fp); +static bool test_rshift(FILE *fp, BN_CTX *ctx); +static bool test_sqr(FILE *fp, BN_CTX *ctx); +static bool test_mul(FILE *fp); +static bool test_div(FILE *fp, BN_CTX *ctx); +static int rand_neg(); + +static bool test_div_word(FILE *fp); +static bool test_mont(FILE *fp, BN_CTX *ctx); +static bool test_mod(FILE *fp, BN_CTX *ctx); +static bool test_mod_mul(FILE *fp, BN_CTX *ctx); +static bool test_mod_exp(FILE *fp, BN_CTX *ctx); +static bool test_mod_exp_mont_consttime(FILE *fp, BN_CTX *ctx); +static bool test_exp(FILE *fp, BN_CTX *ctx); +static bool test_mod_sqrt(FILE *fp, BN_CTX *ctx); +static bool test_exp_mod_zero(void); +static bool test_small_prime(FILE *fp, BN_CTX *ctx); +static bool test_mod_exp_mont5(FILE *fp, BN_CTX *ctx); +static bool test_sqrt(FILE *fp, BN_CTX *ctx); +static bool test_bn2bin_padded(BN_CTX *ctx); +static bool test_dec2bn(BN_CTX *ctx); +static bool test_hex2bn(BN_CTX *ctx); +static bool test_asc2bn(BN_CTX *ctx); +static bool test_mpi(); +static bool test_rand(); +static bool test_asn1(); + +static const uint8_t kSample[] = + "\xC6\x4F\x43\x04\x2A\xEA\xCA\x6E\x58\x36\x80\x5B\xE8\xC9" + "\x9B\x04\x5D\x48\x36\xC2\xFD\x16\xC9\x64\xF0"; + +// A wrapper around puts that takes its arguments in the same order as our *_fp +// functions. +static void puts_fp(FILE *out, const char *m) { + if (out != nullptr) { + fputs(m, out); + } +} + +static void flush_fp(FILE *out) { + if (out != nullptr) { + fflush(out); + } +} + +static void message(FILE *out, const char *m) { + puts_fp(out, "print \"test "); + puts_fp(out, m); + puts_fp(out, "\\n\"\n"); +} + +int main(int argc, char *argv[]) { + CRYPTO_library_init(); + + ScopedFILE bc_file; + argc--; + argv++; + while (argc >= 1) { + if (strcmp(*argv, "-bc") == 0) { + if (argc < 2) { + fprintf(stderr, "Missing parameter to -bc\n"); + return 1; + } + bc_file.reset(fopen(argv[1], "w+")); + if (!bc_file) { + fprintf(stderr, "Failed to open %s: %s\n", argv[1], strerror(errno)); + } + argc--; + argv++; + } else { + fprintf(stderr, "Unknown option: %s\n", argv[0]); + return 1; + } + argc--; + argv++; + } + + + ScopedBN_CTX ctx(BN_CTX_new()); + if (!ctx) { + return 1; + } + + puts_fp(bc_file.get(), "/* This script, when run through the UNIX bc utility, " + "should produce a sequence of zeros. */\n"); + puts_fp(bc_file.get(), "/* tr a-f A-F < bn_test.out | sed s/BAsE/base/ | bc " + "| grep -v 0 */\n"); + puts_fp(bc_file.get(), "obase=16\nibase=16\n"); + + message(bc_file.get(), "BN_add"); + if (!test_add(bc_file.get())) { + return 1; + } + flush_fp(bc_file.get()); + + message(bc_file.get(), "BN_sub"); + if (!test_sub(bc_file.get())) { + return 1; + } + flush_fp(bc_file.get()); + + message(bc_file.get(), "BN_lshift1"); + if (!test_lshift1(bc_file.get())) { + return 1; + } + flush_fp(bc_file.get()); + + message(bc_file.get(), "BN_lshift (fixed)"); + ScopedBIGNUM sample(BN_bin2bn(kSample, sizeof(kSample) - 1, NULL)); + if (!sample) { + return 1; + } + if (!test_lshift(bc_file.get(), ctx.get(), std::move(sample))) { + return 1; + } + flush_fp(bc_file.get()); + + message(bc_file.get(), "BN_lshift"); + if (!test_lshift(bc_file.get(), ctx.get(), nullptr)) { + return 1; + } + flush_fp(bc_file.get()); + + message(bc_file.get(), "BN_rshift1"); + if (!test_rshift1(bc_file.get())) { + return 1; + } + flush_fp(bc_file.get()); + + message(bc_file.get(), "BN_rshift"); + if (!test_rshift(bc_file.get(), ctx.get())) { + return 1; + } + flush_fp(bc_file.get()); + + message(bc_file.get(), "BN_sqr"); + if (!test_sqr(bc_file.get(), ctx.get())) { + return 1; + } + flush_fp(bc_file.get()); + + message(bc_file.get(), "BN_mul"); + if (!test_mul(bc_file.get())) { + return 1; + } + flush_fp(bc_file.get()); + + message(bc_file.get(), "BN_div"); + if (!test_div(bc_file.get(), ctx.get())) { + return 1; + } + flush_fp(bc_file.get()); + + message(bc_file.get(), "BN_div_word"); + if (!test_div_word(bc_file.get())) { + return 1; + } + flush_fp(bc_file.get()); + + message(bc_file.get(), "BN_mod"); + if (!test_mod(bc_file.get(), ctx.get())) { + return 1; + } + flush_fp(bc_file.get()); + + message(bc_file.get(), "BN_mod_mul"); + if (!test_mod_mul(bc_file.get(), ctx.get())) { + return 1; + } + flush_fp(bc_file.get()); + + message(bc_file.get(), "BN_mont"); + if (!test_mont(bc_file.get(), ctx.get())) { + return 1; + } + flush_fp(bc_file.get()); + + message(bc_file.get(), "BN_mod_exp"); + if (!test_mod_exp(bc_file.get(), ctx.get())) { + return 1; + } + flush_fp(bc_file.get()); + + message(bc_file.get(), "BN_mod_exp_mont_consttime"); + if (!test_mod_exp_mont_consttime(bc_file.get(), ctx.get()) || + !test_mod_exp_mont5(bc_file.get(), ctx.get())) { + return 1; + } + flush_fp(bc_file.get()); + + message(bc_file.get(), "BN_exp"); + if (!test_exp(bc_file.get(), ctx.get()) || + !test_exp_mod_zero()) { + return 1; + } + flush_fp(bc_file.get()); + + message(bc_file.get(), "BN_mod_sqrt"); + if (!test_mod_sqrt(bc_file.get(), ctx.get())) { + return 1; + } + flush_fp(bc_file.get()); + + message(bc_file.get(), "Small prime generation"); + if (!test_small_prime(bc_file.get(), ctx.get())) { + return 1; + } + flush_fp(bc_file.get()); + + message(bc_file.get(), "BN_sqrt"); + if (!test_sqrt(bc_file.get(), ctx.get())) { + return 1; + } + flush_fp(bc_file.get()); + + if (!test_bn2bin_padded(ctx.get()) || + !test_dec2bn(ctx.get()) || + !test_hex2bn(ctx.get()) || + !test_asc2bn(ctx.get()) || + !test_mpi() || + !test_rand() || + !test_asn1()) { + return 1; + } + + printf("PASS\n"); + return 0; +} + +static int HexToBIGNUM(ScopedBIGNUM *out, const char *in) { + BIGNUM *raw = NULL; + int ret = BN_hex2bn(&raw, in); + out->reset(raw); + return ret; +} + +static bool test_add(FILE *fp) { + ScopedBIGNUM a(BN_new()); + ScopedBIGNUM b(BN_new()); + ScopedBIGNUM c(BN_new()); + if (!a || !b || !c || !BN_rand(a.get(), 512, 0, 0)) { + return false; + } + + for (int i = 0; i < num0; i++) { + if (!BN_rand(b.get(), 450 + i, 0, 0)) { + return false; + } + a->neg = rand_neg(); + b->neg = rand_neg(); + if (!BN_add(c.get(), a.get(), b.get())) { + return false; + } + if (fp != NULL) { + BN_print_fp(fp, a.get()); + puts_fp(fp, " + "); + BN_print_fp(fp, b.get()); + puts_fp(fp, " - "); + BN_print_fp(fp, c.get()); + puts_fp(fp, "\n"); + } + a->neg = !a->neg; + b->neg = !b->neg; + if (!BN_add(c.get(), c.get(), b.get()) || + !BN_add(c.get(), c.get(), a.get())) { + return false; + } + if (!BN_is_zero(c.get())) { + fprintf(stderr, "Add test failed!\n"); + return false; + } + } + return true; +} + +static bool test_sub(FILE *fp) { + ScopedBIGNUM a(BN_new()); + ScopedBIGNUM b(BN_new()); + ScopedBIGNUM c(BN_new()); + if (!a || !b || !c) { + return false; + } + + for (int i = 0; i < num0 + num1; i++) { + if (i < num1) { + if (!BN_rand(a.get(), 512, 0, 0) || + !BN_copy(b.get(), a.get()) || + !BN_set_bit(a.get(), i) || + !BN_add_word(b.get(), i)) { + return false; + } + } else { + if (!BN_rand(b.get(), 400 + i - num1, 0, 0)) { + return false; + } + a->neg = rand_neg(); + b->neg = rand_neg(); + } + if (!BN_sub(c.get(), a.get(), b.get())) { + return false; + } + if (fp != NULL) { + BN_print_fp(fp, a.get()); + puts_fp(fp, " - "); + BN_print_fp(fp, b.get()); + puts_fp(fp, " - "); + BN_print_fp(fp, c.get()); + puts_fp(fp, "\n"); + } + if (!BN_add(c.get(), c.get(), b.get()) || + !BN_sub(c.get(), c.get(), a.get())) { + return false; + } + if (!BN_is_zero(c.get())) { + fprintf(stderr, "Subtract test failed!\n"); + return false; + } + } + return true; +} + +static bool test_div(FILE *fp, BN_CTX *ctx) { + ScopedBIGNUM a(BN_new()); + ScopedBIGNUM b(BN_new()); + ScopedBIGNUM c(BN_new()); + ScopedBIGNUM d(BN_new()); + ScopedBIGNUM e(BN_new()); + if (!a || !b || !c || !d || !e) { + return false; + } + + if (!BN_one(a.get())) { + return false; + } + BN_zero(b.get()); + if (BN_div(d.get(), c.get(), a.get(), b.get(), ctx)) { + fprintf(stderr, "Division by zero succeeded!\n"); + return false; + } + ERR_clear_error(); + + for (int i = 0; i < num0 + num1; i++) { + if (i < num1) { + if (!BN_rand(a.get(), 400, 0, 0) || + !BN_copy(b.get(), a.get()) || + !BN_lshift(a.get(), a.get(), i) || + !BN_add_word(a.get(), i)) { + return false; + } + } else if (!BN_rand(b.get(), 50 + 3 * (i - num1), 0, 0)) { + return false; + } + a->neg = rand_neg(); + b->neg = rand_neg(); + if (!BN_div(d.get(), c.get(), a.get(), b.get(), ctx)) { + return false; + } + if (fp != NULL) { + BN_print_fp(fp, a.get()); + puts_fp(fp, " / "); + BN_print_fp(fp, b.get()); + puts_fp(fp, " - "); + BN_print_fp(fp, d.get()); + puts_fp(fp, "\n"); + + BN_print_fp(fp, a.get()); + puts_fp(fp, " % "); + BN_print_fp(fp, b.get()); + puts_fp(fp, " - "); + BN_print_fp(fp, c.get()); + puts_fp(fp, "\n"); + } + if (!BN_mul(e.get(), d.get(), b.get(), ctx) || + !BN_add(d.get(), e.get(), c.get()) || + !BN_sub(d.get(), d.get(), a.get())) { + return false; + } + if (!BN_is_zero(d.get())) { + fprintf(stderr, "Division test failed!\n"); + return false; + } + } + + // Test that BN_div never gives negative zero in the quotient. + if (!BN_set_word(a.get(), 1) || + !BN_set_word(b.get(), 2)) { + return false; + } + BN_set_negative(a.get(), 1); + if (!BN_div(d.get(), c.get(), a.get(), b.get(), ctx)) { + return false; + } + if (!BN_is_zero(d.get()) || BN_is_negative(d.get())) { + fprintf(stderr, "Division test failed!\n"); + return false; + } + + // Test that BN_div never gives negative zero in the remainder. + if (!BN_set_word(b.get(), 1)) { + return false; + } + if (!BN_div(d.get(), c.get(), a.get(), b.get(), ctx)) { + return false; + } + if (!BN_is_zero(c.get()) || BN_is_negative(c.get())) { + fprintf(stderr, "Division test failed!\n"); + return false; + } + + return true; +} + +static bool test_lshift1(FILE *fp) { + ScopedBIGNUM a(BN_new()); + ScopedBIGNUM b(BN_new()); + ScopedBIGNUM c(BN_new()); + if (!a || !b || !c || !BN_rand(a.get(), 200, 0, 0)) { + return false; + } + a->neg = rand_neg(); + for (int i = 0; i < num0; i++) { + if (!BN_lshift1(b.get(), a.get())) { + return false; + } + if (fp != NULL) { + BN_print_fp(fp, a.get()); + puts_fp(fp, " * 2"); + puts_fp(fp, " - "); + BN_print_fp(fp, b.get()); + puts_fp(fp, "\n"); + } + if (!BN_add(c.get(), a.get(), a.get()) || + !BN_sub(a.get(), b.get(), c.get())) { + return false; + } + if (!BN_is_zero(a.get())) { + fprintf(stderr, "Left shift one test failed!\n"); + return false; + } + + if (!BN_copy(a.get(), b.get())) { + return false; + } + } + return true; +} + +static bool test_rshift(FILE *fp, BN_CTX *ctx) { + ScopedBIGNUM a(BN_new()); + ScopedBIGNUM b(BN_new()); + ScopedBIGNUM c(BN_new()); + ScopedBIGNUM d(BN_new()); + ScopedBIGNUM e(BN_new()); + if (!a || !b || !c || !d || !e || !BN_one(c.get()) || + !BN_rand(a.get(), 200, 0, 0)) { + return false; + } + a->neg = rand_neg(); + for (int i = 0; i < num0; i++) { + if (!BN_rshift(b.get(), a.get(), i + 1) || + !BN_add(c.get(), c.get(), c.get())) { + return false; + } + if (fp != NULL) { + BN_print_fp(fp, a.get()); + puts_fp(fp, " / "); + BN_print_fp(fp, c.get()); + puts_fp(fp, " - "); + BN_print_fp(fp, b.get()); + puts_fp(fp, "\n"); + } + if (!BN_div(d.get(), e.get(), a.get(), c.get(), ctx) || + !BN_sub(d.get(), d.get(), b.get())) { + return false; + } + if (!BN_is_zero(d.get())) { + fprintf(stderr, "Right shift test failed!\n"); + return false; + } + } + return true; +} + +static bool test_rshift1(FILE *fp) { + ScopedBIGNUM a(BN_new()); + ScopedBIGNUM b(BN_new()); + ScopedBIGNUM c(BN_new()); + if (!a || !b || !c || !BN_rand(a.get(), 200, 0, 0)) { + return false; + } + a->neg = rand_neg(); + + for (int i = 0; i < num0; i++) { + if (!BN_rshift1(b.get(), a.get())) { + return false; + } + if (fp != NULL) { + BN_print_fp(fp, a.get()); + puts_fp(fp, " / 2"); + puts_fp(fp, " - "); + BN_print_fp(fp, b.get()); + puts_fp(fp, "\n"); + } + if (!BN_sub(c.get(), a.get(), b.get()) || + !BN_sub(c.get(), c.get(), b.get())) { + return false; + } + if (!BN_is_zero(c.get()) && !BN_abs_is_word(c.get(), 1)) { + fprintf(stderr, "Right shift one test failed!\n"); + return false; + } + if (!BN_copy(a.get(), b.get())) { + return false; + } + } + return true; +} + +static bool test_lshift(FILE *fp, BN_CTX *ctx, ScopedBIGNUM a) { + if (!a) { + a.reset(BN_new()); + if (!a || !BN_rand(a.get(), 200, 0, 0)) { + return false; + } + a->neg = rand_neg(); + } + + ScopedBIGNUM b(BN_new()); + ScopedBIGNUM c(BN_new()); + ScopedBIGNUM d(BN_new()); + if (!b || !c || !d || !BN_one(c.get())) { + return false; + } + + for (int i = 0; i < num0; i++) { + if (!BN_lshift(b.get(), a.get(), i + 1) || + !BN_add(c.get(), c.get(), c.get())) { + return false; + } + if (fp != NULL) { + BN_print_fp(fp, a.get()); + puts_fp(fp, " * "); + BN_print_fp(fp, c.get()); + puts_fp(fp, " - "); + BN_print_fp(fp, b.get()); + puts_fp(fp, "\n"); + } + if (!BN_mul(d.get(), a.get(), c.get(), ctx) || + !BN_sub(d.get(), d.get(), b.get())) { + return false; + } + if (!BN_is_zero(d.get())) { + fprintf(stderr, "Left shift test failed!\n"); + fprintf(stderr, "a="); + BN_print_fp(stderr, a.get()); + fprintf(stderr, "\nb="); + BN_print_fp(stderr, b.get()); + fprintf(stderr, "\nc="); + BN_print_fp(stderr, c.get()); + fprintf(stderr, "\nd="); + BN_print_fp(stderr, d.get()); + fprintf(stderr, "\n"); + return false; + } + } + return true; +} + +static bool test_mul(FILE *fp) { + ScopedBN_CTX ctx(BN_CTX_new()); + ScopedBIGNUM a(BN_new()); + ScopedBIGNUM b(BN_new()); + ScopedBIGNUM c(BN_new()); + ScopedBIGNUM d(BN_new()); + ScopedBIGNUM e(BN_new()); + if (!ctx || !a || !b || !c || !d || !e) { + return false; + } + + for (int i = 0; i < num0 + num1; i++) { + if (i <= num1) { + if (!BN_rand(a.get(), 100, 0, 0) || + !BN_rand(b.get(), 100, 0, 0)) { + return false; + } + } else if (!BN_rand(b.get(), i - num1, 0, 0)) { + return false; + } + a->neg = rand_neg(); + b->neg = rand_neg(); + if (!BN_mul(c.get(), a.get(), b.get(), ctx.get())) { + return false; + } + if (fp != NULL) { + BN_print_fp(fp, a.get()); + puts_fp(fp, " * "); + BN_print_fp(fp, b.get()); + puts_fp(fp, " - "); + BN_print_fp(fp, c.get()); + puts_fp(fp, "\n"); + } + if (!BN_div(d.get(), e.get(), c.get(), a.get(), ctx.get()) || + !BN_sub(d.get(), d.get(), b.get())) { + return false; + } + if (!BN_is_zero(d.get()) || !BN_is_zero(e.get())) { + fprintf(stderr, "Multiplication test failed!\n"); + return false; + } + } + + // Test that BN_mul never gives negative zero. + if (!BN_set_word(a.get(), 1)) { + return false; + } + BN_set_negative(a.get(), 1); + BN_zero(b.get()); + if (!BN_mul(c.get(), a.get(), b.get(), ctx.get())) { + return false; + } + if (!BN_is_zero(c.get()) || BN_is_negative(c.get())) { + fprintf(stderr, "Multiplication test failed!\n"); + return false; + } + + return true; +} + +static bool test_sqr(FILE *fp, BN_CTX *ctx) { + ScopedBIGNUM a(BN_new()); + ScopedBIGNUM c(BN_new()); + ScopedBIGNUM d(BN_new()); + ScopedBIGNUM e(BN_new()); + if (!a || !c || !d || !e) { + return false; + } + + for (int i = 0; i < num0; i++) { + if (!BN_rand(a.get(), 40 + i * 10, 0, 0)) { + return false; + } + a->neg = rand_neg(); + if (!BN_sqr(c.get(), a.get(), ctx)) { + return false; + } + if (fp != NULL) { + BN_print_fp(fp, a.get()); + puts_fp(fp, " * "); + BN_print_fp(fp, a.get()); + puts_fp(fp, " - "); + BN_print_fp(fp, c.get()); + puts_fp(fp, "\n"); + } + if (!BN_div(d.get(), e.get(), c.get(), a.get(), ctx) || + !BN_sub(d.get(), d.get(), a.get())) { + return false; + } + if (!BN_is_zero(d.get()) || !BN_is_zero(e.get())) { + fprintf(stderr, "Square test failed!\n"); + return false; + } + } + + // Regression test for a BN_sqr overflow bug. + BIGNUM *a_raw = a.get(); + if (!BN_hex2bn( + &a_raw, + "80000000000000008000000000000001FFFFFFFFFFFFFFFE0000000000000000") || + !BN_sqr(c.get(), a.get(), ctx)) { + return false; + } + if (fp != NULL) { + BN_print_fp(fp, a.get()); + puts_fp(fp, " * "); + BN_print_fp(fp, a.get()); + puts_fp(fp, " - "); + BN_print_fp(fp, c.get()); + puts_fp(fp, "\n"); + } + if (!BN_mul(d.get(), a.get(), a.get(), ctx)) { + return false; + } + if (BN_cmp(c.get(), d.get())) { + fprintf(stderr, + "Square test failed: BN_sqr and BN_mul produce " + "different results!\n"); + return false; + } + + // Regression test for a BN_sqr overflow bug. + a_raw = a.get(); + if (!BN_hex2bn( + &a_raw, + "80000000000000000000000080000001FFFFFFFE000000000000000000000000") || + !BN_sqr(c.get(), a.get(), ctx)) { + return false; + } + if (fp != NULL) { + BN_print_fp(fp, a.get()); + puts_fp(fp, " * "); + BN_print_fp(fp, a.get()); + puts_fp(fp, " - "); + BN_print_fp(fp, c.get()); + puts_fp(fp, "\n"); + } + if (!BN_mul(d.get(), a.get(), a.get(), ctx)) { + return false; + } + if (BN_cmp(c.get(), d.get())) { + fprintf(stderr, + "Square test failed: BN_sqr and BN_mul produce " + "different results!\n"); + return false; + } + + return true; +} + + +static int rand_neg() { + static unsigned int neg = 0; + static const int sign[8] = {0, 0, 0, 1, 1, 0, 1, 1}; + + return sign[(neg++) % 8]; +} + +static void print_word(FILE *fp, BN_ULONG w) { + fprintf(fp, BN_HEX_FMT1, w); +} + +static bool test_div_word(FILE *fp) { + ScopedBIGNUM a(BN_new()); + ScopedBIGNUM b(BN_new()); + if (!a || !b) { + return false; + } + + for (int i = 0; i < num0; i++) { + do { + if (!BN_rand(a.get(), 512, -1, 0) || + !BN_rand(b.get(), BN_BITS2, -1, 0)) { + return false; + } + } while (BN_is_zero(b.get())); + + if (!BN_copy(b.get(), a.get())) { + return false; + } + BN_ULONG s = b->d[0]; + BN_ULONG rmod = BN_mod_word(b.get(), s); + BN_ULONG r = BN_div_word(b.get(), s); + if (r == (BN_ULONG)-1) { + return false; + } + + if (rmod != r) { + fprintf(stderr, "Mod (word) test failed!\n"); + return false; + } + + if (fp != NULL) { + BN_print_fp(fp, a.get()); + puts_fp(fp, " / "); + print_word(fp, s); + puts_fp(fp, " - "); + BN_print_fp(fp, b.get()); + puts_fp(fp, "\n"); + + BN_print_fp(fp, a.get()); + puts_fp(fp, " % "); + print_word(fp, s); + puts_fp(fp, " - "); + print_word(fp, r); + puts_fp(fp, "\n"); + } + if (!BN_mul_word(b.get(), s) || + !BN_add_word(b.get(), r) || + !BN_sub(b.get(), a.get(), b.get())) { + return false; + } + if (!BN_is_zero(b.get())) { + fprintf(stderr, "Division (word) test failed!\n"); + return false; + } + } + return true; +} + +static bool test_mont(FILE *fp, BN_CTX *ctx) { + ScopedBIGNUM a(BN_new()); + ScopedBIGNUM b(BN_new()); + ScopedBIGNUM c(BN_new()); + ScopedBIGNUM d(BN_new()); + ScopedBIGNUM A(BN_new()); + ScopedBIGNUM B(BN_new()); + ScopedBIGNUM n(BN_new()); + ScopedBN_MONT_CTX mont(BN_MONT_CTX_new()); + if (!a || !b || !c || !d || !A || !B || !n || !mont) { + return false; + } + + BN_zero(n.get()); + if (BN_MONT_CTX_set(mont.get(), n.get(), ctx)) { + fprintf(stderr, "BN_MONT_CTX_set succeeded for zero modulus!\n"); + return false; + } + ERR_clear_error(); + + if (!BN_set_word(n.get(), 16)) { + return false; + } + if (BN_MONT_CTX_set(mont.get(), n.get(), ctx)) { + fprintf(stderr, "BN_MONT_CTX_set succeeded for even modulus!\n"); + return false; + } + ERR_clear_error(); + + if (!BN_rand(a.get(), 100, 0, 0) || + !BN_rand(b.get(), 100, 0, 0)) { + return false; + } + + for (int i = 0; i < num2; i++) { + int bits = (200 * (i + 1)) / num2; + + if (bits == 0) { + continue; + } + if (!BN_rand(n.get(), bits, 0, 1) || + !BN_MONT_CTX_set(mont.get(), n.get(), ctx) || + !BN_nnmod(a.get(), a.get(), n.get(), ctx) || + !BN_nnmod(b.get(), b.get(), n.get(), ctx) || + !BN_to_montgomery(A.get(), a.get(), mont.get(), ctx) || + !BN_to_montgomery(B.get(), b.get(), mont.get(), ctx) || + !BN_mod_mul_montgomery(c.get(), A.get(), B.get(), mont.get(), ctx) || + !BN_from_montgomery(A.get(), c.get(), mont.get(), ctx)) { + return false; + } + if (fp != NULL) { + BN_print_fp(fp, a.get()); + puts_fp(fp, " * "); + BN_print_fp(fp, b.get()); + puts_fp(fp, " % "); + BN_print_fp(fp, &mont->N); + puts_fp(fp, " - "); + BN_print_fp(fp, A.get()); + puts_fp(fp, "\n"); + } + if (!BN_mod_mul(d.get(), a.get(), b.get(), n.get(), ctx) || + !BN_sub(d.get(), d.get(), A.get())) { + return false; + } + if (!BN_is_zero(d.get())) { + fprintf(stderr, "Montgomery multiplication test failed!\n"); + return false; + } + } + + return true; +} + +static bool test_mod(FILE *fp, BN_CTX *ctx) { + ScopedBIGNUM a(BN_new()); + ScopedBIGNUM b(BN_new()); + ScopedBIGNUM c(BN_new()); + ScopedBIGNUM d(BN_new()); + ScopedBIGNUM e(BN_new()); + if (!a || !b || !c || !d || !e || + !BN_rand(a.get(), 1024, 0, 0)) { + return false; + } + + for (int i = 0; i < num0; i++) { + if (!BN_rand(b.get(), 450 + i * 10, 0, 0)) { + return false; + } + a->neg = rand_neg(); + b->neg = rand_neg(); + if (!BN_mod(c.get(), a.get(), b.get(), ctx)) { + return false; + } + if (fp != NULL) { + BN_print_fp(fp, a.get()); + puts_fp(fp, " % "); + BN_print_fp(fp, b.get()); + puts_fp(fp, " - "); + BN_print_fp(fp, c.get()); + puts_fp(fp, "\n"); + } + if (!BN_div(d.get(), e.get(), a.get(), b.get(), ctx) || + !BN_sub(e.get(), e.get(), c.get())) { + return false; + } + if (!BN_is_zero(e.get())) { + fprintf(stderr, "Modulo test failed!\n"); + return false; + } + } + return true; +} + +static bool test_mod_mul(FILE *fp, BN_CTX *ctx) { + ScopedBIGNUM a(BN_new()); + ScopedBIGNUM b(BN_new()); + ScopedBIGNUM c(BN_new()); + ScopedBIGNUM d(BN_new()); + ScopedBIGNUM e(BN_new()); + if (!a || !b || !c || !d || !e) { + return false; + } + + if (!BN_one(a.get()) || !BN_one(b.get())) { + return false; + } + BN_zero(c.get()); + if (BN_mod_mul(e.get(), a.get(), b.get(), c.get(), ctx)) { + fprintf(stderr, "BN_mod_mul with zero modulus succeeded!\n"); + return false; + } + ERR_clear_error(); + + for (int j = 0; j < 3; j++) { + if (!BN_rand(c.get(), 1024, 0, 0)) { + return false; + } + for (int i = 0; i < num0; i++) { + if (!BN_rand(a.get(), 475 + i * 10, 0, 0) || + !BN_rand(b.get(), 425 + i * 11, 0, 0)) { + return false; + } + a->neg = rand_neg(); + b->neg = rand_neg(); + if (!BN_mod_mul(e.get(), a.get(), b.get(), c.get(), ctx)) { + ERR_print_errors_fp(stderr); + return false; + } + if (fp != NULL) { + BN_print_fp(fp, a.get()); + puts_fp(fp, " * "); + BN_print_fp(fp, b.get()); + puts_fp(fp, " % "); + BN_print_fp(fp, c.get()); + if (a->neg != b->neg && !BN_is_zero(e.get())) { + // If (a*b) % c is negative, c must be added + // in order to obtain the normalized remainder + // (new with OpenSSL 0.9.7, previous versions of + // BN_mod_mul could generate negative results) + puts_fp(fp, " + "); + BN_print_fp(fp, c.get()); + } + puts_fp(fp, " - "); + BN_print_fp(fp, e.get()); + puts_fp(fp, "\n"); + } + if (!BN_mul(d.get(), a.get(), b.get(), ctx) || + !BN_sub(d.get(), d.get(), e.get()) || + !BN_div(a.get(), b.get(), d.get(), c.get(), ctx)) { + return false; + } + if (!BN_is_zero(b.get())) { + fprintf(stderr, "Modulo multiply test failed!\n"); + ERR_print_errors_fp(stderr); + return false; + } + } + } + return true; +} + +static bool test_mod_exp(FILE *fp, BN_CTX *ctx) { + ScopedBIGNUM a(BN_new()); + ScopedBIGNUM b(BN_new()); + ScopedBIGNUM c(BN_new()); + ScopedBIGNUM d(BN_new()); + ScopedBIGNUM e(BN_new()); + if (!a || !b || !c || !d || !e) { + return false; + } + + if (!BN_one(a.get()) || !BN_one(b.get())) { + return false; + } + BN_zero(c.get()); + if (BN_mod_exp(d.get(), a.get(), b.get(), c.get(), ctx)) { + fprintf(stderr, "BN_mod_exp with zero modulus succeeded!\n"); + return 0; + } + ERR_clear_error(); + + if (!BN_rand(c.get(), 30, 0, 1)) { // must be odd for montgomery + return false; + } + for (int i = 0; i < num2; i++) { + if (!BN_rand(a.get(), 20 + i * 5, 0, 0) || + !BN_rand(b.get(), 2 + i, 0, 0) || + !BN_mod_exp(d.get(), a.get(), b.get(), c.get(), ctx)) { + return false; + } + + if (fp != NULL) { + BN_print_fp(fp, a.get()); + puts_fp(fp, " ^ "); + BN_print_fp(fp, b.get()); + puts_fp(fp, " % "); + BN_print_fp(fp, c.get()); + puts_fp(fp, " - "); + BN_print_fp(fp, d.get()); + puts_fp(fp, "\n"); + } + if (!BN_exp(e.get(), a.get(), b.get(), ctx) || + !BN_sub(e.get(), e.get(), d.get()) || + !BN_div(a.get(), b.get(), e.get(), c.get(), ctx)) { + return false; + } + if (!BN_is_zero(b.get())) { + fprintf(stderr, "Modulo exponentiation test failed!\n"); + return false; + } + } + + // Regression test for carry propagation bug in sqr8x_reduction. + if (!HexToBIGNUM(&a, "050505050505") || + !HexToBIGNUM(&b, "02") || + !HexToBIGNUM( + &c, + "4141414141414141414141274141414141414141414141414141414141414141" + "4141414141414141414141414141414141414141414141414141414141414141" + "4141414141414141414141800000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000001") || + !BN_mod_exp(d.get(), a.get(), b.get(), c.get(), ctx) || + !BN_mul(e.get(), a.get(), a.get(), ctx)) { + return false; + } + if (BN_cmp(d.get(), e.get()) != 0) { + fprintf(stderr, "BN_mod_exp and BN_mul produce different results!\n"); + return false; + } + + return true; +} + +static bool test_mod_exp_mont_consttime(FILE *fp, BN_CTX *ctx) { + ScopedBIGNUM a(BN_new()); + ScopedBIGNUM b(BN_new()); + ScopedBIGNUM c(BN_new()); + ScopedBIGNUM d(BN_new()); + ScopedBIGNUM e(BN_new()); + if (!a || !b || !c || !d || !e) { + return false; + } + + if (!BN_one(a.get()) || !BN_one(b.get())) { + return false; + } + BN_zero(c.get()); + if (BN_mod_exp_mont_consttime(d.get(), a.get(), b.get(), c.get(), ctx, + nullptr)) { + fprintf(stderr, "BN_mod_exp_mont_consttime with zero modulus succeeded!\n"); + return 0; + } + ERR_clear_error(); + + if (!BN_set_word(c.get(), 16)) { + return false; + } + if (BN_mod_exp_mont_consttime(d.get(), a.get(), b.get(), c.get(), ctx, + nullptr)) { + fprintf(stderr, "BN_mod_exp_mont_consttime with even modulus succeeded!\n"); + return 0; + } + ERR_clear_error(); + + if (!BN_rand(c.get(), 30, 0, 1)) { // must be odd for montgomery + return false; + } + for (int i = 0; i < num2; i++) { + if (!BN_rand(a.get(), 20 + i * 5, 0, 0) || + !BN_rand(b.get(), 2 + i, 0, 0) || + !BN_mod_exp_mont_consttime(d.get(), a.get(), b.get(), c.get(), ctx, + NULL)) { + return false; + } + + if (fp != NULL) { + BN_print_fp(fp, a.get()); + puts_fp(fp, " ^ "); + BN_print_fp(fp, b.get()); + puts_fp(fp, " % "); + BN_print_fp(fp, c.get()); + puts_fp(fp, " - "); + BN_print_fp(fp, d.get()); + puts_fp(fp, "\n"); + } + if (!BN_exp(e.get(), a.get(), b.get(), ctx) || + !BN_sub(e.get(), e.get(), d.get()) || + !BN_div(a.get(), b.get(), e.get(), c.get(), ctx)) { + return false; + } + if (!BN_is_zero(b.get())) { + fprintf(stderr, "Modulo exponentiation test failed!\n"); + return false; + } + } + return true; +} + +// Test constant-time modular exponentiation with 1024-bit inputs, +// which on x86_64 cause a different code branch to be taken. +static bool test_mod_exp_mont5(FILE *fp, BN_CTX *ctx) { + ScopedBIGNUM a(BN_new()); + ScopedBIGNUM p(BN_new()); + ScopedBIGNUM m(BN_new()); + ScopedBIGNUM d(BN_new()); + ScopedBIGNUM e(BN_new()); + if (!a || !p || !m || !d || !e || + !BN_rand(m.get(), 1024, 0, 1) || // must be odd for montgomery + !BN_rand(a.get(), 1024, 0, 0)) { + return false; + } + // Zero exponent. + BN_zero(p.get()); + if (!BN_mod_exp_mont_consttime(d.get(), a.get(), p.get(), m.get(), ctx, + NULL)) { + return false; + } + if (!BN_is_one(d.get())) { + fprintf(stderr, "Modular exponentiation test failed!\n"); + return false; + } + if (!BN_rand(p.get(), 1024, 0, 0)) { + return false; + } + // Zero input. + BN_zero(a.get()); + if (!BN_mod_exp_mont_consttime(d.get(), a.get(), p.get(), m.get(), ctx, + NULL)) { + return false; + } + if (!BN_is_zero(d.get())) { + fprintf(stderr, "Modular exponentiation test failed!\n"); + return false; + } + // Craft an input whose Montgomery representation is 1, i.e., shorter than the + // modulus m, in order to test the const time precomputation + // scattering/gathering. + ScopedBN_MONT_CTX mont(BN_MONT_CTX_new()); + if (!mont || !BN_one(a.get()) || + !BN_MONT_CTX_set(mont.get(), m.get(), ctx) || + !BN_from_montgomery(e.get(), a.get(), mont.get(), ctx) || + !BN_mod_exp_mont_consttime(d.get(), e.get(), p.get(), m.get(), ctx, + NULL) || + !BN_mod_exp(a.get(), e.get(), p.get(), m.get(), ctx)) { + return false; + } + if (BN_cmp(a.get(), d.get()) != 0) { + fprintf(stderr, "Modular exponentiation test failed!\n"); + return false; + } + // Finally, some regular test vectors. + if (!BN_rand(e.get(), 1024, 0, 0) || + !BN_mod_exp_mont_consttime(d.get(), e.get(), p.get(), m.get(), ctx, + NULL) || + !BN_mod_exp(a.get(), e.get(), p.get(), m.get(), ctx)) { + return false; + } + if (BN_cmp(a.get(), d.get()) != 0) { + fprintf(stderr, "Modular exponentiation test failed!\n"); + return false; + } + + return true; +} + +static bool test_exp(FILE *fp, BN_CTX *ctx) { + ScopedBIGNUM a(BN_new()); + ScopedBIGNUM b(BN_new()); + ScopedBIGNUM d(BN_new()); + ScopedBIGNUM e(BN_new()); + if (!a || !b || !d || !e) { + return false; + } + + for (int i = 0; i < num2; i++) { + if (!BN_rand(a.get(), 20 + i * 5, 0, 0) || + !BN_rand(b.get(), 2 + i, 0, 0) || + !BN_exp(d.get(), a.get(), b.get(), ctx)) { + return false; + } + + if (fp != NULL) { + BN_print_fp(fp, a.get()); + puts_fp(fp, " ^ "); + BN_print_fp(fp, b.get()); + puts_fp(fp, " - "); + BN_print_fp(fp, d.get()); + puts_fp(fp, "\n"); + } + if (!BN_one(e.get())) { + return false; + } + while (!BN_is_zero(b.get())) { + if (!BN_mul(e.get(), e.get(), a.get(), ctx) || + !BN_sub(b.get(), b.get(), BN_value_one())) { + return false; + } + } + if (!BN_sub(e.get(), e.get(), d.get())) { + return false; + } + if (!BN_is_zero(e.get())) { + fprintf(stderr, "Exponentiation test failed!\n"); + return false; + } + } + return true; +} + +// test_exp_mod_zero tests that 1**0 mod 1 == 0. +static bool test_exp_mod_zero(void) { + ScopedBIGNUM zero(BN_new()), a(BN_new()), r(BN_new()); + if (!zero || !a || !r || !BN_rand(a.get(), 1024, 0, 0)) { + return false; + } + BN_zero(zero.get()); + + if (!BN_mod_exp(r.get(), a.get(), zero.get(), BN_value_one(), nullptr) || + !BN_is_zero(r.get()) || + !BN_mod_exp_mont(r.get(), a.get(), zero.get(), BN_value_one(), nullptr, + nullptr) || + !BN_is_zero(r.get()) || + !BN_mod_exp_mont_consttime(r.get(), a.get(), zero.get(), BN_value_one(), + nullptr, nullptr) || + !BN_is_zero(r.get()) || + !BN_mod_exp_mont_word(r.get(), 42, zero.get(), BN_value_one(), nullptr, + nullptr) || + !BN_is_zero(r.get())) { + return false; + } + + return true; +} + +static bool test_mod_sqrt(FILE *fp, BN_CTX *ctx) { + ScopedBIGNUM a(BN_new()); + ScopedBIGNUM p(BN_new()); + ScopedBIGNUM r(BN_new()); + if (!a || !p || !r) { + return false; + } + + for (int i = 0; i < 16; i++) { + if (i < 8) { + const unsigned kPrimes[8] = {2, 3, 5, 7, 11, 13, 17, 19}; + if (!BN_set_word(p.get(), kPrimes[i])) { + return false; + } + } else { + if (!BN_set_word(a.get(), 32) || + !BN_set_word(r.get(), 2 * i + 1) || + !BN_generate_prime_ex(p.get(), 256, 0, a.get(), r.get(), nullptr)) { + return false; + } + } + p->neg = rand_neg(); + + for (int j = 0; j < num2; j++) { + // construct 'a' such that it is a square modulo p, but in general not a + // proper square and not reduced modulo p + if (!BN_rand(r.get(), 256, 0, 3) || + !BN_nnmod(r.get(), r.get(), p.get(), ctx) || + !BN_mod_sqr(r.get(), r.get(), p.get(), ctx) || + !BN_rand(a.get(), 256, 0, 3) || + !BN_nnmod(a.get(), a.get(), p.get(), ctx) || + !BN_mod_sqr(a.get(), a.get(), p.get(), ctx) || + !BN_mul(a.get(), a.get(), r.get(), ctx)) { + return false; + } + if (rand_neg() && !BN_sub(a.get(), a.get(), p.get())) { + return false; + } + + if (!BN_mod_sqrt(r.get(), a.get(), p.get(), ctx) || + !BN_mod_sqr(r.get(), r.get(), p.get(), ctx) || + !BN_nnmod(a.get(), a.get(), p.get(), ctx)) { + return false; + } + + if (BN_cmp(a.get(), r.get()) != 0) { + fprintf(stderr, "BN_mod_sqrt failed: a = "); + BN_print_fp(stderr, a.get()); + fprintf(stderr, ", r = "); + BN_print_fp(stderr, r.get()); + fprintf(stderr, ", p = "); + BN_print_fp(stderr, p.get()); + fprintf(stderr, "\n"); + return false; + } + } + } + return true; +} + +static bool test_small_prime(FILE *fp, BN_CTX *ctx) { + static const unsigned kBits = 10; + + ScopedBIGNUM r(BN_new()); + if (!r || !BN_generate_prime_ex(r.get(), static_cast(kBits), 0, NULL, + NULL, NULL)) { + return false; + } + if (BN_num_bits(r.get()) != kBits) { + fprintf(fp, "Expected %u bit prime, got %u bit number\n", kBits, + BN_num_bits(r.get())); + return false; + } + + return true; +} + +static bool test_sqrt(FILE *fp, BN_CTX *ctx) { + ScopedBIGNUM n(BN_new()); + ScopedBIGNUM nn(BN_new()); + ScopedBIGNUM sqrt(BN_new()); + if (!n || !nn || !sqrt) { + return false; + } + + // Test some random squares. + for (int i = 0; i < 100; i++) { + if (!BN_rand(n.get(), 1024 /* bit length */, + -1 /* no modification of top bits */, + 0 /* don't modify bottom bit */) || + !BN_mul(nn.get(), n.get(), n.get(), ctx) || + !BN_sqrt(sqrt.get(), nn.get(), ctx)) { + ERR_print_errors_fp(stderr); + return false; + } + if (BN_cmp(n.get(), sqrt.get()) != 0) { + fprintf(stderr, "Bad result from BN_sqrt.\n"); + return false; + } + } + + // Test some non-squares. + for (int i = 0; i < 100; i++) { + if (!BN_rand(n.get(), 1024 /* bit length */, + -1 /* no modification of top bits */, + 0 /* don't modify bottom bit */) || + !BN_mul(nn.get(), n.get(), n.get(), ctx) || + !BN_add(nn.get(), nn.get(), BN_value_one())) { + ERR_print_errors_fp(stderr); + return false; + } + + if (BN_sqrt(sqrt.get(), nn.get(), ctx)) { + char *nn_str = BN_bn2dec(nn.get()); + fprintf(stderr, "BIO_sqrt didn't fail on a non-square: %s\n", nn_str); + OPENSSL_free(nn_str); + } + } + + return true; +} + +static bool test_bn2bin_padded(BN_CTX *ctx) { + uint8_t zeros[256], out[256], reference[128]; + + memset(zeros, 0, sizeof(zeros)); + + // Test edge case at 0. + ScopedBIGNUM n(BN_new()); + if (!n || !BN_bn2bin_padded(NULL, 0, n.get())) { + fprintf(stderr, + "BN_bn2bin_padded failed to encode 0 in an empty buffer.\n"); + return false; + } + memset(out, -1, sizeof(out)); + if (!BN_bn2bin_padded(out, sizeof(out), n.get())) { + fprintf(stderr, + "BN_bn2bin_padded failed to encode 0 in a non-empty buffer.\n"); + return false; + } + if (memcmp(zeros, out, sizeof(out))) { + fprintf(stderr, "BN_bn2bin_padded did not zero buffer.\n"); + return false; + } + + // Test a random numbers at various byte lengths. + for (size_t bytes = 128 - 7; bytes <= 128; bytes++) { + if (!BN_rand(n.get(), bytes * 8, 0 /* make sure top bit is 1 */, + 0 /* don't modify bottom bit */)) { + ERR_print_errors_fp(stderr); + return false; + } + if (BN_num_bytes(n.get()) != bytes || + BN_bn2bin(n.get(), reference) != bytes) { + fprintf(stderr, "Bad result from BN_rand; bytes.\n"); + return false; + } + // Empty buffer should fail. + if (BN_bn2bin_padded(NULL, 0, n.get())) { + fprintf(stderr, + "BN_bn2bin_padded incorrectly succeeded on empty buffer.\n"); + return false; + } + // One byte short should fail. + if (BN_bn2bin_padded(out, bytes - 1, n.get())) { + fprintf(stderr, "BN_bn2bin_padded incorrectly succeeded on short.\n"); + return false; + } + // Exactly right size should encode. + if (!BN_bn2bin_padded(out, bytes, n.get()) || + memcmp(out, reference, bytes) != 0) { + fprintf(stderr, "BN_bn2bin_padded gave a bad result.\n"); + return false; + } + // Pad up one byte extra. + if (!BN_bn2bin_padded(out, bytes + 1, n.get()) || + memcmp(out + 1, reference, bytes) || memcmp(out, zeros, 1)) { + fprintf(stderr, "BN_bn2bin_padded gave a bad result.\n"); + return false; + } + // Pad up to 256. + if (!BN_bn2bin_padded(out, sizeof(out), n.get()) || + memcmp(out + sizeof(out) - bytes, reference, bytes) || + memcmp(out, zeros, sizeof(out) - bytes)) { + fprintf(stderr, "BN_bn2bin_padded gave a bad result.\n"); + return false; + } + } + + return true; +} + +static int DecimalToBIGNUM(ScopedBIGNUM *out, const char *in) { + BIGNUM *raw = NULL; + int ret = BN_dec2bn(&raw, in); + out->reset(raw); + return ret; +} + +static bool test_dec2bn(BN_CTX *ctx) { + ScopedBIGNUM bn; + int ret = DecimalToBIGNUM(&bn, "0"); + if (ret != 1 || !BN_is_zero(bn.get()) || BN_is_negative(bn.get())) { + fprintf(stderr, "BN_dec2bn gave a bad result.\n"); + return false; + } + + ret = DecimalToBIGNUM(&bn, "256"); + if (ret != 3 || !BN_is_word(bn.get(), 256) || BN_is_negative(bn.get())) { + fprintf(stderr, "BN_dec2bn gave a bad result.\n"); + return false; + } + + ret = DecimalToBIGNUM(&bn, "-42"); + if (ret != 3 || !BN_abs_is_word(bn.get(), 42) || !BN_is_negative(bn.get())) { + fprintf(stderr, "BN_dec2bn gave a bad result.\n"); + return false; + } + + ret = DecimalToBIGNUM(&bn, "-0"); + if (ret != 2 || !BN_is_zero(bn.get()) || BN_is_negative(bn.get())) { + fprintf(stderr, "BN_dec2bn gave a bad result.\n"); + return false; + } + + ret = DecimalToBIGNUM(&bn, "42trailing garbage is ignored"); + if (ret != 2 || !BN_abs_is_word(bn.get(), 42) || BN_is_negative(bn.get())) { + fprintf(stderr, "BN_dec2bn gave a bad result.\n"); + return false; + } + + return true; +} + +static bool test_hex2bn(BN_CTX *ctx) { + ScopedBIGNUM bn; + int ret = HexToBIGNUM(&bn, "0"); + if (ret != 1 || !BN_is_zero(bn.get()) || BN_is_negative(bn.get())) { + fprintf(stderr, "BN_hex2bn gave a bad result.\n"); + return false; + } + + ret = HexToBIGNUM(&bn, "256"); + if (ret != 3 || !BN_is_word(bn.get(), 0x256) || BN_is_negative(bn.get())) { + fprintf(stderr, "BN_hex2bn gave a bad result.\n"); + return false; + } + + ret = HexToBIGNUM(&bn, "-42"); + if (ret != 3 || !BN_abs_is_word(bn.get(), 0x42) || !BN_is_negative(bn.get())) { + fprintf(stderr, "BN_hex2bn gave a bad result.\n"); + return false; + } + + ret = HexToBIGNUM(&bn, "-0"); + if (ret != 2 || !BN_is_zero(bn.get()) || BN_is_negative(bn.get())) { + fprintf(stderr, "BN_hex2bn gave a bad result.\n"); + return false; + } + + ret = HexToBIGNUM(&bn, "abctrailing garbage is ignored"); + if (ret != 3 || !BN_is_word(bn.get(), 0xabc) || BN_is_negative(bn.get())) { + fprintf(stderr, "BN_hex2bn gave a bad result.\n"); + return false; + } + + return true; +} + +static ScopedBIGNUM ASCIIToBIGNUM(const char *in) { + BIGNUM *raw = NULL; + if (!BN_asc2bn(&raw, in)) { + return nullptr; + } + return ScopedBIGNUM(raw); +} + +static bool test_asc2bn(BN_CTX *ctx) { + ScopedBIGNUM bn = ASCIIToBIGNUM("0"); + if (!bn || !BN_is_zero(bn.get()) || BN_is_negative(bn.get())) { + fprintf(stderr, "BN_asc2bn gave a bad result.\n"); + return false; + } + + bn = ASCIIToBIGNUM("256"); + if (!bn || !BN_is_word(bn.get(), 256) || BN_is_negative(bn.get())) { + fprintf(stderr, "BN_asc2bn gave a bad result.\n"); + return false; + } + + bn = ASCIIToBIGNUM("-42"); + if (!bn || !BN_abs_is_word(bn.get(), 42) || !BN_is_negative(bn.get())) { + fprintf(stderr, "BN_asc2bn gave a bad result.\n"); + return false; + } + + bn = ASCIIToBIGNUM("0x1234"); + if (!bn || !BN_is_word(bn.get(), 0x1234) || BN_is_negative(bn.get())) { + fprintf(stderr, "BN_asc2bn gave a bad result.\n"); + return false; + } + + bn = ASCIIToBIGNUM("0X1234"); + if (!bn || !BN_is_word(bn.get(), 0x1234) || BN_is_negative(bn.get())) { + fprintf(stderr, "BN_asc2bn gave a bad result.\n"); + return false; + } + + bn = ASCIIToBIGNUM("-0xabcd"); + if (!bn || !BN_abs_is_word(bn.get(), 0xabcd) || !BN_is_negative(bn.get())) { + fprintf(stderr, "BN_asc2bn gave a bad result.\n"); + return false; + } + + bn = ASCIIToBIGNUM("-0"); + if (!bn || !BN_is_zero(bn.get()) || BN_is_negative(bn.get())) { + fprintf(stderr, "BN_asc2bn gave a bad result.\n"); + return false; + } + + bn = ASCIIToBIGNUM("123trailing garbage is ignored"); + if (!bn || !BN_is_word(bn.get(), 123) || BN_is_negative(bn.get())) { + fprintf(stderr, "BN_asc2bn gave a bad result.\n"); + return false; + } + + return true; +} + +struct MPITest { + const char *base10; + const char *mpi; + size_t mpi_len; +}; + +static const MPITest kMPITests[] = { + { "0", "\x00\x00\x00\x00", 4 }, + { "1", "\x00\x00\x00\x01\x01", 5 }, + { "-1", "\x00\x00\x00\x01\x81", 5 }, + { "128", "\x00\x00\x00\x02\x00\x80", 6 }, + { "256", "\x00\x00\x00\x02\x01\x00", 6 }, + { "-256", "\x00\x00\x00\x02\x81\x00", 6 }, +}; + +static bool test_mpi() { + uint8_t scratch[8]; + + for (size_t i = 0; i < sizeof(kMPITests) / sizeof(kMPITests[0]); i++) { + const MPITest &test = kMPITests[i]; + ScopedBIGNUM bn(ASCIIToBIGNUM(test.base10)); + const size_t mpi_len = BN_bn2mpi(bn.get(), NULL); + if (mpi_len > sizeof(scratch)) { + fprintf(stderr, "MPI test #%u: MPI size is too large to test.\n", + (unsigned)i); + return false; + } + + const size_t mpi_len2 = BN_bn2mpi(bn.get(), scratch); + if (mpi_len != mpi_len2) { + fprintf(stderr, "MPI test #%u: length changes.\n", (unsigned)i); + return false; + } + + if (mpi_len != test.mpi_len || + memcmp(test.mpi, scratch, mpi_len) != 0) { + fprintf(stderr, "MPI test #%u failed:\n", (unsigned)i); + hexdump(stderr, "Expected: ", test.mpi, test.mpi_len); + hexdump(stderr, "Got: ", scratch, mpi_len); + return false; + } + + ScopedBIGNUM bn2(BN_mpi2bn(scratch, mpi_len, NULL)); + if (bn2.get() == nullptr) { + fprintf(stderr, "MPI test #%u: failed to parse\n", (unsigned)i); + return false; + } + + if (BN_cmp(bn.get(), bn2.get()) != 0) { + fprintf(stderr, "MPI test #%u: wrong result\n", (unsigned)i); + return false; + } + } + + return true; +} + +static bool test_rand() { + ScopedBIGNUM bn(BN_new()); + if (!bn) { + return false; + } + + // Test BN_rand accounts for degenerate cases with |top| and |bottom| + // parameters. + if (!BN_rand(bn.get(), 0, 0 /* top */, 0 /* bottom */) || + !BN_is_zero(bn.get())) { + fprintf(stderr, "BN_rand gave a bad result.\n"); + return false; + } + if (!BN_rand(bn.get(), 0, 1 /* top */, 1 /* bottom */) || + !BN_is_zero(bn.get())) { + fprintf(stderr, "BN_rand gave a bad result.\n"); + return false; + } + + if (!BN_rand(bn.get(), 1, 0 /* top */, 0 /* bottom */) || + !BN_is_word(bn.get(), 1)) { + fprintf(stderr, "BN_rand gave a bad result.\n"); + return false; + } + if (!BN_rand(bn.get(), 1, 1 /* top */, 0 /* bottom */) || + !BN_is_word(bn.get(), 1)) { + fprintf(stderr, "BN_rand gave a bad result.\n"); + return false; + } + if (!BN_rand(bn.get(), 1, -1 /* top */, 1 /* bottom */) || + !BN_is_word(bn.get(), 1)) { + fprintf(stderr, "BN_rand gave a bad result.\n"); + return false; + } + + if (!BN_rand(bn.get(), 2, 1 /* top */, 0 /* bottom */) || + !BN_is_word(bn.get(), 3)) { + fprintf(stderr, "BN_rand gave a bad result.\n"); + return false; + } + + return true; +} + +struct ASN1Test { + const char *value_ascii; + const char *der; + size_t der_len; +}; + +static const ASN1Test kASN1Tests[] = { + {"0", "\x02\x01\x00", 3}, + {"1", "\x02\x01\x01", 3}, + {"127", "\x02\x01\x7f", 3}, + {"128", "\x02\x02\x00\x80", 4}, + {"0xdeadbeef", "\x02\x05\x00\xde\xad\xbe\xef", 7}, + {"0x0102030405060708", + "\x02\x08\x01\x02\x03\x04\x05\x06\x07\x08", 10}, + {"0xffffffffffffffff", + "\x02\x09\x00\xff\xff\xff\xff\xff\xff\xff\xff", 11}, +}; + +struct ASN1InvalidTest { + const char *der; + size_t der_len; +}; + +static const ASN1InvalidTest kASN1InvalidTests[] = { + // Bad tag. + {"\x03\x01\x00", 3}, + // Empty contents. + {"\x02\x00", 2}, +}; + +// kASN1BuggyTests contains incorrect encodings and the corresponding, expected +// results of |BN_parse_asn1_unsigned_buggy| given that input. +static const ASN1Test kASN1BuggyTests[] = { + // Negative numbers. + {"128", "\x02\x01\x80", 3}, + {"255", "\x02\x01\xff", 3}, + // Unnecessary leading zeros. + {"1", "\x02\x02\x00\x01", 4}, +}; + +static bool test_asn1() { + for (const ASN1Test &test : kASN1Tests) { + ScopedBIGNUM bn = ASCIIToBIGNUM(test.value_ascii); + if (!bn) { + return false; + } + + // Test that the input is correctly parsed. + ScopedBIGNUM bn2(BN_new()); + if (!bn2) { + return false; + } + CBS cbs; + CBS_init(&cbs, reinterpret_cast(test.der), test.der_len); + if (!BN_parse_asn1_unsigned(&cbs, bn2.get()) || CBS_len(&cbs) != 0) { + fprintf(stderr, "Parsing ASN.1 INTEGER failed.\n"); + return false; + } + if (BN_cmp(bn.get(), bn2.get()) != 0) { + fprintf(stderr, "Bad parse.\n"); + return false; + } + + // Test the value serializes correctly. + CBB cbb; + uint8_t *der; + size_t der_len; + CBB_zero(&cbb); + if (!CBB_init(&cbb, 0) || + !BN_marshal_asn1(&cbb, bn.get()) || + !CBB_finish(&cbb, &der, &der_len)) { + CBB_cleanup(&cbb); + return false; + } + ScopedOpenSSLBytes delete_der(der); + if (der_len != test.der_len || + memcmp(der, reinterpret_cast(test.der), der_len) != 0) { + fprintf(stderr, "Bad serialization.\n"); + return false; + } + + // |BN_parse_asn1_unsigned_buggy| parses all valid input. + CBS_init(&cbs, reinterpret_cast(test.der), test.der_len); + if (!BN_parse_asn1_unsigned_buggy(&cbs, bn2.get()) || CBS_len(&cbs) != 0) { + fprintf(stderr, "Parsing ASN.1 INTEGER failed.\n"); + return false; + } + if (BN_cmp(bn.get(), bn2.get()) != 0) { + fprintf(stderr, "Bad parse.\n"); + return false; + } + } + + for (const ASN1InvalidTest &test : kASN1InvalidTests) { + ScopedBIGNUM bn(BN_new()); + if (!bn) { + return false; + } + CBS cbs; + CBS_init(&cbs, reinterpret_cast(test.der), test.der_len); + if (BN_parse_asn1_unsigned(&cbs, bn.get())) { + fprintf(stderr, "Parsed invalid input.\n"); + return false; + } + ERR_clear_error(); + + // All tests in kASN1InvalidTests are also rejected by + // |BN_parse_asn1_unsigned_buggy|. + CBS_init(&cbs, reinterpret_cast(test.der), test.der_len); + if (BN_parse_asn1_unsigned_buggy(&cbs, bn.get())) { + fprintf(stderr, "Parsed invalid input.\n"); + return false; + } + ERR_clear_error(); + } + + for (const ASN1Test &test : kASN1BuggyTests) { + // These broken encodings are rejected by |BN_parse_asn1_unsigned|. + ScopedBIGNUM bn(BN_new()); + if (!bn) { + return false; + } + + CBS cbs; + CBS_init(&cbs, reinterpret_cast(test.der), test.der_len); + if (BN_parse_asn1_unsigned(&cbs, bn.get())) { + fprintf(stderr, "Parsed invalid input.\n"); + return false; + } + ERR_clear_error(); + + // However |BN_parse_asn1_unsigned_buggy| accepts them. + ScopedBIGNUM bn2 = ASCIIToBIGNUM(test.value_ascii); + if (!bn2) { + return false; + } + + CBS_init(&cbs, reinterpret_cast(test.der), test.der_len); + if (!BN_parse_asn1_unsigned_buggy(&cbs, bn.get()) || CBS_len(&cbs) != 0) { + fprintf(stderr, "Parsing (invalid) ASN.1 INTEGER failed.\n"); + return false; + } + + if (BN_cmp(bn.get(), bn2.get()) != 0) { + fprintf(stderr, "\"Bad\" parse.\n"); + return false; + } + } + + // Serializing negative numbers is not supported. + ScopedBIGNUM bn = ASCIIToBIGNUM("-1"); + if (!bn) { + return false; + } + CBB cbb; + CBB_zero(&cbb); + if (!CBB_init(&cbb, 0) || + BN_marshal_asn1(&cbb, bn.get())) { + fprintf(stderr, "Serialized negative number.\n"); + CBB_cleanup(&cbb); + return false; + } + CBB_cleanup(&cbb); + + return true; +} diff --git a/external/boringssl/crypto/bn/cmp.c b/external/boringssl/crypto/bn/cmp.c new file mode 100644 index 0000000000..121c894cdd --- /dev/null +++ b/external/boringssl/crypto/bn/cmp.c @@ -0,0 +1,214 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include "internal.h" + + +int BN_ucmp(const BIGNUM *a, const BIGNUM *b) { + int i; + BN_ULONG t1, t2, *ap, *bp; + + i = a->top - b->top; + if (i != 0) { + return i; + } + + ap = a->d; + bp = b->d; + for (i = a->top - 1; i >= 0; i--) { + t1 = ap[i]; + t2 = bp[i]; + if (t1 != t2) { + return (t1 > t2) ? 1 : -1; + } + } + + return 0; +} + +int BN_cmp(const BIGNUM *a, const BIGNUM *b) { + int i; + int gt, lt; + BN_ULONG t1, t2; + + if ((a == NULL) || (b == NULL)) { + if (a != NULL) { + return -1; + } else if (b != NULL) { + return 1; + } else { + return 0; + } + } + + if (a->neg != b->neg) { + if (a->neg) { + return -1; + } + return 1; + } + if (a->neg == 0) { + gt = 1; + lt = -1; + } else { + gt = -1; + lt = 1; + } + + if (a->top > b->top) { + return gt; + } + if (a->top < b->top) { + return lt; + } + + for (i = a->top - 1; i >= 0; i--) { + t1 = a->d[i]; + t2 = b->d[i]; + if (t1 > t2) { + return gt; + } if (t1 < t2) { + return lt; + } + } + + return 0; +} + +int bn_cmp_words(const BN_ULONG *a, const BN_ULONG *b, int n) { + int i; + BN_ULONG aa, bb; + + aa = a[n - 1]; + bb = b[n - 1]; + if (aa != bb) { + return (aa > bb) ? 1 : -1; + } + + for (i = n - 2; i >= 0; i--) { + aa = a[i]; + bb = b[i]; + if (aa != bb) { + return (aa > bb) ? 1 : -1; + } + } + return 0; +} + +int bn_cmp_part_words(const BN_ULONG *a, const BN_ULONG *b, int cl, int dl) { + int n, i; + n = cl - 1; + + if (dl < 0) { + for (i = dl; i < 0; i++) { + if (b[n - i] != 0) { + return -1; /* a < b */ + } + } + } + if (dl > 0) { + for (i = dl; i > 0; i--) { + if (a[n + i] != 0) { + return 1; /* a > b */ + } + } + } + + return bn_cmp_words(a, b, cl); +} + +int BN_abs_is_word(const BIGNUM *bn, BN_ULONG w) { + switch (bn->top) { + case 1: + return bn->d[0] == w; + case 0: + return w == 0; + default: + return 0; + } +} + +int BN_is_zero(const BIGNUM *bn) { + return bn->top == 0; +} + +int BN_is_one(const BIGNUM *bn) { + return bn->neg == 0 && BN_abs_is_word(bn, 1); +} + +int BN_is_word(const BIGNUM *bn, BN_ULONG w) { + return BN_abs_is_word(bn, w) && (w == 0 || bn->neg == 0); +} + +int BN_is_odd(const BIGNUM *bn) { + return bn->top > 0 && (bn->d[0] & 1) == 1; +} + +int BN_equal_consttime(const BIGNUM *a, const BIGNUM *b) { + if (a->top != b->top) { + return 0; + } + + int limbs_are_equal = + CRYPTO_memcmp(a->d, b->d, (size_t)a->top * sizeof(a->d[0])) == 0; + + return constant_time_select_int(constant_time_eq_int(a->neg, b->neg), + limbs_are_equal, 0); +} diff --git a/external/boringssl/crypto/bn/convert.c b/external/boringssl/crypto/bn/convert.c new file mode 100644 index 0000000000..9125bf84be --- /dev/null +++ b/external/boringssl/crypto/bn/convert.c @@ -0,0 +1,607 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "internal.h" + +BIGNUM *BN_bin2bn(const uint8_t *in, size_t len, BIGNUM *ret) { + size_t num_words; + unsigned m; + BN_ULONG word = 0; + BIGNUM *bn = NULL; + + if (ret == NULL) { + ret = bn = BN_new(); + } + + if (ret == NULL) { + return NULL; + } + + if (len == 0) { + ret->top = 0; + return ret; + } + + num_words = ((len - 1) / BN_BYTES) + 1; + m = (len - 1) % BN_BYTES; + if (bn_wexpand(ret, num_words) == NULL) { + if (bn) { + BN_free(bn); + } + return NULL; + } + + /* |bn_wexpand| must check bounds on |num_words| to write it into + * |ret->dmax|. */ + assert(num_words <= INT_MAX); + ret->top = (int)num_words; + ret->neg = 0; + + while (len--) { + word = (word << 8) | *(in++); + if (m-- == 0) { + ret->d[--num_words] = word; + word = 0; + m = BN_BYTES - 1; + } + } + + /* need to call this due to clear byte at top if avoiding having the top bit + * set (-ve number) */ + bn_correct_top(ret); + return ret; +} + +size_t BN_bn2bin(const BIGNUM *in, uint8_t *out) { + size_t n, i; + BN_ULONG l; + + n = i = BN_num_bytes(in); + while (i--) { + l = in->d[i / BN_BYTES]; + *(out++) = (unsigned char)(l >> (8 * (i % BN_BYTES))) & 0xff; + } + return n; +} + +/* constant_time_select_ulong returns |x| if |v| is 1 and |y| if |v| is 0. Its + * behavior is undefined if |v| takes any other value. */ +static BN_ULONG constant_time_select_ulong(int v, BN_ULONG x, BN_ULONG y) { + BN_ULONG mask = v; + mask--; + + return (~mask & x) | (mask & y); +} + +/* constant_time_le_size_t returns 1 if |x| <= |y| and 0 otherwise. |x| and |y| + * must not have their MSBs set. */ +static int constant_time_le_size_t(size_t x, size_t y) { + return ((x - y - 1) >> (sizeof(size_t) * 8 - 1)) & 1; +} + +/* read_word_padded returns the |i|'th word of |in|, if it is not out of + * bounds. Otherwise, it returns 0. It does so without branches on the size of + * |in|, however it necessarily does not have the same memory access pattern. If + * the access would be out of bounds, it reads the last word of |in|. |in| must + * not be zero. */ +static BN_ULONG read_word_padded(const BIGNUM *in, size_t i) { + /* Read |in->d[i]| if valid. Otherwise, read the last word. */ + BN_ULONG l = in->d[constant_time_select_ulong( + constant_time_le_size_t(in->dmax, i), in->dmax - 1, i)]; + + /* Clamp to zero if above |d->top|. */ + return constant_time_select_ulong(constant_time_le_size_t(in->top, i), 0, l); +} + +int BN_bn2bin_padded(uint8_t *out, size_t len, const BIGNUM *in) { + size_t i; + BN_ULONG l; + + /* Special case for |in| = 0. Just branch as the probability is negligible. */ + if (BN_is_zero(in)) { + memset(out, 0, len); + return 1; + } + + /* Check if the integer is too big. This case can exit early in non-constant + * time. */ + if ((size_t)in->top > (len + (BN_BYTES - 1)) / BN_BYTES) { + return 0; + } + if ((len % BN_BYTES) != 0) { + l = read_word_padded(in, len / BN_BYTES); + if (l >> (8 * (len % BN_BYTES)) != 0) { + return 0; + } + } + + /* Write the bytes out one by one. Serialization is done without branching on + * the bits of |in| or on |in->top|, but if the routine would otherwise read + * out of bounds, the memory access pattern can't be fixed. However, for an + * RSA key of size a multiple of the word size, the probability of BN_BYTES + * leading zero octets is low. + * + * See Falko Stenzke, "Manger's Attack revisited", ICICS 2010. */ + i = len; + while (i--) { + l = read_word_padded(in, i / BN_BYTES); + *(out++) = (uint8_t)(l >> (8 * (i % BN_BYTES))) & 0xff; + } + return 1; +} + +int BN_bn2cbb_padded(CBB *out, size_t len, const BIGNUM *in) { + uint8_t *ptr; + return CBB_add_space(out, &ptr, len) && BN_bn2bin_padded(ptr, len, in); +} + +static const char hextable[] = "0123456789abcdef"; + +char *BN_bn2hex(const BIGNUM *bn) { + int i, j, v, z = 0; + char *buf; + char *p; + + buf = OPENSSL_malloc(bn->top * BN_BYTES * 2 + 2); + if (buf == NULL) { + OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE); + return NULL; + } + + p = buf; + if (bn->neg) { + *(p++) = '-'; + } + + if (BN_is_zero(bn)) { + *(p++) = '0'; + } + + for (i = bn->top - 1; i >= 0; i--) { + for (j = BN_BITS2 - 8; j >= 0; j -= 8) { + /* strip leading zeros */ + v = ((int)(bn->d[i] >> (long)j)) & 0xff; + if (z || v != 0) { + *(p++) = hextable[v >> 4]; + *(p++) = hextable[v & 0x0f]; + z = 1; + } + } + } + *p = '\0'; + + return buf; +} + +/* decode_hex decodes |in_len| bytes of hex data from |in| and updates |bn|. */ +static int decode_hex(BIGNUM *bn, const char *in, int in_len) { + if (in_len > INT_MAX/4) { + OPENSSL_PUT_ERROR(BN, BN_R_BIGNUM_TOO_LONG); + return 0; + } + /* |in_len| is the number of hex digits. */ + if (bn_expand(bn, in_len * 4) == NULL) { + return 0; + } + + int i = 0; + while (in_len > 0) { + /* Decode one |BN_ULONG| at a time. */ + int todo = BN_BYTES * 2; + if (todo > in_len) { + todo = in_len; + } + + BN_ULONG word = 0; + int j; + for (j = todo; j > 0; j--) { + char c = in[in_len - j]; + + BN_ULONG hex; + if (c >= '0' && c <= '9') { + hex = c - '0'; + } else if (c >= 'a' && c <= 'f') { + hex = c - 'a' + 10; + } else if (c >= 'A' && c <= 'F') { + hex = c - 'A' + 10; + } else { + hex = 0; + /* This shouldn't happen. The caller checks |isxdigit|. */ + assert(0); + } + word = (word << 4) | hex; + } + + bn->d[i++] = word; + in_len -= todo; + } + assert(i <= bn->dmax); + bn->top = i; + return 1; +} + +/* decode_dec decodes |in_len| bytes of decimal data from |in| and updates |bn|. */ +static int decode_dec(BIGNUM *bn, const char *in, int in_len) { + int i, j; + BN_ULONG l = 0; + + /* Decode |BN_DEC_NUM| digits at a time. */ + j = BN_DEC_NUM - (in_len % BN_DEC_NUM); + if (j == BN_DEC_NUM) { + j = 0; + } + l = 0; + for (i = 0; i < in_len; i++) { + l *= 10; + l += in[i] - '0'; + if (++j == BN_DEC_NUM) { + if (!BN_mul_word(bn, BN_DEC_CONV) || + !BN_add_word(bn, l)) { + return 0; + } + l = 0; + j = 0; + } + } + return 1; +} + +typedef int (*decode_func) (BIGNUM *bn, const char *in, int in_len); +typedef int (*char_test_func) (int c); + +static int bn_x2bn(BIGNUM **outp, const char *in, decode_func decode, char_test_func want_char) { + BIGNUM *ret = NULL; + int neg = 0, i; + int num; + + if (in == NULL || *in == 0) { + return 0; + } + + if (*in == '-') { + neg = 1; + in++; + } + + for (i = 0; want_char((unsigned char)in[i]) && i + neg < INT_MAX; i++) {} + + num = i + neg; + if (outp == NULL) { + return num; + } + + /* in is the start of the hex digits, and it is 'i' long */ + if (*outp == NULL) { + ret = BN_new(); + if (ret == NULL) { + return 0; + } + } else { + ret = *outp; + BN_zero(ret); + } + + if (!decode(ret, in, i)) { + goto err; + } + + bn_correct_top(ret); + if (!BN_is_zero(ret)) { + ret->neg = neg; + } + + *outp = ret; + return num; + +err: + if (*outp == NULL) { + BN_free(ret); + } + + return 0; +} + +int BN_hex2bn(BIGNUM **outp, const char *in) { + return bn_x2bn(outp, in, decode_hex, isxdigit); +} + +char *BN_bn2dec(const BIGNUM *a) { + int i = 0, num, ok = 0; + char *buf = NULL; + char *p; + BIGNUM *t = NULL; + BN_ULONG *bn_data = NULL, *lp; + + /* get an upper bound for the length of the decimal integer + * num <= (BN_num_bits(a) + 1) * log(2) + * <= 3 * BN_num_bits(a) * 0.1001 + log(2) + 1 (rounding error) + * <= BN_num_bits(a)/10 + BN_num_bits/1000 + 1 + 1 + */ + i = BN_num_bits(a) * 3; + num = i / 10 + i / 1000 + 1 + 1; + bn_data = OPENSSL_malloc((num / BN_DEC_NUM + 1) * sizeof(BN_ULONG)); + buf = OPENSSL_malloc(num + 3); + if ((buf == NULL) || (bn_data == NULL)) { + OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE); + goto err; + } + t = BN_dup(a); + if (t == NULL) { + goto err; + } + +#define BUF_REMAIN (num + 3 - (size_t)(p - buf)) + p = buf; + lp = bn_data; + if (BN_is_zero(t)) { + *(p++) = '0'; + *(p++) = '\0'; + } else { + if (BN_is_negative(t)) { + *p++ = '-'; + } + + while (!BN_is_zero(t)) { + *lp = BN_div_word(t, BN_DEC_CONV); + lp++; + } + lp--; + /* We now have a series of blocks, BN_DEC_NUM chars + * in length, where the last one needs truncation. + * The blocks need to be reversed in order. */ + BIO_snprintf(p, BUF_REMAIN, BN_DEC_FMT1, *lp); + while (*p) { + p++; + } + while (lp != bn_data) { + lp--; + BIO_snprintf(p, BUF_REMAIN, BN_DEC_FMT2, *lp); + while (*p) { + p++; + } + } + } + ok = 1; + +err: + OPENSSL_free(bn_data); + BN_free(t); + if (!ok) { + OPENSSL_free(buf); + buf = NULL; + } + + return buf; +} + +int BN_dec2bn(BIGNUM **outp, const char *in) { + return bn_x2bn(outp, in, decode_dec, isdigit); +} + +int BN_asc2bn(BIGNUM **outp, const char *in) { + const char *const orig_in = in; + if (*in == '-') { + in++; + } + + if (in[0] == '0' && (in[1] == 'X' || in[1] == 'x')) { + if (!BN_hex2bn(outp, in+2)) { + return 0; + } + } else { + if (!BN_dec2bn(outp, in)) { + return 0; + } + } + + if (*orig_in == '-' && !BN_is_zero(*outp)) { + (*outp)->neg = 1; + } + + return 1; +} + +int BN_print(BIO *bp, const BIGNUM *a) { + int i, j, v, z = 0; + int ret = 0; + + if (a->neg && BIO_write(bp, "-", 1) != 1) { + goto end; + } + + if (BN_is_zero(a) && BIO_write(bp, "0", 1) != 1) { + goto end; + } + + for (i = a->top - 1; i >= 0; i--) { + for (j = BN_BITS2 - 4; j >= 0; j -= 4) { + /* strip leading zeros */ + v = ((int)(a->d[i] >> (long)j)) & 0x0f; + if (z || v != 0) { + if (BIO_write(bp, &hextable[v], 1) != 1) { + goto end; + } + z = 1; + } + } + } + ret = 1; + +end: + return ret; +} + +int BN_print_fp(FILE *fp, const BIGNUM *a) { + BIO *b; + int ret; + + b = BIO_new(BIO_s_file()); + if (b == NULL) { + return 0; + } + BIO_set_fp(b, fp, BIO_NOCLOSE); + ret = BN_print(b, a); + BIO_free(b); + + return ret; +} + +BN_ULONG BN_get_word(const BIGNUM *bn) { + switch (bn->top) { + case 0: + return 0; + case 1: + return bn->d[0]; + default: + return BN_MASK2; + } +} + +size_t BN_bn2mpi(const BIGNUM *in, uint8_t *out) { + const size_t bits = BN_num_bits(in); + const size_t bytes = (bits + 7) / 8; + /* If the number of bits is a multiple of 8, i.e. if the MSB is set, + * prefix with a zero byte. */ + int extend = 0; + if (bytes != 0 && (bits & 0x07) == 0) { + extend = 1; + } + + const size_t len = bytes + extend; + if (len < bytes || + 4 + len < len || + (len & 0xffffffff) != len) { + /* If we cannot represent the number then we emit zero as the interface + * doesn't allow an error to be signalled. */ + if (out) { + memset(out, 0, 4); + } + return 4; + } + + if (out == NULL) { + return 4 + len; + } + + out[0] = len >> 24; + out[1] = len >> 16; + out[2] = len >> 8; + out[3] = len; + if (extend) { + out[4] = 0; + } + BN_bn2bin(in, out + 4 + extend); + if (in->neg && len > 0) { + out[4] |= 0x80; + } + return len + 4; +} + +BIGNUM *BN_mpi2bn(const uint8_t *in, size_t len, BIGNUM *out) { + if (len < 4) { + OPENSSL_PUT_ERROR(BN, BN_R_BAD_ENCODING); + return NULL; + } + const size_t in_len = ((size_t)in[0] << 24) | + ((size_t)in[1] << 16) | + ((size_t)in[2] << 8) | + ((size_t)in[3]); + if (in_len != len - 4) { + OPENSSL_PUT_ERROR(BN, BN_R_BAD_ENCODING); + return NULL; + } + + int out_is_alloced = 0; + if (out == NULL) { + out = BN_new(); + if (out == NULL) { + OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE); + return NULL; + } + out_is_alloced = 1; + } + + if (in_len == 0) { + BN_zero(out); + return out; + } + + in += 4; + if (BN_bin2bn(in, in_len, out) == NULL) { + if (out_is_alloced) { + BN_free(out); + } + return NULL; + } + out->neg = ((*in) & 0x80) != 0; + if (out->neg) { + BN_clear_bit(out, BN_num_bits(out) - 1); + } + return out; +} diff --git a/external/boringssl/crypto/bn/ctx.c b/external/boringssl/crypto/bn/ctx.c new file mode 100644 index 0000000000..48d9adf651 --- /dev/null +++ b/external/boringssl/crypto/bn/ctx.c @@ -0,0 +1,311 @@ +/* Written by Ulf Moeller for the OpenSSL project. */ +/* ==================================================================== + * Copyright (c) 1998-2004 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + + +#include + +#include + +#include +#include + + +/* How many bignums are in each "pool item"; */ +#define BN_CTX_POOL_SIZE 16 +/* The stack frame info is resizing, set a first-time expansion size; */ +#define BN_CTX_START_FRAMES 32 + +/* A bundle of bignums that can be linked with other bundles */ +typedef struct bignum_pool_item { + /* The bignum values */ + BIGNUM vals[BN_CTX_POOL_SIZE]; + /* Linked-list admin */ + struct bignum_pool_item *prev, *next; +} BN_POOL_ITEM; + + +typedef struct bignum_pool { + /* Linked-list admin */ + BN_POOL_ITEM *head, *current, *tail; + /* Stack depth and allocation size */ + unsigned used, size; +} BN_POOL; + +static void BN_POOL_init(BN_POOL *); +static void BN_POOL_finish(BN_POOL *); +static BIGNUM *BN_POOL_get(BN_POOL *); +static void BN_POOL_release(BN_POOL *, unsigned int); + +/************/ +/* BN_STACK */ +/************/ + +/* A wrapper to manage the "stack frames" */ +typedef struct bignum_ctx_stack { + /* Array of indexes into the bignum stack */ + unsigned int *indexes; + /* Number of stack frames, and the size of the allocated array */ + unsigned int depth, size; +} BN_STACK; + +static void BN_STACK_init(BN_STACK *); +static void BN_STACK_finish(BN_STACK *); +static int BN_STACK_push(BN_STACK *, unsigned int); +static unsigned int BN_STACK_pop(BN_STACK *); + +/**********/ +/* BN_CTX */ +/**********/ + +/* The opaque BN_CTX type */ +struct bignum_ctx { + /* The bignum bundles */ + BN_POOL pool; + /* The "stack frames", if you will */ + BN_STACK stack; + /* The number of bignums currently assigned */ + unsigned int used; + /* Depth of stack overflow */ + int err_stack; + /* Block "gets" until an "end" (compatibility behaviour) */ + int too_many; +}; + +BN_CTX *BN_CTX_new(void) { + BN_CTX *ret = OPENSSL_malloc(sizeof(BN_CTX)); + if (!ret) { + OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE); + return NULL; + } + + /* Initialise the structure */ + BN_POOL_init(&ret->pool); + BN_STACK_init(&ret->stack); + ret->used = 0; + ret->err_stack = 0; + ret->too_many = 0; + return ret; +} + +void BN_CTX_free(BN_CTX *ctx) { + if (ctx == NULL) { + return; + } + + BN_STACK_finish(&ctx->stack); + BN_POOL_finish(&ctx->pool); + OPENSSL_free(ctx); +} + +void BN_CTX_start(BN_CTX *ctx) { + /* If we're already overflowing ... */ + if (ctx->err_stack || ctx->too_many) { + ctx->err_stack++; + } else if (!BN_STACK_push(&ctx->stack, ctx->used)) { + /* (Try to) get a new frame pointer */ + OPENSSL_PUT_ERROR(BN, BN_R_TOO_MANY_TEMPORARY_VARIABLES); + ctx->err_stack++; + } +} + +BIGNUM *BN_CTX_get(BN_CTX *ctx) { + BIGNUM *ret; + if (ctx->err_stack || ctx->too_many) { + return NULL; + } + + ret = BN_POOL_get(&ctx->pool); + if (ret == NULL) { + /* Setting too_many prevents repeated "get" attempts from + * cluttering the error stack. */ + ctx->too_many = 1; + OPENSSL_PUT_ERROR(BN, BN_R_TOO_MANY_TEMPORARY_VARIABLES); + return NULL; + } + + /* OK, make sure the returned bignum is "zero" */ + BN_zero(ret); + ctx->used++; + return ret; +} + +void BN_CTX_end(BN_CTX *ctx) { + if (ctx->err_stack) { + ctx->err_stack--; + } else { + unsigned int fp = BN_STACK_pop(&ctx->stack); + /* Does this stack frame have anything to release? */ + if (fp < ctx->used) { + BN_POOL_release(&ctx->pool, ctx->used - fp); + } + + ctx->used = fp; + /* Unjam "too_many" in case "get" had failed */ + ctx->too_many = 0; + } +} + +/************/ +/* BN_STACK */ +/************/ + +static void BN_STACK_init(BN_STACK *st) { + st->indexes = NULL; + st->depth = st->size = 0; +} + +static void BN_STACK_finish(BN_STACK *st) { + OPENSSL_free(st->indexes); +} + +static int BN_STACK_push(BN_STACK *st, unsigned int idx) { + if (st->depth == st->size) { + /* Need to expand */ + unsigned int newsize = + (st->size ? (st->size * 3 / 2) : BN_CTX_START_FRAMES); + unsigned int *newitems = OPENSSL_malloc(newsize * sizeof(unsigned int)); + if (!newitems) { + return 0; + } + if (st->depth) { + memcpy(newitems, st->indexes, st->depth * sizeof(unsigned int)); + } + OPENSSL_free(st->indexes); + st->indexes = newitems; + st->size = newsize; + } + + st->indexes[(st->depth)++] = idx; + return 1; +} + +static unsigned int BN_STACK_pop(BN_STACK *st) { + return st->indexes[--(st->depth)]; +} + +static void BN_POOL_init(BN_POOL *p) { + p->head = p->current = p->tail = NULL; + p->used = p->size = 0; +} + +static void BN_POOL_finish(BN_POOL *p) { + while (p->head) { + unsigned int loop = 0; + BIGNUM *bn = p->head->vals; + while (loop++ < BN_CTX_POOL_SIZE) { + if (bn->d) { + BN_clear_free(bn); + } + bn++; + } + + p->current = p->head->next; + OPENSSL_free(p->head); + p->head = p->current; + } +} + +static BIGNUM *BN_POOL_get(BN_POOL *p) { + if (p->used == p->size) { + BIGNUM *bn; + unsigned int loop = 0; + BN_POOL_ITEM *item = OPENSSL_malloc(sizeof(BN_POOL_ITEM)); + if (!item) { + return NULL; + } + + /* Initialise the structure */ + bn = item->vals; + while (loop++ < BN_CTX_POOL_SIZE) { + BN_init(bn++); + } + + item->prev = p->tail; + item->next = NULL; + /* Link it in */ + if (!p->head) { + p->head = p->current = p->tail = item; + } else { + p->tail->next = item; + p->tail = item; + p->current = item; + } + + p->size += BN_CTX_POOL_SIZE; + p->used++; + /* Return the first bignum from the new pool */ + return item->vals; + } + + if (!p->used) { + p->current = p->head; + } else if ((p->used % BN_CTX_POOL_SIZE) == 0) { + p->current = p->current->next; + } + + return p->current->vals + ((p->used++) % BN_CTX_POOL_SIZE); +} + +static void BN_POOL_release(BN_POOL *p, unsigned int num) { + unsigned int offset = (p->used - 1) % BN_CTX_POOL_SIZE; + p->used -= num; + + while (num--) { + if (!offset) { + offset = BN_CTX_POOL_SIZE - 1; + p->current = p->current->prev; + } else { + offset--; + } + } +} diff --git a/external/boringssl/crypto/bn/div.c b/external/boringssl/crypto/bn/div.c new file mode 100644 index 0000000000..e824458baf --- /dev/null +++ b/external/boringssl/crypto/bn/div.c @@ -0,0 +1,671 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include +#include + +#include "internal.h" + + +#if !defined(BN_ULLONG) +/* bn_div_words divides a double-width |h|,|l| by |d| and returns the result, + * which must fit in a |BN_ULONG|. */ +static BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d) { + BN_ULONG dh, dl, q, ret = 0, th, tl, t; + int i, count = 2; + + if (d == 0) { + return BN_MASK2; + } + + i = BN_num_bits_word(d); + assert((i == BN_BITS2) || (h <= (BN_ULONG)1 << i)); + + i = BN_BITS2 - i; + if (h >= d) { + h -= d; + } + + if (i) { + d <<= i; + h = (h << i) | (l >> (BN_BITS2 - i)); + l <<= i; + } + dh = (d & BN_MASK2h) >> BN_BITS4; + dl = (d & BN_MASK2l); + for (;;) { + if ((h >> BN_BITS4) == dh) { + q = BN_MASK2l; + } else { + q = h / dh; + } + + th = q * dh; + tl = dl * q; + for (;;) { + t = h - th; + if ((t & BN_MASK2h) || + ((tl) <= ((t << BN_BITS4) | ((l & BN_MASK2h) >> BN_BITS4)))) { + break; + } + q--; + th -= dh; + tl -= dl; + } + t = (tl >> BN_BITS4); + tl = (tl << BN_BITS4) & BN_MASK2h; + th += t; + + if (l < tl) { + th++; + } + l -= tl; + if (h < th) { + h += d; + q--; + } + h -= th; + + if (--count == 0) { + break; + } + + ret = q << BN_BITS4; + h = ((h << BN_BITS4) | (l >> BN_BITS4)) & BN_MASK2; + l = (l & BN_MASK2l) << BN_BITS4; + } + + ret |= q; + return ret; +} +#endif /* !defined(BN_ULLONG) */ + +static inline void bn_div_rem_words(BN_ULONG *quotient_out, BN_ULONG *rem_out, + BN_ULONG n0, BN_ULONG n1, BN_ULONG d0) { + /* GCC and Clang generate function calls to |__udivdi3| and |__umoddi3| when + * the |BN_ULLONG|-based C code is used. + * + * GCC bugs: + * * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=14224 + * * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=43721 + * * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54183 + * * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58897 + * * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65668 + * + * Clang bugs: + * * https://llvm.org/bugs/show_bug.cgi?id=6397 + * * https://llvm.org/bugs/show_bug.cgi?id=12418 + * + * These issues aren't specific to x86 and x86_64, so it might be worthwhile + * to add more assembly language implementations. */ +#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86) && defined(__GNUC__) + __asm__ volatile ( + "divl %4" + : "=a"(*quotient_out), "=d"(*rem_out) + : "a"(n1), "d"(n0), "g"(d0) + : "cc" ); +#elif !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && defined(__GNUC__) + __asm__ volatile ( + "divq %4" + : "=a"(*quotient_out), "=d"(*rem_out) + : "a"(n1), "d"(n0), "g"(d0) + : "cc" ); +#else +#if defined(BN_ULLONG) + BN_ULLONG n = (((BN_ULLONG)n0) << BN_BITS2) | n1; + *quotient_out = (BN_ULONG)(n / d0); +#else + *quotient_out = bn_div_words(n0, n1, d0); +#endif + *rem_out = n1 - (*quotient_out * d0); +#endif +} + +/* BN_div computes dv := num / divisor, rounding towards + * zero, and sets up rm such that dv*divisor + rm = num holds. + * Thus: + * dv->neg == num->neg ^ divisor->neg (unless the result is zero) + * rm->neg == num->neg (unless the remainder is zero) + * If 'dv' or 'rm' is NULL, the respective value is not returned. */ +int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor, + BN_CTX *ctx) { + int norm_shift, i, loop; + BIGNUM *tmp, wnum, *snum, *sdiv, *res; + BN_ULONG *resp, *wnump; + BN_ULONG d0, d1; + int num_n, div_n; + int no_branch = 0; + + /* Invalid zero-padding would have particularly bad consequences + * so don't just rely on bn_check_top() here */ + if ((num->top > 0 && num->d[num->top - 1] == 0) || + (divisor->top > 0 && divisor->d[divisor->top - 1] == 0)) { + OPENSSL_PUT_ERROR(BN, BN_R_NOT_INITIALIZED); + return 0; + } + + if ((num->flags & BN_FLG_CONSTTIME) != 0 || + (divisor->flags & BN_FLG_CONSTTIME) != 0) { + no_branch = 1; + } + + if (BN_is_zero(divisor)) { + OPENSSL_PUT_ERROR(BN, BN_R_DIV_BY_ZERO); + return 0; + } + + if (!no_branch && BN_ucmp(num, divisor) < 0) { + if (rm != NULL) { + if (BN_copy(rm, num) == NULL) { + return 0; + } + } + if (dv != NULL) { + BN_zero(dv); + } + return 1; + } + + BN_CTX_start(ctx); + tmp = BN_CTX_get(ctx); + snum = BN_CTX_get(ctx); + sdiv = BN_CTX_get(ctx); + if (dv == NULL) { + res = BN_CTX_get(ctx); + } else { + res = dv; + } + if (sdiv == NULL || res == NULL || tmp == NULL || snum == NULL) { + goto err; + } + + /* First we normalise the numbers */ + norm_shift = BN_BITS2 - ((BN_num_bits(divisor)) % BN_BITS2); + if (!(BN_lshift(sdiv, divisor, norm_shift))) { + goto err; + } + sdiv->neg = 0; + norm_shift += BN_BITS2; + if (!(BN_lshift(snum, num, norm_shift))) { + goto err; + } + snum->neg = 0; + + if (no_branch) { + /* Since we don't know whether snum is larger than sdiv, + * we pad snum with enough zeroes without changing its + * value. + */ + if (snum->top <= sdiv->top + 1) { + if (bn_wexpand(snum, sdiv->top + 2) == NULL) { + goto err; + } + for (i = snum->top; i < sdiv->top + 2; i++) { + snum->d[i] = 0; + } + snum->top = sdiv->top + 2; + } else { + if (bn_wexpand(snum, snum->top + 1) == NULL) { + goto err; + } + snum->d[snum->top] = 0; + snum->top++; + } + } + + div_n = sdiv->top; + num_n = snum->top; + loop = num_n - div_n; + /* Lets setup a 'window' into snum + * This is the part that corresponds to the current + * 'area' being divided */ + wnum.neg = 0; + wnum.d = &(snum->d[loop]); + wnum.top = div_n; + /* only needed when BN_ucmp messes up the values between top and max */ + wnum.dmax = snum->dmax - loop; /* so we don't step out of bounds */ + + /* Get the top 2 words of sdiv */ + /* div_n=sdiv->top; */ + d0 = sdiv->d[div_n - 1]; + d1 = (div_n == 1) ? 0 : sdiv->d[div_n - 2]; + + /* pointer to the 'top' of snum */ + wnump = &(snum->d[num_n - 1]); + + /* Setup to 'res' */ + res->neg = (num->neg ^ divisor->neg); + if (!bn_wexpand(res, (loop + 1))) { + goto err; + } + res->top = loop - no_branch; + resp = &(res->d[loop - 1]); + + /* space for temp */ + if (!bn_wexpand(tmp, (div_n + 1))) { + goto err; + } + + if (!no_branch) { + if (BN_ucmp(&wnum, sdiv) >= 0) { + bn_sub_words(wnum.d, wnum.d, sdiv->d, div_n); + *resp = 1; + } else { + res->top--; + } + } + + /* if res->top == 0 then clear the neg value otherwise decrease + * the resp pointer */ + if (res->top == 0) { + res->neg = 0; + } else { + resp--; + } + + for (i = 0; i < loop - 1; i++, wnump--, resp--) { + BN_ULONG q, l0; + /* the first part of the loop uses the top two words of snum and sdiv to + * calculate a BN_ULONG q such that | wnum - sdiv * q | < sdiv */ + BN_ULONG n0, n1, rem = 0; + + n0 = wnump[0]; + n1 = wnump[-1]; + if (n0 == d0) { + q = BN_MASK2; + } else { + /* n0 < d0 */ + bn_div_rem_words(&q, &rem, n0, n1, d0); + +#ifdef BN_ULLONG + BN_ULLONG t2 = (BN_ULLONG)d1 * q; + for (;;) { + if (t2 <= ((((BN_ULLONG)rem) << BN_BITS2) | wnump[-2])) { + break; + } + q--; + rem += d0; + if (rem < d0) { + break; /* don't let rem overflow */ + } + t2 -= d1; + } +#else /* !BN_ULLONG */ + BN_ULONG t2l, t2h; + BN_UMULT_LOHI(t2l, t2h, d1, q); + for (;;) { + if ((t2h < rem) || ((t2h == rem) && (t2l <= wnump[-2]))) { + break; + } + q--; + rem += d0; + if (rem < d0) { + break; /* don't let rem overflow */ + } + if (t2l < d1) { + t2h--; + } + t2l -= d1; + } +#endif /* !BN_ULLONG */ + } + + l0 = bn_mul_words(tmp->d, sdiv->d, div_n, q); + tmp->d[div_n] = l0; + wnum.d--; + /* ingore top values of the bignums just sub the two + * BN_ULONG arrays with bn_sub_words */ + if (bn_sub_words(wnum.d, wnum.d, tmp->d, div_n + 1)) { + /* Note: As we have considered only the leading + * two BN_ULONGs in the calculation of q, sdiv * q + * might be greater than wnum (but then (q-1) * sdiv + * is less or equal than wnum) + */ + q--; + if (bn_add_words(wnum.d, wnum.d, sdiv->d, div_n)) { + /* we can't have an overflow here (assuming + * that q != 0, but if q == 0 then tmp is + * zero anyway) */ + (*wnump)++; + } + } + /* store part of the result */ + *resp = q; + } + bn_correct_top(snum); + if (rm != NULL) { + /* Keep a copy of the neg flag in num because if rm==num + * BN_rshift() will overwrite it. + */ + int neg = num->neg; + if (!BN_rshift(rm, snum, norm_shift)) { + goto err; + } + if (!BN_is_zero(rm)) { + rm->neg = neg; + } + } + if (no_branch) { + bn_correct_top(res); + } + BN_CTX_end(ctx); + return 1; + +err: + BN_CTX_end(ctx); + return 0; +} + +int BN_nnmod(BIGNUM *r, const BIGNUM *m, const BIGNUM *d, BN_CTX *ctx) { + if (!(BN_mod(r, m, d, ctx))) { + return 0; + } + if (!r->neg) { + return 1; + } + + /* now -|d| < r < 0, so we have to set r := r + |d|. */ + return (d->neg ? BN_sub : BN_add)(r, r, d); +} + +int BN_mod_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, + BN_CTX *ctx) { + if (!BN_add(r, a, b)) { + return 0; + } + return BN_nnmod(r, r, m, ctx); +} + +int BN_mod_add_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const BIGNUM *m) { + if (!BN_uadd(r, a, b)) { + return 0; + } + if (BN_ucmp(r, m) >= 0) { + return BN_usub(r, r, m); + } + return 1; +} + +int BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, + BN_CTX *ctx) { + if (!BN_sub(r, a, b)) { + return 0; + } + return BN_nnmod(r, r, m, ctx); +} + +/* BN_mod_sub variant that may be used if both a and b are non-negative + * and less than m */ +int BN_mod_sub_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const BIGNUM *m) { + if (!BN_sub(r, a, b)) { + return 0; + } + if (r->neg) { + return BN_add(r, r, m); + } + return 1; +} + +int BN_mod_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, + BN_CTX *ctx) { + BIGNUM *t; + int ret = 0; + + BN_CTX_start(ctx); + t = BN_CTX_get(ctx); + if (t == NULL) { + goto err; + } + + if (a == b) { + if (!BN_sqr(t, a, ctx)) { + goto err; + } + } else { + if (!BN_mul(t, a, b, ctx)) { + goto err; + } + } + + if (!BN_nnmod(r, t, m, ctx)) { + goto err; + } + + ret = 1; + +err: + BN_CTX_end(ctx); + return ret; +} + +int BN_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx) { + if (!BN_sqr(r, a, ctx)) { + return 0; + } + + /* r->neg == 0, thus we don't need BN_nnmod */ + return BN_mod(r, r, m, ctx); +} + +int BN_mod_lshift(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m, + BN_CTX *ctx) { + BIGNUM *abs_m = NULL; + int ret; + + if (!BN_nnmod(r, a, m, ctx)) { + return 0; + } + + if (m->neg) { + abs_m = BN_dup(m); + if (abs_m == NULL) { + return 0; + } + abs_m->neg = 0; + } + + ret = BN_mod_lshift_quick(r, r, n, (abs_m ? abs_m : m)); + + BN_free(abs_m); + return ret; +} + +int BN_mod_lshift_quick(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m) { + if (r != a) { + if (BN_copy(r, a) == NULL) { + return 0; + } + } + + while (n > 0) { + int max_shift; + + /* 0 < r < m */ + max_shift = BN_num_bits(m) - BN_num_bits(r); + /* max_shift >= 0 */ + + if (max_shift < 0) { + OPENSSL_PUT_ERROR(BN, BN_R_INPUT_NOT_REDUCED); + return 0; + } + + if (max_shift > n) { + max_shift = n; + } + + if (max_shift) { + if (!BN_lshift(r, r, max_shift)) { + return 0; + } + n -= max_shift; + } else { + if (!BN_lshift1(r, r)) { + return 0; + } + --n; + } + + /* BN_num_bits(r) <= BN_num_bits(m) */ + if (BN_cmp(r, m) >= 0) { + if (!BN_sub(r, r, m)) { + return 0; + } + } + } + + return 1; +} + +int BN_mod_lshift1(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx) { + if (!BN_lshift1(r, a)) { + return 0; + } + + return BN_nnmod(r, r, m, ctx); +} + +int BN_mod_lshift1_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *m) { + if (!BN_lshift1(r, a)) { + return 0; + } + if (BN_cmp(r, m) >= 0) { + return BN_sub(r, r, m); + } + + return 1; +} + +BN_ULONG BN_div_word(BIGNUM *a, BN_ULONG w) { + BN_ULONG ret = 0; + int i, j; + + w &= BN_MASK2; + + if (!w) { + /* actually this an error (division by zero) */ + return (BN_ULONG) - 1; + } + + if (a->top == 0) { + return 0; + } + + /* normalize input for |bn_div_rem_words|. */ + j = BN_BITS2 - BN_num_bits_word(w); + w <<= j; + if (!BN_lshift(a, a, j)) { + return (BN_ULONG) - 1; + } + + for (i = a->top - 1; i >= 0; i--) { + BN_ULONG l = a->d[i]; + BN_ULONG d; + BN_ULONG unused_rem; + bn_div_rem_words(&d, &unused_rem, ret, l, w); + ret = (l - ((d * w) & BN_MASK2)) & BN_MASK2; + a->d[i] = d; + } + + if ((a->top > 0) && (a->d[a->top - 1] == 0)) { + a->top--; + } + + ret >>= j; + return ret; +} + +BN_ULONG BN_mod_word(const BIGNUM *a, BN_ULONG w) { +#ifndef BN_ULLONG + BN_ULONG ret = 0; +#else + BN_ULLONG ret = 0; +#endif + int i; + + if (w == 0) { + return (BN_ULONG) -1; + } + +#ifndef BN_ULLONG + /* If |w| is too long and we don't have |BN_ULLONG| then we need to fall back + * to using |BN_div_word|. */ + if (w > ((BN_ULONG)1 << BN_BITS4)) { + BIGNUM *tmp = BN_dup(a); + if (tmp == NULL) { + return (BN_ULONG)-1; + } + ret = BN_div_word(tmp, w); + BN_free(tmp); + return ret; + } +#endif + + w &= BN_MASK2; + for (i = a->top - 1; i >= 0; i--) { +#ifndef BN_ULLONG + ret = ((ret << BN_BITS4) | ((a->d[i] >> BN_BITS4) & BN_MASK2l)) % w; + ret = ((ret << BN_BITS4) | (a->d[i] & BN_MASK2l)) % w; +#else + ret = (BN_ULLONG)(((ret << (BN_ULLONG)BN_BITS2) | a->d[i]) % (BN_ULLONG)w); +#endif + } + return (BN_ULONG)ret; +} diff --git a/external/boringssl/crypto/bn/exponentiation.c b/external/boringssl/crypto/bn/exponentiation.c new file mode 100644 index 0000000000..eedc88e879 --- /dev/null +++ b/external/boringssl/crypto/bn/exponentiation.c @@ -0,0 +1,1258 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include + +#include +#include +#include + +#include "internal.h" + + +#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) +#define OPENSSL_BN_ASM_MONT5 +#define RSAZ_ENABLED + +#include "rsaz_exp.h" + +void bn_mul_mont_gather5(BN_ULONG *rp, const BN_ULONG *ap, const void *table, + const BN_ULONG *np, const BN_ULONG *n0, int num, + int power); +void bn_scatter5(const BN_ULONG *inp, size_t num, void *table, size_t power); +void bn_gather5(BN_ULONG *out, size_t num, void *table, size_t power); +void bn_power5(BN_ULONG *rp, const BN_ULONG *ap, const void *table, + const BN_ULONG *np, const BN_ULONG *n0, int num, int power); +int bn_from_montgomery(BN_ULONG *rp, const BN_ULONG *ap, + const BN_ULONG *not_used, const BN_ULONG *np, + const BN_ULONG *n0, int num); +#endif + +int BN_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) { + int i, bits, ret = 0; + BIGNUM *v, *rr; + + if ((p->flags & BN_FLG_CONSTTIME) != 0) { + /* BN_FLG_CONSTTIME only supported by BN_mod_exp_mont() */ + OPENSSL_PUT_ERROR(BN, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + + BN_CTX_start(ctx); + if (r == a || r == p) { + rr = BN_CTX_get(ctx); + } else { + rr = r; + } + + v = BN_CTX_get(ctx); + if (rr == NULL || v == NULL) { + goto err; + } + + if (BN_copy(v, a) == NULL) { + goto err; + } + bits = BN_num_bits(p); + + if (BN_is_odd(p)) { + if (BN_copy(rr, a) == NULL) { + goto err; + } + } else { + if (!BN_one(rr)) { + goto err; + } + } + + for (i = 1; i < bits; i++) { + if (!BN_sqr(v, v, ctx)) { + goto err; + } + if (BN_is_bit_set(p, i)) { + if (!BN_mul(rr, rr, v, ctx)) { + goto err; + } + } + } + + if (r != rr && !BN_copy(r, rr)) { + goto err; + } + ret = 1; + +err: + BN_CTX_end(ctx); + return ret; +} + +/* maximum precomputation table size for *variable* sliding windows */ +#define TABLE_SIZE 32 + +typedef struct bn_recp_ctx_st { + BIGNUM N; /* the divisor */ + BIGNUM Nr; /* the reciprocal */ + int num_bits; + int shift; + int flags; +} BN_RECP_CTX; + +static void BN_RECP_CTX_init(BN_RECP_CTX *recp) { + BN_init(&recp->N); + BN_init(&recp->Nr); + recp->num_bits = 0; + recp->shift = 0; + recp->flags = 0; +} + +static void BN_RECP_CTX_free(BN_RECP_CTX *recp) { + if (recp == NULL) { + return; + } + + BN_free(&recp->N); + BN_free(&recp->Nr); +} + +static int BN_RECP_CTX_set(BN_RECP_CTX *recp, const BIGNUM *d, BN_CTX *ctx) { + if (!BN_copy(&(recp->N), d)) { + return 0; + } + BN_zero(&recp->Nr); + recp->num_bits = BN_num_bits(d); + recp->shift = 0; + + return 1; +} + +/* len is the expected size of the result We actually calculate with an extra + * word of precision, so we can do faster division if the remainder is not + * required. + * r := 2^len / m */ +static int BN_reciprocal(BIGNUM *r, const BIGNUM *m, int len, BN_CTX *ctx) { + int ret = -1; + BIGNUM *t; + + BN_CTX_start(ctx); + t = BN_CTX_get(ctx); + if (t == NULL) { + goto err; + } + + if (!BN_set_bit(t, len)) { + goto err; + } + + if (!BN_div(r, NULL, t, m, ctx)) { + goto err; + } + + ret = len; + +err: + BN_CTX_end(ctx); + return ret; +} + +static int BN_div_recp(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, + BN_RECP_CTX *recp, BN_CTX *ctx) { + int i, j, ret = 0; + BIGNUM *a, *b, *d, *r; + + BN_CTX_start(ctx); + a = BN_CTX_get(ctx); + b = BN_CTX_get(ctx); + if (dv != NULL) { + d = dv; + } else { + d = BN_CTX_get(ctx); + } + + if (rem != NULL) { + r = rem; + } else { + r = BN_CTX_get(ctx); + } + + if (a == NULL || b == NULL || d == NULL || r == NULL) { + goto err; + } + + if (BN_ucmp(m, &recp->N) < 0) { + BN_zero(d); + if (!BN_copy(r, m)) { + goto err; + } + BN_CTX_end(ctx); + return 1; + } + + /* We want the remainder + * Given input of ABCDEF / ab + * we need multiply ABCDEF by 3 digests of the reciprocal of ab */ + + /* i := max(BN_num_bits(m), 2*BN_num_bits(N)) */ + i = BN_num_bits(m); + j = recp->num_bits << 1; + if (j > i) { + i = j; + } + + /* Nr := round(2^i / N) */ + if (i != recp->shift) { + recp->shift = + BN_reciprocal(&(recp->Nr), &(recp->N), i, + ctx); /* BN_reciprocal returns i, or -1 for an error */ + } + + if (recp->shift == -1) { + goto err; + } + + /* d := |round(round(m / 2^BN_num_bits(N)) * recp->Nr / 2^(i - + * BN_num_bits(N)))| + * = |round(round(m / 2^BN_num_bits(N)) * round(2^i / N) / 2^(i - + * BN_num_bits(N)))| + * <= |(m / 2^BN_num_bits(N)) * (2^i / N) * (2^BN_num_bits(N) / 2^i)| + * = |m/N| */ + if (!BN_rshift(a, m, recp->num_bits)) { + goto err; + } + if (!BN_mul(b, a, &(recp->Nr), ctx)) { + goto err; + } + if (!BN_rshift(d, b, i - recp->num_bits)) { + goto err; + } + d->neg = 0; + + if (!BN_mul(b, &(recp->N), d, ctx)) { + goto err; + } + if (!BN_usub(r, m, b)) { + goto err; + } + r->neg = 0; + + j = 0; + while (BN_ucmp(r, &(recp->N)) >= 0) { + if (j++ > 2) { + OPENSSL_PUT_ERROR(BN, BN_R_BAD_RECIPROCAL); + goto err; + } + if (!BN_usub(r, r, &(recp->N))) { + goto err; + } + if (!BN_add_word(d, 1)) { + goto err; + } + } + + r->neg = BN_is_zero(r) ? 0 : m->neg; + d->neg = m->neg ^ recp->N.neg; + ret = 1; + +err: + BN_CTX_end(ctx); + return ret; +} + +static int BN_mod_mul_reciprocal(BIGNUM *r, const BIGNUM *x, const BIGNUM *y, + BN_RECP_CTX *recp, BN_CTX *ctx) { + int ret = 0; + BIGNUM *a; + const BIGNUM *ca; + + BN_CTX_start(ctx); + a = BN_CTX_get(ctx); + if (a == NULL) { + goto err; + } + + if (y != NULL) { + if (x == y) { + if (!BN_sqr(a, x, ctx)) { + goto err; + } + } else { + if (!BN_mul(a, x, y, ctx)) { + goto err; + } + } + ca = a; + } else { + ca = x; /* Just do the mod */ + } + + ret = BN_div_recp(NULL, r, ca, recp, ctx); + +err: + BN_CTX_end(ctx); + return ret; +} + +/* BN_window_bits_for_exponent_size -- macro for sliding window mod_exp + * functions + * + * For window size 'w' (w >= 2) and a random 'b' bits exponent, the number of + * multiplications is a constant plus on average + * + * 2^(w-1) + (b-w)/(w+1); + * + * here 2^(w-1) is for precomputing the table (we actually need entries only + * for windows that have the lowest bit set), and (b-w)/(w+1) is an + * approximation for the expected number of w-bit windows, not counting the + * first one. + * + * Thus we should use + * + * w >= 6 if b > 671 + * w = 5 if 671 > b > 239 + * w = 4 if 239 > b > 79 + * w = 3 if 79 > b > 23 + * w <= 2 if 23 > b + * + * (with draws in between). Very small exponents are often selected + * with low Hamming weight, so we use w = 1 for b <= 23. */ +#define BN_window_bits_for_exponent_size(b) \ + ((b) > 671 ? 6 : \ + (b) > 239 ? 5 : \ + (b) > 79 ? 4 : \ + (b) > 23 ? 3 : 1) + +static int mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx) { + int i, j, bits, ret = 0, wstart, window; + int start = 1; + BIGNUM *aa; + /* Table of variables obtained from 'ctx' */ + BIGNUM *val[TABLE_SIZE]; + BN_RECP_CTX recp; + + if (BN_get_flags(p, BN_FLG_CONSTTIME) != 0) { + /* BN_FLG_CONSTTIME only supported by BN_mod_exp_mont() */ + OPENSSL_PUT_ERROR(BN, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + + bits = BN_num_bits(p); + + if (bits == 0) { + /* x**0 mod 1 is still zero. */ + if (BN_is_one(m)) { + BN_zero(r); + return 1; + } + return BN_one(r); + } + + BN_CTX_start(ctx); + aa = BN_CTX_get(ctx); + val[0] = BN_CTX_get(ctx); + if (!aa || !val[0]) { + goto err; + } + + BN_RECP_CTX_init(&recp); + if (m->neg) { + /* ignore sign of 'm' */ + if (!BN_copy(aa, m)) { + goto err; + } + aa->neg = 0; + if (BN_RECP_CTX_set(&recp, aa, ctx) <= 0) { + goto err; + } + } else { + if (BN_RECP_CTX_set(&recp, m, ctx) <= 0) { + goto err; + } + } + + if (!BN_nnmod(val[0], a, m, ctx)) { + goto err; /* 1 */ + } + if (BN_is_zero(val[0])) { + BN_zero(r); + ret = 1; + goto err; + } + + window = BN_window_bits_for_exponent_size(bits); + if (window > 1) { + if (!BN_mod_mul_reciprocal(aa, val[0], val[0], &recp, ctx)) { + goto err; /* 2 */ + } + j = 1 << (window - 1); + for (i = 1; i < j; i++) { + if (((val[i] = BN_CTX_get(ctx)) == NULL) || + !BN_mod_mul_reciprocal(val[i], val[i - 1], aa, &recp, ctx)) { + goto err; + } + } + } + + start = 1; /* This is used to avoid multiplication etc + * when there is only the value '1' in the + * buffer. */ + wstart = bits - 1; /* The top bit of the window */ + + if (!BN_one(r)) { + goto err; + } + + for (;;) { + int wvalue; /* The 'value' of the window */ + int wend; /* The bottom bit of the window */ + + if (BN_is_bit_set(p, wstart) == 0) { + if (!start) { + if (!BN_mod_mul_reciprocal(r, r, r, &recp, ctx)) { + goto err; + } + } + if (wstart == 0) { + break; + } + wstart--; + continue; + } + + /* We now have wstart on a 'set' bit, we now need to work out + * how bit a window to do. To do this we need to scan + * forward until the last set bit before the end of the + * window */ + wvalue = 1; + wend = 0; + for (i = 1; i < window; i++) { + if (wstart - i < 0) { + break; + } + if (BN_is_bit_set(p, wstart - i)) { + wvalue <<= (i - wend); + wvalue |= 1; + wend = i; + } + } + + /* wend is the size of the current window */ + j = wend + 1; + /* add the 'bytes above' */ + if (!start) { + for (i = 0; i < j; i++) { + if (!BN_mod_mul_reciprocal(r, r, r, &recp, ctx)) { + goto err; + } + } + } + + /* wvalue will be an odd number < 2^window */ + if (!BN_mod_mul_reciprocal(r, r, val[wvalue >> 1], &recp, ctx)) { + goto err; + } + + /* move the 'window' down further */ + wstart -= wend + 1; + start = 0; + if (wstart < 0) { + break; + } + } + ret = 1; + +err: + BN_CTX_end(ctx); + BN_RECP_CTX_free(&recp); + return ret; +} + +int BN_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, + BN_CTX *ctx) { + if (BN_is_odd(m)) { + return BN_mod_exp_mont(r, a, p, m, ctx, NULL); + } + + return mod_exp_recp(r, a, p, m, ctx); +} + +int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, const BN_MONT_CTX *mont) { + int i, j, bits, ret = 0, wstart, window; + int start = 1; + BIGNUM *d, *r; + const BIGNUM *aa; + /* Table of variables obtained from 'ctx' */ + BIGNUM *val[TABLE_SIZE]; + BN_MONT_CTX *new_mont = NULL; + + if (BN_get_flags(p, BN_FLG_CONSTTIME) != 0) { + return BN_mod_exp_mont_consttime(rr, a, p, m, ctx, mont); + } + + if (!BN_is_odd(m)) { + OPENSSL_PUT_ERROR(BN, BN_R_CALLED_WITH_EVEN_MODULUS); + return 0; + } + bits = BN_num_bits(p); + if (bits == 0) { + /* x**0 mod 1 is still zero. */ + if (BN_is_one(m)) { + BN_zero(rr); + return 1; + } + return BN_one(rr); + } + + BN_CTX_start(ctx); + d = BN_CTX_get(ctx); + r = BN_CTX_get(ctx); + val[0] = BN_CTX_get(ctx); + if (!d || !r || !val[0]) { + goto err; + } + + /* Allocate a montgomery context if it was not supplied by the caller. */ + if (mont == NULL) { + new_mont = BN_MONT_CTX_new(); + if (new_mont == NULL || !BN_MONT_CTX_set(new_mont, m, ctx)) { + goto err; + } + mont = new_mont; + } + + if (a->neg || BN_ucmp(a, m) >= 0) { + if (!BN_nnmod(val[0], a, m, ctx)) { + goto err; + } + aa = val[0]; + } else { + aa = a; + } + + if (BN_is_zero(aa)) { + BN_zero(rr); + ret = 1; + goto err; + } + if (!BN_to_montgomery(val[0], aa, mont, ctx)) { + goto err; /* 1 */ + } + + window = BN_window_bits_for_exponent_size(bits); + if (window > 1) { + if (!BN_mod_mul_montgomery(d, val[0], val[0], mont, ctx)) { + goto err; /* 2 */ + } + j = 1 << (window - 1); + for (i = 1; i < j; i++) { + if (((val[i] = BN_CTX_get(ctx)) == NULL) || + !BN_mod_mul_montgomery(val[i], val[i - 1], d, mont, ctx)) { + goto err; + } + } + } + + start = 1; /* This is used to avoid multiplication etc + * when there is only the value '1' in the + * buffer. */ + wstart = bits - 1; /* The top bit of the window */ + + j = m->top; /* borrow j */ + if (m->d[j - 1] & (((BN_ULONG)1) << (BN_BITS2 - 1))) { + if (bn_wexpand(r, j) == NULL) { + goto err; + } + /* 2^(top*BN_BITS2) - m */ + r->d[0] = (0 - m->d[0]) & BN_MASK2; + for (i = 1; i < j; i++) { + r->d[i] = (~m->d[i]) & BN_MASK2; + } + r->top = j; + /* Upper words will be zero if the corresponding words of 'm' + * were 0xfff[...], so decrement r->top accordingly. */ + bn_correct_top(r); + } else if (!BN_to_montgomery(r, BN_value_one(), mont, ctx)) { + goto err; + } + + for (;;) { + int wvalue; /* The 'value' of the window */ + int wend; /* The bottom bit of the window */ + + if (BN_is_bit_set(p, wstart) == 0) { + if (!start && !BN_mod_mul_montgomery(r, r, r, mont, ctx)) { + goto err; + } + if (wstart == 0) { + break; + } + wstart--; + continue; + } + + /* We now have wstart on a 'set' bit, we now need to work out how bit a + * window to do. To do this we need to scan forward until the last set bit + * before the end of the window */ + wvalue = 1; + wend = 0; + for (i = 1; i < window; i++) { + if (wstart - i < 0) { + break; + } + if (BN_is_bit_set(p, wstart - i)) { + wvalue <<= (i - wend); + wvalue |= 1; + wend = i; + } + } + + /* wend is the size of the current window */ + j = wend + 1; + /* add the 'bytes above' */ + if (!start) { + for (i = 0; i < j; i++) { + if (!BN_mod_mul_montgomery(r, r, r, mont, ctx)) { + goto err; + } + } + } + + /* wvalue will be an odd number < 2^window */ + if (!BN_mod_mul_montgomery(r, r, val[wvalue >> 1], mont, ctx)) { + goto err; + } + + /* move the 'window' down further */ + wstart -= wend + 1; + start = 0; + if (wstart < 0) { + break; + } + } + + if (!BN_from_montgomery(rr, r, mont, ctx)) { + goto err; + } + ret = 1; + +err: + BN_MONT_CTX_free(new_mont); + BN_CTX_end(ctx); + return ret; +} + +/* BN_mod_exp_mont_consttime() stores the precomputed powers in a specific + * layout so that accessing any of these table values shows the same access + * pattern as far as cache lines are concerned. The following functions are + * used to transfer a BIGNUM from/to that table. */ +static int copy_to_prebuf(const BIGNUM *b, int top, unsigned char *buf, int idx, + int window) { + int i, j; + const int width = 1 << window; + BN_ULONG *table = (BN_ULONG *) buf; + + if (top > b->top) { + top = b->top; /* this works because 'buf' is explicitly zeroed */ + } + + for (i = 0, j = idx; i < top; i++, j += width) { + table[j] = b->d[i]; + } + + return 1; +} + +static int copy_from_prebuf(BIGNUM *b, int top, unsigned char *buf, int idx, + int window) { + int i, j; + const int width = 1 << window; + volatile BN_ULONG *table = (volatile BN_ULONG *)buf; + + if (bn_wexpand(b, top) == NULL) { + return 0; + } + + if (window <= 3) { + for (i = 0; i < top; i++, table += width) { + BN_ULONG acc = 0; + + for (j = 0; j < width; j++) { + acc |= table[j] & ((BN_ULONG)0 - (constant_time_eq_int(j, idx) & 1)); + } + + b->d[i] = acc; + } + } else { + int xstride = 1 << (window - 2); + BN_ULONG y0, y1, y2, y3; + + i = idx >> (window - 2); /* equivalent of idx / xstride */ + idx &= xstride - 1; /* equivalent of idx % xstride */ + + y0 = (BN_ULONG)0 - (constant_time_eq_int(i, 0) & 1); + y1 = (BN_ULONG)0 - (constant_time_eq_int(i, 1) & 1); + y2 = (BN_ULONG)0 - (constant_time_eq_int(i, 2) & 1); + y3 = (BN_ULONG)0 - (constant_time_eq_int(i, 3) & 1); + + for (i = 0; i < top; i++, table += width) { + BN_ULONG acc = 0; + + for (j = 0; j < xstride; j++) { + acc |= ((table[j + 0 * xstride] & y0) | (table[j + 1 * xstride] & y1) | + (table[j + 2 * xstride] & y2) | (table[j + 3 * xstride] & y3)) & + ((BN_ULONG)0 - (constant_time_eq_int(j, idx) & 1)); + } + + b->d[i] = acc; + } + } + + b->top = top; + bn_correct_top(b); + return 1; +} + +/* BN_mod_exp_mont_conttime is based on the assumption that the L1 data cache + * line width of the target processor is at least the following value. */ +#define MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH (64) +#define MOD_EXP_CTIME_MIN_CACHE_LINE_MASK \ + (MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH - 1) + +/* Window sizes optimized for fixed window size modular exponentiation + * algorithm (BN_mod_exp_mont_consttime). + * + * To achieve the security goals of BN_mode_exp_mont_consttime, the maximum + * size of the window must not exceed + * log_2(MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH). + * + * Window size thresholds are defined for cache line sizes of 32 and 64, cache + * line sizes where log_2(32)=5 and log_2(64)=6 respectively. A window size of + * 7 should only be used on processors that have a 128 byte or greater cache + * line size. */ +#if MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH == 64 + +#define BN_window_bits_for_ctime_exponent_size(b) \ + ((b) > 937 ? 6 : (b) > 306 ? 5 : (b) > 89 ? 4 : (b) > 22 ? 3 : 1) +#define BN_MAX_WINDOW_BITS_FOR_CTIME_EXPONENT_SIZE (6) + +#elif MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH == 32 + +#define BN_window_bits_for_ctime_exponent_size(b) \ + ((b) > 306 ? 5 : (b) > 89 ? 4 : (b) > 22 ? 3 : 1) +#define BN_MAX_WINDOW_BITS_FOR_CTIME_EXPONENT_SIZE (5) + +#endif + +/* Given a pointer value, compute the next address that is a cache line + * multiple. */ +#define MOD_EXP_CTIME_ALIGN(x_) \ + ((unsigned char *)(x_) + \ + (MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH - \ + (((size_t)(x_)) & (MOD_EXP_CTIME_MIN_CACHE_LINE_MASK)))) + +/* This variant of BN_mod_exp_mont() uses fixed windows and the special + * precomputation memory layout to limit data-dependency to a minimum + * to protect secret exponents (cf. the hyper-threading timing attacks + * pointed out by Colin Percival, + * http://www.daemonology.net/hyperthreading-considered-harmful/) + */ +int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, + const BN_MONT_CTX *mont) { + int i, bits, ret = 0, window, wvalue; + int top; + BN_MONT_CTX *new_mont = NULL; + + int numPowers; + unsigned char *powerbufFree = NULL; + int powerbufLen = 0; + unsigned char *powerbuf = NULL; + BIGNUM tmp, am; + + if (!BN_is_odd(m)) { + OPENSSL_PUT_ERROR(BN, BN_R_CALLED_WITH_EVEN_MODULUS); + return 0; + } + + top = m->top; + + bits = BN_num_bits(p); + if (bits == 0) { + /* x**0 mod 1 is still zero. */ + if (BN_is_one(m)) { + BN_zero(rr); + return 1; + } + return BN_one(rr); + } + + /* Allocate a montgomery context if it was not supplied by the caller. */ + if (mont == NULL) { + new_mont = BN_MONT_CTX_new(); + if (new_mont == NULL || !BN_MONT_CTX_set(new_mont, m, ctx)) { + goto err; + } + mont = new_mont; + } + +#ifdef RSAZ_ENABLED + /* If the size of the operands allow it, perform the optimized + * RSAZ exponentiation. For further information see + * crypto/bn/rsaz_exp.c and accompanying assembly modules. */ + if ((16 == a->top) && (16 == p->top) && (BN_num_bits(m) == 1024) && + rsaz_avx2_eligible()) { + if (NULL == bn_wexpand(rr, 16)) { + goto err; + } + RSAZ_1024_mod_exp_avx2(rr->d, a->d, p->d, m->d, mont->RR.d, mont->n0[0]); + rr->top = 16; + rr->neg = 0; + bn_correct_top(rr); + ret = 1; + goto err; + } else if ((8 == a->top) && (8 == p->top) && (BN_num_bits(m) == 512)) { + if (NULL == bn_wexpand(rr, 8)) { + goto err; + } + RSAZ_512_mod_exp(rr->d, a->d, p->d, m->d, mont->n0[0], mont->RR.d); + rr->top = 8; + rr->neg = 0; + bn_correct_top(rr); + ret = 1; + goto err; + } +#endif + + /* Get the window size to use with size of p. */ + window = BN_window_bits_for_ctime_exponent_size(bits); +#if defined(OPENSSL_BN_ASM_MONT5) + if (window >= 5) { + window = 5; /* ~5% improvement for RSA2048 sign, and even for RSA4096 */ + /* reserve space for mont->N.d[] copy */ + powerbufLen += top * sizeof(mont->N.d[0]); + } +#endif + + /* Allocate a buffer large enough to hold all of the pre-computed + * powers of am, am itself and tmp. + */ + numPowers = 1 << window; + powerbufLen += + sizeof(m->d[0]) * + (top * numPowers + ((2 * top) > numPowers ? (2 * top) : numPowers)); +#ifdef alloca + if (powerbufLen < 3072) { + powerbufFree = alloca(powerbufLen + MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH); + } else +#endif + { + if ((powerbufFree = OPENSSL_malloc( + powerbufLen + MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH)) == NULL) { + goto err; + } + } + + powerbuf = MOD_EXP_CTIME_ALIGN(powerbufFree); + memset(powerbuf, 0, powerbufLen); + +#ifdef alloca + if (powerbufLen < 3072) { + powerbufFree = NULL; + } +#endif + + /* lay down tmp and am right after powers table */ + tmp.d = (BN_ULONG *)(powerbuf + sizeof(m->d[0]) * top * numPowers); + am.d = tmp.d + top; + tmp.top = am.top = 0; + tmp.dmax = am.dmax = top; + tmp.neg = am.neg = 0; + tmp.flags = am.flags = BN_FLG_STATIC_DATA; + +/* prepare a^0 in Montgomery domain */ +/* by Shay Gueron's suggestion */ + if (m->d[top - 1] & (((BN_ULONG)1) << (BN_BITS2 - 1))) { + /* 2^(top*BN_BITS2) - m */ + tmp.d[0] = (0 - m->d[0]) & BN_MASK2; + for (i = 1; i < top; i++) { + tmp.d[i] = (~m->d[i]) & BN_MASK2; + } + tmp.top = top; + } else if (!BN_to_montgomery(&tmp, BN_value_one(), mont, ctx)) { + goto err; + } + + /* prepare a^1 in Montgomery domain */ + if (a->neg || BN_ucmp(a, m) >= 0) { + if (!BN_mod(&am, a, m, ctx) || + !BN_to_montgomery(&am, &am, mont, ctx)) { + goto err; + } + } else if (!BN_to_montgomery(&am, a, mont, ctx)) { + goto err; + } + +#if defined(OPENSSL_BN_ASM_MONT5) + /* This optimization uses ideas from http://eprint.iacr.org/2011/239, + * specifically optimization of cache-timing attack countermeasures + * and pre-computation optimization. */ + + /* Dedicated window==4 case improves 512-bit RSA sign by ~15%, but as + * 512-bit RSA is hardly relevant, we omit it to spare size... */ + if (window == 5 && top > 1) { + const BN_ULONG *n0 = mont->n0; + BN_ULONG *np; + + /* BN_to_montgomery can contaminate words above .top + * [in BN_DEBUG[_DEBUG] build]... */ + for (i = am.top; i < top; i++) { + am.d[i] = 0; + } + for (i = tmp.top; i < top; i++) { + tmp.d[i] = 0; + } + + /* copy mont->N.d[] to improve cache locality */ + for (np = am.d + top, i = 0; i < top; i++) { + np[i] = mont->N.d[i]; + } + + bn_scatter5(tmp.d, top, powerbuf, 0); + bn_scatter5(am.d, am.top, powerbuf, 1); + bn_mul_mont(tmp.d, am.d, am.d, np, n0, top); + bn_scatter5(tmp.d, top, powerbuf, 2); + + /* same as above, but uses squaring for 1/2 of operations */ + for (i = 4; i < 32; i *= 2) { + bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top); + bn_scatter5(tmp.d, top, powerbuf, i); + } + for (i = 3; i < 8; i += 2) { + int j; + bn_mul_mont_gather5(tmp.d, am.d, powerbuf, np, n0, top, i - 1); + bn_scatter5(tmp.d, top, powerbuf, i); + for (j = 2 * i; j < 32; j *= 2) { + bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top); + bn_scatter5(tmp.d, top, powerbuf, j); + } + } + for (; i < 16; i += 2) { + bn_mul_mont_gather5(tmp.d, am.d, powerbuf, np, n0, top, i - 1); + bn_scatter5(tmp.d, top, powerbuf, i); + bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top); + bn_scatter5(tmp.d, top, powerbuf, 2 * i); + } + for (; i < 32; i += 2) { + bn_mul_mont_gather5(tmp.d, am.d, powerbuf, np, n0, top, i - 1); + bn_scatter5(tmp.d, top, powerbuf, i); + } + + bits--; + for (wvalue = 0, i = bits % 5; i >= 0; i--, bits--) { + wvalue = (wvalue << 1) + BN_is_bit_set(p, bits); + } + bn_gather5(tmp.d, top, powerbuf, wvalue); + + /* At this point |bits| is 4 mod 5 and at least -1. (|bits| is the first bit + * that has not been read yet.) */ + assert(bits >= -1 && (bits == -1 || bits % 5 == 4)); + + /* Scan the exponent one window at a time starting from the most + * significant bits. + */ + if (top & 7) { + while (bits >= 0) { + for (wvalue = 0, i = 0; i < 5; i++, bits--) { + wvalue = (wvalue << 1) + BN_is_bit_set(p, bits); + } + + bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top); + bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top); + bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top); + bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top); + bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top); + bn_mul_mont_gather5(tmp.d, tmp.d, powerbuf, np, n0, top, wvalue); + } + } else { + const uint8_t *p_bytes = (const uint8_t *)p->d; + int max_bits = p->top * BN_BITS2; + assert(bits < max_bits); + /* |p = 0| has been handled as a special case, so |max_bits| is at least + * one word. */ + assert(max_bits >= 64); + + /* If the first bit to be read lands in the last byte, unroll the first + * iteration to avoid reading past the bounds of |p->d|. (After the first + * iteration, we are guaranteed to be past the last byte.) Note |bits| + * here is the top bit, inclusive. */ + if (bits - 4 >= max_bits - 8) { + /* Read five bits from |bits-4| through |bits|, inclusive. */ + wvalue = p_bytes[p->top * BN_BYTES - 1]; + wvalue >>= (bits - 4) & 7; + wvalue &= 0x1f; + bits -= 5; + bn_power5(tmp.d, tmp.d, powerbuf, np, n0, top, wvalue); + } + while (bits >= 0) { + /* Read five bits from |bits-4| through |bits|, inclusive. */ + int first_bit = bits - 4; + wvalue = *(const uint16_t *) (p_bytes + (first_bit >> 3)); + wvalue >>= first_bit & 7; + wvalue &= 0x1f; + bits -= 5; + bn_power5(tmp.d, tmp.d, powerbuf, np, n0, top, wvalue); + } + } + + ret = bn_from_montgomery(tmp.d, tmp.d, NULL, np, n0, top); + tmp.top = top; + bn_correct_top(&tmp); + if (ret) { + if (!BN_copy(rr, &tmp)) { + ret = 0; + } + goto err; /* non-zero ret means it's not error */ + } + } else +#endif + { + if (!copy_to_prebuf(&tmp, top, powerbuf, 0, window) || + !copy_to_prebuf(&am, top, powerbuf, 1, window)) { + goto err; + } + + /* If the window size is greater than 1, then calculate + * val[i=2..2^winsize-1]. Powers are computed as a*a^(i-1) + * (even powers could instead be computed as (a^(i/2))^2 + * to use the slight performance advantage of sqr over mul). + */ + if (window > 1) { + if (!BN_mod_mul_montgomery(&tmp, &am, &am, mont, ctx) || + !copy_to_prebuf(&tmp, top, powerbuf, 2, window)) { + goto err; + } + for (i = 3; i < numPowers; i++) { + /* Calculate a^i = a^(i-1) * a */ + if (!BN_mod_mul_montgomery(&tmp, &am, &tmp, mont, ctx) || + !copy_to_prebuf(&tmp, top, powerbuf, i, window)) { + goto err; + } + } + } + + bits--; + for (wvalue = 0, i = bits % window; i >= 0; i--, bits--) { + wvalue = (wvalue << 1) + BN_is_bit_set(p, bits); + } + if (!copy_from_prebuf(&tmp, top, powerbuf, wvalue, window)) { + goto err; + } + + /* Scan the exponent one window at a time starting from the most + * significant bits. + */ + while (bits >= 0) { + wvalue = 0; /* The 'value' of the window */ + + /* Scan the window, squaring the result as we go */ + for (i = 0; i < window; i++, bits--) { + if (!BN_mod_mul_montgomery(&tmp, &tmp, &tmp, mont, ctx)) { + goto err; + } + wvalue = (wvalue << 1) + BN_is_bit_set(p, bits); + } + + /* Fetch the appropriate pre-computed value from the pre-buf */ + if (!copy_from_prebuf(&am, top, powerbuf, wvalue, window)) { + goto err; + } + + /* Multiply the result into the intermediate result */ + if (!BN_mod_mul_montgomery(&tmp, &tmp, &am, mont, ctx)) { + goto err; + } + } + } + + /* Convert the final result from montgomery to standard format */ + if (!BN_from_montgomery(rr, &tmp, mont, ctx)) { + goto err; + } + ret = 1; + +err: + BN_MONT_CTX_free(new_mont); + if (powerbuf != NULL) { + OPENSSL_cleanse(powerbuf, powerbufLen); + OPENSSL_free(powerbufFree); + } + return (ret); +} + +int BN_mod_exp_mont_word(BIGNUM *rr, BN_ULONG a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, + const BN_MONT_CTX *mont) { + BIGNUM a_bignum; + BN_init(&a_bignum); + + int ret = 0; + + if (!BN_set_word(&a_bignum, a)) { + OPENSSL_PUT_ERROR(BN, ERR_R_INTERNAL_ERROR); + goto err; + } + + ret = BN_mod_exp_mont(rr, &a_bignum, p, m, ctx, mont); + +err: + BN_free(&a_bignum); + + return ret; +} + +#define TABLE_SIZE 32 + +int BN_mod_exp2_mont(BIGNUM *rr, const BIGNUM *a1, const BIGNUM *p1, + const BIGNUM *a2, const BIGNUM *p2, const BIGNUM *m, + BN_CTX *ctx, const BN_MONT_CTX *mont) { + BIGNUM tmp; + BN_init(&tmp); + + int ret = 0; + BN_MONT_CTX *new_mont = NULL; + + /* Allocate a montgomery context if it was not supplied by the caller. */ + if (mont == NULL) { + new_mont = BN_MONT_CTX_new(); + if (new_mont == NULL || !BN_MONT_CTX_set(new_mont, m, ctx)) { + goto err; + } + mont = new_mont; + } + + /* BN_mod_mul_montgomery removes one Montgomery factor, so passing one + * Montgomery-encoded and one non-Montgomery-encoded value gives a + * non-Montgomery-encoded result. */ + if (!BN_mod_exp_mont(rr, a1, p1, m, ctx, mont) || + !BN_mod_exp_mont(&tmp, a2, p2, m, ctx, mont) || + !BN_to_montgomery(rr, rr, mont, ctx) || + !BN_mod_mul_montgomery(rr, rr, &tmp, mont, ctx)) { + goto err; + } + + ret = 1; + +err: + BN_MONT_CTX_free(new_mont); + BN_free(&tmp); + + return ret; +} diff --git a/external/boringssl/crypto/bn/gcd.c b/external/boringssl/crypto/bn/gcd.c new file mode 100644 index 0000000000..c9a7123f23 --- /dev/null +++ b/external/boringssl/crypto/bn/gcd.c @@ -0,0 +1,712 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include + +#include "internal.h" + +static BIGNUM *euclid(BIGNUM *a, BIGNUM *b) { + BIGNUM *t; + int shifts = 0; + + /* 0 <= b <= a */ + while (!BN_is_zero(b)) { + /* 0 < b <= a */ + + if (BN_is_odd(a)) { + if (BN_is_odd(b)) { + if (!BN_sub(a, a, b)) { + goto err; + } + if (!BN_rshift1(a, a)) { + goto err; + } + if (BN_cmp(a, b) < 0) { + t = a; + a = b; + b = t; + } + } else { + /* a odd - b even */ + if (!BN_rshift1(b, b)) { + goto err; + } + if (BN_cmp(a, b) < 0) { + t = a; + a = b; + b = t; + } + } + } else { + /* a is even */ + if (BN_is_odd(b)) { + if (!BN_rshift1(a, a)) { + goto err; + } + if (BN_cmp(a, b) < 0) { + t = a; + a = b; + b = t; + } + } else { + /* a even - b even */ + if (!BN_rshift1(a, a)) { + goto err; + } + if (!BN_rshift1(b, b)) { + goto err; + } + shifts++; + } + } + /* 0 <= b <= a */ + } + + if (shifts) { + if (!BN_lshift(a, a, shifts)) { + goto err; + } + } + + return a; + +err: + return NULL; +} + +int BN_gcd(BIGNUM *r, const BIGNUM *in_a, const BIGNUM *in_b, BN_CTX *ctx) { + BIGNUM *a, *b, *t; + int ret = 0; + + BN_CTX_start(ctx); + a = BN_CTX_get(ctx); + b = BN_CTX_get(ctx); + + if (a == NULL || b == NULL) { + goto err; + } + if (BN_copy(a, in_a) == NULL) { + goto err; + } + if (BN_copy(b, in_b) == NULL) { + goto err; + } + + a->neg = 0; + b->neg = 0; + + if (BN_cmp(a, b) < 0) { + t = a; + a = b; + b = t; + } + t = euclid(a, b); + if (t == NULL) { + goto err; + } + + if (BN_copy(r, t) == NULL) { + goto err; + } + ret = 1; + +err: + BN_CTX_end(ctx); + return ret; +} + +/* solves ax == 1 (mod n) */ +static BIGNUM *BN_mod_inverse_no_branch(BIGNUM *out, int *out_no_inverse, + const BIGNUM *a, const BIGNUM *n, + BN_CTX *ctx); + +BIGNUM *BN_mod_inverse_ex(BIGNUM *out, int *out_no_inverse, const BIGNUM *a, + const BIGNUM *n, BN_CTX *ctx) { + BIGNUM *A, *B, *X, *Y, *M, *D, *T, *R = NULL; + BIGNUM *ret = NULL; + int sign; + + if ((a->flags & BN_FLG_CONSTTIME) != 0 || + (n->flags & BN_FLG_CONSTTIME) != 0) { + return BN_mod_inverse_no_branch(out, out_no_inverse, a, n, ctx); + } + + *out_no_inverse = 0; + + BN_CTX_start(ctx); + A = BN_CTX_get(ctx); + B = BN_CTX_get(ctx); + X = BN_CTX_get(ctx); + D = BN_CTX_get(ctx); + M = BN_CTX_get(ctx); + Y = BN_CTX_get(ctx); + T = BN_CTX_get(ctx); + if (T == NULL) { + goto err; + } + + if (out == NULL) { + R = BN_new(); + } else { + R = out; + } + if (R == NULL) { + goto err; + } + + BN_zero(Y); + if (!BN_one(X) || BN_copy(B, a) == NULL || BN_copy(A, n) == NULL) { + goto err; + } + A->neg = 0; + if (B->neg || (BN_ucmp(B, A) >= 0)) { + if (!BN_nnmod(B, B, A, ctx)) { + goto err; + } + } + sign = -1; + /* From B = a mod |n|, A = |n| it follows that + * + * 0 <= B < A, + * -sign*X*a == B (mod |n|), + * sign*Y*a == A (mod |n|). + */ + + if (BN_is_odd(n) && (BN_num_bits(n) <= (BN_BITS2 <= 32 ? 450 : 2048))) { + /* Binary inversion algorithm; requires odd modulus. + * This is faster than the general algorithm if the modulus + * is sufficiently small (about 400 .. 500 bits on 32-bit + * sytems, but much more on 64-bit systems) */ + int shift; + + while (!BN_is_zero(B)) { + /* 0 < B < |n|, + * 0 < A <= |n|, + * (1) -sign*X*a == B (mod |n|), + * (2) sign*Y*a == A (mod |n|) */ + + /* Now divide B by the maximum possible power of two in the integers, + * and divide X by the same value mod |n|. + * When we're done, (1) still holds. */ + shift = 0; + while (!BN_is_bit_set(B, shift)) { + /* note that 0 < B */ + shift++; + + if (BN_is_odd(X)) { + if (!BN_uadd(X, X, n)) { + goto err; + } + } + /* now X is even, so we can easily divide it by two */ + if (!BN_rshift1(X, X)) { + goto err; + } + } + if (shift > 0) { + if (!BN_rshift(B, B, shift)) { + goto err; + } + } + + /* Same for A and Y. Afterwards, (2) still holds. */ + shift = 0; + while (!BN_is_bit_set(A, shift)) { + /* note that 0 < A */ + shift++; + + if (BN_is_odd(Y)) { + if (!BN_uadd(Y, Y, n)) { + goto err; + } + } + /* now Y is even */ + if (!BN_rshift1(Y, Y)) { + goto err; + } + } + if (shift > 0) { + if (!BN_rshift(A, A, shift)) { + goto err; + } + } + + /* We still have (1) and (2). + * Both A and B are odd. + * The following computations ensure that + * + * 0 <= B < |n|, + * 0 < A < |n|, + * (1) -sign*X*a == B (mod |n|), + * (2) sign*Y*a == A (mod |n|), + * + * and that either A or B is even in the next iteration. */ + if (BN_ucmp(B, A) >= 0) { + /* -sign*(X + Y)*a == B - A (mod |n|) */ + if (!BN_uadd(X, X, Y)) { + goto err; + } + /* NB: we could use BN_mod_add_quick(X, X, Y, n), but that + * actually makes the algorithm slower */ + if (!BN_usub(B, B, A)) { + goto err; + } + } else { + /* sign*(X + Y)*a == A - B (mod |n|) */ + if (!BN_uadd(Y, Y, X)) { + goto err; + } + /* as above, BN_mod_add_quick(Y, Y, X, n) would slow things down */ + if (!BN_usub(A, A, B)) { + goto err; + } + } + } + } else { + /* general inversion algorithm */ + + while (!BN_is_zero(B)) { + BIGNUM *tmp; + + /* + * 0 < B < A, + * (*) -sign*X*a == B (mod |n|), + * sign*Y*a == A (mod |n|) */ + + /* (D, M) := (A/B, A%B) ... */ + if (BN_num_bits(A) == BN_num_bits(B)) { + if (!BN_one(D)) { + goto err; + } + if (!BN_sub(M, A, B)) { + goto err; + } + } else if (BN_num_bits(A) == BN_num_bits(B) + 1) { + /* A/B is 1, 2, or 3 */ + if (!BN_lshift1(T, B)) { + goto err; + } + if (BN_ucmp(A, T) < 0) { + /* A < 2*B, so D=1 */ + if (!BN_one(D)) { + goto err; + } + if (!BN_sub(M, A, B)) { + goto err; + } + } else { + /* A >= 2*B, so D=2 or D=3 */ + if (!BN_sub(M, A, T)) { + goto err; + } + if (!BN_add(D, T, B)) { + goto err; /* use D (:= 3*B) as temp */ + } + if (BN_ucmp(A, D) < 0) { + /* A < 3*B, so D=2 */ + if (!BN_set_word(D, 2)) { + goto err; + } + /* M (= A - 2*B) already has the correct value */ + } else { + /* only D=3 remains */ + if (!BN_set_word(D, 3)) { + goto err; + } + /* currently M = A - 2*B, but we need M = A - 3*B */ + if (!BN_sub(M, M, B)) { + goto err; + } + } + } + } else { + if (!BN_div(D, M, A, B, ctx)) { + goto err; + } + } + + /* Now + * A = D*B + M; + * thus we have + * (**) sign*Y*a == D*B + M (mod |n|). */ + + tmp = A; /* keep the BIGNUM object, the value does not matter */ + + /* (A, B) := (B, A mod B) ... */ + A = B; + B = M; + /* ... so we have 0 <= B < A again */ + + /* Since the former M is now B and the former B is now A, + * (**) translates into + * sign*Y*a == D*A + B (mod |n|), + * i.e. + * sign*Y*a - D*A == B (mod |n|). + * Similarly, (*) translates into + * -sign*X*a == A (mod |n|). + * + * Thus, + * sign*Y*a + D*sign*X*a == B (mod |n|), + * i.e. + * sign*(Y + D*X)*a == B (mod |n|). + * + * So if we set (X, Y, sign) := (Y + D*X, X, -sign), we arrive back at + * -sign*X*a == B (mod |n|), + * sign*Y*a == A (mod |n|). + * Note that X and Y stay non-negative all the time. */ + + /* most of the time D is very small, so we can optimize tmp := D*X+Y */ + if (BN_is_one(D)) { + if (!BN_add(tmp, X, Y)) { + goto err; + } + } else { + if (BN_is_word(D, 2)) { + if (!BN_lshift1(tmp, X)) { + goto err; + } + } else if (BN_is_word(D, 4)) { + if (!BN_lshift(tmp, X, 2)) { + goto err; + } + } else if (D->top == 1) { + if (!BN_copy(tmp, X)) { + goto err; + } + if (!BN_mul_word(tmp, D->d[0])) { + goto err; + } + } else { + if (!BN_mul(tmp, D, X, ctx)) { + goto err; + } + } + if (!BN_add(tmp, tmp, Y)) { + goto err; + } + } + + M = Y; /* keep the BIGNUM object, the value does not matter */ + Y = X; + X = tmp; + sign = -sign; + } + } + + /* The while loop (Euclid's algorithm) ends when + * A == gcd(a,n); + * we have + * sign*Y*a == A (mod |n|), + * where Y is non-negative. */ + + if (sign < 0) { + if (!BN_sub(Y, n, Y)) { + goto err; + } + } + /* Now Y*a == A (mod |n|). */ + + if (BN_is_one(A)) { + /* Y*a == 1 (mod |n|) */ + if (!Y->neg && BN_ucmp(Y, n) < 0) { + if (!BN_copy(R, Y)) { + goto err; + } + } else { + if (!BN_nnmod(R, Y, n, ctx)) { + goto err; + } + } + } else { + *out_no_inverse = 1; + OPENSSL_PUT_ERROR(BN, BN_R_NO_INVERSE); + goto err; + } + ret = R; + +err: + if (ret == NULL && out == NULL) { + BN_free(R); + } + BN_CTX_end(ctx); + return ret; +} + +BIGNUM *BN_mod_inverse(BIGNUM *out, const BIGNUM *a, const BIGNUM *n, + BN_CTX *ctx) { + int no_inverse; + return BN_mod_inverse_ex(out, &no_inverse, a, n, ctx); +} + +/* BN_mod_inverse_no_branch is a special version of BN_mod_inverse. + * It does not contain branches that may leak sensitive information. */ +static BIGNUM *BN_mod_inverse_no_branch(BIGNUM *out, int *out_no_inverse, + const BIGNUM *a, const BIGNUM *n, + BN_CTX *ctx) { + BIGNUM *A, *B, *X, *Y, *M, *D, *T, *R = NULL; + BIGNUM local_A, local_B; + BIGNUM *pA, *pB; + BIGNUM *ret = NULL; + int sign; + + *out_no_inverse = 0; + + BN_CTX_start(ctx); + A = BN_CTX_get(ctx); + B = BN_CTX_get(ctx); + X = BN_CTX_get(ctx); + D = BN_CTX_get(ctx); + M = BN_CTX_get(ctx); + Y = BN_CTX_get(ctx); + T = BN_CTX_get(ctx); + if (T == NULL) { + goto err; + } + + if (out == NULL) { + R = BN_new(); + } else { + R = out; + } + if (R == NULL) { + goto err; + } + + BN_zero(Y); + if (!BN_one(X) || BN_copy(B, a) == NULL || BN_copy(A, n) == NULL) { + goto err; + } + A->neg = 0; + + if (B->neg || (BN_ucmp(B, A) >= 0)) { + /* Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked, + * BN_div_no_branch will be called eventually. + */ + pB = &local_B; + BN_with_flags(pB, B, BN_FLG_CONSTTIME); + if (!BN_nnmod(B, pB, A, ctx)) { + goto err; + } + } + sign = -1; + /* From B = a mod |n|, A = |n| it follows that + * + * 0 <= B < A, + * -sign*X*a == B (mod |n|), + * sign*Y*a == A (mod |n|). + */ + + while (!BN_is_zero(B)) { + BIGNUM *tmp; + + /* + * 0 < B < A, + * (*) -sign*X*a == B (mod |n|), + * sign*Y*a == A (mod |n|) + */ + + /* Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked, + * BN_div_no_branch will be called eventually. + */ + pA = &local_A; + BN_with_flags(pA, A, BN_FLG_CONSTTIME); + + /* (D, M) := (A/B, A%B) ... */ + if (!BN_div(D, M, pA, B, ctx)) { + goto err; + } + + /* Now + * A = D*B + M; + * thus we have + * (**) sign*Y*a == D*B + M (mod |n|). + */ + + tmp = A; /* keep the BIGNUM object, the value does not matter */ + + /* (A, B) := (B, A mod B) ... */ + A = B; + B = M; + /* ... so we have 0 <= B < A again */ + + /* Since the former M is now B and the former B is now A, + * (**) translates into + * sign*Y*a == D*A + B (mod |n|), + * i.e. + * sign*Y*a - D*A == B (mod |n|). + * Similarly, (*) translates into + * -sign*X*a == A (mod |n|). + * + * Thus, + * sign*Y*a + D*sign*X*a == B (mod |n|), + * i.e. + * sign*(Y + D*X)*a == B (mod |n|). + * + * So if we set (X, Y, sign) := (Y + D*X, X, -sign), we arrive back at + * -sign*X*a == B (mod |n|), + * sign*Y*a == A (mod |n|). + * Note that X and Y stay non-negative all the time. + */ + + if (!BN_mul(tmp, D, X, ctx)) { + goto err; + } + if (!BN_add(tmp, tmp, Y)) { + goto err; + } + + M = Y; /* keep the BIGNUM object, the value does not matter */ + Y = X; + X = tmp; + sign = -sign; + } + + if (!BN_is_one(A)) { + *out_no_inverse = 1; + OPENSSL_PUT_ERROR(BN, BN_R_NO_INVERSE); + goto err; + } + + /* + * The while loop (Euclid's algorithm) ends when + * A == gcd(a,n); + * we have + * sign*Y*a == A (mod |n|), + * where Y is non-negative. + */ + + if (sign < 0) { + if (!BN_sub(Y, n, Y)) { + goto err; + } + } + /* Now Y*a == A (mod |n|). */ + + /* Y*a == 1 (mod |n|) */ + if (!Y->neg && BN_ucmp(Y, n) < 0) { + if (!BN_copy(R, Y)) { + goto err; + } + } else { + if (!BN_nnmod(R, Y, n, ctx)) { + goto err; + } + } + + ret = R; + +err: + if (ret == NULL && out == NULL) { + BN_free(R); + } + + BN_CTX_end(ctx); + return ret; +} diff --git a/external/boringssl/crypto/bn/generic.c b/external/boringssl/crypto/bn/generic.c new file mode 100644 index 0000000000..f552d99f89 --- /dev/null +++ b/external/boringssl/crypto/bn/generic.c @@ -0,0 +1,703 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include "internal.h" + + +/* This file has two other implementations: x86 assembly language in + * asm/bn-586.pl and x86_64 inline assembly in asm/x86_64-gcc.c. */ +#if defined(OPENSSL_NO_ASM) || \ + !(defined(OPENSSL_X86) || (defined(OPENSSL_X86_64) && defined(__GNUC__))) + +#ifdef BN_ULLONG +#define mul_add(r, a, w, c) \ + { \ + BN_ULLONG t; \ + t = (BN_ULLONG)w * (a) + (r) + (c); \ + (r) = Lw(t); \ + (c) = Hw(t); \ + } + +#define mul(r, a, w, c) \ + { \ + BN_ULLONG t; \ + t = (BN_ULLONG)w * (a) + (c); \ + (r) = Lw(t); \ + (c) = Hw(t); \ + } + +#define sqr(r0, r1, a) \ + { \ + BN_ULLONG t; \ + t = (BN_ULLONG)(a) * (a); \ + (r0) = Lw(t); \ + (r1) = Hw(t); \ + } + +#else + +#define mul_add(r, a, w, c) \ + { \ + BN_ULONG high, low, ret, tmp = (a); \ + ret = (r); \ + BN_UMULT_LOHI(low, high, w, tmp); \ + ret += (c); \ + (c) = (ret < (c)) ? 1 : 0; \ + (c) += high; \ + ret += low; \ + (c) += (ret < low) ? 1 : 0; \ + (r) = ret; \ + } + +#define mul(r, a, w, c) \ + { \ + BN_ULONG high, low, ret, ta = (a); \ + BN_UMULT_LOHI(low, high, w, ta); \ + ret = low + (c); \ + (c) = high; \ + (c) += (ret < low) ? 1 : 0; \ + (r) = ret; \ + } + +#define sqr(r0, r1, a) \ + { \ + BN_ULONG tmp = (a); \ + BN_UMULT_LOHI(r0, r1, tmp, tmp); \ + } + +#endif /* !BN_ULLONG */ + +BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num, + BN_ULONG w) { + BN_ULONG c1 = 0; + + assert(num >= 0); + if (num <= 0) { + return c1; + } + + while (num & ~3) { + mul_add(rp[0], ap[0], w, c1); + mul_add(rp[1], ap[1], w, c1); + mul_add(rp[2], ap[2], w, c1); + mul_add(rp[3], ap[3], w, c1); + ap += 4; + rp += 4; + num -= 4; + } + + while (num) { + mul_add(rp[0], ap[0], w, c1); + ap++; + rp++; + num--; + } + + return c1; +} + +BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w) { + BN_ULONG c1 = 0; + + assert(num >= 0); + if (num <= 0) { + return c1; + } + + while (num & ~3) { + mul(rp[0], ap[0], w, c1); + mul(rp[1], ap[1], w, c1); + mul(rp[2], ap[2], w, c1); + mul(rp[3], ap[3], w, c1); + ap += 4; + rp += 4; + num -= 4; + } + while (num) { + mul(rp[0], ap[0], w, c1); + ap++; + rp++; + num--; + } + return c1; +} + +void bn_sqr_words(BN_ULONG *r, const BN_ULONG *a, int n) { + assert(n >= 0); + if (n <= 0) { + return; + } + + while (n & ~3) { + sqr(r[0], r[1], a[0]); + sqr(r[2], r[3], a[1]); + sqr(r[4], r[5], a[2]); + sqr(r[6], r[7], a[3]); + a += 4; + r += 8; + n -= 4; + } + while (n) { + sqr(r[0], r[1], a[0]); + a++; + r += 2; + n--; + } +} + +#ifdef BN_ULLONG +BN_ULONG bn_add_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, + int n) { + BN_ULLONG ll = 0; + + assert(n >= 0); + if (n <= 0) { + return (BN_ULONG)0; + } + + while (n & ~3) { + ll += (BN_ULLONG)a[0] + b[0]; + r[0] = (BN_ULONG)ll & BN_MASK2; + ll >>= BN_BITS2; + ll += (BN_ULLONG)a[1] + b[1]; + r[1] = (BN_ULONG)ll & BN_MASK2; + ll >>= BN_BITS2; + ll += (BN_ULLONG)a[2] + b[2]; + r[2] = (BN_ULONG)ll & BN_MASK2; + ll >>= BN_BITS2; + ll += (BN_ULLONG)a[3] + b[3]; + r[3] = (BN_ULONG)ll & BN_MASK2; + ll >>= BN_BITS2; + a += 4; + b += 4; + r += 4; + n -= 4; + } + while (n) { + ll += (BN_ULLONG)a[0] + b[0]; + r[0] = (BN_ULONG)ll & BN_MASK2; + ll >>= BN_BITS2; + a++; + b++; + r++; + n--; + } + return (BN_ULONG)ll; +} + +#else /* !BN_ULLONG */ + +BN_ULONG bn_add_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, + int n) { + BN_ULONG c, l, t; + + assert(n >= 0); + if (n <= 0) { + return (BN_ULONG)0; + } + + c = 0; + while (n & ~3) { + t = a[0]; + t = (t + c) & BN_MASK2; + c = (t < c); + l = (t + b[0]) & BN_MASK2; + c += (l < t); + r[0] = l; + t = a[1]; + t = (t + c) & BN_MASK2; + c = (t < c); + l = (t + b[1]) & BN_MASK2; + c += (l < t); + r[1] = l; + t = a[2]; + t = (t + c) & BN_MASK2; + c = (t < c); + l = (t + b[2]) & BN_MASK2; + c += (l < t); + r[2] = l; + t = a[3]; + t = (t + c) & BN_MASK2; + c = (t < c); + l = (t + b[3]) & BN_MASK2; + c += (l < t); + r[3] = l; + a += 4; + b += 4; + r += 4; + n -= 4; + } + while (n) { + t = a[0]; + t = (t + c) & BN_MASK2; + c = (t < c); + l = (t + b[0]) & BN_MASK2; + c += (l < t); + r[0] = l; + a++; + b++; + r++; + n--; + } + return (BN_ULONG)c; +} + +#endif /* !BN_ULLONG */ + +BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, + int n) { + BN_ULONG t1, t2; + int c = 0; + + assert(n >= 0); + if (n <= 0) { + return (BN_ULONG)0; + } + + while (n & ~3) { + t1 = a[0]; + t2 = b[0]; + r[0] = (t1 - t2 - c) & BN_MASK2; + if (t1 != t2) { + c = (t1 < t2); + } + t1 = a[1]; + t2 = b[1]; + r[1] = (t1 - t2 - c) & BN_MASK2; + if (t1 != t2) { + c = (t1 < t2); + } + t1 = a[2]; + t2 = b[2]; + r[2] = (t1 - t2 - c) & BN_MASK2; + if (t1 != t2) { + c = (t1 < t2); + } + t1 = a[3]; + t2 = b[3]; + r[3] = (t1 - t2 - c) & BN_MASK2; + if (t1 != t2) { + c = (t1 < t2); + } + a += 4; + b += 4; + r += 4; + n -= 4; + } + while (n) { + t1 = a[0]; + t2 = b[0]; + r[0] = (t1 - t2 - c) & BN_MASK2; + if (t1 != t2) { + c = (t1 < t2); + } + a++; + b++; + r++; + n--; + } + return c; +} + +/* mul_add_c(a,b,c0,c1,c2) -- c+=a*b for three word number c=(c2,c1,c0) */ +/* mul_add_c2(a,b,c0,c1,c2) -- c+=2*a*b for three word number c=(c2,c1,c0) */ +/* sqr_add_c(a,i,c0,c1,c2) -- c+=a[i]^2 for three word number c=(c2,c1,c0) */ +/* sqr_add_c2(a,i,c0,c1,c2) -- c+=2*a[i]*a[j] for three word number c=(c2,c1,c0) */ + +#ifdef BN_ULLONG + +/* Keep in mind that additions to multiplication result can not overflow, + * because its high half cannot be all-ones. */ +#define mul_add_c(a, b, c0, c1, c2) \ + do { \ + BN_ULONG hi; \ + BN_ULLONG t = (BN_ULLONG)(a) * (b); \ + t += c0; /* no carry */ \ + c0 = (BN_ULONG)Lw(t); \ + hi = (BN_ULONG)Hw(t); \ + c1 = (c1 + hi) & BN_MASK2; \ + if (c1 < hi) \ + c2++; \ + } while (0) + +#define mul_add_c2(a, b, c0, c1, c2) \ + do { \ + BN_ULONG hi; \ + BN_ULLONG t = (BN_ULLONG)(a) * (b); \ + BN_ULLONG tt = t + c0; /* no carry */ \ + c0 = (BN_ULONG)Lw(tt); \ + hi = (BN_ULONG)Hw(tt); \ + c1 = (c1 + hi) & BN_MASK2; \ + if (c1 < hi) \ + c2++; \ + t += c0; /* no carry */ \ + c0 = (BN_ULONG)Lw(t); \ + hi = (BN_ULONG)Hw(t); \ + c1 = (c1 + hi) & BN_MASK2; \ + if (c1 < hi) \ + c2++; \ + } while (0) + +#define sqr_add_c(a, i, c0, c1, c2) \ + do { \ + BN_ULONG hi; \ + BN_ULLONG t = (BN_ULLONG)a[i] * a[i]; \ + t += c0; /* no carry */ \ + c0 = (BN_ULONG)Lw(t); \ + hi = (BN_ULONG)Hw(t); \ + c1 = (c1 + hi) & BN_MASK2; \ + if (c1 < hi) \ + c2++; \ + } while (0) + +#define sqr_add_c2(a, i, j, c0, c1, c2) mul_add_c2((a)[i], (a)[j], c0, c1, c2) + +#else + +/* Keep in mind that additions to hi can not overflow, because the high word of + * a multiplication result cannot be all-ones. */ +#define mul_add_c(a, b, c0, c1, c2) \ + do { \ + BN_ULONG ta = (a), tb = (b); \ + BN_ULONG lo, hi; \ + BN_UMULT_LOHI(lo, hi, ta, tb); \ + c0 += lo; \ + hi += (c0 < lo) ? 1 : 0; \ + c1 += hi; \ + c2 += (c1 < hi) ? 1 : 0; \ + } while (0) + +#define mul_add_c2(a, b, c0, c1, c2) \ + do { \ + BN_ULONG ta = (a), tb = (b); \ + BN_ULONG lo, hi, tt; \ + BN_UMULT_LOHI(lo, hi, ta, tb); \ + c0 += lo; \ + tt = hi + ((c0 < lo) ? 1 : 0); \ + c1 += tt; \ + c2 += (c1 < tt) ? 1 : 0; \ + c0 += lo; \ + hi += (c0 < lo) ? 1 : 0; \ + c1 += hi; \ + c2 += (c1 < hi) ? 1 : 0; \ + } while (0) + +#define sqr_add_c(a, i, c0, c1, c2) \ + do { \ + BN_ULONG ta = (a)[i]; \ + BN_ULONG lo, hi; \ + BN_UMULT_LOHI(lo, hi, ta, ta); \ + c0 += lo; \ + hi += (c0 < lo) ? 1 : 0; \ + c1 += hi; \ + c2 += (c1 < hi) ? 1 : 0; \ + } while (0) + +#define sqr_add_c2(a, i, j, c0, c1, c2) mul_add_c2((a)[i], (a)[j], c0, c1, c2) + +#endif /* !BN_ULLONG */ + +void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) { + BN_ULONG c1, c2, c3; + + c1 = 0; + c2 = 0; + c3 = 0; + mul_add_c(a[0], b[0], c1, c2, c3); + r[0] = c1; + c1 = 0; + mul_add_c(a[0], b[1], c2, c3, c1); + mul_add_c(a[1], b[0], c2, c3, c1); + r[1] = c2; + c2 = 0; + mul_add_c(a[2], b[0], c3, c1, c2); + mul_add_c(a[1], b[1], c3, c1, c2); + mul_add_c(a[0], b[2], c3, c1, c2); + r[2] = c3; + c3 = 0; + mul_add_c(a[0], b[3], c1, c2, c3); + mul_add_c(a[1], b[2], c1, c2, c3); + mul_add_c(a[2], b[1], c1, c2, c3); + mul_add_c(a[3], b[0], c1, c2, c3); + r[3] = c1; + c1 = 0; + mul_add_c(a[4], b[0], c2, c3, c1); + mul_add_c(a[3], b[1], c2, c3, c1); + mul_add_c(a[2], b[2], c2, c3, c1); + mul_add_c(a[1], b[3], c2, c3, c1); + mul_add_c(a[0], b[4], c2, c3, c1); + r[4] = c2; + c2 = 0; + mul_add_c(a[0], b[5], c3, c1, c2); + mul_add_c(a[1], b[4], c3, c1, c2); + mul_add_c(a[2], b[3], c3, c1, c2); + mul_add_c(a[3], b[2], c3, c1, c2); + mul_add_c(a[4], b[1], c3, c1, c2); + mul_add_c(a[5], b[0], c3, c1, c2); + r[5] = c3; + c3 = 0; + mul_add_c(a[6], b[0], c1, c2, c3); + mul_add_c(a[5], b[1], c1, c2, c3); + mul_add_c(a[4], b[2], c1, c2, c3); + mul_add_c(a[3], b[3], c1, c2, c3); + mul_add_c(a[2], b[4], c1, c2, c3); + mul_add_c(a[1], b[5], c1, c2, c3); + mul_add_c(a[0], b[6], c1, c2, c3); + r[6] = c1; + c1 = 0; + mul_add_c(a[0], b[7], c2, c3, c1); + mul_add_c(a[1], b[6], c2, c3, c1); + mul_add_c(a[2], b[5], c2, c3, c1); + mul_add_c(a[3], b[4], c2, c3, c1); + mul_add_c(a[4], b[3], c2, c3, c1); + mul_add_c(a[5], b[2], c2, c3, c1); + mul_add_c(a[6], b[1], c2, c3, c1); + mul_add_c(a[7], b[0], c2, c3, c1); + r[7] = c2; + c2 = 0; + mul_add_c(a[7], b[1], c3, c1, c2); + mul_add_c(a[6], b[2], c3, c1, c2); + mul_add_c(a[5], b[3], c3, c1, c2); + mul_add_c(a[4], b[4], c3, c1, c2); + mul_add_c(a[3], b[5], c3, c1, c2); + mul_add_c(a[2], b[6], c3, c1, c2); + mul_add_c(a[1], b[7], c3, c1, c2); + r[8] = c3; + c3 = 0; + mul_add_c(a[2], b[7], c1, c2, c3); + mul_add_c(a[3], b[6], c1, c2, c3); + mul_add_c(a[4], b[5], c1, c2, c3); + mul_add_c(a[5], b[4], c1, c2, c3); + mul_add_c(a[6], b[3], c1, c2, c3); + mul_add_c(a[7], b[2], c1, c2, c3); + r[9] = c1; + c1 = 0; + mul_add_c(a[7], b[3], c2, c3, c1); + mul_add_c(a[6], b[4], c2, c3, c1); + mul_add_c(a[5], b[5], c2, c3, c1); + mul_add_c(a[4], b[6], c2, c3, c1); + mul_add_c(a[3], b[7], c2, c3, c1); + r[10] = c2; + c2 = 0; + mul_add_c(a[4], b[7], c3, c1, c2); + mul_add_c(a[5], b[6], c3, c1, c2); + mul_add_c(a[6], b[5], c3, c1, c2); + mul_add_c(a[7], b[4], c3, c1, c2); + r[11] = c3; + c3 = 0; + mul_add_c(a[7], b[5], c1, c2, c3); + mul_add_c(a[6], b[6], c1, c2, c3); + mul_add_c(a[5], b[7], c1, c2, c3); + r[12] = c1; + c1 = 0; + mul_add_c(a[6], b[7], c2, c3, c1); + mul_add_c(a[7], b[6], c2, c3, c1); + r[13] = c2; + c2 = 0; + mul_add_c(a[7], b[7], c3, c1, c2); + r[14] = c3; + r[15] = c1; +} + +void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) { + BN_ULONG c1, c2, c3; + + c1 = 0; + c2 = 0; + c3 = 0; + mul_add_c(a[0], b[0], c1, c2, c3); + r[0] = c1; + c1 = 0; + mul_add_c(a[0], b[1], c2, c3, c1); + mul_add_c(a[1], b[0], c2, c3, c1); + r[1] = c2; + c2 = 0; + mul_add_c(a[2], b[0], c3, c1, c2); + mul_add_c(a[1], b[1], c3, c1, c2); + mul_add_c(a[0], b[2], c3, c1, c2); + r[2] = c3; + c3 = 0; + mul_add_c(a[0], b[3], c1, c2, c3); + mul_add_c(a[1], b[2], c1, c2, c3); + mul_add_c(a[2], b[1], c1, c2, c3); + mul_add_c(a[3], b[0], c1, c2, c3); + r[3] = c1; + c1 = 0; + mul_add_c(a[3], b[1], c2, c3, c1); + mul_add_c(a[2], b[2], c2, c3, c1); + mul_add_c(a[1], b[3], c2, c3, c1); + r[4] = c2; + c2 = 0; + mul_add_c(a[2], b[3], c3, c1, c2); + mul_add_c(a[3], b[2], c3, c1, c2); + r[5] = c3; + c3 = 0; + mul_add_c(a[3], b[3], c1, c2, c3); + r[6] = c1; + r[7] = c2; +} + +void bn_sqr_comba8(BN_ULONG *r, const BN_ULONG *a) { + BN_ULONG c1, c2, c3; + + c1 = 0; + c2 = 0; + c3 = 0; + sqr_add_c(a, 0, c1, c2, c3); + r[0] = c1; + c1 = 0; + sqr_add_c2(a, 1, 0, c2, c3, c1); + r[1] = c2; + c2 = 0; + sqr_add_c(a, 1, c3, c1, c2); + sqr_add_c2(a, 2, 0, c3, c1, c2); + r[2] = c3; + c3 = 0; + sqr_add_c2(a, 3, 0, c1, c2, c3); + sqr_add_c2(a, 2, 1, c1, c2, c3); + r[3] = c1; + c1 = 0; + sqr_add_c(a, 2, c2, c3, c1); + sqr_add_c2(a, 3, 1, c2, c3, c1); + sqr_add_c2(a, 4, 0, c2, c3, c1); + r[4] = c2; + c2 = 0; + sqr_add_c2(a, 5, 0, c3, c1, c2); + sqr_add_c2(a, 4, 1, c3, c1, c2); + sqr_add_c2(a, 3, 2, c3, c1, c2); + r[5] = c3; + c3 = 0; + sqr_add_c(a, 3, c1, c2, c3); + sqr_add_c2(a, 4, 2, c1, c2, c3); + sqr_add_c2(a, 5, 1, c1, c2, c3); + sqr_add_c2(a, 6, 0, c1, c2, c3); + r[6] = c1; + c1 = 0; + sqr_add_c2(a, 7, 0, c2, c3, c1); + sqr_add_c2(a, 6, 1, c2, c3, c1); + sqr_add_c2(a, 5, 2, c2, c3, c1); + sqr_add_c2(a, 4, 3, c2, c3, c1); + r[7] = c2; + c2 = 0; + sqr_add_c(a, 4, c3, c1, c2); + sqr_add_c2(a, 5, 3, c3, c1, c2); + sqr_add_c2(a, 6, 2, c3, c1, c2); + sqr_add_c2(a, 7, 1, c3, c1, c2); + r[8] = c3; + c3 = 0; + sqr_add_c2(a, 7, 2, c1, c2, c3); + sqr_add_c2(a, 6, 3, c1, c2, c3); + sqr_add_c2(a, 5, 4, c1, c2, c3); + r[9] = c1; + c1 = 0; + sqr_add_c(a, 5, c2, c3, c1); + sqr_add_c2(a, 6, 4, c2, c3, c1); + sqr_add_c2(a, 7, 3, c2, c3, c1); + r[10] = c2; + c2 = 0; + sqr_add_c2(a, 7, 4, c3, c1, c2); + sqr_add_c2(a, 6, 5, c3, c1, c2); + r[11] = c3; + c3 = 0; + sqr_add_c(a, 6, c1, c2, c3); + sqr_add_c2(a, 7, 5, c1, c2, c3); + r[12] = c1; + c1 = 0; + sqr_add_c2(a, 7, 6, c2, c3, c1); + r[13] = c2; + c2 = 0; + sqr_add_c(a, 7, c3, c1, c2); + r[14] = c3; + r[15] = c1; +} + +void bn_sqr_comba4(BN_ULONG *r, const BN_ULONG *a) { + BN_ULONG c1, c2, c3; + + c1 = 0; + c2 = 0; + c3 = 0; + sqr_add_c(a, 0, c1, c2, c3); + r[0] = c1; + c1 = 0; + sqr_add_c2(a, 1, 0, c2, c3, c1); + r[1] = c2; + c2 = 0; + sqr_add_c(a, 1, c3, c1, c2); + sqr_add_c2(a, 2, 0, c3, c1, c2); + r[2] = c3; + c3 = 0; + sqr_add_c2(a, 3, 0, c1, c2, c3); + sqr_add_c2(a, 2, 1, c1, c2, c3); + r[3] = c1; + c1 = 0; + sqr_add_c(a, 2, c2, c3, c1); + sqr_add_c2(a, 3, 1, c2, c3, c1); + r[4] = c2; + c2 = 0; + sqr_add_c2(a, 3, 2, c3, c1, c2); + r[5] = c3; + c3 = 0; + sqr_add_c(a, 3, c1, c2, c3); + r[6] = c1; + r[7] = c2; +} + +#endif diff --git a/external/boringssl/crypto/bn/internal.h b/external/boringssl/crypto/bn/internal.h new file mode 100644 index 0000000000..8b1c8660fd --- /dev/null +++ b/external/boringssl/crypto/bn/internal.h @@ -0,0 +1,237 @@ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * + * Portions of the attached software ("Contribution") are developed by + * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. + * + * The Contribution is licensed pursuant to the Eric Young open source + * license provided above. + * + * The binary polynomial arithmetic software is originally written by + * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems + * Laboratories. */ + +#ifndef OPENSSL_HEADER_BN_INTERNAL_H +#define OPENSSL_HEADER_BN_INTERNAL_H + +#include + +#if defined(OPENSSL_X86_64) && defined(_MSC_VER) +OPENSSL_MSVC_PRAGMA(warning(push, 3)) +#include +OPENSSL_MSVC_PRAGMA(warning(pop)) +#pragma intrinsic(__umulh, _umul128) +#endif + +#include "../internal.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/* bn_expand acts the same as |bn_wexpand|, but takes a number of bits rather + * than a number of words. */ +BIGNUM *bn_expand(BIGNUM *bn, size_t bits); + +#if defined(OPENSSL_64_BIT) + +#if !defined(_MSC_VER) +/* MSVC doesn't support two-word integers on 64-bit. */ +#define BN_ULLONG uint128_t +#endif + +#define BN_BITS2 64 +#define BN_BYTES 8 +#define BN_BITS4 32 +#define BN_MASK2 (0xffffffffffffffffUL) +#define BN_MASK2l (0xffffffffUL) +#define BN_MASK2h (0xffffffff00000000UL) +#define BN_MASK2h1 (0xffffffff80000000UL) +#define BN_TBIT (0x8000000000000000UL) +#define BN_DEC_CONV (10000000000000000000UL) +#define BN_DEC_NUM 19 +#define TOBN(hi, lo) ((BN_ULONG)hi << 32 | lo) + +#elif defined(OPENSSL_32_BIT) + +#define BN_ULLONG uint64_t +#define BN_BITS2 32 +#define BN_BYTES 4 +#define BN_BITS4 16 +#define BN_MASK2 (0xffffffffUL) +#define BN_MASK2l (0xffffUL) +#define BN_MASK2h1 (0xffff8000UL) +#define BN_MASK2h (0xffff0000UL) +#define BN_TBIT (0x80000000UL) +#define BN_DEC_CONV (1000000000UL) +#define BN_DEC_NUM 9 +#define TOBN(hi, lo) lo, hi + +#else +#error "Must define either OPENSSL_32_BIT or OPENSSL_64_BIT" +#endif + + +#define STATIC_BIGNUM(x) \ + { \ + (BN_ULONG *)x, sizeof(x) / sizeof(BN_ULONG), \ + sizeof(x) / sizeof(BN_ULONG), 0, BN_FLG_STATIC_DATA \ + } + +#if defined(BN_ULLONG) +#define Lw(t) (((BN_ULONG)(t))&BN_MASK2) +#define Hw(t) (((BN_ULONG)((t)>>BN_BITS2))&BN_MASK2) +#endif + + +/* bn_set_words sets |bn| to the value encoded in the |num| words in |words|, + * least significant word first. */ +int bn_set_words(BIGNUM *bn, const BN_ULONG *words, size_t num); + +BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w); +BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w); +void bn_sqr_words(BN_ULONG *rp, const BN_ULONG *ap, int num); +BN_ULONG bn_add_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,int num); +BN_ULONG bn_sub_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,int num); + +void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b); +void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b); +void bn_sqr_comba8(BN_ULONG *r, const BN_ULONG *a); +void bn_sqr_comba4(BN_ULONG *r, const BN_ULONG *a); + +/* bn_cmp_words returns a value less than, equal to or greater than zero if + * the, length |n|, array |a| is less than, equal to or greater than |b|. */ +int bn_cmp_words(const BN_ULONG *a, const BN_ULONG *b, int n); + +/* bn_cmp_words returns a value less than, equal to or greater than zero if the + * array |a| is less than, equal to or greater than |b|. The arrays can be of + * different lengths: |cl| gives the minimum of the two lengths and |dl| gives + * the length of |a| minus the length of |b|. */ +int bn_cmp_part_words(const BN_ULONG *a, const BN_ULONG *b, int cl, int dl); + +int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, + const BN_ULONG *np, const BN_ULONG *n0, int num); + +#if defined(OPENSSL_X86_64) && defined(_MSC_VER) +#define BN_UMULT_LOHI(low, high, a, b) ((low) = _umul128((a), (b), &(high))) +#endif + +#if !defined(BN_ULLONG) && !defined(BN_UMULT_LOHI) +#error "Either BN_ULLONG or BN_UMULT_LOHI must be defined on every platform." +#endif + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_BN_INTERNAL_H */ diff --git a/external/boringssl/crypto/bn/kronecker.c b/external/boringssl/crypto/bn/kronecker.c new file mode 100644 index 0000000000..23ef79afa5 --- /dev/null +++ b/external/boringssl/crypto/bn/kronecker.c @@ -0,0 +1,175 @@ +/* ==================================================================== + * Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include "internal.h" + + +/* least significant word */ +#define BN_lsw(n) (((n)->top == 0) ? (BN_ULONG) 0 : (n)->d[0]) + +/* Returns -2 for errors because both -1 and 0 are valid results. */ +int BN_kronecker(const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) { + int i; + int ret = -2; + BIGNUM *A, *B, *tmp; + /* In 'tab', only odd-indexed entries are relevant: + * For any odd BIGNUM n, + * tab[BN_lsw(n) & 7] + * is $(-1)^{(n^2-1)/8}$ (using TeX notation). + * Note that the sign of n does not matter. */ + static const int tab[8] = {0, 1, 0, -1, 0, -1, 0, 1}; + + BN_CTX_start(ctx); + A = BN_CTX_get(ctx); + B = BN_CTX_get(ctx); + if (B == NULL) { + goto end; + } + + if (!BN_copy(A, a) || + !BN_copy(B, b)) { + goto end; + } + + /* Kronecker symbol, imlemented according to Henri Cohen, + * "A Course in Computational Algebraic Number Theory" + * (algorithm 1.4.10). */ + + /* Cohen's step 1: */ + + if (BN_is_zero(B)) { + ret = BN_abs_is_word(A, 1); + goto end; + } + + /* Cohen's step 2: */ + + if (!BN_is_odd(A) && !BN_is_odd(B)) { + ret = 0; + goto end; + } + + /* now B is non-zero */ + i = 0; + while (!BN_is_bit_set(B, i)) { + i++; + } + if (!BN_rshift(B, B, i)) { + goto end; + } + if (i & 1) { + /* i is odd */ + /* (thus B was even, thus A must be odd!) */ + + /* set 'ret' to $(-1)^{(A^2-1)/8}$ */ + ret = tab[BN_lsw(A) & 7]; + } else { + /* i is even */ + ret = 1; + } + + if (B->neg) { + B->neg = 0; + if (A->neg) { + ret = -ret; + } + } + + /* now B is positive and odd, so what remains to be done is to compute the + * Jacobi symbol (A/B) and multiply it by 'ret' */ + + while (1) { + /* Cohen's step 3: */ + + /* B is positive and odd */ + if (BN_is_zero(A)) { + ret = BN_is_one(B) ? ret : 0; + goto end; + } + + /* now A is non-zero */ + i = 0; + while (!BN_is_bit_set(A, i)) { + i++; + } + if (!BN_rshift(A, A, i)) { + goto end; + } + if (i & 1) { + /* i is odd */ + /* multiply 'ret' by $(-1)^{(B^2-1)/8}$ */ + ret = ret * tab[BN_lsw(B) & 7]; + } + + /* Cohen's step 4: */ + /* multiply 'ret' by $(-1)^{(A-1)(B-1)/4}$ */ + if ((A->neg ? ~BN_lsw(A) : BN_lsw(A)) & BN_lsw(B) & 2) { + ret = -ret; + } + + /* (A, B) := (B mod |A|, |A|) */ + if (!BN_nnmod(B, B, A, ctx)) { + ret = -2; + goto end; + } + tmp = A; + A = B; + B = tmp; + tmp->neg = 0; + } + +end: + BN_CTX_end(ctx); + return ret; +} diff --git a/external/boringssl/crypto/bn/montgomery.c b/external/boringssl/crypto/bn/montgomery.c new file mode 100644 index 0000000000..7c3b420cb8 --- /dev/null +++ b/external/boringssl/crypto/bn/montgomery.c @@ -0,0 +1,480 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include + +#include +#include +#include + +#include "internal.h" +#include "../internal.h" + + +#if !defined(OPENSSL_NO_ASM) && \ + (defined(OPENSSL_X86) || defined(OPENSSL_X86_64) || \ + defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)) +#define OPENSSL_BN_ASM_MONT +#endif + +BN_MONT_CTX *BN_MONT_CTX_new(void) { + BN_MONT_CTX *ret = OPENSSL_malloc(sizeof(BN_MONT_CTX)); + + if (ret == NULL) { + return NULL; + } + + memset(ret, 0, sizeof(BN_MONT_CTX)); + BN_init(&ret->RR); + BN_init(&ret->N); + + return ret; +} + +void BN_MONT_CTX_free(BN_MONT_CTX *mont) { + if (mont == NULL) { + return; + } + + BN_free(&mont->RR); + BN_free(&mont->N); + OPENSSL_free(mont); +} + +BN_MONT_CTX *BN_MONT_CTX_copy(BN_MONT_CTX *to, const BN_MONT_CTX *from) { + if (to == from) { + return to; + } + + if (!BN_copy(&to->RR, &from->RR) || + !BN_copy(&to->N, &from->N)) { + return NULL; + } + to->n0[0] = from->n0[0]; + to->n0[1] = from->n0[1]; + return to; +} + +int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx) { + int ret = 0; + BIGNUM *Ri, *R; + BIGNUM tmod; + BN_ULONG buf[2]; + + if (BN_is_zero(mod)) { + OPENSSL_PUT_ERROR(BN, BN_R_DIV_BY_ZERO); + return 0; + } + + BN_CTX_start(ctx); + Ri = BN_CTX_get(ctx); + if (Ri == NULL) { + goto err; + } + R = &mont->RR; /* grab RR as a temp */ + if (!BN_copy(&mont->N, mod)) { + goto err; /* Set N */ + } + mont->N.neg = 0; + + BN_init(&tmod); + tmod.d = buf; + tmod.dmax = 2; + tmod.neg = 0; + +#if defined(OPENSSL_BN_ASM_MONT) && (BN_BITS2 <= 32) + /* Only certain BN_BITS2<=32 platforms actually make use of + * n0[1], and we could use the #else case (with a shorter R + * value) for the others. However, currently only the assembler + * files do know which is which. */ + + BN_zero(R); + if (!BN_set_bit(R, 2 * BN_BITS2)) { + goto err; + } + + tmod.top = 0; + if ((buf[0] = mod->d[0])) { + tmod.top = 1; + } + if ((buf[1] = mod->top > 1 ? mod->d[1] : 0)) { + tmod.top = 2; + } + + if (BN_mod_inverse(Ri, R, &tmod, ctx) == NULL) { + goto err; + } + if (!BN_lshift(Ri, Ri, 2 * BN_BITS2)) { + goto err; /* R*Ri */ + } + if (!BN_is_zero(Ri)) { + if (!BN_sub_word(Ri, 1)) { + goto err; + } + } else { + /* if N mod word size == 1 */ + if (bn_expand(Ri, (int)sizeof(BN_ULONG) * 2) == NULL) { + goto err; + } + /* Ri-- (mod double word size) */ + Ri->neg = 0; + Ri->d[0] = BN_MASK2; + Ri->d[1] = BN_MASK2; + Ri->top = 2; + } + + if (!BN_div(Ri, NULL, Ri, &tmod, ctx)) { + goto err; + } + /* Ni = (R*Ri-1)/N, + * keep only couple of least significant words: */ + mont->n0[0] = (Ri->top > 0) ? Ri->d[0] : 0; + mont->n0[1] = (Ri->top > 1) ? Ri->d[1] : 0; +#else + BN_zero(R); + if (!BN_set_bit(R, BN_BITS2)) { + goto err; /* R */ + } + + buf[0] = mod->d[0]; /* tmod = N mod word size */ + buf[1] = 0; + tmod.top = buf[0] != 0 ? 1 : 0; + /* Ri = R^-1 mod N*/ + if (BN_mod_inverse(Ri, R, &tmod, ctx) == NULL) { + goto err; + } + if (!BN_lshift(Ri, Ri, BN_BITS2)) { + goto err; /* R*Ri */ + } + if (!BN_is_zero(Ri)) { + if (!BN_sub_word(Ri, 1)) { + goto err; + } + } else { + /* if N mod word size == 1 */ + if (!BN_set_word(Ri, BN_MASK2)) { + goto err; /* Ri-- (mod word size) */ + } + } + if (!BN_div(Ri, NULL, Ri, &tmod, ctx)) { + goto err; + } + /* Ni = (R*Ri-1)/N, + * keep only least significant word: */ + mont->n0[0] = (Ri->top > 0) ? Ri->d[0] : 0; + mont->n0[1] = 0; +#endif + + /* RR = (2^ri)^2 == 2^(ri*2) == 1 << (ri*2), which has its (ri*2)th bit set. */ + int ri = (BN_num_bits(mod) + (BN_BITS2 - 1)) / BN_BITS2 * BN_BITS2; + BN_zero(&(mont->RR)); + if (!BN_set_bit(&(mont->RR), ri * 2)) { + goto err; + } + if (!BN_mod(&(mont->RR), &(mont->RR), &(mont->N), ctx)) { + goto err; + } + + ret = 1; + +err: + BN_CTX_end(ctx); + return ret; +} + +int BN_MONT_CTX_set_locked(BN_MONT_CTX **pmont, CRYPTO_MUTEX *lock, + const BIGNUM *mod, BN_CTX *bn_ctx) { + CRYPTO_MUTEX_lock_read(lock); + BN_MONT_CTX *ctx = *pmont; + CRYPTO_MUTEX_unlock_read(lock); + + if (ctx) { + return 1; + } + + CRYPTO_MUTEX_lock_write(lock); + ctx = *pmont; + if (ctx) { + goto out; + } + + ctx = BN_MONT_CTX_new(); + if (ctx == NULL) { + goto out; + } + if (!BN_MONT_CTX_set(ctx, mod, bn_ctx)) { + BN_MONT_CTX_free(ctx); + ctx = NULL; + goto out; + } + *pmont = ctx; + +out: + CRYPTO_MUTEX_unlock_write(lock); + return ctx != NULL; +} + +int BN_to_montgomery(BIGNUM *ret, const BIGNUM *a, const BN_MONT_CTX *mont, + BN_CTX *ctx) { + return BN_mod_mul_montgomery(ret, a, &mont->RR, mont, ctx); +} + +static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, + const BN_MONT_CTX *mont) { + BN_ULONG *ap, *np, *rp, n0, v, carry; + int nl, max, i; + + const BIGNUM *n = &mont->N; + nl = n->top; + if (nl == 0) { + ret->top = 0; + return 1; + } + + max = (2 * nl); /* carry is stored separately */ + if (bn_wexpand(r, max) == NULL) { + return 0; + } + + r->neg ^= n->neg; + np = n->d; + rp = r->d; + + /* clear the top words of T */ + if (max > r->top) { + memset(&rp[r->top], 0, (max - r->top) * sizeof(BN_ULONG)); + } + + r->top = max; + n0 = mont->n0[0]; + + for (carry = 0, i = 0; i < nl; i++, rp++) { + v = bn_mul_add_words(rp, np, nl, (rp[0] * n0) & BN_MASK2); + v = (v + carry + rp[nl]) & BN_MASK2; + carry |= (v != rp[nl]); + carry &= (v <= rp[nl]); + rp[nl] = v; + } + + if (bn_wexpand(ret, nl) == NULL) { + return 0; + } + ret->top = nl; + ret->neg = r->neg; + + rp = ret->d; + ap = &(r->d[nl]); + + { + BN_ULONG *nrp; + uintptr_t m; + + v = bn_sub_words(rp, ap, np, nl) - carry; + /* if subtraction result is real, then trick unconditional memcpy below to + * perform in-place "refresh" instead of actual copy. */ + m = (0u - (uintptr_t)v); + nrp = (BN_ULONG *)(((uintptr_t)rp & ~m) | ((uintptr_t)ap & m)); + + for (i = 0, nl -= 4; i < nl; i += 4) { + BN_ULONG t1, t2, t3, t4; + + t1 = nrp[i + 0]; + t2 = nrp[i + 1]; + t3 = nrp[i + 2]; + ap[i + 0] = 0; + t4 = nrp[i + 3]; + ap[i + 1] = 0; + rp[i + 0] = t1; + ap[i + 2] = 0; + rp[i + 1] = t2; + ap[i + 3] = 0; + rp[i + 2] = t3; + rp[i + 3] = t4; + } + + for (nl += 4; i < nl; i++) { + rp[i] = nrp[i], ap[i] = 0; + } + } + + bn_correct_top(r); + bn_correct_top(ret); + + return 1; +} + +int BN_from_montgomery(BIGNUM *r, const BIGNUM *a, const BN_MONT_CTX *mont, + BN_CTX *ctx) { + int ret = 0; + BIGNUM *t; + + BN_CTX_start(ctx); + t = BN_CTX_get(ctx); + if (t == NULL || + !BN_copy(t, a)) { + goto err; + } + + ret = BN_from_montgomery_word(r, t, mont); + +err: + BN_CTX_end(ctx); + + return ret; +} + +int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const BN_MONT_CTX *mont, BN_CTX *ctx) { + BIGNUM *tmp; + int ret = 0; + +#if defined(OPENSSL_BN_ASM_MONT) + int num = mont->N.top; + + if (num > 1 && a->top == num && b->top == num) { + if (bn_wexpand(r, num) == NULL) { + return 0; + } + if (bn_mul_mont(r->d, a->d, b->d, mont->N.d, mont->n0, num)) { + r->neg = a->neg ^ b->neg; + r->top = num; + bn_correct_top(r); + return 1; + } + } +#endif + + BN_CTX_start(ctx); + tmp = BN_CTX_get(ctx); + if (tmp == NULL) { + goto err; + } + + if (a == b) { + if (!BN_sqr(tmp, a, ctx)) { + goto err; + } + } else { + if (!BN_mul(tmp, a, b, ctx)) { + goto err; + } + } + + /* reduce from aRR to aR */ + if (!BN_from_montgomery_word(r, tmp, mont)) { + goto err; + } + + ret = 1; + +err: + BN_CTX_end(ctx); + return ret; +} diff --git a/external/boringssl/crypto/bn/mul.c b/external/boringssl/crypto/bn/mul.c new file mode 100644 index 0000000000..06e53ee0e6 --- /dev/null +++ b/external/boringssl/crypto/bn/mul.c @@ -0,0 +1,869 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +#include "internal.h" + + +#define BN_MUL_RECURSIVE_SIZE_NORMAL 16 +#define BN_SQR_RECURSIVE_SIZE_NORMAL BN_MUL_RECURSIVE_SIZE_NORMAL + + +static void bn_mul_normal(BN_ULONG *r, BN_ULONG *a, int na, BN_ULONG *b, + int nb) { + BN_ULONG *rr; + + if (na < nb) { + int itmp; + BN_ULONG *ltmp; + + itmp = na; + na = nb; + nb = itmp; + ltmp = a; + a = b; + b = ltmp; + } + rr = &(r[na]); + if (nb <= 0) { + (void)bn_mul_words(r, a, na, 0); + return; + } else { + rr[0] = bn_mul_words(r, a, na, b[0]); + } + + for (;;) { + if (--nb <= 0) { + return; + } + rr[1] = bn_mul_add_words(&(r[1]), a, na, b[1]); + if (--nb <= 0) { + return; + } + rr[2] = bn_mul_add_words(&(r[2]), a, na, b[2]); + if (--nb <= 0) { + return; + } + rr[3] = bn_mul_add_words(&(r[3]), a, na, b[3]); + if (--nb <= 0) { + return; + } + rr[4] = bn_mul_add_words(&(r[4]), a, na, b[4]); + rr += 4; + r += 4; + b += 4; + } +} + +#if !defined(OPENSSL_X86) || defined(OPENSSL_NO_ASM) +/* Here follows specialised variants of bn_add_words() and bn_sub_words(). They + * have the property performing operations on arrays of different sizes. The + * sizes of those arrays is expressed through cl, which is the common length ( + * basicall, min(len(a),len(b)) ), and dl, which is the delta between the two + * lengths, calculated as len(a)-len(b). All lengths are the number of + * BN_ULONGs... For the operations that require a result array as parameter, + * it must have the length cl+abs(dl). These functions should probably end up + * in bn_asm.c as soon as there are assembler counterparts for the systems that + * use assembler files. */ + +static BN_ULONG bn_sub_part_words(BN_ULONG *r, const BN_ULONG *a, + const BN_ULONG *b, int cl, int dl) { + BN_ULONG c, t; + + assert(cl >= 0); + c = bn_sub_words(r, a, b, cl); + + if (dl == 0) { + return c; + } + + r += cl; + a += cl; + b += cl; + + if (dl < 0) { + for (;;) { + t = b[0]; + r[0] = (0 - t - c) & BN_MASK2; + if (t != 0) { + c = 1; + } + if (++dl >= 0) { + break; + } + + t = b[1]; + r[1] = (0 - t - c) & BN_MASK2; + if (t != 0) { + c = 1; + } + if (++dl >= 0) { + break; + } + + t = b[2]; + r[2] = (0 - t - c) & BN_MASK2; + if (t != 0) { + c = 1; + } + if (++dl >= 0) { + break; + } + + t = b[3]; + r[3] = (0 - t - c) & BN_MASK2; + if (t != 0) { + c = 1; + } + if (++dl >= 0) { + break; + } + + b += 4; + r += 4; + } + } else { + int save_dl = dl; + while (c) { + t = a[0]; + r[0] = (t - c) & BN_MASK2; + if (t != 0) { + c = 0; + } + if (--dl <= 0) { + break; + } + + t = a[1]; + r[1] = (t - c) & BN_MASK2; + if (t != 0) { + c = 0; + } + if (--dl <= 0) { + break; + } + + t = a[2]; + r[2] = (t - c) & BN_MASK2; + if (t != 0) { + c = 0; + } + if (--dl <= 0) { + break; + } + + t = a[3]; + r[3] = (t - c) & BN_MASK2; + if (t != 0) { + c = 0; + } + if (--dl <= 0) { + break; + } + + save_dl = dl; + a += 4; + r += 4; + } + if (dl > 0) { + if (save_dl > dl) { + switch (save_dl - dl) { + case 1: + r[1] = a[1]; + if (--dl <= 0) { + break; + } + case 2: + r[2] = a[2]; + if (--dl <= 0) { + break; + } + case 3: + r[3] = a[3]; + if (--dl <= 0) { + break; + } + } + a += 4; + r += 4; + } + } + + if (dl > 0) { + for (;;) { + r[0] = a[0]; + if (--dl <= 0) { + break; + } + r[1] = a[1]; + if (--dl <= 0) { + break; + } + r[2] = a[2]; + if (--dl <= 0) { + break; + } + r[3] = a[3]; + if (--dl <= 0) { + break; + } + + a += 4; + r += 4; + } + } + } + + return c; +} +#else +/* On other platforms the function is defined in asm. */ +BN_ULONG bn_sub_part_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, + int cl, int dl); +#endif + +/* Karatsuba recursive multiplication algorithm + * (cf. Knuth, The Art of Computer Programming, Vol. 2) */ + +/* r is 2*n2 words in size, + * a and b are both n2 words in size. + * n2 must be a power of 2. + * We multiply and return the result. + * t must be 2*n2 words in size + * We calculate + * a[0]*b[0] + * a[0]*b[0]+a[1]*b[1]+(a[0]-a[1])*(b[1]-b[0]) + * a[1]*b[1] + */ +/* dnX may not be positive, but n2/2+dnX has to be */ +static void bn_mul_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n2, + int dna, int dnb, BN_ULONG *t) { + int n = n2 / 2, c1, c2; + int tna = n + dna, tnb = n + dnb; + unsigned int neg, zero; + BN_ULONG ln, lo, *p; + + /* Only call bn_mul_comba 8 if n2 == 8 and the + * two arrays are complete [steve] + */ + if (n2 == 8 && dna == 0 && dnb == 0) { + bn_mul_comba8(r, a, b); + return; + } + + /* Else do normal multiply */ + if (n2 < BN_MUL_RECURSIVE_SIZE_NORMAL) { + bn_mul_normal(r, a, n2 + dna, b, n2 + dnb); + if ((dna + dnb) < 0) { + memset(&r[2 * n2 + dna + dnb], 0, sizeof(BN_ULONG) * -(dna + dnb)); + } + return; + } + + /* r=(a[0]-a[1])*(b[1]-b[0]) */ + c1 = bn_cmp_part_words(a, &(a[n]), tna, n - tna); + c2 = bn_cmp_part_words(&(b[n]), b, tnb, tnb - n); + zero = neg = 0; + switch (c1 * 3 + c2) { + case -4: + bn_sub_part_words(t, &(a[n]), a, tna, tna - n); /* - */ + bn_sub_part_words(&(t[n]), b, &(b[n]), tnb, n - tnb); /* - */ + break; + case -3: + zero = 1; + break; + case -2: + bn_sub_part_words(t, &(a[n]), a, tna, tna - n); /* - */ + bn_sub_part_words(&(t[n]), &(b[n]), b, tnb, tnb - n); /* + */ + neg = 1; + break; + case -1: + case 0: + case 1: + zero = 1; + break; + case 2: + bn_sub_part_words(t, a, &(a[n]), tna, n - tna); /* + */ + bn_sub_part_words(&(t[n]), b, &(b[n]), tnb, n - tnb); /* - */ + neg = 1; + break; + case 3: + zero = 1; + break; + case 4: + bn_sub_part_words(t, a, &(a[n]), tna, n - tna); + bn_sub_part_words(&(t[n]), &(b[n]), b, tnb, tnb - n); + break; + } + + if (n == 4 && dna == 0 && dnb == 0) { + /* XXX: bn_mul_comba4 could take extra args to do this well */ + if (!zero) { + bn_mul_comba4(&(t[n2]), t, &(t[n])); + } else { + memset(&(t[n2]), 0, 8 * sizeof(BN_ULONG)); + } + + bn_mul_comba4(r, a, b); + bn_mul_comba4(&(r[n2]), &(a[n]), &(b[n])); + } else if (n == 8 && dna == 0 && dnb == 0) { + /* XXX: bn_mul_comba8 could take extra args to do this well */ + if (!zero) { + bn_mul_comba8(&(t[n2]), t, &(t[n])); + } else { + memset(&(t[n2]), 0, 16 * sizeof(BN_ULONG)); + } + + bn_mul_comba8(r, a, b); + bn_mul_comba8(&(r[n2]), &(a[n]), &(b[n])); + } else { + p = &(t[n2 * 2]); + if (!zero) { + bn_mul_recursive(&(t[n2]), t, &(t[n]), n, 0, 0, p); + } else { + memset(&(t[n2]), 0, n2 * sizeof(BN_ULONG)); + } + bn_mul_recursive(r, a, b, n, 0, 0, p); + bn_mul_recursive(&(r[n2]), &(a[n]), &(b[n]), n, dna, dnb, p); + } + + /* t[32] holds (a[0]-a[1])*(b[1]-b[0]), c1 is the sign + * r[10] holds (a[0]*b[0]) + * r[32] holds (b[1]*b[1]) */ + + c1 = (int)(bn_add_words(t, r, &(r[n2]), n2)); + + if (neg) { + /* if t[32] is negative */ + c1 -= (int)(bn_sub_words(&(t[n2]), t, &(t[n2]), n2)); + } else { + /* Might have a carry */ + c1 += (int)(bn_add_words(&(t[n2]), &(t[n2]), t, n2)); + } + + /* t[32] holds (a[0]-a[1])*(b[1]-b[0])+(a[0]*b[0])+(a[1]*b[1]) + * r[10] holds (a[0]*b[0]) + * r[32] holds (b[1]*b[1]) + * c1 holds the carry bits */ + c1 += (int)(bn_add_words(&(r[n]), &(r[n]), &(t[n2]), n2)); + if (c1) { + p = &(r[n + n2]); + lo = *p; + ln = (lo + c1) & BN_MASK2; + *p = ln; + + /* The overflow will stop before we over write + * words we should not overwrite */ + if (ln < (BN_ULONG)c1) { + do { + p++; + lo = *p; + ln = (lo + 1) & BN_MASK2; + *p = ln; + } while (ln == 0); + } + } +} + +/* n+tn is the word length + * t needs to be n*4 is size, as does r */ +/* tnX may not be negative but less than n */ +static void bn_mul_part_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n, + int tna, int tnb, BN_ULONG *t) { + int i, j, n2 = n * 2; + int c1, c2, neg; + BN_ULONG ln, lo, *p; + + if (n < 8) { + bn_mul_normal(r, a, n + tna, b, n + tnb); + return; + } + + /* r=(a[0]-a[1])*(b[1]-b[0]) */ + c1 = bn_cmp_part_words(a, &(a[n]), tna, n - tna); + c2 = bn_cmp_part_words(&(b[n]), b, tnb, tnb - n); + neg = 0; + switch (c1 * 3 + c2) { + case -4: + bn_sub_part_words(t, &(a[n]), a, tna, tna - n); /* - */ + bn_sub_part_words(&(t[n]), b, &(b[n]), tnb, n - tnb); /* - */ + break; + case -3: + /* break; */ + case -2: + bn_sub_part_words(t, &(a[n]), a, tna, tna - n); /* - */ + bn_sub_part_words(&(t[n]), &(b[n]), b, tnb, tnb - n); /* + */ + neg = 1; + break; + case -1: + case 0: + case 1: + /* break; */ + case 2: + bn_sub_part_words(t, a, &(a[n]), tna, n - tna); /* + */ + bn_sub_part_words(&(t[n]), b, &(b[n]), tnb, n - tnb); /* - */ + neg = 1; + break; + case 3: + /* break; */ + case 4: + bn_sub_part_words(t, a, &(a[n]), tna, n - tna); + bn_sub_part_words(&(t[n]), &(b[n]), b, tnb, tnb - n); + break; + } + + if (n == 8) { + bn_mul_comba8(&(t[n2]), t, &(t[n])); + bn_mul_comba8(r, a, b); + bn_mul_normal(&(r[n2]), &(a[n]), tna, &(b[n]), tnb); + memset(&(r[n2 + tna + tnb]), 0, sizeof(BN_ULONG) * (n2 - tna - tnb)); + } else { + p = &(t[n2 * 2]); + bn_mul_recursive(&(t[n2]), t, &(t[n]), n, 0, 0, p); + bn_mul_recursive(r, a, b, n, 0, 0, p); + i = n / 2; + /* If there is only a bottom half to the number, + * just do it */ + if (tna > tnb) { + j = tna - i; + } else { + j = tnb - i; + } + + if (j == 0) { + bn_mul_recursive(&(r[n2]), &(a[n]), &(b[n]), i, tna - i, tnb - i, p); + memset(&(r[n2 + i * 2]), 0, sizeof(BN_ULONG) * (n2 - i * 2)); + } else if (j > 0) { + /* eg, n == 16, i == 8 and tn == 11 */ + bn_mul_part_recursive(&(r[n2]), &(a[n]), &(b[n]), i, tna - i, tnb - i, p); + memset(&(r[n2 + tna + tnb]), 0, sizeof(BN_ULONG) * (n2 - tna - tnb)); + } else { + /* (j < 0) eg, n == 16, i == 8 and tn == 5 */ + memset(&(r[n2]), 0, sizeof(BN_ULONG) * n2); + if (tna < BN_MUL_RECURSIVE_SIZE_NORMAL && + tnb < BN_MUL_RECURSIVE_SIZE_NORMAL) { + bn_mul_normal(&(r[n2]), &(a[n]), tna, &(b[n]), tnb); + } else { + for (;;) { + i /= 2; + /* these simplified conditions work + * exclusively because difference + * between tna and tnb is 1 or 0 */ + if (i < tna || i < tnb) { + bn_mul_part_recursive(&(r[n2]), &(a[n]), &(b[n]), i, tna - i, + tnb - i, p); + break; + } else if (i == tna || i == tnb) { + bn_mul_recursive(&(r[n2]), &(a[n]), &(b[n]), i, tna - i, tnb - i, + p); + break; + } + } + } + } + } + + /* t[32] holds (a[0]-a[1])*(b[1]-b[0]), c1 is the sign + * r[10] holds (a[0]*b[0]) + * r[32] holds (b[1]*b[1]) + */ + + c1 = (int)(bn_add_words(t, r, &(r[n2]), n2)); + + if (neg) { + /* if t[32] is negative */ + c1 -= (int)(bn_sub_words(&(t[n2]), t, &(t[n2]), n2)); + } else { + /* Might have a carry */ + c1 += (int)(bn_add_words(&(t[n2]), &(t[n2]), t, n2)); + } + + /* t[32] holds (a[0]-a[1])*(b[1]-b[0])+(a[0]*b[0])+(a[1]*b[1]) + * r[10] holds (a[0]*b[0]) + * r[32] holds (b[1]*b[1]) + * c1 holds the carry bits */ + c1 += (int)(bn_add_words(&(r[n]), &(r[n]), &(t[n2]), n2)); + if (c1) { + p = &(r[n + n2]); + lo = *p; + ln = (lo + c1) & BN_MASK2; + *p = ln; + + /* The overflow will stop before we over write + * words we should not overwrite */ + if (ln < (BN_ULONG)c1) { + do { + p++; + lo = *p; + ln = (lo + 1) & BN_MASK2; + *p = ln; + } while (ln == 0); + } + } +} + +int BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) { + int ret = 0; + int top, al, bl; + BIGNUM *rr; + int i; + BIGNUM *t = NULL; + int j = 0, k; + + al = a->top; + bl = b->top; + + if ((al == 0) || (bl == 0)) { + BN_zero(r); + return 1; + } + top = al + bl; + + BN_CTX_start(ctx); + if ((r == a) || (r == b)) { + if ((rr = BN_CTX_get(ctx)) == NULL) { + goto err; + } + } else { + rr = r; + } + rr->neg = a->neg ^ b->neg; + + i = al - bl; + if (i == 0) { + if (al == 8) { + if (bn_wexpand(rr, 16) == NULL) { + goto err; + } + rr->top = 16; + bn_mul_comba8(rr->d, a->d, b->d); + goto end; + } + } + + static const int kMulNormalSize = 16; + if (al >= kMulNormalSize && bl >= kMulNormalSize) { + if (i >= -1 && i <= 1) { + /* Find out the power of two lower or equal + to the longest of the two numbers */ + if (i >= 0) { + j = BN_num_bits_word((BN_ULONG)al); + } + if (i == -1) { + j = BN_num_bits_word((BN_ULONG)bl); + } + j = 1 << (j - 1); + assert(j <= al || j <= bl); + k = j + j; + t = BN_CTX_get(ctx); + if (t == NULL) { + goto err; + } + if (al > j || bl > j) { + if (bn_wexpand(t, k * 4) == NULL) { + goto err; + } + if (bn_wexpand(rr, k * 4) == NULL) { + goto err; + } + bn_mul_part_recursive(rr->d, a->d, b->d, j, al - j, bl - j, t->d); + } else { + /* al <= j || bl <= j */ + if (bn_wexpand(t, k * 2) == NULL) { + goto err; + } + if (bn_wexpand(rr, k * 2) == NULL) { + goto err; + } + bn_mul_recursive(rr->d, a->d, b->d, j, al - j, bl - j, t->d); + } + rr->top = top; + goto end; + } + } + + if (bn_wexpand(rr, top) == NULL) { + goto err; + } + rr->top = top; + bn_mul_normal(rr->d, a->d, al, b->d, bl); + +end: + bn_correct_top(rr); + if (r != rr && !BN_copy(r, rr)) { + goto err; + } + ret = 1; + +err: + BN_CTX_end(ctx); + return ret; +} + +/* tmp must have 2*n words */ +static void bn_sqr_normal(BN_ULONG *r, const BN_ULONG *a, int n, BN_ULONG *tmp) { + int i, j, max; + const BN_ULONG *ap; + BN_ULONG *rp; + + max = n * 2; + ap = a; + rp = r; + rp[0] = rp[max - 1] = 0; + rp++; + j = n; + + if (--j > 0) { + ap++; + rp[j] = bn_mul_words(rp, ap, j, ap[-1]); + rp += 2; + } + + for (i = n - 2; i > 0; i--) { + j--; + ap++; + rp[j] = bn_mul_add_words(rp, ap, j, ap[-1]); + rp += 2; + } + + bn_add_words(r, r, r, max); + + /* There will not be a carry */ + + bn_sqr_words(tmp, a, n); + + bn_add_words(r, r, tmp, max); +} + +/* r is 2*n words in size, + * a and b are both n words in size. (There's not actually a 'b' here ...) + * n must be a power of 2. + * We multiply and return the result. + * t must be 2*n words in size + * We calculate + * a[0]*b[0] + * a[0]*b[0]+a[1]*b[1]+(a[0]-a[1])*(b[1]-b[0]) + * a[1]*b[1] + */ +static void bn_sqr_recursive(BN_ULONG *r, const BN_ULONG *a, int n2, BN_ULONG *t) { + int n = n2 / 2; + int zero, c1; + BN_ULONG ln, lo, *p; + + if (n2 == 4) { + bn_sqr_comba4(r, a); + return; + } else if (n2 == 8) { + bn_sqr_comba8(r, a); + return; + } + if (n2 < BN_SQR_RECURSIVE_SIZE_NORMAL) { + bn_sqr_normal(r, a, n2, t); + return; + } + /* r=(a[0]-a[1])*(a[1]-a[0]) */ + c1 = bn_cmp_words(a, &(a[n]), n); + zero = 0; + if (c1 > 0) { + bn_sub_words(t, a, &(a[n]), n); + } else if (c1 < 0) { + bn_sub_words(t, &(a[n]), a, n); + } else { + zero = 1; + } + + /* The result will always be negative unless it is zero */ + p = &(t[n2 * 2]); + + if (!zero) { + bn_sqr_recursive(&(t[n2]), t, n, p); + } else { + memset(&(t[n2]), 0, n2 * sizeof(BN_ULONG)); + } + bn_sqr_recursive(r, a, n, p); + bn_sqr_recursive(&(r[n2]), &(a[n]), n, p); + + /* t[32] holds (a[0]-a[1])*(a[1]-a[0]), it is negative or zero + * r[10] holds (a[0]*b[0]) + * r[32] holds (b[1]*b[1]) */ + + c1 = (int)(bn_add_words(t, r, &(r[n2]), n2)); + + /* t[32] is negative */ + c1 -= (int)(bn_sub_words(&(t[n2]), t, &(t[n2]), n2)); + + /* t[32] holds (a[0]-a[1])*(a[1]-a[0])+(a[0]*a[0])+(a[1]*a[1]) + * r[10] holds (a[0]*a[0]) + * r[32] holds (a[1]*a[1]) + * c1 holds the carry bits */ + c1 += (int)(bn_add_words(&(r[n]), &(r[n]), &(t[n2]), n2)); + if (c1) { + p = &(r[n + n2]); + lo = *p; + ln = (lo + c1) & BN_MASK2; + *p = ln; + + /* The overflow will stop before we over write + * words we should not overwrite */ + if (ln < (BN_ULONG)c1) { + do { + p++; + lo = *p; + ln = (lo + 1) & BN_MASK2; + *p = ln; + } while (ln == 0); + } + } +} + +int BN_mul_word(BIGNUM *bn, BN_ULONG w) { + BN_ULONG ll; + + w &= BN_MASK2; + if (!bn->top) { + return 1; + } + + if (w == 0) { + BN_zero(bn); + return 1; + } + + ll = bn_mul_words(bn->d, bn->d, bn->top, w); + if (ll) { + if (bn_wexpand(bn, bn->top + 1) == NULL) { + return 0; + } + bn->d[bn->top++] = ll; + } + + return 1; +} + +int BN_sqr(BIGNUM *r, const BIGNUM *a, BN_CTX *ctx) { + int max, al; + int ret = 0; + BIGNUM *tmp, *rr; + + al = a->top; + if (al <= 0) { + r->top = 0; + r->neg = 0; + return 1; + } + + BN_CTX_start(ctx); + rr = (a != r) ? r : BN_CTX_get(ctx); + tmp = BN_CTX_get(ctx); + if (!rr || !tmp) { + goto err; + } + + max = 2 * al; /* Non-zero (from above) */ + if (bn_wexpand(rr, max) == NULL) { + goto err; + } + + if (al == 4) { + bn_sqr_comba4(rr->d, a->d); + } else if (al == 8) { + bn_sqr_comba8(rr->d, a->d); + } else { + if (al < BN_SQR_RECURSIVE_SIZE_NORMAL) { + BN_ULONG t[BN_SQR_RECURSIVE_SIZE_NORMAL * 2]; + bn_sqr_normal(rr->d, a->d, al, t); + } else { + int j, k; + + j = BN_num_bits_word((BN_ULONG)al); + j = 1 << (j - 1); + k = j + j; + if (al == j) { + if (bn_wexpand(tmp, k * 2) == NULL) { + goto err; + } + bn_sqr_recursive(rr->d, a->d, al, tmp->d); + } else { + if (bn_wexpand(tmp, max) == NULL) { + goto err; + } + bn_sqr_normal(rr->d, a->d, al, tmp->d); + } + } + } + + rr->neg = 0; + /* If the most-significant half of the top word of 'a' is zero, then + * the square of 'a' will max-1 words. */ + if (a->d[al - 1] == (a->d[al - 1] & BN_MASK2l)) { + rr->top = max - 1; + } else { + rr->top = max; + } + + if (rr != r && !BN_copy(r, rr)) { + goto err; + } + ret = 1; + +err: + BN_CTX_end(ctx); + return ret; +} diff --git a/external/boringssl/crypto/bn/prime.c b/external/boringssl/crypto/bn/prime.c new file mode 100644 index 0000000000..d07e6094b9 --- /dev/null +++ b/external/boringssl/crypto/bn/prime.c @@ -0,0 +1,845 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include + +#include "internal.h" + +/* number of Miller-Rabin iterations for an error rate of less than 2^-80 + * for random 'b'-bit input, b >= 100 (taken from table 4.4 in the Handbook + * of Applied Cryptography [Menezes, van Oorschot, Vanstone; CRC Press 1996]; + * original paper: Damgaard, Landrock, Pomerance: Average case error estimates + * for the strong probable prime test. -- Math. Comp. 61 (1993) 177-194) */ +#define BN_prime_checks_for_size(b) ((b) >= 1300 ? 2 : \ + (b) >= 850 ? 3 : \ + (b) >= 650 ? 4 : \ + (b) >= 550 ? 5 : \ + (b) >= 450 ? 6 : \ + (b) >= 400 ? 7 : \ + (b) >= 350 ? 8 : \ + (b) >= 300 ? 9 : \ + (b) >= 250 ? 12 : \ + (b) >= 200 ? 15 : \ + (b) >= 150 ? 18 : \ + /* b >= 100 */ 27) + +/* The quick sieve algorithm approach to weeding out primes is Philip + * Zimmermann's, as implemented in PGP. I have had a read of his comments and + * implemented my own version. */ + +/* NUMPRIMES is the number of primes that fit into a uint16_t. */ +#define NUMPRIMES 2048 + +/* primes contains all the primes that fit into a uint16_t. */ +static const uint16_t primes[NUMPRIMES] = { + 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, + 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, + 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, + 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, + 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, + 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, + 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, + 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, + 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, + 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, + 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, + 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, + 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, + 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, + 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, + 983, 991, 997, 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, + 1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097, 1103, 1109, 1117, + 1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, + 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, + 1291, 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, + 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, 1453, + 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511, 1523, 1531, + 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597, 1601, 1607, + 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, + 1697, 1699, 1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, 1777, + 1783, 1787, 1789, 1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871, + 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949, 1951, + 1973, 1979, 1987, 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, + 2039, 2053, 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, + 2129, 2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213, + 2221, 2237, 2239, 2243, 2251, 2267, 2269, 2273, 2281, 2287, 2293, + 2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, 2371, 2377, + 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, 2437, 2441, 2447, + 2459, 2467, 2473, 2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551, + 2557, 2579, 2591, 2593, 2609, 2617, 2621, 2633, 2647, 2657, 2659, + 2663, 2671, 2677, 2683, 2687, 2689, 2693, 2699, 2707, 2711, 2713, + 2719, 2729, 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, 2797, + 2801, 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, + 2897, 2903, 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, + 2999, 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079, + 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, 3169, 3181, 3187, + 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257, 3259, 3271, + 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, 3343, 3347, 3359, + 3361, 3371, 3373, 3389, 3391, 3407, 3413, 3433, 3449, 3457, 3461, + 3463, 3467, 3469, 3491, 3499, 3511, 3517, 3527, 3529, 3533, 3539, + 3541, 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607, 3613, 3617, + 3623, 3631, 3637, 3643, 3659, 3671, 3673, 3677, 3691, 3697, 3701, + 3709, 3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, + 3803, 3821, 3823, 3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889, + 3907, 3911, 3917, 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989, + 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, 4073, + 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139, 4153, 4157, + 4159, 4177, 4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243, 4253, + 4259, 4261, 4271, 4273, 4283, 4289, 4297, 4327, 4337, 4339, 4349, + 4357, 4363, 4373, 4391, 4397, 4409, 4421, 4423, 4441, 4447, 4451, + 4457, 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, 4523, 4547, + 4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621, 4637, 4639, 4643, + 4649, 4651, 4657, 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, + 4733, 4751, 4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813, 4817, + 4831, 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, 4933, 4937, + 4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003, 5009, + 5011, 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, 5099, 5101, + 5107, 5113, 5119, 5147, 5153, 5167, 5171, 5179, 5189, 5197, 5209, + 5227, 5231, 5233, 5237, 5261, 5273, 5279, 5281, 5297, 5303, 5309, + 5323, 5333, 5347, 5351, 5381, 5387, 5393, 5399, 5407, 5413, 5417, + 5419, 5431, 5437, 5441, 5443, 5449, 5471, 5477, 5479, 5483, 5501, + 5503, 5507, 5519, 5521, 5527, 5531, 5557, 5563, 5569, 5573, 5581, + 5591, 5623, 5639, 5641, 5647, 5651, 5653, 5657, 5659, 5669, 5683, + 5689, 5693, 5701, 5711, 5717, 5737, 5741, 5743, 5749, 5779, 5783, + 5791, 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857, + 5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939, 5953, + 5981, 5987, 6007, 6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073, + 6079, 6089, 6091, 6101, 6113, 6121, 6131, 6133, 6143, 6151, 6163, + 6173, 6197, 6199, 6203, 6211, 6217, 6221, 6229, 6247, 6257, 6263, + 6269, 6271, 6277, 6287, 6299, 6301, 6311, 6317, 6323, 6329, 6337, + 6343, 6353, 6359, 6361, 6367, 6373, 6379, 6389, 6397, 6421, 6427, + 6449, 6451, 6469, 6473, 6481, 6491, 6521, 6529, 6547, 6551, 6553, + 6563, 6569, 6571, 6577, 6581, 6599, 6607, 6619, 6637, 6653, 6659, + 6661, 6673, 6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733, 6737, + 6761, 6763, 6779, 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833, + 6841, 6857, 6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917, 6947, + 6949, 6959, 6961, 6967, 6971, 6977, 6983, 6991, 6997, 7001, 7013, + 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103, 7109, 7121, 7127, + 7129, 7151, 7159, 7177, 7187, 7193, 7207, 7211, 7213, 7219, 7229, + 7237, 7243, 7247, 7253, 7283, 7297, 7307, 7309, 7321, 7331, 7333, + 7349, 7351, 7369, 7393, 7411, 7417, 7433, 7451, 7457, 7459, 7477, + 7481, 7487, 7489, 7499, 7507, 7517, 7523, 7529, 7537, 7541, 7547, + 7549, 7559, 7561, 7573, 7577, 7583, 7589, 7591, 7603, 7607, 7621, + 7639, 7643, 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, + 7723, 7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829, + 7841, 7853, 7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919, 7927, + 7933, 7937, 7949, 7951, 7963, 7993, 8009, 8011, 8017, 8039, 8053, + 8059, 8069, 8081, 8087, 8089, 8093, 8101, 8111, 8117, 8123, 8147, + 8161, 8167, 8171, 8179, 8191, 8209, 8219, 8221, 8231, 8233, 8237, + 8243, 8263, 8269, 8273, 8287, 8291, 8293, 8297, 8311, 8317, 8329, + 8353, 8363, 8369, 8377, 8387, 8389, 8419, 8423, 8429, 8431, 8443, + 8447, 8461, 8467, 8501, 8513, 8521, 8527, 8537, 8539, 8543, 8563, + 8573, 8581, 8597, 8599, 8609, 8623, 8627, 8629, 8641, 8647, 8663, + 8669, 8677, 8681, 8689, 8693, 8699, 8707, 8713, 8719, 8731, 8737, + 8741, 8747, 8753, 8761, 8779, 8783, 8803, 8807, 8819, 8821, 8831, + 8837, 8839, 8849, 8861, 8863, 8867, 8887, 8893, 8923, 8929, 8933, + 8941, 8951, 8963, 8969, 8971, 8999, 9001, 9007, 9011, 9013, 9029, + 9041, 9043, 9049, 9059, 9067, 9091, 9103, 9109, 9127, 9133, 9137, + 9151, 9157, 9161, 9173, 9181, 9187, 9199, 9203, 9209, 9221, 9227, + 9239, 9241, 9257, 9277, 9281, 9283, 9293, 9311, 9319, 9323, 9337, + 9341, 9343, 9349, 9371, 9377, 9391, 9397, 9403, 9413, 9419, 9421, + 9431, 9433, 9437, 9439, 9461, 9463, 9467, 9473, 9479, 9491, 9497, + 9511, 9521, 9533, 9539, 9547, 9551, 9587, 9601, 9613, 9619, 9623, + 9629, 9631, 9643, 9649, 9661, 9677, 9679, 9689, 9697, 9719, 9721, + 9733, 9739, 9743, 9749, 9767, 9769, 9781, 9787, 9791, 9803, 9811, + 9817, 9829, 9833, 9839, 9851, 9857, 9859, 9871, 9883, 9887, 9901, + 9907, 9923, 9929, 9931, 9941, 9949, 9967, 9973, 10007, 10009, 10037, + 10039, 10061, 10067, 10069, 10079, 10091, 10093, 10099, 10103, 10111, 10133, + 10139, 10141, 10151, 10159, 10163, 10169, 10177, 10181, 10193, 10211, 10223, + 10243, 10247, 10253, 10259, 10267, 10271, 10273, 10289, 10301, 10303, 10313, + 10321, 10331, 10333, 10337, 10343, 10357, 10369, 10391, 10399, 10427, 10429, + 10433, 10453, 10457, 10459, 10463, 10477, 10487, 10499, 10501, 10513, 10529, + 10531, 10559, 10567, 10589, 10597, 10601, 10607, 10613, 10627, 10631, 10639, + 10651, 10657, 10663, 10667, 10687, 10691, 10709, 10711, 10723, 10729, 10733, + 10739, 10753, 10771, 10781, 10789, 10799, 10831, 10837, 10847, 10853, 10859, + 10861, 10867, 10883, 10889, 10891, 10903, 10909, 10937, 10939, 10949, 10957, + 10973, 10979, 10987, 10993, 11003, 11027, 11047, 11057, 11059, 11069, 11071, + 11083, 11087, 11093, 11113, 11117, 11119, 11131, 11149, 11159, 11161, 11171, + 11173, 11177, 11197, 11213, 11239, 11243, 11251, 11257, 11261, 11273, 11279, + 11287, 11299, 11311, 11317, 11321, 11329, 11351, 11353, 11369, 11383, 11393, + 11399, 11411, 11423, 11437, 11443, 11447, 11467, 11471, 11483, 11489, 11491, + 11497, 11503, 11519, 11527, 11549, 11551, 11579, 11587, 11593, 11597, 11617, + 11621, 11633, 11657, 11677, 11681, 11689, 11699, 11701, 11717, 11719, 11731, + 11743, 11777, 11779, 11783, 11789, 11801, 11807, 11813, 11821, 11827, 11831, + 11833, 11839, 11863, 11867, 11887, 11897, 11903, 11909, 11923, 11927, 11933, + 11939, 11941, 11953, 11959, 11969, 11971, 11981, 11987, 12007, 12011, 12037, + 12041, 12043, 12049, 12071, 12073, 12097, 12101, 12107, 12109, 12113, 12119, + 12143, 12149, 12157, 12161, 12163, 12197, 12203, 12211, 12227, 12239, 12241, + 12251, 12253, 12263, 12269, 12277, 12281, 12289, 12301, 12323, 12329, 12343, + 12347, 12373, 12377, 12379, 12391, 12401, 12409, 12413, 12421, 12433, 12437, + 12451, 12457, 12473, 12479, 12487, 12491, 12497, 12503, 12511, 12517, 12527, + 12539, 12541, 12547, 12553, 12569, 12577, 12583, 12589, 12601, 12611, 12613, + 12619, 12637, 12641, 12647, 12653, 12659, 12671, 12689, 12697, 12703, 12713, + 12721, 12739, 12743, 12757, 12763, 12781, 12791, 12799, 12809, 12821, 12823, + 12829, 12841, 12853, 12889, 12893, 12899, 12907, 12911, 12917, 12919, 12923, + 12941, 12953, 12959, 12967, 12973, 12979, 12983, 13001, 13003, 13007, 13009, + 13033, 13037, 13043, 13049, 13063, 13093, 13099, 13103, 13109, 13121, 13127, + 13147, 13151, 13159, 13163, 13171, 13177, 13183, 13187, 13217, 13219, 13229, + 13241, 13249, 13259, 13267, 13291, 13297, 13309, 13313, 13327, 13331, 13337, + 13339, 13367, 13381, 13397, 13399, 13411, 13417, 13421, 13441, 13451, 13457, + 13463, 13469, 13477, 13487, 13499, 13513, 13523, 13537, 13553, 13567, 13577, + 13591, 13597, 13613, 13619, 13627, 13633, 13649, 13669, 13679, 13681, 13687, + 13691, 13693, 13697, 13709, 13711, 13721, 13723, 13729, 13751, 13757, 13759, + 13763, 13781, 13789, 13799, 13807, 13829, 13831, 13841, 13859, 13873, 13877, + 13879, 13883, 13901, 13903, 13907, 13913, 13921, 13931, 13933, 13963, 13967, + 13997, 13999, 14009, 14011, 14029, 14033, 14051, 14057, 14071, 14081, 14083, + 14087, 14107, 14143, 14149, 14153, 14159, 14173, 14177, 14197, 14207, 14221, + 14243, 14249, 14251, 14281, 14293, 14303, 14321, 14323, 14327, 14341, 14347, + 14369, 14387, 14389, 14401, 14407, 14411, 14419, 14423, 14431, 14437, 14447, + 14449, 14461, 14479, 14489, 14503, 14519, 14533, 14537, 14543, 14549, 14551, + 14557, 14561, 14563, 14591, 14593, 14621, 14627, 14629, 14633, 14639, 14653, + 14657, 14669, 14683, 14699, 14713, 14717, 14723, 14731, 14737, 14741, 14747, + 14753, 14759, 14767, 14771, 14779, 14783, 14797, 14813, 14821, 14827, 14831, + 14843, 14851, 14867, 14869, 14879, 14887, 14891, 14897, 14923, 14929, 14939, + 14947, 14951, 14957, 14969, 14983, 15013, 15017, 15031, 15053, 15061, 15073, + 15077, 15083, 15091, 15101, 15107, 15121, 15131, 15137, 15139, 15149, 15161, + 15173, 15187, 15193, 15199, 15217, 15227, 15233, 15241, 15259, 15263, 15269, + 15271, 15277, 15287, 15289, 15299, 15307, 15313, 15319, 15329, 15331, 15349, + 15359, 15361, 15373, 15377, 15383, 15391, 15401, 15413, 15427, 15439, 15443, + 15451, 15461, 15467, 15473, 15493, 15497, 15511, 15527, 15541, 15551, 15559, + 15569, 15581, 15583, 15601, 15607, 15619, 15629, 15641, 15643, 15647, 15649, + 15661, 15667, 15671, 15679, 15683, 15727, 15731, 15733, 15737, 15739, 15749, + 15761, 15767, 15773, 15787, 15791, 15797, 15803, 15809, 15817, 15823, 15859, + 15877, 15881, 15887, 15889, 15901, 15907, 15913, 15919, 15923, 15937, 15959, + 15971, 15973, 15991, 16001, 16007, 16033, 16057, 16061, 16063, 16067, 16069, + 16073, 16087, 16091, 16097, 16103, 16111, 16127, 16139, 16141, 16183, 16187, + 16189, 16193, 16217, 16223, 16229, 16231, 16249, 16253, 16267, 16273, 16301, + 16319, 16333, 16339, 16349, 16361, 16363, 16369, 16381, 16411, 16417, 16421, + 16427, 16433, 16447, 16451, 16453, 16477, 16481, 16487, 16493, 16519, 16529, + 16547, 16553, 16561, 16567, 16573, 16603, 16607, 16619, 16631, 16633, 16649, + 16651, 16657, 16661, 16673, 16691, 16693, 16699, 16703, 16729, 16741, 16747, + 16759, 16763, 16787, 16811, 16823, 16829, 16831, 16843, 16871, 16879, 16883, + 16889, 16901, 16903, 16921, 16927, 16931, 16937, 16943, 16963, 16979, 16981, + 16987, 16993, 17011, 17021, 17027, 17029, 17033, 17041, 17047, 17053, 17077, + 17093, 17099, 17107, 17117, 17123, 17137, 17159, 17167, 17183, 17189, 17191, + 17203, 17207, 17209, 17231, 17239, 17257, 17291, 17293, 17299, 17317, 17321, + 17327, 17333, 17341, 17351, 17359, 17377, 17383, 17387, 17389, 17393, 17401, + 17417, 17419, 17431, 17443, 17449, 17467, 17471, 17477, 17483, 17489, 17491, + 17497, 17509, 17519, 17539, 17551, 17569, 17573, 17579, 17581, 17597, 17599, + 17609, 17623, 17627, 17657, 17659, 17669, 17681, 17683, 17707, 17713, 17729, + 17737, 17747, 17749, 17761, 17783, 17789, 17791, 17807, 17827, 17837, 17839, + 17851, 17863, +}; + +static int witness(BIGNUM *w, const BIGNUM *a, const BIGNUM *a1, + const BIGNUM *a1_odd, int k, BN_CTX *ctx, BN_MONT_CTX *mont); +static int probable_prime(BIGNUM *rnd, int bits); +static int probable_prime_dh(BIGNUM *rnd, int bits, const BIGNUM *add, + const BIGNUM *rem, BN_CTX *ctx); +static int probable_prime_dh_safe(BIGNUM *rnd, int bits, const BIGNUM *add, + const BIGNUM *rem, BN_CTX *ctx); + +void BN_GENCB_set(BN_GENCB *callback, + int (*f)(int event, int n, struct bn_gencb_st *), + void *arg) { + callback->callback = f; + callback->arg = arg; +} + +int BN_GENCB_call(BN_GENCB *callback, int event, int n) { + if (!callback) { + return 1; + } + + return callback->callback(event, n, callback); +} + +int BN_generate_prime_ex(BIGNUM *ret, int bits, int safe, const BIGNUM *add, + const BIGNUM *rem, BN_GENCB *cb) { + BIGNUM *t; + int found = 0; + int i, j, c1 = 0; + BN_CTX *ctx; + int checks = BN_prime_checks_for_size(bits); + + if (bits < 2) { + /* There are no prime numbers this small. */ + OPENSSL_PUT_ERROR(BN, BN_R_BITS_TOO_SMALL); + return 0; + } else if (bits == 2 && safe) { + /* The smallest safe prime (7) is three bits. */ + OPENSSL_PUT_ERROR(BN, BN_R_BITS_TOO_SMALL); + return 0; + } + + ctx = BN_CTX_new(); + if (ctx == NULL) { + goto err; + } + BN_CTX_start(ctx); + t = BN_CTX_get(ctx); + if (!t) { + goto err; + } + +loop: + /* make a random number and set the top and bottom bits */ + if (add == NULL) { + if (!probable_prime(ret, bits)) { + goto err; + } + } else { + if (safe) { + if (!probable_prime_dh_safe(ret, bits, add, rem, ctx)) { + goto err; + } + } else { + if (!probable_prime_dh(ret, bits, add, rem, ctx)) { + goto err; + } + } + } + + if (!BN_GENCB_call(cb, BN_GENCB_GENERATED, c1++)) { + /* aborted */ + goto err; + } + + if (!safe) { + i = BN_is_prime_fasttest_ex(ret, checks, ctx, 0, cb); + if (i == -1) { + goto err; + } else if (i == 0) { + goto loop; + } + } else { + /* for "safe prime" generation, check that (p-1)/2 is prime. Since a prime + * is odd, We just need to divide by 2 */ + if (!BN_rshift1(t, ret)) { + goto err; + } + + for (i = 0; i < checks; i++) { + j = BN_is_prime_fasttest_ex(ret, 1, ctx, 0, NULL); + if (j == -1) { + goto err; + } else if (j == 0) { + goto loop; + } + + j = BN_is_prime_fasttest_ex(t, 1, ctx, 0, NULL); + if (j == -1) { + goto err; + } else if (j == 0) { + goto loop; + } + + if (!BN_GENCB_call(cb, i, c1 - 1)) { + goto err; + } + /* We have a safe prime test pass */ + } + } + + /* we have a prime :-) */ + found = 1; + +err: + if (ctx != NULL) { + BN_CTX_end(ctx); + BN_CTX_free(ctx); + } + + return found; +} + +int BN_primality_test(int *is_probably_prime, const BIGNUM *candidate, + int checks, BN_CTX *ctx, int do_trial_division, + BN_GENCB *cb) { + switch (BN_is_prime_fasttest_ex(candidate, checks, ctx, do_trial_division, cb)) { + case 1: + *is_probably_prime = 1; + return 1; + case 0: + *is_probably_prime = 0; + return 1; + default: + *is_probably_prime = 0; + return 0; + } +} + +int BN_is_prime_ex(const BIGNUM *candidate, int checks, BN_CTX *ctx, BN_GENCB *cb) { + return BN_is_prime_fasttest_ex(candidate, checks, ctx, 0, cb); +} + +int BN_is_prime_fasttest_ex(const BIGNUM *a, int checks, BN_CTX *ctx_passed, + int do_trial_division, BN_GENCB *cb) { + int i, j, ret = -1; + int k; + BN_CTX *ctx = NULL; + BIGNUM *A1, *A1_odd, *check; /* taken from ctx */ + BN_MONT_CTX *mont = NULL; + const BIGNUM *A = NULL; + + if (BN_cmp(a, BN_value_one()) <= 0) { + return 0; + } + + if (checks == BN_prime_checks) { + checks = BN_prime_checks_for_size(BN_num_bits(a)); + } + + /* first look for small factors */ + if (!BN_is_odd(a)) { + /* a is even => a is prime if and only if a == 2 */ + return BN_is_word(a, 2); + } + + if (do_trial_division) { + for (i = 1; i < NUMPRIMES; i++) { + if (BN_mod_word(a, primes[i]) == 0) { + return 0; + } + } + + if (!BN_GENCB_call(cb, 1, -1)) { + goto err; + } + } + + if (ctx_passed != NULL) { + ctx = ctx_passed; + } else if ((ctx = BN_CTX_new()) == NULL) { + goto err; + } + BN_CTX_start(ctx); + + /* A := abs(a) */ + if (a->neg) { + BIGNUM *t = BN_CTX_get(ctx); + if (t == NULL || !BN_copy(t, a)) { + goto err; + } + t->neg = 0; + A = t; + } else { + A = a; + } + + A1 = BN_CTX_get(ctx); + A1_odd = BN_CTX_get(ctx); + check = BN_CTX_get(ctx); + if (check == NULL) { + goto err; + } + + /* compute A1 := A - 1 */ + if (!BN_copy(A1, A)) { + goto err; + } + if (!BN_sub_word(A1, 1)) { + goto err; + } + if (BN_is_zero(A1)) { + ret = 0; + goto err; + } + + /* write A1 as A1_odd * 2^k */ + k = 1; + while (!BN_is_bit_set(A1, k)) { + k++; + } + if (!BN_rshift(A1_odd, A1, k)) { + goto err; + } + + /* Montgomery setup for computations mod A */ + mont = BN_MONT_CTX_new(); + if (mont == NULL) { + goto err; + } + if (!BN_MONT_CTX_set(mont, A, ctx)) { + goto err; + } + + for (i = 0; i < checks; i++) { + if (!BN_pseudo_rand_range(check, A1)) { + goto err; + } + if (!BN_add_word(check, 1)) { + goto err; + } + /* now 1 <= check < A */ + + j = witness(check, A, A1, A1_odd, k, ctx, mont); + if (j == -1) { + goto err; + } + if (j) { + ret = 0; + goto err; + } + if (!BN_GENCB_call(cb, 1, i)) { + goto err; + } + } + ret = 1; + +err: + if (ctx != NULL) { + BN_CTX_end(ctx); + if (ctx_passed == NULL) { + BN_CTX_free(ctx); + } + } + if (mont != NULL) { + BN_MONT_CTX_free(mont); + } + + return ret; +} + +static int witness(BIGNUM *w, const BIGNUM *a, const BIGNUM *a1, + const BIGNUM *a1_odd, int k, BN_CTX *ctx, + BN_MONT_CTX *mont) { + if (!BN_mod_exp_mont(w, w, a1_odd, a, ctx, mont)) { /* w := w^a1_odd mod a */ + return -1; + } + if (BN_is_one(w)) { + return 0; /* probably prime */ + } + if (BN_cmp(w, a1) == 0) { + return 0; /* w == -1 (mod a), 'a' is probably prime */ + } + + while (--k) { + if (!BN_mod_mul(w, w, w, a, ctx)) { /* w := w^2 mod a */ + return -1; + } + + if (BN_is_one(w)) { + return 1; /* 'a' is composite, otherwise a previous 'w' would + * have been == -1 (mod 'a') */ + } + + if (BN_cmp(w, a1) == 0) { + return 0; /* w == -1 (mod a), 'a' is probably prime */ + } + } + + /* If we get here, 'w' is the (a-1)/2-th power of the original 'w', + * and it is neither -1 nor +1 -- so 'a' cannot be prime */ + return 1; +} + +static BN_ULONG get_word(const BIGNUM *bn) { + if (bn->top == 1) { + return bn->d[0]; + } + return 0; +} + +static int probable_prime(BIGNUM *rnd, int bits) { + int i; + uint16_t mods[NUMPRIMES]; + BN_ULONG delta; + BN_ULONG maxdelta = BN_MASK2 - primes[NUMPRIMES - 1]; + char is_single_word = bits <= BN_BITS2; + +again: + if (!BN_rand(rnd, bits, 1, 1)) { + return 0; + } + + /* we now have a random number 'rnd' to test. */ + for (i = 1; i < NUMPRIMES; i++) { + mods[i] = (uint16_t)BN_mod_word(rnd, (BN_ULONG)primes[i]); + } + /* If bits is so small that it fits into a single word then we + * additionally don't want to exceed that many bits. */ + if (is_single_word) { + BN_ULONG size_limit; + if (bits == BN_BITS2) { + /* Avoid undefined behavior. */ + size_limit = ~((BN_ULONG)0) - get_word(rnd); + } else { + size_limit = (((BN_ULONG)1) << bits) - get_word(rnd) - 1; + } + if (size_limit < maxdelta) { + maxdelta = size_limit; + } + } + delta = 0; + +loop: + if (is_single_word) { + BN_ULONG rnd_word = get_word(rnd); + + /* In the case that the candidate prime is a single word then + * we check that: + * 1) It's greater than primes[i] because we shouldn't reject + * 3 as being a prime number because it's a multiple of + * three. + * 2) That it's not a multiple of a known prime. We don't + * check that rnd-1 is also coprime to all the known + * primes because there aren't many small primes where + * that's true. */ + for (i = 1; i < NUMPRIMES && primes[i] < rnd_word; i++) { + if ((mods[i] + delta) % primes[i] == 0) { + delta += 2; + if (delta > maxdelta) { + goto again; + } + goto loop; + } + } + } else { + for (i = 1; i < NUMPRIMES; i++) { + /* check that rnd is not a prime and also + * that gcd(rnd-1,primes) == 1 (except for 2) */ + if (((mods[i] + delta) % primes[i]) <= 1) { + delta += 2; + if (delta > maxdelta) { + goto again; + } + goto loop; + } + } + } + + if (!BN_add_word(rnd, delta)) { + return 0; + } + if (BN_num_bits(rnd) != (unsigned)bits) { + goto again; + } + + return 1; +} + +static int probable_prime_dh(BIGNUM *rnd, int bits, const BIGNUM *add, + const BIGNUM *rem, BN_CTX *ctx) { + int i, ret = 0; + BIGNUM *t1; + + BN_CTX_start(ctx); + if ((t1 = BN_CTX_get(ctx)) == NULL) { + goto err; + } + + if (!BN_rand(rnd, bits, 0, 1)) { + goto err; + } + + /* we need ((rnd-rem) % add) == 0 */ + + if (!BN_mod(t1, rnd, add, ctx)) { + goto err; + } + if (!BN_sub(rnd, rnd, t1)) { + goto err; + } + if (rem == NULL) { + if (!BN_add_word(rnd, 1)) { + goto err; + } + } else { + if (!BN_add(rnd, rnd, rem)) { + goto err; + } + } + /* we now have a random number 'rand' to test. */ + +loop: + for (i = 1; i < NUMPRIMES; i++) { + /* check that rnd is a prime */ + if (BN_mod_word(rnd, (BN_ULONG)primes[i]) <= 1) { + if (!BN_add(rnd, rnd, add)) { + goto err; + } + goto loop; + } + } + + ret = 1; + +err: + BN_CTX_end(ctx); + return ret; +} + +static int probable_prime_dh_safe(BIGNUM *p, int bits, const BIGNUM *padd, + const BIGNUM *rem, BN_CTX *ctx) { + int i, ret = 0; + BIGNUM *t1, *qadd, *q; + + bits--; + BN_CTX_start(ctx); + t1 = BN_CTX_get(ctx); + q = BN_CTX_get(ctx); + qadd = BN_CTX_get(ctx); + if (qadd == NULL) { + goto err; + } + + if (!BN_rshift1(qadd, padd)) { + goto err; + } + + if (!BN_rand(q, bits, 0, 1)) { + goto err; + } + + /* we need ((rnd-rem) % add) == 0 */ + if (!BN_mod(t1, q, qadd, ctx)) { + goto err; + } + + if (!BN_sub(q, q, t1)) { + goto err; + } + + if (rem == NULL) { + if (!BN_add_word(q, 1)) { + goto err; + } + } else { + if (!BN_rshift1(t1, rem)) { + goto err; + } + if (!BN_add(q, q, t1)) { + goto err; + } + } + + /* we now have a random number 'rand' to test. */ + if (!BN_lshift1(p, q)) { + goto err; + } + if (!BN_add_word(p, 1)) { + goto err; + } + +loop: + for (i = 1; i < NUMPRIMES; i++) { + /* check that p and q are prime */ + /* check that for p and q + * gcd(p-1,primes) == 1 (except for 2) */ + if ((BN_mod_word(p, (BN_ULONG)primes[i]) == 0) || + (BN_mod_word(q, (BN_ULONG)primes[i]) == 0)) { + if (!BN_add(p, p, padd)) { + goto err; + } + if (!BN_add(q, q, qadd)) { + goto err; + } + goto loop; + } + } + + ret = 1; + +err: + BN_CTX_end(ctx); + return ret; +} diff --git a/external/boringssl/crypto/bn/random.c b/external/boringssl/crypto/bn/random.c new file mode 100644 index 0000000000..3116e54731 --- /dev/null +++ b/external/boringssl/crypto/bn/random.c @@ -0,0 +1,326 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include + +#include +#include +#include +#include + +int BN_rand(BIGNUM *rnd, int bits, int top, int bottom) { + uint8_t *buf = NULL; + int ret = 0, bit, bytes, mask; + + if (rnd == NULL) { + return 0; + } + + if (bits == 0) { + BN_zero(rnd); + return 1; + } + + bytes = (bits + 7) / 8; + bit = (bits - 1) % 8; + mask = 0xff << (bit + 1); + + buf = OPENSSL_malloc(bytes); + if (buf == NULL) { + OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE); + goto err; + } + + /* Make a random number and set the top and bottom bits. */ + if (!RAND_bytes(buf, bytes)) { + goto err; + } + + if (top != -1) { + if (top && bits > 1) { + if (bit == 0) { + buf[0] = 1; + buf[1] |= 0x80; + } else { + buf[0] |= (3 << (bit - 1)); + } + } else { + buf[0] |= (1 << bit); + } + } + + buf[0] &= ~mask; + + /* set bottom bit if requested */ + if (bottom) { + buf[bytes - 1] |= 1; + } + + if (!BN_bin2bn(buf, bytes, rnd)) { + goto err; + } + + ret = 1; + +err: + if (buf != NULL) { + OPENSSL_cleanse(buf, bytes); + OPENSSL_free(buf); + } + return (ret); +} + +int BN_pseudo_rand(BIGNUM *rnd, int bits, int top, int bottom) { + return BN_rand(rnd, bits, top, bottom); +} + +int BN_rand_range(BIGNUM *r, const BIGNUM *range) { + unsigned n; + unsigned count = 100; + + if (range->neg || BN_is_zero(range)) { + OPENSSL_PUT_ERROR(BN, BN_R_INVALID_RANGE); + return 0; + } + + n = BN_num_bits(range); /* n > 0 */ + + /* BN_is_bit_set(range, n - 1) always holds */ + if (n == 1) { + BN_zero(r); + } else if (!BN_is_bit_set(range, n - 2) && !BN_is_bit_set(range, n - 3)) { + /* range = 100..._2, + * so 3*range (= 11..._2) is exactly one bit longer than range */ + do { + if (!BN_rand(r, n + 1, -1 /* don't set most significant bits */, + 0 /* don't set least significant bits */)) { + return 0; + } + + /* If r < 3*range, use r := r MOD range (which is either r, r - range, or + * r - 2*range). Otherwise, iterate again. Since 3*range = 11..._2, each + * iteration succeeds with probability >= .75. */ + if (BN_cmp(r, range) >= 0) { + if (!BN_sub(r, r, range)) { + return 0; + } + if (BN_cmp(r, range) >= 0) { + if (!BN_sub(r, r, range)) { + return 0; + } + } + } + + if (!--count) { + OPENSSL_PUT_ERROR(BN, BN_R_TOO_MANY_ITERATIONS); + return 0; + } + } while (BN_cmp(r, range) >= 0); + } else { + do { + /* range = 11..._2 or range = 101..._2 */ + if (!BN_rand(r, n, -1, 0)) { + return 0; + } + + if (!--count) { + OPENSSL_PUT_ERROR(BN, BN_R_TOO_MANY_ITERATIONS); + return 0; + } + } while (BN_cmp(r, range) >= 0); + } + + return 1; +} + +int BN_pseudo_rand_range(BIGNUM *r, const BIGNUM *range) { + return BN_rand_range(r, range); +} + +int BN_generate_dsa_nonce(BIGNUM *out, const BIGNUM *range, const BIGNUM *priv, + const uint8_t *message, size_t message_len, + BN_CTX *ctx) { + SHA512_CTX sha; + /* We use 512 bits of random data per iteration to + * ensure that we have at least |range| bits of randomness. */ + uint8_t random_bytes[64]; + uint8_t digest[SHA512_DIGEST_LENGTH]; + size_t done, todo, attempt; + const unsigned num_k_bytes = BN_num_bytes(range); + const unsigned bits_to_mask = (8 - (BN_num_bits(range) % 8)) % 8; + uint8_t private_bytes[96]; + uint8_t *k_bytes = NULL; + int ret = 0; + + if (out == NULL) { + return 0; + } + + if (BN_is_zero(range)) { + OPENSSL_PUT_ERROR(BN, BN_R_DIV_BY_ZERO); + goto err; + } + + k_bytes = OPENSSL_malloc(num_k_bytes); + if (!k_bytes) { + OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE); + goto err; + } + + /* We copy |priv| into a local buffer to avoid furthur exposing its + * length. */ + todo = sizeof(priv->d[0]) * priv->top; + if (todo > sizeof(private_bytes)) { + /* No reasonable DSA or ECDSA key should have a private key + * this large and we don't handle this case in order to avoid + * leaking the length of the private key. */ + OPENSSL_PUT_ERROR(BN, BN_R_PRIVATE_KEY_TOO_LARGE); + goto err; + } + memcpy(private_bytes, priv->d, todo); + memset(private_bytes + todo, 0, sizeof(private_bytes) - todo); + + for (attempt = 0;; attempt++) { + for (done = 0; done < num_k_bytes;) { + if (!RAND_bytes(random_bytes, sizeof(random_bytes))) { + goto err; + } + SHA512_Init(&sha); + SHA512_Update(&sha, &attempt, sizeof(attempt)); + SHA512_Update(&sha, &done, sizeof(done)); + SHA512_Update(&sha, private_bytes, sizeof(private_bytes)); + SHA512_Update(&sha, message, message_len); + SHA512_Update(&sha, random_bytes, sizeof(random_bytes)); + SHA512_Final(digest, &sha); + + todo = num_k_bytes - done; + if (todo > SHA512_DIGEST_LENGTH) { + todo = SHA512_DIGEST_LENGTH; + } + memcpy(k_bytes + done, digest, todo); + done += todo; + } + + k_bytes[0] &= 0xff >> bits_to_mask; + + if (!BN_bin2bn(k_bytes, num_k_bytes, out)) { + goto err; + } + if (BN_cmp(out, range) < 0) { + break; + } + } + + ret = 1; + +err: + OPENSSL_free(k_bytes); + return ret; +} diff --git a/external/boringssl/crypto/bn/rsaz_exp.c b/external/boringssl/crypto/bn/rsaz_exp.c new file mode 100644 index 0000000000..30f08e5f8b --- /dev/null +++ b/external/boringssl/crypto/bn/rsaz_exp.c @@ -0,0 +1,319 @@ +/***************************************************************************** +* * +* Copyright (c) 2012, Intel Corporation * +* * +* All rights reserved. * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are * +* met: * +* * +* * Redistributions of source code must retain the above copyright * +* notice, this list of conditions and the following disclaimer. * +* * +* * Redistributions in binary form must reproduce the above copyright * +* notice, this list of conditions and the following disclaimer in the * +* documentation and/or other materials provided with the * +* distribution. * +* * +* * Neither the name of the Intel Corporation nor the names of its * +* contributors may be used to endorse or promote products derived from * +* this software without specific prior written permission. * +* * +* * +* THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION ""AS IS"" AND ANY * +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * +* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR * +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * +* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * +* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +****************************************************************************** +* Developers and authors: * +* Shay Gueron (1, 2), and Vlad Krasnov (1) * +* (1) Intel Corporation, Israel Development Center, Haifa, Israel * +* (2) University of Haifa, Israel * +*****************************************************************************/ + +#include + +#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) + +#include "rsaz_exp.h" + +#include + +#include "../internal.h" + + +/* + * See crypto/bn/asm/rsaz-avx2.pl for further details. + */ +void rsaz_1024_norm2red_avx2(void *red,const void *norm); +void rsaz_1024_mul_avx2(void *ret,const void *a,const void *b,const void *n,BN_ULONG k); +void rsaz_1024_sqr_avx2(void *ret,const void *a,const void *n,BN_ULONG k,int cnt); +void rsaz_1024_scatter5_avx2(void *tbl,const void *val,int i); +void rsaz_1024_gather5_avx2(void *val,const void *tbl,int i); +void rsaz_1024_red2norm_avx2(void *norm,const void *red); + +alignas(64) static const BN_ULONG one[40] = + {1,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; +alignas(64) static const BN_ULONG two80[40] = + {0,0,1<<22,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + +void RSAZ_1024_mod_exp_avx2(BN_ULONG result_norm[16], + const BN_ULONG base_norm[16], const BN_ULONG exponent[16], + const BN_ULONG m_norm[16], const BN_ULONG RR[16], BN_ULONG k0) +{ + alignas(64) uint8_t storage[(320 * 3) + (32 * 9 * 16)]; /* 5.5KB */ + unsigned char *a_inv, *m, *result, + *table_s = storage + (320 * 3), + *R2 = table_s; /* borrow */ + int index; + int wvalue; + + if (((((uintptr_t)storage & 4095) + 320) >> 12) != 0) { + result = storage; + a_inv = storage + 320; + m = storage + (320 * 2); /* should not cross page */ + } else { + m = storage; /* should not cross page */ + result = storage + 320; + a_inv = storage + (320 * 2); + } + + rsaz_1024_norm2red_avx2(m, m_norm); + rsaz_1024_norm2red_avx2(a_inv, base_norm); + rsaz_1024_norm2red_avx2(R2, RR); + + rsaz_1024_mul_avx2(R2, R2, R2, m, k0); + rsaz_1024_mul_avx2(R2, R2, two80, m, k0); + + /* table[0] = 1 */ + rsaz_1024_mul_avx2(result, R2, one, m, k0); + /* table[1] = a_inv^1 */ + rsaz_1024_mul_avx2(a_inv, a_inv, R2, m, k0); + + rsaz_1024_scatter5_avx2(table_s,result,0); + rsaz_1024_scatter5_avx2(table_s,a_inv,1); + + /* table[2] = a_inv^2 */ + rsaz_1024_sqr_avx2(result, a_inv, m, k0, 1); + rsaz_1024_scatter5_avx2(table_s,result,2); +#if 0 + /* this is almost 2x smaller and less than 1% slower */ + for (index=3; index<32; index++) { + rsaz_1024_mul_avx2(result, result, a_inv, m, k0); + rsaz_1024_scatter5_avx2(table_s,result,index); + } +#else + /* table[4] = a_inv^4 */ + rsaz_1024_sqr_avx2(result, result, m, k0, 1); + rsaz_1024_scatter5_avx2(table_s,result,4); + /* table[8] = a_inv^8 */ + rsaz_1024_sqr_avx2(result, result, m, k0, 1); + rsaz_1024_scatter5_avx2(table_s,result,8); + /* table[16] = a_inv^16 */ + rsaz_1024_sqr_avx2(result, result, m, k0, 1); + rsaz_1024_scatter5_avx2(table_s,result,16); + /* table[17] = a_inv^17 */ + rsaz_1024_mul_avx2(result, result, a_inv, m, k0); + rsaz_1024_scatter5_avx2(table_s,result,17); + + /* table[3] */ + rsaz_1024_gather5_avx2(result,table_s,2); + rsaz_1024_mul_avx2(result,result,a_inv,m,k0); + rsaz_1024_scatter5_avx2(table_s,result,3); + /* table[6] */ + rsaz_1024_sqr_avx2(result, result, m, k0, 1); + rsaz_1024_scatter5_avx2(table_s,result,6); + /* table[12] */ + rsaz_1024_sqr_avx2(result, result, m, k0, 1); + rsaz_1024_scatter5_avx2(table_s,result,12); + /* table[24] */ + rsaz_1024_sqr_avx2(result, result, m, k0, 1); + rsaz_1024_scatter5_avx2(table_s,result,24); + /* table[25] */ + rsaz_1024_mul_avx2(result, result, a_inv, m, k0); + rsaz_1024_scatter5_avx2(table_s,result,25); + + /* table[5] */ + rsaz_1024_gather5_avx2(result,table_s,4); + rsaz_1024_mul_avx2(result,result,a_inv,m,k0); + rsaz_1024_scatter5_avx2(table_s,result,5); + /* table[10] */ + rsaz_1024_sqr_avx2(result, result, m, k0, 1); + rsaz_1024_scatter5_avx2(table_s,result,10); + /* table[20] */ + rsaz_1024_sqr_avx2(result, result, m, k0, 1); + rsaz_1024_scatter5_avx2(table_s,result,20); + /* table[21] */ + rsaz_1024_mul_avx2(result, result, a_inv, m, k0); + rsaz_1024_scatter5_avx2(table_s,result,21); + + /* table[7] */ + rsaz_1024_gather5_avx2(result,table_s,6); + rsaz_1024_mul_avx2(result,result,a_inv,m,k0); + rsaz_1024_scatter5_avx2(table_s,result,7); + /* table[14] */ + rsaz_1024_sqr_avx2(result, result, m, k0, 1); + rsaz_1024_scatter5_avx2(table_s,result,14); + /* table[28] */ + rsaz_1024_sqr_avx2(result, result, m, k0, 1); + rsaz_1024_scatter5_avx2(table_s,result,28); + /* table[29] */ + rsaz_1024_mul_avx2(result, result, a_inv, m, k0); + rsaz_1024_scatter5_avx2(table_s,result,29); + + /* table[9] */ + rsaz_1024_gather5_avx2(result,table_s,8); + rsaz_1024_mul_avx2(result,result,a_inv,m,k0); + rsaz_1024_scatter5_avx2(table_s,result,9); + /* table[18] */ + rsaz_1024_sqr_avx2(result, result, m, k0, 1); + rsaz_1024_scatter5_avx2(table_s,result,18); + /* table[19] */ + rsaz_1024_mul_avx2(result, result, a_inv, m, k0); + rsaz_1024_scatter5_avx2(table_s,result,19); + + /* table[11] */ + rsaz_1024_gather5_avx2(result,table_s,10); + rsaz_1024_mul_avx2(result,result,a_inv,m,k0); + rsaz_1024_scatter5_avx2(table_s,result,11); + /* table[22] */ + rsaz_1024_sqr_avx2(result, result, m, k0, 1); + rsaz_1024_scatter5_avx2(table_s,result,22); + /* table[23] */ + rsaz_1024_mul_avx2(result, result, a_inv, m, k0); + rsaz_1024_scatter5_avx2(table_s,result,23); + + /* table[13] */ + rsaz_1024_gather5_avx2(result,table_s,12); + rsaz_1024_mul_avx2(result,result,a_inv,m,k0); + rsaz_1024_scatter5_avx2(table_s,result,13); + /* table[26] */ + rsaz_1024_sqr_avx2(result, result, m, k0, 1); + rsaz_1024_scatter5_avx2(table_s,result,26); + /* table[27] */ + rsaz_1024_mul_avx2(result, result, a_inv, m, k0); + rsaz_1024_scatter5_avx2(table_s,result,27); + + /* table[15] */ + rsaz_1024_gather5_avx2(result,table_s,14); + rsaz_1024_mul_avx2(result,result,a_inv,m,k0); + rsaz_1024_scatter5_avx2(table_s,result,15); + /* table[30] */ + rsaz_1024_sqr_avx2(result, result, m, k0, 1); + rsaz_1024_scatter5_avx2(table_s,result,30); + /* table[31] */ + rsaz_1024_mul_avx2(result, result, a_inv, m, k0); + rsaz_1024_scatter5_avx2(table_s,result,31); +#endif + + const uint8_t *p_str = (const uint8_t *)exponent; + + /* load first window */ + wvalue = p_str[127] >> 3; + rsaz_1024_gather5_avx2(result,table_s,wvalue); + + index = 1014; + + while(index > -1) { /* loop for the remaining 127 windows */ + + rsaz_1024_sqr_avx2(result, result, m, k0, 5); + + wvalue = *((const unsigned short*)&p_str[index / 8]); + wvalue = (wvalue>> (index%8)) & 31; + index-=5; + + rsaz_1024_gather5_avx2(a_inv,table_s,wvalue); /* borrow a_inv */ + rsaz_1024_mul_avx2(result, result, a_inv, m, k0); + } + + /* square four times */ + rsaz_1024_sqr_avx2(result, result, m, k0, 4); + + wvalue = p_str[0] & 15; + + rsaz_1024_gather5_avx2(a_inv,table_s,wvalue); /* borrow a_inv */ + rsaz_1024_mul_avx2(result, result, a_inv, m, k0); + + /* from Montgomery */ + rsaz_1024_mul_avx2(result, result, one, m, k0); + + rsaz_1024_red2norm_avx2(result_norm, result); + + OPENSSL_cleanse(storage,sizeof(storage)); +} + +/* + * See crypto/bn/rsaz-x86_64.pl for further details. + */ +void rsaz_512_mul(void *ret,const void *a,const void *b,const void *n,BN_ULONG k); +void rsaz_512_mul_scatter4(void *ret,const void *a,const void *n,BN_ULONG k,const void *tbl,unsigned int power); +void rsaz_512_mul_gather4(void *ret,const void *a,const void *tbl,const void *n,BN_ULONG k,unsigned int power); +void rsaz_512_mul_by_one(void *ret,const void *a,const void *n,BN_ULONG k); +void rsaz_512_sqr(void *ret,const void *a,const void *n,BN_ULONG k,int cnt); +void rsaz_512_scatter4(void *tbl, const BN_ULONG *val, int power); +void rsaz_512_gather4(BN_ULONG *val, const void *tbl, int power); + +void RSAZ_512_mod_exp(BN_ULONG result[8], + const BN_ULONG base[8], const BN_ULONG exponent[8], + const BN_ULONG m[8], BN_ULONG k0, const BN_ULONG RR[8]) +{ + alignas(64) uint8_t storage[(16*8*8) + (64 * 2)]; /* 1.2KB */ + unsigned char *table = storage; + BN_ULONG *a_inv = (BN_ULONG *)(table+16*8*8), + *temp = (BN_ULONG *)(table+16*8*8+8*8); + int index; + unsigned int wvalue; + + /* table[0] = 1_inv */ + temp[0] = 0-m[0]; temp[1] = ~m[1]; + temp[2] = ~m[2]; temp[3] = ~m[3]; + temp[4] = ~m[4]; temp[5] = ~m[5]; + temp[6] = ~m[6]; temp[7] = ~m[7]; + rsaz_512_scatter4(table, temp, 0); + + /* table [1] = a_inv^1 */ + rsaz_512_mul(a_inv, base, RR, m, k0); + rsaz_512_scatter4(table, a_inv, 1); + + /* table [2] = a_inv^2 */ + rsaz_512_sqr(temp, a_inv, m, k0, 1); + rsaz_512_scatter4(table, temp, 2); + + for (index=3; index<16; index++) + rsaz_512_mul_scatter4(temp, a_inv, m, k0, table, index); + + const uint8_t *p_str = (const uint8_t *)exponent; + + /* load first window */ + wvalue = p_str[63]; + + rsaz_512_gather4(temp, table, wvalue>>4); + rsaz_512_sqr(temp, temp, m, k0, 4); + rsaz_512_mul_gather4(temp, temp, table, m, k0, wvalue&0xf); + + for (index=62; index>=0; index--) { + wvalue = p_str[index]; + + rsaz_512_sqr(temp, temp, m, k0, 4); + rsaz_512_mul_gather4(temp, temp, table, m, k0, wvalue>>4); + + rsaz_512_sqr(temp, temp, m, k0, 4); + rsaz_512_mul_gather4(temp, temp, table, m, k0, wvalue&0x0f); + } + + /* from Montgomery */ + rsaz_512_mul_by_one(result, temp, m, k0); + + OPENSSL_cleanse(storage,sizeof(storage)); +} + +#endif /* OPENSSL_X86_64 */ diff --git a/external/boringssl/crypto/bn/rsaz_exp.h b/external/boringssl/crypto/bn/rsaz_exp.h new file mode 100644 index 0000000000..c752b45f21 --- /dev/null +++ b/external/boringssl/crypto/bn/rsaz_exp.h @@ -0,0 +1,56 @@ +/***************************************************************************** +* * +* Copyright (c) 2012, Intel Corporation * +* * +* All rights reserved. * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are * +* met: * +* * +* * Redistributions of source code must retain the above copyright * +* notice, this list of conditions and the following disclaimer. * +* * +* * Redistributions in binary form must reproduce the above copyright * +* notice, this list of conditions and the following disclaimer in the * +* documentation and/or other materials provided with the * +* distribution. * +* * +* * Neither the name of the Intel Corporation nor the names of its * +* contributors may be used to endorse or promote products derived from * +* this software without specific prior written permission. * +* * +* * +* THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION ""AS IS"" AND ANY * +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * +* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR * +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * +* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * +* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +****************************************************************************** +* Developers and authors: * +* Shay Gueron (1, 2), and Vlad Krasnov (1) * +* (1) Intel Corporation, Israel Development Center, Haifa, Israel * +* (2) University of Haifa, Israel * +*****************************************************************************/ + +#ifndef RSAZ_EXP_H +#define RSAZ_EXP_H + +#include + +void RSAZ_1024_mod_exp_avx2(BN_ULONG result[16], + const BN_ULONG base_norm[16], const BN_ULONG exponent[16], + const BN_ULONG m_norm[16], const BN_ULONG RR[16], BN_ULONG k0); +int rsaz_avx2_eligible(void); + +void RSAZ_512_mod_exp(BN_ULONG result[8], + const BN_ULONG base_norm[8], const BN_ULONG exponent[8], + const BN_ULONG m_norm[8], BN_ULONG k0, const BN_ULONG RR[8]); +#endif diff --git a/external/boringssl/crypto/bn/shift.c b/external/boringssl/crypto/bn/shift.c new file mode 100644 index 0000000000..defec92918 --- /dev/null +++ b/external/boringssl/crypto/bn/shift.c @@ -0,0 +1,299 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include + +#include "internal.h" + + +int BN_lshift(BIGNUM *r, const BIGNUM *a, int n) { + int i, nw, lb, rb; + BN_ULONG *t, *f; + BN_ULONG l; + + if (n < 0) { + OPENSSL_PUT_ERROR(BN, BN_R_NEGATIVE_NUMBER); + return 0; + } + + r->neg = a->neg; + nw = n / BN_BITS2; + if (bn_wexpand(r, a->top + nw + 1) == NULL) { + return 0; + } + lb = n % BN_BITS2; + rb = BN_BITS2 - lb; + f = a->d; + t = r->d; + t[a->top + nw] = 0; + if (lb == 0) { + for (i = a->top - 1; i >= 0; i--) { + t[nw + i] = f[i]; + } + } else { + for (i = a->top - 1; i >= 0; i--) { + l = f[i]; + t[nw + i + 1] |= (l >> rb) & BN_MASK2; + t[nw + i] = (l << lb) & BN_MASK2; + } + } + memset(t, 0, nw * sizeof(t[0])); + r->top = a->top + nw + 1; + bn_correct_top(r); + + return 1; +} + +int BN_lshift1(BIGNUM *r, const BIGNUM *a) { + BN_ULONG *ap, *rp, t, c; + int i; + + if (r != a) { + r->neg = a->neg; + if (bn_wexpand(r, a->top + 1) == NULL) { + return 0; + } + r->top = a->top; + } else { + if (bn_wexpand(r, a->top + 1) == NULL) { + return 0; + } + } + ap = a->d; + rp = r->d; + c = 0; + for (i = 0; i < a->top; i++) { + t = *(ap++); + *(rp++) = ((t << 1) | c) & BN_MASK2; + c = (t & BN_TBIT) ? 1 : 0; + } + if (c) { + *rp = 1; + r->top++; + } + + return 1; +} + +int BN_rshift(BIGNUM *r, const BIGNUM *a, int n) { + int i, j, nw, lb, rb; + BN_ULONG *t, *f; + BN_ULONG l, tmp; + + if (n < 0) { + OPENSSL_PUT_ERROR(BN, BN_R_NEGATIVE_NUMBER); + return 0; + } + + nw = n / BN_BITS2; + rb = n % BN_BITS2; + lb = BN_BITS2 - rb; + if (nw >= a->top || a->top == 0) { + BN_zero(r); + return 1; + } + i = (BN_num_bits(a) - n + (BN_BITS2 - 1)) / BN_BITS2; + if (r != a) { + r->neg = a->neg; + if (bn_wexpand(r, i) == NULL) { + return 0; + } + } else { + if (n == 0) { + return 1; /* or the copying loop will go berserk */ + } + } + + f = &(a->d[nw]); + t = r->d; + j = a->top - nw; + r->top = i; + + if (rb == 0) { + for (i = j; i != 0; i--) { + *(t++) = *(f++); + } + } else { + l = *(f++); + for (i = j - 1; i != 0; i--) { + tmp = (l >> rb) & BN_MASK2; + l = *(f++); + *(t++) = (tmp | (l << lb)) & BN_MASK2; + } + if ((l = (l >> rb) & BN_MASK2)) { + *(t) = l; + } + } + + return 1; +} + +int BN_rshift1(BIGNUM *r, const BIGNUM *a) { + BN_ULONG *ap, *rp, t, c; + int i, j; + + if (BN_is_zero(a)) { + BN_zero(r); + return 1; + } + i = a->top; + ap = a->d; + j = i - (ap[i - 1] == 1); + if (a != r) { + if (bn_wexpand(r, j) == NULL) { + return 0; + } + r->neg = a->neg; + } + rp = r->d; + t = ap[--i]; + c = (t & 1) ? BN_TBIT : 0; + if (t >>= 1) { + rp[i] = t; + } + while (i > 0) { + t = ap[--i]; + rp[i] = ((t >> 1) & BN_MASK2) | c; + c = (t & 1) ? BN_TBIT : 0; + } + r->top = j; + + return 1; +} + +int BN_set_bit(BIGNUM *a, int n) { + int i, j, k; + + if (n < 0) { + return 0; + } + + i = n / BN_BITS2; + j = n % BN_BITS2; + if (a->top <= i) { + if (bn_wexpand(a, i + 1) == NULL) { + return 0; + } + for (k = a->top; k < i + 1; k++) { + a->d[k] = 0; + } + a->top = i + 1; + } + + a->d[i] |= (((BN_ULONG)1) << j); + + return 1; +} + +int BN_clear_bit(BIGNUM *a, int n) { + int i, j; + + if (n < 0) { + return 0; + } + + i = n / BN_BITS2; + j = n % BN_BITS2; + if (a->top <= i) { + return 0; + } + + a->d[i] &= (~(((BN_ULONG)1) << j)); + bn_correct_top(a); + return 1; +} + +int BN_is_bit_set(const BIGNUM *a, int n) { + int i, j; + + if (n < 0) { + return 0; + } + i = n / BN_BITS2; + j = n % BN_BITS2; + if (a->top <= i) { + return 0; + } + + return (a->d[i]>>j)&1; +} + +int BN_mask_bits(BIGNUM *a, int n) { + int b, w; + + if (n < 0) { + return 0; + } + + w = n / BN_BITS2; + b = n % BN_BITS2; + if (w >= a->top) { + return 0; + } + if (b == 0) { + a->top = w; + } else { + a->top = w + 1; + a->d[w] &= ~(BN_MASK2 << b); + } + + bn_correct_top(a); + return 1; +} diff --git a/external/boringssl/crypto/bn/sqrt.c b/external/boringssl/crypto/bn/sqrt.c new file mode 100644 index 0000000000..2ed66c22c7 --- /dev/null +++ b/external/boringssl/crypto/bn/sqrt.c @@ -0,0 +1,505 @@ +/* Written by Lenka Fibikova + * and Bodo Moeller for the OpenSSL project. */ +/* ==================================================================== + * Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include + + +/* Returns 'ret' such that + * ret^2 == a (mod p), + * using the Tonelli/Shanks algorithm (cf. Henri Cohen, "A Course + * in Algebraic Computational Number Theory", algorithm 1.5.1). + * 'p' must be prime! */ +BIGNUM *BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) { + BIGNUM *ret = in; + int err = 1; + int r; + BIGNUM *A, *b, *q, *t, *x, *y; + int e, i, j; + + if (!BN_is_odd(p) || BN_abs_is_word(p, 1)) { + if (BN_abs_is_word(p, 2)) { + if (ret == NULL) { + ret = BN_new(); + } + if (ret == NULL) { + goto end; + } + if (!BN_set_word(ret, BN_is_bit_set(a, 0))) { + if (ret != in) { + BN_free(ret); + } + return NULL; + } + return ret; + } + + OPENSSL_PUT_ERROR(BN, BN_R_P_IS_NOT_PRIME); + return (NULL); + } + + if (BN_is_zero(a) || BN_is_one(a)) { + if (ret == NULL) { + ret = BN_new(); + } + if (ret == NULL) { + goto end; + } + if (!BN_set_word(ret, BN_is_one(a))) { + if (ret != in) { + BN_free(ret); + } + return NULL; + } + return ret; + } + + BN_CTX_start(ctx); + A = BN_CTX_get(ctx); + b = BN_CTX_get(ctx); + q = BN_CTX_get(ctx); + t = BN_CTX_get(ctx); + x = BN_CTX_get(ctx); + y = BN_CTX_get(ctx); + if (y == NULL) { + goto end; + } + + if (ret == NULL) { + ret = BN_new(); + } + if (ret == NULL) { + goto end; + } + + /* A = a mod p */ + if (!BN_nnmod(A, a, p, ctx)) { + goto end; + } + + /* now write |p| - 1 as 2^e*q where q is odd */ + e = 1; + while (!BN_is_bit_set(p, e)) { + e++; + } + /* we'll set q later (if needed) */ + + if (e == 1) { + /* The easy case: (|p|-1)/2 is odd, so 2 has an inverse + * modulo (|p|-1)/2, and square roots can be computed + * directly by modular exponentiation. + * We have + * 2 * (|p|+1)/4 == 1 (mod (|p|-1)/2), + * so we can use exponent (|p|+1)/4, i.e. (|p|-3)/4 + 1. + */ + if (!BN_rshift(q, p, 2)) { + goto end; + } + q->neg = 0; + if (!BN_add_word(q, 1) || + !BN_mod_exp(ret, A, q, p, ctx)) { + goto end; + } + err = 0; + goto vrfy; + } + + if (e == 2) { + /* |p| == 5 (mod 8) + * + * In this case 2 is always a non-square since + * Legendre(2,p) = (-1)^((p^2-1)/8) for any odd prime. + * So if a really is a square, then 2*a is a non-square. + * Thus for + * b := (2*a)^((|p|-5)/8), + * i := (2*a)*b^2 + * we have + * i^2 = (2*a)^((1 + (|p|-5)/4)*2) + * = (2*a)^((p-1)/2) + * = -1; + * so if we set + * x := a*b*(i-1), + * then + * x^2 = a^2 * b^2 * (i^2 - 2*i + 1) + * = a^2 * b^2 * (-2*i) + * = a*(-i)*(2*a*b^2) + * = a*(-i)*i + * = a. + * + * (This is due to A.O.L. Atkin, + * , + * November 1992.) + */ + + /* t := 2*a */ + if (!BN_mod_lshift1_quick(t, A, p)) { + goto end; + } + + /* b := (2*a)^((|p|-5)/8) */ + if (!BN_rshift(q, p, 3)) { + goto end; + } + q->neg = 0; + if (!BN_mod_exp(b, t, q, p, ctx)) { + goto end; + } + + /* y := b^2 */ + if (!BN_mod_sqr(y, b, p, ctx)) { + goto end; + } + + /* t := (2*a)*b^2 - 1*/ + if (!BN_mod_mul(t, t, y, p, ctx) || + !BN_sub_word(t, 1)) { + goto end; + } + + /* x = a*b*t */ + if (!BN_mod_mul(x, A, b, p, ctx) || + !BN_mod_mul(x, x, t, p, ctx)) { + goto end; + } + + if (!BN_copy(ret, x)) { + goto end; + } + err = 0; + goto vrfy; + } + + /* e > 2, so we really have to use the Tonelli/Shanks algorithm. + * First, find some y that is not a square. */ + if (!BN_copy(q, p)) { + goto end; /* use 'q' as temp */ + } + q->neg = 0; + i = 2; + do { + /* For efficiency, try small numbers first; + * if this fails, try random numbers. + */ + if (i < 22) { + if (!BN_set_word(y, i)) { + goto end; + } + } else { + if (!BN_pseudo_rand(y, BN_num_bits(p), 0, 0)) { + goto end; + } + if (BN_ucmp(y, p) >= 0) { + if (!(p->neg ? BN_add : BN_sub)(y, y, p)) { + goto end; + } + } + /* now 0 <= y < |p| */ + if (BN_is_zero(y)) { + if (!BN_set_word(y, i)) { + goto end; + } + } + } + + r = BN_kronecker(y, q, ctx); /* here 'q' is |p| */ + if (r < -1) { + goto end; + } + if (r == 0) { + /* m divides p */ + OPENSSL_PUT_ERROR(BN, BN_R_P_IS_NOT_PRIME); + goto end; + } + } while (r == 1 && ++i < 82); + + if (r != -1) { + /* Many rounds and still no non-square -- this is more likely + * a bug than just bad luck. + * Even if p is not prime, we should have found some y + * such that r == -1. + */ + OPENSSL_PUT_ERROR(BN, BN_R_TOO_MANY_ITERATIONS); + goto end; + } + + /* Here's our actual 'q': */ + if (!BN_rshift(q, q, e)) { + goto end; + } + + /* Now that we have some non-square, we can find an element + * of order 2^e by computing its q'th power. */ + if (!BN_mod_exp(y, y, q, p, ctx)) { + goto end; + } + if (BN_is_one(y)) { + OPENSSL_PUT_ERROR(BN, BN_R_P_IS_NOT_PRIME); + goto end; + } + + /* Now we know that (if p is indeed prime) there is an integer + * k, 0 <= k < 2^e, such that + * + * a^q * y^k == 1 (mod p). + * + * As a^q is a square and y is not, k must be even. + * q+1 is even, too, so there is an element + * + * X := a^((q+1)/2) * y^(k/2), + * + * and it satisfies + * + * X^2 = a^q * a * y^k + * = a, + * + * so it is the square root that we are looking for. + */ + + /* t := (q-1)/2 (note that q is odd) */ + if (!BN_rshift1(t, q)) { + goto end; + } + + /* x := a^((q-1)/2) */ + if (BN_is_zero(t)) /* special case: p = 2^e + 1 */ + { + if (!BN_nnmod(t, A, p, ctx)) { + goto end; + } + if (BN_is_zero(t)) { + /* special case: a == 0 (mod p) */ + BN_zero(ret); + err = 0; + goto end; + } else if (!BN_one(x)) { + goto end; + } + } else { + if (!BN_mod_exp(x, A, t, p, ctx)) { + goto end; + } + if (BN_is_zero(x)) { + /* special case: a == 0 (mod p) */ + BN_zero(ret); + err = 0; + goto end; + } + } + + /* b := a*x^2 (= a^q) */ + if (!BN_mod_sqr(b, x, p, ctx) || + !BN_mod_mul(b, b, A, p, ctx)) { + goto end; + } + + /* x := a*x (= a^((q+1)/2)) */ + if (!BN_mod_mul(x, x, A, p, ctx)) { + goto end; + } + + while (1) { + /* Now b is a^q * y^k for some even k (0 <= k < 2^E + * where E refers to the original value of e, which we + * don't keep in a variable), and x is a^((q+1)/2) * y^(k/2). + * + * We have a*b = x^2, + * y^2^(e-1) = -1, + * b^2^(e-1) = 1. + */ + + if (BN_is_one(b)) { + if (!BN_copy(ret, x)) { + goto end; + } + err = 0; + goto vrfy; + } + + + /* find smallest i such that b^(2^i) = 1 */ + i = 1; + if (!BN_mod_sqr(t, b, p, ctx)) { + goto end; + } + while (!BN_is_one(t)) { + i++; + if (i == e) { + OPENSSL_PUT_ERROR(BN, BN_R_NOT_A_SQUARE); + goto end; + } + if (!BN_mod_mul(t, t, t, p, ctx)) { + goto end; + } + } + + + /* t := y^2^(e - i - 1) */ + if (!BN_copy(t, y)) { + goto end; + } + for (j = e - i - 1; j > 0; j--) { + if (!BN_mod_sqr(t, t, p, ctx)) { + goto end; + } + } + if (!BN_mod_mul(y, t, t, p, ctx) || + !BN_mod_mul(x, x, t, p, ctx) || + !BN_mod_mul(b, b, y, p, ctx)) { + goto end; + } + e = i; + } + +vrfy: + if (!err) { + /* verify the result -- the input might have been not a square + * (test added in 0.9.8) */ + + if (!BN_mod_sqr(x, ret, p, ctx)) { + err = 1; + } + + if (!err && 0 != BN_cmp(x, A)) { + OPENSSL_PUT_ERROR(BN, BN_R_NOT_A_SQUARE); + err = 1; + } + } + +end: + if (err) { + if (ret != in) { + BN_clear_free(ret); + } + ret = NULL; + } + BN_CTX_end(ctx); + return ret; +} + +int BN_sqrt(BIGNUM *out_sqrt, const BIGNUM *in, BN_CTX *ctx) { + BIGNUM *estimate, *tmp, *delta, *last_delta, *tmp2; + int ok = 0, last_delta_valid = 0; + + if (in->neg) { + OPENSSL_PUT_ERROR(BN, BN_R_NEGATIVE_NUMBER); + return 0; + } + if (BN_is_zero(in)) { + BN_zero(out_sqrt); + return 1; + } + + BN_CTX_start(ctx); + if (out_sqrt == in) { + estimate = BN_CTX_get(ctx); + } else { + estimate = out_sqrt; + } + tmp = BN_CTX_get(ctx); + last_delta = BN_CTX_get(ctx); + delta = BN_CTX_get(ctx); + if (estimate == NULL || tmp == NULL || last_delta == NULL || delta == NULL) { + OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE); + goto err; + } + + /* We estimate that the square root of an n-bit number is 2^{n/2}. */ + BN_lshift(estimate, BN_value_one(), BN_num_bits(in)/2); + + /* This is Newton's method for finding a root of the equation |estimate|^2 - + * |in| = 0. */ + for (;;) { + /* |estimate| = 1/2 * (|estimate| + |in|/|estimate|) */ + if (!BN_div(tmp, NULL, in, estimate, ctx) || + !BN_add(tmp, tmp, estimate) || + !BN_rshift1(estimate, tmp) || + /* |tmp| = |estimate|^2 */ + !BN_sqr(tmp, estimate, ctx) || + /* |delta| = |in| - |tmp| */ + !BN_sub(delta, in, tmp)) { + OPENSSL_PUT_ERROR(BN, ERR_R_BN_LIB); + goto err; + } + + delta->neg = 0; + /* The difference between |in| and |estimate| squared is required to always + * decrease. This ensures that the loop always terminates, but I don't have + * a proof that it always finds the square root for a given square. */ + if (last_delta_valid && BN_cmp(delta, last_delta) >= 0) { + break; + } + + last_delta_valid = 1; + + tmp2 = last_delta; + last_delta = delta; + delta = tmp2; + } + + if (BN_cmp(tmp, in) != 0) { + OPENSSL_PUT_ERROR(BN, BN_R_NOT_A_SQUARE); + goto err; + } + + ok = 1; + +err: + if (ok && out_sqrt == in && !BN_copy(out_sqrt, estimate)) { + ok = 0; + } + BN_CTX_end(ctx); + return ok; +} diff --git a/external/boringssl/crypto/buf/CMakeLists.txt b/external/boringssl/crypto/buf/CMakeLists.txt new file mode 100644 index 0000000000..63f10255b0 --- /dev/null +++ b/external/boringssl/crypto/buf/CMakeLists.txt @@ -0,0 +1,9 @@ +include_directories(../../include) + +add_library( + buf + + OBJECT + + buf.c +) diff --git a/external/boringssl/crypto/buf/buf.c b/external/boringssl/crypto/buf/buf.c new file mode 100644 index 0000000000..efe9952af5 --- /dev/null +++ b/external/boringssl/crypto/buf/buf.c @@ -0,0 +1,239 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include +#include + + +BUF_MEM *BUF_MEM_new(void) { + BUF_MEM *ret; + + ret = OPENSSL_malloc(sizeof(BUF_MEM)); + if (ret == NULL) { + OPENSSL_PUT_ERROR(BUF, ERR_R_MALLOC_FAILURE); + return NULL; + } + + memset(ret, 0, sizeof(BUF_MEM)); + return ret; +} + +void BUF_MEM_free(BUF_MEM *buf) { + if (buf == NULL) { + return; + } + + if (buf->data != NULL) { + OPENSSL_cleanse(buf->data, buf->max); + OPENSSL_free(buf->data); + } + + OPENSSL_free(buf); +} + +static int buf_mem_reserve(BUF_MEM *buf, size_t cap, int clean) { + if (buf->max >= cap) { + return 1; + } + + size_t n = cap + 3; + if (n < cap) { + /* overflow */ + OPENSSL_PUT_ERROR(BUF, ERR_R_MALLOC_FAILURE); + return 0; + } + n = n / 3; + size_t alloc_size = n * 4; + if (alloc_size / 4 != n) { + /* overflow */ + OPENSSL_PUT_ERROR(BUF, ERR_R_MALLOC_FAILURE); + return 0; + } + + char *new_buf; + if (buf->data == NULL) { + new_buf = OPENSSL_malloc(alloc_size); + } else { + if (clean) { + new_buf = OPENSSL_realloc_clean(buf->data, buf->max, alloc_size); + } else { + new_buf = OPENSSL_realloc(buf->data, alloc_size); + } + } + + if (new_buf == NULL) { + OPENSSL_PUT_ERROR(BUF, ERR_R_MALLOC_FAILURE); + return 0; + } + + buf->data = new_buf; + buf->max = alloc_size; + return 1; +} + +int BUF_MEM_reserve(BUF_MEM *buf, size_t cap) { + return buf_mem_reserve(buf, cap, 0 /* don't clear old buffer contents. */); +} + +static size_t buf_mem_grow(BUF_MEM *buf, size_t len, int clean) { + if (!buf_mem_reserve(buf, len, clean)) { + return 0; + } + if (buf->length < len) { + memset(&buf->data[buf->length], 0, len - buf->length); + } + buf->length = len; + return len; +} + +size_t BUF_MEM_grow(BUF_MEM *buf, size_t len) { + return buf_mem_grow(buf, len, 0 /* don't clear old buffer contents. */); +} + +size_t BUF_MEM_grow_clean(BUF_MEM *buf, size_t len) { + return buf_mem_grow(buf, len, 1 /* clear old buffer contents. */); +} + +char *BUF_strdup(const char *buf) { + if (buf == NULL) { + return NULL; + } + + return BUF_strndup(buf, strlen(buf)); +} + +size_t BUF_strnlen(const char *str, size_t max_len) { + size_t i; + + for (i = 0; i < max_len; i++) { + if (str[i] == 0) { + break; + } + } + + return i; +} + +char *BUF_strndup(const char *buf, size_t size) { + char *ret; + size_t alloc_size; + + if (buf == NULL) { + return NULL; + } + + size = BUF_strnlen(buf, size); + + alloc_size = size + 1; + if (alloc_size < size) { + /* overflow */ + OPENSSL_PUT_ERROR(BUF, ERR_R_MALLOC_FAILURE); + return NULL; + } + ret = OPENSSL_malloc(alloc_size); + if (ret == NULL) { + OPENSSL_PUT_ERROR(BUF, ERR_R_MALLOC_FAILURE); + return NULL; + } + + memcpy(ret, buf, size); + ret[size] = '\0'; + return ret; +} + +size_t BUF_strlcpy(char *dst, const char *src, size_t dst_size) { + size_t l = 0; + + for (; dst_size > 1 && *src; dst_size--) { + *dst++ = *src++; + l++; + } + + if (dst_size) { + *dst = 0; + } + + return l + strlen(src); +} + +size_t BUF_strlcat(char *dst, const char *src, size_t dst_size) { + size_t l = 0; + for (; dst_size > 0 && *dst; dst_size--, dst++) { + l++; + } + return l + BUF_strlcpy(dst, src, dst_size); +} + +void *BUF_memdup(const void *data, size_t dst_size) { + void *ret; + + if (dst_size == 0) { + return NULL; + } + + ret = OPENSSL_malloc(dst_size); + if (ret == NULL) { + OPENSSL_PUT_ERROR(BUF, ERR_R_MALLOC_FAILURE); + return NULL; + } + + memcpy(ret, data, dst_size); + return ret; +} diff --git a/external/boringssl/crypto/bytestring/CMakeLists.txt b/external/boringssl/crypto/bytestring/CMakeLists.txt new file mode 100644 index 0000000000..a1964b2eb7 --- /dev/null +++ b/external/boringssl/crypto/bytestring/CMakeLists.txt @@ -0,0 +1,25 @@ +include_directories(../../include) + +add_library( + bytestring + + OBJECT + + asn1_compat.c + ber.c + cbs.c + cbb.c +) + +if(ENABLE_TESTS) +add_executable( + bytestring_test + + bytestring_test.cc + + $ +) + +target_link_libraries(bytestring_test crypto) +add_dependencies(all_tests bytestring_test) +endif() diff --git a/external/boringssl/crypto/bytestring/asn1_compat.c b/external/boringssl/crypto/bytestring/asn1_compat.c new file mode 100644 index 0000000000..b17d2d1219 --- /dev/null +++ b/external/boringssl/crypto/bytestring/asn1_compat.c @@ -0,0 +1,51 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + + +#include + +#include +#include +#include + +#include + +#include "internal.h" + + +int CBB_finish_i2d(CBB *cbb, uint8_t **outp) { + assert(cbb->base->can_resize); + + uint8_t *der; + size_t der_len; + if (!CBB_finish(cbb, &der, &der_len)) { + CBB_cleanup(cbb); + return -1; + } + if (der_len > INT_MAX) { + OPENSSL_free(der); + return -1; + } + if (outp != NULL) { + if (*outp == NULL) { + *outp = der; + der = NULL; + } else { + memcpy(*outp, der, der_len); + *outp += der_len; + } + } + OPENSSL_free(der); + return (int)der_len; +} diff --git a/external/boringssl/crypto/bytestring/ber.c b/external/boringssl/crypto/bytestring/ber.c new file mode 100644 index 0000000000..04fcac6aa3 --- /dev/null +++ b/external/boringssl/crypto/bytestring/ber.c @@ -0,0 +1,263 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include +#include + +#include "internal.h" + + +/* kMaxDepth is a just a sanity limit. The code should be such that the length + * of the input being processes always decreases. None the less, a very large + * input could otherwise cause the stack to overflow. */ +static const unsigned kMaxDepth = 2048; + +/* is_string_type returns one if |tag| is a string type and zero otherwise. It + * ignores the constructed bit. */ +static int is_string_type(unsigned tag) { + if ((tag & 0xc0) != 0) { + return 0; + } + switch (tag & 0x1f) { + case CBS_ASN1_BITSTRING: + case CBS_ASN1_OCTETSTRING: + case CBS_ASN1_UTF8STRING: + case CBS_ASN1_NUMERICSTRING: + case CBS_ASN1_PRINTABLESTRING: + case CBS_ASN1_T16STRING: + case CBS_ASN1_VIDEOTEXSTRING: + case CBS_ASN1_IA5STRING: + case CBS_ASN1_GRAPHICSTRING: + case CBS_ASN1_VISIBLESTRING: + case CBS_ASN1_GENERALSTRING: + case CBS_ASN1_UNIVERSALSTRING: + case CBS_ASN1_BMPSTRING: + return 1; + default: + return 0; + } +} + +/* cbs_find_ber walks an ASN.1 structure in |orig_in| and sets |*ber_found| + * depending on whether an indefinite length element or constructed string was + * found. The value of |orig_in| is not changed. It returns one on success (i.e. + * |*ber_found| was set) and zero on error. */ +static int cbs_find_ber(const CBS *orig_in, char *ber_found, unsigned depth) { + CBS in; + + if (depth > kMaxDepth) { + return 0; + } + + CBS_init(&in, CBS_data(orig_in), CBS_len(orig_in)); + *ber_found = 0; + + while (CBS_len(&in) > 0) { + CBS contents; + unsigned tag; + size_t header_len; + + if (!CBS_get_any_ber_asn1_element(&in, &contents, &tag, &header_len)) { + return 0; + } + if (CBS_len(&contents) == header_len && + header_len > 0 && + CBS_data(&contents)[header_len-1] == 0x80) { + /* Found an indefinite-length element. */ + *ber_found = 1; + return 1; + } + if (tag & CBS_ASN1_CONSTRUCTED) { + if (is_string_type(tag)) { + /* Constructed strings are only legal in BER and require conversion. */ + *ber_found = 1; + return 1; + } + if (!CBS_skip(&contents, header_len) || + !cbs_find_ber(&contents, ber_found, depth + 1)) { + return 0; + } + } + } + + return 1; +} + +/* is_eoc returns true if |header_len| and |contents|, as returned by + * |CBS_get_any_ber_asn1_element|, indicate an "end of contents" (EOC) value. */ +static char is_eoc(size_t header_len, CBS *contents) { + return header_len == 2 && CBS_len(contents) == 2 && + memcmp(CBS_data(contents), "\x00\x00", 2) == 0; +} + +/* cbs_convert_ber reads BER data from |in| and writes DER data to |out|. If + * |string_tag| is non-zero, then all elements must match |string_tag| up to the + * constructed bit and primitive element bodies are written to |out| without + * element headers. This is used when concatenating the fragments of a + * constructed string. If |looking_for_eoc| is set then any EOC elements found + * will cause the function to return after consuming it. It returns one on + * success and zero on error. */ +static int cbs_convert_ber(CBS *in, CBB *out, unsigned string_tag, + char looking_for_eoc, unsigned depth) { + assert(!(string_tag & CBS_ASN1_CONSTRUCTED)); + + if (depth > kMaxDepth) { + return 0; + } + + while (CBS_len(in) > 0) { + CBS contents; + unsigned tag, child_string_tag = string_tag; + size_t header_len; + CBB *out_contents, out_contents_storage; + + if (!CBS_get_any_ber_asn1_element(in, &contents, &tag, &header_len)) { + return 0; + } + + if (is_eoc(header_len, &contents)) { + return looking_for_eoc; + } + + if (string_tag != 0) { + /* This is part of a constructed string. All elements must match + * |string_tag| up to the constructed bit and get appended to |out| + * without a child element. */ + if ((tag & ~CBS_ASN1_CONSTRUCTED) != string_tag) { + return 0; + } + out_contents = out; + } else { + unsigned out_tag = tag; + if ((tag & CBS_ASN1_CONSTRUCTED) && is_string_type(tag)) { + /* If a constructed string, clear the constructed bit and inform + * children to concatenate bodies. */ + out_tag &= ~CBS_ASN1_CONSTRUCTED; + child_string_tag = out_tag; + } + if (!CBB_add_asn1(out, &out_contents_storage, out_tag)) { + return 0; + } + out_contents = &out_contents_storage; + } + + if (CBS_len(&contents) == header_len && header_len > 0 && + CBS_data(&contents)[header_len - 1] == 0x80) { + /* This is an indefinite length element. */ + if (!cbs_convert_ber(in, out_contents, child_string_tag, + 1 /* looking for eoc */, depth + 1) || + !CBB_flush(out)) { + return 0; + } + continue; + } + + if (!CBS_skip(&contents, header_len)) { + return 0; + } + + if (tag & CBS_ASN1_CONSTRUCTED) { + /* Recurse into children. */ + if (!cbs_convert_ber(&contents, out_contents, child_string_tag, + 0 /* not looking for eoc */, depth + 1)) { + return 0; + } + } else { + /* Copy primitive contents as-is. */ + if (!CBB_add_bytes(out_contents, CBS_data(&contents), + CBS_len(&contents))) { + return 0; + } + } + + if (!CBB_flush(out)) { + return 0; + } + } + + return looking_for_eoc == 0; +} + +int CBS_asn1_ber_to_der(CBS *in, uint8_t **out, size_t *out_len) { + CBB cbb; + + /* First, do a quick walk to find any indefinite-length elements. Most of the + * time we hope that there aren't any and thus we can quickly return. */ + char conversion_needed; + if (!cbs_find_ber(in, &conversion_needed, 0)) { + return 0; + } + + if (!conversion_needed) { + *out = NULL; + *out_len = 0; + return 1; + } + + if (!CBB_init(&cbb, CBS_len(in)) || + !cbs_convert_ber(in, &cbb, 0, 0, 0) || + !CBB_finish(&cbb, out, out_len)) { + CBB_cleanup(&cbb); + return 0; + } + + return 1; +} + +int CBS_get_asn1_implicit_string(CBS *in, CBS *out, uint8_t **out_storage, + unsigned outer_tag, unsigned inner_tag) { + assert(!(outer_tag & CBS_ASN1_CONSTRUCTED)); + assert(!(inner_tag & CBS_ASN1_CONSTRUCTED)); + assert(is_string_type(inner_tag)); + + if (CBS_peek_asn1_tag(in, outer_tag)) { + /* Normal implicitly-tagged string. */ + *out_storage = NULL; + return CBS_get_asn1(in, out, outer_tag); + } + + /* Otherwise, try to parse an implicitly-tagged constructed string. + * |CBS_asn1_ber_to_der| is assumed to have run, so only allow one level deep + * of nesting. */ + CBB result; + CBS child; + if (!CBB_init(&result, CBS_len(in)) || + !CBS_get_asn1(in, &child, outer_tag | CBS_ASN1_CONSTRUCTED)) { + goto err; + } + + while (CBS_len(&child) > 0) { + CBS chunk; + if (!CBS_get_asn1(&child, &chunk, inner_tag) || + !CBB_add_bytes(&result, CBS_data(&chunk), CBS_len(&chunk))) { + goto err; + } + } + + uint8_t *data; + size_t len; + if (!CBB_finish(&result, &data, &len)) { + goto err; + } + + CBS_init(out, data, len); + *out_storage = data; + return 1; + +err: + CBB_cleanup(&result); + return 0; +} diff --git a/external/boringssl/crypto/bytestring/bytestring_test.cc b/external/boringssl/crypto/bytestring/bytestring_test.cc new file mode 100644 index 0000000000..e1d16f49c4 --- /dev/null +++ b/external/boringssl/crypto/bytestring/bytestring_test.cc @@ -0,0 +1,825 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#if !defined(__STDC_CONSTANT_MACROS) +#define __STDC_CONSTANT_MACROS +#endif + +#include +#include +#include + +#include + +#include +#include + +#include "internal.h" +#include "../test/scoped_types.h" + + +static bool TestSkip() { + static const uint8_t kData[] = {1, 2, 3}; + CBS data; + + CBS_init(&data, kData, sizeof(kData)); + return CBS_len(&data) == 3 && + CBS_skip(&data, 1) && + CBS_len(&data) == 2 && + CBS_skip(&data, 2) && + CBS_len(&data) == 0 && + !CBS_skip(&data, 1); +} + +static bool TestGetUint() { + static const uint8_t kData[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}; + uint8_t u8; + uint16_t u16; + uint32_t u32; + CBS data; + + CBS_init(&data, kData, sizeof(kData)); + return CBS_get_u8(&data, &u8) && + u8 == 1 && + CBS_get_u16(&data, &u16) && + u16 == 0x203 && + CBS_get_u24(&data, &u32) && + u32 == 0x40506 && + CBS_get_u32(&data, &u32) && + u32 == 0x708090a && + CBS_get_last_u8(&data, &u8) && + u8 == 0xb && + !CBS_get_u8(&data, &u8) && + !CBS_get_last_u8(&data, &u8); +} + +static bool TestGetPrefixed() { + static const uint8_t kData[] = {1, 2, 0, 2, 3, 4, 0, 0, 3, 3, 2, 1}; + uint8_t u8; + uint16_t u16; + uint32_t u32; + CBS data, prefixed; + + CBS_init(&data, kData, sizeof(kData)); + return CBS_get_u8_length_prefixed(&data, &prefixed) && + CBS_len(&prefixed) == 1 && + CBS_get_u8(&prefixed, &u8) && + u8 == 2 && + CBS_get_u16_length_prefixed(&data, &prefixed) && + CBS_len(&prefixed) == 2 && + CBS_get_u16(&prefixed, &u16) && + u16 == 0x304 && + CBS_get_u24_length_prefixed(&data, &prefixed) && + CBS_len(&prefixed) == 3 && + CBS_get_u24(&prefixed, &u32) && + u32 == 0x30201; +} + +static bool TestGetPrefixedBad() { + static const uint8_t kData1[] = {2, 1}; + static const uint8_t kData2[] = {0, 2, 1}; + static const uint8_t kData3[] = {0, 0, 2, 1}; + CBS data, prefixed; + + CBS_init(&data, kData1, sizeof(kData1)); + if (CBS_get_u8_length_prefixed(&data, &prefixed)) { + return false; + } + + CBS_init(&data, kData2, sizeof(kData2)); + if (CBS_get_u16_length_prefixed(&data, &prefixed)) { + return false; + } + + CBS_init(&data, kData3, sizeof(kData3)); + if (CBS_get_u24_length_prefixed(&data, &prefixed)) { + return false; + } + + return true; +} + +static bool TestGetASN1() { + static const uint8_t kData1[] = {0x30, 2, 1, 2}; + static const uint8_t kData2[] = {0x30, 3, 1, 2}; + static const uint8_t kData3[] = {0x30, 0x80}; + static const uint8_t kData4[] = {0x30, 0x81, 1, 1}; + static const uint8_t kData5[4 + 0x80] = {0x30, 0x82, 0, 0x80}; + static const uint8_t kData6[] = {0xa1, 3, 0x4, 1, 1}; + static const uint8_t kData7[] = {0xa1, 3, 0x4, 2, 1}; + static const uint8_t kData8[] = {0xa1, 3, 0x2, 1, 1}; + static const uint8_t kData9[] = {0xa1, 3, 0x2, 1, 0xff}; + + CBS data, contents; + int present; + uint64_t value; + + CBS_init(&data, kData1, sizeof(kData1)); + if (CBS_peek_asn1_tag(&data, 0x1) || + !CBS_peek_asn1_tag(&data, 0x30)) { + return false; + } + if (!CBS_get_asn1(&data, &contents, 0x30) || + CBS_len(&contents) != 2 || + memcmp(CBS_data(&contents), "\x01\x02", 2) != 0) { + return false; + } + + CBS_init(&data, kData2, sizeof(kData2)); + // data is truncated + if (CBS_get_asn1(&data, &contents, 0x30)) { + return false; + } + + CBS_init(&data, kData3, sizeof(kData3)); + // zero byte length of length + if (CBS_get_asn1(&data, &contents, 0x30)) { + return false; + } + + CBS_init(&data, kData4, sizeof(kData4)); + // long form mistakenly used. + if (CBS_get_asn1(&data, &contents, 0x30)) { + return false; + } + + CBS_init(&data, kData5, sizeof(kData5)); + // length takes too many bytes. + if (CBS_get_asn1(&data, &contents, 0x30)) { + return false; + } + + CBS_init(&data, kData1, sizeof(kData1)); + // wrong tag. + if (CBS_get_asn1(&data, &contents, 0x31)) { + return false; + } + + CBS_init(&data, NULL, 0); + // peek at empty data. + if (CBS_peek_asn1_tag(&data, 0x30)) { + return false; + } + + CBS_init(&data, NULL, 0); + // optional elements at empty data. + if (!CBS_get_optional_asn1(&data, &contents, &present, 0xa0) || + present || + !CBS_get_optional_asn1_octet_string(&data, &contents, &present, 0xa0) || + present || + CBS_len(&contents) != 0 || + !CBS_get_optional_asn1_octet_string(&data, &contents, NULL, 0xa0) || + CBS_len(&contents) != 0 || + !CBS_get_optional_asn1_uint64(&data, &value, 0xa0, 42) || + value != 42) { + return false; + } + + CBS_init(&data, kData6, sizeof(kData6)); + // optional element. + if (!CBS_get_optional_asn1(&data, &contents, &present, 0xa0) || + present || + !CBS_get_optional_asn1(&data, &contents, &present, 0xa1) || + !present || + CBS_len(&contents) != 3 || + memcmp(CBS_data(&contents), "\x04\x01\x01", 3) != 0) { + return false; + } + + CBS_init(&data, kData6, sizeof(kData6)); + // optional octet string. + if (!CBS_get_optional_asn1_octet_string(&data, &contents, &present, 0xa0) || + present || + CBS_len(&contents) != 0 || + !CBS_get_optional_asn1_octet_string(&data, &contents, &present, 0xa1) || + !present || + CBS_len(&contents) != 1 || + CBS_data(&contents)[0] != 1) { + return false; + } + + CBS_init(&data, kData7, sizeof(kData7)); + // invalid optional octet string. + if (CBS_get_optional_asn1_octet_string(&data, &contents, &present, 0xa1)) { + return false; + } + + CBS_init(&data, kData8, sizeof(kData8)); + // optional octet string. + if (!CBS_get_optional_asn1_uint64(&data, &value, 0xa0, 42) || + value != 42 || + !CBS_get_optional_asn1_uint64(&data, &value, 0xa1, 42) || + value != 1) { + return false; + } + + CBS_init(&data, kData9, sizeof(kData9)); + // invalid optional integer. + if (CBS_get_optional_asn1_uint64(&data, &value, 0xa1, 42)) { + return false; + } + + return true; +} + +static bool TestGetOptionalASN1Bool() { + static const uint8_t kTrue[] = {0x0a, 3, CBS_ASN1_BOOLEAN, 1, 0xff}; + static const uint8_t kFalse[] = {0x0a, 3, CBS_ASN1_BOOLEAN, 1, 0x00}; + static const uint8_t kInvalid[] = {0x0a, 3, CBS_ASN1_BOOLEAN, 1, 0x01}; + + CBS data; + CBS_init(&data, NULL, 0); + int val = 2; + if (!CBS_get_optional_asn1_bool(&data, &val, 0x0a, 0) || + val != 0) { + return false; + } + + CBS_init(&data, kTrue, sizeof(kTrue)); + val = 2; + if (!CBS_get_optional_asn1_bool(&data, &val, 0x0a, 0) || + val != 1) { + return false; + } + + CBS_init(&data, kFalse, sizeof(kFalse)); + val = 2; + if (!CBS_get_optional_asn1_bool(&data, &val, 0x0a, 1) || + val != 0) { + return false; + } + + CBS_init(&data, kInvalid, sizeof(kInvalid)); + if (CBS_get_optional_asn1_bool(&data, &val, 0x0a, 1)) { + return false; + } + + return true; +} + +static bool TestCBBBasic() { + static const uint8_t kExpected[] = {1, 2, 3, 4, 5, 6, 7, 8}; + uint8_t *buf; + size_t buf_len; + CBB cbb; + + if (!CBB_init(&cbb, 100)) { + return false; + } + CBB_cleanup(&cbb); + + if (!CBB_init(&cbb, 0)) { + return false; + } + if (!CBB_add_u8(&cbb, 1) || + !CBB_add_u16(&cbb, 0x203) || + !CBB_add_u24(&cbb, 0x40506) || + !CBB_add_bytes(&cbb, (const uint8_t*) "\x07\x08", 2) || + !CBB_finish(&cbb, &buf, &buf_len)) { + CBB_cleanup(&cbb); + return false; + } + + ScopedOpenSSLBytes scoper(buf); + return buf_len == sizeof(kExpected) && memcmp(buf, kExpected, buf_len) == 0; +} + +static bool TestCBBFixed() { + CBB cbb; + uint8_t buf[1]; + uint8_t *out_buf; + size_t out_size; + + if (!CBB_init_fixed(&cbb, NULL, 0) || + CBB_add_u8(&cbb, 1) || + !CBB_finish(&cbb, &out_buf, &out_size) || + out_buf != NULL || + out_size != 0) { + return false; + } + + if (!CBB_init_fixed(&cbb, buf, 1) || + !CBB_add_u8(&cbb, 1) || + CBB_add_u8(&cbb, 2) || + !CBB_finish(&cbb, &out_buf, &out_size) || + out_buf != buf || + out_size != 1 || + buf[0] != 1) { + return false; + } + + return true; +} + +static bool TestCBBFinishChild() { + CBB cbb, child; + uint8_t *out_buf; + size_t out_size; + + if (!CBB_init(&cbb, 16)) { + return false; + } + if (!CBB_add_u8_length_prefixed(&cbb, &child) || + CBB_finish(&child, &out_buf, &out_size) || + !CBB_finish(&cbb, &out_buf, &out_size)) { + CBB_cleanup(&cbb); + return false; + } + ScopedOpenSSLBytes scoper(out_buf); + return out_size == 1 && out_buf[0] == 0; +} + +static bool TestCBBPrefixed() { + static const uint8_t kExpected[] = {0, 1, 1, 0, 2, 2, 3, 0, 0, 3, + 4, 5, 6, 5, 4, 1, 0, 1, 2}; + uint8_t *buf; + size_t buf_len; + CBB cbb, contents, inner_contents, inner_inner_contents; + + if (!CBB_init(&cbb, 0) || + CBB_len(&cbb) != 0 || + !CBB_add_u8_length_prefixed(&cbb, &contents) || + !CBB_add_u8_length_prefixed(&cbb, &contents) || + !CBB_add_u8(&contents, 1) || + CBB_len(&contents) != 1 || + !CBB_flush(&cbb) || + CBB_len(&cbb) != 3 || + !CBB_add_u16_length_prefixed(&cbb, &contents) || + !CBB_add_u16(&contents, 0x203) || + !CBB_add_u24_length_prefixed(&cbb, &contents) || + !CBB_add_u24(&contents, 0x40506) || + !CBB_add_u8_length_prefixed(&cbb, &contents) || + !CBB_add_u8_length_prefixed(&contents, &inner_contents) || + !CBB_add_u8(&inner_contents, 1) || + !CBB_add_u16_length_prefixed(&inner_contents, &inner_inner_contents) || + !CBB_add_u8(&inner_inner_contents, 2) || + !CBB_finish(&cbb, &buf, &buf_len)) { + CBB_cleanup(&cbb); + return false; + } + + ScopedOpenSSLBytes scoper(buf); + return buf_len == sizeof(kExpected) && memcmp(buf, kExpected, buf_len) == 0; +} + +static bool TestCBBDiscardChild() { + ScopedCBB cbb; + CBB contents, inner_contents, inner_inner_contents; + + if (!CBB_init(cbb.get(), 0) || + !CBB_add_u8(cbb.get(), 0xaa)) { + return false; + } + + // Discarding |cbb|'s children preserves the byte written. + CBB_discard_child(cbb.get()); + + if (!CBB_add_u8_length_prefixed(cbb.get(), &contents) || + !CBB_add_u8_length_prefixed(cbb.get(), &contents) || + !CBB_add_u8(&contents, 0xbb) || + !CBB_add_u16_length_prefixed(cbb.get(), &contents) || + !CBB_add_u16(&contents, 0xcccc) || + !CBB_add_u24_length_prefixed(cbb.get(), &contents) || + !CBB_add_u24(&contents, 0xdddddd) || + !CBB_add_u8_length_prefixed(cbb.get(), &contents) || + !CBB_add_u8(&contents, 0xff) || + !CBB_add_u8_length_prefixed(&contents, &inner_contents) || + !CBB_add_u8(&inner_contents, 0x42) || + !CBB_add_u16_length_prefixed(&inner_contents, &inner_inner_contents) || + !CBB_add_u8(&inner_inner_contents, 0x99)) { + return false; + } + + // Discard everything from |inner_contents| down. + CBB_discard_child(&contents); + + uint8_t *buf; + size_t buf_len; + if (!CBB_finish(cbb.get(), &buf, &buf_len)) { + return false; + } + ScopedOpenSSLBytes scoper(buf); + + static const uint8_t kExpected[] = { + 0xaa, + 0, + 1, 0xbb, + 0, 2, 0xcc, 0xcc, + 0, 0, 3, 0xdd, 0xdd, 0xdd, + 1, 0xff, + }; + return buf_len == sizeof(kExpected) && memcmp(buf, kExpected, buf_len) == 0; +} + +static bool TestCBBMisuse() { + CBB cbb, child, contents; + uint8_t *buf; + size_t buf_len; + + if (!CBB_init(&cbb, 0)) { + return false; + } + if (!CBB_add_u8_length_prefixed(&cbb, &child) || + !CBB_add_u8(&child, 1) || + !CBB_add_u8(&cbb, 2)) { + CBB_cleanup(&cbb); + return false; + } + + // Since we wrote to |cbb|, |child| is now invalid and attempts to write to + // it should fail. + if (CBB_add_u8(&child, 1) || + CBB_add_u16(&child, 1) || + CBB_add_u24(&child, 1) || + CBB_add_u8_length_prefixed(&child, &contents) || + CBB_add_u16_length_prefixed(&child, &contents) || + CBB_add_asn1(&child, &contents, 1) || + CBB_add_bytes(&child, (const uint8_t*) "a", 1)) { + fprintf(stderr, "CBB operation on invalid CBB did not fail.\n"); + CBB_cleanup(&cbb); + return false; + } + + if (!CBB_finish(&cbb, &buf, &buf_len)) { + CBB_cleanup(&cbb); + return false; + } + ScopedOpenSSLBytes scoper(buf); + + if (buf_len != 3 || + memcmp(buf, "\x01\x01\x02", 3) != 0) { + return false; + } + return true; +} + +static bool TestCBBASN1() { + static const uint8_t kExpected[] = {0x30, 3, 1, 2, 3}; + uint8_t *buf; + size_t buf_len; + CBB cbb, contents, inner_contents; + + if (!CBB_init(&cbb, 0)) { + return false; + } + if (!CBB_add_asn1(&cbb, &contents, 0x30) || + !CBB_add_bytes(&contents, (const uint8_t*) "\x01\x02\x03", 3) || + !CBB_finish(&cbb, &buf, &buf_len)) { + CBB_cleanup(&cbb); + return false; + } + ScopedOpenSSLBytes scoper(buf); + + if (buf_len != sizeof(kExpected) || memcmp(buf, kExpected, buf_len) != 0) { + return false; + } + + std::vector test_data(100000, 0x42); + + if (!CBB_init(&cbb, 0)) { + return false; + } + if (!CBB_add_asn1(&cbb, &contents, 0x30) || + !CBB_add_bytes(&contents, test_data.data(), 130) || + !CBB_finish(&cbb, &buf, &buf_len)) { + CBB_cleanup(&cbb); + return false; + } + scoper.reset(buf); + + if (buf_len != 3 + 130 || + memcmp(buf, "\x30\x81\x82", 3) != 0 || + memcmp(buf + 3, test_data.data(), 130) != 0) { + return false; + } + + if (!CBB_init(&cbb, 0)) { + return false; + } + if (!CBB_add_asn1(&cbb, &contents, 0x30) || + !CBB_add_bytes(&contents, test_data.data(), 1000) || + !CBB_finish(&cbb, &buf, &buf_len)) { + CBB_cleanup(&cbb); + return false; + } + scoper.reset(buf); + + if (buf_len != 4 + 1000 || + memcmp(buf, "\x30\x82\x03\xe8", 4) != 0 || + memcmp(buf + 4, test_data.data(), 1000)) { + return false; + } + + if (!CBB_init(&cbb, 0)) { + return false; + } + if (!CBB_add_asn1(&cbb, &contents, 0x30) || + !CBB_add_asn1(&contents, &inner_contents, 0x30) || + !CBB_add_bytes(&inner_contents, test_data.data(), 100000) || + !CBB_finish(&cbb, &buf, &buf_len)) { + CBB_cleanup(&cbb); + return false; + } + scoper.reset(buf); + + if (buf_len != 5 + 5 + 100000 || + memcmp(buf, "\x30\x83\x01\x86\xa5\x30\x83\x01\x86\xa0", 10) != 0 || + memcmp(buf + 10, test_data.data(), 100000)) { + return false; + } + + return true; +} + +static bool DoBerConvert(const char *name, + const uint8_t *der_expected, size_t der_len, + const uint8_t *ber, size_t ber_len) { + CBS in; + uint8_t *out; + size_t out_len; + + CBS_init(&in, ber, ber_len); + if (!CBS_asn1_ber_to_der(&in, &out, &out_len)) { + fprintf(stderr, "%s: CBS_asn1_ber_to_der failed.\n", name); + return false; + } + ScopedOpenSSLBytes scoper(out); + + if (out == NULL) { + if (ber_len != der_len || + memcmp(der_expected, ber, ber_len) != 0) { + fprintf(stderr, "%s: incorrect unconverted result.\n", name); + return false; + } + + return true; + } + + if (out_len != der_len || + memcmp(out, der_expected, der_len) != 0) { + fprintf(stderr, "%s: incorrect converted result.\n", name); + return false; + } + + return true; +} + +static bool TestBerConvert() { + static const uint8_t kSimpleBER[] = {0x01, 0x01, 0x00}; + + // kIndefBER contains a SEQUENCE with an indefinite length. + static const uint8_t kIndefBER[] = {0x30, 0x80, 0x01, 0x01, 0x02, 0x00, 0x00}; + static const uint8_t kIndefDER[] = {0x30, 0x03, 0x01, 0x01, 0x02}; + + // kOctetStringBER contains an indefinite length OCTET STRING with two parts. + // These parts need to be concatenated in DER form. + static const uint8_t kOctetStringBER[] = {0x24, 0x80, 0x04, 0x02, 0, 1, + 0x04, 0x02, 2, 3, 0x00, 0x00}; + static const uint8_t kOctetStringDER[] = {0x04, 0x04, 0, 1, 2, 3}; + + // kNSSBER is part of a PKCS#12 message generated by NSS that uses indefinite + // length elements extensively. + static const uint8_t kNSSBER[] = { + 0x30, 0x80, 0x02, 0x01, 0x03, 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x80, 0x24, 0x80, 0x04, 0x04, + 0x01, 0x02, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x39, + 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, + 0x00, 0x04, 0x14, 0x84, 0x98, 0xfc, 0x66, 0x33, 0xee, 0xba, 0xe7, 0x90, + 0xc1, 0xb6, 0xe8, 0x8f, 0xfe, 0x1d, 0xc5, 0xa5, 0x97, 0x93, 0x3e, 0x04, + 0x10, 0x38, 0x62, 0xc6, 0x44, 0x12, 0xd5, 0x30, 0x00, 0xf8, 0xf2, 0x1b, + 0xf0, 0x6e, 0x10, 0x9b, 0xb8, 0x02, 0x02, 0x07, 0xd0, 0x00, 0x00, + }; + + static const uint8_t kNSSDER[] = { + 0x30, 0x53, 0x02, 0x01, 0x03, 0x30, 0x13, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x06, 0x04, 0x04, + 0x01, 0x02, 0x03, 0x04, 0x30, 0x39, 0x30, 0x21, 0x30, 0x09, 0x06, + 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14, 0x84, + 0x98, 0xfc, 0x66, 0x33, 0xee, 0xba, 0xe7, 0x90, 0xc1, 0xb6, 0xe8, + 0x8f, 0xfe, 0x1d, 0xc5, 0xa5, 0x97, 0x93, 0x3e, 0x04, 0x10, 0x38, + 0x62, 0xc6, 0x44, 0x12, 0xd5, 0x30, 0x00, 0xf8, 0xf2, 0x1b, 0xf0, + 0x6e, 0x10, 0x9b, 0xb8, 0x02, 0x02, 0x07, 0xd0, + }; + + // kConstructedStringBER contains a deeply-nested constructed OCTET STRING. + // The BER conversion collapses this to one level deep, but not completely. + static const uint8_t kConstructedStringBER[] = { + 0xa0, 0x10, 0x24, 0x06, 0x04, 0x01, 0x00, 0x04, 0x01, + 0x01, 0x24, 0x06, 0x04, 0x01, 0x02, 0x04, 0x01, 0x03, + }; + static const uint8_t kConstructedStringDER[] = { + 0xa0, 0x08, 0x04, 0x02, 0x00, 0x01, 0x04, 0x02, 0x02, 0x03, + }; + + return DoBerConvert("kSimpleBER", kSimpleBER, sizeof(kSimpleBER), + kSimpleBER, sizeof(kSimpleBER)) && + DoBerConvert("kIndefBER", kIndefDER, sizeof(kIndefDER), kIndefBER, + sizeof(kIndefBER)) && + DoBerConvert("kOctetStringBER", kOctetStringDER, + sizeof(kOctetStringDER), kOctetStringBER, + sizeof(kOctetStringBER)) && + DoBerConvert("kNSSBER", kNSSDER, sizeof(kNSSDER), kNSSBER, + sizeof(kNSSBER)) && + DoBerConvert("kConstructedStringBER", kConstructedStringDER, + sizeof(kConstructedStringDER), kConstructedStringBER, + sizeof(kConstructedStringBER)); +} + +struct ImplicitStringTest { + const char *in; + size_t in_len; + bool ok; + const char *out; + size_t out_len; +}; + +static const ImplicitStringTest kImplicitStringTests[] = { + // A properly-encoded string. + {"\x80\x03\x61\x61\x61", 5, true, "aaa", 3}, + // An implicit-tagged string. + {"\xa0\x09\x04\x01\x61\x04\x01\x61\x04\x01\x61", 11, true, "aaa", 3}, + // |CBS_get_asn1_implicit_string| only accepts one level deep of nesting. + {"\xa0\x0b\x24\x06\x04\x01\x61\x04\x01\x61\x04\x01\x61", 13, false, nullptr, + 0}, + // The outer tag must match. + {"\x81\x03\x61\x61\x61", 5, false, nullptr, 0}, + {"\xa1\x09\x04\x01\x61\x04\x01\x61\x04\x01\x61", 11, false, nullptr, 0}, + // The inner tag must match. + {"\xa1\x09\x0c\x01\x61\x0c\x01\x61\x0c\x01\x61", 11, false, nullptr, 0}, +}; + +static bool TestImplicitString() { + for (const auto &test : kImplicitStringTests) { + uint8_t *storage = nullptr; + CBS in, out; + CBS_init(&in, reinterpret_cast(test.in), test.in_len); + int ok = CBS_get_asn1_implicit_string(&in, &out, &storage, + CBS_ASN1_CONTEXT_SPECIFIC | 0, + CBS_ASN1_OCTETSTRING); + ScopedOpenSSLBytes scoper(storage); + + if (static_cast(ok) != test.ok) { + fprintf(stderr, "CBS_get_asn1_implicit_string unexpectedly %s\n", + ok ? "succeeded" : "failed"); + return false; + } + + if (ok && (CBS_len(&out) != test.out_len || + memcmp(CBS_data(&out), test.out, test.out_len) != 0)) { + fprintf(stderr, "CBS_get_asn1_implicit_string gave the wrong output\n"); + return false; + } + } + + return true; +} + +struct ASN1Uint64Test { + uint64_t value; + const char *encoding; + size_t encoding_len; +}; + +static const ASN1Uint64Test kASN1Uint64Tests[] = { + {0, "\x02\x01\x00", 3}, + {1, "\x02\x01\x01", 3}, + {127, "\x02\x01\x7f", 3}, + {128, "\x02\x02\x00\x80", 4}, + {0xdeadbeef, "\x02\x05\x00\xde\xad\xbe\xef", 7}, + {UINT64_C(0x0102030405060708), + "\x02\x08\x01\x02\x03\x04\x05\x06\x07\x08", 10}, + {UINT64_C(0xffffffffffffffff), + "\x02\x09\x00\xff\xff\xff\xff\xff\xff\xff\xff", 11}, +}; + +struct ASN1InvalidUint64Test { + const char *encoding; + size_t encoding_len; +}; + +static const ASN1InvalidUint64Test kASN1InvalidUint64Tests[] = { + // Bad tag. + {"\x03\x01\x00", 3}, + // Empty contents. + {"\x02\x00", 2}, + // Negative number. + {"\x02\x01\x80", 3}, + // Overflow. + {"\x02\x09\x01\x00\x00\x00\x00\x00\x00\x00\x00", 11}, + // Leading zeros. + {"\x02\x02\x00\x01", 4}, +}; + +static bool TestASN1Uint64() { + for (size_t i = 0; i < sizeof(kASN1Uint64Tests) / sizeof(kASN1Uint64Tests[0]); + i++) { + const ASN1Uint64Test *test = &kASN1Uint64Tests[i]; + CBS cbs; + uint64_t value; + CBB cbb; + uint8_t *out; + size_t len; + + CBS_init(&cbs, (const uint8_t *)test->encoding, test->encoding_len); + if (!CBS_get_asn1_uint64(&cbs, &value) || + CBS_len(&cbs) != 0 || + value != test->value) { + return false; + } + + if (!CBB_init(&cbb, 0)) { + return false; + } + if (!CBB_add_asn1_uint64(&cbb, test->value) || + !CBB_finish(&cbb, &out, &len)) { + CBB_cleanup(&cbb); + return false; + } + ScopedOpenSSLBytes scoper(out); + if (len != test->encoding_len || memcmp(out, test->encoding, len) != 0) { + return false; + } + } + + for (size_t i = 0; + i < sizeof(kASN1InvalidUint64Tests) / sizeof(kASN1InvalidUint64Tests[0]); + i++) { + const ASN1InvalidUint64Test *test = &kASN1InvalidUint64Tests[i]; + CBS cbs; + uint64_t value; + + CBS_init(&cbs, (const uint8_t *)test->encoding, test->encoding_len); + if (CBS_get_asn1_uint64(&cbs, &value)) { + return false; + } + } + + return true; +} + +static bool TestZero() { + CBB cbb; + CBB_zero(&cbb); + // Calling |CBB_cleanup| on a zero-state |CBB| must not crash. + CBB_cleanup(&cbb); + return true; +} + +static bool TestCBBReserve() { + uint8_t buf[10]; + uint8_t *ptr; + size_t len; + ScopedCBB cbb; + if (!CBB_init_fixed(cbb.get(), buf, sizeof(buf)) || + // Too large. + CBB_reserve(cbb.get(), &ptr, 11) || + // Successfully reserve the entire space. + !CBB_reserve(cbb.get(), &ptr, 10) || + ptr != buf || + // Advancing under the maximum bytes is legal. + !CBB_did_write(cbb.get(), 5) || + !CBB_finish(cbb.get(), NULL, &len) || + len != 5) { + return false; + } + return true; +} + +int main(void) { + CRYPTO_library_init(); + + if (!TestSkip() || + !TestGetUint() || + !TestGetPrefixed() || + !TestGetPrefixedBad() || + !TestGetASN1() || + !TestCBBBasic() || + !TestCBBFixed() || + !TestCBBFinishChild() || + !TestCBBMisuse() || + !TestCBBPrefixed() || + !TestCBBDiscardChild() || + !TestCBBASN1() || + !TestBerConvert() || + !TestImplicitString() || + !TestASN1Uint64() || + !TestGetOptionalASN1Bool() || + !TestZero() || + !TestCBBReserve()) { + return 1; + } + + printf("PASS\n"); + return 0; +} diff --git a/external/boringssl/crypto/bytestring/cbb.c b/external/boringssl/crypto/bytestring/cbb.c new file mode 100644 index 0000000000..8fc518794d --- /dev/null +++ b/external/boringssl/crypto/bytestring/cbb.c @@ -0,0 +1,445 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include +#include + +#include + + +void CBB_zero(CBB *cbb) { + memset(cbb, 0, sizeof(CBB)); +} + +static int cbb_init(CBB *cbb, uint8_t *buf, size_t cap) { + /* This assumes that |cbb| has already been zeroed. */ + struct cbb_buffer_st *base; + + base = OPENSSL_malloc(sizeof(struct cbb_buffer_st)); + if (base == NULL) { + return 0; + } + + base->buf = buf; + base->len = 0; + base->cap = cap; + base->can_resize = 1; + + cbb->base = base; + cbb->is_top_level = 1; + return 1; +} + +int CBB_init(CBB *cbb, size_t initial_capacity) { + CBB_zero(cbb); + + uint8_t *buf = OPENSSL_malloc(initial_capacity); + if (initial_capacity > 0 && buf == NULL) { + return 0; + } + + if (!cbb_init(cbb, buf, initial_capacity)) { + OPENSSL_free(buf); + return 0; + } + + return 1; +} + +int CBB_init_fixed(CBB *cbb, uint8_t *buf, size_t len) { + CBB_zero(cbb); + + if (!cbb_init(cbb, buf, len)) { + return 0; + } + + cbb->base->can_resize = 0; + return 1; +} + +void CBB_cleanup(CBB *cbb) { + if (cbb->base) { + /* Only top-level |CBB|s are cleaned up. Child |CBB|s are non-owning. They + * are implicitly discarded when the parent is flushed or cleaned up. */ + assert(cbb->is_top_level); + + if (cbb->base->can_resize) { + OPENSSL_free(cbb->base->buf); + } + OPENSSL_free(cbb->base); + } + cbb->base = NULL; +} + +static int cbb_buffer_reserve(struct cbb_buffer_st *base, uint8_t **out, + size_t len) { + size_t newlen; + + if (base == NULL) { + return 0; + } + + newlen = base->len + len; + if (newlen < base->len) { + /* Overflow */ + return 0; + } + + if (newlen > base->cap) { + size_t newcap = base->cap * 2; + uint8_t *newbuf; + + if (!base->can_resize) { + return 0; + } + + if (newcap < base->cap || newcap < newlen) { + newcap = newlen; + } + newbuf = OPENSSL_realloc(base->buf, newcap); + if (newbuf == NULL) { + return 0; + } + + base->buf = newbuf; + base->cap = newcap; + } + + if (out) { + *out = base->buf + base->len; + } + + return 1; +} + +static int cbb_buffer_add(struct cbb_buffer_st *base, uint8_t **out, + size_t len) { + if (!cbb_buffer_reserve(base, out, len)) { + return 0; + } + /* This will not overflow or |cbb_buffer_reserve| would have failed. */ + base->len += len; + return 1; +} + +static int cbb_buffer_add_u(struct cbb_buffer_st *base, uint32_t v, + size_t len_len) { + uint8_t *buf; + size_t i; + + if (len_len == 0) { + return 1; + } + if (!cbb_buffer_add(base, &buf, len_len)) { + return 0; + } + + for (i = len_len - 1; i < len_len; i--) { + buf[i] = v; + v >>= 8; + } + return 1; +} + +int CBB_finish(CBB *cbb, uint8_t **out_data, size_t *out_len) { + if (!cbb->is_top_level) { + return 0; + } + + if (!CBB_flush(cbb)) { + return 0; + } + + if (cbb->base->can_resize && (out_data == NULL || out_len == NULL)) { + /* |out_data| and |out_len| can only be NULL if the CBB is fixed. */ + return 0; + } + + if (out_data != NULL) { + *out_data = cbb->base->buf; + } + if (out_len != NULL) { + *out_len = cbb->base->len; + } + cbb->base->buf = NULL; + CBB_cleanup(cbb); + return 1; +} + +/* CBB_flush recurses and then writes out any pending length prefix. The + * current length of the underlying base is taken to be the length of the + * length-prefixed data. */ +int CBB_flush(CBB *cbb) { + size_t child_start, i, len; + + if (cbb->base == NULL) { + return 0; + } + + if (cbb->child == NULL || cbb->child->pending_len_len == 0) { + return 1; + } + + child_start = cbb->child->offset + cbb->child->pending_len_len; + + if (!CBB_flush(cbb->child) || + child_start < cbb->child->offset || + cbb->base->len < child_start) { + return 0; + } + + len = cbb->base->len - child_start; + + if (cbb->child->pending_is_asn1) { + /* For ASN.1 we assume that we'll only need a single byte for the length. + * If that turned out to be incorrect, we have to move the contents along + * in order to make space. */ + size_t len_len; + uint8_t initial_length_byte; + + assert (cbb->child->pending_len_len == 1); + + if (len > 0xfffffffe) { + /* Too large. */ + return 0; + } else if (len > 0xffffff) { + len_len = 5; + initial_length_byte = 0x80 | 4; + } else if (len > 0xffff) { + len_len = 4; + initial_length_byte = 0x80 | 3; + } else if (len > 0xff) { + len_len = 3; + initial_length_byte = 0x80 | 2; + } else if (len > 0x7f) { + len_len = 2; + initial_length_byte = 0x80 | 1; + } else { + len_len = 1; + initial_length_byte = len; + len = 0; + } + + if (len_len != 1) { + /* We need to move the contents along in order to make space. */ + size_t extra_bytes = len_len - 1; + if (!cbb_buffer_add(cbb->base, NULL, extra_bytes)) { + return 0; + } + memmove(cbb->base->buf + child_start + extra_bytes, + cbb->base->buf + child_start, len); + } + cbb->base->buf[cbb->child->offset++] = initial_length_byte; + cbb->child->pending_len_len = len_len - 1; + } + + for (i = cbb->child->pending_len_len - 1; i < cbb->child->pending_len_len; + i--) { + cbb->base->buf[cbb->child->offset + i] = len; + len >>= 8; + } + if (len != 0) { + return 0; + } + + cbb->child->base = NULL; + cbb->child = NULL; + + return 1; +} + +const uint8_t *CBB_data(const CBB *cbb) { + assert(cbb->child == NULL); + return cbb->base->buf + cbb->offset + cbb->pending_len_len; +} + +size_t CBB_len(const CBB *cbb) { + assert(cbb->child == NULL); + assert(cbb->offset + cbb->pending_len_len <= cbb->base->len); + + return cbb->base->len - cbb->offset - cbb->pending_len_len; +} + +static int cbb_add_length_prefixed(CBB *cbb, CBB *out_contents, + size_t len_len) { + uint8_t *prefix_bytes; + + if (!CBB_flush(cbb)) { + return 0; + } + + size_t offset = cbb->base->len; + if (!cbb_buffer_add(cbb->base, &prefix_bytes, len_len)) { + return 0; + } + + memset(prefix_bytes, 0, len_len); + memset(out_contents, 0, sizeof(CBB)); + out_contents->base = cbb->base; + cbb->child = out_contents; + cbb->child->offset = offset; + cbb->child->pending_len_len = len_len; + cbb->child->pending_is_asn1 = 0; + + return 1; +} + +int CBB_add_u8_length_prefixed(CBB *cbb, CBB *out_contents) { + return cbb_add_length_prefixed(cbb, out_contents, 1); +} + +int CBB_add_u16_length_prefixed(CBB *cbb, CBB *out_contents) { + return cbb_add_length_prefixed(cbb, out_contents, 2); +} + +int CBB_add_u24_length_prefixed(CBB *cbb, CBB *out_contents) { + return cbb_add_length_prefixed(cbb, out_contents, 3); +} + +int CBB_add_asn1(CBB *cbb, CBB *out_contents, uint8_t tag) { + if ((tag & 0x1f) == 0x1f) { + /* Long form identifier octets are not supported. */ + return 0; + } + + if (!CBB_flush(cbb) || + !CBB_add_u8(cbb, tag)) { + return 0; + } + + size_t offset = cbb->base->len; + if (!CBB_add_u8(cbb, 0)) { + return 0; + } + + memset(out_contents, 0, sizeof(CBB)); + out_contents->base = cbb->base; + cbb->child = out_contents; + cbb->child->offset = offset; + cbb->child->pending_len_len = 1; + cbb->child->pending_is_asn1 = 1; + + return 1; +} + +int CBB_add_bytes(CBB *cbb, const uint8_t *data, size_t len) { + uint8_t *dest; + + if (!CBB_flush(cbb) || + !cbb_buffer_add(cbb->base, &dest, len)) { + return 0; + } + memcpy(dest, data, len); + return 1; +} + +int CBB_add_space(CBB *cbb, uint8_t **out_data, size_t len) { + if (!CBB_flush(cbb) || + !cbb_buffer_add(cbb->base, out_data, len)) { + return 0; + } + return 1; +} + +int CBB_reserve(CBB *cbb, uint8_t **out_data, size_t len) { + if (!CBB_flush(cbb) || + !cbb_buffer_reserve(cbb->base, out_data, len)) { + return 0; + } + return 1; +} + +int CBB_did_write(CBB *cbb, size_t len) { + size_t newlen = cbb->base->len + len; + if (cbb->child != NULL || + newlen < cbb->base->len || + newlen > cbb->base->cap) { + return 0; + } + cbb->base->len = newlen; + return 1; +} + +int CBB_add_u8(CBB *cbb, uint8_t value) { + if (!CBB_flush(cbb)) { + return 0; + } + + return cbb_buffer_add_u(cbb->base, value, 1); +} + +int CBB_add_u16(CBB *cbb, uint16_t value) { + if (!CBB_flush(cbb)) { + return 0; + } + + return cbb_buffer_add_u(cbb->base, value, 2); +} + +int CBB_add_u24(CBB *cbb, uint32_t value) { + if (!CBB_flush(cbb)) { + return 0; + } + + return cbb_buffer_add_u(cbb->base, value, 3); +} + +void CBB_discard_child(CBB *cbb) { + if (cbb->child == NULL) { + return; + } + + cbb->base->len = cbb->child->offset; + + cbb->child->base = NULL; + cbb->child = NULL; +} + +int CBB_add_asn1_uint64(CBB *cbb, uint64_t value) { + CBB child; + size_t i; + int started = 0; + + if (!CBB_add_asn1(cbb, &child, CBS_ASN1_INTEGER)) { + return 0; + } + + for (i = 0; i < 8; i++) { + uint8_t byte = (value >> 8*(7-i)) & 0xff; + if (!started) { + if (byte == 0) { + /* Don't encode leading zeros. */ + continue; + } + /* If the high bit is set, add a padding byte to make it + * unsigned. */ + if ((byte & 0x80) && !CBB_add_u8(&child, 0)) { + return 0; + } + started = 1; + } + if (!CBB_add_u8(&child, byte)) { + return 0; + } + } + + /* 0 is encoded as a single 0, not the empty string. */ + if (!started && !CBB_add_u8(&child, 0)) { + return 0; + } + + return CBB_flush(cbb); +} diff --git a/external/boringssl/crypto/bytestring/cbs.c b/external/boringssl/crypto/bytestring/cbs.c new file mode 100644 index 0000000000..c86afbda91 --- /dev/null +++ b/external/boringssl/crypto/bytestring/cbs.c @@ -0,0 +1,440 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include +#include + +#include +#include + +#include "internal.h" + + +void CBS_init(CBS *cbs, const uint8_t *data, size_t len) { + cbs->data = data; + cbs->len = len; +} + +static int cbs_get(CBS *cbs, const uint8_t **p, size_t n) { + if (cbs->len < n) { + return 0; + } + + *p = cbs->data; + cbs->data += n; + cbs->len -= n; + return 1; +} + +int CBS_skip(CBS *cbs, size_t len) { + const uint8_t *dummy; + return cbs_get(cbs, &dummy, len); +} + +const uint8_t *CBS_data(const CBS *cbs) { + return cbs->data; +} + +size_t CBS_len(const CBS *cbs) { + return cbs->len; +} + +int CBS_stow(const CBS *cbs, uint8_t **out_ptr, size_t *out_len) { + OPENSSL_free(*out_ptr); + *out_ptr = NULL; + *out_len = 0; + + if (cbs->len == 0) { + return 1; + } + *out_ptr = BUF_memdup(cbs->data, cbs->len); + if (*out_ptr == NULL) { + return 0; + } + *out_len = cbs->len; + return 1; +} + +int CBS_strdup(const CBS *cbs, char **out_ptr) { + if (*out_ptr != NULL) { + OPENSSL_free(*out_ptr); + } + *out_ptr = BUF_strndup((const char*)cbs->data, cbs->len); + return (*out_ptr != NULL); +} + +int CBS_contains_zero_byte(const CBS *cbs) { + return memchr(cbs->data, 0, cbs->len) != NULL; +} + +int CBS_mem_equal(const CBS *cbs, const uint8_t *data, size_t len) { + if (len != cbs->len) { + return 0; + } + return CRYPTO_memcmp(cbs->data, data, len) == 0; +} + +static int cbs_get_u(CBS *cbs, uint32_t *out, size_t len) { + uint32_t result = 0; + size_t i; + const uint8_t *data; + + if (!cbs_get(cbs, &data, len)) { + return 0; + } + for (i = 0; i < len; i++) { + result <<= 8; + result |= data[i]; + } + *out = result; + return 1; +} + +int CBS_get_u8(CBS *cbs, uint8_t *out) { + const uint8_t *v; + if (!cbs_get(cbs, &v, 1)) { + return 0; + } + *out = *v; + return 1; +} + +int CBS_get_u16(CBS *cbs, uint16_t *out) { + uint32_t v; + if (!cbs_get_u(cbs, &v, 2)) { + return 0; + } + *out = v; + return 1; +} + +int CBS_get_u24(CBS *cbs, uint32_t *out) { + return cbs_get_u(cbs, out, 3); +} + +int CBS_get_u32(CBS *cbs, uint32_t *out) { + return cbs_get_u(cbs, out, 4); +} + +int CBS_get_last_u8(CBS *cbs, uint8_t *out) { + if (cbs->len == 0) { + return 0; + } + *out = cbs->data[cbs->len - 1]; + cbs->len--; + return 1; +} + +int CBS_get_bytes(CBS *cbs, CBS *out, size_t len) { + const uint8_t *v; + if (!cbs_get(cbs, &v, len)) { + return 0; + } + CBS_init(out, v, len); + return 1; +} + +int CBS_copy_bytes(CBS *cbs, uint8_t *out, size_t len) { + const uint8_t *v; + if (!cbs_get(cbs, &v, len)) { + return 0; + } + memcpy(out, v, len); + return 1; +} + +static int cbs_get_length_prefixed(CBS *cbs, CBS *out, size_t len_len) { + uint32_t len; + if (!cbs_get_u(cbs, &len, len_len)) { + return 0; + } + return CBS_get_bytes(cbs, out, len); +} + +int CBS_get_u8_length_prefixed(CBS *cbs, CBS *out) { + return cbs_get_length_prefixed(cbs, out, 1); +} + +int CBS_get_u16_length_prefixed(CBS *cbs, CBS *out) { + return cbs_get_length_prefixed(cbs, out, 2); +} + +int CBS_get_u24_length_prefixed(CBS *cbs, CBS *out) { + return cbs_get_length_prefixed(cbs, out, 3); +} + +static int cbs_get_any_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag, + size_t *out_header_len, int ber_ok) { + uint8_t tag, length_byte; + CBS header = *cbs; + CBS throwaway; + + if (out == NULL) { + out = &throwaway; + } + + if (!CBS_get_u8(&header, &tag) || + !CBS_get_u8(&header, &length_byte)) { + return 0; + } + + /* ITU-T X.690 section 8.1.2.3 specifies the format for identifiers with a tag + * number no greater than 30. + * + * If the number portion is 31 (0x1f, the largest value that fits in the + * allotted bits), then the tag is more than one byte long and the + * continuation bytes contain the tag number. This parser only supports tag + * numbers less than 31 (and thus single-byte tags). */ + if ((tag & 0x1f) == 0x1f) { + return 0; + } + + if (out_tag != NULL) { + *out_tag = tag; + } + + size_t len; + /* The format for the length encoding is specified in ITU-T X.690 section + * 8.1.3. */ + if ((length_byte & 0x80) == 0) { + /* Short form length. */ + len = ((size_t) length_byte) + 2; + if (out_header_len != NULL) { + *out_header_len = 2; + } + } else { + /* The high bit indicate that this is the long form, while the next 7 bits + * encode the number of subsequent octets used to encode the length (ITU-T + * X.690 clause 8.1.3.5.b). */ + const size_t num_bytes = length_byte & 0x7f; + uint32_t len32; + + if (ber_ok && (tag & CBS_ASN1_CONSTRUCTED) != 0 && num_bytes == 0) { + /* indefinite length */ + if (out_header_len != NULL) { + *out_header_len = 2; + } + return CBS_get_bytes(cbs, out, 2); + } + + /* ITU-T X.690 clause 8.1.3.5.c specifies that the value 0xff shall not be + * used as the first byte of the length. If this parser encounters that + * value, num_bytes will be parsed as 127, which will fail the check below. + */ + if (num_bytes == 0 || num_bytes > 4) { + return 0; + } + if (!cbs_get_u(&header, &len32, num_bytes)) { + return 0; + } + /* ITU-T X.690 section 10.1 (DER length forms) requires encoding the length + * with the minimum number of octets. */ + if (len32 < 128) { + /* Length should have used short-form encoding. */ + return 0; + } + if ((len32 >> ((num_bytes-1)*8)) == 0) { + /* Length should have been at least one byte shorter. */ + return 0; + } + len = len32; + if (len + 2 + num_bytes < len) { + /* Overflow. */ + return 0; + } + len += 2 + num_bytes; + if (out_header_len != NULL) { + *out_header_len = 2 + num_bytes; + } + } + + return CBS_get_bytes(cbs, out, len); +} + +int CBS_get_any_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag, + size_t *out_header_len) { + return cbs_get_any_asn1_element(cbs, out, out_tag, out_header_len, + 0 /* DER only */); +} + +int CBS_get_any_ber_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag, + size_t *out_header_len) { + return cbs_get_any_asn1_element(cbs, out, out_tag, out_header_len, + 1 /* BER allowed */); +} + +static int cbs_get_asn1(CBS *cbs, CBS *out, unsigned tag_value, + int skip_header) { + size_t header_len; + unsigned tag; + CBS throwaway; + + if (out == NULL) { + out = &throwaway; + } + + if (!CBS_get_any_asn1_element(cbs, out, &tag, &header_len) || + tag != tag_value) { + return 0; + } + + if (skip_header && !CBS_skip(out, header_len)) { + assert(0); + return 0; + } + + return 1; +} + +int CBS_get_asn1(CBS *cbs, CBS *out, unsigned tag_value) { + return cbs_get_asn1(cbs, out, tag_value, 1 /* skip header */); +} + +int CBS_get_asn1_element(CBS *cbs, CBS *out, unsigned tag_value) { + return cbs_get_asn1(cbs, out, tag_value, 0 /* include header */); +} + +int CBS_peek_asn1_tag(const CBS *cbs, unsigned tag_value) { + if (CBS_len(cbs) < 1) { + return 0; + } + return CBS_data(cbs)[0] == tag_value; +} + +int CBS_get_asn1_uint64(CBS *cbs, uint64_t *out) { + CBS bytes; + const uint8_t *data; + size_t i, len; + + if (!CBS_get_asn1(cbs, &bytes, CBS_ASN1_INTEGER)) { + return 0; + } + + *out = 0; + data = CBS_data(&bytes); + len = CBS_len(&bytes); + + if (len == 0) { + /* An INTEGER is encoded with at least one octet. */ + return 0; + } + + if ((data[0] & 0x80) != 0) { + /* Negative number. */ + return 0; + } + + if (data[0] == 0 && len > 1 && (data[1] & 0x80) == 0) { + /* Extra leading zeros. */ + return 0; + } + + for (i = 0; i < len; i++) { + if ((*out >> 56) != 0) { + /* Too large to represent as a uint64_t. */ + return 0; + } + *out <<= 8; + *out |= data[i]; + } + + return 1; +} + +int CBS_get_optional_asn1(CBS *cbs, CBS *out, int *out_present, unsigned tag) { + int present = 0; + + if (CBS_peek_asn1_tag(cbs, tag)) { + if (!CBS_get_asn1(cbs, out, tag)) { + return 0; + } + present = 1; + } + + if (out_present != NULL) { + *out_present = present; + } + + return 1; +} + +int CBS_get_optional_asn1_octet_string(CBS *cbs, CBS *out, int *out_present, + unsigned tag) { + CBS child; + int present; + if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) { + return 0; + } + if (present) { + if (!CBS_get_asn1(&child, out, CBS_ASN1_OCTETSTRING) || + CBS_len(&child) != 0) { + return 0; + } + } else { + CBS_init(out, NULL, 0); + } + if (out_present) { + *out_present = present; + } + return 1; +} + +int CBS_get_optional_asn1_uint64(CBS *cbs, uint64_t *out, unsigned tag, + uint64_t default_value) { + CBS child; + int present; + if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) { + return 0; + } + if (present) { + if (!CBS_get_asn1_uint64(&child, out) || + CBS_len(&child) != 0) { + return 0; + } + } else { + *out = default_value; + } + return 1; +} + +int CBS_get_optional_asn1_bool(CBS *cbs, int *out, unsigned tag, + int default_value) { + CBS child, child2; + int present; + if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) { + return 0; + } + if (present) { + uint8_t boolean; + + if (!CBS_get_asn1(&child, &child2, CBS_ASN1_BOOLEAN) || + CBS_len(&child2) != 1 || + CBS_len(&child) != 0) { + return 0; + } + + boolean = CBS_data(&child2)[0]; + if (boolean == 0) { + *out = 0; + } else if (boolean == 0xff) { + *out = 1; + } else { + return 0; + } + } else { + *out = default_value; + } + return 1; +} diff --git a/external/boringssl/crypto/bytestring/internal.h b/external/boringssl/crypto/bytestring/internal.h new file mode 100644 index 0000000000..2fed413902 --- /dev/null +++ b/external/boringssl/crypto/bytestring/internal.h @@ -0,0 +1,75 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_BYTESTRING_INTERNAL_H +#define OPENSSL_HEADER_BYTESTRING_INTERNAL_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* CBS_asn1_ber_to_der reads a BER element from |in|. If it finds + * indefinite-length elements or constructed strings then it converts the BER + * data to DER and sets |*out| and |*out_length| to describe a malloced buffer + * containing the DER data. Additionally, |*in| will be advanced over the BER + * element. + * + * If it doesn't find any indefinite-length elements or constructed strings then + * it sets |*out| to NULL and |*in| is unmodified. + * + * This function should successfully process any valid BER input, however it + * will not convert all of BER's deviations from DER. BER is ambiguous between + * implicitly-tagged SEQUENCEs of strings and implicitly-tagged constructed + * strings. Implicitly-tagged strings must be parsed with + * |CBS_get_ber_implicitly_tagged_string| instead of |CBS_get_asn1|. The caller + * must also account for BER variations in the contents of a primitive. + * + * It returns one on success and zero otherwise. */ +OPENSSL_EXPORT int CBS_asn1_ber_to_der(CBS *in, uint8_t **out, size_t *out_len); + +/* CBS_get_asn1_implicit_string parses a BER string of primitive type + * |inner_tag| implicitly-tagged with |outer_tag|. It sets |out| to the + * contents. If concatenation was needed, it sets |*out_storage| to a buffer + * which the caller must release with |OPENSSL_free|. Otherwise, it sets + * |*out_storage| to NULL. + * + * This function does not parse all of BER. It requires the string be + * definite-length. Constructed strings are allowed, but all children of the + * outermost element must be primitive. The caller should use + * |CBS_asn1_ber_to_der| before running this function. + * + * It returns one on success and zero otherwise. */ +OPENSSL_EXPORT int CBS_get_asn1_implicit_string(CBS *in, CBS *out, + uint8_t **out_storage, + unsigned outer_tag, + unsigned inner_tag); + +/* CBB_finish_i2d calls |CBB_finish| on |cbb| which must have been initialized + * with |CBB_init|. If |outp| is not NULL then the result is written to |*outp| + * and |*outp| is advanced just past the output. It returns the number of bytes + * in the result, whether written or not, or a negative value on error. On + * error, it calls |CBB_cleanup| on |cbb|. + * + * This function may be used to help implement legacy i2d ASN.1 functions. */ +int CBB_finish_i2d(CBB *cbb, uint8_t **outp); + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_BYTESTRING_INTERNAL_H */ diff --git a/external/boringssl/crypto/chacha/CMakeLists.txt b/external/boringssl/crypto/chacha/CMakeLists.txt new file mode 100644 index 0000000000..73cfc31edd --- /dev/null +++ b/external/boringssl/crypto/chacha/CMakeLists.txt @@ -0,0 +1,60 @@ +include_directories(../../include) + +if (${ARCH} STREQUAL "arm") + set( + CHACHA_ARCH_SOURCES + + chacha-armv4.${ASM_EXT} + ) +endif() + +if (${ARCH} STREQUAL "aarch64") + set( + CHACHA_ARCH_SOURCES + + chacha-armv8.${ASM_EXT} + ) +endif() + +if (${ARCH} STREQUAL "x86") + set( + CHACHA_ARCH_SOURCES + + chacha-x86.${ASM_EXT} + ) +endif() + +if (${ARCH} STREQUAL "x86_64") + set( + CHACHA_ARCH_SOURCES + + chacha-x86_64.${ASM_EXT} + ) +endif() + +add_library( + chacha + + OBJECT + + chacha.c + + ${CHACHA_ARCH_SOURCES} +) + +if(ENABLE_TESTS) +add_executable( + chacha_test + + chacha_test.cc + $ +) + +target_link_libraries(chacha_test crypto) +add_dependencies(all_tests chacha_test) +endif() + +perlasm(chacha-armv4.${ASM_EXT} asm/chacha-armv4.pl) +perlasm(chacha-armv8.${ASM_EXT} asm/chacha-armv8.pl) +perlasm(chacha-x86.${ASM_EXT} asm/chacha-x86.pl) +perlasm(chacha-x86_64.${ASM_EXT} asm/chacha-x86_64.pl) diff --git a/external/boringssl/crypto/chacha/asm/chacha-armv4.pl b/external/boringssl/crypto/chacha/asm/chacha-armv4.pl new file mode 100755 index 0000000000..b190445da5 --- /dev/null +++ b/external/boringssl/crypto/chacha/asm/chacha-armv4.pl @@ -0,0 +1,1151 @@ +#!/usr/bin/env perl +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# December 2014 +# +# ChaCha20 for ARMv4. +# +# Performance in cycles per byte out of large buffer. +# +# IALU/gcc-4.4 1xNEON 3xNEON+1xIALU +# +# Cortex-A5 19.3(*)/+95% 21.8 14.1 +# Cortex-A8 10.5(*)/+160% 13.9 6.35 +# Cortex-A9 12.9(**)/+110% 14.3 6.50 +# Cortex-A15 11.0/+40% 16.0 5.00 +# Snapdragon S4 11.5/+125% 13.6 4.90 +# +# (*) most "favourable" result for aligned data on little-endian +# processor, result for misaligned data is 10-15% lower; +# (**) this result is a trade-off: it can be improved by 20%, +# but then Snapdragon S4 and Cortex-A8 results get +# 20-25% worse; + +$flavour = shift; +if ($flavour=~/^\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; } +else { while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {} } + +if ($flavour && $flavour ne "void") { + $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; + ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or + ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or + die "can't locate arm-xlate.pl"; + + open STDOUT,"| \"$^X\" $xlate $flavour $output"; +} else { + open STDOUT,">$output"; +} + +sub AUTOLOAD() # thunk [simplified] x86-style perlasm +{ my $opcode = $AUTOLOAD; $opcode =~ s/.*:://; $opcode =~ s/_/\./; + my $arg = pop; + $arg = "#$arg" if ($arg*1 eq $arg); + $code .= "\t$opcode\t".join(',',@_,$arg)."\n"; +} + +my @x=map("r$_",(0..7,"x","x","x","x",12,"x",14,"x")); +my @t=map("r$_",(8..11)); + +sub ROUND { +my ($a0,$b0,$c0,$d0)=@_; +my ($a1,$b1,$c1,$d1)=map(($_&~3)+(($_+1)&3),($a0,$b0,$c0,$d0)); +my ($a2,$b2,$c2,$d2)=map(($_&~3)+(($_+1)&3),($a1,$b1,$c1,$d1)); +my ($a3,$b3,$c3,$d3)=map(($_&~3)+(($_+1)&3),($a2,$b2,$c2,$d2)); +my $odd = $d0&1; +my ($xc,$xc_) = (@t[0..1]); +my ($xd,$xd_) = $odd ? (@t[2],@x[$d1]) : (@x[$d0],@t[2]); +my @ret; + + # Consider order in which variables are addressed by their + # index: + # + # a b c d + # + # 0 4 8 12 < even round + # 1 5 9 13 + # 2 6 10 14 + # 3 7 11 15 + # 0 5 10 15 < odd round + # 1 6 11 12 + # 2 7 8 13 + # 3 4 9 14 + # + # 'a', 'b' are permanently allocated in registers, @x[0..7], + # while 'c's and pair of 'd's are maintained in memory. If + # you observe 'c' column, you'll notice that pair of 'c's is + # invariant between rounds. This means that we have to reload + # them once per round, in the middle. This is why you'll see + # bunch of 'c' stores and loads in the middle, but none in + # the beginning or end. If you observe 'd' column, you'll + # notice that 15 and 13 are reused in next pair of rounds. + # This is why these two are chosen for offloading to memory, + # to make loads count more. + push @ret,( + "&add (@x[$a0],@x[$a0],@x[$b0])", + "&mov ($xd,$xd,'ror#16')", + "&add (@x[$a1],@x[$a1],@x[$b1])", + "&mov ($xd_,$xd_,'ror#16')", + "&eor ($xd,$xd,@x[$a0],'ror#16')", + "&eor ($xd_,$xd_,@x[$a1],'ror#16')", + + "&add ($xc,$xc,$xd)", + "&mov (@x[$b0],@x[$b0],'ror#20')", + "&add ($xc_,$xc_,$xd_)", + "&mov (@x[$b1],@x[$b1],'ror#20')", + "&eor (@x[$b0],@x[$b0],$xc,'ror#20')", + "&eor (@x[$b1],@x[$b1],$xc_,'ror#20')", + + "&add (@x[$a0],@x[$a0],@x[$b0])", + "&mov ($xd,$xd,'ror#24')", + "&add (@x[$a1],@x[$a1],@x[$b1])", + "&mov ($xd_,$xd_,'ror#24')", + "&eor ($xd,$xd,@x[$a0],'ror#24')", + "&eor ($xd_,$xd_,@x[$a1],'ror#24')", + + "&add ($xc,$xc,$xd)", + "&mov (@x[$b0],@x[$b0],'ror#25')" ); + push @ret,( + "&str ($xd,'[sp,#4*(16+$d0)]')", + "&ldr ($xd,'[sp,#4*(16+$d2)]')" ) if ($odd); + push @ret,( + "&add ($xc_,$xc_,$xd_)", + "&mov (@x[$b1],@x[$b1],'ror#25')" ); + push @ret,( + "&str ($xd_,'[sp,#4*(16+$d1)]')", + "&ldr ($xd_,'[sp,#4*(16+$d3)]')" ) if (!$odd); + push @ret,( + "&eor (@x[$b0],@x[$b0],$xc,'ror#25')", + "&eor (@x[$b1],@x[$b1],$xc_,'ror#25')" ); + + $xd=@x[$d2] if (!$odd); + $xd_=@x[$d3] if ($odd); + push @ret,( + "&str ($xc,'[sp,#4*(16+$c0)]')", + "&ldr ($xc,'[sp,#4*(16+$c2)]')", + "&add (@x[$a2],@x[$a2],@x[$b2])", + "&mov ($xd,$xd,'ror#16')", + "&str ($xc_,'[sp,#4*(16+$c1)]')", + "&ldr ($xc_,'[sp,#4*(16+$c3)]')", + "&add (@x[$a3],@x[$a3],@x[$b3])", + "&mov ($xd_,$xd_,'ror#16')", + "&eor ($xd,$xd,@x[$a2],'ror#16')", + "&eor ($xd_,$xd_,@x[$a3],'ror#16')", + + "&add ($xc,$xc,$xd)", + "&mov (@x[$b2],@x[$b2],'ror#20')", + "&add ($xc_,$xc_,$xd_)", + "&mov (@x[$b3],@x[$b3],'ror#20')", + "&eor (@x[$b2],@x[$b2],$xc,'ror#20')", + "&eor (@x[$b3],@x[$b3],$xc_,'ror#20')", + + "&add (@x[$a2],@x[$a2],@x[$b2])", + "&mov ($xd,$xd,'ror#24')", + "&add (@x[$a3],@x[$a3],@x[$b3])", + "&mov ($xd_,$xd_,'ror#24')", + "&eor ($xd,$xd,@x[$a2],'ror#24')", + "&eor ($xd_,$xd_,@x[$a3],'ror#24')", + + "&add ($xc,$xc,$xd)", + "&mov (@x[$b2],@x[$b2],'ror#25')", + "&add ($xc_,$xc_,$xd_)", + "&mov (@x[$b3],@x[$b3],'ror#25')", + "&eor (@x[$b2],@x[$b2],$xc,'ror#25')", + "&eor (@x[$b3],@x[$b3],$xc_,'ror#25')" ); + + @ret; +} + +$code.=<<___; +#include + +.text +#if defined(__thumb2__) +.syntax unified +.thumb +#else +.code 32 +#endif + +#if defined(__thumb2__) || defined(__clang__) +#define ldrhsb ldrbhs +#endif + +.align 5 +.Lsigma: +.long 0x61707865,0x3320646e,0x79622d32,0x6b206574 @ endian-neutral +.Lone: +.long 1,0,0,0 +#if __ARM_MAX_ARCH__>=7 +.LOPENSSL_armcap: +.word OPENSSL_armcap_P-.LChaCha20_ctr32 +#else +.word -1 +#endif + +.globl ChaCha20_ctr32 +.type ChaCha20_ctr32,%function +.align 5 +ChaCha20_ctr32: +.LChaCha20_ctr32: + ldr r12,[sp,#0] @ pull pointer to counter and nonce + stmdb sp!,{r0-r2,r4-r11,lr} +#if __ARM_ARCH__<7 && !defined(__thumb2__) + sub r14,pc,#16 @ ChaCha20_ctr32 +#else + adr r14,.LChaCha20_ctr32 +#endif + cmp r2,#0 @ len==0? +#ifdef __thumb2__ + itt eq +#endif + addeq sp,sp,#4*3 + beq .Lno_data +#if __ARM_MAX_ARCH__>=7 + cmp r2,#192 @ test len + bls .Lshort + ldr r4,[r14,#-32] + ldr r4,[r14,r4] +# ifdef __APPLE__ + ldr r4,[r4] +# endif + tst r4,#ARMV7_NEON + bne .LChaCha20_neon +.Lshort: +#endif + ldmia r12,{r4-r7} @ load counter and nonce + sub sp,sp,#4*(16) @ off-load area + sub r14,r14,#64 @ .Lsigma + stmdb sp!,{r4-r7} @ copy counter and nonce + ldmia r3,{r4-r11} @ load key + ldmia r14,{r0-r3} @ load sigma + stmdb sp!,{r4-r11} @ copy key + stmdb sp!,{r0-r3} @ copy sigma + str r10,[sp,#4*(16+10)] @ off-load "@x[10]" + str r11,[sp,#4*(16+11)] @ off-load "@x[11]" + b .Loop_outer_enter + +.align 4 +.Loop_outer: + ldmia sp,{r0-r9} @ load key material + str @t[3],[sp,#4*(32+2)] @ save len + str r12, [sp,#4*(32+1)] @ save inp + str r14, [sp,#4*(32+0)] @ save out +.Loop_outer_enter: + ldr @t[3], [sp,#4*(15)] + ldr @x[12],[sp,#4*(12)] @ modulo-scheduled load + ldr @t[2], [sp,#4*(13)] + ldr @x[14],[sp,#4*(14)] + str @t[3], [sp,#4*(16+15)] + mov @t[3],#10 + b .Loop + +.align 4 +.Loop: + subs @t[3],@t[3],#1 +___ + foreach (&ROUND(0, 4, 8,12)) { eval; } + foreach (&ROUND(0, 5,10,15)) { eval; } +$code.=<<___; + bne .Loop + + ldr @t[3],[sp,#4*(32+2)] @ load len + + str @t[0], [sp,#4*(16+8)] @ modulo-scheduled store + str @t[1], [sp,#4*(16+9)] + str @x[12],[sp,#4*(16+12)] + str @t[2], [sp,#4*(16+13)] + str @x[14],[sp,#4*(16+14)] + + @ at this point we have first half of 512-bit result in + @ @x[0-7] and second half at sp+4*(16+8) + + cmp @t[3],#64 @ done yet? +#ifdef __thumb2__ + itete lo +#endif + addlo r12,sp,#4*(0) @ shortcut or ... + ldrhs r12,[sp,#4*(32+1)] @ ... load inp + addlo r14,sp,#4*(0) @ shortcut or ... + ldrhs r14,[sp,#4*(32+0)] @ ... load out + + ldr @t[0],[sp,#4*(0)] @ load key material + ldr @t[1],[sp,#4*(1)] + +#if __ARM_ARCH__>=6 || !defined(__ARMEB__) +# if __ARM_ARCH__<7 + orr @t[2],r12,r14 + tst @t[2],#3 @ are input and output aligned? + ldr @t[2],[sp,#4*(2)] + bne .Lunaligned + cmp @t[3],#64 @ restore flags +# else + ldr @t[2],[sp,#4*(2)] +# endif + ldr @t[3],[sp,#4*(3)] + + add @x[0],@x[0],@t[0] @ accumulate key material + add @x[1],@x[1],@t[1] +# ifdef __thumb2__ + itt hs +# endif + ldrhs @t[0],[r12],#16 @ load input + ldrhs @t[1],[r12,#-12] + + add @x[2],@x[2],@t[2] + add @x[3],@x[3],@t[3] +# ifdef __thumb2__ + itt hs +# endif + ldrhs @t[2],[r12,#-8] + ldrhs @t[3],[r12,#-4] +# if __ARM_ARCH__>=6 && defined(__ARMEB__) + rev @x[0],@x[0] + rev @x[1],@x[1] + rev @x[2],@x[2] + rev @x[3],@x[3] +# endif +# ifdef __thumb2__ + itt hs +# endif + eorhs @x[0],@x[0],@t[0] @ xor with input + eorhs @x[1],@x[1],@t[1] + add @t[0],sp,#4*(4) + str @x[0],[r14],#16 @ store output +# ifdef __thumb2__ + itt hs +# endif + eorhs @x[2],@x[2],@t[2] + eorhs @x[3],@x[3],@t[3] + ldmia @t[0],{@t[0]-@t[3]} @ load key material + str @x[1],[r14,#-12] + str @x[2],[r14,#-8] + str @x[3],[r14,#-4] + + add @x[4],@x[4],@t[0] @ accumulate key material + add @x[5],@x[5],@t[1] +# ifdef __thumb2__ + itt hs +# endif + ldrhs @t[0],[r12],#16 @ load input + ldrhs @t[1],[r12,#-12] + add @x[6],@x[6],@t[2] + add @x[7],@x[7],@t[3] +# ifdef __thumb2__ + itt hs +# endif + ldrhs @t[2],[r12,#-8] + ldrhs @t[3],[r12,#-4] +# if __ARM_ARCH__>=6 && defined(__ARMEB__) + rev @x[4],@x[4] + rev @x[5],@x[5] + rev @x[6],@x[6] + rev @x[7],@x[7] +# endif +# ifdef __thumb2__ + itt hs +# endif + eorhs @x[4],@x[4],@t[0] + eorhs @x[5],@x[5],@t[1] + add @t[0],sp,#4*(8) + str @x[4],[r14],#16 @ store output +# ifdef __thumb2__ + itt hs +# endif + eorhs @x[6],@x[6],@t[2] + eorhs @x[7],@x[7],@t[3] + str @x[5],[r14,#-12] + ldmia @t[0],{@t[0]-@t[3]} @ load key material + str @x[6],[r14,#-8] + add @x[0],sp,#4*(16+8) + str @x[7],[r14,#-4] + + ldmia @x[0],{@x[0]-@x[7]} @ load second half + + add @x[0],@x[0],@t[0] @ accumulate key material + add @x[1],@x[1],@t[1] +# ifdef __thumb2__ + itt hs +# endif + ldrhs @t[0],[r12],#16 @ load input + ldrhs @t[1],[r12,#-12] +# ifdef __thumb2__ + itt hi +# endif + strhi @t[2],[sp,#4*(16+10)] @ copy "@x[10]" while at it + strhi @t[3],[sp,#4*(16+11)] @ copy "@x[11]" while at it + add @x[2],@x[2],@t[2] + add @x[3],@x[3],@t[3] +# ifdef __thumb2__ + itt hs +# endif + ldrhs @t[2],[r12,#-8] + ldrhs @t[3],[r12,#-4] +# if __ARM_ARCH__>=6 && defined(__ARMEB__) + rev @x[0],@x[0] + rev @x[1],@x[1] + rev @x[2],@x[2] + rev @x[3],@x[3] +# endif +# ifdef __thumb2__ + itt hs +# endif + eorhs @x[0],@x[0],@t[0] + eorhs @x[1],@x[1],@t[1] + add @t[0],sp,#4*(12) + str @x[0],[r14],#16 @ store output +# ifdef __thumb2__ + itt hs +# endif + eorhs @x[2],@x[2],@t[2] + eorhs @x[3],@x[3],@t[3] + str @x[1],[r14,#-12] + ldmia @t[0],{@t[0]-@t[3]} @ load key material + str @x[2],[r14,#-8] + str @x[3],[r14,#-4] + + add @x[4],@x[4],@t[0] @ accumulate key material + add @x[5],@x[5],@t[1] +# ifdef __thumb2__ + itt hi +# endif + addhi @t[0],@t[0],#1 @ next counter value + strhi @t[0],[sp,#4*(12)] @ save next counter value +# ifdef __thumb2__ + itt hs +# endif + ldrhs @t[0],[r12],#16 @ load input + ldrhs @t[1],[r12,#-12] + add @x[6],@x[6],@t[2] + add @x[7],@x[7],@t[3] +# ifdef __thumb2__ + itt hs +# endif + ldrhs @t[2],[r12,#-8] + ldrhs @t[3],[r12,#-4] +# if __ARM_ARCH__>=6 && defined(__ARMEB__) + rev @x[4],@x[4] + rev @x[5],@x[5] + rev @x[6],@x[6] + rev @x[7],@x[7] +# endif +# ifdef __thumb2__ + itt hs +# endif + eorhs @x[4],@x[4],@t[0] + eorhs @x[5],@x[5],@t[1] +# ifdef __thumb2__ + it ne +# endif + ldrne @t[0],[sp,#4*(32+2)] @ re-load len +# ifdef __thumb2__ + itt hs +# endif + eorhs @x[6],@x[6],@t[2] + eorhs @x[7],@x[7],@t[3] + str @x[4],[r14],#16 @ store output + str @x[5],[r14,#-12] +# ifdef __thumb2__ + it hs +# endif + subhs @t[3],@t[0],#64 @ len-=64 + str @x[6],[r14,#-8] + str @x[7],[r14,#-4] + bhi .Loop_outer + + beq .Ldone +# if __ARM_ARCH__<7 + b .Ltail + +.align 4 +.Lunaligned: @ unaligned endian-neutral path + cmp @t[3],#64 @ restore flags +# endif +#endif +#if __ARM_ARCH__<7 + ldr @t[3],[sp,#4*(3)] +___ +for ($i=0;$i<16;$i+=4) { +my $j=$i&0x7; + +$code.=<<___ if ($i==4); + add @x[0],sp,#4*(16+8) +___ +$code.=<<___ if ($i==8); + ldmia @x[0],{@x[0]-@x[7]} @ load second half +# ifdef __thumb2__ + itt hi +# endif + strhi @t[2],[sp,#4*(16+10)] @ copy "@x[10]" + strhi @t[3],[sp,#4*(16+11)] @ copy "@x[11]" +___ +$code.=<<___; + add @x[$j+0],@x[$j+0],@t[0] @ accumulate key material +___ +$code.=<<___ if ($i==12); +# ifdef __thumb2__ + itt hi +# endif + addhi @t[0],@t[0],#1 @ next counter value + strhi @t[0],[sp,#4*(12)] @ save next counter value +___ +$code.=<<___; + add @x[$j+1],@x[$j+1],@t[1] + add @x[$j+2],@x[$j+2],@t[2] +# ifdef __thumb2__ + itete lo +# endif + eorlo @t[0],@t[0],@t[0] @ zero or ... + ldrhsb @t[0],[r12],#16 @ ... load input + eorlo @t[1],@t[1],@t[1] + ldrhsb @t[1],[r12,#-12] + + add @x[$j+3],@x[$j+3],@t[3] +# ifdef __thumb2__ + itete lo +# endif + eorlo @t[2],@t[2],@t[2] + ldrhsb @t[2],[r12,#-8] + eorlo @t[3],@t[3],@t[3] + ldrhsb @t[3],[r12,#-4] + + eor @x[$j+0],@t[0],@x[$j+0] @ xor with input (or zero) + eor @x[$j+1],@t[1],@x[$j+1] +# ifdef __thumb2__ + itt hs +# endif + ldrhsb @t[0],[r12,#-15] @ load more input + ldrhsb @t[1],[r12,#-11] + eor @x[$j+2],@t[2],@x[$j+2] + strb @x[$j+0],[r14],#16 @ store output + eor @x[$j+3],@t[3],@x[$j+3] +# ifdef __thumb2__ + itt hs +# endif + ldrhsb @t[2],[r12,#-7] + ldrhsb @t[3],[r12,#-3] + strb @x[$j+1],[r14,#-12] + eor @x[$j+0],@t[0],@x[$j+0],lsr#8 + strb @x[$j+2],[r14,#-8] + eor @x[$j+1],@t[1],@x[$j+1],lsr#8 +# ifdef __thumb2__ + itt hs +# endif + ldrhsb @t[0],[r12,#-14] @ load more input + ldrhsb @t[1],[r12,#-10] + strb @x[$j+3],[r14,#-4] + eor @x[$j+2],@t[2],@x[$j+2],lsr#8 + strb @x[$j+0],[r14,#-15] + eor @x[$j+3],@t[3],@x[$j+3],lsr#8 +# ifdef __thumb2__ + itt hs +# endif + ldrhsb @t[2],[r12,#-6] + ldrhsb @t[3],[r12,#-2] + strb @x[$j+1],[r14,#-11] + eor @x[$j+0],@t[0],@x[$j+0],lsr#8 + strb @x[$j+2],[r14,#-7] + eor @x[$j+1],@t[1],@x[$j+1],lsr#8 +# ifdef __thumb2__ + itt hs +# endif + ldrhsb @t[0],[r12,#-13] @ load more input + ldrhsb @t[1],[r12,#-9] + strb @x[$j+3],[r14,#-3] + eor @x[$j+2],@t[2],@x[$j+2],lsr#8 + strb @x[$j+0],[r14,#-14] + eor @x[$j+3],@t[3],@x[$j+3],lsr#8 +# ifdef __thumb2__ + itt hs +# endif + ldrhsb @t[2],[r12,#-5] + ldrhsb @t[3],[r12,#-1] + strb @x[$j+1],[r14,#-10] + strb @x[$j+2],[r14,#-6] + eor @x[$j+0],@t[0],@x[$j+0],lsr#8 + strb @x[$j+3],[r14,#-2] + eor @x[$j+1],@t[1],@x[$j+1],lsr#8 + strb @x[$j+0],[r14,#-13] + eor @x[$j+2],@t[2],@x[$j+2],lsr#8 + strb @x[$j+1],[r14,#-9] + eor @x[$j+3],@t[3],@x[$j+3],lsr#8 + strb @x[$j+2],[r14,#-5] + strb @x[$j+3],[r14,#-1] +___ +$code.=<<___ if ($i<12); + add @t[0],sp,#4*(4+$i) + ldmia @t[0],{@t[0]-@t[3]} @ load key material +___ +} +$code.=<<___; +# ifdef __thumb2__ + it ne +# endif + ldrne @t[0],[sp,#4*(32+2)] @ re-load len +# ifdef __thumb2__ + it hs +# endif + subhs @t[3],@t[0],#64 @ len-=64 + bhi .Loop_outer + + beq .Ldone +#endif + +.Ltail: + ldr r12,[sp,#4*(32+1)] @ load inp + add @t[1],sp,#4*(0) + ldr r14,[sp,#4*(32+0)] @ load out + +.Loop_tail: + ldrb @t[2],[@t[1]],#1 @ read buffer on stack + ldrb @t[3],[r12],#1 @ read input + subs @t[0],@t[0],#1 + eor @t[3],@t[3],@t[2] + strb @t[3],[r14],#1 @ store output + bne .Loop_tail + +.Ldone: + add sp,sp,#4*(32+3) +.Lno_data: + ldmia sp!,{r4-r11,pc} +.size ChaCha20_ctr32,.-ChaCha20_ctr32 +___ + +{{{ +my ($a0,$b0,$c0,$d0,$a1,$b1,$c1,$d1,$a2,$b2,$c2,$d2,$t0,$t1,$t2,$t3) = + map("q$_",(0..15)); + +sub NEONROUND { +my $odd = pop; +my ($a,$b,$c,$d,$t)=@_; + + ( + "&vadd_i32 ($a,$a,$b)", + "&veor ($d,$d,$a)", + "&vrev32_16 ($d,$d)", # vrot ($d,16) + + "&vadd_i32 ($c,$c,$d)", + "&veor ($t,$b,$c)", + "&vshr_u32 ($b,$t,20)", + "&vsli_32 ($b,$t,12)", + + "&vadd_i32 ($a,$a,$b)", + "&veor ($t,$d,$a)", + "&vshr_u32 ($d,$t,24)", + "&vsli_32 ($d,$t,8)", + + "&vadd_i32 ($c,$c,$d)", + "&veor ($t,$b,$c)", + "&vshr_u32 ($b,$t,25)", + "&vsli_32 ($b,$t,7)", + + "&vext_8 ($c,$c,$c,8)", + "&vext_8 ($b,$b,$b,$odd?12:4)", + "&vext_8 ($d,$d,$d,$odd?4:12)" + ); +} + +$code.=<<___; +#if __ARM_MAX_ARCH__>=7 +.arch armv7-a +.fpu neon + +.type ChaCha20_neon,%function +.align 5 +ChaCha20_neon: + ldr r12,[sp,#0] @ pull pointer to counter and nonce + stmdb sp!,{r0-r2,r4-r11,lr} +.LChaCha20_neon: + adr r14,.Lsigma + vstmdb sp!,{d8-d15} @ ABI spec says so + stmdb sp!,{r0-r3} + + vld1.32 {$b0-$c0},[r3] @ load key + ldmia r3,{r4-r11} @ load key + + sub sp,sp,#4*(16+16) + vld1.32 {$d0},[r12] @ load counter and nonce + add r12,sp,#4*8 + ldmia r14,{r0-r3} @ load sigma + vld1.32 {$a0},[r14]! @ load sigma + vld1.32 {$t0},[r14] @ one + vst1.32 {$c0-$d0},[r12] @ copy 1/2key|counter|nonce + vst1.32 {$a0-$b0},[sp] @ copy sigma|1/2key + + str r10,[sp,#4*(16+10)] @ off-load "@x[10]" + str r11,[sp,#4*(16+11)] @ off-load "@x[11]" + vshl.i32 $t1#lo,$t0#lo,#1 @ two + vstr $t0#lo,[sp,#4*(16+0)] + vshl.i32 $t2#lo,$t0#lo,#2 @ four + vstr $t1#lo,[sp,#4*(16+2)] + vmov $a1,$a0 + vstr $t2#lo,[sp,#4*(16+4)] + vmov $a2,$a0 + vmov $b1,$b0 + vmov $b2,$b0 + b .Loop_neon_enter + +.align 4 +.Loop_neon_outer: + ldmia sp,{r0-r9} @ load key material + cmp @t[3],#64*2 @ if len<=64*2 + bls .Lbreak_neon @ switch to integer-only + vmov $a1,$a0 + str @t[3],[sp,#4*(32+2)] @ save len + vmov $a2,$a0 + str r12, [sp,#4*(32+1)] @ save inp + vmov $b1,$b0 + str r14, [sp,#4*(32+0)] @ save out + vmov $b2,$b0 +.Loop_neon_enter: + ldr @t[3], [sp,#4*(15)] + vadd.i32 $d1,$d0,$t0 @ counter+1 + ldr @x[12],[sp,#4*(12)] @ modulo-scheduled load + vmov $c1,$c0 + ldr @t[2], [sp,#4*(13)] + vmov $c2,$c0 + ldr @x[14],[sp,#4*(14)] + vadd.i32 $d2,$d1,$t0 @ counter+2 + str @t[3], [sp,#4*(16+15)] + mov @t[3],#10 + add @x[12],@x[12],#3 @ counter+3 + b .Loop_neon + +.align 4 +.Loop_neon: + subs @t[3],@t[3],#1 +___ + my @thread0=&NEONROUND($a0,$b0,$c0,$d0,$t0,0); + my @thread1=&NEONROUND($a1,$b1,$c1,$d1,$t1,0); + my @thread2=&NEONROUND($a2,$b2,$c2,$d2,$t2,0); + my @thread3=&ROUND(0,4,8,12); + + foreach (@thread0) { + eval; eval(shift(@thread3)); + eval(shift(@thread1)); eval(shift(@thread3)); + eval(shift(@thread2)); eval(shift(@thread3)); + } + + @thread0=&NEONROUND($a0,$b0,$c0,$d0,$t0,1); + @thread1=&NEONROUND($a1,$b1,$c1,$d1,$t1,1); + @thread2=&NEONROUND($a2,$b2,$c2,$d2,$t2,1); + @thread3=&ROUND(0,5,10,15); + + foreach (@thread0) { + eval; eval(shift(@thread3)); + eval(shift(@thread1)); eval(shift(@thread3)); + eval(shift(@thread2)); eval(shift(@thread3)); + } +$code.=<<___; + bne .Loop_neon + + add @t[3],sp,#32 + vld1.32 {$t0-$t1},[sp] @ load key material + vld1.32 {$t2-$t3},[@t[3]] + + ldr @t[3],[sp,#4*(32+2)] @ load len + + str @t[0], [sp,#4*(16+8)] @ modulo-scheduled store + str @t[1], [sp,#4*(16+9)] + str @x[12],[sp,#4*(16+12)] + str @t[2], [sp,#4*(16+13)] + str @x[14],[sp,#4*(16+14)] + + @ at this point we have first half of 512-bit result in + @ @x[0-7] and second half at sp+4*(16+8) + + ldr r12,[sp,#4*(32+1)] @ load inp + ldr r14,[sp,#4*(32+0)] @ load out + + vadd.i32 $a0,$a0,$t0 @ accumulate key material + vadd.i32 $a1,$a1,$t0 + vadd.i32 $a2,$a2,$t0 + vldr $t0#lo,[sp,#4*(16+0)] @ one + + vadd.i32 $b0,$b0,$t1 + vadd.i32 $b1,$b1,$t1 + vadd.i32 $b2,$b2,$t1 + vldr $t1#lo,[sp,#4*(16+2)] @ two + + vadd.i32 $c0,$c0,$t2 + vadd.i32 $c1,$c1,$t2 + vadd.i32 $c2,$c2,$t2 + vadd.i32 $d1#lo,$d1#lo,$t0#lo @ counter+1 + vadd.i32 $d2#lo,$d2#lo,$t1#lo @ counter+2 + + vadd.i32 $d0,$d0,$t3 + vadd.i32 $d1,$d1,$t3 + vadd.i32 $d2,$d2,$t3 + + cmp @t[3],#64*4 + blo .Ltail_neon + + vld1.8 {$t0-$t1},[r12]! @ load input + mov @t[3],sp + vld1.8 {$t2-$t3},[r12]! + veor $a0,$a0,$t0 @ xor with input + veor $b0,$b0,$t1 + vld1.8 {$t0-$t1},[r12]! + veor $c0,$c0,$t2 + veor $d0,$d0,$t3 + vld1.8 {$t2-$t3},[r12]! + + veor $a1,$a1,$t0 + vst1.8 {$a0-$b0},[r14]! @ store output + veor $b1,$b1,$t1 + vld1.8 {$t0-$t1},[r12]! + veor $c1,$c1,$t2 + vst1.8 {$c0-$d0},[r14]! + veor $d1,$d1,$t3 + vld1.8 {$t2-$t3},[r12]! + + veor $a2,$a2,$t0 + vld1.32 {$a0-$b0},[@t[3]]! @ load for next iteration + veor $t0#hi,$t0#hi,$t0#hi + vldr $t0#lo,[sp,#4*(16+4)] @ four + veor $b2,$b2,$t1 + vld1.32 {$c0-$d0},[@t[3]] + veor $c2,$c2,$t2 + vst1.8 {$a1-$b1},[r14]! + veor $d2,$d2,$t3 + vst1.8 {$c1-$d1},[r14]! + + vadd.i32 $d0#lo,$d0#lo,$t0#lo @ next counter value + vldr $t0#lo,[sp,#4*(16+0)] @ one + + ldmia sp,{@t[0]-@t[3]} @ load key material + add @x[0],@x[0],@t[0] @ accumulate key material + ldr @t[0],[r12],#16 @ load input + vst1.8 {$a2-$b2},[r14]! + add @x[1],@x[1],@t[1] + ldr @t[1],[r12,#-12] + vst1.8 {$c2-$d2},[r14]! + add @x[2],@x[2],@t[2] + ldr @t[2],[r12,#-8] + add @x[3],@x[3],@t[3] + ldr @t[3],[r12,#-4] +# ifdef __ARMEB__ + rev @x[0],@x[0] + rev @x[1],@x[1] + rev @x[2],@x[2] + rev @x[3],@x[3] +# endif + eor @x[0],@x[0],@t[0] @ xor with input + add @t[0],sp,#4*(4) + eor @x[1],@x[1],@t[1] + str @x[0],[r14],#16 @ store output + eor @x[2],@x[2],@t[2] + str @x[1],[r14,#-12] + eor @x[3],@x[3],@t[3] + ldmia @t[0],{@t[0]-@t[3]} @ load key material + str @x[2],[r14,#-8] + str @x[3],[r14,#-4] + + add @x[4],@x[4],@t[0] @ accumulate key material + ldr @t[0],[r12],#16 @ load input + add @x[5],@x[5],@t[1] + ldr @t[1],[r12,#-12] + add @x[6],@x[6],@t[2] + ldr @t[2],[r12,#-8] + add @x[7],@x[7],@t[3] + ldr @t[3],[r12,#-4] +# ifdef __ARMEB__ + rev @x[4],@x[4] + rev @x[5],@x[5] + rev @x[6],@x[6] + rev @x[7],@x[7] +# endif + eor @x[4],@x[4],@t[0] + add @t[0],sp,#4*(8) + eor @x[5],@x[5],@t[1] + str @x[4],[r14],#16 @ store output + eor @x[6],@x[6],@t[2] + str @x[5],[r14,#-12] + eor @x[7],@x[7],@t[3] + ldmia @t[0],{@t[0]-@t[3]} @ load key material + str @x[6],[r14,#-8] + add @x[0],sp,#4*(16+8) + str @x[7],[r14,#-4] + + ldmia @x[0],{@x[0]-@x[7]} @ load second half + + add @x[0],@x[0],@t[0] @ accumulate key material + ldr @t[0],[r12],#16 @ load input + add @x[1],@x[1],@t[1] + ldr @t[1],[r12,#-12] +# ifdef __thumb2__ + it hi +# endif + strhi @t[2],[sp,#4*(16+10)] @ copy "@x[10]" while at it + add @x[2],@x[2],@t[2] + ldr @t[2],[r12,#-8] +# ifdef __thumb2__ + it hi +# endif + strhi @t[3],[sp,#4*(16+11)] @ copy "@x[11]" while at it + add @x[3],@x[3],@t[3] + ldr @t[3],[r12,#-4] +# ifdef __ARMEB__ + rev @x[0],@x[0] + rev @x[1],@x[1] + rev @x[2],@x[2] + rev @x[3],@x[3] +# endif + eor @x[0],@x[0],@t[0] + add @t[0],sp,#4*(12) + eor @x[1],@x[1],@t[1] + str @x[0],[r14],#16 @ store output + eor @x[2],@x[2],@t[2] + str @x[1],[r14,#-12] + eor @x[3],@x[3],@t[3] + ldmia @t[0],{@t[0]-@t[3]} @ load key material + str @x[2],[r14,#-8] + str @x[3],[r14,#-4] + + add @x[4],@x[4],@t[0] @ accumulate key material + add @t[0],@t[0],#4 @ next counter value + add @x[5],@x[5],@t[1] + str @t[0],[sp,#4*(12)] @ save next counter value + ldr @t[0],[r12],#16 @ load input + add @x[6],@x[6],@t[2] + add @x[4],@x[4],#3 @ counter+3 + ldr @t[1],[r12,#-12] + add @x[7],@x[7],@t[3] + ldr @t[2],[r12,#-8] + ldr @t[3],[r12,#-4] +# ifdef __ARMEB__ + rev @x[4],@x[4] + rev @x[5],@x[5] + rev @x[6],@x[6] + rev @x[7],@x[7] +# endif + eor @x[4],@x[4],@t[0] +# ifdef __thumb2__ + it hi +# endif + ldrhi @t[0],[sp,#4*(32+2)] @ re-load len + eor @x[5],@x[5],@t[1] + eor @x[6],@x[6],@t[2] + str @x[4],[r14],#16 @ store output + eor @x[7],@x[7],@t[3] + str @x[5],[r14,#-12] + sub @t[3],@t[0],#64*4 @ len-=64*4 + str @x[6],[r14,#-8] + str @x[7],[r14,#-4] + bhi .Loop_neon_outer + + b .Ldone_neon + +.align 4 +.Lbreak_neon: + @ harmonize NEON and integer-only stack frames: load data + @ from NEON frame, but save to integer-only one; distance + @ between the two is 4*(32+4+16-32)=4*(20). + + str @t[3], [sp,#4*(20+32+2)] @ save len + add @t[3],sp,#4*(32+4) + str r12, [sp,#4*(20+32+1)] @ save inp + str r14, [sp,#4*(20+32+0)] @ save out + + ldr @x[12],[sp,#4*(16+10)] + ldr @x[14],[sp,#4*(16+11)] + vldmia @t[3],{d8-d15} @ fulfill ABI requirement + str @x[12],[sp,#4*(20+16+10)] @ copy "@x[10]" + str @x[14],[sp,#4*(20+16+11)] @ copy "@x[11]" + + ldr @t[3], [sp,#4*(15)] + ldr @x[12],[sp,#4*(12)] @ modulo-scheduled load + ldr @t[2], [sp,#4*(13)] + ldr @x[14],[sp,#4*(14)] + str @t[3], [sp,#4*(20+16+15)] + add @t[3],sp,#4*(20) + vst1.32 {$a0-$b0},[@t[3]]! @ copy key + add sp,sp,#4*(20) @ switch frame + vst1.32 {$c0-$d0},[@t[3]] + mov @t[3],#10 + b .Loop @ go integer-only + +.align 4 +.Ltail_neon: + cmp @t[3],#64*3 + bhs .L192_or_more_neon + cmp @t[3],#64*2 + bhs .L128_or_more_neon + cmp @t[3],#64*1 + bhs .L64_or_more_neon + + add @t[0],sp,#4*(8) + vst1.8 {$a0-$b0},[sp] + add @t[2],sp,#4*(0) + vst1.8 {$c0-$d0},[@t[0]] + b .Loop_tail_neon + +.align 4 +.L64_or_more_neon: + vld1.8 {$t0-$t1},[r12]! + vld1.8 {$t2-$t3},[r12]! + veor $a0,$a0,$t0 + veor $b0,$b0,$t1 + veor $c0,$c0,$t2 + veor $d0,$d0,$t3 + vst1.8 {$a0-$b0},[r14]! + vst1.8 {$c0-$d0},[r14]! + + beq .Ldone_neon + + add @t[0],sp,#4*(8) + vst1.8 {$a1-$b1},[sp] + add @t[2],sp,#4*(0) + vst1.8 {$c1-$d1},[@t[0]] + sub @t[3],@t[3],#64*1 @ len-=64*1 + b .Loop_tail_neon + +.align 4 +.L128_or_more_neon: + vld1.8 {$t0-$t1},[r12]! + vld1.8 {$t2-$t3},[r12]! + veor $a0,$a0,$t0 + veor $b0,$b0,$t1 + vld1.8 {$t0-$t1},[r12]! + veor $c0,$c0,$t2 + veor $d0,$d0,$t3 + vld1.8 {$t2-$t3},[r12]! + + veor $a1,$a1,$t0 + veor $b1,$b1,$t1 + vst1.8 {$a0-$b0},[r14]! + veor $c1,$c1,$t2 + vst1.8 {$c0-$d0},[r14]! + veor $d1,$d1,$t3 + vst1.8 {$a1-$b1},[r14]! + vst1.8 {$c1-$d1},[r14]! + + beq .Ldone_neon + + add @t[0],sp,#4*(8) + vst1.8 {$a2-$b2},[sp] + add @t[2],sp,#4*(0) + vst1.8 {$c2-$d2},[@t[0]] + sub @t[3],@t[3],#64*2 @ len-=64*2 + b .Loop_tail_neon + +.align 4 +.L192_or_more_neon: + vld1.8 {$t0-$t1},[r12]! + vld1.8 {$t2-$t3},[r12]! + veor $a0,$a0,$t0 + veor $b0,$b0,$t1 + vld1.8 {$t0-$t1},[r12]! + veor $c0,$c0,$t2 + veor $d0,$d0,$t3 + vld1.8 {$t2-$t3},[r12]! + + veor $a1,$a1,$t0 + veor $b1,$b1,$t1 + vld1.8 {$t0-$t1},[r12]! + veor $c1,$c1,$t2 + vst1.8 {$a0-$b0},[r14]! + veor $d1,$d1,$t3 + vld1.8 {$t2-$t3},[r12]! + + veor $a2,$a2,$t0 + vst1.8 {$c0-$d0},[r14]! + veor $b2,$b2,$t1 + vst1.8 {$a1-$b1},[r14]! + veor $c2,$c2,$t2 + vst1.8 {$c1-$d1},[r14]! + veor $d2,$d2,$t3 + vst1.8 {$a2-$b2},[r14]! + vst1.8 {$c2-$d2},[r14]! + + beq .Ldone_neon + + ldmia sp,{@t[0]-@t[3]} @ load key material + add @x[0],@x[0],@t[0] @ accumulate key material + add @t[0],sp,#4*(4) + add @x[1],@x[1],@t[1] + add @x[2],@x[2],@t[2] + add @x[3],@x[3],@t[3] + ldmia @t[0],{@t[0]-@t[3]} @ load key material + + add @x[4],@x[4],@t[0] @ accumulate key material + add @t[0],sp,#4*(8) + add @x[5],@x[5],@t[1] + add @x[6],@x[6],@t[2] + add @x[7],@x[7],@t[3] + ldmia @t[0],{@t[0]-@t[3]} @ load key material +# ifdef __ARMEB__ + rev @x[0],@x[0] + rev @x[1],@x[1] + rev @x[2],@x[2] + rev @x[3],@x[3] + rev @x[4],@x[4] + rev @x[5],@x[5] + rev @x[6],@x[6] + rev @x[7],@x[7] +# endif + stmia sp,{@x[0]-@x[7]} + add @x[0],sp,#4*(16+8) + + ldmia @x[0],{@x[0]-@x[7]} @ load second half + + add @x[0],@x[0],@t[0] @ accumulate key material + add @t[0],sp,#4*(12) + add @x[1],@x[1],@t[1] + add @x[2],@x[2],@t[2] + add @x[3],@x[3],@t[3] + ldmia @t[0],{@t[0]-@t[3]} @ load key material + + add @x[4],@x[4],@t[0] @ accumulate key material + add @t[0],sp,#4*(8) + add @x[5],@x[5],@t[1] + add @x[4],@x[4],#3 @ counter+3 + add @x[6],@x[6],@t[2] + add @x[7],@x[7],@t[3] + ldr @t[3],[sp,#4*(32+2)] @ re-load len +# ifdef __ARMEB__ + rev @x[0],@x[0] + rev @x[1],@x[1] + rev @x[2],@x[2] + rev @x[3],@x[3] + rev @x[4],@x[4] + rev @x[5],@x[5] + rev @x[6],@x[6] + rev @x[7],@x[7] +# endif + stmia @t[0],{@x[0]-@x[7]} + add @t[2],sp,#4*(0) + sub @t[3],@t[3],#64*3 @ len-=64*3 + +.Loop_tail_neon: + ldrb @t[0],[@t[2]],#1 @ read buffer on stack + ldrb @t[1],[r12],#1 @ read input + subs @t[3],@t[3],#1 + eor @t[0],@t[0],@t[1] + strb @t[0],[r14],#1 @ store ouput + bne .Loop_tail_neon + +.Ldone_neon: + add sp,sp,#4*(32+4) + vldmia sp,{d8-d15} + add sp,sp,#4*(16+3) + ldmia sp!,{r4-r11,pc} +.size ChaCha20_neon,.-ChaCha20_neon +.comm OPENSSL_armcap_P,4,4 +#endif +___ +}}} + +foreach (split("\n",$code)) { + s/\`([^\`]*)\`/eval $1/geo; + + s/\bq([0-9]+)#(lo|hi)/sprintf "d%d",2*$1+($2 eq "hi")/geo; + + print $_,"\n"; +} +close STDOUT; diff --git a/external/boringssl/crypto/chacha/asm/chacha-armv8.pl b/external/boringssl/crypto/chacha/asm/chacha-armv8.pl new file mode 100755 index 0000000000..215d9657a1 --- /dev/null +++ b/external/boringssl/crypto/chacha/asm/chacha-armv8.pl @@ -0,0 +1,1127 @@ +#!/usr/bin/env perl +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# June 2015 +# +# ChaCha20 for ARMv8. +# +# Performance in cycles per byte out of large buffer. +# +# IALU/gcc-4.9 3xNEON+1xIALU 6xNEON+2xIALU +# +# Apple A7 5.50/+49% 3.33 1.70 +# Cortex-A53 8.40/+80% 4.72 4.72(*) +# Cortex-A57 8.06/+43% 4.90 4.43(**) +# Denver 4.50/+82% 2.63 2.67(*) +# X-Gene 9.50/+46% 8.82 8.89(*) +# +# (*) it's expected that doubling interleave factor doesn't help +# all processors, only those with higher NEON latency and +# higher instruction issue rate; +# (**) expected improvement was actually higher; + +$flavour=shift; +$output=shift; + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or +die "can't locate arm-xlate.pl"; + +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; + +sub AUTOLOAD() # thunk [simplified] x86-style perlasm +{ my $opcode = $AUTOLOAD; $opcode =~ s/.*:://; $opcode =~ s/_/\./; + my $arg = pop; + $arg = "#$arg" if ($arg*1 eq $arg); + $code .= "\t$opcode\t".join(',',@_,$arg)."\n"; +} + +my ($out,$inp,$len,$key,$ctr) = map("x$_",(0..4)); + +my @x=map("x$_",(5..17,19..21)); +my @d=map("x$_",(22..28,30)); + +sub ROUND { +my ($a0,$b0,$c0,$d0)=@_; +my ($a1,$b1,$c1,$d1)=map(($_&~3)+(($_+1)&3),($a0,$b0,$c0,$d0)); +my ($a2,$b2,$c2,$d2)=map(($_&~3)+(($_+1)&3),($a1,$b1,$c1,$d1)); +my ($a3,$b3,$c3,$d3)=map(($_&~3)+(($_+1)&3),($a2,$b2,$c2,$d2)); + + ( + "&add_32 (@x[$a0],@x[$a0],@x[$b0])", + "&add_32 (@x[$a1],@x[$a1],@x[$b1])", + "&add_32 (@x[$a2],@x[$a2],@x[$b2])", + "&add_32 (@x[$a3],@x[$a3],@x[$b3])", + "&eor_32 (@x[$d0],@x[$d0],@x[$a0])", + "&eor_32 (@x[$d1],@x[$d1],@x[$a1])", + "&eor_32 (@x[$d2],@x[$d2],@x[$a2])", + "&eor_32 (@x[$d3],@x[$d3],@x[$a3])", + "&ror_32 (@x[$d0],@x[$d0],16)", + "&ror_32 (@x[$d1],@x[$d1],16)", + "&ror_32 (@x[$d2],@x[$d2],16)", + "&ror_32 (@x[$d3],@x[$d3],16)", + + "&add_32 (@x[$c0],@x[$c0],@x[$d0])", + "&add_32 (@x[$c1],@x[$c1],@x[$d1])", + "&add_32 (@x[$c2],@x[$c2],@x[$d2])", + "&add_32 (@x[$c3],@x[$c3],@x[$d3])", + "&eor_32 (@x[$b0],@x[$b0],@x[$c0])", + "&eor_32 (@x[$b1],@x[$b1],@x[$c1])", + "&eor_32 (@x[$b2],@x[$b2],@x[$c2])", + "&eor_32 (@x[$b3],@x[$b3],@x[$c3])", + "&ror_32 (@x[$b0],@x[$b0],20)", + "&ror_32 (@x[$b1],@x[$b1],20)", + "&ror_32 (@x[$b2],@x[$b2],20)", + "&ror_32 (@x[$b3],@x[$b3],20)", + + "&add_32 (@x[$a0],@x[$a0],@x[$b0])", + "&add_32 (@x[$a1],@x[$a1],@x[$b1])", + "&add_32 (@x[$a2],@x[$a2],@x[$b2])", + "&add_32 (@x[$a3],@x[$a3],@x[$b3])", + "&eor_32 (@x[$d0],@x[$d0],@x[$a0])", + "&eor_32 (@x[$d1],@x[$d1],@x[$a1])", + "&eor_32 (@x[$d2],@x[$d2],@x[$a2])", + "&eor_32 (@x[$d3],@x[$d3],@x[$a3])", + "&ror_32 (@x[$d0],@x[$d0],24)", + "&ror_32 (@x[$d1],@x[$d1],24)", + "&ror_32 (@x[$d2],@x[$d2],24)", + "&ror_32 (@x[$d3],@x[$d3],24)", + + "&add_32 (@x[$c0],@x[$c0],@x[$d0])", + "&add_32 (@x[$c1],@x[$c1],@x[$d1])", + "&add_32 (@x[$c2],@x[$c2],@x[$d2])", + "&add_32 (@x[$c3],@x[$c3],@x[$d3])", + "&eor_32 (@x[$b0],@x[$b0],@x[$c0])", + "&eor_32 (@x[$b1],@x[$b1],@x[$c1])", + "&eor_32 (@x[$b2],@x[$b2],@x[$c2])", + "&eor_32 (@x[$b3],@x[$b3],@x[$c3])", + "&ror_32 (@x[$b0],@x[$b0],25)", + "&ror_32 (@x[$b1],@x[$b1],25)", + "&ror_32 (@x[$b2],@x[$b2],25)", + "&ror_32 (@x[$b3],@x[$b3],25)" + ); +} + +$code.=<<___; +#include + +.text + +.extern OPENSSL_armcap_P + +.align 5 +.Lsigma: +.quad 0x3320646e61707865,0x6b20657479622d32 // endian-neutral +.Lone: +.long 1,0,0,0 +.LOPENSSL_armcap_P: +#ifdef __ILP32__ +.long OPENSSL_armcap_P-. +#else +.quad OPENSSL_armcap_P-. +#endif +.asciz "ChaCha20 for ARMv8, CRYPTOGAMS by " + +.globl ChaCha20_ctr32 +.type ChaCha20_ctr32,%function +.align 5 +ChaCha20_ctr32: + cbz $len,.Labort + adr @x[0],.LOPENSSL_armcap_P + cmp $len,#192 + b.lo .Lshort +#ifdef __ILP32__ + ldrsw @x[1],[@x[0]] +#else + ldr @x[1],[@x[0]] +#endif + ldr w17,[@x[1],@x[0]] + tst w17,#ARMV7_NEON + b.ne ChaCha20_neon + +.Lshort: + stp x29,x30,[sp,#-96]! + add x29,sp,#0 + + adr @x[0],.Lsigma + stp x19,x20,[sp,#16] + stp x21,x22,[sp,#32] + stp x23,x24,[sp,#48] + stp x25,x26,[sp,#64] + stp x27,x28,[sp,#80] + sub sp,sp,#64 + + ldp @d[0],@d[1],[@x[0]] // load sigma + ldp @d[2],@d[3],[$key] // load key + ldp @d[4],@d[5],[$key,#16] + ldp @d[6],@d[7],[$ctr] // load counter +#ifdef __ARMEB__ + ror @d[2],@d[2],#32 + ror @d[3],@d[3],#32 + ror @d[4],@d[4],#32 + ror @d[5],@d[5],#32 + ror @d[6],@d[6],#32 + ror @d[7],@d[7],#32 +#endif + +.Loop_outer: + mov.32 @x[0],@d[0] // unpack key block + lsr @x[1],@d[0],#32 + mov.32 @x[2],@d[1] + lsr @x[3],@d[1],#32 + mov.32 @x[4],@d[2] + lsr @x[5],@d[2],#32 + mov.32 @x[6],@d[3] + lsr @x[7],@d[3],#32 + mov.32 @x[8],@d[4] + lsr @x[9],@d[4],#32 + mov.32 @x[10],@d[5] + lsr @x[11],@d[5],#32 + mov.32 @x[12],@d[6] + lsr @x[13],@d[6],#32 + mov.32 @x[14],@d[7] + lsr @x[15],@d[7],#32 + + mov $ctr,#10 + subs $len,$len,#64 +.Loop: + sub $ctr,$ctr,#1 +___ + foreach (&ROUND(0, 4, 8,12)) { eval; } + foreach (&ROUND(0, 5,10,15)) { eval; } +$code.=<<___; + cbnz $ctr,.Loop + + add.32 @x[0],@x[0],@d[0] // accumulate key block + add @x[1],@x[1],@d[0],lsr#32 + add.32 @x[2],@x[2],@d[1] + add @x[3],@x[3],@d[1],lsr#32 + add.32 @x[4],@x[4],@d[2] + add @x[5],@x[5],@d[2],lsr#32 + add.32 @x[6],@x[6],@d[3] + add @x[7],@x[7],@d[3],lsr#32 + add.32 @x[8],@x[8],@d[4] + add @x[9],@x[9],@d[4],lsr#32 + add.32 @x[10],@x[10],@d[5] + add @x[11],@x[11],@d[5],lsr#32 + add.32 @x[12],@x[12],@d[6] + add @x[13],@x[13],@d[6],lsr#32 + add.32 @x[14],@x[14],@d[7] + add @x[15],@x[15],@d[7],lsr#32 + + b.lo .Ltail + + add @x[0],@x[0],@x[1],lsl#32 // pack + add @x[2],@x[2],@x[3],lsl#32 + ldp @x[1],@x[3],[$inp,#0] // load input + add @x[4],@x[4],@x[5],lsl#32 + add @x[6],@x[6],@x[7],lsl#32 + ldp @x[5],@x[7],[$inp,#16] + add @x[8],@x[8],@x[9],lsl#32 + add @x[10],@x[10],@x[11],lsl#32 + ldp @x[9],@x[11],[$inp,#32] + add @x[12],@x[12],@x[13],lsl#32 + add @x[14],@x[14],@x[15],lsl#32 + ldp @x[13],@x[15],[$inp,#48] + add $inp,$inp,#64 +#ifdef __ARMEB__ + rev @x[0],@x[0] + rev @x[2],@x[2] + rev @x[4],@x[4] + rev @x[6],@x[6] + rev @x[8],@x[8] + rev @x[10],@x[10] + rev @x[12],@x[12] + rev @x[14],@x[14] +#endif + eor @x[0],@x[0],@x[1] + eor @x[2],@x[2],@x[3] + eor @x[4],@x[4],@x[5] + eor @x[6],@x[6],@x[7] + eor @x[8],@x[8],@x[9] + eor @x[10],@x[10],@x[11] + eor @x[12],@x[12],@x[13] + eor @x[14],@x[14],@x[15] + + stp @x[0],@x[2],[$out,#0] // store output + add @d[6],@d[6],#1 // increment counter + stp @x[4],@x[6],[$out,#16] + stp @x[8],@x[10],[$out,#32] + stp @x[12],@x[14],[$out,#48] + add $out,$out,#64 + + b.hi .Loop_outer + + ldp x19,x20,[x29,#16] + add sp,sp,#64 + ldp x21,x22,[x29,#32] + ldp x23,x24,[x29,#48] + ldp x25,x26,[x29,#64] + ldp x27,x28,[x29,#80] + ldp x29,x30,[sp],#96 +.Labort: + ret + +.align 4 +.Ltail: + add $len,$len,#64 +.Less_than_64: + sub $out,$out,#1 + add $inp,$inp,$len + add $out,$out,$len + add $ctr,sp,$len + neg $len,$len + + add @x[0],@x[0],@x[1],lsl#32 // pack + add @x[2],@x[2],@x[3],lsl#32 + add @x[4],@x[4],@x[5],lsl#32 + add @x[6],@x[6],@x[7],lsl#32 + add @x[8],@x[8],@x[9],lsl#32 + add @x[10],@x[10],@x[11],lsl#32 + add @x[12],@x[12],@x[13],lsl#32 + add @x[14],@x[14],@x[15],lsl#32 +#ifdef __ARMEB__ + rev @x[0],@x[0] + rev @x[2],@x[2] + rev @x[4],@x[4] + rev @x[6],@x[6] + rev @x[8],@x[8] + rev @x[10],@x[10] + rev @x[12],@x[12] + rev @x[14],@x[14] +#endif + stp @x[0],@x[2],[sp,#0] + stp @x[4],@x[6],[sp,#16] + stp @x[8],@x[10],[sp,#32] + stp @x[12],@x[14],[sp,#48] + +.Loop_tail: + ldrb w10,[$inp,$len] + ldrb w11,[$ctr,$len] + add $len,$len,#1 + eor w10,w10,w11 + strb w10,[$out,$len] + cbnz $len,.Loop_tail + + stp xzr,xzr,[sp,#0] + stp xzr,xzr,[sp,#16] + stp xzr,xzr,[sp,#32] + stp xzr,xzr,[sp,#48] + + ldp x19,x20,[x29,#16] + add sp,sp,#64 + ldp x21,x22,[x29,#32] + ldp x23,x24,[x29,#48] + ldp x25,x26,[x29,#64] + ldp x27,x28,[x29,#80] + ldp x29,x30,[sp],#96 + ret +.size ChaCha20_ctr32,.-ChaCha20_ctr32 +___ + +{{{ +my ($A0,$B0,$C0,$D0,$A1,$B1,$C1,$D1,$A2,$B2,$C2,$D2,$T0,$T1,$T2,$T3) = + map("v$_.4s",(0..7,16..23)); +my (@K)=map("v$_.4s",(24..30)); +my $ONE="v31.4s"; + +sub NEONROUND { +my $odd = pop; +my ($a,$b,$c,$d,$t)=@_; + + ( + "&add ('$a','$a','$b')", + "&eor ('$d','$d','$a')", + "&rev32_16 ('$d','$d')", # vrot ($d,16) + + "&add ('$c','$c','$d')", + "&eor ('$t','$b','$c')", + "&ushr ('$b','$t',20)", + "&sli ('$b','$t',12)", + + "&add ('$a','$a','$b')", + "&eor ('$t','$d','$a')", + "&ushr ('$d','$t',24)", + "&sli ('$d','$t',8)", + + "&add ('$c','$c','$d')", + "&eor ('$t','$b','$c')", + "&ushr ('$b','$t',25)", + "&sli ('$b','$t',7)", + + "&ext ('$c','$c','$c',8)", + "&ext ('$d','$d','$d',$odd?4:12)", + "&ext ('$b','$b','$b',$odd?12:4)" + ); +} + +$code.=<<___; + +.type ChaCha20_neon,%function +.align 5 +ChaCha20_neon: + stp x29,x30,[sp,#-96]! + add x29,sp,#0 + + adr @x[0],.Lsigma + stp x19,x20,[sp,#16] + stp x21,x22,[sp,#32] + stp x23,x24,[sp,#48] + stp x25,x26,[sp,#64] + stp x27,x28,[sp,#80] + cmp $len,#512 + b.hs .L512_or_more_neon + + sub sp,sp,#64 + + ldp @d[0],@d[1],[@x[0]] // load sigma + ld1 {@K[0]},[@x[0]],#16 + ldp @d[2],@d[3],[$key] // load key + ldp @d[4],@d[5],[$key,#16] + ld1 {@K[1],@K[2]},[$key] + ldp @d[6],@d[7],[$ctr] // load counter + ld1 {@K[3]},[$ctr] + ld1 {$ONE},[@x[0]] +#ifdef __ARMEB__ + rev64 @K[0],@K[0] + ror @d[2],@d[2],#32 + ror @d[3],@d[3],#32 + ror @d[4],@d[4],#32 + ror @d[5],@d[5],#32 + ror @d[6],@d[6],#32 + ror @d[7],@d[7],#32 +#endif + add @K[3],@K[3],$ONE // += 1 + add @K[4],@K[3],$ONE + add @K[5],@K[4],$ONE + shl $ONE,$ONE,#2 // 1 -> 4 + +.Loop_outer_neon: + mov.32 @x[0],@d[0] // unpack key block + lsr @x[1],@d[0],#32 + mov $A0,@K[0] + mov.32 @x[2],@d[1] + lsr @x[3],@d[1],#32 + mov $A1,@K[0] + mov.32 @x[4],@d[2] + lsr @x[5],@d[2],#32 + mov $A2,@K[0] + mov.32 @x[6],@d[3] + mov $B0,@K[1] + lsr @x[7],@d[3],#32 + mov $B1,@K[1] + mov.32 @x[8],@d[4] + mov $B2,@K[1] + lsr @x[9],@d[4],#32 + mov $D0,@K[3] + mov.32 @x[10],@d[5] + mov $D1,@K[4] + lsr @x[11],@d[5],#32 + mov $D2,@K[5] + mov.32 @x[12],@d[6] + mov $C0,@K[2] + lsr @x[13],@d[6],#32 + mov $C1,@K[2] + mov.32 @x[14],@d[7] + mov $C2,@K[2] + lsr @x[15],@d[7],#32 + + mov $ctr,#10 + subs $len,$len,#256 +.Loop_neon: + sub $ctr,$ctr,#1 +___ + my @thread0=&NEONROUND($A0,$B0,$C0,$D0,$T0,0); + my @thread1=&NEONROUND($A1,$B1,$C1,$D1,$T1,0); + my @thread2=&NEONROUND($A2,$B2,$C2,$D2,$T2,0); + my @thread3=&ROUND(0,4,8,12); + + foreach (@thread0) { + eval; eval(shift(@thread3)); + eval(shift(@thread1)); eval(shift(@thread3)); + eval(shift(@thread2)); eval(shift(@thread3)); + } + + @thread0=&NEONROUND($A0,$B0,$C0,$D0,$T0,1); + @thread1=&NEONROUND($A1,$B1,$C1,$D1,$T1,1); + @thread2=&NEONROUND($A2,$B2,$C2,$D2,$T2,1); + @thread3=&ROUND(0,5,10,15); + + foreach (@thread0) { + eval; eval(shift(@thread3)); + eval(shift(@thread1)); eval(shift(@thread3)); + eval(shift(@thread2)); eval(shift(@thread3)); + } +$code.=<<___; + cbnz $ctr,.Loop_neon + + add.32 @x[0],@x[0],@d[0] // accumulate key block + add $A0,$A0,@K[0] + add @x[1],@x[1],@d[0],lsr#32 + add $A1,$A1,@K[0] + add.32 @x[2],@x[2],@d[1] + add $A2,$A2,@K[0] + add @x[3],@x[3],@d[1],lsr#32 + add $C0,$C0,@K[2] + add.32 @x[4],@x[4],@d[2] + add $C1,$C1,@K[2] + add @x[5],@x[5],@d[2],lsr#32 + add $C2,$C2,@K[2] + add.32 @x[6],@x[6],@d[3] + add $D0,$D0,@K[3] + add @x[7],@x[7],@d[3],lsr#32 + add.32 @x[8],@x[8],@d[4] + add $D1,$D1,@K[4] + add @x[9],@x[9],@d[4],lsr#32 + add.32 @x[10],@x[10],@d[5] + add $D2,$D2,@K[5] + add @x[11],@x[11],@d[5],lsr#32 + add.32 @x[12],@x[12],@d[6] + add $B0,$B0,@K[1] + add @x[13],@x[13],@d[6],lsr#32 + add.32 @x[14],@x[14],@d[7] + add $B1,$B1,@K[1] + add @x[15],@x[15],@d[7],lsr#32 + add $B2,$B2,@K[1] + + b.lo .Ltail_neon + + add @x[0],@x[0],@x[1],lsl#32 // pack + add @x[2],@x[2],@x[3],lsl#32 + ldp @x[1],@x[3],[$inp,#0] // load input + add @x[4],@x[4],@x[5],lsl#32 + add @x[6],@x[6],@x[7],lsl#32 + ldp @x[5],@x[7],[$inp,#16] + add @x[8],@x[8],@x[9],lsl#32 + add @x[10],@x[10],@x[11],lsl#32 + ldp @x[9],@x[11],[$inp,#32] + add @x[12],@x[12],@x[13],lsl#32 + add @x[14],@x[14],@x[15],lsl#32 + ldp @x[13],@x[15],[$inp,#48] + add $inp,$inp,#64 +#ifdef __ARMEB__ + rev @x[0],@x[0] + rev @x[2],@x[2] + rev @x[4],@x[4] + rev @x[6],@x[6] + rev @x[8],@x[8] + rev @x[10],@x[10] + rev @x[12],@x[12] + rev @x[14],@x[14] +#endif + ld1.8 {$T0-$T3},[$inp],#64 + eor @x[0],@x[0],@x[1] + eor @x[2],@x[2],@x[3] + eor @x[4],@x[4],@x[5] + eor @x[6],@x[6],@x[7] + eor @x[8],@x[8],@x[9] + eor $A0,$A0,$T0 + eor @x[10],@x[10],@x[11] + eor $B0,$B0,$T1 + eor @x[12],@x[12],@x[13] + eor $C0,$C0,$T2 + eor @x[14],@x[14],@x[15] + eor $D0,$D0,$T3 + ld1.8 {$T0-$T3},[$inp],#64 + + stp @x[0],@x[2],[$out,#0] // store output + add @d[6],@d[6],#4 // increment counter + stp @x[4],@x[6],[$out,#16] + add @K[3],@K[3],$ONE // += 4 + stp @x[8],@x[10],[$out,#32] + add @K[4],@K[4],$ONE + stp @x[12],@x[14],[$out,#48] + add @K[5],@K[5],$ONE + add $out,$out,#64 + + st1.8 {$A0-$D0},[$out],#64 + ld1.8 {$A0-$D0},[$inp],#64 + + eor $A1,$A1,$T0 + eor $B1,$B1,$T1 + eor $C1,$C1,$T2 + eor $D1,$D1,$T3 + st1.8 {$A1-$D1},[$out],#64 + + eor $A2,$A2,$A0 + eor $B2,$B2,$B0 + eor $C2,$C2,$C0 + eor $D2,$D2,$D0 + st1.8 {$A2-$D2},[$out],#64 + + b.hi .Loop_outer_neon + + ldp x19,x20,[x29,#16] + add sp,sp,#64 + ldp x21,x22,[x29,#32] + ldp x23,x24,[x29,#48] + ldp x25,x26,[x29,#64] + ldp x27,x28,[x29,#80] + ldp x29,x30,[sp],#96 + ret + +.Ltail_neon: + add $len,$len,#256 + cmp $len,#64 + b.lo .Less_than_64 + + add @x[0],@x[0],@x[1],lsl#32 // pack + add @x[2],@x[2],@x[3],lsl#32 + ldp @x[1],@x[3],[$inp,#0] // load input + add @x[4],@x[4],@x[5],lsl#32 + add @x[6],@x[6],@x[7],lsl#32 + ldp @x[5],@x[7],[$inp,#16] + add @x[8],@x[8],@x[9],lsl#32 + add @x[10],@x[10],@x[11],lsl#32 + ldp @x[9],@x[11],[$inp,#32] + add @x[12],@x[12],@x[13],lsl#32 + add @x[14],@x[14],@x[15],lsl#32 + ldp @x[13],@x[15],[$inp,#48] + add $inp,$inp,#64 +#ifdef __ARMEB__ + rev @x[0],@x[0] + rev @x[2],@x[2] + rev @x[4],@x[4] + rev @x[6],@x[6] + rev @x[8],@x[8] + rev @x[10],@x[10] + rev @x[12],@x[12] + rev @x[14],@x[14] +#endif + eor @x[0],@x[0],@x[1] + eor @x[2],@x[2],@x[3] + eor @x[4],@x[4],@x[5] + eor @x[6],@x[6],@x[7] + eor @x[8],@x[8],@x[9] + eor @x[10],@x[10],@x[11] + eor @x[12],@x[12],@x[13] + eor @x[14],@x[14],@x[15] + + stp @x[0],@x[2],[$out,#0] // store output + add @d[6],@d[6],#4 // increment counter + stp @x[4],@x[6],[$out,#16] + stp @x[8],@x[10],[$out,#32] + stp @x[12],@x[14],[$out,#48] + add $out,$out,#64 + b.eq .Ldone_neon + sub $len,$len,#64 + cmp $len,#64 + b.lo .Less_than_128 + + ld1.8 {$T0-$T3},[$inp],#64 + eor $A0,$A0,$T0 + eor $B0,$B0,$T1 + eor $C0,$C0,$T2 + eor $D0,$D0,$T3 + st1.8 {$A0-$D0},[$out],#64 + b.eq .Ldone_neon + sub $len,$len,#64 + cmp $len,#64 + b.lo .Less_than_192 + + ld1.8 {$T0-$T3},[$inp],#64 + eor $A1,$A1,$T0 + eor $B1,$B1,$T1 + eor $C1,$C1,$T2 + eor $D1,$D1,$T3 + st1.8 {$A1-$D1},[$out],#64 + b.eq .Ldone_neon + sub $len,$len,#64 + + st1.8 {$A2-$D2},[sp] + b .Last_neon + +.Less_than_128: + st1.8 {$A0-$D0},[sp] + b .Last_neon +.Less_than_192: + st1.8 {$A1-$D1},[sp] + b .Last_neon + +.align 4 +.Last_neon: + sub $out,$out,#1 + add $inp,$inp,$len + add $out,$out,$len + add $ctr,sp,$len + neg $len,$len + +.Loop_tail_neon: + ldrb w10,[$inp,$len] + ldrb w11,[$ctr,$len] + add $len,$len,#1 + eor w10,w10,w11 + strb w10,[$out,$len] + cbnz $len,.Loop_tail_neon + + stp xzr,xzr,[sp,#0] + stp xzr,xzr,[sp,#16] + stp xzr,xzr,[sp,#32] + stp xzr,xzr,[sp,#48] + +.Ldone_neon: + ldp x19,x20,[x29,#16] + add sp,sp,#64 + ldp x21,x22,[x29,#32] + ldp x23,x24,[x29,#48] + ldp x25,x26,[x29,#64] + ldp x27,x28,[x29,#80] + ldp x29,x30,[sp],#96 + ret +.size ChaCha20_neon,.-ChaCha20_neon +___ +{ +my ($T0,$T1,$T2,$T3,$T4,$T5)=@K; +my ($A0,$B0,$C0,$D0,$A1,$B1,$C1,$D1,$A2,$B2,$C2,$D2, + $A3,$B3,$C3,$D3,$A4,$B4,$C4,$D4,$A5,$B5,$C5,$D5) = map("v$_.4s",(0..23)); + +$code.=<<___; +.type ChaCha20_512_neon,%function +.align 5 +ChaCha20_512_neon: + stp x29,x30,[sp,#-96]! + add x29,sp,#0 + + adr @x[0],.Lsigma + stp x19,x20,[sp,#16] + stp x21,x22,[sp,#32] + stp x23,x24,[sp,#48] + stp x25,x26,[sp,#64] + stp x27,x28,[sp,#80] + +.L512_or_more_neon: + sub sp,sp,#128+64 + + ldp @d[0],@d[1],[@x[0]] // load sigma + ld1 {@K[0]},[@x[0]],#16 + ldp @d[2],@d[3],[$key] // load key + ldp @d[4],@d[5],[$key,#16] + ld1 {@K[1],@K[2]},[$key] + ldp @d[6],@d[7],[$ctr] // load counter + ld1 {@K[3]},[$ctr] + ld1 {$ONE},[@x[0]] +#ifdef __ARMEB__ + rev64 @K[0],@K[0] + ror @d[2],@d[2],#32 + ror @d[3],@d[3],#32 + ror @d[4],@d[4],#32 + ror @d[5],@d[5],#32 + ror @d[6],@d[6],#32 + ror @d[7],@d[7],#32 +#endif + add @K[3],@K[3],$ONE // += 1 + stp @K[0],@K[1],[sp,#0] // off-load key block, invariant part + add @K[3],@K[3],$ONE // not typo + str @K[2],[sp,#32] + add @K[4],@K[3],$ONE + add @K[5],@K[4],$ONE + add @K[6],@K[5],$ONE + shl $ONE,$ONE,#2 // 1 -> 4 + + stp d8,d9,[sp,#128+0] // meet ABI requirements + stp d10,d11,[sp,#128+16] + stp d12,d13,[sp,#128+32] + stp d14,d15,[sp,#128+48] + + sub $len,$len,#512 // not typo + +.Loop_outer_512_neon: + mov $A0,@K[0] + mov $A1,@K[0] + mov $A2,@K[0] + mov $A3,@K[0] + mov $A4,@K[0] + mov $A5,@K[0] + mov $B0,@K[1] + mov.32 @x[0],@d[0] // unpack key block + mov $B1,@K[1] + lsr @x[1],@d[0],#32 + mov $B2,@K[1] + mov.32 @x[2],@d[1] + mov $B3,@K[1] + lsr @x[3],@d[1],#32 + mov $B4,@K[1] + mov.32 @x[4],@d[2] + mov $B5,@K[1] + lsr @x[5],@d[2],#32 + mov $D0,@K[3] + mov.32 @x[6],@d[3] + mov $D1,@K[4] + lsr @x[7],@d[3],#32 + mov $D2,@K[5] + mov.32 @x[8],@d[4] + mov $D3,@K[6] + lsr @x[9],@d[4],#32 + mov $C0,@K[2] + mov.32 @x[10],@d[5] + mov $C1,@K[2] + lsr @x[11],@d[5],#32 + add $D4,$D0,$ONE // +4 + mov.32 @x[12],@d[6] + add $D5,$D1,$ONE // +4 + lsr @x[13],@d[6],#32 + mov $C2,@K[2] + mov.32 @x[14],@d[7] + mov $C3,@K[2] + lsr @x[15],@d[7],#32 + mov $C4,@K[2] + stp @K[3],@K[4],[sp,#48] // off-load key block, variable part + mov $C5,@K[2] + str @K[5],[sp,#80] + + mov $ctr,#5 + subs $len,$len,#512 +.Loop_upper_neon: + sub $ctr,$ctr,#1 +___ + my @thread0=&NEONROUND($A0,$B0,$C0,$D0,$T0,0); + my @thread1=&NEONROUND($A1,$B1,$C1,$D1,$T1,0); + my @thread2=&NEONROUND($A2,$B2,$C2,$D2,$T2,0); + my @thread3=&NEONROUND($A3,$B3,$C3,$D3,$T3,0); + my @thread4=&NEONROUND($A4,$B4,$C4,$D4,$T4,0); + my @thread5=&NEONROUND($A5,$B5,$C5,$D5,$T5,0); + my @thread67=(&ROUND(0,4,8,12),&ROUND(0,5,10,15)); + my $diff = ($#thread0+1)*6 - $#thread67 - 1; + my $i = 0; + + foreach (@thread0) { + eval; eval(shift(@thread67)); + eval(shift(@thread1)); eval(shift(@thread67)); + eval(shift(@thread2)); eval(shift(@thread67)); + eval(shift(@thread3)); eval(shift(@thread67)); + eval(shift(@thread4)); eval(shift(@thread67)); + eval(shift(@thread5)); eval(shift(@thread67)); + } + + @thread0=&NEONROUND($A0,$B0,$C0,$D0,$T0,1); + @thread1=&NEONROUND($A1,$B1,$C1,$D1,$T1,1); + @thread2=&NEONROUND($A2,$B2,$C2,$D2,$T2,1); + @thread3=&NEONROUND($A3,$B3,$C3,$D3,$T3,1); + @thread4=&NEONROUND($A4,$B4,$C4,$D4,$T4,1); + @thread5=&NEONROUND($A5,$B5,$C5,$D5,$T5,1); + @thread67=(&ROUND(0,4,8,12),&ROUND(0,5,10,15)); + + foreach (@thread0) { + eval; eval(shift(@thread67)); + eval(shift(@thread1)); eval(shift(@thread67)); + eval(shift(@thread2)); eval(shift(@thread67)); + eval(shift(@thread3)); eval(shift(@thread67)); + eval(shift(@thread4)); eval(shift(@thread67)); + eval(shift(@thread5)); eval(shift(@thread67)); + } +$code.=<<___; + cbnz $ctr,.Loop_upper_neon + + add.32 @x[0],@x[0],@d[0] // accumulate key block + add @x[1],@x[1],@d[0],lsr#32 + add.32 @x[2],@x[2],@d[1] + add @x[3],@x[3],@d[1],lsr#32 + add.32 @x[4],@x[4],@d[2] + add @x[5],@x[5],@d[2],lsr#32 + add.32 @x[6],@x[6],@d[3] + add @x[7],@x[7],@d[3],lsr#32 + add.32 @x[8],@x[8],@d[4] + add @x[9],@x[9],@d[4],lsr#32 + add.32 @x[10],@x[10],@d[5] + add @x[11],@x[11],@d[5],lsr#32 + add.32 @x[12],@x[12],@d[6] + add @x[13],@x[13],@d[6],lsr#32 + add.32 @x[14],@x[14],@d[7] + add @x[15],@x[15],@d[7],lsr#32 + + add @x[0],@x[0],@x[1],lsl#32 // pack + add @x[2],@x[2],@x[3],lsl#32 + ldp @x[1],@x[3],[$inp,#0] // load input + add @x[4],@x[4],@x[5],lsl#32 + add @x[6],@x[6],@x[7],lsl#32 + ldp @x[5],@x[7],[$inp,#16] + add @x[8],@x[8],@x[9],lsl#32 + add @x[10],@x[10],@x[11],lsl#32 + ldp @x[9],@x[11],[$inp,#32] + add @x[12],@x[12],@x[13],lsl#32 + add @x[14],@x[14],@x[15],lsl#32 + ldp @x[13],@x[15],[$inp,#48] + add $inp,$inp,#64 +#ifdef __ARMEB__ + rev @x[0],@x[0] + rev @x[2],@x[2] + rev @x[4],@x[4] + rev @x[6],@x[6] + rev @x[8],@x[8] + rev @x[10],@x[10] + rev @x[12],@x[12] + rev @x[14],@x[14] +#endif + eor @x[0],@x[0],@x[1] + eor @x[2],@x[2],@x[3] + eor @x[4],@x[4],@x[5] + eor @x[6],@x[6],@x[7] + eor @x[8],@x[8],@x[9] + eor @x[10],@x[10],@x[11] + eor @x[12],@x[12],@x[13] + eor @x[14],@x[14],@x[15] + + stp @x[0],@x[2],[$out,#0] // store output + add @d[6],@d[6],#1 // increment counter + mov.32 @x[0],@d[0] // unpack key block + lsr @x[1],@d[0],#32 + stp @x[4],@x[6],[$out,#16] + mov.32 @x[2],@d[1] + lsr @x[3],@d[1],#32 + stp @x[8],@x[10],[$out,#32] + mov.32 @x[4],@d[2] + lsr @x[5],@d[2],#32 + stp @x[12],@x[14],[$out,#48] + add $out,$out,#64 + mov.32 @x[6],@d[3] + lsr @x[7],@d[3],#32 + mov.32 @x[8],@d[4] + lsr @x[9],@d[4],#32 + mov.32 @x[10],@d[5] + lsr @x[11],@d[5],#32 + mov.32 @x[12],@d[6] + lsr @x[13],@d[6],#32 + mov.32 @x[14],@d[7] + lsr @x[15],@d[7],#32 + + mov $ctr,#5 +.Loop_lower_neon: + sub $ctr,$ctr,#1 +___ + @thread0=&NEONROUND($A0,$B0,$C0,$D0,$T0,0); + @thread1=&NEONROUND($A1,$B1,$C1,$D1,$T1,0); + @thread2=&NEONROUND($A2,$B2,$C2,$D2,$T2,0); + @thread3=&NEONROUND($A3,$B3,$C3,$D3,$T3,0); + @thread4=&NEONROUND($A4,$B4,$C4,$D4,$T4,0); + @thread5=&NEONROUND($A5,$B5,$C5,$D5,$T5,0); + @thread67=(&ROUND(0,4,8,12),&ROUND(0,5,10,15)); + + foreach (@thread0) { + eval; eval(shift(@thread67)); + eval(shift(@thread1)); eval(shift(@thread67)); + eval(shift(@thread2)); eval(shift(@thread67)); + eval(shift(@thread3)); eval(shift(@thread67)); + eval(shift(@thread4)); eval(shift(@thread67)); + eval(shift(@thread5)); eval(shift(@thread67)); + } + + @thread0=&NEONROUND($A0,$B0,$C0,$D0,$T0,1); + @thread1=&NEONROUND($A1,$B1,$C1,$D1,$T1,1); + @thread2=&NEONROUND($A2,$B2,$C2,$D2,$T2,1); + @thread3=&NEONROUND($A3,$B3,$C3,$D3,$T3,1); + @thread4=&NEONROUND($A4,$B4,$C4,$D4,$T4,1); + @thread5=&NEONROUND($A5,$B5,$C5,$D5,$T5,1); + @thread67=(&ROUND(0,4,8,12),&ROUND(0,5,10,15)); + + foreach (@thread0) { + eval; eval(shift(@thread67)); + eval(shift(@thread1)); eval(shift(@thread67)); + eval(shift(@thread2)); eval(shift(@thread67)); + eval(shift(@thread3)); eval(shift(@thread67)); + eval(shift(@thread4)); eval(shift(@thread67)); + eval(shift(@thread5)); eval(shift(@thread67)); + } +$code.=<<___; + cbnz $ctr,.Loop_lower_neon + + add.32 @x[0],@x[0],@d[0] // accumulate key block + ldp @K[0],@K[1],[sp,#0] + add @x[1],@x[1],@d[0],lsr#32 + ldp @K[2],@K[3],[sp,#32] + add.32 @x[2],@x[2],@d[1] + ldp @K[4],@K[5],[sp,#64] + add @x[3],@x[3],@d[1],lsr#32 + add $A0,$A0,@K[0] + add.32 @x[4],@x[4],@d[2] + add $A1,$A1,@K[0] + add @x[5],@x[5],@d[2],lsr#32 + add $A2,$A2,@K[0] + add.32 @x[6],@x[6],@d[3] + add $A3,$A3,@K[0] + add @x[7],@x[7],@d[3],lsr#32 + add $A4,$A4,@K[0] + add.32 @x[8],@x[8],@d[4] + add $A5,$A5,@K[0] + add @x[9],@x[9],@d[4],lsr#32 + add $C0,$C0,@K[2] + add.32 @x[10],@x[10],@d[5] + add $C1,$C1,@K[2] + add @x[11],@x[11],@d[5],lsr#32 + add $C2,$C2,@K[2] + add.32 @x[12],@x[12],@d[6] + add $C3,$C3,@K[2] + add @x[13],@x[13],@d[6],lsr#32 + add $C4,$C4,@K[2] + add.32 @x[14],@x[14],@d[7] + add $C5,$C5,@K[2] + add @x[15],@x[15],@d[7],lsr#32 + add $D4,$D4,$ONE // +4 + add @x[0],@x[0],@x[1],lsl#32 // pack + add $D5,$D5,$ONE // +4 + add @x[2],@x[2],@x[3],lsl#32 + add $D0,$D0,@K[3] + ldp @x[1],@x[3],[$inp,#0] // load input + add $D1,$D1,@K[4] + add @x[4],@x[4],@x[5],lsl#32 + add $D2,$D2,@K[5] + add @x[6],@x[6],@x[7],lsl#32 + add $D3,$D3,@K[6] + ldp @x[5],@x[7],[$inp,#16] + add $D4,$D4,@K[3] + add @x[8],@x[8],@x[9],lsl#32 + add $D5,$D5,@K[4] + add @x[10],@x[10],@x[11],lsl#32 + add $B0,$B0,@K[1] + ldp @x[9],@x[11],[$inp,#32] + add $B1,$B1,@K[1] + add @x[12],@x[12],@x[13],lsl#32 + add $B2,$B2,@K[1] + add @x[14],@x[14],@x[15],lsl#32 + add $B3,$B3,@K[1] + ldp @x[13],@x[15],[$inp,#48] + add $B4,$B4,@K[1] + add $inp,$inp,#64 + add $B5,$B5,@K[1] + +#ifdef __ARMEB__ + rev @x[0],@x[0] + rev @x[2],@x[2] + rev @x[4],@x[4] + rev @x[6],@x[6] + rev @x[8],@x[8] + rev @x[10],@x[10] + rev @x[12],@x[12] + rev @x[14],@x[14] +#endif + ld1.8 {$T0-$T3},[$inp],#64 + eor @x[0],@x[0],@x[1] + eor @x[2],@x[2],@x[3] + eor @x[4],@x[4],@x[5] + eor @x[6],@x[6],@x[7] + eor @x[8],@x[8],@x[9] + eor $A0,$A0,$T0 + eor @x[10],@x[10],@x[11] + eor $B0,$B0,$T1 + eor @x[12],@x[12],@x[13] + eor $C0,$C0,$T2 + eor @x[14],@x[14],@x[15] + eor $D0,$D0,$T3 + ld1.8 {$T0-$T3},[$inp],#64 + + stp @x[0],@x[2],[$out,#0] // store output + add @d[6],@d[6],#7 // increment counter + stp @x[4],@x[6],[$out,#16] + stp @x[8],@x[10],[$out,#32] + stp @x[12],@x[14],[$out,#48] + add $out,$out,#64 + st1.8 {$A0-$D0},[$out],#64 + + ld1.8 {$A0-$D0},[$inp],#64 + eor $A1,$A1,$T0 + eor $B1,$B1,$T1 + eor $C1,$C1,$T2 + eor $D1,$D1,$T3 + st1.8 {$A1-$D1},[$out],#64 + + ld1.8 {$A1-$D1},[$inp],#64 + eor $A2,$A2,$A0 + ldp @K[0],@K[1],[sp,#0] + eor $B2,$B2,$B0 + ldp @K[2],@K[3],[sp,#32] + eor $C2,$C2,$C0 + eor $D2,$D2,$D0 + st1.8 {$A2-$D2},[$out],#64 + + ld1.8 {$A2-$D2},[$inp],#64 + eor $A3,$A3,$A1 + eor $B3,$B3,$B1 + eor $C3,$C3,$C1 + eor $D3,$D3,$D1 + st1.8 {$A3-$D3},[$out],#64 + + ld1.8 {$A3-$D3},[$inp],#64 + eor $A4,$A4,$A2 + eor $B4,$B4,$B2 + eor $C4,$C4,$C2 + eor $D4,$D4,$D2 + st1.8 {$A4-$D4},[$out],#64 + + shl $A0,$ONE,#1 // 4 -> 8 + eor $A5,$A5,$A3 + eor $B5,$B5,$B3 + eor $C5,$C5,$C3 + eor $D5,$D5,$D3 + st1.8 {$A5-$D5},[$out],#64 + + add @K[3],@K[3],$A0 // += 8 + add @K[4],@K[4],$A0 + add @K[5],@K[5],$A0 + add @K[6],@K[6],$A0 + + b.hs .Loop_outer_512_neon + + adds $len,$len,#512 + ushr $A0,$ONE,#2 // 4 -> 1 + + ldp d8,d9,[sp,#128+0] // meet ABI requirements + ldp d10,d11,[sp,#128+16] + ldp d12,d13,[sp,#128+32] + ldp d14,d15,[sp,#128+48] + + stp @K[0],$ONE,[sp,#0] // wipe off-load area + stp @K[0],$ONE,[sp,#32] + stp @K[0],$ONE,[sp,#64] + + b.eq .Ldone_512_neon + + cmp $len,#192 + sub @K[3],@K[3],$A0 // -= 1 + sub @K[4],@K[4],$A0 + sub @K[5],@K[5],$A0 + add sp,sp,#128 + b.hs .Loop_outer_neon + + eor @K[1],@K[1],@K[1] + eor @K[2],@K[2],@K[2] + eor @K[3],@K[3],@K[3] + eor @K[4],@K[4],@K[4] + eor @K[5],@K[5],@K[5] + eor @K[6],@K[6],@K[6] + b .Loop_outer + +.Ldone_512_neon: + ldp x19,x20,[x29,#16] + add sp,sp,#128+64 + ldp x21,x22,[x29,#32] + ldp x23,x24,[x29,#48] + ldp x25,x26,[x29,#64] + ldp x27,x28,[x29,#80] + ldp x29,x30,[sp],#96 + ret +.size ChaCha20_512_neon,.-ChaCha20_512_neon +___ +} +}}} + +foreach (split("\n",$code)) { + s/\`([^\`]*)\`/eval $1/geo; + + (s/\b([a-z]+)\.32\b/$1/ and (s/x([0-9]+)/w$1/g or 1)) or + (m/\b(eor|ext|mov)\b/ and (s/\.4s/\.16b/g or 1)) or + (s/\b((?:ld|st)1)\.8\b/$1/ and (s/\.4s/\.16b/g or 1)) or + (m/\b(ld|st)[rp]\b/ and (s/v([0-9]+)\.4s/q$1/g or 1)) or + (s/\brev32\.16\b/rev32/ and (s/\.4s/\.8h/g or 1)); + + #s/\bq([0-9]+)#(lo|hi)/sprintf "d%d",2*$1+($2 eq "hi")/geo; + + print $_,"\n"; +} +close STDOUT; # flush diff --git a/external/boringssl/crypto/chacha/asm/chacha-x86.pl b/external/boringssl/crypto/chacha/asm/chacha-x86.pl new file mode 100755 index 0000000000..edce43dce5 --- /dev/null +++ b/external/boringssl/crypto/chacha/asm/chacha-x86.pl @@ -0,0 +1,753 @@ +#!/usr/bin/env perl +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# January 2015 +# +# ChaCha20 for x86. +# +# Performance in cycles per byte out of large buffer. +# +# 1xIALU/gcc 4xSSSE3 +# Pentium 17.5/+80% +# PIII 14.2/+60% +# P4 18.6/+84% +# Core2 9.56/+89% 4.83 +# Westmere 9.50/+45% 3.35 +# Sandy Bridge 10.5/+47% 3.20 +# Haswell 8.15/+50% 2.83 +# Silvermont 17.4/+36% 8.35 +# Sledgehammer 10.2/+54% +# Bulldozer 13.4/+50% 4.38(*) +# +# (*) Bulldozer actually executes 4xXOP code path that delivers 3.55; +# +# Modified from upstream OpenSSL to remove the XOP code. + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +push(@INC,"${dir}","${dir}../../perlasm"); +require "x86asm.pl"; + +&asm_init($ARGV[0],"chacha-x86.pl",$ARGV[$#ARGV] eq "386"); + +$xmm=$ymm=0; +for (@ARGV) { $xmm=1 if (/-DOPENSSL_IA32_SSE2/); } + +$ymm=$xmm; + +$a="eax"; +($b,$b_)=("ebx","ebp"); +($c,$c_)=("ecx","esi"); +($d,$d_)=("edx","edi"); + +sub QUARTERROUND { +my ($ai,$bi,$ci,$di,$i)=@_; +my ($an,$bn,$cn,$dn)=map(($_&~3)+(($_+1)&3),($ai,$bi,$ci,$di)); # next +my ($ap,$bp,$cp,$dp)=map(($_&~3)+(($_-1)&3),($ai,$bi,$ci,$di)); # previous + + # a b c d + # + # 0 4 8 12 < even round + # 1 5 9 13 + # 2 6 10 14 + # 3 7 11 15 + # 0 5 10 15 < odd round + # 1 6 11 12 + # 2 7 8 13 + # 3 4 9 14 + + if ($i==0) { + my $j=4; + ($ap,$bp,$cp,$dp)=map(($_&~3)+(($_-$j--)&3),($ap,$bp,$cp,$dp)); + } elsif ($i==3) { + my $j=0; + ($an,$bn,$cn,$dn)=map(($_&~3)+(($_+$j++)&3),($an,$bn,$cn,$dn)); + } elsif ($i==4) { + my $j=4; + ($ap,$bp,$cp,$dp)=map(($_&~3)+(($_+$j--)&3),($ap,$bp,$cp,$dp)); + } elsif ($i==7) { + my $j=0; + ($an,$bn,$cn,$dn)=map(($_&~3)+(($_-$j++)&3),($an,$bn,$cn,$dn)); + } + + #&add ($a,$b); # see elsewhere + &xor ($d,$a); + &mov (&DWP(4*$cp,"esp"),$c_) if ($ai>0 && $ai<3); + &rol ($d,16); + &mov (&DWP(4*$bp,"esp"),$b_) if ($i!=0); + &add ($c,$d); + &mov ($c_,&DWP(4*$cn,"esp")) if ($ai>0 && $ai<3); + &xor ($b,$c); + &mov ($d_,&DWP(4*$dn,"esp")) if ($di!=$dn); + &rol ($b,12); + &mov ($b_,&DWP(4*$bn,"esp")) if ($i<7); + &mov ($b_,&DWP(128,"esp")) if ($i==7); # loop counter + &add ($a,$b); + &xor ($d,$a); + &mov (&DWP(4*$ai,"esp"),$a); + &rol ($d,8); + &mov ($a,&DWP(4*$an,"esp")); + &add ($c,$d); + &mov (&DWP(4*$di,"esp"),$d) if ($di!=$dn); + &mov ($d_,$d) if ($di==$dn); + &xor ($b,$c); + &add ($a,$b_) if ($i<7); # elsewhere + &rol ($b,7); + + ($b,$b_)=($b_,$b); + ($c,$c_)=($c_,$c); + ($d,$d_)=($d_,$d); +} + +&static_label("ssse3_shortcut"); +&static_label("ssse3_data"); +&static_label("pic_point"); + +&function_begin("ChaCha20_ctr32"); + &xor ("eax","eax"); + &cmp ("eax",&wparam(2)); # len==0? + &je (&label("no_data")); +if ($xmm) { + &call (&label("pic_point")); +&set_label("pic_point"); + &blindpop("eax"); + &picmeup("ebp","OPENSSL_ia32cap_P","eax",&label("pic_point")); + &test (&DWP(0,"ebp"),1<<24); # test FXSR bit + &jz (&label("x86")); + &test (&DWP(4,"ebp"),1<<9); # test SSSE3 bit + &jz (&label("x86")); + &jmp (&label("ssse3_shortcut")); +&set_label("x86"); +} + &mov ("esi",&wparam(3)); # key + &mov ("edi",&wparam(4)); # counter and nonce + + &stack_push(33); + + &mov ("eax",&DWP(4*0,"esi")); # copy key + &mov ("ebx",&DWP(4*1,"esi")); + &mov ("ecx",&DWP(4*2,"esi")); + &mov ("edx",&DWP(4*3,"esi")); + &mov (&DWP(64+4*4,"esp"),"eax"); + &mov (&DWP(64+4*5,"esp"),"ebx"); + &mov (&DWP(64+4*6,"esp"),"ecx"); + &mov (&DWP(64+4*7,"esp"),"edx"); + &mov ("eax",&DWP(4*4,"esi")); + &mov ("ebx",&DWP(4*5,"esi")); + &mov ("ecx",&DWP(4*6,"esi")); + &mov ("edx",&DWP(4*7,"esi")); + &mov (&DWP(64+4*8,"esp"),"eax"); + &mov (&DWP(64+4*9,"esp"),"ebx"); + &mov (&DWP(64+4*10,"esp"),"ecx"); + &mov (&DWP(64+4*11,"esp"),"edx"); + &mov ("eax",&DWP(4*0,"edi")); # copy counter and nonce + &mov ("ebx",&DWP(4*1,"edi")); + &mov ("ecx",&DWP(4*2,"edi")); + &mov ("edx",&DWP(4*3,"edi")); + &sub ("eax",1); + &mov (&DWP(64+4*12,"esp"),"eax"); + &mov (&DWP(64+4*13,"esp"),"ebx"); + &mov (&DWP(64+4*14,"esp"),"ecx"); + &mov (&DWP(64+4*15,"esp"),"edx"); + &jmp (&label("entry")); + +&set_label("outer_loop",16); + &mov (&wparam(1),$b); # save input + &mov (&wparam(0),$a); # save output + &mov (&wparam(2),$c); # save len +&set_label("entry"); + &mov ($a,0x61707865); + &mov (&DWP(4*1,"esp"),0x3320646e); + &mov (&DWP(4*2,"esp"),0x79622d32); + &mov (&DWP(4*3,"esp"),0x6b206574); + + &mov ($b, &DWP(64+4*5,"esp")); # copy key material + &mov ($b_,&DWP(64+4*6,"esp")); + &mov ($c, &DWP(64+4*10,"esp")); + &mov ($c_,&DWP(64+4*11,"esp")); + &mov ($d, &DWP(64+4*13,"esp")); + &mov ($d_,&DWP(64+4*14,"esp")); + &mov (&DWP(4*5,"esp"),$b); + &mov (&DWP(4*6,"esp"),$b_); + &mov (&DWP(4*10,"esp"),$c); + &mov (&DWP(4*11,"esp"),$c_); + &mov (&DWP(4*13,"esp"),$d); + &mov (&DWP(4*14,"esp"),$d_); + + &mov ($b, &DWP(64+4*7,"esp")); + &mov ($d_,&DWP(64+4*15,"esp")); + &mov ($d, &DWP(64+4*12,"esp")); + &mov ($b_,&DWP(64+4*4,"esp")); + &mov ($c, &DWP(64+4*8,"esp")); + &mov ($c_,&DWP(64+4*9,"esp")); + &add ($d,1); # counter value + &mov (&DWP(4*7,"esp"),$b); + &mov (&DWP(4*15,"esp"),$d_); + &mov (&DWP(64+4*12,"esp"),$d); # save counter value + + &mov ($b,10); # loop counter + &jmp (&label("loop")); + +&set_label("loop",16); + &add ($a,$b_); # elsewhere + &mov (&DWP(128,"esp"),$b); # save loop counter + &mov ($b,$b_); + &QUARTERROUND(0, 4, 8, 12, 0); + &QUARTERROUND(1, 5, 9, 13, 1); + &QUARTERROUND(2, 6,10, 14, 2); + &QUARTERROUND(3, 7,11, 15, 3); + &QUARTERROUND(0, 5,10, 15, 4); + &QUARTERROUND(1, 6,11, 12, 5); + &QUARTERROUND(2, 7, 8, 13, 6); + &QUARTERROUND(3, 4, 9, 14, 7); + &dec ($b); + &jnz (&label("loop")); + + &mov ($b,&wparam(2)); # load len + + &add ($a,0x61707865); # accumulate key material + &add ($b_,&DWP(64+4*4,"esp")); + &add ($c, &DWP(64+4*8,"esp")); + &add ($c_,&DWP(64+4*9,"esp")); + + &cmp ($b,64); + &jb (&label("tail")); + + &mov ($b,&wparam(1)); # load input pointer + &add ($d, &DWP(64+4*12,"esp")); + &add ($d_,&DWP(64+4*14,"esp")); + + &xor ($a, &DWP(4*0,$b)); # xor with input + &xor ($b_,&DWP(4*4,$b)); + &mov (&DWP(4*0,"esp"),$a); + &mov ($a,&wparam(0)); # load output pointer + &xor ($c, &DWP(4*8,$b)); + &xor ($c_,&DWP(4*9,$b)); + &xor ($d, &DWP(4*12,$b)); + &xor ($d_,&DWP(4*14,$b)); + &mov (&DWP(4*4,$a),$b_); # write output + &mov (&DWP(4*8,$a),$c); + &mov (&DWP(4*9,$a),$c_); + &mov (&DWP(4*12,$a),$d); + &mov (&DWP(4*14,$a),$d_); + + &mov ($b_,&DWP(4*1,"esp")); + &mov ($c, &DWP(4*2,"esp")); + &mov ($c_,&DWP(4*3,"esp")); + &mov ($d, &DWP(4*5,"esp")); + &mov ($d_,&DWP(4*6,"esp")); + &add ($b_,0x3320646e); # accumulate key material + &add ($c, 0x79622d32); + &add ($c_,0x6b206574); + &add ($d, &DWP(64+4*5,"esp")); + &add ($d_,&DWP(64+4*6,"esp")); + &xor ($b_,&DWP(4*1,$b)); + &xor ($c, &DWP(4*2,$b)); + &xor ($c_,&DWP(4*3,$b)); + &xor ($d, &DWP(4*5,$b)); + &xor ($d_,&DWP(4*6,$b)); + &mov (&DWP(4*1,$a),$b_); + &mov (&DWP(4*2,$a),$c); + &mov (&DWP(4*3,$a),$c_); + &mov (&DWP(4*5,$a),$d); + &mov (&DWP(4*6,$a),$d_); + + &mov ($b_,&DWP(4*7,"esp")); + &mov ($c, &DWP(4*10,"esp")); + &mov ($c_,&DWP(4*11,"esp")); + &mov ($d, &DWP(4*13,"esp")); + &mov ($d_,&DWP(4*15,"esp")); + &add ($b_,&DWP(64+4*7,"esp")); + &add ($c, &DWP(64+4*10,"esp")); + &add ($c_,&DWP(64+4*11,"esp")); + &add ($d, &DWP(64+4*13,"esp")); + &add ($d_,&DWP(64+4*15,"esp")); + &xor ($b_,&DWP(4*7,$b)); + &xor ($c, &DWP(4*10,$b)); + &xor ($c_,&DWP(4*11,$b)); + &xor ($d, &DWP(4*13,$b)); + &xor ($d_,&DWP(4*15,$b)); + &lea ($b,&DWP(4*16,$b)); + &mov (&DWP(4*7,$a),$b_); + &mov ($b_,&DWP(4*0,"esp")); + &mov (&DWP(4*10,$a),$c); + &mov ($c,&wparam(2)); # len + &mov (&DWP(4*11,$a),$c_); + &mov (&DWP(4*13,$a),$d); + &mov (&DWP(4*15,$a),$d_); + &mov (&DWP(4*0,$a),$b_); + &lea ($a,&DWP(4*16,$a)); + &sub ($c,64); + &jnz (&label("outer_loop")); + + &jmp (&label("done")); + +&set_label("tail"); + &add ($d, &DWP(64+4*12,"esp")); + &add ($d_,&DWP(64+4*14,"esp")); + &mov (&DWP(4*0,"esp"),$a); + &mov (&DWP(4*4,"esp"),$b_); + &mov (&DWP(4*8,"esp"),$c); + &mov (&DWP(4*9,"esp"),$c_); + &mov (&DWP(4*12,"esp"),$d); + &mov (&DWP(4*14,"esp"),$d_); + + &mov ($b_,&DWP(4*1,"esp")); + &mov ($c, &DWP(4*2,"esp")); + &mov ($c_,&DWP(4*3,"esp")); + &mov ($d, &DWP(4*5,"esp")); + &mov ($d_,&DWP(4*6,"esp")); + &add ($b_,0x3320646e); # accumulate key material + &add ($c, 0x79622d32); + &add ($c_,0x6b206574); + &add ($d, &DWP(64+4*5,"esp")); + &add ($d_,&DWP(64+4*6,"esp")); + &mov (&DWP(4*1,"esp"),$b_); + &mov (&DWP(4*2,"esp"),$c); + &mov (&DWP(4*3,"esp"),$c_); + &mov (&DWP(4*5,"esp"),$d); + &mov (&DWP(4*6,"esp"),$d_); + + &mov ($b_,&DWP(4*7,"esp")); + &mov ($c, &DWP(4*10,"esp")); + &mov ($c_,&DWP(4*11,"esp")); + &mov ($d, &DWP(4*13,"esp")); + &mov ($d_,&DWP(4*15,"esp")); + &add ($b_,&DWP(64+4*7,"esp")); + &add ($c, &DWP(64+4*10,"esp")); + &add ($c_,&DWP(64+4*11,"esp")); + &add ($d, &DWP(64+4*13,"esp")); + &add ($d_,&DWP(64+4*15,"esp")); + &mov (&DWP(4*7,"esp"),$b_); + &mov ($b_,&wparam(1)); # load input + &mov (&DWP(4*10,"esp"),$c); + &mov ($c,&wparam(0)); # load output + &mov (&DWP(4*11,"esp"),$c_); + &xor ($c_,$c_); + &mov (&DWP(4*13,"esp"),$d); + &mov (&DWP(4*15,"esp"),$d_); + + &xor ("eax","eax"); + &xor ("edx","edx"); +&set_label("tail_loop"); + &movb ("al",&BP(0,$c_,$b_)); + &movb ("dl",&BP(0,"esp",$c_)); + &lea ($c_,&DWP(1,$c_)); + &xor ("al","dl"); + &mov (&BP(-1,$c,$c_),"al"); + &dec ($b); + &jnz (&label("tail_loop")); + +&set_label("done"); + &stack_pop(33); +&set_label("no_data"); +&function_end("ChaCha20_ctr32"); + +if ($xmm) { +my ($xa,$xa_,$xb,$xb_,$xc,$xc_,$xd,$xd_)=map("xmm$_",(0..7)); +my ($out,$inp,$len)=("edi","esi","ecx"); + +sub QUARTERROUND_SSSE3 { +my ($ai,$bi,$ci,$di,$i)=@_; +my ($an,$bn,$cn,$dn)=map(($_&~3)+(($_+1)&3),($ai,$bi,$ci,$di)); # next +my ($ap,$bp,$cp,$dp)=map(($_&~3)+(($_-1)&3),($ai,$bi,$ci,$di)); # previous + + # a b c d + # + # 0 4 8 12 < even round + # 1 5 9 13 + # 2 6 10 14 + # 3 7 11 15 + # 0 5 10 15 < odd round + # 1 6 11 12 + # 2 7 8 13 + # 3 4 9 14 + + if ($i==0) { + my $j=4; + ($ap,$bp,$cp,$dp)=map(($_&~3)+(($_-$j--)&3),($ap,$bp,$cp,$dp)); + } elsif ($i==3) { + my $j=0; + ($an,$bn,$cn,$dn)=map(($_&~3)+(($_+$j++)&3),($an,$bn,$cn,$dn)); + } elsif ($i==4) { + my $j=4; + ($ap,$bp,$cp,$dp)=map(($_&~3)+(($_+$j--)&3),($ap,$bp,$cp,$dp)); + } elsif ($i==7) { + my $j=0; + ($an,$bn,$cn,$dn)=map(($_&~3)+(($_-$j++)&3),($an,$bn,$cn,$dn)); + } + + #&paddd ($xa,$xb); # see elsewhere + #&pxor ($xd,$xa); # see elsewhere + &movdqa(&QWP(16*$cp-128,"ebx"),$xc_) if ($ai>0 && $ai<3); + &pshufb ($xd,&QWP(0,"eax")); # rot16 + &movdqa(&QWP(16*$bp-128,"ebx"),$xb_) if ($i!=0); + &paddd ($xc,$xd); + &movdqa($xc_,&QWP(16*$cn-128,"ebx")) if ($ai>0 && $ai<3); + &pxor ($xb,$xc); + &movdqa($xb_,&QWP(16*$bn-128,"ebx")) if ($i<7); + &movdqa ($xa_,$xb); # borrow as temporary + &pslld ($xb,12); + &psrld ($xa_,20); + &por ($xb,$xa_); + &movdqa($xa_,&QWP(16*$an-128,"ebx")); + &paddd ($xa,$xb); + &movdqa($xd_,&QWP(16*$dn-128,"ebx")) if ($di!=$dn); + &pxor ($xd,$xa); + &movdqa (&QWP(16*$ai-128,"ebx"),$xa); + &pshufb ($xd,&QWP(16,"eax")); # rot8 + &paddd ($xc,$xd); + &movdqa (&QWP(16*$di-128,"ebx"),$xd) if ($di!=$dn); + &movdqa ($xd_,$xd) if ($di==$dn); + &pxor ($xb,$xc); + &paddd ($xa_,$xb_) if ($i<7); # elsewhere + &movdqa ($xa,$xb); # borrow as temporary + &pslld ($xb,7); + &psrld ($xa,25); + &pxor ($xd_,$xa_) if ($i<7); # elsewhere + &por ($xb,$xa); + + ($xa,$xa_)=($xa_,$xa); + ($xb,$xb_)=($xb_,$xb); + ($xc,$xc_)=($xc_,$xc); + ($xd,$xd_)=($xd_,$xd); +} + +&function_begin("ChaCha20_ssse3"); +&set_label("ssse3_shortcut"); + &mov ($out,&wparam(0)); + &mov ($inp,&wparam(1)); + &mov ($len,&wparam(2)); + &mov ("edx",&wparam(3)); # key + &mov ("ebx",&wparam(4)); # counter and nonce + + &mov ("ebp","esp"); + &stack_push (131); + &and ("esp",-64); + &mov (&DWP(512,"esp"),"ebp"); + + &lea ("eax",&DWP(&label("ssse3_data")."-". + &label("pic_point"),"eax")); + &movdqu ("xmm3",&QWP(0,"ebx")); # counter and nonce + + &cmp ($len,64*4); + &jb (&label("1x")); + + &mov (&DWP(512+4,"esp"),"edx"); # offload pointers + &mov (&DWP(512+8,"esp"),"ebx"); + &sub ($len,64*4); # bias len + &lea ("ebp",&DWP(256+128,"esp")); # size optimization + + &movdqu ("xmm7",&QWP(0,"edx")); # key + &pshufd ("xmm0","xmm3",0x00); + &pshufd ("xmm1","xmm3",0x55); + &pshufd ("xmm2","xmm3",0xaa); + &pshufd ("xmm3","xmm3",0xff); + &paddd ("xmm0",&QWP(16*3,"eax")); # fix counters + &pshufd ("xmm4","xmm7",0x00); + &pshufd ("xmm5","xmm7",0x55); + &psubd ("xmm0",&QWP(16*4,"eax")); + &pshufd ("xmm6","xmm7",0xaa); + &pshufd ("xmm7","xmm7",0xff); + &movdqa (&QWP(16*12-128,"ebp"),"xmm0"); + &movdqa (&QWP(16*13-128,"ebp"),"xmm1"); + &movdqa (&QWP(16*14-128,"ebp"),"xmm2"); + &movdqa (&QWP(16*15-128,"ebp"),"xmm3"); + &movdqu ("xmm3",&QWP(16,"edx")); # key + &movdqa (&QWP(16*4-128,"ebp"),"xmm4"); + &movdqa (&QWP(16*5-128,"ebp"),"xmm5"); + &movdqa (&QWP(16*6-128,"ebp"),"xmm6"); + &movdqa (&QWP(16*7-128,"ebp"),"xmm7"); + &movdqa ("xmm7",&QWP(16*2,"eax")); # sigma + &lea ("ebx",&DWP(128,"esp")); # size optimization + + &pshufd ("xmm0","xmm3",0x00); + &pshufd ("xmm1","xmm3",0x55); + &pshufd ("xmm2","xmm3",0xaa); + &pshufd ("xmm3","xmm3",0xff); + &pshufd ("xmm4","xmm7",0x00); + &pshufd ("xmm5","xmm7",0x55); + &pshufd ("xmm6","xmm7",0xaa); + &pshufd ("xmm7","xmm7",0xff); + &movdqa (&QWP(16*8-128,"ebp"),"xmm0"); + &movdqa (&QWP(16*9-128,"ebp"),"xmm1"); + &movdqa (&QWP(16*10-128,"ebp"),"xmm2"); + &movdqa (&QWP(16*11-128,"ebp"),"xmm3"); + &movdqa (&QWP(16*0-128,"ebp"),"xmm4"); + &movdqa (&QWP(16*1-128,"ebp"),"xmm5"); + &movdqa (&QWP(16*2-128,"ebp"),"xmm6"); + &movdqa (&QWP(16*3-128,"ebp"),"xmm7"); + + &lea ($inp,&DWP(128,$inp)); # size optimization + &lea ($out,&DWP(128,$out)); # size optimization + &jmp (&label("outer_loop")); + +&set_label("outer_loop",16); + #&movdqa ("xmm0",&QWP(16*0-128,"ebp")); # copy key material + &movdqa ("xmm1",&QWP(16*1-128,"ebp")); + &movdqa ("xmm2",&QWP(16*2-128,"ebp")); + &movdqa ("xmm3",&QWP(16*3-128,"ebp")); + #&movdqa ("xmm4",&QWP(16*4-128,"ebp")); + &movdqa ("xmm5",&QWP(16*5-128,"ebp")); + &movdqa ("xmm6",&QWP(16*6-128,"ebp")); + &movdqa ("xmm7",&QWP(16*7-128,"ebp")); + #&movdqa (&QWP(16*0-128,"ebx"),"xmm0"); + &movdqa (&QWP(16*1-128,"ebx"),"xmm1"); + &movdqa (&QWP(16*2-128,"ebx"),"xmm2"); + &movdqa (&QWP(16*3-128,"ebx"),"xmm3"); + #&movdqa (&QWP(16*4-128,"ebx"),"xmm4"); + &movdqa (&QWP(16*5-128,"ebx"),"xmm5"); + &movdqa (&QWP(16*6-128,"ebx"),"xmm6"); + &movdqa (&QWP(16*7-128,"ebx"),"xmm7"); + #&movdqa ("xmm0",&QWP(16*8-128,"ebp")); + #&movdqa ("xmm1",&QWP(16*9-128,"ebp")); + &movdqa ("xmm2",&QWP(16*10-128,"ebp")); + &movdqa ("xmm3",&QWP(16*11-128,"ebp")); + &movdqa ("xmm4",&QWP(16*12-128,"ebp")); + &movdqa ("xmm5",&QWP(16*13-128,"ebp")); + &movdqa ("xmm6",&QWP(16*14-128,"ebp")); + &movdqa ("xmm7",&QWP(16*15-128,"ebp")); + &paddd ("xmm4",&QWP(16*4,"eax")); # counter value + #&movdqa (&QWP(16*8-128,"ebx"),"xmm0"); + #&movdqa (&QWP(16*9-128,"ebx"),"xmm1"); + &movdqa (&QWP(16*10-128,"ebx"),"xmm2"); + &movdqa (&QWP(16*11-128,"ebx"),"xmm3"); + &movdqa (&QWP(16*12-128,"ebx"),"xmm4"); + &movdqa (&QWP(16*13-128,"ebx"),"xmm5"); + &movdqa (&QWP(16*14-128,"ebx"),"xmm6"); + &movdqa (&QWP(16*15-128,"ebx"),"xmm7"); + &movdqa (&QWP(16*12-128,"ebp"),"xmm4"); # save counter value + + &movdqa ($xa, &QWP(16*0-128,"ebp")); + &movdqa ($xd, "xmm4"); + &movdqa ($xb_,&QWP(16*4-128,"ebp")); + &movdqa ($xc, &QWP(16*8-128,"ebp")); + &movdqa ($xc_,&QWP(16*9-128,"ebp")); + + &mov ("edx",10); # loop counter + &nop (); + +&set_label("loop",16); + &paddd ($xa,$xb_); # elsewhere + &movdqa ($xb,$xb_); + &pxor ($xd,$xa); # elsewhere + &QUARTERROUND_SSSE3(0, 4, 8, 12, 0); + &QUARTERROUND_SSSE3(1, 5, 9, 13, 1); + &QUARTERROUND_SSSE3(2, 6,10, 14, 2); + &QUARTERROUND_SSSE3(3, 7,11, 15, 3); + &QUARTERROUND_SSSE3(0, 5,10, 15, 4); + &QUARTERROUND_SSSE3(1, 6,11, 12, 5); + &QUARTERROUND_SSSE3(2, 7, 8, 13, 6); + &QUARTERROUND_SSSE3(3, 4, 9, 14, 7); + &dec ("edx"); + &jnz (&label("loop")); + + &movdqa (&QWP(16*4-128,"ebx"),$xb_); + &movdqa (&QWP(16*8-128,"ebx"),$xc); + &movdqa (&QWP(16*9-128,"ebx"),$xc_); + &movdqa (&QWP(16*12-128,"ebx"),$xd); + &movdqa (&QWP(16*14-128,"ebx"),$xd_); + + my ($xa0,$xa1,$xa2,$xa3,$xt0,$xt1,$xt2,$xt3)=map("xmm$_",(0..7)); + + #&movdqa ($xa0,&QWP(16*0-128,"ebx")); # it's there + &movdqa ($xa1,&QWP(16*1-128,"ebx")); + &movdqa ($xa2,&QWP(16*2-128,"ebx")); + &movdqa ($xa3,&QWP(16*3-128,"ebx")); + + for($i=0;$i<256;$i+=64) { + &paddd ($xa0,&QWP($i+16*0-128,"ebp")); # accumulate key material + &paddd ($xa1,&QWP($i+16*1-128,"ebp")); + &paddd ($xa2,&QWP($i+16*2-128,"ebp")); + &paddd ($xa3,&QWP($i+16*3-128,"ebp")); + + &movdqa ($xt2,$xa0); # "de-interlace" data + &punpckldq ($xa0,$xa1); + &movdqa ($xt3,$xa2); + &punpckldq ($xa2,$xa3); + &punpckhdq ($xt2,$xa1); + &punpckhdq ($xt3,$xa3); + &movdqa ($xa1,$xa0); + &punpcklqdq ($xa0,$xa2); # "a0" + &movdqa ($xa3,$xt2); + &punpcklqdq ($xt2,$xt3); # "a2" + &punpckhqdq ($xa1,$xa2); # "a1" + &punpckhqdq ($xa3,$xt3); # "a3" + + #($xa2,$xt2)=($xt2,$xa2); + + &movdqu ($xt0,&QWP(64*0-128,$inp)); # load input + &movdqu ($xt1,&QWP(64*1-128,$inp)); + &movdqu ($xa2,&QWP(64*2-128,$inp)); + &movdqu ($xt3,&QWP(64*3-128,$inp)); + &lea ($inp,&QWP($i<192?16:(64*4-16*3),$inp)); + &pxor ($xt0,$xa0); + &movdqa ($xa0,&QWP($i+16*4-128,"ebx")) if ($i<192); + &pxor ($xt1,$xa1); + &movdqa ($xa1,&QWP($i+16*5-128,"ebx")) if ($i<192); + &pxor ($xt2,$xa2); + &movdqa ($xa2,&QWP($i+16*6-128,"ebx")) if ($i<192); + &pxor ($xt3,$xa3); + &movdqa ($xa3,&QWP($i+16*7-128,"ebx")) if ($i<192); + &movdqu (&QWP(64*0-128,$out),$xt0); # store output + &movdqu (&QWP(64*1-128,$out),$xt1); + &movdqu (&QWP(64*2-128,$out),$xt2); + &movdqu (&QWP(64*3-128,$out),$xt3); + &lea ($out,&QWP($i<192?16:(64*4-16*3),$out)); + } + &sub ($len,64*4); + &jnc (&label("outer_loop")); + + &add ($len,64*4); + &jz (&label("done")); + + &mov ("ebx",&DWP(512+8,"esp")); # restore pointers + &lea ($inp,&DWP(-128,$inp)); + &mov ("edx",&DWP(512+4,"esp")); + &lea ($out,&DWP(-128,$out)); + + &movd ("xmm2",&DWP(16*12-128,"ebp")); # counter value + &movdqu ("xmm3",&QWP(0,"ebx")); + &paddd ("xmm2",&QWP(16*6,"eax")); # +four + &pand ("xmm3",&QWP(16*7,"eax")); + &por ("xmm3","xmm2"); # counter value +{ +my ($a,$b,$c,$d,$t,$t1,$rot16,$rot24)=map("xmm$_",(0..7)); + +sub SSSE3ROUND { # critical path is 20 "SIMD ticks" per round + &paddd ($a,$b); + &pxor ($d,$a); + &pshufb ($d,$rot16); + + &paddd ($c,$d); + &pxor ($b,$c); + &movdqa ($t,$b); + &psrld ($b,20); + &pslld ($t,12); + &por ($b,$t); + + &paddd ($a,$b); + &pxor ($d,$a); + &pshufb ($d,$rot24); + + &paddd ($c,$d); + &pxor ($b,$c); + &movdqa ($t,$b); + &psrld ($b,25); + &pslld ($t,7); + &por ($b,$t); +} + +&set_label("1x"); + &movdqa ($a,&QWP(16*2,"eax")); # sigma + &movdqu ($b,&QWP(0,"edx")); + &movdqu ($c,&QWP(16,"edx")); + #&movdqu ($d,&QWP(0,"ebx")); # already loaded + &movdqa ($rot16,&QWP(0,"eax")); + &movdqa ($rot24,&QWP(16,"eax")); + &mov (&DWP(16*3,"esp"),"ebp"); + + &movdqa (&QWP(16*0,"esp"),$a); + &movdqa (&QWP(16*1,"esp"),$b); + &movdqa (&QWP(16*2,"esp"),$c); + &movdqa (&QWP(16*3,"esp"),$d); + &mov ("edx",10); + &jmp (&label("loop1x")); + +&set_label("outer1x",16); + &movdqa ($d,&QWP(16*5,"eax")); # one + &movdqa ($a,&QWP(16*0,"esp")); + &movdqa ($b,&QWP(16*1,"esp")); + &movdqa ($c,&QWP(16*2,"esp")); + &paddd ($d,&QWP(16*3,"esp")); + &mov ("edx",10); + &movdqa (&QWP(16*3,"esp"),$d); + &jmp (&label("loop1x")); + +&set_label("loop1x",16); + &SSSE3ROUND(); + &pshufd ($c,$c,0b01001110); + &pshufd ($b,$b,0b00111001); + &pshufd ($d,$d,0b10010011); + &nop (); + + &SSSE3ROUND(); + &pshufd ($c,$c,0b01001110); + &pshufd ($b,$b,0b10010011); + &pshufd ($d,$d,0b00111001); + + &dec ("edx"); + &jnz (&label("loop1x")); + + &paddd ($a,&QWP(16*0,"esp")); + &paddd ($b,&QWP(16*1,"esp")); + &paddd ($c,&QWP(16*2,"esp")); + &paddd ($d,&QWP(16*3,"esp")); + + &cmp ($len,64); + &jb (&label("tail")); + + &movdqu ($t,&QWP(16*0,$inp)); + &movdqu ($t1,&QWP(16*1,$inp)); + &pxor ($a,$t); # xor with input + &movdqu ($t,&QWP(16*2,$inp)); + &pxor ($b,$t1); + &movdqu ($t1,&QWP(16*3,$inp)); + &pxor ($c,$t); + &pxor ($d,$t1); + &lea ($inp,&DWP(16*4,$inp)); # inp+=64 + + &movdqu (&QWP(16*0,$out),$a); # write output + &movdqu (&QWP(16*1,$out),$b); + &movdqu (&QWP(16*2,$out),$c); + &movdqu (&QWP(16*3,$out),$d); + &lea ($out,&DWP(16*4,$out)); # inp+=64 + + &sub ($len,64); + &jnz (&label("outer1x")); + + &jmp (&label("done")); + +&set_label("tail"); + &movdqa (&QWP(16*0,"esp"),$a); + &movdqa (&QWP(16*1,"esp"),$b); + &movdqa (&QWP(16*2,"esp"),$c); + &movdqa (&QWP(16*3,"esp"),$d); + + &xor ("eax","eax"); + &xor ("edx","edx"); + &xor ("ebp","ebp"); + +&set_label("tail_loop"); + &movb ("al",&BP(0,"esp","ebp")); + &movb ("dl",&BP(0,$inp,"ebp")); + &lea ("ebp",&DWP(1,"ebp")); + &xor ("al","dl"); + &movb (&BP(-1,$out,"ebp"),"al"); + &dec ($len); + &jnz (&label("tail_loop")); +} +&set_label("done"); + &mov ("esp",&DWP(512,"esp")); +&function_end("ChaCha20_ssse3"); + +&align (64); +&set_label("ssse3_data"); +&data_byte(0x2,0x3,0x0,0x1, 0x6,0x7,0x4,0x5, 0xa,0xb,0x8,0x9, 0xe,0xf,0xc,0xd); +&data_byte(0x3,0x0,0x1,0x2, 0x7,0x4,0x5,0x6, 0xb,0x8,0x9,0xa, 0xf,0xc,0xd,0xe); +&data_word(0x61707865,0x3320646e,0x79622d32,0x6b206574); +&data_word(0,1,2,3); +&data_word(4,4,4,4); +&data_word(1,0,0,0); +&data_word(4,0,0,0); +&data_word(0,-1,-1,-1); +&align (64); +} +&asciz ("ChaCha20 for x86, CRYPTOGAMS by "); + +&asm_finish(); diff --git a/external/boringssl/crypto/chacha/asm/chacha-x86_64.pl b/external/boringssl/crypto/chacha/asm/chacha-x86_64.pl new file mode 100755 index 0000000000..55b726d230 --- /dev/null +++ b/external/boringssl/crypto/chacha/asm/chacha-x86_64.pl @@ -0,0 +1,1767 @@ +#!/usr/bin/env perl +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# November 2014 +# +# ChaCha20 for x86_64. +# +# Performance in cycles per byte out of large buffer. +# +# IALU/gcc 4.8(i) 1xSSSE3/SSE2 4xSSSE3 8xAVX2 +# +# P4 9.48/+99% -/22.7(ii) - +# Core2 7.83/+55% 7.90/8.08 4.35 +# Westmere 7.19/+50% 5.60/6.70 3.00 +# Sandy Bridge 8.31/+42% 5.45/6.76 2.72 +# Ivy Bridge 6.71/+46% 5.40/6.49 2.41 +# Haswell 5.92/+43% 5.20/6.45 2.42 1.23 +# Silvermont 12.0/+33% 7.75/7.40 7.03(iii) +# Sledgehammer 7.28/+52% -/14.2(ii) - +# Bulldozer 9.66/+28% 9.85/11.1 3.06(iv) +# VIA Nano 10.5/+46% 6.72/8.60 6.05 +# +# (i) compared to older gcc 3.x one can observe >2x improvement on +# most platforms; +# (ii) as it can be seen, SSE2 performance is too low on legacy +# processors; NxSSE2 results are naturally better, but not +# impressively better than IALU ones, which is why you won't +# find SSE2 code below; +# (iii) this is not optimal result for Atom because of MSROM +# limitations, SSE2 can do better, but gain is considered too +# low to justify the [maintenance] effort; +# (iv) Bulldozer actually executes 4xXOP code path that delivers 2.20; +# +# Modified from upstream OpenSSL to remove the XOP code. + +$flavour = shift; +$output = shift; +if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } + +$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or +die "can't locate x86_64-xlate.pl"; + +$avx = 2; + +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; + +# input parameter block +($out,$inp,$len,$key,$counter)=("%rdi","%rsi","%rdx","%rcx","%r8"); + +$code.=<<___; +.text + +.extern OPENSSL_ia32cap_P + +.align 64 +.Lzero: +.long 0,0,0,0 +.Lone: +.long 1,0,0,0 +.Linc: +.long 0,1,2,3 +.Lfour: +.long 4,4,4,4 +.Lincy: +.long 0,2,4,6,1,3,5,7 +.Leight: +.long 8,8,8,8,8,8,8,8 +.Lrot16: +.byte 0x2,0x3,0x0,0x1, 0x6,0x7,0x4,0x5, 0xa,0xb,0x8,0x9, 0xe,0xf,0xc,0xd +.Lrot24: +.byte 0x3,0x0,0x1,0x2, 0x7,0x4,0x5,0x6, 0xb,0x8,0x9,0xa, 0xf,0xc,0xd,0xe +.Lsigma: +.asciz "expand 32-byte k" +.asciz "ChaCha20 for x86_64, CRYPTOGAMS by " +___ + +sub AUTOLOAD() # thunk [simplified] 32-bit style perlasm +{ my $opcode = $AUTOLOAD; $opcode =~ s/.*:://; + my $arg = pop; + $arg = "\$$arg" if ($arg*1 eq $arg); + $code .= "\t$opcode\t".join(',',$arg,reverse @_)."\n"; +} + +@x=("%eax","%ebx","%ecx","%edx",map("%r${_}d",(8..11)), + "%nox","%nox","%nox","%nox",map("%r${_}d",(12..15))); +@t=("%esi","%edi"); + +sub ROUND { # critical path is 24 cycles per round +my ($a0,$b0,$c0,$d0)=@_; +my ($a1,$b1,$c1,$d1)=map(($_&~3)+(($_+1)&3),($a0,$b0,$c0,$d0)); +my ($a2,$b2,$c2,$d2)=map(($_&~3)+(($_+1)&3),($a1,$b1,$c1,$d1)); +my ($a3,$b3,$c3,$d3)=map(($_&~3)+(($_+1)&3),($a2,$b2,$c2,$d2)); +my ($xc,$xc_)=map("\"$_\"",@t); +my @x=map("\"$_\"",@x); + + # Consider order in which variables are addressed by their + # index: + # + # a b c d + # + # 0 4 8 12 < even round + # 1 5 9 13 + # 2 6 10 14 + # 3 7 11 15 + # 0 5 10 15 < odd round + # 1 6 11 12 + # 2 7 8 13 + # 3 4 9 14 + # + # 'a', 'b' and 'd's are permanently allocated in registers, + # @x[0..7,12..15], while 'c's are maintained in memory. If + # you observe 'c' column, you'll notice that pair of 'c's is + # invariant between rounds. This means that we have to reload + # them once per round, in the middle. This is why you'll see + # bunch of 'c' stores and loads in the middle, but none in + # the beginning or end. + + # Normally instructions would be interleaved to favour in-order + # execution. Generally out-of-order cores manage it gracefully, + # but not this time for some reason. As in-order execution + # cores are dying breed, old Atom is the only one around, + # instructions are left uninterleaved. Besides, Atom is better + # off executing 1xSSSE3 code anyway... + + ( + "&add (@x[$a0],@x[$b0])", # Q1 + "&xor (@x[$d0],@x[$a0])", + "&rol (@x[$d0],16)", + "&add (@x[$a1],@x[$b1])", # Q2 + "&xor (@x[$d1],@x[$a1])", + "&rol (@x[$d1],16)", + + "&add ($xc,@x[$d0])", + "&xor (@x[$b0],$xc)", + "&rol (@x[$b0],12)", + "&add ($xc_,@x[$d1])", + "&xor (@x[$b1],$xc_)", + "&rol (@x[$b1],12)", + + "&add (@x[$a0],@x[$b0])", + "&xor (@x[$d0],@x[$a0])", + "&rol (@x[$d0],8)", + "&add (@x[$a1],@x[$b1])", + "&xor (@x[$d1],@x[$a1])", + "&rol (@x[$d1],8)", + + "&add ($xc,@x[$d0])", + "&xor (@x[$b0],$xc)", + "&rol (@x[$b0],7)", + "&add ($xc_,@x[$d1])", + "&xor (@x[$b1],$xc_)", + "&rol (@x[$b1],7)", + + "&mov (\"4*$c0(%rsp)\",$xc)", # reload pair of 'c's + "&mov (\"4*$c1(%rsp)\",$xc_)", + "&mov ($xc,\"4*$c2(%rsp)\")", + "&mov ($xc_,\"4*$c3(%rsp)\")", + + "&add (@x[$a2],@x[$b2])", # Q3 + "&xor (@x[$d2],@x[$a2])", + "&rol (@x[$d2],16)", + "&add (@x[$a3],@x[$b3])", # Q4 + "&xor (@x[$d3],@x[$a3])", + "&rol (@x[$d3],16)", + + "&add ($xc,@x[$d2])", + "&xor (@x[$b2],$xc)", + "&rol (@x[$b2],12)", + "&add ($xc_,@x[$d3])", + "&xor (@x[$b3],$xc_)", + "&rol (@x[$b3],12)", + + "&add (@x[$a2],@x[$b2])", + "&xor (@x[$d2],@x[$a2])", + "&rol (@x[$d2],8)", + "&add (@x[$a3],@x[$b3])", + "&xor (@x[$d3],@x[$a3])", + "&rol (@x[$d3],8)", + + "&add ($xc,@x[$d2])", + "&xor (@x[$b2],$xc)", + "&rol (@x[$b2],7)", + "&add ($xc_,@x[$d3])", + "&xor (@x[$b3],$xc_)", + "&rol (@x[$b3],7)" + ); +} + +######################################################################## +# Generic code path that handles all lengths on pre-SSSE3 processors. +$code.=<<___; +.globl ChaCha20_ctr32 +.type ChaCha20_ctr32,\@function,5 +.align 64 +ChaCha20_ctr32: + cmp \$0,$len + je .Lno_data + mov OPENSSL_ia32cap_P+4(%rip),%r10 + test \$`1<<(41-32)`,%r10d + jnz .LChaCha20_ssse3 + + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + sub \$64+24,%rsp + + #movdqa .Lsigma(%rip),%xmm0 + movdqu ($key),%xmm1 + movdqu 16($key),%xmm2 + movdqu ($counter),%xmm3 + movdqa .Lone(%rip),%xmm4 + + #movdqa %xmm0,4*0(%rsp) # key[0] + movdqa %xmm1,4*4(%rsp) # key[1] + movdqa %xmm2,4*8(%rsp) # key[2] + movdqa %xmm3,4*12(%rsp) # key[3] + mov $len,%rbp # reassign $len + jmp .Loop_outer + +.align 32 +.Loop_outer: + mov \$0x61707865,@x[0] # 'expa' + mov \$0x3320646e,@x[1] # 'nd 3' + mov \$0x79622d32,@x[2] # '2-by' + mov \$0x6b206574,@x[3] # 'te k' + mov 4*4(%rsp),@x[4] + mov 4*5(%rsp),@x[5] + mov 4*6(%rsp),@x[6] + mov 4*7(%rsp),@x[7] + movd %xmm3,@x[12] + mov 4*13(%rsp),@x[13] + mov 4*14(%rsp),@x[14] + mov 4*15(%rsp),@x[15] + + mov %rbp,64+0(%rsp) # save len + mov \$10,%ebp + mov $inp,64+8(%rsp) # save inp + movq %xmm2,%rsi # "@x[8]" + mov $out,64+16(%rsp) # save out + mov %rsi,%rdi + shr \$32,%rdi # "@x[9]" + jmp .Loop + +.align 32 +.Loop: +___ + foreach (&ROUND (0, 4, 8,12)) { eval; } + foreach (&ROUND (0, 5,10,15)) { eval; } + &dec ("%ebp"); + &jnz (".Loop"); + +$code.=<<___; + mov @t[1],4*9(%rsp) # modulo-scheduled + mov @t[0],4*8(%rsp) + mov 64(%rsp),%rbp # load len + movdqa %xmm2,%xmm1 + mov 64+8(%rsp),$inp # load inp + paddd %xmm4,%xmm3 # increment counter + mov 64+16(%rsp),$out # load out + + add \$0x61707865,@x[0] # 'expa' + add \$0x3320646e,@x[1] # 'nd 3' + add \$0x79622d32,@x[2] # '2-by' + add \$0x6b206574,@x[3] # 'te k' + add 4*4(%rsp),@x[4] + add 4*5(%rsp),@x[5] + add 4*6(%rsp),@x[6] + add 4*7(%rsp),@x[7] + add 4*12(%rsp),@x[12] + add 4*13(%rsp),@x[13] + add 4*14(%rsp),@x[14] + add 4*15(%rsp),@x[15] + paddd 4*8(%rsp),%xmm1 + + cmp \$64,%rbp + jb .Ltail + + xor 4*0($inp),@x[0] # xor with input + xor 4*1($inp),@x[1] + xor 4*2($inp),@x[2] + xor 4*3($inp),@x[3] + xor 4*4($inp),@x[4] + xor 4*5($inp),@x[5] + xor 4*6($inp),@x[6] + xor 4*7($inp),@x[7] + movdqu 4*8($inp),%xmm0 + xor 4*12($inp),@x[12] + xor 4*13($inp),@x[13] + xor 4*14($inp),@x[14] + xor 4*15($inp),@x[15] + lea 4*16($inp),$inp # inp+=64 + pxor %xmm1,%xmm0 + + movdqa %xmm2,4*8(%rsp) + movd %xmm3,4*12(%rsp) + + mov @x[0],4*0($out) # write output + mov @x[1],4*1($out) + mov @x[2],4*2($out) + mov @x[3],4*3($out) + mov @x[4],4*4($out) + mov @x[5],4*5($out) + mov @x[6],4*6($out) + mov @x[7],4*7($out) + movdqu %xmm0,4*8($out) + mov @x[12],4*12($out) + mov @x[13],4*13($out) + mov @x[14],4*14($out) + mov @x[15],4*15($out) + lea 4*16($out),$out # out+=64 + + sub \$64,%rbp + jnz .Loop_outer + + jmp .Ldone + +.align 16 +.Ltail: + mov @x[0],4*0(%rsp) + mov @x[1],4*1(%rsp) + xor %rbx,%rbx + mov @x[2],4*2(%rsp) + mov @x[3],4*3(%rsp) + mov @x[4],4*4(%rsp) + mov @x[5],4*5(%rsp) + mov @x[6],4*6(%rsp) + mov @x[7],4*7(%rsp) + movdqa %xmm1,4*8(%rsp) + mov @x[12],4*12(%rsp) + mov @x[13],4*13(%rsp) + mov @x[14],4*14(%rsp) + mov @x[15],4*15(%rsp) + +.Loop_tail: + movzb ($inp,%rbx),%eax + movzb (%rsp,%rbx),%edx + lea 1(%rbx),%rbx + xor %edx,%eax + mov %al,-1($out,%rbx) + dec %rbp + jnz .Loop_tail + +.Ldone: + add \$64+24,%rsp + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx +.Lno_data: + ret +.size ChaCha20_ctr32,.-ChaCha20_ctr32 +___ + +######################################################################## +# SSSE3 code path that handles shorter lengths +{ +my ($a,$b,$c,$d,$t,$t1,$rot16,$rot24)=map("%xmm$_",(0..7)); + +sub SSSE3ROUND { # critical path is 20 "SIMD ticks" per round + &paddd ($a,$b); + &pxor ($d,$a); + &pshufb ($d,$rot16); + + &paddd ($c,$d); + &pxor ($b,$c); + &movdqa ($t,$b); + &psrld ($b,20); + &pslld ($t,12); + &por ($b,$t); + + &paddd ($a,$b); + &pxor ($d,$a); + &pshufb ($d,$rot24); + + &paddd ($c,$d); + &pxor ($b,$c); + &movdqa ($t,$b); + &psrld ($b,25); + &pslld ($t,7); + &por ($b,$t); +} + +my $xframe = $win64 ? 32+32+8 : 24; + +$code.=<<___; +.type ChaCha20_ssse3,\@function,5 +.align 32 +ChaCha20_ssse3: +.LChaCha20_ssse3: +___ +$code.=<<___; + cmp \$128,$len # we might throw away some data, + ja .LChaCha20_4x # but overall it won't be slower + +.Ldo_sse3_after_all: + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + + sub \$64+$xframe,%rsp +___ +$code.=<<___ if ($win64); + movaps %xmm6,64+32(%rsp) + movaps %xmm7,64+48(%rsp) +___ +$code.=<<___; + movdqa .Lsigma(%rip),$a + movdqu ($key),$b + movdqu 16($key),$c + movdqu ($counter),$d + movdqa .Lrot16(%rip),$rot16 + movdqa .Lrot24(%rip),$rot24 + + movdqa $a,0x00(%rsp) + movdqa $b,0x10(%rsp) + movdqa $c,0x20(%rsp) + movdqa $d,0x30(%rsp) + mov \$10,%ebp + jmp .Loop_ssse3 + +.align 32 +.Loop_outer_ssse3: + movdqa .Lone(%rip),$d + movdqa 0x00(%rsp),$a + movdqa 0x10(%rsp),$b + movdqa 0x20(%rsp),$c + paddd 0x30(%rsp),$d + mov \$10,%ebp + movdqa $d,0x30(%rsp) + jmp .Loop_ssse3 + +.align 32 +.Loop_ssse3: +___ + &SSSE3ROUND(); + &pshufd ($c,$c,0b01001110); + &pshufd ($b,$b,0b00111001); + &pshufd ($d,$d,0b10010011); + &nop (); + + &SSSE3ROUND(); + &pshufd ($c,$c,0b01001110); + &pshufd ($b,$b,0b10010011); + &pshufd ($d,$d,0b00111001); + + &dec ("%ebp"); + &jnz (".Loop_ssse3"); + +$code.=<<___; + paddd 0x00(%rsp),$a + paddd 0x10(%rsp),$b + paddd 0x20(%rsp),$c + paddd 0x30(%rsp),$d + + cmp \$64,$len + jb .Ltail_ssse3 + + movdqu 0x00($inp),$t + movdqu 0x10($inp),$t1 + pxor $t,$a # xor with input + movdqu 0x20($inp),$t + pxor $t1,$b + movdqu 0x30($inp),$t1 + lea 0x40($inp),$inp # inp+=64 + pxor $t,$c + pxor $t1,$d + + movdqu $a,0x00($out) # write output + movdqu $b,0x10($out) + movdqu $c,0x20($out) + movdqu $d,0x30($out) + lea 0x40($out),$out # out+=64 + + sub \$64,$len + jnz .Loop_outer_ssse3 + + jmp .Ldone_ssse3 + +.align 16 +.Ltail_ssse3: + movdqa $a,0x00(%rsp) + movdqa $b,0x10(%rsp) + movdqa $c,0x20(%rsp) + movdqa $d,0x30(%rsp) + xor %rbx,%rbx + +.Loop_tail_ssse3: + movzb ($inp,%rbx),%eax + movzb (%rsp,%rbx),%ecx + lea 1(%rbx),%rbx + xor %ecx,%eax + mov %al,-1($out,%rbx) + dec $len + jnz .Loop_tail_ssse3 + +.Ldone_ssse3: +___ +$code.=<<___ if ($win64); + movaps 64+32(%rsp),%xmm6 + movaps 64+48(%rsp),%xmm7 +___ +$code.=<<___; + add \$64+$xframe,%rsp + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + ret +.size ChaCha20_ssse3,.-ChaCha20_ssse3 +___ +} + +######################################################################## +# SSSE3 code path that handles longer messages. +{ +# assign variables to favor Atom front-end +my ($xd0,$xd1,$xd2,$xd3, $xt0,$xt1,$xt2,$xt3, + $xa0,$xa1,$xa2,$xa3, $xb0,$xb1,$xb2,$xb3)=map("%xmm$_",(0..15)); +my @xx=($xa0,$xa1,$xa2,$xa3, $xb0,$xb1,$xb2,$xb3, + "%nox","%nox","%nox","%nox", $xd0,$xd1,$xd2,$xd3); + +sub SSSE3_lane_ROUND { +my ($a0,$b0,$c0,$d0)=@_; +my ($a1,$b1,$c1,$d1)=map(($_&~3)+(($_+1)&3),($a0,$b0,$c0,$d0)); +my ($a2,$b2,$c2,$d2)=map(($_&~3)+(($_+1)&3),($a1,$b1,$c1,$d1)); +my ($a3,$b3,$c3,$d3)=map(($_&~3)+(($_+1)&3),($a2,$b2,$c2,$d2)); +my ($xc,$xc_,$t0,$t1)=map("\"$_\"",$xt0,$xt1,$xt2,$xt3); +my @x=map("\"$_\"",@xx); + + # Consider order in which variables are addressed by their + # index: + # + # a b c d + # + # 0 4 8 12 < even round + # 1 5 9 13 + # 2 6 10 14 + # 3 7 11 15 + # 0 5 10 15 < odd round + # 1 6 11 12 + # 2 7 8 13 + # 3 4 9 14 + # + # 'a', 'b' and 'd's are permanently allocated in registers, + # @x[0..7,12..15], while 'c's are maintained in memory. If + # you observe 'c' column, you'll notice that pair of 'c's is + # invariant between rounds. This means that we have to reload + # them once per round, in the middle. This is why you'll see + # bunch of 'c' stores and loads in the middle, but none in + # the beginning or end. + + ( + "&paddd (@x[$a0],@x[$b0])", # Q1 + "&paddd (@x[$a1],@x[$b1])", # Q2 + "&pxor (@x[$d0],@x[$a0])", + "&pxor (@x[$d1],@x[$a1])", + "&pshufb (@x[$d0],$t1)", + "&pshufb (@x[$d1],$t1)", + + "&paddd ($xc,@x[$d0])", + "&paddd ($xc_,@x[$d1])", + "&pxor (@x[$b0],$xc)", + "&pxor (@x[$b1],$xc_)", + "&movdqa ($t0,@x[$b0])", + "&pslld (@x[$b0],12)", + "&psrld ($t0,20)", + "&movdqa ($t1,@x[$b1])", + "&pslld (@x[$b1],12)", + "&por (@x[$b0],$t0)", + "&psrld ($t1,20)", + "&movdqa ($t0,'(%r11)')", # .Lrot24(%rip) + "&por (@x[$b1],$t1)", + + "&paddd (@x[$a0],@x[$b0])", + "&paddd (@x[$a1],@x[$b1])", + "&pxor (@x[$d0],@x[$a0])", + "&pxor (@x[$d1],@x[$a1])", + "&pshufb (@x[$d0],$t0)", + "&pshufb (@x[$d1],$t0)", + + "&paddd ($xc,@x[$d0])", + "&paddd ($xc_,@x[$d1])", + "&pxor (@x[$b0],$xc)", + "&pxor (@x[$b1],$xc_)", + "&movdqa ($t1,@x[$b0])", + "&pslld (@x[$b0],7)", + "&psrld ($t1,25)", + "&movdqa ($t0,@x[$b1])", + "&pslld (@x[$b1],7)", + "&por (@x[$b0],$t1)", + "&psrld ($t0,25)", + "&movdqa ($t1,'(%r10)')", # .Lrot16(%rip) + "&por (@x[$b1],$t0)", + + "&movdqa (\"`16*($c0-8)`(%rsp)\",$xc)", # reload pair of 'c's + "&movdqa (\"`16*($c1-8)`(%rsp)\",$xc_)", + "&movdqa ($xc,\"`16*($c2-8)`(%rsp)\")", + "&movdqa ($xc_,\"`16*($c3-8)`(%rsp)\")", + + "&paddd (@x[$a2],@x[$b2])", # Q3 + "&paddd (@x[$a3],@x[$b3])", # Q4 + "&pxor (@x[$d2],@x[$a2])", + "&pxor (@x[$d3],@x[$a3])", + "&pshufb (@x[$d2],$t1)", + "&pshufb (@x[$d3],$t1)", + + "&paddd ($xc,@x[$d2])", + "&paddd ($xc_,@x[$d3])", + "&pxor (@x[$b2],$xc)", + "&pxor (@x[$b3],$xc_)", + "&movdqa ($t0,@x[$b2])", + "&pslld (@x[$b2],12)", + "&psrld ($t0,20)", + "&movdqa ($t1,@x[$b3])", + "&pslld (@x[$b3],12)", + "&por (@x[$b2],$t0)", + "&psrld ($t1,20)", + "&movdqa ($t0,'(%r11)')", # .Lrot24(%rip) + "&por (@x[$b3],$t1)", + + "&paddd (@x[$a2],@x[$b2])", + "&paddd (@x[$a3],@x[$b3])", + "&pxor (@x[$d2],@x[$a2])", + "&pxor (@x[$d3],@x[$a3])", + "&pshufb (@x[$d2],$t0)", + "&pshufb (@x[$d3],$t0)", + + "&paddd ($xc,@x[$d2])", + "&paddd ($xc_,@x[$d3])", + "&pxor (@x[$b2],$xc)", + "&pxor (@x[$b3],$xc_)", + "&movdqa ($t1,@x[$b2])", + "&pslld (@x[$b2],7)", + "&psrld ($t1,25)", + "&movdqa ($t0,@x[$b3])", + "&pslld (@x[$b3],7)", + "&por (@x[$b2],$t1)", + "&psrld ($t0,25)", + "&movdqa ($t1,'(%r10)')", # .Lrot16(%rip) + "&por (@x[$b3],$t0)" + ); +} + +my $xframe = $win64 ? 0xa0 : 0; + +$code.=<<___; +.type ChaCha20_4x,\@function,5 +.align 32 +ChaCha20_4x: +.LChaCha20_4x: + mov %r10,%r11 +___ +$code.=<<___ if ($avx>1); + shr \$32,%r10 # OPENSSL_ia32cap_P+8 + test \$`1<<5`,%r10 # test AVX2 + jnz .LChaCha20_8x +___ +$code.=<<___; + cmp \$192,$len + ja .Lproceed4x + + and \$`1<<26|1<<22`,%r11 # isolate XSAVE+MOVBE + cmp \$`1<<22`,%r11 # check for MOVBE without XSAVE + je .Ldo_sse3_after_all # to detect Atom + +.Lproceed4x: + lea -0x78(%rsp),%r11 + sub \$0x148+$xframe,%rsp +___ + ################ stack layout + # +0x00 SIMD equivalent of @x[8-12] + # ... + # +0x40 constant copy of key[0-2] smashed by lanes + # ... + # +0x100 SIMD counters (with nonce smashed by lanes) + # ... + # +0x140 +$code.=<<___ if ($win64); + movaps %xmm6,-0x30(%r11) + movaps %xmm7,-0x20(%r11) + movaps %xmm8,-0x10(%r11) + movaps %xmm9,0x00(%r11) + movaps %xmm10,0x10(%r11) + movaps %xmm11,0x20(%r11) + movaps %xmm12,0x30(%r11) + movaps %xmm13,0x40(%r11) + movaps %xmm14,0x50(%r11) + movaps %xmm15,0x60(%r11) +___ +$code.=<<___; + movdqa .Lsigma(%rip),$xa3 # key[0] + movdqu ($key),$xb3 # key[1] + movdqu 16($key),$xt3 # key[2] + movdqu ($counter),$xd3 # key[3] + lea 0x100(%rsp),%rcx # size optimization + lea .Lrot16(%rip),%r10 + lea .Lrot24(%rip),%r11 + + pshufd \$0x00,$xa3,$xa0 # smash key by lanes... + pshufd \$0x55,$xa3,$xa1 + movdqa $xa0,0x40(%rsp) # ... and offload + pshufd \$0xaa,$xa3,$xa2 + movdqa $xa1,0x50(%rsp) + pshufd \$0xff,$xa3,$xa3 + movdqa $xa2,0x60(%rsp) + movdqa $xa3,0x70(%rsp) + + pshufd \$0x00,$xb3,$xb0 + pshufd \$0x55,$xb3,$xb1 + movdqa $xb0,0x80-0x100(%rcx) + pshufd \$0xaa,$xb3,$xb2 + movdqa $xb1,0x90-0x100(%rcx) + pshufd \$0xff,$xb3,$xb3 + movdqa $xb2,0xa0-0x100(%rcx) + movdqa $xb3,0xb0-0x100(%rcx) + + pshufd \$0x00,$xt3,$xt0 # "$xc0" + pshufd \$0x55,$xt3,$xt1 # "$xc1" + movdqa $xt0,0xc0-0x100(%rcx) + pshufd \$0xaa,$xt3,$xt2 # "$xc2" + movdqa $xt1,0xd0-0x100(%rcx) + pshufd \$0xff,$xt3,$xt3 # "$xc3" + movdqa $xt2,0xe0-0x100(%rcx) + movdqa $xt3,0xf0-0x100(%rcx) + + pshufd \$0x00,$xd3,$xd0 + pshufd \$0x55,$xd3,$xd1 + paddd .Linc(%rip),$xd0 # don't save counters yet + pshufd \$0xaa,$xd3,$xd2 + movdqa $xd1,0x110-0x100(%rcx) + pshufd \$0xff,$xd3,$xd3 + movdqa $xd2,0x120-0x100(%rcx) + movdqa $xd3,0x130-0x100(%rcx) + + jmp .Loop_enter4x + +.align 32 +.Loop_outer4x: + movdqa 0x40(%rsp),$xa0 # re-load smashed key + movdqa 0x50(%rsp),$xa1 + movdqa 0x60(%rsp),$xa2 + movdqa 0x70(%rsp),$xa3 + movdqa 0x80-0x100(%rcx),$xb0 + movdqa 0x90-0x100(%rcx),$xb1 + movdqa 0xa0-0x100(%rcx),$xb2 + movdqa 0xb0-0x100(%rcx),$xb3 + movdqa 0xc0-0x100(%rcx),$xt0 # "$xc0" + movdqa 0xd0-0x100(%rcx),$xt1 # "$xc1" + movdqa 0xe0-0x100(%rcx),$xt2 # "$xc2" + movdqa 0xf0-0x100(%rcx),$xt3 # "$xc3" + movdqa 0x100-0x100(%rcx),$xd0 + movdqa 0x110-0x100(%rcx),$xd1 + movdqa 0x120-0x100(%rcx),$xd2 + movdqa 0x130-0x100(%rcx),$xd3 + paddd .Lfour(%rip),$xd0 # next SIMD counters + +.Loop_enter4x: + movdqa $xt2,0x20(%rsp) # SIMD equivalent of "@x[10]" + movdqa $xt3,0x30(%rsp) # SIMD equivalent of "@x[11]" + movdqa (%r10),$xt3 # .Lrot16(%rip) + mov \$10,%eax + movdqa $xd0,0x100-0x100(%rcx) # save SIMD counters + jmp .Loop4x + +.align 32 +.Loop4x: +___ + foreach (&SSSE3_lane_ROUND(0, 4, 8,12)) { eval; } + foreach (&SSSE3_lane_ROUND(0, 5,10,15)) { eval; } +$code.=<<___; + dec %eax + jnz .Loop4x + + paddd 0x40(%rsp),$xa0 # accumulate key material + paddd 0x50(%rsp),$xa1 + paddd 0x60(%rsp),$xa2 + paddd 0x70(%rsp),$xa3 + + movdqa $xa0,$xt2 # "de-interlace" data + punpckldq $xa1,$xa0 + movdqa $xa2,$xt3 + punpckldq $xa3,$xa2 + punpckhdq $xa1,$xt2 + punpckhdq $xa3,$xt3 + movdqa $xa0,$xa1 + punpcklqdq $xa2,$xa0 # "a0" + movdqa $xt2,$xa3 + punpcklqdq $xt3,$xt2 # "a2" + punpckhqdq $xa2,$xa1 # "a1" + punpckhqdq $xt3,$xa3 # "a3" +___ + ($xa2,$xt2)=($xt2,$xa2); +$code.=<<___; + paddd 0x80-0x100(%rcx),$xb0 + paddd 0x90-0x100(%rcx),$xb1 + paddd 0xa0-0x100(%rcx),$xb2 + paddd 0xb0-0x100(%rcx),$xb3 + + movdqa $xa0,0x00(%rsp) # offload $xaN + movdqa $xa1,0x10(%rsp) + movdqa 0x20(%rsp),$xa0 # "xc2" + movdqa 0x30(%rsp),$xa1 # "xc3" + + movdqa $xb0,$xt2 + punpckldq $xb1,$xb0 + movdqa $xb2,$xt3 + punpckldq $xb3,$xb2 + punpckhdq $xb1,$xt2 + punpckhdq $xb3,$xt3 + movdqa $xb0,$xb1 + punpcklqdq $xb2,$xb0 # "b0" + movdqa $xt2,$xb3 + punpcklqdq $xt3,$xt2 # "b2" + punpckhqdq $xb2,$xb1 # "b1" + punpckhqdq $xt3,$xb3 # "b3" +___ + ($xb2,$xt2)=($xt2,$xb2); + my ($xc0,$xc1,$xc2,$xc3)=($xt0,$xt1,$xa0,$xa1); +$code.=<<___; + paddd 0xc0-0x100(%rcx),$xc0 + paddd 0xd0-0x100(%rcx),$xc1 + paddd 0xe0-0x100(%rcx),$xc2 + paddd 0xf0-0x100(%rcx),$xc3 + + movdqa $xa2,0x20(%rsp) # keep offloading $xaN + movdqa $xa3,0x30(%rsp) + + movdqa $xc0,$xt2 + punpckldq $xc1,$xc0 + movdqa $xc2,$xt3 + punpckldq $xc3,$xc2 + punpckhdq $xc1,$xt2 + punpckhdq $xc3,$xt3 + movdqa $xc0,$xc1 + punpcklqdq $xc2,$xc0 # "c0" + movdqa $xt2,$xc3 + punpcklqdq $xt3,$xt2 # "c2" + punpckhqdq $xc2,$xc1 # "c1" + punpckhqdq $xt3,$xc3 # "c3" +___ + ($xc2,$xt2)=($xt2,$xc2); + ($xt0,$xt1)=($xa2,$xa3); # use $xaN as temporary +$code.=<<___; + paddd 0x100-0x100(%rcx),$xd0 + paddd 0x110-0x100(%rcx),$xd1 + paddd 0x120-0x100(%rcx),$xd2 + paddd 0x130-0x100(%rcx),$xd3 + + movdqa $xd0,$xt2 + punpckldq $xd1,$xd0 + movdqa $xd2,$xt3 + punpckldq $xd3,$xd2 + punpckhdq $xd1,$xt2 + punpckhdq $xd3,$xt3 + movdqa $xd0,$xd1 + punpcklqdq $xd2,$xd0 # "d0" + movdqa $xt2,$xd3 + punpcklqdq $xt3,$xt2 # "d2" + punpckhqdq $xd2,$xd1 # "d1" + punpckhqdq $xt3,$xd3 # "d3" +___ + ($xd2,$xt2)=($xt2,$xd2); +$code.=<<___; + cmp \$64*4,$len + jb .Ltail4x + + movdqu 0x00($inp),$xt0 # xor with input + movdqu 0x10($inp),$xt1 + movdqu 0x20($inp),$xt2 + movdqu 0x30($inp),$xt3 + pxor 0x00(%rsp),$xt0 # $xaN is offloaded, remember? + pxor $xb0,$xt1 + pxor $xc0,$xt2 + pxor $xd0,$xt3 + + movdqu $xt0,0x00($out) + movdqu 0x40($inp),$xt0 + movdqu $xt1,0x10($out) + movdqu 0x50($inp),$xt1 + movdqu $xt2,0x20($out) + movdqu 0x60($inp),$xt2 + movdqu $xt3,0x30($out) + movdqu 0x70($inp),$xt3 + lea 0x80($inp),$inp # size optimization + pxor 0x10(%rsp),$xt0 + pxor $xb1,$xt1 + pxor $xc1,$xt2 + pxor $xd1,$xt3 + + movdqu $xt0,0x40($out) + movdqu 0x00($inp),$xt0 + movdqu $xt1,0x50($out) + movdqu 0x10($inp),$xt1 + movdqu $xt2,0x60($out) + movdqu 0x20($inp),$xt2 + movdqu $xt3,0x70($out) + lea 0x80($out),$out # size optimization + movdqu 0x30($inp),$xt3 + pxor 0x20(%rsp),$xt0 + pxor $xb2,$xt1 + pxor $xc2,$xt2 + pxor $xd2,$xt3 + + movdqu $xt0,0x00($out) + movdqu 0x40($inp),$xt0 + movdqu $xt1,0x10($out) + movdqu 0x50($inp),$xt1 + movdqu $xt2,0x20($out) + movdqu 0x60($inp),$xt2 + movdqu $xt3,0x30($out) + movdqu 0x70($inp),$xt3 + lea 0x80($inp),$inp # inp+=64*4 + pxor 0x30(%rsp),$xt0 + pxor $xb3,$xt1 + pxor $xc3,$xt2 + pxor $xd3,$xt3 + movdqu $xt0,0x40($out) + movdqu $xt1,0x50($out) + movdqu $xt2,0x60($out) + movdqu $xt3,0x70($out) + lea 0x80($out),$out # out+=64*4 + + sub \$64*4,$len + jnz .Loop_outer4x + + jmp .Ldone4x + +.Ltail4x: + cmp \$192,$len + jae .L192_or_more4x + cmp \$128,$len + jae .L128_or_more4x + cmp \$64,$len + jae .L64_or_more4x + + #movdqa 0x00(%rsp),$xt0 # $xaN is offloaded, remember? + xor %r10,%r10 + #movdqa $xt0,0x00(%rsp) + movdqa $xb0,0x10(%rsp) + movdqa $xc0,0x20(%rsp) + movdqa $xd0,0x30(%rsp) + jmp .Loop_tail4x + +.align 32 +.L64_or_more4x: + movdqu 0x00($inp),$xt0 # xor with input + movdqu 0x10($inp),$xt1 + movdqu 0x20($inp),$xt2 + movdqu 0x30($inp),$xt3 + pxor 0x00(%rsp),$xt0 # $xaxN is offloaded, remember? + pxor $xb0,$xt1 + pxor $xc0,$xt2 + pxor $xd0,$xt3 + movdqu $xt0,0x00($out) + movdqu $xt1,0x10($out) + movdqu $xt2,0x20($out) + movdqu $xt3,0x30($out) + je .Ldone4x + + movdqa 0x10(%rsp),$xt0 # $xaN is offloaded, remember? + lea 0x40($inp),$inp # inp+=64*1 + xor %r10,%r10 + movdqa $xt0,0x00(%rsp) + movdqa $xb1,0x10(%rsp) + lea 0x40($out),$out # out+=64*1 + movdqa $xc1,0x20(%rsp) + sub \$64,$len # len-=64*1 + movdqa $xd1,0x30(%rsp) + jmp .Loop_tail4x + +.align 32 +.L128_or_more4x: + movdqu 0x00($inp),$xt0 # xor with input + movdqu 0x10($inp),$xt1 + movdqu 0x20($inp),$xt2 + movdqu 0x30($inp),$xt3 + pxor 0x00(%rsp),$xt0 # $xaN is offloaded, remember? + pxor $xb0,$xt1 + pxor $xc0,$xt2 + pxor $xd0,$xt3 + + movdqu $xt0,0x00($out) + movdqu 0x40($inp),$xt0 + movdqu $xt1,0x10($out) + movdqu 0x50($inp),$xt1 + movdqu $xt2,0x20($out) + movdqu 0x60($inp),$xt2 + movdqu $xt3,0x30($out) + movdqu 0x70($inp),$xt3 + pxor 0x10(%rsp),$xt0 + pxor $xb1,$xt1 + pxor $xc1,$xt2 + pxor $xd1,$xt3 + movdqu $xt0,0x40($out) + movdqu $xt1,0x50($out) + movdqu $xt2,0x60($out) + movdqu $xt3,0x70($out) + je .Ldone4x + + movdqa 0x20(%rsp),$xt0 # $xaN is offloaded, remember? + lea 0x80($inp),$inp # inp+=64*2 + xor %r10,%r10 + movdqa $xt0,0x00(%rsp) + movdqa $xb2,0x10(%rsp) + lea 0x80($out),$out # out+=64*2 + movdqa $xc2,0x20(%rsp) + sub \$128,$len # len-=64*2 + movdqa $xd2,0x30(%rsp) + jmp .Loop_tail4x + +.align 32 +.L192_or_more4x: + movdqu 0x00($inp),$xt0 # xor with input + movdqu 0x10($inp),$xt1 + movdqu 0x20($inp),$xt2 + movdqu 0x30($inp),$xt3 + pxor 0x00(%rsp),$xt0 # $xaN is offloaded, remember? + pxor $xb0,$xt1 + pxor $xc0,$xt2 + pxor $xd0,$xt3 + + movdqu $xt0,0x00($out) + movdqu 0x40($inp),$xt0 + movdqu $xt1,0x10($out) + movdqu 0x50($inp),$xt1 + movdqu $xt2,0x20($out) + movdqu 0x60($inp),$xt2 + movdqu $xt3,0x30($out) + movdqu 0x70($inp),$xt3 + lea 0x80($inp),$inp # size optimization + pxor 0x10(%rsp),$xt0 + pxor $xb1,$xt1 + pxor $xc1,$xt2 + pxor $xd1,$xt3 + + movdqu $xt0,0x40($out) + movdqu 0x00($inp),$xt0 + movdqu $xt1,0x50($out) + movdqu 0x10($inp),$xt1 + movdqu $xt2,0x60($out) + movdqu 0x20($inp),$xt2 + movdqu $xt3,0x70($out) + lea 0x80($out),$out # size optimization + movdqu 0x30($inp),$xt3 + pxor 0x20(%rsp),$xt0 + pxor $xb2,$xt1 + pxor $xc2,$xt2 + pxor $xd2,$xt3 + movdqu $xt0,0x00($out) + movdqu $xt1,0x10($out) + movdqu $xt2,0x20($out) + movdqu $xt3,0x30($out) + je .Ldone4x + + movdqa 0x30(%rsp),$xt0 # $xaN is offloaded, remember? + lea 0x40($inp),$inp # inp+=64*3 + xor %r10,%r10 + movdqa $xt0,0x00(%rsp) + movdqa $xb3,0x10(%rsp) + lea 0x40($out),$out # out+=64*3 + movdqa $xc3,0x20(%rsp) + sub \$192,$len # len-=64*3 + movdqa $xd3,0x30(%rsp) + +.Loop_tail4x: + movzb ($inp,%r10),%eax + movzb (%rsp,%r10),%ecx + lea 1(%r10),%r10 + xor %ecx,%eax + mov %al,-1($out,%r10) + dec $len + jnz .Loop_tail4x + +.Ldone4x: +___ +$code.=<<___ if ($win64); + lea 0x140+0x30(%rsp),%r11 + movaps -0x30(%r11),%xmm6 + movaps -0x20(%r11),%xmm7 + movaps -0x10(%r11),%xmm8 + movaps 0x00(%r11),%xmm9 + movaps 0x10(%r11),%xmm10 + movaps 0x20(%r11),%xmm11 + movaps 0x30(%r11),%xmm12 + movaps 0x40(%r11),%xmm13 + movaps 0x50(%r11),%xmm14 + movaps 0x60(%r11),%xmm15 +___ +$code.=<<___; + add \$0x148+$xframe,%rsp + ret +.size ChaCha20_4x,.-ChaCha20_4x +___ +} + +######################################################################## +# AVX2 code path +if ($avx>1) { +my ($xb0,$xb1,$xb2,$xb3, $xd0,$xd1,$xd2,$xd3, + $xa0,$xa1,$xa2,$xa3, $xt0,$xt1,$xt2,$xt3)=map("%ymm$_",(0..15)); +my @xx=($xa0,$xa1,$xa2,$xa3, $xb0,$xb1,$xb2,$xb3, + "%nox","%nox","%nox","%nox", $xd0,$xd1,$xd2,$xd3); + +sub AVX2_lane_ROUND { +my ($a0,$b0,$c0,$d0)=@_; +my ($a1,$b1,$c1,$d1)=map(($_&~3)+(($_+1)&3),($a0,$b0,$c0,$d0)); +my ($a2,$b2,$c2,$d2)=map(($_&~3)+(($_+1)&3),($a1,$b1,$c1,$d1)); +my ($a3,$b3,$c3,$d3)=map(($_&~3)+(($_+1)&3),($a2,$b2,$c2,$d2)); +my ($xc,$xc_,$t0,$t1)=map("\"$_\"",$xt0,$xt1,$xt2,$xt3); +my @x=map("\"$_\"",@xx); + + # Consider order in which variables are addressed by their + # index: + # + # a b c d + # + # 0 4 8 12 < even round + # 1 5 9 13 + # 2 6 10 14 + # 3 7 11 15 + # 0 5 10 15 < odd round + # 1 6 11 12 + # 2 7 8 13 + # 3 4 9 14 + # + # 'a', 'b' and 'd's are permanently allocated in registers, + # @x[0..7,12..15], while 'c's are maintained in memory. If + # you observe 'c' column, you'll notice that pair of 'c's is + # invariant between rounds. This means that we have to reload + # them once per round, in the middle. This is why you'll see + # bunch of 'c' stores and loads in the middle, but none in + # the beginning or end. + + ( + "&vpaddd (@x[$a0],@x[$a0],@x[$b0])", # Q1 + "&vpxor (@x[$d0],@x[$a0],@x[$d0])", + "&vpshufb (@x[$d0],@x[$d0],$t1)", + "&vpaddd (@x[$a1],@x[$a1],@x[$b1])", # Q2 + "&vpxor (@x[$d1],@x[$a1],@x[$d1])", + "&vpshufb (@x[$d1],@x[$d1],$t1)", + + "&vpaddd ($xc,$xc,@x[$d0])", + "&vpxor (@x[$b0],$xc,@x[$b0])", + "&vpslld ($t0,@x[$b0],12)", + "&vpsrld (@x[$b0],@x[$b0],20)", + "&vpor (@x[$b0],$t0,@x[$b0])", + "&vbroadcasti128($t0,'(%r11)')", # .Lrot24(%rip) + "&vpaddd ($xc_,$xc_,@x[$d1])", + "&vpxor (@x[$b1],$xc_,@x[$b1])", + "&vpslld ($t1,@x[$b1],12)", + "&vpsrld (@x[$b1],@x[$b1],20)", + "&vpor (@x[$b1],$t1,@x[$b1])", + + "&vpaddd (@x[$a0],@x[$a0],@x[$b0])", + "&vpxor (@x[$d0],@x[$a0],@x[$d0])", + "&vpshufb (@x[$d0],@x[$d0],$t0)", + "&vpaddd (@x[$a1],@x[$a1],@x[$b1])", + "&vpxor (@x[$d1],@x[$a1],@x[$d1])", + "&vpshufb (@x[$d1],@x[$d1],$t0)", + + "&vpaddd ($xc,$xc,@x[$d0])", + "&vpxor (@x[$b0],$xc,@x[$b0])", + "&vpslld ($t1,@x[$b0],7)", + "&vpsrld (@x[$b0],@x[$b0],25)", + "&vpor (@x[$b0],$t1,@x[$b0])", + "&vbroadcasti128($t1,'(%r10)')", # .Lrot16(%rip) + "&vpaddd ($xc_,$xc_,@x[$d1])", + "&vpxor (@x[$b1],$xc_,@x[$b1])", + "&vpslld ($t0,@x[$b1],7)", + "&vpsrld (@x[$b1],@x[$b1],25)", + "&vpor (@x[$b1],$t0,@x[$b1])", + + "&vmovdqa (\"`32*($c0-8)`(%rsp)\",$xc)", # reload pair of 'c's + "&vmovdqa (\"`32*($c1-8)`(%rsp)\",$xc_)", + "&vmovdqa ($xc,\"`32*($c2-8)`(%rsp)\")", + "&vmovdqa ($xc_,\"`32*($c3-8)`(%rsp)\")", + + "&vpaddd (@x[$a2],@x[$a2],@x[$b2])", # Q3 + "&vpxor (@x[$d2],@x[$a2],@x[$d2])", + "&vpshufb (@x[$d2],@x[$d2],$t1)", + "&vpaddd (@x[$a3],@x[$a3],@x[$b3])", # Q4 + "&vpxor (@x[$d3],@x[$a3],@x[$d3])", + "&vpshufb (@x[$d3],@x[$d3],$t1)", + + "&vpaddd ($xc,$xc,@x[$d2])", + "&vpxor (@x[$b2],$xc,@x[$b2])", + "&vpslld ($t0,@x[$b2],12)", + "&vpsrld (@x[$b2],@x[$b2],20)", + "&vpor (@x[$b2],$t0,@x[$b2])", + "&vbroadcasti128($t0,'(%r11)')", # .Lrot24(%rip) + "&vpaddd ($xc_,$xc_,@x[$d3])", + "&vpxor (@x[$b3],$xc_,@x[$b3])", + "&vpslld ($t1,@x[$b3],12)", + "&vpsrld (@x[$b3],@x[$b3],20)", + "&vpor (@x[$b3],$t1,@x[$b3])", + + "&vpaddd (@x[$a2],@x[$a2],@x[$b2])", + "&vpxor (@x[$d2],@x[$a2],@x[$d2])", + "&vpshufb (@x[$d2],@x[$d2],$t0)", + "&vpaddd (@x[$a3],@x[$a3],@x[$b3])", + "&vpxor (@x[$d3],@x[$a3],@x[$d3])", + "&vpshufb (@x[$d3],@x[$d3],$t0)", + + "&vpaddd ($xc,$xc,@x[$d2])", + "&vpxor (@x[$b2],$xc,@x[$b2])", + "&vpslld ($t1,@x[$b2],7)", + "&vpsrld (@x[$b2],@x[$b2],25)", + "&vpor (@x[$b2],$t1,@x[$b2])", + "&vbroadcasti128($t1,'(%r10)')", # .Lrot16(%rip) + "&vpaddd ($xc_,$xc_,@x[$d3])", + "&vpxor (@x[$b3],$xc_,@x[$b3])", + "&vpslld ($t0,@x[$b3],7)", + "&vpsrld (@x[$b3],@x[$b3],25)", + "&vpor (@x[$b3],$t0,@x[$b3])" + ); +} + +my $xframe = $win64 ? 0xb0 : 8; + +$code.=<<___; +.type ChaCha20_8x,\@function,5 +.align 32 +ChaCha20_8x: +.LChaCha20_8x: + mov %rsp,%r10 + sub \$0x280+$xframe,%rsp + and \$-32,%rsp +___ +$code.=<<___ if ($win64); + lea 0x290+0x30(%rsp),%r11 + movaps %xmm6,-0x30(%r11) + movaps %xmm7,-0x20(%r11) + movaps %xmm8,-0x10(%r11) + movaps %xmm9,0x00(%r11) + movaps %xmm10,0x10(%r11) + movaps %xmm11,0x20(%r11) + movaps %xmm12,0x30(%r11) + movaps %xmm13,0x40(%r11) + movaps %xmm14,0x50(%r11) + movaps %xmm15,0x60(%r11) +___ +$code.=<<___; + vzeroupper + mov %r10,0x280(%rsp) + + ################ stack layout + # +0x00 SIMD equivalent of @x[8-12] + # ... + # +0x80 constant copy of key[0-2] smashed by lanes + # ... + # +0x200 SIMD counters (with nonce smashed by lanes) + # ... + # +0x280 saved %rsp + + vbroadcasti128 .Lsigma(%rip),$xa3 # key[0] + vbroadcasti128 ($key),$xb3 # key[1] + vbroadcasti128 16($key),$xt3 # key[2] + vbroadcasti128 ($counter),$xd3 # key[3] + lea 0x100(%rsp),%rcx # size optimization + lea 0x200(%rsp),%rax # size optimization + lea .Lrot16(%rip),%r10 + lea .Lrot24(%rip),%r11 + + vpshufd \$0x00,$xa3,$xa0 # smash key by lanes... + vpshufd \$0x55,$xa3,$xa1 + vmovdqa $xa0,0x80-0x100(%rcx) # ... and offload + vpshufd \$0xaa,$xa3,$xa2 + vmovdqa $xa1,0xa0-0x100(%rcx) + vpshufd \$0xff,$xa3,$xa3 + vmovdqa $xa2,0xc0-0x100(%rcx) + vmovdqa $xa3,0xe0-0x100(%rcx) + + vpshufd \$0x00,$xb3,$xb0 + vpshufd \$0x55,$xb3,$xb1 + vmovdqa $xb0,0x100-0x100(%rcx) + vpshufd \$0xaa,$xb3,$xb2 + vmovdqa $xb1,0x120-0x100(%rcx) + vpshufd \$0xff,$xb3,$xb3 + vmovdqa $xb2,0x140-0x100(%rcx) + vmovdqa $xb3,0x160-0x100(%rcx) + + vpshufd \$0x00,$xt3,$xt0 # "xc0" + vpshufd \$0x55,$xt3,$xt1 # "xc1" + vmovdqa $xt0,0x180-0x200(%rax) + vpshufd \$0xaa,$xt3,$xt2 # "xc2" + vmovdqa $xt1,0x1a0-0x200(%rax) + vpshufd \$0xff,$xt3,$xt3 # "xc3" + vmovdqa $xt2,0x1c0-0x200(%rax) + vmovdqa $xt3,0x1e0-0x200(%rax) + + vpshufd \$0x00,$xd3,$xd0 + vpshufd \$0x55,$xd3,$xd1 + vpaddd .Lincy(%rip),$xd0,$xd0 # don't save counters yet + vpshufd \$0xaa,$xd3,$xd2 + vmovdqa $xd1,0x220-0x200(%rax) + vpshufd \$0xff,$xd3,$xd3 + vmovdqa $xd2,0x240-0x200(%rax) + vmovdqa $xd3,0x260-0x200(%rax) + + jmp .Loop_enter8x + +.align 32 +.Loop_outer8x: + vmovdqa 0x80-0x100(%rcx),$xa0 # re-load smashed key + vmovdqa 0xa0-0x100(%rcx),$xa1 + vmovdqa 0xc0-0x100(%rcx),$xa2 + vmovdqa 0xe0-0x100(%rcx),$xa3 + vmovdqa 0x100-0x100(%rcx),$xb0 + vmovdqa 0x120-0x100(%rcx),$xb1 + vmovdqa 0x140-0x100(%rcx),$xb2 + vmovdqa 0x160-0x100(%rcx),$xb3 + vmovdqa 0x180-0x200(%rax),$xt0 # "xc0" + vmovdqa 0x1a0-0x200(%rax),$xt1 # "xc1" + vmovdqa 0x1c0-0x200(%rax),$xt2 # "xc2" + vmovdqa 0x1e0-0x200(%rax),$xt3 # "xc3" + vmovdqa 0x200-0x200(%rax),$xd0 + vmovdqa 0x220-0x200(%rax),$xd1 + vmovdqa 0x240-0x200(%rax),$xd2 + vmovdqa 0x260-0x200(%rax),$xd3 + vpaddd .Leight(%rip),$xd0,$xd0 # next SIMD counters + +.Loop_enter8x: + vmovdqa $xt2,0x40(%rsp) # SIMD equivalent of "@x[10]" + vmovdqa $xt3,0x60(%rsp) # SIMD equivalent of "@x[11]" + vbroadcasti128 (%r10),$xt3 + vmovdqa $xd0,0x200-0x200(%rax) # save SIMD counters + mov \$10,%eax + jmp .Loop8x + +.align 32 +.Loop8x: +___ + foreach (&AVX2_lane_ROUND(0, 4, 8,12)) { eval; } + foreach (&AVX2_lane_ROUND(0, 5,10,15)) { eval; } +$code.=<<___; + dec %eax + jnz .Loop8x + + lea 0x200(%rsp),%rax # size optimization + vpaddd 0x80-0x100(%rcx),$xa0,$xa0 # accumulate key + vpaddd 0xa0-0x100(%rcx),$xa1,$xa1 + vpaddd 0xc0-0x100(%rcx),$xa2,$xa2 + vpaddd 0xe0-0x100(%rcx),$xa3,$xa3 + + vpunpckldq $xa1,$xa0,$xt2 # "de-interlace" data + vpunpckldq $xa3,$xa2,$xt3 + vpunpckhdq $xa1,$xa0,$xa0 + vpunpckhdq $xa3,$xa2,$xa2 + vpunpcklqdq $xt3,$xt2,$xa1 # "a0" + vpunpckhqdq $xt3,$xt2,$xt2 # "a1" + vpunpcklqdq $xa2,$xa0,$xa3 # "a2" + vpunpckhqdq $xa2,$xa0,$xa0 # "a3" +___ + ($xa0,$xa1,$xa2,$xa3,$xt2)=($xa1,$xt2,$xa3,$xa0,$xa2); +$code.=<<___; + vpaddd 0x100-0x100(%rcx),$xb0,$xb0 + vpaddd 0x120-0x100(%rcx),$xb1,$xb1 + vpaddd 0x140-0x100(%rcx),$xb2,$xb2 + vpaddd 0x160-0x100(%rcx),$xb3,$xb3 + + vpunpckldq $xb1,$xb0,$xt2 + vpunpckldq $xb3,$xb2,$xt3 + vpunpckhdq $xb1,$xb0,$xb0 + vpunpckhdq $xb3,$xb2,$xb2 + vpunpcklqdq $xt3,$xt2,$xb1 # "b0" + vpunpckhqdq $xt3,$xt2,$xt2 # "b1" + vpunpcklqdq $xb2,$xb0,$xb3 # "b2" + vpunpckhqdq $xb2,$xb0,$xb0 # "b3" +___ + ($xb0,$xb1,$xb2,$xb3,$xt2)=($xb1,$xt2,$xb3,$xb0,$xb2); +$code.=<<___; + vperm2i128 \$0x20,$xb0,$xa0,$xt3 # "de-interlace" further + vperm2i128 \$0x31,$xb0,$xa0,$xb0 + vperm2i128 \$0x20,$xb1,$xa1,$xa0 + vperm2i128 \$0x31,$xb1,$xa1,$xb1 + vperm2i128 \$0x20,$xb2,$xa2,$xa1 + vperm2i128 \$0x31,$xb2,$xa2,$xb2 + vperm2i128 \$0x20,$xb3,$xa3,$xa2 + vperm2i128 \$0x31,$xb3,$xa3,$xb3 +___ + ($xa0,$xa1,$xa2,$xa3,$xt3)=($xt3,$xa0,$xa1,$xa2,$xa3); + my ($xc0,$xc1,$xc2,$xc3)=($xt0,$xt1,$xa0,$xa1); +$code.=<<___; + vmovdqa $xa0,0x00(%rsp) # offload $xaN + vmovdqa $xa1,0x20(%rsp) + vmovdqa 0x40(%rsp),$xc2 # $xa0 + vmovdqa 0x60(%rsp),$xc3 # $xa1 + + vpaddd 0x180-0x200(%rax),$xc0,$xc0 + vpaddd 0x1a0-0x200(%rax),$xc1,$xc1 + vpaddd 0x1c0-0x200(%rax),$xc2,$xc2 + vpaddd 0x1e0-0x200(%rax),$xc3,$xc3 + + vpunpckldq $xc1,$xc0,$xt2 + vpunpckldq $xc3,$xc2,$xt3 + vpunpckhdq $xc1,$xc0,$xc0 + vpunpckhdq $xc3,$xc2,$xc2 + vpunpcklqdq $xt3,$xt2,$xc1 # "c0" + vpunpckhqdq $xt3,$xt2,$xt2 # "c1" + vpunpcklqdq $xc2,$xc0,$xc3 # "c2" + vpunpckhqdq $xc2,$xc0,$xc0 # "c3" +___ + ($xc0,$xc1,$xc2,$xc3,$xt2)=($xc1,$xt2,$xc3,$xc0,$xc2); +$code.=<<___; + vpaddd 0x200-0x200(%rax),$xd0,$xd0 + vpaddd 0x220-0x200(%rax),$xd1,$xd1 + vpaddd 0x240-0x200(%rax),$xd2,$xd2 + vpaddd 0x260-0x200(%rax),$xd3,$xd3 + + vpunpckldq $xd1,$xd0,$xt2 + vpunpckldq $xd3,$xd2,$xt3 + vpunpckhdq $xd1,$xd0,$xd0 + vpunpckhdq $xd3,$xd2,$xd2 + vpunpcklqdq $xt3,$xt2,$xd1 # "d0" + vpunpckhqdq $xt3,$xt2,$xt2 # "d1" + vpunpcklqdq $xd2,$xd0,$xd3 # "d2" + vpunpckhqdq $xd2,$xd0,$xd0 # "d3" +___ + ($xd0,$xd1,$xd2,$xd3,$xt2)=($xd1,$xt2,$xd3,$xd0,$xd2); +$code.=<<___; + vperm2i128 \$0x20,$xd0,$xc0,$xt3 # "de-interlace" further + vperm2i128 \$0x31,$xd0,$xc0,$xd0 + vperm2i128 \$0x20,$xd1,$xc1,$xc0 + vperm2i128 \$0x31,$xd1,$xc1,$xd1 + vperm2i128 \$0x20,$xd2,$xc2,$xc1 + vperm2i128 \$0x31,$xd2,$xc2,$xd2 + vperm2i128 \$0x20,$xd3,$xc3,$xc2 + vperm2i128 \$0x31,$xd3,$xc3,$xd3 +___ + ($xc0,$xc1,$xc2,$xc3,$xt3)=($xt3,$xc0,$xc1,$xc2,$xc3); + ($xb0,$xb1,$xb2,$xb3,$xc0,$xc1,$xc2,$xc3)= + ($xc0,$xc1,$xc2,$xc3,$xb0,$xb1,$xb2,$xb3); + ($xa0,$xa1)=($xt2,$xt3); +$code.=<<___; + vmovdqa 0x00(%rsp),$xa0 # $xaN was offloaded, remember? + vmovdqa 0x20(%rsp),$xa1 + + cmp \$64*8,$len + jb .Ltail8x + + vpxor 0x00($inp),$xa0,$xa0 # xor with input + vpxor 0x20($inp),$xb0,$xb0 + vpxor 0x40($inp),$xc0,$xc0 + vpxor 0x60($inp),$xd0,$xd0 + lea 0x80($inp),$inp # size optimization + vmovdqu $xa0,0x00($out) + vmovdqu $xb0,0x20($out) + vmovdqu $xc0,0x40($out) + vmovdqu $xd0,0x60($out) + lea 0x80($out),$out # size optimization + + vpxor 0x00($inp),$xa1,$xa1 + vpxor 0x20($inp),$xb1,$xb1 + vpxor 0x40($inp),$xc1,$xc1 + vpxor 0x60($inp),$xd1,$xd1 + lea 0x80($inp),$inp # size optimization + vmovdqu $xa1,0x00($out) + vmovdqu $xb1,0x20($out) + vmovdqu $xc1,0x40($out) + vmovdqu $xd1,0x60($out) + lea 0x80($out),$out # size optimization + + vpxor 0x00($inp),$xa2,$xa2 + vpxor 0x20($inp),$xb2,$xb2 + vpxor 0x40($inp),$xc2,$xc2 + vpxor 0x60($inp),$xd2,$xd2 + lea 0x80($inp),$inp # size optimization + vmovdqu $xa2,0x00($out) + vmovdqu $xb2,0x20($out) + vmovdqu $xc2,0x40($out) + vmovdqu $xd2,0x60($out) + lea 0x80($out),$out # size optimization + + vpxor 0x00($inp),$xa3,$xa3 + vpxor 0x20($inp),$xb3,$xb3 + vpxor 0x40($inp),$xc3,$xc3 + vpxor 0x60($inp),$xd3,$xd3 + lea 0x80($inp),$inp # size optimization + vmovdqu $xa3,0x00($out) + vmovdqu $xb3,0x20($out) + vmovdqu $xc3,0x40($out) + vmovdqu $xd3,0x60($out) + lea 0x80($out),$out # size optimization + + sub \$64*8,$len + jnz .Loop_outer8x + + jmp .Ldone8x + +.Ltail8x: + cmp \$448,$len + jae .L448_or_more8x + cmp \$384,$len + jae .L384_or_more8x + cmp \$320,$len + jae .L320_or_more8x + cmp \$256,$len + jae .L256_or_more8x + cmp \$192,$len + jae .L192_or_more8x + cmp \$128,$len + jae .L128_or_more8x + cmp \$64,$len + jae .L64_or_more8x + + xor %r10,%r10 + vmovdqa $xa0,0x00(%rsp) + vmovdqa $xb0,0x20(%rsp) + jmp .Loop_tail8x + +.align 32 +.L64_or_more8x: + vpxor 0x00($inp),$xa0,$xa0 # xor with input + vpxor 0x20($inp),$xb0,$xb0 + vmovdqu $xa0,0x00($out) + vmovdqu $xb0,0x20($out) + je .Ldone8x + + lea 0x40($inp),$inp # inp+=64*1 + xor %r10,%r10 + vmovdqa $xc0,0x00(%rsp) + lea 0x40($out),$out # out+=64*1 + sub \$64,$len # len-=64*1 + vmovdqa $xd0,0x20(%rsp) + jmp .Loop_tail8x + +.align 32 +.L128_or_more8x: + vpxor 0x00($inp),$xa0,$xa0 # xor with input + vpxor 0x20($inp),$xb0,$xb0 + vpxor 0x40($inp),$xc0,$xc0 + vpxor 0x60($inp),$xd0,$xd0 + vmovdqu $xa0,0x00($out) + vmovdqu $xb0,0x20($out) + vmovdqu $xc0,0x40($out) + vmovdqu $xd0,0x60($out) + je .Ldone8x + + lea 0x80($inp),$inp # inp+=64*2 + xor %r10,%r10 + vmovdqa $xa1,0x00(%rsp) + lea 0x80($out),$out # out+=64*2 + sub \$128,$len # len-=64*2 + vmovdqa $xb1,0x20(%rsp) + jmp .Loop_tail8x + +.align 32 +.L192_or_more8x: + vpxor 0x00($inp),$xa0,$xa0 # xor with input + vpxor 0x20($inp),$xb0,$xb0 + vpxor 0x40($inp),$xc0,$xc0 + vpxor 0x60($inp),$xd0,$xd0 + vpxor 0x80($inp),$xa1,$xa1 + vpxor 0xa0($inp),$xb1,$xb1 + vmovdqu $xa0,0x00($out) + vmovdqu $xb0,0x20($out) + vmovdqu $xc0,0x40($out) + vmovdqu $xd0,0x60($out) + vmovdqu $xa1,0x80($out) + vmovdqu $xb1,0xa0($out) + je .Ldone8x + + lea 0xc0($inp),$inp # inp+=64*3 + xor %r10,%r10 + vmovdqa $xc1,0x00(%rsp) + lea 0xc0($out),$out # out+=64*3 + sub \$192,$len # len-=64*3 + vmovdqa $xd1,0x20(%rsp) + jmp .Loop_tail8x + +.align 32 +.L256_or_more8x: + vpxor 0x00($inp),$xa0,$xa0 # xor with input + vpxor 0x20($inp),$xb0,$xb0 + vpxor 0x40($inp),$xc0,$xc0 + vpxor 0x60($inp),$xd0,$xd0 + vpxor 0x80($inp),$xa1,$xa1 + vpxor 0xa0($inp),$xb1,$xb1 + vpxor 0xc0($inp),$xc1,$xc1 + vpxor 0xe0($inp),$xd1,$xd1 + vmovdqu $xa0,0x00($out) + vmovdqu $xb0,0x20($out) + vmovdqu $xc0,0x40($out) + vmovdqu $xd0,0x60($out) + vmovdqu $xa1,0x80($out) + vmovdqu $xb1,0xa0($out) + vmovdqu $xc1,0xc0($out) + vmovdqu $xd1,0xe0($out) + je .Ldone8x + + lea 0x100($inp),$inp # inp+=64*4 + xor %r10,%r10 + vmovdqa $xa2,0x00(%rsp) + lea 0x100($out),$out # out+=64*4 + sub \$256,$len # len-=64*4 + vmovdqa $xb2,0x20(%rsp) + jmp .Loop_tail8x + +.align 32 +.L320_or_more8x: + vpxor 0x00($inp),$xa0,$xa0 # xor with input + vpxor 0x20($inp),$xb0,$xb0 + vpxor 0x40($inp),$xc0,$xc0 + vpxor 0x60($inp),$xd0,$xd0 + vpxor 0x80($inp),$xa1,$xa1 + vpxor 0xa0($inp),$xb1,$xb1 + vpxor 0xc0($inp),$xc1,$xc1 + vpxor 0xe0($inp),$xd1,$xd1 + vpxor 0x100($inp),$xa2,$xa2 + vpxor 0x120($inp),$xb2,$xb2 + vmovdqu $xa0,0x00($out) + vmovdqu $xb0,0x20($out) + vmovdqu $xc0,0x40($out) + vmovdqu $xd0,0x60($out) + vmovdqu $xa1,0x80($out) + vmovdqu $xb1,0xa0($out) + vmovdqu $xc1,0xc0($out) + vmovdqu $xd1,0xe0($out) + vmovdqu $xa2,0x100($out) + vmovdqu $xb2,0x120($out) + je .Ldone8x + + lea 0x140($inp),$inp # inp+=64*5 + xor %r10,%r10 + vmovdqa $xc2,0x00(%rsp) + lea 0x140($out),$out # out+=64*5 + sub \$320,$len # len-=64*5 + vmovdqa $xd2,0x20(%rsp) + jmp .Loop_tail8x + +.align 32 +.L384_or_more8x: + vpxor 0x00($inp),$xa0,$xa0 # xor with input + vpxor 0x20($inp),$xb0,$xb0 + vpxor 0x40($inp),$xc0,$xc0 + vpxor 0x60($inp),$xd0,$xd0 + vpxor 0x80($inp),$xa1,$xa1 + vpxor 0xa0($inp),$xb1,$xb1 + vpxor 0xc0($inp),$xc1,$xc1 + vpxor 0xe0($inp),$xd1,$xd1 + vpxor 0x100($inp),$xa2,$xa2 + vpxor 0x120($inp),$xb2,$xb2 + vpxor 0x140($inp),$xc2,$xc2 + vpxor 0x160($inp),$xd2,$xd2 + vmovdqu $xa0,0x00($out) + vmovdqu $xb0,0x20($out) + vmovdqu $xc0,0x40($out) + vmovdqu $xd0,0x60($out) + vmovdqu $xa1,0x80($out) + vmovdqu $xb1,0xa0($out) + vmovdqu $xc1,0xc0($out) + vmovdqu $xd1,0xe0($out) + vmovdqu $xa2,0x100($out) + vmovdqu $xb2,0x120($out) + vmovdqu $xc2,0x140($out) + vmovdqu $xd2,0x160($out) + je .Ldone8x + + lea 0x180($inp),$inp # inp+=64*6 + xor %r10,%r10 + vmovdqa $xa3,0x00(%rsp) + lea 0x180($out),$out # out+=64*6 + sub \$384,$len # len-=64*6 + vmovdqa $xb3,0x20(%rsp) + jmp .Loop_tail8x + +.align 32 +.L448_or_more8x: + vpxor 0x00($inp),$xa0,$xa0 # xor with input + vpxor 0x20($inp),$xb0,$xb0 + vpxor 0x40($inp),$xc0,$xc0 + vpxor 0x60($inp),$xd0,$xd0 + vpxor 0x80($inp),$xa1,$xa1 + vpxor 0xa0($inp),$xb1,$xb1 + vpxor 0xc0($inp),$xc1,$xc1 + vpxor 0xe0($inp),$xd1,$xd1 + vpxor 0x100($inp),$xa2,$xa2 + vpxor 0x120($inp),$xb2,$xb2 + vpxor 0x140($inp),$xc2,$xc2 + vpxor 0x160($inp),$xd2,$xd2 + vpxor 0x180($inp),$xa3,$xa3 + vpxor 0x1a0($inp),$xb3,$xb3 + vmovdqu $xa0,0x00($out) + vmovdqu $xb0,0x20($out) + vmovdqu $xc0,0x40($out) + vmovdqu $xd0,0x60($out) + vmovdqu $xa1,0x80($out) + vmovdqu $xb1,0xa0($out) + vmovdqu $xc1,0xc0($out) + vmovdqu $xd1,0xe0($out) + vmovdqu $xa2,0x100($out) + vmovdqu $xb2,0x120($out) + vmovdqu $xc2,0x140($out) + vmovdqu $xd2,0x160($out) + vmovdqu $xa3,0x180($out) + vmovdqu $xb3,0x1a0($out) + je .Ldone8x + + lea 0x1c0($inp),$inp # inp+=64*7 + xor %r10,%r10 + vmovdqa $xc3,0x00(%rsp) + lea 0x1c0($out),$out # out+=64*7 + sub \$448,$len # len-=64*7 + vmovdqa $xd3,0x20(%rsp) + +.Loop_tail8x: + movzb ($inp,%r10),%eax + movzb (%rsp,%r10),%ecx + lea 1(%r10),%r10 + xor %ecx,%eax + mov %al,-1($out,%r10) + dec $len + jnz .Loop_tail8x + +.Ldone8x: + vzeroall +___ +$code.=<<___ if ($win64); + lea 0x290+0x30(%rsp),%r11 + movaps -0x30(%r11),%xmm6 + movaps -0x20(%r11),%xmm7 + movaps -0x10(%r11),%xmm8 + movaps 0x00(%r11),%xmm9 + movaps 0x10(%r11),%xmm10 + movaps 0x20(%r11),%xmm11 + movaps 0x30(%r11),%xmm12 + movaps 0x40(%r11),%xmm13 + movaps 0x50(%r11),%xmm14 + movaps 0x60(%r11),%xmm15 +___ +$code.=<<___; + mov 0x280(%rsp),%rsp + ret +.size ChaCha20_8x,.-ChaCha20_8x +___ +} + +foreach (split("\n",$code)) { + s/\`([^\`]*)\`/eval $1/geo; + + s/%x#%y/%x/go; + + print $_,"\n"; +} + +close STDOUT; diff --git a/external/boringssl/crypto/chacha/chacha.c b/external/boringssl/crypto/chacha/chacha.c new file mode 100644 index 0000000000..156208945c --- /dev/null +++ b/external/boringssl/crypto/chacha/chacha.c @@ -0,0 +1,170 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +/* Adapted from the public domain, estream code by D. Bernstein. */ + +#include + +#include +#include + +#include + +#include "../internal.h" + + +#define U8TO32_LITTLE(p) \ + (((uint32_t)((p)[0])) | ((uint32_t)((p)[1]) << 8) | \ + ((uint32_t)((p)[2]) << 16) | ((uint32_t)((p)[3]) << 24)) + +#if !defined(OPENSSL_NO_ASM) && \ + (defined(OPENSSL_X86) || defined(OPENSSL_X86_64) || \ + defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)) + +/* ChaCha20_ctr32 is defined in asm/chacha-*.pl. */ +void ChaCha20_ctr32(uint8_t *out, const uint8_t *in, size_t in_len, + const uint32_t key[8], const uint32_t counter[4]); + +void CRYPTO_chacha_20(uint8_t *out, const uint8_t *in, size_t in_len, + const uint8_t key[32], const uint8_t nonce[12], + uint32_t counter) { + assert(!buffers_alias(out, in_len, in, in_len) || in == out); + + uint32_t counter_nonce[4]; counter_nonce[0] = counter; + counter_nonce[1] = U8TO32_LITTLE(nonce + 0); + counter_nonce[2] = U8TO32_LITTLE(nonce + 4); + counter_nonce[3] = U8TO32_LITTLE(nonce + 8); + + const uint32_t *key_ptr = (const uint32_t *)key; +#if !defined(OPENSSL_X86) && !defined(OPENSSL_X86_64) + /* The assembly expects the key to be four-byte aligned. */ + uint32_t key_u32[8]; + if ((((uintptr_t)key) & 3) != 0) { + key_u32[0] = U8TO32_LITTLE(key + 0); + key_u32[1] = U8TO32_LITTLE(key + 4); + key_u32[2] = U8TO32_LITTLE(key + 8); + key_u32[3] = U8TO32_LITTLE(key + 12); + key_u32[4] = U8TO32_LITTLE(key + 16); + key_u32[5] = U8TO32_LITTLE(key + 20); + key_u32[6] = U8TO32_LITTLE(key + 24); + key_u32[7] = U8TO32_LITTLE(key + 28); + + key_ptr = key_u32; + } +#endif + + ChaCha20_ctr32(out, in, in_len, key_ptr, counter_nonce); +} + +#else + +/* sigma contains the ChaCha constants, which happen to be an ASCII string. */ +static const uint8_t sigma[16] = { 'e', 'x', 'p', 'a', 'n', 'd', ' ', '3', + '2', '-', 'b', 'y', 't', 'e', ' ', 'k' }; + +#define ROTATE(v, n) (((v) << (n)) | ((v) >> (32 - (n)))) +#define XOR(v, w) ((v) ^ (w)) +#define PLUS(x, y) ((x) + (y)) +#define PLUSONE(v) (PLUS((v), 1)) + +#define U32TO8_LITTLE(p, v) \ + { \ + (p)[0] = (v >> 0) & 0xff; \ + (p)[1] = (v >> 8) & 0xff; \ + (p)[2] = (v >> 16) & 0xff; \ + (p)[3] = (v >> 24) & 0xff; \ + } + +/* QUARTERROUND updates a, b, c, d with a ChaCha "quarter" round. */ +#define QUARTERROUND(a,b,c,d) \ + x[a] = PLUS(x[a],x[b]); x[d] = ROTATE(XOR(x[d],x[a]),16); \ + x[c] = PLUS(x[c],x[d]); x[b] = ROTATE(XOR(x[b],x[c]),12); \ + x[a] = PLUS(x[a],x[b]); x[d] = ROTATE(XOR(x[d],x[a]), 8); \ + x[c] = PLUS(x[c],x[d]); x[b] = ROTATE(XOR(x[b],x[c]), 7); + +/* chacha_core performs 20 rounds of ChaCha on the input words in + * |input| and writes the 64 output bytes to |output|. */ +static void chacha_core(uint8_t output[64], const uint32_t input[16]) { + uint32_t x[16]; + int i; + + memcpy(x, input, sizeof(uint32_t) * 16); + for (i = 20; i > 0; i -= 2) { + QUARTERROUND(0, 4, 8, 12) + QUARTERROUND(1, 5, 9, 13) + QUARTERROUND(2, 6, 10, 14) + QUARTERROUND(3, 7, 11, 15) + QUARTERROUND(0, 5, 10, 15) + QUARTERROUND(1, 6, 11, 12) + QUARTERROUND(2, 7, 8, 13) + QUARTERROUND(3, 4, 9, 14) + } + + for (i = 0; i < 16; ++i) { + x[i] = PLUS(x[i], input[i]); + } + for (i = 0; i < 16; ++i) { + U32TO8_LITTLE(output + 4 * i, x[i]); + } +} + +void CRYPTO_chacha_20(uint8_t *out, const uint8_t *in, size_t in_len, + const uint8_t key[32], const uint8_t nonce[12], + uint32_t counter) { + assert(!buffers_alias(out, in_len, in, in_len) || in == out); + + uint32_t input[16]; + uint8_t buf[64]; + size_t todo, i; + + input[0] = U8TO32_LITTLE(sigma + 0); + input[1] = U8TO32_LITTLE(sigma + 4); + input[2] = U8TO32_LITTLE(sigma + 8); + input[3] = U8TO32_LITTLE(sigma + 12); + + input[4] = U8TO32_LITTLE(key + 0); + input[5] = U8TO32_LITTLE(key + 4); + input[6] = U8TO32_LITTLE(key + 8); + input[7] = U8TO32_LITTLE(key + 12); + + input[8] = U8TO32_LITTLE(key + 16); + input[9] = U8TO32_LITTLE(key + 20); + input[10] = U8TO32_LITTLE(key + 24); + input[11] = U8TO32_LITTLE(key + 28); + + input[12] = counter; + input[13] = U8TO32_LITTLE(nonce + 0); + input[14] = U8TO32_LITTLE(nonce + 4); + input[15] = U8TO32_LITTLE(nonce + 8); + + while (in_len > 0) { + todo = sizeof(buf); + if (in_len < todo) { + todo = in_len; + } + + chacha_core(buf, input); + for (i = 0; i < todo; i++) { + out[i] = in[i] ^ buf[i]; + } + + out += todo; + in += todo; + in_len -= todo; + + input[12]++; + } +} + +#endif diff --git a/external/boringssl/crypto/chacha/chacha_test.cc b/external/boringssl/crypto/chacha/chacha_test.cc new file mode 100644 index 0000000000..0a5972f7d4 --- /dev/null +++ b/external/boringssl/crypto/chacha/chacha_test.cc @@ -0,0 +1,248 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include +#include + +#include + +#include +#include + + +static const uint8_t kKey[32] = { + 0x98, 0xbe, 0xf1, 0x46, 0x9b, 0xe7, 0x26, 0x98, 0x37, 0xa4, 0x5b, + 0xfb, 0xc9, 0x2a, 0x5a, 0x6a, 0xc7, 0x62, 0x50, 0x7c, 0xf9, 0x64, + 0x43, 0xbf, 0x33, 0xb9, 0x6b, 0x1b, 0xd4, 0xc6, 0xf8, 0xf6, +}; + +static const uint8_t kNonce[12] = { + 0x44, 0xe7, 0x92, 0xd6, 0x33, 0x35, 0xab, 0xb1, 0x58, 0x2e, 0x92, 0x53, +}; + +static uint32_t kCounter = 42; + +static const uint8_t kInput[] = { + 0x58, 0x28, 0xd5, 0x30, 0x36, 0x2c, 0x60, 0x55, 0x29, 0xf8, 0xe1, 0x8c, + 0xae, 0x15, 0x15, 0x26, 0xf2, 0x3a, 0x73, 0xa0, 0xf3, 0x12, 0xa3, 0x88, + 0x5f, 0x2b, 0x74, 0x23, 0x3d, 0xc9, 0x05, 0x23, 0xc6, 0x54, 0x49, 0x1e, + 0x44, 0x88, 0x14, 0xd9, 0xda, 0x37, 0x15, 0xdc, 0xb7, 0xe4, 0x23, 0xb3, + 0x9d, 0x7e, 0x16, 0x68, 0x35, 0xfc, 0x02, 0x6d, 0xcc, 0x8a, 0xe5, 0xdd, + 0x5f, 0xe4, 0xd2, 0x56, 0x6f, 0x12, 0x9c, 0x9c, 0x7d, 0x6a, 0x38, 0x48, + 0xbd, 0xdf, 0xd9, 0xac, 0x1b, 0xa2, 0x4d, 0xc5, 0x43, 0x04, 0x3c, 0xd7, + 0x99, 0xe1, 0xa7, 0x13, 0x9c, 0x51, 0xc2, 0x6d, 0xf9, 0xcf, 0x07, 0x3b, + 0xe4, 0xbf, 0x93, 0xa3, 0xa9, 0xb4, 0xc5, 0xf0, 0x1a, 0xe4, 0x8d, 0x5f, + 0xc6, 0xc4, 0x7c, 0x69, 0x7a, 0xde, 0x1a, 0xc1, 0xc9, 0xcf, 0xc2, 0x4e, + 0x7a, 0x25, 0x2c, 0x32, 0xe9, 0x17, 0xba, 0x68, 0xf1, 0x37, 0x5d, 0x62, + 0x84, 0x46, 0xf5, 0x80, 0x7f, 0x1a, 0x71, 0xf7, 0xbe, 0x72, 0x4b, 0xb8, + 0x1c, 0xfe, 0x3e, 0xbd, 0xae, 0x0d, 0x73, 0x0d, 0x87, 0x4a, 0x31, 0xc3, + 0x3d, 0x46, 0x6f, 0xb3, 0xd7, 0x6b, 0xe3, 0xb8, 0x70, 0x17, 0x8e, 0x7a, + 0x6a, 0x0e, 0xbf, 0xa8, 0xbc, 0x2b, 0xdb, 0xfa, 0x4f, 0xb6, 0x26, 0x20, + 0xee, 0x63, 0xf0, 0x6d, 0x26, 0xac, 0x6a, 0x18, 0x37, 0x6e, 0x59, 0x81, + 0xd1, 0x60, 0xe6, 0x40, 0xd5, 0x6d, 0x68, 0xba, 0x8b, 0x65, 0x4a, 0xf9, + 0xf1, 0xae, 0x56, 0x24, 0x8f, 0xe3, 0x8e, 0xe7, 0x7e, 0x6f, 0xcf, 0x92, + 0xdf, 0xa9, 0x75, 0x3a, 0xd6, 0x2e, 0x1c, 0xaf, 0xf2, 0xd6, 0x8b, 0x39, + 0xad, 0xd2, 0x5d, 0xfb, 0xd7, 0xdf, 0x05, 0x57, 0x0d, 0xf7, 0xf6, 0x8f, + 0x2d, 0x14, 0xb0, 0x4e, 0x1a, 0x3c, 0x77, 0x04, 0xcd, 0x3c, 0x5c, 0x58, + 0x52, 0x10, 0x6f, 0xcf, 0x5c, 0x03, 0xc8, 0x5f, 0x85, 0x2b, 0x05, 0x82, + 0x60, 0xda, 0xcc, 0xcd, 0xd6, 0x88, 0xbf, 0xc0, 0x10, 0xb3, 0x6f, 0x54, + 0x54, 0x42, 0xbc, 0x4b, 0x77, 0x21, 0x4d, 0xee, 0x87, 0x45, 0x06, 0x4c, + 0x60, 0x38, 0xd2, 0x7e, 0x1d, 0x30, 0x6c, 0x55, 0xf0, 0x38, 0x80, 0x1c, + 0xde, 0x3d, 0xea, 0x68, 0x3e, 0xf6, 0x3e, 0x59, 0xcf, 0x0d, 0x08, 0xae, + 0x8c, 0x02, 0x0b, 0xc1, 0x72, 0x6a, 0xb4, 0x6d, 0xf3, 0xf7, 0xb3, 0xef, + 0x3a, 0xb1, 0x06, 0xf2, 0xf4, 0xd6, 0x69, 0x7b, 0x3e, 0xa2, 0x16, 0x31, + 0x31, 0x79, 0xb6, 0x33, 0xa9, 0xca, 0x8a, 0xa8, 0xbe, 0xf3, 0xe9, 0x38, + 0x28, 0xd1, 0xe1, 0x3b, 0x4e, 0x2e, 0x47, 0x35, 0xa4, 0x61, 0x14, 0x1e, + 0x42, 0x2c, 0x49, 0x55, 0xea, 0xe3, 0xb3, 0xce, 0x39, 0xd3, 0xb3, 0xef, + 0x4a, 0x4d, 0x78, 0x49, 0xbd, 0xf6, 0x7c, 0x0a, 0x2c, 0xd3, 0x26, 0xcb, + 0xd9, 0x6a, 0xad, 0x63, 0x93, 0xa7, 0x29, 0x92, 0xdc, 0x1f, 0xaf, 0x61, + 0x82, 0x80, 0x74, 0xb2, 0x9c, 0x4a, 0x86, 0x73, 0x50, 0xd8, 0xd1, 0xff, + 0xee, 0x1a, 0xe2, 0xdd, 0xa2, 0x61, 0xbd, 0x10, 0xc3, 0x5f, 0x67, 0x9f, + 0x29, 0xe4, 0xd3, 0x70, 0xe5, 0x67, 0x3a, 0xd2, 0x20, 0x00, 0xcc, 0x25, + 0x15, 0x96, 0x54, 0x45, 0x85, 0xed, 0x82, 0x88, 0x3b, 0x9f, 0x3b, 0xc3, + 0x04, 0xd4, 0x23, 0xb1, 0x0d, 0xdc, 0xc8, 0x26, 0x9d, 0x28, 0xb3, 0x25, + 0x4d, 0x52, 0xe5, 0x33, 0xf3, 0xed, 0x2c, 0xb8, 0x1a, 0xcf, 0xc3, 0x52, + 0xb4, 0x2f, 0xc7, 0x79, 0x96, 0x14, 0x7d, 0x72, 0x27, 0x72, 0x85, 0xea, + 0x6d, 0x41, 0xa0, 0x22, 0x13, 0x6d, 0x06, 0x83, 0xa4, 0xdd, 0x0f, 0x69, + 0xd2, 0x01, 0xcd, 0xc6, 0xb8, 0x64, 0x5c, 0x2c, 0x79, 0xd1, 0xc7, 0xd3, + 0x31, 0xdb, 0x2c, 0xff, 0xda, 0xd0, 0x69, 0x31, 0xad, 0x83, 0x5f, 0xed, + 0x6a, 0x97, 0xe4, 0x00, 0x43, 0xb0, 0x2e, 0x97, 0xae, 0x00, 0x5f, 0x5c, + 0xb9, 0xe8, 0x39, 0x80, 0x10, 0xca, 0x0c, 0xfa, 0xf0, 0xb5, 0xcd, 0xaa, + 0x27, 0x11, 0x60, 0xd9, 0x21, 0x86, 0x93, 0x91, 0x9f, 0x2d, 0x1a, 0x8e, + 0xde, 0x0b, 0xb5, 0xcb, 0x05, 0x24, 0x30, 0x45, 0x4d, 0x11, 0x75, 0xfd, + 0xe5, 0xa0, 0xa9, 0x4e, 0x3a, 0x8c, 0x3b, 0x52, 0x5a, 0x37, 0x18, 0x05, + 0x4a, 0x7a, 0x09, 0x6a, 0xe6, 0xd5, 0xa9, 0xa6, 0x71, 0x47, 0x4c, 0x50, + 0xe1, 0x3e, 0x8a, 0x21, 0x2b, 0x4f, 0x0e, 0xe3, 0xcb, 0x72, 0xc5, 0x28, + 0x3e, 0x5a, 0x33, 0xec, 0x48, 0x92, 0x2e, 0xa1, 0x24, 0x57, 0x09, 0x0f, + 0x01, 0x85, 0x3b, 0x34, 0x39, 0x7e, 0xc7, 0x90, 0x62, 0xe2, 0xdc, 0x5d, + 0x0a, 0x2c, 0x51, 0x26, 0x95, 0x3a, 0x95, 0x92, 0xa5, 0x39, 0x8f, 0x0c, + 0x83, 0x0b, 0x9d, 0x38, 0xab, 0x98, 0x2a, 0xc4, 0x01, 0xc4, 0x0d, 0x77, + 0x13, 0xcb, 0xca, 0xf1, 0x28, 0x31, 0x52, 0x75, 0x27, 0x2c, 0xf0, 0x04, + 0x86, 0xc8, 0xf3, 0x3d, 0xf2, 0x9d, 0x8f, 0x55, 0x52, 0x40, 0x3f, 0xaa, + 0x22, 0x7f, 0xe7, 0x69, 0x3b, 0xee, 0x44, 0x09, 0xde, 0xff, 0xb0, 0x69, + 0x3a, 0xae, 0x74, 0xe9, 0x9d, 0x33, 0xae, 0x8b, 0x6d, 0x60, 0x04, 0xff, + 0x53, 0x3f, 0x88, 0xe9, 0x63, 0x9b, 0xb1, 0x6d, 0x2c, 0x22, 0x15, 0x5a, + 0x15, 0xd9, 0xe5, 0xcb, 0x03, 0x78, 0x3c, 0xca, 0x59, 0x8c, 0xc8, 0xc2, + 0x86, 0xff, 0xd2, 0x79, 0xd6, 0xc6, 0xec, 0x5b, 0xbb, 0xa0, 0xae, 0x01, + 0x20, 0x09, 0x2e, 0x38, 0x5d, 0xda, 0x5d, 0xe0, 0x59, 0x4e, 0xe5, 0x8b, + 0x84, 0x8f, 0xb6, 0xe0, 0x56, 0x9f, 0x21, 0xa1, 0xcf, 0xb2, 0x0f, 0x2c, + 0x93, 0xf8, 0xcf, 0x37, 0xc1, 0x9f, 0x32, 0x98, 0x21, 0x65, 0x52, 0x66, + 0x6e, 0xd3, 0x71, 0x98, 0x55, 0xb9, 0x46, 0x9f, 0x1a, 0x35, 0xc4, 0x47, + 0x69, 0x62, 0x70, 0x4b, 0x77, 0x9e, 0xe4, 0x21, 0xe6, 0x32, 0x5a, 0x26, + 0x05, 0xba, 0x57, 0x53, 0xd7, 0x9b, 0x55, 0x3c, 0xbb, 0x53, 0x79, 0x60, + 0x9c, 0xc8, 0x4d, 0xf7, 0xf5, 0x1d, 0x54, 0x02, 0x91, 0x68, 0x0e, 0xaa, + 0xca, 0x5a, 0x78, 0x0c, 0x28, 0x9a, 0xc3, 0xac, 0x49, 0xc0, 0xf4, 0x85, + 0xee, 0x59, 0x76, 0x7e, 0x28, 0x4e, 0xf1, 0x5c, 0x63, 0xf7, 0xce, 0x0e, + 0x2c, 0x21, 0xa0, 0x58, 0xe9, 0x01, 0xfd, 0xeb, 0xd1, 0xaf, 0xe6, 0xef, + 0x93, 0xb3, 0x95, 0x51, 0x60, 0xa2, 0x74, 0x40, 0x15, 0xe5, 0xf4, 0x0a, + 0xca, 0x6d, 0x9a, 0x37, 0x42, 0x4d, 0x5a, 0x58, 0x49, 0x0f, 0xe9, 0x02, + 0xfc, 0x77, 0xd8, 0x59, 0xde, 0xdd, 0xad, 0x4b, 0x99, 0x2e, 0x64, 0x73, + 0xad, 0x42, 0x2f, 0xf3, 0x2c, 0x0d, 0x49, 0xe4, 0x2e, 0x6c, 0xa4, 0x73, + 0x75, 0x18, 0x14, 0x85, 0xbb, 0x64, 0xb4, 0xa1, 0xb0, 0x6e, 0x01, 0xc0, + 0xcf, 0x17, 0x9c, 0xc5, 0x28, 0xc3, 0x2d, 0x6c, 0x17, 0x2a, 0x3d, 0x06, + 0x5c, 0xf3, 0xb4, 0x49, 0x75, 0xad, 0x17, 0x69, 0xd4, 0xca, 0x65, 0xae, + 0x44, 0x71, 0xa5, 0xf6, 0x0d, 0x0f, 0x8e, 0x37, 0xc7, 0x43, 0xce, 0x6b, + 0x08, 0xe9, 0xd1, 0x34, 0x48, 0x8f, 0xc9, 0xfc, 0xf3, 0x5d, 0x2d, 0xec, + 0x62, 0xd3, 0xf0, 0xb3, 0xfe, 0x2e, 0x40, 0x55, 0x76, 0x54, 0xc7, 0xb4, + 0x61, 0x16, 0xcc, 0x7c, 0x1c, 0x19, 0x24, 0xe6, 0x4d, 0xd4, 0xc3, 0x77, + 0x67, 0x1f, 0x3c, 0x74, 0x79, 0xa1, 0xf8, 0x85, 0x88, 0x1d, 0x6f, 0xa4, + 0x7e, 0x2c, 0x21, 0x9f, 0x49, 0xf5, 0xaa, 0x4e, 0xf3, 0x4a, 0xfa, 0x9d, + 0xbe, 0xf6, 0xce, 0xda, 0xb5, 0xab, 0x39, 0xbd, 0x16, 0x41, 0xa9, 0x4a, + 0xac, 0x09, 0x01, 0xca, +}; +static const uint8_t kOutput[] = { + 0x54, 0x30, 0x6a, 0x13, 0xda, 0x59, 0x6b, 0x6d, 0x59, 0x49, 0xc8, 0xc5, + 0xab, 0x26, 0xd4, 0x8a, 0xad, 0xc0, 0x3d, 0xaf, 0x14, 0xb9, 0x15, 0xb8, + 0xca, 0xdf, 0x17, 0xa7, 0x03, 0xd3, 0xc5, 0x06, 0x01, 0xef, 0x21, 0xdd, + 0xa3, 0x0b, 0x9e, 0x48, 0xb8, 0x5e, 0x0b, 0x87, 0x9f, 0x95, 0x23, 0x68, + 0x85, 0x69, 0xd2, 0x5d, 0xaf, 0x57, 0xe9, 0x27, 0x11, 0x3d, 0x49, 0xfa, + 0xf1, 0x08, 0xcc, 0x15, 0xec, 0x1d, 0x19, 0x16, 0x12, 0x9b, 0xc8, 0x66, + 0x1f, 0xfa, 0x2c, 0x93, 0xf4, 0x99, 0x11, 0x27, 0x31, 0x0e, 0xd8, 0x46, + 0x47, 0x40, 0x11, 0x70, 0x01, 0xca, 0xe8, 0x5b, 0xc5, 0x91, 0xc8, 0x3a, + 0xdc, 0xaa, 0xf3, 0x4b, 0x80, 0xe5, 0xbc, 0x03, 0xd0, 0x89, 0x72, 0xbc, + 0xce, 0x2a, 0x76, 0x0c, 0xf5, 0xda, 0x4c, 0x10, 0x06, 0x35, 0x41, 0xb1, + 0xe6, 0xb4, 0xaa, 0x7a, 0xef, 0xf0, 0x62, 0x4a, 0xc5, 0x9f, 0x2c, 0xaf, + 0xb8, 0x2f, 0xd9, 0xd1, 0x01, 0x7a, 0x36, 0x2f, 0x3e, 0x83, 0xa5, 0xeb, + 0x81, 0x70, 0xa0, 0x57, 0x17, 0x46, 0xea, 0x9e, 0xcb, 0x0e, 0x74, 0xd3, + 0x44, 0x57, 0x1d, 0x40, 0x06, 0xf8, 0xb7, 0xcb, 0x5f, 0xf4, 0x79, 0xbd, + 0x11, 0x19, 0xd6, 0xee, 0xf8, 0xb0, 0xaa, 0xdd, 0x00, 0x62, 0xad, 0x3b, + 0x88, 0x9a, 0x88, 0x5b, 0x1b, 0x07, 0xc9, 0xae, 0x9e, 0xa6, 0x94, 0xe5, + 0x55, 0xdb, 0x45, 0x23, 0xb9, 0x2c, 0xcd, 0x29, 0xd3, 0x54, 0xc3, 0x88, + 0x1e, 0x5f, 0x52, 0xf2, 0x09, 0x00, 0x26, 0x26, 0x1a, 0xed, 0xf5, 0xc2, + 0xa9, 0x7d, 0xf9, 0x21, 0x5a, 0xaf, 0x6d, 0xab, 0x8e, 0x16, 0x84, 0x96, + 0xb5, 0x4f, 0xcf, 0x1e, 0xa3, 0xaf, 0x08, 0x9f, 0x79, 0x86, 0xc3, 0xbe, + 0x0c, 0x70, 0xcb, 0x8f, 0xf3, 0xc5, 0xf8, 0xe8, 0x4b, 0x21, 0x7d, 0x18, + 0xa9, 0xed, 0x8b, 0xfb, 0x6b, 0x5a, 0x6f, 0x26, 0x0b, 0x56, 0x04, 0x7c, + 0xfe, 0x0e, 0x1e, 0xc1, 0x3f, 0x82, 0xc5, 0x73, 0xbd, 0x53, 0x0c, 0xf0, + 0xe2, 0xc9, 0xf3, 0x3d, 0x1b, 0x6d, 0xba, 0x70, 0xc1, 0x6d, 0xb6, 0x00, + 0x28, 0xe1, 0xc4, 0x78, 0x62, 0x04, 0xda, 0x23, 0x86, 0xc3, 0xda, 0x74, + 0x3d, 0x7c, 0xd6, 0x76, 0x29, 0xb2, 0x27, 0x2e, 0xb2, 0x35, 0x42, 0x60, + 0x82, 0xcf, 0x30, 0x2c, 0x59, 0xe4, 0xe3, 0xd0, 0x74, 0x1f, 0x58, 0xe8, + 0xda, 0x47, 0x45, 0x73, 0x1c, 0x05, 0x93, 0xae, 0x75, 0xbe, 0x1f, 0x81, + 0xd8, 0xb7, 0xb3, 0xff, 0xfc, 0x8b, 0x52, 0x9e, 0xed, 0x8b, 0x37, 0x9f, + 0xe0, 0xb8, 0xa2, 0x66, 0xe1, 0x6a, 0xc5, 0x1f, 0x1d, 0xf0, 0xde, 0x3f, + 0x3d, 0xb0, 0x28, 0xf3, 0xaa, 0x4e, 0x4d, 0x31, 0xb0, 0x26, 0x79, 0x2b, + 0x08, 0x0f, 0xe9, 0x2f, 0x79, 0xb3, 0xc8, 0xdd, 0xa7, 0x89, 0xa8, 0xa8, + 0x1d, 0x59, 0x0e, 0x4f, 0x1e, 0x93, 0x1f, 0x70, 0x7f, 0x4e, 0x7e, 0xfe, + 0xb8, 0xca, 0x63, 0xe0, 0xa6, 0x05, 0xcc, 0xd7, 0xde, 0x2a, 0x49, 0x31, + 0x78, 0x5c, 0x5f, 0x44, 0xb2, 0x9b, 0x91, 0x99, 0x14, 0x29, 0x63, 0x09, + 0x12, 0xdd, 0x02, 0xd9, 0x7b, 0xe9, 0xf5, 0x12, 0x07, 0xd0, 0xe7, 0xe6, + 0xe8, 0xdd, 0xda, 0xa4, 0x73, 0xc4, 0x8e, 0xbd, 0x7b, 0xb7, 0xbb, 0xcb, + 0x83, 0x2f, 0x43, 0xf6, 0x1c, 0x50, 0xae, 0x9b, 0x2e, 0x52, 0x80, 0x18, + 0x85, 0xa8, 0x23, 0x52, 0x7a, 0x6a, 0xf7, 0x42, 0x36, 0xca, 0x91, 0x5a, + 0x3d, 0x2a, 0xa0, 0x35, 0x7d, 0x70, 0xfc, 0x4c, 0x18, 0x7c, 0x57, 0x72, + 0xcf, 0x9b, 0x29, 0xd6, 0xd0, 0xb4, 0xd7, 0xe6, 0x89, 0x70, 0x69, 0x22, + 0x5e, 0x45, 0x09, 0x4d, 0x49, 0x87, 0x84, 0x5f, 0x8a, 0x5f, 0xe4, 0x15, + 0xd3, 0xe3, 0x72, 0xaf, 0xb2, 0x30, 0x9c, 0xc1, 0xff, 0x8e, 0x6d, 0x2a, + 0x76, 0x9e, 0x08, 0x03, 0x7e, 0xe0, 0xc3, 0xc2, 0x97, 0x06, 0x6b, 0x33, + 0x2b, 0x08, 0xe3, 0xd5, 0x0b, 0xd8, 0x32, 0x67, 0x61, 0x10, 0xed, 0x6b, + 0xed, 0x50, 0xef, 0xd7, 0x1c, 0x1b, 0xe0, 0x6d, 0xa1, 0x64, 0x19, 0x34, + 0x2f, 0xe4, 0xe8, 0x54, 0xbf, 0x84, 0x0e, 0xdf, 0x0e, 0x8b, 0xd8, 0xdd, + 0x77, 0x96, 0xb8, 0x54, 0xab, 0xf2, 0x95, 0x59, 0x0d, 0x0d, 0x0a, 0x15, + 0x6e, 0x01, 0xf2, 0x24, 0xab, 0xa0, 0xd8, 0xdf, 0x38, 0xea, 0x97, 0x58, + 0x76, 0x88, 0xbe, 0xaf, 0x45, 0xe3, 0x56, 0x4f, 0x68, 0xe8, 0x4b, 0xe7, + 0x2b, 0x22, 0x18, 0x96, 0x82, 0x89, 0x25, 0x34, 0xd1, 0xdd, 0x08, 0xea, + 0x7e, 0x21, 0xef, 0x57, 0x55, 0x43, 0xf7, 0xfa, 0xca, 0x1c, 0xde, 0x99, + 0x2e, 0x8b, 0xd8, 0xc3, 0xcf, 0x89, 0x4d, 0xfc, 0x3b, 0x7d, 0x4a, 0xc9, + 0x99, 0xc4, 0x31, 0xb6, 0x7a, 0xae, 0xf8, 0x49, 0xb2, 0x46, 0xc1, 0x60, + 0x05, 0x75, 0xf3, 0x3d, 0xf2, 0xc9, 0x84, 0xa4, 0xb9, 0x8a, 0x87, 0x2a, + 0x87, 0x5c, 0x0a, 0xbc, 0x51, 0x7d, 0x9a, 0xf5, 0xc9, 0x24, 0x2d, 0x5e, + 0xe6, 0xc6, 0xe3, 0xcd, 0x7e, 0xe4, 0xaf, 0x8a, 0x6c, 0x00, 0x04, 0xc8, + 0xd7, 0xa5, 0xad, 0xfa, 0xb2, 0x08, 0x4a, 0x26, 0x9b, 0x7c, 0xd0, 0xc6, + 0x13, 0xb1, 0xb9, 0x65, 0x3f, 0x70, 0x30, 0xf9, 0x98, 0x9d, 0x87, 0x99, + 0x57, 0x71, 0x3e, 0xb1, 0xc3, 0x24, 0xf0, 0xa6, 0xa2, 0x60, 0x9d, 0x66, + 0xd2, 0x5f, 0xae, 0xe3, 0x94, 0x87, 0xea, 0xd1, 0xea, 0x0d, 0x2a, 0x77, + 0xef, 0x31, 0xcc, 0xeb, 0xf9, 0x0c, 0xdc, 0x9c, 0x12, 0x80, 0xbb, 0xb0, + 0x8e, 0xab, 0x9a, 0x04, 0xcd, 0x4b, 0x95, 0x4f, 0x7a, 0x0b, 0x53, 0x7c, + 0x16, 0xcc, 0x0e, 0xb1, 0x73, 0x10, 0xdd, 0xaa, 0x76, 0x94, 0x90, 0xd9, + 0x8b, 0x66, 0x41, 0x31, 0xed, 0x8c, 0x7d, 0x74, 0xc4, 0x33, 0xfa, 0xc3, + 0x43, 0x8d, 0x10, 0xbc, 0x84, 0x4d, 0x0e, 0x95, 0x32, 0xdf, 0x17, 0x43, + 0x6d, 0xd2, 0x5e, 0x12, 0xb9, 0xed, 0x33, 0xd9, 0x97, 0x6f, 0x4a, 0xcd, + 0xc3, 0xcd, 0x81, 0x34, 0xbe, 0x7e, 0xa2, 0xd0, 0xa7, 0x91, 0x5d, 0x90, + 0xf6, 0x5e, 0x4a, 0x25, 0x0f, 0xcc, 0x24, 0xeb, 0xe1, 0xe4, 0x62, 0x6c, + 0x8f, 0x45, 0x36, 0x97, 0x5d, 0xda, 0x20, 0x2b, 0x86, 0x00, 0x8c, 0x94, + 0xa9, 0x6a, 0x69, 0xb2, 0xe9, 0xbb, 0x82, 0x8e, 0x41, 0x95, 0xb4, 0xb7, + 0xf1, 0x55, 0x52, 0x30, 0x39, 0x48, 0xb3, 0x25, 0x82, 0xa9, 0x10, 0x27, + 0x89, 0xb5, 0xe5, 0x1f, 0xab, 0x72, 0x3c, 0x70, 0x08, 0xce, 0xe6, 0x61, + 0xbf, 0x19, 0xc8, 0x90, 0x2b, 0x29, 0x30, 0x3e, 0xb8, 0x4c, 0x33, 0xf0, + 0xf0, 0x15, 0x2e, 0xb7, 0x25, 0xca, 0x99, 0x4b, 0x6f, 0x4b, 0x41, 0x50, + 0xee, 0x56, 0x99, 0xcf, 0x2b, 0xa4, 0xc4, 0x7c, 0x5c, 0xa6, 0xd4, 0x67, + 0x04, 0x5c, 0x5d, 0x5f, 0x26, 0x9e, 0x0f, 0xe2, 0x58, 0x68, 0x4c, 0x30, + 0xcd, 0xef, 0x46, 0xdb, 0x37, 0x6f, 0xbb, 0xc4, 0x80, 0xca, 0x8a, 0x54, + 0x5d, 0x71, 0x9d, 0x0c, 0xe8, 0xb8, 0x2c, 0x10, 0x90, 0x44, 0xa4, 0x88, + 0x3f, 0xbc, 0x15, 0x3c, 0xd2, 0xca, 0x0e, 0xc3, 0xe4, 0x6e, 0xef, 0xb0, + 0xcb, 0xfd, 0x61, 0x7c, 0x27, 0xf2, 0x25, 0xea, 0x71, 0x6d, 0xf7, 0x49, + 0x9c, 0x81, 0x27, 0xf0, 0x61, 0x33, 0xcf, 0x55, 0x68, 0xd3, 0x73, 0xa4, + 0xed, 0x35, 0x65, 0x2a, 0xf2, 0x3e, 0xcf, 0x90, 0x98, 0x54, 0x6d, 0x95, + 0x6a, 0x0c, 0x9c, 0x24, 0x0e, 0xb4, 0xb7, 0x9b, 0x8d, 0x6e, 0x1c, 0xbc, + 0xeb, 0x17, 0x10, 0x86, 0xda, 0x91, 0x6d, 0x89, 0x4c, 0xeb, 0xf5, 0x50, + 0x8f, 0x40, 0xcf, 0x4a, +}; + +static_assert(sizeof(kInput) == sizeof(kOutput), + "Input and output lengths don't match."); + +static bool TestChaCha20(size_t len) { + std::unique_ptr buf(new uint8_t[len]); + CRYPTO_chacha_20(buf.get(), kInput, len, kKey, kNonce, kCounter); + if (memcmp(buf.get(), kOutput, len) != 0) { + fprintf(stderr, "Mismatch at length %zu.\n", len); + return false; + } + + // Test in-place. + memcpy(buf.get(), kInput, len); + CRYPTO_chacha_20(buf.get(), buf.get(), len, kKey, kNonce, kCounter); + if (memcmp(buf.get(), kOutput, len) != 0) { + fprintf(stderr, "Mismatch at length %zu, in-place.\n", len); + return false; + } + + return true; +} + +int main(int argc, char **argv) { + CRYPTO_library_init(); + + // Run the test with the test vector at all lengths. + for (size_t len = 0; len <= sizeof(kInput); len++) { + if (!TestChaCha20(len)) { + return 1; + } + } + + printf("PASS\n"); + return 0; +} diff --git a/external/boringssl/crypto/cipher/CMakeLists.txt b/external/boringssl/crypto/cipher/CMakeLists.txt new file mode 100644 index 0000000000..49e5c6d8ef --- /dev/null +++ b/external/boringssl/crypto/cipher/CMakeLists.txt @@ -0,0 +1,42 @@ +include_directories(../../include) + +add_library( + cipher + + OBJECT + + cipher.c + derive_key.c + aead.c + + e_null.c + e_rc2.c + e_rc4.c + e_des.c + e_aes.c + e_chacha20poly1305.c + + tls_cbc.c + e_tls.c + e_ssl3.c +) + +if(ENABLE_TESTS) +add_executable( + cipher_test + + cipher_test.cc + $ +) + +add_executable( + aead_test + + aead_test.cc + $ +) + +target_link_libraries(cipher_test crypto) +target_link_libraries(aead_test crypto) +add_dependencies(all_tests cipher_test aead_test) +endif() diff --git a/external/boringssl/crypto/cipher/aead.c b/external/boringssl/crypto/cipher/aead.c new file mode 100644 index 0000000000..57eecc1b89 --- /dev/null +++ b/external/boringssl/crypto/cipher/aead.c @@ -0,0 +1,162 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include + +#include +#include + +#include "internal.h" +#include "../internal.h" + + +size_t EVP_AEAD_key_length(const EVP_AEAD *aead) { return aead->key_len; } + +size_t EVP_AEAD_nonce_length(const EVP_AEAD *aead) { return aead->nonce_len; } + +size_t EVP_AEAD_max_overhead(const EVP_AEAD *aead) { return aead->overhead; } + +size_t EVP_AEAD_max_tag_len(const EVP_AEAD *aead) { return aead->max_tag_len; } + +void EVP_AEAD_CTX_zero(EVP_AEAD_CTX *ctx) { + memset(ctx, 0, sizeof(EVP_AEAD_CTX)); +} + +int EVP_AEAD_CTX_init(EVP_AEAD_CTX *ctx, const EVP_AEAD *aead, + const uint8_t *key, size_t key_len, size_t tag_len, + ENGINE *impl) { + if (!aead->init) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_NO_DIRECTION_SET); + ctx->aead = NULL; + return 0; + } + return EVP_AEAD_CTX_init_with_direction(ctx, aead, key, key_len, tag_len, + evp_aead_open); +} + +int EVP_AEAD_CTX_init_with_direction(EVP_AEAD_CTX *ctx, const EVP_AEAD *aead, + const uint8_t *key, size_t key_len, + size_t tag_len, + enum evp_aead_direction_t dir) { + if (key_len != aead->key_len) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_KEY_SIZE); + ctx->aead = NULL; + return 0; + } + + ctx->aead = aead; + + int ok; + if (aead->init) { + ok = aead->init(ctx, key, key_len, tag_len); + } else { + ok = aead->init_with_direction(ctx, key, key_len, tag_len, dir); + } + + if (!ok) { + ctx->aead = NULL; + } + + return ok; +} + +void EVP_AEAD_CTX_cleanup(EVP_AEAD_CTX *ctx) { + if (ctx->aead == NULL) { + return; + } + ctx->aead->cleanup(ctx); + ctx->aead = NULL; +} + +/* check_alias returns 1 if |out| is compatible with |in| and 0 otherwise. If + * |in| and |out| alias, we require that |in| == |out|. */ +static int check_alias(const uint8_t *in, size_t in_len, const uint8_t *out, + size_t out_len) { + if (!buffers_alias(in, in_len, out, out_len)) { + return 1; + } + + return in == out; +} + +int EVP_AEAD_CTX_seal(const EVP_AEAD_CTX *ctx, uint8_t *out, size_t *out_len, + size_t max_out_len, const uint8_t *nonce, + size_t nonce_len, const uint8_t *in, size_t in_len, + const uint8_t *ad, size_t ad_len) { + size_t possible_out_len = in_len + ctx->aead->overhead; + + if (possible_out_len < in_len /* overflow */) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE); + goto error; + } + + if (!check_alias(in, in_len, out, max_out_len)) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_OUTPUT_ALIASES_INPUT); + goto error; + } + + if (ctx->aead->seal(ctx, out, out_len, max_out_len, nonce, nonce_len, in, + in_len, ad, ad_len)) { + return 1; + } + +error: + /* In the event of an error, clear the output buffer so that a caller + * that doesn't check the return value doesn't send raw data. */ + memset(out, 0, max_out_len); + *out_len = 0; + return 0; +} + +int EVP_AEAD_CTX_open(const EVP_AEAD_CTX *ctx, uint8_t *out, size_t *out_len, + size_t max_out_len, const uint8_t *nonce, + size_t nonce_len, const uint8_t *in, size_t in_len, + const uint8_t *ad, size_t ad_len) { + if (!check_alias(in, in_len, out, max_out_len)) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_OUTPUT_ALIASES_INPUT); + goto error; + } + + if (ctx->aead->open(ctx, out, out_len, max_out_len, nonce, nonce_len, in, + in_len, ad, ad_len)) { + return 1; + } + +error: + /* In the event of an error, clear the output buffer so that a caller + * that doesn't check the return value doesn't try and process bad + * data. */ + memset(out, 0, max_out_len); + *out_len = 0; + return 0; +} + +int EVP_AEAD_CTX_get_rc4_state(const EVP_AEAD_CTX *ctx, const RC4_KEY **out_key) { + if (ctx->aead->get_rc4_state == NULL) { + return 0; + } + + return ctx->aead->get_rc4_state(ctx, out_key); +} + +int EVP_AEAD_CTX_get_iv(const EVP_AEAD_CTX *ctx, const uint8_t **out_iv, + size_t *out_len) { + if (ctx->aead->get_iv == NULL) { + return 0; + } + + return ctx->aead->get_iv(ctx, out_iv, out_len); +} diff --git a/external/boringssl/crypto/cipher/aead_test.cc b/external/boringssl/crypto/cipher/aead_test.cc new file mode 100644 index 0000000000..8bad93f55e --- /dev/null +++ b/external/boringssl/crypto/cipher/aead_test.cc @@ -0,0 +1,362 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include + +#include + +#include +#include +#include + +#include "../test/file_test.h" +#include "../test/scoped_types.h" + + +// This program tests an AEAD against a series of test vectors from a file, +// using the FileTest format. As an example, here's a valid test case: +// +// KEY: 5a19f3173586b4c42f8412f4d5a786531b3231753e9e00998aec12fda8df10e4 +// NONCE: 978105dfce667bf4 +// IN: 6a4583908d +// AD: b654574932 +// CT: 5294265a60 +// TAG: 1d45758621762e061368e68868e2f929 + +static bool TestAEAD(FileTest *t, void *arg) { + const EVP_AEAD *aead = reinterpret_cast(arg); + + std::vector key, nonce, in, ad, ct, tag; + if (!t->GetBytes(&key, "KEY") || + !t->GetBytes(&nonce, "NONCE") || + !t->GetBytes(&in, "IN") || + !t->GetBytes(&ad, "AD") || + !t->GetBytes(&ct, "CT") || + !t->GetBytes(&tag, "TAG")) { + return false; + } + + ScopedEVP_AEAD_CTX ctx; + if (!EVP_AEAD_CTX_init_with_direction(ctx.get(), aead, key.data(), key.size(), + tag.size(), evp_aead_seal)) { + t->PrintLine("Failed to init AEAD."); + return false; + } + + std::vector out(in.size() + EVP_AEAD_max_overhead(aead)); + if (!t->HasAttribute("NO_SEAL")) { + size_t out_len; + if (!EVP_AEAD_CTX_seal(ctx.get(), out.data(), &out_len, out.size(), + nonce.data(), nonce.size(), in.data(), in.size(), + ad.data(), ad.size())) { + t->PrintLine("Failed to run AEAD."); + return false; + } + out.resize(out_len); + + if (out.size() != ct.size() + tag.size()) { + t->PrintLine("Bad output length: %u vs %u.", (unsigned)out_len, + (unsigned)(ct.size() + tag.size())); + return false; + } + if (!t->ExpectBytesEqual(ct.data(), ct.size(), out.data(), ct.size()) || + !t->ExpectBytesEqual(tag.data(), tag.size(), out.data() + ct.size(), + tag.size())) { + return false; + } + } else { + out.resize(ct.size() + tag.size()); + memcpy(out.data(), ct.data(), ct.size()); + memcpy(out.data() + ct.size(), tag.data(), tag.size()); + } + + // The "stateful" AEADs for implementing pre-AEAD cipher suites need to be + // reset after each operation. + ctx.Reset(); + if (!EVP_AEAD_CTX_init_with_direction(ctx.get(), aead, key.data(), key.size(), + tag.size(), evp_aead_open)) { + t->PrintLine("Failed to init AEAD."); + return false; + } + + std::vector out2(out.size()); + size_t out2_len; + int ret = EVP_AEAD_CTX_open(ctx.get(), out2.data(), &out2_len, out2.size(), + nonce.data(), nonce.size(), out.data(), + out.size(), ad.data(), ad.size()); + if (t->HasAttribute("FAILS")) { + if (ret) { + t->PrintLine("Decrypted bad data."); + return false; + } + ERR_clear_error(); + return true; + } + + if (!ret) { + t->PrintLine("Failed to decrypt."); + return false; + } + out2.resize(out2_len); + if (!t->ExpectBytesEqual(in.data(), in.size(), out2.data(), out2.size())) { + return false; + } + + // The "stateful" AEADs for implementing pre-AEAD cipher suites need to be + // reset after each operation. + ctx.Reset(); + if (!EVP_AEAD_CTX_init_with_direction(ctx.get(), aead, key.data(), key.size(), + tag.size(), evp_aead_open)) { + t->PrintLine("Failed to init AEAD."); + return false; + } + + // Garbage at the end isn't ignored. + out.push_back(0); + out2.resize(out.size()); + if (EVP_AEAD_CTX_open(ctx.get(), out2.data(), &out2_len, out2.size(), + nonce.data(), nonce.size(), out.data(), out.size(), + ad.data(), ad.size())) { + t->PrintLine("Decrypted bad data with trailing garbage."); + return false; + } + ERR_clear_error(); + + // The "stateful" AEADs for implementing pre-AEAD cipher suites need to be + // reset after each operation. + ctx.Reset(); + if (!EVP_AEAD_CTX_init_with_direction(ctx.get(), aead, key.data(), key.size(), + tag.size(), evp_aead_open)) { + t->PrintLine("Failed to init AEAD."); + return false; + } + + // Verify integrity is checked. + out[0] ^= 0x80; + out.resize(out.size() - 1); + out2.resize(out.size()); + if (EVP_AEAD_CTX_open(ctx.get(), out2.data(), &out2_len, out2.size(), + nonce.data(), nonce.size(), out.data(), out.size(), + ad.data(), ad.size())) { + t->PrintLine("Decrypted bad data with corrupted byte."); + return false; + } + ERR_clear_error(); + + return true; +} + +static int TestCleanupAfterInitFailure(const EVP_AEAD *aead) { + EVP_AEAD_CTX ctx; + uint8_t key[128]; + + memset(key, 0, sizeof(key)); + const size_t key_len = EVP_AEAD_key_length(aead); + if (key_len > sizeof(key)) { + fprintf(stderr, "Key length of AEAD too long.\n"); + return 0; + } + + if (EVP_AEAD_CTX_init(&ctx, aead, key, key_len, + 9999 /* a silly tag length to trigger an error */, + NULL /* ENGINE */) != 0) { + fprintf(stderr, "A silly tag length didn't trigger an error!\n"); + return 0; + } + ERR_clear_error(); + + /* Running a second, failed _init should not cause a memory leak. */ + if (EVP_AEAD_CTX_init(&ctx, aead, key, key_len, + 9999 /* a silly tag length to trigger an error */, + NULL /* ENGINE */) != 0) { + fprintf(stderr, "A silly tag length didn't trigger an error!\n"); + return 0; + } + ERR_clear_error(); + + /* Calling _cleanup on an |EVP_AEAD_CTX| after a failed _init should be a + * no-op. */ + EVP_AEAD_CTX_cleanup(&ctx); + return 1; +} + +static bool TestWithAliasedBuffers(const EVP_AEAD *aead) { + const size_t key_len = EVP_AEAD_key_length(aead); + const size_t nonce_len = EVP_AEAD_nonce_length(aead); + const size_t max_overhead = EVP_AEAD_max_overhead(aead); + + std::vector key(key_len, 'a'); + ScopedEVP_AEAD_CTX ctx; + if (!EVP_AEAD_CTX_init(ctx.get(), aead, key.data(), key_len, + EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr)) { + return false; + } + + static const uint8_t kPlaintext[260] = + "testing123456testing123456testing123456testing123456testing123456testing" + "123456testing123456testing123456testing123456testing123456testing123456t" + "esting123456testing123456testing123456testing123456testing123456testing1" + "23456testing123456testing123456testing12345"; + const std::vector offsets = { + 0, 1, 2, 8, 15, 16, 17, 31, 32, 33, 63, + 64, 65, 95, 96, 97, 127, 128, 129, 255, 256, 257, + }; + + std::vector nonce(nonce_len, 'b'); + std::vector valid_encryption(sizeof(kPlaintext) + max_overhead); + size_t valid_encryption_len; + if (!EVP_AEAD_CTX_seal( + ctx.get(), valid_encryption.data(), &valid_encryption_len, + sizeof(kPlaintext) + max_overhead, nonce.data(), nonce_len, + kPlaintext, sizeof(kPlaintext), nullptr, 0)) { + fprintf(stderr, "EVP_AEAD_CTX_seal failed with disjoint buffers.\n"); + return false; + } + + // Test with out != in which we expect to fail. + std::vector buffer(2 + valid_encryption_len); + uint8_t *in = buffer.data() + 1; + uint8_t *out1 = buffer.data(); + uint8_t *out2 = buffer.data() + 2; + + memcpy(in, kPlaintext, sizeof(kPlaintext)); + size_t out_len; + if (EVP_AEAD_CTX_seal(ctx.get(), out1, &out_len, + sizeof(kPlaintext) + max_overhead, nonce.data(), + nonce_len, in, sizeof(kPlaintext), nullptr, 0) || + EVP_AEAD_CTX_seal(ctx.get(), out2, &out_len, + sizeof(kPlaintext) + max_overhead, nonce.data(), + nonce_len, in, sizeof(kPlaintext), nullptr, 0)) { + fprintf(stderr, "EVP_AEAD_CTX_seal unexpectedly succeeded.\n"); + return false; + } + ERR_clear_error(); + + memcpy(in, valid_encryption.data(), valid_encryption_len); + if (EVP_AEAD_CTX_open(ctx.get(), out1, &out_len, valid_encryption_len, + nonce.data(), nonce_len, in, valid_encryption_len, + nullptr, 0) || + EVP_AEAD_CTX_open(ctx.get(), out2, &out_len, valid_encryption_len, + nonce.data(), nonce_len, in, valid_encryption_len, + nullptr, 0)) { + fprintf(stderr, "EVP_AEAD_CTX_open unexpectedly succeeded.\n"); + return false; + } + ERR_clear_error(); + + // Test with out == in, which we expect to work. + memcpy(in, kPlaintext, sizeof(kPlaintext)); + + if (!EVP_AEAD_CTX_seal(ctx.get(), in, &out_len, + sizeof(kPlaintext) + max_overhead, nonce.data(), + nonce_len, in, sizeof(kPlaintext), nullptr, 0)) { + fprintf(stderr, "EVP_AEAD_CTX_seal failed in-place.\n"); + return false; + } + + if (out_len != valid_encryption_len || + memcmp(in, valid_encryption.data(), out_len) != 0) { + fprintf(stderr, "EVP_AEAD_CTX_seal produced bad output in-place.\n"); + return false; + } + + memcpy(in, valid_encryption.data(), valid_encryption_len); + if (!EVP_AEAD_CTX_open(ctx.get(), in, &out_len, valid_encryption_len, + nonce.data(), nonce_len, in, valid_encryption_len, + nullptr, 0)) { + fprintf(stderr, "EVP_AEAD_CTX_open failed in-place.\n"); + return false; + } + + if (out_len != sizeof(kPlaintext) || + memcmp(in, kPlaintext, out_len) != 0) { + fprintf(stderr, "EVP_AEAD_CTX_open produced bad output in-place.\n"); + return false; + } + + return true; +} + +struct KnownAEAD { + const char name[40]; + const EVP_AEAD *(*func)(void); + // limited_implementation indicates that tests that assume a generic AEAD + // interface should not be performed. For example, the key-wrap AEADs only + // handle inputs that are a multiple of eight bytes in length and the + // SSLv3/TLS AEADs have the concept of “directionâ€. + bool limited_implementation; +}; + +static const struct KnownAEAD kAEADs[] = { + { "aes-128-gcm", EVP_aead_aes_128_gcm, false }, + { "aes-256-gcm", EVP_aead_aes_256_gcm, false }, + { "chacha20-poly1305", EVP_aead_chacha20_poly1305, false }, + { "chacha20-poly1305-old", EVP_aead_chacha20_poly1305_old, false }, + { "rc4-md5-tls", EVP_aead_rc4_md5_tls, true }, + { "rc4-sha1-tls", EVP_aead_rc4_sha1_tls, true }, + { "aes-128-cbc-sha1-tls", EVP_aead_aes_128_cbc_sha1_tls, true }, + { "aes-128-cbc-sha1-tls-implicit-iv", EVP_aead_aes_128_cbc_sha1_tls_implicit_iv, true }, + { "aes-128-cbc-sha256-tls", EVP_aead_aes_128_cbc_sha256_tls, true }, + { "aes-256-cbc-sha1-tls", EVP_aead_aes_256_cbc_sha1_tls, true }, + { "aes-256-cbc-sha1-tls-implicit-iv", EVP_aead_aes_256_cbc_sha1_tls_implicit_iv, true }, + { "aes-256-cbc-sha256-tls", EVP_aead_aes_256_cbc_sha256_tls, true }, + { "aes-256-cbc-sha384-tls", EVP_aead_aes_256_cbc_sha384_tls, true }, + { "des-ede3-cbc-sha1-tls", EVP_aead_des_ede3_cbc_sha1_tls, true }, + { "des-ede3-cbc-sha1-tls-implicit-iv", EVP_aead_des_ede3_cbc_sha1_tls_implicit_iv, true }, + { "rc4-md5-ssl3", EVP_aead_rc4_md5_ssl3, true }, + { "rc4-sha1-ssl3", EVP_aead_rc4_sha1_ssl3, true }, + { "aes-128-cbc-sha1-ssl3", EVP_aead_aes_128_cbc_sha1_ssl3, true }, + { "aes-256-cbc-sha1-ssl3", EVP_aead_aes_256_cbc_sha1_ssl3, true }, + { "des-ede3-cbc-sha1-ssl3", EVP_aead_des_ede3_cbc_sha1_ssl3, true }, + { "aes-128-key-wrap", EVP_aead_aes_128_key_wrap, true }, + { "aes-256-key-wrap", EVP_aead_aes_256_key_wrap, true }, + { "aes-128-ctr-hmac-sha256", EVP_aead_aes_128_ctr_hmac_sha256, false }, + { "aes-256-ctr-hmac-sha256", EVP_aead_aes_256_ctr_hmac_sha256, false }, + { "", NULL, false }, +}; + +int main(int argc, char **argv) { + CRYPTO_library_init(); + + if (argc != 3) { + fprintf(stderr, "%s \n", argv[0]); + return 1; + } + + const struct KnownAEAD *known_aead; + for (unsigned i = 0;; i++) { + known_aead = &kAEADs[i]; + if (known_aead->func == NULL) { + fprintf(stderr, "Unknown AEAD: %s\n", argv[1]); + return 2; + } + if (strcmp(known_aead->name, argv[1]) == 0) { + break; + } + } + + const EVP_AEAD *const aead = known_aead->func(); + + if (!TestCleanupAfterInitFailure(aead)) { + return 1; + } + + if (!known_aead->limited_implementation && !TestWithAliasedBuffers(aead)) { + fprintf(stderr, "Aliased buffers test failed for %s.\n", known_aead->name); + return 1; + } + + return FileTestMain(TestAEAD, const_cast(aead), argv[2]); +} diff --git a/external/boringssl/crypto/cipher/cipher.c b/external/boringssl/crypto/cipher/cipher.c new file mode 100644 index 0000000000..f61c59f4fe --- /dev/null +++ b/external/boringssl/crypto/cipher/cipher.c @@ -0,0 +1,652 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +#include +#include +#include + +#include "internal.h" + + +const EVP_CIPHER *EVP_get_cipherbynid(int nid) { + switch (nid) { + case NID_rc2_cbc: + return EVP_rc2_cbc(); + case NID_rc2_40_cbc: + return EVP_rc2_40_cbc(); + case NID_des_ede3_cbc: + return EVP_des_ede3_cbc(); + case NID_des_ede_cbc: + return EVP_des_cbc(); + case NID_aes_128_cbc: + return EVP_aes_128_cbc(); + case NID_aes_192_cbc: + return EVP_aes_192_cbc(); + case NID_aes_256_cbc: + return EVP_aes_256_cbc(); + default: + return NULL; + } +} + +void EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *ctx) { + memset(ctx, 0, sizeof(EVP_CIPHER_CTX)); +} + +EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void) { + EVP_CIPHER_CTX *ctx = OPENSSL_malloc(sizeof(EVP_CIPHER_CTX)); + if (ctx) { + EVP_CIPHER_CTX_init(ctx); + } + return ctx; +} + +int EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *c) { + if (c->cipher != NULL) { + if (c->cipher->cleanup) { + c->cipher->cleanup(c); + } + OPENSSL_cleanse(c->cipher_data, c->cipher->ctx_size); + } + OPENSSL_free(c->cipher_data); + + memset(c, 0, sizeof(EVP_CIPHER_CTX)); + return 1; +} + +void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx) { + if (ctx) { + EVP_CIPHER_CTX_cleanup(ctx); + OPENSSL_free(ctx); + } +} + +int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in) { + if (in == NULL || in->cipher == NULL) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INPUT_NOT_INITIALIZED); + return 0; + } + + EVP_CIPHER_CTX_cleanup(out); + memcpy(out, in, sizeof(EVP_CIPHER_CTX)); + + if (in->cipher_data && in->cipher->ctx_size) { + out->cipher_data = OPENSSL_malloc(in->cipher->ctx_size); + if (!out->cipher_data) { + OPENSSL_PUT_ERROR(CIPHER, ERR_R_MALLOC_FAILURE); + return 0; + } + memcpy(out->cipher_data, in->cipher_data, in->cipher->ctx_size); + } + + if (in->cipher->flags & EVP_CIPH_CUSTOM_COPY) { + return in->cipher->ctrl((EVP_CIPHER_CTX *)in, EVP_CTRL_COPY, 0, out); + } + + return 1; +} + +int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, + ENGINE *engine, const uint8_t *key, const uint8_t *iv, + int enc) { + if (enc == -1) { + enc = ctx->encrypt; + } else { + if (enc) { + enc = 1; + } + ctx->encrypt = enc; + } + + if (cipher) { + /* Ensure a context left from last time is cleared (the previous check + * attempted to avoid this if the same ENGINE and EVP_CIPHER could be + * used). */ + if (ctx->cipher) { + EVP_CIPHER_CTX_cleanup(ctx); + /* Restore encrypt and flags */ + ctx->encrypt = enc; + } + + ctx->cipher = cipher; + if (ctx->cipher->ctx_size) { + ctx->cipher_data = OPENSSL_malloc(ctx->cipher->ctx_size); + if (!ctx->cipher_data) { + ctx->cipher = NULL; + OPENSSL_PUT_ERROR(CIPHER, ERR_R_MALLOC_FAILURE); + return 0; + } + } else { + ctx->cipher_data = NULL; + } + + ctx->key_len = cipher->key_len; + ctx->flags = 0; + + if (ctx->cipher->flags & EVP_CIPH_CTRL_INIT) { + if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_INIT, 0, NULL)) { + ctx->cipher = NULL; + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INITIALIZATION_ERROR); + return 0; + } + } + } else if (!ctx->cipher) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_NO_CIPHER_SET); + return 0; + } + + /* we assume block size is a power of 2 in *cryptUpdate */ + assert(ctx->cipher->block_size == 1 || ctx->cipher->block_size == 8 || + ctx->cipher->block_size == 16); + + if (!(EVP_CIPHER_CTX_flags(ctx) & EVP_CIPH_CUSTOM_IV)) { + switch (EVP_CIPHER_CTX_mode(ctx)) { + case EVP_CIPH_STREAM_CIPHER: + case EVP_CIPH_ECB_MODE: + break; + + case EVP_CIPH_CFB_MODE: + ctx->num = 0; + /* fall-through */ + + case EVP_CIPH_CBC_MODE: + assert(EVP_CIPHER_CTX_iv_length(ctx) <= sizeof(ctx->iv)); + if (iv) { + memcpy(ctx->oiv, iv, EVP_CIPHER_CTX_iv_length(ctx)); + } + memcpy(ctx->iv, ctx->oiv, EVP_CIPHER_CTX_iv_length(ctx)); + break; + + case EVP_CIPH_CTR_MODE: + case EVP_CIPH_OFB_MODE: + ctx->num = 0; + /* Don't reuse IV for CTR mode */ + if (iv) { + memcpy(ctx->iv, iv, EVP_CIPHER_CTX_iv_length(ctx)); + } + break; + + default: + return 0; + } + } + + if (key || (ctx->cipher->flags & EVP_CIPH_ALWAYS_CALL_INIT)) { + if (!ctx->cipher->init(ctx, key, iv, enc)) { + return 0; + } + } + + ctx->buf_len = 0; + ctx->final_used = 0; + ctx->block_mask = ctx->cipher->block_size - 1; + return 1; +} + +int EVP_EncryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, + ENGINE *impl, const uint8_t *key, const uint8_t *iv) { + return EVP_CipherInit_ex(ctx, cipher, impl, key, iv, 1); +} + +int EVP_DecryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, + ENGINE *impl, const uint8_t *key, const uint8_t *iv) { + return EVP_CipherInit_ex(ctx, cipher, impl, key, iv, 0); +} + +int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, uint8_t *out, int *out_len, + const uint8_t *in, int in_len) { + int i, j, bl; + + if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) { + i = ctx->cipher->cipher(ctx, out, in, in_len); + if (i < 0) { + return 0; + } else { + *out_len = i; + } + return 1; + } + + if (in_len <= 0) { + *out_len = 0; + return in_len == 0; + } + + if (ctx->buf_len == 0 && (in_len & ctx->block_mask) == 0) { + if (ctx->cipher->cipher(ctx, out, in, in_len)) { + *out_len = in_len; + return 1; + } else { + *out_len = 0; + return 0; + } + } + + i = ctx->buf_len; + bl = ctx->cipher->block_size; + assert(bl <= (int)sizeof(ctx->buf)); + if (i != 0) { + if (bl - i > in_len) { + memcpy(&ctx->buf[i], in, in_len); + ctx->buf_len += in_len; + *out_len = 0; + return 1; + } else { + j = bl - i; + memcpy(&ctx->buf[i], in, j); + if (!ctx->cipher->cipher(ctx, out, ctx->buf, bl)) { + return 0; + } + in_len -= j; + in += j; + out += bl; + *out_len = bl; + } + } else { + *out_len = 0; + } + + i = in_len & ctx->block_mask; + in_len -= i; + if (in_len > 0) { + if (!ctx->cipher->cipher(ctx, out, in, in_len)) { + return 0; + } + *out_len += in_len; + } + + if (i != 0) { + memcpy(ctx->buf, &in[in_len], i); + } + ctx->buf_len = i; + return 1; +} + +int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, uint8_t *out, int *out_len) { + int n, ret; + unsigned int i, b, bl; + + if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) { + ret = ctx->cipher->cipher(ctx, out, NULL, 0); + if (ret < 0) { + return 0; + } else { + *out_len = ret; + } + return 1; + } + + b = ctx->cipher->block_size; + assert(b <= sizeof(ctx->buf)); + if (b == 1) { + *out_len = 0; + return 1; + } + + bl = ctx->buf_len; + if (ctx->flags & EVP_CIPH_NO_PADDING) { + if (bl) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH); + return 0; + } + *out_len = 0; + return 1; + } + + n = b - bl; + for (i = bl; i < b; i++) { + ctx->buf[i] = n; + } + ret = ctx->cipher->cipher(ctx, out, ctx->buf, b); + + if (ret) { + *out_len = b; + } + + return ret; +} + +int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, uint8_t *out, int *out_len, + const uint8_t *in, int in_len) { + int fix_len; + unsigned int b; + + if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) { + int r = ctx->cipher->cipher(ctx, out, in, in_len); + if (r < 0) { + *out_len = 0; + return 0; + } else { + *out_len = r; + } + return 1; + } + + if (in_len <= 0) { + *out_len = 0; + return in_len == 0; + } + + if (ctx->flags & EVP_CIPH_NO_PADDING) { + return EVP_EncryptUpdate(ctx, out, out_len, in, in_len); + } + + b = ctx->cipher->block_size; + assert(b <= sizeof(ctx->final)); + + if (ctx->final_used) { + memcpy(out, ctx->final, b); + out += b; + fix_len = 1; + } else { + fix_len = 0; + } + + if (!EVP_EncryptUpdate(ctx, out, out_len, in, in_len)) { + return 0; + } + + /* if we have 'decrypted' a multiple of block size, make sure + * we have a copy of this last block */ + if (b > 1 && !ctx->buf_len) { + *out_len -= b; + ctx->final_used = 1; + memcpy(ctx->final, &out[*out_len], b); + } else { + ctx->final_used = 0; + } + + if (fix_len) { + *out_len += b; + } + + return 1; +} + +int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *out_len) { + int i, n; + unsigned int b; + *out_len = 0; + + if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) { + i = ctx->cipher->cipher(ctx, out, NULL, 0); + if (i < 0) { + return 0; + } else { + *out_len = i; + } + return 1; + } + + b = ctx->cipher->block_size; + if (ctx->flags & EVP_CIPH_NO_PADDING) { + if (ctx->buf_len) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH); + return 0; + } + *out_len = 0; + return 1; + } + + if (b > 1) { + if (ctx->buf_len || !ctx->final_used) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_WRONG_FINAL_BLOCK_LENGTH); + return 0; + } + assert(b <= sizeof(ctx->final)); + + /* The following assumes that the ciphertext has been authenticated. + * Otherwise it provides a padding oracle. */ + n = ctx->final[b - 1]; + if (n == 0 || n > (int)b) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT); + return 0; + } + + for (i = 0; i < n; i++) { + if (ctx->final[--b] != n) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT); + return 0; + } + } + + n = ctx->cipher->block_size - n; + for (i = 0; i < n; i++) { + out[i] = ctx->final[i]; + } + *out_len = n; + } else { + *out_len = 0; + } + + return 1; +} + +int EVP_Cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in, + size_t in_len) { + return ctx->cipher->cipher(ctx, out, in, in_len); +} + +int EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, uint8_t *out, int *out_len, + const uint8_t *in, int in_len) { + if (ctx->encrypt) { + return EVP_EncryptUpdate(ctx, out, out_len, in, in_len); + } else { + return EVP_DecryptUpdate(ctx, out, out_len, in, in_len); + } +} + +int EVP_CipherFinal_ex(EVP_CIPHER_CTX *ctx, uint8_t *out, int *out_len) { + if (ctx->encrypt) { + return EVP_EncryptFinal_ex(ctx, out, out_len); + } else { + return EVP_DecryptFinal_ex(ctx, out, out_len); + } +} + +const EVP_CIPHER *EVP_CIPHER_CTX_cipher(const EVP_CIPHER_CTX *ctx) { + return ctx->cipher; +} + +int EVP_CIPHER_CTX_nid(const EVP_CIPHER_CTX *ctx) { + return ctx->cipher->nid; +} + +unsigned EVP_CIPHER_CTX_block_size(const EVP_CIPHER_CTX *ctx) { + return ctx->cipher->block_size; +} + +unsigned EVP_CIPHER_CTX_key_length(const EVP_CIPHER_CTX *ctx) { + return ctx->key_len; +} + +unsigned EVP_CIPHER_CTX_iv_length(const EVP_CIPHER_CTX *ctx) { + return ctx->cipher->iv_len; +} + +void *EVP_CIPHER_CTX_get_app_data(const EVP_CIPHER_CTX *ctx) { + return ctx->app_data; +} + +void EVP_CIPHER_CTX_set_app_data(EVP_CIPHER_CTX *ctx, void *data) { + ctx->app_data = data; +} + +uint32_t EVP_CIPHER_CTX_flags(const EVP_CIPHER_CTX *ctx) { + return ctx->cipher->flags & ~EVP_CIPH_MODE_MASK; +} + +uint32_t EVP_CIPHER_CTX_mode(const EVP_CIPHER_CTX *ctx) { + return ctx->cipher->flags & EVP_CIPH_MODE_MASK; +} + +int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int command, int arg, void *ptr) { + int ret; + if (!ctx->cipher) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_NO_CIPHER_SET); + return 0; + } + + if (!ctx->cipher->ctrl) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_CTRL_NOT_IMPLEMENTED); + return 0; + } + + ret = ctx->cipher->ctrl(ctx, command, arg, ptr); + if (ret == -1) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_CTRL_OPERATION_NOT_IMPLEMENTED); + return 0; + } + + return ret; +} + +int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *ctx, int pad) { + if (pad) { + ctx->flags &= ~EVP_CIPH_NO_PADDING; + } else { + ctx->flags |= EVP_CIPH_NO_PADDING; + } + return 1; +} + +int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *c, unsigned key_len) { + if (c->key_len == key_len) { + return 1; + } + + if (key_len == 0 || !(c->cipher->flags & EVP_CIPH_VARIABLE_LENGTH)) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_KEY_LENGTH); + return 0; + } + + c->key_len = key_len; + return 1; +} + +int EVP_CIPHER_nid(const EVP_CIPHER *cipher) { return cipher->nid; } + +unsigned EVP_CIPHER_block_size(const EVP_CIPHER *cipher) { + return cipher->block_size; +} + +unsigned EVP_CIPHER_key_length(const EVP_CIPHER *cipher) { + return cipher->key_len; +} + +unsigned EVP_CIPHER_iv_length(const EVP_CIPHER *cipher) { + return cipher->iv_len; +} + +uint32_t EVP_CIPHER_flags(const EVP_CIPHER *cipher) { + return cipher->flags & ~EVP_CIPH_MODE_MASK; +} + +uint32_t EVP_CIPHER_mode(const EVP_CIPHER *cipher) { + return cipher->flags & EVP_CIPH_MODE_MASK; +} + +int EVP_CipherInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, + const uint8_t *key, const uint8_t *iv, int enc) { + if (cipher) { + EVP_CIPHER_CTX_init(ctx); + } + return EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, enc); +} + +int EVP_EncryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, + const uint8_t *key, const uint8_t *iv) { + return EVP_CipherInit(ctx, cipher, key, iv, 1); +} + +int EVP_DecryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, + const uint8_t *key, const uint8_t *iv) { + return EVP_CipherInit(ctx, cipher, key, iv, 0); +} + +int EVP_add_cipher_alias(const char *a, const char *b) { + return 1; +} + +const EVP_CIPHER *EVP_get_cipherbyname(const char *name) { + if (OPENSSL_strcasecmp(name, "rc4") == 0) { + return EVP_rc4(); + } else if (OPENSSL_strcasecmp(name, "des-cbc") == 0) { + return EVP_des_cbc(); + } else if (OPENSSL_strcasecmp(name, "des-ede3-cbc") == 0 || + OPENSSL_strcasecmp(name, "3des") == 0) { + return EVP_des_ede3_cbc(); + } else if (OPENSSL_strcasecmp(name, "aes-128-cbc") == 0) { + return EVP_aes_128_cbc(); + } else if (OPENSSL_strcasecmp(name, "aes-256-cbc") == 0) { + return EVP_aes_256_cbc(); + } else if (OPENSSL_strcasecmp(name, "aes-128-ctr") == 0) { + return EVP_aes_128_ctr(); + } else if (OPENSSL_strcasecmp(name, "aes-256-ctr") == 0) { + return EVP_aes_256_ctr(); + } else if (OPENSSL_strcasecmp(name, "aes-128-ecb") == 0) { + return EVP_aes_128_ecb(); + } else if (OPENSSL_strcasecmp(name, "aes-256-ecb") == 0) { + return EVP_aes_256_ecb(); + } + + return NULL; +} diff --git a/external/boringssl/crypto/cipher/cipher_test.cc b/external/boringssl/crypto/cipher/cipher_test.cc new file mode 100644 index 0000000000..fa384c69ea --- /dev/null +++ b/external/boringssl/crypto/cipher/cipher_test.cc @@ -0,0 +1,296 @@ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project. + */ +/* ==================================================================== + * Copyright (c) 2015 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ + +#include +#include + +#include +#include + +#include +#include +#include + +#include "../test/file_test.h" +#include "../test/scoped_types.h" + + +static const EVP_CIPHER *GetCipher(const std::string &name) { + if (name == "DES-CBC") { + return EVP_des_cbc(); + } else if (name == "DES-ECB") { + return EVP_des_ecb(); + } else if (name == "DES-EDE") { + return EVP_des_ede(); + } else if (name == "DES-EDE-CBC") { + return EVP_des_ede_cbc(); + } else if (name == "DES-EDE3-CBC") { + return EVP_des_ede3_cbc(); + } else if (name == "RC4") { + return EVP_rc4(); + } else if (name == "AES-128-ECB") { + return EVP_aes_128_ecb(); + } else if (name == "AES-256-ECB") { + return EVP_aes_256_ecb(); + } else if (name == "AES-128-CBC") { + return EVP_aes_128_cbc(); + } else if (name == "AES-128-GCM") { + return EVP_aes_128_gcm(); + } else if (name == "AES-128-OFB") { + return EVP_aes_128_ofb(); + } else if (name == "AES-192-CBC") { + return EVP_aes_192_cbc(); + } else if (name == "AES-192-ECB") { + return EVP_aes_192_ecb(); + } else if (name == "AES-256-CBC") { + return EVP_aes_256_cbc(); + } else if (name == "AES-128-CTR") { + return EVP_aes_128_ctr(); + } else if (name == "AES-256-CTR") { + return EVP_aes_256_ctr(); + } else if (name == "AES-256-GCM") { + return EVP_aes_256_gcm(); + } else if (name == "AES-256-OFB") { + return EVP_aes_256_ofb(); + } + return nullptr; +} + +static bool TestOperation(FileTest *t, + const EVP_CIPHER *cipher, + bool encrypt, + size_t chunk_size, + const std::vector &key, + const std::vector &iv, + const std::vector &plaintext, + const std::vector &ciphertext, + const std::vector &aad, + const std::vector &tag) { + const std::vector *in, *out; + if (encrypt) { + in = &plaintext; + out = &ciphertext; + } else { + in = &ciphertext; + out = &plaintext; + } + + bool is_aead = EVP_CIPHER_mode(cipher) == EVP_CIPH_GCM_MODE; + + ScopedEVP_CIPHER_CTX ctx; + if (!EVP_CipherInit_ex(ctx.get(), cipher, nullptr, nullptr, nullptr, + encrypt ? 1 : 0)) { + return false; + } + if (t->HasAttribute("IV")) { + if (is_aead) { + if (!EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_SET_IVLEN, + iv.size(), 0)) { + return false; + } + } else if (iv.size() != EVP_CIPHER_CTX_iv_length(ctx.get())) { + t->PrintLine("Bad IV length."); + return false; + } + } + if (is_aead && !encrypt && + !EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_SET_TAG, tag.size(), + const_cast(tag.data()))) { + return false; + } + // The ciphers are run with no padding. For each of the ciphers we test, the + // output size matches the input size. + std::vector result(in->size()); + if (in->size() != out->size()) { + t->PrintLine("Input/output size mismatch (%u vs %u).", (unsigned)in->size(), + (unsigned)out->size()); + return false; + } + // Note: the deprecated |EVP_CIPHER|-based AES-GCM API is sensitive to whether + // parameters are NULL, so it is important to skip the |in| and |aad| + // |EVP_CipherUpdate| calls when empty. + int unused, result_len1 = 0, result_len2; + if (!EVP_CIPHER_CTX_set_key_length(ctx.get(), key.size()) || + !EVP_CipherInit_ex(ctx.get(), nullptr, nullptr, key.data(), iv.data(), + -1) || + (!aad.empty() && + !EVP_CipherUpdate(ctx.get(), nullptr, &unused, aad.data(), + aad.size())) || + !EVP_CIPHER_CTX_set_padding(ctx.get(), 0)) { + t->PrintLine("Operation failed."); + return false; + } + if (chunk_size != 0) { + for (size_t i = 0; i < in->size();) { + size_t todo = chunk_size; + if (i + todo > in->size()) { + todo = in->size() - i; + } + + int len; + if (!EVP_CipherUpdate(ctx.get(), result.data() + result_len1, &len, + in->data() + i, todo)) { + t->PrintLine("Operation failed."); + return false; + } + result_len1 += len; + i += todo; + } + } else if (!in->empty() && + !EVP_CipherUpdate(ctx.get(), result.data(), &result_len1, + in->data(), in->size())) { + t->PrintLine("Operation failed."); + return false; + } + if (!EVP_CipherFinal_ex(ctx.get(), result.data() + result_len1, + &result_len2)) { + t->PrintLine("Operation failed."); + return false; + } + result.resize(result_len1 + result_len2); + if (!t->ExpectBytesEqual(out->data(), out->size(), result.data(), + result.size())) { + return false; + } + if (encrypt && is_aead) { + uint8_t rtag[16]; + if (tag.size() > sizeof(rtag)) { + t->PrintLine("Bad tag length."); + return false; + } + if (!EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_GET_TAG, tag.size(), + rtag) || + !t->ExpectBytesEqual(tag.data(), tag.size(), rtag, + tag.size())) { + return false; + } + } + return true; +} + +static bool TestCipher(FileTest *t, void *arg) { + std::string cipher_str; + if (!t->GetAttribute(&cipher_str, "Cipher")) { + return false; + } + const EVP_CIPHER *cipher = GetCipher(cipher_str); + if (cipher == nullptr) { + t->PrintLine("Unknown cipher: '%s'.", cipher_str.c_str()); + return false; + } + + std::vector key, iv, plaintext, ciphertext, aad, tag; + if (!t->GetBytes(&key, "Key") || + !t->GetBytes(&plaintext, "Plaintext") || + !t->GetBytes(&ciphertext, "Ciphertext")) { + return false; + } + if (EVP_CIPHER_iv_length(cipher) > 0 && + !t->GetBytes(&iv, "IV")) { + return false; + } + if (EVP_CIPHER_mode(cipher) == EVP_CIPH_GCM_MODE) { + if (!t->GetBytes(&aad, "AAD") || + !t->GetBytes(&tag, "Tag")) { + return false; + } + } + + enum { + kEncrypt, + kDecrypt, + kBoth, + } operation = kBoth; + if (t->HasAttribute("Operation")) { + const std::string &str = t->GetAttributeOrDie("Operation"); + if (str == "ENCRYPT") { + operation = kEncrypt; + } else if (str == "DECRYPT") { + operation = kDecrypt; + } else { + t->PrintLine("Unknown operation: '%s'.", str.c_str()); + return false; + } + } + + const std::vector chunk_sizes = {0, 1, 2, 5, 7, 8, 9, 15, 16, + 17, 31, 32, 33, 63, 64, 65, 512}; + + for (size_t chunk_size : chunk_sizes) { + // By default, both directions are run, unless overridden by the operation. + if (operation != kDecrypt && + !TestOperation(t, cipher, true /* encrypt */, chunk_size, key, iv, + plaintext, ciphertext, aad, tag)) { + return false; + } + + if (operation != kEncrypt && + !TestOperation(t, cipher, false /* decrypt */, chunk_size, key, iv, + plaintext, ciphertext, aad, tag)) { + return false; + } + } + + return true; +} + +int main(int argc, char **argv) { + CRYPTO_library_init(); + + if (argc != 2) { + fprintf(stderr, "%s \n", argv[0]); + return 1; + } + + return FileTestMain(TestCipher, nullptr, argv[1]); +} diff --git a/external/boringssl/crypto/cipher/derive_key.c b/external/boringssl/crypto/cipher/derive_key.c new file mode 100644 index 0000000000..9e1634ab96 --- /dev/null +++ b/external/boringssl/crypto/cipher/derive_key.c @@ -0,0 +1,154 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include +#include + +#include "internal.h" + + +#define PKCS5_SALT_LEN 8 + +int EVP_BytesToKey(const EVP_CIPHER *type, const EVP_MD *md, + const uint8_t *salt, const uint8_t *data, size_t data_len, + unsigned count, uint8_t *key, uint8_t *iv) { + EVP_MD_CTX c; + uint8_t md_buf[EVP_MAX_MD_SIZE]; + unsigned niv, nkey, addmd = 0; + unsigned mds = 0, i; + int rv = 0; + + nkey = type->key_len; + niv = type->iv_len; + + assert(nkey <= EVP_MAX_KEY_LENGTH); + assert(niv <= EVP_MAX_IV_LENGTH); + + if (data == NULL) { + return nkey; + } + + EVP_MD_CTX_init(&c); + for (;;) { + if (!EVP_DigestInit_ex(&c, md, NULL)) { + return 0; + } + if (addmd++) { + if (!EVP_DigestUpdate(&c, md_buf, mds)) { + goto err; + } + } + if (!EVP_DigestUpdate(&c, data, data_len)) { + goto err; + } + if (salt != NULL) { + if (!EVP_DigestUpdate(&c, salt, PKCS5_SALT_LEN)) { + goto err; + } + } + if (!EVP_DigestFinal_ex(&c, md_buf, &mds)) { + goto err; + } + + for (i = 1; i < count; i++) { + if (!EVP_DigestInit_ex(&c, md, NULL) || + !EVP_DigestUpdate(&c, md_buf, mds) || + !EVP_DigestFinal_ex(&c, md_buf, &mds)) { + goto err; + } + } + + i = 0; + if (nkey) { + for (;;) { + if (nkey == 0 || i == mds) { + break; + } + if (key != NULL) { + *(key++) = md_buf[i]; + } + nkey--; + i++; + } + } + + if (niv && i != mds) { + for (;;) { + if (niv == 0 || i == mds) { + break; + } + if (iv != NULL) { + *(iv++) = md_buf[i]; + } + niv--; + i++; + } + } + if (nkey == 0 && niv == 0) { + break; + } + } + rv = type->key_len; + +err: + EVP_MD_CTX_cleanup(&c); + OPENSSL_cleanse(md_buf, EVP_MAX_MD_SIZE); + return rv; +} diff --git a/external/boringssl/crypto/cipher/e_aes.c b/external/boringssl/crypto/cipher/e_aes.c new file mode 100644 index 0000000000..24c4d8a3ba --- /dev/null +++ b/external/boringssl/crypto/cipher/e_aes.c @@ -0,0 +1,1715 @@ +/* ==================================================================== + * Copyright (c) 2001-2011 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "internal.h" +#include "../internal.h" +#include "../modes/internal.h" + +#if defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64) +#include +#endif + + +OPENSSL_MSVC_PRAGMA(warning(disable: 4702)) /* Unreachable code. */ + +typedef struct { + union { + double align; + AES_KEY ks; + } ks; + block128_f block; + union { + cbc128_f cbc; + ctr128_f ctr; + } stream; +} EVP_AES_KEY; + +typedef struct { + union { + double align; + AES_KEY ks; + } ks; /* AES key schedule to use */ + int key_set; /* Set if key initialised */ + int iv_set; /* Set if an iv is set */ + GCM128_CONTEXT gcm; + uint8_t *iv; /* Temporary IV store */ + int ivlen; /* IV length */ + int taglen; + int iv_gen; /* It is OK to generate IVs */ + ctr128_f ctr; +} EVP_AES_GCM_CTX; + +#if !defined(OPENSSL_NO_ASM) && \ + (defined(OPENSSL_X86_64) || defined(OPENSSL_X86)) +#define VPAES +static char vpaes_capable(void) { + return (OPENSSL_ia32cap_P[1] & (1 << (41 - 32))) != 0; +} + +#if defined(OPENSSL_X86_64) +#define BSAES +static char bsaes_capable(void) { + return vpaes_capable(); +} +#endif + +#elif !defined(OPENSSL_NO_ASM) && \ + (defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)) + +#if defined(OPENSSL_ARM) && __ARM_MAX_ARCH__ >= 7 +#define BSAES +static char bsaes_capable(void) { + return CRYPTO_is_NEON_capable(); +} +#endif + +#define HWAES +static int hwaes_capable(void) { + return CRYPTO_is_ARMv8_AES_capable(); +} + +int aes_v8_set_encrypt_key(const uint8_t *user_key, const int bits, + AES_KEY *key); +int aes_v8_set_decrypt_key(const uint8_t *user_key, const int bits, + AES_KEY *key); +void aes_v8_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key); +void aes_v8_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key); +void aes_v8_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t length, + const AES_KEY *key, uint8_t *ivec, const int enc); +void aes_v8_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out, size_t len, + const AES_KEY *key, const uint8_t ivec[16]); + +#endif /* OPENSSL_ARM */ + +#if defined(BSAES) +/* On platforms where BSAES gets defined (just above), then these functions are + * provided by asm. */ +void bsaes_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t length, + const AES_KEY *key, uint8_t ivec[16], int enc); +void bsaes_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out, size_t len, + const AES_KEY *key, const uint8_t ivec[16]); +#else +static char bsaes_capable(void) { + return 0; +} + +/* On other platforms, bsaes_capable() will always return false and so the + * following will never be called. */ +static void bsaes_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t length, + const AES_KEY *key, uint8_t ivec[16], int enc) { + abort(); +} + +static void bsaes_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out, + size_t len, const AES_KEY *key, + const uint8_t ivec[16]) { + abort(); +} +#endif + +#if defined(VPAES) +/* On platforms where VPAES gets defined (just above), then these functions are + * provided by asm. */ +int vpaes_set_encrypt_key(const uint8_t *userKey, int bits, AES_KEY *key); +int vpaes_set_decrypt_key(const uint8_t *userKey, int bits, AES_KEY *key); + +void vpaes_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key); +void vpaes_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key); + +void vpaes_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t length, + const AES_KEY *key, uint8_t *ivec, int enc); +#else +static char vpaes_capable(void) { + return 0; +} + +/* On other platforms, vpaes_capable() will always return false and so the + * following will never be called. */ +static int vpaes_set_encrypt_key(const uint8_t *userKey, int bits, + AES_KEY *key) { + abort(); +} +static int vpaes_set_decrypt_key(const uint8_t *userKey, int bits, + AES_KEY *key) { + abort(); +} +static void vpaes_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) { + abort(); +} +static void vpaes_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) { + abort(); +} +static void vpaes_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t length, + const AES_KEY *key, uint8_t *ivec, int enc) { + abort(); +} +#endif + +#if !defined(HWAES) +/* If HWAES isn't defined then we provide dummy functions for each of the hwaes + * functions. */ +static int hwaes_capable(void) { + return 0; +} + +static int aes_v8_set_encrypt_key(const uint8_t *user_key, int bits, + AES_KEY *key) { + abort(); +} + +static int aes_v8_set_decrypt_key(const uint8_t *user_key, int bits, + AES_KEY *key) { + abort(); +} + +static void aes_v8_encrypt(const uint8_t *in, uint8_t *out, + const AES_KEY *key) { + abort(); +} + +static void aes_v8_decrypt(const uint8_t *in, uint8_t *out, + const AES_KEY *key) { + abort(); +} + +static void aes_v8_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t length, + const AES_KEY *key, uint8_t *ivec, int enc) { + abort(); +} + +static void aes_v8_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out, + size_t len, const AES_KEY *key, + const uint8_t ivec[16]) { + abort(); +} +#endif + +#if !defined(OPENSSL_NO_ASM) && \ + (defined(OPENSSL_X86_64) || defined(OPENSSL_X86)) +int aesni_set_encrypt_key(const uint8_t *userKey, int bits, AES_KEY *key); +int aesni_set_decrypt_key(const uint8_t *userKey, int bits, AES_KEY *key); + +void aesni_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key); +void aesni_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key); + +void aesni_ecb_encrypt(const uint8_t *in, uint8_t *out, size_t length, + const AES_KEY *key, int enc); +void aesni_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t length, + const AES_KEY *key, uint8_t *ivec, int enc); + +#else + +/* On other platforms, aesni_capable() will always return false and so the + * following will never be called. */ +static void aesni_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) { + abort(); +} +static int aesni_set_encrypt_key(const uint8_t *userKey, int bits, + AES_KEY *key) { + abort(); +} +static void aesni_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out, + size_t blocks, const void *key, + const uint8_t *ivec) { + abort(); +} + +#endif + +static int aes_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key, + const uint8_t *iv, int enc) { + int ret, mode; + EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data; + + mode = ctx->cipher->flags & EVP_CIPH_MODE_MASK; + if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE) && !enc) { + if (hwaes_capable()) { + ret = aes_v8_set_decrypt_key(key, ctx->key_len * 8, &dat->ks.ks); + dat->block = (block128_f)aes_v8_decrypt; + dat->stream.cbc = NULL; + if (mode == EVP_CIPH_CBC_MODE) { + dat->stream.cbc = (cbc128_f)aes_v8_cbc_encrypt; + } + } else if (bsaes_capable() && mode == EVP_CIPH_CBC_MODE) { + ret = AES_set_decrypt_key(key, ctx->key_len * 8, &dat->ks.ks); + dat->block = (block128_f)AES_decrypt; + dat->stream.cbc = (cbc128_f)bsaes_cbc_encrypt; + } else if (vpaes_capable()) { + ret = vpaes_set_decrypt_key(key, ctx->key_len * 8, &dat->ks.ks); + dat->block = (block128_f)vpaes_decrypt; + dat->stream.cbc = + mode == EVP_CIPH_CBC_MODE ? (cbc128_f)vpaes_cbc_encrypt : NULL; + } else { + ret = AES_set_decrypt_key(key, ctx->key_len * 8, &dat->ks.ks); + dat->block = (block128_f)AES_decrypt; + dat->stream.cbc = + mode == EVP_CIPH_CBC_MODE ? (cbc128_f)AES_cbc_encrypt : NULL; + } + } else if (hwaes_capable()) { + ret = aes_v8_set_encrypt_key(key, ctx->key_len * 8, &dat->ks.ks); + dat->block = (block128_f)aes_v8_encrypt; + dat->stream.cbc = NULL; + if (mode == EVP_CIPH_CBC_MODE) { + dat->stream.cbc = (cbc128_f)aes_v8_cbc_encrypt; + } else if (mode == EVP_CIPH_CTR_MODE) { + dat->stream.ctr = (ctr128_f)aes_v8_ctr32_encrypt_blocks; + } + } else if (bsaes_capable() && mode == EVP_CIPH_CTR_MODE) { + ret = AES_set_encrypt_key(key, ctx->key_len * 8, &dat->ks.ks); + dat->block = (block128_f)AES_encrypt; + dat->stream.ctr = (ctr128_f)bsaes_ctr32_encrypt_blocks; + } else if (vpaes_capable()) { + ret = vpaes_set_encrypt_key(key, ctx->key_len * 8, &dat->ks.ks); + dat->block = (block128_f)vpaes_encrypt; + dat->stream.cbc = + mode == EVP_CIPH_CBC_MODE ? (cbc128_f)vpaes_cbc_encrypt : NULL; + } else { + ret = AES_set_encrypt_key(key, ctx->key_len * 8, &dat->ks.ks); + dat->block = (block128_f)AES_encrypt; + dat->stream.cbc = + mode == EVP_CIPH_CBC_MODE ? (cbc128_f)AES_cbc_encrypt : NULL; + } + + if (ret < 0) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_AES_KEY_SETUP_FAILED); + return 0; + } + + return 1; +} + +static int aes_cbc_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in, + size_t len) { + EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data; + + if (dat->stream.cbc) { + (*dat->stream.cbc)(in, out, len, &dat->ks, ctx->iv, ctx->encrypt); + } else if (ctx->encrypt) { + CRYPTO_cbc128_encrypt(in, out, len, &dat->ks, ctx->iv, dat->block); + } else { + CRYPTO_cbc128_decrypt(in, out, len, &dat->ks, ctx->iv, dat->block); + } + + return 1; +} + +static int aes_ecb_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in, + size_t len) { + size_t bl = ctx->cipher->block_size; + size_t i; + EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data; + + if (len < bl) { + return 1; + } + + for (i = 0, len -= bl; i <= len; i += bl) { + (*dat->block)(in + i, out + i, &dat->ks); + } + + return 1; +} + +static int aes_ctr_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in, + size_t len) { + EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data; + + if (dat->stream.ctr) { + CRYPTO_ctr128_encrypt_ctr32(in, out, len, &dat->ks, ctx->iv, ctx->buf, + &ctx->num, dat->stream.ctr); + } else { + CRYPTO_ctr128_encrypt(in, out, len, &dat->ks, ctx->iv, ctx->buf, &ctx->num, + dat->block); + } + return 1; +} + +static int aes_ofb_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in, + size_t len) { + EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data; + + CRYPTO_ofb128_encrypt(in, out, len, &dat->ks, ctx->iv, &ctx->num, dat->block); + return 1; +} + +static char aesni_capable(void); + +static ctr128_f aes_ctr_set_key(AES_KEY *aes_key, GCM128_CONTEXT *gcm_ctx, + block128_f *out_block, const uint8_t *key, + size_t key_len) { + if (aesni_capable()) { + aesni_set_encrypt_key(key, key_len * 8, aes_key); + if (gcm_ctx != NULL) { + CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)aesni_encrypt); + } + if (out_block) { + *out_block = (block128_f) aesni_encrypt; + } + return (ctr128_f)aesni_ctr32_encrypt_blocks; + } + + if (hwaes_capable()) { + aes_v8_set_encrypt_key(key, key_len * 8, aes_key); + if (gcm_ctx != NULL) { + CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)aes_v8_encrypt); + } + if (out_block) { + *out_block = (block128_f) aes_v8_encrypt; + } + return (ctr128_f)aes_v8_ctr32_encrypt_blocks; + } + + if (bsaes_capable()) { + AES_set_encrypt_key(key, key_len * 8, aes_key); + if (gcm_ctx != NULL) { + CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)AES_encrypt); + } + if (out_block) { + *out_block = (block128_f) AES_encrypt; + } + return (ctr128_f)bsaes_ctr32_encrypt_blocks; + } + + if (vpaes_capable()) { + vpaes_set_encrypt_key(key, key_len * 8, aes_key); + if (out_block) { + *out_block = (block128_f) vpaes_encrypt; + } + if (gcm_ctx != NULL) { + CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)vpaes_encrypt); + } + return NULL; + } + + AES_set_encrypt_key(key, key_len * 8, aes_key); + if (gcm_ctx != NULL) { + CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)AES_encrypt); + } + if (out_block) { + *out_block = (block128_f) AES_encrypt; + } + return NULL; +} + +static int aes_gcm_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key, + const uint8_t *iv, int enc) { + EVP_AES_GCM_CTX *gctx = ctx->cipher_data; + if (!iv && !key) { + return 1; + } + if (key) { + gctx->ctr = + aes_ctr_set_key(&gctx->ks.ks, &gctx->gcm, NULL, key, ctx->key_len); + /* If we have an iv can set it directly, otherwise use saved IV. */ + if (iv == NULL && gctx->iv_set) { + iv = gctx->iv; + } + if (iv) { + CRYPTO_gcm128_setiv(&gctx->gcm, &gctx->ks.ks, iv, gctx->ivlen); + gctx->iv_set = 1; + } + gctx->key_set = 1; + } else { + /* If key set use IV, otherwise copy */ + if (gctx->key_set) { + CRYPTO_gcm128_setiv(&gctx->gcm, &gctx->ks.ks, iv, gctx->ivlen); + } else { + memcpy(gctx->iv, iv, gctx->ivlen); + } + gctx->iv_set = 1; + gctx->iv_gen = 0; + } + return 1; +} + +static void aes_gcm_cleanup(EVP_CIPHER_CTX *c) { + EVP_AES_GCM_CTX *gctx = c->cipher_data; + OPENSSL_cleanse(&gctx->gcm, sizeof(gctx->gcm)); + if (gctx->iv != c->iv) { + OPENSSL_free(gctx->iv); + } +} + +/* increment counter (64-bit int) by 1 */ +static void ctr64_inc(uint8_t *counter) { + int n = 8; + uint8_t c; + + do { + --n; + c = counter[n]; + ++c; + counter[n] = c; + if (c) { + return; + } + } while (n); +} + +static int aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) { + EVP_AES_GCM_CTX *gctx = c->cipher_data; + switch (type) { + case EVP_CTRL_INIT: + gctx->key_set = 0; + gctx->iv_set = 0; + gctx->ivlen = c->cipher->iv_len; + gctx->iv = c->iv; + gctx->taglen = -1; + gctx->iv_gen = 0; + return 1; + + case EVP_CTRL_GCM_SET_IVLEN: + if (arg <= 0) { + return 0; + } + + /* Allocate memory for IV if needed */ + if (arg > EVP_MAX_IV_LENGTH && arg > gctx->ivlen) { + if (gctx->iv != c->iv) { + OPENSSL_free(gctx->iv); + } + gctx->iv = OPENSSL_malloc(arg); + if (!gctx->iv) { + return 0; + } + } + gctx->ivlen = arg; + return 1; + + case EVP_CTRL_GCM_SET_TAG: + if (arg <= 0 || arg > 16 || c->encrypt) { + return 0; + } + memcpy(c->buf, ptr, arg); + gctx->taglen = arg; + return 1; + + case EVP_CTRL_GCM_GET_TAG: + if (arg <= 0 || arg > 16 || !c->encrypt || gctx->taglen < 0) { + return 0; + } + memcpy(ptr, c->buf, arg); + return 1; + + case EVP_CTRL_GCM_SET_IV_FIXED: + /* Special case: -1 length restores whole IV */ + if (arg == -1) { + memcpy(gctx->iv, ptr, gctx->ivlen); + gctx->iv_gen = 1; + return 1; + } + /* Fixed field must be at least 4 bytes and invocation field + * at least 8. */ + if (arg < 4 || (gctx->ivlen - arg) < 8) { + return 0; + } + if (arg) { + memcpy(gctx->iv, ptr, arg); + } + if (c->encrypt && !RAND_bytes(gctx->iv + arg, gctx->ivlen - arg)) { + return 0; + } + gctx->iv_gen = 1; + return 1; + + case EVP_CTRL_GCM_IV_GEN: + if (gctx->iv_gen == 0 || gctx->key_set == 0) { + return 0; + } + CRYPTO_gcm128_setiv(&gctx->gcm, &gctx->ks.ks, gctx->iv, gctx->ivlen); + if (arg <= 0 || arg > gctx->ivlen) { + arg = gctx->ivlen; + } + memcpy(ptr, gctx->iv + gctx->ivlen - arg, arg); + /* Invocation field will be at least 8 bytes in size and + * so no need to check wrap around or increment more than + * last 8 bytes. */ + ctr64_inc(gctx->iv + gctx->ivlen - 8); + gctx->iv_set = 1; + return 1; + + case EVP_CTRL_GCM_SET_IV_INV: + if (gctx->iv_gen == 0 || gctx->key_set == 0 || c->encrypt) { + return 0; + } + memcpy(gctx->iv + gctx->ivlen - arg, ptr, arg); + CRYPTO_gcm128_setiv(&gctx->gcm, &gctx->ks.ks, gctx->iv, gctx->ivlen); + gctx->iv_set = 1; + return 1; + + case EVP_CTRL_COPY: { + EVP_CIPHER_CTX *out = ptr; + EVP_AES_GCM_CTX *gctx_out = out->cipher_data; + if (gctx->iv == c->iv) { + gctx_out->iv = out->iv; + } else { + gctx_out->iv = OPENSSL_malloc(gctx->ivlen); + if (!gctx_out->iv) { + return 0; + } + memcpy(gctx_out->iv, gctx->iv, gctx->ivlen); + } + return 1; + } + + default: + return -1; + } +} + +static int aes_gcm_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in, + size_t len) { + EVP_AES_GCM_CTX *gctx = ctx->cipher_data; + + /* If not set up, return error */ + if (!gctx->key_set) { + return -1; + } + if (!gctx->iv_set) { + return -1; + } + + if (in) { + if (out == NULL) { + if (!CRYPTO_gcm128_aad(&gctx->gcm, in, len)) { + return -1; + } + } else if (ctx->encrypt) { + if (gctx->ctr) { + if (!CRYPTO_gcm128_encrypt_ctr32(&gctx->gcm, &gctx->ks.ks, in, out, len, + gctx->ctr)) { + return -1; + } + } else { + if (!CRYPTO_gcm128_encrypt(&gctx->gcm, &gctx->ks.ks, in, out, len)) { + return -1; + } + } + } else { + if (gctx->ctr) { + if (!CRYPTO_gcm128_decrypt_ctr32(&gctx->gcm, &gctx->ks.ks, in, out, len, + gctx->ctr)) { + return -1; + } + } else { + if (!CRYPTO_gcm128_decrypt(&gctx->gcm, &gctx->ks.ks, in, out, len)) { + return -1; + } + } + } + return len; + } else { + if (!ctx->encrypt) { + if (gctx->taglen < 0 || + !CRYPTO_gcm128_finish(&gctx->gcm, ctx->buf, gctx->taglen)) { + return -1; + } + gctx->iv_set = 0; + return 0; + } + CRYPTO_gcm128_tag(&gctx->gcm, ctx->buf, 16); + gctx->taglen = 16; + /* Don't reuse the IV */ + gctx->iv_set = 0; + return 0; + } +} + +static const EVP_CIPHER aes_128_cbc = { + NID_aes_128_cbc, 16 /* block_size */, 16 /* key_size */, + 16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_CBC_MODE, + NULL /* app_data */, aes_init_key, aes_cbc_cipher, + NULL /* cleanup */, NULL /* ctrl */}; + +static const EVP_CIPHER aes_128_ctr = { + NID_aes_128_ctr, 1 /* block_size */, 16 /* key_size */, + 16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_CTR_MODE, + NULL /* app_data */, aes_init_key, aes_ctr_cipher, + NULL /* cleanup */, NULL /* ctrl */}; + +static const EVP_CIPHER aes_128_ecb = { + NID_aes_128_ecb, 16 /* block_size */, 16 /* key_size */, + 0 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_ECB_MODE, + NULL /* app_data */, aes_init_key, aes_ecb_cipher, + NULL /* cleanup */, NULL /* ctrl */}; + +static const EVP_CIPHER aes_128_ofb = { + NID_aes_128_ofb128, 1 /* block_size */, 16 /* key_size */, + 16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_OFB_MODE, + NULL /* app_data */, aes_init_key, aes_ofb_cipher, + NULL /* cleanup */, NULL /* ctrl */}; + +static const EVP_CIPHER aes_128_gcm = { + NID_aes_128_gcm, 1 /* block_size */, 16 /* key_size */, 12 /* iv_len */, + sizeof(EVP_AES_GCM_CTX), + EVP_CIPH_GCM_MODE | EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER | + EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT | + EVP_CIPH_FLAG_AEAD_CIPHER, + NULL /* app_data */, aes_gcm_init_key, aes_gcm_cipher, aes_gcm_cleanup, + aes_gcm_ctrl}; + + +static const EVP_CIPHER aes_192_cbc = { + NID_aes_192_cbc, 16 /* block_size */, 24 /* key_size */, + 16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_CBC_MODE, + NULL /* app_data */, aes_init_key, aes_cbc_cipher, + NULL /* cleanup */, NULL /* ctrl */}; + +static const EVP_CIPHER aes_192_ctr = { + NID_aes_192_ctr, 1 /* block_size */, 24 /* key_size */, + 16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_CTR_MODE, + NULL /* app_data */, aes_init_key, aes_ctr_cipher, + NULL /* cleanup */, NULL /* ctrl */}; + +static const EVP_CIPHER aes_192_ecb = { + NID_aes_192_ecb, 16 /* block_size */, 24 /* key_size */, + 0 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_ECB_MODE, + NULL /* app_data */, aes_init_key, aes_ecb_cipher, + NULL /* cleanup */, NULL /* ctrl */}; + +static const EVP_CIPHER aes_192_gcm = { + NID_aes_192_gcm, 1 /* block_size */, 24 /* key_size */, 12 /* iv_len */, + sizeof(EVP_AES_GCM_CTX), + EVP_CIPH_GCM_MODE | EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER | + EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT | + EVP_CIPH_FLAG_AEAD_CIPHER, + NULL /* app_data */, aes_gcm_init_key, aes_gcm_cipher, aes_gcm_cleanup, + aes_gcm_ctrl}; + + +static const EVP_CIPHER aes_256_cbc = { + NID_aes_256_cbc, 16 /* block_size */, 32 /* key_size */, + 16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_CBC_MODE, + NULL /* app_data */, aes_init_key, aes_cbc_cipher, + NULL /* cleanup */, NULL /* ctrl */}; + +static const EVP_CIPHER aes_256_ctr = { + NID_aes_256_ctr, 1 /* block_size */, 32 /* key_size */, + 16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_CTR_MODE, + NULL /* app_data */, aes_init_key, aes_ctr_cipher, + NULL /* cleanup */, NULL /* ctrl */}; + +static const EVP_CIPHER aes_256_ecb = { + NID_aes_256_ecb, 16 /* block_size */, 32 /* key_size */, + 0 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_ECB_MODE, + NULL /* app_data */, aes_init_key, aes_ecb_cipher, + NULL /* cleanup */, NULL /* ctrl */}; + +static const EVP_CIPHER aes_256_ofb = { + NID_aes_256_ofb128, 1 /* block_size */, 32 /* key_size */, + 16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_OFB_MODE, + NULL /* app_data */, aes_init_key, aes_ofb_cipher, + NULL /* cleanup */, NULL /* ctrl */}; + +static const EVP_CIPHER aes_256_gcm = { + NID_aes_256_gcm, 1 /* block_size */, 32 /* key_size */, 12 /* iv_len */, + sizeof(EVP_AES_GCM_CTX), + EVP_CIPH_GCM_MODE | EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER | + EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT | + EVP_CIPH_FLAG_AEAD_CIPHER, + NULL /* app_data */, aes_gcm_init_key, aes_gcm_cipher, aes_gcm_cleanup, + aes_gcm_ctrl}; + +#if !defined(OPENSSL_NO_ASM) && \ + (defined(OPENSSL_X86_64) || defined(OPENSSL_X86)) + +/* AES-NI section. */ + +static char aesni_capable(void) { + return (OPENSSL_ia32cap_P[1] & (1 << (57 - 32))) != 0; +} + +static int aesni_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key, + const uint8_t *iv, int enc) { + int ret, mode; + EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data; + + mode = ctx->cipher->flags & EVP_CIPH_MODE_MASK; + if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE) && !enc) { + ret = aesni_set_decrypt_key(key, ctx->key_len * 8, ctx->cipher_data); + dat->block = (block128_f)aesni_decrypt; + dat->stream.cbc = + mode == EVP_CIPH_CBC_MODE ? (cbc128_f)aesni_cbc_encrypt : NULL; + } else { + ret = aesni_set_encrypt_key(key, ctx->key_len * 8, ctx->cipher_data); + dat->block = (block128_f)aesni_encrypt; + if (mode == EVP_CIPH_CBC_MODE) { + dat->stream.cbc = (cbc128_f)aesni_cbc_encrypt; + } else if (mode == EVP_CIPH_CTR_MODE) { + dat->stream.ctr = (ctr128_f)aesni_ctr32_encrypt_blocks; + } else { + dat->stream.cbc = NULL; + } + } + + if (ret < 0) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_AES_KEY_SETUP_FAILED); + return 0; + } + + return 1; +} + +static int aesni_cbc_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, + const uint8_t *in, size_t len) { + aesni_cbc_encrypt(in, out, len, ctx->cipher_data, ctx->iv, ctx->encrypt); + + return 1; +} + +static int aesni_ecb_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, + const uint8_t *in, size_t len) { + size_t bl = ctx->cipher->block_size; + + if (len < bl) { + return 1; + } + + aesni_ecb_encrypt(in, out, len, ctx->cipher_data, ctx->encrypt); + + return 1; +} + +static int aesni_gcm_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key, + const uint8_t *iv, int enc) { + EVP_AES_GCM_CTX *gctx = ctx->cipher_data; + if (!iv && !key) { + return 1; + } + if (key) { + aesni_set_encrypt_key(key, ctx->key_len * 8, &gctx->ks.ks); + CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks, (block128_f)aesni_encrypt); + gctx->ctr = (ctr128_f)aesni_ctr32_encrypt_blocks; + /* If we have an iv can set it directly, otherwise use + * saved IV. */ + if (iv == NULL && gctx->iv_set) { + iv = gctx->iv; + } + if (iv) { + CRYPTO_gcm128_setiv(&gctx->gcm, &gctx->ks.ks, iv, gctx->ivlen); + gctx->iv_set = 1; + } + gctx->key_set = 1; + } else { + /* If key set use IV, otherwise copy */ + if (gctx->key_set) { + CRYPTO_gcm128_setiv(&gctx->gcm, &gctx->ks.ks, iv, gctx->ivlen); + } else { + memcpy(gctx->iv, iv, gctx->ivlen); + } + gctx->iv_set = 1; + gctx->iv_gen = 0; + } + return 1; +} + +static const EVP_CIPHER aesni_128_cbc = { + NID_aes_128_cbc, 16 /* block_size */, 16 /* key_size */, + 16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_CBC_MODE, + NULL /* app_data */, aesni_init_key, aesni_cbc_cipher, + NULL /* cleanup */, NULL /* ctrl */}; + +static const EVP_CIPHER aesni_128_ctr = { + NID_aes_128_ctr, 1 /* block_size */, 16 /* key_size */, + 16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_CTR_MODE, + NULL /* app_data */, aesni_init_key, aes_ctr_cipher, + NULL /* cleanup */, NULL /* ctrl */}; + +static const EVP_CIPHER aesni_128_ecb = { + NID_aes_128_ecb, 16 /* block_size */, 16 /* key_size */, + 0 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_ECB_MODE, + NULL /* app_data */, aesni_init_key, aesni_ecb_cipher, + NULL /* cleanup */, NULL /* ctrl */}; + +static const EVP_CIPHER aesni_128_ofb = { + NID_aes_128_ofb128, 1 /* block_size */, 16 /* key_size */, + 16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_OFB_MODE, + NULL /* app_data */, aesni_init_key, aes_ofb_cipher, + NULL /* cleanup */, NULL /* ctrl */}; + +static const EVP_CIPHER aesni_128_gcm = { + NID_aes_128_gcm, 1 /* block_size */, 16 /* key_size */, 12 /* iv_len */, + sizeof(EVP_AES_GCM_CTX), + EVP_CIPH_GCM_MODE | EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER | + EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT | + EVP_CIPH_FLAG_AEAD_CIPHER, + NULL /* app_data */, aesni_gcm_init_key, aes_gcm_cipher, aes_gcm_cleanup, + aes_gcm_ctrl}; + + +static const EVP_CIPHER aesni_192_cbc = { + NID_aes_192_cbc, 16 /* block_size */, 24 /* key_size */, + 16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_CBC_MODE, + NULL /* app_data */, aesni_init_key, aesni_cbc_cipher, + NULL /* cleanup */, NULL /* ctrl */}; + +static const EVP_CIPHER aesni_192_ctr = { + NID_aes_192_ctr, 1 /* block_size */, 24 /* key_size */, + 16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_CTR_MODE, + NULL /* app_data */, aesni_init_key, aes_ctr_cipher, + NULL /* cleanup */, NULL /* ctrl */}; + +static const EVP_CIPHER aesni_192_ecb = { + NID_aes_192_ecb, 16 /* block_size */, 24 /* key_size */, + 0 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_ECB_MODE, + NULL /* app_data */, aesni_init_key, aesni_ecb_cipher, + NULL /* cleanup */, NULL /* ctrl */}; + +static const EVP_CIPHER aesni_192_gcm = { + NID_aes_192_gcm, 1 /* block_size */, 24 /* key_size */, 12 /* iv_len */, + sizeof(EVP_AES_GCM_CTX), + EVP_CIPH_GCM_MODE | EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER | + EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT | + EVP_CIPH_FLAG_AEAD_CIPHER, + NULL /* app_data */, aesni_gcm_init_key, aes_gcm_cipher, aes_gcm_cleanup, + aes_gcm_ctrl}; + + +static const EVP_CIPHER aesni_256_cbc = { + NID_aes_256_cbc, 16 /* block_size */, 32 /* key_size */, + 16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_CBC_MODE, + NULL /* app_data */, aesni_init_key, aesni_cbc_cipher, + NULL /* cleanup */, NULL /* ctrl */}; + +static const EVP_CIPHER aesni_256_ctr = { + NID_aes_256_ctr, 1 /* block_size */, 32 /* key_size */, + 16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_CTR_MODE, + NULL /* app_data */, aesni_init_key, aes_ctr_cipher, + NULL /* cleanup */, NULL /* ctrl */}; + +static const EVP_CIPHER aesni_256_ecb = { + NID_aes_256_ecb, 16 /* block_size */, 32 /* key_size */, + 0 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_ECB_MODE, + NULL /* app_data */, aesni_init_key, aesni_ecb_cipher, + NULL /* cleanup */, NULL /* ctrl */}; + +static const EVP_CIPHER aesni_256_ofb = { + NID_aes_256_ofb128, 1 /* block_size */, 32 /* key_size */, + 16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_OFB_MODE, + NULL /* app_data */, aesni_init_key, aes_ofb_cipher, + NULL /* cleanup */, NULL /* ctrl */}; + +static const EVP_CIPHER aesni_256_gcm = { + NID_aes_256_gcm, 1 /* block_size */, 32 /* key_size */, 12 /* iv_len */, + sizeof(EVP_AES_GCM_CTX), + EVP_CIPH_GCM_MODE | EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER | + EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT | EVP_CIPH_CUSTOM_COPY | + EVP_CIPH_FLAG_AEAD_CIPHER, + NULL /* app_data */, aesni_gcm_init_key, aes_gcm_cipher, aes_gcm_cleanup, + aes_gcm_ctrl}; + +#define EVP_CIPHER_FUNCTION(keybits, mode) \ + const EVP_CIPHER *EVP_aes_##keybits##_##mode(void) { \ + if (aesni_capable()) { \ + return &aesni_##keybits##_##mode; \ + } else { \ + return &aes_##keybits##_##mode; \ + } \ + } + +#else /* ^^^ OPENSSL_X86_64 || OPENSSL_X86 */ + +static char aesni_capable(void) { + return 0; +} + +#define EVP_CIPHER_FUNCTION(keybits, mode) \ + const EVP_CIPHER *EVP_aes_##keybits##_##mode(void) { \ + return &aes_##keybits##_##mode; \ + } + +#endif + +EVP_CIPHER_FUNCTION(128, cbc) +EVP_CIPHER_FUNCTION(128, ctr) +EVP_CIPHER_FUNCTION(128, ecb) +EVP_CIPHER_FUNCTION(128, ofb) +EVP_CIPHER_FUNCTION(128, gcm) + +EVP_CIPHER_FUNCTION(192, cbc) +EVP_CIPHER_FUNCTION(192, ctr) +EVP_CIPHER_FUNCTION(192, ecb) +EVP_CIPHER_FUNCTION(192, gcm) + +EVP_CIPHER_FUNCTION(256, cbc) +EVP_CIPHER_FUNCTION(256, ctr) +EVP_CIPHER_FUNCTION(256, ecb) +EVP_CIPHER_FUNCTION(256, ofb) +EVP_CIPHER_FUNCTION(256, gcm) + + +#define EVP_AEAD_AES_GCM_TAG_LEN 16 + +struct aead_aes_gcm_ctx { + union { + double align; + AES_KEY ks; + } ks; + GCM128_CONTEXT gcm; + ctr128_f ctr; + uint8_t tag_len; +}; + +static int aead_aes_gcm_init(EVP_AEAD_CTX *ctx, const uint8_t *key, + size_t key_len, size_t tag_len) { + struct aead_aes_gcm_ctx *gcm_ctx; + const size_t key_bits = key_len * 8; + + if (key_bits != 128 && key_bits != 256) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_KEY_LENGTH); + return 0; /* EVP_AEAD_CTX_init should catch this. */ + } + + if (tag_len == EVP_AEAD_DEFAULT_TAG_LENGTH) { + tag_len = EVP_AEAD_AES_GCM_TAG_LEN; + } + + if (tag_len > EVP_AEAD_AES_GCM_TAG_LEN) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TAG_TOO_LARGE); + return 0; + } + + gcm_ctx = OPENSSL_malloc(sizeof(struct aead_aes_gcm_ctx)); + if (gcm_ctx == NULL) { + return 0; + } + + gcm_ctx->ctr = + aes_ctr_set_key(&gcm_ctx->ks.ks, &gcm_ctx->gcm, NULL, key, key_len); + gcm_ctx->tag_len = tag_len; + ctx->aead_state = gcm_ctx; + + return 1; +} + +static void aead_aes_gcm_cleanup(EVP_AEAD_CTX *ctx) { + struct aead_aes_gcm_ctx *gcm_ctx = ctx->aead_state; + OPENSSL_cleanse(gcm_ctx, sizeof(struct aead_aes_gcm_ctx)); + OPENSSL_free(gcm_ctx); +} + +static int aead_aes_gcm_seal(const EVP_AEAD_CTX *ctx, uint8_t *out, + size_t *out_len, size_t max_out_len, + const uint8_t *nonce, size_t nonce_len, + const uint8_t *in, size_t in_len, + const uint8_t *ad, size_t ad_len) { + const struct aead_aes_gcm_ctx *gcm_ctx = ctx->aead_state; + GCM128_CONTEXT gcm; + + if (in_len + gcm_ctx->tag_len < in_len) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE); + return 0; + } + + if (max_out_len < in_len + gcm_ctx->tag_len) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL); + return 0; + } + + const AES_KEY *key = &gcm_ctx->ks.ks; + + memcpy(&gcm, &gcm_ctx->gcm, sizeof(gcm)); + CRYPTO_gcm128_setiv(&gcm, key, nonce, nonce_len); + + if (ad_len > 0 && !CRYPTO_gcm128_aad(&gcm, ad, ad_len)) { + return 0; + } + + if (gcm_ctx->ctr) { + if (!CRYPTO_gcm128_encrypt_ctr32(&gcm, key, in, out, in_len, + gcm_ctx->ctr)) { + return 0; + } + } else { + if (!CRYPTO_gcm128_encrypt(&gcm, key, in, out, in_len)) { + return 0; + } + } + + CRYPTO_gcm128_tag(&gcm, out + in_len, gcm_ctx->tag_len); + *out_len = in_len + gcm_ctx->tag_len; + return 1; +} + +static int aead_aes_gcm_open(const EVP_AEAD_CTX *ctx, uint8_t *out, + size_t *out_len, size_t max_out_len, + const uint8_t *nonce, size_t nonce_len, + const uint8_t *in, size_t in_len, + const uint8_t *ad, size_t ad_len) { + const struct aead_aes_gcm_ctx *gcm_ctx = ctx->aead_state; + uint8_t tag[EVP_AEAD_AES_GCM_TAG_LEN]; + size_t plaintext_len; + GCM128_CONTEXT gcm; + + if (in_len < gcm_ctx->tag_len) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT); + return 0; + } + + plaintext_len = in_len - gcm_ctx->tag_len; + + if (max_out_len < plaintext_len) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL); + return 0; + } + + const AES_KEY *key = &gcm_ctx->ks.ks; + + memcpy(&gcm, &gcm_ctx->gcm, sizeof(gcm)); + CRYPTO_gcm128_setiv(&gcm, key, nonce, nonce_len); + + if (!CRYPTO_gcm128_aad(&gcm, ad, ad_len)) { + return 0; + } + + if (gcm_ctx->ctr) { + if (!CRYPTO_gcm128_decrypt_ctr32(&gcm, key, in, out, + in_len - gcm_ctx->tag_len, gcm_ctx->ctr)) { + return 0; + } + } else { + if (!CRYPTO_gcm128_decrypt(&gcm, key, in, out, in_len - gcm_ctx->tag_len)) { + return 0; + } + } + + CRYPTO_gcm128_tag(&gcm, tag, gcm_ctx->tag_len); + if (CRYPTO_memcmp(tag, in + plaintext_len, gcm_ctx->tag_len) != 0) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT); + return 0; + } + + *out_len = plaintext_len; + return 1; +} + +static const EVP_AEAD aead_aes_128_gcm = { + 16, /* key len */ + 12, /* nonce len */ + EVP_AEAD_AES_GCM_TAG_LEN, /* overhead */ + EVP_AEAD_AES_GCM_TAG_LEN, /* max tag length */ + aead_aes_gcm_init, + NULL, /* init_with_direction */ + aead_aes_gcm_cleanup, + aead_aes_gcm_seal, + aead_aes_gcm_open, + NULL, /* get_rc4_state */ + NULL, /* get_iv */ +}; + +static const EVP_AEAD aead_aes_256_gcm = { + 32, /* key len */ + 12, /* nonce len */ + EVP_AEAD_AES_GCM_TAG_LEN, /* overhead */ + EVP_AEAD_AES_GCM_TAG_LEN, /* max tag length */ + aead_aes_gcm_init, + NULL, /* init_with_direction */ + aead_aes_gcm_cleanup, + aead_aes_gcm_seal, + aead_aes_gcm_open, + NULL, /* get_rc4_state */ + NULL, /* get_iv */ +}; + +const EVP_AEAD *EVP_aead_aes_128_gcm(void) { return &aead_aes_128_gcm; } + +const EVP_AEAD *EVP_aead_aes_256_gcm(void) { return &aead_aes_256_gcm; } + + +/* AES Key Wrap is specified in + * http://csrc.nist.gov/groups/ST/toolkit/documents/kms/key-wrap.pdf + * or https://tools.ietf.org/html/rfc3394 */ + +struct aead_aes_key_wrap_ctx { + uint8_t key[32]; + unsigned key_bits; +}; + +static int aead_aes_key_wrap_init(EVP_AEAD_CTX *ctx, const uint8_t *key, + size_t key_len, size_t tag_len) { + struct aead_aes_key_wrap_ctx *kw_ctx; + const size_t key_bits = key_len * 8; + + if (key_bits != 128 && key_bits != 256) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_KEY_LENGTH); + return 0; /* EVP_AEAD_CTX_init should catch this. */ + } + + if (tag_len == EVP_AEAD_DEFAULT_TAG_LENGTH) { + tag_len = 8; + } + + if (tag_len != 8) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_TAG_SIZE); + return 0; + } + + kw_ctx = OPENSSL_malloc(sizeof(struct aead_aes_key_wrap_ctx)); + if (kw_ctx == NULL) { + OPENSSL_PUT_ERROR(CIPHER, ERR_R_MALLOC_FAILURE); + return 0; + } + + memcpy(kw_ctx->key, key, key_len); + kw_ctx->key_bits = key_bits; + + ctx->aead_state = kw_ctx; + return 1; +} + +static void aead_aes_key_wrap_cleanup(EVP_AEAD_CTX *ctx) { + struct aead_aes_key_wrap_ctx *kw_ctx = ctx->aead_state; + OPENSSL_cleanse(kw_ctx, sizeof(struct aead_aes_key_wrap_ctx)); + OPENSSL_free(kw_ctx); +} + +/* kDefaultAESKeyWrapNonce is the default nonce value given in 2.2.3.1. */ +static const uint8_t kDefaultAESKeyWrapNonce[8] = {0xa6, 0xa6, 0xa6, 0xa6, + 0xa6, 0xa6, 0xa6, 0xa6}; + + +static int aead_aes_key_wrap_seal(const EVP_AEAD_CTX *ctx, uint8_t *out, + size_t *out_len, size_t max_out_len, + const uint8_t *nonce, size_t nonce_len, + const uint8_t *in, size_t in_len, + const uint8_t *ad, size_t ad_len) { + const struct aead_aes_key_wrap_ctx *kw_ctx = ctx->aead_state; + union { + double align; + AES_KEY ks; + } ks; + /* Variables in this function match up with the variables in the second half + * of section 2.2.1. */ + unsigned i, j, n; + uint8_t A[AES_BLOCK_SIZE]; + + if (ad_len != 0) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_AD_SIZE); + return 0; + } + + if (nonce_len == 0) { + nonce = kDefaultAESKeyWrapNonce; + nonce_len = sizeof(kDefaultAESKeyWrapNonce); + } + + if (nonce_len != 8) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE); + return 0; + } + + if (in_len % 8 != 0) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_INPUT_SIZE); + return 0; + } + + /* The code below only handles a 32-bit |t| thus 6*|n| must be less than + * 2^32, where |n| is |in_len| / 8. So in_len < 4/3 * 2^32 and we + * conservatively cap it to 2^32-16 to stop 32-bit platforms complaining that + * a comparison is always true. */ + if (in_len > 0xfffffff0) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE); + return 0; + } + + n = in_len / 8; + + if (n < 2) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_INPUT_SIZE); + return 0; + } + + if (in_len + 8 < in_len) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE); + return 0; + } + + if (max_out_len < in_len + 8) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL); + return 0; + } + + if (AES_set_encrypt_key(kw_ctx->key, kw_ctx->key_bits, &ks.ks) < 0) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_AES_KEY_SETUP_FAILED); + return 0; + } + + memmove(out + 8, in, in_len); + memcpy(A, nonce, 8); + + for (j = 0; j < 6; j++) { + for (i = 1; i <= n; i++) { + uint32_t t; + + memcpy(A + 8, out + 8 * i, 8); + AES_encrypt(A, A, &ks.ks); + t = n * j + i; + A[7] ^= t & 0xff; + A[6] ^= (t >> 8) & 0xff; + A[5] ^= (t >> 16) & 0xff; + A[4] ^= (t >> 24) & 0xff; + memcpy(out + 8 * i, A + 8, 8); + } + } + + memcpy(out, A, 8); + *out_len = in_len + 8; + return 1; +} + +static int aead_aes_key_wrap_open(const EVP_AEAD_CTX *ctx, uint8_t *out, + size_t *out_len, size_t max_out_len, + const uint8_t *nonce, size_t nonce_len, + const uint8_t *in, size_t in_len, + const uint8_t *ad, size_t ad_len) { + const struct aead_aes_key_wrap_ctx *kw_ctx = ctx->aead_state; + union { + double align; + AES_KEY ks; + } ks; + /* Variables in this function match up with the variables in the second half + * of section 2.2.1. */ + unsigned i, j, n; + uint8_t A[AES_BLOCK_SIZE]; + + if (ad_len != 0) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_AD_SIZE); + return 0; + } + + if (nonce_len == 0) { + nonce = kDefaultAESKeyWrapNonce; + nonce_len = sizeof(kDefaultAESKeyWrapNonce); + } + + if (nonce_len != 8) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE); + return 0; + } + + if (in_len % 8 != 0) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_INPUT_SIZE); + return 0; + } + + /* The code below only handles a 32-bit |t| thus 6*|n| must be less than + * 2^32, where |n| is |in_len| / 8. So in_len < 4/3 * 2^32 and we + * conservatively cap it to 2^32-8 to stop 32-bit platforms complaining that + * a comparison is always true. */ + if (in_len > 0xfffffff8) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE); + return 0; + } + + if (in_len < 24) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT); + return 0; + } + + n = (in_len / 8) - 1; + + if (max_out_len < in_len - 8) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL); + return 0; + } + + if (AES_set_decrypt_key(kw_ctx->key, kw_ctx->key_bits, &ks.ks) < 0) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_AES_KEY_SETUP_FAILED); + return 0; + } + + memcpy(A, in, 8); + memmove(out, in + 8, in_len - 8); + + for (j = 5; j < 6; j--) { + for (i = n; i > 0; i--) { + uint32_t t; + + t = n * j + i; + A[7] ^= t & 0xff; + A[6] ^= (t >> 8) & 0xff; + A[5] ^= (t >> 16) & 0xff; + A[4] ^= (t >> 24) & 0xff; + memcpy(A + 8, out + 8 * (i - 1), 8); + AES_decrypt(A, A, &ks.ks); + memcpy(out + 8 * (i - 1), A + 8, 8); + } + } + + if (CRYPTO_memcmp(A, nonce, 8) != 0) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT); + return 0; + } + + *out_len = in_len - 8; + return 1; +} + +static const EVP_AEAD aead_aes_128_key_wrap = { + 16, /* key len */ + 8, /* nonce len */ + 8, /* overhead */ + 8, /* max tag length */ + aead_aes_key_wrap_init, + NULL, /* init_with_direction */ + aead_aes_key_wrap_cleanup, + aead_aes_key_wrap_seal, + aead_aes_key_wrap_open, + NULL, /* get_rc4_state */ + NULL, /* get_iv */ +}; + +static const EVP_AEAD aead_aes_256_key_wrap = { + 32, /* key len */ + 8, /* nonce len */ + 8, /* overhead */ + 8, /* max tag length */ + aead_aes_key_wrap_init, + NULL, /* init_with_direction */ + aead_aes_key_wrap_cleanup, + aead_aes_key_wrap_seal, + aead_aes_key_wrap_open, + NULL, /* get_rc4_state */ + NULL, /* get_iv */ +}; + +const EVP_AEAD *EVP_aead_aes_128_key_wrap(void) { return &aead_aes_128_key_wrap; } + +const EVP_AEAD *EVP_aead_aes_256_key_wrap(void) { return &aead_aes_256_key_wrap; } + + +#define EVP_AEAD_AES_CTR_HMAC_SHA256_TAG_LEN SHA256_DIGEST_LENGTH +#define EVP_AEAD_AES_CTR_HMAC_SHA256_NONCE_LEN 12 + +struct aead_aes_ctr_hmac_sha256_ctx { + union { + double align; + AES_KEY ks; + } ks; + ctr128_f ctr; + block128_f block; + SHA256_CTX inner_init_state; + SHA256_CTX outer_init_state; + uint8_t tag_len; +}; + +static void hmac_init(SHA256_CTX *out_inner, SHA256_CTX *out_outer, + const uint8_t hmac_key[32]) { + static const size_t hmac_key_len = 32; + uint8_t block[SHA256_CBLOCK]; + memcpy(block, hmac_key, hmac_key_len); + memset(block + hmac_key_len, 0x36, sizeof(block) - hmac_key_len); + + unsigned i; + for (i = 0; i < hmac_key_len; i++) { + block[i] ^= 0x36; + } + + SHA256_Init(out_inner); + SHA256_Update(out_inner, block, sizeof(block)); + + memset(block + hmac_key_len, 0x5c, sizeof(block) - hmac_key_len); + for (i = 0; i < hmac_key_len; i++) { + block[i] ^= (0x36 ^ 0x5c); + } + + SHA256_Init(out_outer); + SHA256_Update(out_outer, block, sizeof(block)); +} + +static int aead_aes_ctr_hmac_sha256_init(EVP_AEAD_CTX *ctx, const uint8_t *key, + size_t key_len, size_t tag_len) { + struct aead_aes_ctr_hmac_sha256_ctx *aes_ctx; + static const size_t hmac_key_len = 32; + + if (key_len < hmac_key_len) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_KEY_LENGTH); + return 0; /* EVP_AEAD_CTX_init should catch this. */ + } + + const size_t aes_key_len = key_len - hmac_key_len; + if (aes_key_len != 16 && aes_key_len != 32) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_KEY_LENGTH); + return 0; /* EVP_AEAD_CTX_init should catch this. */ + } + + if (tag_len == EVP_AEAD_DEFAULT_TAG_LENGTH) { + tag_len = EVP_AEAD_AES_CTR_HMAC_SHA256_TAG_LEN; + } + + if (tag_len > EVP_AEAD_AES_CTR_HMAC_SHA256_TAG_LEN) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TAG_TOO_LARGE); + return 0; + } + + aes_ctx = OPENSSL_malloc(sizeof(struct aead_aes_ctr_hmac_sha256_ctx)); + if (aes_ctx == NULL) { + OPENSSL_PUT_ERROR(CIPHER, ERR_R_MALLOC_FAILURE); + return 0; + } + + aes_ctx->ctr = + aes_ctr_set_key(&aes_ctx->ks.ks, NULL, &aes_ctx->block, key, aes_key_len); + aes_ctx->tag_len = tag_len; + hmac_init(&aes_ctx->inner_init_state, &aes_ctx->outer_init_state, + key + aes_key_len); + + ctx->aead_state = aes_ctx; + + return 1; +} + +static void aead_aes_ctr_hmac_sha256_cleanup(EVP_AEAD_CTX *ctx) { + struct aead_aes_ctr_hmac_sha256_ctx *aes_ctx = ctx->aead_state; + OPENSSL_cleanse(aes_ctx, sizeof(struct aead_aes_ctr_hmac_sha256_ctx)); + OPENSSL_free(aes_ctx); +} + +static void hmac_update_uint64(SHA256_CTX *sha256, uint64_t value) { + unsigned i; + uint8_t bytes[8]; + + for (i = 0; i < sizeof(bytes); i++) { + bytes[i] = value & 0xff; + value >>= 8; + } + SHA256_Update(sha256, bytes, sizeof(bytes)); +} + +static void hmac_calculate(uint8_t out[SHA256_DIGEST_LENGTH], + const SHA256_CTX *inner_init_state, + const SHA256_CTX *outer_init_state, + const uint8_t *ad, size_t ad_len, + const uint8_t *nonce, const uint8_t *ciphertext, + size_t ciphertext_len) { + SHA256_CTX sha256; + memcpy(&sha256, inner_init_state, sizeof(sha256)); + hmac_update_uint64(&sha256, ad_len); + hmac_update_uint64(&sha256, ciphertext_len); + SHA256_Update(&sha256, nonce, EVP_AEAD_AES_CTR_HMAC_SHA256_NONCE_LEN); + SHA256_Update(&sha256, ad, ad_len); + + /* Pad with zeros to the end of the SHA-256 block. */ + const unsigned num_padding = + (SHA256_CBLOCK - ((sizeof(uint64_t)*2 + + EVP_AEAD_AES_CTR_HMAC_SHA256_NONCE_LEN + ad_len) % + SHA256_CBLOCK)) % + SHA256_CBLOCK; + uint8_t padding[SHA256_CBLOCK]; + memset(padding, 0, num_padding); + SHA256_Update(&sha256, padding, num_padding); + + SHA256_Update(&sha256, ciphertext, ciphertext_len); + + uint8_t inner_digest[SHA256_DIGEST_LENGTH]; + SHA256_Final(inner_digest, &sha256); + + memcpy(&sha256, outer_init_state, sizeof(sha256)); + SHA256_Update(&sha256, inner_digest, sizeof(inner_digest)); + SHA256_Final(out, &sha256); +} + +static void aead_aes_ctr_hmac_sha256_crypt( + const struct aead_aes_ctr_hmac_sha256_ctx *aes_ctx, uint8_t *out, + const uint8_t *in, size_t len, const uint8_t *nonce) { + /* Since the AEAD operation is one-shot, keeping a buffer of unused keystream + * bytes is pointless. However, |CRYPTO_ctr128_encrypt| requires it. */ + uint8_t partial_block_buffer[AES_BLOCK_SIZE]; + unsigned partial_block_offset = 0; + memset(partial_block_buffer, 0, sizeof(partial_block_buffer)); + + uint8_t counter[AES_BLOCK_SIZE]; + memcpy(counter, nonce, EVP_AEAD_AES_CTR_HMAC_SHA256_NONCE_LEN); + memset(counter + EVP_AEAD_AES_CTR_HMAC_SHA256_NONCE_LEN, 0, 4); + + if (aes_ctx->ctr) { + CRYPTO_ctr128_encrypt_ctr32(in, out, len, &aes_ctx->ks.ks, counter, + partial_block_buffer, &partial_block_offset, + aes_ctx->ctr); + } else { + CRYPTO_ctr128_encrypt(in, out, len, &aes_ctx->ks.ks, counter, + partial_block_buffer, &partial_block_offset, + aes_ctx->block); + } +} + +static int aead_aes_ctr_hmac_sha256_seal(const EVP_AEAD_CTX *ctx, uint8_t *out, + size_t *out_len, size_t max_out_len, + const uint8_t *nonce, size_t nonce_len, + const uint8_t *in, size_t in_len, + const uint8_t *ad, size_t ad_len) { + const struct aead_aes_ctr_hmac_sha256_ctx *aes_ctx = ctx->aead_state; + const uint64_t in_len_64 = in_len; + + if (in_len + aes_ctx->tag_len < in_len || + /* This input is so large it would overflow the 32-bit block counter. */ + in_len_64 >= (UINT64_C(1) << 32) * AES_BLOCK_SIZE) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE); + return 0; + } + + if (max_out_len < in_len + aes_ctx->tag_len) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL); + return 0; + } + + if (nonce_len != EVP_AEAD_AES_CTR_HMAC_SHA256_NONCE_LEN) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE); + return 0; + } + + aead_aes_ctr_hmac_sha256_crypt(aes_ctx, out, in, in_len, nonce); + + uint8_t hmac_result[SHA256_DIGEST_LENGTH]; + hmac_calculate(hmac_result, &aes_ctx->inner_init_state, + &aes_ctx->outer_init_state, ad, ad_len, nonce, out, in_len); + memcpy(out + in_len, hmac_result, aes_ctx->tag_len); + *out_len = in_len + aes_ctx->tag_len; + + return 1; +} + +static int aead_aes_ctr_hmac_sha256_open(const EVP_AEAD_CTX *ctx, uint8_t *out, + size_t *out_len, size_t max_out_len, + const uint8_t *nonce, size_t nonce_len, + const uint8_t *in, size_t in_len, + const uint8_t *ad, size_t ad_len) { + const struct aead_aes_ctr_hmac_sha256_ctx *aes_ctx = ctx->aead_state; + size_t plaintext_len; + + if (in_len < aes_ctx->tag_len) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT); + return 0; + } + + plaintext_len = in_len - aes_ctx->tag_len; + + if (max_out_len < plaintext_len) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL); + return 0; + } + + if (nonce_len != EVP_AEAD_AES_CTR_HMAC_SHA256_NONCE_LEN) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE); + return 0; + } + + uint8_t hmac_result[SHA256_DIGEST_LENGTH]; + hmac_calculate(hmac_result, &aes_ctx->inner_init_state, + &aes_ctx->outer_init_state, ad, ad_len, nonce, in, + plaintext_len); + if (CRYPTO_memcmp(hmac_result, in + plaintext_len, aes_ctx->tag_len) != 0) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT); + return 0; + } + + aead_aes_ctr_hmac_sha256_crypt(aes_ctx, out, in, plaintext_len, nonce); + + *out_len = plaintext_len; + return 1; +} + +static const EVP_AEAD aead_aes_128_ctr_hmac_sha256 = { + 16 /* AES key */ + 32 /* HMAC key */, + 12, /* nonce length */ + EVP_AEAD_AES_CTR_HMAC_SHA256_TAG_LEN, /* overhead */ + EVP_AEAD_AES_CTR_HMAC_SHA256_TAG_LEN, /* max tag length */ + + aead_aes_ctr_hmac_sha256_init, + NULL /* init_with_direction */, + aead_aes_ctr_hmac_sha256_cleanup, + aead_aes_ctr_hmac_sha256_seal, + aead_aes_ctr_hmac_sha256_open, + NULL /* get_rc4_state */, + NULL /* get_iv */, +}; + +static const EVP_AEAD aead_aes_256_ctr_hmac_sha256 = { + 32 /* AES key */ + 32 /* HMAC key */, + 12, /* nonce length */ + EVP_AEAD_AES_CTR_HMAC_SHA256_TAG_LEN, /* overhead */ + EVP_AEAD_AES_CTR_HMAC_SHA256_TAG_LEN, /* max tag length */ + + aead_aes_ctr_hmac_sha256_init, + NULL /* init_with_direction */, + aead_aes_ctr_hmac_sha256_cleanup, + aead_aes_ctr_hmac_sha256_seal, + aead_aes_ctr_hmac_sha256_open, + NULL /* get_rc4_state */, + NULL /* get_iv */, +}; + +const EVP_AEAD *EVP_aead_aes_128_ctr_hmac_sha256(void) { + return &aead_aes_128_ctr_hmac_sha256; +} + +const EVP_AEAD *EVP_aead_aes_256_ctr_hmac_sha256(void) { + return &aead_aes_256_ctr_hmac_sha256; +} + +int EVP_has_aes_hardware(void) { +#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64) + return aesni_capable() && crypto_gcm_clmul_enabled(); +#elif defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64) + return hwaes_capable() && CRYPTO_is_ARMv8_PMULL_capable(); +#else + return 0; +#endif +} diff --git a/external/boringssl/crypto/cipher/e_chacha20poly1305.c b/external/boringssl/crypto/cipher/e_chacha20poly1305.c new file mode 100644 index 0000000000..852b2c64ee --- /dev/null +++ b/external/boringssl/crypto/cipher/e_chacha20poly1305.c @@ -0,0 +1,302 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include + +#include +#include +#include +#include +#include + +#include "internal.h" +#include "../internal.h" + + +#define POLY1305_TAG_LEN 16 + +struct aead_chacha20_poly1305_ctx { + unsigned char key[32]; + unsigned char tag_len; +}; + +static int aead_chacha20_poly1305_init(EVP_AEAD_CTX *ctx, const uint8_t *key, + size_t key_len, size_t tag_len) { + struct aead_chacha20_poly1305_ctx *c20_ctx; + + if (tag_len == 0) { + tag_len = POLY1305_TAG_LEN; + } + + if (tag_len > POLY1305_TAG_LEN) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE); + return 0; + } + + if (key_len != sizeof(c20_ctx->key)) { + return 0; /* internal error - EVP_AEAD_CTX_init should catch this. */ + } + + c20_ctx = OPENSSL_malloc(sizeof(struct aead_chacha20_poly1305_ctx)); + if (c20_ctx == NULL) { + return 0; + } + + memcpy(c20_ctx->key, key, key_len); + c20_ctx->tag_len = tag_len; + ctx->aead_state = c20_ctx; + + return 1; +} + +static void aead_chacha20_poly1305_cleanup(EVP_AEAD_CTX *ctx) { + struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state; + OPENSSL_cleanse(c20_ctx->key, sizeof(c20_ctx->key)); + OPENSSL_free(c20_ctx); +} + +static void poly1305_update_length(poly1305_state *poly1305, size_t data_len) { + uint8_t length_bytes[8]; + unsigned i; + + for (i = 0; i < sizeof(length_bytes); i++) { + length_bytes[i] = data_len; + data_len >>= 8; + } + + CRYPTO_poly1305_update(poly1305, length_bytes, sizeof(length_bytes)); +} + +typedef void (*aead_poly1305_update)(poly1305_state *ctx, const uint8_t *ad, + size_t ad_len, const uint8_t *ciphertext, + size_t ciphertext_len); + +/* aead_poly1305 fills |tag| with the authentication tag for the given + * inputs, using |update| to control the order and format that the inputs are + * signed/authenticated. */ +static void aead_poly1305(aead_poly1305_update update, + uint8_t tag[POLY1305_TAG_LEN], + const struct aead_chacha20_poly1305_ctx *c20_ctx, + const uint8_t nonce[12], const uint8_t *ad, + size_t ad_len, const uint8_t *ciphertext, + size_t ciphertext_len) { + alignas(16) uint8_t poly1305_key[32]; + memset(poly1305_key, 0, sizeof(poly1305_key)); + CRYPTO_chacha_20(poly1305_key, poly1305_key, sizeof(poly1305_key), + c20_ctx->key, nonce, 0); + poly1305_state ctx; + CRYPTO_poly1305_init(&ctx, poly1305_key); + update(&ctx, ad, ad_len, ciphertext, ciphertext_len); + CRYPTO_poly1305_finish(&ctx, tag); +} + +static int seal_impl(aead_poly1305_update poly1305_update, + const EVP_AEAD_CTX *ctx, uint8_t *out, size_t *out_len, + size_t max_out_len, const uint8_t nonce[12], + const uint8_t *in, size_t in_len, const uint8_t *ad, + size_t ad_len) { + const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state; + const uint64_t in_len_64 = in_len; + + /* |CRYPTO_chacha_20| uses a 32-bit block counter. Therefore we disallow + * individual operations that work on more than 256GB at a time. + * |in_len_64| is needed because, on 32-bit platforms, size_t is only + * 32-bits and this produces a warning because it's always false. + * Casting to uint64_t inside the conditional is not sufficient to stop + * the warning. */ + if (in_len_64 >= (UINT64_C(1) << 32) * 64 - 64) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE); + return 0; + } + + if (in_len + c20_ctx->tag_len < in_len) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE); + return 0; + } + + if (max_out_len < in_len + c20_ctx->tag_len) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL); + return 0; + } + + CRYPTO_chacha_20(out, in, in_len, c20_ctx->key, nonce, 1); + + alignas(16) uint8_t tag[POLY1305_TAG_LEN]; + aead_poly1305(poly1305_update, tag, c20_ctx, nonce, ad, ad_len, out, in_len); + + memcpy(out + in_len, tag, c20_ctx->tag_len); + *out_len = in_len + c20_ctx->tag_len; + return 1; +} + +static int open_impl(aead_poly1305_update poly1305_update, + const EVP_AEAD_CTX *ctx, uint8_t *out, size_t *out_len, + size_t max_out_len, const uint8_t nonce[12], + const uint8_t *in, size_t in_len, const uint8_t *ad, + size_t ad_len) { + const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state; + size_t plaintext_len; + const uint64_t in_len_64 = in_len; + + if (in_len < c20_ctx->tag_len) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT); + return 0; + } + + /* |CRYPTO_chacha_20| uses a 32-bit block counter. Therefore we disallow + * individual operations that work on more than 256GB at a time. + * |in_len_64| is needed because, on 32-bit platforms, size_t is only + * 32-bits and this produces a warning because it's always false. + * Casting to uint64_t inside the conditional is not sufficient to stop + * the warning. */ + if (in_len_64 >= (UINT64_C(1) << 32) * 64 - 64) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE); + return 0; + } + + plaintext_len = in_len - c20_ctx->tag_len; + alignas(16) uint8_t tag[POLY1305_TAG_LEN]; + aead_poly1305(poly1305_update, tag, c20_ctx, nonce, ad, ad_len, in, + plaintext_len); + if (CRYPTO_memcmp(tag, in + plaintext_len, c20_ctx->tag_len) != 0) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT); + return 0; + } + + CRYPTO_chacha_20(out, in, plaintext_len, c20_ctx->key, nonce, 1); + *out_len = plaintext_len; + return 1; +} + +static void poly1305_update_padded_16(poly1305_state *poly1305, + const uint8_t *data, size_t data_len) { + static const uint8_t padding[16] = { 0 }; /* Padding is all zeros. */ + + CRYPTO_poly1305_update(poly1305, data, data_len); + if (data_len % 16 != 0) { + CRYPTO_poly1305_update(poly1305, padding, sizeof(padding) - (data_len % 16)); + } +} + +static void poly1305_update(poly1305_state *ctx, const uint8_t *ad, + size_t ad_len, const uint8_t *ciphertext, + size_t ciphertext_len) { + poly1305_update_padded_16(ctx, ad, ad_len); + poly1305_update_padded_16(ctx, ciphertext, ciphertext_len); + poly1305_update_length(ctx, ad_len); + poly1305_update_length(ctx, ciphertext_len); +} + +static int aead_chacha20_poly1305_seal(const EVP_AEAD_CTX *ctx, uint8_t *out, + size_t *out_len, size_t max_out_len, + const uint8_t *nonce, size_t nonce_len, + const uint8_t *in, size_t in_len, + const uint8_t *ad, size_t ad_len) { + if (nonce_len != 12) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE); + return 0; + } + return seal_impl(poly1305_update, ctx, out, out_len, max_out_len, nonce, in, + in_len, ad, ad_len); +} + +static int aead_chacha20_poly1305_open(const EVP_AEAD_CTX *ctx, uint8_t *out, + size_t *out_len, size_t max_out_len, + const uint8_t *nonce, size_t nonce_len, + const uint8_t *in, size_t in_len, + const uint8_t *ad, size_t ad_len) { + if (nonce_len != 12) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE); + return 0; + } + return open_impl(poly1305_update, ctx, out, out_len, max_out_len, nonce, in, + in_len, ad, ad_len); +} + +static const EVP_AEAD aead_chacha20_poly1305 = { + 32, /* key len */ + 12, /* nonce len */ + POLY1305_TAG_LEN, /* overhead */ + POLY1305_TAG_LEN, /* max tag length */ + aead_chacha20_poly1305_init, + NULL, /* init_with_direction */ + aead_chacha20_poly1305_cleanup, + aead_chacha20_poly1305_seal, + aead_chacha20_poly1305_open, + NULL, /* get_rc4_state */ + NULL, /* get_iv */ +}; + +const EVP_AEAD *EVP_aead_chacha20_poly1305(void) { + return &aead_chacha20_poly1305; +} + +static void poly1305_update_old(poly1305_state *ctx, const uint8_t *ad, + size_t ad_len, const uint8_t *ciphertext, + size_t ciphertext_len) { + CRYPTO_poly1305_update(ctx, ad, ad_len); + poly1305_update_length(ctx, ad_len); + CRYPTO_poly1305_update(ctx, ciphertext, ciphertext_len); + poly1305_update_length(ctx, ciphertext_len); +} + +static int aead_chacha20_poly1305_old_seal( + const EVP_AEAD_CTX *ctx, uint8_t *out, size_t *out_len, size_t max_out_len, + const uint8_t *nonce, size_t nonce_len, const uint8_t *in, size_t in_len, + const uint8_t *ad, size_t ad_len) { + if (nonce_len != 8) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE); + return 0; + } + uint8_t nonce_96[12]; + memset(nonce_96, 0, 4); + memcpy(nonce_96 + 4, nonce, 8); + return seal_impl(poly1305_update_old, ctx, out, out_len, max_out_len, + nonce_96, in, in_len, ad, ad_len); +} + +static int aead_chacha20_poly1305_old_open( + const EVP_AEAD_CTX *ctx, uint8_t *out, size_t *out_len, size_t max_out_len, + const uint8_t *nonce, size_t nonce_len, const uint8_t *in, size_t in_len, + const uint8_t *ad, size_t ad_len) { + if (nonce_len != 8) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE); + return 0; + } + uint8_t nonce_96[12]; + memset(nonce_96, 0, 4); + memcpy(nonce_96 + 4, nonce, 8); + return open_impl(poly1305_update_old, ctx, out, out_len, max_out_len, + nonce_96, in, in_len, ad, ad_len); +} + +static const EVP_AEAD aead_chacha20_poly1305_old = { + 32, /* key len */ + 8, /* nonce len */ + POLY1305_TAG_LEN, /* overhead */ + POLY1305_TAG_LEN, /* max tag length */ + aead_chacha20_poly1305_init, + NULL, /* init_with_direction */ + aead_chacha20_poly1305_cleanup, + aead_chacha20_poly1305_old_seal, + aead_chacha20_poly1305_old_open, + NULL, /* get_rc4_state */ + NULL, /* get_iv */ +}; + +const EVP_AEAD *EVP_aead_chacha20_poly1305_old(void) { + return &aead_chacha20_poly1305_old; +} diff --git a/external/boringssl/crypto/cipher/e_des.c b/external/boringssl/crypto/cipher/e_des.c new file mode 100644 index 0000000000..2ba2bed38b --- /dev/null +++ b/external/boringssl/crypto/cipher/e_des.c @@ -0,0 +1,207 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include +#include +#include + +#include "internal.h" + + +typedef struct { + union { + double align; + DES_key_schedule ks; + } ks; +} EVP_DES_KEY; + +static int des_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key, + const uint8_t *iv, int enc) { + DES_cblock *deskey = (DES_cblock *)key; + EVP_DES_KEY *dat = (EVP_DES_KEY *)ctx->cipher_data; + + DES_set_key(deskey, &dat->ks.ks); + return 1; +} + +static int des_cbc_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in, + size_t in_len) { + EVP_DES_KEY *dat = (EVP_DES_KEY *)ctx->cipher_data; + + DES_ncbc_encrypt(in, out, in_len, &dat->ks.ks, (DES_cblock *)ctx->iv, + ctx->encrypt); + + return 1; +} + +static const EVP_CIPHER des_cbc = { + NID_des_cbc, 8 /* block_size */, 8 /* key_size */, + 8 /* iv_len */, sizeof(EVP_DES_KEY), EVP_CIPH_CBC_MODE, + NULL /* app_data */, des_init_key, des_cbc_cipher, + NULL /* cleanup */, NULL /* ctrl */, }; + +const EVP_CIPHER *EVP_des_cbc(void) { return &des_cbc; } + + +static int des_ecb_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in, + size_t in_len) { + if (in_len < ctx->cipher->block_size) { + return 1; + } + in_len -= ctx->cipher->block_size; + + EVP_DES_KEY *dat = (EVP_DES_KEY *) ctx->cipher_data; + size_t i; + for (i = 0; i <= in_len; i += ctx->cipher->block_size) { + DES_ecb_encrypt((DES_cblock *) (in + i), (DES_cblock *) (out + i), + &dat->ks.ks, ctx->encrypt); + } + return 1; +} + +static const EVP_CIPHER des_ecb = { + NID_des_ecb, 8 /* block_size */, 8 /* key_size */, + 0 /* iv_len */, sizeof(EVP_DES_KEY), EVP_CIPH_ECB_MODE, + NULL /* app_data */, des_init_key, des_ecb_cipher, + NULL /* cleanup */, NULL /* ctrl */, }; + +const EVP_CIPHER *EVP_des_ecb(void) { return &des_ecb; } + + +typedef struct { + union { + double align; + DES_key_schedule ks[3]; + } ks; +} DES_EDE_KEY; + + +static int des_ede3_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key, + const uint8_t *iv, int enc) { + DES_cblock *deskey = (DES_cblock *)key; + DES_EDE_KEY *dat = (DES_EDE_KEY*) ctx->cipher_data; + + DES_set_key(&deskey[0], &dat->ks.ks[0]); + DES_set_key(&deskey[1], &dat->ks.ks[1]); + DES_set_key(&deskey[2], &dat->ks.ks[2]); + + return 1; +} + +static int des_ede3_cbc_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, + const uint8_t *in, size_t in_len) { + DES_EDE_KEY *dat = (DES_EDE_KEY*) ctx->cipher_data; + + DES_ede3_cbc_encrypt(in, out, in_len, &dat->ks.ks[0], &dat->ks.ks[1], + &dat->ks.ks[2], (DES_cblock *)ctx->iv, ctx->encrypt); + + return 1; +} + +static const EVP_CIPHER des_ede3_cbc = { + NID_des_ede3_cbc, 8 /* block_size */, 24 /* key_size */, + 8 /* iv_len */, sizeof(DES_EDE_KEY), EVP_CIPH_CBC_MODE, + NULL /* app_data */, des_ede3_init_key, des_ede3_cbc_cipher, + NULL /* cleanup */, NULL /* ctrl */, }; + +const EVP_CIPHER *EVP_des_ede3_cbc(void) { return &des_ede3_cbc; } + + +static int des_ede_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key, + const uint8_t *iv, int enc) { + DES_cblock *deskey = (DES_cblock *) key; + DES_EDE_KEY *dat = (DES_EDE_KEY *) ctx->cipher_data; + + DES_set_key(&deskey[0], &dat->ks.ks[0]); + DES_set_key(&deskey[1], &dat->ks.ks[1]); + DES_set_key(&deskey[0], &dat->ks.ks[2]); + + return 1; +} + +static const EVP_CIPHER des_ede_cbc = { + NID_des_ede_cbc, 8 /* block_size */, 16 /* key_size */, + 8 /* iv_len */, sizeof(DES_EDE_KEY), EVP_CIPH_CBC_MODE, + NULL /* app_data */, des_ede_init_key , des_ede3_cbc_cipher, + NULL /* cleanup */, NULL /* ctrl */, }; + +const EVP_CIPHER *EVP_des_ede_cbc(void) { return &des_ede_cbc; } + + +static int des_ede_ecb_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, + const uint8_t *in, size_t in_len) { + if (in_len < ctx->cipher->block_size) { + return 1; + } + in_len -= ctx->cipher->block_size; + + DES_EDE_KEY *dat = (DES_EDE_KEY *) ctx->cipher_data; + size_t i; + for (i = 0; i <= in_len; i += ctx->cipher->block_size) { + DES_ecb3_encrypt((DES_cblock *) (in + i), (DES_cblock *) (out + i), + &dat->ks.ks[0], &dat->ks.ks[1], &dat->ks.ks[2], + ctx->encrypt); + } + return 1; +} + +static const EVP_CIPHER des_ede_ecb = { + NID_des_ede_cbc, 8 /* block_size */, 16 /* key_size */, + 0 /* iv_len */, sizeof(DES_EDE_KEY), EVP_CIPH_ECB_MODE, + NULL /* app_data */, des_ede_init_key , des_ede_ecb_cipher, + NULL /* cleanup */, NULL /* ctrl */, }; + +const EVP_CIPHER *EVP_des_ede(void) { return &des_ede_ecb; } diff --git a/external/boringssl/crypto/cipher/e_null.c b/external/boringssl/crypto/cipher/e_null.c new file mode 100644 index 0000000000..3d6a24c38a --- /dev/null +++ b/external/boringssl/crypto/cipher/e_null.c @@ -0,0 +1,85 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include + +#include "internal.h" + + +static int null_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key, + const uint8_t *iv, int enc) { + return 1; +} + +static int null_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, + const uint8_t *in, size_t in_len) { + if (in != out) { + memcpy(out, in, in_len); + } + return 1; +} + +static const EVP_CIPHER n_cipher = { + NID_undef, 1 /* block size */, 0 /* key_len */, 0 /* iv_len */, + 0 /* ctx_size */, 0 /* flags */, NULL /* app_data */, null_init_key, + null_cipher, NULL /* cleanup */, NULL /* ctrl */, +}; + +const EVP_CIPHER *EVP_enc_null(void) { return &n_cipher; } diff --git a/external/boringssl/crypto/cipher/e_rc2.c b/external/boringssl/crypto/cipher/e_rc2.c new file mode 100644 index 0000000000..67418d5497 --- /dev/null +++ b/external/boringssl/crypto/cipher/e_rc2.c @@ -0,0 +1,443 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include +#include + +#include "internal.h" + + +#define c2l(c, l) \ + (l = ((uint32_t)(*((c)++))), l |= ((uint32_t)(*((c)++))) << 8L, \ + l |= ((uint32_t)(*((c)++))) << 16L, \ + l |= ((uint32_t)(*((c)++))) << 24L) + +#define c2ln(c, l1, l2, n) \ + { \ + c += n; \ + l1 = l2 = 0; \ + switch (n) { \ + case 8: \ + l2 = ((uint32_t)(*(--(c)))) << 24L; \ + case 7: \ + l2 |= ((uint32_t)(*(--(c)))) << 16L; \ + case 6: \ + l2 |= ((uint32_t)(*(--(c)))) << 8L; \ + case 5: \ + l2 |= ((uint32_t)(*(--(c)))); \ + case 4: \ + l1 = ((uint32_t)(*(--(c)))) << 24L; \ + case 3: \ + l1 |= ((uint32_t)(*(--(c)))) << 16L; \ + case 2: \ + l1 |= ((uint32_t)(*(--(c)))) << 8L; \ + case 1: \ + l1 |= ((uint32_t)(*(--(c)))); \ + } \ + } + +#define l2c(l, c) \ + (*((c)++) = (uint8_t)(((l)) & 0xff), \ + *((c)++) = (uint8_t)(((l) >> 8L) & 0xff), \ + *((c)++) = (uint8_t)(((l) >> 16L) & 0xff), \ + *((c)++) = (uint8_t)(((l) >> 24L) & 0xff)) + +#define l2cn(l1, l2, c, n) \ + { \ + c += n; \ + switch (n) { \ + case 8: \ + *(--(c)) = (uint8_t)(((l2) >> 24L) & 0xff); \ + case 7: \ + *(--(c)) = (uint8_t)(((l2) >> 16L) & 0xff); \ + case 6: \ + *(--(c)) = (uint8_t)(((l2) >> 8L) & 0xff); \ + case 5: \ + *(--(c)) = (uint8_t)(((l2)) & 0xff); \ + case 4: \ + *(--(c)) = (uint8_t)(((l1) >> 24L) & 0xff); \ + case 3: \ + *(--(c)) = (uint8_t)(((l1) >> 16L) & 0xff); \ + case 2: \ + *(--(c)) = (uint8_t)(((l1) >> 8L) & 0xff); \ + case 1: \ + *(--(c)) = (uint8_t)(((l1)) & 0xff); \ + } \ + } + +typedef struct rc2_key_st { uint16_t data[64]; } RC2_KEY; + +static void RC2_encrypt(uint32_t *d, RC2_KEY *key) { + int i, n; + uint16_t *p0, *p1; + uint16_t x0, x1, x2, x3, t; + uint32_t l; + + l = d[0]; + x0 = (uint16_t)l & 0xffff; + x1 = (uint16_t)(l >> 16L); + l = d[1]; + x2 = (uint16_t)l & 0xffff; + x3 = (uint16_t)(l >> 16L); + + n = 3; + i = 5; + + p0 = p1 = &key->data[0]; + for (;;) { + t = (x0 + (x1 & ~x3) + (x2 & x3) + *(p0++)) & 0xffff; + x0 = (t << 1) | (t >> 15); + t = (x1 + (x2 & ~x0) + (x3 & x0) + *(p0++)) & 0xffff; + x1 = (t << 2) | (t >> 14); + t = (x2 + (x3 & ~x1) + (x0 & x1) + *(p0++)) & 0xffff; + x2 = (t << 3) | (t >> 13); + t = (x3 + (x0 & ~x2) + (x1 & x2) + *(p0++)) & 0xffff; + x3 = (t << 5) | (t >> 11); + + if (--i == 0) { + if (--n == 0) { + break; + } + i = (n == 2) ? 6 : 5; + + x0 += p1[x3 & 0x3f]; + x1 += p1[x0 & 0x3f]; + x2 += p1[x1 & 0x3f]; + x3 += p1[x2 & 0x3f]; + } + } + + d[0] = (uint32_t)(x0 & 0xffff) | ((uint32_t)(x1 & 0xffff) << 16L); + d[1] = (uint32_t)(x2 & 0xffff) | ((uint32_t)(x3 & 0xffff) << 16L); +} + +static void RC2_decrypt(uint32_t *d, RC2_KEY *key) { + int i, n; + uint16_t *p0, *p1; + uint16_t x0, x1, x2, x3, t; + uint32_t l; + + l = d[0]; + x0 = (uint16_t)l & 0xffff; + x1 = (uint16_t)(l >> 16L); + l = d[1]; + x2 = (uint16_t)l & 0xffff; + x3 = (uint16_t)(l >> 16L); + + n = 3; + i = 5; + + p0 = &key->data[63]; + p1 = &key->data[0]; + for (;;) { + t = ((x3 << 11) | (x3 >> 5)) & 0xffff; + x3 = (t - (x0 & ~x2) - (x1 & x2) - *(p0--)) & 0xffff; + t = ((x2 << 13) | (x2 >> 3)) & 0xffff; + x2 = (t - (x3 & ~x1) - (x0 & x1) - *(p0--)) & 0xffff; + t = ((x1 << 14) | (x1 >> 2)) & 0xffff; + x1 = (t - (x2 & ~x0) - (x3 & x0) - *(p0--)) & 0xffff; + t = ((x0 << 15) | (x0 >> 1)) & 0xffff; + x0 = (t - (x1 & ~x3) - (x2 & x3) - *(p0--)) & 0xffff; + + if (--i == 0) { + if (--n == 0) { + break; + } + i = (n == 2) ? 6 : 5; + + x3 = (x3 - p1[x2 & 0x3f]) & 0xffff; + x2 = (x2 - p1[x1 & 0x3f]) & 0xffff; + x1 = (x1 - p1[x0 & 0x3f]) & 0xffff; + x0 = (x0 - p1[x3 & 0x3f]) & 0xffff; + } + } + + d[0] = (uint32_t)(x0 & 0xffff) | ((uint32_t)(x1 & 0xffff) << 16L); + d[1] = (uint32_t)(x2 & 0xffff) | ((uint32_t)(x3 & 0xffff) << 16L); +} + +static void RC2_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t length, + RC2_KEY *ks, uint8_t *iv, int encrypt) { + uint32_t tin0, tin1; + uint32_t tout0, tout1, xor0, xor1; + long l = length; + uint32_t tin[2]; + + if (encrypt) { + c2l(iv, tout0); + c2l(iv, tout1); + iv -= 8; + for (l -= 8; l >= 0; l -= 8) { + c2l(in, tin0); + c2l(in, tin1); + tin0 ^= tout0; + tin1 ^= tout1; + tin[0] = tin0; + tin[1] = tin1; + RC2_encrypt(tin, ks); + tout0 = tin[0]; + l2c(tout0, out); + tout1 = tin[1]; + l2c(tout1, out); + } + if (l != -8) { + c2ln(in, tin0, tin1, l + 8); + tin0 ^= tout0; + tin1 ^= tout1; + tin[0] = tin0; + tin[1] = tin1; + RC2_encrypt(tin, ks); + tout0 = tin[0]; + l2c(tout0, out); + tout1 = tin[1]; + l2c(tout1, out); + } + l2c(tout0, iv); + l2c(tout1, iv); + } else { + c2l(iv, xor0); + c2l(iv, xor1); + iv -= 8; + for (l -= 8; l >= 0; l -= 8) { + c2l(in, tin0); + tin[0] = tin0; + c2l(in, tin1); + tin[1] = tin1; + RC2_decrypt(tin, ks); + tout0 = tin[0] ^ xor0; + tout1 = tin[1] ^ xor1; + l2c(tout0, out); + l2c(tout1, out); + xor0 = tin0; + xor1 = tin1; + } + if (l != -8) { + c2l(in, tin0); + tin[0] = tin0; + c2l(in, tin1); + tin[1] = tin1; + RC2_decrypt(tin, ks); + tout0 = tin[0] ^ xor0; + tout1 = tin[1] ^ xor1; + l2cn(tout0, tout1, out, l + 8); + xor0 = tin0; + xor1 = tin1; + } + l2c(xor0, iv); + l2c(xor1, iv); + } + tin[0] = tin[1] = 0; +} + +static const uint8_t key_table[256] = { + 0xd9, 0x78, 0xf9, 0xc4, 0x19, 0xdd, 0xb5, 0xed, 0x28, 0xe9, 0xfd, 0x79, + 0x4a, 0xa0, 0xd8, 0x9d, 0xc6, 0x7e, 0x37, 0x83, 0x2b, 0x76, 0x53, 0x8e, + 0x62, 0x4c, 0x64, 0x88, 0x44, 0x8b, 0xfb, 0xa2, 0x17, 0x9a, 0x59, 0xf5, + 0x87, 0xb3, 0x4f, 0x13, 0x61, 0x45, 0x6d, 0x8d, 0x09, 0x81, 0x7d, 0x32, + 0xbd, 0x8f, 0x40, 0xeb, 0x86, 0xb7, 0x7b, 0x0b, 0xf0, 0x95, 0x21, 0x22, + 0x5c, 0x6b, 0x4e, 0x82, 0x54, 0xd6, 0x65, 0x93, 0xce, 0x60, 0xb2, 0x1c, + 0x73, 0x56, 0xc0, 0x14, 0xa7, 0x8c, 0xf1, 0xdc, 0x12, 0x75, 0xca, 0x1f, + 0x3b, 0xbe, 0xe4, 0xd1, 0x42, 0x3d, 0xd4, 0x30, 0xa3, 0x3c, 0xb6, 0x26, + 0x6f, 0xbf, 0x0e, 0xda, 0x46, 0x69, 0x07, 0x57, 0x27, 0xf2, 0x1d, 0x9b, + 0xbc, 0x94, 0x43, 0x03, 0xf8, 0x11, 0xc7, 0xf6, 0x90, 0xef, 0x3e, 0xe7, + 0x06, 0xc3, 0xd5, 0x2f, 0xc8, 0x66, 0x1e, 0xd7, 0x08, 0xe8, 0xea, 0xde, + 0x80, 0x52, 0xee, 0xf7, 0x84, 0xaa, 0x72, 0xac, 0x35, 0x4d, 0x6a, 0x2a, + 0x96, 0x1a, 0xd2, 0x71, 0x5a, 0x15, 0x49, 0x74, 0x4b, 0x9f, 0xd0, 0x5e, + 0x04, 0x18, 0xa4, 0xec, 0xc2, 0xe0, 0x41, 0x6e, 0x0f, 0x51, 0xcb, 0xcc, + 0x24, 0x91, 0xaf, 0x50, 0xa1, 0xf4, 0x70, 0x39, 0x99, 0x7c, 0x3a, 0x85, + 0x23, 0xb8, 0xb4, 0x7a, 0xfc, 0x02, 0x36, 0x5b, 0x25, 0x55, 0x97, 0x31, + 0x2d, 0x5d, 0xfa, 0x98, 0xe3, 0x8a, 0x92, 0xae, 0x05, 0xdf, 0x29, 0x10, + 0x67, 0x6c, 0xba, 0xc9, 0xd3, 0x00, 0xe6, 0xcf, 0xe1, 0x9e, 0xa8, 0x2c, + 0x63, 0x16, 0x01, 0x3f, 0x58, 0xe2, 0x89, 0xa9, 0x0d, 0x38, 0x34, 0x1b, + 0xab, 0x33, 0xff, 0xb0, 0xbb, 0x48, 0x0c, 0x5f, 0xb9, 0xb1, 0xcd, 0x2e, + 0xc5, 0xf3, 0xdb, 0x47, 0xe5, 0xa5, 0x9c, 0x77, 0x0a, 0xa6, 0x20, 0x68, + 0xfe, 0x7f, 0xc1, 0xad, +}; + +static void RC2_set_key(RC2_KEY *key, int len, const uint8_t *data, int bits) { + int i, j; + uint8_t *k; + uint16_t *ki; + unsigned int c, d; + + k = (uint8_t *)&key->data[0]; + *k = 0; /* for if there is a zero length key */ + + if (len > 128) { + len = 128; + } + if (bits <= 0) { + bits = 1024; + } + if (bits > 1024) { + bits = 1024; + } + + for (i = 0; i < len; i++) { + k[i] = data[i]; + } + + /* expand table */ + d = k[len - 1]; + j = 0; + for (i = len; i < 128; i++, j++) { + d = key_table[(k[j] + d) & 0xff]; + k[i] = d; + } + + /* hmm.... key reduction to 'bits' bits */ + + j = (bits + 7) >> 3; + i = 128 - j; + c = (0xff >> (-bits & 0x07)); + + d = key_table[k[i] & c]; + k[i] = d; + while (i--) { + d = key_table[k[i + j] ^ d]; + k[i] = d; + } + + /* copy from bytes into uint16_t's */ + ki = &(key->data[63]); + for (i = 127; i >= 0; i -= 2) { + *(ki--) = ((k[i] << 8) | k[i - 1]) & 0xffff; + } +} + +typedef struct { + int key_bits; /* effective key bits */ + RC2_KEY ks; /* key schedule */ +} EVP_RC2_KEY; + +static int rc2_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key, + const uint8_t *iv, int enc) { + EVP_RC2_KEY *rc2_key = (EVP_RC2_KEY *)ctx->cipher_data; + RC2_set_key(&rc2_key->ks, EVP_CIPHER_CTX_key_length(ctx), key, + rc2_key->key_bits); + return 1; +} + +static int rc2_cbc_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in, + size_t inl) { + EVP_RC2_KEY *key = (EVP_RC2_KEY *)ctx->cipher_data; + static const size_t kChunkSize = 0x10000; + + while (inl >= kChunkSize) { + RC2_cbc_encrypt(in, out, kChunkSize, &key->ks, ctx->iv, ctx->encrypt); + inl -= kChunkSize; + in += kChunkSize; + out += kChunkSize; + } + if (inl) { + RC2_cbc_encrypt(in, out, inl, &key->ks, ctx->iv, ctx->encrypt); + } + return 1; +} + +static int rc2_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr) { + EVP_RC2_KEY *key = (EVP_RC2_KEY *)ctx->cipher_data; + + switch (type) { + case EVP_CTRL_INIT: + key->key_bits = EVP_CIPHER_CTX_key_length(ctx) * 8; + return 1; + case EVP_CTRL_SET_RC2_KEY_BITS: + /* Should be overridden by later call to |EVP_CTRL_INIT|, but + * people call it, so it may as well work. */ + key->key_bits = arg; + return 1; + + default: + return -1; + } +} + +static const EVP_CIPHER rc2_40_cbc = { + NID_rc2_40_cbc, + 8 /* block size */, + 5 /* 40 bit */, + 8 /* iv len */, + sizeof(EVP_RC2_KEY), + EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CTRL_INIT, + NULL /* app_data */, + rc2_init_key, + rc2_cbc_cipher, + NULL, + rc2_ctrl, +}; + +const EVP_CIPHER *EVP_rc2_40_cbc(void) { + return &rc2_40_cbc; +} + +static const EVP_CIPHER rc2_cbc = { + NID_rc2_cbc, + 8 /* block size */, + 16 /* 128 bit */, + 8 /* iv len */, + sizeof(EVP_RC2_KEY), + EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CTRL_INIT, + NULL /* app_data */, + rc2_init_key, + rc2_cbc_cipher, + NULL, + rc2_ctrl, +}; + +const EVP_CIPHER *EVP_rc2_cbc(void) { + return &rc2_cbc; +} diff --git a/external/boringssl/crypto/cipher/e_rc4.c b/external/boringssl/crypto/cipher/e_rc4.c new file mode 100644 index 0000000000..e7c2ccaffd --- /dev/null +++ b/external/boringssl/crypto/cipher/e_rc4.c @@ -0,0 +1,87 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include +#include + +#include +#include +#include + + +static int rc4_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key, + const uint8_t *iv, int enc) { + RC4_KEY *rc4key = (RC4_KEY *)ctx->cipher_data; + + RC4_set_key(rc4key, EVP_CIPHER_CTX_key_length(ctx), key); + return 1; +} + +static int rc4_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in, + size_t in_len) { + RC4_KEY *rc4key = (RC4_KEY *)ctx->cipher_data; + + RC4(rc4key, in_len, in, out); + return 1; +} + +static const EVP_CIPHER rc4 = { + NID_rc4, 1 /* block_size */, 16 /* key_size */, + 0 /* iv_len */, sizeof(RC4_KEY), EVP_CIPH_VARIABLE_LENGTH, + NULL /* app_data */, rc4_init_key, rc4_cipher, + NULL /* cleanup */, NULL /* ctrl */, }; + +const EVP_CIPHER *EVP_rc4(void) { return &rc4; } diff --git a/external/boringssl/crypto/cipher/e_ssl3.c b/external/boringssl/crypto/cipher/e_ssl3.c new file mode 100644 index 0000000000..7dddf242f7 --- /dev/null +++ b/external/boringssl/crypto/cipher/e_ssl3.c @@ -0,0 +1,463 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "internal.h" + + +typedef struct { + EVP_CIPHER_CTX cipher_ctx; + EVP_MD_CTX md_ctx; +} AEAD_SSL3_CTX; + +static int ssl3_mac(AEAD_SSL3_CTX *ssl3_ctx, uint8_t *out, unsigned *out_len, + const uint8_t *ad, size_t ad_len, const uint8_t *in, + size_t in_len) { + size_t md_size = EVP_MD_CTX_size(&ssl3_ctx->md_ctx); + size_t pad_len = (md_size == 20) ? 40 : 48; + + /* To allow for CBC mode which changes cipher length, |ad| doesn't include the + * length for legacy ciphers. */ + uint8_t ad_extra[2]; + ad_extra[0] = (uint8_t)(in_len >> 8); + ad_extra[1] = (uint8_t)(in_len & 0xff); + + EVP_MD_CTX md_ctx; + EVP_MD_CTX_init(&md_ctx); + + uint8_t pad[48]; + uint8_t tmp[EVP_MAX_MD_SIZE]; + memset(pad, 0x36, pad_len); + if (!EVP_MD_CTX_copy_ex(&md_ctx, &ssl3_ctx->md_ctx) || + !EVP_DigestUpdate(&md_ctx, pad, pad_len) || + !EVP_DigestUpdate(&md_ctx, ad, ad_len) || + !EVP_DigestUpdate(&md_ctx, ad_extra, sizeof(ad_extra)) || + !EVP_DigestUpdate(&md_ctx, in, in_len) || + !EVP_DigestFinal_ex(&md_ctx, tmp, NULL)) { + EVP_MD_CTX_cleanup(&md_ctx); + return 0; + } + + memset(pad, 0x5c, pad_len); + if (!EVP_MD_CTX_copy_ex(&md_ctx, &ssl3_ctx->md_ctx) || + !EVP_DigestUpdate(&md_ctx, pad, pad_len) || + !EVP_DigestUpdate(&md_ctx, tmp, md_size) || + !EVP_DigestFinal_ex(&md_ctx, out, out_len)) { + EVP_MD_CTX_cleanup(&md_ctx); + return 0; + } + EVP_MD_CTX_cleanup(&md_ctx); + return 1; +} + +static void aead_ssl3_cleanup(EVP_AEAD_CTX *ctx) { + AEAD_SSL3_CTX *ssl3_ctx = (AEAD_SSL3_CTX *)ctx->aead_state; + EVP_CIPHER_CTX_cleanup(&ssl3_ctx->cipher_ctx); + EVP_MD_CTX_cleanup(&ssl3_ctx->md_ctx); + OPENSSL_free(ssl3_ctx); + ctx->aead_state = NULL; +} + +static int aead_ssl3_init(EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len, + size_t tag_len, enum evp_aead_direction_t dir, + const EVP_CIPHER *cipher, const EVP_MD *md) { + if (tag_len != EVP_AEAD_DEFAULT_TAG_LENGTH && + tag_len != EVP_MD_size(md)) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_TAG_SIZE); + return 0; + } + + if (key_len != EVP_AEAD_key_length(ctx->aead)) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_KEY_LENGTH); + return 0; + } + + size_t mac_key_len = EVP_MD_size(md); + size_t enc_key_len = EVP_CIPHER_key_length(cipher); + assert(mac_key_len + enc_key_len + EVP_CIPHER_iv_length(cipher) == key_len); + /* Although EVP_rc4() is a variable-length cipher, the default key size is + * correct for SSL3. */ + + AEAD_SSL3_CTX *ssl3_ctx = OPENSSL_malloc(sizeof(AEAD_SSL3_CTX)); + if (ssl3_ctx == NULL) { + OPENSSL_PUT_ERROR(CIPHER, ERR_R_MALLOC_FAILURE); + return 0; + } + EVP_CIPHER_CTX_init(&ssl3_ctx->cipher_ctx); + EVP_MD_CTX_init(&ssl3_ctx->md_ctx); + + ctx->aead_state = ssl3_ctx; + if (!EVP_CipherInit_ex(&ssl3_ctx->cipher_ctx, cipher, NULL, &key[mac_key_len], + &key[mac_key_len + enc_key_len], + dir == evp_aead_seal) || + !EVP_DigestInit_ex(&ssl3_ctx->md_ctx, md, NULL) || + !EVP_DigestUpdate(&ssl3_ctx->md_ctx, key, mac_key_len)) { + aead_ssl3_cleanup(ctx); + ctx->aead_state = NULL; + return 0; + } + EVP_CIPHER_CTX_set_padding(&ssl3_ctx->cipher_ctx, 0); + + return 1; +} + +static int aead_ssl3_seal(const EVP_AEAD_CTX *ctx, uint8_t *out, + size_t *out_len, size_t max_out_len, + const uint8_t *nonce, size_t nonce_len, + const uint8_t *in, size_t in_len, + const uint8_t *ad, size_t ad_len) { + AEAD_SSL3_CTX *ssl3_ctx = (AEAD_SSL3_CTX *)ctx->aead_state; + size_t total = 0; + + if (!ssl3_ctx->cipher_ctx.encrypt) { + /* Unlike a normal AEAD, an SSL3 AEAD may only be used in one direction. */ + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_OPERATION); + return 0; + } + + if (in_len + EVP_AEAD_max_overhead(ctx->aead) < in_len || + in_len > INT_MAX) { + /* EVP_CIPHER takes int as input. */ + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE); + return 0; + } + + if (max_out_len < in_len + EVP_AEAD_max_overhead(ctx->aead)) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL); + return 0; + } + + if (nonce_len != 0) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_IV_TOO_LARGE); + return 0; + } + + if (ad_len != 11 - 2 /* length bytes */) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_AD_SIZE); + return 0; + } + + /* Compute the MAC. This must be first in case the operation is being done + * in-place. */ + uint8_t mac[EVP_MAX_MD_SIZE]; + unsigned mac_len; + if (!ssl3_mac(ssl3_ctx, mac, &mac_len, ad, ad_len, in, in_len)) { + return 0; + } + + /* Encrypt the input. */ + int len; + if (!EVP_EncryptUpdate(&ssl3_ctx->cipher_ctx, out, &len, in, + (int)in_len)) { + return 0; + } + total = len; + + /* Feed the MAC into the cipher. */ + if (!EVP_EncryptUpdate(&ssl3_ctx->cipher_ctx, out + total, &len, mac, + (int)mac_len)) { + return 0; + } + total += len; + + unsigned block_size = EVP_CIPHER_CTX_block_size(&ssl3_ctx->cipher_ctx); + if (block_size > 1) { + assert(block_size <= 256); + assert(EVP_CIPHER_CTX_mode(&ssl3_ctx->cipher_ctx) == EVP_CIPH_CBC_MODE); + + /* Compute padding and feed that into the cipher. */ + uint8_t padding[256]; + unsigned padding_len = block_size - ((in_len + mac_len) % block_size); + memset(padding, 0, padding_len - 1); + padding[padding_len - 1] = padding_len - 1; + if (!EVP_EncryptUpdate(&ssl3_ctx->cipher_ctx, out + total, &len, padding, + (int)padding_len)) { + return 0; + } + total += len; + } + + if (!EVP_EncryptFinal_ex(&ssl3_ctx->cipher_ctx, out + total, &len)) { + return 0; + } + total += len; + + *out_len = total; + return 1; +} + +static int aead_ssl3_open(const EVP_AEAD_CTX *ctx, uint8_t *out, + size_t *out_len, size_t max_out_len, + const uint8_t *nonce, size_t nonce_len, + const uint8_t *in, size_t in_len, + const uint8_t *ad, size_t ad_len) { + AEAD_SSL3_CTX *ssl3_ctx = (AEAD_SSL3_CTX *)ctx->aead_state; + + if (ssl3_ctx->cipher_ctx.encrypt) { + /* Unlike a normal AEAD, an SSL3 AEAD may only be used in one direction. */ + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_OPERATION); + return 0; + } + + size_t mac_len = EVP_MD_CTX_size(&ssl3_ctx->md_ctx); + if (in_len < mac_len) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT); + return 0; + } + + if (max_out_len < in_len) { + /* This requires that the caller provide space for the MAC, even though it + * will always be removed on return. */ + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL); + return 0; + } + + if (nonce_len != 0) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE); + return 0; + } + + if (ad_len != 11 - 2 /* length bytes */) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_AD_SIZE); + return 0; + } + + if (in_len > INT_MAX) { + /* EVP_CIPHER takes int as input. */ + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE); + return 0; + } + + /* Decrypt to get the plaintext + MAC + padding. */ + size_t total = 0; + int len; + if (!EVP_DecryptUpdate(&ssl3_ctx->cipher_ctx, out, &len, in, (int)in_len)) { + return 0; + } + total += len; + if (!EVP_DecryptFinal_ex(&ssl3_ctx->cipher_ctx, out + total, &len)) { + return 0; + } + total += len; + assert(total == in_len); + + /* Remove CBC padding and MAC. This would normally be timing-sensitive, but SSLv3 CBC + * ciphers are already broken. Support will be removed eventually. + * https://www.openssl.org/~bodo/ssl-poodle.pdf */ + unsigned data_len; + if (EVP_CIPHER_CTX_mode(&ssl3_ctx->cipher_ctx) == EVP_CIPH_CBC_MODE) { + unsigned padding_length = out[total - 1]; + if (total < padding_length + 1 + mac_len) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT); + return 0; + } + /* The padding must be minimal. */ + if (padding_length + 1 > EVP_CIPHER_CTX_block_size(&ssl3_ctx->cipher_ctx)) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT); + return 0; + } + data_len = total - padding_length - 1 - mac_len; + } else { + data_len = total - mac_len; + } + + /* Compute the MAC and compare against the one in the record. */ + uint8_t mac[EVP_MAX_MD_SIZE]; + if (!ssl3_mac(ssl3_ctx, mac, NULL, ad, ad_len, out, data_len)) { + return 0; + } + if (CRYPTO_memcmp(&out[data_len], mac, mac_len) != 0) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT); + return 0; + } + + *out_len = data_len; + return 1; +} + +static int aead_ssl3_get_rc4_state(const EVP_AEAD_CTX *ctx, const RC4_KEY **out_key) { + AEAD_SSL3_CTX *ssl3_ctx = (AEAD_SSL3_CTX *)ctx->aead_state; + if (EVP_CIPHER_CTX_cipher(&ssl3_ctx->cipher_ctx) != EVP_rc4()) { + return 0; + } + + *out_key = (RC4_KEY*) ssl3_ctx->cipher_ctx.cipher_data; + return 1; +} + +static int aead_ssl3_get_iv(const EVP_AEAD_CTX *ctx, const uint8_t **out_iv, + size_t *out_iv_len) { + AEAD_SSL3_CTX *ssl3_ctx = (AEAD_SSL3_CTX *)ctx->aead_state; + const size_t iv_len = EVP_CIPHER_CTX_iv_length(&ssl3_ctx->cipher_ctx); + if (iv_len <= 1) { + return 0; + } + + *out_iv = ssl3_ctx->cipher_ctx.iv; + *out_iv_len = iv_len; + return 1; +} + +static int aead_rc4_md5_ssl3_init(EVP_AEAD_CTX *ctx, const uint8_t *key, + size_t key_len, size_t tag_len, + enum evp_aead_direction_t dir) { + return aead_ssl3_init(ctx, key, key_len, tag_len, dir, EVP_rc4(), EVP_md5()); +} + +static int aead_rc4_sha1_ssl3_init(EVP_AEAD_CTX *ctx, const uint8_t *key, + size_t key_len, size_t tag_len, + enum evp_aead_direction_t dir) { + return aead_ssl3_init(ctx, key, key_len, tag_len, dir, EVP_rc4(), EVP_sha1()); +} + +static int aead_aes_128_cbc_sha1_ssl3_init(EVP_AEAD_CTX *ctx, const uint8_t *key, + size_t key_len, size_t tag_len, + enum evp_aead_direction_t dir) { + return aead_ssl3_init(ctx, key, key_len, tag_len, dir, EVP_aes_128_cbc(), + EVP_sha1()); +} + +static int aead_aes_256_cbc_sha1_ssl3_init(EVP_AEAD_CTX *ctx, const uint8_t *key, + size_t key_len, size_t tag_len, + enum evp_aead_direction_t dir) { + return aead_ssl3_init(ctx, key, key_len, tag_len, dir, EVP_aes_256_cbc(), + EVP_sha1()); +} +static int aead_des_ede3_cbc_sha1_ssl3_init(EVP_AEAD_CTX *ctx, + const uint8_t *key, size_t key_len, + size_t tag_len, + enum evp_aead_direction_t dir) { + return aead_ssl3_init(ctx, key, key_len, tag_len, dir, EVP_des_ede3_cbc(), + EVP_sha1()); +} + +static int aead_null_sha1_ssl3_init(EVP_AEAD_CTX *ctx, const uint8_t *key, + size_t key_len, size_t tag_len, + enum evp_aead_direction_t dir) { + return aead_ssl3_init(ctx, key, key_len, tag_len, dir, EVP_enc_null(), + EVP_sha1()); +} + +static const EVP_AEAD aead_rc4_md5_ssl3 = { + MD5_DIGEST_LENGTH + 16, /* key len (MD5 + RC4) */ + 0, /* nonce len */ + MD5_DIGEST_LENGTH, /* overhead */ + MD5_DIGEST_LENGTH, /* max tag length */ + NULL, /* init */ + aead_rc4_md5_ssl3_init, + aead_ssl3_cleanup, + aead_ssl3_seal, + aead_ssl3_open, + aead_ssl3_get_rc4_state, + NULL, /* get_iv */ +}; + +static const EVP_AEAD aead_rc4_sha1_ssl3 = { + SHA_DIGEST_LENGTH + 16, /* key len (SHA1 + RC4) */ + 0, /* nonce len */ + SHA_DIGEST_LENGTH, /* overhead */ + SHA_DIGEST_LENGTH, /* max tag length */ + NULL, /* init */ + aead_rc4_sha1_ssl3_init, + aead_ssl3_cleanup, + aead_ssl3_seal, + aead_ssl3_open, + aead_ssl3_get_rc4_state, + NULL, /* get_iv */ +}; + +static const EVP_AEAD aead_aes_128_cbc_sha1_ssl3 = { + SHA_DIGEST_LENGTH + 16 + 16, /* key len (SHA1 + AES128 + IV) */ + 0, /* nonce len */ + 16 + SHA_DIGEST_LENGTH, /* overhead (padding + SHA1) */ + SHA_DIGEST_LENGTH, /* max tag length */ + NULL, /* init */ + aead_aes_128_cbc_sha1_ssl3_init, + aead_ssl3_cleanup, + aead_ssl3_seal, + aead_ssl3_open, + NULL, /* get_rc4_state */ + aead_ssl3_get_iv, +}; + +static const EVP_AEAD aead_aes_256_cbc_sha1_ssl3 = { + SHA_DIGEST_LENGTH + 32 + 16, /* key len (SHA1 + AES256 + IV) */ + 0, /* nonce len */ + 16 + SHA_DIGEST_LENGTH, /* overhead (padding + SHA1) */ + SHA_DIGEST_LENGTH, /* max tag length */ + NULL, /* init */ + aead_aes_256_cbc_sha1_ssl3_init, + aead_ssl3_cleanup, + aead_ssl3_seal, + aead_ssl3_open, + NULL, /* get_rc4_state */ + aead_ssl3_get_iv, +}; + +static const EVP_AEAD aead_des_ede3_cbc_sha1_ssl3 = { + SHA_DIGEST_LENGTH + 24 + 8, /* key len (SHA1 + 3DES + IV) */ + 0, /* nonce len */ + 8 + SHA_DIGEST_LENGTH, /* overhead (padding + SHA1) */ + SHA_DIGEST_LENGTH, /* max tag length */ + NULL, /* init */ + aead_des_ede3_cbc_sha1_ssl3_init, + aead_ssl3_cleanup, + aead_ssl3_seal, + aead_ssl3_open, + NULL, /* get_rc4_state */ + aead_ssl3_get_iv, +}; + +static const EVP_AEAD aead_null_sha1_ssl3 = { + SHA_DIGEST_LENGTH, /* key len */ + 0, /* nonce len */ + SHA_DIGEST_LENGTH, /* overhead (SHA1) */ + SHA_DIGEST_LENGTH, /* max tag length */ + NULL, /* init */ + aead_null_sha1_ssl3_init, + aead_ssl3_cleanup, + aead_ssl3_seal, + aead_ssl3_open, + NULL, /* get_rc4_state */ + NULL, /* get_iv */ +}; + +const EVP_AEAD *EVP_aead_rc4_md5_ssl3(void) { return &aead_rc4_md5_ssl3; } + +const EVP_AEAD *EVP_aead_rc4_sha1_ssl3(void) { return &aead_rc4_sha1_ssl3; } + +const EVP_AEAD *EVP_aead_aes_128_cbc_sha1_ssl3(void) { + return &aead_aes_128_cbc_sha1_ssl3; +} + +const EVP_AEAD *EVP_aead_aes_256_cbc_sha1_ssl3(void) { + return &aead_aes_256_cbc_sha1_ssl3; +} + +const EVP_AEAD *EVP_aead_des_ede3_cbc_sha1_ssl3(void) { + return &aead_des_ede3_cbc_sha1_ssl3; +} + +const EVP_AEAD *EVP_aead_null_sha1_ssl3(void) { return &aead_null_sha1_ssl3; } diff --git a/external/boringssl/crypto/cipher/e_tls.c b/external/boringssl/crypto/cipher/e_tls.c new file mode 100644 index 0000000000..b87b0d6ebf --- /dev/null +++ b/external/boringssl/crypto/cipher/e_tls.c @@ -0,0 +1,673 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../crypto/internal.h" +#include "internal.h" + + +typedef struct { + EVP_CIPHER_CTX cipher_ctx; + HMAC_CTX hmac_ctx; + /* mac_key is the portion of the key used for the MAC. It is retained + * separately for the constant-time CBC code. */ + uint8_t mac_key[EVP_MAX_MD_SIZE]; + uint8_t mac_key_len; + /* implicit_iv is one iff this is a pre-TLS-1.1 CBC cipher without an explicit + * IV. */ + char implicit_iv; +} AEAD_TLS_CTX; + +OPENSSL_COMPILE_ASSERT(EVP_MAX_MD_SIZE < 256, mac_key_len_fits_in_uint8_t); + +static void aead_tls_cleanup(EVP_AEAD_CTX *ctx) { + AEAD_TLS_CTX *tls_ctx = (AEAD_TLS_CTX *)ctx->aead_state; + EVP_CIPHER_CTX_cleanup(&tls_ctx->cipher_ctx); + HMAC_CTX_cleanup(&tls_ctx->hmac_ctx); + OPENSSL_cleanse(&tls_ctx->mac_key, sizeof(tls_ctx->mac_key)); + OPENSSL_free(tls_ctx); + ctx->aead_state = NULL; +} + +static int aead_tls_init(EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len, + size_t tag_len, enum evp_aead_direction_t dir, + const EVP_CIPHER *cipher, const EVP_MD *md, + char implicit_iv) { + if (tag_len != EVP_AEAD_DEFAULT_TAG_LENGTH && + tag_len != EVP_MD_size(md)) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_TAG_SIZE); + return 0; + } + + if (key_len != EVP_AEAD_key_length(ctx->aead)) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_KEY_LENGTH); + return 0; + } + + size_t mac_key_len = EVP_MD_size(md); + size_t enc_key_len = EVP_CIPHER_key_length(cipher); + assert(mac_key_len + enc_key_len + + (implicit_iv ? EVP_CIPHER_iv_length(cipher) : 0) == key_len); + /* Although EVP_rc4() is a variable-length cipher, the default key size is + * correct for TLS. */ + + AEAD_TLS_CTX *tls_ctx = OPENSSL_malloc(sizeof(AEAD_TLS_CTX)); + if (tls_ctx == NULL) { + OPENSSL_PUT_ERROR(CIPHER, ERR_R_MALLOC_FAILURE); + return 0; + } + EVP_CIPHER_CTX_init(&tls_ctx->cipher_ctx); + HMAC_CTX_init(&tls_ctx->hmac_ctx); + assert(mac_key_len <= EVP_MAX_MD_SIZE); + memcpy(tls_ctx->mac_key, key, mac_key_len); + tls_ctx->mac_key_len = (uint8_t)mac_key_len; + tls_ctx->implicit_iv = implicit_iv; + + ctx->aead_state = tls_ctx; + if (!EVP_CipherInit_ex(&tls_ctx->cipher_ctx, cipher, NULL, &key[mac_key_len], + implicit_iv ? &key[mac_key_len + enc_key_len] : NULL, + dir == evp_aead_seal) || + !HMAC_Init_ex(&tls_ctx->hmac_ctx, key, mac_key_len, md, NULL)) { + aead_tls_cleanup(ctx); + ctx->aead_state = NULL; + return 0; + } + EVP_CIPHER_CTX_set_padding(&tls_ctx->cipher_ctx, 0); + + return 1; +} + +static int aead_tls_seal(const EVP_AEAD_CTX *ctx, uint8_t *out, + size_t *out_len, size_t max_out_len, + const uint8_t *nonce, size_t nonce_len, + const uint8_t *in, size_t in_len, + const uint8_t *ad, size_t ad_len) { + AEAD_TLS_CTX *tls_ctx = (AEAD_TLS_CTX *)ctx->aead_state; + size_t total = 0; + + if (!tls_ctx->cipher_ctx.encrypt) { + /* Unlike a normal AEAD, a TLS AEAD may only be used in one direction. */ + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_OPERATION); + return 0; + } + + if (in_len + EVP_AEAD_max_overhead(ctx->aead) < in_len || + in_len > INT_MAX) { + /* EVP_CIPHER takes int as input. */ + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE); + return 0; + } + + if (max_out_len < in_len + EVP_AEAD_max_overhead(ctx->aead)) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL); + return 0; + } + + if (nonce_len != EVP_AEAD_nonce_length(ctx->aead)) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_NONCE_SIZE); + return 0; + } + + if (ad_len != 13 - 2 /* length bytes */) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_AD_SIZE); + return 0; + } + + /* To allow for CBC mode which changes cipher length, |ad| doesn't include the + * length for legacy ciphers. */ + uint8_t ad_extra[2]; + ad_extra[0] = (uint8_t)(in_len >> 8); + ad_extra[1] = (uint8_t)(in_len & 0xff); + + /* Compute the MAC. This must be first in case the operation is being done + * in-place. */ + uint8_t mac[EVP_MAX_MD_SIZE]; + unsigned mac_len; + if (!HMAC_Init_ex(&tls_ctx->hmac_ctx, NULL, 0, NULL, NULL) || + !HMAC_Update(&tls_ctx->hmac_ctx, ad, ad_len) || + !HMAC_Update(&tls_ctx->hmac_ctx, ad_extra, sizeof(ad_extra)) || + !HMAC_Update(&tls_ctx->hmac_ctx, in, in_len) || + !HMAC_Final(&tls_ctx->hmac_ctx, mac, &mac_len)) { + return 0; + } + + /* Configure the explicit IV. */ + if (EVP_CIPHER_CTX_mode(&tls_ctx->cipher_ctx) == EVP_CIPH_CBC_MODE && + !tls_ctx->implicit_iv && + !EVP_EncryptInit_ex(&tls_ctx->cipher_ctx, NULL, NULL, NULL, nonce)) { + return 0; + } + + /* Encrypt the input. */ + int len; + if (!EVP_EncryptUpdate(&tls_ctx->cipher_ctx, out, &len, in, + (int)in_len)) { + return 0; + } + total = len; + + /* Feed the MAC into the cipher. */ + if (!EVP_EncryptUpdate(&tls_ctx->cipher_ctx, out + total, &len, mac, + (int)mac_len)) { + return 0; + } + total += len; + + unsigned block_size = EVP_CIPHER_CTX_block_size(&tls_ctx->cipher_ctx); + if (block_size > 1) { + assert(block_size <= 256); + assert(EVP_CIPHER_CTX_mode(&tls_ctx->cipher_ctx) == EVP_CIPH_CBC_MODE); + + /* Compute padding and feed that into the cipher. */ + uint8_t padding[256]; + unsigned padding_len = block_size - ((in_len + mac_len) % block_size); + memset(padding, padding_len - 1, padding_len); + if (!EVP_EncryptUpdate(&tls_ctx->cipher_ctx, out + total, &len, padding, + (int)padding_len)) { + return 0; + } + total += len; + } + + if (!EVP_EncryptFinal_ex(&tls_ctx->cipher_ctx, out + total, &len)) { + return 0; + } + total += len; + + *out_len = total; + return 1; +} + +static int aead_tls_open(const EVP_AEAD_CTX *ctx, uint8_t *out, + size_t *out_len, size_t max_out_len, + const uint8_t *nonce, size_t nonce_len, + const uint8_t *in, size_t in_len, + const uint8_t *ad, size_t ad_len) { + AEAD_TLS_CTX *tls_ctx = (AEAD_TLS_CTX *)ctx->aead_state; + + if (tls_ctx->cipher_ctx.encrypt) { + /* Unlike a normal AEAD, a TLS AEAD may only be used in one direction. */ + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_OPERATION); + return 0; + } + + if (in_len < HMAC_size(&tls_ctx->hmac_ctx)) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT); + return 0; + } + + if (max_out_len < in_len) { + /* This requires that the caller provide space for the MAC, even though it + * will always be removed on return. */ + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL); + return 0; + } + + if (nonce_len != EVP_AEAD_nonce_length(ctx->aead)) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_NONCE_SIZE); + return 0; + } + + if (ad_len != 13 - 2 /* length bytes */) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_AD_SIZE); + return 0; + } + + if (in_len > INT_MAX) { + /* EVP_CIPHER takes int as input. */ + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE); + return 0; + } + + /* Configure the explicit IV. */ + if (EVP_CIPHER_CTX_mode(&tls_ctx->cipher_ctx) == EVP_CIPH_CBC_MODE && + !tls_ctx->implicit_iv && + !EVP_DecryptInit_ex(&tls_ctx->cipher_ctx, NULL, NULL, NULL, nonce)) { + return 0; + } + + /* Decrypt to get the plaintext + MAC + padding. */ + size_t total = 0; + int len; + if (!EVP_DecryptUpdate(&tls_ctx->cipher_ctx, out, &len, in, (int)in_len)) { + return 0; + } + total += len; + if (!EVP_DecryptFinal_ex(&tls_ctx->cipher_ctx, out + total, &len)) { + return 0; + } + total += len; + assert(total == in_len); + + /* Remove CBC padding. Code from here on is timing-sensitive with respect to + * |padding_ok| and |data_plus_mac_len| for CBC ciphers. */ + int padding_ok; + unsigned data_plus_mac_len, data_len; + if (EVP_CIPHER_CTX_mode(&tls_ctx->cipher_ctx) == EVP_CIPH_CBC_MODE) { + padding_ok = EVP_tls_cbc_remove_padding( + &data_plus_mac_len, out, total, + EVP_CIPHER_CTX_block_size(&tls_ctx->cipher_ctx), + (unsigned)HMAC_size(&tls_ctx->hmac_ctx)); + /* Publicly invalid. This can be rejected in non-constant time. */ + if (padding_ok == 0) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT); + return 0; + } + } else { + padding_ok = 1; + data_plus_mac_len = total; + /* |data_plus_mac_len| = |total| = |in_len| at this point. |in_len| has + * already been checked against the MAC size at the top of the function. */ + assert(data_plus_mac_len >= HMAC_size(&tls_ctx->hmac_ctx)); + } + data_len = data_plus_mac_len - HMAC_size(&tls_ctx->hmac_ctx); + + /* At this point, |padding_ok| is 1 or -1. If 1, the padding is valid and the + * first |data_plus_mac_size| bytes after |out| are the plaintext and + * MAC. Either way, |data_plus_mac_size| is large enough to extract a MAC. */ + + /* To allow for CBC mode which changes cipher length, |ad| doesn't include the + * length for legacy ciphers. */ + uint8_t ad_fixed[13]; + memcpy(ad_fixed, ad, 11); + ad_fixed[11] = (uint8_t)(data_len >> 8); + ad_fixed[12] = (uint8_t)(data_len & 0xff); + ad_len += 2; + + /* Compute the MAC and extract the one in the record. */ + uint8_t mac[EVP_MAX_MD_SIZE]; + size_t mac_len; + uint8_t record_mac_tmp[EVP_MAX_MD_SIZE]; + uint8_t *record_mac; + if (EVP_CIPHER_CTX_mode(&tls_ctx->cipher_ctx) == EVP_CIPH_CBC_MODE && + EVP_tls_cbc_record_digest_supported(tls_ctx->hmac_ctx.md)) { + if (!EVP_tls_cbc_digest_record(tls_ctx->hmac_ctx.md, mac, &mac_len, + ad_fixed, out, data_plus_mac_len, total, + tls_ctx->mac_key, tls_ctx->mac_key_len)) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT); + return 0; + } + assert(mac_len == HMAC_size(&tls_ctx->hmac_ctx)); + + record_mac = record_mac_tmp; + EVP_tls_cbc_copy_mac(record_mac, mac_len, out, data_plus_mac_len, total); + } else { + /* We should support the constant-time path for all CBC-mode ciphers + * implemented. */ + assert(EVP_CIPHER_CTX_mode(&tls_ctx->cipher_ctx) != EVP_CIPH_CBC_MODE); + + unsigned mac_len_u; + if (!HMAC_Init_ex(&tls_ctx->hmac_ctx, NULL, 0, NULL, NULL) || + !HMAC_Update(&tls_ctx->hmac_ctx, ad_fixed, ad_len) || + !HMAC_Update(&tls_ctx->hmac_ctx, out, data_len) || + !HMAC_Final(&tls_ctx->hmac_ctx, mac, &mac_len_u)) { + return 0; + } + mac_len = mac_len_u; + + assert(mac_len == HMAC_size(&tls_ctx->hmac_ctx)); + record_mac = &out[data_len]; + } + + /* Perform the MAC check and the padding check in constant-time. It should be + * safe to simply perform the padding check first, but it would not be under a + * different choice of MAC location on padding failure. See + * EVP_tls_cbc_remove_padding. */ + unsigned good = constant_time_eq_int(CRYPTO_memcmp(record_mac, mac, mac_len), + 0); + good &= constant_time_eq_int(padding_ok, 1); + if (!good) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT); + return 0; + } + + /* End of timing-sensitive code. */ + + *out_len = data_len; + return 1; +} + +static int aead_rc4_md5_tls_init(EVP_AEAD_CTX *ctx, const uint8_t *key, + size_t key_len, size_t tag_len, + enum evp_aead_direction_t dir) { + return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_rc4(), EVP_md5(), + 0); +} + +static int aead_rc4_sha1_tls_init(EVP_AEAD_CTX *ctx, const uint8_t *key, + size_t key_len, size_t tag_len, + enum evp_aead_direction_t dir) { + return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_rc4(), EVP_sha1(), + 0); +} + +static int aead_aes_128_cbc_sha1_tls_init(EVP_AEAD_CTX *ctx, const uint8_t *key, + size_t key_len, size_t tag_len, + enum evp_aead_direction_t dir) { + return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_aes_128_cbc(), + EVP_sha1(), 0); +} + +static int aead_aes_128_cbc_sha1_tls_implicit_iv_init( + EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len, size_t tag_len, + enum evp_aead_direction_t dir) { + return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_aes_128_cbc(), + EVP_sha1(), 1); +} + +static int aead_aes_128_cbc_sha256_tls_init(EVP_AEAD_CTX *ctx, + const uint8_t *key, size_t key_len, + size_t tag_len, + enum evp_aead_direction_t dir) { + return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_aes_128_cbc(), + EVP_sha256(), 0); +} + +static int aead_aes_256_cbc_sha1_tls_init(EVP_AEAD_CTX *ctx, const uint8_t *key, + size_t key_len, size_t tag_len, + enum evp_aead_direction_t dir) { + return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_aes_256_cbc(), + EVP_sha1(), 0); +} + +static int aead_aes_256_cbc_sha1_tls_implicit_iv_init( + EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len, size_t tag_len, + enum evp_aead_direction_t dir) { + return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_aes_256_cbc(), + EVP_sha1(), 1); +} + +static int aead_aes_256_cbc_sha256_tls_init(EVP_AEAD_CTX *ctx, + const uint8_t *key, size_t key_len, + size_t tag_len, + enum evp_aead_direction_t dir) { + return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_aes_256_cbc(), + EVP_sha256(), 0); +} + +static int aead_aes_256_cbc_sha384_tls_init(EVP_AEAD_CTX *ctx, + const uint8_t *key, size_t key_len, + size_t tag_len, + enum evp_aead_direction_t dir) { + return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_aes_256_cbc(), + EVP_sha384(), 0); +} + +static int aead_des_ede3_cbc_sha1_tls_init(EVP_AEAD_CTX *ctx, + const uint8_t *key, size_t key_len, + size_t tag_len, + enum evp_aead_direction_t dir) { + return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_des_ede3_cbc(), + EVP_sha1(), 0); +} + +static int aead_des_ede3_cbc_sha1_tls_implicit_iv_init( + EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len, size_t tag_len, + enum evp_aead_direction_t dir) { + return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_des_ede3_cbc(), + EVP_sha1(), 1); +} + +static int aead_rc4_tls_get_rc4_state(const EVP_AEAD_CTX *ctx, + const RC4_KEY **out_key) { + const AEAD_TLS_CTX *tls_ctx = (AEAD_TLS_CTX*) ctx->aead_state; + if (EVP_CIPHER_CTX_cipher(&tls_ctx->cipher_ctx) != EVP_rc4()) { + return 0; + } + + *out_key = (const RC4_KEY*) tls_ctx->cipher_ctx.cipher_data; + return 1; +} + +static int aead_tls_get_iv(const EVP_AEAD_CTX *ctx, const uint8_t **out_iv, + size_t *out_iv_len) { + const AEAD_TLS_CTX *tls_ctx = (AEAD_TLS_CTX*) ctx->aead_state; + const size_t iv_len = EVP_CIPHER_CTX_iv_length(&tls_ctx->cipher_ctx); + if (iv_len <= 1) { + return 0; + } + + *out_iv = tls_ctx->cipher_ctx.iv; + *out_iv_len = iv_len; + return 1; +} + +static int aead_null_sha1_tls_init(EVP_AEAD_CTX *ctx, const uint8_t *key, + size_t key_len, size_t tag_len, + enum evp_aead_direction_t dir) { + return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_enc_null(), + EVP_sha1(), 1 /* implicit iv */); +} + +static const EVP_AEAD aead_rc4_md5_tls = { + MD5_DIGEST_LENGTH + 16, /* key len (MD5 + RC4) */ + 0, /* nonce len */ + MD5_DIGEST_LENGTH, /* overhead */ + MD5_DIGEST_LENGTH, /* max tag length */ + NULL, /* init */ + aead_rc4_md5_tls_init, + aead_tls_cleanup, + aead_tls_seal, + aead_tls_open, + aead_rc4_tls_get_rc4_state, /* get_rc4_state */ + NULL, /* get_iv */ +}; + +static const EVP_AEAD aead_rc4_sha1_tls = { + SHA_DIGEST_LENGTH + 16, /* key len (SHA1 + RC4) */ + 0, /* nonce len */ + SHA_DIGEST_LENGTH, /* overhead */ + SHA_DIGEST_LENGTH, /* max tag length */ + NULL, /* init */ + aead_rc4_sha1_tls_init, + aead_tls_cleanup, + aead_tls_seal, + aead_tls_open, + aead_rc4_tls_get_rc4_state, /* get_rc4_state */ + NULL, /* get_iv */ +}; + +static const EVP_AEAD aead_aes_128_cbc_sha1_tls = { + SHA_DIGEST_LENGTH + 16, /* key len (SHA1 + AES128) */ + 16, /* nonce len (IV) */ + 16 + SHA_DIGEST_LENGTH, /* overhead (padding + SHA1) */ + SHA_DIGEST_LENGTH, /* max tag length */ + NULL, /* init */ + aead_aes_128_cbc_sha1_tls_init, + aead_tls_cleanup, + aead_tls_seal, + aead_tls_open, + NULL, /* get_rc4_state */ + NULL, /* get_iv */ +}; + +static const EVP_AEAD aead_aes_128_cbc_sha1_tls_implicit_iv = { + SHA_DIGEST_LENGTH + 16 + 16, /* key len (SHA1 + AES128 + IV) */ + 0, /* nonce len */ + 16 + SHA_DIGEST_LENGTH, /* overhead (padding + SHA1) */ + SHA_DIGEST_LENGTH, /* max tag length */ + NULL, /* init */ + aead_aes_128_cbc_sha1_tls_implicit_iv_init, + aead_tls_cleanup, + aead_tls_seal, + aead_tls_open, + NULL, /* get_rc4_state */ + aead_tls_get_iv, /* get_iv */ +}; + +static const EVP_AEAD aead_aes_128_cbc_sha256_tls = { + SHA256_DIGEST_LENGTH + 16, /* key len (SHA256 + AES128) */ + 16, /* nonce len (IV) */ + 16 + SHA256_DIGEST_LENGTH, /* overhead (padding + SHA256) */ + SHA256_DIGEST_LENGTH, /* max tag length */ + NULL, /* init */ + aead_aes_128_cbc_sha256_tls_init, + aead_tls_cleanup, + aead_tls_seal, + aead_tls_open, + NULL, /* get_rc4_state */ + NULL, /* get_iv */ +}; + +static const EVP_AEAD aead_aes_256_cbc_sha1_tls = { + SHA_DIGEST_LENGTH + 32, /* key len (SHA1 + AES256) */ + 16, /* nonce len (IV) */ + 16 + SHA_DIGEST_LENGTH, /* overhead (padding + SHA1) */ + SHA_DIGEST_LENGTH, /* max tag length */ + NULL, /* init */ + aead_aes_256_cbc_sha1_tls_init, + aead_tls_cleanup, + aead_tls_seal, + aead_tls_open, + NULL, /* get_rc4_state */ + NULL, /* get_iv */ +}; + +static const EVP_AEAD aead_aes_256_cbc_sha1_tls_implicit_iv = { + SHA_DIGEST_LENGTH + 32 + 16, /* key len (SHA1 + AES256 + IV) */ + 0, /* nonce len */ + 16 + SHA_DIGEST_LENGTH, /* overhead (padding + SHA1) */ + SHA_DIGEST_LENGTH, /* max tag length */ + NULL, /* init */ + aead_aes_256_cbc_sha1_tls_implicit_iv_init, + aead_tls_cleanup, + aead_tls_seal, + aead_tls_open, + NULL, /* get_rc4_state */ + aead_tls_get_iv, /* get_iv */ +}; + +static const EVP_AEAD aead_aes_256_cbc_sha256_tls = { + SHA256_DIGEST_LENGTH + 32, /* key len (SHA256 + AES256) */ + 16, /* nonce len (IV) */ + 16 + SHA256_DIGEST_LENGTH, /* overhead (padding + SHA256) */ + SHA256_DIGEST_LENGTH, /* max tag length */ + NULL, /* init */ + aead_aes_256_cbc_sha256_tls_init, + aead_tls_cleanup, + aead_tls_seal, + aead_tls_open, + NULL, /* get_rc4_state */ + NULL, /* get_iv */ +}; + +static const EVP_AEAD aead_aes_256_cbc_sha384_tls = { + SHA384_DIGEST_LENGTH + 32, /* key len (SHA384 + AES256) */ + 16, /* nonce len (IV) */ + 16 + SHA384_DIGEST_LENGTH, /* overhead (padding + SHA384) */ + SHA384_DIGEST_LENGTH, /* max tag length */ + NULL, /* init */ + aead_aes_256_cbc_sha384_tls_init, + aead_tls_cleanup, + aead_tls_seal, + aead_tls_open, + NULL, /* get_rc4_state */ + NULL, /* get_iv */ +}; + +static const EVP_AEAD aead_des_ede3_cbc_sha1_tls = { + SHA_DIGEST_LENGTH + 24, /* key len (SHA1 + 3DES) */ + 8, /* nonce len (IV) */ + 8 + SHA_DIGEST_LENGTH, /* overhead (padding + SHA1) */ + SHA_DIGEST_LENGTH, /* max tag length */ + NULL, /* init */ + aead_des_ede3_cbc_sha1_tls_init, + aead_tls_cleanup, + aead_tls_seal, + aead_tls_open, + NULL, /* get_rc4_state */ + NULL, /* get_iv */ +}; + +static const EVP_AEAD aead_des_ede3_cbc_sha1_tls_implicit_iv = { + SHA_DIGEST_LENGTH + 24 + 8, /* key len (SHA1 + 3DES + IV) */ + 0, /* nonce len */ + 8 + SHA_DIGEST_LENGTH, /* overhead (padding + SHA1) */ + SHA_DIGEST_LENGTH, /* max tag length */ + NULL, /* init */ + aead_des_ede3_cbc_sha1_tls_implicit_iv_init, + aead_tls_cleanup, + aead_tls_seal, + aead_tls_open, + NULL, /* get_rc4_state */ + aead_tls_get_iv, /* get_iv */ +}; + +static const EVP_AEAD aead_null_sha1_tls = { + SHA_DIGEST_LENGTH, /* key len */ + 0, /* nonce len */ + SHA_DIGEST_LENGTH, /* overhead (SHA1) */ + SHA_DIGEST_LENGTH, /* max tag length */ + NULL, /* init */ + aead_null_sha1_tls_init, + aead_tls_cleanup, + aead_tls_seal, + aead_tls_open, + NULL, /* get_rc4_state */ + NULL, /* get_iv */ +}; + +const EVP_AEAD *EVP_aead_rc4_md5_tls(void) { return &aead_rc4_md5_tls; } + +const EVP_AEAD *EVP_aead_rc4_sha1_tls(void) { return &aead_rc4_sha1_tls; } + +const EVP_AEAD *EVP_aead_aes_128_cbc_sha1_tls(void) { + return &aead_aes_128_cbc_sha1_tls; +} + +const EVP_AEAD *EVP_aead_aes_128_cbc_sha1_tls_implicit_iv(void) { + return &aead_aes_128_cbc_sha1_tls_implicit_iv; +} + +const EVP_AEAD *EVP_aead_aes_128_cbc_sha256_tls(void) { + return &aead_aes_128_cbc_sha256_tls; +} + +const EVP_AEAD *EVP_aead_aes_256_cbc_sha1_tls(void) { + return &aead_aes_256_cbc_sha1_tls; +} + +const EVP_AEAD *EVP_aead_aes_256_cbc_sha1_tls_implicit_iv(void) { + return &aead_aes_256_cbc_sha1_tls_implicit_iv; +} + +const EVP_AEAD *EVP_aead_aes_256_cbc_sha256_tls(void) { + return &aead_aes_256_cbc_sha256_tls; +} + +const EVP_AEAD *EVP_aead_aes_256_cbc_sha384_tls(void) { + return &aead_aes_256_cbc_sha384_tls; +} + +const EVP_AEAD *EVP_aead_des_ede3_cbc_sha1_tls(void) { + return &aead_des_ede3_cbc_sha1_tls; +} + +const EVP_AEAD *EVP_aead_des_ede3_cbc_sha1_tls_implicit_iv(void) { + return &aead_des_ede3_cbc_sha1_tls_implicit_iv; +} + +const EVP_AEAD *EVP_aead_null_sha1_tls(void) { return &aead_null_sha1_tls; } diff --git a/external/boringssl/crypto/cipher/internal.h b/external/boringssl/crypto/cipher/internal.h new file mode 100644 index 0000000000..72ac1189f3 --- /dev/null +++ b/external/boringssl/crypto/cipher/internal.h @@ -0,0 +1,164 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_CIPHER_INTERNAL_H +#define OPENSSL_HEADER_CIPHER_INTERNAL_H + +#include + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* EVP_CIPH_MODE_MASK contains the bits of |flags| that represent the mode. */ +#define EVP_CIPH_MODE_MASK 0x3f + + +/* EVP_AEAD represents a specific AEAD algorithm. */ +struct evp_aead_st { + uint8_t key_len; + uint8_t nonce_len; + uint8_t overhead; + uint8_t max_tag_len; + + /* init initialises an |EVP_AEAD_CTX|. If this call returns zero then + * |cleanup| will not be called for that context. */ + int (*init)(EVP_AEAD_CTX *, const uint8_t *key, size_t key_len, + size_t tag_len); + int (*init_with_direction)(EVP_AEAD_CTX *, const uint8_t *key, size_t key_len, + size_t tag_len, enum evp_aead_direction_t dir); + void (*cleanup)(EVP_AEAD_CTX *); + + int (*seal)(const EVP_AEAD_CTX *ctx, uint8_t *out, size_t *out_len, + size_t max_out_len, const uint8_t *nonce, size_t nonce_len, + const uint8_t *in, size_t in_len, const uint8_t *ad, + size_t ad_len); + + int (*open)(const EVP_AEAD_CTX *ctx, uint8_t *out, size_t *out_len, + size_t max_out_len, const uint8_t *nonce, size_t nonce_len, + const uint8_t *in, size_t in_len, const uint8_t *ad, + size_t ad_len); + + int (*get_rc4_state)(const EVP_AEAD_CTX *ctx, const RC4_KEY **out_key); + + int (*get_iv)(const EVP_AEAD_CTX *ctx, const uint8_t **out_iv, + size_t *out_len); +}; + + +/* EVP_tls_cbc_get_padding determines the padding from the decrypted, TLS, CBC + * record in |in|. This decrypted record should not include any "decrypted" + * explicit IV. It sets |*out_len| to the length with the padding removed or + * |in_len| if invalid. + * + * block_size: the block size of the cipher used to encrypt the record. + * returns: + * 0: (in non-constant time) if the record is publicly invalid. + * 1: if the padding was valid + * -1: otherwise. */ +int EVP_tls_cbc_remove_padding(unsigned *out_len, + const uint8_t *in, unsigned in_len, + unsigned block_size, unsigned mac_size); + +/* EVP_tls_cbc_copy_mac copies |md_size| bytes from the end of the first + * |in_len| bytes of |in| to |out| in constant time (independent of the concrete + * value of |in_len|, which may vary within a 256-byte window). |in| must point + * to a buffer of |orig_len| bytes. + * + * On entry: + * orig_len >= in_len >= md_size + * md_size <= EVP_MAX_MD_SIZE */ +void EVP_tls_cbc_copy_mac(uint8_t *out, unsigned md_size, + const uint8_t *in, unsigned in_len, + unsigned orig_len); + +/* EVP_tls_cbc_record_digest_supported returns 1 iff |md| is a hash function + * which EVP_tls_cbc_digest_record supports. */ +int EVP_tls_cbc_record_digest_supported(const EVP_MD *md); + +/* EVP_tls_cbc_digest_record computes the MAC of a decrypted, padded TLS + * record. + * + * md: the hash function used in the HMAC. + * EVP_tls_cbc_record_digest_supported must return true for this hash. + * md_out: the digest output. At most EVP_MAX_MD_SIZE bytes will be written. + * md_out_size: the number of output bytes is written here. + * header: the 13-byte, TLS record header. + * data: the record data itself + * data_plus_mac_size: the secret, reported length of the data and MAC + * once the padding has been removed. + * data_plus_mac_plus_padding_size: the public length of the whole + * record, including padding. + * + * On entry: by virtue of having been through one of the remove_padding + * functions, above, we know that data_plus_mac_size is large enough to contain + * a padding byte and MAC. (If the padding was invalid, it might contain the + * padding too. ) */ +int EVP_tls_cbc_digest_record(const EVP_MD *md, uint8_t *md_out, + size_t *md_out_size, const uint8_t header[13], + const uint8_t *data, size_t data_plus_mac_size, + size_t data_plus_mac_plus_padding_size, + const uint8_t *mac_secret, + unsigned mac_secret_length); + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_CIPHER_INTERNAL_H */ diff --git a/external/boringssl/crypto/cipher/test/aes_128_cbc_sha1_ssl3_tests.txt.REMOVED.git-id b/external/boringssl/crypto/cipher/test/aes_128_cbc_sha1_ssl3_tests.txt.REMOVED.git-id new file mode 100644 index 0000000000..9ffe136af1 --- /dev/null +++ b/external/boringssl/crypto/cipher/test/aes_128_cbc_sha1_ssl3_tests.txt.REMOVED.git-id @@ -0,0 +1 @@ +5bc08f07c3a6e236a177f67844f1a5012a202ad5 \ No newline at end of file diff --git a/external/boringssl/crypto/cipher/test/aes_128_cbc_sha1_tls_implicit_iv_tests.txt.REMOVED.git-id b/external/boringssl/crypto/cipher/test/aes_128_cbc_sha1_tls_implicit_iv_tests.txt.REMOVED.git-id new file mode 100644 index 0000000000..722430d14f --- /dev/null +++ b/external/boringssl/crypto/cipher/test/aes_128_cbc_sha1_tls_implicit_iv_tests.txt.REMOVED.git-id @@ -0,0 +1 @@ +477f1eb1b47788dad48444b16e5430efe5c0cf2c \ No newline at end of file diff --git a/external/boringssl/crypto/cipher/test/aes_128_cbc_sha1_tls_tests.txt.REMOVED.git-id b/external/boringssl/crypto/cipher/test/aes_128_cbc_sha1_tls_tests.txt.REMOVED.git-id new file mode 100644 index 0000000000..34d71526de --- /dev/null +++ b/external/boringssl/crypto/cipher/test/aes_128_cbc_sha1_tls_tests.txt.REMOVED.git-id @@ -0,0 +1 @@ +2b34b7bfb374532266b4b70a842e62b98e814de1 \ No newline at end of file diff --git a/external/boringssl/crypto/cipher/test/aes_128_cbc_sha256_tls_tests.txt.REMOVED.git-id b/external/boringssl/crypto/cipher/test/aes_128_cbc_sha256_tls_tests.txt.REMOVED.git-id new file mode 100644 index 0000000000..1350dce9ee --- /dev/null +++ b/external/boringssl/crypto/cipher/test/aes_128_cbc_sha256_tls_tests.txt.REMOVED.git-id @@ -0,0 +1 @@ +c6419fa62598adb03186c2d4199ddc79c6ddda0a \ No newline at end of file diff --git a/external/boringssl/crypto/cipher/test/aes_128_ctr_hmac_sha256.txt b/external/boringssl/crypto/cipher/test/aes_128_ctr_hmac_sha256.txt new file mode 100644 index 0000000000..d4803a0fb2 --- /dev/null +++ b/external/boringssl/crypto/cipher/test/aes_128_ctr_hmac_sha256.txt @@ -0,0 +1,336 @@ +KEY: 067b841a2540cb467b75f2188f5da4b5aeb7e0e44582a2b668b5b1ff39e21c4e65745470fb1be1aa909c62fabcf0e6ac +NONCE: 10e0ecb00da5345127407150 +IN: +AD: +CT: +TAG: a82a891565e466957ad5a499d45b579d31acaf582f54d518f8f9c128936dac4c + +KEY: c9d9ef2c808c3f8b22f659c12147104b08cec2390a84f0c4b887ca4c247c8c9dd45e72f48b30b67a8545750387232344 +NONCE: 58bddf96158a3a588bf3ec05 +IN: +AD: 5d +CT: +TAG: 3580c1601d1c9a5b1595d3dee35b0cd9e1b115d8b0abee557b2c207b8d0df5ee + +KEY: f755dc6786e21f39b595389a51d36673e1ffb94ffc066c03873eb31839be6fa319fd31c8bea29f03ff28831861e60b6e +NONCE: bd6c80797f1f4c563b06fd3b +IN: +AD: 78d88005136e312639572343a2d0daf7483d8235291ee3ac002469456b075243dc03380c387030d546c2b1 +CT: +TAG: dede80d810fc449a769c79a5ecd2c0d68e9e0fae567781e623ab2098c88d8a86 + +KEY: 43a0a28fef8b89b8fb0f76de01d802935ad561e27ca9c9fa629347be676a6af758501b6a652f369045da5fef751b56bb +NONCE: 0f6472f1e589c16ca5ad45b2 +IN: +AD: 78e4eafccfc87631f0314c442ba4c07bca36f996a5b3408f9e445d6009a87ded16b33a4af9537a4619cab70d +CT: +TAG: 11fa62dd8374aabe728ebf7e9aa1c02cf8f2dbc29f9aaf1940313f0b7c3e0301 + +KEY: acf8e5f1bd64e6289370650b5b3fd773320025c8b229fd335d9461768cd0a17b4bcc946919932efdc9fc84a7f50768bf +NONCE: 1aecfc90d28bcdcc5a8e3578 +IN: +AD: 6daedbdc69133b56f6a8f098f9f70cdb7e129e51115df385a6d86204a53412cd999cf2e69f45e168efed4742b6 +CT: +TAG: fbe0511ba0ec5709def9966a9b05facf171cddd81ee2cd56e7afc867af465f31 + +KEY: 2773c92e6cddc9a5e5dcaf3893080fd2153f009d807df0b175c76615645f2087539e299d8411b27badb749a9845c5e29 +NONCE: 6d04ed129299651aec0465f8 +IN: +AD: 44219577e361a7a4681172d120a2d653a53ec74bc487ccde4954835943bca413d55c65dc665310148654d8c1e2e6bc2f06ec344473120ad1f95739b993a57f9ec0b3299cc088f385894fff876fc2ce8ce6b77ca253f177ba615101e84e17ad0e60704cff195dcd50eb48c77de409797e0b1c8c4c5b9215a4a0399954a008267b +CT: +TAG: 6ab61ac4493e58e48d071d994a000f1c1f498d22f83c8d2af56b03c155afc57e + +KEY: 23189bf23bc4b734410d1c7ae321c42e144a25347a8029bb925e3d8ac1b92f4eb97227c1dece86ae9dea7d127eb33f9b +NONCE: 30681944cd5d78f46d36ed8a +IN: 59 +AD: +CT: 92 +TAG: 986aa8438da3cf4a98f478f90d24908c6a4e848f299873e649b256f5499d89d9 + +KEY: 463d1148325c5f57af670877068a78203571b8b19f40e9f0373156b7448ab315df86c77d7c85ba6e54b9bc329399f687 +NONCE: cc9d015a4b5a888b36b14d05 +IN: 28 +AD: 6a +CT: 05 +TAG: f66e8dc794b142944fa46d5c04a3e3fe00291668374846d763f2beeffd4ca4a0 + +KEY: 937eaab44e7c7d2cd5bbb053c12e6255e0aaa42cbe7d83025b7a2887eff8f098d019c80af849b0ed7da54a5ba5b39200 +NONCE: 2b160d24df579836e1572ea2 +IN: 9a +AD: 35841a33ba3a6ed3d89a1f76d06c61613d09834847e5a41f8616748e30c14335e5baa43d49fceaf85aeb22 +CT: 80 +TAG: 5e5799c147be0329dbcabf7ecdba6ac595ebc2d06b9d757426fbb31e8b39f62a + +KEY: 68a746f382fcc11c02af7b352b9d710c137a9f59bc5886dc374ca88cdc01b86fe5678fde16cfa846846539f67a429276 +NONCE: b94346c033ac1a3d709c4f09 +IN: ad +AD: ad61c9168debf9974e19759088944e888346aff99f3e2e4522549c8ae332a0f41922972fb7c1d5ff24e7ae4b +CT: 46 +TAG: 62ae92ff64710a9f260da2562e246356e9d749c3584fb9f40d9572307ccbbd31 + +KEY: 6622579d1d6350fd5dff432b69d172cc51f99bdaff50b0a1c0f4cda8d5904581ba8657ba61c6936407243d7fb64b00da +NONCE: a880caa7157a13540d2b724f +IN: 2a +AD: 95a23eafcff892deecaf093109d30290d819851ad5c91061510e54baa2b039b114c815da20f0e3ba2ba4875bdd +CT: ce +TAG: 33f09666f9fd1d92f137d9f3f7092b47b2bd71a7e3139dcd19a803a6b17f2a3a + +KEY: 91ce9dd87c7d11d2c4da41863b6851c40fba786a612e0fbf0d1956a71286dfc61fa10bf7d148cecd72b6ceeb82b68d3f +NONCE: a50dc3d8fd63d3076cc70ff6 +IN: da +AD: 9ce8e1a777c159ec775abbd67d85e84f3550c3296e848dec18b61bbd713a98a033805bfe6e2f2a011dd7fd754708e524168142aeee579cae19c7eab78fa7c42fa335f0c725baf556160beef9e4afd1050a2c8813be6bd14cc6982116d0229d53e9b4de923abf6ba99bdffe1d5f21748ae74caddb077d9f7488b394436222beca +CT: 2b +TAG: 1541cd745bc0259dd72a212474f5c7b8c121dd0289d674e5ba8d56a220d1f1d0 + +KEY: 1ad577d3b47e3fff8528e336a43a7ffef72f811e05b5c69ccfe777b10f29061e289178e394a1c87ba483c7f98ea5431d +NONCE: 1fcaa4757a9e48ed2cb3be62 +IN: 46d30dac550103006c292a9ac05d31 +AD: +CT: 37616eba30c55595fa0ad5d50f91ca +TAG: 5c3ac4010f75adf90f81e775b07ab939e7551a9b8e0486ba33766728ed498245 + +KEY: 6df310dc1847b42c68e50b03d154b73d7f3823354b32759c5369bce1a1b4cd63ccdb911c2dc792acf84b8b8f3fdfb89d +NONCE: 92e6759a31dd556ff9124d73 +IN: 6daba76658db642209e276ff7c8d46 +AD: 32 +CT: ce1814c03037078b6be3252460af48 +TAG: 46e61913f2a1ff6e77faade9a7cd37a82eff3ebec4276fbddff9266b9c9bd873 + +KEY: f848c2300995f5c98dcd0db24574d7c61459ca64c084421c6ad156e80e398904417ee745245ddae91be20fb07e66bdb6 +NONCE: 3b177e11063445717f417d14 +IN: bbf225131c821a6a60817cc65bf699 +AD: 4c5ab4fdbe0018344629349feed5d8c3ae0c5b64f2b093576a2aaa1225e7a50eca01a9962c9b4f8fc5c12a +CT: 1538957e78f3ab0fed77906153d715 +TAG: 2c7760d47407ad7b0d5b85fa4967eaa7b6c0bb6eb16619adde7a191abfdf3da3 + +KEY: d406cac07630ce2c071732a0ec95f55123486d2677465768dc7db13f90902cf172f92e19f57f5cf7c68cd7bde7ee4b4b +NONCE: 766aede0120b634a4be6fa12 +IN: 3804d40090a38d4c97a5fff631068c +AD: 7707b7d0f266284e84c2ecdd5a18832650c3e27d66697616c9e9bb2f8a09a3295de0119582ca3614b9608548 +CT: 91e96462a5dfbe8b7af201158a36dc +TAG: 56623e5813070a0e2f5184aed83b9863301ca02e3108f7afc478d48305e397f8 + +KEY: 42bb22a317ed9f9df8119746e9a1257217e5b0144051ca56f39587021d969bc0acc02795f3bd201031e8c05af08ad079 +NONCE: 0a9f6bace71a1ab21f4917df +IN: 013f7b8c75307158f4f300450e7a78 +AD: cd95a649ae215fe73442a6991e157232cbcabecff6042b87d41557e35b97606d606c3ded54f5d3db7aa2773f67 +CT: e588dbcecbdb7667dccf7fe34f8387 +TAG: b04461748109ed9068c7e9c0446528ef09b01613c3b3aa1ffeed6685ebb550f5 + +KEY: e1cfcbaba3a04b5108ce2a87099a6aae936ee38acd92b7e6b7df0e3bcb9ad18fc579b5d470ef3e04c23459f509852458 +NONCE: 112dd267174bcd81e6fbd924 +IN: 288a1e44b406aebec7b418674f81e7 +AD: 7809d8011c5a963df14fb8981e874119c60b7a9d897d13a05651759db5835deffdd991fbf98b9aa71c79e48bd701b228ba248b6bed874b02da7fcf28a04c38b81c0ff628846015258af30dbf28ea4f3283f664f888fca545f5fc57dccc4ad1dd476c52fba341182ecf783706c5c458bf0ee5ec83454afba78eb8b5ca17af88ec +CT: 80f4e1012d76f6180ca00fd32c8fec +TAG: 6de00bf2fd3c88ab34ca9390f7e559875e43e0f938303816a3a75a35729bc453 + +KEY: 84172547d8608bd9e788a7bb60df2982963716e45f8e63f0c5033327d85c920c5e3776e314246b1694b739c39abfa29f +NONCE: a3f1643bb504b7ce9e5b43c2 +IN: 7e76323eb13e64da9b240a57c95c855b +AD: +CT: 966487c18f025d67b42a04c30d3ff4c3 +TAG: 8bb03d893f0ce8ea4a6a47245bc7f20c72acf8caa466edd01365d0f74c929463 + +KEY: 02dee8f2e63b37fe3cbae9101fed0946e05e5090510bef3324a82e3f27456a45ab1b6cdeddb1fe515ad07aefeee6ccbc +NONCE: 64723d21365d62926d5c2262 +IN: 4f1f132c50a01ad48882ce88655b33f7 +AD: d8 +CT: b102082e14cd9ecc0895f7a6f08ab522 +TAG: 2c09651c1a51cb8a375746236fe258a36e725936ccedbc4dfafee6c3084a4716 + +KEY: 5db57cf6301bab815d38879b35c9db72fd40ac576d259ad5074d0828364050554e9fc08335b5f2bf066b09e50fbe6ba4 +NONCE: 36e5340d844de213c312177a +IN: 41a6e910b14388740ea351eb1df980c9 +AD: 8316a6b9b155b2de5e724f7593ecdcee442eaef7b9ad204eda4744a5e648c2dd84f48ee81397e485953465 +CT: ee21d4d47042415ca27d2ecb11b13d79 +TAG: 5015da5a3339389d39d0fcafb56ef4005b342e69ba47930e84408d33aadf5f2a + +KEY: a493dd6de6fd6584599096442dd9345f6f2d8fc2d426c78eee2b992b4071aba4ce463f3ca293c84b2faf3e8644b6ec25 +NONCE: 4f9be6f788ee960adc650d86 +IN: 4de6e244251091cf13762d20685e9085 +AD: d15da312b7522c18384acdbf6348b5e105557f1790a6a203a65acd73397524681666743f3145048775ad84e3 +CT: bb1296457daa39d889c8f986938d6a39 +TAG: b93548cea90c34d03d6f5683ae2cc78814531b803d42cfe57623fd4bdc8f084c + +KEY: 8cc59ebe2c7375a70915c48d2978a1f720bc0aa2775ce9189ae7b3d5dda9a81e56cde0e0a29939599409b71f0b65f346 +NONCE: b0ab041f37ea1e594f1eddb3 +IN: cd0aeaf6806cb99e6bc1c8c5d830de8c +AD: 8f4b5a9609df757826dbe7e51bb6a2c6f45f601263cf668836193513cf008ab6b36a7d5447039f1268821ec37e +CT: 5d5375b9d9cff6d0c1dbd14221509a0d +TAG: d8850bbc838e068b817c24d018f8f1e1cb8aac0a68392a700f48099f81b6c37c + +KEY: f3e9c507478d3f99dbf3e2421e45929b096ab3f3d4aa4ef9c338c5a1a2425c9936b7df602502d33cbafcf781350da77e +NONCE: d4872a30c9d1fa9001a25afe +IN: 25e05ea69a956b12a9be4ef03ae9d30c +AD: 8b346c20e7c64b805d9c8d325829201753069c60b3f221f31474f55cb20315373ccd7c2a8f215e9efc407ae91b05d8b6d693a3780fdd65d7715cdded86c3d6204055812f3fce897f829d1df9ffaaf48885291701ac1765090c383162dd13d6bac88baa0cb2d748363bbb79843a1594ec6d8778854a63b7c9ffeb6d1fb17e90f1 +CT: 61325c7e0d29e9ad50b9c0fec02d7ef4 +TAG: 4b2d0caece46ce2496445883c03234e900189c22b54390b399d78ee4ebfbb7d4 + +KEY: 3d9b651e65e9239c9e33aafb091b348161ab797901fd0468aedd014e4d5683c8f3f54f20ea6bb07bb25dd258df7bcd5e +NONCE: 32bcf856a14437114e7814cc +IN: 08a667c2923f87a7db6502478d32280bdc +AD: +CT: 5e8e02cc91c732356bb9f1fc599426a379 +TAG: 5449e878d558beff4bc7dfbb5f0195444705cfb259773b4faec524fbaca37ea0 + +KEY: 2124cedb5f3f2558f8b9a2304a29c0df6102333cb4aa10625aa82cd76ab645c73f3b7cbf7c96cacdcb9e0b738e40c042 +NONCE: 7ae419446a3a105beb2fbcc5 +IN: a305dc4a2e50cc8e7a65a4b10b73849636 +AD: 70 +CT: fcaea620f7e9ed1337214c4b432d9869d2 +TAG: bfc739c8504a4d9033ab1915f46c1bf65c5382fe9ed1c134026ba32c63ca131e + +KEY: b027feb1aced8fb3af27a9fd7f531c30991ec1abd9f230a3e5d6ee9fc6a77747013f8e14dcdbd07b0083d0ce23dfa711 +NONCE: a30a6520f933ff5265e6e305 +IN: a705f842d542cb6957fbce21854755c6dc +AD: 447bdaf34dfab9cc3dd7777ebaf80077f391093bac9817bf02ad98db9d3f271282ecaf0ff19652f92076d1 +CT: 3ddcb07c121b498f1abb73bedb527d4df4 +TAG: 55957a0e884dea22d6ace10e5936cdac891f5b54225349ede5c44715f1064b5e + +KEY: ffefb7770a7cf125395703985823f3e926f3722ca0764518fd2b8996577bec03648c8d542af1c6e36b51174b0ba88316 +NONCE: 4c31394b4b24f6251a839891 +IN: f026a1d352c37b204c6c1138abee9a9a75 +AD: 1e7c0f71a3aacd87ea785521ea31f93b1efd0bdf97952e0b84ecd50c706806deffc19caea312b5a9988454d2 +CT: 23c8bae37db93ed9f55f2903e04b7c6a8e +TAG: 89d0a7e7d921dea5bb54c28e79b612688e42506aa69b141de830c8d63bdefcee + +KEY: 453cf5e4f48ce5a961c94af0e1639c156965970f561ac17fe08d5b75975abe3db87412640972e463290800666be80441 +NONCE: b3e3f9708a86c7cdf139e496 +IN: 53f1b11de497cc6ecb411a777dc3d60197 +AD: afe29e074dcce850ac6640230e6b9f66a64587c5fbe8679144e065d3b1700c721833ba8f918e926c9142f5f362 +CT: 15d5f597be46a19566a72c5e843b77f70c +TAG: a561c3375c096a116a721e9404e555a2deaf3f677a8611694281663274708f58 + +KEY: 3d497f81d0652d475bcd85cf53bda13f79ef0afeaec09dd679a6e5ea58f87ba6576269f836096d5ac034594b17073331 +NONCE: 3fb1664830821e2b524890c8 +IN: bd75c313f5c8f6007a2185bc39d0af01bb +AD: 50744ed959e2b8ba5b5f4807e2997ea0b96ebfcdeaa1c6b33853219844592e82ad67abf6ccbb272cfdba6a3e45c07fec4d4a0ebe4235f11d916771a764d9a129d39f6b84f0b5fb4cdf789ca2f5ea306b25d047a9b1a1e2e90905b6fba472e70b2fa25c96602cfa0031f31c68954d7487507081b8e70f8aa1342cb8b4a98ce9c2 +CT: abe3869ac43fd8b429ee8b8539c970bc86 +TAG: 33fcd301c2bf624bccb92a986c2dd5f2ecafc32649ff550eb5312fc81cbce46e + +KEY: 353c3e9f87b40fc0281869c68d9d9bee5c95771dd79998c059bc5ceda71f139fe447cfdf340e9eac57f232b9d230e45d +NONCE: cc7a4b46b02f4e7f96fd34e3 +IN: 44bcb61332930f606276268ddbf3287bcaedb5b25704489cbee63ec839d7a69533dbfb6e95fe5b4694eb485beb1437f0777774868ecf45c8a5b3edafa1d62a +AD: +CT: d038d67b8b690519fafa7467c9fb94135f9bf0bcd8247cd2c30da62ddf37a6d9a3a9bdcf8ec081fb4469c0fc2798e2e30afede7cda384438fd01e5d672dcb8 +TAG: db2c685a59cdf304c1fb57b66966a5ca1cc3536fe21eb1113c25868428640c7d + +KEY: 3b3786e38e110ec0c8b05fbdb3d9b6d117d1ebcdc0e7d942249fea6baafa31fe5caac227979fc833b104641e8e9ed01e +NONCE: 53bf31912a3ededc01c91f84 +IN: 6de5890028382aafb186042864c5cca1a77ff80ba4f7f0942dcffa1579711093fb652c8d475dfca81a976be8ca77eb9c7a6b49dca1425610c945bf404ba65b +AD: a9 +CT: 886939354fa117139f5e077baa186825ee7e2955c3a74f88af3a86b260ee9f9959a90409e7d602e36cea31e606aeaa8b9229e28f7fa58ace6fd217e5cce1e7 +TAG: 91a769003ec900dbb40ea9c9b959882d822421b510ba85ca826bc4af3b5c42e0 + +KEY: 5a75c97f3583983bbc5eee4a882b766a6708d798a46f71e63b7509af69afd7cf86f9b42df04b626940914007078a8b9b +NONCE: 426e8bcbcffb6b425706dae0 +IN: c24fa29a66197cad518c5a1a76abd9446a8f24c2dd81e953bfc5c00544c119d67986781a1c754224af234b0ec5e44e78610a4420eb78c283e9a56637c35c24 +AD: 6376835513967e4ccaff9a0c56b4d27a2bd0d013cd54abf95fe9a162d036af285ebc9567a16ed5abfa69aa +CT: bc4daeef3ccdf9abdaa75591781685eee3fd7825bfe63132817a7e0f93817f22bfca30ed775a773f5bb290aac3a381a01085e861cab7b9fe4c5143138e17a5 +TAG: 79c779bfcb974ad9a8ac88dce5027df5691a3a1163a5d5893b4cdb1663b17aa1 + +KEY: d1b301c029fe3b81e4b97e08e84dbc03b138f422161c0e74ccbda3172c034b99610f09a9e611f0e9a3ca40af4fcb3c56 +NONCE: 4032c79eb3ee4b63e44fa932 +IN: 71bcf5a5198787b85a66221c22e7bdb9d038dd3e10000555ec9271e54bfefc460ef4e71729ff7ae52859015b49f45df89ddf183fe1e19de3acb032dbaa4d57 +AD: f1cd18ff1e5ad2b65de41e083b5175966625ebebb3031e1027761e407dae4e8e193ffe7dea52ff61147f1b4e +CT: 7c521a703b7d1cbd086bdc316d4f2ff0852c462eeaa1d7a586c561354be9ed412d9d9bd1f78cc85468750f1af09b7b17dc1ee84c926760d63504cd3a1dfa3a +TAG: 831f3552890d997f0a8f2d832b6e92e26f6e865424699f0364a82d86ab7734d0 + +KEY: fdd24bf37b36666a4f641115581ab4bd6b896dd3017006031b3675beed33f21a314363e3a07bbbf4359d9ac02eec847f +NONCE: 7767cff1a096a9f7d8a9b32c +IN: e62b7695dd41baf49d1b356e64c6d5504784380b75724b86f5f3185d1a530664aea0e5f9aeef347e1ea4754acaa7f3c233638db234c0e93db02e0bf988e7ab +AD: 2d650f3daed2564b0df86fa23ed0343634663adfae2c422f80f9d5674bbb63e824f01ad3994834f889133bbc0e +CT: a51f50a6ce77a22ec472bc18c37d08fb28e77efe55065b600e3edbd9ac97f0fd0eec93cd312ec7ef886cb04e1849526f0a38b14d862bcd578b99bf9a007c2e +TAG: 89d83264364c9c84ba705e5549abcd496abed3900f65e3daa012275fed18a7da + +KEY: 0f88e2d00d2c4bd682f1591ea5f4c1a1090180e1195809cb363b27c863360a85b27814e6a724effa44f298430d6c9628 +NONCE: 6e2e62ecb2aa47c7e5921d25 +IN: 91efc710a57adb57017725cfa26d17d3e2993c5ee66942ca42e770a83763e9df8a455bd408dc1e2661cf301f1dd669cd6d5b4d92a886be0f54527779bae8f9 +AD: d060cbe84271e85f25a3dcb6dbf299551f0dcd5783e3df80468636e491c0100f3ec8316f24240482a88bc430a398b0ecaee5c48a274ffb2d835e200bc39ec0aa86a1c90c9e2dcb4217595d48826a81de90eb949846a33fc26bf8886ca0554e1b8f12cbeee36e65e33cbbf610c2d24264619fa93c44c88e0e3d9d368fdece461b +CT: 10d99b98ed67d85a44fa57e706a8b028c61ef17f35f6713613d158cad90e826f90ef036a2190ba123f9b68b352ca94fbebf8ea947e569ad45f00e6a36975f8 +TAG: e345bebcc4a8ac01528bc5f317e5c378236b292c2baab6ae8654245da35d90d6 + +KEY: 1ccec52c77239bdf6ca50e5b702943b23015d08cb1d9bac592b3dec4c96be904110713e52e114a8bc294df26530a758a +NONCE: 38554b7c40027afe9721e14a +IN: dac91fcdb3768df8d5ae9ddba1fe5917c084a5d9e6b14eee9a609cab2da34ec9f95cf2d10fff77108477e694c76f362e29b9a9287d8b190a748ed0a929967ff8 +AD: +CT: e6bcb38b3bfd0b428a14bb3aca01a4a9e54b0853f10bd7750f5bb58d0e7dd18006f8929d7d862e5d6601ef63be8442334b4d51a99219cfedaa31f7ab19028459 +TAG: c4f05d9415840c2325dabbcd12dbeda31e47637437514c606dedfb8ce622edd0 + +KEY: c82ad4c6f248bc51d3a51b958ecc2460a3c64d669f6c485c2309d26abb3fa84644a0d8c28da8091f90184b53cd556413 +NONCE: 35a29938fb7a31225b08d0e4 +IN: bb0045cec5587e50b148b140b6969612425243ed1412e812aa9f4b471ed34ced6dfa9e0acf3e31455893e4ee7e66b4661c6e1f80b7d6f1159c11387ce579b80f +AD: 12 +CT: 5f1854fc2fb11fd721755445a1efa5a28607a725ad71cda9a3464860a6a0efe3f58727c0e0cd315f867611232abd72034dfc2b9deace8cf6cb507b1cd4032b59 +TAG: e40429ca19a88da73a7654d7ed8e0621ac2e504b0245615e262ac70bd05a3f47 + +KEY: b01bec74fe97e5af7db2a0b1432f8b4c069447d2b56dc2668371387f753b03465412213999d2394a4b79873db06c590a +NONCE: fec7de97d54dec8d36c9f253 +IN: 88ab078d03ffacd128edbceea7ace2e6465f4076097445a5db7f0e61ed817b6e24f22874489049bee0c58d0aa2b42b4db0bbef6ec88d032da9c82ebef57c424d +AD: cf0ceb3e80a76d1a75f6e070f5d3fee1cd1e2699434f96e7cb3adce12d4a3148dd433b08c68b9d66962f24 +CT: 8aa3c7478b0cd86fa30870957fb5307345f89346a869d508da9d3a4fe36fb3d6a9b0c3c1bc2d44c8ea31ec028012098d6032085af0b54603dc2fa65ff091fdd6 +TAG: acb670172ec3754064b366566bdccf5056eae132e2041f1a285c5883e7eff4f3 + +KEY: 699a94f6e6eb457b186af58c25118fcea81c8f0ad265e7c16bd6cdca15c9db64bb9a537580ca0474a4b4d54d47412d88 +NONCE: ac3fb6525f4357d831529407 +IN: a7300aa94f3d357cdb272f0a739979e08aad9551dd3bfcd0b5aca6a0972a71b502639e79e1b9e0d22db2f3220b982800d9cebbac3d10d9bf86ea25d3d417fc57 +AD: 19c3d34bb9d57d0f63f14bdd3da06a43a5afe6a8c505f038cb403515876a2765c2d61aa7e4c84e11c999b81d +CT: 8b472f1069ace78172611369b03073f751e5206dcd2ce3b45c431095f303e70c59bfad3af8006e66e4a68f8fa2ffa534bd76bdef089d07dd38988cbf723393c6 +TAG: 8e7c3c2c41b1117928ca1cd0cd48c25c319c18e009804c007d1aab0967c0d0d4 + +KEY: f3a7b8c2a39531d5fb3c97bc9224168aa835973f48243d6f046d00937ed428e5d672e22af26e734f0c24f989fe62621a +NONCE: 65c61af60769672f0eeda005 +IN: 59667fceb2594e002c844a47d2b3935d2c99570b1639f0887fb082499e1d36f9699ff9ef53be3b4236136aa9e441abdc63dfe536e6fc9fa8f332baa1dad577ad +AD: f79036742501f1ac19dbb2984e09cf5000bc4bc0424082376c307b8f1e5bf74dd29c802139d7ea93d55d336464 +CT: 9375a81f016c2dc59a8e99dc33fc0db7ef99ab2f9ade4b0ba000a614ff2bd13bfbee2d4a2338109c98c1147edca6023cea43570adc503da98379326ace89d796 +TAG: f563869420699dfa0aa84751526bd75af1473bd88311001e49230b09b8ef2797 + +KEY: 27611a8f11cb57d08648ec816b5f3c45882dae394200cdfc803d1a52bb03f225206574ea63b63423da6972bf5a994332 +NONCE: a7f617fe7a52dd76ee443dff +IN: d6ccb950515a4a2de7c3cf5a73b568f32fe30567bb22b3b46feb7ef07205d3215a3d689b96d4b9dbaac5a5bd6ecac6ba50314b19b37179fff2557c869950e162 +AD: 777282a98b2f262ed9456fed3610a2028bcc4433eb8f028597d3bfa220bdb0c04882de03a276d0191cd1a125270ce1630c1b94e2ec0021ce5c494d2e0bdb8745e6e94a387cbb31a0898965174bcff8bba105f94dbf080059b49dee71c3194fefe679ef6c00065154ea809293b088c0c3f2ed7824aac72319a4c4ad85ea990844 +CT: 41eacc31aa3c3a282ae7638d48fc7541d2f129e4cb3455df7e60259be9a814c8e1642ea826ac1ec7ed1fcc216a6624e79845521e7a8b16702566f27f7a7f3317 +TAG: b959992feb7005410f9ea6963525e3d9244f038731ffab8da8c4ebc72489f17a + +KEY: 0d9322713cd132c339c38ec7a75862860de304c70486b89b0f587095c66bfd1abe56f0b34f9ca0dac577fd4262616600 +NONCE: 3298d02dd4eb85a98cb935e3 +IN: 5dfedb1d168fe262d35f78d797560b2634f71d40f438c21cdcb8e73cf9884c11570554f55a6abd23d0e7775a9ab385ae6c9bbd67f08d1aec57347a8fad5a4b8c7b042b03c25facbffc76f0b1ce2e6c07d427eaebe71255d661ac8e8bfe8867e2d947d496ce2318a601d0beed02426311ca678d036deb3b4c65b1f89bd644a410 +AD: +CT: ff09fe27f12a87d5208bf246378ee0740e848262442b8b9c7670c8a73fe6732192cde43c1a1246743ed49e15ec63c87dc06eb3e0c92c1f286108b2c7e0754dcf1b9c3fc87efe3683289daabf2db71d8742061f93098788c3c6f26328b86e358507a03af296d2c29009562cad3763399e0e2b89ed440f756c16214c8ab7ddfb84 +TAG: 5076c80fc76c67d6e4f9b9d470cc184db62ea7da49cae44cb3ce9e46c2f2ca9e + +KEY: 2695671fe86f1658d8b01ec856fb4c9d09a0c51a1b994fc87a3f72bec12052537b7429f11f7eb4aef0b128302ec8f336 +NONCE: 9739e577595418c47b9c10b7 +IN: c723c39be334a0761db795076e81e3dd85e37a57258c7e0e10fe0f48dc31bd5e683430aa70531b7c8e3a904e49bec838e760d07afa9f86b2cf78ae90f612c4560632acb7ea2d89fb1fd5396d0337111c429cdba99c6a52e863e8603aac24a83302ebf86ae69a212cb938e12085cbf73a28f75e4422995a5ec8705b12d4aa8b6d +AD: 31 +CT: 1569b20732ee6395e605217e1cb419ce57496ba6f6e889bdfa3c93575e969eb7a0410c7930b7ea146e88577376d84f0e824b62890eb84bfe768a1513a12c2958ad1835bc1eabe602cf40f7812c7dd7da955567242cd7512090fca685fdd7306bd98a908b09464961114abbdcd610c153637400a1f81825cfdf06505947fe54ee +TAG: d07e14a62a32ef1933abc2127cc5bfc1e43bbca663e460409c6faa3a4ccf99f3 + +KEY: 1785ef6e7016733dd1952b3268639f231e7afa973c0a3db8780b81084c67a1783200149a1ed849ca8b5c14c7b1798b4b +NONCE: cdf48b73c3c8d8625e52fe11 +IN: 14002f17e056d7f5524537cee6c2061e2741c01a6f9a82e2cb1747887875860d51bebf8d9b63950a051f6b228ad7567227f8a45b9fa7c4ab47eab410125303defa7e3141bd9bc5bf4ed56550801ff3bfc2dfaaf499c192b1e18879b2f59e1230778132818df8f6ad8a3dce9a1d11c98075b8b4e560edd9b5ea180f0424ab3706 +AD: a35e86e22e9a3df65e4c08e5175b4216fa9895a1be6252de911cf98349841494617eefaa007759dad7f337 +CT: 99eae989435578cb57715a7457da31b807b8078a59c2332a0a866eee9da5188baed3f517b6808095f0067e9b4b91cc1424a464f0a09fc946adbe4135a17b0e8e545d2046f81cdfdb233aa3520797319c0884ccbade8235c32d195e7b802017f88ddd86fb630de19eb97f4bf91029c001fc8f1cd2189a8ee6c120e9f1682a8703 +TAG: 1848f0b163e7b0d270e2a0ced288ea6525697170aae15038f3dcbb4ea49ef843 + +KEY: ba9aed2bfa90eaed9b27a697bb44c715c0209cae6b2c4ddffc684bcf07ab51b0e096dbcfa26c18fc24b63408317da567 +NONCE: 4b850d6bfa64520f1aa1e79e +IN: 5bcc2ea4d729c84340c5ceb827f239578971c595e915f0bd9d49ed51d723f8d0e8362e69fd11466230bda0dad57ad724307edcc621ebde1e57fa91fee206d81d2bb6ead94b4a804f74b6cae979f66bdfa4ad93d107ccf114c59cd3d261aa6e2fc0dfbd0df5f7c18e80d0699cc1712abbefab5029e35549d2919d0f937d444051 +AD: f80c759062e9ed0ee597406aedbcda9a14261d66a9546f1c939d20cb1d0d0974fe7a9b33d8c93287a6a8d60a +CT: dae4fc873d302c51e55910e67482bb80ac68e9bc6ef77cb3e57a31d85fe75f9071d0b64026ba16d0b68fa9c0b7e958cf7682bcd329c4174ea0e3f3f9d2e65d82aae1350a53ea7cdcf9ab848b85cd731751f0e2917628e5066f5b1ddebc7dbda5d2d37e46a7a7ee62bb49c4431af730f9cd3da4c1d0e5f8593d8c99803f781bee +TAG: 58b42e9117fc8cc2ba5cff74b0d92e8b381a444fa837018b15e9514fc4319fb4 + +KEY: 37235623acb0d650f905f106dc3bfe6fd83192e53056de8795ed8d20c6e58e5efd84584007ecb17de9e76b392e12fcd7 +NONCE: dc441f1c743a92c4b975c6b6 +IN: 960ceb8d80774bd88b7c5f17042ad2e4baac71b4021c548458cffcd9a049291cb0df93076c115b54f9af878745acebc6e8f04666d053b1ed980728043c4fe7f67b2bcb0341d8a4973ed126342f9add14279f8402cbbffcecfc847379dca8a68ba4f2f26141acfca7f3ef558dbaf04629f0f46e43246b19d875be452f14e7bf56 +AD: 32579218062560f15ff966932838460f99099782e79f1f8c41cd9f6eb59b4c2c3d2dae9cd199fe66d74c7a9940 +CT: 49ad8e24a31e90ab1f8dc37dc51dff0f93f1420e79eb108f90f800274a5aa573f64e274cd52f1dbfdee363e4f86e1457bfb8f87ce57aefd34c3a5a3a93db4ebde3f73a3b4c202c993903ab378ae71042ad238e94f400c7ac1891a9890b19d445eb1db60773a3ea165f7c4b2bb2071faaf588daebac7ce09ebfc88f4d9232d9ca +TAG: 82f908b837a5768598982f860ecea16aee84427371c4de1f1314749b70ffc173 + +KEY: e7fc36c9fe87a38f9bb4ca67723267e80e16bf39740eb1090234a473d68aed9c96fe2f96e539795eb042276aec5d7505 +NONCE: 83d768746d40dcd695e49ff4 +IN: e61f0e02a70249b62ec9a8fdbaf6622c9c6316599daff421f1b19815707b67587d196b7e1452c7d7609f108ea946675ac5d97ed215b92a451aa6a11717ab7819f84848151007f37e2cdc8aa99969c3d5652aeeb65fc21b621865f47f44eb2c528ee1142d11f513761a6bb2d169126503db5b263a410cadd2773ff931a032a885 +AD: 59114e9f21b380ae6068609ac36688e6aa7c2533cbfe07013ad1b6663bfa42e39f20e62b45c0faa256c1d33caa9f59b1e30d8502bb7148d051451b3d0265cb9fd0d82e4f4e0489ac606956762d8e7b70abd7eca413ddb708f119c342b3d0d5df673769d8df281656d909b68b6f6438edd60339fd84ff69918b6036ad12a0a588 +CT: 4f12807736c9ab32a2be2e00c9a0236394a8bcfcec6037e7582af462a73bf10aa73bd90e2bc24b97f7001ccf653574aea294bc7b30b77540f475e0e846ab78ffcfa1fef28058e540fea43d9017d4efa05c837611b2eacf0034f26cb7903eff7874973c6da7843892bfc676170a75f839e297dc7f04c74b40f4bda20a45b2a352 +TAG: 9b05aab44ba4d1451f14e087be626232ed11c4ed04081f0d4d47ab593fc619b1 + diff --git a/external/boringssl/crypto/cipher/test/aes_128_gcm_tests.txt b/external/boringssl/crypto/cipher/test/aes_128_gcm_tests.txt new file mode 100644 index 0000000000..eac9aa9270 --- /dev/null +++ b/external/boringssl/crypto/cipher/test/aes_128_gcm_tests.txt @@ -0,0 +1,531 @@ +# The AES-128-GCM test cases from cipher_tests.txt have been merged into this +# file. + +KEY: d480429666d48b400633921c5407d1d1 +NONCE: 3388c676dc754acfa66e172a +IN: +AD: +CT: +TAG: 7d7daf44850921a34e636b01adeb104f + +KEY: 3881e7be1bb3bbcaff20bdb78e5d1b67 +NONCE: dcf5b7ae2d7552e2297fcfa9 +IN: 0a2714aa7d +AD: c60c64bbf7 +CT: 5626f96ecb +TAG: ff4c4f1d92b0abb1d0820833d9eb83c7 + +KEY: ea4f6f3c2fed2b9dd9708c2e721ae00f +NONCE: f975809ddb5172382745634f +IN: 8d6c08446cb10d9a2075 +AD: 5c65d4f261d2c54ffe6a +CT: 0f51f7a83c5b5aa796b9 +TAG: 70259cddfe8f9a15a5c5eb485af578fb + +KEY: cdbc90e60aab7905bdffdfd8d13c0138 +NONCE: 9d987184c4b4e873d4774931 +IN: cb75a0f9134c579bebbd27fe4a3011 +AD: 7dc79f38e1df9383e5d3a1378b56ef +CT: c6a899758b6c11208241627c8a0096 +TAG: 7525125e650d397d0e176fa21315f09a + +KEY: 819bc8d2f41996baca697441f982ad37 +NONCE: 08b7a15f388fafb16711ce19 +IN: 9b1ddd177d2842a701b794450e3c81f151f195a1 +AD: 277c372784559784b0e047c6f8b7e9efb6f7491e +CT: de9b9c8fe09f705f558c62dc6d40b75e3aa625b6 +TAG: 52e2d2f153a4235eb6fac87ff6b96926 + +KEY: 682769d52fa0bfeaebe0d0c898d3cda7 +NONCE: 6af0738b249d09547837883c +IN: 3461523cd98a6e8bdddd01150812e6c58d5cfa25d385cdbbc4 +AD: abe8302d7d5595698d9f31011c24d4d180a637597098361354 +CT: aa3ecb46b9330554b36d0cf6f6ac4cf5e27bfd5f602da1b3c9 +TAG: 0ba547961eba5c58726c418f51d31311 + +KEY: e2b30b9b040bce7902c54ca7eec00d09 +NONCE: 28ccf218e8de56ea91422a25 +IN: 483080d7e2fb42580dfb862d2d266fad9fdce7cdcdb1158d415f84b6e269 +AD: 9f06fbe67eb2ace15c8011032feeaf72fdf6d316e1e08ef4cc0a176588af +CT: 67e1980ced4cd232ce893938e40b0798b17a1692476342e520b480a18570 +TAG: 9994185d4329cfa5f4bbeb170ef3a54b + +KEY: eaafa992ef6dbcc29cc58b6b8684f7c7 +NONCE: 1ded022dbc56e9ad733e880f +IN: 900951f487221c7125aa140104b776ba77e7b656194933fa4b94a6d7f9722aad51b2fe +AD: 863ceb297cb90c445dbcf2fcffe85b71db88d8c935158f697023e2cea103ec39766679 +CT: e0b3aaa890e45f1c39ad4f13ba7592f5251d6a02ca40fe3633651b35fba74a579f48c5 +TAG: 5c95fd941b272bafbd757553f394991b + +KEY: a43859049b2702e8807ac55b0ad27b0e +NONCE: bbe8c571342cac7fcc5d66cd +IN: 8673d6ee2903265c92446ce110d5bb30aa2dd1b1ac5558029f23974acb8a2fbf4c74858fc73d6104 +AD: f77c998ad3ace0839a8657e350bed15ffbd58f152a0dc04ffc227d6beb5738ad061d0f83c2a26999 +CT: 40e201a513979b093637445275b2db5ed4cb1fa050af0e20e43b21af6bc56dec654541e55b295b72 +TAG: 41bbef45727d19ee544fba5b360312f0 + +KEY: 68fd608c8697243d30bd3f1f028c5b74 +NONCE: 319a210b33c523d8bc39fbea +IN: 2c088f38f7a58e68bdd92632da84770303cd1ff115d6364479fb0aa706571f68d51be745f5c1d1b44fa1501cd5 +AD: 1417a65249b85a918622472a49df50bdb2766aae7bc74a6230b056549851b3c2f0cef727dc805ba2160727fbb2 +CT: 9d376b147620c2ac6a5eaa8ee44f82f179f61c9bc8acdd21680a7ff03acec953437a3cc9660c7ecb1204563944 +TAG: 05a4fb5be11e3edd89e34d0b7132d0fa + +KEY: 6edd3bd2aa318f78b4a51103cb08d489 +NONCE: ef0027b144691bc9716fbeca +IN: e98f2f99680dc748fe0b57390df38a99950faaf555a888d463d005ef4e4b1c22663d3d3daa812b20ae35ac934c2e187cbba7 +AD: 97337902507391de0f15c88462aa5ffc5e4760543850719ccd8a0cfef89484d8095c23ff8c1d06eae4ff6d758c95e65cc3b5 +CT: 3c54842c2099b73daa9c3f1cb64bb913c0527955d923510f3f3046df471c1365db97333bc5a86dc7c5f23047e938fac976c0 +TAG: 375b2a25421434e5e3a021d434fb2d04 + +KEY: f70482d53d3ef70cdc3cd3c4a37aeb2b +NONCE: e69d3de363e225749cb1666f +IN: 4cb68874e69125e1a6f6e68669b48317e1b361d0f7f95ec4cf613b7da2c835832010e8f95eaef4e6800b79bd86cd7cda869d2df258c267 +AD: d72975f15721bd0957f5cb1edecaad2d1ef047afb0e779035f777f94cd7ed1bdf8ca9d4f357d2a1e195f195e7483dea1476133235f7e6b +CT: caa1e48decbda18e314057c5ec32f8733a5cf03ed0d05c3654531bf56faa70751a6c7f70fbd7d39f7e9775a772aba8fe7731cd0230beab +TAG: 47d909cbdd1c7f8b485fc3232bb7185f + +KEY: 98a12fe16a02ec2a4b3a45c82138ae82 +NONCE: 4b3404684825dfcf81966e96 +IN: 899710fc8333c0d2d87f4496436349259cf57c592e98ec1e3c54c037bc7ef24d039a8c573ec7868e8ce9610b0404ea1b553ae10cc8cec26468cc975c +AD: ea1a99cee666bf56c8c3667ef4c73c2e1e6534800d6e39a97de3bd5d39068bb3e2f74f96c03463afa18f1ee88c21209bae87f37e5d0269b68db370fe +CT: 0431b7fc4889ae401eab5edba07a60f9682fe58419d4140cbf4f20c62d79d8a3cc1f23fabead0e96e1c8c90929756ea1efab508336e1d0ed552eafd0 +TAG: 01053ceeb4f9c797eef9426930573d23 + +KEY: 6538e8c8753928960ffc9356d43306b6 +NONCE: eee386a2b1e310665e335746 +IN: a92eb9a93a90fdbb2c74dea91d273a48efe9582f8af7a4e3a377b114770a69ca45421959fcf36107815e53dc61b7bf018fc42965fb71d1eafce0961d7698fabbd4 +AD: c5e572e464718398374c8b45ff8749cd9f517bbd97767f77a96cd021176c49c0acec8b055ef761f49aa6d910375a45b2f572cd5420b99153971a682b377ac88f09 +CT: f36353de609d0b5246f64a519d89a4dfcd9d53325a2d2cf910e7692e68391b0357b056b944e0b53e41568f304bea8822f9ff7a0375a5a8087509799226862f707f +TAG: f7f9b891089d02cac1181337d95b6725 + +KEY: cabdcf541aebf917bac019f13925d267 +NONCE: 2c34c00c42dae382279d7974 +IN: 88cc1e07dfde8e08082e6766e0a88103384742af378d7b6b8a87fce036af7441c13961c25afea7f6e56193f54bee0011cb78642c3ab9e6d5b2e35833ec16cd355515af1a190f +AD: dd10e371b22e15671c31afee552bf1dea07cbbf685e2caa0e0363716a276e120c6c0eb4acb1a4d1ba73fde6615f708aaa46bc76c7ff345a4f76bda117fe56f0dc9b939040ddd +CT: 049453baf1578787d68ed5478726c0b8a636337a0b8a82b86836f91cde25e6e44c345940e819a0c505751e603cb8f8c4fe98719185562794a185e5dec415c81f2f162cdcd650 +TAG: dce7198728bfc1b5f949b9b5374199c6 + +KEY: fd1dd6a237a12d7f64f68eb96890c872 +NONCE: 459ced97ebc385ab3a8da8d5 +IN: 04a9709fdc0a4edb423fe8cf61c33a40043f1a585d5458c7512ec8e4e066a0f95e2e6609abf3c95a5d3ae2c738269533855daedd92eca20bdedbbd5677cd4eee84b7a1efae0904364f1e54 +AD: d253b829a2fbc5877b0fbe92e7b79f38886a49ca889ae72b91f2c3aebe257a3ffe0d390b5d320bea22d6a5536cd9213612f5ed6e3b0ea33ac91cfee284cb25eaaf6b85b15f7ca894317182 +CT: 4a565d3ba4f2ec461c9bd8dd0f96bc00d2a561bfb56443c8cf47681bdf1c61f55854bea060c4219696cac79c09aa9400a7e5c59c6b6ca556f38c619a662905fc5f0e8437b906af6138e3fb +TAG: be5f93201d7980af4c5bceb24ac1d238 + +KEY: b09a4d99112e1637d7f89a058988b417 +NONCE: 74348f7126c0cac836e9de5d +IN: 6b3c4cfd1eb139b62d91ed5d1d8b0f3b52278d5c48787ce46f12b9f026e3eed1bfbc8c6684c6662f06614c69440b3d7cff7c46b2e4aebaa4b5b89236a3cc75535bc600104f240d01de91e0fb3bcad02c +AD: 7883ad259fa5d856ce283419f6da371b444b9b64ea0ddb371b17ec0a9ada27b0eb61b53bd3605f21a848b1e7ed91162f3d51f25481f32d61ec902a7f2cbd6938a7ce466a37e4467e4ec2b2c82b4e66ca +CT: 5e1b783b20fd740310333eddde99a06b5740428cb1a910812219fabd394b72a22a6e3ca31df0afae0a965f0bc0ae631feeaa5ce4c9a38cd5233140b8557bde9f878e65e8932b9e3c3f6e57a73cda36cc +TAG: 784b73ee7824adf7279c0a18e46d9a2b + +KEY: 284bd8c4b5d7b16aebce1b12988fa1d3 +NONCE: 7ff05007c5d018b17562f803 +IN: 903416331583dcbd31420906c64dc76e14d0c5044d728cd9b605b531ddc350fdaadeabe67d08f0b4c7179f82a1044696716cd96459506453141e9ec3130e893d8c2ff9b8b4c241b73866ca4fc1f712d17d7a88bf4a +AD: d0a1f92f80094c1fad630ca584edd953bf44cdde404f22c8e476df8708a97a0712e7fbd8054caa7d65144d0be3b30442d0dfa5469ba720afe1d00aa6bb53c79c1c178ed42fce596eeb6c638c8a8dedf76a431976c5 +CT: 9bc3708f70a68fc16bcc33099325c821a0ae9a2fd0a6a98382fa21b42ddb3a9ac6c34a13c4805d3beb92586cdf0f4dce3885793d49abce33190685e7009a79242dd93594722a1ceaa44886371c30bcc8312fa2bf67 +TAG: 3fd8a4d760d5b878852b1ca2d34dde6e + +KEY: 6d76dd7dea607a5cf5c21cd44c21a315 +NONCE: c1d13e56b080a500f1cb80bd +IN: cb959b92e777f835afc4ae4149b190638851238b7b13c9bf65343adb3130e8ad2356101037f30997d4a5fcc0a1d6415210179fdec881236a799f6e90dd43ea3817819b432611eaafd072368b9c7036c7a88c8b7774a8ed986134 +AD: 92a2bc3b6b6ca9de0cef10d8bdeaadf6f54782cdb2b09e66cce8cb5b56895636e982f7a3c7bd9d221ade62c9ecf68bde70becf683804386606ab1c48ac764c4e11620064545c5beaa5911c118856dfc5cdb8df50052b01762c6c +CT: 522ba9bfb47efc624cd8933fc9e17784919d2b3ccfaeec46af414c1b316355f65b9f9fd7f0be6ac3064b4016e43b8fb2028459f0fa0d81fb6656be0ab8fd841d05d24682b4a57c7c59d89af384db22c2f77ce10abc4d1c352a1a +TAG: 5ea4a77381679876e0e272b53519d533 + +KEY: 1dbcbe45a47e527e3b6f9c5c9c89e675 +NONCE: 98f2da8ed8aa23e137148913 +IN: bb23b884c897103b7850b83f65b2fea85264784737d40f93ecf867bfdba1052f41f10d2c5607127da2c10c23b1fbd3a05ce378a9583b1a29c0efbf78a84b382698346e27469330a898b341ec1554d7bf408cf979d81807c0cc78260afdb214 +AD: 46f1bde51f6c97a9dae712e653fcac4da639d93a10b39350956681e121fb9ea969d9dc8ef6ddfb2203fad7ab7e3ef7b71eb90b5089844d60d666e8b55388d8afb261f92b6252f4d56240fe8c6c48bfde63e54bd994ff17e0bf9380ebfb653b +CT: 0d90e869d2f4c85b511fdf85b947ba3ab75c6b1845d8191634770413d7574a6fbd9d86897cb3d3b5d3d8e6f74fac3bd2a9b783cb16cfbec55dd7d2f7fc5c39fe85d39bf186a3fdd3564bc27d86f4019ae0cb73f5f516b602331433689c1b08 +TAG: 8777f2002d5a5214a7bd8ef5a3ccfbbb + +KEY: fe33f47136506e5cc14114eb62d26d64 +NONCE: 9534a10af0c96d8981eaf6b3 +IN: 3ca38385513eaf1fcd03ac837e4db95c0ed1a2528b7ab3ac8e09ecc95698d52b7d90bf974bf96d8f791aa595965e2527aa466fb76da53b5743eda30bb3ebd9f6a8a7721fbfe71fe637d99a7b4b622e6da89e0824ac8aea299ea15e43250d2eccb0d4d553 +AD: 50b7bd342df76bea99b2e9118a525c0f7041c7acdf4a3b17912b5cbb9650900246ed945cfc7db2b34a988af822c763451ac2e769ec67361eded9bcab37ac41f04cdb1d2471c9520a02db9673daaf07001570f9d9f4ac38f09da03ff1c56fdefe16a855ac +CT: 927fe3c924d914a7aae6695ddad54961142b7dd5ff4c0ba5ca3e0cf3d73bdb576afd59bd2b54d820d2a5da03286c124507a48008c571c28a0ce76f0ed68dbac3a61848e7e2162be8e0bee8147b9bf60da625cdab8601bfb37dfcd165f533e94a32c26952 +TAG: 9bd47a4a2acaf865a8a260179aabf8ad + +KEY: dec1b34b7b81fb19586c6ec948ecf462 +NONCE: d9faf07e72e3c39a0165fecd +IN: f7b0bbe9f0ff4dcf162792e9ee14d1ed286114f411c834ad06b143cadbbe10a6fbc86f6664e0e07ff7c6876d4543e5b01ff5ddb629f896c30c8cefd56c15d9f24dfd2ed590304a6aae24caac5870ddafc0e672ac3aacae1867891942998c712d45efbfa4d99a8a6f03 +AD: d3c4fc4838cb3cda3937455229ddaf1cb9102e815cb9f519a5434677c68b11a0bae1280faee82f1a5bee593e669e6f81d5ece3675b8af63f1491bb298531aacc940f53678ba56ae96fc66be92b904bc35f2d5b68b3ed98569a4d04e8f8a9689ad9fa4b51db0938a9f3 +CT: 2f44ecf549077b98ba551819538097bb80304a55c48ef853e20ed8c3f808dc8cb5eb41c2463d19fed2606b59cee4b458958ea75715f7654146df4519dc63524a0569a00d7bbc4b32a372f82d955be5f190d09d35c267da1017e8b16096ae84f8a671b45aaf0d1ca59c +TAG: bc3af80cf9388d35deadecff5455d515 + +KEY: 021add6030bd9f3fed8b0d1f16f83783 +NONCE: 4e460f51fe6b5eb9558c4571 +IN: d9aa1d0db5de536cfbacb59bb75c592ae3f34a5f9c5ff4f22d14e8e4bd0754af19570221893797f60c89a251cd6a19c2953662dca51264afc21099ed5c80077b0e10a5295b3c4c6fe47d3c1c84fee69ebf7d8a7d9b1b338dae162e657e6cf5277ca70d47b9290aa7efe67b0ce574 +AD: 38d99cfd7578d40ffa1749d5fe83500362ceee76c5af38935806837b2f2d1b3422a5057bf617b07868dd95d8e5f4a24e74f96177d53a0275450b429a2b1f364805030765e376151ae35001d6a4872200142fdce82017f3e976ab0edac1a08d2649d297648320e7dd9143b554fa3d +CT: 8863ad51578fd1c9dc40702e34236adee885955f0478ad9a094a6941f95f900e466882dcd5b86e1563ba89aa105f56f3ba5ed860ec3338ee1b750a2f9332acb3f0f61718de7e40fb80442d046b35f147f178bd05362f0559a20a53ebbf78e920fe14c9d80d1c9fb21bee152f8ab2 +TAG: 614539247fdcf1a2aa851102d25bb3bc + +KEY: 311c2045d5486bfadd698e5e14faa58a +NONCE: f1cd8b373cec6451ae405618 +IN: bd154e428369aac5c13128d29bd3031364939abd071c34bacac6ea7292b657b794b2e717d9bcb5d7d01496d805283fffd8f7de6a3493ddd8d1dd7f58835a44d43ea22d95468d1239ca5567d6c80bdf432fce2afc544a731a2852ef733667b9f8f4f8923eaa9de3aa32addddf99b607efce966f +AD: f70cb7e67b2842207df55fc7582013bbddff8c7f3bd9ebbaf43827aa40f8490e65397934ee6a412de6272cd568566ea172789a006a92e5920140ca5f93f292b47dc262cefc66b75543f94365c08795b7c5e9c6c29b7dc67b2532fbf8a6487d40a3eff504e75c3f2bb2cc3969621028e2112e67 +CT: f88f4ef0431d0f23911aaa38a4022e700d3a33c31e0c7bdebe00f62ca3b55d358385de25ceb0538242871eb9c24530e557d7981fa0182436e1e49272d52689541f09517fd147a8da0f0d2bb32d54911a36eded0b87bcba54d6842edf461b45839df1cab5176e2c82c871b3be4ec1bced67ec5d +TAG: ae8d847f106e914ffadbdfe7cb57beba + +KEY: ceab57de6220b2c80e67f0c088e97b36 +NONCE: 8cf438aeb0cb29dd67506b9c +IN: ce2a7a5663449cf6e0068085e3c373c5ca6f027544e327bbc09ac00f1571268bee186d51a00bbc16da7429e4d3d5235d8d54ac96b6ecb2fb7d77a6e5b9e70d431dd4dce78ceb972e9e4b63059e350efaff841c2c42bc29c139b7fd070097556b6281b58e074d5271d9f66c6744ec6dd3b9db2f4a21aeeb7d +AD: 03e464d111ac9228d39d22a00120c6ee671fe5bbf462b1ee3fdf348b34999518998ac4e175ed48189c29b49b5527c27c43094eecbeaeacd3cdb48cd15aa82573e884a7b97bbcdad610a6955f7d8b04f6f98a13a907bc2bec4c940b77582b248f5fced1771f810977b2d0a4fa48bd4d78e4bc383bb92743fd +CT: 1fa9c379c78b92fa3c1e478443ae38d7b4b50235448ce2a88467514bc9db95844ec1baf4dbdbd1b0720e377d05d82c3b58b52af8c9c50417b39ad225e373c7ff18ac5a6ea5d182b255f1c8a2766e31e3e4e3d55dc08dfc64b818ead40a0e824b06ab24f0dc9f4f0c383db7cd4d40016b31701bb401b126dd +TAG: a9a885578467430504731d1a8f537e3c + +KEY: 585bbac0ab4508afb8b72d84167551aa +NONCE: 774c82af194277a5506e45ba +IN: d788112213d2b8b5b66b056e8b3e344a7876f6193b59a480c51fc04d3ec2e5166344c833187b14117276fd671a20937a4553181c29d3d85afe385dd86093708226f082a2ea4ec3288f372c772ca7ceae86b746ff428e8add17b0f34f8553e3db63f55224c39edf41f138a2c28be49d56aa8b4c93502b9794a16310f78b +AD: a29665261a8eb58c88803bcf623dd1a14e76af49ec5db72a267f2ebcbc479385fb6b32bafcb1239515d74a8282b228e83daf282d1ab228099b315bbed0f0e6b3427e029cc28c025460a8bf0914bd584c13e7de7830ab77fb4a9258dfdc9fdaa96ca941546477f04cea19a365a27de34e23e154e7419aefb0be0e871bbe +CT: 24f2856e4e40c0b2b8b47e43d94c1faba498884f59d2ae1cdf58c73770279c96feeee3025ec698cd8f0ae25bf0c9fbf2b350674c317e52bad50aa6ed9845e194f294eb71ff192604af50ac7192f308583a3edaf6c7aeb588990be81b801dc916ffd621dd4016e2b76e9078c89fac9da39f3a88f6548006a48b0199a732 +TAG: a5c8f9daa30b045bd3e1c1b01f438518 + +KEY: c5d727d159dd328b4160ff45a183226b +NONCE: 881c0802db519ce1595573ff +IN: 88b4be77bb8a2f37bc5e84ef9da92a4b8c3777dbcccfed13b97e93c19674c8c3f13119363ace377a14e5f36501ba9a3898fc09340886d91bf0a17ef0d028f2a92ec150071623a4a5db8e56e99e764629679943ea879ec7634fad1480e8617fe834c26210276d7db208b13f9b4c2060f2867aacb1b47c8e110830beff721dd8d120de +AD: 5f6513ad3d490f784dd68ca1df41e8c8e1ab9a240ea8e9bc22d0b1d7353da94d5d37c94f0dcd1a2dedd6d8e1c79a383e7e214cbb6ee2ccb7c6d894ffce5d01b6cf13876ae2648d36adccd88710d7d2ab6d43826d37ee0ee3b434972a2cb8f4db1c3304cee0a352bbef76f05de0e6f55a410eea5e697afb197f2483f0200d0abee224 +CT: 66bbee209eb11c675ecd3303c38cf1087b010c532e1357732c4911ca9db78c67805c95c829194cd413b635a900a08454c6eb9cfa3597ab531fc9ddfdc5b02b290be2a618df7d03b1ab465d6d03e8b87a430bf4e80d8cb9916145cf2d2342a91fc79defa151b1f3c695608e76ca2abc4c0383897f1cbb9d4bd9969b2f33813e2b5502 +TAG: 43daa08e6eac70e3238ce655adb65005 + +KEY: 16af56326046c92afca49fe173d643ad +NONCE: d32a935b4e56472d92d9f2ce +IN: c49c8e5769670384d23d9af9834026395d3f3bd32d88e61ed06b2e00e52a5ae4fe3867993c2af95203cd4006470a89677864431fb9edbed17412913bad4bb3eaff0fccaa150c9b13f83b9bf06698af844841a640d6f94d845296638ac27fb5ed87c310dbbd36415161310b284b8f84b4e025267906e0a4c822b76a682d44a70f9afde9bcf48ac2 +AD: f713886f4086026779a7e479fa646cb33574e6c977d70b8da49c8fdbb395dc7c149a59e219db8e4fff053cb00e2a1df9850fce94e52fd34661fd3d4cd8ad3ffe0b4bc7ccfbbf42eeef3e30ce13cdfd77dbd067ae9f5aebfa068f6b7ae2c17ad956dc03511dfcc38eac9fa3c0c0e9a340f5c58e39d868b77dede54fea1173216c0bb8f0a6c2990f +CT: d5d7d1ed0ae3e3481e2ccee201857ce1f427734fbb4fbe82a2b90601104008b8ad4daf74514b8ab3e42b6f6b509159ca04489b1175ce1e3fe33d36ea521e0aedff8c69fd00aa588d7a2eb9d2d551e2b8fea321f573e2a1df147535a873d540a3169d3ebc099ea6c33cefc04a2d55dc2d47237b95ad269fcdcd3c3750af426beb4edfe7837b413f +TAG: cbe0fb9509c224bb0e8e33f7ef9b49e6 + +KEY: b3df227e6dc2c846095e2a3b825d7645 +NONCE: 578bc24ca3845e23204df661 +IN: bf69be81cf0b340b006badc9f644d10376f4f9a7a78c997edb8729e3786447f21e97e4c1e0c0c74e01ef655d0a84ffc04ff7c6712ad65adc9a0da2e3078d4c9e796c9bcd71e7a9da26b987990d366b5e00a23a93652e10942e07a6aa01375af27080c9cbab5f554497abc48260937a6fe895361e79cd3d5e78c1a65c6723d4a4fbe9b3dcae3c05699cf6d3fb +AD: 00898eedad307fc017917a3296bcedabaad8a505edd34e93d92f3b61797ddccf3fc31144ef70f255be3b0c165c97eb8706f14c495f4aa9b3f15d2dafd65bf6741d67fe240967efbf0e75e610db9a8f722035e039b5e9246d258084a04c12ee8ad1668032f8caec737481fd894dba2ef702d3e6089acbb0fe0bdd6daa2a5cd47fc62603499fe3ea37365072e5 +CT: cfeb249551a695ddfec5f789e7f0a9f916abc8ee01d6233c32744c10a09b5b19ff9ed15e9f10de8f93c8ca1ae3c34e26fdbbb7f3b0f5f8b064501830d3cc982da99b294ce51bd33085c98b0ac0bfe44a8f4a5a26511afa3461aa88b770f076fe119ec90f33d8c9e7777f30b8cc95864f06e04dd8e328ad7a2c7dab83b03abfdde065bcd0c7d6dd47389108c4 +TAG: 3dedd1054f1a29286a51817264317b83 + +KEY: 58a57f04d1d5cbdd1bfbe01dd5f7e915 +NONCE: 47affabd7dbb4cce76661081 +IN: 5f82d481a6a3856c6f0be2aca54d666f16de88294a4d763134dd51ef03661bab45da94b9871d94e5b574a52214b22c92cf9690ecbffca9b108fe796abed9e608778c0b99d7bea1daec08dae89d5f7229c04fd52cc906b5f5b9fc0f0fc1e0b2272dcf4865286ee22bd9edcce1afadb579ec72cdf6038cfc75c2dbab5a1fd64b6f8e200d1ad0afcf25863293fdb7276648de +AD: 4b662822b48005fbd85bb99e6a946eaa74403909f646d914a236eecc5f4558b60b2efb1584b1f32d936b90428dda6568515801d21d24d6fb622e6463897c70be01f81fef741d6dd5c6556d163c3f048abe49f21817b41850ce79d7ec1fdfeba32935b58d898e964fa4b36f79c0f1f560b0afec3887ab325e1a025fa7662f9baf8e08a9ee714b8369621a2f1e6d2e96896a +CT: 31ab08ce0aaa883628f4b33369e5f6e5a54ee4a6596f25ecd54eeea30e81b41d357cb6c671adb6acd3d4e6654feb2ab1f3259692502efb33c5121e0852cbcb2dc5d9a4c65752debe9c4bf5e995fc909a2881621d46cc220806703795e61c0fe74c99e3c1230521b1f97bcbf4e95326e2d581f0cc879a2fc06ef88226a4413f9e9985edc913c418cc198c4df13cd46afc24 +TAG: 1e54066c6cc37f35c62b47426b609457 + +KEY: 64011470970333b7b677d4ad8ebf3ea2 +NONCE: 17031c5133a426d96de93123 +IN: 882cac1ece2d22a1db7f8339332379eb68516c8b7dcb3c089a5bfecceb49f48a169215313686eb5708135f379d89962af478cae865841e0c97ab47a57a456f634282c4e03c99abf7f7cc4e8360deb48160288f06e96cb09114877f9d91dae98828285626a1528aac87f39cfb8ad3db344fe4318aeef6f6ba14bd1edf9caab548c09f8eea091229a90dbc4b0fa34fda2bf13d300a1f9c +AD: 0394bb920cf58806b909d90c046402c745f6876af85d8a281081e22a1908f8475126594b39a0e191a070bda7c78d30dc4867e69ea522cfc962fa5f9915daea9133e998eab22f32a18957a3cf7d91c6f3d54cea94875d60be694ee841fef01e69bf5997ba4f25e846558431eb592605265f235211c2bb2d4807278f4b9c314039d0768df24e9c098c6a01c689d6a143073fb1a29f4400 +CT: dd347d6a3d4a71b2bcae0a0c690ca311f012c6ceda4f7fc054b8f9b59bad54237b64b93331b99f1305801640a68e7d50cef581a57ff2564c90995a8dbf57fa8cff046d0b946af5f68e0aa3d73262965622fe6d35c78f949a6cf9e4f62ba71accbf403b690e31f610305faa6737a19efba1e1ee97084cff2d125bd69a5a4ff99aa399df650452daa835b3e54114b295f00d94fc60e2f8 +TAG: e5e72cda6755bfb3a44377945adb5ca1 + +KEY: 4852e546fdea545d7dd12493a687e895 +NONCE: 7a3e136cd961191570c1b0b7 +IN: 30c10d7a63b614bcae1b79b07c252dc55f322554ac34ca664910fe4a0c9a33e30698e124d91cbb55cf34e931807cbe591a87667f2284c1c18dacd108163aa7a82e274ae659c4ea144191e3fc0f82d4cac929969a50b98ed9fbee52cdf465a1f0535d7d7df15a9a6eff3f4a14e254571cc47f82716d7a835dfa839213677c4da8c8623517244891993ad5956f65d318d9bba16f1eb54d2974a741ac +AD: c5ded7f545d2eaccbc2cf5cbd1b38b0ec3b6bbc054ba25a16efdd448e5a47b0085974e469c1b0df22441340170d6677f5158e4ccd71446d7ac73dcf5fcfe4ad7248c4ddcfab4c8ccab0968d74d66d9c9561650eb98c088d87766440fc9967e8463febcd12ed07f7e44fef47cabf05274002d0014c4e31f230a41171868db68bf5a83c902724397ed181dd8c6768a898e0c78f6aeb886df95442e99 +CT: f798de4998683da7fa9ca030a23dbc493f36c48bb52cd1113c3ea97ef2b67433c00195000777fa3b75a3f689a66b148159524a1fe9576587948760b279cda56164a23748564ec66ea51368ba2a900c97169eb33cf1e557f46100193575737dba670175035f0d921675d45415c6591cae079698e6b1f74e82d4b9216c20e907b148a1d514b2cf653d2e4994f7f668dcfe88dc49c29c544de96d8dd0 +TAG: 3663fb2672223154981b4c580ed3d2d9 + +KEY: a65b520a2ab67a24fb8fc669c41f2753 +NONCE: 3bd6c7e8d29242abecc4c108 +IN: 9d1559d283f7a38847088116f2156b19a8feab0731f04d0d499c6b0d21b8563a89a9c284230c1298b28a622cbdd38dbceb098ab896a7259caaabfcc7b0d9ea797178c18aaaa351c7f516342dcb9d3e91405882c8faa9a28f7c67f3db8913b31c0dcd56472d8ebbfb20cda2896a66bff2706b12ae0d9bc8c6c123c02f1f0bbaa418c1806482423eac72d718cad0dbccd208eb81663a9d9043d6ae7a52cf32b1fa +AD: 2538529cc6eec03f70df2ab085027ce015279484981422f31e58aeee31e79703d72752af2b8822dce9b385f1530f19e692e00e20ef973d333f4bd585ecf122bd4ed9b0626cef46baff0302c71411d27e372361f36c7245096faff21f0236f3dd675646760d5687b3cf1544dbcaa863f1267bce04bca976616b890c7c6ff3448d16072c3938f9b62377609950ff7818cbdd21fba2560bf1954a93517962181b18 +CT: c3194fbb5c319a94c0f61c432a730ce7611a005cfc78266ac4e5d7c95351e71d613f06f52d9d008b9d886f4d9a57bcc232d47e0c75ab755dfccc057a9c7558d7fb696a8c29843a8b9199e2406d23cd6507d35a872fa54cb95e2cb9af45405ebc6b6ee353e8a80debc393329bb9499c61c6344a6380c118f30fcd76376a9765517652e1b21ecafa63c0d19c1875658f1eda89c15ac2daf1a6f526ca72ee792a4f +TAG: fc16cd532c926ba01e2e6b15327bfb3a + +KEY: 84215d2c8f86e5b7bf93cb0620da6bb7 +NONCE: b35e99ce89dffd1ec616ed92 +IN: dfe500919f97713f6d9c4f53913175b162b8b7587d85d5b63f0cd5f51def23119e2e02c224142ecfba7f0a519aaea3c28be20b9c2a9c98eb145afd4db523b7f0b822e67dad630846b2a192bb146dcbeae00198c81b80c290d881125c24a6b01ec901b8912bad5b081ec7d97d6997b33052ec287f692489df928ce36cba1e3d6a41cf10c697a9e1f4aaf75dc5be054b98965ec3ce173be7e127c4c5387048ae6ab5a8d247f3 +AD: 6bf6222e64a46c90f83f47305554d090bc8d3838b7a856f0e5e1d92c4e7231eda6af1d9eb7ff6ce914f2256a3b0c853453b9bc75e46109cf8d7e8a9dca224e022d3d1a139d00476775622799541edf9d53eb645a40f6d98ea559e181d96e4df0141e51fe067542300581c0424f534d2c2e3b1b27153c0cd496a1c03301226beeed2b5cce0710d1f485e68b44a918b63fd8db610c7ff894514e272b6ed7ae33a38907e0698b +CT: 6c6faa54df62ba5659d45f64a5f014684138c93bf152da8a495e9d067b13a30b9fb84847f56231b2da4d87e6cd509a3e38a9ff47589c627e5b5a1196e27fc7afaa14a8432c2d10d8fbfd5d6d394e4b947c456420708a76c2aa638df7de119c160636fc8dfba32227c5de12e5ef429da933ab04e77b489f2eb761d0c753738647ad6793cad64b8942f621ac67b13bd0cab106ffeff21f24c79de69424e50ae550f2241d4029 +TAG: 202b232472d050b9bbc68b59a0c02040 + +KEY: 7c02b6bc3db61e23736c5f36faddd942 +NONCE: b958decc680d5f79ea7b8632 +IN: 7e5992ed0474f4224b8da1d038eeb78413fc2f9614fab7120043e75986a4bf1114a80703780a149fcc8dfd115b768f45917065c85176a3f00be40b427fe3765d3919a5b741708624e29bcae876d251fd46dd8d36a8ef66f671c25f984761cf7f75f4329de7093937cdabe32f130b77531ab1aa0a1bc38fbe2758c2664eded828b2589fc5c34d9a0d57a5a4463163736f419b65f0543f50207fff4cf1065a551bc00ffe9466538b673b2a +AD: 76e430fce1a7d8340104e6001f1c2048d457ac335c5453e48727244b75c3c4f04f55afbb5ce55ba6f8632dbc168ed715b83968a32e5b8e91cb24abc9efee6dcb7a8bed9394a546f0b9efc5823ecaa192df061eb41c671bd863498c2130f322074a711ee43791a1cc02b5cacccf25119ecdd99233abf3b131c83ddb8c62c93a0d653e91499e7481303adc8dbac615ec464eb8640ea138f6236b0ee31cea060f97ea9145a22d15e28eaf6b +CT: 14cfd190ae0521f94ee6b36bfcc403139782bfac3d33fe95c81f53e83c7d0c9a8fdebbddd79746b550a383ece1b5c93316b2fdf5aa36b4e97f739f78ccd2de9963ee7fb4d77b581cf676bb679b2dc4a48d977b45564f21181dc60ecee84d736f2324196c20327495d18973660ccb5dae69b79853d12e48ee0706c8ed821b7f722e46f35c8dee2b7b55ebee01dd3ea1e8ef80493cab6b27c264a67596cee06c15062e3a96b140d0d9ba38 +TAG: b6c47410e6f4a2f2b172c6a4490732f8 + +KEY: 1f58ccb33649d0dc91c50f2aedc95cbc +NONCE: b3a392b1fff0157e95f82a44 +IN: 738e04dc5a8188d775262c2cdaa04468844755dc912a4edf9db308efb3c229b8e46b2b34aee2c6330219bcd29d3493e3cead142cef5f192b043502b8a4cf0419f9b3f5e001a640541c84141e36d585b05a2f702356bd39bda518c42b461564326969983d22c3ac5a2aa214807ede803d57a61c9547505dd7e08402cc43e6ed1574a48366cf5b5573afcc7aa3c4d4721b362d20a58cbf251315f2b5f9e2c97c5ef6bff44beaa5004e5b7c7f28295df2 +AD: 93f7f5054605edc769efc30b35018ee6c929a83bc6454352c69ba9c72e4b4ea6f51c9ed06f314b5682be6a701c719087765d0a7022e5c9d495f28a9053bd435b8b834045c3670856149b08dae742b372a15a0184375d50eb09877bf94f63859e64228606791c516e76c5695a4e529b9dc5f76eff1d4641a22597e4460aea4eff107348077d4ed2d6262744b0a2d6610f25264d905133309ace10bb52f7138674c25e5d43ededbd87c13dc8fd9d3b1b +CT: a002b47b18d1febaf64842fe9011484d618a2e855c4efcccc7d08f02dc9b53d0bd4fc8013e01e21fbf2d9bc7fdda69e68be0c06d32003d045dca6bd251c0bb8c2cbe3693b252265c8694295772b767f83661ecefd57353f6f1c442f9d21ed98c55cbe1db8171ef7b54fe3e3a1a253b4dd48416b5fbc7c18d73692e9fc90dc75d4b88de1fa47c9ad33ddfa4e582d3fc61ca2a8b1eab898b9992c8e56d170730454ca50cd4f28d2759388cb8e302be10 +TAG: ac502a9a52fb3a68a7e90dc639c7ad42 + +KEY: c67510714f556ea1744af9207917eb60 +NONCE: 71b347a21653cec3d113087a +IN: 7040fde3513cf7f1886d7be9c0f371a3b75415e94c3bdfbef485081199bec4494beeee76dcea05b6601ebd4c8fe231fa16d3b0f046eb3e9c9ed8baef25bb0ff6bc85469b2eb41b929fe904735f819b241b01230c68c0b61577899426bf0dd30e085cccb4ac290244d8c1cd7514412a3ebc51aecb6bb4be1a5a4a8d2ff3fc99191f7d7d0b44fe2cc4ec34deccf901f54e3dbe19d2dfe663855fa9d93a01ab14faed7f00c14834f63e1d153441c6fabb3cf22506e8 +AD: 6d28b410c788dba025c387f5b94c0bc392c69ef646b9cdce53dc169326359de26a721703d9a7c5017631a469da13b2d9ad9115de7d06922ed6f093792ac25ae2e27993ad6be5217dc4f6c51e18f230d4eabb01a474704b71b1407d9cff921bd98e28bb60c4fc019b4d609667c747e83eef779ee62000b6800ba2666f415dccb12d43af4f585d3185d66ba2ecf0b0fcddf762445dd1b6154591dd069f03977243b45b113b6f9b110f9fdd96f0b74e2c9843a45c6a +CT: f2a2cdb4f890241f44e00b3373769542cc3dd24c3d07502ed162dfa10be9906871051b991f36b2d5c4240df483c2ad704be14b9efe79ca704e8eeb9dc250e75a92ebf5800c59fb9a6a32228fa1121d21e0b423b77e20010d36b9e6c68dbc000f69bddbd521a1f7bbc9d7e431e4e46e5094be96a928c6729293d2d805c468a3993fb7439f192b1142272a78585e3b7fcedd2f7cced52ab2bc42e2521603b89ba7633fa3b4d07d9a314d1159d7bd5b2dc5198b0c34 +TAG: 0b386c3a58ad23e9a45f00ae107d319c + +KEY: 171d25e195bae2eaf666993f3b42d690 +NONCE: fc16bde0c69d5c894642f1f3 +IN: 8775d6aa2e46ffea6ad4439000a968bcd4fce86535b7265684071a498e0bfb37646f56fad79e0fdc4d6016fd1e935dac5ad74b11c69f5261c3321efdb9cf03f9b7ec681a7f708ba8e3f66648b24c41485a5147df31385809c800155d0d4bbf41d248453302c3754eed4909b267893309ba5249588cb4a4a14b4a29496f1e799559ac9f4baba7a9b4cb5bace1c11dc0e7ef7a2ddd2596c29cdaa378b97c7d3c50db49bcadb8e1840c6b9fa12ad88c0b8152fd753efb04ead427 +AD: ebb169a863dd05cffb9deb866bdd130a1c6852046881f3f8e9013158c83bfcbaa98743957ed4b0619eb88d7ff69b3a5d06da74076c3cc2dff83dc0375236d363c0e2b1fb60c9cf10ecc0fec94757b1b719abc7066af15ff9b66788b38083f766d67005369319967995407ea20339ba27e7bf1dc263fdd54ddd8088232a500f605ba825fedfed69cccca75c207b06594d1d0070ed12a259d4f574f352d2e2ea6fa45199213b6a42d53a7c717250715e0404f2fe7b64e3ec7e89 +CT: 8694eac2bb3968303f795bf0118e43c132c9dd22ec320ecffefbe878ebe6b1e0833d19515c07ebc83f12cd9bb50d2658e6d7fe44a9fbcc2225e93ed58e1bebd78edecbe6c8b3491eedfdcc957cc8ddc95d8116d50cc50b1999ac420802605cc652134ce51a41533e00fe232344e805df146a952b40ce27a2f5c6bbba2154489ca40cbb617476ce6ceac1a6b9c0175ee33615f252377f52583e970f77795b573610baf5cbf5edc6d2837244f88bc155f71588c9c4c1c802be9c +TAG: f6725998336b3ef020b99818e0d932ac + +KEY: f7db0fd345ca6ca82ec8624950f8e672 +NONCE: 3e7ee1a209b1a191f0a00370 +IN: fa86869e14df0fd8e77eba7fe5a933fd1bc58654deab310a03aa7202a089713e323a323f4932b4b8f6b40982d6738aef48951f621aeb82a747d290d93d1eb5bdec6a62fe66774209a4aea7261acff80af9512af090e0eb0f5905ce8baf2a0ec50ed89906d8d67f370639e6f16eafbdfa982897cd5a3f88929d7f1032a8b3355223bf666be94ba9945fb5cafe655d59af69829ef92365f54ff3eebc45e01ffc439b16e23ce892ba6db7e661fc3676a175a8ede746000ca147db57a14303a1 +AD: f7b826afe62356f985e8e10ff356dc9b5b9d9df24486523c3bab7db355c84ec7e4bbdf66482b74fc6b4c6aaeccd7717fba44eb4820a40f03639076776719ea7aabd3a815c201146428bf4c6bf1e8b056b5a22ebcb214fbba64de54089a20ababda5c860ec301f36e1801fc55fe8fa189f35722a2cbf83ae921a9537be2b4f060d918af9b12f9111909d59db7cad24418896ce49762223d8a20a3a83fdf24b64703c19c78f528daecaa8689f307da7fe0befa1d6b1bef24ac8d9f5f12b6c1 +CT: acdacc648833698eff4d42a5dc0b123cdf6f2985ef05e6f2d42c9cd04663635d240648da18dce158b21cc0a3f7a2c35441799a4f1f5622e11051c874b2bcc64314bf0b94c2589d2a24d996af57d22085a64f10135322cb68428fbb951d8b14683bf6fc96b1395829a0b05ec83eeb20e54daf7a413e070ae1e0b73bde56faac630363fe215f1883cd9eef9c3b7d076bbb56f6f5ffcce0d31570f79be8864482b6b3666424dadb674f873a1b52ae6e3d8ec8984edf54186e38c71602098308 +TAG: 4dba5b1385565427a987c9d0b030f4b2 + +KEY: ca80ac4cf4057182d06d65dcdc09763a +NONCE: 63cdd8090e041baa9dca5bec +IN: 701c739ba0c146983b9e1fe0a9723850caeb818514860c3d4adef10dc5e020a8dd7f2fa282896170f9039d5b3fa629dbee3bcb81db44d0d68f9522477619269a59ec1a9ed399d4902f25271dff5c42f3747ab0f4b61c26a2c1bfe1c0fed02282fc2ef88b47825cdfb11df3ced0fe0227e8264132dd62af2d31f23d0c0e253f01c80400127c37806762eb28bc71f31807229172c78ae994b4ad800d6247ea12d3f4f902bb50b72c132902dd4faee05e67836facc7001c8f58475366668ed20d4899aec4 +AD: 0e91b38fdc70951b97e43aa9ea2c6f78d445d90ddf4faabd3e6e0ef74f528fbd5c3d4da18cc3d8bd3167b756da495cba49ea35e2db849bc37f6db8370b492d7f82f2efafa5444ac62835cb5602796cdbe85caa50084e51eec2651996d2da0dc18fe10bd6f374168d4c9ea0a36ba665148192252ce9d05cb78429c55256fbb65f1bbffb8799d63bf41701d1d706a44e3f27eb245cf720f2a329ea24fbea803c575513830fff579a1bde3daa975eecdb8d3956ddd374fe252637aac86ed3c702c4ec63e6 +CT: ca46eac0addd544bb45a97a4989d45d21599ec70f843d9db38157d186716dc39a5d1a5c0624e6c825b5b7f1fd41aa542ac846ec0edfe6bc28f727823667a33cf6cb5ba1ba6654cd023857c53ff00a63b34d2c17ebae5d46dbd073edb7b2f9e02842dbf663bbe36238f3eaeb7a23e328b0d3d50f49674253898f360c0243722af266c934f021e4f2fb8747fae728d06717b2d68cadbff762956826c910cc8ad2d4aea4518d5ac4deec978a13072fd1675a272539ebea31d736c759227f31abc911e0e76 +TAG: 9f0202c228ec48f4be6b2f876fd05a83 + +KEY: 9c2daabcfae974ae165a2ea58ecb212a +NONCE: 4b9317e4be2256a467e2831c +IN: 09169c1f5d873f03821393bef013bbcafcd82314cc986675922e2d43031417c8e65e625ce737af4621aabea6fe75030b84acf96967e791f8427b8f052051d6247a897006c6ddedd49cb7148afa5109a561e78abff7c55b97091f356e31b5667270d5653a497e2503d75e5856ac1efdcf3fb6e80b8deba8802acc064905e2b09d45e446d7d810971e5996540ee9c01fac1b4331f99ad329565a8db38eb93f2e2a8ca37d64d73cc8a7f4fe3234cc155226393f1f2ad17d0f01d5e60537ea44835dea853e027dd597f7 +AD: 1feb0ca13b3022456a4801d8f5382cad95f7a50e466a102d2208e7482dc8ba5c710d1721de7103000fe8811bb13fdf698844257dd164f1e21b0707251f228ca8bd437994526ed5684c4165c9754d1cefe7eb18f9e116a455c28db1f7c04feab74ab06af029819f51ed96f453fb6a634f73ba8c80e19dc62384e82feac70a12d42e3125c360ec2a97f4ce0a07039687ffc37c5dc1df1ed24f05a37591fcd5c34a3fc5f825c79213adbbdef65078f5e41a4062517334a67560ab215fedde53cd8129a51f27baa80f53 +CT: 8a4d4ae0842f8032d83b2e4eecfaea439f745f1d0d07808bee4b68e3b58fcb65a4c8fd9b93cba2d5b4781d28a9cc01508e9e85796551064867551f9083cce342ba1aac4d2b8f5b0b0e4e3d7c82082c441467e47aa2b0f47e167b28fd29cb8d5ee52c2298c1f87cf811061d922f056214346c1ec3d2534045c5c485ccddac7d9998d3d08a80a62eceb2ee18e1a27f97616969df52ec486015974f160745667d6be25ffc20b143d89bcc8b6eab9dff82ce3c8f95a034316a8f2f2a52674105f1246b2daa28edfd829d +TAG: 0361e65b1fdb9d967492ded32e1fe811 + +KEY: c98ed84949749efd2ee41eaeec51edba +NONCE: 7b056c9c7b393b0b04382946 +IN: 41b87fe62c82bd34cbdc70033ca8d2ec5f13eb2c14947f97fbb5d97da7323f8eb5c2eba210be11b1ab9554feaa516aa493822af4a264c8849e9c6ff41f690f44966bb49c9c1df5995de8070a2fcfa42d0b0b5115a36738102134f571988ba4fb210edc3202d3c74b5f8801a7d1e217b90caa27acb49ece590ebe6637fb6e2f5f0b849f29804efdeb8c102b3e3d2abfc4f6f2c5f71f0a6e4d5daa5cf16561914f14601edc40547d55f7d11eb4768d5c64fc621d04e8c64aa3aa1245c7192852d2ccaaabd448e06f806eae66da1b +AD: 2fdac5a70356c2c8d70def497321c6bee8ebb08a5abc8dd508d83f03bf1a09942d7f7a387d4f875a1ff16c7b5abb53d32bcc372012eab7a3b848a93f7af634eff8c5deb3269d418be698a3026f6f08f55a6e31543105cf1ccf56193cd1af802f32e10512a6bcd3101b7b54a8f3efdba03018d5f2475b51bd65e5e183a62ab11c9462450883e3e87a9640eac909f72b83da8bbd34431ed87d14c6f7e79957067c1cf2a12b5fa083496f903269a3c6c8ccd5e3f9cc287904223ee62bffc4f157f0db409e82101e3ca5e05d962378 +CT: 384ddc8e7ed6868aa722f6785fab15eb69caadf43246521b97c8d016afd976360365bbfc9f48c08b0eaf5437af8a9c23061dcbdd0d22e1d58c92951b43e013689afa6b1587f79fe9ad3104ee1f80b3c95388e35b0b9a5a3b733b32a3e62fc143e6255d0e5b1b55bc9439d3c1cbed610d36c3667378bbc1ac20d93a5a7e5563409a5b94ec799a5281213d724e46f4987588e6bc7e9e6468bbcf340d5f1a1eb1b45dc9fe9c832befff54c8a85db9c07196d7d45cc389fc9d62f4bf1f4bb82801cfa9c408498331eef4ae1ee2809e +TAG: e8cbdc1d6d51ac64f16cf08725f81370 + +KEY: 42ece9aeffc9d2e8ea02e73d1a4de834 +NONCE: b59e0770c689d60823c06c69 +IN: eccbb9a2c1241c88d17204cb0f0c069e20512bb1d31f966349add203d84cbb79d88f7add957a0a8370b9a0e04c9f17215531cd48d08c4612bbeeecf3dce68d41724166e06a331e7897e8c7c6a6affb7bf07dae1874bf3bec044d38227bef5c228f4cface9ea37255e15d6b27e154b349b16048b0e7984f17cffa03da07924b190f9b91d6222db1124c1e4e77c2b989fe2a7c338c7316a49c7df0be173d0420e8790bad669f6da96745cf34cd2eb429d18eeb61a8e80a5e03294dcf3a5886bd1865e2a55a72574db8db04a9560f969711aa7a +AD: 2aeb8ee162a7aafe5a72a8d8873ce3bc43a65fd7bbdef1f6ba71b61e5a9c3bd033e7e8eaa55e08ae381362ad0991d65bf22c99a425019c4cd7768622f108f5917a4be22b4ab65ede66c58191e402f8cdad69decf6552dd52b62e8d62268b84122b64145c97115373a26d2d5e59e69b7dca5f96c48106e9fb3f7fc7e0ab11c78a1fafc697fc73603d3f08fdfc0ee885f84572fb04fda718a21744c7e5dbace91b0e141fa82fbd4d1a7dc35edafaba7c5894778c5952ec787bb547a37e509b035c684a8f51ceac5e12ae71b165dfe957c6de15 +CT: c5874137f5e75ef02521b37f0759b5724798aaab8a1e62df81b73175690ca1d32cab6e7a9d7803a8aea420ab273fb46eab9e5f0773b7f5457d7a8c0058ed9675a6e1a7f15805c7fb695d277ba06adc3963606ead0cedb342614cb410f4197f4fad0b5df2187f8d2ebfe85ad3d5f59bbf652364c7e8c3542c5d7f15bc6e6c24eeb1d3232bcddf6588ab1c1953085bd0a1516046b76714d2b97718ce57ad23cd213507f6cda95ee9c5c23036cc7d4133c84a1d36393979f9d1bbc613350252a6de78d905607adf51368175a20106f81aa9ff9d +TAG: eab1c7790a5941270f2ae49895b3113d + +KEY: 6ace8b5fa16054558c9d0e272573a7a1 +NONCE: 358c73828e032f0e0db608fa +IN: 915466e994705239afebb8025aa965626973e41a750bd75f9e8ccc7c1078ec555fa618120b4f4b5e273fb9b262df73d39950fe5cc1c265c06a08e2318efa83c63dfc689de80966f45cab0d2dba603bf116b9ef7242bf4d9cc691a775f78148d2c75059d6049c861da5dc40d5f94848c7247a724db956d050975d613433066ab89bf91936e0fc85c61af5c2c61cd1eb414b9df0dc125a31a3805903a886b427fb78551bc696610833a9e55c7776ec1622abf839d733594864de06999be8d483f8dbc4da99f541c6f7e21d946cce229a104a57e4b823bfea +AD: e54b90d037c375238f4989910d423bc58d32ccc06ddee558dc6a0c2f9a0f13b2332883e2c4ef9cce41d72cd636516b3506f28f914dcc88311fd7c79bff0ad32770e4847362affd98ad468117cf0daa0f5747c86359615ad6087ee18e6c58453be60f3bf30f8c61c1466d107116f88499fb1b5df9a01eb762317676d5413b839c66e5c1b74121f6f2f7408825745fafa2b10ba7450f4ce207a9cc682d1e1442f972a86d5d4039c4856ccbc00c43b5b3412f5b3f87c16508ffa527c8080a556944d359f388f787f9cbc033fb3333e72127e94c455b433222 +CT: 37be446820f5635c1b5ca1d8ccc2c5ab5b393243ef5229999a2c084fbb54a330bb338963740ba470973adc86e640fcc167a88bb940e5ad1723a01089b5e804b932138efed6fa0ed99c1ac4e9c607f466c829af04407a4a2e5cba486685f693a7b973921746902ad8a0242e02075cab66204084e6b281d58430f2d62bf55ad56ad279bdab0fc8c3d570fc3371dc3280ef3aea70d686c855d40ff205c04d457adb518d904f5715fc6a9a5f30bf1cc74703b175d70a1470cc810a366cb8927fb937aecc200928db6b73873935c429e2f8d595b418c5b1bf9c +TAG: 01b05fbaa9f2257b3c23ed3cf91bcbd0 + +KEY: c5bf40aa1127073b03c114b10f3f78f2 +NONCE: b4ac4fe9920fbb4e032f6aa6 +IN: 164906110c34354a0d4cb6370e1ccc17a739350cbb11d6570f398d50efe3d9db1a97f00d031a579f56d23da2441295af18a640a4e33c29dfdc848d722786d9b73550bfb76da1676af24a7bdf5fd3301090bf342369a24ba830c7f8883db6ed77a2ced83bb85205ca31f75a16a58fbbbd163a3af5e5021bee2d2cece33c08442e89d3f4d6d2359b94a7ec6cac388208a689b584d5dd1103fcf6af10ea2c7cda4f690ea0e4c7376fe2c3e69365d982da28c5bc18d58fe384c9ad2689f4047f9575e54970961a02419d9f2bac8061ce943f132edae1b9622738593cde52 +AD: 9f05d0391cb128690cd8bd120120f21725a79e5d2d0ef9e8322c04bf775f7215a82ce1ffdcf0f6562c188e84cb520f30842b8dcbdec36436725633325020cfdda7ed1af3323d86b2bc72d1b4a326f02be2231fcf133762c4fa76c8a7d5d3ac31cd19f63411a220eba4fcbdec40b8eb01e4ef33c6620978d09a8d428ce0e74d02c140881f46f6f81c2850edd82dc46f3460b5d5fe0b54f09a3f31548dc520f1dd46ed657995e63297b6834df57525408b944badf56234eb2b9a43b1422a5c6a59bc58be683e47753803f7341cbb0075b5795228b586cc571c1bca70d5 +CT: 5c75ee10a917651c49eab6a1187ed631c7069134e492bdb5e5698f8ccd5503cea5b1902d779c2f6e6c03b0108cee3fba03f2b47803e390930060ee4ac984b1ceb9488b4cce80e329d3427851aa7da2213eca2dc5f79366caf601c49a6b7a8ab068f1a9bb899b81a23c99a9de20466fe01398bc071c724b2942640cb1a00489e0ca7052f7a06398ad42500780f194078e3e77142df5710ae88540761b902084f57d87c2b0ec57bcb7eacee6743d419d8877d61666f93a127d22ccb49b5db0b93e4f4ac0dd9393d6351780dafa412380205a90fc8daad3dfcb1b7ffaff +TAG: 8048088e7e9dadc4ef98777c0f6cb661 + +KEY: b628ee6726a4d7925734ab1db3ec4645 +NONCE: c830b0d1b4113f4c9aae46b2 +IN: cdccda3718f2b0963414d965a3c36bce0a165f8e88aa70ca9eb3de6510d02b0b49c29cda4a7f6d439c18cc8fd80b932d0a4190236a13edc9994b1c4a71dbdb694ea5dea53ef781ed398e453ce372a99c204a138739edf5b606160e38cc8444c8fb6e9cfc3aeecc1760e90d13d01692ca894572a0bcb02e13f61d8604a75bb98e96f5f36d10e70a48bbb4f73771ef97031c7da23550b3a12554c2c436115fe56713dd303d1c3d87bcebf25f61710eecc9f01c555494facac496c68ef44344aae40bbe1199de793096d4630018a725b130a27d38ab2e8c629e61d2d8d37b5974f9b7 +AD: f4d345e55ebd1ef9faf967d76736f7ef38e5eb9d659bf8a89fd3c6c3c674161bb54758f1c14856281a7dff7c9cec16cc138384f644544881d50c7692bf22513223b63274e3cb7509c8a410a389277f86cefc801d026b0049c13d85b26da1dbcc7cb387084a3d4a469788ef85b6da02ed2ba0412ba999c8cd83c9c6716cd66b65760c42d4ef3e324b470c2a5e031846fde97cadc448e87bec15164da006c10d3a846adab2b09c29ecc27ec8a9134d5fcfd2c54f17fb23f1a05dc8da46e737f317db42e927818ed00d36af8dabfef09c8641159fabfcfaed344b03a1dd6f9b883f7e +CT: 4f39b8fbd8ecbc8aaea871db2e67583a5b06cb83ed8035ff639dbc9af92c4e3f9fe57b970f4e998a0262dbf77dc024d5e208d3678ae0d90e6fa5d45e2c7f0cf90676368c8784c851d3818e221abaa87c5e54298229a2f4d3f82505ef7bf45686aaf12e8322210a727cfd57c74a5f23bb5d8222115b28503eae7a5c600ebc4765011161736a346b535e1bfcded85c198c6ce6fccfcff0fdb0c2fc480bc6e71fd5de77355932d82f8eae245091bcf5abfa0d62123302e5805ab1f5006a976bc1468e3bed0452c5844029d7d4ea6cbd4a907e905dfc796c01bbeb69c54807354a5bd8 +TAG: 2b55edb998ac9971e53ebc8973c4e8fc + +KEY: 095b26bf096971842fae34af6833c77c +NONCE: d59d30bd5384b86b19b33c13 +IN: 3be9eeac265ec4eb947dd32583ac2e595505b363d660f8b8c2ef631390bb152f016ba7c75bf7c2e5e23c980d6967772ca4535bcbf4871ac1bf70b53826a34174e5a2e6118d7ff86d4836736c9a1f9de44c80b236c5530bb5f80e5fbce9814f3b0843a088afd029f4cd2e6190dd51fa804f8216448e7acc785ddc5478287b101bab80256977494fae87d0c13054fa4470c3827b2e8172224944c8c4f78b0a33dd78ee2bff16fabff15e5909f62c49beb455dd655ee1188b8eff35bfba72f2ec5e4ebad63d7db8b6338660f9b818c6832954241860925ea9b7eb07479dd6de27489d64b1a9191b +AD: 2ff9a8d12980e63a378d6d635d319c26e8f747435aa5d797c6e21aa69fe21f653f56da7db7d67cbf54451f336f683aa9cf373ab40c16738c44efd3e664ecc6eec40d6af82df2b3e58d7abcf26b1d9ebbe6263176ce4ef8087d14b0d5ae1c16917141d2ebdc76a0834e8d83c4ef76add82e957ae376b210ce2d94d2684a045a109454799f3cb453279d89c60ba9d038a1dcb99540fac078d7216ee94f96f5cce939eca9b5f9715b1cf3c9f1e6be982897c2f25225919db3e31595713a4e281e9919bc2c5a88c46835ce05411d0757eb738ac9e45ab3f1a42ffcd6dbd09f17f656f40f1cc2c050 +CT: 4723fb7339048f811434eaaf1db24759fc232466f5f53926b84e740b67f457c8c76f902f4d70ebfd97696380de95e8e40e62434ab1089e3a5308cb066fd4cc7e862a391c2f727a63a01bfd9fdb8ceae55067fd9d6f55312f73bc2c38e4b12b3aa96edd156dd758e9175e67a64a17aedd27c9c70945a065216773d756f533b035f2ab53335a159d9ed3f97b2b7a57aef676fad95c46e3b82eb800197c03812ca4e580916c5f7cdbd4aa1308ab16096a8af5290a0a2330902966a58dcf2e72eea7ce799a8f05c986c6457b05e3eec2adfdd4ed38926a3dc07ef208c91a619848917b96a082ac27 +TAG: 3ff349a628f7fa8d3f970aff8a6302f0 + +KEY: e27171ed1baad563d3d299abc0968b75 +NONCE: 5931a4414d5a90e93d2ac47b +IN: 1d209b32a772e87c5bc593fe943d3d7a1497f390ecdccfefac50ce14595b98b682111f82957278241f291e655b3af108a9cc1523721652b6d446f34cdba2e61464a3217b29344e18ce8f47f10da88c2845a009b7491bbd1e1f36ec49997a0fb09764ee25355de29e56eae7af42a8c96aa137c02268078b7f145fb1249bdd74f2d4e4685de75be4dd7fcf29482eb26b5dfa5028accbd23c3c654bc202c1c0ae7a597ef15f4d14f7b8a14fd45698470ac6355e04fe4a14e3b2907bcade18e4152c68631f313cbef48341008482f434c017bf8e1dbd048f0d6d207446e697fea68202be7283188d1227f21ae4 +AD: af2f6abc40ca82d92901de02113cb8f7638f0a510f6a03bf056a75b02beb10157c97632320fe14fdf0610235e3a06172b6b6e80d2fe18263b11e9a5e3a07758c55131ffca0a6c9b121c37a0c85658125d5bc2edc8e4e247a636d7793a1cde364ac22bf754844607daec0a6b939d05fff5a8c44ad030181aad2361ff61f20a224f2bbf2083b2fc2a5b92f5a66bf2f9b4c49b39dcc23cd3ba66b5e7c19c5b7b74a766c3da0c2b02ac80ac22c006e8eaddf48ce6f6887f69fff1fd0aaba0a0f70ef84b54280830a62d8b0dba55ddaa5b0385c586dee60d1a05a28863a081cb9b41edbf3ee9ebff98cff983917 +CT: 673ae48b6080a3dbd08034312c36201d18508f4e1ee178ae2632a9a5ce0938687ac7e6cb238cff852ecfc736bb8b3c04b42752fe65cbf6ff897e207582e85533f7c238b0be14bb1deb4cdaff524b013661e4f2c96807bcd928e15e4e159390e1eeed036ce776b579d9f3fadcad81adfcbb99986babc9a8465def3de8de0cae19bdbf6488c12534a9b6b7d6fdaeb1d4c3be36b4adf7444a0b9fc69c69a46f7bdeced1214743f3357803d2eae24dc50933a733defc653dec56f0e0bfb8928de76699d4f7029fce9175b3b7cfb6c7ab1018f6f3eeb2b9401115c8cd382b06e4b9b43a097f42bebcc1493a49d4 +TAG: 285c1a0028fed3ab2a4d68946399d700 + +KEY: cfea8c059d7b866051aa54b8977befe3 +NONCE: e54e684ef16a2fa8e25786d9 +IN: 5a20333c4dd9b7378bfb773b7d64ab80379d16c0a56eb1f48f53c19d0fc4519d0b5f478e37f16d6e5085af31dc63488f9f2cbde3e49ba954b674b0a4e20df811098f7b8e716efaee6a4109f16afe128ddb0e54034d66bd00d13a6c69c9ef2e5a065825701f5e85634e118c69ff0fd71bfccc25030fe94e778e7f474136cd3722eb5bfd88bc99fb45dbc3060a24ac2bdadc5c82d883c5c63ccc0f7aaf5384f4c7fb07310b66a7c767d025c1a02dc9aa3d7aa921a72084906ae6039f837454493aac3e3549ad3722a735dfce4211819a2d7ec279221d43360edd9a4cb930815c8565c22b94b4849a979d5e2a57b2da8ecb +AD: 376d8e02071a93c892293902e369b8c7c44a4c9541b5050347b016243935408d0c9557b0f66c6cd493c1b8da68c8635f4c868e685674aed42f196ee9b6e56ee44510eb9b9e89108d878be917454dca0c62d207fa462a563a267270d6b1602d6795717475bc6fb5c87b747589328e39b1d4db3cb19f0fbe9791aa4232e33abd9e14b5fa3abe4705ee988c657677fa063aa349f1a05de045f3ee66da03af18b6b8b83e29b203e12bb02a4cbaf79eab3cfeb83a5a997daaf8f36fa9e12faee86c9cb351ff361351d98ee3a10af999799955a02fc46ddf56c23070319b3fe0cb42d07d811ae976f242670e618eed113b4342 +CT: 06ccc7336773919c2b1bd832e7c48ae4a569db96545363ae0b28061fede28a25ab6cc0382aae3e6b31efaa4c225073640d0148878524a7f381f53b4d21a43e39afd4c12cfdcda442d5023a8d2a8ad49f4a002ecc8354c86520524017e561fe891b6962682d168a860210e0def1cb4be1bfc6590121c1b1988254757fc5a37ef916827a5fc258ae772773a6902b084817f3641c21d3d1d1e8818b9851dd05aa49ea74e16778593f6f486957345462732ab92b1e4b06c32b5ad3270c5ef3d80b4e4bd08451e92c26acebcac1a4592e08ea434a1fbc6dfedc677151ae9471661913db19723184d9ef4bb49342606f784d98 +TAG: e7be877dad60c889d397726bf1b6ea89 + +KEY: 40d35704108a944f1e7582503018cc85 +NONCE: 26048431289e7e100481e2bb +IN: 515f9bd4935dc10e77dadd81f5a4e0b53eb858ded393979ed75330b80adb36f6b81288dcbc581e8d93b0e4705c07be3e200422397ca3648c9676952e60ea26d12198add3e33cdc589ee5a800a750d77978976344dd5dc710e56dbad462fab7fbd08c057a9f8765c4caa9418e6380038d288e09a90befeffb1e8d60e79925dcb3772cbb3258b15544f9c9554181df3483784b89b73bb6f9ca55f6d644c02fbd7e31bfbff45cc40132d2bbd08db6a27f5a302e1dce2f0afe4ef5bd4ca844c7900ba18faa1896a36896a1c80307cb37162174205665613b39cabd0a5b2dd1d5f8b6fee948006f0b2e31488c0c613c1d178b7800dddcfc +AD: 9c86692c874fa785e0d9384061bfce8d8332871ecc195621ed478706c46057bb4fff80515ed65b5fbbca3d463a62e227c228a340143bf012233b1c05a50fdb4ed04b840d983f47e00e001844a0d2ce14f6dcea58069c9b0bd8824537d2420147be7caf4a88dc9912853a7fde6d2a5cc21f85eeabca7902b94eb79d5fa143d02585acd57b93e4eb6bcdbe289a51c6631f7aea7bd9dc0f6cc2ee8426b37220216f834033fde15e3543422612fb3d972b8eacaece9614a4b759d93dcdeed026cc90ea058d7dc985c10859d4ef14ac5cb14849d4ae404badbcd98c28663eaf7274aade4bb7527c4f960875ca703ee6732c9a3720b629f2 +CT: 89a21a1d502ba947ac1921efd3c998bfdb437c2da0802e5eefff66de3af00bde934fb9109e961f179771c52de783680683f4bb752f877897882103146d030bea5bc3c03f923b477443e640450244cdf66d7d346954f6e862a3a577820d49151a82f4205340ccf2e11e4575b53f7ffeef09ec640df65a0b8c04b37f6dad7f940cf2d7446a6fc5bc2dc31854c27567b2badf6f8e94294ed5d899a458a080f38d6e72df59f13f5c8f736264fa2b302d5375d6e3f8c3abe4811f4f85cb6e302e2c12a892a1e7a78a5a33e4b555c02917330ea7a45f20cb59fa991f183d1e2a5bb1761005b73fb728124fa2082f41cdbc88bb06389eb165 +TAG: 5476c08e9561442745fd2f222d08b535 + +KEY: 2c6796d0773d12455829a3242ac7d480 +NONCE: b43c0e7842006f6a7953d598 +IN: e0f7ac13e8cdf4da6c17f1221df18b98267277e79c362ec2793dbb842bb9662b5e2fa34e43cea12f71b4eb53d9c862f176efc5d91f06b5c532d9c30206eb4355ad442127d325ae2c30ec436889e3d7a56b683ee09c7d79768d6876ebeb67b5a2cc13df02ab93646386106e0473149ed77ad0ec91dd282712d0aa26f30bfc44f93cad39504356e3472c5bfcbbf9557cd85b53e33e1a88d2f08686955a3d876e4eacfe783e5f6089b3106295899d4a73fbbdc1bd22e1408a2b93a9d89c9489cfe7a9a7cda7c92b06560a189f5ed04d1f02489685c602f8741baeef3fddf610b1a25ed26d88daf9a05aa0a476c8000dbbf798de92b0ab8779add7b7 +AD: 1048769719a44958dbafe1a59a159ddf2427c5dd8746a8454180dbf59f48ff6467d760f8e06aae8d2d2a79efefaef2dd2abf33ba1929073685d0320a583a56e8748288b50c7eac551aa859b274629f3d3cdca5fd7b2a08f0bc830e929584bcba85f80e2eb12bf83de607e4749eaf7631c3545f06ac236d55769c8a08427abce0174c52718c2c08b02afc7e418bd7aa7715de95a930eaf92f54c7dfa2f3ff3691187a21c6bb9b238d2fe2dac7266de30c94c7ee96fa60caf5ec0f5aae5cef28264933cbbc295cade787321f4c12f63ddd85185997a63fec48fc5ddb83be3b47a94e15dda3f315e7495098bc7a0b7d26802e12fdfc6a94bc6c5a76 +CT: 794ba0a7df144e66e6e7fc83ee290431818d149673d1821e1df496565aa7996f9e581fcfe9499c01d8716fd3f6d67acd6641285b70f8457108063933126c95b665e551925722af60aed5343e429e645574a65cb6fd767b204ca8fa91979c6fe49377fe4b43fb9994e619e1dd962fa49a8ae5ae0b8eb630f112c43a4e9c28ad91fee9b5bec0b27c5472e30c2699e984dcd9f984a3eb7a7b7209a165b2f4a74bca555dceb81e3495a3d39115d32609f372d8dfce820aded274ac567112d295de5b261b10c01f4939ac532d4a0591f87742d9502d7a2201178b4cb4c069b1873c44b73a901e299d4a41e57dabdefa39907dc559b44e99f2b950e09c +TAG: ae5afc2bc4096e308cffe8063277ef88 + +KEY: 092e4a78c47bcd0b169aa35343c885f6 +NONCE: adb73023c873661f02bf4ea6 +IN: 0751fac5f54602181fac252cd2fc408ea3763fe229b80149bfb4b0044f541801843c8a20ffa1ec931830bdbde31efa998e0875c09eadaba6906c870549dcc650b865665c56b5cf29b75da63de088fe4d79cce59499518a04a17dce18879e3e33ed11ad808d470b2811da4617039758109f56fe75eeee696ff51c18d5ac04fe895518fe59435ed1f073b56079dec1701999ce0e5ab45829cbb85cb1f94dc67c9ad28815728f6de85fb7ae12203eff28420393c1ae5cf644bfb5633156e9189beb02294d7199e54ca0d2012bee2dcd6322eb90f41b3c6086cf0ac6b3888b21131f3e57643f2ab60141aeb17d9d07daa213658b52503482fabc4a0ba17bbe3a1a +AD: 60fbcd82efaa99e17f3cb16a4d2a1e04659d13d84a83135a5e332366ba5e6716bb3674d27e6b2df4269180a0df25841e2235eed7d8eaba571b34178ac1a1041623138641f500a7d4ceb28efdc0ab45274cf26c0dd16174c77dcdbb79a7980e04d48b35efd3656e501e352b605bdd1b57cb7f9ceca5ca14a3953b2dc77d18fe1c4e1b859d2b02feffd3da7e259fbbf27721d330049f0d1c2729ed2f8048abfdc0e7b3609d2e6b4f5b42ece472f0fc330247880fd04768b678fbe20ba9581f3db18bf3668fa0c80751d78286e1927aa6e27ecce63fe883ee88e7a05f8ca2a387b86246f7d1a4791881b14f619a340163da62f4130b2a2c0bf39f463ef0af4120 +CT: eb0fffeb17e3309d1104c9a9c211bfbd585f9516f775793c365d36352e93af1b4db15430b454d1e7aa913f2af994191c365d76a4d49eda531fa7ce9c49b98bad4d591c868fb066a2e00a6bf4b1bf529002d403313c5df306ae34b8c62e939569bb5401eb7ba87080ba505e5c40a3856d2e177d247a5d8c727b32a13014a00a57e9f01cdeacb4d1abd16f1548256d661c45da12c2fe3ab561375875c7b6e273bbff5659749631fe26cef86e02742d0cc3f63a76ae5ece59b6556ab27da9de1a20c627da8bef3c596ebd7b246505006d1a381c2a24dda70e52b126b919471acfce274b89e07d125bc69bd94f2c65bddb82441897973566014fef625bca7e342f +TAG: 8f2dbbcc01538ccc45436e7176c2df47 + +KEY: ab1405116f454a3b1f106fd491cdfc8e +NONCE: a9e9a06e4bb83c215fc59a00 +IN: f64f0ed5ca25e118f2a2dbf069a9dc0169ab0079d91c6552d4a7e8d0314c910ce0614e1f6157b0f758ed6d3fb3fc3e2eaaa9718ef30e8d0c136c8bd6dcff97c0f5ff8a5d3808d8c23f2a9ccc35fb9427afd10dc1c298e95b335044b8d33e414ecc17d7b34901608284bc175418910116410a40b29dbb379eacf4ead521db3ab2a3d9956081af6d7438714c0631147b7d1e9ee4789751d4260b57630bb573739a3fd0b19a7ee8c301d7f1b09f86e60e31d5f2a86c7a65b244d5e4d591df3df3caab80887ea5f1dbb569516672eee351db5d5ee4d662a3d3c0e48cca108966ac6dfa6e4f9b88e5e577752826d2da05f2677dac7c31774eb64b1b0fc938580a78e4a296889c +AD: 3726f25fea1d10c2712d157e1a1bfa75d6f9e5bda448944ea2b7b85c7d4ff4ac00f68988f2a290cff3d5dfd6af33770a021b03fadd5741bffb7532924f3f2841a7f7658c49c6b915b1dc41ee4bb9ee89386c9911974979f43e71297bcb34ad6ed085177ea91300c9b42524503bbbbfcdcaea03e3f2c939d6b1dfc9c6b6e53e221568d2557bc3055752f4fd487b903a2a0bb7697a19a763fb7c615c7edd099f72e87849f57722cb0987651bfc476a0acfe13d02d6b01f761784d247301bf514a14a990cd4b59664f826649e0f389787641c1e5b87388cff42fec144d6ff3f382b85062bc21368c93019bacb56b643808a848c60bb3d804aa64e2b8fa1c128d6914663d9d3 +CT: bc1c14f1df6ca46e6b4daafb016daa235718fcccfc1ac698a061885c33479c0a7fd44e46e805869383232168940b1a9379bc652c565059ba81b4ec2ab435eb9b91de5bc03cb0a7dc11805690ed9abbadafeab2add15f9fd69b5ff4bf4ab5cdb4a6fd3164ceb7820530641d8460b83929b13860bd2e64b984407dbfd2de51e865d88c63554ea1f04305ab72bfc991fa5573bd6b41c4f8c848fff4b0c5d2398a57b4de4678ca4dfcb16a7612773a24088893444a8ea3d0916e4b460b33657f41d2b04d0c28653ed068a3653975402c31088cd74722d3bc09c50679d0ec94c1e84844886b1a56c4fc3b14614634f08c5b0868d276e9f8f992f94b2c55be5f2e408a498d27c7 +TAG: ee43dba528a9ce84a53ed8fc1fbcd871 + +KEY: 7990cd12d13fbb929fa541bdb8e3107e +NONCE: ff7b2818b62e856952aa2cac +IN: 5ba2afc1da8c18d8be3936a2e515bf9eabb93e44905a86773a38de7f959c49ca56d7f1fb43213cf7fe394b49733b031334729ce6c7ef17d843790fde814672ca982807b76475350210871ddf8309f59fb280a7d41726ba7f00ed2fd96b4a17aeb7d157130cb7e49c8a454cd08622824d20f86b4ba062bb3b3f9d4a9c1402a9d80f3324e4127ee57ad94f87d6ccfda76145363fa70df95341d483dfcc304757da7541a0f148036b2e2dc7f93697d8d275456107a016b425542a89ee33ec02289f5260257176369d990c8c89df73892d7e67227086c0c2c258e5fbfff8bf9129a230c229356fb0935738d2d6fb82992c3465ca5a9472ec06c7b5a29240b611837225c61a0e14ca2dd30f +AD: 865a9b2706eea62f3fd3164805cd8fe4740d1ba7be809cad9fb39cac26f7c57d4c449f4eac03d87f87dcf219c562b9ee07ab3ce22abd46237eef8221049fe499c9189f789948af92bc434b24aa44fff600c2d698593bdfcaea878f8780adbe8dad2cf453d253e8668631a6eb831be01db9c7f1b7b8bfedfae83bcdfef3501cf2b2ea48bcb19f40a70733f3e4c3dd90e17912d5797fa46ec852edcd49b0780bf6287679aaad13a926f750ad7d3ca1ccab577b74fc0ce4cb22e5c619d2d668292c9db4a98c5acc4c49561a77275c06f5c3fd514ed8555db3e2f50dde5c23e84a38129e7a91cec8d168bc828d09239a5c6bbb180bf69950540d8876f9fac5d1a258543a771610991b92ec +CT: 1901c8f9b5a99c46c9cbdf8ace9db03f36ac17183295544d8170fdc3a16c7194a2fda400f8f0b251a3eccf639f539cc356ed3fd09383954a8119b536290865c30a629d44e467acff5fc323d2be97f29fb9b4ef7cf2c18a63dabfefd7f75e696c574372f4a35249897a3387a2b10c1a50ae23ea74560b498c9d06bede78f4c8c9d879667c8c8e137a0a254f3f881ce8d183588546e066314bf1989d1acadbae61f7836fa633de9fd0fcc5b3f72aa03ac432be8f7a14c8e86b45bee416acfdace44b783137e3135a801342061781007ab939a52c68d686f5e3b401240bb10e764211a059fb0aa00e2f635ef214322918fffd0326ae38ee939b4045c6039df7e7def36fdad7f5b65c20dd +TAG: 3e003897b4d9411cbd449cd8dca5b58b + +KEY: 64f0a8065987a4713e35dede10afb708 +NONCE: d6ee984b82f1097331400f38 +IN: 29327f95b41119679b80c3b51fb5240490689880ebb5ff7b59a62ae5e08f7cf0993c09b13fd845ffb32a99ce18c22bb8825c137c3aa622cf3a8390042c6a1a159aa1dcb6b6b21f4e07fada584dd21620b2fe0aef64dc609aac925d8b8d26915fc101031b68a4bc89898bb92146a0a580103da265cad1946791c5735b95d85d3f0f1f39a88f47b9c52e61307627c084d68d14bd14e3572825e190bc7146080bca423099f643d53ee3989386b87fe3dd9c383f6a58fc0437fdb2087b5211df2069bfd981d8ca785384cab31545ecfc35345f38837883dbde917155e631a46ed1444ea0ea8a5441bebd54e5f6ff914fcdd66d62efd223f34e16a880370a529b2ce6ade88e907102021dc87aba9900b6 +AD: c8116196a12363785d4d6fc593b23226a5fe83b00a77ba24c69644d2e52291dc59d2af3c6ae102707439f22c33251a01c41867f54ecc552396a5aa98ffc687e3a88d8d0dcf826645bc78ff9c1a3052481933c3e8ba8e30bc249e6d095699ebdc51684696a15dcc9e28d09cac757e51336f79a0cd5ce8d070579e12956a740666d28ead49c47bae10db20fff8dfe6fb0260a87cc6f5a879cd0b2f949dbff046d90cf42c7ab51337e8908302935e50755a4503107c84fc94f7db3d3f0e8eac9c0def7435676701c9acd7f4c2349c3b7324622dfc4d6ddd8265a810c000158260aa6a7e3af973f8b178959de409792652e9c4ed1d50fce2e5e6bcf205c6889ed717db7f4b14500aa8641b8514150cab +CT: 3e04445e0ba21e8788f6f192b710b466d5d3433463f0308a3c0fbf7f1666fe01853b9d340f496bb0c2212ae3e3d34b0fa1adaf33f039201d1962f2b51031c2a4dd9aedc08f7c895682d1352e9a21225d81c98ac7fd4b4de6efe3dbe437d255e4464a1258d4497e2a1d4ef6c319869b78fdbcf4632743825112fc21acc0a1431d8cf8eb8865e695c0f3668ff5acd8e850373331ed7ae3bbe515b42c1d0ca0b9caa4df0048425fcd08850f23a86b4adc859291b5c49ed54e41778c7ee2a11da9598396aa889dda9513afb9fa0b66c0affa555bf76849d754702163004fe3e77ae5a7c46f3696bbd52cb8680583aa5cac22608c6d45b96770dbbfca14312fba61b3fd0d7041ded80d8dfbdc3f901b10 +TAG: f42a0e4e6e6a1e0654aca2ab7877350d + +KEY: 2c351f0b77cf0920873fb57c910cea15 +NONCE: 4f844d27dd26df3015608119 +IN: 227ae9330bfd5a662af4137ca7fa164f383a63e5bc33eba94726a0e7a27f666887fe484680899ad8aaf6fc5426600760f5e6ba53b0484615d0089d9b1e75f5952ce0665d16a045b272c3c50194ab7b3831b313dbd800168a24e576cab5dca4319660fc6add76bb400376fa29cbcaa25adf3cac81f3e66a6baeb0d94ed92aa37271d2cbd8219c0647f0af6a4ba8a8e169c10cf6354122054a547ba046e67cf1fb424271d3d3eee5b51e94019d450de6c1f770395316421b61c5ee9ff00c910103e58d423946c68369730a974a392c21be3fc8223cd816e7432200390fd7cc3f5160795422c9daffed23df42a7f8259e295d43fe57f75f674886c6405bc6954d17c2a36348761ba09694964646cb86c0d8c64c00 +AD: 9d7d5e5f63267154bab863a7b53e0ba159a6d8a57a8c49e084b513b463a1e812e94611116dce9c1ceab2b7e18b4d69f7dfd225d2bdf5b7750d0d9dc131f22987bc812da5b0a8ecbe9d0ca2210cf6ed8a791d95c3f72898497226f69c8971c2da342500b75367842d14983384b5985041eda7f1cd73e2b5c71bbbec6537390313583bbd53d2d563848fc93d81579d8db321d1bec973f7c4e8f34b6cab8bd7b5789a7b40f599f2f8c43f6d7f8fdf940577ca8b5159e699d449ffb00acee0940937d491a71a81ee9da0949f8fa1d780f3957908819221941f0c5d011bfb2560acf2d7386f973358d68487954e26ea9ad3068c65b797307831e03aef7d1f1bba9ddbba2f251329e85172ed8efb1a689f8026b5068c +CT: 4ef2a097a8e507143b6354ecd94d072c0068c68698fd04f2211a771bec45d616d8eb7eaf90140850c135cf468dab9e9f3dbf059b56efcf616b32992df407bdb735a8b5ac2c361973abf47029bcde46dd5b13728add772264f2faf60f3de10494b0606618c383c8929377f2390c4a104141a11711ba7e3a3c83396761d7d62a997e8782822f51ffd0eaa0e6c9e02ae4effc0686af29f2805039c1cabc8b826d1ceb75c4274e95f854a9f5be709ddf1002481272586aa021acc2fcfe3e6cb0b2a47d124bd8b83585b43bc38599a497d0de3979c30c81536ab06a1649a3cf5dc2c2a6e52bcbb05a76e35139c668dc8a3c038ffd1fde8c1b4a31de48341b5fd586c674e35bef3b104e4b84063889907c268226dc73 +TAG: 12aa2a46a9014800b3243d1020290d1b + +KEY: d94582550b2e0d42255f13a8753f8e82 +NONCE: 82f7abb31dfc28491697b347 +IN: 53ba297d691fc3abd93ea8b6f3d629584370ac045934b1b738a73c09a8236bf5f99f357b1cbb120414c68ee64d304b7751c88c563d5d16fa094602c0ad3c803a8f116f3a5071c049a4b88f19ba2d500a171565c719fa64e691bd4a9c4588077b0c2b91733a30a214e474d868ac6b301898dc85346523bdd4f6c9807ef69941a5369b4b7ff7fdfd252729d3829a7bde65427639de0b2b154b4830f57ac13894bbe705f02362f8b75367ec7962c53bd6aebbf15d72b25c08570392592b6a83d4f44d2037da8cbfea2456696cc39a3272e46a5b4fb837bc6e4bcd9606afa58d3b260e9f6f58bb5d0f07438f378b6a36c1931e9eaf923c2a3679a789e7ef5865c7e799ff4633f1b2acfb79a5a0fe9cdda9cf347b9664568def93 +AD: 2bfb6a6726c6564b31cca749bec29a8c9fd7bfa22f26af0a80db5e6b13a3b10367be6ad87325abc59252453422535466347059b7d57fd2b1eda1d6d37dcfa9da7df34746e1bbc98baeb4bae17281a537fff85c0785f9f27617e77333f11be28f9aa3704651e4ddd72502c79cb2a810c4686147cedf056b5f035566eb34d117c83ae7815e7e1e83163907020cf0736ff1862371e87269e5c8c1926e0bafbc10610a6ba6cfc273c9d9bec0922726dea04acf72b3f88a5fffc57e0af6dddd0396b4937d2e7d52feaf60d29dddc5b4cc139eb855acbb794b99d74b8a93e3731f9092b92b9bd50c846eecb6eaed2e51290cd1f98dccf3fe746c5293e0b970dde72835c44b3a445dc1f2bd67fff6b1a7e378611eaa42889fb92de1 +CT: 1afa2fec98728ce39fba26bcc769e9766993c8276f88613db574773c84c91fce6ee7dc6ba4281b8d2dfe13820723526f0d6f20cc21f305b792e9a2bb1622c742fbc05ca1f0121cb9f6e1ad6c3ba80891e2043adaac4f1bdf29260a44a182cb165f58f480be5f16b51fddfd0d264bc4a18bec589d24817f586fc8bad15df7cb4d48d788fe7fbe69f821b5558b0a664ee12ba8ddc6bbd325f9b83a024245b4e68b310f2282f4cc6005209f7b7aa6ccc025d435441e3bb990e81bcd4c8218b8360163ab266be4a1f5603059db2bb67e541e1edbe8e7762ac522a81f495f5ff8bf99948050e61c86e83134f4e1212f879c86f7fccff472fd9753e27a0601f914655a5f803061cc986431445021c907b3ae0f060fac13f3723867 +TAG: 5ef1ed1e2bf562893b094d58516c11a9 + +KEY: 31d93fd51c2d6450cf35d9edd71413f4 +NONCE: 28f6f0c288c9f92e80252e1e +IN: e78eba6c58f93cc2374932fc21e54f695f2daeda3bd1e0121a77d178e3bf5c0e824a99042e8f2522df829d014e4d35a756780e8c07f53ca8fb78db6fb76754ad461665051c4572b2514804d0a9cbae1a1a013b796565eee13a7832ab8834b8406b1185332552d38754dde2344ff4f6e4823390964ba2dc43de136f2235b1d919e0f4ad60813d30f0ac1dad35abe3bee9479337c7b430841d2c722f12aeaf931cedd8a82053f697fff8d07f0af6013da7da58a5dfcf45561943e7ccdfd8d11fbe96a68a5a27982e47346500c0284caf8e6b63c6621e80503a7365d6693dc9a249093dc45221cfd88562e25910034c2c123e44e3b09d8a8a15547285d2596b98c7a0ee9d10b2cdb032d08a6caee1212420b6854181a583c15e046aa202dd +AD: a4fdd42aad5475ffc1b122170024486406033c8640233cd9b23c286fdd40c5b69eee39cfbf965f7a10c73663f9804e6821c4f62980f8362a580bab446325b009a004b60b1dbd12566b55b42e58d8037d86c1050cd6ecaaac2fb0ef616a15bc5bcd8252fd459165795c500bbb2fb1476e5cfef9549db733be65bde391c810d099e3745a2cc7a94debe1f4ff6653b338123ef7d2f9a602bc9a4bbe757a63f932a802014f2f06c6688faf14332a355b1025f33687124399f55b6a5adb4864727ec6c5334c41d78d1463400925f6c29c0f611f35c9640045a740dad5b4f0dcb632e7f9a3478b526aa9f97cd9f8d3ad094b7922890e7b6d9c67fcc4f747d04ddcd115fba0a8f0433c6fb1bf6011a9cd153f866c76b26d427a25aebc60d10540 +CT: 8d668fb50efda82552aeb5d075ff3977c37929d73f6639289e7c6da8c89c664df80b2387e788d12398d62d3c0ed2f9f918010d41021c464d54f016c4e10e85e29ba3a45793df2ebd6cdf30045363434387bb0d20439f4986e6eb7ae9fd85fe776f7b8035025624c2413ca8491cc6e79fe901b9c40ff3a0e37a7c7e88b56de4fee65861865162821e046846d253982e4ecd17bd26214b0923a4297d4ed9423395d856940829ca5ee74488c3b4d8aa3c5ceade17d8a3f2e45d3ba91360ac1c76d6a29f8243bf49c1d75aa41ba239fa6f3b123e198ba799e3b70c674607c5371894800954eda0264b3b82606433f71371dabc5f1fb3d703232533662920a241f613c38d16b0bad24f4aa3b336af89cdcd2f371e1bed7aaa47c56d17100a01 +TAG: 594ee5c93636cfb5fde940e3d561440a + +KEY: b06d694a83b14768ae26a8f00fb78ecf +NONCE: af11369ee342454cddb8db62 +IN: c01130afd7d3f4276dcfc1ffaf4bb636a85d18e0778df6c6791b6edb92a617894b84cffef6556c834a4800b336dc295e80b699b28cf478a01c54052ab0d0d4208e1865edd6906e3a263862c05f033668d7eb5b42baf36c702d102a6a5c723974e63bec848c89d16584f0d1ec429c87686b1ccffd7626e0a83f9c471cb615541ccb02cb58d10e63ffef171f1affca492ace4d39fbf33bb5126c575963e6b6ef9fd2ee4d6efcae5afe422bbfd9c3dc22b6b47cab8dc04127ff93b016e0f92f5d8518d5bd3bc6edd45e0397440f1a4a0c7c9c2773c0a0cd3b890effb010dbcc00237dbed1177b86bf60913309bfda9376b4192da59a360afc5bcfaf8be16ea8313de97b417aaddceadc63a1c3a355693616413ed4101ad68f6e6aaa99c839dd2a9ff536 +AD: 18e3195358bae4ccf43ff8daa34902fe48f99fc1371d34060aaa442a43016a1d756f795fa5c9c4a828525554571e18c27134f46094790dd1e68471ee40c17bfa02f175b2c2f7f2aef20f00e4d71926560b58f015de19c871d808acdd341675d8fc19d1e6d4028e1e8926df500c4685c14729c6a056898cf919bf3ae429fa3ca8746495716d78c9a8f2ecde596f985b1c25ad0e73aa305a86259319176b4c4f3bb231fdaa478a856f46416ddb10a14ed23c96dcb86f5bea3114568a44d8fc6ff4bb47fd0e2538b70d964842910a682e7bc7c7263249832c21b7083a1e8b143828de0f3dea8b404cbd82efb19a11e4d60aeef13abd86621ccbc3d8f220715730eabbe04a6bf0e11a4f78cd2c4369ce2447a76f4fa48ef8d322a8a28a67039c24c4bfbf +CT: 6beeb306c71318cedabe3877ec916ce2074b2c3f1df887cc3a3e8019c10d353854b6b65c947359138d5decc62a42d50921dc8f6cf63a16062af47aa8cd50d0b2dcbc3300ba0d7d069a5e4b4fe03bbf7062c6001e276be116fdd00d15a6399d1b0db71c58f396f8bc7e51c2b1f47430d4ebd6c5d05328b29aa79bcb26927ea5a40c82715aa0e36cc83ca6d250812c1305c02ed4291a25762cd709cb3d808031b5f918ce253f622c1afcb83c43707edc493d18ec6f0dba4353a1cde7184db65654088fa13baf45f7643f0dfedf4058e6095156b791ed30827c556a7721658314356e7a3f3c62cd62fe938b008cda56ceca71442fa0ffeb78b13c5847a3ee9668bcd2a01c753bd797c240378505d1e8f2b8905428b23bf589de9af390f94f21630d1826 +TAG: df5a21a399354b2b3346a9eb6820b81f + +KEY: 06a4c6a8aa189134f5784a525d46ff10 +NONCE: 0f765d3893af99f5c3e6d9e1 +IN: 706b754094869313523493089e591d34868b708cbde9bd8b42cba8175d1fdb6a8769bb9ec156d44bcb8f9cbf2685a0dc18b5a802dcf7a12570bb9042a0aa53dfb19af8c0f13763f388d9626a480d6d435dd90fbdbb4292d9015a5633252aa0583498d6f7ec54460d8589c1d6a6d16a349d10ec6070e1cc52e5fb996f810d333675a7130e4f3db9f4db0e3fd3541d32e0b2efbd40ba70cd59295bc8d08481f0f137832b01bac1778ffd7450376e174067b3ec23d0495cbf936bdc176cabc3f42e2991947a4fa87dd8343c32fa3d7ac0e2d22660a0c128a00e1b51a8742fdb2aff44540e39e588c5920ea16293aaa522513c944d3b77f3a0e90bd9105319c170886202e336893d100b0a25aa609a49a8255f78233561f7b88256386d1c3c002c3ee68f2775585c65 +AD: 18e2ed6d500b176e49f7e1b5074c0b7dbfdefdf00a63d9fa2fea8c5e78a1c4ae00f17b23442933543ac864097629e112a099f3dce6d5beb1e3f3c8e19522c6b8f615cbe23444bc91a802edf8a08995a55125da805ebb073fd89863996ef708f7293069a744ad95db8c17cbcfedc331119e85020df8852d74b8092fd38ad424f3da41b4775beac19536ed801ac1069925b12303d8ad2c52c36ca5b4ec95e96f02ebc5725ee6cdc099e666d9055b789e39ded77a8fdca0fe2d94b8039be55b6a75209cbee4fc7864957402b50427db71bc75a0b1e3d2ed6ea20f12a980c5ee916067d0dde7d686570d075da4df7088fe5dccf0d440064a96998da6f318b603d513104c723f27484780bdad586ee358d821b480f9569e4dbdd1a45ab9056f8d8e5a879789a0d65338 +CT: 5f3627bd53f8da0bbe6f3c9246d6f96fe9abb91cdecf66ddd42f833d98f4d4634c2e1e1ad4088c84c22191bdb9d99ef227320e455dd112c4a9e9cca95724fcc9ae024ed12bf60a802d0b87b99d9bf22590786567c2962171d2b05bec9754c627608e9eba7bccc70540aa4da72e1e04b26d8f968b10230f707501c0091a8ac118f86e87aae1ac00257aee29c3345bd3839154977acd378fc1b2197f5c1fd8e12262f9c2974fb92dc481eeb51aadd44a8851f61b93a84ba57f2870df0423d289bfdcfe634f9ecb7d7c6110a95b49418a2dd6663377690275c205b3efa79a0a77c92567fb429d8ee437312a39df7516dc238f7b9414938223d7ec24d256d3fb3a5954a7c75dbd79486d49ba6bb38a7ccce0f58700260b71319adf98ab8684e34913abe2d9d97193e2 +TAG: e690e89af39ff367f5d40a1b7c7ccd4f + +KEY: 31323334353637383930313233343536 +NONCE: 31323334353637383930313233343536 +IN: 48656c6c6f2c20576f726c64 +AD: +CT: cec189d0e8419b90fb16d555 +TAG: 32893832a8d609224d77c2e56a922282 + +# AES GCM test vectors from http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-spec.pdf + +KEY: 00000000000000000000000000000000 +NONCE: 000000000000000000000000 +IN: "" +CT: "" +AD: "" +TAG: 58e2fccefa7e3061367f1d57a4e7455a + +KEY: 00000000000000000000000000000000 +NONCE: 000000000000000000000000 +IN: 00000000000000000000000000000000 +CT: 0388dace60b6a392f328c2b971b2fe78 +AD: "" +TAG: ab6e47d42cec13bdf53a67b21257bddf + +KEY: feffe9928665731c6d6a8f9467308308 +NONCE: cafebabefacedbaddecaf888 +IN: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255 +CT: 42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091473f5985 +AD: "" +TAG: 4d5c2af327cd64a62cf35abd2ba6fab4 + +KEY: feffe9928665731c6d6a8f9467308308 +NONCE: cafebabefacedbaddecaf888 +IN: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 +CT: 42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091 +AD: feedfacedeadbeeffeedfacedeadbeefabaddad2 +TAG: 5bc94fbc3221a5db94fae95ae7121a47 + +KEY: feffe9928665731c6d6a8f9467308308 +NONCE: cafebabefacedbad +IN: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 +CT: 61353b4c2806934a777ff51fa22a4755699b2a714fcdc6f83766e5f97b6c742373806900e49f24b22b097544d4896b424989b5e1ebac0f07c23f4598 +AD: feedfacedeadbeeffeedfacedeadbeefabaddad2 +TAG: 3612d2e79e3b0785561be14aaca2fccb + +KEY: feffe9928665731c6d6a8f9467308308 +NONCE: 9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b +IN: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 +CT: 8ce24998625615b603a033aca13fb894be9112a5c3a211a8ba262a3cca7e2ca701e4a9a4fba43c90ccdcb281d48c7c6fd62875d2aca417034c34aee5 +AD: feedfacedeadbeeffeedfacedeadbeefabaddad2 +TAG: 619cc5aefffe0bfa462af43c1699d050 + +# local add-ons, primarily streaming ghash tests + +# 128 bytes AD +KEY: 00000000000000000000000000000000 +NONCE: 000000000000000000000000 +IN: "" +CT: "" +AD: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad +TAG: 5fea793a2d6f974d37e68e0cb8ff9492 + +# 48 bytes plaintext +KEY: 00000000000000000000000000000000 +NONCE: 000000000000000000000000 +IN: 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +CT: 0388dace60b6a392f328c2b971b2fe78f795aaab494b5923f7fd89ff948bc1e0200211214e7394da2089b6acd093abe0 +AD: "" +TAG: 9dd0a376b08e40eb00c35f29f9ea61a4 + +# 80 bytes plaintext +KEY: 00000000000000000000000000000000 +NONCE: 000000000000000000000000 +IN: 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +CT: 0388dace60b6a392f328c2b971b2fe78f795aaab494b5923f7fd89ff948bc1e0200211214e7394da2089b6acd093abe0c94da219118e297d7b7ebcbcc9c388f28ade7d85a8ee35616f7124a9d5270291 +AD: "" +TAG: 98885a3a22bd4742fe7b72172193b163 + +# 128 bytes plaintext +KEY: 00000000000000000000000000000000 +NONCE: 000000000000000000000000 +IN: 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +CT: 0388dace60b6a392f328c2b971b2fe78f795aaab494b5923f7fd89ff948bc1e0200211214e7394da2089b6acd093abe0c94da219118e297d7b7ebcbcc9c388f28ade7d85a8ee35616f7124a9d527029195b84d1b96c690ff2f2de30bf2ec89e00253786e126504f0dab90c48a30321de3345e6b0461e7c9e6c6b7afedde83f40 +AD: "" +TAG: cac45f60e31efd3b5a43b98a22ce1aa1 + +# 192 bytes plaintext, iv is chosen so that initial counter LSB is 0xFF +KEY: 00000000000000000000000000000000 +NONCE: ffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +IN: 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +CT: 56b3373ca9ef6e4a2b64fe1e9a17b61425f10d47a75a5fce13efc6bc784af24f4141bdd48cf7c770887afd573cca5418a9aeffcd7c5ceddfc6a78397b9a85b499da558257267caab2ad0b23ca476a53cb17fb41c4b8b475cb4f3f7165094c229c9e8c4dc0a2a5ff1903e501511221376a1cdb8364c5061a20cae74bc4acd76ceb0abc9fd3217ef9f8c90be402ddf6d8697f4f880dff15bfb7a6b28241ec8fe183c2d59e3f9dfff653c7126f0acb9e64211f42bae12af462b1070bef1ab5e3606 +AD: "" +TAG: 566f8ef683078bfdeeffa869d751a017 + +# 288 bytes plaintext, iv is chosen so that initial counter LSB is 0xFF +KEY: 00000000000000000000000000000000 +NONCE: ffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +IN: 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +CT: 56b3373ca9ef6e4a2b64fe1e9a17b61425f10d47a75a5fce13efc6bc784af24f4141bdd48cf7c770887afd573cca5418a9aeffcd7c5ceddfc6a78397b9a85b499da558257267caab2ad0b23ca476a53cb17fb41c4b8b475cb4f3f7165094c229c9e8c4dc0a2a5ff1903e501511221376a1cdb8364c5061a20cae74bc4acd76ceb0abc9fd3217ef9f8c90be402ddf6d8697f4f880dff15bfb7a6b28241ec8fe183c2d59e3f9dfff653c7126f0acb9e64211f42bae12af462b1070bef1ab5e3606872ca10dee15b3249b1a1b958f23134c4bccb7d03200bce420a2f8eb66dcf3644d1423c1b5699003c13ecef4bf38a3b60eedc34033bac1902783dc6d89e2e774188a439c7ebcc0672dbda4ddcfb2794613b0be41315ef778708a70ee7d75165c +AD: "" +TAG: 8b307f6b33286d0ab026a9ed3fe1e85f + +# 80 bytes plaintext, submitted by Intel +KEY: 843ffcf5d2b72694d19ed01d01249412 +NONCE: dbcca32ebf9b804617c3aa9e +IN: 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f +AD: 00000000000000000000000000000000101112131415161718191a1b1c1d1e1f +CT: 6268c6fa2a80b2d137467f092f657ac04d89be2beaa623d61b5a868c8f03ff95d3dcee23ad2f1ab3a6c80eaf4b140eb05de3457f0fbc111a6b43d0763aa422a3013cf1dc37fe417d1fbfc449b75d4cc5 +TAG: 3b629ccfbc1119b7319e1dce2cd6fd6d diff --git a/external/boringssl/crypto/cipher/test/aes_128_key_wrap_tests.txt b/external/boringssl/crypto/cipher/test/aes_128_key_wrap_tests.txt new file mode 100644 index 0000000000..561ec90b25 --- /dev/null +++ b/external/boringssl/crypto/cipher/test/aes_128_key_wrap_tests.txt @@ -0,0 +1,9 @@ +# These test vectors have been taken from +# http://csrc.nist.gov/groups/ST/toolkit/documents/kms/key-wrap.pdf + +KEY: 000102030405060708090A0B0C0D0E0F +NONCE: +IN: 00112233445566778899AABBCCDDEEFF +AD: +CT: 1FA68B0A8112B447AEF34BD8FB5A7B82 +TAG: 9D3E862371D2CFE5 diff --git a/external/boringssl/crypto/cipher/test/aes_256_cbc_sha1_ssl3_tests.txt.REMOVED.git-id b/external/boringssl/crypto/cipher/test/aes_256_cbc_sha1_ssl3_tests.txt.REMOVED.git-id new file mode 100644 index 0000000000..4fd75e2bc6 --- /dev/null +++ b/external/boringssl/crypto/cipher/test/aes_256_cbc_sha1_ssl3_tests.txt.REMOVED.git-id @@ -0,0 +1 @@ +a6441689e7569d2a8b8d02bad02ee7e4281a7d3d \ No newline at end of file diff --git a/external/boringssl/crypto/cipher/test/aes_256_cbc_sha1_tls_implicit_iv_tests.txt.REMOVED.git-id b/external/boringssl/crypto/cipher/test/aes_256_cbc_sha1_tls_implicit_iv_tests.txt.REMOVED.git-id new file mode 100644 index 0000000000..5f2fe28ff5 --- /dev/null +++ b/external/boringssl/crypto/cipher/test/aes_256_cbc_sha1_tls_implicit_iv_tests.txt.REMOVED.git-id @@ -0,0 +1 @@ +06ce309b334fb4ddaefb19c1c33fdefbece01a52 \ No newline at end of file diff --git a/external/boringssl/crypto/cipher/test/aes_256_cbc_sha1_tls_tests.txt.REMOVED.git-id b/external/boringssl/crypto/cipher/test/aes_256_cbc_sha1_tls_tests.txt.REMOVED.git-id new file mode 100644 index 0000000000..ae8bb4ec98 --- /dev/null +++ b/external/boringssl/crypto/cipher/test/aes_256_cbc_sha1_tls_tests.txt.REMOVED.git-id @@ -0,0 +1 @@ +9cbeb39eedee59a9a40744c2b599daeabf0e2d59 \ No newline at end of file diff --git a/external/boringssl/crypto/cipher/test/aes_256_cbc_sha256_tls_tests.txt.REMOVED.git-id b/external/boringssl/crypto/cipher/test/aes_256_cbc_sha256_tls_tests.txt.REMOVED.git-id new file mode 100644 index 0000000000..880b265be7 --- /dev/null +++ b/external/boringssl/crypto/cipher/test/aes_256_cbc_sha256_tls_tests.txt.REMOVED.git-id @@ -0,0 +1 @@ +c61427662ba032d0a1797b841affa88ce57bb249 \ No newline at end of file diff --git a/external/boringssl/crypto/cipher/test/aes_256_cbc_sha384_tls_tests.txt.REMOVED.git-id b/external/boringssl/crypto/cipher/test/aes_256_cbc_sha384_tls_tests.txt.REMOVED.git-id new file mode 100644 index 0000000000..a0d2482313 --- /dev/null +++ b/external/boringssl/crypto/cipher/test/aes_256_cbc_sha384_tls_tests.txt.REMOVED.git-id @@ -0,0 +1 @@ +9f38bb012cdf08a50f1ba070f0b8815217752184 \ No newline at end of file diff --git a/external/boringssl/crypto/cipher/test/aes_256_ctr_hmac_sha256.txt b/external/boringssl/crypto/cipher/test/aes_256_ctr_hmac_sha256.txt new file mode 100644 index 0000000000..2a72e1c9d4 --- /dev/null +++ b/external/boringssl/crypto/cipher/test/aes_256_ctr_hmac_sha256.txt @@ -0,0 +1,336 @@ +KEY: a5060fecb0a738d8ff6dd50009a757c6e58db73228534d03f32c26baa1c209f402c3e03a6947c1d9421d63ce43f6df26d30ce783f5ed0d6b88edd389d9f92d8d +NONCE: b52227e92203630a79ec7f5c +IN: +AD: +CT: +TAG: e61a28f5df7061b4236834d2034d2b62cb63c660b7de696c26b345e66b34d222 + +KEY: d676047046bd5be9263ae39caaa0f688abb1bc67c083658894da6aeeff80b6d58ffc7ca1a1c88f49e629bf5544b2cc7669367202b158fce83fc4a4826dd90a7c +NONCE: eabef87a00fd99ebb6ed6d25 +IN: +AD: 83 +CT: +TAG: 473cf728899cd5fdd54f18d6f934c3901f7ca118fc5ab2cbb837feefa7852a67 + +KEY: 5eaef3b8e068fbb652bd37df4dfad6490095642cd49761a35476dffc2b5b5f75236d0351d96a9028660788893323a777ea8a2ac88bb5e500b334af02b1c2a648 +NONCE: 34d049342b9db5ffa039eac0 +IN: +AD: 7578949699d44dec9188a7f7e14b0a23637cddb9107dbb1f8e2a968aad0443356d7eeceff4316ba7b2e8fe +CT: +TAG: 4d2612c21357638bada9290d2a272f10fb5f070337bf87bae396a1e7253633ae + +KEY: eb7b3d7eeb5f26010915a36837dc83da2bad07eba714566584bf1ce62fa9b61210b0ead7182bc28c8f0427699bf04786583fa32f3c3a8a6582cdc254930043bc +NONCE: 3bee5ebcdfc72f4ab0023211 +IN: +AD: efecb57e79a326c6b2ce0ae74d7656992a005fbb8da5a55b9595fc5348a5489ee2e69541ec0e8a727a560625 +CT: +TAG: f457db1e274adabe5fc898fb1eb7c4a5a8e9a2b66f964d0958aa058c1f9e15ba + +KEY: 1c1abffa8a2667a8c1ab347860528162d316d58e3966050dc140fd360e6ff7c557520a8982aae97c5db5495d8951eaa485e1cac4cd8f448a13d071d759885474 +NONCE: 4fdce4e59bfdf5d9b57c78e9 +IN: +AD: 55125cefc919379b3b4b2a24ee1794f44ac66fd99b8b68f98d4abd45ba50a5b76e5375d08abe3b8b8d3c576bc8 +CT: +TAG: c021d2c73737e54ac6e7f61f9bb44818e5bdbf8d81d43842fd25a535790fafba + +KEY: 366cf53bc185473acf62610b74231e53aace84e9c5d6fbf71fc24db4f42956065d3eec01ecc72a6c89266565ff530075f4532c860e3192e866b41aee98c5c42a +NONCE: 9ff54bd7b10f4fdfd8db76c7 +IN: +AD: 853ef59ae873bf0bfe1465e9dd8c2cddfcf123d213ba4f599d984e4ea69d3c85a23508ec7941ca740a9157ca2a788e9b519291240b307d6c5a8c6860a96b4be698659d19e31ab0ac7ae6ba31dcd609c1db67ad580fe4422e42d368c3e93a56f2a087b0d587188462310c2ebe58ecfcf7178412223808eeb2eda76446168730fe +CT: +TAG: 12d869dc4bd4ac4ce9ed643cccda9e11a1ade65c76f7c1535fa4ec2bcc5eb4c3 + +KEY: 147b41369bed390f0a9561586fd975474e3b3bbf7f7ebb7a35e5cc43b516c044dce93e154ac790a109709ac5299bb17b709a913d33fd57ebfef2b48ed66393b3 +NONCE: 85b81732d2863b41d2551763 +IN: 73 +AD: +CT: bc +TAG: 47fd81f6eed8d3c66afe06d788ffe40717847785f4b4c617d75a11171690a60c + +KEY: 9bf35c1194659c1da634eab6707c55b853c8f61d087187162e926adbae02f8bd4d15bae5b05865d0e2236d64715fc39f32e4e3679a0309396c37eab13d1c637b +NONCE: 8da14a98ee741a5fce0de732 +IN: 10 +AD: 8e +CT: 17 +TAG: b76af41002a946af4947f98f42a873b7da0871f482990a70bda8f005274ca179 + +KEY: 0befac10caec674c9f23676d121f065dbcc8c91852dd5eb4e80c41076995a2138077592fec665954d21fd6787234d32d3d54bf9c220cf2bf018b374bde29926e +NONCE: a96bfb49f3a136840a0e32ff +IN: 59 +AD: 236adab55e1bb8a8db384c01bb2afd30ff35da71f955fb217b8305a45ee075e7f8d863d4c0e5dbe36e297c +CT: ac +TAG: 7bb634357e0835b02a0642352a834ff6598c2ded1af8e8ab60b9ef0641fe863d + +KEY: acc672aecf6f10119ee77070abbc2b4fade7e910efd1f93a5716161f88606469a49df05b40332b390d3ac289abfdf6bf7c37c033b1671082922d939139de0d42 +NONCE: af0f57b55f1a73794b3ce5cc +IN: ee +AD: f385a50ef027e532635878a4df0deb23369774be47c42f17cbd44925b668f628338ea5f8256c5ad8219c13cf +CT: 71 +TAG: 13a5296075ef23216c2f2e83b940d24e8e1e6a01967af96599360f11499ac0a6 + +KEY: 6195ef5ce3ee01188c48b04ce7a28b3ddd04b78711a6d1233121fc8ec3db3a7a0e496d1b6a416675b1e666b9a3df167efb8ade29e4f22fc77111f32ba8bd1ec2 +NONCE: 092070b2f8b65fcfe646f6bc +IN: 26 +AD: 98526dba4437d88f657c0b7ce2a2be44ef4951711a40747a7d14b195e4c0eae97247256bba7dbd93d6a8f738c1 +CT: 83 +TAG: b6aad3f91a26a38245031d6a7eb97be0d386939d4536b2a27c90a2ddb891de73 + +KEY: 40335487f9958dfc00b76ff06dfec162ae5c6be4e26918bd12e3f21760cb0bd364521a11f5bfae11dee989627525ab5295ee404bce476c280d13d238dea1bd40 +NONCE: ecf77c7c827a34efd8cdf79d +IN: 34 +AD: f6e661254bf235c7d5b8ee330cb754087480dec5fe4c31dee65d1ab4479642101404bb563522937fb2e41d3aa8a4d269a222e6e0bcfd07ec4b29c1185f99fff7cb5bd2ca8c5b38742270e586c8db19138b446833f2ee07a11dae5b6a1a4c28657f3380e84bffe1bafeccad57d9cfea3da7f728119ec5bb18b79e002954f4379c +CT: 5c +TAG: f3420d4cecae2c1ad79d977abbe408045bd87525c0da2b93e0af3e6c53ba7d74 + +KEY: bf32ef44c7ca9851f397e70df736d7e0e6243cfd875ebb81d76ad7612dbcfd084cab6b0d67c6a6e8b567c93fd0c3abb78ae121fdb3051a62ccfa045692d3453c +NONCE: 46e0cc64d6e431c1efc2bd2d +IN: 959348a8ad6912d7d6c8eae52f19b1 +AD: +CT: 55e8cb6fd958f18b3c19451c5c79a7 +TAG: af09194071cb0ed4488d27e79700f938ce77386e5d772f9853b17b719f2b1ebc + +KEY: a6b5b8b051edf5cea0353ead88ea887fab048ef32f8303275e93d8f926da0d4b0e34b9447cf44fa70c24c9ab964380065398336bbb20be167fc6cd5e591ef50e +NONCE: 371363612c4675a2e59ebd39 +IN: 443d16621b0cf9a12552216f9558ca +AD: 32 +CT: b7f432eeda8e4b8a25f0445f17ca7c +TAG: 649934922826febab4d59dfb52a7558e6d30d56e273602b98f3c55fd8e24f4da + +KEY: 075b75434269a3fcc57922ee8cc55b5bbe1b90516a3b71838ade73d41ed1d1f33ae1e0e86f88f6ed7e091cae3ccb05144b3ef239831554d6e79ff97c4d8f150e +NONCE: 754d5c4ccbfb291133859de3 +IN: 62a151add825077c59459fbf82b708 +AD: c8db27487de71124a95eb6359270a8363908159200333b46ee74e2709b308878779686bd43c24e9ecabfc3 +CT: 2ffb9a9f65c9fe3daad13768ab56bf +TAG: 4430a90fed7d4b5b2adf5a60d6854956be4feef497781ac7d864a04259e99516 + +KEY: e787fdeca1095f2f2760a1c5e0f302e07d6b08de39ce31fe6a0db2f76e4626eb0968768ae04d37082c114573c307699707630b8c7ceef60abe3b7831d2adcd6e +NONCE: 9dc9bcfe8b4e2ea059e349bb +IN: 3ad57105144e544f95b82d485f80bb +AD: 96bce5dcaf4a90f6638a7e30cfd840a1e8dbc60cb70ab9592803f8799f909cafe71a83c2d884e1e289cc61e7 +CT: e504109cdbf57b0e8a87080379e00d +TAG: 1798a64b5261761ecd88f36eaf7f86ed3db62100aed20dc6e337bc93c459487e + +KEY: b43ab650bdd201cf05e0436afe89ac54867383f04c5ed2faea5db8e6784c720d905234f1f5443c550ca14edd8d697fa2d9e288aa58c9a337b30e6d41cfa56545 +NONCE: 4e3dd3efe527902b9de45a5f +IN: e386663e249b241fb8249cfec33ac2 +AD: 3cf7a396e1bd034ea77a54ffca789f206f94263d90d98bf3e69cb42205fc5c95cfbd0481b0ec490ea447299159 +CT: 94aacf00092723e778d25ba78e9d27 +TAG: bd5fcf90b9532e7abfa858aed90d5170f08edcdd28ff2c673e0ab45b8c0a0f39 + +KEY: b22a7c5bb38715025cd59cc0feed9ad8e51101200000168052b294fb1ead545a517dee636a7acd22b8283afb33d30adbe02c1c8557715eea7147f3d98a97cbb9 +NONCE: 3b4244c9ad9fedd3f10fdf7a +IN: da79e1ed131856cec3250fde7bda4b +AD: 4b77472ade3f06500169405b86a793d63cfa58f57bde0dd706f369b391142c2fa8a3e6345ccf0a9c29b2182f578e22f55c576f155a05be5e81997fbe06410034ecddd871e5ed94b5eeffc6dbd90a8e66449da01f8ef47d28a4a4bd253ffc427f868867c73b5c709b01732bd8035b1a23ff0a903def1eb136fc90d8b3c8279769 +CT: 5d8ad7abc047bfdf9d9cd0b0aaa53e +TAG: 41d050d518d0e51ce16bc2920aa6c76eb8eabd4ed76373c59618c6354885f47a + +KEY: 04b3fd8126d65f851f47b3dea22cd6e32506f21effaa3e29820ac7825e01b51c5a2816f0298154f2d8addefa2fdc34c0635d4d6b80ad23eb320c4d4f2aa1de1c +NONCE: fae1b1da40471dbdcec64d4e +IN: 509f116ef7435b0640cf141d5b958aaf +AD: +CT: ecf553eba80e6dd1fae2eab24d772a89 +TAG: 11473566e80cff5d7421f65949c34301f34de378e91ad50928cf2caeadc466d4 + +KEY: 413d154dadc7d8869e9e0f24b3320019a04b7a37620dd9e7aa40b5c08d70dea03c12ccf7faad7009e972680e81544b647650c6ff033f56e5bcdac9a35bd7f804 +NONCE: 6a4404adae3f4a7bd2bef95c +IN: 3539fe02b75981fad4f8762772b3c11f +AD: eb +CT: 3f8a96905609a4ef1a95fdb87337503d +TAG: 8ee076fd624d90e1f6336a92165e80408ca6f0e165b201547d351177c95e8d51 + +KEY: ddc10df673e720c00f28fdfb69f1b8fba99696f23b6f29704a0114444cc0c8a6c8606e8d37fa95aabfd65b29c655678fcec50966c8758a3fb15332a1854a8eac +NONCE: 06331613842b4af86c13f8a2 +IN: 55d74bcfc3d1cfc716c6e6b7153c6369 +AD: acc264344ae79959f9dd5130664273ba6f345c3fc7bc33c6c1ce33312bfbd5f181a3c7a24f15e7acf72ccf +CT: 20650d9e846eb42854692d438b21d5e8 +TAG: 973857523e7ff600cf9bcfcc98403b34ab38d939a6d76716beac42678ca5f5bd + +KEY: be0c884db54cf761fc24ff3dd572362910dedacece5e1d93a916df277f923f78e7dcd908e60beb0043503c5b4877a9d962a7de37cacc7387a7553949b52894ec +NONCE: 3f027a93e2716668c7634195 +IN: 1ba8f3a87ac6738167aac1491b602ddd +AD: d06dd1b9360a68afa3de5d239b6d91d212c5c555567545a4f133bf5a3b0f26addb9379e1cc1cd690cd427c57 +CT: 3596cc50ae72db932dd83bbc8661641d +TAG: 44a1834b1587d0f88e34137dcebbca059dfb8f65ddab18f338a8a30152167be0 + +KEY: 2ee848726730c64332877a4f88ad7fb241a73b71fbee8eeb4d9d6485855ea32b487e03968e1a7b9e8ac8ab7fbd84257efbce0aa207aeefa67302d5847e0d9c05 +NONCE: 526b0a79b6359d133ad51011 +IN: a0c0477e8a9ebfd275b674ed33230d42 +AD: ded2f0f3f28aea28b17aa58d4b906c6a9b3078f97ffe95b7e161b0c3dbf66879bea7603a046da4945c802ac8b3 +CT: b1691c8275f12f7d9af85e71dde9dd5d +TAG: 65a5742dcbc49295c4805387e0a15f986ae47e51add9389dfabb6468a6e83013 + +KEY: f4a7c0e29ff510c034778e47bb30a468a92140a707936d381b1554d421af107c578e74c53ea08c7f7d93cf67612061359ae458408a9c79250f776ca4192016c0 +NONCE: 025bc10dc99346c4d0766a7d +IN: d449a2e812429beb5c466d344f5b5eec +AD: 304dbf9a59bfd33b777d8dec9dddce4c365e72aed851210eb964c1da18119bd13248266a67408e88ac2eadfc54def0fb57f23743d376b11293377565d253d2bffe0309f2946cb78d4e9536dde4691fe1eef9ce2dc916a773d06b42fe2b014e7974d4aeffce25a0902c9b44265e5d6d26809b5f24875e80cc13f1f8872b04a237 +CT: f366e7b66683f52586e1c363c15b7fb1 +TAG: e0e1bb733471f150ddce1b83f3fc2d88589d286ca052574b7f0735bb598362d2 + +KEY: eb78ea626b219e12937057155884547cb7578718f569dc8f2b370c0fea80e7f0d0f5cb590f0b7341d20c775bcd6a3c818e23b6cea949cf99eb94a23a81cd2249 +NONCE: 75a10f16d429b809cf12b9ef +IN: 6b0203316e8108ff01b12df91ba6644382 +AD: +CT: 7ee07054f76471115be159259340c24391 +TAG: ab970669d1603767d588a93cf215673ad307244f9179f46fca56e97f64a5fbac + +KEY: 3221167926be262b7bd0591f56be6bf030365d45ab84a93a94ea41a5e07735b17245ad43787e8791e7ceaa0472b562ed17e3b609c66c868c9b08304c8bb328b1 +NONCE: a94d8417d2bb0323bcfd354d +IN: cec81bac7b85c441b6261163d67921eb49 +AD: dd +CT: ddd8860fa9e2e8087db30c9da1ec9f9487 +TAG: 26a3b9bc4d4cd802cc22e7647a19fc2a5092293c9f5b1c84bdab7245a6d8f4ab + +KEY: 4b16e2d62294f76cd2a6c8e0928279d9de40f0b169ef9465738cbfa064c520128ee89cf657da27e4e532d8c4709d992970bfc9daab2f31b3a67e53200d3d6710 +NONCE: e746d498b9031007332447f7 +IN: 16841e3fc1f53990d33f7ba525dab121a0 +AD: a785917bc9f3aaadfd170abe83bb30c0c5d595fc8b491d983131aeab1a7b8d8771f1a963c251976152dd63 +CT: 6bcf5eac15ef74cb8a706856f62eb5e8c7 +TAG: 9dc84b06e8ec8921be4bc7762e8cebb61a95ac5660022520f9438e8f77b45796 + +KEY: ff2f5944111226df1d9a300533d3e871694fe15a418b2090265cd8c0111b249dfb7ee86bd9228f7ea5d89d8afcf10bf69942ee4c29bfa8409b63c00c2213629e +NONCE: 477060f0c61555873bbeb225 +IN: f091891c43e2374c2755a88a11b04beb4a +AD: f1323fd1ac4de9719dc5966dae45dd7b8ddbee3f8da4f4f4d5f25d06bdb8ebf57328dde76d0bdb9bdc5f6b12 +CT: e0d96f6f3ed0493a289d4c3b79238b9ed6 +TAG: 71276c05b52bab0063108dbf4e8ff57cf3e15079055a309d725f14bb86671ce1 + +KEY: 1ce841bcf2ad8accc458a2d94774c3aa53a99e7dbec587376212101303ca2b42272a23fe28514be190b82e503e7772a3713800f4360fdb767e85ea5e1f7b8eca +NONCE: a2f8afc5ceb5382882907630 +IN: 620fece1e843d1d0b5c5a541a6f615a81d +AD: ded910647464d0fbb0a5d93ffb9839de3360c675179c5991ad3470285d79071436025111153628c563ad1b595e +CT: 34431c3422e009373c50f3ee6c5b3fcc2d +TAG: 6e4e8a3967307f47e233a36ce05a4826a698fada2ac19543bab7c9ac4f79451b + +KEY: 6bafd28a32690851fda667eb2d3c5993f13df52b2e97630527f26c498fd5019f26177a78f27c0c41616d2a4a73757fcaf9cd92a7da8498f90315d41e7479d90a +NONCE: 75166c506c8e1d10da4da8b9 +IN: 697bea4d6eed5e6ed243cf01cc79bfd3a5 +AD: c0fa663961c3f7e09a8c7bc73e252a232977dd6c9483f02067b34fe695f341d05338ea2002952439ce08295ee5c12f38dafffeb5716908d3f1d4bfbf9eb0e4077bf8e534f19568ed04fca3bbff95da9088cb939f7a20cc97cc0994f9308e184219bf12c8af0d66df436c296ad39832d661b88c98cbb168c751719ac1383c9124 +CT: 8f37885b9602725385fd9a244ab2a156ea +TAG: 7fa5cedd330887900f4a44d098e04d5eca16cf94e21f897fa54b0fc116b711b6 + +KEY: 815786c7744d15afe1d6ab452cb6696fead8b88269ba3eb35c458f6248bad77b404acc744ebb74612c4f97deaccb99a7bcc6ad41917d61057c05b30c581dc4a0 +NONCE: 12342e4704f02336ebfc91df +IN: 7f15e696b49ae5104ced5bebbf58a9d8ddcfaf46ddce9df88fe0d58a2f8546feeb83b975c66e4dafddb7fd9d17e80127e70af06b3b8b13c3390f1f50a227e7 +AD: +CT: 22e7c5d54a7b622c47a9edb77cfe7c094e500b0ef9595bc346de736e0088e5934dc07160aea34f24d3ab21440878213d28059551cbfdaa418af40d344674f7 +TAG: 8c271ea5c15aa771c900388267efb2f435f001c2e83f4ec297e77c608de2d579 + +KEY: 66d87d2b18e46257476456a1f87123424477decf196b88b09acfd3ca74bdebef4c98f1b93803098a141e0acc3ce8eede065417a0c1eda9b4614558d2383762b6 +NONCE: 1ec0ca1d3b09ef186ac4bb1a +IN: cbb59e14098c2a8ab7e84ace913515c74e056e0fb272c7b88d0dddfb62e395afb695647d97d1071eb09cc1e1776b609fceaf4e30e92640379bb8f0e762ca9c +AD: ec +CT: 832804b8003b0ca1b4eff1dc4da6f6a9649e5a582854bb72cd74357476bf38d81ea3bc8ac0463f21fe37683bcbe07360d0ec2d7ab90b588adf669099303ac1 +TAG: 9fecafc768fca71ffe7d640dbb7a052d97d6c8e2fc86001d71feaf284ab609f0 + +KEY: fbff97085351f4500e73190ac139dd3ac91e268042b5926b57e0394c750b10348b47641d195d5fb5b0846256ab229f102538b81e209db5d93b4d55f30c453d9c +NONCE: d4868c918de2af7d3e3f57d3 +IN: 4f14aa5a680d66ae15ce0ce4739888f64d827def862572f9a6cd620badbe4ee9d75f4f9bc1f73d409f519a657f53a50d50e68e22f33a8ef5aa08b1212889e5 +AD: c41253e96696a948ce500030af27086842aacb79c04cc02a42b858a65c630065a5292bb9b2e69ea5fe5a7a +CT: 08596ac0550574e352edc13d7e390d8fd0a57406dd61e1543066b4aa0ea06670f356e26ada0d6c61c1e41de1b4fd7a251c961fae44b23523ce227eec99a338 +TAG: 72f58de3e6697c8419ef518748fe0bb3cb930907c71b6d682c5e61068206d991 + +KEY: c78c550aba82b571d39ce21d6ecf5e5f7c2a7bf921c6162c64ec1fdff4d0b8c41bfcea0e2486cc86b9ed9e9ceb73c4ec228a2ecbcfa0379174e76475cc21ae31 +NONCE: b5adf4de19980a71cb8ae8e6 +IN: 3d5e43ce95ff9d7f797f27b904c07291a35678fe76a9c57f0c0cba724f38acbb22c6c185db864a2a17b7ef2d67a04810ee5a45fd5a4e28a15a1ae16971451d +AD: b5eeb9a18d436ada7bd5601944784f50fb0a989397b5c781a2cdf29337315dc7664f3c1cbf17f37fd0cc8b30 +CT: f91f1f20d06ad4480ff233480228994cfa052f9bf3038d06d997d31eb68bffa4960341b93eb5ed2260341e6816519c47bf231db2a41ad8a9719f4de6a33de5 +TAG: 6e5eabda421961e26dc17a7e1f750425235df4eaf9a97934c1e1b4439fc22791 + +KEY: 17b90dec44546d9dbc489e55a01f2cc64452a9b0e50506a8ad7c81bc6fb21328285cafed901a7204048866ff3bd543003fdcbeb3e9e2f3d580f9062362879633 +NONCE: f0c0cb247d210031f9b233bc +IN: 75b9b524cbfd1287259da116f536aff56112a406f069aa08f545b5372d45b66d7a5d05e02728c4bc2c779609dfe251386f78c5f48b9dad90b363d324826cd6 +AD: 8a604a9b06ad595ce0b9ad1644a596c7d3cde81490abc80840c764c40d6df08fc71d1e8196eae0802f8c8dfc24 +CT: 23ad62a668f942e613c3b5a7828142048f1f6a67f7f0e0cc8bf3fffb2d1dd967da472d080353dc9c23b900a566f20afb850e4a47688ee507faa6178fef2afd +TAG: e9e82d3221f964d9e6c09d761afa3f05d1316d39c82618a82dafa23607bb40a3 + +KEY: d5c09fe24201fcc3ad4c9a9c4b759345f643e930301c3714f62c8dd4974bb15a026b217ac637b4f0e8d6ef40f36be967c50aaea83b2e72df18eeb9576865f1d8 +NONCE: 9cfa0df1fe0910b33ee9849d +IN: bfeb3d86ce3f4c5ccd0c3945e1da0e75dd057aa5b4e1f070593394f4a0227abedac0b77478e04d498506245b162e909cb711d8b875d33f9c4578e80a0e2113 +AD: b874a8523799554436a1174ab124677dc2ae2042a436c85065c50d5b5e7519623379ffed9a9c2b84b9626214b13c1806b65a432ba79066ff28ed94d17628f5ff84618593954389181e997ebd245d31f520539e250b31c86b99992983820f79e74aeaacb3a95e690e2841aba5a384d0333ebaa5d1fde06b4b8e3e1cabc6639459 +CT: afa649ea47db94936f89612ece681bb175664a97aa6faae5745f49ac9fcbfd4287b73cb58e8d8aa12eccf309182f075098f339db697fc60540481dad0cd82e +TAG: 9909335130df0326650823de5a4f5b6f45e6941a6a72ceaf80ef32fe67363944 + +KEY: a13c4654606f532a8df47c367dab1b214166e4f7188c20560831ac30ba5e58d316d29764e4c716ec0126657c926ba2e4541da062447228ae61340a951101b4a0 +NONCE: a2df3417ebb86bbb2f954939 +IN: f1954e59a319547d32e81f846e0c79db41c681166b43eb9c10458948606ced50a44df26fad5654a7c25d3fb52539cf25fcc1c11707c4b5aca7910a76e2374740 +AD: +CT: 374726a4691f178a4c0a6f96108ba30c4ca8a30242c14e84380969473879d4a5de580fab4cf6ef6e465560a15028ba78a1a88f9e62322cb698b15ccce6ba83a8 +TAG: 683e5a3e61d9d9c8b170f1d4eaa4f74dcbecb1a4cb1551dc364bbb336d4e4109 + +KEY: 0c1751677a9b7373e0c2ceab2c8e4dab50af22e2230be3187c21ed46069168d173c28a7474d8f7c3cab39401663405aebdcc474ce136e1fff9cfc520bfe17ca6 +NONCE: 38bc2efcd97998de1528b064 +IN: 8a3c6212240bdcb86da98f0e3ab3e9e78f7f61f0627ea088ab283e739a0bed5c360eeed26cea43ec09b4f3556049a1d7f8ef86abfd1118f9c0e34cc6eea4544a +AD: 20 +CT: a1a9f7f4750be3d89fc4f25917f8ffa7dd462ce712ddf61792a01b1840bc8e428000372252f1b41055416a961db3be8fbe774f0a0a71a82e79e74927522703a0 +TAG: ae24708df0d5893a902765f6c6c2eebae0c11312936cd415bf4a74bb8498a367 + +KEY: 154c21eb43d8d556e5f782ddd64d577ac8066fa172c2936fc2b2e875aa437f941819d9ecfaefa2e388fdeea81a0ece8dcb7647f2c68da48884aeb1315b577c09 +NONCE: e14d1bd8681373d41702a762 +IN: a2c880fcda87d9d4681a735a6790d93a1c9c68e55b87d5f7b3146665a6b2051398eb9895e1f5d522841668b9915633aa8cb40048c619baf6d63ca2da486cdeb8 +AD: b0b725cf634349ce1d3ac49d48313a09697efd9996cc5afd06b1d0817181d0374db05825dc2f08207bfb3b +CT: 1cc0db5980863df7a40c78e323a78be6c6d556d4e3b5f930d8d0f2c6a10c6477e31c000d3f0563b46e1a4aa566a4ef4b433e17e94c43338b51a7a3f862739b6e +TAG: fe005424112de2a5ca6e68ada40984df1ae5ac666cf5fee19e9a0f203dd69f52 + +KEY: c34482341724ee431b5272ee2964b245d7657778f7927cad4b5a1bc30a176b1eb88a83ac9faf58215a72855edf94f8e86fade58c5b5907994bb8381c9f21b753 +NONCE: 4934d9afc32fc7e2d8851594 +IN: aa3d32adc47b0b84d1b038ddcaeb007a7d5c96cc06a943eba5da6d0d367625330556e67da099c84086b3f46bb4b72986e076eb426913e415cd20bee34e434bd0 +AD: 076a7bc587b306f3da3ba88e66a55cb8125bbf8aa000dda266e950f381e35ac938ac86f8a15a83022a25f28b +CT: cf017d87da8927e42c1f10fd3d73cf483bae43f4e110363159a9fbb7cba363930a0364cd42a5de2c70171edc4caf15bfc7238f7087bf1402b32c7bdb1f493393 +TAG: 3961efea656aab1b83082522b801fafdae346f7d4be70db1981283f323e5b5dd + +KEY: 363e10d8b3fe349014d6222761bba7af86545dcd1812fe2e5ada564c5008f8ea1850f374208e87362afa135f20f9e79dd0ad32f86448263416086d3afc5d37c0 +NONCE: cc545928edd3b21c0e8bc0f1 +IN: b68e3a54d17dab6eb41b03de2df14e792201d78a9c1cbf341da421da82b026ff471d4305ede5c6baae162a098c73da5cab93f30d6d540b4eaa0ee772448dade8 +AD: e21498edf4e25ada2dd6a382eceaf737623e501db34f5c5bd5c963f45818b146a6e45aa92db2a2069e55d46a4c +CT: e4920c1fddb5dfed2268781fbb17e9ad2ea88bf2a0f116fbb7b309b25a5b9f989e1abc334999ab175b65f87e874d8ba80792044b458dc27d2b24c989d24385e1 +TAG: f0dcfa064cdf042e0b9a0443d634c38695dd09b99dadc647195fc2ad53dde547 + +KEY: ae93f58aefa94e4e0622f2e962529fd2efdab840fd0bce62e163ca0fb004ec3b22e246073614203d9b63fe2842ef5903ed08b3e52abf7ea18acbe16fa8f66368 +NONCE: c9ac237c87270f2d88b91b64 +IN: a75f49778a6c03b0f8915f5d09efe99c5f4e9cd928713882e6b9b78bab3541812db41792b893c7e2259debc6c660ce708851912a5b9eaf91416d86b5de114ce1 +AD: a4b198a329e9c5bb6d9f31a6415811eb33c79422b0db130b78d788c38c0b9a5122688cbc50fea811afa20789465f9ee4362336cc3701ece701179af96eb7c86d5a00ed8582f24364393287d5dbc3e83a82b7a585cee5b152b5da40aa45ccd46dc841004778998c7efe9eb43c9762d1c8581eee64e18c5a961bda5aafdd5cfec8 +CT: 453fad9395106a703ccbfe811bf775f1827ea960c71d79242d2ea0e3e31b14baa76eb6d107dfc6e484f4e5146f8cad5b389e4c0fa18260c96a193edbc8091a36 +TAG: b67082c21557b31392a9821fbce4b93706f96856d2581c92e7fb65dd2166624f + +KEY: a145adafac46280e1cee8696903c5f3866540f27f17a519637373d95dca4ac5ac0bfd85ca6e1f8df8ae3fcfc9158421581669db52c20a3e19c5d251952f63218 +NONCE: 90bd43611f235ff225b23208 +IN: cbe5f3a5b7a94b8665cac1a4d173a225679e1a3926d8596b5adc0ef4fd00f7d93a432ff141cc04f877be60b6a17fff40ac845a91bcee3b483862f67d9a76ef498ce5e49c361bfc018e401aff47b397e96b2982d4fdcd043ca09905be9634e83dc22a667c955bc992ec96ca1b76f73631767f64fc7151284d5aa81c1aa42eb3aa +AD: +CT: 604f718dbce17dfca1fc5e0f400151cb65bea9d7d8f26d56687a76a23f89201aab01ef928006d15493f5b1501bb99c517cf123acd956ab575e687298488a88d5739c266e67ca6a20a5dbe5f5f27ac778816f04e7b1764cb716477f3aa01482cb6b25fe034ab5d942013164aa124608cacf13d6cc9487446cfba54315fc6bfc42 +TAG: 8e3e1a01945bfd9e1aa4eff1cdd0a6da6d8fdd5446e6d732a673effe8e44d76a + +KEY: 63ac8e2561341587bc066c87cd23f7f33e6023bdc1521a91d6ce63d3ab213825d95d674928b56da1741aad8e85a8b703239ad74e0304ad555eeadebf4ae30aa6 +NONCE: 4f3073c3b780ebb146e136c7 +IN: 7f9a05b1aead29b4d5361c2606e5db8a48122858842679cd46f8386ef9359f998cd2c6c266791429624ff634a160d08faf1523b650c30b2fcd71517da5f377000251ef23cfd2510a0630215ad45fa6d2313f9add040a07df8259b82d3f29cf1ab8477cd114c9ee579d3e2ce60c5da2f3375b68b4d6e0913d39dac9399c00bd32 +AD: 22 +CT: d4ed811c8db932348e0c311e9278ef22f22cec8af88b3ac0cef77f13bbd9b8cca037c1ea87590a0ce3f3e7b3ffe1dcc4c7cd9e721baa5f126a3e0afb26dcfa02bf44428846c0f1e07ba0e026c23a39877de1e69e16a2766ff4fa3d4e8d3a97ba28f407f459ae3520dd840e8f9e149ea582048dc6e3d0227bd86a9c26ddd59895 +TAG: 0abc9111229bcb725953d139a2dcb1aa0cb9d3d6c01ef4733482dc5edcc88958 + +KEY: 355454fbe12f125edbc13550a7494f37efbe12b843058d29f892e1524289c2868ef0050a75a232d3083c381289e4950e352d68d64bf05f0608d694763c36641c +NONCE: 0a344bb3da1c4260f2daf256 +IN: 362e97f8ef09f30e5db2f21d40568d347d9bc42d4c94a563484b12eb109886ccfd2c61c40dfe93eb836bb6aa4f828e77c137485da2df494cbeb6a9a0192c3777b4d7a927fba11a8eaf604b85a81ac4719ce8b595a74656286fd0b80d1ad3f3393e6038b258af97af9a77f6760d486d9caf5a451ba26dee51bda0f76d75bfc26e +AD: c7c2e8196f37185b44515480d5d9451d79d07df4c1256bff6382f942727ce9b3a4f81ae964d8af2cd9f638 +CT: 32a67922947fd6b1c1bfaf3e1d41397173b97095e55307cae1c574daca275778d4aa4313fb1fe5b3997ff18800903ce044c7d0976abbb03b6cc1f7498d8b56d00672bd74f7cb152b677c632ef7a6f6fc13e95e82b6e35d663eb47f27c229c81174fd7c62c94c414e47216af2580fe822643e54907af77ae18e903fe856a02173 +TAG: 72d0fe5baee8090c5f8e79890b77f6d72a4213a7d1a81e0d1f1c9e6731e44d54 + +KEY: 664478c9d30d2cbc39351ec3b3494f3edb81e32e48bd4ef05969da07e770e4181a9ada3b2f83b46f40fc2d9ad35fd8ee6864ff3d70436d6cca3f8e0563cc3b06 +NONCE: 7313df9679181ffad2972a6b +IN: 142f073f2ce443c68822f120b5009e39bea3453017dc04c1b091adfddcb2a7e361c2b79eab1bf0818bc86e9d7964834d3775698b56a11ee07a0c9c03cb7bb895bf1a1dde3975c3662d233052824f1539f58cd6ad5cadb58fecaf2b34935ff711c45a639d642fb8fc3a52929b1296683bb13e67f2cc8ed9090126cdf28a4395c6 +AD: d0d78b94505793af546912f3780699dd72e288c775bfc75da6e306defcd868f6d40c6d6ce34fab9c11574ef5 +CT: cb913e40ea5dfe76beae612e9732d23ce352789987134822b2324db585179bf90d0ee20bee102e93a49a55fc978d19e99ba316cf8d9a10d2f2bcb75da4b135d1fcb8057edc33a180586015d8829a128f8fdc87b72497016c280f54f4d974c2c7e9d32ae137eaa1bcb670be237269fa73c3a0f273da9e70d89600ae7c231fc9d4 +TAG: dcc158c254ff7e131ad854a2158d51c643c281dfd7df342d5481384ab236a685 + +KEY: 409d1b4e1c187c8b1c053e999f2af648583e1045d56d553cce9270d08c5643ef365eb35e3bdeaedcd164b0122ad185e71c75146a9807104d9b65b56d9bc1dc55 +NONCE: 1cce3f08a5aa5824d063a6f2 +IN: a255239e4065f3effe6aa5e88814d516236d016c51cd8eb35af7cee86418966559802f8ff7ac39c6a45acc1f1b18cc28d7cc32ae66dff43289fe44c3a2a72fbadf3a7249d76c1ba9671dfc420ddf513539f2da5f31030f2b6775c57432c2c3486621d841e80dd4894229debc12ef47d74716838f2d807e208f0fdaf733bce76e +AD: 8f34f8b676e71844841c6a7b63fef1ad3061f2449c1044e1a281595da2d9e9fd141aea7350bd8cf9774d375e67 +CT: 969fc2c64261db415e51eee8cc5e0cf5185b8e3325dea516a70e32115a5b72233a44458c40f2daff3594d71e42ca2e3fc1c444ce171d22ef40009d798456613fa4b76beaa6d469e235997a302ac468c8bcfb8ef5de5cda58d7e554a9eab6cb568945dc37f28b0dbd674c083dfbd2e42fda1b42d0c1966e9652a21b32af71e2d5 +TAG: fa0789a83c255412501944a67bdceaff3f01d9a23b0c749be38abc956e2acae6 + +KEY: e6fd8144cdb305bf9e62a2c901764c62902f354409d8c5b9c8cbfc0ba8ac7d0859ff8994e573e46784395d89c355a91a313f601b56e86ed3fd10ba428a5481ce +NONCE: bae080718d3e5c5998542f15 +IN: 2258ffcd6fcf91b1723f8db0047525d61cc8ffc440acf3290690685d16384292493807312b7dfc23ac9d9c3ee1405baab21a3770a05875cfe325268b65fc877463e3208c842ea4a32cf144cc46d57afd91f6b6b5d85fb2dedb0702f0c4e7f742cf4c9b4aec02f07267ec1f7b96a5a3ef25f6c1b4c27bd829e86583e239cd854b +AD: 51ae57749b7757718aef9b9c47da5794659516e7f98bc80e6c18c89253f8617963331f54d4f009f087d1d2bd69a083f3a4b98f2a51ce24ffc6079774f7c7b01638b6131bfccebe21fea67bc839c259a50fcc0a16a69ada3c5adee4097d9e053a03266cb9b4b39ee2a465ec1aa058e61a0b9888b93bfcfd103f91ca3a7b274a10 +CT: 5b2fe8eea3313cc04d5ec75d75d05b3242b6e3b65c6fa1761716780c9529ff8ca523096dd037c5bda27984aa93c702ce9c01c63569a90657cc6373ad5d4473028b7eef69dd79c44c38d0063e8a8b7f1aa2bf6b646711ecd4eea3fa27408e089d9c4c4aceedff29a25baa6a9069eb7eac83a53212c0b387d700547c46cdc525e3 +TAG: 60319de093aec5c0bb8d5f17e950b0f4df0dfd20ad96490f6f12db461b2a4a84 + diff --git a/external/boringssl/crypto/cipher/test/aes_256_gcm_tests.txt b/external/boringssl/crypto/cipher/test/aes_256_gcm_tests.txt new file mode 100644 index 0000000000..30fd422d80 --- /dev/null +++ b/external/boringssl/crypto/cipher/test/aes_256_gcm_tests.txt @@ -0,0 +1,466 @@ +# The AES-256-GCM test cases from cipher_tests.txt have been merged into this +# file. + +KEY: e5ac4a32c67e425ac4b143c83c6f161312a97d88d634afdf9f4da5bd35223f01 +NONCE: 5bf11a0951f0bfc7ea5c9e58 +IN: +AD: +CT: +TAG: d7cba289d6d19a5af45dc13857016bac + +KEY: 73ad7bbbbc640c845a150f67d058b279849370cd2c1f3c67c4dd6c869213e13a +NONCE: a330a184fc245812f4820caa +IN: f0535fe211 +AD: e91428be04 +CT: e9b8a896da +TAG: 9115ed79f26a030c14947b3e454db9e7 + +KEY: 80e2e561886eb2a953cf923aaac1653ed2db0111ee62e09cb20d9e2652bd3476 +NONCE: 5daf201589654da8884c3c68 +IN: 96669d2d3542a4d49c7c +AD: e51e5bce7cbceb660399 +CT: 4521953e7d39497e4563 +TAG: 2083e3c0d84d663066bbe2961b08dcf7 + +KEY: 881cca012ef9d6f1241b88e4364084d8c95470c6022e59b62732a1afcc02e657 +NONCE: 172ec639be736062bba5c32f +IN: 8ed8ef4c09360ef70bb22c716554ef +AD: 98c115f2c3bbe22e3a0c562e8e67ff +CT: 06a761987a7eb0e57a31979043747d +TAG: cf07239b9d40a759e0f4f8ef088f016a + +KEY: a6efd2e2b0056d0f955e008ca88ca59fb21a8f5fc0e9aa6d730fbfc5a28b5f90 +NONCE: f6775dca7cd8674c16fdb4ee +IN: 5dc495d949f4b2c8a709092b120ac8078cdfd104 +AD: 86a597f5e2c398fff963fcfe126eae1bc13f097f +CT: 04416e23586ee364b1cf3fb75405f8ef28fddbde +TAG: e7b9d5ecb2cf30162a28c8f645f62f87 + +KEY: 8d6ed9a6d410989e3bd37874edb5a89f9ab355fa395967dcbbfa216ec9ce3f45 +NONCE: 55debbb289b9439eb47834ab +IN: 52939c7416220822a77435a46687f134cebc70a2f1a4c33d37 +AD: 7790af913d84a04c1b72d4484ea2e09fdaa802d8b1733b8470 +CT: d7bddae8929ed6bbc9ac077e2415d9fbafae4a0432f8f7eb6b +TAG: e6383b16ed9c32521dcaeef3a7b9b67f + +KEY: 525429d45a66b9d860c83860111cc65324ab91ff77938bbc30a654220bb3e526 +NONCE: 31535d82b9b46f5ad75a1629 +IN: 677eca74660499acf2e2fd6c7800fd6da2d0273a31906a691205b5765b85 +AD: 513bc218acee89848e73ab108401bfc4f9c2aa70310a4e543644c37dd2f3 +CT: f1e6032ee3ce224b2e8f17f91055c81a480398e07fd9366ad69d84dca712 +TAG: e39da5658f1d2994a529646d692c55d8 + +KEY: 630b506aa4b15c555cf279dc4a7ee9add213219d2c68163ceaeda903fb892c30 +NONCE: 79eca200a5cdf92b28be5a7a +IN: b12e6f1f8160cd65278c48f68ad53c8c82fd17c2c39bbb109f077c17fdcb8a0b3a5dbf +AD: 46cb18593b3b26ba75e4cb20a252caef31d00be31093d2369e93572a393d650c68313f +CT: 9a9ad1f78b4d411afe450d2e46347a7df98f39daa4fd478b9ab6e6b417878bcd52743a +TAG: 55453a003b021c8a247379cdc4fa6da6 + +KEY: d10bb6641e9ba0a3f1b016317831ad4232f81c2137adac0940ecd7fa36de0563 +NONCE: 99c922d37c95ebeda8e81ae8 +IN: 8b9089df5bb048cebbe709cb61e178ec768515a0031288d95b7cc4dfffeb51b836e126a237ec50cc +AD: f1cbf6c83493b2087d9f88e02121a114f45ed51817e46ffc0b66a783350eae89c6700db3f3be5f4a +CT: 8a838c51a8ef8134481e9951033295ae686624aa4df72f869d140980347a5e69a6d7cb3d7119b303 +TAG: 9152bef766579a3e9a1e36abd7ebb64c + +KEY: ca665229adcc7554f1b1c8f50e7444c6d4059c525f9c0da1406ffb35d50cae97 +NONCE: 8e2df19123ce0ad41df416d4 +IN: 12365eaac86b270e9c61b3ae7702a6f3583ef4accb80a98454c56e34e2ab97d8afa23ddee34e7e3a522497f985 +AD: bf539d8e9e3a02f3e5834970e7efd40cc7cb340a075041428d6a69ed9fa5105e4bc63720be9a7040ce5b4af6e1 +CT: 96027efdcd4433df8e7f6181c05be365cdce550b09d45cfc96fe258eab6d55976a9306a0070c9589ef08cf7a42 +TAG: ec9fb5e79cdf8ad4c8a79c900975159d + +KEY: 5033338bf7526cca0425f4a620424662ebc58364c8d985d130e525fd1f598f3f +NONCE: b40842b30758aa3eef7cda62 +IN: 69a62b8c5f9b81cebee3a9345f4e49ea089b0d9c1cc57b4ef707956d0287de83fcca6d8f5270a9393e00693075028189bda7 +AD: 3efe0ed6fbafa61070388abc59c0d06589309736b02418df5534c8c594d61a2afefbee17af8283d01634b6ca3e8e2aeadff8 +CT: d6184677a21978b6443d99d7de1fd01c6b6334cf01b7e7d58456267453f4de96708b62301172c8c87e970f91c5301e0ff61e +TAG: f8ac7aef208712845d137b8b176c89f1 + +KEY: f33c39140999a2cb69e43129cb5df18fffeb3513ec3560792e9909784daee43b +NONCE: 70608463f1dfabb1fc4451e9 +IN: e2802c4d290468177fdb031a717345753cd7c3028ed07dea428db84e7c50c3eb7b24f7381a167b4ee31bf88dcaf5251fdb90ecbb74ac2f +AD: 10a6f463dc59d4791b3c2b4c93cbe2dec579a154962cb2c4cc77664e8c2b106c574fe115fd43dad94b8b1bf2f74820e28435b4444b2b82 +CT: a27419a46037323c033d7cf2a716777fedc02a5ddd8bfbdbca82ffbdea3037bc1cc80df7c5e502b32276ae88ad6fd0f0cfe72604648812 +TAG: b1ae330d47fd399aaaa687e141e23fc7 + +KEY: 2121056225a7b2316a93c4bfeb970486fa9c586c14ba8b40be5844a31e9449c0 +NONCE: b4b7d1e8fa7d0e2334c92315 +IN: 2038e2c6cdf5282f081292448f8febbb60a1520fa3771cbfef387f48c5915a1438ab709628e8d4c81623ddbc2f6f159c3c9a8922905c4994269898b8 +AD: b07f66508a39c4932b04c16172d6462d78273cd9463e52284bb73e3b8b8e7047bdf10c5ace1f903e5a5eacbf67c9351f82c74bda140df2fe0480c80a +CT: 7b54618ae09b37ee72e51873c82cdd20b6dca37c334af89548f52f34df3a757e632cc0d453fc97270898eb50ce2f2a98c4cbd4cbb22a5b7c7564406b +TAG: de3a9e2aab2439675c4f7f0b61216d5a + +KEY: efb15235bc91771aa32d51472877b0eb364de2f88766908eebc6e6b57a702099 +NONCE: 1a510b42dc20d1d0fb34fb52 +IN: 4eff604dd4bba67f143dab0728b8597e269d4e0ecb4ce80c9850afc645d96da239d9db360605bb4268d74e1fe3431a44242ae862fa2340c076db13315f615b85f0 +AD: e8dad34f727e77444a96cf06425640f1fc80fe3b01dafd1d91476140afe8204286d01b0ebdadc0270a3d218516ff5f08a69a7ba251ac325983caccbe0d9e1de359 +CT: 989fef0145e2fe93b9f99fd90123632d83d9df8f37d8e1f80dac329dbe0c214c2191009e31232538fec63a29665f0fc1c77dc86b2f5f2050b86b3ae48e85d63116 +TAG: 6816304faeb45da4e4772f5c35730f8a + +KEY: 998c22912d5687fc3faac262a902783fcb0c738520b5c4135a8dd2cdbd7b0dfb +NONCE: eeb535c5bd6edfd696655b60 +IN: 1f6ae10d425923c882b7d2f556571acfc10333ec665b07bfad9f8948a3b8c5e5f163a4e99d4726da1a35359c657c848f327b7fd9b5f61987440ab12b9399db24715715a2d1c8 +AD: 9a3c76dbaeb69a6481a89318caeb6358267ef51a1a364a48387bf77526837c9c70afb6f105cd47d2b976dbda7d2b6bfea7b76b135810c53437472f7b80ffc8ce4dc95c7e5045 +CT: 87f4e2c80a4f15f92a8e94f468e70fe7f0e0f83c0a7799a1d465043d25210ac6f0f39a5e9765b4daca637864d1bcc090d2ef33ddfccded2d2dad61dab443b3cfcc683147c490 +TAG: 0744d928a5b5ec95f3087cc2623f0031 + +KEY: e12effa8da2c90a5d35d257c07d1b467991bd5f75fecd7129aea4e26b9e27ff1 +NONCE: 4edd0b4cc349d37eb77f5576 +IN: 21dc87984edca46a629ed95ffb04471397da8806c525a781d9a71818422e344e4af577f38e7cdbc556d4766770a9a3c95bea59ad497fe0127816ec4dcecb6b999486719b0b86cdb2c9d09e +AD: bc158e6570fb0a08d73367dba65b80a8c8e57ba6c7b99493ebdaef0424e18d8ab1f7c88670cf51c4d91b77eb9ce0f89a46ed1316141e4299ec6c3d6e712ec9e92d3db44640402aa4ac00ba +CT: 07ab8c623d683ff83030392e2864edd4b8e3d296d60579a226a8d2aff6bc5af3c4598a18cc1e8d7db4ac8eb56a082af864ac52a324851dd29af51a0945cee4bf303ea111b9b627aabf5ff8 +TAG: 53e69b7be969c39560c016c6bc1aa4e1 + +KEY: 3d9723c9235939df8647529b7e4a57b8536476d5b71b424e2c27ba4d0b82b0e8 +NONCE: 60163d2eb7822af7fad64c04 +IN: b44face0f45e4a8da19aa0c5cbe3aa960ed6b74fe3d3d9201f52523dfe7651756b2ce482e759c87bde4ec670a0e808fb4883e437c7cbcf2f6470352174327824200cb0897edc4def1736f51e229addaa +AD: a4b2b7bf36a70a5246feee52c474058100bc618fb0e3d32e8c1f76153edec47fab3045dcc7eed9ca1886bb2593703c9ffb8883c45386d2f4e3fbb0b7c722d19f2eca94767174d9127450549e8993ae33 +CT: 66fa63ded066ac67bf218af7bc21169a875f4bd695f44fbdff906f0a9b8a067be721fd260571c53a8b51661c8d49fe178dcb28c31deb3fa71b096b387f9fc8f3657d280404c05d2b6443eba7e60b562e +TAG: 59d5450872510c4bfb590d9497524331 + +KEY: 75b0a20935c4a5e2126ac7420d632bfda8d41bc947c2402bed4759b6e617ff92 +NONCE: 0c3edf0dcd1125d7e263b897 +IN: 8edc98e70030e40bea1548f6f56b4561272be0c333f3b7ae53ff3e27c35a91b1aa42d39e6305ec4811e75931e5cae2261d88a6f7d6c5b05bfb48802264e9cac782411f1de579e29d464ba56840b126a3fad07f01c4 +AD: 7e35081ef652424da6304852243ce43ff711da17f7881d5e0433b1ad7535e755a8531b93d67ce99ffe66e59fbb24f6b42655524b39f2c84daa5cdacb5e7916266c05711a118b2128930b95de83ff1a67e53337474a +CT: 858dc74dbec6fdbe4ef15a3596ff7201c8f4fcca765bf5452f678b1493a66ed9852a6fa174a73099acf951a35699f33289ec50625538c01eaa456dc658013a29e4d133b856eb969c1f221f99e11fadc98b0ee08243 +TAG: 3d8f17838c4fc69f04d7e2b76eebbc0b + +KEY: 7a3823191abcebadb7970d1b65c2a8dab8a908151737bd5400b3b6c0d59e3b08 +NONCE: e32eb00e5106097e2ef0e8ba +IN: 220db5400dce604adee4cb698cdc02d2ca61622bbdeebe347b0bfef55cc45319b940f93773a9878725c5f55485d7a26363251b9ce0d3da1f8f6e34ad5329dc9f752ec7dc12b2d259ac89a8059085996a431a56cc2dc2400a26b4 +AD: a83b6dc78931cb7500eddcf77792e810c1edbd5f4e33f85018807a8539a3cace094fb794fa9ea058e82c830d42d5a6b3e22b7785698774aec5c73edd92731c51106a23c569c0c0fef18d13da1562a9a42aa435b243c4fbc9fe42 +CT: 5ce6ec0e1d67ced5a6aa46c909b9b8907b372be03331dd0940ceb6d87e928c14a1a1e8ef9096c9b63ab4cd93242ec7be7e38b80643f9c52e7e90ffa06b8f2d238fa63dcd97af74ae37802d124623b8a272e68ca18b3432b7c017 +TAG: e21c61d604253bc5b5d58283756b9eb3 + +KEY: 53ff6dc0af3e89fc2de7370caa433f539d068609fcfed6400a5b9fda4c83e3aa +NONCE: 91a824c5e023283959858062 +IN: fc23e07b4018460279f8392e86423ecfe465b25b60382f58995ef5fa1f9ca235e4bf87112554aa0e72836831d7b5f39125df11518b8aeb1809d804419beb05ae013482213012e4ce980ddd1c58e11608b775d12b450ecace83e678c69d2c5d +AD: b3a1db2d467780480f166859e0e7aab212738b85e88237c2782496c9c503347de02f3dad6bfc671fda71a04ff1e4661767c11303daa0c36d944346d39e3e29ec63d695cdcd83b2b57181582c5ac692b13e4299ab5e86c59d09c2dc6194ebe9 +CT: 88af588ec33bdac2cc748a01ee3eec97e5bbfdf69de1d66176f42b66383bbffa8b185cdedc25b11a62237d334d68120fccfd68c2f9447b3b8e1f623f33f7f97ad8815d29bf11bc0c65641ba8fca4a087783f4694fb1d574450191825f84402 +TAG: 2c4973323e635a885f78ee106eddf19e + +KEY: ca2b4d335598f26d3d3607e62b9ef853d3543e741350f92f3050894721d3d450 +NONCE: 2431b5cee8c3ecec4caad278 +IN: 75e29e46350d1fa99403b1e5baa414e41a8e714910f313f8e850cf3076508ff650011af766b51283fbd5626166d775fd4b4cb7124d26d77b41eb17bf642bf67a34c1caf0fa9b43eec12103f864e56c5ccdc81b89c1a35e394362688d05dd94eda3d05dd2 +AD: 31c3ce532bc1bae65b5ced69449129b112019cc6078268b853dd17c41832ecae07f9c6b068ef6cba2b55f352904afd6096ff8432081aed408d9340c319fd8e2029c389b6e3a4bdc38853444c3f7be9385ff1ca27e59c43b542e99799bb4ce56b8e26d6c1 +CT: 90c13ec26d01b7b96bdd6816d3ee57df57efeabdb15ba602229ff71d71793fe8081eb1b462e8b2967bc4af96fd6dc72cee3d2b6495c7f04c9068b2ad0b073e11cd5999df541ad705c6315eefa8da49c5dbc258f7ba922908489c1ce672971c3bfb6e8482 +TAG: 3a7741a094be92b838850c32e4b06c6d + +KEY: 49fbbdb5ae21cd955be7f7603cb8563ea0b02b77a9ea14016baa5cffc55d20c9 +NONCE: c0a4463350506d2af9e35d8f +IN: f31003aaf5d8fd6261c01c5bb1e7bf6af248e0be3cf8aac67ccaeb0b7468a40d98be526a8e4f692dd23763563e601915ebcb59ecbf03bf9c665c4c5313c318939a911888fd427d5297b9b2fd91dd33eb7ed38e2f0f6ab74ec263989cdd9915811a022d4a46ed35eef0 +AD: 17e01af2386531ce67d5bc3325d8f83b53a87b38f1c305f99c0798380a7e59d3ecddf33a5ad23a82e33f0fa34eb2438b17e958451439774ab642fafd3794f80a0ee1b9bc165f32df705a6175310670ba54af3a204e446db35170ab02670086c47a475c22d1f14cbe44 +CT: bd661836d1b74244baca62d7d1cb6717e17e2fb0bcbc8d36b3265a983d557c562b0be60708499d0e7e9626825bc049db79a0ef4d2393fef6024d849089455e55693fd4da3d910eac11496492a645e4376855732765e1b3580461a2a2533cebb482736ac928cba175bb +TAG: 4596e3802109c899f27f6cfcbdceac5d + +KEY: 30d0e4f6425e38c92ac34dcaa06a815166f301289ca9cb0ed08156617d87bdf4 +NONCE: 525618ac9e317405c7d44367 +IN: 06f2204ca864dd3f7c9d0290f6fe3d0337eb9442cd5d2b586d1d5c30e58951fc2f4e99831ac7bca4356db4609a0428c482f2580b9e8cf5fd00d86d474fd88ac3b2413f44c1ff66e59e7538c090b2444396f02004ff636aca05ec40439f4e3f470a24916fa4033cb60127223addc1 +AD: 23c1a3e1083904f7226be7242027abb7af9d62f1115340cd4a57611be88303955cbcbeba44eab5488c80aed3e063c70cb7bbdd9ac289c8c8977868c3702be63d0358836838a97b31f6aee148f2b8615ad7c5dc0de7c48db7752e5f1ae8637f8c70335bbecf1313ae1b972ffb9442 +CT: afe3e71953bad46ad28113b7c8f2092fdebaeb81626bf94bd7e9dd59e000e8ba31c1ce7f728fe19dbbb42322e54aab278e3c29beb59b2d085e65cb8e54ea45d6a9fb1f561bac0bb74afe18cc8de51abf962c2fbc974c7ed54ccf2c063ff148b3e6cccdaa65cc89ab19fcd9cd0436 +TAG: e9f5edea1fdfc31cd5da693b50b72094 + +KEY: 661309741227606892db13ab553070b456c5e421cca59087144873ae6d59e590 +NONCE: 9f07692c017e1391a981e70e +IN: 40b5f8081b5dd173203e02e90a6c171fc41f804b2903ea18109edcf77c03dba687b47ca389c55389bd7b0ac59bfaefaf43b5f97065df6a5375c1fbb95d95cad589c2a45cd9e1e7960b1d13622440f7180aa565863b4f9dfe26ed336ff4318653e1a520bdb830e01db78a7e598f251834d0c9bb +AD: e8540d084f24b80414af554f470048b29a5af8adb2f9d55c9759e5ff1595ca74884af67027324587131d90c77ca72b2d15b66564549ce93df7f667d0218a6e874848563a33886c6a0c5a9d00fa435dfabaa9053243b4c8c25779a4dbf79eb4b8530a7c7bf4263ea824713a90cee92dec78c449 +CT: d543f49e6cbe26f1d8a6e058769d5b16e6f8255a28b4d73ba2cbdf664bbc5ded73f9dea12a11b86b6a6acd578f685afabc232dbe9ff8431a5318ec7f0202959a310595b147353a7ca89c9d1fc2d2b92ea610cf6d9ad2716df2dfed70f5b74d498edab114058c22c96873a2a64abc254c82af46 +TAG: 31a8441886d0e4c6bfcd6d74f6a5ee5e + +KEY: a248b0d683973d205ef2d3f86468cf5a343d6ad7c5aaac0b9b6b2a412eed3552 +NONCE: 8f62ffac4027f4dfeacf3df2 +IN: c2d7d29256832def577392acb9fe4f249eb4859025ea55cc0c4a67806caba3e1cb81bc7f5717d94e1c91ff06607b23c238daafcb0fa96905616f02205b702508970fe3bfca87270ed1102a9ab96df57ebdcfd86ef6e9c4c4242b4febd82b0220b0d6f76d8c2d0fba33ca49279907f6bcf7e8401d1419ed58 +AD: c738cdbde6dc277ab81dae20fbbb4a50d71bcf0ac1ee0ec6a39747ccd87be40b1f0f2c37f2c6b32ea99722979fcfddd0ddc2e4ff34a2e6113b591cbfda317c6f4b021ad30325276f8d8dd78f757618b53297fec091f029f9b00850b35f3863a3801c882422b318b4a1bdd89002f928371ea05c6fabcb1792 +CT: 7a837df292ad2e58f21b89da43a74de411e1746556fe47db55a136757513bd249384bf67887a5c1f605e7f7e3057596e17039701ea351e5ccaf0fd4882559e87197144632977cf07cf9e86784a959fa7399476a4fd196d7c507fe3876d759e2b37bd37edb3c12b89716f29ddc8b64974263a1ec1b6364b0e +TAG: 291098a2376a0faa5da6fb2606b4f2a4 + +KEY: 80634a8baea1c4fe5dedb664c9b5d714422dd1726d642e60d15e02364195206e +NONCE: 725ee5023ae08fece15d621a +IN: 4d1d8855b4d155e77bd1bf34b3d049ef09b2b94f4e604306406b015a2d520e8772b084ed668b868e32c7563085f2a82e7d99219da549e507aff9515e45a045c7cd5292c0e09a3a38c769acfd0a11826b27d8bf05184971670200e79c49754debbfc57d9ebc661b25f22f241c4d143bd922f7b0981a48c6a63462cb5cfd +AD: 12b3fa94a64454dc5b47433df1ce0a7dd5e8066d05b2433c6cbcb83087bb7d22d153a19c05aeb76141431c5f9801cb13531691655939c0c812611c6a30083ed3ec27e63e6868f186be559c48367a00b18085ffb8c7727638e833a7b907ff8465e3a01d654b52432767b18b855c05a9cfb5d4aabae19164f0dc2ca6346c +CT: 6b01e934916823f391cd0d2829c224a12eeddc79f18351d2484ef6cb5d492ec9ec4d8c4bd3354f01d538bbd81327f6360a7d157feee64b539489bfdd1be4d7f724d2a6dfa1af91e4108dbfffd529afa71388b07e5079236644da289ae236100b2fbeda0c17bf2a01e76cd1f88081682c2d074223fb8a41d59e70a37870 +TAG: 55762e95d897a33c4c75106449112986 + +KEY: 4f2edc967b11983f05ef5ee2a4364039ac02dbcccef3f3719913ae2719c8217c +NONCE: 255f8209b0c67a6277bdb42e +IN: f8217163bcaf77c1383089e396b271e22c517e8ccda244256cc39315fab7d0c291078d90e9b6e336992f015282caa1ec0ea858a179c9735b7a2f0d50f6f1eecaf3b9308772279ebb95f8aa53826e9dd60fb354de0c50c10001c98812b59d7c0f36daa1aecda6782ca36130fbb559363fe07704b0b91ea85be319ada027e47840c764 +AD: 1dc7065f1585384b88be47598ca484782716c78f49b3b6bf5d24a5b0d24fbd7831f18d77d80951d2c4fafb6f939d46362a69b558afadb3bb4d8aa27f7fcf3dd9624e1e075fce9bb239926d51ea9dff03619d64d5828103a414e360adcda8fd864fca55c21df86c76972c3765ab1d68ce89f708e7e5a3e06cd4de08573cf750c6f5f9 +CT: 6719849b7cea3f7f2a8e4de13d7a864d581b7c638f49fb06378a768d2034548179963c33f0ad099254c2edda9ef771daf5d299f58850033e2e449d7bc21ca3f7d3b7408429b596da615c8582886a6d8c1a9ba81fec4a41a38b7cbf1a80ee0ec8bd71451e727051fbf2a1d1e3c6ca98ee113e47650ba4fe80451e79b04abc8bb99a2a +TAG: 2ac7f962553a8007de3369c7795bc876 + +KEY: 51c5cf1f0c76ec96f4a5f9aa50a36185521f3ba259145ac6cb4da3cd12467696 +NONCE: c751e5e7e3d75874acfd2bfa +IN: fcda42cd098b7936f4bebaa37d5850cb0fdd6526966b1b5734f23d5050ee44466627576e1144957929123198e40b64eaef74476870afecd7b70f7583208603a1b5247074c6c77e10b9bbd41a3d468ff41db89895b0e9ca95be77526ddb30d4c5eb0796ba97d7d5c56d0eece344dde3ebd7de586226c00da224b04e74d9abe832686797df067c52 +AD: 343ae5e73fd1da48dce92ba7b86d21de0a203ba8587536fbaf4646bc45051a7feb343e38916f6c4c75b65f940045e830857c7b62b34a44622a36b34268b8a397892ed3e4de5df3fa7384d4ca50202b5b0833f921349c877931f4b735cec45db6b95410c8042ba49c1a39870276e0165f09c73b14bdf7f36d19084f958695c7ad2cc56f0487eae9 +CT: 04192659d6a2f1b7be472372c8f969a7de388c97d37b4a89653593e48b630947d2160b569379698e94de49b21572ef0b4dd330487a8be814a84e959a1a8e3cf33dcc9f7464fd44814d0cd7ab85e4c01c9d015f42ce3723c8ef8c311222b0c78eb83d81696c217992be725faf27701b4922c6e6099442787ddde2b7572500a5320a4d0c787b786e +TAG: 23c7a866574976dca8f401c4b5b58292 + +KEY: 1cec3efc0311d623f34b6853b3dc97e470fa728cdfd65993d9d48fdc192b28e9 +NONCE: 320fe742ef171b7b8cb615cc +IN: 722e503a97166a07974dcbf136fbaec6c03668fa52495b040383433ca59f6311103f2fc6a95ba4c925f8637167537321eff6949aa3051269fc094393a7b17d1ac8d29af052760835665b0ee89adda5dae7738656af9e8513c96e8a532a46ef34cd7430832d2be51c586a14e9aaec2458c1911bbc0f90b496737e838a12ff37d3db058bda9360d7d33e11629a +AD: fd5ccf6b6948c3eb96543aa40f107fafe94e5206c326dd8900ea510c6b61d1bcf746151a75404e31406c8e991fbf6e660db7c18e243fd2608aa22dd7ca9de88f277037661ce6dea4ff0a86809dbfe1708cd47d3061a34657cad143e6577549c9944e081f79c276300bb406378b26f349a91fa87de02a1405d712c516ae11b4bcf30ac9d56e677d03eb33e3be +CT: 363c1d6b806a6d97e2fddf53b242378e1d2b818828863fbb3f856f7737d63998a84e02d6c91e1df5f5eb6cf89f7ef53e16d10ad52f82362292d3acafaa02c23be7da7616a8b8daf8ee3ae74ee1078742c4ddc3e5a110e510417b9f43fbcbb00e17af3301b2fbcb784fb0a05b66469e771fbd78114fce3c4352c42928bf5a0ecc49228a3c930b0790bde7ad7b +TAG: 669482999be99149f9b723b60fec62d3 + +KEY: d3465cdecaecbf25943b7bbf8084ccabc15474a4228c46cbe652a99be24a861b +NONCE: 04fc836de3a1420b8e7136ca +IN: 81e0e984ce0a4074a44524f93e375eabc650a847a42393f5c524c65523368d38a7e2b677fe08502dd3bc42311775016b5689c660cc0ca8cb33a09b89f3ed3d02fa0fb75ca5bf0dc3c27c546b369ab5e7731f93bc074d37ee50d6f8366f6c8a45f73ac92b05c4aa552ecc5266041dc122a0df69a36ad625a26edb57bfff43a84e527ea0d9d3cf076f8de9eda28eb09de3ff +AD: e4adc14ac4bbf3ae7ec7d97f5c0e6090bf8127a75e8b70e9b86496a62a759dba5a4eef64a8c679c362785501260d29b58e1af647782564947950428dbf14edab8e6841c7afaf9e7949b560419c44bae30315c597f6f6e02204da7ec605a4d9a8753de1268bb0b1c84c972b4e7296da5c969781feeb35a44d2aef799ed228aa399ea04e21cf9f7d5600a2c07b047aa78388 +CT: d7995e7b610eede708526c05c584039d48b9b4356fc71b0c37ec2559309a688a7c69ac9655f94e178cd2311db58587863b0fbb990554dc9a6aa849571f945c61e5611ae7e1a96903be725a1aa75adc381b86e43fbc68a36f44e0e0cb8fe5c494caa91f758597b6ef3b80a879154cd8a7e5f570893b4f768105b24b58efb67c5f07c6db60e0f48eba9563f17d38aaf0847e +TAG: cc3fe61642c2d7fcbd579048fdfb19ec + +KEY: 1a0dfe2a6bc6a69659c68942ad0858e1df905890f47dab728ab9c73f742f469f +NONCE: f8f76b014116ba61392597de +IN: d93eead436e835a061ca061e3a53c3f9c66c6f011b21682b8a6fed098bde2018a2462aa5ab542c69bfa2805612cf6146c9150888b9720db1dcd0f359c1fa3416df4cd225dd0b0d949e917adfb3e83bf5ba2b967d48908e6b6d8aabc545335014d951a67390d7b5c7cd7dcbcf66e4e3f02aa4e5e9cccaf73e75622bad006c63433d36cb1c6aa4aa253dd1b2eacac75c548aa6648ecf9d +AD: 56ca2d5340629ca75de4e98921da352941559bd79f47ef0ab42d1d5857059352f96ee877f5458f090ca237e4eef5b08a53311c8dfd4c4582f18a93aaa8cf75080734cb2ea3389c9c74d2b04ead614eb54512ea93f0e3434e9a9366454b303a8129d6ce6cf96b1d6dd4f751311c736b517dcb50a6f6e0962c46637b4f5aaf0f34bff518cbd551a7aad3fa615708b17cf6d8fbc864f580 +CT: 8dc4d8483dc665b174ba32d6b6244da5f2a8fcc4b1865d662ec23057838b332a07ff073ecc893d413696f3fffc6dca5d107a5673f14abe8e0457a02e61138380d25e269686cbbd23cb7da3060f482f62bf80a40dcc2e711ecf5f7836ca14e456c4b73a48bef90749024393f5f8af01b73302e81bc37c4110dc26174702231d831cd14231905d2dd3f375cf2bef0425084d5b19f1039f +TAG: 825e7b7e195f65c454ce9fdd637138c1 + +KEY: 03cec87d0a947822493b5b67b918b5c6a6bbdebe45d016ec5cb6779c3ddfb35d +NONCE: eb7d261a6b56a179c88e88ad +IN: 2326102c58524326759ad399222c5b5a563cd01a29809d6aed4d49772a4723cfdf30c9f85f031063e838f543c201412d6f085a8f5435b0b2fe94659aaf70cf7bde99309239ed5b815b48342d4f81011f5aefe10ba105ac15601c64a91076c29c3cdafaa12bdd5706dd7305b48e923873cf06944b5027b210c59d79856f602bd6481980ea909152216756d77362c59d57673cedb91ee6f56a40061e +AD: 4d0fbeb69c1869d2d23198ec49b3dc23149005a84aace7025293c3afb8cb2e38c167a822e25c2fdf667d3677f4e94ed6574529c987de506d26b7ffccf3b7a36d9adac48bca76084710338eeb5bfca9df1bf6b403e33e90761a0b3152afac333071a5ef4f54010b945d03b51f123865673e8877f41ca23359e60518f076cc64232b306bd858634417e92e546ede4ac6231635c9cfcf43aab1f8fc1e +CT: 06746f993843901ce72f2fcd4af7d15e64b3102d2f9bec0fe72cdd0b97e43177a1a2238c9c1dfc3311f701196653249e767a73dbe819b660cee07a5f3bb8f25823875fb4b4d34a5a3a212d2e166311bbe11fb1d36f4e725c3b74054ed7fffb7082203ccb5e9d65873cb8a1ce28d5c6e2b6555c1a864a725e6c7d5555d37dcaf1d0884264be72d38cc4b65bc2f0d039d542c5055da56c57e084b804 +TAG: d36a4b6d2f592d4f0d347d906fc319cc + +KEY: 7f4b4bfa26719d9610c80ba3f474c43127f4aa3414fb070fc2f389e5219886e1 +NONCE: b144d4df961d4f1c25342d12 +IN: 638982b95d66ddb689b7b92e3adb683ac0ac19480148bac9db550be034cd18dbd10f2459c915e99c385cd8dc4dc6ec48b75f97e818030fc2d8fcdf66d66b80df64f0ca4af91bba83a74f3946b17af405bbbc6e216435641f5633ad3ee24c1a2ed1b39f649acce59ee56c282a3aebaee6e97f96b34cfc63d5b0482fec20d755f399dd5f61688fe55878713cc55d562c2d72236eb674a340d1a64932cdd8534a06 +AD: f2fe3d27bfc278cdcf16fffc541846d428b31534ec5cf51c30c8b6d988dc36cd6c0d41a4485a3f4469e92ea0fc7e694065bd8130c2854c95549630bd9cbaab2205f27a6efdc2c918c3be53f2d12f8f7cc8e6a81dc8be7cccd217be1fa2e6887cea7d637d2e2a390f50d2c5be10a32a9b380a400cddbdd40eac67f1fe9ba6033d4bfa88c563eaf57272c8a7052916cf4460f31ad026a0ac2588a45d082fbb5c0e +CT: 0d4de3489e09c7239972b675063579e409acbb663bea76bee8fb3f7e8785158ebe1c26db9219a9b97ea29e74762999518613249c3a87fbcd0128f651e2db8e2167f10ab532eced3464b56bcaa09780e5ece18182a6e092477ad933bd8de015c80e67c6802257a97a647fe2b1e9ab6a76c1cbf7d905deeb824aba2a34095f84b276d55ff940d6ab788c16cd63d9b16e0908d718c851a3230b0a37257751df5a38 +TAG: 9f0a882d4456847f44c7287c8ff3ba04 + +KEY: 9799ae8045d58250e4d9c3b0ccc8897a04b5b9fb164e54019dc58d7d77b65459 +NONCE: 0f20d002dbcd06528a23d5e0 +IN: 8f323018b1b636617c935791e1c8023f887da67974080af07378b533a7573424f1de9193c5d38f55e9af870f6c60ab49c80d7d1ad1f18f1a34893fd2892d49c315ee668c431f5f35e3f60ecfd534b4b09b64cc77cd16b0e1b8882872cd109a5ca377518e5b660d75052e9a4228e3935705b6bf6b4f4249346b7bf4afb891641a76621cd315cd75de391c898959be945ccca7a96073f2569f217617b08502f7d569bd2f80e0 +AD: 3f1e297bd91a276a4a4b613add617b0488414a57ede2ac75d10934e03be58ec518a418e98a4dbb39d2365889db7c5f389b2a16d8c702cf21b888a4cbf77b356df48a30298c825fb86128de45d7fa0e5f4b0b7bf82a2c4cad2470f33c231802263901fbda54a6edbf2df638716492157ec1407e7fc2eb6c663d9a215afbec3612778b8115e78a5fd68cf6ce66c12c0ca26e5c1f7ab079bc09c3bc7b673d21835671a13dd2a0 +CT: 9a5758dad7997a766db05d698b43fd491bdcec21352032cc023bcf10e136523219745a56f0360efee75a37de55da23cc7d8184a50ccebb110bcb960dcf6b25fe731e21f26290281d9c1c7715c4e6ff3dc0026cce52929163ba222f123d4f50e1d3cf67725fb4737f4010ee2b5b163ca6251c50efe05c5ab0b1ff57b97ffa24c98653f5c82690d40c791047a3d5e553a0142fa2f4346cfcd1c849a9647885c0daaac9efe222 +TAG: 5b85501a476217f100be680b2f5882cb + +KEY: a26c0e3864a7dd3b589d17a74a7c9c1f7e8f9adb4aafa0e75c083d10956b6bf6 +NONCE: b54a2a43ca3f84aef3824375 +IN: 6fd4ec60613646490791d82de30ded1a12e61fd270f1642d2221272dbb150ef63ef2604213e203b740dfc9c4bcdf722b3c85aa20abb1197949de710d7e8311956c8649524afc72a9bf5eddf0b284c7fc6d48a741b82c215a0dcd73bb8afd08d5532a6f7f99b5c6beb2ad793d6da53a81e6523b2240729924ddac996a723421f57125f928990daa7a55a5b6b53d7361d9728f66590d969659aacd9aa5c0ec627d991b55e9fd0bf9c3210f +AD: d6d8b570eca29a48a4d408d5b27ec6aec291d70cfefcd02bbfe8d8ba8aeb6db770bfd723d2c3a4859f1992767d24e7b33e3e241874292af640e2bd22a5b77e0e9e1e0d5e485041cac41d4694ac929ae1fbc08e7591e1cef689028f5db26f95fc9e0868887fb9c635579fc6335757697f63b4f2b46664ae338eafdd827988c8f2ebad80ea9787871ed8d6b302d5dbf7e8019f2e139c59036cb5964a3701ec049b839e19e33e68b83539c8 +CT: 2420e09adb24098038b2750c946551a5f6a5bdf23b126947348ddb5e938b3fcb874b33fbac6407095e05ce62df999e7234cd2b4e413009c71d855b23993cd58c1e26ba0deed891dc88f099fdf852cec0aab45f488a90edd8feb6f4c837036945bd304edbf7a2737921a2f8c1b00a1daaf9e25b908a65a8f69963fc767bc975b5b7bcc215ce37009009dc90b5c7edb1a1174a10ad28f4c1d1a2241e7ffc215edef4f847ceedf7b64f2d15 +TAG: 20521b35310385ae66557740b435d204 + +KEY: 53ef3dc7a10e435650dd20550cf3ec2b997afc8d9e79cca8f7062622afac3496 +NONCE: 257a205ed0f84016183f4613 +IN: 081e2769935f945419aa06fb5fa7d8412efd1f9b52a45863808022850836c1974d53d2b2c5c0cd420711a71e6d1a09e984366b8b677e6c61bbce8f3adf9f5a9fb5860887617a08c923171d681c4fbc6d569690f6a183d42b52a80ef0693862efd22bf83b7b4014a7008424c356b5022df1842309b3a4a2caee0fd3f4d3fc52a17d53959daccf8e0ca889578ee2905dd8c17d52e76712dc104344148e8184c82af8165ea8386f91de585b54fc8535c3 +AD: 5b73ae02bf4a70e57f5d48fbf45f85b8496ae8514c8aeb779c184f9cf823d8c1883c9e5a42b2c099d959c2298ace2d86c4479059256d6a4325e109fa4b6c4ce90f84a8228316e80aa86de9b5e111d88b2be447a29297b35ca90a8eb280d4c0fe92a1d593cb966cb0010bc06831efb0c72c1e222b031e900ef06ab8da542a5abe2870a0efbe92351d5915ab545b14900e41a27c5ca9d75d6277afafe7ae861131c2767eb314c0c3da5c264f8f2b4ac7 +CT: 20ecb6cda861b660656d692c626436227bd4ac17a9bc71f6c84a1917ef3b5a0f6ba370f00fa2e7f1bd5aa8d6c15032572090482c23e4ab7376ef1f4dfb77f79d5dc065792fe3476c9c37614e32f493e461981b519dd7d10234c2c69264ffe5be06a8e14c81022b652c8cfa24adcc7c7536a55a2fc41e9ffcd09e1c483541cba814eafd5e09e9e44477018a41b073e387c9257c07d97e40f0761fe295d015e1f2df5be65b13f34b6ef0fe1b109ad109 +TAG: c129ba4c10bc9e9c2b7d67f5f249d971 + +KEY: 15ddf0d794b1bf2e67db1af47b45b8abb0c62ff5fe09b29659f63ff943815c39 +NONCE: a6e6b4fd129bee3ab8144da1 +IN: 9c82ac83e3dd227d0cb9692703dbf41292fbaf4961e28b7407ef069e33850371ce2838b1808ec1f837511dae9899a867959183ef3d988ac20758d7a1a6859cedf687d8a42f3dd53fa4b5843e5be61422fb8774c9eb0fd22cbda5950155caa0ceaa00417f1e89a863fcc08cbf911776fbea8d7c14a6d819c070c9abe76a7f0d04598188d07fcbb822758081172e654c025703bb24c523cee2dfdc31c8d2c84534a60e7efa9f52f7e74e19c859889f9bd024f28763 +AD: 892bc04375e9ad5ad2b5c117d1aacc202a74ee4cd4125019f38ed4d716ce361b8b50463ec3255a00670f5f95d361e79349e90bfccbf084586cb5fa145b9eece8a10187c13055ba0d17c0fa526ba7985f00f3eb4a2cd53b6da488827fa8481cf47f6be58771d1e40125652732a7dd5adc49cf99ed6b085fa9fe8721c86f7241b6efb6002e65ae5f72e16ce6a09ce81365485b20f1fc2e092216024b1acd0bb4c2b4ffe28d62a9a813fcc389774688eedd76c0b041 +CT: e30465518e7dab44b9ca4ab6c86fd7b701e334b050a7889fefd08aa12c9e381acc7875ad5f8574fa44f8550bfc820b6d9a5600cfb82d1f98721a875610a91c8f47960ea64445c0e22fd3ebe94b3564e98b9b00a68e9bd941eef5382a67782c5e24ac44b928fc986c62a02fc702b145843b1c6882188dcbbb6f6b51ce1aa7784da03cbdc3efb1a01c1cfd7e90dc3332fc6e912a6a967ef1f239cfdc9752e235dfe75dab8088f8cc207a4a28994f122859aeb52d01 +TAG: 62e7455cd6b95319efa3ae0d14b88452 + +KEY: dc0cff51030582f29676482ec8dbf0490a135a4cf3e444edfb7d1ec733cdf7b9 +NONCE: 58c892d618ceb6027afbabb9 +IN: d6c4d49a9431d51bfda5bd4b07997690748fdc3df196d27d219a62480dfcb6300c5a234d675aec1239280446cc134bd4e0e0b5ebf6f10bb11b788caf949c0c3553497b62e729f08700b66c6720c35f1f434f16b15a4e404d627fd054ae1394a77d5ba728f3422aad5d99a608c2aa52b058946a76a408c5dfb210d280629ac999e86ab1f9da8f2b7b79ec07cb666105582564974180ace98c63bdb962e4580692abe58929d29f066d2f7e25c23a3824483d9e49cb6f5fc4a1b0 +AD: ee3bc8d875a4d43c278cfeefed8ced8a3da946adaef93dc356001da151010548990fe08b62edda46634db320601c7f4b50956e29868bda9ae5df186f15c3ab4a19d7cec274209cecc71602e45c37c273b7e4b2a168de5c29278042a3dd1fbea0998d7d9707d412f476ac8de7936e2e5c268a2f22646f682e664e526f88004e7c461bd42337dd21b1cb39ff678974adb67c2ea1b7055ca98697ec16c4b3bfa95b4dcbd7fb015480135634c34acb20f58549f7e7e11e20a991a1 +CT: 54eedf8ca21f31d21067af5a05dc3cb99c3dc046540d2cd1664abb32fc7714ac057d039cebdeb124e1ca9511bc71f92ddfd4c6bd3edc8a1934f2fa2511503944f2a0818e30b9bdd26bd3c51b9673f55ad3f2ee5e41de114ccc55abcdce06a5bcf63a5bd61fe71dbbfc97e1c7f3417fcb9c1462e244ad91725081c9176a0b91d3485400d273a16eecd870ec1e9e016a7f4af2fab39a0bc93576ffd1eeef9cc15b7e47feaef85b21de422666ec722cbaef26edd1941e7dc03f72 +TAG: 1cc8c395b2ccae3a685183667ee7bd34 + +KEY: 90da49f8f64e8a585697a43644a48bcbef33a8ed23c1a93c65e59a217c04a1e0 +NONCE: 0812f87792508dee6868d454 +IN: 26dac57d9f30bae5831f98ed074cbc9af9731a52b2322cdd23f1f0abbf78092c48d6d24a43c7d49edb3fa66086030f37dd9dc67847714437b11577d2bec645b3210baa8f7a540cbfc20deec5973b7489b7607eafe72e249df5d0fed95e29f03cf7f0c7a22fb2f06a0bc75214446b06d25a45ab8087270eec56af3960f53b80412a4ea7b45e54a2c374e8a3789e8eb57e656e22107503920313ee3e4025836b9e1a98541446c23bd5674cb83483642f2f3e8270bd1f77c85bcfb205a9133c +AD: f2168cef97c27a902d93cbca07b03f35c5c3ed934192d29a743c3a6c480c5a62172c088fc89cb2d8651b8979e5bd1864272ff179be8003c6dee18789c17583dc1de4e8b4fec80e5c7575838e621cac4b5b51ce5952f22e06b1c196101d2ac8d05e797323e5baacc49d1e74db97142e1bed723d46ab858d59fd36d5d08eaa63f696b610eebdc9662e504992fd3481de1264bcac8ac426b09fbc641ebc93f72c5d460088fe0b08420d88fae219b6a5a67420a5f9d1201bf8d64b2ab3e9050a +CT: 82196d89624689bb172e4ff71619046a91149c8ea99ebbaa3f2c32c77938b5ac466481575dd82a008c7f5867bc46ee44faf95fa40b6237c8c3b62474af2efcf07c771e23a63e65b48b0bd8ed26fc64dffe03e71fac6d3857b1248df63d888567d7d3618c68d6b8f1c88029bd7af8677d3b51f70ccccb4eec9e100768515637ad8a4b2e2e317902e456974ce9fe23095cc68566e85cd913e8b64119444f124640d16ef3e98136f32d618eef78f7ffbafb64227b3185bda8f541c0e7ee8405 +TAG: 71fffdbd6358f755dd22f1dbe42c4aca + +KEY: 0b1b256665284390a9193b7b7aa4e3ad15a3d2a58e79d75da8ec284c02fa3a2f +NONCE: 346ae65660de8920605fe8d1 +IN: acfa83f56f137ac39d6447d98c5f7d5e812d1d8e7c7fa7f7beea9a87c59961449683fcf5332c9ef1587135030309a1c2d95257114b790b18cc32f65f4c7d1652c0106e3331f826e9b8b0dffc50aa6723d0827076b71c668370ddc8156db3831559a72e48266b3886a6d88318e6ca646ff561ed4f71e665abb7a60089f0a115c7b7fad9cbba6c4cb0c242b9e1f17705825d98f4bc10bacd8ab2e11cf579f29b2a0b085d8c96a372434785856b483c3fc9ae909029b0c931098d7e59f233cb6450fe0b0d +AD: 64347fc132379d39cf142ca81d7e49c010f54f354ca3365d5195a7e43175c9a47603062c5ca61aaf2b381f5cd538bbf48f50d620ff2b5980c086049a378aca69570ab7c406b510a6aa6b7e8682ade6a091b1f822a97ce671fcf7c911c43c4795b78ce1c86e990e32bc5c9fa34a8a4b22a20d6f7c46722d1bafd49443b4da9634db4615f7cabc3d5bd9a8921e67de45dac261f54bcd0af2b2f845e255a16f2d2f1ffe26e88238f5dbdbe111393aab3409e08dee8b9bc85c51b385c191ee9290454236ab +CT: 9d7421330f0c2a525495bc360cd5c2273531d050d461336a254c9af8611d07c3559931cd6804fbdc6e6c9c997283cf40bc23596efd1bf116fffcc6620e45d1c738569af012a7ed0d575ace3c12662f88f3ee480af30ee015ae70db112bf4a185e220660a912f9ad840346e7cc0715e853dcd9b415ca9e865d5e4de2321e6a1b7cd8a35c760abd3f099d395576a91503147bdd51cb4bd1452c4043b42dd526de6f61bcbe819cfa3c122c6f62e0d4c38b443f5a138325a5f0ff8a9a2071c2773ce62edda +TAG: 2af508d74bcf8157ae9c55b28b5d2db9 + +KEY: c055bfc7828d9fe8fa8d9851d33f3e4888e0f7e286e1eed455e14832369f26fa +NONCE: 2804e5ec079eada8bb3946e4 +IN: a26a9b189ada0ccafab92a79711360c7c396374c6170de395bd8ed80dc5db96ef1534adc4dcd419fdf1801add1444a195367213e374eb1ab093f1f54cd82eaba5c1cde6b867e0d8fff99cdab4d96e69aee0c58a64120ce0cfd923f15cdf65076a12e06e53ab37463096d9ccb11ec654e401c24309fda7afa45ee26e5e4b8adc8febbddaff1e7cecacad1d825a6b16a115287b4b3c9f8a29b30fa6236ca6e883abda412177af38b93e0e64b012d33d7bf52ed18c4219bdf07f36151b7ea4c53091ddfe58b6c9beeca +AD: a184e4811d5565849a08d0b312f009143ac954d426ca8d563ad47550688c82dbddc1edbdea672f3a94a3c145676de66085ded7bcf356c5b7e798f5ab3bb3a11bd63c485fbcded50c3b31f914d020840cbc936c24e0b3245fead8c2f0f3e10b165d5f9c3f6be8f8d9e99b97efda5c6722051d5b81a343a7d107e30d9319c94dbc7c31c23b06a4ae948f276d0eabd050394c05781712b879317ac03eb7752462f048bcd0dccb5440f6740ad0a3a4c742c3da32a49dfda82ed1b66380a8cfd09dda73178ffa49236d20 +CT: 58dca29b5008f74bf132947df768dc85e2492a381429f151a3bad3132e63a4a977aa09f10879d206f43f27a26909495d0a2c8cb252fbcb3abd953f6e0ef0f6d5e89d89a1d9ecdb0e44686fbf5567a6fe7557a084a8a5ef5316890917bc432164266a331118c828fad4f5d1776645d163dc5444c2e12def608efb47adeb8f9928a5ffd3c46f963a749c310688e78525e34a510f529472a14bc7a5b65594338f6f5ea1d95bb5bddc6e8e1d1a449d126442accd162e4e03c10824fd48b32df763de5d7700dafc54206b +TAG: 141c80e1d044e1e9cf1c217bd881589c + +KEY: a54a347a7a388c2e0661d4ae1b5743d1c2f9116c0a7aa2d6c778a21e2bf691a9 +NONCE: bd3456b0dd0e971451627522 +IN: 3d17e3d9b5020d51295f7bd72e524027e763b94e045755af4b3cc4f86bce632a1286f71734e051dbcac95780b9817b5f1b272c419e6bc00d90c27496ac5ab8a65d63c2ea16eeeebe4b06457e66beeed20fc8d23a9b844ba2cc3eb3d87e16e1230fdb6a9134bad3e42eadccd49baed5e03e055f389a488d939c276982e4bc77f0a1c738fcdee222e2641b06fe12ed63ede2ab2fee3c54d7901d0911c32980b7c663a67d35ece23136c77f8e4536464225ab427d937e7a4260460d55bb5fdd7ea2f105604c4b0cf129dec49b81b1 +AD: c12d1ffb08acf27d51e63f5c0e311180b687438e825204074d4456d70b7c5ba9903ad0b0778a5fe36c3e12e82718c00f5d1ce585e5c73b23d6c5e41ac4a180c97c9418b07ccccbfc58c678e97882ea36395c0a05572b4cd25ddb3c32fa580c89c48a0e3066b8032e3823893a5721a4fd1e59c7d012a01b9e9afc12f3bea93e9d1a2cf5cab26e064576b36bb65606de62fe2887ace0cf399dec08da618954ce55362c8a2bcf31457a1804bbfff68a76d752f9aea81be8868bbca8f1af3375f7137941a1924b8a2b178f06a9e33f +CT: 938f8f596e17eae6920410f602c805ad9715833087e1d543eb20b1b313771266dc6a8f86f2ba033609fadec92ac38c1f1f0f728e568fe8bcecbae2ade7b9c4128fb3133c8b4107ad5c29cacbd5937f66905e18cc52d9239c14e4c8edbb2db89b26f5f4a9ff0f2045192fd212af6c65e448834580deb8787b612d6345466483dbec00b03fee4751f543a6155f2dbb745c1094e9721aea3e544a894e4a19a14645725cb8fdc21d259e086b1e411fb1bdb11293d0224ada25da2896dfe0d35095230af6894404d27d901540b0ec35 +TAG: c55c870a5eac5c0c774dd10dbadd3fec + +KEY: b262f6a609c4ad6da3710d58530b634fd7bed875956d426bf4b2412209902233 +NONCE: 0b455031d28e4e17a45b7a60 +IN: 9cff6ec8832bd0e62d9063e43821db6a1e0f3ae7947ab4d029643b0e7db8224f8bd00a2c011b246a4d5eccf9801fb314aeadc0532fa71cffe188e801d7c045e81b9dfc5cf6ae1e310b363adec4e7ca52fa754ece2540545a5161eaf9ed5748070b6e232125fa8e0fb7548fd3eed57a6be72ce0a9112f166776816a0a4ccf8151b6b93780875d03ea3d59ac57e7904c83b90b7666de85f055b25f9e342af4cb04b0c3f123ea0906c04f252f2b16b28d612e37b2a7b788d66beb8b361385efb73a825ccfb1a5ca55d60afde0349e5dad8096c7 +AD: fb99bc661b51464c0df92ba4f64c4c56d601622287bb1bf8e0a082ed3793e74db6a2f5a546391ef55dc45fd2f24878834bdc2903054d9d02ac05bd5ff122b65555d7ab1664cc36b630039e4432315445f303837e57149fdf6bf8d6856ba97abc5a18b6cd2f8f28cd3ac079355b314561c50126812861c39180fd94f9aa24edbec37bead760093d32b96ce30e389f63b2b271fc051b42952b3f5cf3950def581f7cbb2b4aa5b151a16ed3773166761232c106d3ff57851895640ea12befd69daadecc4122b4a481e85088edb093e02d5d3d8a +CT: 5341e8c7e67303d5374e3f5693c28dd9f9a5c9368efaaf82d900b4a4ab44337f7d53364544bbd822020d79443e2ab0fd2381bc73750203caa3d28858a8f9a6dba57a7c5248361ebb152a81a89c00b1bf49de9e2d08c0243b38eefe316ef89164b4907515f340468291e0b51009c9d80cf5a998d9cd8fce41d0c7405fc2d1854aae873f0e24cfad253ee07d9f4cd27080ee8ec85d787459080a06d290e6e721d23738470835f173ed815f1a15f293ffe95ad973210486372e19a9cc737c73928572cbc03f64201d1b6fd23ebb7b49d12f2eef +TAG: 5e0ac1993ceccc89d44cfa37bb319d1c + +KEY: 9b4387e01c03d2e039a44ca2991aa8557dea6179d19259d819d70ab2d5179eb0 +NONCE: 852124b4e04d7d1d63743d74 +IN: 92c6f01cd2cd959495bd8aca704f948060bee01ca61c46005b4db43e2e7655af4c0d96656cd75d904325ecc325f5fc9a5fff3eeafde6f81323b0e3b64269028cb64c9fbe866b400e76487f1759d6ab8fc66589e23df0c008974e1613bb4ec556bd1a6a0751f6dbbbaeff219874c57dffca59a955e0aae62e8fd6a904a50fa7eaacccc6dfd4a2b8c6c040505d3448ed2217b7024224bbc4335c63b2ae8172d7d3088b819edbaa17991a4729bcd5a456cad20ba20dbee99ae56f8ef669dff93c99a995c8f5dcb5d113db4178a49516206a1cba7d872682b1 +AD: 92a1d2574182f850e37aa62338b19f403fe99dbc7ddbe1e6524ac67c4092cfe296b5ee9b94eddb5c228c902c18ec1ec26e1ef0263d05c5caf1c71ed9e5ff987e9964b46f27be05a83e20867f1f2107db26b6bc7066af2b0efdcad2b65f2ebe8b31fbe2f3c30171f2e4969f1650c9642ae47c8db5bda47e57e8a9af210a6fd4894dcc2934b4ecf823cc841cdb3c93ecc779b455b8cc796d7d60437da201c3f848dcd5f45e88973e06364e7cd01afd2d49fd3032550f1c1a60c4ba48137398f4d58e5fd0093c06042b103ce0064f2cd1cfdd39b7440121d7 +CT: 28b87d324854d5c9c6ebb303fb802b12d946ed681ed5b3384dce2cd782bfbd022f213f193bcac579176440bbf2af378b019d21dde5d70e42d257722d15417a9fecc8e56430551ea3bee798a01faf74d0fb09be6dd0c14cd03feaae29c7d17581e1fda0b4bce632ef790202e98c8c4f8f842fb3e33b3fa5e8700c8644ed6d64280652bc2a5d40b3ee0e47dd5a9f3535e15b1fabb30264515afd4f9b1caa5c224574636935baebf6d1992bf1a7a3d698d457db4248a2b38a803837ac4fab7998722d52de61bfab4f98e1933a77046bfb3941bb7988acebce +TAG: 1b07d58be48b81f7007e5683b399dc28 + +KEY: 9d36155d429b90b5ff22ded128c9f0cfe77ed514d410998091bfca4dce7e3c88 +NONCE: a7b73ba1b2b0e846c3f635aa +IN: 2510210b420b12300d51ee4a7ad233c9c97d71672c0f9a7b9041d32172fdf3a6ce274aca77a0db6961d7921d1681ede2c1088a7618382481296778e7f56d2c0074c7c545ccda313495ae2a6dfd042474b07d2b59c79a0cd8c3dc16132beff1687111a48ee3d291ac556987e73c5a3807923c2deb3b9a59a135a8fa0d85d5b39016edfe0649dc13be672a639db58839d3362eaeca046767fa1182ef8a63abc104e7cdc8610b1e956aac89af76b40844a358fe6f7343d217e1838aad19587ab4b1c765d2cd7bf7018e338c0207d4c9dabdb1625af0c75749e9a20a0d8d +AD: 39e96c8d824bee306189a3bc8a8d4862df55e8016726222a528d76de169746a363e82e82e359b774d061a6e98e3c35aca8ba802a5956a2c512501fed44ae341cfa65ec9d95485763d99cbd9aea078ce551f7f82272bf54dfb6420ae7653f275ef145b2c87720c9ccfa56bd286c61cb822d0473dc2cc3fa22d50fd16bc0358e7c615aa1791b990f30b1d737f798219f4446d173e80fa62380dfdfebdb36b1284a62c2b6638f28fc370034812d09b57d27e5b7d589075bbab42fcd6a91fa2714538be6286e4c7b2657b80f045df7f8954738efa7d49a38e5a55a2af934 +CT: 8cb991b10218bfefa522e2f808dc973620ea391623947cb260b852efd28939ccca4c8b1f02d66fd6d0d7058854fac028fa0f23e8de801ed9a4361bf7e5a23e6a7086624a64a29815bedd5e5ebe4d9f9386d47e1408286971654b38ff8e5dd1fef7686d7614ef01900ad33bf97896b4ad02e7445782b1794b45af967ca3ba72a2e5cd5252a9ff0ff550ee56fdd8aa555bbb0bf8a5dd534fd65b13235fa6650761dfe2a28b2757077a2680ef88c84eaada743d1f0d25de38fdd1974ffc07dbb9c7fa67cacca309a10753c6e2561c4784470f5c7e116e12070fb3d87131 +TAG: 665fe87506f8df07d173fedcc401d18b + +KEY: bd187500219308edd6ac7340d72813ee20054d6d4b1bc2ebcde466046e96a255 +NONCE: aab93d3181e7a04cedf17031 +IN: 55b824816e045702526f8b5def71a0d023a2e42257fc1e06f9a8531ef9f7717474ba4f469e442b471d5da6e71aa635a307205c0a935a54b8a59be8856144dec435e29aa1a3568073aa6bd3439bc0f219fa1179ba0a316f7d966ea379da16be4db2f1fdac2fa6d00bef9351b78bb2773bc30ddc9d019e6e7d78dfaf38010080027afac33e751c0429ef6c70a1f2d01f103482818e9353e39a3a4b785a7dd2c7e1ba7a4c36a5f3836d5465c002bcd1ac576d90ad276952ac155dabba6873e6d92b5278280a540071b205ba99b77b7568862e70e6ddbd804906c33fa130f8b0862001 +AD: 11b35743bbcd0113d2c188f75d382df44e874a2d4b3c3148ecf8e0406479305f29197a3a71dc7bcd71b6136ab11a7cf46de80140e15046acfa18774cbcc755e9f3beb37202fc308c03b1c20470b3128f5b91d925bd6703dfb3277d65159688f656d5ccd83d2beadfd778854472b1cb8fe440bdb7efe806f4cb95249cddf69fa0013dc5a626eb8ab69a48b3ddb1a317b35f7772f711221cee1cee9469e2639c44448c5942c95324dc2fcfdc952e05aa336ddbaf57cec2d1b33981ecb8f70ccd34a279b211c50a7784906f2981a2d2ad8fb130100c4f6bdb09c95dfcf4b0eb7ac6d5 +CT: 1e99d06f82333ec8e4fa1e81014458c81325e5d69db561449b153727da35c0b540c570b60488aca6aae58f75f84792388d0160dc45e4e5bef552c49228d806fcc22259f0f94da2f786cc94a3ecf3cc15ac67719379d86abaa54ce41e868110ed2b56dbeeaad4a444eab51a96aed404a4f4b9677d22345fdb67ed0df091d23d8acd70bf6cd29f19c99910888b3281b65637590af984e493ac70011486ca88e72fd14ef1cba06a50070f138dfaed35ab12690a14b1c8ac319f597bb690cae28019d64c868acf9a58fde1d8aa18dc1ec9c3c4a0ee9c4cfff8912b1bf23c805af6df48 +TAG: 1a43147e6e097a46b61f8b05c7dbbe1b + +KEY: ce53e967bb4675a51652a9e6e87da6be36d16245c1e37ee00bae09cc30ed8528 +NONCE: 0f53ed18bfdd28918c3993d9 +IN: 3f2416477ff2ce7da3e5766f043e7a06ea2b87fdf06320d296c71cbaec4b115da356f8c7f34220f91e90c97a5cbbb7fcf0048fb89414eddeb2ec1062d08cc75a39a1f9f214fc3efd6fc8e70d78418007d7d28944b3f37fa5667ff79098d7af36a9324419b53efa76e98a311e1436ecedd977397cd02cc8d377ea8558edca35ff4c71ec31943119b76af4c78a435033eafe73c7079224bf2328b49ed58acef9b043ae3c7ff17a66b521e190d6ca2b2835ed8edc2c173f04616af237391a4440fc5306366c834f6a504e902dca6d3e9e1554088eaf5b15db7fc1fa19f0867ece90ded639ee8072 +AD: 64a596ffca0889833fcb537f58d94791f9ba9b6b7ce0c7f144f2f1a95d62ce334f7bf7f0d2ef0c6e7afa2324b069dc6a7a522f19a001c335cc0252ac4a26079c3f267cdca1e3f933069f52fe72e1a00c83d8fcbd2e76149a912c7b37663c2e7967a3a80656c87094d349af6b9d64b3873f467ed376eaa1e0abae06180c847e981c6a12d32b580acd34f779c343f8b79df1b5004d333a5c37a8be7a94c6f6400f819ffbe6d54d3c1a92824fb15c279fc8121c735b6c42248ee22e665245966d40eadc51f12904cd64110d69354cc9d9fc415b3469317d5e4643942dd4b649de0ee2fc5d200701 +CT: be462da8cc9d8cdf343f7025df0b8b41c24f7b6060cea2d3c63338b6c3e83f0797e966b8c5dd889bf1b5058fb4d694be2178fb33d9be1a351812046a6d3bd36c84ee3665d39fb98159e4d30f8a25a60064caf980f744fc519e2dc451f5fbcc0834b72920d32f0492abedc1022b0db4f2f44b91ec48c588334775fac91f174a4714b3825e96fa53cad3de94807f3b888950c8776189cc18fdf379cdc9d6054952c6ed2b3fb7f6b49beebacee7ddcb19a3eaee2b2e2b7a5d6476e5fc1f216ca443b859a9a661dcf2f7709f87361186368a62f255d78150f09ad4ab1a20e7329f3d96fa2a33cbf6 +TAG: 1cf74908f6fbfa5b2b309ebeff2f3ad1 + +KEY: 093d932ed969cfae63f07e0c04c7f9eaf1b36f656095f8d5f112517dfc430cdc +NONCE: ce36a837ae93a280d2fffc63 +IN: d9da99635f8d728843dd587cbb24e68e1df2f81b5f7abfe233a224cdbd48cd8b82da3711d2ab6c1ca722610b87f426a2cdee4456b50781e3b25da037ca636f2a5eea01f4eeea52d0feb7f1f6c2594d63d8c05c2adf339839449cb1d2aca94852d1b64b5641a572c2da02ebe299c7d1ff4da8706f44b14602f44c0ced711fc78005f87b1686106250d3d3860b67f5b38788db1891150f88d4c5276751afa0b2e37a59587cd8b718767455e65eef25bddaf787d52b88556710f740f117b02f244edd47cf0e45646d40e789671ae61ab06336e24fad8b64cd8f60b427ea1f58af443c6f55d54028edd5f40d78 +AD: 5e9c95c3449cee3f9f726be031089b2358ee92fe7b408b355739c8da6369304f3b287ca60dde4685bdc59879e1530ffd8f6589449196abf0f0dc6dcd82ba7fba481f13376cf29b32af2ecca24a161e6e57b6db70a7e02ee2154cc0bb5280b08f8dca35b1a342fa18b8025c7a805cebaed99e30b43c139de7c37adc25b0b6b5d873ed86530622ef2d0ed3ab19e9c27df98a4a15324f902c35a23adcad4598c6e990c64893355be15fa7320c1935b4ad3c069c068d6b3c8f43d6fe0588b59170bf567ac3a53a50db68e4be17964f55acfe695638cb5fdea5c40805334a385c2d35aa836637ccdf71390487d9 +CT: 40380718f069f44c88932af22a10f80513821caa71fd7a9e5c4f37e1c756c43fe491ac13f244bd1299844cc78d7812110f570b693e63614e639ec7395cf65c206eb6fc9bba86f89d03dd19e45d5ec64c7d3a308ced4ac1f59cf4e13be64e49acd9ebee209afc508c97ac817f1367629af9d59b0cd48f138d23abb61f92dac530351f46a4e7f70ac87388e44f6e9548d3e6a26884bb7611f632da7db2a12fd9174773e685df316ea9401d8b352135b6b32a374eef8661b77eeedc34fa4178d0a5731ac9bfc14bce1dfe96af095b0088371ab1a04b2062625f0c4fdf01fc0a6bbf1661cca11932e93690501a +TAG: ef7f960b146747ba4f25c705d942f8c7 + +KEY: 86875efa72ec1827f133a8935193292463ecef801bf3b461c96b0312cfcf32e1 +NONCE: 738136465c8935d77c8d4ea4 +IN: d692d3ef47a5c9d0d9a3b6a0d498e90a3ea06278134ce90cc1d69da2159d9a1f5d0a9ef4b4ce5f873e26e8f9d53ced79991491325ba5511be4d9e6563b70459b10e60d8c5da45d3b0b34dad86772b0560314f0215bef7b55c6ae53999cb2d6a14a35b50fe5a1598adb7ebeee097968ee7624bde42862824900c8cb45b12785d9c4d50ef38133d31a66a612d8638008d03edd19c4d7edb5f9b9f195c60883a7d6aa85bc3ca3b59c395b85dbe9bb30ef6896c4ebae8d72cbecfadfa451bf36631aefddd3feb36978aa8d9a45c9fa09bfa0b2c040d9a422840e68f4dcc3eb902f6be1d91b11e1749183d89715761b6cf22c +AD: 17208cfe5a96adf0ec903c7618d994492d3eb77275fe5bfce5ab1f67d27431c7746314e52934b8c44481e5760cc8f6b0e17d1fcac7fd5b476196e3152c3dc90adeb58c2c9c62cd684b4b18d4a94f8e5b4336ed3f1758b58a254f48b3aecd9cfa63cf758f2df54c52eb246d046198b6eabc90b2a0dd6c5323e915a117235174fc9089cc9bcb1a3bb49080cbcc24367e7f4e17e27a2054bdda0ad8996df1cfc6bcf43f70cd854f4d97aaa4badb5826dd86765d36a2ecc83d3daaf31594eff02999a423185356d693f26025a576037336c156543353423dd3b5da75f45e297c60dd8e091b961f60eb6786fc988f6324f9e8 +CT: 55f48dc2b6836b8603e19264382ddfc568b1bf06e678de255d355fd865ef03339f644312c4372494386589431d4ae7af2eaee5dd3c16340ecae3e87dda9220a5f9b9fe6cc3eaa226d9608385b7e8a6216e7da71997088eaf7c67b5402be01c0b182383ed3c0e72e91fc51fc99c59cc8271660dd7a59ee0e7d9626ccd4439bb9a1499c71492807f8126891ce09451d07d9c5525c5f185559ec44aa31498be3fc574389cf948640dcc37d0b122249060bb7d5d7e5194d4b7a7bb64d98d82a1155e30970a854f7c0d294fbb1a9e058f3b9f4762972c21086e0bf228768d0d879a9cdb110f9e3a172feca7417d48b3fa0b0b +TAG: e588a9849c6b7556b2f9068d5f9ead57 + +KEY: e9467b3a75dde39b0dd44e7cbf2b70ba1757ba6a2f70cc233d5258e321d5b3ad +NONCE: a9756c7b8e2e2f4e0459f1bb +IN: d6d7f6112947be12e7ec8d27ce02924503f548456d0ba407bf23e848b9ecc310e4a0c7b00c0de141777a94cb4b84a5cc34b2b05c8a37cda08b6c2dba80e80853f2a18bcc41341a719f84262b601610a93721f638a8ca651a2f6c03c3cf1070f32b92c4ab7a4982a8f5e8ae70800f7513405f3ae28ba97a9ce8241608eeb5351e6cef5560c4209790ee528b3876896846e013a0bd3a1aa89edaefe08fb4b73b3fa64c0c8b0f7ab70653ee138456319230174f0f1f7f3477f0cfc80eab8a96e29e85e20658cebb830ba216b1d8281ce499f729278dcfeb59cde3a043ef3fe2c42705f311a422e9f80fc3b58ca849dd4b99e5e66a958c +AD: ccab7afe4d320e94f77963d779ade1343e66ae80446eaa5f9ec4d3e3bb3166255e4aac5707ab407b284dfcdbb18ff515cf08790f0470cf335946040438c7de2d2a342096d7607e1920d86b519e96cec1715f4b0dfe375c5959644bd664d23d879b825dffbbdc458ea9da5ede5682ce1ad1cff33dd8820761b1c067cec638873a3cae79c7682ee8d4f97cb96a413dbbded1c242ca669d50ebb6de3c27eca3041fa8aee8974c3d17b0cf79c32c7bbfe20dcfd57303cc40334fbdc43e925df1d63fde57bf60553d7790fc56bd95e675db934dabb1125eb97cded95f397b32bfb3a2d40703e3f11c6c226633b3cb7f9da1e3367de2ba4d +CT: 47bb258ddc0945079a0b99ed5cdc0186f453f8e0393cfea258412e423dde4a00c014ac298c4dfe7c03b0d9bbd4ad189624cb6fbaf13e60ec2b4d83c5bc3294dfec30bd6c8f7125e11d7be145a966dfd78fd77af68099b855989fe077cd9f427d4381b4930abc1daae55722540e4bcbe1b560fde208ef1c2dfcaa2c51b76072e67da311c2556eaa2c25413bfc43d00dd84aa8859b296e05945683e028699d60a29227de1363c4138b9ec2db8f3b502fe09d368c5f2ffd81abe50cc1ec1ef216f27f401456d061429d1910623af00bcf500cbc6509c5aebf7de9c956e40a3f0b0d562775b03c282c204e33c0b380ce1475eb5c0441f6 +TAG: 9ea19333f5050354a7937fed68e38dd4 + +KEY: 4e323dedb68bb5cc4cf2edfe3a54a19b410f849492ed6f66fc053d8903c3d766 +NONCE: f77b876eff796db621eabe88 +IN: a7514c4111d7d8bce2d56faee25d9f5fbb527162576b444fadebf42d48d2631cfed344b0437ce8a7609bf30bf0a44aef172f8b12ea7567cfa5dccbd08bb3115efec59437ff02e7128df9d9e5193794373e30dff7b3d8ec0fcd6cd3872d755c0314f1cd9cb996e4c6ca8ee2e35f9b64a1f0bd1669369f9b333a356ba58e553ff9bf9cb6c5522599dccca2f7f57a91006e7dca4095d11955e5aabff69febb98a408aee92293c0abc12ff23482ebe9d541bf8fc7493eef2c68044dd185eb243b54a2bad9844d831d9b0766a0ef013ad3ac03627b1feeb287e5e61875bb1d0a01315761bae6323a9d678cdcd3c4a85be71b70213d081b348c63fc603 +AD: 9bd10dc97ab5e9b35e1c8c36ef37f90a11bae7dd18af436fa8b283eafe04a5bbb16bede6ce1260187299ae6474628e706cc08b3627f5243f1a9ab469455666e6d5f2ab597b6799bd60a365a9248341decc36d473fa52ac5ac469b965cb2023d43b437dded84ad49de95a6dfc6ae4bbefaf86f9b06e3a33ec90d32ea3af541fd2c43387c75dbd94d44b9582e8ea41afba5e49f1d158d48e979d04888fbd42876e12bfd6695cb99640c537f2f9223d37cf6b627207b9318bd1f4c64556b5db1101c486c53dd8dccd7405e148d6d9b38b7ac875a44bd6df75edfa4da8594a9c43b223e7a6f5b81a5cb8dd6e06e9a976ef156e45520af332e4d56035 +CT: 9885d7a11004ec546955fb7a8c77ae57588fa2e7fedcc8e9000123495b9016d1a101fec1e6724302e93eb8e01bd05efbe8502eb97b1064bafa9bba5658b1677819cec4998dbf02df1f1eef51bb3e75c19f570efdda98b0b8dc5dd9250eae8396090ca9ebecdb90f32c5e2085e86b64e57464d251af62d9f8c01d7bd6cec5f9dfa5eb7c4cd412077571bd071a4eff5098883940d63b917c08bf373916cccd7a446abff0aa5c687518703c25cd8d3c5d724f348e20be54f77fd18dbf6344d1d25c788ccb5a5747d575435829b1825e31f9e94abc33c0d2750fb62ae167a7a74fc9e39db620d43e0b8514d5f70a647e53dd5764254b7785b1519474 +TAG: 936072d637b12b0b6a4141050f4024ce + +KEY: e57e74595d230e8eae078df1dbc071c66a979a912e2252257e28447e97fc82a7 +NONCE: b613d6d5fff507e917674f2f +IN: f1ecbb2a45f04ca844616528b10ffa4d2c5d522ed4ae3366888fb371b6ee7eb4be53c8204783e43265931f58f308623f7b2733384c173540aa0bdf879fad0283c2be6c42a7b4feb2b29265fffdb518ea77d33507dbbff7d9921bd97fd27f1100402e02135f7df4b5df85f7472fa75618facca3e24d487453e831efa91242e62ee9d32880bc20f7ec016eb12edb589dc8a669f7c78375f915d7c2b03457b00ac2aceaf37c0369a85c3f6fe7c0447c022d66bb5acaee62163837a36e882cfb8579ba9182d3153a25623f339758ede5a62f67b199fc8abe235fe4b607a6804fd4d15378c76e0c26c1edf1cd637b7ea59edc66cd5ef9b8cf79b95ff89c235ab195 +AD: bf4c0737e461c1d6fc45b87175fd7833625c98a03e089c4e3d47c6b21f4bf38cb4b7666322217eb8fa022afae473df56ba3502c88cf702276bf39c6fcccf01e629925a83816a5096e612458af6380dcb7f63cfc0eae99d63475616b18b44111a1927b05503c4ce46ca48321b0f8f247a54919fc844fbabd3a2481e83bed8a5ee8086d7559db00fd1d64f4892ee9363d59829ce1e10af66696c28e86297b43190800251f346bec1b577446120529d486266a271c71011528b24ff4caf2c30f9748a2b03c788dd583541368a643075a52127c48b3b6f0c6ef413e61479c9afdbeb4bda44340ff0d81c7bc0321d3de4080cf7e108dda3fd4e480e685b202c6bfc +CT: afb2aae2dce03cb0bd3467447ef6895a132cec06b9f7764ee24d90078660dc820b8384c01375e03c20a6c688a780d7d7fbe5837d477e8f3d7ab3ab865dacb0eedb5694d3276ea914a421b03b9d4e4f586227a3af7e8d5d579bd832450f038eaa7bac57aab996df55367ddf59b338e5d370e310124e8ef43c9fe54e5d23d60023aee266054ea66c9f32170ce97998b527073fd178ed4e1752cb9c515c0b32766b363c39c513c2e9ff6d1c24807afb43af3c5a317f1536087d8576fa3be3b007d3a77ab0422303cd0b142c4ad194e1bb86471b91861235dc336dfe9666f4f2c6a32a92b8fc52b99873f9792cb359476a2aea21996d21c17ab814de4a52eeeb33 +TAG: 05906cbf531931559cf2d86c383c145e + +KEY: 847eb274561fdf0c1af8b565a92da74641f17261a0ea4cf63ba5f36ba7028192 +NONCE: a379511688390ade6f0318bb +IN: 1e588cd0636f34b656b140b591a9adafb8dc68d0abb75531942e3c6ec1d29e4f67853e3d718dbe61b733490525c7f9ce6746f8639e4d271267a95f0940b3406c67ded0aaed36374b9a4bb8c753579051c6dc3244d6126a8a97d4a912569ba139d55dd00c380e7ec450d44f6c7b9482c2594b21f61ef8d165666c830867139262be5ad3a31f44a286d7e86d4e5c9bd6118147efc8e606c522ad0e9a218aea4daa39d1653157e4c3730240fff67a42e4f34186de1c13ddcb1e44020b7a31d21ba6ba96b3f42360dd1d754a7bae75b6fdb6eb3c76412cc1fd8e900d7aacf4d897f4224f19a1d44a77e06c95eda5fe76b11c6f5088e8ca75c87e07edc64c09a6a31371552449 +AD: 331d48e814f660516f3a796b08afb1312625b3b17218819cfdbbbca4c333378b57fd93482d971992b5b15b62f0724d6e7b9beb5ddffd3c70b6f8bdd3cd826663eeb91d37734a686c987efeb4d4906b80c5378fcd07806d2dbf3eb528472a110743df8cd96b6eb67e98b13ac506c9bda167f045a412c93d78e860c9b4bbd7a2d71adbd3530f30253847b4112d4b898b520c7a14fd075e62605b05084f26fd138179c2791fd6e8d3bfbb2735002ae12d986f92d7d300fd6f1dc12c993449f8522f6f32f506a677c8a981aef9815e83019713b2f9943acc8d5b3f6f65b9e2b9a14ad2e300d636166da2d35a6a0a756a76d08709a043d65341695490124971a7574cf0b5845a +CT: fc1f0d7309e6420b42d59740c9b9d4b97075b874015251ad55483068b00f87502b18182b140db07c70a80fd884fd79b7b5fef1d307ca4db0ff046494443e1cae83478d275c31402035f1fc24e26214b78d9a4dac78d074150012f9fee810a121d87a16d8e1eec5700e9facba350029788480a259d9f30df1c2b8df7691629314391719853c0b68614134f6028865700b1fc4e7f34ff28f449c6abc3027f38d7a7f6d84b8f27f7cc5afa09478c809eec346bb58244ab42a3bef61a14ae7640d76591343983de9fe5f1b985ce56c9fcfb2e3f6220779ca6f92a6b8aa726573b38ed7663ebe4c85066ae3f488ea3309593fa41dba8efd2b8f44b9fa8f7a427823c1228093a3 +TAG: f1832022e06228c36181856325d4eb68 + +KEY: 3828b138f72f8fe793d46c55ad413bab31a51e7a9093cdd10fddb4739e28e678 +NONCE: a60413c0ab529ccf3de58468 +IN: fec017c1c51da5ce9dcd8e84cdc03a43145b31edfd039c7c85d8811a2f58efe7a2d7590149a98cf0b5af82d3e0a325223bc9d5585ceb1afc4cdd96024be6c8064c2abac14f68e65de49e25e3e967500ce5b4504d00a9cbad1e86bbdcf65c01a7a92de27583b7b92122b6a4923b7192994a1edf00b75d14a982f92559dbc2d5e427a75ad29715375d90193ddbb39b9a52c1a23d75629c539e0a6ce822c7c08fc77dcd3adc357893215df4694673a16d34513de21217ce86897c8f0575d213ce0c66eb1d1985fe73dd86da3ab5e89df4243e1be9dd95af94f878995d02929ee42a062100d6d4d3884730f54593d5ff7b7ae53e03d4f0e10f6f4c3077206499ab7d4de1e825d532d0918f +AD: e2b16ff2b6c73c9374704ffb4cdfe7bad9eeee32157f2eedf427f99c2cce80c5aa4d9145e85af0cb08e6ed477cbe79ee168ded5c0895f9f4f939c21916b3dd5c9d268b3aabdefb85d953bce9b70732fc9acf6c7b727f78d8c9aaca9e022d7cf0f95583e81744227d87fa34ae19de44d202ba01e3d03993f38c9b2fb00b54dfb677d67e6f5a15f46c29eb5597ae3d5384b37bbeca3f3d825e2b7cceaaeb36a8c1273062259608956dd0c79877cc460d0268de27355e34b9d8d1188c062ac5e10a73f2d70fd0636304b3de06cffeedd246e2db19b8b66785f9f9c62b8f0198f29d37a4ab5280f4aa0320559810f89a1618844d0ad5f3a4f5a0e834ab31e56798b7158217f834d372c36f +CT: 88ea11ef6b6ee6fb0be77bcbf227e77508922550ef0d7534bf05668ae5fcab2f4defe643747716e7e000950e36c6cb24b79987389a150382c091d39ddf841b0a5e31d763d9c59753a3ef36a23b81f38e6e715357395ce715d30c14d6ab5b7454804ecf633daa39b6107f562fae6a646efb25c1119dd17955bb9e640105a21566345408f72f2acc8f2726a0be465551f9ae566da559fc0b92c36764c5ca20a18a316c02e606030a53450e7ae1146050a48a64c600d33cb84389b0bdac7ff45d3d1f2f669a6e365ef722d76d2fe9bef2df93c58bbdd6965e18111b5de0f4a62dbb874161bf8adfa61e9cdecd97b4fff668b3efeb3e32eeb929cf58d94ad8077c0a2ca79e80877c5d9329 +TAG: 9b47afc5816b7229213cd3c9135545ed + +KEY: 91ea63dc27d9d6bbc279ec6cecdce6c45ff0b247cfb8e26b6ab15f9b63b031a4 +NONCE: 80a134fac73eca30459d5964 +IN: a848e41c77ac8c733370435b5b6a9960af36031e96260d5703ce15b003606875a7901cd11e4571bf88dda29a627c0b98065a8b4e6d382852dfa4f47d86fa08e48ad8f5a98e55c305900b83200d44029f304abd21e0264115192a3fd7b0eb69b9f8ca7865b3be93f4ba5a28468fd7bbb584c32ae867f5146efbeb1412d3ac36c30cb308c327a6f207e30f561d6efe0a535446c693e14176e9e714ffb5a5b1075812909a362a6c4bbe18322e15690c2c9cf5a18e0120c11551cb7055b5aee97e7a56d7c24fdf1214641c8eacb196d74f3d96a7fbecdd4fe52dc7b6ead9041cafd5a3fdf91fd3614e63189b488d4d7c1ea3c6351d112a2223b29d390ac3ab7f09a60bbd3df6e0d606d902aa44244334 +AD: 47940a0694183b2fcb5e760c9ef6dbe4cbff6ccf33208337a981138f9d35c03f8adbd810e94636acaebef6791b531a65e99b03fc78e7eb48036615874e97cf762fa6ca5d880bb2c2f644f1aed70c667880f98834d501caa277cb8ef1095ff882e79c3a92ea8982abebf63ea9ed7e9a24d32cb81d5d98e891974e3d636a59e165984e00f05a040d33f07b39eccb924fb24780a422a6b2b7bddb5b316beddcf6fad20e4cee7d0141c2f7c4e4f759db8691dc7b8525ccbc3ee6071a2ead63e750d6d92dde7eb1303d5b1194702b6c3e0c2e6f9649e60eeddec9c1f71cf309af0672cd2ffcf94ba7e6c3d7cee020a224a9a956274d1d36ba16030e215d90a165756666eff066a8e51bf7d4babe8b7d8d +CT: b90449af99327afb1124bb24f1c8b5cb878423b0370d5f7cd297b28cc4135ee77d6f1913a221cfeee119bafa873072bfa79e303fe377bbed05add41ce3a42ca4632b98f40a36227de1a9ba84d6176c01eca9d33d954d0ebdf4e40f136e0f6a56156fbb33b344a8a433941fd6e08774bd00075aedb0e396c2bc37d1250541248dbeb899e1b5170cdfeaf7b89995b049428bb277c501354f8cd48fb58f6f04f956dfd099c48778dbdbb4c95b7c9d6797cf6d3bcd1d00e88cea885ee4a10d94356509e148990a0e10dd89103a9d5c8434a7bdbed6c0ac1271e0709eba144abf3cf075c020e9f7835d5a98fb2439b399e377ae6e19fc5f32df9ddfb9e936190d3e9c62de99835249d1f32ca3f92ecd44 +TAG: 6ccaf7c142d86b83e4d0b4289b49c4d4 + +KEY: 1344db082889367fd48c5f06bc39f9cb9e3ad4b92fa484ccf49418dd4caa2e19 +NONCE: c04a98e7e29326b5330818d4 +IN: b0e12e3122c1ebfdcadded5a45163a6208548e9bdf95cfd18ea504e5d2e97372e58dbfe460a57b724d38f3bc0ce02a54015779bcf127343474d7d4c1402d598bee56897203b903da5b819e2218bd0d1a2af11c542544f02c46969cd2bfac683b76a8de61698ccba63361a1a0b570adf69d24e9a7e466873c8c12e25e0bcead7828386179a4d65d5bbdb800eb52fc01b67498d7b5f9864270162158a8572eccf541b07833f001848672098c57708eb479855799567c318b1aa097efa70db0d8a8d36fe0ac22ebcc2870baacac690a79e07ab286acad9f7a877939cf2989cd6200eb86dfa7a41e969a3683ceacc7c97d1cd5487f13c439a9777a67770687657d38267a347a0b6d3aa3cf64e7f31017246e4369da +AD: c96db14dbc2aa0ce3ac63794f75c7e78037dac6763282edb307821a7938de4baa3d2e35a8cfe0c8724c2a8d870d0a462ea157e15aacc69a3c881d9c819225ea8be479872d55e655c897936c95b9ab340820264567495fc5e4e3354f42b84e191b470ca9f4d8fc25d011bf9c9e73e1590e1bb919dd2f288b26935fbfb8c93e54331dc8edad5e1cc4aec103c2f3320d59870c1770319f105ee790b704ed655be423e63ab040f1153f41e7070ae3a0f34d217c4649c180c84814463902d99a9396f8c7c85a3a4c8ae2f01737649fae478a40fc72303a108822775e9c421f945cc0eea992730790a9aa0c0d014518dab371b52d30b5a560f34946a9344cfb8a19b09ee9b123bcb8f642780697508f04983b790dd2d +CT: ffda075dbde7b874995230e1324f17894689baaa7f1354e26100befb546ea23dc74807818e43a3cee00ec1bbb95c82180489ae5f3a1c482dec28f96ecaf5ca4655ff7f33c814197cb1973cf02a0b720a5c44068d8ddff0789fc1e7f20ef408c1a438133fce4f7a3e8c85d95a381b94e949ce47a85895c4be7cbfad468e52a160dee34b8ddeef2ab280eaaed4990ecec790ac16de3c74aac6fe2d5e28ea2b66a921c894a3971cee4a2158054c3567e0d941f867ded5ed1d21d8ab090848fb3eddfb1559bf11815db52b8eed871cfc117980f297da79da31da32de3f162a03d95090d3329da3662df29e6ec9b236e0f7c1d7d957cfd54d5efc99c694b9dece989912388254798513d881e5943ce830729a8e2ddf +TAG: 81c55fe9aa2de0d63efe3f74a3d8096f + +KEY: 31dbefe589b661af00a6fbad426e013f30f448c763f957bbcbaf9c09764f4a95 +NONCE: 147fe99bba0f606c57242314 +IN: 908bd801b70d85085dd480e1207a4a4b7ef179dac495a9befb16afe5adf7cb6f6d734882e6e96f587d38bfc080341dc8d5428a5fe3498b9d5faa497f60646bcb1155d2342f6b26381795daeb261d4ab1415f35c6c8ac9c8e90ea34823122df25c6ddae365cc66d92fc2fe2941f60895e00233b2e5968b01e2811c8c6f7a0a229f1c301a72715bd5c35234c1be81ef7d5cc2779e146314d3783a7aa72d87a8f107654b93cb66e3648c26fc9e4a2f0378fa178c586d096092f6a80e2e03708da72d6e4d7316c2384a522459a4ad369c82d192f6f695b0d90fcc47c6f86b8bbc6f2f4ea303aa64f5ce8b8710da62482147bcc29c8238116549256a7a011fd9c78bbb8c40e278740dc156c2cc99c3591fec2918cdeb5240fb428 +AD: 5a32d7044f003b2ffefffe5896933f4d8d64909fa03e321a1bdf063099b9f89752d72e877291d8da12340c5dd570d7d42984ffab5177824fc5483b4faf488504e6822e371dca9af541c6a97312b9cbf341b4198b0902cd2985ac10a8b5b5fe9691bb29a88344f863c980e4e871a72a8b74f92eef68c176e9d2ef037898ff567298e186af52ec62eb7429a8004ac46b945678b82859396d36d388ec3d67653aec35cf1da2684bbc6c78a5f9e3ce1b355af3b207f64e0fa73501c5d48a14638d0906c87eaa876debcf1a532c1475d80ed3d4b96458d2236eb9f67988863bc6d5c16b96b93d898683d248d7bc601b5035fc365481b89465e37a8f7dd64635e19a0282639cecde72c6b1638e0aa6e56f9c00d031cdadc59ce37e +CT: aeab9db30a579ca54195e54a9e6c787f40100c6d12ceee35643f36ae45f618cc9bb66aa4c0fae0ec2686cb4101a5b23a46877460c7e020b38b0d8d1f533ecfa99df03d346bc854a578276d7d5685ad1fb03655683a64aae4159c9efa6781f053057e0811226c7c533967a94587f4025353b28cc3a2ce5763783b4c31e7818b8ad9195bc03be8f294f9f6ceac578f9d30b22b1f5a68d647d46cf6db4a9c3a8a5c06fa97c9efb4578f501ea96db1f40942e3f24c44a7e4070a6b931c39947d9692930b67767357015de51a39e46fff94b6019e4bc1ad9d216a571ba0dc88859c49d2c487ca657384e49b4d382d86a60c8d5195320909c4e82fc077a3b22bd4eccf0f067e66ec78eed642b2d16f0f304f60f1d9ba69e205c982 +TAG: 17ca09e3084504fc22e914ee28312c8e + +KEY: 0ecc44c9036961fba57c841ace4ca3c547c51d9f126567bf41626765cfcbd53b +NONCE: aa98b6ddff7e4b2041f29d70 +IN: e49a2a5713f507bfa00c140dfbefc0c43e37bcb932e0741db03f0055da61cd837b6e2d8f99115d70750fb23685a17121b52e98a37c87204e0207729fd9219d11a48e57970d790338793cf329f7b239512a44dd4409fe9d157f92123dfc5cba24af106442644dedda87e1d9e95fd395f2f0ad8f7d27f313e6ce1a07d9845dec5ad732e6e4749b3a161527c8ce42331f5de1d700650072fb68e9c7645a0e0e529d0563d2727e3fb38ed341f74ef1ad95a0216a440e1384d0e7ef71cde38cecdc9e2b2d563f19014c40c1f92ea0af3b4f6da9146d433ae85f647153db326a28ef6ea2e0ebac0cc1aff157067c7dba7cc4317d56920ee9deab5764368e7e5b3ce8bebd0fa129f869b15897c09659c53188bf8efb7b6ac7d265c9b85fe96166 +AD: df41db4ef5350d4afcaa88b4a577b3370b96699bbd73e59aeebca6ea856cf22694a9399ae7f97a3bec226d82f5598f8949dfb92530dcfe77770f066f2af988fba5543b8ba7655bc43f8dca032981a34a1beff695c6908169d475c55b2119fe5578623f68a9dd85b653656881b0db4006d3336fdfc784d1805e48ff478fdc196601f044c9d33fca3ddde2db0102f90fff0b370f520e00e3786c2a9b0b4a9a7ea6f9d866f77d870c8ef0f3a8bedef17949a32598512af665679dfbe71e1c3efc3dee8f5d4499e20dc63281191751f67e51f201973a6675896484527d66bed94d6aaceff65fbc4192cec19452b8873f22d72bf2f4981fe656285cb24be5c58e77dafd3e096166b230f18d3f4197fe16f6ec84c060ce0793ae6848311a18b7 +CT: b15b2bc4b9e8ecc5d9c4a6359a805b7590bdb4bfaa9b3fc4d7676d721edc4b3b1ef71b18a3d78f1b31a477cf25e55b278eb3ed774805ae8e5a2a0204f7291d9587663c4d8b1b744154f3b7cef796e0b91590161f3bde82f1d8139cb8d017606ae6d0552ba144788fd8caf435ab09a43a1f4057776af49bad98fc35cefefb159cfebfed76f2e4d18b7be143677ff8b3d6e2b440fe68475b5a1193bcd19ab157d0d2257f33de8e50091ea3388648c3410aa68c830566a0413d92454e4eff433c3edc74e8f7516ec17b2c01cf57a2d7c48db97b706b8d7da0b68051f2d6a87c417f46cf217a48611980890f669d39b478c35d834ed2c79299df2381a1215d6db303cb63e2795fe517649874226e0a6dbfe2c86370b9fbdd8c5de349bfa25f +TAG: 7082c7ef72c82d23e0ba524132acd208 + +KEY: c05dc14b5def43f2e8f86c3008ef44e4dc6513768812e9218b2b216818c4cec6 +NONCE: 5cfe0dca6e599ed9aa89ba97 +IN: 8a06e2997b8e5f8040b22e07978c83c48d0f90bd2b2f8b426b43feea0b614d3b0681745ea4224cabcaa25ca45c3053a6300c47ffa4f72e838db135ae35c27939aad4cf7f75fb61daa3148d869057598e4e8b44c6fb19b0d9281e18676d8bc137489bb77a51a3a8f807a896d558f00040e8729ea9bbdc7db6102c8b99c8a1eacb0735577bc6533cd1d8147013935b6344116090a1bdef1f2e38a877a50c8fc0f394bafede31375c57476ba06d95ae734e6dae771a32e5091dff71d845c5f7385b9b9069ced12fcfea34a510880b088bb0016e94a5932c89baee038cbafbf06b3d09426afd2d5dd5e392636362e9ffa9186b5c753eb84f82f68fb1286ed06c58a5a936cad018ebc4269037b49f2ea0349373adea99f06062e5dbb0bf94f2883f5c0556 +AD: f2a3f7af8ea984bbd85953f14202c6e478f98d0bcaacd414329ec480d0c29fb4c1a052d3228c883928448f0bef12cee5b69829b4a3eb4680084131867cfc3d3af84fcc0d80c2292d3fe02405634f6cfb20b0fb90345da3a557fb30582175c32e432be66ad096f9425ff4060df54d6741fd6567a1e2fc5f6f3ed95cefc806ff64ae91ae82920b5c829ea026f83fd90d760e240da3c9ddaafe4d08507f4af1049056dc6d09657779a3dbd889d851e97d4ac60dc66df2d24979ba8947a7890a304bb301d0d42b67824e0c68fc882e90cb6deee50c2e3d9f0da59ab23c997b05635a0d56c71fc39aa0e6b19c43a7fe12d4e4145453cd7fbd8a3f33bf5451addf05052df7ef044a33513bc5f1a4cfc8b68015664bb5c8e4bf54a85efff109ee96af75d4a5 +CT: 2cf630548d6f2b449057c7861920308958199f77b123a142c6b7c89c4982f4ed0efa2fe899914ddbf4543e70865a5e683b0721d6c8443df2e697acf31e11c8809aba94196409020a7c64d396fe136826455aec973af23a6c7733cb567f5ea550e50e0b796623a97807d042855568e3c568990cfc818c31a1bf415337f43e9baed57fada2fb2ad3c3543f2b7f2777e03f84040c1c854c310ab1cc5dc7f2a5fb213af79ac068b46c7d9475bea126adf079e2100bb57904a931faf248e0f7d5832ca83ea8a283e0136979737132afb1f4ab38d307ac0774814f4d5ecdc4aad79185c05f8a706f579b78f2c1c7004cb38e6cd22c2080735b34c3f6134955ed3bc36b1ad5c8e33209c9f3c658fb07b59b6002b2526cd8d853a5c624b7108573d7df60c827 +TAG: 3dcdabcd1c82002a551cea41921570e5 + +KEY: b33f449deccc2ef0d7616f22b4a00fcd84c51a8383782f66f1696bc6405005ee +NONCE: 6afa8baf923f986b5779ac6a +IN: b0af85a6deae5fcaa94778bce015ce2da7400ab768f3e114cc1b645fb2716789e2aeb96894fda6da5bc24fcf2466124720d6ba99e5475d77e5bcf2c2f8c8e5becf5eb73ad650861bbdeb51ba5ee789c227478934200fc18f36e4fe392c99d4c3fe0b38b40d2e84f831b8ef9bce9ac1362c755943521ecf5b5cf8fbcdf08f2d47ff7cd62838597dd342695a1b037bcede69500bf70bf1edbb40a17b44695bd8ff8bc8664b3211a6bbfdcbd1bffbfb1a2ea0141cfbc6ac841c803b137be5eeb2666c46c09cc1c4fa82be43bfd56e7a2b8ceeecb6efc1933a90213a0e1bc7aca2af35f2d1dad5f0d9002561064a699f1ce76c39d9c2224ae596e88a1517e19c2115370768d50107f3f2a55051838ae5897acf2ac0814ccd864eee2f6b5d7a6728c6ac6e6a57327102 +AD: 2134f74e882a44e457c38b6580cd58ce20e81267baeb4a9d50c41ababc2a91ddf300c39963643d3c0797b628c75a5fc39c058d319e7d6deb836334dbe8e1fe3cc5704b90c712e1fb60a3c8b58d474a73d65fae886394f8b2c029e420b923f2af4d54c9de3c7fa2bccaa1e96664ccf681cacbbf9845069a4bfd6c135c4392d7d6be338eca414e3a45f50510718e2a5a3e5815eafa0c50172cf5f147510645d2269929843bbbab682deb5823d4cdf42bd250bdbd20c43e2919d7a6e48973f43a4cab73454b97cdca96721ebd83b6dbaaec7e12cf0dae678a57c431b81421657037dd47dccbee73a41f56495fd7c25c75744fe8f55cbd1eac4a174d8f7dd6f6ba57b3e53449a9ce7806517e3e07cf6546a0fa62c7b1fa244d42eee64a3182461792edb628e567b23a +CT: 0fe35823610ea698aeb5b571f3ebbaf0ac3586ecb3b24fcc7c56943d4426f7fdf4e4a53fb430751456d41551f8e5502faa0e1ac5f452b27b13c1dc63e9231c6b192f8dd2978300293298acb6293459d3204429e374881085d49ed6ad76f1d85e3f6dd5455a7a5a9d7127386a30f80658395dc8eb158e5ca052a7137feef28aa247e176cceb9c031f73fb8d48139e3bdb30e2e19627f7fc3501a6d6287e2fb89ad184cefa1774585aa663586f289c778462eee3cd88071140274770e4ed98b9b83cd4fa659fcdd2d1fde7e58333c6cf7f83fe285b97ad8f276a375fafa15f88e6167f5f2bfb95af1aefee80b0620a9bc09402ab79036e716f0c8d518ae2fa15094f6ea4c5e8b283f97cc27f2f1d0b6367b4b508c7bad16f1539325751bd785e9e08cd508bdb3b84 +TAG: 1976d7e121704ce463a8d4fe1b93d90f + +# AES GCM test vectors from http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-spec.pdf + +KEY: 0000000000000000000000000000000000000000000000000000000000000000 +NONCE: 000000000000000000000000 +IN: "" +CT: "" +AD: "" +TAG: 530f8afbc74536b9a963b4f1c4cb738b + +KEY: 0000000000000000000000000000000000000000000000000000000000000000 +NONCE: 000000000000000000000000 +IN: 00000000000000000000000000000000 +CT: cea7403d4d606b6e074ec5d3baf39d18 +AD: "" +TAG: d0d1c8a799996bf0265b98b5d48ab919 + +KEY: feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308 +NONCE: cafebabefacedbaddecaf888 +IN: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255 +CT: 522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad +AD: "" +TAG: b094dac5d93471bdec1a502270e3cc6c + +KEY: feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308 +NONCE: cafebabefacedbaddecaf888 +IN: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 +CT: 522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662 +AD: feedfacedeadbeeffeedfacedeadbeefabaddad2 +TAG: 76fc6ece0f4e1768cddf8853bb2d551b + +KEY: feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308 +NONCE: cafebabefacedbad +IN: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 +CT: c3762df1ca787d32ae47c13bf19844cbaf1ae14d0b976afac52ff7d79bba9de0feb582d33934a4f0954cc2363bc73f7862ac430e64abe499f47c9b1f +AD: feedfacedeadbeeffeedfacedeadbeefabaddad2 +TAG: 3a337dbf46a792c45e454913fe2ea8f2 + +KEY: feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308 +NONCE: 9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b +IN: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 +CT: 5a8def2f0c9e53f1f75d7853659e2a20eeb2b22aafde6419a058ab4f6f746bf40fc0c3b780f244452da3ebf1c5d82cdea2418997200ef82e44ae7e3f +AD: feedfacedeadbeeffeedfacedeadbeefabaddad2 +TAG: a44a8266ee1c8eb0c8b5d4cf5ae9f19a diff --git a/external/boringssl/crypto/cipher/test/aes_256_key_wrap_tests.txt b/external/boringssl/crypto/cipher/test/aes_256_key_wrap_tests.txt new file mode 100644 index 0000000000..92d3a049b0 --- /dev/null +++ b/external/boringssl/crypto/cipher/test/aes_256_key_wrap_tests.txt @@ -0,0 +1,23 @@ +# These test vectors have been taken from +# http://csrc.nist.gov/groups/ST/toolkit/documents/kms/key-wrap.pdf + +KEY: 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +NONCE: +IN: 00112233445566778899AABBCCDDEEFF +AD: +CT: 64E8C3F9CE0F5BA263E9777905818A2A +TAG: 93C8191E7D6E8AE7 + +KEY: 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +NONCE: +IN: 00112233445566778899AABBCCDDEEFF0001020304050607 +AD: +CT: A8F9BC1612C68B3FF6E6F4FBE30E71E4769C8B80A32CB895 +TAG: 8CD5D17D6B254DA1 + +KEY: 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +NONCE: +IN: 00112233445566778899AABBCCDDEEFF000102030405060708090A0B0C0D0E0F +AD: +CT: 28C9F404C4B810F4CBCCB35CFB87F8263F5786E2D80ED326CBC7F0E71A99F43B +TAG: FB988B9B7A02DD21 diff --git a/external/boringssl/crypto/cipher/test/chacha20_poly1305_old_tests.txt b/external/boringssl/crypto/cipher/test/chacha20_poly1305_old_tests.txt new file mode 100644 index 0000000000..d40b21cbbc --- /dev/null +++ b/external/boringssl/crypto/cipher/test/chacha20_poly1305_old_tests.txt @@ -0,0 +1,524 @@ +KEY: 9a97f65b9b4c721b960a672145fca8d4e32e67f9111ea979ce9c4826806aeee6 +NONCE: 3de9c0da2bd7f91e +IN: "" +AD: "" +CT: "" +TAG: 5a6e21f4ba6dbee57380e79e79c30def + +KEY: bcb2639bf989c6251b29bf38d39a9bdce7c55f4b2ac12a39c8a37b5d0a5cc2b5 +NONCE: 1e8b4c510f5ca083 +IN: 8c8419bc27 +AD: 34ab88c265 +CT: 1a7c2f33f5 +TAG: 2875c659d0f2808de3a40027feff91a4 + +KEY: 4290bcb154173531f314af57f3be3b5006da371ece272afa1b5dbdd1100a1007 +NONCE: cd7cf67be39c794a +IN: 86d09974840bded2a5ca +AD: 87e229d4500845a079c0 +CT: e3e446f7ede9a19b62a4 +TAG: 677dabf4e3d24b876bb284753896e1d6 + +KEY: 422a5355b56dcf2b436aa8152858106a88d9ba23cdfe087b5e74e817a52388b3 +NONCE: 1d12d6d91848f2ea +IN: 537a645387f22d6f6dbbea568d3feb +AD: bef267c99aec8af56bc238612bfea6 +CT: 281a366705c5a24b94e56146681e44 +TAG: 38f2b8ee3be44abba3c010d9cab6e042 + +KEY: ec7b864a078c3d05d970b6ea3ba6d33d6bb73dfa64c622a4727a96ede876f685 +NONCE: 2bca0e59e39508d3 +IN: b76733895c871edd728a45ed1a21f15a9597d49d +AD: cc1243ea54272db602fb0853c8e7027c56338b6c +CT: 1fb9b2958fce47a5cada9d895fbb0c00d3569858 +TAG: 042ad5042c89ebc1aad57d3fb703d314 + +KEY: 2c4c0fdb611df2d4d5e7898c6af0022795364adb8749155e2c68776a090e7d5c +NONCE: 13ce7382734c4a71 +IN: 0dc6ff21a346e1337dd0db81d8f7d9f6fd1864418b98aadcdb +AD: 0115edcb176ab8bfa947d1f7c3a86a845d310bf6706c59a8f9 +CT: dad65e4244a1a17ce59d88b00af4f7434bd7830ffdd4c5558f +TAG: ac1437b45d8eacf9c0fe547c84fb82a2 + +KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865 +NONCE: 5d9856060c54ab06 +IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e +AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51 +CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36 +TAG: 6dd98710d8a889dceea0d0a936f98617 + +KEY: a8b9766f404dea8cf7d7dfaf5822f53df9ccd092e332a57f007b301b507d5e14 +NONCE: c7f2f7a233104a2d +IN: 4d6faeaee39179a7c892faae3719656cc614c7e6ecd8fcb570a3b82c4dace969090338 +AD: c6d83b6a56408a356e68d0494d4eff150530b09551d008373d6dee2b8d6b5619d67fdb +CT: a15443f083316eef627a371f4c9ac654d0dd75255d8a303125e9f51af4233ff4ceb7fe +TAG: 52504e880f6792a60708cc6db72eae42 + +KEY: 5e8d0e5f1467f7a750c55144d0c670f7d91075f386795b230c9bf1c04ba250bc +NONCE: 88049f44ba61b88f +IN: 51a1eebcc348e0582196a0bce16ed1f8ac2e91c3e8a690e04a9f4b5cf63313d7ad08d1efbff85c89 +AD: 5d09bf0be90026f9fc51f73418d6d864b6d197ea030b3de072bd2c2f5cab5860a342abbd29dba9dc +CT: 35aa4bd4537aa611fd7578fc227df50ebcb00c692a1cf6f02e50ed9270bd93af3bc68f4c75b96638 +TAG: ccea1cbbc83944cc66df4dbf6fb7fc46 + +KEY: 21a9f07ec891d488805e9b92bb1b2286f3f0410c323b07fee1dc6f7379e22e48 +NONCE: 066215be6567377a +IN: c1b0affaf2b8d7ef51cca9aacf7969f92f928c2e3cc7db2e15f47ee1f65023910d09f209d007b7436ee898133d +AD: dfdfdf4d3a68b47ad0d48828dc17b2585da9c81c3a8d71d826b5fa8020fee002397e91fc9658e9d61d728b93eb +CT: 8ff4ceb600e7d45696d02467f8e30df0d33864a040a41ffb9e4c2da09b92e88b6f6b850e9f7258d827b9aaf346 +TAG: 4eeddc99784011f0758ba5ebfba61827 + +KEY: 54c93db9aa0e00d10b45041c7a7e41ee9f90ab78ae4c1bba18d673c3b370abde +NONCE: 3f2d44e7b352360f +IN: 1241e7d6fbe5eef5d8af9c2fb8b516e0f1dd49aa4ebe5491205194fe5aea3704efaf30d392f44cc99e0925b84460d4873344 +AD: f1d1b08dd6fe96c46578c1d1ad38881840b10cb5eae41e5f05fe5287223fa72242aea48cb374a80be937b541f9381efa66bb +CT: 027b86865b80b4c4da823a7d3dbcf5845bf57d58ee334eb357e82369cc628979e2947830d9d4817efd3d0bc4779f0b388943 +TAG: 4303fa0174ac2b9916bf89c593baee37 + +KEY: 808e0e73e9bcd274d4c6f65df2fe957822a602f039d4752616ba29a28926ef4a +NONCE: 1b9cd73d2fc3cb8e +IN: 3436c7b5be2394af7e88320c82326a6db37887ff9de41961c7d654dd22dd1f7d40444d48f5c663b86ff41f3e15b5c8ca1337f97635858f +AD: d57cfbe5f2538044282e53b2f0bb4e86ea2233041fb36adb8338ded092148f8c2e894ef8766a7ec2dd02c6ac5dbab0c3703c5e9119e37c +CT: 9b950b3caf7d25eaf5fca6fa3fe12ed077d80dcd5579851233c766bb8bb613ec91d925a939bb52fb88d5eda803cfe2a8cda2e055b962fd +TAG: 6bf5b718f5bbe1395a5fdfcbbef752f5 + +KEY: 4adfe1a26c5636536cd7cb72aa5bded0b1aa64487ad0e4078f311e8782768e97 +NONCE: d69e54badec11560 +IN: 19b3f9411ce875fcb684cbdc07938c4c1347e164f9640d37b22f975b4b9a373c4302ae0e7dfdeba1e0d00ced446e338f4c5bc01b4becef5115825276 +AD: bda1b0f6c2f4eb8121dcbd2eebd91a03ae1d6e0523b9b6f34b6f16ceca0d086654fb0552bfd5c8e1887730e1449ea02d7f647ae835bc2dab4bbc65b9 +CT: ea765a829d961e08bacaed801237ef4067df38ad3737b7c6de4db587a102a86fc4abbaabea0ee97c95ca7f571c7bab6f38cbae60cd6e6a4ce3c7a320 +TAG: b425cdf10cd0123a7e64b347c6b4b1f0 + +KEY: eb3db86c14b7cc2e494345d0dfb4841bbd3aa1e2bc640cca0c6c405520685639 +NONCE: 88b54b28d6da8c81 +IN: f75c0a357271430b1ecff07a307b6c29325c6e66935046704a19845e629f87a9e3b8aa6c1df55dd426a487d533bb333e46f0d3418464ac1bef059231f8e87e6284 +AD: 34b08bb0df821c573dcb56f5b8b4a9920465067f3b5bf3e3254ea1da1a7fc9847fd38bdfe6b30927945263a91fa288c7cf1bee0fddb0fadf5948c5d83eb4623575 +CT: 146ec84f5dc1c9fe9de3307a9182dbaa75965bf85f5e64563e68d039a5b659aa8863b89228edb93ff3d8c3323ab0d03300476aa4aca206d4626a6b269b2078912d +TAG: 0058a8dff32c29935c62210c359bd281 + +KEY: dd5b49b5953e04d926d664da3b65ebcffbbf06abbe93a3819dfc1abbecbaab13 +NONCE: c5c8009459b9e31a +IN: f21f6706a4dc33a361362c214defd56d353bcb29811e5819ab3c5c2c13950c7aa0000b9d1fe69bb46454514dcce88a4a5eda097c281b81e51d6a4dba47c80326ba6cea8e2bab +AD: fe6f4cbb00794adea59e9de8b03c7fdf482e46f6c47a35f96997669c735ed5e729a49416b42468777e6a8d7aa173c18b8177418ded600124a98cbb65489f9c24a04f1e7127ce +CT: 911ead61b2aa81d00c5eff53aeea3ab713709ed571765890d558fb59d3993b45f598a39e5eff4be844c4d4bd1ef9622e60412b21140007d54dcf31b2c0e3e98cf33a00fd27f0 +TAG: d38d672665e2c8c4a07954b10ecff7d9 + +KEY: 3b319e40148a67dc0bb19271d9272b327bc5eee087173d3d134ad56c8c7dc020 +NONCE: ce5cf6fef84d0010 +IN: 27b5627b17a2de31ad00fc2ecb347da0a399bb75cc6eadd4d6ee02de8fbd6a2168d4763ba9368ba982e97a2db8126df0343cdad06d2bc7d7e12eec731d130f8b8745c1954bfd1d717b4ea2 +AD: a026b6638f2939ec9cc28d935fb7113157f3b5b7e26c12f8f25b36412b0cd560b7f11b62788a76bd171342e2ae858bcecb8266ff8482bbaed593afe818b9829e05e8e2b281ae7799580142 +CT: 368fb69892447b75778f1c5236e1e9d5d89255c3d68d565a5bba4f524d6ad27de13087f301e2ef4c08f5e2c6128b1d3e26de845c4ac4869e4c8bd8858ad0d26dec3b5d61a9e3666a3911ba +TAG: 2e70564c3999c448d92cc6df29d095c4 + +KEY: 43bf97407a82d0f684bb85342380d66b85fcc81c3e22f1c0d972cd5bfdf407f4 +NONCE: 8b6ba494c540fba4 +IN: 4b4c7e292a357f56fdf567c32fc0f33608110d7ce5c69112987d7b5a0bd46d8627a721b0aed070b54ea9726084188c518cba829f3920365afc9382c6a5eb0dd332b84612366735be2479b63c9efc7ff5 +AD: 1e0acf4070e8d6758b60d81b6d289a4ecdc30e3de4f9090c13691d5b93d5bbcef984f90956de53c5cf44be6c70440661fa58e65dec2734ff51d6d03f57bddda1f47807247e3194e2f7ddd5f3cafd250f +CT: d0076c88ad4bc12d77eb8ae8d9b5bf3a2c5888a8d4c15297b38ece5d64f673191dc81547240a0cbe066c9c563f5c3424809971b5a07dcc70b107305561ce85aecb0b0ea0e8b4ff4d1e4f84836955a945 +TAG: 75c9347425b459af6d99b17345c61ff7 + +KEY: 12fc0bc94104ed8150bde1e56856ce3c57cd1cf633954d22552140e1f4e7c65d +NONCE: d3875d1b6c808353 +IN: 24592082d6e73eb65c409b26ceae032e57f6877514947fc45eb007b8a6034494dde5563ac586ea081dc12fa6cda32266be858e4748be40bb20f71320711bf84c3f0e2783a63ad6e25a63b44c373a99af845cdf452c +AD: b8be08463e84a909d071f5ff87213391b7da889dc56fd2f1e3cf86a0a03e2c8eaa2f539bf73f90f5298c26f27ef4a673a12784833acb4d0861562142c974ee37b09ae7708a19f14d1ad8c402bd1ecf5ea280fab280 +CT: 9d9ae6328711fb897a88462d20b8aa1b278134cdf7b23e1f1c809fa408b68a7bfc2be61a790008edaa98823381f45ae65f71042689d88acfa5f63332f0fba737c4772c972eba266640056452903d6522cefd3f264e +TAG: e9c982d4ade7397bcfaa1e4c5a6cd578 + +KEY: 7b6300f7dc21c9fddeaa71f439d53b553a7bf3e69ff515b5cb6495d652a0f99c +NONCE: 40b32e3fdc646453 +IN: 572f60d98c8becc8ba80dd6b8d2d0f7b7bbfd7e4abc235f374abd44d9035c7650a79d1dd545fa2f6fb0b5eba271779913e5c5eb450528e4128909a96d11a652bf3f7ae9d0d17adbf612ec9ca32e73ef6e87d7f4e21fe3412ce14 +AD: 9ff377545a35cf1bfb77c734ad900c703aee6c3174fdb3736664863036a3a9d09163c2992f093e2408911b8751f001e493decc41e4eeeed04f698b6daed48452a7e1a74ec3b4f3dcf2151ca249fa568aa084c8428a41f20be5fd +CT: 229da76844426639e2fd3ef253a195e0a93f08452ba37219b6773f103134f3f87b1345f9b4bf8cfc11277c311780a2b6e19a363b6ac2efe6c4cc54a39b144e29c94b9ebbde6fd094c30f59d1b770ebf9fcad2a5c695dc003bf51 +TAG: b72acab50131a29558d56ae7b9d48e4e + +KEY: 4aeb62f024e187606ee7cc9f5865c391c43df1963f459c87ba00e44bb163a866 +NONCE: 9559bd08718b75af +IN: c5d586ceece6f41812c969bcf1e727fe6ff8d1ae8c8c52367c612caa7cdf50e0662f5dffc5ea7d3cc39400dfe3dc1897905f6490fd7747b5f5f9842739c67d07ce7c339a5b3997a7fb4cd0d8e4817ff8916b251c11ef919167f858e41504b9 +AD: 51f5b503b73a5de8b96534c2a3f2d859ece0bd063ea6dfa486a7eec99f6c020983f7148cccb86202cf9685cc1cc266930f04e536ad8bc26094252baa4606d883bd2aeed6b430152202e9b6cc797ff24fc365315ed67391374c1357c9a845f2 +CT: 252ea42b6e5740306816974a4fe67b66e793ebe0914778ef485d55288eb6c9c45fa34ac853dc7a39252520514c3cb34c72b973b14b32bc257687d398f36f64cc2a668faffa7305ab240171343b5f9f49b6c2197e4fbe187b10540d7cdcfa37 +TAG: 711ff33ef8d2b067a1b85c64f32f1814 + +KEY: 9a19e72f005cae1ae78b8e350d7aabe59fc8845999e8c52fad545b942c225eaf +NONCE: d9dae2ea8d2ffc31 +IN: 2110378d856ded07eb2be8e8f43308e0c75bc8a3fcc7b1773b0725b7de49f6a166c4528e64120bdf7c9776615d3ce6feeb03de964a7b919206a77392f80437faceb6745845cafc166e1c13b68e70ca2a1d00c71737b8fcbbbd50902565c32159e05fcd23 +AD: 1cd73b72c4e103afbefd7c777e0480f3f5e68c60b85bd2e71ef5caebb175d7fc6535d39f38f92c24f2eb0fe97d878ed3d5967c0bb4394a5d41f7d34cda6e1523d3848f049cde554a7d31e1afeab5d3e6150f85858335cbd28c8a7f87d528058df50eea06 +CT: 5f009fbce4ec8e4ca9d8d42258b1a3e4e920b2fbad33d5e9f07557d9595e841025193b521ba440110dd83958e8ee30219d952b418e98a6c624894aa248aedc0678f2d263e7bfaf54ca379fef6c5d2f7ac422ea4b4369408b82d6225a7a2cf9a9f46fd4ef +TAG: aa0a5fa7d3cf717a4704a59973b1cd15 + +KEY: ba1d0b3329ecc009f1da0fab4c854b00ad944870fdca561838e38bad364da507 +NONCE: 8a81c92b37221f2f +IN: 6289944ffa3ccea4bf25cd601b271f64e6deb0eba77d65efb4d69ca93e01996e4727168b6f74f3ccf17bd44715f23ceb8fc030c0e035e77f53263db025021fd2d04b87a1b54b12229c5e860481452a80a125cb0693a2ba1b47e28ee7cbaf9e683c178232c7f6d34f97 +AD: e57883961b8d041d9b9eeaddcfd61fa9f59213f66571fadffffdd1498b9b014f1ef2e7e56c3044d7f9fa7a1403a1169e86430a2a782137093f5456e142aad03a5f7a66d38009dd01b7fc02c9cf61642dedaf7cc8d46066c281ee17780674c3a36eae66c58d2d765075 +CT: 9c44d9135db0dbf81c862c1f69bec55a279794cdd29a58e61909aa29ec4c120c9c5a508d856b9e56138095714a4bb58402a1ad06774cf4ecdf2273839c0007cb88b5444b25c76f6d2424281101d043fc6369ebb3b2ff63cdb0f11a6ea1b8a7dafc80cdaef2813fa661 +TAG: 65c746f659bcbdcd054e768c57c848c9 + +KEY: 0cf8c73a6cffc1b8b2f5d320da1d859d314374e4a9468db7fd42c8d270b7613a +NONCE: 3c4c6f0281841aff +IN: 4434728d234603c916e2faa06b25d83bad3348990ecde2344368d1a7af1309bd04251bb2e0b72044948f8dea33cce2618283b6af742073a9586b26c1089335fe735141e099785a1235810a3a67ff309e2f0ce68220ba0077ad1a5dc1a4aef898a3b9ff8f5ad7fe60149bd0bd6d83 +AD: a38d09a4f1c9241623c639b7688d8d35345ea5824080c9d74e4352919db63c74d318f19e1cbb9b14eebd7c74b0ad0119247651911f3551583e749ea50ff648858dcaaa789b7419d9e93a5bf6c8167188dbac2f36804380db325201982b8b06597efeb7684546b272642941591e92 +CT: bdfbfea261b1f4c134445321db9e6e40476e2dd2f4e4dbe86e31d6a116d25830762e065b07b11a3799aab93a94b4f98c31c0faeb77ec52c02048e9579257e67f5a6bae9bc65210c25b37fc16ee93bda88fd5f30a533e470b6188c6ce5739fa3e90f77120b490fc1027964f277f40 +TAG: 4993ee9582f58eabdb26b98c4d56a244 + +KEY: 69f4e5788d486a75adf9207df1bd262dd2fe3dd3a0236420390d16e2a3040466 +NONCE: 6255bf5c71bb27d1 +IN: c15048ca2941ef9600e767a5045aa98ac615225b805a9fbda3ac6301cd5a66aef611400fa3bc04838ead9924d382bef8251a47f1e487d2f3ca4bccd3476a6ca7f13e94fd639a259ef23cc2f8b8d248a471d30ac9219631c3e6985100dc45e0b59b8fc62046309165ddb6f092da3a4f067c8a44 +AD: 0c83039504c8464b49d63b7f944802f0d39c85e9f3745e250f10119fa2c960490f75ae4dced8503b156d072a69f20400e9494ab2fa58446c255d82ff0be4b7e43046580bc1cf34060c6f076c72ea455c3687381a3b908e152b10c95c7b94155b0b4b303b7764a8a27d1db0a885f1040d5dbcc3 +CT: f0bb2b73d94f2a7cef70fe77e054f206998eacf2b86c05c4fa3f40f2b8cebf034fe17bcbee4dea821f51c18c0aa85b160f8508bd1dc455cc7f49668b1fb25557cdae147bf2399e07fcacaca18eccded741e026ef25365a6b0f44a6b3dd975ee6bb580f5fccd040b73c18b0fbf8f63199ba10fe +TAG: 4236a8750f0cafee3c4a06a577a85cb3 + +KEY: ad7b9409147a896648a2a2fe2128f79022a70d96dc482730cd85c70db492b638 +NONCE: a28a6dedf3f2b01a +IN: 791d293ff0a3b8510b4d494b30f50b38a01638bf130e58c7601904f12cb8900871e8cf3d50abd4d34fda122c76dfee5b7f82cd6e8590647535c915ae08714e427da52f80aef09f40040036034ca52718ea68313c534e7a045cd51745ec52f2e1b59463db07de7ca401c6f6453841d247f370341b2dbc1212 +AD: 9a6defddb9b8d5c24a26dd8096f5b8c3af7a89e1f7d886f560fabbe64f14db838d6eb9d6879f4f0b769fe1f9eebf67fcd47b6f9ceb4840b2dba7587e98dc5cae186ef2a0f8601060e8058d9dda812d91387c583da701d2ba3347f285c5d44385a2b0bf07150cbc95e7fcfa8ae07132849a023c98817c03d2 +CT: c2f109d6d94f77a7289c8a2ab33bc6a98d976554721b0c726cbf4121069473e62ba36e7090e02414f3edc25c5d83ac80b49ad528cda1e3ad815b5a8c8ae9ad0753de725319df236983abd3f69ab4465d9b806c075b1896d40bdba72d73ba84c4a530896eb94ffccf5fb67eb59119e66a1861872218f928cf +TAG: e48dc0153d5b0f7edb76fc97a0224987 + +KEY: 48470da98228c9b53f58747673504f74ca1737d7d4bb6dbf7c0cba6ca42f80b9 +NONCE: 56fb4923a97e9320 +IN: bc6626d651e2b237f22ee51608ddcffeba5f31c26df72f443f701f2b085d6f34f806e29673584cb21522179edb62a82427d946acabce065b88b2878e9eb87ed1004e55ef58f51ec46375ac542c5782725ff013136cb506fcf99496e13fcd224b8a74a971cc8ddb8b393ccc6ac910bd1906ea9f2ed8a5d066dc639c20cd +AD: df8ab634d3dca14e2e091b15ecc78f91e229a1a13cba5edd6526d182525ec575aa45bc70fb6193ffcd59bad3c347159099c4f139c323c30a230753d070018786b2e59b758dd4a97d1a88e8f672092bef780b451fd66ba7431cbb5660ea7816cdf26e19a6ebb9aadc3088e6923f29f53f877a6758068f79a6f2a182b4bf +CT: a62e313ecf258cc9087cbb94fcc12643eb722d255c3f98c39f130e10058a375f0809662442c7b18044feb1602d89be40facae8e89ca967015f0b7f8c2e4e4a3855dbb46a066e49abf9cef67e6036400c8ff46b241fc99ba1974ba3ba6ea20dc52ec6753f6fc7697adbccd02b0bbea1df8352629b03b43cc3d632576787 +TAG: 675287f8143b9b976e50a80f8531bd39 + +KEY: b62fb85c1decd0faf242ce662140ad1b82975e99a3fa01666cac2385ab91da54 +NONCE: 2f4a5ca096a4faf8 +IN: 03b14f13c0065e4a4421de62ab1d842bffb80f3da30bf47d115c09857f5bdd5756fd7c9ac3d9af1c9fb94f2640f7f4386cfba74db468e5288dbe4dd78bfe4f69e41480ca6138e8beacc6eaa3374157c713cfa900c07dd836eaecc8827fa3e70e052ae09e8473e2ae1a10b1bb669ef60a8dd957f6553daa8114918e17371f2ac327bd +AD: cfe3b7ab7550b0e8e2e8235fa0dcef95647ce6814abd3dc3f5a3bd7d6d282504660c34ad8341e4d11402c7d46c83a494d7ddb105e1002979023e0e3dc2978c9ae53e10eb8567e7a02b60e51e945c7040d832ca900d132b4205a35034fed939a1b7965183c25654931a9b744401c4649c945710b0d9733b87451348b32ba81de30ea7 +CT: 8965db3d3ae4fb483208f147276e7d81b71a86e7202ffc9b1eaade009bc016838dc09ca4bcf30887b2f4243fbd652cd90ebed1ceef8151ff17ea70518d03b0f2a24960aa7de9b30fa65c2e2d57360061aae6d9376e984e9fcd5e5dd0911a4bc8deca832ffb76f252bd7da523076593ba6b174f7d9fb0377e066ecbb6638036241e86 +TAG: 3d0fc53e9058c2be32aa0850e0fab5a6 + +KEY: de9c657258774d4ebc09d109a0fc79d66493ae578797cac4eb8830a6a4b547e0 +NONCE: b5e35fe3398efa34 +IN: 4d68fb683aa4f4c7a16ba1114fc0b1b8d8898610fa2763e435ded8771b3651078bef73d4dfd14e76a34cd5eb9ef4db4ead4da9e83f4ce50fe059977b2d17d687c29335a04d87389d211f8215449749969f7652dc1935a0f9a94538dc81dc9a39af63446a6517609076987920547d0098a9c6766cf5e704883ea32feaea1889b1554b5eb0ce5ecc +AD: 436ea5a5fee8293b93e4e8488116c94d3269c19f1d5050def23d280515457b931bbed64a542b317cc5023d648330a4b7adca14dd6f3783207b94f86ccaa0a0ac39b7db00ac87a99e3cd8a764ed9c75da8454479636ab2b29e770b166a5b75cacc425c919bf1ce9ac34afe6b4425c3d9fd2e48bc81e7d15516d60e592bfcc2ebefb660f0995f2b5 +CT: 97a97b8f0f5420845ae8d57567f9bba693d30e6db916fad0b971f553ad7d993f806f27ab8b458d8046062ced4778c004b4f958a4436141637c6039963308dea2f54008b7feab79650295ed41bf9e65e1a2d75ab1c7b2a70ebb9e9f38d07a9a672d3e95ea78afe9ac02f2566b48b0251aef6eeeca8bd15bd8d43b559426aa9d15d960ee35cb3edf +TAG: e55dbb21851e8a5b365f86d02518331c + +KEY: 6885bd333c336c7672db8ebdf24c1a1b605c5a4ae279f0f698162f47e6c73401 +NONCE: f0c4a213a6168aab +IN: fa905a2bfa5b5bad767239fb070a7bc0b303d1503ecd2b429418cc8feba843e5444ed89022fdb379c3b155a0f9ceab2979000a0f60292a631771f2fde4ef065aa746426609082969530a9c70ad145308c30ba389ea122fd766081511a031ce3a0bd9f9f583c7000b333b79ac004fbde6ec3eb2d905977ff95dcff77858e3c424fe8932a6a12139e6ec8d5e98 +AD: 8ded368f919efb522bb6a9ad009e02ffbc6a16536e34d95cdb34f1153d7cb7b0f3c2b13dd05cedae27cfe68ec3aca8047e0930a29c9d0770c1b83c234dcb0385deae7ae85da73a5f8de3dfb28612a001f4e552c4f67ae0e2ec53853289b7017a58591fd6f70b0e954876bb2f7ec33001e298856a64bb16181017ba924648c09fc63c62eff262c80d614679bd +CT: 0cb3d6c31e0f4029eca5524f951244df042fc637c4162511fea512a52d3f7581af097eb642e79e48666cb1086edbd38c4777c535a20945fabc23e7c9277e2b960aac46865f1026eb6da82759108b9baece5da930ccfc1052b1656b0eadaa120ed0c45ad04b24ae8cdb22ceab76c5f180b46a392ab45b1b99c612546e6b947f4d5c06ad5abee92ff96345ad43 +TAG: d3b541ac446c84626daf800c0172eec6 + +KEY: fbc978abb1240a6937ccc16735b8d6ed5411cdbc1897214165a174e16f4e699b +NONCE: 7968379a8ce88117 +IN: 1a8196cd4a1389ec916ef8b7da5078a2afa8e9f1081223fa72f6524ac0a1a8019e44a09563a953615587429295052cc904b89f778ef446ed341430d7d8f747cf2db4308478524639f44457253ae5a4451c7efca8ae0b6c5c051aaa781e9c505489b381a6dcba87b157edc7f820a8fbaf2a52e484dc121f33d9d8b9ac59d4901d6ed8996ed4f62d9d4d82274c449cd74efa +AD: 3913cd01299b8a4e507f067d887d7e9a6ded16dd9f9bb3115c5779aa14239fd33ee9f25756d45262dc3011069356425b5c81a4729594e17c9747119f81463e85625d5603d05e00f568b0c800bb181eb717be8d7a93166a504ce1bc817e15530c5bd2b3df1d4222245ea78a38bc10f66c5cf68d661503131f11af885c8a910b6dce70bc3a7448dfae00595beb707fe054d3 +CT: d152bcb4c24c3711b0fad28548dc4db605bbc89237cdbea7dbf956b8855d1161a0781f27bd56d798141e2ace339955efb98fe05d9b44cd011e645106bf47726183958cb6df34ce5766695f60bc70b6fe0fabb9afa009a8ef043dbf75f861881368fa07726625448fe608d578cdc48277f2dc53eaaf1bdc075269a42f9302a57cad387a82c6969608acacda20e1cac4596c +TAG: 945dca73cf2f007ae243991c4fbe0479 + +KEY: 77d1a857fbadfe01aba7974eea2dfb3dc7bf41de73686aece403993e5016c714 +NONCE: fdd913a321c40eb0 +IN: db8915bfe651e2ecb3ce0b27d99a6bfa7a7c507cfcb2987293018636c365a459c6a138b4428be538413db15bda69e697cbb92b154b7f4d2cbb07965225aa6865d7dcd1ba2c17c484b00b1986fed63e889f25a4966dc3ed4273f1577768f665362d7d3e824484f0dded7f82b8be8797ad951719719365e45abbf76324bc7d657799d4d4f4bb1dba67d96ab1c88519a5bee704f7214814 +AD: 3cb2c06c20cb0832bbacebfc205d77393ca1816346ea2681de4d3ab1fadb774ad273e4713290454496f5281ebc65e04cfe84ed37cd0aedc4bbe3decbd8d79d04a4e434876650e0d64309e336bfb10e924066a64acb92260b2dbd96735d03af03909aa6a80a6e89fda81037257aec21fe9be7e91a64e88e0a58fa38ecba4c4c4cffb61958f3c486cbb0b1d0b0014a2d1d3df248eec1ca +CT: acb825e6023b44b03b2efc265603e887954e8612b2ee134bdcb61501cfb9492952bf67be597c3a005b09af74d9e421a576d2c65e98104780feab838d8cb1bd135452ea39dc8907a4c1a6a9161805e4fa3e16989e6a418a7eea2582bf895da967028eab7c95d846a6de4b9980785814cf00484baa2f6de609912fff689bce6e854261ffe866bd8e63274605c7c5ad677bd7897ade543e +TAG: 938478a41a3223a2199f9276d116210f + +KEY: b7e9b90dc02b5cd6df5df7283ef293ed4dc07513d9e67331b606f4d42dec7d29 +NONCE: a6c191f6d1818f8e +IN: 2ada0e3c7ca6db1f780ce8c79472af4e8e951ddc828e0d6e8a67df520638ff5f14a2f95a5e5931749ae2c4e9946ae4d5eb5de42fb5b77d2236e2e2bd817df51be40b1b8a6c21015a7c79fe06dba4a08b34013dfa02747b5f03930268404c455dc54a74d9c6e35485e10026da573cb41cd50b64cfafe4cfcdf3c9684ef877e45d84e22bd5e15fa6c8fd5be921366ff0dc6fe2df45f7252972c9b303 +AD: 0f4269ed5ef0bfff7be39946a4e86e8bf79f84b70cd0b14fecb7be3c071316ce86de3d99d6871e0ba5667d9d7bba7dcaba10cb2a36668b6c3e2fb6c102938b75008bb9c213ebf9b85b5e91a802df0d31d7f11d764b2289f6225212694ab6b7c0e3ff36e84245d9f4f43fc5f98e654dea7ba9bd918658879c5bb4a1642af0d83113e3cf935d3c0d5208318f66f654eb17d8c28a602543e77ad3e815 +CT: 22586fe7338e99cdaad9f85bd724ba4cfe6249b8a71399f9a3707b5c4323b8d96679568dfc8d230aefb453df596e13eb3e8a439249bd64bc93a58f95089a62b94f6562b821c83d91f56c55147381e9de4beb4ae81bd6fe7caef7e7e9a2078f2fba8f3e70d4910da9accc92b8e81a61b0fefbece4bd89443e66e8ddda8e47a66a62f17fd0e7d0a4852ce1a4d43d72a0b5e8914bbec698f060f2b092 +TAG: c082470297da8c5f682a169d28bc0239 + +KEY: 6b2cb2678d1102f2fbbd028794a79f14585c223d405e1ae904c0361e9b241e99 +NONCE: 7b3ae31f8f938251 +IN: b3cb745930e05f3ab8c926c0a343a6eb14809fd21b8390a6fcc58adb5579e5432021765b2d249a0ecf6ba678634c4f53f71495865f031ee97aa159f9ead3a3fcb823ee5238bdf12706a9c6137d236e2e7110ce650c321e41daf0afd62bab2a8fe55d7018de49a14efe6d83a15b2f256d595e998d25309f23633360f5745c50c4e5af8ccc9a8a2cb47064105a023e919c7795d2dc331d3f2afb8c42e5c0bcc26d +AD: 1c32fd3df22b3e440e2a3c7a7624990194cb16a5f74af36f87fd6ca7d410ce9064316a2d091945deef7d9b35ceec8396069307caced2b80afd7d53ec479c35cedf2dfd4c95c3dd8400f71ad34028c6e4f8681d93d0774064ba38f3fb9b0c1dfa1f5f0c7d20676a5911d999fb6a1d41367a8e99d852bf3d3b7b3f4c233249ed1ca135389a674ff48232ded3f6800a97b6d409c40e6cd70d09bf9d2ad25d9b9485 +CT: ef70c7de98ab1d4ad817024a970be463443640eb0cd7ff234bdd00e653074a77a1d5749e698bd526dc709f82df06f4c0e64046b3dc5f3c7044aef53aebb807d32239d0652dd990362c44ec25bf5aeae641e27bf716e0c4a1c9fbd37bbf602bb0d0c35b0638be20dd5d5891d446137e842f92c0ee075c68225e4dbacb63cc6fb32442b4bcda5e62cb500a4df2741a4059034d2ccb71b0b8b0112bf1c4ca6eec74 +TAG: 393ae233848034248c191ac0e36b6123 + +KEY: 4dbc80a402c9fceaa755e1105dc49ef6489016776883e06fcf3aed93bf7f6af7 +NONCE: 2358ae0ce3fb8e9f +IN: 197c06403eb896d2fa6465e4d64426d24cc7476aa1ae4127cd2bd8a48ce2c99c16b1cbf3064856e84073b6cf12e7406698ef3dd1240c026cbd1ab04ee603e1e6e735c9b7551fd0d355202b4f64b482dd4a7c7d82c4fe2eb494d0d5e17788982d704c1356c41a94655530deda23118cba281d0f717e149fbeb2c59b22d0c0574c1a2e640afad1a6ceb92e1bf1dde71752a1c991e9a5517fe98688a16b073dbf6884cfde61ac +AD: cf6ce7b899fb700a90d2a5466d54d31358ecf0562e02b330a27ba0138006b342b7ed6349d73c4c5c6d29bde75a25089b11dac5b27adea7e7640ca1a7ceb050e3aae84a47e11640a6e485bd54ae9fdb547edc7313d24a0328429fcffd8b18f39880edd616447344ebeec9eadb2dcb1fa7e67179e7f913c194ebd8f5a58aea73b0c5d1133561245b6d9c5cfd8bb0c25b38ffb37db5e2de5cdded6b57355e9d215cb095b8731f +CT: aa87f9a83048b6919c8f2b050315db4e2adae4a9c2ca0109b81961b520e63299dcb028cec0b9d3249a945ee67dd029b40f361245c740f004f8cf0d2214fcfa65e6124a3e74b78aa94345c46fdc158d34823ed249ee550431eaae9218367321cdd6e6a477650469bb3cc137a8f48d9cf27934b16703608b383d2145659922fb83bb2e7ee2ef938a90f2ff846a4a949129b1fb74dde55c5ae013c2f285de84f7dac7d1662f23 +TAG: 06b4318ac7f65d556f781428a0514ffe + +KEY: 9e4a62016dae4b3223fed1d01d0787e31d30694f79e8142224fe4c4735248a83 +NONCE: 263a2fc06a2872e7 +IN: 5a46946601f93a0cee5993c69575e599cc24f51aafa2d7c28d816a5b9b4decda2e59c111075fb60a903d701ad2680bb14aeda14af2ae9c07a759d8388b30446f28b85f0a05cd150050bd2e715ff550ebbd24da3ebb1eac15aba23d448659de34be962ab3ab31cb1758db76c468b5bb8ce44b06c4e4db9bd2f0615b1e727f053f6b4ffb6358d248f022bcad6ca973044bed23d3920906a89a9a9c5d8024ec67d7f061f64529a955ce16b3 +AD: 4cd65f68f9f88c0516231f2a425c8f8a287de47d409d5ecde3ad151e906b3839fb01bb91a456f20ea9d394d4b06604ab1f9009ef29019af7968d965d1643161ab33a5354cda2fdc9f1d21ec9cb71c325c65964a14f9b26eb16560beb9792075a1597394000fd5f331bd8b7d20d88e5f89cf8d0b33e4e78e4904bb59c9c8d5d31ac86b893e4a0667af1be85fdb77f7ec3e2594a68048d20c2fb9422f5879078772ee26a1c560cbcbb2113 +CT: e944bb2ab06d138ad633c16ce82706ecf0ef5d119be1f3460c9ce101d9c4e04ef1677707fca40d1f8ca181e07273707b06624d6d7063c3b7b0bb0151b757b3e5237fb8004c161233d8bc7e5f28ea1c18da1874b3d54c5ad6ff0835eed35c8853704585cf83996e5e7cec68180af414e04f08134d3b0384ebdf0393c9310b55d8698fe10cb362defc0995e9a13b48b42cff61ffd9fe4c3c8c6dab355713b88f6e98a02e7231a0c6644ec4 +TAG: 27de0d4ca7648f6396d5419a7b1243b7 + +KEY: 18ca3ea3e8baeed1b341189297d33cef7f4e0a2fab40ec3b6bb67385d0969cfe +NONCE: b6aef34c75818e7c +IN: ef6d1bb4094782f602fcf41561cba4970679661c63befe35ff2ca7ad1a280bf6b1e7f153fa848edfeffe25153f540b71253e8baba9aeb719a02752cda60ea5938aab339eead5aabf81b19b0fc5c1ed556be6ad8970ea43c303d3046205b12c419dea71c4245cfedd0a31b0f4150b5a9fe80052790188529ab32f5e61d8ccde5973ed30bdf290cbfbd5f073c0c6a020eac0332fced17a9a08cef6f9217bd6bef68c1505d6eed40953e15508d87f08fc +AD: f40f03beaa023db6311bad9b4d5d0d66a58d978e0bcbbf78acebde1f4eb9a284095628955a0b15afc454152f962ec3ea2b9a3b089b99658e68ede4dee5acd56672025eb7323bcbc6ba5d91c94310f18c918e3914bbbf869e1b8721476f9def31b9d32c471a54132481aa89f6c735ab193369496d8dbeb49b130d85fbff3f9cb7dccea4c1da7a2846eef5e6929d9009a9149e39c6c8ec150c9ab49a09c18c4749a0a9fcba77057cdea6efd4d142256c +CT: c531633c0c98230dcf059c1081d1d69c96bab71c3143ae60f9fc2b9cd18762314496ab6e90bf6796252cb9f667a1f08da47fc2b0eecda813228cae00d4c0d71f5e01b6ce762fa636efffe55d0e89fdc89ba42521cc019ab9d408fcd79c14914e8bbf0ea44d8a1d35743ad628327e432fdcfeb0b6679ddca8c92b998473732abd55dba54eefff83c78488eee5f92b145a74b6866531476fc46279d4fde24d049c1ce2b42358ff3ab2ba3a8866e547af +TAG: a0a5242759a6d9b1aa5baf9a4ef895a2 + +KEY: 95fdd2d3d4296069055b6b79e5d1387628254a7be647baafdf99dd8af354d817 +NONCE: cd7ed9e70f608613 +IN: 0248284acffa4b2c46636bdf8cc70028dd151a6d8e7a5a5bc2d39acc1020e736885031b252bfe9f96490921f41d1e174bf1ac03707bc2ae5088a1208a7c664583835e8bb93c787b96dea9fc4b884930c57799e7b7a6649c61340376d042b9f5faee8956c70a63cf1cff4fc2c7cb8535c10214e73cec6b79669d824f23ff8c8a2ca1c05974dd6189cfee484d0906df487b6bd85671ce2b23825052e44b84803e2839a96391abc25945cb867b527cdd9b373fbfb83 +AD: 24a45a3a0076a5bcfd5afe1c54f7b77496117d29f4c0909f1e6940b81dde3abacb71ec71f0f4db8a7e540bd4c2c60faee21dd3ce72963855be1b0ce54fb20ad82dbc45be20cd6c171e2bebb79e65e7d01567ad0eeb869883e4e814c93688607a12b3b732c1703b09566c308d29ce676a5c762a85700639b70d82aaef408cf98821a372c6a0614a73ba9918a7951ea8b2bb77cd9896d26988086d8586d72edc92af2042ff5e5f1429a22f61065e03cfcd7edc2a93 +CT: 40c6318d9e383e107cdd3e1c8951562193c3ef64ee442432a63e2edefc78f32ab07772aeac172cb67ecf4d21f8b448423527bbeb9d8ddd0b46bdb27f74096ceb24e41963b4cdca176676a75bdbe3abc270b349ac0c6cbd9c3a5cd5bce20202fc5cc0c1bdd4fd25e121e0a24bd7bbeb9b19b1912467bf5338ee2ce88aa383c082b42cc399c9654ca325f35523e81438beb3f8926be79c378822d7c8f785614408a5f7cac49e4543188725643e6c1a70b46d0ec400 +TAG: 5801e84192c7267f66b0e04607a39a3e + +KEY: 6ae1102f84ed4dc114bb9d63f4dc78d7dbb1ab63f1659dd95f47940a7b7a811f +NONCE: c965d578ba91d227 +IN: b82a8a9209618f1f5be9c2c32aba3dc45b4947007b14c851cd694456b303ad59a465662803006705673d6c3e29f1d3510dfc0405463c03414e0e07e359f1f1816c68b2434a19d3eee0464873e23c43f3ab60a3f606a0e5be81e3ab4aa27fb7707a57b949f00d6cd3a11ae4827d4889dd455a0b6d39e99012fd40db23fb50e79e11f8a6451669beb2fbd913effd49ad1b43926311f6e13a6e7a09cf4bebb1c0bf63ce59cd5a08e4b8d8dbf9d002e8a3d9e80c7995bb0b485280 +AD: dfd4ac3e80b2904623ff79ea8ee87862268939decf5306c07a175b6b9da0eb13ac209b4d164755929e03240a0fe26599f136fb2afdffd12bb20354aa1d20e5799839abb68ae46d50c8974e13e361d87ef550fe6d82e8b5b172cf5cd08482efdef793ede3530d24667faf3a1e96348867c2942641f4c036981b83f50236b8e8a10b83ebf6909aad0076302f1083f72de4cf4a1a3183fe6ec6bfe2e73e2af8e1e8c9d85079083fd179ccc2ee9ff002f213dbd7333053a46c5e43 +CT: a9aeb8f0a2b3ca141ac71a808dcc0c9798ac117c5d2bd09b3cfe622693a9f8ca62e841b58bddb2042f888e3099b53638b88dfc930b7a6ee4272d77e4b1d7e442bab6afbde96ab0b432f0092d9ca50eef42f63c60c09e7b8de019b32ebe4030c37b8183cc1e3b913b0ce4ee4d744398fa03f9af1c070bed8cdafd65b3a84140cb4deadc70184de757332ce3780af84353f540755227e886a8d7ad980f3dd6fd68263d82e93f883381dec888bc9f4f48349aa2b4c342cb9f48c6 +TAG: f26b3af8a45c416291ce66330733b2f8 + +KEY: 405bb7b94715b875df068655f00513cb1ae23ffaac977ce273e57d3f83b43663 +NONCE: 5c6da1259451119a +IN: f9f143c0c52c94b4ba7b0608b144156a49e7b5d27c97315743d171911e3645ab7957c80924e3c6b9c22ab7a1cac4b7e9c0de84e49fd5e4a2d1ab51d764fc5670318688ec942f7ab34c331dce8f90fea6972e07f0dadec29d8eb3b7b6521ddd678a6527a962f4d8af78c077e27f7a0b2ef7eabd19e92b7f8c1e8fb166d4763ce9c40c888cf49aa9cdfc3e997c8fe1cce3fe802441bbd698de269ff316f31c196e62d12c6bb5cd93fb3c79ca6369f8c1ac9102daf818975ea7f513bb38576a +AD: 6fe6446505677bf08b385e2f6d83ef70e1547712208d9cebc010cba8c16ea4ece058d73c72273eed650afdc9f954f35aa1bdf90f1118b1173368acbc8d38d93ebf85bd30d6dc6d1b90913790c3efa55f34d31531f70c958759b2ba6f956c6fcdd289b58cb4c26e9515bf550f0fd71ab8527f062c9505cbb16e8e037d34de1756bef02a133dbf4a9c00ac03befc3fb7f137af04e12595ce9560f98b612480fcdba3b8be01db56ebec40f9deae532c3b0370b5c23a2a6b02a4de69efa8900c +CT: 1a4b073881922c6366680cc9c2a127b26f264148651b29abb0c388cf6c9b1865dba5a991e1f8309efbdb91bce44b278772c58fd41273526c33fec84beb53d1689b9da8483f71be6db73a73417069bb4cd3f195236e8d0a00d124eed3a6b6f89415b19a27fbe35774f6a1a6ee4bd4350b252b975f0db2d2eea82f4836350850d6290901e726e8af13644e2d98bc1d569c20800521e6affe976bd407049a2e6d9dd23f88d52e651391ecd2fc45b864310824aaadfa203762a77c1d64562dae +TAG: 0060026d3efc120f11c0739959ae0066 + +KEY: 8c602bd94c630cd00c7a9c508067a5a9f133d12f06d9f6fe2a7b68dce4786d8a +NONCE: 760de0f7b7cb67e2 +IN: c3ff559cf1d6ba6c0cc793ca09a0ba573a28359386a6ec93e1bacd8e630209e0b477a20aedec3c9cbf513ee6a1e3887112218d6155b9875f7e6c4bbba2c31972e905d19f529f4f0f9502996199f94f8728ba8d6424bb15f87fcacd88bb42c63fcc513759712bd0172b1e87c9da122f1993ffb7efd3a5c34b240dd3db89dddea36dbeb2836d9f8648f8e7cd428c0f948097af753b35f9876059e7702027bb00dc69071206e785f48fcbf81b39cc0343974ac70784a2e60c0df93b40379bea4ad8cac625 +AD: 9e14907c3a8e96c2636db1f3d78eb1f673d6ef043cbbb349467f1fe29bf60f23d5d5d1c3b133a8ad72065d822347541c13d1574baf737eb3cc3382fb479e6d5193b9c8e7d2444c66971ef099dc7f37f6cd97b9f7959d46e2cf25e8a5b3111b4d9e2ef906d905f0ee2d17587f7082d7c8e9a51509bde03d3d64338e1838d71700f1b4fcb100b5e0402969da462f26f974b4f9e766121f8fd54be99fc10beb9a606e13fbb1f960062815d19e67f80093360324013095719273c65542b0e31b1a2a3d928f +CT: 2794e6e133f6892f23837fff60cf7c28ee9942f8982ef8089db117903d0143293fdf12ea1cc014bcd8806fb83c19570eed7af522db0de489bbc87133a13434518bcfb9cda4d9f6d832a69209657a447abf8afd816ae15f313c7ea95ec4bc694efc2386cdd8d915dc475e8fadf3421fbb0319a3c0b3b6dfa80ca3bb22c7aab07fe14a3fea5f0aee17ab1302338eeac010a04e505e20096a95f3347dc2b4510f62d6a4c1fae6b36939503a6ac22780a62d72f2fc3849d4ef21267fffdef23196d88fbb9b +TAG: 457cce6e075ffdb180765ab2e105c707 + +KEY: bd68ff5eb296c71cfe6bc903c14907f7726bcb1331f0c75f7801cd1b7948f3a1 +NONCE: 65a748004b352ba6 +IN: 52bf78c00f6e5dca2fc60e2e9a52e827df97808e9cf727773860cafc89f4b64178a19b30b46ed813fe00c8f09b25a6a1b6e350d5b005122934a59bfbd5e6e0c635c84a5226c3f2f7dcf951560f18ac220453d583015fdb2e446c69c6e6fdecf2e595e04fab1b0c506e3c6bd5e4414a35f15021e97f447aa334f54a8f1ef942dec6273511b5668b696fca97188ff15ed84b2f46145cce031c1a7f00bd88bb83d90797edc46161b3fda7a2299173496d73b812139556e8b4eb318078b9eb2ae5046e83b79dd3d45950 +AD: 5557b08a5010cbc9f46bb140c2505f68684eb24889324bff44b27234fd7a95a99cfb4ff90a8f9982085b725f78ac42eca6ce7f3314e457dc41f404008681a9d29ba765660de2e05bb679d65b81f5e797d8417b94eb9aabbd0576b5c57f86eae25f6050a7918e4c8021a85b47f7a83b4c8446898441c5cc4e0229776ef3e809cb085d71f3c75ec03378730cb066150f07e60f96aec983c0e7e72bf6bf87ae42228dfda195f97855fcdf4e6d1c4479d978abcfa276d16ed60ecbfbfc664041335ce65a40a2ca3424df +CT: a5c8cf42287d4760fca755e2111817b981c47e85b0047de270ec301ca5f7b3679f4749210892b6ea6568f3a6a4344734a0efc0120ffedecf212d55cbcbb67815ac964875af45f735b70092a8f8435f52fc01b981ae971d486026fb69a9c3927acfe1f2eab0340ae95f8dbee41b2548e400805ece191db5fd1f0804053f1dbfaf7f8d6fded3874cb92d99a2729d3faaa60522060cf0b8101b463b3eb35b380fcddb6406c027d73fe701a5090c8dd531c203ce979e26b9ced3431e2b726a7244a20d9377bd62951bf5 +TAG: 4579fa1fdb4c674cc3cd232b8da52a97 + +KEY: 934fd043c32d16a88fad01c3506469b077cb79d258b5664fa55ad8521afdcaa2 +NONCE: c7091f6afbbeb360 +IN: 2bdd1fc4f011ef97ea52ec643819941c7e0fb39023c2f3c7683804a0ddee14a5d1784a5246966d533b3538edc7d8742d27061c3cab88df0318ab242102de3a54d03632eeb871b72c7e8f8065b49f4a91e95e15f3f46b29fd76b8fcea0d23570c5530e3bbb8a6aafa9ae32c1b3eac653c5ed5fdb2da5a986075808f6385870c85b1913e26042a9d8e78f5bc2ea6de5a64f8aeafa22adcffc7f6932d543c29bb3a04614783f948680e433a71573568d2ce984d249fb4fc06a9f358c76aa3e64a357f4eae924c1356bd5baccf7e0f +AD: f737dd85638eb324dd3891219c5eef7c2dd053cfd055d447a411eba304a4b27dce981d112c4540590933c153d603022c91ebd2b4a58069d27e6ca17a462ef822ca41bffa80b43a68b1b564644cb3c5a7f0fddf7a13a30ff24437fddd8ef93c6f6f205d054f81890d982bd4d4ece0b1563677e843fe48c1f54e9a57ed4da66061482712e710a401073be5080d5b8b96525bffa67de5af31d50385fbbf1a87c21bf0e0a1fdff69ec32c7b7103e0b8ee6c844245e0fc84b9f89fcce62966cea68e2871d3b82e8df424c76309fc88d +CT: dd13fbf22c8d18354d774bcd18f7eb814e9b528e9e424abc4e3f2463195e8018576565d16ab48845d11c9277f2865ebb4dc412fd5b27078f8325eadf971e6944c66542e34d9dda971e2aba70dbd3e94a1e638d521477a027776b52acf90520ca229ebc760b73128879475d1cbe1f70fc598b549cd92d8a9ac6833e500c138c56474db84cb3d70b7aa4f293a4c2b4d818b0ff9fd85918dc590a12a8c0e375c4d98b7fc87596547eb960676aad5559834588f00f251a9d53f95c47af4df3c4299175d5211779c148cfc988a5e9d9 +TAG: 476616ea15190c1093fdc4a087643cae + +KEY: f9f6eb9ad736a8f66e7459fef5ec2890188dc26baf34a95f6f0384e79f5c6559 +NONCE: 7858dfc084fe4b0f +IN: a644ca6e7cc076e87eb2929fd257693fce0f6fb64fd632f7f07c648ebd03696c8e262e6a810d7b7c4e5eef8c65b5323c99dbba50a70b4a9e5c2a9e7315973cd67f35d8052ce9a85a206416dd3031929f4f929b13d0a5fb10cb73c65f6c0ace019da146b51c5274a099f44e3669d26add6f2ff081e886f3cf952fe0dbbe6b0534c23e307574bd35fbd657f5fcbd5dc19fb382a1dc0a2dc8285a0350f71554e4c601497749e35567dd4a273cddc9a48ce53a5f1d297fd8baf8d1b9feb35d9151114345abada4d90db947bb9a743c175f5653d1 +AD: 2048d1c2ddfb5ec385b201832c7a993f229ba72ec16d6ebf723ef0c5032b9966209a9e8a63151b40412e96b82f86728ea6588c7e8e11ac71cc8eabab8c4b54de866658d9c5011def61fb3dbe4e630158a45ea41a2ed55ebd1efb1abeda7637de6fa5fd2f151c6d2f385bf6cd002ca8b4a2896e0d65944ee913e3c784669dd201b1985ef3577f7f123a5f9bcffa176c8f557c4f729133cac518642f27d9b22ca9b97faaafe5b669a10b79ace4a7d5727df146c77ce681357d69f9c2d65b4401bd73cd113387e3b3a05d897adad7a24c485e7b +CT: 4146faffd7313f5d9f625370d20413cc62ab65f4acfa3c7ee1125b937dd7a39f638fc46c8ed004fb525698de5d8620ec153435571817c3de257b0d0e648ebb92940c86a98262d54e764f28cbdd4f7d9bea970291f2110414f62064d7229c6332236c507b3dac742e651d85a2a22fb243c0cc7cc2d016e5bea38f33f9a9ce048944a5fe8b078d71d23168e12dfe5a0f0b829771edc7073fb96032b7be471337a37aca0cf7c0cdd543eed686cd34934717fd79a3f18492eef72f9f450b880aa7e2e1b65e3b04c22e72301338b43aa32ceec2e6 +TAG: 10ffaf2be316676da02d7473a9df87b9 + +KEY: 29b19636cdd32507fd98ec4ee26caab1a917646fb8f05b0dc01728a9f4a127f0 +NONCE: 06699d245916686d +IN: 5fdf913aceab1d6dbaf7d9a29352fa8a3eb22718043a79cffa2fe8c35c820aec7c07644b8785dcf7a433b4189abb257fb12b06fae0662641011a069873c3e3c5ccc78e7358184a62c2005c44b8a92254958eb5ff460d73cd80284d6daba22c3faba046c5426fe8b7cacec64b235a8f8d3e2641e5bc378830594bcfb27c177aea745951ee5780a63705727ef42c4ad3abf556d88e3830f3db6b09e93edd09485cbf907f79de61f8dc5cb5fb7665ffa0ef53cb48702f6a81d8ad421cef20c1dbdf402b8fafed56a5361b2f93f914a2380fdd0557faf1f4de +AD: 39116c49cc13adb065b92cb7635f73d5f6bf6b5ccbf72a3f65a5df6bd4a661105015358d9e69f42e98aed795e8161282bc113058b7ef3b9e23fcd8eeab34a392e03f4d6329c112cb968385ec52a7afc98bb8695785af6b27b700973cc952630b7247ce226b4fbb99b8a486370bf6345d4516c52c64e33f407c4f2d1ba90545c88732d98bbd97972ac5e94c694624a9b3782b0099824651cb7567914d25b3e13181a791dbcd40e76e836b3350d310a52151bf835d3c357c9871482c2928e8404c6e533406d4d6fa8f63366f2c4ed828141f1ff00f01a536 +CT: 01e237220b619054a1f3670928fe67d40484b5af40fbd04d032500aac5acaa3b4584dd99a58c390627636a50de5d744f76a56a33205f9e3b00e16162eb47ff3333e1e208ca200f1a5338a86e17bd92dd2d16af8bb022a7dc05b923d019e05247f1a0d0b4bfcfce58dd6d83830705707676d55739abee89fcd5cb94b8fde006a5da02df64b00a467f45970b5ca440f22319b9735a55d454b9fba0588fef0c59d3d83823eba6e0601a96e10233826c5adeea6b2a51d386a07a9e047ad405b23d4c3d89f30c31e3199f0c8f927bfac43ceea1f969de0a8c0f +TAG: 092f9f3c5d4f2570c9946c87967f4579 + +KEY: bae06b9b5456707551c7b0e207aae02a19b4848ad8ca4ce40705bf8c856a6e52 +NONCE: 9c27065c3ef2d522 +IN: 50cdd88137ff428a88e87b5845be4924f6387537bb5c0b654c80107ab5698db75b2e131848e7aec156d31aed0766d31c379fece4095d38264c6d5945974d25f729c3b0ba11ea853e9cebdb6f03bb670fce08adff74d0a8f02d633fb34e0fb7337a8e66e1c12084d914fb6173b8105684db822752c6751a372bb16690284d661b8b8bc6a6dfbddf45ebc2219596f9f2f878c118df69030de38b4d99dde43b9b9e20a3dab691645dd518342f49b06a0fe0a397adf261e99f07af5b0b3798b1022ba0939c42a54d3b93641cffa3c2e174bce9ab7ad7e7c7924308d1a77a +AD: 5d5590db1bd316eb7a0e30e4c7a6dfdbef9d3287fdb8d824389599c3c2ee262b2192eb5b9708e66e22dbc7eca83fa1a995da3ce64c86fe5aa08b826d476dc439497e2d12e2702c63c8d27aa7f09fedee816dc8bffe1351d53271a34d4292b613b7efcedb7e3cf3e6ad389eef12471e9e20e38e7ae22a323abbadfe8f2e84271bffb1819feb4f77b82843cb8757cfae293631bc6d39669107e7015c85d7343ffa6fc1bbe6f5ab4de30cd752a281e03061ea89de2a3f5e90e20da22fd6e8525c100738667f42212b2cf45fcb23bbb54b21c117484b22c6e514685314df +CT: 66b7f69ac49fab4e5975aeb6fa9287d8eac02ac312c4de78f77f59da16cbcf87274e66801c4b862c33ea79cdc76528862bb2956c06db8b8acfac4794ebf39e35ac03cc73a4351a4ff762f681a48d6f25cad36e2814c9b5c40b9ae92509e58429106847789454d376836936bebc7a80e6c66e7aa52936d6b361378a41f849ad4e48f9ee2d3e92217a908fa8eb35736ac8ada7d32ae05391f2d807be3512543c36138a5fe660dd4cd4cd184bb43b6ba6bc0bae634e2fa9669304cd510ed5103f630068ff76d3375738de60a381842b421477e25a490cdd6894b2704125 +TAG: c9998a677dfb0e91924aec9de0afd585 + +KEY: 2cb374cb048c168f2e43597f028d9e73cade1b458284ffc260d4fc6b9011c414 +NONCE: 9fb909169bc9f4e9 +IN: 39eb929482784b463546f5d84f80510f2019923d465b99d194246d68c7ae343f91971d8f7059cebb86aa5dd099289aa648248b8c5ca04e66ac5e9bf06776e3883495397618a0227f035666806e636836b47d3d2d255a49db79866cf00d9ddabda259c4f968a1e01e651c7811cebbee2ee71803ea1d9d23487eb221f2d9555756800aba5e6abbefd6fb72b3151cc99ced599cd86df2a9b1ce94f89f347eeb124d9e7f0d9cc48d3dedd819e6d3dbac57ecee199547b266116a2035c9acc4c8ca3271ac74952372897c4a5f2cb84e2d81817fec9d6774f6d8a5b2021684132db4fca3 +AD: 0c7bd4f3a30ee944ccf9489181e6911684dcffad4593a9b65a67dfc80718c69b35897d01281016b7731e12c15cad8482e79458e08a755622e3f3f22a23ef6c8487a36ad1771ba06c641f06f85de0db3776cc6df06ad8fe3b4d60d58508de943083f17cbb9dc0d390ac94d8429e8c6fcfe063f424fbde0f62f6a7f91a626d195dc498a6e69bd93109c4e9ba13e7330aba456d710a4b0cc279d4045660406e26d61dff70d4a33c4f1052869f9248024e7a0f85f1effb32f6f7ccb1f860f3ef04e8f7b29096e6bcf9d4b3e0ce703e9bf228fdf515c2ff9cbabd16987be0f9babd3d8a +CT: 91ddadb86b7ebef798ddaa59da51d71316fcf6c9678143178227d778750dc9827fc6cc21e605c505023e6db25849df7fb6fc1ca4d223aa215f8c85b724643c83bf8218815a9f9e2952384e0ca6a80a3760b39daf91a3c6154c4728c2371fd181fa3764753d0b0c23808a82cd8f0497246e3a0f17f8906a07c725d2891ce968a9d432c2b102d85c05510b28e715bb60d0403a77490e7f18be81218bc4f39287b9bb09f50227dd2f55e4fb70c4438da8ba3c8ffbced87d90155913faa9979fc57e6cbeddfaba3d3ab4163c0eebc7d94279c27d3ed56338893dba542eaefba30f8c3b +TAG: 728e60f8124effbac234f70da925881c + +KEY: f0f16b6f12b3840bbd1c4a6a0811eef237f1521b45de9986daec9f28fca6485c +NONCE: 7ac93e754e290323 +IN: 0530556424d823f90a7f1c524c4baa706aad2807e289e9479301e3e7a71f2a5e14e6232ea785f339c669af2e6d25f1d5a261096a548d23864945c3a589b67b09b0304a784d61b42b2419139485242e0d51fcbe9e8fed996d214de8717e6a71f8987ccad65eb92e66707034a5ae38e6486e26eb4374c565aad5df949dab209f7f7bcd8eb6fc52761a26cfe5d01fd349e59f4042e6dbe6b232f9301b971dee121d8aa1e62d40f043a42f3aa859d867eb809b1ced5ae1ec62cacf94a69fafd0631a8b5dfd66d855900fb295eec90ae5fcbf77beae267a79d24081bb322d8c4e0630fed252541b36 +AD: 13bfcc17b810099cda31ca53a1323db9b07633ceb2088a42263a4cbd6a4d47978776005c9a20203319c3a3ae434e9a26fb541047dc9df38dc36c095267272e203d0b24d119a70a7e96041b6d82b7c4d5570e1e4a1cf2f6e44ae63fe005a1f5b900778c482f7bd89e2e02305e35b8f61b7bb2c78a13aebfce0145d1c5aa0bf1d10d23616d5a3a446de550302f56f81dc56fe4f3700f14242688d9b92d8a427979b403c8de8c493a2cde510eaf6b285e6675b173aa0314a386b635c7577d5aff0d868a0cb3f73c8d2005f8c7c9dab5a060ef80102c9d4a4af988838afe87aff04c0689e8c3c7f9 +CT: 2c14c3931e98e84507c4c165c2ed47ad4a178f0e216cd7ac2453bbbf9f85dd06bd8ef54a9ff1fd3dd8e0cafb635d8f2de861a0db5b14d03f17aaea8c89b3010797c71c13a0e666899d7ff6e53c4f08be8ddb3e37688b5afa088079b6c7519b833e16560073e699530302028a3496e05edddec01a23a4c7983956250e8d9e616f7b940856955cde81c1efabf6b7b92f153d03f4cd17e7f7d2907670cfc84d45c1d7936775a3fce47968504278ffaecacea0871b227f250e2979516f6fa310fec0d8df1af7872e5a534e82870aa05f43ef0a455846b93ce938064fa33e92de262e4156dae56775 +TAG: d95d73bf9aeb71eba9042396f3725424 + +KEY: 3792943c0396f1840496917ce8ad89608385007e796febeea3805f3f4cbeccf7 +NONCE: 23b2f9068b2c4c85 +IN: be6b67eb943ee7b5c785cd882f653e73a8f75b4a41a2a7c56ae5a10f729caf39948fe48ad0e51240e2e7aa43193c7ec6ce7f4909fc94c9f99e38e6a0ad7e98eb29c5c2e61c99e9cbe890f154185cec213a74725d23c1a4e4d0cb9b1a36b78c87e5eee20d2aa29aae80d4759eb0c51c5dc3a95bdbbf7e14eb434419a6c88a954ac03d0c98739f4211b8732acd71c297f578b8cb64ccac45f7235ddc7f2a3f5f997525c1ed39dc550126cdf9cedaf55425489085e91b170be6205a5a395f2dd4084a3e8dbc4fd8b13252f7effae067b571cb94a1e54aba45b1b9841308db0cc75b03cfce4ddafe89ce20f2d1 +AD: 7eb6d7b7bbaaa3c202a4f0f1de2263767169eb4a64853240d48c0f8d5d31b08d5baf42977614a57aad99426cde76d242cb37d2956d8c77dc4fd62a3abf30e8ac6cd58c8ef35e67497022960138c57787818892460f3bfc16e37ff388b1edc6ce2bc53c22717edc7a03d4c78b0dbbe9121c7fd8a3e3993b87a4fe389bff13bdae3b349de0b6db561602c53f746022aeb4483c723b67825042f4af20b7dd1e6031cf54215266295c524ac8e1370424c5c5e607fb3e23e97c8eebe64656775edf616422a8b974e1acf13ab45c9a367a7dd9b2d62f48bbc05819b65eccb813ca813f57b22ee4c280dbb5a9d8d5 +CT: 0b316ab2bcf5359900fa4082d5d253b49ad94b70e3fab544f98bd111cbcef6766cf953deec08cae1f489fe12f7acc0032db8a6b0c0eee0c206ea5fb973feaebf90f690e840094db5e13fdd7157ba127368c995b426529435a1bcdd1f14ce9125b8a0e4c96b6ec09e3c36a180adf81941c002d19c19d53c2009be803b987504606b7d43bdee5e0b32ff23c466b6cccfcd0d4e88fd1332e73712b5ab725c1a383e584f34f80daff29d285ae5e43cf1d0cc7a828e75c25daced3a581a93d7a50f313b33f38dddfaa23cd5b9914797db820ee2400d52bf5fa982277fe9b5881ac42981633b3957b0e935051828 +TAG: 01973ee2e81cef22751a6a8831d752ef + +KEY: fe4be6054773f634356ac328591fbc6f833b0d1beeb38dd5b6feb7481b4489d4 +NONCE: 0b3f16f898a5a7d5 +IN: 76ced1ade6d1ef4069afddb32e7432d4ff2fd06685121f7b16464e7a72d365744f547d2ccf53486310e38b42d8bacaf711e54c5458d2d68c4dbcc8de31ab6732f4430e88a64565f5b287640775aaa2af1cc461d3e415bb275c6246b1b58517aa72667eae291a2982eda175d1b22c5a58e6fec2b3743d55712f201ca24ba5c0ae8c25724871b2ec2fb914a8da5a52670ab9b43a83b8568ce74db5c634061cb80530c8070c38b8f48c33ba136cb9f2158ee7eda8b65f2192fc94d1291f182f101795b7190c74b319d2d3e02a97c824d9c9471a83797e4936310b207e3a1e0bcf75f7c3e3ee48a747641cdc4377f2d55082 +AD: 834cd775cbefe4b33a3ca53a00c06a3c4a666983e4115a029f15729460daa45d1505e95172d3695625a186b28b8be173a925af04665f209267b3c5123e8be13da447ee1ae856bb0925f35aaa76e04a7bca8460f76c2024de2149f38a8cfba81694b854885d72568105571b6b213a0bc188a44cc7fe13153cbf261401b238cf12a95e23cb56f240114f16e2f1e3a514615aab4449c0c49e4d900b0e17d1a8dabb53d43dca32fa052d576b73dd9b40856b515d6d7efc2a5c17e0ebcb17bd59dc86f22ce909301a2652f134e82ef0e4519487ed12d51536024f2ae8f75d937c42d003076e5dea8de0c684cda1f34253d8fc +CT: f8defb6fe95dfec499b909996a1f75a198a90e4d6c6464d00a357a555311c42fe92dbbc4b79c935e4f0b1a95e44fdbc1380bebabca28db4dd0d2870daaafc38ef27908c3509e945714801cc51f1a07b2430c74fa64f2a7c2f7fd1551d258c9c3be020873fc1bf19f33ab6c660911dcf2317195d0efee82d20ec26d22611f9cf86c51a64e28b3a1f344500018e0855c88dae3c07acaeaa10b60388484dce93e16e6e1a6e69e899806648a92568c8780e9f4baacd98cbb353ac2f908e775d92303cfab843f15be0e0c322a958802fb1a60fcc7631f151f4c2b8cb965d2d296acef250275a2fecc0cea803ce7c058b12dd2 +TAG: ade515091930dd7861b27f78a87ef60c + +KEY: a288b11ce5382ec724ce4ab2d7efa8e777e91ebd04367935e15f9dac483e9596 +NONCE: 874144dbf648b325 +IN: 4c9195280a79a509919af4947e9e07231695fd7c5088539f23936ce88770ce07d9ad3ae4a463b3a57d0634d3a77ceaadf347a334682b04be8e58b8e86fb94a1f93255132b8cdb0df86f5bea354eea4e8315fea83e3fdf6e58aa9f26e93caa08e5e2551a94bd916a51fed29ec16f66800cda6a0aa24ec308bf5fb885afba272685de27c1edcdd3668048ef07b06e90d464a8aa28664903cac45e154e8e1e39c257e1ff506b9d95cef4f300bb73b899e7828602c3c1d290b8cf55ee5fd72ecce9e6efc9293aebf674a70e2a7673e75629c12950622dff71d3ec0992e57776c788c6927d30b4e24b749191c3ce8017f0ada6276e43720 +AD: 04abe8588c8c8c39a182092e5e7840442bd1c1149da102c4ee412bd8b82baa5087ef7291b5cd077c177c42770b0023e0e462b06e7553f191bcb0315a34918dcdbffe2b99c3e011b4220cc1775debcc0db55fa60df9b52234f3d3fa9606508badc26f30b47cdb4f1c0f4708d417b6853e66c2f1f67f6200daf760ceb64ffc43db27f057ad3ee973e31d7e5d5deb050315c1c687980c0c148ee1a492d47acfcd6132334176c11258c89b19ba02e6acc55d852f87b6a2169ed34a6147caa60906ac8c0813c0f05522af7b7f0faddb4bc297405e28ecf5a0f6aac6258422d29cfe250d61402840f3c27d0ce39b3e2d5f1e520541d2965e +CT: 0afce770a12f15d67ac104ba0640aab95922390607473cbda71321156a5559906be933fb0980da56f27e89796eaa1054f5aacf1668d9f273cc69071b9e8e22af6a205a6a88f7ad918e22f616bddbb07c78913c7e056e769e6fcf91c7600c2740212e3a176e4110cac9e361a59a773457064d2dc652dd115d04f1c3756c0e1d39f6737a16b4508663e310934c49c58058b3c7b9af7bb2334c8a163608c42499658986927cda365e2aead3ac29de16e47e954383ea566f8fb245a4e5a934c767bb3bf7e0eb8a477fd0e1f61bcb238462a0d19c5cea9293ca58ade76829413216a7882cd2846323046694f78cd8b0347792ebb75abdc1 +TAG: 973e58b1b8adb176a6f1e5c963bfdc5c + +KEY: 65b63ed53750c88c508c44881ae59e6fff69c66288f3c14cfec503391262cafc +NONCE: 7f5e560a1de434ba +IN: 845ef27b6615fb699d37971db6b597930a7ef1e6f90054791eb04ddfe7252b5f88fd60eba5af469bc09661c0987a496fa540621afeec51bebda786826800943d977039dee76235248112ff8b743f25ed5f3cb0d3307f5e118d84fdbb9c3f5531bc177fb84549c994ea4496c65e5249da987dd755d46dc1788f582410266a10f291c1474f732183a2a39afe603771bb9c423fe3e8906f2be44a0c9a7c3f0ceb09d1d0f92d942383a875c0567c7869f045e56dd1a4d6e90c58d44fe0c5760bb4fd01de55439db52b56831e5a26a47de14249453a4f8e7da3cb3282c6622916197ebfaad85dd65c61e7d2d3ba626276366746f396394c1bf75f51ce +AD: 51a3588398808e1d6a98505c6e5601ae2a2766f1f28f8f69d1ccbcad18038c157b41525be58ae4527a073748b7a04809e52a5df0c7988417607738e63d7ead47db795a346b04e740186e73ccad79f725b58ee22dc6e30d1f0a218eda1791e2229b253d4ab2b963a43e12318c8b0785c20fca3abcf220c08745d9f9602f0ece544a05736d76b12d249699c9e3e99f3f13cf4e5dc13a04125c949a5b30d034b23cb364c8781964bc6c30e5e5ca9673d517ef5f35965d8a8cf1be017e343df97b6bee37b30638b154286d1f36d2f9a0eaa23cc484eac5a05b15d9efc537d989dbc8b3106c0dc1a56e97e6aec2eff54a82cf7ae9df2af46b4c860f83 +CT: 027b14197b4012256b133b78ddc94e72fb4d724fefa4ae329f5a5fa3fa784fe6d7e1e805e3f7a75557de64de506d38237b467fa577efb59e7cfe2356bed6655c5aa4e238dcfeb75c16549a0917268768a96acb5e20546a1fb7e3a7cff887f49f2cd7a135f72a98a779150f3207bf733e88861fd79eadbf77fa3bfe97bfe8b6a991cb3bcc2cde8287f7e89384846561934b0f3e05e0646e0e1907770df67a7594161a4d0763faa6fa844080932159999d528ee0558710058ce16f97d13ac9fd9bf5044191188bbfb598d0fafbdf790b61ce0781ecc04218a30ded45efd498cc9ba03562ed2b4a993ee98876b3ab7a9bc07829f1c4ca6ead98c06b +TAG: e4d18a701b8308697b5e79141ed783c1 + +KEY: 4986fd62d6cb86b2eaf219174bec681bebcdef86c8be291f27d3e5dc69e2feba +NONCE: d08d486620ed2e84 +IN: 3a22ad5de387db4fdd5d62a1b728c23a8dddc50b1e89f54f6198b90499f9da3122ebeb38ebf5fdfe30309734f79aff01e3de1e196b35bffa33bae451f31f74b8aec03763f9e0861a34fe5db0b40c76e57c7fc582bfa19c94ee25b5e168270f379bf9f8a0a18bed05de256f8f0dd7c23ba2ff1c7f721409462f04cc611ad9bd4c3c9acf30742acfb9518a6375cbb15d65a1bc6993ea434894f93d4f6e05996ebc1bd56579296309a2c6b8fde95072168b5fd31927c4c0abaa056bcd16221d5f220be47591f43255013a262dce439817f534830ba82155347e5fe3101f8011b89365a6568214ed0661914e8cb3431d6c8f2347dfc1209a3eca4aaf0a111f47fe +AD: 7dd3f656a03c001b45ca0680bc3ac9d68c6e96b591d3c69eb8c65e489009d845cb331c98b82e627e06d5bf01e74c573df268c2386f12628c019951d42f55991ff20d72a7b2c45f41d0be7af428c92f324aaab8df70d900301cdf09a3d93eb711c919d34a86fff9cb078322ee2e0ad48dbdf3b7884f0f2dc5c36262c59bcfd75ac6200f59c6fcd0ce10ff5005fef5df8f0432377dfbfc1db8f559e27e1aeef3380ea3864867d36a25a18654779a751586cad3b8a46b90864ee697b08605673b8d2123433c020a21c4db243dde2420c12fd4d54a2704a0c8c376454a1b5e80fd6db89aabd56d9b421f29649e474824dfa56cb5c673c504d10be52b53751709fe +CT: c40180afd53001663ff4834110f56e6b0f178cd3c0e7f7de5d0089ee41d8403ffb98e84922706544a344d7e2625b12cf66b9c966f9f57d7b94e3e4b34e6f0aaed1763ce012782e2f5e1682e6c343fc7961fedddd0919d0b910e9923c17e36406979b256b85aec24ee352f03b48c1302eab419c83dccc5372cc059e9de596224fa70098eb32fc9579e97917b923914fa2efc30ab29b457bf14e45583b3771486bdc0876f3ea6e1a646746c4f8c5cb2641a1557c8473e6ea67d4811a67485ae9a678ff3a2408ca845c3b51957e189eef47dfc1d46bde4b9d754d7df13f828ddadb06e4ebddb5f0dafbdb28de4c5e6078926f20cdf9e97ecd58e309e640f74f06 +TAG: fd5e29332832a14a31a9ce2ca8568498 + +KEY: 7d28a60810e43d3dfa32e97c07957ec069fc80cc6a50061830aa29b3aa777dfc +NONCE: 47738ac8f10f2c3a +IN: b50278ae0f0fa2f918bb9a5ed3a0797c328e452974d33cbf26a1e213aa20c03d0d89490869754abf84dbbe231d7bccdced77d53fd4527356d8e02b681fc89a535ae87308bf7fbc26197a5ea85bdb3aa033b8da5cd197ea6d72f96f63b03f4ecc7adedf399a5043776cdb32c08f30b77f34df85f8adb8e02649a04b020b03e17d445ca63e4ed73ae432c481392e031eba2f9d2f7f981d1e50917822bd6ff71c239d33444ada3523a59dfbce5457eadec1ab926c9e6c5299c7521e3f204b96901a712504fcc782e8cea80ba12a7f7e71cec3d0871899b6ca059061da037715f7d13fed01c9cade1e687b4fbb1f4ac4b040db3b43800f112fb900e4f772d61b921cbce4da6f +AD: 324292813b7df15bc070cc5d8a4bf74ead036430be63abc43304cf653959a24a91c7de5a671c50fa8a87e21bb82b069999aadfb6895d8bda4c3083d17b8ca55b9ab1511ed8c4b39d8c28c11a22ef90c08a983e3fe2d988df9e02b16a20b24f39ddb28429625f511db08298c4dc321f6c268fc836a6191df6232f51c463a397a8d8b33374abe94e62c0f5c322387e1fc4a1c1980a04a1a3c2c31b32f183a11c3268c6dca521149dc16af120a78be6627210e8ddbc44472bc24d66ce3681c7579b3d9a425212a704a4f5105cb80f0d18ee860953d10b59c114826779bbc368d7a0eece9f223e47cd8e5fd453607d101d9d9c2bd9a658d6520b87d7b4263f6d845a524a36e4 +CT: 2c217e969c04740a1acfa30117eb5b32dc573df3354f4cc3bf8f696ff905f1e640f3b2c250473b376622e0c9bda13b94640521be1ef0fc660b4c10dbe2bfc093030753e04f6aaecf813b43b61f960455974b8bb8a9b461d1e8fd3802315e863c00448f24dd38deb90e135493274eb14ccbde15c50dcad734ed815a806be6622492a84cd062e3ba567b909a205a1d0d2bedd40169697d261c7b6c2e0b1f069853fd470e8f364a142c386c439a6dbe192ded5a3d0fbf73799f588c59e58c60249d980ddcf0d9693631cd9b3f972509c3a77123d38d9e267ecad06e1208e3f1c0a69fbca7c3bb1a48fda19493d0f8f48398820057b94120f3ef97d87e9e8a1b301a2534c68f +TAG: 1fdd2dcd935f55822bf7231a516ca841 + +KEY: a76e9b916f5a67b78a5949651c8c3a9741a1bc3c41cdf85fd2c8f3e9a0616098 +NONCE: 0808da8292dc14e0 +IN: 9c149eeb09345c3c22462b03e49eb4dba6bc98b269b1086d752bcd8eea53b8977b238a04a994baf915591686baab90b79a3bf7d9adb2c6c2e31acd3e72f0813fb745aa5fb2e3da408f78001c9c09bd26a1a2646011b6120aaa2bbacc4a16c39fb5257b9b2ea2ad8bf70bcc9855cf11841116c2767310cf3cd49d1aa44cd505f079761e064d5bc7cea4a7173b086882a77d3fc179efc86fc4db8a373491d2ed81eabc63c950e832db17d09f474d4ec46bde47830caf26fabaa0372b81fccc449c0e19ccd630caf693a7b43bb1c408a54e03f50c44280a05ad89fb6e8f01d8ac278edf556e5d86ceb4b614fb2ef133819c6e1ff6abb86c54a135256204b5cd400b93624d3932e7c2b046 +AD: 6aeb7031e4a2e23eea93f05fdc562aa2bf43b8998bea7344377aaddc60fbdb7bcb1491d379ed0cb613ee757cfb66490db61bb431d2fad34b38ddd55bc5b22aa6c4773b9992f34b878c5663f6e8cdb5f80a17f4d312bf342492e48d1ce4c6d754076a634fece61500acf8168d47381af4faf980c6cac2bfd5da8c09b6edb0f543bf0fe02643e38d73fa37d8ae87fb66193f22e57faf4393c007d48c8631a685d520578f8f89db684fb371ea02f3a58b1e2168f0216321139472e0d03b6d90ba8aab65402e1c1ac4f9172a60e27e3d997b9b05e2f672120d6c87bcafa6d4c9b4cf8ba8a82932d92840368fc53dc5b48526103dcab5f1531038aabe89171327ac559b98a3cf4ea70bf051 +CT: 9c3faab9261a63cea9477b3269007283995b06ba77ef83d9e693f7e4ee9855550eef94855be39a7a435b6a3584b202973777c7b2482376ba47b49311947a64983b60236756ee4455d4cfada8c36af8eb06b06ba2f6b79ffb1185c89f2b2a831cfaa3855fc1841d8910908be5078352011168a67d36372d851a3217cabf593ea462dcd325cf9a4f67e85418fd5c924e9b92ab026cbee4e7ab1067066cb5949dfc699a68fe539e1abb13cec33904e5207e6963d24f5a0b770613b8b00014e791bfff88f9c25ca126127a2f8d1d1e9794efd28dce98b53e228073faae8d5047530d502184fc341321c3f55fcbf41187fc31262c325b97f519959b6a29b36c71f76f60196bb1457b77c8bb +TAG: b45df119043d29008fcef36a169ef886 + +KEY: 98cd2477a7a072c69f375b88d09ed9d7b9c3df3f87e36ce621726f76e3b41a1d +NONCE: 77d185aaf715aa48 +IN: 42b31eefdacab0f03ef6060156000c8195adb0976cabbe1a42bfcc09f85659c60b98638401f2d2e2facfb9a97a62926bb0cecaf3af0180a01bfb6e576babf7fc43331937a92abd30cddfa3e450f895e9dd914dea3fafd759c136d685310ebce28ac0613ccdbf30115946c9634b67510b77d0e37f07714b2ddac9d7095b8d4bd887c132c4a9127eb01c8dedb4c39c87b98a741316656f9a8d5a5b0c0ac84789aa2347a5f99ca5ad55cd1bcf98f703eb4b00badb8a8555f38b3b368db8ba7ceea94e8b219f51edce75d84166b5602156ed5962a93a51db73c59d87e906179d7a74a2a2a69d8ad99f323225c87e475d3f771b4a203a2e2b03b458401044649fa6536dfab24d7037807dcbf6518e6578 +AD: f5bb1496052a4361dddf72a288e36953a3d815d6876c013f1d6ba839e127f721b052b1f7d8ca20c7dc0386a7d459ebd7eb9fc8cb08941e6ca9ddb980f3115f65bc1928a414d441ae71dcb879d5bfe0cde0562bc37f8fde0d5291ad405c92fcbb860c43b55ac0fe663b54b3d0616aca13a5c82b7b5d34125a05c2acb5530141030e6f2aa0c8322b2c8fa307e7518918e550e9f48921c6168f094d8758e16b9f815fd0458095c4143f0922adb1840d0e685636825a9c90ee90ee537f4b8dceecbc4287c82dc9a00d7e51671e37ea284ee3ca501b1b2596459d3f592f70186f41125739e342c9f6be9241973b1414dfe5fb8cba1af82e679278cfcf95420df0c5364af4d7e72ad57d5c871fcbc35462 +CT: 7a3bf3e3ad5ae3ab71fb1f7121c3d8fb511099484b50af7ca128ee0337ed4b828dc4cde0b88dc1e8089101fa82c9beb3eb48fdcf0f5b16da441f5a3fce9a590022af95a94aed6a3e71e505f60f303c78c356f274ea85a55354078530664ecda32c80e77dc20974b3b38f4825b8fbee8c3970769a2f42c5181608a8d7d76ef4d093961b665ee42b9708fcafe2c82d3a307173e2a25ad2528c3bf83352b9265e45b70722d7cf8c9b80826d21335234ee3db69d0d37871c83222365900c96c17a7e9f5742d0bfe383be24d0d44590d4b0f29f7abe0c65daaffb968b3f2657b1eb300534eacb52ec7a6b6f9f57a50a91b1799f491361cf613c934b7f520dc4eeeb40ffc45e10be0a95e76f366d4eac14 +TAG: f613b65226afb64c614fe60d9c71ed74 + +KEY: 2f0f4631ab1c1bcf8f3ad0559c818d50e0af7d8cd63faa357f2069f30881d9cb +NONCE: 7d0ced2fdb1c9173 +IN: 6516ba1d29357144eebfa486d21decf223da3aa76ec29bbfcbe7f1eeaf4a847710e5080177f7e5a7c8b4752c219b1cc70aef4db861ba67d0fa6222d9f4a1dc756a0ba44e62906f9374a960c16198866d867854d88f528a60e212eb91645787e75685b2e215c0a41990abc344a77236ec0186ba63a664592938cc5a8ac1d3eb99c95ce00e19fbe249263083d85b052d48bfdffc01585dc57bb2a2c6c4a819604c1ec0548c6f0f78dc05e4418b36277dc07233c7532f9c289d6aed0cc6bc7df4fd0a536c497b982e2dad2c30d2db1c6545a845c5dfa83a4ac49ef06fc9c919079d3e299e31b5c3be370814ae5022ae469d3ee55246a41bd0dc4e64351cc38c3c09af0a1aee3b388a6892deff0df3f93cd92d722b +AD: 1ccfa1ececc8de1e200d0ecc19dcf67b7c96bea3a282c2bccba61035db5c14776387b8b8f58e5757deb0129d4e5e315f64df354a5985d2e47ebbbeafe0c914f7cf1d63dd0311ace19e69a8b6ff0ab25cc8df0408d22132205e89e5eb679268d82b2913e64e3f885bbf4a6d379b760b94590e3140dd7275ab4713cb56d0b716e2718f11316640cb394802862d39e77a46d0c065af3caf7dec14e887039d8aa8c3d3a8ac1ee06026f49d00b2f59d971b54735e95a51f199389a93a4fc24ebaba1f7a2eef7412f61febf79084fbf481afc6fb6b204084e5ef5df71f30506459dea074f11fc055cd2a8c0fc922c4811a849984352a56a15659b7d07a4cc90b88623638ea00c4c8bc13884df2237b359f2877aa41d6 +CT: e580093789ba17ffb46672dc326f09278aca08598d3e5458eaa53e6ed45d5c71a396e35b5ea3fe7b7c0496a734d24f1c75420694be2ff095d5172fd3407794e4b99fd7c374fbe8d1564a048614d3f355bfb5866de1a53e1a51f9f5e8312253cfd82f36efaa1898c850ca0d975ad1e8b0d9597a5a9e6516fe2a3c92efb7495557a8afc3da15b0d3e2ba58f612519836946cf2d15b898320d16a026c8c00a1be2e35f0ebe68f28d91c6c45d24c3f3c157cb132fa659b7794df883d90741fa2d2afcc4f27858e13ecd41b154a35d24947ae7361170060c107d8ecacb393ea67104b60457278a392fdf1794bab97d3b02b71a4eb015eaa38a4b4c944c2bc7cd5e329da4a1ab2937a6af81a6caa5fce752331fdefd4 +TAG: 0fd7419c54bc84265ed310a3411a3f2e + +KEY: a48b9b6df475e566aba7671fbd76772cb0eff0b12499967978ce3e25fac92feb +NONCE: 2ccbf0d6c40cb302 +IN: 09da1cacd001dce4f7573a065a4406fe0da04ab367a2d87780a2762e168957a88d3fa78f0a4b6978d449026e5a801d32884b6e14fdaaaf864214f928ebc03dead081fee96683ebb032362d5088c4c2a3b1e242f055f2604919f4dd551db777a258cf9da6d95a2bde249247812b9efc7985cf08707620808524d6dd3079b0b63bf0f71ea5de834ccb8b7c6a97125fd6ca49148e866d3134bbf1d8a6b714e9a80fe549c8bfefe342f41be2ba2300e0028f78cefab65274632dfdbe70bf7d655ec4036df561f2d4fc4d56a482bbe2f9f2ae279b3aa216b39afee75e53602de319484db89a51e844f38c361634e474f8f1f01c340f3f3594860d671346449c6d08ee38de22d246309bc7e4a252a29c86aa6d94b5b4fa58904c70 +AD: 1c2503d5aa1aad193f0da12874074ea0432bb76a61cd43a3017061514da0759846a0f3ae3a49fdb0b6d29f713de665beacb6568f2694112ca380d13f3c1698316866a7a7f87f1d7503a92176ab84fc08977b46ba664508a858e7525753c45511b3d2f407d5e993c6ede77f13d12975707e5195704970a89f71fc30828049f92f944f3aa93d6a5297e678e08952919beb7eac5919df1919cab3c3da6aa696a1eeab6371f310f7e81143e7d240b0213ae554524b52000306160dd4877bf13ba0f13bbe867da7c7d707f31335eef4cd942938ac890a0829ec66bd30ae01a2188a6e5ea0f17cd7dc875e17f03c0ab5dd18e36db8a1fc1f72859ee046b62368f168b3bea2234e0432c07b7d8e1b9277f21e692c513b9e816e6860 +CT: 7d35cfe4be56bd6e0e09dedcd01735b915bc1891a4d1f6a541abc4bcd0ebe89dcb8e365e5813742e8ec65777b6159422fada747da99394252baf8a046fc1b60ad79755f545f4448627b7acaf403000894f5641e78d3f946dfca29ec617f0660dcd6e8d8827e67e1022a245c595d86e60fbd176bf721b171bbe5ecaf4ae671b9f3dd3920146e6ad431bd8fc431820e19454b6ca209723d80fdbee187fca9c937c979206ae97be55f6ba7366a5608770a11d537396485eb0a66586385f4d4cf3905d1fc90831c3e136d5d513fa22be285193142994a3ed477145bacdcbdd791e8b3b88b0d4f1d18b27382550a818c4fd8884bf36f677c6c3ff5677406e510911e696af75e5b3f859bef699bdd16e6215fdb98d874025eada50 +TAG: 2aabff35611b3e0013f6ae0df130799b + +KEY: 923d4b086b9e43b986f7b65e4cea6113a3d8aabefa89323c5e4d5b6f158bb7e0 +NONCE: a0f73297b87f5deb +IN: 21435e8d5c8edf0684f58c2cba4070c10b4801adf46b6c4d322eb3990a38a9ad338ad704b9df6597f3e68d66cd5b56290c8466db2231e56d6bcb9c44e1bd081f42ca2a894dad369df2bd0d2c63d6c881732d6ea22bb22b5bc9a62eaffa1b094d0845f6b966d2cb095e7b3b8bcbc15e707449d35c8df4aea30c3b7243e977fffd59c80f1c5c9af4bb5a54b9c786fbbe8d21b2b906a87a786caed841a34a3e0cc0ac3209d83c58afba19edd63622dd261532d2cfb0b49d527d8eaa0887a087f5129d897f665264b229f860363d71a88b7d49c8dc6360182b357b0662391bb41337f46010ac32b9fada2d60a2efcb99365d3b27b7ac396900d1c821d0df8b86cc9cc1f2673259a33efea610bf8e1d00d7e9db2afea21da8f58c55f799999d +AD: c853a8b39c0dc597d562f123cd221e4104b65423a062a4f4ba890ba344feb84290f61817e23330c365f58c3583ce08360d3c1171982ead5496d525ac878f23a57480a6ee39d4e65afd6268245bb982a2545fa1195427cdbbcd404cdad5198f55cce2a5a028fae435f71b15921d066e8d43766c32b2f2c3f57c0674e129607dcd3703eca529414adaee79d81fed432153cceb6f3fc53404810d8ec878f7d94be5d379d0e0e1aa9bc404b4b5d396038a9d76a5ce53c9f3759b8e50fb331858ca58cee81bfc3ee58baef5d19c402a3dc8b36370ec1ace5a4aa2527fb94b4f933a4ab8ccaaf6a5af5a779eae5667c2a24ab027e781c8d4f30c377aa5885a2fdaf6507d18cd824a847c35368b4ea984d2c3c3824a5b8ba3042e1852504a21a3 +CT: f2e21052eebbb86a4f5e803360855d8632aa727dca6f5e79dd74d7aff106e442001928d113005b030f8446f8eff2ee951db663978abe43090dd5ad2c51ba97a0ecf988c607d95e486d02524f690fa3c28d5c48c1f75c1f555e7b43fe7e46f2ca2b9fdb408ec4ba18b6cdde2af673183cb7b1a3c23ae77eddd4cac75e1ea14743fc571f8d31ce2e96787524cd48aadaa474181c096a032184574ddc25a6e0ac8441c212bc36298708e33c963ae931e6c6241d1affeef7b6ef759495df44b6ab647447693cf703569e69aa72f1def9a342b8978c1edea9703a421ca75b92cac4de14b88c693200022b8a2ed22b1c4678b99f4d695e080dd1196d7168e14f0d0f8ff880d742e97b9f6d00af1f7118e10b77c5ef3ea6c52f84a20fd6ea46dc +TAG: fa8ee13400fb3f63b899df582f2fec45 + +KEY: df73adab2768559ea983cce85453fe81d79be3b3c57f202b31b94d6635cf2e4b +NONCE: e7a87e6bf6b5a354 +IN: 0032a37abf661faa18c587fd2aa88885c061deeba81105dd221969bed5d59c7204b09b1a8c4c8de3b9f748c7fc70626ebeaca060233a57b102221b1bf0f3d9fdaaad3d2b1439c24d08f9c67f49f3c47128f92ee530abf4c4f4573bc60ae4b38109f55bca3ca9e1ba9f9fd6e34ba0d174892977a53356e1f5c88c614fe3ff3b3dd0818e7a2285412e3b37444bbe8a80942efcfd03958809a6966cda9430b2f0c9e552f4bced6e19eb3e85fc5758bd7b588297ccbed37ed94c3adc8c08ea8b058462aac9d57a939ec711bc4ecfec944d2b653b7cfc7b02a65d7057c9fdadd51b9da8cc4a3c68dae9da8b9c5319c1a2baa3d6c891c5ac4a39461484b5a01abc64df447ada24c04a4363e605eaccf339a9aa515e724206206da6d22bbd2f52e64cd7c895 +AD: f833e5ab4f8bc89167f80f576b1d6b22cdd0e30721f5f735799746cf645b6eff531d4c7b03584f3dfcb73cbd35ac42736216dc7f0de098a4f42c61ceb4b227ee288e47d697a0a76afc762f084e8fdbf9351c28340c324771c109a469341ab10ca10483ed2af5e878d7d3dc2bced2f72da3d1a25852b103ee9878e8158eb4309c1ce528f3a178ace153b6d3ae0af0d577cb3cb1540489e80427f792217ad8a09b84f027fca7ceb651b4264e98e94b4cb8a37b133390897233e8ba9103628d05b9609e8552c4a4b11e3f2fa8d56af36957390e88cba44656be3edace798cf8cdf7771bac338a256bc3cba6df97728f222f423ca7c6d149c9372d66163a98f79a234b00d4b75fb2ec860dcc2d1998105e4b9c01d68f079f3e0aa21cc534047fc7b858f8 +CT: b842eadfdf431c135bd6581d3eccae54e2267d8890036aa33dfe2d2d9715c44625441210a3a0d666d708d30588fe851ec36e10d8fa3584ed77b095149494b7c54379d62c8935e1d2b9a8f47e4759ad0b3437fdf2cc2fb6c5ea25ad10e0bdc9dc5b0517fc237eb783cc461c46665e2b1d1a5b8008dbf409ea2a63fea0276de23a32c99d92a498807a0f95e208fc6262321a78aafaf0cc3f833fff37bd4efa66f6023a25cdc6702cee3912799563d908a5183c9956a06aa71085d855dc7c809ed6e2889592b361ab3ab39060f8e419152187a794a19c2a1128882201900ea2cd597860674bf78d9720643df8701676718fd201baed4935a88e50558daf86edd08a9ab227ac7afae55c974b68de8dacad4a4d79b13ed6dfe74017a4cb9148e033436fb6 +TAG: 184095b7a8190abec08bb72d19eeb103 + +KEY: 55a4be2448b464c2ea52a2f2664ed6aba865c14ea1fea77f4689331fd105c8d4 +NONCE: db37c0a405b4626d +IN: d266e66272e5d3462081b004cb42429c8b9741e9f678153754d726f6f9aa513464763c5e793b482fe512fece97585f1426120d4cefb3d0a8cc0a8db4bde93fc72c78f44d4fecca14650c660d3e285b327e7cdd813063e7e867b8a2d059a41bab70432b7f857199894da90dca3fe5272bae1ec694a1a07b60b05df275784d4975637e4673109f3ba846dfd1a048b202ed8e89973be608b91ee4743b1e759900f1443038951fe6189e806638985f3c16338c3c60695df58e621154d79bb973859c4558e9dca90470f77c73f004443ad5db0717abbe43266f90e57397b83ac34d1fef2e897e2483d5bcdcb627abd64b0d1aef525835f25e76d6e9158232cdde6dce970b59f58de8a98e653be32fb58edabbcefa5065d73afdf1c9c4fbf50c1022bd22bfcb98e4b422 +AD: fd6a3fdd879f8880843eac20ae01c1b9dc3487d270a806572088ef2ddc1f1e0de495e71d4813bf5c501ad31e5d791c4b5b3a0a71b63fdddcc8de4b056064ef467989ecccc5d0160d403bf3a025d4892b3b1de3e062bc3581d4410f273338311eb4637529e4a680a6e4a5e26e308630a5b6d49ead6d543f8f2bf9050aa94ce091318721e1d8b96e279f34b9759b65037bec4bf6ccda6929705aeeeebe49e327e4d7a916620c9faf3765120658af34c53fbb97ec07657b3f088fcbdc401aa7949ddeda34d885018c2c23f4f0bb8218bf0d4fc90643658b4d8834f4a8c08e590c2a790995baa9e77627c342d283e454f84fcc05be15e9627a2d9be340c9d72f222bbdfc47905f56616cd9f936d49e4732f319f020513340fb8b22828db251b102b6b137c9533936d6 +CT: bd11ed07b7b4b30eeaf25d6a41a549cca0a5aee71f990ac566a37265d7af2ce3c03703427ee0b2755c2bdfc29f9d826aec6ee4ad28af48079ac23db16580b97424f3a4e35cc23625d39f95699d9ff5143e9a2bc26fcfee4f125f5aa2d968ccfc2faaf9db3c28850f6757f735cbc50c94c498bcde4f23bffafa8dd5f70d1a011e35eb26e905d4e68848fedebeb197be595c085ba33f11ba8398258445051751888e9bba111f800f31b37c447074ca6dce6d54b4dfad6cee5138643d4f6ac045e8047248924e88ea4294c7878bc22c9b41924ce301f22693c33733107bf1ba85e34806c5e4366ea66fc52a5f89dd9bf213239158b3d4d2600dde696c61d76c398b9bf10de9118e812e891c8f3355c0ecc6405f79bc32a58905e37888a1d8395fbedc3ac54eca569f +TAG: f7d3b58a34a86e99267e5db206f17bbe + +KEY: 3304e4917ad7777b86c26a636292c9cc4c10d32003c49e07209eb0ef8505031a +NONCE: 4d572d116fbd8c4d +IN: 2f242c2ba33790ecef862b0e077ff8b15eb9d10cf2ff621ed65902494431dcbd +AD: e699bbf250cdd93d229d0740e433897e2d19132e2b722df8b69bb6a7c2cf3b93 +CT: fb81e30436e437c7f686f86b1b65c73549a9d09db810d320785c3634934150b3 +TAG: 8b + +KEY: ed6057bb163f1609ff28b938122f495e3d5ae4ec3dbd7456c9b5c82e28e952dc +NONCE: e6ff6852f3a3afde +IN: 3c50edc967eb0b3b2355f6400e0a036e796c8b7d72c5e583a86e820d53e76c43 +AD: 2441db55148e14e9e241d68296eb60d529408f0534143089671bce546db96d88 +CT: 6ecabccee31519374d4bed11296e7483d1cb759bea3f4446a96bda8b4ca6d7ac +TAG: 355f + +KEY: 73568183c1f9725af30e0f2067606ce802c3fe3ab5cff8d02b3db8c35176ee0d +NONCE: 0bc9e19321b3d00a +IN: ec2590af5ccd226a32ff750c1b029c11e3dd76c469a5579da9418e4c3fdc0d41 +AD: df30160ae0cbf2cf8992221bd62dffe691dd602afa784ca691479e957af3acf1 +CT: 9e8d8ac30626f8b831448d6976933aa5bb8c6dbc794e1f4b7eeb0e4a59342c07 +TAG: 9fd36a + +KEY: 273bcb3f8c067da4ec3418799ad40e7e4aee74ad7e629499d646df4a7e585025 +NONCE: f60be3eb894b4030 +IN: 697498ba964d5ef401da4d94844fab1efc635e7157d0831a325bb5a4cf1fbd34 +AD: 9129715deab14f02c76ba8172571b1fa9d50365cd795bfccdfc28e7e7b4f66fc +CT: bd4cd5af83be1c13933302675d9fcaf1c4cacdf269f6ff441d1ea2211c54e7ed +TAG: 7ab12a37 + +KEY: ad39610c2e6a6d0961207390e076e972c2edadca885c92965fa648b2ce34fdbf +NONCE: a90db690bba83b78 +IN: 31c49e3cd3d80a82e6b90316dfb94b38b8a23042519bf40c8181fec873c99002 +AD: ddbd7d821d18d44c66295abf245b227b5cf4366811b7b34c07679600abdbfc29 +CT: 94628fc303a0546edd51e966f2bd87968f37800c607d5e5a91f727fc1fec406f +TAG: c22ec4e4c8 + +KEY: 29984954060ba06ece1bcfc0e50195f4632c6df48da1e02ae6c14f7065668971 +NONCE: cce53a25aeeaf747 +IN: b9b87433a9894f3c9ca8212623d62369a565a2edcddd276e07d611eda3597426 +AD: 19fa9aa59697559d8b46d9cd49c3b763c0b73b26b9e334a3eeac2c86fdbaca8d +CT: b68c83397770c36f073710882fa86d43b0e54e8efef0ff75075604d0d7ec4e1b +TAG: 40d4ab752f3d + +KEY: 5c3b838b84100b2a818c0842e9fe19a7c50cf5f3ea73364c816ef588e500ff3f +NONCE: fdf6b0229e4bcc2a +IN: 2ba91904c143be99297b39f52856904af41705c176c8c6554b6bc89bddffbcc1 +AD: 3539d9dd821f004f4ced1637071f4be6abd7fe98f017f0a8ce3f49dc8d496f46 +CT: ff9d6d924e737a1df8c2bd3047e40ab401f903aa0e5b51acb991bac38ac2cc4d +TAG: 1bcaa415a6a3c7 + +KEY: 6d65e627cab6d5eb1a088b25bd6c3a8a004a7a19cccae909d62fed3559c812f7 +NONCE: 7ff00a8798b792de +IN: 6848ee4ac820291a2e1dc3baad97f1ad8b7160dfeaa1bc83b2700ae42b5a366b +AD: d2437b1306bf0ea211449fac863ca0d1074d84caee9009c5d54b9e9bdc8de6b1 +CT: 2da0abe2a71e1c0b1ab309c160a8cebe45c6e16170aa5561806484ba2b5b9a9a +TAG: 566003e1f78d2a90 + +KEY: 63401046a96efbc8c6483a2c396b2a593d3fae0db565525b85999fae13a46b6a +NONCE: 051393d775e635ee +IN: 2b4b6477580382aae782f8b5772c0948a444d8d95caacd85c0856c7e4393fe09 +AD: 3d84d2e70e9c062d1f511eb685a9a90c8d5fa50eadf8455c7148666b3e7155e0 +CT: 880c1123e54fd8ffb3c293720dd174913572e619ef46504cdaa64fc451b0ec1c +TAG: 339274339c88d50ac0 + +KEY: 291fccfce0782f1787d62d4b9293d2ada4c04d37a8288ba9ba9aae0d31aad204 +NONCE: 7450bbd62e4aba7b +IN: adc251e793181e5d4c4bd983b853eb13f2096ccb340996b6eca4cd2157efcec7 +AD: 4c598f6deedc8c1d97da33654763495cca3517430eec4edb006b10c95e031ae6 +CT: 28bda22e4922cd8ff6739cd8a6bdafce036d9c61a145a65ca1b86f6d4d3206a1 +TAG: d98fd43fe7ac74d4b016 + +KEY: fa3a9674d4a0eb36b2f7547c956443d09e6b4e4acfc9deda838eb7ebdb999a8d +NONCE: 0a2572592c3bbbf6 +IN: ae27f70fda9f5a5be0f704a27f0b8a9c04ce83d3c2e0d7ec152da25f473b0c8a +AD: 6ee8705a9a3655d198497ad410da02005872ecbe397824851b80f4050bfdd311 +CT: f356cbd88e4e2aff62d91e3f914032085388955bbba995fde013758b8702e38f +TAG: 00324c76fecd3f50e1e3b8 + +KEY: 471ec87b992b104d369748d96856b5f66149cb45ca05c17f29d24eb9526fe6db +NONCE: 23a2df9ed0b47439 +IN: 2b9452bca0f48e5519ec3d0736597608df6ad9ce799eba913cff71573d79c092 +AD: a56722ddfaee5f1b64398c225ee8bcdcfde5c2127101c363bfac52bc409c1082 +CT: 7bbc464aac5dd29c25262fe0b116c176d827c2cc8dd63428393b0a9110f3c194 +TAG: 2e87f4a6663a62e47c7e197f + +KEY: a29d1cfd4ccdc18803fbca9500f4bb29ce99cfcbf8acc41b8208dae4b7ee5d64 +NONCE: 634f99e88e237ef0 +IN: 09ee5982c5743f396d0c29c13e3fbb8fb89f61705da05466291e010effd51a5c +AD: 564dddfcc3227b413244f1105b610f192decf15c4cfa067f4d7fcd6bd7af11b8 +CT: 32916b67a6f32733623344c98c49773f3e721dc2ded105fb245799525bc9c84c +TAG: ff463c07e7ef831321d3fd775f + +KEY: 08ba23616d911188f91da063278bef1237dcbf17f52585e53c2c4b6cf3ac9f0d +NONCE: 989ae593eddd3874 +IN: 749152c9478944c8271c0c11e07bc1c569eec01493e65b3b94842a1bf5d721f8 +AD: a12d1a45b7c9b91ab08751a70b753714052ad24e0b2619fe8c3be303c65f2dbc +CT: 34c40538ee1d22ddf8ac290dd7d423dfc622b5cf8f3412a5343e277822aea713 +TAG: 014c7c678e0949e88071d1fe3531 + +KEY: c2ba8bed8634156afc6bfe3754c91744d4131de39d059f3a866399f916553b5c +NONCE: 80fbf7b433a4cd9c +IN: 419be6623e7964f9f26068dd969e4a139617e67c5ffb269b3013c433fe771c77 +AD: 3937592db78a61ff469691b6800792019bc2b3d42512f23c1b1a66a8274495cb +CT: 9d5bd1c7e766763eb00684c038043111d8c6390a8d6e17a15ef97c02ab16f09c +TAG: a64d0eeb4a01481ec0cee8c1c357e3 diff --git a/external/boringssl/crypto/cipher/test/chacha20_poly1305_tests.txt b/external/boringssl/crypto/cipher/test/chacha20_poly1305_tests.txt new file mode 100644 index 0000000000..103c196244 --- /dev/null +++ b/external/boringssl/crypto/cipher/test/chacha20_poly1305_tests.txt @@ -0,0 +1,578 @@ +# Test vector from RFC 7539 Section 2.8.1. + +KEY: 808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f +NONCE: 070000004041424344454647 +IN: "Ladies and Gentlemen of the class of '99: If I could offer you only one tip for the future, sunscreen would be it." +AD: 50515253c0c1c2c3c4c5c6c7 +CT: d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d63dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b3692ddbd7f2d778b8c9803aee328091b58fab324e4fad675945585808b4831d7bc3ff4def08e4b7a9de576d26586cec64b6116 +TAG: 1ae10b594f09e26a7e902ecbd0600691 + +# Test padding AD with 15 zeros in the tag calculation. +KEY: 808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f +NONCE: 070000004041424344454647 +IN: "123456789abcdef0" +AD: "1" +CT: ae49da6934cb77822c83ed9852e46c9e +TAG: dac9c841c168379dcf8f2bb8e22d6da2 + +# Test padding IN with 15 zeros in the tag calculation. +KEY: 808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f +NONCE: 070000004041424344454647 +IN: "1" +AD: "123456789abcdef0" +CT: ae +TAG: 3ed2f824f901a8994052f852127c196a + +# Test padding AD with 1 zero in the tag calculation. +KEY: 808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f +NONCE: 070000004041424344454647 +IN: "123456789abcdef0" +AD: "123456789abcdef" +CT: ae49da6934cb77822c83ed9852e46c9e +TAG: 2e9c9b1689adb5ec444002eb920efb66 + +# Test padding IN with 1 zero in the tag calculation. +KEY: 808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f +NONCE: 070000004041424344454647 +IN: "123456789abcdef" +AD: "123456789abcdef0" +CT: ae49da6934cb77822c83ed9852e46c +TAG: 05b2937f8bbc64fed21f0fb74cd7147c + +# Test maximal nonce value. +KEY: 808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f +NONCE: ffffffffffffffffffffffff +IN: "123456789abcdef0" +AD: "123456789abcdef0" +CT: e275aeb341e1fc9a70c4fd4496fc7cdb +TAG: 41acd0560ea6843d3e5d4e5babf6e946 + +# Test vectors from chacha20_poly1305_old_tests.txt, modified for the RFC 7539 +# AEAD construction. + +KEY: 9a97f65b9b4c721b960a672145fca8d4e32e67f9111ea979ce9c4826806aeee6 +NONCE: 000000003de9c0da2bd7f91e +IN: "" +AD: "" +CT: "" +TAG: 5a6e21f4ba6dbee57380e79e79c30def + +KEY: bcb2639bf989c6251b29bf38d39a9bdce7c55f4b2ac12a39c8a37b5d0a5cc2b5 +NONCE: 000000001e8b4c510f5ca083 +IN: 8c8419bc27 +AD: 34ab88c265 +CT: 1a7c2f33f5 +TAG: 2a63876a887f4f080c9df418813fc1fd + +KEY: 4290bcb154173531f314af57f3be3b5006da371ece272afa1b5dbdd1100a1007 +NONCE: 00000000cd7cf67be39c794a +IN: 86d09974840bded2a5ca +AD: 87e229d4500845a079c0 +CT: e3e446f7ede9a19b62a4 +TAG: 356d9eda66d08016b853d87c08b5c1b3 + +KEY: 422a5355b56dcf2b436aa8152858106a88d9ba23cdfe087b5e74e817a52388b3 +NONCE: 000000001d12d6d91848f2ea +IN: 537a645387f22d6f6dbbea568d3feb +AD: bef267c99aec8af56bc238612bfea6 +CT: 281a366705c5a24b94e56146681e44 +TAG: 59143dab187449060a3ec2a1681613cc + +KEY: ec7b864a078c3d05d970b6ea3ba6d33d6bb73dfa64c622a4727a96ede876f685 +NONCE: 000000002bca0e59e39508d3 +IN: b76733895c871edd728a45ed1a21f15a9597d49d +AD: cc1243ea54272db602fb0853c8e7027c56338b6c +CT: 1fb9b2958fce47a5cada9d895fbb0c00d3569858 +TAG: 219b4252deb16a43b292165aabc5d5ce + +KEY: 2c4c0fdb611df2d4d5e7898c6af0022795364adb8749155e2c68776a090e7d5c +NONCE: 0000000013ce7382734c4a71 +IN: 0dc6ff21a346e1337dd0db81d8f7d9f6fd1864418b98aadcdb +AD: 0115edcb176ab8bfa947d1f7c3a86a845d310bf6706c59a8f9 +CT: dad65e4244a1a17ce59d88b00af4f7434bd7830ffdd4c5558f +TAG: 7ae32f186cf9ec59b41b764b34307d4f + +KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865 +NONCE: 000000005d9856060c54ab06 +IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e +AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51 +CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36 +TAG: d3f7b9c295f374651a84138648a5919a + +KEY: a8b9766f404dea8cf7d7dfaf5822f53df9ccd092e332a57f007b301b507d5e14 +NONCE: 00000000c7f2f7a233104a2d +IN: 4d6faeaee39179a7c892faae3719656cc614c7e6ecd8fcb570a3b82c4dace969090338 +AD: c6d83b6a56408a356e68d0494d4eff150530b09551d008373d6dee2b8d6b5619d67fdb +CT: a15443f083316eef627a371f4c9ac654d0dd75255d8a303125e9f51af4233ff4ceb7fe +TAG: 63c2b4e0973096299488b0a66ffa54c1 + +KEY: 5e8d0e5f1467f7a750c55144d0c670f7d91075f386795b230c9bf1c04ba250bc +NONCE: 0000000088049f44ba61b88f +IN: 51a1eebcc348e0582196a0bce16ed1f8ac2e91c3e8a690e04a9f4b5cf63313d7ad08d1efbff85c89 +AD: 5d09bf0be90026f9fc51f73418d6d864b6d197ea030b3de072bd2c2f5cab5860a342abbd29dba9dc +CT: 35aa4bd4537aa611fd7578fc227df50ebcb00c692a1cf6f02e50ed9270bd93af3bc68f4c75b96638 +TAG: 4461139c4055333106cf7f7556fd4171 + +KEY: 21a9f07ec891d488805e9b92bb1b2286f3f0410c323b07fee1dc6f7379e22e48 +NONCE: 00000000066215be6567377a +IN: c1b0affaf2b8d7ef51cca9aacf7969f92f928c2e3cc7db2e15f47ee1f65023910d09f209d007b7436ee898133d +AD: dfdfdf4d3a68b47ad0d48828dc17b2585da9c81c3a8d71d826b5fa8020fee002397e91fc9658e9d61d728b93eb +CT: 8ff4ceb600e7d45696d02467f8e30df0d33864a040a41ffb9e4c2da09b92e88b6f6b850e9f7258d827b9aaf346 +TAG: b2ad07b86aca1b3ab34033c12d6a08cc + +KEY: 54c93db9aa0e00d10b45041c7a7e41ee9f90ab78ae4c1bba18d673c3b370abde +NONCE: 000000003f2d44e7b352360f +IN: 1241e7d6fbe5eef5d8af9c2fb8b516e0f1dd49aa4ebe5491205194fe5aea3704efaf30d392f44cc99e0925b84460d4873344 +AD: f1d1b08dd6fe96c46578c1d1ad38881840b10cb5eae41e5f05fe5287223fa72242aea48cb374a80be937b541f9381efa66bb +CT: 027b86865b80b4c4da823a7d3dbcf5845bf57d58ee334eb357e82369cc628979e2947830d9d4817efd3d0bc4779f0b388943 +TAG: 6de01091d749f189c4e25aa315b31495 + +KEY: 808e0e73e9bcd274d4c6f65df2fe957822a602f039d4752616ba29a28926ef4a +NONCE: 000000001b9cd73d2fc3cb8e +IN: 3436c7b5be2394af7e88320c82326a6db37887ff9de41961c7d654dd22dd1f7d40444d48f5c663b86ff41f3e15b5c8ca1337f97635858f +AD: d57cfbe5f2538044282e53b2f0bb4e86ea2233041fb36adb8338ded092148f8c2e894ef8766a7ec2dd02c6ac5dbab0c3703c5e9119e37c +CT: 9b950b3caf7d25eaf5fca6fa3fe12ed077d80dcd5579851233c766bb8bb613ec91d925a939bb52fb88d5eda803cfe2a8cda2e055b962fd +TAG: 0887ec7d5e1a4e532746ec247a30825a + +KEY: 4adfe1a26c5636536cd7cb72aa5bded0b1aa64487ad0e4078f311e8782768e97 +NONCE: 00000000d69e54badec11560 +IN: 19b3f9411ce875fcb684cbdc07938c4c1347e164f9640d37b22f975b4b9a373c4302ae0e7dfdeba1e0d00ced446e338f4c5bc01b4becef5115825276 +AD: bda1b0f6c2f4eb8121dcbd2eebd91a03ae1d6e0523b9b6f34b6f16ceca0d086654fb0552bfd5c8e1887730e1449ea02d7f647ae835bc2dab4bbc65b9 +CT: ea765a829d961e08bacaed801237ef4067df38ad3737b7c6de4db587a102a86fc4abbaabea0ee97c95ca7f571c7bab6f38cbae60cd6e6a4ce3c7a320 +TAG: a27f18846f5a4f7fcc724656c91cf4f3 + +KEY: eb3db86c14b7cc2e494345d0dfb4841bbd3aa1e2bc640cca0c6c405520685639 +NONCE: 0000000088b54b28d6da8c81 +IN: f75c0a357271430b1ecff07a307b6c29325c6e66935046704a19845e629f87a9e3b8aa6c1df55dd426a487d533bb333e46f0d3418464ac1bef059231f8e87e6284 +AD: 34b08bb0df821c573dcb56f5b8b4a9920465067f3b5bf3e3254ea1da1a7fc9847fd38bdfe6b30927945263a91fa288c7cf1bee0fddb0fadf5948c5d83eb4623575 +CT: 146ec84f5dc1c9fe9de3307a9182dbaa75965bf85f5e64563e68d039a5b659aa8863b89228edb93ff3d8c3323ab0d03300476aa4aca206d4626a6b269b2078912d +TAG: 854cbb42bade86a09597482c8604681a + +KEY: dd5b49b5953e04d926d664da3b65ebcffbbf06abbe93a3819dfc1abbecbaab13 +NONCE: 00000000c5c8009459b9e31a +IN: f21f6706a4dc33a361362c214defd56d353bcb29811e5819ab3c5c2c13950c7aa0000b9d1fe69bb46454514dcce88a4a5eda097c281b81e51d6a4dba47c80326ba6cea8e2bab +AD: fe6f4cbb00794adea59e9de8b03c7fdf482e46f6c47a35f96997669c735ed5e729a49416b42468777e6a8d7aa173c18b8177418ded600124a98cbb65489f9c24a04f1e7127ce +CT: 911ead61b2aa81d00c5eff53aeea3ab713709ed571765890d558fb59d3993b45f598a39e5eff4be844c4d4bd1ef9622e60412b21140007d54dcf31b2c0e3e98cf33a00fd27f0 +TAG: 2865d2a26f413cc92416340f9491e1be + +KEY: 3b319e40148a67dc0bb19271d9272b327bc5eee087173d3d134ad56c8c7dc020 +NONCE: 00000000ce5cf6fef84d0010 +IN: 27b5627b17a2de31ad00fc2ecb347da0a399bb75cc6eadd4d6ee02de8fbd6a2168d4763ba9368ba982e97a2db8126df0343cdad06d2bc7d7e12eec731d130f8b8745c1954bfd1d717b4ea2 +AD: a026b6638f2939ec9cc28d935fb7113157f3b5b7e26c12f8f25b36412b0cd560b7f11b62788a76bd171342e2ae858bcecb8266ff8482bbaed593afe818b9829e05e8e2b281ae7799580142 +CT: 368fb69892447b75778f1c5236e1e9d5d89255c3d68d565a5bba4f524d6ad27de13087f301e2ef4c08f5e2c6128b1d3e26de845c4ac4869e4c8bd8858ad0d26dec3b5d61a9e3666a3911ba +TAG: 1414f1b91966340417c38226ccca9d3d + +KEY: 43bf97407a82d0f684bb85342380d66b85fcc81c3e22f1c0d972cd5bfdf407f4 +NONCE: 000000008b6ba494c540fba4 +IN: 4b4c7e292a357f56fdf567c32fc0f33608110d7ce5c69112987d7b5a0bd46d8627a721b0aed070b54ea9726084188c518cba829f3920365afc9382c6a5eb0dd332b84612366735be2479b63c9efc7ff5 +AD: 1e0acf4070e8d6758b60d81b6d289a4ecdc30e3de4f9090c13691d5b93d5bbcef984f90956de53c5cf44be6c70440661fa58e65dec2734ff51d6d03f57bddda1f47807247e3194e2f7ddd5f3cafd250f +CT: d0076c88ad4bc12d77eb8ae8d9b5bf3a2c5888a8d4c15297b38ece5d64f673191dc81547240a0cbe066c9c563f5c3424809971b5a07dcc70b107305561ce85aecb0b0ea0e8b4ff4d1e4f84836955a945 +TAG: c5ca34599c6a8b357c6723ee12b24da8 + +KEY: 12fc0bc94104ed8150bde1e56856ce3c57cd1cf633954d22552140e1f4e7c65d +NONCE: 00000000d3875d1b6c808353 +IN: 24592082d6e73eb65c409b26ceae032e57f6877514947fc45eb007b8a6034494dde5563ac586ea081dc12fa6cda32266be858e4748be40bb20f71320711bf84c3f0e2783a63ad6e25a63b44c373a99af845cdf452c +AD: b8be08463e84a909d071f5ff87213391b7da889dc56fd2f1e3cf86a0a03e2c8eaa2f539bf73f90f5298c26f27ef4a673a12784833acb4d0861562142c974ee37b09ae7708a19f14d1ad8c402bd1ecf5ea280fab280 +CT: 9d9ae6328711fb897a88462d20b8aa1b278134cdf7b23e1f1c809fa408b68a7bfc2be61a790008edaa98823381f45ae65f71042689d88acfa5f63332f0fba737c4772c972eba266640056452903d6522cefd3f264e +TAG: e84211b6cfd43543f8b1b4db07a494d1 + +KEY: 7b6300f7dc21c9fddeaa71f439d53b553a7bf3e69ff515b5cb6495d652a0f99c +NONCE: 0000000040b32e3fdc646453 +IN: 572f60d98c8becc8ba80dd6b8d2d0f7b7bbfd7e4abc235f374abd44d9035c7650a79d1dd545fa2f6fb0b5eba271779913e5c5eb450528e4128909a96d11a652bf3f7ae9d0d17adbf612ec9ca32e73ef6e87d7f4e21fe3412ce14 +AD: 9ff377545a35cf1bfb77c734ad900c703aee6c3174fdb3736664863036a3a9d09163c2992f093e2408911b8751f001e493decc41e4eeeed04f698b6daed48452a7e1a74ec3b4f3dcf2151ca249fa568aa084c8428a41f20be5fd +CT: 229da76844426639e2fd3ef253a195e0a93f08452ba37219b6773f103134f3f87b1345f9b4bf8cfc11277c311780a2b6e19a363b6ac2efe6c4cc54a39b144e29c94b9ebbde6fd094c30f59d1b770ebf9fcad2a5c695dc003bf51 +TAG: 55e025a1eb87bc84d4be00c775c92ad2 + +KEY: 4aeb62f024e187606ee7cc9f5865c391c43df1963f459c87ba00e44bb163a866 +NONCE: 000000009559bd08718b75af +IN: c5d586ceece6f41812c969bcf1e727fe6ff8d1ae8c8c52367c612caa7cdf50e0662f5dffc5ea7d3cc39400dfe3dc1897905f6490fd7747b5f5f9842739c67d07ce7c339a5b3997a7fb4cd0d8e4817ff8916b251c11ef919167f858e41504b9 +AD: 51f5b503b73a5de8b96534c2a3f2d859ece0bd063ea6dfa486a7eec99f6c020983f7148cccb86202cf9685cc1cc266930f04e536ad8bc26094252baa4606d883bd2aeed6b430152202e9b6cc797ff24fc365315ed67391374c1357c9a845f2 +CT: 252ea42b6e5740306816974a4fe67b66e793ebe0914778ef485d55288eb6c9c45fa34ac853dc7a39252520514c3cb34c72b973b14b32bc257687d398f36f64cc2a668faffa7305ab240171343b5f9f49b6c2197e4fbe187b10540d7cdcfa37 +TAG: ab1d8a5a1f3eda9b5609c0028737477f + +KEY: 9a19e72f005cae1ae78b8e350d7aabe59fc8845999e8c52fad545b942c225eaf +NONCE: 00000000d9dae2ea8d2ffc31 +IN: 2110378d856ded07eb2be8e8f43308e0c75bc8a3fcc7b1773b0725b7de49f6a166c4528e64120bdf7c9776615d3ce6feeb03de964a7b919206a77392f80437faceb6745845cafc166e1c13b68e70ca2a1d00c71737b8fcbbbd50902565c32159e05fcd23 +AD: 1cd73b72c4e103afbefd7c777e0480f3f5e68c60b85bd2e71ef5caebb175d7fc6535d39f38f92c24f2eb0fe97d878ed3d5967c0bb4394a5d41f7d34cda6e1523d3848f049cde554a7d31e1afeab5d3e6150f85858335cbd28c8a7f87d528058df50eea06 +CT: 5f009fbce4ec8e4ca9d8d42258b1a3e4e920b2fbad33d5e9f07557d9595e841025193b521ba440110dd83958e8ee30219d952b418e98a6c624894aa248aedc0678f2d263e7bfaf54ca379fef6c5d2f7ac422ea4b4369408b82d6225a7a2cf9a9f46fd4ef +TAG: 1c6bdff7d8b9554dc7bf40e50b37d352 + +KEY: ba1d0b3329ecc009f1da0fab4c854b00ad944870fdca561838e38bad364da507 +NONCE: 000000008a81c92b37221f2f +IN: 6289944ffa3ccea4bf25cd601b271f64e6deb0eba77d65efb4d69ca93e01996e4727168b6f74f3ccf17bd44715f23ceb8fc030c0e035e77f53263db025021fd2d04b87a1b54b12229c5e860481452a80a125cb0693a2ba1b47e28ee7cbaf9e683c178232c7f6d34f97 +AD: e57883961b8d041d9b9eeaddcfd61fa9f59213f66571fadffffdd1498b9b014f1ef2e7e56c3044d7f9fa7a1403a1169e86430a2a782137093f5456e142aad03a5f7a66d38009dd01b7fc02c9cf61642dedaf7cc8d46066c281ee17780674c3a36eae66c58d2d765075 +CT: 9c44d9135db0dbf81c862c1f69bec55a279794cdd29a58e61909aa29ec4c120c9c5a508d856b9e56138095714a4bb58402a1ad06774cf4ecdf2273839c0007cb88b5444b25c76f6d2424281101d043fc6369ebb3b2ff63cdb0f11a6ea1b8a7dafc80cdaef2813fa661 +TAG: 689a141bc11159d306dad7a4ecf6ad9d + +KEY: 0cf8c73a6cffc1b8b2f5d320da1d859d314374e4a9468db7fd42c8d270b7613a +NONCE: 000000003c4c6f0281841aff +IN: 4434728d234603c916e2faa06b25d83bad3348990ecde2344368d1a7af1309bd04251bb2e0b72044948f8dea33cce2618283b6af742073a9586b26c1089335fe735141e099785a1235810a3a67ff309e2f0ce68220ba0077ad1a5dc1a4aef898a3b9ff8f5ad7fe60149bd0bd6d83 +AD: a38d09a4f1c9241623c639b7688d8d35345ea5824080c9d74e4352919db63c74d318f19e1cbb9b14eebd7c74b0ad0119247651911f3551583e749ea50ff648858dcaaa789b7419d9e93a5bf6c8167188dbac2f36804380db325201982b8b06597efeb7684546b272642941591e92 +CT: bdfbfea261b1f4c134445321db9e6e40476e2dd2f4e4dbe86e31d6a116d25830762e065b07b11a3799aab93a94b4f98c31c0faeb77ec52c02048e9579257e67f5a6bae9bc65210c25b37fc16ee93bda88fd5f30a533e470b6188c6ce5739fa3e90f77120b490fc1027964f277f40 +TAG: 780cc54bb6f1c9b78545c1562cd9d550 + +KEY: 69f4e5788d486a75adf9207df1bd262dd2fe3dd3a0236420390d16e2a3040466 +NONCE: 000000006255bf5c71bb27d1 +IN: c15048ca2941ef9600e767a5045aa98ac615225b805a9fbda3ac6301cd5a66aef611400fa3bc04838ead9924d382bef8251a47f1e487d2f3ca4bccd3476a6ca7f13e94fd639a259ef23cc2f8b8d248a471d30ac9219631c3e6985100dc45e0b59b8fc62046309165ddb6f092da3a4f067c8a44 +AD: 0c83039504c8464b49d63b7f944802f0d39c85e9f3745e250f10119fa2c960490f75ae4dced8503b156d072a69f20400e9494ab2fa58446c255d82ff0be4b7e43046580bc1cf34060c6f076c72ea455c3687381a3b908e152b10c95c7b94155b0b4b303b7764a8a27d1db0a885f1040d5dbcc3 +CT: f0bb2b73d94f2a7cef70fe77e054f206998eacf2b86c05c4fa3f40f2b8cebf034fe17bcbee4dea821f51c18c0aa85b160f8508bd1dc455cc7f49668b1fb25557cdae147bf2399e07fcacaca18eccded741e026ef25365a6b0f44a6b3dd975ee6bb580f5fccd040b73c18b0fbf8f63199ba10fe +TAG: 2ecccea4607d14dbb2d2475792aeb468 + +KEY: ad7b9409147a896648a2a2fe2128f79022a70d96dc482730cd85c70db492b638 +NONCE: 00000000a28a6dedf3f2b01a +IN: 791d293ff0a3b8510b4d494b30f50b38a01638bf130e58c7601904f12cb8900871e8cf3d50abd4d34fda122c76dfee5b7f82cd6e8590647535c915ae08714e427da52f80aef09f40040036034ca52718ea68313c534e7a045cd51745ec52f2e1b59463db07de7ca401c6f6453841d247f370341b2dbc1212 +AD: 9a6defddb9b8d5c24a26dd8096f5b8c3af7a89e1f7d886f560fabbe64f14db838d6eb9d6879f4f0b769fe1f9eebf67fcd47b6f9ceb4840b2dba7587e98dc5cae186ef2a0f8601060e8058d9dda812d91387c583da701d2ba3347f285c5d44385a2b0bf07150cbc95e7fcfa8ae07132849a023c98817c03d2 +CT: c2f109d6d94f77a7289c8a2ab33bc6a98d976554721b0c726cbf4121069473e62ba36e7090e02414f3edc25c5d83ac80b49ad528cda1e3ad815b5a8c8ae9ad0753de725319df236983abd3f69ab4465d9b806c075b1896d40bdba72d73ba84c4a530896eb94ffccf5fb67eb59119e66a1861872218f928cf +TAG: 17ec6cf2b172f01e3c456ad047196805 + +KEY: 48470da98228c9b53f58747673504f74ca1737d7d4bb6dbf7c0cba6ca42f80b9 +NONCE: 0000000056fb4923a97e9320 +IN: bc6626d651e2b237f22ee51608ddcffeba5f31c26df72f443f701f2b085d6f34f806e29673584cb21522179edb62a82427d946acabce065b88b2878e9eb87ed1004e55ef58f51ec46375ac542c5782725ff013136cb506fcf99496e13fcd224b8a74a971cc8ddb8b393ccc6ac910bd1906ea9f2ed8a5d066dc639c20cd +AD: df8ab634d3dca14e2e091b15ecc78f91e229a1a13cba5edd6526d182525ec575aa45bc70fb6193ffcd59bad3c347159099c4f139c323c30a230753d070018786b2e59b758dd4a97d1a88e8f672092bef780b451fd66ba7431cbb5660ea7816cdf26e19a6ebb9aadc3088e6923f29f53f877a6758068f79a6f2a182b4bf +CT: a62e313ecf258cc9087cbb94fcc12643eb722d255c3f98c39f130e10058a375f0809662442c7b18044feb1602d89be40facae8e89ca967015f0b7f8c2e4e4a3855dbb46a066e49abf9cef67e6036400c8ff46b241fc99ba1974ba3ba6ea20dc52ec6753f6fc7697adbccd02b0bbea1df8352629b03b43cc3d632576787 +TAG: d29a8968067aeb457ffc114c3a9efb95 + +KEY: b62fb85c1decd0faf242ce662140ad1b82975e99a3fa01666cac2385ab91da54 +NONCE: 000000002f4a5ca096a4faf8 +IN: 03b14f13c0065e4a4421de62ab1d842bffb80f3da30bf47d115c09857f5bdd5756fd7c9ac3d9af1c9fb94f2640f7f4386cfba74db468e5288dbe4dd78bfe4f69e41480ca6138e8beacc6eaa3374157c713cfa900c07dd836eaecc8827fa3e70e052ae09e8473e2ae1a10b1bb669ef60a8dd957f6553daa8114918e17371f2ac327bd +AD: cfe3b7ab7550b0e8e2e8235fa0dcef95647ce6814abd3dc3f5a3bd7d6d282504660c34ad8341e4d11402c7d46c83a494d7ddb105e1002979023e0e3dc2978c9ae53e10eb8567e7a02b60e51e945c7040d832ca900d132b4205a35034fed939a1b7965183c25654931a9b744401c4649c945710b0d9733b87451348b32ba81de30ea7 +CT: 8965db3d3ae4fb483208f147276e7d81b71a86e7202ffc9b1eaade009bc016838dc09ca4bcf30887b2f4243fbd652cd90ebed1ceef8151ff17ea70518d03b0f2a24960aa7de9b30fa65c2e2d57360061aae6d9376e984e9fcd5e5dd0911a4bc8deca832ffb76f252bd7da523076593ba6b174f7d9fb0377e066ecbb6638036241e86 +TAG: 28a5284696ed82714eaa94c9ebe6e815 + +KEY: de9c657258774d4ebc09d109a0fc79d66493ae578797cac4eb8830a6a4b547e0 +NONCE: 00000000b5e35fe3398efa34 +IN: 4d68fb683aa4f4c7a16ba1114fc0b1b8d8898610fa2763e435ded8771b3651078bef73d4dfd14e76a34cd5eb9ef4db4ead4da9e83f4ce50fe059977b2d17d687c29335a04d87389d211f8215449749969f7652dc1935a0f9a94538dc81dc9a39af63446a6517609076987920547d0098a9c6766cf5e704883ea32feaea1889b1554b5eb0ce5ecc +AD: 436ea5a5fee8293b93e4e8488116c94d3269c19f1d5050def23d280515457b931bbed64a542b317cc5023d648330a4b7adca14dd6f3783207b94f86ccaa0a0ac39b7db00ac87a99e3cd8a764ed9c75da8454479636ab2b29e770b166a5b75cacc425c919bf1ce9ac34afe6b4425c3d9fd2e48bc81e7d15516d60e592bfcc2ebefb660f0995f2b5 +CT: 97a97b8f0f5420845ae8d57567f9bba693d30e6db916fad0b971f553ad7d993f806f27ab8b458d8046062ced4778c004b4f958a4436141637c6039963308dea2f54008b7feab79650295ed41bf9e65e1a2d75ab1c7b2a70ebb9e9f38d07a9a672d3e95ea78afe9ac02f2566b48b0251aef6eeeca8bd15bd8d43b559426aa9d15d960ee35cb3edf +TAG: 4ef49e8a0c2ef85826d7f03e81c577f2 + +KEY: 6885bd333c336c7672db8ebdf24c1a1b605c5a4ae279f0f698162f47e6c73401 +NONCE: 00000000f0c4a213a6168aab +IN: fa905a2bfa5b5bad767239fb070a7bc0b303d1503ecd2b429418cc8feba843e5444ed89022fdb379c3b155a0f9ceab2979000a0f60292a631771f2fde4ef065aa746426609082969530a9c70ad145308c30ba389ea122fd766081511a031ce3a0bd9f9f583c7000b333b79ac004fbde6ec3eb2d905977ff95dcff77858e3c424fe8932a6a12139e6ec8d5e98 +AD: 8ded368f919efb522bb6a9ad009e02ffbc6a16536e34d95cdb34f1153d7cb7b0f3c2b13dd05cedae27cfe68ec3aca8047e0930a29c9d0770c1b83c234dcb0385deae7ae85da73a5f8de3dfb28612a001f4e552c4f67ae0e2ec53853289b7017a58591fd6f70b0e954876bb2f7ec33001e298856a64bb16181017ba924648c09fc63c62eff262c80d614679bd +CT: 0cb3d6c31e0f4029eca5524f951244df042fc637c4162511fea512a52d3f7581af097eb642e79e48666cb1086edbd38c4777c535a20945fabc23e7c9277e2b960aac46865f1026eb6da82759108b9baece5da930ccfc1052b1656b0eadaa120ed0c45ad04b24ae8cdb22ceab76c5f180b46a392ab45b1b99c612546e6b947f4d5c06ad5abee92ff96345ad43 +TAG: fad7d5a5193dfb121c68529ba8c0c35d + +KEY: fbc978abb1240a6937ccc16735b8d6ed5411cdbc1897214165a174e16f4e699b +NONCE: 000000007968379a8ce88117 +IN: 1a8196cd4a1389ec916ef8b7da5078a2afa8e9f1081223fa72f6524ac0a1a8019e44a09563a953615587429295052cc904b89f778ef446ed341430d7d8f747cf2db4308478524639f44457253ae5a4451c7efca8ae0b6c5c051aaa781e9c505489b381a6dcba87b157edc7f820a8fbaf2a52e484dc121f33d9d8b9ac59d4901d6ed8996ed4f62d9d4d82274c449cd74efa +AD: 3913cd01299b8a4e507f067d887d7e9a6ded16dd9f9bb3115c5779aa14239fd33ee9f25756d45262dc3011069356425b5c81a4729594e17c9747119f81463e85625d5603d05e00f568b0c800bb181eb717be8d7a93166a504ce1bc817e15530c5bd2b3df1d4222245ea78a38bc10f66c5cf68d661503131f11af885c8a910b6dce70bc3a7448dfae00595beb707fe054d3 +CT: d152bcb4c24c3711b0fad28548dc4db605bbc89237cdbea7dbf956b8855d1161a0781f27bd56d798141e2ace339955efb98fe05d9b44cd011e645106bf47726183958cb6df34ce5766695f60bc70b6fe0fabb9afa009a8ef043dbf75f861881368fa07726625448fe608d578cdc48277f2dc53eaaf1bdc075269a42f9302a57cad387a82c6969608acacda20e1cac4596c +TAG: 96ae06cd7c72456e5568a42317046158 + +KEY: 77d1a857fbadfe01aba7974eea2dfb3dc7bf41de73686aece403993e5016c714 +NONCE: 00000000fdd913a321c40eb0 +IN: db8915bfe651e2ecb3ce0b27d99a6bfa7a7c507cfcb2987293018636c365a459c6a138b4428be538413db15bda69e697cbb92b154b7f4d2cbb07965225aa6865d7dcd1ba2c17c484b00b1986fed63e889f25a4966dc3ed4273f1577768f665362d7d3e824484f0dded7f82b8be8797ad951719719365e45abbf76324bc7d657799d4d4f4bb1dba67d96ab1c88519a5bee704f7214814 +AD: 3cb2c06c20cb0832bbacebfc205d77393ca1816346ea2681de4d3ab1fadb774ad273e4713290454496f5281ebc65e04cfe84ed37cd0aedc4bbe3decbd8d79d04a4e434876650e0d64309e336bfb10e924066a64acb92260b2dbd96735d03af03909aa6a80a6e89fda81037257aec21fe9be7e91a64e88e0a58fa38ecba4c4c4cffb61958f3c486cbb0b1d0b0014a2d1d3df248eec1ca +CT: acb825e6023b44b03b2efc265603e887954e8612b2ee134bdcb61501cfb9492952bf67be597c3a005b09af74d9e421a576d2c65e98104780feab838d8cb1bd135452ea39dc8907a4c1a6a9161805e4fa3e16989e6a418a7eea2582bf895da967028eab7c95d846a6de4b9980785814cf00484baa2f6de609912fff689bce6e854261ffe866bd8e63274605c7c5ad677bd7897ade543e +TAG: bcf523a9bcf772e157941753c6d7401e + +KEY: b7e9b90dc02b5cd6df5df7283ef293ed4dc07513d9e67331b606f4d42dec7d29 +NONCE: 00000000a6c191f6d1818f8e +IN: 2ada0e3c7ca6db1f780ce8c79472af4e8e951ddc828e0d6e8a67df520638ff5f14a2f95a5e5931749ae2c4e9946ae4d5eb5de42fb5b77d2236e2e2bd817df51be40b1b8a6c21015a7c79fe06dba4a08b34013dfa02747b5f03930268404c455dc54a74d9c6e35485e10026da573cb41cd50b64cfafe4cfcdf3c9684ef877e45d84e22bd5e15fa6c8fd5be921366ff0dc6fe2df45f7252972c9b303 +AD: 0f4269ed5ef0bfff7be39946a4e86e8bf79f84b70cd0b14fecb7be3c071316ce86de3d99d6871e0ba5667d9d7bba7dcaba10cb2a36668b6c3e2fb6c102938b75008bb9c213ebf9b85b5e91a802df0d31d7f11d764b2289f6225212694ab6b7c0e3ff36e84245d9f4f43fc5f98e654dea7ba9bd918658879c5bb4a1642af0d83113e3cf935d3c0d5208318f66f654eb17d8c28a602543e77ad3e815 +CT: 22586fe7338e99cdaad9f85bd724ba4cfe6249b8a71399f9a3707b5c4323b8d96679568dfc8d230aefb453df596e13eb3e8a439249bd64bc93a58f95089a62b94f6562b821c83d91f56c55147381e9de4beb4ae81bd6fe7caef7e7e9a2078f2fba8f3e70d4910da9accc92b8e81a61b0fefbece4bd89443e66e8ddda8e47a66a62f17fd0e7d0a4852ce1a4d43d72a0b5e8914bbec698f060f2b092 +TAG: bd05336ed6426de412aac37661953052 + +KEY: 6b2cb2678d1102f2fbbd028794a79f14585c223d405e1ae904c0361e9b241e99 +NONCE: 000000007b3ae31f8f938251 +IN: b3cb745930e05f3ab8c926c0a343a6eb14809fd21b8390a6fcc58adb5579e5432021765b2d249a0ecf6ba678634c4f53f71495865f031ee97aa159f9ead3a3fcb823ee5238bdf12706a9c6137d236e2e7110ce650c321e41daf0afd62bab2a8fe55d7018de49a14efe6d83a15b2f256d595e998d25309f23633360f5745c50c4e5af8ccc9a8a2cb47064105a023e919c7795d2dc331d3f2afb8c42e5c0bcc26d +AD: 1c32fd3df22b3e440e2a3c7a7624990194cb16a5f74af36f87fd6ca7d410ce9064316a2d091945deef7d9b35ceec8396069307caced2b80afd7d53ec479c35cedf2dfd4c95c3dd8400f71ad34028c6e4f8681d93d0774064ba38f3fb9b0c1dfa1f5f0c7d20676a5911d999fb6a1d41367a8e99d852bf3d3b7b3f4c233249ed1ca135389a674ff48232ded3f6800a97b6d409c40e6cd70d09bf9d2ad25d9b9485 +CT: ef70c7de98ab1d4ad817024a970be463443640eb0cd7ff234bdd00e653074a77a1d5749e698bd526dc709f82df06f4c0e64046b3dc5f3c7044aef53aebb807d32239d0652dd990362c44ec25bf5aeae641e27bf716e0c4a1c9fbd37bbf602bb0d0c35b0638be20dd5d5891d446137e842f92c0ee075c68225e4dbacb63cc6fb32442b4bcda5e62cb500a4df2741a4059034d2ccb71b0b8b0112bf1c4ca6eec74 +TAG: d48657033095db3f873c33445fec8d35 + +KEY: 4dbc80a402c9fceaa755e1105dc49ef6489016776883e06fcf3aed93bf7f6af7 +NONCE: 000000002358ae0ce3fb8e9f +IN: 197c06403eb896d2fa6465e4d64426d24cc7476aa1ae4127cd2bd8a48ce2c99c16b1cbf3064856e84073b6cf12e7406698ef3dd1240c026cbd1ab04ee603e1e6e735c9b7551fd0d355202b4f64b482dd4a7c7d82c4fe2eb494d0d5e17788982d704c1356c41a94655530deda23118cba281d0f717e149fbeb2c59b22d0c0574c1a2e640afad1a6ceb92e1bf1dde71752a1c991e9a5517fe98688a16b073dbf6884cfde61ac +AD: cf6ce7b899fb700a90d2a5466d54d31358ecf0562e02b330a27ba0138006b342b7ed6349d73c4c5c6d29bde75a25089b11dac5b27adea7e7640ca1a7ceb050e3aae84a47e11640a6e485bd54ae9fdb547edc7313d24a0328429fcffd8b18f39880edd616447344ebeec9eadb2dcb1fa7e67179e7f913c194ebd8f5a58aea73b0c5d1133561245b6d9c5cfd8bb0c25b38ffb37db5e2de5cdded6b57355e9d215cb095b8731f +CT: aa87f9a83048b6919c8f2b050315db4e2adae4a9c2ca0109b81961b520e63299dcb028cec0b9d3249a945ee67dd029b40f361245c740f004f8cf0d2214fcfa65e6124a3e74b78aa94345c46fdc158d34823ed249ee550431eaae9218367321cdd6e6a477650469bb3cc137a8f48d9cf27934b16703608b383d2145659922fb83bb2e7ee2ef938a90f2ff846a4a949129b1fb74dde55c5ae013c2f285de84f7dac7d1662f23 +TAG: 298f84c8312029a7b1f38c5ea6021f57 + +KEY: 9e4a62016dae4b3223fed1d01d0787e31d30694f79e8142224fe4c4735248a83 +NONCE: 00000000263a2fc06a2872e7 +IN: 5a46946601f93a0cee5993c69575e599cc24f51aafa2d7c28d816a5b9b4decda2e59c111075fb60a903d701ad2680bb14aeda14af2ae9c07a759d8388b30446f28b85f0a05cd150050bd2e715ff550ebbd24da3ebb1eac15aba23d448659de34be962ab3ab31cb1758db76c468b5bb8ce44b06c4e4db9bd2f0615b1e727f053f6b4ffb6358d248f022bcad6ca973044bed23d3920906a89a9a9c5d8024ec67d7f061f64529a955ce16b3 +AD: 4cd65f68f9f88c0516231f2a425c8f8a287de47d409d5ecde3ad151e906b3839fb01bb91a456f20ea9d394d4b06604ab1f9009ef29019af7968d965d1643161ab33a5354cda2fdc9f1d21ec9cb71c325c65964a14f9b26eb16560beb9792075a1597394000fd5f331bd8b7d20d88e5f89cf8d0b33e4e78e4904bb59c9c8d5d31ac86b893e4a0667af1be85fdb77f7ec3e2594a68048d20c2fb9422f5879078772ee26a1c560cbcbb2113 +CT: e944bb2ab06d138ad633c16ce82706ecf0ef5d119be1f3460c9ce101d9c4e04ef1677707fca40d1f8ca181e07273707b06624d6d7063c3b7b0bb0151b757b3e5237fb8004c161233d8bc7e5f28ea1c18da1874b3d54c5ad6ff0835eed35c8853704585cf83996e5e7cec68180af414e04f08134d3b0384ebdf0393c9310b55d8698fe10cb362defc0995e9a13b48b42cff61ffd9fe4c3c8c6dab355713b88f6e98a02e7231a0c6644ec4 +TAG: 6234e81e089b779d0d509d14e566b5d7 + +KEY: 18ca3ea3e8baeed1b341189297d33cef7f4e0a2fab40ec3b6bb67385d0969cfe +NONCE: 00000000b6aef34c75818e7c +IN: ef6d1bb4094782f602fcf41561cba4970679661c63befe35ff2ca7ad1a280bf6b1e7f153fa848edfeffe25153f540b71253e8baba9aeb719a02752cda60ea5938aab339eead5aabf81b19b0fc5c1ed556be6ad8970ea43c303d3046205b12c419dea71c4245cfedd0a31b0f4150b5a9fe80052790188529ab32f5e61d8ccde5973ed30bdf290cbfbd5f073c0c6a020eac0332fced17a9a08cef6f9217bd6bef68c1505d6eed40953e15508d87f08fc +AD: f40f03beaa023db6311bad9b4d5d0d66a58d978e0bcbbf78acebde1f4eb9a284095628955a0b15afc454152f962ec3ea2b9a3b089b99658e68ede4dee5acd56672025eb7323bcbc6ba5d91c94310f18c918e3914bbbf869e1b8721476f9def31b9d32c471a54132481aa89f6c735ab193369496d8dbeb49b130d85fbff3f9cb7dccea4c1da7a2846eef5e6929d9009a9149e39c6c8ec150c9ab49a09c18c4749a0a9fcba77057cdea6efd4d142256c +CT: c531633c0c98230dcf059c1081d1d69c96bab71c3143ae60f9fc2b9cd18762314496ab6e90bf6796252cb9f667a1f08da47fc2b0eecda813228cae00d4c0d71f5e01b6ce762fa636efffe55d0e89fdc89ba42521cc019ab9d408fcd79c14914e8bbf0ea44d8a1d35743ad628327e432fdcfeb0b6679ddca8c92b998473732abd55dba54eefff83c78488eee5f92b145a74b6866531476fc46279d4fde24d049c1ce2b42358ff3ab2ba3a8866e547af +TAG: e3b4192f6e50528c4f4f70267f094c56 + +KEY: 95fdd2d3d4296069055b6b79e5d1387628254a7be647baafdf99dd8af354d817 +NONCE: 00000000cd7ed9e70f608613 +IN: 0248284acffa4b2c46636bdf8cc70028dd151a6d8e7a5a5bc2d39acc1020e736885031b252bfe9f96490921f41d1e174bf1ac03707bc2ae5088a1208a7c664583835e8bb93c787b96dea9fc4b884930c57799e7b7a6649c61340376d042b9f5faee8956c70a63cf1cff4fc2c7cb8535c10214e73cec6b79669d824f23ff8c8a2ca1c05974dd6189cfee484d0906df487b6bd85671ce2b23825052e44b84803e2839a96391abc25945cb867b527cdd9b373fbfb83 +AD: 24a45a3a0076a5bcfd5afe1c54f7b77496117d29f4c0909f1e6940b81dde3abacb71ec71f0f4db8a7e540bd4c2c60faee21dd3ce72963855be1b0ce54fb20ad82dbc45be20cd6c171e2bebb79e65e7d01567ad0eeb869883e4e814c93688607a12b3b732c1703b09566c308d29ce676a5c762a85700639b70d82aaef408cf98821a372c6a0614a73ba9918a7951ea8b2bb77cd9896d26988086d8586d72edc92af2042ff5e5f1429a22f61065e03cfcd7edc2a93 +CT: 40c6318d9e383e107cdd3e1c8951562193c3ef64ee442432a63e2edefc78f32ab07772aeac172cb67ecf4d21f8b448423527bbeb9d8ddd0b46bdb27f74096ceb24e41963b4cdca176676a75bdbe3abc270b349ac0c6cbd9c3a5cd5bce20202fc5cc0c1bdd4fd25e121e0a24bd7bbeb9b19b1912467bf5338ee2ce88aa383c082b42cc399c9654ca325f35523e81438beb3f8926be79c378822d7c8f785614408a5f7cac49e4543188725643e6c1a70b46d0ec400 +TAG: 874875c9a0ba3060a0680291c3dc85a2 + +KEY: 6ae1102f84ed4dc114bb9d63f4dc78d7dbb1ab63f1659dd95f47940a7b7a811f +NONCE: 00000000c965d578ba91d227 +IN: b82a8a9209618f1f5be9c2c32aba3dc45b4947007b14c851cd694456b303ad59a465662803006705673d6c3e29f1d3510dfc0405463c03414e0e07e359f1f1816c68b2434a19d3eee0464873e23c43f3ab60a3f606a0e5be81e3ab4aa27fb7707a57b949f00d6cd3a11ae4827d4889dd455a0b6d39e99012fd40db23fb50e79e11f8a6451669beb2fbd913effd49ad1b43926311f6e13a6e7a09cf4bebb1c0bf63ce59cd5a08e4b8d8dbf9d002e8a3d9e80c7995bb0b485280 +AD: dfd4ac3e80b2904623ff79ea8ee87862268939decf5306c07a175b6b9da0eb13ac209b4d164755929e03240a0fe26599f136fb2afdffd12bb20354aa1d20e5799839abb68ae46d50c8974e13e361d87ef550fe6d82e8b5b172cf5cd08482efdef793ede3530d24667faf3a1e96348867c2942641f4c036981b83f50236b8e8a10b83ebf6909aad0076302f1083f72de4cf4a1a3183fe6ec6bfe2e73e2af8e1e8c9d85079083fd179ccc2ee9ff002f213dbd7333053a46c5e43 +CT: a9aeb8f0a2b3ca141ac71a808dcc0c9798ac117c5d2bd09b3cfe622693a9f8ca62e841b58bddb2042f888e3099b53638b88dfc930b7a6ee4272d77e4b1d7e442bab6afbde96ab0b432f0092d9ca50eef42f63c60c09e7b8de019b32ebe4030c37b8183cc1e3b913b0ce4ee4d744398fa03f9af1c070bed8cdafd65b3a84140cb4deadc70184de757332ce3780af84353f540755227e886a8d7ad980f3dd6fd68263d82e93f883381dec888bc9f4f48349aa2b4c342cb9f48c6 +TAG: f6dcad5412b95994f5e4d6829c2eba98 + +KEY: 405bb7b94715b875df068655f00513cb1ae23ffaac977ce273e57d3f83b43663 +NONCE: 000000005c6da1259451119a +IN: f9f143c0c52c94b4ba7b0608b144156a49e7b5d27c97315743d171911e3645ab7957c80924e3c6b9c22ab7a1cac4b7e9c0de84e49fd5e4a2d1ab51d764fc5670318688ec942f7ab34c331dce8f90fea6972e07f0dadec29d8eb3b7b6521ddd678a6527a962f4d8af78c077e27f7a0b2ef7eabd19e92b7f8c1e8fb166d4763ce9c40c888cf49aa9cdfc3e997c8fe1cce3fe802441bbd698de269ff316f31c196e62d12c6bb5cd93fb3c79ca6369f8c1ac9102daf818975ea7f513bb38576a +AD: 6fe6446505677bf08b385e2f6d83ef70e1547712208d9cebc010cba8c16ea4ece058d73c72273eed650afdc9f954f35aa1bdf90f1118b1173368acbc8d38d93ebf85bd30d6dc6d1b90913790c3efa55f34d31531f70c958759b2ba6f956c6fcdd289b58cb4c26e9515bf550f0fd71ab8527f062c9505cbb16e8e037d34de1756bef02a133dbf4a9c00ac03befc3fb7f137af04e12595ce9560f98b612480fcdba3b8be01db56ebec40f9deae532c3b0370b5c23a2a6b02a4de69efa8900c +CT: 1a4b073881922c6366680cc9c2a127b26f264148651b29abb0c388cf6c9b1865dba5a991e1f8309efbdb91bce44b278772c58fd41273526c33fec84beb53d1689b9da8483f71be6db73a73417069bb4cd3f195236e8d0a00d124eed3a6b6f89415b19a27fbe35774f6a1a6ee4bd4350b252b975f0db2d2eea82f4836350850d6290901e726e8af13644e2d98bc1d569c20800521e6affe976bd407049a2e6d9dd23f88d52e651391ecd2fc45b864310824aaadfa203762a77c1d64562dae +TAG: 90fcc2544880250f1c3abe8a3761ba08 + +KEY: 8c602bd94c630cd00c7a9c508067a5a9f133d12f06d9f6fe2a7b68dce4786d8a +NONCE: 00000000760de0f7b7cb67e2 +IN: c3ff559cf1d6ba6c0cc793ca09a0ba573a28359386a6ec93e1bacd8e630209e0b477a20aedec3c9cbf513ee6a1e3887112218d6155b9875f7e6c4bbba2c31972e905d19f529f4f0f9502996199f94f8728ba8d6424bb15f87fcacd88bb42c63fcc513759712bd0172b1e87c9da122f1993ffb7efd3a5c34b240dd3db89dddea36dbeb2836d9f8648f8e7cd428c0f948097af753b35f9876059e7702027bb00dc69071206e785f48fcbf81b39cc0343974ac70784a2e60c0df93b40379bea4ad8cac625 +AD: 9e14907c3a8e96c2636db1f3d78eb1f673d6ef043cbbb349467f1fe29bf60f23d5d5d1c3b133a8ad72065d822347541c13d1574baf737eb3cc3382fb479e6d5193b9c8e7d2444c66971ef099dc7f37f6cd97b9f7959d46e2cf25e8a5b3111b4d9e2ef906d905f0ee2d17587f7082d7c8e9a51509bde03d3d64338e1838d71700f1b4fcb100b5e0402969da462f26f974b4f9e766121f8fd54be99fc10beb9a606e13fbb1f960062815d19e67f80093360324013095719273c65542b0e31b1a2a3d928f +CT: 2794e6e133f6892f23837fff60cf7c28ee9942f8982ef8089db117903d0143293fdf12ea1cc014bcd8806fb83c19570eed7af522db0de489bbc87133a13434518bcfb9cda4d9f6d832a69209657a447abf8afd816ae15f313c7ea95ec4bc694efc2386cdd8d915dc475e8fadf3421fbb0319a3c0b3b6dfa80ca3bb22c7aab07fe14a3fea5f0aee17ab1302338eeac010a04e505e20096a95f3347dc2b4510f62d6a4c1fae6b36939503a6ac22780a62d72f2fc3849d4ef21267fffdef23196d88fbb9b +TAG: 7fa630c9bcb455e89f13d7a99d5e8dbe + +KEY: bd68ff5eb296c71cfe6bc903c14907f7726bcb1331f0c75f7801cd1b7948f3a1 +NONCE: 0000000065a748004b352ba6 +IN: 52bf78c00f6e5dca2fc60e2e9a52e827df97808e9cf727773860cafc89f4b64178a19b30b46ed813fe00c8f09b25a6a1b6e350d5b005122934a59bfbd5e6e0c635c84a5226c3f2f7dcf951560f18ac220453d583015fdb2e446c69c6e6fdecf2e595e04fab1b0c506e3c6bd5e4414a35f15021e97f447aa334f54a8f1ef942dec6273511b5668b696fca97188ff15ed84b2f46145cce031c1a7f00bd88bb83d90797edc46161b3fda7a2299173496d73b812139556e8b4eb318078b9eb2ae5046e83b79dd3d45950 +AD: 5557b08a5010cbc9f46bb140c2505f68684eb24889324bff44b27234fd7a95a99cfb4ff90a8f9982085b725f78ac42eca6ce7f3314e457dc41f404008681a9d29ba765660de2e05bb679d65b81f5e797d8417b94eb9aabbd0576b5c57f86eae25f6050a7918e4c8021a85b47f7a83b4c8446898441c5cc4e0229776ef3e809cb085d71f3c75ec03378730cb066150f07e60f96aec983c0e7e72bf6bf87ae42228dfda195f97855fcdf4e6d1c4479d978abcfa276d16ed60ecbfbfc664041335ce65a40a2ca3424df +CT: a5c8cf42287d4760fca755e2111817b981c47e85b0047de270ec301ca5f7b3679f4749210892b6ea6568f3a6a4344734a0efc0120ffedecf212d55cbcbb67815ac964875af45f735b70092a8f8435f52fc01b981ae971d486026fb69a9c3927acfe1f2eab0340ae95f8dbee41b2548e400805ece191db5fd1f0804053f1dbfaf7f8d6fded3874cb92d99a2729d3faaa60522060cf0b8101b463b3eb35b380fcddb6406c027d73fe701a5090c8dd531c203ce979e26b9ced3431e2b726a7244a20d9377bd62951bf5 +TAG: 82c6194de4d27aac4c54b023b9831634 + +KEY: 934fd043c32d16a88fad01c3506469b077cb79d258b5664fa55ad8521afdcaa2 +NONCE: 00000000c7091f6afbbeb360 +IN: 2bdd1fc4f011ef97ea52ec643819941c7e0fb39023c2f3c7683804a0ddee14a5d1784a5246966d533b3538edc7d8742d27061c3cab88df0318ab242102de3a54d03632eeb871b72c7e8f8065b49f4a91e95e15f3f46b29fd76b8fcea0d23570c5530e3bbb8a6aafa9ae32c1b3eac653c5ed5fdb2da5a986075808f6385870c85b1913e26042a9d8e78f5bc2ea6de5a64f8aeafa22adcffc7f6932d543c29bb3a04614783f948680e433a71573568d2ce984d249fb4fc06a9f358c76aa3e64a357f4eae924c1356bd5baccf7e0f +AD: f737dd85638eb324dd3891219c5eef7c2dd053cfd055d447a411eba304a4b27dce981d112c4540590933c153d603022c91ebd2b4a58069d27e6ca17a462ef822ca41bffa80b43a68b1b564644cb3c5a7f0fddf7a13a30ff24437fddd8ef93c6f6f205d054f81890d982bd4d4ece0b1563677e843fe48c1f54e9a57ed4da66061482712e710a401073be5080d5b8b96525bffa67de5af31d50385fbbf1a87c21bf0e0a1fdff69ec32c7b7103e0b8ee6c844245e0fc84b9f89fcce62966cea68e2871d3b82e8df424c76309fc88d +CT: dd13fbf22c8d18354d774bcd18f7eb814e9b528e9e424abc4e3f2463195e8018576565d16ab48845d11c9277f2865ebb4dc412fd5b27078f8325eadf971e6944c66542e34d9dda971e2aba70dbd3e94a1e638d521477a027776b52acf90520ca229ebc760b73128879475d1cbe1f70fc598b549cd92d8a9ac6833e500c138c56474db84cb3d70b7aa4f293a4c2b4d818b0ff9fd85918dc590a12a8c0e375c4d98b7fc87596547eb960676aad5559834588f00f251a9d53f95c47af4df3c4299175d5211779c148cfc988a5e9d9 +TAG: aeb0a4eb29886f0a7a12ec0516bd4af5 + +KEY: f9f6eb9ad736a8f66e7459fef5ec2890188dc26baf34a95f6f0384e79f5c6559 +NONCE: 000000007858dfc084fe4b0f +IN: a644ca6e7cc076e87eb2929fd257693fce0f6fb64fd632f7f07c648ebd03696c8e262e6a810d7b7c4e5eef8c65b5323c99dbba50a70b4a9e5c2a9e7315973cd67f35d8052ce9a85a206416dd3031929f4f929b13d0a5fb10cb73c65f6c0ace019da146b51c5274a099f44e3669d26add6f2ff081e886f3cf952fe0dbbe6b0534c23e307574bd35fbd657f5fcbd5dc19fb382a1dc0a2dc8285a0350f71554e4c601497749e35567dd4a273cddc9a48ce53a5f1d297fd8baf8d1b9feb35d9151114345abada4d90db947bb9a743c175f5653d1 +AD: 2048d1c2ddfb5ec385b201832c7a993f229ba72ec16d6ebf723ef0c5032b9966209a9e8a63151b40412e96b82f86728ea6588c7e8e11ac71cc8eabab8c4b54de866658d9c5011def61fb3dbe4e630158a45ea41a2ed55ebd1efb1abeda7637de6fa5fd2f151c6d2f385bf6cd002ca8b4a2896e0d65944ee913e3c784669dd201b1985ef3577f7f123a5f9bcffa176c8f557c4f729133cac518642f27d9b22ca9b97faaafe5b669a10b79ace4a7d5727df146c77ce681357d69f9c2d65b4401bd73cd113387e3b3a05d897adad7a24c485e7b +CT: 4146faffd7313f5d9f625370d20413cc62ab65f4acfa3c7ee1125b937dd7a39f638fc46c8ed004fb525698de5d8620ec153435571817c3de257b0d0e648ebb92940c86a98262d54e764f28cbdd4f7d9bea970291f2110414f62064d7229c6332236c507b3dac742e651d85a2a22fb243c0cc7cc2d016e5bea38f33f9a9ce048944a5fe8b078d71d23168e12dfe5a0f0b829771edc7073fb96032b7be471337a37aca0cf7c0cdd543eed686cd34934717fd79a3f18492eef72f9f450b880aa7e2e1b65e3b04c22e72301338b43aa32ceec2e6 +TAG: 61c6d4d6918b04fc1b72a7a0e9a3b799 + +KEY: 29b19636cdd32507fd98ec4ee26caab1a917646fb8f05b0dc01728a9f4a127f0 +NONCE: 0000000006699d245916686d +IN: 5fdf913aceab1d6dbaf7d9a29352fa8a3eb22718043a79cffa2fe8c35c820aec7c07644b8785dcf7a433b4189abb257fb12b06fae0662641011a069873c3e3c5ccc78e7358184a62c2005c44b8a92254958eb5ff460d73cd80284d6daba22c3faba046c5426fe8b7cacec64b235a8f8d3e2641e5bc378830594bcfb27c177aea745951ee5780a63705727ef42c4ad3abf556d88e3830f3db6b09e93edd09485cbf907f79de61f8dc5cb5fb7665ffa0ef53cb48702f6a81d8ad421cef20c1dbdf402b8fafed56a5361b2f93f914a2380fdd0557faf1f4de +AD: 39116c49cc13adb065b92cb7635f73d5f6bf6b5ccbf72a3f65a5df6bd4a661105015358d9e69f42e98aed795e8161282bc113058b7ef3b9e23fcd8eeab34a392e03f4d6329c112cb968385ec52a7afc98bb8695785af6b27b700973cc952630b7247ce226b4fbb99b8a486370bf6345d4516c52c64e33f407c4f2d1ba90545c88732d98bbd97972ac5e94c694624a9b3782b0099824651cb7567914d25b3e13181a791dbcd40e76e836b3350d310a52151bf835d3c357c9871482c2928e8404c6e533406d4d6fa8f63366f2c4ed828141f1ff00f01a536 +CT: 01e237220b619054a1f3670928fe67d40484b5af40fbd04d032500aac5acaa3b4584dd99a58c390627636a50de5d744f76a56a33205f9e3b00e16162eb47ff3333e1e208ca200f1a5338a86e17bd92dd2d16af8bb022a7dc05b923d019e05247f1a0d0b4bfcfce58dd6d83830705707676d55739abee89fcd5cb94b8fde006a5da02df64b00a467f45970b5ca440f22319b9735a55d454b9fba0588fef0c59d3d83823eba6e0601a96e10233826c5adeea6b2a51d386a07a9e047ad405b23d4c3d89f30c31e3199f0c8f927bfac43ceea1f969de0a8c0f +TAG: b9fec6da464c7b85b2a4726694562fe9 + +KEY: bae06b9b5456707551c7b0e207aae02a19b4848ad8ca4ce40705bf8c856a6e52 +NONCE: 000000009c27065c3ef2d522 +IN: 50cdd88137ff428a88e87b5845be4924f6387537bb5c0b654c80107ab5698db75b2e131848e7aec156d31aed0766d31c379fece4095d38264c6d5945974d25f729c3b0ba11ea853e9cebdb6f03bb670fce08adff74d0a8f02d633fb34e0fb7337a8e66e1c12084d914fb6173b8105684db822752c6751a372bb16690284d661b8b8bc6a6dfbddf45ebc2219596f9f2f878c118df69030de38b4d99dde43b9b9e20a3dab691645dd518342f49b06a0fe0a397adf261e99f07af5b0b3798b1022ba0939c42a54d3b93641cffa3c2e174bce9ab7ad7e7c7924308d1a77a +AD: 5d5590db1bd316eb7a0e30e4c7a6dfdbef9d3287fdb8d824389599c3c2ee262b2192eb5b9708e66e22dbc7eca83fa1a995da3ce64c86fe5aa08b826d476dc439497e2d12e2702c63c8d27aa7f09fedee816dc8bffe1351d53271a34d4292b613b7efcedb7e3cf3e6ad389eef12471e9e20e38e7ae22a323abbadfe8f2e84271bffb1819feb4f77b82843cb8757cfae293631bc6d39669107e7015c85d7343ffa6fc1bbe6f5ab4de30cd752a281e03061ea89de2a3f5e90e20da22fd6e8525c100738667f42212b2cf45fcb23bbb54b21c117484b22c6e514685314df +CT: 66b7f69ac49fab4e5975aeb6fa9287d8eac02ac312c4de78f77f59da16cbcf87274e66801c4b862c33ea79cdc76528862bb2956c06db8b8acfac4794ebf39e35ac03cc73a4351a4ff762f681a48d6f25cad36e2814c9b5c40b9ae92509e58429106847789454d376836936bebc7a80e6c66e7aa52936d6b361378a41f849ad4e48f9ee2d3e92217a908fa8eb35736ac8ada7d32ae05391f2d807be3512543c36138a5fe660dd4cd4cd184bb43b6ba6bc0bae634e2fa9669304cd510ed5103f630068ff76d3375738de60a381842b421477e25a490cdd6894b2704125 +TAG: 94118ccc68de1921d480aab43d1ef0d1 + +KEY: 2cb374cb048c168f2e43597f028d9e73cade1b458284ffc260d4fc6b9011c414 +NONCE: 000000009fb909169bc9f4e9 +IN: 39eb929482784b463546f5d84f80510f2019923d465b99d194246d68c7ae343f91971d8f7059cebb86aa5dd099289aa648248b8c5ca04e66ac5e9bf06776e3883495397618a0227f035666806e636836b47d3d2d255a49db79866cf00d9ddabda259c4f968a1e01e651c7811cebbee2ee71803ea1d9d23487eb221f2d9555756800aba5e6abbefd6fb72b3151cc99ced599cd86df2a9b1ce94f89f347eeb124d9e7f0d9cc48d3dedd819e6d3dbac57ecee199547b266116a2035c9acc4c8ca3271ac74952372897c4a5f2cb84e2d81817fec9d6774f6d8a5b2021684132db4fca3 +AD: 0c7bd4f3a30ee944ccf9489181e6911684dcffad4593a9b65a67dfc80718c69b35897d01281016b7731e12c15cad8482e79458e08a755622e3f3f22a23ef6c8487a36ad1771ba06c641f06f85de0db3776cc6df06ad8fe3b4d60d58508de943083f17cbb9dc0d390ac94d8429e8c6fcfe063f424fbde0f62f6a7f91a626d195dc498a6e69bd93109c4e9ba13e7330aba456d710a4b0cc279d4045660406e26d61dff70d4a33c4f1052869f9248024e7a0f85f1effb32f6f7ccb1f860f3ef04e8f7b29096e6bcf9d4b3e0ce703e9bf228fdf515c2ff9cbabd16987be0f9babd3d8a +CT: 91ddadb86b7ebef798ddaa59da51d71316fcf6c9678143178227d778750dc9827fc6cc21e605c505023e6db25849df7fb6fc1ca4d223aa215f8c85b724643c83bf8218815a9f9e2952384e0ca6a80a3760b39daf91a3c6154c4728c2371fd181fa3764753d0b0c23808a82cd8f0497246e3a0f17f8906a07c725d2891ce968a9d432c2b102d85c05510b28e715bb60d0403a77490e7f18be81218bc4f39287b9bb09f50227dd2f55e4fb70c4438da8ba3c8ffbced87d90155913faa9979fc57e6cbeddfaba3d3ab4163c0eebc7d94279c27d3ed56338893dba542eaefba30f8c3b +TAG: 8980e8e4fe796428b733f4f8e1954a45 + +KEY: f0f16b6f12b3840bbd1c4a6a0811eef237f1521b45de9986daec9f28fca6485c +NONCE: 000000007ac93e754e290323 +IN: 0530556424d823f90a7f1c524c4baa706aad2807e289e9479301e3e7a71f2a5e14e6232ea785f339c669af2e6d25f1d5a261096a548d23864945c3a589b67b09b0304a784d61b42b2419139485242e0d51fcbe9e8fed996d214de8717e6a71f8987ccad65eb92e66707034a5ae38e6486e26eb4374c565aad5df949dab209f7f7bcd8eb6fc52761a26cfe5d01fd349e59f4042e6dbe6b232f9301b971dee121d8aa1e62d40f043a42f3aa859d867eb809b1ced5ae1ec62cacf94a69fafd0631a8b5dfd66d855900fb295eec90ae5fcbf77beae267a79d24081bb322d8c4e0630fed252541b36 +AD: 13bfcc17b810099cda31ca53a1323db9b07633ceb2088a42263a4cbd6a4d47978776005c9a20203319c3a3ae434e9a26fb541047dc9df38dc36c095267272e203d0b24d119a70a7e96041b6d82b7c4d5570e1e4a1cf2f6e44ae63fe005a1f5b900778c482f7bd89e2e02305e35b8f61b7bb2c78a13aebfce0145d1c5aa0bf1d10d23616d5a3a446de550302f56f81dc56fe4f3700f14242688d9b92d8a427979b403c8de8c493a2cde510eaf6b285e6675b173aa0314a386b635c7577d5aff0d868a0cb3f73c8d2005f8c7c9dab5a060ef80102c9d4a4af988838afe87aff04c0689e8c3c7f9 +CT: 2c14c3931e98e84507c4c165c2ed47ad4a178f0e216cd7ac2453bbbf9f85dd06bd8ef54a9ff1fd3dd8e0cafb635d8f2de861a0db5b14d03f17aaea8c89b3010797c71c13a0e666899d7ff6e53c4f08be8ddb3e37688b5afa088079b6c7519b833e16560073e699530302028a3496e05edddec01a23a4c7983956250e8d9e616f7b940856955cde81c1efabf6b7b92f153d03f4cd17e7f7d2907670cfc84d45c1d7936775a3fce47968504278ffaecacea0871b227f250e2979516f6fa310fec0d8df1af7872e5a534e82870aa05f43ef0a455846b93ce938064fa33e92de262e4156dae56775 +TAG: 16c972829819b8fb030b2c5f40dab717 + +KEY: 3792943c0396f1840496917ce8ad89608385007e796febeea3805f3f4cbeccf7 +NONCE: 0000000023b2f9068b2c4c85 +IN: be6b67eb943ee7b5c785cd882f653e73a8f75b4a41a2a7c56ae5a10f729caf39948fe48ad0e51240e2e7aa43193c7ec6ce7f4909fc94c9f99e38e6a0ad7e98eb29c5c2e61c99e9cbe890f154185cec213a74725d23c1a4e4d0cb9b1a36b78c87e5eee20d2aa29aae80d4759eb0c51c5dc3a95bdbbf7e14eb434419a6c88a954ac03d0c98739f4211b8732acd71c297f578b8cb64ccac45f7235ddc7f2a3f5f997525c1ed39dc550126cdf9cedaf55425489085e91b170be6205a5a395f2dd4084a3e8dbc4fd8b13252f7effae067b571cb94a1e54aba45b1b9841308db0cc75b03cfce4ddafe89ce20f2d1 +AD: 7eb6d7b7bbaaa3c202a4f0f1de2263767169eb4a64853240d48c0f8d5d31b08d5baf42977614a57aad99426cde76d242cb37d2956d8c77dc4fd62a3abf30e8ac6cd58c8ef35e67497022960138c57787818892460f3bfc16e37ff388b1edc6ce2bc53c22717edc7a03d4c78b0dbbe9121c7fd8a3e3993b87a4fe389bff13bdae3b349de0b6db561602c53f746022aeb4483c723b67825042f4af20b7dd1e6031cf54215266295c524ac8e1370424c5c5e607fb3e23e97c8eebe64656775edf616422a8b974e1acf13ab45c9a367a7dd9b2d62f48bbc05819b65eccb813ca813f57b22ee4c280dbb5a9d8d5 +CT: 0b316ab2bcf5359900fa4082d5d253b49ad94b70e3fab544f98bd111cbcef6766cf953deec08cae1f489fe12f7acc0032db8a6b0c0eee0c206ea5fb973feaebf90f690e840094db5e13fdd7157ba127368c995b426529435a1bcdd1f14ce9125b8a0e4c96b6ec09e3c36a180adf81941c002d19c19d53c2009be803b987504606b7d43bdee5e0b32ff23c466b6cccfcd0d4e88fd1332e73712b5ab725c1a383e584f34f80daff29d285ae5e43cf1d0cc7a828e75c25daced3a581a93d7a50f313b33f38dddfaa23cd5b9914797db820ee2400d52bf5fa982277fe9b5881ac42981633b3957b0e935051828 +TAG: c549aa944d6d97e52e0793ed572682c0 + +KEY: fe4be6054773f634356ac328591fbc6f833b0d1beeb38dd5b6feb7481b4489d4 +NONCE: 000000000b3f16f898a5a7d5 +IN: 76ced1ade6d1ef4069afddb32e7432d4ff2fd06685121f7b16464e7a72d365744f547d2ccf53486310e38b42d8bacaf711e54c5458d2d68c4dbcc8de31ab6732f4430e88a64565f5b287640775aaa2af1cc461d3e415bb275c6246b1b58517aa72667eae291a2982eda175d1b22c5a58e6fec2b3743d55712f201ca24ba5c0ae8c25724871b2ec2fb914a8da5a52670ab9b43a83b8568ce74db5c634061cb80530c8070c38b8f48c33ba136cb9f2158ee7eda8b65f2192fc94d1291f182f101795b7190c74b319d2d3e02a97c824d9c9471a83797e4936310b207e3a1e0bcf75f7c3e3ee48a747641cdc4377f2d55082 +AD: 834cd775cbefe4b33a3ca53a00c06a3c4a666983e4115a029f15729460daa45d1505e95172d3695625a186b28b8be173a925af04665f209267b3c5123e8be13da447ee1ae856bb0925f35aaa76e04a7bca8460f76c2024de2149f38a8cfba81694b854885d72568105571b6b213a0bc188a44cc7fe13153cbf261401b238cf12a95e23cb56f240114f16e2f1e3a514615aab4449c0c49e4d900b0e17d1a8dabb53d43dca32fa052d576b73dd9b40856b515d6d7efc2a5c17e0ebcb17bd59dc86f22ce909301a2652f134e82ef0e4519487ed12d51536024f2ae8f75d937c42d003076e5dea8de0c684cda1f34253d8fc +CT: f8defb6fe95dfec499b909996a1f75a198a90e4d6c6464d00a357a555311c42fe92dbbc4b79c935e4f0b1a95e44fdbc1380bebabca28db4dd0d2870daaafc38ef27908c3509e945714801cc51f1a07b2430c74fa64f2a7c2f7fd1551d258c9c3be020873fc1bf19f33ab6c660911dcf2317195d0efee82d20ec26d22611f9cf86c51a64e28b3a1f344500018e0855c88dae3c07acaeaa10b60388484dce93e16e6e1a6e69e899806648a92568c8780e9f4baacd98cbb353ac2f908e775d92303cfab843f15be0e0c322a958802fb1a60fcc7631f151f4c2b8cb965d2d296acef250275a2fecc0cea803ce7c058b12dd2 +TAG: baf9a51180f172e5c0cc2c946ce55055 + +KEY: a288b11ce5382ec724ce4ab2d7efa8e777e91ebd04367935e15f9dac483e9596 +NONCE: 00000000874144dbf648b325 +IN: 4c9195280a79a509919af4947e9e07231695fd7c5088539f23936ce88770ce07d9ad3ae4a463b3a57d0634d3a77ceaadf347a334682b04be8e58b8e86fb94a1f93255132b8cdb0df86f5bea354eea4e8315fea83e3fdf6e58aa9f26e93caa08e5e2551a94bd916a51fed29ec16f66800cda6a0aa24ec308bf5fb885afba272685de27c1edcdd3668048ef07b06e90d464a8aa28664903cac45e154e8e1e39c257e1ff506b9d95cef4f300bb73b899e7828602c3c1d290b8cf55ee5fd72ecce9e6efc9293aebf674a70e2a7673e75629c12950622dff71d3ec0992e57776c788c6927d30b4e24b749191c3ce8017f0ada6276e43720 +AD: 04abe8588c8c8c39a182092e5e7840442bd1c1149da102c4ee412bd8b82baa5087ef7291b5cd077c177c42770b0023e0e462b06e7553f191bcb0315a34918dcdbffe2b99c3e011b4220cc1775debcc0db55fa60df9b52234f3d3fa9606508badc26f30b47cdb4f1c0f4708d417b6853e66c2f1f67f6200daf760ceb64ffc43db27f057ad3ee973e31d7e5d5deb050315c1c687980c0c148ee1a492d47acfcd6132334176c11258c89b19ba02e6acc55d852f87b6a2169ed34a6147caa60906ac8c0813c0f05522af7b7f0faddb4bc297405e28ecf5a0f6aac6258422d29cfe250d61402840f3c27d0ce39b3e2d5f1e520541d2965e +CT: 0afce770a12f15d67ac104ba0640aab95922390607473cbda71321156a5559906be933fb0980da56f27e89796eaa1054f5aacf1668d9f273cc69071b9e8e22af6a205a6a88f7ad918e22f616bddbb07c78913c7e056e769e6fcf91c7600c2740212e3a176e4110cac9e361a59a773457064d2dc652dd115d04f1c3756c0e1d39f6737a16b4508663e310934c49c58058b3c7b9af7bb2334c8a163608c42499658986927cda365e2aead3ac29de16e47e954383ea566f8fb245a4e5a934c767bb3bf7e0eb8a477fd0e1f61bcb238462a0d19c5cea9293ca58ade76829413216a7882cd2846323046694f78cd8b0347792ebb75abdc1 +TAG: eb9b2ee43e9a3ae1e33561800169d868 + +KEY: 65b63ed53750c88c508c44881ae59e6fff69c66288f3c14cfec503391262cafc +NONCE: 000000007f5e560a1de434ba +IN: 845ef27b6615fb699d37971db6b597930a7ef1e6f90054791eb04ddfe7252b5f88fd60eba5af469bc09661c0987a496fa540621afeec51bebda786826800943d977039dee76235248112ff8b743f25ed5f3cb0d3307f5e118d84fdbb9c3f5531bc177fb84549c994ea4496c65e5249da987dd755d46dc1788f582410266a10f291c1474f732183a2a39afe603771bb9c423fe3e8906f2be44a0c9a7c3f0ceb09d1d0f92d942383a875c0567c7869f045e56dd1a4d6e90c58d44fe0c5760bb4fd01de55439db52b56831e5a26a47de14249453a4f8e7da3cb3282c6622916197ebfaad85dd65c61e7d2d3ba626276366746f396394c1bf75f51ce +AD: 51a3588398808e1d6a98505c6e5601ae2a2766f1f28f8f69d1ccbcad18038c157b41525be58ae4527a073748b7a04809e52a5df0c7988417607738e63d7ead47db795a346b04e740186e73ccad79f725b58ee22dc6e30d1f0a218eda1791e2229b253d4ab2b963a43e12318c8b0785c20fca3abcf220c08745d9f9602f0ece544a05736d76b12d249699c9e3e99f3f13cf4e5dc13a04125c949a5b30d034b23cb364c8781964bc6c30e5e5ca9673d517ef5f35965d8a8cf1be017e343df97b6bee37b30638b154286d1f36d2f9a0eaa23cc484eac5a05b15d9efc537d989dbc8b3106c0dc1a56e97e6aec2eff54a82cf7ae9df2af46b4c860f83 +CT: 027b14197b4012256b133b78ddc94e72fb4d724fefa4ae329f5a5fa3fa784fe6d7e1e805e3f7a75557de64de506d38237b467fa577efb59e7cfe2356bed6655c5aa4e238dcfeb75c16549a0917268768a96acb5e20546a1fb7e3a7cff887f49f2cd7a135f72a98a779150f3207bf733e88861fd79eadbf77fa3bfe97bfe8b6a991cb3bcc2cde8287f7e89384846561934b0f3e05e0646e0e1907770df67a7594161a4d0763faa6fa844080932159999d528ee0558710058ce16f97d13ac9fd9bf5044191188bbfb598d0fafbdf790b61ce0781ecc04218a30ded45efd498cc9ba03562ed2b4a993ee98876b3ab7a9bc07829f1c4ca6ead98c06b +TAG: e0bf9b6837428843f5a233ee5ddb8a1e + +KEY: 4986fd62d6cb86b2eaf219174bec681bebcdef86c8be291f27d3e5dc69e2feba +NONCE: 00000000d08d486620ed2e84 +IN: 3a22ad5de387db4fdd5d62a1b728c23a8dddc50b1e89f54f6198b90499f9da3122ebeb38ebf5fdfe30309734f79aff01e3de1e196b35bffa33bae451f31f74b8aec03763f9e0861a34fe5db0b40c76e57c7fc582bfa19c94ee25b5e168270f379bf9f8a0a18bed05de256f8f0dd7c23ba2ff1c7f721409462f04cc611ad9bd4c3c9acf30742acfb9518a6375cbb15d65a1bc6993ea434894f93d4f6e05996ebc1bd56579296309a2c6b8fde95072168b5fd31927c4c0abaa056bcd16221d5f220be47591f43255013a262dce439817f534830ba82155347e5fe3101f8011b89365a6568214ed0661914e8cb3431d6c8f2347dfc1209a3eca4aaf0a111f47fe +AD: 7dd3f656a03c001b45ca0680bc3ac9d68c6e96b591d3c69eb8c65e489009d845cb331c98b82e627e06d5bf01e74c573df268c2386f12628c019951d42f55991ff20d72a7b2c45f41d0be7af428c92f324aaab8df70d900301cdf09a3d93eb711c919d34a86fff9cb078322ee2e0ad48dbdf3b7884f0f2dc5c36262c59bcfd75ac6200f59c6fcd0ce10ff5005fef5df8f0432377dfbfc1db8f559e27e1aeef3380ea3864867d36a25a18654779a751586cad3b8a46b90864ee697b08605673b8d2123433c020a21c4db243dde2420c12fd4d54a2704a0c8c376454a1b5e80fd6db89aabd56d9b421f29649e474824dfa56cb5c673c504d10be52b53751709fe +CT: c40180afd53001663ff4834110f56e6b0f178cd3c0e7f7de5d0089ee41d8403ffb98e84922706544a344d7e2625b12cf66b9c966f9f57d7b94e3e4b34e6f0aaed1763ce012782e2f5e1682e6c343fc7961fedddd0919d0b910e9923c17e36406979b256b85aec24ee352f03b48c1302eab419c83dccc5372cc059e9de596224fa70098eb32fc9579e97917b923914fa2efc30ab29b457bf14e45583b3771486bdc0876f3ea6e1a646746c4f8c5cb2641a1557c8473e6ea67d4811a67485ae9a678ff3a2408ca845c3b51957e189eef47dfc1d46bde4b9d754d7df13f828ddadb06e4ebddb5f0dafbdb28de4c5e6078926f20cdf9e97ecd58e309e640f74f06 +TAG: 2e8eb9ff4467c0f61c2abf6ca10893ef + +KEY: 7d28a60810e43d3dfa32e97c07957ec069fc80cc6a50061830aa29b3aa777dfc +NONCE: 0000000047738ac8f10f2c3a +IN: b50278ae0f0fa2f918bb9a5ed3a0797c328e452974d33cbf26a1e213aa20c03d0d89490869754abf84dbbe231d7bccdced77d53fd4527356d8e02b681fc89a535ae87308bf7fbc26197a5ea85bdb3aa033b8da5cd197ea6d72f96f63b03f4ecc7adedf399a5043776cdb32c08f30b77f34df85f8adb8e02649a04b020b03e17d445ca63e4ed73ae432c481392e031eba2f9d2f7f981d1e50917822bd6ff71c239d33444ada3523a59dfbce5457eadec1ab926c9e6c5299c7521e3f204b96901a712504fcc782e8cea80ba12a7f7e71cec3d0871899b6ca059061da037715f7d13fed01c9cade1e687b4fbb1f4ac4b040db3b43800f112fb900e4f772d61b921cbce4da6f +AD: 324292813b7df15bc070cc5d8a4bf74ead036430be63abc43304cf653959a24a91c7de5a671c50fa8a87e21bb82b069999aadfb6895d8bda4c3083d17b8ca55b9ab1511ed8c4b39d8c28c11a22ef90c08a983e3fe2d988df9e02b16a20b24f39ddb28429625f511db08298c4dc321f6c268fc836a6191df6232f51c463a397a8d8b33374abe94e62c0f5c322387e1fc4a1c1980a04a1a3c2c31b32f183a11c3268c6dca521149dc16af120a78be6627210e8ddbc44472bc24d66ce3681c7579b3d9a425212a704a4f5105cb80f0d18ee860953d10b59c114826779bbc368d7a0eece9f223e47cd8e5fd453607d101d9d9c2bd9a658d6520b87d7b4263f6d845a524a36e4 +CT: 2c217e969c04740a1acfa30117eb5b32dc573df3354f4cc3bf8f696ff905f1e640f3b2c250473b376622e0c9bda13b94640521be1ef0fc660b4c10dbe2bfc093030753e04f6aaecf813b43b61f960455974b8bb8a9b461d1e8fd3802315e863c00448f24dd38deb90e135493274eb14ccbde15c50dcad734ed815a806be6622492a84cd062e3ba567b909a205a1d0d2bedd40169697d261c7b6c2e0b1f069853fd470e8f364a142c386c439a6dbe192ded5a3d0fbf73799f588c59e58c60249d980ddcf0d9693631cd9b3f972509c3a77123d38d9e267ecad06e1208e3f1c0a69fbca7c3bb1a48fda19493d0f8f48398820057b94120f3ef97d87e9e8a1b301a2534c68f +TAG: ce507bdb0c71f8e89f5078495f7995b8 + +KEY: a76e9b916f5a67b78a5949651c8c3a9741a1bc3c41cdf85fd2c8f3e9a0616098 +NONCE: 000000000808da8292dc14e0 +IN: 9c149eeb09345c3c22462b03e49eb4dba6bc98b269b1086d752bcd8eea53b8977b238a04a994baf915591686baab90b79a3bf7d9adb2c6c2e31acd3e72f0813fb745aa5fb2e3da408f78001c9c09bd26a1a2646011b6120aaa2bbacc4a16c39fb5257b9b2ea2ad8bf70bcc9855cf11841116c2767310cf3cd49d1aa44cd505f079761e064d5bc7cea4a7173b086882a77d3fc179efc86fc4db8a373491d2ed81eabc63c950e832db17d09f474d4ec46bde47830caf26fabaa0372b81fccc449c0e19ccd630caf693a7b43bb1c408a54e03f50c44280a05ad89fb6e8f01d8ac278edf556e5d86ceb4b614fb2ef133819c6e1ff6abb86c54a135256204b5cd400b93624d3932e7c2b046 +AD: 6aeb7031e4a2e23eea93f05fdc562aa2bf43b8998bea7344377aaddc60fbdb7bcb1491d379ed0cb613ee757cfb66490db61bb431d2fad34b38ddd55bc5b22aa6c4773b9992f34b878c5663f6e8cdb5f80a17f4d312bf342492e48d1ce4c6d754076a634fece61500acf8168d47381af4faf980c6cac2bfd5da8c09b6edb0f543bf0fe02643e38d73fa37d8ae87fb66193f22e57faf4393c007d48c8631a685d520578f8f89db684fb371ea02f3a58b1e2168f0216321139472e0d03b6d90ba8aab65402e1c1ac4f9172a60e27e3d997b9b05e2f672120d6c87bcafa6d4c9b4cf8ba8a82932d92840368fc53dc5b48526103dcab5f1531038aabe89171327ac559b98a3cf4ea70bf051 +CT: 9c3faab9261a63cea9477b3269007283995b06ba77ef83d9e693f7e4ee9855550eef94855be39a7a435b6a3584b202973777c7b2482376ba47b49311947a64983b60236756ee4455d4cfada8c36af8eb06b06ba2f6b79ffb1185c89f2b2a831cfaa3855fc1841d8910908be5078352011168a67d36372d851a3217cabf593ea462dcd325cf9a4f67e85418fd5c924e9b92ab026cbee4e7ab1067066cb5949dfc699a68fe539e1abb13cec33904e5207e6963d24f5a0b770613b8b00014e791bfff88f9c25ca126127a2f8d1d1e9794efd28dce98b53e228073faae8d5047530d502184fc341321c3f55fcbf41187fc31262c325b97f519959b6a29b36c71f76f60196bb1457b77c8bb +TAG: 73b00b1705602479aab944dcc1b282a2 + +KEY: 98cd2477a7a072c69f375b88d09ed9d7b9c3df3f87e36ce621726f76e3b41a1d +NONCE: 0000000077d185aaf715aa48 +IN: 42b31eefdacab0f03ef6060156000c8195adb0976cabbe1a42bfcc09f85659c60b98638401f2d2e2facfb9a97a62926bb0cecaf3af0180a01bfb6e576babf7fc43331937a92abd30cddfa3e450f895e9dd914dea3fafd759c136d685310ebce28ac0613ccdbf30115946c9634b67510b77d0e37f07714b2ddac9d7095b8d4bd887c132c4a9127eb01c8dedb4c39c87b98a741316656f9a8d5a5b0c0ac84789aa2347a5f99ca5ad55cd1bcf98f703eb4b00badb8a8555f38b3b368db8ba7ceea94e8b219f51edce75d84166b5602156ed5962a93a51db73c59d87e906179d7a74a2a2a69d8ad99f323225c87e475d3f771b4a203a2e2b03b458401044649fa6536dfab24d7037807dcbf6518e6578 +AD: f5bb1496052a4361dddf72a288e36953a3d815d6876c013f1d6ba839e127f721b052b1f7d8ca20c7dc0386a7d459ebd7eb9fc8cb08941e6ca9ddb980f3115f65bc1928a414d441ae71dcb879d5bfe0cde0562bc37f8fde0d5291ad405c92fcbb860c43b55ac0fe663b54b3d0616aca13a5c82b7b5d34125a05c2acb5530141030e6f2aa0c8322b2c8fa307e7518918e550e9f48921c6168f094d8758e16b9f815fd0458095c4143f0922adb1840d0e685636825a9c90ee90ee537f4b8dceecbc4287c82dc9a00d7e51671e37ea284ee3ca501b1b2596459d3f592f70186f41125739e342c9f6be9241973b1414dfe5fb8cba1af82e679278cfcf95420df0c5364af4d7e72ad57d5c871fcbc35462 +CT: 7a3bf3e3ad5ae3ab71fb1f7121c3d8fb511099484b50af7ca128ee0337ed4b828dc4cde0b88dc1e8089101fa82c9beb3eb48fdcf0f5b16da441f5a3fce9a590022af95a94aed6a3e71e505f60f303c78c356f274ea85a55354078530664ecda32c80e77dc20974b3b38f4825b8fbee8c3970769a2f42c5181608a8d7d76ef4d093961b665ee42b9708fcafe2c82d3a307173e2a25ad2528c3bf83352b9265e45b70722d7cf8c9b80826d21335234ee3db69d0d37871c83222365900c96c17a7e9f5742d0bfe383be24d0d44590d4b0f29f7abe0c65daaffb968b3f2657b1eb300534eacb52ec7a6b6f9f57a50a91b1799f491361cf613c934b7f520dc4eeeb40ffc45e10be0a95e76f366d4eac14 +TAG: 69302888812eea030d621b640e7bcf7c + +KEY: 2f0f4631ab1c1bcf8f3ad0559c818d50e0af7d8cd63faa357f2069f30881d9cb +NONCE: 000000007d0ced2fdb1c9173 +IN: 6516ba1d29357144eebfa486d21decf223da3aa76ec29bbfcbe7f1eeaf4a847710e5080177f7e5a7c8b4752c219b1cc70aef4db861ba67d0fa6222d9f4a1dc756a0ba44e62906f9374a960c16198866d867854d88f528a60e212eb91645787e75685b2e215c0a41990abc344a77236ec0186ba63a664592938cc5a8ac1d3eb99c95ce00e19fbe249263083d85b052d48bfdffc01585dc57bb2a2c6c4a819604c1ec0548c6f0f78dc05e4418b36277dc07233c7532f9c289d6aed0cc6bc7df4fd0a536c497b982e2dad2c30d2db1c6545a845c5dfa83a4ac49ef06fc9c919079d3e299e31b5c3be370814ae5022ae469d3ee55246a41bd0dc4e64351cc38c3c09af0a1aee3b388a6892deff0df3f93cd92d722b +AD: 1ccfa1ececc8de1e200d0ecc19dcf67b7c96bea3a282c2bccba61035db5c14776387b8b8f58e5757deb0129d4e5e315f64df354a5985d2e47ebbbeafe0c914f7cf1d63dd0311ace19e69a8b6ff0ab25cc8df0408d22132205e89e5eb679268d82b2913e64e3f885bbf4a6d379b760b94590e3140dd7275ab4713cb56d0b716e2718f11316640cb394802862d39e77a46d0c065af3caf7dec14e887039d8aa8c3d3a8ac1ee06026f49d00b2f59d971b54735e95a51f199389a93a4fc24ebaba1f7a2eef7412f61febf79084fbf481afc6fb6b204084e5ef5df71f30506459dea074f11fc055cd2a8c0fc922c4811a849984352a56a15659b7d07a4cc90b88623638ea00c4c8bc13884df2237b359f2877aa41d6 +CT: e580093789ba17ffb46672dc326f09278aca08598d3e5458eaa53e6ed45d5c71a396e35b5ea3fe7b7c0496a734d24f1c75420694be2ff095d5172fd3407794e4b99fd7c374fbe8d1564a048614d3f355bfb5866de1a53e1a51f9f5e8312253cfd82f36efaa1898c850ca0d975ad1e8b0d9597a5a9e6516fe2a3c92efb7495557a8afc3da15b0d3e2ba58f612519836946cf2d15b898320d16a026c8c00a1be2e35f0ebe68f28d91c6c45d24c3f3c157cb132fa659b7794df883d90741fa2d2afcc4f27858e13ecd41b154a35d24947ae7361170060c107d8ecacb393ea67104b60457278a392fdf1794bab97d3b02b71a4eb015eaa38a4b4c944c2bc7cd5e329da4a1ab2937a6af81a6caa5fce752331fdefd4 +TAG: 19bbacfac768bb0ce71e39c5d4d3e9a0 + +KEY: a48b9b6df475e566aba7671fbd76772cb0eff0b12499967978ce3e25fac92feb +NONCE: 000000002ccbf0d6c40cb302 +IN: 09da1cacd001dce4f7573a065a4406fe0da04ab367a2d87780a2762e168957a88d3fa78f0a4b6978d449026e5a801d32884b6e14fdaaaf864214f928ebc03dead081fee96683ebb032362d5088c4c2a3b1e242f055f2604919f4dd551db777a258cf9da6d95a2bde249247812b9efc7985cf08707620808524d6dd3079b0b63bf0f71ea5de834ccb8b7c6a97125fd6ca49148e866d3134bbf1d8a6b714e9a80fe549c8bfefe342f41be2ba2300e0028f78cefab65274632dfdbe70bf7d655ec4036df561f2d4fc4d56a482bbe2f9f2ae279b3aa216b39afee75e53602de319484db89a51e844f38c361634e474f8f1f01c340f3f3594860d671346449c6d08ee38de22d246309bc7e4a252a29c86aa6d94b5b4fa58904c70 +AD: 1c2503d5aa1aad193f0da12874074ea0432bb76a61cd43a3017061514da0759846a0f3ae3a49fdb0b6d29f713de665beacb6568f2694112ca380d13f3c1698316866a7a7f87f1d7503a92176ab84fc08977b46ba664508a858e7525753c45511b3d2f407d5e993c6ede77f13d12975707e5195704970a89f71fc30828049f92f944f3aa93d6a5297e678e08952919beb7eac5919df1919cab3c3da6aa696a1eeab6371f310f7e81143e7d240b0213ae554524b52000306160dd4877bf13ba0f13bbe867da7c7d707f31335eef4cd942938ac890a0829ec66bd30ae01a2188a6e5ea0f17cd7dc875e17f03c0ab5dd18e36db8a1fc1f72859ee046b62368f168b3bea2234e0432c07b7d8e1b9277f21e692c513b9e816e6860 +CT: 7d35cfe4be56bd6e0e09dedcd01735b915bc1891a4d1f6a541abc4bcd0ebe89dcb8e365e5813742e8ec65777b6159422fada747da99394252baf8a046fc1b60ad79755f545f4448627b7acaf403000894f5641e78d3f946dfca29ec617f0660dcd6e8d8827e67e1022a245c595d86e60fbd176bf721b171bbe5ecaf4ae671b9f3dd3920146e6ad431bd8fc431820e19454b6ca209723d80fdbee187fca9c937c979206ae97be55f6ba7366a5608770a11d537396485eb0a66586385f4d4cf3905d1fc90831c3e136d5d513fa22be285193142994a3ed477145bacdcbdd791e8b3b88b0d4f1d18b27382550a818c4fd8884bf36f677c6c3ff5677406e510911e696af75e5b3f859bef699bdd16e6215fdb98d874025eada50 +TAG: 0fa4cb2bab84336409aa4349ab99a8bd + +KEY: 923d4b086b9e43b986f7b65e4cea6113a3d8aabefa89323c5e4d5b6f158bb7e0 +NONCE: 00000000a0f73297b87f5deb +IN: 21435e8d5c8edf0684f58c2cba4070c10b4801adf46b6c4d322eb3990a38a9ad338ad704b9df6597f3e68d66cd5b56290c8466db2231e56d6bcb9c44e1bd081f42ca2a894dad369df2bd0d2c63d6c881732d6ea22bb22b5bc9a62eaffa1b094d0845f6b966d2cb095e7b3b8bcbc15e707449d35c8df4aea30c3b7243e977fffd59c80f1c5c9af4bb5a54b9c786fbbe8d21b2b906a87a786caed841a34a3e0cc0ac3209d83c58afba19edd63622dd261532d2cfb0b49d527d8eaa0887a087f5129d897f665264b229f860363d71a88b7d49c8dc6360182b357b0662391bb41337f46010ac32b9fada2d60a2efcb99365d3b27b7ac396900d1c821d0df8b86cc9cc1f2673259a33efea610bf8e1d00d7e9db2afea21da8f58c55f799999d +AD: c853a8b39c0dc597d562f123cd221e4104b65423a062a4f4ba890ba344feb84290f61817e23330c365f58c3583ce08360d3c1171982ead5496d525ac878f23a57480a6ee39d4e65afd6268245bb982a2545fa1195427cdbbcd404cdad5198f55cce2a5a028fae435f71b15921d066e8d43766c32b2f2c3f57c0674e129607dcd3703eca529414adaee79d81fed432153cceb6f3fc53404810d8ec878f7d94be5d379d0e0e1aa9bc404b4b5d396038a9d76a5ce53c9f3759b8e50fb331858ca58cee81bfc3ee58baef5d19c402a3dc8b36370ec1ace5a4aa2527fb94b4f933a4ab8ccaaf6a5af5a779eae5667c2a24ab027e781c8d4f30c377aa5885a2fdaf6507d18cd824a847c35368b4ea984d2c3c3824a5b8ba3042e1852504a21a3 +CT: f2e21052eebbb86a4f5e803360855d8632aa727dca6f5e79dd74d7aff106e442001928d113005b030f8446f8eff2ee951db663978abe43090dd5ad2c51ba97a0ecf988c607d95e486d02524f690fa3c28d5c48c1f75c1f555e7b43fe7e46f2ca2b9fdb408ec4ba18b6cdde2af673183cb7b1a3c23ae77eddd4cac75e1ea14743fc571f8d31ce2e96787524cd48aadaa474181c096a032184574ddc25a6e0ac8441c212bc36298708e33c963ae931e6c6241d1affeef7b6ef759495df44b6ab647447693cf703569e69aa72f1def9a342b8978c1edea9703a421ca75b92cac4de14b88c693200022b8a2ed22b1c4678b99f4d695e080dd1196d7168e14f0d0f8ff880d742e97b9f6d00af1f7118e10b77c5ef3ea6c52f84a20fd6ea46dc +TAG: 9bd8b7743c056bb2334833afd6143e18 + +KEY: df73adab2768559ea983cce85453fe81d79be3b3c57f202b31b94d6635cf2e4b +NONCE: 00000000e7a87e6bf6b5a354 +IN: 0032a37abf661faa18c587fd2aa88885c061deeba81105dd221969bed5d59c7204b09b1a8c4c8de3b9f748c7fc70626ebeaca060233a57b102221b1bf0f3d9fdaaad3d2b1439c24d08f9c67f49f3c47128f92ee530abf4c4f4573bc60ae4b38109f55bca3ca9e1ba9f9fd6e34ba0d174892977a53356e1f5c88c614fe3ff3b3dd0818e7a2285412e3b37444bbe8a80942efcfd03958809a6966cda9430b2f0c9e552f4bced6e19eb3e85fc5758bd7b588297ccbed37ed94c3adc8c08ea8b058462aac9d57a939ec711bc4ecfec944d2b653b7cfc7b02a65d7057c9fdadd51b9da8cc4a3c68dae9da8b9c5319c1a2baa3d6c891c5ac4a39461484b5a01abc64df447ada24c04a4363e605eaccf339a9aa515e724206206da6d22bbd2f52e64cd7c895 +AD: f833e5ab4f8bc89167f80f576b1d6b22cdd0e30721f5f735799746cf645b6eff531d4c7b03584f3dfcb73cbd35ac42736216dc7f0de098a4f42c61ceb4b227ee288e47d697a0a76afc762f084e8fdbf9351c28340c324771c109a469341ab10ca10483ed2af5e878d7d3dc2bced2f72da3d1a25852b103ee9878e8158eb4309c1ce528f3a178ace153b6d3ae0af0d577cb3cb1540489e80427f792217ad8a09b84f027fca7ceb651b4264e98e94b4cb8a37b133390897233e8ba9103628d05b9609e8552c4a4b11e3f2fa8d56af36957390e88cba44656be3edace798cf8cdf7771bac338a256bc3cba6df97728f222f423ca7c6d149c9372d66163a98f79a234b00d4b75fb2ec860dcc2d1998105e4b9c01d68f079f3e0aa21cc534047fc7b858f8 +CT: b842eadfdf431c135bd6581d3eccae54e2267d8890036aa33dfe2d2d9715c44625441210a3a0d666d708d30588fe851ec36e10d8fa3584ed77b095149494b7c54379d62c8935e1d2b9a8f47e4759ad0b3437fdf2cc2fb6c5ea25ad10e0bdc9dc5b0517fc237eb783cc461c46665e2b1d1a5b8008dbf409ea2a63fea0276de23a32c99d92a498807a0f95e208fc6262321a78aafaf0cc3f833fff37bd4efa66f6023a25cdc6702cee3912799563d908a5183c9956a06aa71085d855dc7c809ed6e2889592b361ab3ab39060f8e419152187a794a19c2a1128882201900ea2cd597860674bf78d9720643df8701676718fd201baed4935a88e50558daf86edd08a9ab227ac7afae55c974b68de8dacad4a4d79b13ed6dfe74017a4cb9148e033436fb6 +TAG: ee1ec36804e1d5cdbddb52608c711fd8 + +KEY: 55a4be2448b464c2ea52a2f2664ed6aba865c14ea1fea77f4689331fd105c8d4 +NONCE: 00000000db37c0a405b4626d +IN: d266e66272e5d3462081b004cb42429c8b9741e9f678153754d726f6f9aa513464763c5e793b482fe512fece97585f1426120d4cefb3d0a8cc0a8db4bde93fc72c78f44d4fecca14650c660d3e285b327e7cdd813063e7e867b8a2d059a41bab70432b7f857199894da90dca3fe5272bae1ec694a1a07b60b05df275784d4975637e4673109f3ba846dfd1a048b202ed8e89973be608b91ee4743b1e759900f1443038951fe6189e806638985f3c16338c3c60695df58e621154d79bb973859c4558e9dca90470f77c73f004443ad5db0717abbe43266f90e57397b83ac34d1fef2e897e2483d5bcdcb627abd64b0d1aef525835f25e76d6e9158232cdde6dce970b59f58de8a98e653be32fb58edabbcefa5065d73afdf1c9c4fbf50c1022bd22bfcb98e4b422 +AD: fd6a3fdd879f8880843eac20ae01c1b9dc3487d270a806572088ef2ddc1f1e0de495e71d4813bf5c501ad31e5d791c4b5b3a0a71b63fdddcc8de4b056064ef467989ecccc5d0160d403bf3a025d4892b3b1de3e062bc3581d4410f273338311eb4637529e4a680a6e4a5e26e308630a5b6d49ead6d543f8f2bf9050aa94ce091318721e1d8b96e279f34b9759b65037bec4bf6ccda6929705aeeeebe49e327e4d7a916620c9faf3765120658af34c53fbb97ec07657b3f088fcbdc401aa7949ddeda34d885018c2c23f4f0bb8218bf0d4fc90643658b4d8834f4a8c08e590c2a790995baa9e77627c342d283e454f84fcc05be15e9627a2d9be340c9d72f222bbdfc47905f56616cd9f936d49e4732f319f020513340fb8b22828db251b102b6b137c9533936d6 +CT: bd11ed07b7b4b30eeaf25d6a41a549cca0a5aee71f990ac566a37265d7af2ce3c03703427ee0b2755c2bdfc29f9d826aec6ee4ad28af48079ac23db16580b97424f3a4e35cc23625d39f95699d9ff5143e9a2bc26fcfee4f125f5aa2d968ccfc2faaf9db3c28850f6757f735cbc50c94c498bcde4f23bffafa8dd5f70d1a011e35eb26e905d4e68848fedebeb197be595c085ba33f11ba8398258445051751888e9bba111f800f31b37c447074ca6dce6d54b4dfad6cee5138643d4f6ac045e8047248924e88ea4294c7878bc22c9b41924ce301f22693c33733107bf1ba85e34806c5e4366ea66fc52a5f89dd9bf213239158b3d4d2600dde696c61d76c398b9bf10de9118e812e891c8f3355c0ecc6405f79bc32a58905e37888a1d8395fbedc3ac54eca569f +TAG: 296a397d280d026fc3627f4718971be9 + +# Tag truncation tests. + +KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865 +NONCE: 000000005d9856060c54ab06 +IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e +AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51 +CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36 +TAG: d3 + +KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865 +NONCE: 000000005d9856060c54ab06 +IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e +AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51 +CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36 +TAG: d3f7 + +KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865 +NONCE: 000000005d9856060c54ab06 +IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e +AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51 +CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36 +TAG: d3f7b9 + +KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865 +NONCE: 000000005d9856060c54ab06 +IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e +AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51 +CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36 +TAG: d3f7b9c2 + +KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865 +NONCE: 000000005d9856060c54ab06 +IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e +AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51 +CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36 +TAG: d3f7b9c295 + +KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865 +NONCE: 000000005d9856060c54ab06 +IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e +AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51 +CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36 +TAG: d3f7b9c295f3 + +KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865 +NONCE: 000000005d9856060c54ab06 +IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e +AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51 +CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36 +TAG: d3f7b9c295f374 + +KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865 +NONCE: 000000005d9856060c54ab06 +IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e +AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51 +CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36 +TAG: d3f7b9c295f37465 + +KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865 +NONCE: 000000005d9856060c54ab06 +IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e +AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51 +CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36 +TAG: d3f7b9c295f374651a + +KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865 +NONCE: 000000005d9856060c54ab06 +IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e +AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51 +CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36 +TAG: d3f7b9c295f374651a84 + +KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865 +NONCE: 000000005d9856060c54ab06 +IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e +AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51 +CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36 +TAG: d3f7b9c295f374651a8413 + +KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865 +NONCE: 000000005d9856060c54ab06 +IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e +AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51 +CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36 +TAG: d3f7b9c295f374651a841386 + +KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865 +NONCE: 000000005d9856060c54ab06 +IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e +AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51 +CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36 +TAG: d3f7b9c295f374651a84138648 + +KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865 +NONCE: 000000005d9856060c54ab06 +IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e +AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51 +CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36 +TAG: d3f7b9c295f374651a84138648a5 + +KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865 +NONCE: 000000005d9856060c54ab06 +IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e +AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51 +CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36 +TAG: d3f7b9c295f374651a84138648a591 diff --git a/external/boringssl/crypto/cipher/test/cipher_tests.txt b/external/boringssl/crypto/cipher/test/cipher_tests.txt new file mode 100644 index 0000000000..0a940f14aa --- /dev/null +++ b/external/boringssl/crypto/cipher/test/cipher_tests.txt @@ -0,0 +1,613 @@ +# RC4 tests (from rc4test) +Cipher = RC4 +Key = 0123456789abcdef0123456789abcdef +Plaintext = 0123456789abcdef +Ciphertext = 75b7878099e0c596 + +Cipher = RC4 +Key = 0123456789abcdef0123456789abcdef +Plaintext = 0000000000000000 +Ciphertext = 7494c2e7104b0879 + +Cipher = RC4 +Key = 00000000000000000000000000000000 +Plaintext = 0000000000000000 +Ciphertext = de188941a3375d3a + +Cipher = RC4 +Key = ef012345ef012345ef012345ef012345 +Plaintext = 0000000000000000000000000000000000000000 +Ciphertext = d6a141a7ec3c38dfbd615a1162e1c7ba36b67858 + +Cipher = RC4 +Key = 0123456789abcdef0123456789abcdef +Plaintext = 123456789ABCDEF0123456789ABCDEF0123456789ABCDEF012345678 +Ciphertext = 66a0949f8af7d6891f7f832ba833c00c892ebe30143ce28740011ecf + +Cipher = RC4 +Key = ef012345ef012345ef012345ef012345 +Plaintext = 00000000000000000000 +Ciphertext = d6a141a7ec3c38dfbd61 + + +# DES EDE3 CBC tests (from destest) +Cipher = DES-EDE3-CBC +Key = 0123456789abcdeff1e0d3c2b5a49786fedcba9876543210 +IV = fedcba9876543210 +Plaintext = 37363534333231204E6F77206973207468652074696D6520666F722000000000 +Ciphertext = 3FE301C962AC01D02213763C1CBD4CDC799657C064ECF5D41C673812CFDE9675 + + +# DES EDE CBC tests +Cipher = DES-EDE-CBC +Key = 0123456789abcdeff1e0d3c2b5a49786 +IV = fedcba9876543210 +Plaintext = 37363534333231204E6F77206973207468652074696D6520666F722000000000 +Ciphertext = 7948C0DA4FE91CD815DCA96DBC9B60A857EB954F4DEB08EB98722642AE69257B + + +# DES EDE tests +Cipher = DES-EDE +Key = 0123456789abcdeff1e0d3c2b5a49786 +IV = fedcba9876543210 +Plaintext = 37363534333231204E6F77206973207468652074696D6520666F722000000000 +Ciphertext = 22E889402E28422F8167AD279D90A566DA75B734E12C671FC2669AECB3E4FE8F + + +# AES 128 ECB tests (from FIPS-197 test vectors, encrypt) +Cipher = AES-128-ECB +Key = 000102030405060708090A0B0C0D0E0F +Operation = ENCRYPT +Plaintext = 00112233445566778899AABBCCDDEEFF +Ciphertext = 69C4E0D86A7B0430D8CDB78070B4C55A + + +# AES 256 ECB tests (from FIPS-197 test vectors, encrypt) +Cipher = AES-256-ECB +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Operation = ENCRYPT +Plaintext = 00112233445566778899AABBCCDDEEFF +Ciphertext = 8EA2B7CA516745BFEAFC49904B496089 + + +# AES tests from NIST document SP800-38A +# For all ECB encrypts and decrypts, the transformed sequence is +# AES-bits-ECB:key::plaintext:ciphertext:encdec +# ECB-AES128.Encrypt and ECB-AES128.Decrypt +Cipher = AES-128-ECB +Key = 2B7E151628AED2A6ABF7158809CF4F3C +Plaintext = 6BC1BEE22E409F96E93D7E117393172A +Ciphertext = 3AD77BB40D7A3660A89ECAF32466EF97 + +Cipher = AES-128-ECB +Key = 2B7E151628AED2A6ABF7158809CF4F3C +Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51 +Ciphertext = F5D3D58503B9699DE785895A96FDBAAF + +Cipher = AES-128-ECB +Key = 2B7E151628AED2A6ABF7158809CF4F3C +Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF +Ciphertext = 43B1CD7F598ECE23881B00E3ED030688 + +Cipher = AES-128-ECB +Key = 2B7E151628AED2A6ABF7158809CF4F3C +Plaintext = F69F2445DF4F9B17AD2B417BE66C3710 +Ciphertext = 7B0C785E27E8AD3F8223207104725DD4 + + +# ECB-AES256.Encrypt and ECB-AES256.Decrypt +Cipher = AES-256-ECB +Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4 +Plaintext = 6BC1BEE22E409F96E93D7E117393172A +Ciphertext = F3EED1BDB5D2A03C064B5A7E3DB181F8 + +Cipher = AES-256-ECB +Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4 +Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51 +Ciphertext = 591CCB10D410ED26DC5BA74A31362870 + +Cipher = AES-256-ECB +Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4 +Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF +Ciphertext = B6ED21B99CA6F4F9F153E7B1BEAFED1D + +Cipher = AES-256-ECB +Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4 +Plaintext = F69F2445DF4F9B17AD2B417BE66C3710 +Ciphertext = 23304B7A39F9F3FF067D8D8F9E24ECC7 + + +# For all CBC encrypts and decrypts, the transformed sequence is +# AES-bits-CBC:key:IV/ciphertext':plaintext:ciphertext:encdec +# CBC-AES128.Encrypt and CBC-AES128.Decrypt +Cipher = AES-128-CBC +Key = 2B7E151628AED2A6ABF7158809CF4F3C +IV = 000102030405060708090A0B0C0D0E0F +Plaintext = 6BC1BEE22E409F96E93D7E117393172A +Ciphertext = 7649ABAC8119B246CEE98E9B12E9197D + +Cipher = AES-128-CBC +Key = 2B7E151628AED2A6ABF7158809CF4F3C +IV = 7649ABAC8119B246CEE98E9B12E9197D +Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51 +Ciphertext = 5086CB9B507219EE95DB113A917678B2 + +Cipher = AES-128-CBC +Key = 2B7E151628AED2A6ABF7158809CF4F3C +IV = 5086CB9B507219EE95DB113A917678B2 +Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF +Ciphertext = 73BED6B8E3C1743B7116E69E22229516 + +Cipher = AES-128-CBC +Key = 2B7E151628AED2A6ABF7158809CF4F3C +IV = 73BED6B8E3C1743B7116E69E22229516 +Plaintext = F69F2445DF4F9B17AD2B417BE66C3710 +Ciphertext = 3FF1CAA1681FAC09120ECA307586E1A7 + + +# CBC-AES256.Encrypt and CBC-AES256.Decrypt +Cipher = AES-256-CBC +Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4 +IV = 000102030405060708090A0B0C0D0E0F +Plaintext = 6BC1BEE22E409F96E93D7E117393172A +Ciphertext = F58C4C04D6E5F1BA779EABFB5F7BFBD6 + +Cipher = AES-256-CBC +Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4 +IV = F58C4C04D6E5F1BA779EABFB5F7BFBD6 +Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51 +Ciphertext = 9CFC4E967EDB808D679F777BC6702C7D + +Cipher = AES-256-CBC +Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4 +IV = 9CFC4E967EDB808D679F777BC6702C7D +Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF +Ciphertext = 39F23369A9D9BACFA530E26304231461 + +Cipher = AES-256-CBC +Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4 +IV = 39F23369A9D9BACFA530E26304231461 +Plaintext = F69F2445DF4F9B17AD2B417BE66C3710 +Ciphertext = B2EB05E2C39BE9FCDA6C19078C6A9D1B + + +# AES Counter test vectors from RFC3686 +Cipher = AES-128-CTR +Key = AE6852F8121067CC4BF7A5765577F39E +IV = 00000030000000000000000000000001 +Operation = ENCRYPT +Plaintext = 53696E676C6520626C6F636B206D7367 +Ciphertext = E4095D4FB7A7B3792D6175A3261311B8 + +Cipher = AES-128-CTR +Key = 7E24067817FAE0D743D6CE1F32539163 +IV = 006CB6DBC0543B59DA48D90B00000001 +Operation = ENCRYPT +Plaintext = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Ciphertext = 5104A106168A72D9790D41EE8EDAD388EB2E1EFC46DA57C8FCE630DF9141BE28 + +Cipher = AES-128-CTR +Key = 7691BE035E5020A8AC6E618529F9A0DC +IV = 00E0017B27777F3F4A1786F000000001 +Operation = ENCRYPT +Plaintext = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20212223 +Ciphertext = C1CF48A89F2FFDD9CF4652E9EFDB72D74540A42BDE6D7836D59A5CEAAEF3105325B2072F + +Cipher = AES-256-CTR +Key = 776BEFF2851DB06F4C8A0542C8696F6C6A81AF1EEC96B4D37FC1D689E6C1C104 +IV = 00000060DB5672C97AA8F0B200000001 +Operation = ENCRYPT +Plaintext = 53696E676C6520626C6F636B206D7367 +Ciphertext = 145AD01DBF824EC7560863DC71E3E0C0 + +Cipher = AES-256-CTR +Key = F6D66D6BD52D59BB0796365879EFF886C66DD51A5B6A99744B50590C87A23884 +IV = 00FAAC24C1585EF15A43D87500000001 +Operation = ENCRYPT +Plaintext = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Ciphertext = F05E231B3894612C49EE000B804EB2A9B8306B508F839D6A5530831D9344AF1C + +Cipher = AES-256-CTR +Key = FF7A617CE69148E4F1726E2F43581DE2AA62D9F805532EDFF1EED687FB54153D +IV = 001CC5B751A51D70A1C1114800000001 +Operation = ENCRYPT +Plaintext = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20212223 +Ciphertext = EB6C52821D0BBBF7CE7594462ACA4FAAB407DF866569FD07F48CC0B583D6071F1EC0E6B8 + + +# AES GCM test vectors from http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-spec.pdf +Cipher = AES-128-GCM +Key = 00000000000000000000000000000000 +IV = 000000000000000000000000 +Plaintext = +Ciphertext = +AAD = +Tag = 58e2fccefa7e3061367f1d57a4e7455a + +Cipher = AES-128-GCM +Key = 00000000000000000000000000000000 +IV = 000000000000000000000000 +Plaintext = 00000000000000000000000000000000 +Ciphertext = 0388dace60b6a392f328c2b971b2fe78 +AAD = +Tag = ab6e47d42cec13bdf53a67b21257bddf + +Cipher = AES-128-GCM +Key = feffe9928665731c6d6a8f9467308308 +IV = cafebabefacedbaddecaf888 +Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255 +Ciphertext = 42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091473f5985 +AAD = +Tag = 4d5c2af327cd64a62cf35abd2ba6fab4 + +Cipher = AES-128-GCM +Key = feffe9928665731c6d6a8f9467308308 +IV = cafebabefacedbaddecaf888 +Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 +Ciphertext = 42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091 +AAD = feedfacedeadbeeffeedfacedeadbeefabaddad2 +Tag = 5bc94fbc3221a5db94fae95ae7121a47 + +Cipher = AES-128-GCM +Key = feffe9928665731c6d6a8f9467308308 +IV = cafebabefacedbad +Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 +Ciphertext = 61353b4c2806934a777ff51fa22a4755699b2a714fcdc6f83766e5f97b6c742373806900e49f24b22b097544d4896b424989b5e1ebac0f07c23f4598 +AAD = feedfacedeadbeeffeedfacedeadbeefabaddad2 +Tag = 3612d2e79e3b0785561be14aaca2fccb + +Cipher = AES-128-GCM +Key = feffe9928665731c6d6a8f9467308308 +IV = 9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b +Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 +Ciphertext = 8ce24998625615b603a033aca13fb894be9112a5c3a211a8ba262a3cca7e2ca701e4a9a4fba43c90ccdcb281d48c7c6fd62875d2aca417034c34aee5 +AAD = feedfacedeadbeeffeedfacedeadbeefabaddad2 +Tag = 619cc5aefffe0bfa462af43c1699d050 + +Cipher = AES-128-GCM +Key = 3de7b368783bd7287f2b9b731814c876 +IV = 90dedcfff100eb1f1db9d935 +Plaintext = 8d766795cadc0961c0f448c62df3827eef3a8664599b3adbaab0cfd63875bceb8f992b4f7447dca10ddd716aa0bc4fe925e1aa3e3fd1d5c430c650fe3546d6b9a24d576a857c5f04e8c0a3b149df277aa19cfa64ee235891d3b8ec0e840d268b1e70dd8a4bf97628a0c7aea38aa21eeb8fb1a8437f2abfee05e0d2c30659e312ec03d30da51b7c19073a2341c17df806e27e796d581143d39e4de8d3f8d46aa6d6fc1a98d94fa69b92dab751d930cc12de21fb1a7468af09e3c12ff6c3db3967d10cf140bc46f17a16e24b010b6cba5ebf777341c52042596ee53008389c48d9690ab9f5625795c3e588f72f7a1670b2b25a9f4eee1c8845ac90f1bf47ae4ea4b607a50aca88ed304cbb700d02d5486139b0bc81ec042e574abf986972fa008b83ef22dbfe720c2f2f6355c87c975932cec545ebed657e5e7570c503e9aa7f0b87d0b2648e421ed1d34749637c95d1e931af8925236387e50454f0ba2e22ed05f90450fad46f4eb7ddb08656511dd065c0f852a7e42f618a961a6c6bec42226c6b6043580b009ec9837cf99844cb74794a82c269ff648e0bae9ae50256a0ad98ad9f5a35057b3004ac96f469f9ee966dadc16dc47616586cf242706df96bb2f7ee43d3bd1c65d2eac7b82ef242e77ab509afb9639e5f3995380e926305729ca762c487f4411ec2a9c688b8347e5287216dbb38c3fe2281a89fcb47ee2ee7ddf79bfa3ab61cd56a00981019bbcea8aa0444eb75958e5fa56ea0036d2de4950a7db886f4a318b433bd41e00905ab158171e0ef13172293bdf70064b9dc7b243bf9dc927589bf9e99468d1cb330639dbff1850cc51929b8971b0b2ede9d06bc5f6ba39d4551b587f09bf6f8206e8f1524f55714612581d6aa45d8fb83425f84a736576deeecafdcbfbb8670d14cd2ab2a7f8b7f374c07881b7bac2605fd5ff7ff7cf43e30cf49910961a9079c0343b8601be8c3e9fe38f49fdab0b7e1a8c1536cf84e4d80d26ae5ec37570839b5cda02929221898d611525c3a88fc444167ffc532b256cdd0a8f31ff08097d75b629fab99c9e1062d1d9962b211e15ec8709934029c4934e64db8d7a2f32e23dc541be306e9a57a3419115994cbc3a8f8d5ea2a6f45b9ea9ac0e51ed0c6680fa029f4552a6c8665aab00ab77928342e7284c321e9500ad4774ef1fed0f596d5aea371fe1793271aef38cde55547f34701a525526e83a72673385a85f44db511bc87ce1f831fc6ccf8204ca4f4a20eac09897aae93684f14ede21bcaf40a09c08012b92600d6a839ebdf8bdca7b34192c6c50bad8796b3be3c375dbae6217815d2c75cc878d39b4e842d4eaa5f5df2242cf230e44a240e18e47827f089b18bf880fd41a2516eac8e6ba3fc2db64a4bc28789860d7b18d9edeae8b3059f4d945b15d0ee27b1f74842dd1df117fe83a8fdade23a47c93902eedc4d33f2dbfcd1996e6dc1458409fde2302830e8d44c58c5ae67486b9950dd938f14c38bc4c9484fdc4ded93a0f90875773453fc14d428cd6e7beb0c705d61229d2b3df09632ebb30b325fefe2aebbf2a7aa8e4ad46277ca4b8b078818b63d04e7652057f6cbbab7c43ac355537e0d3918b4a73c00dbe6b30a27ee7a6fa213d3347ae478e8edc323404b8322b9c7b0173ed61c38ed25f3576a675d527d22edd51d6dfa5767560d3a50a91226338e8c4e6436eedbcd3d2efe9dc1e686b15d2f57d553abcfda57dc316ca453a690f20148f0dfa20c1c4a58240aaf7195095fedfa56d839d0230d55ce9a8ca1b9d1acd6fe98d583148ba0f4a4e3413c76e6ec57ddb79428d3a90079f64d3321c791f60d501c3fd02c8403f0f5e6c6836bbc96430c1b48e83350c3a3cfd017f15bee3e4bb1295d821dc98b85ab3145555cce2c34a8142fe50f8db19918b514a165d12ff6301fb2296788760ac0b6d9e3a57770ad5111cde5d24b6321918cb0b0887a282b827a8749733171914b000e7d3c0edad1d42ca60da37f0698554bb2a1749f73b3120dbeaa32951f8217a781a200467d5b569d16f56fc9b7dff0ac524f03fee0617f4c692d94613b1e13b18075dc9f0d32811d4a8949a95f6b5fa46aeb83597adb409e68b2a0177c36dcc95dcb2e7dd4fb7337ff97c013364fe139e185014948fa698741d822044fa3f6978b16afd18138c845587c405ebf7a6cd1c28610ce67e992ed49e406658a0a202feed9709500d064b6f53eecfca57dd4b38363ce3aae9d59126d8ae7e140a373851188ae28c909181d0ac64770df70dd2475809350cb367825b59d521d5e457b4e36aea6dedd90a2266898b753b57fa359d43cd388e7d6c7ed90bc4c2af34ceafe88a3af6ac376fec35f1240f08af4f3eb30bc53dd68e5762e6d39e6b16f63003fbe0bee828d0d7adc58c41e857c2c44702215b202701fc696eae021af19c79e59c3e32627cd571f5db99b17f1772b5d746196befabb0b7446687827f3315b391d5dff069b1c39c00bb143218ef458e3b397e1c99640d57fc8db2e0083d3d22ed4111a8fc9e0e6f55fe6a56e946dbee43909bdd7d516fdf756ed8099ba80b1e17a5e279119345104379a36962ca9c8b2a53c414d79eb09fe79862ca749a9eabd9185ad1df57215945882f5894868a134bfc35c835e040e77ecf077d6a98a73ee022963d70b036be3fe5718280ae52c5d751211b22950c0597aaedd35af41f7dd5999e5f7ee34a37edcf97df54a46742b0252b196eaee454ff0c30685b15f8de087de208906be1d971f0fd89f7cdff2af0bdc96759d6889fba9ef092ad1c8deab0404562a7f3977d211c28dfd1573aebd5427a8773f03986101703fa19cd4ab96a381c76a747f63b63f7a9a3a08e251cdc593a024f63b443b76d17dd9e151809da3c582fbd334fa6dd0221b6d410c6a78ba95bb0154bb8999f619f2e084a6b9755ceee4ca3c7e0481a47776c8814f13054e627e37630d593bd09d5f10a049c66c9999f4b0b037e81ef70615d674c7c7975972994a053c069675fad3fae5ae3e779233b70254fb87f25d44c104afc3d5911b8b695173f9337130e39a02cf97356cb817f6cd23f55ef74dd06bd24ce5887a7001ef576262ffaa99f9bb5e3f55bda2aa0f199115909af48bb4d6b1a0a0847774515302cafebe75aad1f63362b1f38141e8721851c3ef1a247931b3b450581eb5d09027b9e3ba60ae9801d629b74991b7fd65520eac561d47115a85141d9a757bc75710bedff1630561ae05254ea541a7ff1846ed5e164834417556dd562c45543c88d8030bb56451fd5b3cbf10fb0164c5288789d2aac7e7a836e79bc3dd401a8e3e05aa6714ffb2dfddb3037c35fa1ebed62a073b2da42133f2620ae88de5e3f46cc69f2b9b3c9b88e39b8b108059ac6bd493be5f7a39f6b53ee825f4593b77ec9238f5ab804d533f48803e7d8187291ee25cfac4da5d8c9279517adfb09c422f6d704711726c73828a5082b4c7b3d85611b8f496d3e0f78c5c4f1dd1c722b1b11d55861f232beee6aaef8a00fd2eeeb45f182af191ca6de8eaa25ceda5451416fbf6d1abc0670b8c10e2815076f271044c690bdcb64856b91265bac202043a28f6bbeb807535aad4bd89e572a9427c826b170d3862f4cca70ddffb4769d6593a1cc6c42fd06cf68642835fe474a23e6f63df316f8361bab959b768d78e20c03c2a99913c162a9662bd9981eee55922f36792de0af68da04ab49dca72e3d9b0de79df828b433bcf6be073f851a36418c03a717d54d48c1014ccb793577c8393b7cb53cad6bc7060a54cc6363734f6ad388763519ca09b533078d3cfa61d7bdd4c4dd0ffe64d68d501b55903d3f4a1f310a3826ac2ca700de01d656188dcf577fd1b63e305614b8d13471f6f84a5d4b12c5e119870a63d1e3dbd39d3b5c26b09f9d80f8a59ce836b20bc933496923d278a022c00f3aac204d07d2e5075bbcef1e4820d633a3a2b35974f72a033484a91a1d6a9913239c93e5783b01833073c98f358e3465efd5087af37ad60b7285550e776d67ea7019e788776c5a456102358c32eb4e7c28096af88b9a20d8ce379ba3928a10ffd539c106f4927e7ac0f382c74017d6e4438fb128c660affd45e9bb68452de72b574eeffe3ce239d0718908c3800bc7e8ecd2fc7d9754171506017fd7868594c9373a96579fed475a28811649ce5dc8a3107bd0d8578748878ce4998684620931dc3981a2499568c2f61174c3b3fc46a7010468e8ff75c08cd43ac764d95e2ad1659f9db62e9554f811e0f43bb74779d923c8c243d12a5314d3c0c6ec84fe60e1d2b2e2b20d3e64054d62049ef9233ff55223a319c285e4e3f4c98dc95b2ca81230d7fed9bb99fd7d97430eb32c9c11647992bd85dcb47cfd58ea3e221d095bcf9374a6baa7c8333581f62b9e489282483023fdd18451f09bec764146b587209160b3d1d7a3d2e145fdb640c4bc382541e0d84255122d51a710887ebe1ccf29d41b4dd7fd7368d68ada250d3968d6f0971f0849c13c09abadb9db8b08960a18f84f0346ea0aa71227afa55b90cabc062d549b616400d36450b19adb67d7358e48c043fa1135abfca89374c906f8d1a6a845debf6b37f055d390b029c7f4524958bdf8d7e2755dde3b957f0926f9d3b8821ba96044d3cad2d637b973bfb657fcc06ff44c17965acf572ab7a0c87604c7dd1cfd136a0ad02b22e8ef320e101ea09772588e8c5b4d88f40fe1be18d27146a2b9559491949671700cebff9a709f297c2621ca9d5d1749623abc20a326ff5be55cb9435c03bf49b147b1e0a4a918bfdc3642df90b396a474f81d75c953d87b3f3b4e31fced630bd7c481c63acbb84dd31249101ac5277a36dcdfc80d8d9a2e928e9b2d65bb257bce97ccda83b187da8a7886dc96eab93d0864d88c358105f9cfe1ad0f0a8508b5b3985ff95de652e684da970b57669aa3fdfbe590a631522abe8246393639709a9a6cd549e78e3c2d1acf84643e9f554c5e076f75a5c1dce1be20a66722d0b896837b7036509ab8d473d5d2b7a8374d6a575f69d54afe3e7e18f4faf4e917be8a74e55c271b96d966e0c0b883f84b3ef2e4f278daeda2efd3ce770801d2c4bda5eb9b646deeab9fa55324e917e63e4eb6aeb4176cb4e43af3db61aea1546fbf16e76a12fcdbe726b565710e3f9866551023e5fbac0038678717e6ab4d3e92dcc53049e8cb65c00216d31a8869ff4d3539313fe2fd7ce0f53b255e3659e7dfc5f92b7627dd9ba42972f0ba72b888932d870ab97226040c4c0f4826be131fe1d2cdc21005ec2addd7796f0927501251ab26b0e5f3f9d2a1cb346a774e18bc233cc89aa69f5f70e3d5c17098eed350ec419c82837153b5c7f5813bf5918defc8df143063f3fe45125deded2b15892d5cebce589b60f2ada0f9d608983e8d107d8e6482b5f542c6650b014445e8c055aac142f16cfc59229fc9626f7aaa40cefacef777e494e13dfa93d27c201788ca9f60e572af8d65ffb513473dade5fe494cbf7377bd1ed03db2571d65af3be4b0bf27c1f069797bfb67ef0bd8a88c6286af6712c106df9c418d88054e3b46c88296a2e63894d6bee0dda8833c373d6a1b27637e1510fea3eb2fb34ae27354571369653a282a8d19f2c34f9e5ec34555b4ed24327dc5d246df13736bd41021697104f80c85bd0ae920e9aeb4e628fb8aec269d55858df149af298b06d61250b043c8a14a15f0646d0aaa18109d031c449e66dd7336044dbdec912b1bb615fae2a3df480bd64cbed74be65c8f1acac247e80bbaeb6f9dab38c6addf4f3b094d5934ef5c9749053b9159e280034e601731a12d6688ff27ee3581ae289de424d16676fb750d2ccd5b3f964dd77bdefc15bb204e2350632822384cc194cf9130f1ee81bfc3887d3366ec0b48cbbe0fe674281ae7445f03791887873659825680448f162452cef57d783821a73047078a8cf94c416850092ac772ef0b2e48517ef101ee0681b5259aa27fd56edf3c01e6dba6298ccc91b09bb304b637eccf8c673b816e74bd7f8ceffa6b17ab03df7ee9ca4098d24d044015a07df782a309cb6761528272632a6e1323c4e18284b463dfcabed708e4fc95cef133865cdbec8bfdde100621c65a92762cc3141ff37b66dea8fa6e3aad61dcbf3b512467c4773d36e58989e12a636389c1678c191137a5f7f59668c8a527dddcdd0c3fbb14cf48b8f3ea306850a5eda76c57aad06312d7bbfc18969d7b611f512358a7bdf959cc2f41de1c408133ef02b1fb2cdf8efe9973c27536434e56fc1bb4880db7fe901087b53ef3c0de18aafa47c25f1cd62c362f2e5da41c2dbff0e13adaba26c1e0829f027dc0320442e851eaed9507b70ac17180725349f6ea7b59bf39c095a9d10790e87221c7c2d24b8bca184ee95a3ef7449aad6c1d905f688498ae7a0cd1b01f76dabc342fb2be0295ca1484bece3c9b8a1b91e53de2d2587f3607a7f348f5cbefaa7a6dcf61bbbcae9444e2d25a77b016cbd1508c8cd319e9812b43b0bbca52df155d418dacb6ab1360a9e605fb53c6e20588a10bef42d884989e836b2ff16fbcdd2c1704f75dc8c1ac2cc6aeb92726f5d46e4784c70e1e249c102be6da506e5e3c2cef6a8bc4a60dac7adf3cacca8679f8f792ddc27613e44a70fd849b7617e042da46d65a3e6cf425f59b83cbae5b6e911142abd13a0a8cdf06d041435ee20e2ca417e905d2dc49c15b863ae5920ff7f9380a86bb0c86b69a000c157cd35245bf71f9dfdefbd1760af90ec3e554ebc511aebf650633221ca9157226f613f41406872765f8d7b916ff3877266f017b8d840dca0697ec3dffce7912ea9eafb62cc2f2d0a112c9bc0727444b47b62766bddf5b5f26d391f653b6894b069069979d0cf8cc7fc4143626a8420bc0a3866db3860096cc128d620ceff059d1614487004adbdf6b0c4428ac8897dcf16e6b11a692a6b465a92b40010f3480b444d4d2e24b0af8467666905c2a6233bdd6502521b621d3cdd4a5e1f268d65bf6a1879608ffd3abf635c5f0948f3cec7e087485c72b00258ba69783cfe7d611bc41c27814ef5674185791dbe626e1f276cf2c399a4eb264f19c77ee95d94252f546528f629188318e9ede65a927aafd2f2af56ff32c0ef39862d2f92268bc9400afa8ddeff591f3ef99681263a33b873bd9e01a59c8b281da30875245cbffee5268563c7f6f20b9e22d998934131dd219624d3cef6df2f3d2d6401833f72c619d6f763837141dbf93179d0f01375581ebe227185166aa7988eb9fd453d510ca6616cc013d551d23a33a4241e85aac3201284344977d496d768f5d920c5670b1d8bb608efc1b99abd261afb0a4ebe191605cc5c2e20523a13b3b94dd1fb24a27009d9a5b6329336f3516a327642386ba64c8769da1324a8a3d1f304cf0700df2b3e38215a954523e1d40ae96d0046e2929a815bf70785e94bc9b89246ab6aded60d65170eeb49b0ee0a57ee2e57db92409105c25f2d0c1a17b5556d06511bd0991a426258372c7f2b402dd533a75aa175524eb5d6b9575300b81fdb2258bd74429add8aa477bd1182db57107d411d16147defc3582861c68f5ce82e0a0316edd5d0f3cf36825a2c79a33e376cce2e63274b3b41bcbdd755845ad9ed2a3bdacb6fa3fa9484b7b60edeb1d9ef84772e78e39adca14c9fa0bb3ad1f1c17fb9449270e9b4c97b5b320839947fc73853fc58304ee9c9e86f3775f5469554d5006eb7ce9d02d5f900c771806c275ee7022e2b55d111338dd93ad51d14008df4c13d8c03fd9bb3689607e5cbdd499c3a372b487af74cb140f6300cd2dc2acda07277ea3dab57ecf09f1a8f2d6abf7c44fcdaa6dcb1f6e791164004b20b3b4c860f409c1483c7044b6fa445f7224606894e386ba08057a387b48920d4de203b1acc4dbe2b0b4cbdc3f7d7bbb097abbf81e01db09e120eab83def925a059cdb513efe6bc93f0579ebf75638df3c3d7f9eba3c36a169e9d88495c452888853640d93ee70f254f86e2d2d3fbb5e8883b36fbd2da105cf3a75cfe998068203186bb37f1d1ebead8ce1f9383b816f1da2fd0a9e01377b6ebfed4f05bec08b4ff9b90e385736fd13a3af7980c21b0dab58decea8e9545af5d0fb11bb51aeda2c8616960e8f6f84e6c2fc4f50d7e413afe030f75475509fbcf49cbe14445d267994fd3f38f41a1339f2895c0b2969a9bf9c59b85e629486c7bb5107c7a6b069793be7690f7a7c96c93b09a9d610594a156ab27a32d5557a5b1ec8920761cd2f559ad808dff3da64717ea5f10fba87b8ff2712ce322eb3c288939e0007f779a3920f45fdd533369f6f85a8cce21f91552fe03702ef81a926af0e402b418fbb25a6a3dad0ec18ec663126b3f48c341e2725abfeae865352d5ad275a9e3ca20393c64d118968023daac84bdc724a3c522d97a5878ed788cf8e44f80f8803d57584d8c8688cff24dd8c0e881b62d16ea30104d62007a4bec051da7fdc95d1df8556ebdf607383a0825ae503e24661ceb8ba773b793360c3f4ed3b761bd372570cb17e7c2030f07b0b45a7974e45ee6fcf5bd7ae9e9abde5421b42cff6af0c6eb7fc73f4deb67bb4e0b3dc9b4008da30c67071243cda649091a14b89bdacf2ae98dd230e932d9b277d6968c65e0006a8ff63f283f2cd9c21615dfd82e0b24af6ff559c97922a3d112ff0ef4af9d6583bec1f84d1aa8bbae705b9bcf458f5d93059b90fc2217ab27d0072a38aec3229d13266beb3015ac2389a06dec3120c6c04e540886091597919da293a4a8c0812d6cd336d5c5faeb64162ec0459e252d219bed78c4b6bb61c1213939bb3cca12a625ce5a45001d7408f6d40fa9466377caa43afe961b5c1602679220258fae72a8de2ac69c0dc97c90c270e306dbd8eb681ba9c092896b19a8d42665b94ff4d5b8b188f19f7c44abc8f88d4ad7b5df1cce3465de377072c70dd20dbd6779336f05ce328ad741d1e4606dce7065347df111c7d3282c8a3fa4a9458561c04d1056cd53ec5a8ddd6bd4434ac910c69cea0443fd09ee32d1256da44ab7896867a0c97fe4faa4a53b6db5cbfe3812a6667f04cd318f3da127a0dd46170cfbaadfcca863e0d4240ebec1cb2a5952881fe89804892d36dc5bd6484cc78db41bed868ed1b321a680a293bc29c420cffb5305d15fba05c76c2138b986f799b6a3d061658e498204c2b641f2f2ba73d633538eef6b5a01117951eedb7611742c120ff24261bea605e94d21e452ddb9ad27af08ed972b7d5e1eae010ec5d83e4505f6a2b7d9a0bb32a1fbba32a2a8c7823e736a69f516b781fb5354be4b0a67343c009a09b8f656c34ab895f9213531fdeee911d677d1cbc5e72c0fd1ad1f3b4b8bc735e14c3f75f1828ea28c90cda40e0cbdc40dec37031ff3d50305d5a8bba1d53d2f176895e53faa3067129a5c97505799967e55e4e9d87faf5920d71055009fd060ad06691b78583f63881b566d4a06b639c55796b23531ea79c6de24092c0e6fb4d3dc739f6d82ee3ee39f229de4c844aba36432d6119be0d2f02e5f72ef1d95fb2494522a7221e18e92cf22e00010ffd93b89fe60b6895a37fca91aa2fefa8debdae3147fe4f01a6adbfa0a59a5203516b2cc7de5faf821a2e72d43beafa30ac379791ad1e5da3286abecfc7a546b80191b7b892cdd01c25e95506471f5eb74568257439aea03300e80699909cc06db2fd607f3279651f7392f80bf4fc61d66f0dfed7b7db09744139d7374d3cdd18d153dede2a65f26130506acc51d5c721a7989485a145dac9565ef6d3cc938c5a51f31ccc88bb0739920ef8f0a01145f4ddccc74790a22a3099a4b57e31b3a01b4118c9e6c393c1304cc51ca1784db5633eb96ccdc88f8b732815b92c9072dbeb61a2cc1e6b2e7098d883e6174f5af7bd4f129389250926e041ba94d1ac543aab6525f151294060791fd26b668d09302c3482c78e5f3271c0150c437b4e78b1cff6f2b8660dc310965f2df14a1f2ad45cd2759433c4f3952402fefd79fff00dd309c3f09a58600223441c11693cdeeaf0a6100d38d612a759a8e01f753982803af30c7470f7bfd1ccf2c08aa0b187382d25868a9fdf729da10bb0aa0e1cd9c6e695eb2c80c6b6ce62737c3e655246edbce5b8f7ae21c473762db0969dc216a93d4db239f67dea74a1de21d50336793d1ae45e931d975bc706ea718a2ab10d66a59d9d23f76969d870ac279611246ed3aab0f79e11611b312624d78b88a9d1a49dc68d6968f7428c33f0a7a65675826422f7ac058101d2f85663de331345b3a25cf76b7c8fe0988a13278be9599b8e4708526b44a70bc31ac5c278ab739e3e6f0927b72507f34b0034e7fdf43364c466bb75b559e03d4d18c864714eb6061f83a6331b3f59dd62f39bfc2529d5cc68bb6ce63db1075105cbd7d7c4d4ab68c9e65a32092e34e76c3178382a965f49386bd4aae307128242a2ffe3022fd7dc1a824b330b9f032d55573c2f004a6905178a2479ba8a2d5b3140ed5f3e10d986265d8b4cf262295658f301b4d36281611d9c61624928da9abc51ff9a6eb481310511772fcb1c1786203d25295e4a319b9c6d65ccc966b4c5795e6e30b2b3ae8246c38b4a911d1904145de63dbd4470fac47f8ee3eeb3f58b5e665c26a316362382ccc6bf8db7699fa3334cb2ce61c746a7d3af24d8030df6759835f5890b7dd1de538cac1dfe843ad06eba2e887f08d9a49b39246fb26eff5cacc937d63c8d0136f7a8ed2af4cf473f3f0d9064f97fb4fe9938d631f7cea3c617c38771553eddd606ab80bf792f34b44111933796fe1fb8bb104223a4de9e16e17321ea7f8de3306e75a2bc79aa5e9c0ec8dde9b3dd1f2ae42a6a278410afa8fb62c16282f1e3dc1e2f8c28d4538a75b5da7645101253dd43aaa150b273f73e505d490490314606264c737bb344b616a80a4931825043a740ea4f75847e98cc99c6880d3085787903e54c63e90b60f03192234ab20cb41c70c6e82b00e0575a1bb0b0f435831c9ceb9dacd1fab8a7328eb3e28533d5bfbeace430e21758cac204631bf033752f947f78ac2bbd9423c2baf4dea22fcc65c96c332ece9abb20fed504643e82f3ba0fff213635910789a2fe1f2cedef68799fcf4a86d63ab0ccd395d6d4f393f7ee8905eb77df32d97592fb34ac86dcf20cbe5afbf9e9cff37bc34d75af046a09a1781cbf51ee2e0b0f40096d85413a30de974c4d1d16ec06c0fad00716c4e10f8dae46ef3cf27ccde74502b657d3dd26b5481d9787f5c6034083ff88807896da55fd2c951a28f15c8c9e6c86ab50c369e5ba4f6311de505c07c7b85573b5a539785820c672557cee4b58dcda948fb51c95674c23f1275b423ee5bf3a646df19bb5dfa22747857fb5c605669f334d116710bd9f1495e242bf47d6b607c1c9d9c706ee770808484ba552c978ef64daabb642a7caddf5a55facba474b8a63577ac817dc57e48ab072bc6a2cc5f5ae96edc45af41c896cecd8acfc36604db3b7fed9d2d17d429f94bd2542b194a3d3405f46c1021ecf6bb907fdfb4b53fe445d5adb18501aa772c9ba75619214384260306ab68a5ab59161b +Ciphertext = 66c03198b3422cf3fd8291080f6fb3ebd9ad863e41cdff169becde726946a342ffa0ee547a27bae28cc782d95a90b0a618f717e3beb577354bd91e00a7a57485588265ad2dd0ab946926fea7c754c42751ec7247ee84c17262c0ed092186ec57d6044f0ac9deb21da6714ec7452e441e687e138ff144ea95636286263685419afd35f002830765d810b6f60e8dee0e6879995e9272c798b067d5f99f49e460b86d67c641f48240b61a16dc7cc27b048e8b8e8e80016470ecd2fc4225e29bb127ab48dfe7e7d5a65542176dd7ad40c07ac8b92891d595bbd7afb63fb6f9e1c2aa2fc659aa101f9b6a5c346625acec86fccf17f0d45809f3b9ee81572e5627f1afeed4ba96c6d3ed7e9232358dec01a1231ae7b94ad4675239f3b456adccec439b3cdd45504c5475bbc77dfd242e5e9671d103ba71a4601a7322e0e295357f335fa8d5651d528dda66575d106308338993e615b1c5bd7e95bf3f755ff726b4ac6dd5a43ef061ac9783f8f2804c68f66486f5844969103a36278ee0d10798bf8a802d3fee3a31294bf00ee74f087749ab3325c027d42b55b197469a5312bdc5c9b316b20093154e66605941d58f4db8d46a815c06f209c1dce2363771b5a794dd8d17e93a2fa7b194c6a0b79793c06f002638e5e3052365221232cc4b30adf161cc6e7865cf02911e2ac9b0a75f000e7ef3aa4f3c7438433513da7246d421f208b179763651f18e22a793961e5976a74744696912f22915244fcfbefdc472baee0be1e591d6503f2d9511ee1eededd9f5547c95eb94de134d0c2186109935207a23b2b8420a5858d831ed78202be855cc6b98d6663c1c52e1a0022ed7ebe0eea6b107da4cf50c1c7fced9744a914a66d4604a081587ce4b7e0f96ed408b8a9a2964314b1334a123d5184889958e6467a6d16e7615e5364e09aab75994e2758345511113321a3436db79351c63a282095ec6b99b6d775a5c09ea3f3225716e39e14df260bdefb2ecfe9a65c73ab4b3712ec842e43ccdfb535e3685fa39b4912719e67bbe195e5f0fe6c3aaada2d81b669c4565921f6c183d708b50c3f7172ba841815e9351fe5fbfe2fb1fabeb7cec9bd1dcf2d6332372f1b972b5144aa7ed6c5a985132f9a54469097e2e981b9e75a7df48fa79d0736c6f8a201c7c7d0ac8ac6512a7089514bf58442dbae0529135a7f2455e0ee5716c6610bd7600b3159197bcb20ca055695a36597bf7d3b18ecd08031b4ce3a643951e231c7ad15481e32ed7a3edd2b379c8e96d3288d5b93b562972a04f1b7e0abcc5090cb8655422cf5e9dac0b49678138faec81c78f113255eaa6110e95406a7e7417a6e221a8ec7fb9d55643bd589ace2da70fcb41722e66e0efce932cd7a34218375b6dfa3df1747953b24a41f94e50b84bad4d130d5dab4194665338e06f102f46badc5dad7aa06edb01f8a31244dceebe5e2006d6ab4a31582ff46731b19071c08ad1db79ba018687f3e6afbe703b1de26c11bc8b62fd6b2fa3219fa7190379504820abc97ff6c034f7850e2c7fd335462725db6748fe45920c213c539356b691f22eb490faca24e99f0a044a9f727d0786566ad00635983692ef324bbf1f80c42b269e9d5a8df3249873c51521c81400c729ed7a5e73995928abe94d189cddf2774f1735bc2060bb2240e558699c365dee45fa68801e6a1745e03736ced1b89fc2755565e3b36c2102594d43c451122d94f4a263664bd26b2fb5bc7700319f6b08796864f92d0fdb41710910bbc13aa9cc7baac3b48a24e4f3573f315448c317c149ddb433d9ddd2a2f0cfc81c22d3dab31f184975355b41e4b36fd8f22e8efa01d61a5cbb0e4fcdd273cdf68ac73fee745faff44d44d93c5a111aefe4a5ca8e8e7c075ffdb738cc5b6466dff78ddd837c72c54941707b04d60bc126a3a2fae9540ec2e4672ae13de0d927a7bd363f8abb5a56364d6d564df90a46df9fd59e2c54d5bcb8280415257a6976d8fb24c33330af32600cd1559e0eb05d55b34be456d434bca98252fa531486ce2a24c8bdea1d57d93a550ec586920903a39ca61cbfbce79b8f3a5b1653794872b2c614458177e748f8dfd43840e5bb0d608c26389347673fd0b005f60f52c56731ee5faec6c8d0617fb53d5f2415c2e7906ea0e6d0066354b213b3e94f4dfc311e4ec6afa7e8d1c69a63cccf8326741456a5e0bd0a359b7a37c117f7892969ad7b70cba9bea0a975ada7cf67e0d7255be8d2c6e7b8788b9ff14c5d1449d6173e07b5f9d94560d46f474ab2a67056fe9f4a9fd617a617d23143adb4e7ea35f2d5cc1398fb9ed43ddcd10f28debb27eb13533110005e6c78ca4a874db68c65081ecb8bff1b64eb1e2d7b76a1da3b375dce8a92d32a6277ed847879345717b9649f27e846a701549311c7e69a96d61df616157a114bdf1663ad93a26c28e1a62ee4a7c72bccb9785639eaf1e569decf777bb0548ad9ee36788cfa1150eee3ca3c96f09052ba2300cfb7526b9424b6f7418c27a1e9bc13e4d9868e5c330c051c3885e44714bddf7cb090fbd0f36b826aacbe191dc8c35c219e19fe736198c29dc4fa1a98b5fb1805dc29ecd02f74d4510a3928448b5ee61b5991e46644850a4885bb1ee272883faf27962430de1922d0883e7e80215cf5fe7e8f3fd0e2a49bd50727af793cb7e5b40860e80a1fbb9d5b5696bdf2f741909ab5a713de47716332df6c4f78288edcd6ea130d895fdb2f29f94635bbf2061de55f1801bd6a24294aa199d78021a1ba771c651de4bc08f032fe6ad7a5caf6a6afc6de649b901f783a0ee0fea9b803beeb0f431400d0707f159d7dc29c0c334a918fa08a653137a4a8bc86066c8800e1d171f1dbddf1fab8a3eff6b5023da96f002e7e217e826fa378b15dc8a376db30228f5d6b629f331a162d63e53e5b5bd7ff9ec098b4314285908281930ff0a8aa86a6d89411e6b5bc6b9c9e931623ccca6741fd6d36311e6a8e323a37ad40b7a2797b84694e736d9c135e52d149c760e727598726378cd674b0f4df1c361de0a12a2b8232e611d789bfbea699e8e77b99f3449609caff3d6ef7233df8cfc624376c905eea46c6f77c0b01d288868a19db77e227dbb5bfea5cc3f49d219c7477f7f2b3447b0b8efe08eab8f69579d727555e547c13ec7ae13b83386f2adf634140c311b6e2759cfb9c8aca1c32bb7c002d0f46ecc526916589a29e328ded9679c2163838f071b5b85b35e5e7d99c3c45d25bb9d37d7bafb8350ad4695a6e0cb7ea7d93868c30bb54e301e21147696b7dda156226a5ef8c62121e6b2cad0c4e192116192012468eaad46bea69a140aa3cb9056dec87c911636a1e55695b9e5a27c63cd8c03f31570d4b7507d13731ea31f082b33c6db8dd6e22282f9790be41350a96abfc4dc3de78e0a698930f540dbda3fee923a463a4c4a66bf00bb2cdd6d22b62a47af96b78b1f0f0a174e4ec5b785b3820f47d3c8cc1691d4751ce4e4ab78a4551956158a36717dc35488e890d0631241906db565603205e054815aaaaf17945c3372dfc7193369871e2e88fb84c15a2b9071101e1208177fc18397e6af17b5843e1fa75392d8d3ed214975d50f2b19c24e83f010f8c394ec1edbb1cb912e61627d2760b0e630b986bba2ae113b8f3b51ba00ddc495520274a85e6f6fa7573ac4ec6e2a86a1da9199ceb007aa6f132e5ab8ab8fdca7c829f452ff17524fec475b8f485b29fc6f0d972eea4ce98e242b5d58f6ddc1b3a71256de1c584c9914a3cf1e469f0033165d934fae68a7559011dac7a4e0c72e3b398fab8f8cc2fb67963b0f9220f410e5ba13026a27288a1d49edfaa51e8f220503fb5ec476147cbea975994fffde3ddc51bb189c470078978d238f5287fb2629d23989875d74b006a4122f6a342c996d4a244e8c5e4b804a44c301ac4d6054181a07964b279e0a44c158364395a2ead40053d2f3350ea0529a57552ed835513f533ee0c4b94ef674f31851616a4fa2d0302d13cd4aabf5f96ce28219c0b5bc0e5410fe0fa387ba1009a6f2280f9e7bbe20c33be5eb411a5f6327714b3443b4152cbc54c4012473237dd98b0490fc4228ded74afc81be2a58a22e03ca987faef5310e474f4f5a183f6b7ebede5a8df8a0f94a87a41852826b29466fd761f40b416ad0f263dd34e5497867766a361af1654c3fcd6ee7e6bb3f72d64cc980f04305b63bd574f116d1aa35b4bd642cab0cde6a29139aaa163805c6c40384313d4ec6027c891023083988c1b0d2edbdd9b1afe102fbda285a6f897efff72a0d7fc19a3cb6756cfaa2371e13be3cd167cddb90d525cba7da69608b9995cef92a6424a14df6b860ef0f09830fd7189497a432347680de0f463c0aff82df8098cc4f7753f7680c8c7374d01046b05c63be73f3a1623be778fdb0bdb90d4fb4b458af2890d15f108b0927304c91c8d62cb148c35cc93797db3ef9bba1014d89859a91da0c0a971f330600d71565d30e9c9ea8c07e7f629e1a6d578da04d37e597261cae8ab7d9a952bbf71573f1bf70e064f36c032cc624e3c980e5ea46d36232d61a57fa598347b7fb6b28401e34628b051d6ca3dea190d1d3c343fcc83175f70f77a8fc5e8791b9788989df1e37cc4881648f4fc673772003079adae55c83cf02a894b98561e4a6e4416bea3df18d6f702ad5c4f40faedec6b53cfdb5b3a52d7d43b97ee23ccfa2d30c7264ec555b15f1d9e7e19cd9890a7e8e01ff21d3b8b451e50932f189a420d18e7c7e2f103332c78c84600e5e8fdedd84f055a8b39be9a52782d47c6205c0de41644b09c0931f2da269a7e58e669f3b61ebda28ab8e3f9b83ff3d2bce37864af494860b2f01b000abeb737fbeaf8f9fa6378366606dcd0fc33031b94f9a7a0e562c08ea720a671ff92520047f69b138b4e032c3828874ec4c29e49aab302089956566372b20c0216b601c3958ed9691bbd89f1df45c6613d469e3b9758a70c860fddf768b10a6bf70237a454a2c0b70dd5d02da612a91fc5731513012a4a6fbc16d01550bdfdccaeca22bba104ccf6aeb19f21d4cdd3da231af8ec5bf2a726ee9cc7c85b8ed46d2f6fa4f1b010b2561fb69690d5a9df76d729450a6e139962bdaa2bec0254c5a252b97e7ce7eab1817f454c6121130952b8c40628065dc9b77b0f953552f5aa3ff983b6a51a51dd87c2b51a18e14adb8c80e002d0b47c61cb357babbbe3ed51d371941a8f111837ecf0e45020cb941de170c4a1b5e61bb928b1b11a8d902febd2ba016771f171b8a7ae825fcc4642d95649d53675d0027822e4ff79ffd302bfab1a0ff26f3648c7ab00c10f8d95f21e40ca2b40691bd4be79bb9ccc0bf760a05be4728bbc0a64e585207d1d09393a80d5f574442d6a933966777ab05f699c4e84aabbf753059287e7261d972745906a4fd8967bfc80ae9b6ec2ee1b22a81775f4f24999987365ae2dfb6739902ed51b9a4394fdf29f216c34567102d9db301661b09b728a79e377cf4bdfcf5c83b110a2e267abf6d40947e643ae2ff0c244af168c9f33e7685474ac30611ef95f218e0dd280899a92a41e7a759d03ce3709c2a140ebd35e199f1dbb96f7351cbe1f3de8da8c49758a49b9e724ebd3220ed6f51112944f70c0d1e9178f68a2c9476a913de00abbd1f5bcffa646f926da77a9e9fbdf81cdeaf7f9b13e843afefbca81c93614f8f1675325965b5836b8a77620a5ff162e25366718d8da7781e1a7e01fe2e9e56cf958c6273473abf5c2c8c7fb209307544e1c0726d5571e521621b18b6da3064b473423536b1b76ed75b21b4ee205d7ab5f081bada63062706bd155672dccf84614210d72660095437c6bc2213d9c904a4ba1bfda14d350fa3dce7141e817a50859b1a74aa64560b2ebc67add9f945b6e85577589817078c8ae54a9fc311593d2cbdb6692b089ee6264cebcc7719753f80e30dbe48b64fcfd1037fb9ddab69a5ff9e5898bd8aa947d9ad827c26df67c6786edcacb3478a20bded1ad8c48018ae0d439bb5afad5d39bb8fbaf22d72ffd759c4fa2e94a5a89f41358ebdc4c3aea5110f1965a049fdadff9cf703eabe9628e2680fa4e70320d304ecaed13f513f27220db1916ca1500f1c2e091671fb71329dec0bd6e310c83e67af61b8ab60ee1a8d559a508d174648b1bca451ef0ab0ee2ef74f4fcfaad1cc5ea6cadb8f1bffcb1f2c05122011ebbf6abc16838e452fc47653821589da4cb5bbac10deeea3ba0e0a6241338e64cc78d7a923d018e8b5b51c4442070e5b0e6f1e8c2b83791e930899c5897a602c401c1b85827962ff56d19c06f5af033059bc7fb1bd29b65f66aa5b4397834e846935e523b16438a42c1f990ebe4f83182163ca5fc60a4c6d77fc182e81fcda943a962e9e7f00f6399728b48bbe38d8178fae3582c8d9998e49df5f28e32d541636df3cdc8ac00df45db12da2e5e76f366c1ea8667ba5f3542d21f58ead7c55d06a4b35251b8f77dd34d3de262947379107a06d2f4891ffa0ad3a3e5bb2bbbb978af4953310d4cbe5525ab344ebb98ed24d003600de8f3af36ff3d0a7efeada963845d573685bec2221403b994f97b1e714fd7dccc300b62c2a516e9c6780983062eddde0178e93fcbb2ed4f06f60767356a11d22ca37078fda1ddb3cb907d1020f62ba85d09044574ba28aa3df36988eb8a41e4305e5b0687abe43a90e4f68f0374b6b05049aff5b065d7688cbbfb0e96ab03df38903bfa1c269f43a114085eb4596aec87ced88701b42f0b7426389727308bf10aee9d8f15ebdc411ce1e764a290a12faa2d7c1126dc7b5076f219b826ac8d380b69af7f95d69fc3929a97f5c7da1db6270e9ee1f2a5f7fa3a1b6bfcca00463655121f681d3a627d03efdf0b5fd045fb153bc4488a9a8b7264373c710ebfdb1c267fdca37723b21d5c3eaef48e784bd76e27c133cbc24d114f610c79f2a1f2c30d87ddba395887030b65097ca5566eb0361e70615b46d4b86c2759f1cc2efa3915b4cebdf51a745fb3c6cec69a1fda2ec5e884dce228e30af362815d2d8b59a14f89606bc77439042109369a9648db7d71024ed6df06c8ebd22e8623f48feea77f48b5e88827fafa84b0564151a5997b7f29c4d3d18068e34f2690a293d54003d0ea8f3bab9387ca72212cedb5f4602ad047dbffae2ab3a4cd2865bf896cd96f78b90e4017eb7e3c7092320c0a37f81dd65a5c4817a4e7053e6d2bcb23b11e09f681587f3a9361e974ad54b88c72c296629b1ab754d25be15e87c414cff975fafb3d7cb68167b21f1889685a48966705222b525fa47143b00041df94817c275d93c2550fdd82471cb3cc1b5644338060b767e807bca902c180b3e535c77be2651b3962287b6d1f6403033de4e0aa3a20615ab59d290f4b167325959c1524ef216dda2ffce86b50cb6b56b62a20a043d9d78c704479c22340151df5a1907670f8d4f8c90d93f7b5d94d04a4d383914867aa3c0e5ac85fc299a4d2801a3f80f4b0f046fb62c1c8c539a83b21c7549df0afe200537b52c80ebdbad8a438e430cf876cbbfee9ceb1bc5270577c27d53b40ac153cab377a565b1a9fbdee8bf8e94839c0fc04f7f664383bc90d56ccd1cc01b465c250b158b5e6f321c20db245602d10aab80c553d52f17282b095b5e2234c6c689a84b096112100359816cef7e92029fdfc048058f847cd2f2369ceec9fd171a0487bd7acfed6b0319832df6d59affbfd460ce8d12e4171da0f094e872a2888fe74925c5ef0621c4edad337f7006086748913b24d4d48ce36e662fefbe672b6d476456b1fbac6d80030ab93da93acb4a7e10f955547e7e20a0abcdbf909f05a2ee2e0b7485fa16be652b9d9fbfbf01f082488a81022bdb69af9e6fbe753e9eb92a1762afbb4df49f83ffc0cf03db563aa96fc5ba1af6d4d7eede6067749e8ecec79b63e09742e29e99e1c960dfb0688b0222c49ed919379ac66e3fa1c72645122d1664721e78fefdd1224c0b886f6e214e37d268ca9acab76ab3adc9f5549e5dcdbb3d31ac34ac472894d004eed71f88ca2377fcfa48d3ae43805dc612891dadd06c263ed8617194f890bcbb964f010d277ddce1f6682e661577ecd51a4d5421f00935a5b24fef0ea1809fa5c4fe9cf8c453046f61136ec8872915d2462157d73a205d56d77bb83cf16b88cadf6430c0e5397fae1f91a6a11b177bf04b065a2e55df81d5c086ec8dc8a0a660eed37d41fe4d8b3e3f22238e2a63b6e4feee1fe9a140ed37b2be4193f75c2d038aac7f6b7dad2a3b37e5b9b660615ec1db77a9b7ab416f43e66c872b71cb67c9245c757dc87723ab3b9544fdd8a16c9486e8ec3c4a44cefd98535d6e5683426c1cc8c888b8e0c2e7528bd7eb89b80d9e00969efd2f0a0fb09845426edf0d1d9a0809648e7e46ea0a8c9988bf9df475be12a72c7326c1f2bf01afafb190cf6f649133c7dc14ecf9b8c971135bd303c8894bac637e08257d45e1b68edf550d896c41682c002396e8f1eb7c1e2f4e0ed9b8b7010fc7847e6fb1c5907c17b2d2b7cd24c96f47406bd04cfcb2099d82dc2902d6f91e2f8f3a05bc62019af536309e7847fc06c10dbf7272a1509079fd16bb16a85ae2e078f97f9ce66bba66d6329c7ee70f9688f6d91aa38b25c7f4884658a72ad8cbf96d7d7a9652673273ee1b3d4d17780dfe9ca865416e318bdcbe9efd8e071fcb15ceb0743df5af4f7d598b31e38677e65af61c1109fdbb11fb11e3952e6c3ae8abc3f894ccdf205ae55dafce1dd05dca6b899877f57d712223dde4e7fdec7e0ed4f0a29ad359e318eb36ddb42fb205adca400f5b2615947c4f0ede95788093a1152d88acbbbb272750823151e245354e658452a95f21fef05bbfd98a10c1c975ad1a08c59fa3efa9fc73588407a83d0b26a53f1b4115f83780bc70ee2619d7374ca45b9e200055df1b93977e17aca89a009110a6e74caec7f86114f91975bc6e8bcdc7267ed2920cf12cd7137840628e1b8a0ea181dfef18dc5f74e752f842ea91bdce4b420ee709bca72c4514e92bcff55902e5529d77fd95f5837c8f4fffce80c813630550a0dde24092a25f65eba90790a06f4d4c3e739aaa8194a147fb32e81c71d3e8def79251c33637661b0a621a2a6b302dea00d34a9dbe9b621c1dabd0464e85241aa6712d90b4287cb23c17bf1e4d0e6dbed372e6b49c4a843305b3b0e5cab0b0964a93ad0bbc99ee711afa7f2d0a296a375fdb3176c65a957ddd9b88e9d57df736acdeb02a71b924cc2e972f51ba68a597215678573bede9ca5b3a0a2461b2d3b9ea57a5af8c91d40779bf917ded32f14a66d96e28e1415fea1e9306654c6b84d8a64243a5271c1f11590423c718961aecf5f659b49f67efa78e02ef2524d0966ebcc446d73d49ab7ec31f0c009069d14ccd63f926169291b83a3e37610054b0b964741e2ed8771d20bfa225eac0280b4d5af0c09d3218bd497a035536f5af0816884d606f1a872b8161a266466b56e0be8b80a7bde65ac706eea8cacf1749e5e71ff9fa3e69ce878427a0728d44e666eff977026abfe18cf3ad156a943b917e72ad65725a9a8d60b7b5740494fa63143a7f2a94fe6d8b319be55d6fe1a988244deb798f345f30dcafdb6af9e9cee9e35733274bdf3896750897371563ed2516c4ca6c3c3c994b48cc94b67e8129d234a0e19dabe39e500214c0ed5f0e5d61b2f58d7355d147102d93b2689bc5185dd4c0a18efd11a307b887d4d0fa84fd992731b3a80dbd027dd36cd6933766c537e8e9e27d35d5187e8276b0f59fbe7b6d629d3416b782e7981d85e1e890853c3aa94a93c1667a55044ae42badefab979fe7d525c6a180307c5ee3a9c3933038028c3e1d15d1e78fbf53b6ea61ac5e02db0161719398a31570c55f73cb47ddec8f99e3e14af5adb8d5cd179f4204d080331e75bd391b19d38eb81f148c36af3e8a3ebe76209bb75c9741a89b5d0708bb0fbb0945fc6fcd6ce142d19faf0947c338dbc8d976963281866b5216421c00cbd77c0907d1e16f5e925319cf6c62f8c6e8eff0c2f831c504e7a1c0df09a54e2af708ceef39ed7d0f63d83429e9b0920c03cf85c2244f2fbac3958847113bed577dbde8992cd91be5833c75faedd5e2005d4f7b66fab8fa9305927406f863d1795dfe04028940b765bd79de6972dc7094fe1c2503a73d7b50208835216c23aab3e47094587549fdd74bb50ae21cd1354daab632fd0907e63f4c2b2d39d7fdc4fc216bfa742b4608238623cb7fa01bd851c1e7ad5ef5215173a71f363fbb7dae8092486f4a1549e32ae53b14c1343ff7fb5e2b1487d9c594a1b56e22625d275e41535534d225b7b2c9deeb0d30dba7188cf75d680d4545ed05044a0661c690a37fa14a73ba8c68357e2c948e290b5d9a4b51822824614ef2938d19ea4b650041f59f3b548f0a305b86f55e69760f37f09dfdad62651aa5fd84eef28a4431136b34a49c9bf1f2891364f86b0aae70b0414e821e3db1533b0f1db5fd232308bf118f858aab5ae974c10583f61b283a3870eb82aaa8ea3c4e2ee3c3a3d7169aa8e975ddee7f620f6c5bcf3eaaef0101b62cd54495cb8809052c9e3151690cff7c1efcc4f63b22472111a7c5d9d7d2a2be951510f60dec8c426f14700c8630f8a14dfd359addf5d9b7ae031a745ecb4e17321b385799c90f924c4780287ac187530a40b064064b9036cc46e3f87c4d23aeeed1bc22a5411c7c503594d5d1261eb9fc4da242493beee9f671485a978a32e965faf9b0e2c13f78e31e1630b72d35b4be691e90b3798e18223c1b514b39a8e1eeb7897c22fdee1e33fc76e2b2f9298ad4fd89f44163aaab23d754d98c7890e58708b81b3832aee31aeca85e76416133710aeba0e5d9f17695e607d09ae3f94be191553bc39c6df03cefb4ee05516fc02d66c9866e4eb0d89a662e309379a347159db2e070abceee226f2b8b62847ef7c51d69c5f12eb567fa13af4b4f90b3f3d9d4b6a3f68bc4dd77075081e2e99833c18b154d0d6ac360141de2a25af61d551f10a34e03e1419a37409b4c177c51a8d248157b411868eb607c34d2daaa453a0954fade5eac45d5f21f50efba8bbc9c87ff0435c70f064b42cb2d158384fe0a4d9c90030ace7723af0a6c8faecd8f97f9850e2a489a94ebcc655301e2e14711de9eb08726638a9ddb57160c5545c152a26860a17dd18172bfac138a300f60431fc49eff18c93f71400e887f878f4dd637cf5df8c1e2b12c0f87e31ba2754ac1748479eda0c4184b528554106128320dcce349939e5e6cd3434f86dc7adfee28c008a21ddf9d0dbc87ceb14cc3afbef1e06fb3f9908a4b14f5e6c43b23ba783b75a6cbfa2ebac6533661b8c1143a34e8e2a9723389c4b7087dc07701c53b169894551084aedbb423bcce2f470881fdc7240c26b3b76fd6cfeebf8eb2828b4741e5e8698b19fa0a44703cb4e4c8ed6a7e4d6063f5fab724e08a159f4f04a2f351dcfb6335ae6697dbeca25c76b55e6ec9045eaaa8706902df492b8c8cfbf68c4cc1be5d1e5a173262e38bde051656ea85ffe35d97f1b25f6a47381bc327a946f7cbf6210adfd957b2921 +AAD = 85ddde4720659e80e25168585a354eb1e021c0b5d2ee289f2314dd5aae52bdf1fd44755bb56a6e659111a1d4b4da73315bde01c7d2c15a4f7114aefd68c141049fac27acfdca24e65c51fb1c27d307cd948e13af2963166bbc9411401d124f1ddf20f890db5611385257f52aa05c09b467e3ae886decf5744ec3749e5879f2a60017f601bbee11a66604d5f3d521d2c48cea1794f77366f29c7bd12a8aa51d34a4f3fb52809561b527016bc6badf9d136156c330e1d69d1aab98c7caa9cb46e782a898b4c66e4ee3e2445fbfacaadf9a8f73c4cbcb2a1ceb604ba5637b51337fcbe0fc366da98e805ceeb29feaf05420113b16e1005079c0e88af33f5970b3d7a8b51d0d9f5120a0795063db508171b75ed07705ac6d6bfe4ecc59243091d48865536515e036860affa880bfc91aae2fd1700de15994792aefc4a176e5d49d0f9135c7d670f3cb8798bfbe83fe73de7427e0f3e6a2df561cfa15ffe6ae80d5016096c8875b0beac8cee8fb530fb421b9a8ada4d551a528d0a0b521086f5a2db371a3bf12a2ef861f831fcb44cb2baede907a9306d3e5a3af796e0a50ba2c8dd61fb03727df5f0654d837dabee2fd90eecb7b2e8f303b0d57f97dc6a52d8281574d8457c89c6a9f5d80e0bd86c90ed39b1db4253affee614e8cf1ff05166c66e7d2a2aa2fe8a81c4741339683debe189c126e7f553a5f2dc16fc16672f74aebf94c7e3041c758fbc6d0c7f71c192cfd0fb2ec52d0a0705b05815d567f3d19f9b5d553a2adce9a79159b0e38980851bf64e97f896c028a6df8363cf1f13f4654265a7b0c0b24198efcf4418c32772bafd3980dbc689fab12e85b3ef4a491e2e5ffaa2fadaaf3deb392105a42380797d3b41ef61303a6016b269ec9a9f6e3f26070ff33cb467435ecb325dc7e18728a5c2e882e720c8f876fef10f5bffd5a925cdc9689d934272019e90e3a3bbf63a295f207faa5c014e1517c7d5c18c3ed70e92304d51944dcd3604c999d4aa8d8dbf2a4c69cbbc08635c968a20dcb80f438d43c57851c4cafec0b9568dd6c19932fd3f1294afd16f019f20e40ec87f6f5dffc7717470614b2de6e9000969e6b7e561cf91c06dd379a09c6c25c7841330dc78fc5be1d9b86581a81f55c0289531128638441fc98a1ad9472d74e2be2f874aff2fcf9c941502f59f716185a4c39289ca368c6dbf5257b5dc5e57a420792c26e602e4ecbc4f17c8787004eb88ea091d6b6ddc3c85dc110b5d1f46f6e1d872723176f4c73664ecb4219258fedce19ae22360354fa4894fe51d69434c2e58e1ec665b5cc33bb295053c591b474b6ae178c8834667bef971604279440170ebf3e739a4ff19704e5886767f81edce95a3dd93d1147995e7eb6c794b7be136658ed23cec7c374705ec0d8479dfb44cc7213076668e5fbe6a508537a9157815c6e5187b89f +Tag = 469e3ef168a64945f76d7a2013f27b68 + +Cipher = AES-256-GCM +Key = 0000000000000000000000000000000000000000000000000000000000000000 +IV = 000000000000000000000000 +Plaintext = +Ciphertext = +AAD = +Tag = 530f8afbc74536b9a963b4f1c4cb738b + +Cipher = AES-256-GCM +Key = 0000000000000000000000000000000000000000000000000000000000000000 +IV = 000000000000000000000000 +Plaintext = 00000000000000000000000000000000 +Ciphertext = cea7403d4d606b6e074ec5d3baf39d18 +AAD = +Tag = d0d1c8a799996bf0265b98b5d48ab919 + +Cipher = AES-256-GCM +Key = feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308 +IV = cafebabefacedbaddecaf888 +Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255 +Ciphertext = 522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad +AAD = +Tag = b094dac5d93471bdec1a502270e3cc6c + +Cipher = AES-256-GCM +Key = feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308 +IV = cafebabefacedbaddecaf888 +Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 +Ciphertext = 522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662 +AAD = feedfacedeadbeeffeedfacedeadbeefabaddad2 +Tag = 76fc6ece0f4e1768cddf8853bb2d551b + +Cipher = AES-256-GCM +Key = feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308 +IV = cafebabefacedbad +Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 +Ciphertext = c3762df1ca787d32ae47c13bf19844cbaf1ae14d0b976afac52ff7d79bba9de0feb582d33934a4f0954cc2363bc73f7862ac430e64abe499f47c9b1f +AAD = feedfacedeadbeeffeedfacedeadbeefabaddad2 +Tag = 3a337dbf46a792c45e454913fe2ea8f2 + +Cipher = AES-256-GCM +Key = feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308 +IV = 9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b +Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 +Ciphertext = 5a8def2f0c9e53f1f75d7853659e2a20eeb2b22aafde6419a058ab4f6f746bf40fc0c3b780f244452da3ebf1c5d82cdea2418997200ef82e44ae7e3f +AAD = feedfacedeadbeeffeedfacedeadbeefabaddad2 +Tag = a44a8266ee1c8eb0c8b5d4cf5ae9f19a + +# local add-ons, primarily streaming ghash tests +# 128 bytes aad +Cipher = AES-128-GCM +Key = 00000000000000000000000000000000 +IV = 000000000000000000000000 +Plaintext = +Ciphertext = +AAD = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad +Tag = 5fea793a2d6f974d37e68e0cb8ff9492 + +# 48 bytes plaintext +Cipher = AES-128-GCM +Key = 00000000000000000000000000000000 +IV = 000000000000000000000000 +Plaintext = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Ciphertext = 0388dace60b6a392f328c2b971b2fe78f795aaab494b5923f7fd89ff948bc1e0200211214e7394da2089b6acd093abe0 +AAD = +Tag = 9dd0a376b08e40eb00c35f29f9ea61a4 + +# 80 bytes plaintext +Cipher = AES-128-GCM +Key = 00000000000000000000000000000000 +IV = 000000000000000000000000 +Plaintext = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Ciphertext = 0388dace60b6a392f328c2b971b2fe78f795aaab494b5923f7fd89ff948bc1e0200211214e7394da2089b6acd093abe0c94da219118e297d7b7ebcbcc9c388f28ade7d85a8ee35616f7124a9d5270291 +AAD = +Tag = 98885a3a22bd4742fe7b72172193b163 + +# 128 bytes plaintext +Cipher = AES-128-GCM +Key = 00000000000000000000000000000000 +IV = 000000000000000000000000 +Plaintext = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Ciphertext = 0388dace60b6a392f328c2b971b2fe78f795aaab494b5923f7fd89ff948bc1e0200211214e7394da2089b6acd093abe0c94da219118e297d7b7ebcbcc9c388f28ade7d85a8ee35616f7124a9d527029195b84d1b96c690ff2f2de30bf2ec89e00253786e126504f0dab90c48a30321de3345e6b0461e7c9e6c6b7afedde83f40 +AAD = +Tag = cac45f60e31efd3b5a43b98a22ce1aa1 + +# 192 bytes plaintext, iv is chosen so that initial counter LSB is 0xFF +Cipher = AES-128-GCM +Key = 00000000000000000000000000000000 +IV = ffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Ciphertext = 56b3373ca9ef6e4a2b64fe1e9a17b61425f10d47a75a5fce13efc6bc784af24f4141bdd48cf7c770887afd573cca5418a9aeffcd7c5ceddfc6a78397b9a85b499da558257267caab2ad0b23ca476a53cb17fb41c4b8b475cb4f3f7165094c229c9e8c4dc0a2a5ff1903e501511221376a1cdb8364c5061a20cae74bc4acd76ceb0abc9fd3217ef9f8c90be402ddf6d8697f4f880dff15bfb7a6b28241ec8fe183c2d59e3f9dfff653c7126f0acb9e64211f42bae12af462b1070bef1ab5e3606 +AAD = +Tag = 566f8ef683078bfdeeffa869d751a017 + +# 288 bytes plaintext, iv is chosen so that initial counter LSB is 0xFF +Cipher = AES-128-GCM +Key = 00000000000000000000000000000000 +IV = ffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Ciphertext = 56b3373ca9ef6e4a2b64fe1e9a17b61425f10d47a75a5fce13efc6bc784af24f4141bdd48cf7c770887afd573cca5418a9aeffcd7c5ceddfc6a78397b9a85b499da558257267caab2ad0b23ca476a53cb17fb41c4b8b475cb4f3f7165094c229c9e8c4dc0a2a5ff1903e501511221376a1cdb8364c5061a20cae74bc4acd76ceb0abc9fd3217ef9f8c90be402ddf6d8697f4f880dff15bfb7a6b28241ec8fe183c2d59e3f9dfff653c7126f0acb9e64211f42bae12af462b1070bef1ab5e3606872ca10dee15b3249b1a1b958f23134c4bccb7d03200bce420a2f8eb66dcf3644d1423c1b5699003c13ecef4bf38a3b60eedc34033bac1902783dc6d89e2e774188a439c7ebcc0672dbda4ddcfb2794613b0be41315ef778708a70ee7d75165c +AAD = +Tag = 8b307f6b33286d0ab026a9ed3fe1e85f + +# 80 bytes plaintext, submitted by Intel +Cipher = AES-128-GCM +Key = 843ffcf5d2b72694d19ed01d01249412 +IV = dbcca32ebf9b804617c3aa9e +Plaintext = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f +Ciphertext = 6268c6fa2a80b2d137467f092f657ac04d89be2beaa623d61b5a868c8f03ff95d3dcee23ad2f1ab3a6c80eaf4b140eb05de3457f0fbc111a6b43d0763aa422a3013cf1dc37fe417d1fbfc449b75d4cc5 +AAD = 00000000000000000000000000000000101112131415161718191a1b1c1d1e1f +Tag = 3b629ccfbc1119b7319e1dce2cd6fd6d + +Cipher = AES-128-GCM +Key = 31323334353637383930313233343536 +IV = 31323334353637383930313233343536 +Plaintext = 48656c6c6f2c20576f726c64 +Ciphertext = cec189d0e8419b90fb16d555 +Tag = 32893832a8d609224d77c2e56a922282 +AAD = + +Cipher = AES-256-GCM +Key = 53a6f0d9b8a81818f2fd7525acd65acbaac82684cda4fd357b1ceb6146b31ee4 +IV = 05d8a92b5a510c3a3dacbbc0 +Plaintext = ac0ae17d3d0ee5935e18675c36d9e43967f6da38dddec14c7ec574ff8473e11ae5019e638232323c175b7672a7462df6709f5014bbe12a1370a1ffb570177927106f995dc8f35bd6e6228de7c16acb71e583c87477dcc7b17a908ce01543496c2cab8a14a21c43b18fab52d8a882dd1d999b4275db34c7f32bcba624d128580d7566a2da4bcfcc4136d58816c437d21e90456fc86381b946b8955f0448e83564165a629cb2edb978e5941010ee9153b054ee429b315058334ad7899aacedbc0bf423de69f57c633b56033c6531dde29258694045c46a797987471ae6af8fee8ad0c1be4149605064aaebafd1c5592e61beca9b5c7771410a276c3ae517490735ddd6af499ff705b9fa68d50650e60c19f5ae2c88dbb6d612afc7be28a5f55556a2163b6f66609f7d9ba7e97c074ea39a618727421fbfbb6453ffeefa643decf11404764515d28fce8ba66b8c85d077c47a54125a38bcb6b0adf6d248ba0a9ea129c887c66ef537c45e9fd3c17ce352e3936cf139e13a5946a7dc9dcb6423ca6a051bf560cfc572ef366940e71c81aa302cb9701f9a5206e9eacfe9835bdacb6425d058022a27fe73e5edeeba98c7a3edb761578ab2ad5a442c2dc1cb3c143c6f18dbe525fedd2a9cee0ada3b2c116465c5cca9a7e5d4374b29aa4ad8adaff8d6b0d1ac3990685240ce022faaa07241f9ff445566b9e0463350792cadcafd5fdf5c37706c0025b3c627185b356d39dcb2244b15566e6e3f8942f730fd6d855daa1456fe294f9156c4b5131e5bde7f2d938ceb6c7f5deb0f847a98b7fd11a3f5d0163eef9bbeb83cfc96dd8eedd447901ff4d3a35c0ea1f691b01385eb39fd265f756bbd77bb61b1741db0502947b4b985382a08a5916da809a8afd3fb1d78d9e16f8e37f51aba100d031d9da8613e9cd2cc621025b47150b3e76775ab23412d74334bcd79746cf601407481310a923047ac68a4e6a7f7b96bcd85bb6f24e38f03c80ad41a0a581b4246ea4715ee561cdc5384a51a6fc9ed8569ba6b12bcd95e6202ecf834dd9062ec539cc8cc4ed64ab9ff85998da0e63161e7391b14de47dfde41523b6c614618bf2fd1edd68a5de1c03c4181569b6c361d955c637abbf4efdb5dbf2f0dd2544329c44b77081a48f53231fa9d4cf6f2186427e469d0cfbcd698f7e7cf773240dd2b807a2fe699f0ceb4a2339e9cde01114b2aa5c3591a82a3a27b308e1e7f092af8ad97bbe7b28d78ecd80c0c0a28372193d66bdbadc0b58e4d5408acace53bd5e12101fcb25754f8c545340fbbd1328287044a29d18f40a24b4084febebe228b67cefd970df6d44ffdc033a50534e5977bda660c589c6e3c3a28b4c500b29ff4a1c3eaefb068784a29914ecab7868a43999833b0b37ae79afe58875a0425262e0ec7e10ee8a6bc1c97d332bc2a6195de239a166486a3c1ad8de3a026e5b1757f9a778a511024a260c9809ae3b22d78f18ac483281a796b1ccbfe7a9b9f357d12d340e20bdf2037e8bb91ef858cdf2eb9d7161a756d8c244c55524f8f5be2e4f18641bc4c2409c14816846c4655be716276d8356e516640da49e8412fcfc7ac0e084a079129b23e54952d8030e1f8ceaafcd322dfb4bd189bb5d940ac83231de0585783387d0642a245183f7a251779bdb12c63e9edbf3d0c94281140598fea9e73e951ce650c984cfb1398f8813abf8f8827af5eb64a65dfd1305bccc45086438ac439a9265790fb225c509ce3c9d39e25d2276d7f3c06d7cc28d33b2c21bb38b50dca5b10afc09da83ba12ee878e0f6054e8d3e78d731671de4f9d5a7b97298b01f37c7e78e5fcf5188554bcf5d42559d3b15153bb3cd5a0d1cc4a96d02ae8b1b115d1ff617b6ad894ce0585f46a2a5f4cc1b83065c1d7b5d2f25f3f4bf9966b4c7d7156931861d5edd199c126f1ee4ff6345023419d0a4c87f3388fcfbecbb6c1e2f4745922b88085d21d4551e4c127eb423db87a51c9f9a140f8a7415dbd70c4b0173e687a40f895404f2203e14ccd61e0e5b0d5aa3fbd1c8affb5807d787d840916ece24c56c50d3d9ed9f19d73f2c80c461b5b3c07dedcdb41402c3826a958d74be48382dc741dcf3e0eb8955397da33941fc47288147736d778914a57effbafccd4cf293e6ed1c7d19b55433bc0363e41546b3638a4c630eb35dc6a074f90185cb9daaa6eab54825a4daf76f49ad918e90e5777a826d6d5d52f32f7ceaf818f87251ab4d1b5406ae94e41cc97fe022b144f26335829d9c81725b3daead621a0df71313d18214ff8dc687a7ab86b8eec3070ee1ca9f62005a0cc15ca6e2f4fd893de8fd91f6210f6c96a576024678535c962a2dab06f56be377dfa74bca089adb7327abd05c3ad7646b5e9e6fc2f29916b34c8642f3c0caedb53b8f30c2a77d1757103b7ed156cdc703911366b02cde87ce7343886987f7a8c028921a7b87c5c0aca7ada34970a6d0d32eb1b177ed8e64c1fc6839b9d08acec19560bf4a815ca6187635f0cabb8bf062e8216d3b09b7abd99e956734129e16a7c4f3beb850fe2b1548729355f9015c9bba336d3e26a27b3d75d75722f7a8170d15ebf77f325c97778a5a9d7c76d3e101eeae354e54e6fa60b58cbdd900751854ede326b58fa5caca073c630f3719d6f52afe675f10d464e8b58e5fde75a4f225063ca48d76efd1b645e4bc89d98215beae765601f635a3bc8cfc08d74722f3d95ccb4cb4e3ea977d0c534a4abb866fb9a31771222cfd998231c30bd16b6844ef71038b67d72c910cca40db7260dff0b74162449a9e2cf15d7dfbfb3a685080e6c83ff4341c95819c0317502ed49af7ae688b52c9866518f74d69b4144500ab9d5a0829b9287d5fb67b78801119ddae7a76e80be8c4dbcec7866ffa7d081406e51cf617be061530b539cca7e1ef9118cc06e8eb2a01425b45947a1d2332e360acd0654bba8f1fa43ece68467690d36f6802a32f03f9ea056e57fd548dd4a3225ad5006c6c931aef1990639498dc88a23895ff1f75520a8009dbde4debc20ecc546e378eb7ed5ea3740d2244036588471d96e4751390b6b76b39816d853944cb5677b493b36de9736ba0fa404ad4b3a7d7c54d0c15072c040064b871401b25b88559d059a9519c7e2446b0d110a4aba9c12555e5f620680d1fea2359bc85cd15b5c0bfd6b3715d647514118cd60483dbc9c83e285192108f4ea6bcbee1f0935044610c68d052ccaba23258d09465d5521e2664d59358621ebbb8f28a4627362c8397f0a9852e5d8daf53a961d4ee66299e2b54d8adf5134ceedef57011f810aea76262422236c3e1a478a759584c7880fb3f32389c4bd4b637caad7b2bd6fd295aefb150754799434e99e0fd45c1cc4698ab14d1f63eeb06e53797cbdddd45e7f87e85b45a3dd0df6335c3b1addee87ba953bde29ed98042d745c1465a967ef922993798966e1c8b96ad6f68404136be0caa2264e24d8d93aa1b99da9316c7780904753d4e0b45cf282b43a0c91bc9ff83cb25cacea2ea72563b2e759b69cabbb6a50d6a0a5ba545622e5ce576cc301ba35afadbfd1e26668782e1d741feed8aae894b564a425141442fb8470b325cf7c8e1552973463bf4e67a2ad58d15417e418bb91d2df4b1310a0a70ac744bbb4245efd2ae642609079a44cbf6be19809a5ff7ad6847432368c9749cfb336ddcc0e6f52a699b910cd24671f38af5dc39268a3c87771f07d53bf220b7c2d5058cc7b0bcd492abfedf9bb295ec304107130f0e98dacaac6dab998b511f176d48daeb81db53643ad194690b6e28c5ed2927e09a1e959c494b90db401681f67bf1e23fe9ef4c903f666ef39332a91a25c63efe9bc518e9aff61842007dda72dcc0264aa47543c0a8b1f0d25749ddfbed487282241140d4c64def1831c4d75ca975fdb03258ddd013445e08bfb479a516b011fe3a12e4bfca439407c0022889e46914cd41a4d92a25eaa57a55bc7337e5fbbd11584dca34adb5643105c8171e53cf04b1412c3107e72330ebf1b52f524b4e72570cfdc0ab179991f3782d05091ea57b1a233048bf062e88939cfeefb61e8beaa90395faf61c4d974b23723a4a5cd39d70f92620f8f4f27bc99ca67bed7fb6e594913991ca3025480ad791bc94a0def36fca491a206440ec31e32bb85850c3606c875708309be63c2b4f5c477521aa08e1d059cedaafe4fbef5523b79f88b57d0c81bbdd09202095f10f13e2609e833ff41b862b2214c22e8f2b04a363b38d26bf95c07b184b9f909ad3a92122e158d3566d2204b22d4f2f3ce11a65544ccecb01a4a5ef62bc969fddcb648224a5c7bd94f8da9a7d4df393d880f537a377888874c19dad357a0564d303a5c1485c1451ea55d68779dc0c11c7c38025660684ba3f70cbbab00d15b34c0f2342207ad548eacb32ebad95292e85211a8669b586d05b0d0b9f278a35ea4d78e97fd5dafca6b72d8e1fbf3e704a60a8ec60befe2e3e4d3d37f9d33a0feb88add59f0171ddeba0b79a52feb9a1f4a7a6ee7c6927bd10968fba788a807409346a0fccd4f7daac3c8591fc689aed881829d479e8d360cdb5819d5eac718a6f860f2d9ef6a0d36ef6e10efbb37819bb7b03ab7649173447b2cd47f3433a2422b1611dff91cee0b10c6d060d4e84a9e3f4dc194514cb67f1e3985be05c845fc92b41955d0f61aeba6268789998bbf341a8b37af48f07b13a676a11d27330529cabcd52365842be559857cbc2a63a4ea1c77fa8619040e79705c5b51f473e13b73fc09c28598e070dbbb63ce884c2843ec365d4c5bebbf815ee3314dde0bab6b0a71a398e2d9ee8ba2f832863fae7eb0c18adcdd17f1dee0df29a8409acabf516c8e6dfea5a264c1c6657f774c86a14cf96eecac18a41b1650a9e652c6c9264b03aa2fd30e333a9f24cd6b0313358e3c00943a1de63ca970b7da2cb8a0fd1109cefbf12176f5dfb59457480428b194e88449bffd8b8d87d05d30f9ffe9ac3a7442b0df3418acf9165b14242489a54b6b47ea543fed5de74a00f61ab2af553b60d8d21c76c42052c72e4841bd94cf88185c39287c04d05f6336ae581cf7528a59b2874795caca79f5600ac64ad5820a91c711ae5a1c3762028242c5c8a9aae89177ec4db5785cd07402d45805a2e2e970059e4e6483074df1bcc01f57470fb66f45ab475ebb5343b727168e355a6c25d42384e39802d7b4a8c54ac94d82de12f8de13630ec8c19f008f98c505dbbfb21b363472e23d0147d1ac555f0981e2bfd07c62d097acf930094dcf239a40699421b207ac2575b7edf9b1d772ab066362820c182c2c5097a47d1dd25ca9e0dd9c3ae94e9a8f0dece74cdeeec3a17803d5e11f037820ea20364234079286a7c291f3424292b0eec3e956513cc6b078a76a3b8ab42c5fb5efdcea1d438f7ae08507275b48f9588a15be763ad094885269efa7330f6fc9d4746997c98d9f5feeb6dff2734d75afc6a11196b35bb9fd0c0af428cacef0df2c5ad4e5fb4559f0f93af2fafad6fb77f453238f409ec71a912350d7b62952e4858927f620d31569242615345265ff1cbbd7fdfaff35a45732628da663bfff3d3af3d7b537337754554458a2d1af0e16aa8ad9436096f42e243109cad32fac1adc58d714cd3d0d8483c783006991f3da263ef5ae1ff2ea06584e45849d64a07170675c29f0b2abcf1eedbb63b6f5d9dba600996c7d5edce9ac69448d05c0704fb9f84e831b60c376b8a5d33ea22030e2dd3dd421d8e0a810a77c085a3861fcba214a8baf592d624d673fb34f906581d923d80b06186db8ce5fbef2bb750166f7556adfe93d4951a825d55b0bf92c9f25776df784f6aec808ae221cc98d05ce988fe6a13ff96083dba15500e149409b54345274e3633fa8f6685d6fed40c20a5c5705f8b37099a5949846ca15def5a6a427eb4eec72747f116366adcb9b74d3de0b125bdee23ca98ee6312f41fa3d9bba43a8d343552c969c41f766ab4341a42ec4cd6f4d1d4c4b1f16979e5389fea36a150580418d95520506fe0cb1a1d861e09d21c57d88c46e10a3c5ad1aedc8f2743f5c06f10d6da9b2bb3ec783c6f5788ce9400795022cdcec197f9dd3ee4cd26531e7f057b6d9418a0c52ecdb35a24a2a079b3d396017feca8b31aa55e3d5ef79c9ea9ccc7e3d0b47f28f273276666fa1763b3a452672fedc94557d984c3353344a8bc9fc833dee685e33d63540d0801d8068cf66cc48ddcb0d42cec881eae36fc2614f96ad67fceb5c98ec33fbade0e3049178d503c13c2d5d71f32f4582d1cb0f47a2ace578b903796768a906998bed2995798251d7eb92faacc19255bf12c0024a94971c185841113faa288beb7e58d4a98289630fb3d230f936eb1b9d9c7b94b5ac9d3a211c0b454a26e29bdffb522548a65e8dde3730918fdf0575245e71ba013ce08f6e698342a61a81b1355d2483e97c06462cae1cdc7787f4bcee4396a08dac9c14981f2a8f4614a31b019c83782d5d8370acf9db467d9d95e8efbe44274fefde5860c2333cf81593a2ada9f5bb6c2362ba97fd7c3e5bc836c327c66b57c0f023efc0c0ff6feae0e625df2f4e21057060170c844c86412700d7d337b1f7835a0dafee5206cbd76104c5a36623c7783213f8dd457b5e69a86b74030a27b3c30074242b1d97e65a233885a681ec5a8532bce9dca1998dc32c6b40dd997b99a6ed6288e0b9b09447e356bc5345b2133571e65d47db2c736a391970879103d4137cab6c0724b8e67064167cd5521f32135fb6ca43c1e118adcded8227c9dbfdc18cdce154108eba5d8c60e5362e8fffc5c9ae6ac2572188617e4ce0f432e2476c74a4227af64b58e0ebafaf0b1ce01723ecd36a2a4167b7991e28b6a9e81992fcaf7b4b906d0361add02104db83914f28baea26b50561faa46293ba5247e8263ac0347509c36405747866d2fa2beef44f366108f6a4047e282a477c28654511075ddfaad9b9844e18e67320a831e647d923b2720d65ddd9ece165c222231d3c3e7f0001d15e3c690e9831ceb369a8edf183133814bfd20dd25d50973bda58ad03c4cbda8008556fc653ef401ff76ee858c1f79a0b09b4232768e72dd06e42078923d5647cb310bb644feb24d6b7e9d1167c3676cd96f79965a066aca314089db60bdc40c2be4b69c569ec76b3bb74a43fe731bc869c9222ab5404304a513d4f7d2ec5af278f7c3d664fcde579bba7bd472bdc00a1eb4c46ff69fb7e45e5712919e8656a8887afa28cadd66461fc57f53d574c92105818a89f210d7e8aee6de2e78228b2cb03b850a6e77627f70f51bb919bddf61837a978dd4cec2db138c657214ac07b67134bd53b071e2bffa3608a0b0bac88b0ddcfc1ba4dea17191c9ad76ab8de72118893256a7e13e15a3bf98bb5757a78c58328cc4b380f3786f22c6be81884d213ec3cc2784583a47a4003a59ebea08bd06e290a892c937448e664dac672942b068b839593c442f6e1d22875e01859cd24c17d108696a3196ea4794ddfdf25721d3dd3e754d1ea884e5086479819452991403a39014297fcc734e56f8daae4d49d5c47016fc3ead550783df895542229ff3b034b5b722ae2a2b04ba70e42c174e9ddb89ffa60024aa16f297ac9383b2ccad53de4bbe4ea2fa3fe3d059d16b4b4fe9959ba3c4e58922e7fa2673f50be5b636ee7c79b445471ddf5b851ec3ac505980bb184c8fe44c7776ae9aab4e66ce31fe1bc00efced390a82f96b4866e31ba3ff832a25b1e1d00ec44bf525ae523b7102ba60c1d3a2e2bed004524afc90a064b325a258eb36315b1496c748f5407e922914787acb8b47bdc495e521518e0637eac4b1b4fe1adede145181ec7ef038d48c473d6f296b349d7cf874d329c71f272883eb7e77ff303957e159fd417d5055d82687448950dd149e1074a1785518ebaf7ac167e07f1f559893a20d133b59aa294efebdae1e19a30ec9a3e257203eb9a854096395825ef4d1e4ecf1f8daeadfa049ea6c435c50d67fd21c6f6b11a8be46502f0dda1715f5349df5330454316498660b7996432e679c73f1af33e529ac669496bde538890cc093122842e3e2e4bff937708dd4b1b1d3fc066a63824266461e4af9245032d690aac0ea5636c29606473820ee57b112e2bd68c0ce1936b7e76a7873cad678b26b560d7bb10a7dcad3f69bbf226faf2f572c105741a121fa1c55ff30b2d0b7339ed9aa4c9a3671e6e4b572800afcbc8764b16f0a61c4c1ff24c3b64992cd84f39d1a4d5532a7dbd9f7bc847258a33c509a945e53236cbc46b61fc6fad662c523eef0c1eaa4bc0a49610c8d09659e7bdfa858d2494dc3da0a54fcce229951d366fd17f4120f27ac77e5e6b777693641a853eacec09cc4dc08ff6ba22295acec61c5e6215eaf2a3a012461eaade8faa9cba630c5ce2bee6f1a4676d54b4a38b7b5cfb6c98106a4882ed88153a4f0bad3e0f3d04dc1ae5318e3b8f4ab1d122a548eed47f70edad1a164a9c5c3eb10fdecb24b0b68005b2e958980481834c4f673478d3f47d07836d3c1c513dd920042381f70f1a68671acee2fdd453a7552eba497af27127999a13a33104f0086390e01635d1a0b79d92dd43211c74047804e82d9ab26f97ee88e664871dab52a2a79443e39f06a6e8ac9d5e986252529b389d9ed0b2f55fb16ca65f6e90cc9a149065f499630f973996c1e2b6c53f2ab391b7d78cc6926b1684d066a3a74b86b3b633baaf3730acd28deaf18fb926e1ec9c1f8a2345103cc4cbec05345db57c5adcf062412f289607f5fa41194f69bc2f426a30c7a6f8d1027ee8dc96c9957e90fbd9b16475b82dfd8698195159bd7b4860004beb1fa85e6843eca1acbbb0b8c7ec0b865ed108e297a2d5f915304167e18d01e51497e6e3ea76ae99bcb849f7595fa74c2a6263e2bef65f1063bce05483980ed51eac5289307117f17e99d761337e9b1fb625a1b900e6179f3b02de57a0b5f52352298c8a2d2c816182ec169d2b9c0490097ad98e2edc99c6df683a4b5b6eb73ccee0aaf07e8cf8f2f632381ac407c5c578bc1c5a8d0915dc231b01b92dbd25c2bfd412995780582793736572f1e23ef690bfe6872c2572285cd737a4be91f4dcafef09232de77b315d73f5beb23d03625e031d2438081222b063c343f52565ae314ac47a4fe518b45d0c12f2ceabc5e05c20f607b97035afbe0e29249e47961d9cf9b385c065966b0c7ea91cfa9ed1b55a58b9aaa9de080ca05c6405fdf15bcef74177226eb225a47d532bcbc82a5ffed7fd86c2609b146d86f566d0b84f638d46d6eb696bfbbc62c4fc981a94c1d6ccb9f3f7ed7976ea7e8ff1d2a2d79986fb27f1401f25d5a83f64844fa9e839fc8855007b417b261d325b6e7cb124b27ede8ad18d2b6da8bfc4d4f50c3960d5a1c82e4557b16d05471602d2a31462e4bac9535c9a57389ae0613a674815c2ec10c19f529c9274896dfe49ab06889da517d482145ed8f57ba4b7c0434ce24090ef2459682a4f6342ecc382b4cd3409c3415bcb7f1bbaadfb7ec308eea8b6cb2912469b707c99a55c1754db0650616754735b85a41433a30b28e3946754f90caeb03c7579fc9982e6ec5501d6f23e0f2b6392acc435907d79ea11eb6955723a81c4f02bfc78e2eeb1d0408f8f06b4d2f6d20d90f7698c4e58bcfa993884424f8fcb602ef35d23737fb6aff220927e28c19043ae708fd9755256a8a1660d9c5827bab1b836a10aa23aea9c92fa3b25428b3791c5d25f3f1b63befd5480ac4192c966350edceea8938ecc608e0f063d16d427049ad62625f5177470e7a0d811e8d4273aea8f7377d51db07fc34d9f18497a0c2b5c0bc5e8778e06bf7460f0487eed54d661d74346eeada9090957159b86f8b68183e33d0c3fc134d87e068badd8789d4c7adb829fe08e4558bada5ef3f526afb2c7b6184244af0d07aa5cb525c519ed32298bb6241d900ead0532b0b1fc77a6577963e7a44627ed326741af254ab957ca0298a74323d2ee4f1bca70e20ff796491424e108e03c20f2eed7374c0aa2474a91f3ced6f46165c886a510734d606ceaa08822bfced69def33cea3662512fb42ecefee341d1b499b826ad882542374b032e907a7e6a4dddc4620a5d1002b5aee25711fd2dd6e9d4e90ee350f2889d6c1f4328e4b711fc919ef3c655311637b83b4eff39c157e0510807ec61714b843bc9eb22a0f4dac7e5cc07b8e9ed587b701d9aca2a239e76ac9a16338b74d50578956e06b1ac35ee3b822ca779922d89de7d915afd7d80831e8534b8f8a2eaed252fd862abc99aadde62d4520d9a7c3c3da86081fc36927de60e3479096a2b5025b9a789da01da969cfb0ab2f252c82db9e6663dce3888146b365080f649cf94f991312817147d8f0d1774d8d44ba4afd846060df2de1d1043659c3b94b1eff51fff84e5a81a0c635aedcf677285e0d722e3335449fd0f49a41264fb963ea5bba31dae469c789047812071d8853291fd8003cc31a8968ce7acb68a6e0172ba6ee0e9dedbebeb62143047336c5a91c77085afb01fc075938b306d7e36383ecdfda55b9b5dfdab53aa34000289c398f617a146c4a06404737600484d8d4ea960061ec2cb575dc485f65f275540d0ce7550da08417632b6f0f7d044f6f719ff839aa3e5c9db94d45225a1cf0bdb0c5bffa781572ad605ad37aa988240858c9493dee9f00ed281e93532d89aba5e9e59ec430cdd5edfdfc2ef65e094eeab71cc40b59c997943a0e0dbbc80f1e11834bf3b53153ba1c1f0ccf63b3c802439b2ef1430be6994300d9b2efe4b84e25bd3bf8a566d4851e7fff57cada544d722438e8980a31563ef0558fdd8db9bdd6f1a3e34f06104b680f63c1f80a08ec6ed74bca69bb1023fe63d24c7e7a14ce85db6e21173f2ddf14f233f3787a37e4b347e4d64907fc0a23c3da017c81c27df9fafd4695886d0ddec8c47982912eceef886ab5680a130bfacbf3c67bb4f0cc118274bdfed43bbc2ba56f048d6a390e48932469b30ac84fdfc2e812f32d00a85349bb22f2d8091e64282fca1b40811db756059de5d03861d6a22cfc6289097d23c26c5e3f000f9b34a0e1b28a1269d8673d09107b29ccaa1adc8939bdca312c69ae4a238f45410d8f1b27392d594ceea2a6b42899ee5c5857965b29bea1bc413da618899b1894f2adff3b3a7b05a626e50e42379f5d0e0a148ded33d815f59d1401b197a85656466eaf88ed30d1ad4a87985570291efbb3a2c6f22c0b111e65c843ca3c6179e94335f0f91d4696e1a31107948a042f55f264c32a35e719668483957c9c8e13fd01e5f751870a509f5f06ba41ad63cbd5f706f25b1e598f6c9709ee6bab627211bc38494962e930779ed4ea2a8471d309c4c4f0603238959cb13476b673489696c87ad9da5fef0d6467145a77ae0b1089c8626988278a85be3292680d9d7e4c6866f19b78595d611f15f9a5e37b3d145d5aff4a5b58a3286bd25a862904817afe8e9b9105584af15f54554ca5e7dceaa0fbd1111aae126d74f68bb6f0ce98094dc9a59a31d9526729efa171beda9ac5b7db9118aa94b9b5ad58dc20ae1c328e31269244d636139 +Ciphertext = d248b9e47c303f735b0d29f6111a742d93509ae051466688d56b587104a74fab1b259da64475fc0d2c3e28d87ca4edfeaa5715c23dc0e5281eb0c0c14e22182bb02f9f7d3c24555cd6a3ff766c774e67730a920db5f85d47dc23bbbee460f0922cd7ddba81ccbe727b4b489e79a19db2d012dad2a732273dafabc0fbded3c47dbe5b6b585570c39eb62850dc47f4aa0c29bf5fadf334041fdd4658fa6cc29a81192a53dcf47c03ddca9d03b33b06e5b3808be77925b7e7d8cf51fa939e023161d969f92430917d73f3aa10b83d5b7402410280561a27c376ce0b5151a51be2ef4eb9057eed25a0715436233615dcad1559fdbd81042544441857cdf46d72f5f50ee552cfd3bf166c530e57fd97f34e2e71bff8a90b30b4c4cc3e843b0f06e4eb2ff82675e428f5303aa9141dbeb615cf6aca5540fd7cb756fe5f9b08a4abdc6eb90b2eaef51c21eb9ae79a0e44b0755b3ed48f5e6e57f3148ce02501528dd3dd2b0bbec2650710a183e38510990002ce6498dc5ce7bf33d699dd18b66c0f8031d958b11d678674c355a635f4b5e8d863785f5dc2f99eba9ce74595493c017697344b651dcc2a0b1d5386b73abd8bb2dc77a2d92173d3688d0d704da9e44a6385af9fb3a81db68822b1eac9ab284f0155c20f6bc34af85d8518d0dfd32fdaece1379abca339a00e1326b624b3e4050be5db8dced5e6c4b88b82b6ee2a48c373d236ea3565ecc072e953ffe01b624c6ecbf534678aad9c3f8a07d7dd7232134b6b397d0c96ab5f795f9e3af65b96e7a765283d8081dab9f953113abe06e8d150bf9a8416d8932fac17b032dc346be43736dbf066ed239328803510f6f62bc8abc92f6df9a82c02cbf85de91739bc8d7805d392341be99798079419540dc952fa0d3ceca4b806ab1db3b717f0d720038343465a8bc0da8e8964e58634e8a2d6c99230af2ac7c89acd3f86a22075dc40818028f3c632b36a39c0e064e3ca2a078c617a3e73aaea56ef11114f9efaac90a3ec8f8d9b18921a80d74b09ada83efee127f41179dc6c19c7965f3e7f43e22f636534b123e9246172f9920f253d2a2652a5e8c337ff93b2d479bef5e96e972a9b9cd8af057c750bd711010d59ce065ad50fdd487b5dde616301d0ae6373b6f9efae99d8972f242dd7a6bc61caee70201869be202fd384a992478dfc133b84171f013244c5d17585934aed3b43b818926246227d255bf832ff481f5f8d074ab159a11d6d17ed0ac50f727b870db966e0373bd3b1eecbf9ed66aa66caf33ac57cffe4ac6df3cf7b0e54ac54be4f3d50f61b33557c2990c908a710c85000ef6fa62716960daf918ae3d81ee60b3813e65673bd911ce468510bd230b9c2d215afe86ec12e49e0ae87e4235baf3df237188f5e0af2e61c22a4bf77190dd5dc804b4cc330b360c3dc093ef208c37d299ea0cd2ba906084011e16ac5f4fc9646538d5b538a99546d34a4599c8529c1524fc4b394d6a9cd762855905233ed92e72c8b538372ffe2f0df7085eb074616c7e695d7de40779e384d5fdb49fe02385424ea991dc05c6ae813f76c673eb45d6105bcdcfdbf04dcdd20caa6e30efcf3537bcf72947e1ac37d1e8c600ba9238569a4b3afa590d61acceb2572da85885146a142c8f8c60afe4d53ee4d61f33c47e5a99da9a346bcfbd013754ef39a4d7f16c4c5fbfa53d7f180c16e2b64f97dcfd65349939b5fc167c7a78926f638f1893fe9a81e897beea3258a4175d14f41dc123ddd846e45a87f35154db8a5ac27c7a0fc95d3b3113cfa9e7c828f83a1f0d91ab7789c33be5f55ecbb8eb0c81bcc0fccc880011b21000e2f10773388b198ce79c5d694472d3ef6b2e55c342b29c70e4f33fe59e2e0bd3f9ef617733dd3329a0e426338d9c007bcdd382522cb96e59b223825a39b01b52809f5e8518f64b81c99022d8215b5c435d87cc1a57bd440b31a19b197b277b2072968595ccd64c135ae1b218046e27a7f2685d013ce3173efd07586dc72a28ac4792e804d44f9efd785ef005213df928560a20daa4c24ab07f081479270a0dcee3c26331c48a164e4b9d79a7c30c77ab06b00e9b72c190d35fb873bc095d5e6231a89b52a0737a99532079bcc72ee221b48f0d0d9ba9105f981beb4225f6efc1230d6da10fd2b58a65112a98e4bbbe1accd6e8589eb6d9c771bb911cccf42aa6cbc68d1976f0da7eff1e70277e8c5f83734ec1efb2b00708fef08e986bd6519a0fa4b5772e585ac8e37fd2a2af07aa382579498b3b75863fe792461492b8e71c4a1a2f4421705696a96601317cfff1632784b5d75fc2036ed3fa650354620781b9fcfd53f1927223fa045edf4abe7b2144512f3e3aee99f7ac3e46028bc2427aeb18e9cb40db57b696ea884658abc9b7bae0d8117f93074a3ef903528f8b55c7687cf9f0119a1f246cc9e993219c6384359e7e5e639bb294b264048060224ae168d7b9f1f795c07eaafcddb10b61ac2be3ab3e1fddf75c1f47559f38d24f0c773d0e8bc5fa85d7d33e3aa8d0f15583b8c1e7aab6f5d0e085b7175678bf11cfee8eb069b78220377819e3f4d28eb833d3d21efff543d5c6357fffb4a8fdd6ce399fca42e2d71c53c50f6b20bcbaa1650b57ff483837c39a37d5e978393c332b43021508b8ef27773164d69d0af3c0dfdc125cf30a7c49a7d8e5320d68a35e80cdfd62a0b7ce6a412f08c8062e35265fad5d1f226d590e9b068d09e48772711d7dbd786a38c0325b3d5665c2ff45ad0a20c174dc5739896ac727b34f11c7af299d36d30c69bbdc35770138cf891cfdd8123489fdef2dfaffa9c2548ebd60b0f0bcedff44691979b4e92b364753120364dc2e3b895095da828e8659575a85cca587ba05ca625480f977a6fe10181ab6ce005defbcd8894f8c71811909cd6b56eb7ffe327f46793a9e98bd7fe8951400276bb9c7607f8ba1e633034b73d7f0d040197c3f346394eba68c8accccefe05f59cb7ea9ab1ae2e172d8f466ee21c6531cec2c9dfeebc477a6d98195c28bccc1d5e23ae50e3a1ddd7de189e36ffe0e387df7be43427b194b16e18b42eacd517bba78edc9f56a2c7e89e6f13513718869da7c8c529bc337217a69e14e35cf97ff7db2c23700347f0a33ad25a299fc52b35f63949735ad864aa127053797541864b07168f89ffb7ba5c9a8bfbcb4248383a95f45461a7aee9c658c5679205f47144ba4a06175e746037b8cb6556f06405e0d537d0f2bcd898dd5fb987d96dbce33001a50abff5b9cb0161dbfe30f5df5a161ddd8a750b0cb33898c110415881fc81239f2e25440bca41a5bc46fbd3787e6c8fe8a463415cd9a82be368a02566da740dca8e40e686e1213d9c15de2d3556a1e1180b298ba3074b4ab93e469dd9a39ac0c8a173b04a5ad913e72e4d7b5ff520f108e1a1747c11b6b2fcfaa89b3ef7e669f8ad9620364b4f4f0f9ab274e76bdd631df033357a24723653e427324d907a9eceb3c375c43ee36cdeb046a6374be19ab04922da93d4dc07c5914df06fee97dd813f5fd501ca75e3c5ad53574837f2e51ba6a257134e8ee0f4127c59840ba8b1bb13592dcbe47aea50e453c7837e91bb12ad1c74fd0f149479bc0334c511a822145690a3a408caa32671ed05c2dd219ea360c67727c1fe6a6cd842301761e94bedc73f93de7091b8b6d2783a788313b2fa12595904bf5d1167a5ddc4ee151b1522de60b7293b72a62c4d08b396ed682b6a6262a212ddc8c70dbec1a972cedc09f593e21d843279561884f9759a593da7b17a147db7559f19d5d6f43ea98012872f974306037dc0d344c55403b35a5903f766359341bee5bccb696fc0fd1c7aa8803e4c2f9e6e23d386d3a202027c5792e355592efab9330af330392a7c91e3cacc4e645359edafd78b77829374cd4b644817322b7650696fa763a0cc7143f9ec7e2f6ab3c9ec2443b0c0b0a31e9eeafb7bb8c375232357f08256959a10a6d4bc98d6cd9314a2ce7feaa8c0eb1eeb15047f715d6ae9ebd64238d648ed6bc50617a360d8ff9a01aa0ce0e29338d34bb9612751445372ac6d74837c7d2d67729760216ee33476cce1a154086ec31d986cc5a14e86561c6929554fb280646164bb03e8e52588a1b947960a77d61c2d2499212a742e1a5b78805b5b64fed141d3c4834301b8a8bef31ce65edb539fd9469b590a6980d0d1bd29e34a09f87438059a09b1ea234d1bb29882e67599fc1e417db9d86332077cfb05fe440ad1243e26a67a0ea30e63cdee8850a543d76e810140547412fb1400ac87a10e3bc77d3918750a5cc3e7a0efbd736c7ed4139cd5855ddba47143362bf40b91fcbf27222017c1552360466483e67ed125745724cc713c713dcf7ef6ea3081d65d8d78b903382717848bee7410431e1040ec92373f75a1bf229816f55dcfffb6e6da33ed8e1e8b05f9348cdcd6938f053eb9f93e0de639e922627bf61a6688f9649bb9cdfce6236a176db8b9b53ce4b5f9eb9c0680c92128bd327aa7f04a745025faaf117a18d5664027ab0e3f5898b834e1a75cd4b4087637733416f8bac1ccd67cb4457005945676d03f76fd0453fdb9968643fec98d28da7c8cd7070a803b14a2459f073ea075fd023a896d3306fdabc54416e95907103cd2fb642e301c71cc48e8eabedaae356582761a14e0b3b0ef1de06002c2acf594c85820ae3a094e5b4680566b592221543c1dc5192d6b208e86b5aca91d4e3454564eedb3b8208169ce97e1632b864f1d9d4c4c4c0fd4bcc5206e8f6d64c7cdf212d718cb5b7c7ee21593ada3f33f5952e12bba4f46cb99044978fe75349c6ca735db35891351d7e5f02a93354bc45a9ec756453f053cb87430b3e9211807f81ad99b6fceb8ef1b2d655910e1f5fd22f2ee90e42abab230f8f39a8345eed6ad294a0d32416a253f829093ecae209bc1dbfadae04a373080f9ea8394a28ddfe1134309bb53ae571d2019ff2bd4be94f8176d90987fcebad323f0b2921b85b2610852973f383a2ff4a5fa82a77b13cfd50a33f29164a9ff409422cc4cbd772132856cbd08470b220ace957a6b8e02c8003d750539a38a8df19a5b662907b72e3098d77c2fc3ece0693b47ff19ce911a93b6adce75653d48ace6af10b8f1141437f9206658707b16794e349db3f1a02606ea167d0213ce3644f64ced64de3799b1729210fc31ba1811b0c226306f2466b230ae35e6d8fa11c8f932e27da8cb1bd311919bf9178ef08bb7a2b4ca2d2e6e9585ee9f916991cfcd4862f5de9fbbc63bee6edbdcfcec9173a252eb59fc6d6e58258ca8b2a4475acfc1e09a0c9566d23d92e9ada97de51895bfb0867c42025c8d089c65bba67f4dd84d7c5155a930329345cdf3b1d6e910e730df273e183190beb900344bbce8c3bdb13a7e4ecbe967a61d47921aa55bac2bbb24e3e03d386ddbfafb3b32235b5ed922ed6ac2c89ded1316b69079b826507d708a6cca14ce2244a67be90fb91ddcb0c97432703729bceb432bc856f5eb9d2f169800a04283b080f0e053670a21468df9414fda9f4153eaf1669a19ede7925f832280800f0063ceee34b9d3b0f8da2012525fa7927e76bda71954714d5f51405b920391eca2ad71160acef4091878b907974573b4cf1b377baca0340ab0e4ec546fcaa6130603ad633c3ef980e88d8f44ec5de743cdc6cd9e0e4cbdb97a5c076be9ada8f26bc54d711facec16a2401292cc167bb98cdd320ec9321414bd97498f6d9b54dbb45ffe4b3e3f88260657ee23e19de48a93595c8e3a289a02d76a27ceead05d591633464709aca117c26aa49b64667f2a3b6371984f813d7098fae7a6ba1841775b52314a06c80b4c994ef8100e233ab3115ba2c39b97f2d5082a145720ad0b12b8a7cb275ba848b3fae14fc0c82bf0353195c056b302e508982f73a8519cca722892482b9d9e6a58bfb4d862fa393eabe6aedeae1be5ed772ea3c94a0df1d9684a131c35246c68b32e46aaf89f3649e58b2e99bd6bb3923d3ab43cbf73b6b3d19fe3b62bef178f46c79ba85e23ee4b25bc561e8fa97f51605bc0b210b02aa28242e81dae9489076d259f17d25b93b0e8a2010584d907314e3bd55482f0fa43d37ae9535629d28d6f837360bb35ec869d2a959789dc49b9c8c515942a1e03650566b736551a5180a60279bdb0ff9c387beebeb9e59ed930b3746464a010a6f7ef1de3c7d76fc6899b1e5ed98213813ffb333d969ad72fd8537ef4e12ca7b78d35c24f44ac82da4a7116492ca2efd86ee6a4474014e72a5cfeee7f729b77cfdd1a5d10a03f3cf28f1d314fca36d31ef2ecb3cfccecbcdfd22367b0a0e04435654286ae3d4fee13f56bb7cdab40b4e1dd01f9ef857f94a67c1e237e24819949935ff3bd73b0461ee9020fd0a2db2cc6312ace97e4a8a33c295271453a12822db8d1438f22ed0d466150990dcb39ed042424eef7a1210c83224c856923e3251484a81a15cddb4d7ada8bb7968dcc8f85e39ca99ece8ce2ed7753fcee6900cc9b7b5691f2d67ef9be13f70d195bbd0047908025df01b4f4d581fd59239836578627d9d585ebe9b053d807e9d3ba25405029a148938a746636decdade02b1afb5ccbf2f0e14a27c98a1e130d9208bbf7da4bb4e572927eb348568921d4a3309a2c24f367c935c2a8e1524c3024ff350ac7da8d2849586817bc9d46a08a21aef035a6151e608ed93b1556a484e455819f9ac2fb155020738962e7255a82a0854b31fe20cdd351c10a33eb693c9be1a51a932e04d0364ced41ee1bf800d0c12ab5eb37fe52563666e52827720e856d4f24eb06e0aba446910aabbe36513f2274362fedba4c19398433029495284ccb499bb559a9cdbc94a0d1b733136969a743945a04e1d2d4e77fed21550af35f22651c7de802eab7a3942d7ec55a3a5002bde8d5cccc1d4ac4bb7f4926615fcece543fe5d9092d2c4f50d94fd9868775a072f4a5bcf2e5fd10795f7f172a3341ce33505ba68e7ebedc9c1e9165864244ed31bbe5c308dceff858cc42010ad8c281a24689cf2dee8a549b1abab9981d70a912174944b403ce664d8608b2f723150f5c12164e4caf28676e7a25c3928ca2a4dbe96355ef8f282e57888d40715df07bd8b5895549ad957e758abf868def1c1f5e260d26498616e2ac962bcaa33b879874569f198a91ce4e50fc50da77fea1df9f9ea900c834dcdd462d338efcf8e612aedebf254fac596507d175d30a90543627cfcef6852c7cda8b430e255c4d6d417de31eb5dba123e3ce9e2269867d9a94fdcd8ccac40a9451953085109f5ae0c3e04daadb4a2a47b0e176917660eb3c9f1aae0ec6b00635fa387e056623947c0621f0a12e86fac1881ed1dc1b9f523388d6b6596a152b3e732c561972879dcd3f0232ef0773a4fb195a90c3186c4688ea58967ce7f18386b80bd38e90cfd4cb899337ab27cba8db6523e979b4c449645bb2f320ccd28578bc7ec38f47225273fa61a2e5df97c4d76c556fbe2b0fd30e615f5fc82c3de7194caed9f5946c151c22b7a0c48f4a7cf78aa153414f2913c5eb95e3dbcea7ca544272cd13a1c52fa87759aeb430aab144fab418c835344605df3a044825965ca15de6ba0e59b2080f5844b2d110d71587e19acf14264cec2de5b8c77d18893215d1c1da0a940e7c2ee429a99e2633c216aecb7675a2314a09044951ca5a8eac798f8878fb5ea65f4ddccac53ee0c786e597169079fb6e8ceb37a71580b0904a97450909ca454a690821e249aebb75449e582fe1b30f1fa9f6464bdef654daa5ede6d4f223f4589ea25a25f4672cfbe974d51008bce296628556f55d26646e40b59f40e3149273760b40806ace3b5171e0b79865c6adb53513da2f24c4115de243150cec76107b48ca8da19117f00b5870e67eb8357e43c1b7b593c9875795d46ede26a109e05406b69fda988947e49ab195f22454c3c743c2ec51b91370b4df8d38653b353e51bb83215d122bcfa591009c007bbb6124bc590fed3f9c5699180b3b1424ad02f7c90a149b77d22dea5c996aba675c2a1a20e206d9c25d9446247d495a26486c0d0bfb09d0b5a1a177a09fa749dc36cee73af0116a6b779c2b827512a04ff0f60b483edbcdb33d2a18339463c498ae67ffa9da0aa3f3beb6bc99212f9e6961afde89045520b1f3f2e2761666a333d76030f443f53322f099035584a60978ef8b49f46d7d4d8c5c758ea52a04b59c1a3a1c2f9df3f3b6f5c45cf4b3547043b18c1d615a2c965c3918d090cc72946e8fd0b938e60e03464f4bc71fb719a1d173b0931930e58bf7f6d4403971d36b40f83be6b57244a7029e1d41dc908764d57a5442557218b509faeda4e9fcf31debbc54ae671ef636871233f29e0013c0e33933543f4b59df1978ec89b109c3977b0cf938b7f6166d6c93be5e87684a703c8b7b5fe1a8bfe153a179b55575ff05e599b39e32ed10d958699a1ffe07136081f0719b18c69dc74f66f211103e9c544f3c81a88ba9f66a9bc7017d9ca9e2cd97634052694a598476b99daf1cdfb6122869375ca5873d32d5c1e07d9b5b380b4f09dbe04478cfb1a13853eafacfed70c8abcd444ed095f78d07c0e8b4093be95c3aa24b2e5b6bfe3a06e9d2d9fedfcfeac4cea2490627e6da6a5cca383351952f654ce2b0ad359c0f7f4ad3f8d1d4a030a947d4a2e417bb79102729115cc8b6558c3362b1d805fb48ce4858deff97677e60375ed13e150a12ee7dcc8ccc64d9710c7f516555c1f7a1a08f0d7c6fd21f864fcf28c8f748c40494e01fc32006f977a5100577f86a484d11b82c90cfe6b4d6b1902fef486cc6f3e033904e150e67283e49a5382961dabd244412ca9657b48796e476a82443167e277d5a65c0c563a6abca77d316e5d3ab639a1ecfb1110af2d29f146508bd9874486dbb56328d6f59479e2766692821660462aa60b6bc8a710707ceeb0ea6429e5113e03c9f41ce0d69c7589deb547527673e8a9f9a9a74e9e4bbcabf2e306b35504c1da99730ae86e94cd047b2e6ea5e97e63a492430d37ec446434fb3b066adde08b17d7d903ad194a4a863d6cfe181a45c8c97b5062bf7c4e44d69c0d1a7e1f5029b805b7c21d1b5e56e697999a32557870ebaae8d87dcb5ca5eea2c5547a16b3f30ef9df8df821028c106f86e091050ff8b6ea4171e59dc2592d405073bea53f8ea62edf112dfbc7ca69809db8005783d63557d3d90d123a944be395c1dc3b5e1476dff188346327769fea65f3cf9363e88ed67335870ec8ef13eb9d9ff5317c4e24dfce9d11699e5f47b4233cc8f9d1b915e716a5730a5898ee65d30b1628b484a5e82eda95a590964a8d8bc89dd3c5cf6c4f9137b8c6ee9d6a692e0c0d1d858dd5b3c12de48badade4d01bff312c56ce3ddb34b0fdde3b0c2706fc292b9fac7e1a0dcd0b6534c968117f7de15eba84d2754e4bcb8093a5440297605598659f686075e2b1b464b6b3ec68abb13cde263b1c607545c45746338b9b207b5c381da690f653b35e363e1249551ad938b9fd7b0a944151cda07127bf9ba76958e926472f4aa1de8512ce834cfcae5414b226f23acdb1fe5cf685d2201b78167ad35fc1da282744c2a43cc49d49242f968f7e06de14455e7ef5adedc5b33184346018114e2d1fc7a5349e378da9b2af5b328c213888652aca9f1145363809eca7c1fd8e64a5cc3255418736e048a731f3053db77971f67014e6121a8e464833e5dbd02ea6caf385e43e9f378bfba657986bf852b32adb55e35a2675bfc8d70d43a902032a61f59f57dad2dd7d7963322136233200cb9a90c952074e9ba0fc0654f1b6fd6f7f0eb77c0fa6d8143213ce6e8b0c178f73e17a7c64839f9bebca2fc955ea8ae406a13b80a9045fa8d129fd859faa46fd27c48bde7b890f98ee938c0d78889f84181ae2f5711304fe554d4251bbc6437ced59d577a2a1f26da736193c3674adb13cef9f4cb4aa6585c4d6874b0309ecde300493b1642c595746f09e03977c8902f3a4a877db1153b248f295a0ca2f1e437d15fcab8fd77c5f967304efb5c4920b990674ae61b954af40be17a8559dc377c591b68067fdcaf2d27bd9a22041b981a84be3de50d5962b58f8c4a22fa05192c5ac99a0a9423284fe62a3a59f085136cec72cda2a53af106a2eb5bda28b6e02c299118cd91714c2e7d045346c78d9ed1b41c73231a21e42c298949f70122277f4134ed5c56639edbf3c3e717310e3d1f03dc5a94e64c4ce148bc5c6bde64eb80b17d5979892786a31225eb89bf9f5a582bcf65b83ff7aa361ccd9238d144f6a22a3f77dd8a01382df4ee90a2057dd310a6b0c4b81dfc92a2cc0c606d3be8b18fbe64ddfdf2004eeabea892be2f914edd1edd8e8829dc7704d71bbaaf08c41824dd0f4b34c9eedead9e10e53bfc6fc0bd37417de0c5c71cff0754d672f29c262d8e27b524427e12bc4e4705ab311d3bedcb1ddd09a3ca0c268c05c64951b7d724a9dafe4d249aaabda91d68633aaab845bf78f9a22d467c7e0c5fc70fc9a318b01d7492efea7fffd329d70692e76647ae665c62b280da0d62f870a52e4dc4cd92c9150c96aab16f8c23475e3152d4debb41b6756f000c3d8aceef18b49e295be7a71da1eeadf4eb96509d45d7cc42af4b7013d8bb445f577e8d4cff92770b8ba0e451f3e24c6d981efdb68c7f2dfafee40b8a425955796e369f0d4da3e998c1626ae0fa583334475f1fdde68ca211c3f2e9afb003f553191702e11f8b731c89ea26059ea4466f2bd0a1a5601025ca9417006bca5c9a57dfdba44c603ef9ad38922623b40feda036d84425c47fa42973e348a180a7570e1215044c375313ab08d6f521052dda415707ebb74d6c4774e039bb04cadc2799224bde1802e2ee2a018032e3a341700c0fa2aa28bf93cc479231efe7da0e9f68e572415348c08cf648117e9b6d1267fef6617f5927252c86cc087775db3e30180feb5ce7e1ac9c3761161e07a4853aa6d97e525aa88302954cf9390fde81f8e11d97a11c79e3bad261364c18890dd1f8fc71127edefe3571518a42be611a46a0426a33221aa25a0ae6514daaf96038cb59aaba898de49e3b215a4464e0af614e638c2d9b6e676ec427fc906bc516331a18121f306a5246d179e2d3d0f38ab8393f7ea5a2d24585e7cca649637b9983924a15483c167e8780f8dd7aa1154cbf731745a8d8d54a8c4f8d854371bb8172303f9ba3c8c7cfe8c378ee56bc35c6376aafe907d3294ee9a8786281b7deff78ff125761f1a31d0e8fffe04a52a7574eeb8679670ca3bfb740167a559488d4337819613d32752d8a89013622f6a8d70f3c64b84a4215f4b7bb282a2d17c36a326167e3270757b8f1d9a0137bfc5ec278e8ca35a69e49779cfc25b95a89cc18732b5b9d1986b18878c57e118506909207207ad0b4edf32fb2b35b6e70546f45d0849bd139ffff9d8ae547787e7b51403b54f110e2ac65468cd0910d80a4e321deafd46e9af19609bee1efa41b762b8ace989dd681503539e7d9948664cf7a73ffac9ce2a34b514253c4f21bbccd38057a6d68732930dcdfc9a32219b53339d100db0037a8bbd101e71f5054f3 +AAD = 7b3b9c07148fcd897f657ecfcc87e530191536b8e77f9309e8d7323888b3b21477f2ab7c885c105d9c29ac96aed23b366f9fde4177401b7038c6770c7bd2ee8b4335105cc0eab9e367f0cea90d6f1ae3fa76cd21ceb9f3500ce7fb4b2a3f9e90f900a231ec693aeced7afb6821391d1f5b1b957895777aa7a2b71d9571c00336f26d54d756392cdb74bfb67d5a621d517db20441f74d0940180baf613b09452f64224f8af7bbc864ab4a8434ff624d0c0646ee07132fd376506951899bde975df8c836ab4ed9cc084f1f6d500ad56345d2f250a0d6991b9e458c62b6023191f341c8659e8a38c878cfac12b032674503df9c9bb01c4340c709eb6dd7c74907d769a317f4dd7317843c47bdb4c5e1f07f2380d464b0c47269389cc8a43a09adba86f6aa8f44c8fe514e73b5fe8d344769c1aa20a4538ecfbf47562ca79fa497b0f02f103f75522db9ead50d56dbe86997d6085f1b5aa7a4cab9e51a1247ce4f724a14983b6bafd17369fac973c6be268e20d800de870928e100990ebb0d3bedfceda36c64be3a729b603bce677a49e8caf282c9159b6e3e1e775129bd30dc3f5c9849535d86a27474be03bb5749b4c0115e2614f8feaa7405cc69b1de479b3b57e551f876a9c8c57ab9879cc68bb2ea110b2e77e59dd6a65eaa67cc4d4b2f4d6e646b2a298d3c80fb43969275d4414734e74726145dab06124c040656c39a94846e8fd58d326f4f9eafe5b95d85254765a21993f55070fcb9e85db5d42ab6b9464ce66de3f236dd2a0a26c4e5535dbdcd6eb350209a65aee785c6647ad4103d092a8ac932470880eb314f7c98cdff34fdf35ee2d36f09bd443b5defad7a5acb9df55965421fd043def6f4771e1bb27385b30ba22c0d8972aead6b654085a7dd3b60c4004a0dae22e25100e54e0badd0cadf909799329ddff699de8066dd6c3822d80c73c52d87e6fcbdb2dbbf852e37804b1256e23e76dbe43f30be4a577bc23c7941a3d708d1e1f579e9c6eebc219c74768168f6790a41f883790e08cd1e88ad09a544eb97b3d1d5af67eea666b9c027e5c7c976921189b955a9e605f6cc9c012c1c2e197c5b02504cb9ffbcb0f3ed778d540d5194fdf5d38dba6340c93da7c5501a082689616f337d8b59c2a92c25e777515726e1d7f6cc9552693cc7c30f1294b37f97d49814250d6c1e3eb335c5d214ef3641739d508b87106eaaf367902433a148ca962ec694409acb82d7749e1c88938ad382d0ca6e6cbe8255746832fe737c3e71dae8397f260c98d4a292a126ec21935c24096d2f91ae114194af659455d8a4206197495a28474dd2809debf5f550d77ffac2b0db521559910c352f23472d7aa9f4dbbdb158f40aa36912cbd918ae4c642e76d78d57ade1075c4fe1086ddee3d554353b4693bbcef1cfa87e49890838c36156af0edf384b0413d6d7aa +Tag = 51cbcf4a2fd82f221de1bfebf86a8c24 + +# OFB tests from OpenSSL upstream. + +# OFB-AES128.Encrypt +Cipher = AES-128-OFB +Key = 2B7E151628AED2A6ABF7158809CF4F3C +IV = 000102030405060708090A0B0C0D0E0F +Operation = ENCRYPT +Plaintext = 6BC1BEE22E409F96E93D7E117393172A +Ciphertext = 3B3FD92EB72DAD20333449F8E83CFB4A + +Cipher = AES-128-OFB +Key = 2B7E151628AED2A6ABF7158809CF4F3C +IV = 50FE67CC996D32B6DA0937E99BAFEC60 +Operation = ENCRYPT +Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51 +Ciphertext = 7789508D16918F03F53C52DAC54ED825 + +Cipher = AES-128-OFB +Key = 2B7E151628AED2A6ABF7158809CF4F3C +IV = D9A4DADA0892239F6B8B3D7680E15674 +Operation = ENCRYPT +Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF +Ciphertext = 9740051E9C5FECF64344F7A82260EDCC + +Cipher = AES-128-OFB +Key = 2B7E151628AED2A6ABF7158809CF4F3C +IV = A78819583F0308E7A6BF36B1386ABF23 +Operation = ENCRYPT +Plaintext = F69F2445DF4F9B17AD2B417BE66C3710 +Ciphertext = 304C6528F659C77866A510D9C1D6AE5E + +# OFB-AES128.Decrypt +Cipher = AES-128-OFB +Key = 2B7E151628AED2A6ABF7158809CF4F3C +IV = 000102030405060708090A0B0C0D0E0F +Operation = DECRYPT +Plaintext = 6BC1BEE22E409F96E93D7E117393172A +Ciphertext = 3B3FD92EB72DAD20333449F8E83CFB4A + +Cipher = AES-128-OFB +Key = 2B7E151628AED2A6ABF7158809CF4F3C +IV = 50FE67CC996D32B6DA0937E99BAFEC60 +Operation = DECRYPT +Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51 +Ciphertext = 7789508D16918F03F53C52DAC54ED825 + +Cipher = AES-128-OFB +Key = 2B7E151628AED2A6ABF7158809CF4F3C +IV = D9A4DADA0892239F6B8B3D7680E15674 +Operation = DECRYPT +Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF +Ciphertext = 9740051E9C5FECF64344F7A82260EDCC + +Cipher = AES-128-OFB +Key = 2B7E151628AED2A6ABF7158809CF4F3C +IV = A78819583F0308E7A6BF36B1386ABF23 +Operation = DECRYPT +Plaintext = F69F2445DF4F9B17AD2B417BE66C3710 +Ciphertext = 304C6528F659C77866A510D9C1D6AE5E + +# OFB-AES256.Encrypt +Cipher = AES-256-OFB +Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4 +IV = 000102030405060708090A0B0C0D0E0F +Operation = ENCRYPT +Plaintext = 6BC1BEE22E409F96E93D7E117393172A +Ciphertext = DC7E84BFDA79164B7ECD8486985D3860 + +Cipher = AES-256-OFB +Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4 +IV = B7BF3A5DF43989DD97F0FA97EBCE2F4A +Operation = ENCRYPT +Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51 +Ciphertext = 4FEBDC6740D20B3AC88F6AD82A4FB08D + +Cipher = AES-256-OFB +Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4 +IV = E1C656305ED1A7A6563805746FE03EDC +Operation = ENCRYPT +Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF +Ciphertext = 71AB47A086E86EEDF39D1C5BBA97C408 + +Cipher = AES-256-OFB +Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4 +IV = 41635BE625B48AFC1666DD42A09D96E7 +Operation = ENCRYPT +Plaintext = F69F2445DF4F9B17AD2B417BE66C3710 +Ciphertext = 0126141D67F37BE8538F5A8BE740E484 + + +# OFB-AES256.Decrypt +Cipher = AES-256-OFB +Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4 +IV = 000102030405060708090A0B0C0D0E0F +Operation = DECRYPT +Plaintext = 6BC1BEE22E409F96E93D7E117393172A +Ciphertext = DC7E84BFDA79164B7ECD8486985D3860 + +Cipher = AES-256-OFB +Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4 +IV = B7BF3A5DF43989DD97F0FA97EBCE2F4A +Operation = DECRYPT +Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51 +Ciphertext = 4FEBDC6740D20B3AC88F6AD82A4FB08D + +Cipher = AES-256-OFB +Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4 +IV = E1C656305ED1A7A6563805746FE03EDC +Operation = DECRYPT +Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF +Ciphertext = 71AB47A086E86EEDF39D1C5BBA97C408 + +Cipher = AES-256-OFB +Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4 +IV = 41635BE625B48AFC1666DD42A09D96E7 +Operation = DECRYPT +Plaintext = F69F2445DF4F9B17AD2B417BE66C3710 +Ciphertext = 0126141D67F37BE8538F5A8BE740E484 + + +# AES-192 CBC-mode test from upstream OpenSSL. +Cipher = AES-192-CBC +Key = 8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B +IV = 000102030405060708090A0B0C0D0E0F +Plaintext = 6BC1BEE22E409F96E93D7E117393172A +Ciphertext = 4F021DB243BC633D7178183A9FA071E8 + +Cipher = AES-192-CBC +Key = 8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B +IV = 4F021DB243BC633D7178183A9FA071E8 +Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51 +Ciphertext = B4D9ADA9AD7DEDF4E5E738763F69145A + +Cipher = AES-192-CBC +Key = 8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B +IV = B4D9ADA9AD7DEDF4E5E738763F69145A +Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF +Ciphertext = 571B242012FB7AE07FA9BAAC3DF102E0 + +Cipher = AES-192-CBC +Key = 8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B +IV = 571B242012FB7AE07FA9BAAC3DF102E0 +Plaintext = F69F2445DF4F9B17AD2B417BE66C3710 +Ciphertext = 08B0E27988598881D920A9E64F5615CD + + +# AES-192-ECB tests from FIPS-197 +Cipher = AES-192-ECB +Key = 000102030405060708090A0B0C0D0E0F1011121314151617 +Operation = ENCRYPT +Plaintext = 00112233445566778899AABBCCDDEEFF +Ciphertext = DDA97CA4864CDFE06EAF70A0EC0D7191 + + +# AES-192-ECB tests from NIST document SP800-38A +Cipher = AES-192-ECB +Key = 8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B +Plaintext = 6BC1BEE22E409F96E93D7E117393172A +Ciphertext = BD334F1D6E45F25FF712A214571FA5CC + +Cipher = AES-192-ECB +Key = 8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B +Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51 +Ciphertext = 974104846D0AD3AD7734ECB3ECEE4EEF + +Cipher = AES-192-ECB +Key = 8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B +Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF +Ciphertext = EF7AFD2270E2E60ADCE0BA2FACE6444E + +Cipher = AES-192-ECB +Key = 8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B +Plaintext = F69F2445DF4F9B17AD2B417BE66C3710 +Ciphertext = 9A4B41BA738D6C72FB16691603C18E0E + +# DES ECB tests + +Cipher = DES-ECB +Key = 0000000000000000 +Plaintext = 0000000000000000 +Ciphertext = 8CA64DE9C1B123A7 + +Cipher = DES-ECB +Key = FFFFFFFFFFFFFFFF +Plaintext = FFFFFFFFFFFFFFFF +Ciphertext = 7359B2163E4EDC58 + +Cipher = DES-ECB +Key = 3000000000000000 +Plaintext = 1000000000000001 +Ciphertext = 958E6E627A05557B + +Cipher = DES-ECB +Key = 1111111111111111 +Plaintext = 1111111111111111 +Ciphertext = F40379AB9E0EC533 + +Cipher = DES-ECB +Key = 0123456789ABCDEF +Plaintext = 1111111111111111 +Ciphertext = 17668DFC7292532D + +Cipher = DES-ECB +Key = 1111111111111111 +Plaintext = 0123456789ABCDEF +Ciphertext = 8A5AE1F81AB8F2DD + +Cipher = DES-ECB +Key = FEDCBA9876543210 +Plaintext = 0123456789ABCDEF +Ciphertext = ED39D950FA74BCC4 diff --git a/external/boringssl/crypto/cipher/test/des_ede3_cbc_sha1_ssl3_tests.txt.REMOVED.git-id b/external/boringssl/crypto/cipher/test/des_ede3_cbc_sha1_ssl3_tests.txt.REMOVED.git-id new file mode 100644 index 0000000000..a341aacbb5 --- /dev/null +++ b/external/boringssl/crypto/cipher/test/des_ede3_cbc_sha1_ssl3_tests.txt.REMOVED.git-id @@ -0,0 +1 @@ +2b57c8d88a60e99a7afbb713d1a16ce497e329a4 \ No newline at end of file diff --git a/external/boringssl/crypto/cipher/test/des_ede3_cbc_sha1_tls_implicit_iv_tests.txt.REMOVED.git-id b/external/boringssl/crypto/cipher/test/des_ede3_cbc_sha1_tls_implicit_iv_tests.txt.REMOVED.git-id new file mode 100644 index 0000000000..f8b80eeb16 --- /dev/null +++ b/external/boringssl/crypto/cipher/test/des_ede3_cbc_sha1_tls_implicit_iv_tests.txt.REMOVED.git-id @@ -0,0 +1 @@ +ef97ddf0539eb9515e4597013f8b8ba47f26fc78 \ No newline at end of file diff --git a/external/boringssl/crypto/cipher/test/des_ede3_cbc_sha1_tls_tests.txt.REMOVED.git-id b/external/boringssl/crypto/cipher/test/des_ede3_cbc_sha1_tls_tests.txt.REMOVED.git-id new file mode 100644 index 0000000000..67988c2615 --- /dev/null +++ b/external/boringssl/crypto/cipher/test/des_ede3_cbc_sha1_tls_tests.txt.REMOVED.git-id @@ -0,0 +1 @@ +19fd026f4145a329dc04bb85e00e74234716cc40 \ No newline at end of file diff --git a/external/boringssl/crypto/cipher/test/make_all_legacy_aead_tests.sh b/external/boringssl/crypto/cipher/test/make_all_legacy_aead_tests.sh new file mode 100755 index 0000000000..12f8853331 --- /dev/null +++ b/external/boringssl/crypto/cipher/test/make_all_legacy_aead_tests.sh @@ -0,0 +1,24 @@ +#!/bin/sh + +set -xe + +go run make_legacy_aead_tests.go -cipher rc4 -mac md5 > rc4_md5_tls_tests.txt +go run make_legacy_aead_tests.go -cipher rc4 -mac sha1 > rc4_sha1_tls_tests.txt + +go run make_legacy_aead_tests.go -cipher aes128 -mac sha1 > aes_128_cbc_sha1_tls_tests.txt +go run make_legacy_aead_tests.go -cipher aes128 -mac sha1 -implicit-iv > aes_128_cbc_sha1_tls_implicit_iv_tests.txt +go run make_legacy_aead_tests.go -cipher aes128 -mac sha256 > aes_128_cbc_sha256_tls_tests.txt + +go run make_legacy_aead_tests.go -cipher aes256 -mac sha1 > aes_256_cbc_sha1_tls_tests.txt +go run make_legacy_aead_tests.go -cipher aes256 -mac sha1 -implicit-iv > aes_256_cbc_sha1_tls_implicit_iv_tests.txt +go run make_legacy_aead_tests.go -cipher aes256 -mac sha256 > aes_256_cbc_sha256_tls_tests.txt +go run make_legacy_aead_tests.go -cipher aes256 -mac sha384 > aes_256_cbc_sha384_tls_tests.txt + +go run make_legacy_aead_tests.go -cipher 3des -mac sha1 > des_ede3_cbc_sha1_tls_tests.txt +go run make_legacy_aead_tests.go -cipher 3des -mac sha1 -implicit-iv > des_ede3_cbc_sha1_tls_implicit_iv_tests.txt + +go run make_legacy_aead_tests.go -cipher rc4 -mac md5 -ssl3 > rc4_md5_ssl3_tests.txt +go run make_legacy_aead_tests.go -cipher rc4 -mac sha1 -ssl3 > rc4_sha1_ssl3_tests.txt +go run make_legacy_aead_tests.go -cipher aes128 -mac sha1 -ssl3 > aes_128_cbc_sha1_ssl3_tests.txt +go run make_legacy_aead_tests.go -cipher aes256 -mac sha1 -ssl3 > aes_256_cbc_sha1_ssl3_tests.txt +go run make_legacy_aead_tests.go -cipher 3des -mac sha1 -ssl3 > des_ede3_cbc_sha1_ssl3_tests.txt diff --git a/external/boringssl/crypto/cipher/test/make_legacy_aead_tests.go b/external/boringssl/crypto/cipher/test/make_legacy_aead_tests.go new file mode 100644 index 0000000000..40b8a015a3 --- /dev/null +++ b/external/boringssl/crypto/cipher/test/make_legacy_aead_tests.go @@ -0,0 +1,357 @@ +package main + +import ( + "crypto" + "crypto/aes" + "crypto/cipher" + "crypto/des" + "crypto/hmac" + _ "crypto/md5" + "crypto/rc4" + _ "crypto/sha1" + _ "crypto/sha256" + _ "crypto/sha512" + "encoding/hex" + "flag" + "fmt" + "os" +) + +var bulkCipher *string = flag.String("cipher", "", "The bulk cipher to use") +var mac *string = flag.String("mac", "", "The hash function to use in the MAC") +var implicitIV *bool = flag.Bool("implicit-iv", false, "If true, generate tests for a cipher using a pre-TLS-1.0 implicit IV") +var ssl3 *bool = flag.Bool("ssl3", false, "If true, use the SSLv3 MAC and padding rather than TLS") + +// rc4Stream produces a deterministic stream of pseudorandom bytes. This is to +// make this script idempotent. +type rc4Stream struct { + cipher *rc4.Cipher +} + +func newRc4Stream(seed string) (*rc4Stream, error) { + cipher, err := rc4.NewCipher([]byte(seed)) + if err != nil { + return nil, err + } + return &rc4Stream{cipher}, nil +} + +func (rs *rc4Stream) fillBytes(p []byte) { + for i := range p { + p[i] = 0 + } + rs.cipher.XORKeyStream(p, p) +} + +func getHash(name string) (crypto.Hash, bool) { + switch name { + case "md5": + return crypto.MD5, true + case "sha1": + return crypto.SHA1, true + case "sha256": + return crypto.SHA256, true + case "sha384": + return crypto.SHA384, true + default: + return 0, false + } +} + +func getKeySize(name string) int { + switch name { + case "rc4": + return 16 + case "aes128": + return 16 + case "aes256": + return 32 + case "3des": + return 24 + default: + return 0 + } +} + +func newBlockCipher(name string, key []byte) (cipher.Block, error) { + switch name { + case "aes128": + return aes.NewCipher(key) + case "aes256": + return aes.NewCipher(key) + case "3des": + return des.NewTripleDESCipher(key) + default: + return nil, fmt.Errorf("unknown cipher '%s'", name) + } +} + +var ssl30Pad1 = [48]byte{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36} + +var ssl30Pad2 = [48]byte{0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c} + +func ssl30MAC(hash crypto.Hash, key, input, ad []byte) []byte { + padLength := 48 + if hash.Size() == 20 { + padLength = 40 + } + + h := hash.New() + h.Write(key) + h.Write(ssl30Pad1[:padLength]) + h.Write(ad) + h.Write(input) + digestBuf := h.Sum(nil) + + h.Reset() + h.Write(key) + h.Write(ssl30Pad2[:padLength]) + h.Write(digestBuf) + return h.Sum(digestBuf[:0]) +} + +type testCase struct { + digest []byte + key []byte + nonce []byte + input []byte + ad []byte + ciphertext []byte + tag []byte + noSeal bool + fails bool +} + +// options adds additional options for a test. +type options struct { + // extraPadding causes an extra block of padding to be added. + extraPadding bool + // wrongPadding causes one of the padding bytes to be wrong. + wrongPadding bool + // noPadding causes padding is to be omitted. The plaintext + MAC must + // be a multiple of the block size. + noPadding bool +} + +func makeTestCase(length int, options options) (*testCase, error) { + rand, err := newRc4Stream("input stream") + if err != nil { + return nil, err + } + + input := make([]byte, length) + rand.fillBytes(input) + + var adFull []byte + if *ssl3 { + adFull = make([]byte, 11) + } else { + adFull = make([]byte, 13) + } + ad := adFull[:len(adFull)-2] + rand.fillBytes(ad) + adFull[len(adFull)-2] = uint8(length >> 8) + adFull[len(adFull)-1] = uint8(length & 0xff) + + hash, ok := getHash(*mac) + if !ok { + return nil, fmt.Errorf("unknown hash function '%s'", *mac) + } + + macKey := make([]byte, hash.Size()) + rand.fillBytes(macKey) + + var digest []byte + if *ssl3 { + if hash != crypto.SHA1 && hash != crypto.MD5 { + return nil, fmt.Errorf("invalid hash for SSLv3: '%s'", *mac) + } + digest = ssl30MAC(hash, macKey, input, adFull) + } else { + h := hmac.New(hash.New, macKey) + h.Write(adFull) + h.Write(input) + digest = h.Sum(nil) + } + + size := getKeySize(*bulkCipher) + if size == 0 { + return nil, fmt.Errorf("unknown cipher '%s'", *bulkCipher) + } + encKey := make([]byte, size) + rand.fillBytes(encKey) + + var fixedIV []byte + var nonce []byte + var sealed []byte + var noSeal, fails bool + if *bulkCipher == "rc4" { + if *implicitIV { + return nil, fmt.Errorf("implicit IV enabled on a stream cipher") + } + + stream, err := rc4.NewCipher(encKey) + if err != nil { + return nil, err + } + + sealed = make([]byte, 0, len(input)+len(digest)) + sealed = append(sealed, input...) + sealed = append(sealed, digest...) + stream.XORKeyStream(sealed, sealed) + } else { + block, err := newBlockCipher(*bulkCipher, encKey) + if err != nil { + return nil, err + } + + iv := make([]byte, block.BlockSize()) + rand.fillBytes(iv) + if *implicitIV || *ssl3 { + fixedIV = iv + } else { + nonce = iv + } + + cbc := cipher.NewCBCEncrypter(block, iv) + + sealed = make([]byte, 0, len(input)+len(digest)+cbc.BlockSize()) + sealed = append(sealed, input...) + sealed = append(sealed, digest...) + paddingLen := cbc.BlockSize() - (len(sealed) % cbc.BlockSize()) + if options.noPadding { + if paddingLen != cbc.BlockSize() { + return nil, fmt.Errorf("invalid length for noPadding") + } + noSeal = true + fails = true + } else { + if options.extraPadding { + paddingLen += cbc.BlockSize() + noSeal = true + if *ssl3 { + // SSLv3 padding must be minimal. + fails = true + } + } + if *ssl3 { + sealed = append(sealed, make([]byte, paddingLen-1)...) + sealed = append(sealed, byte(paddingLen-1)) + } else { + pad := make([]byte, paddingLen) + for i := range pad { + pad[i] = byte(paddingLen - 1) + } + sealed = append(sealed, pad...) + } + if options.wrongPadding && paddingLen > 1 { + sealed[len(sealed)-2]++ + noSeal = true + if !*ssl3 { + // TLS specifies the all the padding bytes. + fails = true + } + } + } + cbc.CryptBlocks(sealed, sealed) + } + + key := make([]byte, 0, len(macKey)+len(encKey)+len(fixedIV)) + key = append(key, macKey...) + key = append(key, encKey...) + key = append(key, fixedIV...) + t := &testCase{ + digest: digest, + key: key, + nonce: nonce, + input: input, + ad: ad, + ciphertext: sealed[:len(sealed)-hash.Size()], + tag: sealed[len(sealed)-hash.Size():], + noSeal: noSeal, + fails: fails, + } + return t, nil +} + +func printTestCase(t *testCase) { + fmt.Printf("# DIGEST: %s\n", hex.EncodeToString(t.digest)) + fmt.Printf("KEY: %s\n", hex.EncodeToString(t.key)) + fmt.Printf("NONCE: %s\n", hex.EncodeToString(t.nonce)) + fmt.Printf("IN: %s\n", hex.EncodeToString(t.input)) + fmt.Printf("AD: %s\n", hex.EncodeToString(t.ad)) + fmt.Printf("CT: %s\n", hex.EncodeToString(t.ciphertext)) + fmt.Printf("TAG: %s\n", hex.EncodeToString(t.tag)) + if t.noSeal { + fmt.Printf("NO_SEAL: 01\n") + } + if t.fails { + fmt.Printf("FAILS: 01\n") + } +} + +func main() { + flag.Parse() + + commandLine := fmt.Sprintf("go run make_legacy_aead_tests.go -cipher %s -mac %s", *bulkCipher, *mac) + if *implicitIV { + commandLine += " -implicit-iv" + } + if *ssl3 { + commandLine += " -ssl3" + } + fmt.Printf("# Generated by\n") + fmt.Printf("# %s\n", commandLine) + fmt.Printf("#\n") + fmt.Printf("# Note: aead_test's input format splits the ciphertext and tag positions of the sealed\n") + fmt.Printf("# input. But these legacy AEADs are MAC-then-encrypt and may include padding, so this\n") + fmt.Printf("# split isn't meaningful. The unencrypted MAC is included in the 'DIGEST' tag above\n") + fmt.Printf("# each test case.\n") + fmt.Printf("\n") + + // For CBC-mode ciphers, emit tests for padding flexibility. + if *bulkCipher != "rc4" { + fmt.Printf("# Test with non-minimal padding.\n") + t, err := makeTestCase(5, options{extraPadding: true}) + if err != nil { + fmt.Fprintf(os.Stderr, "%s\n", err) + os.Exit(1) + } + printTestCase(t) + fmt.Printf("\n") + + fmt.Printf("# Test with bad padding values.\n") + t, err = makeTestCase(5, options{wrongPadding: true}) + if err != nil { + fmt.Fprintf(os.Stderr, "%s\n", err) + os.Exit(1) + } + printTestCase(t) + fmt.Printf("\n") + + fmt.Printf("# Test with no padding.\n") + hash, ok := getHash(*mac) + if !ok { + panic("unknown hash") + } + t, err = makeTestCase(64-hash.Size(), options{noPadding: true}) + if err != nil { + fmt.Fprintf(os.Stderr, "%s\n", err) + os.Exit(1) + } + printTestCase(t) + fmt.Printf("\n") + } + + // Generate long enough of input to cover a non-zero num_starting_blocks + // value in the constant-time CBC logic. + for l := 0; l < 500; l += 5 { + t, err := makeTestCase(l, options{}) + if err != nil { + fmt.Fprintf(os.Stderr, "%s\n", err) + os.Exit(1) + } + printTestCase(t) + fmt.Printf("\n") + } +} diff --git a/external/boringssl/crypto/cipher/test/rc4_md5_ssl3_tests.txt.REMOVED.git-id b/external/boringssl/crypto/cipher/test/rc4_md5_ssl3_tests.txt.REMOVED.git-id new file mode 100644 index 0000000000..f71b0c1b11 --- /dev/null +++ b/external/boringssl/crypto/cipher/test/rc4_md5_ssl3_tests.txt.REMOVED.git-id @@ -0,0 +1 @@ +329569a7682f7f6cbff0102a8c3502c346a38ff6 \ No newline at end of file diff --git a/external/boringssl/crypto/cipher/test/rc4_md5_tls_tests.txt.REMOVED.git-id b/external/boringssl/crypto/cipher/test/rc4_md5_tls_tests.txt.REMOVED.git-id new file mode 100644 index 0000000000..ecd58616cb --- /dev/null +++ b/external/boringssl/crypto/cipher/test/rc4_md5_tls_tests.txt.REMOVED.git-id @@ -0,0 +1 @@ +26a282453f1cebb74b7adc35e18094291aeb913b \ No newline at end of file diff --git a/external/boringssl/crypto/cipher/test/rc4_sha1_ssl3_tests.txt.REMOVED.git-id b/external/boringssl/crypto/cipher/test/rc4_sha1_ssl3_tests.txt.REMOVED.git-id new file mode 100644 index 0000000000..5917cc9282 --- /dev/null +++ b/external/boringssl/crypto/cipher/test/rc4_sha1_ssl3_tests.txt.REMOVED.git-id @@ -0,0 +1 @@ +721cef958939be2ab9dae1d470cd485a7d45f60a \ No newline at end of file diff --git a/external/boringssl/crypto/cipher/test/rc4_sha1_tls_tests.txt.REMOVED.git-id b/external/boringssl/crypto/cipher/test/rc4_sha1_tls_tests.txt.REMOVED.git-id new file mode 100644 index 0000000000..3386996462 --- /dev/null +++ b/external/boringssl/crypto/cipher/test/rc4_sha1_tls_tests.txt.REMOVED.git-id @@ -0,0 +1 @@ +fd80f2ba8af7094d6ca3bf2056bdee98d8313e2f \ No newline at end of file diff --git a/external/boringssl/crypto/cipher/tls_cbc.c b/external/boringssl/crypto/cipher/tls_cbc.c new file mode 100644 index 0000000000..fbc93fa607 --- /dev/null +++ b/external/boringssl/crypto/cipher/tls_cbc.c @@ -0,0 +1,564 @@ +/* ==================================================================== + * Copyright (c) 2012 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include +#include + +#include +#include +#include + +#include "../internal.h" +#include "internal.h" + + +/* TODO(davidben): unsigned should be size_t. The various constant_time + * functions need to be switched to size_t. */ + +/* MAX_HASH_BIT_COUNT_BYTES is the maximum number of bytes in the hash's length + * field. (SHA-384/512 have 128-bit length.) */ +#define MAX_HASH_BIT_COUNT_BYTES 16 + +/* MAX_HASH_BLOCK_SIZE is the maximum hash block size that we'll support. + * Currently SHA-384/512 has a 128-byte block size and that's the largest + * supported by TLS.) */ +#define MAX_HASH_BLOCK_SIZE 128 + +int EVP_tls_cbc_remove_padding(unsigned *out_len, + const uint8_t *in, unsigned in_len, + unsigned block_size, unsigned mac_size) { + unsigned padding_length, good, to_check, i; + const unsigned overhead = 1 /* padding length byte */ + mac_size; + + /* These lengths are all public so we can test them in non-constant time. */ + if (overhead > in_len) { + return 0; + } + + padding_length = in[in_len - 1]; + + good = constant_time_ge(in_len, overhead + padding_length); + /* The padding consists of a length byte at the end of the record and + * then that many bytes of padding, all with the same value as the + * length byte. Thus, with the length byte included, there are i+1 + * bytes of padding. + * + * We can't check just |padding_length+1| bytes because that leaks + * decrypted information. Therefore we always have to check the maximum + * amount of padding possible. (Again, the length of the record is + * public information so we can use it.) */ + to_check = 256; /* maximum amount of padding, inc length byte. */ + if (to_check > in_len) { + to_check = in_len; + } + + for (i = 0; i < to_check; i++) { + uint8_t mask = constant_time_ge_8(padding_length, i); + uint8_t b = in[in_len - 1 - i]; + /* The final |padding_length+1| bytes should all have the value + * |padding_length|. Therefore the XOR should be zero. */ + good &= ~(mask & (padding_length ^ b)); + } + + /* If any of the final |padding_length+1| bytes had the wrong value, + * one or more of the lower eight bits of |good| will be cleared. */ + good = constant_time_eq(0xff, good & 0xff); + + /* Always treat |padding_length| as zero on error. If, assuming block size of + * 16, a padding of [<15 arbitrary bytes> 15] treated |padding_length| as 16 + * and returned -1, distinguishing good MAC and bad padding from bad MAC and + * bad padding would give POODLE's padding oracle. */ + padding_length = good & (padding_length + 1); + *out_len = in_len - padding_length; + + return constant_time_select_int(good, 1, -1); +} + +/* If CBC_MAC_ROTATE_IN_PLACE is defined then EVP_tls_cbc_copy_mac is performed + * with variable accesses in a 64-byte-aligned buffer. Assuming that this fits + * into a single or pair of cache-lines, then the variable memory accesses don't + * actually affect the timing. CPUs with smaller cache-lines [if any] are not + * multi-core and are not considered vulnerable to cache-timing attacks. */ +#define CBC_MAC_ROTATE_IN_PLACE + +void EVP_tls_cbc_copy_mac(uint8_t *out, unsigned md_size, + const uint8_t *in, unsigned in_len, + unsigned orig_len) { +#if defined(CBC_MAC_ROTATE_IN_PLACE) + uint8_t rotated_mac_buf[64 + EVP_MAX_MD_SIZE]; + uint8_t *rotated_mac; +#else + uint8_t rotated_mac[EVP_MAX_MD_SIZE]; +#endif + + /* mac_end is the index of |in| just after the end of the MAC. */ + unsigned mac_end = in_len; + unsigned mac_start = mac_end - md_size; + /* scan_start contains the number of bytes that we can ignore because + * the MAC's position can only vary by 255 bytes. */ + unsigned scan_start = 0; + unsigned i, j; + unsigned rotate_offset; + + assert(orig_len >= in_len); + assert(in_len >= md_size); + assert(md_size <= EVP_MAX_MD_SIZE); + +#if defined(CBC_MAC_ROTATE_IN_PLACE) + rotated_mac = rotated_mac_buf + ((0 - (size_t)rotated_mac_buf) & 63); +#endif + + /* This information is public so it's safe to branch based on it. */ + if (orig_len > md_size + 255 + 1) { + scan_start = orig_len - (md_size + 255 + 1); + } + + /* Ideally the next statement would be: + * + * rotate_offset = (mac_start - scan_start) % md_size; + * + * However, division is not a constant-time operation (at least on Intel + * chips). Thus we enumerate the possible values of md_size and handle each + * separately. The value of |md_size| is public information (it's determined + * by the cipher suite in the ServerHello) so our timing can vary based on + * its value. */ + + rotate_offset = mac_start - scan_start; + /* rotate_offset can be, at most, 255 (bytes of padding) + 1 (padding length) + * + md_size = 256 + 48 (since SHA-384 is the largest hash) = 304. */ + assert(rotate_offset <= 304); + + /* Below is an SMT-LIB2 verification that the Barrett reductions below are + * correct within this range: + * + * (define-fun barrett ( + * (x (_ BitVec 32)) + * (mul (_ BitVec 32)) + * (shift (_ BitVec 32)) + * (divisor (_ BitVec 32)) ) (_ BitVec 32) + * (let ((q (bvsub x (bvmul divisor (bvlshr (bvmul x mul) shift))) )) + * (ite (bvuge q divisor) + * (bvsub q divisor) + * q))) + * + * (declare-fun x () (_ BitVec 32)) + * + * (assert (or + * (let ( + * (divisor (_ bv20 32)) + * (mul (_ bv25 32)) + * (shift (_ bv9 32)) + * (limit (_ bv853 32))) + * + * (and (bvule x limit) (not (= (bvurem x divisor) + * (barrett x mul shift divisor))))) + * + * (let ( + * (divisor (_ bv48 32)) + * (mul (_ bv10 32)) + * (shift (_ bv9 32)) + * (limit (_ bv768 32))) + * + * (and (bvule x limit) (not (= (bvurem x divisor) + * (barrett x mul shift divisor))))) + * )) + * + * (check-sat) + * (get-model) + */ + + if (md_size == 16) { + rotate_offset &= 15; + } else if (md_size == 20) { + /* 1/20 is approximated as 25/512 and then Barrett reduction is used. + * Analytically, this is correct for 0 <= rotate_offset <= 853. */ + unsigned q = (rotate_offset * 25) >> 9; + rotate_offset -= q * 20; + rotate_offset -= + constant_time_select(constant_time_ge(rotate_offset, 20), 20, 0); + } else if (md_size == 32) { + rotate_offset &= 31; + } else if (md_size == 48) { + /* 1/48 is approximated as 10/512 and then Barrett reduction is used. + * Analytically, this is correct for 0 <= rotate_offset <= 768. */ + unsigned q = (rotate_offset * 10) >> 9; + rotate_offset -= q * 48; + rotate_offset -= + constant_time_select(constant_time_ge(rotate_offset, 48), 48, 0); + } else { + /* This should be impossible therefore this path doesn't run in constant + * time. */ + assert(0); + rotate_offset = rotate_offset % md_size; + } + + memset(rotated_mac, 0, md_size); + for (i = scan_start, j = 0; i < orig_len; i++) { + uint8_t mac_started = constant_time_ge_8(i, mac_start); + uint8_t mac_ended = constant_time_ge_8(i, mac_end); + uint8_t b = in[i]; + rotated_mac[j++] |= b & mac_started & ~mac_ended; + j &= constant_time_lt(j, md_size); + } + +/* Now rotate the MAC */ +#if defined(CBC_MAC_ROTATE_IN_PLACE) + j = 0; + for (i = 0; i < md_size; i++) { + /* in case cache-line is 32 bytes, touch second line */ + ((volatile uint8_t *)rotated_mac)[rotate_offset ^ 32]; + out[j++] = rotated_mac[rotate_offset++]; + rotate_offset &= constant_time_lt(rotate_offset, md_size); + } +#else + memset(out, 0, md_size); + rotate_offset = md_size - rotate_offset; + rotate_offset &= constant_time_lt(rotate_offset, md_size); + for (i = 0; i < md_size; i++) { + for (j = 0; j < md_size; j++) { + out[j] |= rotated_mac[i] & constant_time_eq_8(j, rotate_offset); + } + rotate_offset++; + rotate_offset &= constant_time_lt(rotate_offset, md_size); + } +#endif +} + +/* u32toBE serialises an unsigned, 32-bit number (n) as four bytes at (p) in + * big-endian order. The value of p is advanced by four. */ +#define u32toBE(n, p) \ + (*((p)++)=(uint8_t)(n>>24), \ + *((p)++)=(uint8_t)(n>>16), \ + *((p)++)=(uint8_t)(n>>8), \ + *((p)++)=(uint8_t)(n)) + +/* u64toBE serialises an unsigned, 64-bit number (n) as eight bytes at (p) in + * big-endian order. The value of p is advanced by eight. */ +#define u64toBE(n, p) \ + (*((p)++)=(uint8_t)(n>>56), \ + *((p)++)=(uint8_t)(n>>48), \ + *((p)++)=(uint8_t)(n>>40), \ + *((p)++)=(uint8_t)(n>>32), \ + *((p)++)=(uint8_t)(n>>24), \ + *((p)++)=(uint8_t)(n>>16), \ + *((p)++)=(uint8_t)(n>>8), \ + *((p)++)=(uint8_t)(n)) + +/* These functions serialize the state of a hash and thus perform the standard + * "final" operation without adding the padding and length that such a function + * typically does. */ +static void tls1_sha1_final_raw(void *ctx, uint8_t *md_out) { + SHA_CTX *sha1 = ctx; + u32toBE(sha1->h[0], md_out); + u32toBE(sha1->h[1], md_out); + u32toBE(sha1->h[2], md_out); + u32toBE(sha1->h[3], md_out); + u32toBE(sha1->h[4], md_out); +} +#define LARGEST_DIGEST_CTX SHA_CTX + +static void tls1_sha256_final_raw(void *ctx, uint8_t *md_out) { + SHA256_CTX *sha256 = ctx; + unsigned i; + + for (i = 0; i < 8; i++) { + u32toBE(sha256->h[i], md_out); + } +} +#undef LARGEST_DIGEST_CTX +#define LARGEST_DIGEST_CTX SHA256_CTX + +static void tls1_sha512_final_raw(void *ctx, uint8_t *md_out) { + SHA512_CTX *sha512 = ctx; + unsigned i; + + for (i = 0; i < 8; i++) { + u64toBE(sha512->h[i], md_out); + } +} +#undef LARGEST_DIGEST_CTX +#define LARGEST_DIGEST_CTX SHA512_CTX + +int EVP_tls_cbc_record_digest_supported(const EVP_MD *md) { + switch (EVP_MD_type(md)) { + case NID_sha1: + case NID_sha256: + case NID_sha384: + return 1; + + default: + return 0; + } +} + +int EVP_tls_cbc_digest_record(const EVP_MD *md, uint8_t *md_out, + size_t *md_out_size, const uint8_t header[13], + const uint8_t *data, size_t data_plus_mac_size, + size_t data_plus_mac_plus_padding_size, + const uint8_t *mac_secret, + unsigned mac_secret_length) { + union { + double align; + uint8_t c[sizeof(LARGEST_DIGEST_CTX)]; + } md_state; + void (*md_final_raw)(void *ctx, uint8_t *md_out); + void (*md_transform)(void *ctx, const uint8_t *block); + unsigned md_size, md_block_size = 64; + unsigned len, max_mac_bytes, num_blocks, num_starting_blocks, k, + mac_end_offset, c, index_a, index_b; + unsigned int bits; /* at most 18 bits */ + uint8_t length_bytes[MAX_HASH_BIT_COUNT_BYTES]; + /* hmac_pad is the masked HMAC key. */ + uint8_t hmac_pad[MAX_HASH_BLOCK_SIZE]; + uint8_t first_block[MAX_HASH_BLOCK_SIZE]; + uint8_t mac_out[EVP_MAX_MD_SIZE]; + unsigned i, j, md_out_size_u; + EVP_MD_CTX md_ctx; + /* mdLengthSize is the number of bytes in the length field that terminates + * the hash. */ + unsigned md_length_size = 8; + + /* This is a, hopefully redundant, check that allows us to forget about + * many possible overflows later in this function. */ + assert(data_plus_mac_plus_padding_size < 1024 * 1024); + + switch (EVP_MD_type(md)) { + case NID_sha1: + SHA1_Init((SHA_CTX *)md_state.c); + md_final_raw = tls1_sha1_final_raw; + md_transform = + (void (*)(void *ctx, const uint8_t *block))SHA1_Transform; + md_size = 20; + break; + + case NID_sha256: + SHA256_Init((SHA256_CTX *)md_state.c); + md_final_raw = tls1_sha256_final_raw; + md_transform = + (void (*)(void *ctx, const uint8_t *block))SHA256_Transform; + md_size = 32; + break; + + case NID_sha384: + SHA384_Init((SHA512_CTX *)md_state.c); + md_final_raw = tls1_sha512_final_raw; + md_transform = + (void (*)(void *ctx, const uint8_t *block))SHA512_Transform; + md_size = 384 / 8; + md_block_size = 128; + md_length_size = 16; + break; + + default: + /* EVP_tls_cbc_record_digest_supported should have been called first to + * check that the hash function is supported. */ + assert(0); + *md_out_size = 0; + return 0; + } + + assert(md_length_size <= MAX_HASH_BIT_COUNT_BYTES); + assert(md_block_size <= MAX_HASH_BLOCK_SIZE); + assert(md_size <= EVP_MAX_MD_SIZE); + + static const unsigned kHeaderLength = 13; + + /* kVarianceBlocks is the number of blocks of the hash that we have to + * calculate in constant time because they could be altered by the + * padding value. + * + * TLSv1 has MACs up to 48 bytes long (SHA-384) and the padding is not + * required to be minimal. Therefore we say that the final six blocks + * can vary based on the padding. */ + static const unsigned kVarianceBlocks = 6; + + /* From now on we're dealing with the MAC, which conceptually has 13 + * bytes of `header' before the start of the data. */ + len = data_plus_mac_plus_padding_size + kHeaderLength; + /* max_mac_bytes contains the maximum bytes of bytes in the MAC, including + * |header|, assuming that there's no padding. */ + max_mac_bytes = len - md_size - 1; + /* num_blocks is the maximum number of hash blocks. */ + num_blocks = + (max_mac_bytes + 1 + md_length_size + md_block_size - 1) / md_block_size; + /* In order to calculate the MAC in constant time we have to handle + * the final blocks specially because the padding value could cause the + * end to appear somewhere in the final |kVarianceBlocks| blocks and we + * can't leak where. However, |num_starting_blocks| worth of data can + * be hashed right away because no padding value can affect whether + * they are plaintext. */ + num_starting_blocks = 0; + /* k is the starting byte offset into the conceptual header||data where + * we start processing. */ + k = 0; + /* mac_end_offset is the index just past the end of the data to be + * MACed. */ + mac_end_offset = data_plus_mac_size + kHeaderLength - md_size; + /* c is the index of the 0x80 byte in the final hash block that + * contains application data. */ + c = mac_end_offset % md_block_size; + /* index_a is the hash block number that contains the 0x80 terminating + * value. */ + index_a = mac_end_offset / md_block_size; + /* index_b is the hash block number that contains the 64-bit hash + * length, in bits. */ + index_b = (mac_end_offset + md_length_size) / md_block_size; + /* bits is the hash-length in bits. It includes the additional hash + * block for the masked HMAC key. */ + + if (num_blocks > kVarianceBlocks) { + num_starting_blocks = num_blocks - kVarianceBlocks; + k = md_block_size * num_starting_blocks; + } + + bits = 8 * mac_end_offset; + + /* Compute the initial HMAC block. */ + bits += 8 * md_block_size; + memset(hmac_pad, 0, md_block_size); + assert(mac_secret_length <= sizeof(hmac_pad)); + memcpy(hmac_pad, mac_secret, mac_secret_length); + for (i = 0; i < md_block_size; i++) { + hmac_pad[i] ^= 0x36; + } + + md_transform(md_state.c, hmac_pad); + + memset(length_bytes, 0, md_length_size - 4); + length_bytes[md_length_size - 4] = (uint8_t)(bits >> 24); + length_bytes[md_length_size - 3] = (uint8_t)(bits >> 16); + length_bytes[md_length_size - 2] = (uint8_t)(bits >> 8); + length_bytes[md_length_size - 1] = (uint8_t)bits; + + if (k > 0) { + /* k is a multiple of md_block_size. */ + memcpy(first_block, header, 13); + memcpy(first_block + 13, data, md_block_size - 13); + md_transform(md_state.c, first_block); + for (i = 1; i < k / md_block_size; i++) { + md_transform(md_state.c, data + md_block_size * i - 13); + } + } + + memset(mac_out, 0, sizeof(mac_out)); + + /* We now process the final hash blocks. For each block, we construct + * it in constant time. If the |i==index_a| then we'll include the 0x80 + * bytes and zero pad etc. For each block we selectively copy it, in + * constant time, to |mac_out|. */ + for (i = num_starting_blocks; i <= num_starting_blocks + kVarianceBlocks; + i++) { + uint8_t block[MAX_HASH_BLOCK_SIZE]; + uint8_t is_block_a = constant_time_eq_8(i, index_a); + uint8_t is_block_b = constant_time_eq_8(i, index_b); + for (j = 0; j < md_block_size; j++) { + uint8_t b = 0, is_past_c, is_past_cp1; + if (k < kHeaderLength) { + b = header[k]; + } else if (k < data_plus_mac_plus_padding_size + kHeaderLength) { + b = data[k - kHeaderLength]; + } + k++; + + is_past_c = is_block_a & constant_time_ge_8(j, c); + is_past_cp1 = is_block_a & constant_time_ge_8(j, c + 1); + /* If this is the block containing the end of the + * application data, and we are at the offset for the + * 0x80 value, then overwrite b with 0x80. */ + b = constant_time_select_8(is_past_c, 0x80, b); + /* If this the the block containing the end of the + * application data and we're past the 0x80 value then + * just write zero. */ + b = b & ~is_past_cp1; + /* If this is index_b (the final block), but not + * index_a (the end of the data), then the 64-bit + * length didn't fit into index_a and we're having to + * add an extra block of zeros. */ + b &= ~is_block_b | is_block_a; + + /* The final bytes of one of the blocks contains the + * length. */ + if (j >= md_block_size - md_length_size) { + /* If this is index_b, write a length byte. */ + b = constant_time_select_8( + is_block_b, length_bytes[j - (md_block_size - md_length_size)], b); + } + block[j] = b; + } + + md_transform(md_state.c, block); + md_final_raw(md_state.c, block); + /* If this is index_b, copy the hash value to |mac_out|. */ + for (j = 0; j < md_size; j++) { + mac_out[j] |= block[j] & is_block_b; + } + } + + EVP_MD_CTX_init(&md_ctx); + if (!EVP_DigestInit_ex(&md_ctx, md, NULL /* engine */)) { + EVP_MD_CTX_cleanup(&md_ctx); + return 0; + } + + /* Complete the HMAC in the standard manner. */ + for (i = 0; i < md_block_size; i++) { + hmac_pad[i] ^= 0x6a; + } + + EVP_DigestUpdate(&md_ctx, hmac_pad, md_block_size); + EVP_DigestUpdate(&md_ctx, mac_out, md_size); + EVP_DigestFinal(&md_ctx, md_out, &md_out_size_u); + *md_out_size = md_out_size_u; + EVP_MD_CTX_cleanup(&md_ctx); + + return 1; +} diff --git a/external/boringssl/crypto/cmac/CMakeLists.txt b/external/boringssl/crypto/cmac/CMakeLists.txt new file mode 100644 index 0000000000..0c3bf0d192 --- /dev/null +++ b/external/boringssl/crypto/cmac/CMakeLists.txt @@ -0,0 +1,22 @@ +include_directories(../../include) + +add_library( + cmac + + OBJECT + + cmac.c +) + +if(ENABLE_TESTS) +add_executable( + cmac_test + + cmac_test.cc + + $ +) + +target_link_libraries(cmac_test crypto) +add_dependencies(all_tests cmac_test) +endif() diff --git a/external/boringssl/crypto/cmac/cmac.c b/external/boringssl/crypto/cmac/cmac.c new file mode 100644 index 0000000000..fa4c3c49b9 --- /dev/null +++ b/external/boringssl/crypto/cmac/cmac.c @@ -0,0 +1,239 @@ +/* ==================================================================== + * Copyright (c) 2010 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== */ + +#include + +#include +#include + +#include +#include +#include + + +struct cmac_ctx_st { + EVP_CIPHER_CTX cipher_ctx; + /* k1 and k2 are the CMAC subkeys. See + * https://tools.ietf.org/html/rfc4493#section-2.3 */ + uint8_t k1[AES_BLOCK_SIZE]; + uint8_t k2[AES_BLOCK_SIZE]; + /* Last (possibly partial) scratch */ + uint8_t block[AES_BLOCK_SIZE]; + /* block_used contains the number of valid bytes in |block|. */ + unsigned block_used; +}; + +static void CMAC_CTX_init(CMAC_CTX *ctx) { + EVP_CIPHER_CTX_init(&ctx->cipher_ctx); +} + +static void CMAC_CTX_cleanup(CMAC_CTX *ctx) { + EVP_CIPHER_CTX_cleanup(&ctx->cipher_ctx); + OPENSSL_cleanse(ctx->k1, sizeof(ctx->k1)); + OPENSSL_cleanse(ctx->k2, sizeof(ctx->k2)); + OPENSSL_cleanse(ctx->block, sizeof(ctx->block)); +} + +int AES_CMAC(uint8_t out[16], const uint8_t *key, size_t key_len, + const uint8_t *in, size_t in_len) { + const EVP_CIPHER *cipher; + switch (key_len) { + case 16: + cipher = EVP_aes_128_cbc(); + break; + case 32: + cipher = EVP_aes_256_cbc(); + break; + default: + return 0; + } + + size_t scratch_out_len; + CMAC_CTX ctx; + CMAC_CTX_init(&ctx); + + const int ok = CMAC_Init(&ctx, key, key_len, cipher, NULL /* engine */) && + CMAC_Update(&ctx, in, in_len) && + CMAC_Final(&ctx, out, &scratch_out_len); + + CMAC_CTX_cleanup(&ctx); + return ok; +} + +CMAC_CTX *CMAC_CTX_new(void) { + CMAC_CTX *ctx = OPENSSL_malloc(sizeof(*ctx)); + if (ctx != NULL) { + CMAC_CTX_init(ctx); + } + return ctx; +} + +void CMAC_CTX_free(CMAC_CTX *ctx) { + if (ctx == NULL) { + return; + } + + CMAC_CTX_cleanup(ctx); + OPENSSL_free(ctx); +} + +/* binary_field_mul_x treats the 128 bits at |in| as an element of GF(2¹²â¸) + * with a hard-coded reduction polynomial and sets |out| as x times the + * input. + * + * See https://tools.ietf.org/html/rfc4493#section-2.3 */ +static void binary_field_mul_x(uint8_t out[16], const uint8_t in[16]) { + unsigned i; + + /* Shift |in| to left, including carry. */ + for (i = 0; i < 15; i++) { + out[i] = (in[i] << 1) | (in[i+1] >> 7); + } + + /* If MSB set fixup with R. */ + const uint8_t carry = in[0] >> 7; + out[i] = (in[i] << 1) ^ ((0 - carry) & 0x87); +} + +static const uint8_t kZeroIV[AES_BLOCK_SIZE] = {0}; + +int CMAC_Init(CMAC_CTX *ctx, const void *key, size_t key_len, + const EVP_CIPHER *cipher, ENGINE *engine) { + uint8_t scratch[AES_BLOCK_SIZE]; + + if (EVP_CIPHER_block_size(cipher) != AES_BLOCK_SIZE || + EVP_CIPHER_key_length(cipher) != key_len || + !EVP_EncryptInit_ex(&ctx->cipher_ctx, cipher, NULL, key, kZeroIV) || + !EVP_Cipher(&ctx->cipher_ctx, scratch, kZeroIV, AES_BLOCK_SIZE) || + /* Reset context again ready for first data. */ + !EVP_EncryptInit_ex(&ctx->cipher_ctx, NULL, NULL, NULL, kZeroIV)) { + return 0; + } + + binary_field_mul_x(ctx->k1, scratch); + binary_field_mul_x(ctx->k2, ctx->k1); + ctx->block_used = 0; + + return 1; +} + +int CMAC_Reset(CMAC_CTX *ctx) { + ctx->block_used = 0; + return EVP_EncryptInit_ex(&ctx->cipher_ctx, NULL, NULL, NULL, kZeroIV); +} + +int CMAC_Update(CMAC_CTX *ctx, const uint8_t *in, size_t in_len) { + uint8_t scratch[AES_BLOCK_SIZE]; + + if (ctx->block_used > 0) { + size_t todo = AES_BLOCK_SIZE - ctx->block_used; + if (in_len < todo) { + todo = in_len; + } + + memcpy(ctx->block + ctx->block_used, in, todo); + in += todo; + in_len -= todo; + ctx->block_used += todo; + + /* If |in_len| is zero then either |ctx->block_used| is less than + * |AES_BLOCK_SIZE|, in which case we can stop here, or |ctx->block_used| + * is exactly |AES_BLOCK_SIZE| but there's no more data to process. In the + * latter case we don't want to process this block now because it might be + * the last block and that block is treated specially. */ + if (in_len == 0) { + return 1; + } + + assert(ctx->block_used == AES_BLOCK_SIZE); + + if (!EVP_Cipher(&ctx->cipher_ctx, scratch, ctx->block, AES_BLOCK_SIZE)) { + return 0; + } + } + + /* Encrypt all but one of the remaining blocks. */ + while (in_len > AES_BLOCK_SIZE) { + if (!EVP_Cipher(&ctx->cipher_ctx, scratch, in, AES_BLOCK_SIZE)) { + return 0; + } + in += AES_BLOCK_SIZE; + in_len -= AES_BLOCK_SIZE; + } + + memcpy(ctx->block, in, in_len); + ctx->block_used = in_len; + + return 1; +} + +int CMAC_Final(CMAC_CTX *ctx, uint8_t *out, size_t *out_len) { + *out_len = AES_BLOCK_SIZE; + if (out == NULL) { + return 1; + } + + const uint8_t *mask = ctx->k1; + + if (ctx->block_used != AES_BLOCK_SIZE) { + /* If the last block is incomplete, terminate it with a single 'one' bit + * followed by zeros. */ + ctx->block[ctx->block_used] = 0x80; + memset(ctx->block + ctx->block_used + 1, 0, + AES_BLOCK_SIZE - (ctx->block_used + 1)); + + mask = ctx->k2; + } + + unsigned i; + for (i = 0; i < AES_BLOCK_SIZE; i++) { + out[i] = ctx->block[i] ^ mask[i]; + } + + return EVP_Cipher(&ctx->cipher_ctx, out, out, AES_BLOCK_SIZE); +} diff --git a/external/boringssl/crypto/cmac/cmac_test.cc b/external/boringssl/crypto/cmac/cmac_test.cc new file mode 100644 index 0000000000..2496f2a92e --- /dev/null +++ b/external/boringssl/crypto/cmac/cmac_test.cc @@ -0,0 +1,151 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include + +#include + +#include "../test/scoped_types.h" +#include "../test/test_util.h" + + +static void dump(const uint8_t *got, const uint8_t *want, size_t len) { + hexdump(stderr, "got :", got, len); + hexdump(stderr, "want:", want, len); + fflush(stderr); +} + +static int test(const char *name, const uint8_t *key, size_t key_len, + const uint8_t *msg, size_t msg_len, const uint8_t *expected) { + uint8_t out[16]; + + if (!AES_CMAC(out, key, key_len, msg, msg_len)) { + fprintf(stderr, "%s: AES_CMAC failed\n", name); + return 0; + } + + if (CRYPTO_memcmp(out, expected, sizeof(out)) != 0) { + fprintf(stderr, "%s: CMAC result differs:\n", name); + dump(out, expected, sizeof(out)); + return 0; + } + + ScopedCMAC_CTX ctx(CMAC_CTX_new()); + if (!ctx || !CMAC_Init(ctx.get(), key, key_len, EVP_aes_128_cbc(), NULL)) { + fprintf(stderr, "%s: CMAC_Init failed.\n", name); + return 0; + } + + for (unsigned chunk_size = 1; chunk_size <= msg_len; chunk_size++) { + if (!CMAC_Reset(ctx.get())) { + fprintf(stderr, "%s/%u: CMAC_Reset failed.\n", name, chunk_size); + return 0; + } + + size_t done = 0; + while (done < msg_len) { + size_t todo = std::min(msg_len - done, static_cast(chunk_size)); + if (!CMAC_Update(ctx.get(), msg + done, todo)) { + fprintf(stderr, "%s/%u: CMAC_Update failed.\n", name, chunk_size); + return 0; + } + + done += todo; + } + + size_t out_len; + if (!CMAC_Final(ctx.get(), out, &out_len)) { + fprintf(stderr, "%s/%u: CMAC_Final failed.\n", name, chunk_size); + return 0; + } + + if (out_len != sizeof(out)) { + fprintf(stderr, "%s/%u: incorrect out_len: %u.\n", name, chunk_size, + static_cast(out_len)); + return 0; + } + + if (CRYPTO_memcmp(out, expected, sizeof(out)) != 0) { + fprintf(stderr, "%s/%u: CMAC result differs:\n", name, chunk_size); + dump(out, expected, sizeof(out)); + return 0; + } + } + + return 1; +} + +static int rfc_4493_test_vectors(void) { + static const uint8_t kKey[16] = { + 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c, + }; + static const uint8_t kOut1[16] = { + 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28, + 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46, + }; + static const uint8_t kMsg2[] = { + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + }; + static const uint8_t kOut2[16] = { + 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44, + 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c, + }; + static const uint8_t kMsg3[] = { + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, + }; + static const uint8_t kOut3[16] = { + 0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30, + 0x30, 0xca, 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27, + }; + static const uint8_t kMsg4[] = { + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, + 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, + 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, + 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10, + }; + static const uint8_t kOut4[16] = { + 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92, + 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe, + }; + + if (!test("RFC 4493 #1", kKey, sizeof(kKey), NULL, 0, kOut1) || + !test("RFC 4493 #2", kKey, sizeof(kKey), kMsg2, sizeof(kMsg2), kOut2) || + !test("RFC 4493 #3", kKey, sizeof(kKey), kMsg3, sizeof(kMsg3), kOut3) || + !test("RFC 4493 #4", kKey, sizeof(kKey), kMsg4, sizeof(kMsg4), kOut4)) { + return 0; + } + + return 1; +} + +int main(int argc, char **argv) { + if (!rfc_4493_test_vectors()) { + return 1; + } + + printf("PASS\n"); + return 0; +} diff --git a/external/boringssl/crypto/conf/CMakeLists.txt b/external/boringssl/crypto/conf/CMakeLists.txt new file mode 100644 index 0000000000..0a3c79538f --- /dev/null +++ b/external/boringssl/crypto/conf/CMakeLists.txt @@ -0,0 +1,9 @@ +include_directories(../../include) + +add_library( + conf + + OBJECT + + conf.c +) diff --git a/external/boringssl/crypto/conf/conf.c b/external/boringssl/crypto/conf/conf.c new file mode 100644 index 0000000000..e4fc428bb3 --- /dev/null +++ b/external/boringssl/crypto/conf/conf.c @@ -0,0 +1,788 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +#include +#include +#include +#include + +#include "conf_def.h" +#include "internal.h" + + +static uint32_t conf_value_hash(const CONF_VALUE *v) { + return (lh_strhash(v->section) << 2) ^ lh_strhash(v->name); +} + +static int conf_value_cmp(const CONF_VALUE *a, const CONF_VALUE *b) { + int i; + + if (a->section != b->section) { + i = strcmp(a->section, b->section); + if (i) { + return i; + } + } + + if (a->name != NULL && b->name != NULL) { + return strcmp(a->name, b->name); + } else if (a->name == b->name) { + return 0; + } else { + return (a->name == NULL) ? -1 : 1; + } +} + +CONF *NCONF_new(void *method) { + CONF *conf; + + if (method != NULL) { + return NULL; + } + + conf = OPENSSL_malloc(sizeof(CONF)); + if (conf == NULL) { + return NULL; + } + + conf->data = lh_CONF_VALUE_new(conf_value_hash, conf_value_cmp); + if (conf->data == NULL) { + OPENSSL_free(conf); + return NULL; + } + + return conf; +} + +CONF_VALUE *CONF_VALUE_new(void) { + CONF_VALUE *v = OPENSSL_malloc(sizeof(CONF_VALUE)); + if (!v) { + OPENSSL_PUT_ERROR(CONF, ERR_R_MALLOC_FAILURE); + return NULL; + } + memset(v, 0, sizeof(CONF_VALUE)); + return v; +} + +static void value_free_contents(CONF_VALUE *value) { + if (value->section) { + OPENSSL_free(value->section); + } + if (value->name) { + OPENSSL_free(value->name); + if (value->value) { + OPENSSL_free(value->value); + } + } else { + if (value->value) { + sk_CONF_VALUE_free((STACK_OF(CONF_VALUE)*)value->value); + } + } +} + +static void value_free(CONF_VALUE *value) { + value_free_contents(value); + OPENSSL_free(value); +} + +void NCONF_free(CONF *conf) { + if (conf == NULL || conf->data == NULL) { + return; + } + + lh_CONF_VALUE_doall(conf->data, value_free); + lh_CONF_VALUE_free(conf->data); + OPENSSL_free(conf); +} + +static CONF_VALUE *NCONF_new_section(const CONF *conf, const char *section) { + STACK_OF(CONF_VALUE) *sk = NULL; + int ok = 0; + CONF_VALUE *v = NULL, *old_value; + + sk = sk_CONF_VALUE_new_null(); + v = CONF_VALUE_new(); + if (sk == NULL || v == NULL) { + goto err; + } + v->section = OPENSSL_strdup(section); + if (v->section == NULL) { + goto err; + } + + v->name = NULL; + v->value = (char *)sk; + + if (!lh_CONF_VALUE_insert(conf->data, &old_value, v)) { + goto err; + } + if (old_value) { + value_free(old_value); + } + ok = 1; + +err: + if (!ok) { + if (sk != NULL) { + sk_CONF_VALUE_free(sk); + } + if (v != NULL) { + OPENSSL_free(v); + } + v = NULL; + } + return v; +} + +static int str_copy(CONF *conf, char *section, char **pto, char *from) { + int q, r, rr = 0, to = 0, len = 0; + char *s, *e, *rp, *rrp, *np, *cp, v; + const char *p; + BUF_MEM *buf; + + buf = BUF_MEM_new(); + if (buf == NULL) { + return 0; + } + + len = strlen(from) + 1; + if (!BUF_MEM_grow(buf, len)) { + goto err; + } + + for (;;) { + if (IS_QUOTE(conf, *from)) { + q = *from; + from++; + while (!IS_EOF(conf, *from) && (*from != q)) { + if (IS_ESC(conf, *from)) { + from++; + if (IS_EOF(conf, *from)) { + break; + } + } + buf->data[to++] = *(from++); + } + if (*from == q) { + from++; + } + } else if (IS_DQUOTE(conf, *from)) { + q = *from; + from++; + while (!IS_EOF(conf, *from)) { + if (*from == q) { + if (*(from + 1) == q) { + from++; + } else { + break; + } + } + buf->data[to++] = *(from++); + } + if (*from == q) { + from++; + } + } else if (IS_ESC(conf, *from)) { + from++; + v = *(from++); + if (IS_EOF(conf, v)) { + break; + } else if (v == 'r') { + v = '\r'; + } else if (v == 'n') { + v = '\n'; + } else if (v == 'b') { + v = '\b'; + } else if (v == 't') { + v = '\t'; + } + buf->data[to++] = v; + } else if (IS_EOF(conf, *from)) { + break; + } else if (*from == '$') { + /* try to expand it */ + rrp = NULL; + s = &(from[1]); + if (*s == '{') { + q = '}'; + } else if (*s == '(') { + q = ')'; + } else { + q = 0; + } + + if (q) { + s++; + } + cp = section; + e = np = s; + while (IS_ALPHA_NUMERIC(conf, *e)) { + e++; + } + if (e[0] == ':' && e[1] == ':') { + cp = np; + rrp = e; + rr = *e; + *rrp = '\0'; + e += 2; + np = e; + while (IS_ALPHA_NUMERIC(conf, *e)) { + e++; + } + } + r = *e; + *e = '\0'; + rp = e; + if (q) { + if (r != q) { + OPENSSL_PUT_ERROR(CONF, CONF_R_NO_CLOSE_BRACE); + goto err; + } + e++; + } + /* So at this point we have + * np which is the start of the name string which is + * '\0' terminated. + * cp which is the start of the section string which is + * '\0' terminated. + * e is the 'next point after'. + * r and rr are the chars replaced by the '\0' + * rp and rrp is where 'r' and 'rr' came from. */ + p = NCONF_get_string(conf, cp, np); + if (rrp != NULL) { + *rrp = rr; + } + *rp = r; + if (p == NULL) { + OPENSSL_PUT_ERROR(CONF, CONF_R_VARIABLE_HAS_NO_VALUE); + goto err; + } + BUF_MEM_grow_clean(buf, (strlen(p) + buf->length - (e - from))); + while (*p) { + buf->data[to++] = *(p++); + } + + /* Since we change the pointer 'from', we also have + to change the perceived length of the string it + points at. /RL */ + len -= e - from; + from = e; + + /* In case there were no braces or parenthesis around + the variable reference, we have to put back the + character that was replaced with a '\0'. /RL */ + *rp = r; + } else { + buf->data[to++] = *(from++); + } + } + + buf->data[to] = '\0'; + if (*pto != NULL) { + OPENSSL_free(*pto); + } + *pto = buf->data; + OPENSSL_free(buf); + return 1; + +err: + if (buf != NULL) { + BUF_MEM_free(buf); + } + return 0; +} + +static CONF_VALUE *get_section(const CONF *conf, const char *section) { + CONF_VALUE template; + + memset(&template, 0, sizeof(template)); + template.section = (char *) section; + return lh_CONF_VALUE_retrieve(conf->data, &template); +} + +STACK_OF(CONF_VALUE) *NCONF_get_section(const CONF *conf, const char *section) { + CONF_VALUE *section_value = get_section(conf, section); + if (section_value == NULL) { + return NULL; + } + return (STACK_OF(CONF_VALUE)*) section_value->value; +} + +const char *NCONF_get_string(const CONF *conf, const char *section, + const char *name) { + CONF_VALUE template, *value; + + memset(&template, 0, sizeof(template)); + template.section = (char *) section; + template.name = (char *) name; + value = lh_CONF_VALUE_retrieve(conf->data, &template); + if (value == NULL) { + return NULL; + } + return value->value; +} + +static int add_string(const CONF *conf, CONF_VALUE *section, + CONF_VALUE *value) { + STACK_OF(CONF_VALUE) *section_stack = (STACK_OF(CONF_VALUE)*) section->value; + CONF_VALUE *old_value; + + value->section = OPENSSL_strdup(section->section); + if (!sk_CONF_VALUE_push(section_stack, value)) { + return 0; + } + + if (!lh_CONF_VALUE_insert(conf->data, &old_value, value)) { + return 0; + } + if (old_value != NULL) { + (void)sk_CONF_VALUE_delete_ptr(section_stack, old_value); + value_free(old_value); + } + + return 1; +} + +static char *eat_ws(CONF *conf, char *p) { + while (IS_WS(conf, *p) && !IS_EOF(conf, *p)) { + p++; + } + return p; +} + +#define scan_esc(conf, p) (((IS_EOF((conf), (p)[1])) ? ((p) + 1) : ((p) + 2))) + +static char *eat_alpha_numeric(CONF *conf, char *p) { + for (;;) { + if (IS_ESC(conf, *p)) { + p = scan_esc(conf, p); + continue; + } + if (!IS_ALPHA_NUMERIC_PUNCT(conf, *p)) { + return p; + } + p++; + } +} + +static char *scan_quote(CONF *conf, char *p) { + int q = *p; + + p++; + while (!IS_EOF(conf, *p) && *p != q) { + if (IS_ESC(conf, *p)) { + p++; + if (IS_EOF(conf, *p)) { + return p; + } + } + p++; + } + if (*p == q) { + p++; + } + return p; +} + + +static char *scan_dquote(CONF *conf, char *p) { + int q = *p; + + p++; + while (!(IS_EOF(conf, *p))) { + if (*p == q) { + if (*(p + 1) == q) { + p++; + } else { + break; + } + } + p++; + } + if (*p == q) { + p++; + } + return p; +} + +static void clear_comments(CONF *conf, char *p) { + for (;;) { + if (IS_FCOMMENT(conf, *p)) { + *p = '\0'; + return; + } + if (!IS_WS(conf, *p)) { + break; + } + p++; + } + + for (;;) { + if (IS_COMMENT(conf, *p)) { + *p = '\0'; + return; + } + if (IS_DQUOTE(conf, *p)) { + p = scan_dquote(conf, p); + continue; + } + if (IS_QUOTE(conf, *p)) { + p = scan_quote(conf, p); + continue; + } + if (IS_ESC(conf, *p)) { + p = scan_esc(conf, p); + continue; + } + if (IS_EOF(conf, *p)) { + return; + } else { + p++; + } + } +} + +static int def_load_bio(CONF *conf, BIO *in, long *out_error_line) { + static const size_t CONFBUFSIZE = 512; + int bufnum = 0, i, ii; + BUF_MEM *buff = NULL; + char *s, *p, *end; + int again; + long eline = 0; + char btmp[DECIMAL_SIZE(eline) + 1]; + CONF_VALUE *v = NULL, *tv; + CONF_VALUE *sv = NULL; + char *section = NULL, *buf; + char *start, *psection, *pname; + + if ((buff = BUF_MEM_new()) == NULL) { + OPENSSL_PUT_ERROR(CONF, ERR_R_BUF_LIB); + goto err; + } + + section = OPENSSL_strdup("default"); + if (section == NULL) { + OPENSSL_PUT_ERROR(CONF, ERR_R_MALLOC_FAILURE); + goto err; + } + + sv = NCONF_new_section(conf, section); + if (sv == NULL) { + OPENSSL_PUT_ERROR(CONF, CONF_R_UNABLE_TO_CREATE_NEW_SECTION); + goto err; + } + + bufnum = 0; + again = 0; + for (;;) { + if (!BUF_MEM_grow(buff, bufnum + CONFBUFSIZE)) { + OPENSSL_PUT_ERROR(CONF, ERR_R_BUF_LIB); + goto err; + } + p = &(buff->data[bufnum]); + *p = '\0'; + BIO_gets(in, p, CONFBUFSIZE - 1); + p[CONFBUFSIZE - 1] = '\0'; + ii = i = strlen(p); + if (i == 0 && !again) { + break; + } + again = 0; + while (i > 0) { + if ((p[i - 1] != '\r') && (p[i - 1] != '\n')) { + break; + } else { + i--; + } + } + /* we removed some trailing stuff so there is a new + * line on the end. */ + if (ii && i == ii) { + again = 1; /* long line */ + } else { + p[i] = '\0'; + eline++; /* another input line */ + } + + /* we now have a line with trailing \r\n removed */ + + /* i is the number of bytes */ + bufnum += i; + + v = NULL; + /* check for line continuation */ + if (bufnum >= 1) { + /* If we have bytes and the last char '\\' and + * second last char is not '\\' */ + p = &(buff->data[bufnum - 1]); + if (IS_ESC(conf, p[0]) && ((bufnum <= 1) || !IS_ESC(conf, p[-1]))) { + bufnum--; + again = 1; + } + } + if (again) { + continue; + } + bufnum = 0; + buf = buff->data; + + clear_comments(conf, buf); + s = eat_ws(conf, buf); + if (IS_EOF(conf, *s)) { + continue; /* blank line */ + } + if (*s == '[') { + char *ss; + + s++; + start = eat_ws(conf, s); + ss = start; + again: + end = eat_alpha_numeric(conf, ss); + p = eat_ws(conf, end); + if (*p != ']') { + if (*p != '\0' && ss != p) { + ss = p; + goto again; + } + OPENSSL_PUT_ERROR(CONF, CONF_R_MISSING_CLOSE_SQUARE_BRACKET); + goto err; + } + *end = '\0'; + if (!str_copy(conf, NULL, §ion, start)) { + goto err; + } + if ((sv = get_section(conf, section)) == NULL) { + sv = NCONF_new_section(conf, section); + } + if (sv == NULL) { + OPENSSL_PUT_ERROR(CONF, CONF_R_UNABLE_TO_CREATE_NEW_SECTION); + goto err; + } + continue; + } else { + pname = s; + psection = NULL; + end = eat_alpha_numeric(conf, s); + if ((end[0] == ':') && (end[1] == ':')) { + *end = '\0'; + end += 2; + psection = pname; + pname = end; + end = eat_alpha_numeric(conf, end); + } + p = eat_ws(conf, end); + if (*p != '=') { + OPENSSL_PUT_ERROR(CONF, CONF_R_MISSING_EQUAL_SIGN); + goto err; + } + *end = '\0'; + p++; + start = eat_ws(conf, p); + while (!IS_EOF(conf, *p)) { + p++; + } + p--; + while ((p != start) && (IS_WS(conf, *p))) { + p--; + } + p++; + *p = '\0'; + + if (!(v = CONF_VALUE_new())) { + goto err; + } + if (psection == NULL) { + psection = section; + } + v->name = OPENSSL_strdup(pname); + if (v->name == NULL) { + OPENSSL_PUT_ERROR(CONF, ERR_R_MALLOC_FAILURE); + goto err; + } + if (!str_copy(conf, psection, &(v->value), start)) { + goto err; + } + + if (strcmp(psection, section) != 0) { + if ((tv = get_section(conf, psection)) == NULL) { + tv = NCONF_new_section(conf, psection); + } + if (tv == NULL) { + OPENSSL_PUT_ERROR(CONF, CONF_R_UNABLE_TO_CREATE_NEW_SECTION); + goto err; + } + } else { + tv = sv; + } + if (add_string(conf, tv, v) == 0) { + OPENSSL_PUT_ERROR(CONF, ERR_R_MALLOC_FAILURE); + goto err; + } + v = NULL; + } + } + if (buff != NULL) { + BUF_MEM_free(buff); + } + if (section != NULL) { + OPENSSL_free(section); + } + return 1; + +err: + if (buff != NULL) { + BUF_MEM_free(buff); + } + if (section != NULL) { + OPENSSL_free(section); + } + if (out_error_line != NULL) { + *out_error_line = eline; + } + BIO_snprintf(btmp, sizeof btmp, "%ld", eline); + ERR_add_error_data(2, "line ", btmp); + + if (v != NULL) { + if (v->name != NULL) { + OPENSSL_free(v->name); + } + if (v->value != NULL) { + OPENSSL_free(v->value); + } + if (v != NULL) { + OPENSSL_free(v); + } + } + return 0; +} + +int NCONF_load(CONF *conf, const char *filename, long *out_error_line) { + BIO *in = BIO_new_file(filename, "rb"); + int ret; + + if (in == NULL) { + OPENSSL_PUT_ERROR(CONF, ERR_R_SYS_LIB); + return 0; + } + + ret = def_load_bio(conf, in, out_error_line); + BIO_free(in); + + return ret; +} + +int NCONF_load_bio(CONF *conf, BIO *bio, long *out_error_line) { + return def_load_bio(conf, bio, out_error_line); +} + +int CONF_parse_list(const char *list, char sep, int remove_whitespace, + int (*list_cb)(const char *elem, int len, void *usr), + void *arg) { + int ret; + const char *lstart, *tmpend, *p; + + if (list == NULL) { + OPENSSL_PUT_ERROR(CONF, CONF_R_LIST_CANNOT_BE_NULL); + return 0; + } + + lstart = list; + for (;;) { + if (remove_whitespace) { + while (*lstart && isspace((unsigned char)*lstart)) { + lstart++; + } + } + p = strchr(lstart, sep); + if (p == lstart || !*lstart) { + ret = list_cb(NULL, 0, arg); + } else { + if (p) { + tmpend = p - 1; + } else { + tmpend = lstart + strlen(lstart) - 1; + } + if (remove_whitespace) { + while (isspace((unsigned char)*tmpend)) { + tmpend--; + } + } + ret = list_cb(lstart, tmpend - lstart + 1, arg); + } + if (ret <= 0) { + return ret; + } + if (p == NULL) { + return 1; + } + lstart = p + 1; + } +} + +int CONF_modules_load_file(CONF_MUST_BE_NULL *filename, const char *appname, + unsigned long flags) { + return 1; +} + +void CONF_modules_free(void) {} + +void OPENSSL_config(CONF_MUST_BE_NULL *config_name) {} diff --git a/external/boringssl/crypto/conf/conf_def.h b/external/boringssl/crypto/conf/conf_def.h new file mode 100644 index 0000000000..b1e6ba63ac --- /dev/null +++ b/external/boringssl/crypto/conf/conf_def.h @@ -0,0 +1,127 @@ +/* crypto/conf/conf_def.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +/* THIS FILE WAS AUTOMAGICALLY GENERATED! + Please modify and use keysets.pl to regenerate it. */ + +#define CONF_NUMBER 1 +#define CONF_UPPER 2 +#define CONF_LOWER 4 +#define CONF_UNDER 256 +#define CONF_PUNCTUATION 512 +#define CONF_WS 16 +#define CONF_ESC 32 +#define CONF_QUOTE 64 +#define CONF_DQUOTE 1024 +#define CONF_COMMENT 128 +#define CONF_FCOMMENT 2048 +#define CONF_EOF 8 +#define CONF_HIGHBIT 4096 +#define CONF_ALPHA (CONF_UPPER|CONF_LOWER) +#define CONF_ALPHA_NUMERIC (CONF_ALPHA|CONF_NUMBER|CONF_UNDER) +#define CONF_ALPHA_NUMERIC_PUNCT (CONF_ALPHA|CONF_NUMBER|CONF_UNDER| \ + CONF_PUNCTUATION) + +#define KEYTYPES(c) CONF_type_default +#define IS_COMMENT(c,a) (KEYTYPES(c)[(a)&0xff]&CONF_COMMENT) +#define IS_FCOMMENT(c,a) (KEYTYPES(c)[(a)&0xff]&CONF_FCOMMENT) +#define IS_EOF(c,a) (KEYTYPES(c)[(a)&0xff]&CONF_EOF) +#define IS_ESC(c,a) (KEYTYPES(c)[(a)&0xff]&CONF_ESC) +#define IS_NUMBER(c,a) (KEYTYPES(c)[(a)&0xff]&CONF_NUMBER) +#define IS_WS(c,a) (KEYTYPES(c)[(a)&0xff]&CONF_WS) +#define IS_ALPHA_NUMERIC(c,a) (KEYTYPES(c)[(a)&0xff]&CONF_ALPHA_NUMERIC) +#define IS_ALPHA_NUMERIC_PUNCT(c,a) \ + (KEYTYPES(c)[(a)&0xff]&CONF_ALPHA_NUMERIC_PUNCT) +#define IS_QUOTE(c,a) (KEYTYPES(c)[(a)&0xff]&CONF_QUOTE) +#define IS_DQUOTE(c,a) (KEYTYPES(c)[(a)&0xff]&CONF_DQUOTE) +#define IS_HIGHBIT(c,a) (KEYTYPES(c)[(a)&0xff]&CONF_HIGHBIT) + +static const unsigned short CONF_type_default[256]={ + 0x0008,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0010,0x0010,0x0000,0x0000,0x0010,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0010,0x0200,0x0040,0x0080,0x0000,0x0200,0x0200,0x0040, + 0x0000,0x0000,0x0200,0x0200,0x0200,0x0200,0x0200,0x0200, + 0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001, + 0x0001,0x0001,0x0000,0x0200,0x0000,0x0000,0x0000,0x0200, + 0x0200,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002, + 0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002, + 0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002, + 0x0002,0x0002,0x0002,0x0000,0x0020,0x0000,0x0200,0x0100, + 0x0040,0x0004,0x0004,0x0004,0x0004,0x0004,0x0004,0x0004, + 0x0004,0x0004,0x0004,0x0004,0x0004,0x0004,0x0004,0x0004, + 0x0004,0x0004,0x0004,0x0004,0x0004,0x0004,0x0004,0x0004, + 0x0004,0x0004,0x0004,0x0000,0x0200,0x0000,0x0200,0x0000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + }; diff --git a/external/boringssl/crypto/conf/internal.h b/external/boringssl/crypto/conf/internal.h new file mode 100644 index 0000000000..03d1a8f395 --- /dev/null +++ b/external/boringssl/crypto/conf/internal.h @@ -0,0 +1,31 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_CRYPTO_CONF_INTERNAL_H +#define OPENSSL_HEADER_CRYPTO_CONF_INTERNAL_H + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* CONF_VALUE_new returns a freshly allocated and zeroed |CONF_VALUE|. */ +CONF_VALUE *CONF_VALUE_new(void); + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_CRYPTO_CONF_INTERNAL_H */ diff --git a/external/boringssl/crypto/constant_time_test.c b/external/boringssl/crypto/constant_time_test.c new file mode 100644 index 0000000000..bc127c1c9e --- /dev/null +++ b/external/boringssl/crypto/constant_time_test.c @@ -0,0 +1,307 @@ +/* + * Utilities for constant-time cryptography. + * + * Author: Emilia Kasper (emilia@openssl.org) + * Based on previous work by Bodo Moeller, Emilia Kasper, Adam Langley + * (Google). + * ==================================================================== + * Copyright (c) 2014 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include "internal.h" + +#include +#include +#include + + +static const unsigned int CONSTTIME_TRUE = (unsigned)(~0); +static const unsigned int CONSTTIME_FALSE = 0; +static const uint8_t CONSTTIME_TRUE_8 = 0xff; +static const uint8_t CONSTTIME_FALSE_8 = 0; + +static int test_binary_op(unsigned int (*op)(unsigned int a, unsigned int b), + const char* op_name, unsigned int a, unsigned int b, + int is_true) { + unsigned c = op(a, b); + if (is_true && c != CONSTTIME_TRUE) { + fprintf(stderr, + "Test failed for %s(%du, %du): expected %du (TRUE), got %du\n", + op_name, a, b, CONSTTIME_TRUE, c); + return 1; + } else if (!is_true && c != CONSTTIME_FALSE) { + fprintf(stderr, + "Test failed for %s(%du, %du): expected %du (FALSE), got %du\n", + op_name, a, b, CONSTTIME_FALSE, c); + return 1; + } + return 0; +} + +static int test_binary_op_8(uint8_t (*op)(unsigned int a, unsigned int b), + const char* op_name, unsigned int a, unsigned int b, + int is_true) { + uint8_t c = op(a, b); + if (is_true && c != CONSTTIME_TRUE_8) { + fprintf(stderr, + "Test failed for %s(%du, %du): expected %u (TRUE), got %u\n", + op_name, a, b, CONSTTIME_TRUE_8, c); + return 1; + } else if (!is_true && c != CONSTTIME_FALSE_8) { + fprintf(stderr, + "Test failed for %s(%du, %du): expected %u (FALSE), got %u\n", + op_name, a, b, CONSTTIME_FALSE_8, c); + return 1; + } + return 0; +} + +static int test_is_zero(unsigned int a) { + unsigned int c = constant_time_is_zero(a); + if (a == 0 && c != CONSTTIME_TRUE) { + fprintf(stderr, + "Test failed for constant_time_is_zero(%du): expected %du (TRUE), " + "got %du\n", + a, CONSTTIME_TRUE, c); + return 1; + } else if (a != 0 && c != CONSTTIME_FALSE) { + fprintf(stderr, + "Test failed for constant_time_is_zero(%du): expected %du (FALSE), " + "got %du\n", + a, CONSTTIME_FALSE, c); + return 1; + } + return 0; +} + +static int test_is_zero_8(unsigned int a) { + uint8_t c = constant_time_is_zero_8(a); + if (a == 0 && c != CONSTTIME_TRUE_8) { + fprintf(stderr, + "Test failed for constant_time_is_zero(%du): expected %u (TRUE), " + "got %u\n", + a, CONSTTIME_TRUE_8, c); + return 1; + } else if (a != 0 && c != CONSTTIME_FALSE) { + fprintf(stderr, + "Test failed for constant_time_is_zero(%du): expected %u (FALSE), " + "got %u\n", + a, CONSTTIME_FALSE_8, c); + return 1; + } + return 0; +} + +static int test_select(unsigned int a, unsigned int b) { + unsigned int selected = constant_time_select(CONSTTIME_TRUE, a, b); + if (selected != a) { + fprintf(stderr, + "Test failed for constant_time_select(%du, %du," + "%du): expected %du(first value), got %du\n", + CONSTTIME_TRUE, a, b, a, selected); + return 1; + } + selected = constant_time_select(CONSTTIME_FALSE, a, b); + if (selected != b) { + fprintf(stderr, + "Test failed for constant_time_select(%du, %du," + "%du): expected %du(second value), got %du\n", + CONSTTIME_FALSE, a, b, b, selected); + return 1; + } + return 0; +} + +static int test_select_8(uint8_t a, uint8_t b) { + uint8_t selected = constant_time_select_8(CONSTTIME_TRUE_8, a, b); + if (selected != a) { + fprintf(stderr, + "Test failed for constant_time_select(%u, %u," + "%u): expected %u(first value), got %u\n", + CONSTTIME_TRUE, a, b, a, selected); + return 1; + } + selected = constant_time_select_8(CONSTTIME_FALSE_8, a, b); + if (selected != b) { + fprintf(stderr, + "Test failed for constant_time_select(%u, %u," + "%u): expected %u(second value), got %u\n", + CONSTTIME_FALSE, a, b, b, selected); + return 1; + } + return 0; +} + +static int test_select_int(int a, int b) { + int selected = constant_time_select_int(CONSTTIME_TRUE, a, b); + if (selected != a) { + fprintf(stderr, + "Test failed for constant_time_select(%du, %d," + "%d): expected %d(first value), got %d\n", + CONSTTIME_TRUE, a, b, a, selected); + return 1; + } + selected = constant_time_select_int(CONSTTIME_FALSE, a, b); + if (selected != b) { + fprintf(stderr, + "Test failed for constant_time_select(%du, %d," + "%d): expected %d(second value), got %d\n", + CONSTTIME_FALSE, a, b, b, selected); + return 1; + } + return 0; +} + +static int test_eq_int(int a, int b) { + unsigned int equal = constant_time_eq_int(a, b); + if (a == b && equal != CONSTTIME_TRUE) { + fprintf(stderr, + "Test failed for constant_time_eq_int(%d, %d): expected %du(TRUE), " + "got %du\n", + a, b, CONSTTIME_TRUE, equal); + return 1; + } else if (a != b && equal != CONSTTIME_FALSE) { + fprintf(stderr, + "Test failed for constant_time_eq_int(%d, %d): expected " + "%du(FALSE), got %du\n", + a, b, CONSTTIME_FALSE, equal); + return 1; + } + return 0; +} + +static int test_eq_int_8(int a, int b) { + uint8_t equal = constant_time_eq_int_8(a, b); + if (a == b && equal != CONSTTIME_TRUE_8) { + fprintf(stderr, + "Test failed for constant_time_eq_int_8(%d, %d): expected " + "%u(TRUE), got %u\n", + a, b, CONSTTIME_TRUE_8, equal); + return 1; + } else if (a != b && equal != CONSTTIME_FALSE_8) { + fprintf(stderr, + "Test failed for constant_time_eq_int_8(%d, %d): expected " + "%u(FALSE), got %u\n", + a, b, CONSTTIME_FALSE_8, equal); + return 1; + } + return 0; +} + +static unsigned int test_values[] = {0, 1, 1024, 12345, 32000, UINT_MAX / 2 - 1, + UINT_MAX / 2, UINT_MAX / 2 + 1, + UINT_MAX - 1, UINT_MAX}; + +static uint8_t test_values_8[] = {0, 1, 2, 20, 32, 127, 128, 129, 255}; + +static int signed_test_values[] = { + 0, 1, -1, 1024, -1024, 12345, -12345, + 32000, -32000, INT_MAX, INT_MIN, INT_MAX - 1, INT_MIN + 1}; + +int main(int argc, char* argv[]) { + unsigned int a, b, i, j; + int c, d; + uint8_t e, f; + int num_failed = 0, num_all = 0; + fprintf(stdout, "Testing constant time operations...\n"); + + for (i = 0; i < sizeof(test_values) / sizeof(int); ++i) { + a = test_values[i]; + num_failed += test_is_zero(a); + num_failed += test_is_zero_8(a); + num_all += 2; + for (j = 0; j < sizeof(test_values) / sizeof(int); ++j) { + b = test_values[j]; + num_failed += + test_binary_op(&constant_time_lt, "constant_time_lt", a, b, a < b); + num_failed += test_binary_op_8(&constant_time_lt_8, "constant_time_lt_8", + a, b, a < b); + num_failed += + test_binary_op(&constant_time_lt, "constant_time_lt_8", b, a, b < a); + num_failed += test_binary_op_8(&constant_time_lt_8, "constant_time_lt_8", + b, a, b < a); + num_failed += + test_binary_op(&constant_time_ge, "constant_time_ge", a, b, a >= b); + num_failed += test_binary_op_8(&constant_time_ge_8, "constant_time_ge_8", + a, b, a >= b); + num_failed += + test_binary_op(&constant_time_ge, "constant_time_ge", b, a, b >= a); + num_failed += test_binary_op_8(&constant_time_ge_8, "constant_time_ge_8", + b, a, b >= a); + num_failed += + test_binary_op(&constant_time_eq, "constant_time_eq", a, b, a == b); + num_failed += test_binary_op_8(&constant_time_eq_8, "constant_time_eq_8", + a, b, a == b); + num_failed += + test_binary_op(&constant_time_eq, "constant_time_eq", b, a, b == a); + num_failed += test_binary_op_8(&constant_time_eq_8, "constant_time_eq_8", + b, a, b == a); + num_failed += test_select(a, b); + num_all += 13; + } + } + + for (i = 0; i < sizeof(signed_test_values) / sizeof(int); ++i) { + c = signed_test_values[i]; + for (j = 0; j < sizeof(signed_test_values) / sizeof(int); ++j) { + d = signed_test_values[j]; + num_failed += test_select_int(c, d); + num_failed += test_eq_int(c, d); + num_failed += test_eq_int_8(c, d); + num_all += 3; + } + } + + for (i = 0; i < sizeof(test_values_8); ++i) { + e = test_values_8[i]; + for (j = 0; j < sizeof(test_values_8); ++j) { + f = test_values_8[j]; + num_failed += test_select_8(e, f); + num_all += 1; + } + } + + if (!num_failed) { + fprintf(stdout, "ok (ran %d tests)\n", num_all); + fprintf(stdout, "PASS\n"); + return EXIT_SUCCESS; + } else { + fprintf(stdout, "%d of %d tests failed!\n", num_failed, num_all); + return EXIT_FAILURE; + } +} diff --git a/external/boringssl/crypto/cpu-aarch64-linux.c b/external/boringssl/crypto/cpu-aarch64-linux.c new file mode 100644 index 0000000000..1b0f39552e --- /dev/null +++ b/external/boringssl/crypto/cpu-aarch64-linux.c @@ -0,0 +1,61 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#if defined(OPENSSL_AARCH64) && !defined(OPENSSL_STATIC_ARMCAP) + +#include + +#include + +#include "internal.h" + + +extern uint32_t OPENSSL_armcap_P; + +void OPENSSL_cpuid_setup(void) { + unsigned long hwcap = getauxval(AT_HWCAP); + + /* See /usr/include/asm/hwcap.h on an aarch64 installation for the source of + * these values. */ + static const unsigned long kNEON = 1 << 1; + static const unsigned long kAES = 1 << 3; + static const unsigned long kPMULL = 1 << 4; + static const unsigned long kSHA1 = 1 << 5; + static const unsigned long kSHA256 = 1 << 6; + + if ((hwcap & kNEON) == 0) { + /* Matching OpenSSL, if NEON is missing, don't report other features + * either. */ + return; + } + + OPENSSL_armcap_P |= ARMV7_NEON; + + if (hwcap & kAES) { + OPENSSL_armcap_P |= ARMV8_AES; + } + if (hwcap & kPMULL) { + OPENSSL_armcap_P |= ARMV8_PMULL; + } + if (hwcap & kSHA1) { + OPENSSL_armcap_P |= ARMV8_SHA1; + } + if (hwcap & kSHA256) { + OPENSSL_armcap_P |= ARMV8_SHA256; + } +} + +#endif /* OPENSSL_AARCH64 && !OPENSSL_STATIC_ARMCAP */ diff --git a/external/boringssl/crypto/cpu-arm-linux.c b/external/boringssl/crypto/cpu-arm-linux.c new file mode 100644 index 0000000000..73c38eccce --- /dev/null +++ b/external/boringssl/crypto/cpu-arm-linux.c @@ -0,0 +1,360 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#if defined(OPENSSL_ARM) && !defined(OPENSSL_STATIC_ARMCAP) + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "internal.h" + + +#define AT_HWCAP 16 +#define AT_HWCAP2 26 + +#define HWCAP_NEON (1 << 12) + +/* See /usr/include/asm/hwcap.h on an ARM installation for the source of + * these values. */ +#define HWCAP2_AES (1 << 0) +#define HWCAP2_PMULL (1 << 1) +#define HWCAP2_SHA1 (1 << 2) +#define HWCAP2_SHA2 (1 << 3) + +/* |getauxval| is not available on Android until API level 20. Link it as a weak + * symbol and use other methods as fallback. */ +unsigned long getauxval(unsigned long type) __attribute__((weak)); + +static int open_eintr(const char *path, int flags) { + int ret; + do { + ret = open(path, flags); + } while (ret < 0 && errno == EINTR); + return ret; +} + +static ssize_t read_eintr(int fd, void *out, size_t len) { + ssize_t ret; + do { + ret = read(fd, out, len); + } while (ret < 0 && errno == EINTR); + return ret; +} + +/* read_full reads exactly |len| bytes from |fd| to |out|. On error or end of + * file, it returns zero. */ +static int read_full(int fd, void *out, size_t len) { + char *outp = out; + while (len > 0) { + ssize_t ret = read_eintr(fd, outp, len); + if (ret <= 0) { + return 0; + } + outp += ret; + len -= ret; + } + return 1; +} + +/* read_file opens |path| and reads until end-of-file. On success, it returns + * one and sets |*out_ptr| and |*out_len| to a newly-allocated buffer with the + * contents. Otherwise, it returns zero. */ +static int read_file(char **out_ptr, size_t *out_len, const char *path) { + int fd = open_eintr(path, O_RDONLY); + if (fd < 0) { + return 0; + } + + static const size_t kReadSize = 1024; + int ret = 0; + size_t cap = kReadSize, len = 0; + char *buf = OPENSSL_malloc(cap); + if (buf == NULL) { + goto err; + } + + for (;;) { + if (cap - len < kReadSize) { + size_t new_cap = cap * 2; + if (new_cap < cap) { + goto err; + } + char *new_buf = OPENSSL_realloc(buf, new_cap); + if (new_buf == NULL) { + goto err; + } + buf = new_buf; + cap = new_cap; + } + + ssize_t bytes_read = read_eintr(fd, buf + len, kReadSize); + if (bytes_read < 0) { + goto err; + } + if (bytes_read == 0) { + break; + } + len += bytes_read; + } + + *out_ptr = buf; + *out_len = len; + ret = 1; + buf = NULL; + +err: + OPENSSL_free(buf); + close(fd); + return ret; +} + +/* getauxval_proc behaves like |getauxval| but reads from /proc/self/auxv. */ +static unsigned long getauxval_proc(unsigned long type) { + int fd = open_eintr("/proc/self/auxv", O_RDONLY); + if (fd < 0) { + return 0; + } + + struct { + unsigned long tag; + unsigned long value; + } entry; + + for (;;) { + if (!read_full(fd, &entry, sizeof(entry)) || + (entry.tag == 0 && entry.value == 0)) { + break; + } + if (entry.tag == type) { + close(fd); + return entry.value; + } + } + close(fd); + return 0; +} + +typedef struct { + const char *data; + size_t len; +} STRING_PIECE; + +static int STRING_PIECE_equals(const STRING_PIECE *a, const char *b) { + size_t b_len = strlen(b); + return a->len == b_len && memcmp(a->data, b, b_len) == 0; +} + +/* STRING_PIECE_split finds the first occurence of |sep| in |in| and, if found, + * sets |*out_left| and |*out_right| to |in| split before and after it. It + * returns one if |sep| was found and zero otherwise. */ +static int STRING_PIECE_split(STRING_PIECE *out_left, STRING_PIECE *out_right, + const STRING_PIECE *in, char sep) { + const char *p = memchr(in->data, sep, in->len); + if (p == NULL) { + return 0; + } + /* |out_left| or |out_right| may alias |in|, so make a copy. */ + STRING_PIECE in_copy = *in; + out_left->data = in_copy.data; + out_left->len = p - in_copy.data; + out_right->data = in_copy.data + out_left->len + 1; + out_right->len = in_copy.len - out_left->len - 1; + return 1; +} + +/* STRING_PIECE_trim removes leading and trailing whitespace from |s|. */ +static void STRING_PIECE_trim(STRING_PIECE *s) { + while (s->len != 0 && (s->data[0] == ' ' || s->data[0] == '\t')) { + s->data++; + s->len--; + } + while (s->len != 0 && + (s->data[s->len - 1] == ' ' || s->data[s->len - 1] == '\t')) { + s->len--; + } +} + +/* extract_cpuinfo_field extracts a /proc/cpuinfo field named |field| from + * |in|. If found, it sets |*out| to the value and returns one. Otherwise, it + * returns zero. */ +static int extract_cpuinfo_field(STRING_PIECE *out, const STRING_PIECE *in, + const char *field) { + /* Process |in| one line at a time. */ + STRING_PIECE remaining = *in, line; + while (STRING_PIECE_split(&line, &remaining, &remaining, '\n')) { + STRING_PIECE key, value; + if (!STRING_PIECE_split(&key, &value, &line, ':')) { + continue; + } + STRING_PIECE_trim(&key); + if (STRING_PIECE_equals(&key, field)) { + STRING_PIECE_trim(&value); + *out = value; + return 1; + } + } + + return 0; +} + +static int cpuinfo_field_equals(const STRING_PIECE *cpuinfo, const char *field, + const char *value) { + STRING_PIECE extracted; + return extract_cpuinfo_field(&extracted, cpuinfo, field) && + STRING_PIECE_equals(&extracted, value); +} + +/* has_list_item treats |list| as a space-separated list of items and returns + * one if |item| is contained in |list| and zero otherwise. */ +static int has_list_item(const STRING_PIECE *list, const char *item) { + STRING_PIECE remaining = *list, feature; + while (STRING_PIECE_split(&feature, &remaining, &remaining, ' ')) { + if (STRING_PIECE_equals(&feature, item)) { + return 1; + } + } + return 0; +} + +static unsigned long get_hwcap_cpuinfo(const STRING_PIECE *cpuinfo) { + if (cpuinfo_field_equals(cpuinfo, "CPU architecture", "8")) { + /* This is a 32-bit ARM binary running on a 64-bit kernel. NEON is always + * available on ARMv8. Linux omits required features, so reading the + * "Features" line does not work. (For simplicity, use strict equality. We + * assume everything running on future ARM architectures will have a + * working |getauxval|.) */ + return HWCAP_NEON; + } + + STRING_PIECE features; + if (extract_cpuinfo_field(&features, cpuinfo, "Features") && + has_list_item(&features, "neon")) { + return HWCAP_NEON; + } + return 0; +} + +static unsigned long get_hwcap2_cpuinfo(const STRING_PIECE *cpuinfo) { + STRING_PIECE features; + if (!extract_cpuinfo_field(&features, cpuinfo, "Features")) { + return 0; + } + + unsigned long ret = 0; + if (has_list_item(&features, "aes")) { + ret |= HWCAP2_AES; + } + if (has_list_item(&features, "pmull")) { + ret |= HWCAP2_PMULL; + } + if (has_list_item(&features, "sha1")) { + ret |= HWCAP2_SHA1; + } + if (has_list_item(&features, "sha2")) { + ret |= HWCAP2_SHA2; + } + return ret; +} + +/* has_broken_neon returns one if |in| matches a CPU known to have a broken + * NEON unit. See https://crbug.com/341598. */ +static int has_broken_neon(const STRING_PIECE *cpuinfo) { + return cpuinfo_field_equals(cpuinfo, "CPU implementer", "0x51") && + cpuinfo_field_equals(cpuinfo, "CPU architecture", "7") && + cpuinfo_field_equals(cpuinfo, "CPU variant", "0x1") && + cpuinfo_field_equals(cpuinfo, "CPU part", "0x04d") && + cpuinfo_field_equals(cpuinfo, "CPU revision", "0"); +} + +extern uint32_t OPENSSL_armcap_P; + +static int g_has_broken_neon; + +void OPENSSL_cpuid_setup(void) { + char *cpuinfo_data; + size_t cpuinfo_len; + if (!read_file(&cpuinfo_data, &cpuinfo_len, "/proc/cpuinfo")) { + return; + } + STRING_PIECE cpuinfo; + cpuinfo.data = cpuinfo_data; + cpuinfo.len = cpuinfo_len; + + /* |getauxval| is not available on Android until API level 20. If it is + * unavailable, read from /proc/self/auxv as a fallback. This is unreadable + * on some versions of Android, so further fall back to /proc/cpuinfo. + * + * See + * https://android.googlesource.com/platform/ndk/+/882ac8f3392858991a0e1af33b4b7387ec856bd2 + * and b/13679666 (Google-internal) for details. */ + unsigned long hwcap = 0; + if (getauxval != NULL) { + hwcap = getauxval(AT_HWCAP); + } + if (hwcap == 0) { + hwcap = getauxval_proc(AT_HWCAP); + } + if (hwcap == 0) { + hwcap = get_hwcap_cpuinfo(&cpuinfo); + } + + /* Clear NEON support if known broken. */ + g_has_broken_neon = has_broken_neon(&cpuinfo); + if (g_has_broken_neon) { + hwcap &= ~HWCAP_NEON; + } + + /* Matching OpenSSL, only report other features if NEON is present. */ + if (hwcap & HWCAP_NEON) { + OPENSSL_armcap_P |= ARMV7_NEON; + + /* Some ARMv8 Android devices don't expose AT_HWCAP2. Fall back to + * /proc/cpuinfo. See https://crbug.com/596156. */ + unsigned long hwcap2 = 0; + if (getauxval != NULL) { + hwcap2 = getauxval(AT_HWCAP2); + } + if (hwcap2 == 0) { + hwcap2 = get_hwcap2_cpuinfo(&cpuinfo); + } + + if (hwcap2 & HWCAP2_AES) { + OPENSSL_armcap_P |= ARMV8_AES; + } + if (hwcap2 & HWCAP2_PMULL) { + OPENSSL_armcap_P |= ARMV8_PMULL; + } + if (hwcap2 & HWCAP2_SHA1) { + OPENSSL_armcap_P |= ARMV8_SHA1; + } + if (hwcap2 & HWCAP2_SHA2) { + OPENSSL_armcap_P |= ARMV8_SHA256; + } + } + + OPENSSL_free(cpuinfo_data); +} + +int CRYPTO_has_broken_NEON(void) { return g_has_broken_neon; } + +#endif /* OPENSSL_ARM && !OPENSSL_STATIC_ARMCAP */ diff --git a/external/boringssl/crypto/cpu-arm.c b/external/boringssl/crypto/cpu-arm.c new file mode 100644 index 0000000000..ef395eaeb9 --- /dev/null +++ b/external/boringssl/crypto/cpu-arm.c @@ -0,0 +1,38 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#if (defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)) && \ + !defined(OPENSSL_STATIC_ARMCAP) + +#include + + +extern uint32_t OPENSSL_armcap_P; + +char CRYPTO_is_NEON_capable_at_runtime(void) { + return (OPENSSL_armcap_P & ARMV7_NEON) != 0; +} + +int CRYPTO_is_ARMv8_AES_capable(void) { + return (OPENSSL_armcap_P & ARMV8_AES) != 0; +} + +int CRYPTO_is_ARMv8_PMULL_capable(void) { + return (OPENSSL_armcap_P & ARMV8_PMULL) != 0; +} + +#endif /* (defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)) && + !defined(OPENSSL_STATIC_ARMCAP) */ diff --git a/external/boringssl/crypto/cpu-intel.c b/external/boringssl/crypto/cpu-intel.c new file mode 100644 index 0000000000..f2e0c4cbc9 --- /dev/null +++ b/external/boringssl/crypto/cpu-intel.c @@ -0,0 +1,263 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#if !defined(__STDC_FORMAT_MACROS) +#define __STDC_FORMAT_MACROS +#endif + +#include + + +#if !defined(OPENSSL_NO_ASM) && (defined(OPENSSL_X86) || defined(OPENSSL_X86_64)) + +#include +#include +#include +#include + +#if defined(OPENSSL_WINDOWS) +OPENSSL_MSVC_PRAGMA(warning(push, 3)) +#include +#include +OPENSSL_MSVC_PRAGMA(warning(pop)) +#endif + +#include "internal.h" + + +/* OPENSSL_cpuid runs the cpuid instruction. |leaf| is passed in as EAX and ECX + * is set to zero. It writes EAX, EBX, ECX, and EDX to |*out_eax| through + * |*out_edx|. */ +static void OPENSSL_cpuid(uint32_t *out_eax, uint32_t *out_ebx, + uint32_t *out_ecx, uint32_t *out_edx, uint32_t leaf) { +#if defined(OPENSSL_WINDOWS) + int tmp[4]; + __cpuid(tmp, (int)leaf); + *out_eax = (uint32_t)tmp[0]; + *out_ebx = (uint32_t)tmp[1]; + *out_ecx = (uint32_t)tmp[2]; + *out_edx = (uint32_t)tmp[3]; +#elif defined(__pic__) && defined(OPENSSL_32_BIT) + /* Inline assembly may not clobber the PIC register. For 32-bit, this is EBX. + * See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47602. */ + __asm__ volatile ( + "xor %%ecx, %%ecx\n" + "mov %%ebx, %%edi\n" + "cpuid\n" + "xchg %%edi, %%ebx\n" + : "=a"(*out_eax), "=D"(*out_ebx), "=c"(*out_ecx), "=d"(*out_edx) + : "a"(leaf) + ); +#else + __asm__ volatile ( + "xor %%ecx, %%ecx\n" + "cpuid\n" + : "=a"(*out_eax), "=b"(*out_ebx), "=c"(*out_ecx), "=d"(*out_edx) + : "a"(leaf) + ); +#endif +} + +/* OPENSSL_xgetbv returns the value of an Intel Extended Control Register (XCR). + * Currently only XCR0 is defined by Intel so |xcr| should always be zero. */ +static uint64_t OPENSSL_xgetbv(uint32_t xcr) { +#if defined(OPENSSL_WINDOWS) + return (uint64_t)_xgetbv(xcr); +#else + uint32_t eax, edx; + __asm__ volatile ("xgetbv" : "=a"(eax), "=d"(edx) : "c"(xcr)); + return (((uint64_t)edx) << 32) | eax; +#endif +} + +/* handle_cpu_env applies the value from |in| to the CPUID values in |out[0]| + * and |out[1]|. See the comment in |OPENSSL_cpuid_setup| about this. */ +static void handle_cpu_env(uint32_t *out, const char *in) { + const int invert = in[0] == '~'; + uint64_t v; + + if (!sscanf(in + invert, "%" PRIu64, &v)) { + return; + } + + if (invert) { + out[0] &= ~v; + out[1] &= ~(v >> 32); + } else { + out[0] = v; + out[1] = v >> 32; + } +} + +void OPENSSL_cpuid_setup(void) { + /* Determine the vendor and maximum input value. */ + uint32_t eax, ebx, ecx, edx; + OPENSSL_cpuid(&eax, &ebx, &ecx, &edx, 0); + + uint32_t num_ids = eax; + + int is_intel = ebx == 0x756e6547 /* Genu */ && + edx == 0x49656e69 /* ineI */ && + ecx == 0x6c65746e /* ntel */; + int is_amd = ebx == 0x68747541 /* Auth */ && + edx == 0x69746e65 /* enti */ && + ecx == 0x444d4163 /* cAMD */; + + int has_amd_xop = 0; + if (is_amd) { + /* AMD-specific logic. + * See http://developer.amd.com/wordpress/media/2012/10/254811.pdf */ + OPENSSL_cpuid(&eax, &ebx, &ecx, &edx, 0x80000000); + uint32_t num_extended_ids = eax; + if (num_extended_ids >= 0x80000001) { + OPENSSL_cpuid(&eax, &ebx, &ecx, &edx, 0x80000001); + if (ecx & (1 << 11)) { + has_amd_xop = 1; + } + } + } + + uint32_t extended_features = 0; + if (num_ids >= 7) { + OPENSSL_cpuid(&eax, &ebx, &ecx, &edx, 7); + extended_features = ebx; + } + + /* Determine the number of cores sharing an L1 data cache to adjust the + * hyper-threading bit. */ + uint32_t cores_per_cache = 0; + if (is_amd) { + /* AMD CPUs never share an L1 data cache between threads but do set the HTT + * bit on multi-core CPUs. */ + cores_per_cache = 1; + } else if (num_ids >= 4) { + /* TODO(davidben): The Intel manual says this CPUID leaf enumerates all + * caches using ECX and doesn't say which is first. Does this matter? */ + OPENSSL_cpuid(&eax, &ebx, &ecx, &edx, 4); + cores_per_cache = 1 + ((eax >> 14) & 0xfff); + } + + OPENSSL_cpuid(&eax, &ebx, &ecx, &edx, 1); + + /* Adjust the hyper-threading bit. */ + if (edx & (1 << 28)) { + uint32_t num_logical_cores = (ebx >> 16) & 0xff; + if (cores_per_cache == 1 || num_logical_cores <= 1) { + edx &= ~(1 << 28); + } + } + + /* Reserved bit #20 was historically repurposed to control the in-memory + * representation of RC4 state. Always set it to zero. */ + edx &= ~(1 << 20); + + /* Reserved bit #30 is repurposed to signal an Intel CPU. */ + if (is_intel) { + edx |= (1 << 30); + } else { + edx &= ~(1 << 30); + } + + /* The SDBG bit is repurposed to denote AMD XOP support. */ + if (has_amd_xop) { + ecx |= (1 << 11); + } else { + ecx &= ~(1 << 11); + } + + uint64_t xcr0 = 0; + if (ecx & (1 << 27)) { + /* XCR0 may only be queried if the OSXSAVE bit is set. */ + xcr0 = OPENSSL_xgetbv(0); + } + /* See Intel manual, section 14.3. */ + if ((xcr0 & 6) != 6) { + /* YMM registers cannot be used. */ + ecx &= ~(1 << 28); /* AVX */ + ecx &= ~(1 << 12); /* FMA */ + ecx &= ~(1 << 11); /* AMD XOP */ + extended_features &= ~(1 << 5); /* AVX2 */ + } + + OPENSSL_ia32cap_P[0] = edx; + OPENSSL_ia32cap_P[1] = ecx; + OPENSSL_ia32cap_P[2] = extended_features; + OPENSSL_ia32cap_P[3] = 0; + + const char *env1, *env2; + env1 = getenv("OPENSSL_ia32cap"); + if (env1 == NULL) { + return; + } + + /* OPENSSL_ia32cap can contain zero, one or two values, separated with a ':'. + * Each value is a 64-bit, unsigned value which may start with "0x" to + * indicate a hex value. Prior to the 64-bit value, a '~' may be given. + * + * If '~' isn't present, then the value is taken as the result of the CPUID. + * Otherwise the value is inverted and ANDed with the probed CPUID result. + * + * The first value determines OPENSSL_ia32cap_P[0] and [1]. The second [2] + * and [3]. */ + + handle_cpu_env(&OPENSSL_ia32cap_P[0], env1); + env2 = strchr(env1, ':'); + if (env2 != NULL) { + handle_cpu_env(&OPENSSL_ia32cap_P[2], env2 + 1); + } +} + +#endif /* !OPENSSL_NO_ASM && (OPENSSL_X86 || OPENSSL_X86_64) */ diff --git a/external/boringssl/crypto/crypto.c b/external/boringssl/crypto/crypto.c new file mode 100644 index 0000000000..c9f2bc87f7 --- /dev/null +++ b/external/boringssl/crypto/crypto.c @@ -0,0 +1,158 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include + +#include "internal.h" + + +#if !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_STATIC_ARMCAP) && \ + (defined(OPENSSL_X86) || defined(OPENSSL_X86_64) || \ + defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)) +/* x86, x86_64 and the ARMs need to record the result of a cpuid call for the + * asm to work correctly, unless compiled without asm code. */ +#define NEED_CPUID + +#else + +/* Otherwise, don't emit a static initialiser. */ + +#if !defined(BORINGSSL_NO_STATIC_INITIALIZER) +#define BORINGSSL_NO_STATIC_INITIALIZER +#endif + +#endif /* !OPENSSL_NO_ASM && (OPENSSL_X86 || OPENSSL_X86_64 || + OPENSSL_ARM || OPENSSL_AARCH64) */ + + +/* The capability variables are defined in this file in order to work around a + * linker bug. When linking with a .a, if no symbols in a .o are referenced + * then the .o is discarded, even if it has constructor functions. + * + * This still means that any binaries that don't include some functionality + * that tests the capability values will still skip the constructor but, so + * far, the init constructor function only sets the capability variables. */ + +#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64) +/* This value must be explicitly initialised to zero in order to work around a + * bug in libtool or the linker on OS X. + * + * If not initialised then it becomes a "common symbol". When put into an + * archive, linking on OS X will fail to resolve common symbols. By + * initialising it to zero, it becomes a "data symbol", which isn't so + * affected. */ +uint32_t OPENSSL_ia32cap_P[4] = {0}; +#elif defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64) + +#include + +#if defined(OPENSSL_STATIC_ARMCAP) + +uint32_t OPENSSL_armcap_P = +#if defined(OPENSSL_STATIC_ARMCAP_NEON) || defined(__ARM_NEON__) + ARMV7_NEON | +#endif +#if defined(OPENSSL_STATIC_ARMCAP_AES) + ARMV8_AES | +#endif +#if defined(OPENSSL_STATIC_ARMCAP_SHA1) + ARMV8_SHA1 | +#endif +#if defined(OPENSSL_STATIC_ARMCAP_SHA256) + ARMV8_SHA256 | +#endif +#if defined(OPENSSL_STATIC_ARMCAP_PMULL) + ARMV8_PMULL | +#endif + 0; + +#else +uint32_t OPENSSL_armcap_P = 0; +#endif + +#endif + + +#if defined(OPENSSL_WINDOWS) && !defined(BORINGSSL_NO_STATIC_INITIALIZER) +#define OPENSSL_CDECL __cdecl +#else +#define OPENSSL_CDECL +#endif + +#if defined(BORINGSSL_NO_STATIC_INITIALIZER) +static CRYPTO_once_t once = CRYPTO_ONCE_INIT; +#elif defined(OPENSSL_WINDOWS) +#pragma section(".CRT$XCU", read) +static void __cdecl do_library_init(void); +__declspec(allocate(".CRT$XCU")) void(*library_init_constructor)(void) = + do_library_init; +#else +static void do_library_init(void) __attribute__ ((constructor)); +#endif + +/* do_library_init is the actual initialization function. If + * BORINGSSL_NO_STATIC_INITIALIZER isn't defined, this is set as a static + * initializer. Otherwise, it is called by CRYPTO_library_init. */ +static void OPENSSL_CDECL do_library_init(void) { + /* WARNING: this function may only configure the capability variables. See the + * note above about the linker bug. */ +#if defined(NEED_CPUID) + OPENSSL_cpuid_setup(); +#endif +} + +void CRYPTO_library_init(void) { + /* TODO(davidben): It would be tidier if this build knob could be replaced + * with an internal lazy-init mechanism that would handle things correctly + * in-library. https://crbug.com/542879 */ +#if defined(BORINGSSL_NO_STATIC_INITIALIZER) + CRYPTO_once(&once, do_library_init); +#endif +} + +int CRYPTO_is_confidential_build(void) { +#if defined(BORINGSSL_CONFIDENTIAL) + return 1; +#else + return 0; +#endif +} + +int CRYPTO_has_asm(void) { +#if defined(OPENSSL_NO_ASM) + return 0; +#else + return 1; +#endif +} + +const char *SSLeay_version(int unused) { + return "BoringSSL"; +} + +unsigned long SSLeay(void) { + return OPENSSL_VERSION_NUMBER; +} + +int CRYPTO_malloc_init(void) { + return 1; +} + +void ENGINE_load_builtin_engines(void) {} + +void OPENSSL_load_builtin_modules(void) {} + +int FIPS_mode(void) { return 0; } diff --git a/external/boringssl/crypto/curve25519/CMakeLists.txt b/external/boringssl/crypto/curve25519/CMakeLists.txt new file mode 100644 index 0000000000..7260edca3d --- /dev/null +++ b/external/boringssl/crypto/curve25519/CMakeLists.txt @@ -0,0 +1,59 @@ +include_directories(../../include) + +if (${ARCH} STREQUAL "arm") + set( + CURVE25519_ARCH_SOURCES + + asm/x25519-asm-arm.S + ) +endif() + +if (${ARCH} STREQUAL "x86_64") + set( + CURVE25519_ARCH_SOURCES + + asm/x25519-asm-x86_64.S + ) +endif() + +add_library( + curve25519 + + OBJECT + + curve25519.c + spake25519.c + x25519-x86_64.c + + ${CURVE25519_ARCH_SOURCES} +) + +if(ENABLE_TESTS) +add_executable( + ed25519_test + + ed25519_test.cc + $ +) + +target_link_libraries(ed25519_test crypto) +add_dependencies(all_tests ed25519_test) + +add_executable( + x25519_test + + x25519_test.cc +) + +target_link_libraries(x25519_test crypto) +add_dependencies(all_tests x25519_test) + +add_executable( + spake25519_test + + spake25519_test.cc +) + +target_link_libraries(spake25519_test crypto) +add_dependencies(all_tests spake25519_test) +endif() diff --git a/external/boringssl/crypto/curve25519/asm/x25519-asm-arm.S b/external/boringssl/crypto/curve25519/asm/x25519-asm-arm.S new file mode 100644 index 0000000000..3af1dba947 --- /dev/null +++ b/external/boringssl/crypto/curve25519/asm/x25519-asm-arm.S @@ -0,0 +1,2124 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +/* This file is taken from crypto_scalarmult/curve25519/neon2/scalarmult.s in + * SUPERCOP 20141124 (http://bench.cr.yp.to/supercop.html). That code is public + * domain licensed but the standard ISC license is included above to keep + * licensing simple. */ + +#if !defined(OPENSSL_NO_ASM) +#if defined(__arm__) + +.fpu neon +.text +.align 4 + +.global x25519_NEON +.hidden x25519_NEON +.type x25519_NEON, %function +x25519_NEON: +vpush {q4,q5,q6,q7} +mov r12,sp +sub sp,sp,#736 +and sp,sp,#0xffffffe0 +strd r4,[sp,#0] +strd r6,[sp,#8] +strd r8,[sp,#16] +strd r10,[sp,#24] +str r12,[sp,#480] +str r14,[sp,#484] +mov r0,r0 +mov r1,r1 +mov r2,r2 +add r3,sp,#32 +ldr r4,=0 +ldr r5,=254 +vmov.i32 q0,#1 +vshr.u64 q1,q0,#7 +vshr.u64 q0,q0,#8 +vmov.i32 d4,#19 +vmov.i32 d5,#38 +add r6,sp,#512 +vst1.8 {d2-d3},[r6,: 128] +add r6,sp,#528 +vst1.8 {d0-d1},[r6,: 128] +add r6,sp,#544 +vst1.8 {d4-d5},[r6,: 128] +add r6,r3,#0 +vmov.i32 q2,#0 +vst1.8 {d4-d5},[r6,: 128]! +vst1.8 {d4-d5},[r6,: 128]! +vst1.8 d4,[r6,: 64] +add r6,r3,#0 +ldr r7,=960 +sub r7,r7,#2 +neg r7,r7 +sub r7,r7,r7,LSL #7 +str r7,[r6] +add r6,sp,#704 +vld1.8 {d4-d5},[r1]! +vld1.8 {d6-d7},[r1] +vst1.8 {d4-d5},[r6,: 128]! +vst1.8 {d6-d7},[r6,: 128] +sub r1,r6,#16 +ldrb r6,[r1] +and r6,r6,#248 +strb r6,[r1] +ldrb r6,[r1,#31] +and r6,r6,#127 +orr r6,r6,#64 +strb r6,[r1,#31] +vmov.i64 q2,#0xffffffff +vshr.u64 q3,q2,#7 +vshr.u64 q2,q2,#6 +vld1.8 {d8},[r2] +vld1.8 {d10},[r2] +add r2,r2,#6 +vld1.8 {d12},[r2] +vld1.8 {d14},[r2] +add r2,r2,#6 +vld1.8 {d16},[r2] +add r2,r2,#4 +vld1.8 {d18},[r2] +vld1.8 {d20},[r2] +add r2,r2,#6 +vld1.8 {d22},[r2] +add r2,r2,#2 +vld1.8 {d24},[r2] +vld1.8 {d26},[r2] +vshr.u64 q5,q5,#26 +vshr.u64 q6,q6,#3 +vshr.u64 q7,q7,#29 +vshr.u64 q8,q8,#6 +vshr.u64 q10,q10,#25 +vshr.u64 q11,q11,#3 +vshr.u64 q12,q12,#12 +vshr.u64 q13,q13,#38 +vand q4,q4,q2 +vand q6,q6,q2 +vand q8,q8,q2 +vand q10,q10,q2 +vand q2,q12,q2 +vand q5,q5,q3 +vand q7,q7,q3 +vand q9,q9,q3 +vand q11,q11,q3 +vand q3,q13,q3 +add r2,r3,#48 +vadd.i64 q12,q4,q1 +vadd.i64 q13,q10,q1 +vshr.s64 q12,q12,#26 +vshr.s64 q13,q13,#26 +vadd.i64 q5,q5,q12 +vshl.i64 q12,q12,#26 +vadd.i64 q14,q5,q0 +vadd.i64 q11,q11,q13 +vshl.i64 q13,q13,#26 +vadd.i64 q15,q11,q0 +vsub.i64 q4,q4,q12 +vshr.s64 q12,q14,#25 +vsub.i64 q10,q10,q13 +vshr.s64 q13,q15,#25 +vadd.i64 q6,q6,q12 +vshl.i64 q12,q12,#25 +vadd.i64 q14,q6,q1 +vadd.i64 q2,q2,q13 +vsub.i64 q5,q5,q12 +vshr.s64 q12,q14,#26 +vshl.i64 q13,q13,#25 +vadd.i64 q14,q2,q1 +vadd.i64 q7,q7,q12 +vshl.i64 q12,q12,#26 +vadd.i64 q15,q7,q0 +vsub.i64 q11,q11,q13 +vshr.s64 q13,q14,#26 +vsub.i64 q6,q6,q12 +vshr.s64 q12,q15,#25 +vadd.i64 q3,q3,q13 +vshl.i64 q13,q13,#26 +vadd.i64 q14,q3,q0 +vadd.i64 q8,q8,q12 +vshl.i64 q12,q12,#25 +vadd.i64 q15,q8,q1 +add r2,r2,#8 +vsub.i64 q2,q2,q13 +vshr.s64 q13,q14,#25 +vsub.i64 q7,q7,q12 +vshr.s64 q12,q15,#26 +vadd.i64 q14,q13,q13 +vadd.i64 q9,q9,q12 +vtrn.32 d12,d14 +vshl.i64 q12,q12,#26 +vtrn.32 d13,d15 +vadd.i64 q0,q9,q0 +vadd.i64 q4,q4,q14 +vst1.8 d12,[r2,: 64]! +vshl.i64 q6,q13,#4 +vsub.i64 q7,q8,q12 +vshr.s64 q0,q0,#25 +vadd.i64 q4,q4,q6 +vadd.i64 q6,q10,q0 +vshl.i64 q0,q0,#25 +vadd.i64 q8,q6,q1 +vadd.i64 q4,q4,q13 +vshl.i64 q10,q13,#25 +vadd.i64 q1,q4,q1 +vsub.i64 q0,q9,q0 +vshr.s64 q8,q8,#26 +vsub.i64 q3,q3,q10 +vtrn.32 d14,d0 +vshr.s64 q1,q1,#26 +vtrn.32 d15,d1 +vadd.i64 q0,q11,q8 +vst1.8 d14,[r2,: 64] +vshl.i64 q7,q8,#26 +vadd.i64 q5,q5,q1 +vtrn.32 d4,d6 +vshl.i64 q1,q1,#26 +vtrn.32 d5,d7 +vsub.i64 q3,q6,q7 +add r2,r2,#16 +vsub.i64 q1,q4,q1 +vst1.8 d4,[r2,: 64] +vtrn.32 d6,d0 +vtrn.32 d7,d1 +sub r2,r2,#8 +vtrn.32 d2,d10 +vtrn.32 d3,d11 +vst1.8 d6,[r2,: 64] +sub r2,r2,#24 +vst1.8 d2,[r2,: 64] +add r2,r3,#96 +vmov.i32 q0,#0 +vmov.i64 d2,#0xff +vmov.i64 d3,#0 +vshr.u32 q1,q1,#7 +vst1.8 {d2-d3},[r2,: 128]! +vst1.8 {d0-d1},[r2,: 128]! +vst1.8 d0,[r2,: 64] +add r2,r3,#144 +vmov.i32 q0,#0 +vst1.8 {d0-d1},[r2,: 128]! +vst1.8 {d0-d1},[r2,: 128]! +vst1.8 d0,[r2,: 64] +add r2,r3,#240 +vmov.i32 q0,#0 +vmov.i64 d2,#0xff +vmov.i64 d3,#0 +vshr.u32 q1,q1,#7 +vst1.8 {d2-d3},[r2,: 128]! +vst1.8 {d0-d1},[r2,: 128]! +vst1.8 d0,[r2,: 64] +add r2,r3,#48 +add r6,r3,#192 +vld1.8 {d0-d1},[r2,: 128]! +vld1.8 {d2-d3},[r2,: 128]! +vld1.8 {d4},[r2,: 64] +vst1.8 {d0-d1},[r6,: 128]! +vst1.8 {d2-d3},[r6,: 128]! +vst1.8 d4,[r6,: 64] +._mainloop: +mov r2,r5,LSR #3 +and r6,r5,#7 +ldrb r2,[r1,r2] +mov r2,r2,LSR r6 +and r2,r2,#1 +str r5,[sp,#488] +eor r4,r4,r2 +str r2,[sp,#492] +neg r2,r4 +add r4,r3,#96 +add r5,r3,#192 +add r6,r3,#144 +vld1.8 {d8-d9},[r4,: 128]! +add r7,r3,#240 +vld1.8 {d10-d11},[r5,: 128]! +veor q6,q4,q5 +vld1.8 {d14-d15},[r6,: 128]! +vdup.i32 q8,r2 +vld1.8 {d18-d19},[r7,: 128]! +veor q10,q7,q9 +vld1.8 {d22-d23},[r4,: 128]! +vand q6,q6,q8 +vld1.8 {d24-d25},[r5,: 128]! +vand q10,q10,q8 +vld1.8 {d26-d27},[r6,: 128]! +veor q4,q4,q6 +vld1.8 {d28-d29},[r7,: 128]! +veor q5,q5,q6 +vld1.8 {d0},[r4,: 64] +veor q6,q7,q10 +vld1.8 {d2},[r5,: 64] +veor q7,q9,q10 +vld1.8 {d4},[r6,: 64] +veor q9,q11,q12 +vld1.8 {d6},[r7,: 64] +veor q10,q0,q1 +sub r2,r4,#32 +vand q9,q9,q8 +sub r4,r5,#32 +vand q10,q10,q8 +sub r5,r6,#32 +veor q11,q11,q9 +sub r6,r7,#32 +veor q0,q0,q10 +veor q9,q12,q9 +veor q1,q1,q10 +veor q10,q13,q14 +veor q12,q2,q3 +vand q10,q10,q8 +vand q8,q12,q8 +veor q12,q13,q10 +veor q2,q2,q8 +veor q10,q14,q10 +veor q3,q3,q8 +vadd.i32 q8,q4,q6 +vsub.i32 q4,q4,q6 +vst1.8 {d16-d17},[r2,: 128]! +vadd.i32 q6,q11,q12 +vst1.8 {d8-d9},[r5,: 128]! +vsub.i32 q4,q11,q12 +vst1.8 {d12-d13},[r2,: 128]! +vadd.i32 q6,q0,q2 +vst1.8 {d8-d9},[r5,: 128]! +vsub.i32 q0,q0,q2 +vst1.8 d12,[r2,: 64] +vadd.i32 q2,q5,q7 +vst1.8 d0,[r5,: 64] +vsub.i32 q0,q5,q7 +vst1.8 {d4-d5},[r4,: 128]! +vadd.i32 q2,q9,q10 +vst1.8 {d0-d1},[r6,: 128]! +vsub.i32 q0,q9,q10 +vst1.8 {d4-d5},[r4,: 128]! +vadd.i32 q2,q1,q3 +vst1.8 {d0-d1},[r6,: 128]! +vsub.i32 q0,q1,q3 +vst1.8 d4,[r4,: 64] +vst1.8 d0,[r6,: 64] +add r2,sp,#544 +add r4,r3,#96 +add r5,r3,#144 +vld1.8 {d0-d1},[r2,: 128] +vld1.8 {d2-d3},[r4,: 128]! +vld1.8 {d4-d5},[r5,: 128]! +vzip.i32 q1,q2 +vld1.8 {d6-d7},[r4,: 128]! +vld1.8 {d8-d9},[r5,: 128]! +vshl.i32 q5,q1,#1 +vzip.i32 q3,q4 +vshl.i32 q6,q2,#1 +vld1.8 {d14},[r4,: 64] +vshl.i32 q8,q3,#1 +vld1.8 {d15},[r5,: 64] +vshl.i32 q9,q4,#1 +vmul.i32 d21,d7,d1 +vtrn.32 d14,d15 +vmul.i32 q11,q4,q0 +vmul.i32 q0,q7,q0 +vmull.s32 q12,d2,d2 +vmlal.s32 q12,d11,d1 +vmlal.s32 q12,d12,d0 +vmlal.s32 q12,d13,d23 +vmlal.s32 q12,d16,d22 +vmlal.s32 q12,d7,d21 +vmull.s32 q10,d2,d11 +vmlal.s32 q10,d4,d1 +vmlal.s32 q10,d13,d0 +vmlal.s32 q10,d6,d23 +vmlal.s32 q10,d17,d22 +vmull.s32 q13,d10,d4 +vmlal.s32 q13,d11,d3 +vmlal.s32 q13,d13,d1 +vmlal.s32 q13,d16,d0 +vmlal.s32 q13,d17,d23 +vmlal.s32 q13,d8,d22 +vmull.s32 q1,d10,d5 +vmlal.s32 q1,d11,d4 +vmlal.s32 q1,d6,d1 +vmlal.s32 q1,d17,d0 +vmlal.s32 q1,d8,d23 +vmull.s32 q14,d10,d6 +vmlal.s32 q14,d11,d13 +vmlal.s32 q14,d4,d4 +vmlal.s32 q14,d17,d1 +vmlal.s32 q14,d18,d0 +vmlal.s32 q14,d9,d23 +vmull.s32 q11,d10,d7 +vmlal.s32 q11,d11,d6 +vmlal.s32 q11,d12,d5 +vmlal.s32 q11,d8,d1 +vmlal.s32 q11,d19,d0 +vmull.s32 q15,d10,d8 +vmlal.s32 q15,d11,d17 +vmlal.s32 q15,d12,d6 +vmlal.s32 q15,d13,d5 +vmlal.s32 q15,d19,d1 +vmlal.s32 q15,d14,d0 +vmull.s32 q2,d10,d9 +vmlal.s32 q2,d11,d8 +vmlal.s32 q2,d12,d7 +vmlal.s32 q2,d13,d6 +vmlal.s32 q2,d14,d1 +vmull.s32 q0,d15,d1 +vmlal.s32 q0,d10,d14 +vmlal.s32 q0,d11,d19 +vmlal.s32 q0,d12,d8 +vmlal.s32 q0,d13,d17 +vmlal.s32 q0,d6,d6 +add r2,sp,#512 +vld1.8 {d18-d19},[r2,: 128] +vmull.s32 q3,d16,d7 +vmlal.s32 q3,d10,d15 +vmlal.s32 q3,d11,d14 +vmlal.s32 q3,d12,d9 +vmlal.s32 q3,d13,d8 +add r2,sp,#528 +vld1.8 {d8-d9},[r2,: 128] +vadd.i64 q5,q12,q9 +vadd.i64 q6,q15,q9 +vshr.s64 q5,q5,#26 +vshr.s64 q6,q6,#26 +vadd.i64 q7,q10,q5 +vshl.i64 q5,q5,#26 +vadd.i64 q8,q7,q4 +vadd.i64 q2,q2,q6 +vshl.i64 q6,q6,#26 +vadd.i64 q10,q2,q4 +vsub.i64 q5,q12,q5 +vshr.s64 q8,q8,#25 +vsub.i64 q6,q15,q6 +vshr.s64 q10,q10,#25 +vadd.i64 q12,q13,q8 +vshl.i64 q8,q8,#25 +vadd.i64 q13,q12,q9 +vadd.i64 q0,q0,q10 +vsub.i64 q7,q7,q8 +vshr.s64 q8,q13,#26 +vshl.i64 q10,q10,#25 +vadd.i64 q13,q0,q9 +vadd.i64 q1,q1,q8 +vshl.i64 q8,q8,#26 +vadd.i64 q15,q1,q4 +vsub.i64 q2,q2,q10 +vshr.s64 q10,q13,#26 +vsub.i64 q8,q12,q8 +vshr.s64 q12,q15,#25 +vadd.i64 q3,q3,q10 +vshl.i64 q10,q10,#26 +vadd.i64 q13,q3,q4 +vadd.i64 q14,q14,q12 +add r2,r3,#288 +vshl.i64 q12,q12,#25 +add r4,r3,#336 +vadd.i64 q15,q14,q9 +add r2,r2,#8 +vsub.i64 q0,q0,q10 +add r4,r4,#8 +vshr.s64 q10,q13,#25 +vsub.i64 q1,q1,q12 +vshr.s64 q12,q15,#26 +vadd.i64 q13,q10,q10 +vadd.i64 q11,q11,q12 +vtrn.32 d16,d2 +vshl.i64 q12,q12,#26 +vtrn.32 d17,d3 +vadd.i64 q1,q11,q4 +vadd.i64 q4,q5,q13 +vst1.8 d16,[r2,: 64]! +vshl.i64 q5,q10,#4 +vst1.8 d17,[r4,: 64]! +vsub.i64 q8,q14,q12 +vshr.s64 q1,q1,#25 +vadd.i64 q4,q4,q5 +vadd.i64 q5,q6,q1 +vshl.i64 q1,q1,#25 +vadd.i64 q6,q5,q9 +vadd.i64 q4,q4,q10 +vshl.i64 q10,q10,#25 +vadd.i64 q9,q4,q9 +vsub.i64 q1,q11,q1 +vshr.s64 q6,q6,#26 +vsub.i64 q3,q3,q10 +vtrn.32 d16,d2 +vshr.s64 q9,q9,#26 +vtrn.32 d17,d3 +vadd.i64 q1,q2,q6 +vst1.8 d16,[r2,: 64] +vshl.i64 q2,q6,#26 +vst1.8 d17,[r4,: 64] +vadd.i64 q6,q7,q9 +vtrn.32 d0,d6 +vshl.i64 q7,q9,#26 +vtrn.32 d1,d7 +vsub.i64 q2,q5,q2 +add r2,r2,#16 +vsub.i64 q3,q4,q7 +vst1.8 d0,[r2,: 64] +add r4,r4,#16 +vst1.8 d1,[r4,: 64] +vtrn.32 d4,d2 +vtrn.32 d5,d3 +sub r2,r2,#8 +sub r4,r4,#8 +vtrn.32 d6,d12 +vtrn.32 d7,d13 +vst1.8 d4,[r2,: 64] +vst1.8 d5,[r4,: 64] +sub r2,r2,#24 +sub r4,r4,#24 +vst1.8 d6,[r2,: 64] +vst1.8 d7,[r4,: 64] +add r2,r3,#240 +add r4,r3,#96 +vld1.8 {d0-d1},[r4,: 128]! +vld1.8 {d2-d3},[r4,: 128]! +vld1.8 {d4},[r4,: 64] +add r4,r3,#144 +vld1.8 {d6-d7},[r4,: 128]! +vtrn.32 q0,q3 +vld1.8 {d8-d9},[r4,: 128]! +vshl.i32 q5,q0,#4 +vtrn.32 q1,q4 +vshl.i32 q6,q3,#4 +vadd.i32 q5,q5,q0 +vadd.i32 q6,q6,q3 +vshl.i32 q7,q1,#4 +vld1.8 {d5},[r4,: 64] +vshl.i32 q8,q4,#4 +vtrn.32 d4,d5 +vadd.i32 q7,q7,q1 +vadd.i32 q8,q8,q4 +vld1.8 {d18-d19},[r2,: 128]! +vshl.i32 q10,q2,#4 +vld1.8 {d22-d23},[r2,: 128]! +vadd.i32 q10,q10,q2 +vld1.8 {d24},[r2,: 64] +vadd.i32 q5,q5,q0 +add r2,r3,#192 +vld1.8 {d26-d27},[r2,: 128]! +vadd.i32 q6,q6,q3 +vld1.8 {d28-d29},[r2,: 128]! +vadd.i32 q8,q8,q4 +vld1.8 {d25},[r2,: 64] +vadd.i32 q10,q10,q2 +vtrn.32 q9,q13 +vadd.i32 q7,q7,q1 +vadd.i32 q5,q5,q0 +vtrn.32 q11,q14 +vadd.i32 q6,q6,q3 +add r2,sp,#560 +vadd.i32 q10,q10,q2 +vtrn.32 d24,d25 +vst1.8 {d12-d13},[r2,: 128] +vshl.i32 q6,q13,#1 +add r2,sp,#576 +vst1.8 {d20-d21},[r2,: 128] +vshl.i32 q10,q14,#1 +add r2,sp,#592 +vst1.8 {d12-d13},[r2,: 128] +vshl.i32 q15,q12,#1 +vadd.i32 q8,q8,q4 +vext.32 d10,d31,d30,#0 +vadd.i32 q7,q7,q1 +add r2,sp,#608 +vst1.8 {d16-d17},[r2,: 128] +vmull.s32 q8,d18,d5 +vmlal.s32 q8,d26,d4 +vmlal.s32 q8,d19,d9 +vmlal.s32 q8,d27,d3 +vmlal.s32 q8,d22,d8 +vmlal.s32 q8,d28,d2 +vmlal.s32 q8,d23,d7 +vmlal.s32 q8,d29,d1 +vmlal.s32 q8,d24,d6 +vmlal.s32 q8,d25,d0 +add r2,sp,#624 +vst1.8 {d14-d15},[r2,: 128] +vmull.s32 q2,d18,d4 +vmlal.s32 q2,d12,d9 +vmlal.s32 q2,d13,d8 +vmlal.s32 q2,d19,d3 +vmlal.s32 q2,d22,d2 +vmlal.s32 q2,d23,d1 +vmlal.s32 q2,d24,d0 +add r2,sp,#640 +vst1.8 {d20-d21},[r2,: 128] +vmull.s32 q7,d18,d9 +vmlal.s32 q7,d26,d3 +vmlal.s32 q7,d19,d8 +vmlal.s32 q7,d27,d2 +vmlal.s32 q7,d22,d7 +vmlal.s32 q7,d28,d1 +vmlal.s32 q7,d23,d6 +vmlal.s32 q7,d29,d0 +add r2,sp,#656 +vst1.8 {d10-d11},[r2,: 128] +vmull.s32 q5,d18,d3 +vmlal.s32 q5,d19,d2 +vmlal.s32 q5,d22,d1 +vmlal.s32 q5,d23,d0 +vmlal.s32 q5,d12,d8 +add r2,sp,#672 +vst1.8 {d16-d17},[r2,: 128] +vmull.s32 q4,d18,d8 +vmlal.s32 q4,d26,d2 +vmlal.s32 q4,d19,d7 +vmlal.s32 q4,d27,d1 +vmlal.s32 q4,d22,d6 +vmlal.s32 q4,d28,d0 +vmull.s32 q8,d18,d7 +vmlal.s32 q8,d26,d1 +vmlal.s32 q8,d19,d6 +vmlal.s32 q8,d27,d0 +add r2,sp,#576 +vld1.8 {d20-d21},[r2,: 128] +vmlal.s32 q7,d24,d21 +vmlal.s32 q7,d25,d20 +vmlal.s32 q4,d23,d21 +vmlal.s32 q4,d29,d20 +vmlal.s32 q8,d22,d21 +vmlal.s32 q8,d28,d20 +vmlal.s32 q5,d24,d20 +add r2,sp,#576 +vst1.8 {d14-d15},[r2,: 128] +vmull.s32 q7,d18,d6 +vmlal.s32 q7,d26,d0 +add r2,sp,#656 +vld1.8 {d30-d31},[r2,: 128] +vmlal.s32 q2,d30,d21 +vmlal.s32 q7,d19,d21 +vmlal.s32 q7,d27,d20 +add r2,sp,#624 +vld1.8 {d26-d27},[r2,: 128] +vmlal.s32 q4,d25,d27 +vmlal.s32 q8,d29,d27 +vmlal.s32 q8,d25,d26 +vmlal.s32 q7,d28,d27 +vmlal.s32 q7,d29,d26 +add r2,sp,#608 +vld1.8 {d28-d29},[r2,: 128] +vmlal.s32 q4,d24,d29 +vmlal.s32 q8,d23,d29 +vmlal.s32 q8,d24,d28 +vmlal.s32 q7,d22,d29 +vmlal.s32 q7,d23,d28 +add r2,sp,#608 +vst1.8 {d8-d9},[r2,: 128] +add r2,sp,#560 +vld1.8 {d8-d9},[r2,: 128] +vmlal.s32 q7,d24,d9 +vmlal.s32 q7,d25,d31 +vmull.s32 q1,d18,d2 +vmlal.s32 q1,d19,d1 +vmlal.s32 q1,d22,d0 +vmlal.s32 q1,d24,d27 +vmlal.s32 q1,d23,d20 +vmlal.s32 q1,d12,d7 +vmlal.s32 q1,d13,d6 +vmull.s32 q6,d18,d1 +vmlal.s32 q6,d19,d0 +vmlal.s32 q6,d23,d27 +vmlal.s32 q6,d22,d20 +vmlal.s32 q6,d24,d26 +vmull.s32 q0,d18,d0 +vmlal.s32 q0,d22,d27 +vmlal.s32 q0,d23,d26 +vmlal.s32 q0,d24,d31 +vmlal.s32 q0,d19,d20 +add r2,sp,#640 +vld1.8 {d18-d19},[r2,: 128] +vmlal.s32 q2,d18,d7 +vmlal.s32 q2,d19,d6 +vmlal.s32 q5,d18,d6 +vmlal.s32 q5,d19,d21 +vmlal.s32 q1,d18,d21 +vmlal.s32 q1,d19,d29 +vmlal.s32 q0,d18,d28 +vmlal.s32 q0,d19,d9 +vmlal.s32 q6,d18,d29 +vmlal.s32 q6,d19,d28 +add r2,sp,#592 +vld1.8 {d18-d19},[r2,: 128] +add r2,sp,#512 +vld1.8 {d22-d23},[r2,: 128] +vmlal.s32 q5,d19,d7 +vmlal.s32 q0,d18,d21 +vmlal.s32 q0,d19,d29 +vmlal.s32 q6,d18,d6 +add r2,sp,#528 +vld1.8 {d6-d7},[r2,: 128] +vmlal.s32 q6,d19,d21 +add r2,sp,#576 +vld1.8 {d18-d19},[r2,: 128] +vmlal.s32 q0,d30,d8 +add r2,sp,#672 +vld1.8 {d20-d21},[r2,: 128] +vmlal.s32 q5,d30,d29 +add r2,sp,#608 +vld1.8 {d24-d25},[r2,: 128] +vmlal.s32 q1,d30,d28 +vadd.i64 q13,q0,q11 +vadd.i64 q14,q5,q11 +vmlal.s32 q6,d30,d9 +vshr.s64 q4,q13,#26 +vshr.s64 q13,q14,#26 +vadd.i64 q7,q7,q4 +vshl.i64 q4,q4,#26 +vadd.i64 q14,q7,q3 +vadd.i64 q9,q9,q13 +vshl.i64 q13,q13,#26 +vadd.i64 q15,q9,q3 +vsub.i64 q0,q0,q4 +vshr.s64 q4,q14,#25 +vsub.i64 q5,q5,q13 +vshr.s64 q13,q15,#25 +vadd.i64 q6,q6,q4 +vshl.i64 q4,q4,#25 +vadd.i64 q14,q6,q11 +vadd.i64 q2,q2,q13 +vsub.i64 q4,q7,q4 +vshr.s64 q7,q14,#26 +vshl.i64 q13,q13,#25 +vadd.i64 q14,q2,q11 +vadd.i64 q8,q8,q7 +vshl.i64 q7,q7,#26 +vadd.i64 q15,q8,q3 +vsub.i64 q9,q9,q13 +vshr.s64 q13,q14,#26 +vsub.i64 q6,q6,q7 +vshr.s64 q7,q15,#25 +vadd.i64 q10,q10,q13 +vshl.i64 q13,q13,#26 +vadd.i64 q14,q10,q3 +vadd.i64 q1,q1,q7 +add r2,r3,#144 +vshl.i64 q7,q7,#25 +add r4,r3,#96 +vadd.i64 q15,q1,q11 +add r2,r2,#8 +vsub.i64 q2,q2,q13 +add r4,r4,#8 +vshr.s64 q13,q14,#25 +vsub.i64 q7,q8,q7 +vshr.s64 q8,q15,#26 +vadd.i64 q14,q13,q13 +vadd.i64 q12,q12,q8 +vtrn.32 d12,d14 +vshl.i64 q8,q8,#26 +vtrn.32 d13,d15 +vadd.i64 q3,q12,q3 +vadd.i64 q0,q0,q14 +vst1.8 d12,[r2,: 64]! +vshl.i64 q7,q13,#4 +vst1.8 d13,[r4,: 64]! +vsub.i64 q1,q1,q8 +vshr.s64 q3,q3,#25 +vadd.i64 q0,q0,q7 +vadd.i64 q5,q5,q3 +vshl.i64 q3,q3,#25 +vadd.i64 q6,q5,q11 +vadd.i64 q0,q0,q13 +vshl.i64 q7,q13,#25 +vadd.i64 q8,q0,q11 +vsub.i64 q3,q12,q3 +vshr.s64 q6,q6,#26 +vsub.i64 q7,q10,q7 +vtrn.32 d2,d6 +vshr.s64 q8,q8,#26 +vtrn.32 d3,d7 +vadd.i64 q3,q9,q6 +vst1.8 d2,[r2,: 64] +vshl.i64 q6,q6,#26 +vst1.8 d3,[r4,: 64] +vadd.i64 q1,q4,q8 +vtrn.32 d4,d14 +vshl.i64 q4,q8,#26 +vtrn.32 d5,d15 +vsub.i64 q5,q5,q6 +add r2,r2,#16 +vsub.i64 q0,q0,q4 +vst1.8 d4,[r2,: 64] +add r4,r4,#16 +vst1.8 d5,[r4,: 64] +vtrn.32 d10,d6 +vtrn.32 d11,d7 +sub r2,r2,#8 +sub r4,r4,#8 +vtrn.32 d0,d2 +vtrn.32 d1,d3 +vst1.8 d10,[r2,: 64] +vst1.8 d11,[r4,: 64] +sub r2,r2,#24 +sub r4,r4,#24 +vst1.8 d0,[r2,: 64] +vst1.8 d1,[r4,: 64] +add r2,r3,#288 +add r4,r3,#336 +vld1.8 {d0-d1},[r2,: 128]! +vld1.8 {d2-d3},[r4,: 128]! +vsub.i32 q0,q0,q1 +vld1.8 {d2-d3},[r2,: 128]! +vld1.8 {d4-d5},[r4,: 128]! +vsub.i32 q1,q1,q2 +add r5,r3,#240 +vld1.8 {d4},[r2,: 64] +vld1.8 {d6},[r4,: 64] +vsub.i32 q2,q2,q3 +vst1.8 {d0-d1},[r5,: 128]! +vst1.8 {d2-d3},[r5,: 128]! +vst1.8 d4,[r5,: 64] +add r2,r3,#144 +add r4,r3,#96 +add r5,r3,#144 +add r6,r3,#192 +vld1.8 {d0-d1},[r2,: 128]! +vld1.8 {d2-d3},[r4,: 128]! +vsub.i32 q2,q0,q1 +vadd.i32 q0,q0,q1 +vld1.8 {d2-d3},[r2,: 128]! +vld1.8 {d6-d7},[r4,: 128]! +vsub.i32 q4,q1,q3 +vadd.i32 q1,q1,q3 +vld1.8 {d6},[r2,: 64] +vld1.8 {d10},[r4,: 64] +vsub.i32 q6,q3,q5 +vadd.i32 q3,q3,q5 +vst1.8 {d4-d5},[r5,: 128]! +vst1.8 {d0-d1},[r6,: 128]! +vst1.8 {d8-d9},[r5,: 128]! +vst1.8 {d2-d3},[r6,: 128]! +vst1.8 d12,[r5,: 64] +vst1.8 d6,[r6,: 64] +add r2,r3,#0 +add r4,r3,#240 +vld1.8 {d0-d1},[r4,: 128]! +vld1.8 {d2-d3},[r4,: 128]! +vld1.8 {d4},[r4,: 64] +add r4,r3,#336 +vld1.8 {d6-d7},[r4,: 128]! +vtrn.32 q0,q3 +vld1.8 {d8-d9},[r4,: 128]! +vshl.i32 q5,q0,#4 +vtrn.32 q1,q4 +vshl.i32 q6,q3,#4 +vadd.i32 q5,q5,q0 +vadd.i32 q6,q6,q3 +vshl.i32 q7,q1,#4 +vld1.8 {d5},[r4,: 64] +vshl.i32 q8,q4,#4 +vtrn.32 d4,d5 +vadd.i32 q7,q7,q1 +vadd.i32 q8,q8,q4 +vld1.8 {d18-d19},[r2,: 128]! +vshl.i32 q10,q2,#4 +vld1.8 {d22-d23},[r2,: 128]! +vadd.i32 q10,q10,q2 +vld1.8 {d24},[r2,: 64] +vadd.i32 q5,q5,q0 +add r2,r3,#288 +vld1.8 {d26-d27},[r2,: 128]! +vadd.i32 q6,q6,q3 +vld1.8 {d28-d29},[r2,: 128]! +vadd.i32 q8,q8,q4 +vld1.8 {d25},[r2,: 64] +vadd.i32 q10,q10,q2 +vtrn.32 q9,q13 +vadd.i32 q7,q7,q1 +vadd.i32 q5,q5,q0 +vtrn.32 q11,q14 +vadd.i32 q6,q6,q3 +add r2,sp,#560 +vadd.i32 q10,q10,q2 +vtrn.32 d24,d25 +vst1.8 {d12-d13},[r2,: 128] +vshl.i32 q6,q13,#1 +add r2,sp,#576 +vst1.8 {d20-d21},[r2,: 128] +vshl.i32 q10,q14,#1 +add r2,sp,#592 +vst1.8 {d12-d13},[r2,: 128] +vshl.i32 q15,q12,#1 +vadd.i32 q8,q8,q4 +vext.32 d10,d31,d30,#0 +vadd.i32 q7,q7,q1 +add r2,sp,#608 +vst1.8 {d16-d17},[r2,: 128] +vmull.s32 q8,d18,d5 +vmlal.s32 q8,d26,d4 +vmlal.s32 q8,d19,d9 +vmlal.s32 q8,d27,d3 +vmlal.s32 q8,d22,d8 +vmlal.s32 q8,d28,d2 +vmlal.s32 q8,d23,d7 +vmlal.s32 q8,d29,d1 +vmlal.s32 q8,d24,d6 +vmlal.s32 q8,d25,d0 +add r2,sp,#624 +vst1.8 {d14-d15},[r2,: 128] +vmull.s32 q2,d18,d4 +vmlal.s32 q2,d12,d9 +vmlal.s32 q2,d13,d8 +vmlal.s32 q2,d19,d3 +vmlal.s32 q2,d22,d2 +vmlal.s32 q2,d23,d1 +vmlal.s32 q2,d24,d0 +add r2,sp,#640 +vst1.8 {d20-d21},[r2,: 128] +vmull.s32 q7,d18,d9 +vmlal.s32 q7,d26,d3 +vmlal.s32 q7,d19,d8 +vmlal.s32 q7,d27,d2 +vmlal.s32 q7,d22,d7 +vmlal.s32 q7,d28,d1 +vmlal.s32 q7,d23,d6 +vmlal.s32 q7,d29,d0 +add r2,sp,#656 +vst1.8 {d10-d11},[r2,: 128] +vmull.s32 q5,d18,d3 +vmlal.s32 q5,d19,d2 +vmlal.s32 q5,d22,d1 +vmlal.s32 q5,d23,d0 +vmlal.s32 q5,d12,d8 +add r2,sp,#672 +vst1.8 {d16-d17},[r2,: 128] +vmull.s32 q4,d18,d8 +vmlal.s32 q4,d26,d2 +vmlal.s32 q4,d19,d7 +vmlal.s32 q4,d27,d1 +vmlal.s32 q4,d22,d6 +vmlal.s32 q4,d28,d0 +vmull.s32 q8,d18,d7 +vmlal.s32 q8,d26,d1 +vmlal.s32 q8,d19,d6 +vmlal.s32 q8,d27,d0 +add r2,sp,#576 +vld1.8 {d20-d21},[r2,: 128] +vmlal.s32 q7,d24,d21 +vmlal.s32 q7,d25,d20 +vmlal.s32 q4,d23,d21 +vmlal.s32 q4,d29,d20 +vmlal.s32 q8,d22,d21 +vmlal.s32 q8,d28,d20 +vmlal.s32 q5,d24,d20 +add r2,sp,#576 +vst1.8 {d14-d15},[r2,: 128] +vmull.s32 q7,d18,d6 +vmlal.s32 q7,d26,d0 +add r2,sp,#656 +vld1.8 {d30-d31},[r2,: 128] +vmlal.s32 q2,d30,d21 +vmlal.s32 q7,d19,d21 +vmlal.s32 q7,d27,d20 +add r2,sp,#624 +vld1.8 {d26-d27},[r2,: 128] +vmlal.s32 q4,d25,d27 +vmlal.s32 q8,d29,d27 +vmlal.s32 q8,d25,d26 +vmlal.s32 q7,d28,d27 +vmlal.s32 q7,d29,d26 +add r2,sp,#608 +vld1.8 {d28-d29},[r2,: 128] +vmlal.s32 q4,d24,d29 +vmlal.s32 q8,d23,d29 +vmlal.s32 q8,d24,d28 +vmlal.s32 q7,d22,d29 +vmlal.s32 q7,d23,d28 +add r2,sp,#608 +vst1.8 {d8-d9},[r2,: 128] +add r2,sp,#560 +vld1.8 {d8-d9},[r2,: 128] +vmlal.s32 q7,d24,d9 +vmlal.s32 q7,d25,d31 +vmull.s32 q1,d18,d2 +vmlal.s32 q1,d19,d1 +vmlal.s32 q1,d22,d0 +vmlal.s32 q1,d24,d27 +vmlal.s32 q1,d23,d20 +vmlal.s32 q1,d12,d7 +vmlal.s32 q1,d13,d6 +vmull.s32 q6,d18,d1 +vmlal.s32 q6,d19,d0 +vmlal.s32 q6,d23,d27 +vmlal.s32 q6,d22,d20 +vmlal.s32 q6,d24,d26 +vmull.s32 q0,d18,d0 +vmlal.s32 q0,d22,d27 +vmlal.s32 q0,d23,d26 +vmlal.s32 q0,d24,d31 +vmlal.s32 q0,d19,d20 +add r2,sp,#640 +vld1.8 {d18-d19},[r2,: 128] +vmlal.s32 q2,d18,d7 +vmlal.s32 q2,d19,d6 +vmlal.s32 q5,d18,d6 +vmlal.s32 q5,d19,d21 +vmlal.s32 q1,d18,d21 +vmlal.s32 q1,d19,d29 +vmlal.s32 q0,d18,d28 +vmlal.s32 q0,d19,d9 +vmlal.s32 q6,d18,d29 +vmlal.s32 q6,d19,d28 +add r2,sp,#592 +vld1.8 {d18-d19},[r2,: 128] +add r2,sp,#512 +vld1.8 {d22-d23},[r2,: 128] +vmlal.s32 q5,d19,d7 +vmlal.s32 q0,d18,d21 +vmlal.s32 q0,d19,d29 +vmlal.s32 q6,d18,d6 +add r2,sp,#528 +vld1.8 {d6-d7},[r2,: 128] +vmlal.s32 q6,d19,d21 +add r2,sp,#576 +vld1.8 {d18-d19},[r2,: 128] +vmlal.s32 q0,d30,d8 +add r2,sp,#672 +vld1.8 {d20-d21},[r2,: 128] +vmlal.s32 q5,d30,d29 +add r2,sp,#608 +vld1.8 {d24-d25},[r2,: 128] +vmlal.s32 q1,d30,d28 +vadd.i64 q13,q0,q11 +vadd.i64 q14,q5,q11 +vmlal.s32 q6,d30,d9 +vshr.s64 q4,q13,#26 +vshr.s64 q13,q14,#26 +vadd.i64 q7,q7,q4 +vshl.i64 q4,q4,#26 +vadd.i64 q14,q7,q3 +vadd.i64 q9,q9,q13 +vshl.i64 q13,q13,#26 +vadd.i64 q15,q9,q3 +vsub.i64 q0,q0,q4 +vshr.s64 q4,q14,#25 +vsub.i64 q5,q5,q13 +vshr.s64 q13,q15,#25 +vadd.i64 q6,q6,q4 +vshl.i64 q4,q4,#25 +vadd.i64 q14,q6,q11 +vadd.i64 q2,q2,q13 +vsub.i64 q4,q7,q4 +vshr.s64 q7,q14,#26 +vshl.i64 q13,q13,#25 +vadd.i64 q14,q2,q11 +vadd.i64 q8,q8,q7 +vshl.i64 q7,q7,#26 +vadd.i64 q15,q8,q3 +vsub.i64 q9,q9,q13 +vshr.s64 q13,q14,#26 +vsub.i64 q6,q6,q7 +vshr.s64 q7,q15,#25 +vadd.i64 q10,q10,q13 +vshl.i64 q13,q13,#26 +vadd.i64 q14,q10,q3 +vadd.i64 q1,q1,q7 +add r2,r3,#288 +vshl.i64 q7,q7,#25 +add r4,r3,#96 +vadd.i64 q15,q1,q11 +add r2,r2,#8 +vsub.i64 q2,q2,q13 +add r4,r4,#8 +vshr.s64 q13,q14,#25 +vsub.i64 q7,q8,q7 +vshr.s64 q8,q15,#26 +vadd.i64 q14,q13,q13 +vadd.i64 q12,q12,q8 +vtrn.32 d12,d14 +vshl.i64 q8,q8,#26 +vtrn.32 d13,d15 +vadd.i64 q3,q12,q3 +vadd.i64 q0,q0,q14 +vst1.8 d12,[r2,: 64]! +vshl.i64 q7,q13,#4 +vst1.8 d13,[r4,: 64]! +vsub.i64 q1,q1,q8 +vshr.s64 q3,q3,#25 +vadd.i64 q0,q0,q7 +vadd.i64 q5,q5,q3 +vshl.i64 q3,q3,#25 +vadd.i64 q6,q5,q11 +vadd.i64 q0,q0,q13 +vshl.i64 q7,q13,#25 +vadd.i64 q8,q0,q11 +vsub.i64 q3,q12,q3 +vshr.s64 q6,q6,#26 +vsub.i64 q7,q10,q7 +vtrn.32 d2,d6 +vshr.s64 q8,q8,#26 +vtrn.32 d3,d7 +vadd.i64 q3,q9,q6 +vst1.8 d2,[r2,: 64] +vshl.i64 q6,q6,#26 +vst1.8 d3,[r4,: 64] +vadd.i64 q1,q4,q8 +vtrn.32 d4,d14 +vshl.i64 q4,q8,#26 +vtrn.32 d5,d15 +vsub.i64 q5,q5,q6 +add r2,r2,#16 +vsub.i64 q0,q0,q4 +vst1.8 d4,[r2,: 64] +add r4,r4,#16 +vst1.8 d5,[r4,: 64] +vtrn.32 d10,d6 +vtrn.32 d11,d7 +sub r2,r2,#8 +sub r4,r4,#8 +vtrn.32 d0,d2 +vtrn.32 d1,d3 +vst1.8 d10,[r2,: 64] +vst1.8 d11,[r4,: 64] +sub r2,r2,#24 +sub r4,r4,#24 +vst1.8 d0,[r2,: 64] +vst1.8 d1,[r4,: 64] +add r2,sp,#544 +add r4,r3,#144 +add r5,r3,#192 +vld1.8 {d0-d1},[r2,: 128] +vld1.8 {d2-d3},[r4,: 128]! +vld1.8 {d4-d5},[r5,: 128]! +vzip.i32 q1,q2 +vld1.8 {d6-d7},[r4,: 128]! +vld1.8 {d8-d9},[r5,: 128]! +vshl.i32 q5,q1,#1 +vzip.i32 q3,q4 +vshl.i32 q6,q2,#1 +vld1.8 {d14},[r4,: 64] +vshl.i32 q8,q3,#1 +vld1.8 {d15},[r5,: 64] +vshl.i32 q9,q4,#1 +vmul.i32 d21,d7,d1 +vtrn.32 d14,d15 +vmul.i32 q11,q4,q0 +vmul.i32 q0,q7,q0 +vmull.s32 q12,d2,d2 +vmlal.s32 q12,d11,d1 +vmlal.s32 q12,d12,d0 +vmlal.s32 q12,d13,d23 +vmlal.s32 q12,d16,d22 +vmlal.s32 q12,d7,d21 +vmull.s32 q10,d2,d11 +vmlal.s32 q10,d4,d1 +vmlal.s32 q10,d13,d0 +vmlal.s32 q10,d6,d23 +vmlal.s32 q10,d17,d22 +vmull.s32 q13,d10,d4 +vmlal.s32 q13,d11,d3 +vmlal.s32 q13,d13,d1 +vmlal.s32 q13,d16,d0 +vmlal.s32 q13,d17,d23 +vmlal.s32 q13,d8,d22 +vmull.s32 q1,d10,d5 +vmlal.s32 q1,d11,d4 +vmlal.s32 q1,d6,d1 +vmlal.s32 q1,d17,d0 +vmlal.s32 q1,d8,d23 +vmull.s32 q14,d10,d6 +vmlal.s32 q14,d11,d13 +vmlal.s32 q14,d4,d4 +vmlal.s32 q14,d17,d1 +vmlal.s32 q14,d18,d0 +vmlal.s32 q14,d9,d23 +vmull.s32 q11,d10,d7 +vmlal.s32 q11,d11,d6 +vmlal.s32 q11,d12,d5 +vmlal.s32 q11,d8,d1 +vmlal.s32 q11,d19,d0 +vmull.s32 q15,d10,d8 +vmlal.s32 q15,d11,d17 +vmlal.s32 q15,d12,d6 +vmlal.s32 q15,d13,d5 +vmlal.s32 q15,d19,d1 +vmlal.s32 q15,d14,d0 +vmull.s32 q2,d10,d9 +vmlal.s32 q2,d11,d8 +vmlal.s32 q2,d12,d7 +vmlal.s32 q2,d13,d6 +vmlal.s32 q2,d14,d1 +vmull.s32 q0,d15,d1 +vmlal.s32 q0,d10,d14 +vmlal.s32 q0,d11,d19 +vmlal.s32 q0,d12,d8 +vmlal.s32 q0,d13,d17 +vmlal.s32 q0,d6,d6 +add r2,sp,#512 +vld1.8 {d18-d19},[r2,: 128] +vmull.s32 q3,d16,d7 +vmlal.s32 q3,d10,d15 +vmlal.s32 q3,d11,d14 +vmlal.s32 q3,d12,d9 +vmlal.s32 q3,d13,d8 +add r2,sp,#528 +vld1.8 {d8-d9},[r2,: 128] +vadd.i64 q5,q12,q9 +vadd.i64 q6,q15,q9 +vshr.s64 q5,q5,#26 +vshr.s64 q6,q6,#26 +vadd.i64 q7,q10,q5 +vshl.i64 q5,q5,#26 +vadd.i64 q8,q7,q4 +vadd.i64 q2,q2,q6 +vshl.i64 q6,q6,#26 +vadd.i64 q10,q2,q4 +vsub.i64 q5,q12,q5 +vshr.s64 q8,q8,#25 +vsub.i64 q6,q15,q6 +vshr.s64 q10,q10,#25 +vadd.i64 q12,q13,q8 +vshl.i64 q8,q8,#25 +vadd.i64 q13,q12,q9 +vadd.i64 q0,q0,q10 +vsub.i64 q7,q7,q8 +vshr.s64 q8,q13,#26 +vshl.i64 q10,q10,#25 +vadd.i64 q13,q0,q9 +vadd.i64 q1,q1,q8 +vshl.i64 q8,q8,#26 +vadd.i64 q15,q1,q4 +vsub.i64 q2,q2,q10 +vshr.s64 q10,q13,#26 +vsub.i64 q8,q12,q8 +vshr.s64 q12,q15,#25 +vadd.i64 q3,q3,q10 +vshl.i64 q10,q10,#26 +vadd.i64 q13,q3,q4 +vadd.i64 q14,q14,q12 +add r2,r3,#144 +vshl.i64 q12,q12,#25 +add r4,r3,#192 +vadd.i64 q15,q14,q9 +add r2,r2,#8 +vsub.i64 q0,q0,q10 +add r4,r4,#8 +vshr.s64 q10,q13,#25 +vsub.i64 q1,q1,q12 +vshr.s64 q12,q15,#26 +vadd.i64 q13,q10,q10 +vadd.i64 q11,q11,q12 +vtrn.32 d16,d2 +vshl.i64 q12,q12,#26 +vtrn.32 d17,d3 +vadd.i64 q1,q11,q4 +vadd.i64 q4,q5,q13 +vst1.8 d16,[r2,: 64]! +vshl.i64 q5,q10,#4 +vst1.8 d17,[r4,: 64]! +vsub.i64 q8,q14,q12 +vshr.s64 q1,q1,#25 +vadd.i64 q4,q4,q5 +vadd.i64 q5,q6,q1 +vshl.i64 q1,q1,#25 +vadd.i64 q6,q5,q9 +vadd.i64 q4,q4,q10 +vshl.i64 q10,q10,#25 +vadd.i64 q9,q4,q9 +vsub.i64 q1,q11,q1 +vshr.s64 q6,q6,#26 +vsub.i64 q3,q3,q10 +vtrn.32 d16,d2 +vshr.s64 q9,q9,#26 +vtrn.32 d17,d3 +vadd.i64 q1,q2,q6 +vst1.8 d16,[r2,: 64] +vshl.i64 q2,q6,#26 +vst1.8 d17,[r4,: 64] +vadd.i64 q6,q7,q9 +vtrn.32 d0,d6 +vshl.i64 q7,q9,#26 +vtrn.32 d1,d7 +vsub.i64 q2,q5,q2 +add r2,r2,#16 +vsub.i64 q3,q4,q7 +vst1.8 d0,[r2,: 64] +add r4,r4,#16 +vst1.8 d1,[r4,: 64] +vtrn.32 d4,d2 +vtrn.32 d5,d3 +sub r2,r2,#8 +sub r4,r4,#8 +vtrn.32 d6,d12 +vtrn.32 d7,d13 +vst1.8 d4,[r2,: 64] +vst1.8 d5,[r4,: 64] +sub r2,r2,#24 +sub r4,r4,#24 +vst1.8 d6,[r2,: 64] +vst1.8 d7,[r4,: 64] +add r2,r3,#336 +add r4,r3,#288 +vld1.8 {d0-d1},[r2,: 128]! +vld1.8 {d2-d3},[r4,: 128]! +vadd.i32 q0,q0,q1 +vld1.8 {d2-d3},[r2,: 128]! +vld1.8 {d4-d5},[r4,: 128]! +vadd.i32 q1,q1,q2 +add r5,r3,#288 +vld1.8 {d4},[r2,: 64] +vld1.8 {d6},[r4,: 64] +vadd.i32 q2,q2,q3 +vst1.8 {d0-d1},[r5,: 128]! +vst1.8 {d2-d3},[r5,: 128]! +vst1.8 d4,[r5,: 64] +add r2,r3,#48 +add r4,r3,#144 +vld1.8 {d0-d1},[r4,: 128]! +vld1.8 {d2-d3},[r4,: 128]! +vld1.8 {d4},[r4,: 64] +add r4,r3,#288 +vld1.8 {d6-d7},[r4,: 128]! +vtrn.32 q0,q3 +vld1.8 {d8-d9},[r4,: 128]! +vshl.i32 q5,q0,#4 +vtrn.32 q1,q4 +vshl.i32 q6,q3,#4 +vadd.i32 q5,q5,q0 +vadd.i32 q6,q6,q3 +vshl.i32 q7,q1,#4 +vld1.8 {d5},[r4,: 64] +vshl.i32 q8,q4,#4 +vtrn.32 d4,d5 +vadd.i32 q7,q7,q1 +vadd.i32 q8,q8,q4 +vld1.8 {d18-d19},[r2,: 128]! +vshl.i32 q10,q2,#4 +vld1.8 {d22-d23},[r2,: 128]! +vadd.i32 q10,q10,q2 +vld1.8 {d24},[r2,: 64] +vadd.i32 q5,q5,q0 +add r2,r3,#240 +vld1.8 {d26-d27},[r2,: 128]! +vadd.i32 q6,q6,q3 +vld1.8 {d28-d29},[r2,: 128]! +vadd.i32 q8,q8,q4 +vld1.8 {d25},[r2,: 64] +vadd.i32 q10,q10,q2 +vtrn.32 q9,q13 +vadd.i32 q7,q7,q1 +vadd.i32 q5,q5,q0 +vtrn.32 q11,q14 +vadd.i32 q6,q6,q3 +add r2,sp,#560 +vadd.i32 q10,q10,q2 +vtrn.32 d24,d25 +vst1.8 {d12-d13},[r2,: 128] +vshl.i32 q6,q13,#1 +add r2,sp,#576 +vst1.8 {d20-d21},[r2,: 128] +vshl.i32 q10,q14,#1 +add r2,sp,#592 +vst1.8 {d12-d13},[r2,: 128] +vshl.i32 q15,q12,#1 +vadd.i32 q8,q8,q4 +vext.32 d10,d31,d30,#0 +vadd.i32 q7,q7,q1 +add r2,sp,#608 +vst1.8 {d16-d17},[r2,: 128] +vmull.s32 q8,d18,d5 +vmlal.s32 q8,d26,d4 +vmlal.s32 q8,d19,d9 +vmlal.s32 q8,d27,d3 +vmlal.s32 q8,d22,d8 +vmlal.s32 q8,d28,d2 +vmlal.s32 q8,d23,d7 +vmlal.s32 q8,d29,d1 +vmlal.s32 q8,d24,d6 +vmlal.s32 q8,d25,d0 +add r2,sp,#624 +vst1.8 {d14-d15},[r2,: 128] +vmull.s32 q2,d18,d4 +vmlal.s32 q2,d12,d9 +vmlal.s32 q2,d13,d8 +vmlal.s32 q2,d19,d3 +vmlal.s32 q2,d22,d2 +vmlal.s32 q2,d23,d1 +vmlal.s32 q2,d24,d0 +add r2,sp,#640 +vst1.8 {d20-d21},[r2,: 128] +vmull.s32 q7,d18,d9 +vmlal.s32 q7,d26,d3 +vmlal.s32 q7,d19,d8 +vmlal.s32 q7,d27,d2 +vmlal.s32 q7,d22,d7 +vmlal.s32 q7,d28,d1 +vmlal.s32 q7,d23,d6 +vmlal.s32 q7,d29,d0 +add r2,sp,#656 +vst1.8 {d10-d11},[r2,: 128] +vmull.s32 q5,d18,d3 +vmlal.s32 q5,d19,d2 +vmlal.s32 q5,d22,d1 +vmlal.s32 q5,d23,d0 +vmlal.s32 q5,d12,d8 +add r2,sp,#672 +vst1.8 {d16-d17},[r2,: 128] +vmull.s32 q4,d18,d8 +vmlal.s32 q4,d26,d2 +vmlal.s32 q4,d19,d7 +vmlal.s32 q4,d27,d1 +vmlal.s32 q4,d22,d6 +vmlal.s32 q4,d28,d0 +vmull.s32 q8,d18,d7 +vmlal.s32 q8,d26,d1 +vmlal.s32 q8,d19,d6 +vmlal.s32 q8,d27,d0 +add r2,sp,#576 +vld1.8 {d20-d21},[r2,: 128] +vmlal.s32 q7,d24,d21 +vmlal.s32 q7,d25,d20 +vmlal.s32 q4,d23,d21 +vmlal.s32 q4,d29,d20 +vmlal.s32 q8,d22,d21 +vmlal.s32 q8,d28,d20 +vmlal.s32 q5,d24,d20 +add r2,sp,#576 +vst1.8 {d14-d15},[r2,: 128] +vmull.s32 q7,d18,d6 +vmlal.s32 q7,d26,d0 +add r2,sp,#656 +vld1.8 {d30-d31},[r2,: 128] +vmlal.s32 q2,d30,d21 +vmlal.s32 q7,d19,d21 +vmlal.s32 q7,d27,d20 +add r2,sp,#624 +vld1.8 {d26-d27},[r2,: 128] +vmlal.s32 q4,d25,d27 +vmlal.s32 q8,d29,d27 +vmlal.s32 q8,d25,d26 +vmlal.s32 q7,d28,d27 +vmlal.s32 q7,d29,d26 +add r2,sp,#608 +vld1.8 {d28-d29},[r2,: 128] +vmlal.s32 q4,d24,d29 +vmlal.s32 q8,d23,d29 +vmlal.s32 q8,d24,d28 +vmlal.s32 q7,d22,d29 +vmlal.s32 q7,d23,d28 +add r2,sp,#608 +vst1.8 {d8-d9},[r2,: 128] +add r2,sp,#560 +vld1.8 {d8-d9},[r2,: 128] +vmlal.s32 q7,d24,d9 +vmlal.s32 q7,d25,d31 +vmull.s32 q1,d18,d2 +vmlal.s32 q1,d19,d1 +vmlal.s32 q1,d22,d0 +vmlal.s32 q1,d24,d27 +vmlal.s32 q1,d23,d20 +vmlal.s32 q1,d12,d7 +vmlal.s32 q1,d13,d6 +vmull.s32 q6,d18,d1 +vmlal.s32 q6,d19,d0 +vmlal.s32 q6,d23,d27 +vmlal.s32 q6,d22,d20 +vmlal.s32 q6,d24,d26 +vmull.s32 q0,d18,d0 +vmlal.s32 q0,d22,d27 +vmlal.s32 q0,d23,d26 +vmlal.s32 q0,d24,d31 +vmlal.s32 q0,d19,d20 +add r2,sp,#640 +vld1.8 {d18-d19},[r2,: 128] +vmlal.s32 q2,d18,d7 +vmlal.s32 q2,d19,d6 +vmlal.s32 q5,d18,d6 +vmlal.s32 q5,d19,d21 +vmlal.s32 q1,d18,d21 +vmlal.s32 q1,d19,d29 +vmlal.s32 q0,d18,d28 +vmlal.s32 q0,d19,d9 +vmlal.s32 q6,d18,d29 +vmlal.s32 q6,d19,d28 +add r2,sp,#592 +vld1.8 {d18-d19},[r2,: 128] +add r2,sp,#512 +vld1.8 {d22-d23},[r2,: 128] +vmlal.s32 q5,d19,d7 +vmlal.s32 q0,d18,d21 +vmlal.s32 q0,d19,d29 +vmlal.s32 q6,d18,d6 +add r2,sp,#528 +vld1.8 {d6-d7},[r2,: 128] +vmlal.s32 q6,d19,d21 +add r2,sp,#576 +vld1.8 {d18-d19},[r2,: 128] +vmlal.s32 q0,d30,d8 +add r2,sp,#672 +vld1.8 {d20-d21},[r2,: 128] +vmlal.s32 q5,d30,d29 +add r2,sp,#608 +vld1.8 {d24-d25},[r2,: 128] +vmlal.s32 q1,d30,d28 +vadd.i64 q13,q0,q11 +vadd.i64 q14,q5,q11 +vmlal.s32 q6,d30,d9 +vshr.s64 q4,q13,#26 +vshr.s64 q13,q14,#26 +vadd.i64 q7,q7,q4 +vshl.i64 q4,q4,#26 +vadd.i64 q14,q7,q3 +vadd.i64 q9,q9,q13 +vshl.i64 q13,q13,#26 +vadd.i64 q15,q9,q3 +vsub.i64 q0,q0,q4 +vshr.s64 q4,q14,#25 +vsub.i64 q5,q5,q13 +vshr.s64 q13,q15,#25 +vadd.i64 q6,q6,q4 +vshl.i64 q4,q4,#25 +vadd.i64 q14,q6,q11 +vadd.i64 q2,q2,q13 +vsub.i64 q4,q7,q4 +vshr.s64 q7,q14,#26 +vshl.i64 q13,q13,#25 +vadd.i64 q14,q2,q11 +vadd.i64 q8,q8,q7 +vshl.i64 q7,q7,#26 +vadd.i64 q15,q8,q3 +vsub.i64 q9,q9,q13 +vshr.s64 q13,q14,#26 +vsub.i64 q6,q6,q7 +vshr.s64 q7,q15,#25 +vadd.i64 q10,q10,q13 +vshl.i64 q13,q13,#26 +vadd.i64 q14,q10,q3 +vadd.i64 q1,q1,q7 +add r2,r3,#240 +vshl.i64 q7,q7,#25 +add r4,r3,#144 +vadd.i64 q15,q1,q11 +add r2,r2,#8 +vsub.i64 q2,q2,q13 +add r4,r4,#8 +vshr.s64 q13,q14,#25 +vsub.i64 q7,q8,q7 +vshr.s64 q8,q15,#26 +vadd.i64 q14,q13,q13 +vadd.i64 q12,q12,q8 +vtrn.32 d12,d14 +vshl.i64 q8,q8,#26 +vtrn.32 d13,d15 +vadd.i64 q3,q12,q3 +vadd.i64 q0,q0,q14 +vst1.8 d12,[r2,: 64]! +vshl.i64 q7,q13,#4 +vst1.8 d13,[r4,: 64]! +vsub.i64 q1,q1,q8 +vshr.s64 q3,q3,#25 +vadd.i64 q0,q0,q7 +vadd.i64 q5,q5,q3 +vshl.i64 q3,q3,#25 +vadd.i64 q6,q5,q11 +vadd.i64 q0,q0,q13 +vshl.i64 q7,q13,#25 +vadd.i64 q8,q0,q11 +vsub.i64 q3,q12,q3 +vshr.s64 q6,q6,#26 +vsub.i64 q7,q10,q7 +vtrn.32 d2,d6 +vshr.s64 q8,q8,#26 +vtrn.32 d3,d7 +vadd.i64 q3,q9,q6 +vst1.8 d2,[r2,: 64] +vshl.i64 q6,q6,#26 +vst1.8 d3,[r4,: 64] +vadd.i64 q1,q4,q8 +vtrn.32 d4,d14 +vshl.i64 q4,q8,#26 +vtrn.32 d5,d15 +vsub.i64 q5,q5,q6 +add r2,r2,#16 +vsub.i64 q0,q0,q4 +vst1.8 d4,[r2,: 64] +add r4,r4,#16 +vst1.8 d5,[r4,: 64] +vtrn.32 d10,d6 +vtrn.32 d11,d7 +sub r2,r2,#8 +sub r4,r4,#8 +vtrn.32 d0,d2 +vtrn.32 d1,d3 +vst1.8 d10,[r2,: 64] +vst1.8 d11,[r4,: 64] +sub r2,r2,#24 +sub r4,r4,#24 +vst1.8 d0,[r2,: 64] +vst1.8 d1,[r4,: 64] +ldr r2,[sp,#488] +ldr r4,[sp,#492] +subs r5,r2,#1 +bge ._mainloop +add r1,r3,#144 +add r2,r3,#336 +vld1.8 {d0-d1},[r1,: 128]! +vld1.8 {d2-d3},[r1,: 128]! +vld1.8 {d4},[r1,: 64] +vst1.8 {d0-d1},[r2,: 128]! +vst1.8 {d2-d3},[r2,: 128]! +vst1.8 d4,[r2,: 64] +ldr r1,=0 +._invertloop: +add r2,r3,#144 +ldr r4,=0 +ldr r5,=2 +cmp r1,#1 +ldreq r5,=1 +addeq r2,r3,#336 +addeq r4,r3,#48 +cmp r1,#2 +ldreq r5,=1 +addeq r2,r3,#48 +cmp r1,#3 +ldreq r5,=5 +addeq r4,r3,#336 +cmp r1,#4 +ldreq r5,=10 +cmp r1,#5 +ldreq r5,=20 +cmp r1,#6 +ldreq r5,=10 +addeq r2,r3,#336 +addeq r4,r3,#336 +cmp r1,#7 +ldreq r5,=50 +cmp r1,#8 +ldreq r5,=100 +cmp r1,#9 +ldreq r5,=50 +addeq r2,r3,#336 +cmp r1,#10 +ldreq r5,=5 +addeq r2,r3,#48 +cmp r1,#11 +ldreq r5,=0 +addeq r2,r3,#96 +add r6,r3,#144 +add r7,r3,#288 +vld1.8 {d0-d1},[r6,: 128]! +vld1.8 {d2-d3},[r6,: 128]! +vld1.8 {d4},[r6,: 64] +vst1.8 {d0-d1},[r7,: 128]! +vst1.8 {d2-d3},[r7,: 128]! +vst1.8 d4,[r7,: 64] +cmp r5,#0 +beq ._skipsquaringloop +._squaringloop: +add r6,r3,#288 +add r7,r3,#288 +add r8,r3,#288 +vmov.i32 q0,#19 +vmov.i32 q1,#0 +vmov.i32 q2,#1 +vzip.i32 q1,q2 +vld1.8 {d4-d5},[r7,: 128]! +vld1.8 {d6-d7},[r7,: 128]! +vld1.8 {d9},[r7,: 64] +vld1.8 {d10-d11},[r6,: 128]! +add r7,sp,#416 +vld1.8 {d12-d13},[r6,: 128]! +vmul.i32 q7,q2,q0 +vld1.8 {d8},[r6,: 64] +vext.32 d17,d11,d10,#1 +vmul.i32 q9,q3,q0 +vext.32 d16,d10,d8,#1 +vshl.u32 q10,q5,q1 +vext.32 d22,d14,d4,#1 +vext.32 d24,d18,d6,#1 +vshl.u32 q13,q6,q1 +vshl.u32 d28,d8,d2 +vrev64.i32 d22,d22 +vmul.i32 d1,d9,d1 +vrev64.i32 d24,d24 +vext.32 d29,d8,d13,#1 +vext.32 d0,d1,d9,#1 +vrev64.i32 d0,d0 +vext.32 d2,d9,d1,#1 +vext.32 d23,d15,d5,#1 +vmull.s32 q4,d20,d4 +vrev64.i32 d23,d23 +vmlal.s32 q4,d21,d1 +vrev64.i32 d2,d2 +vmlal.s32 q4,d26,d19 +vext.32 d3,d5,d15,#1 +vmlal.s32 q4,d27,d18 +vrev64.i32 d3,d3 +vmlal.s32 q4,d28,d15 +vext.32 d14,d12,d11,#1 +vmull.s32 q5,d16,d23 +vext.32 d15,d13,d12,#1 +vmlal.s32 q5,d17,d4 +vst1.8 d8,[r7,: 64]! +vmlal.s32 q5,d14,d1 +vext.32 d12,d9,d8,#0 +vmlal.s32 q5,d15,d19 +vmov.i64 d13,#0 +vmlal.s32 q5,d29,d18 +vext.32 d25,d19,d7,#1 +vmlal.s32 q6,d20,d5 +vrev64.i32 d25,d25 +vmlal.s32 q6,d21,d4 +vst1.8 d11,[r7,: 64]! +vmlal.s32 q6,d26,d1 +vext.32 d9,d10,d10,#0 +vmlal.s32 q6,d27,d19 +vmov.i64 d8,#0 +vmlal.s32 q6,d28,d18 +vmlal.s32 q4,d16,d24 +vmlal.s32 q4,d17,d5 +vmlal.s32 q4,d14,d4 +vst1.8 d12,[r7,: 64]! +vmlal.s32 q4,d15,d1 +vext.32 d10,d13,d12,#0 +vmlal.s32 q4,d29,d19 +vmov.i64 d11,#0 +vmlal.s32 q5,d20,d6 +vmlal.s32 q5,d21,d5 +vmlal.s32 q5,d26,d4 +vext.32 d13,d8,d8,#0 +vmlal.s32 q5,d27,d1 +vmov.i64 d12,#0 +vmlal.s32 q5,d28,d19 +vst1.8 d9,[r7,: 64]! +vmlal.s32 q6,d16,d25 +vmlal.s32 q6,d17,d6 +vst1.8 d10,[r7,: 64] +vmlal.s32 q6,d14,d5 +vext.32 d8,d11,d10,#0 +vmlal.s32 q6,d15,d4 +vmov.i64 d9,#0 +vmlal.s32 q6,d29,d1 +vmlal.s32 q4,d20,d7 +vmlal.s32 q4,d21,d6 +vmlal.s32 q4,d26,d5 +vext.32 d11,d12,d12,#0 +vmlal.s32 q4,d27,d4 +vmov.i64 d10,#0 +vmlal.s32 q4,d28,d1 +vmlal.s32 q5,d16,d0 +sub r6,r7,#32 +vmlal.s32 q5,d17,d7 +vmlal.s32 q5,d14,d6 +vext.32 d30,d9,d8,#0 +vmlal.s32 q5,d15,d5 +vld1.8 {d31},[r6,: 64]! +vmlal.s32 q5,d29,d4 +vmlal.s32 q15,d20,d0 +vext.32 d0,d6,d18,#1 +vmlal.s32 q15,d21,d25 +vrev64.i32 d0,d0 +vmlal.s32 q15,d26,d24 +vext.32 d1,d7,d19,#1 +vext.32 d7,d10,d10,#0 +vmlal.s32 q15,d27,d23 +vrev64.i32 d1,d1 +vld1.8 {d6},[r6,: 64] +vmlal.s32 q15,d28,d22 +vmlal.s32 q3,d16,d4 +add r6,r6,#24 +vmlal.s32 q3,d17,d2 +vext.32 d4,d31,d30,#0 +vmov d17,d11 +vmlal.s32 q3,d14,d1 +vext.32 d11,d13,d13,#0 +vext.32 d13,d30,d30,#0 +vmlal.s32 q3,d15,d0 +vext.32 d1,d8,d8,#0 +vmlal.s32 q3,d29,d3 +vld1.8 {d5},[r6,: 64] +sub r6,r6,#16 +vext.32 d10,d6,d6,#0 +vmov.i32 q1,#0xffffffff +vshl.i64 q4,q1,#25 +add r7,sp,#512 +vld1.8 {d14-d15},[r7,: 128] +vadd.i64 q9,q2,q7 +vshl.i64 q1,q1,#26 +vshr.s64 q10,q9,#26 +vld1.8 {d0},[r6,: 64]! +vadd.i64 q5,q5,q10 +vand q9,q9,q1 +vld1.8 {d16},[r6,: 64]! +add r6,sp,#528 +vld1.8 {d20-d21},[r6,: 128] +vadd.i64 q11,q5,q10 +vsub.i64 q2,q2,q9 +vshr.s64 q9,q11,#25 +vext.32 d12,d5,d4,#0 +vand q11,q11,q4 +vadd.i64 q0,q0,q9 +vmov d19,d7 +vadd.i64 q3,q0,q7 +vsub.i64 q5,q5,q11 +vshr.s64 q11,q3,#26 +vext.32 d18,d11,d10,#0 +vand q3,q3,q1 +vadd.i64 q8,q8,q11 +vadd.i64 q11,q8,q10 +vsub.i64 q0,q0,q3 +vshr.s64 q3,q11,#25 +vand q11,q11,q4 +vadd.i64 q3,q6,q3 +vadd.i64 q6,q3,q7 +vsub.i64 q8,q8,q11 +vshr.s64 q11,q6,#26 +vand q6,q6,q1 +vadd.i64 q9,q9,q11 +vadd.i64 d25,d19,d21 +vsub.i64 q3,q3,q6 +vshr.s64 d23,d25,#25 +vand q4,q12,q4 +vadd.i64 d21,d23,d23 +vshl.i64 d25,d23,#4 +vadd.i64 d21,d21,d23 +vadd.i64 d25,d25,d21 +vadd.i64 d4,d4,d25 +vzip.i32 q0,q8 +vadd.i64 d12,d4,d14 +add r6,r8,#8 +vst1.8 d0,[r6,: 64] +vsub.i64 d19,d19,d9 +add r6,r6,#16 +vst1.8 d16,[r6,: 64] +vshr.s64 d22,d12,#26 +vand q0,q6,q1 +vadd.i64 d10,d10,d22 +vzip.i32 q3,q9 +vsub.i64 d4,d4,d0 +sub r6,r6,#8 +vst1.8 d6,[r6,: 64] +add r6,r6,#16 +vst1.8 d18,[r6,: 64] +vzip.i32 q2,q5 +sub r6,r6,#32 +vst1.8 d4,[r6,: 64] +subs r5,r5,#1 +bhi ._squaringloop +._skipsquaringloop: +mov r2,r2 +add r5,r3,#288 +add r6,r3,#144 +vmov.i32 q0,#19 +vmov.i32 q1,#0 +vmov.i32 q2,#1 +vzip.i32 q1,q2 +vld1.8 {d4-d5},[r5,: 128]! +vld1.8 {d6-d7},[r5,: 128]! +vld1.8 {d9},[r5,: 64] +vld1.8 {d10-d11},[r2,: 128]! +add r5,sp,#416 +vld1.8 {d12-d13},[r2,: 128]! +vmul.i32 q7,q2,q0 +vld1.8 {d8},[r2,: 64] +vext.32 d17,d11,d10,#1 +vmul.i32 q9,q3,q0 +vext.32 d16,d10,d8,#1 +vshl.u32 q10,q5,q1 +vext.32 d22,d14,d4,#1 +vext.32 d24,d18,d6,#1 +vshl.u32 q13,q6,q1 +vshl.u32 d28,d8,d2 +vrev64.i32 d22,d22 +vmul.i32 d1,d9,d1 +vrev64.i32 d24,d24 +vext.32 d29,d8,d13,#1 +vext.32 d0,d1,d9,#1 +vrev64.i32 d0,d0 +vext.32 d2,d9,d1,#1 +vext.32 d23,d15,d5,#1 +vmull.s32 q4,d20,d4 +vrev64.i32 d23,d23 +vmlal.s32 q4,d21,d1 +vrev64.i32 d2,d2 +vmlal.s32 q4,d26,d19 +vext.32 d3,d5,d15,#1 +vmlal.s32 q4,d27,d18 +vrev64.i32 d3,d3 +vmlal.s32 q4,d28,d15 +vext.32 d14,d12,d11,#1 +vmull.s32 q5,d16,d23 +vext.32 d15,d13,d12,#1 +vmlal.s32 q5,d17,d4 +vst1.8 d8,[r5,: 64]! +vmlal.s32 q5,d14,d1 +vext.32 d12,d9,d8,#0 +vmlal.s32 q5,d15,d19 +vmov.i64 d13,#0 +vmlal.s32 q5,d29,d18 +vext.32 d25,d19,d7,#1 +vmlal.s32 q6,d20,d5 +vrev64.i32 d25,d25 +vmlal.s32 q6,d21,d4 +vst1.8 d11,[r5,: 64]! +vmlal.s32 q6,d26,d1 +vext.32 d9,d10,d10,#0 +vmlal.s32 q6,d27,d19 +vmov.i64 d8,#0 +vmlal.s32 q6,d28,d18 +vmlal.s32 q4,d16,d24 +vmlal.s32 q4,d17,d5 +vmlal.s32 q4,d14,d4 +vst1.8 d12,[r5,: 64]! +vmlal.s32 q4,d15,d1 +vext.32 d10,d13,d12,#0 +vmlal.s32 q4,d29,d19 +vmov.i64 d11,#0 +vmlal.s32 q5,d20,d6 +vmlal.s32 q5,d21,d5 +vmlal.s32 q5,d26,d4 +vext.32 d13,d8,d8,#0 +vmlal.s32 q5,d27,d1 +vmov.i64 d12,#0 +vmlal.s32 q5,d28,d19 +vst1.8 d9,[r5,: 64]! +vmlal.s32 q6,d16,d25 +vmlal.s32 q6,d17,d6 +vst1.8 d10,[r5,: 64] +vmlal.s32 q6,d14,d5 +vext.32 d8,d11,d10,#0 +vmlal.s32 q6,d15,d4 +vmov.i64 d9,#0 +vmlal.s32 q6,d29,d1 +vmlal.s32 q4,d20,d7 +vmlal.s32 q4,d21,d6 +vmlal.s32 q4,d26,d5 +vext.32 d11,d12,d12,#0 +vmlal.s32 q4,d27,d4 +vmov.i64 d10,#0 +vmlal.s32 q4,d28,d1 +vmlal.s32 q5,d16,d0 +sub r2,r5,#32 +vmlal.s32 q5,d17,d7 +vmlal.s32 q5,d14,d6 +vext.32 d30,d9,d8,#0 +vmlal.s32 q5,d15,d5 +vld1.8 {d31},[r2,: 64]! +vmlal.s32 q5,d29,d4 +vmlal.s32 q15,d20,d0 +vext.32 d0,d6,d18,#1 +vmlal.s32 q15,d21,d25 +vrev64.i32 d0,d0 +vmlal.s32 q15,d26,d24 +vext.32 d1,d7,d19,#1 +vext.32 d7,d10,d10,#0 +vmlal.s32 q15,d27,d23 +vrev64.i32 d1,d1 +vld1.8 {d6},[r2,: 64] +vmlal.s32 q15,d28,d22 +vmlal.s32 q3,d16,d4 +add r2,r2,#24 +vmlal.s32 q3,d17,d2 +vext.32 d4,d31,d30,#0 +vmov d17,d11 +vmlal.s32 q3,d14,d1 +vext.32 d11,d13,d13,#0 +vext.32 d13,d30,d30,#0 +vmlal.s32 q3,d15,d0 +vext.32 d1,d8,d8,#0 +vmlal.s32 q3,d29,d3 +vld1.8 {d5},[r2,: 64] +sub r2,r2,#16 +vext.32 d10,d6,d6,#0 +vmov.i32 q1,#0xffffffff +vshl.i64 q4,q1,#25 +add r5,sp,#512 +vld1.8 {d14-d15},[r5,: 128] +vadd.i64 q9,q2,q7 +vshl.i64 q1,q1,#26 +vshr.s64 q10,q9,#26 +vld1.8 {d0},[r2,: 64]! +vadd.i64 q5,q5,q10 +vand q9,q9,q1 +vld1.8 {d16},[r2,: 64]! +add r2,sp,#528 +vld1.8 {d20-d21},[r2,: 128] +vadd.i64 q11,q5,q10 +vsub.i64 q2,q2,q9 +vshr.s64 q9,q11,#25 +vext.32 d12,d5,d4,#0 +vand q11,q11,q4 +vadd.i64 q0,q0,q9 +vmov d19,d7 +vadd.i64 q3,q0,q7 +vsub.i64 q5,q5,q11 +vshr.s64 q11,q3,#26 +vext.32 d18,d11,d10,#0 +vand q3,q3,q1 +vadd.i64 q8,q8,q11 +vadd.i64 q11,q8,q10 +vsub.i64 q0,q0,q3 +vshr.s64 q3,q11,#25 +vand q11,q11,q4 +vadd.i64 q3,q6,q3 +vadd.i64 q6,q3,q7 +vsub.i64 q8,q8,q11 +vshr.s64 q11,q6,#26 +vand q6,q6,q1 +vadd.i64 q9,q9,q11 +vadd.i64 d25,d19,d21 +vsub.i64 q3,q3,q6 +vshr.s64 d23,d25,#25 +vand q4,q12,q4 +vadd.i64 d21,d23,d23 +vshl.i64 d25,d23,#4 +vadd.i64 d21,d21,d23 +vadd.i64 d25,d25,d21 +vadd.i64 d4,d4,d25 +vzip.i32 q0,q8 +vadd.i64 d12,d4,d14 +add r2,r6,#8 +vst1.8 d0,[r2,: 64] +vsub.i64 d19,d19,d9 +add r2,r2,#16 +vst1.8 d16,[r2,: 64] +vshr.s64 d22,d12,#26 +vand q0,q6,q1 +vadd.i64 d10,d10,d22 +vzip.i32 q3,q9 +vsub.i64 d4,d4,d0 +sub r2,r2,#8 +vst1.8 d6,[r2,: 64] +add r2,r2,#16 +vst1.8 d18,[r2,: 64] +vzip.i32 q2,q5 +sub r2,r2,#32 +vst1.8 d4,[r2,: 64] +cmp r4,#0 +beq ._skippostcopy +add r2,r3,#144 +mov r4,r4 +vld1.8 {d0-d1},[r2,: 128]! +vld1.8 {d2-d3},[r2,: 128]! +vld1.8 {d4},[r2,: 64] +vst1.8 {d0-d1},[r4,: 128]! +vst1.8 {d2-d3},[r4,: 128]! +vst1.8 d4,[r4,: 64] +._skippostcopy: +cmp r1,#1 +bne ._skipfinalcopy +add r2,r3,#288 +add r4,r3,#144 +vld1.8 {d0-d1},[r2,: 128]! +vld1.8 {d2-d3},[r2,: 128]! +vld1.8 {d4},[r2,: 64] +vst1.8 {d0-d1},[r4,: 128]! +vst1.8 {d2-d3},[r4,: 128]! +vst1.8 d4,[r4,: 64] +._skipfinalcopy: +add r1,r1,#1 +cmp r1,#12 +blo ._invertloop +add r1,r3,#144 +ldr r2,[r1],#4 +ldr r3,[r1],#4 +ldr r4,[r1],#4 +ldr r5,[r1],#4 +ldr r6,[r1],#4 +ldr r7,[r1],#4 +ldr r8,[r1],#4 +ldr r9,[r1],#4 +ldr r10,[r1],#4 +ldr r1,[r1] +add r11,r1,r1,LSL #4 +add r11,r11,r1,LSL #1 +add r11,r11,#16777216 +mov r11,r11,ASR #25 +add r11,r11,r2 +mov r11,r11,ASR #26 +add r11,r11,r3 +mov r11,r11,ASR #25 +add r11,r11,r4 +mov r11,r11,ASR #26 +add r11,r11,r5 +mov r11,r11,ASR #25 +add r11,r11,r6 +mov r11,r11,ASR #26 +add r11,r11,r7 +mov r11,r11,ASR #25 +add r11,r11,r8 +mov r11,r11,ASR #26 +add r11,r11,r9 +mov r11,r11,ASR #25 +add r11,r11,r10 +mov r11,r11,ASR #26 +add r11,r11,r1 +mov r11,r11,ASR #25 +add r2,r2,r11 +add r2,r2,r11,LSL #1 +add r2,r2,r11,LSL #4 +mov r11,r2,ASR #26 +add r3,r3,r11 +sub r2,r2,r11,LSL #26 +mov r11,r3,ASR #25 +add r4,r4,r11 +sub r3,r3,r11,LSL #25 +mov r11,r4,ASR #26 +add r5,r5,r11 +sub r4,r4,r11,LSL #26 +mov r11,r5,ASR #25 +add r6,r6,r11 +sub r5,r5,r11,LSL #25 +mov r11,r6,ASR #26 +add r7,r7,r11 +sub r6,r6,r11,LSL #26 +mov r11,r7,ASR #25 +add r8,r8,r11 +sub r7,r7,r11,LSL #25 +mov r11,r8,ASR #26 +add r9,r9,r11 +sub r8,r8,r11,LSL #26 +mov r11,r9,ASR #25 +add r10,r10,r11 +sub r9,r9,r11,LSL #25 +mov r11,r10,ASR #26 +add r1,r1,r11 +sub r10,r10,r11,LSL #26 +mov r11,r1,ASR #25 +sub r1,r1,r11,LSL #25 +add r2,r2,r3,LSL #26 +mov r3,r3,LSR #6 +add r3,r3,r4,LSL #19 +mov r4,r4,LSR #13 +add r4,r4,r5,LSL #13 +mov r5,r5,LSR #19 +add r5,r5,r6,LSL #6 +add r6,r7,r8,LSL #25 +mov r7,r8,LSR #7 +add r7,r7,r9,LSL #19 +mov r8,r9,LSR #13 +add r8,r8,r10,LSL #12 +mov r9,r10,LSR #20 +add r1,r9,r1,LSL #6 +str r2,[r0],#4 +str r3,[r0],#4 +str r4,[r0],#4 +str r5,[r0],#4 +str r6,[r0],#4 +str r7,[r0],#4 +str r8,[r0],#4 +str r1,[r0] +ldrd r4,[sp,#0] +ldrd r6,[sp,#8] +ldrd r8,[sp,#16] +ldrd r10,[sp,#24] +ldr r12,[sp,#480] +ldr r14,[sp,#484] +ldr r0,=0 +mov sp,r12 +vpop {q4,q5,q6,q7} +bx lr + +#endif /* __arm__ */ +#endif /* !OPENSSL_NO_ASM */ diff --git a/external/boringssl/crypto/curve25519/asm/x25519-asm-x86_64.S b/external/boringssl/crypto/curve25519/asm/x25519-asm-x86_64.S new file mode 100644 index 0000000000..531ac16332 --- /dev/null +++ b/external/boringssl/crypto/curve25519/asm/x25519-asm-x86_64.S @@ -0,0 +1,1937 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +/* This file is adapted from crypto_scalarmult/curve25519/amd64-51/ in + * SUPERCOP 20141124 (http://bench.cr.yp.to/supercop.html). That code is public + * domain licensed but the standard ISC license is included above to keep + * licensing simple. */ + +#if !defined(OPENSSL_NO_ASM) +#if defined(__x86_64__) + +.data +.p2align 4 + +#if defined(__APPLE__) +/* OS X's C ABI prefixes functions with underscore. */ +#define C_ABI(x) _ ## x +#define HIDDEN .private_extern +#else +#define C_ABI(x) x +#define HIDDEN .hidden +#endif + +x25519_x86_64_REDMASK51: .quad 0x0007FFFFFFFFFFFF +x25519_x86_64_121666_213: .quad 996687872 +x25519_x86_64_2P0: .quad 0xFFFFFFFFFFFDA +x25519_x86_64_2P1234: .quad 0xFFFFFFFFFFFFE +x25519_x86_64_4P0: .quad 0x1FFFFFFFFFFFB4 +x25519_x86_64_4P1234: .quad 0x1FFFFFFFFFFFFC +x25519_x86_64_MU0: .quad 0xED9CE5A30A2C131B +x25519_x86_64_MU1: .quad 0x2106215D086329A7 +x25519_x86_64_MU2: .quad 0xFFFFFFFFFFFFFFEB +x25519_x86_64_MU3: .quad 0xFFFFFFFFFFFFFFFF +x25519_x86_64_MU4: .quad 0x000000000000000F +x25519_x86_64_ORDER0: .quad 0x5812631A5CF5D3ED +x25519_x86_64_ORDER1: .quad 0x14DEF9DEA2F79CD6 +x25519_x86_64_ORDER2: .quad 0x0000000000000000 +x25519_x86_64_ORDER3: .quad 0x1000000000000000 +x25519_x86_64_EC2D0: .quad 1859910466990425 +x25519_x86_64_EC2D1: .quad 932731440258426 +x25519_x86_64_EC2D2: .quad 1072319116312658 +x25519_x86_64_EC2D3: .quad 1815898335770999 +x25519_x86_64_EC2D4: .quad 633789495995903 +x25519_x86_64__38: .quad 38 + +.text +.p2align 5 + +.globl C_ABI(x25519_x86_64_freeze) +HIDDEN C_ABI(x25519_x86_64_freeze) +C_ABI(x25519_x86_64_freeze): +mov %rsp,%r11 +and $31,%r11 +add $64,%r11 +sub %r11,%rsp +movq %r11,0(%rsp) +movq %r12,8(%rsp) +movq %r13,16(%rsp) +movq %r14,24(%rsp) +movq %r15,32(%rsp) +movq %rbx,40(%rsp) +movq %rbp,48(%rsp) +movq 0(%rdi),%rsi +movq 8(%rdi),%rdx +movq 16(%rdi),%rcx +movq 24(%rdi),%r8 +movq 32(%rdi),%r9 +movq x25519_x86_64_REDMASK51(%rip),%rax +mov %rax,%r10 +sub $18,%r10 +mov $3,%r11 +._reduceloop: +mov %rsi,%r12 +shr $51,%r12 +and %rax,%rsi +add %r12,%rdx +mov %rdx,%r12 +shr $51,%r12 +and %rax,%rdx +add %r12,%rcx +mov %rcx,%r12 +shr $51,%r12 +and %rax,%rcx +add %r12,%r8 +mov %r8,%r12 +shr $51,%r12 +and %rax,%r8 +add %r12,%r9 +mov %r9,%r12 +shr $51,%r12 +and %rax,%r9 +imulq $19,%r12,%r12 +add %r12,%rsi +sub $1,%r11 +ja ._reduceloop +mov $1,%r12 +cmp %r10,%rsi +cmovl %r11,%r12 +cmp %rax,%rdx +cmovne %r11,%r12 +cmp %rax,%rcx +cmovne %r11,%r12 +cmp %rax,%r8 +cmovne %r11,%r12 +cmp %rax,%r9 +cmovne %r11,%r12 +neg %r12 +and %r12,%rax +and %r12,%r10 +sub %r10,%rsi +sub %rax,%rdx +sub %rax,%rcx +sub %rax,%r8 +sub %rax,%r9 +movq %rsi,0(%rdi) +movq %rdx,8(%rdi) +movq %rcx,16(%rdi) +movq %r8,24(%rdi) +movq %r9,32(%rdi) +movq 0(%rsp),%r11 +movq 8(%rsp),%r12 +movq 16(%rsp),%r13 +movq 24(%rsp),%r14 +movq 32(%rsp),%r15 +movq 40(%rsp),%rbx +movq 48(%rsp),%rbp +add %r11,%rsp +mov %rdi,%rax +mov %rsi,%rdx +ret + +.p2align 5 +.globl C_ABI(x25519_x86_64_mul) +HIDDEN C_ABI(x25519_x86_64_mul) +C_ABI(x25519_x86_64_mul): +mov %rsp,%r11 +and $31,%r11 +add $96,%r11 +sub %r11,%rsp +movq %r11,0(%rsp) +movq %r12,8(%rsp) +movq %r13,16(%rsp) +movq %r14,24(%rsp) +movq %r15,32(%rsp) +movq %rbx,40(%rsp) +movq %rbp,48(%rsp) +movq %rdi,56(%rsp) +mov %rdx,%rcx +movq 24(%rsi),%rdx +imulq $19,%rdx,%rax +movq %rax,64(%rsp) +mulq 16(%rcx) +mov %rax,%r8 +mov %rdx,%r9 +movq 32(%rsi),%rdx +imulq $19,%rdx,%rax +movq %rax,72(%rsp) +mulq 8(%rcx) +add %rax,%r8 +adc %rdx,%r9 +movq 0(%rsi),%rax +mulq 0(%rcx) +add %rax,%r8 +adc %rdx,%r9 +movq 0(%rsi),%rax +mulq 8(%rcx) +mov %rax,%r10 +mov %rdx,%r11 +movq 0(%rsi),%rax +mulq 16(%rcx) +mov %rax,%r12 +mov %rdx,%r13 +movq 0(%rsi),%rax +mulq 24(%rcx) +mov %rax,%r14 +mov %rdx,%r15 +movq 0(%rsi),%rax +mulq 32(%rcx) +mov %rax,%rbx +mov %rdx,%rbp +movq 8(%rsi),%rax +mulq 0(%rcx) +add %rax,%r10 +adc %rdx,%r11 +movq 8(%rsi),%rax +mulq 8(%rcx) +add %rax,%r12 +adc %rdx,%r13 +movq 8(%rsi),%rax +mulq 16(%rcx) +add %rax,%r14 +adc %rdx,%r15 +movq 8(%rsi),%rax +mulq 24(%rcx) +add %rax,%rbx +adc %rdx,%rbp +movq 8(%rsi),%rdx +imulq $19,%rdx,%rax +mulq 32(%rcx) +add %rax,%r8 +adc %rdx,%r9 +movq 16(%rsi),%rax +mulq 0(%rcx) +add %rax,%r12 +adc %rdx,%r13 +movq 16(%rsi),%rax +mulq 8(%rcx) +add %rax,%r14 +adc %rdx,%r15 +movq 16(%rsi),%rax +mulq 16(%rcx) +add %rax,%rbx +adc %rdx,%rbp +movq 16(%rsi),%rdx +imulq $19,%rdx,%rax +mulq 24(%rcx) +add %rax,%r8 +adc %rdx,%r9 +movq 16(%rsi),%rdx +imulq $19,%rdx,%rax +mulq 32(%rcx) +add %rax,%r10 +adc %rdx,%r11 +movq 24(%rsi),%rax +mulq 0(%rcx) +add %rax,%r14 +adc %rdx,%r15 +movq 24(%rsi),%rax +mulq 8(%rcx) +add %rax,%rbx +adc %rdx,%rbp +movq 64(%rsp),%rax +mulq 24(%rcx) +add %rax,%r10 +adc %rdx,%r11 +movq 64(%rsp),%rax +mulq 32(%rcx) +add %rax,%r12 +adc %rdx,%r13 +movq 32(%rsi),%rax +mulq 0(%rcx) +add %rax,%rbx +adc %rdx,%rbp +movq 72(%rsp),%rax +mulq 16(%rcx) +add %rax,%r10 +adc %rdx,%r11 +movq 72(%rsp),%rax +mulq 24(%rcx) +add %rax,%r12 +adc %rdx,%r13 +movq 72(%rsp),%rax +mulq 32(%rcx) +add %rax,%r14 +adc %rdx,%r15 +movq x25519_x86_64_REDMASK51(%rip),%rsi +shld $13,%r8,%r9 +and %rsi,%r8 +shld $13,%r10,%r11 +and %rsi,%r10 +add %r9,%r10 +shld $13,%r12,%r13 +and %rsi,%r12 +add %r11,%r12 +shld $13,%r14,%r15 +and %rsi,%r14 +add %r13,%r14 +shld $13,%rbx,%rbp +and %rsi,%rbx +add %r15,%rbx +imulq $19,%rbp,%rdx +add %rdx,%r8 +mov %r8,%rdx +shr $51,%rdx +add %r10,%rdx +mov %rdx,%rcx +shr $51,%rdx +and %rsi,%r8 +add %r12,%rdx +mov %rdx,%r9 +shr $51,%rdx +and %rsi,%rcx +add %r14,%rdx +mov %rdx,%rax +shr $51,%rdx +and %rsi,%r9 +add %rbx,%rdx +mov %rdx,%r10 +shr $51,%rdx +and %rsi,%rax +imulq $19,%rdx,%rdx +add %rdx,%r8 +and %rsi,%r10 +movq %r8,0(%rdi) +movq %rcx,8(%rdi) +movq %r9,16(%rdi) +movq %rax,24(%rdi) +movq %r10,32(%rdi) +movq 0(%rsp),%r11 +movq 8(%rsp),%r12 +movq 16(%rsp),%r13 +movq 24(%rsp),%r14 +movq 32(%rsp),%r15 +movq 40(%rsp),%rbx +movq 48(%rsp),%rbp +add %r11,%rsp +mov %rdi,%rax +mov %rsi,%rdx +ret + +.p2align 5 +.globl C_ABI(x25519_x86_64_square) +HIDDEN C_ABI(x25519_x86_64_square) +C_ABI(x25519_x86_64_square): +mov %rsp,%r11 +and $31,%r11 +add $64,%r11 +sub %r11,%rsp +movq %r11,0(%rsp) +movq %r12,8(%rsp) +movq %r13,16(%rsp) +movq %r14,24(%rsp) +movq %r15,32(%rsp) +movq %rbx,40(%rsp) +movq %rbp,48(%rsp) +movq 0(%rsi),%rax +mulq 0(%rsi) +mov %rax,%rcx +mov %rdx,%r8 +movq 0(%rsi),%rax +shl $1,%rax +mulq 8(%rsi) +mov %rax,%r9 +mov %rdx,%r10 +movq 0(%rsi),%rax +shl $1,%rax +mulq 16(%rsi) +mov %rax,%r11 +mov %rdx,%r12 +movq 0(%rsi),%rax +shl $1,%rax +mulq 24(%rsi) +mov %rax,%r13 +mov %rdx,%r14 +movq 0(%rsi),%rax +shl $1,%rax +mulq 32(%rsi) +mov %rax,%r15 +mov %rdx,%rbx +movq 8(%rsi),%rax +mulq 8(%rsi) +add %rax,%r11 +adc %rdx,%r12 +movq 8(%rsi),%rax +shl $1,%rax +mulq 16(%rsi) +add %rax,%r13 +adc %rdx,%r14 +movq 8(%rsi),%rax +shl $1,%rax +mulq 24(%rsi) +add %rax,%r15 +adc %rdx,%rbx +movq 8(%rsi),%rdx +imulq $38,%rdx,%rax +mulq 32(%rsi) +add %rax,%rcx +adc %rdx,%r8 +movq 16(%rsi),%rax +mulq 16(%rsi) +add %rax,%r15 +adc %rdx,%rbx +movq 16(%rsi),%rdx +imulq $38,%rdx,%rax +mulq 24(%rsi) +add %rax,%rcx +adc %rdx,%r8 +movq 16(%rsi),%rdx +imulq $38,%rdx,%rax +mulq 32(%rsi) +add %rax,%r9 +adc %rdx,%r10 +movq 24(%rsi),%rdx +imulq $19,%rdx,%rax +mulq 24(%rsi) +add %rax,%r9 +adc %rdx,%r10 +movq 24(%rsi),%rdx +imulq $38,%rdx,%rax +mulq 32(%rsi) +add %rax,%r11 +adc %rdx,%r12 +movq 32(%rsi),%rdx +imulq $19,%rdx,%rax +mulq 32(%rsi) +add %rax,%r13 +adc %rdx,%r14 +movq x25519_x86_64_REDMASK51(%rip),%rsi +shld $13,%rcx,%r8 +and %rsi,%rcx +shld $13,%r9,%r10 +and %rsi,%r9 +add %r8,%r9 +shld $13,%r11,%r12 +and %rsi,%r11 +add %r10,%r11 +shld $13,%r13,%r14 +and %rsi,%r13 +add %r12,%r13 +shld $13,%r15,%rbx +and %rsi,%r15 +add %r14,%r15 +imulq $19,%rbx,%rdx +add %rdx,%rcx +mov %rcx,%rdx +shr $51,%rdx +add %r9,%rdx +and %rsi,%rcx +mov %rdx,%r8 +shr $51,%rdx +add %r11,%rdx +and %rsi,%r8 +mov %rdx,%r9 +shr $51,%rdx +add %r13,%rdx +and %rsi,%r9 +mov %rdx,%rax +shr $51,%rdx +add %r15,%rdx +and %rsi,%rax +mov %rdx,%r10 +shr $51,%rdx +imulq $19,%rdx,%rdx +add %rdx,%rcx +and %rsi,%r10 +movq %rcx,0(%rdi) +movq %r8,8(%rdi) +movq %r9,16(%rdi) +movq %rax,24(%rdi) +movq %r10,32(%rdi) +movq 0(%rsp),%r11 +movq 8(%rsp),%r12 +movq 16(%rsp),%r13 +movq 24(%rsp),%r14 +movq 32(%rsp),%r15 +movq 40(%rsp),%rbx +movq 48(%rsp),%rbp +add %r11,%rsp +mov %rdi,%rax +mov %rsi,%rdx +ret + +.p2align 5 +.globl C_ABI(x25519_x86_64_ladderstep) +HIDDEN C_ABI(x25519_x86_64_ladderstep) +C_ABI(x25519_x86_64_ladderstep): +mov %rsp,%r11 +and $31,%r11 +add $352,%r11 +sub %r11,%rsp +movq %r11,0(%rsp) +movq %r12,8(%rsp) +movq %r13,16(%rsp) +movq %r14,24(%rsp) +movq %r15,32(%rsp) +movq %rbx,40(%rsp) +movq %rbp,48(%rsp) +movq 40(%rdi),%rsi +movq 48(%rdi),%rdx +movq 56(%rdi),%rcx +movq 64(%rdi),%r8 +movq 72(%rdi),%r9 +mov %rsi,%rax +mov %rdx,%r10 +mov %rcx,%r11 +mov %r8,%r12 +mov %r9,%r13 +add x25519_x86_64_2P0(%rip),%rax +add x25519_x86_64_2P1234(%rip),%r10 +add x25519_x86_64_2P1234(%rip),%r11 +add x25519_x86_64_2P1234(%rip),%r12 +add x25519_x86_64_2P1234(%rip),%r13 +addq 80(%rdi),%rsi +addq 88(%rdi),%rdx +addq 96(%rdi),%rcx +addq 104(%rdi),%r8 +addq 112(%rdi),%r9 +subq 80(%rdi),%rax +subq 88(%rdi),%r10 +subq 96(%rdi),%r11 +subq 104(%rdi),%r12 +subq 112(%rdi),%r13 +movq %rsi,56(%rsp) +movq %rdx,64(%rsp) +movq %rcx,72(%rsp) +movq %r8,80(%rsp) +movq %r9,88(%rsp) +movq %rax,96(%rsp) +movq %r10,104(%rsp) +movq %r11,112(%rsp) +movq %r12,120(%rsp) +movq %r13,128(%rsp) +movq 96(%rsp),%rax +mulq 96(%rsp) +mov %rax,%rsi +mov %rdx,%rcx +movq 96(%rsp),%rax +shl $1,%rax +mulq 104(%rsp) +mov %rax,%r8 +mov %rdx,%r9 +movq 96(%rsp),%rax +shl $1,%rax +mulq 112(%rsp) +mov %rax,%r10 +mov %rdx,%r11 +movq 96(%rsp),%rax +shl $1,%rax +mulq 120(%rsp) +mov %rax,%r12 +mov %rdx,%r13 +movq 96(%rsp),%rax +shl $1,%rax +mulq 128(%rsp) +mov %rax,%r14 +mov %rdx,%r15 +movq 104(%rsp),%rax +mulq 104(%rsp) +add %rax,%r10 +adc %rdx,%r11 +movq 104(%rsp),%rax +shl $1,%rax +mulq 112(%rsp) +add %rax,%r12 +adc %rdx,%r13 +movq 104(%rsp),%rax +shl $1,%rax +mulq 120(%rsp) +add %rax,%r14 +adc %rdx,%r15 +movq 104(%rsp),%rdx +imulq $38,%rdx,%rax +mulq 128(%rsp) +add %rax,%rsi +adc %rdx,%rcx +movq 112(%rsp),%rax +mulq 112(%rsp) +add %rax,%r14 +adc %rdx,%r15 +movq 112(%rsp),%rdx +imulq $38,%rdx,%rax +mulq 120(%rsp) +add %rax,%rsi +adc %rdx,%rcx +movq 112(%rsp),%rdx +imulq $38,%rdx,%rax +mulq 128(%rsp) +add %rax,%r8 +adc %rdx,%r9 +movq 120(%rsp),%rdx +imulq $19,%rdx,%rax +mulq 120(%rsp) +add %rax,%r8 +adc %rdx,%r9 +movq 120(%rsp),%rdx +imulq $38,%rdx,%rax +mulq 128(%rsp) +add %rax,%r10 +adc %rdx,%r11 +movq 128(%rsp),%rdx +imulq $19,%rdx,%rax +mulq 128(%rsp) +add %rax,%r12 +adc %rdx,%r13 +movq x25519_x86_64_REDMASK51(%rip),%rdx +shld $13,%rsi,%rcx +and %rdx,%rsi +shld $13,%r8,%r9 +and %rdx,%r8 +add %rcx,%r8 +shld $13,%r10,%r11 +and %rdx,%r10 +add %r9,%r10 +shld $13,%r12,%r13 +and %rdx,%r12 +add %r11,%r12 +shld $13,%r14,%r15 +and %rdx,%r14 +add %r13,%r14 +imulq $19,%r15,%rcx +add %rcx,%rsi +mov %rsi,%rcx +shr $51,%rcx +add %r8,%rcx +and %rdx,%rsi +mov %rcx,%r8 +shr $51,%rcx +add %r10,%rcx +and %rdx,%r8 +mov %rcx,%r9 +shr $51,%rcx +add %r12,%rcx +and %rdx,%r9 +mov %rcx,%rax +shr $51,%rcx +add %r14,%rcx +and %rdx,%rax +mov %rcx,%r10 +shr $51,%rcx +imulq $19,%rcx,%rcx +add %rcx,%rsi +and %rdx,%r10 +movq %rsi,136(%rsp) +movq %r8,144(%rsp) +movq %r9,152(%rsp) +movq %rax,160(%rsp) +movq %r10,168(%rsp) +movq 56(%rsp),%rax +mulq 56(%rsp) +mov %rax,%rsi +mov %rdx,%rcx +movq 56(%rsp),%rax +shl $1,%rax +mulq 64(%rsp) +mov %rax,%r8 +mov %rdx,%r9 +movq 56(%rsp),%rax +shl $1,%rax +mulq 72(%rsp) +mov %rax,%r10 +mov %rdx,%r11 +movq 56(%rsp),%rax +shl $1,%rax +mulq 80(%rsp) +mov %rax,%r12 +mov %rdx,%r13 +movq 56(%rsp),%rax +shl $1,%rax +mulq 88(%rsp) +mov %rax,%r14 +mov %rdx,%r15 +movq 64(%rsp),%rax +mulq 64(%rsp) +add %rax,%r10 +adc %rdx,%r11 +movq 64(%rsp),%rax +shl $1,%rax +mulq 72(%rsp) +add %rax,%r12 +adc %rdx,%r13 +movq 64(%rsp),%rax +shl $1,%rax +mulq 80(%rsp) +add %rax,%r14 +adc %rdx,%r15 +movq 64(%rsp),%rdx +imulq $38,%rdx,%rax +mulq 88(%rsp) +add %rax,%rsi +adc %rdx,%rcx +movq 72(%rsp),%rax +mulq 72(%rsp) +add %rax,%r14 +adc %rdx,%r15 +movq 72(%rsp),%rdx +imulq $38,%rdx,%rax +mulq 80(%rsp) +add %rax,%rsi +adc %rdx,%rcx +movq 72(%rsp),%rdx +imulq $38,%rdx,%rax +mulq 88(%rsp) +add %rax,%r8 +adc %rdx,%r9 +movq 80(%rsp),%rdx +imulq $19,%rdx,%rax +mulq 80(%rsp) +add %rax,%r8 +adc %rdx,%r9 +movq 80(%rsp),%rdx +imulq $38,%rdx,%rax +mulq 88(%rsp) +add %rax,%r10 +adc %rdx,%r11 +movq 88(%rsp),%rdx +imulq $19,%rdx,%rax +mulq 88(%rsp) +add %rax,%r12 +adc %rdx,%r13 +movq x25519_x86_64_REDMASK51(%rip),%rdx +shld $13,%rsi,%rcx +and %rdx,%rsi +shld $13,%r8,%r9 +and %rdx,%r8 +add %rcx,%r8 +shld $13,%r10,%r11 +and %rdx,%r10 +add %r9,%r10 +shld $13,%r12,%r13 +and %rdx,%r12 +add %r11,%r12 +shld $13,%r14,%r15 +and %rdx,%r14 +add %r13,%r14 +imulq $19,%r15,%rcx +add %rcx,%rsi +mov %rsi,%rcx +shr $51,%rcx +add %r8,%rcx +and %rdx,%rsi +mov %rcx,%r8 +shr $51,%rcx +add %r10,%rcx +and %rdx,%r8 +mov %rcx,%r9 +shr $51,%rcx +add %r12,%rcx +and %rdx,%r9 +mov %rcx,%rax +shr $51,%rcx +add %r14,%rcx +and %rdx,%rax +mov %rcx,%r10 +shr $51,%rcx +imulq $19,%rcx,%rcx +add %rcx,%rsi +and %rdx,%r10 +movq %rsi,176(%rsp) +movq %r8,184(%rsp) +movq %r9,192(%rsp) +movq %rax,200(%rsp) +movq %r10,208(%rsp) +mov %rsi,%rsi +mov %r8,%rdx +mov %r9,%rcx +mov %rax,%r8 +mov %r10,%r9 +add x25519_x86_64_2P0(%rip),%rsi +add x25519_x86_64_2P1234(%rip),%rdx +add x25519_x86_64_2P1234(%rip),%rcx +add x25519_x86_64_2P1234(%rip),%r8 +add x25519_x86_64_2P1234(%rip),%r9 +subq 136(%rsp),%rsi +subq 144(%rsp),%rdx +subq 152(%rsp),%rcx +subq 160(%rsp),%r8 +subq 168(%rsp),%r9 +movq %rsi,216(%rsp) +movq %rdx,224(%rsp) +movq %rcx,232(%rsp) +movq %r8,240(%rsp) +movq %r9,248(%rsp) +movq 120(%rdi),%rsi +movq 128(%rdi),%rdx +movq 136(%rdi),%rcx +movq 144(%rdi),%r8 +movq 152(%rdi),%r9 +mov %rsi,%rax +mov %rdx,%r10 +mov %rcx,%r11 +mov %r8,%r12 +mov %r9,%r13 +add x25519_x86_64_2P0(%rip),%rax +add x25519_x86_64_2P1234(%rip),%r10 +add x25519_x86_64_2P1234(%rip),%r11 +add x25519_x86_64_2P1234(%rip),%r12 +add x25519_x86_64_2P1234(%rip),%r13 +addq 160(%rdi),%rsi +addq 168(%rdi),%rdx +addq 176(%rdi),%rcx +addq 184(%rdi),%r8 +addq 192(%rdi),%r9 +subq 160(%rdi),%rax +subq 168(%rdi),%r10 +subq 176(%rdi),%r11 +subq 184(%rdi),%r12 +subq 192(%rdi),%r13 +movq %rsi,256(%rsp) +movq %rdx,264(%rsp) +movq %rcx,272(%rsp) +movq %r8,280(%rsp) +movq %r9,288(%rsp) +movq %rax,296(%rsp) +movq %r10,304(%rsp) +movq %r11,312(%rsp) +movq %r12,320(%rsp) +movq %r13,328(%rsp) +movq 280(%rsp),%rsi +imulq $19,%rsi,%rax +movq %rax,336(%rsp) +mulq 112(%rsp) +mov %rax,%rsi +mov %rdx,%rcx +movq 288(%rsp),%rdx +imulq $19,%rdx,%rax +movq %rax,344(%rsp) +mulq 104(%rsp) +add %rax,%rsi +adc %rdx,%rcx +movq 256(%rsp),%rax +mulq 96(%rsp) +add %rax,%rsi +adc %rdx,%rcx +movq 256(%rsp),%rax +mulq 104(%rsp) +mov %rax,%r8 +mov %rdx,%r9 +movq 256(%rsp),%rax +mulq 112(%rsp) +mov %rax,%r10 +mov %rdx,%r11 +movq 256(%rsp),%rax +mulq 120(%rsp) +mov %rax,%r12 +mov %rdx,%r13 +movq 256(%rsp),%rax +mulq 128(%rsp) +mov %rax,%r14 +mov %rdx,%r15 +movq 264(%rsp),%rax +mulq 96(%rsp) +add %rax,%r8 +adc %rdx,%r9 +movq 264(%rsp),%rax +mulq 104(%rsp) +add %rax,%r10 +adc %rdx,%r11 +movq 264(%rsp),%rax +mulq 112(%rsp) +add %rax,%r12 +adc %rdx,%r13 +movq 264(%rsp),%rax +mulq 120(%rsp) +add %rax,%r14 +adc %rdx,%r15 +movq 264(%rsp),%rdx +imulq $19,%rdx,%rax +mulq 128(%rsp) +add %rax,%rsi +adc %rdx,%rcx +movq 272(%rsp),%rax +mulq 96(%rsp) +add %rax,%r10 +adc %rdx,%r11 +movq 272(%rsp),%rax +mulq 104(%rsp) +add %rax,%r12 +adc %rdx,%r13 +movq 272(%rsp),%rax +mulq 112(%rsp) +add %rax,%r14 +adc %rdx,%r15 +movq 272(%rsp),%rdx +imulq $19,%rdx,%rax +mulq 120(%rsp) +add %rax,%rsi +adc %rdx,%rcx +movq 272(%rsp),%rdx +imulq $19,%rdx,%rax +mulq 128(%rsp) +add %rax,%r8 +adc %rdx,%r9 +movq 280(%rsp),%rax +mulq 96(%rsp) +add %rax,%r12 +adc %rdx,%r13 +movq 280(%rsp),%rax +mulq 104(%rsp) +add %rax,%r14 +adc %rdx,%r15 +movq 336(%rsp),%rax +mulq 120(%rsp) +add %rax,%r8 +adc %rdx,%r9 +movq 336(%rsp),%rax +mulq 128(%rsp) +add %rax,%r10 +adc %rdx,%r11 +movq 288(%rsp),%rax +mulq 96(%rsp) +add %rax,%r14 +adc %rdx,%r15 +movq 344(%rsp),%rax +mulq 112(%rsp) +add %rax,%r8 +adc %rdx,%r9 +movq 344(%rsp),%rax +mulq 120(%rsp) +add %rax,%r10 +adc %rdx,%r11 +movq 344(%rsp),%rax +mulq 128(%rsp) +add %rax,%r12 +adc %rdx,%r13 +movq x25519_x86_64_REDMASK51(%rip),%rdx +shld $13,%rsi,%rcx +and %rdx,%rsi +shld $13,%r8,%r9 +and %rdx,%r8 +add %rcx,%r8 +shld $13,%r10,%r11 +and %rdx,%r10 +add %r9,%r10 +shld $13,%r12,%r13 +and %rdx,%r12 +add %r11,%r12 +shld $13,%r14,%r15 +and %rdx,%r14 +add %r13,%r14 +imulq $19,%r15,%rcx +add %rcx,%rsi +mov %rsi,%rcx +shr $51,%rcx +add %r8,%rcx +mov %rcx,%r8 +shr $51,%rcx +and %rdx,%rsi +add %r10,%rcx +mov %rcx,%r9 +shr $51,%rcx +and %rdx,%r8 +add %r12,%rcx +mov %rcx,%rax +shr $51,%rcx +and %rdx,%r9 +add %r14,%rcx +mov %rcx,%r10 +shr $51,%rcx +and %rdx,%rax +imulq $19,%rcx,%rcx +add %rcx,%rsi +and %rdx,%r10 +movq %rsi,96(%rsp) +movq %r8,104(%rsp) +movq %r9,112(%rsp) +movq %rax,120(%rsp) +movq %r10,128(%rsp) +movq 320(%rsp),%rsi +imulq $19,%rsi,%rax +movq %rax,256(%rsp) +mulq 72(%rsp) +mov %rax,%rsi +mov %rdx,%rcx +movq 328(%rsp),%rdx +imulq $19,%rdx,%rax +movq %rax,264(%rsp) +mulq 64(%rsp) +add %rax,%rsi +adc %rdx,%rcx +movq 296(%rsp),%rax +mulq 56(%rsp) +add %rax,%rsi +adc %rdx,%rcx +movq 296(%rsp),%rax +mulq 64(%rsp) +mov %rax,%r8 +mov %rdx,%r9 +movq 296(%rsp),%rax +mulq 72(%rsp) +mov %rax,%r10 +mov %rdx,%r11 +movq 296(%rsp),%rax +mulq 80(%rsp) +mov %rax,%r12 +mov %rdx,%r13 +movq 296(%rsp),%rax +mulq 88(%rsp) +mov %rax,%r14 +mov %rdx,%r15 +movq 304(%rsp),%rax +mulq 56(%rsp) +add %rax,%r8 +adc %rdx,%r9 +movq 304(%rsp),%rax +mulq 64(%rsp) +add %rax,%r10 +adc %rdx,%r11 +movq 304(%rsp),%rax +mulq 72(%rsp) +add %rax,%r12 +adc %rdx,%r13 +movq 304(%rsp),%rax +mulq 80(%rsp) +add %rax,%r14 +adc %rdx,%r15 +movq 304(%rsp),%rdx +imulq $19,%rdx,%rax +mulq 88(%rsp) +add %rax,%rsi +adc %rdx,%rcx +movq 312(%rsp),%rax +mulq 56(%rsp) +add %rax,%r10 +adc %rdx,%r11 +movq 312(%rsp),%rax +mulq 64(%rsp) +add %rax,%r12 +adc %rdx,%r13 +movq 312(%rsp),%rax +mulq 72(%rsp) +add %rax,%r14 +adc %rdx,%r15 +movq 312(%rsp),%rdx +imulq $19,%rdx,%rax +mulq 80(%rsp) +add %rax,%rsi +adc %rdx,%rcx +movq 312(%rsp),%rdx +imulq $19,%rdx,%rax +mulq 88(%rsp) +add %rax,%r8 +adc %rdx,%r9 +movq 320(%rsp),%rax +mulq 56(%rsp) +add %rax,%r12 +adc %rdx,%r13 +movq 320(%rsp),%rax +mulq 64(%rsp) +add %rax,%r14 +adc %rdx,%r15 +movq 256(%rsp),%rax +mulq 80(%rsp) +add %rax,%r8 +adc %rdx,%r9 +movq 256(%rsp),%rax +mulq 88(%rsp) +add %rax,%r10 +adc %rdx,%r11 +movq 328(%rsp),%rax +mulq 56(%rsp) +add %rax,%r14 +adc %rdx,%r15 +movq 264(%rsp),%rax +mulq 72(%rsp) +add %rax,%r8 +adc %rdx,%r9 +movq 264(%rsp),%rax +mulq 80(%rsp) +add %rax,%r10 +adc %rdx,%r11 +movq 264(%rsp),%rax +mulq 88(%rsp) +add %rax,%r12 +adc %rdx,%r13 +movq x25519_x86_64_REDMASK51(%rip),%rdx +shld $13,%rsi,%rcx +and %rdx,%rsi +shld $13,%r8,%r9 +and %rdx,%r8 +add %rcx,%r8 +shld $13,%r10,%r11 +and %rdx,%r10 +add %r9,%r10 +shld $13,%r12,%r13 +and %rdx,%r12 +add %r11,%r12 +shld $13,%r14,%r15 +and %rdx,%r14 +add %r13,%r14 +imulq $19,%r15,%rcx +add %rcx,%rsi +mov %rsi,%rcx +shr $51,%rcx +add %r8,%rcx +mov %rcx,%r8 +shr $51,%rcx +and %rdx,%rsi +add %r10,%rcx +mov %rcx,%r9 +shr $51,%rcx +and %rdx,%r8 +add %r12,%rcx +mov %rcx,%rax +shr $51,%rcx +and %rdx,%r9 +add %r14,%rcx +mov %rcx,%r10 +shr $51,%rcx +and %rdx,%rax +imulq $19,%rcx,%rcx +add %rcx,%rsi +and %rdx,%r10 +mov %rsi,%rdx +mov %r8,%rcx +mov %r9,%r11 +mov %rax,%r12 +mov %r10,%r13 +add x25519_x86_64_2P0(%rip),%rdx +add x25519_x86_64_2P1234(%rip),%rcx +add x25519_x86_64_2P1234(%rip),%r11 +add x25519_x86_64_2P1234(%rip),%r12 +add x25519_x86_64_2P1234(%rip),%r13 +addq 96(%rsp),%rsi +addq 104(%rsp),%r8 +addq 112(%rsp),%r9 +addq 120(%rsp),%rax +addq 128(%rsp),%r10 +subq 96(%rsp),%rdx +subq 104(%rsp),%rcx +subq 112(%rsp),%r11 +subq 120(%rsp),%r12 +subq 128(%rsp),%r13 +movq %rsi,120(%rdi) +movq %r8,128(%rdi) +movq %r9,136(%rdi) +movq %rax,144(%rdi) +movq %r10,152(%rdi) +movq %rdx,160(%rdi) +movq %rcx,168(%rdi) +movq %r11,176(%rdi) +movq %r12,184(%rdi) +movq %r13,192(%rdi) +movq 120(%rdi),%rax +mulq 120(%rdi) +mov %rax,%rsi +mov %rdx,%rcx +movq 120(%rdi),%rax +shl $1,%rax +mulq 128(%rdi) +mov %rax,%r8 +mov %rdx,%r9 +movq 120(%rdi),%rax +shl $1,%rax +mulq 136(%rdi) +mov %rax,%r10 +mov %rdx,%r11 +movq 120(%rdi),%rax +shl $1,%rax +mulq 144(%rdi) +mov %rax,%r12 +mov %rdx,%r13 +movq 120(%rdi),%rax +shl $1,%rax +mulq 152(%rdi) +mov %rax,%r14 +mov %rdx,%r15 +movq 128(%rdi),%rax +mulq 128(%rdi) +add %rax,%r10 +adc %rdx,%r11 +movq 128(%rdi),%rax +shl $1,%rax +mulq 136(%rdi) +add %rax,%r12 +adc %rdx,%r13 +movq 128(%rdi),%rax +shl $1,%rax +mulq 144(%rdi) +add %rax,%r14 +adc %rdx,%r15 +movq 128(%rdi),%rdx +imulq $38,%rdx,%rax +mulq 152(%rdi) +add %rax,%rsi +adc %rdx,%rcx +movq 136(%rdi),%rax +mulq 136(%rdi) +add %rax,%r14 +adc %rdx,%r15 +movq 136(%rdi),%rdx +imulq $38,%rdx,%rax +mulq 144(%rdi) +add %rax,%rsi +adc %rdx,%rcx +movq 136(%rdi),%rdx +imulq $38,%rdx,%rax +mulq 152(%rdi) +add %rax,%r8 +adc %rdx,%r9 +movq 144(%rdi),%rdx +imulq $19,%rdx,%rax +mulq 144(%rdi) +add %rax,%r8 +adc %rdx,%r9 +movq 144(%rdi),%rdx +imulq $38,%rdx,%rax +mulq 152(%rdi) +add %rax,%r10 +adc %rdx,%r11 +movq 152(%rdi),%rdx +imulq $19,%rdx,%rax +mulq 152(%rdi) +add %rax,%r12 +adc %rdx,%r13 +movq x25519_x86_64_REDMASK51(%rip),%rdx +shld $13,%rsi,%rcx +and %rdx,%rsi +shld $13,%r8,%r9 +and %rdx,%r8 +add %rcx,%r8 +shld $13,%r10,%r11 +and %rdx,%r10 +add %r9,%r10 +shld $13,%r12,%r13 +and %rdx,%r12 +add %r11,%r12 +shld $13,%r14,%r15 +and %rdx,%r14 +add %r13,%r14 +imulq $19,%r15,%rcx +add %rcx,%rsi +mov %rsi,%rcx +shr $51,%rcx +add %r8,%rcx +and %rdx,%rsi +mov %rcx,%r8 +shr $51,%rcx +add %r10,%rcx +and %rdx,%r8 +mov %rcx,%r9 +shr $51,%rcx +add %r12,%rcx +and %rdx,%r9 +mov %rcx,%rax +shr $51,%rcx +add %r14,%rcx +and %rdx,%rax +mov %rcx,%r10 +shr $51,%rcx +imulq $19,%rcx,%rcx +add %rcx,%rsi +and %rdx,%r10 +movq %rsi,120(%rdi) +movq %r8,128(%rdi) +movq %r9,136(%rdi) +movq %rax,144(%rdi) +movq %r10,152(%rdi) +movq 160(%rdi),%rax +mulq 160(%rdi) +mov %rax,%rsi +mov %rdx,%rcx +movq 160(%rdi),%rax +shl $1,%rax +mulq 168(%rdi) +mov %rax,%r8 +mov %rdx,%r9 +movq 160(%rdi),%rax +shl $1,%rax +mulq 176(%rdi) +mov %rax,%r10 +mov %rdx,%r11 +movq 160(%rdi),%rax +shl $1,%rax +mulq 184(%rdi) +mov %rax,%r12 +mov %rdx,%r13 +movq 160(%rdi),%rax +shl $1,%rax +mulq 192(%rdi) +mov %rax,%r14 +mov %rdx,%r15 +movq 168(%rdi),%rax +mulq 168(%rdi) +add %rax,%r10 +adc %rdx,%r11 +movq 168(%rdi),%rax +shl $1,%rax +mulq 176(%rdi) +add %rax,%r12 +adc %rdx,%r13 +movq 168(%rdi),%rax +shl $1,%rax +mulq 184(%rdi) +add %rax,%r14 +adc %rdx,%r15 +movq 168(%rdi),%rdx +imulq $38,%rdx,%rax +mulq 192(%rdi) +add %rax,%rsi +adc %rdx,%rcx +movq 176(%rdi),%rax +mulq 176(%rdi) +add %rax,%r14 +adc %rdx,%r15 +movq 176(%rdi),%rdx +imulq $38,%rdx,%rax +mulq 184(%rdi) +add %rax,%rsi +adc %rdx,%rcx +movq 176(%rdi),%rdx +imulq $38,%rdx,%rax +mulq 192(%rdi) +add %rax,%r8 +adc %rdx,%r9 +movq 184(%rdi),%rdx +imulq $19,%rdx,%rax +mulq 184(%rdi) +add %rax,%r8 +adc %rdx,%r9 +movq 184(%rdi),%rdx +imulq $38,%rdx,%rax +mulq 192(%rdi) +add %rax,%r10 +adc %rdx,%r11 +movq 192(%rdi),%rdx +imulq $19,%rdx,%rax +mulq 192(%rdi) +add %rax,%r12 +adc %rdx,%r13 +movq x25519_x86_64_REDMASK51(%rip),%rdx +shld $13,%rsi,%rcx +and %rdx,%rsi +shld $13,%r8,%r9 +and %rdx,%r8 +add %rcx,%r8 +shld $13,%r10,%r11 +and %rdx,%r10 +add %r9,%r10 +shld $13,%r12,%r13 +and %rdx,%r12 +add %r11,%r12 +shld $13,%r14,%r15 +and %rdx,%r14 +add %r13,%r14 +imulq $19,%r15,%rcx +add %rcx,%rsi +mov %rsi,%rcx +shr $51,%rcx +add %r8,%rcx +and %rdx,%rsi +mov %rcx,%r8 +shr $51,%rcx +add %r10,%rcx +and %rdx,%r8 +mov %rcx,%r9 +shr $51,%rcx +add %r12,%rcx +and %rdx,%r9 +mov %rcx,%rax +shr $51,%rcx +add %r14,%rcx +and %rdx,%rax +mov %rcx,%r10 +shr $51,%rcx +imulq $19,%rcx,%rcx +add %rcx,%rsi +and %rdx,%r10 +movq %rsi,160(%rdi) +movq %r8,168(%rdi) +movq %r9,176(%rdi) +movq %rax,184(%rdi) +movq %r10,192(%rdi) +movq 184(%rdi),%rsi +imulq $19,%rsi,%rax +movq %rax,56(%rsp) +mulq 16(%rdi) +mov %rax,%rsi +mov %rdx,%rcx +movq 192(%rdi),%rdx +imulq $19,%rdx,%rax +movq %rax,64(%rsp) +mulq 8(%rdi) +add %rax,%rsi +adc %rdx,%rcx +movq 160(%rdi),%rax +mulq 0(%rdi) +add %rax,%rsi +adc %rdx,%rcx +movq 160(%rdi),%rax +mulq 8(%rdi) +mov %rax,%r8 +mov %rdx,%r9 +movq 160(%rdi),%rax +mulq 16(%rdi) +mov %rax,%r10 +mov %rdx,%r11 +movq 160(%rdi),%rax +mulq 24(%rdi) +mov %rax,%r12 +mov %rdx,%r13 +movq 160(%rdi),%rax +mulq 32(%rdi) +mov %rax,%r14 +mov %rdx,%r15 +movq 168(%rdi),%rax +mulq 0(%rdi) +add %rax,%r8 +adc %rdx,%r9 +movq 168(%rdi),%rax +mulq 8(%rdi) +add %rax,%r10 +adc %rdx,%r11 +movq 168(%rdi),%rax +mulq 16(%rdi) +add %rax,%r12 +adc %rdx,%r13 +movq 168(%rdi),%rax +mulq 24(%rdi) +add %rax,%r14 +adc %rdx,%r15 +movq 168(%rdi),%rdx +imulq $19,%rdx,%rax +mulq 32(%rdi) +add %rax,%rsi +adc %rdx,%rcx +movq 176(%rdi),%rax +mulq 0(%rdi) +add %rax,%r10 +adc %rdx,%r11 +movq 176(%rdi),%rax +mulq 8(%rdi) +add %rax,%r12 +adc %rdx,%r13 +movq 176(%rdi),%rax +mulq 16(%rdi) +add %rax,%r14 +adc %rdx,%r15 +movq 176(%rdi),%rdx +imulq $19,%rdx,%rax +mulq 24(%rdi) +add %rax,%rsi +adc %rdx,%rcx +movq 176(%rdi),%rdx +imulq $19,%rdx,%rax +mulq 32(%rdi) +add %rax,%r8 +adc %rdx,%r9 +movq 184(%rdi),%rax +mulq 0(%rdi) +add %rax,%r12 +adc %rdx,%r13 +movq 184(%rdi),%rax +mulq 8(%rdi) +add %rax,%r14 +adc %rdx,%r15 +movq 56(%rsp),%rax +mulq 24(%rdi) +add %rax,%r8 +adc %rdx,%r9 +movq 56(%rsp),%rax +mulq 32(%rdi) +add %rax,%r10 +adc %rdx,%r11 +movq 192(%rdi),%rax +mulq 0(%rdi) +add %rax,%r14 +adc %rdx,%r15 +movq 64(%rsp),%rax +mulq 16(%rdi) +add %rax,%r8 +adc %rdx,%r9 +movq 64(%rsp),%rax +mulq 24(%rdi) +add %rax,%r10 +adc %rdx,%r11 +movq 64(%rsp),%rax +mulq 32(%rdi) +add %rax,%r12 +adc %rdx,%r13 +movq x25519_x86_64_REDMASK51(%rip),%rdx +shld $13,%rsi,%rcx +and %rdx,%rsi +shld $13,%r8,%r9 +and %rdx,%r8 +add %rcx,%r8 +shld $13,%r10,%r11 +and %rdx,%r10 +add %r9,%r10 +shld $13,%r12,%r13 +and %rdx,%r12 +add %r11,%r12 +shld $13,%r14,%r15 +and %rdx,%r14 +add %r13,%r14 +imulq $19,%r15,%rcx +add %rcx,%rsi +mov %rsi,%rcx +shr $51,%rcx +add %r8,%rcx +mov %rcx,%r8 +shr $51,%rcx +and %rdx,%rsi +add %r10,%rcx +mov %rcx,%r9 +shr $51,%rcx +and %rdx,%r8 +add %r12,%rcx +mov %rcx,%rax +shr $51,%rcx +and %rdx,%r9 +add %r14,%rcx +mov %rcx,%r10 +shr $51,%rcx +and %rdx,%rax +imulq $19,%rcx,%rcx +add %rcx,%rsi +and %rdx,%r10 +movq %rsi,160(%rdi) +movq %r8,168(%rdi) +movq %r9,176(%rdi) +movq %rax,184(%rdi) +movq %r10,192(%rdi) +movq 200(%rsp),%rsi +imulq $19,%rsi,%rax +movq %rax,56(%rsp) +mulq 152(%rsp) +mov %rax,%rsi +mov %rdx,%rcx +movq 208(%rsp),%rdx +imulq $19,%rdx,%rax +movq %rax,64(%rsp) +mulq 144(%rsp) +add %rax,%rsi +adc %rdx,%rcx +movq 176(%rsp),%rax +mulq 136(%rsp) +add %rax,%rsi +adc %rdx,%rcx +movq 176(%rsp),%rax +mulq 144(%rsp) +mov %rax,%r8 +mov %rdx,%r9 +movq 176(%rsp),%rax +mulq 152(%rsp) +mov %rax,%r10 +mov %rdx,%r11 +movq 176(%rsp),%rax +mulq 160(%rsp) +mov %rax,%r12 +mov %rdx,%r13 +movq 176(%rsp),%rax +mulq 168(%rsp) +mov %rax,%r14 +mov %rdx,%r15 +movq 184(%rsp),%rax +mulq 136(%rsp) +add %rax,%r8 +adc %rdx,%r9 +movq 184(%rsp),%rax +mulq 144(%rsp) +add %rax,%r10 +adc %rdx,%r11 +movq 184(%rsp),%rax +mulq 152(%rsp) +add %rax,%r12 +adc %rdx,%r13 +movq 184(%rsp),%rax +mulq 160(%rsp) +add %rax,%r14 +adc %rdx,%r15 +movq 184(%rsp),%rdx +imulq $19,%rdx,%rax +mulq 168(%rsp) +add %rax,%rsi +adc %rdx,%rcx +movq 192(%rsp),%rax +mulq 136(%rsp) +add %rax,%r10 +adc %rdx,%r11 +movq 192(%rsp),%rax +mulq 144(%rsp) +add %rax,%r12 +adc %rdx,%r13 +movq 192(%rsp),%rax +mulq 152(%rsp) +add %rax,%r14 +adc %rdx,%r15 +movq 192(%rsp),%rdx +imulq $19,%rdx,%rax +mulq 160(%rsp) +add %rax,%rsi +adc %rdx,%rcx +movq 192(%rsp),%rdx +imulq $19,%rdx,%rax +mulq 168(%rsp) +add %rax,%r8 +adc %rdx,%r9 +movq 200(%rsp),%rax +mulq 136(%rsp) +add %rax,%r12 +adc %rdx,%r13 +movq 200(%rsp),%rax +mulq 144(%rsp) +add %rax,%r14 +adc %rdx,%r15 +movq 56(%rsp),%rax +mulq 160(%rsp) +add %rax,%r8 +adc %rdx,%r9 +movq 56(%rsp),%rax +mulq 168(%rsp) +add %rax,%r10 +adc %rdx,%r11 +movq 208(%rsp),%rax +mulq 136(%rsp) +add %rax,%r14 +adc %rdx,%r15 +movq 64(%rsp),%rax +mulq 152(%rsp) +add %rax,%r8 +adc %rdx,%r9 +movq 64(%rsp),%rax +mulq 160(%rsp) +add %rax,%r10 +adc %rdx,%r11 +movq 64(%rsp),%rax +mulq 168(%rsp) +add %rax,%r12 +adc %rdx,%r13 +movq x25519_x86_64_REDMASK51(%rip),%rdx +shld $13,%rsi,%rcx +and %rdx,%rsi +shld $13,%r8,%r9 +and %rdx,%r8 +add %rcx,%r8 +shld $13,%r10,%r11 +and %rdx,%r10 +add %r9,%r10 +shld $13,%r12,%r13 +and %rdx,%r12 +add %r11,%r12 +shld $13,%r14,%r15 +and %rdx,%r14 +add %r13,%r14 +imulq $19,%r15,%rcx +add %rcx,%rsi +mov %rsi,%rcx +shr $51,%rcx +add %r8,%rcx +mov %rcx,%r8 +shr $51,%rcx +and %rdx,%rsi +add %r10,%rcx +mov %rcx,%r9 +shr $51,%rcx +and %rdx,%r8 +add %r12,%rcx +mov %rcx,%rax +shr $51,%rcx +and %rdx,%r9 +add %r14,%rcx +mov %rcx,%r10 +shr $51,%rcx +and %rdx,%rax +imulq $19,%rcx,%rcx +add %rcx,%rsi +and %rdx,%r10 +movq %rsi,40(%rdi) +movq %r8,48(%rdi) +movq %r9,56(%rdi) +movq %rax,64(%rdi) +movq %r10,72(%rdi) +movq 216(%rsp),%rax +mulq x25519_x86_64_121666_213(%rip) +shr $13,%rax +mov %rax,%rsi +mov %rdx,%rcx +movq 224(%rsp),%rax +mulq x25519_x86_64_121666_213(%rip) +shr $13,%rax +add %rax,%rcx +mov %rdx,%r8 +movq 232(%rsp),%rax +mulq x25519_x86_64_121666_213(%rip) +shr $13,%rax +add %rax,%r8 +mov %rdx,%r9 +movq 240(%rsp),%rax +mulq x25519_x86_64_121666_213(%rip) +shr $13,%rax +add %rax,%r9 +mov %rdx,%r10 +movq 248(%rsp),%rax +mulq x25519_x86_64_121666_213(%rip) +shr $13,%rax +add %rax,%r10 +imulq $19,%rdx,%rdx +add %rdx,%rsi +addq 136(%rsp),%rsi +addq 144(%rsp),%rcx +addq 152(%rsp),%r8 +addq 160(%rsp),%r9 +addq 168(%rsp),%r10 +movq %rsi,80(%rdi) +movq %rcx,88(%rdi) +movq %r8,96(%rdi) +movq %r9,104(%rdi) +movq %r10,112(%rdi) +movq 104(%rdi),%rsi +imulq $19,%rsi,%rax +movq %rax,56(%rsp) +mulq 232(%rsp) +mov %rax,%rsi +mov %rdx,%rcx +movq 112(%rdi),%rdx +imulq $19,%rdx,%rax +movq %rax,64(%rsp) +mulq 224(%rsp) +add %rax,%rsi +adc %rdx,%rcx +movq 80(%rdi),%rax +mulq 216(%rsp) +add %rax,%rsi +adc %rdx,%rcx +movq 80(%rdi),%rax +mulq 224(%rsp) +mov %rax,%r8 +mov %rdx,%r9 +movq 80(%rdi),%rax +mulq 232(%rsp) +mov %rax,%r10 +mov %rdx,%r11 +movq 80(%rdi),%rax +mulq 240(%rsp) +mov %rax,%r12 +mov %rdx,%r13 +movq 80(%rdi),%rax +mulq 248(%rsp) +mov %rax,%r14 +mov %rdx,%r15 +movq 88(%rdi),%rax +mulq 216(%rsp) +add %rax,%r8 +adc %rdx,%r9 +movq 88(%rdi),%rax +mulq 224(%rsp) +add %rax,%r10 +adc %rdx,%r11 +movq 88(%rdi),%rax +mulq 232(%rsp) +add %rax,%r12 +adc %rdx,%r13 +movq 88(%rdi),%rax +mulq 240(%rsp) +add %rax,%r14 +adc %rdx,%r15 +movq 88(%rdi),%rdx +imulq $19,%rdx,%rax +mulq 248(%rsp) +add %rax,%rsi +adc %rdx,%rcx +movq 96(%rdi),%rax +mulq 216(%rsp) +add %rax,%r10 +adc %rdx,%r11 +movq 96(%rdi),%rax +mulq 224(%rsp) +add %rax,%r12 +adc %rdx,%r13 +movq 96(%rdi),%rax +mulq 232(%rsp) +add %rax,%r14 +adc %rdx,%r15 +movq 96(%rdi),%rdx +imulq $19,%rdx,%rax +mulq 240(%rsp) +add %rax,%rsi +adc %rdx,%rcx +movq 96(%rdi),%rdx +imulq $19,%rdx,%rax +mulq 248(%rsp) +add %rax,%r8 +adc %rdx,%r9 +movq 104(%rdi),%rax +mulq 216(%rsp) +add %rax,%r12 +adc %rdx,%r13 +movq 104(%rdi),%rax +mulq 224(%rsp) +add %rax,%r14 +adc %rdx,%r15 +movq 56(%rsp),%rax +mulq 240(%rsp) +add %rax,%r8 +adc %rdx,%r9 +movq 56(%rsp),%rax +mulq 248(%rsp) +add %rax,%r10 +adc %rdx,%r11 +movq 112(%rdi),%rax +mulq 216(%rsp) +add %rax,%r14 +adc %rdx,%r15 +movq 64(%rsp),%rax +mulq 232(%rsp) +add %rax,%r8 +adc %rdx,%r9 +movq 64(%rsp),%rax +mulq 240(%rsp) +add %rax,%r10 +adc %rdx,%r11 +movq 64(%rsp),%rax +mulq 248(%rsp) +add %rax,%r12 +adc %rdx,%r13 +movq x25519_x86_64_REDMASK51(%rip),%rdx +shld $13,%rsi,%rcx +and %rdx,%rsi +shld $13,%r8,%r9 +and %rdx,%r8 +add %rcx,%r8 +shld $13,%r10,%r11 +and %rdx,%r10 +add %r9,%r10 +shld $13,%r12,%r13 +and %rdx,%r12 +add %r11,%r12 +shld $13,%r14,%r15 +and %rdx,%r14 +add %r13,%r14 +imulq $19,%r15,%rcx +add %rcx,%rsi +mov %rsi,%rcx +shr $51,%rcx +add %r8,%rcx +mov %rcx,%r8 +shr $51,%rcx +and %rdx,%rsi +add %r10,%rcx +mov %rcx,%r9 +shr $51,%rcx +and %rdx,%r8 +add %r12,%rcx +mov %rcx,%rax +shr $51,%rcx +and %rdx,%r9 +add %r14,%rcx +mov %rcx,%r10 +shr $51,%rcx +and %rdx,%rax +imulq $19,%rcx,%rcx +add %rcx,%rsi +and %rdx,%r10 +movq %rsi,80(%rdi) +movq %r8,88(%rdi) +movq %r9,96(%rdi) +movq %rax,104(%rdi) +movq %r10,112(%rdi) +movq 0(%rsp),%r11 +movq 8(%rsp),%r12 +movq 16(%rsp),%r13 +movq 24(%rsp),%r14 +movq 32(%rsp),%r15 +movq 40(%rsp),%rbx +movq 48(%rsp),%rbp +add %r11,%rsp +mov %rdi,%rax +mov %rsi,%rdx +ret + +.p2align 5 +.globl C_ABI(x25519_x86_64_work_cswap) +HIDDEN C_ABI(x25519_x86_64_work_cswap) +C_ABI(x25519_x86_64_work_cswap): +mov %rsp,%r11 +and $31,%r11 +add $0,%r11 +sub %r11,%rsp +cmp $1,%rsi +movq 0(%rdi),%rsi +movq 80(%rdi),%rdx +movq 8(%rdi),%rcx +movq 88(%rdi),%r8 +mov %rsi,%r9 +cmove %rdx,%rsi +cmove %r9,%rdx +mov %rcx,%r9 +cmove %r8,%rcx +cmove %r9,%r8 +movq %rsi,0(%rdi) +movq %rdx,80(%rdi) +movq %rcx,8(%rdi) +movq %r8,88(%rdi) +movq 16(%rdi),%rsi +movq 96(%rdi),%rdx +movq 24(%rdi),%rcx +movq 104(%rdi),%r8 +mov %rsi,%r9 +cmove %rdx,%rsi +cmove %r9,%rdx +mov %rcx,%r9 +cmove %r8,%rcx +cmove %r9,%r8 +movq %rsi,16(%rdi) +movq %rdx,96(%rdi) +movq %rcx,24(%rdi) +movq %r8,104(%rdi) +movq 32(%rdi),%rsi +movq 112(%rdi),%rdx +movq 40(%rdi),%rcx +movq 120(%rdi),%r8 +mov %rsi,%r9 +cmove %rdx,%rsi +cmove %r9,%rdx +mov %rcx,%r9 +cmove %r8,%rcx +cmove %r9,%r8 +movq %rsi,32(%rdi) +movq %rdx,112(%rdi) +movq %rcx,40(%rdi) +movq %r8,120(%rdi) +movq 48(%rdi),%rsi +movq 128(%rdi),%rdx +movq 56(%rdi),%rcx +movq 136(%rdi),%r8 +mov %rsi,%r9 +cmove %rdx,%rsi +cmove %r9,%rdx +mov %rcx,%r9 +cmove %r8,%rcx +cmove %r9,%r8 +movq %rsi,48(%rdi) +movq %rdx,128(%rdi) +movq %rcx,56(%rdi) +movq %r8,136(%rdi) +movq 64(%rdi),%rsi +movq 144(%rdi),%rdx +movq 72(%rdi),%rcx +movq 152(%rdi),%r8 +mov %rsi,%r9 +cmove %rdx,%rsi +cmove %r9,%rdx +mov %rcx,%r9 +cmove %r8,%rcx +cmove %r9,%r8 +movq %rsi,64(%rdi) +movq %rdx,144(%rdi) +movq %rcx,72(%rdi) +movq %r8,152(%rdi) +add %r11,%rsp +mov %rdi,%rax +mov %rsi,%rdx +ret + +#endif /* __x86_64__ */ +#endif /* !OPENSSL_NO_ASM */ diff --git a/external/boringssl/crypto/curve25519/curve25519.c.REMOVED.git-id b/external/boringssl/crypto/curve25519/curve25519.c.REMOVED.git-id new file mode 100644 index 0000000000..c14695bfbd --- /dev/null +++ b/external/boringssl/crypto/curve25519/curve25519.c.REMOVED.git-id @@ -0,0 +1 @@ +1dd1b3ed76d4f6a8770552896cf254bbdbe9cb6b \ No newline at end of file diff --git a/external/boringssl/crypto/curve25519/ed25519_test.cc b/external/boringssl/crypto/curve25519/ed25519_test.cc new file mode 100644 index 0000000000..1b6a0b6157 --- /dev/null +++ b/external/boringssl/crypto/curve25519/ed25519_test.cc @@ -0,0 +1,63 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include + +#include + +#include "../test/file_test.h" + + +static bool TestSignature(FileTest *t, void *arg) { + std::vector private_key, public_key, message, expected_signature; + if (!t->GetBytes(&private_key, "PRIV") || + private_key.size() != 64 || + !t->GetBytes(&public_key, "PUB") || + public_key.size() != 32 || + !t->GetBytes(&message, "MESSAGE") || + !t->GetBytes(&expected_signature, "SIG") || + expected_signature.size() != 64) { + return false; + } + + uint8_t signature[64]; + if (!ED25519_sign(signature, message.data(), message.size(), + private_key.data())) { + t->PrintLine("ED25519_sign failed"); + return false; + } + + if (!t->ExpectBytesEqual(expected_signature.data(), expected_signature.size(), + signature, sizeof(signature))) { + return false; + } + + if (!ED25519_verify(message.data(), message.size(), signature, + public_key.data())) { + t->PrintLine("ED25519_verify failed"); + return false; + } + + return true; +} + +int main(int argc, char **argv) { + if (argc != 2) { + fprintf(stderr, "%s \n", argv[0]); + return 1; + } + + return FileTestMain(TestSignature, nullptr, argv[1]); +} diff --git a/external/boringssl/crypto/curve25519/ed25519_tests.txt.REMOVED.git-id b/external/boringssl/crypto/curve25519/ed25519_tests.txt.REMOVED.git-id new file mode 100644 index 0000000000..cc7556c08b --- /dev/null +++ b/external/boringssl/crypto/curve25519/ed25519_tests.txt.REMOVED.git-id @@ -0,0 +1 @@ +4d43417d44eaceb588add4a29d87e300ec368c92 \ No newline at end of file diff --git a/external/boringssl/crypto/curve25519/internal.h b/external/boringssl/crypto/curve25519/internal.h new file mode 100644 index 0000000000..ea206a3e9b --- /dev/null +++ b/external/boringssl/crypto/curve25519/internal.h @@ -0,0 +1,109 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_CURVE25519_INTERNAL_H +#define OPENSSL_HEADER_CURVE25519_INTERNAL_H + +#if defined(__cplusplus) +extern "C" { +#endif + + +#if defined(OPENSSL_X86_64) && !defined(OPENSSL_SMALL) && \ + !defined(OPENSSL_WINDOWS) && !defined(OPENSSL_NO_ASM) +#define BORINGSSL_X25519_X86_64 + +void x25519_x86_64(uint8_t out[32], const uint8_t scalar[32], + const uint8_t point[32]); +#endif + + +#if defined(OPENSSL_ARM) && !defined(OPENSSL_NO_ASM) +#define BORINGSSL_X25519_NEON + +/* x25519_NEON is defined in asm/x25519-arm.S. */ +void x25519_NEON(uint8_t out[32], const uint8_t scalar[32], + const uint8_t point[32]); +#endif + +/* fe means field element. Here the field is \Z/(2^255-19). An element t, + * entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77 + * t[3]+2^102 t[4]+...+2^230 t[9]. Bounds on each t[i] vary depending on + * context. */ +typedef int32_t fe[10]; + +/* ge means group element. + + * Here the group is the set of pairs (x,y) of field elements (see fe.h) + * satisfying -x^2 + y^2 = 1 + d x^2y^2 + * where d = -121665/121666. + * + * Representations: + * ge_p2 (projective): (X:Y:Z) satisfying x=X/Z, y=Y/Z + * ge_p3 (extended): (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT + * ge_p1p1 (completed): ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T + * ge_precomp (Duif): (y+x,y-x,2dxy) */ + +typedef struct { + fe X; + fe Y; + fe Z; +} ge_p2; + +typedef struct { + fe X; + fe Y; + fe Z; + fe T; +} ge_p3; + +typedef struct { + fe X; + fe Y; + fe Z; + fe T; +} ge_p1p1; + +typedef struct { + fe yplusx; + fe yminusx; + fe xy2d; +} ge_precomp; + +typedef struct { + fe YplusX; + fe YminusX; + fe Z; + fe T2d; +} ge_cached; + +void x25519_ge_tobytes(uint8_t *s, const ge_p2 *h); +int x25519_ge_frombytes_vartime(ge_p3 *h, const uint8_t *s); +void x25519_ge_p3_to_cached(ge_cached *r, const ge_p3 *p); +void x25519_ge_p1p1_to_p2(ge_p2 *r, const ge_p1p1 *p); +void x25519_ge_p1p1_to_p3(ge_p3 *r, const ge_p1p1 *p); +void x25519_ge_add(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q); +void x25519_ge_sub(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q); +void x25519_ge_scalarmult_small_precomp( + ge_p3 *h, const uint8_t a[32], const uint8_t precomp_table[15 * 2 * 32]); +void x25519_ge_scalarmult_base(ge_p3 *h, const uint8_t a[32]); +void x25519_ge_scalarmult(ge_p2 *r, const uint8_t *scalar, const ge_p3 *A); +void x25519_sc_reduce(uint8_t *s); + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_CURVE25519_INTERNAL_H */ diff --git a/external/boringssl/crypto/curve25519/spake25519.c b/external/boringssl/crypto/curve25519/spake25519.c new file mode 100644 index 0000000000..617418cfbd --- /dev/null +++ b/external/boringssl/crypto/curve25519/spake25519.c @@ -0,0 +1,464 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include + +#include +#include +#include +#include + +#include "internal.h" + + +/* The following precomputation tables are for the following + * points used in the SPAKE2 protocol. + * + * N: + * x: 49918732221787544735331783592030787422991506689877079631459872391322455579424 + * y: 54629554431565467720832445949441049581317094546788069926228343916274969994000 + * encoded: 10e3df0ae37d8e7a99b5fe74b44672103dbddcbd06af680d71329a11693bc778 + * + * M: + * x: 31406539342727633121250288103050113562375374900226415211311216773867585644232 + * y: 21177308356423958466833845032658859666296341766942662650232962324899758529114 + * encoded: 5ada7e4bf6ddd9adb6626d32131c6b5c51a1e347a3478f53cfcf441b88eed12e + * + * These points and their precomputation tables are generated with the + * following Python code. For a description of the precomputation table, + * see curve25519.c in this directory. + * + * Exact copies of the source code are kept in bug 27296743. + * + * import hashlib + * import ed25519 as E # http://ed25519.cr.yp.to/python/ed25519.py + * + * SEED_N = 'edwards25519 point generation seed (N)' + * SEED_M = 'edwards25519 point generation seed (M)' + * + * def genpoint(seed): + * v = hashlib.sha256(seed).digest() + * it = 1 + * while True: + * try: + * x,y = E.decodepoint(v) + * except Exception, e: + * print e + * it += 1 + * v = hashlib.sha256(v).digest() + * continue + * print "Found in %d iterations:" % it + * print " x = %d" % x + * print " y = %d" % y + * print " Encoded (hex)" + * print E.encodepoint((x,y)).encode('hex') + * return (x,y) + * + * def gentable(P): + * t = [] + * for i in range(1,16): + * k = (i >> 3 & 1) * (1 << 192) + \ + * (i >> 2 & 1) * (1 << 128) + \ + * (i >> 1 & 1) * (1 << 64) + \ + * (i & 1) + * t.append(E.scalarmult(P, k)) + * return ''.join(E.encodeint(x) + E.encodeint(y) for (x,y) in t) + * + * def printtable(table, name): + * print "static const uint8_t %s[15 * 2 * 32] = {" % name, + * for i in range(15 * 2 * 32): + * if i % 12 == 0: + * print "\n ", + * print " 0x%02x," % ord(table[i]), + * print "\n};" + * + * if __name__ == "__main__": + * print "Searching for N" + * N = genpoint(SEED_N) + * print "Generating precomputation table for N" + * Ntable = gentable(N) + * printtable(Ntable, "kSpakeNSmallPrecomp") + * + * print "Searching for M" + * M = genpoint(SEED_M) + * print "Generating precomputation table for M" + * Mtable = gentable(M) + * printtable(Mtable, "kSpakeMSmallPrecomp") + */ +static const uint8_t kSpakeNSmallPrecomp[15 * 2 * 32] = { + 0x20, 0x1b, 0xc5, 0xb3, 0x43, 0x17, 0x71, 0x10, 0x44, 0x1e, 0x73, 0xb3, + 0xae, 0x3f, 0xbf, 0x9f, 0xf5, 0x44, 0xc8, 0x13, 0x8f, 0xd1, 0x01, 0xc2, + 0x8a, 0x1a, 0x6d, 0xea, 0x4d, 0x00, 0x5d, 0x6e, 0x10, 0xe3, 0xdf, 0x0a, + 0xe3, 0x7d, 0x8e, 0x7a, 0x99, 0xb5, 0xfe, 0x74, 0xb4, 0x46, 0x72, 0x10, + 0x3d, 0xbd, 0xdc, 0xbd, 0x06, 0xaf, 0x68, 0x0d, 0x71, 0x32, 0x9a, 0x11, + 0x69, 0x3b, 0xc7, 0x78, 0x93, 0xf1, 0x57, 0x97, 0x6e, 0xf0, 0x6e, 0x45, + 0x37, 0x4a, 0xf4, 0x0b, 0x18, 0x51, 0xf5, 0x4f, 0x67, 0x3c, 0xdc, 0xec, + 0x84, 0xed, 0xd0, 0xeb, 0xca, 0xfb, 0xdb, 0xff, 0x7f, 0xeb, 0xa8, 0x23, + 0x68, 0x87, 0x13, 0x64, 0x6a, 0x10, 0xf7, 0x45, 0xe0, 0x0f, 0x32, 0x21, + 0x59, 0x7c, 0x0e, 0x50, 0xad, 0x56, 0xd7, 0x12, 0x69, 0x7b, 0x58, 0xf8, + 0xb9, 0x3b, 0xa5, 0xbb, 0x4d, 0x1b, 0x87, 0x1c, 0x46, 0xa7, 0x17, 0x9d, + 0x6d, 0x84, 0x45, 0xbe, 0x7f, 0x95, 0xd2, 0x34, 0xcd, 0x89, 0x95, 0xc0, + 0xf0, 0xd3, 0xdf, 0x6e, 0x10, 0x4a, 0xe3, 0x7b, 0xce, 0x7f, 0x40, 0x27, + 0xc7, 0x2b, 0xab, 0x66, 0x03, 0x59, 0xb4, 0x7b, 0xc7, 0xc7, 0xf0, 0x39, + 0x9a, 0x33, 0x35, 0xbf, 0xcc, 0x2f, 0xf3, 0x2e, 0x68, 0x9d, 0x53, 0x5c, + 0x88, 0x52, 0xe3, 0x77, 0x90, 0xa1, 0x27, 0x85, 0xc5, 0x74, 0x7f, 0x23, + 0x0e, 0x93, 0x01, 0x3e, 0xe7, 0x2e, 0x2e, 0x95, 0xf3, 0x0d, 0xc2, 0x25, + 0x25, 0x39, 0x39, 0x3d, 0x6e, 0x8e, 0x89, 0xbd, 0xe8, 0xbb, 0x67, 0x5e, + 0x8c, 0x66, 0x8b, 0x63, 0x28, 0x1e, 0x4e, 0x74, 0x85, 0xa8, 0xaf, 0x0f, + 0x12, 0x5d, 0xb6, 0x8a, 0x83, 0x1a, 0x77, 0x76, 0x5e, 0x62, 0x8a, 0xa7, + 0x3c, 0xb8, 0x05, 0x57, 0x2b, 0xaf, 0x36, 0x2e, 0x10, 0x90, 0xb2, 0x39, + 0xb4, 0x3e, 0x75, 0x6d, 0x3a, 0xa8, 0x31, 0x35, 0xc2, 0x1e, 0x8f, 0xc2, + 0x79, 0x89, 0x35, 0x16, 0x26, 0xd1, 0xc7, 0x0b, 0x04, 0x1f, 0x1d, 0xf9, + 0x9c, 0x05, 0xa6, 0x6b, 0xb5, 0x19, 0x5a, 0x24, 0x6d, 0x91, 0xc5, 0x31, + 0xfd, 0xc5, 0xfa, 0xe7, 0xa6, 0xcb, 0x0e, 0x4b, 0x18, 0x0d, 0x94, 0xc7, + 0xee, 0x1d, 0x46, 0x1f, 0x92, 0xb1, 0xb2, 0x4a, 0x2b, 0x43, 0x37, 0xfe, + 0xc2, 0x15, 0x11, 0x89, 0xef, 0x59, 0x73, 0x3c, 0x06, 0x76, 0x78, 0xcb, + 0xa6, 0x0d, 0x79, 0x5f, 0x28, 0x0b, 0x5b, 0x8c, 0x9e, 0xe4, 0xaa, 0x51, + 0x9a, 0x42, 0x6f, 0x11, 0x50, 0x3d, 0x01, 0xd6, 0x21, 0xc0, 0x99, 0x5e, + 0x1a, 0xe8, 0x81, 0x25, 0x80, 0xeb, 0xed, 0x5d, 0x37, 0x47, 0x30, 0x70, + 0xa0, 0x4e, 0x0b, 0x43, 0x17, 0xbe, 0xb6, 0x47, 0xe7, 0x2a, 0x62, 0x9d, + 0x5d, 0xa6, 0xc5, 0x33, 0x62, 0x9d, 0x56, 0x24, 0x9d, 0x1d, 0xb2, 0x13, + 0xbc, 0x17, 0x66, 0x43, 0xd1, 0x68, 0xd5, 0x3b, 0x17, 0x69, 0x17, 0xa6, + 0x06, 0x9e, 0x12, 0xb8, 0x7c, 0xd5, 0xaf, 0x3e, 0x21, 0x1b, 0x31, 0xeb, + 0x0b, 0xa4, 0x98, 0x1c, 0xf2, 0x6a, 0x5e, 0x7c, 0x9b, 0x45, 0x8f, 0xb2, + 0x12, 0x06, 0xd5, 0x8c, 0x1d, 0xb2, 0xa7, 0x57, 0x5f, 0x2f, 0x4f, 0xdb, + 0x52, 0x99, 0x7c, 0x58, 0x01, 0x5f, 0xf2, 0xa5, 0xf6, 0x51, 0x86, 0x21, + 0x2f, 0x5b, 0x8d, 0x6a, 0xae, 0x83, 0x34, 0x6d, 0x58, 0x4b, 0xef, 0xfe, + 0xbf, 0x73, 0x5d, 0xdb, 0xc4, 0x97, 0x2a, 0x85, 0xf3, 0x6c, 0x46, 0x42, + 0xb3, 0x90, 0xc1, 0x57, 0x97, 0x50, 0x35, 0xb1, 0x9d, 0xb7, 0xc7, 0x3c, + 0x85, 0x6d, 0x6c, 0xfd, 0xce, 0xb0, 0xc9, 0xa2, 0x77, 0xee, 0xc3, 0x6b, + 0x0c, 0x37, 0xfa, 0x30, 0x91, 0xd1, 0x2c, 0xb8, 0x5e, 0x7f, 0x81, 0x5f, + 0x87, 0xfd, 0x18, 0x02, 0x5a, 0x30, 0x4e, 0x62, 0xbc, 0x65, 0xc6, 0xce, + 0x1a, 0xcf, 0x2b, 0xaa, 0x56, 0x3e, 0x4d, 0xcf, 0xba, 0x62, 0x5f, 0x9a, + 0xd0, 0x72, 0xff, 0xef, 0x28, 0xbd, 0xbe, 0xd8, 0x57, 0x3d, 0xf5, 0x57, + 0x7d, 0xe9, 0x71, 0x31, 0xec, 0x98, 0x90, 0x94, 0xd9, 0x54, 0xbf, 0x84, + 0x0b, 0xe3, 0x06, 0x47, 0x19, 0x9a, 0x13, 0x1d, 0xef, 0x9d, 0x13, 0xf3, + 0xdb, 0xc3, 0x5c, 0x72, 0x9e, 0xed, 0x24, 0xaa, 0x64, 0xed, 0xe7, 0x0d, + 0xa0, 0x7c, 0x73, 0xba, 0x9b, 0x86, 0xa7, 0x3b, 0x55, 0xab, 0x58, 0x30, + 0xf1, 0x15, 0x81, 0x83, 0x2f, 0xf9, 0x62, 0x84, 0x98, 0x66, 0xf6, 0x55, + 0x21, 0xd8, 0xf2, 0x25, 0x64, 0x71, 0x4b, 0x12, 0x76, 0x59, 0xc5, 0xaa, + 0x93, 0x67, 0xc3, 0x86, 0x25, 0xab, 0x4e, 0x4b, 0xf6, 0xd8, 0x3f, 0x44, + 0x2e, 0x11, 0xe0, 0xbd, 0x6a, 0xf2, 0x5d, 0xf5, 0xf9, 0x53, 0xea, 0xa4, + 0xc8, 0xd9, 0x50, 0x33, 0x81, 0xd9, 0xa8, 0x2d, 0x91, 0x7d, 0x13, 0x2a, + 0x11, 0xcf, 0xde, 0x3f, 0x0a, 0xd2, 0xbc, 0x33, 0xb2, 0x62, 0x53, 0xea, + 0x77, 0x88, 0x43, 0x66, 0x27, 0x43, 0x85, 0xe9, 0x5f, 0x55, 0xf5, 0x2a, + 0x8a, 0xac, 0xdf, 0xff, 0x9b, 0x4c, 0x96, 0x9c, 0xa5, 0x7a, 0xce, 0xd5, + 0x79, 0x18, 0xf1, 0x0b, 0x58, 0x95, 0x7a, 0xe7, 0xd3, 0x74, 0x65, 0x0b, + 0xa4, 0x64, 0x30, 0xe8, 0x5c, 0xfc, 0x55, 0x56, 0xee, 0x14, 0x14, 0xd3, + 0x45, 0x3b, 0xf8, 0xde, 0x05, 0x3e, 0xb9, 0x3c, 0xd7, 0x6a, 0x52, 0x72, + 0x5b, 0x39, 0x09, 0xbe, 0x82, 0x23, 0x10, 0x4a, 0xb7, 0xc3, 0xdc, 0x4c, + 0x5d, 0xc9, 0xf1, 0x14, 0x83, 0xf9, 0x0b, 0x9b, 0xe9, 0x23, 0x84, 0x6a, + 0xc4, 0x08, 0x3d, 0xda, 0x3d, 0x12, 0x95, 0x87, 0x18, 0xa4, 0x7d, 0x3f, + 0x23, 0xde, 0xd4, 0x1e, 0xa8, 0x47, 0xc3, 0x71, 0xdb, 0xf5, 0x03, 0x6c, + 0x57, 0xe7, 0xa4, 0x43, 0x82, 0x33, 0x7b, 0x62, 0x46, 0x7d, 0xf7, 0x10, + 0x69, 0x18, 0x38, 0x27, 0x9a, 0x6f, 0x38, 0xac, 0xfa, 0x92, 0xc5, 0xae, + 0x66, 0xa6, 0x73, 0x95, 0x15, 0x0e, 0x4c, 0x04, 0xb6, 0xfc, 0xf5, 0xc7, + 0x21, 0x3a, 0x99, 0xdb, 0x0e, 0x36, 0xf0, 0x56, 0xbc, 0x75, 0xf9, 0x87, + 0x9b, 0x11, 0x18, 0x92, 0x64, 0x1a, 0xe7, 0xc7, 0xab, 0x5a, 0xc7, 0x26, + 0x7f, 0x13, 0x98, 0x42, 0x52, 0x43, 0xdb, 0xc8, 0x6d, 0x0b, 0xb7, 0x31, + 0x93, 0x24, 0xd6, 0xe8, 0x24, 0x1f, 0x6f, 0x21, 0xa7, 0x8c, 0xeb, 0xdb, + 0x83, 0xb8, 0x89, 0xe3, 0xc1, 0xd7, 0x69, 0x3b, 0x02, 0x6b, 0x54, 0x0f, + 0x84, 0x2f, 0xb5, 0x5c, 0x17, 0x77, 0xbe, 0xe5, 0x61, 0x0d, 0xc5, 0xdf, + 0x3b, 0xcf, 0x3e, 0x93, 0x4f, 0xf5, 0x89, 0xb9, 0x5a, 0xc5, 0x29, 0x31, + 0xc0, 0xc2, 0xff, 0xe5, 0x3f, 0xa6, 0xac, 0x03, 0xca, 0xf5, 0xff, 0xe0, + 0x36, 0xce, 0xf3, 0xe2, 0xb7, 0x9c, 0x02, 0xe9, 0x9e, 0xd2, 0xbc, 0x87, + 0x2f, 0x3d, 0x9a, 0x1d, 0x8f, 0xc5, 0x72, 0xb8, 0xa2, 0x01, 0xd4, 0x68, + 0xb1, 0x84, 0x16, 0x10, 0xf6, 0xf3, 0x52, 0x25, 0xd9, 0xdc, 0x4c, 0xdd, + 0x0f, 0xd6, 0x4a, 0xcf, 0x60, 0x96, 0x7e, 0xcc, 0x42, 0x0f, 0x64, 0x9d, + 0x72, 0x46, 0x04, 0x07, 0xf2, 0x5b, 0xf4, 0x07, 0xd1, 0xf4, 0x59, 0x71, +}; + +static const uint8_t kSpakeMSmallPrecomp[15 * 2 * 32] = { + 0xc8, 0xa6, 0x63, 0xc5, 0x97, 0xf1, 0xee, 0x40, 0xab, 0x62, 0x42, 0xee, + 0x25, 0x6f, 0x32, 0x6c, 0x75, 0x2c, 0xa7, 0xd3, 0xbd, 0x32, 0x3b, 0x1e, + 0x11, 0x9c, 0xbd, 0x04, 0xa9, 0x78, 0x6f, 0x45, 0x5a, 0xda, 0x7e, 0x4b, + 0xf6, 0xdd, 0xd9, 0xad, 0xb6, 0x62, 0x6d, 0x32, 0x13, 0x1c, 0x6b, 0x5c, + 0x51, 0xa1, 0xe3, 0x47, 0xa3, 0x47, 0x8f, 0x53, 0xcf, 0xcf, 0x44, 0x1b, + 0x88, 0xee, 0xd1, 0x2e, 0x03, 0x89, 0xaf, 0xc0, 0x61, 0x2d, 0x9e, 0x35, + 0xeb, 0x0e, 0x03, 0xe0, 0xb7, 0xfb, 0xa5, 0xbc, 0x44, 0xbe, 0x0c, 0x89, + 0x0a, 0x0f, 0xd6, 0x59, 0x47, 0x9e, 0xe6, 0x3d, 0x36, 0x9d, 0xff, 0x44, + 0x5e, 0xac, 0xab, 0xe5, 0x3a, 0xd5, 0xb0, 0x35, 0x9f, 0x6d, 0x7f, 0xba, + 0xc0, 0x85, 0x0e, 0xf4, 0x70, 0x3f, 0x13, 0x90, 0x4c, 0x50, 0x1a, 0xee, + 0xc5, 0xeb, 0x69, 0xfe, 0x98, 0x42, 0x87, 0x1d, 0xce, 0x6c, 0x29, 0xaa, + 0x2b, 0x31, 0xc2, 0x38, 0x7b, 0x6b, 0xee, 0x88, 0x0b, 0xba, 0xce, 0xa8, + 0xca, 0x19, 0x60, 0x1b, 0x16, 0xf1, 0x25, 0x1e, 0xcf, 0x63, 0x66, 0x1e, + 0xbb, 0x63, 0xeb, 0x7d, 0xca, 0xd2, 0xb4, 0x23, 0x5a, 0x01, 0x6f, 0x05, + 0xd1, 0xdc, 0x41, 0x73, 0x75, 0xc0, 0xfd, 0x30, 0x91, 0x52, 0x68, 0x96, + 0x45, 0xb3, 0x66, 0x01, 0x3b, 0x53, 0x89, 0x3c, 0x69, 0xbc, 0x6c, 0x69, + 0xe3, 0x51, 0x8f, 0xe3, 0xd2, 0x84, 0xd5, 0x28, 0x66, 0xb5, 0xe6, 0x06, + 0x09, 0xfe, 0x6d, 0xb0, 0x72, 0x16, 0xe0, 0x8a, 0xce, 0x61, 0x65, 0xa9, + 0x21, 0x32, 0x48, 0xdc, 0x7a, 0x1d, 0xe1, 0x38, 0x7f, 0x8c, 0x75, 0x88, + 0x3d, 0x08, 0xa9, 0x4a, 0x6f, 0x3d, 0x9f, 0x7f, 0x3f, 0xbd, 0x57, 0x6b, + 0x19, 0xce, 0x3f, 0x4a, 0xc9, 0xd3, 0xf9, 0x6e, 0x72, 0x7b, 0x5b, 0x74, + 0xea, 0xbe, 0x9c, 0x7a, 0x6d, 0x9c, 0x40, 0x49, 0xe6, 0xfb, 0x2a, 0x1a, + 0x75, 0x70, 0xe5, 0x4e, 0xed, 0x74, 0xe0, 0x75, 0xac, 0xc0, 0xb1, 0x11, + 0x3e, 0xf2, 0xaf, 0x88, 0x4d, 0x66, 0xb6, 0xf6, 0x15, 0x4f, 0x3c, 0x6c, + 0x77, 0xae, 0x47, 0x51, 0x63, 0x9a, 0xfe, 0xe1, 0xb4, 0x1a, 0x12, 0xdf, + 0xe9, 0x54, 0x8d, 0x3b, 0x30, 0x2a, 0x75, 0xe3, 0xe5, 0x29, 0xb1, 0x4c, + 0xb0, 0x7c, 0x6d, 0xb5, 0xae, 0x85, 0xdb, 0x1e, 0x38, 0x55, 0x96, 0xa5, + 0x5b, 0x9f, 0x15, 0x23, 0x28, 0x36, 0xb8, 0xa2, 0x41, 0xb4, 0xd7, 0x19, + 0x91, 0x8d, 0x26, 0x3e, 0xca, 0x9c, 0x05, 0x7a, 0x2b, 0x60, 0x45, 0x86, + 0x8b, 0xee, 0x64, 0x6f, 0x5c, 0x09, 0x4d, 0x4b, 0x5a, 0x7f, 0xb0, 0xc3, + 0x26, 0x9d, 0x8b, 0xb8, 0x83, 0x69, 0xcf, 0x16, 0x72, 0x62, 0x3e, 0x5e, + 0x53, 0x4f, 0x9c, 0x73, 0x76, 0xfc, 0x19, 0xef, 0xa0, 0x74, 0x3a, 0x11, + 0x1e, 0xd0, 0x4d, 0xb7, 0x87, 0xa1, 0xd6, 0x87, 0x6c, 0x0e, 0x6c, 0x8c, + 0xe9, 0xa0, 0x44, 0xc4, 0x72, 0x3e, 0x73, 0x17, 0x13, 0xd1, 0x4e, 0x3d, + 0x8e, 0x1d, 0x5a, 0x8b, 0x75, 0xcb, 0x59, 0x2c, 0x47, 0x87, 0x15, 0x41, + 0xfe, 0x08, 0xe9, 0xa6, 0x97, 0x17, 0x08, 0x26, 0x6a, 0xb5, 0xbb, 0x73, + 0xaa, 0xb8, 0x5b, 0x65, 0x65, 0x5b, 0x30, 0x9e, 0x62, 0x59, 0x02, 0xf8, + 0xb8, 0x0f, 0x32, 0x10, 0xc1, 0x36, 0x08, 0x52, 0x98, 0x4a, 0x1e, 0xf0, + 0xab, 0x21, 0x5e, 0xde, 0x16, 0x0c, 0xda, 0x09, 0x99, 0x6b, 0x9e, 0xc0, + 0x90, 0xa5, 0x5a, 0xcc, 0xb0, 0xb7, 0xbb, 0xd2, 0x8b, 0x5f, 0xd3, 0x3b, + 0x3e, 0x8c, 0xa5, 0x71, 0x66, 0x06, 0xe3, 0x28, 0xd4, 0xf8, 0x3f, 0xe5, + 0x27, 0xdf, 0xfe, 0x0f, 0x09, 0xb2, 0x8a, 0x09, 0x5a, 0x23, 0x61, 0x0d, + 0x2d, 0xf5, 0x44, 0xf1, 0x5c, 0xf8, 0x82, 0x4e, 0xdc, 0x78, 0x7a, 0xab, + 0xc3, 0x57, 0x91, 0xaf, 0x65, 0x6e, 0x71, 0xf1, 0x44, 0xbf, 0xed, 0x43, + 0x50, 0xb4, 0x67, 0x48, 0xef, 0x5a, 0x10, 0x46, 0x81, 0xb4, 0x0c, 0xc8, + 0x48, 0xed, 0x99, 0x7a, 0x45, 0xa5, 0x92, 0xc3, 0x69, 0xd6, 0xd7, 0x8a, + 0x20, 0x1b, 0xeb, 0x8f, 0xb2, 0xff, 0xec, 0x6d, 0x76, 0x04, 0xf8, 0xc2, + 0x58, 0x9b, 0xf2, 0x20, 0x53, 0xc4, 0x74, 0x91, 0x19, 0xdd, 0x2d, 0x12, + 0x53, 0xc7, 0x6e, 0xd0, 0x02, 0x51, 0x3c, 0xa6, 0x7d, 0x80, 0x75, 0x6b, + 0x1d, 0xdf, 0xf8, 0x6a, 0x52, 0xbb, 0x81, 0xf8, 0x30, 0x45, 0xef, 0x51, + 0x85, 0x36, 0xbe, 0x8e, 0xcf, 0x0b, 0x9a, 0x46, 0xe8, 0x3f, 0x99, 0xfd, + 0xf7, 0xd9, 0x3e, 0x84, 0xe5, 0xe3, 0x37, 0xcf, 0x98, 0x7f, 0xeb, 0x5e, + 0x5a, 0x53, 0x77, 0x1c, 0x20, 0xdc, 0xf1, 0x20, 0x99, 0xec, 0x60, 0x40, + 0x93, 0xef, 0x5c, 0x1c, 0x81, 0xe2, 0xa5, 0xad, 0x2a, 0xc2, 0xdb, 0x6b, + 0xc1, 0x7e, 0x8f, 0xa9, 0x23, 0x5b, 0xd9, 0x0d, 0xfe, 0xa0, 0xac, 0x11, + 0x28, 0xba, 0x8e, 0x92, 0x07, 0x2d, 0x07, 0x40, 0x83, 0x14, 0x4c, 0x35, + 0x8d, 0xd0, 0x11, 0xff, 0x98, 0xdb, 0x00, 0x30, 0x6f, 0x65, 0xb6, 0xa0, + 0x7f, 0x9c, 0x08, 0xb8, 0xce, 0xb3, 0xa8, 0x42, 0xd3, 0x84, 0x45, 0xe1, + 0xe3, 0x8f, 0xa6, 0x89, 0x21, 0xd7, 0x74, 0x02, 0x4d, 0x64, 0xdf, 0x54, + 0x15, 0x9e, 0xba, 0x12, 0x49, 0x09, 0x41, 0xf6, 0x10, 0x24, 0xa1, 0x84, + 0x15, 0xfd, 0x68, 0x6a, 0x57, 0x66, 0xb3, 0x6d, 0x4c, 0xea, 0xbf, 0xbc, + 0x60, 0x3f, 0x52, 0x1c, 0x44, 0x1b, 0xc0, 0x4a, 0x25, 0xe3, 0xd9, 0x4c, + 0x9a, 0x74, 0xad, 0xfc, 0x9e, 0x8d, 0x0b, 0x18, 0x66, 0x24, 0xd1, 0x06, + 0xac, 0x68, 0xc1, 0xae, 0x14, 0xce, 0xb1, 0xf3, 0x86, 0x9f, 0x87, 0x11, + 0xd7, 0x9f, 0x30, 0x92, 0xdb, 0xec, 0x0b, 0x4a, 0xe8, 0xf6, 0x53, 0x36, + 0x68, 0x12, 0x11, 0x5e, 0xe0, 0x34, 0xa4, 0xff, 0x00, 0x0a, 0x26, 0xb8, + 0x62, 0x79, 0x9c, 0x0c, 0xd5, 0xe5, 0xf5, 0x1c, 0x1a, 0x16, 0x84, 0x4d, + 0x8e, 0x5d, 0x31, 0x7e, 0xf7, 0xe2, 0xd3, 0xa1, 0x41, 0x90, 0x61, 0x5d, + 0x04, 0xb2, 0x9a, 0x18, 0x9e, 0x54, 0xfb, 0xd1, 0x61, 0x95, 0x1b, 0x08, + 0xca, 0x7c, 0x49, 0x44, 0x74, 0x1d, 0x2f, 0xca, 0xc4, 0x7a, 0xe1, 0x8b, + 0x2f, 0xbb, 0x96, 0xee, 0x19, 0x8a, 0x5d, 0xfb, 0x3e, 0x82, 0xe7, 0x15, + 0xdb, 0x29, 0x14, 0xee, 0xc9, 0x4d, 0x9a, 0xfb, 0x9f, 0x8a, 0xbb, 0x17, + 0x37, 0x1b, 0x6e, 0x28, 0x6c, 0xf9, 0xff, 0xb5, 0xb5, 0x8b, 0x9d, 0x88, + 0x20, 0x08, 0x10, 0xd7, 0xca, 0x58, 0xf6, 0xe1, 0x32, 0x91, 0x6f, 0x36, + 0xc0, 0xad, 0xc1, 0x57, 0x5d, 0x76, 0x31, 0x43, 0xf3, 0xdd, 0xec, 0xf1, + 0xa9, 0x79, 0xe9, 0xe9, 0x85, 0xd7, 0x91, 0xc7, 0x31, 0x62, 0x3c, 0xd2, + 0x90, 0x2c, 0x9c, 0xa4, 0x56, 0x37, 0x7b, 0xbe, 0x40, 0x58, 0xc0, 0x81, + 0x83, 0x22, 0xe8, 0x13, 0x79, 0x18, 0xdb, 0x3a, 0x1b, 0x31, 0x0d, 0x00, + 0x6c, 0x22, 0x62, 0x75, 0x70, 0xd8, 0x96, 0x59, 0x99, 0x44, 0x79, 0x71, + 0xa6, 0x76, 0x81, 0x28, 0xb2, 0x65, 0xe8, 0x47, 0x14, 0xc6, 0x39, 0x06, +}; + +enum spake2_state_t { + spake2_state_init = 0, + spake2_state_msg_generated, + spake2_state_key_generated, +}; + +struct spake2_ctx_st { + uint8_t private_key[32]; + uint8_t my_msg[32]; + uint8_t password_scalar[32]; + uint8_t password_hash[SHA512_DIGEST_LENGTH]; + uint8_t *my_name; + size_t my_name_len; + uint8_t *their_name; + size_t their_name_len; + enum spake2_role_t my_role; + enum spake2_state_t state; +}; + +SPAKE2_CTX *SPAKE2_CTX_new(enum spake2_role_t my_role, + const uint8_t *my_name, size_t my_name_len, + const uint8_t *their_name, size_t their_name_len) { + SPAKE2_CTX *ctx = OPENSSL_malloc(sizeof(SPAKE2_CTX)); + if (ctx == NULL) { + return NULL; + } + + memset(ctx, 0, sizeof(SPAKE2_CTX)); + ctx->my_role = my_role; + + CBS my_name_cbs, their_name_cbs; + CBS_init(&my_name_cbs, my_name, my_name_len); + CBS_init(&their_name_cbs, their_name, their_name_len); + if (!CBS_stow(&my_name_cbs, &ctx->my_name, &ctx->my_name_len) || + !CBS_stow(&their_name_cbs, &ctx->their_name, &ctx->their_name_len)) { + SPAKE2_CTX_free(ctx); + return NULL; + } + + return ctx; +} + +void SPAKE2_CTX_free(SPAKE2_CTX *ctx) { + if (ctx == NULL) { + return; + } + + OPENSSL_free(ctx->my_name); + OPENSSL_free(ctx->their_name); + OPENSSL_free(ctx); +} + +/* left_shift_3 sets |n| to |n|*8, where |n| is represented in little-endian + * order. */ +static void left_shift_3(uint8_t n[32]) { + uint8_t carry = 0; + unsigned i; + + for (i = 0; i < 32; i++) { + const uint8_t next_carry = n[i] >> 5; + n[i] = (n[i] << 3) | carry; + carry = next_carry; + } +} + +int SPAKE2_generate_msg(SPAKE2_CTX *ctx, uint8_t *out, size_t *out_len, + size_t max_out_len, const uint8_t *password, + size_t password_len) { + if (ctx->state != spake2_state_init) { + return 0; + } + + if (max_out_len < sizeof(ctx->my_msg)) { + return 0; + } + + uint8_t private_tmp[64]; + RAND_bytes(private_tmp, sizeof(private_tmp)); + x25519_sc_reduce(private_tmp); + /* Multiply by the cofactor (eight) so that we'll clear it when operating on + * the peer's point later in the protocol. */ + left_shift_3(private_tmp); + memcpy(ctx->private_key, private_tmp, sizeof(ctx->private_key)); + + ge_p3 P; + x25519_ge_scalarmult_base(&P, ctx->private_key); + + /* mask = h(password) * . */ + uint8_t password_tmp[SHA512_DIGEST_LENGTH]; + SHA512(password, password_len, password_tmp); + memcpy(ctx->password_hash, password_tmp, sizeof(ctx->password_hash)); + x25519_sc_reduce(password_tmp); + memcpy(ctx->password_scalar, password_tmp, sizeof(ctx->password_scalar)); + + ge_p3 mask; + x25519_ge_scalarmult_small_precomp(&mask, ctx->password_scalar, + ctx->my_role == spake2_role_alice + ? kSpakeMSmallPrecomp + : kSpakeNSmallPrecomp); + + /* P* = P + mask. */ + ge_cached mask_cached; + x25519_ge_p3_to_cached(&mask_cached, &mask); + ge_p1p1 Pstar; + x25519_ge_add(&Pstar, &P, &mask_cached); + + /* Encode P* */ + ge_p2 Pstar_proj; + x25519_ge_p1p1_to_p2(&Pstar_proj, &Pstar); + x25519_ge_tobytes(ctx->my_msg, &Pstar_proj); + + memcpy(out, ctx->my_msg, sizeof(ctx->my_msg)); + *out_len = sizeof(ctx->my_msg); + ctx->state = spake2_state_msg_generated; + + return 1; +} + +static void update_with_length_prefix(SHA512_CTX *sha, const uint8_t *data, + const size_t len) { + uint8_t len_le[8]; + size_t l = len; + unsigned i; + + for (i = 0; i < 8; i++) { + len_le[i] = l & 0xff; + l >>= 8; + } + + SHA512_Update(sha, len_le, sizeof(len_le)); + SHA512_Update(sha, data, len); +} + +int SPAKE2_process_msg(SPAKE2_CTX *ctx, uint8_t *out_key, size_t *out_key_len, + size_t max_out_key_len, const uint8_t *their_msg, + size_t their_msg_len) { + if (ctx->state != spake2_state_msg_generated || + their_msg_len != 32) { + return 0; + } + + ge_p3 Qstar; + if (0 != x25519_ge_frombytes_vartime(&Qstar, their_msg)) { + /* Point received from peer was not on the curve. */ + return 0; + } + + /* Unmask peer's value. */ + ge_p3 peers_mask; + x25519_ge_scalarmult_small_precomp(&peers_mask, ctx->password_scalar, + ctx->my_role == spake2_role_alice + ? kSpakeNSmallPrecomp + : kSpakeMSmallPrecomp); + + ge_cached peers_mask_cached; + x25519_ge_p3_to_cached(&peers_mask_cached, &peers_mask); + + ge_p1p1 Q_compl; + ge_p3 Q_ext; + x25519_ge_sub(&Q_compl, &Qstar, &peers_mask_cached); + x25519_ge_p1p1_to_p3(&Q_ext, &Q_compl); + + ge_p2 dh_shared; + x25519_ge_scalarmult(&dh_shared, ctx->private_key, &Q_ext); + + uint8_t dh_shared_encoded[32]; + x25519_ge_tobytes(dh_shared_encoded, &dh_shared); + + SHA512_CTX sha; + SHA512_Init(&sha); + if (ctx->my_role == spake2_role_alice) { + update_with_length_prefix(&sha, ctx->my_name, ctx->my_name_len); + update_with_length_prefix(&sha, ctx->their_name, ctx->their_name_len); + update_with_length_prefix(&sha, ctx->my_msg, sizeof(ctx->my_msg)); + update_with_length_prefix(&sha, their_msg, 32); + } else { + update_with_length_prefix(&sha, ctx->their_name, ctx->their_name_len); + update_with_length_prefix(&sha, ctx->my_name, ctx->my_name_len); + update_with_length_prefix(&sha, their_msg, 32); + update_with_length_prefix(&sha, ctx->my_msg, sizeof(ctx->my_msg)); + } + update_with_length_prefix(&sha, dh_shared_encoded, sizeof(dh_shared_encoded)); + update_with_length_prefix(&sha, ctx->password_hash, + sizeof(ctx->password_hash)); + + uint8_t key[SHA512_DIGEST_LENGTH]; + SHA512_Final(key, &sha); + + size_t to_copy = max_out_key_len; + if (to_copy > sizeof(key)) { + to_copy = sizeof(key); + } + memcpy(out_key, key, to_copy); + *out_key_len = to_copy; + ctx->state = spake2_state_key_generated; + + return 1; +} diff --git a/external/boringssl/crypto/curve25519/spake25519_test.cc b/external/boringssl/crypto/curve25519/spake25519_test.cc new file mode 100644 index 0000000000..d97a8602af --- /dev/null +++ b/external/boringssl/crypto/curve25519/spake25519_test.cc @@ -0,0 +1,169 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include +#include +#include + +#include +#include "../test/scoped_types.h" + + +struct SPAKE2Run { + bool Run() { + ScopedSPAKE2_CTX alice(SPAKE2_CTX_new( + spake2_role_alice, + reinterpret_cast(alice_names.first.data()), + alice_names.first.size(), + reinterpret_cast(alice_names.second.data()), + alice_names.second.size())); + ScopedSPAKE2_CTX bob(SPAKE2_CTX_new( + spake2_role_bob, + reinterpret_cast(bob_names.first.data()), + bob_names.first.size(), + reinterpret_cast(bob_names.second.data()), + bob_names.second.size())); + + if (!alice || !bob) { + return false; + } + + uint8_t alice_msg[SPAKE2_MAX_MSG_SIZE]; + uint8_t bob_msg[SPAKE2_MAX_MSG_SIZE]; + size_t alice_msg_len, bob_msg_len; + + if (!SPAKE2_generate_msg( + alice.get(), alice_msg, &alice_msg_len, sizeof(alice_msg), + reinterpret_cast(alice_password.data()), + alice_password.size()) || + !SPAKE2_generate_msg( + bob.get(), bob_msg, &bob_msg_len, sizeof(bob_msg), + reinterpret_cast(bob_password.data()), + bob_password.size())) { + return false; + } + + if (alice_corrupt_msg_bit >= 0 && + static_cast(alice_corrupt_msg_bit) < 8 * alice_msg_len) { + alice_msg[alice_corrupt_msg_bit/8] ^= 1 << (alice_corrupt_msg_bit & 7); + } + + uint8_t alice_key[64], bob_key[64]; + size_t alice_key_len, bob_key_len; + + if (!SPAKE2_process_msg(alice.get(), alice_key, &alice_key_len, + sizeof(alice_key), bob_msg, bob_msg_len) || + !SPAKE2_process_msg(bob.get(), bob_key, &bob_key_len, sizeof(bob_key), + alice_msg, alice_msg_len)) { + return false; + } + + key_matches_ = (alice_key_len == bob_key_len && + memcmp(alice_key, bob_key, alice_key_len) == 0); + + return true; + } + + bool key_matches() const { + return key_matches_; + } + + std::string alice_password = "password"; + std::string bob_password = "password"; + std::pair alice_names = {"alice", "bob"}; + std::pair bob_names = {"bob", "alice"}; + int alice_corrupt_msg_bit = -1; + + private: + bool key_matches_ = false; +}; + +static bool TestSPAKE2() { + for (unsigned i = 0; i < 20; i++) { + SPAKE2Run spake2; + if (!spake2.Run()) { + fprintf(stderr, "TestSPAKE2: SPAKE2 failed.\n"); + return false; + } + + if (!spake2.key_matches()) { + fprintf(stderr, "Key didn't match for equal passwords.\n"); + return false; + } + } + + return true; +} + +static bool TestWrongPassword() { + SPAKE2Run spake2; + spake2.bob_password = "wrong password"; + if (!spake2.Run()) { + fprintf(stderr, "TestSPAKE2: SPAKE2 failed.\n"); + return false; + } + + if (spake2.key_matches()) { + fprintf(stderr, "Key matched for unequal passwords.\n"); + return false; + } + + return true; +} + +static bool TestWrongNames() { + SPAKE2Run spake2; + spake2.alice_names.second = "charlie"; + spake2.bob_names.second = "charlie"; + if (!spake2.Run()) { + fprintf(stderr, "TestSPAKE2: SPAKE2 failed.\n"); + return false; + } + + if (spake2.key_matches()) { + fprintf(stderr, "Key matched for unequal names.\n"); + return false; + } + + return true; +} + +static bool TestCorruptMessages() { + for (int i = 0; i < 8 * SPAKE2_MAX_MSG_SIZE; i++) { + SPAKE2Run spake2; + spake2.alice_corrupt_msg_bit = i; + if (spake2.Run() && spake2.key_matches()) { + fprintf(stderr, "Passed after corrupting Alice's message, bit %d\n", i); + return false; + } + } + + return true; +} + +/* TODO(agl): add tests with fixed vectors once SPAKE2 is nailed down. */ + +int main(int argc, char **argv) { + if (!TestSPAKE2() || + !TestWrongPassword() || + !TestWrongNames() || + !TestCorruptMessages()) { + return 1; + } + + printf("PASS\n"); + return 0; +} diff --git a/external/boringssl/crypto/curve25519/x25519-x86_64.c b/external/boringssl/crypto/curve25519/x25519-x86_64.c new file mode 100644 index 0000000000..1bd86a09f3 --- /dev/null +++ b/external/boringssl/crypto/curve25519/x25519-x86_64.c @@ -0,0 +1,246 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +/* This code is mostly taken from the ref10 version of Ed25519 in SUPERCOP + * 20141124 (http://bench.cr.yp.to/supercop.html). That code is released as + * public domain but this file has the ISC license just to keep licencing + * simple. + * + * The field functions are shared by Ed25519 and X25519 where possible. */ + +#include + +#include + +#include "internal.h" + + +#if defined(BORINGSSL_X25519_X86_64) + +typedef struct { uint64_t v[5]; } fe25519; + +/* These functions are defined in asm/x25519-x86_64.S */ +void x25519_x86_64_work_cswap(fe25519 *, uint64_t); +void x25519_x86_64_mul(fe25519 *out, const fe25519 *a, const fe25519 *b); +void x25519_x86_64_square(fe25519 *out, const fe25519 *a); +void x25519_x86_64_freeze(fe25519 *); +void x25519_x86_64_ladderstep(fe25519 *work); + +static void fe25519_setint(fe25519 *r, unsigned v) { + r->v[0] = v; + r->v[1] = 0; + r->v[2] = 0; + r->v[3] = 0; + r->v[4] = 0; +} + +/* Assumes input x being reduced below 2^255 */ +static void fe25519_pack(unsigned char r[32], const fe25519 *x) { + fe25519 t; + t = *x; + x25519_x86_64_freeze(&t); + + r[0] = (uint8_t)(t.v[0] & 0xff); + r[1] = (uint8_t)((t.v[0] >> 8) & 0xff); + r[2] = (uint8_t)((t.v[0] >> 16) & 0xff); + r[3] = (uint8_t)((t.v[0] >> 24) & 0xff); + r[4] = (uint8_t)((t.v[0] >> 32) & 0xff); + r[5] = (uint8_t)((t.v[0] >> 40) & 0xff); + r[6] = (uint8_t)((t.v[0] >> 48)); + + r[6] ^= (uint8_t)((t.v[1] << 3) & 0xf8); + r[7] = (uint8_t)((t.v[1] >> 5) & 0xff); + r[8] = (uint8_t)((t.v[1] >> 13) & 0xff); + r[9] = (uint8_t)((t.v[1] >> 21) & 0xff); + r[10] = (uint8_t)((t.v[1] >> 29) & 0xff); + r[11] = (uint8_t)((t.v[1] >> 37) & 0xff); + r[12] = (uint8_t)((t.v[1] >> 45)); + + r[12] ^= (uint8_t)((t.v[2] << 6) & 0xc0); + r[13] = (uint8_t)((t.v[2] >> 2) & 0xff); + r[14] = (uint8_t)((t.v[2] >> 10) & 0xff); + r[15] = (uint8_t)((t.v[2] >> 18) & 0xff); + r[16] = (uint8_t)((t.v[2] >> 26) & 0xff); + r[17] = (uint8_t)((t.v[2] >> 34) & 0xff); + r[18] = (uint8_t)((t.v[2] >> 42) & 0xff); + r[19] = (uint8_t)((t.v[2] >> 50)); + + r[19] ^= (uint8_t)((t.v[3] << 1) & 0xfe); + r[20] = (uint8_t)((t.v[3] >> 7) & 0xff); + r[21] = (uint8_t)((t.v[3] >> 15) & 0xff); + r[22] = (uint8_t)((t.v[3] >> 23) & 0xff); + r[23] = (uint8_t)((t.v[3] >> 31) & 0xff); + r[24] = (uint8_t)((t.v[3] >> 39) & 0xff); + r[25] = (uint8_t)((t.v[3] >> 47)); + + r[25] ^= (uint8_t)((t.v[4] << 4) & 0xf0); + r[26] = (uint8_t)((t.v[4] >> 4) & 0xff); + r[27] = (uint8_t)((t.v[4] >> 12) & 0xff); + r[28] = (uint8_t)((t.v[4] >> 20) & 0xff); + r[29] = (uint8_t)((t.v[4] >> 28) & 0xff); + r[30] = (uint8_t)((t.v[4] >> 36) & 0xff); + r[31] = (uint8_t)((t.v[4] >> 44)); +} + +static void fe25519_unpack(fe25519 *r, const uint8_t x[32]) { + r->v[0] = x[0]; + r->v[0] += (uint64_t)x[1] << 8; + r->v[0] += (uint64_t)x[2] << 16; + r->v[0] += (uint64_t)x[3] << 24; + r->v[0] += (uint64_t)x[4] << 32; + r->v[0] += (uint64_t)x[5] << 40; + r->v[0] += ((uint64_t)x[6] & 7) << 48; + + r->v[1] = x[6] >> 3; + r->v[1] += (uint64_t)x[7] << 5; + r->v[1] += (uint64_t)x[8] << 13; + r->v[1] += (uint64_t)x[9] << 21; + r->v[1] += (uint64_t)x[10] << 29; + r->v[1] += (uint64_t)x[11] << 37; + r->v[1] += ((uint64_t)x[12] & 63) << 45; + + r->v[2] = x[12] >> 6; + r->v[2] += (uint64_t)x[13] << 2; + r->v[2] += (uint64_t)x[14] << 10; + r->v[2] += (uint64_t)x[15] << 18; + r->v[2] += (uint64_t)x[16] << 26; + r->v[2] += (uint64_t)x[17] << 34; + r->v[2] += (uint64_t)x[18] << 42; + r->v[2] += ((uint64_t)x[19] & 1) << 50; + + r->v[3] = x[19] >> 1; + r->v[3] += (uint64_t)x[20] << 7; + r->v[3] += (uint64_t)x[21] << 15; + r->v[3] += (uint64_t)x[22] << 23; + r->v[3] += (uint64_t)x[23] << 31; + r->v[3] += (uint64_t)x[24] << 39; + r->v[3] += ((uint64_t)x[25] & 15) << 47; + + r->v[4] = x[25] >> 4; + r->v[4] += (uint64_t)x[26] << 4; + r->v[4] += (uint64_t)x[27] << 12; + r->v[4] += (uint64_t)x[28] << 20; + r->v[4] += (uint64_t)x[29] << 28; + r->v[4] += (uint64_t)x[30] << 36; + r->v[4] += ((uint64_t)x[31] & 127) << 44; +} + +static void fe25519_invert(fe25519 *r, const fe25519 *x) { + fe25519 z2; + fe25519 z9; + fe25519 z11; + fe25519 z2_5_0; + fe25519 z2_10_0; + fe25519 z2_20_0; + fe25519 z2_50_0; + fe25519 z2_100_0; + fe25519 t; + int i; + + /* 2 */ x25519_x86_64_square(&z2, x); + /* 4 */ x25519_x86_64_square(&t, &z2); + /* 8 */ x25519_x86_64_square(&t, &t); + /* 9 */ x25519_x86_64_mul(&z9, &t, x); + /* 11 */ x25519_x86_64_mul(&z11, &z9, &z2); + /* 22 */ x25519_x86_64_square(&t, &z11); + /* 2^5 - 2^0 = 31 */ x25519_x86_64_mul(&z2_5_0, &t, &z9); + + /* 2^6 - 2^1 */ x25519_x86_64_square(&t, &z2_5_0); + /* 2^20 - 2^10 */ for (i = 1; i < 5; i++) { x25519_x86_64_square(&t, &t); } + /* 2^10 - 2^0 */ x25519_x86_64_mul(&z2_10_0, &t, &z2_5_0); + + /* 2^11 - 2^1 */ x25519_x86_64_square(&t, &z2_10_0); + /* 2^20 - 2^10 */ for (i = 1; i < 10; i++) { x25519_x86_64_square(&t, &t); } + /* 2^20 - 2^0 */ x25519_x86_64_mul(&z2_20_0, &t, &z2_10_0); + + /* 2^21 - 2^1 */ x25519_x86_64_square(&t, &z2_20_0); + /* 2^40 - 2^20 */ for (i = 1; i < 20; i++) { x25519_x86_64_square(&t, &t); } + /* 2^40 - 2^0 */ x25519_x86_64_mul(&t, &t, &z2_20_0); + + /* 2^41 - 2^1 */ x25519_x86_64_square(&t, &t); + /* 2^50 - 2^10 */ for (i = 1; i < 10; i++) { x25519_x86_64_square(&t, &t); } + /* 2^50 - 2^0 */ x25519_x86_64_mul(&z2_50_0, &t, &z2_10_0); + + /* 2^51 - 2^1 */ x25519_x86_64_square(&t, &z2_50_0); + /* 2^100 - 2^50 */ for (i = 1; i < 50; i++) { x25519_x86_64_square(&t, &t); } + /* 2^100 - 2^0 */ x25519_x86_64_mul(&z2_100_0, &t, &z2_50_0); + + /* 2^101 - 2^1 */ x25519_x86_64_square(&t, &z2_100_0); + /* 2^200 - 2^100 */ for (i = 1; i < 100; i++) { + x25519_x86_64_square(&t, &t); + } + /* 2^200 - 2^0 */ x25519_x86_64_mul(&t, &t, &z2_100_0); + + /* 2^201 - 2^1 */ x25519_x86_64_square(&t, &t); + /* 2^250 - 2^50 */ for (i = 1; i < 50; i++) { x25519_x86_64_square(&t, &t); } + /* 2^250 - 2^0 */ x25519_x86_64_mul(&t, &t, &z2_50_0); + + /* 2^251 - 2^1 */ x25519_x86_64_square(&t, &t); + /* 2^252 - 2^2 */ x25519_x86_64_square(&t, &t); + /* 2^253 - 2^3 */ x25519_x86_64_square(&t, &t); + + /* 2^254 - 2^4 */ x25519_x86_64_square(&t, &t); + + /* 2^255 - 2^5 */ x25519_x86_64_square(&t, &t); + /* 2^255 - 21 */ x25519_x86_64_mul(r, &t, &z11); +} + +static void mladder(fe25519 *xr, fe25519 *zr, const uint8_t s[32]) { + fe25519 work[5]; + + work[0] = *xr; + fe25519_setint(work + 1, 1); + fe25519_setint(work + 2, 0); + work[3] = *xr; + fe25519_setint(work + 4, 1); + + int i, j; + uint8_t prevbit = 0; + + j = 6; + for (i = 31; i >= 0; i--) { + while (j >= 0) { + const uint8_t bit = 1 & (s[i] >> j); + const uint64_t swap = bit ^ prevbit; + prevbit = bit; + x25519_x86_64_work_cswap(work + 1, swap); + x25519_x86_64_ladderstep(work); + j -= 1; + } + j = 7; + } + + *xr = work[1]; + *zr = work[2]; +} + +void x25519_x86_64(uint8_t out[32], const uint8_t scalar[32], + const uint8_t point[32]) { + uint8_t e[32]; + memcpy(e, scalar, sizeof(e)); + + e[0] &= 248; + e[31] &= 127; + e[31] |= 64; + + fe25519 t; + fe25519 z; + fe25519_unpack(&t, point); + mladder(&t, &z, e); + fe25519_invert(&z, &z); + x25519_x86_64_mul(&t, &t, &z); + fe25519_pack(out, &t); +} + +#endif /* BORINGSSL_X25519_X86_64 */ diff --git a/external/boringssl/crypto/curve25519/x25519_test.cc b/external/boringssl/crypto/curve25519/x25519_test.cc new file mode 100644 index 0000000000..24dfa650c9 --- /dev/null +++ b/external/boringssl/crypto/curve25519/x25519_test.cc @@ -0,0 +1,126 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include +#include + +#include + + +static bool TestX25519() { + /* Taken from https://tools.ietf.org/html/rfc7748#section-5.2 */ + static const uint8_t kScalar1[32] = { + 0xa5, 0x46, 0xe3, 0x6b, 0xf0, 0x52, 0x7c, 0x9d, 0x3b, 0x16, 0x15, + 0x4b, 0x82, 0x46, 0x5e, 0xdd, 0x62, 0x14, 0x4c, 0x0a, 0xc1, 0xfc, + 0x5a, 0x18, 0x50, 0x6a, 0x22, 0x44, 0xba, 0x44, 0x9a, 0xc4, + }; + static const uint8_t kPoint1[32] = { + 0xe6, 0xdb, 0x68, 0x67, 0x58, 0x30, 0x30, 0xdb, 0x35, 0x94, 0xc1, + 0xa4, 0x24, 0xb1, 0x5f, 0x7c, 0x72, 0x66, 0x24, 0xec, 0x26, 0xb3, + 0x35, 0x3b, 0x10, 0xa9, 0x03, 0xa6, 0xd0, 0xab, 0x1c, 0x4c, + }; + + uint8_t out[32]; + X25519(out, kScalar1, kPoint1); + + static const uint8_t kExpected1[32] = { + 0xc3, 0xda, 0x55, 0x37, 0x9d, 0xe9, 0xc6, 0x90, 0x8e, 0x94, 0xea, + 0x4d, 0xf2, 0x8d, 0x08, 0x4f, 0x32, 0xec, 0xcf, 0x03, 0x49, 0x1c, + 0x71, 0xf7, 0x54, 0xb4, 0x07, 0x55, 0x77, 0xa2, 0x85, 0x52, + }; + if (memcmp(kExpected1, out, sizeof(out)) != 0) { + fprintf(stderr, "X25519 test one failed.\n"); + return false; + } + + static const uint8_t kScalar2[32] = { + 0x4b, 0x66, 0xe9, 0xd4, 0xd1, 0xb4, 0x67, 0x3c, 0x5a, 0xd2, 0x26, + 0x91, 0x95, 0x7d, 0x6a, 0xf5, 0xc1, 0x1b, 0x64, 0x21, 0xe0, 0xea, + 0x01, 0xd4, 0x2c, 0xa4, 0x16, 0x9e, 0x79, 0x18, 0xba, 0x0d, + }; + static const uint8_t kPoint2[32] = { + 0xe5, 0x21, 0x0f, 0x12, 0x78, 0x68, 0x11, 0xd3, 0xf4, 0xb7, 0x95, + 0x9d, 0x05, 0x38, 0xae, 0x2c, 0x31, 0xdb, 0xe7, 0x10, 0x6f, 0xc0, + 0x3c, 0x3e, 0xfc, 0x4c, 0xd5, 0x49, 0xc7, 0x15, 0xa4, 0x93, + }; + + X25519(out, kScalar2, kPoint2); + + static const uint8_t kExpected2[32] = { + 0x95, 0xcb, 0xde, 0x94, 0x76, 0xe8, 0x90, 0x7d, 0x7a, 0xad, 0xe4, + 0x5c, 0xb4, 0xb8, 0x73, 0xf8, 0x8b, 0x59, 0x5a, 0x68, 0x79, 0x9f, + 0xa1, 0x52, 0xe6, 0xf8, 0xf7, 0x64, 0x7a, 0xac, 0x79, 0x57, + }; + if (memcmp(kExpected2, out, sizeof(out)) != 0) { + fprintf(stderr, "X25519 test two failed.\n"); + return false; + } + + return true; +} + +static bool TestX25519SmallOrder() { + static const uint8_t kSmallOrderPoint[32] = { + 0xe0, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae, 0x16, 0x56, 0xe3, + 0xfa, 0xf1, 0x9f, 0xc4, 0x6a, 0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32, + 0xb1, 0xfd, 0x86, 0x62, 0x05, 0x16, 0x5f, 0x49, 0xb8, + }; + + uint8_t out[32], private_key[32]; + memset(private_key, 0x11, sizeof(private_key)); + + if (X25519(out, private_key, kSmallOrderPoint)) { + fprintf(stderr, "X25519 returned success with a small-order input.\n"); + return false; + } + + return true; +} + +static bool TestX25519Iterated() { + /* Taken from https://tools.ietf.org/html/rfc7748#section-5.2 */ + uint8_t scalar[32] = {9}, point[32] = {9}, out[32]; + + unsigned i; + for (i = 0; i < 1000; i++) { + X25519(out, scalar, point); + memcpy(point, scalar, sizeof(point)); + memcpy(scalar, out, sizeof(scalar)); + } + + static const uint8_t kExpected[32] = { + 0x68, 0x4c, 0xf5, 0x9b, 0xa8, 0x33, 0x09, 0x55, 0x28, 0x00, 0xef, + 0x56, 0x6f, 0x2f, 0x4d, 0x3c, 0x1c, 0x38, 0x87, 0xc4, 0x93, 0x60, + 0xe3, 0x87, 0x5f, 0x2e, 0xb9, 0x4d, 0x99, 0x53, 0x2c, 0x51, + }; + + if (memcmp(kExpected, scalar, sizeof(kExpected)) != 0) { + fprintf(stderr, "Iterated X25519 test failed\n"); + return false; + } + + return true; +} + +int main(int argc, char **argv) { + if (!TestX25519() || + !TestX25519Iterated() || + !TestX25519SmallOrder()) { + return 1; + } + + printf("PASS\n"); + return 0; +} diff --git a/external/boringssl/crypto/des/CMakeLists.txt b/external/boringssl/crypto/des/CMakeLists.txt new file mode 100644 index 0000000000..f61fa14a66 --- /dev/null +++ b/external/boringssl/crypto/des/CMakeLists.txt @@ -0,0 +1,9 @@ +include_directories(../../include) + +add_library( + des + + OBJECT + + des.c +) diff --git a/external/boringssl/crypto/des/des.c b/external/boringssl/crypto/des/des.c new file mode 100644 index 0000000000..1d27ebe4b2 --- /dev/null +++ b/external/boringssl/crypto/des/des.c @@ -0,0 +1,771 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include "internal.h" + + +static const uint32_t des_skb[8][64] = { + {/* for C bits (numbered as per FIPS 46) 1 2 3 4 5 6 */ + 0x00000000L, 0x00000010L, 0x20000000L, 0x20000010L, 0x00010000L, + 0x00010010L, 0x20010000L, 0x20010010L, 0x00000800L, 0x00000810L, + 0x20000800L, 0x20000810L, 0x00010800L, 0x00010810L, 0x20010800L, + 0x20010810L, 0x00000020L, 0x00000030L, 0x20000020L, 0x20000030L, + 0x00010020L, 0x00010030L, 0x20010020L, 0x20010030L, 0x00000820L, + 0x00000830L, 0x20000820L, 0x20000830L, 0x00010820L, 0x00010830L, + 0x20010820L, 0x20010830L, 0x00080000L, 0x00080010L, 0x20080000L, + 0x20080010L, 0x00090000L, 0x00090010L, 0x20090000L, 0x20090010L, + 0x00080800L, 0x00080810L, 0x20080800L, 0x20080810L, 0x00090800L, + 0x00090810L, 0x20090800L, 0x20090810L, 0x00080020L, 0x00080030L, + 0x20080020L, 0x20080030L, 0x00090020L, 0x00090030L, 0x20090020L, + 0x20090030L, 0x00080820L, 0x00080830L, 0x20080820L, 0x20080830L, + 0x00090820L, 0x00090830L, 0x20090820L, 0x20090830L, }, + {/* for C bits (numbered as per FIPS 46) 7 8 10 11 12 13 */ + 0x00000000L, 0x02000000L, 0x00002000L, 0x02002000L, 0x00200000L, + 0x02200000L, 0x00202000L, 0x02202000L, 0x00000004L, 0x02000004L, + 0x00002004L, 0x02002004L, 0x00200004L, 0x02200004L, 0x00202004L, + 0x02202004L, 0x00000400L, 0x02000400L, 0x00002400L, 0x02002400L, + 0x00200400L, 0x02200400L, 0x00202400L, 0x02202400L, 0x00000404L, + 0x02000404L, 0x00002404L, 0x02002404L, 0x00200404L, 0x02200404L, + 0x00202404L, 0x02202404L, 0x10000000L, 0x12000000L, 0x10002000L, + 0x12002000L, 0x10200000L, 0x12200000L, 0x10202000L, 0x12202000L, + 0x10000004L, 0x12000004L, 0x10002004L, 0x12002004L, 0x10200004L, + 0x12200004L, 0x10202004L, 0x12202004L, 0x10000400L, 0x12000400L, + 0x10002400L, 0x12002400L, 0x10200400L, 0x12200400L, 0x10202400L, + 0x12202400L, 0x10000404L, 0x12000404L, 0x10002404L, 0x12002404L, + 0x10200404L, 0x12200404L, 0x10202404L, 0x12202404L, }, + {/* for C bits (numbered as per FIPS 46) 14 15 16 17 19 20 */ + 0x00000000L, 0x00000001L, 0x00040000L, 0x00040001L, 0x01000000L, + 0x01000001L, 0x01040000L, 0x01040001L, 0x00000002L, 0x00000003L, + 0x00040002L, 0x00040003L, 0x01000002L, 0x01000003L, 0x01040002L, + 0x01040003L, 0x00000200L, 0x00000201L, 0x00040200L, 0x00040201L, + 0x01000200L, 0x01000201L, 0x01040200L, 0x01040201L, 0x00000202L, + 0x00000203L, 0x00040202L, 0x00040203L, 0x01000202L, 0x01000203L, + 0x01040202L, 0x01040203L, 0x08000000L, 0x08000001L, 0x08040000L, + 0x08040001L, 0x09000000L, 0x09000001L, 0x09040000L, 0x09040001L, + 0x08000002L, 0x08000003L, 0x08040002L, 0x08040003L, 0x09000002L, + 0x09000003L, 0x09040002L, 0x09040003L, 0x08000200L, 0x08000201L, + 0x08040200L, 0x08040201L, 0x09000200L, 0x09000201L, 0x09040200L, + 0x09040201L, 0x08000202L, 0x08000203L, 0x08040202L, 0x08040203L, + 0x09000202L, 0x09000203L, 0x09040202L, 0x09040203L, }, + {/* for C bits (numbered as per FIPS 46) 21 23 24 26 27 28 */ + 0x00000000L, 0x00100000L, 0x00000100L, 0x00100100L, 0x00000008L, + 0x00100008L, 0x00000108L, 0x00100108L, 0x00001000L, 0x00101000L, + 0x00001100L, 0x00101100L, 0x00001008L, 0x00101008L, 0x00001108L, + 0x00101108L, 0x04000000L, 0x04100000L, 0x04000100L, 0x04100100L, + 0x04000008L, 0x04100008L, 0x04000108L, 0x04100108L, 0x04001000L, + 0x04101000L, 0x04001100L, 0x04101100L, 0x04001008L, 0x04101008L, + 0x04001108L, 0x04101108L, 0x00020000L, 0x00120000L, 0x00020100L, + 0x00120100L, 0x00020008L, 0x00120008L, 0x00020108L, 0x00120108L, + 0x00021000L, 0x00121000L, 0x00021100L, 0x00121100L, 0x00021008L, + 0x00121008L, 0x00021108L, 0x00121108L, 0x04020000L, 0x04120000L, + 0x04020100L, 0x04120100L, 0x04020008L, 0x04120008L, 0x04020108L, + 0x04120108L, 0x04021000L, 0x04121000L, 0x04021100L, 0x04121100L, + 0x04021008L, 0x04121008L, 0x04021108L, 0x04121108L, }, + {/* for D bits (numbered as per FIPS 46) 1 2 3 4 5 6 */ + 0x00000000L, 0x10000000L, 0x00010000L, 0x10010000L, 0x00000004L, + 0x10000004L, 0x00010004L, 0x10010004L, 0x20000000L, 0x30000000L, + 0x20010000L, 0x30010000L, 0x20000004L, 0x30000004L, 0x20010004L, + 0x30010004L, 0x00100000L, 0x10100000L, 0x00110000L, 0x10110000L, + 0x00100004L, 0x10100004L, 0x00110004L, 0x10110004L, 0x20100000L, + 0x30100000L, 0x20110000L, 0x30110000L, 0x20100004L, 0x30100004L, + 0x20110004L, 0x30110004L, 0x00001000L, 0x10001000L, 0x00011000L, + 0x10011000L, 0x00001004L, 0x10001004L, 0x00011004L, 0x10011004L, + 0x20001000L, 0x30001000L, 0x20011000L, 0x30011000L, 0x20001004L, + 0x30001004L, 0x20011004L, 0x30011004L, 0x00101000L, 0x10101000L, + 0x00111000L, 0x10111000L, 0x00101004L, 0x10101004L, 0x00111004L, + 0x10111004L, 0x20101000L, 0x30101000L, 0x20111000L, 0x30111000L, + 0x20101004L, 0x30101004L, 0x20111004L, 0x30111004L, }, + {/* for D bits (numbered as per FIPS 46) 8 9 11 12 13 14 */ + 0x00000000L, 0x08000000L, 0x00000008L, 0x08000008L, 0x00000400L, + 0x08000400L, 0x00000408L, 0x08000408L, 0x00020000L, 0x08020000L, + 0x00020008L, 0x08020008L, 0x00020400L, 0x08020400L, 0x00020408L, + 0x08020408L, 0x00000001L, 0x08000001L, 0x00000009L, 0x08000009L, + 0x00000401L, 0x08000401L, 0x00000409L, 0x08000409L, 0x00020001L, + 0x08020001L, 0x00020009L, 0x08020009L, 0x00020401L, 0x08020401L, + 0x00020409L, 0x08020409L, 0x02000000L, 0x0A000000L, 0x02000008L, + 0x0A000008L, 0x02000400L, 0x0A000400L, 0x02000408L, 0x0A000408L, + 0x02020000L, 0x0A020000L, 0x02020008L, 0x0A020008L, 0x02020400L, + 0x0A020400L, 0x02020408L, 0x0A020408L, 0x02000001L, 0x0A000001L, + 0x02000009L, 0x0A000009L, 0x02000401L, 0x0A000401L, 0x02000409L, + 0x0A000409L, 0x02020001L, 0x0A020001L, 0x02020009L, 0x0A020009L, + 0x02020401L, 0x0A020401L, 0x02020409L, 0x0A020409L, }, + {/* for D bits (numbered as per FIPS 46) 16 17 18 19 20 21 */ + 0x00000000L, 0x00000100L, 0x00080000L, 0x00080100L, 0x01000000L, + 0x01000100L, 0x01080000L, 0x01080100L, 0x00000010L, 0x00000110L, + 0x00080010L, 0x00080110L, 0x01000010L, 0x01000110L, 0x01080010L, + 0x01080110L, 0x00200000L, 0x00200100L, 0x00280000L, 0x00280100L, + 0x01200000L, 0x01200100L, 0x01280000L, 0x01280100L, 0x00200010L, + 0x00200110L, 0x00280010L, 0x00280110L, 0x01200010L, 0x01200110L, + 0x01280010L, 0x01280110L, 0x00000200L, 0x00000300L, 0x00080200L, + 0x00080300L, 0x01000200L, 0x01000300L, 0x01080200L, 0x01080300L, + 0x00000210L, 0x00000310L, 0x00080210L, 0x00080310L, 0x01000210L, + 0x01000310L, 0x01080210L, 0x01080310L, 0x00200200L, 0x00200300L, + 0x00280200L, 0x00280300L, 0x01200200L, 0x01200300L, 0x01280200L, + 0x01280300L, 0x00200210L, 0x00200310L, 0x00280210L, 0x00280310L, + 0x01200210L, 0x01200310L, 0x01280210L, 0x01280310L, }, + {/* for D bits (numbered as per FIPS 46) 22 23 24 25 27 28 */ + 0x00000000L, 0x04000000L, 0x00040000L, 0x04040000L, 0x00000002L, + 0x04000002L, 0x00040002L, 0x04040002L, 0x00002000L, 0x04002000L, + 0x00042000L, 0x04042000L, 0x00002002L, 0x04002002L, 0x00042002L, + 0x04042002L, 0x00000020L, 0x04000020L, 0x00040020L, 0x04040020L, + 0x00000022L, 0x04000022L, 0x00040022L, 0x04040022L, 0x00002020L, + 0x04002020L, 0x00042020L, 0x04042020L, 0x00002022L, 0x04002022L, + 0x00042022L, 0x04042022L, 0x00000800L, 0x04000800L, 0x00040800L, + 0x04040800L, 0x00000802L, 0x04000802L, 0x00040802L, 0x04040802L, + 0x00002800L, 0x04002800L, 0x00042800L, 0x04042800L, 0x00002802L, + 0x04002802L, 0x00042802L, 0x04042802L, 0x00000820L, 0x04000820L, + 0x00040820L, 0x04040820L, 0x00000822L, 0x04000822L, 0x00040822L, + 0x04040822L, 0x00002820L, 0x04002820L, 0x00042820L, 0x04042820L, + 0x00002822L, 0x04002822L, 0x00042822L, 0x04042822L, }}; + +static const uint32_t DES_SPtrans[8][64] = { + {/* nibble 0 */ + 0x02080800L, 0x00080000L, 0x02000002L, 0x02080802L, 0x02000000L, + 0x00080802L, 0x00080002L, 0x02000002L, 0x00080802L, 0x02080800L, + 0x02080000L, 0x00000802L, 0x02000802L, 0x02000000L, 0x00000000L, + 0x00080002L, 0x00080000L, 0x00000002L, 0x02000800L, 0x00080800L, + 0x02080802L, 0x02080000L, 0x00000802L, 0x02000800L, 0x00000002L, + 0x00000800L, 0x00080800L, 0x02080002L, 0x00000800L, 0x02000802L, + 0x02080002L, 0x00000000L, 0x00000000L, 0x02080802L, 0x02000800L, + 0x00080002L, 0x02080800L, 0x00080000L, 0x00000802L, 0x02000800L, + 0x02080002L, 0x00000800L, 0x00080800L, 0x02000002L, 0x00080802L, + 0x00000002L, 0x02000002L, 0x02080000L, 0x02080802L, 0x00080800L, + 0x02080000L, 0x02000802L, 0x02000000L, 0x00000802L, 0x00080002L, + 0x00000000L, 0x00080000L, 0x02000000L, 0x02000802L, 0x02080800L, + 0x00000002L, 0x02080002L, 0x00000800L, 0x00080802L, }, + {/* nibble 1 */ + 0x40108010L, 0x00000000L, 0x00108000L, 0x40100000L, 0x40000010L, + 0x00008010L, 0x40008000L, 0x00108000L, 0x00008000L, 0x40100010L, + 0x00000010L, 0x40008000L, 0x00100010L, 0x40108000L, 0x40100000L, + 0x00000010L, 0x00100000L, 0x40008010L, 0x40100010L, 0x00008000L, + 0x00108010L, 0x40000000L, 0x00000000L, 0x00100010L, 0x40008010L, + 0x00108010L, 0x40108000L, 0x40000010L, 0x40000000L, 0x00100000L, + 0x00008010L, 0x40108010L, 0x00100010L, 0x40108000L, 0x40008000L, + 0x00108010L, 0x40108010L, 0x00100010L, 0x40000010L, 0x00000000L, + 0x40000000L, 0x00008010L, 0x00100000L, 0x40100010L, 0x00008000L, + 0x40000000L, 0x00108010L, 0x40008010L, 0x40108000L, 0x00008000L, + 0x00000000L, 0x40000010L, 0x00000010L, 0x40108010L, 0x00108000L, + 0x40100000L, 0x40100010L, 0x00100000L, 0x00008010L, 0x40008000L, + 0x40008010L, 0x00000010L, 0x40100000L, 0x00108000L, }, + {/* nibble 2 */ + 0x04000001L, 0x04040100L, 0x00000100L, 0x04000101L, 0x00040001L, + 0x04000000L, 0x04000101L, 0x00040100L, 0x04000100L, 0x00040000L, + 0x04040000L, 0x00000001L, 0x04040101L, 0x00000101L, 0x00000001L, + 0x04040001L, 0x00000000L, 0x00040001L, 0x04040100L, 0x00000100L, + 0x00000101L, 0x04040101L, 0x00040000L, 0x04000001L, 0x04040001L, + 0x04000100L, 0x00040101L, 0x04040000L, 0x00040100L, 0x00000000L, + 0x04000000L, 0x00040101L, 0x04040100L, 0x00000100L, 0x00000001L, + 0x00040000L, 0x00000101L, 0x00040001L, 0x04040000L, 0x04000101L, + 0x00000000L, 0x04040100L, 0x00040100L, 0x04040001L, 0x00040001L, + 0x04000000L, 0x04040101L, 0x00000001L, 0x00040101L, 0x04000001L, + 0x04000000L, 0x04040101L, 0x00040000L, 0x04000100L, 0x04000101L, + 0x00040100L, 0x04000100L, 0x00000000L, 0x04040001L, 0x00000101L, + 0x04000001L, 0x00040101L, 0x00000100L, 0x04040000L, }, + {/* nibble 3 */ + 0x00401008L, 0x10001000L, 0x00000008L, 0x10401008L, 0x00000000L, + 0x10400000L, 0x10001008L, 0x00400008L, 0x10401000L, 0x10000008L, + 0x10000000L, 0x00001008L, 0x10000008L, 0x00401008L, 0x00400000L, + 0x10000000L, 0x10400008L, 0x00401000L, 0x00001000L, 0x00000008L, + 0x00401000L, 0x10001008L, 0x10400000L, 0x00001000L, 0x00001008L, + 0x00000000L, 0x00400008L, 0x10401000L, 0x10001000L, 0x10400008L, + 0x10401008L, 0x00400000L, 0x10400008L, 0x00001008L, 0x00400000L, + 0x10000008L, 0x00401000L, 0x10001000L, 0x00000008L, 0x10400000L, + 0x10001008L, 0x00000000L, 0x00001000L, 0x00400008L, 0x00000000L, + 0x10400008L, 0x10401000L, 0x00001000L, 0x10000000L, 0x10401008L, + 0x00401008L, 0x00400000L, 0x10401008L, 0x00000008L, 0x10001000L, + 0x00401008L, 0x00400008L, 0x00401000L, 0x10400000L, 0x10001008L, + 0x00001008L, 0x10000000L, 0x10000008L, 0x10401000L, }, + {/* nibble 4 */ + 0x08000000L, 0x00010000L, 0x00000400L, 0x08010420L, 0x08010020L, + 0x08000400L, 0x00010420L, 0x08010000L, 0x00010000L, 0x00000020L, + 0x08000020L, 0x00010400L, 0x08000420L, 0x08010020L, 0x08010400L, + 0x00000000L, 0x00010400L, 0x08000000L, 0x00010020L, 0x00000420L, + 0x08000400L, 0x00010420L, 0x00000000L, 0x08000020L, 0x00000020L, + 0x08000420L, 0x08010420L, 0x00010020L, 0x08010000L, 0x00000400L, + 0x00000420L, 0x08010400L, 0x08010400L, 0x08000420L, 0x00010020L, + 0x08010000L, 0x00010000L, 0x00000020L, 0x08000020L, 0x08000400L, + 0x08000000L, 0x00010400L, 0x08010420L, 0x00000000L, 0x00010420L, + 0x08000000L, 0x00000400L, 0x00010020L, 0x08000420L, 0x00000400L, + 0x00000000L, 0x08010420L, 0x08010020L, 0x08010400L, 0x00000420L, + 0x00010000L, 0x00010400L, 0x08010020L, 0x08000400L, 0x00000420L, + 0x00000020L, 0x00010420L, 0x08010000L, 0x08000020L, }, + {/* nibble 5 */ + 0x80000040L, 0x00200040L, 0x00000000L, 0x80202000L, 0x00200040L, + 0x00002000L, 0x80002040L, 0x00200000L, 0x00002040L, 0x80202040L, + 0x00202000L, 0x80000000L, 0x80002000L, 0x80000040L, 0x80200000L, + 0x00202040L, 0x00200000L, 0x80002040L, 0x80200040L, 0x00000000L, + 0x00002000L, 0x00000040L, 0x80202000L, 0x80200040L, 0x80202040L, + 0x80200000L, 0x80000000L, 0x00002040L, 0x00000040L, 0x00202000L, + 0x00202040L, 0x80002000L, 0x00002040L, 0x80000000L, 0x80002000L, + 0x00202040L, 0x80202000L, 0x00200040L, 0x00000000L, 0x80002000L, + 0x80000000L, 0x00002000L, 0x80200040L, 0x00200000L, 0x00200040L, + 0x80202040L, 0x00202000L, 0x00000040L, 0x80202040L, 0x00202000L, + 0x00200000L, 0x80002040L, 0x80000040L, 0x80200000L, 0x00202040L, + 0x00000000L, 0x00002000L, 0x80000040L, 0x80002040L, 0x80202000L, + 0x80200000L, 0x00002040L, 0x00000040L, 0x80200040L, }, + {/* nibble 6 */ + 0x00004000L, 0x00000200L, 0x01000200L, 0x01000004L, 0x01004204L, + 0x00004004L, 0x00004200L, 0x00000000L, 0x01000000L, 0x01000204L, + 0x00000204L, 0x01004000L, 0x00000004L, 0x01004200L, 0x01004000L, + 0x00000204L, 0x01000204L, 0x00004000L, 0x00004004L, 0x01004204L, + 0x00000000L, 0x01000200L, 0x01000004L, 0x00004200L, 0x01004004L, + 0x00004204L, 0x01004200L, 0x00000004L, 0x00004204L, 0x01004004L, + 0x00000200L, 0x01000000L, 0x00004204L, 0x01004000L, 0x01004004L, + 0x00000204L, 0x00004000L, 0x00000200L, 0x01000000L, 0x01004004L, + 0x01000204L, 0x00004204L, 0x00004200L, 0x00000000L, 0x00000200L, + 0x01000004L, 0x00000004L, 0x01000200L, 0x00000000L, 0x01000204L, + 0x01000200L, 0x00004200L, 0x00000204L, 0x00004000L, 0x01004204L, + 0x01000000L, 0x01004200L, 0x00000004L, 0x00004004L, 0x01004204L, + 0x01000004L, 0x01004200L, 0x01004000L, 0x00004004L, }, + {/* nibble 7 */ + 0x20800080L, 0x20820000L, 0x00020080L, 0x00000000L, 0x20020000L, + 0x00800080L, 0x20800000L, 0x20820080L, 0x00000080L, 0x20000000L, + 0x00820000L, 0x00020080L, 0x00820080L, 0x20020080L, 0x20000080L, + 0x20800000L, 0x00020000L, 0x00820080L, 0x00800080L, 0x20020000L, + 0x20820080L, 0x20000080L, 0x00000000L, 0x00820000L, 0x20000000L, + 0x00800000L, 0x20020080L, 0x20800080L, 0x00800000L, 0x00020000L, + 0x20820000L, 0x00000080L, 0x00800000L, 0x00020000L, 0x20000080L, + 0x20820080L, 0x00020080L, 0x20000000L, 0x00000000L, 0x00820000L, + 0x20800080L, 0x20020080L, 0x20020000L, 0x00800080L, 0x20820000L, + 0x00000080L, 0x00800080L, 0x20020000L, 0x20820080L, 0x00800000L, + 0x20800000L, 0x20000080L, 0x00820000L, 0x00020080L, 0x20020080L, + 0x20800000L, 0x00000080L, 0x20820000L, 0x00820080L, 0x00000000L, + 0x20000000L, 0x20800080L, 0x00020000L, 0x00820080L, }}; + +#define HPERM_OP(a, t, n, m) \ + ((t) = ((((a) << (16 - (n))) ^ (a)) & (m)), \ + (a) = (a) ^ (t) ^ (t >> (16 - (n)))) + +void DES_set_key(const DES_cblock *key, DES_key_schedule *schedule) { + static const int shifts2[16] = {0, 0, 1, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 1, 0}; + uint32_t c, d, t, s, t2; + const uint8_t *in; + int i; + + in = key->bytes; + + c2l(in, c); + c2l(in, d); + + /* do PC1 in 47 simple operations :-) + * Thanks to John Fletcher (john_fletcher@lccmail.ocf.llnl.gov) + * for the inspiration. :-) */ + PERM_OP(d, c, t, 4, 0x0f0f0f0fL); + HPERM_OP(c, t, -2, 0xcccc0000L); + HPERM_OP(d, t, -2, 0xcccc0000L); + PERM_OP(d, c, t, 1, 0x55555555L); + PERM_OP(c, d, t, 8, 0x00ff00ffL); + PERM_OP(d, c, t, 1, 0x55555555L); + d = (((d & 0x000000ffL) << 16L) | (d & 0x0000ff00L) | + ((d & 0x00ff0000L) >> 16L) | ((c & 0xf0000000L) >> 4L)); + c &= 0x0fffffffL; + + for (i = 0; i < ITERATIONS; i++) { + if (shifts2[i]) { + c = ((c >> 2L) | (c << 26L)); + d = ((d >> 2L) | (d << 26L)); + } else { + c = ((c >> 1L) | (c << 27L)); + d = ((d >> 1L) | (d << 27L)); + } + c &= 0x0fffffffL; + d &= 0x0fffffffL; + /* could be a few less shifts but I am to lazy at this + * point in time to investigate */ + s = des_skb[0][(c) & 0x3f] | + des_skb[1][((c >> 6L) & 0x03) | ((c >> 7L) & 0x3c)] | + des_skb[2][((c >> 13L) & 0x0f) | ((c >> 14L) & 0x30)] | + des_skb[3][((c >> 20L) & 0x01) | ((c >> 21L) & 0x06) | + ((c >> 22L) & 0x38)]; + t = des_skb[4][(d) & 0x3f] | + des_skb[5][((d >> 7L) & 0x03) | ((d >> 8L) & 0x3c)] | + des_skb[6][(d >> 15L) & 0x3f] | + des_skb[7][((d >> 21L) & 0x0f) | ((d >> 22L) & 0x30)]; + + /* table contained 0213 4657 */ + t2 = ((t << 16L) | (s & 0x0000ffffL)) & 0xffffffffL; + schedule->subkeys[i][0] = ROTATE(t2, 30) & 0xffffffffL; + + t2 = ((s >> 16L) | (t & 0xffff0000L)); + schedule->subkeys[i][1] = ROTATE(t2, 26) & 0xffffffffL; + } +} + +static const uint8_t kOddParity[256] = { + 1, 1, 2, 2, 4, 4, 7, 7, 8, 8, 11, 11, 13, 13, 14, + 14, 16, 16, 19, 19, 21, 21, 22, 22, 25, 25, 26, 26, 28, 28, + 31, 31, 32, 32, 35, 35, 37, 37, 38, 38, 41, 41, 42, 42, 44, + 44, 47, 47, 49, 49, 50, 50, 52, 52, 55, 55, 56, 56, 59, 59, + 61, 61, 62, 62, 64, 64, 67, 67, 69, 69, 70, 70, 73, 73, 74, + 74, 76, 76, 79, 79, 81, 81, 82, 82, 84, 84, 87, 87, 88, 88, + 91, 91, 93, 93, 94, 94, 97, 97, 98, 98, 100, 100, 103, 103, 104, + 104, 107, 107, 109, 109, 110, 110, 112, 112, 115, 115, 117, 117, 118, 118, + 121, 121, 122, 122, 124, 124, 127, 127, 128, 128, 131, 131, 133, 133, 134, + 134, 137, 137, 138, 138, 140, 140, 143, 143, 145, 145, 146, 146, 148, 148, + 151, 151, 152, 152, 155, 155, 157, 157, 158, 158, 161, 161, 162, 162, 164, + 164, 167, 167, 168, 168, 171, 171, 173, 173, 174, 174, 176, 176, 179, 179, + 181, 181, 182, 182, 185, 185, 186, 186, 188, 188, 191, 191, 193, 193, 194, + 194, 196, 196, 199, 199, 200, 200, 203, 203, 205, 205, 206, 206, 208, 208, + 211, 211, 213, 213, 214, 214, 217, 217, 218, 218, 220, 220, 223, 223, 224, + 224, 227, 227, 229, 229, 230, 230, 233, 233, 234, 234, 236, 236, 239, 239, + 241, 241, 242, 242, 244, 244, 247, 247, 248, 248, 251, 251, 253, 253, 254, + 254 +}; + +void DES_set_odd_parity(DES_cblock *key) { + unsigned i; + + for (i = 0; i < DES_KEY_SZ; i++) { + key->bytes[i] = kOddParity[key->bytes[i]]; + } +} + +static void DES_encrypt1(uint32_t *data, const DES_key_schedule *ks, int enc) { + uint32_t l, r, t, u; + + r = data[0]; + l = data[1]; + + IP(r, l); + /* Things have been modified so that the initial rotate is done outside + * the loop. This required the DES_SPtrans values in sp.h to be + * rotated 1 bit to the right. One perl script later and things have a + * 5% speed up on a sparc2. Thanks to Richard Outerbridge + * <71755.204@CompuServe.COM> for pointing this out. */ + /* clear the top bits on machines with 8byte longs */ + /* shift left by 2 */ + r = ROTATE(r, 29) & 0xffffffffL; + l = ROTATE(l, 29) & 0xffffffffL; + + /* I don't know if it is worth the effort of loop unrolling the + * inner loop */ + if (enc) { + D_ENCRYPT(ks, l, r, 0); + D_ENCRYPT(ks, r, l, 1); + D_ENCRYPT(ks, l, r, 2); + D_ENCRYPT(ks, r, l, 3); + D_ENCRYPT(ks, l, r, 4); + D_ENCRYPT(ks, r, l, 5); + D_ENCRYPT(ks, l, r, 6); + D_ENCRYPT(ks, r, l, 7); + D_ENCRYPT(ks, l, r, 8); + D_ENCRYPT(ks, r, l, 9); + D_ENCRYPT(ks, l, r, 10); + D_ENCRYPT(ks, r, l, 11); + D_ENCRYPT(ks, l, r, 12); + D_ENCRYPT(ks, r, l, 13); + D_ENCRYPT(ks, l, r, 14); + D_ENCRYPT(ks, r, l, 15); + } else { + D_ENCRYPT(ks, l, r, 15); + D_ENCRYPT(ks, r, l, 14); + D_ENCRYPT(ks, l, r, 13); + D_ENCRYPT(ks, r, l, 12); + D_ENCRYPT(ks, l, r, 11); + D_ENCRYPT(ks, r, l, 10); + D_ENCRYPT(ks, l, r, 9); + D_ENCRYPT(ks, r, l, 8); + D_ENCRYPT(ks, l, r, 7); + D_ENCRYPT(ks, r, l, 6); + D_ENCRYPT(ks, l, r, 5); + D_ENCRYPT(ks, r, l, 4); + D_ENCRYPT(ks, l, r, 3); + D_ENCRYPT(ks, r, l, 2); + D_ENCRYPT(ks, l, r, 1); + D_ENCRYPT(ks, r, l, 0); + } + + /* rotate and clear the top bits on machines with 8byte longs */ + l = ROTATE(l, 3) & 0xffffffffL; + r = ROTATE(r, 3) & 0xffffffffL; + + FP(r, l); + data[0] = l; + data[1] = r; +} + +static void DES_encrypt2(uint32_t *data, const DES_key_schedule *ks, int enc) { + uint32_t l, r, t, u; + + r = data[0]; + l = data[1]; + + /* Things have been modified so that the initial rotate is done outside the + * loop. This required the DES_SPtrans values in sp.h to be rotated 1 bit to + * the right. One perl script later and things have a 5% speed up on a + * sparc2. Thanks to Richard Outerbridge <71755.204@CompuServe.COM> for + * pointing this out. */ + /* clear the top bits on machines with 8byte longs */ + r = ROTATE(r, 29) & 0xffffffffL; + l = ROTATE(l, 29) & 0xffffffffL; + + /* I don't know if it is worth the effort of loop unrolling the + * inner loop */ + if (enc) { + D_ENCRYPT(ks, l, r, 0); + D_ENCRYPT(ks, r, l, 1); + D_ENCRYPT(ks, l, r, 2); + D_ENCRYPT(ks, r, l, 3); + D_ENCRYPT(ks, l, r, 4); + D_ENCRYPT(ks, r, l, 5); + D_ENCRYPT(ks, l, r, 6); + D_ENCRYPT(ks, r, l, 7); + D_ENCRYPT(ks, l, r, 8); + D_ENCRYPT(ks, r, l, 9); + D_ENCRYPT(ks, l, r, 10); + D_ENCRYPT(ks, r, l, 11); + D_ENCRYPT(ks, l, r, 12); + D_ENCRYPT(ks, r, l, 13); + D_ENCRYPT(ks, l, r, 14); + D_ENCRYPT(ks, r, l, 15); + } else { + D_ENCRYPT(ks, l, r, 15); + D_ENCRYPT(ks, r, l, 14); + D_ENCRYPT(ks, l, r, 13); + D_ENCRYPT(ks, r, l, 12); + D_ENCRYPT(ks, l, r, 11); + D_ENCRYPT(ks, r, l, 10); + D_ENCRYPT(ks, l, r, 9); + D_ENCRYPT(ks, r, l, 8); + D_ENCRYPT(ks, l, r, 7); + D_ENCRYPT(ks, r, l, 6); + D_ENCRYPT(ks, l, r, 5); + D_ENCRYPT(ks, r, l, 4); + D_ENCRYPT(ks, l, r, 3); + D_ENCRYPT(ks, r, l, 2); + D_ENCRYPT(ks, l, r, 1); + D_ENCRYPT(ks, r, l, 0); + } + /* rotate and clear the top bits on machines with 8byte longs */ + data[0] = ROTATE(l, 3) & 0xffffffffL; + data[1] = ROTATE(r, 3) & 0xffffffffL; +} + +void DES_encrypt3(uint32_t *data, const DES_key_schedule *ks1, + const DES_key_schedule *ks2, const DES_key_schedule *ks3) { + uint32_t l, r; + + l = data[0]; + r = data[1]; + IP(l, r); + data[0] = l; + data[1] = r; + DES_encrypt2((uint32_t *)data, ks1, DES_ENCRYPT); + DES_encrypt2((uint32_t *)data, ks2, DES_DECRYPT); + DES_encrypt2((uint32_t *)data, ks3, DES_ENCRYPT); + l = data[0]; + r = data[1]; + FP(r, l); + data[0] = l; + data[1] = r; +} + +void DES_decrypt3(uint32_t *data, const DES_key_schedule *ks1, + const DES_key_schedule *ks2, const DES_key_schedule *ks3) { + uint32_t l, r; + + l = data[0]; + r = data[1]; + IP(l, r); + data[0] = l; + data[1] = r; + DES_encrypt2((uint32_t *)data, ks3, DES_DECRYPT); + DES_encrypt2((uint32_t *)data, ks2, DES_ENCRYPT); + DES_encrypt2((uint32_t *)data, ks1, DES_DECRYPT); + l = data[0]; + r = data[1]; + FP(r, l); + data[0] = l; + data[1] = r; +} + +void DES_ecb_encrypt(const DES_cblock *in_block, DES_cblock *out_block, + const DES_key_schedule *schedule, int is_encrypt) { + uint32_t l; + uint32_t ll[2]; + const uint8_t *in = in_block->bytes; + uint8_t *out = out_block->bytes; + + c2l(in, l); + ll[0] = l; + c2l(in, l); + ll[1] = l; + DES_encrypt1(ll, schedule, is_encrypt); + l = ll[0]; + l2c(l, out); + l = ll[1]; + l2c(l, out); + ll[0] = ll[1] = 0; +} + +void DES_ncbc_encrypt(const uint8_t *in, uint8_t *out, size_t len, + const DES_key_schedule *schedule, DES_cblock *ivec, + int enc) { + uint32_t tin0, tin1; + uint32_t tout0, tout1, xor0, xor1; + uint32_t tin[2]; + unsigned char *iv; + + iv = ivec->bytes; + + if (enc) { + c2l(iv, tout0); + c2l(iv, tout1); + for (; len >= 8; len -= 8) { + c2l(in, tin0); + c2l(in, tin1); + tin0 ^= tout0; + tin[0] = tin0; + tin1 ^= tout1; + tin[1] = tin1; + DES_encrypt1((uint32_t *)tin, schedule, DES_ENCRYPT); + tout0 = tin[0]; + l2c(tout0, out); + tout1 = tin[1]; + l2c(tout1, out); + } + if (len != 0) { + c2ln(in, tin0, tin1, len); + tin0 ^= tout0; + tin[0] = tin0; + tin1 ^= tout1; + tin[1] = tin1; + DES_encrypt1((uint32_t *)tin, schedule, DES_ENCRYPT); + tout0 = tin[0]; + l2c(tout0, out); + tout1 = tin[1]; + l2c(tout1, out); + } + iv = ivec->bytes; + l2c(tout0, iv); + l2c(tout1, iv); + } else { + c2l(iv, xor0); + c2l(iv, xor1); + for (; len >= 8; len -= 8) { + c2l(in, tin0); + tin[0] = tin0; + c2l(in, tin1); + tin[1] = tin1; + DES_encrypt1((uint32_t *)tin, schedule, DES_DECRYPT); + tout0 = tin[0] ^ xor0; + tout1 = tin[1] ^ xor1; + l2c(tout0, out); + l2c(tout1, out); + xor0 = tin0; + xor1 = tin1; + } + if (len != 0) { + c2l(in, tin0); + tin[0] = tin0; + c2l(in, tin1); + tin[1] = tin1; + DES_encrypt1((uint32_t *)tin, schedule, DES_DECRYPT); + tout0 = tin[0] ^ xor0; + tout1 = tin[1] ^ xor1; + l2cn(tout0, tout1, out, len); + xor0 = tin0; + xor1 = tin1; + } + iv = ivec->bytes; + l2c(xor0, iv); + l2c(xor1, iv); + } + tin[0] = tin[1] = 0; +} + +void DES_ecb3_encrypt(const DES_cblock *input, DES_cblock *output, + const DES_key_schedule *ks1, const DES_key_schedule *ks2, + const DES_key_schedule *ks3, int enc) { + uint32_t l0, l1; + uint32_t ll[2]; + const uint8_t *in = input->bytes; + uint8_t *out = output->bytes; + + c2l(in, l0); + c2l(in, l1); + ll[0] = l0; + ll[1] = l1; + if (enc) { + DES_encrypt3(ll, ks1, ks2, ks3); + } else { + DES_decrypt3(ll, ks1, ks2, ks3); + } + l0 = ll[0]; + l1 = ll[1]; + l2c(l0, out); + l2c(l1, out); +} + +void DES_ede3_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t len, + const DES_key_schedule *ks1, + const DES_key_schedule *ks2, + const DES_key_schedule *ks3, DES_cblock *ivec, + int enc) { + uint32_t tin0, tin1; + uint32_t tout0, tout1, xor0, xor1; + uint32_t tin[2]; + uint8_t *iv; + + iv = ivec->bytes; + + if (enc) { + c2l(iv, tout0); + c2l(iv, tout1); + for (; len >= 8; len -= 8) { + c2l(in, tin0); + c2l(in, tin1); + tin0 ^= tout0; + tin1 ^= tout1; + + tin[0] = tin0; + tin[1] = tin1; + DES_encrypt3((uint32_t *)tin, ks1, ks2, ks3); + tout0 = tin[0]; + tout1 = tin[1]; + + l2c(tout0, out); + l2c(tout1, out); + } + if (len != 0) { + c2ln(in, tin0, tin1, len); + tin0 ^= tout0; + tin1 ^= tout1; + + tin[0] = tin0; + tin[1] = tin1; + DES_encrypt3((uint32_t *)tin, ks1, ks2, ks3); + tout0 = tin[0]; + tout1 = tin[1]; + + l2c(tout0, out); + l2c(tout1, out); + } + iv = ivec->bytes; + l2c(tout0, iv); + l2c(tout1, iv); + } else { + uint32_t t0, t1; + + c2l(iv, xor0); + c2l(iv, xor1); + for (; len >= 8; len -= 8) { + c2l(in, tin0); + c2l(in, tin1); + + t0 = tin0; + t1 = tin1; + + tin[0] = tin0; + tin[1] = tin1; + DES_decrypt3((uint32_t *)tin, ks1, ks2, ks3); + tout0 = tin[0]; + tout1 = tin[1]; + + tout0 ^= xor0; + tout1 ^= xor1; + l2c(tout0, out); + l2c(tout1, out); + xor0 = t0; + xor1 = t1; + } + if (len != 0) { + c2l(in, tin0); + c2l(in, tin1); + + t0 = tin0; + t1 = tin1; + + tin[0] = tin0; + tin[1] = tin1; + DES_decrypt3((uint32_t *)tin, ks1, ks2, ks3); + tout0 = tin[0]; + tout1 = tin[1]; + + tout0 ^= xor0; + tout1 ^= xor1; + l2cn(tout0, tout1, out, len); + xor0 = t0; + xor1 = t1; + } + + iv = ivec->bytes; + l2c(xor0, iv); + l2c(xor1, iv); + } + + tin[0] = tin[1] = 0; +} + +void DES_ede2_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t len, + const DES_key_schedule *ks1, + const DES_key_schedule *ks2, + DES_cblock *ivec, + int enc) { + DES_ede3_cbc_encrypt(in, out, len, ks1, ks2, ks1, ivec, enc); +} + + +/* Deprecated functions. */ + +void DES_set_key_unchecked(const DES_cblock *key, DES_key_schedule *schedule) { + DES_set_key(key, schedule); +} diff --git a/external/boringssl/crypto/des/internal.h b/external/boringssl/crypto/des/internal.h new file mode 100644 index 0000000000..00b45586ff --- /dev/null +++ b/external/boringssl/crypto/des/internal.h @@ -0,0 +1,212 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_DES_INTERNAL_H +#define OPENSSL_HEADER_DES_INTERNAL_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +#define c2l(c, l) \ + (l = ((uint32_t)(*((c)++))), l |= ((uint32_t)(*((c)++))) << 8L, \ + l |= ((uint32_t)(*((c)++))) << 16L, l |= ((uint32_t)(*((c)++))) << 24L) + +#define l2c(l, c) \ + (*((c)++) = (unsigned char)(((l)) & 0xff), \ + *((c)++) = (unsigned char)(((l) >> 8L) & 0xff), \ + *((c)++) = (unsigned char)(((l) >> 16L) & 0xff), \ + *((c)++) = (unsigned char)(((l) >> 24L) & 0xff)) + +/* NOTE - c is not incremented as per c2l */ +#define c2ln(c, l1, l2, n) \ + { \ + c += n; \ + l1 = l2 = 0; \ + switch (n) { \ + case 8: \ + l2 = ((uint32_t)(*(--(c)))) << 24L; \ + case 7: \ + l2 |= ((uint32_t)(*(--(c)))) << 16L; \ + case 6: \ + l2 |= ((uint32_t)(*(--(c)))) << 8L; \ + case 5: \ + l2 |= ((uint32_t)(*(--(c)))); \ + case 4: \ + l1 = ((uint32_t)(*(--(c)))) << 24L; \ + case 3: \ + l1 |= ((uint32_t)(*(--(c)))) << 16L; \ + case 2: \ + l1 |= ((uint32_t)(*(--(c)))) << 8L; \ + case 1: \ + l1 |= ((uint32_t)(*(--(c)))); \ + } \ + } + +/* NOTE - c is not incremented as per l2c */ +#define l2cn(l1, l2, c, n) \ + { \ + c += n; \ + switch (n) { \ + case 8: \ + *(--(c)) = (unsigned char)(((l2) >> 24L) & 0xff); \ + case 7: \ + *(--(c)) = (unsigned char)(((l2) >> 16L) & 0xff); \ + case 6: \ + *(--(c)) = (unsigned char)(((l2) >> 8L) & 0xff); \ + case 5: \ + *(--(c)) = (unsigned char)(((l2)) & 0xff); \ + case 4: \ + *(--(c)) = (unsigned char)(((l1) >> 24L) & 0xff); \ + case 3: \ + *(--(c)) = (unsigned char)(((l1) >> 16L) & 0xff); \ + case 2: \ + *(--(c)) = (unsigned char)(((l1) >> 8L) & 0xff); \ + case 1: \ + *(--(c)) = (unsigned char)(((l1)) & 0xff); \ + } \ + } + +/* IP and FP + * The problem is more of a geometric problem that random bit fiddling. + 0 1 2 3 4 5 6 7 62 54 46 38 30 22 14 6 + 8 9 10 11 12 13 14 15 60 52 44 36 28 20 12 4 +16 17 18 19 20 21 22 23 58 50 42 34 26 18 10 2 +24 25 26 27 28 29 30 31 to 56 48 40 32 24 16 8 0 + +32 33 34 35 36 37 38 39 63 55 47 39 31 23 15 7 +40 41 42 43 44 45 46 47 61 53 45 37 29 21 13 5 +48 49 50 51 52 53 54 55 59 51 43 35 27 19 11 3 +56 57 58 59 60 61 62 63 57 49 41 33 25 17 9 1 + +The output has been subject to swaps of the form +0 1 -> 3 1 but the odd and even bits have been put into +2 3 2 0 +different words. The main trick is to remember that +t=((l>>size)^r)&(mask); +r^=t; +l^=(t<> (n)) ^ (b)) & (m)), (b) ^= (t), (a) ^= ((t) << (n))) + +#define IP(l, r) \ + { \ + uint32_t tt; \ + PERM_OP(r, l, tt, 4, 0x0f0f0f0fL); \ + PERM_OP(l, r, tt, 16, 0x0000ffffL); \ + PERM_OP(r, l, tt, 2, 0x33333333L); \ + PERM_OP(l, r, tt, 8, 0x00ff00ffL); \ + PERM_OP(r, l, tt, 1, 0x55555555L); \ + } + +#define FP(l, r) \ + { \ + uint32_t tt; \ + PERM_OP(l, r, tt, 1, 0x55555555L); \ + PERM_OP(r, l, tt, 8, 0x00ff00ffL); \ + PERM_OP(l, r, tt, 2, 0x33333333L); \ + PERM_OP(r, l, tt, 16, 0x0000ffffL); \ + PERM_OP(l, r, tt, 4, 0x0f0f0f0fL); \ + } + +#define LOAD_DATA(ks, R, S, u, t, E0, E1) \ + u = R ^ ks->subkeys[S][0]; \ + t = R ^ ks->subkeys[S][1] + +#define D_ENCRYPT(ks, LL, R, S) \ + { \ + LOAD_DATA(ks, R, S, u, t, E0, E1); \ + t = ROTATE(t, 4); \ + LL ^= \ + DES_SPtrans[0][(u >> 2L) & 0x3f] ^ DES_SPtrans[2][(u >> 10L) & 0x3f] ^ \ + DES_SPtrans[4][(u >> 18L) & 0x3f] ^ \ + DES_SPtrans[6][(u >> 26L) & 0x3f] ^ DES_SPtrans[1][(t >> 2L) & 0x3f] ^ \ + DES_SPtrans[3][(t >> 10L) & 0x3f] ^ \ + DES_SPtrans[5][(t >> 18L) & 0x3f] ^ DES_SPtrans[7][(t >> 26L) & 0x3f]; \ + } + +#define ITERATIONS 16 +#define HALF_ITERATIONS 8 + +#define ROTATE(a, n) (((a) >> (n)) + ((a) << (32 - (n)))) + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_DES_INTERNAL_H */ diff --git a/external/boringssl/crypto/dh/CMakeLists.txt b/external/boringssl/crypto/dh/CMakeLists.txt new file mode 100644 index 0000000000..2f3a6deddc --- /dev/null +++ b/external/boringssl/crypto/dh/CMakeLists.txt @@ -0,0 +1,25 @@ +include_directories(../../include) + +add_library( + dh + + OBJECT + + dh.c + params.c + check.c + dh_asn1.c +) + +if(ENABLE_TESTS) +add_executable( + dh_test + + dh_test.cc + + $ +) + +target_link_libraries(dh_test crypto) +add_dependencies(all_tests dh_test) +endif() diff --git a/external/boringssl/crypto/dh/check.c b/external/boringssl/crypto/dh/check.c new file mode 100644 index 0000000000..d27fdf1540 --- /dev/null +++ b/external/boringssl/crypto/dh/check.c @@ -0,0 +1,202 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include "internal.h" + + +int DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *ret) { + *ret = 0; + + BN_CTX *ctx = BN_CTX_new(); + if (ctx == NULL) { + return 0; + } + BN_CTX_start(ctx); + + int ok = 0; + + /* Check |pub_key| is greater than 1. */ + BIGNUM *tmp = BN_CTX_get(ctx); + if (tmp == NULL || + !BN_set_word(tmp, 1)) { + goto err; + } + if (BN_cmp(pub_key, tmp) <= 0) { + *ret |= DH_CHECK_PUBKEY_TOO_SMALL; + } + + /* Check |pub_key| is less than |dh->p| - 1. */ + if (!BN_copy(tmp, dh->p) || + !BN_sub_word(tmp, 1)) { + goto err; + } + if (BN_cmp(pub_key, tmp) >= 0) { + *ret |= DH_CHECK_PUBKEY_TOO_LARGE; + } + + if (dh->q != NULL) { + /* Check |pub_key|^|dh->q| is 1 mod |dh->p|. This is necessary for RFC 5114 + * groups which are not safe primes but pick a generator on a prime-order + * subgroup of size |dh->q|. */ + if (!BN_mod_exp(tmp, pub_key, dh->q, dh->p, ctx)) { + goto err; + } + if (!BN_is_one(tmp)) { + *ret |= DH_CHECK_PUBKEY_INVALID; + } + } + + ok = 1; + +err: + BN_CTX_end(ctx); + BN_CTX_free(ctx); + return ok; +} + + +int DH_check(const DH *dh, int *ret) { + /* Check that p is a safe prime and if g is 2, 3 or 5, check that it is a + * suitable generator where: + * for 2, p mod 24 == 11 + * for 3, p mod 12 == 5 + * for 5, p mod 10 == 3 or 7 + * should hold. + */ + int ok = 0; + BN_CTX *ctx = NULL; + BN_ULONG l; + BIGNUM *t1 = NULL, *t2 = NULL; + + *ret = 0; + ctx = BN_CTX_new(); + if (ctx == NULL) { + goto err; + } + BN_CTX_start(ctx); + t1 = BN_CTX_get(ctx); + if (t1 == NULL) { + goto err; + } + t2 = BN_CTX_get(ctx); + if (t2 == NULL) { + goto err; + } + + if (dh->q) { + if (BN_cmp(dh->g, BN_value_one()) <= 0) { + *ret |= DH_CHECK_NOT_SUITABLE_GENERATOR; + } else if (BN_cmp(dh->g, dh->p) >= 0) { + *ret |= DH_CHECK_NOT_SUITABLE_GENERATOR; + } else { + /* Check g^q == 1 mod p */ + if (!BN_mod_exp(t1, dh->g, dh->q, dh->p, ctx)) { + goto err; + } + if (!BN_is_one(t1)) { + *ret |= DH_CHECK_NOT_SUITABLE_GENERATOR; + } + } + if (!BN_is_prime_ex(dh->q, BN_prime_checks, ctx, NULL)) { + *ret |= DH_CHECK_Q_NOT_PRIME; + } + /* Check p == 1 mod q i.e. q divides p - 1 */ + if (!BN_div(t1, t2, dh->p, dh->q, ctx)) { + goto err; + } + if (!BN_is_one(t2)) { + *ret |= DH_CHECK_INVALID_Q_VALUE; + } + if (dh->j && BN_cmp(dh->j, t1)) { + *ret |= DH_CHECK_INVALID_J_VALUE; + } + } else if (BN_is_word(dh->g, DH_GENERATOR_2)) { + l = BN_mod_word(dh->p, 24); + if (l != 11) { + *ret |= DH_CHECK_NOT_SUITABLE_GENERATOR; + } + } else if (BN_is_word(dh->g, DH_GENERATOR_5)) { + l = BN_mod_word(dh->p, 10); + if (l != 3 && l != 7) { + *ret |= DH_CHECK_NOT_SUITABLE_GENERATOR; + } + } else { + *ret |= DH_CHECK_UNABLE_TO_CHECK_GENERATOR; + } + + if (!BN_is_prime_ex(dh->p, BN_prime_checks, ctx, NULL)) { + *ret |= DH_CHECK_P_NOT_PRIME; + } else if (!dh->q) { + if (!BN_rshift1(t1, dh->p)) { + goto err; + } + if (!BN_is_prime_ex(t1, BN_prime_checks, ctx, NULL)) { + *ret |= DH_CHECK_P_NOT_SAFE_PRIME; + } + } + ok = 1; + +err: + if (ctx != NULL) { + BN_CTX_end(ctx); + BN_CTX_free(ctx); + } + return ok; +} diff --git a/external/boringssl/crypto/dh/dh.c b/external/boringssl/crypto/dh/dh.c new file mode 100644 index 0000000000..94eb3643c6 --- /dev/null +++ b/external/boringssl/crypto/dh/dh.c @@ -0,0 +1,460 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include "internal.h" +#include "../internal.h" + + +#define OPENSSL_DH_MAX_MODULUS_BITS 10000 + +static CRYPTO_EX_DATA_CLASS g_ex_data_class = CRYPTO_EX_DATA_CLASS_INIT; + +DH *DH_new(void) { + DH *dh = OPENSSL_malloc(sizeof(DH)); + if (dh == NULL) { + OPENSSL_PUT_ERROR(DH, ERR_R_MALLOC_FAILURE); + return NULL; + } + + memset(dh, 0, sizeof(DH)); + + CRYPTO_MUTEX_init(&dh->method_mont_p_lock); + + dh->references = 1; + CRYPTO_new_ex_data(&dh->ex_data); + + return dh; +} + +void DH_free(DH *dh) { + if (dh == NULL) { + return; + } + + if (!CRYPTO_refcount_dec_and_test_zero(&dh->references)) { + return; + } + + CRYPTO_free_ex_data(&g_ex_data_class, dh, &dh->ex_data); + + BN_MONT_CTX_free(dh->method_mont_p); + BN_clear_free(dh->p); + BN_clear_free(dh->g); + BN_clear_free(dh->q); + BN_clear_free(dh->j); + OPENSSL_free(dh->seed); + BN_clear_free(dh->counter); + BN_clear_free(dh->pub_key); + BN_clear_free(dh->priv_key); + CRYPTO_MUTEX_cleanup(&dh->method_mont_p_lock); + + OPENSSL_free(dh); +} + +int DH_generate_parameters_ex(DH *dh, int prime_bits, int generator, BN_GENCB *cb) { + /* We generate DH parameters as follows + * find a prime q which is prime_bits/2 bits long. + * p=(2*q)+1 or (p-1)/2 = q + * For this case, g is a generator if + * g^((p-1)/q) mod p != 1 for values of q which are the factors of p-1. + * Since the factors of p-1 are q and 2, we just need to check + * g^2 mod p != 1 and g^q mod p != 1. + * + * Having said all that, + * there is another special case method for the generators 2, 3 and 5. + * for 2, p mod 24 == 11 + * for 3, p mod 12 == 5 <<<<< does not work for safe primes. + * for 5, p mod 10 == 3 or 7 + * + * Thanks to Phil Karn for the pointers about the + * special generators and for answering some of my questions. + * + * I've implemented the second simple method :-). + * Since DH should be using a safe prime (both p and q are prime), + * this generator function can take a very very long time to run. + */ + + /* Actually there is no reason to insist that 'generator' be a generator. + * It's just as OK (and in some sense better) to use a generator of the + * order-q subgroup. + */ + + BIGNUM *t1, *t2; + int g, ok = 0; + BN_CTX *ctx = NULL; + + ctx = BN_CTX_new(); + if (ctx == NULL) { + goto err; + } + BN_CTX_start(ctx); + t1 = BN_CTX_get(ctx); + t2 = BN_CTX_get(ctx); + if (t1 == NULL || t2 == NULL) { + goto err; + } + + /* Make sure |dh| has the necessary elements */ + if (dh->p == NULL) { + dh->p = BN_new(); + if (dh->p == NULL) { + goto err; + } + } + if (dh->g == NULL) { + dh->g = BN_new(); + if (dh->g == NULL) { + goto err; + } + } + + if (generator <= 1) { + OPENSSL_PUT_ERROR(DH, DH_R_BAD_GENERATOR); + goto err; + } + if (generator == DH_GENERATOR_2) { + if (!BN_set_word(t1, 24)) { + goto err; + } + if (!BN_set_word(t2, 11)) { + goto err; + } + g = 2; + } else if (generator == DH_GENERATOR_5) { + if (!BN_set_word(t1, 10)) { + goto err; + } + if (!BN_set_word(t2, 3)) { + goto err; + } + /* BN_set_word(t3,7); just have to miss + * out on these ones :-( */ + g = 5; + } else { + /* in the general case, don't worry if 'generator' is a + * generator or not: since we are using safe primes, + * it will generate either an order-q or an order-2q group, + * which both is OK */ + if (!BN_set_word(t1, 2)) { + goto err; + } + if (!BN_set_word(t2, 1)) { + goto err; + } + g = generator; + } + + if (!BN_generate_prime_ex(dh->p, prime_bits, 1, t1, t2, cb)) { + goto err; + } + if (!BN_GENCB_call(cb, 3, 0)) { + goto err; + } + if (!BN_set_word(dh->g, g)) { + goto err; + } + ok = 1; + +err: + if (!ok) { + OPENSSL_PUT_ERROR(DH, ERR_R_BN_LIB); + } + + if (ctx != NULL) { + BN_CTX_end(ctx); + BN_CTX_free(ctx); + } + return ok; +} + +int DH_generate_key(DH *dh) { + int ok = 0; + int generate_new_key = 0; + unsigned l; + BN_CTX *ctx = NULL; + BIGNUM *pub_key = NULL, *priv_key = NULL; + BIGNUM local_priv; + + if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS) { + OPENSSL_PUT_ERROR(DH, DH_R_MODULUS_TOO_LARGE); + goto err; + } + + ctx = BN_CTX_new(); + if (ctx == NULL) { + goto err; + } + + if (dh->priv_key == NULL) { + priv_key = BN_new(); + if (priv_key == NULL) { + goto err; + } + generate_new_key = 1; + } else { + priv_key = dh->priv_key; + } + + if (dh->pub_key == NULL) { + pub_key = BN_new(); + if (pub_key == NULL) { + goto err; + } + } else { + pub_key = dh->pub_key; + } + + if (!BN_MONT_CTX_set_locked(&dh->method_mont_p, &dh->method_mont_p_lock, + dh->p, ctx)) { + goto err; + } + + if (generate_new_key) { + if (dh->q) { + do { + if (!BN_rand_range(priv_key, dh->q)) { + goto err; + } + } while (BN_is_zero(priv_key) || BN_is_one(priv_key)); + } else { + /* secret exponent length */ + DH_check_standard_parameters(dh); + l = dh->priv_length ? dh->priv_length : BN_num_bits(dh->p) - 1; + if (!BN_rand(priv_key, l, 0, 0)) { + goto err; + } + } + } + + BN_with_flags(&local_priv, priv_key, BN_FLG_CONSTTIME); + if (!BN_mod_exp_mont_consttime(pub_key, dh->g, &local_priv, dh->p, ctx, + dh->method_mont_p)) { + goto err; + } + + dh->pub_key = pub_key; + dh->priv_key = priv_key; + ok = 1; + +err: + if (ok != 1) { + OPENSSL_PUT_ERROR(DH, ERR_R_BN_LIB); + } + + if (dh->pub_key == NULL) { + BN_free(pub_key); + } + if (dh->priv_key == NULL) { + BN_free(priv_key); + } + BN_CTX_free(ctx); + return ok; +} + +int DH_compute_key(unsigned char *out, const BIGNUM *peers_key, DH *dh) { + BN_CTX *ctx = NULL; + BIGNUM *shared_key; + int ret = -1; + int check_result; + BIGNUM local_priv; + + if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS) { + OPENSSL_PUT_ERROR(DH, DH_R_MODULUS_TOO_LARGE); + goto err; + } + + ctx = BN_CTX_new(); + if (ctx == NULL) { + goto err; + } + BN_CTX_start(ctx); + shared_key = BN_CTX_get(ctx); + if (shared_key == NULL) { + goto err; + } + + if (dh->priv_key == NULL) { + OPENSSL_PUT_ERROR(DH, DH_R_NO_PRIVATE_VALUE); + goto err; + } + + if (!BN_MONT_CTX_set_locked(&dh->method_mont_p, &dh->method_mont_p_lock, + dh->p, ctx)) { + goto err; + } + + if (!DH_check_pub_key(dh, peers_key, &check_result) || check_result) { + OPENSSL_PUT_ERROR(DH, DH_R_INVALID_PUBKEY); + goto err; + } + + BN_with_flags(&local_priv, dh->priv_key, BN_FLG_CONSTTIME); + if (!BN_mod_exp_mont_consttime(shared_key, peers_key, &local_priv, dh->p, ctx, + dh->method_mont_p)) { + OPENSSL_PUT_ERROR(DH, ERR_R_BN_LIB); + goto err; + } + + ret = BN_bn2bin(shared_key, out); + +err: + if (ctx != NULL) { + BN_CTX_end(ctx); + BN_CTX_free(ctx); + } + + return ret; +} + +int DH_size(const DH *dh) { return BN_num_bytes(dh->p); } + +unsigned DH_num_bits(const DH *dh) { return BN_num_bits(dh->p); } + +int DH_up_ref(DH *dh) { + CRYPTO_refcount_inc(&dh->references); + return 1; +} + +static int int_dh_bn_cpy(BIGNUM **dst, const BIGNUM *src) { + BIGNUM *a = NULL; + + if (src) { + a = BN_dup(src); + if (!a) { + return 0; + } + } + + BN_free(*dst); + *dst = a; + return 1; +} + +static int int_dh_param_copy(DH *to, const DH *from, int is_x942) { + if (is_x942 == -1) { + is_x942 = !!from->q; + } + if (!int_dh_bn_cpy(&to->p, from->p) || + !int_dh_bn_cpy(&to->g, from->g)) { + return 0; + } + + if (!is_x942) { + return 1; + } + + if (!int_dh_bn_cpy(&to->q, from->q) || + !int_dh_bn_cpy(&to->j, from->j)) { + return 0; + } + + OPENSSL_free(to->seed); + to->seed = NULL; + to->seedlen = 0; + + if (from->seed) { + to->seed = BUF_memdup(from->seed, from->seedlen); + if (!to->seed) { + return 0; + } + to->seedlen = from->seedlen; + } + + return 1; +} + +DH *DHparams_dup(const DH *dh) { + DH *ret = DH_new(); + if (!ret) { + return NULL; + } + + if (!int_dh_param_copy(ret, dh, -1)) { + DH_free(ret); + return NULL; + } + + return ret; +} + +int DH_get_ex_new_index(long argl, void *argp, CRYPTO_EX_unused *unused, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) { + int index; + if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp, dup_func, + free_func)) { + return -1; + } + return index; +} + +int DH_set_ex_data(DH *d, int idx, void *arg) { + return CRYPTO_set_ex_data(&d->ex_data, idx, arg); +} + +void *DH_get_ex_data(DH *d, int idx) { + return CRYPTO_get_ex_data(&d->ex_data, idx); +} diff --git a/external/boringssl/crypto/dh/dh_asn1.c b/external/boringssl/crypto/dh/dh_asn1.c new file mode 100644 index 0000000000..1a147eea91 --- /dev/null +++ b/external/boringssl/crypto/dh/dh_asn1.c @@ -0,0 +1,160 @@ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 2000-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include + +#include +#include +#include + +#include "../bytestring/internal.h" + + +static int parse_integer(CBS *cbs, BIGNUM **out) { + assert(*out == NULL); + *out = BN_new(); + if (*out == NULL) { + return 0; + } + return BN_parse_asn1_unsigned(cbs, *out); +} + +static int marshal_integer(CBB *cbb, BIGNUM *bn) { + if (bn == NULL) { + /* A DH object may be missing some components. */ + OPENSSL_PUT_ERROR(DH, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + return BN_marshal_asn1(cbb, bn); +} + +DH *DH_parse_parameters(CBS *cbs) { + DH *ret = DH_new(); + if (ret == NULL) { + return NULL; + } + + CBS child; + if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) || + !parse_integer(&child, &ret->p) || + !parse_integer(&child, &ret->g)) { + goto err; + } + + uint64_t priv_length; + if (CBS_len(&child) != 0) { + if (!CBS_get_asn1_uint64(&child, &priv_length) || + priv_length > UINT_MAX) { + goto err; + } + ret->priv_length = (unsigned)priv_length; + } + + if (CBS_len(&child) != 0) { + goto err; + } + + return ret; + +err: + OPENSSL_PUT_ERROR(DH, DH_R_DECODE_ERROR); + DH_free(ret); + return NULL; +} + +int DH_marshal_parameters(CBB *cbb, const DH *dh) { + CBB child; + if (!CBB_add_asn1(cbb, &child, CBS_ASN1_SEQUENCE) || + !marshal_integer(&child, dh->p) || + !marshal_integer(&child, dh->g) || + (dh->priv_length != 0 && + !CBB_add_asn1_uint64(&child, dh->priv_length)) || + !CBB_flush(cbb)) { + OPENSSL_PUT_ERROR(DH, DH_R_ENCODE_ERROR); + return 0; + } + return 1; +} + +DH *d2i_DHparams(DH **out, const uint8_t **inp, long len) { + if (len < 0) { + return NULL; + } + CBS cbs; + CBS_init(&cbs, *inp, (size_t)len); + DH *ret = DH_parse_parameters(&cbs); + if (ret == NULL) { + return NULL; + } + if (out != NULL) { + DH_free(*out); + *out = ret; + } + *inp = CBS_data(&cbs); + return ret; +} + +int i2d_DHparams(const DH *in, uint8_t **outp) { + CBB cbb; + if (!CBB_init(&cbb, 0) || + !DH_marshal_parameters(&cbb, in)) { + CBB_cleanup(&cbb); + return -1; + } + return CBB_finish_i2d(&cbb, outp); +} diff --git a/external/boringssl/crypto/dh/dh_test.cc b/external/boringssl/crypto/dh/dh_test.cc new file mode 100644 index 0000000000..1c2442833b --- /dev/null +++ b/external/boringssl/crypto/dh/dh_test.cc @@ -0,0 +1,626 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include "internal.h" +#include "../test/scoped_types.h" + + +static bool RunBasicTests(); +static bool RunRFC5114Tests(); +static bool TestBadY(); +static bool TestASN1(); + +int main(int argc, char *argv[]) { + CRYPTO_library_init(); + + if (!RunBasicTests() || + !RunRFC5114Tests() || + !TestBadY() || + !TestASN1()) { + ERR_print_errors_fp(stderr); + return 1; + } + + printf("PASS\n"); + return 0; +} + +static int GenerateCallback(int p, int n, BN_GENCB *arg) { + char c = '*'; + + if (p == 0) { + c = '.'; + } else if (p == 1) { + c = '+'; + } else if (p == 2) { + c = '*'; + } else if (p == 3) { + c = '\n'; + } + FILE *out = reinterpret_cast(arg->arg); + fputc(c, out); + fflush(out); + + return 1; +} + +static bool RunBasicTests() { + BN_GENCB cb; + BN_GENCB_set(&cb, &GenerateCallback, stdout); + ScopedDH a(DH_new()); + if (!a || !DH_generate_parameters_ex(a.get(), 64, DH_GENERATOR_5, &cb)) { + return false; + } + + int check_result; + if (!DH_check(a.get(), &check_result)) { + return false; + } + if (check_result & DH_CHECK_P_NOT_PRIME) { + printf("p value is not prime\n"); + } + if (check_result & DH_CHECK_P_NOT_SAFE_PRIME) { + printf("p value is not a safe prime\n"); + } + if (check_result & DH_CHECK_UNABLE_TO_CHECK_GENERATOR) { + printf("unable to check the generator value\n"); + } + if (check_result & DH_CHECK_NOT_SUITABLE_GENERATOR) { + printf("the g value is not a generator\n"); + } + + printf("\np = "); + BN_print_fp(stdout, a->p); + printf("\ng = "); + BN_print_fp(stdout, a->g); + printf("\n"); + + ScopedDH b(DH_new()); + if (!b) { + return false; + } + + b->p = BN_dup(a->p); + b->g = BN_dup(a->g); + if (b->p == nullptr || b->g == nullptr) { + return false; + } + + if (!DH_generate_key(a.get())) { + return false; + } + printf("pri1 = "); + BN_print_fp(stdout, a->priv_key); + printf("\npub1 = "); + BN_print_fp(stdout, a->pub_key); + printf("\n"); + + if (!DH_generate_key(b.get())) { + return false; + } + printf("pri2 = "); + BN_print_fp(stdout, b->priv_key); + printf("\npub2 = "); + BN_print_fp(stdout, b->pub_key); + printf("\n"); + + std::vector key1(DH_size(a.get())); + int ret = DH_compute_key(key1.data(), b->pub_key, a.get()); + if (ret < 0) { + return false; + } + key1.resize(ret); + + printf("key1 = "); + for (size_t i = 0; i < key1.size(); i++) { + printf("%02x", key1[i]); + } + printf("\n"); + + std::vector key2(DH_size(b.get())); + ret = DH_compute_key(key2.data(), a->pub_key, b.get()); + if (ret < 0) { + return false; + } + key2.resize(ret); + + printf("key2 = "); + for (size_t i = 0; i < key2.size(); i++) { + printf("%02x", key2[i]); + } + printf("\n"); + + if (key1.size() < 4 || key1 != key2) { + fprintf(stderr, "Error in DH routines\n"); + return false; + } + + return true; +} + +/* Test data from RFC 5114 */ + +static const uint8_t kDHTest1024_160_xA[] = { + 0xB9, 0xA3, 0xB3, 0xAE, 0x8F, 0xEF, 0xC1, 0xA2, 0x93, 0x04, + 0x96, 0x50, 0x70, 0x86, 0xF8, 0x45, 0x5D, 0x48, 0x94, 0x3E}; +static const uint8_t kDHTest1024_160_yA[] = { + 0x2A, 0x85, 0x3B, 0x3D, 0x92, 0x19, 0x75, 0x01, 0xB9, 0x01, 0x5B, 0x2D, + 0xEB, 0x3E, 0xD8, 0x4F, 0x5E, 0x02, 0x1D, 0xCC, 0x3E, 0x52, 0xF1, 0x09, + 0xD3, 0x27, 0x3D, 0x2B, 0x75, 0x21, 0x28, 0x1C, 0xBA, 0xBE, 0x0E, 0x76, + 0xFF, 0x57, 0x27, 0xFA, 0x8A, 0xCC, 0xE2, 0x69, 0x56, 0xBA, 0x9A, 0x1F, + 0xCA, 0x26, 0xF2, 0x02, 0x28, 0xD8, 0x69, 0x3F, 0xEB, 0x10, 0x84, 0x1D, + 0x84, 0xA7, 0x36, 0x00, 0x54, 0xEC, 0xE5, 0xA7, 0xF5, 0xB7, 0xA6, 0x1A, + 0xD3, 0xDF, 0xB3, 0xC6, 0x0D, 0x2E, 0x43, 0x10, 0x6D, 0x87, 0x27, 0xDA, + 0x37, 0xDF, 0x9C, 0xCE, 0x95, 0xB4, 0x78, 0x75, 0x5D, 0x06, 0xBC, 0xEA, + 0x8F, 0x9D, 0x45, 0x96, 0x5F, 0x75, 0xA5, 0xF3, 0xD1, 0xDF, 0x37, 0x01, + 0x16, 0x5F, 0xC9, 0xE5, 0x0C, 0x42, 0x79, 0xCE, 0xB0, 0x7F, 0x98, 0x95, + 0x40, 0xAE, 0x96, 0xD5, 0xD8, 0x8E, 0xD7, 0x76}; +static const uint8_t kDHTest1024_160_xB[] = { + 0x93, 0x92, 0xC9, 0xF9, 0xEB, 0x6A, 0x7A, 0x6A, 0x90, 0x22, + 0xF7, 0xD8, 0x3E, 0x72, 0x23, 0xC6, 0x83, 0x5B, 0xBD, 0xDA}; +static const uint8_t kDHTest1024_160_yB[] = { + 0x71, 0x7A, 0x6C, 0xB0, 0x53, 0x37, 0x1F, 0xF4, 0xA3, 0xB9, 0x32, 0x94, + 0x1C, 0x1E, 0x56, 0x63, 0xF8, 0x61, 0xA1, 0xD6, 0xAD, 0x34, 0xAE, 0x66, + 0x57, 0x6D, 0xFB, 0x98, 0xF6, 0xC6, 0xCB, 0xF9, 0xDD, 0xD5, 0xA5, 0x6C, + 0x78, 0x33, 0xF6, 0xBC, 0xFD, 0xFF, 0x09, 0x55, 0x82, 0xAD, 0x86, 0x8E, + 0x44, 0x0E, 0x8D, 0x09, 0xFD, 0x76, 0x9E, 0x3C, 0xEC, 0xCD, 0xC3, 0xD3, + 0xB1, 0xE4, 0xCF, 0xA0, 0x57, 0x77, 0x6C, 0xAA, 0xF9, 0x73, 0x9B, 0x6A, + 0x9F, 0xEE, 0x8E, 0x74, 0x11, 0xF8, 0xD6, 0xDA, 0xC0, 0x9D, 0x6A, 0x4E, + 0xDB, 0x46, 0xCC, 0x2B, 0x5D, 0x52, 0x03, 0x09, 0x0E, 0xAE, 0x61, 0x26, + 0x31, 0x1E, 0x53, 0xFD, 0x2C, 0x14, 0xB5, 0x74, 0xE6, 0xA3, 0x10, 0x9A, + 0x3D, 0xA1, 0xBE, 0x41, 0xBD, 0xCE, 0xAA, 0x18, 0x6F, 0x5C, 0xE0, 0x67, + 0x16, 0xA2, 0xB6, 0xA0, 0x7B, 0x3C, 0x33, 0xFE}; +static const uint8_t kDHTest1024_160_Z[] = { + 0x5C, 0x80, 0x4F, 0x45, 0x4D, 0x30, 0xD9, 0xC4, 0xDF, 0x85, 0x27, 0x1F, + 0x93, 0x52, 0x8C, 0x91, 0xDF, 0x6B, 0x48, 0xAB, 0x5F, 0x80, 0xB3, 0xB5, + 0x9C, 0xAA, 0xC1, 0xB2, 0x8F, 0x8A, 0xCB, 0xA9, 0xCD, 0x3E, 0x39, 0xF3, + 0xCB, 0x61, 0x45, 0x25, 0xD9, 0x52, 0x1D, 0x2E, 0x64, 0x4C, 0x53, 0xB8, + 0x07, 0xB8, 0x10, 0xF3, 0x40, 0x06, 0x2F, 0x25, 0x7D, 0x7D, 0x6F, 0xBF, + 0xE8, 0xD5, 0xE8, 0xF0, 0x72, 0xE9, 0xB6, 0xE9, 0xAF, 0xDA, 0x94, 0x13, + 0xEA, 0xFB, 0x2E, 0x8B, 0x06, 0x99, 0xB1, 0xFB, 0x5A, 0x0C, 0xAC, 0xED, + 0xDE, 0xAE, 0xAD, 0x7E, 0x9C, 0xFB, 0xB3, 0x6A, 0xE2, 0xB4, 0x20, 0x83, + 0x5B, 0xD8, 0x3A, 0x19, 0xFB, 0x0B, 0x5E, 0x96, 0xBF, 0x8F, 0xA4, 0xD0, + 0x9E, 0x34, 0x55, 0x25, 0x16, 0x7E, 0xCD, 0x91, 0x55, 0x41, 0x6F, 0x46, + 0xF4, 0x08, 0xED, 0x31, 0xB6, 0x3C, 0x6E, 0x6D}; +static const uint8_t kDHTest2048_224_xA[] = { + 0x22, 0xE6, 0x26, 0x01, 0xDB, 0xFF, 0xD0, 0x67, 0x08, 0xA6, + 0x80, 0xF7, 0x47, 0xF3, 0x61, 0xF7, 0x6D, 0x8F, 0x4F, 0x72, + 0x1A, 0x05, 0x48, 0xE4, 0x83, 0x29, 0x4B, 0x0C}; +static const uint8_t kDHTest2048_224_yA[] = { + 0x1B, 0x3A, 0x63, 0x45, 0x1B, 0xD8, 0x86, 0xE6, 0x99, 0xE6, 0x7B, 0x49, + 0x4E, 0x28, 0x8B, 0xD7, 0xF8, 0xE0, 0xD3, 0x70, 0xBA, 0xDD, 0xA7, 0xA0, + 0xEF, 0xD2, 0xFD, 0xE7, 0xD8, 0xF6, 0x61, 0x45, 0xCC, 0x9F, 0x28, 0x04, + 0x19, 0x97, 0x5E, 0xB8, 0x08, 0x87, 0x7C, 0x8A, 0x4C, 0x0C, 0x8E, 0x0B, + 0xD4, 0x8D, 0x4A, 0x54, 0x01, 0xEB, 0x1E, 0x87, 0x76, 0xBF, 0xEE, 0xE1, + 0x34, 0xC0, 0x38, 0x31, 0xAC, 0x27, 0x3C, 0xD9, 0xD6, 0x35, 0xAB, 0x0C, + 0xE0, 0x06, 0xA4, 0x2A, 0x88, 0x7E, 0x3F, 0x52, 0xFB, 0x87, 0x66, 0xB6, + 0x50, 0xF3, 0x80, 0x78, 0xBC, 0x8E, 0xE8, 0x58, 0x0C, 0xEF, 0xE2, 0x43, + 0x96, 0x8C, 0xFC, 0x4F, 0x8D, 0xC3, 0xDB, 0x08, 0x45, 0x54, 0x17, 0x1D, + 0x41, 0xBF, 0x2E, 0x86, 0x1B, 0x7B, 0xB4, 0xD6, 0x9D, 0xD0, 0xE0, 0x1E, + 0xA3, 0x87, 0xCB, 0xAA, 0x5C, 0xA6, 0x72, 0xAF, 0xCB, 0xE8, 0xBD, 0xB9, + 0xD6, 0x2D, 0x4C, 0xE1, 0x5F, 0x17, 0xDD, 0x36, 0xF9, 0x1E, 0xD1, 0xEE, + 0xDD, 0x65, 0xCA, 0x4A, 0x06, 0x45, 0x5C, 0xB9, 0x4C, 0xD4, 0x0A, 0x52, + 0xEC, 0x36, 0x0E, 0x84, 0xB3, 0xC9, 0x26, 0xE2, 0x2C, 0x43, 0x80, 0xA3, + 0xBF, 0x30, 0x9D, 0x56, 0x84, 0x97, 0x68, 0xB7, 0xF5, 0x2C, 0xFD, 0xF6, + 0x55, 0xFD, 0x05, 0x3A, 0x7E, 0xF7, 0x06, 0x97, 0x9E, 0x7E, 0x58, 0x06, + 0xB1, 0x7D, 0xFA, 0xE5, 0x3A, 0xD2, 0xA5, 0xBC, 0x56, 0x8E, 0xBB, 0x52, + 0x9A, 0x7A, 0x61, 0xD6, 0x8D, 0x25, 0x6F, 0x8F, 0xC9, 0x7C, 0x07, 0x4A, + 0x86, 0x1D, 0x82, 0x7E, 0x2E, 0xBC, 0x8C, 0x61, 0x34, 0x55, 0x31, 0x15, + 0xB7, 0x0E, 0x71, 0x03, 0x92, 0x0A, 0xA1, 0x6D, 0x85, 0xE5, 0x2B, 0xCB, + 0xAB, 0x8D, 0x78, 0x6A, 0x68, 0x17, 0x8F, 0xA8, 0xFF, 0x7C, 0x2F, 0x5C, + 0x71, 0x64, 0x8D, 0x6F}; +static const uint8_t kDHTest2048_224_xB[] = { + 0x4F, 0xF3, 0xBC, 0x96, 0xC7, 0xFC, 0x6A, 0x6D, 0x71, 0xD3, + 0xB3, 0x63, 0x80, 0x0A, 0x7C, 0xDF, 0xEF, 0x6F, 0xC4, 0x1B, + 0x44, 0x17, 0xEA, 0x15, 0x35, 0x3B, 0x75, 0x90}; +static const uint8_t kDHTest2048_224_yB[] = { + 0x4D, 0xCE, 0xE9, 0x92, 0xA9, 0x76, 0x2A, 0x13, 0xF2, 0xF8, 0x38, 0x44, + 0xAD, 0x3D, 0x77, 0xEE, 0x0E, 0x31, 0xC9, 0x71, 0x8B, 0x3D, 0xB6, 0xC2, + 0x03, 0x5D, 0x39, 0x61, 0x18, 0x2C, 0x3E, 0x0B, 0xA2, 0x47, 0xEC, 0x41, + 0x82, 0xD7, 0x60, 0xCD, 0x48, 0xD9, 0x95, 0x99, 0x97, 0x06, 0x22, 0xA1, + 0x88, 0x1B, 0xBA, 0x2D, 0xC8, 0x22, 0x93, 0x9C, 0x78, 0xC3, 0x91, 0x2C, + 0x66, 0x61, 0xFA, 0x54, 0x38, 0xB2, 0x07, 0x66, 0x22, 0x2B, 0x75, 0xE2, + 0x4C, 0x2E, 0x3A, 0xD0, 0xC7, 0x28, 0x72, 0x36, 0x12, 0x95, 0x25, 0xEE, + 0x15, 0xB5, 0xDD, 0x79, 0x98, 0xAA, 0x04, 0xC4, 0xA9, 0x69, 0x6C, 0xAC, + 0xD7, 0x17, 0x20, 0x83, 0xA9, 0x7A, 0x81, 0x66, 0x4E, 0xAD, 0x2C, 0x47, + 0x9E, 0x44, 0x4E, 0x4C, 0x06, 0x54, 0xCC, 0x19, 0xE2, 0x8D, 0x77, 0x03, + 0xCE, 0xE8, 0xDA, 0xCD, 0x61, 0x26, 0xF5, 0xD6, 0x65, 0xEC, 0x52, 0xC6, + 0x72, 0x55, 0xDB, 0x92, 0x01, 0x4B, 0x03, 0x7E, 0xB6, 0x21, 0xA2, 0xAC, + 0x8E, 0x36, 0x5D, 0xE0, 0x71, 0xFF, 0xC1, 0x40, 0x0A, 0xCF, 0x07, 0x7A, + 0x12, 0x91, 0x3D, 0xD8, 0xDE, 0x89, 0x47, 0x34, 0x37, 0xAB, 0x7B, 0xA3, + 0x46, 0x74, 0x3C, 0x1B, 0x21, 0x5D, 0xD9, 0xC1, 0x21, 0x64, 0xA7, 0xE4, + 0x05, 0x31, 0x18, 0xD1, 0x99, 0xBE, 0xC8, 0xEF, 0x6F, 0xC5, 0x61, 0x17, + 0x0C, 0x84, 0xC8, 0x7D, 0x10, 0xEE, 0x9A, 0x67, 0x4A, 0x1F, 0xA8, 0xFF, + 0xE1, 0x3B, 0xDF, 0xBA, 0x1D, 0x44, 0xDE, 0x48, 0x94, 0x6D, 0x68, 0xDC, + 0x0C, 0xDD, 0x77, 0x76, 0x35, 0xA7, 0xAB, 0x5B, 0xFB, 0x1E, 0x4B, 0xB7, + 0xB8, 0x56, 0xF9, 0x68, 0x27, 0x73, 0x4C, 0x18, 0x41, 0x38, 0xE9, 0x15, + 0xD9, 0xC3, 0x00, 0x2E, 0xBC, 0xE5, 0x31, 0x20, 0x54, 0x6A, 0x7E, 0x20, + 0x02, 0x14, 0x2B, 0x6C}; +static const uint8_t kDHTest2048_224_Z[] = { + 0x34, 0xD9, 0xBD, 0xDC, 0x1B, 0x42, 0x17, 0x6C, 0x31, 0x3F, 0xEA, 0x03, + 0x4C, 0x21, 0x03, 0x4D, 0x07, 0x4A, 0x63, 0x13, 0xBB, 0x4E, 0xCD, 0xB3, + 0x70, 0x3F, 0xFF, 0x42, 0x45, 0x67, 0xA4, 0x6B, 0xDF, 0x75, 0x53, 0x0E, + 0xDE, 0x0A, 0x9D, 0xA5, 0x22, 0x9D, 0xE7, 0xD7, 0x67, 0x32, 0x28, 0x6C, + 0xBC, 0x0F, 0x91, 0xDA, 0x4C, 0x3C, 0x85, 0x2F, 0xC0, 0x99, 0xC6, 0x79, + 0x53, 0x1D, 0x94, 0xC7, 0x8A, 0xB0, 0x3D, 0x9D, 0xEC, 0xB0, 0xA4, 0xE4, + 0xCA, 0x8B, 0x2B, 0xB4, 0x59, 0x1C, 0x40, 0x21, 0xCF, 0x8C, 0xE3, 0xA2, + 0x0A, 0x54, 0x1D, 0x33, 0x99, 0x40, 0x17, 0xD0, 0x20, 0x0A, 0xE2, 0xC9, + 0x51, 0x6E, 0x2F, 0xF5, 0x14, 0x57, 0x79, 0x26, 0x9E, 0x86, 0x2B, 0x0F, + 0xB4, 0x74, 0xA2, 0xD5, 0x6D, 0xC3, 0x1E, 0xD5, 0x69, 0xA7, 0x70, 0x0B, + 0x4C, 0x4A, 0xB1, 0x6B, 0x22, 0xA4, 0x55, 0x13, 0x53, 0x1E, 0xF5, 0x23, + 0xD7, 0x12, 0x12, 0x07, 0x7B, 0x5A, 0x16, 0x9B, 0xDE, 0xFF, 0xAD, 0x7A, + 0xD9, 0x60, 0x82, 0x84, 0xC7, 0x79, 0x5B, 0x6D, 0x5A, 0x51, 0x83, 0xB8, + 0x70, 0x66, 0xDE, 0x17, 0xD8, 0xD6, 0x71, 0xC9, 0xEB, 0xD8, 0xEC, 0x89, + 0x54, 0x4D, 0x45, 0xEC, 0x06, 0x15, 0x93, 0xD4, 0x42, 0xC6, 0x2A, 0xB9, + 0xCE, 0x3B, 0x1C, 0xB9, 0x94, 0x3A, 0x1D, 0x23, 0xA5, 0xEA, 0x3B, 0xCF, + 0x21, 0xA0, 0x14, 0x71, 0xE6, 0x7E, 0x00, 0x3E, 0x7F, 0x8A, 0x69, 0xC7, + 0x28, 0xBE, 0x49, 0x0B, 0x2F, 0xC8, 0x8C, 0xFE, 0xB9, 0x2D, 0xB6, 0xA2, + 0x15, 0xE5, 0xD0, 0x3C, 0x17, 0xC4, 0x64, 0xC9, 0xAC, 0x1A, 0x46, 0xE2, + 0x03, 0xE1, 0x3F, 0x95, 0x29, 0x95, 0xFB, 0x03, 0xC6, 0x9D, 0x3C, 0xC4, + 0x7F, 0xCB, 0x51, 0x0B, 0x69, 0x98, 0xFF, 0xD3, 0xAA, 0x6D, 0xE7, 0x3C, + 0xF9, 0xF6, 0x38, 0x69}; +static const uint8_t kDHTest2048_256_xA[] = { + 0x08, 0x81, 0x38, 0x2C, 0xDB, 0x87, 0x66, 0x0C, 0x6D, 0xC1, 0x3E, + 0x61, 0x49, 0x38, 0xD5, 0xB9, 0xC8, 0xB2, 0xF2, 0x48, 0x58, 0x1C, + 0xC5, 0xE3, 0x1B, 0x35, 0x45, 0x43, 0x97, 0xFC, 0xE5, 0x0E}; +static const uint8_t kDHTest2048_256_yA[] = { + 0x2E, 0x93, 0x80, 0xC8, 0x32, 0x3A, 0xF9, 0x75, 0x45, 0xBC, 0x49, 0x41, + 0xDE, 0xB0, 0xEC, 0x37, 0x42, 0xC6, 0x2F, 0xE0, 0xEC, 0xE8, 0x24, 0xA6, + 0xAB, 0xDB, 0xE6, 0x6C, 0x59, 0xBE, 0xE0, 0x24, 0x29, 0x11, 0xBF, 0xB9, + 0x67, 0x23, 0x5C, 0xEB, 0xA3, 0x5A, 0xE1, 0x3E, 0x4E, 0xC7, 0x52, 0xBE, + 0x63, 0x0B, 0x92, 0xDC, 0x4B, 0xDE, 0x28, 0x47, 0xA9, 0xC6, 0x2C, 0xB8, + 0x15, 0x27, 0x45, 0x42, 0x1F, 0xB7, 0xEB, 0x60, 0xA6, 0x3C, 0x0F, 0xE9, + 0x15, 0x9F, 0xCC, 0xE7, 0x26, 0xCE, 0x7C, 0xD8, 0x52, 0x3D, 0x74, 0x50, + 0x66, 0x7E, 0xF8, 0x40, 0xE4, 0x91, 0x91, 0x21, 0xEB, 0x5F, 0x01, 0xC8, + 0xC9, 0xB0, 0xD3, 0xD6, 0x48, 0xA9, 0x3B, 0xFB, 0x75, 0x68, 0x9E, 0x82, + 0x44, 0xAC, 0x13, 0x4A, 0xF5, 0x44, 0x71, 0x1C, 0xE7, 0x9A, 0x02, 0xDC, + 0xC3, 0x42, 0x26, 0x68, 0x47, 0x80, 0xDD, 0xDC, 0xB4, 0x98, 0x59, 0x41, + 0x06, 0xC3, 0x7F, 0x5B, 0xC7, 0x98, 0x56, 0x48, 0x7A, 0xF5, 0xAB, 0x02, + 0x2A, 0x2E, 0x5E, 0x42, 0xF0, 0x98, 0x97, 0xC1, 0xA8, 0x5A, 0x11, 0xEA, + 0x02, 0x12, 0xAF, 0x04, 0xD9, 0xB4, 0xCE, 0xBC, 0x93, 0x7C, 0x3C, 0x1A, + 0x3E, 0x15, 0xA8, 0xA0, 0x34, 0x2E, 0x33, 0x76, 0x15, 0xC8, 0x4E, 0x7F, + 0xE3, 0xB8, 0xB9, 0xB8, 0x7F, 0xB1, 0xE7, 0x3A, 0x15, 0xAF, 0x12, 0xA3, + 0x0D, 0x74, 0x6E, 0x06, 0xDF, 0xC3, 0x4F, 0x29, 0x0D, 0x79, 0x7C, 0xE5, + 0x1A, 0xA1, 0x3A, 0xA7, 0x85, 0xBF, 0x66, 0x58, 0xAF, 0xF5, 0xE4, 0xB0, + 0x93, 0x00, 0x3C, 0xBE, 0xAF, 0x66, 0x5B, 0x3C, 0x2E, 0x11, 0x3A, 0x3A, + 0x4E, 0x90, 0x52, 0x69, 0x34, 0x1D, 0xC0, 0x71, 0x14, 0x26, 0x68, 0x5F, + 0x4E, 0xF3, 0x7E, 0x86, 0x8A, 0x81, 0x26, 0xFF, 0x3F, 0x22, 0x79, 0xB5, + 0x7C, 0xA6, 0x7E, 0x29}; +static const uint8_t kDHTest2048_256_xB[] = { + 0x7D, 0x62, 0xA7, 0xE3, 0xEF, 0x36, 0xDE, 0x61, 0x7B, 0x13, 0xD1, + 0xAF, 0xB8, 0x2C, 0x78, 0x0D, 0x83, 0xA2, 0x3B, 0xD4, 0xEE, 0x67, + 0x05, 0x64, 0x51, 0x21, 0xF3, 0x71, 0xF5, 0x46, 0xA5, 0x3D}; +static const uint8_t kDHTest2048_256_yB[] = { + 0x57, 0x5F, 0x03, 0x51, 0xBD, 0x2B, 0x1B, 0x81, 0x74, 0x48, 0xBD, 0xF8, + 0x7A, 0x6C, 0x36, 0x2C, 0x1E, 0x28, 0x9D, 0x39, 0x03, 0xA3, 0x0B, 0x98, + 0x32, 0xC5, 0x74, 0x1F, 0xA2, 0x50, 0x36, 0x3E, 0x7A, 0xCB, 0xC7, 0xF7, + 0x7F, 0x3D, 0xAC, 0xBC, 0x1F, 0x13, 0x1A, 0xDD, 0x8E, 0x03, 0x36, 0x7E, + 0xFF, 0x8F, 0xBB, 0xB3, 0xE1, 0xC5, 0x78, 0x44, 0x24, 0x80, 0x9B, 0x25, + 0xAF, 0xE4, 0xD2, 0x26, 0x2A, 0x1A, 0x6F, 0xD2, 0xFA, 0xB6, 0x41, 0x05, + 0xCA, 0x30, 0xA6, 0x74, 0xE0, 0x7F, 0x78, 0x09, 0x85, 0x20, 0x88, 0x63, + 0x2F, 0xC0, 0x49, 0x23, 0x37, 0x91, 0xAD, 0x4E, 0xDD, 0x08, 0x3A, 0x97, + 0x8B, 0x88, 0x3E, 0xE6, 0x18, 0xBC, 0x5E, 0x0D, 0xD0, 0x47, 0x41, 0x5F, + 0x2D, 0x95, 0xE6, 0x83, 0xCF, 0x14, 0x82, 0x6B, 0x5F, 0xBE, 0x10, 0xD3, + 0xCE, 0x41, 0xC6, 0xC1, 0x20, 0xC7, 0x8A, 0xB2, 0x00, 0x08, 0xC6, 0x98, + 0xBF, 0x7F, 0x0B, 0xCA, 0xB9, 0xD7, 0xF4, 0x07, 0xBE, 0xD0, 0xF4, 0x3A, + 0xFB, 0x29, 0x70, 0xF5, 0x7F, 0x8D, 0x12, 0x04, 0x39, 0x63, 0xE6, 0x6D, + 0xDD, 0x32, 0x0D, 0x59, 0x9A, 0xD9, 0x93, 0x6C, 0x8F, 0x44, 0x13, 0x7C, + 0x08, 0xB1, 0x80, 0xEC, 0x5E, 0x98, 0x5C, 0xEB, 0xE1, 0x86, 0xF3, 0xD5, + 0x49, 0x67, 0x7E, 0x80, 0x60, 0x73, 0x31, 0xEE, 0x17, 0xAF, 0x33, 0x80, + 0xA7, 0x25, 0xB0, 0x78, 0x23, 0x17, 0xD7, 0xDD, 0x43, 0xF5, 0x9D, 0x7A, + 0xF9, 0x56, 0x8A, 0x9B, 0xB6, 0x3A, 0x84, 0xD3, 0x65, 0xF9, 0x22, 0x44, + 0xED, 0x12, 0x09, 0x88, 0x21, 0x93, 0x02, 0xF4, 0x29, 0x24, 0xC7, 0xCA, + 0x90, 0xB8, 0x9D, 0x24, 0xF7, 0x1B, 0x0A, 0xB6, 0x97, 0x82, 0x3D, 0x7D, + 0xEB, 0x1A, 0xFF, 0x5B, 0x0E, 0x8E, 0x4A, 0x45, 0xD4, 0x9F, 0x7F, 0x53, + 0x75, 0x7E, 0x19, 0x13}; +static const uint8_t kDHTest2048_256_Z[] = { + 0x86, 0xC7, 0x0B, 0xF8, 0xD0, 0xBB, 0x81, 0xBB, 0x01, 0x07, 0x8A, 0x17, + 0x21, 0x9C, 0xB7, 0xD2, 0x72, 0x03, 0xDB, 0x2A, 0x19, 0xC8, 0x77, 0xF1, + 0xD1, 0xF1, 0x9F, 0xD7, 0xD7, 0x7E, 0xF2, 0x25, 0x46, 0xA6, 0x8F, 0x00, + 0x5A, 0xD5, 0x2D, 0xC8, 0x45, 0x53, 0xB7, 0x8F, 0xC6, 0x03, 0x30, 0xBE, + 0x51, 0xEA, 0x7C, 0x06, 0x72, 0xCA, 0xC1, 0x51, 0x5E, 0x4B, 0x35, 0xC0, + 0x47, 0xB9, 0xA5, 0x51, 0xB8, 0x8F, 0x39, 0xDC, 0x26, 0xDA, 0x14, 0xA0, + 0x9E, 0xF7, 0x47, 0x74, 0xD4, 0x7C, 0x76, 0x2D, 0xD1, 0x77, 0xF9, 0xED, + 0x5B, 0xC2, 0xF1, 0x1E, 0x52, 0xC8, 0x79, 0xBD, 0x95, 0x09, 0x85, 0x04, + 0xCD, 0x9E, 0xEC, 0xD8, 0xA8, 0xF9, 0xB3, 0xEF, 0xBD, 0x1F, 0x00, 0x8A, + 0xC5, 0x85, 0x30, 0x97, 0xD9, 0xD1, 0x83, 0x7F, 0x2B, 0x18, 0xF7, 0x7C, + 0xD7, 0xBE, 0x01, 0xAF, 0x80, 0xA7, 0xC7, 0xB5, 0xEA, 0x3C, 0xA5, 0x4C, + 0xC0, 0x2D, 0x0C, 0x11, 0x6F, 0xEE, 0x3F, 0x95, 0xBB, 0x87, 0x39, 0x93, + 0x85, 0x87, 0x5D, 0x7E, 0x86, 0x74, 0x7E, 0x67, 0x6E, 0x72, 0x89, 0x38, + 0xAC, 0xBF, 0xF7, 0x09, 0x8E, 0x05, 0xBE, 0x4D, 0xCF, 0xB2, 0x40, 0x52, + 0xB8, 0x3A, 0xEF, 0xFB, 0x14, 0x78, 0x3F, 0x02, 0x9A, 0xDB, 0xDE, 0x7F, + 0x53, 0xFA, 0xE9, 0x20, 0x84, 0x22, 0x40, 0x90, 0xE0, 0x07, 0xCE, 0xE9, + 0x4D, 0x4B, 0xF2, 0xBA, 0xCE, 0x9F, 0xFD, 0x4B, 0x57, 0xD2, 0xAF, 0x7C, + 0x72, 0x4D, 0x0C, 0xAA, 0x19, 0xBF, 0x05, 0x01, 0xF6, 0xF1, 0x7B, 0x4A, + 0xA1, 0x0F, 0x42, 0x5E, 0x3E, 0xA7, 0x60, 0x80, 0xB4, 0xB9, 0xD6, 0xB3, + 0xCE, 0xFE, 0xA1, 0x15, 0xB2, 0xCE, 0xB8, 0x78, 0x9B, 0xB8, 0xA3, 0xB0, + 0xEA, 0x87, 0xFE, 0xBE, 0x63, 0xB6, 0xC8, 0xF8, 0x46, 0xEC, 0x6D, 0xB0, + 0xC2, 0x6C, 0x5D, 0x7C}; + +struct RFC5114TestData { + DH *(*get_param)(const ENGINE *engine); + const uint8_t *xA; + size_t xA_len; + const uint8_t *yA; + size_t yA_len; + const uint8_t *xB; + size_t xB_len; + const uint8_t *yB; + size_t yB_len; + const uint8_t *Z; + size_t Z_len; +}; + +#define MAKE_RFC5114_TEST_DATA(pre) \ + { \ + DH_get_##pre, kDHTest##pre##_xA, sizeof(kDHTest##pre##_xA), \ + kDHTest##pre##_yA, sizeof(kDHTest##pre##_yA), kDHTest##pre##_xB, \ + sizeof(kDHTest##pre##_xB), kDHTest##pre##_yB, \ + sizeof(kDHTest##pre##_yB), kDHTest##pre##_Z, sizeof(kDHTest##pre##_Z) \ + } + +static const RFC5114TestData kRFCTestData[] = { + MAKE_RFC5114_TEST_DATA(1024_160), + MAKE_RFC5114_TEST_DATA(2048_224), + MAKE_RFC5114_TEST_DATA(2048_256), + }; + +static bool RunRFC5114Tests() { + for (unsigned i = 0; i < sizeof(kRFCTestData) / sizeof(RFC5114TestData); i++) { + const RFC5114TestData *td = kRFCTestData + i; + /* Set up DH structures setting key components */ + ScopedDH dhA(td->get_param(nullptr)); + ScopedDH dhB(td->get_param(nullptr)); + if (!dhA || !dhB) { + fprintf(stderr, "Initialisation error RFC5114 set %u\n", i + 1); + return false; + } + + dhA->priv_key = BN_bin2bn(td->xA, td->xA_len, nullptr); + dhA->pub_key = BN_bin2bn(td->yA, td->yA_len, nullptr); + + dhB->priv_key = BN_bin2bn(td->xB, td->xB_len, nullptr); + dhB->pub_key = BN_bin2bn(td->yB, td->yB_len, nullptr); + + if (!dhA->priv_key || !dhA->pub_key || !dhB->priv_key || !dhB->pub_key) { + fprintf(stderr, "BN_bin2bn error RFC5114 set %u\n", i + 1); + return false; + } + + if ((td->Z_len != (size_t)DH_size(dhA.get())) || + (td->Z_len != (size_t)DH_size(dhB.get()))) { + return false; + } + + std::vector Z1(DH_size(dhA.get())); + std::vector Z2(DH_size(dhB.get())); + /* Work out shared secrets using both sides and compare + * with expected values. */ + int ret1 = DH_compute_key(Z1.data(), dhB->pub_key, dhA.get()); + int ret2 = DH_compute_key(Z2.data(), dhA->pub_key, dhB.get()); + if (ret1 < 0 || ret2 < 0) { + fprintf(stderr, "DH_compute_key error RFC5114 set %u\n", i + 1); + return false; + } + + if (static_cast(ret1) != td->Z_len || + memcmp(Z1.data(), td->Z, td->Z_len) != 0 || + static_cast(ret2) != td->Z_len || + memcmp(Z2.data(), td->Z, td->Z_len) != 0) { + fprintf(stderr, "Test failed RFC5114 set %u\n", i + 1); + return false; + } + + printf("RFC5114 parameter test %u OK\n", i + 1); + } + + return 1; +} + +// kRFC5114_2048_224BadY is a bad y-coordinate for RFC 5114's 2048-bit MODP +// Group with 224-bit Prime Order Subgroup (section 2.2). +static const uint8_t kRFC5114_2048_224BadY[] = { + 0x45, 0x32, 0x5f, 0x51, 0x07, 0xe5, 0xdf, 0x1c, 0xd6, 0x02, 0x82, 0xb3, + 0x32, 0x8f, 0xa4, 0x0f, 0x87, 0xb8, 0x41, 0xfe, 0xb9, 0x35, 0xde, 0xad, + 0xc6, 0x26, 0x85, 0xb4, 0xff, 0x94, 0x8c, 0x12, 0x4c, 0xbf, 0x5b, 0x20, + 0xc4, 0x46, 0xa3, 0x26, 0xeb, 0xa4, 0x25, 0xb7, 0x68, 0x8e, 0xcc, 0x67, + 0xba, 0xea, 0x58, 0xd0, 0xf2, 0xe9, 0xd2, 0x24, 0x72, 0x60, 0xda, 0x88, + 0x18, 0x9c, 0xe0, 0x31, 0x6a, 0xad, 0x50, 0x6d, 0x94, 0x35, 0x8b, 0x83, + 0x4a, 0x6e, 0xfa, 0x48, 0x73, 0x0f, 0x83, 0x87, 0xff, 0x6b, 0x66, 0x1f, + 0xa8, 0x82, 0xc6, 0x01, 0xe5, 0x80, 0xb5, 0xb0, 0x52, 0xd0, 0xe9, 0xd8, + 0x72, 0xf9, 0x7d, 0x5b, 0x8b, 0xa5, 0x4c, 0xa5, 0x25, 0x95, 0x74, 0xe2, + 0x7a, 0x61, 0x4e, 0xa7, 0x8f, 0x12, 0xe2, 0xd2, 0x9d, 0x8c, 0x02, 0x70, + 0x34, 0x44, 0x32, 0xc7, 0xb2, 0xf3, 0xb9, 0xfe, 0x17, 0x2b, 0xd6, 0x1f, + 0x8b, 0x7e, 0x4a, 0xfa, 0xa3, 0xb5, 0x3e, 0x7a, 0x81, 0x9a, 0x33, 0x66, + 0x62, 0xa4, 0x50, 0x18, 0x3e, 0xa2, 0x5f, 0x00, 0x07, 0xd8, 0x9b, 0x22, + 0xe4, 0xec, 0x84, 0xd5, 0xeb, 0x5a, 0xf3, 0x2a, 0x31, 0x23, 0xd8, 0x44, + 0x22, 0x2a, 0x8b, 0x37, 0x44, 0xcc, 0xc6, 0x87, 0x4b, 0xbe, 0x50, 0x9d, + 0x4a, 0xc4, 0x8e, 0x45, 0xcf, 0x72, 0x4d, 0xc0, 0x89, 0xb3, 0x72, 0xed, + 0x33, 0x2c, 0xbc, 0x7f, 0x16, 0x39, 0x3b, 0xeb, 0xd2, 0xdd, 0xa8, 0x01, + 0x73, 0x84, 0x62, 0xb9, 0x29, 0xd2, 0xc9, 0x51, 0x32, 0x9e, 0x7a, 0x6a, + 0xcf, 0xc1, 0x0a, 0xdb, 0x0e, 0xe0, 0x62, 0x77, 0x6f, 0x59, 0x62, 0x72, + 0x5a, 0x69, 0xa6, 0x5b, 0x70, 0xca, 0x65, 0xc4, 0x95, 0x6f, 0x9a, 0xc2, + 0xdf, 0x72, 0x6d, 0xb1, 0x1e, 0x54, 0x7b, 0x51, 0xb4, 0xef, 0x7f, 0x89, + 0x93, 0x74, 0x89, 0x59, +}; + +static bool TestBadY() { + ScopedDH dh(DH_get_2048_224(nullptr)); + ScopedBIGNUM pub_key( + BN_bin2bn(kRFC5114_2048_224BadY, sizeof(kRFC5114_2048_224BadY), nullptr)); + if (!dh || !pub_key || !DH_generate_key(dh.get())) { + return false; + } + + int flags; + if (!DH_check_pub_key(dh.get(), pub_key.get(), &flags)) { + return false; + } + if (!(flags & DH_CHECK_PUBKEY_INVALID)) { + fprintf(stderr, "DH_check_pub_key did not reject the key.\n"); + return false; + } + + std::vector result(DH_size(dh.get())); + if (DH_compute_key(result.data(), pub_key.get(), dh.get()) >= 0) { + fprintf(stderr, "DH_compute_key unexpectedly succeeded.\n"); + return false; + } + ERR_clear_error(); + + return true; +} + +static bool BIGNUMEqualsHex(const BIGNUM *bn, const char *hex) { + BIGNUM *hex_bn = NULL; + if (!BN_hex2bn(&hex_bn, hex)) { + return false; + } + ScopedBIGNUM free_hex_bn(hex_bn); + return BN_cmp(bn, hex_bn) == 0; +} + +static bool TestASN1() { + // kParams are a set of Diffie-Hellman parameters generated with + // openssl dhparam 256 + static const uint8_t kParams[] = { + 0x30, 0x26, 0x02, 0x21, 0x00, 0xd7, 0x20, 0x34, 0xa3, 0x27, + 0x4f, 0xdf, 0xbf, 0x04, 0xfd, 0x24, 0x68, 0x25, 0xb6, 0x56, + 0xd8, 0xab, 0x2a, 0x41, 0x2d, 0x74, 0x0a, 0x52, 0x08, 0x7c, + 0x40, 0x71, 0x4e, 0xd2, 0x57, 0x93, 0x13, 0x02, 0x01, 0x02, + }; + + CBS cbs; + CBS_init(&cbs, kParams, sizeof(kParams)); + ScopedDH dh(DH_parse_parameters(&cbs)); + if (!dh || CBS_len(&cbs) != 0 || + !BIGNUMEqualsHex( + dh->p, + "d72034a3274fdfbf04fd246825b656d8ab2a412d740a52087c40714ed2579313") || + !BIGNUMEqualsHex(dh->g, "2") || dh->priv_length != 0) { + return false; + } + + ScopedCBB cbb; + uint8_t *der; + size_t der_len; + if (!CBB_init(cbb.get(), 0) || + !DH_marshal_parameters(cbb.get(), dh.get()) || + !CBB_finish(cbb.get(), &der, &der_len)) { + return false; + } + ScopedOpenSSLBytes free_der(der); + if (der_len != sizeof(kParams) || memcmp(der, kParams, der_len) != 0) { + return false; + } + + // kParamsDSA are a set of Diffie-Hellman parameters generated with + // openssl dhparam 256 -dsaparam + static const uint8_t kParamsDSA[] = { + 0x30, 0x81, 0x89, 0x02, 0x41, 0x00, 0x93, 0xf3, 0xc1, 0x18, 0x01, 0xe6, + 0x62, 0xb6, 0xd1, 0x46, 0x9a, 0x2c, 0x72, 0xea, 0x31, 0xd9, 0x18, 0x10, + 0x30, 0x28, 0x63, 0xe2, 0x34, 0x7d, 0x80, 0xca, 0xee, 0x82, 0x2b, 0x19, + 0x3c, 0x19, 0xbb, 0x42, 0x83, 0x02, 0x70, 0xdd, 0xdb, 0x8c, 0x03, 0xab, + 0xe9, 0x9c, 0xc4, 0x00, 0x4d, 0x70, 0x5f, 0x52, 0x03, 0x31, 0x2c, 0xa4, + 0x67, 0x34, 0x51, 0x95, 0x2a, 0xac, 0x11, 0xe2, 0x6a, 0x55, 0x02, 0x40, + 0x44, 0xc8, 0x10, 0x53, 0x44, 0x32, 0x31, 0x63, 0xd8, 0xd1, 0x8c, 0x75, + 0xc8, 0x98, 0x53, 0x3b, 0x5b, 0x4a, 0x2a, 0x0a, 0x09, 0xe7, 0xd0, 0x3c, + 0x53, 0x72, 0xa8, 0x6b, 0x70, 0x41, 0x9c, 0x26, 0x71, 0x44, 0xfc, 0x7f, + 0x08, 0x75, 0xe1, 0x02, 0xab, 0x74, 0x41, 0xe8, 0x2a, 0x3d, 0x3c, 0x26, + 0x33, 0x09, 0xe4, 0x8b, 0xb4, 0x41, 0xec, 0xa6, 0xa8, 0xba, 0x1a, 0x07, + 0x8a, 0x77, 0xf5, 0x5f, 0x02, 0x02, 0x00, 0xa0, + }; + + CBS_init(&cbs, kParamsDSA, sizeof(kParamsDSA)); + dh.reset(DH_parse_parameters(&cbs)); + if (!dh || CBS_len(&cbs) != 0 || + !BIGNUMEqualsHex(dh->p, + "93f3c11801e662b6d1469a2c72ea31d91810302863e2347d80caee8" + "22b193c19bb42830270dddb8c03abe99cc4004d705f5203312ca467" + "3451952aac11e26a55") || + !BIGNUMEqualsHex(dh->g, + "44c8105344323163d8d18c75c898533b5b4a2a0a09e7d03c5372a86" + "b70419c267144fc7f0875e102ab7441e82a3d3c263309e48bb441ec" + "a6a8ba1a078a77f55f") || + dh->priv_length != 160) { + return false; + } + + if (!CBB_init(cbb.get(), 0) || + !DH_marshal_parameters(cbb.get(), dh.get()) || + !CBB_finish(cbb.get(), &der, &der_len)) { + return false; + } + ScopedOpenSSLBytes free_der2(der); + if (der_len != sizeof(kParamsDSA) || memcmp(der, kParamsDSA, der_len) != 0) { + return false; + } + + return true; +} diff --git a/external/boringssl/crypto/dh/internal.h b/external/boringssl/crypto/dh/internal.h new file mode 100644 index 0000000000..81b9c90290 --- /dev/null +++ b/external/boringssl/crypto/dh/internal.h @@ -0,0 +1,80 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_DH_INTERNAL_H +#define OPENSSL_HEADER_DH_INTERNAL_H + +#include + +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* DH_check_standard_parameters checks if the parameters in |dh| are well + * known and safe. If so, it sets |dh->priv_length| to an appropriately smaller + * value than the default. */ +void DH_check_standard_parameters(DH *dh); + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_DH_INTERNAL_H */ diff --git a/external/boringssl/crypto/dh/params.c b/external/boringssl/crypto/dh/params.c new file mode 100644 index 0000000000..7e8102a014 --- /dev/null +++ b/external/boringssl/crypto/dh/params.c @@ -0,0 +1,301 @@ +/* ==================================================================== + * Copyright (c) 2011 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include + +#include "internal.h" +#include "../bn/internal.h" + + +static const BN_ULONG dh1024_160_p[] = { + TOBN(0xDF1FB2BC, 0x2E4A4371), TOBN(0xE68CFDA7, 0x6D4DA708), + TOBN(0x45BF37DF, 0x365C1A65), TOBN(0xA151AF5F, 0x0DC8B4BD), + TOBN(0xFAA31A4F, 0xF55BCCC0), TOBN(0x4EFFD6FA, 0xE5644738), + TOBN(0x98488E9C, 0x219A7372), TOBN(0xACCBDD7D, 0x90C4BD70), + TOBN(0x24975C3C, 0xD49B83BF), TOBN(0x13ECB4AE, 0xA9061123), + TOBN(0x9838EF1E, 0x2EE652C0), TOBN(0x6073E286, 0x75A23D18), + TOBN(0x9A6A9DCA, 0x52D23B61), TOBN(0x52C99FBC, 0xFB06A3C6), + TOBN(0xDE92DE5E, 0xAE5D54EC), TOBN(0xB10B8F96, 0xA080E01D), +}; +static const BN_ULONG dh1024_160_g[] = { + TOBN(0x855E6EEB, 0x22B3B2E5), TOBN(0x858F4DCE, 0xF97C2A24), + TOBN(0x2D779D59, 0x18D08BC8), TOBN(0xD662A4D1, 0x8E73AFA3), + TOBN(0x1DBF0A01, 0x69B6A28A), TOBN(0xA6A24C08, 0x7A091F53), + TOBN(0x909D0D22, 0x63F80A76), TOBN(0xD7FBD7D3, 0xB9A92EE1), + TOBN(0x5E91547F, 0x9E2749F4), TOBN(0x160217B4, 0xB01B886A), + TOBN(0x777E690F, 0x5504F213), TOBN(0x266FEA1E, 0x5C41564B), + TOBN(0xD6406CFF, 0x14266D31), TOBN(0xF8104DD2, 0x58AC507F), + TOBN(0x6765A442, 0xEFB99905), TOBN(0xA4D1CBD5, 0xC3FD3412), +}; +static const BN_ULONG dh1024_160_q[] = { + TOBN(0x64B7CB9D, 0x49462353), TOBN(0x81A8DF27, 0x8ABA4E7D), 0xF518AA87, +}; + +static const BN_ULONG dh2048_224_p[] = { + TOBN(0x0AC4DFFE, 0x0C10E64F), TOBN(0xCF9DE538, 0x4E71B81C), + TOBN(0x7EF363E2, 0xFFA31F71), TOBN(0xE3FB73C1, 0x6B8E75B9), + TOBN(0xC9B53DCF, 0x4BA80A29), TOBN(0x23F10B0E, 0x16E79763), + TOBN(0xC52172E4, 0x13042E9B), TOBN(0xBE60E69C, 0xC928B2B9), + TOBN(0x80CD86A1, 0xB9E587E8), TOBN(0x315D75E1, 0x98C641A4), + TOBN(0xCDF93ACC, 0x44328387), TOBN(0x15987D9A, 0xDC0A486D), + TOBN(0x7310F712, 0x1FD5A074), TOBN(0x278273C7, 0xDE31EFDC), + TOBN(0x1602E714, 0x415D9330), TOBN(0x81286130, 0xBC8985DB), + TOBN(0xB3BF8A31, 0x70918836), TOBN(0x6A00E0A0, 0xB9C49708), + TOBN(0xC6BA0B2C, 0x8BBC27BE), TOBN(0xC9F98D11, 0xED34DBF6), + TOBN(0x7AD5B7D0, 0xB6C12207), TOBN(0xD91E8FEF, 0x55B7394B), + TOBN(0x9037C9ED, 0xEFDA4DF8), TOBN(0x6D3F8152, 0xAD6AC212), + TOBN(0x1DE6B85A, 0x1274A0A6), TOBN(0xEB3D688A, 0x309C180E), + TOBN(0xAF9A3C40, 0x7BA1DF15), TOBN(0xE6FA141D, 0xF95A56DB), + TOBN(0xB54B1597, 0xB61D0A75), TOBN(0xA20D64E5, 0x683B9FD1), + TOBN(0xD660FAA7, 0x9559C51F), TOBN(0xAD107E1E, 0x9123A9D0), +}; + +static const BN_ULONG dh2048_224_g[] = { + TOBN(0x84B890D3, 0x191F2BFA), TOBN(0x81BC087F, 0x2A7065B3), + TOBN(0x19C418E1, 0xF6EC0179), TOBN(0x7B5A0F1C, 0x71CFFF4C), + TOBN(0xEDFE72FE, 0x9B6AA4BD), TOBN(0x81E1BCFE, 0x94B30269), + TOBN(0x566AFBB4, 0x8D6C0191), TOBN(0xB539CCE3, 0x409D13CD), + TOBN(0x6AA21E7F, 0x5F2FF381), TOBN(0xD9E263E4, 0x770589EF), + TOBN(0x10E183ED, 0xD19963DD), TOBN(0xB70A8137, 0x150B8EEB), + TOBN(0x051AE3D4, 0x28C8F8AC), TOBN(0xBB77A86F, 0x0C1AB15B), + TOBN(0x6E3025E3, 0x16A330EF), TOBN(0x19529A45, 0xD6F83456), + TOBN(0xF180EB34, 0x118E98D1), TOBN(0xB5F6C6B2, 0x50717CBE), + TOBN(0x09939D54, 0xDA7460CD), TOBN(0xE2471504, 0x22EA1ED4), + TOBN(0xB8A762D0, 0x521BC98A), TOBN(0xF4D02727, 0x5AC1348B), + TOBN(0xC1766910, 0x1999024A), TOBN(0xBE5E9001, 0xA8D66AD7), + TOBN(0xC57DB17C, 0x620A8652), TOBN(0xAB739D77, 0x00C29F52), + TOBN(0xDD921F01, 0xA70C4AFA), TOBN(0xA6824A4E, 0x10B9A6F0), + TOBN(0x74866A08, 0xCFE4FFE3), TOBN(0x6CDEBE7B, 0x89998CAF), + TOBN(0x9DF30B5C, 0x8FFDAC50), TOBN(0xAC4032EF, 0x4F2D9AE3), +}; + +static const BN_ULONG dh2048_224_q[] = { + TOBN(0xBF389A99, 0xB36371EB), TOBN(0x1F80535A, 0x4738CEBC), + TOBN(0xC58D93FE, 0x99717710), 0x801C0D34, +}; + +static const BN_ULONG dh2048_256_p[] = { + TOBN(0xDB094AE9, 0x1E1A1597), TOBN(0x693877FA, 0xD7EF09CA), + TOBN(0x6116D227, 0x6E11715F), TOBN(0xA4B54330, 0xC198AF12), + TOBN(0x75F26375, 0xD7014103), TOBN(0xC3A3960A, 0x54E710C3), + TOBN(0xDED4010A, 0xBD0BE621), TOBN(0xC0B857F6, 0x89962856), + TOBN(0xB3CA3F79, 0x71506026), TOBN(0x1CCACB83, 0xE6B486F6), + TOBN(0x67E144E5, 0x14056425), TOBN(0xF6A167B5, 0xA41825D9), + TOBN(0x3AD83477, 0x96524D8E), TOBN(0xF13C6D9A, 0x51BFA4AB), + TOBN(0x2D525267, 0x35488A0E), TOBN(0xB63ACAE1, 0xCAA6B790), + TOBN(0x4FDB70C5, 0x81B23F76), TOBN(0xBC39A0BF, 0x12307F5C), + TOBN(0xB941F54E, 0xB1E59BB8), TOBN(0x6C5BFC11, 0xD45F9088), + TOBN(0x22E0B1EF, 0x4275BF7B), TOBN(0x91F9E672, 0x5B4758C0), + TOBN(0x5A8A9D30, 0x6BCF67ED), TOBN(0x209E0C64, 0x97517ABD), + TOBN(0x3BF4296D, 0x830E9A7C), TOBN(0x16C3D911, 0x34096FAA), + TOBN(0xFAF7DF45, 0x61B2AA30), TOBN(0xE00DF8F1, 0xD61957D4), + TOBN(0x5D2CEED4, 0x435E3B00), TOBN(0x8CEEF608, 0x660DD0F2), + TOBN(0xFFBBD19C, 0x65195999), TOBN(0x87A8E61D, 0xB4B6663C), +}; +static const BN_ULONG dh2048_256_g[] = { + TOBN(0x664B4C0F, 0x6CC41659), TOBN(0x5E2327CF, 0xEF98C582), + TOBN(0xD647D148, 0xD4795451), TOBN(0x2F630784, 0x90F00EF8), + TOBN(0x184B523D, 0x1DB246C3), TOBN(0xC7891428, 0xCDC67EB6), + TOBN(0x7FD02837, 0x0DF92B52), TOBN(0xB3353BBB, 0x64E0EC37), + TOBN(0xECD06E15, 0x57CD0915), TOBN(0xB7D2BBD2, 0xDF016199), + TOBN(0xC8484B1E, 0x052588B9), TOBN(0xDB2A3B73, 0x13D3FE14), + TOBN(0xD052B985, 0xD182EA0A), TOBN(0xA4BD1BFF, 0xE83B9C80), + TOBN(0xDFC967C1, 0xFB3F2E55), TOBN(0xB5045AF2, 0x767164E1), + TOBN(0x1D14348F, 0x6F2F9193), TOBN(0x64E67982, 0x428EBC83), + TOBN(0x8AC376D2, 0x82D6ED38), TOBN(0x777DE62A, 0xAAB8A862), + TOBN(0xDDF463E5, 0xE9EC144B), TOBN(0x0196F931, 0xC77A57F2), + TOBN(0xA55AE313, 0x41000A65), TOBN(0x901228F8, 0xC28CBB18), + TOBN(0xBC3773BF, 0x7E8C6F62), TOBN(0xBE3A6C1B, 0x0C6B47B1), + TOBN(0xFF4FED4A, 0xAC0BB555), TOBN(0x10DBC150, 0x77BE463F), + TOBN(0x07F4793A, 0x1A0BA125), TOBN(0x4CA7B18F, 0x21EF2054), + TOBN(0x2E775066, 0x60EDBD48), TOBN(0x3FB32C9B, 0x73134D0B), +}; +static const BN_ULONG dh2048_256_q[] = { + TOBN(0xA308B0FE, 0x64F5FBD3), TOBN(0x99B1A47D, 0x1EB3750B), + TOBN(0xB4479976, 0x40129DA2), TOBN(0x8CF83642, 0xA709A097), +}; + +/* dh1024_safe_prime_1 is hard-coded in Apache httpd 2.2, + * modules/ssl/ssl_engine_dh.c. */ +static const BN_ULONG dh1024_safe_prime_1[] = { + TOBN(0xE7393E0F, 0x24218EB3), TOBN(0x7DE0F4D6, 0xE2BD68B0), + TOBN(0x07DD62DB, 0x88AEAA74), TOBN(0x10EA9FCC, 0x9DDD3305), + TOBN(0xA7DBCA78, 0x74087D15), TOBN(0xDAE88600, 0x78045B07), + TOBN(0x33168A46, 0x1AAD3B72), TOBN(0xFF590137, 0x7BEDDCFD), + TOBN(0xFE324A46, 0x7A635E81), TOBN(0x5AC179BA, 0x420B2A29), + TOBN(0x13B4B4D7, 0x177E16D5), TOBN(0x849F912E, 0x639C72FB), + TOBN(0xB88174CB, 0x98BCE951), TOBN(0x0C84D239, 0xA45F520B), + TOBN(0x36D693D3, 0x4AFD0AD5), TOBN(0xD67DE440, 0xCBBBDC19), +}; + +/* dh1024_safe_prime_2 is hard-coded in nginx, + * src/event/ngx_event_openssl.c. */ +static const BN_ULONG dh1024_safe_prime_2[] = { + TOBN(0x071DF045, 0xCFE16B9B), TOBN(0x88D0F65D, 0x146757DA), + TOBN(0x4A63AB1E, 0x58FAFD49), TOBN(0x35D8CECE, 0xEF9EA027), + TOBN(0x25ECE662, 0x70CC9A50), TOBN(0xF29BA5DF, 0x81DC2CA7), + TOBN(0x8F68B076, 0xF7D36CC8), TOBN(0x60E91A92, 0xA757E304), + TOBN(0x87A2BC04, 0x9BE67780), TOBN(0xBEECA565, 0xA5FDF1D2), + TOBN(0x5CCBBAA8, 0x922614C5), TOBN(0x6C030276, 0xE710800C), + TOBN(0x08EED4EB, 0x0FB3504C), TOBN(0xD958A3F5, 0x68B42D4B), + TOBN(0x7C43FCF5, 0x80E9CFDB), TOBN(0xBBBC2DCA, 0xD8467490), +}; + +/* dh1024_safe_prime_3 is offered as a parameter by several high-traffic sites, + * including mozilla.org, as of Jan 2015. */ +static const BN_ULONG dh1024_safe_prime_3[] = { + TOBN(0x671746AE, 0x349E721B), TOBN(0x258A0655, 0xD75E93B2), + TOBN(0xD425E6FB, 0x25592EB6), TOBN(0x0C46AB04, 0xBF7CDD9A), + TOBN(0x0AD0BC99, 0x28968680), TOBN(0xF53907FB, 0xD0B7EB49), + TOBN(0x202EABB3, 0xEBC85C1D), TOBN(0x3129C693, 0x364D8C71), + TOBN(0x53728351, 0x2D46F195), TOBN(0xDF326DD6, 0x8C76CC85), + TOBN(0xF898B3F9, 0x9188E24E), TOBN(0x95EFB13C, 0x2855DFD2), + TOBN(0x1F5DAC48, 0x7B2241FE), TOBN(0x117B6BF7, 0x99A13D9F), + TOBN(0x0F97CDDA, 0x3A3468C7), TOBN(0xC9BBF5F7, 0x74A8297B)}; + +/* dh1024_safe_prime_4 is hard-coded in Apache httpd 2.0, + * modules/ssl/ssl_engine_dh.c. */ +static const BN_ULONG dh1024_safe_prime_4[] = { + TOBN(0x5085E21F, 0x0DD5C86B), TOBN(0x871538DF, 0xD823C650), + TOBN(0x125136F7, 0x262E56A8), TOBN(0x974E9EF1, 0x839EB5DB), + TOBN(0xEA9BAD99, 0x1B13A63C), TOBN(0x6044CF02, 0x3D76E05E), + TOBN(0x611EBBBE, 0x1BAC9B5C), TOBN(0x3E371D79, 0x4E5327DF), + TOBN(0x000E6EDD, 0x061CBC05), TOBN(0x2F971F3C, 0x20129B48), + TOBN(0xA6EF09C4, 0x3048D5A2), TOBN(0xFA15A259, 0xCBD523A6), + TOBN(0x2A206490, 0x4A79A770), TOBN(0x91B78182, 0x51BB055E), + TOBN(0x7CF180C3, 0xBDD4798E), TOBN(0xE6969D3D, 0x495BE32C)}; + +static const BN_ULONG bn_two_data[] = {2}; + +struct standard_parameters { + BIGNUM p, q, g; +}; + +static const struct standard_parameters dh1024_160 = { + STATIC_BIGNUM(dh1024_160_p), + STATIC_BIGNUM(dh1024_160_q), + STATIC_BIGNUM(dh1024_160_g), +}; + +static const struct standard_parameters dh2048_224 = { + STATIC_BIGNUM(dh2048_224_p), + STATIC_BIGNUM(dh2048_224_q), + STATIC_BIGNUM(dh2048_224_g), +}; + +static const struct standard_parameters dh2048_256 = { + STATIC_BIGNUM(dh2048_256_p), + STATIC_BIGNUM(dh2048_256_q), + STATIC_BIGNUM(dh2048_256_g), +}; + +static const BIGNUM dh1024_safe_prime[] = { + STATIC_BIGNUM(dh1024_safe_prime_1), + STATIC_BIGNUM(dh1024_safe_prime_2), + STATIC_BIGNUM(dh1024_safe_prime_3), + STATIC_BIGNUM(dh1024_safe_prime_4) +}; + +static BIGNUM bn_two = STATIC_BIGNUM(bn_two_data); + +static DH *get_standard_parameters(const struct standard_parameters *params, + const ENGINE *engine) { + DH *dh = DH_new(); + if (!dh) { + return NULL; + } + + dh->p = BN_dup(¶ms->p); + dh->q = BN_dup(¶ms->q); + dh->g = BN_dup(¶ms->g); + if (!dh->p || !dh->q || !dh->g) { + DH_free(dh); + return NULL; + } + + return dh; +} + +DH *DH_get_1024_160(const ENGINE *engine) { + return get_standard_parameters(&dh1024_160, engine); +} + +DH *DH_get_2048_224(const ENGINE *engine) { + return get_standard_parameters(&dh2048_224, engine); +} + +DH *DH_get_2048_256(const ENGINE *engine) { + return get_standard_parameters(&dh2048_256, engine); +} + +void DH_check_standard_parameters(DH *dh) { + unsigned i; + + if (dh->p == NULL || + dh->g == NULL || + BN_num_bytes(dh->p) != (1024 / 8) || + BN_cmp(dh->g, &bn_two) != 0) { + return; + } + + for (i = 0; i < sizeof(dh1024_safe_prime) / sizeof(dh1024_safe_prime[0]); + i++) { + if (BN_cmp(dh->p, &dh1024_safe_prime[i]) == 0) { + /* The well-known DH groups are known to have safe primes. In this case + * we can safely reduce the size of the private key. */ + dh->priv_length = 161; + break; + } + } +} diff --git a/external/boringssl/crypto/digest/CMakeLists.txt b/external/boringssl/crypto/digest/CMakeLists.txt new file mode 100644 index 0000000000..f0a0b23fd4 --- /dev/null +++ b/external/boringssl/crypto/digest/CMakeLists.txt @@ -0,0 +1,23 @@ +include_directories(../../include) + +add_library( + digest + + OBJECT + + digest.c + digests.c +) + +if(ENABLE_TESTS) +add_executable( + digest_test + + digest_test.cc + + $ +) + +target_link_libraries(digest_test crypto) +add_dependencies(all_tests digest_test) +endif() diff --git a/external/boringssl/crypto/digest/digest.c b/external/boringssl/crypto/digest/digest.c new file mode 100644 index 0000000000..fdd9fe551a --- /dev/null +++ b/external/boringssl/crypto/digest/digest.c @@ -0,0 +1,248 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +#include +#include + +#include "internal.h" + + +int EVP_MD_type(const EVP_MD *md) { return md->type; } + +uint32_t EVP_MD_flags(const EVP_MD *md) { return md->flags; } + +size_t EVP_MD_size(const EVP_MD *md) { return md->md_size; } + +size_t EVP_MD_block_size(const EVP_MD *md) { return md->block_size; } + + +void EVP_MD_CTX_init(EVP_MD_CTX *ctx) { memset(ctx, 0, sizeof(EVP_MD_CTX)); } + +EVP_MD_CTX *EVP_MD_CTX_create(void) { + EVP_MD_CTX *ctx = OPENSSL_malloc(sizeof(EVP_MD_CTX)); + + if (ctx) { + EVP_MD_CTX_init(ctx); + } + + return ctx; +} + +int EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx) { + if (ctx->digest && ctx->digest->ctx_size && ctx->md_data) { + OPENSSL_cleanse(ctx->md_data, ctx->digest->ctx_size); + OPENSSL_free(ctx->md_data); + } + + assert(ctx->pctx == NULL || ctx->pctx_ops != NULL); + if (ctx->pctx_ops) { + ctx->pctx_ops->free(ctx->pctx); + } + + EVP_MD_CTX_init(ctx); + + return 1; +} + +void EVP_MD_CTX_destroy(EVP_MD_CTX *ctx) { + if (!ctx) { + return; + } + + EVP_MD_CTX_cleanup(ctx); + OPENSSL_free(ctx); +} + +int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in) { + uint8_t *tmp_buf = NULL; + + if (in == NULL || in->digest == NULL) { + OPENSSL_PUT_ERROR(DIGEST, DIGEST_R_INPUT_NOT_INITIALIZED); + return 0; + } + + if (out->digest == in->digest) { + /* |md_data| will be the correct size in this case so it's removed from + * |out| at this point so that |EVP_MD_CTX_cleanup| doesn't free it and + * then it's reused. */ + tmp_buf = out->md_data; + out->md_data = NULL; + } + + EVP_MD_CTX_cleanup(out); + + out->digest = in->digest; + if (in->md_data && in->digest->ctx_size) { + if (tmp_buf) { + out->md_data = tmp_buf; + } else { + out->md_data = OPENSSL_malloc(in->digest->ctx_size); + if (!out->md_data) { + OPENSSL_PUT_ERROR(DIGEST, ERR_R_MALLOC_FAILURE); + return 0; + } + } + memcpy(out->md_data, in->md_data, in->digest->ctx_size); + } + + assert(in->pctx == NULL || in->pctx_ops != NULL); + out->pctx_ops = in->pctx_ops; + if (in->pctx && in->pctx_ops) { + out->pctx = in->pctx_ops->dup(in->pctx); + if (!out->pctx) { + EVP_MD_CTX_cleanup(out); + return 0; + } + } + + return 1; +} + +int EVP_MD_CTX_copy(EVP_MD_CTX *out, const EVP_MD_CTX *in) { + EVP_MD_CTX_init(out); + return EVP_MD_CTX_copy_ex(out, in); +} + +int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *engine) { + if (ctx->digest != type) { + if (ctx->digest && ctx->digest->ctx_size > 0) { + OPENSSL_free(ctx->md_data); + ctx->md_data = NULL; + } + ctx->digest = type; + if (type->ctx_size > 0) { + ctx->md_data = OPENSSL_malloc(type->ctx_size); + if (ctx->md_data == NULL) { + OPENSSL_PUT_ERROR(DIGEST, ERR_R_MALLOC_FAILURE); + return 0; + } + } + } + + assert(ctx->pctx == NULL || ctx->pctx_ops != NULL); + + ctx->digest->init(ctx); + return 1; +} + +int EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type) { + EVP_MD_CTX_init(ctx); + return EVP_DigestInit_ex(ctx, type, NULL); +} + +int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *data, size_t len) { + ctx->digest->update(ctx, data, len); + return 1; +} + +int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, uint8_t *md_out, unsigned int *size) { + assert(ctx->digest->md_size <= EVP_MAX_MD_SIZE); + ctx->digest->final(ctx, md_out); + if (size != NULL) { + *size = ctx->digest->md_size; + } + OPENSSL_cleanse(ctx->md_data, ctx->digest->ctx_size); + return 1; +} + +int EVP_DigestFinal(EVP_MD_CTX *ctx, uint8_t *md, unsigned int *size) { + (void)EVP_DigestFinal_ex(ctx, md, size); + EVP_MD_CTX_cleanup(ctx); + return 1; +} + +int EVP_Digest(const void *data, size_t count, uint8_t *out_md, + unsigned int *out_size, const EVP_MD *type, ENGINE *impl) { + EVP_MD_CTX ctx; + int ret; + + EVP_MD_CTX_init(&ctx); + ret = EVP_DigestInit_ex(&ctx, type, impl) && + EVP_DigestUpdate(&ctx, data, count) && + EVP_DigestFinal_ex(&ctx, out_md, out_size); + EVP_MD_CTX_cleanup(&ctx); + + return ret; +} + + +const EVP_MD *EVP_MD_CTX_md(const EVP_MD_CTX *ctx) { + if (ctx == NULL) { + return NULL; + } + return ctx->digest; +} + +size_t EVP_MD_CTX_size(const EVP_MD_CTX *ctx) { + return EVP_MD_size(EVP_MD_CTX_md(ctx)); +} + +size_t EVP_MD_CTX_block_size(const EVP_MD_CTX *ctx) { + return EVP_MD_block_size(EVP_MD_CTX_md(ctx)); +} + +int EVP_MD_CTX_type(const EVP_MD_CTX *ctx) { + return EVP_MD_type(EVP_MD_CTX_md(ctx)); +} + +int EVP_add_digest(const EVP_MD *digest) { + return 1; +} diff --git a/external/boringssl/crypto/digest/digest_test.cc b/external/boringssl/crypto/digest/digest_test.cc new file mode 100644 index 0000000000..39ceaffcd8 --- /dev/null +++ b/external/boringssl/crypto/digest/digest_test.cc @@ -0,0 +1,262 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "../test/scoped_types.h" + + +struct MD { + // name is the name of the digest. + const char* name; + // md_func is the digest to test. + const EVP_MD *(*func)(void); + // one_shot_func is the convenience one-shot version of the + // digest. + uint8_t *(*one_shot_func)(const uint8_t *, size_t, uint8_t *); +}; + +static const MD md4 = { "MD4", &EVP_md4, nullptr }; +static const MD md5 = { "MD5", &EVP_md5, &MD5 }; +static const MD sha1 = { "SHA1", &EVP_sha1, &SHA1 }; +static const MD sha224 = { "SHA224", &EVP_sha224, &SHA224 }; +static const MD sha256 = { "SHA256", &EVP_sha256, &SHA256 }; +static const MD sha384 = { "SHA384", &EVP_sha384, &SHA384 }; +static const MD sha512 = { "SHA512", &EVP_sha512, &SHA512 }; +static const MD md5_sha1 = { "MD5-SHA1", &EVP_md5_sha1, nullptr }; + +struct TestVector { + // md is the digest to test. + const MD &md; + // input is a NUL-terminated string to hash. + const char *input; + // repeat is the number of times to repeat input. + size_t repeat; + // expected_hex is the expected digest in hexadecimal. + const char *expected_hex; +}; + +static const TestVector kTestVectors[] = { + // MD4 tests, from RFC 1320. (crypto/md4 does not provide a + // one-shot MD4 function.) + { md4, "", 1, "31d6cfe0d16ae931b73c59d7e0c089c0" }, + { md4, "a", 1, "bde52cb31de33e46245e05fbdbd6fb24" }, + { md4, "abc", 1, "a448017aaf21d8525fc10ae87aa6729d" }, + { md4, "message digest", 1, "d9130a8164549fe818874806e1c7014b" }, + { md4, "abcdefghijklmnopqrstuvwxyz", 1, + "d79e1c308aa5bbcdeea8ed63df412da9" }, + { md4, + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 1, + "043f8582f241db351ce627e153e7f0e4" }, + { md4, "1234567890", 8, "e33b4ddc9c38f2199c3e7b164fcc0536" }, + + // MD5 tests, from RFC 1321. + { md5, "", 1, "d41d8cd98f00b204e9800998ecf8427e" }, + { md5, "a", 1, "0cc175b9c0f1b6a831c399e269772661" }, + { md5, "abc", 1, "900150983cd24fb0d6963f7d28e17f72" }, + { md5, "message digest", 1, "f96b697d7cb7938d525a2f31aaf161d0" }, + { md5, "abcdefghijklmnopqrstuvwxyz", 1, + "c3fcd3d76192e4007dfb496cca67e13b" }, + { md5, + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 1, + "d174ab98d277d9f5a5611c2c9f419d9f" }, + { md5, "1234567890", 8, "57edf4a22be3c955ac49da2e2107b67a" }, + + // SHA-1 tests, from RFC 3174. + { sha1, "abc", 1, "a9993e364706816aba3e25717850c26c9cd0d89d" }, + { sha1, + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 1, + "84983e441c3bd26ebaae4aa1f95129e5e54670f1" }, + { sha1, "a", 1000000, "34aa973cd4c4daa4f61eeb2bdbad27316534016f" }, + { sha1, + "0123456701234567012345670123456701234567012345670123456701234567", 10, + "dea356a2cddd90c7a7ecedc5ebb563934f460452" }, + + // SHA-224 tests, from RFC 3874. + { sha224, "abc", 1, + "23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7" }, + { sha224, + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 1, + "75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525" }, + { sha224, + "a", 1000000, + "20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67" }, + + // SHA-256 tests, from NIST. + { sha256, "abc", 1, + "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" }, + { sha256, + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 1, + "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1" }, + + // SHA-384 tests, from NIST. + { sha384, "abc", 1, + "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed" + "8086072ba1e7cc2358baeca134c825a7" }, + { sha384, + "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" + "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 1, + "09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712" + "fcc7c71a557e2db966c3e9fa91746039" }, + + // SHA-512 tests, from NIST. + { sha512, "abc", 1, + "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a" + "2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f" }, + { sha512, + "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" + "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 1, + "8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018" + "501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909" }, + + // MD5-SHA1 tests. + { md5_sha1, "abc", 1, + "900150983cd24fb0d6963f7d28e17f72a9993e364706816aba3e25717850c26c9cd0d89d" }, +}; + +static bool CompareDigest(const TestVector *test, + const uint8_t *digest, + size_t digest_len) { + static const char kHexTable[] = "0123456789abcdef"; + size_t i; + char digest_hex[2*EVP_MAX_MD_SIZE + 1]; + + for (i = 0; i < digest_len; i++) { + digest_hex[2*i] = kHexTable[digest[i] >> 4]; + digest_hex[2*i + 1] = kHexTable[digest[i] & 0xf]; + } + digest_hex[2*digest_len] = '\0'; + + if (strcmp(digest_hex, test->expected_hex) != 0) { + fprintf(stderr, "%s(\"%s\" * %d) = %s; want %s\n", + test->md.name, test->input, (int)test->repeat, + digest_hex, test->expected_hex); + return false; + } + + return true; +} + +static int TestDigest(const TestVector *test) { + ScopedEVP_MD_CTX ctx; + + // Test the input provided. + if (!EVP_DigestInit_ex(ctx.get(), test->md.func(), NULL)) { + fprintf(stderr, "EVP_DigestInit_ex failed\n"); + return false; + } + for (size_t i = 0; i < test->repeat; i++) { + if (!EVP_DigestUpdate(ctx.get(), test->input, strlen(test->input))) { + fprintf(stderr, "EVP_DigestUpdate failed\n"); + return false; + } + } + uint8_t digest[EVP_MAX_MD_SIZE]; + unsigned digest_len; + if (!EVP_DigestFinal_ex(ctx.get(), digest, &digest_len)) { + fprintf(stderr, "EVP_DigestFinal_ex failed\n"); + return false; + } + if (!CompareDigest(test, digest, digest_len)) { + return false; + } + + // Test the input one character at a time. + if (!EVP_DigestInit_ex(ctx.get(), test->md.func(), NULL)) { + fprintf(stderr, "EVP_DigestInit_ex failed\n"); + return false; + } + if (!EVP_DigestUpdate(ctx.get(), NULL, 0)) { + fprintf(stderr, "EVP_DigestUpdate failed\n"); + return false; + } + for (size_t i = 0; i < test->repeat; i++) { + for (const char *p = test->input; *p; p++) { + if (!EVP_DigestUpdate(ctx.get(), p, 1)) { + fprintf(stderr, "EVP_DigestUpdate failed\n"); + return false; + } + } + } + if (!EVP_DigestFinal_ex(ctx.get(), digest, &digest_len)) { + fprintf(stderr, "EVP_DigestFinal_ex failed\n"); + return false; + } + if (digest_len != EVP_MD_size(test->md.func())) { + fprintf(stderr, "EVP_MD_size output incorrect\n"); + return false; + } + if (!CompareDigest(test, digest, digest_len)) { + return false; + } + + // Test the one-shot function. + if (test->md.one_shot_func && test->repeat == 1) { + uint8_t *out = test->md.one_shot_func((const uint8_t *)test->input, + strlen(test->input), digest); + if (out != digest) { + fprintf(stderr, "one_shot_func gave incorrect return\n"); + return false; + } + if (!CompareDigest(test, digest, EVP_MD_size(test->md.func()))) { + return false; + } + + // Test the deprecated static buffer variant, until it's removed. + out = test->md.one_shot_func((const uint8_t *)test->input, + strlen(test->input), NULL); + if (!CompareDigest(test, out, EVP_MD_size(test->md.func()))) { + return false; + } + } + + return true; +} + +static int TestGetters() { + if (EVP_get_digestbyname("RSA-SHA512") == NULL || + EVP_get_digestbyname("sha512WithRSAEncryption") == NULL || + EVP_get_digestbyname("nonsense") != NULL) { + return false; + } + + return true; +} + +int main(void) { + CRYPTO_library_init(); + + for (size_t i = 0; i < sizeof(kTestVectors) / sizeof(kTestVectors[0]); i++) { + if (!TestDigest(&kTestVectors[i])) { + fprintf(stderr, "Test %d failed\n", (int)i); + return 1; + } + } + + if (!TestGetters()) { + return 1; + } + + printf("PASS\n"); + return 0; +} diff --git a/external/boringssl/crypto/digest/digests.c b/external/boringssl/crypto/digest/digests.c new file mode 100644 index 0000000000..3307f2656c --- /dev/null +++ b/external/boringssl/crypto/digest/digests.c @@ -0,0 +1,321 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +#include +#include +#include +#include + +#include "internal.h" + +#if defined(NDEBUG) +#define CHECK(x) (void) (x) +#else +#define CHECK(x) assert(x) +#endif + + +static void md4_init(EVP_MD_CTX *ctx) { + CHECK(MD4_Init(ctx->md_data)); +} + +static void md4_update(EVP_MD_CTX *ctx, const void *data, size_t count) { + CHECK(MD4_Update(ctx->md_data, data, count)); +} + +static void md4_final(EVP_MD_CTX *ctx, uint8_t *out) { + CHECK(MD4_Final(out, ctx->md_data)); +} + +static const EVP_MD md4_md = { + NID_md4, MD4_DIGEST_LENGTH, 0 /* flags */, md4_init, + md4_update, md4_final, 64 /* block size */, sizeof(MD4_CTX), +}; + +const EVP_MD *EVP_md4(void) { return &md4_md; } + + +static void md5_init(EVP_MD_CTX *ctx) { + CHECK(MD5_Init(ctx->md_data)); +} + +static void md5_update(EVP_MD_CTX *ctx, const void *data, size_t count) { + CHECK(MD5_Update(ctx->md_data, data, count)); +} + +static void md5_final(EVP_MD_CTX *ctx, uint8_t *out) { + CHECK(MD5_Final(out, ctx->md_data)); +} + +static const EVP_MD md5_md = { + NID_md5, MD5_DIGEST_LENGTH, 0 /* flags */, md5_init, + md5_update, md5_final, 64 /* block size */, sizeof(MD5_CTX), +}; + +const EVP_MD *EVP_md5(void) { return &md5_md; } + + +static void sha1_init(EVP_MD_CTX *ctx) { + CHECK(SHA1_Init(ctx->md_data)); +} + +static void sha1_update(EVP_MD_CTX *ctx, const void *data, size_t count) { + CHECK(SHA1_Update(ctx->md_data, data, count)); +} + +static void sha1_final(EVP_MD_CTX *ctx, uint8_t *md) { + CHECK(SHA1_Final(md, ctx->md_data)); +} + +static const EVP_MD sha1_md = { + NID_sha1, SHA_DIGEST_LENGTH, 0 /* flags */, sha1_init, + sha1_update, sha1_final, 64 /* block size */, sizeof(SHA_CTX), +}; + +const EVP_MD *EVP_sha1(void) { return &sha1_md; } + + +static void sha224_init(EVP_MD_CTX *ctx) { + CHECK(SHA224_Init(ctx->md_data)); +} + +static void sha224_update(EVP_MD_CTX *ctx, const void *data, size_t count) { + CHECK(SHA224_Update(ctx->md_data, data, count)); +} + +static void sha224_final(EVP_MD_CTX *ctx, uint8_t *md) { + CHECK(SHA224_Final(md, ctx->md_data)); +} + +static const EVP_MD sha224_md = { + NID_sha224, SHA224_DIGEST_LENGTH, 0 /* flags */, + sha224_init, sha224_update, sha224_final, + 64 /* block size */, sizeof(SHA256_CTX), +}; + +const EVP_MD *EVP_sha224(void) { return &sha224_md; } + + +static void sha256_init(EVP_MD_CTX *ctx) { + CHECK(SHA256_Init(ctx->md_data)); +} + +static void sha256_update(EVP_MD_CTX *ctx, const void *data, size_t count) { + CHECK(SHA256_Update(ctx->md_data, data, count)); +} + +static void sha256_final(EVP_MD_CTX *ctx, uint8_t *md) { + CHECK(SHA256_Final(md, ctx->md_data)); +} + +static const EVP_MD sha256_md = { + NID_sha256, SHA256_DIGEST_LENGTH, 0 /* flags */, + sha256_init, sha256_update, sha256_final, + 64 /* block size */, sizeof(SHA256_CTX), +}; + +const EVP_MD *EVP_sha256(void) { return &sha256_md; } + + +static void sha384_init(EVP_MD_CTX *ctx) { + CHECK(SHA384_Init(ctx->md_data)); +} + +static void sha384_update(EVP_MD_CTX *ctx, const void *data, size_t count) { + CHECK(SHA384_Update(ctx->md_data, data, count)); +} + +static void sha384_final(EVP_MD_CTX *ctx, uint8_t *md) { + CHECK(SHA384_Final(md, ctx->md_data)); +} + +static const EVP_MD sha384_md = { + NID_sha384, SHA384_DIGEST_LENGTH, 0 /* flags */, + sha384_init, sha384_update, sha384_final, + 128 /* block size */, sizeof(SHA512_CTX), +}; + +const EVP_MD *EVP_sha384(void) { return &sha384_md; } + + +static void sha512_init(EVP_MD_CTX *ctx) { + CHECK(SHA512_Init(ctx->md_data)); +} + +static void sha512_update(EVP_MD_CTX *ctx, const void *data, size_t count) { + CHECK(SHA512_Update(ctx->md_data, data, count)); +} + +static void sha512_final(EVP_MD_CTX *ctx, uint8_t *md) { + CHECK(SHA512_Final(md, ctx->md_data)); +} + +static const EVP_MD sha512_md = { + NID_sha512, SHA512_DIGEST_LENGTH, 0 /* flags */, + sha512_init, sha512_update, sha512_final, + 128 /* block size */, sizeof(SHA512_CTX), +}; + +const EVP_MD *EVP_sha512(void) { return &sha512_md; } + + +typedef struct { + MD5_CTX md5; + SHA_CTX sha1; +} MD5_SHA1_CTX; + +static void md5_sha1_init(EVP_MD_CTX *md_ctx) { + MD5_SHA1_CTX *ctx = md_ctx->md_data; + CHECK(MD5_Init(&ctx->md5) && SHA1_Init(&ctx->sha1)); +} + +static void md5_sha1_update(EVP_MD_CTX *md_ctx, const void *data, + size_t count) { + MD5_SHA1_CTX *ctx = md_ctx->md_data; + CHECK(MD5_Update(&ctx->md5, data, count) && + SHA1_Update(&ctx->sha1, data, count)); +} + +static void md5_sha1_final(EVP_MD_CTX *md_ctx, uint8_t *out) { + MD5_SHA1_CTX *ctx = md_ctx->md_data; + CHECK(MD5_Final(out, &ctx->md5) && + SHA1_Final(out + MD5_DIGEST_LENGTH, &ctx->sha1)); +} + +static const EVP_MD md5_sha1_md = { + NID_md5_sha1, + MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH, + 0 /* flags */, + md5_sha1_init, + md5_sha1_update, + md5_sha1_final, + 64 /* block size */, + sizeof(MD5_SHA1_CTX), +}; + +const EVP_MD *EVP_md5_sha1(void) { return &md5_sha1_md; } + + +struct nid_to_digest { + int nid; + const EVP_MD* (*md_func)(void); + const char *short_name; + const char *long_name; +}; + +static const struct nid_to_digest nid_to_digest_mapping[] = { + { NID_md4, EVP_md4, SN_md4, LN_md4 }, + { NID_md5, EVP_md5, SN_md5, LN_md5 }, + { NID_sha1, EVP_sha1, SN_sha1, LN_sha1 }, + { NID_sha224, EVP_sha224, SN_sha224, LN_sha224 }, + { NID_sha256, EVP_sha256, SN_sha256, LN_sha256 }, + { NID_sha384, EVP_sha384, SN_sha384, LN_sha384 }, + { NID_sha512, EVP_sha512, SN_sha512, LN_sha512 }, + { NID_md5_sha1, EVP_md5_sha1, SN_md5_sha1, LN_md5_sha1 }, + { NID_dsaWithSHA, EVP_sha1, SN_dsaWithSHA, LN_dsaWithSHA }, + { NID_dsaWithSHA1, EVP_sha1, SN_dsaWithSHA1, LN_dsaWithSHA1 }, + { NID_ecdsa_with_SHA1, EVP_sha1, SN_ecdsa_with_SHA1, NULL }, + { NID_md5WithRSAEncryption, EVP_md5, SN_md5WithRSAEncryption, + LN_md5WithRSAEncryption }, + { NID_sha1WithRSAEncryption, EVP_sha1, SN_sha1WithRSAEncryption, + LN_sha1WithRSAEncryption }, + { NID_sha224WithRSAEncryption, EVP_sha224, SN_sha224WithRSAEncryption, + LN_sha224WithRSAEncryption }, + { NID_sha256WithRSAEncryption, EVP_sha256, SN_sha256WithRSAEncryption, + LN_sha256WithRSAEncryption }, + { NID_sha384WithRSAEncryption, EVP_sha384, SN_sha384WithRSAEncryption, + LN_sha384WithRSAEncryption }, + { NID_sha512WithRSAEncryption, EVP_sha512, SN_sha512WithRSAEncryption, + LN_sha512WithRSAEncryption }, +}; + +const EVP_MD* EVP_get_digestbynid(int nid) { + unsigned i; + + for (i = 0; i < sizeof(nid_to_digest_mapping) / sizeof(struct nid_to_digest); + i++) { + if (nid_to_digest_mapping[i].nid == nid) { + return nid_to_digest_mapping[i].md_func(); + } + } + + return NULL; +} + +const EVP_MD* EVP_get_digestbyobj(const ASN1_OBJECT *obj) { + return EVP_get_digestbynid(OBJ_obj2nid(obj)); +} + +const EVP_MD *EVP_get_digestbyname(const char *name) { + unsigned i; + + for (i = 0; i < sizeof(nid_to_digest_mapping) / sizeof(struct nid_to_digest); + i++) { + const char *short_name = nid_to_digest_mapping[i].short_name; + const char *long_name = nid_to_digest_mapping[i].long_name; + if ((short_name && strcmp(short_name, name) == 0) || + (long_name && strcmp(long_name, name) == 0)) { + return nid_to_digest_mapping[i].md_func(); + } + } + + return NULL; +} diff --git a/external/boringssl/crypto/digest/internal.h b/external/boringssl/crypto/digest/internal.h new file mode 100644 index 0000000000..e3d812ad8c --- /dev/null +++ b/external/boringssl/crypto/digest/internal.h @@ -0,0 +1,112 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_DIGEST_INTERNAL_H +#define OPENSSL_HEADER_DIGEST_INTERNAL_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +struct env_md_st { + /* type contains a NID identifing the digest function. (For example, + * NID_md5.) */ + int type; + + /* md_size contains the size, in bytes, of the resulting digest. */ + unsigned md_size; + + /* flags contains the OR of |EVP_MD_FLAG_*| values. */ + uint32_t flags; + + /* init initialises the state in |ctx->md_data|. */ + void (*init)(EVP_MD_CTX *ctx); + + /* update hashes |len| bytes of |data| into the state in |ctx->md_data|. */ + void (*update)(EVP_MD_CTX *ctx, const void *data, size_t count); + + /* final completes the hash and writes |md_size| bytes of digest to |out|. */ + void (*final)(EVP_MD_CTX *ctx, uint8_t *out); + + /* block_size contains the hash's native block size. */ + unsigned block_size; + + /* ctx_size contains the size, in bytes, of the state of the hash function. */ + unsigned ctx_size; +}; + +/* evp_md_pctx_ops contains function pointers to allow the |pctx| member of + * |EVP_MD_CTX| to be manipulated without breaking layering by calling EVP + * functions. */ +struct evp_md_pctx_ops { + /* free is called when an |EVP_MD_CTX| is being freed and the |pctx| also + * needs to be freed. */ + void (*free) (EVP_PKEY_CTX *pctx); + + /* dup is called when an |EVP_MD_CTX| is copied and so the |pctx| also needs + * to be copied. */ + EVP_PKEY_CTX* (*dup) (EVP_PKEY_CTX *pctx); +}; + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_DIGEST_INTERNAL */ diff --git a/external/boringssl/crypto/digest/md32_common.h b/external/boringssl/crypto/digest/md32_common.h new file mode 100644 index 0000000000..4cf050caec --- /dev/null +++ b/external/boringssl/crypto/digest/md32_common.h @@ -0,0 +1,262 @@ +/* ==================================================================== + * Copyright (c) 1999-2007 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== */ + +#ifndef OPENSSL_HEADER_MD32_COMMON_H +#define OPENSSL_HEADER_MD32_COMMON_H + +#include + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* This is a generic 32-bit "collector" for message digest algorithms. It + * collects input character stream into chunks of 32-bit values and invokes the + * block function that performs the actual hash calculations. To make use of + * this mechanism, the following macros must be defined before including + * md32_common.h. + * + * One of |DATA_ORDER_IS_BIG_ENDIAN| or |DATA_ORDER_IS_LITTLE_ENDIAN| must be + * defined to specify the byte order of the input stream. + * + * |HASH_CBLOCK| must be defined as the integer block size, in bytes. + * + * |HASH_CTX| must be defined as the name of the context structure, which must + * have at least the following members: + * + * typedef struct _state_st { + * uint32_t h[ / sizeof(uint32_t)]; + * uint32_t Nl, Nh; + * uint8_t data[HASH_CBLOCK]; + * unsigned num; + * ... + * } _CTX; + * + * is the output length of the hash in bytes, before + * any truncation (e.g. 64 for SHA-224 and SHA-256, 128 for SHA-384 and + * SHA-512). + * + * |HASH_UPDATE| must be defined as the name of the "Update" function to + * generate. + * + * |HASH_TRANSFORM| must be defined as the the name of the "Transform" + * function to generate. + * + * |HASH_FINAL| must be defined as the name of "Final" function to generate. + * + * |HASH_BLOCK_DATA_ORDER| must be defined as the name of the "Block" function. + * That function must be implemented manually. It must be capable of operating + * on *unaligned* input data in its original (data) byte order. It must have + * this signature: + * + * void HASH_BLOCK_DATA_ORDER(uint32_t *state, const uint8_t *data, + * size_t num); + * + * It must update the hash state |state| with |num| blocks of data from |data|, + * where each block is |HASH_CBLOCK| bytes; i.e. |data| points to a array of + * |HASH_CBLOCK * num| bytes. |state| points to the |h| member of a |HASH_CTX|, + * and so will have | / sizeof(uint32_t)| elements. + * + * |HASH_MAKE_STRING(c, s)| must be defined as a block statement that converts + * the hash state |c->h| into the output byte order, storing the result in |s|. + */ + +#if !defined(DATA_ORDER_IS_BIG_ENDIAN) && !defined(DATA_ORDER_IS_LITTLE_ENDIAN) +#error "DATA_ORDER must be defined!" +#endif + +#ifndef HASH_CBLOCK +#error "HASH_CBLOCK must be defined!" +#endif +#ifndef HASH_CTX +#error "HASH_CTX must be defined!" +#endif + +#ifndef HASH_UPDATE +#error "HASH_UPDATE must be defined!" +#endif +#ifndef HASH_TRANSFORM +#error "HASH_TRANSFORM must be defined!" +#endif +#ifndef HASH_FINAL +#error "HASH_FINAL must be defined!" +#endif + +#ifndef HASH_BLOCK_DATA_ORDER +#error "HASH_BLOCK_DATA_ORDER must be defined!" +#endif + +#ifndef HASH_MAKE_STRING +#error "HASH_MAKE_STRING must be defined!" +#endif + +#if defined(DATA_ORDER_IS_BIG_ENDIAN) + +#define HOST_c2l(c, l) \ + (void)(l = (((uint32_t)(*((c)++))) << 24), \ + l |= (((uint32_t)(*((c)++))) << 16), \ + l |= (((uint32_t)(*((c)++))) << 8), l |= (((uint32_t)(*((c)++))))) + +#define HOST_l2c(l, c) \ + (void)(*((c)++) = (uint8_t)(((l) >> 24) & 0xff), \ + *((c)++) = (uint8_t)(((l) >> 16) & 0xff), \ + *((c)++) = (uint8_t)(((l) >> 8) & 0xff), \ + *((c)++) = (uint8_t)(((l)) & 0xff)) + +#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN) + +#define HOST_c2l(c, l) \ + (void)(l = (((uint32_t)(*((c)++)))), l |= (((uint32_t)(*((c)++))) << 8), \ + l |= (((uint32_t)(*((c)++))) << 16), \ + l |= (((uint32_t)(*((c)++))) << 24)) + +#define HOST_l2c(l, c) \ + (void)(*((c)++) = (uint8_t)(((l)) & 0xff), \ + *((c)++) = (uint8_t)(((l) >> 8) & 0xff), \ + *((c)++) = (uint8_t)(((l) >> 16) & 0xff), \ + *((c)++) = (uint8_t)(((l) >> 24) & 0xff)) + +#endif /* DATA_ORDER */ + +int HASH_UPDATE(HASH_CTX *c, const void *data_, size_t len) { + const uint8_t *data = data_; + + if (len == 0) { + return 1; + } + + uint32_t l = c->Nl + (((uint32_t)len) << 3); + if (l < c->Nl) { + /* Handle carries. */ + c->Nh++; + } + c->Nh += (uint32_t)(len >> 29); + c->Nl = l; + + size_t n = c->num; + if (n != 0) { + if (len >= HASH_CBLOCK || len + n >= HASH_CBLOCK) { + memcpy(c->data + n, data, HASH_CBLOCK - n); + HASH_BLOCK_DATA_ORDER(c->h, c->data, 1); + n = HASH_CBLOCK - n; + data += n; + len -= n; + c->num = 0; + /* Keep |c->data| zeroed when unused. */ + memset(c->data, 0, HASH_CBLOCK); + } else { + memcpy(c->data + n, data, len); + c->num += (unsigned)len; + return 1; + } + } + + n = len / HASH_CBLOCK; + if (n > 0) { + HASH_BLOCK_DATA_ORDER(c->h, data, n); + n *= HASH_CBLOCK; + data += n; + len -= n; + } + + if (len != 0) { + c->num = (unsigned)len; + memcpy(c->data, data, len); + } + return 1; +} + + +void HASH_TRANSFORM(HASH_CTX *c, const uint8_t *data) { + HASH_BLOCK_DATA_ORDER(c->h, data, 1); +} + + +int HASH_FINAL(uint8_t *md, HASH_CTX *c) { + /* |c->data| always has room for at least one byte. A full block would have + * been consumed. */ + size_t n = c->num; + assert(n < HASH_CBLOCK); + c->data[n] = 0x80; + n++; + + /* Fill the block with zeros if there isn't room for a 64-bit length. */ + if (n > (HASH_CBLOCK - 8)) { + memset(c->data + n, 0, HASH_CBLOCK - n); + n = 0; + HASH_BLOCK_DATA_ORDER(c->h, c->data, 1); + } + memset(c->data + n, 0, HASH_CBLOCK - 8 - n); + + /* Append a 64-bit length to the block and process it. */ + uint8_t *p = c->data + HASH_CBLOCK - 8; +#if defined(DATA_ORDER_IS_BIG_ENDIAN) + HOST_l2c(c->Nh, p); + HOST_l2c(c->Nl, p); +#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN) + HOST_l2c(c->Nl, p); + HOST_l2c(c->Nh, p); +#endif + assert(p == c->data + HASH_CBLOCK); + HASH_BLOCK_DATA_ORDER(c->h, c->data, 1); + c->num = 0; + memset(c->data, 0, HASH_CBLOCK); + + HASH_MAKE_STRING(c, md); + return 1; +} + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_MD32_COMMON_H */ diff --git a/external/boringssl/crypto/dsa/CMakeLists.txt b/external/boringssl/crypto/dsa/CMakeLists.txt new file mode 100644 index 0000000000..3cb7c349b1 --- /dev/null +++ b/external/boringssl/crypto/dsa/CMakeLists.txt @@ -0,0 +1,23 @@ +include_directories(../../include) + +add_library( + dsa + + OBJECT + + dsa.c + dsa_asn1.c +) + +if(ENABLE_TESTS) +add_executable( + dsa_test + + dsa_test.c + + $ +) + +target_link_libraries(dsa_test crypto) +add_dependencies(all_tests dsa_test) +endif() diff --git a/external/boringssl/crypto/dsa/dsa.c b/external/boringssl/crypto/dsa/dsa.c new file mode 100644 index 0000000000..1de0071e38 --- /dev/null +++ b/external/boringssl/crypto/dsa/dsa.c @@ -0,0 +1,933 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + * + * The DSS routines are based on patches supplied by + * Steven Schoch . */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../internal.h" + + +#define OPENSSL_DSA_MAX_MODULUS_BITS 10000 + +/* Primality test according to FIPS PUB 186[-1], Appendix 2.1: 50 rounds of + * Rabin-Miller */ +#define DSS_prime_checks 50 + +static CRYPTO_EX_DATA_CLASS g_ex_data_class = CRYPTO_EX_DATA_CLASS_INIT; + +DSA *DSA_new(void) { + DSA *dsa = OPENSSL_malloc(sizeof(DSA)); + if (dsa == NULL) { + OPENSSL_PUT_ERROR(DSA, ERR_R_MALLOC_FAILURE); + return NULL; + } + + memset(dsa, 0, sizeof(DSA)); + + dsa->references = 1; + + CRYPTO_MUTEX_init(&dsa->method_mont_p_lock); + CRYPTO_new_ex_data(&dsa->ex_data); + + return dsa; +} + +void DSA_free(DSA *dsa) { + if (dsa == NULL) { + return; + } + + if (!CRYPTO_refcount_dec_and_test_zero(&dsa->references)) { + return; + } + + CRYPTO_free_ex_data(&g_ex_data_class, dsa, &dsa->ex_data); + + BN_clear_free(dsa->p); + BN_clear_free(dsa->q); + BN_clear_free(dsa->g); + BN_clear_free(dsa->pub_key); + BN_clear_free(dsa->priv_key); + BN_clear_free(dsa->kinv); + BN_clear_free(dsa->r); + BN_MONT_CTX_free(dsa->method_mont_p); + CRYPTO_MUTEX_cleanup(&dsa->method_mont_p_lock); + OPENSSL_free(dsa); +} + +int DSA_up_ref(DSA *dsa) { + CRYPTO_refcount_inc(&dsa->references); + return 1; +} + +int DSA_generate_parameters_ex(DSA *dsa, unsigned bits, const uint8_t *seed_in, + size_t seed_len, int *out_counter, + unsigned long *out_h, BN_GENCB *cb) { + int ok = 0; + unsigned char seed[SHA256_DIGEST_LENGTH]; + unsigned char md[SHA256_DIGEST_LENGTH]; + unsigned char buf[SHA256_DIGEST_LENGTH], buf2[SHA256_DIGEST_LENGTH]; + BIGNUM *r0, *W, *X, *c, *test; + BIGNUM *g = NULL, *q = NULL, *p = NULL; + BN_MONT_CTX *mont = NULL; + int k, n = 0, m = 0; + unsigned i; + int counter = 0; + int r = 0; + BN_CTX *ctx = NULL; + unsigned int h = 2; + unsigned qsize; + const EVP_MD *evpmd; + + evpmd = (bits >= 2048) ? EVP_sha256() : EVP_sha1(); + qsize = EVP_MD_size(evpmd); + + if (bits < 512) { + bits = 512; + } + + bits = (bits + 63) / 64 * 64; + + if (seed_in != NULL) { + if (seed_len < (size_t)qsize) { + return 0; + } + if (seed_len > (size_t)qsize) { + /* Only consume as much seed as is expected. */ + seed_len = qsize; + } + memcpy(seed, seed_in, seed_len); + } + + ctx = BN_CTX_new(); + if (ctx == NULL) { + goto err; + } + BN_CTX_start(ctx); + + mont = BN_MONT_CTX_new(); + if (mont == NULL) { + goto err; + } + + r0 = BN_CTX_get(ctx); + g = BN_CTX_get(ctx); + W = BN_CTX_get(ctx); + q = BN_CTX_get(ctx); + X = BN_CTX_get(ctx); + c = BN_CTX_get(ctx); + p = BN_CTX_get(ctx); + test = BN_CTX_get(ctx); + + if (test == NULL || !BN_lshift(test, BN_value_one(), bits - 1)) { + goto err; + } + + for (;;) { + /* Find q. */ + for (;;) { + /* step 1 */ + if (!BN_GENCB_call(cb, 0, m++)) { + goto err; + } + + int use_random_seed = (seed_in == NULL); + if (use_random_seed) { + if (!RAND_bytes(seed, qsize)) { + goto err; + } + } else { + /* If we come back through, use random seed next time. */ + seed_in = NULL; + } + memcpy(buf, seed, qsize); + memcpy(buf2, seed, qsize); + /* precompute "SEED + 1" for step 7: */ + for (i = qsize - 1; i < qsize; i--) { + buf[i]++; + if (buf[i] != 0) { + break; + } + } + + /* step 2 */ + if (!EVP_Digest(seed, qsize, md, NULL, evpmd, NULL) || + !EVP_Digest(buf, qsize, buf2, NULL, evpmd, NULL)) { + goto err; + } + for (i = 0; i < qsize; i++) { + md[i] ^= buf2[i]; + } + + /* step 3 */ + md[0] |= 0x80; + md[qsize - 1] |= 0x01; + if (!BN_bin2bn(md, qsize, q)) { + goto err; + } + + /* step 4 */ + r = BN_is_prime_fasttest_ex(q, DSS_prime_checks, ctx, use_random_seed, cb); + if (r > 0) { + break; + } + if (r != 0) { + goto err; + } + + /* do a callback call */ + /* step 5 */ + } + + if (!BN_GENCB_call(cb, 2, 0) || !BN_GENCB_call(cb, 3, 0)) { + goto err; + } + + /* step 6 */ + counter = 0; + /* "offset = 2" */ + + n = (bits - 1) / 160; + + for (;;) { + if ((counter != 0) && !BN_GENCB_call(cb, 0, counter)) { + goto err; + } + + /* step 7 */ + BN_zero(W); + /* now 'buf' contains "SEED + offset - 1" */ + for (k = 0; k <= n; k++) { + /* obtain "SEED + offset + k" by incrementing: */ + for (i = qsize - 1; i < qsize; i--) { + buf[i]++; + if (buf[i] != 0) { + break; + } + } + + if (!EVP_Digest(buf, qsize, md, NULL, evpmd, NULL)) { + goto err; + } + + /* step 8 */ + if (!BN_bin2bn(md, qsize, r0) || + !BN_lshift(r0, r0, (qsize << 3) * k) || + !BN_add(W, W, r0)) { + goto err; + } + } + + /* more of step 8 */ + if (!BN_mask_bits(W, bits - 1) || + !BN_copy(X, W) || + !BN_add(X, X, test)) { + goto err; + } + + /* step 9 */ + if (!BN_lshift1(r0, q) || + !BN_mod(c, X, r0, ctx) || + !BN_sub(r0, c, BN_value_one()) || + !BN_sub(p, X, r0)) { + goto err; + } + + /* step 10 */ + if (BN_cmp(p, test) >= 0) { + /* step 11 */ + r = BN_is_prime_fasttest_ex(p, DSS_prime_checks, ctx, 1, cb); + if (r > 0) { + goto end; /* found it */ + } + if (r != 0) { + goto err; + } + } + + /* step 13 */ + counter++; + /* "offset = offset + n + 1" */ + + /* step 14 */ + if (counter >= 4096) { + break; + } + } + } +end: + if (!BN_GENCB_call(cb, 2, 1)) { + goto err; + } + + /* We now need to generate g */ + /* Set r0=(p-1)/q */ + if (!BN_sub(test, p, BN_value_one()) || + !BN_div(r0, NULL, test, q, ctx)) { + goto err; + } + + if (!BN_set_word(test, h) || + !BN_MONT_CTX_set(mont, p, ctx)) { + goto err; + } + + for (;;) { + /* g=test^r0%p */ + if (!BN_mod_exp_mont(g, test, r0, p, ctx, mont)) { + goto err; + } + if (!BN_is_one(g)) { + break; + } + if (!BN_add(test, test, BN_value_one())) { + goto err; + } + h++; + } + + if (!BN_GENCB_call(cb, 3, 1)) { + goto err; + } + + ok = 1; + +err: + if (ok) { + BN_free(dsa->p); + BN_free(dsa->q); + BN_free(dsa->g); + dsa->p = BN_dup(p); + dsa->q = BN_dup(q); + dsa->g = BN_dup(g); + if (dsa->p == NULL || dsa->q == NULL || dsa->g == NULL) { + ok = 0; + goto err; + } + if (out_counter != NULL) { + *out_counter = counter; + } + if (out_h != NULL) { + *out_h = h; + } + } + + if (ctx) { + BN_CTX_end(ctx); + BN_CTX_free(ctx); + } + + BN_MONT_CTX_free(mont); + + return ok; +} + +DSA *DSAparams_dup(const DSA *dsa) { + DSA *ret = DSA_new(); + if (ret == NULL) { + return NULL; + } + ret->p = BN_dup(dsa->p); + ret->q = BN_dup(dsa->q); + ret->g = BN_dup(dsa->g); + if (ret->p == NULL || ret->q == NULL || ret->g == NULL) { + DSA_free(ret); + return NULL; + } + return ret; +} + +int DSA_generate_key(DSA *dsa) { + int ok = 0; + BN_CTX *ctx = NULL; + BIGNUM *pub_key = NULL, *priv_key = NULL; + BIGNUM prk; + + ctx = BN_CTX_new(); + if (ctx == NULL) { + goto err; + } + + priv_key = dsa->priv_key; + if (priv_key == NULL) { + priv_key = BN_new(); + if (priv_key == NULL) { + goto err; + } + } + + do { + if (!BN_rand_range(priv_key, dsa->q)) { + goto err; + } + } while (BN_is_zero(priv_key)); + + pub_key = dsa->pub_key; + if (pub_key == NULL) { + pub_key = BN_new(); + if (pub_key == NULL) { + goto err; + } + } + + BN_init(&prk); + BN_with_flags(&prk, priv_key, BN_FLG_CONSTTIME); + + if (!BN_mod_exp(pub_key, dsa->g, &prk, dsa->p, ctx)) { + goto err; + } + + dsa->priv_key = priv_key; + dsa->pub_key = pub_key; + ok = 1; + +err: + if (dsa->pub_key == NULL) { + BN_free(pub_key); + } + if (dsa->priv_key == NULL) { + BN_free(priv_key); + } + BN_CTX_free(ctx); + + return ok; +} + +DSA_SIG *DSA_SIG_new(void) { + DSA_SIG *sig; + sig = OPENSSL_malloc(sizeof(DSA_SIG)); + if (!sig) { + return NULL; + } + sig->r = NULL; + sig->s = NULL; + return sig; +} + +void DSA_SIG_free(DSA_SIG *sig) { + if (!sig) { + return; + } + + BN_free(sig->r); + BN_free(sig->s); + OPENSSL_free(sig); +} + +DSA_SIG *DSA_do_sign(const uint8_t *digest, size_t digest_len, DSA *dsa) { + BIGNUM *kinv = NULL, *r = NULL, *s = NULL; + BIGNUM m; + BIGNUM xr; + BN_CTX *ctx = NULL; + int reason = ERR_R_BN_LIB; + DSA_SIG *ret = NULL; + int noredo = 0; + + BN_init(&m); + BN_init(&xr); + + if (!dsa->p || !dsa->q || !dsa->g) { + reason = DSA_R_MISSING_PARAMETERS; + goto err; + } + + s = BN_new(); + if (s == NULL) { + goto err; + } + ctx = BN_CTX_new(); + if (ctx == NULL) { + goto err; + } + +redo: + if (dsa->kinv == NULL || dsa->r == NULL) { + if (!DSA_sign_setup(dsa, ctx, &kinv, &r)) { + goto err; + } + } else { + kinv = dsa->kinv; + dsa->kinv = NULL; + r = dsa->r; + dsa->r = NULL; + noredo = 1; + } + + if (digest_len > BN_num_bytes(dsa->q)) { + /* if the digest length is greater than the size of q use the + * BN_num_bits(dsa->q) leftmost bits of the digest, see + * fips 186-3, 4.2 */ + digest_len = BN_num_bytes(dsa->q); + } + + if (BN_bin2bn(digest, digest_len, &m) == NULL) { + goto err; + } + + /* Compute s = inv(k) (m + xr) mod q */ + if (!BN_mod_mul(&xr, dsa->priv_key, r, dsa->q, ctx)) { + goto err; /* s = xr */ + } + if (!BN_add(s, &xr, &m)) { + goto err; /* s = m + xr */ + } + if (BN_cmp(s, dsa->q) > 0) { + if (!BN_sub(s, s, dsa->q)) { + goto err; + } + } + if (!BN_mod_mul(s, s, kinv, dsa->q, ctx)) { + goto err; + } + + /* Redo if r or s is zero as required by FIPS 186-3: this is + * very unlikely. */ + if (BN_is_zero(r) || BN_is_zero(s)) { + if (noredo) { + reason = DSA_R_NEED_NEW_SETUP_VALUES; + goto err; + } + goto redo; + } + ret = DSA_SIG_new(); + if (ret == NULL) { + goto err; + } + ret->r = r; + ret->s = s; + +err: + if (ret == NULL) { + OPENSSL_PUT_ERROR(DSA, reason); + BN_free(r); + BN_free(s); + } + BN_CTX_free(ctx); + BN_clear_free(&m); + BN_clear_free(&xr); + BN_clear_free(kinv); + + return ret; +} + +int DSA_do_verify(const uint8_t *digest, size_t digest_len, DSA_SIG *sig, + const DSA *dsa) { + int valid; + if (!DSA_do_check_signature(&valid, digest, digest_len, sig, dsa)) { + return -1; + } + return valid; +} + +int DSA_do_check_signature(int *out_valid, const uint8_t *digest, + size_t digest_len, DSA_SIG *sig, const DSA *dsa) { + BN_CTX *ctx; + BIGNUM u1, u2, t1; + int ret = 0; + unsigned i; + + *out_valid = 0; + + if (!dsa->p || !dsa->q || !dsa->g) { + OPENSSL_PUT_ERROR(DSA, DSA_R_MISSING_PARAMETERS); + return 0; + } + + i = BN_num_bits(dsa->q); + /* fips 186-3 allows only different sizes for q */ + if (i != 160 && i != 224 && i != 256) { + OPENSSL_PUT_ERROR(DSA, DSA_R_BAD_Q_VALUE); + return 0; + } + + if (BN_num_bits(dsa->p) > OPENSSL_DSA_MAX_MODULUS_BITS) { + OPENSSL_PUT_ERROR(DSA, DSA_R_MODULUS_TOO_LARGE); + return 0; + } + + BN_init(&u1); + BN_init(&u2); + BN_init(&t1); + + ctx = BN_CTX_new(); + if (ctx == NULL) { + goto err; + } + + if (BN_is_zero(sig->r) || BN_is_negative(sig->r) || + BN_ucmp(sig->r, dsa->q) >= 0) { + ret = 1; + goto err; + } + if (BN_is_zero(sig->s) || BN_is_negative(sig->s) || + BN_ucmp(sig->s, dsa->q) >= 0) { + ret = 1; + goto err; + } + + /* Calculate W = inv(S) mod Q + * save W in u2 */ + if (BN_mod_inverse(&u2, sig->s, dsa->q, ctx) == NULL) { + goto err; + } + + /* save M in u1 */ + if (digest_len > (i >> 3)) { + /* if the digest length is greater than the size of q use the + * BN_num_bits(dsa->q) leftmost bits of the digest, see + * fips 186-3, 4.2 */ + digest_len = (i >> 3); + } + + if (BN_bin2bn(digest, digest_len, &u1) == NULL) { + goto err; + } + + /* u1 = M * w mod q */ + if (!BN_mod_mul(&u1, &u1, &u2, dsa->q, ctx)) { + goto err; + } + + /* u2 = r * w mod q */ + if (!BN_mod_mul(&u2, sig->r, &u2, dsa->q, ctx)) { + goto err; + } + + if (!BN_MONT_CTX_set_locked((BN_MONT_CTX **)&dsa->method_mont_p, + (CRYPTO_MUTEX *)&dsa->method_mont_p_lock, dsa->p, + ctx)) { + goto err; + } + + if (!BN_mod_exp2_mont(&t1, dsa->g, &u1, dsa->pub_key, &u2, dsa->p, ctx, + dsa->method_mont_p)) { + goto err; + } + + /* BN_copy(&u1,&t1); */ + /* let u1 = u1 mod q */ + if (!BN_mod(&u1, &t1, dsa->q, ctx)) { + goto err; + } + + /* V is now in u1. If the signature is correct, it will be + * equal to R. */ + *out_valid = BN_ucmp(&u1, sig->r) == 0; + ret = 1; + +err: + if (ret != 1) { + OPENSSL_PUT_ERROR(DSA, ERR_R_BN_LIB); + } + BN_CTX_free(ctx); + BN_free(&u1); + BN_free(&u2); + BN_free(&t1); + + return ret; +} + +int DSA_sign(int type, const uint8_t *digest, size_t digest_len, + uint8_t *out_sig, unsigned int *out_siglen, DSA *dsa) { + DSA_SIG *s; + + s = DSA_do_sign(digest, digest_len, dsa); + if (s == NULL) { + *out_siglen = 0; + return 0; + } + + *out_siglen = i2d_DSA_SIG(s, &out_sig); + DSA_SIG_free(s); + return 1; +} + +int DSA_verify(int type, const uint8_t *digest, size_t digest_len, + const uint8_t *sig, size_t sig_len, const DSA *dsa) { + int valid; + if (!DSA_check_signature(&valid, digest, digest_len, sig, sig_len, dsa)) { + return -1; + } + return valid; +} + +int DSA_check_signature(int *out_valid, const uint8_t *digest, + size_t digest_len, const uint8_t *sig, size_t sig_len, + const DSA *dsa) { + DSA_SIG *s = NULL; + int ret = 0; + uint8_t *der = NULL; + + s = DSA_SIG_new(); + if (s == NULL) { + goto err; + } + + const uint8_t *sigp = sig; + if (d2i_DSA_SIG(&s, &sigp, sig_len) == NULL || sigp != sig + sig_len) { + goto err; + } + + /* Ensure that the signature uses DER and doesn't have trailing garbage. */ + int der_len = i2d_DSA_SIG(s, &der); + if (der_len < 0 || (size_t)der_len != sig_len || memcmp(sig, der, sig_len)) { + goto err; + } + + ret = DSA_do_check_signature(out_valid, digest, digest_len, s, dsa); + +err: + OPENSSL_free(der); + DSA_SIG_free(s); + return ret; +} + +/* der_len_len returns the number of bytes needed to represent a length of |len| + * in DER. */ +static size_t der_len_len(size_t len) { + if (len < 0x80) { + return 1; + } + size_t ret = 1; + while (len > 0) { + ret++; + len >>= 8; + } + return ret; +} + +int DSA_size(const DSA *dsa) { + size_t order_len = BN_num_bytes(dsa->q); + /* Compute the maximum length of an |order_len| byte integer. Defensively + * assume that the leading 0x00 is included. */ + size_t integer_len = 1 /* tag */ + der_len_len(order_len + 1) + 1 + order_len; + if (integer_len < order_len) { + return 0; + } + /* A DSA signature is two INTEGERs. */ + size_t value_len = 2 * integer_len; + if (value_len < integer_len) { + return 0; + } + /* Add the header. */ + size_t ret = 1 /* tag */ + der_len_len(value_len) + value_len; + if (ret < value_len) { + return 0; + } + return ret; +} + +int DSA_sign_setup(const DSA *dsa, BN_CTX *ctx_in, BIGNUM **out_kinv, + BIGNUM **out_r) { + BN_CTX *ctx; + BIGNUM k, kq, *K, *kinv = NULL, *r = NULL; + int ret = 0; + + if (!dsa->p || !dsa->q || !dsa->g) { + OPENSSL_PUT_ERROR(DSA, DSA_R_MISSING_PARAMETERS); + return 0; + } + + BN_init(&k); + BN_init(&kq); + + ctx = ctx_in; + if (ctx == NULL) { + ctx = BN_CTX_new(); + if (ctx == NULL) { + goto err; + } + } + + r = BN_new(); + if (r == NULL) { + goto err; + } + + /* Get random k */ + do { + if (!BN_rand_range(&k, dsa->q)) { + goto err; + } + } while (BN_is_zero(&k)); + + BN_set_flags(&k, BN_FLG_CONSTTIME); + + if (!BN_MONT_CTX_set_locked((BN_MONT_CTX **)&dsa->method_mont_p, + (CRYPTO_MUTEX *)&dsa->method_mont_p_lock, dsa->p, + ctx)) { + goto err; + } + + /* Compute r = (g^k mod p) mod q */ + if (!BN_copy(&kq, &k)) { + goto err; + } + + /* We do not want timing information to leak the length of k, + * so we compute g^k using an equivalent exponent of fixed length. + * + * (This is a kludge that we need because the BN_mod_exp_mont() + * does not let us specify the desired timing behaviour.) */ + + if (!BN_add(&kq, &kq, dsa->q)) { + goto err; + } + if (BN_num_bits(&kq) <= BN_num_bits(dsa->q) && !BN_add(&kq, &kq, dsa->q)) { + goto err; + } + + BN_set_flags(&kq, BN_FLG_CONSTTIME); + K = &kq; + + if (!BN_mod_exp_mont(r, dsa->g, K, dsa->p, ctx, dsa->method_mont_p)) { + goto err; + } + if (!BN_mod(r, r, dsa->q, ctx)) { + goto err; + } + + /* Compute part of 's = inv(k) (m + xr) mod q' */ + kinv = BN_mod_inverse(NULL, &k, dsa->q, ctx); + if (kinv == NULL) { + goto err; + } + + BN_clear_free(*out_kinv); + *out_kinv = kinv; + kinv = NULL; + BN_clear_free(*out_r); + *out_r = r; + ret = 1; + +err: + if (!ret) { + OPENSSL_PUT_ERROR(DSA, ERR_R_BN_LIB); + if (r != NULL) { + BN_clear_free(r); + } + } + + if (ctx_in == NULL) { + BN_CTX_free(ctx); + } + BN_clear_free(&k); + BN_clear_free(&kq); + return ret; +} + +int DSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_unused *unused, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) { + int index; + if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp, dup_func, + free_func)) { + return -1; + } + return index; +} + +int DSA_set_ex_data(DSA *d, int idx, void *arg) { + return CRYPTO_set_ex_data(&d->ex_data, idx, arg); +} + +void *DSA_get_ex_data(const DSA *d, int idx) { + return CRYPTO_get_ex_data(&d->ex_data, idx); +} + +DH *DSA_dup_DH(const DSA *r) { + DH *ret = NULL; + + if (r == NULL) { + goto err; + } + ret = DH_new(); + if (ret == NULL) { + goto err; + } + if (r->q != NULL) { + ret->priv_length = BN_num_bits(r->q); + if ((ret->q = BN_dup(r->q)) == NULL) { + goto err; + } + } + if ((r->p != NULL && (ret->p = BN_dup(r->p)) == NULL) || + (r->g != NULL && (ret->g = BN_dup(r->g)) == NULL) || + (r->pub_key != NULL && (ret->pub_key = BN_dup(r->pub_key)) == NULL) || + (r->priv_key != NULL && (ret->priv_key = BN_dup(r->priv_key)) == NULL)) { + goto err; + } + + return ret; + +err: + DH_free(ret); + return NULL; +} diff --git a/external/boringssl/crypto/dsa/dsa_asn1.c b/external/boringssl/crypto/dsa/dsa_asn1.c new file mode 100644 index 0000000000..ff5ee0039c --- /dev/null +++ b/external/boringssl/crypto/dsa/dsa_asn1.c @@ -0,0 +1,339 @@ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 2000. */ +/* ==================================================================== + * Copyright (c) 2000-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include + +#include +#include +#include +#include + +#include "../bytestring/internal.h" + + +static int parse_integer(CBS *cbs, BIGNUM **out) { + assert(*out == NULL); + *out = BN_new(); + if (*out == NULL) { + return 0; + } + return BN_parse_asn1_unsigned(cbs, *out); +} + +static int marshal_integer(CBB *cbb, BIGNUM *bn) { + if (bn == NULL) { + /* A DSA object may be missing some components. */ + OPENSSL_PUT_ERROR(DSA, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + return BN_marshal_asn1(cbb, bn); +} + +DSA_SIG *DSA_SIG_parse(CBS *cbs) { + DSA_SIG *ret = DSA_SIG_new(); + if (ret == NULL) { + return NULL; + } + CBS child; + if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) || + !parse_integer(&child, &ret->r) || + !parse_integer(&child, &ret->s) || + CBS_len(&child) != 0) { + OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR); + DSA_SIG_free(ret); + return NULL; + } + return ret; +} + +int DSA_SIG_marshal(CBB *cbb, const DSA_SIG *sig) { + CBB child; + if (!CBB_add_asn1(cbb, &child, CBS_ASN1_SEQUENCE) || + !marshal_integer(&child, sig->r) || + !marshal_integer(&child, sig->s) || + !CBB_flush(cbb)) { + OPENSSL_PUT_ERROR(DSA, DSA_R_ENCODE_ERROR); + return 0; + } + return 1; +} + +DSA *DSA_parse_public_key(CBS *cbs) { + DSA *ret = DSA_new(); + if (ret == NULL) { + return NULL; + } + CBS child; + if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) || + !parse_integer(&child, &ret->pub_key) || + !parse_integer(&child, &ret->p) || + !parse_integer(&child, &ret->q) || + !parse_integer(&child, &ret->g) || + CBS_len(&child) != 0) { + OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR); + DSA_free(ret); + return NULL; + } + return ret; +} + +int DSA_marshal_public_key(CBB *cbb, const DSA *dsa) { + CBB child; + if (!CBB_add_asn1(cbb, &child, CBS_ASN1_SEQUENCE) || + !marshal_integer(&child, dsa->pub_key) || + !marshal_integer(&child, dsa->p) || + !marshal_integer(&child, dsa->q) || + !marshal_integer(&child, dsa->g) || + !CBB_flush(cbb)) { + OPENSSL_PUT_ERROR(DSA, DSA_R_ENCODE_ERROR); + return 0; + } + return 1; +} + +DSA *DSA_parse_parameters(CBS *cbs) { + DSA *ret = DSA_new(); + if (ret == NULL) { + return NULL; + } + CBS child; + if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) || + !parse_integer(&child, &ret->p) || + !parse_integer(&child, &ret->q) || + !parse_integer(&child, &ret->g) || + CBS_len(&child) != 0) { + OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR); + DSA_free(ret); + return NULL; + } + return ret; +} + +int DSA_marshal_parameters(CBB *cbb, const DSA *dsa) { + CBB child; + if (!CBB_add_asn1(cbb, &child, CBS_ASN1_SEQUENCE) || + !marshal_integer(&child, dsa->p) || + !marshal_integer(&child, dsa->q) || + !marshal_integer(&child, dsa->g) || + !CBB_flush(cbb)) { + OPENSSL_PUT_ERROR(DSA, DSA_R_ENCODE_ERROR); + return 0; + } + return 1; +} + +DSA *DSA_parse_private_key(CBS *cbs) { + DSA *ret = DSA_new(); + if (ret == NULL) { + return NULL; + } + + CBS child; + uint64_t version; + if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) || + !CBS_get_asn1_uint64(&child, &version)) { + OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR); + goto err; + } + + if (version != 0) { + OPENSSL_PUT_ERROR(DSA, DSA_R_BAD_VERSION); + goto err; + } + + if (!parse_integer(&child, &ret->p) || + !parse_integer(&child, &ret->q) || + !parse_integer(&child, &ret->g) || + !parse_integer(&child, &ret->pub_key) || + !parse_integer(&child, &ret->priv_key) || + CBS_len(&child) != 0) { + OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR); + goto err; + } + return ret; + +err: + DSA_free(ret); + return NULL; +} + +int DSA_marshal_private_key(CBB *cbb, const DSA *dsa) { + CBB child; + if (!CBB_add_asn1(cbb, &child, CBS_ASN1_SEQUENCE) || + !CBB_add_asn1_uint64(&child, 0 /* version */) || + !marshal_integer(&child, dsa->p) || + !marshal_integer(&child, dsa->q) || + !marshal_integer(&child, dsa->g) || + !marshal_integer(&child, dsa->pub_key) || + !marshal_integer(&child, dsa->priv_key) || + !CBB_flush(cbb)) { + OPENSSL_PUT_ERROR(DSA, DSA_R_ENCODE_ERROR); + return 0; + } + return 1; +} + +DSA_SIG *d2i_DSA_SIG(DSA_SIG **out_sig, const uint8_t **inp, long len) { + if (len < 0) { + return NULL; + } + CBS cbs; + CBS_init(&cbs, *inp, (size_t)len); + DSA_SIG *ret = DSA_SIG_parse(&cbs); + if (ret == NULL) { + return NULL; + } + if (out_sig != NULL) { + DSA_SIG_free(*out_sig); + *out_sig = ret; + } + *inp = CBS_data(&cbs); + return ret; +} + +int i2d_DSA_SIG(const DSA_SIG *in, uint8_t **outp) { + CBB cbb; + if (!CBB_init(&cbb, 0) || + !DSA_SIG_marshal(&cbb, in)) { + CBB_cleanup(&cbb); + return -1; + } + return CBB_finish_i2d(&cbb, outp); +} + +DSA *d2i_DSAPublicKey(DSA **out, const uint8_t **inp, long len) { + if (len < 0) { + return NULL; + } + CBS cbs; + CBS_init(&cbs, *inp, (size_t)len); + DSA *ret = DSA_parse_public_key(&cbs); + if (ret == NULL) { + return NULL; + } + if (out != NULL) { + DSA_free(*out); + *out = ret; + } + *inp = CBS_data(&cbs); + return ret; +} + +int i2d_DSAPublicKey(const DSA *in, uint8_t **outp) { + CBB cbb; + if (!CBB_init(&cbb, 0) || + !DSA_marshal_public_key(&cbb, in)) { + CBB_cleanup(&cbb); + return -1; + } + return CBB_finish_i2d(&cbb, outp); +} + +DSA *d2i_DSAPrivateKey(DSA **out, const uint8_t **inp, long len) { + if (len < 0) { + return NULL; + } + CBS cbs; + CBS_init(&cbs, *inp, (size_t)len); + DSA *ret = DSA_parse_private_key(&cbs); + if (ret == NULL) { + return NULL; + } + if (out != NULL) { + DSA_free(*out); + *out = ret; + } + *inp = CBS_data(&cbs); + return ret; +} + +int i2d_DSAPrivateKey(const DSA *in, uint8_t **outp) { + CBB cbb; + if (!CBB_init(&cbb, 0) || + !DSA_marshal_private_key(&cbb, in)) { + CBB_cleanup(&cbb); + return -1; + } + return CBB_finish_i2d(&cbb, outp); +} + +DSA *d2i_DSAparams(DSA **out, const uint8_t **inp, long len) { + if (len < 0) { + return NULL; + } + CBS cbs; + CBS_init(&cbs, *inp, (size_t)len); + DSA *ret = DSA_parse_parameters(&cbs); + if (ret == NULL) { + return NULL; + } + if (out != NULL) { + DSA_free(*out); + *out = ret; + } + *inp = CBS_data(&cbs); + return ret; +} + +int i2d_DSAparams(const DSA *in, uint8_t **outp) { + CBB cbb; + if (!CBB_init(&cbb, 0) || + !DSA_marshal_parameters(&cbb, in)) { + CBB_cleanup(&cbb); + return -1; + } + return CBB_finish_i2d(&cbb, outp); +} diff --git a/external/boringssl/crypto/dsa/dsa_test.c b/external/boringssl/crypto/dsa/dsa_test.c new file mode 100644 index 0000000000..6296c8f06e --- /dev/null +++ b/external/boringssl/crypto/dsa/dsa_test.c @@ -0,0 +1,323 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + * + * The DSS routines are based on patches supplied by + * Steven Schoch . */ + +#include + +#include + +#include +#include +#include + + +static int dsa_cb(int p, int n, BN_GENCB *arg); + +/* The following values are taken from the updated Appendix 5 to FIPS PUB 186 + * and also appear in Appendix 5 to FIPS PUB 186-1. */ + +static const uint8_t seed[20] = { + 0xd5, 0x01, 0x4e, 0x4b, 0x60, 0xef, 0x2b, 0xa8, 0xb6, 0x21, 0x1b, + 0x40, 0x62, 0xba, 0x32, 0x24, 0xe0, 0x42, 0x7d, 0xd3, +}; + +static const uint8_t fips_p[] = { + 0x8d, 0xf2, 0xa4, 0x94, 0x49, 0x22, 0x76, 0xaa, 0x3d, 0x25, 0x75, + 0x9b, 0xb0, 0x68, 0x69, 0xcb, 0xea, 0xc0, 0xd8, 0x3a, 0xfb, 0x8d, + 0x0c, 0xf7, 0xcb, 0xb8, 0x32, 0x4f, 0x0d, 0x78, 0x82, 0xe5, 0xd0, + 0x76, 0x2f, 0xc5, 0xb7, 0x21, 0x0e, 0xaf, 0xc2, 0xe9, 0xad, 0xac, + 0x32, 0xab, 0x7a, 0xac, 0x49, 0x69, 0x3d, 0xfb, 0xf8, 0x37, 0x24, + 0xc2, 0xec, 0x07, 0x36, 0xee, 0x31, 0xc8, 0x02, 0x91, +}; + +static const uint8_t fips_q[] = { + 0xc7, 0x73, 0x21, 0x8c, 0x73, 0x7e, 0xc8, 0xee, 0x99, 0x3b, 0x4f, + 0x2d, 0xed, 0x30, 0xf4, 0x8e, 0xda, 0xce, 0x91, 0x5f, +}; + +static const uint8_t fips_g[] = { + 0x62, 0x6d, 0x02, 0x78, 0x39, 0xea, 0x0a, 0x13, 0x41, 0x31, 0x63, + 0xa5, 0x5b, 0x4c, 0xb5, 0x00, 0x29, 0x9d, 0x55, 0x22, 0x95, 0x6c, + 0xef, 0xcb, 0x3b, 0xff, 0x10, 0xf3, 0x99, 0xce, 0x2c, 0x2e, 0x71, + 0xcb, 0x9d, 0xe5, 0xfa, 0x24, 0xba, 0xbf, 0x58, 0xe5, 0xb7, 0x95, + 0x21, 0x92, 0x5c, 0x9c, 0xc4, 0x2e, 0x9f, 0x6f, 0x46, 0x4b, 0x08, + 0x8c, 0xc5, 0x72, 0xaf, 0x53, 0xe6, 0xd7, 0x88, 0x02, +}; + +static const uint8_t fips_x[] = { + 0x20, 0x70, 0xb3, 0x22, 0x3d, 0xba, 0x37, 0x2f, 0xde, 0x1c, 0x0f, + 0xfc, 0x7b, 0x2e, 0x3b, 0x49, 0x8b, 0x26, 0x06, 0x14, +}; + +static const uint8_t fips_y[] = { + 0x19, 0x13, 0x18, 0x71, 0xd7, 0x5b, 0x16, 0x12, 0xa8, 0x19, 0xf2, + 0x9d, 0x78, 0xd1, 0xb0, 0xd7, 0x34, 0x6f, 0x7a, 0xa7, 0x7b, 0xb6, + 0x2a, 0x85, 0x9b, 0xfd, 0x6c, 0x56, 0x75, 0xda, 0x9d, 0x21, 0x2d, + 0x3a, 0x36, 0xef, 0x16, 0x72, 0xef, 0x66, 0x0b, 0x8c, 0x7c, 0x25, + 0x5c, 0xc0, 0xec, 0x74, 0x85, 0x8f, 0xba, 0x33, 0xf4, 0x4c, 0x06, + 0x69, 0x96, 0x30, 0xa7, 0x6b, 0x03, 0x0e, 0xe3, 0x33, +}; + +static const uint8_t fips_digest[] = { + 0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a, 0xba, 0x3e, 0x25, + 0x71, 0x78, 0x50, 0xc2, 0x6c, 0x9c, 0xd0, 0xd8, 0x9d, +}; + +/* fips_sig is a DER-encoded version of the r and s values in FIPS PUB 186-1. */ +static const uint8_t fips_sig[] = { + 0x30, 0x2d, 0x02, 0x15, 0x00, 0x8b, 0xac, 0x1a, 0xb6, 0x64, 0x10, + 0x43, 0x5c, 0xb7, 0x18, 0x1f, 0x95, 0xb1, 0x6a, 0xb9, 0x7c, 0x92, + 0xb3, 0x41, 0xc0, 0x02, 0x14, 0x41, 0xe2, 0x34, 0x5f, 0x1f, 0x56, + 0xdf, 0x24, 0x58, 0xf4, 0x26, 0xd1, 0x55, 0xb4, 0xba, 0x2d, 0xb6, + 0xdc, 0xd8, 0xc8, +}; + +/* fips_sig_negative is fips_sig with r encoded as a negative number. */ +static const uint8_t fips_sig_negative[] = { + 0x30, 0x2c, 0x02, 0x14, 0x8b, 0xac, 0x1a, 0xb6, 0x64, 0x10, 0x43, + 0x5c, 0xb7, 0x18, 0x1f, 0x95, 0xb1, 0x6a, 0xb9, 0x7c, 0x92, 0xb3, + 0x41, 0xc0, 0x02, 0x14, 0x41, 0xe2, 0x34, 0x5f, 0x1f, 0x56, 0xdf, + 0x24, 0x58, 0xf4, 0x26, 0xd1, 0x55, 0xb4, 0xba, 0x2d, 0xb6, 0xdc, + 0xd8, 0xc8, +}; + +/* fip_sig_extra is fips_sig with trailing data. */ +static const uint8_t fips_sig_extra[] = { + 0x30, 0x2d, 0x02, 0x15, 0x00, 0x8b, 0xac, 0x1a, 0xb6, 0x64, 0x10, + 0x43, 0x5c, 0xb7, 0x18, 0x1f, 0x95, 0xb1, 0x6a, 0xb9, 0x7c, 0x92, + 0xb3, 0x41, 0xc0, 0x02, 0x14, 0x41, 0xe2, 0x34, 0x5f, 0x1f, 0x56, + 0xdf, 0x24, 0x58, 0xf4, 0x26, 0xd1, 0x55, 0xb4, 0xba, 0x2d, 0xb6, + 0xdc, 0xd8, 0xc8, 0x00, +}; + +/* fips_sig_lengths is fips_sig with a non-minimally encoded length. */ +static const uint8_t fips_sig_bad_length[] = { + 0x30, 0x81, 0x2d, 0x02, 0x15, 0x00, 0x8b, 0xac, 0x1a, 0xb6, 0x64, + 0x10, 0x43, 0x5c, 0xb7, 0x18, 0x1f, 0x95, 0xb1, 0x6a, 0xb9, 0x7c, + 0x92, 0xb3, 0x41, 0xc0, 0x02, 0x14, 0x41, 0xe2, 0x34, 0x5f, 0x1f, + 0x56, 0xdf, 0x24, 0x58, 0xf4, 0x26, 0xd1, 0x55, 0xb4, 0xba, 0x2d, + 0xb6, 0xdc, 0xd8, 0xc8, 0x00, +}; + +/* fips_sig_bad_r is fips_sig with a bad r value. */ +static const uint8_t fips_sig_bad_r[] = { + 0x30, 0x2d, 0x02, 0x15, 0x00, 0x8c, 0xac, 0x1a, 0xb6, 0x64, 0x10, + 0x43, 0x5c, 0xb7, 0x18, 0x1f, 0x95, 0xb1, 0x6a, 0xb9, 0x7c, 0x92, + 0xb3, 0x41, 0xc0, 0x02, 0x14, 0x41, 0xe2, 0x34, 0x5f, 0x1f, 0x56, + 0xdf, 0x24, 0x58, 0xf4, 0x26, 0xd1, 0x55, 0xb4, 0xba, 0x2d, 0xb6, + 0xdc, 0xd8, 0xc8, +}; + +static DSA *get_fips_dsa(void) { + DSA *dsa = DSA_new(); + if (!dsa) { + return NULL; + } + dsa->p = BN_bin2bn(fips_p, sizeof(fips_p), NULL); + dsa->q = BN_bin2bn(fips_q, sizeof(fips_q), NULL); + dsa->g = BN_bin2bn(fips_g, sizeof(fips_g), NULL); + dsa->pub_key = BN_bin2bn(fips_y, sizeof(fips_y), NULL); + dsa->priv_key = BN_bin2bn(fips_x, sizeof(fips_x), NULL); + if (dsa->p == NULL || dsa->q == NULL || dsa->g == NULL || + dsa->pub_key == NULL || dsa->priv_key == NULL) { + DSA_free(dsa); + return NULL; + } + return dsa; +} + +static int test_generate(FILE *out) { + BN_GENCB cb; + DSA *dsa = NULL; + int counter, ok = 0, i, j; + uint8_t buf[256]; + unsigned long h; + uint8_t sig[256]; + unsigned int siglen; + + fprintf(out, "test generation of DSA parameters\n"); + + BN_GENCB_set(&cb, dsa_cb, out); + dsa = DSA_new(); + if (dsa == NULL || + !DSA_generate_parameters_ex(dsa, 512, seed, 20, &counter, &h, &cb)) { + goto end; + } + + fprintf(out, "seed\n"); + for (i = 0; i < 20; i += 4) { + fprintf(out, "%02X%02X%02X%02X ", seed[i], seed[i + 1], seed[i + 2], + seed[i + 3]); + } + fprintf(out, "\ncounter=%d h=%ld\n", counter, h); + + if (counter != 105) { + fprintf(stderr, "counter should be 105\n"); + goto end; + } + if (h != 2) { + fprintf(stderr, "h should be 2\n"); + goto end; + } + + i = BN_bn2bin(dsa->q, buf); + j = sizeof(fips_q); + if (i != j || memcmp(buf, fips_q, i) != 0) { + fprintf(stderr, "q value is wrong\n"); + goto end; + } + + i = BN_bn2bin(dsa->p, buf); + j = sizeof(fips_p); + if (i != j || memcmp(buf, fips_p, i) != 0) { + fprintf(stderr, "p value is wrong\n"); + goto end; + } + + i = BN_bn2bin(dsa->g, buf); + j = sizeof(fips_g); + if (i != j || memcmp(buf, fips_g, i) != 0) { + fprintf(stderr, "g value is wrong\n"); + goto end; + } + + if (!DSA_generate_key(dsa) || + !DSA_sign(0, fips_digest, sizeof(fips_digest), sig, &siglen, dsa)) { + goto end; + } + if (DSA_verify(0, fips_digest, sizeof(fips_digest), sig, siglen, dsa) == 1) { + ok = 1; + } else { + fprintf(stderr, "verification failure\n"); + } + +end: + DSA_free(dsa); + + return ok; +} + +static int test_verify(const uint8_t *sig, size_t sig_len, int expect) { + int ok = 0; + DSA *dsa = get_fips_dsa(); + if (dsa == NULL) { + goto end; + } + + int ret = DSA_verify(0, fips_digest, sizeof(fips_digest), sig, sig_len, dsa); + if (ret != expect) { + fprintf(stderr, "DSA_verify returned %d, want %d\n", ret, expect); + goto end; + } + ok = 1; + /* Clear any errorrs from a test with expected failure. */ + ERR_clear_error(); + +end: + DSA_free(dsa); + + return ok; +} + +int main(int argc, char **argv) { + CRYPTO_library_init(); + + if (!test_generate(stdout) || + !test_verify(fips_sig, sizeof(fips_sig), 1) || + !test_verify(fips_sig_negative, sizeof(fips_sig_negative), -1) || + !test_verify(fips_sig_extra, sizeof(fips_sig_extra), -1) || + !test_verify(fips_sig_bad_length, sizeof(fips_sig_bad_length), -1) || + !test_verify(fips_sig_bad_r, sizeof(fips_sig_bad_r), 0)) { + ERR_print_errors_fp(stderr); + return 1; + } + + printf("PASS\n"); + return 0; +} + +static int dsa_cb(int p, int n, BN_GENCB *arg) { + char c = '*'; + static int ok = 0, num = 0; + + switch (p) { + case 0: + c = '.'; + num++; + break; + case 1: + c = '+'; + break; + case 2: + c = '*'; + ok++; + break; + case 3: + c = '\n'; + } + + fputc(c, arg->arg); + fflush(arg->arg); + + if (!ok && p == 0 && num > 1) { + fprintf(stderr, "error in dsatest\n"); + return 0; + } + + return 1; +} diff --git a/external/boringssl/crypto/ec/CMakeLists.txt b/external/boringssl/crypto/ec/CMakeLists.txt new file mode 100644 index 0000000000..0d429e0bef --- /dev/null +++ b/external/boringssl/crypto/ec/CMakeLists.txt @@ -0,0 +1,53 @@ +include_directories(../../include) + +if (${ARCH} STREQUAL "x86_64") + set( + EC_ARCH_SOURCES + + p256-x86_64-asm.${ASM_EXT} + ) +endif() + +add_library( + ec + + OBJECT + + ec.c + ec_asn1.c + ec_key.c + ec_montgomery.c + oct.c + p224-64.c + p256-64.c + p256-x86_64.c + simple.c + util-64.c + wnaf.c + + ${EC_ARCH_SOURCES} +) + +perlasm(p256-x86_64-asm.${ASM_EXT} asm/p256-x86_64-asm.pl) + +if(ENABLE_TESTS) +add_executable( + example_mul + + example_mul.c + + $ +) + +add_executable( + ec_test + + ec_test.cc + + $ +) + +target_link_libraries(example_mul crypto) +target_link_libraries(ec_test crypto) +add_dependencies(all_tests example_mul ec_test) +endif() diff --git a/external/boringssl/crypto/ec/asm/p256-x86_64-asm.pl b/external/boringssl/crypto/ec/asm/p256-x86_64-asm.pl new file mode 100755 index 0000000000..50a5fe6ee9 --- /dev/null +++ b/external/boringssl/crypto/ec/asm/p256-x86_64-asm.pl @@ -0,0 +1,2734 @@ +#!/usr/bin/env perl + +# Copyright (c) 2014, Intel Corporation. +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +# Developers and authors: +# Shay Gueron (1, 2), and Vlad Krasnov (1) +# (1) Intel Corporation, Israel Development Center +# (2) University of Haifa + +# Reference: +# S.Gueron and V.Krasnov, "Fast Prime Field Elliptic Curve Cryptography with +# 256 Bit Primes" + +# Further optimization by : +# +# this/original +# Opteron +12-49% +# Bulldozer +14-45% +# P4 +18-46% +# Westmere +12-34% +# Sandy Bridge +9-35% +# Ivy Bridge +9-35% +# Haswell +8-37% +# Broadwell +18-58% +# Atom +15-50% +# VIA Nano +43-160% +# +# Ranges denote minimum and maximum improvement coefficients depending +# on benchmark. + +$flavour = shift; +$output = shift; +if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } + +$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or +die "can't locate x86_64-xlate.pl"; + +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; + +# TODO: enable these after testing. $avx goes to two and $addx to one. +$avx=0; +$addx=0; + +$code.=<<___; +.text +.extern OPENSSL_ia32cap_P + +# The polynomial +.align 64 +.Lpoly: +.quad 0xffffffffffffffff, 0x00000000ffffffff, 0x0000000000000000, 0xffffffff00000001 + +.LOne: +.long 1,1,1,1,1,1,1,1 +.LTwo: +.long 2,2,2,2,2,2,2,2 +.LThree: +.long 3,3,3,3,3,3,3,3 +.LONE_mont: +.quad 0x0000000000000001, 0xffffffff00000000, 0xffffffffffffffff, 0x00000000fffffffe +___ + +{ +################################################################################ +# void ecp_nistz256_mul_by_2(uint64_t res[4], uint64_t a[4]); + +my ($a0,$a1,$a2,$a3)=map("%r$_",(8..11)); +my ($t0,$t1,$t2,$t3,$t4)=("%rax","%rdx","%rcx","%r12","%r13"); +my ($r_ptr,$a_ptr,$b_ptr)=("%rdi","%rsi","%rdx"); + +$code.=<<___; + +.type ecp_nistz256_mul_by_2,\@function,2 +.align 64 +ecp_nistz256_mul_by_2: + push %r12 + push %r13 + + mov 8*0($a_ptr), $a0 + mov 8*1($a_ptr), $a1 + add $a0, $a0 # a0:a3+a0:a3 + mov 8*2($a_ptr), $a2 + adc $a1, $a1 + mov 8*3($a_ptr), $a3 + lea .Lpoly(%rip), $a_ptr + mov $a0, $t0 + adc $a2, $a2 + adc $a3, $a3 + mov $a1, $t1 + sbb $t4, $t4 + + sub 8*0($a_ptr), $a0 + mov $a2, $t2 + sbb 8*1($a_ptr), $a1 + sbb 8*2($a_ptr), $a2 + mov $a3, $t3 + sbb 8*3($a_ptr), $a3 + test $t4, $t4 + + cmovz $t0, $a0 + cmovz $t1, $a1 + mov $a0, 8*0($r_ptr) + cmovz $t2, $a2 + mov $a1, 8*1($r_ptr) + cmovz $t3, $a3 + mov $a2, 8*2($r_ptr) + mov $a3, 8*3($r_ptr) + + pop %r13 + pop %r12 + ret +.size ecp_nistz256_mul_by_2,.-ecp_nistz256_mul_by_2 + +################################################################################ +# void ecp_nistz256_neg(uint64_t res[4], uint64_t a[4]); +.globl ecp_nistz256_neg +.type ecp_nistz256_neg,\@function,2 +.align 32 +ecp_nistz256_neg: + push %r12 + push %r13 + + xor $a0, $a0 + xor $a1, $a1 + xor $a2, $a2 + xor $a3, $a3 + xor $t4, $t4 + + sub 8*0($a_ptr), $a0 + sbb 8*1($a_ptr), $a1 + sbb 8*2($a_ptr), $a2 + mov $a0, $t0 + sbb 8*3($a_ptr), $a3 + lea .Lpoly(%rip), $a_ptr + mov $a1, $t1 + sbb \$0, $t4 + + add 8*0($a_ptr), $a0 + mov $a2, $t2 + adc 8*1($a_ptr), $a1 + adc 8*2($a_ptr), $a2 + mov $a3, $t3 + adc 8*3($a_ptr), $a3 + test $t4, $t4 + + cmovz $t0, $a0 + cmovz $t1, $a1 + mov $a0, 8*0($r_ptr) + cmovz $t2, $a2 + mov $a1, 8*1($r_ptr) + cmovz $t3, $a3 + mov $a2, 8*2($r_ptr) + mov $a3, 8*3($r_ptr) + + pop %r13 + pop %r12 + ret +.size ecp_nistz256_neg,.-ecp_nistz256_neg +___ +} +{ +my ($r_ptr,$a_ptr,$b_org,$b_ptr)=("%rdi","%rsi","%rdx","%rbx"); +my ($acc0,$acc1,$acc2,$acc3,$acc4,$acc5,$acc6,$acc7)=map("%r$_",(8..15)); +my ($t0,$t1,$t2,$t3,$t4)=("%rcx","%rbp","%rbx","%rdx","%rax"); +my ($poly1,$poly3)=($acc6,$acc7); + +$code.=<<___; +################################################################################ +# void ecp_nistz256_mul_mont( +# uint64_t res[4], +# uint64_t a[4], +# uint64_t b[4]); + +.globl ecp_nistz256_mul_mont +.type ecp_nistz256_mul_mont,\@function,3 +.align 32 +ecp_nistz256_mul_mont: +___ +$code.=<<___ if ($addx); + mov \$0x80100, %ecx + and OPENSSL_ia32cap_P+8(%rip), %ecx +___ +$code.=<<___; +.Lmul_mont: + push %rbp + push %rbx + push %r12 + push %r13 + push %r14 + push %r15 +___ +$code.=<<___ if ($addx); + cmp \$0x80100, %ecx + je .Lmul_montx +___ +$code.=<<___; + mov $b_org, $b_ptr + mov 8*0($b_org), %rax + mov 8*0($a_ptr), $acc1 + mov 8*1($a_ptr), $acc2 + mov 8*2($a_ptr), $acc3 + mov 8*3($a_ptr), $acc4 + + call __ecp_nistz256_mul_montq +___ +$code.=<<___ if ($addx); + jmp .Lmul_mont_done + +.align 32 +.Lmul_montx: + mov $b_org, $b_ptr + mov 8*0($b_org), %rdx + mov 8*0($a_ptr), $acc1 + mov 8*1($a_ptr), $acc2 + mov 8*2($a_ptr), $acc3 + mov 8*3($a_ptr), $acc4 + lea -128($a_ptr), $a_ptr # control u-op density + + call __ecp_nistz256_mul_montx +___ +$code.=<<___; +.Lmul_mont_done: + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbx + pop %rbp + ret +.size ecp_nistz256_mul_mont,.-ecp_nistz256_mul_mont + +.type __ecp_nistz256_mul_montq,\@abi-omnipotent +.align 32 +__ecp_nistz256_mul_montq: + ######################################################################## + # Multiply a by b[0] + mov %rax, $t1 + mulq $acc1 + mov .Lpoly+8*1(%rip),$poly1 + mov %rax, $acc0 + mov $t1, %rax + mov %rdx, $acc1 + + mulq $acc2 + mov .Lpoly+8*3(%rip),$poly3 + add %rax, $acc1 + mov $t1, %rax + adc \$0, %rdx + mov %rdx, $acc2 + + mulq $acc3 + add %rax, $acc2 + mov $t1, %rax + adc \$0, %rdx + mov %rdx, $acc3 + + mulq $acc4 + add %rax, $acc3 + mov $acc0, %rax + adc \$0, %rdx + xor $acc5, $acc5 + mov %rdx, $acc4 + + ######################################################################## + # First reduction step + # Basically now we want to multiply acc[0] by p256, + # and add the result to the acc. + # Due to the special form of p256 we do some optimizations + # + # acc[0] x p256[0..1] = acc[0] x 2^96 - acc[0] + # then we add acc[0] and get acc[0] x 2^96 + + mov $acc0, $t1 + shl \$32, $acc0 + mulq $poly3 + shr \$32, $t1 + add $acc0, $acc1 # +=acc[0]<<96 + adc $t1, $acc2 + adc %rax, $acc3 + mov 8*1($b_ptr), %rax + adc %rdx, $acc4 + adc \$0, $acc5 + xor $acc0, $acc0 + + ######################################################################## + # Multiply by b[1] + mov %rax, $t1 + mulq 8*0($a_ptr) + add %rax, $acc1 + mov $t1, %rax + adc \$0, %rdx + mov %rdx, $t0 + + mulq 8*1($a_ptr) + add $t0, $acc2 + adc \$0, %rdx + add %rax, $acc2 + mov $t1, %rax + adc \$0, %rdx + mov %rdx, $t0 + + mulq 8*2($a_ptr) + add $t0, $acc3 + adc \$0, %rdx + add %rax, $acc3 + mov $t1, %rax + adc \$0, %rdx + mov %rdx, $t0 + + mulq 8*3($a_ptr) + add $t0, $acc4 + adc \$0, %rdx + add %rax, $acc4 + mov $acc1, %rax + adc %rdx, $acc5 + adc \$0, $acc0 + + ######################################################################## + # Second reduction step + mov $acc1, $t1 + shl \$32, $acc1 + mulq $poly3 + shr \$32, $t1 + add $acc1, $acc2 + adc $t1, $acc3 + adc %rax, $acc4 + mov 8*2($b_ptr), %rax + adc %rdx, $acc5 + adc \$0, $acc0 + xor $acc1, $acc1 + + ######################################################################## + # Multiply by b[2] + mov %rax, $t1 + mulq 8*0($a_ptr) + add %rax, $acc2 + mov $t1, %rax + adc \$0, %rdx + mov %rdx, $t0 + + mulq 8*1($a_ptr) + add $t0, $acc3 + adc \$0, %rdx + add %rax, $acc3 + mov $t1, %rax + adc \$0, %rdx + mov %rdx, $t0 + + mulq 8*2($a_ptr) + add $t0, $acc4 + adc \$0, %rdx + add %rax, $acc4 + mov $t1, %rax + adc \$0, %rdx + mov %rdx, $t0 + + mulq 8*3($a_ptr) + add $t0, $acc5 + adc \$0, %rdx + add %rax, $acc5 + mov $acc2, %rax + adc %rdx, $acc0 + adc \$0, $acc1 + + ######################################################################## + # Third reduction step + mov $acc2, $t1 + shl \$32, $acc2 + mulq $poly3 + shr \$32, $t1 + add $acc2, $acc3 + adc $t1, $acc4 + adc %rax, $acc5 + mov 8*3($b_ptr), %rax + adc %rdx, $acc0 + adc \$0, $acc1 + xor $acc2, $acc2 + + ######################################################################## + # Multiply by b[3] + mov %rax, $t1 + mulq 8*0($a_ptr) + add %rax, $acc3 + mov $t1, %rax + adc \$0, %rdx + mov %rdx, $t0 + + mulq 8*1($a_ptr) + add $t0, $acc4 + adc \$0, %rdx + add %rax, $acc4 + mov $t1, %rax + adc \$0, %rdx + mov %rdx, $t0 + + mulq 8*2($a_ptr) + add $t0, $acc5 + adc \$0, %rdx + add %rax, $acc5 + mov $t1, %rax + adc \$0, %rdx + mov %rdx, $t0 + + mulq 8*3($a_ptr) + add $t0, $acc0 + adc \$0, %rdx + add %rax, $acc0 + mov $acc3, %rax + adc %rdx, $acc1 + adc \$0, $acc2 + + ######################################################################## + # Final reduction step + mov $acc3, $t1 + shl \$32, $acc3 + mulq $poly3 + shr \$32, $t1 + add $acc3, $acc4 + adc $t1, $acc5 + mov $acc4, $t0 + adc %rax, $acc0 + adc %rdx, $acc1 + mov $acc5, $t1 + adc \$0, $acc2 + + ######################################################################## + # Branch-less conditional subtraction of P + sub \$-1, $acc4 # .Lpoly[0] + mov $acc0, $t2 + sbb $poly1, $acc5 # .Lpoly[1] + sbb \$0, $acc0 # .Lpoly[2] + mov $acc1, $t3 + sbb $poly3, $acc1 # .Lpoly[3] + sbb \$0, $acc2 + + cmovc $t0, $acc4 + cmovc $t1, $acc5 + mov $acc4, 8*0($r_ptr) + cmovc $t2, $acc0 + mov $acc5, 8*1($r_ptr) + cmovc $t3, $acc1 + mov $acc0, 8*2($r_ptr) + mov $acc1, 8*3($r_ptr) + + ret +.size __ecp_nistz256_mul_montq,.-__ecp_nistz256_mul_montq + +################################################################################ +# void ecp_nistz256_sqr_mont( +# uint64_t res[4], +# uint64_t a[4]); + +# we optimize the square according to S.Gueron and V.Krasnov, +# "Speeding up Big-Number Squaring" +.globl ecp_nistz256_sqr_mont +.type ecp_nistz256_sqr_mont,\@function,2 +.align 32 +ecp_nistz256_sqr_mont: +___ +$code.=<<___ if ($addx); + mov \$0x80100, %ecx + and OPENSSL_ia32cap_P+8(%rip), %ecx +___ +$code.=<<___; + push %rbp + push %rbx + push %r12 + push %r13 + push %r14 + push %r15 +___ +$code.=<<___ if ($addx); + cmp \$0x80100, %ecx + je .Lsqr_montx +___ +$code.=<<___; + mov 8*0($a_ptr), %rax + mov 8*1($a_ptr), $acc6 + mov 8*2($a_ptr), $acc7 + mov 8*3($a_ptr), $acc0 + + call __ecp_nistz256_sqr_montq +___ +$code.=<<___ if ($addx); + jmp .Lsqr_mont_done + +.align 32 +.Lsqr_montx: + mov 8*0($a_ptr), %rdx + mov 8*1($a_ptr), $acc6 + mov 8*2($a_ptr), $acc7 + mov 8*3($a_ptr), $acc0 + lea -128($a_ptr), $a_ptr # control u-op density + + call __ecp_nistz256_sqr_montx +___ +$code.=<<___; +.Lsqr_mont_done: + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbx + pop %rbp + ret +.size ecp_nistz256_sqr_mont,.-ecp_nistz256_sqr_mont + +.type __ecp_nistz256_sqr_montq,\@abi-omnipotent +.align 32 +__ecp_nistz256_sqr_montq: + mov %rax, $acc5 + mulq $acc6 # a[1]*a[0] + mov %rax, $acc1 + mov $acc7, %rax + mov %rdx, $acc2 + + mulq $acc5 # a[0]*a[2] + add %rax, $acc2 + mov $acc0, %rax + adc \$0, %rdx + mov %rdx, $acc3 + + mulq $acc5 # a[0]*a[3] + add %rax, $acc3 + mov $acc7, %rax + adc \$0, %rdx + mov %rdx, $acc4 + + ################################# + mulq $acc6 # a[1]*a[2] + add %rax, $acc3 + mov $acc0, %rax + adc \$0, %rdx + mov %rdx, $t1 + + mulq $acc6 # a[1]*a[3] + add %rax, $acc4 + mov $acc0, %rax + adc \$0, %rdx + add $t1, $acc4 + mov %rdx, $acc5 + adc \$0, $acc5 + + ################################# + mulq $acc7 # a[2]*a[3] + xor $acc7, $acc7 + add %rax, $acc5 + mov 8*0($a_ptr), %rax + mov %rdx, $acc6 + adc \$0, $acc6 + + add $acc1, $acc1 # acc1:6<<1 + adc $acc2, $acc2 + adc $acc3, $acc3 + adc $acc4, $acc4 + adc $acc5, $acc5 + adc $acc6, $acc6 + adc \$0, $acc7 + + mulq %rax + mov %rax, $acc0 + mov 8*1($a_ptr), %rax + mov %rdx, $t0 + + mulq %rax + add $t0, $acc1 + adc %rax, $acc2 + mov 8*2($a_ptr), %rax + adc \$0, %rdx + mov %rdx, $t0 + + mulq %rax + add $t0, $acc3 + adc %rax, $acc4 + mov 8*3($a_ptr), %rax + adc \$0, %rdx + mov %rdx, $t0 + + mulq %rax + add $t0, $acc5 + adc %rax, $acc6 + mov $acc0, %rax + adc %rdx, $acc7 + + mov .Lpoly+8*1(%rip), $a_ptr + mov .Lpoly+8*3(%rip), $t1 + + ########################################## + # Now the reduction + # First iteration + mov $acc0, $t0 + shl \$32, $acc0 + mulq $t1 + shr \$32, $t0 + add $acc0, $acc1 # +=acc[0]<<96 + adc $t0, $acc2 + adc %rax, $acc3 + mov $acc1, %rax + adc \$0, %rdx + + ########################################## + # Second iteration + mov $acc1, $t0 + shl \$32, $acc1 + mov %rdx, $acc0 + mulq $t1 + shr \$32, $t0 + add $acc1, $acc2 + adc $t0, $acc3 + adc %rax, $acc0 + mov $acc2, %rax + adc \$0, %rdx + + ########################################## + # Third iteration + mov $acc2, $t0 + shl \$32, $acc2 + mov %rdx, $acc1 + mulq $t1 + shr \$32, $t0 + add $acc2, $acc3 + adc $t0, $acc0 + adc %rax, $acc1 + mov $acc3, %rax + adc \$0, %rdx + + ########################################### + # Last iteration + mov $acc3, $t0 + shl \$32, $acc3 + mov %rdx, $acc2 + mulq $t1 + shr \$32, $t0 + add $acc3, $acc0 + adc $t0, $acc1 + adc %rax, $acc2 + adc \$0, %rdx + xor $acc3, $acc3 + + ############################################ + # Add the rest of the acc + add $acc0, $acc4 + adc $acc1, $acc5 + mov $acc4, $acc0 + adc $acc2, $acc6 + adc %rdx, $acc7 + mov $acc5, $acc1 + adc \$0, $acc3 + + sub \$-1, $acc4 # .Lpoly[0] + mov $acc6, $acc2 + sbb $a_ptr, $acc5 # .Lpoly[1] + sbb \$0, $acc6 # .Lpoly[2] + mov $acc7, $t0 + sbb $t1, $acc7 # .Lpoly[3] + sbb \$0, $acc3 + + cmovc $acc0, $acc4 + cmovc $acc1, $acc5 + mov $acc4, 8*0($r_ptr) + cmovc $acc2, $acc6 + mov $acc5, 8*1($r_ptr) + cmovc $t0, $acc7 + mov $acc6, 8*2($r_ptr) + mov $acc7, 8*3($r_ptr) + + ret +.size __ecp_nistz256_sqr_montq,.-__ecp_nistz256_sqr_montq +___ + +if ($addx) { +$code.=<<___; +.type __ecp_nistz256_mul_montx,\@abi-omnipotent +.align 32 +__ecp_nistz256_mul_montx: + ######################################################################## + # Multiply by b[0] + mulx $acc1, $acc0, $acc1 + mulx $acc2, $t0, $acc2 + mov \$32, $poly1 + xor $acc5, $acc5 # cf=0 + mulx $acc3, $t1, $acc3 + mov .Lpoly+8*3(%rip), $poly3 + adc $t0, $acc1 + mulx $acc4, $t0, $acc4 + mov $acc0, %rdx + adc $t1, $acc2 + shlx $poly1,$acc0,$t1 + adc $t0, $acc3 + shrx $poly1,$acc0,$t0 + adc \$0, $acc4 + + ######################################################################## + # First reduction step + add $t1, $acc1 + adc $t0, $acc2 + + mulx $poly3, $t0, $t1 + mov 8*1($b_ptr), %rdx + adc $t0, $acc3 + adc $t1, $acc4 + adc \$0, $acc5 + xor $acc0, $acc0 # $acc0=0,cf=0,of=0 + + ######################################################################## + # Multiply by b[1] + mulx 8*0+128($a_ptr), $t0, $t1 + adcx $t0, $acc1 + adox $t1, $acc2 + + mulx 8*1+128($a_ptr), $t0, $t1 + adcx $t0, $acc2 + adox $t1, $acc3 + + mulx 8*2+128($a_ptr), $t0, $t1 + adcx $t0, $acc3 + adox $t1, $acc4 + + mulx 8*3+128($a_ptr), $t0, $t1 + mov $acc1, %rdx + adcx $t0, $acc4 + shlx $poly1, $acc1, $t0 + adox $t1, $acc5 + shrx $poly1, $acc1, $t1 + + adcx $acc0, $acc5 + adox $acc0, $acc0 + adc \$0, $acc0 + + ######################################################################## + # Second reduction step + add $t0, $acc2 + adc $t1, $acc3 + + mulx $poly3, $t0, $t1 + mov 8*2($b_ptr), %rdx + adc $t0, $acc4 + adc $t1, $acc5 + adc \$0, $acc0 + xor $acc1 ,$acc1 # $acc1=0,cf=0,of=0 + + ######################################################################## + # Multiply by b[2] + mulx 8*0+128($a_ptr), $t0, $t1 + adcx $t0, $acc2 + adox $t1, $acc3 + + mulx 8*1+128($a_ptr), $t0, $t1 + adcx $t0, $acc3 + adox $t1, $acc4 + + mulx 8*2+128($a_ptr), $t0, $t1 + adcx $t0, $acc4 + adox $t1, $acc5 + + mulx 8*3+128($a_ptr), $t0, $t1 + mov $acc2, %rdx + adcx $t0, $acc5 + shlx $poly1, $acc2, $t0 + adox $t1, $acc0 + shrx $poly1, $acc2, $t1 + + adcx $acc1, $acc0 + adox $acc1, $acc1 + adc \$0, $acc1 + + ######################################################################## + # Third reduction step + add $t0, $acc3 + adc $t1, $acc4 + + mulx $poly3, $t0, $t1 + mov 8*3($b_ptr), %rdx + adc $t0, $acc5 + adc $t1, $acc0 + adc \$0, $acc1 + xor $acc2, $acc2 # $acc2=0,cf=0,of=0 + + ######################################################################## + # Multiply by b[3] + mulx 8*0+128($a_ptr), $t0, $t1 + adcx $t0, $acc3 + adox $t1, $acc4 + + mulx 8*1+128($a_ptr), $t0, $t1 + adcx $t0, $acc4 + adox $t1, $acc5 + + mulx 8*2+128($a_ptr), $t0, $t1 + adcx $t0, $acc5 + adox $t1, $acc0 + + mulx 8*3+128($a_ptr), $t0, $t1 + mov $acc3, %rdx + adcx $t0, $acc0 + shlx $poly1, $acc3, $t0 + adox $t1, $acc1 + shrx $poly1, $acc3, $t1 + + adcx $acc2, $acc1 + adox $acc2, $acc2 + adc \$0, $acc2 + + ######################################################################## + # Fourth reduction step + add $t0, $acc4 + adc $t1, $acc5 + + mulx $poly3, $t0, $t1 + mov $acc4, $t2 + mov .Lpoly+8*1(%rip), $poly1 + adc $t0, $acc0 + mov $acc5, $t3 + adc $t1, $acc1 + adc \$0, $acc2 + + ######################################################################## + # Branch-less conditional subtraction of P + xor %eax, %eax + mov $acc0, $t0 + sbb \$-1, $acc4 # .Lpoly[0] + sbb $poly1, $acc5 # .Lpoly[1] + sbb \$0, $acc0 # .Lpoly[2] + mov $acc1, $t1 + sbb $poly3, $acc1 # .Lpoly[3] + sbb \$0, $acc2 + + cmovc $t2, $acc4 + cmovc $t3, $acc5 + mov $acc4, 8*0($r_ptr) + cmovc $t0, $acc0 + mov $acc5, 8*1($r_ptr) + cmovc $t1, $acc1 + mov $acc0, 8*2($r_ptr) + mov $acc1, 8*3($r_ptr) + + ret +.size __ecp_nistz256_mul_montx,.-__ecp_nistz256_mul_montx + +.type __ecp_nistz256_sqr_montx,\@abi-omnipotent +.align 32 +__ecp_nistz256_sqr_montx: + mulx $acc6, $acc1, $acc2 # a[0]*a[1] + mulx $acc7, $t0, $acc3 # a[0]*a[2] + xor %eax, %eax + adc $t0, $acc2 + mulx $acc0, $t1, $acc4 # a[0]*a[3] + mov $acc6, %rdx + adc $t1, $acc3 + adc \$0, $acc4 + xor $acc5, $acc5 # $acc5=0,cf=0,of=0 + + ################################# + mulx $acc7, $t0, $t1 # a[1]*a[2] + adcx $t0, $acc3 + adox $t1, $acc4 + + mulx $acc0, $t0, $t1 # a[1]*a[3] + mov $acc7, %rdx + adcx $t0, $acc4 + adox $t1, $acc5 + adc \$0, $acc5 + + ################################# + mulx $acc0, $t0, $acc6 # a[2]*a[3] + mov 8*0+128($a_ptr), %rdx + xor $acc7, $acc7 # $acc7=0,cf=0,of=0 + adcx $acc1, $acc1 # acc1:6<<1 + adox $t0, $acc5 + adcx $acc2, $acc2 + adox $acc7, $acc6 # of=0 + + mulx %rdx, $acc0, $t1 + mov 8*1+128($a_ptr), %rdx + adcx $acc3, $acc3 + adox $t1, $acc1 + adcx $acc4, $acc4 + mulx %rdx, $t0, $t4 + mov 8*2+128($a_ptr), %rdx + adcx $acc5, $acc5 + adox $t0, $acc2 + adcx $acc6, $acc6 + .byte 0x67 + mulx %rdx, $t0, $t1 + mov 8*3+128($a_ptr), %rdx + adox $t4, $acc3 + adcx $acc7, $acc7 + adox $t0, $acc4 + mov \$32, $a_ptr + adox $t1, $acc5 + .byte 0x67,0x67 + mulx %rdx, $t0, $t4 + mov $acc0, %rdx + adox $t0, $acc6 + shlx $a_ptr, $acc0, $t0 + adox $t4, $acc7 + shrx $a_ptr, $acc0, $t4 + mov .Lpoly+8*3(%rip), $t1 + + # reduction step 1 + add $t0, $acc1 + adc $t4, $acc2 + + mulx $t1, $t0, $acc0 + mov $acc1, %rdx + adc $t0, $acc3 + shlx $a_ptr, $acc1, $t0 + adc \$0, $acc0 + shrx $a_ptr, $acc1, $t4 + + # reduction step 2 + add $t0, $acc2 + adc $t4, $acc3 + + mulx $t1, $t0, $acc1 + mov $acc2, %rdx + adc $t0, $acc0 + shlx $a_ptr, $acc2, $t0 + adc \$0, $acc1 + shrx $a_ptr, $acc2, $t4 + + # reduction step 3 + add $t0, $acc3 + adc $t4, $acc0 + + mulx $t1, $t0, $acc2 + mov $acc3, %rdx + adc $t0, $acc1 + shlx $a_ptr, $acc3, $t0 + adc \$0, $acc2 + shrx $a_ptr, $acc3, $t4 + + # reduction step 4 + add $t0, $acc0 + adc $t4, $acc1 + + mulx $t1, $t0, $acc3 + adc $t0, $acc2 + adc \$0, $acc3 + + xor $t3, $t3 # cf=0 + adc $acc0, $acc4 # accumulate upper half + mov .Lpoly+8*1(%rip), $a_ptr + adc $acc1, $acc5 + mov $acc4, $acc0 + adc $acc2, $acc6 + adc $acc3, $acc7 + mov $acc5, $acc1 + adc \$0, $t3 + + xor %eax, %eax # cf=0 + sbb \$-1, $acc4 # .Lpoly[0] + mov $acc6, $acc2 + sbb $a_ptr, $acc5 # .Lpoly[1] + sbb \$0, $acc6 # .Lpoly[2] + mov $acc7, $acc3 + sbb $t1, $acc7 # .Lpoly[3] + sbb \$0, $t3 + + cmovc $acc0, $acc4 + cmovc $acc1, $acc5 + mov $acc4, 8*0($r_ptr) + cmovc $acc2, $acc6 + mov $acc5, 8*1($r_ptr) + cmovc $acc3, $acc7 + mov $acc6, 8*2($r_ptr) + mov $acc7, 8*3($r_ptr) + + ret +.size __ecp_nistz256_sqr_montx,.-__ecp_nistz256_sqr_montx +___ +} +} +{ +my ($r_ptr,$in_ptr)=("%rdi","%rsi"); +my ($acc0,$acc1,$acc2,$acc3)=map("%r$_",(8..11)); +my ($t0,$t1,$t2)=("%rcx","%r12","%r13"); + +$code.=<<___; +################################################################################ +# void ecp_nistz256_from_mont( +# uint64_t res[4], +# uint64_t in[4]); +# This one performs Montgomery multiplication by 1, so we only need the reduction + +.globl ecp_nistz256_from_mont +.type ecp_nistz256_from_mont,\@function,2 +.align 32 +ecp_nistz256_from_mont: + push %r12 + push %r13 + + mov 8*0($in_ptr), %rax + mov .Lpoly+8*3(%rip), $t2 + mov 8*1($in_ptr), $acc1 + mov 8*2($in_ptr), $acc2 + mov 8*3($in_ptr), $acc3 + mov %rax, $acc0 + mov .Lpoly+8*1(%rip), $t1 + + ######################################### + # First iteration + mov %rax, $t0 + shl \$32, $acc0 + mulq $t2 + shr \$32, $t0 + add $acc0, $acc1 + adc $t0, $acc2 + adc %rax, $acc3 + mov $acc1, %rax + adc \$0, %rdx + + ######################################### + # Second iteration + mov $acc1, $t0 + shl \$32, $acc1 + mov %rdx, $acc0 + mulq $t2 + shr \$32, $t0 + add $acc1, $acc2 + adc $t0, $acc3 + adc %rax, $acc0 + mov $acc2, %rax + adc \$0, %rdx + + ########################################## + # Third iteration + mov $acc2, $t0 + shl \$32, $acc2 + mov %rdx, $acc1 + mulq $t2 + shr \$32, $t0 + add $acc2, $acc3 + adc $t0, $acc0 + adc %rax, $acc1 + mov $acc3, %rax + adc \$0, %rdx + + ########################################### + # Last iteration + mov $acc3, $t0 + shl \$32, $acc3 + mov %rdx, $acc2 + mulq $t2 + shr \$32, $t0 + add $acc3, $acc0 + adc $t0, $acc1 + mov $acc0, $t0 + adc %rax, $acc2 + mov $acc1, $in_ptr + adc \$0, %rdx + + sub \$-1, $acc0 + mov $acc2, %rax + sbb $t1, $acc1 + sbb \$0, $acc2 + mov %rdx, $acc3 + sbb $t2, %rdx + sbb $t2, $t2 + + cmovnz $t0, $acc0 + cmovnz $in_ptr, $acc1 + mov $acc0, 8*0($r_ptr) + cmovnz %rax, $acc2 + mov $acc1, 8*1($r_ptr) + cmovz %rdx, $acc3 + mov $acc2, 8*2($r_ptr) + mov $acc3, 8*3($r_ptr) + + pop %r13 + pop %r12 + ret +.size ecp_nistz256_from_mont,.-ecp_nistz256_from_mont +___ +} +{ +my ($val,$in_t,$index)=$win64?("%rcx","%rdx","%r8d"):("%rdi","%rsi","%edx"); +my ($ONE,$INDEX,$Ra,$Rb,$Rc,$Rd,$Re,$Rf)=map("%xmm$_",(0..7)); +my ($M0,$T0a,$T0b,$T0c,$T0d,$T0e,$T0f,$TMP0)=map("%xmm$_",(8..15)); +my ($M1,$T2a,$T2b,$TMP2,$M2,$T2a,$T2b,$TMP2)=map("%xmm$_",(8..15)); + +$code.=<<___; +################################################################################ +# void ecp_nistz256_select_w5(uint64_t *val, uint64_t *in_t, int index); +.globl ecp_nistz256_select_w5 +.type ecp_nistz256_select_w5,\@abi-omnipotent +.align 32 +ecp_nistz256_select_w5: +___ +$code.=<<___ if ($avx>1); + mov OPENSSL_ia32cap_P+8(%rip), %eax + test \$`1<<5`, %eax + jnz .Lavx2_select_w5 +___ +$code.=<<___ if ($win64); + lea -0x88(%rsp), %rax +.LSEH_begin_ecp_nistz256_select_w5: + .byte 0x48,0x8d,0x60,0xe0 #lea -0x20(%rax), %rsp + .byte 0x0f,0x29,0x70,0xe0 #movaps %xmm6, -0x20(%rax) + .byte 0x0f,0x29,0x78,0xf0 #movaps %xmm7, -0x10(%rax) + .byte 0x44,0x0f,0x29,0x00 #movaps %xmm8, 0(%rax) + .byte 0x44,0x0f,0x29,0x48,0x10 #movaps %xmm9, 0x10(%rax) + .byte 0x44,0x0f,0x29,0x50,0x20 #movaps %xmm10, 0x20(%rax) + .byte 0x44,0x0f,0x29,0x58,0x30 #movaps %xmm11, 0x30(%rax) + .byte 0x44,0x0f,0x29,0x60,0x40 #movaps %xmm12, 0x40(%rax) + .byte 0x44,0x0f,0x29,0x68,0x50 #movaps %xmm13, 0x50(%rax) + .byte 0x44,0x0f,0x29,0x70,0x60 #movaps %xmm14, 0x60(%rax) + .byte 0x44,0x0f,0x29,0x78,0x70 #movaps %xmm15, 0x70(%rax) +___ +$code.=<<___; + movdqa .LOne(%rip), $ONE + movd $index, $INDEX + + pxor $Ra, $Ra + pxor $Rb, $Rb + pxor $Rc, $Rc + pxor $Rd, $Rd + pxor $Re, $Re + pxor $Rf, $Rf + + movdqa $ONE, $M0 + pshufd \$0, $INDEX, $INDEX + + mov \$16, %rax +.Lselect_loop_sse_w5: + + movdqa $M0, $TMP0 + paddd $ONE, $M0 + pcmpeqd $INDEX, $TMP0 + + movdqa 16*0($in_t), $T0a + movdqa 16*1($in_t), $T0b + movdqa 16*2($in_t), $T0c + movdqa 16*3($in_t), $T0d + movdqa 16*4($in_t), $T0e + movdqa 16*5($in_t), $T0f + lea 16*6($in_t), $in_t + + pand $TMP0, $T0a + pand $TMP0, $T0b + por $T0a, $Ra + pand $TMP0, $T0c + por $T0b, $Rb + pand $TMP0, $T0d + por $T0c, $Rc + pand $TMP0, $T0e + por $T0d, $Rd + pand $TMP0, $T0f + por $T0e, $Re + por $T0f, $Rf + + dec %rax + jnz .Lselect_loop_sse_w5 + + movdqu $Ra, 16*0($val) + movdqu $Rb, 16*1($val) + movdqu $Rc, 16*2($val) + movdqu $Rd, 16*3($val) + movdqu $Re, 16*4($val) + movdqu $Rf, 16*5($val) +___ +$code.=<<___ if ($win64); + movaps (%rsp), %xmm6 + movaps 0x10(%rsp), %xmm7 + movaps 0x20(%rsp), %xmm8 + movaps 0x30(%rsp), %xmm9 + movaps 0x40(%rsp), %xmm10 + movaps 0x50(%rsp), %xmm11 + movaps 0x60(%rsp), %xmm12 + movaps 0x70(%rsp), %xmm13 + movaps 0x80(%rsp), %xmm14 + movaps 0x90(%rsp), %xmm15 + lea 0xa8(%rsp), %rsp +.LSEH_end_ecp_nistz256_select_w5: +___ +$code.=<<___; + ret +.size ecp_nistz256_select_w5,.-ecp_nistz256_select_w5 + +################################################################################ +# void ecp_nistz256_select_w7(uint64_t *val, uint64_t *in_t, int index); +.globl ecp_nistz256_select_w7 +.type ecp_nistz256_select_w7,\@abi-omnipotent +.align 32 +ecp_nistz256_select_w7: +___ +$code.=<<___ if ($avx>1); + mov OPENSSL_ia32cap_P+8(%rip), %eax + test \$`1<<5`, %eax + jnz .Lavx2_select_w7 +___ +$code.=<<___ if ($win64); + lea -0x88(%rsp), %rax +.LSEH_begin_ecp_nistz256_select_w7: + .byte 0x48,0x8d,0x60,0xe0 #lea -0x20(%rax), %rsp + .byte 0x0f,0x29,0x70,0xe0 #movaps %xmm6, -0x20(%rax) + .byte 0x0f,0x29,0x78,0xf0 #movaps %xmm7, -0x10(%rax) + .byte 0x44,0x0f,0x29,0x00 #movaps %xmm8, 0(%rax) + .byte 0x44,0x0f,0x29,0x48,0x10 #movaps %xmm9, 0x10(%rax) + .byte 0x44,0x0f,0x29,0x50,0x20 #movaps %xmm10, 0x20(%rax) + .byte 0x44,0x0f,0x29,0x58,0x30 #movaps %xmm11, 0x30(%rax) + .byte 0x44,0x0f,0x29,0x60,0x40 #movaps %xmm12, 0x40(%rax) + .byte 0x44,0x0f,0x29,0x68,0x50 #movaps %xmm13, 0x50(%rax) + .byte 0x44,0x0f,0x29,0x70,0x60 #movaps %xmm14, 0x60(%rax) + .byte 0x44,0x0f,0x29,0x78,0x70 #movaps %xmm15, 0x70(%rax) +___ +$code.=<<___; + movdqa .LOne(%rip), $M0 + movd $index, $INDEX + + pxor $Ra, $Ra + pxor $Rb, $Rb + pxor $Rc, $Rc + pxor $Rd, $Rd + + movdqa $M0, $ONE + pshufd \$0, $INDEX, $INDEX + mov \$64, %rax + +.Lselect_loop_sse_w7: + movdqa $M0, $TMP0 + paddd $ONE, $M0 + movdqa 16*0($in_t), $T0a + movdqa 16*1($in_t), $T0b + pcmpeqd $INDEX, $TMP0 + movdqa 16*2($in_t), $T0c + movdqa 16*3($in_t), $T0d + lea 16*4($in_t), $in_t + + pand $TMP0, $T0a + pand $TMP0, $T0b + por $T0a, $Ra + pand $TMP0, $T0c + por $T0b, $Rb + pand $TMP0, $T0d + por $T0c, $Rc + prefetcht0 255($in_t) + por $T0d, $Rd + + dec %rax + jnz .Lselect_loop_sse_w7 + + movdqu $Ra, 16*0($val) + movdqu $Rb, 16*1($val) + movdqu $Rc, 16*2($val) + movdqu $Rd, 16*3($val) +___ +$code.=<<___ if ($win64); + movaps (%rsp), %xmm6 + movaps 0x10(%rsp), %xmm7 + movaps 0x20(%rsp), %xmm8 + movaps 0x30(%rsp), %xmm9 + movaps 0x40(%rsp), %xmm10 + movaps 0x50(%rsp), %xmm11 + movaps 0x60(%rsp), %xmm12 + movaps 0x70(%rsp), %xmm13 + movaps 0x80(%rsp), %xmm14 + movaps 0x90(%rsp), %xmm15 + lea 0xa8(%rsp), %rsp +.LSEH_end_ecp_nistz256_select_w7: +___ +$code.=<<___; + ret +.size ecp_nistz256_select_w7,.-ecp_nistz256_select_w7 +___ +} +if ($avx>1) { +my ($val,$in_t,$index)=$win64?("%rcx","%rdx","%r8d"):("%rdi","%rsi","%edx"); +my ($TWO,$INDEX,$Ra,$Rb,$Rc)=map("%ymm$_",(0..4)); +my ($M0,$T0a,$T0b,$T0c,$TMP0)=map("%ymm$_",(5..9)); +my ($M1,$T1a,$T1b,$T1c,$TMP1)=map("%ymm$_",(10..14)); + +$code.=<<___; +################################################################################ +# void ecp_nistz256_avx2_select_w5(uint64_t *val, uint64_t *in_t, int index); +.type ecp_nistz256_avx2_select_w5,\@abi-omnipotent +.align 32 +ecp_nistz256_avx2_select_w5: +.Lavx2_select_w5: + vzeroupper +___ +$code.=<<___ if ($win64); + lea -0x88(%rsp), %rax +.LSEH_begin_ecp_nistz256_avx2_select_w5: + .byte 0x48,0x8d,0x60,0xe0 #lea -0x20(%rax), %rsp + .byte 0xc5,0xf8,0x29,0x70,0xe0 #vmovaps %xmm6, -0x20(%rax) + .byte 0xc5,0xf8,0x29,0x78,0xf0 #vmovaps %xmm7, -0x10(%rax) + .byte 0xc5,0x78,0x29,0x40,0x00 #vmovaps %xmm8, 8(%rax) + .byte 0xc5,0x78,0x29,0x48,0x10 #vmovaps %xmm9, 0x10(%rax) + .byte 0xc5,0x78,0x29,0x50,0x20 #vmovaps %xmm10, 0x20(%rax) + .byte 0xc5,0x78,0x29,0x58,0x30 #vmovaps %xmm11, 0x30(%rax) + .byte 0xc5,0x78,0x29,0x60,0x40 #vmovaps %xmm12, 0x40(%rax) + .byte 0xc5,0x78,0x29,0x68,0x50 #vmovaps %xmm13, 0x50(%rax) + .byte 0xc5,0x78,0x29,0x70,0x60 #vmovaps %xmm14, 0x60(%rax) + .byte 0xc5,0x78,0x29,0x78,0x70 #vmovaps %xmm15, 0x70(%rax) +___ +$code.=<<___; + vmovdqa .LTwo(%rip), $TWO + + vpxor $Ra, $Ra, $Ra + vpxor $Rb, $Rb, $Rb + vpxor $Rc, $Rc, $Rc + + vmovdqa .LOne(%rip), $M0 + vmovdqa .LTwo(%rip), $M1 + + vmovd $index, %xmm1 + vpermd $INDEX, $Ra, $INDEX + + mov \$8, %rax +.Lselect_loop_avx2_w5: + + vmovdqa 32*0($in_t), $T0a + vmovdqa 32*1($in_t), $T0b + vmovdqa 32*2($in_t), $T0c + + vmovdqa 32*3($in_t), $T1a + vmovdqa 32*4($in_t), $T1b + vmovdqa 32*5($in_t), $T1c + + vpcmpeqd $INDEX, $M0, $TMP0 + vpcmpeqd $INDEX, $M1, $TMP1 + + vpaddd $TWO, $M0, $M0 + vpaddd $TWO, $M1, $M1 + lea 32*6($in_t), $in_t + + vpand $TMP0, $T0a, $T0a + vpand $TMP0, $T0b, $T0b + vpand $TMP0, $T0c, $T0c + vpand $TMP1, $T1a, $T1a + vpand $TMP1, $T1b, $T1b + vpand $TMP1, $T1c, $T1c + + vpxor $T0a, $Ra, $Ra + vpxor $T0b, $Rb, $Rb + vpxor $T0c, $Rc, $Rc + vpxor $T1a, $Ra, $Ra + vpxor $T1b, $Rb, $Rb + vpxor $T1c, $Rc, $Rc + + dec %rax + jnz .Lselect_loop_avx2_w5 + + vmovdqu $Ra, 32*0($val) + vmovdqu $Rb, 32*1($val) + vmovdqu $Rc, 32*2($val) + vzeroupper +___ +$code.=<<___ if ($win64); + movaps (%rsp), %xmm6 + movaps 0x10(%rsp), %xmm7 + movaps 0x20(%rsp), %xmm8 + movaps 0x30(%rsp), %xmm9 + movaps 0x40(%rsp), %xmm10 + movaps 0x50(%rsp), %xmm11 + movaps 0x60(%rsp), %xmm12 + movaps 0x70(%rsp), %xmm13 + movaps 0x80(%rsp), %xmm14 + movaps 0x90(%rsp), %xmm15 + lea 0xa8(%rsp), %rsp +.LSEH_end_ecp_nistz256_avx2_select_w5: +___ +$code.=<<___; + ret +.size ecp_nistz256_avx2_select_w5,.-ecp_nistz256_avx2_select_w5 +___ +} +if ($avx>1) { +my ($val,$in_t,$index)=$win64?("%rcx","%rdx","%r8d"):("%rdi","%rsi","%edx"); +my ($THREE,$INDEX,$Ra,$Rb)=map("%ymm$_",(0..3)); +my ($M0,$T0a,$T0b,$TMP0)=map("%ymm$_",(4..7)); +my ($M1,$T1a,$T1b,$TMP1)=map("%ymm$_",(8..11)); +my ($M2,$T2a,$T2b,$TMP2)=map("%ymm$_",(12..15)); + +$code.=<<___; + +################################################################################ +# void ecp_nistz256_avx2_select_w7(uint64_t *val, uint64_t *in_t, int index); +.globl ecp_nistz256_avx2_select_w7 +.type ecp_nistz256_avx2_select_w7,\@abi-omnipotent +.align 32 +ecp_nistz256_avx2_select_w7: +.Lavx2_select_w7: + vzeroupper +___ +$code.=<<___ if ($win64); + lea -0x88(%rsp), %rax +.LSEH_begin_ecp_nistz256_avx2_select_w7: + .byte 0x48,0x8d,0x60,0xe0 #lea -0x20(%rax), %rsp + .byte 0xc5,0xf8,0x29,0x70,0xe0 #vmovaps %xmm6, -0x20(%rax) + .byte 0xc5,0xf8,0x29,0x78,0xf0 #vmovaps %xmm7, -0x10(%rax) + .byte 0xc5,0x78,0x29,0x40,0x00 #vmovaps %xmm8, 8(%rax) + .byte 0xc5,0x78,0x29,0x48,0x10 #vmovaps %xmm9, 0x10(%rax) + .byte 0xc5,0x78,0x29,0x50,0x20 #vmovaps %xmm10, 0x20(%rax) + .byte 0xc5,0x78,0x29,0x58,0x30 #vmovaps %xmm11, 0x30(%rax) + .byte 0xc5,0x78,0x29,0x60,0x40 #vmovaps %xmm12, 0x40(%rax) + .byte 0xc5,0x78,0x29,0x68,0x50 #vmovaps %xmm13, 0x50(%rax) + .byte 0xc5,0x78,0x29,0x70,0x60 #vmovaps %xmm14, 0x60(%rax) + .byte 0xc5,0x78,0x29,0x78,0x70 #vmovaps %xmm15, 0x70(%rax) +___ +$code.=<<___; + vmovdqa .LThree(%rip), $THREE + + vpxor $Ra, $Ra, $Ra + vpxor $Rb, $Rb, $Rb + + vmovdqa .LOne(%rip), $M0 + vmovdqa .LTwo(%rip), $M1 + vmovdqa .LThree(%rip), $M2 + + vmovd $index, %xmm1 + vpermd $INDEX, $Ra, $INDEX + # Skip index = 0, because it is implicitly the point at infinity + + mov \$21, %rax +.Lselect_loop_avx2_w7: + + vmovdqa 32*0($in_t), $T0a + vmovdqa 32*1($in_t), $T0b + + vmovdqa 32*2($in_t), $T1a + vmovdqa 32*3($in_t), $T1b + + vmovdqa 32*4($in_t), $T2a + vmovdqa 32*5($in_t), $T2b + + vpcmpeqd $INDEX, $M0, $TMP0 + vpcmpeqd $INDEX, $M1, $TMP1 + vpcmpeqd $INDEX, $M2, $TMP2 + + vpaddd $THREE, $M0, $M0 + vpaddd $THREE, $M1, $M1 + vpaddd $THREE, $M2, $M2 + lea 32*6($in_t), $in_t + + vpand $TMP0, $T0a, $T0a + vpand $TMP0, $T0b, $T0b + vpand $TMP1, $T1a, $T1a + vpand $TMP1, $T1b, $T1b + vpand $TMP2, $T2a, $T2a + vpand $TMP2, $T2b, $T2b + + vpxor $T0a, $Ra, $Ra + vpxor $T0b, $Rb, $Rb + vpxor $T1a, $Ra, $Ra + vpxor $T1b, $Rb, $Rb + vpxor $T2a, $Ra, $Ra + vpxor $T2b, $Rb, $Rb + + dec %rax + jnz .Lselect_loop_avx2_w7 + + + vmovdqa 32*0($in_t), $T0a + vmovdqa 32*1($in_t), $T0b + + vpcmpeqd $INDEX, $M0, $TMP0 + + vpand $TMP0, $T0a, $T0a + vpand $TMP0, $T0b, $T0b + + vpxor $T0a, $Ra, $Ra + vpxor $T0b, $Rb, $Rb + + vmovdqu $Ra, 32*0($val) + vmovdqu $Rb, 32*1($val) + vzeroupper +___ +$code.=<<___ if ($win64); + movaps (%rsp), %xmm6 + movaps 0x10(%rsp), %xmm7 + movaps 0x20(%rsp), %xmm8 + movaps 0x30(%rsp), %xmm9 + movaps 0x40(%rsp), %xmm10 + movaps 0x50(%rsp), %xmm11 + movaps 0x60(%rsp), %xmm12 + movaps 0x70(%rsp), %xmm13 + movaps 0x80(%rsp), %xmm14 + movaps 0x90(%rsp), %xmm15 + lea 0xa8(%rsp), %rsp +.LSEH_end_ecp_nistz256_avx2_select_w7: +___ +$code.=<<___; + ret +.size ecp_nistz256_avx2_select_w7,.-ecp_nistz256_avx2_select_w7 +___ +} else { +$code.=<<___; +.globl ecp_nistz256_avx2_select_w7 +.type ecp_nistz256_avx2_select_w7,\@function,3 +.align 32 +ecp_nistz256_avx2_select_w7: + .byte 0x0f,0x0b # ud2 + ret +.size ecp_nistz256_avx2_select_w7,.-ecp_nistz256_avx2_select_w7 +___ +} +{{{ +######################################################################## +# This block implements higher level point_double, point_add and +# point_add_affine. The key to performance in this case is to allow +# out-of-order execution logic to overlap computations from next step +# with tail processing from current step. By using tailored calling +# sequence we minimize inter-step overhead to give processor better +# shot at overlapping operations... +# +# You will notice that input data is copied to stack. Trouble is that +# there are no registers to spare for holding original pointers and +# reloading them, pointers, would create undesired dependencies on +# effective addresses calculation paths. In other words it's too done +# to favour out-of-order execution logic. +# + +my ($r_ptr,$a_ptr,$b_org,$b_ptr)=("%rdi","%rsi","%rdx","%rbx"); +my ($acc0,$acc1,$acc2,$acc3,$acc4,$acc5,$acc6,$acc7)=map("%r$_",(8..15)); +my ($t0,$t1,$t2,$t3,$t4)=("%rax","%rbp","%rcx",$acc4,$acc4); +my ($poly1,$poly3)=($acc6,$acc7); + +sub load_for_mul () { +my ($a,$b,$src0) = @_; +my $bias = $src0 eq "%rax" ? 0 : -128; + +" mov $b, $src0 + lea $b, $b_ptr + mov 8*0+$a, $acc1 + mov 8*1+$a, $acc2 + lea $bias+$a, $a_ptr + mov 8*2+$a, $acc3 + mov 8*3+$a, $acc4" +} + +sub load_for_sqr () { +my ($a,$src0) = @_; +my $bias = $src0 eq "%rax" ? 0 : -128; + +" mov 8*0+$a, $src0 + mov 8*1+$a, $acc6 + lea $bias+$a, $a_ptr + mov 8*2+$a, $acc7 + mov 8*3+$a, $acc0" +} + + { +######################################################################## +# operate in 4-5-0-1 "name space" that matches multiplication output +# +my ($a0,$a1,$a2,$a3,$t3,$t4)=($acc4,$acc5,$acc0,$acc1,$acc2,$acc3); + +$code.=<<___; +.type __ecp_nistz256_add_toq,\@abi-omnipotent +.align 32 +__ecp_nistz256_add_toq: + add 8*0($b_ptr), $a0 + adc 8*1($b_ptr), $a1 + mov $a0, $t0 + adc 8*2($b_ptr), $a2 + adc 8*3($b_ptr), $a3 + mov $a1, $t1 + sbb $t4, $t4 + + sub \$-1, $a0 + mov $a2, $t2 + sbb $poly1, $a1 + sbb \$0, $a2 + mov $a3, $t3 + sbb $poly3, $a3 + test $t4, $t4 + + cmovz $t0, $a0 + cmovz $t1, $a1 + mov $a0, 8*0($r_ptr) + cmovz $t2, $a2 + mov $a1, 8*1($r_ptr) + cmovz $t3, $a3 + mov $a2, 8*2($r_ptr) + mov $a3, 8*3($r_ptr) + + ret +.size __ecp_nistz256_add_toq,.-__ecp_nistz256_add_toq + +.type __ecp_nistz256_sub_fromq,\@abi-omnipotent +.align 32 +__ecp_nistz256_sub_fromq: + sub 8*0($b_ptr), $a0 + sbb 8*1($b_ptr), $a1 + mov $a0, $t0 + sbb 8*2($b_ptr), $a2 + sbb 8*3($b_ptr), $a3 + mov $a1, $t1 + sbb $t4, $t4 + + add \$-1, $a0 + mov $a2, $t2 + adc $poly1, $a1 + adc \$0, $a2 + mov $a3, $t3 + adc $poly3, $a3 + test $t4, $t4 + + cmovz $t0, $a0 + cmovz $t1, $a1 + mov $a0, 8*0($r_ptr) + cmovz $t2, $a2 + mov $a1, 8*1($r_ptr) + cmovz $t3, $a3 + mov $a2, 8*2($r_ptr) + mov $a3, 8*3($r_ptr) + + ret +.size __ecp_nistz256_sub_fromq,.-__ecp_nistz256_sub_fromq + +.type __ecp_nistz256_subq,\@abi-omnipotent +.align 32 +__ecp_nistz256_subq: + sub $a0, $t0 + sbb $a1, $t1 + mov $t0, $a0 + sbb $a2, $t2 + sbb $a3, $t3 + mov $t1, $a1 + sbb $t4, $t4 + + add \$-1, $t0 + mov $t2, $a2 + adc $poly1, $t1 + adc \$0, $t2 + mov $t3, $a3 + adc $poly3, $t3 + test $t4, $t4 + + cmovnz $t0, $a0 + cmovnz $t1, $a1 + cmovnz $t2, $a2 + cmovnz $t3, $a3 + + ret +.size __ecp_nistz256_subq,.-__ecp_nistz256_subq + +.type __ecp_nistz256_mul_by_2q,\@abi-omnipotent +.align 32 +__ecp_nistz256_mul_by_2q: + add $a0, $a0 # a0:a3+a0:a3 + adc $a1, $a1 + mov $a0, $t0 + adc $a2, $a2 + adc $a3, $a3 + mov $a1, $t1 + sbb $t4, $t4 + + sub \$-1, $a0 + mov $a2, $t2 + sbb $poly1, $a1 + sbb \$0, $a2 + mov $a3, $t3 + sbb $poly3, $a3 + test $t4, $t4 + + cmovz $t0, $a0 + cmovz $t1, $a1 + mov $a0, 8*0($r_ptr) + cmovz $t2, $a2 + mov $a1, 8*1($r_ptr) + cmovz $t3, $a3 + mov $a2, 8*2($r_ptr) + mov $a3, 8*3($r_ptr) + + ret +.size __ecp_nistz256_mul_by_2q,.-__ecp_nistz256_mul_by_2q +___ + } +sub gen_double () { + my $x = shift; + my ($src0,$sfx,$bias); + my ($S,$M,$Zsqr,$in_x,$tmp0)=map(32*$_,(0..4)); + + if ($x ne "x") { + $src0 = "%rax"; + $sfx = ""; + $bias = 0; + +$code.=<<___; +.globl ecp_nistz256_point_double +.type ecp_nistz256_point_double,\@function,2 +.align 32 +ecp_nistz256_point_double: +___ +$code.=<<___ if ($addx); + mov \$0x80100, %ecx + and OPENSSL_ia32cap_P+8(%rip), %ecx + cmp \$0x80100, %ecx + je .Lpoint_doublex +___ + } else { + $src0 = "%rdx"; + $sfx = "x"; + $bias = 128; + +$code.=<<___; +.type ecp_nistz256_point_doublex,\@function,2 +.align 32 +ecp_nistz256_point_doublex: +.Lpoint_doublex: +___ + } +$code.=<<___; + push %rbp + push %rbx + push %r12 + push %r13 + push %r14 + push %r15 + sub \$32*5+8, %rsp + +.Lpoint_double_shortcut$x: + movdqu 0x00($a_ptr), %xmm0 # copy *(P256_POINT *)$a_ptr.x + mov $a_ptr, $b_ptr # backup copy + movdqu 0x10($a_ptr), %xmm1 + mov 0x20+8*0($a_ptr), $acc4 # load in_y in "5-4-0-1" order + mov 0x20+8*1($a_ptr), $acc5 + mov 0x20+8*2($a_ptr), $acc0 + mov 0x20+8*3($a_ptr), $acc1 + mov .Lpoly+8*1(%rip), $poly1 + mov .Lpoly+8*3(%rip), $poly3 + movdqa %xmm0, $in_x(%rsp) + movdqa %xmm1, $in_x+0x10(%rsp) + lea 0x20($r_ptr), $acc2 + lea 0x40($r_ptr), $acc3 + movq $r_ptr, %xmm0 + movq $acc2, %xmm1 + movq $acc3, %xmm2 + + lea $S(%rsp), $r_ptr + call __ecp_nistz256_mul_by_2$x # p256_mul_by_2(S, in_y); + + mov 0x40+8*0($a_ptr), $src0 + mov 0x40+8*1($a_ptr), $acc6 + mov 0x40+8*2($a_ptr), $acc7 + mov 0x40+8*3($a_ptr), $acc0 + lea 0x40-$bias($a_ptr), $a_ptr + lea $Zsqr(%rsp), $r_ptr + call __ecp_nistz256_sqr_mont$x # p256_sqr_mont(Zsqr, in_z); + + `&load_for_sqr("$S(%rsp)", "$src0")` + lea $S(%rsp), $r_ptr + call __ecp_nistz256_sqr_mont$x # p256_sqr_mont(S, S); + + mov 0x20($b_ptr), $src0 # $b_ptr is still valid + mov 0x40+8*0($b_ptr), $acc1 + mov 0x40+8*1($b_ptr), $acc2 + mov 0x40+8*2($b_ptr), $acc3 + mov 0x40+8*3($b_ptr), $acc4 + lea 0x40-$bias($b_ptr), $a_ptr + lea 0x20($b_ptr), $b_ptr + movq %xmm2, $r_ptr + call __ecp_nistz256_mul_mont$x # p256_mul_mont(res_z, in_z, in_y); + call __ecp_nistz256_mul_by_2$x # p256_mul_by_2(res_z, res_z); + + mov $in_x+8*0(%rsp), $acc4 # "5-4-0-1" order + mov $in_x+8*1(%rsp), $acc5 + lea $Zsqr(%rsp), $b_ptr + mov $in_x+8*2(%rsp), $acc0 + mov $in_x+8*3(%rsp), $acc1 + lea $M(%rsp), $r_ptr + call __ecp_nistz256_add_to$x # p256_add(M, in_x, Zsqr); + + mov $in_x+8*0(%rsp), $acc4 # "5-4-0-1" order + mov $in_x+8*1(%rsp), $acc5 + lea $Zsqr(%rsp), $b_ptr + mov $in_x+8*2(%rsp), $acc0 + mov $in_x+8*3(%rsp), $acc1 + lea $Zsqr(%rsp), $r_ptr + call __ecp_nistz256_sub_from$x # p256_sub(Zsqr, in_x, Zsqr); + + `&load_for_sqr("$S(%rsp)", "$src0")` + movq %xmm1, $r_ptr + call __ecp_nistz256_sqr_mont$x # p256_sqr_mont(res_y, S); +___ +{ +######## ecp_nistz256_div_by_2(res_y, res_y); ########################## +# operate in 4-5-6-7 "name space" that matches squaring output +# +my ($poly1,$poly3)=($a_ptr,$t1); +my ($a0,$a1,$a2,$a3,$t3,$t4,$t1)=($acc4,$acc5,$acc6,$acc7,$acc0,$acc1,$acc2); + +$code.=<<___; + xor $t4, $t4 + mov $a0, $t0 + add \$-1, $a0 + mov $a1, $t1 + adc $poly1, $a1 + mov $a2, $t2 + adc \$0, $a2 + mov $a3, $t3 + adc $poly3, $a3 + adc \$0, $t4 + xor $a_ptr, $a_ptr # borrow $a_ptr + test \$1, $t0 + + cmovz $t0, $a0 + cmovz $t1, $a1 + cmovz $t2, $a2 + cmovz $t3, $a3 + cmovz $a_ptr, $t4 + + mov $a1, $t0 # a0:a3>>1 + shr \$1, $a0 + shl \$63, $t0 + mov $a2, $t1 + shr \$1, $a1 + or $t0, $a0 + shl \$63, $t1 + mov $a3, $t2 + shr \$1, $a2 + or $t1, $a1 + shl \$63, $t2 + mov $a0, 8*0($r_ptr) + shr \$1, $a3 + mov $a1, 8*1($r_ptr) + shl \$63, $t4 + or $t2, $a2 + or $t4, $a3 + mov $a2, 8*2($r_ptr) + mov $a3, 8*3($r_ptr) +___ +} +$code.=<<___; + `&load_for_mul("$M(%rsp)", "$Zsqr(%rsp)", "$src0")` + lea $M(%rsp), $r_ptr + call __ecp_nistz256_mul_mont$x # p256_mul_mont(M, M, Zsqr); + + lea $tmp0(%rsp), $r_ptr + call __ecp_nistz256_mul_by_2$x + + lea $M(%rsp), $b_ptr + lea $M(%rsp), $r_ptr + call __ecp_nistz256_add_to$x # p256_mul_by_3(M, M); + + `&load_for_mul("$S(%rsp)", "$in_x(%rsp)", "$src0")` + lea $S(%rsp), $r_ptr + call __ecp_nistz256_mul_mont$x # p256_mul_mont(S, S, in_x); + + lea $tmp0(%rsp), $r_ptr + call __ecp_nistz256_mul_by_2$x # p256_mul_by_2(tmp0, S); + + `&load_for_sqr("$M(%rsp)", "$src0")` + movq %xmm0, $r_ptr + call __ecp_nistz256_sqr_mont$x # p256_sqr_mont(res_x, M); + + lea $tmp0(%rsp), $b_ptr + mov $acc6, $acc0 # harmonize sqr output and sub input + mov $acc7, $acc1 + mov $a_ptr, $poly1 + mov $t1, $poly3 + call __ecp_nistz256_sub_from$x # p256_sub(res_x, res_x, tmp0); + + mov $S+8*0(%rsp), $t0 + mov $S+8*1(%rsp), $t1 + mov $S+8*2(%rsp), $t2 + mov $S+8*3(%rsp), $acc2 # "4-5-0-1" order + lea $S(%rsp), $r_ptr + call __ecp_nistz256_sub$x # p256_sub(S, S, res_x); + + mov $M(%rsp), $src0 + lea $M(%rsp), $b_ptr + mov $acc4, $acc6 # harmonize sub output and mul input + xor %ecx, %ecx + mov $acc4, $S+8*0(%rsp) # have to save:-( + mov $acc5, $acc2 + mov $acc5, $S+8*1(%rsp) + cmovz $acc0, $acc3 + mov $acc0, $S+8*2(%rsp) + lea $S-$bias(%rsp), $a_ptr + cmovz $acc1, $acc4 + mov $acc1, $S+8*3(%rsp) + mov $acc6, $acc1 + lea $S(%rsp), $r_ptr + call __ecp_nistz256_mul_mont$x # p256_mul_mont(S, S, M); + + movq %xmm1, $b_ptr + movq %xmm1, $r_ptr + call __ecp_nistz256_sub_from$x # p256_sub(res_y, S, res_y); + + add \$32*5+8, %rsp + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbx + pop %rbp + ret +.size ecp_nistz256_point_double$sfx,.-ecp_nistz256_point_double$sfx +___ +} +&gen_double("q"); + +sub gen_add () { + my $x = shift; + my ($src0,$sfx,$bias); + my ($H,$Hsqr,$R,$Rsqr,$Hcub, + $U1,$U2,$S1,$S2, + $res_x,$res_y,$res_z, + $in1_x,$in1_y,$in1_z, + $in2_x,$in2_y,$in2_z)=map(32*$_,(0..17)); + my ($Z1sqr, $Z2sqr) = ($Hsqr, $Rsqr); + + if ($x ne "x") { + $src0 = "%rax"; + $sfx = ""; + $bias = 0; + +$code.=<<___; +.globl ecp_nistz256_point_add +.type ecp_nistz256_point_add,\@function,3 +.align 32 +ecp_nistz256_point_add: +___ +$code.=<<___ if ($addx); + mov \$0x80100, %ecx + and OPENSSL_ia32cap_P+8(%rip), %ecx + cmp \$0x80100, %ecx + je .Lpoint_addx +___ + } else { + $src0 = "%rdx"; + $sfx = "x"; + $bias = 128; + +$code.=<<___; +.type ecp_nistz256_point_addx,\@function,3 +.align 32 +ecp_nistz256_point_addx: +.Lpoint_addx: +___ + } +$code.=<<___; + push %rbp + push %rbx + push %r12 + push %r13 + push %r14 + push %r15 + sub \$32*18+8, %rsp + + movdqu 0x00($a_ptr), %xmm0 # copy *(P256_POINT *)$a_ptr + movdqu 0x10($a_ptr), %xmm1 + movdqu 0x20($a_ptr), %xmm2 + movdqu 0x30($a_ptr), %xmm3 + movdqu 0x40($a_ptr), %xmm4 + movdqu 0x50($a_ptr), %xmm5 + mov $a_ptr, $b_ptr # reassign + mov $b_org, $a_ptr # reassign + movdqa %xmm0, $in1_x(%rsp) + movdqa %xmm1, $in1_x+0x10(%rsp) + por %xmm0, %xmm1 + movdqa %xmm2, $in1_y(%rsp) + movdqa %xmm3, $in1_y+0x10(%rsp) + por %xmm2, %xmm3 + movdqa %xmm4, $in1_z(%rsp) + movdqa %xmm5, $in1_z+0x10(%rsp) + por %xmm1, %xmm3 + + movdqu 0x00($a_ptr), %xmm0 # copy *(P256_POINT *)$b_ptr + pshufd \$0xb1, %xmm3, %xmm5 + movdqu 0x10($a_ptr), %xmm1 + movdqu 0x20($a_ptr), %xmm2 + por %xmm3, %xmm5 + movdqu 0x30($a_ptr), %xmm3 + mov 0x40+8*0($a_ptr), $src0 # load original in2_z + mov 0x40+8*1($a_ptr), $acc6 + mov 0x40+8*2($a_ptr), $acc7 + mov 0x40+8*3($a_ptr), $acc0 + movdqa %xmm0, $in2_x(%rsp) + pshufd \$0x1e, %xmm5, %xmm4 + movdqa %xmm1, $in2_x+0x10(%rsp) + por %xmm0, %xmm1 + movq $r_ptr, %xmm0 # save $r_ptr + movdqa %xmm2, $in2_y(%rsp) + movdqa %xmm3, $in2_y+0x10(%rsp) + por %xmm2, %xmm3 + por %xmm4, %xmm5 + pxor %xmm4, %xmm4 + por %xmm1, %xmm3 + + lea 0x40-$bias($a_ptr), $a_ptr # $a_ptr is still valid + mov $src0, $in2_z+8*0(%rsp) # make in2_z copy + mov $acc6, $in2_z+8*1(%rsp) + mov $acc7, $in2_z+8*2(%rsp) + mov $acc0, $in2_z+8*3(%rsp) + lea $Z2sqr(%rsp), $r_ptr # Z2^2 + call __ecp_nistz256_sqr_mont$x # p256_sqr_mont(Z2sqr, in2_z); + + pcmpeqd %xmm4, %xmm5 + pshufd \$0xb1, %xmm3, %xmm4 + por %xmm3, %xmm4 + pshufd \$0, %xmm5, %xmm5 # in1infty + pshufd \$0x1e, %xmm4, %xmm3 + por %xmm3, %xmm4 + pxor %xmm3, %xmm3 + pcmpeqd %xmm3, %xmm4 + pshufd \$0, %xmm4, %xmm4 # in2infty + mov 0x40+8*0($b_ptr), $src0 # load original in1_z + mov 0x40+8*1($b_ptr), $acc6 + mov 0x40+8*2($b_ptr), $acc7 + mov 0x40+8*3($b_ptr), $acc0 + movq $b_ptr, %xmm1 + + lea 0x40-$bias($b_ptr), $a_ptr + lea $Z1sqr(%rsp), $r_ptr # Z1^2 + call __ecp_nistz256_sqr_mont$x # p256_sqr_mont(Z1sqr, in1_z); + + `&load_for_mul("$Z2sqr(%rsp)", "$in2_z(%rsp)", "$src0")` + lea $S1(%rsp), $r_ptr # S1 = Z2^3 + call __ecp_nistz256_mul_mont$x # p256_mul_mont(S1, Z2sqr, in2_z); + + `&load_for_mul("$Z1sqr(%rsp)", "$in1_z(%rsp)", "$src0")` + lea $S2(%rsp), $r_ptr # S2 = Z1^3 + call __ecp_nistz256_mul_mont$x # p256_mul_mont(S2, Z1sqr, in1_z); + + `&load_for_mul("$S1(%rsp)", "$in1_y(%rsp)", "$src0")` + lea $S1(%rsp), $r_ptr # S1 = Y1*Z2^3 + call __ecp_nistz256_mul_mont$x # p256_mul_mont(S1, S1, in1_y); + + `&load_for_mul("$S2(%rsp)", "$in2_y(%rsp)", "$src0")` + lea $S2(%rsp), $r_ptr # S2 = Y2*Z1^3 + call __ecp_nistz256_mul_mont$x # p256_mul_mont(S2, S2, in2_y); + + lea $S1(%rsp), $b_ptr + lea $R(%rsp), $r_ptr # R = S2 - S1 + call __ecp_nistz256_sub_from$x # p256_sub(R, S2, S1); + + or $acc5, $acc4 # see if result is zero + movdqa %xmm4, %xmm2 + or $acc0, $acc4 + or $acc1, $acc4 + por %xmm5, %xmm2 # in1infty || in2infty + movq $acc4, %xmm3 + + `&load_for_mul("$Z2sqr(%rsp)", "$in1_x(%rsp)", "$src0")` + lea $U1(%rsp), $r_ptr # U1 = X1*Z2^2 + call __ecp_nistz256_mul_mont$x # p256_mul_mont(U1, in1_x, Z2sqr); + + `&load_for_mul("$Z1sqr(%rsp)", "$in2_x(%rsp)", "$src0")` + lea $U2(%rsp), $r_ptr # U2 = X2*Z1^2 + call __ecp_nistz256_mul_mont$x # p256_mul_mont(U2, in2_x, Z1sqr); + + lea $U1(%rsp), $b_ptr + lea $H(%rsp), $r_ptr # H = U2 - U1 + call __ecp_nistz256_sub_from$x # p256_sub(H, U2, U1); + + or $acc5, $acc4 # see if result is zero + or $acc0, $acc4 + or $acc1, $acc4 + + .byte 0x3e # predict taken + jnz .Ladd_proceed$x # is_equal(U1,U2)? + movq %xmm2, $acc0 + movq %xmm3, $acc1 + test $acc0, $acc0 + jnz .Ladd_proceed$x # (in1infty || in2infty)? + test $acc1, $acc1 + jz .Ladd_double$x # is_equal(S1,S2)? + + movq %xmm0, $r_ptr # restore $r_ptr + pxor %xmm0, %xmm0 + movdqu %xmm0, 0x00($r_ptr) + movdqu %xmm0, 0x10($r_ptr) + movdqu %xmm0, 0x20($r_ptr) + movdqu %xmm0, 0x30($r_ptr) + movdqu %xmm0, 0x40($r_ptr) + movdqu %xmm0, 0x50($r_ptr) + jmp .Ladd_done$x + +.align 32 +.Ladd_double$x: + movq %xmm1, $a_ptr # restore $a_ptr + movq %xmm0, $r_ptr # restore $r_ptr + add \$`32*(18-5)`, %rsp # difference in frame sizes + jmp .Lpoint_double_shortcut$x + +.align 32 +.Ladd_proceed$x: + `&load_for_sqr("$R(%rsp)", "$src0")` + lea $Rsqr(%rsp), $r_ptr # R^2 + call __ecp_nistz256_sqr_mont$x # p256_sqr_mont(Rsqr, R); + + `&load_for_mul("$H(%rsp)", "$in1_z(%rsp)", "$src0")` + lea $res_z(%rsp), $r_ptr # Z3 = H*Z1*Z2 + call __ecp_nistz256_mul_mont$x # p256_mul_mont(res_z, H, in1_z); + + `&load_for_sqr("$H(%rsp)", "$src0")` + lea $Hsqr(%rsp), $r_ptr # H^2 + call __ecp_nistz256_sqr_mont$x # p256_sqr_mont(Hsqr, H); + + `&load_for_mul("$res_z(%rsp)", "$in2_z(%rsp)", "$src0")` + lea $res_z(%rsp), $r_ptr # Z3 = H*Z1*Z2 + call __ecp_nistz256_mul_mont$x # p256_mul_mont(res_z, res_z, in2_z); + + `&load_for_mul("$Hsqr(%rsp)", "$H(%rsp)", "$src0")` + lea $Hcub(%rsp), $r_ptr # H^3 + call __ecp_nistz256_mul_mont$x # p256_mul_mont(Hcub, Hsqr, H); + + `&load_for_mul("$Hsqr(%rsp)", "$U1(%rsp)", "$src0")` + lea $U2(%rsp), $r_ptr # U1*H^2 + call __ecp_nistz256_mul_mont$x # p256_mul_mont(U2, U1, Hsqr); +___ +{ +####################################################################### +# operate in 4-5-0-1 "name space" that matches multiplication output +# +my ($acc0,$acc1,$acc2,$acc3,$t3,$t4)=($acc4,$acc5,$acc0,$acc1,$acc2,$acc3); +my ($poly1, $poly3)=($acc6,$acc7); + +$code.=<<___; + #lea $U2(%rsp), $a_ptr + #lea $Hsqr(%rsp), $r_ptr # 2*U1*H^2 + #call __ecp_nistz256_mul_by_2 # ecp_nistz256_mul_by_2(Hsqr, U2); + + add $acc0, $acc0 # a0:a3+a0:a3 + lea $Rsqr(%rsp), $a_ptr + adc $acc1, $acc1 + mov $acc0, $t0 + adc $acc2, $acc2 + adc $acc3, $acc3 + mov $acc1, $t1 + sbb $t4, $t4 + + sub \$-1, $acc0 + mov $acc2, $t2 + sbb $poly1, $acc1 + sbb \$0, $acc2 + mov $acc3, $t3 + sbb $poly3, $acc3 + test $t4, $t4 + + cmovz $t0, $acc0 + mov 8*0($a_ptr), $t0 + cmovz $t1, $acc1 + mov 8*1($a_ptr), $t1 + cmovz $t2, $acc2 + mov 8*2($a_ptr), $t2 + cmovz $t3, $acc3 + mov 8*3($a_ptr), $t3 + + call __ecp_nistz256_sub$x # p256_sub(res_x, Rsqr, Hsqr); + + lea $Hcub(%rsp), $b_ptr + lea $res_x(%rsp), $r_ptr + call __ecp_nistz256_sub_from$x # p256_sub(res_x, res_x, Hcub); + + mov $U2+8*0(%rsp), $t0 + mov $U2+8*1(%rsp), $t1 + mov $U2+8*2(%rsp), $t2 + mov $U2+8*3(%rsp), $t3 + lea $res_y(%rsp), $r_ptr + + call __ecp_nistz256_sub$x # p256_sub(res_y, U2, res_x); + + mov $acc0, 8*0($r_ptr) # save the result, as + mov $acc1, 8*1($r_ptr) # __ecp_nistz256_sub doesn't + mov $acc2, 8*2($r_ptr) + mov $acc3, 8*3($r_ptr) +___ +} +$code.=<<___; + `&load_for_mul("$S1(%rsp)", "$Hcub(%rsp)", "$src0")` + lea $S2(%rsp), $r_ptr + call __ecp_nistz256_mul_mont$x # p256_mul_mont(S2, S1, Hcub); + + `&load_for_mul("$R(%rsp)", "$res_y(%rsp)", "$src0")` + lea $res_y(%rsp), $r_ptr + call __ecp_nistz256_mul_mont$x # p256_mul_mont(res_y, R, res_y); + + lea $S2(%rsp), $b_ptr + lea $res_y(%rsp), $r_ptr + call __ecp_nistz256_sub_from$x # p256_sub(res_y, res_y, S2); + + movq %xmm0, $r_ptr # restore $r_ptr + + movdqa %xmm5, %xmm0 # copy_conditional(res_z, in2_z, in1infty); + movdqa %xmm5, %xmm1 + pandn $res_z(%rsp), %xmm0 + movdqa %xmm5, %xmm2 + pandn $res_z+0x10(%rsp), %xmm1 + movdqa %xmm5, %xmm3 + pand $in2_z(%rsp), %xmm2 + pand $in2_z+0x10(%rsp), %xmm3 + por %xmm0, %xmm2 + por %xmm1, %xmm3 + + movdqa %xmm4, %xmm0 # copy_conditional(res_z, in1_z, in2infty); + movdqa %xmm4, %xmm1 + pandn %xmm2, %xmm0 + movdqa %xmm4, %xmm2 + pandn %xmm3, %xmm1 + movdqa %xmm4, %xmm3 + pand $in1_z(%rsp), %xmm2 + pand $in1_z+0x10(%rsp), %xmm3 + por %xmm0, %xmm2 + por %xmm1, %xmm3 + movdqu %xmm2, 0x40($r_ptr) + movdqu %xmm3, 0x50($r_ptr) + + movdqa %xmm5, %xmm0 # copy_conditional(res_x, in2_x, in1infty); + movdqa %xmm5, %xmm1 + pandn $res_x(%rsp), %xmm0 + movdqa %xmm5, %xmm2 + pandn $res_x+0x10(%rsp), %xmm1 + movdqa %xmm5, %xmm3 + pand $in2_x(%rsp), %xmm2 + pand $in2_x+0x10(%rsp), %xmm3 + por %xmm0, %xmm2 + por %xmm1, %xmm3 + + movdqa %xmm4, %xmm0 # copy_conditional(res_x, in1_x, in2infty); + movdqa %xmm4, %xmm1 + pandn %xmm2, %xmm0 + movdqa %xmm4, %xmm2 + pandn %xmm3, %xmm1 + movdqa %xmm4, %xmm3 + pand $in1_x(%rsp), %xmm2 + pand $in1_x+0x10(%rsp), %xmm3 + por %xmm0, %xmm2 + por %xmm1, %xmm3 + movdqu %xmm2, 0x00($r_ptr) + movdqu %xmm3, 0x10($r_ptr) + + movdqa %xmm5, %xmm0 # copy_conditional(res_y, in2_y, in1infty); + movdqa %xmm5, %xmm1 + pandn $res_y(%rsp), %xmm0 + movdqa %xmm5, %xmm2 + pandn $res_y+0x10(%rsp), %xmm1 + movdqa %xmm5, %xmm3 + pand $in2_y(%rsp), %xmm2 + pand $in2_y+0x10(%rsp), %xmm3 + por %xmm0, %xmm2 + por %xmm1, %xmm3 + + movdqa %xmm4, %xmm0 # copy_conditional(res_y, in1_y, in2infty); + movdqa %xmm4, %xmm1 + pandn %xmm2, %xmm0 + movdqa %xmm4, %xmm2 + pandn %xmm3, %xmm1 + movdqa %xmm4, %xmm3 + pand $in1_y(%rsp), %xmm2 + pand $in1_y+0x10(%rsp), %xmm3 + por %xmm0, %xmm2 + por %xmm1, %xmm3 + movdqu %xmm2, 0x20($r_ptr) + movdqu %xmm3, 0x30($r_ptr) + +.Ladd_done$x: + add \$32*18+8, %rsp + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbx + pop %rbp + ret +.size ecp_nistz256_point_add$sfx,.-ecp_nistz256_point_add$sfx +___ +} +&gen_add("q"); + +sub gen_add_affine () { + my $x = shift; + my ($src0,$sfx,$bias); + my ($U2,$S2,$H,$R,$Hsqr,$Hcub,$Rsqr, + $res_x,$res_y,$res_z, + $in1_x,$in1_y,$in1_z, + $in2_x,$in2_y)=map(32*$_,(0..14)); + my $Z1sqr = $S2; + + if ($x ne "x") { + $src0 = "%rax"; + $sfx = ""; + $bias = 0; + +$code.=<<___; +.globl ecp_nistz256_point_add_affine +.type ecp_nistz256_point_add_affine,\@function,3 +.align 32 +ecp_nistz256_point_add_affine: +___ +$code.=<<___ if ($addx); + mov \$0x80100, %ecx + and OPENSSL_ia32cap_P+8(%rip), %ecx + cmp \$0x80100, %ecx + je .Lpoint_add_affinex +___ + } else { + $src0 = "%rdx"; + $sfx = "x"; + $bias = 128; + +$code.=<<___; +.type ecp_nistz256_point_add_affinex,\@function,3 +.align 32 +ecp_nistz256_point_add_affinex: +.Lpoint_add_affinex: +___ + } +$code.=<<___; + push %rbp + push %rbx + push %r12 + push %r13 + push %r14 + push %r15 + sub \$32*15+8, %rsp + + movdqu 0x00($a_ptr), %xmm0 # copy *(P256_POINT *)$a_ptr + mov $b_org, $b_ptr # reassign + movdqu 0x10($a_ptr), %xmm1 + movdqu 0x20($a_ptr), %xmm2 + movdqu 0x30($a_ptr), %xmm3 + movdqu 0x40($a_ptr), %xmm4 + movdqu 0x50($a_ptr), %xmm5 + mov 0x40+8*0($a_ptr), $src0 # load original in1_z + mov 0x40+8*1($a_ptr), $acc6 + mov 0x40+8*2($a_ptr), $acc7 + mov 0x40+8*3($a_ptr), $acc0 + movdqa %xmm0, $in1_x(%rsp) + movdqa %xmm1, $in1_x+0x10(%rsp) + por %xmm0, %xmm1 + movdqa %xmm2, $in1_y(%rsp) + movdqa %xmm3, $in1_y+0x10(%rsp) + por %xmm2, %xmm3 + movdqa %xmm4, $in1_z(%rsp) + movdqa %xmm5, $in1_z+0x10(%rsp) + por %xmm1, %xmm3 + + movdqu 0x00($b_ptr), %xmm0 # copy *(P256_POINT_AFFINE *)$b_ptr + pshufd \$0xb1, %xmm3, %xmm5 + movdqu 0x10($b_ptr), %xmm1 + movdqu 0x20($b_ptr), %xmm2 + por %xmm3, %xmm5 + movdqu 0x30($b_ptr), %xmm3 + movdqa %xmm0, $in2_x(%rsp) + pshufd \$0x1e, %xmm5, %xmm4 + movdqa %xmm1, $in2_x+0x10(%rsp) + por %xmm0, %xmm1 + movq $r_ptr, %xmm0 # save $r_ptr + movdqa %xmm2, $in2_y(%rsp) + movdqa %xmm3, $in2_y+0x10(%rsp) + por %xmm2, %xmm3 + por %xmm4, %xmm5 + pxor %xmm4, %xmm4 + por %xmm1, %xmm3 + + lea 0x40-$bias($a_ptr), $a_ptr # $a_ptr is still valid + lea $Z1sqr(%rsp), $r_ptr # Z1^2 + call __ecp_nistz256_sqr_mont$x # p256_sqr_mont(Z1sqr, in1_z); + + pcmpeqd %xmm4, %xmm5 + pshufd \$0xb1, %xmm3, %xmm4 + mov 0x00($b_ptr), $src0 # $b_ptr is still valid + #lea 0x00($b_ptr), $b_ptr + mov $acc4, $acc1 # harmonize sqr output and mul input + por %xmm3, %xmm4 + pshufd \$0, %xmm5, %xmm5 # in1infty + pshufd \$0x1e, %xmm4, %xmm3 + mov $acc5, $acc2 + por %xmm3, %xmm4 + pxor %xmm3, %xmm3 + mov $acc6, $acc3 + pcmpeqd %xmm3, %xmm4 + pshufd \$0, %xmm4, %xmm4 # in2infty + + lea $Z1sqr-$bias(%rsp), $a_ptr + mov $acc7, $acc4 + lea $U2(%rsp), $r_ptr # U2 = X2*Z1^2 + call __ecp_nistz256_mul_mont$x # p256_mul_mont(U2, Z1sqr, in2_x); + + lea $in1_x(%rsp), $b_ptr + lea $H(%rsp), $r_ptr # H = U2 - U1 + call __ecp_nistz256_sub_from$x # p256_sub(H, U2, in1_x); + + `&load_for_mul("$Z1sqr(%rsp)", "$in1_z(%rsp)", "$src0")` + lea $S2(%rsp), $r_ptr # S2 = Z1^3 + call __ecp_nistz256_mul_mont$x # p256_mul_mont(S2, Z1sqr, in1_z); + + `&load_for_mul("$H(%rsp)", "$in1_z(%rsp)", "$src0")` + lea $res_z(%rsp), $r_ptr # Z3 = H*Z1*Z2 + call __ecp_nistz256_mul_mont$x # p256_mul_mont(res_z, H, in1_z); + + `&load_for_mul("$S2(%rsp)", "$in2_y(%rsp)", "$src0")` + lea $S2(%rsp), $r_ptr # S2 = Y2*Z1^3 + call __ecp_nistz256_mul_mont$x # p256_mul_mont(S2, S2, in2_y); + + lea $in1_y(%rsp), $b_ptr + lea $R(%rsp), $r_ptr # R = S2 - S1 + call __ecp_nistz256_sub_from$x # p256_sub(R, S2, in1_y); + + `&load_for_sqr("$H(%rsp)", "$src0")` + lea $Hsqr(%rsp), $r_ptr # H^2 + call __ecp_nistz256_sqr_mont$x # p256_sqr_mont(Hsqr, H); + + `&load_for_sqr("$R(%rsp)", "$src0")` + lea $Rsqr(%rsp), $r_ptr # R^2 + call __ecp_nistz256_sqr_mont$x # p256_sqr_mont(Rsqr, R); + + `&load_for_mul("$H(%rsp)", "$Hsqr(%rsp)", "$src0")` + lea $Hcub(%rsp), $r_ptr # H^3 + call __ecp_nistz256_mul_mont$x # p256_mul_mont(Hcub, Hsqr, H); + + `&load_for_mul("$Hsqr(%rsp)", "$in1_x(%rsp)", "$src0")` + lea $U2(%rsp), $r_ptr # U1*H^2 + call __ecp_nistz256_mul_mont$x # p256_mul_mont(U2, in1_x, Hsqr); +___ +{ +####################################################################### +# operate in 4-5-0-1 "name space" that matches multiplication output +# +my ($acc0,$acc1,$acc2,$acc3,$t3,$t4)=($acc4,$acc5,$acc0,$acc1,$acc2,$acc3); +my ($poly1, $poly3)=($acc6,$acc7); + +$code.=<<___; + #lea $U2(%rsp), $a_ptr + #lea $Hsqr(%rsp), $r_ptr # 2*U1*H^2 + #call __ecp_nistz256_mul_by_2 # ecp_nistz256_mul_by_2(Hsqr, U2); + + add $acc0, $acc0 # a0:a3+a0:a3 + lea $Rsqr(%rsp), $a_ptr + adc $acc1, $acc1 + mov $acc0, $t0 + adc $acc2, $acc2 + adc $acc3, $acc3 + mov $acc1, $t1 + sbb $t4, $t4 + + sub \$-1, $acc0 + mov $acc2, $t2 + sbb $poly1, $acc1 + sbb \$0, $acc2 + mov $acc3, $t3 + sbb $poly3, $acc3 + test $t4, $t4 + + cmovz $t0, $acc0 + mov 8*0($a_ptr), $t0 + cmovz $t1, $acc1 + mov 8*1($a_ptr), $t1 + cmovz $t2, $acc2 + mov 8*2($a_ptr), $t2 + cmovz $t3, $acc3 + mov 8*3($a_ptr), $t3 + + call __ecp_nistz256_sub$x # p256_sub(res_x, Rsqr, Hsqr); + + lea $Hcub(%rsp), $b_ptr + lea $res_x(%rsp), $r_ptr + call __ecp_nistz256_sub_from$x # p256_sub(res_x, res_x, Hcub); + + mov $U2+8*0(%rsp), $t0 + mov $U2+8*1(%rsp), $t1 + mov $U2+8*2(%rsp), $t2 + mov $U2+8*3(%rsp), $t3 + lea $H(%rsp), $r_ptr + + call __ecp_nistz256_sub$x # p256_sub(H, U2, res_x); + + mov $acc0, 8*0($r_ptr) # save the result, as + mov $acc1, 8*1($r_ptr) # __ecp_nistz256_sub doesn't + mov $acc2, 8*2($r_ptr) + mov $acc3, 8*3($r_ptr) +___ +} +$code.=<<___; + `&load_for_mul("$Hcub(%rsp)", "$in1_y(%rsp)", "$src0")` + lea $S2(%rsp), $r_ptr + call __ecp_nistz256_mul_mont$x # p256_mul_mont(S2, Hcub, in1_y); + + `&load_for_mul("$H(%rsp)", "$R(%rsp)", "$src0")` + lea $H(%rsp), $r_ptr + call __ecp_nistz256_mul_mont$x # p256_mul_mont(H, H, R); + + lea $S2(%rsp), $b_ptr + lea $res_y(%rsp), $r_ptr + call __ecp_nistz256_sub_from$x # p256_sub(res_y, H, S2); + + movq %xmm0, $r_ptr # restore $r_ptr + + movdqa %xmm5, %xmm0 # copy_conditional(res_z, ONE, in1infty); + movdqa %xmm5, %xmm1 + pandn $res_z(%rsp), %xmm0 + movdqa %xmm5, %xmm2 + pandn $res_z+0x10(%rsp), %xmm1 + movdqa %xmm5, %xmm3 + pand .LONE_mont(%rip), %xmm2 + pand .LONE_mont+0x10(%rip), %xmm3 + por %xmm0, %xmm2 + por %xmm1, %xmm3 + + movdqa %xmm4, %xmm0 # copy_conditional(res_z, in1_z, in2infty); + movdqa %xmm4, %xmm1 + pandn %xmm2, %xmm0 + movdqa %xmm4, %xmm2 + pandn %xmm3, %xmm1 + movdqa %xmm4, %xmm3 + pand $in1_z(%rsp), %xmm2 + pand $in1_z+0x10(%rsp), %xmm3 + por %xmm0, %xmm2 + por %xmm1, %xmm3 + movdqu %xmm2, 0x40($r_ptr) + movdqu %xmm3, 0x50($r_ptr) + + movdqa %xmm5, %xmm0 # copy_conditional(res_x, in2_x, in1infty); + movdqa %xmm5, %xmm1 + pandn $res_x(%rsp), %xmm0 + movdqa %xmm5, %xmm2 + pandn $res_x+0x10(%rsp), %xmm1 + movdqa %xmm5, %xmm3 + pand $in2_x(%rsp), %xmm2 + pand $in2_x+0x10(%rsp), %xmm3 + por %xmm0, %xmm2 + por %xmm1, %xmm3 + + movdqa %xmm4, %xmm0 # copy_conditional(res_x, in1_x, in2infty); + movdqa %xmm4, %xmm1 + pandn %xmm2, %xmm0 + movdqa %xmm4, %xmm2 + pandn %xmm3, %xmm1 + movdqa %xmm4, %xmm3 + pand $in1_x(%rsp), %xmm2 + pand $in1_x+0x10(%rsp), %xmm3 + por %xmm0, %xmm2 + por %xmm1, %xmm3 + movdqu %xmm2, 0x00($r_ptr) + movdqu %xmm3, 0x10($r_ptr) + + movdqa %xmm5, %xmm0 # copy_conditional(res_y, in2_y, in1infty); + movdqa %xmm5, %xmm1 + pandn $res_y(%rsp), %xmm0 + movdqa %xmm5, %xmm2 + pandn $res_y+0x10(%rsp), %xmm1 + movdqa %xmm5, %xmm3 + pand $in2_y(%rsp), %xmm2 + pand $in2_y+0x10(%rsp), %xmm3 + por %xmm0, %xmm2 + por %xmm1, %xmm3 + + movdqa %xmm4, %xmm0 # copy_conditional(res_y, in1_y, in2infty); + movdqa %xmm4, %xmm1 + pandn %xmm2, %xmm0 + movdqa %xmm4, %xmm2 + pandn %xmm3, %xmm1 + movdqa %xmm4, %xmm3 + pand $in1_y(%rsp), %xmm2 + pand $in1_y+0x10(%rsp), %xmm3 + por %xmm0, %xmm2 + por %xmm1, %xmm3 + movdqu %xmm2, 0x20($r_ptr) + movdqu %xmm3, 0x30($r_ptr) + + add \$32*15+8, %rsp + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbx + pop %rbp + ret +.size ecp_nistz256_point_add_affine$sfx,.-ecp_nistz256_point_add_affine$sfx +___ +} +&gen_add_affine("q"); + +######################################################################## +# AD*X magic +# +if ($addx) { { +######################################################################## +# operate in 4-5-0-1 "name space" that matches multiplication output +# +my ($a0,$a1,$a2,$a3,$t3,$t4)=($acc4,$acc5,$acc0,$acc1,$acc2,$acc3); + +$code.=<<___; +.type __ecp_nistz256_add_tox,\@abi-omnipotent +.align 32 +__ecp_nistz256_add_tox: + xor $t4, $t4 + adc 8*0($b_ptr), $a0 + adc 8*1($b_ptr), $a1 + mov $a0, $t0 + adc 8*2($b_ptr), $a2 + adc 8*3($b_ptr), $a3 + mov $a1, $t1 + adc \$0, $t4 + + xor $t3, $t3 + sbb \$-1, $a0 + mov $a2, $t2 + sbb $poly1, $a1 + sbb \$0, $a2 + mov $a3, $t3 + sbb $poly3, $a3 + + bt \$0, $t4 + cmovnc $t0, $a0 + cmovnc $t1, $a1 + mov $a0, 8*0($r_ptr) + cmovnc $t2, $a2 + mov $a1, 8*1($r_ptr) + cmovnc $t3, $a3 + mov $a2, 8*2($r_ptr) + mov $a3, 8*3($r_ptr) + + ret +.size __ecp_nistz256_add_tox,.-__ecp_nistz256_add_tox + +.type __ecp_nistz256_sub_fromx,\@abi-omnipotent +.align 32 +__ecp_nistz256_sub_fromx: + xor $t4, $t4 + sbb 8*0($b_ptr), $a0 + sbb 8*1($b_ptr), $a1 + mov $a0, $t0 + sbb 8*2($b_ptr), $a2 + sbb 8*3($b_ptr), $a3 + mov $a1, $t1 + sbb \$0, $t4 + + xor $t3, $t3 + adc \$-1, $a0 + mov $a2, $t2 + adc $poly1, $a1 + adc \$0, $a2 + mov $a3, $t3 + adc $poly3, $a3 + + bt \$0, $t4 + cmovnc $t0, $a0 + cmovnc $t1, $a1 + mov $a0, 8*0($r_ptr) + cmovnc $t2, $a2 + mov $a1, 8*1($r_ptr) + cmovnc $t3, $a3 + mov $a2, 8*2($r_ptr) + mov $a3, 8*3($r_ptr) + + ret +.size __ecp_nistz256_sub_fromx,.-__ecp_nistz256_sub_fromx + +.type __ecp_nistz256_subx,\@abi-omnipotent +.align 32 +__ecp_nistz256_subx: + xor $t4, $t4 + sbb $a0, $t0 + sbb $a1, $t1 + mov $t0, $a0 + sbb $a2, $t2 + sbb $a3, $t3 + mov $t1, $a1 + sbb \$0, $t4 + + xor $a3 ,$a3 + adc \$-1, $t0 + mov $t2, $a2 + adc $poly1, $t1 + adc \$0, $t2 + mov $t3, $a3 + adc $poly3, $t3 + + bt \$0, $t4 + cmovc $t0, $a0 + cmovc $t1, $a1 + cmovc $t2, $a2 + cmovc $t3, $a3 + + ret +.size __ecp_nistz256_subx,.-__ecp_nistz256_subx + +.type __ecp_nistz256_mul_by_2x,\@abi-omnipotent +.align 32 +__ecp_nistz256_mul_by_2x: + xor $t4, $t4 + adc $a0, $a0 # a0:a3+a0:a3 + adc $a1, $a1 + mov $a0, $t0 + adc $a2, $a2 + adc $a3, $a3 + mov $a1, $t1 + adc \$0, $t4 + + xor $t3, $t3 + sbb \$-1, $a0 + mov $a2, $t2 + sbb $poly1, $a1 + sbb \$0, $a2 + mov $a3, $t3 + sbb $poly3, $a3 + + bt \$0, $t4 + cmovnc $t0, $a0 + cmovnc $t1, $a1 + mov $a0, 8*0($r_ptr) + cmovnc $t2, $a2 + mov $a1, 8*1($r_ptr) + cmovnc $t3, $a3 + mov $a2, 8*2($r_ptr) + mov $a3, 8*3($r_ptr) + + ret +.size __ecp_nistz256_mul_by_2x,.-__ecp_nistz256_mul_by_2x +___ + } +&gen_double("x"); +&gen_add("x"); +&gen_add_affine("x"); +} +}}} + +$code =~ s/\`([^\`]*)\`/eval $1/gem; +print $code; +close STDOUT; diff --git a/external/boringssl/crypto/ec/ec.c b/external/boringssl/crypto/ec/ec.c new file mode 100644 index 0000000000..8f3fa6e13a --- /dev/null +++ b/external/boringssl/crypto/ec/ec.c @@ -0,0 +1,935 @@ +/* Originally written by Bodo Moeller for the OpenSSL project. + * ==================================================================== + * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * + * Portions of the attached software ("Contribution") are developed by + * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. + * + * The Contribution is licensed pursuant to the OpenSSL open source + * license provided above. + * + * The elliptic curve binary polynomial software is originally written by + * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems + * Laboratories. */ + +#include + +#include +#include + +#include +#include +#include +#include + +#include "internal.h" +#include "../internal.h" + + +static const struct curve_data P224 = { + "NIST P-224", + 28, + 1, + {/* p */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, + /* a */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFE, + /* b */ + 0xB4, 0x05, 0x0A, 0x85, 0x0C, 0x04, 0xB3, 0xAB, 0xF5, 0x41, 0x32, 0x56, + 0x50, 0x44, 0xB0, 0xB7, 0xD7, 0xBF, 0xD8, 0xBA, 0x27, 0x0B, 0x39, 0x43, + 0x23, 0x55, 0xFF, 0xB4, + /* x */ + 0xB7, 0x0E, 0x0C, 0xBD, 0x6B, 0xB4, 0xBF, 0x7F, 0x32, 0x13, 0x90, 0xB9, + 0x4A, 0x03, 0xC1, 0xD3, 0x56, 0xC2, 0x11, 0x22, 0x34, 0x32, 0x80, 0xD6, + 0x11, 0x5C, 0x1D, 0x21, + /* y */ + 0xbd, 0x37, 0x63, 0x88, 0xb5, 0xf7, 0x23, 0xfb, 0x4c, 0x22, 0xdf, 0xe6, + 0xcd, 0x43, 0x75, 0xa0, 0x5a, 0x07, 0x47, 0x64, 0x44, 0xd5, 0x81, 0x99, + 0x85, 0x00, 0x7e, 0x34, + /* order */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0x16, 0xA2, 0xE0, 0xB8, 0xF0, 0x3E, 0x13, 0xDD, 0x29, 0x45, + 0x5C, 0x5C, 0x2A, 0x3D, + }}; + +static const struct curve_data P256 = { + "NIST P-256", + 32, + 1, + {/* p */ + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /* a */ + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, + /* b */ + 0x5A, 0xC6, 0x35, 0xD8, 0xAA, 0x3A, 0x93, 0xE7, 0xB3, 0xEB, 0xBD, 0x55, + 0x76, 0x98, 0x86, 0xBC, 0x65, 0x1D, 0x06, 0xB0, 0xCC, 0x53, 0xB0, 0xF6, + 0x3B, 0xCE, 0x3C, 0x3E, 0x27, 0xD2, 0x60, 0x4B, + /* x */ + 0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8, 0xBC, 0xE6, 0xE5, + 0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0, + 0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2, 0x96, + /* y */ + 0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 0x4a, + 0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce, + 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5, + /* order */ + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84, + 0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51}}; + +static const struct curve_data P384 = { + "NIST P-384", + 48, + 1, + {/* p */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + /* a */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFC, + /* b */ + 0xB3, 0x31, 0x2F, 0xA7, 0xE2, 0x3E, 0xE7, 0xE4, 0x98, 0x8E, 0x05, 0x6B, + 0xE3, 0xF8, 0x2D, 0x19, 0x18, 0x1D, 0x9C, 0x6E, 0xFE, 0x81, 0x41, 0x12, + 0x03, 0x14, 0x08, 0x8F, 0x50, 0x13, 0x87, 0x5A, 0xC6, 0x56, 0x39, 0x8D, + 0x8A, 0x2E, 0xD1, 0x9D, 0x2A, 0x85, 0xC8, 0xED, 0xD3, 0xEC, 0x2A, 0xEF, + /* x */ + 0xAA, 0x87, 0xCA, 0x22, 0xBE, 0x8B, 0x05, 0x37, 0x8E, 0xB1, 0xC7, 0x1E, + 0xF3, 0x20, 0xAD, 0x74, 0x6E, 0x1D, 0x3B, 0x62, 0x8B, 0xA7, 0x9B, 0x98, + 0x59, 0xF7, 0x41, 0xE0, 0x82, 0x54, 0x2A, 0x38, 0x55, 0x02, 0xF2, 0x5D, + 0xBF, 0x55, 0x29, 0x6C, 0x3A, 0x54, 0x5E, 0x38, 0x72, 0x76, 0x0A, 0xB7, + /* y */ + 0x36, 0x17, 0xde, 0x4a, 0x96, 0x26, 0x2c, 0x6f, 0x5d, 0x9e, 0x98, 0xbf, + 0x92, 0x92, 0xdc, 0x29, 0xf8, 0xf4, 0x1d, 0xbd, 0x28, 0x9a, 0x14, 0x7c, + 0xe9, 0xda, 0x31, 0x13, 0xb5, 0xf0, 0xb8, 0xc0, 0x0a, 0x60, 0xb1, 0xce, + 0x1d, 0x7e, 0x81, 0x9d, 0x7a, 0x43, 0x1d, 0x7c, 0x90, 0xea, 0x0e, 0x5f, + /* order */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xC7, 0x63, 0x4D, 0x81, 0xF4, 0x37, 0x2D, 0xDF, 0x58, 0x1A, 0x0D, 0xB2, + 0x48, 0xB0, 0xA7, 0x7A, 0xEC, 0xEC, 0x19, 0x6A, 0xCC, 0xC5, 0x29, 0x73}}; + +static const struct curve_data P521 = { + "NIST P-521", + 66, + 1, + {/* p */ + 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /* a */ + 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, + /* b */ + 0x00, 0x51, 0x95, 0x3E, 0xB9, 0x61, 0x8E, 0x1C, 0x9A, 0x1F, 0x92, 0x9A, + 0x21, 0xA0, 0xB6, 0x85, 0x40, 0xEE, 0xA2, 0xDA, 0x72, 0x5B, 0x99, 0xB3, + 0x15, 0xF3, 0xB8, 0xB4, 0x89, 0x91, 0x8E, 0xF1, 0x09, 0xE1, 0x56, 0x19, + 0x39, 0x51, 0xEC, 0x7E, 0x93, 0x7B, 0x16, 0x52, 0xC0, 0xBD, 0x3B, 0xB1, + 0xBF, 0x07, 0x35, 0x73, 0xDF, 0x88, 0x3D, 0x2C, 0x34, 0xF1, 0xEF, 0x45, + 0x1F, 0xD4, 0x6B, 0x50, 0x3F, 0x00, + /* x */ + 0x00, 0xC6, 0x85, 0x8E, 0x06, 0xB7, 0x04, 0x04, 0xE9, 0xCD, 0x9E, 0x3E, + 0xCB, 0x66, 0x23, 0x95, 0xB4, 0x42, 0x9C, 0x64, 0x81, 0x39, 0x05, 0x3F, + 0xB5, 0x21, 0xF8, 0x28, 0xAF, 0x60, 0x6B, 0x4D, 0x3D, 0xBA, 0xA1, 0x4B, + 0x5E, 0x77, 0xEF, 0xE7, 0x59, 0x28, 0xFE, 0x1D, 0xC1, 0x27, 0xA2, 0xFF, + 0xA8, 0xDE, 0x33, 0x48, 0xB3, 0xC1, 0x85, 0x6A, 0x42, 0x9B, 0xF9, 0x7E, + 0x7E, 0x31, 0xC2, 0xE5, 0xBD, 0x66, + /* y */ + 0x01, 0x18, 0x39, 0x29, 0x6a, 0x78, 0x9a, 0x3b, 0xc0, 0x04, 0x5c, 0x8a, + 0x5f, 0xb4, 0x2c, 0x7d, 0x1b, 0xd9, 0x98, 0xf5, 0x44, 0x49, 0x57, 0x9b, + 0x44, 0x68, 0x17, 0xaf, 0xbd, 0x17, 0x27, 0x3e, 0x66, 0x2c, 0x97, 0xee, + 0x72, 0x99, 0x5e, 0xf4, 0x26, 0x40, 0xc5, 0x50, 0xb9, 0x01, 0x3f, 0xad, + 0x07, 0x61, 0x35, 0x3c, 0x70, 0x86, 0xa2, 0x72, 0xc2, 0x40, 0x88, 0xbe, + 0x94, 0x76, 0x9f, 0xd1, 0x66, 0x50, + /* order */ + 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0x51, 0x86, + 0x87, 0x83, 0xBF, 0x2F, 0x96, 0x6B, 0x7F, 0xCC, 0x01, 0x48, 0xF7, 0x09, + 0xA5, 0xD0, 0x3B, 0xB5, 0xC9, 0xB8, 0x89, 0x9C, 0x47, 0xAE, 0xBB, 0x6F, + 0xB7, 0x1E, 0x91, 0x38, 0x64, 0x09}}; + +/* MSan appears to have a bug that causes code to be miscompiled in opt mode. + * While that is being looked at, don't run the uint128_t code under MSan. */ +#if defined(OPENSSL_64_BIT) && !defined(OPENSSL_WINDOWS) && \ + !defined(MEMORY_SANITIZER) +#define BORINGSSL_USE_INT128_CODE +#endif + +const struct built_in_curve OPENSSL_built_in_curves[] = { + { + NID_secp521r1, + /* 1.3.132.0.35 */ + {0x2b, 0x81, 0x04, 0x00, 0x23}, 5, + &P521, + NULL, + }, + { + NID_secp384r1, + /* 1.3.132.0.34 */ + {0x2b, 0x81, 0x04, 0x00, 0x22}, 5, + &P384, + NULL, + }, + { + NID_X9_62_prime256v1, + /* 1.2.840.10045.3.1.7 */ + {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07}, 8, + &P256, +#if defined(BORINGSSL_USE_INT128_CODE) +#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && \ + !defined(OPENSSL_SMALL) + EC_GFp_nistz256_method, +#else + EC_GFp_nistp256_method, +#endif +#else + NULL, +#endif + }, + { + NID_secp224r1, + /* 1.3.132.0.33 */ + {0x2b, 0x81, 0x04, 0x00, 0x21}, 5, + &P224, +#if defined(BORINGSSL_USE_INT128_CODE) && !defined(OPENSSL_SMALL) + EC_GFp_nistp224_method, +#else + NULL, +#endif + }, + {NID_undef, {0}, 0, NULL, NULL}, +}; + +/* built_in_curve_scalar_field_monts contains Montgomery contexts for + * performing inversions in the scalar fields of each of the built-in + * curves. It's protected by |built_in_curve_scalar_field_monts_once|. */ +static const BN_MONT_CTX **built_in_curve_scalar_field_monts; + +static CRYPTO_once_t built_in_curve_scalar_field_monts_once; + +static void built_in_curve_scalar_field_monts_init(void) { + unsigned num_built_in_curves; + for (num_built_in_curves = 0;; num_built_in_curves++) { + if (OPENSSL_built_in_curves[num_built_in_curves].nid == NID_undef) { + break; + } + } + + assert(0 < num_built_in_curves); + + built_in_curve_scalar_field_monts = + OPENSSL_malloc(sizeof(BN_MONT_CTX *) * num_built_in_curves); + if (built_in_curve_scalar_field_monts == NULL) { + return; + } + + BIGNUM *order = BN_new(); + BN_CTX *bn_ctx = BN_CTX_new(); + BN_MONT_CTX *mont_ctx = NULL; + + if (bn_ctx == NULL || + order == NULL) { + goto err; + } + + unsigned i; + for (i = 0; i < num_built_in_curves; i++) { + const struct curve_data *curve = OPENSSL_built_in_curves[i].data; + const unsigned param_len = curve->param_len; + const uint8_t *params = curve->data; + + mont_ctx = BN_MONT_CTX_new(); + if (mont_ctx == NULL) { + goto err; + } + + if (!BN_bin2bn(params + 5 * param_len, param_len, order) || + !BN_MONT_CTX_set(mont_ctx, order, bn_ctx)) { + goto err; + } + + built_in_curve_scalar_field_monts[i] = mont_ctx; + mont_ctx = NULL; + } + + goto out; + +err: + BN_MONT_CTX_free(mont_ctx); + OPENSSL_free((BN_MONT_CTX**) built_in_curve_scalar_field_monts); + built_in_curve_scalar_field_monts = NULL; + +out: + BN_free(order); + BN_CTX_free(bn_ctx); +} + +EC_GROUP *ec_group_new(const EC_METHOD *meth) { + EC_GROUP *ret; + + if (meth == NULL) { + OPENSSL_PUT_ERROR(EC, EC_R_SLOT_FULL); + return NULL; + } + + if (meth->group_init == 0) { + OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return NULL; + } + + ret = OPENSSL_malloc(sizeof(EC_GROUP)); + if (ret == NULL) { + OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); + return NULL; + } + memset(ret, 0, sizeof(EC_GROUP)); + + ret->meth = meth; + BN_init(&ret->order); + BN_init(&ret->cofactor); + + if (!meth->group_init(ret)) { + OPENSSL_free(ret); + return NULL; + } + + return ret; +} + +EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a, + const BIGNUM *b, BN_CTX *ctx) { + const EC_METHOD *meth = EC_GFp_mont_method(); + EC_GROUP *ret; + + ret = ec_group_new(meth); + if (ret == NULL) { + return NULL; + } + + if (ret->meth->group_set_curve == 0) { + OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + if (!ret->meth->group_set_curve(ret, p, a, b, ctx)) { + EC_GROUP_free(ret); + return NULL; + } + return ret; +} + +int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, + const BIGNUM *order, const BIGNUM *cofactor) { + if (group->curve_name != NID_undef || group->generator != NULL) { + /* |EC_GROUP_set_generator| may only be used with |EC_GROUP|s returned by + * |EC_GROUP_new_curve_GFp| and may only used once on each group. */ + return 0; + } + + group->generator = EC_POINT_new(group); + return group->generator != NULL && + EC_POINT_copy(group->generator, generator) && + BN_copy(&group->order, order) && + BN_copy(&group->cofactor, cofactor); +} + +EC_GROUP *EC_GROUP_new_arbitrary(const BIGNUM *p, const BIGNUM *a, + const BIGNUM *b, const BIGNUM *gx, + const BIGNUM *gy, const BIGNUM *order, + const BIGNUM *cofactor) { + BN_CTX *ctx = BN_CTX_new(); + if (ctx == NULL) { + return NULL; + } + + EC_POINT *generator = NULL; + EC_GROUP *ret = EC_GROUP_new_curve_GFp(p, a, b, ctx); + if (ret == NULL) { + goto err; + } + + generator = EC_POINT_new(ret); + if (generator == NULL || + !EC_POINT_set_affine_coordinates_GFp(ret, generator, gx, gy, ctx) || + !EC_GROUP_set_generator(ret, generator, order, cofactor)) { + goto err; + } + + EC_POINT_free(generator); + BN_CTX_free(ctx); + return ret; + +err: + EC_POINT_free(generator); + EC_GROUP_free(ret); + BN_CTX_free(ctx); + return NULL; +} + +static EC_GROUP *ec_group_new_from_data(unsigned built_in_index) { + const struct built_in_curve *curve = &OPENSSL_built_in_curves[built_in_index]; + EC_GROUP *group = NULL; + EC_POINT *P = NULL; + BIGNUM *p = NULL, *a = NULL, *b = NULL, *x = NULL, *y = NULL; + const EC_METHOD *meth; + int ok = 0; + + BN_CTX *ctx = BN_CTX_new(); + if (ctx == NULL) { + OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); + goto err; + } + + const struct curve_data *data = curve->data; + const unsigned param_len = data->param_len; + const uint8_t *params = data->data; + + if (!(p = BN_bin2bn(params + 0 * param_len, param_len, NULL)) || + !(a = BN_bin2bn(params + 1 * param_len, param_len, NULL)) || + !(b = BN_bin2bn(params + 2 * param_len, param_len, NULL))) { + OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); + goto err; + } + + if (curve->method != 0) { + meth = curve->method(); + if (((group = ec_group_new(meth)) == NULL) || + (!(group->meth->group_set_curve(group, p, a, b, ctx)))) { + OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB); + goto err; + } + } else { + if ((group = EC_GROUP_new_curve_GFp(p, a, b, ctx)) == NULL) { + OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB); + goto err; + } + } + + if ((P = EC_POINT_new(group)) == NULL) { + OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB); + goto err; + } + + if (!(x = BN_bin2bn(params + 3 * param_len, param_len, NULL)) || + !(y = BN_bin2bn(params + 4 * param_len, param_len, NULL))) { + OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); + goto err; + } + + if (!EC_POINT_set_affine_coordinates_GFp(group, P, x, y, ctx)) { + OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB); + goto err; + } + if (!BN_bin2bn(params + 5 * param_len, param_len, &group->order) || + !BN_set_word(&group->cofactor, (BN_ULONG)data->cofactor)) { + OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); + goto err; + } + + CRYPTO_once(&built_in_curve_scalar_field_monts_once, + built_in_curve_scalar_field_monts_init); + if (built_in_curve_scalar_field_monts != NULL) { + group->mont_data = built_in_curve_scalar_field_monts[built_in_index]; + } + + group->generator = P; + P = NULL; + ok = 1; + +err: + if (!ok) { + EC_GROUP_free(group); + group = NULL; + } + EC_POINT_free(P); + BN_CTX_free(ctx); + BN_free(p); + BN_free(a); + BN_free(b); + BN_free(x); + BN_free(y); + return group; +} + +EC_GROUP *EC_GROUP_new_by_curve_name(int nid) { + unsigned i; + const struct built_in_curve *curve; + EC_GROUP *ret = NULL; + + for (i = 0; OPENSSL_built_in_curves[i].nid != NID_undef; i++) { + curve = &OPENSSL_built_in_curves[i]; + if (curve->nid == nid) { + ret = ec_group_new_from_data(i); + break; + } + } + + if (ret == NULL) { + OPENSSL_PUT_ERROR(EC, EC_R_UNKNOWN_GROUP); + return NULL; + } + + ret->curve_name = nid; + return ret; +} + +void EC_GROUP_free(EC_GROUP *group) { + if (!group) { + return; + } + + if (group->meth->group_finish != 0) { + group->meth->group_finish(group); + } + + EC_POINT_free(group->generator); + BN_free(&group->order); + BN_free(&group->cofactor); + + OPENSSL_free(group); +} + +int ec_group_copy(EC_GROUP *dest, const EC_GROUP *src) { + if (dest->meth->group_copy == 0) { + OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + if (dest->meth != src->meth) { + OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + if (dest == src) { + return 1; + } + + dest->mont_data = src->mont_data; + + if (src->generator != NULL) { + if (dest->generator == NULL) { + dest->generator = EC_POINT_new(dest); + if (dest->generator == NULL) { + return 0; + } + } + if (!EC_POINT_copy(dest->generator, src->generator)) { + return 0; + } + } else { + EC_POINT_clear_free(dest->generator); + dest->generator = NULL; + } + + if (!BN_copy(&dest->order, &src->order) || + !BN_copy(&dest->cofactor, &src->cofactor)) { + return 0; + } + + dest->curve_name = src->curve_name; + + return dest->meth->group_copy(dest, src); +} + +const BN_MONT_CTX *ec_group_get_mont_data(const EC_GROUP *group) { + return group->mont_data; +} + +EC_GROUP *EC_GROUP_dup(const EC_GROUP *a) { + EC_GROUP *t = NULL; + int ok = 0; + + if (a == NULL) { + return NULL; + } + + t = ec_group_new(a->meth); + if (t == NULL) { + return NULL; + } + if (!ec_group_copy(t, a)) { + goto err; + } + + ok = 1; + +err: + if (!ok) { + EC_GROUP_free(t); + return NULL; + } else { + return t; + } +} + +int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ignored) { + return a->curve_name == NID_undef || + b->curve_name == NID_undef || + a->curve_name != b->curve_name; +} + +const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group) { + return group->generator; +} + +const BIGNUM *EC_GROUP_get0_order(const EC_GROUP *group) { + assert(!BN_is_zero(&group->order)); + return &group->order; +} + +int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx) { + if (BN_copy(order, EC_GROUP_get0_order(group)) == NULL) { + return 0; + } + return 1; +} + +int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor, + BN_CTX *ctx) { + if (!BN_copy(cofactor, &group->cofactor)) { + return 0; + } + + return !BN_is_zero(&group->cofactor); +} + +int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *out_p, BIGNUM *out_a, + BIGNUM *out_b, BN_CTX *ctx) { + return ec_GFp_simple_group_get_curve(group, out_p, out_a, out_b, ctx); +} + +int EC_GROUP_get_curve_name(const EC_GROUP *group) { return group->curve_name; } + +unsigned EC_GROUP_get_degree(const EC_GROUP *group) { + return ec_GFp_simple_group_get_degree(group); +} + +EC_POINT *EC_POINT_new(const EC_GROUP *group) { + EC_POINT *ret; + + if (group == NULL) { + OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + + ret = OPENSSL_malloc(sizeof *ret); + if (ret == NULL) { + OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); + return NULL; + } + + ret->meth = group->meth; + + if (!ec_GFp_simple_point_init(ret)) { + OPENSSL_free(ret); + return NULL; + } + + return ret; +} + +void EC_POINT_free(EC_POINT *point) { + if (!point) { + return; + } + + ec_GFp_simple_point_finish(point); + + OPENSSL_free(point); +} + +void EC_POINT_clear_free(EC_POINT *point) { + if (!point) { + return; + } + + ec_GFp_simple_point_clear_finish(point); + + OPENSSL_cleanse(point, sizeof *point); + OPENSSL_free(point); +} + +int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src) { + if (dest->meth != src->meth) { + OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + if (dest == src) { + return 1; + } + return ec_GFp_simple_point_copy(dest, src); +} + +EC_POINT *EC_POINT_dup(const EC_POINT *a, const EC_GROUP *group) { + EC_POINT *t; + int r; + + if (a == NULL) { + return NULL; + } + + t = EC_POINT_new(group); + if (t == NULL) { + OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); + return NULL; + } + r = EC_POINT_copy(t, a); + if (!r) { + EC_POINT_free(t); + return NULL; + } else { + return t; + } +} + +int EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point) { + if (group->meth != point->meth) { + OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + return ec_GFp_simple_point_set_to_infinity(group, point); +} + +int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point) { + if (group->meth != point->meth) { + OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + return ec_GFp_simple_is_at_infinity(group, point); +} + +int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point, + BN_CTX *ctx) { + if (group->meth != point->meth) { + OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + return ec_GFp_simple_is_on_curve(group, point, ctx); +} + +int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, + BN_CTX *ctx) { + if ((group->meth != a->meth) || (a->meth != b->meth)) { + OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS); + return -1; + } + return ec_GFp_simple_cmp(group, a, b, ctx); +} + +int EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx) { + if (group->meth != point->meth) { + OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + return ec_GFp_simple_make_affine(group, point, ctx); +} + +int EC_POINTs_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[], + BN_CTX *ctx) { + size_t i; + + for (i = 0; i < num; i++) { + if (group->meth != points[i]->meth) { + OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + } + return ec_GFp_simple_points_make_affine(group, num, points, ctx); +} + +int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group, + const EC_POINT *point, BIGNUM *x, + BIGNUM *y, BN_CTX *ctx) { + if (group->meth->point_get_affine_coordinates == 0) { + OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + if (group->meth != point->meth) { + OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + return group->meth->point_get_affine_coordinates(group, point, x, y, ctx); +} + +int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *point, + const BIGNUM *x, const BIGNUM *y, + BN_CTX *ctx) { + if (group->meth != point->meth) { + OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + if (!ec_GFp_simple_point_set_affine_coordinates(group, point, x, y, ctx)) { + return 0; + } + + if (!EC_POINT_is_on_curve(group, point, ctx)) { + OPENSSL_PUT_ERROR(EC, EC_R_POINT_IS_NOT_ON_CURVE); + return 0; + } + + return 1; +} + +int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, + const EC_POINT *b, BN_CTX *ctx) { + if ((group->meth != r->meth) || (r->meth != a->meth) || + (a->meth != b->meth)) { + OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + return ec_GFp_simple_add(group, r, a, b, ctx); +} + + +int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, + BN_CTX *ctx) { + if ((group->meth != r->meth) || (r->meth != a->meth)) { + OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + return ec_GFp_simple_dbl(group, r, a, ctx); +} + + +int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx) { + if (group->meth != a->meth) { + OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + return ec_GFp_simple_invert(group, a, ctx); +} + +int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar, + const EC_POINT *p, const BIGNUM *p_scalar, BN_CTX *ctx) { + /* Previously, this function set |r| to the point at infinity if there was + * nothing to multiply. But, nobody should be calling this function with + * nothing to multiply in the first place. */ + if ((g_scalar == NULL && p_scalar == NULL) || + ((p == NULL) != (p_scalar == NULL))) { + OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (group->meth != r->meth || + (p != NULL && group->meth != p->meth)) { + OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + + return group->meth->mul(group, r, g_scalar, p, p_scalar, ctx); +} + +int ec_point_set_Jprojective_coordinates_GFp(const EC_GROUP *group, EC_POINT *point, + const BIGNUM *x, const BIGNUM *y, + const BIGNUM *z, BN_CTX *ctx) { + if (group->meth != point->meth) { + OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + return ec_GFp_simple_set_Jprojective_coordinates_GFp(group, point, x, y, z, + ctx); +} + +void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag) {} + +const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group) { + return NULL; +} + +int EC_METHOD_get_field_type(const EC_METHOD *meth) { + return NID_X9_62_prime_field; +} + +void EC_GROUP_set_point_conversion_form(EC_GROUP *group, + point_conversion_form_t form) { + if (form != POINT_CONVERSION_UNCOMPRESSED) { + abort(); + } +} + +size_t EC_get_builtin_curves(EC_builtin_curve *out_curves, + size_t max_num_curves) { + unsigned num_built_in_curves; + for (num_built_in_curves = 0;; num_built_in_curves++) { + if (OPENSSL_built_in_curves[num_built_in_curves].nid == NID_undef) { + break; + } + } + + unsigned i; + for (i = 0; i < max_num_curves && i < num_built_in_curves; i++) { + out_curves[i].comment = OPENSSL_built_in_curves[i].data->comment; + out_curves[i].nid = OPENSSL_built_in_curves[i].nid; + } + + return num_built_in_curves; +} diff --git a/external/boringssl/crypto/ec/ec_asn1.c b/external/boringssl/crypto/ec/ec_asn1.c new file mode 100644 index 0000000000..f31e158709 --- /dev/null +++ b/external/boringssl/crypto/ec/ec_asn1.c @@ -0,0 +1,549 @@ +/* Written by Nils Larsch for the OpenSSL project. */ +/* ==================================================================== + * Copyright (c) 2000-2003 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include "internal.h" +#include "../bytestring/internal.h" + + +static const uint8_t kParametersTag = + CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 0; +static const uint8_t kPublicKeyTag = + CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 1; + +EC_KEY *EC_KEY_parse_private_key(CBS *cbs, const EC_GROUP *group) { + CBS ec_private_key, private_key; + uint64_t version; + if (!CBS_get_asn1(cbs, &ec_private_key, CBS_ASN1_SEQUENCE) || + !CBS_get_asn1_uint64(&ec_private_key, &version) || + version != 1 || + !CBS_get_asn1(&ec_private_key, &private_key, CBS_ASN1_OCTETSTRING)) { + OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR); + return NULL; + } + + /* Parse the optional parameters field. */ + EC_GROUP *inner_group = NULL; + EC_KEY *ret = NULL; + if (CBS_peek_asn1_tag(&ec_private_key, kParametersTag)) { + /* Per SEC 1, as an alternative to omitting it, one is allowed to specify + * this field and put in a NULL to mean inheriting this value. This was + * omitted in a previous version of this logic without problems, so leave it + * unimplemented. */ + CBS child; + if (!CBS_get_asn1(&ec_private_key, &child, kParametersTag)) { + OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR); + goto err; + } + inner_group = EC_KEY_parse_parameters(&child); + if (inner_group == NULL) { + goto err; + } + if (group == NULL) { + group = inner_group; + } else if (EC_GROUP_cmp(group, inner_group, NULL) != 0) { + /* If a group was supplied externally, it must match. */ + OPENSSL_PUT_ERROR(EC, EC_R_GROUP_MISMATCH); + goto err; + } + if (CBS_len(&child) != 0) { + OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR); + goto err; + } + } + + if (group == NULL) { + OPENSSL_PUT_ERROR(EC, EC_R_MISSING_PARAMETERS); + goto err; + } + + ret = EC_KEY_new(); + if (ret == NULL || !EC_KEY_set_group(ret, group)) { + goto err; + } + + /* Although RFC 5915 specifies the length of the key, OpenSSL historically + * got this wrong, so accept any length. See upstream's + * 30cd4ff294252c4b6a4b69cbef6a5b4117705d22. */ + ret->priv_key = + BN_bin2bn(CBS_data(&private_key), CBS_len(&private_key), NULL); + ret->pub_key = EC_POINT_new(group); + if (ret->priv_key == NULL || ret->pub_key == NULL) { + goto err; + } + + if (BN_cmp(ret->priv_key, EC_GROUP_get0_order(group)) >= 0) { + OPENSSL_PUT_ERROR(EC, EC_R_WRONG_ORDER); + goto err; + } + + if (CBS_peek_asn1_tag(&ec_private_key, kPublicKeyTag)) { + CBS child, public_key; + uint8_t padding; + if (!CBS_get_asn1(&ec_private_key, &child, kPublicKeyTag) || + !CBS_get_asn1(&child, &public_key, CBS_ASN1_BITSTRING) || + /* As in a SubjectPublicKeyInfo, the byte-encoded public key is then + * encoded as a BIT STRING with bits ordered as in the DER encoding. */ + !CBS_get_u8(&public_key, &padding) || + padding != 0 || + /* Explicitly check |public_key| is non-empty to save the conversion + * form later. */ + CBS_len(&public_key) == 0 || + !EC_POINT_oct2point(group, ret->pub_key, CBS_data(&public_key), + CBS_len(&public_key), NULL) || + CBS_len(&child) != 0) { + OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR); + goto err; + } + + /* Save the point conversion form. + * TODO(davidben): Consider removing this. */ + ret->conv_form = (point_conversion_form_t)(CBS_data(&public_key)[0] & ~0x01); + } else { + /* Compute the public key instead. */ + if (!EC_POINT_mul(group, ret->pub_key, ret->priv_key, NULL, NULL, NULL)) { + goto err; + } + /* Remember the original private-key-only encoding. + * TODO(davidben): Consider removing this. */ + ret->enc_flag |= EC_PKEY_NO_PUBKEY; + } + + if (CBS_len(&ec_private_key) != 0) { + OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR); + goto err; + } + + /* Ensure the resulting key is valid. */ + if (!EC_KEY_check_key(ret)) { + goto err; + } + + EC_GROUP_free(inner_group); + return ret; + +err: + EC_KEY_free(ret); + EC_GROUP_free(inner_group); + return NULL; +} + +int EC_KEY_marshal_private_key(CBB *cbb, const EC_KEY *key, + unsigned enc_flags) { + if (key == NULL || key->group == NULL || key->priv_key == NULL) { + OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + CBB ec_private_key, private_key; + if (!CBB_add_asn1(cbb, &ec_private_key, CBS_ASN1_SEQUENCE) || + !CBB_add_asn1_uint64(&ec_private_key, 1 /* version */) || + !CBB_add_asn1(&ec_private_key, &private_key, CBS_ASN1_OCTETSTRING) || + !BN_bn2cbb_padded(&private_key, + BN_num_bytes(EC_GROUP_get0_order(key->group)), + key->priv_key)) { + OPENSSL_PUT_ERROR(EC, EC_R_ENCODE_ERROR); + return 0; + } + + if (!(enc_flags & EC_PKEY_NO_PARAMETERS)) { + CBB child; + if (!CBB_add_asn1(&ec_private_key, &child, kParametersTag) || + !EC_KEY_marshal_curve_name(&child, key->group) || + !CBB_flush(&ec_private_key)) { + OPENSSL_PUT_ERROR(EC, EC_R_ENCODE_ERROR); + return 0; + } + } + + /* TODO(fork): replace this flexibility with sensible default? */ + if (!(enc_flags & EC_PKEY_NO_PUBKEY) && key->pub_key != NULL) { + CBB child, public_key; + if (!CBB_add_asn1(&ec_private_key, &child, kPublicKeyTag) || + !CBB_add_asn1(&child, &public_key, CBS_ASN1_BITSTRING) || + /* As in a SubjectPublicKeyInfo, the byte-encoded public key is then + * encoded as a BIT STRING with bits ordered as in the DER encoding. */ + !CBB_add_u8(&public_key, 0 /* padding */) || + !EC_POINT_point2cbb(&public_key, key->group, key->pub_key, + key->conv_form, NULL) || + !CBB_flush(&ec_private_key)) { + OPENSSL_PUT_ERROR(EC, EC_R_ENCODE_ERROR); + return 0; + } + } + + if (!CBB_flush(cbb)) { + OPENSSL_PUT_ERROR(EC, EC_R_ENCODE_ERROR); + return 0; + } + + return 1; +} + +/* is_unsigned_integer returns one if |cbs| is a valid unsigned DER INTEGER and + * zero otherwise. */ +static int is_unsigned_integer(const CBS *cbs) { + if (CBS_len(cbs) == 0) { + return 0; + } + uint8_t byte = CBS_data(cbs)[0]; + if ((byte & 0x80) || + (byte == 0 && CBS_len(cbs) > 1 && (CBS_data(cbs)[1] & 0x80) == 0)) { + /* Negative or not minimally-encoded. */ + return 0; + } + return 1; +} + +/* kPrimeFieldOID is the encoding of 1.2.840.10045.1.1. */ +static const uint8_t kPrimeField[] = {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01, 0x01}; + +static int parse_explicit_prime_curve(CBS *in, CBS *out_prime, CBS *out_a, + CBS *out_b, CBS *out_base_x, + CBS *out_base_y, CBS *out_order) { + /* See RFC 3279, section 2.3.5. Note that RFC 3279 calls this structure an + * ECParameters while RFC 5480 calls it a SpecifiedECDomain. */ + CBS params, field_id, field_type, curve, base; + uint64_t version; + if (!CBS_get_asn1(in, ¶ms, CBS_ASN1_SEQUENCE) || + !CBS_get_asn1_uint64(¶ms, &version) || + version != 1 || + !CBS_get_asn1(¶ms, &field_id, CBS_ASN1_SEQUENCE) || + !CBS_get_asn1(&field_id, &field_type, CBS_ASN1_OBJECT) || + CBS_len(&field_type) != sizeof(kPrimeField) || + memcmp(CBS_data(&field_type), kPrimeField, sizeof(kPrimeField)) != 0 || + !CBS_get_asn1(&field_id, out_prime, CBS_ASN1_INTEGER) || + !is_unsigned_integer(out_prime) || + CBS_len(&field_id) != 0 || + !CBS_get_asn1(¶ms, &curve, CBS_ASN1_SEQUENCE) || + !CBS_get_asn1(&curve, out_a, CBS_ASN1_OCTETSTRING) || + !CBS_get_asn1(&curve, out_b, CBS_ASN1_OCTETSTRING) || + /* |curve| has an optional BIT STRING seed which we ignore. */ + !CBS_get_asn1(¶ms, &base, CBS_ASN1_OCTETSTRING) || + !CBS_get_asn1(¶ms, out_order, CBS_ASN1_INTEGER) || + !is_unsigned_integer(out_order)) { + OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR); + return 0; + } + + /* |params| has an optional cofactor which we ignore. With the optional seed + * in |curve|, a group already has arbitrarily many encodings. Parse enough to + * uniquely determine the curve. */ + + /* Require that the base point use uncompressed form. */ + uint8_t form; + if (!CBS_get_u8(&base, &form) || form != POINT_CONVERSION_UNCOMPRESSED) { + OPENSSL_PUT_ERROR(EC, EC_R_INVALID_FORM); + return 0; + } + + if (CBS_len(&base) % 2 != 0) { + OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR); + return 0; + } + size_t field_len = CBS_len(&base) / 2; + CBS_init(out_base_x, CBS_data(&base), field_len); + CBS_init(out_base_y, CBS_data(&base) + field_len, field_len); + + return 1; +} + +/* integers_equal returns one if |a| and |b| are equal, up to leading zeros, and + * zero otherwise. */ +static int integers_equal(const CBS *a, const uint8_t *b, size_t b_len) { + /* Remove leading zeros from |a| and |b|. */ + CBS a_copy = *a; + while (CBS_len(&a_copy) > 0 && CBS_data(&a_copy)[0] == 0) { + CBS_skip(&a_copy, 1); + } + while (b_len > 0 && b[0] == 0) { + b++; + b_len--; + } + return CBS_mem_equal(&a_copy, b, b_len); +} + +EC_GROUP *EC_KEY_parse_curve_name(CBS *cbs) { + CBS named_curve; + if (!CBS_get_asn1(cbs, &named_curve, CBS_ASN1_OBJECT)) { + OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR); + return NULL; + } + + /* Look for a matching curve. */ + unsigned i; + for (i = 0; OPENSSL_built_in_curves[i].nid != NID_undef; i++) { + const struct built_in_curve *curve = &OPENSSL_built_in_curves[i]; + if (CBS_len(&named_curve) == curve->oid_len && + memcmp(CBS_data(&named_curve), curve->oid, curve->oid_len) == 0) { + return EC_GROUP_new_by_curve_name(curve->nid); + } + } + + OPENSSL_PUT_ERROR(EC, EC_R_UNKNOWN_GROUP); + return NULL; +} + +int EC_KEY_marshal_curve_name(CBB *cbb, const EC_GROUP *group) { + int nid = EC_GROUP_get_curve_name(group); + if (nid == NID_undef) { + OPENSSL_PUT_ERROR(EC, EC_R_UNKNOWN_GROUP); + return 0; + } + + unsigned i; + for (i = 0; OPENSSL_built_in_curves[i].nid != NID_undef; i++) { + const struct built_in_curve *curve = &OPENSSL_built_in_curves[i]; + if (curve->nid == nid) { + CBB child; + return CBB_add_asn1(cbb, &child, CBS_ASN1_OBJECT) && + CBB_add_bytes(&child, curve->oid, curve->oid_len) && + CBB_flush(cbb); + } + } + + OPENSSL_PUT_ERROR(EC, EC_R_UNKNOWN_GROUP); + return 0; +} + +EC_GROUP *EC_KEY_parse_parameters(CBS *cbs) { + if (!CBS_peek_asn1_tag(cbs, CBS_ASN1_SEQUENCE)) { + return EC_KEY_parse_curve_name(cbs); + } + + /* OpenSSL sometimes produces ECPrivateKeys with explicitly-encoded versions + * of named curves. + * + * TODO(davidben): Remove support for this. */ + CBS prime, a, b, base_x, base_y, order; + if (!parse_explicit_prime_curve(cbs, &prime, &a, &b, &base_x, &base_y, + &order)) { + return NULL; + } + + /* Look for a matching prime curve. */ + unsigned i; + for (i = 0; OPENSSL_built_in_curves[i].nid != NID_undef; i++) { + const struct built_in_curve *curve = &OPENSSL_built_in_curves[i]; + const unsigned param_len = curve->data->param_len; + /* |curve->data->data| is ordered p, a, b, x, y, order, each component + * zero-padded up to the field length. Although SEC 1 states that the + * Field-Element-to-Octet-String conversion also pads, OpenSSL mis-encodes + * |a| and |b|, so this comparison must allow omitting leading zeros. (This + * is relevant for P-521 whose |b| has a leading 0.) */ + if (integers_equal(&prime, curve->data->data, param_len) && + integers_equal(&a, curve->data->data + param_len, param_len) && + integers_equal(&b, curve->data->data + param_len * 2, param_len) && + integers_equal(&base_x, curve->data->data + param_len * 3, param_len) && + integers_equal(&base_y, curve->data->data + param_len * 4, param_len) && + integers_equal(&order, curve->data->data + param_len * 5, param_len)) { + return EC_GROUP_new_by_curve_name(curve->nid); + } + } + + OPENSSL_PUT_ERROR(EC, EC_R_UNKNOWN_GROUP); + return NULL; +} + +EC_KEY *d2i_ECPrivateKey(EC_KEY **out, const uint8_t **inp, long len) { + /* This function treats its |out| parameter differently from other |d2i| + * functions. If supplied, take the group from |*out|. */ + const EC_GROUP *group = NULL; + if (out != NULL && *out != NULL) { + group = EC_KEY_get0_group(*out); + } + + if (len < 0) { + OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR); + return NULL; + } + CBS cbs; + CBS_init(&cbs, *inp, (size_t)len); + EC_KEY *ret = EC_KEY_parse_private_key(&cbs, group); + if (ret == NULL) { + return NULL; + } + if (out != NULL) { + EC_KEY_free(*out); + *out = ret; + } + *inp = CBS_data(&cbs); + return ret; +} + +int i2d_ECPrivateKey(const EC_KEY *key, uint8_t **outp) { + CBB cbb; + if (!CBB_init(&cbb, 0) || + !EC_KEY_marshal_private_key(&cbb, key, EC_KEY_get_enc_flags(key))) { + CBB_cleanup(&cbb); + return -1; + } + return CBB_finish_i2d(&cbb, outp); +} + +EC_KEY *d2i_ECParameters(EC_KEY **out_key, const uint8_t **inp, long len) { + if (len < 0) { + return NULL; + } + + CBS cbs; + CBS_init(&cbs, *inp, (size_t)len); + EC_GROUP *group = EC_KEY_parse_parameters(&cbs); + if (group == NULL) { + return NULL; + } + + EC_KEY *ret = EC_KEY_new(); + if (ret == NULL || !EC_KEY_set_group(ret, group)) { + EC_GROUP_free(group); + EC_KEY_free(ret); + return NULL; + } + EC_GROUP_free(group); + + if (out_key != NULL) { + EC_KEY_free(*out_key); + *out_key = ret; + } + *inp = CBS_data(&cbs); + return ret; +} + +int i2d_ECParameters(const EC_KEY *key, uint8_t **outp) { + if (key == NULL || key->group == NULL) { + OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER); + return -1; + } + + CBB cbb; + if (!CBB_init(&cbb, 0) || + !EC_KEY_marshal_curve_name(&cbb, key->group)) { + CBB_cleanup(&cbb); + return -1; + } + return CBB_finish_i2d(&cbb, outp); +} + +EC_KEY *o2i_ECPublicKey(EC_KEY **keyp, const uint8_t **inp, long len) { + EC_KEY *ret = NULL; + + if (keyp == NULL || *keyp == NULL || (*keyp)->group == NULL) { + OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + ret = *keyp; + if (ret->pub_key == NULL && + (ret->pub_key = EC_POINT_new(ret->group)) == NULL) { + OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); + return NULL; + } + if (!EC_POINT_oct2point(ret->group, ret->pub_key, *inp, len, NULL)) { + OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB); + return NULL; + } + /* save the point conversion form */ + ret->conv_form = (point_conversion_form_t)(*inp[0] & ~0x01); + *inp += len; + return ret; +} + +int i2o_ECPublicKey(const EC_KEY *key, uint8_t **outp) { + size_t buf_len = 0; + int new_buffer = 0; + + if (key == NULL) { + OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + buf_len = EC_POINT_point2oct(key->group, key->pub_key, key->conv_form, NULL, + 0, NULL); + + if (outp == NULL || buf_len == 0) { + /* out == NULL => just return the length of the octet string */ + return buf_len; + } + + if (*outp == NULL) { + *outp = OPENSSL_malloc(buf_len); + if (*outp == NULL) { + OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); + return 0; + } + new_buffer = 1; + } + if (!EC_POINT_point2oct(key->group, key->pub_key, key->conv_form, *outp, + buf_len, NULL)) { + OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB); + if (new_buffer) { + OPENSSL_free(*outp); + *outp = NULL; + } + return 0; + } + + if (!new_buffer) { + *outp += buf_len; + } + return buf_len; +} diff --git a/external/boringssl/crypto/ec/ec_key.c b/external/boringssl/crypto/ec/ec_key.c new file mode 100644 index 0000000000..fee71fed89 --- /dev/null +++ b/external/boringssl/crypto/ec/ec_key.c @@ -0,0 +1,489 @@ +/* Originally written by Bodo Moeller for the OpenSSL project. + * ==================================================================== + * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * + * Portions of the attached software ("Contribution") are developed by + * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. + * + * The Contribution is licensed pursuant to the OpenSSL open source + * license provided above. + * + * The elliptic curve binary polynomial software is originally written by + * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems + * Laboratories. */ + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include "internal.h" +#include "../internal.h" + + +static CRYPTO_EX_DATA_CLASS g_ex_data_class = CRYPTO_EX_DATA_CLASS_INIT; + +EC_KEY *EC_KEY_new(void) { return EC_KEY_new_method(NULL); } + +EC_KEY *EC_KEY_new_method(const ENGINE *engine) { + EC_KEY *ret = OPENSSL_malloc(sizeof(EC_KEY)); + if (ret == NULL) { + OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); + return NULL; + } + + memset(ret, 0, sizeof(EC_KEY)); + + if (engine) { + ret->ecdsa_meth = ENGINE_get_ECDSA_method(engine); + } + if (ret->ecdsa_meth) { + METHOD_ref(ret->ecdsa_meth); + } + + ret->conv_form = POINT_CONVERSION_UNCOMPRESSED; + ret->references = 1; + + CRYPTO_new_ex_data(&ret->ex_data); + + if (ret->ecdsa_meth && ret->ecdsa_meth->init && !ret->ecdsa_meth->init(ret)) { + CRYPTO_free_ex_data(&g_ex_data_class, ret, &ret->ex_data); + if (ret->ecdsa_meth) { + METHOD_unref(ret->ecdsa_meth); + } + OPENSSL_free(ret); + return NULL; + } + + return ret; +} + +EC_KEY *EC_KEY_new_by_curve_name(int nid) { + EC_KEY *ret = EC_KEY_new(); + if (ret == NULL) { + OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); + return NULL; + } + ret->group = EC_GROUP_new_by_curve_name(nid); + if (ret->group == NULL) { + EC_KEY_free(ret); + return NULL; + } + return ret; +} + +void EC_KEY_free(EC_KEY *r) { + if (r == NULL) { + return; + } + + if (!CRYPTO_refcount_dec_and_test_zero(&r->references)) { + return; + } + + if (r->ecdsa_meth) { + if (r->ecdsa_meth->finish) { + r->ecdsa_meth->finish(r); + } + METHOD_unref(r->ecdsa_meth); + } + + EC_GROUP_free(r->group); + EC_POINT_free(r->pub_key); + BN_clear_free(r->priv_key); + + CRYPTO_free_ex_data(&g_ex_data_class, r, &r->ex_data); + + OPENSSL_cleanse((void *)r, sizeof(EC_KEY)); + OPENSSL_free(r); +} + +EC_KEY *EC_KEY_copy(EC_KEY *dest, const EC_KEY *src) { + if (dest == NULL || src == NULL) { + OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + /* Copy the parameters. */ + if (src->group) { + /* TODO(fork): duplicating the group seems wasteful. */ + EC_GROUP_free(dest->group); + dest->group = EC_GROUP_dup(src->group); + if (dest->group == NULL) { + return NULL; + } + } + + /* Copy the public key. */ + if (src->pub_key && src->group) { + EC_POINT_free(dest->pub_key); + dest->pub_key = EC_POINT_dup(src->pub_key, src->group); + if (dest->pub_key == NULL) { + return NULL; + } + } + + /* copy the private key */ + if (src->priv_key) { + if (dest->priv_key == NULL) { + dest->priv_key = BN_new(); + if (dest->priv_key == NULL) { + return NULL; + } + } + if (!BN_copy(dest->priv_key, src->priv_key)) { + return NULL; + } + } + /* copy method/extra data */ + if (src->ecdsa_meth) { + METHOD_unref(dest->ecdsa_meth); + dest->ecdsa_meth = src->ecdsa_meth; + METHOD_ref(dest->ecdsa_meth); + } + CRYPTO_free_ex_data(&g_ex_data_class, dest, &dest->ex_data); + if (!CRYPTO_dup_ex_data(&g_ex_data_class, &dest->ex_data, + &src->ex_data)) { + return NULL; + } + + /* copy the rest */ + dest->enc_flag = src->enc_flag; + dest->conv_form = src->conv_form; + + return dest; +} + +EC_KEY *EC_KEY_dup(const EC_KEY *ec_key) { + EC_KEY *ret = EC_KEY_new(); + if (ret == NULL) { + return NULL; + } + if (EC_KEY_copy(ret, ec_key) == NULL) { + EC_KEY_free(ret); + return NULL; + } + return ret; +} + +int EC_KEY_up_ref(EC_KEY *r) { + CRYPTO_refcount_inc(&r->references); + return 1; +} + +int EC_KEY_is_opaque(const EC_KEY *key) { + return key->ecdsa_meth && (key->ecdsa_meth->flags & ECDSA_FLAG_OPAQUE); +} + +const EC_GROUP *EC_KEY_get0_group(const EC_KEY *key) { return key->group; } + +int EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group) { + EC_GROUP_free(key->group); + /* TODO(fork): duplicating the group seems wasteful but see + * |EC_KEY_set_conv_form|. */ + key->group = EC_GROUP_dup(group); + if (key->group == NULL) { + return 0; + } + /* XXX: |BN_cmp| is not constant time. */ + if (key->priv_key != NULL && + BN_cmp(key->priv_key, EC_GROUP_get0_order(group)) >= 0) { + return 0; + } + return 1; +} + +const BIGNUM *EC_KEY_get0_private_key(const EC_KEY *key) { + return key->priv_key; +} + +int EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *priv_key) { + /* XXX: |BN_cmp| is not constant time. */ + if (key->group != NULL && + BN_cmp(priv_key, EC_GROUP_get0_order(key->group)) >= 0) { + OPENSSL_PUT_ERROR(EC, EC_R_WRONG_ORDER); + return 0; + } + BN_clear_free(key->priv_key); + key->priv_key = BN_dup(priv_key); + return (key->priv_key == NULL) ? 0 : 1; +} + +const EC_POINT *EC_KEY_get0_public_key(const EC_KEY *key) { + return key->pub_key; +} + +int EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub_key) { + EC_POINT_free(key->pub_key); + key->pub_key = EC_POINT_dup(pub_key, key->group); + return (key->pub_key == NULL) ? 0 : 1; +} + +unsigned int EC_KEY_get_enc_flags(const EC_KEY *key) { return key->enc_flag; } + +void EC_KEY_set_enc_flags(EC_KEY *key, unsigned int flags) { + key->enc_flag = flags; +} + +point_conversion_form_t EC_KEY_get_conv_form(const EC_KEY *key) { + return key->conv_form; +} + +void EC_KEY_set_conv_form(EC_KEY *key, point_conversion_form_t cform) { + key->conv_form = cform; +} + +int EC_KEY_check_key(const EC_KEY *eckey) { + int ok = 0; + BN_CTX *ctx = NULL; + EC_POINT *point = NULL; + + if (!eckey || !eckey->group || !eckey->pub_key) { + OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (EC_POINT_is_at_infinity(eckey->group, eckey->pub_key)) { + OPENSSL_PUT_ERROR(EC, EC_R_POINT_AT_INFINITY); + goto err; + } + + ctx = BN_CTX_new(); + + if (ctx == NULL) { + goto err; + } + + /* testing whether the pub_key is on the elliptic curve */ + if (!EC_POINT_is_on_curve(eckey->group, eckey->pub_key, ctx)) { + OPENSSL_PUT_ERROR(EC, EC_R_POINT_IS_NOT_ON_CURVE); + goto err; + } + /* TODO(fork): can this be skipped if the cofactor is one or if we're about + * to check the private key, below? */ + if (eckey->group->meth->check_pub_key_order != NULL && + !eckey->group->meth->check_pub_key_order(eckey->group, eckey->pub_key, + ctx)) { + OPENSSL_PUT_ERROR(EC, EC_R_WRONG_ORDER); + goto err; + } + /* in case the priv_key is present : + * check if generator * priv_key == pub_key + */ + if (eckey->priv_key) { + /* XXX: |BN_cmp| is not constant time. */ + if (BN_cmp(eckey->priv_key, EC_GROUP_get0_order(eckey->group)) >= 0) { + OPENSSL_PUT_ERROR(EC, EC_R_WRONG_ORDER); + goto err; + } + point = EC_POINT_new(eckey->group); + if (point == NULL || + !EC_POINT_mul(eckey->group, point, eckey->priv_key, NULL, NULL, ctx)) { + OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB); + goto err; + } + if (EC_POINT_cmp(eckey->group, point, eckey->pub_key, ctx) != 0) { + OPENSSL_PUT_ERROR(EC, EC_R_INVALID_PRIVATE_KEY); + goto err; + } + } + ok = 1; + +err: + BN_CTX_free(ctx); + EC_POINT_free(point); + return ok; +} + +int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x, + BIGNUM *y) { + BN_CTX *ctx = NULL; + BIGNUM *tx, *ty; + EC_POINT *point = NULL; + int ok = 0; + + if (!key || !key->group || !x || !y) { + OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + ctx = BN_CTX_new(); + + if (ctx == NULL) { + return 0; + } + + BN_CTX_start(ctx); + point = EC_POINT_new(key->group); + + if (point == NULL) { + goto err; + } + + tx = BN_CTX_get(ctx); + ty = BN_CTX_get(ctx); + if (tx == NULL || + ty == NULL) { + goto err; + } + + if (!EC_POINT_set_affine_coordinates_GFp(key->group, point, x, y, ctx) || + !EC_POINT_get_affine_coordinates_GFp(key->group, point, tx, ty, ctx)) { + goto err; + } + + /* Check if retrieved coordinates match originals: if not values + * are out of range. */ + if (BN_cmp(x, tx) || BN_cmp(y, ty)) { + OPENSSL_PUT_ERROR(EC, EC_R_COORDINATES_OUT_OF_RANGE); + goto err; + } + + if (!EC_KEY_set_public_key(key, point)) { + goto err; + } + + if (EC_KEY_check_key(key) == 0) { + goto err; + } + + ok = 1; + +err: + BN_CTX_end(ctx); + BN_CTX_free(ctx); + EC_POINT_free(point); + return ok; +} + +int EC_KEY_generate_key(EC_KEY *eckey) { + int ok = 0; + BIGNUM *priv_key = NULL; + EC_POINT *pub_key = NULL; + + if (!eckey || !eckey->group) { + OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (eckey->priv_key == NULL) { + priv_key = BN_new(); + if (priv_key == NULL) { + goto err; + } + } else { + priv_key = eckey->priv_key; + } + + const BIGNUM *order = EC_GROUP_get0_order(eckey->group); + do { + if (!BN_rand_range(priv_key, order)) { + goto err; + } + } while (BN_is_zero(priv_key)); + + if (eckey->pub_key == NULL) { + pub_key = EC_POINT_new(eckey->group); + if (pub_key == NULL) { + goto err; + } + } else { + pub_key = eckey->pub_key; + } + + if (!EC_POINT_mul(eckey->group, pub_key, priv_key, NULL, NULL, NULL)) { + goto err; + } + + eckey->priv_key = priv_key; + eckey->pub_key = pub_key; + + ok = 1; + +err: + if (eckey->pub_key == NULL) { + EC_POINT_free(pub_key); + } + if (eckey->priv_key == NULL) { + BN_free(priv_key); + } + return ok; +} + +int EC_KEY_get_ex_new_index(long argl, void *argp, CRYPTO_EX_unused *unused, + CRYPTO_EX_dup *dup_func, + CRYPTO_EX_free *free_func) { + int index; + if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp, dup_func, + free_func)) { + return -1; + } + return index; +} + +int EC_KEY_set_ex_data(EC_KEY *d, int idx, void *arg) { + return CRYPTO_set_ex_data(&d->ex_data, idx, arg); +} + +void *EC_KEY_get_ex_data(const EC_KEY *d, int idx) { + return CRYPTO_get_ex_data(&d->ex_data, idx); +} + +void EC_KEY_set_asn1_flag(EC_KEY *key, int flag) {} diff --git a/external/boringssl/crypto/ec/ec_montgomery.c b/external/boringssl/crypto/ec/ec_montgomery.c new file mode 100644 index 0000000000..35df365126 --- /dev/null +++ b/external/boringssl/crypto/ec/ec_montgomery.c @@ -0,0 +1,323 @@ +/* Originally written by Bodo Moeller and Nils Larsch for the OpenSSL project. + * ==================================================================== + * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * + * Portions of the attached software ("Contribution") are developed by + * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. + * + * The Contribution is licensed pursuant to the OpenSSL open source + * license provided above. + * + * The elliptic curve binary polynomial software is originally written by + * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems + * Laboratories. */ + +#include + +#include +#include +#include + +#include "internal.h" + + +int ec_GFp_mont_group_init(EC_GROUP *group) { + int ok; + + ok = ec_GFp_simple_group_init(group); + group->mont = NULL; + return ok; +} + +void ec_GFp_mont_group_finish(EC_GROUP *group) { + BN_MONT_CTX_free(group->mont); + group->mont = NULL; + ec_GFp_simple_group_finish(group); +} + +int ec_GFp_mont_group_copy(EC_GROUP *dest, const EC_GROUP *src) { + BN_MONT_CTX_free(dest->mont); + dest->mont = NULL; + + if (!ec_GFp_simple_group_copy(dest, src)) { + return 0; + } + + if (src->mont != NULL) { + dest->mont = BN_MONT_CTX_new(); + if (dest->mont == NULL) { + return 0; + } + if (!BN_MONT_CTX_copy(dest->mont, src->mont)) { + goto err; + } + } + + return 1; + +err: + BN_MONT_CTX_free(dest->mont); + dest->mont = NULL; + return 0; +} + +int ec_GFp_mont_group_set_curve(EC_GROUP *group, const BIGNUM *p, + const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) { + BN_CTX *new_ctx = NULL; + BN_MONT_CTX *mont = NULL; + int ret = 0; + + BN_MONT_CTX_free(group->mont); + group->mont = NULL; + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) { + return 0; + } + } + + mont = BN_MONT_CTX_new(); + if (mont == NULL) { + goto err; + } + if (!BN_MONT_CTX_set(mont, p, ctx)) { + OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); + goto err; + } + + group->mont = mont; + mont = NULL; + + ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx); + + if (!ret) { + BN_MONT_CTX_free(group->mont); + group->mont = NULL; + } + +err: + BN_CTX_free(new_ctx); + BN_MONT_CTX_free(mont); + return ret; +} + +int ec_GFp_mont_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, + const BIGNUM *b, BN_CTX *ctx) { + if (group->mont == NULL) { + OPENSSL_PUT_ERROR(EC, EC_R_NOT_INITIALIZED); + return 0; + } + + return BN_mod_mul_montgomery(r, a, b, group->mont, ctx); +} + +int ec_GFp_mont_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, + BN_CTX *ctx) { + if (group->mont == NULL) { + OPENSSL_PUT_ERROR(EC, EC_R_NOT_INITIALIZED); + return 0; + } + + return BN_mod_mul_montgomery(r, a, a, group->mont, ctx); +} + +int ec_GFp_mont_field_encode(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, + BN_CTX *ctx) { + if (group->mont == NULL) { + OPENSSL_PUT_ERROR(EC, EC_R_NOT_INITIALIZED); + return 0; + } + + return BN_to_montgomery(r, a, group->mont, ctx); +} + +int ec_GFp_mont_field_decode(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, + BN_CTX *ctx) { + if (group->mont == NULL) { + OPENSSL_PUT_ERROR(EC, EC_R_NOT_INITIALIZED); + return 0; + } + + return BN_from_montgomery(r, a, group->mont, ctx); +} + +static int ec_GFp_mont_check_pub_key_order(const EC_GROUP *group, + const EC_POINT* pub_key, + BN_CTX *ctx) { + EC_POINT *point = EC_POINT_new(group); + int ret = 0; + + if (point == NULL || + !ec_wNAF_mul(group, point, NULL, pub_key, EC_GROUP_get0_order(group), + ctx) || + !EC_POINT_is_at_infinity(group, point)) { + goto err; + } + + ret = 1; + +err: + EC_POINT_free(point); + return ret; +} + +static int ec_GFp_mont_point_get_affine_coordinates(const EC_GROUP *group, + const EC_POINT *point, + BIGNUM *x, BIGNUM *y, + BN_CTX *ctx) { + if (EC_POINT_is_at_infinity(group, point)) { + OPENSSL_PUT_ERROR(EC, EC_R_POINT_AT_INFINITY); + return 0; + } + + BN_CTX *new_ctx = NULL; + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) { + return 0; + } + } + + int ret = 0; + + BN_CTX_start(ctx); + + if (BN_cmp(&point->Z, &group->one) == 0) { + /* |point| is already affine. */ + if (x != NULL && !BN_from_montgomery(x, &point->X, group->mont, ctx)) { + goto err; + } + if (y != NULL && !BN_from_montgomery(y, &point->Y, group->mont, ctx)) { + goto err; + } + } else { + /* transform (X, Y, Z) into (x, y) := (X/Z^2, Y/Z^3) */ + + BIGNUM *Z_1 = BN_CTX_get(ctx); + BIGNUM *Z_2 = BN_CTX_get(ctx); + BIGNUM *Z_3 = BN_CTX_get(ctx); + if (Z_1 == NULL || + Z_2 == NULL || + Z_3 == NULL) { + goto err; + } + + /* The straightforward way to calculate the inverse of a Montgomery-encoded + * value where the result is Montgomery-encoded is: + * + * |BN_from_montgomery| + |BN_mod_inverse| + |BN_to_montgomery|. + * + * This is equivalent, but more efficient, because |BN_from_montgomery| + * is more efficient (at least in theory) than |BN_to_montgomery|, since it + * doesn't have to do the multiplication before the reduction. */ + if (!BN_from_montgomery(Z_1, &point->Z, group->mont, ctx) || + !BN_from_montgomery(Z_1, Z_1, group->mont, ctx) || + !BN_mod_inverse(Z_1, Z_1, &group->field, ctx)) { + goto err; + } + + if (!BN_mod_mul_montgomery(Z_2, Z_1, Z_1, group->mont, ctx)) { + goto err; + } + + /* Instead of using |BN_from_montgomery| to convert the |x| coordinate + * and then calling |BN_from_montgomery| again to convert the |y| + * coordinate below, convert the common factor |Z_2| once now, saving one + * reduction. */ + if (!BN_from_montgomery(Z_2, Z_2, group->mont, ctx)) { + goto err; + } + + if (x != NULL) { + if (!BN_mod_mul_montgomery(x, &point->X, Z_2, group->mont, ctx)) { + goto err; + } + } + + if (y != NULL) { + if (!BN_mod_mul_montgomery(Z_3, Z_2, Z_1, group->mont, ctx) || + !BN_mod_mul_montgomery(y, &point->Y, Z_3, group->mont, ctx)) { + goto err; + } + } + } + + ret = 1; + +err: + BN_CTX_end(ctx); + BN_CTX_free(new_ctx); + return ret; +} + +const EC_METHOD *EC_GFp_mont_method(void) { + static const EC_METHOD ret = { + ec_GFp_mont_group_init, + ec_GFp_mont_group_finish, + ec_GFp_mont_group_copy, + ec_GFp_mont_group_set_curve, + ec_GFp_mont_point_get_affine_coordinates, + ec_wNAF_mul /* XXX: Not constant time. */, + ec_GFp_mont_check_pub_key_order, + ec_GFp_mont_field_mul, + ec_GFp_mont_field_sqr, + ec_GFp_mont_field_encode, + ec_GFp_mont_field_decode, + }; + + return &ret; +} diff --git a/external/boringssl/crypto/ec/ec_test.cc b/external/boringssl/crypto/ec/ec_test.cc new file mode 100644 index 0000000000..ce9d99f3b4 --- /dev/null +++ b/external/boringssl/crypto/ec/ec_test.cc @@ -0,0 +1,520 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include "../test/scoped_types.h" + + +// kECKeyWithoutPublic is an ECPrivateKey with the optional publicKey field +// omitted. +static const uint8_t kECKeyWithoutPublic[] = { + 0x30, 0x31, 0x02, 0x01, 0x01, 0x04, 0x20, 0xc6, 0xc1, 0xaa, 0xda, 0x15, 0xb0, + 0x76, 0x61, 0xf8, 0x14, 0x2c, 0x6c, 0xaf, 0x0f, 0xdb, 0x24, 0x1a, 0xff, 0x2e, + 0xfe, 0x46, 0xc0, 0x93, 0x8b, 0x74, 0xf2, 0xbc, 0xc5, 0x30, 0x52, 0xb0, 0x77, + 0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, +}; + +// kECKeySpecifiedCurve is the above key with P-256's parameters explicitly +// spelled out rather than using a named curve. +static const uint8_t kECKeySpecifiedCurve[] = { + 0x30, 0x82, 0x01, 0x22, 0x02, 0x01, 0x01, 0x04, 0x20, 0xc6, 0xc1, 0xaa, + 0xda, 0x15, 0xb0, 0x76, 0x61, 0xf8, 0x14, 0x2c, 0x6c, 0xaf, 0x0f, 0xdb, + 0x24, 0x1a, 0xff, 0x2e, 0xfe, 0x46, 0xc0, 0x93, 0x8b, 0x74, 0xf2, 0xbc, + 0xc5, 0x30, 0x52, 0xb0, 0x77, 0xa0, 0x81, 0xfa, 0x30, 0x81, 0xf7, 0x02, + 0x01, 0x01, 0x30, 0x2c, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01, + 0x01, 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x30, 0x5b, 0x04, 0x20, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, + 0x04, 0x20, 0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, 0xb3, 0xeb, + 0xbd, 0x55, 0x76, 0x98, 0x86, 0xbc, 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53, + 0xb0, 0xf6, 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b, 0x03, 0x15, + 0x00, 0xc4, 0x9d, 0x36, 0x08, 0x86, 0xe7, 0x04, 0x93, 0x6a, 0x66, 0x78, + 0xe1, 0x13, 0x9d, 0x26, 0xb7, 0x81, 0x9f, 0x7e, 0x90, 0x04, 0x41, 0x04, + 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6, 0xe5, + 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb, 0x33, 0xa0, + 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96, 0x4f, 0xe3, 0x42, 0xe2, + 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16, + 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, + 0x37, 0xbf, 0x51, 0xf5, 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbc, + 0xe6, 0xfa, 0xad, 0xa7, 0x17, 0x9e, 0x84, 0xf3, 0xb9, 0xca, 0xc2, 0xfc, + 0x63, 0x25, 0x51, 0x02, 0x01, 0x01, +}; + +// kECKeyMissingZeros is an ECPrivateKey containing a degenerate P-256 key where +// the private key is one. The private key is incorrectly encoded without zero +// padding. +static const uint8_t kECKeyMissingZeros[] = { + 0x30, 0x58, 0x02, 0x01, 0x01, 0x04, 0x01, 0x01, 0xa0, 0x0a, 0x06, 0x08, 0x2a, + 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04, + 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6, 0xe5, 0x63, + 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb, 0x33, 0xa0, 0xf4, 0xa1, + 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96, 0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, + 0x9b, 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57, + 0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5, +}; + +// kECKeyMissingZeros is an ECPrivateKey containing a degenerate P-256 key where +// the private key is one. The private key is encoded with the required zero +// padding. +static const uint8_t kECKeyWithZeros[] = { + 0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0xa1, + 0x44, 0x03, 0x42, 0x00, 0x04, 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, + 0xf8, 0xbc, 0xe6, 0xe5, 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, + 0xeb, 0x33, 0xa0, 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96, 0x4f, 0xe3, + 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, + 0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, + 0x37, 0xbf, 0x51, 0xf5, +}; + +// DecodeECPrivateKey decodes |in| as an ECPrivateKey structure and returns the +// result or nullptr on error. +static ScopedEC_KEY DecodeECPrivateKey(const uint8_t *in, size_t in_len) { + CBS cbs; + CBS_init(&cbs, in, in_len); + ScopedEC_KEY ret(EC_KEY_parse_private_key(&cbs, NULL)); + if (!ret || CBS_len(&cbs) != 0) { + return nullptr; + } + return ret; +} + +// EncodeECPrivateKey encodes |key| as an ECPrivateKey structure into |*out|. It +// returns true on success or false on error. +static bool EncodeECPrivateKey(std::vector *out, const EC_KEY *key) { + ScopedCBB cbb; + uint8_t *der; + size_t der_len; + if (!CBB_init(cbb.get(), 0) || + !EC_KEY_marshal_private_key(cbb.get(), key, EC_KEY_get_enc_flags(key)) || + !CBB_finish(cbb.get(), &der, &der_len)) { + return false; + } + out->assign(der, der + der_len); + OPENSSL_free(der); + return true; +} + +static bool Testd2i_ECPrivateKey() { + ScopedEC_KEY key = DecodeECPrivateKey(kECKeyWithoutPublic, + sizeof(kECKeyWithoutPublic)); + if (!key) { + fprintf(stderr, "Failed to parse private key.\n"); + ERR_print_errors_fp(stderr); + return false; + } + + std::vector out; + if (!EncodeECPrivateKey(&out, key.get())) { + fprintf(stderr, "Failed to serialize private key.\n"); + ERR_print_errors_fp(stderr); + return false; + } + + if (std::vector(kECKeyWithoutPublic, + kECKeyWithoutPublic + sizeof(kECKeyWithoutPublic)) != + out) { + fprintf(stderr, "Serialisation of key doesn't match original.\n"); + return false; + } + + const EC_POINT *pub_key = EC_KEY_get0_public_key(key.get()); + if (pub_key == NULL) { + fprintf(stderr, "Public key missing.\n"); + return false; + } + + ScopedBIGNUM x(BN_new()); + ScopedBIGNUM y(BN_new()); + if (!x || !y) { + return false; + } + if (!EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(key.get()), + pub_key, x.get(), y.get(), NULL)) { + fprintf(stderr, "Failed to get public key in affine coordinates.\n"); + return false; + } + ScopedOpenSSLString x_hex(BN_bn2hex(x.get())); + ScopedOpenSSLString y_hex(BN_bn2hex(y.get())); + if (!x_hex || !y_hex) { + return false; + } + if (0 != strcmp( + x_hex.get(), + "c81561ecf2e54edefe6617db1c7a34a70744ddb261f269b83dacfcd2ade5a681") || + 0 != strcmp( + y_hex.get(), + "e0e2afa3f9b6abe4c698ef6495f1be49a3196c5056acb3763fe4507eec596e88")) { + fprintf(stderr, "Incorrect public key: %s %s\n", x_hex.get(), y_hex.get()); + return false; + } + + return true; +} + +static bool TestZeroPadding() { + // Check that the correct encoding round-trips. + ScopedEC_KEY key = DecodeECPrivateKey(kECKeyWithZeros, + sizeof(kECKeyWithZeros)); + std::vector out; + if (!key || !EncodeECPrivateKey(&out, key.get())) { + ERR_print_errors_fp(stderr); + return false; + } + + if (std::vector(kECKeyWithZeros, + kECKeyWithZeros + sizeof(kECKeyWithZeros)) != out) { + fprintf(stderr, "Serialisation of key was incorrect.\n"); + return false; + } + + // Keys without leading zeros also parse, but they encode correctly. + key = DecodeECPrivateKey(kECKeyMissingZeros, sizeof(kECKeyMissingZeros)); + if (!key || !EncodeECPrivateKey(&out, key.get())) { + ERR_print_errors_fp(stderr); + return false; + } + + if (std::vector(kECKeyWithZeros, + kECKeyWithZeros + sizeof(kECKeyWithZeros)) != out) { + fprintf(stderr, "Serialisation of key was incorrect.\n"); + return false; + } + + return true; +} + +static bool TestSpecifiedCurve() { + // Test keys with specified curves may be decoded. + ScopedEC_KEY key = + DecodeECPrivateKey(kECKeySpecifiedCurve, sizeof(kECKeySpecifiedCurve)); + if (!key) { + ERR_print_errors_fp(stderr); + return false; + } + + // The group should have been interpreted as P-256. + if (EC_GROUP_get_curve_name(EC_KEY_get0_group(key.get())) != + NID_X9_62_prime256v1) { + fprintf(stderr, "Curve name incorrect.\n"); + return false; + } + + // Encoding the key should still use named form. + std::vector out; + if (!EncodeECPrivateKey(&out, key.get())) { + ERR_print_errors_fp(stderr); + return false; + } + if (std::vector(kECKeyWithoutPublic, + kECKeyWithoutPublic + sizeof(kECKeyWithoutPublic)) != + out) { + fprintf(stderr, "Serialisation of key was incorrect.\n"); + return false; + } + + return true; +} + +static bool TestSetAffine(const int nid) { + ScopedEC_KEY key(EC_KEY_new_by_curve_name(nid)); + if (!key) { + return false; + } + + const EC_GROUP *const group = EC_KEY_get0_group(key.get()); + + if (!EC_KEY_generate_key(key.get())) { + fprintf(stderr, "EC_KEY_generate_key failed with nid %d\n", nid); + ERR_print_errors_fp(stderr); + return false; + } + + if (!EC_POINT_is_on_curve(group, EC_KEY_get0_public_key(key.get()), + nullptr)) { + fprintf(stderr, "generated point is not on curve with nid %d", nid); + ERR_print_errors_fp(stderr); + return false; + } + + ScopedBIGNUM x(BN_new()); + ScopedBIGNUM y(BN_new()); + if (!EC_POINT_get_affine_coordinates_GFp(group, + EC_KEY_get0_public_key(key.get()), + x.get(), y.get(), nullptr)) { + fprintf(stderr, "EC_POINT_get_affine_coordinates_GFp failed with nid %d\n", + nid); + ERR_print_errors_fp(stderr); + return false; + } + + ScopedEC_POINT point(EC_POINT_new(group)); + if (!point) { + return false; + } + + if (!EC_POINT_set_affine_coordinates_GFp(group, point.get(), x.get(), y.get(), + nullptr)) { + fprintf(stderr, "EC_POINT_set_affine_coordinates_GFp failed with nid %d\n", + nid); + ERR_print_errors_fp(stderr); + return false; + } + + // Subtract one from |y| to make the point no longer on the curve. + if (!BN_sub(y.get(), y.get(), BN_value_one())) { + return false; + } + + ScopedEC_POINT invalid_point(EC_POINT_new(group)); + if (!invalid_point) { + return false; + } + + if (EC_POINT_set_affine_coordinates_GFp(group, invalid_point.get(), x.get(), + y.get(), nullptr)) { + fprintf(stderr, + "EC_POINT_set_affine_coordinates_GFp succeeded with invalid " + "coordinates with nid %d\n", + nid); + ERR_print_errors_fp(stderr); + return false; + } + + return true; +} + +static bool TestArbitraryCurve() { + // Make a P-256 key and extract the affine coordinates. + ScopedEC_KEY key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)); + if (!key || !EC_KEY_generate_key(key.get())) { + return false; + } + + // Make an arbitrary curve which is identical to P-256. + static const uint8_t kP[] = { + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + }; + static const uint8_t kA[] = { + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, + }; + static const uint8_t kB[] = { + 0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, 0xb3, 0xeb, 0xbd, + 0x55, 0x76, 0x98, 0x86, 0xbc, 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53, + 0xb0, 0xf6, 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b, + }; + static const uint8_t kX[] = { + 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6, + 0xe5, 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb, + 0x33, 0xa0, 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96, + }; + static const uint8_t kY[] = { + 0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, + 0x4a, 0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, + 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5, + }; + static const uint8_t kOrder[] = { + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xbc, 0xe6, 0xfa, 0xad, 0xa7, 0x17, + 0x9e, 0x84, 0xf3, 0xb9, 0xca, 0xc2, 0xfc, 0x63, 0x25, 0x51, + }; + ScopedBN_CTX ctx(BN_CTX_new()); + ScopedBIGNUM p(BN_bin2bn(kP, sizeof(kP), nullptr)); + ScopedBIGNUM a(BN_bin2bn(kA, sizeof(kA), nullptr)); + ScopedBIGNUM b(BN_bin2bn(kB, sizeof(kB), nullptr)); + ScopedBIGNUM gx(BN_bin2bn(kX, sizeof(kX), nullptr)); + ScopedBIGNUM gy(BN_bin2bn(kY, sizeof(kY), nullptr)); + ScopedBIGNUM order(BN_bin2bn(kOrder, sizeof(kOrder), nullptr)); + ScopedBIGNUM cofactor(BN_new()); + if (!ctx || !p || !a || !b || !gx || !gy || !order || !cofactor || + !BN_set_word(cofactor.get(), 1)) { + return false; + } + + ScopedEC_GROUP group( + EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), ctx.get())); + if (!group) { + return false; + } + ScopedEC_POINT generator(EC_POINT_new(group.get())); + if (!generator || + !EC_POINT_set_affine_coordinates_GFp(group.get(), generator.get(), + gx.get(), gy.get(), ctx.get()) || + !EC_GROUP_set_generator(group.get(), generator.get(), order.get(), + cofactor.get())) { + return false; + } + + // |group| should not have a curve name. + if (EC_GROUP_get_curve_name(group.get()) != NID_undef) { + return false; + } + + // Copy |key| to |key2| using |group|. + ScopedEC_KEY key2(EC_KEY_new()); + ScopedEC_POINT point(EC_POINT_new(group.get())); + ScopedBIGNUM x(BN_new()), y(BN_new()); + if (!key2 || !point || !x || !y || + !EC_KEY_set_group(key2.get(), group.get()) || + !EC_KEY_set_private_key(key2.get(), EC_KEY_get0_private_key(key.get())) || + !EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(key.get()), + EC_KEY_get0_public_key(key.get()), + x.get(), y.get(), nullptr) || + !EC_POINT_set_affine_coordinates_GFp(group.get(), point.get(), x.get(), + y.get(), nullptr) || + !EC_KEY_set_public_key(key2.get(), point.get())) { + fprintf(stderr, "Could not copy key.\n"); + return false; + } + + // The key must be valid according to the new group too. + if (!EC_KEY_check_key(key2.get())) { + fprintf(stderr, "Copied key is not valid.\n"); + return false; + } + + // Repeat the process for |EC_GROUP_new_arbitrary|. + group.reset(EC_GROUP_new_arbitrary(p.get(), a.get(), b.get(), gx.get(), + gy.get(), order.get(), cofactor.get())); + if (!group) { + return false; + } + + // |group| should not have a curve name. + if (EC_GROUP_get_curve_name(group.get()) != NID_undef) { + return false; + } + + // Copy |key| to |key2| using |group|. + key2.reset(EC_KEY_new()); + point.reset(EC_POINT_new(group.get())); + if (!key2 || !point || + !EC_KEY_set_group(key2.get(), group.get()) || + !EC_KEY_set_private_key(key2.get(), EC_KEY_get0_private_key(key.get())) || + !EC_POINT_set_affine_coordinates_GFp(group.get(), point.get(), x.get(), + y.get(), nullptr) || + !EC_KEY_set_public_key(key2.get(), point.get())) { + fprintf(stderr, "Could not copy key.\n"); + return false; + } + + // The key must be valid according to the new group too. + if (!EC_KEY_check_key(key2.get())) { + fprintf(stderr, "Copied key is not valid.\n"); + return false; + } + + return true; +} + +static bool TestAddingEqualPoints(int nid) { + ScopedEC_KEY key(EC_KEY_new_by_curve_name(nid)); + if (!key) { + return false; + } + + const EC_GROUP *const group = EC_KEY_get0_group(key.get()); + + if (!EC_KEY_generate_key(key.get())) { + fprintf(stderr, "EC_KEY_generate_key failed with nid %d\n", nid); + ERR_print_errors_fp(stderr); + return false; + } + + ScopedEC_POINT p1(EC_POINT_new(group)); + ScopedEC_POINT p2(EC_POINT_new(group)); + ScopedEC_POINT double_p1(EC_POINT_new(group)); + ScopedEC_POINT p1_plus_p2(EC_POINT_new(group)); + if (!p1 || !p2 || !double_p1 || !p1_plus_p2) { + return false; + } + + if (!EC_POINT_copy(p1.get(), EC_KEY_get0_public_key(key.get())) || + !EC_POINT_copy(p2.get(), EC_KEY_get0_public_key(key.get()))) { + fprintf(stderr, "EC_POINT_COPY failed with nid %d\n", nid); + ERR_print_errors_fp(stderr); + return false; + } + + ScopedBN_CTX ctx(BN_CTX_new()); + if (!ctx) { + return false; + } + + if (!EC_POINT_dbl(group, double_p1.get(), p1.get(), ctx.get()) || + !EC_POINT_add(group, p1_plus_p2.get(), p1.get(), p2.get(), ctx.get())) { + fprintf(stderr, "Point operation failed with nid %d\n", nid); + ERR_print_errors_fp(stderr); + return false; + } + + if (EC_POINT_cmp(group, double_p1.get(), p1_plus_p2.get(), ctx.get()) != 0) { + fprintf(stderr, "A+A != 2A for nid %d", nid); + return false; + } + + return true; +} + +static bool ForEachCurve(bool (*test_func)(int nid)) { + const size_t num_curves = EC_get_builtin_curves(nullptr, 0); + std::vector curves(num_curves); + EC_get_builtin_curves(curves.data(), num_curves); + + for (const auto& curve : curves) { + if (!test_func(curve.nid)) { + fprintf(stderr, "Test failed for %s\n", curve.comment); + return false; + } + } + + return true; +} + +int main(void) { + CRYPTO_library_init(); + + if (!Testd2i_ECPrivateKey() || + !TestZeroPadding() || + !TestSpecifiedCurve() || + !ForEachCurve(TestSetAffine) || + !ForEachCurve(TestAddingEqualPoints) || + !TestArbitraryCurve()) { + fprintf(stderr, "failed\n"); + return 1; + } + + printf("PASS\n"); + return 0; +} diff --git a/external/boringssl/crypto/ec/example_mul.c b/external/boringssl/crypto/ec/example_mul.c new file mode 100644 index 0000000000..a2bdd5277e --- /dev/null +++ b/external/boringssl/crypto/ec/example_mul.c @@ -0,0 +1,133 @@ +/* Originally written by Bodo Moeller for the OpenSSL project. + * ==================================================================== + * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * + * Portions of the attached software ("Contribution") are developed by + * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. + * + * The Contribution is licensed pursuant to the OpenSSL open source + * license provided above. + * + * The elliptic curve binary polynomial software is originally written by + * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems + * Laboratories. */ + +#include + +#include +#include +#include +#include + + +static int example_EC_POINT_mul(void) { + /* This example ensures that 10×∞ + G = G, in P-256. */ + EC_GROUP *group = NULL; + EC_POINT *p = NULL, *result = NULL; + BIGNUM *n = NULL; + int ret = 0; + const EC_POINT *generator; + + group = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1); + p = EC_POINT_new(group); + result = EC_POINT_new(group); + n = BN_new(); + + if (p == NULL || + result == NULL || + group == NULL || + n == NULL || + !EC_POINT_set_to_infinity(group, p) || + !BN_set_word(n, 10)) { + goto err; + } + + /* First check that 10×∞ = ∞. */ + if (!EC_POINT_mul(group, result, NULL, p, n, NULL) || + !EC_POINT_is_at_infinity(group, result)) { + goto err; + } + + generator = EC_GROUP_get0_generator(group); + + /* Now check that 10×∞ + G = G. */ + if (!EC_POINT_mul(group, result, BN_value_one(), p, n, NULL) || + EC_POINT_cmp(group, result, generator, NULL) != 0) { + goto err; + } + + ret = 1; + +err: + BN_free(n); + EC_POINT_free(result); + EC_POINT_free(p); + EC_GROUP_free(group); + + return ret; +} + +int main(void) { + CRYPTO_library_init(); + + if (!example_EC_POINT_mul()) { + fprintf(stderr, "failed\n"); + return 1; + } + + printf("PASS\n"); + return 0; +} diff --git a/external/boringssl/crypto/ec/internal.h b/external/boringssl/crypto/ec/internal.h new file mode 100644 index 0000000000..f2cbb96191 --- /dev/null +++ b/external/boringssl/crypto/ec/internal.h @@ -0,0 +1,288 @@ +/* Originally written by Bodo Moeller for the OpenSSL project. + * ==================================================================== + * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * + * Portions of the attached software ("Contribution") are developed by + * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. + * + * The Contribution is licensed pursuant to the OpenSSL open source + * license provided above. + * + * The elliptic curve binary polynomial software is originally written by + * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems + * Laboratories. */ + +#ifndef OPENSSL_HEADER_EC_INTERNAL_H +#define OPENSSL_HEADER_EC_INTERNAL_H + +#include + +#include +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +struct ec_method_st { + int (*group_init)(EC_GROUP *); + void (*group_finish)(EC_GROUP *); + int (*group_copy)(EC_GROUP *, const EC_GROUP *); + int (*group_set_curve)(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, + const BIGNUM *b, BN_CTX *); + int (*point_get_affine_coordinates)(const EC_GROUP *, const EC_POINT *, + BIGNUM *x, BIGNUM *y, BN_CTX *); + + /* Computes |r = g_scalar*generator + p_scalar*p| if |g_scalar| and |p_scalar| + * are both non-null. Computes |r = g_scalar*generator| if |p_scalar| is null. + * Computes |r = p_scalar*p| if g_scalar is null. At least one of |g_scalar| + * and |p_scalar| must be non-null, and |p| must be non-null if |p_scalar| is + * non-null. */ + int (*mul)(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar, + const EC_POINT *p, const BIGNUM *p_scalar, BN_CTX *ctx); + + /* |check_pub_key_order| checks that the public key is in the proper subgroup + * by checking that |pub_key*group->order| is the point at infinity. This may + * be NULL for |EC_METHOD|s specialized for prime-order curves (i.e. with + * cofactor one), as this check is not necessary for such curves (See section + * A.3 of the NSA's "Suite B Implementer's Guide to FIPS 186-3 + * (ECDSA)"). */ + int (*check_pub_key_order)(const EC_GROUP *group, const EC_POINT *pub_key, + BN_CTX *ctx); + + /* 'field_mul' and 'field_sqr' can be used by 'add' and 'dbl' so that the + * same implementations of point operations can be used with different + * optimized implementations of expensive field operations: */ + int (*field_mul)(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + const BIGNUM *b, BN_CTX *); + int (*field_sqr)(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *); + + int (*field_encode)(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + BN_CTX *); /* e.g. to Montgomery */ + int (*field_decode)(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + BN_CTX *); /* e.g. from Montgomery */ +} /* EC_METHOD */; + +const EC_METHOD* EC_GFp_mont_method(void); + +struct ec_group_st { + const EC_METHOD *meth; + + EC_POINT *generator; + BIGNUM order, cofactor; + + int curve_name; /* optional NID for named curve */ + + const BN_MONT_CTX *mont_data; /* data for ECDSA inverse */ + + /* The following members are handled by the method functions, + * even if they appear generic */ + + BIGNUM field; /* For curves over GF(p), this is the modulus. */ + + BIGNUM a, b; /* Curve coefficients. */ + + int a_is_minus3; /* enable optimized point arithmetics for special case */ + + BN_MONT_CTX *mont; /* Montgomery structure. */ + + BIGNUM one; /* The value one. */ +} /* EC_GROUP */; + +struct ec_point_st { + const EC_METHOD *meth; + + BIGNUM X; + BIGNUM Y; + BIGNUM Z; /* Jacobian projective coordinates: + * (X, Y, Z) represents (X/Z^2, Y/Z^3) if Z != 0 */ +} /* EC_POINT */; + +EC_GROUP *ec_group_new(const EC_METHOD *meth); +int ec_group_copy(EC_GROUP *dest, const EC_GROUP *src); + +/* ec_group_get_mont_data returns a Montgomery context for operations in the + * scalar field of |group|. It may return NULL in the case that |group| is not + * a built-in group. */ +const BN_MONT_CTX *ec_group_get_mont_data(const EC_GROUP *group); + +int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar, + const EC_POINT *p, const BIGNUM *p_scalar, BN_CTX *ctx); + +/* method functions in simple.c */ +int ec_GFp_simple_group_init(EC_GROUP *); +void ec_GFp_simple_group_finish(EC_GROUP *); +int ec_GFp_simple_group_copy(EC_GROUP *, const EC_GROUP *); +int ec_GFp_simple_group_set_curve(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, + const BIGNUM *b, BN_CTX *); +int ec_GFp_simple_group_get_curve(const EC_GROUP *, BIGNUM *p, BIGNUM *a, + BIGNUM *b, BN_CTX *); +unsigned ec_GFp_simple_group_get_degree(const EC_GROUP *); +int ec_GFp_simple_point_init(EC_POINT *); +void ec_GFp_simple_point_finish(EC_POINT *); +void ec_GFp_simple_point_clear_finish(EC_POINT *); +int ec_GFp_simple_point_copy(EC_POINT *, const EC_POINT *); +int ec_GFp_simple_point_set_to_infinity(const EC_GROUP *, EC_POINT *); +int ec_GFp_simple_set_Jprojective_coordinates_GFp(const EC_GROUP *, EC_POINT *, + const BIGNUM *x, + const BIGNUM *y, + const BIGNUM *z, BN_CTX *); +int ec_GFp_simple_get_Jprojective_coordinates_GFp(const EC_GROUP *, + const EC_POINT *, BIGNUM *x, + BIGNUM *y, BIGNUM *z, + BN_CTX *); +int ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP *, EC_POINT *, + const BIGNUM *x, const BIGNUM *y, + BN_CTX *); +int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *, EC_POINT *, + const BIGNUM *x, int y_bit, + BN_CTX *); +int ec_GFp_simple_add(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, + const EC_POINT *b, BN_CTX *); +int ec_GFp_simple_dbl(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, + BN_CTX *); +int ec_GFp_simple_invert(const EC_GROUP *, EC_POINT *, BN_CTX *); +int ec_GFp_simple_is_at_infinity(const EC_GROUP *, const EC_POINT *); +int ec_GFp_simple_is_on_curve(const EC_GROUP *, const EC_POINT *, BN_CTX *); +int ec_GFp_simple_cmp(const EC_GROUP *, const EC_POINT *a, const EC_POINT *b, + BN_CTX *); +int ec_GFp_simple_make_affine(const EC_GROUP *, EC_POINT *, BN_CTX *); +int ec_GFp_simple_points_make_affine(const EC_GROUP *, size_t num, + EC_POINT * [], BN_CTX *); +int ec_GFp_simple_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + const BIGNUM *b, BN_CTX *); +int ec_GFp_simple_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + BN_CTX *); + +/* method functions in montgomery.c */ +int ec_GFp_mont_group_init(EC_GROUP *); +int ec_GFp_mont_group_set_curve(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, + const BIGNUM *b, BN_CTX *); +void ec_GFp_mont_group_finish(EC_GROUP *); +int ec_GFp_mont_group_copy(EC_GROUP *, const EC_GROUP *); +int ec_GFp_mont_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + const BIGNUM *b, BN_CTX *); +int ec_GFp_mont_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + BN_CTX *); +int ec_GFp_mont_field_encode(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + BN_CTX *); +int ec_GFp_mont_field_decode(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + BN_CTX *); + +int ec_point_set_Jprojective_coordinates_GFp(const EC_GROUP *group, + EC_POINT *point, const BIGNUM *x, + const BIGNUM *y, const BIGNUM *z, + BN_CTX *ctx); + +void ec_GFp_nistp_recode_scalar_bits(uint8_t *sign, uint8_t *digit, uint8_t in); + +const EC_METHOD *EC_GFp_nistp224_method(void); +const EC_METHOD *EC_GFp_nistp256_method(void); + +/* Returns GFp methods using montgomery multiplication, with x86-64 + * optimized P256. See http://eprint.iacr.org/2013/816. */ +const EC_METHOD *EC_GFp_nistz256_method(void); + +struct ec_key_st { + EC_GROUP *group; + + EC_POINT *pub_key; + BIGNUM *priv_key; + + unsigned int enc_flag; + point_conversion_form_t conv_form; + + CRYPTO_refcount_t references; + + ECDSA_METHOD *ecdsa_meth; + + CRYPTO_EX_DATA ex_data; +} /* EC_KEY */; + +/* curve_data contains data about a built-in elliptic curve. */ +struct curve_data { + /* comment is a human-readable string describing the curve. */ + const char *comment; + /* param_len is the number of bytes needed to store a field element. */ + uint8_t param_len; + /* cofactor is the cofactor of the group (i.e. the number of elements in the + * group divided by the size of the main subgroup. */ + uint8_t cofactor; /* promoted to BN_ULONG */ + /* data points to an array of 6*|param_len| bytes which hold the field + * elements of the following (in big-endian order): prime, a, b, generator x, + * generator y, order. */ + const uint8_t data[]; +}; + +struct built_in_curve { + int nid; + uint8_t oid[8]; + uint8_t oid_len; + const struct curve_data *data; + const EC_METHOD *(*method)(void); +}; + +/* OPENSSL_built_in_curves is terminated with an entry where |nid| is + * |NID_undef|. */ +extern const struct built_in_curve OPENSSL_built_in_curves[]; + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_EC_INTERNAL_H */ diff --git a/external/boringssl/crypto/ec/oct.c b/external/boringssl/crypto/ec/oct.c new file mode 100644 index 0000000000..bf1957cade --- /dev/null +++ b/external/boringssl/crypto/ec/oct.c @@ -0,0 +1,428 @@ +/* Originally written by Bodo Moeller for the OpenSSL project. + * ==================================================================== + * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * + * Portions of the attached software ("Contribution") are developed by + * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. + * + * The Contribution is licensed pursuant to the OpenSSL open source + * license provided above. + * + * The elliptic curve binary polynomial software is originally written by + * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems + * Laboratories. */ + +#include + +#include +#include +#include + +#include "internal.h" + + +static size_t ec_GFp_simple_point2oct(const EC_GROUP *group, + const EC_POINT *point, + point_conversion_form_t form, + uint8_t *buf, size_t len, BN_CTX *ctx) { + size_t ret; + BN_CTX *new_ctx = NULL; + int used_ctx = 0; + BIGNUM *x, *y; + size_t field_len, i; + + if ((form != POINT_CONVERSION_COMPRESSED) && + (form != POINT_CONVERSION_UNCOMPRESSED)) { + OPENSSL_PUT_ERROR(EC, EC_R_INVALID_FORM); + goto err; + } + + if (EC_POINT_is_at_infinity(group, point)) { + OPENSSL_PUT_ERROR(EC, EC_R_POINT_AT_INFINITY); + goto err; + } + + /* ret := required output buffer length */ + field_len = BN_num_bytes(&group->field); + ret = + (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2 * field_len; + + /* if 'buf' is NULL, just return required length */ + if (buf != NULL) { + if (len < ret) { + OPENSSL_PUT_ERROR(EC, EC_R_BUFFER_TOO_SMALL); + goto err; + } + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) { + goto err; + } + } + + BN_CTX_start(ctx); + used_ctx = 1; + x = BN_CTX_get(ctx); + y = BN_CTX_get(ctx); + if (y == NULL) { + goto err; + } + + if (!EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx)) { + goto err; + } + + if ((form == POINT_CONVERSION_COMPRESSED) && + BN_is_odd(y)) { + buf[0] = form + 1; + } else { + buf[0] = form; + } + i = 1; + + if (!BN_bn2bin_padded(buf + i, field_len, x)) { + OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR); + goto err; + } + i += field_len; + + if (form == POINT_CONVERSION_UNCOMPRESSED) { + if (!BN_bn2bin_padded(buf + i, field_len, y)) { + OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR); + goto err; + } + i += field_len; + } + + if (i != ret) { + OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR); + goto err; + } + } + + if (used_ctx) { + BN_CTX_end(ctx); + } + BN_CTX_free(new_ctx); + return ret; + +err: + if (used_ctx) { + BN_CTX_end(ctx); + } + BN_CTX_free(new_ctx); + return 0; +} + + +static int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point, + const uint8_t *buf, size_t len, + BN_CTX *ctx) { + point_conversion_form_t form; + int y_bit; + BN_CTX *new_ctx = NULL; + BIGNUM *x, *y; + size_t field_len, enc_len; + int ret = 0; + + if (len == 0) { + OPENSSL_PUT_ERROR(EC, EC_R_BUFFER_TOO_SMALL); + return 0; + } + form = buf[0]; + y_bit = form & 1; + form = form & ~1U; + if ((form != POINT_CONVERSION_COMPRESSED && + form != POINT_CONVERSION_UNCOMPRESSED) || + (form == POINT_CONVERSION_UNCOMPRESSED && y_bit)) { + OPENSSL_PUT_ERROR(EC, EC_R_INVALID_ENCODING); + return 0; + } + + field_len = BN_num_bytes(&group->field); + enc_len = + (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2 * field_len; + + if (len != enc_len) { + OPENSSL_PUT_ERROR(EC, EC_R_INVALID_ENCODING); + return 0; + } + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) { + return 0; + } + } + + BN_CTX_start(ctx); + x = BN_CTX_get(ctx); + y = BN_CTX_get(ctx); + if (x == NULL || y == NULL) { + goto err; + } + + if (!BN_bin2bn(buf + 1, field_len, x)) { + goto err; + } + if (BN_ucmp(x, &group->field) >= 0) { + OPENSSL_PUT_ERROR(EC, EC_R_INVALID_ENCODING); + goto err; + } + + if (form == POINT_CONVERSION_COMPRESSED) { + if (!EC_POINT_set_compressed_coordinates_GFp(group, point, x, y_bit, ctx)) { + goto err; + } + } else { + if (!BN_bin2bn(buf + 1 + field_len, field_len, y)) { + goto err; + } + if (BN_ucmp(y, &group->field) >= 0) { + OPENSSL_PUT_ERROR(EC, EC_R_INVALID_ENCODING); + goto err; + } + + if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) { + goto err; + } + } + + ret = 1; + +err: + BN_CTX_end(ctx); + BN_CTX_free(new_ctx); + return ret; +} + +int EC_POINT_oct2point(const EC_GROUP *group, EC_POINT *point, + const uint8_t *buf, size_t len, BN_CTX *ctx) { + if (group->meth != point->meth) { + OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + return ec_GFp_simple_oct2point(group, point, buf, len, ctx); +} + +size_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *point, + point_conversion_form_t form, uint8_t *buf, + size_t len, BN_CTX *ctx) { + if (group->meth != point->meth) { + OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + return ec_GFp_simple_point2oct(group, point, form, buf, len, ctx); +} + +int EC_POINT_point2cbb(CBB *out, const EC_GROUP *group, const EC_POINT *point, + point_conversion_form_t form, BN_CTX *ctx) { + size_t len = EC_POINT_point2oct(group, point, form, NULL, 0, ctx); + if (len == 0) { + return 0; + } + uint8_t *p; + return CBB_add_space(out, &p, len) && + EC_POINT_point2oct(group, point, form, p, len, ctx) == len; +} + +int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group, + EC_POINT *point, const BIGNUM *x, + int y_bit, BN_CTX *ctx) { + if (BN_is_negative(x) || BN_cmp(x, &group->field) >= 0) { + OPENSSL_PUT_ERROR(EC, EC_R_INVALID_COMPRESSION_BIT); + return 0; + } + + BN_CTX *new_ctx = NULL; + BIGNUM *tmp1, *tmp2, *y; + int ret = 0; + + ERR_clear_error(); + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) { + return 0; + } + } + + y_bit = (y_bit != 0); + + BN_CTX_start(ctx); + tmp1 = BN_CTX_get(ctx); + tmp2 = BN_CTX_get(ctx); + y = BN_CTX_get(ctx); + if (y == NULL) { + goto err; + } + + /* Recover y. We have a Weierstrass equation + * y^2 = x^3 + a*x + b, + * so y is one of the square roots of x^3 + a*x + b. */ + + /* tmp1 := x^3 */ + if (group->meth->field_decode == 0) { + /* field_{sqr,mul} work on standard representation */ + if (!group->meth->field_sqr(group, tmp2, x, ctx) || + !group->meth->field_mul(group, tmp1, tmp2, x, ctx)) { + goto err; + } + } else { + if (!BN_mod_sqr(tmp2, x, &group->field, ctx) || + !BN_mod_mul(tmp1, tmp2, x, &group->field, ctx)) { + goto err; + } + } + + /* tmp1 := tmp1 + a*x */ + if (group->a_is_minus3) { + if (!BN_mod_lshift1_quick(tmp2, x, &group->field) || + !BN_mod_add_quick(tmp2, tmp2, x, &group->field) || + !BN_mod_sub_quick(tmp1, tmp1, tmp2, &group->field)) { + goto err; + } + } else { + if (group->meth->field_decode) { + if (!group->meth->field_decode(group, tmp2, &group->a, ctx) || + !BN_mod_mul(tmp2, tmp2, x, &group->field, ctx)) { + goto err; + } + } else { + /* field_mul works on standard representation */ + if (!group->meth->field_mul(group, tmp2, &group->a, x, ctx)) { + goto err; + } + } + + if (!BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field)) { + goto err; + } + } + + /* tmp1 := tmp1 + b */ + if (group->meth->field_decode) { + if (!group->meth->field_decode(group, tmp2, &group->b, ctx) || + !BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field)) { + goto err; + } + } else { + if (!BN_mod_add_quick(tmp1, tmp1, &group->b, &group->field)) { + goto err; + } + } + + if (!BN_mod_sqrt(y, tmp1, &group->field, ctx)) { + unsigned long err = ERR_peek_last_error(); + + if (ERR_GET_LIB(err) == ERR_LIB_BN && + ERR_GET_REASON(err) == BN_R_NOT_A_SQUARE) { + ERR_clear_error(); + OPENSSL_PUT_ERROR(EC, EC_R_INVALID_COMPRESSED_POINT); + } else { + OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); + } + goto err; + } + + if (y_bit != BN_is_odd(y)) { + if (BN_is_zero(y)) { + int kron; + + kron = BN_kronecker(x, &group->field, ctx); + if (kron == -2) { + goto err; + } + + if (kron == 1) { + OPENSSL_PUT_ERROR(EC, EC_R_INVALID_COMPRESSION_BIT); + } else { + /* BN_mod_sqrt() should have cought this error (not a square) */ + OPENSSL_PUT_ERROR(EC, EC_R_INVALID_COMPRESSED_POINT); + } + goto err; + } + if (!BN_usub(y, &group->field, y)) { + goto err; + } + } + if (y_bit != BN_is_odd(y)) { + OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR); + goto err; + } + + if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) { + goto err; + } + + ret = 1; + +err: + BN_CTX_end(ctx); + BN_CTX_free(new_ctx); + return ret; +} + +int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group, + EC_POINT *point, const BIGNUM *x, + int y_bit, BN_CTX *ctx) { + if (group->meth != point->meth) { + OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + return ec_GFp_simple_set_compressed_coordinates(group, point, x, y_bit, ctx); +} diff --git a/external/boringssl/crypto/ec/p224-64.c b/external/boringssl/crypto/ec/p224-64.c new file mode 100644 index 0000000000..7bf889c969 --- /dev/null +++ b/external/boringssl/crypto/ec/p224-64.c @@ -0,0 +1,1198 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +/* A 64-bit implementation of the NIST P-224 elliptic curve point multiplication + * + * Inspired by Daniel J. Bernstein's public domain nistp224 implementation + * and Adam Langley's public domain 64-bit C implementation of curve25519. */ + +#include + +#if defined(OPENSSL_64_BIT) && !defined(OPENSSL_WINDOWS) && \ + !defined(OPENSSL_SMALL) + +#include +#include +#include +#include + +#include + +#include "internal.h" +#include "../internal.h" + + +typedef uint8_t u8; +typedef uint64_t u64; +typedef int64_t s64; + +/* Field elements are represented as a_0 + 2^56*a_1 + 2^112*a_2 + 2^168*a_3 + * using 64-bit coefficients called 'limbs', and sometimes (for multiplication + * results) as b_0 + 2^56*b_1 + 2^112*b_2 + 2^168*b_3 + 2^224*b_4 + 2^280*b_5 + + * 2^336*b_6 using 128-bit coefficients called 'widelimbs'. A 4-limb + * representation is an 'felem'; a 7-widelimb representation is a 'widefelem'. + * Even within felems, bits of adjacent limbs overlap, and we don't always + * reduce the representations: we ensure that inputs to each felem + * multiplication satisfy a_i < 2^60, so outputs satisfy b_i < 4*2^60*2^60, and + * fit into a 128-bit word without overflow. The coefficients are then again + * partially reduced to obtain an felem satisfying a_i < 2^57. We only reduce + * to the unique minimal representation at the end of the computation. */ + +typedef uint64_t limb; +typedef uint128_t widelimb; + +typedef limb felem[4]; +typedef widelimb widefelem[7]; + +/* Field element represented as a byte arrary. 28*8 = 224 bits is also the + * group order size for the elliptic curve, and we also use this type for + * scalars for point multiplication. */ +typedef u8 felem_bytearray[28]; + +/* Precomputed multiples of the standard generator + * Points are given in coordinates (X, Y, Z) where Z normally is 1 + * (0 for the point at infinity). + * For each field element, slice a_0 is word 0, etc. + * + * The table has 2 * 16 elements, starting with the following: + * index | bits | point + * ------+---------+------------------------------ + * 0 | 0 0 0 0 | 0G + * 1 | 0 0 0 1 | 1G + * 2 | 0 0 1 0 | 2^56G + * 3 | 0 0 1 1 | (2^56 + 1)G + * 4 | 0 1 0 0 | 2^112G + * 5 | 0 1 0 1 | (2^112 + 1)G + * 6 | 0 1 1 0 | (2^112 + 2^56)G + * 7 | 0 1 1 1 | (2^112 + 2^56 + 1)G + * 8 | 1 0 0 0 | 2^168G + * 9 | 1 0 0 1 | (2^168 + 1)G + * 10 | 1 0 1 0 | (2^168 + 2^56)G + * 11 | 1 0 1 1 | (2^168 + 2^56 + 1)G + * 12 | 1 1 0 0 | (2^168 + 2^112)G + * 13 | 1 1 0 1 | (2^168 + 2^112 + 1)G + * 14 | 1 1 1 0 | (2^168 + 2^112 + 2^56)G + * 15 | 1 1 1 1 | (2^168 + 2^112 + 2^56 + 1)G + * followed by a copy of this with each element multiplied by 2^28. + * + * The reason for this is so that we can clock bits into four different + * locations when doing simple scalar multiplies against the base point, + * and then another four locations using the second 16 elements. */ +static const felem g_pre_comp[2][16][3] = { + {{{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, + {{0x3280d6115c1d21, 0xc1d356c2112234, 0x7f321390b94a03, 0xb70e0cbd6bb4bf}, + {0xd5819985007e34, 0x75a05a07476444, 0xfb4c22dfe6cd43, 0xbd376388b5f723}, + {1, 0, 0, 0}}, + {{0xfd9675666ebbe9, 0xbca7664d40ce5e, 0x2242df8d8a2a43, 0x1f49bbb0f99bc5}, + {0x29e0b892dc9c43, 0xece8608436e662, 0xdc858f185310d0, 0x9812dd4eb8d321}, + {1, 0, 0, 0}}, + {{0x6d3e678d5d8eb8, 0x559eed1cb362f1, 0x16e9a3bbce8a3f, 0xeedcccd8c2a748}, + {0xf19f90ed50266d, 0xabf2b4bf65f9df, 0x313865468fafec, 0x5cb379ba910a17}, + {1, 0, 0, 0}}, + {{0x0641966cab26e3, 0x91fb2991fab0a0, 0xefec27a4e13a0b, 0x0499aa8a5f8ebe}, + {0x7510407766af5d, 0x84d929610d5450, 0x81d77aae82f706, 0x6916f6d4338c5b}, + {1, 0, 0, 0}}, + {{0xea95ac3b1f15c6, 0x086000905e82d4, 0xdd323ae4d1c8b1, 0x932b56be7685a3}, + {0x9ef93dea25dbbf, 0x41665960f390f0, 0xfdec76dbe2a8a7, 0x523e80f019062a}, + {1, 0, 0, 0}}, + {{0x822fdd26732c73, 0xa01c83531b5d0f, 0x363f37347c1ba4, 0xc391b45c84725c}, + {0xbbd5e1b2d6ad24, 0xddfbcde19dfaec, 0xc393da7e222a7f, 0x1efb7890ede244}, + {1, 0, 0, 0}}, + {{0x4c9e90ca217da1, 0xd11beca79159bb, 0xff8d33c2c98b7c, 0x2610b39409f849}, + {0x44d1352ac64da0, 0xcdbb7b2c46b4fb, 0x966c079b753c89, 0xfe67e4e820b112}, + {1, 0, 0, 0}}, + {{0xe28cae2df5312d, 0xc71b61d16f5c6e, 0x79b7619a3e7c4c, 0x05c73240899b47}, + {0x9f7f6382c73e3a, 0x18615165c56bda, 0x641fab2116fd56, 0x72855882b08394}, + {1, 0, 0, 0}}, + {{0x0469182f161c09, 0x74a98ca8d00fb5, 0xb89da93489a3e0, 0x41c98768fb0c1d}, + {0xe5ea05fb32da81, 0x3dce9ffbca6855, 0x1cfe2d3fbf59e6, 0x0e5e03408738a7}, + {1, 0, 0, 0}}, + {{0xdab22b2333e87f, 0x4430137a5dd2f6, 0xe03ab9f738beb8, 0xcb0c5d0dc34f24}, + {0x764a7df0c8fda5, 0x185ba5c3fa2044, 0x9281d688bcbe50, 0xc40331df893881}, + {1, 0, 0, 0}}, + {{0xb89530796f0f60, 0xade92bd26909a3, 0x1a0c83fb4884da, 0x1765bf22a5a984}, + {0x772a9ee75db09e, 0x23bc6c67cec16f, 0x4c1edba8b14e2f, 0xe2a215d9611369}, + {1, 0, 0, 0}}, + {{0x571e509fb5efb3, 0xade88696410552, 0xc8ae85fada74fe, 0x6c7e4be83bbde3}, + {0xff9f51160f4652, 0xb47ce2495a6539, 0xa2946c53b582f4, 0x286d2db3ee9a60}, + {1, 0, 0, 0}}, + {{0x40bbd5081a44af, 0x0995183b13926c, 0xbcefba6f47f6d0, 0x215619e9cc0057}, + {0x8bc94d3b0df45e, 0xf11c54a3694f6f, 0x8631b93cdfe8b5, 0xe7e3f4b0982db9}, + {1, 0, 0, 0}}, + {{0xb17048ab3e1c7b, 0xac38f36ff8a1d8, 0x1c29819435d2c6, 0xc813132f4c07e9}, + {0x2891425503b11f, 0x08781030579fea, 0xf5426ba5cc9674, 0x1e28ebf18562bc}, + {1, 0, 0, 0}}, + {{0x9f31997cc864eb, 0x06cd91d28b5e4c, 0xff17036691a973, 0xf1aef351497c58}, + {0xdd1f2d600564ff, 0xdead073b1402db, 0x74a684435bd693, 0xeea7471f962558}, + {1, 0, 0, 0}}}, + {{{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, + {{0x9665266dddf554, 0x9613d78b60ef2d, 0xce27a34cdba417, 0xd35ab74d6afc31}, + {0x85ccdd22deb15e, 0x2137e5783a6aab, 0xa141cffd8c93c6, 0x355a1830e90f2d}, + {1, 0, 0, 0}}, + {{0x1a494eadaade65, 0xd6da4da77fe53c, 0xe7992996abec86, 0x65c3553c6090e3}, + {0xfa610b1fb09346, 0xf1c6540b8a4aaf, 0xc51a13ccd3cbab, 0x02995b1b18c28a}, + {1, 0, 0, 0}}, + {{0x7874568e7295ef, 0x86b419fbe38d04, 0xdc0690a7550d9a, 0xd3966a44beac33}, + {0x2b7280ec29132f, 0xbeaa3b6a032df3, 0xdc7dd88ae41200, 0xd25e2513e3a100}, + {1, 0, 0, 0}}, + {{0x924857eb2efafd, 0xac2bce41223190, 0x8edaa1445553fc, 0x825800fd3562d5}, + {0x8d79148ea96621, 0x23a01c3dd9ed8d, 0xaf8b219f9416b5, 0xd8db0cc277daea}, + {1, 0, 0, 0}}, + {{0x76a9c3b1a700f0, 0xe9acd29bc7e691, 0x69212d1a6b0327, 0x6322e97fe154be}, + {0x469fc5465d62aa, 0x8d41ed18883b05, 0x1f8eae66c52b88, 0xe4fcbe9325be51}, + {1, 0, 0, 0}}, + {{0x825fdf583cac16, 0x020b857c7b023a, 0x683c17744b0165, 0x14ffd0a2daf2f1}, + {0x323b36184218f9, 0x4944ec4e3b47d4, 0xc15b3080841acf, 0x0bced4b01a28bb}, + {1, 0, 0, 0}}, + {{0x92ac22230df5c4, 0x52f33b4063eda8, 0xcb3f19870c0c93, 0x40064f2ba65233}, + {0xfe16f0924f8992, 0x012da25af5b517, 0x1a57bb24f723a6, 0x06f8bc76760def}, + {1, 0, 0, 0}}, + {{0x4a7084f7817cb9, 0xbcab0738ee9a78, 0x3ec11e11d9c326, 0xdc0fe90e0f1aae}, + {0xcf639ea5f98390, 0x5c350aa22ffb74, 0x9afae98a4047b7, 0x956ec2d617fc45}, + {1, 0, 0, 0}}, + {{0x4306d648c1be6a, 0x9247cd8bc9a462, 0xf5595e377d2f2e, 0xbd1c3caff1a52e}, + {0x045e14472409d0, 0x29f3e17078f773, 0x745a602b2d4f7d, 0x191837685cdfbb}, + {1, 0, 0, 0}}, + {{0x5b6ee254a8cb79, 0x4953433f5e7026, 0xe21faeb1d1def4, 0xc4c225785c09de}, + {0x307ce7bba1e518, 0x31b125b1036db8, 0x47e91868839e8f, 0xc765866e33b9f3}, + {1, 0, 0, 0}}, + {{0x3bfece24f96906, 0x4794da641e5093, 0xde5df64f95db26, 0x297ecd89714b05}, + {0x701bd3ebb2c3aa, 0x7073b4f53cb1d5, 0x13c5665658af16, 0x9895089d66fe58}, + {1, 0, 0, 0}}, + {{0x0fef05f78c4790, 0x2d773633b05d2e, 0x94229c3a951c94, 0xbbbd70df4911bb}, + {0xb2c6963d2c1168, 0x105f47a72b0d73, 0x9fdf6111614080, 0x7b7e94b39e67b0}, + {1, 0, 0, 0}}, + {{0xad1a7d6efbe2b3, 0xf012482c0da69d, 0x6b3bdf12438345, 0x40d7558d7aa4d9}, + {0x8a09fffb5c6d3d, 0x9a356e5d9ffd38, 0x5973f15f4f9b1c, 0xdcd5f59f63c3ea}, + {1, 0, 0, 0}}, + {{0xacf39f4c5ca7ab, 0x4c8071cc5fd737, 0xc64e3602cd1184, 0x0acd4644c9abba}, + {0x6c011a36d8bf6e, 0xfecd87ba24e32a, 0x19f6f56574fad8, 0x050b204ced9405}, + {1, 0, 0, 0}}, + {{0xed4f1cae7d9a96, 0x5ceef7ad94c40a, 0x778e4a3bf3ef9b, 0x7405783dc3b55e}, + {0x32477c61b6e8c6, 0xb46a97570f018b, 0x91176d0a7e95d1, 0x3df90fbc4c7d0e}, + {1, 0, 0, 0}}}}; + +/* Helper functions to convert field elements to/from internal representation */ +static void bin28_to_felem(felem out, const u8 in[28]) { + out[0] = *((const uint64_t *)(in)) & 0x00ffffffffffffff; + out[1] = (*((const uint64_t *)(in + 7))) & 0x00ffffffffffffff; + out[2] = (*((const uint64_t *)(in + 14))) & 0x00ffffffffffffff; + out[3] = (*((const uint64_t *)(in + 20))) >> 8; +} + +static void felem_to_bin28(u8 out[28], const felem in) { + size_t i; + for (i = 0; i < 7; ++i) { + out[i] = in[0] >> (8 * i); + out[i + 7] = in[1] >> (8 * i); + out[i + 14] = in[2] >> (8 * i); + out[i + 21] = in[3] >> (8 * i); + } +} + +/* To preserve endianness when using BN_bn2bin and BN_bin2bn */ +static void flip_endian(u8 *out, const u8 *in, size_t len) { + size_t i; + for (i = 0; i < len; ++i) { + out[i] = in[len - 1 - i]; + } +} + +/* From OpenSSL BIGNUM to internal representation */ +static int BN_to_felem(felem out, const BIGNUM *bn) { + /* BN_bn2bin eats leading zeroes */ + felem_bytearray b_out; + memset(b_out, 0, sizeof(b_out)); + size_t num_bytes = BN_num_bytes(bn); + if (num_bytes > sizeof(b_out) || + BN_is_negative(bn)) { + OPENSSL_PUT_ERROR(EC, EC_R_BIGNUM_OUT_OF_RANGE); + return 0; + } + + felem_bytearray b_in; + num_bytes = BN_bn2bin(bn, b_in); + flip_endian(b_out, b_in, num_bytes); + bin28_to_felem(out, b_out); + return 1; +} + +/* From internal representation to OpenSSL BIGNUM */ +static BIGNUM *felem_to_BN(BIGNUM *out, const felem in) { + felem_bytearray b_in, b_out; + felem_to_bin28(b_in, in); + flip_endian(b_out, b_in, sizeof(b_out)); + return BN_bin2bn(b_out, sizeof(b_out), out); +} + +/* Field operations, using the internal representation of field elements. + * NB! These operations are specific to our point multiplication and cannot be + * expected to be correct in general - e.g., multiplication with a large scalar + * will cause an overflow. */ + +static void felem_assign(felem out, const felem in) { + out[0] = in[0]; + out[1] = in[1]; + out[2] = in[2]; + out[3] = in[3]; +} + +/* Sum two field elements: out += in */ +static void felem_sum(felem out, const felem in) { + out[0] += in[0]; + out[1] += in[1]; + out[2] += in[2]; + out[3] += in[3]; +} + +/* Get negative value: out = -in */ +/* Assumes in[i] < 2^57 */ +static void felem_neg(felem out, const felem in) { + static const limb two58p2 = (((limb)1) << 58) + (((limb)1) << 2); + static const limb two58m2 = (((limb)1) << 58) - (((limb)1) << 2); + static const limb two58m42m2 = + (((limb)1) << 58) - (((limb)1) << 42) - (((limb)1) << 2); + + /* Set to 0 mod 2^224-2^96+1 to ensure out > in */ + out[0] = two58p2 - in[0]; + out[1] = two58m42m2 - in[1]; + out[2] = two58m2 - in[2]; + out[3] = two58m2 - in[3]; +} + +/* Subtract field elements: out -= in */ +/* Assumes in[i] < 2^57 */ +static void felem_diff(felem out, const felem in) { + static const limb two58p2 = (((limb)1) << 58) + (((limb)1) << 2); + static const limb two58m2 = (((limb)1) << 58) - (((limb)1) << 2); + static const limb two58m42m2 = + (((limb)1) << 58) - (((limb)1) << 42) - (((limb)1) << 2); + + /* Add 0 mod 2^224-2^96+1 to ensure out > in */ + out[0] += two58p2; + out[1] += two58m42m2; + out[2] += two58m2; + out[3] += two58m2; + + out[0] -= in[0]; + out[1] -= in[1]; + out[2] -= in[2]; + out[3] -= in[3]; +} + +/* Subtract in unreduced 128-bit mode: out -= in */ +/* Assumes in[i] < 2^119 */ +static void widefelem_diff(widefelem out, const widefelem in) { + static const widelimb two120 = ((widelimb)1) << 120; + static const widelimb two120m64 = + (((widelimb)1) << 120) - (((widelimb)1) << 64); + static const widelimb two120m104m64 = + (((widelimb)1) << 120) - (((widelimb)1) << 104) - (((widelimb)1) << 64); + + /* Add 0 mod 2^224-2^96+1 to ensure out > in */ + out[0] += two120; + out[1] += two120m64; + out[2] += two120m64; + out[3] += two120; + out[4] += two120m104m64; + out[5] += two120m64; + out[6] += two120m64; + + out[0] -= in[0]; + out[1] -= in[1]; + out[2] -= in[2]; + out[3] -= in[3]; + out[4] -= in[4]; + out[5] -= in[5]; + out[6] -= in[6]; +} + +/* Subtract in mixed mode: out128 -= in64 */ +/* in[i] < 2^63 */ +static void felem_diff_128_64(widefelem out, const felem in) { + static const widelimb two64p8 = (((widelimb)1) << 64) + (((widelimb)1) << 8); + static const widelimb two64m8 = (((widelimb)1) << 64) - (((widelimb)1) << 8); + static const widelimb two64m48m8 = + (((widelimb)1) << 64) - (((widelimb)1) << 48) - (((widelimb)1) << 8); + + /* Add 0 mod 2^224-2^96+1 to ensure out > in */ + out[0] += two64p8; + out[1] += two64m48m8; + out[2] += two64m8; + out[3] += two64m8; + + out[0] -= in[0]; + out[1] -= in[1]; + out[2] -= in[2]; + out[3] -= in[3]; +} + +/* Multiply a field element by a scalar: out = out * scalar + * The scalars we actually use are small, so results fit without overflow */ +static void felem_scalar(felem out, const limb scalar) { + out[0] *= scalar; + out[1] *= scalar; + out[2] *= scalar; + out[3] *= scalar; +} + +/* Multiply an unreduced field element by a scalar: out = out * scalar + * The scalars we actually use are small, so results fit without overflow */ +static void widefelem_scalar(widefelem out, const widelimb scalar) { + out[0] *= scalar; + out[1] *= scalar; + out[2] *= scalar; + out[3] *= scalar; + out[4] *= scalar; + out[5] *= scalar; + out[6] *= scalar; +} + +/* Square a field element: out = in^2 */ +static void felem_square(widefelem out, const felem in) { + limb tmp0, tmp1, tmp2; + tmp0 = 2 * in[0]; + tmp1 = 2 * in[1]; + tmp2 = 2 * in[2]; + out[0] = ((widelimb)in[0]) * in[0]; + out[1] = ((widelimb)in[0]) * tmp1; + out[2] = ((widelimb)in[0]) * tmp2 + ((widelimb)in[1]) * in[1]; + out[3] = ((widelimb)in[3]) * tmp0 + ((widelimb)in[1]) * tmp2; + out[4] = ((widelimb)in[3]) * tmp1 + ((widelimb)in[2]) * in[2]; + out[5] = ((widelimb)in[3]) * tmp2; + out[6] = ((widelimb)in[3]) * in[3]; +} + +/* Multiply two field elements: out = in1 * in2 */ +static void felem_mul(widefelem out, const felem in1, const felem in2) { + out[0] = ((widelimb)in1[0]) * in2[0]; + out[1] = ((widelimb)in1[0]) * in2[1] + ((widelimb)in1[1]) * in2[0]; + out[2] = ((widelimb)in1[0]) * in2[2] + ((widelimb)in1[1]) * in2[1] + + ((widelimb)in1[2]) * in2[0]; + out[3] = ((widelimb)in1[0]) * in2[3] + ((widelimb)in1[1]) * in2[2] + + ((widelimb)in1[2]) * in2[1] + ((widelimb)in1[3]) * in2[0]; + out[4] = ((widelimb)in1[1]) * in2[3] + ((widelimb)in1[2]) * in2[2] + + ((widelimb)in1[3]) * in2[1]; + out[5] = ((widelimb)in1[2]) * in2[3] + ((widelimb)in1[3]) * in2[2]; + out[6] = ((widelimb)in1[3]) * in2[3]; +} + +/* Reduce seven 128-bit coefficients to four 64-bit coefficients. + * Requires in[i] < 2^126, + * ensures out[0] < 2^56, out[1] < 2^56, out[2] < 2^56, out[3] <= 2^56 + 2^16 */ +static void felem_reduce(felem out, const widefelem in) { + static const widelimb two127p15 = + (((widelimb)1) << 127) + (((widelimb)1) << 15); + static const widelimb two127m71 = + (((widelimb)1) << 127) - (((widelimb)1) << 71); + static const widelimb two127m71m55 = + (((widelimb)1) << 127) - (((widelimb)1) << 71) - (((widelimb)1) << 55); + widelimb output[5]; + + /* Add 0 mod 2^224-2^96+1 to ensure all differences are positive */ + output[0] = in[0] + two127p15; + output[1] = in[1] + two127m71m55; + output[2] = in[2] + two127m71; + output[3] = in[3]; + output[4] = in[4]; + + /* Eliminate in[4], in[5], in[6] */ + output[4] += in[6] >> 16; + output[3] += (in[6] & 0xffff) << 40; + output[2] -= in[6]; + + output[3] += in[5] >> 16; + output[2] += (in[5] & 0xffff) << 40; + output[1] -= in[5]; + + output[2] += output[4] >> 16; + output[1] += (output[4] & 0xffff) << 40; + output[0] -= output[4]; + + /* Carry 2 -> 3 -> 4 */ + output[3] += output[2] >> 56; + output[2] &= 0x00ffffffffffffff; + + output[4] = output[3] >> 56; + output[3] &= 0x00ffffffffffffff; + + /* Now output[2] < 2^56, output[3] < 2^56, output[4] < 2^72 */ + + /* Eliminate output[4] */ + output[2] += output[4] >> 16; + /* output[2] < 2^56 + 2^56 = 2^57 */ + output[1] += (output[4] & 0xffff) << 40; + output[0] -= output[4]; + + /* Carry 0 -> 1 -> 2 -> 3 */ + output[1] += output[0] >> 56; + out[0] = output[0] & 0x00ffffffffffffff; + + output[2] += output[1] >> 56; + /* output[2] < 2^57 + 2^72 */ + out[1] = output[1] & 0x00ffffffffffffff; + output[3] += output[2] >> 56; + /* output[3] <= 2^56 + 2^16 */ + out[2] = output[2] & 0x00ffffffffffffff; + + /* out[0] < 2^56, out[1] < 2^56, out[2] < 2^56, + * out[3] <= 2^56 + 2^16 (due to final carry), + * so out < 2*p */ + out[3] = output[3]; +} + +/* Reduce to unique minimal representation. + * Requires 0 <= in < 2*p (always call felem_reduce first) */ +static void felem_contract(felem out, const felem in) { + static const int64_t two56 = ((limb)1) << 56; + /* 0 <= in < 2*p, p = 2^224 - 2^96 + 1 */ + /* if in > p , reduce in = in - 2^224 + 2^96 - 1 */ + int64_t tmp[4], a; + tmp[0] = in[0]; + tmp[1] = in[1]; + tmp[2] = in[2]; + tmp[3] = in[3]; + /* Case 1: a = 1 iff in >= 2^224 */ + a = (in[3] >> 56); + tmp[0] -= a; + tmp[1] += a << 40; + tmp[3] &= 0x00ffffffffffffff; + /* Case 2: a = 0 iff p <= in < 2^224, i.e., the high 128 bits are all 1 and + * the lower part is non-zero */ + a = ((in[3] & in[2] & (in[1] | 0x000000ffffffffff)) + 1) | + (((int64_t)(in[0] + (in[1] & 0x000000ffffffffff)) - 1) >> 63); + a &= 0x00ffffffffffffff; + /* turn a into an all-one mask (if a = 0) or an all-zero mask */ + a = (a - 1) >> 63; + /* subtract 2^224 - 2^96 + 1 if a is all-one */ + tmp[3] &= a ^ 0xffffffffffffffff; + tmp[2] &= a ^ 0xffffffffffffffff; + tmp[1] &= (a ^ 0xffffffffffffffff) | 0x000000ffffffffff; + tmp[0] -= 1 & a; + + /* eliminate negative coefficients: if tmp[0] is negative, tmp[1] must + * be non-zero, so we only need one step */ + a = tmp[0] >> 63; + tmp[0] += two56 & a; + tmp[1] -= 1 & a; + + /* carry 1 -> 2 -> 3 */ + tmp[2] += tmp[1] >> 56; + tmp[1] &= 0x00ffffffffffffff; + + tmp[3] += tmp[2] >> 56; + tmp[2] &= 0x00ffffffffffffff; + + /* Now 0 <= out < p */ + out[0] = tmp[0]; + out[1] = tmp[1]; + out[2] = tmp[2]; + out[3] = tmp[3]; +} + +/* Zero-check: returns 1 if input is 0, and 0 otherwise. We know that field + * elements are reduced to in < 2^225, so we only need to check three cases: 0, + * 2^224 - 2^96 + 1, and 2^225 - 2^97 + 2 */ +static limb felem_is_zero(const felem in) { + limb zero = in[0] | in[1] | in[2] | in[3]; + zero = (((int64_t)(zero)-1) >> 63) & 1; + + limb two224m96p1 = (in[0] ^ 1) | (in[1] ^ 0x00ffff0000000000) | + (in[2] ^ 0x00ffffffffffffff) | + (in[3] ^ 0x00ffffffffffffff); + two224m96p1 = (((int64_t)(two224m96p1)-1) >> 63) & 1; + limb two225m97p2 = (in[0] ^ 2) | (in[1] ^ 0x00fffe0000000000) | + (in[2] ^ 0x00ffffffffffffff) | + (in[3] ^ 0x01ffffffffffffff); + two225m97p2 = (((int64_t)(two225m97p2)-1) >> 63) & 1; + return (zero | two224m96p1 | two225m97p2); +} + +/* Invert a field element */ +/* Computation chain copied from djb's code */ +static void felem_inv(felem out, const felem in) { + felem ftmp, ftmp2, ftmp3, ftmp4; + widefelem tmp; + size_t i; + + felem_square(tmp, in); + felem_reduce(ftmp, tmp); /* 2 */ + felem_mul(tmp, in, ftmp); + felem_reduce(ftmp, tmp); /* 2^2 - 1 */ + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); /* 2^3 - 2 */ + felem_mul(tmp, in, ftmp); + felem_reduce(ftmp, tmp); /* 2^3 - 1 */ + felem_square(tmp, ftmp); + felem_reduce(ftmp2, tmp); /* 2^4 - 2 */ + felem_square(tmp, ftmp2); + felem_reduce(ftmp2, tmp); /* 2^5 - 4 */ + felem_square(tmp, ftmp2); + felem_reduce(ftmp2, tmp); /* 2^6 - 8 */ + felem_mul(tmp, ftmp2, ftmp); + felem_reduce(ftmp, tmp); /* 2^6 - 1 */ + felem_square(tmp, ftmp); + felem_reduce(ftmp2, tmp); /* 2^7 - 2 */ + for (i = 0; i < 5; ++i) { /* 2^12 - 2^6 */ + felem_square(tmp, ftmp2); + felem_reduce(ftmp2, tmp); + } + felem_mul(tmp, ftmp2, ftmp); + felem_reduce(ftmp2, tmp); /* 2^12 - 1 */ + felem_square(tmp, ftmp2); + felem_reduce(ftmp3, tmp); /* 2^13 - 2 */ + for (i = 0; i < 11; ++i) {/* 2^24 - 2^12 */ + felem_square(tmp, ftmp3); + felem_reduce(ftmp3, tmp); + } + felem_mul(tmp, ftmp3, ftmp2); + felem_reduce(ftmp2, tmp); /* 2^24 - 1 */ + felem_square(tmp, ftmp2); + felem_reduce(ftmp3, tmp); /* 2^25 - 2 */ + for (i = 0; i < 23; ++i) {/* 2^48 - 2^24 */ + felem_square(tmp, ftmp3); + felem_reduce(ftmp3, tmp); + } + felem_mul(tmp, ftmp3, ftmp2); + felem_reduce(ftmp3, tmp); /* 2^48 - 1 */ + felem_square(tmp, ftmp3); + felem_reduce(ftmp4, tmp); /* 2^49 - 2 */ + for (i = 0; i < 47; ++i) {/* 2^96 - 2^48 */ + felem_square(tmp, ftmp4); + felem_reduce(ftmp4, tmp); + } + felem_mul(tmp, ftmp3, ftmp4); + felem_reduce(ftmp3, tmp); /* 2^96 - 1 */ + felem_square(tmp, ftmp3); + felem_reduce(ftmp4, tmp); /* 2^97 - 2 */ + for (i = 0; i < 23; ++i) {/* 2^120 - 2^24 */ + felem_square(tmp, ftmp4); + felem_reduce(ftmp4, tmp); + } + felem_mul(tmp, ftmp2, ftmp4); + felem_reduce(ftmp2, tmp); /* 2^120 - 1 */ + for (i = 0; i < 6; ++i) { /* 2^126 - 2^6 */ + felem_square(tmp, ftmp2); + felem_reduce(ftmp2, tmp); + } + felem_mul(tmp, ftmp2, ftmp); + felem_reduce(ftmp, tmp); /* 2^126 - 1 */ + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); /* 2^127 - 2 */ + felem_mul(tmp, ftmp, in); + felem_reduce(ftmp, tmp); /* 2^127 - 1 */ + for (i = 0; i < 97; ++i) {/* 2^224 - 2^97 */ + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); + } + felem_mul(tmp, ftmp, ftmp3); + felem_reduce(out, tmp); /* 2^224 - 2^96 - 1 */ +} + +/* Copy in constant time: + * if icopy == 1, copy in to out, + * if icopy == 0, copy out to itself. */ +static void copy_conditional(felem out, const felem in, limb icopy) { + size_t i; + /* icopy is a (64-bit) 0 or 1, so copy is either all-zero or all-one */ + const limb copy = -icopy; + for (i = 0; i < 4; ++i) { + const limb tmp = copy & (in[i] ^ out[i]); + out[i] ^= tmp; + } +} + +/* ELLIPTIC CURVE POINT OPERATIONS + * + * Points are represented in Jacobian projective coordinates: + * (X, Y, Z) corresponds to the affine point (X/Z^2, Y/Z^3), + * or to the point at infinity if Z == 0. */ + +/* Double an elliptic curve point: + * (X', Y', Z') = 2 * (X, Y, Z), where + * X' = (3 * (X - Z^2) * (X + Z^2))^2 - 8 * X * Y^2 + * Y' = 3 * (X - Z^2) * (X + Z^2) * (4 * X * Y^2 - X') - 8 * Y^2 + * Z' = (Y + Z)^2 - Y^2 - Z^2 = 2 * Y * Z + * Outputs can equal corresponding inputs, i.e., x_out == x_in is allowed, + * while x_out == y_in is not (maybe this works, but it's not tested). */ +static void point_double(felem x_out, felem y_out, felem z_out, + const felem x_in, const felem y_in, const felem z_in) { + widefelem tmp, tmp2; + felem delta, gamma, beta, alpha, ftmp, ftmp2; + + felem_assign(ftmp, x_in); + felem_assign(ftmp2, x_in); + + /* delta = z^2 */ + felem_square(tmp, z_in); + felem_reduce(delta, tmp); + + /* gamma = y^2 */ + felem_square(tmp, y_in); + felem_reduce(gamma, tmp); + + /* beta = x*gamma */ + felem_mul(tmp, x_in, gamma); + felem_reduce(beta, tmp); + + /* alpha = 3*(x-delta)*(x+delta) */ + felem_diff(ftmp, delta); + /* ftmp[i] < 2^57 + 2^58 + 2 < 2^59 */ + felem_sum(ftmp2, delta); + /* ftmp2[i] < 2^57 + 2^57 = 2^58 */ + felem_scalar(ftmp2, 3); + /* ftmp2[i] < 3 * 2^58 < 2^60 */ + felem_mul(tmp, ftmp, ftmp2); + /* tmp[i] < 2^60 * 2^59 * 4 = 2^121 */ + felem_reduce(alpha, tmp); + + /* x' = alpha^2 - 8*beta */ + felem_square(tmp, alpha); + /* tmp[i] < 4 * 2^57 * 2^57 = 2^116 */ + felem_assign(ftmp, beta); + felem_scalar(ftmp, 8); + /* ftmp[i] < 8 * 2^57 = 2^60 */ + felem_diff_128_64(tmp, ftmp); + /* tmp[i] < 2^116 + 2^64 + 8 < 2^117 */ + felem_reduce(x_out, tmp); + + /* z' = (y + z)^2 - gamma - delta */ + felem_sum(delta, gamma); + /* delta[i] < 2^57 + 2^57 = 2^58 */ + felem_assign(ftmp, y_in); + felem_sum(ftmp, z_in); + /* ftmp[i] < 2^57 + 2^57 = 2^58 */ + felem_square(tmp, ftmp); + /* tmp[i] < 4 * 2^58 * 2^58 = 2^118 */ + felem_diff_128_64(tmp, delta); + /* tmp[i] < 2^118 + 2^64 + 8 < 2^119 */ + felem_reduce(z_out, tmp); + + /* y' = alpha*(4*beta - x') - 8*gamma^2 */ + felem_scalar(beta, 4); + /* beta[i] < 4 * 2^57 = 2^59 */ + felem_diff(beta, x_out); + /* beta[i] < 2^59 + 2^58 + 2 < 2^60 */ + felem_mul(tmp, alpha, beta); + /* tmp[i] < 4 * 2^57 * 2^60 = 2^119 */ + felem_square(tmp2, gamma); + /* tmp2[i] < 4 * 2^57 * 2^57 = 2^116 */ + widefelem_scalar(tmp2, 8); + /* tmp2[i] < 8 * 2^116 = 2^119 */ + widefelem_diff(tmp, tmp2); + /* tmp[i] < 2^119 + 2^120 < 2^121 */ + felem_reduce(y_out, tmp); +} + +/* Add two elliptic curve points: + * (X_1, Y_1, Z_1) + (X_2, Y_2, Z_2) = (X_3, Y_3, Z_3), where + * X_3 = (Z_1^3 * Y_2 - Z_2^3 * Y_1)^2 - (Z_1^2 * X_2 - Z_2^2 * X_1)^3 - + * 2 * Z_2^2 * X_1 * (Z_1^2 * X_2 - Z_2^2 * X_1)^2 + * Y_3 = (Z_1^3 * Y_2 - Z_2^3 * Y_1) * (Z_2^2 * X_1 * (Z_1^2 * X_2 - Z_2^2 * + * X_1)^2 - X_3) - + * Z_2^3 * Y_1 * (Z_1^2 * X_2 - Z_2^2 * X_1)^3 + * Z_3 = (Z_1^2 * X_2 - Z_2^2 * X_1) * (Z_1 * Z_2) + * + * This runs faster if 'mixed' is set, which requires Z_2 = 1 or Z_2 = 0. */ + +/* This function is not entirely constant-time: it includes a branch for + * checking whether the two input points are equal, (while not equal to the + * point at infinity). This case never happens during single point + * multiplication, so there is no timing leak for ECDH or ECDSA signing. */ +static void point_add(felem x3, felem y3, felem z3, const felem x1, + const felem y1, const felem z1, const int mixed, + const felem x2, const felem y2, const felem z2) { + felem ftmp, ftmp2, ftmp3, ftmp4, ftmp5, x_out, y_out, z_out; + widefelem tmp, tmp2; + limb z1_is_zero, z2_is_zero, x_equal, y_equal; + + if (!mixed) { + /* ftmp2 = z2^2 */ + felem_square(tmp, z2); + felem_reduce(ftmp2, tmp); + + /* ftmp4 = z2^3 */ + felem_mul(tmp, ftmp2, z2); + felem_reduce(ftmp4, tmp); + + /* ftmp4 = z2^3*y1 */ + felem_mul(tmp2, ftmp4, y1); + felem_reduce(ftmp4, tmp2); + + /* ftmp2 = z2^2*x1 */ + felem_mul(tmp2, ftmp2, x1); + felem_reduce(ftmp2, tmp2); + } else { + /* We'll assume z2 = 1 (special case z2 = 0 is handled later) */ + + /* ftmp4 = z2^3*y1 */ + felem_assign(ftmp4, y1); + + /* ftmp2 = z2^2*x1 */ + felem_assign(ftmp2, x1); + } + + /* ftmp = z1^2 */ + felem_square(tmp, z1); + felem_reduce(ftmp, tmp); + + /* ftmp3 = z1^3 */ + felem_mul(tmp, ftmp, z1); + felem_reduce(ftmp3, tmp); + + /* tmp = z1^3*y2 */ + felem_mul(tmp, ftmp3, y2); + /* tmp[i] < 4 * 2^57 * 2^57 = 2^116 */ + + /* ftmp3 = z1^3*y2 - z2^3*y1 */ + felem_diff_128_64(tmp, ftmp4); + /* tmp[i] < 2^116 + 2^64 + 8 < 2^117 */ + felem_reduce(ftmp3, tmp); + + /* tmp = z1^2*x2 */ + felem_mul(tmp, ftmp, x2); + /* tmp[i] < 4 * 2^57 * 2^57 = 2^116 */ + + /* ftmp = z1^2*x2 - z2^2*x1 */ + felem_diff_128_64(tmp, ftmp2); + /* tmp[i] < 2^116 + 2^64 + 8 < 2^117 */ + felem_reduce(ftmp, tmp); + + /* the formulae are incorrect if the points are equal + * so we check for this and do doubling if this happens */ + x_equal = felem_is_zero(ftmp); + y_equal = felem_is_zero(ftmp3); + z1_is_zero = felem_is_zero(z1); + z2_is_zero = felem_is_zero(z2); + /* In affine coordinates, (X_1, Y_1) == (X_2, Y_2) */ + if (x_equal && y_equal && !z1_is_zero && !z2_is_zero) { + point_double(x3, y3, z3, x1, y1, z1); + return; + } + + /* ftmp5 = z1*z2 */ + if (!mixed) { + felem_mul(tmp, z1, z2); + felem_reduce(ftmp5, tmp); + } else { + /* special case z2 = 0 is handled later */ + felem_assign(ftmp5, z1); + } + + /* z_out = (z1^2*x2 - z2^2*x1)*(z1*z2) */ + felem_mul(tmp, ftmp, ftmp5); + felem_reduce(z_out, tmp); + + /* ftmp = (z1^2*x2 - z2^2*x1)^2 */ + felem_assign(ftmp5, ftmp); + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); + + /* ftmp5 = (z1^2*x2 - z2^2*x1)^3 */ + felem_mul(tmp, ftmp, ftmp5); + felem_reduce(ftmp5, tmp); + + /* ftmp2 = z2^2*x1*(z1^2*x2 - z2^2*x1)^2 */ + felem_mul(tmp, ftmp2, ftmp); + felem_reduce(ftmp2, tmp); + + /* tmp = z2^3*y1*(z1^2*x2 - z2^2*x1)^3 */ + felem_mul(tmp, ftmp4, ftmp5); + /* tmp[i] < 4 * 2^57 * 2^57 = 2^116 */ + + /* tmp2 = (z1^3*y2 - z2^3*y1)^2 */ + felem_square(tmp2, ftmp3); + /* tmp2[i] < 4 * 2^57 * 2^57 < 2^116 */ + + /* tmp2 = (z1^3*y2 - z2^3*y1)^2 - (z1^2*x2 - z2^2*x1)^3 */ + felem_diff_128_64(tmp2, ftmp5); + /* tmp2[i] < 2^116 + 2^64 + 8 < 2^117 */ + + /* ftmp5 = 2*z2^2*x1*(z1^2*x2 - z2^2*x1)^2 */ + felem_assign(ftmp5, ftmp2); + felem_scalar(ftmp5, 2); + /* ftmp5[i] < 2 * 2^57 = 2^58 */ + + /* x_out = (z1^3*y2 - z2^3*y1)^2 - (z1^2*x2 - z2^2*x1)^3 - + 2*z2^2*x1*(z1^2*x2 - z2^2*x1)^2 */ + felem_diff_128_64(tmp2, ftmp5); + /* tmp2[i] < 2^117 + 2^64 + 8 < 2^118 */ + felem_reduce(x_out, tmp2); + + /* ftmp2 = z2^2*x1*(z1^2*x2 - z2^2*x1)^2 - x_out */ + felem_diff(ftmp2, x_out); + /* ftmp2[i] < 2^57 + 2^58 + 2 < 2^59 */ + + /* tmp2 = (z1^3*y2 - z2^3*y1)*(z2^2*x1*(z1^2*x2 - z2^2*x1)^2 - x_out) */ + felem_mul(tmp2, ftmp3, ftmp2); + /* tmp2[i] < 4 * 2^57 * 2^59 = 2^118 */ + + /* y_out = (z1^3*y2 - z2^3*y1)*(z2^2*x1*(z1^2*x2 - z2^2*x1)^2 - x_out) - + z2^3*y1*(z1^2*x2 - z2^2*x1)^3 */ + widefelem_diff(tmp2, tmp); + /* tmp2[i] < 2^118 + 2^120 < 2^121 */ + felem_reduce(y_out, tmp2); + + /* the result (x_out, y_out, z_out) is incorrect if one of the inputs is + * the point at infinity, so we need to check for this separately */ + + /* if point 1 is at infinity, copy point 2 to output, and vice versa */ + copy_conditional(x_out, x2, z1_is_zero); + copy_conditional(x_out, x1, z2_is_zero); + copy_conditional(y_out, y2, z1_is_zero); + copy_conditional(y_out, y1, z2_is_zero); + copy_conditional(z_out, z2, z1_is_zero); + copy_conditional(z_out, z1, z2_is_zero); + felem_assign(x3, x_out); + felem_assign(y3, y_out); + felem_assign(z3, z_out); +} + +/* select_point selects the |idx|th point from a precomputation table and + * copies it to out. */ +static void select_point(const u64 idx, size_t size, + const felem pre_comp[/*size*/][3], felem out[3]) { + limb *outlimbs = &out[0][0]; + memset(outlimbs, 0, 3 * sizeof(felem)); + + size_t i; + for (i = 0; i < size; i++) { + const limb *inlimbs = &pre_comp[i][0][0]; + u64 mask = i ^ idx; + mask |= mask >> 4; + mask |= mask >> 2; + mask |= mask >> 1; + mask &= 1; + mask--; + size_t j; + for (j = 0; j < 4 * 3; j++) { + outlimbs[j] |= inlimbs[j] & mask; + } + } +} + +/* get_bit returns the |i|th bit in |in| */ +static char get_bit(const felem_bytearray in, size_t i) { + if (i >= 224) { + return 0; + } + return (in[i >> 3] >> (i & 7)) & 1; +} + +/* Interleaved point multiplication using precomputed point multiples: + * The small point multiples 0*P, 1*P, ..., 16*P are in pre_comp[], + * the scalars in scalars[]. If g_scalar is non-NULL, we also add this multiple + * of the generator, using certain (large) precomputed multiples in g_pre_comp. + * Output point (X, Y, Z) is stored in x_out, y_out, z_out */ +static void batch_mul(felem x_out, felem y_out, felem z_out, + const felem_bytearray scalars[], + const size_t num_points, const u8 *g_scalar, + const felem pre_comp[][17][3]) { + felem nq[3], tmp[4]; + u64 bits; + u8 sign, digit; + + /* set nq to the point at infinity */ + memset(nq, 0, 3 * sizeof(felem)); + + /* Loop over all scalars msb-to-lsb, interleaving additions + * of multiples of the generator (two in each of the last 28 rounds) + * and additions of other points multiples (every 5th round). */ + int skip = 1; /* save two point operations in the first round */ + size_t i = num_points != 0 ? 220 : 27; + for (;;) { + /* double */ + if (!skip) { + point_double(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2]); + } + + /* add multiples of the generator */ + if (g_scalar != NULL && i <= 27) { + /* first, look 28 bits upwards */ + bits = get_bit(g_scalar, i + 196) << 3; + bits |= get_bit(g_scalar, i + 140) << 2; + bits |= get_bit(g_scalar, i + 84) << 1; + bits |= get_bit(g_scalar, i + 28); + /* select the point to add, in constant time */ + select_point(bits, 16, g_pre_comp[1], tmp); + + if (!skip) { + point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], 1 /* mixed */, + tmp[0], tmp[1], tmp[2]); + } else { + memcpy(nq, tmp, 3 * sizeof(felem)); + skip = 0; + } + + /* second, look at the current position */ + bits = get_bit(g_scalar, i + 168) << 3; + bits |= get_bit(g_scalar, i + 112) << 2; + bits |= get_bit(g_scalar, i + 56) << 1; + bits |= get_bit(g_scalar, i); + /* select the point to add, in constant time */ + select_point(bits, 16, g_pre_comp[0], tmp); + point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], 1 /* mixed */, tmp[0], + tmp[1], tmp[2]); + } + + /* do other additions every 5 doublings */ + if (num_points != 0 && i % 5 == 0) { + /* loop over all scalars */ + size_t num; + for (num = 0; num < num_points; ++num) { + bits = get_bit(scalars[num], i + 4) << 5; + bits |= get_bit(scalars[num], i + 3) << 4; + bits |= get_bit(scalars[num], i + 2) << 3; + bits |= get_bit(scalars[num], i + 1) << 2; + bits |= get_bit(scalars[num], i) << 1; + bits |= get_bit(scalars[num], i - 1); + ec_GFp_nistp_recode_scalar_bits(&sign, &digit, bits); + + /* select the point to add or subtract */ + select_point(digit, 17, pre_comp[num], tmp); + felem_neg(tmp[3], tmp[1]); /* (X, -Y, Z) is the negative point */ + copy_conditional(tmp[1], tmp[3], sign); + + if (!skip) { + point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], 0 /* mixed */, + tmp[0], tmp[1], tmp[2]); + } else { + memcpy(nq, tmp, 3 * sizeof(felem)); + skip = 0; + } + } + } + + if (i == 0) { + break; + } + --i; + } + felem_assign(x_out, nq[0]); + felem_assign(y_out, nq[1]); + felem_assign(z_out, nq[2]); +} + +/* Takes the Jacobian coordinates (X, Y, Z) of a point and returns + * (X', Y') = (X/Z^2, Y/Z^3) */ +static int ec_GFp_nistp224_point_get_affine_coordinates(const EC_GROUP *group, + const EC_POINT *point, + BIGNUM *x, BIGNUM *y, + BN_CTX *ctx) { + felem z1, z2, x_in, y_in, x_out, y_out; + widefelem tmp; + + if (EC_POINT_is_at_infinity(group, point)) { + OPENSSL_PUT_ERROR(EC, EC_R_POINT_AT_INFINITY); + return 0; + } + + if (!BN_to_felem(x_in, &point->X) || + !BN_to_felem(y_in, &point->Y) || + !BN_to_felem(z1, &point->Z)) { + return 0; + } + + felem_inv(z2, z1); + felem_square(tmp, z2); + felem_reduce(z1, tmp); + felem_mul(tmp, x_in, z1); + felem_reduce(x_in, tmp); + felem_contract(x_out, x_in); + if (x != NULL && !felem_to_BN(x, x_out)) { + OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); + return 0; + } + + felem_mul(tmp, z1, z2); + felem_reduce(z1, tmp); + felem_mul(tmp, y_in, z1); + felem_reduce(y_in, tmp); + felem_contract(y_out, y_in); + if (y != NULL && !felem_to_BN(y, y_out)) { + OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); + return 0; + } + + return 1; +} + +static int ec_GFp_nistp224_points_mul(const EC_GROUP *group, + EC_POINT *r, + const BIGNUM *g_scalar, + const EC_POINT *p_, + const BIGNUM *p_scalar_, + BN_CTX *ctx) { + /* TODO: This function used to take |points| and |scalars| as arrays of + * |num| elements. The code below should be simplified to work in terms of + * |p_| and |p_scalar_|. */ + size_t num = p_ != NULL ? 1 : 0; + const EC_POINT **points = p_ != NULL ? &p_ : NULL; + BIGNUM const *const *scalars = p_ != NULL ? &p_scalar_ : NULL; + + int ret = 0; + BN_CTX *new_ctx = NULL; + BIGNUM *x, *y, *z, *tmp_scalar; + felem_bytearray g_secret; + felem_bytearray *secrets = NULL; + felem(*pre_comp)[17][3] = NULL; + felem_bytearray tmp; + size_t num_points = num; + felem x_in, y_in, z_in, x_out, y_out, z_out; + const EC_POINT *p = NULL; + const BIGNUM *p_scalar = NULL; + + if (ctx == NULL) { + ctx = BN_CTX_new(); + new_ctx = ctx; + if (ctx == NULL) { + return 0; + } + } + + BN_CTX_start(ctx); + if ((x = BN_CTX_get(ctx)) == NULL || + (y = BN_CTX_get(ctx)) == NULL || + (z = BN_CTX_get(ctx)) == NULL || + (tmp_scalar = BN_CTX_get(ctx)) == NULL) { + goto err; + } + + if (num_points > 0) { + secrets = OPENSSL_malloc(num_points * sizeof(felem_bytearray)); + pre_comp = OPENSSL_malloc(num_points * sizeof(felem[17][3])); + if (secrets == NULL || + pre_comp == NULL) { + OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); + goto err; + } + + /* we treat NULL scalars as 0, and NULL points as points at infinity, + * i.e., they contribute nothing to the linear combination */ + memset(secrets, 0, num_points * sizeof(felem_bytearray)); + memset(pre_comp, 0, num_points * 17 * 3 * sizeof(felem)); + size_t i; + for (i = 0; i < num_points; ++i) { + if (i == num) { + /* the generator */ + p = EC_GROUP_get0_generator(group); + p_scalar = g_scalar; + } else { + /* the i^th point */ + p = points[i]; + p_scalar = scalars[i]; + } + + if (p_scalar != NULL && p != NULL) { + size_t num_bytes; + /* reduce g_scalar to 0 <= g_scalar < 2^224 */ + if (BN_num_bits(p_scalar) > 224 || BN_is_negative(p_scalar)) { + /* this is an unusual input, and we don't guarantee + * constant-timeness */ + if (!BN_nnmod(tmp_scalar, p_scalar, &group->order, ctx)) { + OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); + goto err; + } + num_bytes = BN_bn2bin(tmp_scalar, tmp); + } else { + num_bytes = BN_bn2bin(p_scalar, tmp); + } + + flip_endian(secrets[i], tmp, num_bytes); + /* precompute multiples */ + if (!BN_to_felem(x_out, &p->X) || + !BN_to_felem(y_out, &p->Y) || + !BN_to_felem(z_out, &p->Z)) { + goto err; + } + + felem_assign(pre_comp[i][1][0], x_out); + felem_assign(pre_comp[i][1][1], y_out); + felem_assign(pre_comp[i][1][2], z_out); + + size_t j; + for (j = 2; j <= 16; ++j) { + if (j & 1) { + point_add(pre_comp[i][j][0], pre_comp[i][j][1], pre_comp[i][j][2], + pre_comp[i][1][0], pre_comp[i][1][1], pre_comp[i][1][2], + 0, pre_comp[i][j - 1][0], pre_comp[i][j - 1][1], + pre_comp[i][j - 1][2]); + } else { + point_double(pre_comp[i][j][0], pre_comp[i][j][1], + pre_comp[i][j][2], pre_comp[i][j / 2][0], + pre_comp[i][j / 2][1], pre_comp[i][j / 2][2]); + } + } + } + } + } + + if (g_scalar != NULL) { + memset(g_secret, 0, sizeof(g_secret)); + size_t num_bytes; + /* reduce g_scalar to 0 <= g_scalar < 2^224 */ + if (BN_num_bits(g_scalar) > 224 || BN_is_negative(g_scalar)) { + /* this is an unusual input, and we don't guarantee constant-timeness */ + if (!BN_nnmod(tmp_scalar, g_scalar, &group->order, ctx)) { + OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); + goto err; + } + num_bytes = BN_bn2bin(tmp_scalar, tmp); + } else { + num_bytes = BN_bn2bin(g_scalar, tmp); + } + + flip_endian(g_secret, tmp, num_bytes); + } + batch_mul(x_out, y_out, z_out, (const felem_bytearray(*))secrets, + num_points, g_scalar != NULL ? g_secret : NULL, + (const felem(*)[17][3])pre_comp); + + /* reduce the output to its unique minimal representation */ + felem_contract(x_in, x_out); + felem_contract(y_in, y_out); + felem_contract(z_in, z_out); + if (!felem_to_BN(x, x_in) || + !felem_to_BN(y, y_in) || + !felem_to_BN(z, z_in)) { + OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); + goto err; + } + ret = ec_point_set_Jprojective_coordinates_GFp(group, r, x, y, z, ctx); + +err: + BN_CTX_end(ctx); + BN_CTX_free(new_ctx); + OPENSSL_free(secrets); + OPENSSL_free(pre_comp); + return ret; +} + +const EC_METHOD *EC_GFp_nistp224_method(void) { + static const EC_METHOD ret = {ec_GFp_simple_group_init, + ec_GFp_simple_group_finish, + ec_GFp_simple_group_copy, + ec_GFp_simple_group_set_curve, + ec_GFp_nistp224_point_get_affine_coordinates, + ec_GFp_nistp224_points_mul, + 0 /* check_pub_key_order */, + ec_GFp_simple_field_mul, + ec_GFp_simple_field_sqr, + 0 /* field_encode */, + 0 /* field_decode */}; + + return &ret; +} + +#endif /* 64_BIT && !WINDOWS && !SMALL */ diff --git a/external/boringssl/crypto/ec/p256-64.c b/external/boringssl/crypto/ec/p256-64.c new file mode 100644 index 0000000000..c4259b629f --- /dev/null +++ b/external/boringssl/crypto/ec/p256-64.c @@ -0,0 +1,1753 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +/* A 64-bit implementation of the NIST P-256 elliptic curve point + * multiplication + * + * OpenSSL integration was taken from Emilia Kasper's work in ecp_nistp224.c. + * Otherwise based on Emilia's P224 work, which was inspired by my curve25519 + * work which got its smarts from Daniel J. Bernstein's work on the same. */ + +#include + +#if defined(OPENSSL_64_BIT) && !defined(OPENSSL_WINDOWS) + +#include +#include +#include +#include + +#include + +#include "internal.h" +#include "../internal.h" + + +typedef uint8_t u8; +typedef uint64_t u64; +typedef int64_t s64; + +/* The underlying field. P256 operates over GF(2^256-2^224+2^192+2^96-1). We + * can serialise an element of this field into 32 bytes. We call this an + * felem_bytearray. */ +typedef u8 felem_bytearray[32]; + +/* The representation of field elements. + * ------------------------------------ + * + * We represent field elements with either four 128-bit values, eight 128-bit + * values, or four 64-bit values. The field element represented is: + * v[0]*2^0 + v[1]*2^64 + v[2]*2^128 + v[3]*2^192 (mod p) + * or: + * v[0]*2^0 + v[1]*2^64 + v[2]*2^128 + ... + v[8]*2^512 (mod p) + * + * 128-bit values are called 'limbs'. Since the limbs are spaced only 64 bits + * apart, but are 128-bits wide, the most significant bits of each limb overlap + * with the least significant bits of the next. + * + * A field element with four limbs is an 'felem'. One with eight limbs is a + * 'longfelem' + * + * A field element with four, 64-bit values is called a 'smallfelem'. Small + * values are used as intermediate values before multiplication. */ + +#define NLIMBS 4 + +typedef uint128_t limb; +typedef limb felem[NLIMBS]; +typedef limb longfelem[NLIMBS * 2]; +typedef u64 smallfelem[NLIMBS]; + +/* This is the value of the prime as four 64-bit words, little-endian. */ +static const u64 kPrime[4] = {0xfffffffffffffffful, 0xffffffff, 0, + 0xffffffff00000001ul}; +static const u64 bottom63bits = 0x7ffffffffffffffful; + +/* bin32_to_felem takes a little-endian byte array and converts it into felem + * form. This assumes that the CPU is little-endian. */ +static void bin32_to_felem(felem out, const u8 in[32]) { + out[0] = *((const u64 *)&in[0]); + out[1] = *((const u64 *)&in[8]); + out[2] = *((const u64 *)&in[16]); + out[3] = *((const u64 *)&in[24]); +} + +/* smallfelem_to_bin32 takes a smallfelem and serialises into a little endian, + * 32 byte array. This assumes that the CPU is little-endian. */ +static void smallfelem_to_bin32(u8 out[32], const smallfelem in) { + *((u64 *)&out[0]) = in[0]; + *((u64 *)&out[8]) = in[1]; + *((u64 *)&out[16]) = in[2]; + *((u64 *)&out[24]) = in[3]; +} + +/* To preserve endianness when using BN_bn2bin and BN_bin2bn. */ +static void flip_endian(u8 *out, const u8 *in, size_t len) { + size_t i; + for (i = 0; i < len; ++i) { + out[i] = in[len - 1 - i]; + } +} + +/* BN_to_felem converts an OpenSSL BIGNUM into an felem. */ +static int BN_to_felem(felem out, const BIGNUM *bn) { + if (BN_is_negative(bn)) { + OPENSSL_PUT_ERROR(EC, EC_R_BIGNUM_OUT_OF_RANGE); + return 0; + } + + felem_bytearray b_out; + /* BN_bn2bin eats leading zeroes */ + memset(b_out, 0, sizeof(b_out)); + size_t num_bytes = BN_num_bytes(bn); + if (num_bytes > sizeof(b_out)) { + OPENSSL_PUT_ERROR(EC, EC_R_BIGNUM_OUT_OF_RANGE); + return 0; + } + + felem_bytearray b_in; + num_bytes = BN_bn2bin(bn, b_in); + flip_endian(b_out, b_in, num_bytes); + bin32_to_felem(out, b_out); + return 1; +} + +/* felem_to_BN converts an felem into an OpenSSL BIGNUM. */ +static BIGNUM *smallfelem_to_BN(BIGNUM *out, const smallfelem in) { + felem_bytearray b_in, b_out; + smallfelem_to_bin32(b_in, in); + flip_endian(b_out, b_in, sizeof(b_out)); + return BN_bin2bn(b_out, sizeof(b_out), out); +} + +/* Field operations. */ + +static void felem_assign(felem out, const felem in) { + out[0] = in[0]; + out[1] = in[1]; + out[2] = in[2]; + out[3] = in[3]; +} + +/* felem_sum sets out = out + in. */ +static void felem_sum(felem out, const felem in) { + out[0] += in[0]; + out[1] += in[1]; + out[2] += in[2]; + out[3] += in[3]; +} + +/* felem_small_sum sets out = out + in. */ +static void felem_small_sum(felem out, const smallfelem in) { + out[0] += in[0]; + out[1] += in[1]; + out[2] += in[2]; + out[3] += in[3]; +} + +/* felem_scalar sets out = out * scalar */ +static void felem_scalar(felem out, const u64 scalar) { + out[0] *= scalar; + out[1] *= scalar; + out[2] *= scalar; + out[3] *= scalar; +} + +/* longfelem_scalar sets out = out * scalar */ +static void longfelem_scalar(longfelem out, const u64 scalar) { + out[0] *= scalar; + out[1] *= scalar; + out[2] *= scalar; + out[3] *= scalar; + out[4] *= scalar; + out[5] *= scalar; + out[6] *= scalar; + out[7] *= scalar; +} + +#define two105m41m9 (((limb)1) << 105) - (((limb)1) << 41) - (((limb)1) << 9) +#define two105 (((limb)1) << 105) +#define two105m41p9 (((limb)1) << 105) - (((limb)1) << 41) + (((limb)1) << 9) + +/* zero105 is 0 mod p */ +static const felem zero105 = {two105m41m9, two105, two105m41p9, two105m41p9}; + +/* smallfelem_neg sets |out| to |-small| + * On exit: + * out[i] < out[i] + 2^105 */ +static void smallfelem_neg(felem out, const smallfelem small) { + /* In order to prevent underflow, we subtract from 0 mod p. */ + out[0] = zero105[0] - small[0]; + out[1] = zero105[1] - small[1]; + out[2] = zero105[2] - small[2]; + out[3] = zero105[3] - small[3]; +} + +/* felem_diff subtracts |in| from |out| + * On entry: + * in[i] < 2^104 + * On exit: + * out[i] < out[i] + 2^105. */ +static void felem_diff(felem out, const felem in) { + /* In order to prevent underflow, we add 0 mod p before subtracting. */ + out[0] += zero105[0]; + out[1] += zero105[1]; + out[2] += zero105[2]; + out[3] += zero105[3]; + + out[0] -= in[0]; + out[1] -= in[1]; + out[2] -= in[2]; + out[3] -= in[3]; +} + +#define two107m43m11 (((limb)1) << 107) - (((limb)1) << 43) - (((limb)1) << 11) +#define two107 (((limb)1) << 107) +#define two107m43p11 (((limb)1) << 107) - (((limb)1) << 43) + (((limb)1) << 11) + +/* zero107 is 0 mod p */ +static const felem zero107 = {two107m43m11, two107, two107m43p11, two107m43p11}; + +/* An alternative felem_diff for larger inputs |in| + * felem_diff_zero107 subtracts |in| from |out| + * On entry: + * in[i] < 2^106 + * On exit: + * out[i] < out[i] + 2^107. */ +static void felem_diff_zero107(felem out, const felem in) { + /* In order to prevent underflow, we add 0 mod p before subtracting. */ + out[0] += zero107[0]; + out[1] += zero107[1]; + out[2] += zero107[2]; + out[3] += zero107[3]; + + out[0] -= in[0]; + out[1] -= in[1]; + out[2] -= in[2]; + out[3] -= in[3]; +} + +/* longfelem_diff subtracts |in| from |out| + * On entry: + * in[i] < 7*2^67 + * On exit: + * out[i] < out[i] + 2^70 + 2^40. */ +static void longfelem_diff(longfelem out, const longfelem in) { + static const limb two70m8p6 = + (((limb)1) << 70) - (((limb)1) << 8) + (((limb)1) << 6); + static const limb two70p40 = (((limb)1) << 70) + (((limb)1) << 40); + static const limb two70 = (((limb)1) << 70); + static const limb two70m40m38p6 = (((limb)1) << 70) - (((limb)1) << 40) - + (((limb)1) << 38) + (((limb)1) << 6); + static const limb two70m6 = (((limb)1) << 70) - (((limb)1) << 6); + + /* add 0 mod p to avoid underflow */ + out[0] += two70m8p6; + out[1] += two70p40; + out[2] += two70; + out[3] += two70m40m38p6; + out[4] += two70m6; + out[5] += two70m6; + out[6] += two70m6; + out[7] += two70m6; + + /* in[i] < 7*2^67 < 2^70 - 2^40 - 2^38 + 2^6 */ + out[0] -= in[0]; + out[1] -= in[1]; + out[2] -= in[2]; + out[3] -= in[3]; + out[4] -= in[4]; + out[5] -= in[5]; + out[6] -= in[6]; + out[7] -= in[7]; +} + +#define two64m0 (((limb)1) << 64) - 1 +#define two110p32m0 (((limb)1) << 110) + (((limb)1) << 32) - 1 +#define two64m46 (((limb)1) << 64) - (((limb)1) << 46) +#define two64m32 (((limb)1) << 64) - (((limb)1) << 32) + +/* zero110 is 0 mod p. */ +static const felem zero110 = {two64m0, two110p32m0, two64m46, two64m32}; + +/* felem_shrink converts an felem into a smallfelem. The result isn't quite + * minimal as the value may be greater than p. + * + * On entry: + * in[i] < 2^109 + * On exit: + * out[i] < 2^64. */ +static void felem_shrink(smallfelem out, const felem in) { + felem tmp; + u64 a, b, mask; + s64 high, low; + static const u64 kPrime3Test = 0x7fffffff00000001ul; /* 2^63 - 2^32 + 1 */ + + /* Carry 2->3 */ + tmp[3] = zero110[3] + in[3] + ((u64)(in[2] >> 64)); + /* tmp[3] < 2^110 */ + + tmp[2] = zero110[2] + (u64)in[2]; + tmp[0] = zero110[0] + in[0]; + tmp[1] = zero110[1] + in[1]; + /* tmp[0] < 2**110, tmp[1] < 2^111, tmp[2] < 2**65 */ + + /* We perform two partial reductions where we eliminate the high-word of + * tmp[3]. We don't update the other words till the end. */ + a = tmp[3] >> 64; /* a < 2^46 */ + tmp[3] = (u64)tmp[3]; + tmp[3] -= a; + tmp[3] += ((limb)a) << 32; + /* tmp[3] < 2^79 */ + + b = a; + a = tmp[3] >> 64; /* a < 2^15 */ + b += a; /* b < 2^46 + 2^15 < 2^47 */ + tmp[3] = (u64)tmp[3]; + tmp[3] -= a; + tmp[3] += ((limb)a) << 32; + /* tmp[3] < 2^64 + 2^47 */ + + /* This adjusts the other two words to complete the two partial + * reductions. */ + tmp[0] += b; + tmp[1] -= (((limb)b) << 32); + + /* In order to make space in tmp[3] for the carry from 2 -> 3, we + * conditionally subtract kPrime if tmp[3] is large enough. */ + high = tmp[3] >> 64; + /* As tmp[3] < 2^65, high is either 1 or 0 */ + high = ~(high - 1); + /* high is: + * all ones if the high word of tmp[3] is 1 + * all zeros if the high word of tmp[3] if 0 */ + low = tmp[3]; + mask = low >> 63; + /* mask is: + * all ones if the MSB of low is 1 + * all zeros if the MSB of low if 0 */ + low &= bottom63bits; + low -= kPrime3Test; + /* if low was greater than kPrime3Test then the MSB is zero */ + low = ~low; + low >>= 63; + /* low is: + * all ones if low was > kPrime3Test + * all zeros if low was <= kPrime3Test */ + mask = (mask & low) | high; + tmp[0] -= mask & kPrime[0]; + tmp[1] -= mask & kPrime[1]; + /* kPrime[2] is zero, so omitted */ + tmp[3] -= mask & kPrime[3]; + /* tmp[3] < 2**64 - 2**32 + 1 */ + + tmp[1] += ((u64)(tmp[0] >> 64)); + tmp[0] = (u64)tmp[0]; + tmp[2] += ((u64)(tmp[1] >> 64)); + tmp[1] = (u64)tmp[1]; + tmp[3] += ((u64)(tmp[2] >> 64)); + tmp[2] = (u64)tmp[2]; + /* tmp[i] < 2^64 */ + + out[0] = tmp[0]; + out[1] = tmp[1]; + out[2] = tmp[2]; + out[3] = tmp[3]; +} + +/* smallfelem_expand converts a smallfelem to an felem */ +static void smallfelem_expand(felem out, const smallfelem in) { + out[0] = in[0]; + out[1] = in[1]; + out[2] = in[2]; + out[3] = in[3]; +} + +/* smallfelem_square sets |out| = |small|^2 + * On entry: + * small[i] < 2^64 + * On exit: + * out[i] < 7 * 2^64 < 2^67 */ +static void smallfelem_square(longfelem out, const smallfelem small) { + limb a; + u64 high, low; + + a = ((uint128_t)small[0]) * small[0]; + low = a; + high = a >> 64; + out[0] = low; + out[1] = high; + + a = ((uint128_t)small[0]) * small[1]; + low = a; + high = a >> 64; + out[1] += low; + out[1] += low; + out[2] = high; + + a = ((uint128_t)small[0]) * small[2]; + low = a; + high = a >> 64; + out[2] += low; + out[2] *= 2; + out[3] = high; + + a = ((uint128_t)small[0]) * small[3]; + low = a; + high = a >> 64; + out[3] += low; + out[4] = high; + + a = ((uint128_t)small[1]) * small[2]; + low = a; + high = a >> 64; + out[3] += low; + out[3] *= 2; + out[4] += high; + + a = ((uint128_t)small[1]) * small[1]; + low = a; + high = a >> 64; + out[2] += low; + out[3] += high; + + a = ((uint128_t)small[1]) * small[3]; + low = a; + high = a >> 64; + out[4] += low; + out[4] *= 2; + out[5] = high; + + a = ((uint128_t)small[2]) * small[3]; + low = a; + high = a >> 64; + out[5] += low; + out[5] *= 2; + out[6] = high; + out[6] += high; + + a = ((uint128_t)small[2]) * small[2]; + low = a; + high = a >> 64; + out[4] += low; + out[5] += high; + + a = ((uint128_t)small[3]) * small[3]; + low = a; + high = a >> 64; + out[6] += low; + out[7] = high; +} + +/*felem_square sets |out| = |in|^2 + * On entry: + * in[i] < 2^109 + * On exit: + * out[i] < 7 * 2^64 < 2^67. */ +static void felem_square(longfelem out, const felem in) { + u64 small[4]; + felem_shrink(small, in); + smallfelem_square(out, small); +} + +/* smallfelem_mul sets |out| = |small1| * |small2| + * On entry: + * small1[i] < 2^64 + * small2[i] < 2^64 + * On exit: + * out[i] < 7 * 2^64 < 2^67. */ +static void smallfelem_mul(longfelem out, const smallfelem small1, + const smallfelem small2) { + limb a; + u64 high, low; + + a = ((uint128_t)small1[0]) * small2[0]; + low = a; + high = a >> 64; + out[0] = low; + out[1] = high; + + a = ((uint128_t)small1[0]) * small2[1]; + low = a; + high = a >> 64; + out[1] += low; + out[2] = high; + + a = ((uint128_t)small1[1]) * small2[0]; + low = a; + high = a >> 64; + out[1] += low; + out[2] += high; + + a = ((uint128_t)small1[0]) * small2[2]; + low = a; + high = a >> 64; + out[2] += low; + out[3] = high; + + a = ((uint128_t)small1[1]) * small2[1]; + low = a; + high = a >> 64; + out[2] += low; + out[3] += high; + + a = ((uint128_t)small1[2]) * small2[0]; + low = a; + high = a >> 64; + out[2] += low; + out[3] += high; + + a = ((uint128_t)small1[0]) * small2[3]; + low = a; + high = a >> 64; + out[3] += low; + out[4] = high; + + a = ((uint128_t)small1[1]) * small2[2]; + low = a; + high = a >> 64; + out[3] += low; + out[4] += high; + + a = ((uint128_t)small1[2]) * small2[1]; + low = a; + high = a >> 64; + out[3] += low; + out[4] += high; + + a = ((uint128_t)small1[3]) * small2[0]; + low = a; + high = a >> 64; + out[3] += low; + out[4] += high; + + a = ((uint128_t)small1[1]) * small2[3]; + low = a; + high = a >> 64; + out[4] += low; + out[5] = high; + + a = ((uint128_t)small1[2]) * small2[2]; + low = a; + high = a >> 64; + out[4] += low; + out[5] += high; + + a = ((uint128_t)small1[3]) * small2[1]; + low = a; + high = a >> 64; + out[4] += low; + out[5] += high; + + a = ((uint128_t)small1[2]) * small2[3]; + low = a; + high = a >> 64; + out[5] += low; + out[6] = high; + + a = ((uint128_t)small1[3]) * small2[2]; + low = a; + high = a >> 64; + out[5] += low; + out[6] += high; + + a = ((uint128_t)small1[3]) * small2[3]; + low = a; + high = a >> 64; + out[6] += low; + out[7] = high; +} + +/* felem_mul sets |out| = |in1| * |in2| + * On entry: + * in1[i] < 2^109 + * in2[i] < 2^109 + * On exit: + * out[i] < 7 * 2^64 < 2^67 */ +static void felem_mul(longfelem out, const felem in1, const felem in2) { + smallfelem small1, small2; + felem_shrink(small1, in1); + felem_shrink(small2, in2); + smallfelem_mul(out, small1, small2); +} + +/* felem_small_mul sets |out| = |small1| * |in2| + * On entry: + * small1[i] < 2^64 + * in2[i] < 2^109 + * On exit: + * out[i] < 7 * 2^64 < 2^67 */ +static void felem_small_mul(longfelem out, const smallfelem small1, + const felem in2) { + smallfelem small2; + felem_shrink(small2, in2); + smallfelem_mul(out, small1, small2); +} + +#define two100m36m4 (((limb)1) << 100) - (((limb)1) << 36) - (((limb)1) << 4) +#define two100 (((limb)1) << 100) +#define two100m36p4 (((limb)1) << 100) - (((limb)1) << 36) + (((limb)1) << 4) + +/* zero100 is 0 mod p */ +static const felem zero100 = {two100m36m4, two100, two100m36p4, two100m36p4}; + +/* Internal function for the different flavours of felem_reduce. + * felem_reduce_ reduces the higher coefficients in[4]-in[7]. + * On entry: + * out[0] >= in[6] + 2^32*in[6] + in[7] + 2^32*in[7] + * out[1] >= in[7] + 2^32*in[4] + * out[2] >= in[5] + 2^32*in[5] + * out[3] >= in[4] + 2^32*in[5] + 2^32*in[6] + * On exit: + * out[0] <= out[0] + in[4] + 2^32*in[5] + * out[1] <= out[1] + in[5] + 2^33*in[6] + * out[2] <= out[2] + in[7] + 2*in[6] + 2^33*in[7] + * out[3] <= out[3] + 2^32*in[4] + 3*in[7] */ +static void felem_reduce_(felem out, const longfelem in) { + int128_t c; + /* combine common terms from below */ + c = in[4] + (in[5] << 32); + out[0] += c; + out[3] -= c; + + c = in[5] - in[7]; + out[1] += c; + out[2] -= c; + + /* the remaining terms */ + /* 256: [(0,1),(96,-1),(192,-1),(224,1)] */ + out[1] -= (in[4] << 32); + out[3] += (in[4] << 32); + + /* 320: [(32,1),(64,1),(128,-1),(160,-1),(224,-1)] */ + out[2] -= (in[5] << 32); + + /* 384: [(0,-1),(32,-1),(96,2),(128,2),(224,-1)] */ + out[0] -= in[6]; + out[0] -= (in[6] << 32); + out[1] += (in[6] << 33); + out[2] += (in[6] * 2); + out[3] -= (in[6] << 32); + + /* 448: [(0,-1),(32,-1),(64,-1),(128,1),(160,2),(192,3)] */ + out[0] -= in[7]; + out[0] -= (in[7] << 32); + out[2] += (in[7] << 33); + out[3] += (in[7] * 3); +} + +/* felem_reduce converts a longfelem into an felem. + * To be called directly after felem_square or felem_mul. + * On entry: + * in[0] < 2^64, in[1] < 3*2^64, in[2] < 5*2^64, in[3] < 7*2^64 + * in[4] < 7*2^64, in[5] < 5*2^64, in[6] < 3*2^64, in[7] < 2*64 + * On exit: + * out[i] < 2^101 */ +static void felem_reduce(felem out, const longfelem in) { + out[0] = zero100[0] + in[0]; + out[1] = zero100[1] + in[1]; + out[2] = zero100[2] + in[2]; + out[3] = zero100[3] + in[3]; + + felem_reduce_(out, in); + + /* out[0] > 2^100 - 2^36 - 2^4 - 3*2^64 - 3*2^96 - 2^64 - 2^96 > 0 + * out[1] > 2^100 - 2^64 - 7*2^96 > 0 + * out[2] > 2^100 - 2^36 + 2^4 - 5*2^64 - 5*2^96 > 0 + * out[3] > 2^100 - 2^36 + 2^4 - 7*2^64 - 5*2^96 - 3*2^96 > 0 + * + * out[0] < 2^100 + 2^64 + 7*2^64 + 5*2^96 < 2^101 + * out[1] < 2^100 + 3*2^64 + 5*2^64 + 3*2^97 < 2^101 + * out[2] < 2^100 + 5*2^64 + 2^64 + 3*2^65 + 2^97 < 2^101 + * out[3] < 2^100 + 7*2^64 + 7*2^96 + 3*2^64 < 2^101 */ +} + +/* felem_reduce_zero105 converts a larger longfelem into an felem. + * On entry: + * in[0] < 2^71 + * On exit: + * out[i] < 2^106 */ +static void felem_reduce_zero105(felem out, const longfelem in) { + out[0] = zero105[0] + in[0]; + out[1] = zero105[1] + in[1]; + out[2] = zero105[2] + in[2]; + out[3] = zero105[3] + in[3]; + + felem_reduce_(out, in); + + /* out[0] > 2^105 - 2^41 - 2^9 - 2^71 - 2^103 - 2^71 - 2^103 > 0 + * out[1] > 2^105 - 2^71 - 2^103 > 0 + * out[2] > 2^105 - 2^41 + 2^9 - 2^71 - 2^103 > 0 + * out[3] > 2^105 - 2^41 + 2^9 - 2^71 - 2^103 - 2^103 > 0 + * + * out[0] < 2^105 + 2^71 + 2^71 + 2^103 < 2^106 + * out[1] < 2^105 + 2^71 + 2^71 + 2^103 < 2^106 + * out[2] < 2^105 + 2^71 + 2^71 + 2^71 + 2^103 < 2^106 + * out[3] < 2^105 + 2^71 + 2^103 + 2^71 < 2^106 */ +} + +/* subtract_u64 sets *result = *result - v and *carry to one if the + * subtraction underflowed. */ +static void subtract_u64(u64 *result, u64 *carry, u64 v) { + uint128_t r = *result; + r -= v; + *carry = (r >> 64) & 1; + *result = (u64)r; +} + +/* felem_contract converts |in| to its unique, minimal representation. On + * entry: in[i] < 2^109. */ +static void felem_contract(smallfelem out, const felem in) { + u64 all_equal_so_far = 0, result = 0; + + felem_shrink(out, in); + /* small is minimal except that the value might be > p */ + + all_equal_so_far--; + /* We are doing a constant time test if out >= kPrime. We need to compare + * each u64, from most-significant to least significant. For each one, if + * all words so far have been equal (m is all ones) then a non-equal + * result is the answer. Otherwise we continue. */ + size_t i; + for (i = 3; i < 4; i--) { + u64 equal; + uint128_t a = ((uint128_t)kPrime[i]) - out[i]; + /* if out[i] > kPrime[i] then a will underflow and the high 64-bits + * will all be set. */ + result |= all_equal_so_far & ((u64)(a >> 64)); + + /* if kPrime[i] == out[i] then |equal| will be all zeros and the + * decrement will make it all ones. */ + equal = kPrime[i] ^ out[i]; + equal--; + equal &= equal << 32; + equal &= equal << 16; + equal &= equal << 8; + equal &= equal << 4; + equal &= equal << 2; + equal &= equal << 1; + equal = ((s64)equal) >> 63; + + all_equal_so_far &= equal; + } + + /* if all_equal_so_far is still all ones then the two values are equal + * and so out >= kPrime is true. */ + result |= all_equal_so_far; + + /* if out >= kPrime then we subtract kPrime. */ + u64 carry; + subtract_u64(&out[0], &carry, result & kPrime[0]); + subtract_u64(&out[1], &carry, carry); + subtract_u64(&out[2], &carry, carry); + subtract_u64(&out[3], &carry, carry); + + subtract_u64(&out[1], &carry, result & kPrime[1]); + subtract_u64(&out[2], &carry, carry); + subtract_u64(&out[3], &carry, carry); + + subtract_u64(&out[2], &carry, result & kPrime[2]); + subtract_u64(&out[3], &carry, carry); + + subtract_u64(&out[3], &carry, result & kPrime[3]); +} + +/* felem_is_zero returns a limb with all bits set if |in| == 0 (mod p) and 0 + * otherwise. + * On entry: + * small[i] < 2^64 */ +static limb smallfelem_is_zero(const smallfelem small) { + limb result; + u64 is_p; + + u64 is_zero = small[0] | small[1] | small[2] | small[3]; + is_zero--; + is_zero &= is_zero << 32; + is_zero &= is_zero << 16; + is_zero &= is_zero << 8; + is_zero &= is_zero << 4; + is_zero &= is_zero << 2; + is_zero &= is_zero << 1; + is_zero = ((s64)is_zero) >> 63; + + is_p = (small[0] ^ kPrime[0]) | (small[1] ^ kPrime[1]) | + (small[2] ^ kPrime[2]) | (small[3] ^ kPrime[3]); + is_p--; + is_p &= is_p << 32; + is_p &= is_p << 16; + is_p &= is_p << 8; + is_p &= is_p << 4; + is_p &= is_p << 2; + is_p &= is_p << 1; + is_p = ((s64)is_p) >> 63; + + is_zero |= is_p; + + result = is_zero; + result |= ((limb)is_zero) << 64; + return result; +} + +/* felem_inv calculates |out| = |in|^{-1} + * + * Based on Fermat's Little Theorem: + * a^p = a (mod p) + * a^{p-1} = 1 (mod p) + * a^{p-2} = a^{-1} (mod p) */ +static void felem_inv(felem out, const felem in) { + felem ftmp, ftmp2; + /* each e_I will hold |in|^{2^I - 1} */ + felem e2, e4, e8, e16, e32, e64; + longfelem tmp; + size_t i; + + felem_square(tmp, in); + felem_reduce(ftmp, tmp); /* 2^1 */ + felem_mul(tmp, in, ftmp); + felem_reduce(ftmp, tmp); /* 2^2 - 2^0 */ + felem_assign(e2, ftmp); + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); /* 2^3 - 2^1 */ + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); /* 2^4 - 2^2 */ + felem_mul(tmp, ftmp, e2); + felem_reduce(ftmp, tmp); /* 2^4 - 2^0 */ + felem_assign(e4, ftmp); + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); /* 2^5 - 2^1 */ + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); /* 2^6 - 2^2 */ + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); /* 2^7 - 2^3 */ + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); /* 2^8 - 2^4 */ + felem_mul(tmp, ftmp, e4); + felem_reduce(ftmp, tmp); /* 2^8 - 2^0 */ + felem_assign(e8, ftmp); + for (i = 0; i < 8; i++) { + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); + } /* 2^16 - 2^8 */ + felem_mul(tmp, ftmp, e8); + felem_reduce(ftmp, tmp); /* 2^16 - 2^0 */ + felem_assign(e16, ftmp); + for (i = 0; i < 16; i++) { + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); + } /* 2^32 - 2^16 */ + felem_mul(tmp, ftmp, e16); + felem_reduce(ftmp, tmp); /* 2^32 - 2^0 */ + felem_assign(e32, ftmp); + for (i = 0; i < 32; i++) { + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); + } /* 2^64 - 2^32 */ + felem_assign(e64, ftmp); + felem_mul(tmp, ftmp, in); + felem_reduce(ftmp, tmp); /* 2^64 - 2^32 + 2^0 */ + for (i = 0; i < 192; i++) { + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); + } /* 2^256 - 2^224 + 2^192 */ + + felem_mul(tmp, e64, e32); + felem_reduce(ftmp2, tmp); /* 2^64 - 2^0 */ + for (i = 0; i < 16; i++) { + felem_square(tmp, ftmp2); + felem_reduce(ftmp2, tmp); + } /* 2^80 - 2^16 */ + felem_mul(tmp, ftmp2, e16); + felem_reduce(ftmp2, tmp); /* 2^80 - 2^0 */ + for (i = 0; i < 8; i++) { + felem_square(tmp, ftmp2); + felem_reduce(ftmp2, tmp); + } /* 2^88 - 2^8 */ + felem_mul(tmp, ftmp2, e8); + felem_reduce(ftmp2, tmp); /* 2^88 - 2^0 */ + for (i = 0; i < 4; i++) { + felem_square(tmp, ftmp2); + felem_reduce(ftmp2, tmp); + } /* 2^92 - 2^4 */ + felem_mul(tmp, ftmp2, e4); + felem_reduce(ftmp2, tmp); /* 2^92 - 2^0 */ + felem_square(tmp, ftmp2); + felem_reduce(ftmp2, tmp); /* 2^93 - 2^1 */ + felem_square(tmp, ftmp2); + felem_reduce(ftmp2, tmp); /* 2^94 - 2^2 */ + felem_mul(tmp, ftmp2, e2); + felem_reduce(ftmp2, tmp); /* 2^94 - 2^0 */ + felem_square(tmp, ftmp2); + felem_reduce(ftmp2, tmp); /* 2^95 - 2^1 */ + felem_square(tmp, ftmp2); + felem_reduce(ftmp2, tmp); /* 2^96 - 2^2 */ + felem_mul(tmp, ftmp2, in); + felem_reduce(ftmp2, tmp); /* 2^96 - 3 */ + + felem_mul(tmp, ftmp2, ftmp); + felem_reduce(out, tmp); /* 2^256 - 2^224 + 2^192 + 2^96 - 3 */ +} + +/* Group operations + * ---------------- + * + * Building on top of the field operations we have the operations on the + * elliptic curve group itself. Points on the curve are represented in Jacobian + * coordinates. */ + +/* point_double calculates 2*(x_in, y_in, z_in) + * + * The method is taken from: + * http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b + * + * Outputs can equal corresponding inputs, i.e., x_out == x_in is allowed. + * while x_out == y_in is not (maybe this works, but it's not tested). */ +static void point_double(felem x_out, felem y_out, felem z_out, + const felem x_in, const felem y_in, const felem z_in) { + longfelem tmp, tmp2; + felem delta, gamma, beta, alpha, ftmp, ftmp2; + smallfelem small1, small2; + + felem_assign(ftmp, x_in); + /* ftmp[i] < 2^106 */ + felem_assign(ftmp2, x_in); + /* ftmp2[i] < 2^106 */ + + /* delta = z^2 */ + felem_square(tmp, z_in); + felem_reduce(delta, tmp); + /* delta[i] < 2^101 */ + + /* gamma = y^2 */ + felem_square(tmp, y_in); + felem_reduce(gamma, tmp); + /* gamma[i] < 2^101 */ + felem_shrink(small1, gamma); + + /* beta = x*gamma */ + felem_small_mul(tmp, small1, x_in); + felem_reduce(beta, tmp); + /* beta[i] < 2^101 */ + + /* alpha = 3*(x-delta)*(x+delta) */ + felem_diff(ftmp, delta); + /* ftmp[i] < 2^105 + 2^106 < 2^107 */ + felem_sum(ftmp2, delta); + /* ftmp2[i] < 2^105 + 2^106 < 2^107 */ + felem_scalar(ftmp2, 3); + /* ftmp2[i] < 3 * 2^107 < 2^109 */ + felem_mul(tmp, ftmp, ftmp2); + felem_reduce(alpha, tmp); + /* alpha[i] < 2^101 */ + felem_shrink(small2, alpha); + + /* x' = alpha^2 - 8*beta */ + smallfelem_square(tmp, small2); + felem_reduce(x_out, tmp); + felem_assign(ftmp, beta); + felem_scalar(ftmp, 8); + /* ftmp[i] < 8 * 2^101 = 2^104 */ + felem_diff(x_out, ftmp); + /* x_out[i] < 2^105 + 2^101 < 2^106 */ + + /* z' = (y + z)^2 - gamma - delta */ + felem_sum(delta, gamma); + /* delta[i] < 2^101 + 2^101 = 2^102 */ + felem_assign(ftmp, y_in); + felem_sum(ftmp, z_in); + /* ftmp[i] < 2^106 + 2^106 = 2^107 */ + felem_square(tmp, ftmp); + felem_reduce(z_out, tmp); + felem_diff(z_out, delta); + /* z_out[i] < 2^105 + 2^101 < 2^106 */ + + /* y' = alpha*(4*beta - x') - 8*gamma^2 */ + felem_scalar(beta, 4); + /* beta[i] < 4 * 2^101 = 2^103 */ + felem_diff_zero107(beta, x_out); + /* beta[i] < 2^107 + 2^103 < 2^108 */ + felem_small_mul(tmp, small2, beta); + /* tmp[i] < 7 * 2^64 < 2^67 */ + smallfelem_square(tmp2, small1); + /* tmp2[i] < 7 * 2^64 */ + longfelem_scalar(tmp2, 8); + /* tmp2[i] < 8 * 7 * 2^64 = 7 * 2^67 */ + longfelem_diff(tmp, tmp2); + /* tmp[i] < 2^67 + 2^70 + 2^40 < 2^71 */ + felem_reduce_zero105(y_out, tmp); + /* y_out[i] < 2^106 */ +} + +/* point_double_small is the same as point_double, except that it operates on + * smallfelems. */ +static void point_double_small(smallfelem x_out, smallfelem y_out, + smallfelem z_out, const smallfelem x_in, + const smallfelem y_in, const smallfelem z_in) { + felem felem_x_out, felem_y_out, felem_z_out; + felem felem_x_in, felem_y_in, felem_z_in; + + smallfelem_expand(felem_x_in, x_in); + smallfelem_expand(felem_y_in, y_in); + smallfelem_expand(felem_z_in, z_in); + point_double(felem_x_out, felem_y_out, felem_z_out, felem_x_in, felem_y_in, + felem_z_in); + felem_shrink(x_out, felem_x_out); + felem_shrink(y_out, felem_y_out); + felem_shrink(z_out, felem_z_out); +} + +/* copy_conditional copies in to out iff mask is all ones. */ +static void copy_conditional(felem out, const felem in, limb mask) { + size_t i; + for (i = 0; i < NLIMBS; ++i) { + const limb tmp = mask & (in[i] ^ out[i]); + out[i] ^= tmp; + } +} + +/* copy_small_conditional copies in to out iff mask is all ones. */ +static void copy_small_conditional(felem out, const smallfelem in, limb mask) { + size_t i; + const u64 mask64 = mask; + for (i = 0; i < NLIMBS; ++i) { + out[i] = ((limb)(in[i] & mask64)) | (out[i] & ~mask); + } +} + +/* point_add calcuates (x1, y1, z1) + (x2, y2, z2) + * + * The method is taken from: + * http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl, + * adapted for mixed addition (z2 = 1, or z2 = 0 for the point at infinity). + * + * This function includes a branch for checking whether the two input points + * are equal, (while not equal to the point at infinity). This case never + * happens during single point multiplication, so there is no timing leak for + * ECDH or ECDSA signing. */ +static void point_add(felem x3, felem y3, felem z3, const felem x1, + const felem y1, const felem z1, const int mixed, + const smallfelem x2, const smallfelem y2, + const smallfelem z2) { + felem ftmp, ftmp2, ftmp3, ftmp4, ftmp5, ftmp6, x_out, y_out, z_out; + longfelem tmp, tmp2; + smallfelem small1, small2, small3, small4, small5; + limb x_equal, y_equal, z1_is_zero, z2_is_zero; + + felem_shrink(small3, z1); + + z1_is_zero = smallfelem_is_zero(small3); + z2_is_zero = smallfelem_is_zero(z2); + + /* ftmp = z1z1 = z1**2 */ + smallfelem_square(tmp, small3); + felem_reduce(ftmp, tmp); + /* ftmp[i] < 2^101 */ + felem_shrink(small1, ftmp); + + if (!mixed) { + /* ftmp2 = z2z2 = z2**2 */ + smallfelem_square(tmp, z2); + felem_reduce(ftmp2, tmp); + /* ftmp2[i] < 2^101 */ + felem_shrink(small2, ftmp2); + + felem_shrink(small5, x1); + + /* u1 = ftmp3 = x1*z2z2 */ + smallfelem_mul(tmp, small5, small2); + felem_reduce(ftmp3, tmp); + /* ftmp3[i] < 2^101 */ + + /* ftmp5 = z1 + z2 */ + felem_assign(ftmp5, z1); + felem_small_sum(ftmp5, z2); + /* ftmp5[i] < 2^107 */ + + /* ftmp5 = (z1 + z2)**2 - (z1z1 + z2z2) = 2z1z2 */ + felem_square(tmp, ftmp5); + felem_reduce(ftmp5, tmp); + /* ftmp2 = z2z2 + z1z1 */ + felem_sum(ftmp2, ftmp); + /* ftmp2[i] < 2^101 + 2^101 = 2^102 */ + felem_diff(ftmp5, ftmp2); + /* ftmp5[i] < 2^105 + 2^101 < 2^106 */ + + /* ftmp2 = z2 * z2z2 */ + smallfelem_mul(tmp, small2, z2); + felem_reduce(ftmp2, tmp); + + /* s1 = ftmp2 = y1 * z2**3 */ + felem_mul(tmp, y1, ftmp2); + felem_reduce(ftmp6, tmp); + /* ftmp6[i] < 2^101 */ + } else { + /* We'll assume z2 = 1 (special case z2 = 0 is handled later). */ + + /* u1 = ftmp3 = x1*z2z2 */ + felem_assign(ftmp3, x1); + /* ftmp3[i] < 2^106 */ + + /* ftmp5 = 2z1z2 */ + felem_assign(ftmp5, z1); + felem_scalar(ftmp5, 2); + /* ftmp5[i] < 2*2^106 = 2^107 */ + + /* s1 = ftmp2 = y1 * z2**3 */ + felem_assign(ftmp6, y1); + /* ftmp6[i] < 2^106 */ + } + + /* u2 = x2*z1z1 */ + smallfelem_mul(tmp, x2, small1); + felem_reduce(ftmp4, tmp); + + /* h = ftmp4 = u2 - u1 */ + felem_diff_zero107(ftmp4, ftmp3); + /* ftmp4[i] < 2^107 + 2^101 < 2^108 */ + felem_shrink(small4, ftmp4); + + x_equal = smallfelem_is_zero(small4); + + /* z_out = ftmp5 * h */ + felem_small_mul(tmp, small4, ftmp5); + felem_reduce(z_out, tmp); + /* z_out[i] < 2^101 */ + + /* ftmp = z1 * z1z1 */ + smallfelem_mul(tmp, small1, small3); + felem_reduce(ftmp, tmp); + + /* s2 = tmp = y2 * z1**3 */ + felem_small_mul(tmp, y2, ftmp); + felem_reduce(ftmp5, tmp); + + /* r = ftmp5 = (s2 - s1)*2 */ + felem_diff_zero107(ftmp5, ftmp6); + /* ftmp5[i] < 2^107 + 2^107 = 2^108 */ + felem_scalar(ftmp5, 2); + /* ftmp5[i] < 2^109 */ + felem_shrink(small1, ftmp5); + y_equal = smallfelem_is_zero(small1); + + if (x_equal && y_equal && !z1_is_zero && !z2_is_zero) { + point_double(x3, y3, z3, x1, y1, z1); + return; + } + + /* I = ftmp = (2h)**2 */ + felem_assign(ftmp, ftmp4); + felem_scalar(ftmp, 2); + /* ftmp[i] < 2*2^108 = 2^109 */ + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); + + /* J = ftmp2 = h * I */ + felem_mul(tmp, ftmp4, ftmp); + felem_reduce(ftmp2, tmp); + + /* V = ftmp4 = U1 * I */ + felem_mul(tmp, ftmp3, ftmp); + felem_reduce(ftmp4, tmp); + + /* x_out = r**2 - J - 2V */ + smallfelem_square(tmp, small1); + felem_reduce(x_out, tmp); + felem_assign(ftmp3, ftmp4); + felem_scalar(ftmp4, 2); + felem_sum(ftmp4, ftmp2); + /* ftmp4[i] < 2*2^101 + 2^101 < 2^103 */ + felem_diff(x_out, ftmp4); + /* x_out[i] < 2^105 + 2^101 */ + + /* y_out = r(V-x_out) - 2 * s1 * J */ + felem_diff_zero107(ftmp3, x_out); + /* ftmp3[i] < 2^107 + 2^101 < 2^108 */ + felem_small_mul(tmp, small1, ftmp3); + felem_mul(tmp2, ftmp6, ftmp2); + longfelem_scalar(tmp2, 2); + /* tmp2[i] < 2*2^67 = 2^68 */ + longfelem_diff(tmp, tmp2); + /* tmp[i] < 2^67 + 2^70 + 2^40 < 2^71 */ + felem_reduce_zero105(y_out, tmp); + /* y_out[i] < 2^106 */ + + copy_small_conditional(x_out, x2, z1_is_zero); + copy_conditional(x_out, x1, z2_is_zero); + copy_small_conditional(y_out, y2, z1_is_zero); + copy_conditional(y_out, y1, z2_is_zero); + copy_small_conditional(z_out, z2, z1_is_zero); + copy_conditional(z_out, z1, z2_is_zero); + felem_assign(x3, x_out); + felem_assign(y3, y_out); + felem_assign(z3, z_out); +} + +/* point_add_small is the same as point_add, except that it operates on + * smallfelems. */ +static void point_add_small(smallfelem x3, smallfelem y3, smallfelem z3, + smallfelem x1, smallfelem y1, smallfelem z1, + smallfelem x2, smallfelem y2, smallfelem z2) { + felem felem_x3, felem_y3, felem_z3; + felem felem_x1, felem_y1, felem_z1; + smallfelem_expand(felem_x1, x1); + smallfelem_expand(felem_y1, y1); + smallfelem_expand(felem_z1, z1); + point_add(felem_x3, felem_y3, felem_z3, felem_x1, felem_y1, felem_z1, 0, x2, + y2, z2); + felem_shrink(x3, felem_x3); + felem_shrink(y3, felem_y3); + felem_shrink(z3, felem_z3); +} + +/* Base point pre computation + * -------------------------- + * + * Two different sorts of precomputed tables are used in the following code. + * Each contain various points on the curve, where each point is three field + * elements (x, y, z). + * + * For the base point table, z is usually 1 (0 for the point at infinity). + * This table has 2 * 16 elements, starting with the following: + * index | bits | point + * ------+---------+------------------------------ + * 0 | 0 0 0 0 | 0G + * 1 | 0 0 0 1 | 1G + * 2 | 0 0 1 0 | 2^64G + * 3 | 0 0 1 1 | (2^64 + 1)G + * 4 | 0 1 0 0 | 2^128G + * 5 | 0 1 0 1 | (2^128 + 1)G + * 6 | 0 1 1 0 | (2^128 + 2^64)G + * 7 | 0 1 1 1 | (2^128 + 2^64 + 1)G + * 8 | 1 0 0 0 | 2^192G + * 9 | 1 0 0 1 | (2^192 + 1)G + * 10 | 1 0 1 0 | (2^192 + 2^64)G + * 11 | 1 0 1 1 | (2^192 + 2^64 + 1)G + * 12 | 1 1 0 0 | (2^192 + 2^128)G + * 13 | 1 1 0 1 | (2^192 + 2^128 + 1)G + * 14 | 1 1 1 0 | (2^192 + 2^128 + 2^64)G + * 15 | 1 1 1 1 | (2^192 + 2^128 + 2^64 + 1)G + * followed by a copy of this with each element multiplied by 2^32. + * + * The reason for this is so that we can clock bits into four different + * locations when doing simple scalar multiplies against the base point, + * and then another four locations using the second 16 elements. + * + * Tables for other points have table[i] = iG for i in 0 .. 16. */ + +/* g_pre_comp is the table of precomputed base points */ +static const smallfelem g_pre_comp[2][16][3] = { + {{{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, + {{0xf4a13945d898c296, 0x77037d812deb33a0, 0xf8bce6e563a440f2, + 0x6b17d1f2e12c4247}, + {0xcbb6406837bf51f5, 0x2bce33576b315ece, 0x8ee7eb4a7c0f9e16, + 0x4fe342e2fe1a7f9b}, + {1, 0, 0, 0}}, + {{0x90e75cb48e14db63, 0x29493baaad651f7e, 0x8492592e326e25de, + 0x0fa822bc2811aaa5}, + {0xe41124545f462ee7, 0x34b1a65050fe82f5, 0x6f4ad4bcb3df188b, + 0xbff44ae8f5dba80d}, + {1, 0, 0, 0}}, + {{0x93391ce2097992af, 0xe96c98fd0d35f1fa, 0xb257c0de95e02789, + 0x300a4bbc89d6726f}, + {0xaa54a291c08127a0, 0x5bb1eeada9d806a5, 0x7f1ddb25ff1e3c6f, + 0x72aac7e0d09b4644}, + {1, 0, 0, 0}}, + {{0x57c84fc9d789bd85, 0xfc35ff7dc297eac3, 0xfb982fd588c6766e, + 0x447d739beedb5e67}, + {0x0c7e33c972e25b32, 0x3d349b95a7fae500, 0xe12e9d953a4aaff7, + 0x2d4825ab834131ee}, + {1, 0, 0, 0}}, + {{0x13949c932a1d367f, 0xef7fbd2b1a0a11b7, 0xddc6068bb91dfc60, + 0xef9519328a9c72ff}, + {0x196035a77376d8a8, 0x23183b0895ca1740, 0xc1ee9807022c219c, + 0x611e9fc37dbb2c9b}, + {1, 0, 0, 0}}, + {{0xcae2b1920b57f4bc, 0x2936df5ec6c9bc36, 0x7dea6482e11238bf, + 0x550663797b51f5d8}, + {0x44ffe216348a964c, 0x9fb3d576dbdefbe1, 0x0afa40018d9d50e5, + 0x157164848aecb851}, + {1, 0, 0, 0}}, + {{0xe48ecafffc5cde01, 0x7ccd84e70d715f26, 0xa2e8f483f43e4391, + 0xeb5d7745b21141ea}, + {0xcac917e2731a3479, 0x85f22cfe2844b645, 0x0990e6a158006cee, + 0xeafd72ebdbecc17b}, + {1, 0, 0, 0}}, + {{0x6cf20ffb313728be, 0x96439591a3c6b94a, 0x2736ff8344315fc5, + 0xa6d39677a7849276}, + {0xf2bab833c357f5f4, 0x824a920c2284059b, 0x66b8babd2d27ecdf, + 0x674f84749b0b8816}, + {1, 0, 0, 0}}, + {{0x2df48c04677c8a3e, 0x74e02f080203a56b, 0x31855f7db8c7fedb, + 0x4e769e7672c9ddad}, + {0xa4c36165b824bbb0, 0xfb9ae16f3b9122a5, 0x1ec0057206947281, + 0x42b99082de830663}, + {1, 0, 0, 0}}, + {{0x6ef95150dda868b9, 0xd1f89e799c0ce131, 0x7fdc1ca008a1c478, + 0x78878ef61c6ce04d}, + {0x9c62b9121fe0d976, 0x6ace570ebde08d4f, 0xde53142c12309def, + 0xb6cb3f5d7b72c321}, + {1, 0, 0, 0}}, + {{0x7f991ed2c31a3573, 0x5b82dd5bd54fb496, 0x595c5220812ffcae, + 0x0c88bc4d716b1287}, + {0x3a57bf635f48aca8, 0x7c8181f4df2564f3, 0x18d1b5b39c04e6aa, + 0xdd5ddea3f3901dc6}, + {1, 0, 0, 0}}, + {{0xe96a79fb3e72ad0c, 0x43a0a28c42ba792f, 0xefe0a423083e49f3, + 0x68f344af6b317466}, + {0xcdfe17db3fb24d4a, 0x668bfc2271f5c626, 0x604ed93c24d67ff3, + 0x31b9c405f8540a20}, + {1, 0, 0, 0}}, + {{0xd36b4789a2582e7f, 0x0d1a10144ec39c28, 0x663c62c3edbad7a0, + 0x4052bf4b6f461db9}, + {0x235a27c3188d25eb, 0xe724f33999bfcc5b, 0x862be6bd71d70cc8, + 0xfecf4d5190b0fc61}, + {1, 0, 0, 0}}, + {{0x74346c10a1d4cfac, 0xafdf5cc08526a7a4, 0x123202a8f62bff7a, + 0x1eddbae2c802e41a}, + {0x8fa0af2dd603f844, 0x36e06b7e4c701917, 0x0c45f45273db33a0, + 0x43104d86560ebcfc}, + {1, 0, 0, 0}}, + {{0x9615b5110d1d78e5, 0x66b0de3225c4744b, 0x0a4a46fb6aaf363a, + 0xb48e26b484f7a21c}, + {0x06ebb0f621a01b2d, 0xc004e4048b7b0f98, 0x64131bcdfed6f668, + 0xfac015404d4d3dab}, + {1, 0, 0, 0}}}, + {{{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, + {{0x3a5a9e22185a5943, 0x1ab919365c65dfb6, 0x21656b32262c71da, + 0x7fe36b40af22af89}, + {0xd50d152c699ca101, 0x74b3d5867b8af212, 0x9f09f40407dca6f1, + 0xe697d45825b63624}, + {1, 0, 0, 0}}, + {{0xa84aa9397512218e, 0xe9a521b074ca0141, 0x57880b3a18a2e902, + 0x4a5b506612a677a6}, + {0x0beada7a4c4f3840, 0x626db15419e26d9d, 0xc42604fbe1627d40, + 0xeb13461ceac089f1}, + {1, 0, 0, 0}}, + {{0xf9faed0927a43281, 0x5e52c4144103ecbc, 0xc342967aa815c857, + 0x0781b8291c6a220a}, + {0x5a8343ceeac55f80, 0x88f80eeee54a05e3, 0x97b2a14f12916434, + 0x690cde8df0151593}, + {1, 0, 0, 0}}, + {{0xaee9c75df7f82f2a, 0x9e4c35874afdf43a, 0xf5622df437371326, + 0x8a535f566ec73617}, + {0xc5f9a0ac223094b7, 0xcde533864c8c7669, 0x37e02819085a92bf, + 0x0455c08468b08bd7}, + {1, 0, 0, 0}}, + {{0x0c0a6e2c9477b5d9, 0xf9a4bf62876dc444, 0x5050a949b6cdc279, + 0x06bada7ab77f8276}, + {0xc8b4aed1ea48dac9, 0xdebd8a4b7ea1070f, 0x427d49101366eb70, + 0x5b476dfd0e6cb18a}, + {1, 0, 0, 0}}, + {{0x7c5c3e44278c340a, 0x4d54606812d66f3b, 0x29a751b1ae23c5d8, + 0x3e29864e8a2ec908}, + {0x142d2a6626dbb850, 0xad1744c4765bd780, 0x1f150e68e322d1ed, + 0x239b90ea3dc31e7e}, + {1, 0, 0, 0}}, + {{0x78c416527a53322a, 0x305dde6709776f8e, 0xdbcab759f8862ed4, + 0x820f4dd949f72ff7}, + {0x6cc544a62b5debd4, 0x75be5d937b4e8cc4, 0x1b481b1b215c14d3, + 0x140406ec783a05ec}, + {1, 0, 0, 0}}, + {{0x6a703f10e895df07, 0xfd75f3fa01876bd8, 0xeb5b06e70ce08ffe, + 0x68f6b8542783dfee}, + {0x90c76f8a78712655, 0xcf5293d2f310bf7f, 0xfbc8044dfda45028, + 0xcbe1feba92e40ce6}, + {1, 0, 0, 0}}, + {{0xe998ceea4396e4c1, 0xfc82ef0b6acea274, 0x230f729f2250e927, + 0xd0b2f94d2f420109}, + {0x4305adddb38d4966, 0x10b838f8624c3b45, 0x7db2636658954e7a, + 0x971459828b0719e5}, + {1, 0, 0, 0}}, + {{0x4bd6b72623369fc9, 0x57f2929e53d0b876, 0xc2d5cba4f2340687, + 0x961610004a866aba}, + {0x49997bcd2e407a5e, 0x69ab197d92ddcb24, 0x2cf1f2438fe5131c, + 0x7acb9fadcee75e44}, + {1, 0, 0, 0}}, + {{0x254e839423d2d4c0, 0xf57f0c917aea685b, 0xa60d880f6f75aaea, + 0x24eb9acca333bf5b}, + {0xe3de4ccb1cda5dea, 0xfeef9341c51a6b4f, 0x743125f88bac4c4d, + 0x69f891c5acd079cc}, + {1, 0, 0, 0}}, + {{0xeee44b35702476b5, 0x7ed031a0e45c2258, 0xb422d1e7bd6f8514, + 0xe51f547c5972a107}, + {0xa25bcd6fc9cf343d, 0x8ca922ee097c184e, 0xa62f98b3a9fe9a06, + 0x1c309a2b25bb1387}, + {1, 0, 0, 0}}, + {{0x9295dbeb1967c459, 0xb00148833472c98e, 0xc504977708011828, + 0x20b87b8aa2c4e503}, + {0x3063175de057c277, 0x1bd539338fe582dd, 0x0d11adef5f69a044, + 0xf5c6fa49919776be}, + {1, 0, 0, 0}}, + {{0x8c944e760fd59e11, 0x3876cba1102fad5f, 0xa454c3fad83faa56, + 0x1ed7d1b9332010b9}, + {0xa1011a270024b889, 0x05e4d0dcac0cd344, 0x52b520f0eb6a2a24, + 0x3a2b03f03217257a}, + {1, 0, 0, 0}}, + {{0xf20fc2afdf1d043d, 0xf330240db58d5a62, 0xfc7d229ca0058c3b, + 0x15fee545c78dd9f6}, + {0x501e82885bc98cda, 0x41ef80e5d046ac04, 0x557d9f49461210fb, + 0x4ab5b6b2b8753f81}, + {1, 0, 0, 0}}}}; + +/* select_point selects the |idx|th point from a precomputation table and + * copies it to out. */ +static void select_point(const u64 idx, size_t size, + const smallfelem pre_comp[/*size*/][3], + smallfelem out[3]) { + u64 *outlimbs = &out[0][0]; + memset(outlimbs, 0, 3 * sizeof(smallfelem)); + + size_t i; + for (i = 0; i < size; i++) { + const u64 *inlimbs = (const u64 *)&pre_comp[i][0][0]; + u64 mask = i ^ idx; + mask |= mask >> 4; + mask |= mask >> 2; + mask |= mask >> 1; + mask &= 1; + mask--; + size_t j; + for (j = 0; j < NLIMBS * 3; j++) { + outlimbs[j] |= inlimbs[j] & mask; + } + } +} + +/* get_bit returns the |i|th bit in |in| */ +static char get_bit(const felem_bytearray in, int i) { + if (i < 0 || i >= 256) { + return 0; + } + return (in[i >> 3] >> (i & 7)) & 1; +} + +/* Interleaved point multiplication using precomputed point multiples: The + * small point multiples 0*P, 1*P, ..., 17*P are in pre_comp[], the scalars + * in scalars[]. If g_scalar is non-NULL, we also add this multiple of the + * generator, using certain (large) precomputed multiples in g_pre_comp. + * Output point (X, Y, Z) is stored in x_out, y_out, z_out. */ +static void batch_mul(felem x_out, felem y_out, felem z_out, + const felem_bytearray scalars[], + const size_t num_points, const u8 *g_scalar, + const smallfelem pre_comp[][17][3]) { + felem nq[3], ftmp; + smallfelem tmp[3]; + u64 bits; + u8 sign, digit; + + /* set nq to the point at infinity */ + memset(nq, 0, 3 * sizeof(felem)); + + /* Loop over all scalars msb-to-lsb, interleaving additions of multiples + * of the generator (two in each of the last 32 rounds) and additions of + * other points multiples (every 5th round). */ + + int skip = 1; /* save two point operations in the first round */ + size_t i = num_points != 0 ? 255 : 31; + for (;;) { + /* double */ + if (!skip) { + point_double(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2]); + } + + /* add multiples of the generator */ + if (g_scalar != NULL && i <= 31) { + /* first, look 32 bits upwards */ + bits = get_bit(g_scalar, i + 224) << 3; + bits |= get_bit(g_scalar, i + 160) << 2; + bits |= get_bit(g_scalar, i + 96) << 1; + bits |= get_bit(g_scalar, i + 32); + /* select the point to add, in constant time */ + select_point(bits, 16, g_pre_comp[1], tmp); + + if (!skip) { + point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], 1 /* mixed */, + tmp[0], tmp[1], tmp[2]); + } else { + smallfelem_expand(nq[0], tmp[0]); + smallfelem_expand(nq[1], tmp[1]); + smallfelem_expand(nq[2], tmp[2]); + skip = 0; + } + + /* second, look at the current position */ + bits = get_bit(g_scalar, i + 192) << 3; + bits |= get_bit(g_scalar, i + 128) << 2; + bits |= get_bit(g_scalar, i + 64) << 1; + bits |= get_bit(g_scalar, i); + /* select the point to add, in constant time */ + select_point(bits, 16, g_pre_comp[0], tmp); + point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], 1 /* mixed */, tmp[0], + tmp[1], tmp[2]); + } + + /* do other additions every 5 doublings */ + if (num_points != 0 && i % 5 == 0) { + /* loop over all scalars */ + size_t num; + for (num = 0; num < num_points; ++num) { + bits = get_bit(scalars[num], i + 4) << 5; + bits |= get_bit(scalars[num], i + 3) << 4; + bits |= get_bit(scalars[num], i + 2) << 3; + bits |= get_bit(scalars[num], i + 1) << 2; + bits |= get_bit(scalars[num], i) << 1; + bits |= get_bit(scalars[num], i - 1); + ec_GFp_nistp_recode_scalar_bits(&sign, &digit, bits); + + /* select the point to add or subtract, in constant time. */ + select_point(digit, 17, pre_comp[num], tmp); + smallfelem_neg(ftmp, tmp[1]); /* (X, -Y, Z) is the negative + * point */ + copy_small_conditional(ftmp, tmp[1], (((limb)sign) - 1)); + felem_contract(tmp[1], ftmp); + + if (!skip) { + point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], 0 /* mixed */, + tmp[0], tmp[1], tmp[2]); + } else { + smallfelem_expand(nq[0], tmp[0]); + smallfelem_expand(nq[1], tmp[1]); + smallfelem_expand(nq[2], tmp[2]); + skip = 0; + } + } + } + + if (i == 0) { + break; + } + --i; + } + felem_assign(x_out, nq[0]); + felem_assign(y_out, nq[1]); + felem_assign(z_out, nq[2]); +} + +/******************************************************************************/ +/* + * OPENSSL EC_METHOD FUNCTIONS + */ + +/* Takes the Jacobian coordinates (X, Y, Z) of a point and returns (X', Y') = + * (X/Z^2, Y/Z^3). */ +static int ec_GFp_nistp256_point_get_affine_coordinates(const EC_GROUP *group, + const EC_POINT *point, + BIGNUM *x, BIGNUM *y, + BN_CTX *ctx) { + felem z1, z2, x_in, y_in; + smallfelem x_out, y_out; + longfelem tmp; + + if (EC_POINT_is_at_infinity(group, point)) { + OPENSSL_PUT_ERROR(EC, EC_R_POINT_AT_INFINITY); + return 0; + } + if (!BN_to_felem(x_in, &point->X) || + !BN_to_felem(y_in, &point->Y) || + !BN_to_felem(z1, &point->Z)) { + return 0; + } + felem_inv(z2, z1); + felem_square(tmp, z2); + felem_reduce(z1, tmp); + + if (x != NULL) { + felem_mul(tmp, x_in, z1); + felem_reduce(x_in, tmp); + felem_contract(x_out, x_in); + if (!smallfelem_to_BN(x, x_out)) { + OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); + return 0; + } + } + + if (y != NULL) { + felem_mul(tmp, z1, z2); + felem_reduce(z1, tmp); + felem_mul(tmp, y_in, z1); + felem_reduce(y_in, tmp); + felem_contract(y_out, y_in); + if (!smallfelem_to_BN(y, y_out)) { + OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); + return 0; + } + } + + return 1; +} + +static int ec_GFp_nistp256_points_mul(const EC_GROUP *group, + EC_POINT *r, + const BIGNUM *g_scalar, + const EC_POINT *p_, + const BIGNUM *p_scalar_, + BN_CTX *ctx) { + /* TODO: This function used to take |points| and |scalars| as arrays of + * |num| elements. The code below should be simplified to work in terms of |p| + * and |p_scalar|. */ + size_t num = p_ != NULL ? 1 : 0; + const EC_POINT **points = p_ != NULL ? &p_ : NULL; + BIGNUM const *const *scalars = p_ != NULL ? &p_scalar_ : NULL; + + int ret = 0; + BN_CTX *new_ctx = NULL; + BIGNUM *x, *y, *z, *tmp_scalar; + felem_bytearray g_secret; + felem_bytearray *secrets = NULL; + smallfelem(*pre_comp)[17][3] = NULL; + felem_bytearray tmp; + size_t num_points = num; + smallfelem x_in, y_in, z_in; + felem x_out, y_out, z_out; + const EC_POINT *p = NULL; + const BIGNUM *p_scalar = NULL; + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) { + return 0; + } + } + + BN_CTX_start(ctx); + if ((x = BN_CTX_get(ctx)) == NULL || + (y = BN_CTX_get(ctx)) == NULL || + (z = BN_CTX_get(ctx)) == NULL || + (tmp_scalar = BN_CTX_get(ctx)) == NULL) { + goto err; + } + + if (num_points > 0) { + secrets = OPENSSL_malloc(num_points * sizeof(felem_bytearray)); + pre_comp = OPENSSL_malloc(num_points * sizeof(smallfelem[17][3])); + if (secrets == NULL || pre_comp == NULL) { + OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); + goto err; + } + + /* we treat NULL scalars as 0, and NULL points as points at infinity, + * i.e., they contribute nothing to the linear combination. */ + memset(secrets, 0, num_points * sizeof(felem_bytearray)); + memset(pre_comp, 0, num_points * 17 * 3 * sizeof(smallfelem)); + size_t i; + for (i = 0; i < num_points; ++i) { + if (i == num) { + /* we didn't have a valid precomputation, so we pick the generator. */ + p = EC_GROUP_get0_generator(group); + p_scalar = g_scalar; + } else { + /* the i^th point */ + p = points[i]; + p_scalar = scalars[i]; + } + if (p_scalar != NULL && p != NULL) { + size_t num_bytes; + /* reduce g_scalar to 0 <= g_scalar < 2^256 */ + if (BN_num_bits(p_scalar) > 256 || BN_is_negative(p_scalar)) { + /* this is an unusual input, and we don't guarantee + * constant-timeness. */ + if (!BN_nnmod(tmp_scalar, p_scalar, &group->order, ctx)) { + OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); + goto err; + } + num_bytes = BN_bn2bin(tmp_scalar, tmp); + } else { + num_bytes = BN_bn2bin(p_scalar, tmp); + } + flip_endian(secrets[i], tmp, num_bytes); + /* precompute multiples */ + if (!BN_to_felem(x_out, &p->X) || + !BN_to_felem(y_out, &p->Y) || + !BN_to_felem(z_out, &p->Z)) { + goto err; + } + felem_shrink(pre_comp[i][1][0], x_out); + felem_shrink(pre_comp[i][1][1], y_out); + felem_shrink(pre_comp[i][1][2], z_out); + size_t j; + for (j = 2; j <= 16; ++j) { + if (j & 1) { + point_add_small(pre_comp[i][j][0], pre_comp[i][j][1], + pre_comp[i][j][2], pre_comp[i][1][0], + pre_comp[i][1][1], pre_comp[i][1][2], + pre_comp[i][j - 1][0], pre_comp[i][j - 1][1], + pre_comp[i][j - 1][2]); + } else { + point_double_small(pre_comp[i][j][0], pre_comp[i][j][1], + pre_comp[i][j][2], pre_comp[i][j / 2][0], + pre_comp[i][j / 2][1], pre_comp[i][j / 2][2]); + } + } + } + } + } + + if (g_scalar != NULL) { + size_t num_bytes; + + memset(g_secret, 0, sizeof(g_secret)); + /* reduce g_scalar to 0 <= g_scalar < 2^256 */ + if (BN_num_bits(g_scalar) > 256 || BN_is_negative(g_scalar)) { + /* this is an unusual input, and we don't guarantee + * constant-timeness. */ + if (!BN_nnmod(tmp_scalar, g_scalar, &group->order, ctx)) { + OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); + goto err; + } + num_bytes = BN_bn2bin(tmp_scalar, tmp); + } else { + num_bytes = BN_bn2bin(g_scalar, tmp); + } + flip_endian(g_secret, tmp, num_bytes); + } + batch_mul(x_out, y_out, z_out, (const felem_bytearray(*))secrets, + num_points, g_scalar != NULL ? g_secret : NULL, + (const smallfelem(*)[17][3])pre_comp); + + /* reduce the output to its unique minimal representation */ + felem_contract(x_in, x_out); + felem_contract(y_in, y_out); + felem_contract(z_in, z_out); + if (!smallfelem_to_BN(x, x_in) || + !smallfelem_to_BN(y, y_in) || + !smallfelem_to_BN(z, z_in)) { + OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); + goto err; + } + ret = ec_point_set_Jprojective_coordinates_GFp(group, r, x, y, z, ctx); + +err: + BN_CTX_end(ctx); + BN_CTX_free(new_ctx); + OPENSSL_free(secrets); + OPENSSL_free(pre_comp); + return ret; +} + +const EC_METHOD *EC_GFp_nistp256_method(void) { + static const EC_METHOD ret = { + ec_GFp_simple_group_init, + ec_GFp_simple_group_finish, + ec_GFp_simple_group_copy, + ec_GFp_simple_group_set_curve, + ec_GFp_nistp256_point_get_affine_coordinates, + ec_GFp_nistp256_points_mul, + 0 /* check_pub_key_order */, + ec_GFp_simple_field_mul, ec_GFp_simple_field_sqr, + 0 /* field_encode */, 0 /* field_decode */, + }; + + return &ret; +} + +#endif /* 64_BIT && !WINDOWS */ diff --git a/external/boringssl/crypto/ec/p256-x86_64-table.h.REMOVED.git-id b/external/boringssl/crypto/ec/p256-x86_64-table.h.REMOVED.git-id new file mode 100644 index 0000000000..010e9e3ebe --- /dev/null +++ b/external/boringssl/crypto/ec/p256-x86_64-table.h.REMOVED.git-id @@ -0,0 +1 @@ +e4705f8e11a6f57a44b53640beced5cab94a7f2d \ No newline at end of file diff --git a/external/boringssl/crypto/ec/p256-x86_64.c b/external/boringssl/crypto/ec/p256-x86_64.c new file mode 100644 index 0000000000..e1afec4827 --- /dev/null +++ b/external/boringssl/crypto/ec/p256-x86_64.c @@ -0,0 +1,573 @@ +/* Copyright (c) 2014, Intel Corporation. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +/* Developers and authors: + * Shay Gueron (1, 2), and Vlad Krasnov (1) + * (1) Intel Corporation, Israel Development Center + * (2) University of Haifa + * Reference: + * S.Gueron and V.Krasnov, "Fast Prime Field Elliptic Curve Cryptography with + * 256 Bit Primes" */ + +#include + +#include +#include +#include + +#include +#include +#include + +#include "../bn/internal.h" +#include "../ec/internal.h" +#include "../internal.h" + + +#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && \ + !defined(OPENSSL_SMALL) + + +#define P256_LIMBS (256 / BN_BITS2) + +typedef struct { + BN_ULONG X[P256_LIMBS]; + BN_ULONG Y[P256_LIMBS]; + BN_ULONG Z[P256_LIMBS]; +} P256_POINT; + +typedef struct { + BN_ULONG X[P256_LIMBS]; + BN_ULONG Y[P256_LIMBS]; +} P256_POINT_AFFINE; + +typedef P256_POINT_AFFINE PRECOMP256_ROW[64]; + +/* Functions implemented in assembly */ + +/* Modular neg: res = -a mod P */ +void ecp_nistz256_neg(BN_ULONG res[P256_LIMBS], const BN_ULONG a[P256_LIMBS]); +/* Montgomery mul: res = a*b*2^-256 mod P */ +void ecp_nistz256_mul_mont(BN_ULONG res[P256_LIMBS], + const BN_ULONG a[P256_LIMBS], + const BN_ULONG b[P256_LIMBS]); +/* Montgomery sqr: res = a*a*2^-256 mod P */ +void ecp_nistz256_sqr_mont(BN_ULONG res[P256_LIMBS], + const BN_ULONG a[P256_LIMBS]); +/* Convert a number from Montgomery domain, by multiplying with 1 */ +void ecp_nistz256_from_mont(BN_ULONG res[P256_LIMBS], + const BN_ULONG in[P256_LIMBS]); +/* Functions that perform constant time access to the precomputed tables */ +void ecp_nistz256_select_w5(P256_POINT *val, const P256_POINT *in_t, int index); +void ecp_nistz256_select_w7(P256_POINT_AFFINE *val, + const P256_POINT_AFFINE *in_t, int index); + +/* One converted into the Montgomery domain */ +static const BN_ULONG ONE[P256_LIMBS] = { + TOBN(0x00000000, 0x00000001), TOBN(0xffffffff, 0x00000000), + TOBN(0xffffffff, 0xffffffff), TOBN(0x00000000, 0xfffffffe), +}; + +/* Precomputed tables for the default generator */ +#include "p256-x86_64-table.h" + +/* Recode window to a signed digit, see ecp_nistputil.c for details */ +static unsigned booth_recode_w5(unsigned in) { + unsigned s, d; + + s = ~((in >> 5) - 1); + d = (1 << 6) - in - 1; + d = (d & s) | (in & ~s); + d = (d >> 1) + (d & 1); + + return (d << 1) + (s & 1); +} + +static unsigned booth_recode_w7(unsigned in) { + unsigned s, d; + + s = ~((in >> 7) - 1); + d = (1 << 8) - in - 1; + d = (d & s) | (in & ~s); + d = (d >> 1) + (d & 1); + + return (d << 1) + (s & 1); +} + +static void copy_conditional(BN_ULONG dst[P256_LIMBS], + const BN_ULONG src[P256_LIMBS], BN_ULONG move) { + BN_ULONG mask1 = ((BN_ULONG)0) - move; + BN_ULONG mask2 = ~mask1; + + dst[0] = (src[0] & mask1) ^ (dst[0] & mask2); + dst[1] = (src[1] & mask1) ^ (dst[1] & mask2); + dst[2] = (src[2] & mask1) ^ (dst[2] & mask2); + dst[3] = (src[3] & mask1) ^ (dst[3] & mask2); + if (P256_LIMBS == 8) { + dst[4] = (src[4] & mask1) ^ (dst[4] & mask2); + dst[5] = (src[5] & mask1) ^ (dst[5] & mask2); + dst[6] = (src[6] & mask1) ^ (dst[6] & mask2); + dst[7] = (src[7] & mask1) ^ (dst[7] & mask2); + } +} + +void ecp_nistz256_point_double(P256_POINT *r, const P256_POINT *a); +void ecp_nistz256_point_add(P256_POINT *r, const P256_POINT *a, + const P256_POINT *b); +void ecp_nistz256_point_add_affine(P256_POINT *r, const P256_POINT *a, + const P256_POINT_AFFINE *b); + +/* r = in^-1 mod p */ +static void ecp_nistz256_mod_inverse(BN_ULONG r[P256_LIMBS], + const BN_ULONG in[P256_LIMBS]) { + /* The poly is ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff + ffffffff + We use FLT and used poly-2 as exponent */ + BN_ULONG p2[P256_LIMBS]; + BN_ULONG p4[P256_LIMBS]; + BN_ULONG p8[P256_LIMBS]; + BN_ULONG p16[P256_LIMBS]; + BN_ULONG p32[P256_LIMBS]; + BN_ULONG res[P256_LIMBS]; + int i; + + ecp_nistz256_sqr_mont(res, in); + ecp_nistz256_mul_mont(p2, res, in); /* 3*p */ + + ecp_nistz256_sqr_mont(res, p2); + ecp_nistz256_sqr_mont(res, res); + ecp_nistz256_mul_mont(p4, res, p2); /* f*p */ + + ecp_nistz256_sqr_mont(res, p4); + ecp_nistz256_sqr_mont(res, res); + ecp_nistz256_sqr_mont(res, res); + ecp_nistz256_sqr_mont(res, res); + ecp_nistz256_mul_mont(p8, res, p4); /* ff*p */ + + ecp_nistz256_sqr_mont(res, p8); + for (i = 0; i < 7; i++) { + ecp_nistz256_sqr_mont(res, res); + } + ecp_nistz256_mul_mont(p16, res, p8); /* ffff*p */ + + ecp_nistz256_sqr_mont(res, p16); + for (i = 0; i < 15; i++) { + ecp_nistz256_sqr_mont(res, res); + } + ecp_nistz256_mul_mont(p32, res, p16); /* ffffffff*p */ + + ecp_nistz256_sqr_mont(res, p32); + for (i = 0; i < 31; i++) { + ecp_nistz256_sqr_mont(res, res); + } + ecp_nistz256_mul_mont(res, res, in); + + for (i = 0; i < 32 * 4; i++) { + ecp_nistz256_sqr_mont(res, res); + } + ecp_nistz256_mul_mont(res, res, p32); + + for (i = 0; i < 32; i++) { + ecp_nistz256_sqr_mont(res, res); + } + ecp_nistz256_mul_mont(res, res, p32); + + for (i = 0; i < 16; i++) { + ecp_nistz256_sqr_mont(res, res); + } + ecp_nistz256_mul_mont(res, res, p16); + + for (i = 0; i < 8; i++) { + ecp_nistz256_sqr_mont(res, res); + } + ecp_nistz256_mul_mont(res, res, p8); + + ecp_nistz256_sqr_mont(res, res); + ecp_nistz256_sqr_mont(res, res); + ecp_nistz256_sqr_mont(res, res); + ecp_nistz256_sqr_mont(res, res); + ecp_nistz256_mul_mont(res, res, p4); + + ecp_nistz256_sqr_mont(res, res); + ecp_nistz256_sqr_mont(res, res); + ecp_nistz256_mul_mont(res, res, p2); + + ecp_nistz256_sqr_mont(res, res); + ecp_nistz256_sqr_mont(res, res); + ecp_nistz256_mul_mont(r, res, in); +} + +/* ecp_nistz256_bignum_to_field_elem copies the contents of |in| to |out| and + * returns one if it fits. Otherwise it returns zero. */ +static int ecp_nistz256_bignum_to_field_elem(BN_ULONG out[P256_LIMBS], + const BIGNUM *in) { + if (in->top > P256_LIMBS) { + return 0; + } + + memset(out, 0, sizeof(BN_ULONG) * P256_LIMBS); + memcpy(out, in->d, sizeof(BN_ULONG) * in->top); + return 1; +} + +/* r = p * p_scalar */ +static int ecp_nistz256_windowed_mul(const EC_GROUP *group, P256_POINT *r, + const EC_POINT *p, const BIGNUM *p_scalar, + BN_CTX *ctx) { + assert(p != NULL); + assert(p_scalar != NULL); + + static const unsigned kWindowSize = 5; + static const unsigned kMask = (1 << (5 /* kWindowSize */ + 1)) - 1; + + /* A |P256_POINT| is (3 * 32) = 96 bytes, and the 64-byte alignment should + * add no more than 63 bytes of overhead. Thus, |table| should require + * ~1599 ((96 * 16) + 63) bytes of stack space. */ + alignas(64) P256_POINT table[16]; + uint8_t p_str[33]; + + + int ret = 0; + BN_CTX *new_ctx = NULL; + int ctx_started = 0; + + if (BN_num_bits(p_scalar) > 256 || BN_is_negative(p_scalar)) { + if (ctx == NULL) { + new_ctx = BN_CTX_new(); + if (new_ctx == NULL) { + OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); + goto err; + } + ctx = new_ctx; + } + BN_CTX_start(ctx); + ctx_started = 1; + BIGNUM *mod = BN_CTX_get(ctx); + if (mod == NULL) { + OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); + goto err; + } + if (!BN_nnmod(mod, p_scalar, &group->order, ctx)) { + OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); + goto err; + } + p_scalar = mod; + } + + int j; + for (j = 0; j < p_scalar->top * BN_BYTES; j += BN_BYTES) { + BN_ULONG d = p_scalar->d[j / BN_BYTES]; + + p_str[j + 0] = d & 0xff; + p_str[j + 1] = (d >> 8) & 0xff; + p_str[j + 2] = (d >> 16) & 0xff; + p_str[j + 3] = (d >>= 24) & 0xff; + if (BN_BYTES == 8) { + d >>= 8; + p_str[j + 4] = d & 0xff; + p_str[j + 5] = (d >> 8) & 0xff; + p_str[j + 6] = (d >> 16) & 0xff; + p_str[j + 7] = (d >> 24) & 0xff; + } + } + + for (; j < 33; j++) { + p_str[j] = 0; + } + + /* table[0] is implicitly (0,0,0) (the point at infinity), therefore it is + * not stored. All other values are actually stored with an offset of -1 in + * table. */ + P256_POINT *row = table; + + if (!ecp_nistz256_bignum_to_field_elem(row[1 - 1].X, &p->X) || + !ecp_nistz256_bignum_to_field_elem(row[1 - 1].Y, &p->Y) || + !ecp_nistz256_bignum_to_field_elem(row[1 - 1].Z, &p->Z)) { + OPENSSL_PUT_ERROR(EC, EC_R_COORDINATES_OUT_OF_RANGE); + goto err; + } + + ecp_nistz256_point_double(&row[2 - 1], &row[1 - 1]); + ecp_nistz256_point_add(&row[3 - 1], &row[2 - 1], &row[1 - 1]); + ecp_nistz256_point_double(&row[4 - 1], &row[2 - 1]); + ecp_nistz256_point_double(&row[6 - 1], &row[3 - 1]); + ecp_nistz256_point_double(&row[8 - 1], &row[4 - 1]); + ecp_nistz256_point_double(&row[12 - 1], &row[6 - 1]); + ecp_nistz256_point_add(&row[5 - 1], &row[4 - 1], &row[1 - 1]); + ecp_nistz256_point_add(&row[7 - 1], &row[6 - 1], &row[1 - 1]); + ecp_nistz256_point_add(&row[9 - 1], &row[8 - 1], &row[1 - 1]); + ecp_nistz256_point_add(&row[13 - 1], &row[12 - 1], &row[1 - 1]); + ecp_nistz256_point_double(&row[14 - 1], &row[7 - 1]); + ecp_nistz256_point_double(&row[10 - 1], &row[5 - 1]); + ecp_nistz256_point_add(&row[15 - 1], &row[14 - 1], &row[1 - 1]); + ecp_nistz256_point_add(&row[11 - 1], &row[10 - 1], &row[1 - 1]); + ecp_nistz256_point_add(&row[16 - 1], &row[15 - 1], &row[1 - 1]); + + BN_ULONG tmp[P256_LIMBS]; + alignas(32) P256_POINT h; + unsigned index = 255; + unsigned wvalue = p_str[(index - 1) / 8]; + wvalue = (wvalue >> ((index - 1) % 8)) & kMask; + + ecp_nistz256_select_w5(r, table, booth_recode_w5(wvalue) >> 1); + + while (index >= 5) { + if (index != 255) { + unsigned off = (index - 1) / 8; + + wvalue = p_str[off] | p_str[off + 1] << 8; + wvalue = (wvalue >> ((index - 1) % 8)) & kMask; + + wvalue = booth_recode_w5(wvalue); + + ecp_nistz256_select_w5(&h, table, wvalue >> 1); + + ecp_nistz256_neg(tmp, h.Y); + copy_conditional(h.Y, tmp, (wvalue & 1)); + + ecp_nistz256_point_add(r, r, &h); + } + + index -= kWindowSize; + + ecp_nistz256_point_double(r, r); + ecp_nistz256_point_double(r, r); + ecp_nistz256_point_double(r, r); + ecp_nistz256_point_double(r, r); + ecp_nistz256_point_double(r, r); + } + + /* Final window */ + wvalue = p_str[0]; + wvalue = (wvalue << 1) & kMask; + + wvalue = booth_recode_w5(wvalue); + + ecp_nistz256_select_w5(&h, table, wvalue >> 1); + + ecp_nistz256_neg(tmp, h.Y); + copy_conditional(h.Y, tmp, wvalue & 1); + + ecp_nistz256_point_add(r, r, &h); + + ret = 1; + +err: + if (ctx_started) { + BN_CTX_end(ctx); + } + BN_CTX_free(new_ctx); + return ret; +} + +static int ecp_nistz256_points_mul( + const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar, + const EC_POINT *p_, const BIGNUM *p_scalar, BN_CTX *ctx) { + assert((p_ != NULL) == (p_scalar != NULL)); + + static const unsigned kWindowSize = 7; + static const unsigned kMask = (1 << (7 /* kWindowSize */ + 1)) - 1; + + alignas(32) union { + P256_POINT p; + P256_POINT_AFFINE a; + } t, p; + + int ret = 0; + BN_CTX *new_ctx = NULL; + int ctx_started = 0; + + if (g_scalar != NULL) { + if (BN_num_bits(g_scalar) > 256 || BN_is_negative(g_scalar)) { + if (ctx == NULL) { + new_ctx = BN_CTX_new(); + if (new_ctx == NULL) { + goto err; + } + ctx = new_ctx; + } + BN_CTX_start(ctx); + ctx_started = 1; + BIGNUM *tmp_scalar = BN_CTX_get(ctx); + if (tmp_scalar == NULL) { + goto err; + } + + if (!BN_nnmod(tmp_scalar, g_scalar, &group->order, ctx)) { + OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); + goto err; + } + g_scalar = tmp_scalar; + } + + uint8_t p_str[33] = {0}; + int i; + for (i = 0; i < g_scalar->top * BN_BYTES; i += BN_BYTES) { + BN_ULONG d = g_scalar->d[i / BN_BYTES]; + + p_str[i + 0] = d & 0xff; + p_str[i + 1] = (d >> 8) & 0xff; + p_str[i + 2] = (d >> 16) & 0xff; + p_str[i + 3] = (d >>= 24) & 0xff; + if (BN_BYTES == 8) { + d >>= 8; + p_str[i + 4] = d & 0xff; + p_str[i + 5] = (d >> 8) & 0xff; + p_str[i + 6] = (d >> 16) & 0xff; + p_str[i + 7] = (d >> 24) & 0xff; + } + } + + for (; i < (int) sizeof(p_str); i++) { + p_str[i] = 0; + } + + /* First window */ + unsigned wvalue = (p_str[0] << 1) & kMask; + unsigned index = kWindowSize; + + wvalue = booth_recode_w7(wvalue); + + const PRECOMP256_ROW *const precomputed_table = + (const PRECOMP256_ROW *)ecp_nistz256_precomputed; + ecp_nistz256_select_w7(&p.a, precomputed_table[0], wvalue >> 1); + + ecp_nistz256_neg(p.p.Z, p.p.Y); + copy_conditional(p.p.Y, p.p.Z, wvalue & 1); + + memcpy(p.p.Z, ONE, sizeof(ONE)); + + for (i = 1; i < 37; i++) { + unsigned off = (index - 1) / 8; + wvalue = p_str[off] | p_str[off + 1] << 8; + wvalue = (wvalue >> ((index - 1) % 8)) & kMask; + index += kWindowSize; + + wvalue = booth_recode_w7(wvalue); + + ecp_nistz256_select_w7(&t.a, precomputed_table[i], wvalue >> 1); + + ecp_nistz256_neg(t.p.Z, t.a.Y); + copy_conditional(t.a.Y, t.p.Z, wvalue & 1); + + ecp_nistz256_point_add_affine(&p.p, &p.p, &t.a); + } + } + + const int p_is_infinity = g_scalar == NULL; + if (p_scalar != NULL) { + P256_POINT *out = &t.p; + if (p_is_infinity) { + out = &p.p; + } + + if (!ecp_nistz256_windowed_mul(group, out, p_, p_scalar, ctx)) { + goto err; + } + + if (!p_is_infinity) { + ecp_nistz256_point_add(&p.p, &p.p, out); + } + } + + /* Not constant-time, but we're only operating on the public output. */ + if (!bn_set_words(&r->X, p.p.X, P256_LIMBS) || + !bn_set_words(&r->Y, p.p.Y, P256_LIMBS) || + !bn_set_words(&r->Z, p.p.Z, P256_LIMBS)) { + return 0; + } + + ret = 1; + +err: + if (ctx_started) { + BN_CTX_end(ctx); + } + BN_CTX_free(new_ctx); + return ret; +} + +static int ecp_nistz256_get_affine(const EC_GROUP *group, const EC_POINT *point, + BIGNUM *x, BIGNUM *y, BN_CTX *ctx) { + BN_ULONG z_inv2[P256_LIMBS]; + BN_ULONG z_inv3[P256_LIMBS]; + BN_ULONG point_x[P256_LIMBS], point_y[P256_LIMBS], point_z[P256_LIMBS]; + + if (EC_POINT_is_at_infinity(group, point)) { + OPENSSL_PUT_ERROR(EC, EC_R_POINT_AT_INFINITY); + return 0; + } + + if (!ecp_nistz256_bignum_to_field_elem(point_x, &point->X) || + !ecp_nistz256_bignum_to_field_elem(point_y, &point->Y) || + !ecp_nistz256_bignum_to_field_elem(point_z, &point->Z)) { + OPENSSL_PUT_ERROR(EC, EC_R_COORDINATES_OUT_OF_RANGE); + return 0; + } + + ecp_nistz256_mod_inverse(z_inv3, point_z); + ecp_nistz256_sqr_mont(z_inv2, z_inv3); + + /* Instead of using |ecp_nistz256_from_mont| to convert the |x| coordinate + * and then calling |ecp_nistz256_from_mont| again to convert the |y| + * coordinate below, convert the common factor |z_inv2| once now, saving one + * reduction. */ + ecp_nistz256_from_mont(z_inv2, z_inv2); + + if (x != NULL) { + if (bn_wexpand(x, P256_LIMBS) == NULL) { + OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); + return 0; + } + x->top = P256_LIMBS; + x->neg = 0; + ecp_nistz256_mul_mont(x->d, z_inv2, point_x); + bn_correct_top(x); + } + + if (y != NULL) { + ecp_nistz256_mul_mont(z_inv3, z_inv3, z_inv2); + if (bn_wexpand(y, P256_LIMBS) == NULL) { + OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); + return 0; + } + y->top = P256_LIMBS; + y->neg = 0; + ecp_nistz256_mul_mont(y->d, z_inv3, point_y); + bn_correct_top(y); + } + + return 1; +} + +const EC_METHOD *EC_GFp_nistz256_method(void) { + static const EC_METHOD ret = { + ec_GFp_mont_group_init, + ec_GFp_mont_group_finish, + ec_GFp_mont_group_copy, + ec_GFp_mont_group_set_curve, + ecp_nistz256_get_affine, + ecp_nistz256_points_mul, + 0 /* check_pub_key_order */, + ec_GFp_mont_field_mul, + ec_GFp_mont_field_sqr, + ec_GFp_mont_field_encode, + ec_GFp_mont_field_decode, + }; + + return &ret; +} + +#endif /* !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && \ + !defined(OPENSSL_SMALL) */ diff --git a/external/boringssl/crypto/ec/simple.c b/external/boringssl/crypto/ec/simple.c new file mode 100644 index 0000000000..4508d83fb6 --- /dev/null +++ b/external/boringssl/crypto/ec/simple.c @@ -0,0 +1,1112 @@ +/* Originally written by Bodo Moeller for the OpenSSL project. + * ==================================================================== + * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * + * Portions of the attached software ("Contribution") are developed by + * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. + * + * The Contribution is licensed pursuant to the OpenSSL open source + * license provided above. + * + * The elliptic curve binary polynomial software is originally written by + * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems + * Laboratories. */ + +#include + +#include + +#include +#include +#include + +#include "internal.h" + + +/* Most method functions in this file are designed to work with non-trivial + * representations of field elements if necessary (see ecp_mont.c): while + * standard modular addition and subtraction are used, the field_mul and + * field_sqr methods will be used for multiplication, and field_encode and + * field_decode (if defined) will be used for converting between + * representations. + * + * Functions here specifically assume that if a non-trivial representation is + * used, it is a Montgomery representation (i.e. 'encoding' means multiplying + * by some factor R). */ + +int ec_GFp_simple_group_init(EC_GROUP *group) { + BN_init(&group->field); + BN_init(&group->a); + BN_init(&group->b); + BN_init(&group->one); + group->a_is_minus3 = 0; + return 1; +} + +void ec_GFp_simple_group_finish(EC_GROUP *group) { + BN_free(&group->field); + BN_free(&group->a); + BN_free(&group->b); + BN_free(&group->one); +} + +int ec_GFp_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src) { + if (!BN_copy(&dest->field, &src->field) || + !BN_copy(&dest->a, &src->a) || + !BN_copy(&dest->b, &src->b) || + !BN_copy(&dest->one, &src->one)) { + return 0; + } + + dest->a_is_minus3 = src->a_is_minus3; + return 1; +} + +int ec_GFp_simple_group_set_curve(EC_GROUP *group, const BIGNUM *p, + const BIGNUM *a, const BIGNUM *b, + BN_CTX *ctx) { + int ret = 0; + BN_CTX *new_ctx = NULL; + BIGNUM *tmp_a; + + /* p must be a prime > 3 */ + if (BN_num_bits(p) <= 2 || !BN_is_odd(p)) { + OPENSSL_PUT_ERROR(EC, EC_R_INVALID_FIELD); + return 0; + } + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) { + return 0; + } + } + + BN_CTX_start(ctx); + tmp_a = BN_CTX_get(ctx); + if (tmp_a == NULL) { + goto err; + } + + /* group->field */ + if (!BN_copy(&group->field, p)) { + goto err; + } + BN_set_negative(&group->field, 0); + + /* group->a */ + if (!BN_nnmod(tmp_a, a, p, ctx)) { + goto err; + } + if (group->meth->field_encode) { + if (!group->meth->field_encode(group, &group->a, tmp_a, ctx)) { + goto err; + } + } else if (!BN_copy(&group->a, tmp_a)) { + goto err; + } + + /* group->b */ + if (!BN_nnmod(&group->b, b, p, ctx)) { + goto err; + } + if (group->meth->field_encode && + !group->meth->field_encode(group, &group->b, &group->b, ctx)) { + goto err; + } + + /* group->a_is_minus3 */ + if (!BN_add_word(tmp_a, 3)) { + goto err; + } + group->a_is_minus3 = (0 == BN_cmp(tmp_a, &group->field)); + + if (group->meth->field_encode != NULL) { + if (!group->meth->field_encode(group, &group->one, BN_value_one(), ctx)) { + goto err; + } + } else if (!BN_copy(&group->one, BN_value_one())) { + goto err; + } + + ret = 1; + +err: + BN_CTX_end(ctx); + BN_CTX_free(new_ctx); + return ret; +} + +int ec_GFp_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, + BIGNUM *b, BN_CTX *ctx) { + int ret = 0; + BN_CTX *new_ctx = NULL; + + if (p != NULL && !BN_copy(p, &group->field)) { + return 0; + } + + if (a != NULL || b != NULL) { + if (group->meth->field_decode) { + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) { + return 0; + } + } + if (a != NULL && !group->meth->field_decode(group, a, &group->a, ctx)) { + goto err; + } + if (b != NULL && !group->meth->field_decode(group, b, &group->b, ctx)) { + goto err; + } + } else { + if (a != NULL && !BN_copy(a, &group->a)) { + goto err; + } + if (b != NULL && !BN_copy(b, &group->b)) { + goto err; + } + } + } + + ret = 1; + +err: + BN_CTX_free(new_ctx); + return ret; +} + +unsigned ec_GFp_simple_group_get_degree(const EC_GROUP *group) { + return BN_num_bits(&group->field); +} + +int ec_GFp_simple_point_init(EC_POINT *point) { + BN_init(&point->X); + BN_init(&point->Y); + BN_init(&point->Z); + + return 1; +} + +void ec_GFp_simple_point_finish(EC_POINT *point) { + BN_free(&point->X); + BN_free(&point->Y); + BN_free(&point->Z); +} + +void ec_GFp_simple_point_clear_finish(EC_POINT *point) { + BN_clear_free(&point->X); + BN_clear_free(&point->Y); + BN_clear_free(&point->Z); +} + +int ec_GFp_simple_point_copy(EC_POINT *dest, const EC_POINT *src) { + if (!BN_copy(&dest->X, &src->X) || + !BN_copy(&dest->Y, &src->Y) || + !BN_copy(&dest->Z, &src->Z)) { + return 0; + } + + return 1; +} + +int ec_GFp_simple_point_set_to_infinity(const EC_GROUP *group, + EC_POINT *point) { + BN_zero(&point->Z); + return 1; +} + +static int set_Jprojective_coordinate_GFp(const EC_GROUP *group, BIGNUM *out, + const BIGNUM *in, BN_CTX *ctx) { + if (in == NULL) { + return 1; + } + if (BN_is_negative(in) || + BN_cmp(in, &group->field) >= 0) { + OPENSSL_PUT_ERROR(EC, EC_R_COORDINATES_OUT_OF_RANGE); + return 0; + } + if (group->meth->field_encode) { + return group->meth->field_encode(group, out, in, ctx); + } + return BN_copy(out, in) != NULL; +} + +int ec_GFp_simple_set_Jprojective_coordinates_GFp( + const EC_GROUP *group, EC_POINT *point, const BIGNUM *x, const BIGNUM *y, + const BIGNUM *z, BN_CTX *ctx) { + BN_CTX *new_ctx = NULL; + int ret = 0; + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) { + return 0; + } + } + + if (!set_Jprojective_coordinate_GFp(group, &point->X, x, ctx) || + !set_Jprojective_coordinate_GFp(group, &point->Y, y, ctx) || + !set_Jprojective_coordinate_GFp(group, &point->Z, z, ctx)) { + goto err; + } + + ret = 1; + +err: + BN_CTX_free(new_ctx); + return ret; +} + +int ec_GFp_simple_get_Jprojective_coordinates_GFp(const EC_GROUP *group, + const EC_POINT *point, + BIGNUM *x, BIGNUM *y, + BIGNUM *z, BN_CTX *ctx) { + BN_CTX *new_ctx = NULL; + int ret = 0; + + if (group->meth->field_decode != 0) { + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) { + return 0; + } + } + + if (x != NULL && !group->meth->field_decode(group, x, &point->X, ctx)) { + goto err; + } + if (y != NULL && !group->meth->field_decode(group, y, &point->Y, ctx)) { + goto err; + } + if (z != NULL && !group->meth->field_decode(group, z, &point->Z, ctx)) { + goto err; + } + } else { + if (x != NULL && !BN_copy(x, &point->X)) { + goto err; + } + if (y != NULL && !BN_copy(y, &point->Y)) { + goto err; + } + if (z != NULL && !BN_copy(z, &point->Z)) { + goto err; + } + } + + ret = 1; + +err: + BN_CTX_free(new_ctx); + return ret; +} + +int ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP *group, + EC_POINT *point, const BIGNUM *x, + const BIGNUM *y, BN_CTX *ctx) { + if (x == NULL || y == NULL) { + /* unlike for projective coordinates, we do not tolerate this */ + OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + return ec_point_set_Jprojective_coordinates_GFp(group, point, x, y, + BN_value_one(), ctx); +} + +int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, + const EC_POINT *b, BN_CTX *ctx) { + int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, + BN_CTX *); + int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *); + const BIGNUM *p; + BN_CTX *new_ctx = NULL; + BIGNUM *n0, *n1, *n2, *n3, *n4, *n5, *n6; + int ret = 0; + + if (a == b) { + return EC_POINT_dbl(group, r, a, ctx); + } + if (EC_POINT_is_at_infinity(group, a)) { + return EC_POINT_copy(r, b); + } + if (EC_POINT_is_at_infinity(group, b)) { + return EC_POINT_copy(r, a); + } + + field_mul = group->meth->field_mul; + field_sqr = group->meth->field_sqr; + p = &group->field; + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) { + return 0; + } + } + + BN_CTX_start(ctx); + n0 = BN_CTX_get(ctx); + n1 = BN_CTX_get(ctx); + n2 = BN_CTX_get(ctx); + n3 = BN_CTX_get(ctx); + n4 = BN_CTX_get(ctx); + n5 = BN_CTX_get(ctx); + n6 = BN_CTX_get(ctx); + if (n6 == NULL) { + goto end; + } + + /* Note that in this function we must not read components of 'a' or 'b' + * once we have written the corresponding components of 'r'. + * ('r' might be one of 'a' or 'b'.) + */ + + /* n1, n2 */ + int b_Z_is_one = BN_cmp(&b->Z, &group->one) == 0; + + if (b_Z_is_one) { + if (!BN_copy(n1, &a->X) || !BN_copy(n2, &a->Y)) { + goto end; + } + /* n1 = X_a */ + /* n2 = Y_a */ + } else { + if (!field_sqr(group, n0, &b->Z, ctx) || + !field_mul(group, n1, &a->X, n0, ctx)) { + goto end; + } + /* n1 = X_a * Z_b^2 */ + + if (!field_mul(group, n0, n0, &b->Z, ctx) || + !field_mul(group, n2, &a->Y, n0, ctx)) { + goto end; + } + /* n2 = Y_a * Z_b^3 */ + } + + /* n3, n4 */ + int a_Z_is_one = BN_cmp(&a->Z, &group->one) == 0; + if (a_Z_is_one) { + if (!BN_copy(n3, &b->X) || !BN_copy(n4, &b->Y)) { + goto end; + } + /* n3 = X_b */ + /* n4 = Y_b */ + } else { + if (!field_sqr(group, n0, &a->Z, ctx) || + !field_mul(group, n3, &b->X, n0, ctx)) { + goto end; + } + /* n3 = X_b * Z_a^2 */ + + if (!field_mul(group, n0, n0, &a->Z, ctx) || + !field_mul(group, n4, &b->Y, n0, ctx)) { + goto end; + } + /* n4 = Y_b * Z_a^3 */ + } + + /* n5, n6 */ + if (!BN_mod_sub_quick(n5, n1, n3, p) || + !BN_mod_sub_quick(n6, n2, n4, p)) { + goto end; + } + /* n5 = n1 - n3 */ + /* n6 = n2 - n4 */ + + if (BN_is_zero(n5)) { + if (BN_is_zero(n6)) { + /* a is the same point as b */ + BN_CTX_end(ctx); + ret = EC_POINT_dbl(group, r, a, ctx); + ctx = NULL; + goto end; + } else { + /* a is the inverse of b */ + BN_zero(&r->Z); + ret = 1; + goto end; + } + } + + /* 'n7', 'n8' */ + if (!BN_mod_add_quick(n1, n1, n3, p) || + !BN_mod_add_quick(n2, n2, n4, p)) { + goto end; + } + /* 'n7' = n1 + n3 */ + /* 'n8' = n2 + n4 */ + + /* Z_r */ + if (a_Z_is_one && b_Z_is_one) { + if (!BN_copy(&r->Z, n5)) { + goto end; + } + } else { + if (a_Z_is_one) { + if (!BN_copy(n0, &b->Z)) { + goto end; + } + } else if (b_Z_is_one) { + if (!BN_copy(n0, &a->Z)) { + goto end; + } + } else if (!field_mul(group, n0, &a->Z, &b->Z, ctx)) { + goto end; + } + if (!field_mul(group, &r->Z, n0, n5, ctx)) { + goto end; + } + } + + /* Z_r = Z_a * Z_b * n5 */ + + /* X_r */ + if (!field_sqr(group, n0, n6, ctx) || + !field_sqr(group, n4, n5, ctx) || + !field_mul(group, n3, n1, n4, ctx) || + !BN_mod_sub_quick(&r->X, n0, n3, p)) { + goto end; + } + /* X_r = n6^2 - n5^2 * 'n7' */ + + /* 'n9' */ + if (!BN_mod_lshift1_quick(n0, &r->X, p) || + !BN_mod_sub_quick(n0, n3, n0, p)) { + goto end; + } + /* n9 = n5^2 * 'n7' - 2 * X_r */ + + /* Y_r */ + if (!field_mul(group, n0, n0, n6, ctx) || + !field_mul(group, n5, n4, n5, ctx)) { + goto end; /* now n5 is n5^3 */ + } + if (!field_mul(group, n1, n2, n5, ctx) || + !BN_mod_sub_quick(n0, n0, n1, p)) { + goto end; + } + if (BN_is_odd(n0) && !BN_add(n0, n0, p)) { + goto end; + } + /* now 0 <= n0 < 2*p, and n0 is even */ + if (!BN_rshift1(&r->Y, n0)) { + goto end; + } + /* Y_r = (n6 * 'n9' - 'n8' * 'n5^3') / 2 */ + + ret = 1; + +end: + if (ctx) { + /* otherwise we already called BN_CTX_end */ + BN_CTX_end(ctx); + } + BN_CTX_free(new_ctx); + return ret; +} + +int ec_GFp_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, + BN_CTX *ctx) { + int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, + BN_CTX *); + int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *); + const BIGNUM *p; + BN_CTX *new_ctx = NULL; + BIGNUM *n0, *n1, *n2, *n3; + int ret = 0; + + if (EC_POINT_is_at_infinity(group, a)) { + BN_zero(&r->Z); + return 1; + } + + field_mul = group->meth->field_mul; + field_sqr = group->meth->field_sqr; + p = &group->field; + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) { + return 0; + } + } + + BN_CTX_start(ctx); + n0 = BN_CTX_get(ctx); + n1 = BN_CTX_get(ctx); + n2 = BN_CTX_get(ctx); + n3 = BN_CTX_get(ctx); + if (n3 == NULL) { + goto err; + } + + /* Note that in this function we must not read components of 'a' + * once we have written the corresponding components of 'r'. + * ('r' might the same as 'a'.) + */ + + /* n1 */ + if (BN_cmp(&a->Z, &group->one) == 0) { + if (!field_sqr(group, n0, &a->X, ctx) || + !BN_mod_lshift1_quick(n1, n0, p) || + !BN_mod_add_quick(n0, n0, n1, p) || + !BN_mod_add_quick(n1, n0, &group->a, p)) { + goto err; + } + /* n1 = 3 * X_a^2 + a_curve */ + } else if (group->a_is_minus3) { + if (!field_sqr(group, n1, &a->Z, ctx) || + !BN_mod_add_quick(n0, &a->X, n1, p) || + !BN_mod_sub_quick(n2, &a->X, n1, p) || + !field_mul(group, n1, n0, n2, ctx) || + !BN_mod_lshift1_quick(n0, n1, p) || + !BN_mod_add_quick(n1, n0, n1, p)) { + goto err; + } + /* n1 = 3 * (X_a + Z_a^2) * (X_a - Z_a^2) + * = 3 * X_a^2 - 3 * Z_a^4 */ + } else { + if (!field_sqr(group, n0, &a->X, ctx) || + !BN_mod_lshift1_quick(n1, n0, p) || + !BN_mod_add_quick(n0, n0, n1, p) || + !field_sqr(group, n1, &a->Z, ctx) || + !field_sqr(group, n1, n1, ctx) || + !field_mul(group, n1, n1, &group->a, ctx) || + !BN_mod_add_quick(n1, n1, n0, p)) { + goto err; + } + /* n1 = 3 * X_a^2 + a_curve * Z_a^4 */ + } + + /* Z_r */ + if (BN_cmp(&a->Z, &group->one) == 0) { + if (!BN_copy(n0, &a->Y)) { + goto err; + } + } else if (!field_mul(group, n0, &a->Y, &a->Z, ctx)) { + goto err; + } + if (!BN_mod_lshift1_quick(&r->Z, n0, p)) { + goto err; + } + /* Z_r = 2 * Y_a * Z_a */ + + /* n2 */ + if (!field_sqr(group, n3, &a->Y, ctx) || + !field_mul(group, n2, &a->X, n3, ctx) || + !BN_mod_lshift_quick(n2, n2, 2, p)) { + goto err; + } + /* n2 = 4 * X_a * Y_a^2 */ + + /* X_r */ + if (!BN_mod_lshift1_quick(n0, n2, p) || + !field_sqr(group, &r->X, n1, ctx) || + !BN_mod_sub_quick(&r->X, &r->X, n0, p)) { + goto err; + } + /* X_r = n1^2 - 2 * n2 */ + + /* n3 */ + if (!field_sqr(group, n0, n3, ctx) || + !BN_mod_lshift_quick(n3, n0, 3, p)) { + goto err; + } + /* n3 = 8 * Y_a^4 */ + + /* Y_r */ + if (!BN_mod_sub_quick(n0, n2, &r->X, p) || + !field_mul(group, n0, n1, n0, ctx) || + !BN_mod_sub_quick(&r->Y, n0, n3, p)) { + goto err; + } + /* Y_r = n1 * (n2 - X_r) - n3 */ + + ret = 1; + +err: + BN_CTX_end(ctx); + BN_CTX_free(new_ctx); + return ret; +} + +int ec_GFp_simple_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx) { + if (EC_POINT_is_at_infinity(group, point) || BN_is_zero(&point->Y)) { + /* point is its own inverse */ + return 1; + } + + return BN_usub(&point->Y, &group->field, &point->Y); +} + +int ec_GFp_simple_is_at_infinity(const EC_GROUP *group, const EC_POINT *point) { + return BN_is_zero(&point->Z); +} + +int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, + BN_CTX *ctx) { + int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, + BN_CTX *); + int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *); + const BIGNUM *p; + BN_CTX *new_ctx = NULL; + BIGNUM *rh, *tmp, *Z4, *Z6; + int ret = 0; + + if (EC_POINT_is_at_infinity(group, point)) { + return 1; + } + + field_mul = group->meth->field_mul; + field_sqr = group->meth->field_sqr; + p = &group->field; + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) { + return 0; + } + } + + BN_CTX_start(ctx); + rh = BN_CTX_get(ctx); + tmp = BN_CTX_get(ctx); + Z4 = BN_CTX_get(ctx); + Z6 = BN_CTX_get(ctx); + if (Z6 == NULL) { + goto err; + } + + /* We have a curve defined by a Weierstrass equation + * y^2 = x^3 + a*x + b. + * The point to consider is given in Jacobian projective coordinates + * where (X, Y, Z) represents (x, y) = (X/Z^2, Y/Z^3). + * Substituting this and multiplying by Z^6 transforms the above equation + * into + * Y^2 = X^3 + a*X*Z^4 + b*Z^6. + * To test this, we add up the right-hand side in 'rh'. + */ + + /* rh := X^2 */ + if (!field_sqr(group, rh, &point->X, ctx)) { + goto err; + } + + if (BN_cmp(&point->Z, &group->one) != 0) { + if (!field_sqr(group, tmp, &point->Z, ctx) || + !field_sqr(group, Z4, tmp, ctx) || + !field_mul(group, Z6, Z4, tmp, ctx)) { + goto err; + } + + /* rh := (rh + a*Z^4)*X */ + if (group->a_is_minus3) { + if (!BN_mod_lshift1_quick(tmp, Z4, p) || + !BN_mod_add_quick(tmp, tmp, Z4, p) || + !BN_mod_sub_quick(rh, rh, tmp, p) || + !field_mul(group, rh, rh, &point->X, ctx)) { + goto err; + } + } else { + if (!field_mul(group, tmp, Z4, &group->a, ctx) || + !BN_mod_add_quick(rh, rh, tmp, p) || + !field_mul(group, rh, rh, &point->X, ctx)) { + goto err; + } + } + + /* rh := rh + b*Z^6 */ + if (!field_mul(group, tmp, &group->b, Z6, ctx) || + !BN_mod_add_quick(rh, rh, tmp, p)) { + goto err; + } + } else { + /* rh := (rh + a)*X */ + if (!BN_mod_add_quick(rh, rh, &group->a, p) || + !field_mul(group, rh, rh, &point->X, ctx)) { + goto err; + } + /* rh := rh + b */ + if (!BN_mod_add_quick(rh, rh, &group->b, p)) { + goto err; + } + } + + /* 'lh' := Y^2 */ + if (!field_sqr(group, tmp, &point->Y, ctx)) { + goto err; + } + + ret = (0 == BN_ucmp(tmp, rh)); + +err: + BN_CTX_end(ctx); + BN_CTX_free(new_ctx); + return ret; +} + +int ec_GFp_simple_cmp(const EC_GROUP *group, const EC_POINT *a, + const EC_POINT *b, BN_CTX *ctx) { + /* return values: + * -1 error + * 0 equal (in affine coordinates) + * 1 not equal + */ + + int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, + BN_CTX *); + int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *); + BN_CTX *new_ctx = NULL; + BIGNUM *tmp1, *tmp2, *Za23, *Zb23; + const BIGNUM *tmp1_, *tmp2_; + int ret = -1; + + if (EC_POINT_is_at_infinity(group, a)) { + return EC_POINT_is_at_infinity(group, b) ? 0 : 1; + } + + if (EC_POINT_is_at_infinity(group, b)) { + return 1; + } + + int a_Z_is_one = BN_cmp(&a->Z, &group->one) == 0; + int b_Z_is_one = BN_cmp(&b->Z, &group->one) == 0; + + if (a_Z_is_one && b_Z_is_one) { + return ((BN_cmp(&a->X, &b->X) == 0) && BN_cmp(&a->Y, &b->Y) == 0) ? 0 : 1; + } + + field_mul = group->meth->field_mul; + field_sqr = group->meth->field_sqr; + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) { + return -1; + } + } + + BN_CTX_start(ctx); + tmp1 = BN_CTX_get(ctx); + tmp2 = BN_CTX_get(ctx); + Za23 = BN_CTX_get(ctx); + Zb23 = BN_CTX_get(ctx); + if (Zb23 == NULL) { + goto end; + } + + /* We have to decide whether + * (X_a/Z_a^2, Y_a/Z_a^3) = (X_b/Z_b^2, Y_b/Z_b^3), + * or equivalently, whether + * (X_a*Z_b^2, Y_a*Z_b^3) = (X_b*Z_a^2, Y_b*Z_a^3). + */ + + if (!b_Z_is_one) { + if (!field_sqr(group, Zb23, &b->Z, ctx) || + !field_mul(group, tmp1, &a->X, Zb23, ctx)) { + goto end; + } + tmp1_ = tmp1; + } else { + tmp1_ = &a->X; + } + if (!a_Z_is_one) { + if (!field_sqr(group, Za23, &a->Z, ctx) || + !field_mul(group, tmp2, &b->X, Za23, ctx)) { + goto end; + } + tmp2_ = tmp2; + } else { + tmp2_ = &b->X; + } + + /* compare X_a*Z_b^2 with X_b*Z_a^2 */ + if (BN_cmp(tmp1_, tmp2_) != 0) { + ret = 1; /* points differ */ + goto end; + } + + + if (!b_Z_is_one) { + if (!field_mul(group, Zb23, Zb23, &b->Z, ctx) || + !field_mul(group, tmp1, &a->Y, Zb23, ctx)) { + goto end; + } + /* tmp1_ = tmp1 */ + } else { + tmp1_ = &a->Y; + } + if (!a_Z_is_one) { + if (!field_mul(group, Za23, Za23, &a->Z, ctx) || + !field_mul(group, tmp2, &b->Y, Za23, ctx)) { + goto end; + } + /* tmp2_ = tmp2 */ + } else { + tmp2_ = &b->Y; + } + + /* compare Y_a*Z_b^3 with Y_b*Z_a^3 */ + if (BN_cmp(tmp1_, tmp2_) != 0) { + ret = 1; /* points differ */ + goto end; + } + + /* points are equal */ + ret = 0; + +end: + BN_CTX_end(ctx); + BN_CTX_free(new_ctx); + return ret; +} + +int ec_GFp_simple_make_affine(const EC_GROUP *group, EC_POINT *point, + BN_CTX *ctx) { + BN_CTX *new_ctx = NULL; + BIGNUM *x, *y; + int ret = 0; + + if (BN_cmp(&point->Z, &group->one) == 0 || + EC_POINT_is_at_infinity(group, point)) { + return 1; + } + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) { + return 0; + } + } + + BN_CTX_start(ctx); + x = BN_CTX_get(ctx); + y = BN_CTX_get(ctx); + if (y == NULL) { + goto err; + } + + if (!EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx) || + !EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) { + goto err; + } + if (BN_cmp(&point->Z, &group->one) != 0) { + OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR); + goto err; + } + + ret = 1; + +err: + BN_CTX_end(ctx); + BN_CTX_free(new_ctx); + return ret; +} + +int ec_GFp_simple_points_make_affine(const EC_GROUP *group, size_t num, + EC_POINT *points[], BN_CTX *ctx) { + BN_CTX *new_ctx = NULL; + BIGNUM *tmp, *tmp_Z; + BIGNUM **prod_Z = NULL; + size_t i; + int ret = 0; + + if (num == 0) { + return 1; + } + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) { + return 0; + } + } + + BN_CTX_start(ctx); + tmp = BN_CTX_get(ctx); + tmp_Z = BN_CTX_get(ctx); + if (tmp == NULL || tmp_Z == NULL) { + goto err; + } + + prod_Z = OPENSSL_malloc(num * sizeof(prod_Z[0])); + if (prod_Z == NULL) { + goto err; + } + memset(prod_Z, 0, num * sizeof(prod_Z[0])); + for (i = 0; i < num; i++) { + prod_Z[i] = BN_new(); + if (prod_Z[i] == NULL) { + goto err; + } + } + + /* Set each prod_Z[i] to the product of points[0]->Z .. points[i]->Z, + * skipping any zero-valued inputs (pretend that they're 1). */ + + if (!BN_is_zero(&points[0]->Z)) { + if (!BN_copy(prod_Z[0], &points[0]->Z)) { + goto err; + } + } else { + if (BN_copy(prod_Z[0], &group->one) == NULL) { + goto err; + } + } + + for (i = 1; i < num; i++) { + if (!BN_is_zero(&points[i]->Z)) { + if (!group->meth->field_mul(group, prod_Z[i], prod_Z[i - 1], + &points[i]->Z, ctx)) { + goto err; + } + } else { + if (!BN_copy(prod_Z[i], prod_Z[i - 1])) { + goto err; + } + } + } + + /* Now use a single explicit inversion to replace every + * non-zero points[i]->Z by its inverse. */ + + if (!BN_mod_inverse(tmp, prod_Z[num - 1], &group->field, ctx)) { + OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); + goto err; + } + + if (group->meth->field_encode != NULL) { + /* In the Montgomery case, we just turned R*H (representing H) + * into 1/(R*H), but we need R*(1/H) (representing 1/H); + * i.e. we need to multiply by the Montgomery factor twice. */ + if (!group->meth->field_encode(group, tmp, tmp, ctx) || + !group->meth->field_encode(group, tmp, tmp, ctx)) { + goto err; + } + } + + for (i = num - 1; i > 0; --i) { + /* Loop invariant: tmp is the product of the inverses of + * points[0]->Z .. points[i]->Z (zero-valued inputs skipped). */ + if (BN_is_zero(&points[i]->Z)) { + continue; + } + + /* Set tmp_Z to the inverse of points[i]->Z (as product + * of Z inverses 0 .. i, Z values 0 .. i - 1). */ + if (!group->meth->field_mul(group, tmp_Z, prod_Z[i - 1], tmp, ctx) || + /* Update tmp to satisfy the loop invariant for i - 1. */ + !group->meth->field_mul(group, tmp, tmp, &points[i]->Z, ctx) || + /* Replace points[i]->Z by its inverse. */ + !BN_copy(&points[i]->Z, tmp_Z)) { + goto err; + } + } + + /* Replace points[0]->Z by its inverse. */ + if (!BN_is_zero(&points[0]->Z) && !BN_copy(&points[0]->Z, tmp)) { + goto err; + } + + /* Finally, fix up the X and Y coordinates for all points. */ + for (i = 0; i < num; i++) { + EC_POINT *p = points[i]; + + if (!BN_is_zero(&p->Z)) { + /* turn (X, Y, 1/Z) into (X/Z^2, Y/Z^3, 1). */ + if (!group->meth->field_sqr(group, tmp, &p->Z, ctx) || + !group->meth->field_mul(group, &p->X, &p->X, tmp, ctx) || + !group->meth->field_mul(group, tmp, tmp, &p->Z, ctx) || + !group->meth->field_mul(group, &p->Y, &p->Y, tmp, ctx)) { + goto err; + } + + if (BN_copy(&p->Z, &group->one) == NULL) { + goto err; + } + } + } + + ret = 1; + +err: + BN_CTX_end(ctx); + BN_CTX_free(new_ctx); + if (prod_Z != NULL) { + for (i = 0; i < num; i++) { + if (prod_Z[i] == NULL) { + break; + } + BN_clear_free(prod_Z[i]); + } + OPENSSL_free(prod_Z); + } + + return ret; +} + +int ec_GFp_simple_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, + const BIGNUM *b, BN_CTX *ctx) { + return BN_mod_mul(r, a, b, &group->field, ctx); +} + +int ec_GFp_simple_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, + BN_CTX *ctx) { + return BN_mod_sqr(r, a, &group->field, ctx); +} diff --git a/external/boringssl/crypto/ec/util-64.c b/external/boringssl/crypto/ec/util-64.c new file mode 100644 index 0000000000..4006271253 --- /dev/null +++ b/external/boringssl/crypto/ec/util-64.c @@ -0,0 +1,109 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + + +#if defined(OPENSSL_64_BIT) && !defined(OPENSSL_WINDOWS) + +#include + +#include "internal.h" + +/* This function looks at 5+1 scalar bits (5 current, 1 adjacent less + * significant bit), and recodes them into a signed digit for use in fast point + * multiplication: the use of signed rather than unsigned digits means that + * fewer points need to be precomputed, given that point inversion is easy (a + * precomputed point dP makes -dP available as well). + * + * BACKGROUND: + * + * Signed digits for multiplication were introduced by Booth ("A signed binary + * multiplication technique", Quart. Journ. Mech. and Applied Math., vol. IV, + * pt. 2 (1951), pp. 236-240), in that case for multiplication of integers. + * Booth's original encoding did not generally improve the density of nonzero + * digits over the binary representation, and was merely meant to simplify the + * handling of signed factors given in two's complement; but it has since been + * shown to be the basis of various signed-digit representations that do have + * further advantages, including the wNAF, using the following general + * approach: + * + * (1) Given a binary representation + * + * b_k ... b_2 b_1 b_0, + * + * of a nonnegative integer (b_k in {0, 1}), rewrite it in digits 0, 1, -1 + * by using bit-wise subtraction as follows: + * + * b_k b_(k-1) ... b_2 b_1 b_0 + * - b_k ... b_3 b_2 b_1 b_0 + * ------------------------------------- + * s_k b_(k-1) ... s_3 s_2 s_1 s_0 + * + * A left-shift followed by subtraction of the original value yields a new + * representation of the same value, using signed bits s_i = b_(i+1) - b_i. + * This representation from Booth's paper has since appeared in the + * literature under a variety of different names including "reversed binary + * form", "alternating greedy expansion", "mutual opposite form", and + * "sign-alternating {+-1}-representation". + * + * An interesting property is that among the nonzero bits, values 1 and -1 + * strictly alternate. + * + * (2) Various window schemes can be applied to the Booth representation of + * integers: for example, right-to-left sliding windows yield the wNAF + * (a signed-digit encoding independently discovered by various researchers + * in the 1990s), and left-to-right sliding windows yield a left-to-right + * equivalent of the wNAF (independently discovered by various researchers + * around 2004). + * + * To prevent leaking information through side channels in point multiplication, + * we need to recode the given integer into a regular pattern: sliding windows + * as in wNAFs won't do, we need their fixed-window equivalent -- which is a few + * decades older: we'll be using the so-called "modified Booth encoding" due to + * MacSorley ("High-speed arithmetic in binary computers", Proc. IRE, vol. 49 + * (1961), pp. 67-91), in a radix-2^5 setting. That is, we always combine five + * signed bits into a signed digit: + * + * s_(4j + 4) s_(4j + 3) s_(4j + 2) s_(4j + 1) s_(4j) + * + * The sign-alternating property implies that the resulting digit values are + * integers from -16 to 16. + * + * Of course, we don't actually need to compute the signed digits s_i as an + * intermediate step (that's just a nice way to see how this scheme relates + * to the wNAF): a direct computation obtains the recoded digit from the + * six bits b_(4j + 4) ... b_(4j - 1). + * + * This function takes those five bits as an integer (0 .. 63), writing the + * recoded digit to *sign (0 for positive, 1 for negative) and *digit (absolute + * value, in the range 0 .. 8). Note that this integer essentially provides the + * input bits "shifted to the left" by one position: for example, the input to + * compute the least significant recoded digit, given that there's no bit b_-1, + * has to be b_4 b_3 b_2 b_1 b_0 0. */ +void ec_GFp_nistp_recode_scalar_bits(uint8_t *sign, uint8_t *digit, + uint8_t in) { + uint8_t s, d; + + s = ~((in >> 5) - 1); /* sets all bits to MSB(in), 'in' seen as + * 6-bit value */ + d = (1 << 6) - in - 1; + d = (d & s) | (in & ~s); + d = (d >> 1) + (d & 1); + + *sign = s & 1; + *digit = d; +} + +#endif /* 64_BIT && !WINDOWS */ diff --git a/external/boringssl/crypto/ec/wnaf.c b/external/boringssl/crypto/ec/wnaf.c new file mode 100644 index 0000000000..ba2257c46f --- /dev/null +++ b/external/boringssl/crypto/ec/wnaf.c @@ -0,0 +1,449 @@ +/* Originally written by Bodo Moeller for the OpenSSL project. + * ==================================================================== + * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * + * Portions of the attached software ("Contribution") are developed by + * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. + * + * The Contribution is licensed pursuant to the OpenSSL open source + * license provided above. + * + * The elliptic curve binary polynomial software is originally written by + * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems + * Laboratories. */ + +#include + +#include + +#include +#include +#include +#include + +#include "internal.h" +#include "../internal.h" + + +/* This file implements the wNAF-based interleaving multi-exponentation method + * (); + * */ + +/* Determine the modified width-(w+1) Non-Adjacent Form (wNAF) of 'scalar'. + * This is an array r[] of values that are either zero or odd with an + * absolute value less than 2^w satisfying + * scalar = \sum_j r[j]*2^j + * where at most one of any w+1 consecutive digits is non-zero + * with the exception that the most significant digit may be only + * w-1 zeros away from that next non-zero digit. + */ +static signed char *compute_wNAF(const BIGNUM *scalar, int w, size_t *ret_len) { + int window_val; + int ok = 0; + signed char *r = NULL; + int sign = 1; + int bit, next_bit, mask; + size_t len = 0, j; + + if (BN_is_zero(scalar)) { + r = OPENSSL_malloc(1); + if (!r) { + OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); + goto err; + } + r[0] = 0; + *ret_len = 1; + return r; + } + + if (w <= 0 || w > 7) /* 'signed char' can represent integers with absolute + values less than 2^7 */ + { + OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR); + goto err; + } + bit = 1 << w; /* at most 128 */ + next_bit = bit << 1; /* at most 256 */ + mask = next_bit - 1; /* at most 255 */ + + if (BN_is_negative(scalar)) { + sign = -1; + } + + if (scalar->d == NULL || scalar->top == 0) { + OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR); + goto err; + } + + len = BN_num_bits(scalar); + r = OPENSSL_malloc( + len + + 1); /* modified wNAF may be one digit longer than binary representation + * (*ret_len will be set to the actual length, i.e. at most + * BN_num_bits(scalar) + 1) */ + if (r == NULL) { + OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); + goto err; + } + window_val = scalar->d[0] & mask; + j = 0; + while ((window_val != 0) || + (j + w + 1 < len)) /* if j+w+1 >= len, window_val will not increase */ + { + int digit = 0; + + /* 0 <= window_val <= 2^(w+1) */ + + if (window_val & 1) { + /* 0 < window_val < 2^(w+1) */ + + if (window_val & bit) { + digit = window_val - next_bit; /* -2^w < digit < 0 */ + +#if 1 /* modified wNAF */ + if (j + w + 1 >= len) { + /* special case for generating modified wNAFs: + * no new bits will be added into window_val, + * so using a positive digit here will decrease + * the total length of the representation */ + + digit = window_val & (mask >> 1); /* 0 < digit < 2^w */ + } +#endif + } else { + digit = window_val; /* 0 < digit < 2^w */ + } + + if (digit <= -bit || digit >= bit || !(digit & 1)) { + OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR); + goto err; + } + + window_val -= digit; + + /* now window_val is 0 or 2^(w+1) in standard wNAF generation; + * for modified window NAFs, it may also be 2^w + */ + if (window_val != 0 && window_val != next_bit && window_val != bit) { + OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR); + goto err; + } + } + + r[j++] = sign * digit; + + window_val >>= 1; + window_val += bit * BN_is_bit_set(scalar, j + w); + + if (window_val > next_bit) { + OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR); + goto err; + } + } + + if (j > len + 1) { + OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR); + goto err; + } + len = j; + ok = 1; + +err: + if (!ok) { + OPENSSL_free(r); + r = NULL; + } + if (ok) { + *ret_len = len; + } + return r; +} + + +/* TODO: table should be optimised for the wNAF-based implementation, + * sometimes smaller windows will give better performance + * (thus the boundaries should be increased) + */ +#define EC_window_bits_for_scalar_size(b) \ + ((size_t)((b) >= 2000 ? 6 : (b) >= 800 ? 5 : (b) >= 300 \ + ? 4 \ + : (b) >= 70 ? 3 : (b) >= 20 \ + ? 2 \ + : 1)) + +int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar, + const EC_POINT *p, const BIGNUM *p_scalar, BN_CTX *ctx) { + BN_CTX *new_ctx = NULL; + const EC_POINT *generator = NULL; + EC_POINT *tmp = NULL; + size_t total_num; + size_t i, j; + int k; + int r_is_inverted = 0; + int r_is_at_infinity = 1; + size_t *wsize = NULL; /* individual window sizes */ + signed char **wNAF = NULL; /* individual wNAFs */ + size_t *wNAF_len = NULL; + size_t max_len = 0; + size_t num_val; + EC_POINT **val = NULL; /* precomputation */ + EC_POINT **v; + EC_POINT ***val_sub = NULL; /* pointers to sub-arrays of 'val' */ + int ret = 0; + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) { + goto err; + } + } + + /* TODO: This function used to take |points| and |scalars| as arrays of + * |num| elements. The code below should be simplified to work in terms of |p| + * and |p_scalar|. */ + size_t num = p != NULL ? 1 : 0; + const EC_POINT **points = p != NULL ? &p : NULL; + const BIGNUM **scalars = p != NULL ? &p_scalar : NULL; + + total_num = num; + + if (g_scalar != NULL) { + generator = EC_GROUP_get0_generator(group); + if (generator == NULL) { + OPENSSL_PUT_ERROR(EC, EC_R_UNDEFINED_GENERATOR); + goto err; + } + + ++total_num; /* treat 'g_scalar' like 'num'-th element of 'scalars' */ + } + + + wsize = OPENSSL_malloc(total_num * sizeof wsize[0]); + wNAF_len = OPENSSL_malloc(total_num * sizeof wNAF_len[0]); + wNAF = OPENSSL_malloc((total_num + 1) * + sizeof wNAF[0]); /* includes space for pivot */ + val_sub = OPENSSL_malloc(total_num * sizeof val_sub[0]); + + /* Ensure wNAF is initialised in case we end up going to err. */ + if (wNAF) { + wNAF[0] = NULL; /* preliminary pivot */ + } + + if (!wsize || !wNAF_len || !wNAF || !val_sub) { + OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); + goto err; + } + + /* num_val will be the total number of temporarily precomputed points */ + num_val = 0; + + for (i = 0; i < total_num; i++) { + size_t bits; + + bits = i < num ? BN_num_bits(scalars[i]) : BN_num_bits(g_scalar); + wsize[i] = EC_window_bits_for_scalar_size(bits); + num_val += (size_t)1 << (wsize[i] - 1); + wNAF[i + 1] = NULL; /* make sure we always have a pivot */ + wNAF[i] = + compute_wNAF((i < num ? scalars[i] : g_scalar), wsize[i], &wNAF_len[i]); + if (wNAF[i] == NULL) { + goto err; + } + if (wNAF_len[i] > max_len) { + max_len = wNAF_len[i]; + } + } + + /* All points we precompute now go into a single array 'val'. 'val_sub[i]' is + * a pointer to the subarray for the i-th point. */ + val = OPENSSL_malloc((num_val + 1) * sizeof val[0]); + if (val == NULL) { + OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); + goto err; + } + val[num_val] = NULL; /* pivot element */ + + /* allocate points for precomputation */ + v = val; + for (i = 0; i < total_num; i++) { + val_sub[i] = v; + for (j = 0; j < ((size_t)1 << (wsize[i] - 1)); j++) { + *v = EC_POINT_new(group); + if (*v == NULL) { + goto err; + } + v++; + } + } + if (!(v == val + num_val)) { + OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR); + goto err; + } + + if (!(tmp = EC_POINT_new(group))) { + goto err; + } + + /* prepare precomputed values: + * val_sub[i][0] := points[i] + * val_sub[i][1] := 3 * points[i] + * val_sub[i][2] := 5 * points[i] + * ... + */ + for (i = 0; i < total_num; i++) { + if (i < num) { + if (!EC_POINT_copy(val_sub[i][0], points[i])) { + goto err; + } + } else if (!EC_POINT_copy(val_sub[i][0], generator)) { + goto err; + } + + if (wsize[i] > 1) { + if (!EC_POINT_dbl(group, tmp, val_sub[i][0], ctx)) { + goto err; + } + for (j = 1; j < ((size_t)1 << (wsize[i] - 1)); j++) { + if (!EC_POINT_add(group, val_sub[i][j], val_sub[i][j - 1], tmp, ctx)) { + goto err; + } + } + } + } + +#if 1 /* optional; EC_window_bits_for_scalar_size assumes we do this step */ + if (!EC_POINTs_make_affine(group, num_val, val, ctx)) { + goto err; + } +#endif + + r_is_at_infinity = 1; + + for (k = max_len - 1; k >= 0; k--) { + if (!r_is_at_infinity && !EC_POINT_dbl(group, r, r, ctx)) { + goto err; + } + + for (i = 0; i < total_num; i++) { + if (wNAF_len[i] > (size_t)k) { + int digit = wNAF[i][k]; + int is_neg; + + if (digit) { + is_neg = digit < 0; + + if (is_neg) { + digit = -digit; + } + + if (is_neg != r_is_inverted) { + if (!r_is_at_infinity && !EC_POINT_invert(group, r, ctx)) { + goto err; + } + r_is_inverted = !r_is_inverted; + } + + /* digit > 0 */ + + if (r_is_at_infinity) { + if (!EC_POINT_copy(r, val_sub[i][digit >> 1])) { + goto err; + } + r_is_at_infinity = 0; + } else { + if (!EC_POINT_add(group, r, r, val_sub[i][digit >> 1], ctx)) { + goto err; + } + } + } + } + } + } + + if (r_is_at_infinity) { + if (!EC_POINT_set_to_infinity(group, r)) { + goto err; + } + } else if (r_is_inverted && !EC_POINT_invert(group, r, ctx)) { + goto err; + } + + ret = 1; + +err: + BN_CTX_free(new_ctx); + EC_POINT_free(tmp); + OPENSSL_free(wsize); + OPENSSL_free(wNAF_len); + if (wNAF != NULL) { + signed char **w; + + for (w = wNAF; *w != NULL; w++) { + OPENSSL_free(*w); + } + + OPENSSL_free(wNAF); + } + if (val != NULL) { + for (v = val; *v != NULL; v++) { + EC_POINT_clear_free(*v); + } + + OPENSSL_free(val); + } + OPENSSL_free(val_sub); + return ret; +} diff --git a/external/boringssl/crypto/ecdh/CMakeLists.txt b/external/boringssl/crypto/ecdh/CMakeLists.txt new file mode 100644 index 0000000000..8eaeae5e70 --- /dev/null +++ b/external/boringssl/crypto/ecdh/CMakeLists.txt @@ -0,0 +1,9 @@ +include_directories(../../include) + +add_library( + ecdh + + OBJECT + + ecdh.c +) diff --git a/external/boringssl/crypto/ecdh/ecdh.c b/external/boringssl/crypto/ecdh/ecdh.c new file mode 100644 index 0000000000..4a1964a0b3 --- /dev/null +++ b/external/boringssl/crypto/ecdh/ecdh.c @@ -0,0 +1,153 @@ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * + * The Elliptic Curve Public-Key Crypto Library (ECC Code) included + * herein is developed by SUN MICROSYSTEMS, INC., and is contributed + * to the OpenSSL project. + * + * The ECC Code is licensed pursuant to the OpenSSL open source + * license provided below. + * + * The ECDH software is originally written by Douglas Stebila of + * Sun Microsystems Laboratories. + * + */ +/* ==================================================================== + * Copyright (c) 2000-2002 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include + +#include +#include +#include +#include + + +int ECDH_compute_key(void *out, size_t outlen, const EC_POINT *pub_key, + EC_KEY *priv_key, + void *(*kdf)(const void *in, size_t inlen, void *out, + size_t *outlen)) { + const BIGNUM *const priv = EC_KEY_get0_private_key(priv_key); + if (priv == NULL) { + OPENSSL_PUT_ERROR(ECDH, ECDH_R_NO_PRIVATE_VALUE); + return -1; + } + + BN_CTX *ctx = BN_CTX_new(); + if (ctx == NULL) { + return -1; + } + BN_CTX_start(ctx); + + int ret = -1; + size_t buflen = 0; + uint8_t *buf = NULL; + + const EC_GROUP *const group = EC_KEY_get0_group(priv_key); + EC_POINT *tmp = EC_POINT_new(group); + if (tmp == NULL) { + OPENSSL_PUT_ERROR(ECDH, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (!EC_POINT_mul(group, tmp, NULL, pub_key, priv, ctx)) { + OPENSSL_PUT_ERROR(ECDH, ECDH_R_POINT_ARITHMETIC_FAILURE); + goto err; + } + + BIGNUM *x = BN_CTX_get(ctx); + if (!x) { + OPENSSL_PUT_ERROR(ECDH, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (!EC_POINT_get_affine_coordinates_GFp(group, tmp, x, NULL, ctx)) { + OPENSSL_PUT_ERROR(ECDH, ECDH_R_POINT_ARITHMETIC_FAILURE); + goto err; + } + + buflen = (EC_GROUP_get_degree(group) + 7) / 8; + buf = OPENSSL_malloc(buflen); + if (buf == NULL) { + OPENSSL_PUT_ERROR(ECDH, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (!BN_bn2bin_padded(buf, buflen, x)) { + OPENSSL_PUT_ERROR(ECDH, ERR_R_INTERNAL_ERROR); + goto err; + } + + if (kdf != NULL) { + if (kdf(buf, buflen, out, &outlen) == NULL) { + OPENSSL_PUT_ERROR(ECDH, ECDH_R_KDF_FAILED); + goto err; + } + } else { + /* no KDF, just copy as much as we can */ + if (buflen < outlen) { + outlen = buflen; + } + memcpy(out, buf, outlen); + } + + ret = outlen; + +err: + OPENSSL_free(buf); + EC_POINT_free(tmp); + BN_CTX_end(ctx); + BN_CTX_free(ctx); + return ret; +} diff --git a/external/boringssl/crypto/ecdsa/CMakeLists.txt b/external/boringssl/crypto/ecdsa/CMakeLists.txt new file mode 100644 index 0000000000..f9af1ed714 --- /dev/null +++ b/external/boringssl/crypto/ecdsa/CMakeLists.txt @@ -0,0 +1,24 @@ +include_directories(../../include) + +add_library( + ecdsa + + OBJECT + + ecdsa.c + ecdsa_asn1.c +) + + +if(ENABLE_TESTS) +add_executable( + ecdsa_test + + ecdsa_test.cc + + $ +) + +target_link_libraries(ecdsa_test crypto) +add_dependencies(all_tests ecdsa_test) +endif() diff --git a/external/boringssl/crypto/ecdsa/ecdsa.c b/external/boringssl/crypto/ecdsa/ecdsa.c new file mode 100644 index 0000000000..70cb11897b --- /dev/null +++ b/external/boringssl/crypto/ecdsa/ecdsa.c @@ -0,0 +1,487 @@ +/* ==================================================================== + * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include + +#include +#include +#include +#include + +#include "../ec/internal.h" + + +int ECDSA_sign(int type, const uint8_t *digest, size_t digest_len, uint8_t *sig, + unsigned int *sig_len, EC_KEY *eckey) { + if (eckey->ecdsa_meth && eckey->ecdsa_meth->sign) { + return eckey->ecdsa_meth->sign(digest, digest_len, sig, sig_len, eckey); + } + + return ECDSA_sign_ex(type, digest, digest_len, sig, sig_len, NULL, NULL, + eckey); +} + +int ECDSA_verify(int type, const uint8_t *digest, size_t digest_len, + const uint8_t *sig, size_t sig_len, EC_KEY *eckey) { + ECDSA_SIG *s; + int ret = 0; + uint8_t *der = NULL; + + /* Decode the ECDSA signature. */ + s = ECDSA_SIG_from_bytes(sig, sig_len); + if (s == NULL) { + goto err; + } + + /* Defend against potential laxness in the DER parser. */ + size_t der_len; + if (!ECDSA_SIG_to_bytes(&der, &der_len, s) || + der_len != sig_len || memcmp(sig, der, sig_len) != 0) { + /* This should never happen. crypto/bytestring is strictly DER. */ + OPENSSL_PUT_ERROR(ECDSA, ERR_R_INTERNAL_ERROR); + goto err; + } + + ret = ECDSA_do_verify(digest, digest_len, s, eckey); + +err: + OPENSSL_free(der); + ECDSA_SIG_free(s); + return ret; +} + +/* digest_to_bn interprets |digest_len| bytes from |digest| as a big-endian + * number and sets |out| to that value. It then truncates |out| so that it's, + * at most, as long as |order|. It returns one on success and zero otherwise. */ +static int digest_to_bn(BIGNUM *out, const uint8_t *digest, size_t digest_len, + const BIGNUM *order) { + size_t num_bits; + + num_bits = BN_num_bits(order); + /* Need to truncate digest if it is too long: first truncate whole + * bytes. */ + if (8 * digest_len > num_bits) { + digest_len = (num_bits + 7) / 8; + } + if (!BN_bin2bn(digest, digest_len, out)) { + OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB); + return 0; + } + + /* If still too long truncate remaining bits with a shift */ + if ((8 * digest_len > num_bits) && + !BN_rshift(out, out, 8 - (num_bits & 0x7))) { + OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB); + return 0; + } + + return 1; +} + +ECDSA_SIG *ECDSA_do_sign(const uint8_t *digest, size_t digest_len, + EC_KEY *key) { + return ECDSA_do_sign_ex(digest, digest_len, NULL, NULL, key); +} + +int ECDSA_do_verify(const uint8_t *digest, size_t digest_len, + const ECDSA_SIG *sig, EC_KEY *eckey) { + int ret = 0; + BN_CTX *ctx; + BIGNUM *u1, *u2, *m, *X; + EC_POINT *point = NULL; + const EC_GROUP *group; + const EC_POINT *pub_key; + + /* check input values */ + if ((group = EC_KEY_get0_group(eckey)) == NULL || + (pub_key = EC_KEY_get0_public_key(eckey)) == NULL || + sig == NULL) { + OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_MISSING_PARAMETERS); + return 0; + } + + ctx = BN_CTX_new(); + if (!ctx) { + OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE); + return 0; + } + BN_CTX_start(ctx); + u1 = BN_CTX_get(ctx); + u2 = BN_CTX_get(ctx); + m = BN_CTX_get(ctx); + X = BN_CTX_get(ctx); + if (u1 == NULL || u2 == NULL || m == NULL || X == NULL) { + OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB); + goto err; + } + + const BIGNUM *order = EC_GROUP_get0_order(group); + if (BN_is_zero(sig->r) || BN_is_negative(sig->r) || + BN_ucmp(sig->r, order) >= 0 || BN_is_zero(sig->s) || + BN_is_negative(sig->s) || BN_ucmp(sig->s, order) >= 0) { + OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_BAD_SIGNATURE); + ret = 0; /* signature is invalid */ + goto err; + } + /* calculate tmp1 = inv(S) mod order */ + if (!BN_mod_inverse(u2, sig->s, order, ctx)) { + OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB); + goto err; + } + if (!digest_to_bn(m, digest, digest_len, order)) { + goto err; + } + /* u1 = m * tmp mod order */ + if (!BN_mod_mul(u1, m, u2, order, ctx)) { + OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB); + goto err; + } + /* u2 = r * w mod q */ + if (!BN_mod_mul(u2, sig->r, u2, order, ctx)) { + OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB); + goto err; + } + + point = EC_POINT_new(group); + if (point == NULL) { + OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE); + goto err; + } + if (!EC_POINT_mul(group, point, u1, pub_key, u2, ctx)) { + OPENSSL_PUT_ERROR(ECDSA, ERR_R_EC_LIB); + goto err; + } + if (!EC_POINT_get_affine_coordinates_GFp(group, point, X, NULL, ctx)) { + OPENSSL_PUT_ERROR(ECDSA, ERR_R_EC_LIB); + goto err; + } + if (!BN_nnmod(u1, X, order, ctx)) { + OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB); + goto err; + } + /* if the signature is correct u1 is equal to sig->r */ + ret = (BN_ucmp(u1, sig->r) == 0); + +err: + BN_CTX_end(ctx); + BN_CTX_free(ctx); + EC_POINT_free(point); + return ret; +} + +static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, + BIGNUM **rp, const uint8_t *digest, + size_t digest_len) { + BN_CTX *ctx = NULL; + BIGNUM *k = NULL, *r = NULL, *X = NULL; + EC_POINT *tmp_point = NULL; + const EC_GROUP *group; + int ret = 0; + + if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL) { + OPENSSL_PUT_ERROR(ECDSA, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (ctx_in == NULL) { + if ((ctx = BN_CTX_new()) == NULL) { + OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE); + return 0; + } + } else { + ctx = ctx_in; + } + + k = BN_new(); /* this value is later returned in *kinvp */ + r = BN_new(); /* this value is later returned in *rp */ + X = BN_new(); + if (k == NULL || r == NULL || X == NULL) { + OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE); + goto err; + } + tmp_point = EC_POINT_new(group); + if (tmp_point == NULL) { + OPENSSL_PUT_ERROR(ECDSA, ERR_R_EC_LIB); + goto err; + } + + const BIGNUM *order = EC_GROUP_get0_order(group); + + do { + /* If possible, we'll include the private key and message digest in the k + * generation. The |digest| argument is only empty if |ECDSA_sign_setup| is + * being used. */ + do { + int ok; + + if (digest_len > 0) { + ok = BN_generate_dsa_nonce(k, order, EC_KEY_get0_private_key(eckey), + digest, digest_len, ctx); + } else { + ok = BN_rand_range(k, order); + } + if (!ok) { + OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED); + goto err; + } + } while (BN_is_zero(k)); + + /* We do not want timing information to leak the length of k, + * so we compute G*k using an equivalent scalar of fixed + * bit-length. */ + + if (!BN_add(k, k, order)) { + goto err; + } + if (BN_num_bits(k) <= BN_num_bits(order)) { + if (!BN_add(k, k, order)) { + goto err; + } + } + + /* compute r the x-coordinate of generator * k */ + if (!EC_POINT_mul(group, tmp_point, k, NULL, NULL, ctx)) { + OPENSSL_PUT_ERROR(ECDSA, ERR_R_EC_LIB); + goto err; + } + if (!EC_POINT_get_affine_coordinates_GFp(group, tmp_point, X, NULL, ctx)) { + OPENSSL_PUT_ERROR(ECDSA, ERR_R_EC_LIB); + goto err; + } + + if (!BN_nnmod(r, X, order, ctx)) { + OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB); + goto err; + } + } while (BN_is_zero(r)); + + /* compute the inverse of k */ + if (ec_group_get_mont_data(group) != NULL) { + /* We want inverse in constant time, therefore we use that the order must + * be prime and thus we can use Fermat's Little Theorem. */ + if (!BN_set_word(X, 2) || + !BN_sub(X, order, X)) { + OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB); + goto err; + } + BN_set_flags(X, BN_FLG_CONSTTIME); + if (!BN_mod_exp_mont_consttime(k, k, X, order, ctx, + ec_group_get_mont_data(group))) { + OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB); + goto err; + } + } else if (!BN_mod_inverse(k, k, order, ctx)) { + OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB); + goto err; + } + /* clear old values if necessary */ + BN_clear_free(*rp); + BN_clear_free(*kinvp); + + /* save the pre-computed values */ + *rp = r; + *kinvp = k; + ret = 1; + +err: + if (!ret) { + BN_clear_free(k); + BN_clear_free(r); + } + if (ctx_in == NULL) { + BN_CTX_free(ctx); + } + EC_POINT_free(tmp_point); + BN_clear_free(X); + return ret; +} + +int ECDSA_sign_setup(EC_KEY *eckey, BN_CTX *ctx, BIGNUM **kinv, BIGNUM **rp) { + return ecdsa_sign_setup(eckey, ctx, kinv, rp, NULL, 0); +} + +ECDSA_SIG *ECDSA_do_sign_ex(const uint8_t *digest, size_t digest_len, + const BIGNUM *in_kinv, const BIGNUM *in_r, + EC_KEY *eckey) { + int ok = 0; + BIGNUM *kinv = NULL, *s, *m = NULL, *tmp = NULL; + const BIGNUM *ckinv; + BN_CTX *ctx = NULL; + const EC_GROUP *group; + ECDSA_SIG *ret; + const BIGNUM *priv_key; + + if (eckey->ecdsa_meth && eckey->ecdsa_meth->sign) { + OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_NOT_IMPLEMENTED); + return NULL; + } + + group = EC_KEY_get0_group(eckey); + priv_key = EC_KEY_get0_private_key(eckey); + + if (group == NULL || priv_key == NULL) { + OPENSSL_PUT_ERROR(ECDSA, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + + ret = ECDSA_SIG_new(); + if (!ret) { + OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE); + return NULL; + } + s = ret->s; + + if ((ctx = BN_CTX_new()) == NULL || + (tmp = BN_new()) == NULL || + (m = BN_new()) == NULL) { + OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE); + goto err; + } + + const BIGNUM *order = EC_GROUP_get0_order(group); + + if (!digest_to_bn(m, digest, digest_len, order)) { + goto err; + } + for (;;) { + if (in_kinv == NULL || in_r == NULL) { + if (!ecdsa_sign_setup(eckey, ctx, &kinv, &ret->r, digest, digest_len)) { + OPENSSL_PUT_ERROR(ECDSA, ERR_R_ECDSA_LIB); + goto err; + } + ckinv = kinv; + } else { + ckinv = in_kinv; + if (BN_copy(ret->r, in_r) == NULL) { + OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE); + goto err; + } + } + + if (!BN_mod_mul(tmp, priv_key, ret->r, order, ctx)) { + OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB); + goto err; + } + if (!BN_mod_add_quick(s, tmp, m, order)) { + OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB); + goto err; + } + if (!BN_mod_mul(s, s, ckinv, order, ctx)) { + OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB); + goto err; + } + if (BN_is_zero(s)) { + /* if kinv and r have been supplied by the caller + * don't to generate new kinv and r values */ + if (in_kinv != NULL && in_r != NULL) { + OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_NEED_NEW_SETUP_VALUES); + goto err; + } + } else { + /* s != 0 => we have a valid signature */ + break; + } + } + + ok = 1; + +err: + if (!ok) { + ECDSA_SIG_free(ret); + ret = NULL; + } + BN_CTX_free(ctx); + BN_clear_free(m); + BN_clear_free(tmp); + BN_clear_free(kinv); + return ret; +} + +int ECDSA_sign_ex(int type, const uint8_t *digest, size_t digest_len, + uint8_t *sig, unsigned int *sig_len, const BIGNUM *kinv, + const BIGNUM *r, EC_KEY *eckey) { + int ret = 0; + ECDSA_SIG *s = NULL; + + if (eckey->ecdsa_meth && eckey->ecdsa_meth->sign) { + OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_NOT_IMPLEMENTED); + *sig_len = 0; + goto err; + } + + s = ECDSA_do_sign_ex(digest, digest_len, kinv, r, eckey); + if (s == NULL) { + *sig_len = 0; + goto err; + } + + CBB cbb; + CBB_zero(&cbb); + size_t len; + if (!CBB_init_fixed(&cbb, sig, ECDSA_size(eckey)) || + !ECDSA_SIG_marshal(&cbb, s) || + !CBB_finish(&cbb, NULL, &len)) { + OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_ENCODE_ERROR); + CBB_cleanup(&cbb); + *sig_len = 0; + goto err; + } + *sig_len = (unsigned)len; + ret = 1; + +err: + ECDSA_SIG_free(s); + return ret; +} diff --git a/external/boringssl/crypto/ecdsa/ecdsa_asn1.c b/external/boringssl/crypto/ecdsa/ecdsa_asn1.c new file mode 100644 index 0000000000..d41a536679 --- /dev/null +++ b/external/boringssl/crypto/ecdsa/ecdsa_asn1.c @@ -0,0 +1,227 @@ +/* ==================================================================== + * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include "../bytestring/internal.h" +#include "../ec/internal.h" + + +size_t ECDSA_size(const EC_KEY *key) { + if (key == NULL) { + return 0; + } + + size_t group_order_size; + if (key->ecdsa_meth && key->ecdsa_meth->group_order_size) { + group_order_size = key->ecdsa_meth->group_order_size(key); + } else { + const EC_GROUP *group = EC_KEY_get0_group(key); + if (group == NULL) { + return 0; + } + + group_order_size = BN_num_bytes(EC_GROUP_get0_order(group)); + } + + return ECDSA_SIG_max_len(group_order_size); +} + +ECDSA_SIG *ECDSA_SIG_new(void) { + ECDSA_SIG *sig = OPENSSL_malloc(sizeof(ECDSA_SIG)); + if (sig == NULL) { + return NULL; + } + sig->r = BN_new(); + sig->s = BN_new(); + if (sig->r == NULL || sig->s == NULL) { + ECDSA_SIG_free(sig); + return NULL; + } + return sig; +} + +void ECDSA_SIG_free(ECDSA_SIG *sig) { + if (sig == NULL) { + return; + } + + BN_free(sig->r); + BN_free(sig->s); + OPENSSL_free(sig); +} + +ECDSA_SIG *ECDSA_SIG_parse(CBS *cbs) { + ECDSA_SIG *ret = ECDSA_SIG_new(); + if (ret == NULL) { + return NULL; + } + CBS child; + if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) || + !BN_parse_asn1_unsigned(&child, ret->r) || + !BN_parse_asn1_unsigned(&child, ret->s) || + CBS_len(&child) != 0) { + OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_BAD_SIGNATURE); + ECDSA_SIG_free(ret); + return NULL; + } + return ret; +} + +ECDSA_SIG *ECDSA_SIG_from_bytes(const uint8_t *in, size_t in_len) { + CBS cbs; + CBS_init(&cbs, in, in_len); + ECDSA_SIG *ret = ECDSA_SIG_parse(&cbs); + if (ret == NULL || CBS_len(&cbs) != 0) { + OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_BAD_SIGNATURE); + ECDSA_SIG_free(ret); + return NULL; + } + return ret; +} + +int ECDSA_SIG_marshal(CBB *cbb, const ECDSA_SIG *sig) { + CBB child; + if (!CBB_add_asn1(cbb, &child, CBS_ASN1_SEQUENCE) || + !BN_marshal_asn1(&child, sig->r) || + !BN_marshal_asn1(&child, sig->s) || + !CBB_flush(cbb)) { + OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_ENCODE_ERROR); + return 0; + } + return 1; +} + +int ECDSA_SIG_to_bytes(uint8_t **out_bytes, size_t *out_len, + const ECDSA_SIG *sig) { + CBB cbb; + CBB_zero(&cbb); + if (!CBB_init(&cbb, 0) || + !ECDSA_SIG_marshal(&cbb, sig) || + !CBB_finish(&cbb, out_bytes, out_len)) { + OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_ENCODE_ERROR); + CBB_cleanup(&cbb); + return 0; + } + return 1; +} + +/* der_len_len returns the number of bytes needed to represent a length of |len| + * in DER. */ +static size_t der_len_len(size_t len) { + if (len < 0x80) { + return 1; + } + size_t ret = 1; + while (len > 0) { + ret++; + len >>= 8; + } + return ret; +} + +size_t ECDSA_SIG_max_len(size_t order_len) { + /* Compute the maximum length of an |order_len| byte integer. Defensively + * assume that the leading 0x00 is included. */ + size_t integer_len = 1 /* tag */ + der_len_len(order_len + 1) + 1 + order_len; + if (integer_len < order_len) { + return 0; + } + /* An ECDSA signature is two INTEGERs. */ + size_t value_len = 2 * integer_len; + if (value_len < integer_len) { + return 0; + } + /* Add the header. */ + size_t ret = 1 /* tag */ + der_len_len(value_len) + value_len; + if (ret < value_len) { + return 0; + } + return ret; +} + +ECDSA_SIG *d2i_ECDSA_SIG(ECDSA_SIG **out, const uint8_t **inp, long len) { + if (len < 0) { + return NULL; + } + CBS cbs; + CBS_init(&cbs, *inp, (size_t)len); + ECDSA_SIG *ret = ECDSA_SIG_parse(&cbs); + if (ret == NULL) { + return NULL; + } + if (out != NULL) { + ECDSA_SIG_free(*out); + *out = ret; + } + *inp = CBS_data(&cbs); + return ret; +} + +int i2d_ECDSA_SIG(const ECDSA_SIG *sig, uint8_t **outp) { + CBB cbb; + if (!CBB_init(&cbb, 0) || + !ECDSA_SIG_marshal(&cbb, sig)) { + CBB_cleanup(&cbb); + return -1; + } + return CBB_finish_i2d(&cbb, outp); +} diff --git a/external/boringssl/crypto/ecdsa/ecdsa_test.cc b/external/boringssl/crypto/ecdsa/ecdsa_test.cc new file mode 100644 index 0000000000..8d7827df5e --- /dev/null +++ b/external/boringssl/crypto/ecdsa/ecdsa_test.cc @@ -0,0 +1,363 @@ +/* ==================================================================== + * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "../test/scoped_types.h" + +enum Api { + kEncodedApi, + kRawApi, +}; + +// VerifyECDSASig returns true on success, false on failure. +static bool VerifyECDSASig(Api api, const uint8_t *digest, + size_t digest_len, const ECDSA_SIG *ecdsa_sig, + EC_KEY *eckey, int expected_result) { + int actual_result; + + switch (api) { + case kEncodedApi: { + uint8_t *der; + size_t der_len; + if (!ECDSA_SIG_to_bytes(&der, &der_len, ecdsa_sig)) { + return false; + } + ScopedOpenSSLBytes delete_der(der); + actual_result = ECDSA_verify(0, digest, digest_len, der, der_len, eckey); + break; + } + + case kRawApi: + actual_result = ECDSA_do_verify(digest, digest_len, ecdsa_sig, eckey); + break; + + default: + return false; + } + return expected_result == actual_result; +} + +// TestTamperedSig verifies that signature verification fails when a valid +// signature is tampered with. |ecdsa_sig| must be a valid signature, which will +// be modified. TestTamperedSig returns true on success, false on failure. +static bool TestTamperedSig(FILE *out, Api api, const uint8_t *digest, + size_t digest_len, ECDSA_SIG *ecdsa_sig, + EC_KEY *eckey, const BIGNUM *order) { + // Modify a single byte of the signature: to ensure we don't + // garble the ASN1 structure, we read the raw signature and + // modify a byte in one of the bignums directly. + + // Store the two BIGNUMs in raw_buf. + size_t r_len = BN_num_bytes(ecdsa_sig->r); + size_t s_len = BN_num_bytes(ecdsa_sig->s); + size_t bn_len = BN_num_bytes(order); + if (r_len > bn_len || s_len > bn_len) { + return false; + } + size_t buf_len = 2 * bn_len; + std::vector raw_buf(buf_len); + // Pad the bignums with leading zeroes. + if (!BN_bn2bin_padded(raw_buf.data(), bn_len, ecdsa_sig->r) || + !BN_bn2bin_padded(raw_buf.data() + bn_len, bn_len, ecdsa_sig->s)) { + return false; + } + + // Modify a single byte in the buffer. + size_t offset = raw_buf[10] % buf_len; + uint8_t dirt = raw_buf[11] ? raw_buf[11] : 1; + raw_buf[offset] ^= dirt; + // Now read the BIGNUMs back in from raw_buf. + if (BN_bin2bn(raw_buf.data(), bn_len, ecdsa_sig->r) == NULL || + BN_bin2bn(raw_buf.data() + bn_len, bn_len, ecdsa_sig->s) == NULL || + !VerifyECDSASig(api, digest, digest_len, ecdsa_sig, eckey, 0)) { + return false; + } + + // Sanity check: Undo the modification and verify signature. + raw_buf[offset] ^= dirt; + if (BN_bin2bn(raw_buf.data(), bn_len, ecdsa_sig->r) == NULL || + BN_bin2bn(raw_buf.data() + bn_len, bn_len, ecdsa_sig->s) == NULL || + !VerifyECDSASig(api, digest, digest_len, ecdsa_sig, eckey, 1)) { + return false; + } + + return true; +} + +static bool TestBuiltin(FILE *out) { + // Fill digest values with some random data. + uint8_t digest[20], wrong_digest[20]; + if (!RAND_bytes(digest, 20) || !RAND_bytes(wrong_digest, 20)) { + fprintf(out, "ERROR: unable to get random data\n"); + return false; + } + + static const struct { + int nid; + const char *name; + } kCurves[] = { + { NID_secp224r1, "secp224r1" }, + { NID_X9_62_prime256v1, "secp256r1" }, + { NID_secp384r1, "secp384r1" }, + { NID_secp521r1, "secp521r1" }, + { NID_undef, NULL } + }; + + // Create and verify ECDSA signatures with every available curve. + fputs("\ntesting ECDSA_sign(), ECDSA_verify(), ECDSA_do_sign(), and " + "ECDSA_do_verify() with some internal curves:\n", out); + + for (size_t n = 0; kCurves[n].nid != NID_undef; n++) { + fprintf(out, "%s: ", kCurves[n].name); + + int nid = kCurves[n].nid; + ScopedEC_GROUP group(EC_GROUP_new_by_curve_name(nid)); + if (!group) { + fprintf(out, " failed\n"); + return false; + } + const BIGNUM *order = EC_GROUP_get0_order(group.get()); + if (BN_num_bits(order) < 160) { + // Too small to test. + fprintf(out, " skipped\n"); + continue; + } + + // Create a new ECDSA key. + ScopedEC_KEY eckey(EC_KEY_new()); + if (!eckey || !EC_KEY_set_group(eckey.get(), group.get()) || + !EC_KEY_generate_key(eckey.get())) { + fprintf(out, " failed\n"); + return false; + } + // Create a second key. + ScopedEC_KEY wrong_eckey(EC_KEY_new()); + if (!wrong_eckey || !EC_KEY_set_group(wrong_eckey.get(), group.get()) || + !EC_KEY_generate_key(wrong_eckey.get())) { + fprintf(out, " failed\n"); + return false; + } + + fprintf(out, "."); + fflush(out); + + // Check the key. + if (!EC_KEY_check_key(eckey.get())) { + fprintf(out, " failed\n"); + return false; + } + fprintf(out, "."); + fflush(out); + + // Test ASN.1-encoded signatures. + // Create a signature. + unsigned sig_len = ECDSA_size(eckey.get()); + std::vector signature(sig_len); + if (!ECDSA_sign(0, digest, 20, signature.data(), &sig_len, eckey.get())) { + fprintf(out, " failed\n"); + return false; + } + signature.resize(sig_len); + fprintf(out, "."); + fflush(out); + // Verify the signature. + if (!ECDSA_verify(0, digest, 20, signature.data(), signature.size(), + eckey.get())) { + fprintf(out, " failed\n"); + return false; + } + fprintf(out, "."); + fflush(out); + // Verify the signature with the wrong key. + if (ECDSA_verify(0, digest, 20, signature.data(), signature.size(), + wrong_eckey.get())) { + fprintf(out, " failed\n"); + return false; + } + fprintf(out, "."); + fflush(out); + // Verify the signature using the wrong digest. + if (ECDSA_verify(0, wrong_digest, 20, signature.data(), signature.size(), + eckey.get())) { + fprintf(out, " failed\n"); + return false; + } + fprintf(out, "."); + fflush(out); + // Verify a truncated signature. + if (ECDSA_verify(0, digest, 20, signature.data(), signature.size() - 1, + eckey.get())) { + fprintf(out, " failed\n"); + return false; + } + fprintf(out, "."); + fflush(out); + // Verify a tampered signature. + ScopedECDSA_SIG ecdsa_sig(ECDSA_SIG_from_bytes( + signature.data(), signature.size())); + if (!ecdsa_sig || + !TestTamperedSig(out, kEncodedApi, digest, 20, ecdsa_sig.get(), + eckey.get(), order)) { + fprintf(out, " failed\n"); + return false; + } + fprintf(out, "."); + fflush(out); + + // Test ECDSA_SIG signing and verification. + // Create a signature. + ecdsa_sig.reset(ECDSA_do_sign(digest, 20, eckey.get())); + if (!ecdsa_sig) { + fprintf(out, " failed\n"); + return false; + } + fprintf(out, "."); + fflush(out); + // Verify the signature using the correct key. + if (!ECDSA_do_verify(digest, 20, ecdsa_sig.get(), eckey.get())) { + fprintf(out, " failed\n"); + return false; + } + fprintf(out, "."); + fflush(out); + // Verify the signature with the wrong key. + if (ECDSA_do_verify(digest, 20, ecdsa_sig.get(), wrong_eckey.get())) { + fprintf(out, " failed\n"); + return false; + } + fprintf(out, "."); + fflush(out); + // Verify the signature using the wrong digest. + if (ECDSA_do_verify(wrong_digest, 20, ecdsa_sig.get(), eckey.get())) { + fprintf(out, " failed\n"); + return false; + } + fprintf(out, "."); + fflush(out); + // Verify a tampered signature. + if (!TestTamperedSig(out, kRawApi, digest, 20, ecdsa_sig.get(), eckey.get(), + order)) { + fprintf(out, " failed\n"); + return false; + } + fprintf(out, "."); + fflush(out); + + fprintf(out, " ok\n"); + // Clear bogus errors. + ERR_clear_error(); + } + + return true; +} + +static bool TestECDSA_SIG_max_len(size_t order_len) { + /* Create the largest possible |ECDSA_SIG| of the given constraints. */ + ScopedECDSA_SIG sig(ECDSA_SIG_new()); + if (!sig) { + return false; + } + std::vector bytes(order_len, 0xff); + if (!BN_bin2bn(bytes.data(), bytes.size(), sig->r) || + !BN_bin2bn(bytes.data(), bytes.size(), sig->s)) { + return false; + } + /* Serialize it. */ + uint8_t *der; + size_t der_len; + if (!ECDSA_SIG_to_bytes(&der, &der_len, sig.get())) { + return false; + } + ScopedOpenSSLBytes delete_der(der); + + size_t max_len = ECDSA_SIG_max_len(order_len); + if (max_len != der_len) { + fprintf(stderr, "ECDSA_SIG_max_len(%u) returned %u, wanted %u\n", + static_cast(order_len), static_cast(max_len), + static_cast(der_len)); + return false; + } + return true; +} + +static size_t BitsToBytes(size_t bits) { + return (bits / 8) + (7 + (bits % 8)) / 8; +} + +int main(void) { + CRYPTO_library_init(); + + if (!TestBuiltin(stdout) || + !TestECDSA_SIG_max_len(BitsToBytes(224)) || + !TestECDSA_SIG_max_len(BitsToBytes(256)) || + !TestECDSA_SIG_max_len(BitsToBytes(384)) || + !TestECDSA_SIG_max_len(BitsToBytes(521)) || + !TestECDSA_SIG_max_len(BitsToBytes(10000))) { + printf("\nECDSA test failed\n"); + ERR_print_errors_fp(stdout); + return 1; + } + + printf("\nPASS\n"); + return 0; +} diff --git a/external/boringssl/crypto/engine/CMakeLists.txt b/external/boringssl/crypto/engine/CMakeLists.txt new file mode 100644 index 0000000000..5667f02348 --- /dev/null +++ b/external/boringssl/crypto/engine/CMakeLists.txt @@ -0,0 +1,9 @@ +include_directories(../../include) + +add_library( + engine + + OBJECT + + engine.c +) diff --git a/external/boringssl/crypto/engine/engine.c b/external/boringssl/crypto/engine/engine.c new file mode 100644 index 0000000000..25ea98de2e --- /dev/null +++ b/external/boringssl/crypto/engine/engine.c @@ -0,0 +1,96 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include +#include + +#include +#include +#include +#include +#include + + +struct engine_st { + RSA_METHOD *rsa_method; + ECDSA_METHOD *ecdsa_method; +}; + +ENGINE *ENGINE_new(void) { + ENGINE *engine = OPENSSL_malloc(sizeof(ENGINE)); + if (engine == NULL) { + return NULL; + } + + memset(engine, 0, sizeof(ENGINE)); + return engine; +} + +void ENGINE_free(ENGINE *engine) { + /* Methods are currently required to be static so are not unref'ed. */ + OPENSSL_free(engine); +} + +/* set_method takes a pointer to a method and its given size and sets + * |*out_member| to point to it. This function might want to be extended in the + * future to support making a copy of the method so that a stable ABI for + * ENGINEs can be supported. But, for the moment, all *_METHODS must be + * static. */ +static int set_method(void **out_member, const void *method, size_t method_size, + size_t compiled_size) { + const struct openssl_method_common_st *common = method; + if (method_size != compiled_size || !common->is_static) { + return 0; + } + + *out_member = (void*) method; + return 1; +} + +int ENGINE_set_RSA_method(ENGINE *engine, const RSA_METHOD *method, + size_t method_size) { + return set_method((void **)&engine->rsa_method, method, method_size, + sizeof(RSA_METHOD)); +} + +RSA_METHOD *ENGINE_get_RSA_method(const ENGINE *engine) { + return engine->rsa_method; +} + +int ENGINE_set_ECDSA_method(ENGINE *engine, const ECDSA_METHOD *method, + size_t method_size) { + return set_method((void **)&engine->ecdsa_method, method, method_size, + sizeof(ECDSA_METHOD)); +} + +ECDSA_METHOD *ENGINE_get_ECDSA_method(const ENGINE *engine) { + return engine->ecdsa_method; +} + +void METHOD_ref(void *method_in) { + assert(((struct openssl_method_common_st*) method_in)->is_static); +} + +void METHOD_unref(void *method_in) { + struct openssl_method_common_st *method = method_in; + + if (method == NULL) { + return; + } + assert(method->is_static); +} + +OPENSSL_DECLARE_ERROR_REASON(ENGINE, OPERATION_NOT_SUPPORTED); diff --git a/external/boringssl/crypto/err/CMakeLists.txt b/external/boringssl/crypto/err/CMakeLists.txt new file mode 100644 index 0000000000..9151088194 --- /dev/null +++ b/external/boringssl/crypto/err/CMakeLists.txt @@ -0,0 +1,52 @@ +include_directories(../../include) + +#add_custom_command( +# OUTPUT err_data.c +# COMMAND ${GO_EXECUTABLE} run err_data_generate.go > ${CMAKE_CURRENT_BINARY_DIR}/err_data.c +# DEPENDS +# err_data_generate.go +# asn1.errordata +# bio.errordata +# bn.errordata +# cipher.errordata +# conf.errordata +# dh.errordata +# digest.errordata +# dsa.errordata +# ecdh.errordata +# ecdsa.errordata +# ec.errordata +# engine.errordata +# evp.errordata +# hkdf.errordata +# obj.errordata +# pem.errordata +# pkcs8.errordata +# rsa.errordata +# ssl.errordata +# x509.errordata +# x509v3.errordata +# WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +#) + +add_library( + err + + OBJECT + + err.c + err_data.c +) + +if(ENABLE_TESTS) +add_executable( + err_test + + err_test.cc + + $ +) + +target_link_libraries(err_test crypto) +add_dependencies(all_tests err_test) +endif() diff --git a/external/boringssl/crypto/err/asn1.errordata b/external/boringssl/crypto/err/asn1.errordata new file mode 100644 index 0000000000..c304b2caf5 --- /dev/null +++ b/external/boringssl/crypto/err/asn1.errordata @@ -0,0 +1,92 @@ +ASN1,100,ASN1_LENGTH_MISMATCH +ASN1,101,AUX_ERROR +ASN1,102,BAD_GET_ASN1_OBJECT_CALL +ASN1,103,BAD_OBJECT_HEADER +ASN1,104,BMPSTRING_IS_WRONG_LENGTH +ASN1,105,BN_LIB +ASN1,106,BOOLEAN_IS_WRONG_LENGTH +ASN1,107,BUFFER_TOO_SMALL +ASN1,108,CONTEXT_NOT_INITIALISED +ASN1,109,DECODE_ERROR +ASN1,110,DEPTH_EXCEEDED +ASN1,111,DIGEST_AND_KEY_TYPE_NOT_SUPPORTED +ASN1,112,ENCODE_ERROR +ASN1,113,ERROR_GETTING_TIME +ASN1,114,EXPECTING_AN_ASN1_SEQUENCE +ASN1,115,EXPECTING_AN_INTEGER +ASN1,116,EXPECTING_AN_OBJECT +ASN1,117,EXPECTING_A_BOOLEAN +ASN1,118,EXPECTING_A_TIME +ASN1,119,EXPLICIT_LENGTH_MISMATCH +ASN1,120,EXPLICIT_TAG_NOT_CONSTRUCTED +ASN1,121,FIELD_MISSING +ASN1,122,FIRST_NUM_TOO_LARGE +ASN1,123,HEADER_TOO_LONG +ASN1,124,ILLEGAL_BITSTRING_FORMAT +ASN1,125,ILLEGAL_BOOLEAN +ASN1,126,ILLEGAL_CHARACTERS +ASN1,127,ILLEGAL_FORMAT +ASN1,128,ILLEGAL_HEX +ASN1,129,ILLEGAL_IMPLICIT_TAG +ASN1,130,ILLEGAL_INTEGER +ASN1,131,ILLEGAL_NESTED_TAGGING +ASN1,132,ILLEGAL_NULL +ASN1,133,ILLEGAL_NULL_VALUE +ASN1,134,ILLEGAL_OBJECT +ASN1,135,ILLEGAL_OPTIONAL_ANY +ASN1,136,ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE +ASN1,137,ILLEGAL_TAGGED_ANY +ASN1,138,ILLEGAL_TIME_VALUE +ASN1,139,INTEGER_NOT_ASCII_FORMAT +ASN1,140,INTEGER_TOO_LARGE_FOR_LONG +ASN1,141,INVALID_BIT_STRING_BITS_LEFT +ASN1,142,INVALID_BMPSTRING_LENGTH +ASN1,143,INVALID_DIGIT +ASN1,144,INVALID_MODIFIER +ASN1,145,INVALID_NUMBER +ASN1,146,INVALID_OBJECT_ENCODING +ASN1,147,INVALID_SEPARATOR +ASN1,148,INVALID_TIME_FORMAT +ASN1,149,INVALID_UNIVERSALSTRING_LENGTH +ASN1,150,INVALID_UTF8STRING +ASN1,151,LIST_ERROR +ASN1,152,MISSING_ASN1_EOS +ASN1,153,MISSING_EOC +ASN1,154,MISSING_SECOND_NUMBER +ASN1,155,MISSING_VALUE +ASN1,156,MSTRING_NOT_UNIVERSAL +ASN1,157,MSTRING_WRONG_TAG +ASN1,158,NESTED_ASN1_ERROR +ASN1,159,NESTED_ASN1_STRING +ASN1,160,NON_HEX_CHARACTERS +ASN1,161,NOT_ASCII_FORMAT +ASN1,162,NOT_ENOUGH_DATA +ASN1,163,NO_MATCHING_CHOICE_TYPE +ASN1,164,NULL_IS_WRONG_LENGTH +ASN1,165,OBJECT_NOT_ASCII_FORMAT +ASN1,166,ODD_NUMBER_OF_CHARS +ASN1,167,SECOND_NUMBER_TOO_LARGE +ASN1,168,SEQUENCE_LENGTH_MISMATCH +ASN1,169,SEQUENCE_NOT_CONSTRUCTED +ASN1,170,SEQUENCE_OR_SET_NEEDS_CONFIG +ASN1,171,SHORT_LINE +ASN1,172,STREAMING_NOT_SUPPORTED +ASN1,173,STRING_TOO_LONG +ASN1,174,STRING_TOO_SHORT +ASN1,175,TAG_VALUE_TOO_HIGH +ASN1,176,TIME_NOT_ASCII_FORMAT +ASN1,177,TOO_LONG +ASN1,178,TYPE_NOT_CONSTRUCTED +ASN1,179,TYPE_NOT_PRIMITIVE +ASN1,180,UNEXPECTED_EOC +ASN1,181,UNIVERSALSTRING_IS_WRONG_LENGTH +ASN1,182,UNKNOWN_FORMAT +ASN1,183,UNKNOWN_MESSAGE_DIGEST_ALGORITHM +ASN1,184,UNKNOWN_SIGNATURE_ALGORITHM +ASN1,185,UNKNOWN_TAG +ASN1,186,UNSUPPORTED_ANY_DEFINED_BY_TYPE +ASN1,187,UNSUPPORTED_PUBLIC_KEY_TYPE +ASN1,188,UNSUPPORTED_TYPE +ASN1,189,WRONG_PUBLIC_KEY_TYPE +ASN1,190,WRONG_TAG +ASN1,191,WRONG_TYPE diff --git a/external/boringssl/crypto/err/bio.errordata b/external/boringssl/crypto/err/bio.errordata new file mode 100644 index 0000000000..94b3c9717e --- /dev/null +++ b/external/boringssl/crypto/err/bio.errordata @@ -0,0 +1,17 @@ +BIO,100,BAD_FOPEN_MODE +BIO,101,BROKEN_PIPE +BIO,102,CONNECT_ERROR +BIO,103,ERROR_SETTING_NBIO +BIO,104,INVALID_ARGUMENT +BIO,105,IN_USE +BIO,106,KEEPALIVE +BIO,107,NBIO_CONNECT_ERROR +BIO,108,NO_HOSTNAME_SPECIFIED +BIO,109,NO_PORT_SPECIFIED +BIO,110,NO_SUCH_FILE +BIO,111,NULL_PARAMETER +BIO,112,SYS_LIB +BIO,113,UNABLE_TO_CREATE_SOCKET +BIO,114,UNINITIALIZED +BIO,115,UNSUPPORTED_METHOD +BIO,116,WRITE_TO_READ_ONLY_BIO diff --git a/external/boringssl/crypto/err/bn.errordata b/external/boringssl/crypto/err/bn.errordata new file mode 100644 index 0000000000..76b63925d2 --- /dev/null +++ b/external/boringssl/crypto/err/bn.errordata @@ -0,0 +1,19 @@ +BN,100,ARG2_LT_ARG3 +BN,117,BAD_ENCODING +BN,101,BAD_RECIPROCAL +BN,102,BIGNUM_TOO_LONG +BN,103,BITS_TOO_SMALL +BN,104,CALLED_WITH_EVEN_MODULUS +BN,105,DIV_BY_ZERO +BN,118,ENCODE_ERROR +BN,106,EXPAND_ON_STATIC_BIGNUM_DATA +BN,107,INPUT_NOT_REDUCED +BN,108,INVALID_RANGE +BN,109,NEGATIVE_NUMBER +BN,110,NOT_A_SQUARE +BN,111,NOT_INITIALIZED +BN,112,NO_INVERSE +BN,113,PRIVATE_KEY_TOO_LARGE +BN,114,P_IS_NOT_PRIME +BN,115,TOO_MANY_ITERATIONS +BN,116,TOO_MANY_TEMPORARY_VARIABLES diff --git a/external/boringssl/crypto/err/cipher.errordata b/external/boringssl/crypto/err/cipher.errordata new file mode 100644 index 0000000000..103750558f --- /dev/null +++ b/external/boringssl/crypto/err/cipher.errordata @@ -0,0 +1,25 @@ +CIPHER,100,AES_KEY_SETUP_FAILED +CIPHER,101,BAD_DECRYPT +CIPHER,102,BAD_KEY_LENGTH +CIPHER,103,BUFFER_TOO_SMALL +CIPHER,104,CTRL_NOT_IMPLEMENTED +CIPHER,105,CTRL_OPERATION_NOT_IMPLEMENTED +CIPHER,106,DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH +CIPHER,107,INITIALIZATION_ERROR +CIPHER,108,INPUT_NOT_INITIALIZED +CIPHER,109,INVALID_AD_SIZE +CIPHER,110,INVALID_KEY_LENGTH +CIPHER,111,INVALID_NONCE_SIZE +CIPHER,112,INVALID_OPERATION +CIPHER,113,IV_TOO_LARGE +CIPHER,114,NO_CIPHER_SET +CIPHER,124,NO_DIRECTION_SET +CIPHER,115,OUTPUT_ALIASES_INPUT +CIPHER,116,TAG_TOO_LARGE +CIPHER,117,TOO_LARGE +CIPHER,118,UNSUPPORTED_AD_SIZE +CIPHER,119,UNSUPPORTED_INPUT_SIZE +CIPHER,120,UNSUPPORTED_KEY_SIZE +CIPHER,121,UNSUPPORTED_NONCE_SIZE +CIPHER,122,UNSUPPORTED_TAG_SIZE +CIPHER,123,WRONG_FINAL_BLOCK_LENGTH diff --git a/external/boringssl/crypto/err/conf.errordata b/external/boringssl/crypto/err/conf.errordata new file mode 100644 index 0000000000..651fabe10a --- /dev/null +++ b/external/boringssl/crypto/err/conf.errordata @@ -0,0 +1,6 @@ +CONF,100,LIST_CANNOT_BE_NULL +CONF,101,MISSING_CLOSE_SQUARE_BRACKET +CONF,102,MISSING_EQUAL_SIGN +CONF,103,NO_CLOSE_BRACE +CONF,104,UNABLE_TO_CREATE_NEW_SECTION +CONF,105,VARIABLE_HAS_NO_VALUE diff --git a/external/boringssl/crypto/err/dh.errordata b/external/boringssl/crypto/err/dh.errordata new file mode 100644 index 0000000000..9e1b87d850 --- /dev/null +++ b/external/boringssl/crypto/err/dh.errordata @@ -0,0 +1,6 @@ +DH,100,BAD_GENERATOR +DH,104,DECODE_ERROR +DH,105,ENCODE_ERROR +DH,101,INVALID_PUBKEY +DH,102,MODULUS_TOO_LARGE +DH,103,NO_PRIVATE_VALUE diff --git a/external/boringssl/crypto/err/digest.errordata b/external/boringssl/crypto/err/digest.errordata new file mode 100644 index 0000000000..411e778b84 --- /dev/null +++ b/external/boringssl/crypto/err/digest.errordata @@ -0,0 +1 @@ +DIGEST,100,INPUT_NOT_INITIALIZED diff --git a/external/boringssl/crypto/err/dsa.errordata b/external/boringssl/crypto/err/dsa.errordata new file mode 100644 index 0000000000..6f4bc138ab --- /dev/null +++ b/external/boringssl/crypto/err/dsa.errordata @@ -0,0 +1,7 @@ +DSA,100,BAD_Q_VALUE +DSA,104,BAD_VERSION +DSA,105,DECODE_ERROR +DSA,106,ENCODE_ERROR +DSA,101,MISSING_PARAMETERS +DSA,102,MODULUS_TOO_LARGE +DSA,103,NEED_NEW_SETUP_VALUES diff --git a/external/boringssl/crypto/err/ec.errordata b/external/boringssl/crypto/err/ec.errordata new file mode 100644 index 0000000000..d074afc967 --- /dev/null +++ b/external/boringssl/crypto/err/ec.errordata @@ -0,0 +1,31 @@ +EC,126,BIGNUM_OUT_OF_RANGE +EC,100,BUFFER_TOO_SMALL +EC,101,COORDINATES_OUT_OF_RANGE +EC,102,D2I_ECPKPARAMETERS_FAILURE +EC,128,DECODE_ERROR +EC,103,EC_GROUP_NEW_BY_NAME_FAILURE +EC,129,ENCODE_ERROR +EC,104,GROUP2PKPARAMETERS_FAILURE +EC,130,GROUP_MISMATCH +EC,105,I2D_ECPKPARAMETERS_FAILURE +EC,106,INCOMPATIBLE_OBJECTS +EC,107,INVALID_COMPRESSED_POINT +EC,108,INVALID_COMPRESSION_BIT +EC,109,INVALID_ENCODING +EC,110,INVALID_FIELD +EC,111,INVALID_FORM +EC,112,INVALID_GROUP_ORDER +EC,113,INVALID_PRIVATE_KEY +EC,114,MISSING_PARAMETERS +EC,115,MISSING_PRIVATE_KEY +EC,116,NON_NAMED_CURVE +EC,117,NOT_INITIALIZED +EC,118,PKPARAMETERS2GROUP_FAILURE +EC,119,POINT_AT_INFINITY +EC,120,POINT_IS_NOT_ON_CURVE +EC,121,SLOT_FULL +EC,122,UNDEFINED_GENERATOR +EC,123,UNKNOWN_GROUP +EC,124,UNKNOWN_ORDER +EC,127,WRONG_CURVE_PARAMETERS +EC,125,WRONG_ORDER diff --git a/external/boringssl/crypto/err/ecdh.errordata b/external/boringssl/crypto/err/ecdh.errordata new file mode 100644 index 0000000000..f714c3049d --- /dev/null +++ b/external/boringssl/crypto/err/ecdh.errordata @@ -0,0 +1,3 @@ +ECDH,100,KDF_FAILED +ECDH,101,NO_PRIVATE_VALUE +ECDH,102,POINT_ARITHMETIC_FAILURE diff --git a/external/boringssl/crypto/err/ecdsa.errordata b/external/boringssl/crypto/err/ecdsa.errordata new file mode 100644 index 0000000000..58ba591fab --- /dev/null +++ b/external/boringssl/crypto/err/ecdsa.errordata @@ -0,0 +1,6 @@ +ECDSA,100,BAD_SIGNATURE +ECDSA,105,ENCODE_ERROR +ECDSA,101,MISSING_PARAMETERS +ECDSA,102,NEED_NEW_SETUP_VALUES +ECDSA,103,NOT_IMPLEMENTED +ECDSA,104,RANDOM_NUMBER_GENERATION_FAILED diff --git a/external/boringssl/crypto/err/engine.errordata b/external/boringssl/crypto/err/engine.errordata new file mode 100644 index 0000000000..edbd7b97b9 --- /dev/null +++ b/external/boringssl/crypto/err/engine.errordata @@ -0,0 +1 @@ +ENGINE,100,OPERATION_NOT_SUPPORTED diff --git a/external/boringssl/crypto/err/err.c b/external/boringssl/crypto/err/err.c new file mode 100644 index 0000000000..48d631f4cf --- /dev/null +++ b/external/boringssl/crypto/err/err.c @@ -0,0 +1,756 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include +#include +#include + +#if defined(OPENSSL_WINDOWS) +OPENSSL_MSVC_PRAGMA(warning(push, 3)) +#include +OPENSSL_MSVC_PRAGMA(warning(pop)) +#endif + +#include +#include + +#include "../internal.h" + + +extern const uint32_t kOpenSSLReasonValues[]; +extern const size_t kOpenSSLReasonValuesLen; +extern const char kOpenSSLReasonStringData[]; + +/* err_clear_data frees the optional |data| member of the given error. */ +static void err_clear_data(struct err_error_st *error) { + if ((error->flags & ERR_FLAG_MALLOCED) != 0) { + OPENSSL_free(error->data); + } + error->data = NULL; + error->flags &= ~ERR_FLAG_MALLOCED; +} + +/* err_clear clears the given queued error. */ +static void err_clear(struct err_error_st *error) { + err_clear_data(error); + memset(error, 0, sizeof(struct err_error_st)); +} + +/* global_next_library contains the next custom library value to return. */ +static int global_next_library = ERR_NUM_LIBS; + +/* global_next_library_mutex protects |global_next_library| from concurrent + * updates. */ +static struct CRYPTO_STATIC_MUTEX global_next_library_mutex = + CRYPTO_STATIC_MUTEX_INIT; + +static void err_state_free(void *statep) { + ERR_STATE *state = statep; + + if (state == NULL) { + return; + } + + unsigned i; + for (i = 0; i < ERR_NUM_ERRORS; i++) { + err_clear(&state->errors[i]); + } + OPENSSL_free(state->to_free); + OPENSSL_free(state); +} + +/* err_get_state gets the ERR_STATE object for the current thread. */ +static ERR_STATE *err_get_state(void) { + ERR_STATE *state = CRYPTO_get_thread_local(OPENSSL_THREAD_LOCAL_ERR); + if (state == NULL) { + state = OPENSSL_malloc(sizeof(ERR_STATE)); + if (state == NULL) { + return NULL; + } + memset(state, 0, sizeof(ERR_STATE)); + if (!CRYPTO_set_thread_local(OPENSSL_THREAD_LOCAL_ERR, state, + err_state_free)) { + return NULL; + } + } + + return state; +} + +static uint32_t get_error_values(int inc, int top, const char **file, int *line, + const char **data, int *flags) { + unsigned i = 0; + ERR_STATE *state; + struct err_error_st *error; + uint32_t ret; + + state = err_get_state(); + if (state == NULL || state->bottom == state->top) { + return 0; + } + + if (top) { + assert(!inc); + /* last error */ + i = state->top; + } else { + i = (state->bottom + 1) % ERR_NUM_ERRORS; + } + + error = &state->errors[i]; + ret = error->packed; + + if (file != NULL && line != NULL) { + if (error->file == NULL) { + *file = "NA"; + *line = 0; + } else { + *file = error->file; + *line = error->line; + } + } + + if (data != NULL) { + if (error->data == NULL) { + *data = ""; + if (flags != NULL) { + *flags = 0; + } + } else { + *data = error->data; + if (flags != NULL) { + *flags = error->flags & ERR_FLAG_PUBLIC_MASK; + } + /* If this error is being removed, take ownership of data from + * the error. The semantics are such that the caller doesn't + * take ownership either. Instead the error system takes + * ownership and retains it until the next call that affects the + * error queue. */ + if (inc) { + if (error->flags & ERR_FLAG_MALLOCED) { + OPENSSL_free(state->to_free); + state->to_free = error->data; + } + error->data = NULL; + error->flags = 0; + } + } + } + + if (inc) { + assert(!top); + err_clear(error); + state->bottom = i; + } + + return ret; +} + +uint32_t ERR_get_error(void) { + return get_error_values(1 /* inc */, 0 /* bottom */, NULL, NULL, NULL, NULL); +} + +uint32_t ERR_get_error_line(const char **file, int *line) { + return get_error_values(1 /* inc */, 0 /* bottom */, file, line, NULL, NULL); +} + +uint32_t ERR_get_error_line_data(const char **file, int *line, + const char **data, int *flags) { + return get_error_values(1 /* inc */, 0 /* bottom */, file, line, data, flags); +} + +uint32_t ERR_peek_error(void) { + return get_error_values(0 /* peek */, 0 /* bottom */, NULL, NULL, NULL, NULL); +} + +uint32_t ERR_peek_error_line(const char **file, int *line) { + return get_error_values(0 /* peek */, 0 /* bottom */, file, line, NULL, NULL); +} + +uint32_t ERR_peek_error_line_data(const char **file, int *line, + const char **data, int *flags) { + return get_error_values(0 /* peek */, 0 /* bottom */, file, line, data, + flags); +} + +uint32_t ERR_peek_last_error(void) { + return get_error_values(0 /* peek */, 1 /* top */, NULL, NULL, NULL, NULL); +} + +uint32_t ERR_peek_last_error_line(const char **file, int *line) { + return get_error_values(0 /* peek */, 1 /* top */, file, line, NULL, NULL); +} + +uint32_t ERR_peek_last_error_line_data(const char **file, int *line, + const char **data, int *flags) { + return get_error_values(0 /* peek */, 1 /* top */, file, line, data, flags); +} + +void ERR_clear_error(void) { + ERR_STATE *const state = err_get_state(); + unsigned i; + + if (state == NULL) { + return; + } + + for (i = 0; i < ERR_NUM_ERRORS; i++) { + err_clear(&state->errors[i]); + } + OPENSSL_free(state->to_free); + state->to_free = NULL; + + state->top = state->bottom = 0; +} + +void ERR_remove_thread_state(const CRYPTO_THREADID *tid) { + if (tid != NULL) { + assert(0); + return; + } + + ERR_clear_error(); +} + +int ERR_get_next_error_library(void) { + int ret; + + CRYPTO_STATIC_MUTEX_lock_write(&global_next_library_mutex); + ret = global_next_library++; + CRYPTO_STATIC_MUTEX_unlock_write(&global_next_library_mutex); + + return ret; +} + +void ERR_remove_state(unsigned long pid) { + ERR_clear_error(); +} + +void ERR_clear_system_error(void) { + errno = 0; +} + +char *ERR_error_string(uint32_t packed_error, char *ret) { + static char buf[ERR_ERROR_STRING_BUF_LEN]; + + if (ret == NULL) { + /* TODO(fork): remove this. */ + ret = buf; + } + +#if !defined(NDEBUG) + /* This is aimed to help catch callers who don't provide + * |ERR_ERROR_STRING_BUF_LEN| bytes of space. */ + memset(ret, 0, ERR_ERROR_STRING_BUF_LEN); +#endif + + ERR_error_string_n(packed_error, ret, ERR_ERROR_STRING_BUF_LEN); + + return ret; +} + +void ERR_error_string_n(uint32_t packed_error, char *buf, size_t len) { + char lib_buf[64], reason_buf[64]; + const char *lib_str, *reason_str; + unsigned lib, reason; + + if (len == 0) { + return; + } + + lib = ERR_GET_LIB(packed_error); + reason = ERR_GET_REASON(packed_error); + + lib_str = ERR_lib_error_string(packed_error); + reason_str = ERR_reason_error_string(packed_error); + + if (lib_str == NULL) { + BIO_snprintf(lib_buf, sizeof(lib_buf), "lib(%u)", lib); + lib_str = lib_buf; + } + + if (reason_str == NULL) { + BIO_snprintf(reason_buf, sizeof(reason_buf), "reason(%u)", reason); + reason_str = reason_buf; + } + + BIO_snprintf(buf, len, "error:%08" PRIx32 ":%s:OPENSSL_internal:%s", + packed_error, lib_str, reason_str); + + if (strlen(buf) == len - 1) { + /* output may be truncated; make sure we always have 5 colon-separated + * fields, i.e. 4 colons. */ + static const unsigned num_colons = 4; + unsigned i; + char *s = buf; + + if (len <= num_colons) { + /* In this situation it's not possible to ensure that the correct number + * of colons are included in the output. */ + return; + } + + for (i = 0; i < num_colons; i++) { + char *colon = strchr(s, ':'); + char *last_pos = &buf[len - 1] - num_colons + i; + + if (colon == NULL || colon > last_pos) { + /* set colon |i| at last possible position (buf[len-1] is the + * terminating 0). If we're setting this colon, then all whole of the + * rest of the string must be colons in order to have the correct + * number. */ + memset(last_pos, ':', num_colons - i); + break; + } + + s = colon + 1; + } + } +} + +// err_string_cmp is a compare function for searching error values with +// |bsearch| in |err_string_lookup|. +static int err_string_cmp(const void *a, const void *b) { + const uint32_t a_key = *((const uint32_t*) a) >> 15; + const uint32_t b_key = *((const uint32_t*) b) >> 15; + + if (a_key < b_key) { + return -1; + } else if (a_key > b_key) { + return 1; + } else { + return 0; + } +} + +/* err_string_lookup looks up the string associated with |lib| and |key| in + * |values| and |string_data|. It returns the string or NULL if not found. */ +static const char *err_string_lookup(uint32_t lib, uint32_t key, + const uint32_t *values, + size_t num_values, + const char *string_data) { + /* |values| points to data in err_data.h, which is generated by + * err_data_generate.go. It's an array of uint32_t values. Each value has the + * following structure: + * | lib | key | offset | + * |6 bits| 11 bits | 15 bits | + * + * The |lib| value is a library identifier: one of the |ERR_LIB_*| values. + * The |key| is a reason code, depending on the context. + * The |offset| is the number of bytes from the start of |string_data| where + * the (NUL terminated) string for this value can be found. + * + * Values are sorted based on treating the |lib| and |key| part as an + * unsigned integer. */ + if (lib >= (1 << 6) || key >= (1 << 11)) { + return NULL; + } + uint32_t search_key = lib << 26 | key << 15; + const uint32_t *result = bsearch(&search_key, values, num_values, + sizeof(uint32_t), err_string_cmp); + if (result == NULL) { + return NULL; + } + + return &string_data[(*result) & 0x7fff]; +} + +static const char *const kLibraryNames[ERR_NUM_LIBS] = { + "invalid library (0)", + "unknown library", /* ERR_LIB_NONE */ + "system library", /* ERR_LIB_SYS */ + "bignum routines", /* ERR_LIB_BN */ + "RSA routines", /* ERR_LIB_RSA */ + "Diffie-Hellman routines", /* ERR_LIB_DH */ + "public key routines", /* ERR_LIB_EVP */ + "memory buffer routines", /* ERR_LIB_BUF */ + "object identifier routines", /* ERR_LIB_OBJ */ + "PEM routines", /* ERR_LIB_PEM */ + "DSA routines", /* ERR_LIB_DSA */ + "X.509 certificate routines", /* ERR_LIB_X509 */ + "ASN.1 encoding routines", /* ERR_LIB_ASN1 */ + "configuration file routines", /* ERR_LIB_CONF */ + "common libcrypto routines", /* ERR_LIB_CRYPTO */ + "elliptic curve routines", /* ERR_LIB_EC */ + "SSL routines", /* ERR_LIB_SSL */ + "BIO routines", /* ERR_LIB_BIO */ + "PKCS7 routines", /* ERR_LIB_PKCS7 */ + "PKCS8 routines", /* ERR_LIB_PKCS8 */ + "X509 V3 routines", /* ERR_LIB_X509V3 */ + "random number generator", /* ERR_LIB_RAND */ + "ENGINE routines", /* ERR_LIB_ENGINE */ + "OCSP routines", /* ERR_LIB_OCSP */ + "UI routines", /* ERR_LIB_UI */ + "COMP routines", /* ERR_LIB_COMP */ + "ECDSA routines", /* ERR_LIB_ECDSA */ + "ECDH routines", /* ERR_LIB_ECDH */ + "HMAC routines", /* ERR_LIB_HMAC */ + "Digest functions", /* ERR_LIB_DIGEST */ + "Cipher functions", /* ERR_LIB_CIPHER */ + "HKDF functions", /* ERR_LIB_HKDF */ + "User defined functions", /* ERR_LIB_USER */ +}; + +const char *ERR_lib_error_string(uint32_t packed_error) { + const uint32_t lib = ERR_GET_LIB(packed_error); + + if (lib >= ERR_NUM_LIBS) { + return NULL; + } + return kLibraryNames[lib]; +} + +const char *ERR_func_error_string(uint32_t packed_error) { + return "OPENSSL_internal"; +} + +const char *ERR_reason_error_string(uint32_t packed_error) { + const uint32_t lib = ERR_GET_LIB(packed_error); + const uint32_t reason = ERR_GET_REASON(packed_error); + + if (lib == ERR_LIB_SYS) { + if (reason < 127) { + return strerror(reason); + } + return NULL; + } + + if (reason < ERR_NUM_LIBS) { + return kLibraryNames[reason]; + } + + if (reason < 100) { + switch (reason) { + case ERR_R_MALLOC_FAILURE: + return "malloc failure"; + case ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED: + return "function should not have been called"; + case ERR_R_PASSED_NULL_PARAMETER: + return "passed a null parameter"; + case ERR_R_INTERNAL_ERROR: + return "internal error"; + case ERR_R_OVERFLOW: + return "overflow"; + default: + return NULL; + } + } + + return err_string_lookup(lib, reason, kOpenSSLReasonValues, + kOpenSSLReasonValuesLen, kOpenSSLReasonStringData); +} + +void ERR_print_errors_cb(ERR_print_errors_callback_t callback, void *ctx) { + char buf[ERR_ERROR_STRING_BUF_LEN]; + char buf2[1024]; + const char *file, *data; + int line, flags; + uint32_t packed_error; + + /* thread_hash is the least-significant bits of the |ERR_STATE| pointer value + * for this thread. */ + const unsigned long thread_hash = (uintptr_t) err_get_state(); + + for (;;) { + packed_error = ERR_get_error_line_data(&file, &line, &data, &flags); + if (packed_error == 0) { + break; + } + + ERR_error_string_n(packed_error, buf, sizeof(buf)); + BIO_snprintf(buf2, sizeof(buf2), "%lu:%s:%s:%d:%s\n", thread_hash, buf, + file, line, (flags & ERR_FLAG_STRING) ? data : ""); + if (callback(buf2, strlen(buf2), ctx) <= 0) { + break; + } + } +} + +static int print_errors_to_file(const char* msg, size_t msg_len, void* ctx) { + assert(msg[msg_len] == '\0'); + FILE* fp = ctx; + int res = fputs(msg, fp); + return res < 0 ? 0 : 1; +} + +void ERR_print_errors_fp(FILE *file) { + ERR_print_errors_cb(print_errors_to_file, file); +} + +/* err_set_error_data sets the data on the most recent error. The |flags| + * argument is a combination of the |ERR_FLAG_*| values. */ +static void err_set_error_data(char *data, int flags) { + ERR_STATE *const state = err_get_state(); + struct err_error_st *error; + + if (state == NULL || state->top == state->bottom) { + if (flags & ERR_FLAG_MALLOCED) { + OPENSSL_free(data); + } + return; + } + + error = &state->errors[state->top]; + + err_clear_data(error); + error->data = data; + error->flags = flags; +} + +void ERR_put_error(int library, int unused, int reason, const char *file, + unsigned line) { + ERR_STATE *const state = err_get_state(); + struct err_error_st *error; + + if (state == NULL) { + return; + } + + if (library == ERR_LIB_SYS && reason == 0) { +#if defined(OPENSSL_WINDOWS) + reason = GetLastError(); +#else + reason = errno; +#endif + } + + state->top = (state->top + 1) % ERR_NUM_ERRORS; + if (state->top == state->bottom) { + state->bottom = (state->bottom + 1) % ERR_NUM_ERRORS; + } + + error = &state->errors[state->top]; + err_clear(error); + error->file = file; + error->line = line; + error->packed = ERR_PACK(library, reason); +} + +/* ERR_add_error_data_vdata takes a variable number of const char* pointers, + * concatenates them and sets the result as the data on the most recent + * error. */ +static void err_add_error_vdata(unsigned num, va_list args) { + size_t alloced, new_len, len = 0, substr_len; + char *buf; + const char *substr; + unsigned i; + + alloced = 80; + buf = OPENSSL_malloc(alloced + 1); + if (buf == NULL) { + return; + } + + for (i = 0; i < num; i++) { + substr = va_arg(args, const char *); + if (substr == NULL) { + continue; + } + + substr_len = strlen(substr); + new_len = len + substr_len; + if (new_len > alloced) { + char *new_buf; + + if (alloced + 20 + 1 < alloced) { + /* overflow. */ + OPENSSL_free(buf); + return; + } + + alloced = new_len + 20; + new_buf = OPENSSL_realloc(buf, alloced + 1); + if (new_buf == NULL) { + OPENSSL_free(buf); + return; + } + buf = new_buf; + } + + memcpy(buf + len, substr, substr_len); + len = new_len; + } + + buf[len] = 0; + err_set_error_data(buf, ERR_FLAG_MALLOCED | ERR_FLAG_STRING); +} + +void ERR_add_error_data(unsigned count, ...) { + va_list args; + va_start(args, count); + err_add_error_vdata(count, args); + va_end(args); +} + +void ERR_add_error_dataf(const char *format, ...) { + va_list ap; + char *buf; + static const unsigned buf_len = 256; + + /* A fixed-size buffer is used because va_copy (which would be needed in + * order to call vsnprintf twice and measure the buffer) wasn't defined until + * C99. */ + buf = OPENSSL_malloc(buf_len + 1); + if (buf == NULL) { + return; + } + + va_start(ap, format); + BIO_vsnprintf(buf, buf_len, format, ap); + buf[buf_len] = 0; + va_end(ap); + + err_set_error_data(buf, ERR_FLAG_MALLOCED | ERR_FLAG_STRING); +} + +int ERR_set_mark(void) { + ERR_STATE *const state = err_get_state(); + + if (state == NULL || state->bottom == state->top) { + return 0; + } + state->errors[state->top].flags |= ERR_FLAG_MARK; + return 1; +} + +int ERR_pop_to_mark(void) { + ERR_STATE *const state = err_get_state(); + + if (state == NULL) { + return 0; + } + + while (state->bottom != state->top) { + struct err_error_st *error = &state->errors[state->top]; + + if ((error->flags & ERR_FLAG_MARK) != 0) { + error->flags &= ~ERR_FLAG_MARK; + return 1; + } + + err_clear(error); + if (state->top == 0) { + state->top = ERR_NUM_ERRORS - 1; + } else { + state->top--; + } + } + + return 0; +} + +void ERR_load_crypto_strings(void) {} + +void ERR_free_strings(void) {} + +void ERR_load_BIO_strings(void) {} + +void ERR_load_ERR_strings(void) {} diff --git a/external/boringssl/crypto/err/err_data.c b/external/boringssl/crypto/err/err_data.c new file mode 100644 index 0000000000..d4cc08bd99 --- /dev/null +++ b/external/boringssl/crypto/err/err_data.c @@ -0,0 +1,1258 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + + /* This file was generated by err_data_generate.go. */ + +#include +#include +#include + + +OPENSSL_COMPILE_ASSERT(ERR_LIB_NONE == 1, library_values_changed_1); +OPENSSL_COMPILE_ASSERT(ERR_LIB_SYS == 2, library_values_changed_2); +OPENSSL_COMPILE_ASSERT(ERR_LIB_BN == 3, library_values_changed_3); +OPENSSL_COMPILE_ASSERT(ERR_LIB_RSA == 4, library_values_changed_4); +OPENSSL_COMPILE_ASSERT(ERR_LIB_DH == 5, library_values_changed_5); +OPENSSL_COMPILE_ASSERT(ERR_LIB_EVP == 6, library_values_changed_6); +OPENSSL_COMPILE_ASSERT(ERR_LIB_BUF == 7, library_values_changed_7); +OPENSSL_COMPILE_ASSERT(ERR_LIB_OBJ == 8, library_values_changed_8); +OPENSSL_COMPILE_ASSERT(ERR_LIB_PEM == 9, library_values_changed_9); +OPENSSL_COMPILE_ASSERT(ERR_LIB_DSA == 10, library_values_changed_10); +OPENSSL_COMPILE_ASSERT(ERR_LIB_X509 == 11, library_values_changed_11); +OPENSSL_COMPILE_ASSERT(ERR_LIB_ASN1 == 12, library_values_changed_12); +OPENSSL_COMPILE_ASSERT(ERR_LIB_CONF == 13, library_values_changed_13); +OPENSSL_COMPILE_ASSERT(ERR_LIB_CRYPTO == 14, library_values_changed_14); +OPENSSL_COMPILE_ASSERT(ERR_LIB_EC == 15, library_values_changed_15); +OPENSSL_COMPILE_ASSERT(ERR_LIB_SSL == 16, library_values_changed_16); +OPENSSL_COMPILE_ASSERT(ERR_LIB_BIO == 17, library_values_changed_17); +OPENSSL_COMPILE_ASSERT(ERR_LIB_PKCS7 == 18, library_values_changed_18); +OPENSSL_COMPILE_ASSERT(ERR_LIB_PKCS8 == 19, library_values_changed_19); +OPENSSL_COMPILE_ASSERT(ERR_LIB_X509V3 == 20, library_values_changed_20); +OPENSSL_COMPILE_ASSERT(ERR_LIB_RAND == 21, library_values_changed_21); +OPENSSL_COMPILE_ASSERT(ERR_LIB_ENGINE == 22, library_values_changed_22); +OPENSSL_COMPILE_ASSERT(ERR_LIB_OCSP == 23, library_values_changed_23); +OPENSSL_COMPILE_ASSERT(ERR_LIB_UI == 24, library_values_changed_24); +OPENSSL_COMPILE_ASSERT(ERR_LIB_COMP == 25, library_values_changed_25); +OPENSSL_COMPILE_ASSERT(ERR_LIB_ECDSA == 26, library_values_changed_26); +OPENSSL_COMPILE_ASSERT(ERR_LIB_ECDH == 27, library_values_changed_27); +OPENSSL_COMPILE_ASSERT(ERR_LIB_HMAC == 28, library_values_changed_28); +OPENSSL_COMPILE_ASSERT(ERR_LIB_DIGEST == 29, library_values_changed_29); +OPENSSL_COMPILE_ASSERT(ERR_LIB_CIPHER == 30, library_values_changed_30); +OPENSSL_COMPILE_ASSERT(ERR_LIB_HKDF == 31, library_values_changed_31); +OPENSSL_COMPILE_ASSERT(ERR_LIB_USER == 32, library_values_changed_32); +OPENSSL_COMPILE_ASSERT(ERR_NUM_LIBS == 33, library_values_changed_num); + +const uint32_t kOpenSSLReasonValues[] = { + 0xc3207ab, + 0xc3287c5, + 0xc3307d4, + 0xc3387e4, + 0xc3407f3, + 0xc34880c, + 0xc350818, + 0xc358835, + 0xc360847, + 0xc368855, + 0xc370865, + 0xc378872, + 0xc380882, + 0xc38888d, + 0xc3908a3, + 0xc3988b2, + 0xc3a08c6, + 0xc3a87b8, + 0xc3b00b0, + 0x10321484, + 0x10329490, + 0x103314a9, + 0x103394bc, + 0x10340ded, + 0x103494cf, + 0x103514e4, + 0x10359516, + 0x1036152f, + 0x10369544, + 0x10371562, + 0x10379571, + 0x1038158d, + 0x103895a8, + 0x103915b7, + 0x103995d3, + 0x103a15ee, + 0x103a9605, + 0x103b1616, + 0x103b962a, + 0x103c1649, + 0x103c9658, + 0x103d166f, + 0x103d9682, + 0x103e0b5d, + 0x103e96b3, + 0x103f16c6, + 0x103f96e0, + 0x104016f0, + 0x10409704, + 0x1041171a, + 0x10419732, + 0x10421747, + 0x1042975b, + 0x1043176d, + 0x104385c1, + 0x104408b2, + 0x10449782, + 0x10451799, + 0x104597ae, + 0x104617bc, + 0x10469695, + 0x104714f7, + 0x104787b8, + 0x104800b0, + 0x10488b8c, + 0x14320b40, + 0x14328b4e, + 0x14330b5d, + 0x14338b6f, + 0x18320083, + 0x18328e53, + 0x18340e81, + 0x18348e95, + 0x18358ecc, + 0x18368ef9, + 0x18370f0c, + 0x18378f20, + 0x18380f44, + 0x18388f52, + 0x18390f68, + 0x18398f7c, + 0x183a0f8c, + 0x183b0f9c, + 0x183b8fb1, + 0x183c8fdc, + 0x183d0ff0, + 0x183d9000, + 0x183e0b98, + 0x183e900d, + 0x183f101f, + 0x183f902a, + 0x1840103a, + 0x1840904b, + 0x1841105c, + 0x1841906e, + 0x18421097, + 0x184290c9, + 0x184310d8, + 0x18451141, + 0x18459157, + 0x18461172, + 0x18468ee4, + 0x184709ca, + 0x18478094, + 0x18480fc8, + 0x1848910d, + 0x18490e69, + 0x18498eaa, + 0x184a11a8, + 0x184a9125, + 0x184b10ec, + 0x184b8e43, + 0x184c10b0, + 0x184c865c, + 0x184d118d, + 0x184d80b0, + 0x203211cf, + 0x243211db, + 0x243288f8, + 0x243311ed, + 0x243391fa, + 0x24341207, + 0x24349219, + 0x24351228, + 0x24359245, + 0x24361252, + 0x24369260, + 0x2437126e, + 0x2437927c, + 0x24381285, + 0x24389292, + 0x243912a5, + 0x28320b80, + 0x28328b98, + 0x28330b5d, + 0x28338bab, + 0x28340b8c, + 0x28348094, + 0x283500b0, + 0x2c32281d, + 0x2c32a82b, + 0x2c33283d, + 0x2c33a84f, + 0x2c342863, + 0x2c34a875, + 0x2c352890, + 0x2c35a8a2, + 0x2c3628b5, + 0x2c3682f3, + 0x2c3728c2, + 0x2c37a8d4, + 0x2c3828e7, + 0x2c38a8f5, + 0x2c392905, + 0x2c39a917, + 0x2c3a292b, + 0x2c3aa93c, + 0x2c3b1365, + 0x2c3ba94d, + 0x2c3c2961, + 0x2c3ca977, + 0x2c3d2990, + 0x2c3da9be, + 0x2c3e29cc, + 0x2c3ea9e4, + 0x2c3f29fc, + 0x2c3faa09, + 0x2c402a2c, + 0x2c40aa4b, + 0x2c4111cf, + 0x2c41aa5c, + 0x2c422a6f, + 0x2c429141, + 0x2c432a80, + 0x2c438693, + 0x2c4429ad, + 0x30320000, + 0x30328015, + 0x3033001f, + 0x30338038, + 0x3034004a, + 0x30348064, + 0x3035006b, + 0x30358083, + 0x30360094, + 0x303680a1, + 0x303700b0, + 0x303780bd, + 0x303800d0, + 0x303880eb, + 0x30390100, + 0x30398114, + 0x303a0128, + 0x303a8139, + 0x303b0152, + 0x303b816f, + 0x303c017d, + 0x303c8191, + 0x303d01a1, + 0x303d81ba, + 0x303e01ca, + 0x303e81dd, + 0x303f01ec, + 0x303f81f8, + 0x3040020d, + 0x3040821d, + 0x30410234, + 0x30418241, + 0x30420254, + 0x30428263, + 0x30430278, + 0x30438299, + 0x304402ac, + 0x304482bf, + 0x304502d8, + 0x304582f3, + 0x30460310, + 0x30468329, + 0x30470337, + 0x30478348, + 0x30480357, + 0x3048836f, + 0x30490381, + 0x30498395, + 0x304a03b4, + 0x304a83c7, + 0x304b03d2, + 0x304b83e3, + 0x304c03ef, + 0x304c8405, + 0x304d0413, + 0x304d8429, + 0x304e043b, + 0x304e844d, + 0x304f0460, + 0x304f8473, + 0x30500484, + 0x30508494, + 0x305104ac, + 0x305184c1, + 0x305204d9, + 0x305284ed, + 0x30530505, + 0x3053851e, + 0x30540537, + 0x30548554, + 0x3055055f, + 0x30558577, + 0x30560587, + 0x30568598, + 0x305705ab, + 0x305785c1, + 0x305805ca, + 0x305885df, + 0x305905f2, + 0x30598601, + 0x305a0621, + 0x305a8630, + 0x305b063c, + 0x305b865c, + 0x305c0678, + 0x305c8689, + 0x305d0693, + 0x34320aba, + 0x34328ace, + 0x34330aeb, + 0x34338afe, + 0x34340b0d, + 0x34348b2a, + 0x3c320083, + 0x3c328bd5, + 0x3c330bee, + 0x3c338c09, + 0x3c340c26, + 0x3c348c50, + 0x3c350c6b, + 0x3c358c80, + 0x3c360c99, + 0x3c368cb1, + 0x3c370cc2, + 0x3c378cd0, + 0x3c380cdd, + 0x3c388cf1, + 0x3c390b98, + 0x3c398d05, + 0x3c3a0d19, + 0x3c3a8872, + 0x3c3b0d29, + 0x3c3b8d44, + 0x3c3c0d56, + 0x3c3c8d6c, + 0x3c3d0d76, + 0x3c3d8d8a, + 0x3c3e0d98, + 0x3c3e8dbd, + 0x3c3f0bc1, + 0x3c3f8da6, + 0x3c400094, + 0x3c4080b0, + 0x3c410c41, + 0x403217d3, + 0x403297e9, + 0x40331817, + 0x40339821, + 0x40341838, + 0x40349856, + 0x40351866, + 0x40359878, + 0x40361885, + 0x40369891, + 0x403718a6, + 0x403798b8, + 0x403818c3, + 0x403898d5, + 0x40390ded, + 0x403998e5, + 0x403a18f8, + 0x403a9919, + 0x403b192a, + 0x403b993a, + 0x403c0064, + 0x403c8083, + 0x403d1946, + 0x403d995c, + 0x403e196b, + 0x403e997e, + 0x403f1998, + 0x403f99a6, + 0x404019bb, + 0x404099cf, + 0x404119ec, + 0x40419a07, + 0x40421a20, + 0x40429a33, + 0x40431a47, + 0x40439a5f, + 0x40441a76, + 0x40448094, + 0x40451a8b, + 0x40459a9d, + 0x40461ac1, + 0x40469ae1, + 0x40471aef, + 0x40479b03, + 0x40481b18, + 0x40489b31, + 0x40491b48, + 0x40499b62, + 0x404a1b79, + 0x404a9b97, + 0x404b1baf, + 0x404b9bc6, + 0x404c1bdc, + 0x404c9bee, + 0x404d1c0f, + 0x404d9c31, + 0x404e1c45, + 0x404e9c52, + 0x404f1c69, + 0x404f9c79, + 0x40501c89, + 0x40509c9d, + 0x40511cb8, + 0x40519cc8, + 0x40521cdf, + 0x40529cf1, + 0x40531d09, + 0x40539d1c, + 0x40541d31, + 0x40549d54, + 0x40551d62, + 0x40559d7f, + 0x40561d8c, + 0x40569da5, + 0x40571dbd, + 0x40579dd0, + 0x40581de5, + 0x40589df7, + 0x40591e07, + 0x40599e20, + 0x405a1e34, + 0x405a9e44, + 0x405b1e5c, + 0x405b9e6d, + 0x405c1e80, + 0x405c9e91, + 0x405d1e9e, + 0x405d9eb5, + 0x405e1ed5, + 0x405e8a08, + 0x405f1ef6, + 0x405f9f03, + 0x40601f11, + 0x40609f33, + 0x40611f5b, + 0x40619f70, + 0x40621f87, + 0x40629f98, + 0x40631fa9, + 0x40639fbe, + 0x40641fd5, + 0x40649fe6, + 0x40652001, + 0x4065a018, + 0x40662030, + 0x4066a05a, + 0x40672085, + 0x4067a0a6, + 0x406820b9, + 0x4068a0da, + 0x406920f5, + 0x4069a123, + 0x406a2144, + 0x406aa164, + 0x406b22ec, + 0x406ba30f, + 0x406c2325, + 0x406ca551, + 0x406d2580, + 0x406da5a8, + 0x406e25c1, + 0x406ea5d9, + 0x406f25f8, + 0x406fa60d, + 0x40702620, + 0x4070a63d, + 0x40710773, + 0x4071a64f, + 0x40722662, + 0x4072a67b, + 0x40732693, + 0x407390c9, + 0x407426a7, + 0x4074a6c1, + 0x407526d2, + 0x4075a6e6, + 0x407626f4, + 0x40769292, + 0x40772719, + 0x4077a73b, + 0x40782756, + 0x4078a76b, + 0x40792782, + 0x4079a798, + 0x407a27a4, + 0x407aa7b7, + 0x407b27cc, + 0x407ba7de, + 0x407c27f3, + 0x407ca7fc, + 0x41f42217, + 0x41f922a9, + 0x41fe219c, + 0x41fea378, + 0x41ff2469, + 0x42032230, + 0x42082252, + 0x4208a28e, + 0x42092180, + 0x4209a2c8, + 0x420a21d7, + 0x420aa1b7, + 0x420b21f7, + 0x420ba270, + 0x420c2485, + 0x420ca345, + 0x420d235f, + 0x420da396, + 0x421223b0, + 0x4217244c, + 0x4217a3f2, + 0x421c2414, + 0x421f23cf, + 0x4221249c, + 0x4226242f, + 0x422b2535, + 0x422ba4fe, + 0x422c251d, + 0x422ca4d8, + 0x422d24b7, + 0x4432069e, + 0x443286ad, + 0x443306b9, + 0x443386c7, + 0x443406da, + 0x443486eb, + 0x443506f2, + 0x443586fc, + 0x4436070f, + 0x44368725, + 0x44370737, + 0x44378744, + 0x44380753, + 0x4438875b, + 0x44390773, + 0x44398781, + 0x443a0794, + 0x4c3212bc, + 0x4c3292cc, + 0x4c3312df, + 0x4c3392ff, + 0x4c340094, + 0x4c3480b0, + 0x4c35130b, + 0x4c359319, + 0x4c361335, + 0x4c369348, + 0x4c371357, + 0x4c379365, + 0x4c38137a, + 0x4c389386, + 0x4c3913a6, + 0x4c3993d0, + 0x4c3a13e9, + 0x4c3a9402, + 0x4c3b05c1, + 0x4c3b941b, + 0x4c3c142d, + 0x4c3c943c, + 0x4c3d10c9, + 0x4c3d9455, + 0x4c3e1462, + 0x50322a92, + 0x5032aaa1, + 0x50332aac, + 0x5033aabc, + 0x50342ad5, + 0x5034aaef, + 0x50352afd, + 0x5035ab13, + 0x50362b25, + 0x5036ab3b, + 0x50372b54, + 0x5037ab67, + 0x50382b7f, + 0x5038ab90, + 0x50392ba5, + 0x5039abb9, + 0x503a2bd9, + 0x503aabef, + 0x503b2c07, + 0x503bac19, + 0x503c2c35, + 0x503cac4c, + 0x503d2c65, + 0x503dac7b, + 0x503e2c88, + 0x503eac9e, + 0x503f2cb0, + 0x503f8348, + 0x50402cc3, + 0x5040acd3, + 0x50412ced, + 0x5041acfc, + 0x50422d16, + 0x5042ad33, + 0x50432d43, + 0x5043ad53, + 0x50442d62, + 0x50448405, + 0x50452d76, + 0x5045ad94, + 0x50462da7, + 0x5046adbd, + 0x50472dcf, + 0x5047ade4, + 0x50482e0a, + 0x5048ae18, + 0x50492e2b, + 0x5049ae40, + 0x504a2e56, + 0x504aae66, + 0x504b2e86, + 0x504bae99, + 0x504c2ebc, + 0x504caeea, + 0x504d2efc, + 0x504daf19, + 0x504e2f34, + 0x504eaf50, + 0x504f2f62, + 0x504faf79, + 0x50502f88, + 0x50508678, + 0x50512f9b, + 0x58320e2b, + 0x68320ded, + 0x68328b98, + 0x68330bab, + 0x68338dfb, + 0x68340e0b, + 0x683480b0, + 0x6c320dc9, + 0x6c328b6f, + 0x6c330dd4, + 0x7432097e, + 0x783208e3, + 0x783288f8, + 0x78330904, + 0x78338083, + 0x78340913, + 0x78348928, + 0x78350947, + 0x78358969, + 0x7836097e, + 0x78368994, + 0x783709a4, + 0x783789b7, + 0x783809ca, + 0x783889dc, + 0x783909e9, + 0x78398a08, + 0x783a0a1d, + 0x783a8a2b, + 0x783b0a35, + 0x783b8a49, + 0x783c0a60, + 0x783c8a75, + 0x783d0a8c, + 0x783d8aa1, + 0x783e09f7, + 0x7c3211be, +}; + +const size_t kOpenSSLReasonValuesLen = sizeof(kOpenSSLReasonValues) / sizeof(kOpenSSLReasonValues[0]); + +const char kOpenSSLReasonStringData[] = + "ASN1_LENGTH_MISMATCH\0" + "AUX_ERROR\0" + "BAD_GET_ASN1_OBJECT_CALL\0" + "BAD_OBJECT_HEADER\0" + "BMPSTRING_IS_WRONG_LENGTH\0" + "BN_LIB\0" + "BOOLEAN_IS_WRONG_LENGTH\0" + "BUFFER_TOO_SMALL\0" + "DECODE_ERROR\0" + "DEPTH_EXCEEDED\0" + "ENCODE_ERROR\0" + "ERROR_GETTING_TIME\0" + "EXPECTING_AN_ASN1_SEQUENCE\0" + "EXPECTING_AN_INTEGER\0" + "EXPECTING_AN_OBJECT\0" + "EXPECTING_A_BOOLEAN\0" + "EXPECTING_A_TIME\0" + "EXPLICIT_LENGTH_MISMATCH\0" + "EXPLICIT_TAG_NOT_CONSTRUCTED\0" + "FIELD_MISSING\0" + "FIRST_NUM_TOO_LARGE\0" + "HEADER_TOO_LONG\0" + "ILLEGAL_BITSTRING_FORMAT\0" + "ILLEGAL_BOOLEAN\0" + "ILLEGAL_CHARACTERS\0" + "ILLEGAL_FORMAT\0" + "ILLEGAL_HEX\0" + "ILLEGAL_IMPLICIT_TAG\0" + "ILLEGAL_INTEGER\0" + "ILLEGAL_NESTED_TAGGING\0" + "ILLEGAL_NULL\0" + "ILLEGAL_NULL_VALUE\0" + "ILLEGAL_OBJECT\0" + "ILLEGAL_OPTIONAL_ANY\0" + "ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE\0" + "ILLEGAL_TAGGED_ANY\0" + "ILLEGAL_TIME_VALUE\0" + "INTEGER_NOT_ASCII_FORMAT\0" + "INTEGER_TOO_LARGE_FOR_LONG\0" + "INVALID_BIT_STRING_BITS_LEFT\0" + "INVALID_BMPSTRING_LENGTH\0" + "INVALID_DIGIT\0" + "INVALID_MODIFIER\0" + "INVALID_NUMBER\0" + "INVALID_OBJECT_ENCODING\0" + "INVALID_SEPARATOR\0" + "INVALID_TIME_FORMAT\0" + "INVALID_UNIVERSALSTRING_LENGTH\0" + "INVALID_UTF8STRING\0" + "LIST_ERROR\0" + "MISSING_ASN1_EOS\0" + "MISSING_EOC\0" + "MISSING_SECOND_NUMBER\0" + "MISSING_VALUE\0" + "MSTRING_NOT_UNIVERSAL\0" + "MSTRING_WRONG_TAG\0" + "NESTED_ASN1_ERROR\0" + "NESTED_ASN1_STRING\0" + "NON_HEX_CHARACTERS\0" + "NOT_ASCII_FORMAT\0" + "NOT_ENOUGH_DATA\0" + "NO_MATCHING_CHOICE_TYPE\0" + "NULL_IS_WRONG_LENGTH\0" + "OBJECT_NOT_ASCII_FORMAT\0" + "ODD_NUMBER_OF_CHARS\0" + "SECOND_NUMBER_TOO_LARGE\0" + "SEQUENCE_LENGTH_MISMATCH\0" + "SEQUENCE_NOT_CONSTRUCTED\0" + "SEQUENCE_OR_SET_NEEDS_CONFIG\0" + "SHORT_LINE\0" + "STREAMING_NOT_SUPPORTED\0" + "STRING_TOO_LONG\0" + "STRING_TOO_SHORT\0" + "TAG_VALUE_TOO_HIGH\0" + "TIME_NOT_ASCII_FORMAT\0" + "TOO_LONG\0" + "TYPE_NOT_CONSTRUCTED\0" + "TYPE_NOT_PRIMITIVE\0" + "UNEXPECTED_EOC\0" + "UNIVERSALSTRING_IS_WRONG_LENGTH\0" + "UNKNOWN_FORMAT\0" + "UNKNOWN_TAG\0" + "UNSUPPORTED_ANY_DEFINED_BY_TYPE\0" + "UNSUPPORTED_PUBLIC_KEY_TYPE\0" + "UNSUPPORTED_TYPE\0" + "WRONG_TAG\0" + "WRONG_TYPE\0" + "BAD_FOPEN_MODE\0" + "BROKEN_PIPE\0" + "CONNECT_ERROR\0" + "ERROR_SETTING_NBIO\0" + "INVALID_ARGUMENT\0" + "IN_USE\0" + "KEEPALIVE\0" + "NBIO_CONNECT_ERROR\0" + "NO_HOSTNAME_SPECIFIED\0" + "NO_PORT_SPECIFIED\0" + "NO_SUCH_FILE\0" + "NULL_PARAMETER\0" + "SYS_LIB\0" + "UNABLE_TO_CREATE_SOCKET\0" + "UNINITIALIZED\0" + "UNSUPPORTED_METHOD\0" + "WRITE_TO_READ_ONLY_BIO\0" + "ARG2_LT_ARG3\0" + "BAD_ENCODING\0" + "BAD_RECIPROCAL\0" + "BIGNUM_TOO_LONG\0" + "BITS_TOO_SMALL\0" + "CALLED_WITH_EVEN_MODULUS\0" + "DIV_BY_ZERO\0" + "EXPAND_ON_STATIC_BIGNUM_DATA\0" + "INPUT_NOT_REDUCED\0" + "INVALID_RANGE\0" + "NEGATIVE_NUMBER\0" + "NOT_A_SQUARE\0" + "NOT_INITIALIZED\0" + "NO_INVERSE\0" + "PRIVATE_KEY_TOO_LARGE\0" + "P_IS_NOT_PRIME\0" + "TOO_MANY_ITERATIONS\0" + "TOO_MANY_TEMPORARY_VARIABLES\0" + "AES_KEY_SETUP_FAILED\0" + "BAD_DECRYPT\0" + "BAD_KEY_LENGTH\0" + "CTRL_NOT_IMPLEMENTED\0" + "CTRL_OPERATION_NOT_IMPLEMENTED\0" + "DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH\0" + "INITIALIZATION_ERROR\0" + "INPUT_NOT_INITIALIZED\0" + "INVALID_AD_SIZE\0" + "INVALID_KEY_LENGTH\0" + "INVALID_NONCE_SIZE\0" + "INVALID_OPERATION\0" + "IV_TOO_LARGE\0" + "NO_CIPHER_SET\0" + "NO_DIRECTION_SET\0" + "OUTPUT_ALIASES_INPUT\0" + "TAG_TOO_LARGE\0" + "TOO_LARGE\0" + "UNSUPPORTED_AD_SIZE\0" + "UNSUPPORTED_INPUT_SIZE\0" + "UNSUPPORTED_KEY_SIZE\0" + "UNSUPPORTED_NONCE_SIZE\0" + "UNSUPPORTED_TAG_SIZE\0" + "WRONG_FINAL_BLOCK_LENGTH\0" + "LIST_CANNOT_BE_NULL\0" + "MISSING_CLOSE_SQUARE_BRACKET\0" + "MISSING_EQUAL_SIGN\0" + "NO_CLOSE_BRACE\0" + "UNABLE_TO_CREATE_NEW_SECTION\0" + "VARIABLE_HAS_NO_VALUE\0" + "BAD_GENERATOR\0" + "INVALID_PUBKEY\0" + "MODULUS_TOO_LARGE\0" + "NO_PRIVATE_VALUE\0" + "BAD_Q_VALUE\0" + "BAD_VERSION\0" + "MISSING_PARAMETERS\0" + "NEED_NEW_SETUP_VALUES\0" + "BIGNUM_OUT_OF_RANGE\0" + "COORDINATES_OUT_OF_RANGE\0" + "D2I_ECPKPARAMETERS_FAILURE\0" + "EC_GROUP_NEW_BY_NAME_FAILURE\0" + "GROUP2PKPARAMETERS_FAILURE\0" + "GROUP_MISMATCH\0" + "I2D_ECPKPARAMETERS_FAILURE\0" + "INCOMPATIBLE_OBJECTS\0" + "INVALID_COMPRESSED_POINT\0" + "INVALID_COMPRESSION_BIT\0" + "INVALID_ENCODING\0" + "INVALID_FIELD\0" + "INVALID_FORM\0" + "INVALID_GROUP_ORDER\0" + "INVALID_PRIVATE_KEY\0" + "MISSING_PRIVATE_KEY\0" + "NON_NAMED_CURVE\0" + "PKPARAMETERS2GROUP_FAILURE\0" + "POINT_AT_INFINITY\0" + "POINT_IS_NOT_ON_CURVE\0" + "SLOT_FULL\0" + "UNDEFINED_GENERATOR\0" + "UNKNOWN_GROUP\0" + "UNKNOWN_ORDER\0" + "WRONG_CURVE_PARAMETERS\0" + "WRONG_ORDER\0" + "KDF_FAILED\0" + "POINT_ARITHMETIC_FAILURE\0" + "BAD_SIGNATURE\0" + "NOT_IMPLEMENTED\0" + "RANDOM_NUMBER_GENERATION_FAILED\0" + "OPERATION_NOT_SUPPORTED\0" + "BN_DECODE_ERROR\0" + "COMMAND_NOT_SUPPORTED\0" + "CONTEXT_NOT_INITIALISED\0" + "DIFFERENT_KEY_TYPES\0" + "DIFFERENT_PARAMETERS\0" + "DIGEST_AND_KEY_TYPE_NOT_SUPPORTED\0" + "EXPECTING_AN_EC_KEY_KEY\0" + "EXPECTING_AN_RSA_KEY\0" + "EXPECTING_A_DH_KEY\0" + "EXPECTING_A_DSA_KEY\0" + "ILLEGAL_OR_UNSUPPORTED_PADDING_MODE\0" + "INVALID_CURVE\0" + "INVALID_DIGEST_LENGTH\0" + "INVALID_DIGEST_TYPE\0" + "INVALID_KEYBITS\0" + "INVALID_MGF1_MD\0" + "INVALID_PADDING_MODE\0" + "INVALID_PSS_PARAMETERS\0" + "INVALID_PSS_SALTLEN\0" + "INVALID_SALT_LENGTH\0" + "INVALID_TRAILER\0" + "KEYS_NOT_SET\0" + "NO_DEFAULT_DIGEST\0" + "NO_KEY_SET\0" + "NO_MDC2_SUPPORT\0" + "NO_NID_FOR_CURVE\0" + "NO_OPERATION_SET\0" + "NO_PARAMETERS_SET\0" + "OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE\0" + "OPERATON_NOT_INITIALIZED\0" + "PARAMETER_ENCODING_ERROR\0" + "UNKNOWN_DIGEST\0" + "UNKNOWN_MASK_DIGEST\0" + "UNKNOWN_MESSAGE_DIGEST_ALGORITHM\0" + "UNKNOWN_PUBLIC_KEY_TYPE\0" + "UNKNOWN_SIGNATURE_ALGORITHM\0" + "UNSUPPORTED_ALGORITHM\0" + "UNSUPPORTED_MASK_ALGORITHM\0" + "UNSUPPORTED_MASK_PARAMETER\0" + "UNSUPPORTED_SIGNATURE_TYPE\0" + "WRONG_PUBLIC_KEY_TYPE\0" + "OUTPUT_TOO_LARGE\0" + "UNKNOWN_NID\0" + "BAD_BASE64_DECODE\0" + "BAD_END_LINE\0" + "BAD_IV_CHARS\0" + "BAD_PASSWORD_READ\0" + "CIPHER_IS_NULL\0" + "ERROR_CONVERTING_PRIVATE_KEY\0" + "NOT_DEK_INFO\0" + "NOT_ENCRYPTED\0" + "NOT_PROC_TYPE\0" + "NO_START_LINE\0" + "READ_KEY\0" + "SHORT_HEADER\0" + "UNSUPPORTED_CIPHER\0" + "UNSUPPORTED_ENCRYPTION\0" + "BAD_PKCS12_DATA\0" + "BAD_PKCS12_VERSION\0" + "CIPHER_HAS_NO_OBJECT_IDENTIFIER\0" + "CRYPT_ERROR\0" + "ENCRYPT_ERROR\0" + "ERROR_SETTING_CIPHER_PARAMS\0" + "INCORRECT_PASSWORD\0" + "KEYGEN_FAILURE\0" + "KEY_GEN_ERROR\0" + "METHOD_NOT_SUPPORTED\0" + "MISSING_MAC\0" + "MULTIPLE_PRIVATE_KEYS_IN_PKCS12\0" + "PKCS12_PUBLIC_KEY_INTEGRITY_NOT_SUPPORTED\0" + "PKCS12_TOO_DEEPLY_NESTED\0" + "PRIVATE_KEY_DECODE_ERROR\0" + "PRIVATE_KEY_ENCODE_ERROR\0" + "UNKNOWN_ALGORITHM\0" + "UNKNOWN_CIPHER\0" + "UNKNOWN_CIPHER_ALGORITHM\0" + "UNKNOWN_HASH\0" + "UNSUPPORTED_PRIVATE_KEY_ALGORITHM\0" + "BAD_E_VALUE\0" + "BAD_FIXED_HEADER_DECRYPT\0" + "BAD_PAD_BYTE_COUNT\0" + "BAD_RSA_PARAMETERS\0" + "BLOCK_TYPE_IS_NOT_01\0" + "BN_NOT_INITIALIZED\0" + "CANNOT_RECOVER_MULTI_PRIME_KEY\0" + "CRT_PARAMS_ALREADY_GIVEN\0" + "CRT_VALUES_INCORRECT\0" + "DATA_LEN_NOT_EQUAL_TO_MOD_LEN\0" + "DATA_TOO_LARGE\0" + "DATA_TOO_LARGE_FOR_KEY_SIZE\0" + "DATA_TOO_LARGE_FOR_MODULUS\0" + "DATA_TOO_SMALL\0" + "DATA_TOO_SMALL_FOR_KEY_SIZE\0" + "DIGEST_TOO_BIG_FOR_RSA_KEY\0" + "D_E_NOT_CONGRUENT_TO_1\0" + "EMPTY_PUBLIC_KEY\0" + "FIRST_OCTET_INVALID\0" + "INCONSISTENT_SET_OF_CRT_VALUES\0" + "INTERNAL_ERROR\0" + "INVALID_MESSAGE_LENGTH\0" + "KEY_SIZE_TOO_SMALL\0" + "LAST_OCTET_INVALID\0" + "MUST_HAVE_AT_LEAST_TWO_PRIMES\0" + "NO_PUBLIC_EXPONENT\0" + "NULL_BEFORE_BLOCK_MISSING\0" + "N_NOT_EQUAL_P_Q\0" + "OAEP_DECODING_ERROR\0" + "ONLY_ONE_OF_P_Q_GIVEN\0" + "OUTPUT_BUFFER_TOO_SMALL\0" + "PADDING_CHECK_FAILED\0" + "PKCS_DECODING_ERROR\0" + "SLEN_CHECK_FAILED\0" + "SLEN_RECOVERY_FAILED\0" + "UNKNOWN_ALGORITHM_TYPE\0" + "UNKNOWN_PADDING_TYPE\0" + "VALUE_MISSING\0" + "WRONG_SIGNATURE_LENGTH\0" + "APP_DATA_IN_HANDSHAKE\0" + "ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT\0" + "BAD_ALERT\0" + "BAD_CHANGE_CIPHER_SPEC\0" + "BAD_DATA_RETURNED_BY_CALLBACK\0" + "BAD_DH_P_LENGTH\0" + "BAD_DIGEST_LENGTH\0" + "BAD_ECC_CERT\0" + "BAD_ECPOINT\0" + "BAD_HANDSHAKE_RECORD\0" + "BAD_HELLO_REQUEST\0" + "BAD_LENGTH\0" + "BAD_PACKET_LENGTH\0" + "BAD_RSA_ENCRYPT\0" + "BAD_SRTP_MKI_VALUE\0" + "BAD_SRTP_PROTECTION_PROFILE_LIST\0" + "BAD_SSL_FILETYPE\0" + "BAD_WRITE_RETRY\0" + "BIO_NOT_SET\0" + "CA_DN_LENGTH_MISMATCH\0" + "CA_DN_TOO_LONG\0" + "CCS_RECEIVED_EARLY\0" + "CERTIFICATE_VERIFY_FAILED\0" + "CERT_CB_ERROR\0" + "CERT_LENGTH_MISMATCH\0" + "CHANNEL_ID_NOT_P256\0" + "CHANNEL_ID_SIGNATURE_INVALID\0" + "CIPHER_OR_HASH_UNAVAILABLE\0" + "CLIENTHELLO_PARSE_FAILED\0" + "CLIENTHELLO_TLSEXT\0" + "CONNECTION_REJECTED\0" + "CONNECTION_TYPE_NOT_SET\0" + "CUSTOM_EXTENSION_ERROR\0" + "DATA_LENGTH_TOO_LONG\0" + "DECRYPTION_FAILED\0" + "DECRYPTION_FAILED_OR_BAD_RECORD_MAC\0" + "DH_PUBLIC_VALUE_LENGTH_IS_WRONG\0" + "DH_P_TOO_LONG\0" + "DIGEST_CHECK_FAILED\0" + "DTLS_MESSAGE_TOO_BIG\0" + "ECC_CERT_NOT_FOR_SIGNING\0" + "EMS_STATE_INCONSISTENT\0" + "ENCRYPTED_LENGTH_TOO_LONG\0" + "ERROR_ADDING_EXTENSION\0" + "ERROR_IN_RECEIVED_CIPHER_LIST\0" + "ERROR_PARSING_EXTENSION\0" + "EXCESSIVE_MESSAGE_SIZE\0" + "EXTRA_DATA_IN_MESSAGE\0" + "FRAGMENT_MISMATCH\0" + "GOT_NEXT_PROTO_WITHOUT_EXTENSION\0" + "HANDSHAKE_FAILURE_ON_CLIENT_HELLO\0" + "HTTPS_PROXY_REQUEST\0" + "HTTP_REQUEST\0" + "INAPPROPRIATE_FALLBACK\0" + "INVALID_COMMAND\0" + "INVALID_MESSAGE\0" + "INVALID_SSL_SESSION\0" + "INVALID_TICKET_KEYS_LENGTH\0" + "LENGTH_MISMATCH\0" + "LIBRARY_HAS_NO_CIPHERS\0" + "MISSING_EXTENSION\0" + "MISSING_RSA_CERTIFICATE\0" + "MISSING_TMP_DH_KEY\0" + "MISSING_TMP_ECDH_KEY\0" + "MIXED_SPECIAL_OPERATOR_WITH_GROUPS\0" + "MTU_TOO_SMALL\0" + "NEGOTIATED_BOTH_NPN_AND_ALPN\0" + "NESTED_GROUP\0" + "NO_CERTIFICATES_RETURNED\0" + "NO_CERTIFICATE_ASSIGNED\0" + "NO_CERTIFICATE_SET\0" + "NO_CIPHERS_AVAILABLE\0" + "NO_CIPHERS_PASSED\0" + "NO_CIPHER_MATCH\0" + "NO_COMPRESSION_SPECIFIED\0" + "NO_METHOD_SPECIFIED\0" + "NO_P256_SUPPORT\0" + "NO_PRIVATE_KEY_ASSIGNED\0" + "NO_RENEGOTIATION\0" + "NO_REQUIRED_DIGEST\0" + "NO_SHARED_CIPHER\0" + "NULL_SSL_CTX\0" + "NULL_SSL_METHOD_PASSED\0" + "OLD_SESSION_CIPHER_NOT_RETURNED\0" + "OLD_SESSION_VERSION_NOT_RETURNED\0" + "PARSE_TLSEXT\0" + "PATH_TOO_LONG\0" + "PEER_DID_NOT_RETURN_A_CERTIFICATE\0" + "PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE\0" + "PROTOCOL_IS_SHUTDOWN\0" + "PSK_IDENTITY_NOT_FOUND\0" + "PSK_NO_CLIENT_CB\0" + "PSK_NO_SERVER_CB\0" + "READ_TIMEOUT_EXPIRED\0" + "RECORD_LENGTH_MISMATCH\0" + "RECORD_TOO_LARGE\0" + "RENEGOTIATION_ENCODING_ERR\0" + "RENEGOTIATION_MISMATCH\0" + "REQUIRED_CIPHER_MISSING\0" + "RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION\0" + "RESUMED_NON_EMS_SESSION_WITH_EMS_EXTENSION\0" + "SCSV_RECEIVED_WHEN_RENEGOTIATING\0" + "SERVERHELLO_TLSEXT\0" + "SESSION_ID_CONTEXT_UNINITIALIZED\0" + "SESSION_MAY_NOT_BE_CREATED\0" + "SIGNATURE_ALGORITHMS_EXTENSION_SENT_BY_SERVER\0" + "SRTP_COULD_NOT_ALLOCATE_PROFILES\0" + "SRTP_UNKNOWN_PROTECTION_PROFILE\0" + "SSL3_EXT_INVALID_SERVERNAME\0" + "SSLV3_ALERT_BAD_CERTIFICATE\0" + "SSLV3_ALERT_BAD_RECORD_MAC\0" + "SSLV3_ALERT_CERTIFICATE_EXPIRED\0" + "SSLV3_ALERT_CERTIFICATE_REVOKED\0" + "SSLV3_ALERT_CERTIFICATE_UNKNOWN\0" + "SSLV3_ALERT_CLOSE_NOTIFY\0" + "SSLV3_ALERT_DECOMPRESSION_FAILURE\0" + "SSLV3_ALERT_HANDSHAKE_FAILURE\0" + "SSLV3_ALERT_ILLEGAL_PARAMETER\0" + "SSLV3_ALERT_NO_CERTIFICATE\0" + "SSLV3_ALERT_UNEXPECTED_MESSAGE\0" + "SSLV3_ALERT_UNSUPPORTED_CERTIFICATE\0" + "SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION\0" + "SSL_HANDSHAKE_FAILURE\0" + "SSL_SESSION_ID_CONTEXT_TOO_LONG\0" + "TLSV1_ALERT_ACCESS_DENIED\0" + "TLSV1_ALERT_DECODE_ERROR\0" + "TLSV1_ALERT_DECRYPTION_FAILED\0" + "TLSV1_ALERT_DECRYPT_ERROR\0" + "TLSV1_ALERT_EXPORT_RESTRICTION\0" + "TLSV1_ALERT_INAPPROPRIATE_FALLBACK\0" + "TLSV1_ALERT_INSUFFICIENT_SECURITY\0" + "TLSV1_ALERT_INTERNAL_ERROR\0" + "TLSV1_ALERT_NO_RENEGOTIATION\0" + "TLSV1_ALERT_PROTOCOL_VERSION\0" + "TLSV1_ALERT_RECORD_OVERFLOW\0" + "TLSV1_ALERT_UNKNOWN_CA\0" + "TLSV1_ALERT_USER_CANCELLED\0" + "TLSV1_BAD_CERTIFICATE_HASH_VALUE\0" + "TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE\0" + "TLSV1_CERTIFICATE_UNOBTAINABLE\0" + "TLSV1_UNRECOGNIZED_NAME\0" + "TLSV1_UNSUPPORTED_EXTENSION\0" + "TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST\0" + "TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG\0" + "TOO_MANY_EMPTY_FRAGMENTS\0" + "TOO_MANY_WARNING_ALERTS\0" + "UNABLE_TO_FIND_ECDH_PARAMETERS\0" + "UNEXPECTED_EXTENSION\0" + "UNEXPECTED_MESSAGE\0" + "UNEXPECTED_OPERATOR_IN_GROUP\0" + "UNEXPECTED_RECORD\0" + "UNKNOWN_ALERT_TYPE\0" + "UNKNOWN_CERTIFICATE_TYPE\0" + "UNKNOWN_CIPHER_RETURNED\0" + "UNKNOWN_CIPHER_TYPE\0" + "UNKNOWN_KEY_EXCHANGE_TYPE\0" + "UNKNOWN_PROTOCOL\0" + "UNKNOWN_SSL_VERSION\0" + "UNKNOWN_STATE\0" + "UNSAFE_LEGACY_RENEGOTIATION_DISABLED\0" + "UNSUPPORTED_COMPRESSION_ALGORITHM\0" + "UNSUPPORTED_ELLIPTIC_CURVE\0" + "UNSUPPORTED_PROTOCOL\0" + "WRONG_CERTIFICATE_TYPE\0" + "WRONG_CIPHER_RETURNED\0" + "WRONG_CURVE\0" + "WRONG_MESSAGE_TYPE\0" + "WRONG_SIGNATURE_TYPE\0" + "WRONG_SSL_VERSION\0" + "WRONG_VERSION_NUMBER\0" + "X509_LIB\0" + "X509_VERIFICATION_SETUP_PROBLEMS\0" + "AKID_MISMATCH\0" + "BAD_PKCS7_VERSION\0" + "BAD_X509_FILETYPE\0" + "BASE64_DECODE_ERROR\0" + "CANT_CHECK_DH_KEY\0" + "CERT_ALREADY_IN_HASH_TABLE\0" + "CRL_ALREADY_DELTA\0" + "CRL_VERIFY_FAILURE\0" + "IDP_MISMATCH\0" + "INVALID_DIRECTORY\0" + "INVALID_FIELD_NAME\0" + "INVALID_TRUST\0" + "ISSUER_MISMATCH\0" + "KEY_TYPE_MISMATCH\0" + "KEY_VALUES_MISMATCH\0" + "LOADING_CERT_DIR\0" + "LOADING_DEFAULTS\0" + "NEWER_CRL_NOT_NEWER\0" + "NOT_PKCS7_SIGNED_DATA\0" + "NO_CERTIFICATES_INCLUDED\0" + "NO_CERT_SET_FOR_US_TO_VERIFY\0" + "NO_CRLS_INCLUDED\0" + "NO_CRL_NUMBER\0" + "PUBLIC_KEY_DECODE_ERROR\0" + "PUBLIC_KEY_ENCODE_ERROR\0" + "SHOULD_RETRY\0" + "UNABLE_TO_FIND_PARAMETERS_IN_CHAIN\0" + "UNABLE_TO_GET_CERTS_PUBLIC_KEY\0" + "UNKNOWN_KEY_TYPE\0" + "UNKNOWN_PURPOSE_ID\0" + "UNKNOWN_TRUST_ID\0" + "WRONG_LOOKUP_TYPE\0" + "BAD_IP_ADDRESS\0" + "BAD_OBJECT\0" + "BN_DEC2BN_ERROR\0" + "BN_TO_ASN1_INTEGER_ERROR\0" + "CANNOT_FIND_FREE_FUNCTION\0" + "DIRNAME_ERROR\0" + "DISTPOINT_ALREADY_SET\0" + "DUPLICATE_ZONE_ID\0" + "ERROR_CONVERTING_ZONE\0" + "ERROR_CREATING_EXTENSION\0" + "ERROR_IN_EXTENSION\0" + "EXPECTED_A_SECTION_NAME\0" + "EXTENSION_EXISTS\0" + "EXTENSION_NAME_ERROR\0" + "EXTENSION_NOT_FOUND\0" + "EXTENSION_SETTING_NOT_SUPPORTED\0" + "EXTENSION_VALUE_ERROR\0" + "ILLEGAL_EMPTY_EXTENSION\0" + "ILLEGAL_HEX_DIGIT\0" + "INCORRECT_POLICY_SYNTAX_TAG\0" + "INVALID_BOOLEAN_STRING\0" + "INVALID_EXTENSION_STRING\0" + "INVALID_MULTIPLE_RDNS\0" + "INVALID_NAME\0" + "INVALID_NULL_ARGUMENT\0" + "INVALID_NULL_NAME\0" + "INVALID_NULL_VALUE\0" + "INVALID_NUMBERS\0" + "INVALID_OBJECT_IDENTIFIER\0" + "INVALID_OPTION\0" + "INVALID_POLICY_IDENTIFIER\0" + "INVALID_PROXY_POLICY_SETTING\0" + "INVALID_PURPOSE\0" + "INVALID_SECTION\0" + "INVALID_SYNTAX\0" + "ISSUER_DECODE_ERROR\0" + "NEED_ORGANIZATION_AND_NUMBERS\0" + "NO_CONFIG_DATABASE\0" + "NO_ISSUER_CERTIFICATE\0" + "NO_ISSUER_DETAILS\0" + "NO_POLICY_IDENTIFIER\0" + "NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED\0" + "NO_PUBLIC_KEY\0" + "NO_SUBJECT_DETAILS\0" + "ODD_NUMBER_OF_DIGITS\0" + "OPERATION_NOT_DEFINED\0" + "OTHERNAME_ERROR\0" + "POLICY_LANGUAGE_ALREADY_DEFINED\0" + "POLICY_PATH_LENGTH\0" + "POLICY_PATH_LENGTH_ALREADY_DEFINED\0" + "POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY\0" + "SECTION_NOT_FOUND\0" + "UNABLE_TO_GET_ISSUER_DETAILS\0" + "UNABLE_TO_GET_ISSUER_KEYID\0" + "UNKNOWN_BIT_STRING_ARGUMENT\0" + "UNKNOWN_EXTENSION\0" + "UNKNOWN_EXTENSION_NAME\0" + "UNKNOWN_OPTION\0" + "UNSUPPORTED_OPTION\0" + "USER_TOO_LONG\0" + ""; + diff --git a/external/boringssl/crypto/err/err_data_generate.go b/external/boringssl/crypto/err/err_data_generate.go new file mode 100644 index 0000000000..893ebffe5a --- /dev/null +++ b/external/boringssl/crypto/err/err_data_generate.go @@ -0,0 +1,284 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +package main + +import ( + "bufio" + "bytes" + "errors" + "flag" + "fmt" + "io" + "os" + "sort" + "strconv" + "strings" +) + +var verbose = flag.Bool("verbose", false, "If true, prints a status message at the end.") + +// libraryNames must be kept in sync with the enum in err.h. The generated code +// will contain static assertions to enforce this. +var libraryNames = []string{ + "NONE", + "SYS", + "BN", + "RSA", + "DH", + "EVP", + "BUF", + "OBJ", + "PEM", + "DSA", + "X509", + "ASN1", + "CONF", + "CRYPTO", + "EC", + "SSL", + "BIO", + "PKCS7", + "PKCS8", + "X509V3", + "RAND", + "ENGINE", + "OCSP", + "UI", + "COMP", + "ECDSA", + "ECDH", + "HMAC", + "DIGEST", + "CIPHER", + "HKDF", + "USER", +} + +// stringList is a map from uint32 -> string which can output data for a sorted +// list as C literals. +type stringList struct { + // entries is an array of keys and offsets into |stringData|. The + // offsets are in the bottom 15 bits of each uint32 and the key is the + // top 17 bits. + entries []uint32 + // internedStrings contains the same strings as are in |stringData|, + // but allows for easy deduplication. It maps a string to its offset in + // |stringData|. + internedStrings map[string]uint32 + stringData []byte +} + +func newStringList() *stringList { + return &stringList{ + internedStrings: make(map[string]uint32), + } +} + +// offsetMask is the bottom 15 bits. It's a mask that selects the offset from a +// uint32 in entries. +const offsetMask = 0x7fff + +func (st *stringList) Add(key uint32, value string) error { + if key&offsetMask != 0 { + return errors.New("need bottom 15 bits of the key for the offset") + } + offset, ok := st.internedStrings[value] + if !ok { + offset = uint32(len(st.stringData)) + if offset&offsetMask != offset { + return errors.New("stringList overflow") + } + st.stringData = append(st.stringData, []byte(value)...) + st.stringData = append(st.stringData, 0) + st.internedStrings[value] = offset + } + + for _, existing := range st.entries { + if existing>>15 == key>>15 { + panic("duplicate entry") + } + } + st.entries = append(st.entries, key|offset) + return nil +} + +// keySlice is a type that implements sorting of entries values. +type keySlice []uint32 + +func (ks keySlice) Len() int { + return len(ks) +} + +func (ks keySlice) Less(i, j int) bool { + return (ks[i] >> 15) < (ks[j] >> 15) +} + +func (ks keySlice) Swap(i, j int) { + ks[i], ks[j] = ks[j], ks[i] +} + +func (st *stringList) buildList() []uint32 { + sort.Sort(keySlice(st.entries)) + return st.entries +} + +type stringWriter interface { + io.Writer + WriteString(string) (int, error) +} + +func (st *stringList) WriteTo(out stringWriter, name string) { + list := st.buildList() + if *verbose { + fmt.Fprintf(os.Stderr, "%s: %d bytes of list and %d bytes of string data.\n", name, 4*len(list), len(st.stringData)) + } + + values := "kOpenSSL" + name + "Values" + out.WriteString("const uint32_t " + values + "[] = {\n") + for _, v := range list { + fmt.Fprintf(out, " 0x%x,\n", v) + } + out.WriteString("};\n\n") + out.WriteString("const size_t " + values + "Len = sizeof(" + values + ") / sizeof(" + values + "[0]);\n\n") + + stringData := "kOpenSSL" + name + "StringData" + out.WriteString("const char " + stringData + "[] =\n \"") + for i, c := range st.stringData { + if c == 0 { + out.WriteString("\\0\"\n \"") + continue + } + out.Write(st.stringData[i : i+1]) + } + out.WriteString("\";\n\n") +} + +type errorData struct { + reasons *stringList + libraryMap map[string]uint32 +} + +func (e *errorData) readErrorDataFile(filename string) error { + inFile, err := os.Open(filename) + if err != nil { + return err + } + defer inFile.Close() + + scanner := bufio.NewScanner(inFile) + comma := []byte(",") + + lineNo := 0 + for scanner.Scan() { + lineNo++ + + line := scanner.Bytes() + if len(line) == 0 { + continue + } + parts := bytes.Split(line, comma) + if len(parts) != 3 { + return fmt.Errorf("bad line %d in %s: found %d values but want 3", lineNo, filename, len(parts)) + } + libNum, ok := e.libraryMap[string(parts[0])] + if !ok { + return fmt.Errorf("bad line %d in %s: unknown library", lineNo, filename) + } + if libNum >= 64 { + return fmt.Errorf("bad line %d in %s: library value too large", lineNo, filename) + } + key, err := strconv.ParseUint(string(parts[1]), 10 /* base */, 32 /* bit size */) + if err != nil { + return fmt.Errorf("bad line %d in %s: %s", lineNo, filename, err) + } + if key >= 2048 { + return fmt.Errorf("bad line %d in %s: key too large", lineNo, filename) + } + value := string(parts[2]) + + listKey := libNum<<26 | uint32(key)<<15 + + err = e.reasons.Add(listKey, value) + if err != nil { + return err + } + } + + return scanner.Err() +} + +func main() { + flag.Parse() + + e := &errorData{ + reasons: newStringList(), + libraryMap: make(map[string]uint32), + } + for i, name := range libraryNames { + e.libraryMap[name] = uint32(i) + 1 + } + + cwd, err := os.Open(".") + if err != nil { + panic(err) + } + names, err := cwd.Readdirnames(-1) + if err != nil { + panic(err) + } + + sort.Strings(names) + for _, name := range names { + if !strings.HasSuffix(name, ".errordata") { + continue + } + if err := e.readErrorDataFile(name); err != nil { + panic(err) + } + } + + out := os.Stdout + + out.WriteString(`/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + + /* This file was generated by err_data_generate.go. */ + +#include +#include +#include + + +`) + + for i, name := range libraryNames { + fmt.Fprintf(out, "OPENSSL_COMPILE_ASSERT(ERR_LIB_%s == %d, library_values_changed_%d);\n", name, i+1, i+1) + } + fmt.Fprintf(out, "OPENSSL_COMPILE_ASSERT(ERR_NUM_LIBS == %d, library_values_changed_num);\n", len(libraryNames)+1) + out.WriteString("\n") + + e.reasons.WriteTo(out, "Reason") +} diff --git a/external/boringssl/crypto/err/err_test.cc b/external/boringssl/crypto/err/err_test.cc new file mode 100644 index 0000000000..d69135585d --- /dev/null +++ b/external/boringssl/crypto/err/err_test.cc @@ -0,0 +1,162 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include + +#include +#include +#include + + +static bool TestOverflow() { + for (unsigned i = 0; i < ERR_NUM_ERRORS*2; i++) { + ERR_put_error(1, 0 /* unused */, i+1, "test", 1); + } + + for (unsigned i = 0; i < ERR_NUM_ERRORS - 1; i++) { + uint32_t err = ERR_get_error(); + /* Errors are returned in order they were pushed, with the least recent ones + * removed, up to |ERR_NUM_ERRORS - 1| errors. So the errors returned are + * |ERR_NUM_ERRORS + 2| through |ERR_NUM_ERRORS * 2|, inclusive. */ + if (err == 0 || ((unsigned)ERR_GET_REASON(err)) != i + ERR_NUM_ERRORS + 2) { + fprintf(stderr, "ERR_get_error failed at %u\n", i); + return false; + } + } + + if (ERR_get_error() != 0) { + fprintf(stderr, "ERR_get_error more than the expected number of values.\n"); + return false; + } + + return true; +} + +static bool TestPutError() { + if (ERR_get_error() != 0) { + fprintf(stderr, "ERR_get_error returned value before an error was added.\n"); + return false; + } + + ERR_put_error(1, 0 /* unused */, 2, "test", 4); + ERR_add_error_data(1, "testing"); + + int peeked_line, line, peeked_flags, flags; + const char *peeked_file, *file, *peeked_data, *data; + uint32_t peeked_packed_error = + ERR_peek_error_line_data(&peeked_file, &peeked_line, &peeked_data, + &peeked_flags); + uint32_t packed_error = ERR_get_error_line_data(&file, &line, &data, &flags); + + if (peeked_packed_error != packed_error || + peeked_file != file || + peeked_data != data || + peeked_flags != flags) { + fprintf(stderr, "Bad peeked error data returned.\n"); + return false; + } + + if (strcmp(file, "test") != 0 || + line != 4 || + (flags & ERR_FLAG_STRING) == 0 || + ERR_GET_LIB(packed_error) != 1 || + ERR_GET_REASON(packed_error) != 2 || + strcmp(data, "testing") != 0) { + fprintf(stderr, "Bad error data returned.\n"); + return false; + } + + return true; +} + +static bool TestClearError() { + if (ERR_get_error() != 0) { + fprintf(stderr, "ERR_get_error returned value before an error was added.\n"); + return false; + } + + ERR_put_error(1, 0 /* unused */, 2, "test", 4); + ERR_clear_error(); + + if (ERR_get_error() != 0) { + fprintf(stderr, "Error remained after clearing.\n"); + return false; + } + + return true; +} + +static bool TestPrint() { + ERR_put_error(1, 0 /* unused */, 2, "test", 4); + ERR_add_error_data(1, "testing"); + uint32_t packed_error = ERR_get_error(); + + char buf[256]; + for (size_t i = 0; i <= sizeof(buf); i++) { + ERR_error_string_n(packed_error, buf, i); + } + + return true; +} + +static bool TestRelease() { + ERR_put_error(1, 0 /* unused */, 2, "test", 4); + ERR_remove_thread_state(NULL); + return true; +} + +static bool HasSuffix(const char *str, const char *suffix) { + size_t suffix_len = strlen(suffix); + size_t str_len = strlen(str); + if (str_len < suffix_len) { + return false; + } + return strcmp(str + str_len - suffix_len, suffix) == 0; +} + +static bool TestPutMacro() { + int expected_line = __LINE__ + 1; + OPENSSL_PUT_ERROR(USER, ERR_R_INTERNAL_ERROR); + + int line; + const char *file; + uint32_t error = ERR_get_error_line(&file, &line); + + if (!HasSuffix(file, "err_test.cc") || + line != expected_line || + ERR_GET_LIB(error) != ERR_LIB_USER || + ERR_GET_REASON(error) != ERR_R_INTERNAL_ERROR) { + fprintf(stderr, "Bad error data returned.\n"); + return false; + } + + return true; +} + +int main() { + CRYPTO_library_init(); + + if (!TestOverflow() || + !TestPutError() || + !TestClearError() || + !TestPrint() || + !TestRelease() || + !TestPutMacro()) { + return 1; + } + + printf("PASS\n"); + return 0; +} diff --git a/external/boringssl/crypto/err/evp.errordata b/external/boringssl/crypto/err/evp.errordata new file mode 100644 index 0000000000..a482f7693e --- /dev/null +++ b/external/boringssl/crypto/err/evp.errordata @@ -0,0 +1,30 @@ +EVP,100,BUFFER_TOO_SMALL +EVP,101,COMMAND_NOT_SUPPORTED +EVP,102,DECODE_ERROR +EVP,103,DIFFERENT_KEY_TYPES +EVP,104,DIFFERENT_PARAMETERS +EVP,105,ENCODE_ERROR +EVP,106,EXPECTING_AN_EC_KEY_KEY +EVP,107,EXPECTING_AN_RSA_KEY +EVP,108,EXPECTING_A_DSA_KEY +EVP,109,ILLEGAL_OR_UNSUPPORTED_PADDING_MODE +EVP,110,INVALID_DIGEST_LENGTH +EVP,111,INVALID_DIGEST_TYPE +EVP,112,INVALID_KEYBITS +EVP,113,INVALID_MGF1_MD +EVP,114,INVALID_OPERATION +EVP,115,INVALID_PADDING_MODE +EVP,116,INVALID_PSS_SALTLEN +EVP,117,KEYS_NOT_SET +EVP,118,MISSING_PARAMETERS +EVP,119,NO_DEFAULT_DIGEST +EVP,120,NO_KEY_SET +EVP,121,NO_MDC2_SUPPORT +EVP,122,NO_NID_FOR_CURVE +EVP,123,NO_OPERATION_SET +EVP,124,NO_PARAMETERS_SET +EVP,125,OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE +EVP,126,OPERATON_NOT_INITIALIZED +EVP,127,UNKNOWN_PUBLIC_KEY_TYPE +EVP,128,UNSUPPORTED_ALGORITHM +EVP,129,UNSUPPORTED_PUBLIC_KEY_TYPE diff --git a/external/boringssl/crypto/err/hkdf.errordata b/external/boringssl/crypto/err/hkdf.errordata new file mode 100644 index 0000000000..84866dee16 --- /dev/null +++ b/external/boringssl/crypto/err/hkdf.errordata @@ -0,0 +1 @@ +HKDF,100,OUTPUT_TOO_LARGE diff --git a/external/boringssl/crypto/err/obj.errordata b/external/boringssl/crypto/err/obj.errordata new file mode 100644 index 0000000000..c54435ea97 --- /dev/null +++ b/external/boringssl/crypto/err/obj.errordata @@ -0,0 +1 @@ +OBJ,100,UNKNOWN_NID diff --git a/external/boringssl/crypto/err/pem.errordata b/external/boringssl/crypto/err/pem.errordata new file mode 100644 index 0000000000..2a4b73af2d --- /dev/null +++ b/external/boringssl/crypto/err/pem.errordata @@ -0,0 +1,15 @@ +PEM,100,BAD_BASE64_DECODE +PEM,101,BAD_DECRYPT +PEM,102,BAD_END_LINE +PEM,103,BAD_IV_CHARS +PEM,104,BAD_PASSWORD_READ +PEM,105,CIPHER_IS_NULL +PEM,106,ERROR_CONVERTING_PRIVATE_KEY +PEM,107,NOT_DEK_INFO +PEM,108,NOT_ENCRYPTED +PEM,109,NOT_PROC_TYPE +PEM,110,NO_START_LINE +PEM,111,READ_KEY +PEM,112,SHORT_HEADER +PEM,113,UNSUPPORTED_CIPHER +PEM,114,UNSUPPORTED_ENCRYPTION diff --git a/external/boringssl/crypto/err/pkcs8.errordata b/external/boringssl/crypto/err/pkcs8.errordata new file mode 100644 index 0000000000..0eb5083bc2 --- /dev/null +++ b/external/boringssl/crypto/err/pkcs8.errordata @@ -0,0 +1,25 @@ +PKCS8,100,BAD_PKCS12_DATA +PKCS8,101,BAD_PKCS12_VERSION +PKCS8,102,CIPHER_HAS_NO_OBJECT_IDENTIFIER +PKCS8,103,CRYPT_ERROR +PKCS8,104,DECODE_ERROR +PKCS8,105,ENCODE_ERROR +PKCS8,106,ENCRYPT_ERROR +PKCS8,107,ERROR_SETTING_CIPHER_PARAMS +PKCS8,108,INCORRECT_PASSWORD +PKCS8,109,KEYGEN_FAILURE +PKCS8,110,KEY_GEN_ERROR +PKCS8,111,METHOD_NOT_SUPPORTED +PKCS8,112,MISSING_MAC +PKCS8,113,MULTIPLE_PRIVATE_KEYS_IN_PKCS12 +PKCS8,114,PKCS12_PUBLIC_KEY_INTEGRITY_NOT_SUPPORTED +PKCS8,115,PKCS12_TOO_DEEPLY_NESTED +PKCS8,116,PRIVATE_KEY_DECODE_ERROR +PKCS8,117,PRIVATE_KEY_ENCODE_ERROR +PKCS8,118,TOO_LONG +PKCS8,119,UNKNOWN_ALGORITHM +PKCS8,120,UNKNOWN_CIPHER +PKCS8,121,UNKNOWN_CIPHER_ALGORITHM +PKCS8,122,UNKNOWN_DIGEST +PKCS8,123,UNKNOWN_HASH +PKCS8,124,UNSUPPORTED_PRIVATE_KEY_ALGORITHM diff --git a/external/boringssl/crypto/err/rsa.errordata b/external/boringssl/crypto/err/rsa.errordata new file mode 100644 index 0000000000..62d286cc38 --- /dev/null +++ b/external/boringssl/crypto/err/rsa.errordata @@ -0,0 +1,46 @@ +RSA,100,BAD_ENCODING +RSA,101,BAD_E_VALUE +RSA,102,BAD_FIXED_HEADER_DECRYPT +RSA,103,BAD_PAD_BYTE_COUNT +RSA,104,BAD_RSA_PARAMETERS +RSA,105,BAD_SIGNATURE +RSA,106,BAD_VERSION +RSA,107,BLOCK_TYPE_IS_NOT_01 +RSA,108,BN_NOT_INITIALIZED +RSA,109,CANNOT_RECOVER_MULTI_PRIME_KEY +RSA,110,CRT_PARAMS_ALREADY_GIVEN +RSA,111,CRT_VALUES_INCORRECT +RSA,112,DATA_LEN_NOT_EQUAL_TO_MOD_LEN +RSA,113,DATA_TOO_LARGE +RSA,114,DATA_TOO_LARGE_FOR_KEY_SIZE +RSA,115,DATA_TOO_LARGE_FOR_MODULUS +RSA,116,DATA_TOO_SMALL +RSA,117,DATA_TOO_SMALL_FOR_KEY_SIZE +RSA,118,DIGEST_TOO_BIG_FOR_RSA_KEY +RSA,119,D_E_NOT_CONGRUENT_TO_1 +RSA,120,EMPTY_PUBLIC_KEY +RSA,121,ENCODE_ERROR +RSA,122,FIRST_OCTET_INVALID +RSA,123,INCONSISTENT_SET_OF_CRT_VALUES +RSA,124,INTERNAL_ERROR +RSA,125,INVALID_MESSAGE_LENGTH +RSA,126,KEY_SIZE_TOO_SMALL +RSA,127,LAST_OCTET_INVALID +RSA,128,MODULUS_TOO_LARGE +RSA,129,MUST_HAVE_AT_LEAST_TWO_PRIMES +RSA,130,NO_PUBLIC_EXPONENT +RSA,131,NULL_BEFORE_BLOCK_MISSING +RSA,132,N_NOT_EQUAL_P_Q +RSA,133,OAEP_DECODING_ERROR +RSA,134,ONLY_ONE_OF_P_Q_GIVEN +RSA,135,OUTPUT_BUFFER_TOO_SMALL +RSA,136,PADDING_CHECK_FAILED +RSA,137,PKCS_DECODING_ERROR +RSA,138,SLEN_CHECK_FAILED +RSA,139,SLEN_RECOVERY_FAILED +RSA,140,TOO_LONG +RSA,141,TOO_MANY_ITERATIONS +RSA,142,UNKNOWN_ALGORITHM_TYPE +RSA,143,UNKNOWN_PADDING_TYPE +RSA,144,VALUE_MISSING +RSA,145,WRONG_SIGNATURE_LENGTH diff --git a/external/boringssl/crypto/err/ssl.errordata b/external/boringssl/crypto/err/ssl.errordata new file mode 100644 index 0000000000..dfe4ac8127 --- /dev/null +++ b/external/boringssl/crypto/err/ssl.errordata @@ -0,0 +1,181 @@ +SSL,100,APP_DATA_IN_HANDSHAKE +SSL,101,ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT +SSL,102,BAD_ALERT +SSL,103,BAD_CHANGE_CIPHER_SPEC +SSL,104,BAD_DATA_RETURNED_BY_CALLBACK +SSL,105,BAD_DH_P_LENGTH +SSL,106,BAD_DIGEST_LENGTH +SSL,107,BAD_ECC_CERT +SSL,108,BAD_ECPOINT +SSL,109,BAD_HANDSHAKE_RECORD +SSL,110,BAD_HELLO_REQUEST +SSL,111,BAD_LENGTH +SSL,112,BAD_PACKET_LENGTH +SSL,113,BAD_RSA_ENCRYPT +SSL,114,BAD_SIGNATURE +SSL,115,BAD_SRTP_MKI_VALUE +SSL,116,BAD_SRTP_PROTECTION_PROFILE_LIST +SSL,117,BAD_SSL_FILETYPE +SSL,118,BAD_WRITE_RETRY +SSL,119,BIO_NOT_SET +SSL,120,BN_LIB +SSL,121,BUFFER_TOO_SMALL +SSL,122,CA_DN_LENGTH_MISMATCH +SSL,123,CA_DN_TOO_LONG +SSL,124,CCS_RECEIVED_EARLY +SSL,125,CERTIFICATE_VERIFY_FAILED +SSL,126,CERT_CB_ERROR +SSL,127,CERT_LENGTH_MISMATCH +SSL,128,CHANNEL_ID_NOT_P256 +SSL,129,CHANNEL_ID_SIGNATURE_INVALID +SSL,130,CIPHER_OR_HASH_UNAVAILABLE +SSL,131,CLIENTHELLO_PARSE_FAILED +SSL,132,CLIENTHELLO_TLSEXT +SSL,133,CONNECTION_REJECTED +SSL,134,CONNECTION_TYPE_NOT_SET +SSL,135,CUSTOM_EXTENSION_ERROR +SSL,136,DATA_LENGTH_TOO_LONG +SSL,137,DECODE_ERROR +SSL,138,DECRYPTION_FAILED +SSL,139,DECRYPTION_FAILED_OR_BAD_RECORD_MAC +SSL,140,DH_PUBLIC_VALUE_LENGTH_IS_WRONG +SSL,141,DH_P_TOO_LONG +SSL,142,DIGEST_CHECK_FAILED +SSL,143,DTLS_MESSAGE_TOO_BIG +SSL,144,ECC_CERT_NOT_FOR_SIGNING +SSL,145,EMS_STATE_INCONSISTENT +SSL,146,ENCRYPTED_LENGTH_TOO_LONG +SSL,147,ERROR_ADDING_EXTENSION +SSL,148,ERROR_IN_RECEIVED_CIPHER_LIST +SSL,149,ERROR_PARSING_EXTENSION +SSL,150,EXCESSIVE_MESSAGE_SIZE +SSL,151,EXTRA_DATA_IN_MESSAGE +SSL,152,FRAGMENT_MISMATCH +SSL,153,GOT_NEXT_PROTO_WITHOUT_EXTENSION +SSL,154,HANDSHAKE_FAILURE_ON_CLIENT_HELLO +SSL,155,HTTPS_PROXY_REQUEST +SSL,156,HTTP_REQUEST +SSL,157,INAPPROPRIATE_FALLBACK +SSL,158,INVALID_COMMAND +SSL,159,INVALID_MESSAGE +SSL,160,INVALID_SSL_SESSION +SSL,161,INVALID_TICKET_KEYS_LENGTH +SSL,162,LENGTH_MISMATCH +SSL,163,LIBRARY_HAS_NO_CIPHERS +SSL,164,MISSING_EXTENSION +SSL,165,MISSING_RSA_CERTIFICATE +SSL,166,MISSING_TMP_DH_KEY +SSL,167,MISSING_TMP_ECDH_KEY +SSL,168,MIXED_SPECIAL_OPERATOR_WITH_GROUPS +SSL,169,MTU_TOO_SMALL +SSL,170,NEGOTIATED_BOTH_NPN_AND_ALPN +SSL,171,NESTED_GROUP +SSL,172,NO_CERTIFICATES_RETURNED +SSL,173,NO_CERTIFICATE_ASSIGNED +SSL,174,NO_CERTIFICATE_SET +SSL,175,NO_CIPHERS_AVAILABLE +SSL,176,NO_CIPHERS_PASSED +SSL,177,NO_CIPHER_MATCH +SSL,178,NO_COMPRESSION_SPECIFIED +SSL,179,NO_METHOD_SPECIFIED +SSL,180,NO_P256_SUPPORT +SSL,181,NO_PRIVATE_KEY_ASSIGNED +SSL,182,NO_RENEGOTIATION +SSL,183,NO_REQUIRED_DIGEST +SSL,184,NO_SHARED_CIPHER +SSL,185,NULL_SSL_CTX +SSL,186,NULL_SSL_METHOD_PASSED +SSL,187,OLD_SESSION_CIPHER_NOT_RETURNED +SSL,188,OLD_SESSION_VERSION_NOT_RETURNED +SSL,189,OUTPUT_ALIASES_INPUT +SSL,190,PARSE_TLSEXT +SSL,191,PATH_TOO_LONG +SSL,192,PEER_DID_NOT_RETURN_A_CERTIFICATE +SSL,193,PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE +SSL,194,PROTOCOL_IS_SHUTDOWN +SSL,195,PSK_IDENTITY_NOT_FOUND +SSL,196,PSK_NO_CLIENT_CB +SSL,197,PSK_NO_SERVER_CB +SSL,198,READ_TIMEOUT_EXPIRED +SSL,199,RECORD_LENGTH_MISMATCH +SSL,200,RECORD_TOO_LARGE +SSL,201,RENEGOTIATION_ENCODING_ERR +SSL,202,RENEGOTIATION_MISMATCH +SSL,203,REQUIRED_CIPHER_MISSING +SSL,204,RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION +SSL,205,RESUMED_NON_EMS_SESSION_WITH_EMS_EXTENSION +SSL,206,SCSV_RECEIVED_WHEN_RENEGOTIATING +SSL,207,SERVERHELLO_TLSEXT +SSL,208,SESSION_ID_CONTEXT_UNINITIALIZED +SSL,209,SESSION_MAY_NOT_BE_CREATED +SSL,250,SHUTDOWN_WHILE_IN_INIT +SSL,210,SIGNATURE_ALGORITHMS_EXTENSION_SENT_BY_SERVER +SSL,211,SRTP_COULD_NOT_ALLOCATE_PROFILES +SSL,212,SRTP_UNKNOWN_PROTECTION_PROFILE +SSL,213,SSL3_EXT_INVALID_SERVERNAME +SSL,1042,SSLV3_ALERT_BAD_CERTIFICATE +SSL,1020,SSLV3_ALERT_BAD_RECORD_MAC +SSL,1045,SSLV3_ALERT_CERTIFICATE_EXPIRED +SSL,1044,SSLV3_ALERT_CERTIFICATE_REVOKED +SSL,1046,SSLV3_ALERT_CERTIFICATE_UNKNOWN +SSL,1000,SSLV3_ALERT_CLOSE_NOTIFY +SSL,1030,SSLV3_ALERT_DECOMPRESSION_FAILURE +SSL,1040,SSLV3_ALERT_HANDSHAKE_FAILURE +SSL,1047,SSLV3_ALERT_ILLEGAL_PARAMETER +SSL,1041,SSLV3_ALERT_NO_CERTIFICATE +SSL,1010,SSLV3_ALERT_UNEXPECTED_MESSAGE +SSL,1043,SSLV3_ALERT_UNSUPPORTED_CERTIFICATE +SSL,214,SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION +SSL,215,SSL_HANDSHAKE_FAILURE +SSL,216,SSL_SESSION_ID_CONTEXT_TOO_LONG +SSL,1049,TLSV1_ALERT_ACCESS_DENIED +SSL,1050,TLSV1_ALERT_DECODE_ERROR +SSL,1021,TLSV1_ALERT_DECRYPTION_FAILED +SSL,1051,TLSV1_ALERT_DECRYPT_ERROR +SSL,1060,TLSV1_ALERT_EXPORT_RESTRICTION +SSL,1086,TLSV1_ALERT_INAPPROPRIATE_FALLBACK +SSL,1071,TLSV1_ALERT_INSUFFICIENT_SECURITY +SSL,1080,TLSV1_ALERT_INTERNAL_ERROR +SSL,1100,TLSV1_ALERT_NO_RENEGOTIATION +SSL,1070,TLSV1_ALERT_PROTOCOL_VERSION +SSL,1022,TLSV1_ALERT_RECORD_OVERFLOW +SSL,1048,TLSV1_ALERT_UNKNOWN_CA +SSL,1090,TLSV1_ALERT_USER_CANCELLED +SSL,1114,TLSV1_BAD_CERTIFICATE_HASH_VALUE +SSL,1113,TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE +SSL,1111,TLSV1_CERTIFICATE_UNOBTAINABLE +SSL,1112,TLSV1_UNRECOGNIZED_NAME +SSL,1110,TLSV1_UNSUPPORTED_EXTENSION +SSL,217,TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST +SSL,218,TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG +SSL,219,TOO_MANY_EMPTY_FRAGMENTS +SSL,220,TOO_MANY_WARNING_ALERTS +SSL,221,UNABLE_TO_FIND_ECDH_PARAMETERS +SSL,222,UNEXPECTED_EXTENSION +SSL,223,UNEXPECTED_MESSAGE +SSL,224,UNEXPECTED_OPERATOR_IN_GROUP +SSL,225,UNEXPECTED_RECORD +SSL,226,UNINITIALIZED +SSL,227,UNKNOWN_ALERT_TYPE +SSL,228,UNKNOWN_CERTIFICATE_TYPE +SSL,229,UNKNOWN_CIPHER_RETURNED +SSL,230,UNKNOWN_CIPHER_TYPE +SSL,231,UNKNOWN_DIGEST +SSL,232,UNKNOWN_KEY_EXCHANGE_TYPE +SSL,233,UNKNOWN_PROTOCOL +SSL,234,UNKNOWN_SSL_VERSION +SSL,235,UNKNOWN_STATE +SSL,236,UNSAFE_LEGACY_RENEGOTIATION_DISABLED +SSL,237,UNSUPPORTED_CIPHER +SSL,238,UNSUPPORTED_COMPRESSION_ALGORITHM +SSL,239,UNSUPPORTED_ELLIPTIC_CURVE +SSL,240,UNSUPPORTED_PROTOCOL +SSL,241,WRONG_CERTIFICATE_TYPE +SSL,242,WRONG_CIPHER_RETURNED +SSL,243,WRONG_CURVE +SSL,244,WRONG_MESSAGE_TYPE +SSL,245,WRONG_SIGNATURE_TYPE +SSL,246,WRONG_SSL_VERSION +SSL,247,WRONG_VERSION_NUMBER +SSL,248,X509_LIB +SSL,249,X509_VERIFICATION_SETUP_PROBLEMS diff --git a/external/boringssl/crypto/err/x509.errordata b/external/boringssl/crypto/err/x509.errordata new file mode 100644 index 0000000000..5687c30c9b --- /dev/null +++ b/external/boringssl/crypto/err/x509.errordata @@ -0,0 +1,36 @@ +X509,100,AKID_MISMATCH +X509,101,BAD_PKCS7_VERSION +X509,102,BAD_X509_FILETYPE +X509,103,BASE64_DECODE_ERROR +X509,104,CANT_CHECK_DH_KEY +X509,105,CERT_ALREADY_IN_HASH_TABLE +X509,106,CRL_ALREADY_DELTA +X509,107,CRL_VERIFY_FAILURE +X509,108,IDP_MISMATCH +X509,109,INVALID_BIT_STRING_BITS_LEFT +X509,110,INVALID_DIRECTORY +X509,111,INVALID_FIELD_NAME +X509,112,INVALID_PSS_PARAMETERS +X509,113,INVALID_TRUST +X509,114,ISSUER_MISMATCH +X509,115,KEY_TYPE_MISMATCH +X509,116,KEY_VALUES_MISMATCH +X509,117,LOADING_CERT_DIR +X509,118,LOADING_DEFAULTS +X509,135,NAME_TOO_LONG +X509,119,NEWER_CRL_NOT_NEWER +X509,120,NOT_PKCS7_SIGNED_DATA +X509,121,NO_CERTIFICATES_INCLUDED +X509,122,NO_CERT_SET_FOR_US_TO_VERIFY +X509,123,NO_CRLS_INCLUDED +X509,124,NO_CRL_NUMBER +X509,125,PUBLIC_KEY_DECODE_ERROR +X509,126,PUBLIC_KEY_ENCODE_ERROR +X509,127,SHOULD_RETRY +X509,128,UNKNOWN_KEY_TYPE +X509,129,UNKNOWN_NID +X509,130,UNKNOWN_PURPOSE_ID +X509,131,UNKNOWN_TRUST_ID +X509,132,UNSUPPORTED_ALGORITHM +X509,133,WRONG_LOOKUP_TYPE +X509,134,WRONG_TYPE diff --git a/external/boringssl/crypto/err/x509v3.errordata b/external/boringssl/crypto/err/x509v3.errordata new file mode 100644 index 0000000000..e53b7800a2 --- /dev/null +++ b/external/boringssl/crypto/err/x509v3.errordata @@ -0,0 +1,63 @@ +X509V3,100,BAD_IP_ADDRESS +X509V3,101,BAD_OBJECT +X509V3,102,BN_DEC2BN_ERROR +X509V3,103,BN_TO_ASN1_INTEGER_ERROR +X509V3,104,CANNOT_FIND_FREE_FUNCTION +X509V3,105,DIRNAME_ERROR +X509V3,106,DISTPOINT_ALREADY_SET +X509V3,107,DUPLICATE_ZONE_ID +X509V3,108,ERROR_CONVERTING_ZONE +X509V3,109,ERROR_CREATING_EXTENSION +X509V3,110,ERROR_IN_EXTENSION +X509V3,111,EXPECTED_A_SECTION_NAME +X509V3,112,EXTENSION_EXISTS +X509V3,113,EXTENSION_NAME_ERROR +X509V3,114,EXTENSION_NOT_FOUND +X509V3,115,EXTENSION_SETTING_NOT_SUPPORTED +X509V3,116,EXTENSION_VALUE_ERROR +X509V3,117,ILLEGAL_EMPTY_EXTENSION +X509V3,118,ILLEGAL_HEX_DIGIT +X509V3,119,INCORRECT_POLICY_SYNTAX_TAG +X509V3,120,INVALID_BOOLEAN_STRING +X509V3,121,INVALID_EXTENSION_STRING +X509V3,122,INVALID_MULTIPLE_RDNS +X509V3,123,INVALID_NAME +X509V3,124,INVALID_NULL_ARGUMENT +X509V3,125,INVALID_NULL_NAME +X509V3,126,INVALID_NULL_VALUE +X509V3,127,INVALID_NUMBER +X509V3,128,INVALID_NUMBERS +X509V3,129,INVALID_OBJECT_IDENTIFIER +X509V3,130,INVALID_OPTION +X509V3,131,INVALID_POLICY_IDENTIFIER +X509V3,132,INVALID_PROXY_POLICY_SETTING +X509V3,133,INVALID_PURPOSE +X509V3,134,INVALID_SECTION +X509V3,135,INVALID_SYNTAX +X509V3,136,ISSUER_DECODE_ERROR +X509V3,137,MISSING_VALUE +X509V3,138,NEED_ORGANIZATION_AND_NUMBERS +X509V3,139,NO_CONFIG_DATABASE +X509V3,140,NO_ISSUER_CERTIFICATE +X509V3,141,NO_ISSUER_DETAILS +X509V3,142,NO_POLICY_IDENTIFIER +X509V3,143,NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED +X509V3,144,NO_PUBLIC_KEY +X509V3,145,NO_SUBJECT_DETAILS +X509V3,146,ODD_NUMBER_OF_DIGITS +X509V3,147,OPERATION_NOT_DEFINED +X509V3,148,OTHERNAME_ERROR +X509V3,149,POLICY_LANGUAGE_ALREADY_DEFINED +X509V3,150,POLICY_PATH_LENGTH +X509V3,151,POLICY_PATH_LENGTH_ALREADY_DEFINED +X509V3,152,POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY +X509V3,153,SECTION_NOT_FOUND +X509V3,154,UNABLE_TO_GET_ISSUER_DETAILS +X509V3,155,UNABLE_TO_GET_ISSUER_KEYID +X509V3,156,UNKNOWN_BIT_STRING_ARGUMENT +X509V3,157,UNKNOWN_EXTENSION +X509V3,158,UNKNOWN_EXTENSION_NAME +X509V3,159,UNKNOWN_OPTION +X509V3,160,UNSUPPORTED_OPTION +X509V3,161,UNSUPPORTED_TYPE +X509V3,162,USER_TOO_LONG diff --git a/external/boringssl/crypto/evp/CMakeLists.txt b/external/boringssl/crypto/evp/CMakeLists.txt new file mode 100644 index 0000000000..1174be6381 --- /dev/null +++ b/external/boringssl/crypto/evp/CMakeLists.txt @@ -0,0 +1,52 @@ +include_directories(../../include) + +add_library( + evp + + OBJECT + + digestsign.c + evp.c + evp_asn1.c + evp_ctx.c + p_dsa_asn1.c + p_ec.c + p_ec_asn1.c + p_rsa.c + p_rsa_asn1.c + pbkdf.c + print.c + sign.c +) + + +if(ENABLE_TESTS) +add_executable( + evp_extra_test + + evp_extra_test.cc + + $ +) + +add_executable( + evp_test + + evp_test.cc + + $ +) + +add_executable( + pbkdf_test + + pbkdf_test.cc + + $ +) + +target_link_libraries(evp_extra_test crypto) +target_link_libraries(evp_test crypto) +target_link_libraries(pbkdf_test crypto) +add_dependencies(all_tests evp_extra_test evp_test pbkdf_test) +endif() diff --git a/external/boringssl/crypto/evp/digestsign.c b/external/boringssl/crypto/evp/digestsign.c new file mode 100644 index 0000000000..69c483ad78 --- /dev/null +++ b/external/boringssl/crypto/evp/digestsign.c @@ -0,0 +1,159 @@ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 2006. + */ +/* ==================================================================== + * Copyright (c) 2006,2007 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include + +#include "internal.h" +#include "../digest/internal.h" + + +static const struct evp_md_pctx_ops md_pctx_ops = { + EVP_PKEY_CTX_free, + EVP_PKEY_CTX_dup, +}; + +static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, + const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey, + int is_verify) { + if (ctx->pctx == NULL) { + ctx->pctx = EVP_PKEY_CTX_new(pkey, e); + } + if (ctx->pctx == NULL) { + return 0; + } + ctx->pctx_ops = &md_pctx_ops; + + if (type == NULL) { + OPENSSL_PUT_ERROR(EVP, EVP_R_NO_DEFAULT_DIGEST); + return 0; + } + + if (is_verify) { + if (!EVP_PKEY_verify_init(ctx->pctx)) { + return 0; + } + } else { + if (!EVP_PKEY_sign_init(ctx->pctx)) { + return 0; + } + } + if (!EVP_PKEY_CTX_set_signature_md(ctx->pctx, type)) { + return 0; + } + if (pctx) { + *pctx = ctx->pctx; + } + if (!EVP_DigestInit_ex(ctx, type, e)) { + return 0; + } + return 1; +} + +int EVP_DigestSignInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, const EVP_MD *type, + ENGINE *e, EVP_PKEY *pkey) { + return do_sigver_init(ctx, pctx, type, e, pkey, 0); +} + +int EVP_DigestVerifyInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, + const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey) { + return do_sigver_init(ctx, pctx, type, e, pkey, 1); +} + +int EVP_DigestSignUpdate(EVP_MD_CTX *ctx, const void *data, size_t len) { + return EVP_DigestUpdate(ctx, data, len); +} + +int EVP_DigestVerifyUpdate(EVP_MD_CTX *ctx, const void *data, size_t len) { + return EVP_DigestUpdate(ctx, data, len); +} + +int EVP_DigestSignFinal(EVP_MD_CTX *ctx, uint8_t *out_sig, + size_t *out_sig_len) { + if (out_sig) { + EVP_MD_CTX tmp_ctx; + int ret; + uint8_t md[EVP_MAX_MD_SIZE]; + unsigned int mdlen; + + EVP_MD_CTX_init(&tmp_ctx); + ret = EVP_MD_CTX_copy_ex(&tmp_ctx, ctx) && + EVP_DigestFinal_ex(&tmp_ctx, md, &mdlen) && + EVP_PKEY_sign(ctx->pctx, out_sig, out_sig_len, md, mdlen); + EVP_MD_CTX_cleanup(&tmp_ctx); + + return ret; + } else { + size_t s = EVP_MD_size(ctx->digest); + return EVP_PKEY_sign(ctx->pctx, out_sig, out_sig_len, NULL, s); + } +} + +int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const uint8_t *sig, + size_t sig_len) { + EVP_MD_CTX tmp_ctx; + int ret; + uint8_t md[EVP_MAX_MD_SIZE]; + unsigned int mdlen; + + EVP_MD_CTX_init(&tmp_ctx); + ret = EVP_MD_CTX_copy_ex(&tmp_ctx, ctx) && + EVP_DigestFinal_ex(&tmp_ctx, md, &mdlen) && + EVP_PKEY_verify(ctx->pctx, sig, sig_len, md, mdlen); + EVP_MD_CTX_cleanup(&tmp_ctx); + + return ret; +} diff --git a/external/boringssl/crypto/evp/evp.c b/external/boringssl/crypto/evp/evp.c new file mode 100644 index 0000000000..ee207f9b86 --- /dev/null +++ b/external/boringssl/crypto/evp/evp.c @@ -0,0 +1,365 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "internal.h" +#include "../internal.h" + + +EVP_PKEY *EVP_PKEY_new(void) { + EVP_PKEY *ret; + + ret = OPENSSL_malloc(sizeof(EVP_PKEY)); + if (ret == NULL) { + OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE); + return NULL; + } + + memset(ret, 0, sizeof(EVP_PKEY)); + ret->type = EVP_PKEY_NONE; + ret->references = 1; + + return ret; +} + +static void free_it(EVP_PKEY *pkey) { + if (pkey->ameth && pkey->ameth->pkey_free) { + pkey->ameth->pkey_free(pkey); + pkey->pkey.ptr = NULL; + pkey->type = EVP_PKEY_NONE; + } +} + +void EVP_PKEY_free(EVP_PKEY *pkey) { + if (pkey == NULL) { + return; + } + + if (!CRYPTO_refcount_dec_and_test_zero(&pkey->references)) { + return; + } + + free_it(pkey); + OPENSSL_free(pkey); +} + +EVP_PKEY *EVP_PKEY_up_ref(EVP_PKEY *pkey) { + CRYPTO_refcount_inc(&pkey->references); + return pkey; +} + +int EVP_PKEY_is_opaque(const EVP_PKEY *pkey) { + if (pkey->ameth && pkey->ameth->pkey_opaque) { + return pkey->ameth->pkey_opaque(pkey); + } + return 0; +} + +int EVP_PKEY_supports_digest(const EVP_PKEY *pkey, const EVP_MD *md) { + if (pkey->ameth && pkey->ameth->pkey_supports_digest) { + return pkey->ameth->pkey_supports_digest(pkey, md); + } + return 1; +} + +int EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b) { + if (a->type != b->type) { + return -1; + } + + if (a->ameth) { + int ret; + /* Compare parameters if the algorithm has them */ + if (a->ameth->param_cmp) { + ret = a->ameth->param_cmp(a, b); + if (ret <= 0) { + return ret; + } + } + + if (a->ameth->pub_cmp) { + return a->ameth->pub_cmp(a, b); + } + } + + return -2; +} + +int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) { + if (to->type != from->type) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DIFFERENT_KEY_TYPES); + goto err; + } + + if (EVP_PKEY_missing_parameters(from)) { + OPENSSL_PUT_ERROR(EVP, EVP_R_MISSING_PARAMETERS); + goto err; + } + + if (from->ameth && from->ameth->param_copy) { + return from->ameth->param_copy(to, from); + } + +err: + return 0; +} + +int EVP_PKEY_missing_parameters(const EVP_PKEY *pkey) { + if (pkey->ameth && pkey->ameth->param_missing) { + return pkey->ameth->param_missing(pkey); + } + return 0; +} + +int EVP_PKEY_size(const EVP_PKEY *pkey) { + if (pkey && pkey->ameth && pkey->ameth->pkey_size) { + return pkey->ameth->pkey_size(pkey); + } + return 0; +} + +int EVP_PKEY_bits(EVP_PKEY *pkey) { + if (pkey && pkey->ameth && pkey->ameth->pkey_bits) { + return pkey->ameth->pkey_bits(pkey); + } + return 0; +} + +int EVP_PKEY_id(const EVP_PKEY *pkey) { + return pkey->type; +} + +/* evp_pkey_asn1_find returns the ASN.1 method table for the given |nid|, which + * should be one of the |EVP_PKEY_*| values. It returns NULL if |nid| is + * unknown. */ +static const EVP_PKEY_ASN1_METHOD *evp_pkey_asn1_find(int nid) { + switch (nid) { + case EVP_PKEY_RSA: + return &rsa_asn1_meth; + case EVP_PKEY_EC: + return &ec_asn1_meth; + case EVP_PKEY_DSA: + return &dsa_asn1_meth; + default: + return NULL; + } +} + +int EVP_PKEY_type(int nid) { + const EVP_PKEY_ASN1_METHOD *meth = evp_pkey_asn1_find(nid); + if (meth == NULL) { + return NID_undef; + } + return meth->pkey_id; +} + +int EVP_PKEY_set1_RSA(EVP_PKEY *pkey, RSA *key) { + if (EVP_PKEY_assign_RSA(pkey, key)) { + RSA_up_ref(key); + return 1; + } + return 0; +} + +int EVP_PKEY_assign_RSA(EVP_PKEY *pkey, RSA *key) { + return EVP_PKEY_assign(pkey, EVP_PKEY_RSA, key); +} + +RSA *EVP_PKEY_get0_RSA(EVP_PKEY *pkey) { + if (pkey->type != EVP_PKEY_RSA) { + OPENSSL_PUT_ERROR(EVP, EVP_R_EXPECTING_AN_RSA_KEY); + return NULL; + } + return pkey->pkey.rsa; +} + +RSA *EVP_PKEY_get1_RSA(EVP_PKEY *pkey) { + RSA *rsa = EVP_PKEY_get0_RSA(pkey); + if (rsa != NULL) { + RSA_up_ref(rsa); + } + return rsa; +} + +int EVP_PKEY_set1_DSA(EVP_PKEY *pkey, DSA *key) { + if (EVP_PKEY_assign_DSA(pkey, key)) { + DSA_up_ref(key); + return 1; + } + return 0; +} + +int EVP_PKEY_assign_DSA(EVP_PKEY *pkey, DSA *key) { + return EVP_PKEY_assign(pkey, EVP_PKEY_DSA, key); +} + +DSA *EVP_PKEY_get0_DSA(EVP_PKEY *pkey) { + if (pkey->type != EVP_PKEY_DSA) { + OPENSSL_PUT_ERROR(EVP, EVP_R_EXPECTING_A_DSA_KEY); + return NULL; + } + return pkey->pkey.dsa; +} + +DSA *EVP_PKEY_get1_DSA(EVP_PKEY *pkey) { + DSA *dsa = EVP_PKEY_get0_DSA(pkey); + if (dsa != NULL) { + DSA_up_ref(dsa); + } + return dsa; +} + +int EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey, EC_KEY *key) { + if (EVP_PKEY_assign_EC_KEY(pkey, key)) { + EC_KEY_up_ref(key); + return 1; + } + return 0; +} + +int EVP_PKEY_assign_EC_KEY(EVP_PKEY *pkey, EC_KEY *key) { + return EVP_PKEY_assign(pkey, EVP_PKEY_EC, key); +} + +EC_KEY *EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey) { + if (pkey->type != EVP_PKEY_EC) { + OPENSSL_PUT_ERROR(EVP, EVP_R_EXPECTING_AN_EC_KEY_KEY); + return NULL; + } + return pkey->pkey.ec; +} + +EC_KEY *EVP_PKEY_get1_EC_KEY(EVP_PKEY *pkey) { + EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(pkey); + if (ec_key != NULL) { + EC_KEY_up_ref(ec_key); + } + return ec_key; +} + +int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key) { + if (!EVP_PKEY_set_type(pkey, type)) { + return 0; + } + pkey->pkey.ptr = key; + return key != NULL; +} + +int EVP_PKEY_set_type(EVP_PKEY *pkey, int type) { + const EVP_PKEY_ASN1_METHOD *ameth; + + if (pkey && pkey->pkey.ptr) { + free_it(pkey); + } + + ameth = evp_pkey_asn1_find(type); + if (ameth == NULL) { + OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM); + ERR_add_error_dataf("algorithm %d", type); + return 0; + } + + if (pkey) { + pkey->ameth = ameth; + pkey->type = pkey->ameth->pkey_id; + } + + return 1; +} + + + +int EVP_PKEY_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b) { + if (a->type != b->type) { + return -1; + } + if (a->ameth && a->ameth->param_cmp) { + return a->ameth->param_cmp(a, b); + } + return -2; +} + +int EVP_PKEY_CTX_set_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD *md) { + return EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_TYPE_SIG, EVP_PKEY_CTRL_MD, 0, + (void *)md); +} + +int EVP_PKEY_CTX_get_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD **out_md) { + return EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_TYPE_SIG, EVP_PKEY_CTRL_GET_MD, + 0, (void *)out_md); +} + +void OpenSSL_add_all_algorithms(void) {} + +void OPENSSL_add_all_algorithms_conf(void) {} + +void OpenSSL_add_all_ciphers(void) {} + +void OpenSSL_add_all_digests(void) {} + +void EVP_cleanup(void) {} diff --git a/external/boringssl/crypto/evp/evp_asn1.c b/external/boringssl/crypto/evp/evp_asn1.c new file mode 100644 index 0000000000..3681d4fcd6 --- /dev/null +++ b/external/boringssl/crypto/evp/evp_asn1.c @@ -0,0 +1,336 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include +#include +#include +#include +#include + +#include "internal.h" + + +static const EVP_PKEY_ASN1_METHOD *const kASN1Methods[] = { + &rsa_asn1_meth, + &ec_asn1_meth, + &dsa_asn1_meth, +}; + +static int parse_key_type(CBS *cbs, int *out_type) { + CBS oid; + if (!CBS_get_asn1(cbs, &oid, CBS_ASN1_OBJECT)) { + return 0; + } + + unsigned i; + for (i = 0; i < sizeof(kASN1Methods)/sizeof(kASN1Methods[0]); i++) { + const EVP_PKEY_ASN1_METHOD *method = kASN1Methods[i]; + if (CBS_len(&oid) == method->oid_len && + memcmp(CBS_data(&oid), method->oid, method->oid_len) == 0) { + *out_type = method->pkey_id; + return 1; + } + } + + return 0; +} + +EVP_PKEY *EVP_parse_public_key(CBS *cbs) { + /* Parse the SubjectPublicKeyInfo. */ + CBS spki, algorithm, key; + int type; + uint8_t padding; + if (!CBS_get_asn1(cbs, &spki, CBS_ASN1_SEQUENCE) || + !CBS_get_asn1(&spki, &algorithm, CBS_ASN1_SEQUENCE) || + !parse_key_type(&algorithm, &type) || + !CBS_get_asn1(&spki, &key, CBS_ASN1_BITSTRING) || + CBS_len(&spki) != 0 || + /* Every key type defined encodes the key as a byte string with the same + * conversion to BIT STRING. */ + !CBS_get_u8(&key, &padding) || + padding != 0) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + return NULL; + } + + /* Set up an |EVP_PKEY| of the appropriate type. */ + EVP_PKEY *ret = EVP_PKEY_new(); + if (ret == NULL || + !EVP_PKEY_set_type(ret, type)) { + goto err; + } + + /* Call into the type-specific SPKI decoding function. */ + if (ret->ameth->pub_decode == NULL) { + OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM); + goto err; + } + if (!ret->ameth->pub_decode(ret, &algorithm, &key)) { + goto err; + } + + return ret; + +err: + EVP_PKEY_free(ret); + return NULL; +} + +int EVP_marshal_public_key(CBB *cbb, const EVP_PKEY *key) { + if (key->ameth == NULL || key->ameth->pub_encode == NULL) { + OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM); + return 0; + } + + return key->ameth->pub_encode(cbb, key); +} + +EVP_PKEY *EVP_parse_private_key(CBS *cbs) { + /* Parse the PrivateKeyInfo. */ + CBS pkcs8, algorithm, key; + uint64_t version; + int type; + if (!CBS_get_asn1(cbs, &pkcs8, CBS_ASN1_SEQUENCE) || + !CBS_get_asn1_uint64(&pkcs8, &version) || + version != 0 || + !CBS_get_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) || + !parse_key_type(&algorithm, &type) || + !CBS_get_asn1(&pkcs8, &key, CBS_ASN1_OCTETSTRING)) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + return NULL; + } + + /* A PrivateKeyInfo ends with a SET of Attributes which we ignore. */ + + /* Set up an |EVP_PKEY| of the appropriate type. */ + EVP_PKEY *ret = EVP_PKEY_new(); + if (ret == NULL || + !EVP_PKEY_set_type(ret, type)) { + goto err; + } + + /* Call into the type-specific PrivateKeyInfo decoding function. */ + if (ret->ameth->priv_decode == NULL) { + OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM); + goto err; + } + if (!ret->ameth->priv_decode(ret, &algorithm, &key)) { + goto err; + } + + return ret; + +err: + EVP_PKEY_free(ret); + return NULL; +} + +int EVP_marshal_private_key(CBB *cbb, const EVP_PKEY *key) { + if (key->ameth == NULL || key->ameth->priv_encode == NULL) { + OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM); + return 0; + } + + return key->ameth->priv_encode(cbb, key); +} + +static EVP_PKEY *old_priv_decode(CBS *cbs, int type) { + EVP_PKEY *ret = EVP_PKEY_new(); + if (ret == NULL) { + return NULL; + } + + switch (type) { + case EVP_PKEY_EC: { + EC_KEY *ec_key = EC_KEY_parse_private_key(cbs, NULL); + if (ec_key == NULL || !EVP_PKEY_assign_EC_KEY(ret, ec_key)) { + EC_KEY_free(ec_key); + goto err; + } + return ret; + } + case EVP_PKEY_DSA: { + DSA *dsa = DSA_parse_private_key(cbs); + if (dsa == NULL || !EVP_PKEY_assign_DSA(ret, dsa)) { + DSA_free(dsa); + goto err; + } + return ret; + } + case EVP_PKEY_RSA: { + RSA *rsa = RSA_parse_private_key(cbs); + if (rsa == NULL || !EVP_PKEY_assign_RSA(ret, rsa)) { + RSA_free(rsa); + goto err; + } + return ret; + } + default: + OPENSSL_PUT_ERROR(EVP, EVP_R_UNKNOWN_PUBLIC_KEY_TYPE); + goto err; + } + +err: + EVP_PKEY_free(ret); + return NULL; +} + +EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **out, const uint8_t **inp, + long len) { + if (len < 0) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + return NULL; + } + + /* Parse with the legacy format. */ + CBS cbs; + CBS_init(&cbs, *inp, (size_t)len); + EVP_PKEY *ret = old_priv_decode(&cbs, type); + if (ret == NULL) { + /* Try again with PKCS#8. */ + ERR_clear_error(); + CBS_init(&cbs, *inp, (size_t)len); + ret = EVP_parse_private_key(&cbs); + if (ret == NULL) { + return NULL; + } + if (ret->type != type) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DIFFERENT_KEY_TYPES); + EVP_PKEY_free(ret); + return NULL; + } + } + + if (out != NULL) { + EVP_PKEY_free(*out); + *out = ret; + } + *inp = CBS_data(&cbs); + return ret; +} + +/* num_elements parses one SEQUENCE from |in| and returns the number of elements + * in it. On parse error, it returns zero. */ +static size_t num_elements(const uint8_t *in, size_t in_len) { + CBS cbs, sequence; + CBS_init(&cbs, in, (size_t)in_len); + + if (!CBS_get_asn1(&cbs, &sequence, CBS_ASN1_SEQUENCE)) { + return 0; + } + + size_t count = 0; + while (CBS_len(&sequence) > 0) { + if (!CBS_get_any_asn1_element(&sequence, NULL, NULL, NULL)) { + return 0; + } + + count++; + } + + return count; +} + +EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **out, const uint8_t **inp, long len) { + if (len < 0) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + return NULL; + } + + /* Parse the input as a PKCS#8 PrivateKeyInfo. */ + CBS cbs; + CBS_init(&cbs, *inp, (size_t)len); + EVP_PKEY *ret = EVP_parse_private_key(&cbs); + if (ret != NULL) { + if (out != NULL) { + EVP_PKEY_free(*out); + *out = ret; + } + *inp = CBS_data(&cbs); + return ret; + } + ERR_clear_error(); + + /* Count the elements to determine the legacy key format. */ + switch (num_elements(*inp, (size_t)len)) { + case 4: + return d2i_PrivateKey(EVP_PKEY_EC, out, inp, len); + + case 6: + return d2i_PrivateKey(EVP_PKEY_DSA, out, inp, len); + + default: + return d2i_PrivateKey(EVP_PKEY_RSA, out, inp, len); + } +} + +int i2d_PublicKey(EVP_PKEY *key, uint8_t **outp) { + switch (key->type) { + case EVP_PKEY_RSA: + return i2d_RSAPublicKey(key->pkey.rsa, outp); + case EVP_PKEY_DSA: + return i2d_DSAPublicKey(key->pkey.dsa, outp); + case EVP_PKEY_EC: + return i2o_ECPublicKey(key->pkey.ec, outp); + default: + OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_PUBLIC_KEY_TYPE); + return -1; + } +} diff --git a/external/boringssl/crypto/evp/evp_ctx.c b/external/boringssl/crypto/evp/evp_ctx.c new file mode 100644 index 0000000000..f510f6c7d8 --- /dev/null +++ b/external/boringssl/crypto/evp/evp_ctx.c @@ -0,0 +1,445 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include +#include + +#include "internal.h" + + +static const EVP_PKEY_METHOD *const evp_methods[] = { + &rsa_pkey_meth, + &ec_pkey_meth, +}; + +static const EVP_PKEY_METHOD *evp_pkey_meth_find(int type) { + unsigned i; + + for (i = 0; i < sizeof(evp_methods)/sizeof(EVP_PKEY_METHOD*); i++) { + if (evp_methods[i]->pkey_id == type) { + return evp_methods[i]; + } + } + + return NULL; +} + +static EVP_PKEY_CTX *evp_pkey_ctx_new(EVP_PKEY *pkey, ENGINE *e, int id) { + EVP_PKEY_CTX *ret; + const EVP_PKEY_METHOD *pmeth; + + if (id == -1) { + if (!pkey || !pkey->ameth) { + return NULL; + } + id = pkey->ameth->pkey_id; + } + + pmeth = evp_pkey_meth_find(id); + + if (pmeth == NULL) { + OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM); + ERR_add_error_dataf("algorithm %d", id); + return NULL; + } + + ret = OPENSSL_malloc(sizeof(EVP_PKEY_CTX)); + if (!ret) { + OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE); + return NULL; + } + memset(ret, 0, sizeof(EVP_PKEY_CTX)); + + ret->engine = e; + ret->pmeth = pmeth; + ret->operation = EVP_PKEY_OP_UNDEFINED; + + if (pkey) { + ret->pkey = EVP_PKEY_up_ref(pkey); + } + + if (pmeth->init) { + if (pmeth->init(ret) <= 0) { + EVP_PKEY_free(ret->pkey); + OPENSSL_free(ret); + return NULL; + } + } + + return ret; +} + +EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *e) { + return evp_pkey_ctx_new(pkey, e, -1); +} + +EVP_PKEY_CTX *EVP_PKEY_CTX_new_id(int id, ENGINE *e) { + return evp_pkey_ctx_new(NULL, e, id); +} + +void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx) { + if (ctx == NULL) { + return; + } + if (ctx->pmeth && ctx->pmeth->cleanup) { + ctx->pmeth->cleanup(ctx); + } + EVP_PKEY_free(ctx->pkey); + EVP_PKEY_free(ctx->peerkey); + OPENSSL_free(ctx); +} + +EVP_PKEY_CTX *EVP_PKEY_CTX_dup(EVP_PKEY_CTX *pctx) { + EVP_PKEY_CTX *rctx; + + if (!pctx->pmeth || !pctx->pmeth->copy) { + return NULL; + } + + rctx = OPENSSL_malloc(sizeof(EVP_PKEY_CTX)); + if (!rctx) { + return NULL; + } + + memset(rctx, 0, sizeof(EVP_PKEY_CTX)); + + rctx->pmeth = pctx->pmeth; + rctx->engine = pctx->engine; + rctx->operation = pctx->operation; + + if (pctx->pkey) { + rctx->pkey = EVP_PKEY_up_ref(pctx->pkey); + if (rctx->pkey == NULL) { + goto err; + } + } + + if (pctx->peerkey) { + rctx->peerkey = EVP_PKEY_up_ref(pctx->peerkey); + if (rctx->peerkey == NULL) { + goto err; + } + } + + if (pctx->pmeth->copy(rctx, pctx) > 0) { + return rctx; + } + +err: + EVP_PKEY_CTX_free(rctx); + OPENSSL_PUT_ERROR(EVP, ERR_LIB_EVP); + return NULL; +} + +EVP_PKEY *EVP_PKEY_CTX_get0_pkey(EVP_PKEY_CTX *ctx) { return ctx->pkey; } + +int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype, int cmd, + int p1, void *p2) { + if (!ctx || !ctx->pmeth || !ctx->pmeth->ctrl) { + OPENSSL_PUT_ERROR(EVP, EVP_R_COMMAND_NOT_SUPPORTED); + return 0; + } + if (keytype != -1 && ctx->pmeth->pkey_id != keytype) { + return 0; + } + + if (ctx->operation == EVP_PKEY_OP_UNDEFINED) { + OPENSSL_PUT_ERROR(EVP, EVP_R_NO_OPERATION_SET); + return 0; + } + + if (optype != -1 && !(ctx->operation & optype)) { + OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_OPERATION); + return 0; + } + + return ctx->pmeth->ctrl(ctx, cmd, p1, p2); +} + +int EVP_PKEY_sign_init(EVP_PKEY_CTX *ctx) { + if (!ctx || !ctx->pmeth || !ctx->pmeth->sign) { + OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return 0; + } + + ctx->operation = EVP_PKEY_OP_SIGN; + return 1; +} + +int EVP_PKEY_sign(EVP_PKEY_CTX *ctx, uint8_t *sig, size_t *sig_len, + const uint8_t *data, size_t data_len) { + if (!ctx || !ctx->pmeth || !ctx->pmeth->sign) { + OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return 0; + } + if (ctx->operation != EVP_PKEY_OP_SIGN) { + OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATON_NOT_INITIALIZED); + return 0; + } + return ctx->pmeth->sign(ctx, sig, sig_len, data, data_len); +} + +int EVP_PKEY_verify_init(EVP_PKEY_CTX *ctx) { + if (!ctx || !ctx->pmeth || !ctx->pmeth->verify) { + OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return 0; + } + ctx->operation = EVP_PKEY_OP_VERIFY; + return 1; +} + +int EVP_PKEY_verify(EVP_PKEY_CTX *ctx, const uint8_t *sig, size_t sig_len, + const uint8_t *data, size_t data_len) { + if (!ctx || !ctx->pmeth || !ctx->pmeth->verify) { + OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return 0; + } + if (ctx->operation != EVP_PKEY_OP_VERIFY) { + OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATON_NOT_INITIALIZED); + return 0; + } + return ctx->pmeth->verify(ctx, sig, sig_len, data, data_len); +} + +int EVP_PKEY_encrypt_init(EVP_PKEY_CTX *ctx) { + if (!ctx || !ctx->pmeth || !ctx->pmeth->encrypt) { + OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return 0; + } + ctx->operation = EVP_PKEY_OP_ENCRYPT; + return 1; +} + +int EVP_PKEY_encrypt(EVP_PKEY_CTX *ctx, uint8_t *out, size_t *outlen, + const uint8_t *in, size_t inlen) { + if (!ctx || !ctx->pmeth || !ctx->pmeth->encrypt) { + OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return 0; + } + if (ctx->operation != EVP_PKEY_OP_ENCRYPT) { + OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATON_NOT_INITIALIZED); + return 0; + } + return ctx->pmeth->encrypt(ctx, out, outlen, in, inlen); +} + +int EVP_PKEY_decrypt_init(EVP_PKEY_CTX *ctx) { + if (!ctx || !ctx->pmeth || !ctx->pmeth->decrypt) { + OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return 0; + } + ctx->operation = EVP_PKEY_OP_DECRYPT; + return 1; +} + +int EVP_PKEY_decrypt(EVP_PKEY_CTX *ctx, uint8_t *out, size_t *outlen, + const uint8_t *in, size_t inlen) { + if (!ctx || !ctx->pmeth || !ctx->pmeth->decrypt) { + OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return 0; + } + if (ctx->operation != EVP_PKEY_OP_DECRYPT) { + OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATON_NOT_INITIALIZED); + return 0; + } + return ctx->pmeth->decrypt(ctx, out, outlen, in, inlen); +} + +int EVP_PKEY_verify_recover_init(EVP_PKEY_CTX *ctx) { + if (!ctx || !ctx->pmeth || !ctx->pmeth->verify_recover) { + OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return 0; + } + ctx->operation = EVP_PKEY_OP_VERIFYRECOVER; + return 1; +} + +int EVP_PKEY_verify_recover(EVP_PKEY_CTX *ctx, uint8_t *out, size_t *out_len, + const uint8_t *sig, size_t sig_len) { + if (!ctx || !ctx->pmeth || !ctx->pmeth->verify_recover) { + OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return 0; + } + if (ctx->operation != EVP_PKEY_OP_VERIFYRECOVER) { + OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATON_NOT_INITIALIZED); + return 0; + } + return ctx->pmeth->verify_recover(ctx, out, out_len, sig, sig_len); +} + +int EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx) { + if (!ctx || !ctx->pmeth || !ctx->pmeth->derive) { + OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return 0; + } + ctx->operation = EVP_PKEY_OP_DERIVE; + return 1; +} + +int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer) { + int ret; + if (!ctx || !ctx->pmeth || + !(ctx->pmeth->derive || ctx->pmeth->encrypt || ctx->pmeth->decrypt) || + !ctx->pmeth->ctrl) { + OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return 0; + } + if (ctx->operation != EVP_PKEY_OP_DERIVE && + ctx->operation != EVP_PKEY_OP_ENCRYPT && + ctx->operation != EVP_PKEY_OP_DECRYPT) { + OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATON_NOT_INITIALIZED); + return 0; + } + + ret = ctx->pmeth->ctrl(ctx, EVP_PKEY_CTRL_PEER_KEY, 0, peer); + + if (ret <= 0) { + return 0; + } + + if (ret == 2) { + return 1; + } + + if (!ctx->pkey) { + OPENSSL_PUT_ERROR(EVP, EVP_R_NO_KEY_SET); + return 0; + } + + if (ctx->pkey->type != peer->type) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DIFFERENT_KEY_TYPES); + return 0; + } + + /* ran@cryptocom.ru: For clarity. The error is if parameters in peer are + * present (!missing) but don't match. EVP_PKEY_cmp_parameters may return + * 1 (match), 0 (don't match) and -2 (comparison is not defined). -1 + * (different key types) is impossible here because it is checked earlier. + * -2 is OK for us here, as well as 1, so we can check for 0 only. */ + if (!EVP_PKEY_missing_parameters(peer) && + !EVP_PKEY_cmp_parameters(ctx->pkey, peer)) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DIFFERENT_PARAMETERS); + return 0; + } + + EVP_PKEY_free(ctx->peerkey); + ctx->peerkey = peer; + + ret = ctx->pmeth->ctrl(ctx, EVP_PKEY_CTRL_PEER_KEY, 1, peer); + + if (ret <= 0) { + ctx->peerkey = NULL; + return 0; + } + + EVP_PKEY_up_ref(peer); + return 1; +} + +int EVP_PKEY_derive(EVP_PKEY_CTX *ctx, uint8_t *key, size_t *out_key_len) { + if (!ctx || !ctx->pmeth || !ctx->pmeth->derive) { + OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return 0; + } + if (ctx->operation != EVP_PKEY_OP_DERIVE) { + OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATON_NOT_INITIALIZED); + return 0; + } + return ctx->pmeth->derive(ctx, key, out_key_len); +} + +int EVP_PKEY_keygen_init(EVP_PKEY_CTX *ctx) { + if (!ctx || !ctx->pmeth || !ctx->pmeth->keygen) { + OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return 0; + } + ctx->operation = EVP_PKEY_OP_KEYGEN; + return 1; +} + +int EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey) { + if (!ctx || !ctx->pmeth || !ctx->pmeth->keygen) { + OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return 0; + } + if (ctx->operation != EVP_PKEY_OP_KEYGEN) { + OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATON_NOT_INITIALIZED); + return 0; + } + + if (!ppkey) { + return 0; + } + + if (!*ppkey) { + *ppkey = EVP_PKEY_new(); + if (!*ppkey) { + OPENSSL_PUT_ERROR(EVP, ERR_LIB_EVP); + return 0; + } + } + + if (!ctx->pmeth->keygen(ctx, *ppkey)) { + EVP_PKEY_free(*ppkey); + *ppkey = NULL; + return 0; + } + return 1; +} diff --git a/external/boringssl/crypto/evp/evp_extra_test.cc b/external/boringssl/crypto/evp/evp_extra_test.cc new file mode 100644 index 0000000000..9bc36ad886 --- /dev/null +++ b/external/boringssl/crypto/evp/evp_extra_test.cc @@ -0,0 +1,721 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "../test/scoped_types.h" + + +// kExampleRSAKeyDER is an RSA private key in ASN.1, DER format. Of course, you +// should never use this key anywhere but in an example. +static const uint8_t kExampleRSAKeyDER[] = { + 0x30, 0x82, 0x02, 0x5c, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81, 0x00, 0xf8, + 0xb8, 0x6c, 0x83, 0xb4, 0xbc, 0xd9, 0xa8, 0x57, 0xc0, 0xa5, 0xb4, 0x59, + 0x76, 0x8c, 0x54, 0x1d, 0x79, 0xeb, 0x22, 0x52, 0x04, 0x7e, 0xd3, 0x37, + 0xeb, 0x41, 0xfd, 0x83, 0xf9, 0xf0, 0xa6, 0x85, 0x15, 0x34, 0x75, 0x71, + 0x5a, 0x84, 0xa8, 0x3c, 0xd2, 0xef, 0x5a, 0x4e, 0xd3, 0xde, 0x97, 0x8a, + 0xdd, 0xff, 0xbb, 0xcf, 0x0a, 0xaa, 0x86, 0x92, 0xbe, 0xb8, 0x50, 0xe4, + 0xcd, 0x6f, 0x80, 0x33, 0x30, 0x76, 0x13, 0x8f, 0xca, 0x7b, 0xdc, 0xec, + 0x5a, 0xca, 0x63, 0xc7, 0x03, 0x25, 0xef, 0xa8, 0x8a, 0x83, 0x58, 0x76, + 0x20, 0xfa, 0x16, 0x77, 0xd7, 0x79, 0x92, 0x63, 0x01, 0x48, 0x1a, 0xd8, + 0x7b, 0x67, 0xf1, 0x52, 0x55, 0x49, 0x4e, 0xd6, 0x6e, 0x4a, 0x5c, 0xd7, + 0x7a, 0x37, 0x36, 0x0c, 0xde, 0xdd, 0x8f, 0x44, 0xe8, 0xc2, 0xa7, 0x2c, + 0x2b, 0xb5, 0xaf, 0x64, 0x4b, 0x61, 0x07, 0x02, 0x03, 0x01, 0x00, 0x01, + 0x02, 0x81, 0x80, 0x74, 0x88, 0x64, 0x3f, 0x69, 0x45, 0x3a, 0x6d, 0xc7, + 0x7f, 0xb9, 0xa3, 0xc0, 0x6e, 0xec, 0xdc, 0xd4, 0x5a, 0xb5, 0x32, 0x85, + 0x5f, 0x19, 0xd4, 0xf8, 0xd4, 0x3f, 0x3c, 0xfa, 0xc2, 0xf6, 0x5f, 0xee, + 0xe6, 0xba, 0x87, 0x74, 0x2e, 0xc7, 0x0c, 0xd4, 0x42, 0xb8, 0x66, 0x85, + 0x9c, 0x7b, 0x24, 0x61, 0xaa, 0x16, 0x11, 0xf6, 0xb5, 0xb6, 0xa4, 0x0a, + 0xc9, 0x55, 0x2e, 0x81, 0xa5, 0x47, 0x61, 0xcb, 0x25, 0x8f, 0xc2, 0x15, + 0x7b, 0x0e, 0x7c, 0x36, 0x9f, 0x3a, 0xda, 0x58, 0x86, 0x1c, 0x5b, 0x83, + 0x79, 0xe6, 0x2b, 0xcc, 0xe6, 0xfa, 0x2c, 0x61, 0xf2, 0x78, 0x80, 0x1b, + 0xe2, 0xf3, 0x9d, 0x39, 0x2b, 0x65, 0x57, 0x91, 0x3d, 0x71, 0x99, 0x73, + 0xa5, 0xc2, 0x79, 0x20, 0x8c, 0x07, 0x4f, 0xe5, 0xb4, 0x60, 0x1f, 0x99, + 0xa2, 0xb1, 0x4f, 0x0c, 0xef, 0xbc, 0x59, 0x53, 0x00, 0x7d, 0xb1, 0x02, + 0x41, 0x00, 0xfc, 0x7e, 0x23, 0x65, 0x70, 0xf8, 0xce, 0xd3, 0x40, 0x41, + 0x80, 0x6a, 0x1d, 0x01, 0xd6, 0x01, 0xff, 0xb6, 0x1b, 0x3d, 0x3d, 0x59, + 0x09, 0x33, 0x79, 0xc0, 0x4f, 0xde, 0x96, 0x27, 0x4b, 0x18, 0xc6, 0xd9, + 0x78, 0xf1, 0xf4, 0x35, 0x46, 0xe9, 0x7c, 0x42, 0x7a, 0x5d, 0x9f, 0xef, + 0x54, 0xb8, 0xf7, 0x9f, 0xc4, 0x33, 0x6c, 0xf3, 0x8c, 0x32, 0x46, 0x87, + 0x67, 0x30, 0x7b, 0xa7, 0xac, 0xe3, 0x02, 0x41, 0x00, 0xfc, 0x2c, 0xdf, + 0x0c, 0x0d, 0x88, 0xf5, 0xb1, 0x92, 0xa8, 0x93, 0x47, 0x63, 0x55, 0xf5, + 0xca, 0x58, 0x43, 0xba, 0x1c, 0xe5, 0x9e, 0xb6, 0x95, 0x05, 0xcd, 0xb5, + 0x82, 0xdf, 0xeb, 0x04, 0x53, 0x9d, 0xbd, 0xc2, 0x38, 0x16, 0xb3, 0x62, + 0xdd, 0xa1, 0x46, 0xdb, 0x6d, 0x97, 0x93, 0x9f, 0x8a, 0xc3, 0x9b, 0x64, + 0x7e, 0x42, 0xe3, 0x32, 0x57, 0x19, 0x1b, 0xd5, 0x6e, 0x85, 0xfa, 0xb8, + 0x8d, 0x02, 0x41, 0x00, 0xbc, 0x3d, 0xde, 0x6d, 0xd6, 0x97, 0xe8, 0xba, + 0x9e, 0x81, 0x37, 0x17, 0xe5, 0xa0, 0x64, 0xc9, 0x00, 0xb7, 0xe7, 0xfe, + 0xf4, 0x29, 0xd9, 0x2e, 0x43, 0x6b, 0x19, 0x20, 0xbd, 0x99, 0x75, 0xe7, + 0x76, 0xf8, 0xd3, 0xae, 0xaf, 0x7e, 0xb8, 0xeb, 0x81, 0xf4, 0x9d, 0xfe, + 0x07, 0x2b, 0x0b, 0x63, 0x0b, 0x5a, 0x55, 0x90, 0x71, 0x7d, 0xf1, 0xdb, + 0xd9, 0xb1, 0x41, 0x41, 0x68, 0x2f, 0x4e, 0x39, 0x02, 0x40, 0x5a, 0x34, + 0x66, 0xd8, 0xf5, 0xe2, 0x7f, 0x18, 0xb5, 0x00, 0x6e, 0x26, 0x84, 0x27, + 0x14, 0x93, 0xfb, 0xfc, 0xc6, 0x0f, 0x5e, 0x27, 0xe6, 0xe1, 0xe9, 0xc0, + 0x8a, 0xe4, 0x34, 0xda, 0xe9, 0xa2, 0x4b, 0x73, 0xbc, 0x8c, 0xb9, 0xba, + 0x13, 0x6c, 0x7a, 0x2b, 0x51, 0x84, 0xa3, 0x4a, 0xe0, 0x30, 0x10, 0x06, + 0x7e, 0xed, 0x17, 0x5a, 0x14, 0x00, 0xc9, 0xef, 0x85, 0xea, 0x52, 0x2c, + 0xbc, 0x65, 0x02, 0x40, 0x51, 0xe3, 0xf2, 0x83, 0x19, 0x9b, 0xc4, 0x1e, + 0x2f, 0x50, 0x3d, 0xdf, 0x5a, 0xa2, 0x18, 0xca, 0x5f, 0x2e, 0x49, 0xaf, + 0x6f, 0xcc, 0xfa, 0x65, 0x77, 0x94, 0xb5, 0xa1, 0x0a, 0xa9, 0xd1, 0x8a, + 0x39, 0x37, 0xf4, 0x0b, 0xa0, 0xd7, 0x82, 0x27, 0x5e, 0xae, 0x17, 0x17, + 0xa1, 0x1e, 0x54, 0x34, 0xbf, 0x6e, 0xc4, 0x8e, 0x99, 0x5d, 0x08, 0xf1, + 0x2d, 0x86, 0x9d, 0xa5, 0x20, 0x1b, 0xe5, 0xdf, +}; + +static const uint8_t kExampleDSAKeyDER[] = { + 0x30, 0x82, 0x03, 0x56, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, + 0x9e, 0x12, 0xfa, 0xb3, 0xde, 0x12, 0x21, 0x35, 0x01, 0xdd, 0x82, 0xaa, + 0x10, 0xca, 0x2d, 0x10, 0x1d, 0x2d, 0x4e, 0xbf, 0xef, 0x4d, 0x2a, 0x3f, + 0x8d, 0xaa, 0x0f, 0xe0, 0xce, 0xda, 0xd8, 0xd6, 0xaf, 0x85, 0x61, 0x6a, + 0xa2, 0xf3, 0x25, 0x2c, 0x0a, 0x2b, 0x5a, 0x6d, 0xb0, 0x9e, 0x6f, 0x14, + 0x90, 0x0e, 0x0d, 0xdb, 0x83, 0x11, 0x87, 0x6d, 0xd8, 0xf9, 0x66, 0x95, + 0x25, 0xf9, 0x9e, 0xd6, 0x59, 0x49, 0xe1, 0x84, 0xd5, 0x06, 0x47, 0x93, + 0x27, 0x11, 0x69, 0xa2, 0x28, 0x68, 0x0b, 0x95, 0xec, 0x12, 0xf5, 0x9a, + 0x8e, 0x20, 0xb2, 0x1f, 0x2b, 0x58, 0xeb, 0x2a, 0x20, 0x12, 0xd3, 0x5b, + 0xde, 0x2e, 0xe3, 0x51, 0x82, 0x2f, 0xe8, 0xf3, 0x2d, 0x0a, 0x33, 0x05, + 0x65, 0xdc, 0xce, 0x5c, 0x67, 0x2b, 0x72, 0x59, 0xc1, 0x4b, 0x24, 0x33, + 0xd0, 0xb5, 0xb2, 0xca, 0x2b, 0x2d, 0xb0, 0xab, 0x62, 0x6e, 0x8f, 0x13, + 0xf4, 0x7f, 0xe0, 0x34, 0x5d, 0x90, 0x4e, 0x72, 0x94, 0xbb, 0x03, 0x8e, + 0x9c, 0xe2, 0x1a, 0x9e, 0x58, 0x0b, 0x83, 0x35, 0x62, 0x78, 0x70, 0x6c, + 0xfe, 0x76, 0x84, 0x36, 0xc6, 0x9d, 0xe1, 0x49, 0xcc, 0xff, 0x98, 0xb4, + 0xaa, 0xb8, 0xcb, 0x4f, 0x63, 0x85, 0xc9, 0xf1, 0x02, 0xce, 0x59, 0x34, + 0x6e, 0xae, 0xef, 0x27, 0xe0, 0xad, 0x22, 0x2d, 0x53, 0xd6, 0xe8, 0x9c, + 0xc8, 0xcd, 0xe5, 0x77, 0x6d, 0xd0, 0x00, 0x57, 0xb0, 0x3f, 0x2d, 0x88, + 0xab, 0x3c, 0xed, 0xba, 0xfd, 0x7b, 0x58, 0x5f, 0x0b, 0x7f, 0x78, 0x35, + 0xe1, 0x7a, 0x37, 0x28, 0xbb, 0xf2, 0x5e, 0xa6, 0x25, 0x72, 0xf2, 0x45, + 0xdc, 0x11, 0x1f, 0x3c, 0xe3, 0x9c, 0xb6, 0xff, 0xac, 0xc3, 0x1b, 0x0a, + 0x27, 0x90, 0xe7, 0xbd, 0xe9, 0x02, 0x24, 0xea, 0x9b, 0x09, 0x31, 0x53, + 0x62, 0xaf, 0x3d, 0x2b, 0x02, 0x21, 0x00, 0xf3, 0x81, 0xdc, 0xf5, 0x3e, + 0xbf, 0x72, 0x4f, 0x8b, 0x2e, 0x5c, 0xa8, 0x2c, 0x01, 0x0f, 0xb4, 0xb5, + 0xed, 0xa9, 0x35, 0x8d, 0x0f, 0xd8, 0x8e, 0xd2, 0x78, 0x58, 0x94, 0x88, + 0xb5, 0x4f, 0xc3, 0x02, 0x82, 0x01, 0x00, 0x0c, 0x40, 0x2a, 0x72, 0x5d, + 0xcc, 0x3a, 0x62, 0xe0, 0x2b, 0xf4, 0xcf, 0x43, 0xcd, 0x17, 0xf4, 0xa4, + 0x93, 0x59, 0x12, 0x20, 0x22, 0x36, 0x69, 0xcf, 0x41, 0x93, 0xed, 0xab, + 0x42, 0x3a, 0xd0, 0x8d, 0xfb, 0x55, 0x2e, 0x30, 0x8a, 0x6a, 0x57, 0xa5, + 0xff, 0xbc, 0x7c, 0xd0, 0xfb, 0x20, 0x87, 0xf8, 0x1f, 0x8d, 0xf0, 0xcb, + 0x08, 0xab, 0x21, 0x33, 0x28, 0x7d, 0x2b, 0x69, 0x68, 0x71, 0x4a, 0x94, + 0xf6, 0x33, 0xc9, 0x40, 0x84, 0x5a, 0x48, 0xa3, 0xe1, 0x67, 0x08, 0xdd, + 0xe7, 0x61, 0xcc, 0x6a, 0x8e, 0xab, 0x2d, 0x84, 0xdb, 0x21, 0xb6, 0xea, + 0x5b, 0x07, 0x68, 0x14, 0x93, 0xcc, 0x9c, 0x31, 0xfb, 0xc3, 0x68, 0xb2, + 0x43, 0xf6, 0xdd, 0xf8, 0xc9, 0x32, 0xa8, 0xb4, 0x03, 0x8f, 0x44, 0xe7, + 0xb1, 0x5c, 0xa8, 0x76, 0x34, 0x4a, 0x14, 0x78, 0x59, 0xf2, 0xb4, 0x3b, + 0x39, 0x45, 0x86, 0x68, 0xad, 0x5e, 0x0a, 0x1a, 0x9a, 0x66, 0x95, 0x46, + 0xdd, 0x28, 0x12, 0xe3, 0xb3, 0x61, 0x7a, 0x0a, 0xef, 0x99, 0xd5, 0x8e, + 0x3b, 0xb4, 0xcc, 0x87, 0xfd, 0x94, 0x22, 0x5e, 0x01, 0xd2, 0xdc, 0xc4, + 0x69, 0xa7, 0x72, 0x68, 0x14, 0x6c, 0x51, 0x91, 0x8f, 0x18, 0xe8, 0xb4, + 0xd7, 0x0a, 0xa1, 0xf0, 0xc7, 0x62, 0x3b, 0xcc, 0x52, 0xcf, 0x37, 0x31, + 0xd3, 0x86, 0x41, 0xb2, 0xd2, 0x83, 0x0b, 0x7e, 0xec, 0xb2, 0xf0, 0x95, + 0x52, 0xff, 0x13, 0x7d, 0x04, 0x6e, 0x49, 0x4e, 0x7f, 0x33, 0xc3, 0x59, + 0x00, 0x02, 0xb1, 0x6d, 0x1b, 0x97, 0xd9, 0x36, 0xfd, 0xa2, 0x8f, 0x90, + 0xc3, 0xed, 0x3c, 0xa3, 0x53, 0x38, 0x16, 0x8a, 0xc1, 0x6f, 0x77, 0xc3, + 0xc5, 0x7a, 0xdc, 0x2e, 0x8f, 0x7c, 0x6c, 0x22, 0x56, 0xe4, 0x1a, 0x5f, + 0x65, 0x45, 0x05, 0x90, 0xdb, 0xb5, 0xbc, 0xf0, 0x6d, 0x66, 0x61, 0x02, + 0x82, 0x01, 0x00, 0x31, 0x97, 0x31, 0xa1, 0x4e, 0x38, 0x56, 0x88, 0xdb, + 0x94, 0x1d, 0xbf, 0x65, 0x5c, 0xda, 0x4b, 0xc2, 0x10, 0xde, 0x74, 0x20, + 0x03, 0xce, 0x13, 0x60, 0xf2, 0x25, 0x1d, 0x55, 0x7c, 0x5d, 0x94, 0x82, + 0x54, 0x08, 0x53, 0xdb, 0x85, 0x95, 0xbf, 0xdd, 0x5e, 0x50, 0xd5, 0x96, + 0xe0, 0x79, 0x51, 0x1b, 0xbf, 0x4d, 0x4e, 0xb9, 0x3a, 0xc5, 0xee, 0xc4, + 0x5e, 0x98, 0x75, 0x7b, 0xbe, 0xff, 0x30, 0xe6, 0xd0, 0x7b, 0xa6, 0xf1, + 0xbc, 0x29, 0xea, 0xdf, 0xec, 0xf3, 0x8b, 0xfa, 0x83, 0x11, 0x9f, 0x3f, + 0xf0, 0x5d, 0x06, 0x51, 0x32, 0xaa, 0x21, 0xfc, 0x26, 0x17, 0xe7, 0x50, + 0xc2, 0x16, 0xba, 0xfa, 0x54, 0xb7, 0x7e, 0x1d, 0x2c, 0xa6, 0xa3, 0x41, + 0x66, 0x33, 0x94, 0x83, 0xb9, 0xbf, 0xa0, 0x4f, 0xbd, 0xa6, 0xfd, 0x2c, + 0x81, 0x58, 0x35, 0x33, 0x39, 0xc0, 0x6d, 0x33, 0x40, 0x56, 0x64, 0x12, + 0x5a, 0xcd, 0x35, 0x53, 0x21, 0x78, 0x8f, 0x27, 0x24, 0x37, 0x66, 0x8a, + 0xdf, 0x5e, 0x5f, 0x63, 0xfc, 0x8b, 0x2d, 0xef, 0x57, 0xdb, 0x40, 0x25, + 0xd5, 0x17, 0x53, 0x0b, 0xe4, 0xa5, 0xae, 0x54, 0xbf, 0x46, 0x4f, 0xa6, + 0x79, 0xc3, 0x74, 0xfa, 0x1f, 0x85, 0x34, 0x64, 0x6d, 0xc5, 0x03, 0xeb, + 0x72, 0x98, 0x80, 0x7b, 0xc0, 0x8f, 0x35, 0x11, 0xa7, 0x09, 0xeb, 0x51, + 0xe0, 0xb0, 0xac, 0x92, 0x14, 0xf2, 0xad, 0x37, 0x95, 0x5a, 0xba, 0x8c, + 0xc4, 0xdb, 0xed, 0xc4, 0x4e, 0x8b, 0x8f, 0x84, 0x33, 0x64, 0xf8, 0x57, + 0x12, 0xd7, 0x08, 0x7e, 0x90, 0x66, 0xdf, 0x91, 0x50, 0x23, 0xf2, 0x73, + 0xc0, 0x6b, 0xb1, 0x15, 0xdd, 0x64, 0xd7, 0xc9, 0x75, 0x17, 0x73, 0x72, + 0xda, 0x33, 0xc4, 0x6f, 0xa5, 0x47, 0xa1, 0xcc, 0xd1, 0xc6, 0x62, 0xe5, + 0xca, 0xab, 0x5f, 0x2a, 0x8f, 0x6b, 0xcc, 0x02, 0x21, 0x00, 0xb0, 0xc7, + 0x68, 0x70, 0x27, 0x43, 0xbc, 0x51, 0x24, 0x29, 0x93, 0xa9, 0x71, 0xa5, + 0x28, 0x89, 0x79, 0x54, 0x44, 0xf7, 0xc6, 0x45, 0x22, 0x03, 0xd0, 0xce, + 0x84, 0xfe, 0x61, 0x17, 0xd4, 0x6e, +}; + +static const uint8_t kMsg[] = {1, 2, 3, 4}; + +static const uint8_t kSignature[] = { + 0xa5, 0xf0, 0x8a, 0x47, 0x5d, 0x3c, 0xb3, 0xcc, 0xa9, 0x79, 0xaf, 0x4d, + 0x8c, 0xae, 0x4c, 0x14, 0xef, 0xc2, 0x0b, 0x34, 0x36, 0xde, 0xf4, 0x3e, + 0x3d, 0xbb, 0x4a, 0x60, 0x5c, 0xc8, 0x91, 0x28, 0xda, 0xfb, 0x7e, 0x04, + 0x96, 0x7e, 0x63, 0x13, 0x90, 0xce, 0xb9, 0xb4, 0x62, 0x7a, 0xfd, 0x09, + 0x3d, 0xc7, 0x67, 0x78, 0x54, 0x04, 0xeb, 0x52, 0x62, 0x6e, 0x24, 0x67, + 0xb4, 0x40, 0xfc, 0x57, 0x62, 0xc6, 0xf1, 0x67, 0xc1, 0x97, 0x8f, 0x6a, + 0xa8, 0xae, 0x44, 0x46, 0x5e, 0xab, 0x67, 0x17, 0x53, 0x19, 0x3a, 0xda, + 0x5a, 0xc8, 0x16, 0x3e, 0x86, 0xd5, 0xc5, 0x71, 0x2f, 0xfc, 0x23, 0x48, + 0xd9, 0x0b, 0x13, 0xdd, 0x7b, 0x5a, 0x25, 0x79, 0xef, 0xa5, 0x7b, 0x04, + 0xed, 0x44, 0xf6, 0x18, 0x55, 0xe4, 0x0a, 0xe9, 0x57, 0x79, 0x5d, 0xd7, + 0x55, 0xa7, 0xab, 0x45, 0x02, 0x97, 0x60, 0x42, +}; + +// kExampleRSAKeyPKCS8 is kExampleRSAKeyDER encoded in a PKCS #8 +// PrivateKeyInfo. +static const uint8_t kExampleRSAKeyPKCS8[] = { + 0x30, 0x82, 0x02, 0x76, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, + 0x02, 0x60, 0x30, 0x82, 0x02, 0x5c, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81, + 0x00, 0xf8, 0xb8, 0x6c, 0x83, 0xb4, 0xbc, 0xd9, 0xa8, 0x57, 0xc0, 0xa5, + 0xb4, 0x59, 0x76, 0x8c, 0x54, 0x1d, 0x79, 0xeb, 0x22, 0x52, 0x04, 0x7e, + 0xd3, 0x37, 0xeb, 0x41, 0xfd, 0x83, 0xf9, 0xf0, 0xa6, 0x85, 0x15, 0x34, + 0x75, 0x71, 0x5a, 0x84, 0xa8, 0x3c, 0xd2, 0xef, 0x5a, 0x4e, 0xd3, 0xde, + 0x97, 0x8a, 0xdd, 0xff, 0xbb, 0xcf, 0x0a, 0xaa, 0x86, 0x92, 0xbe, 0xb8, + 0x50, 0xe4, 0xcd, 0x6f, 0x80, 0x33, 0x30, 0x76, 0x13, 0x8f, 0xca, 0x7b, + 0xdc, 0xec, 0x5a, 0xca, 0x63, 0xc7, 0x03, 0x25, 0xef, 0xa8, 0x8a, 0x83, + 0x58, 0x76, 0x20, 0xfa, 0x16, 0x77, 0xd7, 0x79, 0x92, 0x63, 0x01, 0x48, + 0x1a, 0xd8, 0x7b, 0x67, 0xf1, 0x52, 0x55, 0x49, 0x4e, 0xd6, 0x6e, 0x4a, + 0x5c, 0xd7, 0x7a, 0x37, 0x36, 0x0c, 0xde, 0xdd, 0x8f, 0x44, 0xe8, 0xc2, + 0xa7, 0x2c, 0x2b, 0xb5, 0xaf, 0x64, 0x4b, 0x61, 0x07, 0x02, 0x03, 0x01, + 0x00, 0x01, 0x02, 0x81, 0x80, 0x74, 0x88, 0x64, 0x3f, 0x69, 0x45, 0x3a, + 0x6d, 0xc7, 0x7f, 0xb9, 0xa3, 0xc0, 0x6e, 0xec, 0xdc, 0xd4, 0x5a, 0xb5, + 0x32, 0x85, 0x5f, 0x19, 0xd4, 0xf8, 0xd4, 0x3f, 0x3c, 0xfa, 0xc2, 0xf6, + 0x5f, 0xee, 0xe6, 0xba, 0x87, 0x74, 0x2e, 0xc7, 0x0c, 0xd4, 0x42, 0xb8, + 0x66, 0x85, 0x9c, 0x7b, 0x24, 0x61, 0xaa, 0x16, 0x11, 0xf6, 0xb5, 0xb6, + 0xa4, 0x0a, 0xc9, 0x55, 0x2e, 0x81, 0xa5, 0x47, 0x61, 0xcb, 0x25, 0x8f, + 0xc2, 0x15, 0x7b, 0x0e, 0x7c, 0x36, 0x9f, 0x3a, 0xda, 0x58, 0x86, 0x1c, + 0x5b, 0x83, 0x79, 0xe6, 0x2b, 0xcc, 0xe6, 0xfa, 0x2c, 0x61, 0xf2, 0x78, + 0x80, 0x1b, 0xe2, 0xf3, 0x9d, 0x39, 0x2b, 0x65, 0x57, 0x91, 0x3d, 0x71, + 0x99, 0x73, 0xa5, 0xc2, 0x79, 0x20, 0x8c, 0x07, 0x4f, 0xe5, 0xb4, 0x60, + 0x1f, 0x99, 0xa2, 0xb1, 0x4f, 0x0c, 0xef, 0xbc, 0x59, 0x53, 0x00, 0x7d, + 0xb1, 0x02, 0x41, 0x00, 0xfc, 0x7e, 0x23, 0x65, 0x70, 0xf8, 0xce, 0xd3, + 0x40, 0x41, 0x80, 0x6a, 0x1d, 0x01, 0xd6, 0x01, 0xff, 0xb6, 0x1b, 0x3d, + 0x3d, 0x59, 0x09, 0x33, 0x79, 0xc0, 0x4f, 0xde, 0x96, 0x27, 0x4b, 0x18, + 0xc6, 0xd9, 0x78, 0xf1, 0xf4, 0x35, 0x46, 0xe9, 0x7c, 0x42, 0x7a, 0x5d, + 0x9f, 0xef, 0x54, 0xb8, 0xf7, 0x9f, 0xc4, 0x33, 0x6c, 0xf3, 0x8c, 0x32, + 0x46, 0x87, 0x67, 0x30, 0x7b, 0xa7, 0xac, 0xe3, 0x02, 0x41, 0x00, 0xfc, + 0x2c, 0xdf, 0x0c, 0x0d, 0x88, 0xf5, 0xb1, 0x92, 0xa8, 0x93, 0x47, 0x63, + 0x55, 0xf5, 0xca, 0x58, 0x43, 0xba, 0x1c, 0xe5, 0x9e, 0xb6, 0x95, 0x05, + 0xcd, 0xb5, 0x82, 0xdf, 0xeb, 0x04, 0x53, 0x9d, 0xbd, 0xc2, 0x38, 0x16, + 0xb3, 0x62, 0xdd, 0xa1, 0x46, 0xdb, 0x6d, 0x97, 0x93, 0x9f, 0x8a, 0xc3, + 0x9b, 0x64, 0x7e, 0x42, 0xe3, 0x32, 0x57, 0x19, 0x1b, 0xd5, 0x6e, 0x85, + 0xfa, 0xb8, 0x8d, 0x02, 0x41, 0x00, 0xbc, 0x3d, 0xde, 0x6d, 0xd6, 0x97, + 0xe8, 0xba, 0x9e, 0x81, 0x37, 0x17, 0xe5, 0xa0, 0x64, 0xc9, 0x00, 0xb7, + 0xe7, 0xfe, 0xf4, 0x29, 0xd9, 0x2e, 0x43, 0x6b, 0x19, 0x20, 0xbd, 0x99, + 0x75, 0xe7, 0x76, 0xf8, 0xd3, 0xae, 0xaf, 0x7e, 0xb8, 0xeb, 0x81, 0xf4, + 0x9d, 0xfe, 0x07, 0x2b, 0x0b, 0x63, 0x0b, 0x5a, 0x55, 0x90, 0x71, 0x7d, + 0xf1, 0xdb, 0xd9, 0xb1, 0x41, 0x41, 0x68, 0x2f, 0x4e, 0x39, 0x02, 0x40, + 0x5a, 0x34, 0x66, 0xd8, 0xf5, 0xe2, 0x7f, 0x18, 0xb5, 0x00, 0x6e, 0x26, + 0x84, 0x27, 0x14, 0x93, 0xfb, 0xfc, 0xc6, 0x0f, 0x5e, 0x27, 0xe6, 0xe1, + 0xe9, 0xc0, 0x8a, 0xe4, 0x34, 0xda, 0xe9, 0xa2, 0x4b, 0x73, 0xbc, 0x8c, + 0xb9, 0xba, 0x13, 0x6c, 0x7a, 0x2b, 0x51, 0x84, 0xa3, 0x4a, 0xe0, 0x30, + 0x10, 0x06, 0x7e, 0xed, 0x17, 0x5a, 0x14, 0x00, 0xc9, 0xef, 0x85, 0xea, + 0x52, 0x2c, 0xbc, 0x65, 0x02, 0x40, 0x51, 0xe3, 0xf2, 0x83, 0x19, 0x9b, + 0xc4, 0x1e, 0x2f, 0x50, 0x3d, 0xdf, 0x5a, 0xa2, 0x18, 0xca, 0x5f, 0x2e, + 0x49, 0xaf, 0x6f, 0xcc, 0xfa, 0x65, 0x77, 0x94, 0xb5, 0xa1, 0x0a, 0xa9, + 0xd1, 0x8a, 0x39, 0x37, 0xf4, 0x0b, 0xa0, 0xd7, 0x82, 0x27, 0x5e, 0xae, + 0x17, 0x17, 0xa1, 0x1e, 0x54, 0x34, 0xbf, 0x6e, 0xc4, 0x8e, 0x99, 0x5d, + 0x08, 0xf1, 0x2d, 0x86, 0x9d, 0xa5, 0x20, 0x1b, 0xe5, 0xdf, +}; + +// kExampleECKeyDER is a sample EC private key encoded as an ECPrivateKey +// structure. +static const uint8_t kExampleECKeyDER[] = { + 0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0x07, 0x0f, 0x08, 0x72, 0x7a, + 0xd4, 0xa0, 0x4a, 0x9c, 0xdd, 0x59, 0xc9, 0x4d, 0x89, 0x68, 0x77, 0x08, + 0xb5, 0x6f, 0xc9, 0x5d, 0x30, 0x77, 0x0e, 0xe8, 0xd1, 0xc9, 0xce, 0x0a, + 0x8b, 0xb4, 0x6a, 0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, + 0x03, 0x01, 0x07, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04, 0xe6, 0x2b, 0x69, + 0xe2, 0xbf, 0x65, 0x9f, 0x97, 0xbe, 0x2f, 0x1e, 0x0d, 0x94, 0x8a, 0x4c, + 0xd5, 0x97, 0x6b, 0xb7, 0xa9, 0x1e, 0x0d, 0x46, 0xfb, 0xdd, 0xa9, 0xa9, + 0x1e, 0x9d, 0xdc, 0xba, 0x5a, 0x01, 0xe7, 0xd6, 0x97, 0xa8, 0x0a, 0x18, + 0xf9, 0xc3, 0xc4, 0xa3, 0x1e, 0x56, 0xe2, 0x7c, 0x83, 0x48, 0xdb, 0x16, + 0x1a, 0x1c, 0xf5, 0x1d, 0x7e, 0xf1, 0x94, 0x2d, 0x4b, 0xcf, 0x72, 0x22, + 0xc1, +}; + +// kExampleECKeyPKCS8 is a sample EC private key encoded as a PKCS#8 +// PrivateKeyInfo. +static const uint8_t kExampleECKeyPKCS8[] = { + 0x30, 0x81, 0x87, 0x02, 0x01, 0x00, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, + 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, + 0x03, 0x01, 0x07, 0x04, 0x6d, 0x30, 0x6b, 0x02, 0x01, 0x01, 0x04, 0x20, + 0x43, 0x09, 0xc0, 0x67, 0x75, 0x21, 0x47, 0x9d, 0xa8, 0xfa, 0x16, 0xdf, + 0x15, 0x73, 0x61, 0x34, 0x68, 0x6f, 0xe3, 0x8e, 0x47, 0x91, 0x95, 0xab, + 0x79, 0x4a, 0x72, 0x14, 0xcb, 0xe2, 0x49, 0x4f, 0xa1, 0x44, 0x03, 0x42, + 0x00, 0x04, 0xde, 0x09, 0x08, 0x07, 0x03, 0x2e, 0x8f, 0x37, 0x9a, 0xd5, + 0xad, 0xe5, 0xc6, 0x9d, 0xd4, 0x63, 0xc7, 0x4a, 0xe7, 0x20, 0xcb, 0x90, + 0xa0, 0x1f, 0x18, 0x18, 0x72, 0xb5, 0x21, 0x88, 0x38, 0xc0, 0xdb, 0xba, + 0xf6, 0x99, 0xd8, 0xa5, 0x3b, 0x83, 0xe9, 0xe3, 0xd5, 0x61, 0x99, 0x73, + 0x42, 0xc6, 0x6c, 0xe8, 0x0a, 0x95, 0x40, 0x41, 0x3b, 0x0d, 0x10, 0xa7, + 0x4a, 0x93, 0xdb, 0x5a, 0xe7, 0xec, +}; + +// kExampleECKeySpecifiedCurvePKCS8 is a sample EC private key encoded as a +// PKCS#8 PrivateKeyInfo with P-256's parameters spelled out rather than using +// the curve OID. +static const uint8_t kExampleECKeySpecifiedCurvePKCS8[] = { + 0x30, 0x82, 0x01, 0x79, 0x02, 0x01, 0x00, 0x30, 0x82, 0x01, 0x03, 0x06, + 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x30, 0x81, 0xf7, 0x02, + 0x01, 0x01, 0x30, 0x2c, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01, + 0x01, 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x30, 0x5b, 0x04, 0x20, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, + 0x04, 0x20, 0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, 0xb3, 0xeb, + 0xbd, 0x55, 0x76, 0x98, 0x86, 0xbc, 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53, + 0xb0, 0xf6, 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b, 0x03, 0x15, + 0x00, 0xc4, 0x9d, 0x36, 0x08, 0x86, 0xe7, 0x04, 0x93, 0x6a, 0x66, 0x78, + 0xe1, 0x13, 0x9d, 0x26, 0xb7, 0x81, 0x9f, 0x7e, 0x90, 0x04, 0x41, 0x04, + 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6, 0xe5, + 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb, 0x33, 0xa0, + 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96, 0x4f, 0xe3, 0x42, 0xe2, + 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16, + 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, + 0x37, 0xbf, 0x51, 0xf5, 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbc, + 0xe6, 0xfa, 0xad, 0xa7, 0x17, 0x9e, 0x84, 0xf3, 0xb9, 0xca, 0xc2, 0xfc, + 0x63, 0x25, 0x51, 0x02, 0x01, 0x01, 0x04, 0x6d, 0x30, 0x6b, 0x02, 0x01, + 0x01, 0x04, 0x20, 0x43, 0x09, 0xc0, 0x67, 0x75, 0x21, 0x47, 0x9d, 0xa8, + 0xfa, 0x16, 0xdf, 0x15, 0x73, 0x61, 0x34, 0x68, 0x6f, 0xe3, 0x8e, 0x47, + 0x91, 0x95, 0xab, 0x79, 0x4a, 0x72, 0x14, 0xcb, 0xe2, 0x49, 0x4f, 0xa1, + 0x44, 0x03, 0x42, 0x00, 0x04, 0xde, 0x09, 0x08, 0x07, 0x03, 0x2e, 0x8f, + 0x37, 0x9a, 0xd5, 0xad, 0xe5, 0xc6, 0x9d, 0xd4, 0x63, 0xc7, 0x4a, 0xe7, + 0x20, 0xcb, 0x90, 0xa0, 0x1f, 0x18, 0x18, 0x72, 0xb5, 0x21, 0x88, 0x38, + 0xc0, 0xdb, 0xba, 0xf6, 0x99, 0xd8, 0xa5, 0x3b, 0x83, 0xe9, 0xe3, 0xd5, + 0x61, 0x99, 0x73, 0x42, 0xc6, 0x6c, 0xe8, 0x0a, 0x95, 0x40, 0x41, 0x3b, + 0x0d, 0x10, 0xa7, 0x4a, 0x93, 0xdb, 0x5a, 0xe7, 0xec, +}; + +// kExampleBadECKeyDER is a sample EC private key encoded as an ECPrivateKey +// structure. The private key is equal to the order and will fail to import. +static const uint8_t kExampleBadECKeyDER[] = { + 0x30, 0x66, 0x02, 0x01, 0x00, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, + 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, + 0x01, 0x07, 0x04, 0x4C, 0x30, 0x4A, 0x02, 0x01, 0x01, 0x04, 0x20, 0xFF, + 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84, 0xF3, + 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51, 0xA1, 0x23, 0x03, 0x21, 0x00, + 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84, + 0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51 +}; + +// kExampleBadECKeyDER2 is a sample EC private key encoded as an ECPrivateKey +// structure, but with the curve OID swapped out for 1.1.1.1.1.1.1.1.1. It is +// then concatenated with an ECPrivateKey wrapped in a PrivateKeyInfo, +// optional public key omitted, and with the private key chopped off. +static const uint8_t kExampleBadECKeyDER2[] = { + 0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0x07, 0x0f, 0x08, 0x72, 0x7a, + 0xd4, 0xa0, 0x4a, 0x9c, 0xdd, 0x59, 0xc9, 0x4d, 0x89, 0x68, 0x77, 0x08, + 0xb5, 0x6f, 0xc9, 0x5d, 0x30, 0x77, 0x0e, 0xe8, 0xd1, 0xc9, 0xce, 0x0a, + 0x8b, 0xb4, 0x6a, 0xa0, 0x0a, 0x06, 0x08, 0x29, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04, 0xe6, 0x2b, 0x69, + 0xe2, 0xbf, 0x65, 0x9f, 0x97, 0xbe, 0x2f, 0x1e, 0x0d, 0x94, 0x8a, 0x4c, + 0xd5, 0x97, 0x6b, 0xb7, 0xa9, 0x1e, 0x0d, 0x46, 0xfb, 0xdd, 0xa9, 0xa9, + 0x1e, 0x9d, 0xdc, 0xba, 0x5a, 0x01, 0xe7, 0xd6, 0x97, 0xa8, 0x0a, 0x18, + 0xf9, 0xc3, 0xc4, 0xa3, 0x1e, 0x56, 0xe2, 0x7c, 0x83, 0x48, 0xdb, 0x16, + 0x1a, 0x1c, 0xf5, 0x1d, 0x7e, 0xf1, 0x94, 0x2d, 0x4b, 0xcf, 0x72, 0x22, + 0xc1, 0x30, 0x41, 0x02, 0x01, 0x00, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, + 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, + 0x03, 0x01, 0x07, 0x04, 0x27, 0x30, 0x25, 0x02, 0x01, 0x01, 0x04, 0x20, + 0x07, +}; + +// kInvalidPrivateKey is an invalid private key. See +// https://rt.openssl.org/Ticket/Display.html?id=4131. +static const uint8_t kInvalidPrivateKey[] = { + 0x30, 0x39, 0x02, 0x01, 0x02, 0x30, 0x09, 0x06, 0x01, 0x38, 0x08, + 0x04, 0x69, 0x30, 0x30, 0x80, 0x30, 0x19, 0x01, 0x02, 0x9f, 0xf8, + 0x8b, 0x29, 0x80, 0x30, 0xb0, 0x1b, 0x06, 0x09, 0x22, 0xbe, 0x08, + 0x04, 0xe9, 0x30, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x3a, 0x01, 0x80, + 0x09, 0x30, 0x80, 0x06, 0x01, 0x02, 0x30, 0x80, 0x30, 0x01, 0x3b, + 0x02, 0x00, 0x00, 0x04, 0x20, 0x30, 0x82, 0x04, 0xe9, 0x30, 0xc3, + 0xe8, 0x30, 0x01, 0x05, 0x30, 0x80, 0x30, 0x01, 0x3b, 0x01, 0x04, + 0x02, 0x02, 0xff, 0x00, 0x30, 0x29, 0x02, 0x11, 0x03, 0x29, 0x29, + 0x02, 0x00, 0x99, 0x30, 0x80, 0x06, 0x21, 0x02, 0x24, 0x04, 0xe8, + 0x30, 0x01, 0x01, 0x04, 0x30, 0x80, 0x1b, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x30, 0x01, 0xaa, 0x02, 0x86, 0xc0, 0x30, 0xdf, 0xe9, 0x80, +}; + +static ScopedEVP_PKEY LoadExampleRSAKey() { + ScopedRSA rsa(RSA_private_key_from_bytes(kExampleRSAKeyDER, + sizeof(kExampleRSAKeyDER))); + if (!rsa) { + return nullptr; + } + ScopedEVP_PKEY pkey(EVP_PKEY_new()); + if (!pkey || !EVP_PKEY_set1_RSA(pkey.get(), rsa.get())) { + return nullptr; + } + return pkey; +} + +static bool TestEVP_DigestSignInit(void) { + ScopedEVP_PKEY pkey = LoadExampleRSAKey(); + ScopedEVP_MD_CTX md_ctx; + if (!pkey || + !EVP_DigestSignInit(md_ctx.get(), NULL, EVP_sha256(), NULL, pkey.get()) || + !EVP_DigestSignUpdate(md_ctx.get(), kMsg, sizeof(kMsg))) { + return false; + } + // Determine the size of the signature. + size_t sig_len = 0; + if (!EVP_DigestSignFinal(md_ctx.get(), NULL, &sig_len)) { + return false; + } + // Sanity check for testing. + if (sig_len != (size_t)EVP_PKEY_size(pkey.get())) { + fprintf(stderr, "sig_len mismatch\n"); + return false; + } + + std::vector sig; + sig.resize(sig_len); + if (!EVP_DigestSignFinal(md_ctx.get(), sig.data(), &sig_len)) { + return false; + } + sig.resize(sig_len); + + // Ensure that the signature round-trips. + md_ctx.Reset(); + if (!EVP_DigestVerifyInit(md_ctx.get(), NULL, EVP_sha256(), NULL, + pkey.get()) || + !EVP_DigestVerifyUpdate(md_ctx.get(), kMsg, sizeof(kMsg)) || + !EVP_DigestVerifyFinal(md_ctx.get(), sig.data(), sig_len)) { + return false; + } + + return true; +} + +static bool TestEVP_DigestVerifyInit(void) { + ScopedEVP_PKEY pkey = LoadExampleRSAKey(); + ScopedEVP_MD_CTX md_ctx; + if (!pkey || + !EVP_DigestVerifyInit(md_ctx.get(), NULL, EVP_sha256(), NULL, + pkey.get()) || + !EVP_DigestVerifyUpdate(md_ctx.get(), kMsg, sizeof(kMsg)) || + !EVP_DigestVerifyFinal(md_ctx.get(), kSignature, sizeof(kSignature))) { + return false; + } + return true; +} + +static bool TestVerifyRecover() { + ScopedEVP_PKEY pkey = LoadExampleRSAKey(); + if (!pkey) { + return false; + } + + ScopedRSA rsa(EVP_PKEY_get1_RSA(pkey.get())); + if (!rsa) { + return false; + } + + const uint8_t kDummyHash[32] = {0}; + uint8_t sig[2048/8]; + unsigned sig_len = sizeof(sig); + + if (!RSA_sign(NID_sha256, kDummyHash, sizeof(kDummyHash), sig, &sig_len, + rsa.get())) { + fprintf(stderr, "RSA_sign failed.\n"); + ERR_print_errors_fp(stderr); + return false; + } + + size_t out_len; + ScopedEVP_PKEY_CTX ctx(EVP_PKEY_CTX_new(pkey.get(), nullptr)); + if (!EVP_PKEY_verify_recover_init(ctx.get()) || + !EVP_PKEY_CTX_set_rsa_padding(ctx.get(), RSA_PKCS1_PADDING) || + !EVP_PKEY_CTX_set_signature_md(ctx.get(), EVP_sha256()) || + !EVP_PKEY_verify_recover(ctx.get(), nullptr, &out_len, sig, sig_len)) { + fprintf(stderr, "verify_recover failed will nullptr buffer.\n"); + ERR_print_errors_fp(stderr); + return false; + } + + std::vector recovered; + recovered.resize(out_len); + + if (!EVP_PKEY_verify_recover(ctx.get(), recovered.data(), &out_len, sig, + sig_len)) { + fprintf(stderr, "verify_recover failed.\n"); + ERR_print_errors_fp(stderr); + return false; + } + + if (out_len != sizeof(kDummyHash)) { + fprintf(stderr, "verify_recover length is %u, expected %u.\n", + static_cast(out_len), + static_cast(sizeof(kDummyHash))); + return false; + } + + if (memcmp(recovered.data(), kDummyHash, sizeof(kDummyHash)) != 0) { + fprintf(stderr, "verify_recover got wrong value.\n"); + ERR_print_errors_fp(stderr); + return false; + } + + out_len = recovered.size(); + if (!EVP_PKEY_CTX_set_signature_md(ctx.get(), nullptr) || + !EVP_PKEY_verify_recover(ctx.get(), recovered.data(), &out_len, sig, + sig_len)) { + fprintf(stderr, "verify_recover failed with NULL MD.\n"); + ERR_print_errors_fp(stderr); + return false; + } + + /* The size of a SHA-256 hash plus PKCS#1 v1.5 ASN.1 stuff happens to be 51 + * bytes. */ + static const size_t kExpectedASN1Size = 51; + if (out_len != kExpectedASN1Size) { + fprintf(stderr, "verify_recover length without MD is %u, expected %u.\n", + static_cast(out_len), + static_cast(kExpectedASN1Size)); + return false; + } + + return true; +} + +static bool TestValidPrivateKey(const uint8_t *input, size_t input_len, + int expected_id) { + const uint8_t *p = input; + ScopedEVP_PKEY pkey(d2i_AutoPrivateKey(NULL, &p, input_len)); + if (!pkey || p != input + input_len) { + fprintf(stderr, "d2i_AutoPrivateKey failed\n"); + return false; + } + + if (EVP_PKEY_id(pkey.get()) != expected_id) { + fprintf(stderr, "Did not decode expected type\n"); + return false; + } + + return true; +} + +static bool Testd2i_AutoPrivateKey() { + if (!TestValidPrivateKey(kExampleRSAKeyDER, sizeof(kExampleRSAKeyDER), + EVP_PKEY_RSA)) { + fprintf(stderr, "d2i_AutoPrivateKey(kExampleRSAKeyDER) failed\n"); + return false; + } + + if (!TestValidPrivateKey(kExampleRSAKeyPKCS8, sizeof(kExampleRSAKeyPKCS8), + EVP_PKEY_RSA)) { + fprintf(stderr, "d2i_AutoPrivateKey(kExampleRSAKeyPKCS8) failed\n"); + return false; + } + + if (!TestValidPrivateKey(kExampleECKeyDER, sizeof(kExampleECKeyDER), + EVP_PKEY_EC)) { + fprintf(stderr, "d2i_AutoPrivateKey(kExampleECKeyDER) failed\n"); + return false; + } + + if (!TestValidPrivateKey(kExampleECKeyPKCS8, sizeof(kExampleECKeyPKCS8), + EVP_PKEY_EC)) { + fprintf(stderr, "d2i_AutoPrivateKey(kExampleECKeyPKCS8) failed\n"); + return false; + } + + if (!TestValidPrivateKey(kExampleECKeySpecifiedCurvePKCS8, + sizeof(kExampleECKeySpecifiedCurvePKCS8), + EVP_PKEY_EC)) { + fprintf(stderr, + "d2i_AutoPrivateKey(kExampleECKeySpecifiedCurvePKCS8) failed\n"); + return false; + } + + if (!TestValidPrivateKey(kExampleDSAKeyDER, sizeof(kExampleDSAKeyDER), + EVP_PKEY_DSA)) { + fprintf(stderr, "d2i_AutoPrivateKey(kExampleDSAKeyDER) failed\n"); + return false; + } + + const uint8_t *p = kInvalidPrivateKey; + ScopedEVP_PKEY pkey(d2i_AutoPrivateKey(NULL, &p, sizeof(kInvalidPrivateKey))); + if (pkey) { + fprintf(stderr, "Parsed invalid private key\n"); + return false; + } + ERR_clear_error(); + + return true; +} + +// TestEVP_PKCS82PKEY tests loading a bad key in PKCS8 format. +static bool TestEVP_PKCS82PKEY(void) { + const uint8_t *derp = kExampleBadECKeyDER; + ScopedPKCS8_PRIV_KEY_INFO p8inf( + d2i_PKCS8_PRIV_KEY_INFO(NULL, &derp, sizeof(kExampleBadECKeyDER))); + if (!p8inf || derp != kExampleBadECKeyDER + sizeof(kExampleBadECKeyDER)) { + fprintf(stderr, "Failed to parse key\n"); + return false; + } + + ScopedEVP_PKEY pkey(EVP_PKCS82PKEY(p8inf.get())); + if (pkey) { + fprintf(stderr, "Imported invalid EC key\n"); + return false; + } + ERR_clear_error(); + + return true; +} + +// TestEVPMarshalEmptyPublicKey tests |EVP_marshal_public_key| on an empty key. +static bool TestEVPMarshalEmptyPublicKey(void) { + ScopedEVP_PKEY empty(EVP_PKEY_new()); + if (!empty) { + return false; + } + ScopedCBB cbb; + if (EVP_marshal_public_key(cbb.get(), empty.get())) { + fprintf(stderr, "Marshalled empty public key.\n"); + return false; + } + if (ERR_GET_REASON(ERR_peek_last_error()) != EVP_R_UNSUPPORTED_ALGORITHM) { + fprintf(stderr, "Marshalling an empty public key gave wrong error.\n"); + return false; + } + ERR_clear_error(); + return true; +} + +// Testd2i_PrivateKey tests |d2i_PrivateKey|. +static bool Testd2i_PrivateKey(void) { + const uint8_t *derp = kExampleRSAKeyDER; + ScopedEVP_PKEY pkey(d2i_PrivateKey(EVP_PKEY_RSA, nullptr, &derp, + sizeof(kExampleRSAKeyDER))); + if (!pkey || derp != kExampleRSAKeyDER + sizeof(kExampleRSAKeyDER)) { + fprintf(stderr, "Failed to import raw RSA key.\n"); + return false; + } + + derp = kExampleDSAKeyDER; + pkey.reset(d2i_PrivateKey(EVP_PKEY_DSA, nullptr, &derp, + sizeof(kExampleDSAKeyDER))); + if (!pkey || derp != kExampleDSAKeyDER + sizeof(kExampleDSAKeyDER)) { + fprintf(stderr, "Failed to import raw DSA key.\n"); + return false; + } + + derp = kExampleRSAKeyPKCS8; + pkey.reset(d2i_PrivateKey(EVP_PKEY_RSA, nullptr, &derp, + sizeof(kExampleRSAKeyPKCS8))); + if (!pkey || derp != kExampleRSAKeyPKCS8 + sizeof(kExampleRSAKeyPKCS8)) { + fprintf(stderr, "Failed to import PKCS#8 RSA key.\n"); + return false; + } + + derp = kExampleECKeyDER; + pkey.reset(d2i_PrivateKey(EVP_PKEY_EC, nullptr, &derp, + sizeof(kExampleECKeyDER))); + if (!pkey || derp != kExampleECKeyDER + sizeof(kExampleECKeyDER)) { + fprintf(stderr, "Failed to import raw EC key.\n"); + return false; + } + + derp = kExampleBadECKeyDER; + pkey.reset(d2i_PrivateKey(EVP_PKEY_EC, nullptr, &derp, + sizeof(kExampleBadECKeyDER))); + if (pkey) { + fprintf(stderr, "Imported invalid EC key.\n"); + return false; + } + ERR_clear_error(); + + // Copy the input into a |malloc|'d vector to flag memory errors. + std::vector copy(kExampleBadECKeyDER2, kExampleBadECKeyDER2 + + sizeof(kExampleBadECKeyDER2)); + derp = copy.data(); + pkey.reset(d2i_PrivateKey(EVP_PKEY_EC, nullptr, &derp, copy.size())); + if (pkey) { + fprintf(stderr, "Imported invalid EC key #2.\n"); + return false; + } + ERR_clear_error(); + + derp = kExampleRSAKeyPKCS8; + pkey.reset(d2i_PrivateKey(EVP_PKEY_EC, nullptr, &derp, + sizeof(kExampleRSAKeyPKCS8))); + if (pkey) { + fprintf(stderr, "Imported RSA key as EC key.\n"); + return false; + } + ERR_clear_error(); + + return true; +} + +int main(void) { + CRYPTO_library_init(); + + if (!TestEVP_DigestSignInit()) { + fprintf(stderr, "EVP_DigestSignInit failed\n"); + ERR_print_errors_fp(stderr); + return 1; + } + + if (!TestEVP_DigestVerifyInit()) { + fprintf(stderr, "EVP_DigestVerifyInit failed\n"); + ERR_print_errors_fp(stderr); + return 1; + } + + if (!TestVerifyRecover()) { + fprintf(stderr, "EVP_PKEY_verify_recover failed\n"); + ERR_print_errors_fp(stderr); + return 1; + } + + if (!Testd2i_AutoPrivateKey()) { + fprintf(stderr, "Testd2i_AutoPrivateKey failed\n"); + ERR_print_errors_fp(stderr); + return 1; + } + + if (!TestEVP_PKCS82PKEY()) { + fprintf(stderr, "TestEVP_PKCS82PKEY failed\n"); + ERR_print_errors_fp(stderr); + return 1; + } + + if (!TestEVPMarshalEmptyPublicKey()) { + fprintf(stderr, "TestEVPMarshalEmptyPublicKey failed\n"); + ERR_print_errors_fp(stderr); + return 1; + } + + if (!Testd2i_PrivateKey()) { + fprintf(stderr, "Testd2i_PrivateKey failed\n"); + ERR_print_errors_fp(stderr); + return 1; + } + + printf("PASS\n"); + return 0; +} diff --git a/external/boringssl/crypto/evp/evp_test.cc b/external/boringssl/crypto/evp/evp_test.cc new file mode 100644 index 0000000000..b01d1e47a1 --- /dev/null +++ b/external/boringssl/crypto/evp/evp_test.cc @@ -0,0 +1,265 @@ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project. + */ +/* ==================================================================== + * Copyright (c) 2015 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ + +#include + +#include +#include +#include +#include + +OPENSSL_MSVC_PRAGMA(warning(push)) +OPENSSL_MSVC_PRAGMA(warning(disable: 4702)) + +#include +#include +#include +#include + +OPENSSL_MSVC_PRAGMA(warning(pop)) + +#include +#include +#include +#include + +#include "../test/file_test.h" +#include "../test/scoped_types.h" + + +// evp_test dispatches between multiple test types. PrivateKey tests take a key +// name parameter and single block, decode it as a PEM private key, and save it +// under that key name. Decrypt, Sign, and Verify tests take a previously +// imported key name as parameter and test their respective operations. + +static const EVP_MD *GetDigest(FileTest *t, const std::string &name) { + if (name == "MD5") { + return EVP_md5(); + } else if (name == "SHA1") { + return EVP_sha1(); + } else if (name == "SHA224") { + return EVP_sha224(); + } else if (name == "SHA256") { + return EVP_sha256(); + } else if (name == "SHA384") { + return EVP_sha384(); + } else if (name == "SHA512") { + return EVP_sha512(); + } + t->PrintLine("Unknown digest: '%s'", name.c_str()); + return nullptr; +} + +static int GetKeyType(FileTest *t, const std::string &name) { + if (name == "RSA") { + return EVP_PKEY_RSA; + } + if (name == "EC") { + return EVP_PKEY_EC; + } + if (name == "DSA") { + return EVP_PKEY_DSA; + } + t->PrintLine("Unknown key type: '%s'", name.c_str()); + return EVP_PKEY_NONE; +} + +using KeyMap = std::map; + +static bool ImportKey(FileTest *t, KeyMap *key_map, + EVP_PKEY *(*parse_func)(CBS *cbs), + int (*marshal_func)(CBB *cbb, const EVP_PKEY *key)) { + std::vector input; + if (!t->GetBytes(&input, "Input")) { + return false; + } + + CBS cbs; + CBS_init(&cbs, input.data(), input.size()); + ScopedEVP_PKEY pkey(parse_func(&cbs)); + if (!pkey) { + return false; + } + + std::string key_type; + if (!t->GetAttribute(&key_type, "Type")) { + return false; + } + if (EVP_PKEY_id(pkey.get()) != GetKeyType(t, key_type)) { + t->PrintLine("Bad key type."); + return false; + } + + // The key must re-encode correctly. + ScopedCBB cbb; + uint8_t *der; + size_t der_len; + if (!CBB_init(cbb.get(), 0) || + !marshal_func(cbb.get(), pkey.get()) || + !CBB_finish(cbb.get(), &der, &der_len)) { + return false; + } + ScopedOpenSSLBytes free_der(der); + + std::vector output = input; + if (t->HasAttribute("Output") && + !t->GetBytes(&output, "Output")) { + return false; + } + if (!t->ExpectBytesEqual(output.data(), output.size(), der, der_len)) { + t->PrintLine("Re-encoding the key did not match."); + return false; + } + + // Save the key for future tests. + const std::string &key_name = t->GetParameter(); + if (key_map->count(key_name) > 0) { + t->PrintLine("Duplicate key '%s'.", key_name.c_str()); + return false; + } + (*key_map)[key_name] = std::move(pkey); + return true; +} + +static bool TestEVP(FileTest *t, void *arg) { + KeyMap *key_map = reinterpret_cast(arg); + if (t->GetType() == "PrivateKey") { + return ImportKey(t, key_map, EVP_parse_private_key, + EVP_marshal_private_key); + } + + if (t->GetType() == "PublicKey") { + return ImportKey(t, key_map, EVP_parse_public_key, EVP_marshal_public_key); + } + + int (*key_op_init)(EVP_PKEY_CTX *ctx); + int (*key_op)(EVP_PKEY_CTX *ctx, uint8_t *out, size_t *out_len, + const uint8_t *in, size_t in_len); + if (t->GetType() == "Decrypt") { + key_op_init = EVP_PKEY_decrypt_init; + key_op = EVP_PKEY_decrypt; + } else if (t->GetType() == "Sign") { + key_op_init = EVP_PKEY_sign_init; + key_op = EVP_PKEY_sign; + } else if (t->GetType() == "Verify") { + key_op_init = EVP_PKEY_verify_init; + key_op = nullptr; // EVP_PKEY_verify is handled differently. + } else { + t->PrintLine("Unknown test '%s'", t->GetType().c_str()); + return false; + } + + // Load the key. + const std::string &key_name = t->GetParameter(); + if (key_map->count(key_name) == 0) { + t->PrintLine("Could not find key '%s'.", key_name.c_str()); + return false; + } + EVP_PKEY *key = (*key_map)[key_name].get(); + + std::vector input, output; + if (!t->GetBytes(&input, "Input") || + !t->GetBytes(&output, "Output")) { + return false; + } + + // Set up the EVP_PKEY_CTX. + ScopedEVP_PKEY_CTX ctx(EVP_PKEY_CTX_new(key, nullptr)); + if (!ctx || !key_op_init(ctx.get())) { + return false; + } + if (t->HasAttribute("Digest")) { + const EVP_MD *digest = GetDigest(t, t->GetAttributeOrDie("Digest")); + if (digest == nullptr || + !EVP_PKEY_CTX_set_signature_md(ctx.get(), digest)) { + return false; + } + } + + if (t->GetType() == "Verify") { + if (!EVP_PKEY_verify(ctx.get(), output.data(), output.size(), input.data(), + input.size())) { + // ECDSA sometimes doesn't push an error code. Push one on the error queue + // so it's distinguishable from other errors. + OPENSSL_PUT_ERROR(USER, ERR_R_EVP_LIB); + return false; + } + return true; + } + + size_t len; + std::vector actual; + if (!key_op(ctx.get(), nullptr, &len, input.data(), input.size())) { + return false; + } + actual.resize(len); + if (!key_op(ctx.get(), actual.data(), &len, input.data(), input.size())) { + return false; + } + actual.resize(len); + if (!t->ExpectBytesEqual(output.data(), output.size(), actual.data(), len)) { + return false; + } + return true; +} + +int main(int argc, char **argv) { + CRYPTO_library_init(); + if (argc != 2) { + fprintf(stderr, "%s \n", argv[0]); + return 1; + } + + KeyMap map; + return FileTestMain(TestEVP, &map, argv[1]); +} diff --git a/external/boringssl/crypto/evp/evp_tests.txt b/external/boringssl/crypto/evp/evp_tests.txt new file mode 100644 index 0000000000..7c316d8146 --- /dev/null +++ b/external/boringssl/crypto/evp/evp_tests.txt @@ -0,0 +1,215 @@ +# Public key algorithm tests + +# Keys used for PKEY operations. + +# RSA 2048 bit key. +PrivateKey = RSA-2048 +Type = RSA +Input = 308204bc020100300d06092a864886f70d0101010500048204a6308204a20201000282010100cd0081ea7b2ae1ea06d59f7c73d9ffb94a09615c2e4ba7c636cef08dd3533ec3185525b015c769b99a77d6725bf9c3532a9b6e5f6627d5fb85160768d3dda9cbd35974511717dc3d309d2fc47ee41f97e32adb7f9dd864a1c4767a666ecd71bc1aacf5e7517f4b38594fea9b05e42d5ada9912008013e45316a4d9bb8ed086b88d28758bacaf922d46a868b485d239c9baeb0e2b64592710f42b2d1ea0a4b4802c0becab328f8a68b0073bdb546feea9809d2849912b390c1532bc7e29c7658f8175fae46f34332ff87bcab3e40649b98577869da0ea718353f0722754886913648760d122be676e0fc483dd20ffc31bda96a31966c9aa2e75ad03de47e1c44f02030100010282010060297ac7991b167a06d6b24758b8cbe208beb9b2d9ec9738bd80f90a2e35005dd7ce292d9e29ba885bd316fef1f20913bc0ac90d6b0808b2414d82104441d8624a33ce0233c8f780a48b375aff02d76712228a702484db3f9ebecccfbbee1709dba182800d949e9e4216e0bff3558388f8bd90da373a1d82743ec3fbdd1427fd16825a657a316912e8695365117ca2f845c909405fcac55f895fc15d20386c26ee78c9e99075029a178a6c1e4cf0c200e8a9cfb27e9d156f86e6c2adc22b1a84a1cd5ca5b2790875d79407c84b352395cb81cc3fed5bb043b69ede0c07204550025cee8c5f440170b6120bb48e0f747bcd8f522110850df043c428dfd187053102818100f6f961b47cbc035d3aedebc7de850a956b65ecdb9cf60764063f15aa48553c58d972fe6675056e35ddfdc37bf3b9f2f622ee271337256849c9bef2176fe8f7c3f8bb91ba374dd53baf3dec814d2bdec10c1fdc88cdd16876f26b1edfa3f094197edf4d42ff1fb2971103b898ca859c427287086a842ab410bb69cf2d35af6be302818100d47e724a7ff41048b270c2524a4101878b73159bb73d3dbc187b220e635b3534f96e243a184d93f860b6bfbb6b71c1ed9a1e1f458583023c301e96a692c1a08b53d0ec9ca910100d80451e3b7dc6a01bac4aecef8df798846bc235a08cbba2cf4c06804cc11219e95608c714e3f1430d491fadbba32a5751a04f97745834c9a502818021f2452bb9b95dfd028c914bf799f1ca77e89a95d50d3c16d384f8455f8bd7af9eb3dfa3d591d9842def235f7630a8e48c088ff6642e101794535a933e1e976fa8509fc728b2da0c4a1a08d7fcf37abaae1ff3001aca1dc1bbb05d9dffbaa1a09f7fb1eef38237d9ebccc722b9338436dde7119112798c26809c1a8dec4320610281801f7510aa62c2d8de4a3c53282781f41e02d0e8b402ae78432e449c48110161a11403f02d01880a8dcc938152d79721a4711a607ac4471ebf964810f95be47a45e60499e29f4c9773c83773404f606637728c2d0351bb03c326c8bb73a721e7fa5440ea2172bba1465fcc30dcb0d9f89930e815aa1f7f9729a857e00e0338dd590281804d1f0d756fe77e01099a652f50a88b7b685dc5bf00981d5d2376fd0c6fe29cd5b638734479305a73ad3c1599d39eae3bae035fbd6fed07c28de705933879a06e48e6a603686ed8e2560a5f6af1f2c24faf4aa960e382186f15eedce9a2491ae730680dd4cf778b70faa86826ab3223477cc91377b19a6d5a2eaea219760beed5 + +# The public half of the same key encoded as a SubjectPublicKeyInfo. +PublicKey = RSA-2048-SPKI +Type = RSA +Input = 30820122300d06092a864886f70d01010105000382010f003082010a0282010100cd0081ea7b2ae1ea06d59f7c73d9ffb94a09615c2e4ba7c636cef08dd3533ec3185525b015c769b99a77d6725bf9c3532a9b6e5f6627d5fb85160768d3dda9cbd35974511717dc3d309d2fc47ee41f97e32adb7f9dd864a1c4767a666ecd71bc1aacf5e7517f4b38594fea9b05e42d5ada9912008013e45316a4d9bb8ed086b88d28758bacaf922d46a868b485d239c9baeb0e2b64592710f42b2d1ea0a4b4802c0becab328f8a68b0073bdb546feea9809d2849912b390c1532bc7e29c7658f8175fae46f34332ff87bcab3e40649b98577869da0ea718353f0722754886913648760d122be676e0fc483dd20ffc31bda96a31966c9aa2e75ad03de47e1c44f0203010001 + +# The same key but with missing parameters rather than a NULL. +PublicKey = RSA-2048-SPKI-Invalid +Input = 30820120300b06092a864886f70d0101010382010f003082010a0282010100cd0081ea7b2ae1ea06d59f7c73d9ffb94a09615c2e4ba7c636cef08dd3533ec3185525b015c769b99a77d6725bf9c3532a9b6e5f6627d5fb85160768d3dda9cbd35974511717dc3d309d2fc47ee41f97e32adb7f9dd864a1c4767a666ecd71bc1aacf5e7517f4b38594fea9b05e42d5ada9912008013e45316a4d9bb8ed086b88d28758bacaf922d46a868b485d239c9baeb0e2b64592710f42b2d1ea0a4b4802c0becab328f8a68b0073bdb546feea9809d2849912b390c1532bc7e29c7658f8175fae46f34332ff87bcab3e40649b98577869da0ea718353f0722754886913648760d122be676e0fc483dd20ffc31bda96a31966c9aa2e75ad03de47e1c44f0203010001 +Error = DECODE_ERROR + +# The same key but with an incorrectly-encoded length prefix. +PublicKey = RSA-2048-SPKI-Invalid2 +Input = 3083000122300d06092a864886f70d01010105000382010f003082010a0282010100cd0081ea7b2ae1ea06d59f7c73d9ffb94a09615c2e4ba7c636cef08dd3533ec3185525b015c769b99a77d6725bf9c3532a9b6e5f6627d5fb85160768d3dda9cbd35974511717dc3d309d2fc47ee41f97e32adb7f9dd864a1c4767a666ecd71bc1aacf5e7517f4b38594fea9b05e42d5ada9912008013e45316a4d9bb8ed086b88d28758bacaf922d46a868b485d239c9baeb0e2b64592710f42b2d1ea0a4b4802c0becab328f8a68b0073bdb546feea9809d2849912b390c1532bc7e29c7658f8175fae46f34332ff87bcab3e40649b98577869da0ea718353f0722754886913648760d122be676e0fc483dd20ffc31bda96a31966c9aa2e75ad03de47e1c44f0203010001 +Error = DECODE_ERROR + +# EC P-256 key +PrivateKey = P-256 +Type = EC +Input = 308187020100301306072a8648ce3d020106082a8648ce3d030107046d306b02010104208a872fb62893c4d1ffc5b9f0f91758069f8352e08fa05a49f8db926cb5728725a144034200042c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78b33b920e95cdb664e990dcf0cfea0d94e2a8e6af9d0e58056e653104925b9fe6c9 + +# The same key as above with the optional public key omitted. +PrivateKey = P-256-MissingPublic +Type = EC +Input = 3041020100301306072a8648ce3d020106082a8648ce3d0301070427302502010104208a872fb62893c4d1ffc5b9f0f91758069f8352e08fa05a49f8db926cb5728725 + +# The same key as above with redundant parameters. +PrivateKey = P-256-ExtraParameters +Type = EC +Input = 308193020100301306072a8648ce3d020106082a8648ce3d0301070479307702010104208a872fb62893c4d1ffc5b9f0f91758069f8352e08fa05a49f8db926cb5728725a00a06082a8648ce3d030107a144034200042c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78b33b920e95cdb664e990dcf0cfea0d94e2a8e6af9d0e58056e653104925b9fe6c9 +# The key re-encodes with the parameters removed. +Output = 308187020100301306072a8648ce3d020106082a8648ce3d030107046d306b02010104208a872fb62893c4d1ffc5b9f0f91758069f8352e08fa05a49f8db926cb5728725a144034200042c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78b33b920e95cdb664e990dcf0cfea0d94e2a8e6af9d0e58056e653104925b9fe6c9 + +# The same key, but with the redundant parameters in the ECPrivateKey mismatched. +PrivateKey = P-256-BadInnerParameters +Input = 308190020100301306072a8648ce3d020106082a8648ce3d0301070476307402010104208a872fb62893c4d1ffc5b9f0f91758069f8352e08fa05a49f8db926cb5728725a00706052b81040022a144034200042c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78b33b920e95cdb664e990dcf0cfea0d94e2a8e6af9d0e58056e653104925b9fe6c9 +Error = GROUP_MISMATCH + +# The public half of the same key encoded as a PublicKey. +PublicKey = P-256-SPKI +Type = EC +Input = 3059301306072a8648ce3d020106082a8648ce3d030107034200042c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78b33b920e95cdb664e990dcf0cfea0d94e2a8e6af9d0e58056e653104925b9fe6c9 + +# The same as above, but with the curve explicitly spelled out. +PublicKey = P-256-SPKI +Input = 3082014b3082010306072a8648ce3d02013081f7020101302c06072a8648ce3d0101022100ffffffff00000001000000000000000000000000ffffffffffffffffffffffff305b0420ffffffff00000001000000000000000000000000fffffffffffffffffffffffc04205ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b031500c49d360886e704936a6678e1139d26b7819f7e900441046b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551020101034200042c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78b33b920e95cdb664e990dcf0cfea0d94e2a8e6af9d0e58056e653104925b9fe6c9 +Error = DECODE_ERROR + +# The same as above, but with trailing data after the curve name. +PublicKey = P-256-SPKI +Input = 305b301506072a8648ce3d020106082a8648ce3d0301070500034200042c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78b33b920e95cdb664e990dcf0cfea0d94e2a8e6af9d0e58056e653104925b9fe6c9 +Error = DECODE_ERROR + +# A DSA private key. +PrivateKey = DSA-1024 +Type = DSA +Input = 308202650201003082023906072a8648ce3804013082022c02820101009e12fab3de12213501dd82aa10ca2d101d2d4ebfef4d2a3f8daa0fe0cedad8d6af85616aa2f3252c0a2b5a6db09e6f14900e0ddb8311876dd8f9669525f99ed65949e184d5064793271169a228680b95ec12f59a8e20b21f2b58eb2a2012d35bde2ee351822fe8f32d0a330565dcce5c672b7259c14b2433d0b5b2ca2b2db0ab626e8f13f47fe0345d904e7294bb038e9ce21a9e580b83356278706cfe768436c69de149ccff98b4aab8cb4f6385c9f102ce59346eaeef27e0ad222d53d6e89cc8cde5776dd00057b03f2d88ab3cedbafd7b585f0b7f7835e17a3728bbf25ea62572f245dc111f3ce39cb6ffacc31b0a2790e7bde90224ea9b09315362af3d2b022100f381dcf53ebf724f8b2e5ca82c010fb4b5eda9358d0fd88ed278589488b54fc3028201000c402a725dcc3a62e02bf4cf43cd17f4a493591220223669cf4193edab423ad08dfb552e308a6a57a5ffbc7cd0fb2087f81f8df0cb08ab2133287d2b6968714a94f633c940845a48a3e16708dde761cc6a8eab2d84db21b6ea5b07681493cc9c31fbc368b243f6ddf8c932a8b4038f44e7b15ca876344a147859f2b43b39458668ad5e0a1a9a669546dd2812e3b3617a0aef99d58e3bb4cc87fd94225e01d2dcc469a77268146c51918f18e8b4d70aa1f0c7623bcc52cf3731d38641b2d2830b7eecb2f09552ff137d046e494e7f33c3590002b16d1b97d936fda28f90c3ed3ca35338168ac16f77c3c57adc2e8f7c6c2256e41a5f65450590dbb5bcf06d66610423022100b0c768702743bc51242993a971a52889795444f7c6452203d0ce84fe6117d46e + +# A DSA public key. +PublicKey = DSA-1024-SPKI +Type = DSA +Input = 308201b73082012c06072a8648ce3804013082011f02818100b3429b8b128c9079f9b72e86857e98d265e5d91661ed8b5f4cc56e5eed1e571da30186983a9dd76297eab73ee13a1db841f8800d04a7cab478af6cde2ea4a2868531af169a24858c6268efa39ceb7ed0d4227eb5bbb01124a2a5a26038c7bcfb8cc827f68f5202345166e4718596799b65c9def82828ce44e62e38e41a0d24b1021500c5a56c81ddd87f47e676546c56d05706421624cf0281810094de40d27314fe929e47ff9b1ac65cfc73ef38c4d381c890be6217b15039ae18190e6b421af8c0bda35a5cfd050f58ae2644adce83e68c8e5ba11729df56bbb21e227a60b816cc033fa799a38fe1ba5b4aa1801b6f841ce3df99feb3b4fb96950c960af13fa2ce920aabc12dd24ad2044a35063ea0e25f67f560f4cfbdc5598303818400028180258c30ebbb7f34fdc873ce679f6cea373c7886d75d4421b90920db034daedd292c64d8edd8cdbdd7f3ad23d74cfa2135247d0cef6ecf2e14f99e19d22a8c1266bd8fb8719c0e5667c716c45c7adbdabe548085bdad2dfee636f8d52fd6adb2193df6c4f0520fbd171b91882e0e4f321f8250ffecf4dbea00e114427d3ef96c1a + +# The same key as above, but without the parameters. +PublicKey = DSA-1024-SPKI-No-Params +Type = DSA +Input = 308192300906072a8648ce38040103818400028180258c30ebbb7f34fdc873ce679f6cea373c7886d75d4421b90920db034daedd292c64d8edd8cdbdd7f3ad23d74cfa2135247d0cef6ecf2e14f99e19d22a8c1266bd8fb8719c0e5667c716c45c7adbdabe548085bdad2dfee636f8d52fd6adb2193df6c4f0520fbd171b91882e0e4f321f8250ffecf4dbea00e114427d3ef96c1a + + +# RSA tests + +Sign = RSA-2048 +Digest = SHA1 +Input = "0123456789ABCDEF1234" +Output = c09d402423cbf233d26cae21f954547bc43fe80fd41360a0336cfdbe9aedad05bef6fd2eaee6cd60089a52482d4809a238149520df3bdde4cb9e23d9307b05c0a6f327052325a29adf2cc95b66523be7024e2a585c3d4db15dfbe146efe0ecdc0402e33fe5d40324ee96c5c3edd374a15cdc0f5d84aa243c0f07e188c6518fbfceae158a9943be398e31097da81b62074f626eff738be6160741d5a26957a482b3251fd85d8df78b98148459de10aa93305dbb4a5230aa1da291a9b0e481918f99b7638d72bb687f97661d304ae145d64a474437a4ef39d7b8059332ddeb07e92bf6e0e3acaf8afedc93795e4511737ec1e7aab6d5bc9466afc950c1c17b48ad + +Verify = RSA-2048 +Digest = SHA1 +Input = "0123456789ABCDEF1234" +Output = c09d402423cbf233d26cae21f954547bc43fe80fd41360a0336cfdbe9aedad05bef6fd2eaee6cd60089a52482d4809a238149520df3bdde4cb9e23d9307b05c0a6f327052325a29adf2cc95b66523be7024e2a585c3d4db15dfbe146efe0ecdc0402e33fe5d40324ee96c5c3edd374a15cdc0f5d84aa243c0f07e188c6518fbfceae158a9943be398e31097da81b62074f626eff738be6160741d5a26957a482b3251fd85d8df78b98148459de10aa93305dbb4a5230aa1da291a9b0e481918f99b7638d72bb687f97661d304ae145d64a474437a4ef39d7b8059332ddeb07e92bf6e0e3acaf8afedc93795e4511737ec1e7aab6d5bc9466afc950c1c17b48ad + +Verify = RSA-2048-SPKI +Digest = SHA1 +Input = "0123456789ABCDEF1234" +Output = c09d402423cbf233d26cae21f954547bc43fe80fd41360a0336cfdbe9aedad05bef6fd2eaee6cd60089a52482d4809a238149520df3bdde4cb9e23d9307b05c0a6f327052325a29adf2cc95b66523be7024e2a585c3d4db15dfbe146efe0ecdc0402e33fe5d40324ee96c5c3edd374a15cdc0f5d84aa243c0f07e188c6518fbfceae158a9943be398e31097da81b62074f626eff738be6160741d5a26957a482b3251fd85d8df78b98148459de10aa93305dbb4a5230aa1da291a9b0e481918f99b7638d72bb687f97661d304ae145d64a474437a4ef39d7b8059332ddeb07e92bf6e0e3acaf8afedc93795e4511737ec1e7aab6d5bc9466afc950c1c17b48ad + +# Digest too long +Sign = RSA-2048 +Digest = SHA1 +Input = "0123456789ABCDEF12345" +Output = +Error = INVALID_DIGEST_LENGTH + +# Digest too short +Sign = RSA-2048 +Digest = SHA1 +Input = "0123456789ABCDEF12345" +Output = +Error = INVALID_DIGEST_LENGTH + +# Mismatched digest +Verify = RSA-2048 +Digest = SHA1 +Input = "0123456789ABCDEF1233" +Output = c09d402423cbf233d26cae21f954547bc43fe80fd41360a0336cfdbe9aedad05bef6fd2eaee6cd60089a52482d4809a238149520df3bdde4cb9e23d9307b05c0a6f327052325a29adf2cc95b66523be7024e2a585c3d4db15dfbe146efe0ecdc0402e33fe5d40324ee96c5c3edd374a15cdc0f5d84aa243c0f07e188c6518fbfceae158a9943be398e31097da81b62074f626eff738be6160741d5a26957a482b3251fd85d8df78b98148459de10aa93305dbb4a5230aa1da291a9b0e481918f99b7638d72bb687f97661d304ae145d64a474437a4ef39d7b8059332ddeb07e92bf6e0e3acaf8afedc93795e4511737ec1e7aab6d5bc9466afc950c1c17b48ad +Error = BAD_SIGNATURE + +# Corrupted signature +Verify = RSA-2048 +Digest = SHA1 +Input = "0123456789ABCDEF1233" +Output = c09d402423cbf233d26cae21f954547bc43fe80fd41360a0336cfdbe9aedad05bef6fd2eaee6cd60089a52482d4809a238149520df3bdde4cb9e23d9307b05c0a6f327052325a29adf2cc95b66523be7024e2a585c3d4db15dfbe146efe0ecdc0402e33fe5d40324ee96c5c3edd374a15cdc0f5d84aa243c0f07e188c6518fbfceae158a9943be398e31097da81b62074f626eff738be6160741d5a26957a482b3251fd85d8df78b98148459de10aa93305dbb4a5230aa1da291a9b0e481918f99b7638d72bb687f97661d304ae145d64a474437a4ef39d7b8059332ddeb07e92bf6e0e3acaf8afedc93795e4511737ec1e7aab6d5bc9466afc950c1c17b48ae +Error = BLOCK_TYPE_IS_NOT_01 + +# parameter missing (NOTE: this differs from upstream) +Verify = RSA-2048 +Digest = SHA1 +Input = "0123456789ABCDEF1234" +Output = 3ec3fc29eb6e122bd7aa361cd09fe1bcbe85311096a7b9e4799cedfb2351ce0ab7fe4e75b4f6b37f67edd9c60c800f9ab941c0c157d7d880ca9de40c951d60fd293ae220d4bc510b1572d6e85a1bbbd8605b52e05f1c64fafdae59a1c2fbed214b7844d0134619de62851d5a0522e32e556e5950f3f97b8150e3f0dffee612c924201c27cd9bc8b423a71533380c276d3d59fcba35a2e80a1a192ec266a6c2255012cd86a349fe90a542b355fa3355b04da6cdf1df77f0e7bd44a90e880e1760266d233e465226f5db1c68857847d82072861ee266ddfc2e596845b77e1803274a579835ab5e4975d81d20b7df9cec7795489e4a2bdb8c1cf6a6b359945ac92c +Error = BAD_SIGNATURE + +# embedded digest too long +Verify = RSA-2048 +Digest = SHA1 +Input = "0123456789ABCDEF1234" +Output = afec9a0d5330a08f54283bb4a9d4e7e7e70fc1342336c4c766fba713f66970151c6e27413c48c33864ea45a0238787004f338ed3e21b53b0fe9c1151c42c388cbc7cba5a06b706c407a5b48324fbe994dc7afc3a19fb3d2841e66222596c14cd72a0f0a7455a019d8eb554f59c0183f9552b75aa96fee8bf935945e079ca283d2bd3534a86f11351f6d6181fbf433e5b01a6d1422145c7a72214d3aacdd5d3af12b2d6bf6438f9f9a64010d8aeed801c87f0859412b236150b86a545f7239be022f4a7ad246b59df87514294cb4a4c7c5a997ee53c66054d9f38ca4e76c1f7af83c30f737ef70f83a45aebe18238ddb95e1998814ca4fc72388f1533147c169d +Error = BAD_SIGNATURE + +# embedded digest too short +Verify = RSA-2048 +Digest = SHA1 +Input = "0123456789ABCDEF1234" +Output = afec9a0d5330a08f54283bb4a9d4e7e7e70fc1342336c4c766fba713f66970151c6e27413c48c33864ea45a0238787004f338ed3e21b53b0fe9c1151c42c388cbc7cba5a06b706c407a5b48324fbe994dc7afc3a19fb3d2841e66222596c14cd72a0f0a7455a019d8eb554f59c0183f9552b75aa96fee8bf935945e079ca283d2bd3534a86f11351f6d6181fbf433e5b01a6d1422145c7a72214d3aacdd5d3af12b2d6bf6438f9f9a64010d8aeed801c87f0859412b236150b86a545f7239be022f4a7ad246b59df87514294cb4a4c7c5a997ee53c66054d9f38ca4e76c1f7af83c30f737ef70f83a45aebe18238ddb95e1998814ca4fc72388f1533147c169d +Error = BAD_SIGNATURE + +# Garbage after DigestInfo +Verify = RSA-2048 +Digest = SHA1 +Input = "0123456789ABCDEF1234" +Output = 9ee34872d4271a7d8808af0a4052a145a6d6a8437d00da3ed14428c7f087cd39f4d43334c41af63e7fa1ba363fee7bcef401d9d36a662abbab55ce89a696e1be0dfa19a5d09ca617dd488787b6048baaefeb29bc8688b2fe3882de2b77c905b5a8b56cf9616041e5ec934ba6de863efe93acc4eef783fe7f72a00fa65d6093ed32bf98ce527e62ccb1d56317f4be18b7e0f55d7c36617d2d0678a306e3350956b662ac15df45215dd8f6b314babb9788e6c272fa461e4c9b512a11a4b92bc77c3a4c95c903fccb238794eca5c750477bf56ea6ee6a167367d881b485ae3889e7c489af8fdf38e0c0f2aed780831182e34abedd43c39281b290774bf35cc25274 +Error = BAD_SIGNATURE + +# invalid tag for parameter +Verify = RSA-2048 +Digest = SHA1 +Input = "0123456789ABCDEF1234" +Output = 49525db4d44c755e560cba980b1d85ea604b0e077fcadd4ba44072a3487bbddb835016200a7d8739cce2dc3223d9c20cbdd25059ab02277f1f21318efd18e21038ec89aa9d40680987129e8b41ba33bceb86518bdf47268b921cce2037acabca6575d832499538d6f40cdba0d40bd7f4d8ea6ca6e2eec87f294efc971407857f5d7db09f6a7b31e301f571c6d82a5e3d08d2bb3a36e673d28b910f5bec57f0fcc4d968fd7c94d0b9226dec17f5192ad8b42bcab6f26e1bea1fdc3b958199acb00f14ebcb2a352f3afcedd4c09000128a603bbeb9696dea13040445253972d46237a25c7845e3b464e6984c2348ea1f1210a9ff0b00d2d72b50db00c009bb39f9 +Error = BAD_SIGNATURE + +# EC tests + +Verify = P-256 +Digest = SHA1 +Input = "0123456789ABCDEF1234" +Output = 3045022100b1d1cb1a577035bccdd5a86c6148c2cc7c633cd42b7234139b593076d041e15202201898cdd52b41ca502098184b409cf83a21bc945006746e3b7cea52234e043ec8 + +Verify = P-256-SPKI +Digest = SHA1 +Input = "0123456789ABCDEF1234" +Output = 3045022100b1d1cb1a577035bccdd5a86c6148c2cc7c633cd42b7234139b593076d041e15202201898cdd52b41ca502098184b409cf83a21bc945006746e3b7cea52234e043ec8 + +# Digest too long +Verify = P-256 +Digest = SHA1 +Input = "0123456789ABCDEF12345" +Output = 3045022100b1d1cb1a577035bccdd5a86c6148c2cc7c633cd42b7234139b593076d041e15202201898cdd52b41ca502098184b409cf83a21bc945006746e3b7cea52234e043ec8 +# This operation fails without an error code, so ERR_R_EVP_LIB is surfaced. +Error = public key routines + +# Digest too short +Verify = P-256 +Digest = SHA1 +Input = "0123456789ABCDEF123" +Output = 3045022100b1d1cb1a577035bccdd5a86c6148c2cc7c633cd42b7234139b593076d041e15202201898cdd52b41ca502098184b409cf83a21bc945006746e3b7cea52234e043ec8 +# This operation fails without an error code, so ERR_R_EVP_LIB is surfaced. +Error = public key routines + +# Digest invalid +Verify = P-256 +Digest = SHA1 +Input = "0123456789ABCDEF1235" +Output = 3045022100b1d1cb1a577035bccdd5a86c6148c2cc7c633cd42b7234139b593076d041e15202201898cdd52b41ca502098184b409cf83a21bc945006746e3b7cea52234e043ec8 +# This operation fails without an error code, so ERR_R_EVP_LIB is surfaced. +Error = public key routines + +# Invalid signature +Verify = P-256 +Digest = SHA1 +Input = "0123456789ABCDEF1234" +Output = 3045022100b1d1cb1a577035bccdd5a86c6148c2cc7c633cd42b7234139b593076d041e15202201898cdd52b41ca502098184b409cf83a21bc945006746e3b7cea52234e043ec7 +# This operation fails without an error code, so ERR_R_EVP_LIB is surfaced. +Error = public key routines + +# Garbage after signature +Verify = P-256 +Digest = SHA1 +Input = "0123456789ABCDEF1234" +Output = 3045022100b1d1cb1a577035bccdd5a86c6148c2cc7c633cd42b7234139b593076d041e15202201898cdd52b41ca502098184b409cf83a21bc945006746e3b7cea52234e043ec800 +# This operation fails without an error code, so ERR_R_EVP_LIB is surfaced. +Error = BAD_SIGNATURE + +# BER signature +Verify = P-256 +Digest = SHA1 +Input = "0123456789ABCDEF1234" +Output = 3080022100b1d1cb1a577035bccdd5a86c6148c2cc7c633cd42b7234139b593076d041e15202201898cdd52b41ca502098184b409cf83a21bc945006746e3b7cea52234e043ec80000 +Error = BAD_SIGNATURE diff --git a/external/boringssl/crypto/evp/internal.h b/external/boringssl/crypto/evp/internal.h new file mode 100644 index 0000000000..0783143d39 --- /dev/null +++ b/external/boringssl/crypto/evp/internal.h @@ -0,0 +1,237 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_EVP_INTERNAL_H +#define OPENSSL_HEADER_EVP_INTERNAL_H + +#include + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +struct evp_pkey_asn1_method_st { + int pkey_id; + uint8_t oid[9]; + uint8_t oid_len; + + /* pub_decode decodes |params| and |key| as a SubjectPublicKeyInfo + * and writes the result into |out|. It returns one on success and zero on + * error. |params| is the AlgorithmIdentifier after the OBJECT IDENTIFIER + * type field, and |key| is the contents of the subjectPublicKey with the + * leading padding byte checked and removed. Although X.509 uses BIT STRINGs + * to represent SubjectPublicKeyInfo, every key type defined encodes the key + * as a byte string with the same conversion to BIT STRING. */ + int (*pub_decode)(EVP_PKEY *out, CBS *params, CBS *key); + + /* pub_encode encodes |key| as a SubjectPublicKeyInfo and appends the result + * to |out|. It returns one on success and zero on error. */ + int (*pub_encode)(CBB *out, const EVP_PKEY *key); + + int (*pub_cmp)(const EVP_PKEY *a, const EVP_PKEY *b); + + /* priv_decode decodes |params| and |key| as a PrivateKeyInfo and writes the + * result into |out|. It returns one on success and zero on error. |params| is + * the AlgorithmIdentifier after the OBJECT IDENTIFIER type field, and |key| + * is the contents of the OCTET STRING privateKey field. */ + int (*priv_decode)(EVP_PKEY *out, CBS *params, CBS *key); + + /* priv_encode encodes |key| as a PrivateKeyInfo and appends the result to + * |out|. It returns one on success and zero on error. */ + int (*priv_encode)(CBB *out, const EVP_PKEY *key); + + /* pkey_opaque returns 1 if the |pk| is opaque. Opaque keys are backed by + * custom implementations which do not expose key material and parameters.*/ + int (*pkey_opaque)(const EVP_PKEY *pk); + + /* pkey_supports_digest returns one if |pkey| supports digests of + * type |md|. This is intended for use with EVP_PKEYs backing custom + * implementations which can't sign all digests. If null, it is + * assumed that all digests are supported. */ + int (*pkey_supports_digest)(const EVP_PKEY *pkey, const EVP_MD *md); + + int (*pkey_size)(const EVP_PKEY *pk); + int (*pkey_bits)(const EVP_PKEY *pk); + + int (*param_missing)(const EVP_PKEY *pk); + int (*param_copy)(EVP_PKEY *to, const EVP_PKEY *from); + int (*param_cmp)(const EVP_PKEY *a, const EVP_PKEY *b); + + void (*pkey_free)(EVP_PKEY *pkey); +} /* EVP_PKEY_ASN1_METHOD */; + + +#define EVP_PKEY_OP_UNDEFINED 0 +#define EVP_PKEY_OP_KEYGEN (1 << 2) +#define EVP_PKEY_OP_SIGN (1 << 3) +#define EVP_PKEY_OP_VERIFY (1 << 4) +#define EVP_PKEY_OP_VERIFYRECOVER (1 << 5) +#define EVP_PKEY_OP_ENCRYPT (1 << 6) +#define EVP_PKEY_OP_DECRYPT (1 << 7) +#define EVP_PKEY_OP_DERIVE (1 << 8) + +#define EVP_PKEY_OP_TYPE_SIG \ + (EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY | EVP_PKEY_OP_VERIFYRECOVER) + +#define EVP_PKEY_OP_TYPE_CRYPT (EVP_PKEY_OP_ENCRYPT | EVP_PKEY_OP_DECRYPT) + +#define EVP_PKEY_OP_TYPE_NOGEN \ + (EVP_PKEY_OP_SIG | EVP_PKEY_OP_CRYPT | EVP_PKEY_OP_DERIVE) + +#define EVP_PKEY_OP_TYPE_GEN EVP_PKEY_OP_KEYGEN + +/* EVP_PKEY_CTX_ctrl performs |cmd| on |ctx|. The |keytype| and |optype| + * arguments can be -1 to specify that any type and operation are acceptable, + * otherwise |keytype| must match the type of |ctx| and the bits of |optype| + * must intersect the operation flags set on |ctx|. + * + * The |p1| and |p2| arguments depend on the value of |cmd|. + * + * It returns one on success and zero on error. */ +OPENSSL_EXPORT int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype, + int cmd, int p1, void *p2); + +#define EVP_PKEY_CTRL_MD 1 +#define EVP_PKEY_CTRL_GET_MD 2 + +/* EVP_PKEY_CTRL_PEER_KEY is called with different values of |p1|: + * 0: Is called from |EVP_PKEY_derive_set_peer| and |p2| contains a peer key. + * If the return value is <= 0, the key is rejected. + * 1: Is called at the end of |EVP_PKEY_derive_set_peer| and |p2| contains a + * peer key. If the return value is <= 0, the key is rejected. + * 2: Is called with |p2| == NULL to test whether the peer's key was used. + * (EC)DH always return one in this case. + * 3: Is called with |p2| == NULL to set whether the peer's key was used. + * (EC)DH always return one in this case. This was only used for GOST. */ +#define EVP_PKEY_CTRL_PEER_KEY 3 + +/* EVP_PKEY_ALG_CTRL is the base value from which key-type specific ctrl + * commands are numbered. */ +#define EVP_PKEY_ALG_CTRL 0x1000 + +#define EVP_PKEY_CTRL_RSA_PADDING (EVP_PKEY_ALG_CTRL + 1) +#define EVP_PKEY_CTRL_GET_RSA_PADDING (EVP_PKEY_ALG_CTRL + 2) +#define EVP_PKEY_CTRL_RSA_PSS_SALTLEN (EVP_PKEY_ALG_CTRL + 3) +#define EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN (EVP_PKEY_ALG_CTRL + 4) +#define EVP_PKEY_CTRL_RSA_KEYGEN_BITS (EVP_PKEY_ALG_CTRL + 5) +#define EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP (EVP_PKEY_ALG_CTRL + 6) +#define EVP_PKEY_CTRL_RSA_OAEP_MD (EVP_PKEY_ALG_CTRL + 7) +#define EVP_PKEY_CTRL_GET_RSA_OAEP_MD (EVP_PKEY_ALG_CTRL + 8) +#define EVP_PKEY_CTRL_RSA_MGF1_MD (EVP_PKEY_ALG_CTRL + 9) +#define EVP_PKEY_CTRL_GET_RSA_MGF1_MD (EVP_PKEY_ALG_CTRL + 10) +#define EVP_PKEY_CTRL_RSA_OAEP_LABEL (EVP_PKEY_ALG_CTRL + 11) +#define EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL (EVP_PKEY_ALG_CTRL + 12) + +struct evp_pkey_ctx_st { + /* Method associated with this operation */ + const EVP_PKEY_METHOD *pmeth; + /* Engine that implements this method or NULL if builtin */ + ENGINE *engine; + /* Key: may be NULL */ + EVP_PKEY *pkey; + /* Peer key for key agreement, may be NULL */ + EVP_PKEY *peerkey; + /* operation contains one of the |EVP_PKEY_OP_*| values. */ + int operation; + /* Algorithm specific data */ + void *data; +} /* EVP_PKEY_CTX */; + +struct evp_pkey_method_st { + int pkey_id; + + int (*init)(EVP_PKEY_CTX *ctx); + int (*copy)(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src); + void (*cleanup)(EVP_PKEY_CTX *ctx); + + int (*keygen)(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey); + + int (*sign)(EVP_PKEY_CTX *ctx, uint8_t *sig, size_t *siglen, + const uint8_t *tbs, size_t tbslen); + + int (*verify)(EVP_PKEY_CTX *ctx, const uint8_t *sig, size_t siglen, + const uint8_t *tbs, size_t tbslen); + + int (*verify_recover)(EVP_PKEY_CTX *ctx, uint8_t *out, size_t *out_len, + const uint8_t *sig, size_t sig_len); + + int (*encrypt)(EVP_PKEY_CTX *ctx, uint8_t *out, size_t *outlen, + const uint8_t *in, size_t inlen); + + int (*decrypt)(EVP_PKEY_CTX *ctx, uint8_t *out, size_t *outlen, + const uint8_t *in, size_t inlen); + + int (*derive)(EVP_PKEY_CTX *ctx, uint8_t *key, size_t *keylen); + + int (*ctrl)(EVP_PKEY_CTX *ctx, int type, int p1, void *p2); +} /* EVP_PKEY_METHOD */; + +extern const EVP_PKEY_ASN1_METHOD dsa_asn1_meth; +extern const EVP_PKEY_ASN1_METHOD ec_asn1_meth; +extern const EVP_PKEY_ASN1_METHOD rsa_asn1_meth; + +extern const EVP_PKEY_METHOD rsa_pkey_meth; +extern const EVP_PKEY_METHOD ec_pkey_meth; + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_EVP_INTERNAL_H */ diff --git a/external/boringssl/crypto/evp/p_dsa_asn1.c b/external/boringssl/crypto/evp/p_dsa_asn1.c new file mode 100644 index 0000000000..1f022f1a81 --- /dev/null +++ b/external/boringssl/crypto/evp/p_dsa_asn1.c @@ -0,0 +1,268 @@ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project + * 2006. + */ +/* ==================================================================== + * Copyright (c) 2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include +#include +#include +#include + +#include "internal.h" + + +static int dsa_pub_decode(EVP_PKEY *out, CBS *params, CBS *key) { + /* See RFC 3279, section 2.3.2. */ + + /* Parameters may or may not be present. */ + DSA *dsa; + if (CBS_len(params) == 0) { + dsa = DSA_new(); + if (dsa == NULL) { + return 0; + } + } else { + dsa = DSA_parse_parameters(params); + if (dsa == NULL || CBS_len(params) != 0) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + goto err; + } + } + + dsa->pub_key = BN_new(); + if (dsa->pub_key == NULL) { + goto err; + } + + if (!BN_parse_asn1_unsigned(key, dsa->pub_key) || + CBS_len(key) != 0) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + goto err; + } + + EVP_PKEY_assign_DSA(out, dsa); + return 1; + +err: + DSA_free(dsa); + return 0; +} + +static int dsa_pub_encode(CBB *out, const EVP_PKEY *key) { + const DSA *dsa = key->pkey.dsa; + const int has_params = dsa->p != NULL && dsa->q != NULL && dsa->g != NULL; + + /* See RFC 5480, section 2. */ + CBB spki, algorithm, oid, key_bitstring; + if (!CBB_add_asn1(out, &spki, CBS_ASN1_SEQUENCE) || + !CBB_add_asn1(&spki, &algorithm, CBS_ASN1_SEQUENCE) || + !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) || + !CBB_add_bytes(&oid, dsa_asn1_meth.oid, dsa_asn1_meth.oid_len) || + (has_params && + !DSA_marshal_parameters(&algorithm, dsa)) || + !CBB_add_asn1(&spki, &key_bitstring, CBS_ASN1_BITSTRING) || + !CBB_add_u8(&key_bitstring, 0 /* padding */) || + !BN_marshal_asn1(&key_bitstring, dsa->pub_key) || + !CBB_flush(out)) { + OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR); + return 0; + } + + return 1; +} + +static int dsa_priv_decode(EVP_PKEY *out, CBS *params, CBS *key) { + /* See PKCS#11, v2.40, section 2.5. */ + + /* Decode parameters. */ + BN_CTX *ctx = NULL; + DSA *dsa = DSA_parse_parameters(params); + if (dsa == NULL || CBS_len(params) != 0) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + goto err; + } + + dsa->priv_key = BN_new(); + dsa->pub_key = BN_new(); + if (dsa->priv_key == NULL || dsa->pub_key == NULL) { + goto err; + } + + /* Decode the key. */ + if (!BN_parse_asn1_unsigned(key, dsa->priv_key) || + CBS_len(key) != 0) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + goto err; + } + + /* Calculate the public key. */ + ctx = BN_CTX_new(); + if (ctx == NULL || + !BN_mod_exp(dsa->pub_key, dsa->g, dsa->priv_key, dsa->p, ctx)) { + goto err; + } + + BN_CTX_free(ctx); + EVP_PKEY_assign_DSA(out, dsa); + return 1; + +err: + BN_CTX_free(ctx); + DSA_free(dsa); + return 0; +} + +static int dsa_priv_encode(CBB *out, const EVP_PKEY *key) { + const DSA *dsa = key->pkey.dsa; + if (dsa == NULL || dsa->priv_key == NULL) { + OPENSSL_PUT_ERROR(EVP, EVP_R_MISSING_PARAMETERS); + return 0; + } + + /* See PKCS#11, v2.40, section 2.5. */ + CBB pkcs8, algorithm, oid, private_key; + if (!CBB_add_asn1(out, &pkcs8, CBS_ASN1_SEQUENCE) || + !CBB_add_asn1_uint64(&pkcs8, 0 /* version */) || + !CBB_add_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) || + !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) || + !CBB_add_bytes(&oid, dsa_asn1_meth.oid, dsa_asn1_meth.oid_len) || + !DSA_marshal_parameters(&algorithm, dsa) || + !CBB_add_asn1(&pkcs8, &private_key, CBS_ASN1_OCTETSTRING) || + !BN_marshal_asn1(&private_key, dsa->priv_key) || + !CBB_flush(out)) { + OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR); + return 0; + } + + return 1; +} + +static int int_dsa_size(const EVP_PKEY *pkey) { + return DSA_size(pkey->pkey.dsa); +} + +static int dsa_bits(const EVP_PKEY *pkey) { + return BN_num_bits(pkey->pkey.dsa->p); +} + +static int dsa_missing_parameters(const EVP_PKEY *pkey) { + DSA *dsa; + dsa = pkey->pkey.dsa; + if (dsa->p == NULL || dsa->q == NULL || dsa->g == NULL) { + return 1; + } + return 0; +} + +static int dup_bn_into(BIGNUM **out, BIGNUM *src) { + BIGNUM *a; + + a = BN_dup(src); + if (a == NULL) { + return 0; + } + BN_free(*out); + *out = a; + + return 1; +} + +static int dsa_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) { + if (!dup_bn_into(&to->pkey.dsa->p, from->pkey.dsa->p) || + !dup_bn_into(&to->pkey.dsa->q, from->pkey.dsa->q) || + !dup_bn_into(&to->pkey.dsa->g, from->pkey.dsa->g)) { + return 0; + } + + return 1; +} + +static int dsa_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b) { + return BN_cmp(a->pkey.dsa->p, b->pkey.dsa->p) == 0 && + BN_cmp(a->pkey.dsa->q, b->pkey.dsa->q) == 0 && + BN_cmp(a->pkey.dsa->g, b->pkey.dsa->g) == 0; +} + +static int dsa_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) { + return BN_cmp(b->pkey.dsa->pub_key, a->pkey.dsa->pub_key) == 0; +} + +static void int_dsa_free(EVP_PKEY *pkey) { DSA_free(pkey->pkey.dsa); } + +const EVP_PKEY_ASN1_METHOD dsa_asn1_meth = { + EVP_PKEY_DSA, + /* 1.2.840.10040.4.1 */ + {0x2a, 0x86, 0x48, 0xce, 0x38, 0x04, 0x01}, 7, + + dsa_pub_decode, + dsa_pub_encode, + dsa_pub_cmp, + + dsa_priv_decode, + dsa_priv_encode, + + NULL /* pkey_opaque */, + NULL /* pkey_supports_digest */, + + int_dsa_size, + dsa_bits, + + dsa_missing_parameters, + dsa_copy_parameters, + dsa_cmp_parameters, + + int_dsa_free, +}; diff --git a/external/boringssl/crypto/evp/p_ec.c b/external/boringssl/crypto/evp/p_ec.c new file mode 100644 index 0000000000..f92c87cf25 --- /dev/null +++ b/external/boringssl/crypto/evp/p_ec.c @@ -0,0 +1,236 @@ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 2006. + */ +/* ==================================================================== + * Copyright (c) 2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "internal.h" +#include "../ec/internal.h" + + +typedef struct { + /* message digest */ + const EVP_MD *md; +} EC_PKEY_CTX; + + +static int pkey_ec_init(EVP_PKEY_CTX *ctx) { + EC_PKEY_CTX *dctx; + dctx = OPENSSL_malloc(sizeof(EC_PKEY_CTX)); + if (!dctx) { + return 0; + } + memset(dctx, 0, sizeof(EC_PKEY_CTX)); + + ctx->data = dctx; + + return 1; +} + +static int pkey_ec_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) { + EC_PKEY_CTX *dctx, *sctx; + if (!pkey_ec_init(dst)) { + return 0; + } + sctx = src->data; + dctx = dst->data; + + dctx->md = sctx->md; + + return 1; +} + +static void pkey_ec_cleanup(EVP_PKEY_CTX *ctx) { + EC_PKEY_CTX *dctx = ctx->data; + if (!dctx) { + return; + } + + OPENSSL_free(dctx); +} + +static int pkey_ec_sign(EVP_PKEY_CTX *ctx, uint8_t *sig, size_t *siglen, + const uint8_t *tbs, size_t tbslen) { + unsigned int sltmp; + EC_KEY *ec = ctx->pkey->pkey.ec; + + if (!sig) { + *siglen = ECDSA_size(ec); + return 1; + } else if (*siglen < (size_t)ECDSA_size(ec)) { + OPENSSL_PUT_ERROR(EVP, EVP_R_BUFFER_TOO_SMALL); + return 0; + } + + if (!ECDSA_sign(0, tbs, tbslen, sig, &sltmp, ec)) { + return 0; + } + *siglen = (size_t)sltmp; + return 1; +} + +static int pkey_ec_verify(EVP_PKEY_CTX *ctx, const uint8_t *sig, size_t siglen, + const uint8_t *tbs, size_t tbslen) { + return ECDSA_verify(0, tbs, tbslen, sig, siglen, ctx->pkey->pkey.ec); +} + +static int pkey_ec_derive(EVP_PKEY_CTX *ctx, uint8_t *key, + size_t *keylen) { + int ret; + size_t outlen; + const EC_POINT *pubkey = NULL; + EC_KEY *eckey; + + if (!ctx->pkey || !ctx->peerkey) { + OPENSSL_PUT_ERROR(EVP, EVP_R_KEYS_NOT_SET); + return 0; + } + + eckey = ctx->pkey->pkey.ec; + + if (!key) { + const EC_GROUP *group; + group = EC_KEY_get0_group(eckey); + *keylen = (EC_GROUP_get_degree(group) + 7) / 8; + return 1; + } + pubkey = EC_KEY_get0_public_key(ctx->peerkey->pkey.ec); + + /* NB: unlike PKCS#3 DH, if *outlen is less than maximum size this is + * not an error, the result is truncated. */ + + outlen = *keylen; + + ret = ECDH_compute_key(key, outlen, pubkey, eckey, 0); + if (ret < 0) { + return 0; + } + *keylen = ret; + return 1; +} + +static int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) { + EC_PKEY_CTX *dctx = ctx->data; + + switch (type) { + case EVP_PKEY_CTRL_MD: + if (EVP_MD_type((const EVP_MD *)p2) != NID_sha1 && + EVP_MD_type((const EVP_MD *)p2) != NID_ecdsa_with_SHA1 && + EVP_MD_type((const EVP_MD *)p2) != NID_sha224 && + EVP_MD_type((const EVP_MD *)p2) != NID_sha256 && + EVP_MD_type((const EVP_MD *)p2) != NID_sha384 && + EVP_MD_type((const EVP_MD *)p2) != NID_sha512) { + OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_DIGEST_TYPE); + return 0; + } + dctx->md = p2; + return 1; + + case EVP_PKEY_CTRL_GET_MD: + *(const EVP_MD **)p2 = dctx->md; + return 1; + + case EVP_PKEY_CTRL_PEER_KEY: + /* Default behaviour is OK */ + return 1; + + default: + OPENSSL_PUT_ERROR(EVP, EVP_R_COMMAND_NOT_SUPPORTED); + return 0; + } +} + +static int pkey_ec_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) { + if (ctx->pkey == NULL) { + OPENSSL_PUT_ERROR(EVP, EVP_R_NO_PARAMETERS_SET); + return 0; + } + EC_KEY *ec = EC_KEY_new(); + if (ec == NULL || + !EC_KEY_set_group(ec, EC_KEY_get0_group(ctx->pkey->pkey.ec)) || + !EC_KEY_generate_key(ec)) { + EC_KEY_free(ec); + return 0; + } + EVP_PKEY_assign_EC_KEY(pkey, ec); + return 1; +} + +const EVP_PKEY_METHOD ec_pkey_meth = { + EVP_PKEY_EC, + pkey_ec_init, + pkey_ec_copy, + pkey_ec_cleanup, + pkey_ec_keygen, + pkey_ec_sign, + pkey_ec_verify, + 0 /* verify_recover */, + 0 /* encrypt */, + 0 /* decrypt */, + pkey_ec_derive, + pkey_ec_ctrl, +}; diff --git a/external/boringssl/crypto/evp/p_ec_asn1.c b/external/boringssl/crypto/evp/p_ec_asn1.c new file mode 100644 index 0000000000..8d44dcdcee --- /dev/null +++ b/external/boringssl/crypto/evp/p_ec_asn1.c @@ -0,0 +1,257 @@ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 2006. + */ +/* ==================================================================== + * Copyright (c) 2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include +#include +#include +#include +#include + +#include "internal.h" + + +static int eckey_pub_encode(CBB *out, const EVP_PKEY *key) { + const EC_KEY *ec_key = key->pkey.ec; + const EC_GROUP *group = EC_KEY_get0_group(ec_key); + const EC_POINT *public_key = EC_KEY_get0_public_key(ec_key); + + /* See RFC 5480, section 2. */ + CBB spki, algorithm, oid, key_bitstring; + if (!CBB_add_asn1(out, &spki, CBS_ASN1_SEQUENCE) || + !CBB_add_asn1(&spki, &algorithm, CBS_ASN1_SEQUENCE) || + !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) || + !CBB_add_bytes(&oid, ec_asn1_meth.oid, ec_asn1_meth.oid_len) || + !EC_KEY_marshal_curve_name(&algorithm, group) || + !CBB_add_asn1(&spki, &key_bitstring, CBS_ASN1_BITSTRING) || + !CBB_add_u8(&key_bitstring, 0 /* padding */) || + !EC_POINT_point2cbb(&key_bitstring, group, public_key, + POINT_CONVERSION_UNCOMPRESSED, NULL) || + !CBB_flush(out)) { + OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR); + return 0; + } + + return 1; +} + +static int eckey_pub_decode(EVP_PKEY *out, CBS *params, CBS *key) { + /* See RFC 5480, section 2. */ + + /* The parameters are a named curve. */ + EC_POINT *point = NULL; + EC_KEY *eckey = NULL; + EC_GROUP *group = EC_KEY_parse_curve_name(params); + if (group == NULL || CBS_len(params) != 0) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + goto err; + } + + eckey = EC_KEY_new(); + if (eckey == NULL || !EC_KEY_set_group(eckey, group)) { + goto err; + } + + point = EC_POINT_new(group); + if (point == NULL || + !EC_POINT_oct2point(group, point, CBS_data(key), CBS_len(key), NULL) || + !EC_KEY_set_public_key(eckey, point)) { + goto err; + } + + EC_GROUP_free(group); + EC_POINT_free(point); + EVP_PKEY_assign_EC_KEY(out, eckey); + return 1; + +err: + EC_GROUP_free(group); + EC_POINT_free(point); + EC_KEY_free(eckey); + return 0; +} + +static int eckey_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) { + int r; + const EC_GROUP *group = EC_KEY_get0_group(b->pkey.ec); + const EC_POINT *pa = EC_KEY_get0_public_key(a->pkey.ec), + *pb = EC_KEY_get0_public_key(b->pkey.ec); + r = EC_POINT_cmp(group, pa, pb, NULL); + if (r == 0) { + return 1; + } else if (r == 1) { + return 0; + } else { + return -2; + } +} + +static int eckey_priv_decode(EVP_PKEY *out, CBS *params, CBS *key) { + /* See RFC 5915. */ + EC_GROUP *group = EC_KEY_parse_parameters(params); + if (group == NULL || CBS_len(params) != 0) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + EC_GROUP_free(group); + return 0; + } + + EC_KEY *ec_key = EC_KEY_parse_private_key(key, group); + EC_GROUP_free(group); + if (ec_key == NULL || CBS_len(key) != 0) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + EC_KEY_free(ec_key); + return 0; + } + + EVP_PKEY_assign_EC_KEY(out, ec_key); + return 1; +} + +static int eckey_priv_encode(CBB *out, const EVP_PKEY *key) { + const EC_KEY *ec_key = key->pkey.ec; + + /* Omit the redundant copy of the curve name. This contradicts RFC 5915 but + * aligns with PKCS #11. SEC 1 only says they may be omitted if known by other + * means. Both OpenSSL and NSS omit the redundant parameters, so we omit them + * as well. */ + unsigned enc_flags = EC_KEY_get_enc_flags(ec_key) | EC_PKEY_NO_PARAMETERS; + + /* See RFC 5915. */ + CBB pkcs8, algorithm, oid, private_key; + if (!CBB_add_asn1(out, &pkcs8, CBS_ASN1_SEQUENCE) || + !CBB_add_asn1_uint64(&pkcs8, 0 /* version */) || + !CBB_add_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) || + !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) || + !CBB_add_bytes(&oid, ec_asn1_meth.oid, ec_asn1_meth.oid_len) || + !EC_KEY_marshal_curve_name(&algorithm, EC_KEY_get0_group(ec_key)) || + !CBB_add_asn1(&pkcs8, &private_key, CBS_ASN1_OCTETSTRING) || + !EC_KEY_marshal_private_key(&private_key, ec_key, enc_flags) || + !CBB_flush(out)) { + OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR); + return 0; + } + + return 1; +} + +static int int_ec_size(const EVP_PKEY *pkey) { + return ECDSA_size(pkey->pkey.ec); +} + +static int ec_bits(const EVP_PKEY *pkey) { + const EC_GROUP *group = EC_KEY_get0_group(pkey->pkey.ec); + if (group == NULL) { + ERR_clear_error(); + return 0; + } + return BN_num_bits(EC_GROUP_get0_order(group)); +} + +static int ec_missing_parameters(const EVP_PKEY *pkey) { + return EC_KEY_get0_group(pkey->pkey.ec) == NULL; +} + +static int ec_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) { + EC_GROUP *group = EC_GROUP_dup(EC_KEY_get0_group(from->pkey.ec)); + if (group == NULL || + EC_KEY_set_group(to->pkey.ec, group) == 0) { + return 0; + } + EC_GROUP_free(group); + return 1; +} + +static int ec_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b) { + const EC_GROUP *group_a = EC_KEY_get0_group(a->pkey.ec), + *group_b = EC_KEY_get0_group(b->pkey.ec); + if (EC_GROUP_cmp(group_a, group_b, NULL) != 0) { + /* mismatch */ + return 0; + } + return 1; +} + +static void int_ec_free(EVP_PKEY *pkey) { EC_KEY_free(pkey->pkey.ec); } + +static int eckey_opaque(const EVP_PKEY *pkey) { + return EC_KEY_is_opaque(pkey->pkey.ec); +} + +const EVP_PKEY_ASN1_METHOD ec_asn1_meth = { + EVP_PKEY_EC, + /* 1.2.840.10045.2.1 */ + {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01}, 7, + + eckey_pub_decode, + eckey_pub_encode, + eckey_pub_cmp, + + eckey_priv_decode, + eckey_priv_encode, + + eckey_opaque, + 0 /* pkey_supports_digest */, + + int_ec_size, + ec_bits, + + ec_missing_parameters, + ec_copy_parameters, + ec_cmp_parameters, + + int_ec_free, +}; diff --git a/external/boringssl/crypto/evp/p_rsa.c b/external/boringssl/crypto/evp/p_rsa.c new file mode 100644 index 0000000000..a210657288 --- /dev/null +++ b/external/boringssl/crypto/evp/p_rsa.c @@ -0,0 +1,673 @@ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 2006. + */ +/* ==================================================================== + * Copyright (c) 2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../rsa/internal.h" +#include "internal.h" + + +typedef struct { + /* Key gen parameters */ + int nbits; + BIGNUM *pub_exp; + /* RSA padding mode */ + int pad_mode; + /* message digest */ + const EVP_MD *md; + /* message digest for MGF1 */ + const EVP_MD *mgf1md; + /* PSS salt length */ + int saltlen; + /* tbuf is a buffer which is either NULL, or is the size of the RSA modulus. + * It's used to store the output of RSA operations. */ + uint8_t *tbuf; + /* OAEP label */ + uint8_t *oaep_label; + size_t oaep_labellen; +} RSA_PKEY_CTX; + +static int pkey_rsa_init(EVP_PKEY_CTX *ctx) { + RSA_PKEY_CTX *rctx; + rctx = OPENSSL_malloc(sizeof(RSA_PKEY_CTX)); + if (!rctx) { + return 0; + } + memset(rctx, 0, sizeof(RSA_PKEY_CTX)); + + rctx->nbits = 2048; + rctx->pad_mode = RSA_PKCS1_PADDING; + rctx->saltlen = -2; + + ctx->data = rctx; + + return 1; +} + +static int pkey_rsa_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) { + RSA_PKEY_CTX *dctx, *sctx; + if (!pkey_rsa_init(dst)) { + return 0; + } + sctx = src->data; + dctx = dst->data; + dctx->nbits = sctx->nbits; + if (sctx->pub_exp) { + dctx->pub_exp = BN_dup(sctx->pub_exp); + if (!dctx->pub_exp) { + return 0; + } + } + + dctx->pad_mode = sctx->pad_mode; + dctx->md = sctx->md; + dctx->mgf1md = sctx->mgf1md; + if (sctx->oaep_label) { + OPENSSL_free(dctx->oaep_label); + dctx->oaep_label = BUF_memdup(sctx->oaep_label, sctx->oaep_labellen); + if (!dctx->oaep_label) { + return 0; + } + dctx->oaep_labellen = sctx->oaep_labellen; + } + + return 1; +} + +static void pkey_rsa_cleanup(EVP_PKEY_CTX *ctx) { + RSA_PKEY_CTX *rctx = ctx->data; + + if (rctx == NULL) { + return; + } + + BN_free(rctx->pub_exp); + OPENSSL_free(rctx->tbuf); + OPENSSL_free(rctx->oaep_label); + OPENSSL_free(rctx); +} + +static int setup_tbuf(RSA_PKEY_CTX *ctx, EVP_PKEY_CTX *pk) { + if (ctx->tbuf) { + return 1; + } + ctx->tbuf = OPENSSL_malloc(EVP_PKEY_size(pk->pkey)); + if (!ctx->tbuf) { + return 0; + } + return 1; +} + +static int pkey_rsa_sign(EVP_PKEY_CTX *ctx, uint8_t *sig, size_t *siglen, + const uint8_t *tbs, size_t tbslen) { + RSA_PKEY_CTX *rctx = ctx->data; + RSA *rsa = ctx->pkey->pkey.rsa; + const size_t key_len = EVP_PKEY_size(ctx->pkey); + + if (!sig) { + *siglen = key_len; + return 1; + } + + if (*siglen < key_len) { + OPENSSL_PUT_ERROR(EVP, EVP_R_BUFFER_TOO_SMALL); + return 0; + } + + if (rctx->md) { + unsigned int out_len; + + if (tbslen != EVP_MD_size(rctx->md)) { + OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_DIGEST_LENGTH); + return 0; + } + + if (EVP_MD_type(rctx->md) == NID_mdc2) { + OPENSSL_PUT_ERROR(EVP, EVP_R_NO_MDC2_SUPPORT); + return 0; + } + + switch (rctx->pad_mode) { + case RSA_PKCS1_PADDING: + if (!RSA_sign(EVP_MD_type(rctx->md), tbs, tbslen, sig, &out_len, rsa)) { + return 0; + } + *siglen = out_len; + return 1; + + case RSA_PKCS1_PSS_PADDING: + if (!setup_tbuf(rctx, ctx) || + !RSA_padding_add_PKCS1_PSS_mgf1(rsa, rctx->tbuf, tbs, rctx->md, + rctx->mgf1md, rctx->saltlen) || + !RSA_sign_raw(rsa, siglen, sig, *siglen, rctx->tbuf, key_len, + RSA_NO_PADDING)) { + return 0; + } + return 1; + + default: + return 0; + } + } + + return RSA_sign_raw(rsa, siglen, sig, *siglen, tbs, tbslen, rctx->pad_mode); +} + +static int pkey_rsa_verify(EVP_PKEY_CTX *ctx, const uint8_t *sig, + size_t siglen, const uint8_t *tbs, + size_t tbslen) { + RSA_PKEY_CTX *rctx = ctx->data; + RSA *rsa = ctx->pkey->pkey.rsa; + size_t rslen; + const size_t key_len = EVP_PKEY_size(ctx->pkey); + + if (rctx->md) { + switch (rctx->pad_mode) { + case RSA_PKCS1_PADDING: + return RSA_verify(EVP_MD_type(rctx->md), tbs, tbslen, sig, siglen, rsa); + + case RSA_PKCS1_PSS_PADDING: + if (!setup_tbuf(rctx, ctx) || + !RSA_verify_raw(rsa, &rslen, rctx->tbuf, key_len, sig, siglen, + RSA_NO_PADDING) || + !RSA_verify_PKCS1_PSS_mgf1(rsa, tbs, rctx->md, rctx->mgf1md, + rctx->tbuf, rctx->saltlen)) { + return 0; + } + return 1; + + default: + return 0; + } + } + + if (!setup_tbuf(rctx, ctx) || + !RSA_verify_raw(rsa, &rslen, rctx->tbuf, key_len, sig, siglen, + rctx->pad_mode) || + rslen != tbslen || + CRYPTO_memcmp(tbs, rctx->tbuf, rslen) != 0) { + return 0; + } + + return 1; +} + +static int pkey_rsa_verify_recover(EVP_PKEY_CTX *ctx, uint8_t *out, + size_t *out_len, const uint8_t *sig, + size_t sig_len) { + RSA_PKEY_CTX *rctx = ctx->data; + RSA *rsa = ctx->pkey->pkey.rsa; + const size_t key_len = EVP_PKEY_size(ctx->pkey); + + if (out == NULL) { + *out_len = key_len; + return 1; + } + + if (*out_len < key_len) { + OPENSSL_PUT_ERROR(EVP, EVP_R_BUFFER_TOO_SMALL); + return 0; + } + + if (!setup_tbuf(rctx, ctx)) { + return 0; + } + + if (rctx->md == NULL) { + const int ret = RSA_public_decrypt(sig_len, sig, rctx->tbuf, + ctx->pkey->pkey.rsa, rctx->pad_mode); + if (ret < 0) { + return 0; + } + *out_len = ret; + memcpy(out, rctx->tbuf, *out_len); + return 1; + } + + if (rctx->pad_mode != RSA_PKCS1_PADDING) { + return 0; + } + + uint8_t *asn1_prefix; + size_t asn1_prefix_len; + int asn1_prefix_allocated; + if (!RSA_add_pkcs1_prefix(&asn1_prefix, &asn1_prefix_len, + &asn1_prefix_allocated, EVP_MD_type(rctx->md), NULL, + 0)) { + return 0; + } + + size_t rslen; + int ok = 1; + if (!RSA_verify_raw(rsa, &rslen, rctx->tbuf, key_len, sig, sig_len, + RSA_PKCS1_PADDING) || + rslen < asn1_prefix_len || + CRYPTO_memcmp(rctx->tbuf, asn1_prefix, asn1_prefix_len) != 0) { + ok = 0; + } + + if (asn1_prefix_allocated) { + OPENSSL_free(asn1_prefix); + } + + if (!ok) { + return 0; + } + + const size_t result_len = rslen - asn1_prefix_len; + if (result_len != EVP_MD_size(rctx->md)) { + return 0; + } + + if (out != NULL) { + memcpy(out, rctx->tbuf + asn1_prefix_len, result_len); + } + *out_len = result_len; + + return 1; +} + +static int pkey_rsa_encrypt(EVP_PKEY_CTX *ctx, uint8_t *out, size_t *outlen, + const uint8_t *in, size_t inlen) { + RSA_PKEY_CTX *rctx = ctx->data; + RSA *rsa = ctx->pkey->pkey.rsa; + const size_t key_len = EVP_PKEY_size(ctx->pkey); + + if (!out) { + *outlen = key_len; + return 1; + } + + if (*outlen < key_len) { + OPENSSL_PUT_ERROR(EVP, EVP_R_BUFFER_TOO_SMALL); + return 0; + } + + if (rctx->pad_mode == RSA_PKCS1_OAEP_PADDING) { + if (!setup_tbuf(rctx, ctx) || + !RSA_padding_add_PKCS1_OAEP_mgf1(rctx->tbuf, key_len, in, inlen, + rctx->oaep_label, rctx->oaep_labellen, + rctx->md, rctx->mgf1md) || + !RSA_encrypt(rsa, outlen, out, *outlen, rctx->tbuf, key_len, + RSA_NO_PADDING)) { + return 0; + } + return 1; + } + + return RSA_encrypt(rsa, outlen, out, *outlen, in, inlen, rctx->pad_mode); +} + +static int pkey_rsa_decrypt(EVP_PKEY_CTX *ctx, uint8_t *out, + size_t *outlen, const uint8_t *in, + size_t inlen) { + RSA_PKEY_CTX *rctx = ctx->data; + RSA *rsa = ctx->pkey->pkey.rsa; + const size_t key_len = EVP_PKEY_size(ctx->pkey); + + if (!out) { + *outlen = key_len; + return 1; + } + + if (*outlen < key_len) { + OPENSSL_PUT_ERROR(EVP, EVP_R_BUFFER_TOO_SMALL); + return 0; + } + + if (rctx->pad_mode == RSA_PKCS1_OAEP_PADDING) { + size_t plaintext_len; + int message_len; + + if (!setup_tbuf(rctx, ctx) || + !RSA_decrypt(rsa, &plaintext_len, rctx->tbuf, key_len, in, inlen, + RSA_NO_PADDING)) { + return 0; + } + + message_len = RSA_padding_check_PKCS1_OAEP_mgf1( + out, key_len, rctx->tbuf, plaintext_len, rctx->oaep_label, + rctx->oaep_labellen, rctx->md, rctx->mgf1md); + if (message_len < 0) { + return 0; + } + *outlen = message_len; + return 1; + } + + return RSA_decrypt(rsa, outlen, out, key_len, in, inlen, rctx->pad_mode); +} + +static int check_padding_md(const EVP_MD *md, int padding) { + if (!md) { + return 1; + } + + if (padding == RSA_NO_PADDING) { + OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_PADDING_MODE); + return 0; + } + + return 1; +} + +static int is_known_padding(int padding_mode) { + switch (padding_mode) { + case RSA_PKCS1_PADDING: + case RSA_NO_PADDING: + case RSA_PKCS1_OAEP_PADDING: + case RSA_PKCS1_PSS_PADDING: + return 1; + default: + return 0; + } +} + +static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) { + RSA_PKEY_CTX *rctx = ctx->data; + switch (type) { + case EVP_PKEY_CTRL_RSA_PADDING: + if (!is_known_padding(p1) || !check_padding_md(rctx->md, p1) || + (p1 == RSA_PKCS1_PSS_PADDING && + 0 == (ctx->operation & (EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY))) || + (p1 == RSA_PKCS1_OAEP_PADDING && + 0 == (ctx->operation & EVP_PKEY_OP_TYPE_CRYPT))) { + OPENSSL_PUT_ERROR(EVP, EVP_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE); + return 0; + } + if ((p1 == RSA_PKCS1_PSS_PADDING || p1 == RSA_PKCS1_OAEP_PADDING) && + rctx->md == NULL) { + rctx->md = EVP_sha1(); + } + rctx->pad_mode = p1; + return 1; + + case EVP_PKEY_CTRL_GET_RSA_PADDING: + *(int *)p2 = rctx->pad_mode; + return 1; + + case EVP_PKEY_CTRL_RSA_PSS_SALTLEN: + case EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN: + if (rctx->pad_mode != RSA_PKCS1_PSS_PADDING) { + OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_PSS_SALTLEN); + return 0; + } + if (type == EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN) { + *(int *)p2 = rctx->saltlen; + } else { + if (p1 < -2) { + return 0; + } + rctx->saltlen = p1; + } + return 1; + + case EVP_PKEY_CTRL_RSA_KEYGEN_BITS: + if (p1 < 256) { + OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_KEYBITS); + return 0; + } + rctx->nbits = p1; + return 1; + + case EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP: + if (!p2) { + return 0; + } + BN_free(rctx->pub_exp); + rctx->pub_exp = p2; + return 1; + + case EVP_PKEY_CTRL_RSA_OAEP_MD: + case EVP_PKEY_CTRL_GET_RSA_OAEP_MD: + if (rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) { + OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_PADDING_MODE); + return 0; + } + if (type == EVP_PKEY_CTRL_GET_RSA_OAEP_MD) { + *(const EVP_MD **)p2 = rctx->md; + } else { + rctx->md = p2; + } + return 1; + + case EVP_PKEY_CTRL_MD: + if (!check_padding_md(p2, rctx->pad_mode)) { + return 0; + } + rctx->md = p2; + return 1; + + case EVP_PKEY_CTRL_GET_MD: + *(const EVP_MD **)p2 = rctx->md; + return 1; + + case EVP_PKEY_CTRL_RSA_MGF1_MD: + case EVP_PKEY_CTRL_GET_RSA_MGF1_MD: + if (rctx->pad_mode != RSA_PKCS1_PSS_PADDING && + rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) { + OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_MGF1_MD); + return 0; + } + if (type == EVP_PKEY_CTRL_GET_RSA_MGF1_MD) { + if (rctx->mgf1md) { + *(const EVP_MD **)p2 = rctx->mgf1md; + } else { + *(const EVP_MD **)p2 = rctx->md; + } + } else { + rctx->mgf1md = p2; + } + return 1; + + case EVP_PKEY_CTRL_RSA_OAEP_LABEL: + if (rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) { + OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_PADDING_MODE); + return 0; + } + OPENSSL_free(rctx->oaep_label); + if (p2 && p1 > 0) { + rctx->oaep_label = p2; + rctx->oaep_labellen = p1; + } else { + rctx->oaep_label = NULL; + rctx->oaep_labellen = 0; + } + return 1; + + case EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL: + if (rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) { + OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_PADDING_MODE); + return 0; + } + CBS_init((CBS *)p2, rctx->oaep_label, rctx->oaep_labellen); + return 1; + + default: + OPENSSL_PUT_ERROR(EVP, EVP_R_COMMAND_NOT_SUPPORTED); + return 0; + } +} + +static int pkey_rsa_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) { + RSA *rsa = NULL; + RSA_PKEY_CTX *rctx = ctx->data; + + if (!rctx->pub_exp) { + rctx->pub_exp = BN_new(); + if (!rctx->pub_exp || !BN_set_word(rctx->pub_exp, RSA_F4)) { + return 0; + } + } + rsa = RSA_new(); + if (!rsa) { + return 0; + } + + if (!RSA_generate_key_ex(rsa, rctx->nbits, rctx->pub_exp, NULL)) { + RSA_free(rsa); + return 0; + } + + EVP_PKEY_assign_RSA(pkey, rsa); + return 1; +} + +const EVP_PKEY_METHOD rsa_pkey_meth = { + EVP_PKEY_RSA, + pkey_rsa_init, + pkey_rsa_copy, + pkey_rsa_cleanup, + pkey_rsa_keygen, + pkey_rsa_sign, + pkey_rsa_verify, + pkey_rsa_verify_recover, + pkey_rsa_encrypt, + pkey_rsa_decrypt, + 0 /* derive */, + pkey_rsa_ctrl, +}; + +int EVP_PKEY_CTX_set_rsa_padding(EVP_PKEY_CTX *ctx, int padding) { + return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, -1, EVP_PKEY_CTRL_RSA_PADDING, + padding, NULL); +} + +int EVP_PKEY_CTX_get_rsa_padding(EVP_PKEY_CTX *ctx, int *out_padding) { + return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, -1, EVP_PKEY_CTRL_GET_RSA_PADDING, + 0, out_padding); +} + +int EVP_PKEY_CTX_set_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int salt_len) { + return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, + (EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY), + EVP_PKEY_CTRL_RSA_PSS_SALTLEN, salt_len, NULL); +} + +int EVP_PKEY_CTX_get_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int *out_salt_len) { + return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, + (EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY), + EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN, 0, out_salt_len); +} + +int EVP_PKEY_CTX_set_rsa_keygen_bits(EVP_PKEY_CTX *ctx, int bits) { + return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_KEYGEN, + EVP_PKEY_CTRL_RSA_KEYGEN_BITS, bits, NULL); +} + +int EVP_PKEY_CTX_set_rsa_keygen_pubexp(EVP_PKEY_CTX *ctx, BIGNUM *e) { + return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_KEYGEN, + EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP, 0, e); +} + +int EVP_PKEY_CTX_set_rsa_oaep_md(EVP_PKEY_CTX *ctx, const EVP_MD *md) { + return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT, + EVP_PKEY_CTRL_RSA_OAEP_MD, 0, (void *)md); +} + +int EVP_PKEY_CTX_get_rsa_oaep_md(EVP_PKEY_CTX *ctx, const EVP_MD **out_md) { + return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT, + EVP_PKEY_CTRL_GET_RSA_OAEP_MD, 0, (void*) out_md); +} + +int EVP_PKEY_CTX_set_rsa_mgf1_md(EVP_PKEY_CTX *ctx, const EVP_MD *md) { + return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, + EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT, + EVP_PKEY_CTRL_RSA_MGF1_MD, 0, (void*) md); +} + +int EVP_PKEY_CTX_get_rsa_mgf1_md(EVP_PKEY_CTX *ctx, const EVP_MD **out_md) { + return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, + EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT, + EVP_PKEY_CTRL_GET_RSA_MGF1_MD, 0, (void*) out_md); +} + +int EVP_PKEY_CTX_set0_rsa_oaep_label(EVP_PKEY_CTX *ctx, uint8_t *label, + size_t label_len) { + if (label_len > INT_MAX) { + return 0; + } + + return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT, + EVP_PKEY_CTRL_RSA_OAEP_LABEL, (int)label_len, + (void *)label); +} + +int EVP_PKEY_CTX_get0_rsa_oaep_label(EVP_PKEY_CTX *ctx, + const uint8_t **out_label) { + CBS label; + if (!EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT, + EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL, 0, &label)) { + return -1; + } + if (CBS_len(&label) > INT_MAX) { + OPENSSL_PUT_ERROR(EVP, ERR_R_OVERFLOW); + return -1; + } + *out_label = CBS_data(&label); + return (int)CBS_len(&label); +} diff --git a/external/boringssl/crypto/evp/p_rsa_asn1.c b/external/boringssl/crypto/evp/p_rsa_asn1.c new file mode 100644 index 0000000000..2c4b266d96 --- /dev/null +++ b/external/boringssl/crypto/evp/p_rsa_asn1.c @@ -0,0 +1,200 @@ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 2006. + */ +/* ==================================================================== + * Copyright (c) 2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include +#include +#include +#include +#include + +#include "../rsa/internal.h" +#include "internal.h" + + +static int rsa_pub_encode(CBB *out, const EVP_PKEY *key) { + /* See RFC 3279, section 2.3.1. */ + CBB spki, algorithm, oid, null, key_bitstring; + if (!CBB_add_asn1(out, &spki, CBS_ASN1_SEQUENCE) || + !CBB_add_asn1(&spki, &algorithm, CBS_ASN1_SEQUENCE) || + !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) || + !CBB_add_bytes(&oid, rsa_asn1_meth.oid, rsa_asn1_meth.oid_len) || + !CBB_add_asn1(&algorithm, &null, CBS_ASN1_NULL) || + !CBB_add_asn1(&spki, &key_bitstring, CBS_ASN1_BITSTRING) || + !CBB_add_u8(&key_bitstring, 0 /* padding */) || + !RSA_marshal_public_key(&key_bitstring, key->pkey.rsa) || + !CBB_flush(out)) { + OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR); + return 0; + } + + return 1; +} + +static int rsa_pub_decode(EVP_PKEY *out, CBS *params, CBS *key) { + /* See RFC 3279, section 2.3.1. */ + + /* The parameters must be NULL. */ + CBS null; + if (!CBS_get_asn1(params, &null, CBS_ASN1_NULL) || + CBS_len(&null) != 0 || + CBS_len(params) != 0) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + return 0; + } + + /* Estonian IDs issued between September 2014 to September 2015 are + * broken. See https://crbug.com/532048 and https://crbug.com/534766. + * + * TODO(davidben): Switch this to the strict version in March 2016 or when + * Chromium can force client certificates down a different codepath, whichever + * comes first. */ + RSA *rsa = RSA_parse_public_key_buggy(key); + if (rsa == NULL || CBS_len(key) != 0) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + RSA_free(rsa); + return 0; + } + + EVP_PKEY_assign_RSA(out, rsa); + return 1; +} + +static int rsa_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) { + return BN_cmp(b->pkey.rsa->n, a->pkey.rsa->n) == 0 && + BN_cmp(b->pkey.rsa->e, a->pkey.rsa->e) == 0; +} + +static int rsa_priv_encode(CBB *out, const EVP_PKEY *key) { + CBB pkcs8, algorithm, oid, null, private_key; + if (!CBB_add_asn1(out, &pkcs8, CBS_ASN1_SEQUENCE) || + !CBB_add_asn1_uint64(&pkcs8, 0 /* version */) || + !CBB_add_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) || + !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) || + !CBB_add_bytes(&oid, rsa_asn1_meth.oid, rsa_asn1_meth.oid_len) || + !CBB_add_asn1(&algorithm, &null, CBS_ASN1_NULL) || + !CBB_add_asn1(&pkcs8, &private_key, CBS_ASN1_OCTETSTRING) || + !RSA_marshal_private_key(&private_key, key->pkey.rsa) || + !CBB_flush(out)) { + OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR); + return 0; + } + + return 1; +} + +static int rsa_priv_decode(EVP_PKEY *out, CBS *params, CBS *key) { + /* Per RFC 3447, A.1, the parameters have type NULL. */ + CBS null; + if (!CBS_get_asn1(params, &null, CBS_ASN1_NULL) || + CBS_len(&null) != 0 || + CBS_len(params) != 0) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + return 0; + } + + RSA *rsa = RSA_parse_private_key(key); + if (rsa == NULL || CBS_len(key) != 0) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + RSA_free(rsa); + return 0; + } + + EVP_PKEY_assign_RSA(out, rsa); + return 1; +} + +static int rsa_opaque(const EVP_PKEY *pkey) { + return RSA_is_opaque(pkey->pkey.rsa); +} + +static int rsa_supports_digest(const EVP_PKEY *pkey, const EVP_MD *md) { + return RSA_supports_digest(pkey->pkey.rsa, md); +} + +static int int_rsa_size(const EVP_PKEY *pkey) { + return RSA_size(pkey->pkey.rsa); +} + +static int rsa_bits(const EVP_PKEY *pkey) { + return BN_num_bits(pkey->pkey.rsa->n); +} + +static void int_rsa_free(EVP_PKEY *pkey) { RSA_free(pkey->pkey.rsa); } + +const EVP_PKEY_ASN1_METHOD rsa_asn1_meth = { + EVP_PKEY_RSA, + /* 1.2.840.113549.1.1.1 */ + {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01}, 9, + + rsa_pub_decode, + rsa_pub_encode, + rsa_pub_cmp, + + rsa_priv_decode, + rsa_priv_encode, + + rsa_opaque, + rsa_supports_digest, + + int_rsa_size, + rsa_bits, + + 0,0,0, + + int_rsa_free, +}; diff --git a/external/boringssl/crypto/evp/pbkdf.c b/external/boringssl/crypto/evp/pbkdf.c new file mode 100644 index 0000000000..b06b922b0b --- /dev/null +++ b/external/boringssl/crypto/evp/pbkdf.c @@ -0,0 +1,151 @@ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 1999. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include + +#include + + +int PKCS5_PBKDF2_HMAC(const char *password, size_t password_len, + const uint8_t *salt, size_t salt_len, unsigned iterations, + const EVP_MD *digest, size_t key_len, uint8_t *out_key) { + uint8_t digest_tmp[EVP_MAX_MD_SIZE], *p, itmp[4]; + size_t cplen, mdlen, tkeylen, k; + unsigned j; + uint32_t i = 1; + HMAC_CTX hctx_tpl, hctx; + + mdlen = EVP_MD_size(digest); + HMAC_CTX_init(&hctx_tpl); + p = out_key; + tkeylen = key_len; + if (!HMAC_Init_ex(&hctx_tpl, password, password_len, digest, NULL)) { + HMAC_CTX_cleanup(&hctx_tpl); + return 0; + } + while (tkeylen) { + if (tkeylen > mdlen) { + cplen = mdlen; + } else { + cplen = tkeylen; + } + /* We are unlikely to ever use more than 256 blocks (5120 bits!) + * but just in case... */ + itmp[0] = (uint8_t)((i >> 24) & 0xff); + itmp[1] = (uint8_t)((i >> 16) & 0xff); + itmp[2] = (uint8_t)((i >> 8) & 0xff); + itmp[3] = (uint8_t)(i & 0xff); + if (!HMAC_CTX_copy(&hctx, &hctx_tpl)) { + HMAC_CTX_cleanup(&hctx_tpl); + return 0; + } + if (!HMAC_Update(&hctx, salt, salt_len) || + !HMAC_Update(&hctx, itmp, 4) || + !HMAC_Final(&hctx, digest_tmp, NULL)) { + HMAC_CTX_cleanup(&hctx_tpl); + HMAC_CTX_cleanup(&hctx); + return 0; + } + HMAC_CTX_cleanup(&hctx); + memcpy(p, digest_tmp, cplen); + for (j = 1; j < iterations; j++) { + if (!HMAC_CTX_copy(&hctx, &hctx_tpl)) { + HMAC_CTX_cleanup(&hctx_tpl); + return 0; + } + if (!HMAC_Update(&hctx, digest_tmp, mdlen) || + !HMAC_Final(&hctx, digest_tmp, NULL)) { + HMAC_CTX_cleanup(&hctx_tpl); + HMAC_CTX_cleanup(&hctx); + return 0; + } + HMAC_CTX_cleanup(&hctx); + for (k = 0; k < cplen; k++) { + p[k] ^= digest_tmp[k]; + } + } + tkeylen -= cplen; + i++; + p += cplen; + } + HMAC_CTX_cleanup(&hctx_tpl); + + // RFC 2898 describes iterations (c) as being a "positive integer", so a + // value of 0 is an error. + // + // Unfortunatley not all consumers of PKCS5_PBKDF2_HMAC() check their return + // value, expecting it to succeed and unconditonally using |out_key|. + // As a precaution for such callsites in external code, the old behavior + // of iterations < 1 being treated as iterations == 1 is preserved, but + // additionally an error result is returned. + // + // TODO(eroman): Figure out how to remove this compatibility hack, or change + // the default to something more sensible like 2048. + if (iterations == 0) { + return 0; + } + + return 1; +} + +int PKCS5_PBKDF2_HMAC_SHA1(const char *password, size_t password_len, + const uint8_t *salt, size_t salt_len, + unsigned iterations, size_t key_len, + uint8_t *out_key) { + return PKCS5_PBKDF2_HMAC(password, password_len, salt, salt_len, iterations, + EVP_sha1(), key_len, out_key); +} diff --git a/external/boringssl/crypto/evp/pbkdf_test.cc b/external/boringssl/crypto/evp/pbkdf_test.cc new file mode 100644 index 0000000000..438ab644cb --- /dev/null +++ b/external/boringssl/crypto/evp/pbkdf_test.cc @@ -0,0 +1,220 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include + +#include +#include +#include +#include + + +// Prints out the data buffer as a sequence of hex bytes. +static void PrintDataHex(const void *data, size_t len) { + for (size_t i = 0; i < len; ++i) { + fprintf(stderr, "%02x", (int)((const uint8_t *)data)[i]); + } +} + +// Helper for testing that PBKDF2 derives the expected key from the given +// inputs. Returns 1 on success, 0 otherwise. +static bool TestPBKDF2(const void *password, size_t password_len, + const void *salt, size_t salt_len, unsigned iterations, + const EVP_MD *digest, size_t key_len, + const uint8_t *expected_key) { + uint8_t key[64]; + + if (key_len > sizeof(key)) { + fprintf(stderr, "Output buffer is not large enough.\n"); + return false; + } + + if (!PKCS5_PBKDF2_HMAC((const char *)password, password_len, + (const uint8_t *)salt, salt_len, iterations, digest, + key_len, key)) { + fprintf(stderr, "Call to PKCS5_PBKDF2_HMAC failed\n"); + ERR_print_errors_fp(stderr); + return false; + } + + if (memcmp(key, expected_key, key_len) != 0) { + fprintf(stderr, "Resulting key material does not match expectation\n"); + fprintf(stderr, "Expected:\n "); + PrintDataHex(expected_key, key_len); + fprintf(stderr, "\nActual:\n "); + PrintDataHex(key, key_len); + fprintf(stderr, "\n"); + return false; + } + + return true; +} + +// Tests deriving a key using an empty password (specified both as NULL and as +// non-NULL). Note that NULL has special meaning to HMAC initialization. +static bool TestEmptyPassword() { + const uint8_t kKey[] = {0xa3, 0x3d, 0xdd, 0xc3, 0x04, 0x78, 0x18, + 0x55, 0x15, 0x31, 0x1f, 0x87, 0x52, 0x89, + 0x5d, 0x36, 0xea, 0x43, 0x63, 0xa2}; + + if (!TestPBKDF2(NULL, 0, "salt", 4, 1, EVP_sha1(), sizeof(kKey), kKey) || + !TestPBKDF2("", 0, "salt", 4, 1, EVP_sha1(), sizeof(kKey), kKey)) { + return false; + } + + return true; +} + +// Tests deriving a key using an empty salt. Note that the expectation was +// generated using OpenSSL itself, and hence is not verified. +static bool TestEmptySalt() { + const uint8_t kKey[] = {0x8b, 0xc2, 0xf9, 0x16, 0x7a, 0x81, 0xcd, 0xcf, + 0xad, 0x12, 0x35, 0xcd, 0x90, 0x47, 0xf1, 0x13, + 0x62, 0x71, 0xc1, 0xf9, 0x78, 0xfc, 0xfc, 0xb3, + 0x5e, 0x22, 0xdb, 0xea, 0xfa, 0x46, 0x34, 0xf6}; + + if (!TestPBKDF2("password", 8, NULL, 0, 2, EVP_sha256(), sizeof(kKey), + kKey) || + !TestPBKDF2("password", 8, "", 0, 2, EVP_sha256(), sizeof(kKey), kKey)) { + return false; + } + + return true; +} + +// Exercises test vectors taken from https://tools.ietf.org/html/rfc6070. +// Note that each of these test vectors uses SHA-1 as the digest. +static bool TestRFC6070Vectors() { + const uint8_t kKey1[] = {0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, + 0x71, 0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, + 0x12, 0x06, 0x2f, 0xe0, 0x37, 0xa6}; + const uint8_t kKey2[] = {0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, + 0x8c, 0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, + 0x41, 0xf0, 0xd8, 0xde, 0x89, 0x57}; + const uint8_t kKey3[] = {0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d, + 0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3}; + + if (!TestPBKDF2("password", 8, "salt", 4, 1, EVP_sha1(), sizeof(kKey1), + kKey1) || + !TestPBKDF2("password", 8, "salt", 4, 2, EVP_sha1(), sizeof(kKey2), + kKey2) || + !TestPBKDF2("pass\0word", 9, "sa\0lt", 5, 4096, EVP_sha1(), + sizeof(kKey3), kKey3)) { + return false; + } + + return true; +} + +// Tests key derivation using SHA-2 digests. +static bool TestSHA2() { + // This test was taken from: + // http://stackoverflow.com/questions/5130513/pbkdf2-hmac-sha2-test-vectors. + const uint8_t kKey1[] = {0xae, 0x4d, 0x0c, 0x95, 0xaf, 0x6b, 0x46, 0xd3, + 0x2d, 0x0a, 0xdf, 0xf9, 0x28, 0xf0, 0x6d, 0xd0, + 0x2a, 0x30, 0x3f, 0x8e, 0xf3, 0xc2, 0x51, 0xdf, + 0xd6, 0xe2, 0xd8, 0x5a, 0x95, 0x47, 0x4c, 0x43}; + + // This test was taken from: + // http://stackoverflow.com/questions/15593184/pbkdf2-hmac-sha-512-test-vectors. + const uint8_t kKey2[] = { + 0x8c, 0x05, 0x11, 0xf4, 0xc6, 0xe5, 0x97, 0xc6, 0xac, 0x63, 0x15, + 0xd8, 0xf0, 0x36, 0x2e, 0x22, 0x5f, 0x3c, 0x50, 0x14, 0x95, 0xba, + 0x23, 0xb8, 0x68, 0xc0, 0x05, 0x17, 0x4d, 0xc4, 0xee, 0x71, 0x11, + 0x5b, 0x59, 0xf9, 0xe6, 0x0c, 0xd9, 0x53, 0x2f, 0xa3, 0x3e, 0x0f, + 0x75, 0xae, 0xfe, 0x30, 0x22, 0x5c, 0x58, 0x3a, 0x18, 0x6c, 0xd8, + 0x2b, 0xd4, 0xda, 0xea, 0x97, 0x24, 0xa3, 0xd3, 0xb8}; + + if (!TestPBKDF2("password", 8, "salt", 4, 2, EVP_sha256(), sizeof(kKey1), + kKey1) || + !TestPBKDF2("passwordPASSWORDpassword", 24, + "saltSALTsaltSALTsaltSALTsaltSALTsalt", 36, 4096, + EVP_sha512(), sizeof(kKey2), kKey2)) { + return false; + } + + return true; +} + +// Tests key derivation using iterations=0. +// +// RFC 2898 defines the iteration count (c) as a "positive integer". So doing a +// key derivation with iterations=0 is ill-defined and should result in a +// failure. +static bool TestZeroIterations() { + static const char kPassword[] = "password"; + const size_t password_len = strlen(kPassword); + static const uint8_t kSalt[] = {1, 2, 3, 4}; + const size_t salt_len = sizeof(kSalt); + const EVP_MD *digest = EVP_sha1(); + + uint8_t key[10] = {0}; + const size_t key_len = sizeof(key); + + // Verify that calling with iterations=1 works. + if (!PKCS5_PBKDF2_HMAC(kPassword, password_len, kSalt, salt_len, + 1 /* iterations */, digest, key_len, key)) { + fprintf(stderr, "PBKDF2 failed with iterations=1\n"); + return false; + } + + // Flip the first key byte (so can later test if it got set). + const uint8_t expected_first_byte = key[0]; + key[0] = ~key[0]; + + // However calling it with iterations=0 fails. + if (PKCS5_PBKDF2_HMAC(kPassword, password_len, kSalt, salt_len, + 0 /* iterations */, digest, key_len, key)) { + fprintf(stderr, "PBKDF2 returned zero with iterations=0\n"); + return false; + } + + // For backwards compatibility, the iterations == 0 case still fills in + // the out key. + return key[0] == expected_first_byte; +} + +int main(void) { + CRYPTO_library_init(); + + if (!TestEmptyPassword()) { + fprintf(stderr, "TestEmptyPassword failed\n"); + return 1; + } + + if (!TestEmptySalt()) { + fprintf(stderr, "TestEmptySalt failed\n"); + return 1; + } + + if (!TestRFC6070Vectors()) { + fprintf(stderr, "TestRFC6070Vectors failed\n"); + return 1; + } + + if (!TestSHA2()) { + fprintf(stderr, "TestSHA2 failed\n"); + return 1; + } + + if (!TestZeroIterations()) { + fprintf(stderr, "TestZeroIterations failed\n"); + return 1; + } + + printf("PASS\n"); + ERR_free_strings(); + return 0; +} diff --git a/external/boringssl/crypto/evp/print.c b/external/boringssl/crypto/evp/print.c new file mode 100644 index 0000000000..56521ec56b --- /dev/null +++ b/external/boringssl/crypto/evp/print.c @@ -0,0 +1,527 @@ +/* ==================================================================== + * Copyright (c) 2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "../rsa/internal.h" + + +static int bn_print(BIO *bp, const char *number, const BIGNUM *num, + uint8_t *buf, int off) { + if (num == NULL) { + return 1; + } + + if (!BIO_indent(bp, off, 128)) { + return 0; + } + if (BN_is_zero(num)) { + if (BIO_printf(bp, "%s 0\n", number) <= 0) { + return 0; + } + return 1; + } + + if (BN_num_bytes(num) <= sizeof(long)) { + const char *neg = BN_is_negative(num) ? "-" : ""; + if (BIO_printf(bp, "%s %s%lu (%s0x%lx)\n", number, neg, + (unsigned long)num->d[0], neg, + (unsigned long)num->d[0]) <= 0) { + return 0; + } + } else { + buf[0] = 0; + if (BIO_printf(bp, "%s%s", number, + (BN_is_negative(num)) ? " (Negative)" : "") <= 0) { + return 0; + } + int n = BN_bn2bin(num, &buf[1]); + + if (buf[1] & 0x80) { + n++; + } else { + buf++; + } + + int i; + for (i = 0; i < n; i++) { + if ((i % 15) == 0) { + if (BIO_puts(bp, "\n") <= 0 || + !BIO_indent(bp, off + 4, 128)) { + return 0; + } + } + if (BIO_printf(bp, "%02x%s", buf[i], ((i + 1) == n) ? "" : ":") <= 0) { + return 0; + } + } + if (BIO_write(bp, "\n", 1) <= 0) { + return 0; + } + } + return 1; +} + +static void update_buflen(const BIGNUM *b, size_t *pbuflen) { + size_t i; + + if (!b) { + return; + } + + i = BN_num_bytes(b); + if (*pbuflen < i) { + *pbuflen = i; + } +} + +/* RSA keys. */ + +static int do_rsa_print(BIO *out, const RSA *rsa, int off, + int include_private) { + const char *s, *str; + uint8_t *m = NULL; + int ret = 0, mod_len = 0; + size_t buf_len = 0; + + update_buflen(rsa->n, &buf_len); + update_buflen(rsa->e, &buf_len); + + if (include_private) { + update_buflen(rsa->d, &buf_len); + update_buflen(rsa->p, &buf_len); + update_buflen(rsa->q, &buf_len); + update_buflen(rsa->dmp1, &buf_len); + update_buflen(rsa->dmq1, &buf_len); + update_buflen(rsa->iqmp, &buf_len); + + if (rsa->additional_primes != NULL) { + size_t i; + + for (i = 0; i < sk_RSA_additional_prime_num(rsa->additional_primes); + i++) { + const RSA_additional_prime *ap = + sk_RSA_additional_prime_value(rsa->additional_primes, i); + update_buflen(ap->prime, &buf_len); + update_buflen(ap->exp, &buf_len); + update_buflen(ap->coeff, &buf_len); + } + } + } + + m = (uint8_t *)OPENSSL_malloc(buf_len + 10); + if (m == NULL) { + OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (rsa->n != NULL) { + mod_len = BN_num_bits(rsa->n); + } + + if (!BIO_indent(out, off, 128)) { + goto err; + } + + if (include_private && rsa->d) { + if (BIO_printf(out, "Private-Key: (%d bit)\n", mod_len) <= 0) { + goto err; + } + str = "modulus:"; + s = "publicExponent:"; + } else { + if (BIO_printf(out, "Public-Key: (%d bit)\n", mod_len) <= 0) { + goto err; + } + str = "Modulus:"; + s = "Exponent:"; + } + if (!bn_print(out, str, rsa->n, m, off) || + !bn_print(out, s, rsa->e, m, off)) { + goto err; + } + + if (include_private) { + if (!bn_print(out, "privateExponent:", rsa->d, m, off) || + !bn_print(out, "prime1:", rsa->p, m, off) || + !bn_print(out, "prime2:", rsa->q, m, off) || + !bn_print(out, "exponent1:", rsa->dmp1, m, off) || + !bn_print(out, "exponent2:", rsa->dmq1, m, off) || + !bn_print(out, "coefficient:", rsa->iqmp, m, off)) { + goto err; + } + + if (rsa->additional_primes != NULL && + sk_RSA_additional_prime_num(rsa->additional_primes) > 0) { + size_t i; + + if (BIO_printf(out, "otherPrimeInfos:\n") <= 0) { + goto err; + } + for (i = 0; i < sk_RSA_additional_prime_num(rsa->additional_primes); + i++) { + const RSA_additional_prime *ap = + sk_RSA_additional_prime_value(rsa->additional_primes, i); + + if (BIO_printf(out, "otherPrimeInfo (prime %u):\n", + (unsigned)(i + 3)) <= 0 || + !bn_print(out, "prime:", ap->prime, m, off) || + !bn_print(out, "exponent:", ap->exp, m, off) || + !bn_print(out, "coeff:", ap->coeff, m, off)) { + goto err; + } + } + } + } + ret = 1; + +err: + OPENSSL_free(m); + return ret; +} + +static int rsa_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent, + ASN1_PCTX *ctx) { + return do_rsa_print(bp, pkey->pkey.rsa, indent, 0); +} + +static int rsa_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent, + ASN1_PCTX *ctx) { + return do_rsa_print(bp, pkey->pkey.rsa, indent, 1); +} + + +/* DSA keys. */ + +static int do_dsa_print(BIO *bp, const DSA *x, int off, int ptype) { + uint8_t *m = NULL; + int ret = 0; + size_t buf_len = 0; + const char *ktype = NULL; + + const BIGNUM *priv_key, *pub_key; + + priv_key = NULL; + if (ptype == 2) { + priv_key = x->priv_key; + } + + pub_key = NULL; + if (ptype > 0) { + pub_key = x->pub_key; + } + + ktype = "DSA-Parameters"; + if (ptype == 2) { + ktype = "Private-Key"; + } else if (ptype == 1) { + ktype = "Public-Key"; + } + + update_buflen(x->p, &buf_len); + update_buflen(x->q, &buf_len); + update_buflen(x->g, &buf_len); + update_buflen(priv_key, &buf_len); + update_buflen(pub_key, &buf_len); + + m = (uint8_t *)OPENSSL_malloc(buf_len + 10); + if (m == NULL) { + OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (priv_key) { + if (!BIO_indent(bp, off, 128) || + BIO_printf(bp, "%s: (%d bit)\n", ktype, BN_num_bits(x->p)) <= 0) { + goto err; + } + } + + if (!bn_print(bp, "priv:", priv_key, m, off) || + !bn_print(bp, "pub: ", pub_key, m, off) || + !bn_print(bp, "P: ", x->p, m, off) || + !bn_print(bp, "Q: ", x->q, m, off) || + !bn_print(bp, "G: ", x->g, m, off)) { + goto err; + } + ret = 1; + +err: + OPENSSL_free(m); + return ret; +} + +static int dsa_param_print(BIO *bp, const EVP_PKEY *pkey, int indent, + ASN1_PCTX *ctx) { + return do_dsa_print(bp, pkey->pkey.dsa, indent, 0); +} + +static int dsa_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent, + ASN1_PCTX *ctx) { + return do_dsa_print(bp, pkey->pkey.dsa, indent, 1); +} + +static int dsa_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent, + ASN1_PCTX *ctx) { + return do_dsa_print(bp, pkey->pkey.dsa, indent, 2); +} + + +/* EC keys. */ + +static int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, int ktype) { + uint8_t *buffer = NULL; + const char *ecstr; + size_t buf_len = 0, i; + int ret = 0, reason = ERR_R_BIO_LIB; + BIGNUM *order = NULL; + BN_CTX *ctx = NULL; + const EC_GROUP *group; + const EC_POINT *public_key; + const BIGNUM *priv_key; + uint8_t *pub_key_bytes = NULL; + size_t pub_key_bytes_len = 0; + + if (x == NULL || (group = EC_KEY_get0_group(x)) == NULL) { + reason = ERR_R_PASSED_NULL_PARAMETER; + goto err; + } + + ctx = BN_CTX_new(); + if (ctx == NULL) { + reason = ERR_R_MALLOC_FAILURE; + goto err; + } + + if (ktype > 0) { + public_key = EC_KEY_get0_public_key(x); + if (public_key != NULL) { + pub_key_bytes_len = EC_POINT_point2oct( + group, public_key, EC_KEY_get_conv_form(x), NULL, 0, ctx); + if (pub_key_bytes_len == 0) { + reason = ERR_R_MALLOC_FAILURE; + goto err; + } + pub_key_bytes = OPENSSL_malloc(pub_key_bytes_len); + if (pub_key_bytes == NULL) { + reason = ERR_R_MALLOC_FAILURE; + goto err; + } + pub_key_bytes_len = + EC_POINT_point2oct(group, public_key, EC_KEY_get_conv_form(x), + pub_key_bytes, pub_key_bytes_len, ctx); + if (pub_key_bytes_len == 0) { + reason = ERR_R_MALLOC_FAILURE; + goto err; + } + buf_len = pub_key_bytes_len; + } + } + + if (ktype == 2) { + priv_key = EC_KEY_get0_private_key(x); + if (priv_key && (i = (size_t)BN_num_bytes(priv_key)) > buf_len) { + buf_len = i; + } + } else { + priv_key = NULL; + } + + if (ktype > 0) { + buf_len += 10; + if ((buffer = OPENSSL_malloc(buf_len)) == NULL) { + reason = ERR_R_MALLOC_FAILURE; + goto err; + } + } + if (ktype == 2) { + ecstr = "Private-Key"; + } else if (ktype == 1) { + ecstr = "Public-Key"; + } else { + ecstr = "ECDSA-Parameters"; + } + + if (!BIO_indent(bp, off, 128)) { + goto err; + } + order = BN_new(); + if (order == NULL || !EC_GROUP_get_order(group, order, NULL) || + BIO_printf(bp, "%s: (%d bit)\n", ecstr, BN_num_bits(order)) <= 0) { + goto err; + } + + if ((priv_key != NULL) && + !bn_print(bp, "priv:", priv_key, buffer, off)) { + goto err; + } + if (pub_key_bytes != NULL) { + BIO_hexdump(bp, pub_key_bytes, pub_key_bytes_len, off); + } + /* TODO(fork): implement */ + /* + if (!ECPKParameters_print(bp, group, off)) + goto err; */ + ret = 1; + +err: + if (!ret) { + OPENSSL_PUT_ERROR(EVP, reason); + } + OPENSSL_free(pub_key_bytes); + BN_free(order); + BN_CTX_free(ctx); + OPENSSL_free(buffer); + return ret; +} + +static int eckey_param_print(BIO *bp, const EVP_PKEY *pkey, int indent, + ASN1_PCTX *ctx) { + return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 0); +} + +static int eckey_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent, + ASN1_PCTX *ctx) { + return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 1); +} + + +static int eckey_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent, + ASN1_PCTX *ctx) { + return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 2); +} + + +typedef struct { + int type; + int (*pub_print)(BIO *out, const EVP_PKEY *pkey, int indent, ASN1_PCTX *pctx); + int (*priv_print)(BIO *out, const EVP_PKEY *pkey, int indent, + ASN1_PCTX *pctx); + int (*param_print)(BIO *out, const EVP_PKEY *pkey, int indent, + ASN1_PCTX *pctx); +} EVP_PKEY_PRINT_METHOD; + +static EVP_PKEY_PRINT_METHOD kPrintMethods[] = { + { + EVP_PKEY_RSA, + rsa_pub_print, + rsa_priv_print, + NULL /* param_print */, + }, + { + EVP_PKEY_DSA, + dsa_pub_print, + dsa_priv_print, + dsa_param_print, + }, + { + EVP_PKEY_EC, + eckey_pub_print, + eckey_priv_print, + eckey_param_print, + }, +}; + +static size_t kPrintMethodsLen = + sizeof(kPrintMethods) / sizeof(kPrintMethods[0]); + +static EVP_PKEY_PRINT_METHOD *find_method(int type) { + size_t i; + for (i = 0; i < kPrintMethodsLen; i++) { + if (kPrintMethods[i].type == type) { + return &kPrintMethods[i]; + } + } + return NULL; +} + +static int print_unsupported(BIO *out, const EVP_PKEY *pkey, int indent, + const char *kstr) { + BIO_indent(out, indent, 128); + BIO_printf(out, "%s algorithm unsupported\n", kstr); + return 1; +} + +int EVP_PKEY_print_public(BIO *out, const EVP_PKEY *pkey, int indent, + ASN1_PCTX *pctx) { + EVP_PKEY_PRINT_METHOD *method = find_method(pkey->type); + if (method != NULL && method->pub_print != NULL) { + return method->pub_print(out, pkey, indent, pctx); + } + return print_unsupported(out, pkey, indent, "Public Key"); +} + +int EVP_PKEY_print_private(BIO *out, const EVP_PKEY *pkey, int indent, + ASN1_PCTX *pctx) { + EVP_PKEY_PRINT_METHOD *method = find_method(pkey->type); + if (method != NULL && method->priv_print != NULL) { + return method->priv_print(out, pkey, indent, pctx); + } + return print_unsupported(out, pkey, indent, "Private Key"); +} + +int EVP_PKEY_print_params(BIO *out, const EVP_PKEY *pkey, int indent, + ASN1_PCTX *pctx) { + EVP_PKEY_PRINT_METHOD *method = find_method(pkey->type); + if (method != NULL && method->param_print != NULL) { + return method->param_print(out, pkey, indent, pctx); + } + return print_unsupported(out, pkey, indent, "Parameters"); +} diff --git a/external/boringssl/crypto/evp/sign.c b/external/boringssl/crypto/evp/sign.c new file mode 100644 index 0000000000..ced86bdf4b --- /dev/null +++ b/external/boringssl/crypto/evp/sign.c @@ -0,0 +1,151 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +#include "internal.h" + + +int EVP_SignInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl) { + return EVP_DigestInit_ex(ctx, type, impl); +} + +int EVP_SignInit(EVP_MD_CTX *ctx, const EVP_MD *type) { + return EVP_DigestInit(ctx, type); +} + +int EVP_SignUpdate(EVP_MD_CTX *ctx, const void *data, size_t len) { + return EVP_DigestUpdate(ctx, data, len); +} + +int EVP_SignFinal(const EVP_MD_CTX *ctx, uint8_t *sig, + unsigned int *out_sig_len, EVP_PKEY *pkey) { + uint8_t m[EVP_MAX_MD_SIZE]; + unsigned int m_len; + int ret = 0; + EVP_MD_CTX tmp_ctx; + EVP_PKEY_CTX *pkctx = NULL; + size_t sig_len = EVP_PKEY_size(pkey); + + *out_sig_len = 0; + EVP_MD_CTX_init(&tmp_ctx); + if (!EVP_MD_CTX_copy_ex(&tmp_ctx, ctx) || + !EVP_DigestFinal_ex(&tmp_ctx, m, &m_len)) { + goto out; + } + EVP_MD_CTX_cleanup(&tmp_ctx); + + pkctx = EVP_PKEY_CTX_new(pkey, NULL); + if (!pkctx || !EVP_PKEY_sign_init(pkctx) || + !EVP_PKEY_CTX_set_signature_md(pkctx, ctx->digest) || + !EVP_PKEY_sign(pkctx, sig, &sig_len, m, m_len)) { + goto out; + } + *out_sig_len = sig_len; + ret = 1; + +out: + if (pkctx) { + EVP_PKEY_CTX_free(pkctx); + } + + return ret; +} + +int EVP_VerifyInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl) { + return EVP_DigestInit_ex(ctx, type, impl); +} + +int EVP_VerifyInit(EVP_MD_CTX *ctx, const EVP_MD *type) { + return EVP_DigestInit(ctx, type); +} + +int EVP_VerifyUpdate(EVP_MD_CTX *ctx, const void *data, size_t len) { + return EVP_DigestUpdate(ctx, data, len); +} + +int EVP_VerifyFinal(EVP_MD_CTX *ctx, const uint8_t *sig, size_t sig_len, + EVP_PKEY *pkey) { + uint8_t m[EVP_MAX_MD_SIZE]; + unsigned int m_len; + int ret = 0; + EVP_MD_CTX tmp_ctx; + EVP_PKEY_CTX *pkctx = NULL; + + EVP_MD_CTX_init(&tmp_ctx); + if (!EVP_MD_CTX_copy_ex(&tmp_ctx, ctx) || + !EVP_DigestFinal_ex(&tmp_ctx, m, &m_len)) { + EVP_MD_CTX_cleanup(&tmp_ctx); + goto out; + } + EVP_MD_CTX_cleanup(&tmp_ctx); + + pkctx = EVP_PKEY_CTX_new(pkey, NULL); + if (!pkctx || + !EVP_PKEY_verify_init(pkctx) || + !EVP_PKEY_CTX_set_signature_md(pkctx, ctx->digest)) { + goto out; + } + ret = EVP_PKEY_verify(pkctx, sig, sig_len, m, m_len); + +out: + EVP_PKEY_CTX_free(pkctx); + return ret; +} + diff --git a/external/boringssl/crypto/ex_data.c b/external/boringssl/crypto/ex_data.c new file mode 100644 index 0000000000..d67abba2ba --- /dev/null +++ b/external/boringssl/crypto/ex_data.c @@ -0,0 +1,294 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "internal.h" + + +struct crypto_ex_data_func_st { + long argl; /* Arbitary long */ + void *argp; /* Arbitary void pointer */ + CRYPTO_EX_free *free_func; + CRYPTO_EX_dup *dup_func; +}; + +int CRYPTO_get_ex_new_index(CRYPTO_EX_DATA_CLASS *ex_data_class, int *out_index, + long argl, void *argp, CRYPTO_EX_dup *dup_func, + CRYPTO_EX_free *free_func) { + CRYPTO_EX_DATA_FUNCS *funcs; + int ret = 0; + + funcs = OPENSSL_malloc(sizeof(CRYPTO_EX_DATA_FUNCS)); + if (funcs == NULL) { + OPENSSL_PUT_ERROR(CRYPTO, ERR_R_MALLOC_FAILURE); + return 0; + } + + funcs->argl = argl; + funcs->argp = argp; + funcs->dup_func = dup_func; + funcs->free_func = free_func; + + CRYPTO_STATIC_MUTEX_lock_write(&ex_data_class->lock); + + if (ex_data_class->meth == NULL) { + ex_data_class->meth = sk_CRYPTO_EX_DATA_FUNCS_new_null(); + } + + if (ex_data_class->meth == NULL || + !sk_CRYPTO_EX_DATA_FUNCS_push(ex_data_class->meth, funcs)) { + OPENSSL_PUT_ERROR(CRYPTO, ERR_R_MALLOC_FAILURE); + OPENSSL_free(funcs); + goto err; + } + + *out_index = sk_CRYPTO_EX_DATA_FUNCS_num(ex_data_class->meth) - 1 + + ex_data_class->num_reserved; + ret = 1; + +err: + CRYPTO_STATIC_MUTEX_unlock_write(&ex_data_class->lock); + return ret; +} + +int CRYPTO_set_ex_data(CRYPTO_EX_DATA *ad, int index, void *val) { + int n, i; + + if (ad->sk == NULL) { + ad->sk = sk_void_new_null(); + if (ad->sk == NULL) { + OPENSSL_PUT_ERROR(CRYPTO, ERR_R_MALLOC_FAILURE); + return 0; + } + } + + n = sk_void_num(ad->sk); + + /* Add NULL values until the stack is long enough. */ + for (i = n; i <= index; i++) { + if (!sk_void_push(ad->sk, NULL)) { + OPENSSL_PUT_ERROR(CRYPTO, ERR_R_MALLOC_FAILURE); + return 0; + } + } + + sk_void_set(ad->sk, index, val); + return 1; +} + +void *CRYPTO_get_ex_data(const CRYPTO_EX_DATA *ad, int idx) { + if (ad->sk == NULL || idx < 0 || (size_t)idx >= sk_void_num(ad->sk)) { + return NULL; + } + return sk_void_value(ad->sk, idx); +} + +/* get_func_pointers takes a copy of the CRYPTO_EX_DATA_FUNCS pointers, if any, + * for the given class. If there are some pointers, it sets |*out| to point to + * a fresh stack of them. Otherwise it sets |*out| to NULL. It returns one on + * success or zero on error. */ +static int get_func_pointers(STACK_OF(CRYPTO_EX_DATA_FUNCS) **out, + CRYPTO_EX_DATA_CLASS *ex_data_class) { + size_t n; + + *out = NULL; + + /* CRYPTO_EX_DATA_FUNCS structures are static once set, so we can take a + * shallow copy of the list under lock and then use the structures without + * the lock held. */ + CRYPTO_STATIC_MUTEX_lock_read(&ex_data_class->lock); + n = sk_CRYPTO_EX_DATA_FUNCS_num(ex_data_class->meth); + if (n > 0) { + *out = sk_CRYPTO_EX_DATA_FUNCS_dup(ex_data_class->meth); + } + CRYPTO_STATIC_MUTEX_unlock_read(&ex_data_class->lock); + + if (n > 0 && *out == NULL) { + OPENSSL_PUT_ERROR(CRYPTO, ERR_R_MALLOC_FAILURE); + return 0; + } + + return 1; +} + +void CRYPTO_new_ex_data(CRYPTO_EX_DATA *ad) { + ad->sk = NULL; +} + +int CRYPTO_dup_ex_data(CRYPTO_EX_DATA_CLASS *ex_data_class, CRYPTO_EX_DATA *to, + const CRYPTO_EX_DATA *from) { + if (from->sk == NULL) { + /* In this case, |from| is blank, which is also the initial state of |to|, + * so there's nothing to do. */ + return 1; + } + + STACK_OF(CRYPTO_EX_DATA_FUNCS) *func_pointers; + if (!get_func_pointers(&func_pointers, ex_data_class)) { + return 0; + } + + size_t i; + for (i = 0; i < sk_CRYPTO_EX_DATA_FUNCS_num(func_pointers); i++) { + CRYPTO_EX_DATA_FUNCS *func_pointer = + sk_CRYPTO_EX_DATA_FUNCS_value(func_pointers, i); + void *ptr = CRYPTO_get_ex_data(from, i + ex_data_class->num_reserved); + if (func_pointer->dup_func) { + func_pointer->dup_func(to, from, &ptr, i + ex_data_class->num_reserved, + func_pointer->argl, func_pointer->argp); + } + CRYPTO_set_ex_data(to, i + ex_data_class->num_reserved, ptr); + } + + sk_CRYPTO_EX_DATA_FUNCS_free(func_pointers); + + return 1; +} + +void CRYPTO_free_ex_data(CRYPTO_EX_DATA_CLASS *ex_data_class, void *obj, + CRYPTO_EX_DATA *ad) { + if (ad->sk == NULL) { + /* Nothing to do. */ + return; + } + + STACK_OF(CRYPTO_EX_DATA_FUNCS) *func_pointers; + if (!get_func_pointers(&func_pointers, ex_data_class)) { + /* TODO(davidben): This leaks memory on malloc error. */ + return; + } + + size_t i; + for (i = 0; i < sk_CRYPTO_EX_DATA_FUNCS_num(func_pointers); i++) { + CRYPTO_EX_DATA_FUNCS *func_pointer = + sk_CRYPTO_EX_DATA_FUNCS_value(func_pointers, i); + if (func_pointer->free_func) { + void *ptr = CRYPTO_get_ex_data(ad, i + ex_data_class->num_reserved); + func_pointer->free_func(obj, ptr, ad, i + ex_data_class->num_reserved, + func_pointer->argl, func_pointer->argp); + } + } + + sk_CRYPTO_EX_DATA_FUNCS_free(func_pointers); + + sk_void_free(ad->sk); + ad->sk = NULL; +} + +void CRYPTO_cleanup_all_ex_data(void) {} diff --git a/external/boringssl/crypto/hkdf/CMakeLists.txt b/external/boringssl/crypto/hkdf/CMakeLists.txt new file mode 100644 index 0000000000..df9f0d0d69 --- /dev/null +++ b/external/boringssl/crypto/hkdf/CMakeLists.txt @@ -0,0 +1,22 @@ +include_directories(../../include) + +add_library( + hkdf + + OBJECT + + hkdf.c +) + +if(ENABLE_TESTS) +add_executable( + hkdf_test + + hkdf_test.c + + $ +) + +target_link_libraries(hkdf_test crypto) +add_dependencies(all_tests hkdf_test) +endif() diff --git a/external/boringssl/crypto/hkdf/hkdf.c b/external/boringssl/crypto/hkdf/hkdf.c new file mode 100644 index 0000000000..d80834d897 --- /dev/null +++ b/external/boringssl/crypto/hkdf/hkdf.c @@ -0,0 +1,110 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include +#include + +#include +#include + + +int HKDF(uint8_t *out_key, size_t out_len, const EVP_MD *digest, + const uint8_t *secret, size_t secret_len, const uint8_t *salt, + size_t salt_len, const uint8_t *info, size_t info_len) { + /* https://tools.ietf.org/html/rfc5869#section-2 */ + uint8_t prk[EVP_MAX_MD_SIZE]; + size_t prk_len; + + if (!HKDF_extract(prk, &prk_len, digest, secret, secret_len, salt, + salt_len) || + !HKDF_expand(out_key, out_len, digest, prk, prk_len, info, info_len)) { + return 0; + } + + return 1; +} + +int HKDF_extract(uint8_t *out_key, size_t *out_len, const EVP_MD *digest, + const uint8_t *secret, size_t secret_len, const uint8_t *salt, + size_t salt_len) { + /* https://tools.ietf.org/html/rfc5869#section-2.2 */ + + /* If salt is not given, HashLength zeros are used. However, HMAC does that + * internally already so we can ignore it.*/ + unsigned len; + if (HMAC(digest, salt, salt_len, secret, secret_len, out_key, &len) == NULL) { + OPENSSL_PUT_ERROR(HKDF, ERR_R_HMAC_LIB); + return 0; + } + *out_len = len; + assert(*out_len == EVP_MD_size(digest)); + return 1; +} + +int HKDF_expand(uint8_t *out_key, size_t out_len, const EVP_MD *digest, + uint8_t *prk, size_t prk_len, const uint8_t *info, + size_t info_len) { + /* https://tools.ietf.org/html/rfc5869#section-2.3 */ + const size_t digest_len = EVP_MD_size(digest); + uint8_t previous[EVP_MAX_MD_SIZE]; + size_t n, done = 0; + unsigned i; + int ret = 0; + HMAC_CTX hmac; + + /* Expand key material to desired length. */ + n = (out_len + digest_len - 1) / digest_len; + if (out_len + digest_len < out_len || n > 255) { + OPENSSL_PUT_ERROR(HKDF, HKDF_R_OUTPUT_TOO_LARGE); + return 0; + } + + HMAC_CTX_init(&hmac); + if (!HMAC_Init_ex(&hmac, prk, prk_len, digest, NULL)) { + goto out; + } + + for (i = 0; i < n; i++) { + uint8_t ctr = i + 1; + size_t todo; + + if (i != 0 && (!HMAC_Init_ex(&hmac, NULL, 0, NULL, NULL) || + !HMAC_Update(&hmac, previous, digest_len))) { + goto out; + } + if (!HMAC_Update(&hmac, info, info_len) || + !HMAC_Update(&hmac, &ctr, 1) || + !HMAC_Final(&hmac, previous, NULL)) { + goto out; + } + + todo = digest_len; + if (done + todo > out_len) { + todo = out_len - done; + } + memcpy(out_key + done, previous, todo); + done += todo; + } + + ret = 1; + +out: + HMAC_CTX_cleanup(&hmac); + if (ret != 1) { + OPENSSL_PUT_ERROR(HKDF, ERR_R_HMAC_LIB); + } + return ret; +} diff --git a/external/boringssl/crypto/hkdf/hkdf_test.c b/external/boringssl/crypto/hkdf/hkdf_test.c new file mode 100644 index 0000000000..a0f75a96eb --- /dev/null +++ b/external/boringssl/crypto/hkdf/hkdf_test.c @@ -0,0 +1,296 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include + +#include +#include +#include +#include + +#include "../test/test_util.h" + + +typedef struct { + const EVP_MD *(*md_func)(void); + const uint8_t ikm[80]; + const size_t ikm_len; + const uint8_t salt[80]; + const size_t salt_len; + const uint8_t info[80]; + const size_t info_len; + const uint8_t prk[EVP_MAX_MD_SIZE]; + const size_t prk_len; + const size_t out_len; + const uint8_t out[82]; +} hkdf_test_vector_t; + +/* These test vectors are from RFC 5869. */ +static const hkdf_test_vector_t kTests[] = { + { + EVP_sha256, + { + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + }, 22, + { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, + }, 13, + { + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, + }, 10, + { + 0x07, 0x77, 0x09, 0x36, 0x2c, 0x2e, 0x32, 0xdf, 0x0d, 0xdc, 0x3f, 0x0d, + 0xc4, 0x7b, 0xba, 0x63, 0x90, 0xb6, 0xc7, 0x3b, 0xb5, 0x0f, 0x9c, 0x31, + 0x22, 0xec, 0x84, 0x4a, 0xd7, 0xc2, 0xb3, 0xe5, + }, 32, + 42, { + 0x3c, 0xb2, 0x5f, 0x25, 0xfa, 0xac, 0xd5, 0x7a, 0x90, 0x43, 0x4f, 0x64, + 0xd0, 0x36, 0x2f, 0x2a, 0x2d, 0x2d, 0x0a, 0x90, 0xcf, 0x1a, 0x5a, 0x4c, + 0x5d, 0xb0, 0x2d, 0x56, 0xec, 0xc4, 0xc5, 0xbf, 0x34, 0x00, 0x72, 0x08, + 0xd5, 0xb8, 0x87, 0x18, 0x58, 0x65 + } + }, + { + EVP_sha256, + { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, + 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, + 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f + }, 80, + { + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, + 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, + 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, + 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf + }, 80, + { + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, + 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, + 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, + 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff + }, 80, + { + 0x06, 0xa6, 0xb8, 0x8c, 0x58, 0x53, 0x36, 0x1a, 0x06, 0x10, 0x4c, 0x9c, + 0xeb, 0x35, 0xb4, 0x5c, 0xef, 0x76, 0x00, 0x14, 0x90, 0x46, 0x71, 0x01, + 0x4a, 0x19, 0x3f, 0x40, 0xc1, 0x5f, 0xc2, 0x44, + }, 32, + 82, { + 0xb1, 0x1e, 0x39, 0x8d, 0xc8, 0x03, 0x27, 0xa1, 0xc8, 0xe7, 0xf7, 0x8c, + 0x59, 0x6a, 0x49, 0x34, 0x4f, 0x01, 0x2e, 0xda, 0x2d, 0x4e, 0xfa, 0xd8, + 0xa0, 0x50, 0xcc, 0x4c, 0x19, 0xaf, 0xa9, 0x7c, 0x59, 0x04, 0x5a, 0x99, + 0xca, 0xc7, 0x82, 0x72, 0x71, 0xcb, 0x41, 0xc6, 0x5e, 0x59, 0x0e, 0x09, + 0xda, 0x32, 0x75, 0x60, 0x0c, 0x2f, 0x09, 0xb8, 0x36, 0x77, 0x93, 0xa9, + 0xac, 0xa3, 0xdb, 0x71, 0xcc, 0x30, 0xc5, 0x81, 0x79, 0xec, 0x3e, 0x87, + 0xc1, 0x4c, 0x01, 0xd5, 0xc1, 0xf3, 0x43, 0x4f, 0x1d, 0x87 + } + }, + { + EVP_sha256, + { + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + }, 22, + { + 0, + }, 0, + { + 0, + }, 0, + { + 0x19, 0xef, 0x24, 0xa3, 0x2c, 0x71, 0x7b, 0x16, 0x7f, 0x33, 0xa9, 0x1d, + 0x6f, 0x64, 0x8b, 0xdf, 0x96, 0x59, 0x67, 0x76, 0xaf, 0xdb, 0x63, 0x77, + 0xac, 0x43, 0x4c, 0x1c, 0x29, 0x3c, 0xcb, 0x04 + }, 32, + 42, { + 0x8d, 0xa4, 0xe7, 0x75, 0xa5, 0x63, 0xc1, 0x8f, 0x71, 0x5f, 0x80, 0x2a, + 0x06, 0x3c, 0x5a, 0x31, 0xb8, 0xa1, 0x1f, 0x5c, 0x5e, 0xe1, 0x87, 0x9e, + 0xc3, 0x45, 0x4e, 0x5f, 0x3c, 0x73, 0x8d, 0x2d, 0x9d, 0x20, 0x13, 0x95, + 0xfa, 0xa4, 0xb6, 0x1a, 0x96, 0xc8 + } + }, + { + EVP_sha1, + { + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + }, 11, + { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, + }, 13, + { + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, + }, 10, + { + 0x9b, 0x6c, 0x18, 0xc4, 0x32, 0xa7, 0xbf, 0x8f, 0x0e, 0x71, 0xc8, 0xeb, + 0x88, 0xf4, 0xb3, 0x0b, 0xaa, 0x2b, 0xa2, 0x43 + }, 20, + 42, { + 0x08, 0x5a, 0x01, 0xea, 0x1b, 0x10, 0xf3, 0x69, 0x33, 0x06, 0x8b, 0x56, + 0xef, 0xa5, 0xad, 0x81, 0xa4, 0xf1, 0x4b, 0x82, 0x2f, 0x5b, 0x09, 0x15, + 0x68, 0xa9, 0xcd, 0xd4, 0xf1, 0x55, 0xfd, 0xa2, 0xc2, 0x2e, 0x42, 0x24, + 0x78, 0xd3, 0x05, 0xf3, 0xf8, 0x96 + } + }, + { + EVP_sha1, + { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, + 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, + 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f + }, 80, + { + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, + 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, + 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, + 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf + }, 80, + { + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, + 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, + 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, + 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff + }, 80, + { + 0x8a, 0xda, 0xe0, 0x9a, 0x2a, 0x30, 0x70, 0x59, 0x47, 0x8d, 0x30, 0x9b, + 0x26, 0xc4, 0x11, 0x5a, 0x22, 0x4c, 0xfa, 0xf6, + }, 20, + 82, { + 0x0b, 0xd7, 0x70, 0xa7, 0x4d, 0x11, 0x60, 0xf7, 0xc9, 0xf1, 0x2c, 0xd5, + 0x91, 0x2a, 0x06, 0xeb, 0xff, 0x6a, 0xdc, 0xae, 0x89, 0x9d, 0x92, 0x19, + 0x1f, 0xe4, 0x30, 0x56, 0x73, 0xba, 0x2f, 0xfe, 0x8f, 0xa3, 0xf1, 0xa4, + 0xe5, 0xad, 0x79, 0xf3, 0xf3, 0x34, 0xb3, 0xb2, 0x02, 0xb2, 0x17, 0x3c, + 0x48, 0x6e, 0xa3, 0x7c, 0xe3, 0xd3, 0x97, 0xed, 0x03, 0x4c, 0x7f, 0x9d, + 0xfe, 0xb1, 0x5c, 0x5e, 0x92, 0x73, 0x36, 0xd0, 0x44, 0x1f, 0x4c, 0x43, + 0x00, 0xe2, 0xcf, 0xf0, 0xd0, 0x90, 0x0b, 0x52, 0xd3, 0xb4 + } + }, + { + EVP_sha1, + { + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + }, 22, + { + 0, + }, 0, + { + 0, + }, 0, + { + 0xda, 0x8c, 0x8a, 0x73, 0xc7, 0xfa, 0x77, 0x28, 0x8e, 0xc6, 0xf5, 0xe7, + 0xc2, 0x97, 0x78, 0x6a, 0xa0, 0xd3, 0x2d, 0x01, + }, 20, + 42, { + 0x0a, 0xc1, 0xaf, 0x70, 0x02, 0xb3, 0xd7, 0x61, 0xd1, 0xe5, 0x52, 0x98, + 0xda, 0x9d, 0x05, 0x06, 0xb9, 0xae, 0x52, 0x05, 0x72, 0x20, 0xa3, 0x06, + 0xe0, 0x7b, 0x6b, 0x87, 0xe8, 0xdf, 0x21, 0xd0, 0xea, 0x00, 0x03, 0x3d, + 0xe0, 0x39, 0x84, 0xd3, 0x49, 0x18 + } + }, + { + EVP_sha1, + { + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + }, 22, + { + 0, + }, 0, + { + 0, + }, 0, + { + 0x2a, 0xdc, 0xca, 0xda, 0x18, 0x77, 0x9e, 0x7c, 0x20, 0x77, 0xad, 0x2e, + 0xb1, 0x9d, 0x3f, 0x3e, 0x73, 0x13, 0x85, 0xdd, + }, 20, + 42, { + 0x2c, 0x91, 0x11, 0x72, 0x04, 0xd7, 0x45, 0xf3, 0x50, 0x0d, 0x63, 0x6a, + 0x62, 0xf6, 0x4f, 0x0a, 0xb3, 0xba, 0xe5, 0x48, 0xaa, 0x53, 0xd4, 0x23, + 0xb0, 0xd1, 0xf2, 0x7e, 0xbb, 0xa6, 0xf5, 0xe5, 0x67, 0x3a, 0x08, 0x1d, + 0x70, 0xcc, 0xe7, 0xac, 0xfc, 0x48 + } + }, +}; + +int main(void) { + uint8_t buf[82], prk[EVP_MAX_MD_SIZE]; + size_t i, prk_len; + + CRYPTO_library_init(); + + for (i = 0; i < sizeof(kTests) / sizeof(kTests[0]); i++) { + const hkdf_test_vector_t *test = &kTests[i]; + if (!HKDF_extract(prk, &prk_len, test->md_func(), test->ikm, test->ikm_len, + test->salt, test->salt_len)) { + fprintf(stderr, "Call to HKDF_extract failed\n"); + ERR_print_errors_fp(stderr); + return 1; + } + if (prk_len != test->prk_len || + memcmp(prk, test->prk, test->prk_len) != 0) { + fprintf(stderr, "%zu: Resulting PRK does not match test vector\n", i); + return 1; + } + if (!HKDF_expand(buf, test->out_len, test->md_func(), prk, prk_len, + test->info, test->info_len)) { + fprintf(stderr, "Call to HKDF_expand failed\n"); + ERR_print_errors_fp(stderr); + return 1; + } + if (memcmp(buf, test->out, test->out_len) != 0) { + fprintf(stderr, + "%zu: Resulting key material does not match test vector\n", i); + return 1; + } + + if (!HKDF(buf, test->out_len, test->md_func(), test->ikm, test->ikm_len, + test->salt, test->salt_len, test->info, test->info_len)) { + fprintf(stderr, "Call to HKDF failed\n"); + ERR_print_errors_fp(stderr); + return 1; + } + if (memcmp(buf, test->out, test->out_len) != 0) { + fprintf(stderr, + "%zu: Resulting key material does not match test vector\n", i); + return 1; + } + } + + printf("PASS\n"); + ERR_free_strings(); + return 0; +} diff --git a/external/boringssl/crypto/hmac/CMakeLists.txt b/external/boringssl/crypto/hmac/CMakeLists.txt new file mode 100644 index 0000000000..40b73bcd51 --- /dev/null +++ b/external/boringssl/crypto/hmac/CMakeLists.txt @@ -0,0 +1,23 @@ +include_directories(../../include) + +add_library( + hmac + + OBJECT + + hmac.c +) + + +if(ENABLE_TESTS) +add_executable( + hmac_test + + hmac_test.cc + + $ +) + +target_link_libraries(hmac_test crypto) +add_dependencies(all_tests hmac_test) +endif() diff --git a/external/boringssl/crypto/hmac/hmac.c b/external/boringssl/crypto/hmac/hmac.c new file mode 100644 index 0000000000..bccc5c02bd --- /dev/null +++ b/external/boringssl/crypto/hmac/hmac.c @@ -0,0 +1,214 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +#include +#include + + +uint8_t *HMAC(const EVP_MD *evp_md, const void *key, size_t key_len, + const uint8_t *data, size_t data_len, uint8_t *out, + unsigned int *out_len) { + HMAC_CTX ctx; + static uint8_t static_out_buffer[EVP_MAX_MD_SIZE]; + + /* OpenSSL has traditionally supported using a static buffer if |out| is + * NULL. We maintain that but don't document it. This behaviour should be + * considered to be deprecated. */ + if (out == NULL) { + out = static_out_buffer; + } + + HMAC_CTX_init(&ctx); + if (!HMAC_Init_ex(&ctx, key, key_len, evp_md, NULL) || + !HMAC_Update(&ctx, data, data_len) || + !HMAC_Final(&ctx, out, out_len)) { + out = NULL; + } + + HMAC_CTX_cleanup(&ctx); + return out; +} + +void HMAC_CTX_init(HMAC_CTX *ctx) { + ctx->md = NULL; + EVP_MD_CTX_init(&ctx->i_ctx); + EVP_MD_CTX_init(&ctx->o_ctx); + EVP_MD_CTX_init(&ctx->md_ctx); +} + +void HMAC_CTX_cleanup(HMAC_CTX *ctx) { + EVP_MD_CTX_cleanup(&ctx->i_ctx); + EVP_MD_CTX_cleanup(&ctx->o_ctx); + EVP_MD_CTX_cleanup(&ctx->md_ctx); + OPENSSL_cleanse(ctx, sizeof(HMAC_CTX)); +} + +int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, size_t key_len, + const EVP_MD *md, ENGINE *impl) { + if (md == NULL) { + md = ctx->md; + } + + /* If either |key| is non-NULL or |md| has changed, initialize with a new key + * rather than rewinding the previous one. + * + * TODO(davidben,eroman): Passing the previous |md| with a NULL |key| is + * ambiguous between using the empty key and reusing the previous key. There + * exist callers which intend the latter, but the former is an awkward edge + * case. Fix to API to avoid this. */ + if (md != ctx->md || key != NULL) { + size_t i; + uint8_t pad[EVP_MAX_MD_BLOCK_SIZE]; + uint8_t key_block[EVP_MAX_MD_BLOCK_SIZE]; + unsigned key_block_len; + + size_t block_size = EVP_MD_block_size(md); + assert(block_size <= sizeof(key_block)); + if (block_size < key_len) { + /* Long keys are hashed. */ + if (!EVP_DigestInit_ex(&ctx->md_ctx, md, impl) || + !EVP_DigestUpdate(&ctx->md_ctx, key, key_len) || + !EVP_DigestFinal_ex(&ctx->md_ctx, key_block, &key_block_len)) { + return 0; + } + } else { + assert(key_len <= sizeof(key_block)); + memcpy(key_block, key, key_len); + key_block_len = (unsigned)key_len; + } + /* Keys are then padded with zeros. */ + if (key_block_len != EVP_MAX_MD_BLOCK_SIZE) { + memset(&key_block[key_block_len], 0, sizeof(key_block) - key_block_len); + } + + for (i = 0; i < EVP_MAX_MD_BLOCK_SIZE; i++) { + pad[i] = 0x36 ^ key_block[i]; + } + if (!EVP_DigestInit_ex(&ctx->i_ctx, md, impl) || + !EVP_DigestUpdate(&ctx->i_ctx, pad, EVP_MD_block_size(md))) { + return 0; + } + + for (i = 0; i < EVP_MAX_MD_BLOCK_SIZE; i++) { + pad[i] = 0x5c ^ key_block[i]; + } + if (!EVP_DigestInit_ex(&ctx->o_ctx, md, impl) || + !EVP_DigestUpdate(&ctx->o_ctx, pad, EVP_MD_block_size(md))) { + return 0; + } + + ctx->md = md; + } + + if (!EVP_MD_CTX_copy_ex(&ctx->md_ctx, &ctx->i_ctx)) { + return 0; + } + + return 1; +} + +int HMAC_Update(HMAC_CTX *ctx, const uint8_t *data, size_t data_len) { + return EVP_DigestUpdate(&ctx->md_ctx, data, data_len); +} + +int HMAC_Final(HMAC_CTX *ctx, uint8_t *out, unsigned int *out_len) { + unsigned int i; + uint8_t buf[EVP_MAX_MD_SIZE]; + + /* TODO(davidben): The only thing that can officially fail here is + * |EVP_MD_CTX_copy_ex|, but even that should be impossible in this case. */ + if (!EVP_DigestFinal_ex(&ctx->md_ctx, buf, &i) || + !EVP_MD_CTX_copy_ex(&ctx->md_ctx, &ctx->o_ctx) || + !EVP_DigestUpdate(&ctx->md_ctx, buf, i) || + !EVP_DigestFinal_ex(&ctx->md_ctx, out, out_len)) { + *out_len = 0; + return 0; + } + + return 1; +} + +size_t HMAC_size(const HMAC_CTX *ctx) { + return EVP_MD_size(ctx->md); +} + +int HMAC_CTX_copy_ex(HMAC_CTX *dest, const HMAC_CTX *src) { + if (!EVP_MD_CTX_copy_ex(&dest->i_ctx, &src->i_ctx) || + !EVP_MD_CTX_copy_ex(&dest->o_ctx, &src->o_ctx) || + !EVP_MD_CTX_copy_ex(&dest->md_ctx, &src->md_ctx)) { + return 0; + } + + dest->md = src->md; + return 1; +} + +int HMAC_Init(HMAC_CTX *ctx, const void *key, int key_len, const EVP_MD *md) { + if (key && md) { + HMAC_CTX_init(ctx); + } + return HMAC_Init_ex(ctx, key, key_len, md, NULL); +} + +int HMAC_CTX_copy(HMAC_CTX *dest, const HMAC_CTX *src) { + HMAC_CTX_init(dest); + return HMAC_CTX_copy_ex(dest, src); +} diff --git a/external/boringssl/crypto/hmac/hmac_test.cc b/external/boringssl/crypto/hmac/hmac_test.cc new file mode 100644 index 0000000000..da390ef814 --- /dev/null +++ b/external/boringssl/crypto/hmac/hmac_test.cc @@ -0,0 +1,164 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include +#include + +#include +#include + +#include +#include +#include + +#include "../test/file_test.h" +#include "../test/scoped_types.h" + + +static const EVP_MD *GetDigest(const std::string &name) { + if (name == "MD5") { + return EVP_md5(); + } else if (name == "SHA1") { + return EVP_sha1(); + } else if (name == "SHA224") { + return EVP_sha224(); + } else if (name == "SHA256") { + return EVP_sha256(); + } else if (name == "SHA384") { + return EVP_sha384(); + } else if (name == "SHA512") { + return EVP_sha512(); + } + return nullptr; +} + +static bool TestHMAC(FileTest *t, void *arg) { + std::string digest_str; + if (!t->GetAttribute(&digest_str, "HMAC")) { + return false; + } + const EVP_MD *digest = GetDigest(digest_str); + if (digest == nullptr) { + t->PrintLine("Unknown digest '%s'", digest_str.c_str()); + return false; + } + + std::vector key, input, output; + if (!t->GetBytes(&key, "Key") || + !t->GetBytes(&input, "Input") || + !t->GetBytes(&output, "Output")) { + return false; + } + + // Test using the one-shot API. + uint8_t mac[EVP_MAX_MD_SIZE]; + unsigned mac_len; + if (nullptr == HMAC(digest, key.data(), key.size(), input.data(), + input.size(), mac, &mac_len) || + !t->ExpectBytesEqual(output.data(), output.size(), mac, mac_len)) { + t->PrintLine("One-shot API failed."); + return false; + } + + // Test using HMAC_CTX. + ScopedHMAC_CTX ctx; + if (!HMAC_Init_ex(ctx.get(), key.data(), key.size(), digest, nullptr) || + !HMAC_Update(ctx.get(), input.data(), input.size()) || + !HMAC_Final(ctx.get(), mac, &mac_len) || + !t->ExpectBytesEqual(output.data(), output.size(), mac, mac_len)) { + t->PrintLine("HMAC_CTX failed."); + return false; + } + + // Test that an HMAC_CTX may be reset with the same key. + if (!HMAC_Init_ex(ctx.get(), nullptr, 0, digest, nullptr) || + !HMAC_Update(ctx.get(), input.data(), input.size()) || + !HMAC_Final(ctx.get(), mac, &mac_len) || + !t->ExpectBytesEqual(output.data(), output.size(), mac, mac_len)) { + t->PrintLine("HMAC_CTX with reset failed."); + return false; + } + + // Test feeding the input in byte by byte. + if (!HMAC_Init_ex(ctx.get(), nullptr, 0, nullptr, nullptr)) { + t->PrintLine("HMAC_CTX streaming failed."); + return false; + } + for (size_t i = 0; i < input.size(); i++) { + if (!HMAC_Update(ctx.get(), &input[i], 1)) { + t->PrintLine("HMAC_CTX streaming failed."); + return false; + } + } + if (!HMAC_Final(ctx.get(), mac, &mac_len) || + !t->ExpectBytesEqual(output.data(), output.size(), mac, mac_len)) { + t->PrintLine("HMAC_CTX streaming failed."); + return false; + } + + return true; +} + +int main(int argc, char *argv[]) { + CRYPTO_library_init(); + + if (argc != 2) { + fprintf(stderr, "%s \n", argv[0]); + return 1; + } + + return FileTestMain(TestHMAC, nullptr, argv[1]); +} diff --git a/external/boringssl/crypto/hmac/hmac_tests.txt b/external/boringssl/crypto/hmac/hmac_tests.txt new file mode 100644 index 0000000000..53f3f8f9a9 --- /dev/null +++ b/external/boringssl/crypto/hmac/hmac_tests.txt @@ -0,0 +1,120 @@ +HMAC = MD5 +# Note: The empty key results in passing NULL to HMAC_Init_ex, so this tests +# that HMAC_CTX and HMAC treat NULL as the empty key initially. +Key = +Input = "More text test vectors to stuff up EBCDIC machines :-)" +Output = e9139d1e6ee064ef8cf514fc7dc83e86 + +# HMAC tests from RFC2104 +HMAC = MD5 +Key = 0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b +Input = "Hi There" +Output = 9294727a3638bb1c13f48ef8158bfc9d + +HMAC = MD5 +Key = "Jefe" +Input = "what do ya want for nothing?" +Output = 750c783e6ab0b503eaa86e310a5db738 + +HMAC = MD5 +Key = AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +Input = DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD +Output = 56be34521d144c88dbb8c733f0e8b3f6 + +# HMAC tests from NIST test data + +HMAC = SHA1 +Input = "Sample message for keylen=blocklen" +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F +Output = 5FD596EE78D5553C8FF4E72D266DFD192366DA29 + +HMAC = SHA1 +Input = "Sample message for keylen +#include + +#if defined(_MSC_VER) +#if !defined(__cplusplus) || _MSC_VER < 1900 +#define alignas(x) __declspec(align(x)) +#define alignof __alignof +#endif +#else +#include +#endif + +#if defined(OPENSSL_NO_THREADS) +#elif defined(OPENSSL_WINDOWS) +OPENSSL_MSVC_PRAGMA(warning(push, 3)) +#include +OPENSSL_MSVC_PRAGMA(warning(pop)) +#else +#include +#endif + +#if defined(__cplusplus) +extern "C" { +#endif + + +#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64) || defined(OPENSSL_ARM) || \ + defined(OPENSSL_AARCH64) +/* OPENSSL_cpuid_setup initializes OPENSSL_ia32cap_P. */ +void OPENSSL_cpuid_setup(void); +#endif + +#if !defined(inline) +#define inline __inline +#endif + + +#if !defined(_MSC_VER) && defined(OPENSSL_64_BIT) +typedef __int128_t int128_t; +typedef __uint128_t uint128_t; +#endif + + +/* buffers_alias returns one if |a| and |b| alias and zero otherwise. */ +static inline int buffers_alias(const uint8_t *a, size_t a_len, + const uint8_t *b, size_t b_len) { + /* Cast |a| and |b| to integers. In C, pointer comparisons between unrelated + * objects are undefined whereas pointer to integer conversions are merely + * implementation-defined. We assume the implementation defined it in a sane + * way. */ + uintptr_t a_u = (uintptr_t)a; + uintptr_t b_u = (uintptr_t)b; + return a_u + a_len > b_u && b_u + b_len > a_u; +} + + +/* Constant-time utility functions. + * + * The following methods return a bitmask of all ones (0xff...f) for true and 0 + * for false. This is useful for choosing a value based on the result of a + * conditional in constant time. For example, + * + * if (a < b) { + * c = a; + * } else { + * c = b; + * } + * + * can be written as + * + * unsigned int lt = constant_time_lt(a, b); + * c = constant_time_select(lt, a, b); */ + +/* constant_time_msb returns the given value with the MSB copied to all the + * other bits. */ +static inline unsigned int constant_time_msb(unsigned int a) { + return (unsigned int)((int)(a) >> (sizeof(int) * 8 - 1)); +} + +/* constant_time_lt returns 0xff..f if a < b and 0 otherwise. */ +static inline unsigned int constant_time_lt(unsigned int a, unsigned int b) { + /* Consider the two cases of the problem: + * msb(a) == msb(b): a < b iff the MSB of a - b is set. + * msb(a) != msb(b): a < b iff the MSB of b is set. + * + * If msb(a) == msb(b) then the following evaluates as: + * msb(a^((a^b)|((a-b)^a))) == + * msb(a^((a-b) ^ a)) == (because msb(a^b) == 0) + * msb(a^a^(a-b)) == (rearranging) + * msb(a-b) (because ∀x. x^x == 0) + * + * Else, if msb(a) != msb(b) then the following evaluates as: + * msb(a^((a^b)|((a-b)^a))) == + * msb(a^(🙠| ((a-b)^a))) == (because msb(a^b) == 1 and 🙠+ * represents a value s.t. msb(ðŸ™) = 1) + * msb(a^ðŸ™) == (because ORing with 1 results in 1) + * msb(b) + * + * + * Here is an SMT-LIB verification of this formula: + * + * (define-fun lt ((a (_ BitVec 32)) (b (_ BitVec 32))) (_ BitVec 32) + * (bvxor a (bvor (bvxor a b) (bvxor (bvsub a b) a))) + * ) + * + * (declare-fun a () (_ BitVec 32)) + * (declare-fun b () (_ BitVec 32)) + * + * (assert (not (= (= #x00000001 (bvlshr (lt a b) #x0000001f)) (bvult a b)))) + * (check-sat) + * (get-model) + */ + return constant_time_msb(a^((a^b)|((a-b)^a))); +} + +/* constant_time_lt_8 acts like |constant_time_lt| but returns an 8-bit mask. */ +static inline uint8_t constant_time_lt_8(unsigned int a, unsigned int b) { + return (uint8_t)(constant_time_lt(a, b)); +} + +/* constant_time_gt returns 0xff..f if a >= b and 0 otherwise. */ +static inline unsigned int constant_time_ge(unsigned int a, unsigned int b) { + return ~constant_time_lt(a, b); +} + +/* constant_time_ge_8 acts like |constant_time_ge| but returns an 8-bit mask. */ +static inline uint8_t constant_time_ge_8(unsigned int a, unsigned int b) { + return (uint8_t)(constant_time_ge(a, b)); +} + +/* constant_time_is_zero returns 0xff..f if a == 0 and 0 otherwise. */ +static inline unsigned int constant_time_is_zero(unsigned int a) { + /* Here is an SMT-LIB verification of this formula: + * + * (define-fun is_zero ((a (_ BitVec 32))) (_ BitVec 32) + * (bvand (bvnot a) (bvsub a #x00000001)) + * ) + * + * (declare-fun a () (_ BitVec 32)) + * + * (assert (not (= (= #x00000001 (bvlshr (is_zero a) #x0000001f)) (= a #x00000000)))) + * (check-sat) + * (get-model) + */ + return constant_time_msb(~a & (a - 1)); +} + +/* constant_time_is_zero_8 acts like constant_time_is_zero but returns an 8-bit + * mask. */ +static inline uint8_t constant_time_is_zero_8(unsigned int a) { + return (uint8_t)(constant_time_is_zero(a)); +} + +/* constant_time_eq returns 0xff..f if a == b and 0 otherwise. */ +static inline unsigned int constant_time_eq(unsigned int a, unsigned int b) { + return constant_time_is_zero(a ^ b); +} + +/* constant_time_eq_8 acts like |constant_time_eq| but returns an 8-bit mask. */ +static inline uint8_t constant_time_eq_8(unsigned int a, unsigned int b) { + return (uint8_t)(constant_time_eq(a, b)); +} + +/* constant_time_eq_int acts like |constant_time_eq| but works on int values. */ +static inline unsigned int constant_time_eq_int(int a, int b) { + return constant_time_eq((unsigned)(a), (unsigned)(b)); +} + +/* constant_time_eq_int_8 acts like |constant_time_eq_int| but returns an 8-bit + * mask. */ +static inline uint8_t constant_time_eq_int_8(int a, int b) { + return constant_time_eq_8((unsigned)(a), (unsigned)(b)); +} + +/* constant_time_select returns (mask & a) | (~mask & b). When |mask| is all 1s + * or all 0s (as returned by the methods above), the select methods return + * either |a| (if |mask| is nonzero) or |b| (if |mask| is zero). */ +static inline unsigned int constant_time_select(unsigned int mask, + unsigned int a, unsigned int b) { + return (mask & a) | (~mask & b); +} + +/* constant_time_select_8 acts like |constant_time_select| but operates on + * 8-bit values. */ +static inline uint8_t constant_time_select_8(uint8_t mask, uint8_t a, + uint8_t b) { + return (uint8_t)(constant_time_select(mask, a, b)); +} + +/* constant_time_select_int acts like |constant_time_select| but operates on + * ints. */ +static inline int constant_time_select_int(unsigned int mask, int a, int b) { + return (int)(constant_time_select(mask, (unsigned)(a), (unsigned)(b))); +} + + +/* Thread-safe initialisation. */ + +/* Android's mingw-w64 has some prototypes for INIT_ONCE, but is missing + * others. Work around the missing ones. + * + * TODO(davidben): Remove this once Android's mingw-w64 is upgraded. See + * b/26523949. */ +#if defined(__MINGW32__) && !defined(INIT_ONCE_STATIC_INIT) +typedef RTL_RUN_ONCE INIT_ONCE; +#define INIT_ONCE_STATIC_INIT RTL_RUN_ONCE_INIT +#endif + +#if defined(OPENSSL_NO_THREADS) +typedef uint32_t CRYPTO_once_t; +#define CRYPTO_ONCE_INIT 0 +#elif defined(OPENSSL_WINDOWS) +typedef INIT_ONCE CRYPTO_once_t; +#define CRYPTO_ONCE_INIT INIT_ONCE_STATIC_INIT +#else +typedef pthread_once_t CRYPTO_once_t; +#define CRYPTO_ONCE_INIT PTHREAD_ONCE_INIT +#endif + +/* CRYPTO_once calls |init| exactly once per process. This is thread-safe: if + * concurrent threads call |CRYPTO_once| with the same |CRYPTO_once_t| argument + * then they will block until |init| completes, but |init| will have only been + * called once. + * + * The |once| argument must be a |CRYPTO_once_t| that has been initialised with + * the value |CRYPTO_ONCE_INIT|. */ +OPENSSL_EXPORT void CRYPTO_once(CRYPTO_once_t *once, void (*init)(void)); + + +/* Reference counting. */ + +/* CRYPTO_REFCOUNT_MAX is the value at which the reference count saturates. */ +#define CRYPTO_REFCOUNT_MAX 0xffffffff + +/* CRYPTO_refcount_inc atomically increments the value at |*count| unless the + * value would overflow. It's safe for multiple threads to concurrently call + * this or |CRYPTO_refcount_dec_and_test_zero| on the same + * |CRYPTO_refcount_t|. */ +OPENSSL_EXPORT void CRYPTO_refcount_inc(CRYPTO_refcount_t *count); + +/* CRYPTO_refcount_dec_and_test_zero tests the value at |*count|: + * if it's zero, it crashes the address space. + * if it's the maximum value, it returns zero. + * otherwise, it atomically decrements it and returns one iff the resulting + * value is zero. + * + * It's safe for multiple threads to concurrently call this or + * |CRYPTO_refcount_inc| on the same |CRYPTO_refcount_t|. */ +OPENSSL_EXPORT int CRYPTO_refcount_dec_and_test_zero(CRYPTO_refcount_t *count); + + +/* Locks. + * + * Two types of locks are defined: |CRYPTO_MUTEX|, which can be used in + * structures as normal, and |struct CRYPTO_STATIC_MUTEX|, which can be used as + * a global lock. A global lock must be initialised to the value + * |CRYPTO_STATIC_MUTEX_INIT|. + * + * |CRYPTO_MUTEX| can appear in public structures and so is defined in + * thread.h as a structure large enough to fit the real type. The global lock is + * a different type so it may be initialized with platform initializer macros.*/ + +#if defined(OPENSSL_NO_THREADS) +struct CRYPTO_STATIC_MUTEX { + char padding; /* Empty structs have different sizes in C and C++. */ +}; +#define CRYPTO_STATIC_MUTEX_INIT { 0 } +#elif defined(OPENSSL_WINDOWS) +struct CRYPTO_STATIC_MUTEX { + SRWLOCK lock; +}; +#define CRYPTO_STATIC_MUTEX_INIT { SRWLOCK_INIT } +#else +struct CRYPTO_STATIC_MUTEX { + pthread_rwlock_t lock; +}; +#define CRYPTO_STATIC_MUTEX_INIT { PTHREAD_RWLOCK_INITIALIZER } +#endif + +/* CRYPTO_MUTEX_init initialises |lock|. If |lock| is a static variable, use a + * |CRYPTO_STATIC_MUTEX|. */ +OPENSSL_EXPORT void CRYPTO_MUTEX_init(CRYPTO_MUTEX *lock); + +/* CRYPTO_MUTEX_lock_read locks |lock| such that other threads may also have a + * read lock, but none may have a write lock. */ +OPENSSL_EXPORT void CRYPTO_MUTEX_lock_read(CRYPTO_MUTEX *lock); + +/* CRYPTO_MUTEX_lock_write locks |lock| such that no other thread has any type + * of lock on it. */ +OPENSSL_EXPORT void CRYPTO_MUTEX_lock_write(CRYPTO_MUTEX *lock); + +/* CRYPTO_MUTEX_unlock_read unlocks |lock| for reading. */ +OPENSSL_EXPORT void CRYPTO_MUTEX_unlock_read(CRYPTO_MUTEX *lock); + +/* CRYPTO_MUTEX_unlock_write unlocks |lock| for writing. */ +OPENSSL_EXPORT void CRYPTO_MUTEX_unlock_write(CRYPTO_MUTEX *lock); + +/* CRYPTO_MUTEX_cleanup releases all resources held by |lock|. */ +OPENSSL_EXPORT void CRYPTO_MUTEX_cleanup(CRYPTO_MUTEX *lock); + +/* CRYPTO_STATIC_MUTEX_lock_read locks |lock| such that other threads may also + * have a read lock, but none may have a write lock. The |lock| variable does + * not need to be initialised by any function, but must have been statically + * initialised with |CRYPTO_STATIC_MUTEX_INIT|. */ +OPENSSL_EXPORT void CRYPTO_STATIC_MUTEX_lock_read( + struct CRYPTO_STATIC_MUTEX *lock); + +/* CRYPTO_STATIC_MUTEX_lock_write locks |lock| such that no other thread has + * any type of lock on it. The |lock| variable does not need to be initialised + * by any function, but must have been statically initialised with + * |CRYPTO_STATIC_MUTEX_INIT|. */ +OPENSSL_EXPORT void CRYPTO_STATIC_MUTEX_lock_write( + struct CRYPTO_STATIC_MUTEX *lock); + +/* CRYPTO_STATIC_MUTEX_unlock_read unlocks |lock| for reading. */ +OPENSSL_EXPORT void CRYPTO_STATIC_MUTEX_unlock_read( + struct CRYPTO_STATIC_MUTEX *lock); + +/* CRYPTO_STATIC_MUTEX_unlock_write unlocks |lock| for writing. */ +OPENSSL_EXPORT void CRYPTO_STATIC_MUTEX_unlock_write( + struct CRYPTO_STATIC_MUTEX *lock); + + +/* Thread local storage. */ + +/* thread_local_data_t enumerates the types of thread-local data that can be + * stored. */ +typedef enum { + OPENSSL_THREAD_LOCAL_ERR = 0, + OPENSSL_THREAD_LOCAL_RAND, + OPENSSL_THREAD_LOCAL_URANDOM_BUF, + OPENSSL_THREAD_LOCAL_TEST, + NUM_OPENSSL_THREAD_LOCALS, +} thread_local_data_t; + +/* thread_local_destructor_t is the type of a destructor function that will be + * called when a thread exits and its thread-local storage needs to be freed. */ +typedef void (*thread_local_destructor_t)(void *); + +/* CRYPTO_get_thread_local gets the pointer value that is stored for the + * current thread for the given index, or NULL if none has been set. */ +OPENSSL_EXPORT void *CRYPTO_get_thread_local(thread_local_data_t value); + +/* CRYPTO_set_thread_local sets a pointer value for the current thread at the + * given index. This function should only be called once per thread for a given + * |index|: rather than update the pointer value itself, update the data that + * is pointed to. + * + * The destructor function will be called when a thread exits to free this + * thread-local data. All calls to |CRYPTO_set_thread_local| with the same + * |index| should have the same |destructor| argument. The destructor may be + * called with a NULL argument if a thread that never set a thread-local + * pointer for |index|, exits. The destructor may be called concurrently with + * different arguments. + * + * This function returns one on success or zero on error. If it returns zero + * then |destructor| has been called with |value| already. */ +OPENSSL_EXPORT int CRYPTO_set_thread_local( + thread_local_data_t index, void *value, + thread_local_destructor_t destructor); + + +/* ex_data */ + +typedef struct crypto_ex_data_func_st CRYPTO_EX_DATA_FUNCS; + +/* CRYPTO_EX_DATA_CLASS tracks the ex_indices registered for a type which + * supports ex_data. It should defined as a static global within the module + * which defines that type. */ +typedef struct { + struct CRYPTO_STATIC_MUTEX lock; + STACK_OF(CRYPTO_EX_DATA_FUNCS) *meth; + /* num_reserved is one if the ex_data index zero is reserved for legacy + * |TYPE_get_app_data| functions. */ + uint8_t num_reserved; +} CRYPTO_EX_DATA_CLASS; + +#define CRYPTO_EX_DATA_CLASS_INIT {CRYPTO_STATIC_MUTEX_INIT, NULL, 0} +#define CRYPTO_EX_DATA_CLASS_INIT_WITH_APP_DATA \ + {CRYPTO_STATIC_MUTEX_INIT, NULL, 1} + +/* CRYPTO_get_ex_new_index allocates a new index for |ex_data_class| and writes + * it to |*out_index|. Each class of object should provide a wrapper function + * that uses the correct |CRYPTO_EX_DATA_CLASS|. It returns one on success and + * zero otherwise. */ +OPENSSL_EXPORT int CRYPTO_get_ex_new_index(CRYPTO_EX_DATA_CLASS *ex_data_class, + int *out_index, long argl, + void *argp, CRYPTO_EX_dup *dup_func, + CRYPTO_EX_free *free_func); + +/* CRYPTO_set_ex_data sets an extra data pointer on a given object. Each class + * of object should provide a wrapper function. */ +OPENSSL_EXPORT int CRYPTO_set_ex_data(CRYPTO_EX_DATA *ad, int index, void *val); + +/* CRYPTO_get_ex_data returns an extra data pointer for a given object, or NULL + * if no such index exists. Each class of object should provide a wrapper + * function. */ +OPENSSL_EXPORT void *CRYPTO_get_ex_data(const CRYPTO_EX_DATA *ad, int index); + +/* CRYPTO_new_ex_data initialises a newly allocated |CRYPTO_EX_DATA|. */ +OPENSSL_EXPORT void CRYPTO_new_ex_data(CRYPTO_EX_DATA *ad); + +/* CRYPTO_dup_ex_data duplicates |from| into a freshly allocated + * |CRYPTO_EX_DATA|, |to|. Both of which are inside objects of the given + * class. It returns one on success and zero otherwise. */ +OPENSSL_EXPORT int CRYPTO_dup_ex_data(CRYPTO_EX_DATA_CLASS *ex_data_class, + CRYPTO_EX_DATA *to, + const CRYPTO_EX_DATA *from); + +/* CRYPTO_free_ex_data frees |ad|, which is embedded inside |obj|, which is an + * object of the given class. */ +OPENSSL_EXPORT void CRYPTO_free_ex_data(CRYPTO_EX_DATA_CLASS *ex_data_class, + void *obj, CRYPTO_EX_DATA *ad); + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_CRYPTO_INTERNAL_H */ diff --git a/external/boringssl/crypto/lhash/CMakeLists.txt b/external/boringssl/crypto/lhash/CMakeLists.txt new file mode 100644 index 0000000000..f7a00dee8a --- /dev/null +++ b/external/boringssl/crypto/lhash/CMakeLists.txt @@ -0,0 +1,22 @@ +include_directories(../../include) + +add_library( + lhash + + OBJECT + + lhash.c +) + +if(ENABLE_TESTS) +add_executable( + lhash_test + + lhash_test.c + + $ +) + +target_link_libraries(lhash_test crypto) +add_dependencies(all_tests lhash_test) +endif() diff --git a/external/boringssl/crypto/lhash/lhash.c b/external/boringssl/crypto/lhash/lhash.c new file mode 100644 index 0000000000..257900eab5 --- /dev/null +++ b/external/boringssl/crypto/lhash/lhash.c @@ -0,0 +1,346 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include +#include + +#include + +/* kMinNumBuckets is the minimum size of the buckets array in an |_LHASH|. */ +static const size_t kMinNumBuckets = 16; + +/* kMaxAverageChainLength contains the maximum, average chain length. When the + * average chain length exceeds this value, the hash table will be resized. */ +static const size_t kMaxAverageChainLength = 2; +static const size_t kMinAverageChainLength = 1; + +_LHASH *lh_new(lhash_hash_func hash, lhash_cmp_func comp) { + _LHASH *ret; + + ret = OPENSSL_malloc(sizeof(_LHASH)); + if (ret == NULL) { + return NULL; + } + memset(ret, 0, sizeof(_LHASH)); + + ret->num_buckets = kMinNumBuckets; + ret->buckets = OPENSSL_malloc(sizeof(LHASH_ITEM *) * ret->num_buckets); + if (ret->buckets == NULL) { + OPENSSL_free(ret); + return NULL; + } + memset(ret->buckets, 0, sizeof(LHASH_ITEM *) * ret->num_buckets); + + ret->comp = comp; + if (ret->comp == NULL) { + ret->comp = (lhash_cmp_func) strcmp; + } + ret->hash = hash; + if (ret->hash == NULL) { + ret->hash = (lhash_hash_func) lh_strhash; + } + + return ret; +} + +void lh_free(_LHASH *lh) { + size_t i; + LHASH_ITEM *n, *next; + + if (lh == NULL) { + return; + } + + for (i = 0; i < lh->num_buckets; i++) { + for (n = lh->buckets[i]; n != NULL; n = next) { + next = n->next; + OPENSSL_free(n); + } + } + + OPENSSL_free(lh->buckets); + OPENSSL_free(lh); +} + +size_t lh_num_items(const _LHASH *lh) { return lh->num_items; } + +/* get_next_ptr_and_hash returns a pointer to the pointer that points to the + * item equal to |data|. In other words, it searches for an item equal to |data| + * and, if it's at the start of a chain, then it returns a pointer to an + * element of |lh->buckets|, otherwise it returns a pointer to the |next| + * element of the previous item in the chain. If an element equal to |data| is + * not found, it returns a pointer that points to a NULL pointer. If |out_hash| + * is not NULL, then it also puts the hash value of |data| in |*out_hash|. */ +static LHASH_ITEM **get_next_ptr_and_hash(const _LHASH *lh, uint32_t *out_hash, + const void *data) { + const uint32_t hash = lh->hash(data); + LHASH_ITEM *cur, **ret; + + if (out_hash != NULL) { + *out_hash = hash; + } + + ret = &lh->buckets[hash % lh->num_buckets]; + for (cur = *ret; cur != NULL; cur = *ret) { + if (lh->comp(cur->data, data) == 0) { + break; + } + ret = &cur->next; + } + + return ret; +} + +void *lh_retrieve(const _LHASH *lh, const void *data) { + LHASH_ITEM **next_ptr; + + next_ptr = get_next_ptr_and_hash(lh, NULL, data); + + if (*next_ptr == NULL) { + return NULL; + } + + return (*next_ptr)->data; +} + +/* lh_rebucket allocates a new array of |new_num_buckets| pointers and + * redistributes the existing items into it before making it |lh->buckets| and + * freeing the old array. */ +static void lh_rebucket(_LHASH *lh, const size_t new_num_buckets) { + LHASH_ITEM **new_buckets, *cur, *next; + size_t i, alloc_size; + + alloc_size = sizeof(LHASH_ITEM *) * new_num_buckets; + if (alloc_size / sizeof(LHASH_ITEM*) != new_num_buckets) { + return; + } + + new_buckets = OPENSSL_malloc(alloc_size); + if (new_buckets == NULL) { + return; + } + memset(new_buckets, 0, alloc_size); + + for (i = 0; i < lh->num_buckets; i++) { + for (cur = lh->buckets[i]; cur != NULL; cur = next) { + const size_t new_bucket = cur->hash % new_num_buckets; + next = cur->next; + cur->next = new_buckets[new_bucket]; + new_buckets[new_bucket] = cur; + } + } + + OPENSSL_free(lh->buckets); + + lh->num_buckets = new_num_buckets; + lh->buckets = new_buckets; +} + +/* lh_maybe_resize resizes the |buckets| array if needed. */ +static void lh_maybe_resize(_LHASH *lh) { + size_t avg_chain_length; + + if (lh->callback_depth > 0) { + /* Don't resize the hash if we are currently iterating over it. */ + return; + } + + assert(lh->num_buckets >= kMinNumBuckets); + avg_chain_length = lh->num_items / lh->num_buckets; + + if (avg_chain_length > kMaxAverageChainLength) { + const size_t new_num_buckets = lh->num_buckets * 2; + + if (new_num_buckets > lh->num_buckets) { + lh_rebucket(lh, new_num_buckets); + } + } else if (avg_chain_length < kMinAverageChainLength && + lh->num_buckets > kMinNumBuckets) { + size_t new_num_buckets = lh->num_buckets / 2; + + if (new_num_buckets < kMinNumBuckets) { + new_num_buckets = kMinNumBuckets; + } + + lh_rebucket(lh, new_num_buckets); + } +} + +int lh_insert(_LHASH *lh, void **old_data, void *data) { + uint32_t hash; + LHASH_ITEM **next_ptr, *item; + + *old_data = NULL; + next_ptr = get_next_ptr_and_hash(lh, &hash, data); + + + if (*next_ptr != NULL) { + /* An element equal to |data| already exists in the hash table. It will be + * replaced. */ + *old_data = (*next_ptr)->data; + (*next_ptr)->data = data; + return 1; + } + + /* An element equal to |data| doesn't exist in the hash table yet. */ + item = OPENSSL_malloc(sizeof(LHASH_ITEM)); + if (item == NULL) { + return 0; + } + + item->data = data; + item->hash = hash; + item->next = NULL; + *next_ptr = item; + lh->num_items++; + lh_maybe_resize(lh); + + return 1; +} + +void *lh_delete(_LHASH *lh, const void *data) { + LHASH_ITEM **next_ptr, *item, *ret; + + next_ptr = get_next_ptr_and_hash(lh, NULL, data); + + if (*next_ptr == NULL) { + /* No such element. */ + return NULL; + } + + item = *next_ptr; + *next_ptr = item->next; + ret = item->data; + OPENSSL_free(item); + + lh->num_items--; + lh_maybe_resize(lh); + + return ret; +} + +static void lh_doall_internal(_LHASH *lh, void (*no_arg_func)(void *), + void (*arg_func)(void *, void *), void *arg) { + size_t i; + LHASH_ITEM *cur, *next; + + if (lh == NULL) { + return; + } + + if (lh->callback_depth < UINT_MAX) { + /* |callback_depth| is a saturating counter. */ + lh->callback_depth++; + } + + for (i = 0; i < lh->num_buckets; i++) { + for (cur = lh->buckets[i]; cur != NULL; cur = next) { + next = cur->next; + if (arg_func) { + arg_func(cur->data, arg); + } else { + no_arg_func(cur->data); + } + } + } + + if (lh->callback_depth < UINT_MAX) { + lh->callback_depth--; + } + + /* The callback may have added or removed elements and the non-zero value of + * |callback_depth| will have suppressed any resizing. Thus any needed + * resizing is done here. */ + lh_maybe_resize(lh); +} + +void lh_doall(_LHASH *lh, void (*func)(void *)) { + lh_doall_internal(lh, func, NULL, NULL); +} + +void lh_doall_arg(_LHASH *lh, void (*func)(void *, void *), void *arg) { + lh_doall_internal(lh, NULL, func, arg); +} + +uint32_t lh_strhash(const char *c) { + /* The following hash seems to work very well on normal text strings + * no collisions on /usr/dict/words and it distributes on %2^n quite + * well, not as good as MD5, but still good. */ + unsigned long ret = 0; + long n; + unsigned long v; + int r; + + if ((c == NULL) || (*c == '\0')) { + return (ret); + } + + n = 0x100; + while (*c) { + v = n | (*c); + n += 0x100; + r = (int)((v >> 2) ^ v) & 0x0f; + ret = (ret << r) | (ret >> (32 - r)); + ret &= 0xFFFFFFFFL; + ret ^= v * v; + c++; + } + + return ((ret >> 16) ^ ret); +} diff --git a/external/boringssl/crypto/lhash/lhash_test.c b/external/boringssl/crypto/lhash/lhash_test.c new file mode 100644 index 0000000000..309b765d31 --- /dev/null +++ b/external/boringssl/crypto/lhash/lhash_test.c @@ -0,0 +1,203 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#if !defined(_POSIX_C_SOURCE) +#define _POSIX_C_SOURCE 201410L +#endif + +#include +#include + +#include +#include +#include + +struct dummy_lhash_node { + char *s; + struct dummy_lhash_node *next; +}; + +struct dummy_lhash { + struct dummy_lhash_node *head; +}; + +static void dummy_lh_free(struct dummy_lhash *lh) { + struct dummy_lhash_node *cur, *next; + + for (cur = lh->head; cur != NULL; cur = next) { + next = cur->next; + free(cur->s); + free(cur); + } +} + +static size_t dummy_lh_num_items(const struct dummy_lhash *lh) { + size_t count = 0; + struct dummy_lhash_node *cur; + + for (cur = lh->head; cur != NULL; cur = cur->next) { + count++; + } + + return count; +} + +static char *dummy_lh_retrieve(struct dummy_lhash *lh, const char *s) { + struct dummy_lhash_node *cur; + + for (cur = lh->head; cur != NULL; cur = cur->next) { + if (strcmp(cur->s, s) == 0) { + return cur->s; + } + } + + return NULL; +} + +static int dummy_lh_insert(struct dummy_lhash *lh, char **old_data, char *s) { + struct dummy_lhash_node *node, *cur; + + for (cur = lh->head; cur != NULL; cur = cur->next) { + if (strcmp(cur->s, s) == 0) { + *old_data = cur->s; + cur->s = s; + return 1; + } + } + + node = malloc(sizeof(struct dummy_lhash_node)); + *old_data = NULL; + node->s = s; + node->next = lh->head; + lh->head = node; + return 1; +} + +static char *dummy_lh_delete(struct dummy_lhash *lh, const void *s) { + struct dummy_lhash_node *cur, **next_ptr; + char *ret; + + next_ptr = &lh->head; + for (cur = lh->head; cur != NULL; cur = cur->next) { + if (strcmp(cur->s, s) == 0) { + ret = cur->s; + *next_ptr = cur->next; + free(cur); + return ret; + } + next_ptr = &cur->next; + } + + return NULL; +} + +static char *rand_string(void) { + unsigned len = 1 + (rand() % 3); + char *ret = malloc(len + 1); + unsigned i; + + for (i = 0; i < len; i++) { + ret[i] = '0' + (rand() & 7); + } + ret[i] = 0; + + return ret; +} + +int main(int argc, char **argv) { + _LHASH *lh; + struct dummy_lhash dummy_lh = {NULL}; + unsigned i; + + CRYPTO_library_init(); + + lh = lh_new(NULL, NULL); + if (lh == NULL) { + return 1; + } + + for (i = 0; i < 100000; i++) { + unsigned action; + char *s, *s1, *s2; + + if (dummy_lh_num_items(&dummy_lh) != lh_num_items(lh)) { + fprintf(stderr, "Length mismatch\n"); + return 1; + } + + action = rand() % 3; + switch (action) { + case 0: + s = rand_string(); + s1 = (char *)lh_retrieve(lh, s); + s2 = dummy_lh_retrieve(&dummy_lh, s); + if (s1 != NULL && (s2 == NULL || strcmp(s1, s2) != 0)) { + fprintf(stderr, "lh_retrieve failure\n"); + abort(); + } + free(s); + break; + + case 1: + s = rand_string(); + lh_insert(lh, (void **)&s1, s); +#if defined(OPENSSL_WINDOWS) + dummy_lh_insert(&dummy_lh, &s2, _strdup(s)); +#else + dummy_lh_insert(&dummy_lh, &s2, strdup(s)); +#endif + + if (s1 != NULL && (s2 == NULL || strcmp(s1, s2) != 0)) { + fprintf(stderr, "lh_insert failure\n"); + abort(); + } + + if (s1) { + free(s1); + } + if (s2) { + free(s2); + } + break; + + case 2: + s = rand_string(); + s1 = lh_delete(lh, s); + s2 = dummy_lh_delete(&dummy_lh, s); + + if (s1 != NULL && (s2 == NULL || strcmp(s1, s2) != 0)) { + fprintf(stderr, "lh_insert failure\n"); + abort(); + } + + if (s1) { + free(s1); + } + if (s2) { + free(s2); + } + free(s); + break; + + default: + abort(); + } + } + + lh_doall(lh, free); + lh_free(lh); + dummy_lh_free(&dummy_lh); + printf("PASS\n"); + return 0; +} diff --git a/external/boringssl/crypto/lhash/make_macros.sh b/external/boringssl/crypto/lhash/make_macros.sh new file mode 100644 index 0000000000..8a876af33f --- /dev/null +++ b/external/boringssl/crypto/lhash/make_macros.sh @@ -0,0 +1,67 @@ +#!/bin/sh + +include_dir=../../include/openssl +out=${include_dir}/lhash_macros.h + +cat > $out << EOF +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#if !defined(IN_LHASH_H) +#error "Don't include this file directly. Include lhash.h" +#endif + +EOF + +output_lhash () { + type=$1 + + cat >> $out << EOF +/* ${type} */ +#define lh_${type}_new(hash, comp)\\ +((LHASH_OF(${type})*) lh_new(CHECKED_CAST(lhash_hash_func, uint32_t (*) (const ${type} *), hash), CHECKED_CAST(lhash_cmp_func, int (*) (const ${type} *a, const ${type} *b), comp))) + +#define lh_${type}_free(lh)\\ + lh_free(CHECKED_CAST(_LHASH*, LHASH_OF(${type})*, lh)); + +#define lh_${type}_num_items(lh)\\ + lh_num_items(CHECKED_CAST(_LHASH*, LHASH_OF(${type})*, lh)) + +#define lh_${type}_retrieve(lh, data)\\ + ((${type}*) lh_retrieve(CHECKED_CAST(_LHASH*, LHASH_OF(${type})*, lh), CHECKED_CAST(void*, ${type}*, data))) + +#define lh_${type}_insert(lh, old_data, data)\\ + lh_insert(CHECKED_CAST(_LHASH*, LHASH_OF(${type})*, lh), CHECKED_CAST(void**, ${type}**, old_data), CHECKED_CAST(void*, ${type}*, data)) + +#define lh_${type}_delete(lh, data)\\ + ((${type}*) lh_delete(CHECKED_CAST(_LHASH*, LHASH_OF(${type})*, lh), CHECKED_CAST(void*, ${type}*, data))) + +#define lh_${type}_doall(lh, func)\\ + lh_doall(CHECKED_CAST(_LHASH*, LHASH_OF(${type})*, lh), CHECKED_CAST(void (*)(void*), void (*) (${type}*), func)); + +#define lh_${type}_doall_arg(lh, func, arg)\\ + lh_doall_arg(CHECKED_CAST(_LHASH*, LHASH_OF(${type})*, lh), CHECKED_CAST(void (*)(void*, void*), void (*) (${type}*, void*), func), arg); + + +EOF +} + +lhash_types=$(cat ${include_dir}/lhash.h | grep '^ \* LHASH_OF:' | sed -e 's/.*LHASH_OF://' -e 's/ .*//') + +for type in $lhash_types; do + echo Hash of ${type} + output_lhash "${type}" +done + +clang-format -i $out diff --git a/external/boringssl/crypto/md4/CMakeLists.txt b/external/boringssl/crypto/md4/CMakeLists.txt new file mode 100644 index 0000000000..59140a72de --- /dev/null +++ b/external/boringssl/crypto/md4/CMakeLists.txt @@ -0,0 +1,9 @@ +include_directories(../../include) + +add_library( + md4 + + OBJECT + + md4.c +) diff --git a/external/boringssl/crypto/md4/md4.c b/external/boringssl/crypto/md4/md4.c new file mode 100644 index 0000000000..f79da9fd03 --- /dev/null +++ b/external/boringssl/crypto/md4/md4.c @@ -0,0 +1,234 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + + +uint8_t *MD4(const uint8_t *data, size_t len, uint8_t *out) { + MD4_CTX ctx; + MD4_Init(&ctx); + MD4_Update(&ctx, data, len); + MD4_Final(out, &ctx); + + return out; +} + +/* Implemented from RFC1186 The MD4 Message-Digest Algorithm. */ + +int MD4_Init(MD4_CTX *md4) { + memset(md4, 0, sizeof(MD4_CTX)); + md4->h[0] = 0x67452301UL; + md4->h[1] = 0xefcdab89UL; + md4->h[2] = 0x98badcfeUL; + md4->h[3] = 0x10325476UL; + return 1; +} + +void md4_block_data_order(uint32_t *state, const uint8_t *data, size_t num); + +#define DATA_ORDER_IS_LITTLE_ENDIAN + +#define HASH_CTX MD4_CTX +#define HASH_CBLOCK 64 +#define HASH_UPDATE MD4_Update +#define HASH_TRANSFORM MD4_Transform +#define HASH_FINAL MD4_Final +#define HASH_MAKE_STRING(c, s) \ + do { \ + uint32_t ll; \ + ll = (c)->h[0]; \ + HOST_l2c(ll, (s)); \ + ll = (c)->h[1]; \ + HOST_l2c(ll, (s)); \ + ll = (c)->h[2]; \ + HOST_l2c(ll, (s)); \ + ll = (c)->h[3]; \ + HOST_l2c(ll, (s)); \ + } while (0) +#define HASH_BLOCK_DATA_ORDER md4_block_data_order + +#include "../digest/md32_common.h" + +/* As pointed out by Wei Dai , the above can be + * simplified to the code below. Wei attributes these optimizations + * to Peter Gutmann's SHS code, and he attributes it to Rich Schroeppel. */ +#define F(b, c, d) ((((c) ^ (d)) & (b)) ^ (d)) +#define G(b, c, d) (((b) & (c)) | ((b) & (d)) | ((c) & (d))) +#define H(b, c, d) ((b) ^ (c) ^ (d)) + +#define ROTATE(a, n) (((a) << (n)) | ((a) >> (32 - (n)))) + +#define R0(a, b, c, d, k, s, t) \ + { \ + a += ((k) + (t)+F((b), (c), (d))); \ + a = ROTATE(a, s); \ + }; + +#define R1(a, b, c, d, k, s, t) \ + { \ + a += ((k) + (t)+G((b), (c), (d))); \ + a = ROTATE(a, s); \ + }; + +#define R2(a, b, c, d, k, s, t) \ + { \ + a += ((k) + (t)+H((b), (c), (d))); \ + a = ROTATE(a, s); \ + }; + +void md4_block_data_order(uint32_t *state, const uint8_t *data, size_t num) { + uint32_t A, B, C, D, l; + uint32_t X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15; + + A = state[0]; + B = state[1]; + C = state[2]; + D = state[3]; + + for (; num--;) { + HOST_c2l(data, l); + X0 = l; + HOST_c2l(data, l); + X1 = l; + /* Round 0 */ + R0(A, B, C, D, X0, 3, 0); + HOST_c2l(data, l); + X2 = l; + R0(D, A, B, C, X1, 7, 0); + HOST_c2l(data, l); + X3 = l; + R0(C, D, A, B, X2, 11, 0); + HOST_c2l(data, l); + X4 = l; + R0(B, C, D, A, X3, 19, 0); + HOST_c2l(data, l); + X5 = l; + R0(A, B, C, D, X4, 3, 0); + HOST_c2l(data, l); + X6 = l; + R0(D, A, B, C, X5, 7, 0); + HOST_c2l(data, l); + X7 = l; + R0(C, D, A, B, X6, 11, 0); + HOST_c2l(data, l); + X8 = l; + R0(B, C, D, A, X7, 19, 0); + HOST_c2l(data, l); + X9 = l; + R0(A, B, C, D, X8, 3, 0); + HOST_c2l(data, l); + X10 = l; + R0(D, A, B, C, X9, 7, 0); + HOST_c2l(data, l); + X11 = l; + R0(C, D, A, B, X10, 11, 0); + HOST_c2l(data, l); + X12 = l; + R0(B, C, D, A, X11, 19, 0); + HOST_c2l(data, l); + X13 = l; + R0(A, B, C, D, X12, 3, 0); + HOST_c2l(data, l); + X14 = l; + R0(D, A, B, C, X13, 7, 0); + HOST_c2l(data, l); + X15 = l; + R0(C, D, A, B, X14, 11, 0); + R0(B, C, D, A, X15, 19, 0); + /* Round 1 */ + R1(A, B, C, D, X0, 3, 0x5A827999L); + R1(D, A, B, C, X4, 5, 0x5A827999L); + R1(C, D, A, B, X8, 9, 0x5A827999L); + R1(B, C, D, A, X12, 13, 0x5A827999L); + R1(A, B, C, D, X1, 3, 0x5A827999L); + R1(D, A, B, C, X5, 5, 0x5A827999L); + R1(C, D, A, B, X9, 9, 0x5A827999L); + R1(B, C, D, A, X13, 13, 0x5A827999L); + R1(A, B, C, D, X2, 3, 0x5A827999L); + R1(D, A, B, C, X6, 5, 0x5A827999L); + R1(C, D, A, B, X10, 9, 0x5A827999L); + R1(B, C, D, A, X14, 13, 0x5A827999L); + R1(A, B, C, D, X3, 3, 0x5A827999L); + R1(D, A, B, C, X7, 5, 0x5A827999L); + R1(C, D, A, B, X11, 9, 0x5A827999L); + R1(B, C, D, A, X15, 13, 0x5A827999L); + /* Round 2 */ + R2(A, B, C, D, X0, 3, 0x6ED9EBA1L); + R2(D, A, B, C, X8, 9, 0x6ED9EBA1L); + R2(C, D, A, B, X4, 11, 0x6ED9EBA1L); + R2(B, C, D, A, X12, 15, 0x6ED9EBA1L); + R2(A, B, C, D, X2, 3, 0x6ED9EBA1L); + R2(D, A, B, C, X10, 9, 0x6ED9EBA1L); + R2(C, D, A, B, X6, 11, 0x6ED9EBA1L); + R2(B, C, D, A, X14, 15, 0x6ED9EBA1L); + R2(A, B, C, D, X1, 3, 0x6ED9EBA1L); + R2(D, A, B, C, X9, 9, 0x6ED9EBA1L); + R2(C, D, A, B, X5, 11, 0x6ED9EBA1L); + R2(B, C, D, A, X13, 15, 0x6ED9EBA1L); + R2(A, B, C, D, X3, 3, 0x6ED9EBA1L); + R2(D, A, B, C, X11, 9, 0x6ED9EBA1L); + R2(C, D, A, B, X7, 11, 0x6ED9EBA1L); + R2(B, C, D, A, X15, 15, 0x6ED9EBA1L); + + A = state[0] += A; + B = state[1] += B; + C = state[2] += C; + D = state[3] += D; + } +} diff --git a/external/boringssl/crypto/md5/CMakeLists.txt b/external/boringssl/crypto/md5/CMakeLists.txt new file mode 100644 index 0000000000..a37c47e459 --- /dev/null +++ b/external/boringssl/crypto/md5/CMakeLists.txt @@ -0,0 +1,30 @@ +include_directories(../../include) + +if (${ARCH} STREQUAL "x86_64") + set( + MD5_ARCH_SOURCES + + md5-x86_64.${ASM_EXT} + ) +endif() + +if (${ARCH} STREQUAL "x86") + set( + MD5_ARCH_SOURCES + + md5-586.${ASM_EXT} + ) +endif() + +add_library( + md5 + + OBJECT + + md5.c + + ${MD5_ARCH_SOURCES} +) + +perlasm(md5-x86_64.${ASM_EXT} asm/md5-x86_64.pl) +perlasm(md5-586.${ASM_EXT} asm/md5-586.pl) diff --git a/external/boringssl/crypto/md5/asm/md5-586.pl b/external/boringssl/crypto/md5/asm/md5-586.pl new file mode 100644 index 0000000000..6cb66bb499 --- /dev/null +++ b/external/boringssl/crypto/md5/asm/md5-586.pl @@ -0,0 +1,307 @@ +#!/usr/local/bin/perl + +# Normal is the +# md5_block_x86(MD5_CTX *c, ULONG *X); +# version, non-normal is the +# md5_block_x86(MD5_CTX *c, ULONG *X,int blocks); + +$normal=0; + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +push(@INC,"${dir}","${dir}../../perlasm"); +require "x86asm.pl"; + +&asm_init($ARGV[0],$0); + +$A="eax"; +$B="ebx"; +$C="ecx"; +$D="edx"; +$tmp1="edi"; +$tmp2="ebp"; +$X="esi"; + +# What we need to load into $tmp for the next round +%Ltmp1=("R0",&Np($C), "R1",&Np($C), "R2",&Np($C), "R3",&Np($D)); +@xo=( + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, # R0 + 1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, # R1 + 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2, # R2 + 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9, # R3 + ); + +&md5_block("md5_block_asm_data_order"); +&asm_finish(); + +sub Np + { + local($p)=@_; + local(%n)=($A,$D,$B,$A,$C,$B,$D,$C); + return($n{$p}); + } + +sub R0 + { + local($pos,$a,$b,$c,$d,$K,$ki,$s,$t)=@_; + + &mov($tmp1,$C) if $pos < 0; + &mov($tmp2,&DWP($xo[$ki]*4,$K,"",0)) if $pos < 0; # very first one + + # body proper + + &comment("R0 $ki"); + &xor($tmp1,$d); # F function - part 2 + + &and($tmp1,$b); # F function - part 3 + &lea($a,&DWP($t,$a,$tmp2,1)); + + &xor($tmp1,$d); # F function - part 4 + + &add($a,$tmp1); + &mov($tmp1,&Np($c)) if $pos < 1; # next tmp1 for R0 + &mov($tmp1,&Np($c)) if $pos == 1; # next tmp1 for R1 + + &rotl($a,$s); + + &mov($tmp2,&DWP($xo[$ki+1]*4,$K,"",0)) if ($pos != 2); + + &add($a,$b); + } + +sub R1 + { + local($pos,$a,$b,$c,$d,$K,$ki,$s,$t)=@_; + + &comment("R1 $ki"); + + &lea($a,&DWP($t,$a,$tmp2,1)); + + &xor($tmp1,$b); # G function - part 2 + &and($tmp1,$d); # G function - part 3 + + &mov($tmp2,&DWP($xo[$ki+1]*4,$K,"",0)) if ($pos != 2); + &xor($tmp1,$c); # G function - part 4 + + &add($a,$tmp1); + &mov($tmp1,&Np($c)) if $pos < 1; # G function - part 1 + &mov($tmp1,&Np($c)) if $pos == 1; # G function - part 1 + + &rotl($a,$s); + + &add($a,$b); + } + +sub R2 + { + local($n,$pos,$a,$b,$c,$d,$K,$ki,$s,$t)=@_; + # This one is different, only 3 logical operations + +if (($n & 1) == 0) + { + &comment("R2 $ki"); + # make sure to do 'D' first, not 'B', else we clash with + # the last add from the previous round. + + &xor($tmp1,$d); # H function - part 2 + + &xor($tmp1,$b); # H function - part 3 + &lea($a,&DWP($t,$a,$tmp2,1)); + + &add($a,$tmp1); + + &rotl($a,$s); + + &mov($tmp2,&DWP($xo[$ki+1]*4,$K,"",0)); + &mov($tmp1,&Np($c)); + } +else + { + &comment("R2 $ki"); + # make sure to do 'D' first, not 'B', else we clash with + # the last add from the previous round. + + &lea($a,&DWP($t,$a,$tmp2,1)); + + &add($b,$c); # MOVED FORWARD + &xor($tmp1,$d); # H function - part 2 + + &xor($tmp1,$b); # H function - part 3 + &mov($tmp2,&DWP($xo[$ki+1]*4,$K,"",0)) if ($pos != 2); + + &add($a,$tmp1); + &mov($tmp1,&Np($c)) if $pos < 1; # H function - part 1 + &mov($tmp1,-1) if $pos == 1; # I function - part 1 + + &rotl($a,$s); + + &add($a,$b); + } + } + +sub R3 + { + local($pos,$a,$b,$c,$d,$K,$ki,$s,$t)=@_; + + &comment("R3 $ki"); + + # ¬($tmp1) + &xor($tmp1,$d) if $pos < 0; # I function - part 2 + + &or($tmp1,$b); # I function - part 3 + &lea($a,&DWP($t,$a,$tmp2,1)); + + &xor($tmp1,$c); # I function - part 4 + &mov($tmp2,&DWP($xo[$ki+1]*4,$K,"",0)) if $pos != 2; # load X/k value + &mov($tmp2,&wparam(0)) if $pos == 2; + + &add($a,$tmp1); + &mov($tmp1,-1) if $pos < 1; # H function - part 1 + &add($K,64) if $pos >=1 && !$normal; + + &rotl($a,$s); + + &xor($tmp1,&Np($d)) if $pos <= 0; # I function - part = first time + &mov($tmp1,&DWP( 0,$tmp2,"",0)) if $pos > 0; + &add($a,$b); + } + + +sub md5_block + { + local($name)=@_; + + &function_begin_B($name,"",3); + + # parameter 1 is the MD5_CTX structure. + # A 0 + # B 4 + # C 8 + # D 12 + + &push("esi"); + &push("edi"); + &mov($tmp1, &wparam(0)); # edi + &mov($X, &wparam(1)); # esi + &mov($C, &wparam(2)); + &push("ebp"); + &shl($C, 6); + &push("ebx"); + &add($C, $X); # offset we end at + &sub($C, 64); + &mov($A, &DWP( 0,$tmp1,"",0)); + &push($C); # Put on the TOS + &mov($B, &DWP( 4,$tmp1,"",0)); + &mov($C, &DWP( 8,$tmp1,"",0)); + &mov($D, &DWP(12,$tmp1,"",0)); + + &set_label("start") unless $normal; + &comment(""); + &comment("R0 section"); + + &R0(-2,$A,$B,$C,$D,$X, 0, 7,0xd76aa478); + &R0( 0,$D,$A,$B,$C,$X, 1,12,0xe8c7b756); + &R0( 0,$C,$D,$A,$B,$X, 2,17,0x242070db); + &R0( 0,$B,$C,$D,$A,$X, 3,22,0xc1bdceee); + &R0( 0,$A,$B,$C,$D,$X, 4, 7,0xf57c0faf); + &R0( 0,$D,$A,$B,$C,$X, 5,12,0x4787c62a); + &R0( 0,$C,$D,$A,$B,$X, 6,17,0xa8304613); + &R0( 0,$B,$C,$D,$A,$X, 7,22,0xfd469501); + &R0( 0,$A,$B,$C,$D,$X, 8, 7,0x698098d8); + &R0( 0,$D,$A,$B,$C,$X, 9,12,0x8b44f7af); + &R0( 0,$C,$D,$A,$B,$X,10,17,0xffff5bb1); + &R0( 0,$B,$C,$D,$A,$X,11,22,0x895cd7be); + &R0( 0,$A,$B,$C,$D,$X,12, 7,0x6b901122); + &R0( 0,$D,$A,$B,$C,$X,13,12,0xfd987193); + &R0( 0,$C,$D,$A,$B,$X,14,17,0xa679438e); + &R0( 1,$B,$C,$D,$A,$X,15,22,0x49b40821); + + &comment(""); + &comment("R1 section"); + &R1(-1,$A,$B,$C,$D,$X,16, 5,0xf61e2562); + &R1( 0,$D,$A,$B,$C,$X,17, 9,0xc040b340); + &R1( 0,$C,$D,$A,$B,$X,18,14,0x265e5a51); + &R1( 0,$B,$C,$D,$A,$X,19,20,0xe9b6c7aa); + &R1( 0,$A,$B,$C,$D,$X,20, 5,0xd62f105d); + &R1( 0,$D,$A,$B,$C,$X,21, 9,0x02441453); + &R1( 0,$C,$D,$A,$B,$X,22,14,0xd8a1e681); + &R1( 0,$B,$C,$D,$A,$X,23,20,0xe7d3fbc8); + &R1( 0,$A,$B,$C,$D,$X,24, 5,0x21e1cde6); + &R1( 0,$D,$A,$B,$C,$X,25, 9,0xc33707d6); + &R1( 0,$C,$D,$A,$B,$X,26,14,0xf4d50d87); + &R1( 0,$B,$C,$D,$A,$X,27,20,0x455a14ed); + &R1( 0,$A,$B,$C,$D,$X,28, 5,0xa9e3e905); + &R1( 0,$D,$A,$B,$C,$X,29, 9,0xfcefa3f8); + &R1( 0,$C,$D,$A,$B,$X,30,14,0x676f02d9); + &R1( 1,$B,$C,$D,$A,$X,31,20,0x8d2a4c8a); + + &comment(""); + &comment("R2 section"); + &R2( 0,-1,$A,$B,$C,$D,$X,32, 4,0xfffa3942); + &R2( 1, 0,$D,$A,$B,$C,$X,33,11,0x8771f681); + &R2( 2, 0,$C,$D,$A,$B,$X,34,16,0x6d9d6122); + &R2( 3, 0,$B,$C,$D,$A,$X,35,23,0xfde5380c); + &R2( 4, 0,$A,$B,$C,$D,$X,36, 4,0xa4beea44); + &R2( 5, 0,$D,$A,$B,$C,$X,37,11,0x4bdecfa9); + &R2( 6, 0,$C,$D,$A,$B,$X,38,16,0xf6bb4b60); + &R2( 7, 0,$B,$C,$D,$A,$X,39,23,0xbebfbc70); + &R2( 8, 0,$A,$B,$C,$D,$X,40, 4,0x289b7ec6); + &R2( 9, 0,$D,$A,$B,$C,$X,41,11,0xeaa127fa); + &R2(10, 0,$C,$D,$A,$B,$X,42,16,0xd4ef3085); + &R2(11, 0,$B,$C,$D,$A,$X,43,23,0x04881d05); + &R2(12, 0,$A,$B,$C,$D,$X,44, 4,0xd9d4d039); + &R2(13, 0,$D,$A,$B,$C,$X,45,11,0xe6db99e5); + &R2(14, 0,$C,$D,$A,$B,$X,46,16,0x1fa27cf8); + &R2(15, 1,$B,$C,$D,$A,$X,47,23,0xc4ac5665); + + &comment(""); + &comment("R3 section"); + &R3(-1,$A,$B,$C,$D,$X,48, 6,0xf4292244); + &R3( 0,$D,$A,$B,$C,$X,49,10,0x432aff97); + &R3( 0,$C,$D,$A,$B,$X,50,15,0xab9423a7); + &R3( 0,$B,$C,$D,$A,$X,51,21,0xfc93a039); + &R3( 0,$A,$B,$C,$D,$X,52, 6,0x655b59c3); + &R3( 0,$D,$A,$B,$C,$X,53,10,0x8f0ccc92); + &R3( 0,$C,$D,$A,$B,$X,54,15,0xffeff47d); + &R3( 0,$B,$C,$D,$A,$X,55,21,0x85845dd1); + &R3( 0,$A,$B,$C,$D,$X,56, 6,0x6fa87e4f); + &R3( 0,$D,$A,$B,$C,$X,57,10,0xfe2ce6e0); + &R3( 0,$C,$D,$A,$B,$X,58,15,0xa3014314); + &R3( 0,$B,$C,$D,$A,$X,59,21,0x4e0811a1); + &R3( 0,$A,$B,$C,$D,$X,60, 6,0xf7537e82); + &R3( 0,$D,$A,$B,$C,$X,61,10,0xbd3af235); + &R3( 0,$C,$D,$A,$B,$X,62,15,0x2ad7d2bb); + &R3( 2,$B,$C,$D,$A,$X,63,21,0xeb86d391); + + # &mov($tmp2,&wparam(0)); # done in the last R3 + # &mov($tmp1, &DWP( 0,$tmp2,"",0)); # done is the last R3 + + &add($A,$tmp1); + &mov($tmp1, &DWP( 4,$tmp2,"",0)); + + &add($B,$tmp1); + &mov($tmp1, &DWP( 8,$tmp2,"",0)); + + &add($C,$tmp1); + &mov($tmp1, &DWP(12,$tmp2,"",0)); + + &add($D,$tmp1); + &mov(&DWP( 0,$tmp2,"",0),$A); + + &mov(&DWP( 4,$tmp2,"",0),$B); + &mov($tmp1,&swtmp(0)) unless $normal; + + &mov(&DWP( 8,$tmp2,"",0),$C); + &mov(&DWP(12,$tmp2,"",0),$D); + + &cmp($tmp1,$X) unless $normal; # check count + &jae(&label("start")) unless $normal; + + &pop("eax"); # pop the temp variable off the stack + &pop("ebx"); + &pop("ebp"); + &pop("edi"); + &pop("esi"); + &ret(); + &function_end_B($name); + } + diff --git a/external/boringssl/crypto/md5/asm/md5-x86_64.pl b/external/boringssl/crypto/md5/asm/md5-x86_64.pl new file mode 100644 index 0000000000..77a6e01dd8 --- /dev/null +++ b/external/boringssl/crypto/md5/asm/md5-x86_64.pl @@ -0,0 +1,370 @@ +#!/usr/bin/perl -w +# +# MD5 optimized for AMD64. +# +# Author: Marc Bevand +# Licence: I hereby disclaim the copyright on this code and place it +# in the public domain. +# + +use strict; + +my $code; + +# round1_step() does: +# dst = x + ((dst + F(x,y,z) + X[k] + T_i) <<< s) +# %r10d = X[k_next] +# %r11d = z' (copy of z for the next step) +# Each round1_step() takes about 5.3 clocks (9 instructions, 1.7 IPC) +sub round1_step +{ + my ($pos, $dst, $x, $y, $z, $k_next, $T_i, $s) = @_; + $code .= " mov 0*4(%rsi), %r10d /* (NEXT STEP) X[0] */\n" if ($pos == -1); + $code .= " mov %edx, %r11d /* (NEXT STEP) z' = %edx */\n" if ($pos == -1); + $code .= <A + mov 1*4(%rbp), %ebx # ebx = ctx->B + mov 2*4(%rbp), %ecx # ecx = ctx->C + mov 3*4(%rbp), %edx # edx = ctx->D + # end is 'rdi' + # ptr is 'rsi' + # A is 'eax' + # B is 'ebx' + # C is 'ecx' + # D is 'edx' + + cmp %rdi, %rsi # cmp end with ptr + je .Lend # jmp if ptr == end + + # BEGIN of loop over 16-word blocks +.Lloop: # save old values of A, B, C, D + mov %eax, %r8d + mov %ebx, %r9d + mov %ecx, %r14d + mov %edx, %r15d +EOF +round1_step(-1,'%eax','%ebx','%ecx','%edx', '1','0xd76aa478', '7'); +round1_step( 0,'%edx','%eax','%ebx','%ecx', '2','0xe8c7b756','12'); +round1_step( 0,'%ecx','%edx','%eax','%ebx', '3','0x242070db','17'); +round1_step( 0,'%ebx','%ecx','%edx','%eax', '4','0xc1bdceee','22'); +round1_step( 0,'%eax','%ebx','%ecx','%edx', '5','0xf57c0faf', '7'); +round1_step( 0,'%edx','%eax','%ebx','%ecx', '6','0x4787c62a','12'); +round1_step( 0,'%ecx','%edx','%eax','%ebx', '7','0xa8304613','17'); +round1_step( 0,'%ebx','%ecx','%edx','%eax', '8','0xfd469501','22'); +round1_step( 0,'%eax','%ebx','%ecx','%edx', '9','0x698098d8', '7'); +round1_step( 0,'%edx','%eax','%ebx','%ecx','10','0x8b44f7af','12'); +round1_step( 0,'%ecx','%edx','%eax','%ebx','11','0xffff5bb1','17'); +round1_step( 0,'%ebx','%ecx','%edx','%eax','12','0x895cd7be','22'); +round1_step( 0,'%eax','%ebx','%ecx','%edx','13','0x6b901122', '7'); +round1_step( 0,'%edx','%eax','%ebx','%ecx','14','0xfd987193','12'); +round1_step( 0,'%ecx','%edx','%eax','%ebx','15','0xa679438e','17'); +round1_step( 1,'%ebx','%ecx','%edx','%eax', '0','0x49b40821','22'); + +round2_step(-1,'%eax','%ebx','%ecx','%edx', '6','0xf61e2562', '5'); +round2_step( 0,'%edx','%eax','%ebx','%ecx','11','0xc040b340', '9'); +round2_step( 0,'%ecx','%edx','%eax','%ebx', '0','0x265e5a51','14'); +round2_step( 0,'%ebx','%ecx','%edx','%eax', '5','0xe9b6c7aa','20'); +round2_step( 0,'%eax','%ebx','%ecx','%edx','10','0xd62f105d', '5'); +round2_step( 0,'%edx','%eax','%ebx','%ecx','15', '0x2441453', '9'); +round2_step( 0,'%ecx','%edx','%eax','%ebx', '4','0xd8a1e681','14'); +round2_step( 0,'%ebx','%ecx','%edx','%eax', '9','0xe7d3fbc8','20'); +round2_step( 0,'%eax','%ebx','%ecx','%edx','14','0x21e1cde6', '5'); +round2_step( 0,'%edx','%eax','%ebx','%ecx', '3','0xc33707d6', '9'); +round2_step( 0,'%ecx','%edx','%eax','%ebx', '8','0xf4d50d87','14'); +round2_step( 0,'%ebx','%ecx','%edx','%eax','13','0x455a14ed','20'); +round2_step( 0,'%eax','%ebx','%ecx','%edx', '2','0xa9e3e905', '5'); +round2_step( 0,'%edx','%eax','%ebx','%ecx', '7','0xfcefa3f8', '9'); +round2_step( 0,'%ecx','%edx','%eax','%ebx','12','0x676f02d9','14'); +round2_step( 1,'%ebx','%ecx','%edx','%eax', '0','0x8d2a4c8a','20'); + +round3_step(-1,'%eax','%ebx','%ecx','%edx', '8','0xfffa3942', '4'); +round3_step( 0,'%edx','%eax','%ebx','%ecx','11','0x8771f681','11'); +round3_step( 0,'%ecx','%edx','%eax','%ebx','14','0x6d9d6122','16'); +round3_step( 0,'%ebx','%ecx','%edx','%eax', '1','0xfde5380c','23'); +round3_step( 0,'%eax','%ebx','%ecx','%edx', '4','0xa4beea44', '4'); +round3_step( 0,'%edx','%eax','%ebx','%ecx', '7','0x4bdecfa9','11'); +round3_step( 0,'%ecx','%edx','%eax','%ebx','10','0xf6bb4b60','16'); +round3_step( 0,'%ebx','%ecx','%edx','%eax','13','0xbebfbc70','23'); +round3_step( 0,'%eax','%ebx','%ecx','%edx', '0','0x289b7ec6', '4'); +round3_step( 0,'%edx','%eax','%ebx','%ecx', '3','0xeaa127fa','11'); +round3_step( 0,'%ecx','%edx','%eax','%ebx', '6','0xd4ef3085','16'); +round3_step( 0,'%ebx','%ecx','%edx','%eax', '9', '0x4881d05','23'); +round3_step( 0,'%eax','%ebx','%ecx','%edx','12','0xd9d4d039', '4'); +round3_step( 0,'%edx','%eax','%ebx','%ecx','15','0xe6db99e5','11'); +round3_step( 0,'%ecx','%edx','%eax','%ebx', '2','0x1fa27cf8','16'); +round3_step( 1,'%ebx','%ecx','%edx','%eax', '0','0xc4ac5665','23'); + +round4_step(-1,'%eax','%ebx','%ecx','%edx', '7','0xf4292244', '6'); +round4_step( 0,'%edx','%eax','%ebx','%ecx','14','0x432aff97','10'); +round4_step( 0,'%ecx','%edx','%eax','%ebx', '5','0xab9423a7','15'); +round4_step( 0,'%ebx','%ecx','%edx','%eax','12','0xfc93a039','21'); +round4_step( 0,'%eax','%ebx','%ecx','%edx', '3','0x655b59c3', '6'); +round4_step( 0,'%edx','%eax','%ebx','%ecx','10','0x8f0ccc92','10'); +round4_step( 0,'%ecx','%edx','%eax','%ebx', '1','0xffeff47d','15'); +round4_step( 0,'%ebx','%ecx','%edx','%eax', '8','0x85845dd1','21'); +round4_step( 0,'%eax','%ebx','%ecx','%edx','15','0x6fa87e4f', '6'); +round4_step( 0,'%edx','%eax','%ebx','%ecx', '6','0xfe2ce6e0','10'); +round4_step( 0,'%ecx','%edx','%eax','%ebx','13','0xa3014314','15'); +round4_step( 0,'%ebx','%ecx','%edx','%eax', '4','0x4e0811a1','21'); +round4_step( 0,'%eax','%ebx','%ecx','%edx','11','0xf7537e82', '6'); +round4_step( 0,'%edx','%eax','%ebx','%ecx', '2','0xbd3af235','10'); +round4_step( 0,'%ecx','%edx','%eax','%ebx', '9','0x2ad7d2bb','15'); +round4_step( 1,'%ebx','%ecx','%edx','%eax', '0','0xeb86d391','21'); +$code .= <A = A + mov %ebx, 1*4(%rbp) # ctx->B = B + mov %ecx, 2*4(%rbp) # ctx->C = C + mov %edx, 3*4(%rbp) # ctx->D = D + + mov (%rsp),%r15 + mov 8(%rsp),%r14 + mov 16(%rsp),%r12 + mov 24(%rsp),%rbx + mov 32(%rsp),%rbp + add \$40,%rsp +.Lepilogue: + ret +.size md5_block_asm_data_order,.-md5_block_asm_data_order +EOF + +# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame, +# CONTEXT *context,DISPATCHER_CONTEXT *disp) +if ($win64) { +my $rec="%rcx"; +my $frame="%rdx"; +my $context="%r8"; +my $disp="%r9"; + +$code.=<<___; +.extern __imp_RtlVirtualUnwind +.type se_handler,\@abi-omnipotent +.align 16 +se_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + lea .Lprologue(%rip),%r10 + cmp %r10,%rbx # context->Rip<.Lprologue + jb .Lin_prologue + + mov 152($context),%rax # pull context->Rsp + + lea .Lepilogue(%rip),%r10 + cmp %r10,%rbx # context->Rip>=.Lepilogue + jae .Lin_prologue + + lea 40(%rax),%rax + + mov -8(%rax),%rbp + mov -16(%rax),%rbx + mov -24(%rax),%r12 + mov -32(%rax),%r14 + mov -40(%rax),%r15 + mov %rbx,144($context) # restore context->Rbx + mov %rbp,160($context) # restore context->Rbp + mov %r12,216($context) # restore context->R12 + mov %r14,232($context) # restore context->R14 + mov %r15,240($context) # restore context->R15 + +.Lin_prologue: + mov 8(%rax),%rdi + mov 16(%rax),%rsi + mov %rax,152($context) # restore context->Rsp + mov %rsi,168($context) # restore context->Rsi + mov %rdi,176($context) # restore context->Rdi + + mov 40($disp),%rdi # disp->ContextRecord + mov $context,%rsi # context + mov \$154,%ecx # sizeof(CONTEXT) + .long 0xa548f3fc # cld; rep movsq + + mov $disp,%rsi + xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER + mov 8(%rsi),%rdx # arg2, disp->ImageBase + mov 0(%rsi),%r8 # arg3, disp->ControlPc + mov 16(%rsi),%r9 # arg4, disp->FunctionEntry + mov 40(%rsi),%r10 # disp->ContextRecord + lea 56(%rsi),%r11 # &disp->HandlerData + lea 24(%rsi),%r12 # &disp->EstablisherFrame + mov %r10,32(%rsp) # arg5 + mov %r11,40(%rsp) # arg6 + mov %r12,48(%rsp) # arg7 + mov %rcx,56(%rsp) # arg8, (NULL) + call *__imp_RtlVirtualUnwind(%rip) + + mov \$1,%eax # ExceptionContinueSearch + add \$64,%rsp + popfq + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + pop %rdi + pop %rsi + ret +.size se_handler,.-se_handler + +.section .pdata +.align 4 + .rva .LSEH_begin_md5_block_asm_data_order + .rva .LSEH_end_md5_block_asm_data_order + .rva .LSEH_info_md5_block_asm_data_order + +.section .xdata +.align 8 +.LSEH_info_md5_block_asm_data_order: + .byte 9,0,0,0 + .rva se_handler +___ +} + +print $code; + +close STDOUT; diff --git a/external/boringssl/crypto/md5/md5.c b/external/boringssl/crypto/md5/md5.c new file mode 100644 index 0000000000..66483b847f --- /dev/null +++ b/external/boringssl/crypto/md5/md5.c @@ -0,0 +1,275 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include + + +uint8_t *MD5(const uint8_t *data, size_t len, uint8_t *out) { + MD5_CTX ctx; + static uint8_t digest[MD5_DIGEST_LENGTH]; + + /* TODO(fork): remove this static buffer. */ + if (out == NULL) { + out = digest; + } + + MD5_Init(&ctx); + MD5_Update(&ctx, data, len); + MD5_Final(out, &ctx); + + return out; +} + +int MD5_Init(MD5_CTX *md5) { + memset(md5, 0, sizeof(MD5_CTX)); + md5->h[0] = 0x67452301UL; + md5->h[1] = 0xefcdab89UL; + md5->h[2] = 0x98badcfeUL; + md5->h[3] = 0x10325476UL; + return 1; +} + +#if !defined(OPENSSL_NO_ASM) && \ + (defined(OPENSSL_X86_64) || defined(OPENSSL_X86)) +#define MD5_ASM +#define md5_block_data_order md5_block_asm_data_order +#endif + + +void md5_block_data_order(uint32_t *state, const uint8_t *data, size_t num); + +#define DATA_ORDER_IS_LITTLE_ENDIAN + +#define HASH_CTX MD5_CTX +#define HASH_CBLOCK 64 +#define HASH_UPDATE MD5_Update +#define HASH_TRANSFORM MD5_Transform +#define HASH_FINAL MD5_Final +#define HASH_MAKE_STRING(c, s) \ + do { \ + uint32_t ll; \ + ll = (c)->h[0]; \ + HOST_l2c(ll, (s)); \ + ll = (c)->h[1]; \ + HOST_l2c(ll, (s)); \ + ll = (c)->h[2]; \ + HOST_l2c(ll, (s)); \ + ll = (c)->h[3]; \ + HOST_l2c(ll, (s)); \ + } while (0) +#define HASH_BLOCK_DATA_ORDER md5_block_data_order + +#include "../digest/md32_common.h" + +/* As pointed out by Wei Dai , the above can be + * simplified to the code below. Wei attributes these optimizations + * to Peter Gutmann's SHS code, and he attributes it to Rich Schroeppel. + */ +#define F(b,c,d) ((((c) ^ (d)) & (b)) ^ (d)) +#define G(b,c,d) ((((b) ^ (c)) & (d)) ^ (c)) +#define H(b,c,d) ((b) ^ (c) ^ (d)) +#define I(b,c,d) (((~(d)) | (b)) ^ (c)) + +#define ROTATE(a, n) (((a) << (n)) | ((a) >> (32 - (n)))) + +#define R0(a,b,c,d,k,s,t) { \ + a+=((k)+(t)+F((b),(c),(d))); \ + a=ROTATE(a,s); \ + a+=b; };\ + +#define R1(a,b,c,d,k,s,t) { \ + a+=((k)+(t)+G((b),(c),(d))); \ + a=ROTATE(a,s); \ + a+=b; }; + +#define R2(a,b,c,d,k,s,t) { \ + a+=((k)+(t)+H((b),(c),(d))); \ + a=ROTATE(a,s); \ + a+=b; }; + +#define R3(a,b,c,d,k,s,t) { \ + a+=((k)+(t)+I((b),(c),(d))); \ + a=ROTATE(a,s); \ + a+=b; }; + +#ifndef md5_block_data_order +#ifdef X +#undef X +#endif +void md5_block_data_order(uint32_t *state, const uint8_t *data, size_t num) { + uint32_t A, B, C, D, l; + uint32_t XX0, XX1, XX2, XX3, XX4, XX5, XX6, XX7, XX8, XX9, XX10, XX11, XX12, + XX13, XX14, XX15; +#define X(i) XX##i + + A = state[0]; + B = state[1]; + C = state[2]; + D = state[3]; + + for (; num--;) { + HOST_c2l(data, l); + X(0) = l; + HOST_c2l(data, l); + X(1) = l; + /* Round 0 */ + R0(A, B, C, D, X(0), 7, 0xd76aa478L); + HOST_c2l(data, l); + X(2) = l; + R0(D, A, B, C, X(1), 12, 0xe8c7b756L); + HOST_c2l(data, l); + X(3) = l; + R0(C, D, A, B, X(2), 17, 0x242070dbL); + HOST_c2l(data, l); + X(4) = l; + R0(B, C, D, A, X(3), 22, 0xc1bdceeeL); + HOST_c2l(data, l); + X(5) = l; + R0(A, B, C, D, X(4), 7, 0xf57c0fafL); + HOST_c2l(data, l); + X(6) = l; + R0(D, A, B, C, X(5), 12, 0x4787c62aL); + HOST_c2l(data, l); + X(7) = l; + R0(C, D, A, B, X(6), 17, 0xa8304613L); + HOST_c2l(data, l); + X(8) = l; + R0(B, C, D, A, X(7), 22, 0xfd469501L); + HOST_c2l(data, l); + X(9) = l; + R0(A, B, C, D, X(8), 7, 0x698098d8L); + HOST_c2l(data, l); + X(10) = l; + R0(D, A, B, C, X(9), 12, 0x8b44f7afL); + HOST_c2l(data, l); + X(11) = l; + R0(C, D, A, B, X(10), 17, 0xffff5bb1L); + HOST_c2l(data, l); + X(12) = l; + R0(B, C, D, A, X(11), 22, 0x895cd7beL); + HOST_c2l(data, l); + X(13) = l; + R0(A, B, C, D, X(12), 7, 0x6b901122L); + HOST_c2l(data, l); + X(14) = l; + R0(D, A, B, C, X(13), 12, 0xfd987193L); + HOST_c2l(data, l); + X(15) = l; + R0(C, D, A, B, X(14), 17, 0xa679438eL); + R0(B, C, D, A, X(15), 22, 0x49b40821L); + /* Round 1 */ + R1(A, B, C, D, X(1), 5, 0xf61e2562L); + R1(D, A, B, C, X(6), 9, 0xc040b340L); + R1(C, D, A, B, X(11), 14, 0x265e5a51L); + R1(B, C, D, A, X(0), 20, 0xe9b6c7aaL); + R1(A, B, C, D, X(5), 5, 0xd62f105dL); + R1(D, A, B, C, X(10), 9, 0x02441453L); + R1(C, D, A, B, X(15), 14, 0xd8a1e681L); + R1(B, C, D, A, X(4), 20, 0xe7d3fbc8L); + R1(A, B, C, D, X(9), 5, 0x21e1cde6L); + R1(D, A, B, C, X(14), 9, 0xc33707d6L); + R1(C, D, A, B, X(3), 14, 0xf4d50d87L); + R1(B, C, D, A, X(8), 20, 0x455a14edL); + R1(A, B, C, D, X(13), 5, 0xa9e3e905L); + R1(D, A, B, C, X(2), 9, 0xfcefa3f8L); + R1(C, D, A, B, X(7), 14, 0x676f02d9L); + R1(B, C, D, A, X(12), 20, 0x8d2a4c8aL); + /* Round 2 */ + R2(A, B, C, D, X(5), 4, 0xfffa3942L); + R2(D, A, B, C, X(8), 11, 0x8771f681L); + R2(C, D, A, B, X(11), 16, 0x6d9d6122L); + R2(B, C, D, A, X(14), 23, 0xfde5380cL); + R2(A, B, C, D, X(1), 4, 0xa4beea44L); + R2(D, A, B, C, X(4), 11, 0x4bdecfa9L); + R2(C, D, A, B, X(7), 16, 0xf6bb4b60L); + R2(B, C, D, A, X(10), 23, 0xbebfbc70L); + R2(A, B, C, D, X(13), 4, 0x289b7ec6L); + R2(D, A, B, C, X(0), 11, 0xeaa127faL); + R2(C, D, A, B, X(3), 16, 0xd4ef3085L); + R2(B, C, D, A, X(6), 23, 0x04881d05L); + R2(A, B, C, D, X(9), 4, 0xd9d4d039L); + R2(D, A, B, C, X(12), 11, 0xe6db99e5L); + R2(C, D, A, B, X(15), 16, 0x1fa27cf8L); + R2(B, C, D, A, X(2), 23, 0xc4ac5665L); + /* Round 3 */ + R3(A, B, C, D, X(0), 6, 0xf4292244L); + R3(D, A, B, C, X(7), 10, 0x432aff97L); + R3(C, D, A, B, X(14), 15, 0xab9423a7L); + R3(B, C, D, A, X(5), 21, 0xfc93a039L); + R3(A, B, C, D, X(12), 6, 0x655b59c3L); + R3(D, A, B, C, X(3), 10, 0x8f0ccc92L); + R3(C, D, A, B, X(10), 15, 0xffeff47dL); + R3(B, C, D, A, X(1), 21, 0x85845dd1L); + R3(A, B, C, D, X(8), 6, 0x6fa87e4fL); + R3(D, A, B, C, X(15), 10, 0xfe2ce6e0L); + R3(C, D, A, B, X(6), 15, 0xa3014314L); + R3(B, C, D, A, X(13), 21, 0x4e0811a1L); + R3(A, B, C, D, X(4), 6, 0xf7537e82L); + R3(D, A, B, C, X(11), 10, 0xbd3af235L); + R3(C, D, A, B, X(2), 15, 0x2ad7d2bbL); + R3(B, C, D, A, X(9), 21, 0xeb86d391L); + + A = state[0] += A; + B = state[1] += B; + C = state[2] += C; + D = state[3] += D; + } +} +#endif diff --git a/external/boringssl/crypto/mem.c b/external/boringssl/crypto/mem.c new file mode 100644 index 0000000000..527edd9348 --- /dev/null +++ b/external/boringssl/crypto/mem.c @@ -0,0 +1,209 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#if !defined(_POSIX_C_SOURCE) +#define _POSIX_C_SOURCE 201410L /* needed for strdup, snprintf, vprintf etc */ +#endif + +#include + +#include +#include +#include +#include + +#if defined(OPENSSL_WINDOWS) +OPENSSL_MSVC_PRAGMA(warning(push, 3)) +#include + +/* Work around a clang-cl bug: SecureZeroMemory() below uses __stosb() but + * windows.h only declares that intrinsic and then uses `#pragma intrinsic` for + * it. clang-cl doesn't implement `#pragma intrinsic` yet; it instead defines + * the function as an always-inline symbol in its intrin.h. + * TODO(thakis): Remove this once http://llvm.org/PR19898 is fixed. + */ +#include +OPENSSL_MSVC_PRAGMA(warning(pop)) +#else +#include +#endif + + +void *OPENSSL_realloc_clean(void *ptr, size_t old_size, size_t new_size) { + void *ret = NULL; + + if (ptr == NULL) { + return OPENSSL_malloc(new_size); + } + + if (new_size == 0) { + return NULL; + } + + /* We don't support shrinking the buffer. Note the memcpy that copies + * |old_size| bytes to the new buffer, below. */ + if (new_size < old_size) { + return NULL; + } + + ret = OPENSSL_malloc(new_size); + if (ret == NULL) { + return NULL; + } + + memcpy(ret, ptr, old_size); + OPENSSL_cleanse(ptr, old_size); + OPENSSL_free(ptr); + return ret; +} + +void OPENSSL_cleanse(void *ptr, size_t len) { +#if defined(OPENSSL_WINDOWS) + SecureZeroMemory(ptr, len); +#else + memset(ptr, 0, len); + +#if !defined(OPENSSL_NO_ASM) + /* As best as we can tell, this is sufficient to break any optimisations that + might try to eliminate "superfluous" memsets. If there's an easy way to + detect memset_s, it would be better to use that. */ + __asm__ __volatile__("" : : "r"(ptr) : "memory"); +#endif +#endif /* !OPENSSL_NO_ASM */ +} + +int CRYPTO_memcmp(const void *in_a, const void *in_b, size_t len) { + const uint8_t *a = in_a; + const uint8_t *b = in_b; + uint8_t x = 0; + + for (size_t i = 0; i < len; i++) { + x |= a[i] ^ b[i]; + } + + return x; +} + +uint32_t OPENSSL_hash32(const void *ptr, size_t len) { + /* These are the FNV-1a parameters for 32 bits. */ + static const uint32_t kPrime = 16777619u; + static const uint32_t kOffsetBasis = 2166136261u; + + const uint8_t *in = ptr; + size_t i; + uint32_t h = kOffsetBasis; + + for (i = 0; i < len; i++) { + h ^= in[i]; + h *= kPrime; + } + + return h; +} + +size_t OPENSSL_strnlen(const char *s, size_t len) { + size_t i; + + for (i = 0; i < len; i++) { + if (s[i] == 0) { + return i; + } + } + + return len; +} + +#if defined(OPENSSL_WINDOWS) + +char *OPENSSL_strdup(const char *s) { return _strdup(s); } + +int OPENSSL_strcasecmp(const char *a, const char *b) { + return _stricmp(a, b); +} + +int OPENSSL_strncasecmp(const char *a, const char *b, size_t n) { + return _strnicmp(a, b, n); +} + +#else + +char *OPENSSL_strdup(const char *s) { return strdup(s); } + +int OPENSSL_strcasecmp(const char *a, const char *b) { + return strcasecmp(a, b); +} + +int OPENSSL_strncasecmp(const char *a, const char *b, size_t n) { + return strncasecmp(a, b, n); +} + +#endif + +int BIO_snprintf(char *buf, size_t n, const char *format, ...) { + va_list args; + int ret; + + va_start(args, format); + + ret = BIO_vsnprintf(buf, n, format, args); + + va_end(args); + return ret; +} + +int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args) { + return vsnprintf(buf, n, format, args); +} diff --git a/external/boringssl/crypto/modes/CMakeLists.txt b/external/boringssl/crypto/modes/CMakeLists.txt new file mode 100644 index 0000000000..6dae9f6a87 --- /dev/null +++ b/external/boringssl/crypto/modes/CMakeLists.txt @@ -0,0 +1,68 @@ +include_directories(../../include) + +if (${ARCH} STREQUAL "x86_64") + set( + MODES_ARCH_SOURCES + + aesni-gcm-x86_64.${ASM_EXT} + ghash-x86_64.${ASM_EXT} + ) +endif() + +if (${ARCH} STREQUAL "x86") + set( + MODES_ARCH_SOURCES + + ghash-x86.${ASM_EXT} + ) +endif() + +if (${ARCH} STREQUAL "arm") + set( + MODES_ARCH_SOURCES + + ghash-armv4.${ASM_EXT} + ghashv8-armx.${ASM_EXT} + ) +endif() + +if (${ARCH} STREQUAL "aarch64") + set( + MODES_ARCH_SOURCES + + ghashv8-armx.${ASM_EXT} + ) +endif() + +add_library( + modes + + OBJECT + + cbc.c + ctr.c + ofb.c + cfb.c + gcm.c + + ${MODES_ARCH_SOURCES} +) + +perlasm(aesni-gcm-x86_64.${ASM_EXT} asm/aesni-gcm-x86_64.pl) +perlasm(ghash-x86_64.${ASM_EXT} asm/ghash-x86_64.pl) +perlasm(ghash-x86.${ASM_EXT} asm/ghash-x86.pl) +perlasm(ghash-armv4.${ASM_EXT} asm/ghash-armv4.pl) +perlasm(ghashv8-armx.${ASM_EXT} asm/ghashv8-armx.pl) + +if(ENABLE_TESTS) +add_executable( + gcm_test + + gcm_test.c + + $ +) + +target_link_libraries(gcm_test crypto) +add_dependencies(all_tests gcm_test) +endif() diff --git a/external/boringssl/crypto/modes/asm/aesni-gcm-x86_64.pl b/external/boringssl/crypto/modes/asm/aesni-gcm-x86_64.pl new file mode 100644 index 0000000000..5d58bbbbc9 --- /dev/null +++ b/external/boringssl/crypto/modes/asm/aesni-gcm-x86_64.pl @@ -0,0 +1,1087 @@ +#!/usr/bin/env perl +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# +# AES-NI-CTR+GHASH stitch. +# +# February 2013 +# +# OpenSSL GCM implementation is organized in such way that its +# performance is rather close to the sum of its streamed components, +# in the context parallelized AES-NI CTR and modulo-scheduled +# PCLMULQDQ-enabled GHASH. Unfortunately, as no stitch implementation +# was observed to perform significantly better than the sum of the +# components on contemporary CPUs, the effort was deemed impossible to +# justify. This module is based on combination of Intel submissions, +# [1] and [2], with MOVBE twist suggested by Ilya Albrekht and Max +# Locktyukhin of Intel Corp. who verified that it reduces shuffles +# pressure with notable relative improvement, achieving 1.0 cycle per +# byte processed with 128-bit key on Haswell processor, and 0.74 - +# on Broadwell. [Mentioned results are raw profiled measurements for +# favourable packet size, one divisible by 96. Applications using the +# EVP interface will observe a few percent worse performance.] +# +# [1] http://rt.openssl.org/Ticket/Display.html?id=2900&user=guest&pass=guest +# [2] http://www.intel.com/content/dam/www/public/us/en/documents/software-support/enabling-high-performance-gcm.pdf + +$flavour = shift; +$output = shift; +if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } + +$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or +die "can't locate x86_64-xlate.pl"; + +# This must be kept in sync with |$avx| in ghash-x86_64.pl; otherwise tags will +# be computed incorrectly. +# +# In upstream, this is controlled by shelling out to the compiler to check +# versions, but BoringSSL is intended to be used with pre-generated perlasm +# output, so this isn't useful anyway. +$avx = 0; + +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; + +if ($avx>1) {{{ + +($inp,$out,$len,$key,$ivp,$Xip)=("%rdi","%rsi","%rdx","%rcx","%r8","%r9"); + +($Ii,$T1,$T2,$Hkey, + $Z0,$Z1,$Z2,$Z3,$Xi) = map("%xmm$_",(0..8)); + +($inout0,$inout1,$inout2,$inout3,$inout4,$inout5,$rndkey) = map("%xmm$_",(9..15)); + +($counter,$rounds,$ret,$const,$in0,$end0)=("%ebx","%ebp","%r10","%r11","%r14","%r15"); + +$code=<<___; +.text + +.type _aesni_ctr32_ghash_6x,\@abi-omnipotent +.align 32 +_aesni_ctr32_ghash_6x: + vmovdqu 0x20($const),$T2 # borrow $T2, .Lone_msb + sub \$6,$len + vpxor $Z0,$Z0,$Z0 # $Z0 = 0 + vmovdqu 0x00-0x80($key),$rndkey + vpaddb $T2,$T1,$inout1 + vpaddb $T2,$inout1,$inout2 + vpaddb $T2,$inout2,$inout3 + vpaddb $T2,$inout3,$inout4 + vpaddb $T2,$inout4,$inout5 + vpxor $rndkey,$T1,$inout0 + vmovdqu $Z0,16+8(%rsp) # "$Z3" = 0 + jmp .Loop6x + +.align 32 +.Loop6x: + add \$`6<<24`,$counter + jc .Lhandle_ctr32 # discard $inout[1-5]? + vmovdqu 0x00-0x20($Xip),$Hkey # $Hkey^1 + vpaddb $T2,$inout5,$T1 # next counter value + vpxor $rndkey,$inout1,$inout1 + vpxor $rndkey,$inout2,$inout2 + +.Lresume_ctr32: + vmovdqu $T1,($ivp) # save next counter value + vpclmulqdq \$0x10,$Hkey,$Z3,$Z1 + vpxor $rndkey,$inout3,$inout3 + vmovups 0x10-0x80($key),$T2 # borrow $T2 for $rndkey + vpclmulqdq \$0x01,$Hkey,$Z3,$Z2 + + # At this point, the current block of 96 (0x60) bytes has already been + # loaded into registers. Concurrently with processing it, we want to + # load the next 96 bytes of input for the next round. Obviously, we can + # only do this if there are at least 96 more bytes of input beyond the + # input we're currently processing, or else we'd read past the end of + # the input buffer. Here, we set |%r12| to 96 if there are at least 96 + # bytes of input beyond the 96 bytes we're already processing, and we + # set |%r12| to 0 otherwise. In the case where we set |%r12| to 96, + # we'll read in the next block so that it is in registers for the next + # loop iteration. In the case where we set |%r12| to 0, we'll re-read + # the current block and then ignore what we re-read. + # + # At this point, |$in0| points to the current (already read into + # registers) block, and |$end0| points to 2*96 bytes before the end of + # the input. Thus, |$in0| > |$end0| means that we do not have the next + # 96-byte block to read in, and |$in0| <= |$end0| means we do. + xor %r12,%r12 + cmp $in0,$end0 + + vaesenc $T2,$inout0,$inout0 + vmovdqu 0x30+8(%rsp),$Ii # I[4] + vpxor $rndkey,$inout4,$inout4 + vpclmulqdq \$0x00,$Hkey,$Z3,$T1 + vaesenc $T2,$inout1,$inout1 + vpxor $rndkey,$inout5,$inout5 + setnc %r12b + vpclmulqdq \$0x11,$Hkey,$Z3,$Z3 + vaesenc $T2,$inout2,$inout2 + vmovdqu 0x10-0x20($Xip),$Hkey # $Hkey^2 + neg %r12 + vaesenc $T2,$inout3,$inout3 + vpxor $Z1,$Z2,$Z2 + vpclmulqdq \$0x00,$Hkey,$Ii,$Z1 + vpxor $Z0,$Xi,$Xi # modulo-scheduled + vaesenc $T2,$inout4,$inout4 + vpxor $Z1,$T1,$Z0 + and \$0x60,%r12 + vmovups 0x20-0x80($key),$rndkey + vpclmulqdq \$0x10,$Hkey,$Ii,$T1 + vaesenc $T2,$inout5,$inout5 + + vpclmulqdq \$0x01,$Hkey,$Ii,$T2 + lea ($in0,%r12),$in0 + vaesenc $rndkey,$inout0,$inout0 + vpxor 16+8(%rsp),$Xi,$Xi # modulo-scheduled [vpxor $Z3,$Xi,$Xi] + vpclmulqdq \$0x11,$Hkey,$Ii,$Hkey + vmovdqu 0x40+8(%rsp),$Ii # I[3] + vaesenc $rndkey,$inout1,$inout1 + movbe 0x58($in0),%r13 + vaesenc $rndkey,$inout2,$inout2 + movbe 0x50($in0),%r12 + vaesenc $rndkey,$inout3,$inout3 + mov %r13,0x20+8(%rsp) + vaesenc $rndkey,$inout4,$inout4 + mov %r12,0x28+8(%rsp) + vmovdqu 0x30-0x20($Xip),$Z1 # borrow $Z1 for $Hkey^3 + vaesenc $rndkey,$inout5,$inout5 + + vmovups 0x30-0x80($key),$rndkey + vpxor $T1,$Z2,$Z2 + vpclmulqdq \$0x00,$Z1,$Ii,$T1 + vaesenc $rndkey,$inout0,$inout0 + vpxor $T2,$Z2,$Z2 + vpclmulqdq \$0x10,$Z1,$Ii,$T2 + vaesenc $rndkey,$inout1,$inout1 + vpxor $Hkey,$Z3,$Z3 + vpclmulqdq \$0x01,$Z1,$Ii,$Hkey + vaesenc $rndkey,$inout2,$inout2 + vpclmulqdq \$0x11,$Z1,$Ii,$Z1 + vmovdqu 0x50+8(%rsp),$Ii # I[2] + vaesenc $rndkey,$inout3,$inout3 + vaesenc $rndkey,$inout4,$inout4 + vpxor $T1,$Z0,$Z0 + vmovdqu 0x40-0x20($Xip),$T1 # borrow $T1 for $Hkey^4 + vaesenc $rndkey,$inout5,$inout5 + + vmovups 0x40-0x80($key),$rndkey + vpxor $T2,$Z2,$Z2 + vpclmulqdq \$0x00,$T1,$Ii,$T2 + vaesenc $rndkey,$inout0,$inout0 + vpxor $Hkey,$Z2,$Z2 + vpclmulqdq \$0x10,$T1,$Ii,$Hkey + vaesenc $rndkey,$inout1,$inout1 + movbe 0x48($in0),%r13 + vpxor $Z1,$Z3,$Z3 + vpclmulqdq \$0x01,$T1,$Ii,$Z1 + vaesenc $rndkey,$inout2,$inout2 + movbe 0x40($in0),%r12 + vpclmulqdq \$0x11,$T1,$Ii,$T1 + vmovdqu 0x60+8(%rsp),$Ii # I[1] + vaesenc $rndkey,$inout3,$inout3 + mov %r13,0x30+8(%rsp) + vaesenc $rndkey,$inout4,$inout4 + mov %r12,0x38+8(%rsp) + vpxor $T2,$Z0,$Z0 + vmovdqu 0x60-0x20($Xip),$T2 # borrow $T2 for $Hkey^5 + vaesenc $rndkey,$inout5,$inout5 + + vmovups 0x50-0x80($key),$rndkey + vpxor $Hkey,$Z2,$Z2 + vpclmulqdq \$0x00,$T2,$Ii,$Hkey + vaesenc $rndkey,$inout0,$inout0 + vpxor $Z1,$Z2,$Z2 + vpclmulqdq \$0x10,$T2,$Ii,$Z1 + vaesenc $rndkey,$inout1,$inout1 + movbe 0x38($in0),%r13 + vpxor $T1,$Z3,$Z3 + vpclmulqdq \$0x01,$T2,$Ii,$T1 + vpxor 0x70+8(%rsp),$Xi,$Xi # accumulate I[0] + vaesenc $rndkey,$inout2,$inout2 + movbe 0x30($in0),%r12 + vpclmulqdq \$0x11,$T2,$Ii,$T2 + vaesenc $rndkey,$inout3,$inout3 + mov %r13,0x40+8(%rsp) + vaesenc $rndkey,$inout4,$inout4 + mov %r12,0x48+8(%rsp) + vpxor $Hkey,$Z0,$Z0 + vmovdqu 0x70-0x20($Xip),$Hkey # $Hkey^6 + vaesenc $rndkey,$inout5,$inout5 + + vmovups 0x60-0x80($key),$rndkey + vpxor $Z1,$Z2,$Z2 + vpclmulqdq \$0x10,$Hkey,$Xi,$Z1 + vaesenc $rndkey,$inout0,$inout0 + vpxor $T1,$Z2,$Z2 + vpclmulqdq \$0x01,$Hkey,$Xi,$T1 + vaesenc $rndkey,$inout1,$inout1 + movbe 0x28($in0),%r13 + vpxor $T2,$Z3,$Z3 + vpclmulqdq \$0x00,$Hkey,$Xi,$T2 + vaesenc $rndkey,$inout2,$inout2 + movbe 0x20($in0),%r12 + vpclmulqdq \$0x11,$Hkey,$Xi,$Xi + vaesenc $rndkey,$inout3,$inout3 + mov %r13,0x50+8(%rsp) + vaesenc $rndkey,$inout4,$inout4 + mov %r12,0x58+8(%rsp) + vpxor $Z1,$Z2,$Z2 + vaesenc $rndkey,$inout5,$inout5 + vpxor $T1,$Z2,$Z2 + + vmovups 0x70-0x80($key),$rndkey + vpslldq \$8,$Z2,$Z1 + vpxor $T2,$Z0,$Z0 + vmovdqu 0x10($const),$Hkey # .Lpoly + + vaesenc $rndkey,$inout0,$inout0 + vpxor $Xi,$Z3,$Z3 + vaesenc $rndkey,$inout1,$inout1 + vpxor $Z1,$Z0,$Z0 + movbe 0x18($in0),%r13 + vaesenc $rndkey,$inout2,$inout2 + movbe 0x10($in0),%r12 + vpalignr \$8,$Z0,$Z0,$Ii # 1st phase + vpclmulqdq \$0x10,$Hkey,$Z0,$Z0 + mov %r13,0x60+8(%rsp) + vaesenc $rndkey,$inout3,$inout3 + mov %r12,0x68+8(%rsp) + vaesenc $rndkey,$inout4,$inout4 + vmovups 0x80-0x80($key),$T1 # borrow $T1 for $rndkey + vaesenc $rndkey,$inout5,$inout5 + + vaesenc $T1,$inout0,$inout0 + vmovups 0x90-0x80($key),$rndkey + vaesenc $T1,$inout1,$inout1 + vpsrldq \$8,$Z2,$Z2 + vaesenc $T1,$inout2,$inout2 + vpxor $Z2,$Z3,$Z3 + vaesenc $T1,$inout3,$inout3 + vpxor $Ii,$Z0,$Z0 + movbe 0x08($in0),%r13 + vaesenc $T1,$inout4,$inout4 + movbe 0x00($in0),%r12 + vaesenc $T1,$inout5,$inout5 + vmovups 0xa0-0x80($key),$T1 + cmp \$11,$rounds + jb .Lenc_tail # 128-bit key + + vaesenc $rndkey,$inout0,$inout0 + vaesenc $rndkey,$inout1,$inout1 + vaesenc $rndkey,$inout2,$inout2 + vaesenc $rndkey,$inout3,$inout3 + vaesenc $rndkey,$inout4,$inout4 + vaesenc $rndkey,$inout5,$inout5 + + vaesenc $T1,$inout0,$inout0 + vaesenc $T1,$inout1,$inout1 + vaesenc $T1,$inout2,$inout2 + vaesenc $T1,$inout3,$inout3 + vaesenc $T1,$inout4,$inout4 + vmovups 0xb0-0x80($key),$rndkey + vaesenc $T1,$inout5,$inout5 + vmovups 0xc0-0x80($key),$T1 + je .Lenc_tail # 192-bit key + + vaesenc $rndkey,$inout0,$inout0 + vaesenc $rndkey,$inout1,$inout1 + vaesenc $rndkey,$inout2,$inout2 + vaesenc $rndkey,$inout3,$inout3 + vaesenc $rndkey,$inout4,$inout4 + vaesenc $rndkey,$inout5,$inout5 + + vaesenc $T1,$inout0,$inout0 + vaesenc $T1,$inout1,$inout1 + vaesenc $T1,$inout2,$inout2 + vaesenc $T1,$inout3,$inout3 + vaesenc $T1,$inout4,$inout4 + vmovups 0xd0-0x80($key),$rndkey + vaesenc $T1,$inout5,$inout5 + vmovups 0xe0-0x80($key),$T1 + jmp .Lenc_tail # 256-bit key + +.align 32 +.Lhandle_ctr32: + vmovdqu ($const),$Ii # borrow $Ii for .Lbswap_mask + vpshufb $Ii,$T1,$Z2 # byte-swap counter + vmovdqu 0x30($const),$Z1 # borrow $Z1, .Ltwo_lsb + vpaddd 0x40($const),$Z2,$inout1 # .Lone_lsb + vpaddd $Z1,$Z2,$inout2 + vmovdqu 0x00-0x20($Xip),$Hkey # $Hkey^1 + vpaddd $Z1,$inout1,$inout3 + vpshufb $Ii,$inout1,$inout1 + vpaddd $Z1,$inout2,$inout4 + vpshufb $Ii,$inout2,$inout2 + vpxor $rndkey,$inout1,$inout1 + vpaddd $Z1,$inout3,$inout5 + vpshufb $Ii,$inout3,$inout3 + vpxor $rndkey,$inout2,$inout2 + vpaddd $Z1,$inout4,$T1 # byte-swapped next counter value + vpshufb $Ii,$inout4,$inout4 + vpshufb $Ii,$inout5,$inout5 + vpshufb $Ii,$T1,$T1 # next counter value + jmp .Lresume_ctr32 + +.align 32 +.Lenc_tail: + vaesenc $rndkey,$inout0,$inout0 + vmovdqu $Z3,16+8(%rsp) # postpone vpxor $Z3,$Xi,$Xi + vpalignr \$8,$Z0,$Z0,$Xi # 2nd phase + vaesenc $rndkey,$inout1,$inout1 + vpclmulqdq \$0x10,$Hkey,$Z0,$Z0 + vpxor 0x00($inp),$T1,$T2 + vaesenc $rndkey,$inout2,$inout2 + vpxor 0x10($inp),$T1,$Ii + vaesenc $rndkey,$inout3,$inout3 + vpxor 0x20($inp),$T1,$Z1 + vaesenc $rndkey,$inout4,$inout4 + vpxor 0x30($inp),$T1,$Z2 + vaesenc $rndkey,$inout5,$inout5 + vpxor 0x40($inp),$T1,$Z3 + vpxor 0x50($inp),$T1,$Hkey + vmovdqu ($ivp),$T1 # load next counter value + + vaesenclast $T2,$inout0,$inout0 + vmovdqu 0x20($const),$T2 # borrow $T2, .Lone_msb + vaesenclast $Ii,$inout1,$inout1 + vpaddb $T2,$T1,$Ii + mov %r13,0x70+8(%rsp) + lea 0x60($inp),$inp + vaesenclast $Z1,$inout2,$inout2 + vpaddb $T2,$Ii,$Z1 + mov %r12,0x78+8(%rsp) + lea 0x60($out),$out + vmovdqu 0x00-0x80($key),$rndkey + vaesenclast $Z2,$inout3,$inout3 + vpaddb $T2,$Z1,$Z2 + vaesenclast $Z3, $inout4,$inout4 + vpaddb $T2,$Z2,$Z3 + vaesenclast $Hkey,$inout5,$inout5 + vpaddb $T2,$Z3,$Hkey + + add \$0x60,$ret + sub \$0x6,$len + jc .L6x_done + + vmovups $inout0,-0x60($out) # save output + vpxor $rndkey,$T1,$inout0 + vmovups $inout1,-0x50($out) + vmovdqa $Ii,$inout1 # 0 latency + vmovups $inout2,-0x40($out) + vmovdqa $Z1,$inout2 # 0 latency + vmovups $inout3,-0x30($out) + vmovdqa $Z2,$inout3 # 0 latency + vmovups $inout4,-0x20($out) + vmovdqa $Z3,$inout4 # 0 latency + vmovups $inout5,-0x10($out) + vmovdqa $Hkey,$inout5 # 0 latency + vmovdqu 0x20+8(%rsp),$Z3 # I[5] + jmp .Loop6x + +.L6x_done: + vpxor 16+8(%rsp),$Xi,$Xi # modulo-scheduled + vpxor $Z0,$Xi,$Xi # modulo-scheduled + + ret +.size _aesni_ctr32_ghash_6x,.-_aesni_ctr32_ghash_6x +___ +###################################################################### +# +# size_t aesni_gcm_[en|de]crypt(const void *inp, void *out, size_t len, +# const AES_KEY *key, unsigned char iv[16], +# struct { u128 Xi,H,Htbl[9]; } *Xip); +$code.=<<___; +.globl aesni_gcm_decrypt +.type aesni_gcm_decrypt,\@function,6 +.align 32 +aesni_gcm_decrypt: + xor $ret,$ret + + # We call |_aesni_ctr32_ghash_6x|, which requires at least 96 (0x60) + # bytes of input. + cmp \$0x60,$len # minimal accepted length + jb .Lgcm_dec_abort + + lea (%rsp),%rax # save stack pointer + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 +___ +$code.=<<___ if ($win64); + lea -0xa8(%rsp),%rsp + movaps %xmm6,-0xd8(%rax) + movaps %xmm7,-0xc8(%rax) + movaps %xmm8,-0xb8(%rax) + movaps %xmm9,-0xa8(%rax) + movaps %xmm10,-0x98(%rax) + movaps %xmm11,-0x88(%rax) + movaps %xmm12,-0x78(%rax) + movaps %xmm13,-0x68(%rax) + movaps %xmm14,-0x58(%rax) + movaps %xmm15,-0x48(%rax) +.Lgcm_dec_body: +___ +$code.=<<___; + vzeroupper + + vmovdqu ($ivp),$T1 # input counter value + add \$-128,%rsp + mov 12($ivp),$counter + lea .Lbswap_mask(%rip),$const + lea -0x80($key),$in0 # borrow $in0 + mov \$0xf80,$end0 # borrow $end0 + vmovdqu ($Xip),$Xi # load Xi + and \$-128,%rsp # ensure stack alignment + vmovdqu ($const),$Ii # borrow $Ii for .Lbswap_mask + lea 0x80($key),$key # size optimization + lea 0x20+0x20($Xip),$Xip # size optimization + mov 0xf0-0x80($key),$rounds + vpshufb $Ii,$Xi,$Xi + + and $end0,$in0 + and %rsp,$end0 + sub $in0,$end0 + jc .Ldec_no_key_aliasing + cmp \$768,$end0 + jnc .Ldec_no_key_aliasing + sub $end0,%rsp # avoid aliasing with key +.Ldec_no_key_aliasing: + + vmovdqu 0x50($inp),$Z3 # I[5] + lea ($inp),$in0 + vmovdqu 0x40($inp),$Z0 + + # |_aesni_ctr32_ghash_6x| requires |$end0| to point to 2*96 (0xc0) + # bytes before the end of the input. Note, in particular, that this is + # correct even if |$len| is not an even multiple of 96 or 16. XXX: This + # seems to require that |$inp| + |$len| >= 2*96 (0xc0); i.e. |$inp| must + # not be near the very beginning of the address space when |$len| < 2*96 + # (0xc0). + lea -0xc0($inp,$len),$end0 + + vmovdqu 0x30($inp),$Z1 + shr \$4,$len + xor $ret,$ret + vmovdqu 0x20($inp),$Z2 + vpshufb $Ii,$Z3,$Z3 # passed to _aesni_ctr32_ghash_6x + vmovdqu 0x10($inp),$T2 + vpshufb $Ii,$Z0,$Z0 + vmovdqu ($inp),$Hkey + vpshufb $Ii,$Z1,$Z1 + vmovdqu $Z0,0x30(%rsp) + vpshufb $Ii,$Z2,$Z2 + vmovdqu $Z1,0x40(%rsp) + vpshufb $Ii,$T2,$T2 + vmovdqu $Z2,0x50(%rsp) + vpshufb $Ii,$Hkey,$Hkey + vmovdqu $T2,0x60(%rsp) + vmovdqu $Hkey,0x70(%rsp) + + call _aesni_ctr32_ghash_6x + + vmovups $inout0,-0x60($out) # save output + vmovups $inout1,-0x50($out) + vmovups $inout2,-0x40($out) + vmovups $inout3,-0x30($out) + vmovups $inout4,-0x20($out) + vmovups $inout5,-0x10($out) + + vpshufb ($const),$Xi,$Xi # .Lbswap_mask + vmovdqu $Xi,-0x40($Xip) # output Xi + + vzeroupper +___ +$code.=<<___ if ($win64); + movaps -0xd8(%rax),%xmm6 + movaps -0xc8(%rax),%xmm7 + movaps -0xb8(%rax),%xmm8 + movaps -0xa8(%rax),%xmm9 + movaps -0x98(%rax),%xmm10 + movaps -0x88(%rax),%xmm11 + movaps -0x78(%rax),%xmm12 + movaps -0x68(%rax),%xmm13 + movaps -0x58(%rax),%xmm14 + movaps -0x48(%rax),%xmm15 +___ +$code.=<<___; + mov -48(%rax),%r15 + mov -40(%rax),%r14 + mov -32(%rax),%r13 + mov -24(%rax),%r12 + mov -16(%rax),%rbp + mov -8(%rax),%rbx + lea (%rax),%rsp # restore %rsp +.Lgcm_dec_abort: + mov $ret,%rax # return value + ret +.size aesni_gcm_decrypt,.-aesni_gcm_decrypt +___ + +$code.=<<___; +.type _aesni_ctr32_6x,\@abi-omnipotent +.align 32 +_aesni_ctr32_6x: + vmovdqu 0x00-0x80($key),$Z0 # borrow $Z0 for $rndkey + vmovdqu 0x20($const),$T2 # borrow $T2, .Lone_msb + lea -1($rounds),%r13 + vmovups 0x10-0x80($key),$rndkey + lea 0x20-0x80($key),%r12 + vpxor $Z0,$T1,$inout0 + add \$`6<<24`,$counter + jc .Lhandle_ctr32_2 + vpaddb $T2,$T1,$inout1 + vpaddb $T2,$inout1,$inout2 + vpxor $Z0,$inout1,$inout1 + vpaddb $T2,$inout2,$inout3 + vpxor $Z0,$inout2,$inout2 + vpaddb $T2,$inout3,$inout4 + vpxor $Z0,$inout3,$inout3 + vpaddb $T2,$inout4,$inout5 + vpxor $Z0,$inout4,$inout4 + vpaddb $T2,$inout5,$T1 + vpxor $Z0,$inout5,$inout5 + jmp .Loop_ctr32 + +.align 16 +.Loop_ctr32: + vaesenc $rndkey,$inout0,$inout0 + vaesenc $rndkey,$inout1,$inout1 + vaesenc $rndkey,$inout2,$inout2 + vaesenc $rndkey,$inout3,$inout3 + vaesenc $rndkey,$inout4,$inout4 + vaesenc $rndkey,$inout5,$inout5 + vmovups (%r12),$rndkey + lea 0x10(%r12),%r12 + dec %r13d + jnz .Loop_ctr32 + + vmovdqu (%r12),$Hkey # last round key + vaesenc $rndkey,$inout0,$inout0 + vpxor 0x00($inp),$Hkey,$Z0 + vaesenc $rndkey,$inout1,$inout1 + vpxor 0x10($inp),$Hkey,$Z1 + vaesenc $rndkey,$inout2,$inout2 + vpxor 0x20($inp),$Hkey,$Z2 + vaesenc $rndkey,$inout3,$inout3 + vpxor 0x30($inp),$Hkey,$Xi + vaesenc $rndkey,$inout4,$inout4 + vpxor 0x40($inp),$Hkey,$T2 + vaesenc $rndkey,$inout5,$inout5 + vpxor 0x50($inp),$Hkey,$Hkey + lea 0x60($inp),$inp + + vaesenclast $Z0,$inout0,$inout0 + vaesenclast $Z1,$inout1,$inout1 + vaesenclast $Z2,$inout2,$inout2 + vaesenclast $Xi,$inout3,$inout3 + vaesenclast $T2,$inout4,$inout4 + vaesenclast $Hkey,$inout5,$inout5 + vmovups $inout0,0x00($out) + vmovups $inout1,0x10($out) + vmovups $inout2,0x20($out) + vmovups $inout3,0x30($out) + vmovups $inout4,0x40($out) + vmovups $inout5,0x50($out) + lea 0x60($out),$out + + ret +.align 32 +.Lhandle_ctr32_2: + vpshufb $Ii,$T1,$Z2 # byte-swap counter + vmovdqu 0x30($const),$Z1 # borrow $Z1, .Ltwo_lsb + vpaddd 0x40($const),$Z2,$inout1 # .Lone_lsb + vpaddd $Z1,$Z2,$inout2 + vpaddd $Z1,$inout1,$inout3 + vpshufb $Ii,$inout1,$inout1 + vpaddd $Z1,$inout2,$inout4 + vpshufb $Ii,$inout2,$inout2 + vpxor $Z0,$inout1,$inout1 + vpaddd $Z1,$inout3,$inout5 + vpshufb $Ii,$inout3,$inout3 + vpxor $Z0,$inout2,$inout2 + vpaddd $Z1,$inout4,$T1 # byte-swapped next counter value + vpshufb $Ii,$inout4,$inout4 + vpxor $Z0,$inout3,$inout3 + vpshufb $Ii,$inout5,$inout5 + vpxor $Z0,$inout4,$inout4 + vpshufb $Ii,$T1,$T1 # next counter value + vpxor $Z0,$inout5,$inout5 + jmp .Loop_ctr32 +.size _aesni_ctr32_6x,.-_aesni_ctr32_6x + +.globl aesni_gcm_encrypt +.type aesni_gcm_encrypt,\@function,6 +.align 32 +aesni_gcm_encrypt: + xor $ret,$ret + + # We call |_aesni_ctr32_6x| twice, each call consuming 96 bytes of + # input. Then we call |_aesni_ctr32_ghash_6x|, which requires at + # least 96 more bytes of input. + cmp \$0x60*3,$len # minimal accepted length + jb .Lgcm_enc_abort + + lea (%rsp),%rax # save stack pointer + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 +___ +$code.=<<___ if ($win64); + lea -0xa8(%rsp),%rsp + movaps %xmm6,-0xd8(%rax) + movaps %xmm7,-0xc8(%rax) + movaps %xmm8,-0xb8(%rax) + movaps %xmm9,-0xa8(%rax) + movaps %xmm10,-0x98(%rax) + movaps %xmm11,-0x88(%rax) + movaps %xmm12,-0x78(%rax) + movaps %xmm13,-0x68(%rax) + movaps %xmm14,-0x58(%rax) + movaps %xmm15,-0x48(%rax) +.Lgcm_enc_body: +___ +$code.=<<___; + vzeroupper + + vmovdqu ($ivp),$T1 # input counter value + add \$-128,%rsp + mov 12($ivp),$counter + lea .Lbswap_mask(%rip),$const + lea -0x80($key),$in0 # borrow $in0 + mov \$0xf80,$end0 # borrow $end0 + lea 0x80($key),$key # size optimization + vmovdqu ($const),$Ii # borrow $Ii for .Lbswap_mask + and \$-128,%rsp # ensure stack alignment + mov 0xf0-0x80($key),$rounds + + and $end0,$in0 + and %rsp,$end0 + sub $in0,$end0 + jc .Lenc_no_key_aliasing + cmp \$768,$end0 + jnc .Lenc_no_key_aliasing + sub $end0,%rsp # avoid aliasing with key +.Lenc_no_key_aliasing: + + lea ($out),$in0 + + # |_aesni_ctr32_ghash_6x| requires |$end0| to point to 2*96 (0xc0) + # bytes before the end of the input. Note, in particular, that this is + # correct even if |$len| is not an even multiple of 96 or 16. Unlike in + # the decryption case, there's no caveat that |$out| must not be near + # the very beginning of the address space, because we know that + # |$len| >= 3*96 from the check above, and so we know + # |$out| + |$len| >= 2*96 (0xc0). + lea -0xc0($out,$len),$end0 + + shr \$4,$len + + call _aesni_ctr32_6x + vpshufb $Ii,$inout0,$Xi # save bswapped output on stack + vpshufb $Ii,$inout1,$T2 + vmovdqu $Xi,0x70(%rsp) + vpshufb $Ii,$inout2,$Z0 + vmovdqu $T2,0x60(%rsp) + vpshufb $Ii,$inout3,$Z1 + vmovdqu $Z0,0x50(%rsp) + vpshufb $Ii,$inout4,$Z2 + vmovdqu $Z1,0x40(%rsp) + vpshufb $Ii,$inout5,$Z3 # passed to _aesni_ctr32_ghash_6x + vmovdqu $Z2,0x30(%rsp) + + call _aesni_ctr32_6x + + vmovdqu ($Xip),$Xi # load Xi + lea 0x20+0x20($Xip),$Xip # size optimization + sub \$12,$len + mov \$0x60*2,$ret + vpshufb $Ii,$Xi,$Xi + + call _aesni_ctr32_ghash_6x + vmovdqu 0x20(%rsp),$Z3 # I[5] + vmovdqu ($const),$Ii # borrow $Ii for .Lbswap_mask + vmovdqu 0x00-0x20($Xip),$Hkey # $Hkey^1 + vpunpckhqdq $Z3,$Z3,$T1 + vmovdqu 0x20-0x20($Xip),$rndkey # borrow $rndkey for $HK + vmovups $inout0,-0x60($out) # save output + vpshufb $Ii,$inout0,$inout0 # but keep bswapped copy + vpxor $Z3,$T1,$T1 + vmovups $inout1,-0x50($out) + vpshufb $Ii,$inout1,$inout1 + vmovups $inout2,-0x40($out) + vpshufb $Ii,$inout2,$inout2 + vmovups $inout3,-0x30($out) + vpshufb $Ii,$inout3,$inout3 + vmovups $inout4,-0x20($out) + vpshufb $Ii,$inout4,$inout4 + vmovups $inout5,-0x10($out) + vpshufb $Ii,$inout5,$inout5 + vmovdqu $inout0,0x10(%rsp) # free $inout0 +___ +{ my ($HK,$T3)=($rndkey,$inout0); + +$code.=<<___; + vmovdqu 0x30(%rsp),$Z2 # I[4] + vmovdqu 0x10-0x20($Xip),$Ii # borrow $Ii for $Hkey^2 + vpunpckhqdq $Z2,$Z2,$T2 + vpclmulqdq \$0x00,$Hkey,$Z3,$Z1 + vpxor $Z2,$T2,$T2 + vpclmulqdq \$0x11,$Hkey,$Z3,$Z3 + vpclmulqdq \$0x00,$HK,$T1,$T1 + + vmovdqu 0x40(%rsp),$T3 # I[3] + vpclmulqdq \$0x00,$Ii,$Z2,$Z0 + vmovdqu 0x30-0x20($Xip),$Hkey # $Hkey^3 + vpxor $Z1,$Z0,$Z0 + vpunpckhqdq $T3,$T3,$Z1 + vpclmulqdq \$0x11,$Ii,$Z2,$Z2 + vpxor $T3,$Z1,$Z1 + vpxor $Z3,$Z2,$Z2 + vpclmulqdq \$0x10,$HK,$T2,$T2 + vmovdqu 0x50-0x20($Xip),$HK + vpxor $T1,$T2,$T2 + + vmovdqu 0x50(%rsp),$T1 # I[2] + vpclmulqdq \$0x00,$Hkey,$T3,$Z3 + vmovdqu 0x40-0x20($Xip),$Ii # borrow $Ii for $Hkey^4 + vpxor $Z0,$Z3,$Z3 + vpunpckhqdq $T1,$T1,$Z0 + vpclmulqdq \$0x11,$Hkey,$T3,$T3 + vpxor $T1,$Z0,$Z0 + vpxor $Z2,$T3,$T3 + vpclmulqdq \$0x00,$HK,$Z1,$Z1 + vpxor $T2,$Z1,$Z1 + + vmovdqu 0x60(%rsp),$T2 # I[1] + vpclmulqdq \$0x00,$Ii,$T1,$Z2 + vmovdqu 0x60-0x20($Xip),$Hkey # $Hkey^5 + vpxor $Z3,$Z2,$Z2 + vpunpckhqdq $T2,$T2,$Z3 + vpclmulqdq \$0x11,$Ii,$T1,$T1 + vpxor $T2,$Z3,$Z3 + vpxor $T3,$T1,$T1 + vpclmulqdq \$0x10,$HK,$Z0,$Z0 + vmovdqu 0x80-0x20($Xip),$HK + vpxor $Z1,$Z0,$Z0 + + vpxor 0x70(%rsp),$Xi,$Xi # accumulate I[0] + vpclmulqdq \$0x00,$Hkey,$T2,$Z1 + vmovdqu 0x70-0x20($Xip),$Ii # borrow $Ii for $Hkey^6 + vpunpckhqdq $Xi,$Xi,$T3 + vpxor $Z2,$Z1,$Z1 + vpclmulqdq \$0x11,$Hkey,$T2,$T2 + vpxor $Xi,$T3,$T3 + vpxor $T1,$T2,$T2 + vpclmulqdq \$0x00,$HK,$Z3,$Z3 + vpxor $Z0,$Z3,$Z0 + + vpclmulqdq \$0x00,$Ii,$Xi,$Z2 + vmovdqu 0x00-0x20($Xip),$Hkey # $Hkey^1 + vpunpckhqdq $inout5,$inout5,$T1 + vpclmulqdq \$0x11,$Ii,$Xi,$Xi + vpxor $inout5,$T1,$T1 + vpxor $Z1,$Z2,$Z1 + vpclmulqdq \$0x10,$HK,$T3,$T3 + vmovdqu 0x20-0x20($Xip),$HK + vpxor $T2,$Xi,$Z3 + vpxor $Z0,$T3,$Z2 + + vmovdqu 0x10-0x20($Xip),$Ii # borrow $Ii for $Hkey^2 + vpxor $Z1,$Z3,$T3 # aggregated Karatsuba post-processing + vpclmulqdq \$0x00,$Hkey,$inout5,$Z0 + vpxor $T3,$Z2,$Z2 + vpunpckhqdq $inout4,$inout4,$T2 + vpclmulqdq \$0x11,$Hkey,$inout5,$inout5 + vpxor $inout4,$T2,$T2 + vpslldq \$8,$Z2,$T3 + vpclmulqdq \$0x00,$HK,$T1,$T1 + vpxor $T3,$Z1,$Xi + vpsrldq \$8,$Z2,$Z2 + vpxor $Z2,$Z3,$Z3 + + vpclmulqdq \$0x00,$Ii,$inout4,$Z1 + vmovdqu 0x30-0x20($Xip),$Hkey # $Hkey^3 + vpxor $Z0,$Z1,$Z1 + vpunpckhqdq $inout3,$inout3,$T3 + vpclmulqdq \$0x11,$Ii,$inout4,$inout4 + vpxor $inout3,$T3,$T3 + vpxor $inout5,$inout4,$inout4 + vpalignr \$8,$Xi,$Xi,$inout5 # 1st phase + vpclmulqdq \$0x10,$HK,$T2,$T2 + vmovdqu 0x50-0x20($Xip),$HK + vpxor $T1,$T2,$T2 + + vpclmulqdq \$0x00,$Hkey,$inout3,$Z0 + vmovdqu 0x40-0x20($Xip),$Ii # borrow $Ii for $Hkey^4 + vpxor $Z1,$Z0,$Z0 + vpunpckhqdq $inout2,$inout2,$T1 + vpclmulqdq \$0x11,$Hkey,$inout3,$inout3 + vpxor $inout2,$T1,$T1 + vpxor $inout4,$inout3,$inout3 + vxorps 0x10(%rsp),$Z3,$Z3 # accumulate $inout0 + vpclmulqdq \$0x00,$HK,$T3,$T3 + vpxor $T2,$T3,$T3 + + vpclmulqdq \$0x10,0x10($const),$Xi,$Xi + vxorps $inout5,$Xi,$Xi + + vpclmulqdq \$0x00,$Ii,$inout2,$Z1 + vmovdqu 0x60-0x20($Xip),$Hkey # $Hkey^5 + vpxor $Z0,$Z1,$Z1 + vpunpckhqdq $inout1,$inout1,$T2 + vpclmulqdq \$0x11,$Ii,$inout2,$inout2 + vpxor $inout1,$T2,$T2 + vpalignr \$8,$Xi,$Xi,$inout5 # 2nd phase + vpxor $inout3,$inout2,$inout2 + vpclmulqdq \$0x10,$HK,$T1,$T1 + vmovdqu 0x80-0x20($Xip),$HK + vpxor $T3,$T1,$T1 + + vxorps $Z3,$inout5,$inout5 + vpclmulqdq \$0x10,0x10($const),$Xi,$Xi + vxorps $inout5,$Xi,$Xi + + vpclmulqdq \$0x00,$Hkey,$inout1,$Z0 + vmovdqu 0x70-0x20($Xip),$Ii # borrow $Ii for $Hkey^6 + vpxor $Z1,$Z0,$Z0 + vpunpckhqdq $Xi,$Xi,$T3 + vpclmulqdq \$0x11,$Hkey,$inout1,$inout1 + vpxor $Xi,$T3,$T3 + vpxor $inout2,$inout1,$inout1 + vpclmulqdq \$0x00,$HK,$T2,$T2 + vpxor $T1,$T2,$T2 + + vpclmulqdq \$0x00,$Ii,$Xi,$Z1 + vpclmulqdq \$0x11,$Ii,$Xi,$Z3 + vpxor $Z0,$Z1,$Z1 + vpclmulqdq \$0x10,$HK,$T3,$Z2 + vpxor $inout1,$Z3,$Z3 + vpxor $T2,$Z2,$Z2 + + vpxor $Z1,$Z3,$Z0 # aggregated Karatsuba post-processing + vpxor $Z0,$Z2,$Z2 + vpslldq \$8,$Z2,$T1 + vmovdqu 0x10($const),$Hkey # .Lpoly + vpsrldq \$8,$Z2,$Z2 + vpxor $T1,$Z1,$Xi + vpxor $Z2,$Z3,$Z3 + + vpalignr \$8,$Xi,$Xi,$T2 # 1st phase + vpclmulqdq \$0x10,$Hkey,$Xi,$Xi + vpxor $T2,$Xi,$Xi + + vpalignr \$8,$Xi,$Xi,$T2 # 2nd phase + vpclmulqdq \$0x10,$Hkey,$Xi,$Xi + vpxor $Z3,$T2,$T2 + vpxor $T2,$Xi,$Xi +___ +} +$code.=<<___; + vpshufb ($const),$Xi,$Xi # .Lbswap_mask + vmovdqu $Xi,-0x40($Xip) # output Xi + + vzeroupper +___ +$code.=<<___ if ($win64); + movaps -0xd8(%rax),%xmm6 + movaps -0xc8(%rax),%xmm7 + movaps -0xb8(%rax),%xmm8 + movaps -0xa8(%rax),%xmm9 + movaps -0x98(%rax),%xmm10 + movaps -0x88(%rax),%xmm11 + movaps -0x78(%rax),%xmm12 + movaps -0x68(%rax),%xmm13 + movaps -0x58(%rax),%xmm14 + movaps -0x48(%rax),%xmm15 +___ +$code.=<<___; + mov -48(%rax),%r15 + mov -40(%rax),%r14 + mov -32(%rax),%r13 + mov -24(%rax),%r12 + mov -16(%rax),%rbp + mov -8(%rax),%rbx + lea (%rax),%rsp # restore %rsp +.Lgcm_enc_abort: + mov $ret,%rax # return value + ret +.size aesni_gcm_encrypt,.-aesni_gcm_encrypt +___ + +$code.=<<___; +.align 64 +.Lbswap_mask: + .byte 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0 +.Lpoly: + .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xc2 +.Lone_msb: + .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 +.Ltwo_lsb: + .byte 2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +.Lone_lsb: + .byte 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +.asciz "AES-NI GCM module for x86_64, CRYPTOGAMS by " +.align 64 +___ +if ($win64) { +$rec="%rcx"; +$frame="%rdx"; +$context="%r8"; +$disp="%r9"; + +$code.=<<___ +.extern __imp_RtlVirtualUnwind +.type gcm_se_handler,\@abi-omnipotent +.align 16 +gcm_se_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + mov 8($disp),%rsi # disp->ImageBase + mov 56($disp),%r11 # disp->HandlerData + + mov 0(%r11),%r10d # HandlerData[0] + lea (%rsi,%r10),%r10 # prologue label + cmp %r10,%rbx # context->RipRsp + + mov 4(%r11),%r10d # HandlerData[1] + lea (%rsi,%r10),%r10 # epilogue label + cmp %r10,%rbx # context->Rip>=epilogue label + jae .Lcommon_seh_tail + + mov 120($context),%rax # pull context->Rax + + mov -48(%rax),%r15 + mov -40(%rax),%r14 + mov -32(%rax),%r13 + mov -24(%rax),%r12 + mov -16(%rax),%rbp + mov -8(%rax),%rbx + mov %r15,240($context) + mov %r14,232($context) + mov %r13,224($context) + mov %r12,216($context) + mov %rbp,160($context) + mov %rbx,144($context) + + lea -0xd8(%rax),%rsi # %xmm save area + lea 512($context),%rdi # & context.Xmm6 + mov \$20,%ecx # 10*sizeof(%xmm0)/sizeof(%rax) + .long 0xa548f3fc # cld; rep movsq + +.Lcommon_seh_tail: + mov 8(%rax),%rdi + mov 16(%rax),%rsi + mov %rax,152($context) # restore context->Rsp + mov %rsi,168($context) # restore context->Rsi + mov %rdi,176($context) # restore context->Rdi + + mov 40($disp),%rdi # disp->ContextRecord + mov $context,%rsi # context + mov \$154,%ecx # sizeof(CONTEXT) + .long 0xa548f3fc # cld; rep movsq + + mov $disp,%rsi + xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER + mov 8(%rsi),%rdx # arg2, disp->ImageBase + mov 0(%rsi),%r8 # arg3, disp->ControlPc + mov 16(%rsi),%r9 # arg4, disp->FunctionEntry + mov 40(%rsi),%r10 # disp->ContextRecord + lea 56(%rsi),%r11 # &disp->HandlerData + lea 24(%rsi),%r12 # &disp->EstablisherFrame + mov %r10,32(%rsp) # arg5 + mov %r11,40(%rsp) # arg6 + mov %r12,48(%rsp) # arg7 + mov %rcx,56(%rsp) # arg8, (NULL) + call *__imp_RtlVirtualUnwind(%rip) + + mov \$1,%eax # ExceptionContinueSearch + add \$64,%rsp + popfq + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + pop %rdi + pop %rsi + ret +.size gcm_se_handler,.-gcm_se_handler + +.section .pdata +.align 4 + .rva .LSEH_begin_aesni_gcm_decrypt + .rva .LSEH_end_aesni_gcm_decrypt + .rva .LSEH_gcm_dec_info + + .rva .LSEH_begin_aesni_gcm_encrypt + .rva .LSEH_end_aesni_gcm_encrypt + .rva .LSEH_gcm_enc_info +.section .xdata +.align 8 +.LSEH_gcm_dec_info: + .byte 9,0,0,0 + .rva gcm_se_handler + .rva .Lgcm_dec_body,.Lgcm_dec_abort +.LSEH_gcm_enc_info: + .byte 9,0,0,0 + .rva gcm_se_handler + .rva .Lgcm_enc_body,.Lgcm_enc_abort +___ +} +}}} else {{{ +$code=<<___; # assembler is too old +.text + +.globl aesni_gcm_encrypt +.type aesni_gcm_encrypt,\@abi-omnipotent +aesni_gcm_encrypt: + xor %eax,%eax + ret +.size aesni_gcm_encrypt,.-aesni_gcm_encrypt + +.globl aesni_gcm_decrypt +.type aesni_gcm_decrypt,\@abi-omnipotent +aesni_gcm_decrypt: + xor %eax,%eax + ret +.size aesni_gcm_decrypt,.-aesni_gcm_decrypt +___ +}}} + +$code =~ s/\`([^\`]*)\`/eval($1)/gem; + +print $code; + +close STDOUT; diff --git a/external/boringssl/crypto/modes/asm/ghash-armv4.pl b/external/boringssl/crypto/modes/asm/ghash-armv4.pl new file mode 100644 index 0000000000..bb0dba5f53 --- /dev/null +++ b/external/boringssl/crypto/modes/asm/ghash-armv4.pl @@ -0,0 +1,512 @@ +#!/usr/bin/env perl +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# April 2010 +# +# The module implements "4-bit" GCM GHASH function and underlying +# single multiplication operation in GF(2^128). "4-bit" means that it +# uses 256 bytes per-key table [+32 bytes shared table]. There is no +# experimental performance data available yet. The only approximation +# that can be made at this point is based on code size. Inner loop is +# 32 instructions long and on single-issue core should execute in <40 +# cycles. Having verified that gcc 3.4 didn't unroll corresponding +# loop, this assembler loop body was found to be ~3x smaller than +# compiler-generated one... +# +# July 2010 +# +# Rescheduling for dual-issue pipeline resulted in 8.5% improvement on +# Cortex A8 core and ~25 cycles per processed byte (which was observed +# to be ~3 times faster than gcc-generated code:-) +# +# February 2011 +# +# Profiler-assisted and platform-specific optimization resulted in 7% +# improvement on Cortex A8 core and ~23.5 cycles per byte. +# +# March 2011 +# +# Add NEON implementation featuring polynomial multiplication, i.e. no +# lookup tables involved. On Cortex A8 it was measured to process one +# byte in 15 cycles or 55% faster than integer-only code. +# +# April 2014 +# +# Switch to multiplication algorithm suggested in paper referred +# below and combine it with reduction algorithm from x86 module. +# Performance improvement over previous version varies from 65% on +# Snapdragon S4 to 110% on Cortex A9. In absolute terms Cortex A8 +# processes one byte in 8.45 cycles, A9 - in 10.2, A15 - in 7.63, +# Snapdragon S4 - in 9.33. +# +# Câmara, D.; Gouvêa, C. P. L.; López, J. & Dahab, R.: Fast Software +# Polynomial Multiplication on ARM Processors using the NEON Engine. +# +# http://conradoplg.cryptoland.net/files/2010/12/mocrysen13.pdf + +# ==================================================================== +# Note about "528B" variant. In ARM case it makes lesser sense to +# implement it for following reasons: +# +# - performance improvement won't be anywhere near 50%, because 128- +# bit shift operation is neatly fused with 128-bit xor here, and +# "538B" variant would eliminate only 4-5 instructions out of 32 +# in the inner loop (meaning that estimated improvement is ~15%); +# - ARM-based systems are often embedded ones and extra memory +# consumption might be unappreciated (for so little improvement); +# +# Byte order [in]dependence. ========================================= +# +# Caller is expected to maintain specific *dword* order in Htable, +# namely with *least* significant dword of 128-bit value at *lower* +# address. This differs completely from C code and has everything to +# do with ldm instruction and order in which dwords are "consumed" by +# algorithm. *Byte* order within these dwords in turn is whatever +# *native* byte order on current platform. See gcm128.c for working +# example... + +$flavour = shift; +if ($flavour=~/^\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; } +else { while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {} } + +if ($flavour && $flavour ne "void") { + $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; + ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or + ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or + die "can't locate arm-xlate.pl"; + + open STDOUT,"| \"$^X\" $xlate $flavour $output"; +} else { + open STDOUT,">$output"; +} + +$Xi="r0"; # argument block +$Htbl="r1"; +$inp="r2"; +$len="r3"; + +$Zll="r4"; # variables +$Zlh="r5"; +$Zhl="r6"; +$Zhh="r7"; +$Tll="r8"; +$Tlh="r9"; +$Thl="r10"; +$Thh="r11"; +$nlo="r12"; +################# r13 is stack pointer +$nhi="r14"; +################# r15 is program counter + +$rem_4bit=$inp; # used in gcm_gmult_4bit +$cnt=$len; + +sub Zsmash() { + my $i=12; + my @args=@_; + for ($Zll,$Zlh,$Zhl,$Zhh) { + $code.=<<___; +#if __ARM_ARCH__>=7 && defined(__ARMEL__) + rev $_,$_ + str $_,[$Xi,#$i] +#elif defined(__ARMEB__) + str $_,[$Xi,#$i] +#else + mov $Tlh,$_,lsr#8 + strb $_,[$Xi,#$i+3] + mov $Thl,$_,lsr#16 + strb $Tlh,[$Xi,#$i+2] + mov $Thh,$_,lsr#24 + strb $Thl,[$Xi,#$i+1] + strb $Thh,[$Xi,#$i] +#endif +___ + $code.="\t".shift(@args)."\n"; + $i-=4; + } +} + +$code=<<___; +#include + +.syntax unified + +.text +.code 32 + +#ifdef __clang__ +#define ldrplb ldrbpl +#define ldrneb ldrbne +#endif + +.type rem_4bit,%object +.align 5 +rem_4bit: +.short 0x0000,0x1C20,0x3840,0x2460 +.short 0x7080,0x6CA0,0x48C0,0x54E0 +.short 0xE100,0xFD20,0xD940,0xC560 +.short 0x9180,0x8DA0,0xA9C0,0xB5E0 +.size rem_4bit,.-rem_4bit + +.type rem_4bit_get,%function +rem_4bit_get: + sub $rem_4bit,pc,#8 + sub $rem_4bit,$rem_4bit,#32 @ &rem_4bit + b .Lrem_4bit_got + nop +.size rem_4bit_get,.-rem_4bit_get + +.global gcm_ghash_4bit +.type gcm_ghash_4bit,%function +gcm_ghash_4bit: + sub r12,pc,#8 + add $len,$inp,$len @ $len to point at the end + stmdb sp!,{r3-r11,lr} @ save $len/end too + sub r12,r12,#48 @ &rem_4bit + + ldmia r12,{r4-r11} @ copy rem_4bit ... + stmdb sp!,{r4-r11} @ ... to stack + + ldrb $nlo,[$inp,#15] + ldrb $nhi,[$Xi,#15] +.Louter: + eor $nlo,$nlo,$nhi + and $nhi,$nlo,#0xf0 + and $nlo,$nlo,#0x0f + mov $cnt,#14 + + add $Zhh,$Htbl,$nlo,lsl#4 + ldmia $Zhh,{$Zll-$Zhh} @ load Htbl[nlo] + add $Thh,$Htbl,$nhi + ldrb $nlo,[$inp,#14] + + and $nhi,$Zll,#0xf @ rem + ldmia $Thh,{$Tll-$Thh} @ load Htbl[nhi] + add $nhi,$nhi,$nhi + eor $Zll,$Tll,$Zll,lsr#4 + ldrh $Tll,[sp,$nhi] @ rem_4bit[rem] + eor $Zll,$Zll,$Zlh,lsl#28 + ldrb $nhi,[$Xi,#14] + eor $Zlh,$Tlh,$Zlh,lsr#4 + eor $Zlh,$Zlh,$Zhl,lsl#28 + eor $Zhl,$Thl,$Zhl,lsr#4 + eor $Zhl,$Zhl,$Zhh,lsl#28 + eor $Zhh,$Thh,$Zhh,lsr#4 + eor $nlo,$nlo,$nhi + and $nhi,$nlo,#0xf0 + and $nlo,$nlo,#0x0f + eor $Zhh,$Zhh,$Tll,lsl#16 + +.Linner: + add $Thh,$Htbl,$nlo,lsl#4 + and $nlo,$Zll,#0xf @ rem + subs $cnt,$cnt,#1 + add $nlo,$nlo,$nlo + ldmia $Thh,{$Tll-$Thh} @ load Htbl[nlo] + eor $Zll,$Tll,$Zll,lsr#4 + eor $Zll,$Zll,$Zlh,lsl#28 + eor $Zlh,$Tlh,$Zlh,lsr#4 + eor $Zlh,$Zlh,$Zhl,lsl#28 + ldrh $Tll,[sp,$nlo] @ rem_4bit[rem] + eor $Zhl,$Thl,$Zhl,lsr#4 + ldrbpl $nlo,[$inp,$cnt] + eor $Zhl,$Zhl,$Zhh,lsl#28 + eor $Zhh,$Thh,$Zhh,lsr#4 + + add $Thh,$Htbl,$nhi + and $nhi,$Zll,#0xf @ rem + eor $Zhh,$Zhh,$Tll,lsl#16 @ ^= rem_4bit[rem] + add $nhi,$nhi,$nhi + ldmia $Thh,{$Tll-$Thh} @ load Htbl[nhi] + eor $Zll,$Tll,$Zll,lsr#4 + ldrbpl $Tll,[$Xi,$cnt] + eor $Zll,$Zll,$Zlh,lsl#28 + eor $Zlh,$Tlh,$Zlh,lsr#4 + ldrh $Tlh,[sp,$nhi] + eor $Zlh,$Zlh,$Zhl,lsl#28 + eor $Zhl,$Thl,$Zhl,lsr#4 + eor $Zhl,$Zhl,$Zhh,lsl#28 + eorpl $nlo,$nlo,$Tll + eor $Zhh,$Thh,$Zhh,lsr#4 + andpl $nhi,$nlo,#0xf0 + andpl $nlo,$nlo,#0x0f + eor $Zhh,$Zhh,$Tlh,lsl#16 @ ^= rem_4bit[rem] + bpl .Linner + + ldr $len,[sp,#32] @ re-load $len/end + add $inp,$inp,#16 + mov $nhi,$Zll +___ + &Zsmash("cmp\t$inp,$len","ldrbne\t$nlo,[$inp,#15]"); +$code.=<<___; + bne .Louter + + add sp,sp,#36 +#if __ARM_ARCH__>=5 + ldmia sp!,{r4-r11,pc} +#else + ldmia sp!,{r4-r11,lr} + tst lr,#1 + moveq pc,lr @ be binary compatible with V4, yet + bx lr @ interoperable with Thumb ISA:-) +#endif +.size gcm_ghash_4bit,.-gcm_ghash_4bit + +.global gcm_gmult_4bit +.type gcm_gmult_4bit,%function +gcm_gmult_4bit: + stmdb sp!,{r4-r11,lr} + ldrb $nlo,[$Xi,#15] + b rem_4bit_get +.Lrem_4bit_got: + and $nhi,$nlo,#0xf0 + and $nlo,$nlo,#0x0f + mov $cnt,#14 + + add $Zhh,$Htbl,$nlo,lsl#4 + ldmia $Zhh,{$Zll-$Zhh} @ load Htbl[nlo] + ldrb $nlo,[$Xi,#14] + + add $Thh,$Htbl,$nhi + and $nhi,$Zll,#0xf @ rem + ldmia $Thh,{$Tll-$Thh} @ load Htbl[nhi] + add $nhi,$nhi,$nhi + eor $Zll,$Tll,$Zll,lsr#4 + ldrh $Tll,[$rem_4bit,$nhi] @ rem_4bit[rem] + eor $Zll,$Zll,$Zlh,lsl#28 + eor $Zlh,$Tlh,$Zlh,lsr#4 + eor $Zlh,$Zlh,$Zhl,lsl#28 + eor $Zhl,$Thl,$Zhl,lsr#4 + eor $Zhl,$Zhl,$Zhh,lsl#28 + eor $Zhh,$Thh,$Zhh,lsr#4 + and $nhi,$nlo,#0xf0 + eor $Zhh,$Zhh,$Tll,lsl#16 + and $nlo,$nlo,#0x0f + +.Loop: + add $Thh,$Htbl,$nlo,lsl#4 + and $nlo,$Zll,#0xf @ rem + subs $cnt,$cnt,#1 + add $nlo,$nlo,$nlo + ldmia $Thh,{$Tll-$Thh} @ load Htbl[nlo] + eor $Zll,$Tll,$Zll,lsr#4 + eor $Zll,$Zll,$Zlh,lsl#28 + eor $Zlh,$Tlh,$Zlh,lsr#4 + eor $Zlh,$Zlh,$Zhl,lsl#28 + ldrh $Tll,[$rem_4bit,$nlo] @ rem_4bit[rem] + eor $Zhl,$Thl,$Zhl,lsr#4 + ldrbpl $nlo,[$Xi,$cnt] + eor $Zhl,$Zhl,$Zhh,lsl#28 + eor $Zhh,$Thh,$Zhh,lsr#4 + + add $Thh,$Htbl,$nhi + and $nhi,$Zll,#0xf @ rem + eor $Zhh,$Zhh,$Tll,lsl#16 @ ^= rem_4bit[rem] + add $nhi,$nhi,$nhi + ldmia $Thh,{$Tll-$Thh} @ load Htbl[nhi] + eor $Zll,$Tll,$Zll,lsr#4 + eor $Zll,$Zll,$Zlh,lsl#28 + eor $Zlh,$Tlh,$Zlh,lsr#4 + ldrh $Tll,[$rem_4bit,$nhi] @ rem_4bit[rem] + eor $Zlh,$Zlh,$Zhl,lsl#28 + eor $Zhl,$Thl,$Zhl,lsr#4 + eor $Zhl,$Zhl,$Zhh,lsl#28 + eor $Zhh,$Thh,$Zhh,lsr#4 + andpl $nhi,$nlo,#0xf0 + andpl $nlo,$nlo,#0x0f + eor $Zhh,$Zhh,$Tll,lsl#16 @ ^= rem_4bit[rem] + bpl .Loop +___ + &Zsmash(); +$code.=<<___; +#if __ARM_ARCH__>=5 + ldmia sp!,{r4-r11,pc} +#else + ldmia sp!,{r4-r11,lr} + tst lr,#1 + moveq pc,lr @ be binary compatible with V4, yet + bx lr @ interoperable with Thumb ISA:-) +#endif +.size gcm_gmult_4bit,.-gcm_gmult_4bit +___ +{ +my ($Xl,$Xm,$Xh,$IN)=map("q$_",(0..3)); +my ($t0,$t1,$t2,$t3)=map("q$_",(8..12)); +my ($Hlo,$Hhi,$Hhl,$k48,$k32,$k16)=map("d$_",(26..31)); + +sub clmul64x64 { +my ($r,$a,$b)=@_; +$code.=<<___; + vext.8 $t0#lo, $a, $a, #1 @ A1 + vmull.p8 $t0, $t0#lo, $b @ F = A1*B + vext.8 $r#lo, $b, $b, #1 @ B1 + vmull.p8 $r, $a, $r#lo @ E = A*B1 + vext.8 $t1#lo, $a, $a, #2 @ A2 + vmull.p8 $t1, $t1#lo, $b @ H = A2*B + vext.8 $t3#lo, $b, $b, #2 @ B2 + vmull.p8 $t3, $a, $t3#lo @ G = A*B2 + vext.8 $t2#lo, $a, $a, #3 @ A3 + veor $t0, $t0, $r @ L = E + F + vmull.p8 $t2, $t2#lo, $b @ J = A3*B + vext.8 $r#lo, $b, $b, #3 @ B3 + veor $t1, $t1, $t3 @ M = G + H + vmull.p8 $r, $a, $r#lo @ I = A*B3 + veor $t0#lo, $t0#lo, $t0#hi @ t0 = (L) (P0 + P1) << 8 + vand $t0#hi, $t0#hi, $k48 + vext.8 $t3#lo, $b, $b, #4 @ B4 + veor $t1#lo, $t1#lo, $t1#hi @ t1 = (M) (P2 + P3) << 16 + vand $t1#hi, $t1#hi, $k32 + vmull.p8 $t3, $a, $t3#lo @ K = A*B4 + veor $t2, $t2, $r @ N = I + J + veor $t0#lo, $t0#lo, $t0#hi + veor $t1#lo, $t1#lo, $t1#hi + veor $t2#lo, $t2#lo, $t2#hi @ t2 = (N) (P4 + P5) << 24 + vand $t2#hi, $t2#hi, $k16 + vext.8 $t0, $t0, $t0, #15 + veor $t3#lo, $t3#lo, $t3#hi @ t3 = (K) (P6 + P7) << 32 + vmov.i64 $t3#hi, #0 + vext.8 $t1, $t1, $t1, #14 + veor $t2#lo, $t2#lo, $t2#hi + vmull.p8 $r, $a, $b @ D = A*B + vext.8 $t3, $t3, $t3, #12 + vext.8 $t2, $t2, $t2, #13 + veor $t0, $t0, $t1 + veor $t2, $t2, $t3 + veor $r, $r, $t0 + veor $r, $r, $t2 +___ +} + +$code.=<<___; +#if __ARM_MAX_ARCH__>=7 +.arch armv7-a +.fpu neon + +.global gcm_init_neon +.type gcm_init_neon,%function +.align 4 +gcm_init_neon: + vld1.64 $IN#hi,[r1]! @ load H + vmov.i8 $t0,#0xe1 + vld1.64 $IN#lo,[r1] + vshl.i64 $t0#hi,#57 + vshr.u64 $t0#lo,#63 @ t0=0xc2....01 + vdup.8 $t1,$IN#hi[7] + vshr.u64 $Hlo,$IN#lo,#63 + vshr.s8 $t1,#7 @ broadcast carry bit + vshl.i64 $IN,$IN,#1 + vand $t0,$t0,$t1 + vorr $IN#hi,$Hlo @ H<<<=1 + veor $IN,$IN,$t0 @ twisted H + vstmia r0,{$IN} + + ret @ bx lr +.size gcm_init_neon,.-gcm_init_neon + +.global gcm_gmult_neon +.type gcm_gmult_neon,%function +.align 4 +gcm_gmult_neon: + vld1.64 $IN#hi,[$Xi]! @ load Xi + vld1.64 $IN#lo,[$Xi]! + vmov.i64 $k48,#0x0000ffffffffffff + vldmia $Htbl,{$Hlo-$Hhi} @ load twisted H + vmov.i64 $k32,#0x00000000ffffffff +#ifdef __ARMEL__ + vrev64.8 $IN,$IN +#endif + vmov.i64 $k16,#0x000000000000ffff + veor $Hhl,$Hlo,$Hhi @ Karatsuba pre-processing + mov $len,#16 + b .Lgmult_neon +.size gcm_gmult_neon,.-gcm_gmult_neon + +.global gcm_ghash_neon +.type gcm_ghash_neon,%function +.align 4 +gcm_ghash_neon: + vld1.64 $Xl#hi,[$Xi]! @ load Xi + vld1.64 $Xl#lo,[$Xi]! + vmov.i64 $k48,#0x0000ffffffffffff + vldmia $Htbl,{$Hlo-$Hhi} @ load twisted H + vmov.i64 $k32,#0x00000000ffffffff +#ifdef __ARMEL__ + vrev64.8 $Xl,$Xl +#endif + vmov.i64 $k16,#0x000000000000ffff + veor $Hhl,$Hlo,$Hhi @ Karatsuba pre-processing + +.Loop_neon: + vld1.64 $IN#hi,[$inp]! @ load inp + vld1.64 $IN#lo,[$inp]! +#ifdef __ARMEL__ + vrev64.8 $IN,$IN +#endif + veor $IN,$Xl @ inp^=Xi +.Lgmult_neon: +___ + &clmul64x64 ($Xl,$Hlo,"$IN#lo"); # H.lo·Xi.lo +$code.=<<___; + veor $IN#lo,$IN#lo,$IN#hi @ Karatsuba pre-processing +___ + &clmul64x64 ($Xm,$Hhl,"$IN#lo"); # (H.lo+H.hi)·(Xi.lo+Xi.hi) + &clmul64x64 ($Xh,$Hhi,"$IN#hi"); # H.hi·Xi.hi +$code.=<<___; + veor $Xm,$Xm,$Xl @ Karatsuba post-processing + veor $Xm,$Xm,$Xh + veor $Xl#hi,$Xl#hi,$Xm#lo + veor $Xh#lo,$Xh#lo,$Xm#hi @ Xh|Xl - 256-bit result + + @ equivalent of reduction_avx from ghash-x86_64.pl + vshl.i64 $t1,$Xl,#57 @ 1st phase + vshl.i64 $t2,$Xl,#62 + veor $t2,$t2,$t1 @ + vshl.i64 $t1,$Xl,#63 + veor $t2, $t2, $t1 @ + veor $Xl#hi,$Xl#hi,$t2#lo @ + veor $Xh#lo,$Xh#lo,$t2#hi + + vshr.u64 $t2,$Xl,#1 @ 2nd phase + veor $Xh,$Xh,$Xl + veor $Xl,$Xl,$t2 @ + vshr.u64 $t2,$t2,#6 + vshr.u64 $Xl,$Xl,#1 @ + veor $Xl,$Xl,$Xh @ + veor $Xl,$Xl,$t2 @ + + subs $len,#16 + bne .Loop_neon + +#ifdef __ARMEL__ + vrev64.8 $Xl,$Xl +#endif + sub $Xi,#16 + vst1.64 $Xl#hi,[$Xi]! @ write out Xi + vst1.64 $Xl#lo,[$Xi] + + ret @ bx lr +.size gcm_ghash_neon,.-gcm_ghash_neon +#endif +___ +} +$code.=<<___; +.asciz "GHASH for ARMv4/NEON, CRYPTOGAMS by " +.align 2 +___ + +foreach (split("\n",$code)) { + s/\`([^\`]*)\`/eval $1/geo; + + s/\bq([0-9]+)#(lo|hi)/sprintf "d%d",2*$1+($2 eq "hi")/geo or + s/\bret\b/bx lr/go or + s/\bbx\s+lr\b/.word\t0xe12fff1e/go; # make it possible to compile with -march=armv4 + + print $_,"\n"; +} +close STDOUT; # enforce flush diff --git a/external/boringssl/crypto/modes/asm/ghash-x86.pl b/external/boringssl/crypto/modes/asm/ghash-x86.pl new file mode 100644 index 0000000000..0269169fa7 --- /dev/null +++ b/external/boringssl/crypto/modes/asm/ghash-x86.pl @@ -0,0 +1,1393 @@ +#!/usr/bin/env perl +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# March, May, June 2010 +# +# The module implements "4-bit" GCM GHASH function and underlying +# single multiplication operation in GF(2^128). "4-bit" means that it +# uses 256 bytes per-key table [+64/128 bytes fixed table]. It has two +# code paths: vanilla x86 and vanilla SSE. Former will be executed on +# 486 and Pentium, latter on all others. SSE GHASH features so called +# "528B" variant of "4-bit" method utilizing additional 256+16 bytes +# of per-key storage [+512 bytes shared table]. Performance results +# are for streamed GHASH subroutine and are expressed in cycles per +# processed byte, less is better: +# +# gcc 2.95.3(*) SSE assembler x86 assembler +# +# Pentium 105/111(**) - 50 +# PIII 68 /75 12.2 24 +# P4 125/125 17.8 84(***) +# Opteron 66 /70 10.1 30 +# Core2 54 /67 8.4 18 +# Atom 105/105 16.8 53 +# VIA Nano 69 /71 13.0 27 +# +# (*) gcc 3.4.x was observed to generate few percent slower code, +# which is one of reasons why 2.95.3 results were chosen, +# another reason is lack of 3.4.x results for older CPUs; +# comparison with SSE results is not completely fair, because C +# results are for vanilla "256B" implementation, while +# assembler results are for "528B";-) +# (**) second number is result for code compiled with -fPIC flag, +# which is actually more relevant, because assembler code is +# position-independent; +# (***) see comment in non-MMX routine for further details; +# +# To summarize, it's >2-5 times faster than gcc-generated code. To +# anchor it to something else SHA1 assembler processes one byte in +# ~7 cycles on contemporary x86 cores. As for choice of MMX/SSE +# in particular, see comment at the end of the file... + +# May 2010 +# +# Add PCLMULQDQ version performing at 2.10 cycles per processed byte. +# The question is how close is it to theoretical limit? The pclmulqdq +# instruction latency appears to be 14 cycles and there can't be more +# than 2 of them executing at any given time. This means that single +# Karatsuba multiplication would take 28 cycles *plus* few cycles for +# pre- and post-processing. Then multiplication has to be followed by +# modulo-reduction. Given that aggregated reduction method [see +# "Carry-less Multiplication and Its Usage for Computing the GCM Mode" +# white paper by Intel] allows you to perform reduction only once in +# a while we can assume that asymptotic performance can be estimated +# as (28+Tmod/Naggr)/16, where Tmod is time to perform reduction +# and Naggr is the aggregation factor. +# +# Before we proceed to this implementation let's have closer look at +# the best-performing code suggested by Intel in their white paper. +# By tracing inter-register dependencies Tmod is estimated as ~19 +# cycles and Naggr chosen by Intel is 4, resulting in 2.05 cycles per +# processed byte. As implied, this is quite optimistic estimate, +# because it does not account for Karatsuba pre- and post-processing, +# which for a single multiplication is ~5 cycles. Unfortunately Intel +# does not provide performance data for GHASH alone. But benchmarking +# AES_GCM_encrypt ripped out of Fig. 15 of the white paper with aadt +# alone resulted in 2.46 cycles per byte of out 16KB buffer. Note that +# the result accounts even for pre-computing of degrees of the hash +# key H, but its portion is negligible at 16KB buffer size. +# +# Moving on to the implementation in question. Tmod is estimated as +# ~13 cycles and Naggr is 2, giving asymptotic performance of ... +# 2.16. How is it possible that measured performance is better than +# optimistic theoretical estimate? There is one thing Intel failed +# to recognize. By serializing GHASH with CTR in same subroutine +# former's performance is really limited to above (Tmul + Tmod/Naggr) +# equation. But if GHASH procedure is detached, the modulo-reduction +# can be interleaved with Naggr-1 multiplications at instruction level +# and under ideal conditions even disappear from the equation. So that +# optimistic theoretical estimate for this implementation is ... +# 28/16=1.75, and not 2.16. Well, it's probably way too optimistic, +# at least for such small Naggr. I'd argue that (28+Tproc/Naggr), +# where Tproc is time required for Karatsuba pre- and post-processing, +# is more realistic estimate. In this case it gives ... 1.91 cycles. +# Or in other words, depending on how well we can interleave reduction +# and one of the two multiplications the performance should be betwen +# 1.91 and 2.16. As already mentioned, this implementation processes +# one byte out of 8KB buffer in 2.10 cycles, while x86_64 counterpart +# - in 2.02. x86_64 performance is better, because larger register +# bank allows to interleave reduction and multiplication better. +# +# Does it make sense to increase Naggr? To start with it's virtually +# impossible in 32-bit mode, because of limited register bank +# capacity. Otherwise improvement has to be weighed agiainst slower +# setup, as well as code size and complexity increase. As even +# optimistic estimate doesn't promise 30% performance improvement, +# there are currently no plans to increase Naggr. +# +# Special thanks to David Woodhouse for +# providing access to a Westmere-based system on behalf of Intel +# Open Source Technology Centre. + +# January 2010 +# +# Tweaked to optimize transitions between integer and FP operations +# on same XMM register, PCLMULQDQ subroutine was measured to process +# one byte in 2.07 cycles on Sandy Bridge, and in 2.12 - on Westmere. +# The minor regression on Westmere is outweighed by ~15% improvement +# on Sandy Bridge. Strangely enough attempt to modify 64-bit code in +# similar manner resulted in almost 20% degradation on Sandy Bridge, +# where original 64-bit code processes one byte in 1.95 cycles. + +##################################################################### +# For reference, AMD Bulldozer processes one byte in 1.98 cycles in +# 32-bit mode and 1.89 in 64-bit. + +# February 2013 +# +# Overhaul: aggregate Karatsuba post-processing, improve ILP in +# reduction_alg9. Resulting performance is 1.96 cycles per byte on +# Westmere, 1.95 - on Sandy/Ivy Bridge, 1.76 - on Bulldozer. + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +push(@INC,"${dir}","${dir}../../perlasm"); +require "x86asm.pl"; + +&asm_init($ARGV[0],"ghash-x86.pl",$x86only = $ARGV[$#ARGV] eq "386"); + +$sse2=0; +for (@ARGV) { $sse2=1 if (/-DOPENSSL_IA32_SSE2/); } + +($Zhh,$Zhl,$Zlh,$Zll) = ("ebp","edx","ecx","ebx"); +$inp = "edi"; +$Htbl = "esi"; + +$unroll = 0; # Affects x86 loop. Folded loop performs ~7% worse + # than unrolled, which has to be weighted against + # 2.5x x86-specific code size reduction. + +sub x86_loop { + my $off = shift; + my $rem = "eax"; + + &mov ($Zhh,&DWP(4,$Htbl,$Zll)); + &mov ($Zhl,&DWP(0,$Htbl,$Zll)); + &mov ($Zlh,&DWP(12,$Htbl,$Zll)); + &mov ($Zll,&DWP(8,$Htbl,$Zll)); + &xor ($rem,$rem); # avoid partial register stalls on PIII + + # shrd practically kills P4, 2.5x deterioration, but P4 has + # MMX code-path to execute. shrd runs tad faster [than twice + # the shifts, move's and or's] on pre-MMX Pentium (as well as + # PIII and Core2), *but* minimizes code size, spares register + # and thus allows to fold the loop... + if (!$unroll) { + my $cnt = $inp; + &mov ($cnt,15); + &jmp (&label("x86_loop")); + &set_label("x86_loop",16); + for($i=1;$i<=2;$i++) { + &mov (&LB($rem),&LB($Zll)); + &shrd ($Zll,$Zlh,4); + &and (&LB($rem),0xf); + &shrd ($Zlh,$Zhl,4); + &shrd ($Zhl,$Zhh,4); + &shr ($Zhh,4); + &xor ($Zhh,&DWP($off+16,"esp",$rem,4)); + + &mov (&LB($rem),&BP($off,"esp",$cnt)); + if ($i&1) { + &and (&LB($rem),0xf0); + } else { + &shl (&LB($rem),4); + } + + &xor ($Zll,&DWP(8,$Htbl,$rem)); + &xor ($Zlh,&DWP(12,$Htbl,$rem)); + &xor ($Zhl,&DWP(0,$Htbl,$rem)); + &xor ($Zhh,&DWP(4,$Htbl,$rem)); + + if ($i&1) { + &dec ($cnt); + &js (&label("x86_break")); + } else { + &jmp (&label("x86_loop")); + } + } + &set_label("x86_break",16); + } else { + for($i=1;$i<32;$i++) { + &comment($i); + &mov (&LB($rem),&LB($Zll)); + &shrd ($Zll,$Zlh,4); + &and (&LB($rem),0xf); + &shrd ($Zlh,$Zhl,4); + &shrd ($Zhl,$Zhh,4); + &shr ($Zhh,4); + &xor ($Zhh,&DWP($off+16,"esp",$rem,4)); + + if ($i&1) { + &mov (&LB($rem),&BP($off+15-($i>>1),"esp")); + &and (&LB($rem),0xf0); + } else { + &mov (&LB($rem),&BP($off+15-($i>>1),"esp")); + &shl (&LB($rem),4); + } + + &xor ($Zll,&DWP(8,$Htbl,$rem)); + &xor ($Zlh,&DWP(12,$Htbl,$rem)); + &xor ($Zhl,&DWP(0,$Htbl,$rem)); + &xor ($Zhh,&DWP(4,$Htbl,$rem)); + } + } + &bswap ($Zll); + &bswap ($Zlh); + &bswap ($Zhl); + if (!$x86only) { + &bswap ($Zhh); + } else { + &mov ("eax",$Zhh); + &bswap ("eax"); + &mov ($Zhh,"eax"); + } +} + +if ($unroll) { + &function_begin_B("_x86_gmult_4bit_inner"); + &x86_loop(4); + &ret (); + &function_end_B("_x86_gmult_4bit_inner"); +} + +sub deposit_rem_4bit { + my $bias = shift; + + &mov (&DWP($bias+0, "esp"),0x0000<<16); + &mov (&DWP($bias+4, "esp"),0x1C20<<16); + &mov (&DWP($bias+8, "esp"),0x3840<<16); + &mov (&DWP($bias+12,"esp"),0x2460<<16); + &mov (&DWP($bias+16,"esp"),0x7080<<16); + &mov (&DWP($bias+20,"esp"),0x6CA0<<16); + &mov (&DWP($bias+24,"esp"),0x48C0<<16); + &mov (&DWP($bias+28,"esp"),0x54E0<<16); + &mov (&DWP($bias+32,"esp"),0xE100<<16); + &mov (&DWP($bias+36,"esp"),0xFD20<<16); + &mov (&DWP($bias+40,"esp"),0xD940<<16); + &mov (&DWP($bias+44,"esp"),0xC560<<16); + &mov (&DWP($bias+48,"esp"),0x9180<<16); + &mov (&DWP($bias+52,"esp"),0x8DA0<<16); + &mov (&DWP($bias+56,"esp"),0xA9C0<<16); + &mov (&DWP($bias+60,"esp"),0xB5E0<<16); +} + +$suffix = $x86only ? "" : "_x86"; + +&function_begin("gcm_gmult_4bit".$suffix); + &stack_push(16+4+1); # +1 for stack alignment + &mov ($inp,&wparam(0)); # load Xi + &mov ($Htbl,&wparam(1)); # load Htable + + &mov ($Zhh,&DWP(0,$inp)); # load Xi[16] + &mov ($Zhl,&DWP(4,$inp)); + &mov ($Zlh,&DWP(8,$inp)); + &mov ($Zll,&DWP(12,$inp)); + + &deposit_rem_4bit(16); + + &mov (&DWP(0,"esp"),$Zhh); # copy Xi[16] on stack + &mov (&DWP(4,"esp"),$Zhl); + &mov (&DWP(8,"esp"),$Zlh); + &mov (&DWP(12,"esp"),$Zll); + &shr ($Zll,20); + &and ($Zll,0xf0); + + if ($unroll) { + &call ("_x86_gmult_4bit_inner"); + } else { + &x86_loop(0); + &mov ($inp,&wparam(0)); + } + + &mov (&DWP(12,$inp),$Zll); + &mov (&DWP(8,$inp),$Zlh); + &mov (&DWP(4,$inp),$Zhl); + &mov (&DWP(0,$inp),$Zhh); + &stack_pop(16+4+1); +&function_end("gcm_gmult_4bit".$suffix); + +&function_begin("gcm_ghash_4bit".$suffix); + &stack_push(16+4+1); # +1 for 64-bit alignment + &mov ($Zll,&wparam(0)); # load Xi + &mov ($Htbl,&wparam(1)); # load Htable + &mov ($inp,&wparam(2)); # load in + &mov ("ecx",&wparam(3)); # load len + &add ("ecx",$inp); + &mov (&wparam(3),"ecx"); + + &mov ($Zhh,&DWP(0,$Zll)); # load Xi[16] + &mov ($Zhl,&DWP(4,$Zll)); + &mov ($Zlh,&DWP(8,$Zll)); + &mov ($Zll,&DWP(12,$Zll)); + + &deposit_rem_4bit(16); + + &set_label("x86_outer_loop",16); + &xor ($Zll,&DWP(12,$inp)); # xor with input + &xor ($Zlh,&DWP(8,$inp)); + &xor ($Zhl,&DWP(4,$inp)); + &xor ($Zhh,&DWP(0,$inp)); + &mov (&DWP(12,"esp"),$Zll); # dump it on stack + &mov (&DWP(8,"esp"),$Zlh); + &mov (&DWP(4,"esp"),$Zhl); + &mov (&DWP(0,"esp"),$Zhh); + + &shr ($Zll,20); + &and ($Zll,0xf0); + + if ($unroll) { + &call ("_x86_gmult_4bit_inner"); + } else { + &x86_loop(0); + &mov ($inp,&wparam(2)); + } + &lea ($inp,&DWP(16,$inp)); + &cmp ($inp,&wparam(3)); + &mov (&wparam(2),$inp) if (!$unroll); + &jb (&label("x86_outer_loop")); + + &mov ($inp,&wparam(0)); # load Xi + &mov (&DWP(12,$inp),$Zll); + &mov (&DWP(8,$inp),$Zlh); + &mov (&DWP(4,$inp),$Zhl); + &mov (&DWP(0,$inp),$Zhh); + &stack_pop(16+4+1); +&function_end("gcm_ghash_4bit".$suffix); + +if (!$x86only) {{{ + +&static_label("rem_4bit"); + +if (!$sse2) {{ # pure-MMX "May" version... + +$S=12; # shift factor for rem_4bit + +&function_begin_B("_mmx_gmult_4bit_inner"); +# MMX version performs 3.5 times better on P4 (see comment in non-MMX +# routine for further details), 100% better on Opteron, ~70% better +# on Core2 and PIII... In other words effort is considered to be well +# spent... Since initial release the loop was unrolled in order to +# "liberate" register previously used as loop counter. Instead it's +# used to optimize critical path in 'Z.hi ^= rem_4bit[Z.lo&0xf]'. +# The path involves move of Z.lo from MMX to integer register, +# effective address calculation and finally merge of value to Z.hi. +# Reference to rem_4bit is scheduled so late that I had to >>4 +# rem_4bit elements. This resulted in 20-45% procent improvement +# on contemporary µ-archs. +{ + my $cnt; + my $rem_4bit = "eax"; + my @rem = ($Zhh,$Zll); + my $nhi = $Zhl; + my $nlo = $Zlh; + + my ($Zlo,$Zhi) = ("mm0","mm1"); + my $tmp = "mm2"; + + &xor ($nlo,$nlo); # avoid partial register stalls on PIII + &mov ($nhi,$Zll); + &mov (&LB($nlo),&LB($nhi)); + &shl (&LB($nlo),4); + &and ($nhi,0xf0); + &movq ($Zlo,&QWP(8,$Htbl,$nlo)); + &movq ($Zhi,&QWP(0,$Htbl,$nlo)); + &movd ($rem[0],$Zlo); + + for ($cnt=28;$cnt>=-2;$cnt--) { + my $odd = $cnt&1; + my $nix = $odd ? $nlo : $nhi; + + &shl (&LB($nlo),4) if ($odd); + &psrlq ($Zlo,4); + &movq ($tmp,$Zhi); + &psrlq ($Zhi,4); + &pxor ($Zlo,&QWP(8,$Htbl,$nix)); + &mov (&LB($nlo),&BP($cnt/2,$inp)) if (!$odd && $cnt>=0); + &psllq ($tmp,60); + &and ($nhi,0xf0) if ($odd); + &pxor ($Zhi,&QWP(0,$rem_4bit,$rem[1],8)) if ($cnt<28); + &and ($rem[0],0xf); + &pxor ($Zhi,&QWP(0,$Htbl,$nix)); + &mov ($nhi,$nlo) if (!$odd && $cnt>=0); + &movd ($rem[1],$Zlo); + &pxor ($Zlo,$tmp); + + push (@rem,shift(@rem)); # "rotate" registers + } + + &mov ($inp,&DWP(4,$rem_4bit,$rem[1],8)); # last rem_4bit[rem] + + &psrlq ($Zlo,32); # lower part of Zlo is already there + &movd ($Zhl,$Zhi); + &psrlq ($Zhi,32); + &movd ($Zlh,$Zlo); + &movd ($Zhh,$Zhi); + &shl ($inp,4); # compensate for rem_4bit[i] being >>4 + + &bswap ($Zll); + &bswap ($Zhl); + &bswap ($Zlh); + &xor ($Zhh,$inp); + &bswap ($Zhh); + + &ret (); +} +&function_end_B("_mmx_gmult_4bit_inner"); + +&function_begin("gcm_gmult_4bit_mmx"); + &mov ($inp,&wparam(0)); # load Xi + &mov ($Htbl,&wparam(1)); # load Htable + + &call (&label("pic_point")); + &set_label("pic_point"); + &blindpop("eax"); + &lea ("eax",&DWP(&label("rem_4bit")."-".&label("pic_point"),"eax")); + + &movz ($Zll,&BP(15,$inp)); + + &call ("_mmx_gmult_4bit_inner"); + + &mov ($inp,&wparam(0)); # load Xi + &emms (); + &mov (&DWP(12,$inp),$Zll); + &mov (&DWP(4,$inp),$Zhl); + &mov (&DWP(8,$inp),$Zlh); + &mov (&DWP(0,$inp),$Zhh); +&function_end("gcm_gmult_4bit_mmx"); + +# Streamed version performs 20% better on P4, 7% on Opteron, +# 10% on Core2 and PIII... +&function_begin("gcm_ghash_4bit_mmx"); + &mov ($Zhh,&wparam(0)); # load Xi + &mov ($Htbl,&wparam(1)); # load Htable + &mov ($inp,&wparam(2)); # load in + &mov ($Zlh,&wparam(3)); # load len + + &call (&label("pic_point")); + &set_label("pic_point"); + &blindpop("eax"); + &lea ("eax",&DWP(&label("rem_4bit")."-".&label("pic_point"),"eax")); + + &add ($Zlh,$inp); + &mov (&wparam(3),$Zlh); # len to point at the end of input + &stack_push(4+1); # +1 for stack alignment + + &mov ($Zll,&DWP(12,$Zhh)); # load Xi[16] + &mov ($Zhl,&DWP(4,$Zhh)); + &mov ($Zlh,&DWP(8,$Zhh)); + &mov ($Zhh,&DWP(0,$Zhh)); + &jmp (&label("mmx_outer_loop")); + + &set_label("mmx_outer_loop",16); + &xor ($Zll,&DWP(12,$inp)); + &xor ($Zhl,&DWP(4,$inp)); + &xor ($Zlh,&DWP(8,$inp)); + &xor ($Zhh,&DWP(0,$inp)); + &mov (&wparam(2),$inp); + &mov (&DWP(12,"esp"),$Zll); + &mov (&DWP(4,"esp"),$Zhl); + &mov (&DWP(8,"esp"),$Zlh); + &mov (&DWP(0,"esp"),$Zhh); + + &mov ($inp,"esp"); + &shr ($Zll,24); + + &call ("_mmx_gmult_4bit_inner"); + + &mov ($inp,&wparam(2)); + &lea ($inp,&DWP(16,$inp)); + &cmp ($inp,&wparam(3)); + &jb (&label("mmx_outer_loop")); + + &mov ($inp,&wparam(0)); # load Xi + &emms (); + &mov (&DWP(12,$inp),$Zll); + &mov (&DWP(4,$inp),$Zhl); + &mov (&DWP(8,$inp),$Zlh); + &mov (&DWP(0,$inp),$Zhh); + + &stack_pop(4+1); +&function_end("gcm_ghash_4bit_mmx"); + +}} else {{ # "June" MMX version... + # ... has slower "April" gcm_gmult_4bit_mmx with folded + # loop. This is done to conserve code size... +$S=16; # shift factor for rem_4bit + +sub mmx_loop() { +# MMX version performs 2.8 times better on P4 (see comment in non-MMX +# routine for further details), 40% better on Opteron and Core2, 50% +# better on PIII... In other words effort is considered to be well +# spent... + my $inp = shift; + my $rem_4bit = shift; + my $cnt = $Zhh; + my $nhi = $Zhl; + my $nlo = $Zlh; + my $rem = $Zll; + + my ($Zlo,$Zhi) = ("mm0","mm1"); + my $tmp = "mm2"; + + &xor ($nlo,$nlo); # avoid partial register stalls on PIII + &mov ($nhi,$Zll); + &mov (&LB($nlo),&LB($nhi)); + &mov ($cnt,14); + &shl (&LB($nlo),4); + &and ($nhi,0xf0); + &movq ($Zlo,&QWP(8,$Htbl,$nlo)); + &movq ($Zhi,&QWP(0,$Htbl,$nlo)); + &movd ($rem,$Zlo); + &jmp (&label("mmx_loop")); + + &set_label("mmx_loop",16); + &psrlq ($Zlo,4); + &and ($rem,0xf); + &movq ($tmp,$Zhi); + &psrlq ($Zhi,4); + &pxor ($Zlo,&QWP(8,$Htbl,$nhi)); + &mov (&LB($nlo),&BP(0,$inp,$cnt)); + &psllq ($tmp,60); + &pxor ($Zhi,&QWP(0,$rem_4bit,$rem,8)); + &dec ($cnt); + &movd ($rem,$Zlo); + &pxor ($Zhi,&QWP(0,$Htbl,$nhi)); + &mov ($nhi,$nlo); + &pxor ($Zlo,$tmp); + &js (&label("mmx_break")); + + &shl (&LB($nlo),4); + &and ($rem,0xf); + &psrlq ($Zlo,4); + &and ($nhi,0xf0); + &movq ($tmp,$Zhi); + &psrlq ($Zhi,4); + &pxor ($Zlo,&QWP(8,$Htbl,$nlo)); + &psllq ($tmp,60); + &pxor ($Zhi,&QWP(0,$rem_4bit,$rem,8)); + &movd ($rem,$Zlo); + &pxor ($Zhi,&QWP(0,$Htbl,$nlo)); + &pxor ($Zlo,$tmp); + &jmp (&label("mmx_loop")); + + &set_label("mmx_break",16); + &shl (&LB($nlo),4); + &and ($rem,0xf); + &psrlq ($Zlo,4); + &and ($nhi,0xf0); + &movq ($tmp,$Zhi); + &psrlq ($Zhi,4); + &pxor ($Zlo,&QWP(8,$Htbl,$nlo)); + &psllq ($tmp,60); + &pxor ($Zhi,&QWP(0,$rem_4bit,$rem,8)); + &movd ($rem,$Zlo); + &pxor ($Zhi,&QWP(0,$Htbl,$nlo)); + &pxor ($Zlo,$tmp); + + &psrlq ($Zlo,4); + &and ($rem,0xf); + &movq ($tmp,$Zhi); + &psrlq ($Zhi,4); + &pxor ($Zlo,&QWP(8,$Htbl,$nhi)); + &psllq ($tmp,60); + &pxor ($Zhi,&QWP(0,$rem_4bit,$rem,8)); + &movd ($rem,$Zlo); + &pxor ($Zhi,&QWP(0,$Htbl,$nhi)); + &pxor ($Zlo,$tmp); + + &psrlq ($Zlo,32); # lower part of Zlo is already there + &movd ($Zhl,$Zhi); + &psrlq ($Zhi,32); + &movd ($Zlh,$Zlo); + &movd ($Zhh,$Zhi); + + &bswap ($Zll); + &bswap ($Zhl); + &bswap ($Zlh); + &bswap ($Zhh); +} + +&function_begin("gcm_gmult_4bit_mmx"); + &mov ($inp,&wparam(0)); # load Xi + &mov ($Htbl,&wparam(1)); # load Htable + + &call (&label("pic_point")); + &set_label("pic_point"); + &blindpop("eax"); + &lea ("eax",&DWP(&label("rem_4bit")."-".&label("pic_point"),"eax")); + + &movz ($Zll,&BP(15,$inp)); + + &mmx_loop($inp,"eax"); + + &emms (); + &mov (&DWP(12,$inp),$Zll); + &mov (&DWP(4,$inp),$Zhl); + &mov (&DWP(8,$inp),$Zlh); + &mov (&DWP(0,$inp),$Zhh); +&function_end("gcm_gmult_4bit_mmx"); + +###################################################################### +# Below subroutine is "528B" variant of "4-bit" GCM GHASH function +# (see gcm128.c for details). It provides further 20-40% performance +# improvement over above mentioned "May" version. + +&static_label("rem_8bit"); + +&function_begin("gcm_ghash_4bit_mmx"); +{ my ($Zlo,$Zhi) = ("mm7","mm6"); + my $rem_8bit = "esi"; + my $Htbl = "ebx"; + + # parameter block + &mov ("eax",&wparam(0)); # Xi + &mov ("ebx",&wparam(1)); # Htable + &mov ("ecx",&wparam(2)); # inp + &mov ("edx",&wparam(3)); # len + &mov ("ebp","esp"); # original %esp + &call (&label("pic_point")); + &set_label ("pic_point"); + &blindpop ($rem_8bit); + &lea ($rem_8bit,&DWP(&label("rem_8bit")."-".&label("pic_point"),$rem_8bit)); + + &sub ("esp",512+16+16); # allocate stack frame... + &and ("esp",-64); # ...and align it + &sub ("esp",16); # place for (u8)(H[]<<4) + + &add ("edx","ecx"); # pointer to the end of input + &mov (&DWP(528+16+0,"esp"),"eax"); # save Xi + &mov (&DWP(528+16+8,"esp"),"edx"); # save inp+len + &mov (&DWP(528+16+12,"esp"),"ebp"); # save original %esp + + { my @lo = ("mm0","mm1","mm2"); + my @hi = ("mm3","mm4","mm5"); + my @tmp = ("mm6","mm7"); + my ($off1,$off2,$i) = (0,0,); + + &add ($Htbl,128); # optimize for size + &lea ("edi",&DWP(16+128,"esp")); + &lea ("ebp",&DWP(16+256+128,"esp")); + + # decompose Htable (low and high parts are kept separately), + # generate Htable[]>>4, (u8)(Htable[]<<4), save to stack... + for ($i=0;$i<18;$i++) { + + &mov ("edx",&DWP(16*$i+8-128,$Htbl)) if ($i<16); + &movq ($lo[0],&QWP(16*$i+8-128,$Htbl)) if ($i<16); + &psllq ($tmp[1],60) if ($i>1); + &movq ($hi[0],&QWP(16*$i+0-128,$Htbl)) if ($i<16); + &por ($lo[2],$tmp[1]) if ($i>1); + &movq (&QWP($off1-128,"edi"),$lo[1]) if ($i>0 && $i<17); + &psrlq ($lo[1],4) if ($i>0 && $i<17); + &movq (&QWP($off1,"edi"),$hi[1]) if ($i>0 && $i<17); + &movq ($tmp[0],$hi[1]) if ($i>0 && $i<17); + &movq (&QWP($off2-128,"ebp"),$lo[2]) if ($i>1); + &psrlq ($hi[1],4) if ($i>0 && $i<17); + &movq (&QWP($off2,"ebp"),$hi[2]) if ($i>1); + &shl ("edx",4) if ($i<16); + &mov (&BP($i,"esp"),&LB("edx")) if ($i<16); + + unshift (@lo,pop(@lo)); # "rotate" registers + unshift (@hi,pop(@hi)); + unshift (@tmp,pop(@tmp)); + $off1 += 8 if ($i>0); + $off2 += 8 if ($i>1); + } + } + + &movq ($Zhi,&QWP(0,"eax")); + &mov ("ebx",&DWP(8,"eax")); + &mov ("edx",&DWP(12,"eax")); # load Xi + +&set_label("outer",16); + { my $nlo = "eax"; + my $dat = "edx"; + my @nhi = ("edi","ebp"); + my @rem = ("ebx","ecx"); + my @red = ("mm0","mm1","mm2"); + my $tmp = "mm3"; + + &xor ($dat,&DWP(12,"ecx")); # merge input data + &xor ("ebx",&DWP(8,"ecx")); + &pxor ($Zhi,&QWP(0,"ecx")); + &lea ("ecx",&DWP(16,"ecx")); # inp+=16 + #&mov (&DWP(528+12,"esp"),$dat); # save inp^Xi + &mov (&DWP(528+8,"esp"),"ebx"); + &movq (&QWP(528+0,"esp"),$Zhi); + &mov (&DWP(528+16+4,"esp"),"ecx"); # save inp + + &xor ($nlo,$nlo); + &rol ($dat,8); + &mov (&LB($nlo),&LB($dat)); + &mov ($nhi[1],$nlo); + &and (&LB($nlo),0x0f); + &shr ($nhi[1],4); + &pxor ($red[0],$red[0]); + &rol ($dat,8); # next byte + &pxor ($red[1],$red[1]); + &pxor ($red[2],$red[2]); + + # Just like in "May" verson modulo-schedule for critical path in + # 'Z.hi ^= rem_8bit[Z.lo&0xff^((u8)H[nhi]<<4)]<<48'. Final 'pxor' + # is scheduled so late that rem_8bit[] has to be shifted *right* + # by 16, which is why last argument to pinsrw is 2, which + # corresponds to <<32=<<48>>16... + for ($j=11,$i=0;$i<15;$i++) { + + if ($i>0) { + &pxor ($Zlo,&QWP(16,"esp",$nlo,8)); # Z^=H[nlo] + &rol ($dat,8); # next byte + &pxor ($Zhi,&QWP(16+128,"esp",$nlo,8)); + + &pxor ($Zlo,$tmp); + &pxor ($Zhi,&QWP(16+256+128,"esp",$nhi[0],8)); + &xor (&LB($rem[1]),&BP(0,"esp",$nhi[0])); # rem^(H[nhi]<<4) + } else { + &movq ($Zlo,&QWP(16,"esp",$nlo,8)); + &movq ($Zhi,&QWP(16+128,"esp",$nlo,8)); + } + + &mov (&LB($nlo),&LB($dat)); + &mov ($dat,&DWP(528+$j,"esp")) if (--$j%4==0); + + &movd ($rem[0],$Zlo); + &movz ($rem[1],&LB($rem[1])) if ($i>0); + &psrlq ($Zlo,8); # Z>>=8 + + &movq ($tmp,$Zhi); + &mov ($nhi[0],$nlo); + &psrlq ($Zhi,8); + + &pxor ($Zlo,&QWP(16+256+0,"esp",$nhi[1],8)); # Z^=H[nhi]>>4 + &and (&LB($nlo),0x0f); + &psllq ($tmp,56); + + &pxor ($Zhi,$red[1]) if ($i>1); + &shr ($nhi[0],4); + &pinsrw ($red[0],&WP(0,$rem_8bit,$rem[1],2),2) if ($i>0); + + unshift (@red,pop(@red)); # "rotate" registers + unshift (@rem,pop(@rem)); + unshift (@nhi,pop(@nhi)); + } + + &pxor ($Zlo,&QWP(16,"esp",$nlo,8)); # Z^=H[nlo] + &pxor ($Zhi,&QWP(16+128,"esp",$nlo,8)); + &xor (&LB($rem[1]),&BP(0,"esp",$nhi[0])); # rem^(H[nhi]<<4) + + &pxor ($Zlo,$tmp); + &pxor ($Zhi,&QWP(16+256+128,"esp",$nhi[0],8)); + &movz ($rem[1],&LB($rem[1])); + + &pxor ($red[2],$red[2]); # clear 2nd word + &psllq ($red[1],4); + + &movd ($rem[0],$Zlo); + &psrlq ($Zlo,4); # Z>>=4 + + &movq ($tmp,$Zhi); + &psrlq ($Zhi,4); + &shl ($rem[0],4); # rem<<4 + + &pxor ($Zlo,&QWP(16,"esp",$nhi[1],8)); # Z^=H[nhi] + &psllq ($tmp,60); + &movz ($rem[0],&LB($rem[0])); + + &pxor ($Zlo,$tmp); + &pxor ($Zhi,&QWP(16+128,"esp",$nhi[1],8)); + + &pinsrw ($red[0],&WP(0,$rem_8bit,$rem[1],2),2); + &pxor ($Zhi,$red[1]); + + &movd ($dat,$Zlo); + &pinsrw ($red[2],&WP(0,$rem_8bit,$rem[0],2),3); # last is <<48 + + &psllq ($red[0],12); # correct by <<16>>4 + &pxor ($Zhi,$red[0]); + &psrlq ($Zlo,32); + &pxor ($Zhi,$red[2]); + + &mov ("ecx",&DWP(528+16+4,"esp")); # restore inp + &movd ("ebx",$Zlo); + &movq ($tmp,$Zhi); # 01234567 + &psllw ($Zhi,8); # 1.3.5.7. + &psrlw ($tmp,8); # .0.2.4.6 + &por ($Zhi,$tmp); # 10325476 + &bswap ($dat); + &pshufw ($Zhi,$Zhi,0b00011011); # 76543210 + &bswap ("ebx"); + + &cmp ("ecx",&DWP(528+16+8,"esp")); # are we done? + &jne (&label("outer")); + } + + &mov ("eax",&DWP(528+16+0,"esp")); # restore Xi + &mov (&DWP(12,"eax"),"edx"); + &mov (&DWP(8,"eax"),"ebx"); + &movq (&QWP(0,"eax"),$Zhi); + + &mov ("esp",&DWP(528+16+12,"esp")); # restore original %esp + &emms (); +} +&function_end("gcm_ghash_4bit_mmx"); +}} + +if ($sse2) {{ +###################################################################### +# PCLMULQDQ version. + +$Xip="eax"; +$Htbl="edx"; +$const="ecx"; +$inp="esi"; +$len="ebx"; + +($Xi,$Xhi)=("xmm0","xmm1"); $Hkey="xmm2"; +($T1,$T2,$T3)=("xmm3","xmm4","xmm5"); +($Xn,$Xhn)=("xmm6","xmm7"); + +&static_label("bswap"); + +sub clmul64x64_T2 { # minimal "register" pressure +my ($Xhi,$Xi,$Hkey,$HK)=@_; + + &movdqa ($Xhi,$Xi); # + &pshufd ($T1,$Xi,0b01001110); + &pshufd ($T2,$Hkey,0b01001110) if (!defined($HK)); + &pxor ($T1,$Xi); # + &pxor ($T2,$Hkey) if (!defined($HK)); + $HK=$T2 if (!defined($HK)); + + &pclmulqdq ($Xi,$Hkey,0x00); ####### + &pclmulqdq ($Xhi,$Hkey,0x11); ####### + &pclmulqdq ($T1,$HK,0x00); ####### + &xorps ($T1,$Xi); # + &xorps ($T1,$Xhi); # + + &movdqa ($T2,$T1); # + &psrldq ($T1,8); + &pslldq ($T2,8); # + &pxor ($Xhi,$T1); + &pxor ($Xi,$T2); # +} + +sub clmul64x64_T3 { +# Even though this subroutine offers visually better ILP, it +# was empirically found to be a tad slower than above version. +# At least in gcm_ghash_clmul context. But it's just as well, +# because loop modulo-scheduling is possible only thanks to +# minimized "register" pressure... +my ($Xhi,$Xi,$Hkey)=@_; + + &movdqa ($T1,$Xi); # + &movdqa ($Xhi,$Xi); + &pclmulqdq ($Xi,$Hkey,0x00); ####### + &pclmulqdq ($Xhi,$Hkey,0x11); ####### + &pshufd ($T2,$T1,0b01001110); # + &pshufd ($T3,$Hkey,0b01001110); + &pxor ($T2,$T1); # + &pxor ($T3,$Hkey); + &pclmulqdq ($T2,$T3,0x00); ####### + &pxor ($T2,$Xi); # + &pxor ($T2,$Xhi); # + + &movdqa ($T3,$T2); # + &psrldq ($T2,8); + &pslldq ($T3,8); # + &pxor ($Xhi,$T2); + &pxor ($Xi,$T3); # +} + +if (1) { # Algorithm 9 with <<1 twist. + # Reduction is shorter and uses only two + # temporary registers, which makes it better + # candidate for interleaving with 64x64 + # multiplication. Pre-modulo-scheduled loop + # was found to be ~20% faster than Algorithm 5 + # below. Algorithm 9 was therefore chosen for + # further optimization... + +sub reduction_alg9 { # 17/11 times faster than Intel version +my ($Xhi,$Xi) = @_; + + # 1st phase + &movdqa ($T2,$Xi); # + &movdqa ($T1,$Xi); + &psllq ($Xi,5); + &pxor ($T1,$Xi); # + &psllq ($Xi,1); + &pxor ($Xi,$T1); # + &psllq ($Xi,57); # + &movdqa ($T1,$Xi); # + &pslldq ($Xi,8); + &psrldq ($T1,8); # + &pxor ($Xi,$T2); + &pxor ($Xhi,$T1); # + + # 2nd phase + &movdqa ($T2,$Xi); + &psrlq ($Xi,1); + &pxor ($Xhi,$T2); # + &pxor ($T2,$Xi); + &psrlq ($Xi,5); + &pxor ($Xi,$T2); # + &psrlq ($Xi,1); # + &pxor ($Xi,$Xhi) # +} + +&function_begin_B("gcm_init_clmul"); + &mov ($Htbl,&wparam(0)); + &mov ($Xip,&wparam(1)); + + &call (&label("pic")); +&set_label("pic"); + &blindpop ($const); + &lea ($const,&DWP(&label("bswap")."-".&label("pic"),$const)); + + &movdqu ($Hkey,&QWP(0,$Xip)); + &pshufd ($Hkey,$Hkey,0b01001110);# dword swap + + # <<1 twist + &pshufd ($T2,$Hkey,0b11111111); # broadcast uppermost dword + &movdqa ($T1,$Hkey); + &psllq ($Hkey,1); + &pxor ($T3,$T3); # + &psrlq ($T1,63); + &pcmpgtd ($T3,$T2); # broadcast carry bit + &pslldq ($T1,8); + &por ($Hkey,$T1); # H<<=1 + + # magic reduction + &pand ($T3,&QWP(16,$const)); # 0x1c2_polynomial + &pxor ($Hkey,$T3); # if(carry) H^=0x1c2_polynomial + + # calculate H^2 + &movdqa ($Xi,$Hkey); + &clmul64x64_T2 ($Xhi,$Xi,$Hkey); + &reduction_alg9 ($Xhi,$Xi); + + &pshufd ($T1,$Hkey,0b01001110); + &pshufd ($T2,$Xi,0b01001110); + &pxor ($T1,$Hkey); # Karatsuba pre-processing + &movdqu (&QWP(0,$Htbl),$Hkey); # save H + &pxor ($T2,$Xi); # Karatsuba pre-processing + &movdqu (&QWP(16,$Htbl),$Xi); # save H^2 + &palignr ($T2,$T1,8); # low part is H.lo^H.hi + &movdqu (&QWP(32,$Htbl),$T2); # save Karatsuba "salt" + + &ret (); +&function_end_B("gcm_init_clmul"); + +&function_begin_B("gcm_gmult_clmul"); + &mov ($Xip,&wparam(0)); + &mov ($Htbl,&wparam(1)); + + &call (&label("pic")); +&set_label("pic"); + &blindpop ($const); + &lea ($const,&DWP(&label("bswap")."-".&label("pic"),$const)); + + &movdqu ($Xi,&QWP(0,$Xip)); + &movdqa ($T3,&QWP(0,$const)); + &movups ($Hkey,&QWP(0,$Htbl)); + &pshufb ($Xi,$T3); + &movups ($T2,&QWP(32,$Htbl)); + + &clmul64x64_T2 ($Xhi,$Xi,$Hkey,$T2); + &reduction_alg9 ($Xhi,$Xi); + + &pshufb ($Xi,$T3); + &movdqu (&QWP(0,$Xip),$Xi); + + &ret (); +&function_end_B("gcm_gmult_clmul"); + +&function_begin("gcm_ghash_clmul"); + &mov ($Xip,&wparam(0)); + &mov ($Htbl,&wparam(1)); + &mov ($inp,&wparam(2)); + &mov ($len,&wparam(3)); + + &call (&label("pic")); +&set_label("pic"); + &blindpop ($const); + &lea ($const,&DWP(&label("bswap")."-".&label("pic"),$const)); + + &movdqu ($Xi,&QWP(0,$Xip)); + &movdqa ($T3,&QWP(0,$const)); + &movdqu ($Hkey,&QWP(0,$Htbl)); + &pshufb ($Xi,$T3); + + &sub ($len,0x10); + &jz (&label("odd_tail")); + + ####### + # Xi+2 =[H*(Ii+1 + Xi+1)] mod P = + # [(H*Ii+1) + (H*Xi+1)] mod P = + # [(H*Ii+1) + H^2*(Ii+Xi)] mod P + # + &movdqu ($T1,&QWP(0,$inp)); # Ii + &movdqu ($Xn,&QWP(16,$inp)); # Ii+1 + &pshufb ($T1,$T3); + &pshufb ($Xn,$T3); + &movdqu ($T3,&QWP(32,$Htbl)); + &pxor ($Xi,$T1); # Ii+Xi + + &pshufd ($T1,$Xn,0b01001110); # H*Ii+1 + &movdqa ($Xhn,$Xn); + &pxor ($T1,$Xn); # + &lea ($inp,&DWP(32,$inp)); # i+=2 + + &pclmulqdq ($Xn,$Hkey,0x00); ####### + &pclmulqdq ($Xhn,$Hkey,0x11); ####### + &pclmulqdq ($T1,$T3,0x00); ####### + &movups ($Hkey,&QWP(16,$Htbl)); # load H^2 + &nop (); + + &sub ($len,0x20); + &jbe (&label("even_tail")); + &jmp (&label("mod_loop")); + +&set_label("mod_loop",32); + &pshufd ($T2,$Xi,0b01001110); # H^2*(Ii+Xi) + &movdqa ($Xhi,$Xi); + &pxor ($T2,$Xi); # + &nop (); + + &pclmulqdq ($Xi,$Hkey,0x00); ####### + &pclmulqdq ($Xhi,$Hkey,0x11); ####### + &pclmulqdq ($T2,$T3,0x10); ####### + &movups ($Hkey,&QWP(0,$Htbl)); # load H + + &xorps ($Xi,$Xn); # (H*Ii+1) + H^2*(Ii+Xi) + &movdqa ($T3,&QWP(0,$const)); + &xorps ($Xhi,$Xhn); + &movdqu ($Xhn,&QWP(0,$inp)); # Ii + &pxor ($T1,$Xi); # aggregated Karatsuba post-processing + &movdqu ($Xn,&QWP(16,$inp)); # Ii+1 + &pxor ($T1,$Xhi); # + + &pshufb ($Xhn,$T3); + &pxor ($T2,$T1); # + + &movdqa ($T1,$T2); # + &psrldq ($T2,8); + &pslldq ($T1,8); # + &pxor ($Xhi,$T2); + &pxor ($Xi,$T1); # + &pshufb ($Xn,$T3); + &pxor ($Xhi,$Xhn); # "Ii+Xi", consume early + + &movdqa ($Xhn,$Xn); #&clmul64x64_TX ($Xhn,$Xn,$Hkey); H*Ii+1 + &movdqa ($T2,$Xi); #&reduction_alg9($Xhi,$Xi); 1st phase + &movdqa ($T1,$Xi); + &psllq ($Xi,5); + &pxor ($T1,$Xi); # + &psllq ($Xi,1); + &pxor ($Xi,$T1); # + &pclmulqdq ($Xn,$Hkey,0x00); ####### + &movups ($T3,&QWP(32,$Htbl)); + &psllq ($Xi,57); # + &movdqa ($T1,$Xi); # + &pslldq ($Xi,8); + &psrldq ($T1,8); # + &pxor ($Xi,$T2); + &pxor ($Xhi,$T1); # + &pshufd ($T1,$Xhn,0b01001110); + &movdqa ($T2,$Xi); # 2nd phase + &psrlq ($Xi,1); + &pxor ($T1,$Xhn); + &pxor ($Xhi,$T2); # + &pclmulqdq ($Xhn,$Hkey,0x11); ####### + &movups ($Hkey,&QWP(16,$Htbl)); # load H^2 + &pxor ($T2,$Xi); + &psrlq ($Xi,5); + &pxor ($Xi,$T2); # + &psrlq ($Xi,1); # + &pxor ($Xi,$Xhi) # + &pclmulqdq ($T1,$T3,0x00); ####### + + &lea ($inp,&DWP(32,$inp)); + &sub ($len,0x20); + &ja (&label("mod_loop")); + +&set_label("even_tail"); + &pshufd ($T2,$Xi,0b01001110); # H^2*(Ii+Xi) + &movdqa ($Xhi,$Xi); + &pxor ($T2,$Xi); # + + &pclmulqdq ($Xi,$Hkey,0x00); ####### + &pclmulqdq ($Xhi,$Hkey,0x11); ####### + &pclmulqdq ($T2,$T3,0x10); ####### + &movdqa ($T3,&QWP(0,$const)); + + &xorps ($Xi,$Xn); # (H*Ii+1) + H^2*(Ii+Xi) + &xorps ($Xhi,$Xhn); + &pxor ($T1,$Xi); # aggregated Karatsuba post-processing + &pxor ($T1,$Xhi); # + + &pxor ($T2,$T1); # + + &movdqa ($T1,$T2); # + &psrldq ($T2,8); + &pslldq ($T1,8); # + &pxor ($Xhi,$T2); + &pxor ($Xi,$T1); # + + &reduction_alg9 ($Xhi,$Xi); + + &test ($len,$len); + &jnz (&label("done")); + + &movups ($Hkey,&QWP(0,$Htbl)); # load H +&set_label("odd_tail"); + &movdqu ($T1,&QWP(0,$inp)); # Ii + &pshufb ($T1,$T3); + &pxor ($Xi,$T1); # Ii+Xi + + &clmul64x64_T2 ($Xhi,$Xi,$Hkey); # H*(Ii+Xi) + &reduction_alg9 ($Xhi,$Xi); + +&set_label("done"); + &pshufb ($Xi,$T3); + &movdqu (&QWP(0,$Xip),$Xi); +&function_end("gcm_ghash_clmul"); + +} else { # Algorith 5. Kept for reference purposes. + +sub reduction_alg5 { # 19/16 times faster than Intel version +my ($Xhi,$Xi)=@_; + + # <<1 + &movdqa ($T1,$Xi); # + &movdqa ($T2,$Xhi); + &pslld ($Xi,1); + &pslld ($Xhi,1); # + &psrld ($T1,31); + &psrld ($T2,31); # + &movdqa ($T3,$T1); + &pslldq ($T1,4); + &psrldq ($T3,12); # + &pslldq ($T2,4); + &por ($Xhi,$T3); # + &por ($Xi,$T1); + &por ($Xhi,$T2); # + + # 1st phase + &movdqa ($T1,$Xi); + &movdqa ($T2,$Xi); + &movdqa ($T3,$Xi); # + &pslld ($T1,31); + &pslld ($T2,30); + &pslld ($Xi,25); # + &pxor ($T1,$T2); + &pxor ($T1,$Xi); # + &movdqa ($T2,$T1); # + &pslldq ($T1,12); + &psrldq ($T2,4); # + &pxor ($T3,$T1); + + # 2nd phase + &pxor ($Xhi,$T3); # + &movdqa ($Xi,$T3); + &movdqa ($T1,$T3); + &psrld ($Xi,1); # + &psrld ($T1,2); + &psrld ($T3,7); # + &pxor ($Xi,$T1); + &pxor ($Xhi,$T2); + &pxor ($Xi,$T3); # + &pxor ($Xi,$Xhi); # +} + +&function_begin_B("gcm_init_clmul"); + &mov ($Htbl,&wparam(0)); + &mov ($Xip,&wparam(1)); + + &call (&label("pic")); +&set_label("pic"); + &blindpop ($const); + &lea ($const,&DWP(&label("bswap")."-".&label("pic"),$const)); + + &movdqu ($Hkey,&QWP(0,$Xip)); + &pshufd ($Hkey,$Hkey,0b01001110);# dword swap + + # calculate H^2 + &movdqa ($Xi,$Hkey); + &clmul64x64_T3 ($Xhi,$Xi,$Hkey); + &reduction_alg5 ($Xhi,$Xi); + + &movdqu (&QWP(0,$Htbl),$Hkey); # save H + &movdqu (&QWP(16,$Htbl),$Xi); # save H^2 + + &ret (); +&function_end_B("gcm_init_clmul"); + +&function_begin_B("gcm_gmult_clmul"); + &mov ($Xip,&wparam(0)); + &mov ($Htbl,&wparam(1)); + + &call (&label("pic")); +&set_label("pic"); + &blindpop ($const); + &lea ($const,&DWP(&label("bswap")."-".&label("pic"),$const)); + + &movdqu ($Xi,&QWP(0,$Xip)); + &movdqa ($Xn,&QWP(0,$const)); + &movdqu ($Hkey,&QWP(0,$Htbl)); + &pshufb ($Xi,$Xn); + + &clmul64x64_T3 ($Xhi,$Xi,$Hkey); + &reduction_alg5 ($Xhi,$Xi); + + &pshufb ($Xi,$Xn); + &movdqu (&QWP(0,$Xip),$Xi); + + &ret (); +&function_end_B("gcm_gmult_clmul"); + +&function_begin("gcm_ghash_clmul"); + &mov ($Xip,&wparam(0)); + &mov ($Htbl,&wparam(1)); + &mov ($inp,&wparam(2)); + &mov ($len,&wparam(3)); + + &call (&label("pic")); +&set_label("pic"); + &blindpop ($const); + &lea ($const,&DWP(&label("bswap")."-".&label("pic"),$const)); + + &movdqu ($Xi,&QWP(0,$Xip)); + &movdqa ($T3,&QWP(0,$const)); + &movdqu ($Hkey,&QWP(0,$Htbl)); + &pshufb ($Xi,$T3); + + &sub ($len,0x10); + &jz (&label("odd_tail")); + + ####### + # Xi+2 =[H*(Ii+1 + Xi+1)] mod P = + # [(H*Ii+1) + (H*Xi+1)] mod P = + # [(H*Ii+1) + H^2*(Ii+Xi)] mod P + # + &movdqu ($T1,&QWP(0,$inp)); # Ii + &movdqu ($Xn,&QWP(16,$inp)); # Ii+1 + &pshufb ($T1,$T3); + &pshufb ($Xn,$T3); + &pxor ($Xi,$T1); # Ii+Xi + + &clmul64x64_T3 ($Xhn,$Xn,$Hkey); # H*Ii+1 + &movdqu ($Hkey,&QWP(16,$Htbl)); # load H^2 + + &sub ($len,0x20); + &lea ($inp,&DWP(32,$inp)); # i+=2 + &jbe (&label("even_tail")); + +&set_label("mod_loop"); + &clmul64x64_T3 ($Xhi,$Xi,$Hkey); # H^2*(Ii+Xi) + &movdqu ($Hkey,&QWP(0,$Htbl)); # load H + + &pxor ($Xi,$Xn); # (H*Ii+1) + H^2*(Ii+Xi) + &pxor ($Xhi,$Xhn); + + &reduction_alg5 ($Xhi,$Xi); + + ####### + &movdqa ($T3,&QWP(0,$const)); + &movdqu ($T1,&QWP(0,$inp)); # Ii + &movdqu ($Xn,&QWP(16,$inp)); # Ii+1 + &pshufb ($T1,$T3); + &pshufb ($Xn,$T3); + &pxor ($Xi,$T1); # Ii+Xi + + &clmul64x64_T3 ($Xhn,$Xn,$Hkey); # H*Ii+1 + &movdqu ($Hkey,&QWP(16,$Htbl)); # load H^2 + + &sub ($len,0x20); + &lea ($inp,&DWP(32,$inp)); + &ja (&label("mod_loop")); + +&set_label("even_tail"); + &clmul64x64_T3 ($Xhi,$Xi,$Hkey); # H^2*(Ii+Xi) + + &pxor ($Xi,$Xn); # (H*Ii+1) + H^2*(Ii+Xi) + &pxor ($Xhi,$Xhn); + + &reduction_alg5 ($Xhi,$Xi); + + &movdqa ($T3,&QWP(0,$const)); + &test ($len,$len); + &jnz (&label("done")); + + &movdqu ($Hkey,&QWP(0,$Htbl)); # load H +&set_label("odd_tail"); + &movdqu ($T1,&QWP(0,$inp)); # Ii + &pshufb ($T1,$T3); + &pxor ($Xi,$T1); # Ii+Xi + + &clmul64x64_T3 ($Xhi,$Xi,$Hkey); # H*(Ii+Xi) + &reduction_alg5 ($Xhi,$Xi); + + &movdqa ($T3,&QWP(0,$const)); +&set_label("done"); + &pshufb ($Xi,$T3); + &movdqu (&QWP(0,$Xip),$Xi); +&function_end("gcm_ghash_clmul"); + +} + +&set_label("bswap",64); + &data_byte(15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0); + &data_byte(1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xc2); # 0x1c2_polynomial +&set_label("rem_8bit",64); + &data_short(0x0000,0x01C2,0x0384,0x0246,0x0708,0x06CA,0x048C,0x054E); + &data_short(0x0E10,0x0FD2,0x0D94,0x0C56,0x0918,0x08DA,0x0A9C,0x0B5E); + &data_short(0x1C20,0x1DE2,0x1FA4,0x1E66,0x1B28,0x1AEA,0x18AC,0x196E); + &data_short(0x1230,0x13F2,0x11B4,0x1076,0x1538,0x14FA,0x16BC,0x177E); + &data_short(0x3840,0x3982,0x3BC4,0x3A06,0x3F48,0x3E8A,0x3CCC,0x3D0E); + &data_short(0x3650,0x3792,0x35D4,0x3416,0x3158,0x309A,0x32DC,0x331E); + &data_short(0x2460,0x25A2,0x27E4,0x2626,0x2368,0x22AA,0x20EC,0x212E); + &data_short(0x2A70,0x2BB2,0x29F4,0x2836,0x2D78,0x2CBA,0x2EFC,0x2F3E); + &data_short(0x7080,0x7142,0x7304,0x72C6,0x7788,0x764A,0x740C,0x75CE); + &data_short(0x7E90,0x7F52,0x7D14,0x7CD6,0x7998,0x785A,0x7A1C,0x7BDE); + &data_short(0x6CA0,0x6D62,0x6F24,0x6EE6,0x6BA8,0x6A6A,0x682C,0x69EE); + &data_short(0x62B0,0x6372,0x6134,0x60F6,0x65B8,0x647A,0x663C,0x67FE); + &data_short(0x48C0,0x4902,0x4B44,0x4A86,0x4FC8,0x4E0A,0x4C4C,0x4D8E); + &data_short(0x46D0,0x4712,0x4554,0x4496,0x41D8,0x401A,0x425C,0x439E); + &data_short(0x54E0,0x5522,0x5764,0x56A6,0x53E8,0x522A,0x506C,0x51AE); + &data_short(0x5AF0,0x5B32,0x5974,0x58B6,0x5DF8,0x5C3A,0x5E7C,0x5FBE); + &data_short(0xE100,0xE0C2,0xE284,0xE346,0xE608,0xE7CA,0xE58C,0xE44E); + &data_short(0xEF10,0xEED2,0xEC94,0xED56,0xE818,0xE9DA,0xEB9C,0xEA5E); + &data_short(0xFD20,0xFCE2,0xFEA4,0xFF66,0xFA28,0xFBEA,0xF9AC,0xF86E); + &data_short(0xF330,0xF2F2,0xF0B4,0xF176,0xF438,0xF5FA,0xF7BC,0xF67E); + &data_short(0xD940,0xD882,0xDAC4,0xDB06,0xDE48,0xDF8A,0xDDCC,0xDC0E); + &data_short(0xD750,0xD692,0xD4D4,0xD516,0xD058,0xD19A,0xD3DC,0xD21E); + &data_short(0xC560,0xC4A2,0xC6E4,0xC726,0xC268,0xC3AA,0xC1EC,0xC02E); + &data_short(0xCB70,0xCAB2,0xC8F4,0xC936,0xCC78,0xCDBA,0xCFFC,0xCE3E); + &data_short(0x9180,0x9042,0x9204,0x93C6,0x9688,0x974A,0x950C,0x94CE); + &data_short(0x9F90,0x9E52,0x9C14,0x9DD6,0x9898,0x995A,0x9B1C,0x9ADE); + &data_short(0x8DA0,0x8C62,0x8E24,0x8FE6,0x8AA8,0x8B6A,0x892C,0x88EE); + &data_short(0x83B0,0x8272,0x8034,0x81F6,0x84B8,0x857A,0x873C,0x86FE); + &data_short(0xA9C0,0xA802,0xAA44,0xAB86,0xAEC8,0xAF0A,0xAD4C,0xAC8E); + &data_short(0xA7D0,0xA612,0xA454,0xA596,0xA0D8,0xA11A,0xA35C,0xA29E); + &data_short(0xB5E0,0xB422,0xB664,0xB7A6,0xB2E8,0xB32A,0xB16C,0xB0AE); + &data_short(0xBBF0,0xBA32,0xB874,0xB9B6,0xBCF8,0xBD3A,0xBF7C,0xBEBE); +}} # $sse2 + +&set_label("rem_4bit",64); + &data_word(0,0x0000<<$S,0,0x1C20<<$S,0,0x3840<<$S,0,0x2460<<$S); + &data_word(0,0x7080<<$S,0,0x6CA0<<$S,0,0x48C0<<$S,0,0x54E0<<$S); + &data_word(0,0xE100<<$S,0,0xFD20<<$S,0,0xD940<<$S,0,0xC560<<$S); + &data_word(0,0x9180<<$S,0,0x8DA0<<$S,0,0xA9C0<<$S,0,0xB5E0<<$S); +}}} # !$x86only + +&asciz("GHASH for x86, CRYPTOGAMS by "); +&asm_finish(); + +# A question was risen about choice of vanilla MMX. Or rather why wasn't +# SSE2 chosen instead? In addition to the fact that MMX runs on legacy +# CPUs such as PIII, "4-bit" MMX version was observed to provide better +# performance than *corresponding* SSE2 one even on contemporary CPUs. +# SSE2 results were provided by Peter-Michael Hager. He maintains SSE2 +# implementation featuring full range of lookup-table sizes, but with +# per-invocation lookup table setup. Latter means that table size is +# chosen depending on how much data is to be hashed in every given call, +# more data - larger table. Best reported result for Core2 is ~4 cycles +# per processed byte out of 64KB block. This number accounts even for +# 64KB table setup overhead. As discussed in gcm128.c we choose to be +# more conservative in respect to lookup table sizes, but how do the +# results compare? Minimalistic "256B" MMX version delivers ~11 cycles +# on same platform. As also discussed in gcm128.c, next in line "8-bit +# Shoup's" or "4KB" method should deliver twice the performance of +# "256B" one, in other words not worse than ~6 cycles per byte. It +# should be also be noted that in SSE2 case improvement can be "super- +# linear," i.e. more than twice, mostly because >>8 maps to single +# instruction on SSE2 register. This is unlike "4-bit" case when >>4 +# maps to same amount of instructions in both MMX and SSE2 cases. +# Bottom line is that switch to SSE2 is considered to be justifiable +# only in case we choose to implement "8-bit" method... diff --git a/external/boringssl/crypto/modes/asm/ghash-x86_64.pl b/external/boringssl/crypto/modes/asm/ghash-x86_64.pl new file mode 100644 index 0000000000..5a11fb94c6 --- /dev/null +++ b/external/boringssl/crypto/modes/asm/ghash-x86_64.pl @@ -0,0 +1,1742 @@ +#!/usr/bin/env perl +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# March, June 2010 +# +# The module implements "4-bit" GCM GHASH function and underlying +# single multiplication operation in GF(2^128). "4-bit" means that +# it uses 256 bytes per-key table [+128 bytes shared table]. GHASH +# function features so called "528B" variant utilizing additional +# 256+16 bytes of per-key storage [+512 bytes shared table]. +# Performance results are for this streamed GHASH subroutine and are +# expressed in cycles per processed byte, less is better: +# +# gcc 3.4.x(*) assembler +# +# P4 28.6 14.0 +100% +# Opteron 19.3 7.7 +150% +# Core2 17.8 8.1(**) +120% +# Atom 31.6 16.8 +88% +# VIA Nano 21.8 10.1 +115% +# +# (*) comparison is not completely fair, because C results are +# for vanilla "256B" implementation, while assembler results +# are for "528B";-) +# (**) it's mystery [to me] why Core2 result is not same as for +# Opteron; + +# May 2010 +# +# Add PCLMULQDQ version performing at 2.02 cycles per processed byte. +# See ghash-x86.pl for background information and details about coding +# techniques. +# +# Special thanks to David Woodhouse for +# providing access to a Westmere-based system on behalf of Intel +# Open Source Technology Centre. + +# December 2012 +# +# Overhaul: aggregate Karatsuba post-processing, improve ILP in +# reduction_alg9, increase reduction aggregate factor to 4x. As for +# the latter. ghash-x86.pl discusses that it makes lesser sense to +# increase aggregate factor. Then why increase here? Critical path +# consists of 3 independent pclmulqdq instructions, Karatsuba post- +# processing and reduction. "On top" of this we lay down aggregated +# multiplication operations, triplets of independent pclmulqdq's. As +# issue rate for pclmulqdq is limited, it makes lesser sense to +# aggregate more multiplications than it takes to perform remaining +# non-multiplication operations. 2x is near-optimal coefficient for +# contemporary Intel CPUs (therefore modest improvement coefficient), +# but not for Bulldozer. Latter is because logical SIMD operations +# are twice as slow in comparison to Intel, so that critical path is +# longer. A CPU with higher pclmulqdq issue rate would also benefit +# from higher aggregate factor... +# +# Westmere 1.78(+13%) +# Sandy Bridge 1.80(+8%) +# Ivy Bridge 1.80(+7%) +# Haswell 0.55(+93%) (if system doesn't support AVX) +# Broadwell 0.45(+110%)(if system doesn't support AVX) +# Bulldozer 1.49(+27%) +# Silvermont 2.88(+13%) + +# March 2013 +# +# ... 8x aggregate factor AVX code path is using reduction algorithm +# suggested by Shay Gueron[1]. Even though contemporary AVX-capable +# CPUs such as Sandy and Ivy Bridge can execute it, the code performs +# sub-optimally in comparison to above mentioned version. But thanks +# to Ilya Albrekht and Max Locktyukhin of Intel Corp. we knew that +# it performs in 0.41 cycles per byte on Haswell processor, and in +# 0.29 on Broadwell. +# +# [1] http://rt.openssl.org/Ticket/Display.html?id=2900&user=guest&pass=guest + +$flavour = shift; +$output = shift; +if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } + +$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or +die "can't locate x86_64-xlate.pl"; + +# This must be kept in sync with |$avx| in aesni-gcm-x86_64.pl; otherwise tags +# will be computed incorrectly. +# +# In upstream, this is controlled by shelling out to the compiler to check +# versions, but BoringSSL is intended to be used with pre-generated perlasm +# output, so this isn't useful anyway. +$avx = 0; + +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; + +$do4xaggr=1; + +# common register layout +$nlo="%rax"; +$nhi="%rbx"; +$Zlo="%r8"; +$Zhi="%r9"; +$tmp="%r10"; +$rem_4bit = "%r11"; + +$Xi="%rdi"; +$Htbl="%rsi"; + +# per-function register layout +$cnt="%rcx"; +$rem="%rdx"; + +sub LB() { my $r=shift; $r =~ s/%[er]([a-d])x/%\1l/ or + $r =~ s/%[er]([sd]i)/%\1l/ or + $r =~ s/%[er](bp)/%\1l/ or + $r =~ s/%(r[0-9]+)[d]?/%\1b/; $r; } + +sub AUTOLOAD() # thunk [simplified] 32-bit style perlasm +{ my $opcode = $AUTOLOAD; $opcode =~ s/.*:://; + my $arg = pop; + $arg = "\$$arg" if ($arg*1 eq $arg); + $code .= "\t$opcode\t".join(',',$arg,reverse @_)."\n"; +} + +{ my $N; + sub loop() { + my $inp = shift; + + $N++; +$code.=<<___; + xor $nlo,$nlo + xor $nhi,$nhi + mov `&LB("$Zlo")`,`&LB("$nlo")` + mov `&LB("$Zlo")`,`&LB("$nhi")` + shl \$4,`&LB("$nlo")` + mov \$14,$cnt + mov 8($Htbl,$nlo),$Zlo + mov ($Htbl,$nlo),$Zhi + and \$0xf0,`&LB("$nhi")` + mov $Zlo,$rem + jmp .Loop$N + +.align 16 +.Loop$N: + shr \$4,$Zlo + and \$0xf,$rem + mov $Zhi,$tmp + mov ($inp,$cnt),`&LB("$nlo")` + shr \$4,$Zhi + xor 8($Htbl,$nhi),$Zlo + shl \$60,$tmp + xor ($Htbl,$nhi),$Zhi + mov `&LB("$nlo")`,`&LB("$nhi")` + xor ($rem_4bit,$rem,8),$Zhi + mov $Zlo,$rem + shl \$4,`&LB("$nlo")` + xor $tmp,$Zlo + dec $cnt + js .Lbreak$N + + shr \$4,$Zlo + and \$0xf,$rem + mov $Zhi,$tmp + shr \$4,$Zhi + xor 8($Htbl,$nlo),$Zlo + shl \$60,$tmp + xor ($Htbl,$nlo),$Zhi + and \$0xf0,`&LB("$nhi")` + xor ($rem_4bit,$rem,8),$Zhi + mov $Zlo,$rem + xor $tmp,$Zlo + jmp .Loop$N + +.align 16 +.Lbreak$N: + shr \$4,$Zlo + and \$0xf,$rem + mov $Zhi,$tmp + shr \$4,$Zhi + xor 8($Htbl,$nlo),$Zlo + shl \$60,$tmp + xor ($Htbl,$nlo),$Zhi + and \$0xf0,`&LB("$nhi")` + xor ($rem_4bit,$rem,8),$Zhi + mov $Zlo,$rem + xor $tmp,$Zlo + + shr \$4,$Zlo + and \$0xf,$rem + mov $Zhi,$tmp + shr \$4,$Zhi + xor 8($Htbl,$nhi),$Zlo + shl \$60,$tmp + xor ($Htbl,$nhi),$Zhi + xor $tmp,$Zlo + xor ($rem_4bit,$rem,8),$Zhi + + bswap $Zlo + bswap $Zhi +___ +}} + +$code=<<___; +.text +.extern OPENSSL_ia32cap_P + +.globl gcm_gmult_4bit +.type gcm_gmult_4bit,\@function,2 +.align 16 +gcm_gmult_4bit: + push %rbx + push %rbp # %rbp and %r12 are pushed exclusively in + push %r12 # order to reuse Win64 exception handler... +.Lgmult_prologue: + + movzb 15($Xi),$Zlo + lea .Lrem_4bit(%rip),$rem_4bit +___ + &loop ($Xi); +$code.=<<___; + mov $Zlo,8($Xi) + mov $Zhi,($Xi) + + mov 16(%rsp),%rbx + lea 24(%rsp),%rsp +.Lgmult_epilogue: + ret +.size gcm_gmult_4bit,.-gcm_gmult_4bit +___ + +# per-function register layout +$inp="%rdx"; +$len="%rcx"; +$rem_8bit=$rem_4bit; + +$code.=<<___; +.globl gcm_ghash_4bit +.type gcm_ghash_4bit,\@function,4 +.align 16 +gcm_ghash_4bit: + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + sub \$280,%rsp +.Lghash_prologue: + mov $inp,%r14 # reassign couple of args + mov $len,%r15 +___ +{ my $inp="%r14"; + my $dat="%edx"; + my $len="%r15"; + my @nhi=("%ebx","%ecx"); + my @rem=("%r12","%r13"); + my $Hshr4="%rbp"; + + &sub ($Htbl,-128); # size optimization + &lea ($Hshr4,"16+128(%rsp)"); + { my @lo =($nlo,$nhi); + my @hi =($Zlo,$Zhi); + + &xor ($dat,$dat); + for ($i=0,$j=-2;$i<18;$i++,$j++) { + &mov ("$j(%rsp)",&LB($dat)) if ($i>1); + &or ($lo[0],$tmp) if ($i>1); + &mov (&LB($dat),&LB($lo[1])) if ($i>0 && $i<17); + &shr ($lo[1],4) if ($i>0 && $i<17); + &mov ($tmp,$hi[1]) if ($i>0 && $i<17); + &shr ($hi[1],4) if ($i>0 && $i<17); + &mov ("8*$j($Hshr4)",$hi[0]) if ($i>1); + &mov ($hi[0],"16*$i+0-128($Htbl)") if ($i<16); + &shl (&LB($dat),4) if ($i>0 && $i<17); + &mov ("8*$j-128($Hshr4)",$lo[0]) if ($i>1); + &mov ($lo[0],"16*$i+8-128($Htbl)") if ($i<16); + &shl ($tmp,60) if ($i>0 && $i<17); + + push (@lo,shift(@lo)); + push (@hi,shift(@hi)); + } + } + &add ($Htbl,-128); + &mov ($Zlo,"8($Xi)"); + &mov ($Zhi,"0($Xi)"); + &add ($len,$inp); # pointer to the end of data + &lea ($rem_8bit,".Lrem_8bit(%rip)"); + &jmp (".Louter_loop"); + +$code.=".align 16\n.Louter_loop:\n"; + &xor ($Zhi,"($inp)"); + &mov ("%rdx","8($inp)"); + &lea ($inp,"16($inp)"); + &xor ("%rdx",$Zlo); + &mov ("($Xi)",$Zhi); + &mov ("8($Xi)","%rdx"); + &shr ("%rdx",32); + + &xor ($nlo,$nlo); + &rol ($dat,8); + &mov (&LB($nlo),&LB($dat)); + &movz ($nhi[0],&LB($dat)); + &shl (&LB($nlo),4); + &shr ($nhi[0],4); + + for ($j=11,$i=0;$i<15;$i++) { + &rol ($dat,8); + &xor ($Zlo,"8($Htbl,$nlo)") if ($i>0); + &xor ($Zhi,"($Htbl,$nlo)") if ($i>0); + &mov ($Zlo,"8($Htbl,$nlo)") if ($i==0); + &mov ($Zhi,"($Htbl,$nlo)") if ($i==0); + + &mov (&LB($nlo),&LB($dat)); + &xor ($Zlo,$tmp) if ($i>0); + &movzw ($rem[1],"($rem_8bit,$rem[1],2)") if ($i>0); + + &movz ($nhi[1],&LB($dat)); + &shl (&LB($nlo),4); + &movzb ($rem[0],"(%rsp,$nhi[0])"); + + &shr ($nhi[1],4) if ($i<14); + &and ($nhi[1],0xf0) if ($i==14); + &shl ($rem[1],48) if ($i>0); + &xor ($rem[0],$Zlo); + + &mov ($tmp,$Zhi); + &xor ($Zhi,$rem[1]) if ($i>0); + &shr ($Zlo,8); + + &movz ($rem[0],&LB($rem[0])); + &mov ($dat,"$j($Xi)") if (--$j%4==0); + &shr ($Zhi,8); + + &xor ($Zlo,"-128($Hshr4,$nhi[0],8)"); + &shl ($tmp,56); + &xor ($Zhi,"($Hshr4,$nhi[0],8)"); + + unshift (@nhi,pop(@nhi)); # "rotate" registers + unshift (@rem,pop(@rem)); + } + &movzw ($rem[1],"($rem_8bit,$rem[1],2)"); + &xor ($Zlo,"8($Htbl,$nlo)"); + &xor ($Zhi,"($Htbl,$nlo)"); + + &shl ($rem[1],48); + &xor ($Zlo,$tmp); + + &xor ($Zhi,$rem[1]); + &movz ($rem[0],&LB($Zlo)); + &shr ($Zlo,4); + + &mov ($tmp,$Zhi); + &shl (&LB($rem[0]),4); + &shr ($Zhi,4); + + &xor ($Zlo,"8($Htbl,$nhi[0])"); + &movzw ($rem[0],"($rem_8bit,$rem[0],2)"); + &shl ($tmp,60); + + &xor ($Zhi,"($Htbl,$nhi[0])"); + &xor ($Zlo,$tmp); + &shl ($rem[0],48); + + &bswap ($Zlo); + &xor ($Zhi,$rem[0]); + + &bswap ($Zhi); + &cmp ($inp,$len); + &jb (".Louter_loop"); +} +$code.=<<___; + mov $Zlo,8($Xi) + mov $Zhi,($Xi) + + lea 280(%rsp),%rsi + mov 0(%rsi),%r15 + mov 8(%rsi),%r14 + mov 16(%rsi),%r13 + mov 24(%rsi),%r12 + mov 32(%rsi),%rbp + mov 40(%rsi),%rbx + lea 48(%rsi),%rsp +.Lghash_epilogue: + ret +.size gcm_ghash_4bit,.-gcm_ghash_4bit +___ + +###################################################################### +# PCLMULQDQ version. + +@_4args=$win64? ("%rcx","%rdx","%r8", "%r9") : # Win64 order + ("%rdi","%rsi","%rdx","%rcx"); # Unix order + +($Xi,$Xhi)=("%xmm0","%xmm1"); $Hkey="%xmm2"; +($T1,$T2,$T3)=("%xmm3","%xmm4","%xmm5"); + +sub clmul64x64_T2 { # minimal register pressure +my ($Xhi,$Xi,$Hkey,$HK)=@_; + +if (!defined($HK)) { $HK = $T2; +$code.=<<___; + movdqa $Xi,$Xhi # + pshufd \$0b01001110,$Xi,$T1 + pshufd \$0b01001110,$Hkey,$T2 + pxor $Xi,$T1 # + pxor $Hkey,$T2 +___ +} else { +$code.=<<___; + movdqa $Xi,$Xhi # + pshufd \$0b01001110,$Xi,$T1 + pxor $Xi,$T1 # +___ +} +$code.=<<___; + pclmulqdq \$0x00,$Hkey,$Xi ####### + pclmulqdq \$0x11,$Hkey,$Xhi ####### + pclmulqdq \$0x00,$HK,$T1 ####### + pxor $Xi,$T1 # + pxor $Xhi,$T1 # + + movdqa $T1,$T2 # + psrldq \$8,$T1 + pslldq \$8,$T2 # + pxor $T1,$Xhi + pxor $T2,$Xi # +___ +} + +sub reduction_alg9 { # 17/11 times faster than Intel version +my ($Xhi,$Xi) = @_; + +$code.=<<___; + # 1st phase + movdqa $Xi,$T2 # + movdqa $Xi,$T1 + psllq \$5,$Xi + pxor $Xi,$T1 # + psllq \$1,$Xi + pxor $T1,$Xi # + psllq \$57,$Xi # + movdqa $Xi,$T1 # + pslldq \$8,$Xi + psrldq \$8,$T1 # + pxor $T2,$Xi + pxor $T1,$Xhi # + + # 2nd phase + movdqa $Xi,$T2 + psrlq \$1,$Xi + pxor $T2,$Xhi # + pxor $Xi,$T2 + psrlq \$5,$Xi + pxor $T2,$Xi # + psrlq \$1,$Xi # + pxor $Xhi,$Xi # +___ +} + +{ my ($Htbl,$Xip)=@_4args; + my $HK="%xmm6"; + +$code.=<<___; +.globl gcm_init_clmul +.type gcm_init_clmul,\@abi-omnipotent +.align 16 +gcm_init_clmul: +.L_init_clmul: +___ +$code.=<<___ if ($win64); +.LSEH_begin_gcm_init_clmul: + # I can't trust assembler to use specific encoding:-( + .byte 0x48,0x83,0xec,0x18 #sub $0x18,%rsp + .byte 0x0f,0x29,0x34,0x24 #movaps %xmm6,(%rsp) +___ +$code.=<<___; + movdqu ($Xip),$Hkey + pshufd \$0b01001110,$Hkey,$Hkey # dword swap + + # <<1 twist + pshufd \$0b11111111,$Hkey,$T2 # broadcast uppermost dword + movdqa $Hkey,$T1 + psllq \$1,$Hkey + pxor $T3,$T3 # + psrlq \$63,$T1 + pcmpgtd $T2,$T3 # broadcast carry bit + pslldq \$8,$T1 + por $T1,$Hkey # H<<=1 + + # magic reduction + pand .L0x1c2_polynomial(%rip),$T3 + pxor $T3,$Hkey # if(carry) H^=0x1c2_polynomial + + # calculate H^2 + pshufd \$0b01001110,$Hkey,$HK + movdqa $Hkey,$Xi + pxor $Hkey,$HK +___ + &clmul64x64_T2 ($Xhi,$Xi,$Hkey,$HK); + &reduction_alg9 ($Xhi,$Xi); +$code.=<<___; + pshufd \$0b01001110,$Hkey,$T1 + pshufd \$0b01001110,$Xi,$T2 + pxor $Hkey,$T1 # Karatsuba pre-processing + movdqu $Hkey,0x00($Htbl) # save H + pxor $Xi,$T2 # Karatsuba pre-processing + movdqu $Xi,0x10($Htbl) # save H^2 + palignr \$8,$T1,$T2 # low part is H.lo^H.hi... + movdqu $T2,0x20($Htbl) # save Karatsuba "salt" +___ +if ($do4xaggr) { + &clmul64x64_T2 ($Xhi,$Xi,$Hkey,$HK); # H^3 + &reduction_alg9 ($Xhi,$Xi); +$code.=<<___; + movdqa $Xi,$T3 +___ + &clmul64x64_T2 ($Xhi,$Xi,$Hkey,$HK); # H^4 + &reduction_alg9 ($Xhi,$Xi); +$code.=<<___; + pshufd \$0b01001110,$T3,$T1 + pshufd \$0b01001110,$Xi,$T2 + pxor $T3,$T1 # Karatsuba pre-processing + movdqu $T3,0x30($Htbl) # save H^3 + pxor $Xi,$T2 # Karatsuba pre-processing + movdqu $Xi,0x40($Htbl) # save H^4 + palignr \$8,$T1,$T2 # low part is H^3.lo^H^3.hi... + movdqu $T2,0x50($Htbl) # save Karatsuba "salt" +___ +} +$code.=<<___ if ($win64); + movaps (%rsp),%xmm6 + lea 0x18(%rsp),%rsp +.LSEH_end_gcm_init_clmul: +___ +$code.=<<___; + ret +.size gcm_init_clmul,.-gcm_init_clmul +___ +} + +{ my ($Xip,$Htbl)=@_4args; + +$code.=<<___; +.globl gcm_gmult_clmul +.type gcm_gmult_clmul,\@abi-omnipotent +.align 16 +gcm_gmult_clmul: +.L_gmult_clmul: + movdqu ($Xip),$Xi + movdqa .Lbswap_mask(%rip),$T3 + movdqu ($Htbl),$Hkey + movdqu 0x20($Htbl),$T2 + pshufb $T3,$Xi +___ + &clmul64x64_T2 ($Xhi,$Xi,$Hkey,$T2); +$code.=<<___ if (0 || (&reduction_alg9($Xhi,$Xi)&&0)); + # experimental alternative. special thing about is that there + # no dependency between the two multiplications... + mov \$`0xE1<<1`,%eax + mov \$0xA040608020C0E000,%r10 # ((7..0)·0xE0)&0xff + mov \$0x07,%r11d + movq %rax,$T1 + movq %r10,$T2 + movq %r11,$T3 # borrow $T3 + pand $Xi,$T3 + pshufb $T3,$T2 # ($Xi&7)·0xE0 + movq %rax,$T3 + pclmulqdq \$0x00,$Xi,$T1 # ·(0xE1<<1) + pxor $Xi,$T2 + pslldq \$15,$T2 + paddd $T2,$T2 # <<(64+56+1) + pxor $T2,$Xi + pclmulqdq \$0x01,$T3,$Xi + movdqa .Lbswap_mask(%rip),$T3 # reload $T3 + psrldq \$1,$T1 + pxor $T1,$Xhi + pslldq \$7,$Xi + pxor $Xhi,$Xi +___ +$code.=<<___; + pshufb $T3,$Xi + movdqu $Xi,($Xip) + ret +.size gcm_gmult_clmul,.-gcm_gmult_clmul +___ +} + +{ my ($Xip,$Htbl,$inp,$len)=@_4args; + my ($Xln,$Xmn,$Xhn,$Hkey2,$HK) = map("%xmm$_",(3..7)); + my ($T1,$T2,$T3)=map("%xmm$_",(8..10)); + +$code.=<<___; +.globl gcm_ghash_clmul +.type gcm_ghash_clmul,\@abi-omnipotent +.align 32 +gcm_ghash_clmul: +.L_ghash_clmul: +___ +$code.=<<___ if ($win64); + lea -0x88(%rsp),%rax +.LSEH_begin_gcm_ghash_clmul: + # I can't trust assembler to use specific encoding:-( + .byte 0x48,0x8d,0x60,0xe0 #lea -0x20(%rax),%rsp + .byte 0x0f,0x29,0x70,0xe0 #movaps %xmm6,-0x20(%rax) + .byte 0x0f,0x29,0x78,0xf0 #movaps %xmm7,-0x10(%rax) + .byte 0x44,0x0f,0x29,0x00 #movaps %xmm8,0(%rax) + .byte 0x44,0x0f,0x29,0x48,0x10 #movaps %xmm9,0x10(%rax) + .byte 0x44,0x0f,0x29,0x50,0x20 #movaps %xmm10,0x20(%rax) + .byte 0x44,0x0f,0x29,0x58,0x30 #movaps %xmm11,0x30(%rax) + .byte 0x44,0x0f,0x29,0x60,0x40 #movaps %xmm12,0x40(%rax) + .byte 0x44,0x0f,0x29,0x68,0x50 #movaps %xmm13,0x50(%rax) + .byte 0x44,0x0f,0x29,0x70,0x60 #movaps %xmm14,0x60(%rax) + .byte 0x44,0x0f,0x29,0x78,0x70 #movaps %xmm15,0x70(%rax) +___ +$code.=<<___; + movdqa .Lbswap_mask(%rip),$T3 + + movdqu ($Xip),$Xi + movdqu ($Htbl),$Hkey + movdqu 0x20($Htbl),$HK + pshufb $T3,$Xi + + sub \$0x10,$len + jz .Lodd_tail + + movdqu 0x10($Htbl),$Hkey2 +___ +if ($do4xaggr) { +my ($Xl,$Xm,$Xh,$Hkey3,$Hkey4)=map("%xmm$_",(11..15)); + +$code.=<<___; + mov OPENSSL_ia32cap_P+4(%rip),%eax + cmp \$0x30,$len + jb .Lskip4x + + and \$`1<<26|1<<22`,%eax # isolate MOVBE+XSAVE + cmp \$`1<<22`,%eax # check for MOVBE without XSAVE + je .Lskip4x + + sub \$0x30,$len + mov \$0xA040608020C0E000,%rax # ((7..0)·0xE0)&0xff + movdqu 0x30($Htbl),$Hkey3 + movdqu 0x40($Htbl),$Hkey4 + + ####### + # Xi+4 =[(H*Ii+3) + (H^2*Ii+2) + (H^3*Ii+1) + H^4*(Ii+Xi)] mod P + # + movdqu 0x30($inp),$Xln + movdqu 0x20($inp),$Xl + pshufb $T3,$Xln + pshufb $T3,$Xl + movdqa $Xln,$Xhn + pshufd \$0b01001110,$Xln,$Xmn + pxor $Xln,$Xmn + pclmulqdq \$0x00,$Hkey,$Xln + pclmulqdq \$0x11,$Hkey,$Xhn + pclmulqdq \$0x00,$HK,$Xmn + + movdqa $Xl,$Xh + pshufd \$0b01001110,$Xl,$Xm + pxor $Xl,$Xm + pclmulqdq \$0x00,$Hkey2,$Xl + pclmulqdq \$0x11,$Hkey2,$Xh + pclmulqdq \$0x10,$HK,$Xm + xorps $Xl,$Xln + xorps $Xh,$Xhn + movups 0x50($Htbl),$HK + xorps $Xm,$Xmn + + movdqu 0x10($inp),$Xl + movdqu 0($inp),$T1 + pshufb $T3,$Xl + pshufb $T3,$T1 + movdqa $Xl,$Xh + pshufd \$0b01001110,$Xl,$Xm + pxor $T1,$Xi + pxor $Xl,$Xm + pclmulqdq \$0x00,$Hkey3,$Xl + movdqa $Xi,$Xhi + pshufd \$0b01001110,$Xi,$T1 + pxor $Xi,$T1 + pclmulqdq \$0x11,$Hkey3,$Xh + pclmulqdq \$0x00,$HK,$Xm + xorps $Xl,$Xln + xorps $Xh,$Xhn + + lea 0x40($inp),$inp + sub \$0x40,$len + jc .Ltail4x + + jmp .Lmod4_loop +.align 32 +.Lmod4_loop: + pclmulqdq \$0x00,$Hkey4,$Xi + xorps $Xm,$Xmn + movdqu 0x30($inp),$Xl + pshufb $T3,$Xl + pclmulqdq \$0x11,$Hkey4,$Xhi + xorps $Xln,$Xi + movdqu 0x20($inp),$Xln + movdqa $Xl,$Xh + pclmulqdq \$0x10,$HK,$T1 + pshufd \$0b01001110,$Xl,$Xm + xorps $Xhn,$Xhi + pxor $Xl,$Xm + pshufb $T3,$Xln + movups 0x20($Htbl),$HK + xorps $Xmn,$T1 + pclmulqdq \$0x00,$Hkey,$Xl + pshufd \$0b01001110,$Xln,$Xmn + + pxor $Xi,$T1 # aggregated Karatsuba post-processing + movdqa $Xln,$Xhn + pxor $Xhi,$T1 # + pxor $Xln,$Xmn + movdqa $T1,$T2 # + pclmulqdq \$0x11,$Hkey,$Xh + pslldq \$8,$T1 + psrldq \$8,$T2 # + pxor $T1,$Xi + movdqa .L7_mask(%rip),$T1 + pxor $T2,$Xhi # + movq %rax,$T2 + + pand $Xi,$T1 # 1st phase + pshufb $T1,$T2 # + pxor $Xi,$T2 # + pclmulqdq \$0x00,$HK,$Xm + psllq \$57,$T2 # + movdqa $T2,$T1 # + pslldq \$8,$T2 + pclmulqdq \$0x00,$Hkey2,$Xln + psrldq \$8,$T1 # + pxor $T2,$Xi + pxor $T1,$Xhi # + movdqu 0($inp),$T1 + + movdqa $Xi,$T2 # 2nd phase + psrlq \$1,$Xi + pclmulqdq \$0x11,$Hkey2,$Xhn + xorps $Xl,$Xln + movdqu 0x10($inp),$Xl + pshufb $T3,$Xl + pclmulqdq \$0x10,$HK,$Xmn + xorps $Xh,$Xhn + movups 0x50($Htbl),$HK + pshufb $T3,$T1 + pxor $T2,$Xhi # + pxor $Xi,$T2 + psrlq \$5,$Xi + + movdqa $Xl,$Xh + pxor $Xm,$Xmn + pshufd \$0b01001110,$Xl,$Xm + pxor $T2,$Xi # + pxor $T1,$Xhi + pxor $Xl,$Xm + pclmulqdq \$0x00,$Hkey3,$Xl + psrlq \$1,$Xi # + pxor $Xhi,$Xi # + movdqa $Xi,$Xhi + pclmulqdq \$0x11,$Hkey3,$Xh + xorps $Xl,$Xln + pshufd \$0b01001110,$Xi,$T1 + pxor $Xi,$T1 + + pclmulqdq \$0x00,$HK,$Xm + xorps $Xh,$Xhn + + lea 0x40($inp),$inp + sub \$0x40,$len + jnc .Lmod4_loop + +.Ltail4x: + pclmulqdq \$0x00,$Hkey4,$Xi + pclmulqdq \$0x11,$Hkey4,$Xhi + pclmulqdq \$0x10,$HK,$T1 + xorps $Xm,$Xmn + xorps $Xln,$Xi + xorps $Xhn,$Xhi + pxor $Xi,$Xhi # aggregated Karatsuba post-processing + pxor $Xmn,$T1 + + pxor $Xhi,$T1 # + pxor $Xi,$Xhi + + movdqa $T1,$T2 # + psrldq \$8,$T1 + pslldq \$8,$T2 # + pxor $T1,$Xhi + pxor $T2,$Xi # +___ + &reduction_alg9($Xhi,$Xi); +$code.=<<___; + add \$0x40,$len + jz .Ldone + movdqu 0x20($Htbl),$HK + sub \$0x10,$len + jz .Lodd_tail +.Lskip4x: +___ +} +$code.=<<___; + ####### + # Xi+2 =[H*(Ii+1 + Xi+1)] mod P = + # [(H*Ii+1) + (H*Xi+1)] mod P = + # [(H*Ii+1) + H^2*(Ii+Xi)] mod P + # + movdqu ($inp),$T1 # Ii + movdqu 16($inp),$Xln # Ii+1 + pshufb $T3,$T1 + pshufb $T3,$Xln + pxor $T1,$Xi # Ii+Xi + + movdqa $Xln,$Xhn + pshufd \$0b01001110,$Xln,$Xmn + pxor $Xln,$Xmn + pclmulqdq \$0x00,$Hkey,$Xln + pclmulqdq \$0x11,$Hkey,$Xhn + pclmulqdq \$0x00,$HK,$Xmn + + lea 32($inp),$inp # i+=2 + nop + sub \$0x20,$len + jbe .Leven_tail + nop + jmp .Lmod_loop + +.align 32 +.Lmod_loop: + movdqa $Xi,$Xhi + movdqa $Xmn,$T1 + pshufd \$0b01001110,$Xi,$Xmn # + pxor $Xi,$Xmn # + + pclmulqdq \$0x00,$Hkey2,$Xi + pclmulqdq \$0x11,$Hkey2,$Xhi + pclmulqdq \$0x10,$HK,$Xmn + + pxor $Xln,$Xi # (H*Ii+1) + H^2*(Ii+Xi) + pxor $Xhn,$Xhi + movdqu ($inp),$T2 # Ii + pxor $Xi,$T1 # aggregated Karatsuba post-processing + pshufb $T3,$T2 + movdqu 16($inp),$Xln # Ii+1 + + pxor $Xhi,$T1 + pxor $T2,$Xhi # "Ii+Xi", consume early + pxor $T1,$Xmn + pshufb $T3,$Xln + movdqa $Xmn,$T1 # + psrldq \$8,$T1 + pslldq \$8,$Xmn # + pxor $T1,$Xhi + pxor $Xmn,$Xi # + + movdqa $Xln,$Xhn # + + movdqa $Xi,$T2 # 1st phase + movdqa $Xi,$T1 + psllq \$5,$Xi + pxor $Xi,$T1 # + pclmulqdq \$0x00,$Hkey,$Xln ####### + psllq \$1,$Xi + pxor $T1,$Xi # + psllq \$57,$Xi # + movdqa $Xi,$T1 # + pslldq \$8,$Xi + psrldq \$8,$T1 # + pxor $T2,$Xi + pshufd \$0b01001110,$Xhn,$Xmn + pxor $T1,$Xhi # + pxor $Xhn,$Xmn # + + movdqa $Xi,$T2 # 2nd phase + psrlq \$1,$Xi + pclmulqdq \$0x11,$Hkey,$Xhn ####### + pxor $T2,$Xhi # + pxor $Xi,$T2 + psrlq \$5,$Xi + pxor $T2,$Xi # + lea 32($inp),$inp + psrlq \$1,$Xi # + pclmulqdq \$0x00,$HK,$Xmn ####### + pxor $Xhi,$Xi # + + sub \$0x20,$len + ja .Lmod_loop + +.Leven_tail: + movdqa $Xi,$Xhi + movdqa $Xmn,$T1 + pshufd \$0b01001110,$Xi,$Xmn # + pxor $Xi,$Xmn # + + pclmulqdq \$0x00,$Hkey2,$Xi + pclmulqdq \$0x11,$Hkey2,$Xhi + pclmulqdq \$0x10,$HK,$Xmn + + pxor $Xln,$Xi # (H*Ii+1) + H^2*(Ii+Xi) + pxor $Xhn,$Xhi + pxor $Xi,$T1 + pxor $Xhi,$T1 + pxor $T1,$Xmn + movdqa $Xmn,$T1 # + psrldq \$8,$T1 + pslldq \$8,$Xmn # + pxor $T1,$Xhi + pxor $Xmn,$Xi # +___ + &reduction_alg9 ($Xhi,$Xi); +$code.=<<___; + test $len,$len + jnz .Ldone + +.Lodd_tail: + movdqu ($inp),$T1 # Ii + pshufb $T3,$T1 + pxor $T1,$Xi # Ii+Xi +___ + &clmul64x64_T2 ($Xhi,$Xi,$Hkey,$HK); # H*(Ii+Xi) + &reduction_alg9 ($Xhi,$Xi); +$code.=<<___; +.Ldone: + pshufb $T3,$Xi + movdqu $Xi,($Xip) +___ +$code.=<<___ if ($win64); + movaps (%rsp),%xmm6 + movaps 0x10(%rsp),%xmm7 + movaps 0x20(%rsp),%xmm8 + movaps 0x30(%rsp),%xmm9 + movaps 0x40(%rsp),%xmm10 + movaps 0x50(%rsp),%xmm11 + movaps 0x60(%rsp),%xmm12 + movaps 0x70(%rsp),%xmm13 + movaps 0x80(%rsp),%xmm14 + movaps 0x90(%rsp),%xmm15 + lea 0xa8(%rsp),%rsp +.LSEH_end_gcm_ghash_clmul: +___ +$code.=<<___; + ret +.size gcm_ghash_clmul,.-gcm_ghash_clmul +___ +} + +$code.=<<___; +.globl gcm_init_avx +.type gcm_init_avx,\@abi-omnipotent +.align 32 +gcm_init_avx: +___ +if ($avx) { +my ($Htbl,$Xip)=@_4args; +my $HK="%xmm6"; + +$code.=<<___ if ($win64); +.LSEH_begin_gcm_init_avx: + # I can't trust assembler to use specific encoding:-( + .byte 0x48,0x83,0xec,0x18 #sub $0x18,%rsp + .byte 0x0f,0x29,0x34,0x24 #movaps %xmm6,(%rsp) +___ +$code.=<<___; + vzeroupper + + vmovdqu ($Xip),$Hkey + vpshufd \$0b01001110,$Hkey,$Hkey # dword swap + + # <<1 twist + vpshufd \$0b11111111,$Hkey,$T2 # broadcast uppermost dword + vpsrlq \$63,$Hkey,$T1 + vpsllq \$1,$Hkey,$Hkey + vpxor $T3,$T3,$T3 # + vpcmpgtd $T2,$T3,$T3 # broadcast carry bit + vpslldq \$8,$T1,$T1 + vpor $T1,$Hkey,$Hkey # H<<=1 + + # magic reduction + vpand .L0x1c2_polynomial(%rip),$T3,$T3 + vpxor $T3,$Hkey,$Hkey # if(carry) H^=0x1c2_polynomial + + vpunpckhqdq $Hkey,$Hkey,$HK + vmovdqa $Hkey,$Xi + vpxor $Hkey,$HK,$HK + mov \$4,%r10 # up to H^8 + jmp .Linit_start_avx +___ + +sub clmul64x64_avx { +my ($Xhi,$Xi,$Hkey,$HK)=@_; + +if (!defined($HK)) { $HK = $T2; +$code.=<<___; + vpunpckhqdq $Xi,$Xi,$T1 + vpunpckhqdq $Hkey,$Hkey,$T2 + vpxor $Xi,$T1,$T1 # + vpxor $Hkey,$T2,$T2 +___ +} else { +$code.=<<___; + vpunpckhqdq $Xi,$Xi,$T1 + vpxor $Xi,$T1,$T1 # +___ +} +$code.=<<___; + vpclmulqdq \$0x11,$Hkey,$Xi,$Xhi ####### + vpclmulqdq \$0x00,$Hkey,$Xi,$Xi ####### + vpclmulqdq \$0x00,$HK,$T1,$T1 ####### + vpxor $Xi,$Xhi,$T2 # + vpxor $T2,$T1,$T1 # + + vpslldq \$8,$T1,$T2 # + vpsrldq \$8,$T1,$T1 + vpxor $T2,$Xi,$Xi # + vpxor $T1,$Xhi,$Xhi +___ +} + +sub reduction_avx { +my ($Xhi,$Xi) = @_; + +$code.=<<___; + vpsllq \$57,$Xi,$T1 # 1st phase + vpsllq \$62,$Xi,$T2 + vpxor $T1,$T2,$T2 # + vpsllq \$63,$Xi,$T1 + vpxor $T1,$T2,$T2 # + vpslldq \$8,$T2,$T1 # + vpsrldq \$8,$T2,$T2 + vpxor $T1,$Xi,$Xi # + vpxor $T2,$Xhi,$Xhi + + vpsrlq \$1,$Xi,$T2 # 2nd phase + vpxor $Xi,$Xhi,$Xhi + vpxor $T2,$Xi,$Xi # + vpsrlq \$5,$T2,$T2 + vpxor $T2,$Xi,$Xi # + vpsrlq \$1,$Xi,$Xi # + vpxor $Xhi,$Xi,$Xi # +___ +} + +$code.=<<___; +.align 32 +.Linit_loop_avx: + vpalignr \$8,$T1,$T2,$T3 # low part is H.lo^H.hi... + vmovdqu $T3,-0x10($Htbl) # save Karatsuba "salt" +___ + &clmul64x64_avx ($Xhi,$Xi,$Hkey,$HK); # calculate H^3,5,7 + &reduction_avx ($Xhi,$Xi); +$code.=<<___; +.Linit_start_avx: + vmovdqa $Xi,$T3 +___ + &clmul64x64_avx ($Xhi,$Xi,$Hkey,$HK); # calculate H^2,4,6,8 + &reduction_avx ($Xhi,$Xi); +$code.=<<___; + vpshufd \$0b01001110,$T3,$T1 + vpshufd \$0b01001110,$Xi,$T2 + vpxor $T3,$T1,$T1 # Karatsuba pre-processing + vmovdqu $T3,0x00($Htbl) # save H^1,3,5,7 + vpxor $Xi,$T2,$T2 # Karatsuba pre-processing + vmovdqu $Xi,0x10($Htbl) # save H^2,4,6,8 + lea 0x30($Htbl),$Htbl + sub \$1,%r10 + jnz .Linit_loop_avx + + vpalignr \$8,$T2,$T1,$T3 # last "salt" is flipped + vmovdqu $T3,-0x10($Htbl) + + vzeroupper +___ +$code.=<<___ if ($win64); + movaps (%rsp),%xmm6 + lea 0x18(%rsp),%rsp +.LSEH_end_gcm_init_avx: +___ +$code.=<<___; + ret +.size gcm_init_avx,.-gcm_init_avx +___ +} else { +$code.=<<___; + jmp .L_init_clmul +.size gcm_init_avx,.-gcm_init_avx +___ +} + +$code.=<<___; +.globl gcm_gmult_avx +.type gcm_gmult_avx,\@abi-omnipotent +.align 32 +gcm_gmult_avx: + jmp .L_gmult_clmul +.size gcm_gmult_avx,.-gcm_gmult_avx +___ + +$code.=<<___; +.globl gcm_ghash_avx +.type gcm_ghash_avx,\@abi-omnipotent +.align 32 +gcm_ghash_avx: +___ +if ($avx) { +my ($Xip,$Htbl,$inp,$len)=@_4args; +my ($Xlo,$Xhi,$Xmi, + $Zlo,$Zhi,$Zmi, + $Hkey,$HK,$T1,$T2, + $Xi,$Xo,$Tred,$bswap,$Ii,$Ij) = map("%xmm$_",(0..15)); + +$code.=<<___ if ($win64); + lea -0x88(%rsp),%rax +.LSEH_begin_gcm_ghash_avx: + # I can't trust assembler to use specific encoding:-( + .byte 0x48,0x8d,0x60,0xe0 #lea -0x20(%rax),%rsp + .byte 0x0f,0x29,0x70,0xe0 #movaps %xmm6,-0x20(%rax) + .byte 0x0f,0x29,0x78,0xf0 #movaps %xmm7,-0x10(%rax) + .byte 0x44,0x0f,0x29,0x00 #movaps %xmm8,0(%rax) + .byte 0x44,0x0f,0x29,0x48,0x10 #movaps %xmm9,0x10(%rax) + .byte 0x44,0x0f,0x29,0x50,0x20 #movaps %xmm10,0x20(%rax) + .byte 0x44,0x0f,0x29,0x58,0x30 #movaps %xmm11,0x30(%rax) + .byte 0x44,0x0f,0x29,0x60,0x40 #movaps %xmm12,0x40(%rax) + .byte 0x44,0x0f,0x29,0x68,0x50 #movaps %xmm13,0x50(%rax) + .byte 0x44,0x0f,0x29,0x70,0x60 #movaps %xmm14,0x60(%rax) + .byte 0x44,0x0f,0x29,0x78,0x70 #movaps %xmm15,0x70(%rax) +___ +$code.=<<___; + vzeroupper + + vmovdqu ($Xip),$Xi # load $Xi + lea .L0x1c2_polynomial(%rip),%r10 + lea 0x40($Htbl),$Htbl # size optimization + vmovdqu .Lbswap_mask(%rip),$bswap + vpshufb $bswap,$Xi,$Xi + cmp \$0x80,$len + jb .Lshort_avx + sub \$0x80,$len + + vmovdqu 0x70($inp),$Ii # I[7] + vmovdqu 0x00-0x40($Htbl),$Hkey # $Hkey^1 + vpshufb $bswap,$Ii,$Ii + vmovdqu 0x20-0x40($Htbl),$HK + + vpunpckhqdq $Ii,$Ii,$T2 + vmovdqu 0x60($inp),$Ij # I[6] + vpclmulqdq \$0x00,$Hkey,$Ii,$Xlo + vpxor $Ii,$T2,$T2 + vpshufb $bswap,$Ij,$Ij + vpclmulqdq \$0x11,$Hkey,$Ii,$Xhi + vmovdqu 0x10-0x40($Htbl),$Hkey # $Hkey^2 + vpunpckhqdq $Ij,$Ij,$T1 + vmovdqu 0x50($inp),$Ii # I[5] + vpclmulqdq \$0x00,$HK,$T2,$Xmi + vpxor $Ij,$T1,$T1 + + vpshufb $bswap,$Ii,$Ii + vpclmulqdq \$0x00,$Hkey,$Ij,$Zlo + vpunpckhqdq $Ii,$Ii,$T2 + vpclmulqdq \$0x11,$Hkey,$Ij,$Zhi + vmovdqu 0x30-0x40($Htbl),$Hkey # $Hkey^3 + vpxor $Ii,$T2,$T2 + vmovdqu 0x40($inp),$Ij # I[4] + vpclmulqdq \$0x10,$HK,$T1,$Zmi + vmovdqu 0x50-0x40($Htbl),$HK + + vpshufb $bswap,$Ij,$Ij + vpxor $Xlo,$Zlo,$Zlo + vpclmulqdq \$0x00,$Hkey,$Ii,$Xlo + vpxor $Xhi,$Zhi,$Zhi + vpunpckhqdq $Ij,$Ij,$T1 + vpclmulqdq \$0x11,$Hkey,$Ii,$Xhi + vmovdqu 0x40-0x40($Htbl),$Hkey # $Hkey^4 + vpxor $Xmi,$Zmi,$Zmi + vpclmulqdq \$0x00,$HK,$T2,$Xmi + vpxor $Ij,$T1,$T1 + + vmovdqu 0x30($inp),$Ii # I[3] + vpxor $Zlo,$Xlo,$Xlo + vpclmulqdq \$0x00,$Hkey,$Ij,$Zlo + vpxor $Zhi,$Xhi,$Xhi + vpshufb $bswap,$Ii,$Ii + vpclmulqdq \$0x11,$Hkey,$Ij,$Zhi + vmovdqu 0x60-0x40($Htbl),$Hkey # $Hkey^5 + vpxor $Zmi,$Xmi,$Xmi + vpunpckhqdq $Ii,$Ii,$T2 + vpclmulqdq \$0x10,$HK,$T1,$Zmi + vmovdqu 0x80-0x40($Htbl),$HK + vpxor $Ii,$T2,$T2 + + vmovdqu 0x20($inp),$Ij # I[2] + vpxor $Xlo,$Zlo,$Zlo + vpclmulqdq \$0x00,$Hkey,$Ii,$Xlo + vpxor $Xhi,$Zhi,$Zhi + vpshufb $bswap,$Ij,$Ij + vpclmulqdq \$0x11,$Hkey,$Ii,$Xhi + vmovdqu 0x70-0x40($Htbl),$Hkey # $Hkey^6 + vpxor $Xmi,$Zmi,$Zmi + vpunpckhqdq $Ij,$Ij,$T1 + vpclmulqdq \$0x00,$HK,$T2,$Xmi + vpxor $Ij,$T1,$T1 + + vmovdqu 0x10($inp),$Ii # I[1] + vpxor $Zlo,$Xlo,$Xlo + vpclmulqdq \$0x00,$Hkey,$Ij,$Zlo + vpxor $Zhi,$Xhi,$Xhi + vpshufb $bswap,$Ii,$Ii + vpclmulqdq \$0x11,$Hkey,$Ij,$Zhi + vmovdqu 0x90-0x40($Htbl),$Hkey # $Hkey^7 + vpxor $Zmi,$Xmi,$Xmi + vpunpckhqdq $Ii,$Ii,$T2 + vpclmulqdq \$0x10,$HK,$T1,$Zmi + vmovdqu 0xb0-0x40($Htbl),$HK + vpxor $Ii,$T2,$T2 + + vmovdqu ($inp),$Ij # I[0] + vpxor $Xlo,$Zlo,$Zlo + vpclmulqdq \$0x00,$Hkey,$Ii,$Xlo + vpxor $Xhi,$Zhi,$Zhi + vpshufb $bswap,$Ij,$Ij + vpclmulqdq \$0x11,$Hkey,$Ii,$Xhi + vmovdqu 0xa0-0x40($Htbl),$Hkey # $Hkey^8 + vpxor $Xmi,$Zmi,$Zmi + vpclmulqdq \$0x10,$HK,$T2,$Xmi + + lea 0x80($inp),$inp + cmp \$0x80,$len + jb .Ltail_avx + + vpxor $Xi,$Ij,$Ij # accumulate $Xi + sub \$0x80,$len + jmp .Loop8x_avx + +.align 32 +.Loop8x_avx: + vpunpckhqdq $Ij,$Ij,$T1 + vmovdqu 0x70($inp),$Ii # I[7] + vpxor $Xlo,$Zlo,$Zlo + vpxor $Ij,$T1,$T1 + vpclmulqdq \$0x00,$Hkey,$Ij,$Xi + vpshufb $bswap,$Ii,$Ii + vpxor $Xhi,$Zhi,$Zhi + vpclmulqdq \$0x11,$Hkey,$Ij,$Xo + vmovdqu 0x00-0x40($Htbl),$Hkey # $Hkey^1 + vpunpckhqdq $Ii,$Ii,$T2 + vpxor $Xmi,$Zmi,$Zmi + vpclmulqdq \$0x00,$HK,$T1,$Tred + vmovdqu 0x20-0x40($Htbl),$HK + vpxor $Ii,$T2,$T2 + + vmovdqu 0x60($inp),$Ij # I[6] + vpclmulqdq \$0x00,$Hkey,$Ii,$Xlo + vpxor $Zlo,$Xi,$Xi # collect result + vpshufb $bswap,$Ij,$Ij + vpclmulqdq \$0x11,$Hkey,$Ii,$Xhi + vxorps $Zhi,$Xo,$Xo + vmovdqu 0x10-0x40($Htbl),$Hkey # $Hkey^2 + vpunpckhqdq $Ij,$Ij,$T1 + vpclmulqdq \$0x00,$HK, $T2,$Xmi + vpxor $Zmi,$Tred,$Tred + vxorps $Ij,$T1,$T1 + + vmovdqu 0x50($inp),$Ii # I[5] + vpxor $Xi,$Tred,$Tred # aggregated Karatsuba post-processing + vpclmulqdq \$0x00,$Hkey,$Ij,$Zlo + vpxor $Xo,$Tred,$Tred + vpslldq \$8,$Tred,$T2 + vpxor $Xlo,$Zlo,$Zlo + vpclmulqdq \$0x11,$Hkey,$Ij,$Zhi + vpsrldq \$8,$Tred,$Tred + vpxor $T2, $Xi, $Xi + vmovdqu 0x30-0x40($Htbl),$Hkey # $Hkey^3 + vpshufb $bswap,$Ii,$Ii + vxorps $Tred,$Xo, $Xo + vpxor $Xhi,$Zhi,$Zhi + vpunpckhqdq $Ii,$Ii,$T2 + vpclmulqdq \$0x10,$HK, $T1,$Zmi + vmovdqu 0x50-0x40($Htbl),$HK + vpxor $Ii,$T2,$T2 + vpxor $Xmi,$Zmi,$Zmi + + vmovdqu 0x40($inp),$Ij # I[4] + vpalignr \$8,$Xi,$Xi,$Tred # 1st phase + vpclmulqdq \$0x00,$Hkey,$Ii,$Xlo + vpshufb $bswap,$Ij,$Ij + vpxor $Zlo,$Xlo,$Xlo + vpclmulqdq \$0x11,$Hkey,$Ii,$Xhi + vmovdqu 0x40-0x40($Htbl),$Hkey # $Hkey^4 + vpunpckhqdq $Ij,$Ij,$T1 + vpxor $Zhi,$Xhi,$Xhi + vpclmulqdq \$0x00,$HK, $T2,$Xmi + vxorps $Ij,$T1,$T1 + vpxor $Zmi,$Xmi,$Xmi + + vmovdqu 0x30($inp),$Ii # I[3] + vpclmulqdq \$0x10,(%r10),$Xi,$Xi + vpclmulqdq \$0x00,$Hkey,$Ij,$Zlo + vpshufb $bswap,$Ii,$Ii + vpxor $Xlo,$Zlo,$Zlo + vpclmulqdq \$0x11,$Hkey,$Ij,$Zhi + vmovdqu 0x60-0x40($Htbl),$Hkey # $Hkey^5 + vpunpckhqdq $Ii,$Ii,$T2 + vpxor $Xhi,$Zhi,$Zhi + vpclmulqdq \$0x10,$HK, $T1,$Zmi + vmovdqu 0x80-0x40($Htbl),$HK + vpxor $Ii,$T2,$T2 + vpxor $Xmi,$Zmi,$Zmi + + vmovdqu 0x20($inp),$Ij # I[2] + vpclmulqdq \$0x00,$Hkey,$Ii,$Xlo + vpshufb $bswap,$Ij,$Ij + vpxor $Zlo,$Xlo,$Xlo + vpclmulqdq \$0x11,$Hkey,$Ii,$Xhi + vmovdqu 0x70-0x40($Htbl),$Hkey # $Hkey^6 + vpunpckhqdq $Ij,$Ij,$T1 + vpxor $Zhi,$Xhi,$Xhi + vpclmulqdq \$0x00,$HK, $T2,$Xmi + vpxor $Ij,$T1,$T1 + vpxor $Zmi,$Xmi,$Xmi + vxorps $Tred,$Xi,$Xi + + vmovdqu 0x10($inp),$Ii # I[1] + vpalignr \$8,$Xi,$Xi,$Tred # 2nd phase + vpclmulqdq \$0x00,$Hkey,$Ij,$Zlo + vpshufb $bswap,$Ii,$Ii + vpxor $Xlo,$Zlo,$Zlo + vpclmulqdq \$0x11,$Hkey,$Ij,$Zhi + vmovdqu 0x90-0x40($Htbl),$Hkey # $Hkey^7 + vpclmulqdq \$0x10,(%r10),$Xi,$Xi + vxorps $Xo,$Tred,$Tred + vpunpckhqdq $Ii,$Ii,$T2 + vpxor $Xhi,$Zhi,$Zhi + vpclmulqdq \$0x10,$HK, $T1,$Zmi + vmovdqu 0xb0-0x40($Htbl),$HK + vpxor $Ii,$T2,$T2 + vpxor $Xmi,$Zmi,$Zmi + + vmovdqu ($inp),$Ij # I[0] + vpclmulqdq \$0x00,$Hkey,$Ii,$Xlo + vpshufb $bswap,$Ij,$Ij + vpclmulqdq \$0x11,$Hkey,$Ii,$Xhi + vmovdqu 0xa0-0x40($Htbl),$Hkey # $Hkey^8 + vpxor $Tred,$Ij,$Ij + vpclmulqdq \$0x10,$HK, $T2,$Xmi + vpxor $Xi,$Ij,$Ij # accumulate $Xi + + lea 0x80($inp),$inp + sub \$0x80,$len + jnc .Loop8x_avx + + add \$0x80,$len + jmp .Ltail_no_xor_avx + +.align 32 +.Lshort_avx: + vmovdqu -0x10($inp,$len),$Ii # very last word + lea ($inp,$len),$inp + vmovdqu 0x00-0x40($Htbl),$Hkey # $Hkey^1 + vmovdqu 0x20-0x40($Htbl),$HK + vpshufb $bswap,$Ii,$Ij + + vmovdqa $Xlo,$Zlo # subtle way to zero $Zlo, + vmovdqa $Xhi,$Zhi # $Zhi and + vmovdqa $Xmi,$Zmi # $Zmi + sub \$0x10,$len + jz .Ltail_avx + + vpunpckhqdq $Ij,$Ij,$T1 + vpxor $Xlo,$Zlo,$Zlo + vpclmulqdq \$0x00,$Hkey,$Ij,$Xlo + vpxor $Ij,$T1,$T1 + vmovdqu -0x20($inp),$Ii + vpxor $Xhi,$Zhi,$Zhi + vpclmulqdq \$0x11,$Hkey,$Ij,$Xhi + vmovdqu 0x10-0x40($Htbl),$Hkey # $Hkey^2 + vpshufb $bswap,$Ii,$Ij + vpxor $Xmi,$Zmi,$Zmi + vpclmulqdq \$0x00,$HK,$T1,$Xmi + vpsrldq \$8,$HK,$HK + sub \$0x10,$len + jz .Ltail_avx + + vpunpckhqdq $Ij,$Ij,$T1 + vpxor $Xlo,$Zlo,$Zlo + vpclmulqdq \$0x00,$Hkey,$Ij,$Xlo + vpxor $Ij,$T1,$T1 + vmovdqu -0x30($inp),$Ii + vpxor $Xhi,$Zhi,$Zhi + vpclmulqdq \$0x11,$Hkey,$Ij,$Xhi + vmovdqu 0x30-0x40($Htbl),$Hkey # $Hkey^3 + vpshufb $bswap,$Ii,$Ij + vpxor $Xmi,$Zmi,$Zmi + vpclmulqdq \$0x00,$HK,$T1,$Xmi + vmovdqu 0x50-0x40($Htbl),$HK + sub \$0x10,$len + jz .Ltail_avx + + vpunpckhqdq $Ij,$Ij,$T1 + vpxor $Xlo,$Zlo,$Zlo + vpclmulqdq \$0x00,$Hkey,$Ij,$Xlo + vpxor $Ij,$T1,$T1 + vmovdqu -0x40($inp),$Ii + vpxor $Xhi,$Zhi,$Zhi + vpclmulqdq \$0x11,$Hkey,$Ij,$Xhi + vmovdqu 0x40-0x40($Htbl),$Hkey # $Hkey^4 + vpshufb $bswap,$Ii,$Ij + vpxor $Xmi,$Zmi,$Zmi + vpclmulqdq \$0x00,$HK,$T1,$Xmi + vpsrldq \$8,$HK,$HK + sub \$0x10,$len + jz .Ltail_avx + + vpunpckhqdq $Ij,$Ij,$T1 + vpxor $Xlo,$Zlo,$Zlo + vpclmulqdq \$0x00,$Hkey,$Ij,$Xlo + vpxor $Ij,$T1,$T1 + vmovdqu -0x50($inp),$Ii + vpxor $Xhi,$Zhi,$Zhi + vpclmulqdq \$0x11,$Hkey,$Ij,$Xhi + vmovdqu 0x60-0x40($Htbl),$Hkey # $Hkey^5 + vpshufb $bswap,$Ii,$Ij + vpxor $Xmi,$Zmi,$Zmi + vpclmulqdq \$0x00,$HK,$T1,$Xmi + vmovdqu 0x80-0x40($Htbl),$HK + sub \$0x10,$len + jz .Ltail_avx + + vpunpckhqdq $Ij,$Ij,$T1 + vpxor $Xlo,$Zlo,$Zlo + vpclmulqdq \$0x00,$Hkey,$Ij,$Xlo + vpxor $Ij,$T1,$T1 + vmovdqu -0x60($inp),$Ii + vpxor $Xhi,$Zhi,$Zhi + vpclmulqdq \$0x11,$Hkey,$Ij,$Xhi + vmovdqu 0x70-0x40($Htbl),$Hkey # $Hkey^6 + vpshufb $bswap,$Ii,$Ij + vpxor $Xmi,$Zmi,$Zmi + vpclmulqdq \$0x00,$HK,$T1,$Xmi + vpsrldq \$8,$HK,$HK + sub \$0x10,$len + jz .Ltail_avx + + vpunpckhqdq $Ij,$Ij,$T1 + vpxor $Xlo,$Zlo,$Zlo + vpclmulqdq \$0x00,$Hkey,$Ij,$Xlo + vpxor $Ij,$T1,$T1 + vmovdqu -0x70($inp),$Ii + vpxor $Xhi,$Zhi,$Zhi + vpclmulqdq \$0x11,$Hkey,$Ij,$Xhi + vmovdqu 0x90-0x40($Htbl),$Hkey # $Hkey^7 + vpshufb $bswap,$Ii,$Ij + vpxor $Xmi,$Zmi,$Zmi + vpclmulqdq \$0x00,$HK,$T1,$Xmi + vmovq 0xb8-0x40($Htbl),$HK + sub \$0x10,$len + jmp .Ltail_avx + +.align 32 +.Ltail_avx: + vpxor $Xi,$Ij,$Ij # accumulate $Xi +.Ltail_no_xor_avx: + vpunpckhqdq $Ij,$Ij,$T1 + vpxor $Xlo,$Zlo,$Zlo + vpclmulqdq \$0x00,$Hkey,$Ij,$Xlo + vpxor $Ij,$T1,$T1 + vpxor $Xhi,$Zhi,$Zhi + vpclmulqdq \$0x11,$Hkey,$Ij,$Xhi + vpxor $Xmi,$Zmi,$Zmi + vpclmulqdq \$0x00,$HK,$T1,$Xmi + + vmovdqu (%r10),$Tred + + vpxor $Xlo,$Zlo,$Xi + vpxor $Xhi,$Zhi,$Xo + vpxor $Xmi,$Zmi,$Zmi + + vpxor $Xi, $Zmi,$Zmi # aggregated Karatsuba post-processing + vpxor $Xo, $Zmi,$Zmi + vpslldq \$8, $Zmi,$T2 + vpsrldq \$8, $Zmi,$Zmi + vpxor $T2, $Xi, $Xi + vpxor $Zmi,$Xo, $Xo + + vpclmulqdq \$0x10,$Tred,$Xi,$T2 # 1st phase + vpalignr \$8,$Xi,$Xi,$Xi + vpxor $T2,$Xi,$Xi + + vpclmulqdq \$0x10,$Tred,$Xi,$T2 # 2nd phase + vpalignr \$8,$Xi,$Xi,$Xi + vpxor $Xo,$Xi,$Xi + vpxor $T2,$Xi,$Xi + + cmp \$0,$len + jne .Lshort_avx + + vpshufb $bswap,$Xi,$Xi + vmovdqu $Xi,($Xip) + vzeroupper +___ +$code.=<<___ if ($win64); + movaps (%rsp),%xmm6 + movaps 0x10(%rsp),%xmm7 + movaps 0x20(%rsp),%xmm8 + movaps 0x30(%rsp),%xmm9 + movaps 0x40(%rsp),%xmm10 + movaps 0x50(%rsp),%xmm11 + movaps 0x60(%rsp),%xmm12 + movaps 0x70(%rsp),%xmm13 + movaps 0x80(%rsp),%xmm14 + movaps 0x90(%rsp),%xmm15 + lea 0xa8(%rsp),%rsp +.LSEH_end_gcm_ghash_avx: +___ +$code.=<<___; + ret +.size gcm_ghash_avx,.-gcm_ghash_avx +___ +} else { +$code.=<<___; + jmp .L_ghash_clmul +.size gcm_ghash_avx,.-gcm_ghash_avx +___ +} + +$code.=<<___; +.align 64 +.Lbswap_mask: + .byte 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0 +.L0x1c2_polynomial: + .byte 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xc2 +.L7_mask: + .long 7,0,7,0 +.L7_mask_poly: + .long 7,0,`0xE1<<1`,0 +.align 64 +.type .Lrem_4bit,\@object +.Lrem_4bit: + .long 0,`0x0000<<16`,0,`0x1C20<<16`,0,`0x3840<<16`,0,`0x2460<<16` + .long 0,`0x7080<<16`,0,`0x6CA0<<16`,0,`0x48C0<<16`,0,`0x54E0<<16` + .long 0,`0xE100<<16`,0,`0xFD20<<16`,0,`0xD940<<16`,0,`0xC560<<16` + .long 0,`0x9180<<16`,0,`0x8DA0<<16`,0,`0xA9C0<<16`,0,`0xB5E0<<16` +.type .Lrem_8bit,\@object +.Lrem_8bit: + .value 0x0000,0x01C2,0x0384,0x0246,0x0708,0x06CA,0x048C,0x054E + .value 0x0E10,0x0FD2,0x0D94,0x0C56,0x0918,0x08DA,0x0A9C,0x0B5E + .value 0x1C20,0x1DE2,0x1FA4,0x1E66,0x1B28,0x1AEA,0x18AC,0x196E + .value 0x1230,0x13F2,0x11B4,0x1076,0x1538,0x14FA,0x16BC,0x177E + .value 0x3840,0x3982,0x3BC4,0x3A06,0x3F48,0x3E8A,0x3CCC,0x3D0E + .value 0x3650,0x3792,0x35D4,0x3416,0x3158,0x309A,0x32DC,0x331E + .value 0x2460,0x25A2,0x27E4,0x2626,0x2368,0x22AA,0x20EC,0x212E + .value 0x2A70,0x2BB2,0x29F4,0x2836,0x2D78,0x2CBA,0x2EFC,0x2F3E + .value 0x7080,0x7142,0x7304,0x72C6,0x7788,0x764A,0x740C,0x75CE + .value 0x7E90,0x7F52,0x7D14,0x7CD6,0x7998,0x785A,0x7A1C,0x7BDE + .value 0x6CA0,0x6D62,0x6F24,0x6EE6,0x6BA8,0x6A6A,0x682C,0x69EE + .value 0x62B0,0x6372,0x6134,0x60F6,0x65B8,0x647A,0x663C,0x67FE + .value 0x48C0,0x4902,0x4B44,0x4A86,0x4FC8,0x4E0A,0x4C4C,0x4D8E + .value 0x46D0,0x4712,0x4554,0x4496,0x41D8,0x401A,0x425C,0x439E + .value 0x54E0,0x5522,0x5764,0x56A6,0x53E8,0x522A,0x506C,0x51AE + .value 0x5AF0,0x5B32,0x5974,0x58B6,0x5DF8,0x5C3A,0x5E7C,0x5FBE + .value 0xE100,0xE0C2,0xE284,0xE346,0xE608,0xE7CA,0xE58C,0xE44E + .value 0xEF10,0xEED2,0xEC94,0xED56,0xE818,0xE9DA,0xEB9C,0xEA5E + .value 0xFD20,0xFCE2,0xFEA4,0xFF66,0xFA28,0xFBEA,0xF9AC,0xF86E + .value 0xF330,0xF2F2,0xF0B4,0xF176,0xF438,0xF5FA,0xF7BC,0xF67E + .value 0xD940,0xD882,0xDAC4,0xDB06,0xDE48,0xDF8A,0xDDCC,0xDC0E + .value 0xD750,0xD692,0xD4D4,0xD516,0xD058,0xD19A,0xD3DC,0xD21E + .value 0xC560,0xC4A2,0xC6E4,0xC726,0xC268,0xC3AA,0xC1EC,0xC02E + .value 0xCB70,0xCAB2,0xC8F4,0xC936,0xCC78,0xCDBA,0xCFFC,0xCE3E + .value 0x9180,0x9042,0x9204,0x93C6,0x9688,0x974A,0x950C,0x94CE + .value 0x9F90,0x9E52,0x9C14,0x9DD6,0x9898,0x995A,0x9B1C,0x9ADE + .value 0x8DA0,0x8C62,0x8E24,0x8FE6,0x8AA8,0x8B6A,0x892C,0x88EE + .value 0x83B0,0x8272,0x8034,0x81F6,0x84B8,0x857A,0x873C,0x86FE + .value 0xA9C0,0xA802,0xAA44,0xAB86,0xAEC8,0xAF0A,0xAD4C,0xAC8E + .value 0xA7D0,0xA612,0xA454,0xA596,0xA0D8,0xA11A,0xA35C,0xA29E + .value 0xB5E0,0xB422,0xB664,0xB7A6,0xB2E8,0xB32A,0xB16C,0xB0AE + .value 0xBBF0,0xBA32,0xB874,0xB9B6,0xBCF8,0xBD3A,0xBF7C,0xBEBE + +.asciz "GHASH for x86_64, CRYPTOGAMS by " +.align 64 +___ + +# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame, +# CONTEXT *context,DISPATCHER_CONTEXT *disp) +if ($win64) { +$rec="%rcx"; +$frame="%rdx"; +$context="%r8"; +$disp="%r9"; + +$code.=<<___; +.extern __imp_RtlVirtualUnwind +.type se_handler,\@abi-omnipotent +.align 16 +se_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + mov 8($disp),%rsi # disp->ImageBase + mov 56($disp),%r11 # disp->HandlerData + + mov 0(%r11),%r10d # HandlerData[0] + lea (%rsi,%r10),%r10 # prologue label + cmp %r10,%rbx # context->RipRsp + + mov 4(%r11),%r10d # HandlerData[1] + lea (%rsi,%r10),%r10 # epilogue label + cmp %r10,%rbx # context->Rip>=epilogue label + jae .Lin_prologue + + lea 24(%rax),%rax # adjust "rsp" + + mov -8(%rax),%rbx + mov -16(%rax),%rbp + mov -24(%rax),%r12 + mov %rbx,144($context) # restore context->Rbx + mov %rbp,160($context) # restore context->Rbp + mov %r12,216($context) # restore context->R12 + +.Lin_prologue: + mov 8(%rax),%rdi + mov 16(%rax),%rsi + mov %rax,152($context) # restore context->Rsp + mov %rsi,168($context) # restore context->Rsi + mov %rdi,176($context) # restore context->Rdi + + mov 40($disp),%rdi # disp->ContextRecord + mov $context,%rsi # context + mov \$`1232/8`,%ecx # sizeof(CONTEXT) + .long 0xa548f3fc # cld; rep movsq + + mov $disp,%rsi + xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER + mov 8(%rsi),%rdx # arg2, disp->ImageBase + mov 0(%rsi),%r8 # arg3, disp->ControlPc + mov 16(%rsi),%r9 # arg4, disp->FunctionEntry + mov 40(%rsi),%r10 # disp->ContextRecord + lea 56(%rsi),%r11 # &disp->HandlerData + lea 24(%rsi),%r12 # &disp->EstablisherFrame + mov %r10,32(%rsp) # arg5 + mov %r11,40(%rsp) # arg6 + mov %r12,48(%rsp) # arg7 + mov %rcx,56(%rsp) # arg8, (NULL) + call *__imp_RtlVirtualUnwind(%rip) + + mov \$1,%eax # ExceptionContinueSearch + add \$64,%rsp + popfq + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + pop %rdi + pop %rsi + ret +.size se_handler,.-se_handler + +.section .pdata +.align 4 + .rva .LSEH_begin_gcm_gmult_4bit + .rva .LSEH_end_gcm_gmult_4bit + .rva .LSEH_info_gcm_gmult_4bit + + .rva .LSEH_begin_gcm_ghash_4bit + .rva .LSEH_end_gcm_ghash_4bit + .rva .LSEH_info_gcm_ghash_4bit + + .rva .LSEH_begin_gcm_init_clmul + .rva .LSEH_end_gcm_init_clmul + .rva .LSEH_info_gcm_init_clmul + + .rva .LSEH_begin_gcm_ghash_clmul + .rva .LSEH_end_gcm_ghash_clmul + .rva .LSEH_info_gcm_ghash_clmul +___ +$code.=<<___ if ($avx); + .rva .LSEH_begin_gcm_init_avx + .rva .LSEH_end_gcm_init_avx + .rva .LSEH_info_gcm_init_clmul + + .rva .LSEH_begin_gcm_ghash_avx + .rva .LSEH_end_gcm_ghash_avx + .rva .LSEH_info_gcm_ghash_clmul +___ +$code.=<<___; +.section .xdata +.align 8 +.LSEH_info_gcm_gmult_4bit: + .byte 9,0,0,0 + .rva se_handler + .rva .Lgmult_prologue,.Lgmult_epilogue # HandlerData +.LSEH_info_gcm_ghash_4bit: + .byte 9,0,0,0 + .rva se_handler + .rva .Lghash_prologue,.Lghash_epilogue # HandlerData +.LSEH_info_gcm_init_clmul: + .byte 0x01,0x08,0x03,0x00 + .byte 0x08,0x68,0x00,0x00 #movaps 0x00(rsp),xmm6 + .byte 0x04,0x22,0x00,0x00 #sub rsp,0x18 +.LSEH_info_gcm_ghash_clmul: + .byte 0x01,0x33,0x16,0x00 + .byte 0x33,0xf8,0x09,0x00 #movaps 0x90(rsp),xmm15 + .byte 0x2e,0xe8,0x08,0x00 #movaps 0x80(rsp),xmm14 + .byte 0x29,0xd8,0x07,0x00 #movaps 0x70(rsp),xmm13 + .byte 0x24,0xc8,0x06,0x00 #movaps 0x60(rsp),xmm12 + .byte 0x1f,0xb8,0x05,0x00 #movaps 0x50(rsp),xmm11 + .byte 0x1a,0xa8,0x04,0x00 #movaps 0x40(rsp),xmm10 + .byte 0x15,0x98,0x03,0x00 #movaps 0x30(rsp),xmm9 + .byte 0x10,0x88,0x02,0x00 #movaps 0x20(rsp),xmm8 + .byte 0x0c,0x78,0x01,0x00 #movaps 0x10(rsp),xmm7 + .byte 0x08,0x68,0x00,0x00 #movaps 0x00(rsp),xmm6 + .byte 0x04,0x01,0x15,0x00 #sub rsp,0xa8 +___ +} + +$code =~ s/\`([^\`]*)\`/eval($1)/gem; + +print $code; + +close STDOUT; diff --git a/external/boringssl/crypto/modes/asm/ghashv8-armx.pl b/external/boringssl/crypto/modes/asm/ghashv8-armx.pl new file mode 100644 index 0000000000..3a7b8d8b01 --- /dev/null +++ b/external/boringssl/crypto/modes/asm/ghashv8-armx.pl @@ -0,0 +1,422 @@ +#!/usr/bin/env perl +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# GHASH for ARMv8 Crypto Extension, 64-bit polynomial multiplication. +# +# June 2014 +# +# Initial version was developed in tight cooperation with Ard +# Biesheuvel from bits-n-pieces from +# other assembly modules. Just like aesv8-armx.pl this module +# supports both AArch32 and AArch64 execution modes. +# +# July 2014 +# +# Implement 2x aggregated reduction [see ghash-x86.pl for background +# information]. +# +# Current performance in cycles per processed byte: +# +# PMULL[2] 32-bit NEON(*) +# Apple A7 0.92 5.62 +# Cortex-A53 1.01 8.39 +# Cortex-A57 1.17 7.61 +# Denver 0.71 6.02 +# +# (*) presented for reference/comparison purposes; + +$flavour = shift; +$output = shift; + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or +die "can't locate arm-xlate.pl"; + +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; + +$Xi="x0"; # argument block +$Htbl="x1"; +$inp="x2"; +$len="x3"; + +$inc="x12"; + +{ +my ($Xl,$Xm,$Xh,$IN)=map("q$_",(0..3)); +my ($t0,$t1,$t2,$xC2,$H,$Hhl,$H2)=map("q$_",(8..14)); + +$code=<<___; +#include + +.text +___ +$code.=<<___ if ($flavour =~ /64/); +#if !defined(__clang__) +.arch armv8-a+crypto +#endif +___ +$code.=".fpu neon\n.code 32\n" if ($flavour !~ /64/); + +################################################################################ +# void gcm_init_v8(u128 Htable[16],const u64 H[2]); +# +# input: 128-bit H - secret parameter E(K,0^128) +# output: precomputed table filled with degrees of twisted H; +# H is twisted to handle reverse bitness of GHASH; +# only few of 16 slots of Htable[16] are used; +# data is opaque to outside world (which allows to +# optimize the code independently); +# +$code.=<<___; +.global gcm_init_v8 +.type gcm_init_v8,%function +.align 4 +gcm_init_v8: + vld1.64 {$t1},[x1] @ load input H + vmov.i8 $xC2,#0xe1 + vshl.i64 $xC2,$xC2,#57 @ 0xc2.0 + vext.8 $IN,$t1,$t1,#8 + vshr.u64 $t2,$xC2,#63 + vdup.32 $t1,${t1}[1] + vext.8 $t0,$t2,$xC2,#8 @ t0=0xc2....01 + vshr.u64 $t2,$IN,#63 + vshr.s32 $t1,$t1,#31 @ broadcast carry bit + vand $t2,$t2,$t0 + vshl.i64 $IN,$IN,#1 + vext.8 $t2,$t2,$t2,#8 + vand $t0,$t0,$t1 + vorr $IN,$IN,$t2 @ H<<<=1 + veor $H,$IN,$t0 @ twisted H + vst1.64 {$H},[x0],#16 @ store Htable[0] + + @ calculate H^2 + vext.8 $t0,$H,$H,#8 @ Karatsuba pre-processing + vpmull.p64 $Xl,$H,$H + veor $t0,$t0,$H + vpmull2.p64 $Xh,$H,$H + vpmull.p64 $Xm,$t0,$t0 + + vext.8 $t1,$Xl,$Xh,#8 @ Karatsuba post-processing + veor $t2,$Xl,$Xh + veor $Xm,$Xm,$t1 + veor $Xm,$Xm,$t2 + vpmull.p64 $t2,$Xl,$xC2 @ 1st phase + + vmov $Xh#lo,$Xm#hi @ Xh|Xm - 256-bit result + vmov $Xm#hi,$Xl#lo @ Xm is rotated Xl + veor $Xl,$Xm,$t2 + + vext.8 $t2,$Xl,$Xl,#8 @ 2nd phase + vpmull.p64 $Xl,$Xl,$xC2 + veor $t2,$t2,$Xh + veor $H2,$Xl,$t2 + + vext.8 $t1,$H2,$H2,#8 @ Karatsuba pre-processing + veor $t1,$t1,$H2 + vext.8 $Hhl,$t0,$t1,#8 @ pack Karatsuba pre-processed + vst1.64 {$Hhl-$H2},[x0] @ store Htable[1..2] + + ret +.size gcm_init_v8,.-gcm_init_v8 +___ +################################################################################ +# void gcm_gmult_v8(u64 Xi[2],const u128 Htable[16]); +# +# input: Xi - current hash value; +# Htable - table precomputed in gcm_init_v8; +# output: Xi - next hash value Xi; +# +$code.=<<___; +.global gcm_gmult_v8 +.type gcm_gmult_v8,%function +.align 4 +gcm_gmult_v8: + vld1.64 {$t1},[$Xi] @ load Xi + vmov.i8 $xC2,#0xe1 + vld1.64 {$H-$Hhl},[$Htbl] @ load twisted H, ... + vshl.u64 $xC2,$xC2,#57 +#ifndef __ARMEB__ + vrev64.8 $t1,$t1 +#endif + vext.8 $IN,$t1,$t1,#8 + + vpmull.p64 $Xl,$H,$IN @ H.lo·Xi.lo + veor $t1,$t1,$IN @ Karatsuba pre-processing + vpmull2.p64 $Xh,$H,$IN @ H.hi·Xi.hi + vpmull.p64 $Xm,$Hhl,$t1 @ (H.lo+H.hi)·(Xi.lo+Xi.hi) + + vext.8 $t1,$Xl,$Xh,#8 @ Karatsuba post-processing + veor $t2,$Xl,$Xh + veor $Xm,$Xm,$t1 + veor $Xm,$Xm,$t2 + vpmull.p64 $t2,$Xl,$xC2 @ 1st phase of reduction + + vmov $Xh#lo,$Xm#hi @ Xh|Xm - 256-bit result + vmov $Xm#hi,$Xl#lo @ Xm is rotated Xl + veor $Xl,$Xm,$t2 + + vext.8 $t2,$Xl,$Xl,#8 @ 2nd phase of reduction + vpmull.p64 $Xl,$Xl,$xC2 + veor $t2,$t2,$Xh + veor $Xl,$Xl,$t2 + +#ifndef __ARMEB__ + vrev64.8 $Xl,$Xl +#endif + vext.8 $Xl,$Xl,$Xl,#8 + vst1.64 {$Xl},[$Xi] @ write out Xi + + ret +.size gcm_gmult_v8,.-gcm_gmult_v8 +___ +################################################################################ +# void gcm_ghash_v8(u64 Xi[2],const u128 Htable[16],const u8 *inp,size_t len); +# +# input: table precomputed in gcm_init_v8; +# current hash value Xi; +# pointer to input data; +# length of input data in bytes, but divisible by block size; +# output: next hash value Xi; +# +$code.=<<___; +.global gcm_ghash_v8 +.type gcm_ghash_v8,%function +.align 4 +gcm_ghash_v8: +___ +$code.=<<___ if ($flavour !~ /64/); + vstmdb sp!,{d8-d15} @ 32-bit ABI says so +___ +$code.=<<___; + vld1.64 {$Xl},[$Xi] @ load [rotated] Xi + @ "[rotated]" means that + @ loaded value would have + @ to be rotated in order to + @ make it appear as in + @ alorithm specification + subs $len,$len,#32 @ see if $len is 32 or larger + mov $inc,#16 @ $inc is used as post- + @ increment for input pointer; + @ as loop is modulo-scheduled + @ $inc is zeroed just in time + @ to preclude oversteping + @ inp[len], which means that + @ last block[s] are actually + @ loaded twice, but last + @ copy is not processed + vld1.64 {$H-$Hhl},[$Htbl],#32 @ load twisted H, ..., H^2 + vmov.i8 $xC2,#0xe1 + vld1.64 {$H2},[$Htbl] + cclr $inc,eq @ is it time to zero $inc? + vext.8 $Xl,$Xl,$Xl,#8 @ rotate Xi + vld1.64 {$t0},[$inp],#16 @ load [rotated] I[0] + vshl.u64 $xC2,$xC2,#57 @ compose 0xc2.0 constant +#ifndef __ARMEB__ + vrev64.8 $t0,$t0 + vrev64.8 $Xl,$Xl +#endif + vext.8 $IN,$t0,$t0,#8 @ rotate I[0] + b.lo .Lodd_tail_v8 @ $len was less than 32 +___ +{ my ($Xln,$Xmn,$Xhn,$In) = map("q$_",(4..7)); + ####### + # Xi+2 =[H*(Ii+1 + Xi+1)] mod P = + # [(H*Ii+1) + (H*Xi+1)] mod P = + # [(H*Ii+1) + H^2*(Ii+Xi)] mod P + # +$code.=<<___; + vld1.64 {$t1},[$inp],$inc @ load [rotated] I[1] +#ifndef __ARMEB__ + vrev64.8 $t1,$t1 +#endif + vext.8 $In,$t1,$t1,#8 + veor $IN,$IN,$Xl @ I[i]^=Xi + vpmull.p64 $Xln,$H,$In @ H·Ii+1 + veor $t1,$t1,$In @ Karatsuba pre-processing + vpmull2.p64 $Xhn,$H,$In + b .Loop_mod2x_v8 + +.align 4 +.Loop_mod2x_v8: + vext.8 $t2,$IN,$IN,#8 + subs $len,$len,#32 @ is there more data? + vpmull.p64 $Xl,$H2,$IN @ H^2.lo·Xi.lo + cclr $inc,lo @ is it time to zero $inc? + + vpmull.p64 $Xmn,$Hhl,$t1 + veor $t2,$t2,$IN @ Karatsuba pre-processing + vpmull2.p64 $Xh,$H2,$IN @ H^2.hi·Xi.hi + veor $Xl,$Xl,$Xln @ accumulate + vpmull2.p64 $Xm,$Hhl,$t2 @ (H^2.lo+H^2.hi)·(Xi.lo+Xi.hi) + vld1.64 {$t0},[$inp],$inc @ load [rotated] I[i+2] + + veor $Xh,$Xh,$Xhn + cclr $inc,eq @ is it time to zero $inc? + veor $Xm,$Xm,$Xmn + + vext.8 $t1,$Xl,$Xh,#8 @ Karatsuba post-processing + veor $t2,$Xl,$Xh + veor $Xm,$Xm,$t1 + vld1.64 {$t1},[$inp],$inc @ load [rotated] I[i+3] +#ifndef __ARMEB__ + vrev64.8 $t0,$t0 +#endif + veor $Xm,$Xm,$t2 + vpmull.p64 $t2,$Xl,$xC2 @ 1st phase of reduction + +#ifndef __ARMEB__ + vrev64.8 $t1,$t1 +#endif + vmov $Xh#lo,$Xm#hi @ Xh|Xm - 256-bit result + vmov $Xm#hi,$Xl#lo @ Xm is rotated Xl + vext.8 $In,$t1,$t1,#8 + vext.8 $IN,$t0,$t0,#8 + veor $Xl,$Xm,$t2 + vpmull.p64 $Xln,$H,$In @ H·Ii+1 + veor $IN,$IN,$Xh @ accumulate $IN early + + vext.8 $t2,$Xl,$Xl,#8 @ 2nd phase of reduction + vpmull.p64 $Xl,$Xl,$xC2 + veor $IN,$IN,$t2 + veor $t1,$t1,$In @ Karatsuba pre-processing + veor $IN,$IN,$Xl + vpmull2.p64 $Xhn,$H,$In + b.hs .Loop_mod2x_v8 @ there was at least 32 more bytes + + veor $Xh,$Xh,$t2 + vext.8 $IN,$t0,$t0,#8 @ re-construct $IN + adds $len,$len,#32 @ re-construct $len + veor $Xl,$Xl,$Xh @ re-construct $Xl + b.eq .Ldone_v8 @ is $len zero? +___ +} +$code.=<<___; +.Lodd_tail_v8: + vext.8 $t2,$Xl,$Xl,#8 + veor $IN,$IN,$Xl @ inp^=Xi + veor $t1,$t0,$t2 @ $t1 is rotated inp^Xi + + vpmull.p64 $Xl,$H,$IN @ H.lo·Xi.lo + veor $t1,$t1,$IN @ Karatsuba pre-processing + vpmull2.p64 $Xh,$H,$IN @ H.hi·Xi.hi + vpmull.p64 $Xm,$Hhl,$t1 @ (H.lo+H.hi)·(Xi.lo+Xi.hi) + + vext.8 $t1,$Xl,$Xh,#8 @ Karatsuba post-processing + veor $t2,$Xl,$Xh + veor $Xm,$Xm,$t1 + veor $Xm,$Xm,$t2 + vpmull.p64 $t2,$Xl,$xC2 @ 1st phase of reduction + + vmov $Xh#lo,$Xm#hi @ Xh|Xm - 256-bit result + vmov $Xm#hi,$Xl#lo @ Xm is rotated Xl + veor $Xl,$Xm,$t2 + + vext.8 $t2,$Xl,$Xl,#8 @ 2nd phase of reduction + vpmull.p64 $Xl,$Xl,$xC2 + veor $t2,$t2,$Xh + veor $Xl,$Xl,$t2 + +.Ldone_v8: +#ifndef __ARMEB__ + vrev64.8 $Xl,$Xl +#endif + vext.8 $Xl,$Xl,$Xl,#8 + vst1.64 {$Xl},[$Xi] @ write out Xi + +___ +$code.=<<___ if ($flavour !~ /64/); + vldmia sp!,{d8-d15} @ 32-bit ABI says so +___ +$code.=<<___; + ret +.size gcm_ghash_v8,.-gcm_ghash_v8 +___ +} +$code.=<<___; +.asciz "GHASH for ARMv8, CRYPTOGAMS by " +.align 2 +___ + +if ($flavour =~ /64/) { ######## 64-bit code + sub unvmov { + my $arg=shift; + + $arg =~ m/q([0-9]+)#(lo|hi),\s*q([0-9]+)#(lo|hi)/o && + sprintf "ins v%d.d[%d],v%d.d[%d]",$1,($2 eq "lo")?0:1,$3,($4 eq "lo")?0:1; + } + foreach(split("\n",$code)) { + s/cclr\s+([wx])([^,]+),\s*([a-z]+)/csel $1$2,$1zr,$1$2,$3/o or + s/vmov\.i8/movi/o or # fix up legacy mnemonics + s/vmov\s+(.*)/unvmov($1)/geo or + s/vext\.8/ext/o or + s/vshr\.s/sshr\.s/o or + s/vshr/ushr/o or + s/^(\s+)v/$1/o or # strip off v prefix + s/\bbx\s+lr\b/ret/o; + + s/\bq([0-9]+)\b/"v".($1<8?$1:$1+8).".16b"/geo; # old->new registers + s/@\s/\/\//o; # old->new style commentary + + # fix up remainig legacy suffixes + s/\.[ui]?8(\s)/$1/o; + s/\.[uis]?32//o and s/\.16b/\.4s/go; + m/\.p64/o and s/\.16b/\.1q/o; # 1st pmull argument + m/l\.p64/o and s/\.16b/\.1d/go; # 2nd and 3rd pmull arguments + s/\.[uisp]?64//o and s/\.16b/\.2d/go; + s/\.[42]([sd])\[([0-3])\]/\.$1\[$2\]/o; + + print $_,"\n"; + } +} else { ######## 32-bit code + sub unvdup32 { + my $arg=shift; + + $arg =~ m/q([0-9]+),\s*q([0-9]+)\[([0-3])\]/o && + sprintf "vdup.32 q%d,d%d[%d]",$1,2*$2+($3>>1),$3&1; + } + sub unvpmullp64 { + my ($mnemonic,$arg)=@_; + + if ($arg =~ m/q([0-9]+),\s*q([0-9]+),\s*q([0-9]+)/o) { + my $word = 0xf2a00e00|(($1&7)<<13)|(($1&8)<<19) + |(($2&7)<<17)|(($2&8)<<4) + |(($3&7)<<1) |(($3&8)<<2); + $word |= 0x00010001 if ($mnemonic =~ "2"); + # since ARMv7 instructions are always encoded little-endian. + # correct solution is to use .inst directive, but older + # assemblers don't implement it:-( + sprintf ".byte\t0x%02x,0x%02x,0x%02x,0x%02x\t@ %s %s", + $word&0xff,($word>>8)&0xff, + ($word>>16)&0xff,($word>>24)&0xff, + $mnemonic,$arg; + } + } + + foreach(split("\n",$code)) { + s/\b[wx]([0-9]+)\b/r$1/go; # new->old registers + s/\bv([0-9])\.[12468]+[bsd]\b/q$1/go; # new->old registers + s/\/\/\s?/@ /o; # new->old style commentary + + # fix up remainig new-style suffixes + s/\],#[0-9]+/]!/o; + + s/cclr\s+([^,]+),\s*([a-z]+)/mov$2 $1,#0/o or + s/vdup\.32\s+(.*)/unvdup32($1)/geo or + s/v?(pmull2?)\.p64\s+(.*)/unvpmullp64($1,$2)/geo or + s/\bq([0-9]+)#(lo|hi)/sprintf "d%d",2*$1+($2 eq "hi")/geo or + s/^(\s+)b\./$1b/o or + s/^(\s+)ret/$1bx\tlr/o; + + print $_,"\n"; + } +} + +close STDOUT; # enforce flush diff --git a/external/boringssl/crypto/modes/cbc.c b/external/boringssl/crypto/modes/cbc.c new file mode 100644 index 0000000000..e41f2b497f --- /dev/null +++ b/external/boringssl/crypto/modes/cbc.c @@ -0,0 +1,216 @@ +/* ==================================================================== + * Copyright (c) 2008 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== */ + +#include +#include + +#include "internal.h" + + +#ifndef STRICT_ALIGNMENT +# define STRICT_ALIGNMENT 0 +#endif + +void CRYPTO_cbc128_encrypt(const uint8_t *in, uint8_t *out, size_t len, + const void *key, uint8_t ivec[16], + block128_f block) { + size_t n; + const uint8_t *iv = ivec; + + assert(key != NULL && ivec != NULL); + assert(len == 0 || (in != NULL && out != NULL)); + + if (STRICT_ALIGNMENT && + ((size_t)in | (size_t)out | (size_t)ivec) % sizeof(size_t) != 0) { + while (len >= 16) { + for (n = 0; n < 16; ++n) { + out[n] = in[n] ^ iv[n]; + } + (*block)(out, out, key); + iv = out; + len -= 16; + in += 16; + out += 16; + } + } else { + while (len >= 16) { + for (n = 0; n < 16; n += sizeof(size_t)) { + *(size_t *)(out + n) = *(size_t *)(in + n) ^ *(size_t *)(iv + n); + } + (*block)(out, out, key); + iv = out; + len -= 16; + in += 16; + out += 16; + } + } + + while (len) { + for (n = 0; n < 16 && n < len; ++n) { + out[n] = in[n] ^ iv[n]; + } + for (; n < 16; ++n) { + out[n] = iv[n]; + } + (*block)(out, out, key); + iv = out; + if (len <= 16) { + break; + } + len -= 16; + in += 16; + out += 16; + } + + memcpy(ivec, iv, 16); +} + +void CRYPTO_cbc128_decrypt(const uint8_t *in, uint8_t *out, size_t len, + const void *key, uint8_t ivec[16], + block128_f block) { + size_t n; + union { + size_t t[16 / sizeof(size_t)]; + uint8_t c[16]; + } tmp; + + assert(key != NULL && ivec != NULL); + assert(len == 0 || (in != NULL && out != NULL)); + + const uintptr_t inptr = (uintptr_t) in; + const uintptr_t outptr = (uintptr_t) out; + /* If |in| and |out| alias, |in| must be ahead. */ + assert(inptr >= outptr || inptr + len <= outptr); + + if ((inptr >= 32 && outptr <= inptr - 32) || inptr < outptr) { + /* If |out| is at least two blocks behind |in| or completely disjoint, there + * is no need to decrypt to a temporary block. */ + const uint8_t *iv = ivec; + + if (STRICT_ALIGNMENT && + ((size_t)in | (size_t)out | (size_t)ivec) % sizeof(size_t) != 0) { + while (len >= 16) { + (*block)(in, out, key); + for (n = 0; n < 16; ++n) { + out[n] ^= iv[n]; + } + iv = in; + len -= 16; + in += 16; + out += 16; + } + } else if (16 % sizeof(size_t) == 0) { /* always true */ + while (len >= 16) { + size_t *out_t = (size_t *)out, *iv_t = (size_t *)iv; + + (*block)(in, out, key); + for (n = 0; n < 16 / sizeof(size_t); n++) { + out_t[n] ^= iv_t[n]; + } + iv = in; + len -= 16; + in += 16; + out += 16; + } + } + memcpy(ivec, iv, 16); + } else { + /* |out| is less than two blocks behind |in|. Decrypting an input block + * directly to |out| would overwrite a ciphertext block before it is used as + * the next block's IV. Decrypt to a temporary block instead. */ + if (STRICT_ALIGNMENT && + ((size_t)in | (size_t)out | (size_t)ivec) % sizeof(size_t) != 0) { + uint8_t c; + while (len >= 16) { + (*block)(in, tmp.c, key); + for (n = 0; n < 16; ++n) { + c = in[n]; + out[n] = tmp.c[n] ^ ivec[n]; + ivec[n] = c; + } + len -= 16; + in += 16; + out += 16; + } + } else if (16 % sizeof(size_t) == 0) { /* always true */ + while (len >= 16) { + size_t c, *out_t = (size_t *)out, *ivec_t = (size_t *)ivec; + const size_t *in_t = (const size_t *)in; + + (*block)(in, tmp.c, key); + for (n = 0; n < 16 / sizeof(size_t); n++) { + c = in_t[n]; + out_t[n] = tmp.t[n] ^ ivec_t[n]; + ivec_t[n] = c; + } + len -= 16; + in += 16; + out += 16; + } + } + } + + while (len) { + uint8_t c; + (*block)(in, tmp.c, key); + for (n = 0; n < 16 && n < len; ++n) { + c = in[n]; + out[n] = tmp.c[n] ^ ivec[n]; + ivec[n] = c; + } + if (len <= 16) { + for (; n < 16; ++n) { + ivec[n] = in[n]; + } + break; + } + len -= 16; + in += 16; + out += 16; + } +} diff --git a/external/boringssl/crypto/modes/cfb.c b/external/boringssl/crypto/modes/cfb.c new file mode 100644 index 0000000000..51b883e8d4 --- /dev/null +++ b/external/boringssl/crypto/modes/cfb.c @@ -0,0 +1,230 @@ +/* ==================================================================== + * Copyright (c) 2008 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== */ + +#include + +#include +#include + +#include "internal.h" + + +OPENSSL_COMPILE_ASSERT((16 % sizeof(size_t)) == 0, bad_size_t_size); + +void CRYPTO_cfb128_encrypt(const uint8_t *in, uint8_t *out, size_t len, + const void *key, uint8_t ivec[16], unsigned *num, + int enc, block128_f block) { + size_t l = 0; + + assert(in && out && key && ivec && num); + + unsigned n = *num; + + if (enc) { + while (n && len) { + *(out++) = ivec[n] ^= *(in++); + --len; + n = (n + 1) % 16; + } +#if STRICT_ALIGNMENT + if (((size_t)in | (size_t)out | (size_t)ivec) % sizeof(size_t) != 0) { + while (l < len) { + if (n == 0) { + (*block)(ivec, ivec, key); + } + out[l] = ivec[n] ^= in[l]; + ++l; + n = (n + 1) % 16; + } + *num = n; + return; + } +#endif + while (len >= 16) { + (*block)(ivec, ivec, key); + for (; n < 16; n += sizeof(size_t)) { + *(size_t *)(out + n) = *(size_t *)(ivec + n) ^= *(size_t *)(in + n); + } + len -= 16; + out += 16; + in += 16; + n = 0; + } + if (len) { + (*block)(ivec, ivec, key); + while (len--) { + out[n] = ivec[n] ^= in[n]; + ++n; + } + } + *num = n; + return; + } else { + while (n && len) { + uint8_t c; + *(out++) = ivec[n] ^ (c = *(in++)); + ivec[n] = c; + --len; + n = (n + 1) % 16; + } + if (STRICT_ALIGNMENT && ((size_t)in | (size_t)out | (size_t)ivec) % sizeof(size_t) != 0) { + while (l < len) { + unsigned char c; + if (n == 0) { + (*block)(ivec, ivec, key); + } + out[l] = ivec[n] ^ (c = in[l]); + ivec[n] = c; + ++l; + n = (n + 1) % 16; + } + *num = n; + return; + } + while (len >= 16) { + (*block)(ivec, ivec, key); + for (; n < 16; n += sizeof(size_t)) { + size_t t = *(size_t *)(in + n); + *(size_t *)(out + n) = *(size_t *)(ivec + n) ^ t; + *(size_t *)(ivec + n) = t; + } + len -= 16; + out += 16; + in += 16; + n = 0; + } + if (len) { + (*block)(ivec, ivec, key); + while (len--) { + uint8_t c; + out[n] = ivec[n] ^ (c = in[n]); + ivec[n] = c; + ++n; + } + } + *num = n; + return; + } +} + + +/* This expects a single block of size nbits for both in and out. Note that + it corrupts any extra bits in the last byte of out */ +static void cfbr_encrypt_block(const uint8_t *in, uint8_t *out, unsigned nbits, + const void *key, uint8_t ivec[16], int enc, + block128_f block) { + int n, rem, num; + uint8_t ovec[16 * 2 + 1]; /* +1 because we dererefence (but don't use) one + byte off the end */ + + if (nbits <= 0 || nbits > 128) { + return; + } + + /* fill in the first half of the new IV with the current IV */ + memcpy(ovec, ivec, 16); + /* construct the new IV */ + (*block)(ivec, ivec, key); + num = (nbits + 7) / 8; + if (enc) { + /* encrypt the input */ + for (n = 0; n < num; ++n) { + out[n] = (ovec[16 + n] = in[n] ^ ivec[n]); + } + } else { + /* decrypt the input */ + for (n = 0; n < num; ++n) { + out[n] = (ovec[16 + n] = in[n]) ^ ivec[n]; + } + } + /* shift ovec left... */ + rem = nbits % 8; + num = nbits / 8; + if (rem == 0) { + memcpy(ivec, ovec + num, 16); + } else { + for (n = 0; n < 16; ++n) { + ivec[n] = ovec[n + num] << rem | ovec[n + num + 1] >> (8 - rem); + } + } + + /* it is not necessary to cleanse ovec, since the IV is not secret */ +} + +/* N.B. This expects the input to be packed, MS bit first */ +void CRYPTO_cfb128_1_encrypt(const uint8_t *in, uint8_t *out, size_t bits, + const void *key, uint8_t ivec[16], unsigned *num, + int enc, block128_f block) { + size_t n; + uint8_t c[1], d[1]; + + assert(in && out && key && ivec && num); + assert(*num == 0); + + for (n = 0; n < bits; ++n) { + c[0] = (in[n / 8] & (1 << (7 - n % 8))) ? 0x80 : 0; + cfbr_encrypt_block(c, d, 1, key, ivec, enc, block); + out[n / 8] = (out[n / 8] & ~(1 << (unsigned int)(7 - n % 8))) | + ((d[0] & 0x80) >> (unsigned int)(n % 8)); + } +} + +void CRYPTO_cfb128_8_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const void *key, + unsigned char ivec[16], unsigned *num, int enc, + block128_f block) { + size_t n; + + assert(in && out && key && ivec && num); + assert(*num == 0); + + for (n = 0; n < length; ++n) { + cfbr_encrypt_block(&in[n], &out[n], 8, key, ivec, enc, block); + } +} + diff --git a/external/boringssl/crypto/modes/ctr.c b/external/boringssl/crypto/modes/ctr.c new file mode 100644 index 0000000000..b84e72c59a --- /dev/null +++ b/external/boringssl/crypto/modes/ctr.c @@ -0,0 +1,219 @@ +/* ==================================================================== + * Copyright (c) 2008 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== */ + +#include + +#include +#include + +#include "internal.h" + + +/* NOTE: the IV/counter CTR mode is big-endian. The code itself + * is endian-neutral. */ + +/* increment counter (128-bit int) by 1 */ +static void ctr128_inc(uint8_t *counter) { + uint32_t n = 16, c = 1; + + do { + --n; + c += counter[n]; + counter[n] = (uint8_t) c; + c >>= 8; + } while (n); +} + +OPENSSL_COMPILE_ASSERT((16 % sizeof(size_t)) == 0, bad_size_t_size); + +/* The input encrypted as though 128bit counter mode is being used. The extra + * state information to record how much of the 128bit block we have used is + * contained in *num, and the encrypted counter is kept in ecount_buf. Both + * *num and ecount_buf must be initialised with zeros before the first call to + * CRYPTO_ctr128_encrypt(). + * + * This algorithm assumes that the counter is in the x lower bits of the IV + * (ivec), and that the application has full control over overflow and the rest + * of the IV. This implementation takes NO responsibility for checking that + * the counter doesn't overflow into the rest of the IV when incremented. */ +void CRYPTO_ctr128_encrypt(const uint8_t *in, uint8_t *out, size_t len, + const void *key, uint8_t ivec[16], + uint8_t ecount_buf[16], unsigned int *num, + block128_f block) { + unsigned int n; + + assert(key && ecount_buf && num); + assert(len == 0 || (in && out)); + assert(*num < 16); + + n = *num; + + while (n && len) { + *(out++) = *(in++) ^ ecount_buf[n]; + --len; + n = (n + 1) % 16; + } + +#if STRICT_ALIGNMENT + if (((size_t)in | (size_t)out | (size_t)ecount_buf) % sizeof(size_t) != 0) { + size_t l = 0; + while (l < len) { + if (n == 0) { + (*block)(ivec, ecount_buf, key); + ctr128_inc(ivec); + } + out[l] = in[l] ^ ecount_buf[n]; + ++l; + n = (n + 1) % 16; + } + + *num = n; + return; + } +#endif + + while (len >= 16) { + (*block)(ivec, ecount_buf, key); + ctr128_inc(ivec); + for (n = 0; n < 16; n += sizeof(size_t)) { + *(size_t *)(out + n) = *(const size_t *)(in + n) ^ + *(const size_t *)(ecount_buf + n); + } + len -= 16; + out += 16; + in += 16; + n = 0; + } + if (len) { + (*block)(ivec, ecount_buf, key); + ctr128_inc(ivec); + while (len--) { + out[n] = in[n] ^ ecount_buf[n]; + ++n; + } + } + *num = n; +} + +/* increment upper 96 bits of 128-bit counter by 1 */ +static void ctr96_inc(uint8_t *counter) { + uint32_t n = 12, c = 1; + + do { + --n; + c += counter[n]; + counter[n] = (uint8_t) c; + c >>= 8; + } while (n); +} + +void CRYPTO_ctr128_encrypt_ctr32(const uint8_t *in, uint8_t *out, + size_t len, const void *key, + uint8_t ivec[16], + uint8_t ecount_buf[16], + unsigned int *num, ctr128_f func) { + unsigned int n, ctr32; + + assert(key && ecount_buf && num); + assert(len == 0 || (in && out)); + assert(*num < 16); + + n = *num; + + while (n && len) { + *(out++) = *(in++) ^ ecount_buf[n]; + --len; + n = (n + 1) % 16; + } + + ctr32 = GETU32(ivec + 12); + while (len >= 16) { + size_t blocks = len / 16; + /* 1<<28 is just a not-so-small yet not-so-large number... + * Below condition is practically never met, but it has to + * be checked for code correctness. */ + if (sizeof(size_t) > sizeof(unsigned int) && blocks > (1U << 28)) { + blocks = (1U << 28); + } + /* As (*func) operates on 32-bit counter, caller + * has to handle overflow. 'if' below detects the + * overflow, which is then handled by limiting the + * amount of blocks to the exact overflow point... */ + ctr32 += (uint32_t)blocks; + if (ctr32 < blocks) { + blocks -= ctr32; + ctr32 = 0; + } + (*func)(in, out, blocks, key, ivec); + /* (*func) does not update ivec, caller does: */ + PUTU32(ivec + 12, ctr32); + /* ... overflow was detected, propogate carry. */ + if (ctr32 == 0) { + ctr96_inc(ivec); + } + blocks *= 16; + len -= blocks; + out += blocks; + in += blocks; + } + if (len) { + memset(ecount_buf, 0, 16); + (*func)(ecount_buf, ecount_buf, 1, key, ivec); + ++ctr32; + PUTU32(ivec + 12, ctr32); + if (ctr32 == 0) { + ctr96_inc(ivec); + } + while (len--) { + out[n] = in[n] ^ ecount_buf[n]; + ++n; + } + } + + *num = n; +} diff --git a/external/boringssl/crypto/modes/gcm.c b/external/boringssl/crypto/modes/gcm.c new file mode 100644 index 0000000000..b8571313d4 --- /dev/null +++ b/external/boringssl/crypto/modes/gcm.c @@ -0,0 +1,1272 @@ +/* ==================================================================== + * Copyright (c) 2008 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== */ + +#include + +#include +#include + +#include +#include + +#include "internal.h" +#include "../internal.h" + + +#if !defined(OPENSSL_NO_ASM) && \ + (defined(OPENSSL_X86) || defined(OPENSSL_X86_64) || \ + defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)) +#define GHASH_ASM +#endif + +#if defined(BSWAP4) && STRICT_ALIGNMENT == 1 +/* redefine, because alignment is ensured */ +#undef GETU32 +#define GETU32(p) BSWAP4(*(const uint32_t *)(p)) +#undef PUTU32 +#define PUTU32(p, v) *(uint32_t *)(p) = BSWAP4(v) +#endif + +#define PACK(s) ((size_t)(s) << (sizeof(size_t) * 8 - 16)) +#define REDUCE1BIT(V) \ + do { \ + if (sizeof(size_t) == 8) { \ + uint64_t T = UINT64_C(0xe100000000000000) & (0 - (V.lo & 1)); \ + V.lo = (V.hi << 63) | (V.lo >> 1); \ + V.hi = (V.hi >> 1) ^ T; \ + } else { \ + uint32_t T = 0xe1000000U & (0 - (uint32_t)(V.lo & 1)); \ + V.lo = (V.hi << 63) | (V.lo >> 1); \ + V.hi = (V.hi >> 1) ^ ((uint64_t)T << 32); \ + } \ + } while (0) + +// kSizeTWithoutLower4Bits is a mask that can be used to zero the lower four +// bits of a |size_t|. +static const size_t kSizeTWithoutLower4Bits = (size_t) -16; + +static void gcm_init_4bit(u128 Htable[16], uint64_t H[2]) { + u128 V; + + Htable[0].hi = 0; + Htable[0].lo = 0; + V.hi = H[0]; + V.lo = H[1]; + + Htable[8] = V; + REDUCE1BIT(V); + Htable[4] = V; + REDUCE1BIT(V); + Htable[2] = V; + REDUCE1BIT(V); + Htable[1] = V; + Htable[3].hi = V.hi ^ Htable[2].hi, Htable[3].lo = V.lo ^ Htable[2].lo; + V = Htable[4]; + Htable[5].hi = V.hi ^ Htable[1].hi, Htable[5].lo = V.lo ^ Htable[1].lo; + Htable[6].hi = V.hi ^ Htable[2].hi, Htable[6].lo = V.lo ^ Htable[2].lo; + Htable[7].hi = V.hi ^ Htable[3].hi, Htable[7].lo = V.lo ^ Htable[3].lo; + V = Htable[8]; + Htable[9].hi = V.hi ^ Htable[1].hi, Htable[9].lo = V.lo ^ Htable[1].lo; + Htable[10].hi = V.hi ^ Htable[2].hi, Htable[10].lo = V.lo ^ Htable[2].lo; + Htable[11].hi = V.hi ^ Htable[3].hi, Htable[11].lo = V.lo ^ Htable[3].lo; + Htable[12].hi = V.hi ^ Htable[4].hi, Htable[12].lo = V.lo ^ Htable[4].lo; + Htable[13].hi = V.hi ^ Htable[5].hi, Htable[13].lo = V.lo ^ Htable[5].lo; + Htable[14].hi = V.hi ^ Htable[6].hi, Htable[14].lo = V.lo ^ Htable[6].lo; + Htable[15].hi = V.hi ^ Htable[7].hi, Htable[15].lo = V.lo ^ Htable[7].lo; + +#if defined(GHASH_ASM) && defined(OPENSSL_ARM) + /* ARM assembler expects specific dword order in Htable. */ + { + int j; + const union { + long one; + char little; + } is_endian = {1}; + + if (is_endian.little) { + for (j = 0; j < 16; ++j) { + V = Htable[j]; + Htable[j].hi = V.lo; + Htable[j].lo = V.hi; + } + } else { + for (j = 0; j < 16; ++j) { + V = Htable[j]; + Htable[j].hi = V.lo << 32 | V.lo >> 32; + Htable[j].lo = V.hi << 32 | V.hi >> 32; + } + } + } +#endif +} + +#if !defined(GHASH_ASM) || defined(OPENSSL_AARCH64) +static const size_t rem_4bit[16] = { + PACK(0x0000), PACK(0x1C20), PACK(0x3840), PACK(0x2460), + PACK(0x7080), PACK(0x6CA0), PACK(0x48C0), PACK(0x54E0), + PACK(0xE100), PACK(0xFD20), PACK(0xD940), PACK(0xC560), + PACK(0x9180), PACK(0x8DA0), PACK(0xA9C0), PACK(0xB5E0)}; + +static void gcm_gmult_4bit(uint64_t Xi[2], const u128 Htable[16]) { + u128 Z; + int cnt = 15; + size_t rem, nlo, nhi; + const union { + long one; + char little; + } is_endian = {1}; + + nlo = ((const uint8_t *)Xi)[15]; + nhi = nlo >> 4; + nlo &= 0xf; + + Z.hi = Htable[nlo].hi; + Z.lo = Htable[nlo].lo; + + while (1) { + rem = (size_t)Z.lo & 0xf; + Z.lo = (Z.hi << 60) | (Z.lo >> 4); + Z.hi = (Z.hi >> 4); + if (sizeof(size_t) == 8) { + Z.hi ^= rem_4bit[rem]; + } else { + Z.hi ^= (uint64_t)rem_4bit[rem] << 32; + } + + Z.hi ^= Htable[nhi].hi; + Z.lo ^= Htable[nhi].lo; + + if (--cnt < 0) { + break; + } + + nlo = ((const uint8_t *)Xi)[cnt]; + nhi = nlo >> 4; + nlo &= 0xf; + + rem = (size_t)Z.lo & 0xf; + Z.lo = (Z.hi << 60) | (Z.lo >> 4); + Z.hi = (Z.hi >> 4); + if (sizeof(size_t) == 8) { + Z.hi ^= rem_4bit[rem]; + } else { + Z.hi ^= (uint64_t)rem_4bit[rem] << 32; + } + + Z.hi ^= Htable[nlo].hi; + Z.lo ^= Htable[nlo].lo; + } + + if (is_endian.little) { +#ifdef BSWAP8 + Xi[0] = BSWAP8(Z.hi); + Xi[1] = BSWAP8(Z.lo); +#else + uint8_t *p = (uint8_t *)Xi; + uint32_t v; + v = (uint32_t)(Z.hi >> 32); + PUTU32(p, v); + v = (uint32_t)(Z.hi); + PUTU32(p + 4, v); + v = (uint32_t)(Z.lo >> 32); + PUTU32(p + 8, v); + v = (uint32_t)(Z.lo); + PUTU32(p + 12, v); +#endif + } else { + Xi[0] = Z.hi; + Xi[1] = Z.lo; + } +} + +/* Streamed gcm_mult_4bit, see CRYPTO_gcm128_[en|de]crypt for + * details... Compiler-generated code doesn't seem to give any + * performance improvement, at least not on x86[_64]. It's here + * mostly as reference and a placeholder for possible future + * non-trivial optimization[s]... */ +static void gcm_ghash_4bit(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp, + size_t len) { + u128 Z; + int cnt; + size_t rem, nlo, nhi; + const union { + long one; + char little; + } is_endian = {1}; + + do { + cnt = 15; + nlo = ((const uint8_t *)Xi)[15]; + nlo ^= inp[15]; + nhi = nlo >> 4; + nlo &= 0xf; + + Z.hi = Htable[nlo].hi; + Z.lo = Htable[nlo].lo; + + while (1) { + rem = (size_t)Z.lo & 0xf; + Z.lo = (Z.hi << 60) | (Z.lo >> 4); + Z.hi = (Z.hi >> 4); + if (sizeof(size_t) == 8) { + Z.hi ^= rem_4bit[rem]; + } else { + Z.hi ^= (uint64_t)rem_4bit[rem] << 32; + } + + Z.hi ^= Htable[nhi].hi; + Z.lo ^= Htable[nhi].lo; + + if (--cnt < 0) { + break; + } + + nlo = ((const uint8_t *)Xi)[cnt]; + nlo ^= inp[cnt]; + nhi = nlo >> 4; + nlo &= 0xf; + + rem = (size_t)Z.lo & 0xf; + Z.lo = (Z.hi << 60) | (Z.lo >> 4); + Z.hi = (Z.hi >> 4); + if (sizeof(size_t) == 8) { + Z.hi ^= rem_4bit[rem]; + } else { + Z.hi ^= (uint64_t)rem_4bit[rem] << 32; + } + + Z.hi ^= Htable[nlo].hi; + Z.lo ^= Htable[nlo].lo; + } + + if (is_endian.little) { +#ifdef BSWAP8 + Xi[0] = BSWAP8(Z.hi); + Xi[1] = BSWAP8(Z.lo); +#else + uint8_t *p = (uint8_t *)Xi; + uint32_t v; + v = (uint32_t)(Z.hi >> 32); + PUTU32(p, v); + v = (uint32_t)(Z.hi); + PUTU32(p + 4, v); + v = (uint32_t)(Z.lo >> 32); + PUTU32(p + 8, v); + v = (uint32_t)(Z.lo); + PUTU32(p + 12, v); +#endif + } else { + Xi[0] = Z.hi; + Xi[1] = Z.lo; + } + } while (inp += 16, len -= 16); +} +#else /* GHASH_ASM */ +void gcm_gmult_4bit(uint64_t Xi[2], const u128 Htable[16]); +void gcm_ghash_4bit(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp, + size_t len); +#endif + +#define GCM_MUL(ctx, Xi) gcm_gmult_4bit(ctx->Xi.u, ctx->Htable) +#if defined(GHASH_ASM) +#define GHASH(ctx, in, len) gcm_ghash_4bit((ctx)->Xi.u, (ctx)->Htable, in, len) +/* GHASH_CHUNK is "stride parameter" missioned to mitigate cache + * trashing effect. In other words idea is to hash data while it's + * still in L1 cache after encryption pass... */ +#define GHASH_CHUNK (3 * 1024) +#endif + + +#if defined(GHASH_ASM) +#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64) +#define GHASH_ASM_X86_OR_64 +#define GCM_FUNCREF_4BIT +void gcm_init_clmul(u128 Htable[16], const uint64_t Xi[2]); +void gcm_gmult_clmul(uint64_t Xi[2], const u128 Htable[16]); +void gcm_ghash_clmul(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp, + size_t len); + +#if defined(OPENSSL_X86) +#define gcm_init_avx gcm_init_clmul +#define gcm_gmult_avx gcm_gmult_clmul +#define gcm_ghash_avx gcm_ghash_clmul +#else +void gcm_init_avx(u128 Htable[16], const uint64_t Xi[2]); +void gcm_gmult_avx(uint64_t Xi[2], const u128 Htable[16]); +void gcm_ghash_avx(uint64_t Xi[2], const u128 Htable[16], const uint8_t *in, + size_t len); +#define AESNI_GCM +static int aesni_gcm_enabled(GCM128_CONTEXT *ctx, ctr128_f stream) { + return stream == aesni_ctr32_encrypt_blocks && + ctx->ghash == gcm_ghash_avx; +} + +size_t aesni_gcm_encrypt(const uint8_t *in, uint8_t *out, size_t len, + const void *key, uint8_t ivec[16], uint64_t *Xi); +size_t aesni_gcm_decrypt(const uint8_t *in, uint8_t *out, size_t len, + const void *key, uint8_t ivec[16], uint64_t *Xi); +#endif + +#if defined(OPENSSL_X86) +#define GHASH_ASM_X86 +void gcm_gmult_4bit_mmx(uint64_t Xi[2], const u128 Htable[16]); +void gcm_ghash_4bit_mmx(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp, + size_t len); + +void gcm_gmult_4bit_x86(uint64_t Xi[2], const u128 Htable[16]); +void gcm_ghash_4bit_x86(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp, + size_t len); +#endif +#elif defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64) +#include +#if __ARM_ARCH__ >= 7 +#define GHASH_ASM_ARM +#define GCM_FUNCREF_4BIT + +static int pmull_capable(void) { + return CRYPTO_is_ARMv8_PMULL_capable(); +} + +void gcm_init_v8(u128 Htable[16], const uint64_t Xi[2]); +void gcm_gmult_v8(uint64_t Xi[2], const u128 Htable[16]); +void gcm_ghash_v8(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp, + size_t len); + +#if defined(OPENSSL_ARM) +/* 32-bit ARM also has support for doing GCM with NEON instructions. */ +static int neon_capable(void) { + return CRYPTO_is_NEON_capable(); +} + +void gcm_init_neon(u128 Htable[16], const uint64_t Xi[2]); +void gcm_gmult_neon(uint64_t Xi[2], const u128 Htable[16]); +void gcm_ghash_neon(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp, + size_t len); +#else +/* AArch64 only has the ARMv8 versions of functions. */ +static int neon_capable(void) { + return 0; +} +static void gcm_init_neon(u128 Htable[16], const uint64_t Xi[2]) { + abort(); +} +static void gcm_gmult_neon(uint64_t Xi[2], const u128 Htable[16]) { + abort(); +} +static void gcm_ghash_neon(uint64_t Xi[2], const u128 Htable[16], + const uint8_t *inp, size_t len) { + abort(); +} +#endif + +#endif +#endif +#endif + +#ifdef GCM_FUNCREF_4BIT +#undef GCM_MUL +#define GCM_MUL(ctx, Xi) (*gcm_gmult_p)(ctx->Xi.u, ctx->Htable) +#ifdef GHASH +#undef GHASH +#define GHASH(ctx, in, len) (*gcm_ghash_p)(ctx->Xi.u, ctx->Htable, in, len) +#endif +#endif + +void CRYPTO_gcm128_init(GCM128_CONTEXT *ctx, const void *key, + block128_f block) { + const union { + long one; + char little; + } is_endian = {1}; + + memset(ctx, 0, sizeof(*ctx)); + ctx->block = block; + + (*block)(ctx->H.c, ctx->H.c, key); + + if (is_endian.little) { +/* H is stored in host byte order */ +#ifdef BSWAP8 + ctx->H.u[0] = BSWAP8(ctx->H.u[0]); + ctx->H.u[1] = BSWAP8(ctx->H.u[1]); +#else + uint8_t *p = ctx->H.c; + uint64_t hi, lo; + hi = (uint64_t)GETU32(p) << 32 | GETU32(p + 4); + lo = (uint64_t)GETU32(p + 8) << 32 | GETU32(p + 12); + ctx->H.u[0] = hi; + ctx->H.u[1] = lo; +#endif + } + +#if defined(GHASH_ASM_X86_OR_64) + if (crypto_gcm_clmul_enabled()) { + if (((OPENSSL_ia32cap_P[1] >> 22) & 0x41) == 0x41) { /* AVX+MOVBE */ + gcm_init_avx(ctx->Htable, ctx->H.u); + ctx->gmult = gcm_gmult_avx; + ctx->ghash = gcm_ghash_avx; + } else { + gcm_init_clmul(ctx->Htable, ctx->H.u); + ctx->gmult = gcm_gmult_clmul; + ctx->ghash = gcm_ghash_clmul; + } + return; + } + gcm_init_4bit(ctx->Htable, ctx->H.u); +#if defined(GHASH_ASM_X86) /* x86 only */ + if (OPENSSL_ia32cap_P[0] & (1 << 25)) { /* check SSE bit */ + ctx->gmult = gcm_gmult_4bit_mmx; + ctx->ghash = gcm_ghash_4bit_mmx; + } else { + ctx->gmult = gcm_gmult_4bit_x86; + ctx->ghash = gcm_ghash_4bit_x86; + } +#else + ctx->gmult = gcm_gmult_4bit; + ctx->ghash = gcm_ghash_4bit; +#endif +#elif defined(GHASH_ASM_ARM) + if (pmull_capable()) { + gcm_init_v8(ctx->Htable, ctx->H.u); + ctx->gmult = gcm_gmult_v8; + ctx->ghash = gcm_ghash_v8; + } else if (neon_capable()) { + gcm_init_neon(ctx->Htable,ctx->H.u); + ctx->gmult = gcm_gmult_neon; + ctx->ghash = gcm_ghash_neon; + } else { + gcm_init_4bit(ctx->Htable, ctx->H.u); + ctx->gmult = gcm_gmult_4bit; + ctx->ghash = gcm_ghash_4bit; + } +#else + gcm_init_4bit(ctx->Htable, ctx->H.u); + ctx->gmult = gcm_gmult_4bit; + ctx->ghash = gcm_ghash_4bit; +#endif +} + +void CRYPTO_gcm128_setiv(GCM128_CONTEXT *ctx, const void *key, + const uint8_t *iv, size_t len) { + const union { + long one; + char little; + } is_endian = {1}; + unsigned int ctr; +#ifdef GCM_FUNCREF_4BIT + void (*gcm_gmult_p)(uint64_t Xi[2], const u128 Htable[16]) = ctx->gmult; +#endif + + ctx->Yi.u[0] = 0; + ctx->Yi.u[1] = 0; + ctx->Xi.u[0] = 0; + ctx->Xi.u[1] = 0; + ctx->len.u[0] = 0; /* AAD length */ + ctx->len.u[1] = 0; /* message length */ + ctx->ares = 0; + ctx->mres = 0; + + if (len == 12) { + memcpy(ctx->Yi.c, iv, 12); + ctx->Yi.c[15] = 1; + ctr = 1; + } else { + size_t i; + uint64_t len0 = len; + + while (len >= 16) { + for (i = 0; i < 16; ++i) { + ctx->Yi.c[i] ^= iv[i]; + } + GCM_MUL(ctx, Yi); + iv += 16; + len -= 16; + } + if (len) { + for (i = 0; i < len; ++i) { + ctx->Yi.c[i] ^= iv[i]; + } + GCM_MUL(ctx, Yi); + } + len0 <<= 3; + if (is_endian.little) { +#ifdef BSWAP8 + ctx->Yi.u[1] ^= BSWAP8(len0); +#else + ctx->Yi.c[8] ^= (uint8_t)(len0 >> 56); + ctx->Yi.c[9] ^= (uint8_t)(len0 >> 48); + ctx->Yi.c[10] ^= (uint8_t)(len0 >> 40); + ctx->Yi.c[11] ^= (uint8_t)(len0 >> 32); + ctx->Yi.c[12] ^= (uint8_t)(len0 >> 24); + ctx->Yi.c[13] ^= (uint8_t)(len0 >> 16); + ctx->Yi.c[14] ^= (uint8_t)(len0 >> 8); + ctx->Yi.c[15] ^= (uint8_t)(len0); +#endif + } else { + ctx->Yi.u[1] ^= len0; + } + + GCM_MUL(ctx, Yi); + + if (is_endian.little) { + ctr = GETU32(ctx->Yi.c + 12); + } else { + ctr = ctx->Yi.d[3]; + } + } + + (*ctx->block)(ctx->Yi.c, ctx->EK0.c, key); + ++ctr; + if (is_endian.little) { + PUTU32(ctx->Yi.c + 12, ctr); + } else { + ctx->Yi.d[3] = ctr; + } +} + +int CRYPTO_gcm128_aad(GCM128_CONTEXT *ctx, const uint8_t *aad, size_t len) { + size_t i; + unsigned int n; + uint64_t alen = ctx->len.u[0]; +#ifdef GCM_FUNCREF_4BIT + void (*gcm_gmult_p)(uint64_t Xi[2], const u128 Htable[16]) = ctx->gmult; +#ifdef GHASH + void (*gcm_ghash_p)(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp, + size_t len) = ctx->ghash; +#endif +#endif + + if (ctx->len.u[1]) { + return 0; + } + + alen += len; + if (alen > (UINT64_C(1) << 61) || (sizeof(len) == 8 && alen < len)) { + return 0; + } + ctx->len.u[0] = alen; + + n = ctx->ares; + if (n) { + while (n && len) { + ctx->Xi.c[n] ^= *(aad++); + --len; + n = (n + 1) % 16; + } + if (n == 0) { + GCM_MUL(ctx, Xi); + } else { + ctx->ares = n; + return 1; + } + } + +#ifdef GHASH + i = len & kSizeTWithoutLower4Bits; + if (i != 0) { + GHASH(ctx, aad, i); + aad += i; + len -= i; + } +#else + while (len >= 16) { + for (i = 0; i < 16; ++i) { + ctx->Xi.c[i] ^= aad[i]; + } + GCM_MUL(ctx, Xi); + aad += 16; + len -= 16; + } +#endif + if (len) { + n = (unsigned int)len; + for (i = 0; i < len; ++i) { + ctx->Xi.c[i] ^= aad[i]; + } + } + + ctx->ares = n; + return 1; +} + +int CRYPTO_gcm128_encrypt(GCM128_CONTEXT *ctx, const void *key, + const unsigned char *in, unsigned char *out, + size_t len) { + const union { + long one; + char little; + } is_endian = {1}; + unsigned int n, ctr; + size_t i; + uint64_t mlen = ctx->len.u[1]; + block128_f block = ctx->block; +#ifdef GCM_FUNCREF_4BIT + void (*gcm_gmult_p)(uint64_t Xi[2], const u128 Htable[16]) = ctx->gmult; +#ifdef GHASH + void (*gcm_ghash_p)(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp, + size_t len) = ctx->ghash; +#endif +#endif + + mlen += len; + if (mlen > ((UINT64_C(1) << 36) - 32) || + (sizeof(len) == 8 && mlen < len)) { + return 0; + } + ctx->len.u[1] = mlen; + + if (ctx->ares) { + /* First call to encrypt finalizes GHASH(AAD) */ + GCM_MUL(ctx, Xi); + ctx->ares = 0; + } + + if (is_endian.little) { + ctr = GETU32(ctx->Yi.c + 12); + } else { + ctr = ctx->Yi.d[3]; + } + + n = ctx->mres; + if (n) { + while (n && len) { + ctx->Xi.c[n] ^= *(out++) = *(in++) ^ ctx->EKi.c[n]; + --len; + n = (n + 1) % 16; + } + if (n == 0) { + GCM_MUL(ctx, Xi); + } else { + ctx->mres = n; + return 1; + } + } + if (STRICT_ALIGNMENT && ((size_t)in | (size_t)out) % sizeof(size_t) != 0) { + for (i = 0; i < len; ++i) { + if (n == 0) { + (*block)(ctx->Yi.c, ctx->EKi.c, key); + ++ctr; + if (is_endian.little) { + PUTU32(ctx->Yi.c + 12, ctr); + } else { + ctx->Yi.d[3] = ctr; + } + } + ctx->Xi.c[n] ^= out[i] = in[i] ^ ctx->EKi.c[n]; + n = (n + 1) % 16; + if (n == 0) { + GCM_MUL(ctx, Xi); + } + } + + ctx->mres = n; + return 1; + } +#if defined(GHASH) && defined(GHASH_CHUNK) + while (len >= GHASH_CHUNK) { + size_t j = GHASH_CHUNK; + + while (j) { + size_t *out_t = (size_t *)out; + const size_t *in_t = (const size_t *)in; + + (*block)(ctx->Yi.c, ctx->EKi.c, key); + ++ctr; + if (is_endian.little) { + PUTU32(ctx->Yi.c + 12, ctr); + } else { + ctx->Yi.d[3] = ctr; + } + for (i = 0; i < 16 / sizeof(size_t); ++i) { + out_t[i] = in_t[i] ^ ctx->EKi.t[i]; + } + out += 16; + in += 16; + j -= 16; + } + GHASH(ctx, out - GHASH_CHUNK, GHASH_CHUNK); + len -= GHASH_CHUNK; + } + if ((i = (len & (size_t) - 16))) { + size_t j = i; + + while (len >= 16) { + size_t *out_t = (size_t *)out; + const size_t *in_t = (const size_t *)in; + + (*block)(ctx->Yi.c, ctx->EKi.c, key); + ++ctr; + if (is_endian.little) { + PUTU32(ctx->Yi.c + 12, ctr); + } else { + ctx->Yi.d[3] = ctr; + } + for (i = 0; i < 16 / sizeof(size_t); ++i) { + out_t[i] = in_t[i] ^ ctx->EKi.t[i]; + } + out += 16; + in += 16; + len -= 16; + } + GHASH(ctx, out - j, j); + } +#else + while (len >= 16) { + size_t *out_t = (size_t *)out; + const size_t *in_t = (const size_t *)in; + + (*block)(ctx->Yi.c, ctx->EKi.c, key); + ++ctr; + if (is_endian.little) { + PUTU32(ctx->Yi.c + 12, ctr); + } else { + ctx->Yi.d[3] = ctr; + } + for (i = 0; i < 16 / sizeof(size_t); ++i) { + ctx->Xi.t[i] ^= out_t[i] = in_t[i] ^ ctx->EKi.t[i]; + } + GCM_MUL(ctx, Xi); + out += 16; + in += 16; + len -= 16; + } +#endif + if (len) { + (*block)(ctx->Yi.c, ctx->EKi.c, key); + ++ctr; + if (is_endian.little) { + PUTU32(ctx->Yi.c + 12, ctr); + } else { + ctx->Yi.d[3] = ctr; + } + while (len--) { + ctx->Xi.c[n] ^= out[n] = in[n] ^ ctx->EKi.c[n]; + ++n; + } + } + + ctx->mres = n; + return 1; +} + +int CRYPTO_gcm128_decrypt(GCM128_CONTEXT *ctx, const void *key, + const unsigned char *in, unsigned char *out, + size_t len) { + const union { + long one; + char little; + } is_endian = {1}; + unsigned int n, ctr; + size_t i; + uint64_t mlen = ctx->len.u[1]; + block128_f block = ctx->block; +#ifdef GCM_FUNCREF_4BIT + void (*gcm_gmult_p)(uint64_t Xi[2], const u128 Htable[16]) = ctx->gmult; +#ifdef GHASH + void (*gcm_ghash_p)(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp, + size_t len) = ctx->ghash; +#endif +#endif + + mlen += len; + if (mlen > ((UINT64_C(1) << 36) - 32) || + (sizeof(len) == 8 && mlen < len)) { + return 0; + } + ctx->len.u[1] = mlen; + + if (ctx->ares) { + /* First call to decrypt finalizes GHASH(AAD) */ + GCM_MUL(ctx, Xi); + ctx->ares = 0; + } + + if (is_endian.little) { + ctr = GETU32(ctx->Yi.c + 12); + } else { + ctr = ctx->Yi.d[3]; + } + + n = ctx->mres; + if (n) { + while (n && len) { + uint8_t c = *(in++); + *(out++) = c ^ ctx->EKi.c[n]; + ctx->Xi.c[n] ^= c; + --len; + n = (n + 1) % 16; + } + if (n == 0) { + GCM_MUL(ctx, Xi); + } else { + ctx->mres = n; + return 1; + } + } + if (STRICT_ALIGNMENT && ((size_t)in | (size_t)out) % sizeof(size_t) != 0) { + for (i = 0; i < len; ++i) { + uint8_t c; + if (n == 0) { + (*block)(ctx->Yi.c, ctx->EKi.c, key); + ++ctr; + if (is_endian.little) { + PUTU32(ctx->Yi.c + 12, ctr); + } else { + ctx->Yi.d[3] = ctr; + } + } + c = in[i]; + out[i] = c ^ ctx->EKi.c[n]; + ctx->Xi.c[n] ^= c; + n = (n + 1) % 16; + if (n == 0) { + GCM_MUL(ctx, Xi); + } + } + + ctx->mres = n; + return 1; + } +#if defined(GHASH) && defined(GHASH_CHUNK) + while (len >= GHASH_CHUNK) { + size_t j = GHASH_CHUNK; + + GHASH(ctx, in, GHASH_CHUNK); + while (j) { + size_t *out_t = (size_t *)out; + const size_t *in_t = (const size_t *)in; + + (*block)(ctx->Yi.c, ctx->EKi.c, key); + ++ctr; + if (is_endian.little) { + PUTU32(ctx->Yi.c + 12, ctr); + } else { + ctx->Yi.d[3] = ctr; + } + for (i = 0; i < 16 / sizeof(size_t); ++i) { + out_t[i] = in_t[i] ^ ctx->EKi.t[i]; + } + out += 16; + in += 16; + j -= 16; + } + len -= GHASH_CHUNK; + } + i = len & kSizeTWithoutLower4Bits; + if (i != 0) { + GHASH(ctx, in, i); + while (len >= 16) { + size_t *out_t = (size_t *)out; + const size_t *in_t = (const size_t *)in; + + (*block)(ctx->Yi.c, ctx->EKi.c, key); + ++ctr; + if (is_endian.little) { + PUTU32(ctx->Yi.c + 12, ctr); + } else { + ctx->Yi.d[3] = ctr; + } + for (i = 0; i < 16 / sizeof(size_t); ++i) { + out_t[i] = in_t[i] ^ ctx->EKi.t[i]; + } + out += 16; + in += 16; + len -= 16; + } + } +#else + while (len >= 16) { + size_t *out_t = (size_t *)out; + const size_t *in_t = (const size_t *)in; + + (*block)(ctx->Yi.c, ctx->EKi.c, key); + ++ctr; + if (is_endian.little) { + PUTU32(ctx->Yi.c + 12, ctr); + } else { + ctx->Yi.d[3] = ctr; + } + for (i = 0; i < 16 / sizeof(size_t); ++i) { + size_t c = in_t[i]; + out_t[i] = c ^ ctx->EKi.t[i]; + ctx->Xi.t[i] ^= c; + } + GCM_MUL(ctx, Xi); + out += 16; + in += 16; + len -= 16; + } +#endif + if (len) { + (*block)(ctx->Yi.c, ctx->EKi.c, key); + ++ctr; + if (is_endian.little) { + PUTU32(ctx->Yi.c + 12, ctr); + } else { + ctx->Yi.d[3] = ctr; + } + while (len--) { + uint8_t c = in[n]; + ctx->Xi.c[n] ^= c; + out[n] = c ^ ctx->EKi.c[n]; + ++n; + } + } + + ctx->mres = n; + return 1; +} + +int CRYPTO_gcm128_encrypt_ctr32(GCM128_CONTEXT *ctx, const void *key, + const uint8_t *in, uint8_t *out, size_t len, + ctr128_f stream) { + const union { + long one; + char little; + } is_endian = {1}; + unsigned int n, ctr; + uint64_t mlen = ctx->len.u[1]; +#ifdef GCM_FUNCREF_4BIT + void (*gcm_gmult_p)(uint64_t Xi[2], const u128 Htable[16]) = ctx->gmult; +#ifdef GHASH + void (*gcm_ghash_p)(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp, + size_t len) = ctx->ghash; +#endif +#endif + + mlen += len; + if (mlen > ((UINT64_C(1) << 36) - 32) || + (sizeof(len) == 8 && mlen < len)) { + return 0; + } + ctx->len.u[1] = mlen; + + if (ctx->ares) { + /* First call to encrypt finalizes GHASH(AAD) */ + GCM_MUL(ctx, Xi); + ctx->ares = 0; + } + + n = ctx->mres; + if (n) { + while (n && len) { + ctx->Xi.c[n] ^= *(out++) = *(in++) ^ ctx->EKi.c[n]; + --len; + n = (n + 1) % 16; + } + if (n == 0) { + GCM_MUL(ctx, Xi); + } else { + ctx->mres = n; + return 1; + } + } + +#if defined(AESNI_GCM) + if (aesni_gcm_enabled(ctx, stream)) { + /* |aesni_gcm_encrypt| may not process all the input given to it. It may + * not process *any* of its input if it is deemed too small. */ + size_t bulk = aesni_gcm_encrypt(in, out, len, key, ctx->Yi.c, ctx->Xi.u); + in += bulk; + out += bulk; + len -= bulk; + } +#endif + + if (is_endian.little) { + ctr = GETU32(ctx->Yi.c + 12); + } else { + ctr = ctx->Yi.d[3]; + } + +#if defined(GHASH) + while (len >= GHASH_CHUNK) { + (*stream)(in, out, GHASH_CHUNK / 16, key, ctx->Yi.c); + ctr += GHASH_CHUNK / 16; + if (is_endian.little) { + PUTU32(ctx->Yi.c + 12, ctr); + } else { + ctx->Yi.d[3] = ctr; + } + GHASH(ctx, out, GHASH_CHUNK); + out += GHASH_CHUNK; + in += GHASH_CHUNK; + len -= GHASH_CHUNK; + } +#endif + size_t i = len & kSizeTWithoutLower4Bits; + if (i != 0) { + size_t j = i / 16; + + (*stream)(in, out, j, key, ctx->Yi.c); + ctr += (unsigned int)j; + if (is_endian.little) { + PUTU32(ctx->Yi.c + 12, ctr); + } else { + ctx->Yi.d[3] = ctr; + } + in += i; + len -= i; +#if defined(GHASH) + GHASH(ctx, out, i); + out += i; +#else + while (j--) { + for (i = 0; i < 16; ++i) { + ctx->Xi.c[i] ^= out[i]; + } + GCM_MUL(ctx, Xi); + out += 16; + } +#endif + } + if (len) { + (*ctx->block)(ctx->Yi.c, ctx->EKi.c, key); + ++ctr; + if (is_endian.little) { + PUTU32(ctx->Yi.c + 12, ctr); + } else { + ctx->Yi.d[3] = ctr; + } + while (len--) { + ctx->Xi.c[n] ^= out[n] = in[n] ^ ctx->EKi.c[n]; + ++n; + } + } + + ctx->mres = n; + return 1; +} + +int CRYPTO_gcm128_decrypt_ctr32(GCM128_CONTEXT *ctx, const void *key, + const uint8_t *in, uint8_t *out, size_t len, + ctr128_f stream) { + const union { + long one; + char little; + } is_endian = {1}; + unsigned int n, ctr; + uint64_t mlen = ctx->len.u[1]; +#ifdef GCM_FUNCREF_4BIT + void (*gcm_gmult_p)(uint64_t Xi[2], const u128 Htable[16]) = ctx->gmult; +#ifdef GHASH + void (*gcm_ghash_p)(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp, + size_t len) = ctx->ghash; +#endif +#endif + + mlen += len; + if (mlen > ((UINT64_C(1) << 36) - 32) || + (sizeof(len) == 8 && mlen < len)) { + return 0; + } + ctx->len.u[1] = mlen; + + if (ctx->ares) { + /* First call to decrypt finalizes GHASH(AAD) */ + GCM_MUL(ctx, Xi); + ctx->ares = 0; + } + + n = ctx->mres; + if (n) { + while (n && len) { + uint8_t c = *(in++); + *(out++) = c ^ ctx->EKi.c[n]; + ctx->Xi.c[n] ^= c; + --len; + n = (n + 1) % 16; + } + if (n == 0) { + GCM_MUL(ctx, Xi); + } else { + ctx->mres = n; + return 1; + } + } + +#if defined(AESNI_GCM) + if (aesni_gcm_enabled(ctx, stream)) { + /* |aesni_gcm_decrypt| may not process all the input given to it. It may + * not process *any* of its input if it is deemed too small. */ + size_t bulk = aesni_gcm_decrypt(in, out, len, key, ctx->Yi.c, ctx->Xi.u); + in += bulk; + out += bulk; + len -= bulk; + } +#endif + + if (is_endian.little) { + ctr = GETU32(ctx->Yi.c + 12); + } else { + ctr = ctx->Yi.d[3]; + } + +#if defined(GHASH) + while (len >= GHASH_CHUNK) { + GHASH(ctx, in, GHASH_CHUNK); + (*stream)(in, out, GHASH_CHUNK / 16, key, ctx->Yi.c); + ctr += GHASH_CHUNK / 16; + if (is_endian.little) { + PUTU32(ctx->Yi.c + 12, ctr); + } else { + ctx->Yi.d[3] = ctr; + } + out += GHASH_CHUNK; + in += GHASH_CHUNK; + len -= GHASH_CHUNK; + } +#endif + size_t i = len & kSizeTWithoutLower4Bits; + if (i != 0) { + size_t j = i / 16; + +#if defined(GHASH) + GHASH(ctx, in, i); +#else + while (j--) { + size_t k; + for (k = 0; k < 16; ++k) { + ctx->Xi.c[k] ^= in[k]; + } + GCM_MUL(ctx, Xi); + in += 16; + } + j = i / 16; + in -= i; +#endif + (*stream)(in, out, j, key, ctx->Yi.c); + ctr += (unsigned int)j; + if (is_endian.little) { + PUTU32(ctx->Yi.c + 12, ctr); + } else { + ctx->Yi.d[3] = ctr; + } + out += i; + in += i; + len -= i; + } + if (len) { + (*ctx->block)(ctx->Yi.c, ctx->EKi.c, key); + ++ctr; + if (is_endian.little) { + PUTU32(ctx->Yi.c + 12, ctr); + } else { + ctx->Yi.d[3] = ctr; + } + while (len--) { + uint8_t c = in[n]; + ctx->Xi.c[n] ^= c; + out[n] = c ^ ctx->EKi.c[n]; + ++n; + } + } + + ctx->mres = n; + return 1; +} + +int CRYPTO_gcm128_finish(GCM128_CONTEXT *ctx, const uint8_t *tag, size_t len) { + const union { + long one; + char little; + } is_endian = {1}; + uint64_t alen = ctx->len.u[0] << 3; + uint64_t clen = ctx->len.u[1] << 3; +#ifdef GCM_FUNCREF_4BIT + void (*gcm_gmult_p)(uint64_t Xi[2], const u128 Htable[16]) = ctx->gmult; +#endif + + if (ctx->mres || ctx->ares) { + GCM_MUL(ctx, Xi); + } + + if (is_endian.little) { +#ifdef BSWAP8 + alen = BSWAP8(alen); + clen = BSWAP8(clen); +#else + uint8_t *p = ctx->len.c; + + ctx->len.u[0] = alen; + ctx->len.u[1] = clen; + + alen = (uint64_t)GETU32(p) << 32 | GETU32(p + 4); + clen = (uint64_t)GETU32(p + 8) << 32 | GETU32(p + 12); +#endif + } + + ctx->Xi.u[0] ^= alen; + ctx->Xi.u[1] ^= clen; + GCM_MUL(ctx, Xi); + + ctx->Xi.u[0] ^= ctx->EK0.u[0]; + ctx->Xi.u[1] ^= ctx->EK0.u[1]; + + if (tag && len <= sizeof(ctx->Xi)) { + return CRYPTO_memcmp(ctx->Xi.c, tag, len) == 0; + } else { + return 0; + } +} + +void CRYPTO_gcm128_tag(GCM128_CONTEXT *ctx, unsigned char *tag, size_t len) { + CRYPTO_gcm128_finish(ctx, NULL, 0); + memcpy(tag, ctx->Xi.c, len <= sizeof(ctx->Xi.c) ? len : sizeof(ctx->Xi.c)); +} + +#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64) +int crypto_gcm_clmul_enabled(void) { +#ifdef GHASH_ASM + return OPENSSL_ia32cap_P[0] & (1 << 24) && /* check FXSR bit */ + OPENSSL_ia32cap_P[1] & (1 << 1); /* check PCLMULQDQ bit */ +#else + return 0; +#endif +} +#endif diff --git a/external/boringssl/crypto/modes/gcm_test.c b/external/boringssl/crypto/modes/gcm_test.c new file mode 100644 index 0000000000..19c295b54e --- /dev/null +++ b/external/boringssl/crypto/modes/gcm_test.c @@ -0,0 +1,411 @@ +/* ==================================================================== + * Copyright (c) 2008 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== */ + +#include +#include + +#include +#include +#include + +#include "internal.h" +#include "../test/test_util.h" + + +struct test_case { + const char *key; + const char *plaintext; + const char *additional_data; + const char *nonce; + const char *ciphertext; + const char *tag; +}; + +static const struct test_case test_cases[] = { + { + "00000000000000000000000000000000", + NULL, + NULL, + "000000000000000000000000", + NULL, + "58e2fccefa7e3061367f1d57a4e7455a", + }, + { + "00000000000000000000000000000000", + "00000000000000000000000000000000", + NULL, + "000000000000000000000000", + "0388dace60b6a392f328c2b971b2fe78", + "ab6e47d42cec13bdf53a67b21257bddf", + }, + { + "feffe9928665731c6d6a8f9467308308", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255", + NULL, + "cafebabefacedbaddecaf888", + "42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091473f5985", + "4d5c2af327cd64a62cf35abd2ba6fab4", + }, + { + "feffe9928665731c6d6a8f9467308308", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", + "feedfacedeadbeeffeedfacedeadbeefabaddad2", + "cafebabefacedbaddecaf888", + "42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091", + "5bc94fbc3221a5db94fae95ae7121a47", + }, + { + "feffe9928665731c6d6a8f9467308308", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", + "feedfacedeadbeeffeedfacedeadbeefabaddad2", + "cafebabefacedbad", + "61353b4c2806934a777ff51fa22a4755699b2a714fcdc6f83766e5f97b6c742373806900e49f24b22b097544d4896b424989b5e1ebac0f07c23f4598", + "3612d2e79e3b0785561be14aaca2fccb", + }, + { + "feffe9928665731c6d6a8f9467308308", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", + "feedfacedeadbeeffeedfacedeadbeefabaddad2", + "9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b", + "8ce24998625615b603a033aca13fb894be9112a5c3a211a8ba262a3cca7e2ca701e4a9a4fba43c90ccdcb281d48c7c6fd62875d2aca417034c34aee5", + "619cc5aefffe0bfa462af43c1699d050", + }, + { + "000000000000000000000000000000000000000000000000", + NULL, + NULL, + "000000000000000000000000", + NULL, + "cd33b28ac773f74ba00ed1f312572435", + }, + { + "000000000000000000000000000000000000000000000000", + "00000000000000000000000000000000", + NULL, + "000000000000000000000000", + "98e7247c07f0fe411c267e4384b0f600", + "2ff58d80033927ab8ef4d4587514f0fb", + }, + { + "feffe9928665731c6d6a8f9467308308feffe9928665731c", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255", + NULL, + "cafebabefacedbaddecaf888", + "3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710acade256", + "9924a7c8587336bfb118024db8674a14", + }, + { + "feffe9928665731c6d6a8f9467308308feffe9928665731c", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", + "feedfacedeadbeeffeedfacedeadbeefabaddad2", + "cafebabefacedbaddecaf888", + "3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710", + "2519498e80f1478f37ba55bd6d27618c", + }, + { + "feffe9928665731c6d6a8f9467308308feffe9928665731c", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", + "feedfacedeadbeeffeedfacedeadbeefabaddad2", + "cafebabefacedbad", + "0f10f599ae14a154ed24b36e25324db8c566632ef2bbb34f8347280fc4507057fddc29df9a471f75c66541d4d4dad1c9e93a19a58e8b473fa0f062f7", + "65dcc57fcf623a24094fcca40d3533f8", + }, + { + "feffe9928665731c6d6a8f9467308308feffe9928665731c", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", + "feedfacedeadbeeffeedfacedeadbeefabaddad2", + "cafebabefacedbad", + "0f10f599ae14a154ed24b36e25324db8c566632ef2bbb34f8347280fc4507057fddc29df9a471f75c66541d4d4dad1c9e93a19a58e8b473fa0f062f7", + "65dcc57fcf623a24094fcca40d3533f8", + }, + { + "feffe9928665731c6d6a8f9467308308feffe9928665731c", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", + "feedfacedeadbeeffeedfacedeadbeefabaddad2", + "9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b", + "d27e88681ce3243c4830165a8fdcf9ff1de9a1d8e6b447ef6ef7b79828666e4581e79012af34ddd9e2f037589b292db3e67c036745fa22e7e9b7373b", + "dcf566ff291c25bbb8568fc3d376a6d9", + }, + { + "0000000000000000000000000000000000000000000000000000000000000000", + NULL, + NULL, + "000000000000000000000000", + NULL, + "530f8afbc74536b9a963b4f1c4cb738b", + }, + { + "0000000000000000000000000000000000000000000000000000000000000000", + "00000000000000000000000000000000", + NULL, + "000000000000000000000000", + "cea7403d4d606b6e074ec5d3baf39d18", + "d0d1c8a799996bf0265b98b5d48ab919", + }, + { + "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255", + NULL, + "cafebabefacedbaddecaf888", + "522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad", + "b094dac5d93471bdec1a502270e3cc6c", + }, + { + "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", + "feedfacedeadbeeffeedfacedeadbeefabaddad2", + "cafebabefacedbaddecaf888", + "522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662", + "76fc6ece0f4e1768cddf8853bb2d551b", + }, + { + "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", + "feedfacedeadbeeffeedfacedeadbeefabaddad2", + "cafebabefacedbad", + "c3762df1ca787d32ae47c13bf19844cbaf1ae14d0b976afac52ff7d79bba9de0feb582d33934a4f0954cc2363bc73f7862ac430e64abe499f47c9b1f", + "3a337dbf46a792c45e454913fe2ea8f2", + }, + { + "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", + "feedfacedeadbeeffeedfacedeadbeefabaddad2", + "9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b", + "5a8def2f0c9e53f1f75d7853659e2a20eeb2b22aafde6419a058ab4f6f746bf40fc0c3b780f244452da3ebf1c5d82cdea2418997200ef82e44ae7e3f", + "a44a8266ee1c8eb0c8b5d4cf5ae9f19a", + }, + { + "00000000000000000000000000000000", + NULL, + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad", + "000000000000000000000000", + NULL, + "5fea793a2d6f974d37e68e0cb8ff9492", + }, + { + "00000000000000000000000000000000", + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + NULL, + /* This nonce results in 0xfff in counter LSB. */ + "ffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "56b3373ca9ef6e4a2b64fe1e9a17b61425f10d47a75a5fce13efc6bc784af24f4141bdd48cf7c770887afd573cca5418a9aeffcd7c5ceddfc6a78397b9a85b499da558257267caab2ad0b23ca476a53cb17fb41c4b8b475cb4f3f7165094c229c9e8c4dc0a2a5ff1903e501511221376a1cdb8364c5061a20cae74bc4acd76ceb0abc9fd3217ef9f8c90be402ddf6d8697f4f880dff15bfb7a6b28241ec8fe183c2d59e3f9dfff653c7126f0acb9e64211f42bae12af462b1070bef1ab5e3606872ca10dee15b3249b1a1b958f23134c4bccb7d03200bce420a2f8eb66dcf3644d1423c1b5699003c13ecef4bf38a3b60eedc34033bac1902783dc6d89e2e774188a439c7ebcc0672dbda4ddcfb2794613b0be41315ef778708a70ee7d75165c", + "8b307f6b33286d0ab026a9ed3fe1e85f", + }, +}; + +static int from_hex(uint8_t *out, char in) { + if (in >= '0' && in <= '9') { + *out = in - '0'; + return 1; + } + if (in >= 'a' && in <= 'f') { + *out = in - 'a' + 10; + return 1; + } + if (in >= 'A' && in <= 'F') { + *out = in - 'A' + 10; + return 1; + } + + return 0; +} + +static int decode_hex(uint8_t **out, size_t *out_len, const char *in, + unsigned test_num, const char *description) { + uint8_t *buf = NULL; + size_t i; + + if (in == NULL) { + *out = NULL; + *out_len = 0; + return 1; + } + + size_t len = strlen(in); + if (len & 1) { + fprintf(stderr, "%u: Odd-length %s input.\n", test_num, description); + goto err; + } + + buf = OPENSSL_malloc(len / 2); + if (buf == NULL) { + fprintf(stderr, "%u: malloc failure.\n", test_num); + goto err; + } + + for (i = 0; i < len; i += 2) { + uint8_t v, v2; + if (!from_hex(&v, in[i]) || + !from_hex(&v2, in[i+1])) { + fprintf(stderr, "%u: invalid hex digit in %s around offset %zu.\n", + test_num, description, i); + goto err; + } + buf[i/2] = (v << 4) | v2; + } + + *out = buf; + *out_len = len/2; + return 1; + +err: + OPENSSL_free(buf); + return 0; +} + +static int run_test_case(unsigned test_num, const struct test_case *test) { + size_t key_len, plaintext_len, additional_data_len, nonce_len, ciphertext_len, + tag_len; + uint8_t *key = NULL, *plaintext = NULL, *additional_data = NULL, + *nonce = NULL, *ciphertext = NULL, *tag = NULL, *out = NULL; + int ret = 0; + AES_KEY aes_key; + GCM128_CONTEXT ctx; + + if (!decode_hex(&key, &key_len, test->key, test_num, "key") || + !decode_hex(&plaintext, &plaintext_len, test->plaintext, test_num, + "plaintext") || + !decode_hex(&additional_data, &additional_data_len, test->additional_data, + test_num, "additional_data") || + !decode_hex(&nonce, &nonce_len, test->nonce, test_num, "nonce") || + !decode_hex(&ciphertext, &ciphertext_len, test->ciphertext, test_num, + "ciphertext") || + !decode_hex(&tag, &tag_len, test->tag, test_num, "tag")) { + goto out; + } + + if (plaintext_len != ciphertext_len) { + fprintf(stderr, "%u: plaintext and ciphertext have differing lengths.\n", + test_num); + goto out; + } + + if (key_len != 16 && key_len != 24 && key_len != 32) { + fprintf(stderr, "%u: bad key length.\n", test_num); + goto out; + } + + if (tag_len != 16) { + fprintf(stderr, "%u: bad tag length.\n", test_num); + goto out; + } + + out = OPENSSL_malloc(plaintext_len); + if (plaintext_len != 0 && out == NULL) { + goto out; + } + if (AES_set_encrypt_key(key, key_len*8, &aes_key)) { + fprintf(stderr, "%u: AES_set_encrypt_key failed.\n", test_num); + goto out; + } + + CRYPTO_gcm128_init(&ctx, &aes_key, (block128_f) AES_encrypt); + CRYPTO_gcm128_setiv(&ctx, &aes_key, nonce, nonce_len); + memset(out, 0, plaintext_len); + if (additional_data) { + CRYPTO_gcm128_aad(&ctx, additional_data, additional_data_len); + } + if (plaintext) { + CRYPTO_gcm128_encrypt(&ctx, &aes_key, plaintext, out, plaintext_len); + } + if (!CRYPTO_gcm128_finish(&ctx, tag, tag_len) || + (ciphertext && memcmp(out, ciphertext, plaintext_len) != 0)) { + fprintf(stderr, "%u: encrypt failed.\n", test_num); + hexdump(stderr, "got :", out, plaintext_len); + hexdump(stderr, "want:", ciphertext, plaintext_len); + goto out; + } + + CRYPTO_gcm128_setiv(&ctx, &aes_key, nonce, nonce_len); + memset(out, 0, plaintext_len); + if (additional_data) { + CRYPTO_gcm128_aad(&ctx, additional_data, additional_data_len); + } + if (ciphertext) { + CRYPTO_gcm128_decrypt(&ctx, &aes_key, ciphertext, out, plaintext_len); + } + if (!CRYPTO_gcm128_finish(&ctx, tag, tag_len)) { + fprintf(stderr, "%u: decrypt failed.\n", test_num); + goto out; + } + if (plaintext && memcmp(out, plaintext, plaintext_len)) { + fprintf(stderr, "%u: plaintext doesn't match.\n", test_num); + goto out; + } + + ret = 1; + +out: + OPENSSL_free(key); + OPENSSL_free(plaintext); + OPENSSL_free(additional_data); + OPENSSL_free(nonce); + OPENSSL_free(ciphertext); + OPENSSL_free(tag); + OPENSSL_free(out); + return ret; +} + +int main(void) { + int ret = 0; + unsigned i; + + CRYPTO_library_init(); + + for (i = 0; i < sizeof(test_cases) / sizeof(struct test_case); i++) { + if (!run_test_case(i, &test_cases[i])) { + ret = 1; + } + } + + if (ret == 0) { + printf("PASS\n"); + } + + return ret; +} diff --git a/external/boringssl/crypto/modes/internal.h b/external/boringssl/crypto/modes/internal.h new file mode 100644 index 0000000000..430d0401e6 --- /dev/null +++ b/external/boringssl/crypto/modes/internal.h @@ -0,0 +1,358 @@ +/* ==================================================================== + * Copyright (c) 2008 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== */ + +#ifndef OPENSSL_HEADER_MODES_INTERNAL_H +#define OPENSSL_HEADER_MODES_INTERNAL_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +#define asm __asm__ + +#define STRICT_ALIGNMENT 1 +#if defined(OPENSSL_X86_64) || defined(OPENSSL_X86) || defined(OPENSSL_AARCH64) +#undef STRICT_ALIGNMENT +#define STRICT_ALIGNMENT 0 +#endif + +#if !defined(PEDANTIC) && !defined(OPENSSL_NO_ASM) +#if defined(__GNUC__) && __GNUC__ >= 2 +#if defined(OPENSSL_X86_64) +#define BSWAP8(x) \ + ({ \ + uint64_t ret = (x); \ + asm("bswapq %0" : "+r"(ret)); \ + ret; \ + }) +#define BSWAP4(x) \ + ({ \ + uint32_t ret = (x); \ + asm("bswapl %0" : "+r"(ret)); \ + ret; \ + }) +#elif defined(OPENSSL_X86) +#define BSWAP8(x) \ + ({ \ + uint32_t lo = (uint64_t)(x) >> 32, hi = (x); \ + asm("bswapl %0; bswapl %1" : "+r"(hi), "+r"(lo)); \ + (uint64_t) hi << 32 | lo; \ + }) +#define BSWAP4(x) \ + ({ \ + uint32_t ret = (x); \ + asm("bswapl %0" : "+r"(ret)); \ + ret; \ + }) +#elif defined(OPENSSL_AARCH64) +#define BSWAP8(x) \ + ({ \ + uint64_t ret; \ + asm("rev %0,%1" : "=r"(ret) : "r"(x)); \ + ret; \ + }) +#define BSWAP4(x) \ + ({ \ + uint32_t ret; \ + asm("rev %w0,%w1" : "=r"(ret) : "r"(x)); \ + ret; \ + }) +#elif defined(OPENSSL_ARM) && !defined(STRICT_ALIGNMENT) +#define BSWAP8(x) \ + ({ \ + uint32_t lo = (uint64_t)(x) >> 32, hi = (x); \ + asm("rev %0,%0; rev %1,%1" : "+r"(hi), "+r"(lo)); \ + (uint64_t) hi << 32 | lo; \ + }) +#define BSWAP4(x) \ + ({ \ + uint32_t ret; \ + asm("rev %0,%1" : "=r"(ret) : "r"((uint32_t)(x))); \ + ret; \ + }) +#endif +#elif defined(_MSC_VER) +#if _MSC_VER >= 1300 +OPENSSL_MSVC_PRAGMA(warning(push, 3)) +#include +OPENSSL_MSVC_PRAGMA(warning(pop)) +#pragma intrinsic(_byteswap_uint64, _byteswap_ulong) +#define BSWAP8(x) _byteswap_uint64((uint64_t)(x)) +#define BSWAP4(x) _byteswap_ulong((uint32_t)(x)) +#elif defined(OPENSSL_X86) +__inline uint32_t _bswap4(uint32_t val) { + _asm mov eax, val + _asm bswap eax +} +#define BSWAP4(x) _bswap4(x) +#endif +#endif +#endif + +#if defined(BSWAP4) && !defined(STRICT_ALIGNMENT) +#define GETU32(p) BSWAP4(*(const uint32_t *)(p)) +#define PUTU32(p, v) *(uint32_t *)(p) = BSWAP4(v) +#else +#define GETU32(p) \ + ((uint32_t)(p)[0] << 24 | (uint32_t)(p)[1] << 16 | (uint32_t)(p)[2] << 8 | (uint32_t)(p)[3]) +#define PUTU32(p, v) \ + ((p)[0] = (uint8_t)((v) >> 24), (p)[1] = (uint8_t)((v) >> 16), \ + (p)[2] = (uint8_t)((v) >> 8), (p)[3] = (uint8_t)(v)) +#endif + + +/* block128_f is the type of a 128-bit, block cipher. */ +typedef void (*block128_f)(const uint8_t in[16], uint8_t out[16], + const void *key); + +/* GCM definitions */ +typedef struct { uint64_t hi,lo; } u128; + +/* This differs from upstream's |gcm128_context| in that it does not have the + * |key| pointer, in order to make it |memcpy|-friendly. Rather the key is + * passed into each call that needs it. */ +struct gcm128_context { + /* Following 6 names follow names in GCM specification */ + union { + uint64_t u[2]; + uint32_t d[4]; + uint8_t c[16]; + size_t t[16 / sizeof(size_t)]; + } Yi, EKi, EK0, len, Xi, H; + + /* Relative position of Xi, H and pre-computed Htable is used in some + * assembler modules, i.e. don't change the order! */ + u128 Htable[16]; + void (*gmult)(uint64_t Xi[2], const u128 Htable[16]); + void (*ghash)(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp, + size_t len); + + unsigned int mres, ares; + block128_f block; +}; + +#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64) +/* crypto_gcm_clmul_enabled returns one if the CLMUL implementation of GCM is + * used. */ +int crypto_gcm_clmul_enabled(void); +#endif + + +/* CTR. */ + +/* ctr128_f is the type of a function that performs CTR-mode encryption. */ +typedef void (*ctr128_f)(const uint8_t *in, uint8_t *out, size_t blocks, + const void *key, const uint8_t ivec[16]); + +/* CRYPTO_ctr128_encrypt encrypts (or decrypts, it's the same in CTR mode) + * |len| bytes from |in| to |out| using |block| in counter mode. There's no + * requirement that |len| be a multiple of any value and any partial blocks are + * stored in |ecount_buf| and |*num|, which must be zeroed before the initial + * call. The counter is a 128-bit, big-endian value in |ivec| and is + * incremented by this function. */ +void CRYPTO_ctr128_encrypt(const uint8_t *in, uint8_t *out, size_t len, + const void *key, uint8_t ivec[16], + uint8_t ecount_buf[16], unsigned *num, + block128_f block); + +/* CRYPTO_ctr128_encrypt_ctr32 acts like |CRYPTO_ctr128_encrypt| but takes + * |ctr|, a function that performs CTR mode but only deals with the lower 32 + * bits of the counter. This is useful when |ctr| can be an optimised + * function. */ +void CRYPTO_ctr128_encrypt_ctr32(const uint8_t *in, uint8_t *out, size_t len, + const void *key, uint8_t ivec[16], + uint8_t ecount_buf[16], unsigned *num, + ctr128_f ctr); + + +/* GCM. + * + * This API differs from the upstream API slightly. The |GCM128_CONTEXT| does + * not have a |key| pointer that points to the key as upstream's version does. + * Instead, every function takes a |key| parameter. This way |GCM128_CONTEXT| + * can be safely copied. */ + +typedef struct gcm128_context GCM128_CONTEXT; + +/* CRYPTO_gcm128_init initialises |ctx| to use |block| (typically AES) with + * the given key. */ +OPENSSL_EXPORT void CRYPTO_gcm128_init(GCM128_CONTEXT *ctx, const void *key, + block128_f block); + +/* CRYPTO_gcm128_setiv sets the IV (nonce) for |ctx|. The |key| must be the + * same key that was passed to |CRYPTO_gcm128_init|. */ +OPENSSL_EXPORT void CRYPTO_gcm128_setiv(GCM128_CONTEXT *ctx, const void *key, + const uint8_t *iv, size_t iv_len); + +/* CRYPTO_gcm128_aad sets the authenticated data for an instance of GCM. + * This must be called before and data is encrypted. It returns one on success + * and zero otherwise. */ +OPENSSL_EXPORT int CRYPTO_gcm128_aad(GCM128_CONTEXT *ctx, const uint8_t *aad, + size_t len); + +/* CRYPTO_gcm128_encrypt encrypts |len| bytes from |in| to |out|. The |key| + * must be the same key that was passed to |CRYPTO_gcm128_init|. It returns one + * on success and zero otherwise. */ +OPENSSL_EXPORT int CRYPTO_gcm128_encrypt(GCM128_CONTEXT *ctx, const void *key, + const uint8_t *in, uint8_t *out, + size_t len); + +/* CRYPTO_gcm128_decrypt decrypts |len| bytes from |in| to |out|. The |key| + * must be the same key that was passed to |CRYPTO_gcm128_init|. It returns one + * on success and zero otherwise. */ +OPENSSL_EXPORT int CRYPTO_gcm128_decrypt(GCM128_CONTEXT *ctx, const void *key, + const uint8_t *in, uint8_t *out, + size_t len); + +/* CRYPTO_gcm128_encrypt_ctr32 encrypts |len| bytes from |in| to |out| using + * a CTR function that only handles the bottom 32 bits of the nonce, like + * |CRYPTO_ctr128_encrypt_ctr32|. The |key| must be the same key that was + * passed to |CRYPTO_gcm128_init|. It returns one on success and zero + * otherwise. */ +OPENSSL_EXPORT int CRYPTO_gcm128_encrypt_ctr32(GCM128_CONTEXT *ctx, + const void *key, + const uint8_t *in, uint8_t *out, + size_t len, ctr128_f stream); + +/* CRYPTO_gcm128_decrypt_ctr32 decrypts |len| bytes from |in| to |out| using + * a CTR function that only handles the bottom 32 bits of the nonce, like + * |CRYPTO_ctr128_encrypt_ctr32|. The |key| must be the same key that was + * passed to |CRYPTO_gcm128_init|. It returns one on success and zero + * otherwise. */ +OPENSSL_EXPORT int CRYPTO_gcm128_decrypt_ctr32(GCM128_CONTEXT *ctx, + const void *key, + const uint8_t *in, uint8_t *out, + size_t len, ctr128_f stream); + +/* CRYPTO_gcm128_finish calculates the authenticator and compares it against + * |len| bytes of |tag|. It returns one on success and zero otherwise. */ +OPENSSL_EXPORT int CRYPTO_gcm128_finish(GCM128_CONTEXT *ctx, const uint8_t *tag, + size_t len); + +/* CRYPTO_gcm128_tag calculates the authenticator and copies it into |tag|. + * The minimum of |len| and 16 bytes are copied into |tag|. */ +OPENSSL_EXPORT void CRYPTO_gcm128_tag(GCM128_CONTEXT *ctx, uint8_t *tag, + size_t len); + + +/* CBC. */ + +/* cbc128_f is the type of a function that performs CBC-mode encryption. */ +typedef void (*cbc128_f)(const uint8_t *in, uint8_t *out, size_t len, + const void *key, uint8_t ivec[16], int enc); + +/* CRYPTO_cbc128_encrypt encrypts |len| bytes from |in| to |out| using the + * given IV and block cipher in CBC mode. The input need not be a multiple of + * 128 bits long, but the output will round up to the nearest 128 bit multiple, + * zero padding the input if needed. The IV will be updated on return. */ +void CRYPTO_cbc128_encrypt(const uint8_t *in, uint8_t *out, size_t len, + const void *key, uint8_t ivec[16], block128_f block); + +/* CRYPTO_cbc128_decrypt decrypts |len| bytes from |in| to |out| using the + * given IV and block cipher in CBC mode. If |len| is not a multiple of 128 + * bits then only that many bytes will be written, but a multiple of 128 bits + * is always read from |in|. The IV will be updated on return. */ +void CRYPTO_cbc128_decrypt(const uint8_t *in, uint8_t *out, size_t len, + const void *key, uint8_t ivec[16], block128_f block); + + +/* OFB. */ + +/* CRYPTO_ofb128_encrypt encrypts (or decrypts, it's the same with OFB mode) + * |len| bytes from |in| to |out| using |block| in OFB mode. There's no + * requirement that |len| be a multiple of any value and any partial blocks are + * stored in |ivec| and |*num|, the latter must be zero before the initial + * call. */ +void CRYPTO_ofb128_encrypt(const uint8_t *in, uint8_t *out, + size_t len, const void *key, uint8_t ivec[16], + unsigned *num, block128_f block); + + +/* CFB. */ + +/* CRYPTO_cfb128_encrypt encrypts (or decrypts, if |enc| is zero) |len| bytes + * from |in| to |out| using |block| in CFB mode. There's no requirement that + * |len| be a multiple of any value and any partial blocks are stored in |ivec| + * and |*num|, the latter must be zero before the initial call. */ +void CRYPTO_cfb128_encrypt(const uint8_t *in, uint8_t *out, size_t len, + const void *key, uint8_t ivec[16], unsigned *num, + int enc, block128_f block); + +/* CRYPTO_cfb128_8_encrypt encrypts (or decrypts, if |enc| is zero) |len| bytes + * from |in| to |out| using |block| in CFB-8 mode. Prior to the first call + * |num| should be set to zero. */ +void CRYPTO_cfb128_8_encrypt(const uint8_t *in, uint8_t *out, size_t len, + const void *key, uint8_t ivec[16], unsigned *num, + int enc, block128_f block); + +/* CRYPTO_cfb128_1_encrypt encrypts (or decrypts, if |enc| is zero) |len| bytes + * from |in| to |out| using |block| in CFB-1 mode. Prior to the first call + * |num| should be set to zero. */ +void CRYPTO_cfb128_1_encrypt(const uint8_t *in, uint8_t *out, size_t bits, + const void *key, uint8_t ivec[16], unsigned *num, + int enc, block128_f block); + +size_t CRYPTO_cts128_encrypt_block(const uint8_t *in, uint8_t *out, size_t len, + const void *key, uint8_t ivec[16], + block128_f block); + + +#if !defined(OPENSSL_NO_ASM) && \ + (defined(OPENSSL_X86) || defined(OPENSSL_X86_64)) +void aesni_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out, size_t blocks, + const void *key, const uint8_t *ivec); +#endif + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_MODES_INTERNAL_H */ diff --git a/external/boringssl/crypto/modes/ofb.c b/external/boringssl/crypto/modes/ofb.c new file mode 100644 index 0000000000..2c5bdc9ab5 --- /dev/null +++ b/external/boringssl/crypto/modes/ofb.c @@ -0,0 +1,106 @@ +/* ==================================================================== + * Copyright (c) 2008 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== */ + +#include + +#include + +#include "internal.h" + + +OPENSSL_COMPILE_ASSERT((16 % sizeof(size_t)) == 0, bad_size_t_size); + +void CRYPTO_ofb128_encrypt(const uint8_t *in, uint8_t *out, size_t len, + const void *key, uint8_t ivec[16], unsigned *num, + block128_f block) { + assert(in && out && key && ivec && num); + + unsigned n = *num; + + while (n && len) { + *(out++) = *(in++) ^ ivec[n]; + --len; + n = (n + 1) % 16; + } + +#if STRICT_ALIGNMENT + if (((size_t)in | (size_t)out | (size_t)ivec) % sizeof(size_t) != 0) { + size_t l = 0; + while (l < len) { + if (n == 0) { + (*block)(ivec, ivec, key); + } + out[l] = in[l] ^ ivec[n]; + ++l; + n = (n + 1) % 16; + } + + *num = n; + return; + } +#endif + + while (len >= 16) { + (*block)(ivec, ivec, key); + for (; n < 16; n += sizeof(size_t)) { + *(size_t *)(out + n) = *(size_t *)(in + n) ^ *(size_t *)(ivec + n); + } + len -= 16; + out += 16; + in += 16; + n = 0; + } + if (len) { + (*block)(ivec, ivec, key); + while (len--) { + out[n] = in[n] ^ ivec[n]; + ++n; + } + } + *num = n; +} diff --git a/external/boringssl/crypto/newhope/CMakeLists.txt b/external/boringssl/crypto/newhope/CMakeLists.txt new file mode 100644 index 0000000000..0f080f8c5b --- /dev/null +++ b/external/boringssl/crypto/newhope/CMakeLists.txt @@ -0,0 +1,42 @@ +add_library( + newhope + + OBJECT + + error_correction.c + newhope.c + ntt.c + poly.c + precomp.c + reduce.c +) + +if(ENABLE_TESTS) +add_executable( + newhope_test + + newhope_test.cc + $ +) + +add_executable( + newhope_statistical_test + + newhope_statistical_test.cc + $ +) + +add_executable( + newhope_vectors_test + + newhope_vectors_test.cc + $ +) + +target_link_libraries(newhope_test crypto) +target_link_libraries(newhope_statistical_test crypto) +target_link_libraries(newhope_vectors_test crypto) +add_dependencies(all_tests newhope_test) +add_dependencies(all_tests newhope_statistical_test) +add_dependencies(all_tests newhope_vectors_test) +endif() diff --git a/external/boringssl/crypto/newhope/error_correction.c b/external/boringssl/crypto/newhope/error_correction.c new file mode 100644 index 0000000000..2b822b0b32 --- /dev/null +++ b/external/boringssl/crypto/newhope/error_correction.c @@ -0,0 +1,131 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include +#include + +#include "internal.h" + + +/* See paper for details on the error reconciliation */ + +static int32_t abs_32(int32_t v) { + int32_t mask = v >> 31; + return (v ^ mask) - mask; +} + +static int32_t f(int32_t* v0, int32_t* v1, int32_t x) { + int32_t xit, t, r, b; + + /* Next 6 lines compute t = x/PARAM_Q */ + b = x * 2730; + t = b >> 25; + b = x - t * 12289; + b = 12288 - b; + b >>= 31; + t -= b; + + r = t & 1; + xit = (t >> 1); + *v0 = xit + r; /* v0 = round(x/(2*PARAM_Q)) */ + + t -= 1; + r = t & 1; + *v1 = (t >> 1) + r; + + return abs_32(x - ((*v0) * 2 * PARAM_Q)); +} + +static int32_t g(int32_t x) { + int32_t t, c, b; + + /* Next 6 lines compute t = x/(4*PARAM_Q); */ + b = x * 2730; + t = b >> 27; + b = x - t * 49156; + b = 49155 - b; + b >>= 31; + t -= b; + + c = t & 1; + t = (t >> 1) + c; /* t = round(x/(8*PARAM_Q)) */ + + t *= 8 * PARAM_Q; + + return abs_32(t - x); +} + +static int16_t LDDecode(int32_t xi0, int32_t xi1, int32_t xi2, int32_t xi3) { + int32_t t; + + t = g(xi0); + t += g(xi1); + t += g(xi2); + t += g(xi3); + + t -= 8 * PARAM_Q; + t >>= 31; + return t & 1; +} + +void newhope_helprec(NEWHOPE_POLY* c, const NEWHOPE_POLY* v, + const uint8_t rand[32]) { + int32_t v0[4], v1[4], v_tmp[4], k; + uint8_t rbit; + unsigned i; + + for (i = 0; i < 256; i++) { + rbit = (rand[i >> 3] >> (i & 7)) & 1; + + k = f(v0 + 0, v1 + 0, 8 * v->coeffs[0 + i] + 4 * rbit); + k += f(v0 + 1, v1 + 1, 8 * v->coeffs[256 + i] + 4 * rbit); + k += f(v0 + 2, v1 + 2, 8 * v->coeffs[512 + i] + 4 * rbit); + k += f(v0 + 3, v1 + 3, 8 * v->coeffs[768 + i] + 4 * rbit); + + k = (2 * PARAM_Q - 1 - k) >> 31; + + v_tmp[0] = ((~k) & v0[0]) ^ (k & v1[0]); + v_tmp[1] = ((~k) & v0[1]) ^ (k & v1[1]); + v_tmp[2] = ((~k) & v0[2]) ^ (k & v1[2]); + v_tmp[3] = ((~k) & v0[3]) ^ (k & v1[3]); + + c->coeffs[0 + i] = (v_tmp[0] - v_tmp[3]) & 3; + c->coeffs[256 + i] = (v_tmp[1] - v_tmp[3]) & 3; + c->coeffs[512 + i] = (v_tmp[2] - v_tmp[3]) & 3; + c->coeffs[768 + i] = (-k + 2 * v_tmp[3]) & 3; + } +} + +void newhope_reconcile(uint8_t* key, const NEWHOPE_POLY* v, + const NEWHOPE_POLY* c) { + int i; + int32_t tmp[4]; + + memset(key, 0, NEWHOPE_KEY_LENGTH); + + for (i = 0; i < 256; i++) { + tmp[0] = 16 * PARAM_Q + 8 * (int32_t)v->coeffs[0 + i] - + PARAM_Q * (2 * c->coeffs[0 + i] + c->coeffs[768 + i]); + tmp[1] = 16 * PARAM_Q + 8 * (int32_t)v->coeffs[256 + i] - + PARAM_Q * (2 * c->coeffs[256 + i] + c->coeffs[768 + i]); + tmp[2] = 16 * PARAM_Q + 8 * (int32_t)v->coeffs[512 + i] - + PARAM_Q * (2 * c->coeffs[512 + i] + c->coeffs[768 + i]); + tmp[3] = 16 * PARAM_Q + 8 * (int32_t)v->coeffs[768 + i] - + PARAM_Q * (c->coeffs[768 + i]); + + key[i >> 3] |= LDDecode(tmp[0], tmp[1], tmp[2], tmp[3]) << (i & 7); + } +} diff --git a/external/boringssl/crypto/newhope/internal.h b/external/boringssl/crypto/newhope/internal.h new file mode 100644 index 0000000000..eb170c0661 --- /dev/null +++ b/external/boringssl/crypto/newhope/internal.h @@ -0,0 +1,71 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_NEWHOPE_INTERNAL_H +#define OPENSSL_HEADER_NEWHOPE_INTERNAL_H + +#include +#include + +#include "../internal.h" + + +/* The number of polynomial coefficients. */ +#define PARAM_N 1024 + +/* The width the noise distribution. */ +#define PARAM_K 16 + +/* Modulus. */ +#define PARAM_Q 12289 + +/* Polynomial coefficients in unpacked form. */ +struct newhope_poly_st { + uint16_t coeffs[PARAM_N]; +}; + +/* SEED_LENGTH is the length of the AES-CTR seed used to derive a polynomial. */ +#define SEED_LENGTH 32 + +/* newhope_poly_uniform generates the polynomial |a| using AES-CTR mode with the + * seed + * |seed|. (In the reference implementation this was done with SHAKE-128.) */ +void newhope_poly_uniform(NEWHOPE_POLY* a, const uint8_t* seed); + +void newhope_helprec(NEWHOPE_POLY* c, const NEWHOPE_POLY* v, + const uint8_t rbits[32]); + +/* newhope_reconcile performs the error-reconciliation step using the input |v| + * and + * reconciliation data |c|, writing the resulting key to |key|. */ +void newhope_reconcile(uint8_t* key, const NEWHOPE_POLY* v, + const NEWHOPE_POLY* c); + +/* newhope_poly_invntt performs the inverse of NTT(r) in-place. */ +void newhope_poly_invntt(NEWHOPE_POLY* r); + +void newhope_poly_add(NEWHOPE_POLY* r, const NEWHOPE_POLY* a, + const NEWHOPE_POLY* b); +void newhope_poly_pointwise(NEWHOPE_POLY* r, const NEWHOPE_POLY* a, + const NEWHOPE_POLY* b); + +uint16_t newhope_montgomery_reduce(uint32_t a); +uint16_t newhope_barrett_reduce(uint16_t a); + +void newhope_bitrev_vector(uint16_t* poly); +void newhope_mul_coefficients(uint16_t* poly, const uint16_t* factors); +void newhope_ntt(uint16_t* poly, const uint16_t* omegas); + + +#endif /* OPENSSL_HEADER_NEWHOPE_INTERNAL_H */ diff --git a/external/boringssl/crypto/newhope/newhope.c b/external/boringssl/crypto/newhope/newhope.c new file mode 100644 index 0000000000..7edb7eb7b3 --- /dev/null +++ b/external/boringssl/crypto/newhope/newhope.c @@ -0,0 +1,174 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include +#include + +#include "internal.h" + + +NEWHOPE_POLY *NEWHOPE_POLY_new(void) { + return (NEWHOPE_POLY *)OPENSSL_malloc(sizeof(NEWHOPE_POLY)); +} + +void NEWHOPE_POLY_free(NEWHOPE_POLY *p) { OPENSSL_free(p); } + +/* Encodes reconciliation data from |c| into |r|. */ +static void encode_rec(const NEWHOPE_POLY *c, uint8_t *r) { + int i; + for (i = 0; i < PARAM_N / 4; i++) { + r[i] = c->coeffs[4 * i] | (c->coeffs[4 * i + 1] << 2) | + (c->coeffs[4 * i + 2] << 4) | (c->coeffs[4 * i + 3] << 6); + } +} + +/* Decodes reconciliation data from |r| into |c|. */ +static void decode_rec(const uint8_t *r, NEWHOPE_POLY *c) { + int i; + for (i = 0; i < PARAM_N / 4; i++) { + c->coeffs[4 * i + 0] = r[i] & 0x03; + c->coeffs[4 * i + 1] = (r[i] >> 2) & 0x03; + c->coeffs[4 * i + 2] = (r[i] >> 4) & 0x03; + c->coeffs[4 * i + 3] = (r[i] >> 6); + } +} + +void NEWHOPE_offer(uint8_t *offermsg, NEWHOPE_POLY *s) { + NEWHOPE_POLY_noise_ntt(s); + + /* The first part of the offer message is the seed, which compactly encodes + * a. */ + NEWHOPE_POLY a; + uint8_t *seed = &offermsg[NEWHOPE_POLY_LENGTH]; + RAND_bytes(seed, SEED_LENGTH); + newhope_poly_uniform(&a, seed); + + NEWHOPE_POLY e; + NEWHOPE_POLY_noise_ntt(&e); + + /* The second part of the offer message is the polynomial pk = a*s+e */ + NEWHOPE_POLY pk; + NEWHOPE_offer_computation(&pk, s, &e, &a); + NEWHOPE_POLY_tobytes(offermsg, &pk); +} + +int NEWHOPE_accept(uint8_t key[SHA256_DIGEST_LENGTH], + uint8_t acceptmsg[NEWHOPE_ACCEPTMSG_LENGTH], + const uint8_t offermsg[NEWHOPE_OFFERMSG_LENGTH], + size_t msg_len) { + if (msg_len != NEWHOPE_OFFERMSG_LENGTH) { + return 0; + } + + /* Decode the |offermsg|, generating the same |a| as the peer, from the peer's + * seed. */ + NEWHOPE_POLY pk, a; + NEWHOPE_offer_frommsg(&pk, &a, offermsg); + + /* Generate noise polynomials used to generate our key. */ + NEWHOPE_POLY sp, ep, epp; + NEWHOPE_POLY_noise_ntt(&sp); + NEWHOPE_POLY_noise_ntt(&ep); + NEWHOPE_POLY_noise(&epp); /* intentionally not NTT */ + + /* Generate random bytes used for reconciliation. (The reference + * implementation calls ChaCha20 here.) */ + uint8_t rand[32]; + RAND_bytes(rand, sizeof(rand)); + + /* Encode |bp| and |c| as the |acceptmsg|. */ + NEWHOPE_POLY bp, c; + uint8_t k[NEWHOPE_KEY_LENGTH]; + NEWHOPE_accept_computation(k, &bp, &c, &sp, &ep, &epp, rand, &pk, &a); + NEWHOPE_POLY_tobytes(acceptmsg, &bp); + encode_rec(&c, &acceptmsg[NEWHOPE_POLY_LENGTH]); + + SHA256_CTX ctx; + if (!SHA256_Init(&ctx) || + !SHA256_Update(&ctx, k, NEWHOPE_KEY_LENGTH) || + !SHA256_Final(key, &ctx)) { + return 0; + } + + return 1; +} + +int NEWHOPE_finish(uint8_t key[SHA256_DIGEST_LENGTH], const NEWHOPE_POLY *sk, + const uint8_t acceptmsg[NEWHOPE_ACCEPTMSG_LENGTH], + size_t msg_len) { + if (msg_len != NEWHOPE_ACCEPTMSG_LENGTH) { + return 0; + } + + /* Decode the accept message into |bp| and |c|. */ + NEWHOPE_POLY bp, c; + NEWHOPE_POLY_frombytes(&bp, acceptmsg); + decode_rec(&acceptmsg[NEWHOPE_POLY_LENGTH], &c); + + uint8_t k[NEWHOPE_KEY_LENGTH]; + NEWHOPE_finish_computation(k, sk, &bp, &c); + SHA256_CTX ctx; + if (!SHA256_Init(&ctx) || + !SHA256_Update(&ctx, k, NEWHOPE_KEY_LENGTH) || + !SHA256_Final(key, &ctx)) { + return 0; + } + + return 1; +} + +void NEWHOPE_offer_computation(NEWHOPE_POLY *out_pk, + const NEWHOPE_POLY *s, const NEWHOPE_POLY *e, + const NEWHOPE_POLY *a) { + NEWHOPE_POLY r; + newhope_poly_pointwise(&r, s, a); + newhope_poly_add(out_pk, e, &r); +} + +void NEWHOPE_accept_computation( + uint8_t k[NEWHOPE_KEY_LENGTH], NEWHOPE_POLY *bp, + NEWHOPE_POLY *reconciliation, + const NEWHOPE_POLY *sp, const NEWHOPE_POLY *ep, const NEWHOPE_POLY *epp, + const uint8_t rand[32], + const NEWHOPE_POLY *pk, const NEWHOPE_POLY *a) { + /* bp = a*s' + e' */ + newhope_poly_pointwise(bp, a, sp); + newhope_poly_add(bp, bp, ep); + + /* v = pk * s' + e'' */ + NEWHOPE_POLY v; + newhope_poly_pointwise(&v, pk, sp); + newhope_poly_invntt(&v); + newhope_poly_add(&v, &v, epp); + newhope_helprec(reconciliation, &v, rand); + newhope_reconcile(k, &v, reconciliation); +} + +void NEWHOPE_finish_computation(uint8_t k[NEWHOPE_KEY_LENGTH], + const NEWHOPE_POLY *sk, const NEWHOPE_POLY *bp, + const NEWHOPE_POLY *reconciliation) { + NEWHOPE_POLY v; + newhope_poly_pointwise(&v, sk, bp); + newhope_poly_invntt(&v); + newhope_reconcile(k, &v, reconciliation); +} + +void NEWHOPE_offer_frommsg(NEWHOPE_POLY *out_pk, NEWHOPE_POLY *out_a, + const uint8_t offermsg[NEWHOPE_OFFERMSG_LENGTH]) { + NEWHOPE_POLY_frombytes(out_pk, offermsg); + const uint8_t *seed = offermsg + NEWHOPE_POLY_LENGTH; + newhope_poly_uniform(out_a, seed); +} diff --git a/external/boringssl/crypto/newhope/newhope_statistical_test.cc b/external/boringssl/crypto/newhope/newhope_statistical_test.cc new file mode 100644 index 0000000000..44fac48a02 --- /dev/null +++ b/external/boringssl/crypto/newhope/newhope_statistical_test.cc @@ -0,0 +1,156 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include +#include +#include + +#include +#include + +#include "../test/scoped_types.h" +#include "internal.h" + + +static const unsigned kNumTests = 1000; + +static bool TestNoise(void) { + printf("noise distribution:\n"); + + size_t buckets[1 + 2 * PARAM_K]; + memset(buckets, 0, sizeof(buckets)); + for (size_t i = 0; i < kNumTests; i++) { + NEWHOPE_POLY s; + NEWHOPE_POLY_noise(&s); + for (int j = 0; j < PARAM_N; j++) { + uint16_t value = (s.coeffs[j] + PARAM_K) % PARAM_Q; + buckets[value]++; + } + } + + int64_t sum = 0, square_sum = 0; + for (int64_t i = 0; i < 1 + 2 * PARAM_K; i++) { + sum += (i - PARAM_K) * (int64_t) buckets[i]; + square_sum += (i - PARAM_K) * (i - PARAM_K) * (int64_t) buckets[i]; + } + double mean = double(sum) / double(PARAM_N * kNumTests); + + double expected_variance = 0.5 * 0.5 * double(PARAM_K * 2); + double variance = double(square_sum) / double(PARAM_N * kNumTests) - mean * mean; + + for (size_t i = 0; i < 1 + 2 * PARAM_K; i++) { + std::string dots; + for (size_t j = 0; j < 79 * buckets[i] / buckets[PARAM_K]; j++) { + dots += "+"; + } + printf("%+zd\t%zd\t%s\n", i - PARAM_K, buckets[i], dots.c_str()); + } + printf("mean: got %f, want %f\n", mean, 0.0); + printf("variance: got %f, want %f\n", variance, expected_variance); + printf("\n"); + + if (mean < -0.5 || 0.5 < mean) { + fprintf(stderr, "mean out of range: %f\n", mean); + return false; + } + + if (variance < expected_variance - 1.0 || expected_variance + 1.0 < variance) { + fprintf(stderr, "variance out of range: got %f, want %f\n", variance, + expected_variance); + return false; + } + return true; +} + +static int Hamming32(const uint8_t key[NEWHOPE_KEY_LENGTH]) { + static int kHamming[256] = { + 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, + }; + + int r = 0; + for(int i = 0; i < NEWHOPE_KEY_LENGTH; i++) { + r += kHamming[key[i]]; + } + return r; +} + +static bool TestKeys(void) { + printf("keys (prior to whitening):\n"); + + uint8_t key[NEWHOPE_KEY_LENGTH]; + uint8_t offermsg[NEWHOPE_OFFERMSG_LENGTH]; + + ScopedNEWHOPE_POLY sk(NEWHOPE_POLY_new()), pk(NEWHOPE_POLY_new()), + sp(NEWHOPE_POLY_new()), ep(NEWHOPE_POLY_new()), epp(NEWHOPE_POLY_new()), + a(NEWHOPE_POLY_new()), bp(NEWHOPE_POLY_new()), rec(NEWHOPE_POLY_new()); + + int ones = 0; + for (size_t i = 0; i < kNumTests; i++) { + NEWHOPE_offer(offermsg, sk.get()); + NEWHOPE_offer_frommsg(pk.get(), a.get(), offermsg); + + NEWHOPE_POLY_noise_ntt(sp.get()); + NEWHOPE_POLY_noise_ntt(ep.get()); + NEWHOPE_POLY_noise(epp.get()); /* intentionally not NTT */ + + uint8_t rand[32]; + RAND_bytes(rand, 32); + + NEWHOPE_accept_computation(key, bp.get(), rec.get(), + sp.get(), ep.get(), epp.get(), rand, + pk.get(), a.get()); + ones += Hamming32(key); + } + + int bits = NEWHOPE_KEY_LENGTH * 8 * kNumTests; + int diff = bits - 2 * ones; + double fraction = (double) abs(diff) / bits; + printf("ones: %d\n", ones); + printf("zeroes: %d\n", (bits - ones)); + printf("diff: got %d (%f), want 0\n", diff, fraction); + printf("\n"); + + if (fraction > 0.01) { + fprintf(stderr, "key bias is too high (%f)\n", fraction); + return false; + } + + return true; +} + +int main(void) { + if (!TestKeys() || + !TestNoise()) { + return 1; + } + printf("PASS\n"); + return 0; +} diff --git a/external/boringssl/crypto/newhope/newhope_test.cc b/external/boringssl/crypto/newhope/newhope_test.cc new file mode 100644 index 0000000000..6637393f66 --- /dev/null +++ b/external/boringssl/crypto/newhope/newhope_test.cc @@ -0,0 +1,142 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include +#include + +#include +#include + +#include "../test/scoped_types.h" +#include "internal.h" + + +// Set to 10 for quick execution. Tested up to 1,000,000. +static const int kNumTests = 10; + +static bool TestKeys(void) { + // Alice generates a public key. + ScopedNEWHOPE_POLY sk(NEWHOPE_POLY_new()); + uint8_t offer_msg[NEWHOPE_OFFERMSG_LENGTH]; + NEWHOPE_offer(offer_msg, sk.get()); + + // Bob derives a secret key and creates a response. + uint8_t accept_msg[NEWHOPE_ACCEPTMSG_LENGTH]; + uint8_t accept_key[SHA256_DIGEST_LENGTH]; + if (!NEWHOPE_accept(accept_key, accept_msg, offer_msg, sizeof(offer_msg))) { + fprintf(stderr, "ERROR accept key exchange failed\n"); + return false; + } + + // Alice uses Bob's response to get her secret key. + uint8_t offer_key[SHA256_DIGEST_LENGTH]; + if (!NEWHOPE_finish(offer_key, sk.get(), accept_msg, sizeof(accept_msg))) { + fprintf(stderr, "ERROR finish key exchange failed\n"); + return false; + } + + if (memcmp(offer_key, accept_key, SHA256_DIGEST_LENGTH) != 0) { + fprintf(stderr, "ERROR keys did not agree\n"); + return false; + } + + return true; +} + +static bool TestInvalidSK(void) { + // Alice generates a public key. + uint8_t offer_msg[NEWHOPE_OFFERMSG_LENGTH]; + ScopedNEWHOPE_POLY sk(NEWHOPE_POLY_new()); + NEWHOPE_offer(offer_msg, sk.get()); + + // Bob derives a secret key and creates a response. + uint8_t accept_key[SHA256_DIGEST_LENGTH]; + uint8_t accept_msg[NEWHOPE_ACCEPTMSG_LENGTH]; + if (!NEWHOPE_accept(accept_key, accept_msg, offer_msg, sizeof(offer_msg))) { + fprintf(stderr, "ERROR accept key exchange failed\n"); + return false; + } + + // Corrupt the secret key. It turns out that you need to corrupt a lot of + // bits to ensure that the key exchange always fails! + sk->coeffs[PARAM_N - 1] = 0; + sk->coeffs[PARAM_N - 2] = 0; + sk->coeffs[PARAM_N - 3] = 0; + sk->coeffs[PARAM_N - 4] = 0; + + // Alice uses Bob's response to get her secret key. + uint8_t offer_key[SHA256_DIGEST_LENGTH]; + if (!NEWHOPE_finish(offer_key, sk.get(), accept_msg, sizeof(accept_msg))) { + fprintf(stderr, "ERROR finish key exchange failed\n"); + return false; + } + + if (memcmp(offer_key, accept_key, SHA256_DIGEST_LENGTH) == 0) { + fprintf(stderr, "ERROR keys agreed despite corrupt sk\n"); + return false; + } + + return true; +} + +static bool TestInvalidAcceptMsg(void) { + // Alice generates a public key. + ScopedNEWHOPE_POLY sk(NEWHOPE_POLY_new()); + uint8_t offer_msg[NEWHOPE_OFFERMSG_LENGTH]; + NEWHOPE_offer(offer_msg, sk.get()); + + // Bob derives a secret key and creates a response. + uint8_t accept_key[SHA256_DIGEST_LENGTH]; + uint8_t accept_msg[NEWHOPE_ACCEPTMSG_LENGTH]; + if (!NEWHOPE_accept(accept_key, accept_msg, offer_msg, sizeof(offer_msg))) { + fprintf(stderr, "ERROR accept key exchange failed\n"); + return false; + } + + // Corrupt the (polynomial part of the) accept message. It turns out that + // you need to corrupt a lot of bits to ensure that the key exchange always + // fails! + accept_msg[PARAM_N - 1] = 0; + accept_msg[PARAM_N - 2] = 0; + accept_msg[PARAM_N - 3] = 0; + accept_msg[PARAM_N - 4] = 0; + + // Alice uses Bob's response to get her secret key. + uint8_t offer_key[SHA256_DIGEST_LENGTH]; + if (!NEWHOPE_finish(offer_key, sk.get(), accept_msg, sizeof(accept_msg))) { + fprintf(stderr, "ERROR finish key exchange failed\n"); + return false; + } + + if (!memcmp(offer_key, accept_key, SHA256_DIGEST_LENGTH)) { + fprintf(stderr, "ERROR keys agreed despite corrupt accept message\n"); + return false; + } + + return true; +} + +int main(void) { + for (int i = 0; i < kNumTests; i++) { + if (!TestKeys() || + !TestInvalidSK() || + !TestInvalidAcceptMsg()) { + return 1; + } + } + + printf("PASS\n"); + return 0; +} diff --git a/external/boringssl/crypto/newhope/newhope_tests.txt.REMOVED.git-id b/external/boringssl/crypto/newhope/newhope_tests.txt.REMOVED.git-id new file mode 100644 index 0000000000..37d78c41dd --- /dev/null +++ b/external/boringssl/crypto/newhope/newhope_tests.txt.REMOVED.git-id @@ -0,0 +1 @@ +20d9c0371eca2e6a7a8d730e7c3c07698c5f5281 \ No newline at end of file diff --git a/external/boringssl/crypto/newhope/newhope_vectors_test.cc b/external/boringssl/crypto/newhope/newhope_vectors_test.cc new file mode 100644 index 0000000000..fe84cd4b5e --- /dev/null +++ b/external/boringssl/crypto/newhope/newhope_vectors_test.cc @@ -0,0 +1,122 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include +#include + +#include +#include + +#include "../test/file_test.h" +#include "../test/scoped_types.h" +#include "internal.h" + + +static bool TestNewhope(FileTest *t, void *arg) { + ScopedNEWHOPE_POLY a(NEWHOPE_POLY_new()); + ScopedNEWHOPE_POLY s(NEWHOPE_POLY_new()), sp(NEWHOPE_POLY_new()); + ScopedNEWHOPE_POLY e(NEWHOPE_POLY_new()), ep(NEWHOPE_POLY_new()), + epp(NEWHOPE_POLY_new()); + ScopedNEWHOPE_POLY in_pk(NEWHOPE_POLY_new()); + ScopedNEWHOPE_POLY in_rec(NEWHOPE_POLY_new()); + + if (t->GetType() == "InRandA") { + std::vector a_bytes, s_bytes, e_bytes, expected_pk; + if (!t->GetBytes(&a_bytes, "InRandA") || + !t->GetBytes(&s_bytes, "InNoiseS") || + !t->GetBytes(&e_bytes, "InNoiseE") || + !t->GetBytes(&expected_pk, "OutPK")) { + return false; + } + NEWHOPE_POLY_frombytes(a.get(), a_bytes.data()); + NEWHOPE_POLY_frombytes(s.get(), s_bytes.data()); + NEWHOPE_POLY_frombytes(e.get(), e_bytes.data()); + + NEWHOPE_POLY pk; + NEWHOPE_offer_computation(&pk, s.get(), e.get(), a.get()); + + uint8_t pk_bytes[NEWHOPE_POLY_LENGTH]; + NEWHOPE_POLY_tobytes(pk_bytes, &pk); + return t->ExpectBytesEqual(expected_pk.data(), expected_pk.size(), + pk_bytes, NEWHOPE_POLY_LENGTH); + } else if (t->GetType() == "InPK") { + std::vector rand, in_pk_bytes, a_bytes, sp_bytes, ep_bytes, + epp_bytes, expected_pk, expected_rec, expected_key; + if (!t->GetBytes(&in_pk_bytes, "InPK") || + !t->GetBytes(&rand, "InRand") || + !t->GetBytes(&a_bytes, "InA") || + !t->GetBytes(&sp_bytes, "InNoiseSP") || + !t->GetBytes(&ep_bytes, "InNoiseEP") || + !t->GetBytes(&epp_bytes, "InNoiseEPP") || + !t->GetBytes(&expected_pk, "OutPK") || + !t->GetBytes(&expected_rec, "OutRec") || + !t->GetBytes(&expected_key, "Key")) { + return false; + } + NEWHOPE_POLY_frombytes(in_pk.get(), in_pk_bytes.data()); + NEWHOPE_POLY_frombytes(a.get(), a_bytes.data()); + NEWHOPE_POLY_frombytes(sp.get(), sp_bytes.data()); + NEWHOPE_POLY_frombytes(ep.get(), ep_bytes.data()); + NEWHOPE_POLY_frombytes(epp.get(), epp_bytes.data()); + + uint8_t key[NEWHOPE_KEY_LENGTH]; + NEWHOPE_POLY pk, rec; + NEWHOPE_accept_computation(key, &pk, &rec, + sp.get(), ep.get(), epp.get(), + rand.data(), in_pk.get(), a.get()); + + uint8_t pk_bytes[NEWHOPE_POLY_LENGTH], rec_bytes[NEWHOPE_POLY_LENGTH]; + NEWHOPE_POLY_tobytes(pk_bytes, &pk); + NEWHOPE_POLY_tobytes(rec_bytes, &rec); + return + t->ExpectBytesEqual(expected_key.data(), expected_key.size(), + key, NEWHOPE_KEY_LENGTH) && + t->ExpectBytesEqual(expected_pk.data(), expected_pk.size(), + pk_bytes, NEWHOPE_POLY_LENGTH) && + t->ExpectBytesEqual(expected_rec.data(), expected_rec.size(), + rec_bytes, NEWHOPE_POLY_LENGTH); + } else if (t->GetType() == "InNoiseS") { + std::vector s_bytes, in_pk_bytes, in_rec_bytes, expected_key; + if (!t->GetBytes(&s_bytes, "InNoiseS") || + !t->GetBytes(&in_pk_bytes, "InPK") || + !t->GetBytes(&in_rec_bytes, "InRec") || + !t->GetBytes(&expected_key, "Key")) { + return false; + } + NEWHOPE_POLY_frombytes(s.get(), s_bytes.data()); + NEWHOPE_POLY_frombytes(in_pk.get(), in_pk_bytes.data()); + NEWHOPE_POLY_frombytes(in_rec.get(), in_rec_bytes.data()); + + uint8_t key[NEWHOPE_KEY_LENGTH]; + NEWHOPE_finish_computation(key, s.get(), in_pk.get(), in_rec.get()); + + return t->ExpectBytesEqual(expected_key.data(), expected_key.size(), key, + NEWHOPE_KEY_LENGTH); + } else { + t->PrintLine("Unknown test '%s'", t->GetType().c_str()); + return false; + } +} + +int main(int argc, char **argv) { + CRYPTO_library_init(); + + if (argc != 2) { + fprintf(stderr, "%s \n", argv[0]); + return 1; + } + + return FileTestMain(TestNewhope, nullptr, argv[1]); +} diff --git a/external/boringssl/crypto/newhope/ntt.c b/external/boringssl/crypto/newhope/ntt.c new file mode 100644 index 0000000000..163a9d1a0c --- /dev/null +++ b/external/boringssl/crypto/newhope/ntt.c @@ -0,0 +1,148 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include "internal.h" + + +static uint16_t bitrev_table[1024] = { + 0, 512, 256, 768, 128, 640, 384, 896, 64, 576, 320, 832, 192, 704, + 448, 960, 32, 544, 288, 800, 160, 672, 416, 928, 96, 608, 352, 864, + 224, 736, 480, 992, 16, 528, 272, 784, 144, 656, 400, 912, 80, 592, + 336, 848, 208, 720, 464, 976, 48, 560, 304, 816, 176, 688, 432, 944, + 112, 624, 368, 880, 240, 752, 496, 1008, 8, 520, 264, 776, 136, 648, + 392, 904, 72, 584, 328, 840, 200, 712, 456, 968, 40, 552, 296, 808, + 168, 680, 424, 936, 104, 616, 360, 872, 232, 744, 488, 1000, 24, 536, + 280, 792, 152, 664, 408, 920, 88, 600, 344, 856, 216, 728, 472, 984, + 56, 568, 312, 824, 184, 696, 440, 952, 120, 632, 376, 888, 248, 760, + 504, 1016, 4, 516, 260, 772, 132, 644, 388, 900, 68, 580, 324, 836, + 196, 708, 452, 964, 36, 548, 292, 804, 164, 676, 420, 932, 100, 612, + 356, 868, 228, 740, 484, 996, 20, 532, 276, 788, 148, 660, 404, 916, + 84, 596, 340, 852, 212, 724, 468, 980, 52, 564, 308, 820, 180, 692, + 436, 948, 116, 628, 372, 884, 244, 756, 500, 1012, 12, 524, 268, 780, + 140, 652, 396, 908, 76, 588, 332, 844, 204, 716, 460, 972, 44, 556, + 300, 812, 172, 684, 428, 940, 108, 620, 364, 876, 236, 748, 492, 1004, + 28, 540, 284, 796, 156, 668, 412, 924, 92, 604, 348, 860, 220, 732, + 476, 988, 60, 572, 316, 828, 188, 700, 444, 956, 124, 636, 380, 892, + 252, 764, 508, 1020, 2, 514, 258, 770, 130, 642, 386, 898, 66, 578, + 322, 834, 194, 706, 450, 962, 34, 546, 290, 802, 162, 674, 418, 930, + 98, 610, 354, 866, 226, 738, 482, 994, 18, 530, 274, 786, 146, 658, + 402, 914, 82, 594, 338, 850, 210, 722, 466, 978, 50, 562, 306, 818, + 178, 690, 434, 946, 114, 626, 370, 882, 242, 754, 498, 1010, 10, 522, + 266, 778, 138, 650, 394, 906, 74, 586, 330, 842, 202, 714, 458, 970, + 42, 554, 298, 810, 170, 682, 426, 938, 106, 618, 362, 874, 234, 746, + 490, 1002, 26, 538, 282, 794, 154, 666, 410, 922, 90, 602, 346, 858, + 218, 730, 474, 986, 58, 570, 314, 826, 186, 698, 442, 954, 122, 634, + 378, 890, 250, 762, 506, 1018, 6, 518, 262, 774, 134, 646, 390, 902, + 70, 582, 326, 838, 198, 710, 454, 966, 38, 550, 294, 806, 166, 678, + 422, 934, 102, 614, 358, 870, 230, 742, 486, 998, 22, 534, 278, 790, + 150, 662, 406, 918, 86, 598, 342, 854, 214, 726, 470, 982, 54, 566, + 310, 822, 182, 694, 438, 950, 118, 630, 374, 886, 246, 758, 502, 1014, + 14, 526, 270, 782, 142, 654, 398, 910, 78, 590, 334, 846, 206, 718, + 462, 974, 46, 558, 302, 814, 174, 686, 430, 942, 110, 622, 366, 878, + 238, 750, 494, 1006, 30, 542, 286, 798, 158, 670, 414, 926, 94, 606, + 350, 862, 222, 734, 478, 990, 62, 574, 318, 830, 190, 702, 446, 958, + 126, 638, 382, 894, 254, 766, 510, 1022, 1, 513, 257, 769, 129, 641, + 385, 897, 65, 577, 321, 833, 193, 705, 449, 961, 33, 545, 289, 801, + 161, 673, 417, 929, 97, 609, 353, 865, 225, 737, 481, 993, 17, 529, + 273, 785, 145, 657, 401, 913, 81, 593, 337, 849, 209, 721, 465, 977, + 49, 561, 305, 817, 177, 689, 433, 945, 113, 625, 369, 881, 241, 753, + 497, 1009, 9, 521, 265, 777, 137, 649, 393, 905, 73, 585, 329, 841, + 201, 713, 457, 969, 41, 553, 297, 809, 169, 681, 425, 937, 105, 617, + 361, 873, 233, 745, 489, 1001, 25, 537, 281, 793, 153, 665, 409, 921, + 89, 601, 345, 857, 217, 729, 473, 985, 57, 569, 313, 825, 185, 697, + 441, 953, 121, 633, 377, 889, 249, 761, 505, 1017, 5, 517, 261, 773, + 133, 645, 389, 901, 69, 581, 325, 837, 197, 709, 453, 965, 37, 549, + 293, 805, 165, 677, 421, 933, 101, 613, 357, 869, 229, 741, 485, 997, + 21, 533, 277, 789, 149, 661, 405, 917, 85, 597, 341, 853, 213, 725, + 469, 981, 53, 565, 309, 821, 181, 693, 437, 949, 117, 629, 373, 885, + 245, 757, 501, 1013, 13, 525, 269, 781, 141, 653, 397, 909, 77, 589, + 333, 845, 205, 717, 461, 973, 45, 557, 301, 813, 173, 685, 429, 941, + 109, 621, 365, 877, 237, 749, 493, 1005, 29, 541, 285, 797, 157, 669, + 413, 925, 93, 605, 349, 861, 221, 733, 477, 989, 61, 573, 317, 829, + 189, 701, 445, 957, 125, 637, 381, 893, 253, 765, 509, 1021, 3, 515, + 259, 771, 131, 643, 387, 899, 67, 579, 323, 835, 195, 707, 451, 963, + 35, 547, 291, 803, 163, 675, 419, 931, 99, 611, 355, 867, 227, 739, + 483, 995, 19, 531, 275, 787, 147, 659, 403, 915, 83, 595, 339, 851, + 211, 723, 467, 979, 51, 563, 307, 819, 179, 691, 435, 947, 115, 627, + 371, 883, 243, 755, 499, 1011, 11, 523, 267, 779, 139, 651, 395, 907, + 75, 587, 331, 843, 203, 715, 459, 971, 43, 555, 299, 811, 171, 683, + 427, 939, 107, 619, 363, 875, 235, 747, 491, 1003, 27, 539, 283, 795, + 155, 667, 411, 923, 91, 603, 347, 859, 219, 731, 475, 987, 59, 571, + 315, 827, 187, 699, 443, 955, 123, 635, 379, 891, 251, 763, 507, 1019, + 7, 519, 263, 775, 135, 647, 391, 903, 71, 583, 327, 839, 199, 711, + 455, 967, 39, 551, 295, 807, 167, 679, 423, 935, 103, 615, 359, 871, + 231, 743, 487, 999, 23, 535, 279, 791, 151, 663, 407, 919, 87, 599, + 343, 855, 215, 727, 471, 983, 55, 567, 311, 823, 183, 695, 439, 951, + 119, 631, 375, 887, 247, 759, 503, 1015, 15, 527, 271, 783, 143, 655, + 399, 911, 79, 591, 335, 847, 207, 719, 463, 975, 47, 559, 303, 815, + 175, 687, 431, 943, 111, 623, 367, 879, 239, 751, 495, 1007, 31, 543, + 287, 799, 159, 671, 415, 927, 95, 607, 351, 863, 223, 735, 479, 991, + 63, 575, 319, 831, 191, 703, 447, 959, 127, 639, 383, 895, 255, 767, + 511, 1023}; + +void newhope_bitrev_vector(uint16_t* poly) { + unsigned int i, r; + uint16_t tmp; + + for (i = 0; i < PARAM_N; i++) { + r = bitrev_table[i]; + if (i < r) { + tmp = poly[i]; + poly[i] = poly[r]; + poly[r] = tmp; + } + } +} + +void newhope_mul_coefficients(uint16_t* poly, const uint16_t* factors) { + unsigned int i; + + for (i = 0; i < PARAM_N; i++) { + poly[i] = newhope_montgomery_reduce((poly[i] * factors[i])); + } +} + +/* GS_bo_to_no; omegas need to be in Montgomery domain */ +void newhope_ntt(uint16_t* a, const uint16_t* omega) { + int i, start, j, jTwiddle, distance; + uint16_t temp, W; + + for (i = 0; i < 10; i += 2) { + /* Even level */ + distance = (1 << i); + for (start = 0; start < distance; start++) { + jTwiddle = 0; + for (j = start; j < PARAM_N - 1; j += 2 * distance) { + W = omega[jTwiddle++]; + temp = a[j]; + a[j] = (temp + a[j + distance]); /* Omit reduction (be lazy) */ + a[j + distance] = newhope_montgomery_reduce( + (W * ((uint32_t)temp + 3 * PARAM_Q - a[j + distance]))); + } + } + + /* Odd level */ + distance <<= 1; + for (start = 0; start < distance; start++) { + jTwiddle = 0; + for (j = start; j < PARAM_N - 1; j += 2 * distance) { + W = omega[jTwiddle++]; + temp = a[j]; + a[j] = newhope_barrett_reduce((temp + a[j + distance])); + a[j + distance] = newhope_montgomery_reduce( + (W * ((uint32_t)temp + 3 * PARAM_Q - a[j + distance]))); + } + } + } +} diff --git a/external/boringssl/crypto/newhope/poly.c b/external/boringssl/crypto/newhope/poly.c new file mode 100644 index 0000000000..44cd3839bd --- /dev/null +++ b/external/boringssl/crypto/newhope/poly.c @@ -0,0 +1,189 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include + +#include +#include + +#include "internal.h" + + +extern uint16_t newhope_omegas_montgomery[]; +extern uint16_t newhope_omegas_inv_montgomery[]; + +extern uint16_t newhope_psis_bitrev_montgomery[]; +extern uint16_t newhope_psis_inv_montgomery[]; + +void NEWHOPE_POLY_frombytes(NEWHOPE_POLY* r, const uint8_t* a) { + int i; + for (i = 0; i < PARAM_N / 4; i++) { + r->coeffs[4 * i + 0] = + a[7 * i + 0] | (((uint16_t)a[7 * i + 1] & 0x3f) << 8); + r->coeffs[4 * i + 1] = (a[7 * i + 1] >> 6) | + (((uint16_t)a[7 * i + 2]) << 2) | + (((uint16_t)a[7 * i + 3] & 0x0f) << 10); + r->coeffs[4 * i + 2] = (a[7 * i + 3] >> 4) | + (((uint16_t)a[7 * i + 4]) << 4) | + (((uint16_t)a[7 * i + 5] & 0x03) << 12); + r->coeffs[4 * i + 3] = + (a[7 * i + 5] >> 2) | (((uint16_t)a[7 * i + 6]) << 6); + } +} + +void NEWHOPE_POLY_tobytes(uint8_t* r, const NEWHOPE_POLY* p) { + int i; + uint16_t t0, t1, t2, t3, m; + int16_t c; + for (i = 0; i < PARAM_N / 4; i++) { + t0 = newhope_barrett_reduce( + p->coeffs[4 * i + 0]); /* Make sure that coefficients + have only 14 bits */ + t1 = newhope_barrett_reduce(p->coeffs[4 * i + 1]); + t2 = newhope_barrett_reduce(p->coeffs[4 * i + 2]); + t3 = newhope_barrett_reduce(p->coeffs[4 * i + 3]); + + m = t0 - PARAM_Q; + c = m; + c >>= 15; + t0 = m ^ ((t0 ^ m) & c); /* Make sure that coefficients are in [0,q] */ + + m = t1 - PARAM_Q; + c = m; + c >>= 15; + t1 = m ^ ((t1 ^ m) & c); /* >= 15; + t2 = m ^ ((t2 ^ m) & c); /* >= 15; + t3 = m ^ ((t3 ^ m) & c); /* Make sure that coefficients are in [0,q] */ + + r[7 * i + 0] = t0 & 0xff; + r[7 * i + 1] = (t0 >> 8) | (t1 << 6); + r[7 * i + 2] = (t1 >> 2); + r[7 * i + 3] = (t1 >> 10) | (t2 << 4); + r[7 * i + 4] = (t2 >> 4); + r[7 * i + 5] = (t2 >> 12) | (t3 << 2); + r[7 * i + 6] = (t3 >> 6); + } +} + +void newhope_poly_uniform(NEWHOPE_POLY* a, const uint8_t* seed) { +/* The reference implementation uses SHAKE-128 here; this implementation uses + * AES-CTR. Use half the seed for the initialization vector and half for the + * key. */ +#if SEED_LENGTH != 2 * AES_BLOCK_SIZE +#error "2 * seed length != AES_BLOCK_SIZE" +#endif + uint8_t ivec[AES_BLOCK_SIZE]; + memcpy(ivec, &seed[SEED_LENGTH / 2], SEED_LENGTH / 2); + AES_KEY key; + AES_set_encrypt_key(seed, 8 * SEED_LENGTH / 2, &key); + + /* AES state. */ + uint8_t ecount[AES_BLOCK_SIZE]; + memset(ecount, 0, AES_BLOCK_SIZE); + + /* Encrypt a block of zeros just to get the random bytes. With luck, 2688 + * bytes is enough. */ + uint8_t buf[AES_BLOCK_SIZE * 168]; + memset(buf, 0, sizeof(buf)); + + unsigned int block_num = 0; + AES_ctr128_encrypt(buf, buf, sizeof(buf), &key, ivec, ecount, &block_num); + + size_t pos = 0, coeff_num = 0; + while (coeff_num < PARAM_N) { + /* Specialized for q = 12889 */ + uint16_t val = (buf[pos] | ((uint16_t)buf[pos + 1] << 8)) & 0x3fff; + if (val < PARAM_Q) { + a->coeffs[coeff_num++] = val; + } + + pos += 2; + if (pos > sizeof(buf) - 2) { + memset(buf, 0, sizeof(buf)); + AES_ctr128_encrypt(buf, buf, sizeof(buf), &key, ivec, ecount, &block_num); + pos = 0; + } + } +} + +void NEWHOPE_POLY_noise(NEWHOPE_POLY* r) { +#if PARAM_K != 16 +#error "poly_getnoise in poly.c only supports k=16" +#endif + + uint32_t tp[PARAM_N]; + + /* The reference implementation calls ChaCha20 here. */ + RAND_bytes((uint8_t *) tp, sizeof(tp)); + + size_t i; + for (i = 0; i < PARAM_N; i++) { + const uint32_t t = tp[i]; + + size_t j; + uint32_t d = 0; + for (j = 0; j < 8; j++) { + d += (t >> j) & 0x01010101; + } + + const uint32_t a = ((d >> 8) & 0xff) + (d & 0xff); + const uint32_t b = (d >> 24) + ((d >> 16) & 0xff); + r->coeffs[i] = a + PARAM_Q - b; + } +} + +void newhope_poly_pointwise(NEWHOPE_POLY* r, const NEWHOPE_POLY* a, + const NEWHOPE_POLY* b) { + size_t i; + for (i = 0; i < PARAM_N; i++) { + uint16_t t = newhope_montgomery_reduce(3186 * b->coeffs[i]); + /* t is now in Montgomery domain */ + r->coeffs[i] = newhope_montgomery_reduce(a->coeffs[i] * t); + /* r->coeffs[i] is back in normal domain */ + } +} + +void newhope_poly_add(NEWHOPE_POLY* r, const NEWHOPE_POLY* a, + const NEWHOPE_POLY* b) { + size_t i; + for (i = 0; i < PARAM_N; i++) { + r->coeffs[i] = newhope_barrett_reduce(a->coeffs[i] + b->coeffs[i]); + } +} + +void NEWHOPE_POLY_noise_ntt(NEWHOPE_POLY* r) { + NEWHOPE_POLY_noise(r); + /* Forward NTT transformation. Because we're operating on a noise polynomial, + * we can regard the bits as already reversed and skip the bit-reversal + * step: + * + * newhope_bitrev_vector(r->coeffs); */ + newhope_mul_coefficients(r->coeffs, newhope_psis_bitrev_montgomery); + newhope_ntt((uint16_t *) r->coeffs, newhope_omegas_montgomery); +} + +void newhope_poly_invntt(NEWHOPE_POLY* r) { + newhope_bitrev_vector(r->coeffs); + newhope_ntt((uint16_t *) r->coeffs, newhope_omegas_inv_montgomery); + newhope_mul_coefficients(r->coeffs, newhope_psis_inv_montgomery); +} diff --git a/external/boringssl/crypto/newhope/precomp.c b/external/boringssl/crypto/newhope/precomp.c new file mode 100644 index 0000000000..d0c478eefe --- /dev/null +++ b/external/boringssl/crypto/newhope/precomp.c @@ -0,0 +1,306 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include "internal.h" + + +uint16_t newhope_omegas_montgomery[PARAM_N / 2] = { + 4075, 6974, 7373, 7965, 3262, 5079, 522, 2169, 6364, 1018, 1041, + 8775, 2344, 11011, 5574, 1973, 4536, 1050, 6844, 3860, 3818, 6118, + 2683, 1190, 4789, 7822, 7540, 6752, 5456, 4449, 3789, 12142, 11973, + 382, 3988, 468, 6843, 5339, 6196, 3710, 11316, 1254, 5435, 10930, + 3998, 10256, 10367, 3879, 11889, 1728, 6137, 4948, 5862, 6136, 3643, + 6874, 8724, 654, 10302, 1702, 7083, 6760, 56, 3199, 9987, 605, + 11785, 8076, 5594, 9260, 6403, 4782, 6212, 4624, 9026, 8689, 4080, + 11868, 6221, 3602, 975, 8077, 8851, 9445, 5681, 3477, 1105, 142, + 241, 12231, 1003, 3532, 5009, 1956, 6008, 11404, 7377, 2049, 10968, + 12097, 7591, 5057, 3445, 4780, 2920, 7048, 3127, 8120, 11279, 6821, + 11502, 8807, 12138, 2127, 2839, 3957, 431, 1579, 6383, 9784, 5874, + 677, 3336, 6234, 2766, 1323, 9115, 12237, 2031, 6956, 6413, 2281, + 3969, 3991, 12133, 9522, 4737, 10996, 4774, 5429, 11871, 3772, 453, + 5908, 2882, 1805, 2051, 1954, 11713, 3963, 2447, 6142, 8174, 3030, + 1843, 2361, 12071, 2908, 3529, 3434, 3202, 7796, 2057, 5369, 11939, + 1512, 6906, 10474, 11026, 49, 10806, 5915, 1489, 9789, 5942, 10706, + 10431, 7535, 426, 8974, 3757, 10314, 9364, 347, 5868, 9551, 9634, + 6554, 10596, 9280, 11566, 174, 2948, 2503, 6507, 10723, 11606, 2459, + 64, 3656, 8455, 5257, 5919, 7856, 1747, 9166, 5486, 9235, 6065, + 835, 3570, 4240, 11580, 4046, 10970, 9139, 1058, 8210, 11848, 922, + 7967, 1958, 10211, 1112, 3728, 4049, 11130, 5990, 1404, 325, 948, + 11143, 6190, 295, 11637, 5766, 8212, 8273, 2919, 8527, 6119, 6992, + 8333, 1360, 2555, 6167, 1200, 7105, 7991, 3329, 9597, 12121, 5106, + 5961, 10695, 10327, 3051, 9923, 4896, 9326, 81, 3091, 1000, 7969, + 4611, 726, 1853, 12149, 4255, 11112, 2768, 10654, 1062, 2294, 3553, + 4805, 2747, 4846, 8577, 9154, 1170, 2319, 790, 11334, 9275, 9088, + 1326, 5086, 9094, 6429, 11077, 10643, 3504, 3542, 8668, 9744, 1479, + 1, 8246, 7143, 11567, 10984, 4134, 5736, 4978, 10938, 5777, 8961, + 4591, 5728, 6461, 5023, 9650, 7468, 949, 9664, 2975, 11726, 2744, + 9283, 10092, 5067, 12171, 2476, 3748, 11336, 6522, 827, 9452, 5374, + 12159, 7935, 3296, 3949, 9893, 4452, 10908, 2525, 3584, 8112, 8011, + 10616, 4989, 6958, 11809, 9447, 12280, 1022, 11950, 9821, 11745, 5791, + 5092, 2089, 9005, 2881, 3289, 2013, 9048, 729, 7901, 1260, 5755, + 4632, 11955, 2426, 10593, 1428, 4890, 5911, 3932, 9558, 8830, 3637, + 5542, 145, 5179, 8595, 3707, 10530, 355, 3382, 4231, 9741, 1207, + 9041, 7012, 1168, 10146, 11224, 4645, 11885, 10911, 10377, 435, 7952, + 4096, 493, 9908, 6845, 6039, 2422, 2187, 9723, 8643, 9852, 9302, + 6022, 7278, 1002, 4284, 5088, 1607, 7313, 875, 8509, 9430, 1045, + 2481, 5012, 7428, 354, 6591, 9377, 11847, 2401, 1067, 7188, 11516, + 390, 8511, 8456, 7270, 545, 8585, 9611, 12047, 1537, 4143, 4714, + 4885, 1017, 5084, 1632, 3066, 27, 1440, 8526, 9273, 12046, 11618, + 9289, 3400, 9890, 3136, 7098, 8758, 11813, 7384, 3985, 11869, 6730, + 10745, 10111, 2249, 4048, 2884, 11136, 2126, 1630, 9103, 5407, 2686, + 9042, 2969, 8311, 9424, 9919, 8779, 5332, 10626, 1777, 4654, 10863, + 7351, 3636, 9585, 5291, 8374, 2166, 4919, 12176, 9140, 12129, 7852, + 12286, 4895, 10805, 2780, 5195, 2305, 7247, 9644, 4053, 10600, 3364, + 3271, 4057, 4414, 9442, 7917, 2174}; + +uint16_t newhope_omegas_inv_montgomery[PARAM_N / 2] = { + 4075, 5315, 4324, 4916, 10120, 11767, 7210, 9027, 10316, 6715, 1278, + 9945, 3514, 11248, 11271, 5925, 147, 8500, 7840, 6833, 5537, 4749, + 4467, 7500, 11099, 9606, 6171, 8471, 8429, 5445, 11239, 7753, 9090, + 12233, 5529, 5206, 10587, 1987, 11635, 3565, 5415, 8646, 6153, 6427, + 7341, 6152, 10561, 400, 8410, 1922, 2033, 8291, 1359, 6854, 11035, + 973, 8579, 6093, 6950, 5446, 11821, 8301, 11907, 316, 52, 3174, + 10966, 9523, 6055, 8953, 11612, 6415, 2505, 5906, 10710, 11858, 8332, + 9450, 10162, 151, 3482, 787, 5468, 1010, 4169, 9162, 5241, 9369, + 7509, 8844, 7232, 4698, 192, 1321, 10240, 4912, 885, 6281, 10333, + 7280, 8757, 11286, 58, 12048, 12147, 11184, 8812, 6608, 2844, 3438, + 4212, 11314, 8687, 6068, 421, 8209, 3600, 3263, 7665, 6077, 7507, + 5886, 3029, 6695, 4213, 504, 11684, 2302, 1962, 1594, 6328, 7183, + 168, 2692, 8960, 4298, 5184, 11089, 6122, 9734, 10929, 3956, 5297, + 6170, 3762, 9370, 4016, 4077, 6523, 652, 11994, 6099, 1146, 11341, + 11964, 10885, 6299, 1159, 8240, 8561, 11177, 2078, 10331, 4322, 11367, + 441, 4079, 11231, 3150, 1319, 8243, 709, 8049, 8719, 11454, 6224, + 3054, 6803, 3123, 10542, 4433, 6370, 7032, 3834, 8633, 12225, 9830, + 683, 1566, 5782, 9786, 9341, 12115, 723, 3009, 1693, 5735, 2655, + 2738, 6421, 11942, 2925, 1975, 8532, 3315, 11863, 4754, 1858, 1583, + 6347, 2500, 10800, 6374, 1483, 12240, 1263, 1815, 5383, 10777, 350, + 6920, 10232, 4493, 9087, 8855, 8760, 9381, 218, 9928, 10446, 9259, + 4115, 6147, 9842, 8326, 576, 10335, 10238, 10484, 9407, 6381, 11836, + 8517, 418, 6860, 7515, 1293, 7552, 2767, 156, 8298, 8320, 10008, + 5876, 5333, 10258, 10115, 4372, 2847, 7875, 8232, 9018, 8925, 1689, + 8236, 2645, 5042, 9984, 7094, 9509, 1484, 7394, 3, 4437, 160, + 3149, 113, 7370, 10123, 3915, 6998, 2704, 8653, 4938, 1426, 7635, + 10512, 1663, 6957, 3510, 2370, 2865, 3978, 9320, 3247, 9603, 6882, + 3186, 10659, 10163, 1153, 9405, 8241, 10040, 2178, 1544, 5559, 420, + 8304, 4905, 476, 3531, 5191, 9153, 2399, 8889, 3000, 671, 243, + 3016, 3763, 10849, 12262, 9223, 10657, 7205, 11272, 7404, 7575, 8146, + 10752, 242, 2678, 3704, 11744, 5019, 3833, 3778, 11899, 773, 5101, + 11222, 9888, 442, 2912, 5698, 11935, 4861, 7277, 9808, 11244, 2859, + 3780, 11414, 4976, 10682, 7201, 8005, 11287, 5011, 6267, 2987, 2437, + 3646, 2566, 10102, 9867, 6250, 5444, 2381, 11796, 8193, 4337, 11854, + 1912, 1378, 404, 7644, 1065, 2143, 11121, 5277, 3248, 11082, 2548, + 8058, 8907, 11934, 1759, 8582, 3694, 7110, 12144, 6747, 8652, 3459, + 2731, 8357, 6378, 7399, 10861, 1696, 9863, 334, 7657, 6534, 11029, + 4388, 11560, 3241, 10276, 9000, 9408, 3284, 10200, 7197, 6498, 544, + 2468, 339, 11267, 9, 2842, 480, 5331, 7300, 1673, 4278, 4177, + 8705, 9764, 1381, 7837, 2396, 8340, 8993, 4354, 130, 6915, 2837, + 11462, 5767, 953, 8541, 9813, 118, 7222, 2197, 3006, 9545, 563, + 9314, 2625, 11340, 4821, 2639, 7266, 5828, 6561, 7698, 3328, 6512, + 1351, 7311, 6553, 8155, 1305, 722, 5146, 4043, 12288, 10810, 2545, + 3621, 8747, 8785, 1646, 1212, 5860, 3195, 7203, 10963, 3201, 3014, + 955, 11499, 9970, 11119, 3135, 3712, 7443, 9542, 7484, 8736, 9995, + 11227, 1635, 9521, 1177, 8034, 140, 10436, 11563, 7678, 4320, 11289, + 9198, 12208, 2963, 7393, 2366, 9238}; + +uint16_t newhope_psis_bitrev_montgomery[PARAM_N] = { + 4075, 6974, 7373, 7965, 3262, 5079, 522, 2169, 6364, 1018, 1041, + 8775, 2344, 11011, 5574, 1973, 4536, 1050, 6844, 3860, 3818, 6118, + 2683, 1190, 4789, 7822, 7540, 6752, 5456, 4449, 3789, 12142, 11973, + 382, 3988, 468, 6843, 5339, 6196, 3710, 11316, 1254, 5435, 10930, + 3998, 10256, 10367, 3879, 11889, 1728, 6137, 4948, 5862, 6136, 3643, + 6874, 8724, 654, 10302, 1702, 7083, 6760, 56, 3199, 9987, 605, + 11785, 8076, 5594, 9260, 6403, 4782, 6212, 4624, 9026, 8689, 4080, + 11868, 6221, 3602, 975, 8077, 8851, 9445, 5681, 3477, 1105, 142, + 241, 12231, 1003, 3532, 5009, 1956, 6008, 11404, 7377, 2049, 10968, + 12097, 7591, 5057, 3445, 4780, 2920, 7048, 3127, 8120, 11279, 6821, + 11502, 8807, 12138, 2127, 2839, 3957, 431, 1579, 6383, 9784, 5874, + 677, 3336, 6234, 2766, 1323, 9115, 12237, 2031, 6956, 6413, 2281, + 3969, 3991, 12133, 9522, 4737, 10996, 4774, 5429, 11871, 3772, 453, + 5908, 2882, 1805, 2051, 1954, 11713, 3963, 2447, 6142, 8174, 3030, + 1843, 2361, 12071, 2908, 3529, 3434, 3202, 7796, 2057, 5369, 11939, + 1512, 6906, 10474, 11026, 49, 10806, 5915, 1489, 9789, 5942, 10706, + 10431, 7535, 426, 8974, 3757, 10314, 9364, 347, 5868, 9551, 9634, + 6554, 10596, 9280, 11566, 174, 2948, 2503, 6507, 10723, 11606, 2459, + 64, 3656, 8455, 5257, 5919, 7856, 1747, 9166, 5486, 9235, 6065, + 835, 3570, 4240, 11580, 4046, 10970, 9139, 1058, 8210, 11848, 922, + 7967, 1958, 10211, 1112, 3728, 4049, 11130, 5990, 1404, 325, 948, + 11143, 6190, 295, 11637, 5766, 8212, 8273, 2919, 8527, 6119, 6992, + 8333, 1360, 2555, 6167, 1200, 7105, 7991, 3329, 9597, 12121, 5106, + 5961, 10695, 10327, 3051, 9923, 4896, 9326, 81, 3091, 1000, 7969, + 4611, 726, 1853, 12149, 4255, 11112, 2768, 10654, 1062, 2294, 3553, + 4805, 2747, 4846, 8577, 9154, 1170, 2319, 790, 11334, 9275, 9088, + 1326, 5086, 9094, 6429, 11077, 10643, 3504, 3542, 8668, 9744, 1479, + 1, 8246, 7143, 11567, 10984, 4134, 5736, 4978, 10938, 5777, 8961, + 4591, 5728, 6461, 5023, 9650, 7468, 949, 9664, 2975, 11726, 2744, + 9283, 10092, 5067, 12171, 2476, 3748, 11336, 6522, 827, 9452, 5374, + 12159, 7935, 3296, 3949, 9893, 4452, 10908, 2525, 3584, 8112, 8011, + 10616, 4989, 6958, 11809, 9447, 12280, 1022, 11950, 9821, 11745, 5791, + 5092, 2089, 9005, 2881, 3289, 2013, 9048, 729, 7901, 1260, 5755, + 4632, 11955, 2426, 10593, 1428, 4890, 5911, 3932, 9558, 8830, 3637, + 5542, 145, 5179, 8595, 3707, 10530, 355, 3382, 4231, 9741, 1207, + 9041, 7012, 1168, 10146, 11224, 4645, 11885, 10911, 10377, 435, 7952, + 4096, 493, 9908, 6845, 6039, 2422, 2187, 9723, 8643, 9852, 9302, + 6022, 7278, 1002, 4284, 5088, 1607, 7313, 875, 8509, 9430, 1045, + 2481, 5012, 7428, 354, 6591, 9377, 11847, 2401, 1067, 7188, 11516, + 390, 8511, 8456, 7270, 545, 8585, 9611, 12047, 1537, 4143, 4714, + 4885, 1017, 5084, 1632, 3066, 27, 1440, 8526, 9273, 12046, 11618, + 9289, 3400, 9890, 3136, 7098, 8758, 11813, 7384, 3985, 11869, 6730, + 10745, 10111, 2249, 4048, 2884, 11136, 2126, 1630, 9103, 5407, 2686, + 9042, 2969, 8311, 9424, 9919, 8779, 5332, 10626, 1777, 4654, 10863, + 7351, 3636, 9585, 5291, 8374, 2166, 4919, 12176, 9140, 12129, 7852, + 12286, 4895, 10805, 2780, 5195, 2305, 7247, 9644, 4053, 10600, 3364, + 3271, 4057, 4414, 9442, 7917, 2174, 3947, 11951, 2455, 6599, 10545, + 10975, 3654, 2894, 7681, 7126, 7287, 12269, 4119, 3343, 2151, 1522, + 7174, 7350, 11041, 2442, 2148, 5959, 6492, 8330, 8945, 5598, 3624, + 10397, 1325, 6565, 1945, 11260, 10077, 2674, 3338, 3276, 11034, 506, + 6505, 1392, 5478, 8778, 1178, 2776, 3408, 10347, 11124, 2575, 9489, + 12096, 6092, 10058, 4167, 6085, 923, 11251, 11912, 4578, 10669, 11914, + 425, 10453, 392, 10104, 8464, 4235, 8761, 7376, 2291, 3375, 7954, + 8896, 6617, 7790, 1737, 11667, 3982, 9342, 6680, 636, 6825, 7383, + 512, 4670, 2900, 12050, 7735, 994, 1687, 11883, 7021, 146, 10485, + 1403, 5189, 6094, 2483, 2054, 3042, 10945, 3981, 10821, 11826, 8882, + 8151, 180, 9600, 7684, 5219, 10880, 6780, 204, 11232, 2600, 7584, + 3121, 3017, 11053, 7814, 7043, 4251, 4739, 11063, 6771, 7073, 9261, + 2360, 11925, 1928, 11825, 8024, 3678, 3205, 3359, 11197, 5209, 8581, + 3238, 8840, 1136, 9363, 1826, 3171, 4489, 7885, 346, 2068, 1389, + 8257, 3163, 4840, 6127, 8062, 8921, 612, 4238, 10763, 8067, 125, + 11749, 10125, 5416, 2110, 716, 9839, 10584, 11475, 11873, 3448, 343, + 1908, 4538, 10423, 7078, 4727, 1208, 11572, 3589, 2982, 1373, 1721, + 10753, 4103, 2429, 4209, 5412, 5993, 9011, 438, 3515, 7228, 1218, + 8347, 5232, 8682, 1327, 7508, 4924, 448, 1014, 10029, 12221, 4566, + 5836, 12229, 2717, 1535, 3200, 5588, 5845, 412, 5102, 7326, 3744, + 3056, 2528, 7406, 8314, 9202, 6454, 6613, 1417, 10032, 7784, 1518, + 3765, 4176, 5063, 9828, 2275, 6636, 4267, 6463, 2065, 7725, 3495, + 8328, 8755, 8144, 10533, 5966, 12077, 9175, 9520, 5596, 6302, 8400, + 579, 6781, 11014, 5734, 11113, 11164, 4860, 1131, 10844, 9068, 8016, + 9694, 3837, 567, 9348, 7000, 6627, 7699, 5082, 682, 11309, 5207, + 4050, 7087, 844, 7434, 3769, 293, 9057, 6940, 9344, 10883, 2633, + 8190, 3944, 5530, 5604, 3480, 2171, 9282, 11024, 2213, 8136, 3805, + 767, 12239, 216, 11520, 6763, 10353, 7, 8566, 845, 7235, 3154, + 4360, 3285, 10268, 2832, 3572, 1282, 7559, 3229, 8360, 10583, 6105, + 3120, 6643, 6203, 8536, 8348, 6919, 3536, 9199, 10891, 11463, 5043, + 1658, 5618, 8787, 5789, 4719, 751, 11379, 6389, 10783, 3065, 7806, + 6586, 2622, 5386, 510, 7628, 6921, 578, 10345, 11839, 8929, 4684, + 12226, 7154, 9916, 7302, 8481, 3670, 11066, 2334, 1590, 7878, 10734, + 1802, 1891, 5103, 6151, 8820, 3418, 7846, 9951, 4693, 417, 9996, + 9652, 4510, 2946, 5461, 365, 881, 1927, 1015, 11675, 11009, 1371, + 12265, 2485, 11385, 5039, 6742, 8449, 1842, 12217, 8176, 9577, 4834, + 7937, 9461, 2643, 11194, 3045, 6508, 4094, 3451, 7911, 11048, 5406, + 4665, 3020, 6616, 11345, 7519, 3669, 5287, 1790, 7014, 5410, 11038, + 11249, 2035, 6125, 10407, 4565, 7315, 5078, 10506, 2840, 2478, 9270, + 4194, 9195, 4518, 7469, 1160, 6878, 2730, 10421, 10036, 1734, 3815, + 10939, 5832, 10595, 10759, 4423, 8420, 9617, 7119, 11010, 11424, 9173, + 189, 10080, 10526, 3466, 10588, 7592, 3578, 11511, 7785, 9663, 530, + 12150, 8957, 2532, 3317, 9349, 10243, 1481, 9332, 3454, 3758, 7899, + 4218, 2593, 11410, 2276, 982, 6513, 1849, 8494, 9021, 4523, 7988, + 8, 457, 648, 150, 8000, 2307, 2301, 874, 5650, 170, 9462, + 2873, 9855, 11498, 2535, 11169, 5808, 12268, 9687, 1901, 7171, 11787, + 3846, 1573, 6063, 3793, 466, 11259, 10608, 3821, 6320, 4649, 6263, + 2929}; + +uint16_t newhope_psis_inv_montgomery[PARAM_N] = { + 256, 10570, 1510, 7238, 1034, 7170, 6291, 7921, 11665, 3422, 4000, + 2327, 2088, 5565, 795, 10647, 1521, 5484, 2539, 7385, 1055, 7173, + 8047, 11683, 1669, 1994, 3796, 5809, 4341, 9398, 11876, 12230, 10525, + 12037, 12253, 3506, 4012, 9351, 4847, 2448, 7372, 9831, 3160, 2207, + 5582, 2553, 7387, 6322, 9681, 1383, 10731, 1533, 219, 5298, 4268, + 7632, 6357, 9686, 8406, 4712, 9451, 10128, 4958, 5975, 11387, 8649, + 11769, 6948, 11526, 12180, 1740, 10782, 6807, 2728, 7412, 4570, 4164, + 4106, 11120, 12122, 8754, 11784, 3439, 5758, 11356, 6889, 9762, 11928, + 1704, 1999, 10819, 12079, 12259, 7018, 11536, 1648, 1991, 2040, 2047, + 2048, 10826, 12080, 8748, 8272, 8204, 1172, 1923, 7297, 2798, 7422, + 6327, 4415, 7653, 6360, 11442, 12168, 7005, 8023, 9924, 8440, 8228, + 2931, 7441, 1063, 3663, 5790, 9605, 10150, 1450, 8985, 11817, 10466, + 10273, 12001, 3470, 7518, 1074, 1909, 7295, 9820, 4914, 702, 5367, + 7789, 8135, 9940, 1420, 3714, 11064, 12114, 12264, 1752, 5517, 9566, + 11900, 1700, 3754, 5803, 829, 1874, 7290, 2797, 10933, 5073, 7747, + 8129, 6428, 6185, 11417, 1631, 233, 5300, 9535, 10140, 11982, 8734, + 8270, 2937, 10953, 8587, 8249, 2934, 9197, 4825, 5956, 4362, 9401, + 1343, 3703, 529, 10609, 12049, 6988, 6265, 895, 3639, 4031, 4087, + 4095, 585, 10617, 8539, 4731, 4187, 9376, 3095, 9220, 10095, 10220, + 1460, 10742, 12068, 1724, 5513, 11321, 6884, 2739, 5658, 6075, 4379, + 11159, 10372, 8504, 4726, 9453, 3106, 7466, 11600, 10435, 8513, 9994, + 8450, 9985, 3182, 10988, 8592, 2983, 9204, 4826, 2445, 5616, 6069, + 867, 3635, 5786, 11360, 5134, 2489, 10889, 12089, 1727, 7269, 2794, + 9177, 1311, 5454, 9557, 6632, 2703, 9164, 10087, 1441, 3717, 531, + 3587, 2268, 324, 5313, 759, 1864, 5533, 2546, 7386, 9833, 8427, + 4715, 11207, 1601, 7251, 4547, 11183, 12131, 1733, 10781, 10318, 1474, + 10744, 5046, 4232, 11138, 10369, 6748, 964, 7160, 4534, 7670, 8118, + 8182, 4680, 11202, 6867, 981, 8918, 1274, 182, 26, 7026, 8026, + 11680, 12202, 10521, 1503, 7237, 4545, 5916, 9623, 8397, 11733, 10454, + 3249, 9242, 6587, 941, 1890, 270, 10572, 6777, 9746, 6659, 6218, + 6155, 6146, 878, 1881, 7291, 11575, 12187, 1741, 7271, 8061, 11685, + 6936, 4502, 9421, 4857, 4205, 7623, 1089, 10689, 1527, 8996, 10063, + 11971, 10488, 6765, 2722, 3900, 9335, 11867, 6962, 11528, 5158, 4248, + 4118, 5855, 2592, 5637, 6072, 2623, 7397, 8079, 9932, 4930, 5971, + 853, 3633, 519, 8852, 11798, 3441, 11025, 1575, 225, 8810, 11792, + 12218, 3501, 9278, 3081, 9218, 4828, 7712, 8124, 11694, 12204, 3499, + 4011, 573, 3593, 5780, 7848, 9899, 10192, 1456, 208, 7052, 2763, + 7417, 11593, 10434, 12024, 8740, 11782, 10461, 3250, 5731, 7841, 9898, + 1414, 202, 3540, 7528, 2831, 2160, 10842, 5060, 4234, 4116, 588, + 84, 12, 7024, 2759, 9172, 6577, 11473, 1639, 9012, 3043, 7457, + 6332, 11438, 1634, 1989, 9062, 11828, 8712, 11778, 12216, 10523, 6770, + 9745, 10170, 4964, 9487, 6622, 946, 8913, 6540, 6201, 4397, 9406, + 8366, 9973, 8447, 8229, 11709, 8695, 10020, 3187, 5722, 2573, 10901, + 6824, 4486, 4152, 9371, 8361, 2950, 2177, 311, 1800, 9035, 8313, + 11721, 3430, 490, 70, 10, 1757, 251, 3547, 7529, 11609, 3414, + 7510, 4584, 4166, 9373, 1339, 5458, 7802, 11648, 1664, 7260, 9815, + 10180, 6721, 9738, 10169, 8475, 8233, 9954, 1422, 8981, 1283, 5450, + 11312, 1616, 3742, 11068, 10359, 4991, 713, 3613, 9294, 8350, 4704, + 672, 96, 7036, 9783, 11931, 3460, 5761, 823, 10651, 12055, 10500, + 1500, 5481, 783, 3623, 11051, 8601, 8251, 8201, 11705, 10450, 5004, + 4226, 7626, 2845, 2162, 3820, 7568, 9859, 3164, 452, 10598, 1514, + 5483, 6050, 6131, 4387, 7649, 8115, 6426, 918, 8909, 8295, 1185, + 5436, 11310, 8638, 1234, 5443, 11311, 5127, 2488, 2111, 10835, 5059, + 7745, 2862, 3920, 560, 80, 1767, 2008, 3798, 11076, 6849, 2734, + 10924, 12094, 8750, 1250, 10712, 6797, 971, 7161, 1023, 8924, 4786, + 7706, 4612, 4170, 7618, 6355, 4419, 5898, 11376, 10403, 10264, 6733, + 4473, 639, 5358, 2521, 9138, 3061, 5704, 4326, 618, 5355, 765, + 5376, 768, 7132, 4530, 9425, 3102, 9221, 6584, 11474, 10417, 10266, + 12000, 6981, 6264, 4406, 2385, 7363, 4563, 4163, 7617, 9866, 3165, + 9230, 11852, 10471, 5007, 5982, 11388, 5138, 734, 3616, 11050, 12112, + 6997, 11533, 12181, 10518, 12036, 3475, 2252, 7344, 9827, 4915, 9480, + 6621, 4457, 7659, 9872, 6677, 4465, 4149, 7615, 4599, 657, 3605, + 515, 10607, 6782, 4480, 640, 1847, 3775, 5806, 2585, 5636, 9583, + 1369, 10729, 8555, 10000, 11962, 5220, 7768, 8132, 8184, 9947, 1421, + 203, 29, 8782, 11788, 1684, 10774, 10317, 4985, 9490, 8378, 4708, + 11206, 5112, 5997, 7879, 11659, 12199, 8765, 10030, 4944, 5973, 6120, + 6141, 6144, 7900, 11662, 1666, 238, 34, 3516, 5769, 9602, 8394, + 9977, 6692, 956, 10670, 6791, 9748, 11926, 8726, 11780, 5194, 742, + 106, 8793, 10034, 3189, 10989, 5081, 4237, 5872, 4350, 2377, 10873, + 6820, 6241, 11425, 10410, 10265, 3222, 5727, 9596, 4882, 2453, 2106, + 3812, 11078, 12116, 5242, 4260, 11142, 8614, 11764, 12214, 5256, 4262, + 4120, 11122, 5100, 11262, 5120, 2487, 5622, 9581, 8391, 8221, 2930, + 10952, 12098, 6995, 6266, 9673, 4893, 699, 3611, 4027, 5842, 11368, + 1624, 232, 8811, 8281, 1183, 169, 8802, 3013, 2186, 5579, 797, + 3625, 4029, 11109, 1587, 7249, 11569, 8675, 6506, 2685, 10917, 12093, + 12261, 12285, 1755, 7273, 1039, 1904, 272, 3550, 9285, 3082, 5707, + 6082, 4380, 7648, 11626, 5172, 4250, 9385, 8363, 8217, 4685, 5936, + 848, 8899, 6538, 934, 1889, 3781, 9318, 10109, 10222, 6727, 961, + 5404, 772, 5377, 9546, 8386, 1198, 8949, 3034, 2189, 7335, 4559, + 5918, 2601, 10905, 5069, 9502, 3113, 7467, 8089, 11689, 5181, 9518, + 8382, 2953, 3933, 4073, 4093, 7607, 8109, 2914, 5683, 4323, 11151, + 1593, 10761, 6804, 972, 3650, 2277, 5592, 4310, 7638, 9869, 4921, + 703, 1856, 9043, 4803, 9464, 1352, 8971, 11815, 5199, 7765, 6376, + 4422, 7654, 2849, 407, 8836, 6529, 7955, 2892, 9191, 1313, 10721, + 12065, 12257, 1751, 9028, 8312, 2943, 2176, 3822, 546, 78, 8789, + 11789, 10462, 12028, 6985, 4509, 9422, 1346, 5459, 4291, 613, 10621, + 6784, 9747, 3148, 7472, 2823, 5670, 810, 7138, 8042, 4660, 7688, + 6365, 6176, 6149, 2634, 5643, 9584, 10147, 11983, 5223, 9524, 11894, + 10477, 8519, 1217, 3685, 2282, 326, 10580, 3267, 7489, 4581, 2410, + 5611, 11335, 6886, 8006, 8166, 11700, 3427, 11023, 8597, 10006, 3185, + 455, 65, 5276, 7776, 4622, 5927, 7869, 9902, 11948, 5218, 2501, + 5624, 2559, 10899, 1557, 1978, 10816, 10323, 8497, 4725, 675, 1852, + 10798, 12076, 10503, 3256, 9243, 3076, 2195, 10847, 12083, 10504, 12034, + 10497}; diff --git a/external/boringssl/crypto/newhope/reduce.c b/external/boringssl/crypto/newhope/reduce.c new file mode 100644 index 0000000000..e7f1364947 --- /dev/null +++ b/external/boringssl/crypto/newhope/reduce.c @@ -0,0 +1,42 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include "internal.h" + + +/* Incomplete-reduction routines; for details on allowed input ranges + * and produced output ranges, see the description in the paper: + * https://cryptojedi.org/papers/#newhope */ + +static const uint32_t kQInv = 12287; /* -inverse_mod(p,2^18) */ +static const uint32_t kRLog = 18; + +uint16_t newhope_montgomery_reduce(uint32_t a) { + uint32_t u; + + u = (a * kQInv); + u &= ((1 << kRLog) - 1); + u *= PARAM_Q; + a = a + u; + return a >> 18; +} + +uint16_t newhope_barrett_reduce(uint16_t a) { + uint32_t u; + + u = ((uint32_t)a * 5) >> 16; + u *= PARAM_Q; + a -= u; + return a; +} diff --git a/external/boringssl/crypto/obj/CMakeLists.txt b/external/boringssl/crypto/obj/CMakeLists.txt new file mode 100644 index 0000000000..46b7918ddb --- /dev/null +++ b/external/boringssl/crypto/obj/CMakeLists.txt @@ -0,0 +1,23 @@ +include_directories(../../include) + +add_library( + obj + + OBJECT + + obj.c + obj_xref.c +) + +if(ENABLE_TESTS) +add_executable( + obj_test + + obj_test.cc + + $ +) + +target_link_libraries(obj_test crypto) +add_dependencies(all_tests obj_test) +endif() \ No newline at end of file diff --git a/external/boringssl/crypto/obj/README b/external/boringssl/crypto/obj/README new file mode 100644 index 0000000000..6199fb4b77 --- /dev/null +++ b/external/boringssl/crypto/obj/README @@ -0,0 +1,37 @@ +OID information is generated via a series of perl scripts. In order, the full +list of commands to run are: + + perl objects.pl objects.txt obj_mac.num ../../include/openssl/nid.h + perl obj_dat.pl ../../include/openssl/nid.h obj_dat.h + perl obj_xref.pl obj_mac.num obj_xref.txt > obj_xref.h + +objects.txt contains the list of all built-in OIDs. It is processed by +objects.pl to output obj_mac.num and nid.h. obj_mac.num is the list of NID +values for each OID. This is an input/output parameter so NID values are stable +across regenerations. nid.h is the header which defines macros for all the +built-in OIDs in C. + +nid.h is read by obj_dat.pl to generate obj_dat.h. obj_dat.h contains the +ASN1_OBJECTs corresponding to built-in OIDs themselves along with lookup tables +for search by short name, OID, etc. + +obj_mac.num and obj_xref.txt are read by obj_xref.pl to generate +obj_xref.h. obj_xref.txt links signature OIDs to corresponding public key +algorithms and digests. obj_xref.h contains lookup tables for querying this +information in both directions. + +Dependency graph: + + objects.txt + | + V + [objects.pl] <--+ + / \ | + V V | + nid.h obj_mac.num obj_xref.txt + | \ / + V V V + [obj_dat.pl] [obj_xref.pl] + | | + V V + obj_dat.h obj_xref.h diff --git a/external/boringssl/crypto/obj/obj.c b/external/boringssl/crypto/obj/obj.c new file mode 100644 index 0000000000..16d964c546 --- /dev/null +++ b/external/boringssl/crypto/obj/obj.c @@ -0,0 +1,664 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "obj_dat.h" +#include "../internal.h" + + +static struct CRYPTO_STATIC_MUTEX global_added_lock = CRYPTO_STATIC_MUTEX_INIT; +/* These globals are protected by |global_added_lock|. */ +static LHASH_OF(ASN1_OBJECT) *global_added_by_data = NULL; +static LHASH_OF(ASN1_OBJECT) *global_added_by_nid = NULL; +static LHASH_OF(ASN1_OBJECT) *global_added_by_short_name = NULL; +static LHASH_OF(ASN1_OBJECT) *global_added_by_long_name = NULL; + +static struct CRYPTO_STATIC_MUTEX global_next_nid_lock = + CRYPTO_STATIC_MUTEX_INIT; +static unsigned global_next_nid = NUM_NID; + +static int obj_next_nid(void) { + int ret; + + CRYPTO_STATIC_MUTEX_lock_write(&global_next_nid_lock); + ret = global_next_nid++; + CRYPTO_STATIC_MUTEX_unlock_write(&global_next_nid_lock); + + return ret; +} + +ASN1_OBJECT *OBJ_dup(const ASN1_OBJECT *o) { + ASN1_OBJECT *r; + unsigned char *data = NULL; + char *sn = NULL, *ln = NULL; + + if (o == NULL) { + return NULL; + } + + if (!(o->flags & ASN1_OBJECT_FLAG_DYNAMIC)) { + /* TODO(fork): this is a little dangerous. */ + return (ASN1_OBJECT *)o; + } + + r = ASN1_OBJECT_new(); + if (r == NULL) { + OPENSSL_PUT_ERROR(OBJ, ERR_R_ASN1_LIB); + return NULL; + } + r->ln = r->sn = NULL; + + data = OPENSSL_malloc(o->length); + if (data == NULL) { + goto err; + } + if (o->data != NULL) { + memcpy(data, o->data, o->length); + } + + /* once data is attached to an object, it remains const */ + r->data = data; + r->length = o->length; + r->nid = o->nid; + + if (o->ln != NULL) { + ln = OPENSSL_strdup(o->ln); + if (ln == NULL) { + goto err; + } + } + + if (o->sn != NULL) { + sn = OPENSSL_strdup(o->sn); + if (sn == NULL) { + goto err; + } + } + + r->sn = sn; + r->ln = ln; + + r->flags = + o->flags | (ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS | + ASN1_OBJECT_FLAG_DYNAMIC_DATA); + return r; + +err: + OPENSSL_PUT_ERROR(OBJ, ERR_R_MALLOC_FAILURE); + OPENSSL_free(ln); + OPENSSL_free(sn); + OPENSSL_free(data); + OPENSSL_free(r); + return NULL; +} + +int OBJ_cmp(const ASN1_OBJECT *a, const ASN1_OBJECT *b) { + int ret; + + ret = a->length - b->length; + if (ret) { + return ret; + } + return memcmp(a->data, b->data, a->length); +} + +/* obj_cmp is called to search the kNIDsInOIDOrder array. The |key| argument is + * an |ASN1_OBJECT|* that we're looking for and |element| is a pointer to an + * unsigned int in the array. */ +static int obj_cmp(const void *key, const void *element) { + unsigned nid = *((const unsigned*) element); + const ASN1_OBJECT *a = key; + const ASN1_OBJECT *b = &kObjects[nid]; + + if (a->length < b->length) { + return -1; + } else if (a->length > b->length) { + return 1; + } + return memcmp(a->data, b->data, a->length); +} + +int OBJ_obj2nid(const ASN1_OBJECT *obj) { + const unsigned int *nid_ptr; + + if (obj == NULL) { + return NID_undef; + } + + if (obj->nid != 0) { + return obj->nid; + } + + CRYPTO_STATIC_MUTEX_lock_read(&global_added_lock); + if (global_added_by_data != NULL) { + ASN1_OBJECT *match; + + match = lh_ASN1_OBJECT_retrieve(global_added_by_data, obj); + if (match != NULL) { + CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock); + return match->nid; + } + } + CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock); + + nid_ptr = bsearch(obj, kNIDsInOIDOrder, NUM_OBJ, sizeof(unsigned), obj_cmp); + if (nid_ptr == NULL) { + return NID_undef; + } + + return kObjects[*nid_ptr].nid; +} + +int OBJ_cbs2nid(const CBS *cbs) { + ASN1_OBJECT obj; + memset(&obj, 0, sizeof(obj)); + obj.data = CBS_data(cbs); + obj.length = CBS_len(cbs); + + return OBJ_obj2nid(&obj); +} + +/* short_name_cmp is called to search the kNIDsInShortNameOrder array. The + * |key| argument is name that we're looking for and |element| is a pointer to + * an unsigned int in the array. */ +static int short_name_cmp(const void *key, const void *element) { + const char *name = (const char *) key; + unsigned nid = *((unsigned*) element); + + return strcmp(name, kObjects[nid].sn); +} + +int OBJ_sn2nid(const char *short_name) { + const unsigned int *nid_ptr; + + CRYPTO_STATIC_MUTEX_lock_read(&global_added_lock); + if (global_added_by_short_name != NULL) { + ASN1_OBJECT *match, template; + + template.sn = short_name; + match = lh_ASN1_OBJECT_retrieve(global_added_by_short_name, &template); + if (match != NULL) { + CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock); + return match->nid; + } + } + CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock); + + nid_ptr = bsearch(short_name, kNIDsInShortNameOrder, NUM_SN, sizeof(unsigned), short_name_cmp); + if (nid_ptr == NULL) { + return NID_undef; + } + + return kObjects[*nid_ptr].nid; +} + +/* long_name_cmp is called to search the kNIDsInLongNameOrder array. The + * |key| argument is name that we're looking for and |element| is a pointer to + * an unsigned int in the array. */ +static int long_name_cmp(const void *key, const void *element) { + const char *name = (const char *) key; + unsigned nid = *((unsigned*) element); + + return strcmp(name, kObjects[nid].ln); +} + +int OBJ_ln2nid(const char *long_name) { + const unsigned int *nid_ptr; + + CRYPTO_STATIC_MUTEX_lock_read(&global_added_lock); + if (global_added_by_long_name != NULL) { + ASN1_OBJECT *match, template; + + template.ln = long_name; + match = lh_ASN1_OBJECT_retrieve(global_added_by_long_name, &template); + if (match != NULL) { + CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock); + return match->nid; + } + } + CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock); + + nid_ptr = bsearch(long_name, kNIDsInLongNameOrder, NUM_LN, sizeof(unsigned), long_name_cmp); + if (nid_ptr == NULL) { + return NID_undef; + } + + return kObjects[*nid_ptr].nid; +} + +int OBJ_txt2nid(const char *s) { + ASN1_OBJECT *obj; + int nid; + + obj = OBJ_txt2obj(s, 0 /* search names */); + nid = OBJ_obj2nid(obj); + ASN1_OBJECT_free(obj); + return nid; +} + +OPENSSL_EXPORT int OBJ_nid2cbb(CBB *out, int nid) { + const ASN1_OBJECT *obj = OBJ_nid2obj(nid); + CBB oid; + + if (obj == NULL || + !CBB_add_asn1(out, &oid, CBS_ASN1_OBJECT) || + !CBB_add_bytes(&oid, obj->data, obj->length) || + !CBB_flush(out)) { + return 0; + } + + return 1; +} + +const ASN1_OBJECT *OBJ_nid2obj(int nid) { + if (nid >= 0 && nid < NUM_NID) { + if (nid != NID_undef && kObjects[nid].nid == NID_undef) { + goto err; + } + return &kObjects[nid]; + } + + CRYPTO_STATIC_MUTEX_lock_read(&global_added_lock); + if (global_added_by_nid != NULL) { + ASN1_OBJECT *match, template; + + template.nid = nid; + match = lh_ASN1_OBJECT_retrieve(global_added_by_nid, &template); + if (match != NULL) { + CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock); + return match; + } + } + CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock); + +err: + OPENSSL_PUT_ERROR(OBJ, OBJ_R_UNKNOWN_NID); + return NULL; +} + +const char *OBJ_nid2sn(int nid) { + const ASN1_OBJECT *obj = OBJ_nid2obj(nid); + if (obj == NULL) { + return NULL; + } + + return obj->sn; +} + +const char *OBJ_nid2ln(int nid) { + const ASN1_OBJECT *obj = OBJ_nid2obj(nid); + if (obj == NULL) { + return NULL; + } + + return obj->ln; +} + +ASN1_OBJECT *OBJ_txt2obj(const char *s, int dont_search_names) { + int nid = NID_undef; + ASN1_OBJECT *op = NULL; + unsigned char *buf; + unsigned char *p; + const unsigned char *bufp; + int contents_len, total_len; + + if (!dont_search_names) { + nid = OBJ_sn2nid(s); + if (nid == NID_undef) { + nid = OBJ_ln2nid(s); + } + + if (nid != NID_undef) { + return (ASN1_OBJECT*) OBJ_nid2obj(nid); + } + } + + /* Work out size of content octets */ + contents_len = a2d_ASN1_OBJECT(NULL, 0, s, -1); + if (contents_len <= 0) { + return NULL; + } + /* Work out total size */ + total_len = ASN1_object_size(0, contents_len, V_ASN1_OBJECT); + + buf = OPENSSL_malloc(total_len); + if (buf == NULL) { + OPENSSL_PUT_ERROR(OBJ, ERR_R_MALLOC_FAILURE); + return NULL; + } + + p = buf; + /* Write out tag+length */ + ASN1_put_object(&p, 0, contents_len, V_ASN1_OBJECT, V_ASN1_UNIVERSAL); + /* Write out contents */ + a2d_ASN1_OBJECT(p, contents_len, s, -1); + + bufp = buf; + op = d2i_ASN1_OBJECT(NULL, &bufp, total_len); + OPENSSL_free(buf); + + return op; +} + +int OBJ_obj2txt(char *out, int out_len, const ASN1_OBJECT *obj, int dont_return_name) { + int i, n = 0, len, nid, first, use_bn; + BIGNUM *bl; + unsigned long l; + const unsigned char *p; + char tbuf[DECIMAL_SIZE(i) + DECIMAL_SIZE(l) + 2]; + + if (out && out_len > 0) { + out[0] = 0; + } + + if (obj == NULL || obj->data == NULL) { + return 0; + } + + if (!dont_return_name && (nid = OBJ_obj2nid(obj)) != NID_undef) { + const char *s; + s = OBJ_nid2ln(nid); + if (s == NULL) { + s = OBJ_nid2sn(nid); + } + if (s) { + if (out) { + BUF_strlcpy(out, s, out_len); + } + return strlen(s); + } + } + + len = obj->length; + p = obj->data; + + first = 1; + bl = NULL; + + while (len > 0) { + l = 0; + use_bn = 0; + for (;;) { + unsigned char c = *p++; + len--; + if (len == 0 && (c & 0x80)) { + goto err; + } + if (use_bn) { + if (!BN_add_word(bl, c & 0x7f)) { + goto err; + } + } else { + l |= c & 0x7f; + } + if (!(c & 0x80)) { + break; + } + if (!use_bn && (l > (ULONG_MAX >> 7L))) { + if (!bl && !(bl = BN_new())) { + goto err; + } + if (!BN_set_word(bl, l)) { + goto err; + } + use_bn = 1; + } + if (use_bn) { + if (!BN_lshift(bl, bl, 7)) { + goto err; + } + } else { + l <<= 7L; + } + } + + if (first) { + first = 0; + if (l >= 80) { + i = 2; + if (use_bn) { + if (!BN_sub_word(bl, 80)) { + goto err; + } + } else { + l -= 80; + } + } else { + i = (int)(l / 40); + l -= (long)(i * 40); + } + if (out && out_len > 1) { + *out++ = i + '0'; + *out = '0'; + out_len--; + } + n++; + } + + if (use_bn) { + char *bndec; + bndec = BN_bn2dec(bl); + if (!bndec) { + goto err; + } + i = strlen(bndec); + if (out) { + if (out_len > 1) { + *out++ = '.'; + *out = 0; + out_len--; + } + BUF_strlcpy(out, bndec, out_len); + if (i > out_len) { + out += out_len; + out_len = 0; + } else { + out += i; + out_len -= i; + } + } + n++; + n += i; + OPENSSL_free(bndec); + } else { + BIO_snprintf(tbuf, sizeof(tbuf), ".%lu", l); + i = strlen(tbuf); + if (out && out_len > 0) { + BUF_strlcpy(out, tbuf, out_len); + if (i > out_len) { + out += out_len; + out_len = 0; + } else { + out += i; + out_len -= i; + } + } + n += i; + } + } + + BN_free(bl); + return n; + +err: + BN_free(bl); + return -1; +} + +static uint32_t hash_nid(const ASN1_OBJECT *obj) { + return obj->nid; +} + +static int cmp_nid(const ASN1_OBJECT *a, const ASN1_OBJECT *b) { + return a->nid - b->nid; +} + +static uint32_t hash_data(const ASN1_OBJECT *obj) { + return OPENSSL_hash32(obj->data, obj->length); +} + +static int cmp_data(const ASN1_OBJECT *a, const ASN1_OBJECT *b) { + int i = a->length - b->length; + if (i) { + return i; + } + return memcmp(a->data, b->data, a->length); +} + +static uint32_t hash_short_name(const ASN1_OBJECT *obj) { + return lh_strhash(obj->sn); +} + +static int cmp_short_name(const ASN1_OBJECT *a, const ASN1_OBJECT *b) { + return strcmp(a->sn, b->sn); +} + +static uint32_t hash_long_name(const ASN1_OBJECT *obj) { + return lh_strhash(obj->ln); +} + +static int cmp_long_name(const ASN1_OBJECT *a, const ASN1_OBJECT *b) { + return strcmp(a->ln, b->ln); +} + +/* obj_add_object inserts |obj| into the various global hashes for run-time + * added objects. It returns one on success or zero otherwise. */ +static int obj_add_object(ASN1_OBJECT *obj) { + int ok; + ASN1_OBJECT *old_object; + + obj->flags &= ~(ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS | + ASN1_OBJECT_FLAG_DYNAMIC_DATA); + + CRYPTO_STATIC_MUTEX_lock_write(&global_added_lock); + if (global_added_by_nid == NULL) { + global_added_by_nid = lh_ASN1_OBJECT_new(hash_nid, cmp_nid); + global_added_by_data = lh_ASN1_OBJECT_new(hash_data, cmp_data); + global_added_by_short_name = lh_ASN1_OBJECT_new(hash_short_name, cmp_short_name); + global_added_by_long_name = lh_ASN1_OBJECT_new(hash_long_name, cmp_long_name); + } + + /* We don't pay attention to |old_object| (which contains any previous object + * that was evicted from the hashes) because we don't have a reference count + * on ASN1_OBJECT values. Also, we should never have duplicates nids and so + * should always have objects in |global_added_by_nid|. */ + + ok = lh_ASN1_OBJECT_insert(global_added_by_nid, &old_object, obj); + if (obj->length != 0 && obj->data != NULL) { + ok &= lh_ASN1_OBJECT_insert(global_added_by_data, &old_object, obj); + } + if (obj->sn != NULL) { + ok &= lh_ASN1_OBJECT_insert(global_added_by_short_name, &old_object, obj); + } + if (obj->ln != NULL) { + ok &= lh_ASN1_OBJECT_insert(global_added_by_long_name, &old_object, obj); + } + CRYPTO_STATIC_MUTEX_unlock_write(&global_added_lock); + + return ok; +} + +int OBJ_create(const char *oid, const char *short_name, const char *long_name) { + int ret = NID_undef; + ASN1_OBJECT *op = NULL; + unsigned char *buf = NULL; + int len; + + len = a2d_ASN1_OBJECT(NULL, 0, oid, -1); + if (len <= 0) { + goto err; + } + + buf = OPENSSL_malloc(len); + if (buf == NULL) { + OPENSSL_PUT_ERROR(OBJ, ERR_R_MALLOC_FAILURE); + goto err; + } + + len = a2d_ASN1_OBJECT(buf, len, oid, -1); + if (len == 0) { + goto err; + } + + op = (ASN1_OBJECT *)ASN1_OBJECT_create(obj_next_nid(), buf, len, short_name, + long_name); + if (op == NULL) { + goto err; + } + + if (obj_add_object(op)) { + ret = op->nid; + } + op = NULL; + +err: + ASN1_OBJECT_free(op); + OPENSSL_free(buf); + + return ret; +} diff --git a/external/boringssl/crypto/obj/obj_dat.h.REMOVED.git-id b/external/boringssl/crypto/obj/obj_dat.h.REMOVED.git-id new file mode 100644 index 0000000000..f19e464893 --- /dev/null +++ b/external/boringssl/crypto/obj/obj_dat.h.REMOVED.git-id @@ -0,0 +1 @@ +1d779de67cfa59075f036966689c181d7e048889 \ No newline at end of file diff --git a/external/boringssl/crypto/obj/obj_dat.pl b/external/boringssl/crypto/obj/obj_dat.pl new file mode 100644 index 0000000000..036ded5432 --- /dev/null +++ b/external/boringssl/crypto/obj/obj_dat.pl @@ -0,0 +1,309 @@ +#!/usr/bin/env perl + +# fixes bug in floating point emulation on sparc64 when +# this script produces off-by-one output on sparc64 +use integer; + +if (scalar @ARGV != 2) + { + print "Usage: perl obj_dat.pl ../../include/openssl/nid.h obj_dat.h\n"; + exit 1; + } + +sub obj_cmp + { + local(@a,@b,$_,$r); + + $A=$obj_len{$obj{$nid{$a}}}; + $B=$obj_len{$obj{$nid{$b}}}; + + $r=($A-$B); + return($r) if $r != 0; + + $A=$obj_der{$obj{$nid{$a}}}; + $B=$obj_der{$obj{$nid{$b}}}; + + return($A cmp $B); + } + +sub expand_obj + { + local(*v)=@_; + local($k,$d); + local($i); + + do { + $i=0; + foreach $k (keys %v) + { + if (($v{$k} =~ s/(OBJ_[^,]+),/$v{$1},/)) + { $i++; } + } + } while($i); + foreach $k (keys %v) + { + @a=split(/,/,$v{$k}); + $objn{$k}=$#a+1; + } + return(%objn); + } + +open (IN,"$ARGV[0]") || die "Can't open input file $ARGV[0]"; +open (OUT,">$ARGV[1]") || die "Can't open output file $ARGV[1]"; + +while () + { + next unless /^\#define\s+(\S+)\s+(.*)$/; + $v=$1; + $d=$2; + $d =~ s/^\"//; + $d =~ s/\"$//; + if ($v =~ /^SN_(.*)$/) + { + if(defined $snames{$d}) + { + print "WARNING: Duplicate short name \"$d\"\n"; + } + else + { $snames{$d} = "X"; } + $sn{$1}=$d; + } + elsif ($v =~ /^LN_(.*)$/) + { + if(defined $lnames{$d}) + { + print "WARNING: Duplicate long name \"$d\"\n"; + } + else + { $lnames{$d} = "X"; } + $ln{$1}=$d; + } + elsif ($v =~ /^NID_(.*)$/) + { $nid{$d}=$1; } + elsif ($v =~ /^OBJ_(.*)$/) + { + $obj{$1}=$v; + $objd{$v}=$d; + } + } +close IN; + +%ob=&expand_obj(*objd); + +@a=sort { $a <=> $b } keys %nid; +$n=$a[$#a]+1; + +@lvalues=(); +$lvalues=0; + +for ($i=0; $i<$n; $i++) + { + if (!defined($nid{$i})) + { + push(@out,"{NULL,NULL,NID_undef,0,NULL,0},\n"); + } + else + { + $sn=defined($sn{$nid{$i}})?"$sn{$nid{$i}}":"NULL"; + $ln=defined($ln{$nid{$i}})?"$ln{$nid{$i}}":"NULL"; + + if ($sn eq "NULL") { + $sn=$ln; + $sn{$nid{$i}} = $ln; + } + + if ($ln eq "NULL") { + $ln=$sn; + $ln{$nid{$i}} = $sn; + } + + $out ="{"; + $out.="\"$sn\""; + $out.=","."\"$ln\""; + $out.=",NID_$nid{$i},"; + if (defined($obj{$nid{$i}}) && $objd{$obj{$nid{$i}}} =~ /,/) + { + $v=$objd{$obj{$nid{$i}}}; + $v =~ s/L//g; + $v =~ s/,/ /g; + $r=&der_it($v); + $z=""; + $length=0; + foreach (unpack("C*",$r)) + { + $z.=sprintf("0x%02X,",$_); + $length++; + } + $obj_der{$obj{$nid{$i}}}=$z; + $obj_len{$obj{$nid{$i}}}=$length; + + push(@lvalues,sprintf("%-45s/* [%3d] %s */\n", + $z,$lvalues,$obj{$nid{$i}})); + $out.="$length,&(lvalues[$lvalues]),0"; + $lvalues+=$length; + } + else + { + $out.="0,NULL,0"; + } + $out.="},\n"; + push(@out,$out); + } + } + +@a=grep(defined($sn{$nid{$_}}),0 .. $n); +foreach (sort { $sn{$nid{$a}} cmp $sn{$nid{$b}} } @a) + { + push(@sn,sprintf("%2d,\t/* \"$sn{$nid{$_}}\" */\n",$_)); + } + +@a=grep(defined($ln{$nid{$_}}),0 .. $n); +foreach (sort { $ln{$nid{$a}} cmp $ln{$nid{$b}} } @a) + { + push(@ln,sprintf("%2d,\t/* \"$ln{$nid{$_}}\" */\n",$_)); + } + +@a=grep(defined($obj{$nid{$_}}) && $objd{$obj{$nid{$_}}} =~ /,/,0 .. $n); +foreach (sort obj_cmp @a) + { + $m=$obj{$nid{$_}}; + $v=$objd{$m}; + $v =~ s/L//g; + $v =~ s/,/ /g; + push(@ob,sprintf("%2d,\t/* %-32s %s */\n",$_,$m,$v)); + } + +print OUT <<'EOF'; +/* THIS FILE IS GENERATED FROM objects.h by obj_dat.pl via the + * following command: + * perl obj_dat.pl ../../include/openssl/nid.h obj_dat.h */ + +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +EOF + +printf OUT "#define NUM_NID %d\n",$n; +printf OUT "#define NUM_SN %d\n",$#sn+1; +printf OUT "#define NUM_LN %d\n",$#ln+1; +printf OUT "#define NUM_OBJ %d\n\n",$#ob+1; + +printf OUT "static const unsigned char lvalues[%d]={\n",$lvalues+1; +print OUT @lvalues; +print OUT "};\n\n"; + +printf OUT "static const ASN1_OBJECT kObjects[NUM_NID]={\n"; +foreach (@out) + { + if (length($_) > 75) + { + $out=""; + foreach (split(/,/)) + { + $t=$out.$_.","; + if (length($t) > 70) + { + print OUT "$out\n"; + $t="\t$_,"; + } + $out=$t; + } + chop $out; + print OUT "$out"; + } + else + { print OUT $_; } + } +print OUT "};\n\n"; + +printf OUT "static const unsigned int kNIDsInShortNameOrder[NUM_SN]={\n"; +print OUT @sn; +print OUT "};\n\n"; + +printf OUT "static const unsigned int kNIDsInLongNameOrder[NUM_LN]={\n"; +print OUT @ln; +print OUT "};\n\n"; + +printf OUT "static const unsigned int kNIDsInOIDOrder[NUM_OBJ]={\n"; +print OUT @ob; +print OUT "};\n\n"; + +close OUT; + +sub der_it + { + local($v)=@_; + local(@a,$i,$ret,@r); + + @a=split(/\s+/,$v); + $ret.=pack("C*",$a[0]*40+$a[1]); + shift @a; + shift @a; + foreach (@a) + { + @r=(); + $t=0; + while ($_ >= 128) + { + $x=$_%128; + $_/=128; + push(@r,((($t++)?0x80:0)|$x)); + } + push(@r,((($t++)?0x80:0)|$_)); + $ret.=pack("C*",reverse(@r)); + } + return($ret); + } diff --git a/external/boringssl/crypto/obj/obj_mac.num b/external/boringssl/crypto/obj/obj_mac.num new file mode 100644 index 0000000000..3a7844cd7f --- /dev/null +++ b/external/boringssl/crypto/obj/obj_mac.num @@ -0,0 +1,949 @@ +undef 0 +rsadsi 1 +pkcs 2 +md2 3 +md5 4 +rc4 5 +rsaEncryption 6 +md2WithRSAEncryption 7 +md5WithRSAEncryption 8 +pbeWithMD2AndDES_CBC 9 +pbeWithMD5AndDES_CBC 10 +X500 11 +X509 12 +commonName 13 +countryName 14 +localityName 15 +stateOrProvinceName 16 +organizationName 17 +organizationalUnitName 18 +rsa 19 +pkcs7 20 +pkcs7_data 21 +pkcs7_signed 22 +pkcs7_enveloped 23 +pkcs7_signedAndEnveloped 24 +pkcs7_digest 25 +pkcs7_encrypted 26 +pkcs3 27 +dhKeyAgreement 28 +des_ecb 29 +des_cfb64 30 +des_cbc 31 +des_ede_ecb 32 +des_ede3_ecb 33 +idea_cbc 34 +idea_cfb64 35 +idea_ecb 36 +rc2_cbc 37 +rc2_ecb 38 +rc2_cfb64 39 +rc2_ofb64 40 +sha 41 +shaWithRSAEncryption 42 +des_ede_cbc 43 +des_ede3_cbc 44 +des_ofb64 45 +idea_ofb64 46 +pkcs9 47 +pkcs9_emailAddress 48 +pkcs9_unstructuredName 49 +pkcs9_contentType 50 +pkcs9_messageDigest 51 +pkcs9_signingTime 52 +pkcs9_countersignature 53 +pkcs9_challengePassword 54 +pkcs9_unstructuredAddress 55 +pkcs9_extCertAttributes 56 +netscape 57 +netscape_cert_extension 58 +netscape_data_type 59 +des_ede_cfb64 60 +des_ede3_cfb64 61 +des_ede_ofb64 62 +des_ede3_ofb64 63 +sha1 64 +sha1WithRSAEncryption 65 +dsaWithSHA 66 +dsa_2 67 +pbeWithSHA1AndRC2_CBC 68 +id_pbkdf2 69 +dsaWithSHA1_2 70 +netscape_cert_type 71 +netscape_base_url 72 +netscape_revocation_url 73 +netscape_ca_revocation_url 74 +netscape_renewal_url 75 +netscape_ca_policy_url 76 +netscape_ssl_server_name 77 +netscape_comment 78 +netscape_cert_sequence 79 +desx_cbc 80 +id_ce 81 +subject_key_identifier 82 +key_usage 83 +private_key_usage_period 84 +subject_alt_name 85 +issuer_alt_name 86 +basic_constraints 87 +crl_number 88 +certificate_policies 89 +authority_key_identifier 90 +bf_cbc 91 +bf_ecb 92 +bf_cfb64 93 +bf_ofb64 94 +mdc2 95 +mdc2WithRSA 96 +rc4_40 97 +rc2_40_cbc 98 +givenName 99 +surname 100 +initials 101 +uniqueIdentifier 102 +crl_distribution_points 103 +md5WithRSA 104 +serialNumber 105 +title 106 +description 107 +cast5_cbc 108 +cast5_ecb 109 +cast5_cfb64 110 +cast5_ofb64 111 +pbeWithMD5AndCast5_CBC 112 +dsaWithSHA1 113 +md5_sha1 114 +sha1WithRSA 115 +dsa 116 +ripemd160 117 +ripemd160WithRSA 119 +rc5_cbc 120 +rc5_ecb 121 +rc5_cfb64 122 +rc5_ofb64 123 +rle_compression 124 +zlib_compression 125 +ext_key_usage 126 +id_pkix 127 +id_kp 128 +server_auth 129 +client_auth 130 +code_sign 131 +email_protect 132 +time_stamp 133 +ms_code_ind 134 +ms_code_com 135 +ms_ctl_sign 136 +ms_sgc 137 +ms_efs 138 +ns_sgc 139 +delta_crl 140 +crl_reason 141 +invalidity_date 142 +sxnet 143 +pbe_WithSHA1And128BitRC4 144 +pbe_WithSHA1And40BitRC4 145 +pbe_WithSHA1And3_Key_TripleDES_CBC 146 +pbe_WithSHA1And2_Key_TripleDES_CBC 147 +pbe_WithSHA1And128BitRC2_CBC 148 +pbe_WithSHA1And40BitRC2_CBC 149 +keyBag 150 +pkcs8ShroudedKeyBag 151 +certBag 152 +crlBag 153 +secretBag 154 +safeContentsBag 155 +friendlyName 156 +localKeyID 157 +x509Certificate 158 +sdsiCertificate 159 +x509Crl 160 +pbes2 161 +pbmac1 162 +hmacWithSHA1 163 +id_qt_cps 164 +id_qt_unotice 165 +rc2_64_cbc 166 +SMIMECapabilities 167 +pbeWithMD2AndRC2_CBC 168 +pbeWithMD5AndRC2_CBC 169 +pbeWithSHA1AndDES_CBC 170 +ms_ext_req 171 +ext_req 172 +name 173 +dnQualifier 174 +id_pe 175 +id_ad 176 +info_access 177 +ad_OCSP 178 +ad_ca_issuers 179 +OCSP_sign 180 +iso 181 +member_body 182 +ISO_US 183 +X9_57 184 +X9cm 185 +pkcs1 186 +pkcs5 187 +SMIME 188 +id_smime_mod 189 +id_smime_ct 190 +id_smime_aa 191 +id_smime_alg 192 +id_smime_cd 193 +id_smime_spq 194 +id_smime_cti 195 +id_smime_mod_cms 196 +id_smime_mod_ess 197 +id_smime_mod_oid 198 +id_smime_mod_msg_v3 199 +id_smime_mod_ets_eSignature_88 200 +id_smime_mod_ets_eSignature_97 201 +id_smime_mod_ets_eSigPolicy_88 202 +id_smime_mod_ets_eSigPolicy_97 203 +id_smime_ct_receipt 204 +id_smime_ct_authData 205 +id_smime_ct_publishCert 206 +id_smime_ct_TSTInfo 207 +id_smime_ct_TDTInfo 208 +id_smime_ct_contentInfo 209 +id_smime_ct_DVCSRequestData 210 +id_smime_ct_DVCSResponseData 211 +id_smime_aa_receiptRequest 212 +id_smime_aa_securityLabel 213 +id_smime_aa_mlExpandHistory 214 +id_smime_aa_contentHint 215 +id_smime_aa_msgSigDigest 216 +id_smime_aa_encapContentType 217 +id_smime_aa_contentIdentifier 218 +id_smime_aa_macValue 219 +id_smime_aa_equivalentLabels 220 +id_smime_aa_contentReference 221 +id_smime_aa_encrypKeyPref 222 +id_smime_aa_signingCertificate 223 +id_smime_aa_smimeEncryptCerts 224 +id_smime_aa_timeStampToken 225 +id_smime_aa_ets_sigPolicyId 226 +id_smime_aa_ets_commitmentType 227 +id_smime_aa_ets_signerLocation 228 +id_smime_aa_ets_signerAttr 229 +id_smime_aa_ets_otherSigCert 230 +id_smime_aa_ets_contentTimestamp 231 +id_smime_aa_ets_CertificateRefs 232 +id_smime_aa_ets_RevocationRefs 233 +id_smime_aa_ets_certValues 234 +id_smime_aa_ets_revocationValues 235 +id_smime_aa_ets_escTimeStamp 236 +id_smime_aa_ets_certCRLTimestamp 237 +id_smime_aa_ets_archiveTimeStamp 238 +id_smime_aa_signatureType 239 +id_smime_aa_dvcs_dvc 240 +id_smime_alg_ESDHwith3DES 241 +id_smime_alg_ESDHwithRC2 242 +id_smime_alg_3DESwrap 243 +id_smime_alg_RC2wrap 244 +id_smime_alg_ESDH 245 +id_smime_alg_CMS3DESwrap 246 +id_smime_alg_CMSRC2wrap 247 +id_smime_cd_ldap 248 +id_smime_spq_ets_sqt_uri 249 +id_smime_spq_ets_sqt_unotice 250 +id_smime_cti_ets_proofOfOrigin 251 +id_smime_cti_ets_proofOfReceipt 252 +id_smime_cti_ets_proofOfDelivery 253 +id_smime_cti_ets_proofOfSender 254 +id_smime_cti_ets_proofOfApproval 255 +id_smime_cti_ets_proofOfCreation 256 +md4 257 +id_pkix_mod 258 +id_qt 259 +id_it 260 +id_pkip 261 +id_alg 262 +id_cmc 263 +id_on 264 +id_pda 265 +id_aca 266 +id_qcs 267 +id_cct 268 +id_pkix1_explicit_88 269 +id_pkix1_implicit_88 270 +id_pkix1_explicit_93 271 +id_pkix1_implicit_93 272 +id_mod_crmf 273 +id_mod_cmc 274 +id_mod_kea_profile_88 275 +id_mod_kea_profile_93 276 +id_mod_cmp 277 +id_mod_qualified_cert_88 278 +id_mod_qualified_cert_93 279 +id_mod_attribute_cert 280 +id_mod_timestamp_protocol 281 +id_mod_ocsp 282 +id_mod_dvcs 283 +id_mod_cmp2000 284 +biometricInfo 285 +qcStatements 286 +ac_auditEntity 287 +ac_targeting 288 +aaControls 289 +sbgp_ipAddrBlock 290 +sbgp_autonomousSysNum 291 +sbgp_routerIdentifier 292 +textNotice 293 +ipsecEndSystem 294 +ipsecTunnel 295 +ipsecUser 296 +dvcs 297 +id_it_caProtEncCert 298 +id_it_signKeyPairTypes 299 +id_it_encKeyPairTypes 300 +id_it_preferredSymmAlg 301 +id_it_caKeyUpdateInfo 302 +id_it_currentCRL 303 +id_it_unsupportedOIDs 304 +id_it_subscriptionRequest 305 +id_it_subscriptionResponse 306 +id_it_keyPairParamReq 307 +id_it_keyPairParamRep 308 +id_it_revPassphrase 309 +id_it_implicitConfirm 310 +id_it_confirmWaitTime 311 +id_it_origPKIMessage 312 +id_regCtrl 313 +id_regInfo 314 +id_regCtrl_regToken 315 +id_regCtrl_authenticator 316 +id_regCtrl_pkiPublicationInfo 317 +id_regCtrl_pkiArchiveOptions 318 +id_regCtrl_oldCertID 319 +id_regCtrl_protocolEncrKey 320 +id_regInfo_utf8Pairs 321 +id_regInfo_certReq 322 +id_alg_des40 323 +id_alg_noSignature 324 +id_alg_dh_sig_hmac_sha1 325 +id_alg_dh_pop 326 +id_cmc_statusInfo 327 +id_cmc_identification 328 +id_cmc_identityProof 329 +id_cmc_dataReturn 330 +id_cmc_transactionId 331 +id_cmc_senderNonce 332 +id_cmc_recipientNonce 333 +id_cmc_addExtensions 334 +id_cmc_encryptedPOP 335 +id_cmc_decryptedPOP 336 +id_cmc_lraPOPWitness 337 +id_cmc_getCert 338 +id_cmc_getCRL 339 +id_cmc_revokeRequest 340 +id_cmc_regInfo 341 +id_cmc_responseInfo 342 +id_cmc_queryPending 343 +id_cmc_popLinkRandom 344 +id_cmc_popLinkWitness 345 +id_cmc_confirmCertAcceptance 346 +id_on_personalData 347 +id_pda_dateOfBirth 348 +id_pda_placeOfBirth 349 +id_pda_pseudonym 350 +id_pda_gender 351 +id_pda_countryOfCitizenship 352 +id_pda_countryOfResidence 353 +id_aca_authenticationInfo 354 +id_aca_accessIdentity 355 +id_aca_chargingIdentity 356 +id_aca_group 357 +id_aca_role 358 +id_qcs_pkixQCSyntax_v1 359 +id_cct_crs 360 +id_cct_PKIData 361 +id_cct_PKIResponse 362 +ad_timeStamping 363 +ad_dvcs 364 +id_pkix_OCSP_basic 365 +id_pkix_OCSP_Nonce 366 +id_pkix_OCSP_CrlID 367 +id_pkix_OCSP_acceptableResponses 368 +id_pkix_OCSP_noCheck 369 +id_pkix_OCSP_archiveCutoff 370 +id_pkix_OCSP_serviceLocator 371 +id_pkix_OCSP_extendedStatus 372 +id_pkix_OCSP_valid 373 +id_pkix_OCSP_path 374 +id_pkix_OCSP_trustRoot 375 +algorithm 376 +rsaSignature 377 +X500algorithms 378 +org 379 +dod 380 +iana 381 +Directory 382 +Management 383 +Experimental 384 +Private 385 +Security 386 +SNMPv2 387 +Mail 388 +Enterprises 389 +dcObject 390 +domainComponent 391 +Domain 392 +joint_iso_ccitt 393 +selected_attribute_types 394 +clearance 395 +md4WithRSAEncryption 396 +ac_proxying 397 +sinfo_access 398 +id_aca_encAttrs 399 +role 400 +policy_constraints 401 +target_information 402 +no_rev_avail 403 +ccitt 404 +ansi_X9_62 405 +X9_62_prime_field 406 +X9_62_characteristic_two_field 407 +X9_62_id_ecPublicKey 408 +X9_62_prime192v1 409 +X9_62_prime192v2 410 +X9_62_prime192v3 411 +X9_62_prime239v1 412 +X9_62_prime239v2 413 +X9_62_prime239v3 414 +X9_62_prime256v1 415 +ecdsa_with_SHA1 416 +ms_csp_name 417 +aes_128_ecb 418 +aes_128_cbc 419 +aes_128_ofb128 420 +aes_128_cfb128 421 +aes_192_ecb 422 +aes_192_cbc 423 +aes_192_ofb128 424 +aes_192_cfb128 425 +aes_256_ecb 426 +aes_256_cbc 427 +aes_256_ofb128 428 +aes_256_cfb128 429 +hold_instruction_code 430 +hold_instruction_none 431 +hold_instruction_call_issuer 432 +hold_instruction_reject 433 +data 434 +pss 435 +ucl 436 +pilot 437 +pilotAttributeType 438 +pilotAttributeSyntax 439 +pilotObjectClass 440 +pilotGroups 441 +iA5StringSyntax 442 +caseIgnoreIA5StringSyntax 443 +pilotObject 444 +pilotPerson 445 +account 446 +document 447 +room 448 +documentSeries 449 +rFC822localPart 450 +dNSDomain 451 +domainRelatedObject 452 +friendlyCountry 453 +simpleSecurityObject 454 +pilotOrganization 455 +pilotDSA 456 +qualityLabelledData 457 +userId 458 +textEncodedORAddress 459 +rfc822Mailbox 460 +info 461 +favouriteDrink 462 +roomNumber 463 +photo 464 +userClass 465 +host 466 +manager 467 +documentIdentifier 468 +documentTitle 469 +documentVersion 470 +documentAuthor 471 +documentLocation 472 +homeTelephoneNumber 473 +secretary 474 +otherMailbox 475 +lastModifiedTime 476 +lastModifiedBy 477 +aRecord 478 +pilotAttributeType27 479 +mXRecord 480 +nSRecord 481 +sOARecord 482 +cNAMERecord 483 +associatedDomain 484 +associatedName 485 +homePostalAddress 486 +personalTitle 487 +mobileTelephoneNumber 488 +pagerTelephoneNumber 489 +friendlyCountryName 490 +organizationalStatus 491 +janetMailbox 492 +mailPreferenceOption 493 +buildingName 494 +dSAQuality 495 +singleLevelQuality 496 +subtreeMinimumQuality 497 +subtreeMaximumQuality 498 +personalSignature 499 +dITRedirect 500 +audio 501 +documentPublisher 502 +x500UniqueIdentifier 503 +mime_mhs 504 +mime_mhs_headings 505 +mime_mhs_bodies 506 +id_hex_partial_message 507 +id_hex_multipart_message 508 +generationQualifier 509 +pseudonym 510 +InternationalRA 511 +id_set 512 +set_ctype 513 +set_msgExt 514 +set_attr 515 +set_policy 516 +set_certExt 517 +set_brand 518 +setct_PANData 519 +setct_PANToken 520 +setct_PANOnly 521 +setct_OIData 522 +setct_PI 523 +setct_PIData 524 +setct_PIDataUnsigned 525 +setct_HODInput 526 +setct_AuthResBaggage 527 +setct_AuthRevReqBaggage 528 +setct_AuthRevResBaggage 529 +setct_CapTokenSeq 530 +setct_PInitResData 531 +setct_PI_TBS 532 +setct_PResData 533 +setct_AuthReqTBS 534 +setct_AuthResTBS 535 +setct_AuthResTBSX 536 +setct_AuthTokenTBS 537 +setct_CapTokenData 538 +setct_CapTokenTBS 539 +setct_AcqCardCodeMsg 540 +setct_AuthRevReqTBS 541 +setct_AuthRevResData 542 +setct_AuthRevResTBS 543 +setct_CapReqTBS 544 +setct_CapReqTBSX 545 +setct_CapResData 546 +setct_CapRevReqTBS 547 +setct_CapRevReqTBSX 548 +setct_CapRevResData 549 +setct_CredReqTBS 550 +setct_CredReqTBSX 551 +setct_CredResData 552 +setct_CredRevReqTBS 553 +setct_CredRevReqTBSX 554 +setct_CredRevResData 555 +setct_PCertReqData 556 +setct_PCertResTBS 557 +setct_BatchAdminReqData 558 +setct_BatchAdminResData 559 +setct_CardCInitResTBS 560 +setct_MeAqCInitResTBS 561 +setct_RegFormResTBS 562 +setct_CertReqData 563 +setct_CertReqTBS 564 +setct_CertResData 565 +setct_CertInqReqTBS 566 +setct_ErrorTBS 567 +setct_PIDualSignedTBE 568 +setct_PIUnsignedTBE 569 +setct_AuthReqTBE 570 +setct_AuthResTBE 571 +setct_AuthResTBEX 572 +setct_AuthTokenTBE 573 +setct_CapTokenTBE 574 +setct_CapTokenTBEX 575 +setct_AcqCardCodeMsgTBE 576 +setct_AuthRevReqTBE 577 +setct_AuthRevResTBE 578 +setct_AuthRevResTBEB 579 +setct_CapReqTBE 580 +setct_CapReqTBEX 581 +setct_CapResTBE 582 +setct_CapRevReqTBE 583 +setct_CapRevReqTBEX 584 +setct_CapRevResTBE 585 +setct_CredReqTBE 586 +setct_CredReqTBEX 587 +setct_CredResTBE 588 +setct_CredRevReqTBE 589 +setct_CredRevReqTBEX 590 +setct_CredRevResTBE 591 +setct_BatchAdminReqTBE 592 +setct_BatchAdminResTBE 593 +setct_RegFormReqTBE 594 +setct_CertReqTBE 595 +setct_CertReqTBEX 596 +setct_CertResTBE 597 +setct_CRLNotificationTBS 598 +setct_CRLNotificationResTBS 599 +setct_BCIDistributionTBS 600 +setext_genCrypt 601 +setext_miAuth 602 +setext_pinSecure 603 +setext_pinAny 604 +setext_track2 605 +setext_cv 606 +set_policy_root 607 +setCext_hashedRoot 608 +setCext_certType 609 +setCext_merchData 610 +setCext_cCertRequired 611 +setCext_tunneling 612 +setCext_setExt 613 +setCext_setQualf 614 +setCext_PGWYcapabilities 615 +setCext_TokenIdentifier 616 +setCext_Track2Data 617 +setCext_TokenType 618 +setCext_IssuerCapabilities 619 +setAttr_Cert 620 +setAttr_PGWYcap 621 +setAttr_TokenType 622 +setAttr_IssCap 623 +set_rootKeyThumb 624 +set_addPolicy 625 +setAttr_Token_EMV 626 +setAttr_Token_B0Prime 627 +setAttr_IssCap_CVM 628 +setAttr_IssCap_T2 629 +setAttr_IssCap_Sig 630 +setAttr_GenCryptgrm 631 +setAttr_T2Enc 632 +setAttr_T2cleartxt 633 +setAttr_TokICCsig 634 +setAttr_SecDevSig 635 +set_brand_IATA_ATA 636 +set_brand_Diners 637 +set_brand_AmericanExpress 638 +set_brand_JCB 639 +set_brand_Visa 640 +set_brand_MasterCard 641 +set_brand_Novus 642 +des_cdmf 643 +rsaOAEPEncryptionSET 644 +itu_t 645 +joint_iso_itu_t 646 +international_organizations 647 +ms_smartcard_login 648 +ms_upn 649 +aes_128_cfb1 650 +aes_192_cfb1 651 +aes_256_cfb1 652 +aes_128_cfb8 653 +aes_192_cfb8 654 +aes_256_cfb8 655 +des_cfb1 656 +des_cfb8 657 +des_ede3_cfb1 658 +des_ede3_cfb8 659 +streetAddress 660 +postalCode 661 +id_ppl 662 +proxyCertInfo 663 +id_ppl_anyLanguage 664 +id_ppl_inheritAll 665 +name_constraints 666 +Independent 667 +sha256WithRSAEncryption 668 +sha384WithRSAEncryption 669 +sha512WithRSAEncryption 670 +sha224WithRSAEncryption 671 +sha256 672 +sha384 673 +sha512 674 +sha224 675 +identified_organization 676 +certicom_arc 677 +wap 678 +wap_wsg 679 +X9_62_id_characteristic_two_basis 680 +X9_62_onBasis 681 +X9_62_tpBasis 682 +X9_62_ppBasis 683 +X9_62_c2pnb163v1 684 +X9_62_c2pnb163v2 685 +X9_62_c2pnb163v3 686 +X9_62_c2pnb176v1 687 +X9_62_c2tnb191v1 688 +X9_62_c2tnb191v2 689 +X9_62_c2tnb191v3 690 +X9_62_c2onb191v4 691 +X9_62_c2onb191v5 692 +X9_62_c2pnb208w1 693 +X9_62_c2tnb239v1 694 +X9_62_c2tnb239v2 695 +X9_62_c2tnb239v3 696 +X9_62_c2onb239v4 697 +X9_62_c2onb239v5 698 +X9_62_c2pnb272w1 699 +X9_62_c2pnb304w1 700 +X9_62_c2tnb359v1 701 +X9_62_c2pnb368w1 702 +X9_62_c2tnb431r1 703 +secp112r1 704 +secp112r2 705 +secp128r1 706 +secp128r2 707 +secp160k1 708 +secp160r1 709 +secp160r2 710 +secp192k1 711 +secp224k1 712 +secp224r1 713 +secp256k1 714 +secp384r1 715 +secp521r1 716 +sect113r1 717 +sect113r2 718 +sect131r1 719 +sect131r2 720 +sect163k1 721 +sect163r1 722 +sect163r2 723 +sect193r1 724 +sect193r2 725 +sect233k1 726 +sect233r1 727 +sect239k1 728 +sect283k1 729 +sect283r1 730 +sect409k1 731 +sect409r1 732 +sect571k1 733 +sect571r1 734 +wap_wsg_idm_ecid_wtls1 735 +wap_wsg_idm_ecid_wtls3 736 +wap_wsg_idm_ecid_wtls4 737 +wap_wsg_idm_ecid_wtls5 738 +wap_wsg_idm_ecid_wtls6 739 +wap_wsg_idm_ecid_wtls7 740 +wap_wsg_idm_ecid_wtls8 741 +wap_wsg_idm_ecid_wtls9 742 +wap_wsg_idm_ecid_wtls10 743 +wap_wsg_idm_ecid_wtls11 744 +wap_wsg_idm_ecid_wtls12 745 +any_policy 746 +policy_mappings 747 +inhibit_any_policy 748 +ipsec3 749 +ipsec4 750 +camellia_128_cbc 751 +camellia_192_cbc 752 +camellia_256_cbc 753 +camellia_128_ecb 754 +camellia_192_ecb 755 +camellia_256_ecb 756 +camellia_128_cfb128 757 +camellia_192_cfb128 758 +camellia_256_cfb128 759 +camellia_128_cfb1 760 +camellia_192_cfb1 761 +camellia_256_cfb1 762 +camellia_128_cfb8 763 +camellia_192_cfb8 764 +camellia_256_cfb8 765 +camellia_128_ofb128 766 +camellia_192_ofb128 767 +camellia_256_ofb128 768 +subject_directory_attributes 769 +issuing_distribution_point 770 +certificate_issuer 771 +korea 772 +kisa 773 +kftc 774 +npki_alg 775 +seed_ecb 776 +seed_cbc 777 +seed_ofb128 778 +seed_cfb128 779 +hmac_md5 780 +hmac_sha1 781 +id_PasswordBasedMAC 782 +id_DHBasedMac 783 +id_it_suppLangTags 784 +caRepository 785 +id_smime_ct_compressedData 786 +id_ct_asciiTextWithCRLF 787 +id_aes128_wrap 788 +id_aes192_wrap 789 +id_aes256_wrap 790 +ecdsa_with_Recommended 791 +ecdsa_with_Specified 792 +ecdsa_with_SHA224 793 +ecdsa_with_SHA256 794 +ecdsa_with_SHA384 795 +ecdsa_with_SHA512 796 +hmacWithMD5 797 +hmacWithSHA224 798 +hmacWithSHA256 799 +hmacWithSHA384 800 +hmacWithSHA512 801 +dsa_with_SHA224 802 +dsa_with_SHA256 803 +whirlpool 804 +cryptopro 805 +cryptocom 806 +id_GostR3411_94_with_GostR3410_2001 807 +id_GostR3411_94_with_GostR3410_94 808 +id_GostR3411_94 809 +id_HMACGostR3411_94 810 +id_GostR3410_2001 811 +id_GostR3410_94 812 +id_Gost28147_89 813 +gost89_cnt 814 +id_Gost28147_89_MAC 815 +id_GostR3411_94_prf 816 +id_GostR3410_2001DH 817 +id_GostR3410_94DH 818 +id_Gost28147_89_CryptoPro_KeyMeshing 819 +id_Gost28147_89_None_KeyMeshing 820 +id_GostR3411_94_TestParamSet 821 +id_GostR3411_94_CryptoProParamSet 822 +id_Gost28147_89_TestParamSet 823 +id_Gost28147_89_CryptoPro_A_ParamSet 824 +id_Gost28147_89_CryptoPro_B_ParamSet 825 +id_Gost28147_89_CryptoPro_C_ParamSet 826 +id_Gost28147_89_CryptoPro_D_ParamSet 827 +id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet 828 +id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet 829 +id_Gost28147_89_CryptoPro_RIC_1_ParamSet 830 +id_GostR3410_94_TestParamSet 831 +id_GostR3410_94_CryptoPro_A_ParamSet 832 +id_GostR3410_94_CryptoPro_B_ParamSet 833 +id_GostR3410_94_CryptoPro_C_ParamSet 834 +id_GostR3410_94_CryptoPro_D_ParamSet 835 +id_GostR3410_94_CryptoPro_XchA_ParamSet 836 +id_GostR3410_94_CryptoPro_XchB_ParamSet 837 +id_GostR3410_94_CryptoPro_XchC_ParamSet 838 +id_GostR3410_2001_TestParamSet 839 +id_GostR3410_2001_CryptoPro_A_ParamSet 840 +id_GostR3410_2001_CryptoPro_B_ParamSet 841 +id_GostR3410_2001_CryptoPro_C_ParamSet 842 +id_GostR3410_2001_CryptoPro_XchA_ParamSet 843 +id_GostR3410_2001_CryptoPro_XchB_ParamSet 844 +id_GostR3410_94_a 845 +id_GostR3410_94_aBis 846 +id_GostR3410_94_b 847 +id_GostR3410_94_bBis 848 +id_Gost28147_89_cc 849 +id_GostR3410_94_cc 850 +id_GostR3410_2001_cc 851 +id_GostR3411_94_with_GostR3410_94_cc 852 +id_GostR3411_94_with_GostR3410_2001_cc 853 +id_GostR3410_2001_ParamSet_cc 854 +hmac 855 +LocalKeySet 856 +freshest_crl 857 +id_on_permanentIdentifier 858 +searchGuide 859 +businessCategory 860 +postalAddress 861 +postOfficeBox 862 +physicalDeliveryOfficeName 863 +telephoneNumber 864 +telexNumber 865 +teletexTerminalIdentifier 866 +facsimileTelephoneNumber 867 +x121Address 868 +internationaliSDNNumber 869 +registeredAddress 870 +destinationIndicator 871 +preferredDeliveryMethod 872 +presentationAddress 873 +supportedApplicationContext 874 +member 875 +owner 876 +roleOccupant 877 +seeAlso 878 +userPassword 879 +userCertificate 880 +cACertificate 881 +authorityRevocationList 882 +certificateRevocationList 883 +crossCertificatePair 884 +enhancedSearchGuide 885 +protocolInformation 886 +distinguishedName 887 +uniqueMember 888 +houseIdentifier 889 +supportedAlgorithms 890 +deltaRevocationList 891 +dmdName 892 +id_alg_PWRI_KEK 893 +cmac 894 +aes_128_gcm 895 +aes_128_ccm 896 +id_aes128_wrap_pad 897 +aes_192_gcm 898 +aes_192_ccm 899 +id_aes192_wrap_pad 900 +aes_256_gcm 901 +aes_256_ccm 902 +id_aes256_wrap_pad 903 +aes_128_ctr 904 +aes_192_ctr 905 +aes_256_ctr 906 +id_camellia128_wrap 907 +id_camellia192_wrap 908 +id_camellia256_wrap 909 +anyExtendedKeyUsage 910 +mgf1 911 +rsassaPss 912 +aes_128_xts 913 +aes_256_xts 914 +rc4_hmac_md5 915 +aes_128_cbc_hmac_sha1 916 +aes_192_cbc_hmac_sha1 917 +aes_256_cbc_hmac_sha1 918 +rsaesOaep 919 +dhpublicnumber 920 +brainpoolP160r1 921 +brainpoolP160t1 922 +brainpoolP192r1 923 +brainpoolP192t1 924 +brainpoolP224r1 925 +brainpoolP224t1 926 +brainpoolP256r1 927 +brainpoolP256t1 928 +brainpoolP320r1 929 +brainpoolP320t1 930 +brainpoolP384r1 931 +brainpoolP384t1 932 +brainpoolP512r1 933 +brainpoolP512t1 934 +pSpecified 935 +dhSinglePass_stdDH_sha1kdf_scheme 936 +dhSinglePass_stdDH_sha224kdf_scheme 937 +dhSinglePass_stdDH_sha256kdf_scheme 938 +dhSinglePass_stdDH_sha384kdf_scheme 939 +dhSinglePass_stdDH_sha512kdf_scheme 940 +dhSinglePass_cofactorDH_sha1kdf_scheme 941 +dhSinglePass_cofactorDH_sha224kdf_scheme 942 +dhSinglePass_cofactorDH_sha256kdf_scheme 943 +dhSinglePass_cofactorDH_sha384kdf_scheme 944 +dhSinglePass_cofactorDH_sha512kdf_scheme 945 +dh_std_kdf 946 +dh_cofactor_kdf 947 +X25519 948 +cecpq1 949 diff --git a/external/boringssl/crypto/obj/obj_test.cc b/external/boringssl/crypto/obj/obj_test.cc new file mode 100644 index 0000000000..2948941af4 --- /dev/null +++ b/external/boringssl/crypto/obj/obj_test.cc @@ -0,0 +1,106 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include + +#include +#include +#include + + +static bool TestBasic() { + static const int kNID = NID_sha256WithRSAEncryption; + static const char kShortName[] = "RSA-SHA256"; + static const char kLongName[] = "sha256WithRSAEncryption"; + static const char kText[] = "1.2.840.113549.1.1.11"; + static const uint8_t kDER[] = { + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, + }; + + CBS cbs; + CBS_init(&cbs, kDER, sizeof(kDER)); + if (OBJ_cbs2nid(&cbs) != kNID || + OBJ_sn2nid(kShortName) != kNID || + OBJ_ln2nid(kLongName) != kNID || + OBJ_txt2nid(kShortName) != kNID || + OBJ_txt2nid(kLongName) != kNID || + OBJ_txt2nid(kText) != kNID) { + return false; + } + + if (strcmp(kShortName, OBJ_nid2sn(kNID)) != 0 || + strcmp(kLongName, OBJ_nid2ln(kNID)) != 0) { + return false; + } + + if (OBJ_sn2nid("this is not an OID") != NID_undef || + OBJ_ln2nid("this is not an OID") != NID_undef || + OBJ_txt2nid("this is not an OID") != NID_undef) { + return false; + } + + CBS_init(&cbs, NULL, 0); + if (OBJ_cbs2nid(&cbs) != NID_undef) { + return false; + } + + // 1.2.840.113554.4.1.72585.2 (https://davidben.net/oid). + static const uint8_t kUnknownDER[] = { + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04, 0x01, 0x84, 0xb7, 0x09, 0x02, + }; + CBS_init(&cbs, kUnknownDER, sizeof(kUnknownDER)); + if (OBJ_cbs2nid(&cbs) != NID_undef) { + return false; + } + + return true; +} + +static bool TestSignatureAlgorithms() { + int digest_nid, pkey_nid; + if (!OBJ_find_sigid_algs(NID_sha256WithRSAEncryption, &digest_nid, + &pkey_nid) || + digest_nid != NID_sha256 || pkey_nid != NID_rsaEncryption) { + return false; + } + + if (OBJ_find_sigid_algs(NID_sha256, &digest_nid, &pkey_nid)) { + return false; + } + + int sign_nid; + if (!OBJ_find_sigid_by_algs(&sign_nid, NID_sha256, NID_rsaEncryption) || + sign_nid != NID_sha256WithRSAEncryption) { + return false; + } + + if (OBJ_find_sigid_by_algs(&sign_nid, NID_dsa, NID_rsaEncryption)) { + return false; + } + + return true; +} + +int main() { + CRYPTO_library_init(); + + if (!TestBasic() || + !TestSignatureAlgorithms()) { + return 1; + } + + printf("PASS\n"); + return 0; +} diff --git a/external/boringssl/crypto/obj/obj_xref.c b/external/boringssl/crypto/obj/obj_xref.c new file mode 100644 index 0000000000..70babea84b --- /dev/null +++ b/external/boringssl/crypto/obj/obj_xref.c @@ -0,0 +1,124 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include "obj_xref.h" + + +static int nid_triple_cmp_by_sign_id(const void *in_a, const void *in_b) { + const nid_triple *a = in_a; + const nid_triple *b = in_b; + + return a->sign_id - b->sign_id; +} + +int OBJ_find_sigid_algs(int sign_nid, int *out_digest_nid, int *out_pkey_nid) { + nid_triple key; + const nid_triple *triple; + + key.sign_id = sign_nid; + + triple = bsearch(&key, sigoid_srt, sizeof(sigoid_srt) / sizeof(nid_triple), + sizeof(nid_triple), nid_triple_cmp_by_sign_id); + + if (triple == NULL) { + return 0; + } + if (out_digest_nid) { + *out_digest_nid = triple->hash_id; + } + if (out_pkey_nid) { + *out_pkey_nid = triple->pkey_id; + } + + return 1; +} + +static int nid_triple_cmp_by_digest_and_hash(const void *in_a, + const void *in_b) { + const nid_triple *a = *((nid_triple**) in_a); + const nid_triple *b = *((nid_triple**) in_b); + + int ret = a->hash_id - b->hash_id; + if (ret) { + return ret; + } + return a->pkey_id - b->pkey_id; +} + +int OBJ_find_sigid_by_algs(int *out_sign_nid, int digest_nid, int pkey_nid) { + nid_triple key, *pkey; + const nid_triple **triple; + + key.hash_id = digest_nid; + key.pkey_id = pkey_nid; + pkey = &key; + + triple = bsearch(&pkey, sigoid_srt_xref, + sizeof(sigoid_srt_xref) / sizeof(nid_triple *), + sizeof(nid_triple *), nid_triple_cmp_by_digest_and_hash); + + if (triple == NULL) { + return 0; + } + if (out_sign_nid) { + *out_sign_nid = (*triple)->sign_id; + } + return 1; +} diff --git a/external/boringssl/crypto/obj/obj_xref.h b/external/boringssl/crypto/obj/obj_xref.h new file mode 100644 index 0000000000..b2082f55bd --- /dev/null +++ b/external/boringssl/crypto/obj/obj_xref.h @@ -0,0 +1,96 @@ +/* THIS FILE IS GENERATED FROM obj_xref.txt by obj_xref.pl via the + * following command: + * perl obj_xref.pl obj_mac.num obj_xref.txt > obj_xref.h */ + +typedef struct + { + int sign_id; + int hash_id; + int pkey_id; + } nid_triple; + +static const nid_triple sigoid_srt[] = + { + {NID_md2WithRSAEncryption, NID_md2, NID_rsaEncryption}, + {NID_md5WithRSAEncryption, NID_md5, NID_rsaEncryption}, + {NID_shaWithRSAEncryption, NID_sha, NID_rsaEncryption}, + {NID_sha1WithRSAEncryption, NID_sha1, NID_rsaEncryption}, + {NID_dsaWithSHA, NID_sha, NID_dsa}, + {NID_dsaWithSHA1_2, NID_sha1, NID_dsa_2}, + {NID_mdc2WithRSA, NID_mdc2, NID_rsaEncryption}, + {NID_md5WithRSA, NID_md5, NID_rsa}, + {NID_dsaWithSHA1, NID_sha1, NID_dsa}, + {NID_sha1WithRSA, NID_sha1, NID_rsa}, + {NID_ripemd160WithRSA, NID_ripemd160, NID_rsaEncryption}, + {NID_md4WithRSAEncryption, NID_md4, NID_rsaEncryption}, + {NID_ecdsa_with_SHA1, NID_sha1, NID_X9_62_id_ecPublicKey}, + {NID_sha256WithRSAEncryption, NID_sha256, NID_rsaEncryption}, + {NID_sha384WithRSAEncryption, NID_sha384, NID_rsaEncryption}, + {NID_sha512WithRSAEncryption, NID_sha512, NID_rsaEncryption}, + {NID_sha224WithRSAEncryption, NID_sha224, NID_rsaEncryption}, + {NID_ecdsa_with_Recommended, NID_undef, NID_X9_62_id_ecPublicKey}, + {NID_ecdsa_with_Specified, NID_undef, NID_X9_62_id_ecPublicKey}, + {NID_ecdsa_with_SHA224, NID_sha224, NID_X9_62_id_ecPublicKey}, + {NID_ecdsa_with_SHA256, NID_sha256, NID_X9_62_id_ecPublicKey}, + {NID_ecdsa_with_SHA384, NID_sha384, NID_X9_62_id_ecPublicKey}, + {NID_ecdsa_with_SHA512, NID_sha512, NID_X9_62_id_ecPublicKey}, + {NID_dsa_with_SHA224, NID_sha224, NID_dsa}, + {NID_dsa_with_SHA256, NID_sha256, NID_dsa}, + {NID_id_GostR3411_94_with_GostR3410_2001, NID_id_GostR3411_94, NID_id_GostR3410_2001}, + {NID_id_GostR3411_94_with_GostR3410_94, NID_id_GostR3411_94, NID_id_GostR3410_94}, + {NID_id_GostR3411_94_with_GostR3410_94_cc, NID_id_GostR3411_94, NID_id_GostR3410_94_cc}, + {NID_id_GostR3411_94_with_GostR3410_2001_cc, NID_id_GostR3411_94, NID_id_GostR3410_2001_cc}, + {NID_rsassaPss, NID_undef, NID_rsaEncryption}, + {NID_dhSinglePass_stdDH_sha1kdf_scheme, NID_sha1, NID_dh_std_kdf}, + {NID_dhSinglePass_stdDH_sha224kdf_scheme, NID_sha224, NID_dh_std_kdf}, + {NID_dhSinglePass_stdDH_sha256kdf_scheme, NID_sha256, NID_dh_std_kdf}, + {NID_dhSinglePass_stdDH_sha384kdf_scheme, NID_sha384, NID_dh_std_kdf}, + {NID_dhSinglePass_stdDH_sha512kdf_scheme, NID_sha512, NID_dh_std_kdf}, + {NID_dhSinglePass_cofactorDH_sha1kdf_scheme, NID_sha1, NID_dh_cofactor_kdf}, + {NID_dhSinglePass_cofactorDH_sha224kdf_scheme, NID_sha224, NID_dh_cofactor_kdf}, + {NID_dhSinglePass_cofactorDH_sha256kdf_scheme, NID_sha256, NID_dh_cofactor_kdf}, + {NID_dhSinglePass_cofactorDH_sha384kdf_scheme, NID_sha384, NID_dh_cofactor_kdf}, + {NID_dhSinglePass_cofactorDH_sha512kdf_scheme, NID_sha512, NID_dh_cofactor_kdf}, + }; + +static const nid_triple * const sigoid_srt_xref[] = + { + &sigoid_srt[0], + &sigoid_srt[1], + &sigoid_srt[7], + &sigoid_srt[2], + &sigoid_srt[4], + &sigoid_srt[3], + &sigoid_srt[9], + &sigoid_srt[5], + &sigoid_srt[8], + &sigoid_srt[12], + &sigoid_srt[30], + &sigoid_srt[35], + &sigoid_srt[6], + &sigoid_srt[10], + &sigoid_srt[11], + &sigoid_srt[13], + &sigoid_srt[24], + &sigoid_srt[20], + &sigoid_srt[32], + &sigoid_srt[37], + &sigoid_srt[14], + &sigoid_srt[21], + &sigoid_srt[33], + &sigoid_srt[38], + &sigoid_srt[15], + &sigoid_srt[22], + &sigoid_srt[34], + &sigoid_srt[39], + &sigoid_srt[16], + &sigoid_srt[23], + &sigoid_srt[19], + &sigoid_srt[31], + &sigoid_srt[36], + &sigoid_srt[25], + &sigoid_srt[26], + &sigoid_srt[27], + &sigoid_srt[28], + }; + diff --git a/external/boringssl/crypto/obj/obj_xref.pl b/external/boringssl/crypto/obj/obj_xref.pl new file mode 100644 index 0000000000..51dd68f450 --- /dev/null +++ b/external/boringssl/crypto/obj/obj_xref.pl @@ -0,0 +1,118 @@ +#!/usr/bin/env perl + +use strict; + +if (scalar @ARGV != 2) + { + print "Usage: perl obj_xref.pl obj_mac.num obj_xref.txt > obj_xref.h\n"; + exit 1; + } + +my %xref_tbl; +my %oid_tbl; + +my ($mac_file, $xref_file) = @ARGV; + +open(IN, $mac_file) || die "Can't open $mac_file"; + +# Read in OID nid values for a lookup table. + +while () + { + chomp; + my ($name, $num) = /^(\S+)\s+(\S+)$/; + $oid_tbl{$name} = $num; + } +close IN; + +open(IN, $xref_file) || die "Can't open $xref_file"; + +my $ln = 1; + +while () + { + chomp; + s/#.*$//; + next if (/^\S*$/); + my ($xr, $p1, $p2) = /^(\S+)\s+(\S+)\s+(\S+)/; + check_oid($xr); + check_oid($p1); + check_oid($p2); + $xref_tbl{$xr} = [$p1, $p2, $ln]; + } + +my @xrkeys = keys %xref_tbl; + +my @srt1 = sort { $oid_tbl{$a} <=> $oid_tbl{$b}} @xrkeys; + +for(my $i = 0; $i <= $#srt1; $i++) + { + $xref_tbl{$srt1[$i]}[2] = $i; + } + +my @srt2 = sort + { + my$ap1 = $oid_tbl{$xref_tbl{$a}[0]}; + my$bp1 = $oid_tbl{$xref_tbl{$b}[0]}; + return $ap1 - $bp1 if ($ap1 != $bp1); + my$ap2 = $oid_tbl{$xref_tbl{$a}[1]}; + my$bp2 = $oid_tbl{$xref_tbl{$b}[1]}; + + return $ap2 - $bp2; + } @xrkeys; + +my $pname = $0; + +$pname =~ s|^.[^/]/||; + +print < obj_xref.h */ + +typedef struct + { + int sign_id; + int hash_id; + int pkey_id; + } nid_triple; + +static const nid_triple sigoid_srt[] = + { +EOF + +foreach (@srt1) + { + my $xr = $_; + my ($p1, $p2) = @{$xref_tbl{$_}}; + print "\t{NID_$xr, NID_$p1, NID_$p2},\n"; + } + +print "\t};"; +print <) + { + chop; + $o++; + s/#.*$//; + next if /^\s*$/; + $_ = 'X'.$_; + ($Cname,$mynum) = split; + $Cname =~ s/^X//; + if (defined($nidn{$mynum})) + { die "$ARGV[1]:$o:There's already an object with NID ",$mynum," on line ",$order{$mynum},"\n"; } + if (defined($nid{$Cname})) + { die "$ARGV[1]:$o:There's already an object with name ",$Cname," on line ",$order{$nid{$Cname}},"\n"; } + $nid{$Cname} = $mynum; + $nidn{$mynum} = $Cname; + $order{$mynum} = $o; + $max_nid = $mynum if $mynum > $max_nid; + } +close NUMIN; + +open (IN,"$ARGV[0]") || die "Can't open input file $ARGV[0]"; +$Cname=""; +$o=0; +while () + { + chop; + $o++; + if (/^!module\s+(.*)$/) + { + $module = $1."-"; + $module =~ s/\./_/g; + $module =~ s/-/_/g; + } + if (/^!global$/) + { $module = ""; } + if (/^!Cname\s+(.*)$/) + { $Cname = $1; } + if (/^!Alias\s+(.+?)\s+(.*)$/) + { + $Cname = $module.$1; + $myoid = $2; + $myoid = &process_oid($myoid); + $Cname =~ s/-/_/g; + $ordern{$o} = $Cname; + $order{$Cname} = $o; + $obj{$Cname} = $myoid; + $_ = ""; + $Cname = ""; + } + s/!.*$//; + s/#.*$//; + next if /^\s*$/; + ($myoid,$mysn,$myln) = split ':'; + $mysn =~ s/^\s*//; + $mysn =~ s/\s*$//; + $myln =~ s/^\s*//; + $myln =~ s/\s*$//; + $myoid =~ s/^\s*//; + $myoid =~ s/\s*$//; + if ($myoid ne "") + { + $myoid = &process_oid($myoid); + } + + if ($Cname eq "" && !($myln =~ / /)) + { + $Cname = $myln; + $Cname =~ s/\./_/g; + $Cname =~ s/-/_/g; + if ($Cname ne "" && defined($ln{$module.$Cname})) + { die "objects.txt:$o:There's already an object with long name ",$ln{$module.$Cname}," on line ",$order{$module.$Cname},"\n"; } + } + if ($Cname eq "") + { + $Cname = $mysn; + $Cname =~ s/-/_/g; + if ($Cname ne "" && defined($sn{$module.$Cname})) + { die "objects.txt:$o:There's already an object with short name ",$sn{$module.$Cname}," on line ",$order{$module.$Cname},"\n"; } + } + if ($Cname eq "") + { + $Cname = $myln; + $Cname =~ s/-/_/g; + $Cname =~ s/\./_/g; + $Cname =~ s/ /_/g; + if ($Cname ne "" && defined($ln{$module.$Cname})) + { die "objects.txt:$o:There's already an object with long name ",$ln{$module.$Cname}," on line ",$order{$module.$Cname},"\n"; } + } + $Cname =~ s/\./_/g; + $Cname =~ s/-/_/g; + $Cname = $module.$Cname; + $ordern{$o} = $Cname; + $order{$Cname} = $o; + $sn{$Cname} = $mysn; + $ln{$Cname} = $myln; + $obj{$Cname} = $myoid; + if (!defined($nid{$Cname})) + { + $max_nid++; + $nid{$Cname} = $max_nid; + $nidn{$max_nid} = $Cname; +print STDERR "Added OID $Cname\n"; + } + $Cname=""; + } +close IN; + +open (NUMOUT,">$ARGV[1]") || die "Can't open output file $ARGV[1]"; +foreach (sort { $a <=> $b } keys %nidn) + { + print NUMOUT $nidn{$_},"\t\t",$_,"\n"; + } +close NUMOUT; + +open (OUT,">$ARGV[2]") || die "Can't open output file $ARGV[2]"; +print OUT <<'EOF'; +/* THIS FILE IS GENERATED FROM objects.txt by objects.pl via the + * following command: + * perl objects.pl objects.txt obj_mac.num ../../include/openssl/nid.h */ + +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef OPENSSL_HEADER_NID_H +#define OPENSSL_HEADER_NID_H + + +/* The nid library provides numbered values for ASN.1 object identifiers and + * other symbols. These values are used by other libraries to identify + * cryptographic primitives. + * + * A separate objects library, obj.h, provides functions for converting between + * nids and object identifiers. However it depends on large internal tables with + * the encodings of every nid defind. Consumers concerned with binary size + * should instead embed the encodings of the few consumed OIDs and compare + * against those. + * + * These values should not be used outside of a single process; they are not + * stable identifiers. */ + + +#define SN_undef "UNDEF" +#define LN_undef "undefined" +#define NID_undef 0 +#define OBJ_undef 0L + +EOF + +foreach (sort { $a <=> $b } keys %ordern) + { + $Cname=$ordern{$_}; + print OUT "#define SN_",$Cname," \"",$sn{$Cname},"\"\n" if $sn{$Cname} ne ""; + print OUT "#define LN_",$Cname," \"",$ln{$Cname},"\"\n" if $ln{$Cname} ne ""; + print OUT "#define NID_",$Cname," ",$nid{$Cname},"\n" if $nid{$Cname} ne ""; + print OUT "#define OBJ_",$Cname," ",$obj{$Cname},"\n" if $obj{$Cname} ne ""; + print OUT "\n"; + } + +print OUT "\n#endif /* OPENSSL_HEADER_NID_H */\n"; + +close OUT; + +sub process_oid + { + local($oid)=@_; + local(@a,$oid_pref); + + @a = split(/\s+/,$myoid); + $pref_oid = ""; + $pref_sep = ""; + if (!($a[0] =~ /^[0-9]+$/)) + { + $a[0] =~ s/-/_/g; + if (!defined($obj{$a[0]})) + { die "$ARGV[0]:$o:Undefined identifier ",$a[0],"\n"; } + $pref_oid = "OBJ_" . $a[0]; + $pref_sep = ","; + shift @a; + } + $oids = join('L,',@a) . "L"; + if ($oids ne "L") + { + $oids = $pref_oid . $pref_sep . $oids; + } + else + { + $oids = $pref_oid; + } + return($oids); + } diff --git a/external/boringssl/crypto/obj/objects.txt b/external/boringssl/crypto/obj/objects.txt new file mode 100644 index 0000000000..75f2cbf9f8 --- /dev/null +++ b/external/boringssl/crypto/obj/objects.txt @@ -0,0 +1,1338 @@ +# CCITT was renamed to ITU-T quite some time ago +0 : ITU-T : itu-t +!Alias ccitt itu-t + +1 : ISO : iso + +2 : JOINT-ISO-ITU-T : joint-iso-itu-t +!Alias joint-iso-ccitt joint-iso-itu-t + +iso 2 : member-body : ISO Member Body + +iso 3 : identified-organization + +# HMAC OIDs +identified-organization 6 1 5 5 8 1 1 : HMAC-MD5 : hmac-md5 +identified-organization 6 1 5 5 8 1 2 : HMAC-SHA1 : hmac-sha1 + +identified-organization 132 : certicom-arc + +joint-iso-itu-t 23 : international-organizations : International Organizations + +international-organizations 43 : wap +wap 1 : wap-wsg + +joint-iso-itu-t 5 1 5 : selected-attribute-types : Selected Attribute Types + +selected-attribute-types 55 : clearance + +member-body 840 : ISO-US : ISO US Member Body +ISO-US 10040 : X9-57 : X9.57 +X9-57 4 : X9cm : X9.57 CM ? + +!Cname dsa +X9cm 1 : DSA : dsaEncryption +X9cm 3 : DSA-SHA1 : dsaWithSHA1 + + +ISO-US 10045 : ansi-X9-62 : ANSI X9.62 +!module X9-62 +!Alias id-fieldType ansi-X9-62 1 +X9-62_id-fieldType 1 : prime-field +X9-62_id-fieldType 2 : characteristic-two-field +X9-62_characteristic-two-field 3 : id-characteristic-two-basis +X9-62_id-characteristic-two-basis 1 : onBasis +X9-62_id-characteristic-two-basis 2 : tpBasis +X9-62_id-characteristic-two-basis 3 : ppBasis +!Alias id-publicKeyType ansi-X9-62 2 +X9-62_id-publicKeyType 1 : id-ecPublicKey +!Alias ellipticCurve ansi-X9-62 3 +!Alias c-TwoCurve X9-62_ellipticCurve 0 +X9-62_c-TwoCurve 1 : c2pnb163v1 +X9-62_c-TwoCurve 2 : c2pnb163v2 +X9-62_c-TwoCurve 3 : c2pnb163v3 +X9-62_c-TwoCurve 4 : c2pnb176v1 +X9-62_c-TwoCurve 5 : c2tnb191v1 +X9-62_c-TwoCurve 6 : c2tnb191v2 +X9-62_c-TwoCurve 7 : c2tnb191v3 +X9-62_c-TwoCurve 8 : c2onb191v4 +X9-62_c-TwoCurve 9 : c2onb191v5 +X9-62_c-TwoCurve 10 : c2pnb208w1 +X9-62_c-TwoCurve 11 : c2tnb239v1 +X9-62_c-TwoCurve 12 : c2tnb239v2 +X9-62_c-TwoCurve 13 : c2tnb239v3 +X9-62_c-TwoCurve 14 : c2onb239v4 +X9-62_c-TwoCurve 15 : c2onb239v5 +X9-62_c-TwoCurve 16 : c2pnb272w1 +X9-62_c-TwoCurve 17 : c2pnb304w1 +X9-62_c-TwoCurve 18 : c2tnb359v1 +X9-62_c-TwoCurve 19 : c2pnb368w1 +X9-62_c-TwoCurve 20 : c2tnb431r1 +!Alias primeCurve X9-62_ellipticCurve 1 +X9-62_primeCurve 1 : prime192v1 +X9-62_primeCurve 2 : prime192v2 +X9-62_primeCurve 3 : prime192v3 +X9-62_primeCurve 4 : prime239v1 +X9-62_primeCurve 5 : prime239v2 +X9-62_primeCurve 6 : prime239v3 +X9-62_primeCurve 7 : prime256v1 +!Alias id-ecSigType ansi-X9-62 4 +!global +X9-62_id-ecSigType 1 : ecdsa-with-SHA1 +X9-62_id-ecSigType 2 : ecdsa-with-Recommended +X9-62_id-ecSigType 3 : ecdsa-with-Specified +ecdsa-with-Specified 1 : ecdsa-with-SHA224 +ecdsa-with-Specified 2 : ecdsa-with-SHA256 +ecdsa-with-Specified 3 : ecdsa-with-SHA384 +ecdsa-with-Specified 4 : ecdsa-with-SHA512 + +# SECG curve OIDs from "SEC 2: Recommended Elliptic Curve Domain Parameters" +# (http://www.secg.org/) +!Alias secg_ellipticCurve certicom-arc 0 +# SECG prime curves OIDs +secg-ellipticCurve 6 : secp112r1 +secg-ellipticCurve 7 : secp112r2 +secg-ellipticCurve 28 : secp128r1 +secg-ellipticCurve 29 : secp128r2 +secg-ellipticCurve 9 : secp160k1 +secg-ellipticCurve 8 : secp160r1 +secg-ellipticCurve 30 : secp160r2 +secg-ellipticCurve 31 : secp192k1 +# NOTE: the curve secp192r1 is the same as prime192v1 defined above +# and is therefore omitted +secg-ellipticCurve 32 : secp224k1 +secg-ellipticCurve 33 : secp224r1 +secg-ellipticCurve 10 : secp256k1 +# NOTE: the curve secp256r1 is the same as prime256v1 defined above +# and is therefore omitted +secg-ellipticCurve 34 : secp384r1 +secg-ellipticCurve 35 : secp521r1 +# SECG characteristic two curves OIDs +secg-ellipticCurve 4 : sect113r1 +secg-ellipticCurve 5 : sect113r2 +secg-ellipticCurve 22 : sect131r1 +secg-ellipticCurve 23 : sect131r2 +secg-ellipticCurve 1 : sect163k1 +secg-ellipticCurve 2 : sect163r1 +secg-ellipticCurve 15 : sect163r2 +secg-ellipticCurve 24 : sect193r1 +secg-ellipticCurve 25 : sect193r2 +secg-ellipticCurve 26 : sect233k1 +secg-ellipticCurve 27 : sect233r1 +secg-ellipticCurve 3 : sect239k1 +secg-ellipticCurve 16 : sect283k1 +secg-ellipticCurve 17 : sect283r1 +secg-ellipticCurve 36 : sect409k1 +secg-ellipticCurve 37 : sect409r1 +secg-ellipticCurve 38 : sect571k1 +secg-ellipticCurve 39 : sect571r1 + +# WAP/TLS curve OIDs (http://www.wapforum.org/) +!Alias wap-wsg-idm-ecid wap-wsg 4 +wap-wsg-idm-ecid 1 : wap-wsg-idm-ecid-wtls1 +wap-wsg-idm-ecid 3 : wap-wsg-idm-ecid-wtls3 +wap-wsg-idm-ecid 4 : wap-wsg-idm-ecid-wtls4 +wap-wsg-idm-ecid 5 : wap-wsg-idm-ecid-wtls5 +wap-wsg-idm-ecid 6 : wap-wsg-idm-ecid-wtls6 +wap-wsg-idm-ecid 7 : wap-wsg-idm-ecid-wtls7 +wap-wsg-idm-ecid 8 : wap-wsg-idm-ecid-wtls8 +wap-wsg-idm-ecid 9 : wap-wsg-idm-ecid-wtls9 +wap-wsg-idm-ecid 10 : wap-wsg-idm-ecid-wtls10 +wap-wsg-idm-ecid 11 : wap-wsg-idm-ecid-wtls11 +wap-wsg-idm-ecid 12 : wap-wsg-idm-ecid-wtls12 + + +ISO-US 113533 7 66 10 : CAST5-CBC : cast5-cbc + : CAST5-ECB : cast5-ecb +!Cname cast5-cfb64 + : CAST5-CFB : cast5-cfb +!Cname cast5-ofb64 + : CAST5-OFB : cast5-ofb +!Cname pbeWithMD5AndCast5-CBC +ISO-US 113533 7 66 12 : : pbeWithMD5AndCast5CBC + +# Macs for CMP and CRMF +ISO-US 113533 7 66 13 : id-PasswordBasedMAC : password based MAC +ISO-US 113533 7 66 30 : id-DHBasedMac : Diffie-Hellman based MAC + +ISO-US 113549 : rsadsi : RSA Data Security, Inc. + +rsadsi 1 : pkcs : RSA Data Security, Inc. PKCS + +pkcs 1 : pkcs1 +pkcs1 1 : : rsaEncryption +pkcs1 2 : RSA-MD2 : md2WithRSAEncryption +pkcs1 3 : RSA-MD4 : md4WithRSAEncryption +pkcs1 4 : RSA-MD5 : md5WithRSAEncryption +pkcs1 5 : RSA-SHA1 : sha1WithRSAEncryption +# According to PKCS #1 version 2.1 +pkcs1 7 : RSAES-OAEP : rsaesOaep +pkcs1 8 : MGF1 : mgf1 +pkcs1 9 : PSPECIFIED : pSpecified +pkcs1 10 : RSASSA-PSS : rsassaPss + +pkcs1 11 : RSA-SHA256 : sha256WithRSAEncryption +pkcs1 12 : RSA-SHA384 : sha384WithRSAEncryption +pkcs1 13 : RSA-SHA512 : sha512WithRSAEncryption +pkcs1 14 : RSA-SHA224 : sha224WithRSAEncryption + +pkcs 3 : pkcs3 +pkcs3 1 : : dhKeyAgreement + +pkcs 5 : pkcs5 +pkcs5 1 : PBE-MD2-DES : pbeWithMD2AndDES-CBC +pkcs5 3 : PBE-MD5-DES : pbeWithMD5AndDES-CBC +pkcs5 4 : PBE-MD2-RC2-64 : pbeWithMD2AndRC2-CBC +pkcs5 6 : PBE-MD5-RC2-64 : pbeWithMD5AndRC2-CBC +pkcs5 10 : PBE-SHA1-DES : pbeWithSHA1AndDES-CBC +pkcs5 11 : PBE-SHA1-RC2-64 : pbeWithSHA1AndRC2-CBC +!Cname id_pbkdf2 +pkcs5 12 : : PBKDF2 +!Cname pbes2 +pkcs5 13 : : PBES2 +!Cname pbmac1 +pkcs5 14 : : PBMAC1 + +pkcs 7 : pkcs7 +pkcs7 1 : : pkcs7-data +!Cname pkcs7-signed +pkcs7 2 : : pkcs7-signedData +!Cname pkcs7-enveloped +pkcs7 3 : : pkcs7-envelopedData +!Cname pkcs7-signedAndEnveloped +pkcs7 4 : : pkcs7-signedAndEnvelopedData +!Cname pkcs7-digest +pkcs7 5 : : pkcs7-digestData +!Cname pkcs7-encrypted +pkcs7 6 : : pkcs7-encryptedData + +pkcs 9 : pkcs9 +!module pkcs9 +pkcs9 1 : : emailAddress +pkcs9 2 : : unstructuredName +pkcs9 3 : : contentType +pkcs9 4 : : messageDigest +pkcs9 5 : : signingTime +pkcs9 6 : : countersignature +pkcs9 7 : : challengePassword +pkcs9 8 : : unstructuredAddress +!Cname extCertAttributes +pkcs9 9 : : extendedCertificateAttributes +!global + +!Cname ext-req +pkcs9 14 : extReq : Extension Request + +!Cname SMIMECapabilities +pkcs9 15 : SMIME-CAPS : S/MIME Capabilities + +# S/MIME +!Cname SMIME +pkcs9 16 : SMIME : S/MIME +SMIME 0 : id-smime-mod +SMIME 1 : id-smime-ct +SMIME 2 : id-smime-aa +SMIME 3 : id-smime-alg +SMIME 4 : id-smime-cd +SMIME 5 : id-smime-spq +SMIME 6 : id-smime-cti + +# S/MIME Modules +id-smime-mod 1 : id-smime-mod-cms +id-smime-mod 2 : id-smime-mod-ess +id-smime-mod 3 : id-smime-mod-oid +id-smime-mod 4 : id-smime-mod-msg-v3 +id-smime-mod 5 : id-smime-mod-ets-eSignature-88 +id-smime-mod 6 : id-smime-mod-ets-eSignature-97 +id-smime-mod 7 : id-smime-mod-ets-eSigPolicy-88 +id-smime-mod 8 : id-smime-mod-ets-eSigPolicy-97 + +# S/MIME Content Types +id-smime-ct 1 : id-smime-ct-receipt +id-smime-ct 2 : id-smime-ct-authData +id-smime-ct 3 : id-smime-ct-publishCert +id-smime-ct 4 : id-smime-ct-TSTInfo +id-smime-ct 5 : id-smime-ct-TDTInfo +id-smime-ct 6 : id-smime-ct-contentInfo +id-smime-ct 7 : id-smime-ct-DVCSRequestData +id-smime-ct 8 : id-smime-ct-DVCSResponseData +id-smime-ct 9 : id-smime-ct-compressedData +id-smime-ct 27 : id-ct-asciiTextWithCRLF + +# S/MIME Attributes +id-smime-aa 1 : id-smime-aa-receiptRequest +id-smime-aa 2 : id-smime-aa-securityLabel +id-smime-aa 3 : id-smime-aa-mlExpandHistory +id-smime-aa 4 : id-smime-aa-contentHint +id-smime-aa 5 : id-smime-aa-msgSigDigest +# obsolete +id-smime-aa 6 : id-smime-aa-encapContentType +id-smime-aa 7 : id-smime-aa-contentIdentifier +# obsolete +id-smime-aa 8 : id-smime-aa-macValue +id-smime-aa 9 : id-smime-aa-equivalentLabels +id-smime-aa 10 : id-smime-aa-contentReference +id-smime-aa 11 : id-smime-aa-encrypKeyPref +id-smime-aa 12 : id-smime-aa-signingCertificate +id-smime-aa 13 : id-smime-aa-smimeEncryptCerts +id-smime-aa 14 : id-smime-aa-timeStampToken +id-smime-aa 15 : id-smime-aa-ets-sigPolicyId +id-smime-aa 16 : id-smime-aa-ets-commitmentType +id-smime-aa 17 : id-smime-aa-ets-signerLocation +id-smime-aa 18 : id-smime-aa-ets-signerAttr +id-smime-aa 19 : id-smime-aa-ets-otherSigCert +id-smime-aa 20 : id-smime-aa-ets-contentTimestamp +id-smime-aa 21 : id-smime-aa-ets-CertificateRefs +id-smime-aa 22 : id-smime-aa-ets-RevocationRefs +id-smime-aa 23 : id-smime-aa-ets-certValues +id-smime-aa 24 : id-smime-aa-ets-revocationValues +id-smime-aa 25 : id-smime-aa-ets-escTimeStamp +id-smime-aa 26 : id-smime-aa-ets-certCRLTimestamp +id-smime-aa 27 : id-smime-aa-ets-archiveTimeStamp +id-smime-aa 28 : id-smime-aa-signatureType +id-smime-aa 29 : id-smime-aa-dvcs-dvc + +# S/MIME Algorithm Identifiers +# obsolete +id-smime-alg 1 : id-smime-alg-ESDHwith3DES +# obsolete +id-smime-alg 2 : id-smime-alg-ESDHwithRC2 +# obsolete +id-smime-alg 3 : id-smime-alg-3DESwrap +# obsolete +id-smime-alg 4 : id-smime-alg-RC2wrap +id-smime-alg 5 : id-smime-alg-ESDH +id-smime-alg 6 : id-smime-alg-CMS3DESwrap +id-smime-alg 7 : id-smime-alg-CMSRC2wrap +id-smime-alg 9 : id-alg-PWRI-KEK + +# S/MIME Certificate Distribution +id-smime-cd 1 : id-smime-cd-ldap + +# S/MIME Signature Policy Qualifier +id-smime-spq 1 : id-smime-spq-ets-sqt-uri +id-smime-spq 2 : id-smime-spq-ets-sqt-unotice + +# S/MIME Commitment Type Identifier +id-smime-cti 1 : id-smime-cti-ets-proofOfOrigin +id-smime-cti 2 : id-smime-cti-ets-proofOfReceipt +id-smime-cti 3 : id-smime-cti-ets-proofOfDelivery +id-smime-cti 4 : id-smime-cti-ets-proofOfSender +id-smime-cti 5 : id-smime-cti-ets-proofOfApproval +id-smime-cti 6 : id-smime-cti-ets-proofOfCreation + +pkcs9 20 : : friendlyName +pkcs9 21 : : localKeyID +!Cname ms-csp-name +1 3 6 1 4 1 311 17 1 : CSPName : Microsoft CSP Name +1 3 6 1 4 1 311 17 2 : LocalKeySet : Microsoft Local Key set +!Alias certTypes pkcs9 22 +certTypes 1 : : x509Certificate +certTypes 2 : : sdsiCertificate +!Alias crlTypes pkcs9 23 +crlTypes 1 : : x509Crl + +!Alias pkcs12 pkcs 12 +!Alias pkcs12-pbeids pkcs12 1 + +!Cname pbe-WithSHA1And128BitRC4 +pkcs12-pbeids 1 : PBE-SHA1-RC4-128 : pbeWithSHA1And128BitRC4 +!Cname pbe-WithSHA1And40BitRC4 +pkcs12-pbeids 2 : PBE-SHA1-RC4-40 : pbeWithSHA1And40BitRC4 +!Cname pbe-WithSHA1And3_Key_TripleDES-CBC +pkcs12-pbeids 3 : PBE-SHA1-3DES : pbeWithSHA1And3-KeyTripleDES-CBC +!Cname pbe-WithSHA1And2_Key_TripleDES-CBC +pkcs12-pbeids 4 : PBE-SHA1-2DES : pbeWithSHA1And2-KeyTripleDES-CBC +!Cname pbe-WithSHA1And128BitRC2-CBC +pkcs12-pbeids 5 : PBE-SHA1-RC2-128 : pbeWithSHA1And128BitRC2-CBC +!Cname pbe-WithSHA1And40BitRC2-CBC +pkcs12-pbeids 6 : PBE-SHA1-RC2-40 : pbeWithSHA1And40BitRC2-CBC + +!Alias pkcs12-Version1 pkcs12 10 +!Alias pkcs12-BagIds pkcs12-Version1 1 +pkcs12-BagIds 1 : : keyBag +pkcs12-BagIds 2 : : pkcs8ShroudedKeyBag +pkcs12-BagIds 3 : : certBag +pkcs12-BagIds 4 : : crlBag +pkcs12-BagIds 5 : : secretBag +pkcs12-BagIds 6 : : safeContentsBag + +rsadsi 2 2 : MD2 : md2 +rsadsi 2 4 : MD4 : md4 +rsadsi 2 5 : MD5 : md5 + : MD5-SHA1 : md5-sha1 +rsadsi 2 6 : : hmacWithMD5 +rsadsi 2 7 : : hmacWithSHA1 + +# From RFC4231 +rsadsi 2 8 : : hmacWithSHA224 +rsadsi 2 9 : : hmacWithSHA256 +rsadsi 2 10 : : hmacWithSHA384 +rsadsi 2 11 : : hmacWithSHA512 + +rsadsi 3 2 : RC2-CBC : rc2-cbc + : RC2-ECB : rc2-ecb +!Cname rc2-cfb64 + : RC2-CFB : rc2-cfb +!Cname rc2-ofb64 + : RC2-OFB : rc2-ofb + : RC2-40-CBC : rc2-40-cbc + : RC2-64-CBC : rc2-64-cbc +rsadsi 3 4 : RC4 : rc4 + : RC4-40 : rc4-40 +rsadsi 3 7 : DES-EDE3-CBC : des-ede3-cbc +rsadsi 3 8 : RC5-CBC : rc5-cbc + : RC5-ECB : rc5-ecb +!Cname rc5-cfb64 + : RC5-CFB : rc5-cfb +!Cname rc5-ofb64 + : RC5-OFB : rc5-ofb + +!Cname ms-ext-req +1 3 6 1 4 1 311 2 1 14 : msExtReq : Microsoft Extension Request +!Cname ms-code-ind +1 3 6 1 4 1 311 2 1 21 : msCodeInd : Microsoft Individual Code Signing +!Cname ms-code-com +1 3 6 1 4 1 311 2 1 22 : msCodeCom : Microsoft Commercial Code Signing +!Cname ms-ctl-sign +1 3 6 1 4 1 311 10 3 1 : msCTLSign : Microsoft Trust List Signing +!Cname ms-sgc +1 3 6 1 4 1 311 10 3 3 : msSGC : Microsoft Server Gated Crypto +!Cname ms-efs +1 3 6 1 4 1 311 10 3 4 : msEFS : Microsoft Encrypted File System +!Cname ms-smartcard-login +1 3 6 1 4 1 311 20 2 2 : msSmartcardLogin : Microsoft Smartcardlogin +!Cname ms-upn +1 3 6 1 4 1 311 20 2 3 : msUPN : Microsoft Universal Principal Name + +1 3 6 1 4 1 188 7 1 1 2 : IDEA-CBC : idea-cbc + : IDEA-ECB : idea-ecb +!Cname idea-cfb64 + : IDEA-CFB : idea-cfb +!Cname idea-ofb64 + : IDEA-OFB : idea-ofb + +1 3 6 1 4 1 3029 1 2 : BF-CBC : bf-cbc + : BF-ECB : bf-ecb +!Cname bf-cfb64 + : BF-CFB : bf-cfb +!Cname bf-ofb64 + : BF-OFB : bf-ofb + +!Cname id-pkix +1 3 6 1 5 5 7 : PKIX + +# PKIX Arcs +id-pkix 0 : id-pkix-mod +id-pkix 1 : id-pe +id-pkix 2 : id-qt +id-pkix 3 : id-kp +id-pkix 4 : id-it +id-pkix 5 : id-pkip +id-pkix 6 : id-alg +id-pkix 7 : id-cmc +id-pkix 8 : id-on +id-pkix 9 : id-pda +id-pkix 10 : id-aca +id-pkix 11 : id-qcs +id-pkix 12 : id-cct +id-pkix 21 : id-ppl +id-pkix 48 : id-ad + +# PKIX Modules +id-pkix-mod 1 : id-pkix1-explicit-88 +id-pkix-mod 2 : id-pkix1-implicit-88 +id-pkix-mod 3 : id-pkix1-explicit-93 +id-pkix-mod 4 : id-pkix1-implicit-93 +id-pkix-mod 5 : id-mod-crmf +id-pkix-mod 6 : id-mod-cmc +id-pkix-mod 7 : id-mod-kea-profile-88 +id-pkix-mod 8 : id-mod-kea-profile-93 +id-pkix-mod 9 : id-mod-cmp +id-pkix-mod 10 : id-mod-qualified-cert-88 +id-pkix-mod 11 : id-mod-qualified-cert-93 +id-pkix-mod 12 : id-mod-attribute-cert +id-pkix-mod 13 : id-mod-timestamp-protocol +id-pkix-mod 14 : id-mod-ocsp +id-pkix-mod 15 : id-mod-dvcs +id-pkix-mod 16 : id-mod-cmp2000 + +# PKIX Private Extensions +!Cname info-access +id-pe 1 : authorityInfoAccess : Authority Information Access +id-pe 2 : biometricInfo : Biometric Info +id-pe 3 : qcStatements +id-pe 4 : ac-auditEntity +id-pe 5 : ac-targeting +id-pe 6 : aaControls +id-pe 7 : sbgp-ipAddrBlock +id-pe 8 : sbgp-autonomousSysNum +id-pe 9 : sbgp-routerIdentifier +id-pe 10 : ac-proxying +!Cname sinfo-access +id-pe 11 : subjectInfoAccess : Subject Information Access +id-pe 14 : proxyCertInfo : Proxy Certificate Information + +# PKIX policyQualifiers for Internet policy qualifiers +id-qt 1 : id-qt-cps : Policy Qualifier CPS +id-qt 2 : id-qt-unotice : Policy Qualifier User Notice +id-qt 3 : textNotice + +# PKIX key purpose identifiers +!Cname server-auth +id-kp 1 : serverAuth : TLS Web Server Authentication +!Cname client-auth +id-kp 2 : clientAuth : TLS Web Client Authentication +!Cname code-sign +id-kp 3 : codeSigning : Code Signing +!Cname email-protect +id-kp 4 : emailProtection : E-mail Protection +id-kp 5 : ipsecEndSystem : IPSec End System +id-kp 6 : ipsecTunnel : IPSec Tunnel +id-kp 7 : ipsecUser : IPSec User +!Cname time-stamp +id-kp 8 : timeStamping : Time Stamping +# From OCSP spec RFC2560 +!Cname OCSP-sign +id-kp 9 : OCSPSigning : OCSP Signing +id-kp 10 : DVCS : dvcs + +# CMP information types +id-it 1 : id-it-caProtEncCert +id-it 2 : id-it-signKeyPairTypes +id-it 3 : id-it-encKeyPairTypes +id-it 4 : id-it-preferredSymmAlg +id-it 5 : id-it-caKeyUpdateInfo +id-it 6 : id-it-currentCRL +id-it 7 : id-it-unsupportedOIDs +# obsolete +id-it 8 : id-it-subscriptionRequest +# obsolete +id-it 9 : id-it-subscriptionResponse +id-it 10 : id-it-keyPairParamReq +id-it 11 : id-it-keyPairParamRep +id-it 12 : id-it-revPassphrase +id-it 13 : id-it-implicitConfirm +id-it 14 : id-it-confirmWaitTime +id-it 15 : id-it-origPKIMessage +id-it 16 : id-it-suppLangTags + +# CRMF registration +id-pkip 1 : id-regCtrl +id-pkip 2 : id-regInfo + +# CRMF registration controls +id-regCtrl 1 : id-regCtrl-regToken +id-regCtrl 2 : id-regCtrl-authenticator +id-regCtrl 3 : id-regCtrl-pkiPublicationInfo +id-regCtrl 4 : id-regCtrl-pkiArchiveOptions +id-regCtrl 5 : id-regCtrl-oldCertID +id-regCtrl 6 : id-regCtrl-protocolEncrKey + +# CRMF registration information +id-regInfo 1 : id-regInfo-utf8Pairs +id-regInfo 2 : id-regInfo-certReq + +# algorithms +id-alg 1 : id-alg-des40 +id-alg 2 : id-alg-noSignature +id-alg 3 : id-alg-dh-sig-hmac-sha1 +id-alg 4 : id-alg-dh-pop + +# CMC controls +id-cmc 1 : id-cmc-statusInfo +id-cmc 2 : id-cmc-identification +id-cmc 3 : id-cmc-identityProof +id-cmc 4 : id-cmc-dataReturn +id-cmc 5 : id-cmc-transactionId +id-cmc 6 : id-cmc-senderNonce +id-cmc 7 : id-cmc-recipientNonce +id-cmc 8 : id-cmc-addExtensions +id-cmc 9 : id-cmc-encryptedPOP +id-cmc 10 : id-cmc-decryptedPOP +id-cmc 11 : id-cmc-lraPOPWitness +id-cmc 15 : id-cmc-getCert +id-cmc 16 : id-cmc-getCRL +id-cmc 17 : id-cmc-revokeRequest +id-cmc 18 : id-cmc-regInfo +id-cmc 19 : id-cmc-responseInfo +id-cmc 21 : id-cmc-queryPending +id-cmc 22 : id-cmc-popLinkRandom +id-cmc 23 : id-cmc-popLinkWitness +id-cmc 24 : id-cmc-confirmCertAcceptance + +# other names +id-on 1 : id-on-personalData +id-on 3 : id-on-permanentIdentifier : Permanent Identifier + +# personal data attributes +id-pda 1 : id-pda-dateOfBirth +id-pda 2 : id-pda-placeOfBirth +id-pda 3 : id-pda-gender +id-pda 4 : id-pda-countryOfCitizenship +id-pda 5 : id-pda-countryOfResidence + +# attribute certificate attributes +id-aca 1 : id-aca-authenticationInfo +id-aca 2 : id-aca-accessIdentity +id-aca 3 : id-aca-chargingIdentity +id-aca 4 : id-aca-group +# attention : the following seems to be obsolete, replace by 'role' +id-aca 5 : id-aca-role +id-aca 6 : id-aca-encAttrs + +# qualified certificate statements +id-qcs 1 : id-qcs-pkixQCSyntax-v1 + +# CMC content types +id-cct 1 : id-cct-crs +id-cct 2 : id-cct-PKIData +id-cct 3 : id-cct-PKIResponse + +# Predefined Proxy Certificate policy languages +id-ppl 0 : id-ppl-anyLanguage : Any language +id-ppl 1 : id-ppl-inheritAll : Inherit all +id-ppl 2 : id-ppl-independent : Independent + +# access descriptors for authority info access extension +!Cname ad-OCSP +id-ad 1 : OCSP : OCSP +!Cname ad-ca-issuers +id-ad 2 : caIssuers : CA Issuers +!Cname ad-timeStamping +id-ad 3 : ad_timestamping : AD Time Stamping +!Cname ad-dvcs +id-ad 4 : AD_DVCS : ad dvcs +id-ad 5 : caRepository : CA Repository + + +!Alias id-pkix-OCSP ad-OCSP +!module id-pkix-OCSP +!Cname basic +id-pkix-OCSP 1 : basicOCSPResponse : Basic OCSP Response +id-pkix-OCSP 2 : Nonce : OCSP Nonce +id-pkix-OCSP 3 : CrlID : OCSP CRL ID +id-pkix-OCSP 4 : acceptableResponses : Acceptable OCSP Responses +id-pkix-OCSP 5 : noCheck : OCSP No Check +id-pkix-OCSP 6 : archiveCutoff : OCSP Archive Cutoff +id-pkix-OCSP 7 : serviceLocator : OCSP Service Locator +id-pkix-OCSP 8 : extendedStatus : Extended OCSP Status +id-pkix-OCSP 9 : valid +id-pkix-OCSP 10 : path +id-pkix-OCSP 11 : trustRoot : Trust Root +!global + +1 3 14 3 2 : algorithm : algorithm +algorithm 3 : RSA-NP-MD5 : md5WithRSA +algorithm 6 : DES-ECB : des-ecb +algorithm 7 : DES-CBC : des-cbc +!Cname des-ofb64 +algorithm 8 : DES-OFB : des-ofb +!Cname des-cfb64 +algorithm 9 : DES-CFB : des-cfb +algorithm 11 : rsaSignature +!Cname dsa-2 +algorithm 12 : DSA-old : dsaEncryption-old +algorithm 13 : DSA-SHA : dsaWithSHA +algorithm 15 : RSA-SHA : shaWithRSAEncryption +!Cname des-ede-ecb +algorithm 17 : DES-EDE : des-ede +!Cname des-ede3-ecb + : DES-EDE3 : des-ede3 + : DES-EDE-CBC : des-ede-cbc +!Cname des-ede-cfb64 + : DES-EDE-CFB : des-ede-cfb +!Cname des-ede3-cfb64 + : DES-EDE3-CFB : des-ede3-cfb +!Cname des-ede-ofb64 + : DES-EDE-OFB : des-ede-ofb +!Cname des-ede3-ofb64 + : DES-EDE3-OFB : des-ede3-ofb + : DESX-CBC : desx-cbc +algorithm 18 : SHA : sha +algorithm 26 : SHA1 : sha1 +!Cname dsaWithSHA1-2 +algorithm 27 : DSA-SHA1-old : dsaWithSHA1-old +algorithm 29 : RSA-SHA1-2 : sha1WithRSA + +1 3 36 3 2 1 : RIPEMD160 : ripemd160 +1 3 36 3 3 1 2 : RSA-RIPEMD160 : ripemd160WithRSA + +!Cname sxnet +1 3 101 1 4 1 : SXNetID : Strong Extranet ID + +2 5 : X500 : directory services (X.500) + +X500 4 : X509 +X509 3 : CN : commonName +X509 4 : SN : surname +X509 5 : : serialNumber +X509 6 : C : countryName +X509 7 : L : localityName +X509 8 : ST : stateOrProvinceName +X509 9 : street : streetAddress +X509 10 : O : organizationName +X509 11 : OU : organizationalUnitName +X509 12 : title : title +X509 13 : : description +X509 14 : : searchGuide +X509 15 : : businessCategory +X509 16 : : postalAddress +X509 17 : : postalCode +X509 18 : : postOfficeBox +X509 19 : : physicalDeliveryOfficeName +X509 20 : : telephoneNumber +X509 21 : : telexNumber +X509 22 : : teletexTerminalIdentifier +X509 23 : : facsimileTelephoneNumber +X509 24 : : x121Address +X509 25 : : internationaliSDNNumber +X509 26 : : registeredAddress +X509 27 : : destinationIndicator +X509 28 : : preferredDeliveryMethod +X509 29 : : presentationAddress +X509 30 : : supportedApplicationContext +X509 31 : member : +X509 32 : owner : +X509 33 : : roleOccupant +X509 34 : seeAlso : +X509 35 : : userPassword +X509 36 : : userCertificate +X509 37 : : cACertificate +X509 38 : : authorityRevocationList +X509 39 : : certificateRevocationList +X509 40 : : crossCertificatePair +X509 41 : name : name +X509 42 : GN : givenName +X509 43 : initials : initials +X509 44 : : generationQualifier +X509 45 : : x500UniqueIdentifier +X509 46 : dnQualifier : dnQualifier +X509 47 : : enhancedSearchGuide +X509 48 : : protocolInformation +X509 49 : : distinguishedName +X509 50 : : uniqueMember +X509 51 : : houseIdentifier +X509 52 : : supportedAlgorithms +X509 53 : : deltaRevocationList +X509 54 : dmdName : +X509 65 : : pseudonym +X509 72 : role : role + +X500 8 : X500algorithms : directory services - algorithms +X500algorithms 1 1 : RSA : rsa +X500algorithms 3 100 : RSA-MDC2 : mdc2WithRSA +X500algorithms 3 101 : MDC2 : mdc2 + +X500 29 : id-ce +!Cname subject-directory-attributes +id-ce 9 : subjectDirectoryAttributes : X509v3 Subject Directory Attributes +!Cname subject-key-identifier +id-ce 14 : subjectKeyIdentifier : X509v3 Subject Key Identifier +!Cname key-usage +id-ce 15 : keyUsage : X509v3 Key Usage +!Cname private-key-usage-period +id-ce 16 : privateKeyUsagePeriod : X509v3 Private Key Usage Period +!Cname subject-alt-name +id-ce 17 : subjectAltName : X509v3 Subject Alternative Name +!Cname issuer-alt-name +id-ce 18 : issuerAltName : X509v3 Issuer Alternative Name +!Cname basic-constraints +id-ce 19 : basicConstraints : X509v3 Basic Constraints +!Cname crl-number +id-ce 20 : crlNumber : X509v3 CRL Number +!Cname crl-reason +id-ce 21 : CRLReason : X509v3 CRL Reason Code +!Cname invalidity-date +id-ce 24 : invalidityDate : Invalidity Date +!Cname delta-crl +id-ce 27 : deltaCRL : X509v3 Delta CRL Indicator +!Cname issuing-distribution-point +id-ce 28 : issuingDistributionPoint : X509v3 Issuing Distribution Point +!Cname certificate-issuer +id-ce 29 : certificateIssuer : X509v3 Certificate Issuer +!Cname name-constraints +id-ce 30 : nameConstraints : X509v3 Name Constraints +!Cname crl-distribution-points +id-ce 31 : crlDistributionPoints : X509v3 CRL Distribution Points +!Cname certificate-policies +id-ce 32 : certificatePolicies : X509v3 Certificate Policies +!Cname any-policy +certificate-policies 0 : anyPolicy : X509v3 Any Policy +!Cname policy-mappings +id-ce 33 : policyMappings : X509v3 Policy Mappings +!Cname authority-key-identifier +id-ce 35 : authorityKeyIdentifier : X509v3 Authority Key Identifier +!Cname policy-constraints +id-ce 36 : policyConstraints : X509v3 Policy Constraints +!Cname ext-key-usage +id-ce 37 : extendedKeyUsage : X509v3 Extended Key Usage +!Cname freshest-crl +id-ce 46 : freshestCRL : X509v3 Freshest CRL +!Cname inhibit-any-policy +id-ce 54 : inhibitAnyPolicy : X509v3 Inhibit Any Policy +!Cname target-information +id-ce 55 : targetInformation : X509v3 AC Targeting +!Cname no-rev-avail +id-ce 56 : noRevAvail : X509v3 No Revocation Available + +# From RFC5280 +ext-key-usage 0 : anyExtendedKeyUsage : Any Extended Key Usage + + +!Cname netscape +2 16 840 1 113730 : Netscape : Netscape Communications Corp. +!Cname netscape-cert-extension +netscape 1 : nsCertExt : Netscape Certificate Extension +!Cname netscape-data-type +netscape 2 : nsDataType : Netscape Data Type +!Cname netscape-cert-type +netscape-cert-extension 1 : nsCertType : Netscape Cert Type +!Cname netscape-base-url +netscape-cert-extension 2 : nsBaseUrl : Netscape Base Url +!Cname netscape-revocation-url +netscape-cert-extension 3 : nsRevocationUrl : Netscape Revocation Url +!Cname netscape-ca-revocation-url +netscape-cert-extension 4 : nsCaRevocationUrl : Netscape CA Revocation Url +!Cname netscape-renewal-url +netscape-cert-extension 7 : nsRenewalUrl : Netscape Renewal Url +!Cname netscape-ca-policy-url +netscape-cert-extension 8 : nsCaPolicyUrl : Netscape CA Policy Url +!Cname netscape-ssl-server-name +netscape-cert-extension 12 : nsSslServerName : Netscape SSL Server Name +!Cname netscape-comment +netscape-cert-extension 13 : nsComment : Netscape Comment +!Cname netscape-cert-sequence +netscape-data-type 5 : nsCertSequence : Netscape Certificate Sequence +!Cname ns-sgc +netscape 4 1 : nsSGC : Netscape Server Gated Crypto + +# iso(1) +iso 3 : ORG : org +org 6 : DOD : dod +dod 1 : IANA : iana +!Alias internet iana + +internet 1 : directory : Directory +internet 2 : mgmt : Management +internet 3 : experimental : Experimental +internet 4 : private : Private +internet 5 : security : Security +internet 6 : snmpv2 : SNMPv2 +# Documents refer to "internet 7" as "mail". This however leads to ambiguities +# with RFC2798, Section 9.1.3, where "mail" is defined as the short name for +# rfc822Mailbox. The short name is therefore here left out for a reason. +# Subclasses of "mail", e.g. "MIME MHS" don't consitute a problem, as +# references are realized via long name "Mail" (with capital M). +internet 7 : : Mail + +Private 1 : enterprises : Enterprises + +# RFC 2247 +Enterprises 1466 344 : dcobject : dcObject + +# RFC 1495 +Mail 1 : mime-mhs : MIME MHS +mime-mhs 1 : mime-mhs-headings : mime-mhs-headings +mime-mhs 2 : mime-mhs-bodies : mime-mhs-bodies +mime-mhs-headings 1 : id-hex-partial-message : id-hex-partial-message +mime-mhs-headings 2 : id-hex-multipart-message : id-hex-multipart-message + +# RFC 3274 +!Cname zlib-compression +id-smime-alg 8 : ZLIB : zlib compression + +# AES aka Rijndael + +!Alias csor 2 16 840 1 101 3 +!Alias nistAlgorithms csor 4 +!Alias aes nistAlgorithms 1 + +aes 1 : AES-128-ECB : aes-128-ecb +aes 2 : AES-128-CBC : aes-128-cbc +!Cname aes-128-ofb128 +aes 3 : AES-128-OFB : aes-128-ofb +!Cname aes-128-cfb128 +aes 4 : AES-128-CFB : aes-128-cfb +aes 5 : id-aes128-wrap +aes 6 : id-aes128-GCM : aes-128-gcm +aes 7 : id-aes128-CCM : aes-128-ccm +aes 8 : id-aes128-wrap-pad + +aes 21 : AES-192-ECB : aes-192-ecb +aes 22 : AES-192-CBC : aes-192-cbc +!Cname aes-192-ofb128 +aes 23 : AES-192-OFB : aes-192-ofb +!Cname aes-192-cfb128 +aes 24 : AES-192-CFB : aes-192-cfb +aes 25 : id-aes192-wrap +aes 26 : id-aes192-GCM : aes-192-gcm +aes 27 : id-aes192-CCM : aes-192-ccm +aes 28 : id-aes192-wrap-pad + +aes 41 : AES-256-ECB : aes-256-ecb +aes 42 : AES-256-CBC : aes-256-cbc +!Cname aes-256-ofb128 +aes 43 : AES-256-OFB : aes-256-ofb +!Cname aes-256-cfb128 +aes 44 : AES-256-CFB : aes-256-cfb +aes 45 : id-aes256-wrap +aes 46 : id-aes256-GCM : aes-256-gcm +aes 47 : id-aes256-CCM : aes-256-ccm +aes 48 : id-aes256-wrap-pad + +# There are no OIDs for these modes... + + : AES-128-CFB1 : aes-128-cfb1 + : AES-192-CFB1 : aes-192-cfb1 + : AES-256-CFB1 : aes-256-cfb1 + : AES-128-CFB8 : aes-128-cfb8 + : AES-192-CFB8 : aes-192-cfb8 + : AES-256-CFB8 : aes-256-cfb8 + : AES-128-CTR : aes-128-ctr + : AES-192-CTR : aes-192-ctr + : AES-256-CTR : aes-256-ctr + : AES-128-XTS : aes-128-xts + : AES-256-XTS : aes-256-xts + : DES-CFB1 : des-cfb1 + : DES-CFB8 : des-cfb8 + : DES-EDE3-CFB1 : des-ede3-cfb1 + : DES-EDE3-CFB8 : des-ede3-cfb8 + +# OIDs for SHA224, SHA256, SHA385 and SHA512, according to x9.84. +!Alias nist_hashalgs nistAlgorithms 2 +nist_hashalgs 1 : SHA256 : sha256 +nist_hashalgs 2 : SHA384 : sha384 +nist_hashalgs 3 : SHA512 : sha512 +nist_hashalgs 4 : SHA224 : sha224 + +# OIDs for dsa-with-sha224 and dsa-with-sha256 +!Alias dsa_with_sha2 nistAlgorithms 3 +dsa_with_sha2 1 : dsa_with_SHA224 +dsa_with_sha2 2 : dsa_with_SHA256 + +# Hold instruction CRL entry extension +!Cname hold-instruction-code +id-ce 23 : holdInstructionCode : Hold Instruction Code +!Alias holdInstruction X9-57 2 +!Cname hold-instruction-none +holdInstruction 1 : holdInstructionNone : Hold Instruction None +!Cname hold-instruction-call-issuer +holdInstruction 2 : holdInstructionCallIssuer : Hold Instruction Call Issuer +!Cname hold-instruction-reject +holdInstruction 3 : holdInstructionReject : Hold Instruction Reject + +# OID's from ITU-T. Most of this is defined in RFC 1274. A couple of +# them are also mentioned in RFC 2247 +itu-t 9 : data +data 2342 : pss +pss 19200300 : ucl +ucl 100 : pilot +pilot 1 : : pilotAttributeType +pilot 3 : : pilotAttributeSyntax +pilot 4 : : pilotObjectClass +pilot 10 : : pilotGroups +pilotAttributeSyntax 4 : : iA5StringSyntax +pilotAttributeSyntax 5 : : caseIgnoreIA5StringSyntax +pilotObjectClass 3 : : pilotObject +pilotObjectClass 4 : : pilotPerson +pilotObjectClass 5 : account +pilotObjectClass 6 : document +pilotObjectClass 7 : room +pilotObjectClass 9 : : documentSeries +pilotObjectClass 13 : domain : Domain +pilotObjectClass 14 : : rFC822localPart +pilotObjectClass 15 : : dNSDomain +pilotObjectClass 17 : : domainRelatedObject +pilotObjectClass 18 : : friendlyCountry +pilotObjectClass 19 : : simpleSecurityObject +pilotObjectClass 20 : : pilotOrganization +pilotObjectClass 21 : : pilotDSA +pilotObjectClass 22 : : qualityLabelledData +pilotAttributeType 1 : UID : userId +pilotAttributeType 2 : : textEncodedORAddress +pilotAttributeType 3 : mail : rfc822Mailbox +pilotAttributeType 4 : info +pilotAttributeType 5 : : favouriteDrink +pilotAttributeType 6 : : roomNumber +pilotAttributeType 7 : photo +pilotAttributeType 8 : : userClass +pilotAttributeType 9 : host +pilotAttributeType 10 : manager +pilotAttributeType 11 : : documentIdentifier +pilotAttributeType 12 : : documentTitle +pilotAttributeType 13 : : documentVersion +pilotAttributeType 14 : : documentAuthor +pilotAttributeType 15 : : documentLocation +pilotAttributeType 20 : : homeTelephoneNumber +pilotAttributeType 21 : secretary +pilotAttributeType 22 : : otherMailbox +pilotAttributeType 23 : : lastModifiedTime +pilotAttributeType 24 : : lastModifiedBy +pilotAttributeType 25 : DC : domainComponent +pilotAttributeType 26 : : aRecord +pilotAttributeType 27 : : pilotAttributeType27 +pilotAttributeType 28 : : mXRecord +pilotAttributeType 29 : : nSRecord +pilotAttributeType 30 : : sOARecord +pilotAttributeType 31 : : cNAMERecord +pilotAttributeType 37 : : associatedDomain +pilotAttributeType 38 : : associatedName +pilotAttributeType 39 : : homePostalAddress +pilotAttributeType 40 : : personalTitle +pilotAttributeType 41 : : mobileTelephoneNumber +pilotAttributeType 42 : : pagerTelephoneNumber +pilotAttributeType 43 : : friendlyCountryName +# The following clashes with 2.5.4.45, so commented away +#pilotAttributeType 44 : uid : uniqueIdentifier +pilotAttributeType 45 : : organizationalStatus +pilotAttributeType 46 : : janetMailbox +pilotAttributeType 47 : : mailPreferenceOption +pilotAttributeType 48 : : buildingName +pilotAttributeType 49 : : dSAQuality +pilotAttributeType 50 : : singleLevelQuality +pilotAttributeType 51 : : subtreeMinimumQuality +pilotAttributeType 52 : : subtreeMaximumQuality +pilotAttributeType 53 : : personalSignature +pilotAttributeType 54 : : dITRedirect +pilotAttributeType 55 : audio +pilotAttributeType 56 : : documentPublisher + +international-organizations 42 : id-set : Secure Electronic Transactions + +id-set 0 : set-ctype : content types +id-set 1 : set-msgExt : message extensions +id-set 3 : set-attr +id-set 5 : set-policy +id-set 7 : set-certExt : certificate extensions +id-set 8 : set-brand + +set-ctype 0 : setct-PANData +set-ctype 1 : setct-PANToken +set-ctype 2 : setct-PANOnly +set-ctype 3 : setct-OIData +set-ctype 4 : setct-PI +set-ctype 5 : setct-PIData +set-ctype 6 : setct-PIDataUnsigned +set-ctype 7 : setct-HODInput +set-ctype 8 : setct-AuthResBaggage +set-ctype 9 : setct-AuthRevReqBaggage +set-ctype 10 : setct-AuthRevResBaggage +set-ctype 11 : setct-CapTokenSeq +set-ctype 12 : setct-PInitResData +set-ctype 13 : setct-PI-TBS +set-ctype 14 : setct-PResData +set-ctype 16 : setct-AuthReqTBS +set-ctype 17 : setct-AuthResTBS +set-ctype 18 : setct-AuthResTBSX +set-ctype 19 : setct-AuthTokenTBS +set-ctype 20 : setct-CapTokenData +set-ctype 21 : setct-CapTokenTBS +set-ctype 22 : setct-AcqCardCodeMsg +set-ctype 23 : setct-AuthRevReqTBS +set-ctype 24 : setct-AuthRevResData +set-ctype 25 : setct-AuthRevResTBS +set-ctype 26 : setct-CapReqTBS +set-ctype 27 : setct-CapReqTBSX +set-ctype 28 : setct-CapResData +set-ctype 29 : setct-CapRevReqTBS +set-ctype 30 : setct-CapRevReqTBSX +set-ctype 31 : setct-CapRevResData +set-ctype 32 : setct-CredReqTBS +set-ctype 33 : setct-CredReqTBSX +set-ctype 34 : setct-CredResData +set-ctype 35 : setct-CredRevReqTBS +set-ctype 36 : setct-CredRevReqTBSX +set-ctype 37 : setct-CredRevResData +set-ctype 38 : setct-PCertReqData +set-ctype 39 : setct-PCertResTBS +set-ctype 40 : setct-BatchAdminReqData +set-ctype 41 : setct-BatchAdminResData +set-ctype 42 : setct-CardCInitResTBS +set-ctype 43 : setct-MeAqCInitResTBS +set-ctype 44 : setct-RegFormResTBS +set-ctype 45 : setct-CertReqData +set-ctype 46 : setct-CertReqTBS +set-ctype 47 : setct-CertResData +set-ctype 48 : setct-CertInqReqTBS +set-ctype 49 : setct-ErrorTBS +set-ctype 50 : setct-PIDualSignedTBE +set-ctype 51 : setct-PIUnsignedTBE +set-ctype 52 : setct-AuthReqTBE +set-ctype 53 : setct-AuthResTBE +set-ctype 54 : setct-AuthResTBEX +set-ctype 55 : setct-AuthTokenTBE +set-ctype 56 : setct-CapTokenTBE +set-ctype 57 : setct-CapTokenTBEX +set-ctype 58 : setct-AcqCardCodeMsgTBE +set-ctype 59 : setct-AuthRevReqTBE +set-ctype 60 : setct-AuthRevResTBE +set-ctype 61 : setct-AuthRevResTBEB +set-ctype 62 : setct-CapReqTBE +set-ctype 63 : setct-CapReqTBEX +set-ctype 64 : setct-CapResTBE +set-ctype 65 : setct-CapRevReqTBE +set-ctype 66 : setct-CapRevReqTBEX +set-ctype 67 : setct-CapRevResTBE +set-ctype 68 : setct-CredReqTBE +set-ctype 69 : setct-CredReqTBEX +set-ctype 70 : setct-CredResTBE +set-ctype 71 : setct-CredRevReqTBE +set-ctype 72 : setct-CredRevReqTBEX +set-ctype 73 : setct-CredRevResTBE +set-ctype 74 : setct-BatchAdminReqTBE +set-ctype 75 : setct-BatchAdminResTBE +set-ctype 76 : setct-RegFormReqTBE +set-ctype 77 : setct-CertReqTBE +set-ctype 78 : setct-CertReqTBEX +set-ctype 79 : setct-CertResTBE +set-ctype 80 : setct-CRLNotificationTBS +set-ctype 81 : setct-CRLNotificationResTBS +set-ctype 82 : setct-BCIDistributionTBS + +set-msgExt 1 : setext-genCrypt : generic cryptogram +set-msgExt 3 : setext-miAuth : merchant initiated auth +set-msgExt 4 : setext-pinSecure +set-msgExt 5 : setext-pinAny +set-msgExt 7 : setext-track2 +set-msgExt 8 : setext-cv : additional verification + +set-policy 0 : set-policy-root + +set-certExt 0 : setCext-hashedRoot +set-certExt 1 : setCext-certType +set-certExt 2 : setCext-merchData +set-certExt 3 : setCext-cCertRequired +set-certExt 4 : setCext-tunneling +set-certExt 5 : setCext-setExt +set-certExt 6 : setCext-setQualf +set-certExt 7 : setCext-PGWYcapabilities +set-certExt 8 : setCext-TokenIdentifier +set-certExt 9 : setCext-Track2Data +set-certExt 10 : setCext-TokenType +set-certExt 11 : setCext-IssuerCapabilities + +set-attr 0 : setAttr-Cert +set-attr 1 : setAttr-PGWYcap : payment gateway capabilities +set-attr 2 : setAttr-TokenType +set-attr 3 : setAttr-IssCap : issuer capabilities + +setAttr-Cert 0 : set-rootKeyThumb +setAttr-Cert 1 : set-addPolicy + +setAttr-TokenType 1 : setAttr-Token-EMV +setAttr-TokenType 2 : setAttr-Token-B0Prime + +setAttr-IssCap 3 : setAttr-IssCap-CVM +setAttr-IssCap 4 : setAttr-IssCap-T2 +setAttr-IssCap 5 : setAttr-IssCap-Sig + +setAttr-IssCap-CVM 1 : setAttr-GenCryptgrm : generate cryptogram +setAttr-IssCap-T2 1 : setAttr-T2Enc : encrypted track 2 +setAttr-IssCap-T2 2 : setAttr-T2cleartxt : cleartext track 2 + +setAttr-IssCap-Sig 1 : setAttr-TokICCsig : ICC or token signature +setAttr-IssCap-Sig 2 : setAttr-SecDevSig : secure device signature + +set-brand 1 : set-brand-IATA-ATA +set-brand 30 : set-brand-Diners +set-brand 34 : set-brand-AmericanExpress +set-brand 35 : set-brand-JCB +set-brand 4 : set-brand-Visa +set-brand 5 : set-brand-MasterCard +set-brand 6011 : set-brand-Novus + +rsadsi 3 10 : DES-CDMF : des-cdmf +rsadsi 1 1 6 : rsaOAEPEncryptionSET + + : Oakley-EC2N-3 : ipsec3 + : Oakley-EC2N-4 : ipsec4 + +iso 0 10118 3 0 55 : whirlpool + +# GOST OIDs + +member-body 643 2 2 : cryptopro +member-body 643 2 9 : cryptocom + +cryptopro 3 : id-GostR3411-94-with-GostR3410-2001 : GOST R 34.11-94 with GOST R 34.10-2001 +cryptopro 4 : id-GostR3411-94-with-GostR3410-94 : GOST R 34.11-94 with GOST R 34.10-94 +!Cname id-GostR3411-94 +cryptopro 9 : md_gost94 : GOST R 34.11-94 +cryptopro 10 : id-HMACGostR3411-94 : HMAC GOST 34.11-94 +!Cname id-GostR3410-2001 +cryptopro 19 : gost2001 : GOST R 34.10-2001 +!Cname id-GostR3410-94 +cryptopro 20 : gost94 : GOST R 34.10-94 +!Cname id-Gost28147-89 +cryptopro 21 : gost89 : GOST 28147-89 + : gost89-cnt +!Cname id-Gost28147-89-MAC +cryptopro 22 : gost-mac : GOST 28147-89 MAC +!Cname id-GostR3411-94-prf +cryptopro 23 : prf-gostr3411-94 : GOST R 34.11-94 PRF +cryptopro 98 : id-GostR3410-2001DH : GOST R 34.10-2001 DH +cryptopro 99 : id-GostR3410-94DH : GOST R 34.10-94 DH + +cryptopro 14 1 : id-Gost28147-89-CryptoPro-KeyMeshing +cryptopro 14 0 : id-Gost28147-89-None-KeyMeshing + +# GOST parameter set OIDs + +cryptopro 30 0 : id-GostR3411-94-TestParamSet +cryptopro 30 1 : id-GostR3411-94-CryptoProParamSet + +cryptopro 31 0 : id-Gost28147-89-TestParamSet +cryptopro 31 1 : id-Gost28147-89-CryptoPro-A-ParamSet +cryptopro 31 2 : id-Gost28147-89-CryptoPro-B-ParamSet +cryptopro 31 3 : id-Gost28147-89-CryptoPro-C-ParamSet +cryptopro 31 4 : id-Gost28147-89-CryptoPro-D-ParamSet +cryptopro 31 5 : id-Gost28147-89-CryptoPro-Oscar-1-1-ParamSet +cryptopro 31 6 : id-Gost28147-89-CryptoPro-Oscar-1-0-ParamSet +cryptopro 31 7 : id-Gost28147-89-CryptoPro-RIC-1-ParamSet + +cryptopro 32 0 : id-GostR3410-94-TestParamSet +cryptopro 32 2 : id-GostR3410-94-CryptoPro-A-ParamSet +cryptopro 32 3 : id-GostR3410-94-CryptoPro-B-ParamSet +cryptopro 32 4 : id-GostR3410-94-CryptoPro-C-ParamSet +cryptopro 32 5 : id-GostR3410-94-CryptoPro-D-ParamSet + +cryptopro 33 1 : id-GostR3410-94-CryptoPro-XchA-ParamSet +cryptopro 33 2 : id-GostR3410-94-CryptoPro-XchB-ParamSet +cryptopro 33 3 : id-GostR3410-94-CryptoPro-XchC-ParamSet + +cryptopro 35 0 : id-GostR3410-2001-TestParamSet +cryptopro 35 1 : id-GostR3410-2001-CryptoPro-A-ParamSet +cryptopro 35 2 : id-GostR3410-2001-CryptoPro-B-ParamSet +cryptopro 35 3 : id-GostR3410-2001-CryptoPro-C-ParamSet + +cryptopro 36 0 : id-GostR3410-2001-CryptoPro-XchA-ParamSet +cryptopro 36 1 : id-GostR3410-2001-CryptoPro-XchB-ParamSet + +id-GostR3410-94 1 : id-GostR3410-94-a +id-GostR3410-94 2 : id-GostR3410-94-aBis +id-GostR3410-94 3 : id-GostR3410-94-b +id-GostR3410-94 4 : id-GostR3410-94-bBis + +# Cryptocom LTD GOST OIDs + +cryptocom 1 6 1 : id-Gost28147-89-cc : GOST 28147-89 Cryptocom ParamSet +!Cname id-GostR3410-94-cc +cryptocom 1 5 3 : gost94cc : GOST 34.10-94 Cryptocom +!Cname id-GostR3410-2001-cc +cryptocom 1 5 4 : gost2001cc : GOST 34.10-2001 Cryptocom + +cryptocom 1 3 3 : id-GostR3411-94-with-GostR3410-94-cc : GOST R 34.11-94 with GOST R 34.10-94 Cryptocom +cryptocom 1 3 4 : id-GostR3411-94-with-GostR3410-2001-cc : GOST R 34.11-94 with GOST R 34.10-2001 Cryptocom + +cryptocom 1 8 1 : id-GostR3410-2001-ParamSet-cc : GOST R 3410-2001 Parameter Set Cryptocom + +# Definitions for Camellia cipher - CBC MODE + +1 2 392 200011 61 1 1 1 2 : CAMELLIA-128-CBC : camellia-128-cbc +1 2 392 200011 61 1 1 1 3 : CAMELLIA-192-CBC : camellia-192-cbc +1 2 392 200011 61 1 1 1 4 : CAMELLIA-256-CBC : camellia-256-cbc +1 2 392 200011 61 1 1 3 2 : id-camellia128-wrap +1 2 392 200011 61 1 1 3 3 : id-camellia192-wrap +1 2 392 200011 61 1 1 3 4 : id-camellia256-wrap + +# Definitions for Camellia cipher - ECB, CFB, OFB MODE + +!Alias ntt-ds 0 3 4401 5 +!Alias camellia ntt-ds 3 1 9 + +camellia 1 : CAMELLIA-128-ECB : camellia-128-ecb +!Cname camellia-128-ofb128 +camellia 3 : CAMELLIA-128-OFB : camellia-128-ofb +!Cname camellia-128-cfb128 +camellia 4 : CAMELLIA-128-CFB : camellia-128-cfb + +camellia 21 : CAMELLIA-192-ECB : camellia-192-ecb +!Cname camellia-192-ofb128 +camellia 23 : CAMELLIA-192-OFB : camellia-192-ofb +!Cname camellia-192-cfb128 +camellia 24 : CAMELLIA-192-CFB : camellia-192-cfb + +camellia 41 : CAMELLIA-256-ECB : camellia-256-ecb +!Cname camellia-256-ofb128 +camellia 43 : CAMELLIA-256-OFB : camellia-256-ofb +!Cname camellia-256-cfb128 +camellia 44 : CAMELLIA-256-CFB : camellia-256-cfb + +# There are no OIDs for these modes... + + : CAMELLIA-128-CFB1 : camellia-128-cfb1 + : CAMELLIA-192-CFB1 : camellia-192-cfb1 + : CAMELLIA-256-CFB1 : camellia-256-cfb1 + : CAMELLIA-128-CFB8 : camellia-128-cfb8 + : CAMELLIA-192-CFB8 : camellia-192-cfb8 + : CAMELLIA-256-CFB8 : camellia-256-cfb8 + +# Definitions for SEED cipher - ECB, CBC, OFB mode + +member-body 410 200004 : KISA : kisa +kisa 1 3 : SEED-ECB : seed-ecb +kisa 1 4 : SEED-CBC : seed-cbc +!Cname seed-cfb128 +kisa 1 5 : SEED-CFB : seed-cfb +!Cname seed-ofb128 +kisa 1 6 : SEED-OFB : seed-ofb + +# There is no OID that just denotes "HMAC" oddly enough... + + : HMAC : hmac +# Nor CMAC either + : CMAC : cmac + +# Synthetic composite ciphersuites + : RC4-HMAC-MD5 : rc4-hmac-md5 + : AES-128-CBC-HMAC-SHA1 : aes-128-cbc-hmac-sha1 + : AES-192-CBC-HMAC-SHA1 : aes-192-cbc-hmac-sha1 + : AES-256-CBC-HMAC-SHA1 : aes-256-cbc-hmac-sha1 + +ISO-US 10046 2 1 : dhpublicnumber : X9.42 DH + +# RFC 5639 curve OIDs (see http://www.ietf.org/rfc/rfc5639.txt) +# versionOne OBJECT IDENTIFIER ::= { +# iso(1) identifified-organization(3) teletrust(36) algorithm(3) +# signature-algorithm(3) ecSign(2) ecStdCurvesAndGeneration(8) +# ellipticCurve(1) 1 } +1 3 36 3 3 2 8 1 1 1 : brainpoolP160r1 +1 3 36 3 3 2 8 1 1 2 : brainpoolP160t1 +1 3 36 3 3 2 8 1 1 3 : brainpoolP192r1 +1 3 36 3 3 2 8 1 1 4 : brainpoolP192t1 +1 3 36 3 3 2 8 1 1 5 : brainpoolP224r1 +1 3 36 3 3 2 8 1 1 6 : brainpoolP224t1 +1 3 36 3 3 2 8 1 1 7 : brainpoolP256r1 +1 3 36 3 3 2 8 1 1 8 : brainpoolP256t1 +1 3 36 3 3 2 8 1 1 9 : brainpoolP320r1 +1 3 36 3 3 2 8 1 1 10 : brainpoolP320t1 +1 3 36 3 3 2 8 1 1 11 : brainpoolP384r1 +1 3 36 3 3 2 8 1 1 12 : brainpoolP384t1 +1 3 36 3 3 2 8 1 1 13 : brainpoolP512r1 +1 3 36 3 3 2 8 1 1 14 : brainpoolP512t1 + +# ECDH schemes from RFC5753 +!Alias x9-63-scheme 1 3 133 16 840 63 0 +!Alias secg-scheme certicom-arc 1 + +x9-63-scheme 2 : dhSinglePass-stdDH-sha1kdf-scheme +secg-scheme 11 0 : dhSinglePass-stdDH-sha224kdf-scheme +secg-scheme 11 1 : dhSinglePass-stdDH-sha256kdf-scheme +secg-scheme 11 2 : dhSinglePass-stdDH-sha384kdf-scheme +secg-scheme 11 3 : dhSinglePass-stdDH-sha512kdf-scheme + +x9-63-scheme 3 : dhSinglePass-cofactorDH-sha1kdf-scheme +secg-scheme 14 0 : dhSinglePass-cofactorDH-sha224kdf-scheme +secg-scheme 14 1 : dhSinglePass-cofactorDH-sha256kdf-scheme +secg-scheme 14 2 : dhSinglePass-cofactorDH-sha384kdf-scheme +secg-scheme 14 3 : dhSinglePass-cofactorDH-sha512kdf-scheme +# NIDs for use with lookup tables. + : dh-std-kdf + : dh-cofactor-kdf + +# NID for X25519 (no corresponding OID). + : X25519 + +# NID for CECPQ1 (no corresponding OID) + : cecpq1 diff --git a/external/boringssl/crypto/pem/CMakeLists.txt b/external/boringssl/crypto/pem/CMakeLists.txt new file mode 100644 index 0000000000..30dd7c92a7 --- /dev/null +++ b/external/boringssl/crypto/pem/CMakeLists.txt @@ -0,0 +1,16 @@ +include_directories(../../include) + +add_library( + pem + + OBJECT + + pem_all.c + pem_info.c + pem_lib.c + pem_oth.c + pem_pk8.c + pem_pkey.c + pem_x509.c + pem_xaux.c +) diff --git a/external/boringssl/crypto/pem/pem_all.c b/external/boringssl/crypto/pem/pem_all.c new file mode 100644 index 0000000000..e94ff2655f --- /dev/null +++ b/external/boringssl/crypto/pem/pem_all.c @@ -0,0 +1,262 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include +#include +#include +#include +/* + * #include + */ +#include +#include + +static RSA *pkey_get_rsa(EVP_PKEY *key, RSA **rsa); +static DSA *pkey_get_dsa(EVP_PKEY *key, DSA **dsa); +static EC_KEY *pkey_get_eckey(EVP_PKEY *key, EC_KEY **eckey); + +IMPLEMENT_PEM_rw(X509_REQ, X509_REQ, PEM_STRING_X509_REQ, X509_REQ) + +IMPLEMENT_PEM_write(X509_REQ_NEW, X509_REQ, PEM_STRING_X509_REQ_OLD, X509_REQ) +IMPLEMENT_PEM_rw(X509_CRL, X509_CRL, PEM_STRING_X509_CRL, X509_CRL) + +/* + * We treat RSA or DSA private keys as a special case. For private keys we + * read in an EVP_PKEY structure with PEM_read_bio_PrivateKey() and extract + * the relevant private key: this means can handle "traditional" and PKCS#8 + * formats transparently. + */ +static RSA *pkey_get_rsa(EVP_PKEY *key, RSA **rsa) +{ + RSA *rtmp; + if (!key) + return NULL; + rtmp = EVP_PKEY_get1_RSA(key); + EVP_PKEY_free(key); + if (!rtmp) + return NULL; + if (rsa) { + RSA_free(*rsa); + *rsa = rtmp; + } + return rtmp; +} + +RSA *PEM_read_bio_RSAPrivateKey(BIO *bp, RSA **rsa, pem_password_cb *cb, + void *u) +{ + EVP_PKEY *pktmp; + pktmp = PEM_read_bio_PrivateKey(bp, NULL, cb, u); + return pkey_get_rsa(pktmp, rsa); +} + +#ifndef OPENSSL_NO_FP_API + +RSA *PEM_read_RSAPrivateKey(FILE *fp, RSA **rsa, pem_password_cb *cb, void *u) +{ + EVP_PKEY *pktmp; + pktmp = PEM_read_PrivateKey(fp, NULL, cb, u); + return pkey_get_rsa(pktmp, rsa); +} + +#endif + +IMPLEMENT_PEM_write_cb_const(RSAPrivateKey, RSA, PEM_STRING_RSA, + RSAPrivateKey) + + +IMPLEMENT_PEM_rw_const(RSAPublicKey, RSA, PEM_STRING_RSA_PUBLIC, + RSAPublicKey) IMPLEMENT_PEM_rw(RSA_PUBKEY, RSA, + PEM_STRING_PUBLIC, + RSA_PUBKEY) +#ifndef OPENSSL_NO_DSA +static DSA *pkey_get_dsa(EVP_PKEY *key, DSA **dsa) +{ + DSA *dtmp; + if (!key) + return NULL; + dtmp = EVP_PKEY_get1_DSA(key); + EVP_PKEY_free(key); + if (!dtmp) + return NULL; + if (dsa) { + DSA_free(*dsa); + *dsa = dtmp; + } + return dtmp; +} + +DSA *PEM_read_bio_DSAPrivateKey(BIO *bp, DSA **dsa, pem_password_cb *cb, + void *u) +{ + EVP_PKEY *pktmp; + pktmp = PEM_read_bio_PrivateKey(bp, NULL, cb, u); + return pkey_get_dsa(pktmp, dsa); /* will free pktmp */ +} + +IMPLEMENT_PEM_write_cb_const(DSAPrivateKey, DSA, PEM_STRING_DSA, + DSAPrivateKey) + + IMPLEMENT_PEM_rw(DSA_PUBKEY, DSA, PEM_STRING_PUBLIC, DSA_PUBKEY) +# ifndef OPENSSL_NO_FP_API +DSA *PEM_read_DSAPrivateKey(FILE *fp, DSA **dsa, pem_password_cb *cb, void *u) +{ + EVP_PKEY *pktmp; + pktmp = PEM_read_PrivateKey(fp, NULL, cb, u); + return pkey_get_dsa(pktmp, dsa); /* will free pktmp */ +} + +# endif + +IMPLEMENT_PEM_rw_const(DSAparams, DSA, PEM_STRING_DSAPARAMS, DSAparams) +#endif +static EC_KEY *pkey_get_eckey(EVP_PKEY *key, EC_KEY **eckey) +{ + EC_KEY *dtmp; + if (!key) + return NULL; + dtmp = EVP_PKEY_get1_EC_KEY(key); + EVP_PKEY_free(key); + if (!dtmp) + return NULL; + if (eckey) { + EC_KEY_free(*eckey); + *eckey = dtmp; + } + return dtmp; +} + +EC_KEY *PEM_read_bio_ECPrivateKey(BIO *bp, EC_KEY **key, pem_password_cb *cb, + void *u) +{ + EVP_PKEY *pktmp; + pktmp = PEM_read_bio_PrivateKey(bp, NULL, cb, u); + return pkey_get_eckey(pktmp, key); /* will free pktmp */ +} + +IMPLEMENT_PEM_write_cb(ECPrivateKey, EC_KEY, PEM_STRING_ECPRIVATEKEY, + ECPrivateKey) + + IMPLEMENT_PEM_rw(EC_PUBKEY, EC_KEY, PEM_STRING_PUBLIC, EC_PUBKEY) +#ifndef OPENSSL_NO_FP_API +EC_KEY *PEM_read_ECPrivateKey(FILE *fp, EC_KEY **eckey, pem_password_cb *cb, + void *u) +{ + EVP_PKEY *pktmp; + pktmp = PEM_read_PrivateKey(fp, NULL, cb, u); + return pkey_get_eckey(pktmp, eckey); /* will free pktmp */ +} + +#endif + +IMPLEMENT_PEM_write_const(DHparams, DH, PEM_STRING_DHPARAMS, DHparams) + + IMPLEMENT_PEM_rw(PUBKEY, EVP_PKEY, PEM_STRING_PUBLIC, PUBKEY) diff --git a/external/boringssl/crypto/pem/pem_info.c b/external/boringssl/crypto/pem/pem_info.c new file mode 100644 index 0000000000..57c87d4fc2 --- /dev/null +++ b/external/boringssl/crypto/pem/pem_info.c @@ -0,0 +1,381 @@ +/* crypto/pem/pem_info.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef OPENSSL_NO_FP_API +STACK_OF(X509_INFO) *PEM_X509_INFO_read(FILE *fp, STACK_OF(X509_INFO) *sk, + pem_password_cb *cb, void *u) +{ + BIO *b; + STACK_OF(X509_INFO) *ret; + + if ((b = BIO_new(BIO_s_file())) == NULL) { + OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB); + return (0); + } + BIO_set_fp(b, fp, BIO_NOCLOSE); + ret = PEM_X509_INFO_read_bio(b, sk, cb, u); + BIO_free(b); + return (ret); +} +#endif + +STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio(BIO *bp, STACK_OF(X509_INFO) *sk, + pem_password_cb *cb, void *u) +{ + X509_INFO *xi = NULL; + char *name = NULL, *header = NULL; + void *pp; + unsigned char *data = NULL; + const unsigned char *p; + long len, error = 0; + int ok = 0; + STACK_OF(X509_INFO) *ret = NULL; + unsigned int i, raw, ptype; + d2i_of_void *d2i = 0; + + if (sk == NULL) { + if ((ret = sk_X509_INFO_new_null()) == NULL) { + OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE); + goto err; + } + } else + ret = sk; + + if ((xi = X509_INFO_new()) == NULL) + goto err; + for (;;) { + raw = 0; + ptype = 0; + i = PEM_read_bio(bp, &name, &header, &data, &len); + if (i == 0) { + error = ERR_GET_REASON(ERR_peek_last_error()); + if (error == PEM_R_NO_START_LINE) { + ERR_clear_error(); + break; + } + goto err; + } + start: + if ((strcmp(name, PEM_STRING_X509) == 0) || + (strcmp(name, PEM_STRING_X509_OLD) == 0)) { + d2i = (D2I_OF(void)) d2i_X509; + if (xi->x509 != NULL) { + if (!sk_X509_INFO_push(ret, xi)) + goto err; + if ((xi = X509_INFO_new()) == NULL) + goto err; + goto start; + } + pp = &(xi->x509); + } else if ((strcmp(name, PEM_STRING_X509_TRUSTED) == 0)) { + d2i = (D2I_OF(void)) d2i_X509_AUX; + if (xi->x509 != NULL) { + if (!sk_X509_INFO_push(ret, xi)) + goto err; + if ((xi = X509_INFO_new()) == NULL) + goto err; + goto start; + } + pp = &(xi->x509); + } else if (strcmp(name, PEM_STRING_X509_CRL) == 0) { + d2i = (D2I_OF(void)) d2i_X509_CRL; + if (xi->crl != NULL) { + if (!sk_X509_INFO_push(ret, xi)) + goto err; + if ((xi = X509_INFO_new()) == NULL) + goto err; + goto start; + } + pp = &(xi->crl); + } else if (strcmp(name, PEM_STRING_RSA) == 0) { + d2i = (D2I_OF(void)) d2i_RSAPrivateKey; + if (xi->x_pkey != NULL) { + if (!sk_X509_INFO_push(ret, xi)) + goto err; + if ((xi = X509_INFO_new()) == NULL) + goto err; + goto start; + } + + xi->enc_data = NULL; + xi->enc_len = 0; + + xi->x_pkey = X509_PKEY_new(); + ptype = EVP_PKEY_RSA; + pp = &xi->x_pkey->dec_pkey; + if ((int)strlen(header) > 10) /* assume encrypted */ + raw = 1; + } else +#ifndef OPENSSL_NO_DSA + if (strcmp(name, PEM_STRING_DSA) == 0) { + d2i = (D2I_OF(void)) d2i_DSAPrivateKey; + if (xi->x_pkey != NULL) { + if (!sk_X509_INFO_push(ret, xi)) + goto err; + if ((xi = X509_INFO_new()) == NULL) + goto err; + goto start; + } + + xi->enc_data = NULL; + xi->enc_len = 0; + + xi->x_pkey = X509_PKEY_new(); + ptype = EVP_PKEY_DSA; + pp = &xi->x_pkey->dec_pkey; + if ((int)strlen(header) > 10) /* assume encrypted */ + raw = 1; + } else +#endif + if (strcmp(name, PEM_STRING_ECPRIVATEKEY) == 0) { + d2i = (D2I_OF(void)) d2i_ECPrivateKey; + if (xi->x_pkey != NULL) { + if (!sk_X509_INFO_push(ret, xi)) + goto err; + if ((xi = X509_INFO_new()) == NULL) + goto err; + goto start; + } + + xi->enc_data = NULL; + xi->enc_len = 0; + + xi->x_pkey = X509_PKEY_new(); + ptype = EVP_PKEY_EC; + pp = &xi->x_pkey->dec_pkey; + if ((int)strlen(header) > 10) /* assume encrypted */ + raw = 1; + } else { + d2i = NULL; + pp = NULL; + } + + if (d2i != NULL) { + if (!raw) { + EVP_CIPHER_INFO cipher; + + if (!PEM_get_EVP_CIPHER_INFO(header, &cipher)) + goto err; + if (!PEM_do_header(&cipher, data, &len, cb, u)) + goto err; + p = data; + if (ptype) { + if (!d2i_PrivateKey(ptype, pp, &p, len)) { + OPENSSL_PUT_ERROR(PEM, ERR_R_ASN1_LIB); + goto err; + } + } else if (d2i(pp, &p, len) == NULL) { + OPENSSL_PUT_ERROR(PEM, ERR_R_ASN1_LIB); + goto err; + } + } else { /* encrypted RSA data */ + if (!PEM_get_EVP_CIPHER_INFO(header, &xi->enc_cipher)) + goto err; + xi->enc_data = (char *)data; + xi->enc_len = (int)len; + data = NULL; + } + } else { + /* unknown */ + } + if (name != NULL) + OPENSSL_free(name); + if (header != NULL) + OPENSSL_free(header); + if (data != NULL) + OPENSSL_free(data); + name = NULL; + header = NULL; + data = NULL; + } + + /* + * if the last one hasn't been pushed yet and there is anything in it + * then add it to the stack ... + */ + if ((xi->x509 != NULL) || (xi->crl != NULL) || + (xi->x_pkey != NULL) || (xi->enc_data != NULL)) { + if (!sk_X509_INFO_push(ret, xi)) + goto err; + xi = NULL; + } + ok = 1; + err: + if (xi != NULL) + X509_INFO_free(xi); + if (!ok) { + for (i = 0; i < sk_X509_INFO_num(ret); i++) { + xi = sk_X509_INFO_value(ret, i); + X509_INFO_free(xi); + } + if (ret != sk) + sk_X509_INFO_free(ret); + ret = NULL; + } + + if (name != NULL) + OPENSSL_free(name); + if (header != NULL) + OPENSSL_free(header); + if (data != NULL) + OPENSSL_free(data); + return (ret); +} + +/* A TJH addition */ +int PEM_X509_INFO_write_bio(BIO *bp, X509_INFO *xi, EVP_CIPHER *enc, + unsigned char *kstr, int klen, + pem_password_cb *cb, void *u) +{ + EVP_CIPHER_CTX ctx; + int i, ret = 0; + unsigned char *data = NULL; + const char *objstr = NULL; + char buf[PEM_BUFSIZE]; + unsigned char *iv = NULL; + unsigned iv_len = 0; + + if (enc != NULL) { + iv_len = EVP_CIPHER_iv_length(enc); + objstr = OBJ_nid2sn(EVP_CIPHER_nid(enc)); + if (objstr == NULL) { + OPENSSL_PUT_ERROR(PEM, PEM_R_UNSUPPORTED_CIPHER); + goto err; + } + } + + /* + * now for the fun part ... if we have a private key then we have to be + * able to handle a not-yet-decrypted key being written out correctly ... + * if it is decrypted or it is non-encrypted then we use the base code + */ + if (xi->x_pkey != NULL) { + if ((xi->enc_data != NULL) && (xi->enc_len > 0)) { + if (enc == NULL) { + OPENSSL_PUT_ERROR(PEM, PEM_R_CIPHER_IS_NULL); + goto err; + } + + /* copy from weirdo names into more normal things */ + iv = xi->enc_cipher.iv; + data = (unsigned char *)xi->enc_data; + i = xi->enc_len; + + /* + * we take the encryption data from the internal stuff rather + * than what the user has passed us ... as we have to match + * exactly for some strange reason + */ + objstr = OBJ_nid2sn(EVP_CIPHER_nid(xi->enc_cipher.cipher)); + if (objstr == NULL) { + OPENSSL_PUT_ERROR(PEM, PEM_R_UNSUPPORTED_CIPHER); + goto err; + } + + /* create the right magic header stuff */ + assert(strlen(objstr) + 23 + 2 * iv_len + 13 <= sizeof buf); + buf[0] = '\0'; + PEM_proc_type(buf, PEM_TYPE_ENCRYPTED); + PEM_dek_info(buf, objstr, iv_len, (char *)iv); + + /* use the normal code to write things out */ + i = PEM_write_bio(bp, PEM_STRING_RSA, buf, data, i); + if (i <= 0) + goto err; + } else { + /* Add DSA/DH */ + /* normal optionally encrypted stuff */ + if (PEM_write_bio_RSAPrivateKey(bp, + xi->x_pkey->dec_pkey->pkey.rsa, + enc, kstr, klen, cb, u) <= 0) + goto err; + } + } + + /* if we have a certificate then write it out now */ + if ((xi->x509 != NULL) && (PEM_write_bio_X509(bp, xi->x509) <= 0)) + goto err; + + /* + * we are ignoring anything else that is loaded into the X509_INFO + * structure for the moment ... as I don't need it so I'm not coding it + * here and Eric can do it when this makes it into the base library --tjh + */ + + ret = 1; + + err: + OPENSSL_cleanse((char *)&ctx, sizeof(ctx)); + OPENSSL_cleanse(buf, PEM_BUFSIZE); + return (ret); +} diff --git a/external/boringssl/crypto/pem/pem_lib.c b/external/boringssl/crypto/pem/pem_lib.c new file mode 100644 index 0000000000..e53abf8611 --- /dev/null +++ b/external/boringssl/crypto/pem/pem_lib.c @@ -0,0 +1,778 @@ +/* crypto/pem/pem_lib.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MIN_LENGTH 4 + +static int load_iv(char **fromp, unsigned char *to, int num); +static int check_pem(const char *nm, const char *name); + +void PEM_proc_type(char *buf, int type) +{ + const char *str; + + if (type == PEM_TYPE_ENCRYPTED) + str = "ENCRYPTED"; + else if (type == PEM_TYPE_MIC_CLEAR) + str = "MIC-CLEAR"; + else if (type == PEM_TYPE_MIC_ONLY) + str = "MIC-ONLY"; + else + str = "BAD-TYPE"; + + BUF_strlcat(buf, "Proc-Type: 4,", PEM_BUFSIZE); + BUF_strlcat(buf, str, PEM_BUFSIZE); + BUF_strlcat(buf, "\n", PEM_BUFSIZE); +} + +void PEM_dek_info(char *buf, const char *type, int len, char *str) +{ + static const unsigned char map[17] = "0123456789ABCDEF"; + long i; + int j; + + BUF_strlcat(buf, "DEK-Info: ", PEM_BUFSIZE); + BUF_strlcat(buf, type, PEM_BUFSIZE); + BUF_strlcat(buf, ",", PEM_BUFSIZE); + j = strlen(buf); + if (j + (len * 2) + 1 > PEM_BUFSIZE) + return; + for (i = 0; i < len; i++) { + buf[j + i * 2] = map[(str[i] >> 4) & 0x0f]; + buf[j + i * 2 + 1] = map[(str[i]) & 0x0f]; + } + buf[j + i * 2] = '\n'; + buf[j + i * 2 + 1] = '\0'; +} + +#ifndef OPENSSL_NO_FP_API +void *PEM_ASN1_read(d2i_of_void *d2i, const char *name, FILE *fp, void **x, + pem_password_cb *cb, void *u) +{ + BIO *b; + void *ret; + + if ((b = BIO_new(BIO_s_file())) == NULL) { + OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB); + return (0); + } + BIO_set_fp(b, fp, BIO_NOCLOSE); + ret = PEM_ASN1_read_bio(d2i, name, b, x, cb, u); + BIO_free(b); + return (ret); +} +#endif + +static int check_pem(const char *nm, const char *name) +{ + /* Normal matching nm and name */ + if (!strcmp(nm, name)) + return 1; + + /* Make PEM_STRING_EVP_PKEY match any private key */ + + if (!strcmp(name, PEM_STRING_EVP_PKEY)) { + return !strcmp(nm, PEM_STRING_PKCS8) || + !strcmp(nm, PEM_STRING_PKCS8INF) || + !strcmp(nm, PEM_STRING_RSA) || + !strcmp(nm, PEM_STRING_EC) || + !strcmp(nm, PEM_STRING_DSA); + } + + /* Permit older strings */ + + if (!strcmp(nm, PEM_STRING_X509_OLD) && !strcmp(name, PEM_STRING_X509)) + return 1; + + if (!strcmp(nm, PEM_STRING_X509_REQ_OLD) && + !strcmp(name, PEM_STRING_X509_REQ)) + return 1; + + /* Allow normal certs to be read as trusted certs */ + if (!strcmp(nm, PEM_STRING_X509) && + !strcmp(name, PEM_STRING_X509_TRUSTED)) + return 1; + + if (!strcmp(nm, PEM_STRING_X509_OLD) && + !strcmp(name, PEM_STRING_X509_TRUSTED)) + return 1; + + /* Some CAs use PKCS#7 with CERTIFICATE headers */ + if (!strcmp(nm, PEM_STRING_X509) && !strcmp(name, PEM_STRING_PKCS7)) + return 1; + + if (!strcmp(nm, PEM_STRING_PKCS7_SIGNED) && + !strcmp(name, PEM_STRING_PKCS7)) + return 1; + +#ifndef OPENSSL_NO_CMS + if (!strcmp(nm, PEM_STRING_X509) && !strcmp(name, PEM_STRING_CMS)) + return 1; + /* Allow CMS to be read from PKCS#7 headers */ + if (!strcmp(nm, PEM_STRING_PKCS7) && !strcmp(name, PEM_STRING_CMS)) + return 1; +#endif + + return 0; +} + +int PEM_bytes_read_bio(unsigned char **pdata, long *plen, char **pnm, + const char *name, BIO *bp, pem_password_cb *cb, + void *u) +{ + EVP_CIPHER_INFO cipher; + char *nm = NULL, *header = NULL; + unsigned char *data = NULL; + long len; + int ret = 0; + + for (;;) { + if (!PEM_read_bio(bp, &nm, &header, &data, &len)) { + if (ERR_GET_REASON(ERR_peek_error()) == PEM_R_NO_START_LINE) + ERR_add_error_data(2, "Expecting: ", name); + return 0; + } + if (check_pem(nm, name)) + break; + OPENSSL_free(nm); + OPENSSL_free(header); + OPENSSL_free(data); + } + if (!PEM_get_EVP_CIPHER_INFO(header, &cipher)) + goto err; + if (!PEM_do_header(&cipher, data, &len, cb, u)) + goto err; + + *pdata = data; + *plen = len; + + if (pnm) + *pnm = nm; + + ret = 1; + + err: + if (!ret || !pnm) + OPENSSL_free(nm); + OPENSSL_free(header); + if (!ret) + OPENSSL_free(data); + return ret; +} + +#ifndef OPENSSL_NO_FP_API +int PEM_ASN1_write(i2d_of_void *i2d, const char *name, FILE *fp, + void *x, const EVP_CIPHER *enc, unsigned char *kstr, + int klen, pem_password_cb *callback, void *u) +{ + BIO *b; + int ret; + + if ((b = BIO_new(BIO_s_file())) == NULL) { + OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB); + return (0); + } + BIO_set_fp(b, fp, BIO_NOCLOSE); + ret = PEM_ASN1_write_bio(i2d, name, b, x, enc, kstr, klen, callback, u); + BIO_free(b); + return (ret); +} +#endif + +int PEM_ASN1_write_bio(i2d_of_void *i2d, const char *name, BIO *bp, + void *x, const EVP_CIPHER *enc, unsigned char *kstr, + int klen, pem_password_cb *callback, void *u) +{ + EVP_CIPHER_CTX ctx; + int dsize = 0, i, j, ret = 0; + unsigned char *p, *data = NULL; + const char *objstr = NULL; + char buf[PEM_BUFSIZE]; + unsigned char key[EVP_MAX_KEY_LENGTH]; + unsigned char iv[EVP_MAX_IV_LENGTH]; + + if (enc != NULL) { + objstr = OBJ_nid2sn(EVP_CIPHER_nid(enc)); + if (objstr == NULL || EVP_CIPHER_iv_length(enc) == 0) { + OPENSSL_PUT_ERROR(PEM, PEM_R_UNSUPPORTED_CIPHER); + goto err; + } + } + + if ((dsize = i2d(x, NULL)) < 0) { + OPENSSL_PUT_ERROR(PEM, ERR_R_ASN1_LIB); + dsize = 0; + goto err; + } + /* dzise + 8 bytes are needed */ + /* actually it needs the cipher block size extra... */ + data = (unsigned char *)OPENSSL_malloc((unsigned int)dsize + 20); + if (data == NULL) { + OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE); + goto err; + } + p = data; + i = i2d(x, &p); + + if (enc != NULL) { + const unsigned iv_len = EVP_CIPHER_iv_length(enc); + + if (kstr == NULL) { + klen = 0; + if (!callback) + callback = PEM_def_callback; + klen = (*callback) (buf, PEM_BUFSIZE, 1, u); + if (klen <= 0) { + OPENSSL_PUT_ERROR(PEM, PEM_R_READ_KEY); + goto err; + } + kstr = (unsigned char *)buf; + } + assert(iv_len <= (int)sizeof(iv)); + if (!RAND_bytes(iv, iv_len)) /* Generate a salt */ + goto err; + /* + * The 'iv' is used as the iv and as a salt. It is NOT taken from + * the BytesToKey function + */ + if (!EVP_BytesToKey(enc, EVP_md5(), iv, kstr, klen, 1, key, NULL)) + goto err; + + if (kstr == (unsigned char *)buf) + OPENSSL_cleanse(buf, PEM_BUFSIZE); + + assert(strlen(objstr) + 23 + 2 * iv_len + 13 <= sizeof buf); + + buf[0] = '\0'; + PEM_proc_type(buf, PEM_TYPE_ENCRYPTED); + PEM_dek_info(buf, objstr, iv_len, (char *)iv); + /* k=strlen(buf); */ + + EVP_CIPHER_CTX_init(&ctx); + ret = 1; + if (!EVP_EncryptInit_ex(&ctx, enc, NULL, key, iv) + || !EVP_EncryptUpdate(&ctx, data, &j, data, i) + || !EVP_EncryptFinal_ex(&ctx, &(data[j]), &i)) + ret = 0; + else + i += j; + EVP_CIPHER_CTX_cleanup(&ctx); + if (ret == 0) + goto err; + } else { + ret = 1; + buf[0] = '\0'; + } + i = PEM_write_bio(bp, name, buf, data, i); + if (i <= 0) + ret = 0; + err: + OPENSSL_cleanse(key, sizeof(key)); + OPENSSL_cleanse(iv, sizeof(iv)); + OPENSSL_cleanse((char *)&ctx, sizeof(ctx)); + OPENSSL_cleanse(buf, PEM_BUFSIZE); + if (data != NULL) { + OPENSSL_cleanse(data, (unsigned int)dsize); + OPENSSL_free(data); + } + return (ret); +} + +int PEM_do_header(EVP_CIPHER_INFO *cipher, unsigned char *data, long *plen, + pem_password_cb *callback, void *u) +{ + int i = 0, j, o, klen; + long len; + EVP_CIPHER_CTX ctx; + unsigned char key[EVP_MAX_KEY_LENGTH]; + char buf[PEM_BUFSIZE]; + + len = *plen; + + if (cipher->cipher == NULL) + return (1); + + klen = 0; + if (!callback) + callback = PEM_def_callback; + klen = callback(buf, PEM_BUFSIZE, 0, u); + if (klen <= 0) { + OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_PASSWORD_READ); + return (0); + } + + if (!EVP_BytesToKey(cipher->cipher, EVP_md5(), &(cipher->iv[0]), + (unsigned char *)buf, klen, 1, key, NULL)) + return 0; + + j = (int)len; + EVP_CIPHER_CTX_init(&ctx); + o = EVP_DecryptInit_ex(&ctx, cipher->cipher, NULL, key, &(cipher->iv[0])); + if (o) + o = EVP_DecryptUpdate(&ctx, data, &i, data, j); + if (o) + o = EVP_DecryptFinal_ex(&ctx, &(data[i]), &j); + EVP_CIPHER_CTX_cleanup(&ctx); + OPENSSL_cleanse((char *)buf, sizeof(buf)); + OPENSSL_cleanse((char *)key, sizeof(key)); + if (!o) { + OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_DECRYPT); + return (0); + } + j += i; + *plen = j; + return (1); +} + +static const EVP_CIPHER *cipher_by_name(const char *name) +{ + /* This is similar to the (deprecated) function |EVP_get_cipherbyname|. */ + if (0 == strcmp(name, SN_rc4)) { + return EVP_rc4(); + } else if (0 == strcmp(name, SN_des_cbc)) { + return EVP_des_cbc(); + } else if (0 == strcmp(name, SN_des_ede3_cbc)) { + return EVP_des_ede3_cbc(); + } else if (0 == strcmp(name, SN_aes_128_cbc)) { + return EVP_aes_128_cbc(); + } else if (0 == strcmp(name, SN_aes_192_cbc)) { + return EVP_aes_192_cbc(); + } else if (0 == strcmp(name, SN_aes_256_cbc)) { + return EVP_aes_256_cbc(); + } else { + return NULL; + } +} + +int PEM_get_EVP_CIPHER_INFO(char *header, EVP_CIPHER_INFO *cipher) +{ + const EVP_CIPHER *enc = NULL; + char *p, c; + char **header_pp = &header; + + cipher->cipher = NULL; + if ((header == NULL) || (*header == '\0') || (*header == '\n')) + return (1); + if (strncmp(header, "Proc-Type: ", 11) != 0) { + OPENSSL_PUT_ERROR(PEM, PEM_R_NOT_PROC_TYPE); + return (0); + } + header += 11; + if (*header != '4') + return (0); + header++; + if (*header != ',') + return (0); + header++; + if (strncmp(header, "ENCRYPTED", 9) != 0) { + OPENSSL_PUT_ERROR(PEM, PEM_R_NOT_ENCRYPTED); + return (0); + } + for (; (*header != '\n') && (*header != '\0'); header++) ; + if (*header == '\0') { + OPENSSL_PUT_ERROR(PEM, PEM_R_SHORT_HEADER); + return (0); + } + header++; + if (strncmp(header, "DEK-Info: ", 10) != 0) { + OPENSSL_PUT_ERROR(PEM, PEM_R_NOT_DEK_INFO); + return (0); + } + header += 10; + + p = header; + for (;;) { + c = *header; + if (!(((c >= 'A') && (c <= 'Z')) || (c == '-') || + ((c >= '0') && (c <= '9')))) + break; + header++; + } + *header = '\0'; + cipher->cipher = enc = cipher_by_name(p); + *header = c; + header++; + + if (enc == NULL) { + OPENSSL_PUT_ERROR(PEM, PEM_R_UNSUPPORTED_ENCRYPTION); + return (0); + } + if (!load_iv(header_pp, &(cipher->iv[0]), EVP_CIPHER_iv_length(enc))) + return (0); + + return (1); +} + +static int load_iv(char **fromp, unsigned char *to, int num) +{ + int v, i; + char *from; + + from = *fromp; + for (i = 0; i < num; i++) + to[i] = 0; + num *= 2; + for (i = 0; i < num; i++) { + if ((*from >= '0') && (*from <= '9')) + v = *from - '0'; + else if ((*from >= 'A') && (*from <= 'F')) + v = *from - 'A' + 10; + else if ((*from >= 'a') && (*from <= 'f')) + v = *from - 'a' + 10; + else { + OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_IV_CHARS); + return (0); + } + from++; + to[i / 2] |= v << (long)((!(i & 1)) * 4); + } + + *fromp = from; + return (1); +} + +#ifndef OPENSSL_NO_FP_API +int PEM_write(FILE *fp, const char *name, const char *header, + const unsigned char *data, long len) +{ + BIO *b; + int ret; + + if ((b = BIO_new(BIO_s_file())) == NULL) { + OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB); + return (0); + } + BIO_set_fp(b, fp, BIO_NOCLOSE); + ret = PEM_write_bio(b, name, header, data, len); + BIO_free(b); + return (ret); +} +#endif + +int PEM_write_bio(BIO *bp, const char *name, const char *header, + const unsigned char *data, long len) +{ + int nlen, n, i, j, outl; + unsigned char *buf = NULL; + EVP_ENCODE_CTX ctx; + int reason = ERR_R_BUF_LIB; + + EVP_EncodeInit(&ctx); + nlen = strlen(name); + + if ((BIO_write(bp, "-----BEGIN ", 11) != 11) || + (BIO_write(bp, name, nlen) != nlen) || + (BIO_write(bp, "-----\n", 6) != 6)) + goto err; + + i = strlen(header); + if (i > 0) { + if ((BIO_write(bp, header, i) != i) || (BIO_write(bp, "\n", 1) != 1)) + goto err; + } + + buf = OPENSSL_malloc(PEM_BUFSIZE * 8); + if (buf == NULL) { + reason = ERR_R_MALLOC_FAILURE; + goto err; + } + + i = j = 0; + while (len > 0) { + n = (int)((len > (PEM_BUFSIZE * 5)) ? (PEM_BUFSIZE * 5) : len); + EVP_EncodeUpdate(&ctx, buf, &outl, &(data[j]), n); + if ((outl) && (BIO_write(bp, (char *)buf, outl) != outl)) + goto err; + i += outl; + len -= n; + j += n; + } + EVP_EncodeFinal(&ctx, buf, &outl); + if ((outl > 0) && (BIO_write(bp, (char *)buf, outl) != outl)) + goto err; + OPENSSL_cleanse(buf, PEM_BUFSIZE * 8); + OPENSSL_free(buf); + buf = NULL; + if ((BIO_write(bp, "-----END ", 9) != 9) || + (BIO_write(bp, name, nlen) != nlen) || + (BIO_write(bp, "-----\n", 6) != 6)) + goto err; + return (i + outl); + err: + if (buf) { + OPENSSL_cleanse(buf, PEM_BUFSIZE * 8); + OPENSSL_free(buf); + } + OPENSSL_PUT_ERROR(PEM, reason); + return (0); +} + +#ifndef OPENSSL_NO_FP_API +int PEM_read(FILE *fp, char **name, char **header, unsigned char **data, + long *len) +{ + BIO *b; + int ret; + + if ((b = BIO_new(BIO_s_file())) == NULL) { + OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB); + return (0); + } + BIO_set_fp(b, fp, BIO_NOCLOSE); + ret = PEM_read_bio(b, name, header, data, len); + BIO_free(b); + return (ret); +} +#endif + +int PEM_read_bio(BIO *bp, char **name, char **header, unsigned char **data, + long *len) +{ + EVP_ENCODE_CTX ctx; + int end = 0, i, k, bl = 0, hl = 0, nohead = 0; + char buf[256]; + BUF_MEM *nameB; + BUF_MEM *headerB; + BUF_MEM *dataB, *tmpB; + + nameB = BUF_MEM_new(); + headerB = BUF_MEM_new(); + dataB = BUF_MEM_new(); + if ((nameB == NULL) || (headerB == NULL) || (dataB == NULL)) { + BUF_MEM_free(nameB); + BUF_MEM_free(headerB); + BUF_MEM_free(dataB); + OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE); + return (0); + } + + buf[254] = '\0'; + for (;;) { + i = BIO_gets(bp, buf, 254); + + if (i <= 0) { + OPENSSL_PUT_ERROR(PEM, PEM_R_NO_START_LINE); + goto err; + } + + while ((i >= 0) && (buf[i] <= ' ')) + i--; + buf[++i] = '\n'; + buf[++i] = '\0'; + + if (strncmp(buf, "-----BEGIN ", 11) == 0) { + i = strlen(&(buf[11])); + + if (strncmp(&(buf[11 + i - 6]), "-----\n", 6) != 0) + continue; + if (!BUF_MEM_grow(nameB, i + 9)) { + OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE); + goto err; + } + memcpy(nameB->data, &(buf[11]), i - 6); + nameB->data[i - 6] = '\0'; + break; + } + } + hl = 0; + if (!BUF_MEM_grow(headerB, 256)) { + OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE); + goto err; + } + headerB->data[0] = '\0'; + for (;;) { + i = BIO_gets(bp, buf, 254); + if (i <= 0) + break; + + while ((i >= 0) && (buf[i] <= ' ')) + i--; + buf[++i] = '\n'; + buf[++i] = '\0'; + + if (buf[0] == '\n') + break; + if (!BUF_MEM_grow(headerB, hl + i + 9)) { + OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE); + goto err; + } + if (strncmp(buf, "-----END ", 9) == 0) { + nohead = 1; + break; + } + memcpy(&(headerB->data[hl]), buf, i); + headerB->data[hl + i] = '\0'; + hl += i; + } + + bl = 0; + if (!BUF_MEM_grow(dataB, 1024)) { + OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE); + goto err; + } + dataB->data[0] = '\0'; + if (!nohead) { + for (;;) { + i = BIO_gets(bp, buf, 254); + if (i <= 0) + break; + + while ((i >= 0) && (buf[i] <= ' ')) + i--; + buf[++i] = '\n'; + buf[++i] = '\0'; + + if (i != 65) + end = 1; + if (strncmp(buf, "-----END ", 9) == 0) + break; + if (i > 65) + break; + if (!BUF_MEM_grow_clean(dataB, i + bl + 9)) { + OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE); + goto err; + } + memcpy(&(dataB->data[bl]), buf, i); + dataB->data[bl + i] = '\0'; + bl += i; + if (end) { + buf[0] = '\0'; + i = BIO_gets(bp, buf, 254); + if (i <= 0) + break; + + while ((i >= 0) && (buf[i] <= ' ')) + i--; + buf[++i] = '\n'; + buf[++i] = '\0'; + + break; + } + } + } else { + tmpB = headerB; + headerB = dataB; + dataB = tmpB; + bl = hl; + } + i = strlen(nameB->data); + if ((strncmp(buf, "-----END ", 9) != 0) || + (strncmp(nameB->data, &(buf[9]), i) != 0) || + (strncmp(&(buf[9 + i]), "-----\n", 6) != 0)) { + OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_END_LINE); + goto err; + } + + EVP_DecodeInit(&ctx); + i = EVP_DecodeUpdate(&ctx, + (unsigned char *)dataB->data, &bl, + (unsigned char *)dataB->data, bl); + if (i < 0) { + OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_BASE64_DECODE); + goto err; + } + i = EVP_DecodeFinal(&ctx, (unsigned char *)&(dataB->data[bl]), &k); + if (i < 0) { + OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_BASE64_DECODE); + goto err; + } + bl += k; + + if (bl == 0) + goto err; + *name = nameB->data; + *header = headerB->data; + *data = (unsigned char *)dataB->data; + *len = bl; + OPENSSL_free(nameB); + OPENSSL_free(headerB); + OPENSSL_free(dataB); + return (1); + err: + BUF_MEM_free(nameB); + BUF_MEM_free(headerB); + BUF_MEM_free(dataB); + return (0); +} + +int PEM_def_callback(char *buf, int size, int rwflag, void *userdata) +{ + if (!buf || !userdata) { + return 0; + } + size_t len = strlen((char *)userdata); + if (len >= (size_t)size) { + return 0; + } + strcpy(buf, (char *)userdata); + return len; +} diff --git a/external/boringssl/crypto/pem/pem_oth.c b/external/boringssl/crypto/pem/pem_oth.c new file mode 100644 index 0000000000..8530c56756 --- /dev/null +++ b/external/boringssl/crypto/pem/pem_oth.c @@ -0,0 +1,88 @@ +/* crypto/pem/pem_oth.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +/* Handle 'other' PEMs: not private keys */ + +void *PEM_ASN1_read_bio(d2i_of_void *d2i, const char *name, BIO *bp, void **x, + pem_password_cb *cb, void *u) +{ + const unsigned char *p = NULL; + unsigned char *data = NULL; + long len; + char *ret = NULL; + + if (!PEM_bytes_read_bio(&data, &len, NULL, name, bp, cb, u)) + return NULL; + p = data; + ret = d2i(x, &p, len); + if (ret == NULL) + OPENSSL_PUT_ERROR(PEM, ERR_R_ASN1_LIB); + OPENSSL_free(data); + return ret; +} diff --git a/external/boringssl/crypto/pem/pem_pk8.c b/external/boringssl/crypto/pem/pem_pk8.c new file mode 100644 index 0000000000..550661d642 --- /dev/null +++ b/external/boringssl/crypto/pem/pem_pk8.c @@ -0,0 +1,257 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +static int do_pk8pkey(BIO *bp, EVP_PKEY *x, int isder, + int nid, const EVP_CIPHER *enc, + char *kstr, int klen, pem_password_cb *cb, void *u); +static int do_pk8pkey_fp(FILE *bp, EVP_PKEY *x, int isder, + int nid, const EVP_CIPHER *enc, + char *kstr, int klen, pem_password_cb *cb, void *u); + +/* + * These functions write a private key in PKCS#8 format: it is a "drop in" + * replacement for PEM_write_bio_PrivateKey() and friends. As usual if 'enc' + * is NULL then it uses the unencrypted private key form. The 'nid' versions + * uses PKCS#5 v1.5 PBE algorithms whereas the others use PKCS#5 v2.0. + */ + +int PEM_write_bio_PKCS8PrivateKey_nid(BIO *bp, EVP_PKEY *x, int nid, + char *kstr, int klen, + pem_password_cb *cb, void *u) +{ + return do_pk8pkey(bp, x, 0, nid, NULL, kstr, klen, cb, u); +} + +int PEM_write_bio_PKCS8PrivateKey(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc, + char *kstr, int klen, + pem_password_cb *cb, void *u) +{ + return do_pk8pkey(bp, x, 0, -1, enc, kstr, klen, cb, u); +} + +int i2d_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc, + char *kstr, int klen, + pem_password_cb *cb, void *u) +{ + return do_pk8pkey(bp, x, 1, -1, enc, kstr, klen, cb, u); +} + +int i2d_PKCS8PrivateKey_nid_bio(BIO *bp, EVP_PKEY *x, int nid, + char *kstr, int klen, + pem_password_cb *cb, void *u) +{ + return do_pk8pkey(bp, x, 1, nid, NULL, kstr, klen, cb, u); +} + +static int do_pk8pkey(BIO *bp, EVP_PKEY *x, int isder, int nid, + const EVP_CIPHER *enc, char *kstr, int klen, + pem_password_cb *cb, void *u) +{ + X509_SIG *p8; + PKCS8_PRIV_KEY_INFO *p8inf; + char buf[PEM_BUFSIZE]; + int ret; + if (!(p8inf = EVP_PKEY2PKCS8(x))) { + OPENSSL_PUT_ERROR(PEM, PEM_R_ERROR_CONVERTING_PRIVATE_KEY); + return 0; + } + if (enc || (nid != -1)) { + if (!kstr) { + klen = 0; + if (!cb) + cb = PEM_def_callback; + klen = cb(buf, PEM_BUFSIZE, 1, u); + if (klen <= 0) { + OPENSSL_PUT_ERROR(PEM, PEM_R_READ_KEY); + PKCS8_PRIV_KEY_INFO_free(p8inf); + return 0; + } + + kstr = buf; + } + p8 = PKCS8_encrypt(nid, enc, kstr, klen, NULL, 0, 0, p8inf); + if (kstr == buf) + OPENSSL_cleanse(buf, klen); + PKCS8_PRIV_KEY_INFO_free(p8inf); + if (isder) + ret = i2d_PKCS8_bio(bp, p8); + else + ret = PEM_write_bio_PKCS8(bp, p8); + X509_SIG_free(p8); + return ret; + } else { + if (isder) + ret = i2d_PKCS8_PRIV_KEY_INFO_bio(bp, p8inf); + else + ret = PEM_write_bio_PKCS8_PRIV_KEY_INFO(bp, p8inf); + PKCS8_PRIV_KEY_INFO_free(p8inf); + return ret; + } +} + +EVP_PKEY *d2i_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY **x, pem_password_cb *cb, + void *u) +{ + PKCS8_PRIV_KEY_INFO *p8inf = NULL; + X509_SIG *p8 = NULL; + int klen; + EVP_PKEY *ret; + char psbuf[PEM_BUFSIZE]; + p8 = d2i_PKCS8_bio(bp, NULL); + if (!p8) + return NULL; + + klen = 0; + if (!cb) + cb = PEM_def_callback; + klen = cb(psbuf, PEM_BUFSIZE, 0, u); + if (klen <= 0) { + OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_PASSWORD_READ); + X509_SIG_free(p8); + return NULL; + } + p8inf = PKCS8_decrypt(p8, psbuf, klen); + X509_SIG_free(p8); + if (!p8inf) + return NULL; + ret = EVP_PKCS82PKEY(p8inf); + PKCS8_PRIV_KEY_INFO_free(p8inf); + if (!ret) + return NULL; + if (x) { + if (*x) + EVP_PKEY_free(*x); + *x = ret; + } + return ret; +} + +#ifndef OPENSSL_NO_FP_API + +int i2d_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc, + char *kstr, int klen, pem_password_cb *cb, void *u) +{ + return do_pk8pkey_fp(fp, x, 1, -1, enc, kstr, klen, cb, u); +} + +int i2d_PKCS8PrivateKey_nid_fp(FILE *fp, EVP_PKEY *x, int nid, + char *kstr, int klen, + pem_password_cb *cb, void *u) +{ + return do_pk8pkey_fp(fp, x, 1, nid, NULL, kstr, klen, cb, u); +} + +int PEM_write_PKCS8PrivateKey_nid(FILE *fp, EVP_PKEY *x, int nid, + char *kstr, int klen, + pem_password_cb *cb, void *u) +{ + return do_pk8pkey_fp(fp, x, 0, nid, NULL, kstr, klen, cb, u); +} + +int PEM_write_PKCS8PrivateKey(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc, + char *kstr, int klen, pem_password_cb *cb, + void *u) +{ + return do_pk8pkey_fp(fp, x, 0, -1, enc, kstr, klen, cb, u); +} + +static int do_pk8pkey_fp(FILE *fp, EVP_PKEY *x, int isder, int nid, + const EVP_CIPHER *enc, char *kstr, int klen, + pem_password_cb *cb, void *u) +{ + BIO *bp; + int ret; + if (!(bp = BIO_new_fp(fp, BIO_NOCLOSE))) { + OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB); + return (0); + } + ret = do_pk8pkey(bp, x, isder, nid, enc, kstr, klen, cb, u); + BIO_free(bp); + return ret; +} + +EVP_PKEY *d2i_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY **x, pem_password_cb *cb, + void *u) +{ + BIO *bp; + EVP_PKEY *ret; + if (!(bp = BIO_new_fp(fp, BIO_NOCLOSE))) { + OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB); + return NULL; + } + ret = d2i_PKCS8PrivateKey_bio(bp, x, cb, u); + BIO_free(bp); + return ret; +} + +#endif + +IMPLEMENT_PEM_rw(PKCS8, X509_SIG, PEM_STRING_PKCS8, X509_SIG) + + +IMPLEMENT_PEM_rw(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO, PEM_STRING_PKCS8INF, + PKCS8_PRIV_KEY_INFO) diff --git a/external/boringssl/crypto/pem/pem_pkey.c b/external/boringssl/crypto/pem/pem_pkey.c new file mode 100644 index 0000000000..058c031125 --- /dev/null +++ b/external/boringssl/crypto/pem/pem_pkey.c @@ -0,0 +1,227 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +EVP_PKEY *PEM_read_bio_PrivateKey(BIO *bp, EVP_PKEY **x, pem_password_cb *cb, + void *u) +{ + char *nm = NULL; + const unsigned char *p = NULL; + unsigned char *data = NULL; + long len; + EVP_PKEY *ret = NULL; + + if (!PEM_bytes_read_bio(&data, &len, &nm, PEM_STRING_EVP_PKEY, bp, cb, u)) + return NULL; + p = data; + + if (strcmp(nm, PEM_STRING_PKCS8INF) == 0) { + PKCS8_PRIV_KEY_INFO *p8inf; + p8inf = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, len); + if (!p8inf) + goto p8err; + ret = EVP_PKCS82PKEY(p8inf); + if (x) { + if (*x) + EVP_PKEY_free((EVP_PKEY *)*x); + *x = ret; + } + PKCS8_PRIV_KEY_INFO_free(p8inf); + } else if (strcmp(nm, PEM_STRING_PKCS8) == 0) { + PKCS8_PRIV_KEY_INFO *p8inf; + X509_SIG *p8; + int klen; + char psbuf[PEM_BUFSIZE]; + p8 = d2i_X509_SIG(NULL, &p, len); + if (!p8) + goto p8err; + + klen = 0; + if (!cb) + cb = PEM_def_callback; + klen = cb(psbuf, PEM_BUFSIZE, 0, u); + if (klen <= 0) { + OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_PASSWORD_READ); + X509_SIG_free(p8); + goto err; + } + p8inf = PKCS8_decrypt(p8, psbuf, klen); + X509_SIG_free(p8); + if (!p8inf) + goto p8err; + ret = EVP_PKCS82PKEY(p8inf); + if (x) { + if (*x) + EVP_PKEY_free((EVP_PKEY *)*x); + *x = ret; + } + PKCS8_PRIV_KEY_INFO_free(p8inf); + } else if (strcmp(nm, PEM_STRING_RSA) == 0) { + /* TODO(davidben): d2i_PrivateKey parses PKCS#8 along with the + * standalone format. This and the cases below probably should not + * accept PKCS#8. */ + ret = d2i_PrivateKey(EVP_PKEY_RSA, x, &p, len); + } else if (strcmp(nm, PEM_STRING_EC) == 0) { + ret = d2i_PrivateKey(EVP_PKEY_EC, x, &p, len); + } else if (strcmp(nm, PEM_STRING_DSA) == 0) { + ret = d2i_PrivateKey(EVP_PKEY_DSA, x, &p, len); + } + p8err: + if (ret == NULL) + OPENSSL_PUT_ERROR(PEM, ERR_R_ASN1_LIB); + + err: + OPENSSL_free(nm); + OPENSSL_cleanse(data, len); + OPENSSL_free(data); + return (ret); +} + +int PEM_write_bio_PrivateKey(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc, + unsigned char *kstr, int klen, + pem_password_cb *cb, void *u) +{ + return PEM_write_bio_PKCS8PrivateKey(bp, x, enc, (char *)kstr, klen, cb, u); +} + +#ifndef OPENSSL_NO_FP_API +EVP_PKEY *PEM_read_PrivateKey(FILE *fp, EVP_PKEY **x, pem_password_cb *cb, + void *u) +{ + BIO *b; + EVP_PKEY *ret; + + if ((b = BIO_new(BIO_s_file())) == NULL) { + OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB); + return (0); + } + BIO_set_fp(b, fp, BIO_NOCLOSE); + ret = PEM_read_bio_PrivateKey(b, x, cb, u); + BIO_free(b); + return (ret); +} + +int PEM_write_PrivateKey(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc, + unsigned char *kstr, int klen, + pem_password_cb *cb, void *u) +{ + BIO *b; + int ret; + + if ((b = BIO_new_fp(fp, BIO_NOCLOSE)) == NULL) { + OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB); + return 0; + } + ret = PEM_write_bio_PrivateKey(b, x, enc, kstr, klen, cb, u); + BIO_free(b); + return ret; +} + +#endif + +/* Transparently read in PKCS#3 or X9.42 DH parameters */ + +DH *PEM_read_bio_DHparams(BIO *bp, DH **x, pem_password_cb *cb, void *u) +{ + char *nm = NULL; + const unsigned char *p = NULL; + unsigned char *data = NULL; + long len; + DH *ret = NULL; + + if (!PEM_bytes_read_bio(&data, &len, &nm, PEM_STRING_DHPARAMS, bp, cb, u)) + return NULL; + p = data; + + ret = d2i_DHparams(x, &p, len); + + if (ret == NULL) + OPENSSL_PUT_ERROR(PEM, ERR_R_ASN1_LIB); + OPENSSL_free(nm); + OPENSSL_free(data); + return ret; +} + +#ifndef OPENSSL_NO_FP_API +DH *PEM_read_DHparams(FILE *fp, DH **x, pem_password_cb *cb, void *u) +{ + BIO *b; + DH *ret; + + if ((b = BIO_new(BIO_s_file())) == NULL) { + OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB); + return (0); + } + BIO_set_fp(b, fp, BIO_NOCLOSE); + ret = PEM_read_bio_DHparams(b, x, cb, u); + BIO_free(b); + return (ret); +} +#endif diff --git a/external/boringssl/crypto/pem/pem_x509.c b/external/boringssl/crypto/pem/pem_x509.c new file mode 100644 index 0000000000..97f814dba0 --- /dev/null +++ b/external/boringssl/crypto/pem/pem_x509.c @@ -0,0 +1,65 @@ +/* pem_x509.c */ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project + * 2001. + */ +/* ==================================================================== + * Copyright (c) 2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include +#include +#include + +IMPLEMENT_PEM_rw(X509, X509, PEM_STRING_X509, X509) diff --git a/external/boringssl/crypto/pem/pem_xaux.c b/external/boringssl/crypto/pem/pem_xaux.c new file mode 100644 index 0000000000..386dd60d76 --- /dev/null +++ b/external/boringssl/crypto/pem/pem_xaux.c @@ -0,0 +1,67 @@ +/* pem_xaux.c */ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project + * 2001. + */ +/* ==================================================================== + * Copyright (c) 2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include +#include +#include + +IMPLEMENT_PEM_rw(X509_AUX, X509, PEM_STRING_X509_TRUSTED, X509_AUX) +IMPLEMENT_PEM_rw(X509_CERT_PAIR, X509_CERT_PAIR, PEM_STRING_X509_PAIR, + X509_CERT_PAIR) diff --git a/external/boringssl/crypto/perlasm/arm-xlate.pl b/external/boringssl/crypto/perlasm/arm-xlate.pl new file mode 100755 index 0000000000..6e9b019987 --- /dev/null +++ b/external/boringssl/crypto/perlasm/arm-xlate.pl @@ -0,0 +1,172 @@ +#!/usr/bin/env perl + +# ARM assembler distiller by . + +my $flavour = shift; +my $output = shift; +open STDOUT,">$output" || die "can't open $output: $!"; + +$flavour = "linux32" if (!$flavour or $flavour eq "void"); + +my %GLOBALS; +my $dotinlocallabels=($flavour=~/linux/)?1:0; + +################################################################ +# directives which need special treatment on different platforms +################################################################ +my $arch = sub { + if ($flavour =~ /linux/) { ".arch\t".join(',',@_); } + else { ""; } +}; +my $fpu = sub { + if ($flavour =~ /linux/) { ".fpu\t".join(',',@_); } + else { ""; } +}; +my $hidden = sub { + if ($flavour =~ /ios/) { ".private_extern\t".join(',',@_); } + else { ".hidden\t".join(',',@_); } +}; +my $comm = sub { + my @args = split(/,\s*/,shift); + my $name = @args[0]; + my $global = \$GLOBALS{$name}; + my $ret; + + if ($flavour =~ /ios32/) { + $ret = ".comm\t_$name,@args[1]\n"; + $ret .= ".non_lazy_symbol_pointer\n"; + $ret .= "$name:\n"; + $ret .= ".indirect_symbol\t_$name\n"; + $ret .= ".long\t0"; + $name = "_$name"; + } else { $ret = ".comm\t".join(',',@args); } + + $$global = $name; + $ret; +}; +my $globl = sub { + my $name = shift; + my $global = \$GLOBALS{$name}; + my $ret; + + SWITCH: for ($flavour) { + /ios/ && do { $name = "_$name"; + last; + }; + } + + $ret = ".globl $name\n"; + # All symbols in assembly files are hidden. + $ret .= &$hidden($name); + $$global = $name; + $ret; +}; +my $global = $globl; +my $extern = sub { + &$globl(@_); + return; # return nothing +}; +my $type = sub { + if ($flavour =~ /linux/) { ".type\t".join(',',@_); } + else { ""; } +}; +my $size = sub { + if ($flavour =~ /linux/) { ".size\t".join(',',@_); } + else { ""; } +}; +my $inst = sub { + if ($flavour =~ /linux/) { ".inst\t".join(',',@_); } + else { ".long\t".join(',',@_); } +}; +my $asciz = sub { + my $line = join(",",@_); + if ($line =~ /^"(.*)"$/) + { ".byte " . join(",",unpack("C*",$1),0) . "\n.align 2"; } + else + { ""; } +}; + +sub range { + my ($r,$sfx,$start,$end) = @_; + + join(",",map("$r$_$sfx",($start..$end))); +} + +sub expand_line { + my $line = shift; + my @ret = (); + + pos($line)=0; + + while ($line =~ m/\G[^@\/\{\"]*/g) { + if ($line =~ m/\G(@|\/\/|$)/gc) { + last; + } + elsif ($line =~ m/\G\{/gc) { + my $saved_pos = pos($line); + $line =~ s/\G([rdqv])([0-9]+)([^\-]*)\-\1([0-9]+)\3/range($1,$3,$2,$4)/e; + pos($line) = $saved_pos; + $line =~ m/\G[^\}]*\}/g; + } + elsif ($line =~ m/\G\"/gc) { + $line =~ m/\G[^\"]*\"/g; + } + } + + $line =~ s/\b(\w+)/$GLOBALS{$1} or $1/ge; + + return $line; +} + +print "#if defined(__arm__)\n" if ($flavour eq "linux32"); +print "#if defined(__aarch64__)\n" if ($flavour eq "linux64"); + +while($line=<>) { + + if ($line =~ m/^\s*(#|@|\/\/)/) { print $line; next; } + + $line =~ s|/\*.*\*/||; # get rid of C-style comments... + $line =~ s|^\s+||; # ... and skip white spaces in beginning... + $line =~ s|\s+$||; # ... and at the end + + { + $line =~ s|[\b\.]L(\w{2,})|L$1|g; # common denominator for Locallabel + $line =~ s|\bL(\w{2,})|\.L$1|g if ($dotinlocallabels); + } + + { + $line =~ s|(^[\.\w]+)\:\s*||; + my $label = $1; + if ($label) { + printf "%s:",($GLOBALS{$label} or $label); + } + } + + if ($line !~ m/^[#@]/) { + $line =~ s|^\s*(\.?)(\S+)\s*||; + my $c = $1; $c = "\t" if ($c eq ""); + my $mnemonic = $2; + my $opcode; + if ($mnemonic =~ m/([^\.]+)\.([^\.]+)/) { + $opcode = eval("\$$1_$2"); + } else { + $opcode = eval("\$$mnemonic"); + } + + my $arg=expand_line($line); + + if (ref($opcode) eq 'CODE') { + $line = &$opcode($arg); + } elsif ($mnemonic) { + $line = $c.$mnemonic; + $line.= "\t$arg" if ($arg ne ""); + } + } + + print $line if ($line); + print "\n"; +} + +print "#endif\n" if ($flavour eq "linux32" || $flavour eq "linux64"); + +close STDOUT; diff --git a/external/boringssl/crypto/perlasm/cbc.pl b/external/boringssl/crypto/perlasm/cbc.pl new file mode 100644 index 0000000000..24561e759a --- /dev/null +++ b/external/boringssl/crypto/perlasm/cbc.pl @@ -0,0 +1,349 @@ +#!/usr/local/bin/perl + +# void des_ncbc_encrypt(input, output, length, schedule, ivec, enc) +# des_cblock (*input); +# des_cblock (*output); +# long length; +# des_key_schedule schedule; +# des_cblock (*ivec); +# int enc; +# +# calls +# des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT); +# + +#&cbc("des_ncbc_encrypt","des_encrypt",0); +#&cbc("BF_cbc_encrypt","BF_encrypt","BF_encrypt", +# 1,4,5,3,5,-1); +#&cbc("des_ncbc_encrypt","des_encrypt","des_encrypt", +# 0,4,5,3,5,-1); +#&cbc("des_ede3_cbc_encrypt","des_encrypt3","des_decrypt3", +# 0,6,7,3,4,5); +# +# When doing a cipher that needs bigendian order, +# for encrypt, the iv is kept in bigendian form, +# while for decrypt, it is kept in little endian. +sub cbc + { + local($name,$enc_func,$dec_func,$swap,$iv_off,$enc_off,$p1,$p2,$p3)=@_; + # name is the function name + # enc_func and dec_func and the functions to call for encrypt/decrypt + # swap is true if byte order needs to be reversed + # iv_off is parameter number for the iv + # enc_off is parameter number for the encrypt/decrypt flag + # p1,p2,p3 are the offsets for parameters to be passed to the + # underlying calls. + + &function_begin_B($name,""); + &comment(""); + + $in="esi"; + $out="edi"; + $count="ebp"; + + &push("ebp"); + &push("ebx"); + &push("esi"); + &push("edi"); + + $data_off=4; + $data_off+=4 if ($p1 > 0); + $data_off+=4 if ($p2 > 0); + $data_off+=4 if ($p3 > 0); + + &mov($count, &wparam(2)); # length + + &comment("getting iv ptr from parameter $iv_off"); + &mov("ebx", &wparam($iv_off)); # Get iv ptr + + &mov($in, &DWP(0,"ebx","",0));# iv[0] + &mov($out, &DWP(4,"ebx","",0));# iv[1] + + &push($out); + &push($in); + &push($out); # used in decrypt for iv[1] + &push($in); # used in decrypt for iv[0] + + &mov("ebx", "esp"); # This is the address of tin[2] + + &mov($in, &wparam(0)); # in + &mov($out, &wparam(1)); # out + + # We have loaded them all, how lets push things + &comment("getting encrypt flag from parameter $enc_off"); + &mov("ecx", &wparam($enc_off)); # Get enc flag + if ($p3 > 0) + { + &comment("get and push parameter $p3"); + if ($enc_off != $p3) + { &mov("eax", &wparam($p3)); &push("eax"); } + else { &push("ecx"); } + } + if ($p2 > 0) + { + &comment("get and push parameter $p2"); + if ($enc_off != $p2) + { &mov("eax", &wparam($p2)); &push("eax"); } + else { &push("ecx"); } + } + if ($p1 > 0) + { + &comment("get and push parameter $p1"); + if ($enc_off != $p1) + { &mov("eax", &wparam($p1)); &push("eax"); } + else { &push("ecx"); } + } + &push("ebx"); # push data/iv + + &cmp("ecx",0); + &jz(&label("decrypt")); + + &and($count,0xfffffff8); + &mov("eax", &DWP($data_off,"esp","",0)); # load iv[0] + &mov("ebx", &DWP($data_off+4,"esp","",0)); # load iv[1] + + &jz(&label("encrypt_finish")); + + ############################################################# + + &set_label("encrypt_loop"); + # encrypt start + # "eax" and "ebx" hold iv (or the last cipher text) + + &mov("ecx", &DWP(0,$in,"",0)); # load first 4 bytes + &mov("edx", &DWP(4,$in,"",0)); # second 4 bytes + + &xor("eax", "ecx"); + &xor("ebx", "edx"); + + &bswap("eax") if $swap; + &bswap("ebx") if $swap; + + &mov(&DWP($data_off,"esp","",0), "eax"); # put in array for call + &mov(&DWP($data_off+4,"esp","",0), "ebx"); # + + &call($enc_func); + + &mov("eax", &DWP($data_off,"esp","",0)); + &mov("ebx", &DWP($data_off+4,"esp","",0)); + + &bswap("eax") if $swap; + &bswap("ebx") if $swap; + + &mov(&DWP(0,$out,"",0),"eax"); + &mov(&DWP(4,$out,"",0),"ebx"); + + # eax and ebx are the next iv. + + &add($in, 8); + &add($out, 8); + + &sub($count, 8); + &jnz(&label("encrypt_loop")); + +###################################################################3 + &set_label("encrypt_finish"); + &mov($count, &wparam(2)); # length + &and($count, 7); + &jz(&label("finish")); + &call(&label("PIC_point")); +&set_label("PIC_point"); + &blindpop("edx"); + &lea("ecx",&DWP(&label("cbc_enc_jmp_table")."-".&label("PIC_point"),"edx")); + &mov($count,&DWP(0,"ecx",$count,4)); + &add($count,"edx"); + &xor("ecx","ecx"); + &xor("edx","edx"); + #&mov($count,&DWP(&label("cbc_enc_jmp_table"),"",$count,4)); + &jmp_ptr($count); + +&set_label("ej7"); + &movb(&HB("edx"), &BP(6,$in,"",0)); + &shl("edx",8); +&set_label("ej6"); + &movb(&HB("edx"), &BP(5,$in,"",0)); +&set_label("ej5"); + &movb(&LB("edx"), &BP(4,$in,"",0)); +&set_label("ej4"); + &mov("ecx", &DWP(0,$in,"",0)); + &jmp(&label("ejend")); +&set_label("ej3"); + &movb(&HB("ecx"), &BP(2,$in,"",0)); + &shl("ecx",8); +&set_label("ej2"); + &movb(&HB("ecx"), &BP(1,$in,"",0)); +&set_label("ej1"); + &movb(&LB("ecx"), &BP(0,$in,"",0)); +&set_label("ejend"); + + &xor("eax", "ecx"); + &xor("ebx", "edx"); + + &bswap("eax") if $swap; + &bswap("ebx") if $swap; + + &mov(&DWP($data_off,"esp","",0), "eax"); # put in array for call + &mov(&DWP($data_off+4,"esp","",0), "ebx"); # + + &call($enc_func); + + &mov("eax", &DWP($data_off,"esp","",0)); + &mov("ebx", &DWP($data_off+4,"esp","",0)); + + &bswap("eax") if $swap; + &bswap("ebx") if $swap; + + &mov(&DWP(0,$out,"",0),"eax"); + &mov(&DWP(4,$out,"",0),"ebx"); + + &jmp(&label("finish")); + + ############################################################# + ############################################################# + &set_label("decrypt",1); + # decrypt start + &and($count,0xfffffff8); + # The next 2 instructions are only for if the jz is taken + &mov("eax", &DWP($data_off+8,"esp","",0)); # get iv[0] + &mov("ebx", &DWP($data_off+12,"esp","",0)); # get iv[1] + &jz(&label("decrypt_finish")); + + &set_label("decrypt_loop"); + &mov("eax", &DWP(0,$in,"",0)); # load first 4 bytes + &mov("ebx", &DWP(4,$in,"",0)); # second 4 bytes + + &bswap("eax") if $swap; + &bswap("ebx") if $swap; + + &mov(&DWP($data_off,"esp","",0), "eax"); # put back + &mov(&DWP($data_off+4,"esp","",0), "ebx"); # + + &call($dec_func); + + &mov("eax", &DWP($data_off,"esp","",0)); # get return + &mov("ebx", &DWP($data_off+4,"esp","",0)); # + + &bswap("eax") if $swap; + &bswap("ebx") if $swap; + + &mov("ecx", &DWP($data_off+8,"esp","",0)); # get iv[0] + &mov("edx", &DWP($data_off+12,"esp","",0)); # get iv[1] + + &xor("ecx", "eax"); + &xor("edx", "ebx"); + + &mov("eax", &DWP(0,$in,"",0)); # get old cipher text, + &mov("ebx", &DWP(4,$in,"",0)); # next iv actually + + &mov(&DWP(0,$out,"",0),"ecx"); + &mov(&DWP(4,$out,"",0),"edx"); + + &mov(&DWP($data_off+8,"esp","",0), "eax"); # save iv + &mov(&DWP($data_off+12,"esp","",0), "ebx"); # + + &add($in, 8); + &add($out, 8); + + &sub($count, 8); + &jnz(&label("decrypt_loop")); +############################ ENDIT #######################3 + &set_label("decrypt_finish"); + &mov($count, &wparam(2)); # length + &and($count, 7); + &jz(&label("finish")); + + &mov("eax", &DWP(0,$in,"",0)); # load first 4 bytes + &mov("ebx", &DWP(4,$in,"",0)); # second 4 bytes + + &bswap("eax") if $swap; + &bswap("ebx") if $swap; + + &mov(&DWP($data_off,"esp","",0), "eax"); # put back + &mov(&DWP($data_off+4,"esp","",0), "ebx"); # + + &call($dec_func); + + &mov("eax", &DWP($data_off,"esp","",0)); # get return + &mov("ebx", &DWP($data_off+4,"esp","",0)); # + + &bswap("eax") if $swap; + &bswap("ebx") if $swap; + + &mov("ecx", &DWP($data_off+8,"esp","",0)); # get iv[0] + &mov("edx", &DWP($data_off+12,"esp","",0)); # get iv[1] + + &xor("ecx", "eax"); + &xor("edx", "ebx"); + + # this is for when we exit + &mov("eax", &DWP(0,$in,"",0)); # get old cipher text, + &mov("ebx", &DWP(4,$in,"",0)); # next iv actually + +&set_label("dj7"); + &rotr("edx", 16); + &movb(&BP(6,$out,"",0), &LB("edx")); + &shr("edx",16); +&set_label("dj6"); + &movb(&BP(5,$out,"",0), &HB("edx")); +&set_label("dj5"); + &movb(&BP(4,$out,"",0), &LB("edx")); +&set_label("dj4"); + &mov(&DWP(0,$out,"",0), "ecx"); + &jmp(&label("djend")); +&set_label("dj3"); + &rotr("ecx", 16); + &movb(&BP(2,$out,"",0), &LB("ecx")); + &shl("ecx",16); +&set_label("dj2"); + &movb(&BP(1,$in,"",0), &HB("ecx")); +&set_label("dj1"); + &movb(&BP(0,$in,"",0), &LB("ecx")); +&set_label("djend"); + + # final iv is still in eax:ebx + &jmp(&label("finish")); + + +############################ FINISH #######################3 + &set_label("finish",1); + &mov("ecx", &wparam($iv_off)); # Get iv ptr + + ################################################# + $total=16+4; + $total+=4 if ($p1 > 0); + $total+=4 if ($p2 > 0); + $total+=4 if ($p3 > 0); + &add("esp",$total); + + &mov(&DWP(0,"ecx","",0), "eax"); # save iv + &mov(&DWP(4,"ecx","",0), "ebx"); # save iv + + &function_end_A($name); + + &align(64); + &set_label("cbc_enc_jmp_table"); + &data_word("0"); + &data_word(&label("ej1")."-".&label("PIC_point")); + &data_word(&label("ej2")."-".&label("PIC_point")); + &data_word(&label("ej3")."-".&label("PIC_point")); + &data_word(&label("ej4")."-".&label("PIC_point")); + &data_word(&label("ej5")."-".&label("PIC_point")); + &data_word(&label("ej6")."-".&label("PIC_point")); + &data_word(&label("ej7")."-".&label("PIC_point")); + # not used + #&set_label("cbc_dec_jmp_table",1); + #&data_word("0"); + #&data_word(&label("dj1")."-".&label("PIC_point")); + #&data_word(&label("dj2")."-".&label("PIC_point")); + #&data_word(&label("dj3")."-".&label("PIC_point")); + #&data_word(&label("dj4")."-".&label("PIC_point")); + #&data_word(&label("dj5")."-".&label("PIC_point")); + #&data_word(&label("dj6")."-".&label("PIC_point")); + #&data_word(&label("dj7")."-".&label("PIC_point")); + &align(64); + + &function_end_B($name); + + } + +1; diff --git a/external/boringssl/crypto/perlasm/readme b/external/boringssl/crypto/perlasm/readme new file mode 100644 index 0000000000..f02bbee75a --- /dev/null +++ b/external/boringssl/crypto/perlasm/readme @@ -0,0 +1,124 @@ +The perl scripts in this directory are my 'hack' to generate +multiple different assembler formats via the one origional script. + +The way to use this library is to start with adding the path to this directory +and then include it. + +push(@INC,"perlasm","../../perlasm"); +require "x86asm.pl"; + +The first thing we do is setup the file and type of assember + +&asm_init($ARGV[0],$0); + +The first argument is the 'type'. Currently +'cpp', 'sol', 'a.out', 'elf' or 'win32'. +Argument 2 is the file name. + +The reciprocal function is +&asm_finish() which should be called at the end. + +There are 2 main 'packages'. x86ms.pl, which is the microsoft assembler, +and x86unix.pl which is the unix (gas) version. + +Functions of interest are: +&external_label("des_SPtrans"); declare and external variable +&LB(reg); Low byte for a register +&HB(reg); High byte for a register +&BP(off,base,index,scale) Byte pointer addressing +&DWP(off,base,index,scale) Word pointer addressing +&stack_push(num) Basically a 'sub esp, num*4' with extra +&stack_pop(num) inverse of stack_push +&function_begin(name,extra) Start a function with pushing of + edi, esi, ebx and ebp. extra is extra win32 + external info that may be required. +&function_begin_B(name,extra) Same as norma function_begin but no pushing. +&function_end(name) Call at end of function. +&function_end_A(name) Standard pop and ret, for use inside functions +&function_end_B(name) Call at end but with poping or 'ret'. +&swtmp(num) Address on stack temp word. +&wparam(num) Parameter number num, that was push + in C convention. This all works over pushes + and pops. +&comment("hello there") Put in a comment. +&label("loop") Refer to a label, normally a jmp target. +&set_label("loop") Set a label at this point. +&data_word(word) Put in a word of data. + +So how does this all hold together? Given + +int calc(int len, int *data) + { + int i,j=0; + + for (i=0; i. +# +# Why AT&T to MASM and not vice versa? Several reasons. Because AT&T +# format is way easier to parse. Because it's simpler to "gear" from +# Unix ABI to Windows one [see cross-reference "card" at the end of +# file]. Because Linux targets were available first... +# +# In addition the script also "distills" code suitable for GNU +# assembler, so that it can be compiled with more rigid assemblers, +# such as Solaris /usr/ccs/bin/as. +# +# This translator is not designed to convert *arbitrary* assembler +# code from AT&T format to MASM one. It's designed to convert just +# enough to provide for dual-ABI OpenSSL modules development... +# There *are* limitations and you might have to modify your assembler +# code or this script to achieve the desired result... +# +# Currently recognized limitations: +# +# - can't use multiple ops per line; +# +# Dual-ABI styling rules. +# +# 1. Adhere to Unix register and stack layout [see cross-reference +# ABI "card" at the end for explanation]. +# 2. Forget about "red zone," stick to more traditional blended +# stack frame allocation. If volatile storage is actually required +# that is. If not, just leave the stack as is. +# 3. Functions tagged with ".type name,@function" get crafted with +# unified Win64 prologue and epilogue automatically. If you want +# to take care of ABI differences yourself, tag functions as +# ".type name,@abi-omnipotent" instead. +# 4. To optimize the Win64 prologue you can specify number of input +# arguments as ".type name,@function,N." Keep in mind that if N is +# larger than 6, then you *have to* write "abi-omnipotent" code, +# because >6 cases can't be addressed with unified prologue. +# 5. Name local labels as .L*, do *not* use dynamic labels such as 1: +# (sorry about latter). +# 6. Don't use [or hand-code with .byte] "rep ret." "ret" mnemonic is +# required to identify the spots, where to inject Win64 epilogue! +# But on the pros, it's then prefixed with rep automatically:-) +# 7. Stick to explicit ip-relative addressing. If you have to use +# GOTPCREL addressing, stick to mov symbol@GOTPCREL(%rip),%r??. +# Both are recognized and translated to proper Win64 addressing +# modes. To support legacy code a synthetic directive, .picmeup, +# is implemented. It puts address of the *next* instruction into +# target register, e.g.: +# +# .picmeup %rax +# lea .Label-.(%rax),%rax +# +# 8. In order to provide for structured exception handling unified +# Win64 prologue copies %rsp value to %rax. For further details +# see SEH paragraph at the end. +# 9. .init segment is allowed to contain calls to functions only. +# a. If function accepts more than 4 arguments *and* >4th argument +# is declared as non 64-bit value, do clear its upper part. + +my $flavour = shift; +my $output = shift; +if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } + +open STDOUT,">$output" || die "can't open $output: $!" + if (defined($output)); + +my $gas=1; $gas=0 if ($output =~ /\.asm$/); +my $elf=1; $elf=0 if (!$gas); +my $win64=0; +my $prefix=""; +my $decor=".L"; + +my $masmref=8 + 50727*2**-32; # 8.00.50727 shipped with VS2005 +my $masm=0; +my $PTR=" PTR"; + +my $nasmref=2.03; +my $nasm=0; + +if ($flavour eq "mingw64") { $gas=1; $elf=0; $win64=1; + # TODO(davidben): Before supporting the + # mingw64 perlasm flavour, do away with this + # environment variable check. + die "mingw64 not supported"; + $prefix=`echo __USER_LABEL_PREFIX__ | $ENV{CC} -E -P -`; + chomp($prefix); + } +elsif ($flavour eq "macosx") { $gas=1; $elf=0; $prefix="_"; $decor="L\$"; } +elsif ($flavour eq "masm") { $gas=0; $elf=0; $masm=$masmref; $win64=1; $decor="\$L\$"; } +elsif ($flavour eq "nasm") { $gas=0; $elf=0; $nasm=$nasmref; $win64=1; $decor="\$L\$"; $PTR=""; } +elsif (!$gas) { die "unknown flavour $flavour"; } + +my $current_segment; +my $current_function; +my %globals; + +{ package opcode; # pick up opcodes + sub re { + my $self = shift; # single instance in enough... + local *line = shift; + undef $ret; + + if ($line =~ /^([a-z][a-z0-9]*)/i) { + $self->{op} = $1; + $ret = $self; + $line = substr($line,@+[0]); $line =~ s/^\s+//; + + undef $self->{sz}; + if ($self->{op} =~ /^(movz)x?([bw]).*/) { # movz is pain... + $self->{op} = $1; + $self->{sz} = $2; + } elsif ($self->{op} =~ /call|jmp/) { + $self->{sz} = ""; + } elsif ($self->{op} =~ /^p/ && $' !~ /^(ush|op|insrw)/) { # SSEn + $self->{sz} = ""; + } elsif ($self->{op} =~ /^v/) { # VEX + $self->{sz} = ""; + } elsif ($self->{op} =~ /mov[dq]/ && $line =~ /%xmm/) { + $self->{sz} = ""; + } elsif ($self->{op} =~ /([a-z]{3,})([qlwb])$/) { + $self->{op} = $1; + $self->{sz} = $2; + } + } + $ret; + } + sub size { + my $self = shift; + my $sz = shift; + $self->{sz} = $sz if (defined($sz) && !defined($self->{sz})); + $self->{sz}; + } + sub out { + my $self = shift; + if ($gas) { + if ($self->{op} eq "movz") { # movz is pain... + sprintf "%s%s%s",$self->{op},$self->{sz},shift; + } elsif ($self->{op} =~ /^set/) { + "$self->{op}"; + } elsif ($self->{op} eq "ret") { + my $epilogue = ""; + if ($win64 && $current_function->{abi} eq "svr4") { + $epilogue = "movq 8(%rsp),%rdi\n\t" . + "movq 16(%rsp),%rsi\n\t"; + } + $epilogue . ".byte 0xf3,0xc3"; + } elsif ($self->{op} eq "call" && !$elf && $current_segment eq ".init") { + ".p2align\t3\n\t.quad"; + } else { + "$self->{op}$self->{sz}"; + } + } else { + $self->{op} =~ s/^movz/movzx/; + if ($self->{op} eq "ret") { + $self->{op} = ""; + if ($win64 && $current_function->{abi} eq "svr4") { + $self->{op} = "mov rdi,QWORD${PTR}[8+rsp]\t;WIN64 epilogue\n\t". + "mov rsi,QWORD${PTR}[16+rsp]\n\t"; + } + $self->{op} .= "DB\t0F3h,0C3h\t\t;repret"; + } elsif ($self->{op} =~ /^(pop|push)f/) { + $self->{op} .= $self->{sz}; + } elsif ($self->{op} eq "call" && $current_segment eq ".CRT\$XCU") { + $self->{op} = "\tDQ"; + } + $self->{op}; + } + } + sub mnemonic { + my $self=shift; + my $op=shift; + $self->{op}=$op if (defined($op)); + $self->{op}; + } +} +{ package const; # pick up constants, which start with $ + sub re { + my $self = shift; # single instance in enough... + local *line = shift; + undef $ret; + + if ($line =~ /^\$([^,]+)/) { + $self->{value} = $1; + $ret = $self; + $line = substr($line,@+[0]); $line =~ s/^\s+//; + } + $ret; + } + sub out { + my $self = shift; + + $self->{value} =~ s/\b(0b[0-1]+)/oct($1)/eig; + if ($gas) { + # Solaris /usr/ccs/bin/as can't handle multiplications + # in $self->{value} + my $value = $self->{value}; + $value =~ s/(?{value} = $value; + } + sprintf "\$%s",$self->{value}; + } else { + $self->{value} =~ s/0x([0-9a-f]+)/0$1h/ig if ($masm); + sprintf "%s",$self->{value}; + } + } +} +{ package ea; # pick up effective addresses: expr(%reg,%reg,scale) + sub re { + my $self = shift; # single instance in enough... + local *line = shift; + undef $ret; + + # optional * ---vvv--- appears in indirect jmp/call + if ($line =~ /^(\*?)([^\(,]*)\(([%\w,]+)\)/) { + $self->{asterisk} = $1; + $self->{label} = $2; + ($self->{base},$self->{index},$self->{scale})=split(/,/,$3); + $self->{scale} = 1 if (!defined($self->{scale})); + $ret = $self; + $line = substr($line,@+[0]); $line =~ s/^\s+//; + + if ($win64 && $self->{label} =~ s/\@GOTPCREL//) { + die if (opcode->mnemonic() ne "mov"); + opcode->mnemonic("lea"); + } + $self->{base} =~ s/^%//; + $self->{index} =~ s/^%// if (defined($self->{index})); + } + $ret; + } + sub size {} + sub out { + my $self = shift; + my $sz = shift; + + $self->{label} =~ s/([_a-z][_a-z0-9]*)/$globals{$1} or $1/gei; + $self->{label} =~ s/\.L/$decor/g; + + # Silently convert all EAs to 64-bit. This is required for + # elder GNU assembler and results in more compact code, + # *but* most importantly AES module depends on this feature! + $self->{index} =~ s/^[er](.?[0-9xpi])[d]?$/r\1/; + $self->{base} =~ s/^[er](.?[0-9xpi])[d]?$/r\1/; + + # Solaris /usr/ccs/bin/as can't handle multiplications + # in $self->{label}, new gas requires sign extension... + use integer; + $self->{label} =~ s/(?{label} =~ s/\b([0-9]+\s*[\*\/\%]\s*[0-9]+)\b/eval($1)/eg; + $self->{label} =~ s/\b([0-9]+)\b/$1<<32>>32/eg; + + if (!$self->{label} && $self->{index} && $self->{scale}==1 && + $self->{base} =~ /(rbp|r13)/) { + $self->{base} = $self->{index}; $self->{index} = $1; + } + + if ($gas) { + $self->{label} =~ s/^___imp_/__imp__/ if ($flavour eq "mingw64"); + + if (defined($self->{index})) { + sprintf "%s%s(%s,%%%s,%d)",$self->{asterisk}, + $self->{label}, + $self->{base}?"%$self->{base}":"", + $self->{index},$self->{scale}; + } else { + sprintf "%s%s(%%%s)", $self->{asterisk},$self->{label},$self->{base}; + } + } else { + %szmap = ( b=>"BYTE$PTR", w=>"WORD$PTR", + l=>"DWORD$PTR", d=>"DWORD$PTR", + q=>"QWORD$PTR", o=>"OWORD$PTR", + x=>"XMMWORD$PTR", y=>"YMMWORD$PTR", z=>"ZMMWORD$PTR" ); + + $self->{label} =~ s/\./\$/g; + $self->{label} =~ s/(?{label} = "($self->{label})" if ($self->{label} =~ /[\*\+\-\/]/); + + ($self->{asterisk}) && ($sz="q") || + (opcode->mnemonic() =~ /^v?mov([qd])$/) && ($sz=$1) || + (opcode->mnemonic() =~ /^v?pinsr([qdwb])$/) && ($sz=$1) || + (opcode->mnemonic() =~ /^vpbroadcast([qdwb])$/) && ($sz=$1) || + (opcode->mnemonic() =~ /^vinsert[fi]128$/) && ($sz="x"); + + if (defined($self->{index})) { + sprintf "%s[%s%s*%d%s]",$szmap{$sz}, + $self->{label}?"$self->{label}+":"", + $self->{index},$self->{scale}, + $self->{base}?"+$self->{base}":""; + } elsif ($self->{base} eq "rip") { + sprintf "%s[%s]",$szmap{$sz},$self->{label}; + } else { + sprintf "%s[%s%s]",$szmap{$sz}, + $self->{label}?"$self->{label}+":"", + $self->{base}; + } + } + } +} +{ package register; # pick up registers, which start with %. + sub re { + my $class = shift; # muliple instances... + my $self = {}; + local *line = shift; + undef $ret; + + # optional * ---vvv--- appears in indirect jmp/call + if ($line =~ /^(\*?)%(\w+)/) { + bless $self,$class; + $self->{asterisk} = $1; + $self->{value} = $2; + $ret = $self; + $line = substr($line,@+[0]); $line =~ s/^\s+//; + } + $ret; + } + sub size { + my $self = shift; + undef $ret; + + if ($self->{value} =~ /^r[\d]+b$/i) { $ret="b"; } + elsif ($self->{value} =~ /^r[\d]+w$/i) { $ret="w"; } + elsif ($self->{value} =~ /^r[\d]+d$/i) { $ret="l"; } + elsif ($self->{value} =~ /^r[\w]+$/i) { $ret="q"; } + elsif ($self->{value} =~ /^[a-d][hl]$/i){ $ret="b"; } + elsif ($self->{value} =~ /^[\w]{2}l$/i) { $ret="b"; } + elsif ($self->{value} =~ /^[\w]{2}$/i) { $ret="w"; } + elsif ($self->{value} =~ /^e[a-z]{2}$/i){ $ret="l"; } + + $ret; + } + sub out { + my $self = shift; + if ($gas) { sprintf "%s%%%s",$self->{asterisk},$self->{value}; } + else { $self->{value}; } + } +} +{ package label; # pick up labels, which end with : + sub re { + my $self = shift; # single instance is enough... + local *line = shift; + undef $ret; + + if ($line =~ /(^[\.\w]+)\:/) { + $self->{value} = $1; + $ret = $self; + $line = substr($line,@+[0]); $line =~ s/^\s+//; + + $self->{value} =~ s/^\.L/$decor/; + } + $ret; + } + sub out { + my $self = shift; + + if ($gas) { + my $func = ($globals{$self->{value}} or $self->{value}) . ":"; + if ($win64 && + $current_function->{name} eq $self->{value} && + $current_function->{abi} eq "svr4") { + $func .= "\n"; + $func .= " movq %rdi,8(%rsp)\n"; + $func .= " movq %rsi,16(%rsp)\n"; + $func .= " movq %rsp,%rax\n"; + $func .= "${decor}SEH_begin_$current_function->{name}:\n"; + my $narg = $current_function->{narg}; + $narg=6 if (!defined($narg)); + $func .= " movq %rcx,%rdi\n" if ($narg>0); + $func .= " movq %rdx,%rsi\n" if ($narg>1); + $func .= " movq %r8,%rdx\n" if ($narg>2); + $func .= " movq %r9,%rcx\n" if ($narg>3); + $func .= " movq 40(%rsp),%r8\n" if ($narg>4); + $func .= " movq 48(%rsp),%r9\n" if ($narg>5); + } + $func; + } elsif ($self->{value} ne "$current_function->{name}") { + $self->{value} .= ":" if ($masm && $ret!~m/^\$/); + $self->{value} . ":"; + } elsif ($win64 && $current_function->{abi} eq "svr4") { + my $func = "$current_function->{name}" . + ($nasm ? ":" : "\tPROC $current_function->{scope}") . + "\n"; + $func .= " mov QWORD${PTR}[8+rsp],rdi\t;WIN64 prologue\n"; + $func .= " mov QWORD${PTR}[16+rsp],rsi\n"; + $func .= " mov rax,rsp\n"; + $func .= "${decor}SEH_begin_$current_function->{name}:"; + $func .= ":" if ($masm); + $func .= "\n"; + my $narg = $current_function->{narg}; + $narg=6 if (!defined($narg)); + $func .= " mov rdi,rcx\n" if ($narg>0); + $func .= " mov rsi,rdx\n" if ($narg>1); + $func .= " mov rdx,r8\n" if ($narg>2); + $func .= " mov rcx,r9\n" if ($narg>3); + $func .= " mov r8,QWORD${PTR}[40+rsp]\n" if ($narg>4); + $func .= " mov r9,QWORD${PTR}[48+rsp]\n" if ($narg>5); + $func .= "\n"; + } else { + "$current_function->{name}". + ($nasm ? ":" : "\tPROC $current_function->{scope}"); + } + } +} +{ package expr; # pick up expressioins + sub re { + my $self = shift; # single instance is enough... + local *line = shift; + undef $ret; + + if ($line =~ /(^[^,]+)/) { + $self->{value} = $1; + $ret = $self; + $line = substr($line,@+[0]); $line =~ s/^\s+//; + + $self->{value} =~ s/\@PLT// if (!$elf); + $self->{value} =~ s/([_a-z][_a-z0-9]*)/$globals{$1} or $1/gei; + $self->{value} =~ s/\.L/$decor/g; + } + $ret; + } + sub out { + my $self = shift; + if ($nasm && opcode->mnemonic()=~m/^j(?![re]cxz)/) { + "NEAR ".$self->{value}; + } else { + $self->{value}; + } + } +} +{ package directive; # pick up directives, which start with . + sub re { + my $self = shift; # single instance is enough... + local *line = shift; + undef $ret; + my $dir; + my %opcode = # lea 2f-1f(%rip),%dst; 1: nop; 2: + ( "%rax"=>0x01058d48, "%rcx"=>0x010d8d48, + "%rdx"=>0x01158d48, "%rbx"=>0x011d8d48, + "%rsp"=>0x01258d48, "%rbp"=>0x012d8d48, + "%rsi"=>0x01358d48, "%rdi"=>0x013d8d48, + "%r8" =>0x01058d4c, "%r9" =>0x010d8d4c, + "%r10"=>0x01158d4c, "%r11"=>0x011d8d4c, + "%r12"=>0x01258d4c, "%r13"=>0x012d8d4c, + "%r14"=>0x01358d4c, "%r15"=>0x013d8d4c ); + + if ($line =~ /^\s*(\.\w+)/) { + $dir = $1; + $ret = $self; + undef $self->{value}; + $line = substr($line,@+[0]); $line =~ s/^\s+//; + + SWITCH: for ($dir) { + /\.picmeup/ && do { if ($line =~ /(%r[\w]+)/i) { + $dir="\t.long"; + $line=sprintf "0x%x,0x90000000",$opcode{$1}; + } + last; + }; + /\.global|\.globl|\.extern/ + && do { $globals{$line} = $prefix . $line; + $line = $globals{$line} if ($prefix); + last; + }; + /\.type/ && do { ($sym,$type,$narg) = split(',',$line); + if ($type eq "\@function") { + undef $current_function; + $current_function->{name} = $sym; + $current_function->{abi} = "svr4"; + $current_function->{narg} = $narg; + $current_function->{scope} = defined($globals{$sym})?"PUBLIC":"PRIVATE"; + } elsif ($type eq "\@abi-omnipotent") { + undef $current_function; + $current_function->{name} = $sym; + $current_function->{scope} = defined($globals{$sym})?"PUBLIC":"PRIVATE"; + } + $line =~ s/\@abi\-omnipotent/\@function/; + $line =~ s/\@function.*/\@function/; + last; + }; + /\.asciz/ && do { if ($line =~ /^"(.*)"$/) { + $dir = ".byte"; + $line = join(",",unpack("C*",$1),0); + } + last; + }; + /\.rva|\.long|\.quad/ + && do { $line =~ s/([_a-z][_a-z0-9]*)/$globals{$1} or $1/gei; + $line =~ s/\.L/$decor/g; + last; + }; + } + + if ($gas) { + $self->{value} = $dir . "\t" . $line; + + if ($dir =~ /\.extern/) { + if ($flavour eq "elf") { + $self->{value} .= "\n.hidden $line"; + } else { + $self->{value} = ""; + } + } elsif (!$elf && $dir =~ /\.type/) { + $self->{value} = ""; + $self->{value} = ".def\t" . ($globals{$1} or $1) . ";\t" . + (defined($globals{$1})?".scl 2;":".scl 3;") . + "\t.type 32;\t.endef" + if ($win64 && $line =~ /([^,]+),\@function/); + } elsif (!$elf && $dir =~ /\.size/) { + $self->{value} = ""; + if (defined($current_function)) { + $self->{value} .= "${decor}SEH_end_$current_function->{name}:" + if ($win64 && $current_function->{abi} eq "svr4"); + undef $current_function; + } + } elsif (!$elf && $dir =~ /\.align/) { + $self->{value} = ".p2align\t" . (log($line)/log(2)); + } elsif ($dir eq ".section") { + $current_segment=$line; + if (!$elf && $current_segment eq ".init") { + if ($flavour eq "macosx") { $self->{value} = ".mod_init_func"; } + elsif ($flavour eq "mingw64") { $self->{value} = ".section\t.ctors"; } + } + } elsif ($dir =~ /\.(text|data)/) { + $current_segment=".$1"; + } elsif ($dir =~ /\.global|\.globl|\.extern/) { + if ($flavour eq "macosx") { + $self->{value} .= "\n.private_extern $line"; + } else { + $self->{value} .= "\n.hidden $line"; + } + } elsif ($dir =~ /\.hidden/) { + if ($flavour eq "macosx") { $self->{value} = ".private_extern\t$prefix$line"; } + elsif ($flavour eq "mingw64") { $self->{value} = ""; } + } elsif ($dir =~ /\.comm/) { + $self->{value} = "$dir\t$prefix$line"; + $self->{value} =~ s|,([0-9]+),([0-9]+)$|",$1,".log($2)/log(2)|e if ($flavour eq "macosx"); + } + $line = ""; + return $self; + } + + # non-gas case or nasm/masm + SWITCH: for ($dir) { + /\.text/ && do { my $v=undef; + if ($nasm) { + $v="section .text code align=64\n"; + } else { + $v="$current_segment\tENDS\n" if ($current_segment); + $current_segment = ".text\$"; + $v.="$current_segment\tSEGMENT "; + $v.=$masm>=$masmref ? "ALIGN(256)" : "PAGE"; + $v.=" 'CODE'"; + } + $self->{value} = $v; + last; + }; + /\.data/ && do { my $v=undef; + if ($nasm) { + $v="section .data data align=8\n"; + } else { + $v="$current_segment\tENDS\n" if ($current_segment); + $current_segment = "_DATA"; + $v.="$current_segment\tSEGMENT"; + } + $self->{value} = $v; + last; + }; + /\.section/ && do { my $v=undef; + $line =~ s/([^,]*).*/$1/; + $line = ".CRT\$XCU" if ($line eq ".init"); + if ($nasm) { + $v="section $line"; + if ($line=~/\.([px])data/) { + $v.=" rdata align="; + $v.=$1 eq "p"? 4 : 8; + } elsif ($line=~/\.CRT\$/i) { + $v.=" rdata align=8"; + } + } else { + $v="$current_segment\tENDS\n" if ($current_segment); + $v.="$line\tSEGMENT"; + if ($line=~/\.([px])data/) { + $v.=" READONLY"; + $v.=" ALIGN(".($1 eq "p" ? 4 : 8).")" if ($masm>=$masmref); + } elsif ($line=~/\.CRT\$/i) { + $v.=" READONLY "; + $v.=$masm>=$masmref ? "ALIGN(8)" : "DWORD"; + } + } + $current_segment = $line; + $self->{value} = $v; + last; + }; + /\.extern/ && do { $self->{value} = "EXTERN\t".$line; + $self->{value} .= ":NEAR" if ($masm); + last; + }; + /\.globl|.global/ + && do { $self->{value} = $masm?"PUBLIC":"global"; + $self->{value} .= "\t".$line; + last; + }; + /\.size/ && do { if (defined($current_function)) { + undef $self->{value}; + if ($current_function->{abi} eq "svr4") { + $self->{value}="${decor}SEH_end_$current_function->{name}:"; + $self->{value}.=":\n" if($masm); + } + $self->{value}.="$current_function->{name}\tENDP" if($masm && $current_function->{name}); + undef $current_function; + } + last; + }; + /\.align/ && do { $self->{value} = "ALIGN\t".$line; last; }; + /\.(value|long|rva|quad)/ + && do { my $sz = substr($1,0,1); + my @arr = split(/,\s*/,$line); + my $last = pop(@arr); + my $conv = sub { my $var=shift; + $var=~s/^(0b[0-1]+)/oct($1)/eig; + $var=~s/^0x([0-9a-f]+)/0$1h/ig if ($masm); + if ($sz eq "D" && ($current_segment=~/.[px]data/ || $dir eq ".rva")) + { $var=~s/([_a-z\$\@][_a-z0-9\$\@]*)/$nasm?"$1 wrt ..imagebase":"imagerel $1"/egi; } + $var; + }; + + $sz =~ tr/bvlrq/BWDDQ/; + $self->{value} = "\tD$sz\t"; + for (@arr) { $self->{value} .= &$conv($_).","; } + $self->{value} .= &$conv($last); + last; + }; + /\.byte/ && do { my @str=split(/,\s*/,$line); + map(s/(0b[0-1]+)/oct($1)/eig,@str); + map(s/0x([0-9a-f]+)/0$1h/ig,@str) if ($masm); + while ($#str>15) { + $self->{value}.="DB\t" + .join(",",@str[0..15])."\n"; + foreach (0..15) { shift @str; } + } + $self->{value}.="DB\t" + .join(",",@str) if (@str); + last; + }; + /\.comm/ && do { my @str=split(/,\s*/,$line); + my $v=undef; + if ($nasm) { + $v.="common $prefix@str[0] @str[1]"; + } else { + $v="$current_segment\tENDS\n" if ($current_segment); + $current_segment = "_DATA"; + $v.="$current_segment\tSEGMENT\n"; + $v.="COMM @str[0]:DWORD:".@str[1]/4; + } + $self->{value} = $v; + last; + }; + } + $line = ""; + } + + $ret; + } + sub out { + my $self = shift; + $self->{value}; + } +} + +sub rex { + local *opcode=shift; + my ($dst,$src,$rex)=@_; + + $rex|=0x04 if($dst>=8); + $rex|=0x01 if($src>=8); + push @opcode,($rex|0x40) if ($rex); +} + +# older gas and ml64 don't handle SSE>2 instructions +my %regrm = ( "%eax"=>0, "%ecx"=>1, "%edx"=>2, "%ebx"=>3, + "%esp"=>4, "%ebp"=>5, "%esi"=>6, "%edi"=>7 ); + +my $movq = sub { # elderly gas can't handle inter-register movq + my $arg = shift; + my @opcode=(0x66); + if ($arg =~ /%xmm([0-9]+),\s*%r(\w+)/) { + my ($src,$dst)=($1,$2); + if ($dst !~ /[0-9]+/) { $dst = $regrm{"%e$dst"}; } + rex(\@opcode,$src,$dst,0x8); + push @opcode,0x0f,0x7e; + push @opcode,0xc0|(($src&7)<<3)|($dst&7); # ModR/M + @opcode; + } elsif ($arg =~ /%r(\w+),\s*%xmm([0-9]+)/) { + my ($src,$dst)=($2,$1); + if ($dst !~ /[0-9]+/) { $dst = $regrm{"%e$dst"}; } + rex(\@opcode,$src,$dst,0x8); + push @opcode,0x0f,0x6e; + push @opcode,0xc0|(($src&7)<<3)|($dst&7); # ModR/M + @opcode; + } else { + (); + } +}; + +my $pextrd = sub { + if (shift =~ /\$([0-9]+),\s*%xmm([0-9]+),\s*(%\w+)/) { + my @opcode=(0x66); + $imm=$1; + $src=$2; + $dst=$3; + if ($dst =~ /%r([0-9]+)d/) { $dst = $1; } + elsif ($dst =~ /%e/) { $dst = $regrm{$dst}; } + rex(\@opcode,$src,$dst); + push @opcode,0x0f,0x3a,0x16; + push @opcode,0xc0|(($src&7)<<3)|($dst&7); # ModR/M + push @opcode,$imm; + @opcode; + } else { + (); + } +}; + +my $pinsrd = sub { + if (shift =~ /\$([0-9]+),\s*(%\w+),\s*%xmm([0-9]+)/) { + my @opcode=(0x66); + $imm=$1; + $src=$2; + $dst=$3; + if ($src =~ /%r([0-9]+)/) { $src = $1; } + elsif ($src =~ /%e/) { $src = $regrm{$src}; } + rex(\@opcode,$dst,$src); + push @opcode,0x0f,0x3a,0x22; + push @opcode,0xc0|(($dst&7)<<3)|($src&7); # ModR/M + push @opcode,$imm; + @opcode; + } else { + (); + } +}; + +my $pshufb = sub { + if (shift =~ /%xmm([0-9]+),\s*%xmm([0-9]+)/) { + my @opcode=(0x66); + rex(\@opcode,$2,$1); + push @opcode,0x0f,0x38,0x00; + push @opcode,0xc0|($1&7)|(($2&7)<<3); # ModR/M + @opcode; + } else { + (); + } +}; + +my $palignr = sub { + if (shift =~ /\$([0-9]+),\s*%xmm([0-9]+),\s*%xmm([0-9]+)/) { + my @opcode=(0x66); + rex(\@opcode,$3,$2); + push @opcode,0x0f,0x3a,0x0f; + push @opcode,0xc0|($2&7)|(($3&7)<<3); # ModR/M + push @opcode,$1; + @opcode; + } else { + (); + } +}; + +my $pclmulqdq = sub { + if (shift =~ /\$([x0-9a-f]+),\s*%xmm([0-9]+),\s*%xmm([0-9]+)/) { + my @opcode=(0x66); + rex(\@opcode,$3,$2); + push @opcode,0x0f,0x3a,0x44; + push @opcode,0xc0|($2&7)|(($3&7)<<3); # ModR/M + my $c=$1; + push @opcode,$c=~/^0/?oct($c):$c; + @opcode; + } else { + (); + } +}; + +my $rdrand = sub { + if (shift =~ /%[er](\w+)/) { + my @opcode=(); + my $dst=$1; + if ($dst !~ /[0-9]+/) { $dst = $regrm{"%e$dst"}; } + rex(\@opcode,0,$1,8); + push @opcode,0x0f,0xc7,0xf0|($dst&7); + @opcode; + } else { + (); + } +}; + +my $rdseed = sub { + if (shift =~ /%[er](\w+)/) { + my @opcode=(); + my $dst=$1; + if ($dst !~ /[0-9]+/) { $dst = $regrm{"%e$dst"}; } + rex(\@opcode,0,$1,8); + push @opcode,0x0f,0xc7,0xf8|($dst&7); + @opcode; + } else { + (); + } +}; + +sub rxb { + local *opcode=shift; + my ($dst,$src1,$src2,$rxb)=@_; + + $rxb|=0x7<<5; + $rxb&=~(0x04<<5) if($dst>=8); + $rxb&=~(0x01<<5) if($src1>=8); + $rxb&=~(0x02<<5) if($src2>=8); + push @opcode,$rxb; +} + +my $vprotd = sub { + if (shift =~ /\$([x0-9a-f]+),\s*%xmm([0-9]+),\s*%xmm([0-9]+)/) { + my @opcode=(0x8f); + rxb(\@opcode,$3,$2,-1,0x08); + push @opcode,0x78,0xc2; + push @opcode,0xc0|($2&7)|(($3&7)<<3); # ModR/M + my $c=$1; + push @opcode,$c=~/^0/?oct($c):$c; + @opcode; + } else { + (); + } +}; + +my $vprotq = sub { + if (shift =~ /\$([x0-9a-f]+),\s*%xmm([0-9]+),\s*%xmm([0-9]+)/) { + my @opcode=(0x8f); + rxb(\@opcode,$3,$2,-1,0x08); + push @opcode,0x78,0xc3; + push @opcode,0xc0|($2&7)|(($3&7)<<3); # ModR/M + my $c=$1; + push @opcode,$c=~/^0/?oct($c):$c; + @opcode; + } else { + (); + } +}; + +if ($nasm) { + print <<___; +default rel +%define XMMWORD +%define YMMWORD +%define ZMMWORD +___ +} elsif ($masm) { + print <<___; +OPTION DOTNAME +___ +} + +print STDOUT "#if defined(__x86_64__)\n" if ($gas); + +while($line=<>) { + + chomp($line); + + $line =~ s|[#!].*$||; # get rid of asm-style comments... + $line =~ s|/\*.*\*/||; # ... and C-style comments... + $line =~ s|^\s+||; # ... and skip white spaces in beginning + $line =~ s|\s+$||; # ... and at the end + + undef $label; + undef $opcode; + undef @args; + + if ($label=label->re(\$line)) { print $label->out(); } + + if (directive->re(\$line)) { + printf "%s",directive->out(); + } elsif ($opcode=opcode->re(\$line)) { + my $asm = eval("\$".$opcode->mnemonic()); + undef @bytes; + + if ((ref($asm) eq 'CODE') && scalar(@bytes=&$asm($line))) { + print $gas?".byte\t":"DB\t",join(',',@bytes),"\n"; + next; + } + + ARGUMENT: while (1) { + my $arg; + + if ($arg=register->re(\$line)) { opcode->size($arg->size()); } + elsif ($arg=const->re(\$line)) { } + elsif ($arg=ea->re(\$line)) { } + elsif ($arg=expr->re(\$line)) { } + else { last ARGUMENT; } + + push @args,$arg; + + last ARGUMENT if ($line !~ /^,/); + + $line =~ s/^,\s*//; + } # ARGUMENT: + + if ($#args>=0) { + my $insn; + my $sz=opcode->size(); + + if ($gas) { + $insn = $opcode->out($#args>=1?$args[$#args]->size():$sz); + @args = map($_->out($sz),@args); + printf "\t%s\t%s",$insn,join(",",@args); + } else { + $insn = $opcode->out(); + foreach (@args) { + my $arg = $_->out(); + # $insn.=$sz compensates for movq, pinsrw, ... + if ($arg =~ /^xmm[0-9]+$/) { $insn.=$sz; $sz="x" if(!$sz); last; } + if ($arg =~ /^ymm[0-9]+$/) { $insn.=$sz; $sz="y" if(!$sz); last; } + if ($arg =~ /^zmm[0-9]+$/) { $insn.=$sz; $sz="z" if(!$sz); last; } + if ($arg =~ /^mm[0-9]+$/) { $insn.=$sz; $sz="q" if(!$sz); last; } + } + @args = reverse(@args); + undef $sz if ($nasm && $opcode->mnemonic() eq "lea"); + + if ($insn eq "movq" && $#args == 1 && $args[0]->out($sz) eq "xmm0" && $args[1]->out($sz) eq "rax") { + # I have no clue why MASM can't parse this instruction. + printf "DB 66h, 48h, 0fh, 6eh, 0c0h"; + } else { + printf "\t%s\t%s",$insn,join(",",map($_->out($sz),@args)); + } + } + } else { + printf "\t%s",$opcode->out(); + } + } + + print $line,"\n"; +} + +print "\n$current_segment\tENDS\n" if ($current_segment && $masm); +print "END\n" if ($masm); +print "#endif\n" if ($gas); + + +close STDOUT; + + ################################################# +# Cross-reference x86_64 ABI "card" +# +# Unix Win64 +# %rax * * +# %rbx - - +# %rcx #4 #1 +# %rdx #3 #2 +# %rsi #2 - +# %rdi #1 - +# %rbp - - +# %rsp - - +# %r8 #5 #3 +# %r9 #6 #4 +# %r10 * * +# %r11 * * +# %r12 - - +# %r13 - - +# %r14 - - +# %r15 - - +# +# (*) volatile register +# (-) preserved by callee +# (#) Nth argument, volatile +# +# In Unix terms top of stack is argument transfer area for arguments +# which could not be accomodated in registers. Or in other words 7th +# [integer] argument resides at 8(%rsp) upon function entry point. +# 128 bytes above %rsp constitute a "red zone" which is not touched +# by signal handlers and can be used as temporal storage without +# allocating a frame. +# +# In Win64 terms N*8 bytes on top of stack is argument transfer area, +# which belongs to/can be overwritten by callee. N is the number of +# arguments passed to callee, *but* not less than 4! This means that +# upon function entry point 5th argument resides at 40(%rsp), as well +# as that 32 bytes from 8(%rsp) can always be used as temporal +# storage [without allocating a frame]. One can actually argue that +# one can assume a "red zone" above stack pointer under Win64 as well. +# Point is that at apparently no occasion Windows kernel would alter +# the area above user stack pointer in true asynchronous manner... +# +# All the above means that if assembler programmer adheres to Unix +# register and stack layout, but disregards the "red zone" existense, +# it's possible to use following prologue and epilogue to "gear" from +# Unix to Win64 ABI in leaf functions with not more than 6 arguments. +# +# omnipotent_function: +# ifdef WIN64 +# movq %rdi,8(%rsp) +# movq %rsi,16(%rsp) +# movq %rcx,%rdi ; if 1st argument is actually present +# movq %rdx,%rsi ; if 2nd argument is actually ... +# movq %r8,%rdx ; if 3rd argument is ... +# movq %r9,%rcx ; if 4th argument ... +# movq 40(%rsp),%r8 ; if 5th ... +# movq 48(%rsp),%r9 ; if 6th ... +# endif +# ... +# ifdef WIN64 +# movq 8(%rsp),%rdi +# movq 16(%rsp),%rsi +# endif +# ret +# + ################################################# +# Win64 SEH, Structured Exception Handling. +# +# Unlike on Unix systems(*) lack of Win64 stack unwinding information +# has undesired side-effect at run-time: if an exception is raised in +# assembler subroutine such as those in question (basically we're +# referring to segmentation violations caused by malformed input +# parameters), the application is briskly terminated without invoking +# any exception handlers, most notably without generating memory dump +# or any user notification whatsoever. This poses a problem. It's +# possible to address it by registering custom language-specific +# handler that would restore processor context to the state at +# subroutine entry point and return "exception is not handled, keep +# unwinding" code. Writing such handler can be a challenge... But it's +# doable, though requires certain coding convention. Consider following +# snippet: +# +# .type function,@function +# function: +# movq %rsp,%rax # copy rsp to volatile register +# pushq %r15 # save non-volatile registers +# pushq %rbx +# pushq %rbp +# movq %rsp,%r11 +# subq %rdi,%r11 # prepare [variable] stack frame +# andq $-64,%r11 +# movq %rax,0(%r11) # check for exceptions +# movq %r11,%rsp # allocate [variable] stack frame +# movq %rax,0(%rsp) # save original rsp value +# magic_point: +# ... +# movq 0(%rsp),%rcx # pull original rsp value +# movq -24(%rcx),%rbp # restore non-volatile registers +# movq -16(%rcx),%rbx +# movq -8(%rcx),%r15 +# movq %rcx,%rsp # restore original rsp +# ret +# .size function,.-function +# +# The key is that up to magic_point copy of original rsp value remains +# in chosen volatile register and no non-volatile register, except for +# rsp, is modified. While past magic_point rsp remains constant till +# the very end of the function. In this case custom language-specific +# exception handler would look like this: +# +# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame, +# CONTEXT *context,DISPATCHER_CONTEXT *disp) +# { ULONG64 *rsp = (ULONG64 *)context->Rax; +# if (context->Rip >= magic_point) +# { rsp = ((ULONG64 **)context->Rsp)[0]; +# context->Rbp = rsp[-3]; +# context->Rbx = rsp[-2]; +# context->R15 = rsp[-1]; +# } +# context->Rsp = (ULONG64)rsp; +# context->Rdi = rsp[1]; +# context->Rsi = rsp[2]; +# +# memcpy (disp->ContextRecord,context,sizeof(CONTEXT)); +# RtlVirtualUnwind(UNW_FLAG_NHANDLER,disp->ImageBase, +# dips->ControlPc,disp->FunctionEntry,disp->ContextRecord, +# &disp->HandlerData,&disp->EstablisherFrame,NULL); +# return ExceptionContinueSearch; +# } +# +# It's appropriate to implement this handler in assembler, directly in +# function's module. In order to do that one has to know members' +# offsets in CONTEXT and DISPATCHER_CONTEXT structures and some constant +# values. Here they are: +# +# CONTEXT.Rax 120 +# CONTEXT.Rcx 128 +# CONTEXT.Rdx 136 +# CONTEXT.Rbx 144 +# CONTEXT.Rsp 152 +# CONTEXT.Rbp 160 +# CONTEXT.Rsi 168 +# CONTEXT.Rdi 176 +# CONTEXT.R8 184 +# CONTEXT.R9 192 +# CONTEXT.R10 200 +# CONTEXT.R11 208 +# CONTEXT.R12 216 +# CONTEXT.R13 224 +# CONTEXT.R14 232 +# CONTEXT.R15 240 +# CONTEXT.Rip 248 +# CONTEXT.Xmm6 512 +# sizeof(CONTEXT) 1232 +# DISPATCHER_CONTEXT.ControlPc 0 +# DISPATCHER_CONTEXT.ImageBase 8 +# DISPATCHER_CONTEXT.FunctionEntry 16 +# DISPATCHER_CONTEXT.EstablisherFrame 24 +# DISPATCHER_CONTEXT.TargetIp 32 +# DISPATCHER_CONTEXT.ContextRecord 40 +# DISPATCHER_CONTEXT.LanguageHandler 48 +# DISPATCHER_CONTEXT.HandlerData 56 +# UNW_FLAG_NHANDLER 0 +# ExceptionContinueSearch 1 +# +# In order to tie the handler to the function one has to compose +# couple of structures: one for .xdata segment and one for .pdata. +# +# UNWIND_INFO structure for .xdata segment would be +# +# function_unwind_info: +# .byte 9,0,0,0 +# .rva handler +# +# This structure designates exception handler for a function with +# zero-length prologue, no stack frame or frame register. +# +# To facilitate composing of .pdata structures, auto-generated "gear" +# prologue copies rsp value to rax and denotes next instruction with +# .LSEH_begin_{function_name} label. This essentially defines the SEH +# styling rule mentioned in the beginning. Position of this label is +# chosen in such manner that possible exceptions raised in the "gear" +# prologue would be accounted to caller and unwound from latter's frame. +# End of function is marked with respective .LSEH_end_{function_name} +# label. To summarize, .pdata segment would contain +# +# .rva .LSEH_begin_function +# .rva .LSEH_end_function +# .rva function_unwind_info +# +# Reference to functon_unwind_info from .xdata segment is the anchor. +# In case you wonder why references are 32-bit .rvas and not 64-bit +# .quads. References put into these two segments are required to be +# *relative* to the base address of the current binary module, a.k.a. +# image base. No Win64 module, be it .exe or .dll, can be larger than +# 2GB and thus such relative references can be and are accommodated in +# 32 bits. +# +# Having reviewed the example function code, one can argue that "movq +# %rsp,%rax" above is redundant. It is not! Keep in mind that on Unix +# rax would contain an undefined value. If this "offends" you, use +# another register and refrain from modifying rax till magic_point is +# reached, i.e. as if it was a non-volatile register. If more registers +# are required prior [variable] frame setup is completed, note that +# nobody says that you can have only one "magic point." You can +# "liberate" non-volatile registers by denoting last stack off-load +# instruction and reflecting it in finer grade unwind logic in handler. +# After all, isn't it why it's called *language-specific* handler... +# +# Attentive reader can notice that exceptions would be mishandled in +# auto-generated "gear" epilogue. Well, exception effectively can't +# occur there, because if memory area used by it was subject to +# segmentation violation, then it would be raised upon call to the +# function (and as already mentioned be accounted to caller, which is +# not a problem). If you're still not comfortable, then define tail +# "magic point" just prior ret instruction and have handler treat it... +# +# (*) Note that we're talking about run-time, not debug-time. Lack of +# unwind information makes debugging hard on both Windows and +# Unix. "Unlike" referes to the fact that on Unix signal handler +# will always be invoked, core dumped and appropriate exit code +# returned to parent (for user notification). diff --git a/external/boringssl/crypto/perlasm/x86asm.pl b/external/boringssl/crypto/perlasm/x86asm.pl new file mode 100644 index 0000000000..3c7be40c02 --- /dev/null +++ b/external/boringssl/crypto/perlasm/x86asm.pl @@ -0,0 +1,292 @@ +#!/usr/bin/env perl + +# require 'x86asm.pl'; +# &asm_init(,"des-586.pl"[,$i386only]); +# &function_begin("foo"); +# ... +# &function_end("foo"); +# &asm_finish + +$out=(); +$i386=0; + +# AUTOLOAD is this context has quite unpleasant side effect, namely +# that typos in function calls effectively go to assembler output, +# but on the pros side we don't have to implement one subroutine per +# each opcode... +sub ::AUTOLOAD +{ my $opcode = $AUTOLOAD; + + die "more than 4 arguments passed to $opcode" if ($#_>3); + + $opcode =~ s/.*:://; + if ($opcode =~ /^push/) { $stack+=4; } + elsif ($opcode =~ /^pop/) { $stack-=4; } + + &generic($opcode,@_) or die "undefined subroutine \&$AUTOLOAD"; +} + +sub ::emit +{ my $opcode=shift; + + if ($#_==-1) { push(@out,"\t$opcode\n"); } + else { push(@out,"\t$opcode\t".join(',',@_)."\n"); } +} + +sub ::LB +{ $_[0] =~ m/^e?([a-d])x$/o or die "$_[0] does not have a 'low byte'"; + $1."l"; +} +sub ::HB +{ $_[0] =~ m/^e?([a-d])x$/o or die "$_[0] does not have a 'high byte'"; + $1."h"; +} +sub ::stack_push{ my $num=$_[0]*4; $stack+=$num; &sub("esp",$num); } +sub ::stack_pop { my $num=$_[0]*4; $stack-=$num; &add("esp",$num); } +sub ::blindpop { &pop($_[0]); $stack+=4; } +sub ::wparam { &DWP($stack+4*$_[0],"esp"); } +sub ::swtmp { &DWP(4*$_[0],"esp"); } + +sub ::bswap +{ if ($i386) # emulate bswap for i386 + { &comment("bswap @_"); + &xchg(&HB(@_),&LB(@_)); + &ror (@_,16); + &xchg(&HB(@_),&LB(@_)); + } + else + { &generic("bswap",@_); } +} +# These are made-up opcodes introduced over the years essentially +# by ignorance, just alias them to real ones... +sub ::movb { &mov(@_); } +sub ::xorb { &xor(@_); } +sub ::rotl { &rol(@_); } +sub ::rotr { &ror(@_); } +sub ::exch { &xchg(@_); } +sub ::halt { &hlt; } +sub ::movz { &movzx(@_); } +sub ::pushf { &pushfd; } +sub ::popf { &popfd; } + +# 3 argument instructions +sub ::movq +{ my($p1,$p2,$optimize)=@_; + + if ($optimize && $p1=~/^mm[0-7]$/ && $p2=~/^mm[0-7]$/) + # movq between mmx registers can sink Intel CPUs + { &::pshufw($p1,$p2,0xe4); } + else + { &::generic("movq",@_); } +} + +# SSE>2 instructions +my %regrm = ( "eax"=>0, "ecx"=>1, "edx"=>2, "ebx"=>3, + "esp"=>4, "ebp"=>5, "esi"=>6, "edi"=>7 ); +sub ::pextrd +{ my($dst,$src,$imm)=@_; + if ("$dst:$src" =~ /(e[a-dsd][ixp]):xmm([0-7])/) + { &::data_byte(0x66,0x0f,0x3a,0x16,0xc0|($2<<3)|$regrm{$1},$imm); } + else + { &::generic("pextrd",@_); } +} + +sub ::pinsrd +{ my($dst,$src,$imm)=@_; + if ("$dst:$src" =~ /xmm([0-7]):(e[a-dsd][ixp])/) + { &::data_byte(0x66,0x0f,0x3a,0x22,0xc0|($1<<3)|$regrm{$2},$imm); } + else + { &::generic("pinsrd",@_); } +} + +sub ::pshufb +{ my($dst,$src)=@_; + if ("$dst:$src" =~ /xmm([0-7]):xmm([0-7])/) + { &data_byte(0x66,0x0f,0x38,0x00,0xc0|($1<<3)|$2); } + else + { &::generic("pshufb",@_); } +} + +sub ::palignr +{ my($dst,$src,$imm)=@_; + if ("$dst:$src" =~ /xmm([0-7]):xmm([0-7])/) + { &::data_byte(0x66,0x0f,0x3a,0x0f,0xc0|($1<<3)|$2,$imm); } + else + { &::generic("palignr",@_); } +} + +sub ::pclmulqdq +{ my($dst,$src,$imm)=@_; + if ("$dst:$src" =~ /xmm([0-7]):xmm([0-7])/) + { &::data_byte(0x66,0x0f,0x3a,0x44,0xc0|($1<<3)|$2,$imm); } + else + { &::generic("pclmulqdq",@_); } +} + +sub ::rdrand +{ my ($dst)=@_; + if ($dst =~ /(e[a-dsd][ixp])/) + { &::data_byte(0x0f,0xc7,0xf0|$regrm{$dst}); } + else + { &::generic("rdrand",@_); } +} + +sub rxb { + local *opcode=shift; + my ($dst,$src1,$src2,$rxb)=@_; + + $rxb|=0x7<<5; + $rxb&=~(0x04<<5) if($dst>=8); + $rxb&=~(0x01<<5) if($src1>=8); + $rxb&=~(0x02<<5) if($src2>=8); + push @opcode,$rxb; +} + +sub ::vprotd +{ my $args=join(',',@_); + if ($args =~ /xmm([0-7]),xmm([0-7]),([x0-9a-f]+)/) + { my @opcode=(0x8f); + rxb(\@opcode,$1,$2,-1,0x08); + push @opcode,0x78,0xc2; + push @opcode,0xc0|($2&7)|(($1&7)<<3); # ModR/M + my $c=$3; + push @opcode,$c=~/^0/?oct($c):$c; + &::data_byte(@opcode); + } + else + { &::generic("vprotd",@_); } +} + +# label management +$lbdecor="L"; # local label decoration, set by package +$label="000"; + +sub ::islabel # see is argument is a known label +{ my $i; + foreach $i (values %label) { return $i if ($i eq $_[0]); } + $label{$_[0]}; # can be undef +} + +sub ::label # instantiate a function-scope label +{ if (!defined($label{$_[0]})) + { $label{$_[0]}="${lbdecor}${label}${_[0]}"; $label++; } + $label{$_[0]}; +} + +sub ::LABEL # instantiate a file-scope label +{ $label{$_[0]}=$_[1] if (!defined($label{$_[0]})); + $label{$_[0]}; +} + +sub ::static_label { &::LABEL($_[0],$lbdecor.$_[0]); } + +sub ::set_label_B { push(@out,"@_:\n"); } +sub ::set_label +{ my $label=&::label($_[0]); + &::align($_[1]) if ($_[1]>1); + &::set_label_B($label); + $label; +} + +sub ::wipe_labels # wipes function-scope labels +{ foreach $i (keys %label) + { delete $label{$i} if ($label{$i} =~ /^\Q${lbdecor}\E[0-9]{3}/); } +} + +# subroutine management +sub ::function_begin +{ &function_begin_B(@_); + $stack=4; + &push("ebp"); + &push("ebx"); + &push("esi"); + &push("edi"); +} + +sub ::function_end +{ &pop("edi"); + &pop("esi"); + &pop("ebx"); + &pop("ebp"); + &ret(); + &function_end_B(@_); + $stack=0; + &wipe_labels(); +} + +sub ::function_end_A +{ &pop("edi"); + &pop("esi"); + &pop("ebx"); + &pop("ebp"); + &ret(); + $stack+=16; # readjust esp as if we didn't pop anything +} + +sub ::asciz +{ my @str=unpack("C*",shift); + push @str,0; + while ($#str>15) { + &data_byte(@str[0..15]); + foreach (0..15) { shift @str; } + } + &data_byte(@str) if (@str); +} + +sub ::asm_finish +{ &file_end(); + print "#if defined(__i386__)\n" unless $win32; + print @out; + print "#endif\n" unless $win32; +} + +sub ::asm_init +{ my ($type,$fn,$cpu)=@_; + + $filename=$fn; + $i386=$cpu; + + $elf=$cpp=$coff=$aout=$macosx=$win32=$netware=$mwerks=$android=0; + if (($type eq "elf")) + { $elf=1; require "x86gas.pl"; } + elsif (($type eq "elf-1")) + { $elf=-1; require "x86gas.pl"; } + elsif (($type eq "a\.out")) + { $aout=1; require "x86gas.pl"; } + elsif (($type eq "coff" or $type eq "gaswin")) + { $coff=1; require "x86gas.pl"; } + elsif (($type eq "win32n")) + { $win32=1; require "x86nasm.pl"; } + elsif (($type eq "nw-nasm")) + { $netware=1; require "x86nasm.pl"; } + #elsif (($type eq "nw-mwasm")) + #{ $netware=1; $mwerks=1; require "x86nasm.pl"; } + elsif (($type eq "win32")) + { $win32=1; require "x86masm.pl"; } + elsif (($type eq "macosx")) + { $aout=1; $macosx=1; require "x86gas.pl"; } + elsif (($type eq "android")) + { $elf=1; $android=1; require "x86gas.pl"; } + else + { print STDERR <<"EOF"; +Pick one target type from + elf - Linux, FreeBSD, Solaris x86, etc. + a.out - DJGPP, elder OpenBSD, etc. + coff - GAS/COFF such as Win32 targets + win32n - Windows 95/Windows NT NASM format + nw-nasm - NetWare NASM format + macosx - Mac OS X +EOF + exit(1); + } + + $pic=0; + for (@ARGV) { $pic=1 if (/\-[fK]PIC/i); } + + $filename =~ s/\.pl$//; + &file($filename); +} + +sub ::hidden {} + +1; diff --git a/external/boringssl/crypto/perlasm/x86gas.pl b/external/boringssl/crypto/perlasm/x86gas.pl new file mode 100644 index 0000000000..55d09d8ba5 --- /dev/null +++ b/external/boringssl/crypto/perlasm/x86gas.pl @@ -0,0 +1,263 @@ +#!/usr/bin/env perl + +package x86gas; + +*out=\@::out; + +$::lbdecor=$::aout?"L":".L"; # local label decoration +$nmdecor=($::aout or $::coff)?"_":""; # external name decoration + +$initseg=""; + +$align=16; +$align=log($align)/log(2) if ($::aout); +$com_start="#" if ($::aout or $::coff); + +sub opsize() +{ my $reg=shift; + if ($reg =~ m/^%e/o) { "l"; } + elsif ($reg =~ m/^%[a-d][hl]$/o) { "b"; } + elsif ($reg =~ m/^%[yxm]/o) { undef; } + else { "w"; } +} + +# swap arguments; +# expand opcode with size suffix; +# prefix numeric constants with $; +sub ::generic +{ my($opcode,@arg)=@_; + my($suffix,$dst,$src); + + @arg=reverse(@arg); + + for (@arg) + { s/^(\*?)(e?[a-dsixphl]{2})$/$1%$2/o; # gp registers + s/^([xy]?mm[0-7])$/%$1/o; # xmm/mmx registers + s/^(\-?[0-9]+)$/\$$1/o; # constants + s/^(\-?0x[0-9a-f]+)$/\$$1/o; # constants + } + + $dst = $arg[$#arg] if ($#arg>=0); + $src = $arg[$#arg-1] if ($#arg>=1); + if ($dst =~ m/^%/o) { $suffix=&opsize($dst); } + elsif ($src =~ m/^%/o) { $suffix=&opsize($src); } + else { $suffix="l"; } + undef $suffix if ($dst =~ m/^%[xm]/o || $src =~ m/^%[xm]/o); + + if ($#_==0) { &::emit($opcode); } + elsif ($#_==1 && $opcode =~ m/^(call|clflush|j|loop|set)/o) + { &::emit($opcode,@arg); } + else { &::emit($opcode.$suffix,@arg);} + + 1; +} +# +# opcodes not covered by ::generic above, mostly inconsistent namings... +# +sub ::movzx { &::movzb(@_); } +sub ::pushfd { &::pushfl; } +sub ::popfd { &::popfl; } +sub ::cpuid { &::emit(".byte\t0x0f,0xa2"); } +sub ::rdtsc { &::emit(".byte\t0x0f,0x31"); } + +sub ::call { &::emit("call",(&::islabel($_[0]) or "$nmdecor$_[0]")); } +sub ::call_ptr { &::generic("call","*$_[0]"); } +sub ::jmp_ptr { &::generic("jmp","*$_[0]"); } + +*::bswap = sub { &::emit("bswap","%$_[0]"); } if (!$::i386); + +sub ::DWP +{ my($addr,$reg1,$reg2,$idx)=@_; + my $ret=""; + + if (!defined($idx) && 1*$reg2) { $idx=$reg2; $reg2=$reg1; undef $reg1; } + + $addr =~ s/^\s+//; + # prepend global references with optional underscore + $addr =~ s/^([^\+\-0-9][^\+\-]*)/&::islabel($1) or "$nmdecor$1"/ige; + + $reg1 = "%$reg1" if ($reg1); + $reg2 = "%$reg2" if ($reg2); + + $ret .= $addr if (($addr ne "") && ($addr ne 0)); + + if ($reg2) + { $idx!= 0 or $idx=1; + $ret .= "($reg1,$reg2,$idx)"; + } + elsif ($reg1) + { $ret .= "($reg1)"; } + + $ret; +} +sub ::QWP { &::DWP(@_); } +sub ::BP { &::DWP(@_); } +sub ::WP { &::DWP(@_); } +sub ::BC { @_; } +sub ::DWC { @_; } + +sub ::file +{ push(@out,".file\t\"$_[0].S\"\n.text\n"); } + +sub ::function_begin_B +{ my $func=shift; + my $global=($func !~ /^_/); + my $begin="${::lbdecor}_${func}_begin"; + + &::LABEL($func,$global?"$begin":"$nmdecor$func"); + $func=$nmdecor.$func; + + push(@out,".globl\t$func\n") if ($global); + if ($::macosx) { + push(@out,".private_extern\t$func\n"); + } else { + push(@out,".hidden\t$func\n"); + } + if ($::coff) + { push(@out,".def\t$func;\t.scl\t".(3-$global).";\t.type\t32;\t.endef\n"); } + elsif (($::aout and !$::pic) or $::macosx) + { } + else + { push(@out,".type $func,\@function\n"); } + push(@out,".align\t$align\n"); + push(@out,"$func:\n"); + push(@out,"$begin:\n") if ($global); + $::stack=4; +} + +sub ::function_end_B +{ my $func=shift; + push(@out,".size\t$nmdecor$func,.-".&::LABEL($func)."\n") if ($::elf); + $::stack=0; + &::wipe_labels(); +} + +sub ::comment + { + if (!defined($com_start) or $::elf) + { # Regarding $::elf above... + # GNU and SVR4 as'es use different comment delimiters, + push(@out,"\n"); # so we just skip ELF comments... + return; + } + foreach (@_) + { + if (/^\s*$/) + { push(@out,"\n"); } + else + { push(@out,"\t$com_start $_ $com_end\n"); } + } + } + +sub ::external_label +{ foreach(@_) { &::LABEL($_,$nmdecor.$_); } } + +sub ::public_label +{ push(@out,".globl\t".&::LABEL($_[0],$nmdecor.$_[0])."\n"); } + +sub ::file_end +{ if ($::macosx) + { if (%non_lazy_ptr) + { push(@out,".section __IMPORT,__pointers,non_lazy_symbol_pointers\n"); + foreach $i (keys %non_lazy_ptr) + { push(@out,"$non_lazy_ptr{$i}:\n.indirect_symbol\t$i\n.long\t0\n"); } + } + } + if (0 && grep {/\b${nmdecor}OPENSSL_ia32cap_P\b/i} @out) { + my $tmp=".comm\t${nmdecor}OPENSSL_ia32cap_P,16"; + if ($::macosx) { push (@out,"$tmp,2\n"); } + elsif ($::elf) { push (@out,"$tmp,4\n"); } + else { push (@out,"$tmp\n"); } + } + push(@out,$initseg) if ($initseg); +} + +sub ::data_byte { push(@out,".byte\t".join(',',@_)."\n"); } +sub ::data_short{ push(@out,".value\t".join(',',@_)."\n"); } +sub ::data_word { push(@out,".long\t".join(',',@_)."\n"); } + +sub ::align +{ my $val=$_[0]; + if ($::aout) + { $val=int(log($val)/log(2)); + $val.=",0x90"; + } + push(@out,".align\t$val\n"); +} + +sub ::picmeup +{ my($dst,$sym,$base,$reflabel)=@_; + + if (($::pic && ($::elf || $::aout)) || $::macosx) + { if (!defined($base)) + { &::call(&::label("PIC_me_up")); + &::set_label("PIC_me_up"); + &::blindpop($dst); + $base=$dst; + $reflabel=&::label("PIC_me_up"); + } + if ($::macosx) + { my $indirect=&::static_label("$nmdecor$sym\$non_lazy_ptr"); + &::mov($dst,&::DWP("$indirect-$reflabel",$base)); + $non_lazy_ptr{"$nmdecor$sym"}=$indirect; + } + elsif ($sym eq "OPENSSL_ia32cap_P" && $::elf>0) + { &::lea($dst,&::DWP("$sym-$reflabel",$base)); } + else + { &::lea($dst,&::DWP("_GLOBAL_OFFSET_TABLE_+[.-$reflabel]", + $base)); + &::mov($dst,&::DWP("$sym\@GOT",$dst)); + } + } + else + { &::lea($dst,&::DWP($sym)); } +} + +sub ::initseg +{ my $f=$nmdecor.shift; + + if ($::android) + { $initseg.=<<___; +.section .init_array +.align 4 +.long $f +___ + } + elsif ($::elf) + { $initseg.=<<___; +.section .init + call $f +___ + } + elsif ($::coff) + { $initseg.=<<___; # applies to both Cygwin and Mingw +.section .ctors +.long $f +___ + } + elsif ($::macosx) + { $initseg.=<<___; +.mod_init_func +.align 2 +.long $f +___ + } + elsif ($::aout) + { my $ctor="${nmdecor}_GLOBAL_\$I\$$f"; + $initseg.=".text\n"; + $initseg.=".type $ctor,\@function\n" if ($::pic); + $initseg.=<<___; # OpenBSD way... +.globl $ctor +.align 2 +$ctor: + jmp $f +___ + } +} + +sub ::dataseg +{ push(@out,".data\n"); } + +*::hidden = sub { push(@out,".hidden\t$nmdecor$_[0]\n"); } if ($::elf); + +1; diff --git a/external/boringssl/crypto/perlasm/x86masm.pl b/external/boringssl/crypto/perlasm/x86masm.pl new file mode 100644 index 0000000000..b7f49d1c41 --- /dev/null +++ b/external/boringssl/crypto/perlasm/x86masm.pl @@ -0,0 +1,200 @@ +#!/usr/bin/env perl + +package x86masm; + +*out=\@::out; + +$::lbdecor="\$L"; # local label decoration +$nmdecor="_"; # external name decoration + +$initseg=""; +$segment=""; + +sub ::generic +{ my ($opcode,@arg)=@_; + + # fix hexadecimal constants + for (@arg) { s/(?= 0x02030000\n"); + push(@out,"safeseh ".&::LABEL($nm,$nmdecor.$nm)."\n"); + push(@out,"%endif\n"); +} + +1; diff --git a/external/boringssl/crypto/pkcs8/CMakeLists.txt b/external/boringssl/crypto/pkcs8/CMakeLists.txt new file mode 100644 index 0000000000..8f674f915d --- /dev/null +++ b/external/boringssl/crypto/pkcs8/CMakeLists.txt @@ -0,0 +1,32 @@ +include_directories(../../include) + +add_library( + pkcs8_lib + + OBJECT + + pkcs8.c + p8_pkey.c + p5_pbe.c + p5_pbev2.c +) + +if(ENABLE_TESTS) +add_executable( + pkcs12_test + + pkcs12_test.cc + + $ +) + +add_executable( + pkcs8_test + + pkcs8_test.cc +) + +target_link_libraries(pkcs8_test crypto) +target_link_libraries(pkcs12_test crypto) +add_dependencies(all_tests pkcs8_test pkcs12_test) +endif() diff --git a/external/boringssl/crypto/pkcs8/internal.h b/external/boringssl/crypto/pkcs8/internal.h new file mode 100644 index 0000000000..7995e78745 --- /dev/null +++ b/external/boringssl/crypto/pkcs8/internal.h @@ -0,0 +1,83 @@ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 1999. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#ifndef OPENSSL_HEADER_PKCS8_INTERNAL_H +#define OPENSSL_HEADER_PKCS8_INTERNAL_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +#define PKCS5_DEFAULT_ITERATIONS 2048 +#define PKCS5_SALT_LEN 8 + +/* PKCS5_v2_PBE_keyivgen intializes the supplied |ctx| for PBKDF v2, which must + * be specified by |param|. The password is specified by |pass_raw| and + * |pass_raw_len|. |cipher| and |md| are ignored. + * + * It returns one on success and zero on error. */ +int PKCS5_v2_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const uint8_t *pass_raw, + size_t pass_raw_len, ASN1_TYPE *param, + const EVP_CIPHER *cipher, const EVP_MD *md, int enc); + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_PKCS8_INTERNAL_H */ diff --git a/external/boringssl/crypto/pkcs8/p5_pbe.c b/external/boringssl/crypto/pkcs8/p5_pbe.c new file mode 100644 index 0000000000..8e56d41b5c --- /dev/null +++ b/external/boringssl/crypto/pkcs8/p5_pbe.c @@ -0,0 +1,151 @@ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 1999. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include +#include +#include +#include +#include + +#include "internal.h" + + +/* PKCS#5 password based encryption structure */ + +ASN1_SEQUENCE(PBEPARAM) = { + ASN1_SIMPLE(PBEPARAM, salt, ASN1_OCTET_STRING), + ASN1_SIMPLE(PBEPARAM, iter, ASN1_INTEGER) +} ASN1_SEQUENCE_END(PBEPARAM) + +IMPLEMENT_ASN1_FUNCTIONS(PBEPARAM) + + +/* Set an algorithm identifier for a PKCS#5 PBE algorithm */ + +int PKCS5_pbe_set0_algor(X509_ALGOR *algor, int alg, int iter, + const unsigned char *salt, int saltlen) + { + PBEPARAM *pbe=NULL; + ASN1_STRING *pbe_str=NULL; + unsigned char *sstr; + + pbe = PBEPARAM_new(); + if (!pbe) + { + OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE); + goto err; + } + if(iter <= 0) + iter = PKCS5_DEFAULT_ITERATIONS; + if (!ASN1_INTEGER_set(pbe->iter, iter)) + { + OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE); + goto err; + } + if (!saltlen) + saltlen = PKCS5_SALT_LEN; + if (!ASN1_STRING_set(pbe->salt, NULL, saltlen)) + { + OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE); + goto err; + } + sstr = ASN1_STRING_data(pbe->salt); + if (salt) + memcpy(sstr, salt, saltlen); + else if (!RAND_bytes(sstr, saltlen)) + goto err; + + if(!ASN1_item_pack(pbe, ASN1_ITEM_rptr(PBEPARAM), &pbe_str)) + { + OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE); + goto err; + } + + PBEPARAM_free(pbe); + pbe = NULL; + + if (X509_ALGOR_set0(algor, OBJ_nid2obj(alg), V_ASN1_SEQUENCE, pbe_str)) + return 1; + +err: + if (pbe != NULL) + PBEPARAM_free(pbe); + if (pbe_str != NULL) + ASN1_STRING_free(pbe_str); + return 0; + } + +/* Return an algorithm identifier for a PKCS#5 PBE algorithm */ + +X509_ALGOR *PKCS5_pbe_set(int alg, int iter, + const unsigned char *salt, int saltlen) + { + X509_ALGOR *ret; + ret = X509_ALGOR_new(); + if (!ret) + { + OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE); + return NULL; + } + + if (PKCS5_pbe_set0_algor(ret, alg, iter, salt, saltlen)) + return ret; + + X509_ALGOR_free(ret); + return NULL; + } diff --git a/external/boringssl/crypto/pkcs8/p5_pbev2.c b/external/boringssl/crypto/pkcs8/p5_pbev2.c new file mode 100644 index 0000000000..3799b39bf0 --- /dev/null +++ b/external/boringssl/crypto/pkcs8/p5_pbev2.c @@ -0,0 +1,441 @@ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 1999-2004. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "internal.h" + + +/* PKCS#5 v2.0 password based encryption structures */ + +ASN1_SEQUENCE(PBE2PARAM) = { + ASN1_SIMPLE(PBE2PARAM, keyfunc, X509_ALGOR), + ASN1_SIMPLE(PBE2PARAM, encryption, X509_ALGOR) +} ASN1_SEQUENCE_END(PBE2PARAM) + +IMPLEMENT_ASN1_FUNCTIONS(PBE2PARAM) + +ASN1_SEQUENCE(PBKDF2PARAM) = { + ASN1_SIMPLE(PBKDF2PARAM, salt, ASN1_ANY), + ASN1_SIMPLE(PBKDF2PARAM, iter, ASN1_INTEGER), + ASN1_OPT(PBKDF2PARAM, keylength, ASN1_INTEGER), + ASN1_OPT(PBKDF2PARAM, prf, X509_ALGOR) +} ASN1_SEQUENCE_END(PBKDF2PARAM) + +IMPLEMENT_ASN1_FUNCTIONS(PBKDF2PARAM); + +static int ASN1_TYPE_set_octetstring(ASN1_TYPE *a, unsigned char *data, int len) + { + ASN1_STRING *os; + + if ((os=M_ASN1_OCTET_STRING_new()) == NULL) return(0); + if (!M_ASN1_OCTET_STRING_set(os,data,len)) + { + M_ASN1_OCTET_STRING_free(os); + return 0; + } + ASN1_TYPE_set(a,V_ASN1_OCTET_STRING,os); + return(1); + } + +static int param_to_asn1(EVP_CIPHER_CTX *c, ASN1_TYPE *type) + { + unsigned iv_len; + + iv_len = EVP_CIPHER_CTX_iv_length(c); + return ASN1_TYPE_set_octetstring(type, c->oiv, iv_len); + } + +/* Return an algorithm identifier for a PKCS#5 v2.0 PBE algorithm: + * yes I know this is horrible! + * + * Extended version to allow application supplied PRF NID and IV. */ + +X509_ALGOR *PKCS5_pbe2_set_iv(const EVP_CIPHER *cipher, int iter, + unsigned char *salt, int saltlen, + unsigned char *aiv, int prf_nid) +{ + X509_ALGOR *scheme = NULL, *kalg = NULL, *ret = NULL; + int alg_nid, keylen; + EVP_CIPHER_CTX ctx; + unsigned char iv[EVP_MAX_IV_LENGTH]; + PBE2PARAM *pbe2 = NULL; + const ASN1_OBJECT *obj; + + alg_nid = EVP_CIPHER_nid(cipher); + if(alg_nid == NID_undef) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER); + goto err; + } + obj = OBJ_nid2obj(alg_nid); + + if(!(pbe2 = PBE2PARAM_new())) goto merr; + + /* Setup the AlgorithmIdentifier for the encryption scheme */ + scheme = pbe2->encryption; + + scheme->algorithm = (ASN1_OBJECT*) obj; + if(!(scheme->parameter = ASN1_TYPE_new())) goto merr; + + /* Create random IV */ + if (EVP_CIPHER_iv_length(cipher)) + { + if (aiv) + memcpy(iv, aiv, EVP_CIPHER_iv_length(cipher)); + else if (!RAND_bytes(iv, EVP_CIPHER_iv_length(cipher))) + goto err; + } + + EVP_CIPHER_CTX_init(&ctx); + + /* Dummy cipherinit to just setup the IV, and PRF */ + if (!EVP_CipherInit_ex(&ctx, cipher, NULL, NULL, iv, 0)) + goto err; + if(param_to_asn1(&ctx, scheme->parameter) < 0) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_ERROR_SETTING_CIPHER_PARAMS); + EVP_CIPHER_CTX_cleanup(&ctx); + goto err; + } + /* If prf NID unspecified see if cipher has a preference. + * An error is OK here: just means use default PRF. + */ + if ((prf_nid == -1) && + EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_PBE_PRF_NID, 0, &prf_nid) <= 0) + { + ERR_clear_error(); + prf_nid = NID_hmacWithSHA1; + } + EVP_CIPHER_CTX_cleanup(&ctx); + + /* If its RC2 then we'd better setup the key length */ + + if(alg_nid == NID_rc2_cbc) + keylen = EVP_CIPHER_key_length(cipher); + else + keylen = -1; + + /* Setup keyfunc */ + + X509_ALGOR_free(pbe2->keyfunc); + + pbe2->keyfunc = PKCS5_pbkdf2_set(iter, salt, saltlen, prf_nid, keylen); + + if (!pbe2->keyfunc) + goto merr; + + /* Now set up top level AlgorithmIdentifier */ + + if(!(ret = X509_ALGOR_new())) goto merr; + if(!(ret->parameter = ASN1_TYPE_new())) goto merr; + + ret->algorithm = (ASN1_OBJECT*) OBJ_nid2obj(NID_pbes2); + + /* Encode PBE2PARAM into parameter */ + + if(!ASN1_item_pack(pbe2, ASN1_ITEM_rptr(PBE2PARAM), + &ret->parameter->value.sequence)) goto merr; + ret->parameter->type = V_ASN1_SEQUENCE; + + PBE2PARAM_free(pbe2); + pbe2 = NULL; + + return ret; + + merr: + OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE); + + err: + PBE2PARAM_free(pbe2); + /* Note 'scheme' is freed as part of pbe2 */ + X509_ALGOR_free(kalg); + X509_ALGOR_free(ret); + + return NULL; + +} + +X509_ALGOR *PKCS5_pbe2_set(const EVP_CIPHER *cipher, int iter, + unsigned char *salt, int saltlen) + { + return PKCS5_pbe2_set_iv(cipher, iter, salt, saltlen, NULL, -1); + } + +X509_ALGOR *PKCS5_pbkdf2_set(int iter, unsigned char *salt, int saltlen, + int prf_nid, int keylen) + { + X509_ALGOR *keyfunc = NULL; + PBKDF2PARAM *kdf = NULL; + ASN1_OCTET_STRING *osalt = NULL; + + if(!(kdf = PBKDF2PARAM_new())) + goto merr; + if(!(osalt = M_ASN1_OCTET_STRING_new())) + goto merr; + + kdf->salt->value.octet_string = osalt; + kdf->salt->type = V_ASN1_OCTET_STRING; + + if (!saltlen) + saltlen = PKCS5_SALT_LEN; + if (!(osalt->data = OPENSSL_malloc (saltlen))) + goto merr; + + osalt->length = saltlen; + + if (salt) + memcpy (osalt->data, salt, saltlen); + else if (!RAND_bytes(osalt->data, saltlen)) + goto merr; + + if(iter <= 0) + iter = PKCS5_DEFAULT_ITERATIONS; + + if(!ASN1_INTEGER_set(kdf->iter, iter)) + goto merr; + + /* If have a key len set it up */ + + if(keylen > 0) + { + if(!(kdf->keylength = M_ASN1_INTEGER_new())) + goto merr; + if(!ASN1_INTEGER_set (kdf->keylength, keylen)) + goto merr; + } + + /* prf can stay NULL if we are using hmacWithSHA1 */ + if (prf_nid > 0 && prf_nid != NID_hmacWithSHA1) + { + kdf->prf = X509_ALGOR_new(); + if (!kdf->prf) + goto merr; + X509_ALGOR_set0(kdf->prf, OBJ_nid2obj(prf_nid), + V_ASN1_NULL, NULL); + } + + /* Finally setup the keyfunc structure */ + + keyfunc = X509_ALGOR_new(); + if (!keyfunc) + goto merr; + + keyfunc->algorithm = (ASN1_OBJECT*) OBJ_nid2obj(NID_id_pbkdf2); + + /* Encode PBKDF2PARAM into parameter of pbe2 */ + + if(!(keyfunc->parameter = ASN1_TYPE_new())) + goto merr; + + if(!ASN1_item_pack(kdf, ASN1_ITEM_rptr(PBKDF2PARAM), + &keyfunc->parameter->value.sequence)) + goto merr; + keyfunc->parameter->type = V_ASN1_SEQUENCE; + + PBKDF2PARAM_free(kdf); + return keyfunc; + + merr: + OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE); + PBKDF2PARAM_free(kdf); + X509_ALGOR_free(keyfunc); + return NULL; + } + +static int PKCS5_v2_PBKDF2_keyivgen(EVP_CIPHER_CTX *ctx, + const uint8_t *pass_raw, + size_t pass_raw_len, const ASN1_TYPE *param, + const ASN1_TYPE *iv, int enc) { + int rv = 0; + PBKDF2PARAM *pbkdf2param = NULL; + + if (EVP_CIPHER_CTX_cipher(ctx) == NULL) { + OPENSSL_PUT_ERROR(PKCS8, CIPHER_R_NO_CIPHER_SET); + goto err; + } + + /* Decode parameters. */ + if (param == NULL || param->type != V_ASN1_SEQUENCE) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR); + goto err; + } + + const uint8_t *pbuf = param->value.sequence->data; + int plen = param->value.sequence->length; + pbkdf2param = d2i_PBKDF2PARAM(NULL, &pbuf, plen); + if (pbkdf2param == NULL || pbuf != param->value.sequence->data + plen) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR); + goto err; + } + + /* Now check the parameters. */ + uint8_t key[EVP_MAX_KEY_LENGTH]; + const size_t key_len = EVP_CIPHER_CTX_key_length(ctx); + assert(key_len <= sizeof(key)); + + if (pbkdf2param->keylength != NULL && + ASN1_INTEGER_get(pbkdf2param->keylength) != (int) key_len) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNSUPPORTED_KEYLENGTH); + goto err; + } + + if (pbkdf2param->prf != NULL && + OBJ_obj2nid(pbkdf2param->prf->algorithm) != NID_hmacWithSHA1) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNSUPPORTED_PRF); + goto err; + } + + if (pbkdf2param->salt->type != V_ASN1_OCTET_STRING) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNSUPPORTED_SALT_TYPE); + goto err; + } + + if (pbkdf2param->iter->type != V_ASN1_INTEGER) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_ITERATION_COUNT); + goto err; + } + long iterations = ASN1_INTEGER_get(pbkdf2param->iter); + if (iterations <= 0 || + (sizeof(long) > sizeof(unsigned) && iterations > (long)UINT_MAX)) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_ITERATION_COUNT); + goto err; + } + + if (iv->type != V_ASN1_OCTET_STRING || iv->value.octet_string == NULL) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_ERROR_SETTING_CIPHER_PARAMS); + goto err; + } + + const size_t iv_len = EVP_CIPHER_CTX_iv_length(ctx); + if ((size_t) iv->value.octet_string->length != iv_len) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_ERROR_SETTING_CIPHER_PARAMS); + goto err; + } + + if (!PKCS5_PBKDF2_HMAC_SHA1((const char *) pass_raw, pass_raw_len, + pbkdf2param->salt->value.octet_string->data, + pbkdf2param->salt->value.octet_string->length, + iterations, key_len, key)) { + goto err; + } + + rv = EVP_CipherInit_ex(ctx, NULL /* cipher */, NULL /* engine */, key, + iv->value.octet_string->data, enc); + + err: + PBKDF2PARAM_free(pbkdf2param); + return rv; +} + +int PKCS5_v2_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const uint8_t *pass_raw, + size_t pass_raw_len, ASN1_TYPE *param, + const EVP_CIPHER *unused, const EVP_MD *unused2, + int enc) { + PBE2PARAM *pbe2param = NULL; + int rv = 0; + + if (param == NULL || + param->type != V_ASN1_SEQUENCE || + param->value.sequence == NULL) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR); + goto err; + } + + const uint8_t *pbuf = param->value.sequence->data; + int plen = param->value.sequence->length; + pbe2param = d2i_PBE2PARAM(NULL, &pbuf, plen); + if (pbe2param == NULL || pbuf != param->value.sequence->data + plen) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR); + goto err; + } + + /* Check that the key derivation function is PBKDF2. */ + if (OBJ_obj2nid(pbe2param->keyfunc->algorithm) != NID_id_pbkdf2) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION); + goto err; + } + + /* See if we recognise the encryption algorithm. */ + const EVP_CIPHER *cipher = + EVP_get_cipherbynid(OBJ_obj2nid(pbe2param->encryption->algorithm)); + if (cipher == NULL) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNSUPPORTED_CIPHER); + goto err; + } + + /* Fixup cipher based on AlgorithmIdentifier. */ + if (!EVP_CipherInit_ex(ctx, cipher, NULL /* engine */, NULL /* key */, + NULL /* iv */, enc)) { + goto err; + } + + rv = PKCS5_v2_PBKDF2_keyivgen(ctx, pass_raw, pass_raw_len, + pbe2param->keyfunc->parameter, + pbe2param->encryption->parameter, enc); + + err: + PBE2PARAM_free(pbe2param); + return rv; +} diff --git a/external/boringssl/crypto/pkcs8/p8_pkey.c b/external/boringssl/crypto/pkcs8/p8_pkey.c new file mode 100644 index 0000000000..c69d0face2 --- /dev/null +++ b/external/boringssl/crypto/pkcs8/p8_pkey.c @@ -0,0 +1,85 @@ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 1999. + */ +/* ==================================================================== + * Copyright (c) 1999-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + + +#include + +#include +#include +#include + +/* Minor tweak to operation: zero private key data */ +static int pkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, + void *exarg) { + /* Since the structure must still be valid use ASN1_OP_FREE_PRE */ + if (operation == ASN1_OP_FREE_PRE) { + PKCS8_PRIV_KEY_INFO *key = (PKCS8_PRIV_KEY_INFO *)*pval; + if (key->pkey && key->pkey->type == V_ASN1_OCTET_STRING && + key->pkey->value.octet_string) { + OPENSSL_cleanse(key->pkey->value.octet_string->data, + key->pkey->value.octet_string->length); + } + } + return 1; +} + +ASN1_SEQUENCE_cb(PKCS8_PRIV_KEY_INFO, pkey_cb) = { + ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, version, ASN1_INTEGER), + ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, pkeyalg, X509_ALGOR), + ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, pkey, ASN1_ANY), + ASN1_IMP_SET_OF_OPT(PKCS8_PRIV_KEY_INFO, attributes, X509_ATTRIBUTE, 0) +} ASN1_SEQUENCE_END_cb(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO); + +IMPLEMENT_ASN1_FUNCTIONS(PKCS8_PRIV_KEY_INFO); diff --git a/external/boringssl/crypto/pkcs8/pkcs12_test.cc b/external/boringssl/crypto/pkcs8/pkcs12_test.cc new file mode 100644 index 0000000000..17bcd27372 --- /dev/null +++ b/external/boringssl/crypto/pkcs8/pkcs12_test.cc @@ -0,0 +1,770 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../test/scoped_types.h" + + +/* kPKCS12DER contains sample PKCS#12 data generated by OpenSSL with: + * openssl pkcs12 -export -inkey key.pem -in cacert.pem */ +static const uint8_t kOpenSSL[] = { + 0x30, 0x82, 0x09, 0xa1, 0x02, 0x01, 0x03, 0x30, 0x82, 0x09, 0x67, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x82, + 0x09, 0x58, 0x04, 0x82, 0x09, 0x54, 0x30, 0x82, 0x09, 0x50, 0x30, 0x82, + 0x04, 0x07, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, + 0x06, 0xa0, 0x82, 0x03, 0xf8, 0x30, 0x82, 0x03, 0xf4, 0x02, 0x01, 0x00, + 0x30, 0x82, 0x03, 0xed, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x07, 0x01, 0x30, 0x1c, 0x06, 0x0a, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x0c, 0x01, 0x06, 0x30, 0x0e, 0x04, 0x08, 0x31, 0x24, 0xca, + 0x7d, 0xc3, 0x25, 0x3e, 0xdc, 0x02, 0x02, 0x08, 0x00, 0x80, 0x82, 0x03, + 0xc0, 0x55, 0xe7, 0x7f, 0x9c, 0xd6, 0x0c, 0xd2, 0x69, 0x1d, 0x6e, 0x8b, + 0xb8, 0x07, 0xec, 0x4a, 0xe7, 0x06, 0x67, 0xd1, 0x24, 0x1b, 0xd5, 0x68, + 0x13, 0x3d, 0xd7, 0x56, 0x5e, 0x15, 0x40, 0xdb, 0xda, 0x88, 0x36, 0xc9, + 0x02, 0x96, 0xb5, 0xb5, 0xf7, 0x81, 0xef, 0x88, 0x1d, 0x66, 0x62, 0xa8, + 0x83, 0xf7, 0x91, 0xb1, 0x26, 0x1f, 0x9b, 0x25, 0x78, 0x0a, 0x04, 0xb1, + 0xc0, 0x93, 0x48, 0xa2, 0xf0, 0x51, 0x4f, 0x2b, 0xf8, 0x03, 0x67, 0x61, + 0x1b, 0xed, 0x29, 0xfe, 0x3f, 0xdd, 0x83, 0xa3, 0x93, 0x75, 0xa7, 0xd9, + 0x37, 0x5b, 0xa7, 0xc9, 0xf4, 0x52, 0x86, 0xd2, 0x3f, 0xca, 0x61, 0x5c, + 0x1e, 0xf9, 0x07, 0x7d, 0xbd, 0xda, 0x76, 0x8a, 0x03, 0x8e, 0x12, 0x4e, + 0x8f, 0x68, 0x6e, 0x72, 0x6e, 0xf0, 0xbe, 0x22, 0xc7, 0x9d, 0x97, 0x7c, + 0x45, 0xc0, 0xaa, 0x31, 0xe1, 0x55, 0x81, 0xb3, 0xec, 0x98, 0x94, 0xac, + 0xf7, 0x15, 0x9b, 0x42, 0x49, 0x8c, 0x2a, 0x29, 0x7a, 0x25, 0x92, 0x64, + 0x92, 0xbd, 0x4e, 0x5c, 0xec, 0xff, 0x61, 0xbb, 0x8e, 0x5c, 0xc8, 0xdb, + 0xba, 0x97, 0x30, 0xf4, 0x55, 0x9e, 0x1b, 0xfa, 0xbe, 0x2a, 0x90, 0xcf, + 0xe8, 0xc0, 0x9d, 0xb0, 0x0e, 0x24, 0x61, 0xe7, 0x3a, 0xb7, 0x7f, 0xda, + 0x63, 0xaa, 0x2a, 0x4a, 0xa6, 0x91, 0x52, 0xa6, 0x76, 0xc9, 0xbe, 0x9f, + 0x1b, 0x1d, 0xa4, 0x09, 0x5b, 0x0f, 0xd1, 0x64, 0x4e, 0xdf, 0x0c, 0x44, + 0x59, 0x3a, 0xef, 0x9a, 0xd8, 0x22, 0xa2, 0x5f, 0x80, 0xb5, 0x4f, 0xbe, + 0x84, 0x23, 0xe3, 0x74, 0x77, 0x3c, 0x9e, 0x27, 0x64, 0xac, 0x65, 0xf4, + 0xbb, 0x34, 0xb7, 0xa4, 0xfe, 0x02, 0x1a, 0x88, 0x05, 0x3b, 0x4b, 0xb8, + 0xd8, 0xb9, 0x26, 0x69, 0x22, 0x97, 0x3d, 0x93, 0x9b, 0xe8, 0x72, 0xaa, + 0x4d, 0x8f, 0x76, 0x51, 0x12, 0x59, 0x58, 0xf1, 0x1a, 0xa3, 0xdb, 0x5d, + 0xbc, 0xea, 0x84, 0x19, 0x55, 0x4f, 0x00, 0xfb, 0xe2, 0x57, 0x47, 0xca, + 0xea, 0xbe, 0x8f, 0x85, 0x8b, 0x1c, 0x27, 0x8d, 0x81, 0x70, 0x7f, 0xf1, + 0x56, 0x58, 0xe1, 0x26, 0x94, 0xd8, 0x2f, 0xde, 0xac, 0xc8, 0xac, 0xbf, + 0xc3, 0xc6, 0x67, 0xa6, 0xf4, 0x6c, 0xec, 0x20, 0x3c, 0xbc, 0x9d, 0xd9, + 0xd0, 0xa1, 0x4e, 0x8c, 0x11, 0x19, 0x2b, 0xb3, 0xa1, 0xdf, 0x6a, 0x8f, + 0xa2, 0xc3, 0xcc, 0xf6, 0xbd, 0x09, 0x7a, 0x96, 0x61, 0x20, 0xd4, 0x06, + 0x99, 0x4c, 0x6f, 0x23, 0x9b, 0x4c, 0xcc, 0x73, 0x8b, 0x42, 0x48, 0x99, + 0x45, 0x8f, 0xcb, 0xc8, 0x46, 0x1a, 0xfb, 0x51, 0x03, 0x6a, 0xf2, 0x22, + 0x85, 0x88, 0x9d, 0x61, 0x8b, 0x16, 0x33, 0xf4, 0xf7, 0x9b, 0xc8, 0x21, + 0x4f, 0xb1, 0xcd, 0x30, 0xfc, 0x29, 0x88, 0x12, 0xdc, 0xd4, 0x30, 0x4c, + 0xb9, 0xad, 0x34, 0xde, 0x01, 0xf8, 0xc1, 0x12, 0xa7, 0x4d, 0xc7, 0x31, + 0x99, 0x2b, 0x45, 0x88, 0x06, 0x34, 0x69, 0x6e, 0x6d, 0x34, 0xd8, 0xdd, + 0x0a, 0x3d, 0x59, 0x74, 0x36, 0x31, 0x6a, 0xed, 0x91, 0x3b, 0x5b, 0x88, + 0x43, 0x46, 0x3f, 0x67, 0x66, 0xe4, 0xde, 0x52, 0xb4, 0xbf, 0x7b, 0x3d, + 0x54, 0x79, 0xaf, 0x8d, 0xf5, 0x0a, 0x80, 0xfd, 0xeb, 0x31, 0x24, 0xbc, + 0x24, 0xd7, 0x21, 0x9f, 0x87, 0xab, 0xbd, 0x75, 0x2c, 0x13, 0x13, 0x96, + 0xab, 0x76, 0xfb, 0xb2, 0x44, 0xd0, 0xd2, 0x19, 0xf1, 0x95, 0x9a, 0x91, + 0xbf, 0x7a, 0x7b, 0x76, 0x95, 0x72, 0xa9, 0x16, 0xfc, 0x3e, 0xa9, 0x4e, + 0x01, 0x15, 0x3d, 0x43, 0x73, 0xa3, 0x8b, 0xef, 0x48, 0xad, 0x11, 0xbd, + 0x53, 0xd3, 0x0c, 0x15, 0x15, 0x1a, 0xb4, 0x3a, 0xe0, 0x7f, 0x9a, 0xa1, + 0x36, 0x47, 0x72, 0x92, 0xf0, 0xdf, 0xb0, 0xe2, 0xbc, 0x35, 0xd4, 0x32, + 0x6b, 0x37, 0x69, 0x4f, 0x47, 0x9a, 0xe2, 0x35, 0x8a, 0x31, 0x60, 0xed, + 0x80, 0x57, 0xe2, 0x9d, 0x58, 0x9c, 0x7f, 0x46, 0xd2, 0x54, 0x0e, 0x28, + 0x53, 0x8b, 0x1f, 0x46, 0x34, 0x22, 0xac, 0x71, 0xc7, 0xca, 0x0f, 0xb4, + 0xb7, 0x7a, 0xfc, 0x34, 0x57, 0xa5, 0x86, 0x8d, 0x66, 0x5c, 0xc7, 0x3a, + 0xdb, 0xf8, 0x79, 0x3a, 0x8a, 0xf6, 0xa2, 0x1e, 0x09, 0xc9, 0x10, 0xe9, + 0x93, 0x3a, 0xc5, 0xed, 0xb2, 0xca, 0xbb, 0x66, 0xf1, 0x9d, 0xc9, 0x9c, + 0x42, 0x75, 0x64, 0x3e, 0xe4, 0x12, 0x2b, 0x67, 0xf8, 0xbf, 0x2b, 0x98, + 0x5d, 0xb6, 0xa0, 0xba, 0x79, 0x98, 0xe0, 0x47, 0x5c, 0x77, 0x85, 0x4e, + 0x26, 0x71, 0xfe, 0xab, 0x5c, 0xa8, 0x32, 0x93, 0xec, 0xd0, 0x26, 0x90, + 0xe4, 0xda, 0x2f, 0x34, 0x8a, 0x50, 0xb8, 0x3b, 0x7b, 0x4c, 0x5f, 0xa9, + 0x3e, 0x8a, 0xa8, 0xf3, 0xc0, 0xb7, 0x50, 0x0b, 0x77, 0x4e, 0x8c, 0xa0, + 0xaf, 0xdb, 0x59, 0xe7, 0xac, 0xd1, 0x34, 0x4e, 0x62, 0x47, 0x2e, 0x1e, + 0x5e, 0xb4, 0xc9, 0x64, 0xf8, 0x0f, 0xf4, 0xf8, 0xb6, 0x9a, 0xe3, 0x7e, + 0xcf, 0xb7, 0xee, 0x11, 0x14, 0x52, 0x89, 0x3b, 0x27, 0x98, 0xfc, 0x95, + 0xa7, 0xad, 0xbf, 0x61, 0x34, 0xad, 0x1a, 0x24, 0x2a, 0x48, 0x66, 0x65, + 0x75, 0x9c, 0x59, 0xc0, 0x4f, 0x5f, 0x3d, 0x5a, 0x8c, 0xee, 0xd0, 0xb1, + 0x17, 0x6d, 0x34, 0x46, 0x37, 0xa0, 0xba, 0x71, 0xac, 0x77, 0x73, 0x29, + 0xa3, 0x37, 0x4f, 0x02, 0xd3, 0x7f, 0x0e, 0xe8, 0xce, 0xff, 0x80, 0x11, + 0x45, 0x42, 0x03, 0x5a, 0x87, 0xaa, 0xff, 0x25, 0x12, 0x1f, 0x43, 0x19, + 0x3e, 0xa9, 0x62, 0x96, 0x0c, 0x6f, 0x33, 0x88, 0x5c, 0xaa, 0xf9, 0xe2, + 0xb4, 0xb9, 0xf7, 0x55, 0xae, 0xb5, 0x76, 0x57, 0x47, 0x83, 0xe3, 0xfa, + 0x05, 0xda, 0x86, 0x02, 0x97, 0xb4, 0x60, 0xae, 0x59, 0xd5, 0x6c, 0xc1, + 0x33, 0xe1, 0x36, 0x36, 0x94, 0x79, 0x9e, 0xad, 0xa3, 0x2d, 0xbc, 0xb5, + 0xa2, 0xeb, 0xdd, 0xcd, 0xcb, 0x48, 0x42, 0x15, 0xb8, 0xe6, 0x0e, 0x76, + 0x5b, 0x57, 0x74, 0x24, 0xe6, 0x89, 0xc4, 0xe8, 0x08, 0xa9, 0xfe, 0xb3, + 0x23, 0xa6, 0xca, 0x72, 0xe2, 0xe4, 0xcb, 0xc1, 0x4a, 0xd1, 0x1d, 0xb9, + 0x5e, 0x36, 0x97, 0x19, 0x7c, 0x15, 0x48, 0xf1, 0x2d, 0xeb, 0xec, 0xad, + 0x52, 0x6f, 0x2f, 0xe1, 0x19, 0xcf, 0xcf, 0x98, 0x13, 0x0d, 0xcc, 0xb2, + 0xa6, 0x8a, 0xda, 0x93, 0x24, 0x3d, 0x5d, 0x83, 0xfe, 0x8d, 0x9e, 0x47, + 0xd8, 0x6e, 0x8d, 0x06, 0x52, 0x7d, 0x46, 0x84, 0x04, 0x69, 0x34, 0x61, + 0x04, 0x50, 0x1f, 0x86, 0x92, 0x94, 0xe9, 0x0b, 0x13, 0x5b, 0xf6, 0x16, + 0x81, 0xeb, 0xfa, 0xf1, 0xbb, 0x04, 0x68, 0x17, 0xca, 0x35, 0x6f, 0xba, + 0x4e, 0x4c, 0x33, 0xce, 0xf4, 0x26, 0xb7, 0x74, 0xab, 0xa5, 0xd0, 0xaa, + 0x0d, 0x85, 0x11, 0x30, 0x58, 0x62, 0xdf, 0x48, 0xc7, 0xdf, 0xc9, 0x38, + 0x9e, 0x6f, 0x96, 0x23, 0x2f, 0xc1, 0xd4, 0x8d, 0x65, 0x9b, 0x46, 0x5f, + 0x9c, 0xea, 0x26, 0x60, 0xb5, 0x95, 0x85, 0x71, 0x18, 0xc3, 0xf4, 0x54, + 0x61, 0xca, 0xfe, 0x55, 0x3b, 0xbe, 0x81, 0xaf, 0xd9, 0x3a, 0x27, 0xe9, + 0x1c, 0x30, 0x82, 0x05, 0x41, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x82, 0x05, 0x32, 0x04, 0x82, 0x05, 0x2e, + 0x30, 0x82, 0x05, 0x2a, 0x30, 0x82, 0x05, 0x26, 0x06, 0x0b, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x0a, 0x01, 0x02, 0xa0, 0x82, 0x04, + 0xee, 0x30, 0x82, 0x04, 0xea, 0x30, 0x1c, 0x06, 0x0a, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x01, 0x03, 0x30, 0x0e, 0x04, 0x08, 0xd9, + 0x68, 0xcb, 0x08, 0x16, 0xc8, 0x93, 0x57, 0x02, 0x02, 0x08, 0x00, 0x04, + 0x82, 0x04, 0xc8, 0x7c, 0xdb, 0xa6, 0x1e, 0x33, 0xa4, 0xc6, 0x4e, 0x13, + 0x22, 0x7a, 0x1f, 0xc6, 0x82, 0xab, 0x93, 0x5f, 0xf0, 0xa4, 0xe4, 0x40, + 0xac, 0xdf, 0x16, 0xec, 0x8d, 0x1f, 0xd9, 0xe4, 0x03, 0xd6, 0xc9, 0xc4, + 0x1d, 0xfd, 0xa3, 0xe3, 0xba, 0xfc, 0xcb, 0xd0, 0x47, 0x65, 0x0c, 0x6e, + 0x5d, 0xfc, 0xd2, 0xd4, 0x63, 0xa7, 0x93, 0xf6, 0x8a, 0x44, 0x8c, 0xfe, + 0x84, 0xd8, 0x0d, 0xa6, 0x16, 0x22, 0xe1, 0x65, 0x10, 0x5e, 0x18, 0x44, + 0x58, 0x2f, 0xc7, 0x64, 0x74, 0x5f, 0xcf, 0x73, 0x34, 0xe1, 0x4b, 0xe4, + 0xb3, 0x5b, 0xdb, 0x81, 0x4b, 0x1c, 0x38, 0x72, 0xa6, 0xc5, 0xeb, 0x56, + 0x9b, 0xc7, 0xe3, 0x3d, 0x54, 0x6e, 0x05, 0x2c, 0xd3, 0x57, 0xc9, 0x4f, + 0x80, 0x1e, 0xd7, 0xd8, 0x26, 0x6a, 0xcb, 0x79, 0x46, 0x70, 0xfc, 0x45, + 0xa7, 0x79, 0xab, 0x01, 0x03, 0xb6, 0xb1, 0x44, 0x41, 0xd9, 0x73, 0x37, + 0xaa, 0xd7, 0xf9, 0x44, 0x93, 0xaf, 0xbb, 0xb5, 0x77, 0xeb, 0x2b, 0x20, + 0x2e, 0xbd, 0xea, 0x2f, 0xde, 0xa6, 0x2f, 0xd6, 0xac, 0x74, 0xa5, 0x34, + 0xfb, 0xdf, 0xf7, 0x02, 0xa2, 0x20, 0x15, 0xc8, 0x61, 0x72, 0xbb, 0x7f, + 0x04, 0xf6, 0x0f, 0xf8, 0x7e, 0xc3, 0xe6, 0xab, 0x2a, 0xe6, 0xd8, 0xe1, + 0x0d, 0x5a, 0x3c, 0xc0, 0x58, 0xae, 0xf8, 0x1b, 0x15, 0x3c, 0x7b, 0x7f, + 0xf5, 0x9f, 0xec, 0xf7, 0x3f, 0x30, 0x4f, 0x3d, 0x6c, 0x44, 0xdd, 0x0e, + 0x4c, 0x2c, 0x93, 0x68, 0x43, 0x31, 0xa8, 0x97, 0x4b, 0xf6, 0x66, 0x71, + 0x2a, 0x52, 0x3e, 0x3a, 0xe6, 0x72, 0x8a, 0xe6, 0xe3, 0xc8, 0xff, 0x65, + 0x68, 0x1a, 0x46, 0x21, 0xb3, 0xf0, 0x46, 0x7c, 0x0c, 0x65, 0xd1, 0x8e, + 0xa4, 0x91, 0x11, 0x5c, 0x93, 0xeb, 0xeb, 0xae, 0x46, 0xf4, 0xbb, 0xf8, + 0xf3, 0x7e, 0x20, 0x30, 0xf8, 0xcd, 0x19, 0xcd, 0x54, 0x0a, 0x7f, 0x4f, + 0xe8, 0xac, 0xa9, 0xac, 0x72, 0x96, 0x80, 0x45, 0x2a, 0x4a, 0x63, 0x90, + 0x01, 0x19, 0xd0, 0x7e, 0x26, 0x53, 0x2d, 0xc4, 0x20, 0xa5, 0x1f, 0x89, + 0x67, 0x0f, 0xd9, 0x75, 0x51, 0x0a, 0xf1, 0xd4, 0xfd, 0x2e, 0xbe, 0xe6, + 0x94, 0x3b, 0x6c, 0x8c, 0xe3, 0x0f, 0x5f, 0xce, 0x58, 0x48, 0xde, 0x8d, + 0xeb, 0xd3, 0xe1, 0x0a, 0xcd, 0xdf, 0x34, 0x4d, 0xd1, 0x5b, 0xab, 0x41, + 0x41, 0x6b, 0xeb, 0xa1, 0x2f, 0x01, 0x4a, 0x72, 0x2e, 0xf4, 0x5e, 0x44, + 0x76, 0xc7, 0xe6, 0x16, 0xb9, 0xfb, 0x10, 0x37, 0x00, 0x2d, 0xc6, 0x3b, + 0x17, 0x72, 0x21, 0xdb, 0xac, 0x86, 0x7b, 0xf5, 0x70, 0x3f, 0x73, 0xa3, + 0xce, 0x0e, 0x20, 0xbb, 0x59, 0x4c, 0x23, 0xc2, 0xe8, 0x22, 0x22, 0xe0, + 0x02, 0x0d, 0xe4, 0xa2, 0x3f, 0x55, 0x9d, 0xc0, 0xeb, 0x9a, 0xc4, 0xf3, + 0xaa, 0xb8, 0xf1, 0x73, 0xec, 0x47, 0xe8, 0x2d, 0x6b, 0xa1, 0x40, 0x94, + 0xf6, 0x07, 0xb9, 0x6f, 0x03, 0x5a, 0x78, 0xe5, 0x59, 0x41, 0x1a, 0xc7, + 0xcd, 0x43, 0x10, 0x20, 0x28, 0x95, 0xe0, 0x2a, 0x6f, 0xf2, 0xf8, 0x12, + 0xd6, 0x13, 0x7f, 0x37, 0x3d, 0x38, 0xa7, 0x22, 0x91, 0xc6, 0xe3, 0x52, + 0xde, 0xd8, 0xbf, 0x78, 0x9a, 0xa4, 0xf7, 0xc0, 0x8c, 0xbf, 0x81, 0x28, + 0x20, 0xb8, 0x01, 0xde, 0xb5, 0x6b, 0x0a, 0x56, 0x12, 0x5c, 0x62, 0x1d, + 0xaf, 0xb7, 0xf2, 0x74, 0x66, 0x0a, 0x7a, 0xc4, 0x9f, 0x1e, 0xc2, 0xa8, + 0x4c, 0xd6, 0x76, 0x6d, 0x74, 0x35, 0x37, 0x12, 0x5c, 0x95, 0xee, 0x98, + 0x1d, 0xe2, 0x91, 0xde, 0x13, 0x08, 0xd0, 0x59, 0x4d, 0x62, 0x92, 0x69, + 0x1b, 0xf7, 0x21, 0x45, 0xaf, 0x83, 0xf8, 0x64, 0xf0, 0xfb, 0x92, 0x9d, + 0xa1, 0xd9, 0x61, 0x5e, 0x00, 0xc8, 0x1a, 0x6e, 0x6a, 0x2d, 0xad, 0xa8, + 0x1b, 0x0e, 0xaf, 0xea, 0xb2, 0xae, 0x1c, 0x89, 0xc7, 0x4d, 0x2c, 0x0f, + 0x4d, 0x8d, 0x78, 0x8d, 0x15, 0x9d, 0x4c, 0x90, 0x52, 0xa1, 0xa9, 0xd8, + 0xb2, 0x66, 0xb9, 0xb1, 0x46, 0x0a, 0x69, 0x86, 0x2b, 0x0f, 0xb2, 0x41, + 0xce, 0xe8, 0x8e, 0x49, 0x97, 0x08, 0x0b, 0x70, 0x97, 0xcb, 0xa4, 0x33, + 0x3f, 0x83, 0x6b, 0x6c, 0x17, 0xce, 0xd8, 0xd5, 0x9b, 0xd4, 0x55, 0x9b, + 0x99, 0xe1, 0xba, 0x61, 0x31, 0x36, 0x79, 0x31, 0x5f, 0xa1, 0x8c, 0xa9, + 0x77, 0x42, 0xaa, 0x8c, 0x45, 0x6e, 0xb6, 0x90, 0x08, 0xe8, 0x2e, 0xc4, + 0x72, 0x69, 0x42, 0xca, 0xa2, 0xd4, 0x8a, 0x2c, 0x37, 0xe1, 0xde, 0xb8, + 0x98, 0x36, 0xeb, 0xcc, 0x58, 0x0c, 0x24, 0xad, 0xab, 0x62, 0x44, 0x6d, + 0x80, 0xd5, 0xce, 0x2e, 0x4a, 0x3e, 0xa5, 0xc5, 0x34, 0xf8, 0x32, 0x26, + 0x2a, 0x56, 0xa4, 0xdd, 0xe9, 0x92, 0x06, 0xad, 0xe8, 0x85, 0x77, 0x6b, + 0xf1, 0x1b, 0xeb, 0xac, 0x77, 0x19, 0x1c, 0x6a, 0xb7, 0xef, 0x28, 0x70, + 0x87, 0x92, 0x33, 0xdd, 0xaa, 0x30, 0xc1, 0xa0, 0x93, 0x64, 0x18, 0xa2, + 0x91, 0x7f, 0xf7, 0xc4, 0xa5, 0x16, 0x93, 0xb3, 0x5b, 0xd8, 0x53, 0x28, + 0xc5, 0x5e, 0xb1, 0xce, 0x97, 0xbc, 0xb6, 0x65, 0xa8, 0x53, 0xcd, 0xf4, + 0x4d, 0x6b, 0xea, 0x6f, 0x6f, 0xa5, 0x1c, 0xf1, 0x0f, 0xcb, 0x04, 0x25, + 0x4a, 0xfe, 0x7d, 0xfc, 0xa3, 0xbd, 0x41, 0xd3, 0x96, 0x6a, 0x8b, 0xad, + 0xd4, 0xaa, 0x0a, 0x76, 0xea, 0x3b, 0xab, 0x39, 0x55, 0xa3, 0x89, 0x9f, + 0xf6, 0xf5, 0x9b, 0x9c, 0x83, 0xf8, 0x28, 0x50, 0xdf, 0x31, 0x74, 0x83, + 0xdb, 0xf1, 0x0f, 0x4c, 0x35, 0x6a, 0xe5, 0x64, 0x2e, 0xb9, 0x77, 0x3d, + 0xdd, 0xff, 0xa3, 0xa7, 0x90, 0x79, 0xc6, 0x5b, 0x01, 0x16, 0x38, 0xa8, + 0x22, 0xa3, 0x14, 0x13, 0xed, 0xd0, 0x89, 0x0d, 0x1f, 0x3a, 0x41, 0x4c, + 0x57, 0x79, 0xfc, 0x1d, 0xdf, 0xad, 0x1a, 0x11, 0x15, 0x31, 0x7e, 0xdb, + 0x99, 0x3a, 0x6c, 0xde, 0x94, 0x9a, 0x45, 0x4c, 0xfb, 0xa5, 0xa5, 0x31, + 0xee, 0xe3, 0x09, 0x13, 0x6d, 0xfd, 0x19, 0x37, 0x3f, 0xf6, 0xed, 0x8f, + 0x0c, 0xce, 0x4b, 0xd1, 0xe1, 0x3d, 0xfb, 0x85, 0x00, 0x84, 0x19, 0xeb, + 0xa2, 0x63, 0x1d, 0x2b, 0x2d, 0x21, 0xee, 0x08, 0x5a, 0x6d, 0xb0, 0xb1, + 0xd6, 0x81, 0x00, 0xb6, 0xd0, 0x09, 0x90, 0xb4, 0x84, 0x17, 0xd9, 0x2a, + 0x3c, 0x1d, 0x53, 0xc6, 0xc1, 0x8b, 0xda, 0xae, 0x0c, 0x0a, 0x3e, 0x1c, + 0x8a, 0xc4, 0xd6, 0x97, 0x5d, 0x48, 0xe7, 0x79, 0x80, 0x78, 0xaa, 0xde, + 0x17, 0x60, 0x5d, 0x28, 0x15, 0x3a, 0x42, 0xb7, 0x85, 0xc8, 0x60, 0x93, + 0x28, 0xb0, 0x4e, 0xc9, 0xf7, 0x46, 0xe7, 0xfc, 0x4e, 0x9f, 0x9f, 0x12, + 0xdf, 0xcb, 0x6e, 0x0c, 0xaf, 0x71, 0xda, 0xb7, 0xec, 0x3d, 0x46, 0xf3, + 0x35, 0x41, 0x42, 0xd8, 0x27, 0x92, 0x99, 0x1c, 0x4d, 0xc9, 0x3c, 0xe9, + 0x0e, 0xcb, 0x3f, 0x57, 0x65, 0x77, 0x0d, 0xdd, 0xff, 0xea, 0x70, 0x35, + 0xcc, 0xf5, 0x38, 0x1b, 0x57, 0xdf, 0x6d, 0xcb, 0xfd, 0x13, 0x39, 0xd6, + 0x04, 0xe2, 0xf1, 0xc2, 0xd9, 0xea, 0x8c, 0x9f, 0xfb, 0xb5, 0xfc, 0xe6, + 0xa9, 0xaa, 0x0f, 0x43, 0xc9, 0x9c, 0x91, 0xe4, 0x21, 0xaf, 0x37, 0x14, + 0x78, 0x46, 0xe1, 0x29, 0x41, 0x0c, 0x4e, 0xf5, 0x93, 0x1d, 0xf8, 0x33, + 0x47, 0x6f, 0x9d, 0x8b, 0xf3, 0x27, 0xd4, 0xbb, 0xf6, 0xae, 0xfa, 0xa5, + 0x8b, 0x41, 0x8f, 0xb4, 0xd7, 0x2f, 0xc1, 0x27, 0xea, 0x70, 0x55, 0x1d, + 0xe2, 0xd8, 0x0c, 0x4a, 0x5e, 0x7c, 0x87, 0xa4, 0x0e, 0x84, 0x07, 0xd3, + 0x38, 0x67, 0x2c, 0x55, 0x11, 0xfd, 0x1e, 0xda, 0x4d, 0x66, 0x01, 0x12, + 0x0c, 0x1b, 0x7c, 0x7c, 0x5c, 0x82, 0x21, 0x35, 0x65, 0x5c, 0x7a, 0xd2, + 0x66, 0xc2, 0x2b, 0x5e, 0xb8, 0xb1, 0xcb, 0xdf, 0x59, 0xc9, 0x31, 0xb7, + 0x17, 0x26, 0x96, 0x5e, 0x6f, 0x1c, 0x62, 0x3d, 0x8d, 0x88, 0xf1, 0xd1, + 0x01, 0x3e, 0xf9, 0x6f, 0xb9, 0x77, 0xdc, 0xee, 0xee, 0x78, 0x59, 0xef, + 0xcf, 0x3a, 0x87, 0x88, 0xa2, 0xea, 0xfd, 0x0a, 0xa9, 0xa9, 0x3e, 0x0c, + 0xf8, 0x7f, 0x97, 0x32, 0x17, 0xc2, 0x97, 0xcb, 0xa4, 0x9b, 0xae, 0x5d, + 0xe7, 0x39, 0x2b, 0x2b, 0xa8, 0xe6, 0x7b, 0x51, 0x75, 0x1f, 0x53, 0x54, + 0x37, 0xf4, 0x00, 0xa4, 0xb0, 0xa0, 0x93, 0xb4, 0x33, 0xe7, 0xae, 0x28, + 0xc0, 0x2d, 0x3a, 0xb3, 0xaa, 0xd7, 0x3c, 0x76, 0x44, 0x4b, 0xbb, 0x6a, + 0x67, 0x98, 0xce, 0xf8, 0x15, 0x13, 0x67, 0x79, 0x3c, 0x15, 0x09, 0xb7, + 0x22, 0xc0, 0xec, 0x07, 0x8a, 0xfd, 0x44, 0xcb, 0x99, 0xbd, 0xdc, 0xd5, + 0x53, 0x4c, 0x97, 0x1b, 0x46, 0xaf, 0xc0, 0x6c, 0x06, 0x01, 0x93, 0x8a, + 0x50, 0x51, 0x6a, 0xe4, 0x5c, 0x0a, 0x52, 0x81, 0x3b, 0x75, 0xed, 0xa2, + 0x97, 0xa6, 0x5c, 0x55, 0x63, 0xee, 0xfb, 0x33, 0x82, 0x10, 0xa8, 0x21, + 0x1a, 0x8d, 0xc8, 0xe1, 0x52, 0x68, 0x38, 0x88, 0x2f, 0xae, 0x2b, 0x22, + 0x7a, 0x9b, 0x0c, 0x19, 0x73, 0x6f, 0x91, 0xc7, 0xfa, 0x95, 0x61, 0x28, + 0x74, 0x73, 0x70, 0x31, 0x25, 0x30, 0x23, 0x06, 0x09, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x15, 0x31, 0x16, 0x04, 0x14, 0x14, 0x74, + 0x2d, 0x52, 0x8e, 0x0d, 0x0c, 0x06, 0x6c, 0x32, 0x64, 0xd3, 0x7e, 0x33, + 0x31, 0x68, 0x8b, 0x28, 0x1a, 0x75, 0x30, 0x31, 0x30, 0x21, 0x30, 0x09, + 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14, 0x22, + 0x8e, 0xff, 0x5a, 0x78, 0xec, 0x2c, 0x21, 0xa2, 0x48, 0xb7, 0x63, 0x88, + 0x10, 0x47, 0x1c, 0xc0, 0xd3, 0xec, 0x5a, 0x04, 0x08, 0xb3, 0x2e, 0x21, + 0xfd, 0x82, 0x14, 0xd8, 0x5c, 0x02, 0x02, 0x08, 0x00, +}; + +/* kNSS is the result of importing the OpenSSL example PKCS#12 into Chrome and + * then exporting it again. */ +static const uint8_t kNSS[] = { + 0x30, 0x80, 0x02, 0x01, 0x03, 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x80, 0x24, 0x80, 0x04, 0x82, + 0x09, 0xef, 0x30, 0x80, 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x80, 0x24, 0x80, 0x04, 0x82, 0x05, + 0x77, 0x30, 0x82, 0x05, 0x73, 0x30, 0x82, 0x05, 0x6f, 0x06, 0x0b, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x0a, 0x01, 0x02, 0xa0, 0x82, + 0x04, 0xf6, 0x30, 0x82, 0x04, 0xf2, 0x30, 0x24, 0x06, 0x0a, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x01, 0x03, 0x30, 0x16, 0x04, 0x10, + 0xac, 0x71, 0x8a, 0x7c, 0x89, 0xcf, 0xa8, 0xb0, 0xd6, 0xd1, 0x07, 0xf0, + 0x83, 0x4f, 0x7a, 0xd0, 0x02, 0x02, 0x07, 0xd0, 0x04, 0x82, 0x04, 0xc8, + 0xea, 0x51, 0x2c, 0x61, 0xaa, 0x9d, 0xf3, 0x90, 0xe1, 0x38, 0x45, 0xb0, + 0x5f, 0xfd, 0xe2, 0x04, 0x65, 0xe6, 0xff, 0x87, 0xb6, 0x78, 0x69, 0xb0, + 0xcb, 0x14, 0xe9, 0x99, 0x39, 0xe3, 0xe5, 0x70, 0x84, 0x57, 0x68, 0xf7, + 0x28, 0xb9, 0x75, 0xa6, 0xfb, 0x16, 0x72, 0xe1, 0x34, 0xb8, 0x3b, 0x61, + 0x51, 0x89, 0x18, 0x94, 0x40, 0xef, 0x73, 0xda, 0xdb, 0xd7, 0xb7, 0x44, + 0x73, 0x8f, 0x16, 0x84, 0xa2, 0x99, 0xa6, 0x05, 0x5e, 0x74, 0xae, 0xe2, + 0xcf, 0x3e, 0x99, 0xca, 0xcd, 0x76, 0x36, 0x77, 0x59, 0xec, 0x25, 0x59, + 0x3d, 0x4b, 0x45, 0xa5, 0x4e, 0x7b, 0x7a, 0xc9, 0x8b, 0xde, 0x4f, 0x70, + 0x6d, 0xb1, 0xa8, 0xf3, 0xb6, 0xb5, 0xe7, 0x67, 0x3f, 0xe9, 0x64, 0xb8, + 0x49, 0xf4, 0x11, 0x94, 0x9d, 0x1c, 0xb0, 0xa5, 0xfb, 0xb3, 0x61, 0xd4, + 0xf3, 0xa7, 0x68, 0x66, 0xd7, 0xa4, 0xf0, 0xcd, 0xc8, 0x40, 0x4f, 0x3e, + 0xa7, 0x26, 0x40, 0x76, 0x64, 0xa1, 0x4e, 0xf1, 0x91, 0xc2, 0xa3, 0xef, + 0xbc, 0xcd, 0x42, 0xe5, 0xd2, 0x6f, 0xff, 0xfe, 0x4d, 0x33, 0x01, 0xb4, + 0x99, 0x63, 0x1b, 0xd3, 0x01, 0x55, 0x00, 0xa6, 0x23, 0x9b, 0xa9, 0x17, + 0x09, 0x38, 0x32, 0x18, 0x36, 0xbc, 0x20, 0x02, 0xfe, 0x7b, 0xec, 0xd3, + 0x4c, 0x7d, 0xc9, 0xc9, 0xce, 0x66, 0x3b, 0x34, 0x6e, 0xea, 0xf9, 0xb1, + 0x1a, 0x83, 0xa3, 0x3c, 0x8d, 0xc7, 0x79, 0xc9, 0xff, 0x6b, 0x1d, 0x35, + 0xf6, 0x2a, 0x3d, 0x3b, 0x83, 0x16, 0x64, 0xcf, 0x9f, 0x7c, 0x31, 0x02, + 0xda, 0x37, 0x1a, 0x16, 0x49, 0xdc, 0xd9, 0x70, 0xae, 0x99, 0x2c, 0xc7, + 0x01, 0xba, 0x42, 0xab, 0xe9, 0x4d, 0xa4, 0x78, 0x2c, 0xbd, 0xa0, 0xf1, + 0xb7, 0xcf, 0xdd, 0xc1, 0xdb, 0x8f, 0x04, 0x87, 0x0b, 0x47, 0x4f, 0xd5, + 0xd5, 0xe7, 0xfc, 0x6e, 0x42, 0xd5, 0x91, 0x4d, 0x7b, 0x1b, 0x5c, 0x3c, + 0x02, 0x70, 0xdb, 0x05, 0x91, 0xaf, 0x35, 0x43, 0x05, 0xc2, 0x6d, 0xcf, + 0x59, 0x23, 0xfc, 0xc4, 0xf6, 0x67, 0xf1, 0x84, 0x61, 0x4a, 0xb6, 0x4c, + 0x15, 0x15, 0xa3, 0xea, 0x8f, 0x13, 0x15, 0xe3, 0xd2, 0xb5, 0x50, 0xc8, + 0xae, 0xc8, 0x5c, 0x03, 0xb5, 0x63, 0x93, 0xaa, 0x10, 0xd7, 0x56, 0x0d, + 0x6e, 0x13, 0x45, 0x8f, 0xec, 0x17, 0x5c, 0x5c, 0x73, 0x91, 0x5f, 0x6c, + 0xaf, 0x11, 0x13, 0x32, 0x5e, 0x14, 0xf9, 0xaf, 0xaf, 0x43, 0x04, 0x60, + 0x93, 0x42, 0x30, 0xa6, 0x75, 0xc0, 0x83, 0xd2, 0x4c, 0xa5, 0x0a, 0x16, + 0x39, 0xef, 0x3f, 0xf7, 0x9d, 0x23, 0x19, 0xb9, 0xcd, 0xd8, 0x7c, 0x6e, + 0xee, 0x6d, 0x2e, 0xff, 0x5a, 0xf3, 0xb9, 0xab, 0xe5, 0x64, 0xdc, 0xc2, + 0x67, 0x30, 0x73, 0x19, 0x2d, 0xea, 0xd2, 0x19, 0x1f, 0x1f, 0xe0, 0xd9, + 0xac, 0xc9, 0xdb, 0x38, 0x74, 0x5e, 0x31, 0x47, 0x2e, 0x9e, 0x2b, 0xcc, + 0xb9, 0xe4, 0x29, 0xf8, 0xb2, 0xbf, 0x1b, 0xbc, 0x68, 0x96, 0x79, 0xcf, + 0xaf, 0xf2, 0x1f, 0x57, 0x3f, 0x74, 0xc4, 0x71, 0x63, 0xb4, 0xe8, 0xbe, + 0x58, 0xdb, 0x28, 0x62, 0xb5, 0x79, 0x8b, 0xe4, 0xd0, 0x96, 0xd0, 0xda, + 0x0f, 0xd2, 0x70, 0x93, 0x2f, 0x71, 0xe0, 0x9f, 0x28, 0xb7, 0x52, 0x38, + 0x9c, 0xcb, 0x8b, 0x2a, 0x8e, 0xbf, 0x0e, 0x3d, 0x60, 0x05, 0x0a, 0x91, + 0x5b, 0xb5, 0x78, 0x10, 0x31, 0x00, 0x80, 0x31, 0x2d, 0xd7, 0xb0, 0x88, + 0xc7, 0xd9, 0x58, 0xc6, 0xfc, 0x3b, 0xf4, 0xee, 0xec, 0xba, 0x05, 0xae, + 0xae, 0xff, 0xcf, 0xd0, 0x71, 0xc6, 0xe7, 0xf3, 0x8b, 0x64, 0x50, 0x7a, + 0x09, 0x93, 0x0f, 0x34, 0x59, 0x2d, 0xde, 0x4b, 0x1d, 0x86, 0x49, 0xff, + 0x63, 0x76, 0x28, 0x6b, 0x52, 0x1b, 0x46, 0x06, 0x18, 0x90, 0x1c, 0x2d, + 0xc5, 0x03, 0xcc, 0x00, 0x4d, 0xb7, 0xb2, 0x12, 0xc5, 0xf9, 0xb4, 0xa4, + 0x6a, 0x36, 0x62, 0x46, 0x34, 0x2a, 0xf0, 0x11, 0xa3, 0xd6, 0x80, 0x21, + 0xbf, 0x3b, 0xfd, 0xc5, 0x25, 0xa0, 0x4d, 0xc0, 0x2e, 0xc0, 0xf1, 0x7b, + 0x96, 0x11, 0x64, 0x8e, 0xb9, 0xdb, 0x89, 0x4e, 0x33, 0x89, 0xf5, 0xc6, + 0xfc, 0x2b, 0x99, 0xf5, 0xc2, 0x04, 0x83, 0x15, 0x47, 0xa8, 0xa5, 0xc1, + 0x4a, 0xe4, 0x76, 0xab, 0x3e, 0xf0, 0x9b, 0xb7, 0x8d, 0x46, 0xd3, 0x52, + 0x9b, 0xbd, 0xfd, 0x2b, 0xba, 0x73, 0x5d, 0x23, 0x67, 0x68, 0xe1, 0x76, + 0x6f, 0x56, 0x2b, 0x17, 0xe4, 0x7e, 0x9a, 0xfd, 0x05, 0x48, 0x39, 0xc9, + 0xcf, 0xa5, 0x83, 0xf7, 0x90, 0x9c, 0xa4, 0x28, 0x57, 0x40, 0xe9, 0xd4, + 0x4b, 0x1a, 0x4b, 0x6f, 0x65, 0x14, 0xca, 0x43, 0xc1, 0x3f, 0x7c, 0xec, + 0x82, 0x47, 0x0e, 0x64, 0x8b, 0x6f, 0x8c, 0xb2, 0xf0, 0x6d, 0xeb, 0x6f, + 0x71, 0x8f, 0xcc, 0x2d, 0x60, 0x2b, 0xc3, 0x9f, 0x13, 0x94, 0xc7, 0x23, + 0x02, 0xf5, 0xe6, 0xdf, 0x2d, 0xa9, 0xdb, 0xa9, 0xf3, 0xee, 0xe9, 0x3f, + 0x2a, 0x69, 0x24, 0x6b, 0x78, 0xff, 0x6a, 0xd7, 0xe4, 0x69, 0x8c, 0x17, + 0xd5, 0xc1, 0x36, 0x1a, 0xca, 0x77, 0xb0, 0xb5, 0x6b, 0x96, 0x4a, 0xb5, + 0x0e, 0x4d, 0x0b, 0xd6, 0xd9, 0x78, 0xc5, 0xbf, 0xe3, 0x59, 0xfe, 0x63, + 0xe3, 0xd3, 0x3c, 0x9a, 0xfa, 0xd7, 0x69, 0x5b, 0xef, 0xd3, 0xa4, 0xa3, + 0xb9, 0x1f, 0x5c, 0x40, 0x20, 0x95, 0x38, 0x2d, 0xf5, 0x04, 0x0c, 0x2c, + 0x79, 0x77, 0xc1, 0xb6, 0xcc, 0x74, 0x3c, 0x66, 0xf1, 0xc6, 0x65, 0xab, + 0x4d, 0x68, 0x41, 0x16, 0x71, 0x51, 0xb9, 0x1b, 0xcb, 0xa7, 0x6d, 0xe0, + 0x70, 0xa9, 0xfa, 0x65, 0x6b, 0x7b, 0x1e, 0xc5, 0xdf, 0xe2, 0x4c, 0x96, + 0x44, 0x6b, 0x24, 0xa1, 0x15, 0x8e, 0xe7, 0x9b, 0x1f, 0x51, 0xef, 0xd7, + 0x65, 0x5f, 0xcd, 0x74, 0x7f, 0x2d, 0x5c, 0xba, 0xba, 0x20, 0x32, 0x8d, + 0x1c, 0xf1, 0x5a, 0xed, 0x21, 0xad, 0x78, 0x7b, 0x59, 0x58, 0xe4, 0xf6, + 0xa7, 0x10, 0x35, 0xca, 0x5d, 0x86, 0x1a, 0x68, 0xba, 0x1c, 0x3c, 0x1c, + 0x23, 0x79, 0x8b, 0x9f, 0xda, 0x5c, 0xd1, 0x5a, 0xa9, 0xc8, 0xf6, 0xc9, + 0xdf, 0x21, 0x5a, 0x98, 0xdc, 0xf4, 0xb9, 0x02, 0x97, 0x2c, 0x10, 0x60, + 0xc9, 0xb5, 0xea, 0x75, 0x0b, 0xd9, 0x8a, 0xa4, 0x86, 0x92, 0xbe, 0xf5, + 0xd8, 0xc7, 0x6b, 0x13, 0x8b, 0xbb, 0xca, 0x5f, 0xe4, 0x8b, 0xce, 0xb5, + 0x27, 0xae, 0x53, 0xed, 0xef, 0x37, 0xa6, 0x81, 0x8f, 0x70, 0x25, 0x18, + 0x93, 0x06, 0x8c, 0x18, 0xcd, 0x7a, 0x1a, 0x8d, 0xfc, 0xde, 0x6f, 0x30, + 0xdb, 0x41, 0xb6, 0x42, 0x14, 0x54, 0xf8, 0xcd, 0xc6, 0xf8, 0x0f, 0x82, + 0x17, 0xfa, 0x8d, 0xba, 0x80, 0x81, 0x6a, 0xf7, 0x02, 0x97, 0x00, 0x78, + 0xd6, 0x5b, 0xc9, 0xba, 0xd1, 0x99, 0xef, 0x8e, 0x48, 0x6c, 0x35, 0x10, + 0x5b, 0xf1, 0x9b, 0x93, 0x4f, 0xbd, 0x7d, 0x27, 0x9e, 0xc7, 0x86, 0xb2, + 0x8f, 0x6a, 0x91, 0x59, 0x2d, 0x14, 0xab, 0x1b, 0x34, 0x6e, 0xfa, 0x25, + 0x5e, 0x14, 0xc7, 0xef, 0x3d, 0x0f, 0x13, 0xf9, 0x45, 0x4b, 0x90, 0xbc, + 0xd8, 0x51, 0x42, 0x95, 0x25, 0x9b, 0x1b, 0x7c, 0xaf, 0x3b, 0x60, 0x21, + 0x4c, 0x5f, 0x7c, 0x63, 0x4b, 0x45, 0xa6, 0xdc, 0xfd, 0x32, 0xf3, 0x06, + 0x61, 0x11, 0x2d, 0x27, 0xde, 0x19, 0x38, 0x63, 0xf9, 0x70, 0xd1, 0x82, + 0x8e, 0xc7, 0x99, 0xe1, 0x96, 0x9b, 0x54, 0x93, 0x64, 0x5f, 0xd1, 0x62, + 0x9c, 0x37, 0x10, 0x1a, 0x8a, 0x82, 0x8d, 0x2a, 0x93, 0x95, 0x22, 0xc9, + 0x21, 0xf5, 0xce, 0x21, 0xbb, 0x7c, 0x17, 0xee, 0x20, 0xa0, 0x73, 0xaa, + 0x69, 0x78, 0x4e, 0x0d, 0x2c, 0x2c, 0x96, 0x23, 0xdc, 0x07, 0x16, 0xbd, + 0xe7, 0xd5, 0x49, 0xcc, 0x44, 0xd1, 0x9d, 0xd7, 0xa3, 0x01, 0x60, 0xa0, + 0xe0, 0x41, 0x63, 0x28, 0x8a, 0x43, 0xdb, 0x4f, 0x25, 0x5b, 0x27, 0x52, + 0x4a, 0xee, 0x42, 0x43, 0x9a, 0xef, 0x33, 0x43, 0x70, 0xda, 0x64, 0x57, + 0x49, 0x0c, 0x7f, 0xfd, 0xc7, 0x88, 0x26, 0x94, 0x10, 0xcc, 0x05, 0x1d, + 0x54, 0x95, 0xea, 0x4e, 0x65, 0x28, 0x03, 0xbc, 0xa2, 0x62, 0xd2, 0xce, + 0x60, 0x34, 0xf9, 0xdb, 0x26, 0xb5, 0xe6, 0x9b, 0x55, 0x2c, 0x8f, 0x30, + 0x3a, 0x94, 0x9a, 0x15, 0x79, 0x22, 0x75, 0x4d, 0x1b, 0x91, 0xe0, 0x5b, + 0xdb, 0xd1, 0x15, 0x7f, 0xcc, 0xc6, 0x88, 0xb5, 0x00, 0x3f, 0x5d, 0x84, + 0x2e, 0x68, 0xde, 0x6f, 0x41, 0x5b, 0x4e, 0xe7, 0xdf, 0xe6, 0x3b, 0x7e, + 0xf2, 0xdd, 0xfc, 0x01, 0xf2, 0x1b, 0x52, 0xba, 0xc4, 0x51, 0xae, 0x8f, + 0xa0, 0x55, 0x12, 0x81, 0x57, 0xe0, 0x58, 0x5e, 0xea, 0xd7, 0x85, 0xfb, + 0x19, 0x8b, 0xb7, 0x24, 0x29, 0x94, 0xa7, 0xfc, 0xed, 0x17, 0xaa, 0x32, + 0x50, 0x11, 0xb3, 0x7a, 0x43, 0x3a, 0xc0, 0x2b, 0x82, 0x9c, 0x85, 0xd9, + 0xd0, 0xdb, 0x21, 0x71, 0x83, 0xb4, 0x30, 0x14, 0xec, 0xfc, 0x8d, 0x32, + 0xd6, 0xa2, 0x36, 0x5e, 0x3b, 0xe9, 0x12, 0x0c, 0x95, 0xd6, 0x0c, 0x0c, + 0x31, 0x66, 0x30, 0x3f, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x09, 0x14, 0x31, 0x32, 0x1e, 0x30, 0x00, 0x49, 0x00, 0x6e, 0x00, + 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x6e, 0x00, 0x65, 0x00, 0x74, 0x00, + 0x20, 0x00, 0x57, 0x00, 0x69, 0x00, 0x64, 0x00, 0x67, 0x00, 0x69, 0x00, + 0x74, 0x00, 0x73, 0x00, 0x20, 0x00, 0x50, 0x00, 0x74, 0x00, 0x79, 0x00, + 0x20, 0x00, 0x4c, 0x00, 0x74, 0x00, 0x64, 0x30, 0x23, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x15, 0x31, 0x16, 0x04, 0x14, + 0x14, 0x74, 0x2d, 0x52, 0x8e, 0x0d, 0x0c, 0x06, 0x6c, 0x32, 0x64, 0xd3, + 0x7e, 0x33, 0x31, 0x68, 0x8b, 0x28, 0x1a, 0x75, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x07, 0x06, 0xa0, 0x80, 0x30, 0x80, 0x02, 0x01, 0x00, 0x30, 0x80, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0x30, + 0x24, 0x06, 0x0a, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x01, + 0x06, 0x30, 0x16, 0x04, 0x10, 0x9d, 0x1b, 0x68, 0x8e, 0x11, 0xc2, 0xb2, + 0xd6, 0xd0, 0xe9, 0x5a, 0x9e, 0x96, 0xc1, 0x8c, 0xa6, 0x02, 0x02, 0x07, + 0xd0, 0xa0, 0x80, 0x04, 0x82, 0x03, 0xf8, 0x1d, 0xce, 0x13, 0x70, 0x7a, + 0x6b, 0x0a, 0x12, 0x2d, 0x01, 0x84, 0x63, 0x5c, 0x07, 0x82, 0x23, 0xf8, + 0x8a, 0x5e, 0x53, 0x8f, 0xc8, 0xb4, 0x87, 0x1a, 0xa2, 0x98, 0xdb, 0xc6, + 0x26, 0xca, 0xbb, 0x20, 0x24, 0xad, 0xac, 0xdf, 0xbe, 0x73, 0x6d, 0x97, + 0x4b, 0x6e, 0x5b, 0x45, 0xd2, 0x84, 0xd4, 0xa4, 0x82, 0xd0, 0xce, 0x40, + 0x13, 0x4c, 0x6d, 0x4d, 0x2e, 0xc1, 0x96, 0x95, 0x01, 0x64, 0xf3, 0xf0, + 0x5f, 0x06, 0x06, 0xea, 0xf7, 0x84, 0x8f, 0xb3, 0xb0, 0x6e, 0x7c, 0x9b, + 0x71, 0x73, 0xb9, 0xcd, 0xac, 0x72, 0xf6, 0xa0, 0x23, 0xda, 0x9b, 0x9f, + 0xec, 0x16, 0xef, 0x33, 0xd4, 0xd0, 0x4d, 0x20, 0xf0, 0x75, 0xa9, 0x73, + 0xf4, 0x31, 0xc7, 0x57, 0xb8, 0x0d, 0x9d, 0x85, 0x7c, 0xee, 0x3a, 0x24, + 0x7b, 0x74, 0xa0, 0x5c, 0xad, 0xde, 0x5e, 0x05, 0x1e, 0xeb, 0x02, 0x78, + 0x12, 0xb4, 0xb9, 0xc6, 0xe5, 0xc5, 0x99, 0xbc, 0x05, 0x62, 0x5b, 0x10, + 0x52, 0x08, 0x00, 0x9e, 0x73, 0xac, 0xe4, 0x1d, 0xdb, 0xb8, 0xbf, 0x48, + 0x03, 0x28, 0x05, 0x3c, 0x61, 0x1a, 0x8b, 0x4c, 0xd7, 0x5f, 0x8c, 0xb4, + 0xcd, 0x91, 0x1c, 0x0b, 0xf4, 0x55, 0xd4, 0x1c, 0x42, 0x4a, 0xd4, 0xf5, + 0x15, 0x38, 0xd9, 0x06, 0xfc, 0x49, 0xf6, 0xe5, 0xa7, 0x09, 0x5d, 0x01, + 0xbd, 0xc3, 0xd1, 0x09, 0x9f, 0x5d, 0x0c, 0x19, 0x43, 0xd0, 0xfa, 0x25, + 0x17, 0xad, 0x2a, 0xbf, 0x89, 0x63, 0x06, 0xa8, 0x02, 0x03, 0xe4, 0xfe, + 0x19, 0x08, 0x70, 0xa1, 0x74, 0x74, 0xb6, 0xb6, 0x0f, 0x19, 0x4d, 0x54, + 0xa5, 0xb2, 0xd7, 0x37, 0x3b, 0x17, 0xc0, 0x5d, 0xc2, 0x8a, 0xf1, 0xcc, + 0xed, 0xef, 0x65, 0xc8, 0xca, 0xbe, 0x02, 0xd4, 0x9b, 0x1e, 0xef, 0xc9, + 0xe0, 0x91, 0x82, 0xb0, 0xe0, 0x50, 0xc7, 0xa0, 0xcc, 0x01, 0x6d, 0x55, + 0xe5, 0x67, 0x99, 0x65, 0x13, 0xe4, 0xd2, 0x90, 0x91, 0xf3, 0x76, 0x0b, + 0x6a, 0x2d, 0x19, 0xaf, 0x61, 0xb3, 0x7f, 0x4c, 0x04, 0xfe, 0x68, 0xf6, + 0xb3, 0x56, 0xd8, 0xf3, 0x34, 0xd7, 0x04, 0x0a, 0x31, 0xc8, 0x37, 0xdf, + 0xac, 0xd8, 0x91, 0x80, 0x8a, 0x30, 0x12, 0x22, 0x80, 0xd7, 0x24, 0xcf, + 0x70, 0xaf, 0x56, 0xaf, 0x81, 0xfe, 0x63, 0xf1, 0xea, 0x57, 0x4c, 0xf2, + 0xdb, 0x30, 0x50, 0x92, 0xc1, 0xeb, 0x04, 0x9a, 0xdf, 0xf5, 0x74, 0x57, + 0x5b, 0x58, 0xc2, 0x4e, 0x6b, 0x11, 0xf3, 0xe1, 0xb3, 0x0f, 0x56, 0x35, + 0x04, 0xf8, 0x50, 0x1d, 0x7e, 0xe6, 0x99, 0xa2, 0x48, 0xdb, 0xea, 0x62, + 0x4f, 0x98, 0xc2, 0xef, 0xbf, 0x7f, 0x94, 0xc0, 0x36, 0xc0, 0xf3, 0x27, + 0xfe, 0xe2, 0x17, 0x1e, 0x91, 0x7d, 0x96, 0xa9, 0x2b, 0x71, 0x51, 0xc3, + 0x59, 0x2d, 0x11, 0x50, 0x1e, 0xcb, 0xce, 0xff, 0x04, 0x4d, 0x16, 0xf5, + 0xc2, 0xd4, 0x1f, 0xdd, 0x7f, 0x5a, 0xfd, 0x1d, 0xe9, 0x63, 0x52, 0x44, + 0x76, 0x5f, 0x91, 0xfd, 0xe8, 0xdf, 0x0a, 0x69, 0x0d, 0xd3, 0x64, 0x91, + 0xea, 0xdd, 0x03, 0x4f, 0x42, 0xa5, 0xe9, 0xa1, 0x70, 0x05, 0xf3, 0x22, + 0x8e, 0xad, 0x70, 0x1a, 0x3e, 0x94, 0x42, 0x06, 0xe7, 0x47, 0x37, 0x3d, + 0xf5, 0xda, 0x3e, 0x2a, 0x3a, 0xc0, 0x23, 0xd9, 0x4a, 0x26, 0x69, 0x13, + 0xa6, 0x93, 0x7c, 0xf2, 0xaf, 0x04, 0x5e, 0x9b, 0x88, 0xc7, 0x77, 0xd0, + 0x93, 0xab, 0x1b, 0xbd, 0x3d, 0x69, 0x90, 0xab, 0x41, 0xa9, 0xbc, 0x84, + 0x18, 0x4d, 0x29, 0x02, 0xc1, 0xf8, 0xff, 0x63, 0x18, 0x24, 0x74, 0x8f, + 0x7e, 0x44, 0x33, 0xaf, 0x88, 0x8b, 0x93, 0x5b, 0x9a, 0xae, 0x6b, 0x08, + 0xa2, 0x82, 0x5d, 0xf3, 0xbe, 0x61, 0xc3, 0xf0, 0x2d, 0x31, 0x4c, 0xb5, + 0xb5, 0x91, 0x0f, 0xfa, 0x81, 0x61, 0xad, 0xfc, 0xba, 0x91, 0xeb, 0x3b, + 0x9d, 0x22, 0x41, 0x45, 0x0e, 0x8e, 0x24, 0xc7, 0x1c, 0x81, 0x95, 0xa8, + 0x7b, 0x64, 0xed, 0xa5, 0xec, 0x5a, 0x68, 0x3c, 0x85, 0x8d, 0x92, 0xb7, + 0x24, 0x0f, 0xed, 0xf5, 0xc6, 0x31, 0x61, 0xdc, 0xef, 0xa7, 0xcb, 0x8f, + 0xda, 0x43, 0x05, 0x42, 0xf6, 0x9e, 0xbc, 0x1b, 0x9a, 0xa1, 0xe8, 0x1d, + 0x8d, 0x42, 0xdb, 0x80, 0x83, 0x55, 0x52, 0x2b, 0x95, 0x00, 0x05, 0x82, + 0x84, 0xc3, 0x54, 0x23, 0x8e, 0x1d, 0x00, 0xa2, 0x16, 0x3e, 0xce, 0x3d, + 0xcc, 0x9e, 0xb8, 0x4c, 0x59, 0xb2, 0x12, 0xa2, 0x23, 0xc1, 0x46, 0x50, + 0x86, 0xae, 0x75, 0x7e, 0x49, 0x38, 0x77, 0x94, 0xf0, 0x27, 0xd8, 0x17, + 0x38, 0x8c, 0xe0, 0x73, 0x00, 0xfb, 0xaf, 0xbf, 0xe8, 0xed, 0x85, 0x58, + 0x3e, 0xb4, 0x88, 0x04, 0xc8, 0x22, 0x1b, 0xb4, 0x75, 0xa2, 0xc4, 0xdd, + 0x06, 0xd2, 0x83, 0x42, 0x21, 0x57, 0xfc, 0xd8, 0xae, 0x9c, 0x0e, 0xd8, + 0x6a, 0x70, 0xd1, 0xeb, 0x44, 0x9c, 0xb7, 0x37, 0x04, 0x05, 0xf5, 0x17, + 0xbe, 0xf3, 0x56, 0x1b, 0x06, 0x36, 0x1c, 0x59, 0x7b, 0x65, 0x8d, 0xbb, + 0xbe, 0x22, 0x9a, 0x70, 0xa3, 0xe9, 0x60, 0x1a, 0xc9, 0xdd, 0x81, 0x3c, + 0x2d, 0x4e, 0xc0, 0x8a, 0xe5, 0x91, 0xa7, 0xc1, 0x80, 0x07, 0x47, 0x7a, + 0x74, 0x4f, 0x3e, 0x4a, 0xdc, 0xb2, 0xcc, 0xff, 0x37, 0x66, 0x05, 0xcb, + 0xd6, 0xe9, 0x90, 0xf5, 0xef, 0x2b, 0x7e, 0xa7, 0x66, 0x51, 0xcb, 0x48, + 0xb3, 0x8a, 0x6f, 0x06, 0xba, 0x8b, 0x3d, 0x35, 0x36, 0xdf, 0x0e, 0x40, + 0xe5, 0xa1, 0xe3, 0xdd, 0x89, 0xab, 0x64, 0x9c, 0x01, 0x15, 0x9e, 0x93, + 0xea, 0xf9, 0x4f, 0x9e, 0xf5, 0x8b, 0xf2, 0xc2, 0xbb, 0xe5, 0xc3, 0xa3, + 0xe3, 0x13, 0x63, 0x4f, 0x7d, 0x20, 0xe4, 0x66, 0x96, 0x84, 0x8d, 0xd4, + 0xca, 0x72, 0x52, 0xdc, 0xb8, 0x93, 0xd4, 0xa5, 0x3e, 0x6e, 0x42, 0x56, + 0x80, 0x46, 0x77, 0x86, 0x49, 0xfe, 0xf3, 0xb4, 0x5b, 0x37, 0xfc, 0xb8, + 0x0c, 0xd7, 0x63, 0xac, 0x3c, 0x6f, 0xf0, 0xbe, 0xbe, 0xb4, 0x13, 0xe7, + 0x34, 0xe5, 0x06, 0xbf, 0x17, 0x48, 0x6e, 0xc0, 0x26, 0x94, 0xdd, 0xed, + 0xf4, 0xda, 0x97, 0x25, 0xab, 0xd6, 0x9b, 0xc3, 0x8c, 0xeb, 0x17, 0x09, + 0xfc, 0x03, 0x5a, 0x2f, 0x19, 0x85, 0x50, 0xc4, 0xe6, 0x35, 0x71, 0x94, + 0xad, 0xc5, 0xcf, 0x08, 0xcf, 0x69, 0x3b, 0xc3, 0x31, 0xec, 0xf1, 0xfa, + 0x80, 0x66, 0x8f, 0x14, 0xde, 0x56, 0x21, 0x12, 0x9b, 0x0c, 0xdf, 0x92, + 0x48, 0x06, 0xce, 0xdb, 0xeb, 0x28, 0x54, 0x27, 0x8b, 0xa9, 0xef, 0x0c, + 0xf4, 0xa0, 0xcc, 0x84, 0x59, 0x60, 0xed, 0x18, 0x65, 0xca, 0x67, 0x0c, + 0xd1, 0x1f, 0xcf, 0x59, 0x4b, 0xce, 0x07, 0x27, 0x08, 0x6a, 0xea, 0x53, + 0xdc, 0x47, 0xb3, 0x4e, 0xe4, 0x0b, 0xff, 0x9a, 0x7d, 0x6b, 0x0d, 0x2f, + 0x2d, 0x60, 0xd7, 0x8b, 0x22, 0xf5, 0x30, 0x43, 0x09, 0xe6, 0xdf, 0x01, + 0x03, 0x27, 0x2d, 0xb5, 0x74, 0x52, 0x5d, 0x08, 0xc7, 0x5a, 0x44, 0x25, + 0x0f, 0x2c, 0x14, 0x8f, 0x48, 0xea, 0x18, 0x99, 0xd1, 0xcc, 0xc5, 0xdc, + 0x65, 0xa5, 0x3d, 0x25, 0x94, 0xa9, 0xc7, 0xad, 0x3e, 0xa4, 0xf6, 0xe6, + 0xbd, 0xa7, 0x70, 0xd4, 0xdc, 0x9b, 0x26, 0xcb, 0x31, 0x70, 0xaf, 0x3e, + 0xa4, 0xb6, 0x8d, 0x21, 0x31, 0x67, 0x35, 0x35, 0x86, 0x67, 0xd1, 0x02, + 0x6c, 0x36, 0x76, 0xc9, 0x20, 0xf6, 0x0f, 0x30, 0x41, 0x83, 0x19, 0xf5, + 0xe1, 0x33, 0x90, 0xbc, 0x7b, 0x8c, 0x9b, 0x8a, 0x68, 0x30, 0x9e, 0xed, + 0xf4, 0x88, 0xc9, 0x04, 0x08, 0x2b, 0xb0, 0x0f, 0xae, 0xc7, 0xe0, 0x6e, + 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x39, 0x30, 0x21, 0x30, + 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14, + 0xe0, 0xf7, 0xa1, 0x1b, 0xf6, 0x3f, 0x05, 0xad, 0x55, 0x6a, 0x20, 0x4c, + 0x71, 0xca, 0x62, 0x47, 0x13, 0x28, 0xd5, 0x05, 0x04, 0x10, 0x3e, 0x87, + 0x2d, 0x96, 0xea, 0x80, 0x4b, 0xab, 0x3a, 0xb9, 0xee, 0x09, 0x65, 0x28, + 0xbc, 0x8d, 0x02, 0x02, 0x07, 0xd0, 0x00, 0x00, +}; + +/* kWindows is a dummy key and certificate exported from the certificate + * manager on Windows 7. */ +static const uint8_t kWindows[] = { + 0x30, 0x82, 0x0a, 0x02, 0x02, 0x01, 0x03, 0x30, 0x82, 0x09, 0xbe, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x82, + 0x09, 0xaf, 0x04, 0x82, 0x09, 0xab, 0x30, 0x82, 0x09, 0xa7, 0x30, 0x82, + 0x06, 0x08, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, + 0x01, 0xa0, 0x82, 0x05, 0xf9, 0x04, 0x82, 0x05, 0xf5, 0x30, 0x82, 0x05, + 0xf1, 0x30, 0x82, 0x05, 0xed, 0x06, 0x0b, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x0c, 0x0a, 0x01, 0x02, 0xa0, 0x82, 0x04, 0xfe, 0x30, 0x82, + 0x04, 0xfa, 0x30, 0x1c, 0x06, 0x0a, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x0c, 0x01, 0x03, 0x30, 0x0e, 0x04, 0x08, 0xb7, 0x20, 0x55, 0x5a, + 0x4d, 0x3f, 0x0e, 0x89, 0x02, 0x02, 0x07, 0xd0, 0x04, 0x82, 0x04, 0xd8, + 0x3a, 0xcc, 0xd6, 0xcb, 0x4d, 0x54, 0xc0, 0x04, 0x56, 0x10, 0xcc, 0x49, + 0xe4, 0xe0, 0x10, 0x73, 0xfb, 0x1a, 0xdd, 0x1d, 0x4f, 0x6e, 0x55, 0xe3, + 0xa4, 0xab, 0xf9, 0x26, 0xaa, 0x42, 0x54, 0xa0, 0xd1, 0xf0, 0x8d, 0xbf, + 0x71, 0x7d, 0x18, 0x00, 0x17, 0xb3, 0xb7, 0x63, 0x50, 0x8d, 0x2c, 0xeb, + 0x2f, 0xe3, 0xc3, 0xbf, 0x93, 0xc8, 0x46, 0x48, 0x99, 0x47, 0xe2, 0x3b, + 0x8d, 0x71, 0x01, 0x5f, 0x59, 0x5b, 0x61, 0x7e, 0x1f, 0x0c, 0x6e, 0x3e, + 0xc4, 0x74, 0x99, 0x98, 0x30, 0xff, 0x37, 0x7b, 0x30, 0x19, 0xb5, 0xfc, + 0x69, 0x94, 0x5f, 0x79, 0x69, 0x34, 0xda, 0xb5, 0x21, 0xcf, 0xfe, 0x72, + 0x87, 0xe8, 0x7d, 0x29, 0x7e, 0x27, 0x25, 0x90, 0x80, 0x98, 0xdd, 0x8d, + 0xbf, 0x42, 0xb0, 0x10, 0xd8, 0x7d, 0x6d, 0xfe, 0x6f, 0x0d, 0x61, 0x09, + 0xfd, 0xb2, 0x9b, 0xeb, 0xbf, 0x1c, 0xca, 0x33, 0xbc, 0x4e, 0x19, 0x52, + 0x55, 0x53, 0xb4, 0xa5, 0x98, 0x6c, 0xa3, 0x3b, 0xf8, 0xa4, 0x8d, 0x79, + 0xcf, 0x40, 0xf2, 0x89, 0x09, 0x3c, 0x38, 0xab, 0xae, 0xf4, 0x09, 0x3b, + 0xb6, 0xcb, 0xdd, 0xd7, 0xad, 0xe0, 0x5a, 0x71, 0x64, 0xc9, 0x0f, 0x18, + 0xac, 0x3c, 0x12, 0xd4, 0x22, 0x54, 0x24, 0x1a, 0xa5, 0x35, 0x78, 0x99, + 0x09, 0x4a, 0x18, 0x95, 0x23, 0xb9, 0xf7, 0x89, 0x3f, 0x13, 0x43, 0x1f, + 0x8d, 0x76, 0x6b, 0x04, 0xdb, 0x64, 0xf4, 0x8e, 0xf5, 0x50, 0xa0, 0xae, + 0x1c, 0x8c, 0xc8, 0xf3, 0xde, 0xf3, 0x11, 0x2d, 0xfe, 0x76, 0xf0, 0xac, + 0x46, 0x54, 0x23, 0x03, 0x49, 0xfa, 0x73, 0xcd, 0xe0, 0xa1, 0x6c, 0x66, + 0x4d, 0x1b, 0x99, 0x57, 0x3d, 0x61, 0x61, 0xeb, 0x61, 0x40, 0xc7, 0xd6, + 0x41, 0xbe, 0x63, 0x21, 0x1e, 0x7e, 0xb5, 0x0e, 0x94, 0x93, 0x37, 0x41, + 0xe8, 0x91, 0x06, 0xd7, 0xa3, 0x33, 0x78, 0x17, 0x17, 0x59, 0x78, 0x8f, + 0xaf, 0xed, 0xf9, 0x90, 0xfb, 0xb6, 0xc8, 0xa9, 0x0b, 0x10, 0x1a, 0xf1, + 0xab, 0x10, 0x11, 0xbc, 0x7f, 0xa5, 0x2d, 0x34, 0x7d, 0x7b, 0xaf, 0xc8, + 0xb2, 0x00, 0x6b, 0xd4, 0xbb, 0x25, 0x9b, 0xc7, 0x14, 0x8b, 0x50, 0x0a, + 0xd5, 0x2c, 0x1f, 0xa0, 0x5f, 0x07, 0x1d, 0x5e, 0x1a, 0xa4, 0x4b, 0x85, + 0xb2, 0xa6, 0xe2, 0xdd, 0xb7, 0xda, 0x11, 0x25, 0x51, 0xbf, 0x72, 0x50, + 0x53, 0xa1, 0x3d, 0xfa, 0x1d, 0x34, 0x75, 0xdd, 0x7a, 0xe0, 0x90, 0x56, + 0x14, 0xc3, 0xe8, 0x0b, 0xea, 0x32, 0x5f, 0x92, 0xfc, 0x2e, 0x4d, 0x0e, + 0xfe, 0xba, 0x1a, 0x00, 0x6d, 0x8f, 0x75, 0xac, 0x49, 0x4c, 0x79, 0x03, + 0x2e, 0xf2, 0xcc, 0x8e, 0x96, 0x27, 0x3c, 0x59, 0x28, 0x7f, 0x52, 0x8d, + 0xc3, 0x3b, 0x24, 0x68, 0xff, 0xbb, 0xd0, 0x4e, 0xdf, 0xc4, 0x91, 0x32, + 0x14, 0x5e, 0x43, 0x73, 0xd8, 0x56, 0x65, 0xe1, 0x48, 0x89, 0xe4, 0x33, + 0xef, 0x4b, 0x51, 0x50, 0xf2, 0x53, 0xe7, 0xae, 0x7d, 0xb6, 0x8c, 0x80, + 0xee, 0x8d, 0x9e, 0x24, 0x1a, 0xdd, 0x95, 0x7d, 0x22, 0x58, 0x76, 0xf8, + 0xbb, 0x63, 0x36, 0x17, 0xdc, 0xc6, 0x3e, 0xb8, 0xe9, 0x1f, 0xd8, 0xe0, + 0x06, 0x18, 0x1b, 0x3c, 0x45, 0xcb, 0xe1, 0x5a, 0x41, 0xe5, 0x32, 0xa3, + 0x85, 0x1b, 0xff, 0xe0, 0x5e, 0x28, 0xee, 0xe9, 0x05, 0xc7, 0xc8, 0x47, + 0x85, 0xe8, 0x13, 0x7f, 0x1b, 0xda, 0xd7, 0x3e, 0x8e, 0xb8, 0xa3, 0x96, + 0x34, 0x19, 0x3b, 0x0c, 0x88, 0x26, 0x38, 0xe7, 0x65, 0xf6, 0x03, 0x4f, + 0xc8, 0x37, 0x6e, 0x2f, 0x5e, 0x5d, 0xcd, 0xa3, 0x29, 0x37, 0xe8, 0x86, + 0x84, 0x66, 0x37, 0x84, 0xa0, 0x49, 0x4e, 0x8f, 0x3b, 0x1a, 0x42, 0x9f, + 0x62, 0x1f, 0x2b, 0x97, 0xc9, 0x18, 0x21, 0xd2, 0xa5, 0xcd, 0x8f, 0xa4, + 0x03, 0xf8, 0x82, 0x1e, 0xb8, 0x3e, 0x6b, 0x54, 0x29, 0x75, 0x5f, 0x80, + 0xe6, 0x8f, 0x2f, 0x65, 0xb0, 0x6b, 0xbb, 0x18, 0x6e, 0x0d, 0x32, 0x62, + 0x8c, 0x97, 0x48, 0xd3, 0xaa, 0xf2, 0x5e, 0xb8, 0x25, 0xbc, 0xb5, 0x22, + 0x4a, 0xac, 0xcf, 0xdc, 0x8b, 0x48, 0xfc, 0x95, 0xf2, 0x17, 0x21, 0x1e, + 0xda, 0x13, 0xd3, 0x1b, 0xe2, 0x37, 0xd5, 0xbf, 0x92, 0xe4, 0x81, 0xf5, + 0x98, 0x57, 0x51, 0x14, 0xda, 0x80, 0x7d, 0x4a, 0x6a, 0xce, 0x17, 0xaf, + 0xdb, 0xc3, 0x2e, 0x84, 0x3b, 0x1e, 0x02, 0x51, 0x4a, 0xc1, 0x25, 0x8c, + 0x5a, 0x20, 0x56, 0xee, 0xec, 0x59, 0xcf, 0xd7, 0x3e, 0x5f, 0x39, 0x9f, + 0xbf, 0x4d, 0x4e, 0x94, 0xb1, 0x1d, 0x83, 0x70, 0xc0, 0xab, 0xff, 0xfa, + 0x7c, 0x2e, 0x5b, 0xfb, 0x57, 0x3f, 0x60, 0xb8, 0xf3, 0x36, 0x5f, 0xbf, + 0x6a, 0x8c, 0x6f, 0xe0, 0x34, 0xe8, 0x75, 0x26, 0xc2, 0x1e, 0x22, 0x64, + 0x0e, 0x43, 0xc1, 0x93, 0xe6, 0x8a, 0x2e, 0xe9, 0xd9, 0xe0, 0x9f, 0x56, + 0x50, 0x8a, 0xbd, 0x68, 0xf6, 0x57, 0x63, 0x55, 0xbb, 0xe7, 0xfe, 0x22, + 0xca, 0xdc, 0x85, 0x38, 0x39, 0xc8, 0x66, 0x02, 0x28, 0x0f, 0xe0, 0x1c, + 0xd6, 0x0f, 0x5d, 0x6a, 0x0b, 0xd8, 0xe5, 0x6a, 0xeb, 0x54, 0xb2, 0xe0, + 0x02, 0x6f, 0xe2, 0x42, 0x89, 0x66, 0xc2, 0xd5, 0xc6, 0xe2, 0xb2, 0x04, + 0x6d, 0x8a, 0x2b, 0x48, 0xc2, 0x51, 0x07, 0x8e, 0xf3, 0x91, 0x0b, 0xb7, + 0x55, 0x6e, 0xbb, 0xbf, 0x11, 0x5a, 0xcb, 0x2c, 0xb3, 0x1e, 0x61, 0xd3, + 0xdb, 0x90, 0xad, 0xba, 0x10, 0x96, 0xe2, 0x16, 0xf4, 0x0c, 0x47, 0xbd, + 0x64, 0x66, 0x7a, 0x17, 0x63, 0xb9, 0x02, 0xcb, 0x53, 0x7a, 0x35, 0x92, + 0x74, 0xc3, 0x2a, 0x7d, 0xc5, 0x11, 0x18, 0x2f, 0xa3, 0x62, 0x2c, 0xc0, + 0x87, 0xd3, 0xd3, 0xba, 0xcb, 0xe0, 0x86, 0x9b, 0x4b, 0xc5, 0x59, 0x98, + 0x7e, 0x32, 0x96, 0x55, 0xc1, 0x3d, 0x5a, 0xcd, 0x90, 0x2d, 0xf8, 0xb7, + 0xa8, 0xba, 0xce, 0x89, 0x64, 0xa6, 0xf3, 0x1b, 0x11, 0x2e, 0x12, 0x99, + 0x4d, 0x34, 0x45, 0x13, 0x66, 0xb7, 0x69, 0x7b, 0xc5, 0x79, 0xf5, 0x6b, + 0xc2, 0x1d, 0xc8, 0x3f, 0x09, 0x18, 0x0a, 0xfc, 0xf7, 0xaf, 0x98, 0xc2, + 0xc7, 0xcc, 0x85, 0x29, 0xc6, 0x22, 0x7a, 0x77, 0xab, 0xb5, 0xac, 0xf7, + 0x9e, 0x70, 0x8e, 0x7f, 0x3c, 0xf1, 0xbd, 0xd9, 0x7a, 0x92, 0x84, 0xc5, + 0xb8, 0x56, 0xc3, 0xcb, 0xf7, 0x25, 0xad, 0xda, 0x0e, 0x1c, 0xe4, 0x68, + 0x66, 0x83, 0x91, 0x78, 0xf1, 0xe7, 0x8c, 0xaa, 0x45, 0xb6, 0x85, 0x74, + 0x9b, 0x08, 0xff, 0xac, 0x38, 0x55, 0xa5, 0x6a, 0xea, 0x2e, 0x75, 0x71, + 0xd3, 0xa2, 0xdc, 0x1c, 0xc0, 0xc7, 0x0b, 0xa9, 0xd5, 0x7e, 0xf9, 0x63, + 0x82, 0x87, 0xb7, 0x81, 0x01, 0xb9, 0x31, 0xdf, 0x41, 0x35, 0x0e, 0xe2, + 0x1f, 0x48, 0xbf, 0x60, 0xce, 0xb0, 0xb4, 0x38, 0xa5, 0xb4, 0x76, 0xa3, + 0x80, 0x1f, 0x93, 0x57, 0xf2, 0x05, 0x81, 0x42, 0xd1, 0xae, 0x56, 0x6d, + 0xc5, 0x4c, 0xab, 0xa6, 0x24, 0x2a, 0x02, 0x3b, 0xb1, 0xc4, 0x75, 0xcf, + 0x15, 0x90, 0xb5, 0xf2, 0xe7, 0x10, 0x69, 0xa0, 0xe3, 0xc4, 0xe6, 0x52, + 0x63, 0x14, 0xb4, 0x15, 0x91, 0x8e, 0xba, 0x7a, 0xad, 0x2d, 0x9b, 0x24, + 0x74, 0x36, 0x31, 0xca, 0xcb, 0x4b, 0x5a, 0xbf, 0xd3, 0x4e, 0xb4, 0xc1, + 0x48, 0x44, 0x74, 0x2f, 0x83, 0xe4, 0x39, 0x3d, 0x90, 0x2d, 0x32, 0x12, + 0xf7, 0xfa, 0xd3, 0xe3, 0xdb, 0x4f, 0xe6, 0xe7, 0x20, 0x2c, 0x57, 0xc0, + 0xf9, 0x80, 0xe1, 0xdc, 0x1c, 0xf2, 0x05, 0x54, 0x35, 0xf6, 0xbd, 0xfb, + 0xbd, 0xc5, 0xb2, 0x82, 0x32, 0x63, 0x32, 0xca, 0xf4, 0xf7, 0x14, 0x92, + 0x87, 0x8a, 0x45, 0x37, 0x56, 0x93, 0xda, 0x4f, 0x04, 0x59, 0x03, 0x24, + 0x93, 0x1a, 0x0b, 0x4e, 0xdb, 0x58, 0xbf, 0xda, 0x2a, 0x0e, 0x7e, 0x98, + 0x6c, 0x0c, 0xeb, 0x21, 0xf9, 0xbf, 0x9b, 0x1f, 0xc0, 0xef, 0xd3, 0xea, + 0xcb, 0x99, 0x5e, 0x14, 0x3e, 0x10, 0xfa, 0xad, 0x38, 0xf7, 0x68, 0x9f, + 0xa3, 0xcc, 0xdf, 0xe5, 0x31, 0x91, 0x98, 0xde, 0x74, 0x5f, 0x7b, 0xce, + 0xe4, 0x54, 0xd9, 0x51, 0xec, 0xf5, 0x4b, 0x17, 0x5f, 0x99, 0x4c, 0xf8, + 0x00, 0xe0, 0x10, 0x09, 0x07, 0x64, 0xae, 0x61, 0x3b, 0x60, 0xa3, 0x89, + 0x38, 0xc4, 0x80, 0xf2, 0x1e, 0x11, 0x26, 0x78, 0x72, 0x05, 0x97, 0x27, + 0xba, 0x83, 0x33, 0x1b, 0x14, 0x4b, 0xc0, 0xc8, 0xb0, 0xcc, 0x0a, 0x9b, + 0x3e, 0x4c, 0xde, 0x12, 0x07, 0x11, 0xd5, 0xf0, 0xc0, 0xdd, 0x70, 0x3d, + 0xd8, 0x7a, 0xf7, 0xa2, 0xf2, 0x70, 0xad, 0x54, 0xce, 0x67, 0x41, 0x12, + 0x29, 0x1f, 0xe1, 0x49, 0x5f, 0x4c, 0x77, 0x41, 0x7c, 0x74, 0x25, 0x9c, + 0x91, 0xd1, 0x0d, 0xa5, 0x9a, 0xb8, 0x56, 0x4c, 0x01, 0xc0, 0x77, 0x51, + 0x14, 0xc8, 0x92, 0x40, 0x9a, 0xbd, 0x7f, 0x3b, 0x9b, 0x17, 0xbb, 0x80, + 0x6e, 0x50, 0x64, 0x31, 0xed, 0xe2, 0x22, 0x9f, 0x96, 0x8e, 0xe2, 0x4e, + 0x54, 0x6e, 0x36, 0x35, 0xfc, 0xf2, 0xed, 0xfc, 0x56, 0x63, 0xdb, 0x89, + 0x19, 0x99, 0xf8, 0x47, 0xff, 0xce, 0x35, 0xd2, 0x86, 0x63, 0xbc, 0xe4, + 0x8c, 0x5d, 0x12, 0x94, 0x31, 0x81, 0xdb, 0x30, 0x13, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x15, 0x31, 0x06, 0x04, 0x04, + 0x01, 0x00, 0x00, 0x00, 0x30, 0x57, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x09, 0x14, 0x31, 0x4a, 0x1e, 0x48, 0x00, 0x65, 0x00, + 0x65, 0x00, 0x36, 0x00, 0x64, 0x00, 0x38, 0x00, 0x38, 0x00, 0x30, 0x00, + 0x35, 0x00, 0x2d, 0x00, 0x30, 0x00, 0x36, 0x00, 0x64, 0x00, 0x39, 0x00, + 0x2d, 0x00, 0x34, 0x00, 0x32, 0x00, 0x65, 0x00, 0x32, 0x00, 0x2d, 0x00, + 0x38, 0x00, 0x62, 0x00, 0x36, 0x00, 0x38, 0x00, 0x2d, 0x00, 0x66, 0x00, + 0x65, 0x00, 0x61, 0x00, 0x62, 0x00, 0x35, 0x00, 0x65, 0x00, 0x66, 0x00, + 0x32, 0x00, 0x38, 0x00, 0x32, 0x00, 0x37, 0x00, 0x30, 0x30, 0x6b, 0x06, + 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x11, 0x01, 0x31, 0x5e, + 0x1e, 0x5c, 0x00, 0x4d, 0x00, 0x69, 0x00, 0x63, 0x00, 0x72, 0x00, 0x6f, + 0x00, 0x73, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x74, 0x00, 0x20, 0x00, 0x45, + 0x00, 0x6e, 0x00, 0x68, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x65, + 0x00, 0x64, 0x00, 0x20, 0x00, 0x43, 0x00, 0x72, 0x00, 0x79, 0x00, 0x70, + 0x00, 0x74, 0x00, 0x6f, 0x00, 0x67, 0x00, 0x72, 0x00, 0x61, 0x00, 0x70, + 0x00, 0x68, 0x00, 0x69, 0x00, 0x63, 0x00, 0x20, 0x00, 0x50, 0x00, 0x72, + 0x00, 0x6f, 0x00, 0x76, 0x00, 0x69, 0x00, 0x64, 0x00, 0x65, 0x00, 0x72, + 0x00, 0x20, 0x00, 0x76, 0x00, 0x31, 0x00, 0x2e, 0x00, 0x30, 0x30, 0x82, + 0x03, 0x97, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, + 0x06, 0xa0, 0x82, 0x03, 0x88, 0x30, 0x82, 0x03, 0x84, 0x02, 0x01, 0x00, + 0x30, 0x82, 0x03, 0x7d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x07, 0x01, 0x30, 0x1c, 0x06, 0x0a, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x0c, 0x01, 0x06, 0x30, 0x0e, 0x04, 0x08, 0x92, 0x16, 0x6d, + 0x6d, 0x68, 0xd3, 0xb0, 0xc1, 0x02, 0x02, 0x07, 0xd0, 0x80, 0x82, 0x03, + 0x50, 0xee, 0x76, 0xe8, 0x60, 0xbf, 0xca, 0x3c, 0x2d, 0xe5, 0x29, 0x22, + 0xf6, 0x33, 0xc3, 0x50, 0x6a, 0xdb, 0xf3, 0x58, 0x3c, 0xd9, 0x7c, 0xd8, + 0xf9, 0x83, 0x89, 0x17, 0xa8, 0x1b, 0x6b, 0x09, 0xc1, 0x99, 0x49, 0xb0, + 0x43, 0x06, 0xc6, 0x42, 0x4b, 0x7c, 0x85, 0x4b, 0xe6, 0x69, 0x38, 0x91, + 0xce, 0x3d, 0x3c, 0x97, 0xd5, 0x14, 0x4f, 0x15, 0x5a, 0x81, 0x4d, 0x77, + 0x40, 0xe0, 0xe1, 0x1c, 0x69, 0x3f, 0x1d, 0x65, 0x68, 0xb3, 0x98, 0x95, + 0x30, 0x6c, 0xb0, 0x70, 0x93, 0x0c, 0xce, 0xec, 0xaf, 0x57, 0xc6, 0x9c, + 0x34, 0xb4, 0x2b, 0xaf, 0xc3, 0x5e, 0x70, 0x87, 0x17, 0xe8, 0xc9, 0x54, + 0x06, 0xb5, 0xb7, 0x83, 0xff, 0x46, 0x2b, 0xb6, 0x6a, 0x66, 0x2f, 0x6d, + 0x0f, 0x96, 0x53, 0x66, 0x65, 0xb8, 0x7b, 0x48, 0x55, 0x83, 0xd3, 0xc4, + 0x16, 0x93, 0xde, 0x72, 0x59, 0xf1, 0x9a, 0xab, 0xd5, 0xd5, 0xcb, 0x24, + 0xa6, 0x4a, 0x4e, 0x57, 0xf3, 0x6e, 0xca, 0xb1, 0xeb, 0x7d, 0xdb, 0x02, + 0xd2, 0x79, 0x89, 0xef, 0xa2, 0x8b, 0xee, 0x6f, 0xdc, 0x5e, 0x65, 0xa5, + 0x09, 0x33, 0x51, 0xb5, 0x21, 0xc8, 0xc6, 0xab, 0xed, 0xd5, 0x50, 0x93, + 0x39, 0x71, 0x97, 0xd3, 0x2c, 0xdd, 0xaf, 0xb1, 0xc6, 0x9b, 0x4b, 0x69, + 0x98, 0xae, 0xaf, 0x21, 0xa0, 0x8a, 0x90, 0x25, 0xe0, 0xf4, 0x8c, 0xf2, + 0xc3, 0x4f, 0x64, 0xb6, 0xc6, 0x64, 0x90, 0xff, 0x95, 0x0a, 0xcc, 0x8c, + 0xf4, 0x86, 0x80, 0x53, 0x8d, 0x51, 0x0b, 0xcd, 0x45, 0x4f, 0xcf, 0x7c, + 0xc6, 0xdf, 0x08, 0x5e, 0xa7, 0xdf, 0x4f, 0xcf, 0x84, 0xde, 0xb8, 0x4d, + 0x73, 0x40, 0x06, 0xbe, 0x33, 0x82, 0xe8, 0x41, 0x1b, 0x9a, 0xc3, 0x5b, + 0xb6, 0xf3, 0xfc, 0x32, 0x98, 0xcc, 0xcc, 0x5e, 0xd5, 0xb7, 0x86, 0x0f, + 0xc8, 0x59, 0x72, 0xcb, 0x9a, 0xc5, 0x3c, 0x50, 0xb8, 0x25, 0xb8, 0x87, + 0x3e, 0x49, 0xd4, 0x2d, 0x2f, 0x50, 0x35, 0xeb, 0xb8, 0x10, 0xa7, 0xea, + 0xb1, 0xe2, 0x0c, 0x6a, 0x84, 0x2c, 0xe2, 0x7a, 0x26, 0xef, 0x7e, 0x6b, + 0x1e, 0x47, 0x6e, 0x98, 0xc0, 0x3f, 0x92, 0x24, 0xe7, 0x88, 0xf9, 0x18, + 0x78, 0x37, 0x8a, 0x54, 0xa6, 0x2b, 0x5b, 0xf0, 0xc7, 0xe2, 0x98, 0xa4, + 0xa6, 0x2e, 0xc3, 0x6a, 0x75, 0x66, 0x51, 0xe8, 0x0d, 0x90, 0xfd, 0xa7, + 0xec, 0x22, 0xb3, 0x7d, 0x9d, 0x0c, 0xfe, 0x72, 0x7f, 0x98, 0xf6, 0x86, + 0x30, 0xd3, 0x7c, 0xee, 0xa5, 0xc5, 0x20, 0x89, 0x79, 0x04, 0x8e, 0xa8, + 0xb6, 0x94, 0x70, 0x4e, 0x75, 0xe5, 0xa0, 0xae, 0x8c, 0x7f, 0x72, 0x4c, + 0xd5, 0x9f, 0xd2, 0x56, 0x0d, 0xb2, 0x28, 0x45, 0x99, 0xf8, 0x40, 0xd4, + 0x3f, 0x42, 0x4a, 0x0c, 0x92, 0x23, 0xe1, 0x17, 0xaf, 0x68, 0xa6, 0x0f, + 0x1d, 0x32, 0x0d, 0xf8, 0x08, 0x8e, 0xdc, 0x79, 0x68, 0xf0, 0xfe, 0x0b, + 0xda, 0x94, 0x2d, 0xa6, 0xa7, 0x76, 0x7e, 0xd6, 0xca, 0xec, 0x7c, 0x37, + 0x52, 0x4f, 0x77, 0xcf, 0xa3, 0xcf, 0x8a, 0xfe, 0x89, 0xd9, 0x3e, 0xbc, + 0xb5, 0x06, 0xa0, 0x21, 0x91, 0x89, 0x77, 0x84, 0x85, 0x43, 0x2a, 0x65, + 0xec, 0x75, 0x4d, 0x0d, 0x1c, 0x79, 0x0f, 0x61, 0xca, 0x3e, 0x62, 0xbb, + 0x41, 0xf9, 0x4c, 0x5c, 0x3b, 0xde, 0x33, 0x8e, 0xdf, 0x51, 0x72, 0x93, + 0xca, 0xa6, 0xc7, 0x16, 0xe5, 0xb3, 0x22, 0xb6, 0x2e, 0xbf, 0xae, 0x1d, + 0x91, 0x1d, 0x49, 0x96, 0xa3, 0x25, 0xd4, 0xce, 0x6f, 0xf0, 0xfb, 0xb7, + 0xf5, 0x4a, 0x24, 0x03, 0x54, 0x4b, 0x7f, 0x0b, 0xb4, 0x31, 0xb4, 0x33, + 0xb7, 0x40, 0xf0, 0xd5, 0x4c, 0xee, 0xe3, 0x4b, 0x12, 0x8c, 0xc9, 0xa7, + 0x06, 0xb1, 0x02, 0x5a, 0x14, 0x6f, 0xe2, 0x3b, 0x68, 0x9b, 0x3d, 0xfc, + 0x83, 0x4a, 0xcc, 0xb5, 0x77, 0xe7, 0xf0, 0x1b, 0x52, 0xce, 0x60, 0x89, + 0xe2, 0x45, 0x76, 0xaa, 0x76, 0x70, 0xc2, 0xfd, 0x21, 0x8f, 0x1d, 0x67, + 0x1a, 0x4c, 0xe8, 0x81, 0x2b, 0x2e, 0xa9, 0x56, 0x0a, 0x27, 0x0f, 0x81, + 0xba, 0x5c, 0x4f, 0xfa, 0x6e, 0x7e, 0x33, 0x7d, 0x78, 0xed, 0xd2, 0xe3, + 0x24, 0xae, 0x24, 0xb2, 0x1b, 0x62, 0x71, 0x0e, 0x73, 0xfe, 0x8a, 0x3b, + 0x98, 0x0d, 0x82, 0x8e, 0x8d, 0x0f, 0xb3, 0xe2, 0x65, 0x87, 0xeb, 0x36, + 0x91, 0x4d, 0x8a, 0xfb, 0x22, 0x7a, 0x23, 0x2c, 0xe1, 0xb6, 0x94, 0xb6, + 0x90, 0x94, 0xcc, 0x0c, 0x7d, 0x02, 0x36, 0x56, 0xda, 0x45, 0x20, 0x90, + 0x48, 0xdb, 0xa4, 0xf5, 0x27, 0xac, 0x22, 0x49, 0x25, 0xaa, 0xd8, 0xa7, + 0x79, 0x38, 0x80, 0xc0, 0x95, 0xc7, 0xd1, 0x5c, 0x17, 0x7c, 0xa7, 0xec, + 0xd2, 0x63, 0xc6, 0xc6, 0x55, 0xfe, 0x78, 0x99, 0x06, 0x2c, 0x6e, 0x4f, + 0xfe, 0xd1, 0x5b, 0x8c, 0x2f, 0xa1, 0x42, 0x03, 0x26, 0x5a, 0x5e, 0xda, + 0xef, 0x43, 0xd2, 0x0e, 0xf9, 0x5f, 0xdb, 0x1d, 0x9c, 0xd1, 0xcb, 0x65, + 0x84, 0x26, 0xed, 0x91, 0x8f, 0x16, 0xb4, 0x1c, 0xc0, 0xb3, 0x8d, 0x79, + 0xae, 0x9b, 0xcb, 0x36, 0x6d, 0xcd, 0x67, 0x1f, 0x87, 0x11, 0x2a, 0x7c, + 0xb1, 0x8c, 0xfb, 0x06, 0xab, 0xd2, 0xd6, 0x2a, 0xe3, 0x45, 0x6c, 0xa5, + 0xc0, 0x19, 0x6b, 0xfc, 0xc3, 0xb7, 0x54, 0x35, 0xda, 0xdf, 0x12, 0x97, + 0x5c, 0xac, 0x59, 0xb4, 0x42, 0x25, 0xef, 0x04, 0xf7, 0x4c, 0xdb, 0x74, + 0xb9, 0x68, 0x8f, 0xee, 0x37, 0x0a, 0xc6, 0x21, 0x86, 0x0f, 0x6f, 0x8e, + 0xab, 0xd5, 0x7b, 0x38, 0x5e, 0x5f, 0x7d, 0xb9, 0x5a, 0xcb, 0xce, 0xa0, + 0x56, 0x37, 0x13, 0x71, 0x4b, 0xba, 0x43, 0x7c, 0xc0, 0xb7, 0x7f, 0x32, + 0xd7, 0x46, 0x27, 0x58, 0xfc, 0xdb, 0xb5, 0x64, 0x20, 0x3b, 0x20, 0x85, + 0x79, 0xa8, 0x9a, 0x22, 0xaf, 0x29, 0x86, 0xc5, 0x9d, 0x23, 0x96, 0x52, + 0xca, 0xc7, 0x9d, 0x92, 0x26, 0xe5, 0x3a, 0x60, 0xd6, 0xad, 0x8d, 0x5a, + 0xd9, 0x29, 0xbe, 0xd5, 0x5c, 0x3a, 0x77, 0xda, 0x34, 0xe2, 0x76, 0xcb, + 0x98, 0xa4, 0xf3, 0x33, 0xf1, 0x68, 0x20, 0x83, 0x95, 0x0b, 0x8d, 0x93, + 0x59, 0x02, 0x0c, 0x8f, 0xe4, 0xc4, 0xb0, 0xe7, 0x61, 0x0d, 0xf9, 0x80, + 0x20, 0x58, 0x40, 0xea, 0xb7, 0x0b, 0x1b, 0xad, 0xe3, 0x30, 0x3b, 0x30, + 0x1f, 0x30, 0x07, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x04, 0x14, + 0x2d, 0x77, 0x79, 0x79, 0x90, 0x41, 0x75, 0xf4, 0x4a, 0x7f, 0xf7, 0x15, + 0x94, 0x28, 0x62, 0xf7, 0x69, 0xd4, 0x44, 0x27, 0x04, 0x14, 0x2b, 0x2f, + 0xd9, 0x24, 0xc3, 0x8a, 0x34, 0xbb, 0x52, 0x52, 0x7b, 0xf6, 0x0e, 0x7b, + 0xfe, 0x3a, 0x66, 0x47, 0x40, 0x49, 0x02, 0x02, 0x07, 0xd0, +}; + +static const char kPassword[] = "foo"; + +static bool Test(const char *name, const uint8_t *der, size_t der_len) { + ScopedX509Stack certs(sk_X509_new_null()); + if (!certs) { + return false; + } + + CBS pkcs12; + EVP_PKEY *key = nullptr; + CBS_init(&pkcs12, der, der_len); + if (!PKCS12_get_key_and_certs(&key, certs.get(), &pkcs12, kPassword)) { + fprintf(stderr, "PKCS12 failed on %s data.\n", name); + ERR_print_errors_fp(stderr); + return false; + } + ScopedEVP_PKEY delete_key(key); + + if (sk_X509_num(certs.get()) != 1 || key == nullptr) { + fprintf(stderr, "Bad result from %s data.\n", name); + return false; + } + + return true; +} + +static bool TestCompat(const uint8_t *der, size_t der_len) { + ScopedBIO bio(BIO_new_mem_buf(der, der_len)); + if (!bio) { + return false; + } + + ScopedPKCS12 p12(d2i_PKCS12_bio(bio.get(), nullptr)); + if (!p12) { + fprintf(stderr, "PKCS12_parse failed.\n"); + ERR_print_errors_fp(stderr); + return false; + } + + if (PKCS12_verify_mac(p12.get(), "badpass", 7)) { + fprintf(stderr, "PKCS12_verify_mac accepted bad password.\n"); + return false; + } + + if (!PKCS12_verify_mac(p12.get(), kPassword, sizeof(kPassword) - 1)) { + fprintf(stderr, "PKCS12_verify_mac rejected good password.\n"); + return false; + } + + EVP_PKEY *key = nullptr; + X509 *cert = nullptr; + STACK_OF(X509) *ca_certs = nullptr; + if (!PKCS12_parse(p12.get(), kPassword, &key, &cert, &ca_certs)) { + fprintf(stderr, "PKCS12_parse failed.\n"); + ERR_print_errors_fp(stderr); + return false; + } + ScopedEVP_PKEY delete_key(key); + ScopedX509 delete_cert(cert); + ScopedX509Stack delete_ca_certs(ca_certs); + + if (key == nullptr || cert == nullptr) { + fprintf(stderr, "Bad result from PKCS12_parse.\n"); + return false; + } + + if (sk_X509_num(ca_certs) != 0) { + fprintf(stderr, "Bad result from PKCS12_parse.\n"); + return false; + } + + return true; +} + +int main(int argc, char **argv) { + CRYPTO_library_init(); + + if (!Test("OpenSSL", kOpenSSL, sizeof(kOpenSSL)) || + !Test("NSS", kNSS, sizeof(kNSS)) || + !Test("Windows", kWindows, sizeof(kWindows)) || + !TestCompat(kWindows, sizeof(kWindows))) { + return 1; + } + + printf("PASS\n"); + return 0; +} diff --git a/external/boringssl/crypto/pkcs8/pkcs8.c b/external/boringssl/crypto/pkcs8/pkcs8.c new file mode 100644 index 0000000000..0ca0f2ec49 --- /dev/null +++ b/external/boringssl/crypto/pkcs8/pkcs8.c @@ -0,0 +1,1227 @@ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 1999. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "internal.h" +#include "../bytestring/internal.h" + + +#define PKCS12_KEY_ID 1 +#define PKCS12_IV_ID 2 +#define PKCS12_MAC_ID 3 + +static int ascii_to_ucs2(const char *ascii, size_t ascii_len, + uint8_t **out, size_t *out_len) { + uint8_t *unitmp; + size_t ulen, i; + + if (!ascii) { + *out = NULL; + *out_len = 0; + return 1; + } + + ulen = ascii_len * 2 + 2; + if (ulen < ascii_len) { + return 0; + } + unitmp = OPENSSL_malloc(ulen); + if (unitmp == NULL) { + return 0; + } + for (i = 0; i < ulen - 2; i += 2) { + unitmp[i] = 0; + unitmp[i + 1] = ascii[i >> 1]; + } + + /* Make result double null terminated */ + unitmp[ulen - 2] = 0; + unitmp[ulen - 1] = 0; + *out_len = ulen; + *out = unitmp; + return 1; +} + +static int pkcs12_key_gen_raw(const uint8_t *pass_raw, size_t pass_raw_len, + const uint8_t *salt, size_t salt_len, + uint8_t id, int iterations, + size_t out_len, uint8_t *out, + const EVP_MD *md) { + /* See https://tools.ietf.org/html/rfc7292#appendix-B. Quoted parts of the + * specification have errata applied and other typos fixed. */ + + if (iterations < 1) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_ITERATION_COUNT); + return 0; + } + + /* In the spec, |block_size| is called "v", but measured in bits. */ + size_t block_size = EVP_MD_block_size(md); + + /* 1. Construct a string, D (the "diversifier"), by concatenating v/8 copies + * of ID. */ + uint8_t D[EVP_MAX_MD_BLOCK_SIZE]; + memset(D, id, block_size); + + /* 2. Concatenate copies of the salt together to create a string S of length + * v(ceiling(s/v)) bits (the final copy of the salt may be truncated to + * create S). Note that if the salt is the empty string, then so is S. + * + * 3. Concatenate copies of the password together to create a string P of + * length v(ceiling(p/v)) bits (the final copy of the password may be + * truncated to create P). Note that if the password is the empty string, + * then so is P. + * + * 4. Set I=S||P to be the concatenation of S and P. */ + if (salt_len + block_size - 1 < salt_len || + pass_raw_len + block_size - 1 < pass_raw_len) { + OPENSSL_PUT_ERROR(PKCS8, ERR_R_OVERFLOW); + return 0; + } + size_t S_len = block_size * ((salt_len + block_size - 1) / block_size); + size_t P_len = block_size * ((pass_raw_len + block_size - 1) / block_size); + size_t I_len = S_len + P_len; + if (I_len < S_len) { + OPENSSL_PUT_ERROR(PKCS8, ERR_R_OVERFLOW); + return 0; + } + + uint8_t *I = OPENSSL_malloc(I_len); + if (I_len != 0 && I == NULL) { + OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE); + return 0; + } + + size_t i; + for (i = 0; i < S_len; i++) { + I[i] = salt[i % salt_len]; + } + for (i = 0; i < P_len; i++) { + I[i + S_len] = pass_raw[i % pass_raw_len]; + } + + int ret = 0; + EVP_MD_CTX ctx; + EVP_MD_CTX_init(&ctx); + + while (out_len != 0) { + /* A. Set A_i=H^r(D||I). (i.e., the r-th hash of D||I, + * H(H(H(... H(D||I)))) */ + uint8_t A[EVP_MAX_MD_SIZE]; + unsigned A_len; + if (!EVP_DigestInit_ex(&ctx, md, NULL) || + !EVP_DigestUpdate(&ctx, D, block_size) || + !EVP_DigestUpdate(&ctx, I, I_len) || + !EVP_DigestFinal_ex(&ctx, A, &A_len)) { + goto err; + } + int iter; + for (iter = 1; iter < iterations; iter++) { + if (!EVP_DigestInit_ex(&ctx, md, NULL) || + !EVP_DigestUpdate(&ctx, A, A_len) || + !EVP_DigestFinal_ex(&ctx, A, &A_len)) { + goto err; + } + } + + size_t todo = out_len < A_len ? out_len : A_len; + memcpy(out, A, todo); + out += todo; + out_len -= todo; + if (out_len == 0) { + break; + } + + /* B. Concatenate copies of A_i to create a string B of length v bits (the + * final copy of A_i may be truncated to create B). */ + uint8_t B[EVP_MAX_MD_BLOCK_SIZE]; + for (i = 0; i < block_size; i++) { + B[i] = A[i % A_len]; + } + + /* C. Treating I as a concatenation I_0, I_1, ..., I_(k-1) of v-bit blocks, + * where k=ceiling(s/v)+ceiling(p/v), modify I by setting I_j=(I_j+B+1) mod + * 2^v for each j. */ + assert(I_len % block_size == 0); + for (i = 0; i < I_len; i += block_size) { + unsigned carry = 1; + size_t j; + for (j = block_size - 1; j < block_size; j--) { + carry += I[i + j] + B[j]; + I[i + j] = (uint8_t)carry; + carry >>= 8; + } + } + } + + ret = 1; + +err: + OPENSSL_cleanse(I, I_len); + OPENSSL_free(I); + EVP_MD_CTX_cleanup(&ctx); + return ret; +} + +static int pkcs12_pbe_keyivgen(EVP_CIPHER_CTX *ctx, const uint8_t *pass_raw, + size_t pass_raw_len, ASN1_TYPE *param, + const EVP_CIPHER *cipher, const EVP_MD *md, + int is_encrypt) { + PBEPARAM *pbe; + int salt_len, iterations, ret; + uint8_t *salt; + const uint8_t *pbuf; + uint8_t key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH]; + + /* Extract useful info from parameter */ + if (param == NULL || param->type != V_ASN1_SEQUENCE || + param->value.sequence == NULL) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR); + return 0; + } + + pbuf = param->value.sequence->data; + pbe = d2i_PBEPARAM(NULL, &pbuf, param->value.sequence->length); + if (pbe == NULL) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR); + return 0; + } + + if (!pbe->iter) { + iterations = 1; + } else { + iterations = ASN1_INTEGER_get(pbe->iter); + } + salt = pbe->salt->data; + salt_len = pbe->salt->length; + if (!pkcs12_key_gen_raw(pass_raw, pass_raw_len, salt, salt_len, PKCS12_KEY_ID, + iterations, EVP_CIPHER_key_length(cipher), key, md)) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_KEY_GEN_ERROR); + PBEPARAM_free(pbe); + return 0; + } + if (!pkcs12_key_gen_raw(pass_raw, pass_raw_len, salt, salt_len, PKCS12_IV_ID, + iterations, EVP_CIPHER_iv_length(cipher), iv, md)) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_KEY_GEN_ERROR); + PBEPARAM_free(pbe); + return 0; + } + PBEPARAM_free(pbe); + ret = EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, is_encrypt); + OPENSSL_cleanse(key, EVP_MAX_KEY_LENGTH); + OPENSSL_cleanse(iv, EVP_MAX_IV_LENGTH); + return ret; +} + +typedef int (*keygen_func)(EVP_CIPHER_CTX *ctx, const uint8_t *pass_raw, + size_t pass_raw_len, ASN1_TYPE *param, + const EVP_CIPHER *cipher, const EVP_MD *md, + int is_encrypt); + +struct pbe_suite { + int pbe_nid; + const EVP_CIPHER* (*cipher_func)(void); + const EVP_MD* (*md_func)(void); + keygen_func keygen; + int flags; +}; + +#define PBE_UCS2_CONVERT_PASSWORD 0x1 + +static const struct pbe_suite kBuiltinPBE[] = { + { + NID_pbe_WithSHA1And40BitRC2_CBC, EVP_rc2_40_cbc, EVP_sha1, + pkcs12_pbe_keyivgen, PBE_UCS2_CONVERT_PASSWORD + }, + { + NID_pbe_WithSHA1And128BitRC4, EVP_rc4, EVP_sha1, pkcs12_pbe_keyivgen, + PBE_UCS2_CONVERT_PASSWORD + }, + { + NID_pbe_WithSHA1And3_Key_TripleDES_CBC, EVP_des_ede3_cbc, EVP_sha1, + pkcs12_pbe_keyivgen, PBE_UCS2_CONVERT_PASSWORD + }, + { + NID_pbes2, NULL, NULL, PKCS5_v2_PBE_keyivgen, 0 + }, +}; + +static const struct pbe_suite *get_pbe_suite(int pbe_nid) { + unsigned i; + for (i = 0; i < sizeof(kBuiltinPBE) / sizeof(kBuiltinPBE[0]); i++) { + if (kBuiltinPBE[i].pbe_nid == pbe_nid) { + return &kBuiltinPBE[i]; + } + } + + return NULL; +} + +/* pass_to_pass_raw performs a password conversion (possibly a no-op) + * appropriate to the supplied |pbe_nid|. The input |pass| is treated as a + * NUL-terminated string if |pass_len| is -1, otherwise it is treated as a + * buffer of the specified length. If the supplied PBE NID sets the + * |PBE_UCS2_CONVERT_PASSWORD| flag, the supplied |pass| will be converted to + * UCS-2. + * + * It sets |*out_pass_raw| to a new buffer that must be freed by the caller. It + * returns one on success and zero on error. */ +static int pass_to_pass_raw(int pbe_nid, const char *pass, int pass_len, + uint8_t **out_pass_raw, size_t *out_pass_raw_len) { + if (pass == NULL) { + *out_pass_raw = NULL; + *out_pass_raw_len = 0; + return 1; + } + + if (pass_len == -1) { + pass_len = strlen(pass); + } else if (pass_len < 0 || pass_len > 2000000000) { + OPENSSL_PUT_ERROR(PKCS8, ERR_R_OVERFLOW); + return 0; + } + + const struct pbe_suite *suite = get_pbe_suite(pbe_nid); + if (suite != NULL && (suite->flags & PBE_UCS2_CONVERT_PASSWORD)) { + if (!ascii_to_ucs2(pass, pass_len, out_pass_raw, out_pass_raw_len)) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR); + return 0; + } + } else { + *out_pass_raw = BUF_memdup(pass, pass_len); + if (*out_pass_raw == NULL) { + OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE); + return 0; + } + *out_pass_raw_len = (size_t)pass_len; + } + + return 1; +} + +static int pbe_cipher_init(ASN1_OBJECT *pbe_obj, + const uint8_t *pass_raw, size_t pass_raw_len, + ASN1_TYPE *param, + EVP_CIPHER_CTX *ctx, int is_encrypt) { + const EVP_CIPHER *cipher; + const EVP_MD *md; + + const struct pbe_suite *suite = get_pbe_suite(OBJ_obj2nid(pbe_obj)); + if (suite == NULL) { + char obj_str[80]; + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNKNOWN_ALGORITHM); + if (!pbe_obj) { + strncpy(obj_str, "NULL", sizeof(obj_str)); + } else { + i2t_ASN1_OBJECT(obj_str, sizeof(obj_str), pbe_obj); + } + ERR_add_error_data(2, "TYPE=", obj_str); + return 0; + } + + if (suite->cipher_func == NULL) { + cipher = NULL; + } else { + cipher = suite->cipher_func(); + if (!cipher) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNKNOWN_CIPHER); + return 0; + } + } + + if (suite->md_func == NULL) { + md = NULL; + } else { + md = suite->md_func(); + if (!md) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNKNOWN_DIGEST); + return 0; + } + } + + if (!suite->keygen(ctx, pass_raw, pass_raw_len, param, cipher, md, + is_encrypt)) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_KEYGEN_FAILURE); + return 0; + } + + return 1; +} + +static int pbe_crypt(const X509_ALGOR *algor, + const uint8_t *pass_raw, size_t pass_raw_len, + const uint8_t *in, size_t in_len, + uint8_t **out, size_t *out_len, + int is_encrypt) { + uint8_t *buf; + int n, ret = 0; + EVP_CIPHER_CTX ctx; + unsigned block_size; + + EVP_CIPHER_CTX_init(&ctx); + + if (!pbe_cipher_init(algor->algorithm, pass_raw, pass_raw_len, + algor->parameter, &ctx, is_encrypt)) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNKNOWN_CIPHER_ALGORITHM); + return 0; + } + block_size = EVP_CIPHER_CTX_block_size(&ctx); + + if (in_len + block_size < in_len) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_TOO_LONG); + goto err; + } + + buf = OPENSSL_malloc(in_len + block_size); + if (buf == NULL) { + OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (!EVP_CipherUpdate(&ctx, buf, &n, in, in_len)) { + OPENSSL_free(buf); + OPENSSL_PUT_ERROR(PKCS8, ERR_R_EVP_LIB); + goto err; + } + *out_len = n; + + if (!EVP_CipherFinal_ex(&ctx, buf + n, &n)) { + OPENSSL_free(buf); + OPENSSL_PUT_ERROR(PKCS8, ERR_R_EVP_LIB); + goto err; + } + *out_len += n; + *out = buf; + ret = 1; + +err: + EVP_CIPHER_CTX_cleanup(&ctx); + return ret; +} + +static void *pkcs12_item_decrypt_d2i(X509_ALGOR *algor, const ASN1_ITEM *it, + const uint8_t *pass_raw, + size_t pass_raw_len, + ASN1_OCTET_STRING *oct) { + uint8_t *out; + const uint8_t *p; + void *ret; + size_t out_len; + + if (!pbe_crypt(algor, pass_raw, pass_raw_len, oct->data, oct->length, + &out, &out_len, 0 /* decrypt */)) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_CRYPT_ERROR); + return NULL; + } + p = out; + ret = ASN1_item_d2i(NULL, &p, out_len, it); + OPENSSL_cleanse(out, out_len); + if (!ret) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR); + } + OPENSSL_free(out); + return ret; +} + +PKCS8_PRIV_KEY_INFO *PKCS8_decrypt(X509_SIG *pkcs8, const char *pass, + int pass_len) { + uint8_t *pass_raw = NULL; + size_t pass_raw_len = 0; + if (!pass_to_pass_raw(OBJ_obj2nid(pkcs8->algor->algorithm), pass, pass_len, + &pass_raw, &pass_raw_len)) { + return NULL; + } + + PKCS8_PRIV_KEY_INFO *ret = PKCS8_decrypt_pbe(pkcs8, pass_raw, pass_raw_len); + + if (pass_raw) { + OPENSSL_cleanse(pass_raw, pass_raw_len); + OPENSSL_free(pass_raw); + } + return ret; +} + +PKCS8_PRIV_KEY_INFO *PKCS8_decrypt_pbe(X509_SIG *pkcs8, const uint8_t *pass_raw, + size_t pass_raw_len) { + return pkcs12_item_decrypt_d2i(pkcs8->algor, + ASN1_ITEM_rptr(PKCS8_PRIV_KEY_INFO), pass_raw, + pass_raw_len, pkcs8->digest); +} + +static ASN1_OCTET_STRING *pkcs12_item_i2d_encrypt(X509_ALGOR *algor, + const ASN1_ITEM *it, + const uint8_t *pass_raw, + size_t pass_raw_len, void *obj) { + ASN1_OCTET_STRING *oct; + uint8_t *in = NULL; + int in_len; + size_t crypt_len; + + oct = M_ASN1_OCTET_STRING_new(); + if (oct == NULL) { + OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE); + return NULL; + } + in_len = ASN1_item_i2d(obj, &in, it); + if (!in) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_ENCODE_ERROR); + return NULL; + } + if (!pbe_crypt(algor, pass_raw, pass_raw_len, in, in_len, &oct->data, &crypt_len, + 1 /* encrypt */)) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_ENCRYPT_ERROR); + OPENSSL_free(in); + return NULL; + } + oct->length = crypt_len; + OPENSSL_cleanse(in, in_len); + OPENSSL_free(in); + return oct; +} + +X509_SIG *PKCS8_encrypt(int pbe_nid, const EVP_CIPHER *cipher, const char *pass, + int pass_len, uint8_t *salt, size_t salt_len, + int iterations, PKCS8_PRIV_KEY_INFO *p8inf) { + uint8_t *pass_raw = NULL; + size_t pass_raw_len = 0; + if (!pass_to_pass_raw(pbe_nid, pass, pass_len, &pass_raw, &pass_raw_len)) { + return NULL; + } + + X509_SIG *ret = PKCS8_encrypt_pbe(pbe_nid, cipher, pass_raw, pass_raw_len, + salt, salt_len, iterations, p8inf); + + if (pass_raw) { + OPENSSL_cleanse(pass_raw, pass_raw_len); + OPENSSL_free(pass_raw); + } + return ret; +} + +X509_SIG *PKCS8_encrypt_pbe(int pbe_nid, const EVP_CIPHER *cipher, + const uint8_t *pass_raw, size_t pass_raw_len, + uint8_t *salt, size_t salt_len, + int iterations, PKCS8_PRIV_KEY_INFO *p8inf) { + X509_SIG *pkcs8 = NULL; + X509_ALGOR *pbe; + + pkcs8 = X509_SIG_new(); + if (pkcs8 == NULL) { + OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (pbe_nid == -1) { + pbe = PKCS5_pbe2_set(cipher, iterations, salt, salt_len); + } else { + pbe = PKCS5_pbe_set(pbe_nid, iterations, salt, salt_len); + } + if (!pbe) { + OPENSSL_PUT_ERROR(PKCS8, ERR_R_ASN1_LIB); + goto err; + } + + X509_ALGOR_free(pkcs8->algor); + pkcs8->algor = pbe; + M_ASN1_OCTET_STRING_free(pkcs8->digest); + pkcs8->digest = pkcs12_item_i2d_encrypt( + pbe, ASN1_ITEM_rptr(PKCS8_PRIV_KEY_INFO), pass_raw, pass_raw_len, p8inf); + if (!pkcs8->digest) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_ENCRYPT_ERROR); + goto err; + } + + return pkcs8; + +err: + X509_SIG_free(pkcs8); + return NULL; +} + +EVP_PKEY *EVP_PKCS82PKEY(PKCS8_PRIV_KEY_INFO *p8) { + uint8_t *der = NULL; + int der_len = i2d_PKCS8_PRIV_KEY_INFO(p8, &der); + if (der_len < 0) { + return NULL; + } + + CBS cbs; + CBS_init(&cbs, der, (size_t)der_len); + EVP_PKEY *ret = EVP_parse_private_key(&cbs); + if (ret == NULL || CBS_len(&cbs) != 0) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR); + EVP_PKEY_free(ret); + OPENSSL_free(der); + return NULL; + } + + OPENSSL_free(der); + return ret; +} + +PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(EVP_PKEY *pkey) { + CBB cbb; + uint8_t *der = NULL; + size_t der_len; + if (!CBB_init(&cbb, 0) || + !EVP_marshal_private_key(&cbb, pkey) || + !CBB_finish(&cbb, &der, &der_len) || + der_len > LONG_MAX) { + CBB_cleanup(&cbb); + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_ENCODE_ERROR); + goto err; + } + + const uint8_t *p = der; + PKCS8_PRIV_KEY_INFO *p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, (long)der_len); + if (p8 == NULL || p != der + der_len) { + PKCS8_PRIV_KEY_INFO_free(p8); + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR); + goto err; + } + + OPENSSL_free(der); + return p8; + +err: + OPENSSL_free(der); + return NULL; +} + +struct pkcs12_context { + EVP_PKEY **out_key; + STACK_OF(X509) *out_certs; + uint8_t *password; + size_t password_len; +}; + +static int PKCS12_handle_content_info(CBS *content_info, unsigned depth, + struct pkcs12_context *ctx); + +/* PKCS12_handle_content_infos parses a series of PKCS#7 ContentInfos in a + * SEQUENCE. */ +static int PKCS12_handle_content_infos(CBS *content_infos, + unsigned depth, + struct pkcs12_context *ctx) { + uint8_t *der_bytes = NULL; + size_t der_len; + CBS in; + int ret = 0; + + /* Generally we only expect depths 0 (the top level, with a + * pkcs7-encryptedData and a pkcs7-data) and depth 1 (the various PKCS#12 + * bags). */ + if (depth > 3) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_PKCS12_TOO_DEEPLY_NESTED); + return 0; + } + + /* Although a BER->DER conversion is done at the beginning of |PKCS12_parse|, + * the ASN.1 data gets wrapped in OCTETSTRINGs and/or encrypted and the + * conversion cannot see through those wrappings. So each time we step + * through one we need to convert to DER again. */ + if (!CBS_asn1_ber_to_der(content_infos, &der_bytes, &der_len)) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); + return 0; + } + + if (der_bytes != NULL) { + CBS_init(&in, der_bytes, der_len); + } else { + CBS_init(&in, CBS_data(content_infos), CBS_len(content_infos)); + } + + if (!CBS_get_asn1(&in, &in, CBS_ASN1_SEQUENCE)) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); + goto err; + } + + while (CBS_len(&in) > 0) { + CBS content_info; + if (!CBS_get_asn1(&in, &content_info, CBS_ASN1_SEQUENCE)) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); + goto err; + } + + if (!PKCS12_handle_content_info(&content_info, depth + 1, ctx)) { + goto err; + } + } + + /* NSS includes additional data after the SEQUENCE, but it's an (unwrapped) + * copy of the same encrypted private key (with the same IV and + * ciphertext)! */ + + ret = 1; + +err: + OPENSSL_free(der_bytes); + return ret; +} + +/* PKCS12_handle_content_info parses a single PKCS#7 ContentInfo element in a + * PKCS#12 structure. */ +static int PKCS12_handle_content_info(CBS *content_info, unsigned depth, + struct pkcs12_context *ctx) { + CBS content_type, wrapped_contents, contents, content_infos; + int nid, ret = 0; + uint8_t *storage = NULL; + + if (!CBS_get_asn1(content_info, &content_type, CBS_ASN1_OBJECT) || + !CBS_get_asn1(content_info, &wrapped_contents, + CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); + goto err; + } + + nid = OBJ_cbs2nid(&content_type); + if (nid == NID_pkcs7_encrypted) { + /* See https://tools.ietf.org/html/rfc2315#section-13. + * + * PKCS#7 encrypted data inside a PKCS#12 structure is generally an + * encrypted certificate bag and it's generally encrypted with 40-bit + * RC2-CBC. */ + CBS version_bytes, eci, contents_type, ai, encrypted_contents; + X509_ALGOR *algor = NULL; + const uint8_t *inp; + uint8_t *out; + size_t out_len; + + if (!CBS_get_asn1(&wrapped_contents, &contents, CBS_ASN1_SEQUENCE) || + !CBS_get_asn1(&contents, &version_bytes, CBS_ASN1_INTEGER) || + /* EncryptedContentInfo, see + * https://tools.ietf.org/html/rfc2315#section-10.1 */ + !CBS_get_asn1(&contents, &eci, CBS_ASN1_SEQUENCE) || + !CBS_get_asn1(&eci, &contents_type, CBS_ASN1_OBJECT) || + /* AlgorithmIdentifier, see + * https://tools.ietf.org/html/rfc5280#section-4.1.1.2 */ + !CBS_get_asn1_element(&eci, &ai, CBS_ASN1_SEQUENCE) || + !CBS_get_asn1_implicit_string( + &eci, &encrypted_contents, &storage, + CBS_ASN1_CONTEXT_SPECIFIC | 0, CBS_ASN1_OCTETSTRING)) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); + goto err; + } + + if (OBJ_cbs2nid(&contents_type) != NID_pkcs7_data || + CBS_len(&ai) > LONG_MAX) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); + goto err; + } + + inp = CBS_data(&ai); + algor = d2i_X509_ALGOR(NULL, &inp, (long)CBS_len(&ai)); + if (algor == NULL) { + goto err; + } + if (inp != CBS_data(&ai) + CBS_len(&ai)) { + X509_ALGOR_free(algor); + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); + goto err; + } + + if (!pbe_crypt(algor, ctx->password, ctx->password_len, + CBS_data(&encrypted_contents), CBS_len(&encrypted_contents), + &out, &out_len, 0 /* decrypt */)) { + X509_ALGOR_free(algor); + goto err; + } + X509_ALGOR_free(algor); + + CBS_init(&content_infos, out, out_len); + ret = PKCS12_handle_content_infos(&content_infos, depth + 1, ctx); + OPENSSL_free(out); + } else if (nid == NID_pkcs7_data) { + CBS octet_string_contents; + + if (!CBS_get_asn1(&wrapped_contents, &octet_string_contents, + CBS_ASN1_OCTETSTRING)) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); + goto err; + } + + ret = PKCS12_handle_content_infos(&octet_string_contents, depth + 1, ctx); + } else if (nid == NID_pkcs8ShroudedKeyBag) { + /* See ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-12/pkcs-12v1.pdf, section + * 4.2.2. */ + const uint8_t *inp = CBS_data(&wrapped_contents); + PKCS8_PRIV_KEY_INFO *pki = NULL; + X509_SIG *encrypted = NULL; + + if (*ctx->out_key) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_MULTIPLE_PRIVATE_KEYS_IN_PKCS12); + goto err; + } + + if (CBS_len(&wrapped_contents) > LONG_MAX) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); + goto err; + } + + /* encrypted isn't actually an X.509 signature, but it has the same + * structure as one and so |X509_SIG| is reused to store it. */ + encrypted = d2i_X509_SIG(NULL, &inp, (long)CBS_len(&wrapped_contents)); + if (encrypted == NULL) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); + goto err; + } + if (inp != CBS_data(&wrapped_contents) + CBS_len(&wrapped_contents)) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); + X509_SIG_free(encrypted); + goto err; + } + + pki = PKCS8_decrypt_pbe(encrypted, ctx->password, ctx->password_len); + X509_SIG_free(encrypted); + if (pki == NULL) { + goto err; + } + + *ctx->out_key = EVP_PKCS82PKEY(pki); + PKCS8_PRIV_KEY_INFO_free(pki); + + if (ctx->out_key == NULL) { + goto err; + } + ret = 1; + } else if (nid == NID_certBag) { + CBS cert_bag, cert_type, wrapped_cert, cert; + + if (!CBS_get_asn1(&wrapped_contents, &cert_bag, CBS_ASN1_SEQUENCE) || + !CBS_get_asn1(&cert_bag, &cert_type, CBS_ASN1_OBJECT) || + !CBS_get_asn1(&cert_bag, &wrapped_cert, + CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) || + !CBS_get_asn1(&wrapped_cert, &cert, CBS_ASN1_OCTETSTRING)) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); + goto err; + } + + if (OBJ_cbs2nid(&cert_type) == NID_x509Certificate) { + if (CBS_len(&cert) > LONG_MAX) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); + goto err; + } + const uint8_t *inp = CBS_data(&cert); + X509 *x509 = d2i_X509(NULL, &inp, (long)CBS_len(&cert)); + if (!x509) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); + goto err; + } + if (inp != CBS_data(&cert) + CBS_len(&cert)) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); + X509_free(x509); + goto err; + } + + if (0 == sk_X509_push(ctx->out_certs, x509)) { + X509_free(x509); + goto err; + } + } + ret = 1; + } else { + /* Unknown element type - ignore it. */ + ret = 1; + } + +err: + OPENSSL_free(storage); + return ret; +} + +int PKCS12_get_key_and_certs(EVP_PKEY **out_key, STACK_OF(X509) *out_certs, + CBS *ber_in, const char *password) { + uint8_t *der_bytes = NULL; + size_t der_len; + CBS in, pfx, mac_data, authsafe, content_type, wrapped_authsafes, authsafes; + uint64_t version; + int ret = 0; + struct pkcs12_context ctx; + const size_t original_out_certs_len = sk_X509_num(out_certs); + + /* The input may be in BER format. */ + if (!CBS_asn1_ber_to_der(ber_in, &der_bytes, &der_len)) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); + return 0; + } + if (der_bytes != NULL) { + CBS_init(&in, der_bytes, der_len); + } else { + CBS_init(&in, CBS_data(ber_in), CBS_len(ber_in)); + } + + *out_key = NULL; + memset(&ctx, 0, sizeof(ctx)); + + /* See ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-12/pkcs-12v1.pdf, section + * four. */ + if (!CBS_get_asn1(&in, &pfx, CBS_ASN1_SEQUENCE) || + CBS_len(&in) != 0 || + !CBS_get_asn1_uint64(&pfx, &version)) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); + goto err; + } + + if (version < 3) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_VERSION); + goto err; + } + + if (!CBS_get_asn1(&pfx, &authsafe, CBS_ASN1_SEQUENCE)) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); + goto err; + } + + if (CBS_len(&pfx) == 0) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_MISSING_MAC); + goto err; + } + + if (!CBS_get_asn1(&pfx, &mac_data, CBS_ASN1_SEQUENCE)) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); + goto err; + } + + /* authsafe is a PKCS#7 ContentInfo. See + * https://tools.ietf.org/html/rfc2315#section-7. */ + if (!CBS_get_asn1(&authsafe, &content_type, CBS_ASN1_OBJECT) || + !CBS_get_asn1(&authsafe, &wrapped_authsafes, + CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); + goto err; + } + + /* The content type can either be |NID_pkcs7_data| or |NID_pkcs7_signed|. The + * latter indicates that it's signed by a public key, which isn't + * supported. */ + if (OBJ_cbs2nid(&content_type) != NID_pkcs7_data) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_PKCS12_PUBLIC_KEY_INTEGRITY_NOT_SUPPORTED); + goto err; + } + + if (!CBS_get_asn1(&wrapped_authsafes, &authsafes, CBS_ASN1_OCTETSTRING)) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); + goto err; + } + + ctx.out_key = out_key; + ctx.out_certs = out_certs; + if (!ascii_to_ucs2(password, password ? strlen(password) : 0, &ctx.password, + &ctx.password_len)) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR); + goto err; + } + + /* Verify the MAC. */ + { + CBS mac, hash_type_seq, hash_oid, salt, expected_mac; + uint64_t iterations; + int hash_nid; + const EVP_MD *md; + uint8_t hmac_key[EVP_MAX_MD_SIZE]; + uint8_t hmac[EVP_MAX_MD_SIZE]; + unsigned hmac_len; + + if (!CBS_get_asn1(&mac_data, &mac, CBS_ASN1_SEQUENCE) || + !CBS_get_asn1(&mac, &hash_type_seq, CBS_ASN1_SEQUENCE) || + !CBS_get_asn1(&hash_type_seq, &hash_oid, CBS_ASN1_OBJECT) || + !CBS_get_asn1(&mac, &expected_mac, CBS_ASN1_OCTETSTRING) || + !CBS_get_asn1(&mac_data, &salt, CBS_ASN1_OCTETSTRING)) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); + goto err; + } + + /* The iteration count is optional and the default is one. */ + iterations = 1; + if (CBS_len(&mac_data) > 0) { + if (!CBS_get_asn1_uint64(&mac_data, &iterations) || + iterations > INT_MAX) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA); + goto err; + } + } + + hash_nid = OBJ_cbs2nid(&hash_oid); + if (hash_nid == NID_undef || + (md = EVP_get_digestbynid(hash_nid)) == NULL) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNKNOWN_HASH); + goto err; + } + + if (!pkcs12_key_gen_raw(ctx.password, ctx.password_len, CBS_data(&salt), + CBS_len(&salt), PKCS12_MAC_ID, iterations, + EVP_MD_size(md), hmac_key, md)) { + goto err; + } + + if (NULL == HMAC(md, hmac_key, EVP_MD_size(md), CBS_data(&authsafes), + CBS_len(&authsafes), hmac, &hmac_len)) { + goto err; + } + + if (!CBS_mem_equal(&expected_mac, hmac, hmac_len)) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_INCORRECT_PASSWORD); + goto err; + } + } + + /* authsafes contains a series of PKCS#7 ContentInfos. */ + if (!PKCS12_handle_content_infos(&authsafes, 0, &ctx)) { + goto err; + } + + ret = 1; + +err: + OPENSSL_free(ctx.password); + OPENSSL_free(der_bytes); + if (!ret) { + EVP_PKEY_free(*out_key); + *out_key = NULL; + while (sk_X509_num(out_certs) > original_out_certs_len) { + X509 *x509 = sk_X509_pop(out_certs); + X509_free(x509); + } + } + + return ret; +} + +void PKCS12_PBE_add(void) {} + +struct pkcs12_st { + uint8_t *ber_bytes; + size_t ber_len; +}; + +PKCS12* d2i_PKCS12(PKCS12 **out_p12, const uint8_t **ber_bytes, size_t ber_len) { + PKCS12 *p12; + + p12 = OPENSSL_malloc(sizeof(PKCS12)); + if (!p12) { + return NULL; + } + + p12->ber_bytes = OPENSSL_malloc(ber_len); + if (!p12->ber_bytes) { + OPENSSL_free(p12); + return NULL; + } + + memcpy(p12->ber_bytes, *ber_bytes, ber_len); + p12->ber_len = ber_len; + *ber_bytes += ber_len; + + if (out_p12) { + PKCS12_free(*out_p12); + + *out_p12 = p12; + } + + return p12; +} + +PKCS12* d2i_PKCS12_bio(BIO *bio, PKCS12 **out_p12) { + size_t used = 0; + BUF_MEM *buf; + const uint8_t *dummy; + static const size_t kMaxSize = 256 * 1024; + PKCS12 *ret = NULL; + + buf = BUF_MEM_new(); + if (buf == NULL) { + return NULL; + } + if (BUF_MEM_grow(buf, 8192) == 0) { + goto out; + } + + for (;;) { + int n = BIO_read(bio, &buf->data[used], buf->length - used); + if (n < 0) { + if (used == 0) { + goto out; + } + /* Workaround a bug in node.js. It uses a memory BIO for this in the wrong + * mode. */ + n = 0; + } + + if (n == 0) { + break; + } + used += n; + + if (used < buf->length) { + continue; + } + + if (buf->length > kMaxSize || + BUF_MEM_grow(buf, buf->length * 2) == 0) { + goto out; + } + } + + dummy = (uint8_t*) buf->data; + ret = d2i_PKCS12(out_p12, &dummy, used); + +out: + BUF_MEM_free(buf); + return ret; +} + +PKCS12* d2i_PKCS12_fp(FILE *fp, PKCS12 **out_p12) { + BIO *bio; + PKCS12 *ret; + + bio = BIO_new_fp(fp, 0 /* don't take ownership */); + if (!bio) { + return NULL; + } + + ret = d2i_PKCS12_bio(bio, out_p12); + BIO_free(bio); + return ret; +} + +int PKCS12_parse(const PKCS12 *p12, const char *password, EVP_PKEY **out_pkey, + X509 **out_cert, STACK_OF(X509) **out_ca_certs) { + CBS ber_bytes; + STACK_OF(X509) *ca_certs = NULL; + char ca_certs_alloced = 0; + + if (out_ca_certs != NULL && *out_ca_certs != NULL) { + ca_certs = *out_ca_certs; + } + + if (!ca_certs) { + ca_certs = sk_X509_new_null(); + if (ca_certs == NULL) { + OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE); + return 0; + } + ca_certs_alloced = 1; + } + + CBS_init(&ber_bytes, p12->ber_bytes, p12->ber_len); + if (!PKCS12_get_key_and_certs(out_pkey, ca_certs, &ber_bytes, password)) { + if (ca_certs_alloced) { + sk_X509_free(ca_certs); + } + return 0; + } + + *out_cert = NULL; + if (sk_X509_num(ca_certs) > 0) { + *out_cert = sk_X509_shift(ca_certs); + } + + if (out_ca_certs) { + *out_ca_certs = ca_certs; + } else { + sk_X509_pop_free(ca_certs, X509_free); + } + + return 1; +} + +int PKCS12_verify_mac(const PKCS12 *p12, const char *password, + int password_len) { + if (password == NULL) { + if (password_len != 0) { + return 0; + } + } else if (password_len != -1 && + (password[password_len] != 0 || + memchr(password, 0, password_len) != NULL)) { + return 0; + } + + EVP_PKEY *pkey = NULL; + X509 *cert = NULL; + if (!PKCS12_parse(p12, password, &pkey, &cert, NULL)) { + ERR_clear_error(); + return 0; + } + + EVP_PKEY_free(pkey); + X509_free(cert); + + return 1; +} + +void PKCS12_free(PKCS12 *p12) { + if (p12 == NULL) { + return; + } + OPENSSL_free(p12->ber_bytes); + OPENSSL_free(p12); +} diff --git a/external/boringssl/crypto/pkcs8/pkcs8_test.cc b/external/boringssl/crypto/pkcs8/pkcs8_test.cc new file mode 100644 index 0000000000..7a88ddf4f0 --- /dev/null +++ b/external/boringssl/crypto/pkcs8/pkcs8_test.cc @@ -0,0 +1,91 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include +#include + +#include +#include +#include +#include + +#include "../test/scoped_types.h" + + +/* kDER is a PKCS#8 encrypted private key. It was generated with: + * + * openssl genrsa 512 > test.key + * openssl pkcs8 -topk8 -in test.key -out test.key.encrypted -v2 des3 -outform der + * hexdump -Cv test.key.encrypted + * + * The password is "testing". + */ +static const uint8_t kDER[] = { + 0x30, 0x82, 0x01, 0x9e, 0x30, 0x40, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x05, + 0x0d, 0x30, 0x33, 0x30, 0x1b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x05, 0x0c, + 0x30, 0x0e, 0x04, 0x08, 0x06, 0xa5, 0x4b, 0x0c, 0x0c, 0x50, 0x8c, 0x19, 0x02, 0x02, 0x08, 0x00, + 0x30, 0x14, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x03, 0x07, 0x04, 0x08, 0x3a, 0xd0, + 0x70, 0x4b, 0x26, 0x50, 0x13, 0x7b, 0x04, 0x82, 0x01, 0x58, 0xa6, 0xee, 0x02, 0xf2, 0xf2, 0x7c, + 0x19, 0x91, 0xe3, 0xce, 0x32, 0x85, 0xc5, 0x01, 0xd9, 0xe3, 0x5e, 0x14, 0xb6, 0xb8, 0x78, 0xad, + 0xda, 0x01, 0xec, 0x9e, 0x42, 0xe8, 0xbf, 0x0b, 0x46, 0x03, 0xbc, 0x92, 0x6f, 0xe4, 0x0f, 0x0f, + 0x48, 0x30, 0x10, 0x10, 0x9b, 0xfb, 0x4b, 0xb9, 0x45, 0xf8, 0xcf, 0xab, 0xa1, 0x18, 0xdd, 0x19, + 0xa4, 0xa4, 0xe1, 0xf0, 0xa1, 0x8d, 0xc2, 0x23, 0xe7, 0x0d, 0x7a, 0x64, 0x21, 0x6b, 0xfa, 0x48, + 0xb9, 0x41, 0xc1, 0x0c, 0x4b, 0xce, 0x6f, 0x1a, 0x91, 0x9b, 0x9f, 0xdd, 0xcf, 0xa9, 0x8d, 0x33, + 0x2c, 0x45, 0x81, 0x5c, 0x5e, 0x67, 0xc6, 0x68, 0x43, 0x62, 0xff, 0x5e, 0x9b, 0x1a, 0x15, 0x3a, + 0x9d, 0x71, 0x3f, 0xbe, 0x32, 0x2f, 0xe5, 0x90, 0x65, 0x65, 0x9c, 0x22, 0xf6, 0x29, 0x2e, 0xcf, + 0x26, 0x16, 0x7b, 0x66, 0x48, 0x55, 0xad, 0x9a, 0x8d, 0x89, 0xf4, 0x48, 0x4f, 0x1f, 0x9d, 0xb8, + 0xfa, 0xe1, 0xf1, 0x3b, 0x39, 0x5c, 0x72, 0xc6, 0xb8, 0x3e, 0x98, 0xe8, 0x77, 0xe8, 0xb6, 0x71, + 0x84, 0xa8, 0x6e, 0xca, 0xaf, 0x62, 0x96, 0x49, 0x8a, 0x21, 0x6f, 0x9e, 0x78, 0x07, 0x97, 0x38, + 0x40, 0x66, 0x42, 0x5a, 0x1b, 0xe0, 0x9b, 0xe9, 0x91, 0x82, 0xe4, 0xea, 0x8f, 0x2a, 0xb2, 0x80, + 0xce, 0xe8, 0x57, 0xd3, 0xac, 0x11, 0x9d, 0xb2, 0x39, 0x0f, 0xe1, 0xce, 0x18, 0x96, 0x38, 0xa1, + 0x19, 0x80, 0x88, 0x81, 0x3d, 0xda, 0xaa, 0x8e, 0x15, 0x27, 0x19, 0x73, 0x0c, 0xf3, 0xaf, 0x45, + 0xe9, 0x1b, 0xad, 0x6c, 0x3d, 0xbf, 0x95, 0xf7, 0xa0, 0x87, 0x0e, 0xde, 0xf1, 0xd8, 0xee, 0xaa, + 0x92, 0x76, 0x8d, 0x32, 0x45, 0xa1, 0xe7, 0xf5, 0x05, 0xd6, 0x2c, 0x67, 0x63, 0x10, 0xfa, 0xde, + 0x80, 0xc7, 0x5b, 0x96, 0x0f, 0x24, 0x50, 0x78, 0x30, 0xe5, 0x89, 0xf3, 0x73, 0xfa, 0x40, 0x11, + 0xd5, 0x26, 0xb8, 0x36, 0x96, 0x98, 0xe6, 0xbd, 0x73, 0x62, 0x56, 0xb9, 0xea, 0x28, 0x16, 0x93, + 0x5b, 0x33, 0xae, 0x83, 0xf9, 0x1f, 0xee, 0xef, 0xc8, 0xbf, 0xc7, 0xb1, 0x47, 0x43, 0xa1, 0xc6, + 0x1a, 0x64, 0x47, 0x02, 0x40, 0x3e, 0xbc, 0x0f, 0x80, 0x71, 0x5c, 0x44, 0x60, 0xbc, 0x78, 0x2e, + 0xd2, 0x77, 0xf8, 0x6e, 0x12, 0x51, 0x89, 0xdb, 0x90, 0x64, 0xcd, 0x76, 0x10, 0x29, 0x73, 0xc2, + 0x2f, 0x94, 0x7b, 0x98, 0xcd, 0xbb, 0x61, 0x16, 0x1d, 0x52, 0x11, 0x73, 0x48, 0xe6, 0x39, 0xfc, + 0xd6, 0x2d, +}; + +static bool test(const uint8_t *der, size_t der_len) { + const uint8_t *data = der; + ScopedX509_SIG sig(d2i_X509_SIG(NULL, &data, der_len)); + if (sig.get() == NULL || data != der + der_len) { + fprintf(stderr, "d2i_X509_SIG failed or did not consume all bytes.\n"); + return false; + } + + static const char kPassword[] = "testing"; + ScopedPKCS8_PRIV_KEY_INFO keypair(PKCS8_decrypt(sig.get(), kPassword, -1)); + if (!keypair) { + fprintf(stderr, "PKCS8_decrypt failed.\n"); + ERR_print_errors_fp(stderr); + return false; + } + + return true; +} + +int main(int argc, char **argv) { + if (!test(kDER, sizeof(kDER))) { + return 1; + } + + printf("PASS\n"); + return 0; +} diff --git a/external/boringssl/crypto/poly1305/CMakeLists.txt b/external/boringssl/crypto/poly1305/CMakeLists.txt new file mode 100644 index 0000000000..e1d5c74607 --- /dev/null +++ b/external/boringssl/crypto/poly1305/CMakeLists.txt @@ -0,0 +1,33 @@ +include_directories(../../include) + +if (${ARCH} STREQUAL "arm") + set( + POLY1305_ARCH_SOURCES + + poly1305_arm_asm.S + ) +endif() + +add_library( + poly1305 + + OBJECT + + poly1305.c + poly1305_arm.c + poly1305_vec.c + + ${POLY1305_ARCH_SOURCES} +) + +if(ENABLE_TESTS) +add_executable( + poly1305_test + + poly1305_test.cc + $ +) + +target_link_libraries(poly1305_test crypto) +add_dependencies(all_tests poly1305_test) +endif() diff --git a/external/boringssl/crypto/poly1305/asm/poly1305-armv4.pl b/external/boringssl/crypto/poly1305/asm/poly1305-armv4.pl new file mode 100755 index 0000000000..9b765cec69 --- /dev/null +++ b/external/boringssl/crypto/poly1305/asm/poly1305-armv4.pl @@ -0,0 +1,1216 @@ +#!/usr/bin/env perl +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# IALU(*)/gcc-4.4 NEON +# +# ARM11xx(ARMv6) 7.78/+100% - +# Cortex-A5 6.30/+130% 2.96 +# Cortex-A8 6.25/+115% 2.36 +# Cortex-A9 5.10/+95% 2.55 +# Cortex-A15 3.79/+85% 1.25(**) +# Snapdragon S4 5.70/+100% 1.48(**) +# +# (*) this is for -march=armv6, i.e. with bunch of ldrb loading data; +# (**) these are trade-off results, they can be improved by ~8% but at +# the cost of 15/12% regression on Cortex-A5/A7, it's even possible +# to improve Cortex-A9 result, but then A5/A7 loose more than 20%; + +$flavour = shift; +if ($flavour=~/^\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; } +else { while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {} } + +if ($flavour && $flavour ne "void") { + $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; + ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or + ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or + die "can't locate arm-xlate.pl"; + + open STDOUT,"| \"$^X\" $xlate $flavour $output"; +} else { + open STDOUT,">$output"; +} + +($ctx,$inp,$len,$padbit)=map("r$_",(0..3)); + +$code.=<<___; +#include + +.text +#if defined(__thumb2__) +.syntax unified +.thumb +#else +.code 32 +#endif + +.globl poly1305_emit +.globl poly1305_blocks +.globl poly1305_init +.type poly1305_init,%function +.align 5 +poly1305_init: +.Lpoly1305_init: + stmdb sp!,{r4-r11} + + eor r3,r3,r3 + cmp $inp,#0 + str r3,[$ctx,#0] @ zero hash value + str r3,[$ctx,#4] + str r3,[$ctx,#8] + str r3,[$ctx,#12] + str r3,[$ctx,#16] + str r3,[$ctx,#36] @ is_base2_26 + add $ctx,$ctx,#20 + +#ifdef __thumb2__ + it eq +#endif + moveq r0,#0 + beq .Lno_key + +#if __ARM_MAX_ARCH__>=7 + adr r11,.Lpoly1305_init + ldr r12,.LOPENSSL_armcap +#endif + ldrb r4,[$inp,#0] + mov r10,#0x0fffffff + ldrb r5,[$inp,#1] + and r3,r10,#-4 @ 0x0ffffffc + ldrb r6,[$inp,#2] + ldrb r7,[$inp,#3] + orr r4,r4,r5,lsl#8 + ldrb r5,[$inp,#4] + orr r4,r4,r6,lsl#16 + ldrb r6,[$inp,#5] + orr r4,r4,r7,lsl#24 + ldrb r7,[$inp,#6] + and r4,r4,r10 + +#if __ARM_MAX_ARCH__>=7 + ldr r12,[r11,r12] @ OPENSSL_armcap_P +# ifdef __APPLE__ + ldr r12,[r12] +# endif +#endif + ldrb r8,[$inp,#7] + orr r5,r5,r6,lsl#8 + ldrb r6,[$inp,#8] + orr r5,r5,r7,lsl#16 + ldrb r7,[$inp,#9] + orr r5,r5,r8,lsl#24 + ldrb r8,[$inp,#10] + and r5,r5,r3 + +#if __ARM_MAX_ARCH__>=7 + tst r12,#ARMV7_NEON @ check for NEON +# ifdef __APPLE__ + adr r9,poly1305_blocks_neon + adr r11,poly1305_blocks +# ifdef __thumb2__ + it ne +# endif + movne r11,r9 + adr r12,poly1305_emit + adr r10,poly1305_emit_neon +# ifdef __thumb2__ + it ne +# endif + movne r12,r10 +# else +# ifdef __thumb2__ + itete eq +# endif + addeq r12,r11,#(poly1305_emit-.Lpoly1305_init) + addne r12,r11,#(poly1305_emit_neon-.Lpoly1305_init) + addeq r11,r11,#(poly1305_blocks-.Lpoly1305_init) + addne r11,r11,#(poly1305_blocks_neon-.Lpoly1305_init) +# endif +# ifdef __thumb2__ + orr r12,r12,#1 @ thumb-ify address + orr r11,r11,#1 +# endif +#endif + ldrb r9,[$inp,#11] + orr r6,r6,r7,lsl#8 + ldrb r7,[$inp,#12] + orr r6,r6,r8,lsl#16 + ldrb r8,[$inp,#13] + orr r6,r6,r9,lsl#24 + ldrb r9,[$inp,#14] + and r6,r6,r3 + + ldrb r10,[$inp,#15] + orr r7,r7,r8,lsl#8 + str r4,[$ctx,#0] + orr r7,r7,r9,lsl#16 + str r5,[$ctx,#4] + orr r7,r7,r10,lsl#24 + str r6,[$ctx,#8] + and r7,r7,r3 + str r7,[$ctx,#12] +#if __ARM_MAX_ARCH__>=7 + stmia r2,{r11,r12} @ fill functions table + mov r0,#1 +#else + mov r0,#0 +#endif +.Lno_key: + ldmia sp!,{r4-r11} +#if __ARM_ARCH__>=5 + ret @ bx lr +#else + tst lr,#1 + moveq pc,lr @ be binary compatible with V4, yet + bx lr @ interoperable with Thumb ISA:-) +#endif +.size poly1305_init,.-poly1305_init +___ +{ +my ($h0,$h1,$h2,$h3,$h4,$r0,$r1,$r2,$r3)=map("r$_",(4..12)); +my ($s1,$s2,$s3)=($r1,$r2,$r3); + +$code.=<<___; +.type poly1305_blocks,%function +.align 5 +poly1305_blocks: + stmdb sp!,{r3-r11,lr} + + ands $len,$len,#-16 + beq .Lno_data + + cmp $padbit,#0 + add $len,$len,$inp @ end pointer + sub sp,sp,#32 + + ldmia $ctx,{$h0-$r3} @ load context + + str $ctx,[sp,#12] @ offload stuff + mov lr,$inp + str $len,[sp,#16] + str $r1,[sp,#20] + str $r2,[sp,#24] + str $r3,[sp,#28] + b .Loop + +.Loop: +#if __ARM_ARCH__<7 + ldrb r0,[lr],#16 @ load input +# ifdef __thumb2__ + it hi +# endif + addhi $h4,$h4,#1 @ 1<<128 + ldrb r1,[lr,#-15] + ldrb r2,[lr,#-14] + ldrb r3,[lr,#-13] + orr r1,r0,r1,lsl#8 + ldrb r0,[lr,#-12] + orr r2,r1,r2,lsl#16 + ldrb r1,[lr,#-11] + orr r3,r2,r3,lsl#24 + ldrb r2,[lr,#-10] + adds $h0,$h0,r3 @ accumulate input + + ldrb r3,[lr,#-9] + orr r1,r0,r1,lsl#8 + ldrb r0,[lr,#-8] + orr r2,r1,r2,lsl#16 + ldrb r1,[lr,#-7] + orr r3,r2,r3,lsl#24 + ldrb r2,[lr,#-6] + adcs $h1,$h1,r3 + + ldrb r3,[lr,#-5] + orr r1,r0,r1,lsl#8 + ldrb r0,[lr,#-4] + orr r2,r1,r2,lsl#16 + ldrb r1,[lr,#-3] + orr r3,r2,r3,lsl#24 + ldrb r2,[lr,#-2] + adcs $h2,$h2,r3 + + ldrb r3,[lr,#-1] + orr r1,r0,r1,lsl#8 + str lr,[sp,#8] @ offload input pointer + orr r2,r1,r2,lsl#16 + add $s1,$r1,$r1,lsr#2 + orr r3,r2,r3,lsl#24 +#else + ldr r0,[lr],#16 @ load input +# ifdef __thumb2__ + it hi +# endif + addhi $h4,$h4,#1 @ padbit + ldr r1,[lr,#-12] + ldr r2,[lr,#-8] + ldr r3,[lr,#-4] +# ifdef __ARMEB__ + rev r0,r0 + rev r1,r1 + rev r2,r2 + rev r3,r3 +# endif + adds $h0,$h0,r0 @ accumulate input + str lr,[sp,#8] @ offload input pointer + adcs $h1,$h1,r1 + add $s1,$r1,$r1,lsr#2 + adcs $h2,$h2,r2 +#endif + add $s2,$r2,$r2,lsr#2 + adcs $h3,$h3,r3 + add $s3,$r3,$r3,lsr#2 + + umull r2,r3,$h1,$r0 + adc $h4,$h4,#0 + umull r0,r1,$h0,$r0 + umlal r2,r3,$h4,$s1 + umlal r0,r1,$h3,$s1 + ldr $r1,[sp,#20] @ reload $r1 + umlal r2,r3,$h2,$s3 + umlal r0,r1,$h1,$s3 + umlal r2,r3,$h3,$s2 + umlal r0,r1,$h2,$s2 + umlal r2,r3,$h0,$r1 + str r0,[sp,#0] @ future $h0 + mul r0,$s2,$h4 + ldr $r2,[sp,#24] @ reload $r2 + adds r2,r2,r1 @ d1+=d0>>32 + eor r1,r1,r1 + adc lr,r3,#0 @ future $h2 + str r2,[sp,#4] @ future $h1 + + mul r2,$s3,$h4 + eor r3,r3,r3 + umlal r0,r1,$h3,$s3 + ldr $r3,[sp,#28] @ reload $r3 + umlal r2,r3,$h3,$r0 + umlal r0,r1,$h2,$r0 + umlal r2,r3,$h2,$r1 + umlal r0,r1,$h1,$r1 + umlal r2,r3,$h1,$r2 + umlal r0,r1,$h0,$r2 + umlal r2,r3,$h0,$r3 + ldr $h0,[sp,#0] + mul $h4,$r0,$h4 + ldr $h1,[sp,#4] + + adds $h2,lr,r0 @ d2+=d1>>32 + ldr lr,[sp,#8] @ reload input pointer + adc r1,r1,#0 + adds $h3,r2,r1 @ d3+=d2>>32 + ldr r0,[sp,#16] @ reload end pointer + adc r3,r3,#0 + add $h4,$h4,r3 @ h4+=d3>>32 + + and r1,$h4,#-4 + and $h4,$h4,#3 + add r1,r1,r1,lsr#2 @ *=5 + adds $h0,$h0,r1 + adcs $h1,$h1,#0 + adcs $h2,$h2,#0 + adc $h3,$h3,#0 + + cmp r0,lr @ done yet? + bhi .Loop + + ldr $ctx,[sp,#12] + add sp,sp,#32 + stmia $ctx,{$h0-$h4} @ store the result + +.Lno_data: +#if __ARM_ARCH__>=5 + ldmia sp!,{r3-r11,pc} +#else + ldmia sp!,{r3-r11,lr} + tst lr,#1 + moveq pc,lr @ be binary compatible with V4, yet + bx lr @ interoperable with Thumb ISA:-) +#endif +.size poly1305_blocks,.-poly1305_blocks +___ +} +{ +my ($ctx,$mac,$nonce)=map("r$_",(0..2)); +my ($h0,$h1,$h2,$h3,$h4,$g0,$g1,$g2,$g3)=map("r$_",(3..11)); +my $g4=$h4; + +$code.=<<___; +.type poly1305_emit,%function +.align 5 +poly1305_emit: + stmdb sp!,{r4-r11} +.Lpoly1305_emit_enter: + + ldmia $ctx,{$h0-$h4} + adds $g0,$h0,#5 @ compare to modulus + adcs $g1,$h1,#0 + adcs $g2,$h2,#0 + adcs $g3,$h3,#0 + adc $g4,$h4,#0 + tst $g4,#4 @ did it carry/borrow? + +#ifdef __thumb2__ + it ne +#endif + movne $h0,$g0 + ldr $g0,[$nonce,#0] +#ifdef __thumb2__ + it ne +#endif + movne $h1,$g1 + ldr $g1,[$nonce,#4] +#ifdef __thumb2__ + it ne +#endif + movne $h2,$g2 + ldr $g2,[$nonce,#8] +#ifdef __thumb2__ + it ne +#endif + movne $h3,$g3 + ldr $g3,[$nonce,#12] + + adds $h0,$h0,$g0 + adcs $h1,$h1,$g1 + adcs $h2,$h2,$g2 + adc $h3,$h3,$g3 + +#if __ARM_ARCH__>=7 +# ifdef __ARMEB__ + rev $h0,$h0 + rev $h1,$h1 + rev $h2,$h2 + rev $h3,$h3 +# endif + str $h0,[$mac,#0] + str $h1,[$mac,#4] + str $h2,[$mac,#8] + str $h3,[$mac,#12] +#else + strb $h0,[$mac,#0] + mov $h0,$h0,lsr#8 + strb $h1,[$mac,#4] + mov $h1,$h1,lsr#8 + strb $h2,[$mac,#8] + mov $h2,$h2,lsr#8 + strb $h3,[$mac,#12] + mov $h3,$h3,lsr#8 + + strb $h0,[$mac,#1] + mov $h0,$h0,lsr#8 + strb $h1,[$mac,#5] + mov $h1,$h1,lsr#8 + strb $h2,[$mac,#9] + mov $h2,$h2,lsr#8 + strb $h3,[$mac,#13] + mov $h3,$h3,lsr#8 + + strb $h0,[$mac,#2] + mov $h0,$h0,lsr#8 + strb $h1,[$mac,#6] + mov $h1,$h1,lsr#8 + strb $h2,[$mac,#10] + mov $h2,$h2,lsr#8 + strb $h3,[$mac,#14] + mov $h3,$h3,lsr#8 + + strb $h0,[$mac,#3] + strb $h1,[$mac,#7] + strb $h2,[$mac,#11] + strb $h3,[$mac,#15] +#endif + ldmia sp!,{r4-r11} +#if __ARM_ARCH__>=5 + ret @ bx lr +#else + tst lr,#1 + moveq pc,lr @ be binary compatible with V4, yet + bx lr @ interoperable with Thumb ISA:-) +#endif +.size poly1305_emit,.-poly1305_emit +___ +{ +my ($R0,$R1,$S1,$R2,$S2,$R3,$S3,$R4,$S4) = map("d$_",(0..9)); +my ($D0,$D1,$D2,$D3,$D4, $H0,$H1,$H2,$H3,$H4) = map("q$_",(5..14)); +my ($T0,$T1,$MASK) = map("q$_",(15,4,0)); + +my ($in2,$zeros,$tbl0,$tbl1) = map("r$_",(4..7)); + +$code.=<<___; +#if __ARM_MAX_ARCH__>=7 +.fpu neon + +.type poly1305_init_neon,%function +.align 5 +poly1305_init_neon: + ldr r4,[$ctx,#20] @ load key base 2^32 + ldr r5,[$ctx,#24] + ldr r6,[$ctx,#28] + ldr r7,[$ctx,#32] + + and r2,r4,#0x03ffffff @ base 2^32 -> base 2^26 + mov r3,r4,lsr#26 + mov r4,r5,lsr#20 + orr r3,r3,r5,lsl#6 + mov r5,r6,lsr#14 + orr r4,r4,r6,lsl#12 + mov r6,r7,lsr#8 + orr r5,r5,r7,lsl#18 + and r3,r3,#0x03ffffff + and r4,r4,#0x03ffffff + and r5,r5,#0x03ffffff + + vdup.32 $R0,r2 @ r^1 in both lanes + add r2,r3,r3,lsl#2 @ *5 + vdup.32 $R1,r3 + add r3,r4,r4,lsl#2 + vdup.32 $S1,r2 + vdup.32 $R2,r4 + add r4,r5,r5,lsl#2 + vdup.32 $S2,r3 + vdup.32 $R3,r5 + add r5,r6,r6,lsl#2 + vdup.32 $S3,r4 + vdup.32 $R4,r6 + vdup.32 $S4,r5 + + mov $zeros,#2 @ counter + +.Lsquare_neon: + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @ d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4 + @ d1 = h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + h2*5*r4 + @ d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4 + @ d3 = h3*r0 + h2*r1 + h1*r2 + h0*r3 + h4*5*r4 + @ d4 = h4*r0 + h3*r1 + h2*r2 + h1*r3 + h0*r4 + + vmull.u32 $D0,$R0,${R0}[1] + vmull.u32 $D1,$R1,${R0}[1] + vmull.u32 $D2,$R2,${R0}[1] + vmull.u32 $D3,$R3,${R0}[1] + vmull.u32 $D4,$R4,${R0}[1] + + vmlal.u32 $D0,$R4,${S1}[1] + vmlal.u32 $D1,$R0,${R1}[1] + vmlal.u32 $D2,$R1,${R1}[1] + vmlal.u32 $D3,$R2,${R1}[1] + vmlal.u32 $D4,$R3,${R1}[1] + + vmlal.u32 $D0,$R3,${S2}[1] + vmlal.u32 $D1,$R4,${S2}[1] + vmlal.u32 $D3,$R1,${R2}[1] + vmlal.u32 $D2,$R0,${R2}[1] + vmlal.u32 $D4,$R2,${R2}[1] + + vmlal.u32 $D0,$R2,${S3}[1] + vmlal.u32 $D3,$R0,${R3}[1] + vmlal.u32 $D1,$R3,${S3}[1] + vmlal.u32 $D2,$R4,${S3}[1] + vmlal.u32 $D4,$R1,${R3}[1] + + vmlal.u32 $D3,$R4,${S4}[1] + vmlal.u32 $D0,$R1,${S4}[1] + vmlal.u32 $D1,$R2,${S4}[1] + vmlal.u32 $D2,$R3,${S4}[1] + vmlal.u32 $D4,$R0,${R4}[1] + + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @ lazy reduction as discussed in "NEON crypto" by D.J. Bernstein + @ and P. Schwabe + + vshr.u64 $T0,$D3,#26 + vmovn.i64 $D3#lo,$D3 + vshr.u64 $T1,$D0,#26 + vmovn.i64 $D0#lo,$D0 + vadd.i64 $D4,$D4,$T0 @ h3 -> h4 + vbic.i32 $D3#lo,#0xfc000000 @ &=0x03ffffff + vadd.i64 $D1,$D1,$T1 @ h0 -> h1 + vbic.i32 $D0#lo,#0xfc000000 + + vshrn.u64 $T0#lo,$D4,#26 + vmovn.i64 $D4#lo,$D4 + vshr.u64 $T1,$D1,#26 + vmovn.i64 $D1#lo,$D1 + vadd.i64 $D2,$D2,$T1 @ h1 -> h2 + vbic.i32 $D4#lo,#0xfc000000 + vbic.i32 $D1#lo,#0xfc000000 + + vadd.i32 $D0#lo,$D0#lo,$T0#lo + vshl.u32 $T0#lo,$T0#lo,#2 + vshrn.u64 $T1#lo,$D2,#26 + vmovn.i64 $D2#lo,$D2 + vadd.i32 $D0#lo,$D0#lo,$T0#lo @ h4 -> h0 + vadd.i32 $D3#lo,$D3#lo,$T1#lo @ h2 -> h3 + vbic.i32 $D2#lo,#0xfc000000 + + vshr.u32 $T0#lo,$D0#lo,#26 + vbic.i32 $D0#lo,#0xfc000000 + vshr.u32 $T1#lo,$D3#lo,#26 + vbic.i32 $D3#lo,#0xfc000000 + vadd.i32 $D1#lo,$D1#lo,$T0#lo @ h0 -> h1 + vadd.i32 $D4#lo,$D4#lo,$T1#lo @ h3 -> h4 + + subs $zeros,$zeros,#1 + beq .Lsquare_break_neon + + add $tbl0,$ctx,#(48+0*9*4) + add $tbl1,$ctx,#(48+1*9*4) + + vtrn.32 $R0,$D0#lo @ r^2:r^1 + vtrn.32 $R2,$D2#lo + vtrn.32 $R3,$D3#lo + vtrn.32 $R1,$D1#lo + vtrn.32 $R4,$D4#lo + + vshl.u32 $S2,$R2,#2 @ *5 + vshl.u32 $S3,$R3,#2 + vshl.u32 $S1,$R1,#2 + vshl.u32 $S4,$R4,#2 + vadd.i32 $S2,$S2,$R2 + vadd.i32 $S1,$S1,$R1 + vadd.i32 $S3,$S3,$R3 + vadd.i32 $S4,$S4,$R4 + + vst4.32 {${R0}[0],${R1}[0],${S1}[0],${R2}[0]},[$tbl0]! + vst4.32 {${R0}[1],${R1}[1],${S1}[1],${R2}[1]},[$tbl1]! + vst4.32 {${S2}[0],${R3}[0],${S3}[0],${R4}[0]},[$tbl0]! + vst4.32 {${S2}[1],${R3}[1],${S3}[1],${R4}[1]},[$tbl1]! + vst1.32 {${S4}[0]},[$tbl0,:32] + vst1.32 {${S4}[1]},[$tbl1,:32] + + b .Lsquare_neon + +.align 4 +.Lsquare_break_neon: + add $tbl0,$ctx,#(48+2*4*9) + add $tbl1,$ctx,#(48+3*4*9) + + vmov $R0,$D0#lo @ r^4:r^3 + vshl.u32 $S1,$D1#lo,#2 @ *5 + vmov $R1,$D1#lo + vshl.u32 $S2,$D2#lo,#2 + vmov $R2,$D2#lo + vshl.u32 $S3,$D3#lo,#2 + vmov $R3,$D3#lo + vshl.u32 $S4,$D4#lo,#2 + vmov $R4,$D4#lo + vadd.i32 $S1,$S1,$D1#lo + vadd.i32 $S2,$S2,$D2#lo + vadd.i32 $S3,$S3,$D3#lo + vadd.i32 $S4,$S4,$D4#lo + + vst4.32 {${R0}[0],${R1}[0],${S1}[0],${R2}[0]},[$tbl0]! + vst4.32 {${R0}[1],${R1}[1],${S1}[1],${R2}[1]},[$tbl1]! + vst4.32 {${S2}[0],${R3}[0],${S3}[0],${R4}[0]},[$tbl0]! + vst4.32 {${S2}[1],${R3}[1],${S3}[1],${R4}[1]},[$tbl1]! + vst1.32 {${S4}[0]},[$tbl0] + vst1.32 {${S4}[1]},[$tbl1] + + ret @ bx lr +.size poly1305_init_neon,.-poly1305_init_neon + +.type poly1305_blocks_neon,%function +.align 5 +poly1305_blocks_neon: + ldr ip,[$ctx,#36] @ is_base2_26 + ands $len,$len,#-16 + beq .Lno_data_neon + + cmp $len,#64 + bhs .Lenter_neon + tst ip,ip @ is_base2_26? + beq poly1305_blocks + +.Lenter_neon: + stmdb sp!,{r4-r7} + vstmdb sp!,{d8-d15} @ ABI specification says so + + tst ip,ip @ is_base2_26? + bne .Lbase2_26_neon + + stmdb sp!,{r1-r3,lr} + bl poly1305_init_neon + + ldr r4,[$ctx,#0] @ load hash value base 2^32 + ldr r5,[$ctx,#4] + ldr r6,[$ctx,#8] + ldr r7,[$ctx,#12] + ldr ip,[$ctx,#16] + + and r2,r4,#0x03ffffff @ base 2^32 -> base 2^26 + mov r3,r4,lsr#26 + veor $D0#lo,$D0#lo,$D0#lo + mov r4,r5,lsr#20 + orr r3,r3,r5,lsl#6 + veor $D1#lo,$D1#lo,$D1#lo + mov r5,r6,lsr#14 + orr r4,r4,r6,lsl#12 + veor $D2#lo,$D2#lo,$D2#lo + mov r6,r7,lsr#8 + orr r5,r5,r7,lsl#18 + veor $D3#lo,$D3#lo,$D3#lo + and r3,r3,#0x03ffffff + orr r6,r6,ip,lsl#24 + veor $D4#lo,$D4#lo,$D4#lo + and r4,r4,#0x03ffffff + mov r1,#1 + and r5,r5,#0x03ffffff + str r1,[$ctx,#36] @ is_base2_26 + + vmov.32 $D0#lo[0],r2 + vmov.32 $D1#lo[0],r3 + vmov.32 $D2#lo[0],r4 + vmov.32 $D3#lo[0],r5 + vmov.32 $D4#lo[0],r6 + adr $zeros,.Lzeros + + ldmia sp!,{r1-r3,lr} + b .Lbase2_32_neon + +.align 4 +.Lbase2_26_neon: + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @ load hash value + + veor $D0#lo,$D0#lo,$D0#lo + veor $D1#lo,$D1#lo,$D1#lo + veor $D2#lo,$D2#lo,$D2#lo + veor $D3#lo,$D3#lo,$D3#lo + veor $D4#lo,$D4#lo,$D4#lo + vld4.32 {$D0#lo[0],$D1#lo[0],$D2#lo[0],$D3#lo[0]},[$ctx]! + adr $zeros,.Lzeros + vld1.32 {$D4#lo[0]},[$ctx] + sub $ctx,$ctx,#16 @ rewind + +.Lbase2_32_neon: + add $in2,$inp,#32 + mov $padbit,$padbit,lsl#24 + tst $len,#31 + beq .Leven + + vld4.32 {$H0#lo[0],$H1#lo[0],$H2#lo[0],$H3#lo[0]},[$inp]! + vmov.32 $H4#lo[0],$padbit + sub $len,$len,#16 + add $in2,$inp,#32 + +# ifdef __ARMEB__ + vrev32.8 $H0,$H0 + vrev32.8 $H3,$H3 + vrev32.8 $H1,$H1 + vrev32.8 $H2,$H2 +# endif + vsri.u32 $H4#lo,$H3#lo,#8 @ base 2^32 -> base 2^26 + vshl.u32 $H3#lo,$H3#lo,#18 + + vsri.u32 $H3#lo,$H2#lo,#14 + vshl.u32 $H2#lo,$H2#lo,#12 + vadd.i32 $H4#hi,$H4#lo,$D4#lo @ add hash value and move to #hi + + vbic.i32 $H3#lo,#0xfc000000 + vsri.u32 $H2#lo,$H1#lo,#20 + vshl.u32 $H1#lo,$H1#lo,#6 + + vbic.i32 $H2#lo,#0xfc000000 + vsri.u32 $H1#lo,$H0#lo,#26 + vadd.i32 $H3#hi,$H3#lo,$D3#lo + + vbic.i32 $H0#lo,#0xfc000000 + vbic.i32 $H1#lo,#0xfc000000 + vadd.i32 $H2#hi,$H2#lo,$D2#lo + + vadd.i32 $H0#hi,$H0#lo,$D0#lo + vadd.i32 $H1#hi,$H1#lo,$D1#lo + + mov $tbl1,$zeros + add $tbl0,$ctx,#48 + + cmp $len,$len + b .Long_tail + +.align 4 +.Leven: + subs $len,$len,#64 +# ifdef __thumb2__ + it lo +# endif + movlo $in2,$zeros + + vmov.i32 $H4,#1<<24 @ padbit, yes, always + vld4.32 {$H0#lo,$H1#lo,$H2#lo,$H3#lo},[$inp] @ inp[0:1] + add $inp,$inp,#64 + vld4.32 {$H0#hi,$H1#hi,$H2#hi,$H3#hi},[$in2] @ inp[2:3] (or 0) + add $in2,$in2,#64 +# ifdef __thumb2__ + itt hi +# endif + addhi $tbl1,$ctx,#(48+1*9*4) + addhi $tbl0,$ctx,#(48+3*9*4) + +# ifdef __ARMEB__ + vrev32.8 $H0,$H0 + vrev32.8 $H3,$H3 + vrev32.8 $H1,$H1 + vrev32.8 $H2,$H2 +# endif + vsri.u32 $H4,$H3,#8 @ base 2^32 -> base 2^26 + vshl.u32 $H3,$H3,#18 + + vsri.u32 $H3,$H2,#14 + vshl.u32 $H2,$H2,#12 + + vbic.i32 $H3,#0xfc000000 + vsri.u32 $H2,$H1,#20 + vshl.u32 $H1,$H1,#6 + + vbic.i32 $H2,#0xfc000000 + vsri.u32 $H1,$H0,#26 + + vbic.i32 $H0,#0xfc000000 + vbic.i32 $H1,#0xfc000000 + + bls .Lskip_loop + + vld4.32 {${R0}[1],${R1}[1],${S1}[1],${R2}[1]},[$tbl1]! @ load r^2 + vld4.32 {${R0}[0],${R1}[0],${S1}[0],${R2}[0]},[$tbl0]! @ load r^4 + vld4.32 {${S2}[1],${R3}[1],${S3}[1],${R4}[1]},[$tbl1]! + vld4.32 {${S2}[0],${R3}[0],${S3}[0],${R4}[0]},[$tbl0]! + b .Loop_neon + +.align 5 +.Loop_neon: + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @ ((inp[0]*r^4+inp[2]*r^2+inp[4])*r^4+inp[6]*r^2 + @ ((inp[1]*r^4+inp[3]*r^2+inp[5])*r^3+inp[7]*r + @ \___________________/ + @ ((inp[0]*r^4+inp[2]*r^2+inp[4])*r^4+inp[6]*r^2+inp[8])*r^2 + @ ((inp[1]*r^4+inp[3]*r^2+inp[5])*r^4+inp[7]*r^2+inp[9])*r + @ \___________________/ \____________________/ + @ + @ Note that we start with inp[2:3]*r^2. This is because it + @ doesn't depend on reduction in previous iteration. + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @ d4 = h4*r0 + h3*r1 + h2*r2 + h1*r3 + h0*r4 + @ d3 = h3*r0 + h2*r1 + h1*r2 + h0*r3 + h4*5*r4 + @ d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4 + @ d1 = h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + h2*5*r4 + @ d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4 + + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @ inp[2:3]*r^2 + + vadd.i32 $H2#lo,$H2#lo,$D2#lo @ accumulate inp[0:1] + vmull.u32 $D2,$H2#hi,${R0}[1] + vadd.i32 $H0#lo,$H0#lo,$D0#lo + vmull.u32 $D0,$H0#hi,${R0}[1] + vadd.i32 $H3#lo,$H3#lo,$D3#lo + vmull.u32 $D3,$H3#hi,${R0}[1] + vmlal.u32 $D2,$H1#hi,${R1}[1] + vadd.i32 $H1#lo,$H1#lo,$D1#lo + vmull.u32 $D1,$H1#hi,${R0}[1] + + vadd.i32 $H4#lo,$H4#lo,$D4#lo + vmull.u32 $D4,$H4#hi,${R0}[1] + subs $len,$len,#64 + vmlal.u32 $D0,$H4#hi,${S1}[1] +# ifdef __thumb2__ + it lo +# endif + movlo $in2,$zeros + vmlal.u32 $D3,$H2#hi,${R1}[1] + vld1.32 ${S4}[1],[$tbl1,:32] + vmlal.u32 $D1,$H0#hi,${R1}[1] + vmlal.u32 $D4,$H3#hi,${R1}[1] + + vmlal.u32 $D0,$H3#hi,${S2}[1] + vmlal.u32 $D3,$H1#hi,${R2}[1] + vmlal.u32 $D4,$H2#hi,${R2}[1] + vmlal.u32 $D1,$H4#hi,${S2}[1] + vmlal.u32 $D2,$H0#hi,${R2}[1] + + vmlal.u32 $D3,$H0#hi,${R3}[1] + vmlal.u32 $D0,$H2#hi,${S3}[1] + vmlal.u32 $D4,$H1#hi,${R3}[1] + vmlal.u32 $D1,$H3#hi,${S3}[1] + vmlal.u32 $D2,$H4#hi,${S3}[1] + + vmlal.u32 $D3,$H4#hi,${S4}[1] + vmlal.u32 $D0,$H1#hi,${S4}[1] + vmlal.u32 $D4,$H0#hi,${R4}[1] + vmlal.u32 $D1,$H2#hi,${S4}[1] + vmlal.u32 $D2,$H3#hi,${S4}[1] + + vld4.32 {$H0#hi,$H1#hi,$H2#hi,$H3#hi},[$in2] @ inp[2:3] (or 0) + add $in2,$in2,#64 + + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @ (hash+inp[0:1])*r^4 and accumulate + + vmlal.u32 $D3,$H3#lo,${R0}[0] + vmlal.u32 $D0,$H0#lo,${R0}[0] + vmlal.u32 $D4,$H4#lo,${R0}[0] + vmlal.u32 $D1,$H1#lo,${R0}[0] + vmlal.u32 $D2,$H2#lo,${R0}[0] + vld1.32 ${S4}[0],[$tbl0,:32] + + vmlal.u32 $D3,$H2#lo,${R1}[0] + vmlal.u32 $D0,$H4#lo,${S1}[0] + vmlal.u32 $D4,$H3#lo,${R1}[0] + vmlal.u32 $D1,$H0#lo,${R1}[0] + vmlal.u32 $D2,$H1#lo,${R1}[0] + + vmlal.u32 $D3,$H1#lo,${R2}[0] + vmlal.u32 $D0,$H3#lo,${S2}[0] + vmlal.u32 $D4,$H2#lo,${R2}[0] + vmlal.u32 $D1,$H4#lo,${S2}[0] + vmlal.u32 $D2,$H0#lo,${R2}[0] + + vmlal.u32 $D3,$H0#lo,${R3}[0] + vmlal.u32 $D0,$H2#lo,${S3}[0] + vmlal.u32 $D4,$H1#lo,${R3}[0] + vmlal.u32 $D1,$H3#lo,${S3}[0] + vmlal.u32 $D3,$H4#lo,${S4}[0] + + vmlal.u32 $D2,$H4#lo,${S3}[0] + vmlal.u32 $D0,$H1#lo,${S4}[0] + vmlal.u32 $D4,$H0#lo,${R4}[0] + vmov.i32 $H4,#1<<24 @ padbit, yes, always + vmlal.u32 $D1,$H2#lo,${S4}[0] + vmlal.u32 $D2,$H3#lo,${S4}[0] + + vld4.32 {$H0#lo,$H1#lo,$H2#lo,$H3#lo},[$inp] @ inp[0:1] + add $inp,$inp,#64 +# ifdef __ARMEB__ + vrev32.8 $H0,$H0 + vrev32.8 $H1,$H1 + vrev32.8 $H2,$H2 + vrev32.8 $H3,$H3 +# endif + + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @ lazy reduction interleaved with base 2^32 -> base 2^26 + + vshr.u64 $T0,$D3,#26 + vmovn.i64 $D3#lo,$D3 + vshr.u64 $T1,$D0,#26 + vmovn.i64 $D0#lo,$D0 + vadd.i64 $D4,$D4,$T0 @ h3 -> h4 + vbic.i32 $D3#lo,#0xfc000000 + vsri.u32 $H4,$H3,#8 @ base 2^32 -> base 2^26 + vadd.i64 $D1,$D1,$T1 @ h0 -> h1 + vshl.u32 $H3,$H3,#18 + vbic.i32 $D0#lo,#0xfc000000 + + vshrn.u64 $T0#lo,$D4,#26 + vmovn.i64 $D4#lo,$D4 + vshr.u64 $T1,$D1,#26 + vmovn.i64 $D1#lo,$D1 + vadd.i64 $D2,$D2,$T1 @ h1 -> h2 + vsri.u32 $H3,$H2,#14 + vbic.i32 $D4#lo,#0xfc000000 + vshl.u32 $H2,$H2,#12 + vbic.i32 $D1#lo,#0xfc000000 + + vadd.i32 $D0#lo,$D0#lo,$T0#lo + vshl.u32 $T0#lo,$T0#lo,#2 + vbic.i32 $H3,#0xfc000000 + vshrn.u64 $T1#lo,$D2,#26 + vmovn.i64 $D2#lo,$D2 + vadd.i32 $D0#lo,$D0#lo,$T0#lo @ h4 -> h0 + vsri.u32 $H2,$H1,#20 + vadd.i32 $D3#lo,$D3#lo,$T1#lo @ h2 -> h3 + vshl.u32 $H1,$H1,#6 + vbic.i32 $D2#lo,#0xfc000000 + vbic.i32 $H2,#0xfc000000 + + vshr.u32 $T0#lo,$D0#lo,#26 + vbic.i32 $D0#lo,#0xfc000000 + vsri.u32 $H1,$H0,#26 + vbic.i32 $H0,#0xfc000000 + vshr.u32 $T1#lo,$D3#lo,#26 + vbic.i32 $D3#lo,#0xfc000000 + vadd.i32 $D1#lo,$D1#lo,$T0#lo @ h0 -> h1 + vadd.i32 $D4#lo,$D4#lo,$T1#lo @ h3 -> h4 + vbic.i32 $H1,#0xfc000000 + + bhi .Loop_neon + +.Lskip_loop: + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @ multiply (inp[0:1]+hash) or inp[2:3] by r^2:r^1 + + add $tbl1,$ctx,#(48+0*9*4) + add $tbl0,$ctx,#(48+1*9*4) + adds $len,$len,#32 +# ifdef __thumb2__ + it ne +# endif + movne $len,#0 + bne .Long_tail + + vadd.i32 $H2#hi,$H2#lo,$D2#lo @ add hash value and move to #hi + vadd.i32 $H0#hi,$H0#lo,$D0#lo + vadd.i32 $H3#hi,$H3#lo,$D3#lo + vadd.i32 $H1#hi,$H1#lo,$D1#lo + vadd.i32 $H4#hi,$H4#lo,$D4#lo + +.Long_tail: + vld4.32 {${R0}[1],${R1}[1],${S1}[1],${R2}[1]},[$tbl1]! @ load r^1 + vld4.32 {${R0}[0],${R1}[0],${S1}[0],${R2}[0]},[$tbl0]! @ load r^2 + + vadd.i32 $H2#lo,$H2#lo,$D2#lo @ can be redundant + vmull.u32 $D2,$H2#hi,$R0 + vadd.i32 $H0#lo,$H0#lo,$D0#lo + vmull.u32 $D0,$H0#hi,$R0 + vadd.i32 $H3#lo,$H3#lo,$D3#lo + vmull.u32 $D3,$H3#hi,$R0 + vadd.i32 $H1#lo,$H1#lo,$D1#lo + vmull.u32 $D1,$H1#hi,$R0 + vadd.i32 $H4#lo,$H4#lo,$D4#lo + vmull.u32 $D4,$H4#hi,$R0 + + vmlal.u32 $D0,$H4#hi,$S1 + vld4.32 {${S2}[1],${R3}[1],${S3}[1],${R4}[1]},[$tbl1]! + vmlal.u32 $D3,$H2#hi,$R1 + vld4.32 {${S2}[0],${R3}[0],${S3}[0],${R4}[0]},[$tbl0]! + vmlal.u32 $D1,$H0#hi,$R1 + vmlal.u32 $D4,$H3#hi,$R1 + vmlal.u32 $D2,$H1#hi,$R1 + + vmlal.u32 $D3,$H1#hi,$R2 + vld1.32 ${S4}[1],[$tbl1,:32] + vmlal.u32 $D0,$H3#hi,$S2 + vld1.32 ${S4}[0],[$tbl0,:32] + vmlal.u32 $D4,$H2#hi,$R2 + vmlal.u32 $D1,$H4#hi,$S2 + vmlal.u32 $D2,$H0#hi,$R2 + + vmlal.u32 $D3,$H0#hi,$R3 +# ifdef __thumb2__ + it ne +# endif + addne $tbl1,$ctx,#(48+2*9*4) + vmlal.u32 $D0,$H2#hi,$S3 +# ifdef __thumb2__ + it ne +# endif + addne $tbl0,$ctx,#(48+3*9*4) + vmlal.u32 $D4,$H1#hi,$R3 + vmlal.u32 $D1,$H3#hi,$S3 + vmlal.u32 $D2,$H4#hi,$S3 + + vmlal.u32 $D3,$H4#hi,$S4 + vorn $MASK,$MASK,$MASK @ all-ones, can be redundant + vmlal.u32 $D0,$H1#hi,$S4 + vshr.u64 $MASK,$MASK,#38 + vmlal.u32 $D4,$H0#hi,$R4 + vmlal.u32 $D1,$H2#hi,$S4 + vmlal.u32 $D2,$H3#hi,$S4 + + beq .Lshort_tail + + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @ (hash+inp[0:1])*r^4:r^3 and accumulate + + vld4.32 {${R0}[1],${R1}[1],${S1}[1],${R2}[1]},[$tbl1]! @ load r^3 + vld4.32 {${R0}[0],${R1}[0],${S1}[0],${R2}[0]},[$tbl0]! @ load r^4 + + vmlal.u32 $D2,$H2#lo,$R0 + vmlal.u32 $D0,$H0#lo,$R0 + vmlal.u32 $D3,$H3#lo,$R0 + vmlal.u32 $D1,$H1#lo,$R0 + vmlal.u32 $D4,$H4#lo,$R0 + + vmlal.u32 $D0,$H4#lo,$S1 + vld4.32 {${S2}[1],${R3}[1],${S3}[1],${R4}[1]},[$tbl1]! + vmlal.u32 $D3,$H2#lo,$R1 + vld4.32 {${S2}[0],${R3}[0],${S3}[0],${R4}[0]},[$tbl0]! + vmlal.u32 $D1,$H0#lo,$R1 + vmlal.u32 $D4,$H3#lo,$R1 + vmlal.u32 $D2,$H1#lo,$R1 + + vmlal.u32 $D3,$H1#lo,$R2 + vld1.32 ${S4}[1],[$tbl1,:32] + vmlal.u32 $D0,$H3#lo,$S2 + vld1.32 ${S4}[0],[$tbl0,:32] + vmlal.u32 $D4,$H2#lo,$R2 + vmlal.u32 $D1,$H4#lo,$S2 + vmlal.u32 $D2,$H0#lo,$R2 + + vmlal.u32 $D3,$H0#lo,$R3 + vmlal.u32 $D0,$H2#lo,$S3 + vmlal.u32 $D4,$H1#lo,$R3 + vmlal.u32 $D1,$H3#lo,$S3 + vmlal.u32 $D2,$H4#lo,$S3 + + vmlal.u32 $D3,$H4#lo,$S4 + vorn $MASK,$MASK,$MASK @ all-ones + vmlal.u32 $D0,$H1#lo,$S4 + vshr.u64 $MASK,$MASK,#38 + vmlal.u32 $D4,$H0#lo,$R4 + vmlal.u32 $D1,$H2#lo,$S4 + vmlal.u32 $D2,$H3#lo,$S4 + +.Lshort_tail: + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @ horizontal addition + + vadd.i64 $D3#lo,$D3#lo,$D3#hi + vadd.i64 $D0#lo,$D0#lo,$D0#hi + vadd.i64 $D4#lo,$D4#lo,$D4#hi + vadd.i64 $D1#lo,$D1#lo,$D1#hi + vadd.i64 $D2#lo,$D2#lo,$D2#hi + + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @ lazy reduction, but without narrowing + + vshr.u64 $T0,$D3,#26 + vand.i64 $D3,$D3,$MASK + vshr.u64 $T1,$D0,#26 + vand.i64 $D0,$D0,$MASK + vadd.i64 $D4,$D4,$T0 @ h3 -> h4 + vadd.i64 $D1,$D1,$T1 @ h0 -> h1 + + vshr.u64 $T0,$D4,#26 + vand.i64 $D4,$D4,$MASK + vshr.u64 $T1,$D1,#26 + vand.i64 $D1,$D1,$MASK + vadd.i64 $D2,$D2,$T1 @ h1 -> h2 + + vadd.i64 $D0,$D0,$T0 + vshl.u64 $T0,$T0,#2 + vshr.u64 $T1,$D2,#26 + vand.i64 $D2,$D2,$MASK + vadd.i64 $D0,$D0,$T0 @ h4 -> h0 + vadd.i64 $D3,$D3,$T1 @ h2 -> h3 + + vshr.u64 $T0,$D0,#26 + vand.i64 $D0,$D0,$MASK + vshr.u64 $T1,$D3,#26 + vand.i64 $D3,$D3,$MASK + vadd.i64 $D1,$D1,$T0 @ h0 -> h1 + vadd.i64 $D4,$D4,$T1 @ h3 -> h4 + + cmp $len,#0 + bne .Leven + + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @ store hash value + + vst4.32 {$D0#lo[0],$D1#lo[0],$D2#lo[0],$D3#lo[0]},[$ctx]! + vst1.32 {$D4#lo[0]},[$ctx] + + vldmia sp!,{d8-d15} @ epilogue + ldmia sp!,{r4-r7} +.Lno_data_neon: + ret @ bx lr +.size poly1305_blocks_neon,.-poly1305_blocks_neon + +.type poly1305_emit_neon,%function +.align 5 +poly1305_emit_neon: + ldr ip,[$ctx,#36] @ is_base2_26 + + stmdb sp!,{r4-r11} + + tst ip,ip + beq .Lpoly1305_emit_enter + + ldmia $ctx,{$h0-$h4} + eor $g0,$g0,$g0 + + adds $h0,$h0,$h1,lsl#26 @ base 2^26 -> base 2^32 + mov $h1,$h1,lsr#6 + adcs $h1,$h1,$h2,lsl#20 + mov $h2,$h2,lsr#12 + adcs $h2,$h2,$h3,lsl#14 + mov $h3,$h3,lsr#18 + adcs $h3,$h3,$h4,lsl#8 + adc $h4,$g0,$h4,lsr#24 @ can be partially reduced ... + + and $g0,$h4,#-4 @ ... so reduce + and $h4,$h3,#3 + add $g0,$g0,$g0,lsr#2 @ *= 5 + adds $h0,$h0,$g0 + adcs $h1,$h1,#0 + adcs $h2,$h2,#0 + adc $h3,$h3,#0 + + adds $g0,$h0,#5 @ compare to modulus + adcs $g1,$h1,#0 + adcs $g2,$h2,#0 + adcs $g3,$h3,#0 + adc $g4,$h4,#0 + tst $g4,#4 @ did it carry/borrow? + +# ifdef __thumb2__ + it ne +# endif + movne $h0,$g0 + ldr $g0,[$nonce,#0] +# ifdef __thumb2__ + it ne +# endif + movne $h1,$g1 + ldr $g1,[$nonce,#4] +# ifdef __thumb2__ + it ne +# endif + movne $h2,$g2 + ldr $g2,[$nonce,#8] +# ifdef __thumb2__ + it ne +# endif + movne $h3,$g3 + ldr $g3,[$nonce,#12] + + adds $h0,$h0,$g0 @ accumulate nonce + adcs $h1,$h1,$g1 + adcs $h2,$h2,$g2 + adc $h3,$h3,$g3 + +# ifdef __ARMEB__ + rev $h0,$h0 + rev $h1,$h1 + rev $h2,$h2 + rev $h3,$h3 +# endif + str $h0,[$mac,#0] @ store the result + str $h1,[$mac,#4] + str $h2,[$mac,#8] + str $h3,[$mac,#12] + + ldmia sp!,{r4-r11} + ret @ bx lr +.size poly1305_emit_neon,.-poly1305_emit_neon + +.align 5 +.Lzeros: +.long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +.LOPENSSL_armcap: +.word OPENSSL_armcap_P-.Lpoly1305_init +#endif +___ +} } +$code.=<<___; +.asciz "Poly1305 for ARMv4/NEON, CRYPTOGAMS by " +.align 2 +#if __ARM_MAX_ARCH__>=7 +.comm OPENSSL_armcap_P,4,4 +#endif +___ + +foreach (split("\n",$code)) { + s/\`([^\`]*)\`/eval $1/geo; + + s/\bq([0-9]+)#(lo|hi)/sprintf "d%d",2*$1+($2 eq "hi")/geo or + s/\bret\b/bx lr/go or + s/\bbx\s+lr\b/.word\t0xe12fff1e/go; # make it possible to compile with -march=armv4 + + print $_,"\n"; +} +close STDOUT; # enforce flush diff --git a/external/boringssl/crypto/poly1305/asm/poly1305-armv8.pl b/external/boringssl/crypto/poly1305/asm/poly1305-armv8.pl new file mode 100755 index 0000000000..1d9a81b8b0 --- /dev/null +++ b/external/boringssl/crypto/poly1305/asm/poly1305-armv8.pl @@ -0,0 +1,925 @@ +#!/usr/bin/env perl +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# This module implements Poly1305 hash for ARMv8. +# +# June 2015 +# +# Numbers are cycles per processed byte with poly1305_blocks alone. +# +# IALU/gcc-4.9 NEON +# +# Apple A7 1.86/+5% 0.72 +# Cortex-A53 2.63/+58% 1.47 +# Cortex-A57 2.70/+7% 1.14 +# Denver 1.39/+50% 1.18(*) +# X-Gene 2.00/+68% 2.19 +# +# (*) estimate based on resources availability is less than 1.0, +# i.e. measured result is worse than expected, presumably binary +# translator is not almighty; + +$flavour=shift; +$output=shift; + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or +die "can't locate arm-xlate.pl"; + +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; + +my ($ctx,$inp,$len,$padbit) = map("x$_",(0..3)); +my ($mac,$nonce)=($inp,$len); + +my ($h0,$h1,$h2,$r0,$r1,$s1,$t0,$t1,$d0,$d1,$d2) = map("x$_",(4..14)); + +$code.=<<___; +#include + +.text + +// forward "declarations" are required for Apple +.extern OPENSSL_armcap_P +.globl poly1305_blocks +.globl poly1305_emit + +.globl poly1305_init +.type poly1305_init,%function +.align 5 +poly1305_init: + cmp $inp,xzr + stp xzr,xzr,[$ctx] // zero hash value + stp xzr,xzr,[$ctx,#16] // [along with is_base2_26] + + csel x0,xzr,x0,eq + b.eq .Lno_key + +#ifdef __ILP32__ + ldrsw $t1,.LOPENSSL_armcap_P +#else + ldr $t1,.LOPENSSL_armcap_P +#endif + adr $t0,.LOPENSSL_armcap_P + + ldp $r0,$r1,[$inp] // load key + mov $s1,#0xfffffffc0fffffff + movk $s1,#0x0fff,lsl#48 + ldr w17,[$t0,$t1] +#ifdef __ARMEB__ + rev $r0,$r0 // flip bytes + rev $r1,$r1 +#endif + and $r0,$r0,$s1 // &=0ffffffc0fffffff + and $s1,$s1,#-4 + and $r1,$r1,$s1 // &=0ffffffc0ffffffc + stp $r0,$r1,[$ctx,#32] // save key value + + tst w17,#ARMV7_NEON + + adr $d0,poly1305_blocks + adr $r0,poly1305_blocks_neon + adr $d1,poly1305_emit + adr $r1,poly1305_emit_neon + + csel $d0,$d0,$r0,eq + csel $d1,$d1,$r1,eq + + stp $d0,$d1,[$len] + + mov x0,#1 +.Lno_key: + ret +.size poly1305_init,.-poly1305_init + +.type poly1305_blocks,%function +.align 5 +poly1305_blocks: + ands $len,$len,#-16 + b.eq .Lno_data + + ldp $h0,$h1,[$ctx] // load hash value + ldp $r0,$r1,[$ctx,#32] // load key value + ldr $h2,[$ctx,#16] + add $s1,$r1,$r1,lsr#2 // s1 = r1 + (r1 >> 2) + b .Loop + +.align 5 +.Loop: + ldp $t0,$t1,[$inp],#16 // load input + sub $len,$len,#16 +#ifdef __ARMEB__ + rev $t0,$t0 + rev $t1,$t1 +#endif + adds $h0,$h0,$t0 // accumulate input + adcs $h1,$h1,$t1 + + mul $d0,$h0,$r0 // h0*r0 + adc $h2,$h2,$padbit + umulh $d1,$h0,$r0 + + mul $t0,$h1,$s1 // h1*5*r1 + umulh $t1,$h1,$s1 + + adds $d0,$d0,$t0 + mul $t0,$h0,$r1 // h0*r1 + adc $d1,$d1,$t1 + umulh $d2,$h0,$r1 + + adds $d1,$d1,$t0 + mul $t0,$h1,$r0 // h1*r0 + adc $d2,$d2,xzr + umulh $t1,$h1,$r0 + + adds $d1,$d1,$t0 + mul $t0,$h2,$s1 // h2*5*r1 + adc $d2,$d2,$t1 + mul $t1,$h2,$r0 // h2*r0 + + adds $d1,$d1,$t0 + adc $d2,$d2,$t1 + + and $t0,$d2,#-4 // final reduction + and $h2,$d2,#3 + add $t0,$t0,$d2,lsr#2 + adds $h0,$d0,$t0 + adc $h1,$d1,xzr + + cbnz $len,.Loop + + stp $h0,$h1,[$ctx] // store hash value + str $h2,[$ctx,#16] + +.Lno_data: + ret +.size poly1305_blocks,.-poly1305_blocks + +.type poly1305_emit,%function +.align 5 +poly1305_emit: + ldp $h0,$h1,[$ctx] // load hash base 2^64 + ldr $h2,[$ctx,#16] + ldp $t0,$t1,[$nonce] // load nonce + + adds $d0,$h0,#5 // compare to modulus + adcs $d1,$h1,xzr + adc $d2,$h2,xzr + + tst $d2,#-4 // see if it's carried/borrowed + + csel $h0,$h0,$d0,eq + csel $h1,$h1,$d1,eq + +#ifdef __ARMEB__ + ror $t0,$t0,#32 // flip nonce words + ror $t1,$t1,#32 +#endif + adds $h0,$h0,$t0 // accumulate nonce + adc $h1,$h1,$t1 +#ifdef __ARMEB__ + rev $h0,$h0 // flip output bytes + rev $h1,$h1 +#endif + stp $h0,$h1,[$mac] // write result + + ret +.size poly1305_emit,.-poly1305_emit +___ +my ($R0,$R1,$S1,$R2,$S2,$R3,$S3,$R4,$S4) = map("v$_.4s",(0..8)); +my ($IN01_0,$IN01_1,$IN01_2,$IN01_3,$IN01_4) = map("v$_.2s",(9..13)); +my ($IN23_0,$IN23_1,$IN23_2,$IN23_3,$IN23_4) = map("v$_.2s",(14..18)); +my ($ACC0,$ACC1,$ACC2,$ACC3,$ACC4) = map("v$_.2d",(19..23)); +my ($H0,$H1,$H2,$H3,$H4) = map("v$_.2s",(24..28)); +my ($T0,$T1,$MASK) = map("v$_",(29..31)); + +my ($in2,$zeros)=("x16","x17"); +my $is_base2_26 = $zeros; # borrow + +$code.=<<___; +.type poly1305_mult,%function +.align 5 +poly1305_mult: + mul $d0,$h0,$r0 // h0*r0 + umulh $d1,$h0,$r0 + + mul $t0,$h1,$s1 // h1*5*r1 + umulh $t1,$h1,$s1 + + adds $d0,$d0,$t0 + mul $t0,$h0,$r1 // h0*r1 + adc $d1,$d1,$t1 + umulh $d2,$h0,$r1 + + adds $d1,$d1,$t0 + mul $t0,$h1,$r0 // h1*r0 + adc $d2,$d2,xzr + umulh $t1,$h1,$r0 + + adds $d1,$d1,$t0 + mul $t0,$h2,$s1 // h2*5*r1 + adc $d2,$d2,$t1 + mul $t1,$h2,$r0 // h2*r0 + + adds $d1,$d1,$t0 + adc $d2,$d2,$t1 + + and $t0,$d2,#-4 // final reduction + and $h2,$d2,#3 + add $t0,$t0,$d2,lsr#2 + adds $h0,$d0,$t0 + adc $h1,$d1,xzr + + ret +.size poly1305_mult,.-poly1305_mult + +.type poly1305_splat,%function +.align 5 +poly1305_splat: + and x12,$h0,#0x03ffffff // base 2^64 -> base 2^26 + ubfx x13,$h0,#26,#26 + extr x14,$h1,$h0,#52 + and x14,x14,#0x03ffffff + ubfx x15,$h1,#14,#26 + extr x16,$h2,$h1,#40 + + str w12,[$ctx,#16*0] // r0 + add w12,w13,w13,lsl#2 // r1*5 + str w13,[$ctx,#16*1] // r1 + add w13,w14,w14,lsl#2 // r2*5 + str w12,[$ctx,#16*2] // s1 + str w14,[$ctx,#16*3] // r2 + add w14,w15,w15,lsl#2 // r3*5 + str w13,[$ctx,#16*4] // s2 + str w15,[$ctx,#16*5] // r3 + add w15,w16,w16,lsl#2 // r4*5 + str w14,[$ctx,#16*6] // s3 + str w16,[$ctx,#16*7] // r4 + str w15,[$ctx,#16*8] // s4 + + ret +.size poly1305_splat,.-poly1305_splat + +.type poly1305_blocks_neon,%function +.align 5 +poly1305_blocks_neon: + ldr $is_base2_26,[$ctx,#24] + cmp $len,#128 + b.hs .Lblocks_neon + cbz $is_base2_26,poly1305_blocks + +.Lblocks_neon: + stp x29,x30,[sp,#-80]! + add x29,sp,#0 + + ands $len,$len,#-16 + b.eq .Lno_data_neon + + cbz $is_base2_26,.Lbase2_64_neon + + ldp w10,w11,[$ctx] // load hash value base 2^26 + ldp w12,w13,[$ctx,#8] + ldr w14,[$ctx,#16] + + tst $len,#31 + b.eq .Leven_neon + + ldp $r0,$r1,[$ctx,#32] // load key value + + add $h0,x10,x11,lsl#26 // base 2^26 -> base 2^64 + lsr $h1,x12,#12 + adds $h0,$h0,x12,lsl#52 + add $h1,$h1,x13,lsl#14 + adc $h1,$h1,xzr + lsr $h2,x14,#24 + adds $h1,$h1,x14,lsl#40 + adc $d2,$h2,xzr // can be partially reduced... + + ldp $d0,$d1,[$inp],#16 // load input + sub $len,$len,#16 + add $s1,$r1,$r1,lsr#2 // s1 = r1 + (r1 >> 2) + + and $t0,$d2,#-4 // ... so reduce + and $h2,$d2,#3 + add $t0,$t0,$d2,lsr#2 + adds $h0,$h0,$t0 + adc $h1,$h1,xzr + +#ifdef __ARMEB__ + rev $d0,$d0 + rev $d1,$d1 +#endif + adds $h0,$h0,$d0 // accumulate input + adcs $h1,$h1,$d1 + adc $h2,$h2,$padbit + + bl poly1305_mult + ldr x30,[sp,#8] + + cbz $padbit,.Lstore_base2_64_neon + + and x10,$h0,#0x03ffffff // base 2^64 -> base 2^26 + ubfx x11,$h0,#26,#26 + extr x12,$h1,$h0,#52 + and x12,x12,#0x03ffffff + ubfx x13,$h1,#14,#26 + extr x14,$h2,$h1,#40 + + cbnz $len,.Leven_neon + + stp w10,w11,[$ctx] // store hash value base 2^26 + stp w12,w13,[$ctx,#8] + str w14,[$ctx,#16] + b .Lno_data_neon + +.align 4 +.Lstore_base2_64_neon: + stp $h0,$h1,[$ctx] // store hash value base 2^64 + stp $h2,xzr,[$ctx,#16] // note that is_base2_26 is zeroed + b .Lno_data_neon + +.align 4 +.Lbase2_64_neon: + ldp $r0,$r1,[$ctx,#32] // load key value + + ldp $h0,$h1,[$ctx] // load hash value base 2^64 + ldr $h2,[$ctx,#16] + + tst $len,#31 + b.eq .Linit_neon + + ldp $d0,$d1,[$inp],#16 // load input + sub $len,$len,#16 + add $s1,$r1,$r1,lsr#2 // s1 = r1 + (r1 >> 2) +#ifdef __ARMEB__ + rev $d0,$d0 + rev $d1,$d1 +#endif + adds $h0,$h0,$d0 // accumulate input + adcs $h1,$h1,$d1 + adc $h2,$h2,$padbit + + bl poly1305_mult + +.Linit_neon: + and x10,$h0,#0x03ffffff // base 2^64 -> base 2^26 + ubfx x11,$h0,#26,#26 + extr x12,$h1,$h0,#52 + and x12,x12,#0x03ffffff + ubfx x13,$h1,#14,#26 + extr x14,$h2,$h1,#40 + + stp d8,d9,[sp,#16] // meet ABI requirements + stp d10,d11,[sp,#32] + stp d12,d13,[sp,#48] + stp d14,d15,[sp,#64] + + fmov ${H0},x10 + fmov ${H1},x11 + fmov ${H2},x12 + fmov ${H3},x13 + fmov ${H4},x14 + + ////////////////////////////////// initialize r^n table + mov $h0,$r0 // r^1 + add $s1,$r1,$r1,lsr#2 // s1 = r1 + (r1 >> 2) + mov $h1,$r1 + mov $h2,xzr + add $ctx,$ctx,#48+12 + bl poly1305_splat + + bl poly1305_mult // r^2 + sub $ctx,$ctx,#4 + bl poly1305_splat + + bl poly1305_mult // r^3 + sub $ctx,$ctx,#4 + bl poly1305_splat + + bl poly1305_mult // r^4 + sub $ctx,$ctx,#4 + bl poly1305_splat + ldr x30,[sp,#8] + + add $in2,$inp,#32 + adr $zeros,.Lzeros + subs $len,$len,#64 + csel $in2,$zeros,$in2,lo + + mov x4,#1 + str x4,[$ctx,#-24] // set is_base2_26 + sub $ctx,$ctx,#48 // restore original $ctx + b .Ldo_neon + +.align 4 +.Leven_neon: + add $in2,$inp,#32 + adr $zeros,.Lzeros + subs $len,$len,#64 + csel $in2,$zeros,$in2,lo + + stp d8,d9,[sp,#16] // meet ABI requirements + stp d10,d11,[sp,#32] + stp d12,d13,[sp,#48] + stp d14,d15,[sp,#64] + + fmov ${H0},x10 + fmov ${H1},x11 + fmov ${H2},x12 + fmov ${H3},x13 + fmov ${H4},x14 + +.Ldo_neon: + ldp x8,x12,[$in2],#16 // inp[2:3] (or zero) + ldp x9,x13,[$in2],#48 + + lsl $padbit,$padbit,#24 + add x15,$ctx,#48 + +#ifdef __ARMEB__ + rev x8,x8 + rev x12,x12 + rev x9,x9 + rev x13,x13 +#endif + and x4,x8,#0x03ffffff // base 2^64 -> base 2^26 + and x5,x9,#0x03ffffff + ubfx x6,x8,#26,#26 + ubfx x7,x9,#26,#26 + add x4,x4,x5,lsl#32 // bfi x4,x5,#32,#32 + extr x8,x12,x8,#52 + extr x9,x13,x9,#52 + add x6,x6,x7,lsl#32 // bfi x6,x7,#32,#32 + fmov $IN23_0,x4 + and x8,x8,#0x03ffffff + and x9,x9,#0x03ffffff + ubfx x10,x12,#14,#26 + ubfx x11,x13,#14,#26 + add x12,$padbit,x12,lsr#40 + add x13,$padbit,x13,lsr#40 + add x8,x8,x9,lsl#32 // bfi x8,x9,#32,#32 + fmov $IN23_1,x6 + add x10,x10,x11,lsl#32 // bfi x10,x11,#32,#32 + add x12,x12,x13,lsl#32 // bfi x12,x13,#32,#32 + fmov $IN23_2,x8 + fmov $IN23_3,x10 + fmov $IN23_4,x12 + + ldp x8,x12,[$inp],#16 // inp[0:1] + ldp x9,x13,[$inp],#48 + + ld1 {$R0,$R1,$S1,$R2},[x15],#64 + ld1 {$S2,$R3,$S3,$R4},[x15],#64 + ld1 {$S4},[x15] + +#ifdef __ARMEB__ + rev x8,x8 + rev x12,x12 + rev x9,x9 + rev x13,x13 +#endif + and x4,x8,#0x03ffffff // base 2^64 -> base 2^26 + and x5,x9,#0x03ffffff + ubfx x6,x8,#26,#26 + ubfx x7,x9,#26,#26 + add x4,x4,x5,lsl#32 // bfi x4,x5,#32,#32 + extr x8,x12,x8,#52 + extr x9,x13,x9,#52 + add x6,x6,x7,lsl#32 // bfi x6,x7,#32,#32 + fmov $IN01_0,x4 + and x8,x8,#0x03ffffff + and x9,x9,#0x03ffffff + ubfx x10,x12,#14,#26 + ubfx x11,x13,#14,#26 + add x12,$padbit,x12,lsr#40 + add x13,$padbit,x13,lsr#40 + add x8,x8,x9,lsl#32 // bfi x8,x9,#32,#32 + fmov $IN01_1,x6 + add x10,x10,x11,lsl#32 // bfi x10,x11,#32,#32 + add x12,x12,x13,lsl#32 // bfi x12,x13,#32,#32 + fmov $IN01_2,x8 + fmov $IN01_3,x10 + fmov $IN01_4,x12 + + b.ls .Lskip_loop + +.align 4 +.Loop_neon: + //////////////////////////////////////////////////////////////// + // ((inp[0]*r^4+inp[2]*r^2+inp[4])*r^4+inp[6]*r^2 + // ((inp[1]*r^4+inp[3]*r^2+inp[5])*r^3+inp[7]*r + // \___________________/ + // ((inp[0]*r^4+inp[2]*r^2+inp[4])*r^4+inp[6]*r^2+inp[8])*r^2 + // ((inp[1]*r^4+inp[3]*r^2+inp[5])*r^4+inp[7]*r^2+inp[9])*r + // \___________________/ \____________________/ + // + // Note that we start with inp[2:3]*r^2. This is because it + // doesn't depend on reduction in previous iteration. + //////////////////////////////////////////////////////////////// + // d4 = h0*r4 + h1*r3 + h2*r2 + h3*r1 + h4*r0 + // d3 = h0*r3 + h1*r2 + h2*r1 + h3*r0 + h4*5*r4 + // d2 = h0*r2 + h1*r1 + h2*r0 + h3*5*r4 + h4*5*r3 + // d1 = h0*r1 + h1*r0 + h2*5*r4 + h3*5*r3 + h4*5*r2 + // d0 = h0*r0 + h1*5*r4 + h2*5*r3 + h3*5*r2 + h4*5*r1 + + subs $len,$len,#64 + umull $ACC4,$IN23_0,${R4}[2] + csel $in2,$zeros,$in2,lo + umull $ACC3,$IN23_0,${R3}[2] + umull $ACC2,$IN23_0,${R2}[2] + ldp x8,x12,[$in2],#16 // inp[2:3] (or zero) + umull $ACC1,$IN23_0,${R1}[2] + ldp x9,x13,[$in2],#48 + umull $ACC0,$IN23_0,${R0}[2] +#ifdef __ARMEB__ + rev x8,x8 + rev x12,x12 + rev x9,x9 + rev x13,x13 +#endif + + umlal $ACC4,$IN23_1,${R3}[2] + and x4,x8,#0x03ffffff // base 2^64 -> base 2^26 + umlal $ACC3,$IN23_1,${R2}[2] + and x5,x9,#0x03ffffff + umlal $ACC2,$IN23_1,${R1}[2] + ubfx x6,x8,#26,#26 + umlal $ACC1,$IN23_1,${R0}[2] + ubfx x7,x9,#26,#26 + umlal $ACC0,$IN23_1,${S4}[2] + add x4,x4,x5,lsl#32 // bfi x4,x5,#32,#32 + + umlal $ACC4,$IN23_2,${R2}[2] + extr x8,x12,x8,#52 + umlal $ACC3,$IN23_2,${R1}[2] + extr x9,x13,x9,#52 + umlal $ACC2,$IN23_2,${R0}[2] + add x6,x6,x7,lsl#32 // bfi x6,x7,#32,#32 + umlal $ACC1,$IN23_2,${S4}[2] + fmov $IN23_0,x4 + umlal $ACC0,$IN23_2,${S3}[2] + and x8,x8,#0x03ffffff + + umlal $ACC4,$IN23_3,${R1}[2] + and x9,x9,#0x03ffffff + umlal $ACC3,$IN23_3,${R0}[2] + ubfx x10,x12,#14,#26 + umlal $ACC2,$IN23_3,${S4}[2] + ubfx x11,x13,#14,#26 + umlal $ACC1,$IN23_3,${S3}[2] + add x8,x8,x9,lsl#32 // bfi x8,x9,#32,#32 + umlal $ACC0,$IN23_3,${S2}[2] + fmov $IN23_1,x6 + + add $IN01_2,$IN01_2,$H2 + add x12,$padbit,x12,lsr#40 + umlal $ACC4,$IN23_4,${R0}[2] + add x13,$padbit,x13,lsr#40 + umlal $ACC3,$IN23_4,${S4}[2] + add x10,x10,x11,lsl#32 // bfi x10,x11,#32,#32 + umlal $ACC2,$IN23_4,${S3}[2] + add x12,x12,x13,lsl#32 // bfi x12,x13,#32,#32 + umlal $ACC1,$IN23_4,${S2}[2] + fmov $IN23_2,x8 + umlal $ACC0,$IN23_4,${S1}[2] + fmov $IN23_3,x10 + + //////////////////////////////////////////////////////////////// + // (hash+inp[0:1])*r^4 and accumulate + + add $IN01_0,$IN01_0,$H0 + fmov $IN23_4,x12 + umlal $ACC3,$IN01_2,${R1}[0] + ldp x8,x12,[$inp],#16 // inp[0:1] + umlal $ACC0,$IN01_2,${S3}[0] + ldp x9,x13,[$inp],#48 + umlal $ACC4,$IN01_2,${R2}[0] + umlal $ACC1,$IN01_2,${S4}[0] + umlal $ACC2,$IN01_2,${R0}[0] +#ifdef __ARMEB__ + rev x8,x8 + rev x12,x12 + rev x9,x9 + rev x13,x13 +#endif + + add $IN01_1,$IN01_1,$H1 + umlal $ACC3,$IN01_0,${R3}[0] + umlal $ACC4,$IN01_0,${R4}[0] + and x4,x8,#0x03ffffff // base 2^64 -> base 2^26 + umlal $ACC2,$IN01_0,${R2}[0] + and x5,x9,#0x03ffffff + umlal $ACC0,$IN01_0,${R0}[0] + ubfx x6,x8,#26,#26 + umlal $ACC1,$IN01_0,${R1}[0] + ubfx x7,x9,#26,#26 + + add $IN01_3,$IN01_3,$H3 + add x4,x4,x5,lsl#32 // bfi x4,x5,#32,#32 + umlal $ACC3,$IN01_1,${R2}[0] + extr x8,x12,x8,#52 + umlal $ACC4,$IN01_1,${R3}[0] + extr x9,x13,x9,#52 + umlal $ACC0,$IN01_1,${S4}[0] + add x6,x6,x7,lsl#32 // bfi x6,x7,#32,#32 + umlal $ACC2,$IN01_1,${R1}[0] + fmov $IN01_0,x4 + umlal $ACC1,$IN01_1,${R0}[0] + and x8,x8,#0x03ffffff + + add $IN01_4,$IN01_4,$H4 + and x9,x9,#0x03ffffff + umlal $ACC3,$IN01_3,${R0}[0] + ubfx x10,x12,#14,#26 + umlal $ACC0,$IN01_3,${S2}[0] + ubfx x11,x13,#14,#26 + umlal $ACC4,$IN01_3,${R1}[0] + add x8,x8,x9,lsl#32 // bfi x8,x9,#32,#32 + umlal $ACC1,$IN01_3,${S3}[0] + fmov $IN01_1,x6 + umlal $ACC2,$IN01_3,${S4}[0] + add x12,$padbit,x12,lsr#40 + + umlal $ACC3,$IN01_4,${S4}[0] + add x13,$padbit,x13,lsr#40 + umlal $ACC0,$IN01_4,${S1}[0] + add x10,x10,x11,lsl#32 // bfi x10,x11,#32,#32 + umlal $ACC4,$IN01_4,${R0}[0] + add x12,x12,x13,lsl#32 // bfi x12,x13,#32,#32 + umlal $ACC1,$IN01_4,${S2}[0] + fmov $IN01_2,x8 + umlal $ACC2,$IN01_4,${S3}[0] + fmov $IN01_3,x10 + + ///////////////////////////////////////////////////////////////// + // lazy reduction as discussed in "NEON crypto" by D.J. Bernstein + // and P. Schwabe + + ushr $T0.2d,$ACC3,#26 + fmov $IN01_4,x12 + xtn $H3,$ACC3 + ushr $T1.2d,$ACC0,#26 + xtn $H0,$ACC0 + add $ACC4,$ACC4,$T0.2d // h3 -> h4 + bic $H3,#0xfc,lsl#24 // &=0x03ffffff + add $ACC1,$ACC1,$T1.2d // h0 -> h1 + bic $H0,#0xfc,lsl#24 + + shrn $T0.2s,$ACC4,#26 + xtn $H4,$ACC4 + ushr $T1.2d,$ACC1,#26 + xtn $H1,$ACC1 + add $ACC2,$ACC2,$T1.2d // h1 -> h2 + bic $H4,#0xfc,lsl#24 + bic $H1,#0xfc,lsl#24 + + add $H0,$H0,$T0.2s + shl $T0.2s,$T0.2s,#2 + shrn $T1.2s,$ACC2,#26 + xtn $H2,$ACC2 + add $H0,$H0,$T0.2s // h4 -> h0 + add $H3,$H3,$T1.2s // h2 -> h3 + bic $H2,#0xfc,lsl#24 + + ushr $T0.2s,$H0,#26 + bic $H0,#0xfc,lsl#24 + ushr $T1.2s,$H3,#26 + bic $H3,#0xfc,lsl#24 + add $H1,$H1,$T0.2s // h0 -> h1 + add $H4,$H4,$T1.2s // h3 -> h4 + + b.hi .Loop_neon + +.Lskip_loop: + dup $IN23_2,${IN23_2}[0] + movi $MASK.2d,#-1 + add $IN01_2,$IN01_2,$H2 + ushr $MASK.2d,$MASK.2d,#38 + + //////////////////////////////////////////////////////////////// + // multiply (inp[0:1]+hash) or inp[2:3] by r^2:r^1 + + adds $len,$len,#32 + b.ne .Long_tail + + dup $IN23_2,${IN01_2}[0] + add $IN23_0,$IN01_0,$H0 + add $IN23_3,$IN01_3,$H3 + add $IN23_1,$IN01_1,$H1 + add $IN23_4,$IN01_4,$H4 + +.Long_tail: + dup $IN23_0,${IN23_0}[0] + umull2 $ACC0,$IN23_2,${S3} + umull2 $ACC3,$IN23_2,${R1} + umull2 $ACC4,$IN23_2,${R2} + umull2 $ACC2,$IN23_2,${R0} + umull2 $ACC1,$IN23_2,${S4} + + dup $IN23_1,${IN23_1}[0] + umlal2 $ACC0,$IN23_0,${R0} + umlal2 $ACC2,$IN23_0,${R2} + umlal2 $ACC3,$IN23_0,${R3} + umlal2 $ACC4,$IN23_0,${R4} + umlal2 $ACC1,$IN23_0,${R1} + + dup $IN23_3,${IN23_3}[0] + umlal2 $ACC0,$IN23_1,${S4} + umlal2 $ACC3,$IN23_1,${R2} + umlal2 $ACC2,$IN23_1,${R1} + umlal2 $ACC4,$IN23_1,${R3} + umlal2 $ACC1,$IN23_1,${R0} + + dup $IN23_4,${IN23_4}[0] + umlal2 $ACC3,$IN23_3,${R0} + umlal2 $ACC4,$IN23_3,${R1} + umlal2 $ACC0,$IN23_3,${S2} + umlal2 $ACC1,$IN23_3,${S3} + umlal2 $ACC2,$IN23_3,${S4} + + umlal2 $ACC3,$IN23_4,${S4} + umlal2 $ACC0,$IN23_4,${S1} + umlal2 $ACC4,$IN23_4,${R0} + umlal2 $ACC1,$IN23_4,${S2} + umlal2 $ACC2,$IN23_4,${S3} + + b.eq .Lshort_tail + + //////////////////////////////////////////////////////////////// + // (hash+inp[0:1])*r^4:r^3 and accumulate + + add $IN01_0,$IN01_0,$H0 + umlal $ACC3,$IN01_2,${R1} + umlal $ACC0,$IN01_2,${S3} + umlal $ACC4,$IN01_2,${R2} + umlal $ACC1,$IN01_2,${S4} + umlal $ACC2,$IN01_2,${R0} + + add $IN01_1,$IN01_1,$H1 + umlal $ACC3,$IN01_0,${R3} + umlal $ACC0,$IN01_0,${R0} + umlal $ACC4,$IN01_0,${R4} + umlal $ACC1,$IN01_0,${R1} + umlal $ACC2,$IN01_0,${R2} + + add $IN01_3,$IN01_3,$H3 + umlal $ACC3,$IN01_1,${R2} + umlal $ACC0,$IN01_1,${S4} + umlal $ACC4,$IN01_1,${R3} + umlal $ACC1,$IN01_1,${R0} + umlal $ACC2,$IN01_1,${R1} + + add $IN01_4,$IN01_4,$H4 + umlal $ACC3,$IN01_3,${R0} + umlal $ACC0,$IN01_3,${S2} + umlal $ACC4,$IN01_3,${R1} + umlal $ACC1,$IN01_3,${S3} + umlal $ACC2,$IN01_3,${S4} + + umlal $ACC3,$IN01_4,${S4} + umlal $ACC0,$IN01_4,${S1} + umlal $ACC4,$IN01_4,${R0} + umlal $ACC1,$IN01_4,${S2} + umlal $ACC2,$IN01_4,${S3} + +.Lshort_tail: + //////////////////////////////////////////////////////////////// + // horizontal add + + addp $ACC3,$ACC3,$ACC3 + ldp d8,d9,[sp,#16] // meet ABI requirements + addp $ACC0,$ACC0,$ACC0 + ldp d10,d11,[sp,#32] + addp $ACC4,$ACC4,$ACC4 + ldp d12,d13,[sp,#48] + addp $ACC1,$ACC1,$ACC1 + ldp d14,d15,[sp,#64] + addp $ACC2,$ACC2,$ACC2 + + //////////////////////////////////////////////////////////////// + // lazy reduction, but without narrowing + + ushr $T0.2d,$ACC3,#26 + and $ACC3,$ACC3,$MASK.2d + ushr $T1.2d,$ACC0,#26 + and $ACC0,$ACC0,$MASK.2d + + add $ACC4,$ACC4,$T0.2d // h3 -> h4 + add $ACC1,$ACC1,$T1.2d // h0 -> h1 + + ushr $T0.2d,$ACC4,#26 + and $ACC4,$ACC4,$MASK.2d + ushr $T1.2d,$ACC1,#26 + and $ACC1,$ACC1,$MASK.2d + add $ACC2,$ACC2,$T1.2d // h1 -> h2 + + add $ACC0,$ACC0,$T0.2d + shl $T0.2d,$T0.2d,#2 + ushr $T1.2d,$ACC2,#26 + and $ACC2,$ACC2,$MASK.2d + add $ACC0,$ACC0,$T0.2d // h4 -> h0 + add $ACC3,$ACC3,$T1.2d // h2 -> h3 + + ushr $T0.2d,$ACC0,#26 + and $ACC0,$ACC0,$MASK.2d + ushr $T1.2d,$ACC3,#26 + and $ACC3,$ACC3,$MASK.2d + add $ACC1,$ACC1,$T0.2d // h0 -> h1 + add $ACC4,$ACC4,$T1.2d // h3 -> h4 + + //////////////////////////////////////////////////////////////// + // write the result, can be partially reduced + + st4 {$ACC0,$ACC1,$ACC2,$ACC3}[0],[$ctx],#16 + st1 {$ACC4}[0],[$ctx] + +.Lno_data_neon: + ldr x29,[sp],#80 + ret +.size poly1305_blocks_neon,.-poly1305_blocks_neon + +.type poly1305_emit_neon,%function +.align 5 +poly1305_emit_neon: + ldr $is_base2_26,[$ctx,#24] + cbz $is_base2_26,poly1305_emit + + ldp w10,w11,[$ctx] // load hash value base 2^26 + ldp w12,w13,[$ctx,#8] + ldr w14,[$ctx,#16] + + add $h0,x10,x11,lsl#26 // base 2^26 -> base 2^64 + lsr $h1,x12,#12 + adds $h0,$h0,x12,lsl#52 + add $h1,$h1,x13,lsl#14 + adc $h1,$h1,xzr + lsr $h2,x14,#24 + adds $h1,$h1,x14,lsl#40 + adc $h2,$h2,xzr // can be partially reduced... + + ldp $t0,$t1,[$nonce] // load nonce + + and $d0,$h2,#-4 // ... so reduce + add $d0,$d0,$h2,lsr#2 + and $h2,$h2,#3 + adds $h0,$h0,$d0 + adc $h1,$h1,xzr + + adds $d0,$h0,#5 // compare to modulus + adcs $d1,$h1,xzr + adc $d2,$h2,xzr + + tst $d2,#-4 // see if it's carried/borrowed + + csel $h0,$h0,$d0,eq + csel $h1,$h1,$d1,eq + +#ifdef __ARMEB__ + ror $t0,$t0,#32 // flip nonce words + ror $t1,$t1,#32 +#endif + adds $h0,$h0,$t0 // accumulate nonce + adc $h1,$h1,$t1 +#ifdef __ARMEB__ + rev $h0,$h0 // flip output bytes + rev $h1,$h1 +#endif + stp $h0,$h1,[$mac] // write result + + ret +.size poly1305_emit_neon,.-poly1305_emit_neon + +.align 5 +.Lzeros: +.long 0,0,0,0,0,0,0,0 +.LOPENSSL_armcap_P: +#ifdef __ILP32__ +.long OPENSSL_armcap_P-. +#else +.quad OPENSSL_armcap_P-. +#endif +.asciz "Poly1305 for ARMv8, CRYPTOGAMS by " +.align 2 +___ + +foreach (split("\n",$code)) { + s/\b(shrn\s+v[0-9]+)\.[24]d/$1.2s/ or + s/\b(fmov\s+)v([0-9]+)[^,]*,\s*x([0-9]+)/$1d$2,x$3/ or + (m/\bdup\b/ and (s/\.[24]s/.2d/g or 1)) or + (m/\b(eor|and)/ and (s/\.[248][sdh]/.16b/g or 1)) or + (m/\bum(ul|la)l\b/ and (s/\.4s/.2s/g or 1)) or + (m/\bum(ul|la)l2\b/ and (s/\.2s/.4s/g or 1)) or + (m/\bst[1-4]\s+{[^}]+}\[/ and (s/\.[24]d/.s/g or 1)); + + s/\.[124]([sd])\[/.$1\[/; + + print $_,"\n"; +} +close STDOUT; diff --git a/external/boringssl/crypto/poly1305/asm/poly1305-x86.pl b/external/boringssl/crypto/poly1305/asm/poly1305-x86.pl new file mode 100755 index 0000000000..4ad2289e6d --- /dev/null +++ b/external/boringssl/crypto/poly1305/asm/poly1305-x86.pl @@ -0,0 +1,1788 @@ +#!/usr/bin/env perl +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# This module implements Poly1305 hash for x86. +# +# April 2015 +# +# Numbers are cycles per processed byte with poly1305_blocks alone, +# measured with rdtsc at fixed clock frequency. +# +# IALU/gcc-3.4(*) SSE2(**) AVX2 +# Pentium 15.7/+80% - +# PIII 6.21/+90% - +# P4 19.8/+40% 3.24 +# Core 2 4.85/+90% 1.80 +# Westmere 4.58/+100% 1.43 +# Sandy Bridge 3.90/+100% 1.36 +# Haswell 3.88/+70% 1.18 0.72 +# Silvermont 11.0/+40% 4.80 +# VIA Nano 6.71/+90% 2.47 +# Sledgehammer 3.51/+180% 4.27 +# Bulldozer 4.53/+140% 1.31 +# +# (*) gcc 4.8 for some reason generated worse code; +# (**) besides SSE2 there are floating-point and AVX options; FP +# is deemed unnecessary, because pre-SSE2 processor are too +# old to care about, while it's not the fastest option on +# SSE2-capable ones; AVX is omitted, because it doesn't give +# a lot of improvement, 5-10% depending on processor; + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +push(@INC,"${dir}","${dir}../../perlasm"); +require "x86asm.pl"; + +&asm_init($ARGV[0],"poly1305-x86.pl",$ARGV[$#ARGV] eq "386"); + +$sse2=$avx=0; +for (@ARGV) { $sse2=1 if (/-DOPENSSL_IA32_SSE2/); } + +if ($sse2) { + &static_label("const_sse2"); + &static_label("enter_blocks"); + &static_label("enter_emit"); + &external_label("OPENSSL_ia32cap_P"); + + # This may be set to 2, but valgrind can't do AVX2 on 32-bit. Without a + # way to verify test coverage, keep it disabled. + $avx = 0; +} + +######################################################################## +# Layout of opaque area is following. +# +# unsigned __int32 h[5]; # current hash value base 2^32 +# unsigned __int32 pad; # is_base2_26 in vector context +# unsigned __int32 r[4]; # key value base 2^32 + +&align(64); +&function_begin("poly1305_init"); + &mov ("edi",&wparam(0)); # context + &mov ("esi",&wparam(1)); # key + &mov ("ebp",&wparam(2)); # function table + + &xor ("eax","eax"); + &mov (&DWP(4*0,"edi"),"eax"); # zero hash value + &mov (&DWP(4*1,"edi"),"eax"); + &mov (&DWP(4*2,"edi"),"eax"); + &mov (&DWP(4*3,"edi"),"eax"); + &mov (&DWP(4*4,"edi"),"eax"); + &mov (&DWP(4*5,"edi"),"eax"); # is_base2_26 + + &cmp ("esi",0); + &je (&label("nokey")); + + if ($sse2) { + &call (&label("pic_point")); + &set_label("pic_point"); + &blindpop("ebx"); + + &lea ("eax",&DWP("poly1305_blocks-".&label("pic_point"),"ebx")); + &lea ("edx",&DWP("poly1305_emit-".&label("pic_point"),"ebx")); + + &picmeup("edi","OPENSSL_ia32cap_P","ebx",&label("pic_point")); + &mov ("ecx",&DWP(0,"edi")); + &and ("ecx",1<<26|1<<24); + &cmp ("ecx",1<<26|1<<24); # SSE2 and XMM? + &jne (&label("no_sse2")); + + &lea ("eax",&DWP("_poly1305_blocks_sse2-".&label("pic_point"),"ebx")); + &lea ("edx",&DWP("_poly1305_emit_sse2-".&label("pic_point"),"ebx")); + + if ($avx>1) { + &mov ("ecx",&DWP(8,"edi")); + &test ("ecx",1<<5); # AVX2? + &jz (&label("no_sse2")); + + &lea ("eax",&DWP("_poly1305_blocks_avx2-".&label("pic_point"),"ebx")); + } + &set_label("no_sse2"); + &mov ("edi",&wparam(0)); # reload context + &mov (&DWP(0,"ebp"),"eax"); # fill function table + &mov (&DWP(4,"ebp"),"edx"); + } + + &mov ("eax",&DWP(4*0,"esi")); # load input key + &mov ("ebx",&DWP(4*1,"esi")); + &mov ("ecx",&DWP(4*2,"esi")); + &mov ("edx",&DWP(4*3,"esi")); + &and ("eax",0x0fffffff); + &and ("ebx",0x0ffffffc); + &and ("ecx",0x0ffffffc); + &and ("edx",0x0ffffffc); + &mov (&DWP(4*6,"edi"),"eax"); + &mov (&DWP(4*7,"edi"),"ebx"); + &mov (&DWP(4*8,"edi"),"ecx"); + &mov (&DWP(4*9,"edi"),"edx"); + + &mov ("eax",$sse2); +&set_label("nokey"); +&function_end("poly1305_init"); + +($h0,$h1,$h2,$h3,$h4, + $d0,$d1,$d2,$d3, + $r0,$r1,$r2,$r3, + $s1,$s2,$s3)=map(4*$_,(0..15)); + +&function_begin("poly1305_blocks"); + &mov ("edi",&wparam(0)); # ctx + &mov ("esi",&wparam(1)); # inp + &mov ("ecx",&wparam(2)); # len +&set_label("enter_blocks"); + &and ("ecx",-15); + &jz (&label("nodata")); + + &stack_push(16); + &mov ("eax",&DWP(4*6,"edi")); # r0 + &mov ("ebx",&DWP(4*7,"edi")); # r1 + &lea ("ebp",&DWP(0,"esi","ecx")); # end of input + &mov ("ecx",&DWP(4*8,"edi")); # r2 + &mov ("edx",&DWP(4*9,"edi")); # r3 + + &mov (&wparam(2),"ebp"); + &mov ("ebp","esi"); + + &mov (&DWP($r0,"esp"),"eax"); # r0 + &mov ("eax","ebx"); + &shr ("eax",2); + &mov (&DWP($r1,"esp"),"ebx"); # r1 + &add ("eax","ebx"); # s1 + &mov ("ebx","ecx"); + &shr ("ebx",2); + &mov (&DWP($r2,"esp"),"ecx"); # r2 + &add ("ebx","ecx"); # s2 + &mov ("ecx","edx"); + &shr ("ecx",2); + &mov (&DWP($r3,"esp"),"edx"); # r3 + &add ("ecx","edx"); # s3 + &mov (&DWP($s1,"esp"),"eax"); # s1 + &mov (&DWP($s2,"esp"),"ebx"); # s2 + &mov (&DWP($s3,"esp"),"ecx"); # s3 + + &mov ("eax",&DWP(4*0,"edi")); # load hash value + &mov ("ebx",&DWP(4*1,"edi")); + &mov ("ecx",&DWP(4*2,"edi")); + &mov ("esi",&DWP(4*3,"edi")); + &mov ("edi",&DWP(4*4,"edi")); + &jmp (&label("loop")); + +&set_label("loop",32); + &add ("eax",&DWP(4*0,"ebp")); # accumulate input + &adc ("ebx",&DWP(4*1,"ebp")); + &adc ("ecx",&DWP(4*2,"ebp")); + &adc ("esi",&DWP(4*3,"ebp")); + &lea ("ebp",&DWP(4*4,"ebp")); + &adc ("edi",&wparam(3)); # padbit + + &mov (&DWP($h0,"esp"),"eax"); # put aside hash[+inp] + &mov (&DWP($h3,"esp"),"esi"); + + &mul (&DWP($r0,"esp")); # h0*r0 + &mov (&DWP($h4,"esp"),"edi"); + &mov ("edi","eax"); + &mov ("eax","ebx"); # h1 + &mov ("esi","edx"); + &mul (&DWP($s3,"esp")); # h1*s3 + &add ("edi","eax"); + &mov ("eax","ecx"); # h2 + &adc ("esi","edx"); + &mul (&DWP($s2,"esp")); # h2*s2 + &add ("edi","eax"); + &mov ("eax",&DWP($h3,"esp")); + &adc ("esi","edx"); + &mul (&DWP($s1,"esp")); # h3*s1 + &add ("edi","eax"); + &mov ("eax",&DWP($h0,"esp")); + &adc ("esi","edx"); + + &mul (&DWP($r1,"esp")); # h0*r1 + &mov (&DWP($d0,"esp"),"edi"); + &xor ("edi","edi"); + &add ("esi","eax"); + &mov ("eax","ebx"); # h1 + &adc ("edi","edx"); + &mul (&DWP($r0,"esp")); # h1*r0 + &add ("esi","eax"); + &mov ("eax","ecx"); # h2 + &adc ("edi","edx"); + &mul (&DWP($s3,"esp")); # h2*s3 + &add ("esi","eax"); + &mov ("eax",&DWP($h3,"esp")); + &adc ("edi","edx"); + &mul (&DWP($s2,"esp")); # h3*s2 + &add ("esi","eax"); + &mov ("eax",&DWP($h4,"esp")); + &adc ("edi","edx"); + &imul ("eax",&DWP($s1,"esp")); # h4*s1 + &add ("esi","eax"); + &mov ("eax",&DWP($h0,"esp")); + &adc ("edi",0); + + &mul (&DWP($r2,"esp")); # h0*r2 + &mov (&DWP($d1,"esp"),"esi"); + &xor ("esi","esi"); + &add ("edi","eax"); + &mov ("eax","ebx"); # h1 + &adc ("esi","edx"); + &mul (&DWP($r1,"esp")); # h1*r1 + &add ("edi","eax"); + &mov ("eax","ecx"); # h2 + &adc ("esi","edx"); + &mul (&DWP($r0,"esp")); # h2*r0 + &add ("edi","eax"); + &mov ("eax",&DWP($h3,"esp")); + &adc ("esi","edx"); + &mul (&DWP($s3,"esp")); # h3*s3 + &add ("edi","eax"); + &mov ("eax",&DWP($h4,"esp")); + &adc ("esi","edx"); + &imul ("eax",&DWP($s2,"esp")); # h4*s2 + &add ("edi","eax"); + &mov ("eax",&DWP($h0,"esp")); + &adc ("esi",0); + + &mul (&DWP($r3,"esp")); # h0*r3 + &mov (&DWP($d2,"esp"),"edi"); + &xor ("edi","edi"); + &add ("esi","eax"); + &mov ("eax","ebx"); # h1 + &adc ("edi","edx"); + &mul (&DWP($r2,"esp")); # h1*r2 + &add ("esi","eax"); + &mov ("eax","ecx"); # h2 + &adc ("edi","edx"); + &mul (&DWP($r1,"esp")); # h2*r1 + &add ("esi","eax"); + &mov ("eax",&DWP($h3,"esp")); + &adc ("edi","edx"); + &mul (&DWP($r0,"esp")); # h3*r0 + &add ("esi","eax"); + &mov ("ecx",&DWP($h4,"esp")); + &adc ("edi","edx"); + + &mov ("edx","ecx"); + &imul ("ecx",&DWP($s3,"esp")); # h4*s3 + &add ("esi","ecx"); + &mov ("eax",&DWP($d0,"esp")); + &adc ("edi",0); + + &imul ("edx",&DWP($r0,"esp")); # h4*r0 + &add ("edx","edi"); + + &mov ("ebx",&DWP($d1,"esp")); + &mov ("ecx",&DWP($d2,"esp")); + + &mov ("edi","edx"); # last reduction step + &shr ("edx",2); + &and ("edi",3); + &lea ("edx",&DWP(0,"edx","edx",4)); # *5 + &add ("eax","edx"); + &adc ("ebx",0); + &adc ("ecx",0); + &adc ("esi",0); + + &cmp ("ebp",&wparam(2)); # done yet? + &jne (&label("loop")); + + &mov ("edx",&wparam(0)); # ctx + &stack_pop(16); + &mov (&DWP(4*0,"edx"),"eax"); # store hash value + &mov (&DWP(4*1,"edx"),"ebx"); + &mov (&DWP(4*2,"edx"),"ecx"); + &mov (&DWP(4*3,"edx"),"esi"); + &mov (&DWP(4*4,"edx"),"edi"); +&set_label("nodata"); +&function_end("poly1305_blocks"); + +&function_begin("poly1305_emit"); + &mov ("ebp",&wparam(0)); # context +&set_label("enter_emit"); + &mov ("edi",&wparam(1)); # output + &mov ("eax",&DWP(4*0,"ebp")); # load hash value + &mov ("ebx",&DWP(4*1,"ebp")); + &mov ("ecx",&DWP(4*2,"ebp")); + &mov ("edx",&DWP(4*3,"ebp")); + &mov ("esi",&DWP(4*4,"ebp")); + + &add ("eax",5); # compare to modulus + &adc ("ebx",0); + &adc ("ecx",0); + &adc ("edx",0); + &adc ("esi",0); + &shr ("esi",2); # did it carry/borrow? + &neg ("esi"); # do we choose hash-modulus? + + &and ("eax","esi"); + &and ("ebx","esi"); + &and ("ecx","esi"); + &and ("edx","esi"); + &mov (&DWP(4*0,"edi"),"eax"); + &mov (&DWP(4*1,"edi"),"ebx"); + &mov (&DWP(4*2,"edi"),"ecx"); + &mov (&DWP(4*3,"edi"),"edx"); + + ¬ ("esi"); # or original hash value? + &mov ("eax",&DWP(4*0,"ebp")); + &mov ("ebx",&DWP(4*1,"ebp")); + &mov ("ecx",&DWP(4*2,"ebp")); + &mov ("edx",&DWP(4*3,"ebp")); + &mov ("ebp",&wparam(2)); + &and ("eax","esi"); + &and ("ebx","esi"); + &and ("ecx","esi"); + &and ("edx","esi"); + &or ("eax",&DWP(4*0,"edi")); + &or ("ebx",&DWP(4*1,"edi")); + &or ("ecx",&DWP(4*2,"edi")); + &or ("edx",&DWP(4*3,"edi")); + + &add ("eax",&DWP(4*0,"ebp")); # accumulate key + &adc ("ebx",&DWP(4*1,"ebp")); + &adc ("ecx",&DWP(4*2,"ebp")); + &adc ("edx",&DWP(4*3,"ebp")); + + &mov (&DWP(4*0,"edi"),"eax"); + &mov (&DWP(4*1,"edi"),"ebx"); + &mov (&DWP(4*2,"edi"),"ecx"); + &mov (&DWP(4*3,"edi"),"edx"); +&function_end("poly1305_emit"); + +if ($sse2) { +######################################################################## +# Layout of opaque area is following. +# +# unsigned __int32 h[5]; # current hash value base 2^26 +# unsigned __int32 is_base2_26; +# unsigned __int32 r[4]; # key value base 2^32 +# unsigned __int32 pad[2]; +# struct { unsigned __int32 r^4, r^3, r^2, r^1; } r[9]; +# +# where r^n are base 2^26 digits of degrees of multiplier key. There are +# 5 digits, but last four are interleaved with multiples of 5, totalling +# in 9 elements: r0, r1, 5*r1, r2, 5*r2, r3, 5*r3, r4, 5*r4. + +my ($D0,$D1,$D2,$D3,$D4,$T0,$T1,$T2)=map("xmm$_",(0..7)); +my $MASK=$T2; # borrow and keep in mind + +&align (32); +&function_begin_B("_poly1305_init_sse2"); + &movdqu ($D4,&QWP(4*6,"edi")); # key base 2^32 + &lea ("edi",&DWP(16*3,"edi")); # size optimization + &mov ("ebp","esp"); + &sub ("esp",16*(9+5)); + &and ("esp",-16); + + #&pand ($D4,&QWP(96,"ebx")); # magic mask + &movq ($MASK,&QWP(64,"ebx")); + + &movdqa ($D0,$D4); + &movdqa ($D1,$D4); + &movdqa ($D2,$D4); + + &pand ($D0,$MASK); # -> base 2^26 + &psrlq ($D1,26); + &psrldq ($D2,6); + &pand ($D1,$MASK); + &movdqa ($D3,$D2); + &psrlq ($D2,4) + &psrlq ($D3,30); + &pand ($D2,$MASK); + &pand ($D3,$MASK); + &psrldq ($D4,13); + + &lea ("edx",&DWP(16*9,"esp")); # size optimization + &mov ("ecx",2); +&set_label("square"); + &movdqa (&QWP(16*0,"esp"),$D0); + &movdqa (&QWP(16*1,"esp"),$D1); + &movdqa (&QWP(16*2,"esp"),$D2); + &movdqa (&QWP(16*3,"esp"),$D3); + &movdqa (&QWP(16*4,"esp"),$D4); + + &movdqa ($T1,$D1); + &movdqa ($T0,$D2); + &pslld ($T1,2); + &pslld ($T0,2); + &paddd ($T1,$D1); # *5 + &paddd ($T0,$D2); # *5 + &movdqa (&QWP(16*5,"esp"),$T1); + &movdqa (&QWP(16*6,"esp"),$T0); + &movdqa ($T1,$D3); + &movdqa ($T0,$D4); + &pslld ($T1,2); + &pslld ($T0,2); + &paddd ($T1,$D3); # *5 + &paddd ($T0,$D4); # *5 + &movdqa (&QWP(16*7,"esp"),$T1); + &movdqa (&QWP(16*8,"esp"),$T0); + + &pshufd ($T1,$D0,0b01000100); + &movdqa ($T0,$D1); + &pshufd ($D1,$D1,0b01000100); + &pshufd ($D2,$D2,0b01000100); + &pshufd ($D3,$D3,0b01000100); + &pshufd ($D4,$D4,0b01000100); + &movdqa (&QWP(16*0,"edx"),$T1); + &movdqa (&QWP(16*1,"edx"),$D1); + &movdqa (&QWP(16*2,"edx"),$D2); + &movdqa (&QWP(16*3,"edx"),$D3); + &movdqa (&QWP(16*4,"edx"),$D4); + + ################################################################ + # d4 = h4*r0 + h3*r1 + h2*r2 + h1*r3 + h0*r4 + # d3 = h3*r0 + h2*r1 + h1*r2 + h0*r3 + h4*5*r4 + # d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4 + # d1 = h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + h2*5*r4 + # d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4 + + &pmuludq ($D4,$D0); # h4*r0 + &pmuludq ($D3,$D0); # h3*r0 + &pmuludq ($D2,$D0); # h2*r0 + &pmuludq ($D1,$D0); # h1*r0 + &pmuludq ($D0,$T1); # h0*r0 + +sub pmuladd { +my $load = shift; +my $base = shift; $base = "esp" if (!defined($base)); + + ################################################################ + # As for choice to "rotate" $T0-$T2 in order to move paddq + # past next multiplication. While it makes code harder to read + # and doesn't have significant effect on most processors, it + # makes a lot of difference on Atom, up to 30% improvement. + + &movdqa ($T1,$T0); + &pmuludq ($T0,&QWP(16*3,$base)); # r1*h3 + &movdqa ($T2,$T1); + &pmuludq ($T1,&QWP(16*2,$base)); # r1*h2 + &paddq ($D4,$T0); + &movdqa ($T0,$T2); + &pmuludq ($T2,&QWP(16*1,$base)); # r1*h1 + &paddq ($D3,$T1); + &$load ($T1,5); # s1 + &pmuludq ($T0,&QWP(16*0,$base)); # r1*h0 + &paddq ($D2,$T2); + &pmuludq ($T1,&QWP(16*4,$base)); # s1*h4 + &$load ($T2,2); # r2^n + &paddq ($D1,$T0); + + &movdqa ($T0,$T2); + &pmuludq ($T2,&QWP(16*2,$base)); # r2*h2 + &paddq ($D0,$T1); + &movdqa ($T1,$T0); + &pmuludq ($T0,&QWP(16*1,$base)); # r2*h1 + &paddq ($D4,$T2); + &$load ($T2,6); # s2^n + &pmuludq ($T1,&QWP(16*0,$base)); # r2*h0 + &paddq ($D3,$T0); + &movdqa ($T0,$T2); + &pmuludq ($T2,&QWP(16*4,$base)); # s2*h4 + &paddq ($D2,$T1); + &pmuludq ($T0,&QWP(16*3,$base)); # s2*h3 + &$load ($T1,3); # r3^n + &paddq ($D1,$T2); + + &movdqa ($T2,$T1); + &pmuludq ($T1,&QWP(16*1,$base)); # r3*h1 + &paddq ($D0,$T0); + &$load ($T0,7); # s3^n + &pmuludq ($T2,&QWP(16*0,$base)); # r3*h0 + &paddq ($D4,$T1); + &movdqa ($T1,$T0); + &pmuludq ($T0,&QWP(16*4,$base)); # s3*h4 + &paddq ($D3,$T2); + &movdqa ($T2,$T1); + &pmuludq ($T1,&QWP(16*3,$base)); # s3*h3 + &paddq ($D2,$T0); + &pmuludq ($T2,&QWP(16*2,$base)); # s3*h2 + &$load ($T0,4); # r4^n + &paddq ($D1,$T1); + + &$load ($T1,8); # s4^n + &pmuludq ($T0,&QWP(16*0,$base)); # r4*h0 + &paddq ($D0,$T2); + &movdqa ($T2,$T1); + &pmuludq ($T1,&QWP(16*4,$base)); # s4*h4 + &paddq ($D4,$T0); + &movdqa ($T0,$T2); + &pmuludq ($T2,&QWP(16*1,$base)); # s4*h1 + &paddq ($D3,$T1); + &movdqa ($T1,$T0); + &pmuludq ($T0,&QWP(16*2,$base)); # s4*h2 + &paddq ($D0,$T2); + &pmuludq ($T1,&QWP(16*3,$base)); # s4*h3 + &movdqa ($MASK,&QWP(64,"ebx")); + &paddq ($D1,$T0); + &paddq ($D2,$T1); +} + &pmuladd (sub { my ($reg,$i)=@_; + &movdqa ($reg,&QWP(16*$i,"esp")); + },"edx"); + +sub lazy_reduction { +my $extra = shift; +my $paddx = defined($extra) ? paddq : paddd; + + ################################################################ + # lazy reduction as discussed in "NEON crypto" by D.J. Bernstein + # and P. Schwabe + + &movdqa ($T0,$D3); + &pand ($D3,$MASK); + &psrlq ($T0,26); + &$extra () if (defined($extra)); + &paddq ($T0,$D4); # h3 -> h4 + &movdqa ($T1,$D0); + &pand ($D0,$MASK); + &psrlq ($T1,26); + &movdqa ($D4,$T0); + &paddq ($T1,$D1); # h0 -> h1 + &psrlq ($T0,26); + &pand ($D4,$MASK); + &movdqa ($D1,$T1); + &psrlq ($T1,26); + &paddd ($D0,$T0); # favour paddd when + # possible, because + # paddq is "broken" + # on Atom + &psllq ($T0,2); + &paddq ($T1,$D2); # h1 -> h2 + &$paddx ($T0,$D0); # h4 -> h0 + &pand ($D1,$MASK); + &movdqa ($D2,$T1); + &psrlq ($T1,26); + &pand ($D2,$MASK); + &paddd ($T1,$D3); # h2 -> h3 + &movdqa ($D0,$T0); + &psrlq ($T0,26); + &movdqa ($D3,$T1); + &psrlq ($T1,26); + &pand ($D0,$MASK); + &paddd ($D1,$T0); # h0 -> h1 + &pand ($D3,$MASK); + &paddd ($D4,$T1); # h3 -> h4 +} + &lazy_reduction (); + + &dec ("ecx"); + &jz (&label("square_break")); + + &punpcklqdq ($D0,&QWP(16*0,"esp")); # 0:r^1:0:r^2 + &punpcklqdq ($D1,&QWP(16*1,"esp")); + &punpcklqdq ($D2,&QWP(16*2,"esp")); + &punpcklqdq ($D3,&QWP(16*3,"esp")); + &punpcklqdq ($D4,&QWP(16*4,"esp")); + &jmp (&label("square")); + +&set_label("square_break"); + &psllq ($D0,32); # -> r^3:0:r^4:0 + &psllq ($D1,32); + &psllq ($D2,32); + &psllq ($D3,32); + &psllq ($D4,32); + &por ($D0,&QWP(16*0,"esp")); # r^3:r^1:r^4:r^2 + &por ($D1,&QWP(16*1,"esp")); + &por ($D2,&QWP(16*2,"esp")); + &por ($D3,&QWP(16*3,"esp")); + &por ($D4,&QWP(16*4,"esp")); + + &pshufd ($D0,$D0,0b10001101); # -> r^1:r^2:r^3:r^4 + &pshufd ($D1,$D1,0b10001101); + &pshufd ($D2,$D2,0b10001101); + &pshufd ($D3,$D3,0b10001101); + &pshufd ($D4,$D4,0b10001101); + + &movdqu (&QWP(16*0,"edi"),$D0); # save the table + &movdqu (&QWP(16*1,"edi"),$D1); + &movdqu (&QWP(16*2,"edi"),$D2); + &movdqu (&QWP(16*3,"edi"),$D3); + &movdqu (&QWP(16*4,"edi"),$D4); + + &movdqa ($T1,$D1); + &movdqa ($T0,$D2); + &pslld ($T1,2); + &pslld ($T0,2); + &paddd ($T1,$D1); # *5 + &paddd ($T0,$D2); # *5 + &movdqu (&QWP(16*5,"edi"),$T1); + &movdqu (&QWP(16*6,"edi"),$T0); + &movdqa ($T1,$D3); + &movdqa ($T0,$D4); + &pslld ($T1,2); + &pslld ($T0,2); + &paddd ($T1,$D3); # *5 + &paddd ($T0,$D4); # *5 + &movdqu (&QWP(16*7,"edi"),$T1); + &movdqu (&QWP(16*8,"edi"),$T0); + + &mov ("esp","ebp"); + &lea ("edi",&DWP(-16*3,"edi")); # size de-optimization + &ret (); +&function_end_B("_poly1305_init_sse2"); + +&align (32); +&function_begin("_poly1305_blocks_sse2"); + &mov ("edi",&wparam(0)); # ctx + &mov ("esi",&wparam(1)); # inp + &mov ("ecx",&wparam(2)); # len + + &mov ("eax",&DWP(4*5,"edi")); # is_base2_26 + &and ("ecx",-16); + &jz (&label("nodata")); + &cmp ("ecx",64); + &jae (&label("enter_sse2")); + &test ("eax","eax"); # is_base2_26? + &jz (&label("enter_blocks")); + +&set_label("enter_sse2",16); + &call (&label("pic_point")); +&set_label("pic_point"); + &blindpop("ebx"); + &lea ("ebx",&DWP(&label("const_sse2")."-".&label("pic_point"),"ebx")); + + &test ("eax","eax"); # is_base2_26? + &jnz (&label("base2_26")); + + &call ("_poly1305_init_sse2"); + + ################################################# base 2^32 -> base 2^26 + &mov ("eax",&DWP(0,"edi")); + &mov ("ecx",&DWP(3,"edi")); + &mov ("edx",&DWP(6,"edi")); + &mov ("esi",&DWP(9,"edi")); + &mov ("ebp",&DWP(13,"edi")); + &mov (&DWP(4*5,"edi"),1); # is_base2_26 + + &shr ("ecx",2); + &and ("eax",0x3ffffff); + &shr ("edx",4); + &and ("ecx",0x3ffffff); + &shr ("esi",6); + &and ("edx",0x3ffffff); + + &movd ($D0,"eax"); + &movd ($D1,"ecx"); + &movd ($D2,"edx"); + &movd ($D3,"esi"); + &movd ($D4,"ebp"); + + &mov ("esi",&wparam(1)); # [reload] inp + &mov ("ecx",&wparam(2)); # [reload] len + &jmp (&label("base2_32")); + +&set_label("base2_26",16); + &movd ($D0,&DWP(4*0,"edi")); # load hash value + &movd ($D1,&DWP(4*1,"edi")); + &movd ($D2,&DWP(4*2,"edi")); + &movd ($D3,&DWP(4*3,"edi")); + &movd ($D4,&DWP(4*4,"edi")); + &movdqa ($MASK,&QWP(64,"ebx")); + +&set_label("base2_32"); + &mov ("eax",&wparam(3)); # padbit + &mov ("ebp","esp"); + + &sub ("esp",16*(5+5+5+9+9)); + &and ("esp",-16); + + &lea ("edi",&DWP(16*3,"edi")); # size optimization + &shl ("eax",24); # padbit + + &test ("ecx",31); + &jz (&label("even")); + + ################################################################ + # process single block, with SSE2, because it's still faster + # even though half of result is discarded + + &movdqu ($T1,&QWP(0,"esi")); # input + &lea ("esi",&DWP(16,"esi")); + + &movdqa ($T0,$T1); # -> base 2^26 ... + &pand ($T1,$MASK); + &paddd ($D0,$T1); # ... and accumuate + + &movdqa ($T1,$T0); + &psrlq ($T0,26); + &psrldq ($T1,6); + &pand ($T0,$MASK); + &paddd ($D1,$T0); + + &movdqa ($T0,$T1); + &psrlq ($T1,4); + &pand ($T1,$MASK); + &paddd ($D2,$T1); + + &movdqa ($T1,$T0); + &psrlq ($T0,30); + &pand ($T0,$MASK); + &psrldq ($T1,7); + &paddd ($D3,$T0); + + &movd ($T0,"eax"); # padbit + &paddd ($D4,$T1); + &movd ($T1,&DWP(16*0+12,"edi")); # r0 + &paddd ($D4,$T0); + + &movdqa (&QWP(16*0,"esp"),$D0); + &movdqa (&QWP(16*1,"esp"),$D1); + &movdqa (&QWP(16*2,"esp"),$D2); + &movdqa (&QWP(16*3,"esp"),$D3); + &movdqa (&QWP(16*4,"esp"),$D4); + + ################################################################ + # d4 = h4*r0 + h3*r1 + h2*r2 + h1*r3 + h0*r4 + # d3 = h3*r0 + h2*r1 + h1*r2 + h0*r3 + h4*5*r4 + # d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4 + # d1 = h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + h2*5*r4 + # d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4 + + &pmuludq ($D0,$T1); # h4*r0 + &pmuludq ($D1,$T1); # h3*r0 + &pmuludq ($D2,$T1); # h2*r0 + &movd ($T0,&DWP(16*1+12,"edi")); # r1 + &pmuludq ($D3,$T1); # h1*r0 + &pmuludq ($D4,$T1); # h0*r0 + + &pmuladd (sub { my ($reg,$i)=@_; + &movd ($reg,&DWP(16*$i+12,"edi")); + }); + + &lazy_reduction (); + + &sub ("ecx",16); + &jz (&label("done")); + +&set_label("even"); + &lea ("edx",&DWP(16*(5+5+5+9),"esp"));# size optimization + &lea ("eax",&DWP(-16*2,"esi")); + &sub ("ecx",64); + + ################################################################ + # expand and copy pre-calculated table to stack + + &movdqu ($T0,&QWP(16*0,"edi")); # r^1:r^2:r^3:r^4 + &pshufd ($T1,$T0,0b01000100); # duplicate r^3:r^4 + &cmovb ("esi","eax"); + &pshufd ($T0,$T0,0b11101110); # duplicate r^1:r^2 + &movdqa (&QWP(16*0,"edx"),$T1); + &lea ("eax",&DWP(16*10,"esp")); + &movdqu ($T1,&QWP(16*1,"edi")); + &movdqa (&QWP(16*(0-9),"edx"),$T0); + &pshufd ($T0,$T1,0b01000100); + &pshufd ($T1,$T1,0b11101110); + &movdqa (&QWP(16*1,"edx"),$T0); + &movdqu ($T0,&QWP(16*2,"edi")); + &movdqa (&QWP(16*(1-9),"edx"),$T1); + &pshufd ($T1,$T0,0b01000100); + &pshufd ($T0,$T0,0b11101110); + &movdqa (&QWP(16*2,"edx"),$T1); + &movdqu ($T1,&QWP(16*3,"edi")); + &movdqa (&QWP(16*(2-9),"edx"),$T0); + &pshufd ($T0,$T1,0b01000100); + &pshufd ($T1,$T1,0b11101110); + &movdqa (&QWP(16*3,"edx"),$T0); + &movdqu ($T0,&QWP(16*4,"edi")); + &movdqa (&QWP(16*(3-9),"edx"),$T1); + &pshufd ($T1,$T0,0b01000100); + &pshufd ($T0,$T0,0b11101110); + &movdqa (&QWP(16*4,"edx"),$T1); + &movdqu ($T1,&QWP(16*5,"edi")); + &movdqa (&QWP(16*(4-9),"edx"),$T0); + &pshufd ($T0,$T1,0b01000100); + &pshufd ($T1,$T1,0b11101110); + &movdqa (&QWP(16*5,"edx"),$T0); + &movdqu ($T0,&QWP(16*6,"edi")); + &movdqa (&QWP(16*(5-9),"edx"),$T1); + &pshufd ($T1,$T0,0b01000100); + &pshufd ($T0,$T0,0b11101110); + &movdqa (&QWP(16*6,"edx"),$T1); + &movdqu ($T1,&QWP(16*7,"edi")); + &movdqa (&QWP(16*(6-9),"edx"),$T0); + &pshufd ($T0,$T1,0b01000100); + &pshufd ($T1,$T1,0b11101110); + &movdqa (&QWP(16*7,"edx"),$T0); + &movdqu ($T0,&QWP(16*8,"edi")); + &movdqa (&QWP(16*(7-9),"edx"),$T1); + &pshufd ($T1,$T0,0b01000100); + &pshufd ($T0,$T0,0b11101110); + &movdqa (&QWP(16*8,"edx"),$T1); + &movdqa (&QWP(16*(8-9),"edx"),$T0); + +sub load_input { +my ($inpbase,$offbase)=@_; + + &movdqu ($T0,&QWP($inpbase+0,"esi")); # load input + &movdqu ($T1,&QWP($inpbase+16,"esi")); + &lea ("esi",&DWP(16*2,"esi")); + + &movdqa (&QWP($offbase+16*2,"esp"),$D2); + &movdqa (&QWP($offbase+16*3,"esp"),$D3); + &movdqa (&QWP($offbase+16*4,"esp"),$D4); + + &movdqa ($D2,$T0); # splat input + &movdqa ($D3,$T1); + &psrldq ($D2,6); + &psrldq ($D3,6); + &movdqa ($D4,$T0); + &punpcklqdq ($D2,$D3); # 2:3 + &punpckhqdq ($D4,$T1); # 4 + &punpcklqdq ($T0,$T1); # 0:1 + + &movdqa ($D3,$D2); + &psrlq ($D2,4); + &psrlq ($D3,30); + &movdqa ($T1,$T0); + &psrlq ($D4,40); # 4 + &psrlq ($T1,26); + &pand ($T0,$MASK); # 0 + &pand ($T1,$MASK); # 1 + &pand ($D2,$MASK); # 2 + &pand ($D3,$MASK); # 3 + &por ($D4,&QWP(0,"ebx")); # padbit, yes, always + + &movdqa (&QWP($offbase+16*0,"esp"),$D0) if ($offbase); + &movdqa (&QWP($offbase+16*1,"esp"),$D1) if ($offbase); +} + &load_input (16*2,16*5); + + &jbe (&label("skip_loop")); + &jmp (&label("loop")); + +&set_label("loop",32); + ################################################################ + # ((inp[0]*r^4+inp[2]*r^2+inp[4])*r^4+inp[6]*r^2 + # ((inp[1]*r^4+inp[3]*r^2+inp[5])*r^3+inp[7]*r + # \___________________/ + # ((inp[0]*r^4+inp[2]*r^2+inp[4])*r^4+inp[6]*r^2+inp[8])*r^2 + # ((inp[1]*r^4+inp[3]*r^2+inp[5])*r^4+inp[7]*r^2+inp[9])*r + # \___________________/ \____________________/ + ################################################################ + + &movdqa ($T2,&QWP(16*(0-9),"edx")); # r0^2 + &movdqa (&QWP(16*1,"eax"),$T1); + &movdqa (&QWP(16*2,"eax"),$D2); + &movdqa (&QWP(16*3,"eax"),$D3); + &movdqa (&QWP(16*4,"eax"),$D4); + + ################################################################ + # d4 = h4*r0 + h0*r4 + h1*r3 + h2*r2 + h3*r1 + # d3 = h3*r0 + h0*r3 + h1*r2 + h2*r1 + h4*5*r4 + # d2 = h2*r0 + h0*r2 + h1*r1 + h3*5*r4 + h4*5*r3 + # d1 = h1*r0 + h0*r1 + h2*5*r4 + h3*5*r3 + h4*5*r2 + # d0 = h0*r0 + h1*5*r4 + h2*5*r3 + h3*5*r2 + h4*5*r1 + + &movdqa ($D1,$T0); + &pmuludq ($T0,$T2); # h0*r0 + &movdqa ($D0,$T1); + &pmuludq ($T1,$T2); # h1*r0 + &pmuludq ($D2,$T2); # h2*r0 + &pmuludq ($D3,$T2); # h3*r0 + &pmuludq ($D4,$T2); # h4*r0 + +sub pmuladd_alt { +my $addr = shift; + + &pmuludq ($D0,&$addr(8)); # h1*s4 + &movdqa ($T2,$D1); + &pmuludq ($D1,&$addr(1)); # h0*r1 + &paddq ($D0,$T0); + &movdqa ($T0,$T2); + &pmuludq ($T2,&$addr(2)); # h0*r2 + &paddq ($D1,$T1); + &movdqa ($T1,$T0); + &pmuludq ($T0,&$addr(3)); # h0*r3 + &paddq ($D2,$T2); + &movdqa ($T2,&QWP(16*1,"eax")); # pull h1 + &pmuludq ($T1,&$addr(4)); # h0*r4 + &paddq ($D3,$T0); + + &movdqa ($T0,$T2); + &pmuludq ($T2,&$addr(1)); # h1*r1 + &paddq ($D4,$T1); + &movdqa ($T1,$T0); + &pmuludq ($T0,&$addr(2)); # h1*r2 + &paddq ($D2,$T2); + &movdqa ($T2,&QWP(16*2,"eax")); # pull h2 + &pmuludq ($T1,&$addr(3)); # h1*r3 + &paddq ($D3,$T0); + &movdqa ($T0,$T2); + &pmuludq ($T2,&$addr(7)); # h2*s3 + &paddq ($D4,$T1); + &movdqa ($T1,$T0); + &pmuludq ($T0,&$addr(8)); # h2*s4 + &paddq ($D0,$T2); + + &movdqa ($T2,$T1); + &pmuludq ($T1,&$addr(1)); # h2*r1 + &paddq ($D1,$T0); + &movdqa ($T0,&QWP(16*3,"eax")); # pull h3 + &pmuludq ($T2,&$addr(2)); # h2*r2 + &paddq ($D3,$T1); + &movdqa ($T1,$T0); + &pmuludq ($T0,&$addr(6)); # h3*s2 + &paddq ($D4,$T2); + &movdqa ($T2,$T1); + &pmuludq ($T1,&$addr(7)); # h3*s3 + &paddq ($D0,$T0); + &movdqa ($T0,$T2); + &pmuludq ($T2,&$addr(8)); # h3*s4 + &paddq ($D1,$T1); + + &movdqa ($T1,&QWP(16*4,"eax")); # pull h4 + &pmuludq ($T0,&$addr(1)); # h3*r1 + &paddq ($D2,$T2); + &movdqa ($T2,$T1); + &pmuludq ($T1,&$addr(8)); # h4*s4 + &paddq ($D4,$T0); + &movdqa ($T0,$T2); + &pmuludq ($T2,&$addr(5)); # h4*s1 + &paddq ($D3,$T1); + &movdqa ($T1,$T0); + &pmuludq ($T0,&$addr(6)); # h4*s2 + &paddq ($D0,$T2); + &movdqa ($MASK,&QWP(64,"ebx")); + &pmuludq ($T1,&$addr(7)); # h4*s3 + &paddq ($D1,$T0); + &paddq ($D2,$T1); +} + &pmuladd_alt (sub { my $i=shift; &QWP(16*($i-9),"edx"); }); + + &load_input (-16*2,0); + &lea ("eax",&DWP(-16*2,"esi")); + &sub ("ecx",64); + + &paddd ($T0,&QWP(16*(5+0),"esp")); # add hash value + &paddd ($T1,&QWP(16*(5+1),"esp")); + &paddd ($D2,&QWP(16*(5+2),"esp")); + &paddd ($D3,&QWP(16*(5+3),"esp")); + &paddd ($D4,&QWP(16*(5+4),"esp")); + + &cmovb ("esi","eax"); + &lea ("eax",&DWP(16*10,"esp")); + + &movdqa ($T2,&QWP(16*0,"edx")); # r0^4 + &movdqa (&QWP(16*1,"esp"),$D1); + &movdqa (&QWP(16*1,"eax"),$T1); + &movdqa (&QWP(16*2,"eax"),$D2); + &movdqa (&QWP(16*3,"eax"),$D3); + &movdqa (&QWP(16*4,"eax"),$D4); + + ################################################################ + # d4 += h4*r0 + h0*r4 + h1*r3 + h2*r2 + h3*r1 + # d3 += h3*r0 + h0*r3 + h1*r2 + h2*r1 + h4*5*r4 + # d2 += h2*r0 + h0*r2 + h1*r1 + h3*5*r4 + h4*5*r3 + # d1 += h1*r0 + h0*r1 + h2*5*r4 + h3*5*r3 + h4*5*r2 + # d0 += h0*r0 + h1*5*r4 + h2*5*r3 + h3*5*r2 + h4*5*r1 + + &movdqa ($D1,$T0); + &pmuludq ($T0,$T2); # h0*r0 + &paddq ($T0,$D0); + &movdqa ($D0,$T1); + &pmuludq ($T1,$T2); # h1*r0 + &pmuludq ($D2,$T2); # h2*r0 + &pmuludq ($D3,$T2); # h3*r0 + &pmuludq ($D4,$T2); # h4*r0 + + &paddq ($T1,&QWP(16*1,"esp")); + &paddq ($D2,&QWP(16*2,"esp")); + &paddq ($D3,&QWP(16*3,"esp")); + &paddq ($D4,&QWP(16*4,"esp")); + + &pmuladd_alt (sub { my $i=shift; &QWP(16*$i,"edx"); }); + + &lazy_reduction (); + + &load_input (16*2,16*5); + + &ja (&label("loop")); + +&set_label("skip_loop"); + ################################################################ + # multiply (inp[0:1]+hash) or inp[2:3] by r^2:r^1 + + &pshufd ($T2,&QWP(16*(0-9),"edx"),0x10);# r0^n + &add ("ecx",32); + &jnz (&label("long_tail")); + + &paddd ($T0,$D0); # add hash value + &paddd ($T1,$D1); + &paddd ($D2,&QWP(16*7,"esp")); + &paddd ($D3,&QWP(16*8,"esp")); + &paddd ($D4,&QWP(16*9,"esp")); + +&set_label("long_tail"); + + &movdqa (&QWP(16*0,"eax"),$T0); + &movdqa (&QWP(16*1,"eax"),$T1); + &movdqa (&QWP(16*2,"eax"),$D2); + &movdqa (&QWP(16*3,"eax"),$D3); + &movdqa (&QWP(16*4,"eax"),$D4); + + ################################################################ + # d4 = h4*r0 + h3*r1 + h2*r2 + h1*r3 + h0*r4 + # d3 = h3*r0 + h2*r1 + h1*r2 + h0*r3 + h4*5*r4 + # d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4 + # d1 = h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + h2*5*r4 + # d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4 + + &pmuludq ($T0,$T2); # h0*r0 + &pmuludq ($T1,$T2); # h1*r0 + &pmuludq ($D2,$T2); # h2*r0 + &movdqa ($D0,$T0); + &pshufd ($T0,&QWP(16*(1-9),"edx"),0x10);# r1^n + &pmuludq ($D3,$T2); # h3*r0 + &movdqa ($D1,$T1); + &pmuludq ($D4,$T2); # h4*r0 + + &pmuladd (sub { my ($reg,$i)=@_; + &pshufd ($reg,&QWP(16*($i-9),"edx"),0x10); + },"eax"); + + &jz (&label("short_tail")); + + &load_input (-16*2,0); + + &pshufd ($T2,&QWP(16*0,"edx"),0x10); # r0^n + &paddd ($T0,&QWP(16*5,"esp")); # add hash value + &paddd ($T1,&QWP(16*6,"esp")); + &paddd ($D2,&QWP(16*7,"esp")); + &paddd ($D3,&QWP(16*8,"esp")); + &paddd ($D4,&QWP(16*9,"esp")); + + ################################################################ + # multiply inp[0:1] by r^4:r^3 and accumulate + + &movdqa (&QWP(16*0,"esp"),$T0); + &pmuludq ($T0,$T2); # h0*r0 + &movdqa (&QWP(16*1,"esp"),$T1); + &pmuludq ($T1,$T2); # h1*r0 + &paddq ($D0,$T0); + &movdqa ($T0,$D2); + &pmuludq ($D2,$T2); # h2*r0 + &paddq ($D1,$T1); + &movdqa ($T1,$D3); + &pmuludq ($D3,$T2); # h3*r0 + &paddq ($D2,&QWP(16*2,"esp")); + &movdqa (&QWP(16*2,"esp"),$T0); + &pshufd ($T0,&QWP(16*1,"edx"),0x10); # r1^n + &paddq ($D3,&QWP(16*3,"esp")); + &movdqa (&QWP(16*3,"esp"),$T1); + &movdqa ($T1,$D4); + &pmuludq ($D4,$T2); # h4*r0 + &paddq ($D4,&QWP(16*4,"esp")); + &movdqa (&QWP(16*4,"esp"),$T1); + + &pmuladd (sub { my ($reg,$i)=@_; + &pshufd ($reg,&QWP(16*$i,"edx"),0x10); + }); + +&set_label("short_tail"); + + ################################################################ + # horizontal addition + + &pshufd ($T1,$D4,0b01001110); + &pshufd ($T0,$D3,0b01001110); + &paddq ($D4,$T1); + &paddq ($D3,$T0); + &pshufd ($T1,$D0,0b01001110); + &pshufd ($T0,$D1,0b01001110); + &paddq ($D0,$T1); + &paddq ($D1,$T0); + &pshufd ($T1,$D2,0b01001110); + #&paddq ($D2,$T1); + + &lazy_reduction (sub { &paddq ($D2,$T1) }); + +&set_label("done"); + &movd (&DWP(-16*3+4*0,"edi"),$D0); # store hash value + &movd (&DWP(-16*3+4*1,"edi"),$D1); + &movd (&DWP(-16*3+4*2,"edi"),$D2); + &movd (&DWP(-16*3+4*3,"edi"),$D3); + &movd (&DWP(-16*3+4*4,"edi"),$D4); + &mov ("esp","ebp"); +&set_label("nodata"); +&function_end("_poly1305_blocks_sse2"); + +&align (32); +&function_begin("_poly1305_emit_sse2"); + &mov ("ebp",&wparam(0)); # context + + &cmp (&DWP(4*5,"ebp"),0); # is_base2_26? + &je (&label("enter_emit")); + + &mov ("eax",&DWP(4*0,"ebp")); # load hash value + &mov ("edi",&DWP(4*1,"ebp")); + &mov ("ecx",&DWP(4*2,"ebp")); + &mov ("edx",&DWP(4*3,"ebp")); + &mov ("esi",&DWP(4*4,"ebp")); + + &mov ("ebx","edi"); # base 2^26 -> base 2^32 + &shl ("edi",26); + &shr ("ebx",6); + &add ("eax","edi"); + &mov ("edi","ecx"); + &adc ("ebx",0); + + &shl ("edi",20); + &shr ("ecx",12); + &add ("ebx","edi"); + &mov ("edi","edx"); + &adc ("ecx",0); + + &shl ("edi",14); + &shr ("edx",18); + &add ("ecx","edi"); + &mov ("edi","esi"); + &adc ("edx",0); + + &shl ("edi",8); + &shr ("esi",24); + &add ("edx","edi"); + &adc ("esi",0); # can be partially reduced + + &mov ("edi","esi"); # final reduction + &and ("esi",3); + &shr ("edi",2); + &lea ("ebp",&DWP(0,"edi","edi",4)); # *5 + &mov ("edi",&wparam(1)); # output + add ("eax","ebp"); + &mov ("ebp",&wparam(2)); # key + adc ("ebx",0); + adc ("ecx",0); + adc ("edx",0); + + &movd ($D0,"eax"); # offload original hash value + &add ("eax",5); # compare to modulus + &movd ($D1,"ebx"); + &adc ("ebx",0); + &movd ($D2,"ecx"); + &adc ("ecx",0); + &movd ($D3,"edx"); + &adc ("edx",0); + &adc ("esi",0); + &shr ("esi",2); # did it carry/borrow? + + &neg ("esi"); # do we choose (hash-modulus) ... + &and ("eax","esi"); + &and ("ebx","esi"); + &and ("ecx","esi"); + &and ("edx","esi"); + &mov (&DWP(4*0,"edi"),"eax"); + &movd ("eax",$D0); + &mov (&DWP(4*1,"edi"),"ebx"); + &movd ("ebx",$D1); + &mov (&DWP(4*2,"edi"),"ecx"); + &movd ("ecx",$D2); + &mov (&DWP(4*3,"edi"),"edx"); + &movd ("edx",$D3); + + ¬ ("esi"); # ... or original hash value? + &and ("eax","esi"); + &and ("ebx","esi"); + &or ("eax",&DWP(4*0,"edi")); + &and ("ecx","esi"); + &or ("ebx",&DWP(4*1,"edi")); + &and ("edx","esi"); + &or ("ecx",&DWP(4*2,"edi")); + &or ("edx",&DWP(4*3,"edi")); + + &add ("eax",&DWP(4*0,"ebp")); # accumulate key + &adc ("ebx",&DWP(4*1,"ebp")); + &mov (&DWP(4*0,"edi"),"eax"); + &adc ("ecx",&DWP(4*2,"ebp")); + &mov (&DWP(4*1,"edi"),"ebx"); + &adc ("edx",&DWP(4*3,"ebp")); + &mov (&DWP(4*2,"edi"),"ecx"); + &mov (&DWP(4*3,"edi"),"edx"); +&function_end("_poly1305_emit_sse2"); + +if ($avx>1) { +######################################################################## +# Note that poly1305_init_avx2 operates on %xmm, I could have used +# poly1305_init_sse2... + +&align (32); +&function_begin_B("_poly1305_init_avx2"); + &vmovdqu ($D4,&QWP(4*6,"edi")); # key base 2^32 + &lea ("edi",&DWP(16*3,"edi")); # size optimization + &mov ("ebp","esp"); + &sub ("esp",16*(9+5)); + &and ("esp",-16); + + #&vpand ($D4,$D4,&QWP(96,"ebx")); # magic mask + &vmovdqa ($MASK,&QWP(64,"ebx")); + + &vpand ($D0,$D4,$MASK); # -> base 2^26 + &vpsrlq ($D1,$D4,26); + &vpsrldq ($D3,$D4,6); + &vpand ($D1,$D1,$MASK); + &vpsrlq ($D2,$D3,4) + &vpsrlq ($D3,$D3,30); + &vpand ($D2,$D2,$MASK); + &vpand ($D3,$D3,$MASK); + &vpsrldq ($D4,$D4,13); + + &lea ("edx",&DWP(16*9,"esp")); # size optimization + &mov ("ecx",2); +&set_label("square"); + &vmovdqa (&QWP(16*0,"esp"),$D0); + &vmovdqa (&QWP(16*1,"esp"),$D1); + &vmovdqa (&QWP(16*2,"esp"),$D2); + &vmovdqa (&QWP(16*3,"esp"),$D3); + &vmovdqa (&QWP(16*4,"esp"),$D4); + + &vpslld ($T1,$D1,2); + &vpslld ($T0,$D2,2); + &vpaddd ($T1,$T1,$D1); # *5 + &vpaddd ($T0,$T0,$D2); # *5 + &vmovdqa (&QWP(16*5,"esp"),$T1); + &vmovdqa (&QWP(16*6,"esp"),$T0); + &vpslld ($T1,$D3,2); + &vpslld ($T0,$D4,2); + &vpaddd ($T1,$T1,$D3); # *5 + &vpaddd ($T0,$T0,$D4); # *5 + &vmovdqa (&QWP(16*7,"esp"),$T1); + &vmovdqa (&QWP(16*8,"esp"),$T0); + + &vpshufd ($T0,$D0,0b01000100); + &vmovdqa ($T1,$D1); + &vpshufd ($D1,$D1,0b01000100); + &vpshufd ($D2,$D2,0b01000100); + &vpshufd ($D3,$D3,0b01000100); + &vpshufd ($D4,$D4,0b01000100); + &vmovdqa (&QWP(16*0,"edx"),$T0); + &vmovdqa (&QWP(16*1,"edx"),$D1); + &vmovdqa (&QWP(16*2,"edx"),$D2); + &vmovdqa (&QWP(16*3,"edx"),$D3); + &vmovdqa (&QWP(16*4,"edx"),$D4); + + ################################################################ + # d4 = h4*r0 + h3*r1 + h2*r2 + h1*r3 + h0*r4 + # d3 = h3*r0 + h2*r1 + h1*r2 + h0*r3 + h4*5*r4 + # d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4 + # d1 = h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + h2*5*r4 + # d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4 + + &vpmuludq ($D4,$D4,$D0); # h4*r0 + &vpmuludq ($D3,$D3,$D0); # h3*r0 + &vpmuludq ($D2,$D2,$D0); # h2*r0 + &vpmuludq ($D1,$D1,$D0); # h1*r0 + &vpmuludq ($D0,$T0,$D0); # h0*r0 + + &vpmuludq ($T0,$T1,&QWP(16*3,"edx")); # r1*h3 + &vpaddq ($D4,$D4,$T0); + &vpmuludq ($T2,$T1,&QWP(16*2,"edx")); # r1*h2 + &vpaddq ($D3,$D3,$T2); + &vpmuludq ($T0,$T1,&QWP(16*1,"edx")); # r1*h1 + &vpaddq ($D2,$D2,$T0); + &vmovdqa ($T2,&QWP(16*5,"esp")); # s1 + &vpmuludq ($T1,$T1,&QWP(16*0,"edx")); # r1*h0 + &vpaddq ($D1,$D1,$T1); + &vmovdqa ($T0,&QWP(16*2,"esp")); # r2 + &vpmuludq ($T2,$T2,&QWP(16*4,"edx")); # s1*h4 + &vpaddq ($D0,$D0,$T2); + + &vpmuludq ($T1,$T0,&QWP(16*2,"edx")); # r2*h2 + &vpaddq ($D4,$D4,$T1); + &vpmuludq ($T2,$T0,&QWP(16*1,"edx")); # r2*h1 + &vpaddq ($D3,$D3,$T2); + &vmovdqa ($T1,&QWP(16*6,"esp")); # s2 + &vpmuludq ($T0,$T0,&QWP(16*0,"edx")); # r2*h0 + &vpaddq ($D2,$D2,$T0); + &vpmuludq ($T2,$T1,&QWP(16*4,"edx")); # s2*h4 + &vpaddq ($D1,$D1,$T2); + &vmovdqa ($T0,&QWP(16*3,"esp")); # r3 + &vpmuludq ($T1,$T1,&QWP(16*3,"edx")); # s2*h3 + &vpaddq ($D0,$D0,$T1); + + &vpmuludq ($T2,$T0,&QWP(16*1,"edx")); # r3*h1 + &vpaddq ($D4,$D4,$T2); + &vmovdqa ($T1,&QWP(16*7,"esp")); # s3 + &vpmuludq ($T0,$T0,&QWP(16*0,"edx")); # r3*h0 + &vpaddq ($D3,$D3,$T0); + &vpmuludq ($T2,$T1,&QWP(16*4,"edx")); # s3*h4 + &vpaddq ($D2,$D2,$T2); + &vpmuludq ($T0,$T1,&QWP(16*3,"edx")); # s3*h3 + &vpaddq ($D1,$D1,$T0); + &vmovdqa ($T2,&QWP(16*4,"esp")); # r4 + &vpmuludq ($T1,$T1,&QWP(16*2,"edx")); # s3*h2 + &vpaddq ($D0,$D0,$T1); + + &vmovdqa ($T0,&QWP(16*8,"esp")); # s4 + &vpmuludq ($T2,$T2,&QWP(16*0,"edx")); # r4*h0 + &vpaddq ($D4,$D4,$T2); + &vpmuludq ($T1,$T0,&QWP(16*4,"edx")); # s4*h4 + &vpaddq ($D3,$D3,$T1); + &vpmuludq ($T2,$T0,&QWP(16*1,"edx")); # s4*h1 + &vpaddq ($D0,$D0,$T2); + &vpmuludq ($T1,$T0,&QWP(16*2,"edx")); # s4*h2 + &vpaddq ($D1,$D1,$T1); + &vmovdqa ($MASK,&QWP(64,"ebx")); + &vpmuludq ($T0,$T0,&QWP(16*3,"edx")); # s4*h3 + &vpaddq ($D2,$D2,$T0); + + ################################################################ + # lazy reduction + &vpsrlq ($T0,$D3,26); + &vpand ($D3,$D3,$MASK); + &vpsrlq ($T1,$D0,26); + &vpand ($D0,$D0,$MASK); + &vpaddq ($D4,$D4,$T0); # h3 -> h4 + &vpaddq ($D1,$D1,$T1); # h0 -> h1 + &vpsrlq ($T0,$D4,26); + &vpand ($D4,$D4,$MASK); + &vpsrlq ($T1,$D1,26); + &vpand ($D1,$D1,$MASK); + &vpaddq ($D2,$D2,$T1); # h1 -> h2 + &vpaddd ($D0,$D0,$T0); + &vpsllq ($T0,$T0,2); + &vpsrlq ($T1,$D2,26); + &vpand ($D2,$D2,$MASK); + &vpaddd ($D0,$D0,$T0); # h4 -> h0 + &vpaddd ($D3,$D3,$T1); # h2 -> h3 + &vpsrlq ($T1,$D3,26); + &vpsrlq ($T0,$D0,26); + &vpand ($D0,$D0,$MASK); + &vpand ($D3,$D3,$MASK); + &vpaddd ($D1,$D1,$T0); # h0 -> h1 + &vpaddd ($D4,$D4,$T1); # h3 -> h4 + + &dec ("ecx"); + &jz (&label("square_break")); + + &vpunpcklqdq ($D0,$D0,&QWP(16*0,"esp")); # 0:r^1:0:r^2 + &vpunpcklqdq ($D1,$D1,&QWP(16*1,"esp")); + &vpunpcklqdq ($D2,$D2,&QWP(16*2,"esp")); + &vpunpcklqdq ($D3,$D3,&QWP(16*3,"esp")); + &vpunpcklqdq ($D4,$D4,&QWP(16*4,"esp")); + &jmp (&label("square")); + +&set_label("square_break"); + &vpsllq ($D0,$D0,32); # -> r^3:0:r^4:0 + &vpsllq ($D1,$D1,32); + &vpsllq ($D2,$D2,32); + &vpsllq ($D3,$D3,32); + &vpsllq ($D4,$D4,32); + &vpor ($D0,$D0,&QWP(16*0,"esp")); # r^3:r^1:r^4:r^2 + &vpor ($D1,$D1,&QWP(16*1,"esp")); + &vpor ($D2,$D2,&QWP(16*2,"esp")); + &vpor ($D3,$D3,&QWP(16*3,"esp")); + &vpor ($D4,$D4,&QWP(16*4,"esp")); + + &vpshufd ($D0,$D0,0b10001101); # -> r^1:r^2:r^3:r^4 + &vpshufd ($D1,$D1,0b10001101); + &vpshufd ($D2,$D2,0b10001101); + &vpshufd ($D3,$D3,0b10001101); + &vpshufd ($D4,$D4,0b10001101); + + &vmovdqu (&QWP(16*0,"edi"),$D0); # save the table + &vmovdqu (&QWP(16*1,"edi"),$D1); + &vmovdqu (&QWP(16*2,"edi"),$D2); + &vmovdqu (&QWP(16*3,"edi"),$D3); + &vmovdqu (&QWP(16*4,"edi"),$D4); + + &vpslld ($T1,$D1,2); + &vpslld ($T0,$D2,2); + &vpaddd ($T1,$T1,$D1); # *5 + &vpaddd ($T0,$T0,$D2); # *5 + &vmovdqu (&QWP(16*5,"edi"),$T1); + &vmovdqu (&QWP(16*6,"edi"),$T0); + &vpslld ($T1,$D3,2); + &vpslld ($T0,$D4,2); + &vpaddd ($T1,$T1,$D3); # *5 + &vpaddd ($T0,$T0,$D4); # *5 + &vmovdqu (&QWP(16*7,"edi"),$T1); + &vmovdqu (&QWP(16*8,"edi"),$T0); + + &mov ("esp","ebp"); + &lea ("edi",&DWP(-16*3,"edi")); # size de-optimization + &ret (); +&function_end_B("_poly1305_init_avx2"); + +######################################################################## +# now it's time to switch to %ymm + +my ($D0,$D1,$D2,$D3,$D4,$T0,$T1,$T2)=map("ymm$_",(0..7)); +my $MASK=$T2; + +sub X { my $reg=shift; $reg=~s/^ymm/xmm/; $reg; } + +&align (32); +&function_begin("_poly1305_blocks_avx2"); + &mov ("edi",&wparam(0)); # ctx + &mov ("esi",&wparam(1)); # inp + &mov ("ecx",&wparam(2)); # len + + &mov ("eax",&DWP(4*5,"edi")); # is_base2_26 + &and ("ecx",-16); + &jz (&label("nodata")); + &cmp ("ecx",64); + &jae (&label("enter_avx2")); + &test ("eax","eax"); # is_base2_26? + &jz (&label("enter_blocks")); + +&set_label("enter_avx2"); + &vzeroupper (); + + &call (&label("pic_point")); +&set_label("pic_point"); + &blindpop("ebx"); + &lea ("ebx",&DWP(&label("const_sse2")."-".&label("pic_point"),"ebx")); + + &test ("eax","eax"); # is_base2_26? + &jnz (&label("base2_26")); + + &call ("_poly1305_init_avx2"); + + ################################################# base 2^32 -> base 2^26 + &mov ("eax",&DWP(0,"edi")); + &mov ("ecx",&DWP(3,"edi")); + &mov ("edx",&DWP(6,"edi")); + &mov ("esi",&DWP(9,"edi")); + &mov ("ebp",&DWP(13,"edi")); + + &shr ("ecx",2); + &and ("eax",0x3ffffff); + &shr ("edx",4); + &and ("ecx",0x3ffffff); + &shr ("esi",6); + &and ("edx",0x3ffffff); + + &mov (&DWP(4*0,"edi"),"eax"); + &mov (&DWP(4*1,"edi"),"ecx"); + &mov (&DWP(4*2,"edi"),"edx"); + &mov (&DWP(4*3,"edi"),"esi"); + &mov (&DWP(4*4,"edi"),"ebp"); + &mov (&DWP(4*5,"edi"),1); # is_base2_26 + + &mov ("esi",&wparam(1)); # [reload] inp + &mov ("ecx",&wparam(2)); # [reload] len + +&set_label("base2_26"); + &mov ("eax",&wparam(3)); # padbit + &mov ("ebp","esp"); + + &sub ("esp",32*(5+9)); + &and ("esp",-512); # ensure that frame + # doesn't cross page + # boundary, which is + # essential for + # misaligned 32-byte + # loads + + ################################################################ + # expand and copy pre-calculated table to stack + + &vmovdqu (&X($D0),&QWP(16*(3+0),"edi")); + &lea ("edx",&DWP(32*5+128,"esp")); # +128 size optimization + &vmovdqu (&X($D1),&QWP(16*(3+1),"edi")); + &vmovdqu (&X($D2),&QWP(16*(3+2),"edi")); + &vmovdqu (&X($D3),&QWP(16*(3+3),"edi")); + &vmovdqu (&X($D4),&QWP(16*(3+4),"edi")); + &lea ("edi",&DWP(16*3,"edi")); # size optimization + &vpermq ($D0,$D0,0b01000000); # 00001234 -> 12343434 + &vpermq ($D1,$D1,0b01000000); + &vpermq ($D2,$D2,0b01000000); + &vpermq ($D3,$D3,0b01000000); + &vpermq ($D4,$D4,0b01000000); + &vpshufd ($D0,$D0,0b11001000); # 12343434 -> 14243444 + &vpshufd ($D1,$D1,0b11001000); + &vpshufd ($D2,$D2,0b11001000); + &vpshufd ($D3,$D3,0b11001000); + &vpshufd ($D4,$D4,0b11001000); + &vmovdqa (&QWP(32*0-128,"edx"),$D0); + &vmovdqu (&X($D0),&QWP(16*5,"edi")); + &vmovdqa (&QWP(32*1-128,"edx"),$D1); + &vmovdqu (&X($D1),&QWP(16*6,"edi")); + &vmovdqa (&QWP(32*2-128,"edx"),$D2); + &vmovdqu (&X($D2),&QWP(16*7,"edi")); + &vmovdqa (&QWP(32*3-128,"edx"),$D3); + &vmovdqu (&X($D3),&QWP(16*8,"edi")); + &vmovdqa (&QWP(32*4-128,"edx"),$D4); + &vpermq ($D0,$D0,0b01000000); + &vpermq ($D1,$D1,0b01000000); + &vpermq ($D2,$D2,0b01000000); + &vpermq ($D3,$D3,0b01000000); + &vpshufd ($D0,$D0,0b11001000); + &vpshufd ($D1,$D1,0b11001000); + &vpshufd ($D2,$D2,0b11001000); + &vpshufd ($D3,$D3,0b11001000); + &vmovdqa (&QWP(32*5-128,"edx"),$D0); + &vmovd (&X($D0),&DWP(-16*3+4*0,"edi"));# load hash value + &vmovdqa (&QWP(32*6-128,"edx"),$D1); + &vmovd (&X($D1),&DWP(-16*3+4*1,"edi")); + &vmovdqa (&QWP(32*7-128,"edx"),$D2); + &vmovd (&X($D2),&DWP(-16*3+4*2,"edi")); + &vmovdqa (&QWP(32*8-128,"edx"),$D3); + &vmovd (&X($D3),&DWP(-16*3+4*3,"edi")); + &vmovd (&X($D4),&DWP(-16*3+4*4,"edi")); + &vmovdqa ($MASK,&QWP(64,"ebx")); + &neg ("eax"); # padbit + + &test ("ecx",63); + &jz (&label("even")); + + &mov ("edx","ecx"); + &and ("ecx",-64); + &and ("edx",63); + + &vmovdqu (&X($T0),&QWP(16*0,"esi")); + &cmp ("edx",32); + &jb (&label("one")); + + &vmovdqu (&X($T1),&QWP(16*1,"esi")); + &je (&label("two")); + + &vinserti128 ($T0,$T0,&QWP(16*2,"esi"),1); + &lea ("esi",&DWP(16*3,"esi")); + &lea ("ebx",&DWP(8,"ebx")); # three padbits + &lea ("edx",&DWP(32*5+128+8,"esp")); # --:r^1:r^2:r^3 (*) + &jmp (&label("tail")); + +&set_label("two"); + &lea ("esi",&DWP(16*2,"esi")); + &lea ("ebx",&DWP(16,"ebx")); # two padbits + &lea ("edx",&DWP(32*5+128+16,"esp"));# --:--:r^1:r^2 (*) + &jmp (&label("tail")); + +&set_label("one"); + &lea ("esi",&DWP(16*1,"esi")); + &vpxor ($T1,$T1,$T1); + &lea ("ebx",&DWP(32,"ebx","eax",8)); # one or no padbits + &lea ("edx",&DWP(32*5+128+24,"esp"));# --:--:--:r^1 (*) + &jmp (&label("tail")); + +# (*) spots marked with '--' are data from next table entry, but they +# are multiplied by 0 and therefore rendered insignificant + +&set_label("even",32); + &vmovdqu (&X($T0),&QWP(16*0,"esi")); # load input + &vmovdqu (&X($T1),&QWP(16*1,"esi")); + &vinserti128 ($T0,$T0,&QWP(16*2,"esi"),1); + &vinserti128 ($T1,$T1,&QWP(16*3,"esi"),1); + &lea ("esi",&DWP(16*4,"esi")); + &sub ("ecx",64); + &jz (&label("tail")); + +&set_label("loop"); + ################################################################ + # ((inp[0]*r^4+r[4])*r^4+r[8])*r^4 + # ((inp[1]*r^4+r[5])*r^4+r[9])*r^3 + # ((inp[2]*r^4+r[6])*r^4+r[10])*r^2 + # ((inp[3]*r^4+r[7])*r^4+r[11])*r^1 + # \________/ \_______/ + ################################################################ + +sub vsplat_input { + &vmovdqa (&QWP(32*2,"esp"),$D2); + &vpsrldq ($D2,$T0,6); # splat input + &vmovdqa (&QWP(32*0,"esp"),$D0); + &vpsrldq ($D0,$T1,6); + &vmovdqa (&QWP(32*1,"esp"),$D1); + &vpunpckhqdq ($D1,$T0,$T1); # 4 + &vpunpcklqdq ($T0,$T0,$T1); # 0:1 + &vpunpcklqdq ($D2,$D2,$D0); # 2:3 + + &vpsrlq ($D0,$D2,30); + &vpsrlq ($D2,$D2,4); + &vpsrlq ($T1,$T0,26); + &vpsrlq ($D1,$D1,40); # 4 + &vpand ($D2,$D2,$MASK); # 2 + &vpand ($T0,$T0,$MASK); # 0 + &vpand ($T1,$T1,$MASK); # 1 + &vpand ($D0,$D0,$MASK); # 3 (*) + &vpor ($D1,$D1,&QWP(0,"ebx")); # padbit, yes, always + + # (*) note that output is counterintuitive, inp[3:4] is + # returned in $D1-2, while $D3-4 are preserved; +} + &vsplat_input (); + +sub vpmuladd { +my $addr = shift; + + &vpaddq ($D2,$D2,&QWP(32*2,"esp")); # add hash value + &vpaddq ($T0,$T0,&QWP(32*0,"esp")); + &vpaddq ($T1,$T1,&QWP(32*1,"esp")); + &vpaddq ($D0,$D0,$D3); + &vpaddq ($D1,$D1,$D4); + + ################################################################ + # d3 = h2*r1 + h0*r3 + h1*r2 + h3*r0 + h4*5*r4 + # d4 = h2*r2 + h0*r4 + h1*r3 + h3*r1 + h4*r0 + # d0 = h2*5*r3 + h0*r0 + h1*5*r4 + h3*5*r2 + h4*5*r1 + # d1 = h2*5*r4 + h0*r1 + h1*r0 + h3*5*r3 + h4*5*r2 + # d2 = h2*r0 + h0*r2 + h1*r1 + h3*5*r4 + h4*5*r3 + + &vpmuludq ($D3,$D2,&$addr(1)); # d3 = h2*r1 + &vmovdqa (QWP(32*1,"esp"),$T1); + &vpmuludq ($D4,$D2,&$addr(2)); # d4 = h2*r2 + &vmovdqa (QWP(32*3,"esp"),$D0); + &vpmuludq ($D0,$D2,&$addr(7)); # d0 = h2*s3 + &vmovdqa (QWP(32*4,"esp"),$D1); + &vpmuludq ($D1,$D2,&$addr(8)); # d1 = h2*s4 + &vpmuludq ($D2,$D2,&$addr(0)); # d2 = h2*r0 + + &vpmuludq ($T2,$T0,&$addr(3)); # h0*r3 + &vpaddq ($D3,$D3,$T2); # d3 += h0*r3 + &vpmuludq ($T1,$T0,&$addr(4)); # h0*r4 + &vpaddq ($D4,$D4,$T1); # d4 + h0*r4 + &vpmuludq ($T2,$T0,&$addr(0)); # h0*r0 + &vpaddq ($D0,$D0,$T2); # d0 + h0*r0 + &vmovdqa ($T2,&QWP(32*1,"esp")); # h1 + &vpmuludq ($T1,$T0,&$addr(1)); # h0*r1 + &vpaddq ($D1,$D1,$T1); # d1 += h0*r1 + &vpmuludq ($T0,$T0,&$addr(2)); # h0*r2 + &vpaddq ($D2,$D2,$T0); # d2 += h0*r2 + + &vpmuludq ($T1,$T2,&$addr(2)); # h1*r2 + &vpaddq ($D3,$D3,$T1); # d3 += h1*r2 + &vpmuludq ($T0,$T2,&$addr(3)); # h1*r3 + &vpaddq ($D4,$D4,$T0); # d4 += h1*r3 + &vpmuludq ($T1,$T2,&$addr(8)); # h1*s4 + &vpaddq ($D0,$D0,$T1); # d0 += h1*s4 + &vmovdqa ($T1,&QWP(32*3,"esp")); # h3 + &vpmuludq ($T0,$T2,&$addr(0)); # h1*r0 + &vpaddq ($D1,$D1,$T0); # d1 += h1*r0 + &vpmuludq ($T2,$T2,&$addr(1)); # h1*r1 + &vpaddq ($D2,$D2,$T2); # d2 += h1*r1 + + &vpmuludq ($T0,$T1,&$addr(0)); # h3*r0 + &vpaddq ($D3,$D3,$T0); # d3 += h3*r0 + &vpmuludq ($T2,$T1,&$addr(1)); # h3*r1 + &vpaddq ($D4,$D4,$T2); # d4 += h3*r1 + &vpmuludq ($T0,$T1,&$addr(6)); # h3*s2 + &vpaddq ($D0,$D0,$T0); # d0 += h3*s2 + &vmovdqa ($T0,&QWP(32*4,"esp")); # h4 + &vpmuludq ($T2,$T1,&$addr(7)); # h3*s3 + &vpaddq ($D1,$D1,$T2); # d1+= h3*s3 + &vpmuludq ($T1,$T1,&$addr(8)); # h3*s4 + &vpaddq ($D2,$D2,$T1); # d2 += h3*s4 + + &vpmuludq ($T2,$T0,&$addr(8)); # h4*s4 + &vpaddq ($D3,$D3,$T2); # d3 += h4*s4 + &vpmuludq ($T1,$T0,&$addr(5)); # h4*s1 + &vpaddq ($D0,$D0,$T1); # d0 += h4*s1 + &vpmuludq ($T2,$T0,&$addr(0)); # h4*r0 + &vpaddq ($D4,$D4,$T2); # d4 += h4*r0 + &vmovdqa ($MASK,&QWP(64,"ebx")); + &vpmuludq ($T1,$T0,&$addr(6)); # h4*s2 + &vpaddq ($D1,$D1,$T1); # d1 += h4*s2 + &vpmuludq ($T0,$T0,&$addr(7)); # h4*s3 + &vpaddq ($D2,$D2,$T0); # d2 += h4*s3 +} + &vpmuladd (sub { my $i=shift; &QWP(32*$i-128,"edx"); }); + +sub vlazy_reduction { + ################################################################ + # lazy reduction + + &vpsrlq ($T0,$D3,26); + &vpand ($D3,$D3,$MASK); + &vpsrlq ($T1,$D0,26); + &vpand ($D0,$D0,$MASK); + &vpaddq ($D4,$D4,$T0); # h3 -> h4 + &vpaddq ($D1,$D1,$T1); # h0 -> h1 + &vpsrlq ($T0,$D4,26); + &vpand ($D4,$D4,$MASK); + &vpsrlq ($T1,$D1,26); + &vpand ($D1,$D1,$MASK); + &vpaddq ($D2,$D2,$T1); # h1 -> h2 + &vpaddq ($D0,$D0,$T0); + &vpsllq ($T0,$T0,2); + &vpsrlq ($T1,$D2,26); + &vpand ($D2,$D2,$MASK); + &vpaddq ($D0,$D0,$T0); # h4 -> h0 + &vpaddq ($D3,$D3,$T1); # h2 -> h3 + &vpsrlq ($T1,$D3,26); + &vpsrlq ($T0,$D0,26); + &vpand ($D0,$D0,$MASK); + &vpand ($D3,$D3,$MASK); + &vpaddq ($D1,$D1,$T0); # h0 -> h1 + &vpaddq ($D4,$D4,$T1); # h3 -> h4 +} + &vlazy_reduction(); + + &vmovdqu (&X($T0),&QWP(16*0,"esi")); # load input + &vmovdqu (&X($T1),&QWP(16*1,"esi")); + &vinserti128 ($T0,$T0,&QWP(16*2,"esi"),1); + &vinserti128 ($T1,$T1,&QWP(16*3,"esi"),1); + &lea ("esi",&DWP(16*4,"esi")); + &sub ("ecx",64); + &jnz (&label("loop")); + +&set_label("tail"); + &vsplat_input (); + &and ("ebx",-64); # restore pointer + + &vpmuladd (sub { my $i=shift; &QWP(4+32*$i-128,"edx"); }); + + ################################################################ + # horizontal addition + + &vpsrldq ($T0,$D4,8); + &vpsrldq ($T1,$D3,8); + &vpaddq ($D4,$D4,$T0); + &vpsrldq ($T0,$D0,8); + &vpaddq ($D3,$D3,$T1); + &vpsrldq ($T1,$D1,8); + &vpaddq ($D0,$D0,$T0); + &vpsrldq ($T0,$D2,8); + &vpaddq ($D1,$D1,$T1); + &vpermq ($T1,$D4,2); # keep folding + &vpaddq ($D2,$D2,$T0); + &vpermq ($T0,$D3,2); + &vpaddq ($D4,$D4,$T1); + &vpermq ($T1,$D0,2); + &vpaddq ($D3,$D3,$T0); + &vpermq ($T0,$D1,2); + &vpaddq ($D0,$D0,$T1); + &vpermq ($T1,$D2,2); + &vpaddq ($D1,$D1,$T0); + &vpaddq ($D2,$D2,$T1); + + &vlazy_reduction(); + + &cmp ("ecx",0); + &je (&label("done")); + + ################################################################ + # clear all but single word + + &vpshufd (&X($D0),&X($D0),0b11111100); + &lea ("edx",&DWP(32*5+128,"esp")); # restore pointer + &vpshufd (&X($D1),&X($D1),0b11111100); + &vpshufd (&X($D2),&X($D2),0b11111100); + &vpshufd (&X($D3),&X($D3),0b11111100); + &vpshufd (&X($D4),&X($D4),0b11111100); + &jmp (&label("even")); + +&set_label("done",16); + &vmovd (&DWP(-16*3+4*0,"edi"),&X($D0));# store hash value + &vmovd (&DWP(-16*3+4*1,"edi"),&X($D1)); + &vmovd (&DWP(-16*3+4*2,"edi"),&X($D2)); + &vmovd (&DWP(-16*3+4*3,"edi"),&X($D3)); + &vmovd (&DWP(-16*3+4*4,"edi"),&X($D4)); + &vzeroupper (); + &mov ("esp","ebp"); +&set_label("nodata"); +&function_end("_poly1305_blocks_avx2"); +} +&set_label("const_sse2",64); + &data_word(1<<24,0, 1<<24,0, 1<<24,0, 1<<24,0); + &data_word(0,0, 0,0, 0,0, 0,0); + &data_word(0x03ffffff,0,0x03ffffff,0, 0x03ffffff,0, 0x03ffffff,0); + &data_word(0x0fffffff,0x0ffffffc,0x0ffffffc,0x0ffffffc); +} +&asciz ("Poly1305 for x86, CRYPTOGAMS by "); +&align (4); + +&asm_finish(); diff --git a/external/boringssl/crypto/poly1305/asm/poly1305-x86_64.pl b/external/boringssl/crypto/poly1305/asm/poly1305-x86_64.pl new file mode 100755 index 0000000000..3c810c5a00 --- /dev/null +++ b/external/boringssl/crypto/poly1305/asm/poly1305-x86_64.pl @@ -0,0 +1,2235 @@ +#!/usr/bin/env perl +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# This module implements Poly1305 hash for x86_64. +# +# March 2015 +# +# Numbers are cycles per processed byte with poly1305_blocks alone, +# measured with rdtsc at fixed clock frequency. +# +# IALU/gcc-4.8(*) AVX(**) AVX2 +# P4 4.90/+120% - +# Core 2 2.39/+90% - +# Westmere 1.86/+120% - +# Sandy Bridge 1.39/+140% 1.10 +# Haswell 1.10/+175% 1.11 0.65 +# Skylake 1.12/+120% 0.96 0.51 +# Silvermont 2.83/+95% - +# VIA Nano 1.82/+150% - +# Sledgehammer 1.38/+160% - +# Bulldozer 2.21/+130% 0.97 +# +# (*) improvement coefficients relative to clang are more modest and +# are ~50% on most processors, in both cases we are comparing to +# __int128 code; +# (**) SSE2 implementation was attempted, but among non-AVX processors +# it was faster than integer-only code only on older Intel P4 and +# Core processors, 50-30%, less newer processor is, but slower on +# contemporary ones, for example almost 2x slower on Atom, and as +# former are naturally disappearing, SSE2 is deemed unnecessary; + +$flavour = shift; +$output = shift; +if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } + +$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or +die "can't locate x86_64-xlate.pl"; + +$avx = 2; + +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; + +my ($ctx,$inp,$len,$padbit)=("%rdi","%rsi","%rdx","%rcx"); +my ($mac,$nonce)=($inp,$len); # *_emit arguments +my ($d1,$d2,$d3, $r0,$r1,$s1)=map("%r$_",(8..13)); +my ($h0,$h1,$h2)=("%r14","%rbx","%rbp"); + +sub poly1305_iteration { +# input: copy of $r1 in %rax, $h0-$h2, $r0-$r1 +# output: $h0-$h2 *= $r0-$r1 +$code.=<<___; + mulq $h0 # h0*r1 + mov %rax,$d2 + mov $r0,%rax + mov %rdx,$d3 + + mulq $h0 # h0*r0 + mov %rax,$h0 # future $h0 + mov $r0,%rax + mov %rdx,$d1 + + mulq $h1 # h1*r0 + add %rax,$d2 + mov $s1,%rax + adc %rdx,$d3 + + mulq $h1 # h1*s1 + mov $h2,$h1 # borrow $h1 + add %rax,$h0 + adc %rdx,$d1 + + imulq $s1,$h1 # h2*s1 + add $h1,$d2 + mov $d1,$h1 + adc \$0,$d3 + + imulq $r0,$h2 # h2*r0 + add $d2,$h1 + mov \$-4,%rax # mask value + adc $h2,$d3 + + and $d3,%rax # last reduction step + mov $d3,$h2 + shr \$2,$d3 + and \$3,$h2 + add $d3,%rax + add %rax,$h0 + adc \$0,$h1 +___ +} + +######################################################################## +# Layout of opaque area is following. +# +# unsigned __int64 h[3]; # current hash value base 2^64 +# unsigned __int64 r[2]; # key value base 2^64 + +$code.=<<___; +.text + +.extern OPENSSL_ia32cap_P + +.globl poly1305_init +.globl poly1305_blocks +.globl poly1305_emit +.type poly1305_init,\@function,3 +.align 32 +poly1305_init: + xor %rax,%rax + mov %rax,0($ctx) # initialize hash value + mov %rax,8($ctx) + mov %rax,16($ctx) + + cmp \$0,$inp + je .Lno_key + + lea poly1305_blocks(%rip),%r10 + lea poly1305_emit(%rip),%r11 +___ +$code.=<<___ if ($avx); + mov OPENSSL_ia32cap_P+4(%rip),%r9 + lea poly1305_blocks_avx(%rip),%rax + lea poly1305_emit_avx(%rip),%rcx + bt \$`60-32`,%r9 # AVX? + cmovc %rax,%r10 + cmovc %rcx,%r11 +___ +$code.=<<___ if ($avx>1); + lea poly1305_blocks_avx2(%rip),%rax + bt \$`5+32`,%r9 # AVX2? + cmovc %rax,%r10 +___ +$code.=<<___; + mov \$0x0ffffffc0fffffff,%rax + mov \$0x0ffffffc0ffffffc,%rcx + and 0($inp),%rax + and 8($inp),%rcx + mov %rax,24($ctx) + mov %rcx,32($ctx) +___ +$code.=<<___ if ($flavour !~ /elf32/); + mov %r10,0(%rdx) + mov %r11,8(%rdx) +___ +$code.=<<___ if ($flavour =~ /elf32/); + mov %r10d,0(%rdx) + mov %r11d,4(%rdx) +___ +$code.=<<___; + mov \$1,%eax +.Lno_key: + ret +.size poly1305_init,.-poly1305_init + +.type poly1305_blocks,\@function,4 +.align 32 +poly1305_blocks: +.Lblocks: + sub \$16,$len # too short? + jc .Lno_data + + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 +.Lblocks_body: + + mov $len,%r15 # reassign $len + + mov 24($ctx),$r0 # load r + mov 32($ctx),$s1 + + mov 0($ctx),$h0 # load hash value + mov 8($ctx),$h1 + mov 16($ctx),$h2 + + mov $s1,$r1 + shr \$2,$s1 + mov $r1,%rax + add $r1,$s1 # s1 = r1 + (r1 >> 2) + jmp .Loop + +.align 32 +.Loop: + add 0($inp),$h0 # accumulate input + adc 8($inp),$h1 + lea 16($inp),$inp + adc $padbit,$h2 +___ + &poly1305_iteration(); +$code.=<<___; + mov $r1,%rax + sub \$16,%r15 # len-=16 + jnc .Loop + + mov $h0,0($ctx) # store hash value + mov $h1,8($ctx) + mov $h2,16($ctx) + + mov 0(%rsp),%r15 + mov 8(%rsp),%r14 + mov 16(%rsp),%r13 + mov 24(%rsp),%r12 + mov 32(%rsp),%rbp + mov 40(%rsp),%rbx + lea 48(%rsp),%rsp +.Lno_data: +.Lblocks_epilogue: + ret +.size poly1305_blocks,.-poly1305_blocks + +.type poly1305_emit,\@function,3 +.align 32 +poly1305_emit: +.Lemit: + mov 0($ctx),%r8 # load hash value + mov 8($ctx),%r9 + mov 16($ctx),%r10 + + mov %r8,%rax + add \$5,%r8 # compare to modulus + mov %r9,%rcx + adc \$0,%r9 + adc \$0,%r10 + shr \$2,%r10 # did 130-bit value overfow? + cmovnz %r8,%rax + cmovnz %r9,%rcx + + add 0($nonce),%rax # accumulate nonce + adc 8($nonce),%rcx + mov %rax,0($mac) # write result + mov %rcx,8($mac) + + ret +.size poly1305_emit,.-poly1305_emit +___ +if ($avx) { + +######################################################################## +# Layout of opaque area is following. +# +# unsigned __int32 h[5]; # current hash value base 2^26 +# unsigned __int32 is_base2_26; +# unsigned __int64 r[2]; # key value base 2^64 +# unsigned __int64 pad; +# struct { unsigned __int32 r^2, r^1, r^4, r^3; } r[9]; +# +# where r^n are base 2^26 digits of degrees of multiplier key. There are +# 5 digits, but last four are interleaved with multiples of 5, totalling +# in 9 elements: r0, r1, 5*r1, r2, 5*r2, r3, 5*r3, r4, 5*r4. + +my ($H0,$H1,$H2,$H3,$H4, $T0,$T1,$T2,$T3,$T4, $D0,$D1,$D2,$D3,$D4, $MASK) = + map("%xmm$_",(0..15)); + +$code.=<<___; +.type __poly1305_block,\@abi-omnipotent +.align 32 +__poly1305_block: +___ + &poly1305_iteration(); +$code.=<<___; + ret +.size __poly1305_block,.-__poly1305_block + +.type __poly1305_init_avx,\@abi-omnipotent +.align 32 +__poly1305_init_avx: + mov $r0,$h0 + mov $r1,$h1 + xor $h2,$h2 + + lea 48+64($ctx),$ctx # size optimization + + mov $r1,%rax + call __poly1305_block # r^2 + + mov \$0x3ffffff,%eax # save interleaved r^2 and r base 2^26 + mov \$0x3ffffff,%edx + mov $h0,$d1 + and $h0#d,%eax + mov $r0,$d2 + and $r0#d,%edx + mov %eax,`16*0+0-64`($ctx) + shr \$26,$d1 + mov %edx,`16*0+4-64`($ctx) + shr \$26,$d2 + + mov \$0x3ffffff,%eax + mov \$0x3ffffff,%edx + and $d1#d,%eax + and $d2#d,%edx + mov %eax,`16*1+0-64`($ctx) + lea (%rax,%rax,4),%eax # *5 + mov %edx,`16*1+4-64`($ctx) + lea (%rdx,%rdx,4),%edx # *5 + mov %eax,`16*2+0-64`($ctx) + shr \$26,$d1 + mov %edx,`16*2+4-64`($ctx) + shr \$26,$d2 + + mov $h1,%rax + mov $r1,%rdx + shl \$12,%rax + shl \$12,%rdx + or $d1,%rax + or $d2,%rdx + and \$0x3ffffff,%eax + and \$0x3ffffff,%edx + mov %eax,`16*3+0-64`($ctx) + lea (%rax,%rax,4),%eax # *5 + mov %edx,`16*3+4-64`($ctx) + lea (%rdx,%rdx,4),%edx # *5 + mov %eax,`16*4+0-64`($ctx) + mov $h1,$d1 + mov %edx,`16*4+4-64`($ctx) + mov $r1,$d2 + + mov \$0x3ffffff,%eax + mov \$0x3ffffff,%edx + shr \$14,$d1 + shr \$14,$d2 + and $d1#d,%eax + and $d2#d,%edx + mov %eax,`16*5+0-64`($ctx) + lea (%rax,%rax,4),%eax # *5 + mov %edx,`16*5+4-64`($ctx) + lea (%rdx,%rdx,4),%edx # *5 + mov %eax,`16*6+0-64`($ctx) + shr \$26,$d1 + mov %edx,`16*6+4-64`($ctx) + shr \$26,$d2 + + mov $h2,%rax + shl \$24,%rax + or %rax,$d1 + mov $d1#d,`16*7+0-64`($ctx) + lea ($d1,$d1,4),$d1 # *5 + mov $d2#d,`16*7+4-64`($ctx) + lea ($d2,$d2,4),$d2 # *5 + mov $d1#d,`16*8+0-64`($ctx) + mov $d2#d,`16*8+4-64`($ctx) + + mov $r1,%rax + call __poly1305_block # r^3 + + mov \$0x3ffffff,%eax # save r^3 base 2^26 + mov $h0,$d1 + and $h0#d,%eax + shr \$26,$d1 + mov %eax,`16*0+12-64`($ctx) + + mov \$0x3ffffff,%edx + and $d1#d,%edx + mov %edx,`16*1+12-64`($ctx) + lea (%rdx,%rdx,4),%edx # *5 + shr \$26,$d1 + mov %edx,`16*2+12-64`($ctx) + + mov $h1,%rax + shl \$12,%rax + or $d1,%rax + and \$0x3ffffff,%eax + mov %eax,`16*3+12-64`($ctx) + lea (%rax,%rax,4),%eax # *5 + mov $h1,$d1 + mov %eax,`16*4+12-64`($ctx) + + mov \$0x3ffffff,%edx + shr \$14,$d1 + and $d1#d,%edx + mov %edx,`16*5+12-64`($ctx) + lea (%rdx,%rdx,4),%edx # *5 + shr \$26,$d1 + mov %edx,`16*6+12-64`($ctx) + + mov $h2,%rax + shl \$24,%rax + or %rax,$d1 + mov $d1#d,`16*7+12-64`($ctx) + lea ($d1,$d1,4),$d1 # *5 + mov $d1#d,`16*8+12-64`($ctx) + + mov $r1,%rax + call __poly1305_block # r^4 + + mov \$0x3ffffff,%eax # save r^4 base 2^26 + mov $h0,$d1 + and $h0#d,%eax + shr \$26,$d1 + mov %eax,`16*0+8-64`($ctx) + + mov \$0x3ffffff,%edx + and $d1#d,%edx + mov %edx,`16*1+8-64`($ctx) + lea (%rdx,%rdx,4),%edx # *5 + shr \$26,$d1 + mov %edx,`16*2+8-64`($ctx) + + mov $h1,%rax + shl \$12,%rax + or $d1,%rax + and \$0x3ffffff,%eax + mov %eax,`16*3+8-64`($ctx) + lea (%rax,%rax,4),%eax # *5 + mov $h1,$d1 + mov %eax,`16*4+8-64`($ctx) + + mov \$0x3ffffff,%edx + shr \$14,$d1 + and $d1#d,%edx + mov %edx,`16*5+8-64`($ctx) + lea (%rdx,%rdx,4),%edx # *5 + shr \$26,$d1 + mov %edx,`16*6+8-64`($ctx) + + mov $h2,%rax + shl \$24,%rax + or %rax,$d1 + mov $d1#d,`16*7+8-64`($ctx) + lea ($d1,$d1,4),$d1 # *5 + mov $d1#d,`16*8+8-64`($ctx) + + lea -48-64($ctx),$ctx # size [de-]optimization + ret +.size __poly1305_init_avx,.-__poly1305_init_avx + +.type poly1305_blocks_avx,\@function,4 +.align 32 +poly1305_blocks_avx: + mov 20($ctx),%r8d # is_base2_26 + cmp \$128,$len + jae .Lblocks_avx + test %r8d,%r8d + jz .Lblocks + +.Lblocks_avx: + and \$-16,$len + jz .Lno_data_avx + + vzeroupper + + test %r8d,%r8d + jz .Lbase2_64_avx + + test \$31,$len + jz .Leven_avx + + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 +.Lblocks_avx_body: + + mov $len,%r15 # reassign $len + + mov 0($ctx),$d1 # load hash value + mov 8($ctx),$d2 + mov 16($ctx),$h2#d + + mov 24($ctx),$r0 # load r + mov 32($ctx),$s1 + + ################################# base 2^26 -> base 2^64 + mov $d1#d,$h0#d + and \$-1<<31,$d1 + mov $d2,$r1 # borrow $r1 + mov $d2#d,$h1#d + and \$-1<<31,$d2 + + shr \$6,$d1 + shl \$52,$r1 + add $d1,$h0 + shr \$12,$h1 + shr \$18,$d2 + add $r1,$h0 + adc $d2,$h1 + + mov $h2,$d1 + shl \$40,$d1 + shr \$24,$h2 + add $d1,$h1 + adc \$0,$h2 # can be partially reduced... + + mov \$-4,$d2 # ... so reduce + mov $h2,$d1 + and $h2,$d2 + shr \$2,$d1 + and \$3,$h2 + add $d2,$d1 # =*5 + add $d1,$h0 + adc \$0,$h1 + + mov $s1,$r1 + mov $s1,%rax + shr \$2,$s1 + add $r1,$s1 # s1 = r1 + (r1 >> 2) + + add 0($inp),$h0 # accumulate input + adc 8($inp),$h1 + lea 16($inp),$inp + adc $padbit,$h2 + + call __poly1305_block + + test $padbit,$padbit # if $padbit is zero, + jz .Lstore_base2_64_avx # store hash in base 2^64 format + + ################################# base 2^64 -> base 2^26 + mov $h0,%rax + mov $h0,%rdx + shr \$52,$h0 + mov $h1,$r0 + mov $h1,$r1 + shr \$26,%rdx + and \$0x3ffffff,%rax # h[0] + shl \$12,$r0 + and \$0x3ffffff,%rdx # h[1] + shr \$14,$h1 + or $r0,$h0 + shl \$24,$h2 + and \$0x3ffffff,$h0 # h[2] + shr \$40,$r1 + and \$0x3ffffff,$h1 # h[3] + or $r1,$h2 # h[4] + + sub \$16,%r15 + jz .Lstore_base2_26_avx + + vmovd %rax#d,$H0 + vmovd %rdx#d,$H1 + vmovd $h0#d,$H2 + vmovd $h1#d,$H3 + vmovd $h2#d,$H4 + jmp .Lproceed_avx + +.align 32 +.Lstore_base2_64_avx: + mov $h0,0($ctx) + mov $h1,8($ctx) + mov $h2,16($ctx) # note that is_base2_26 is zeroed + jmp .Ldone_avx + +.align 16 +.Lstore_base2_26_avx: + mov %rax#d,0($ctx) # store hash value base 2^26 + mov %rdx#d,4($ctx) + mov $h0#d,8($ctx) + mov $h1#d,12($ctx) + mov $h2#d,16($ctx) +.align 16 +.Ldone_avx: + mov 0(%rsp),%r15 + mov 8(%rsp),%r14 + mov 16(%rsp),%r13 + mov 24(%rsp),%r12 + mov 32(%rsp),%rbp + mov 40(%rsp),%rbx + lea 48(%rsp),%rsp +.Lno_data_avx: +.Lblocks_avx_epilogue: + ret + +.align 32 +.Lbase2_64_avx: + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 +.Lbase2_64_avx_body: + + mov $len,%r15 # reassign $len + + mov 24($ctx),$r0 # load r + mov 32($ctx),$s1 + + mov 0($ctx),$h0 # load hash value + mov 8($ctx),$h1 + mov 16($ctx),$h2#d + + mov $s1,$r1 + mov $s1,%rax + shr \$2,$s1 + add $r1,$s1 # s1 = r1 + (r1 >> 2) + + test \$31,$len + jz .Linit_avx + + add 0($inp),$h0 # accumulate input + adc 8($inp),$h1 + lea 16($inp),$inp + adc $padbit,$h2 + sub \$16,%r15 + + call __poly1305_block + +.Linit_avx: + ################################# base 2^64 -> base 2^26 + mov $h0,%rax + mov $h0,%rdx + shr \$52,$h0 + mov $h1,$d1 + mov $h1,$d2 + shr \$26,%rdx + and \$0x3ffffff,%rax # h[0] + shl \$12,$d1 + and \$0x3ffffff,%rdx # h[1] + shr \$14,$h1 + or $d1,$h0 + shl \$24,$h2 + and \$0x3ffffff,$h0 # h[2] + shr \$40,$d2 + and \$0x3ffffff,$h1 # h[3] + or $d2,$h2 # h[4] + + vmovd %rax#d,$H0 + vmovd %rdx#d,$H1 + vmovd $h0#d,$H2 + vmovd $h1#d,$H3 + vmovd $h2#d,$H4 + movl \$1,20($ctx) # set is_base2_26 + + call __poly1305_init_avx + +.Lproceed_avx: + mov %r15,$len + + mov 0(%rsp),%r15 + mov 8(%rsp),%r14 + mov 16(%rsp),%r13 + mov 24(%rsp),%r12 + mov 32(%rsp),%rbp + mov 40(%rsp),%rbx + lea 48(%rsp),%rax + lea 48(%rsp),%rsp +.Lbase2_64_avx_epilogue: + jmp .Ldo_avx + +.align 32 +.Leven_avx: + vmovd 4*0($ctx),$H0 # load hash value + vmovd 4*1($ctx),$H1 + vmovd 4*2($ctx),$H2 + vmovd 4*3($ctx),$H3 + vmovd 4*4($ctx),$H4 + +.Ldo_avx: +___ +$code.=<<___ if (!$win64); + lea -0x58(%rsp),%r11 + sub \$0x178,%rsp +___ +$code.=<<___ if ($win64); + lea -0xf8(%rsp),%r11 + sub \$0x218,%rsp + vmovdqa %xmm6,0x50(%r11) + vmovdqa %xmm7,0x60(%r11) + vmovdqa %xmm8,0x70(%r11) + vmovdqa %xmm9,0x80(%r11) + vmovdqa %xmm10,0x90(%r11) + vmovdqa %xmm11,0xa0(%r11) + vmovdqa %xmm12,0xb0(%r11) + vmovdqa %xmm13,0xc0(%r11) + vmovdqa %xmm14,0xd0(%r11) + vmovdqa %xmm15,0xe0(%r11) +.Ldo_avx_body: +___ +$code.=<<___; + sub \$64,$len + lea -32($inp),%rax + cmovc %rax,$inp + + vmovdqu `16*3`($ctx),$D4 # preload r0^2 + lea `16*3+64`($ctx),$ctx # size optimization + lea .Lconst(%rip),%rcx + + ################################################################ + # load input + vmovdqu 16*2($inp),$T0 + vmovdqu 16*3($inp),$T1 + vmovdqa 64(%rcx),$MASK # .Lmask26 + + vpsrldq \$6,$T0,$T2 # splat input + vpsrldq \$6,$T1,$T3 + vpunpckhqdq $T1,$T0,$T4 # 4 + vpunpcklqdq $T1,$T0,$T0 # 0:1 + vpunpcklqdq $T3,$T2,$T3 # 2:3 + + vpsrlq \$40,$T4,$T4 # 4 + vpsrlq \$26,$T0,$T1 + vpand $MASK,$T0,$T0 # 0 + vpsrlq \$4,$T3,$T2 + vpand $MASK,$T1,$T1 # 1 + vpsrlq \$30,$T3,$T3 + vpand $MASK,$T2,$T2 # 2 + vpand $MASK,$T3,$T3 # 3 + vpor 32(%rcx),$T4,$T4 # padbit, yes, always + + jbe .Lskip_loop_avx + + # expand and copy pre-calculated table to stack + vmovdqu `16*1-64`($ctx),$D1 + vmovdqu `16*2-64`($ctx),$D2 + vpshufd \$0xEE,$D4,$D3 # 34xx -> 3434 + vpshufd \$0x44,$D4,$D0 # xx12 -> 1212 + vmovdqa $D3,-0x90(%r11) + vmovdqa $D0,0x00(%rsp) + vpshufd \$0xEE,$D1,$D4 + vmovdqu `16*3-64`($ctx),$D0 + vpshufd \$0x44,$D1,$D1 + vmovdqa $D4,-0x80(%r11) + vmovdqa $D1,0x10(%rsp) + vpshufd \$0xEE,$D2,$D3 + vmovdqu `16*4-64`($ctx),$D1 + vpshufd \$0x44,$D2,$D2 + vmovdqa $D3,-0x70(%r11) + vmovdqa $D2,0x20(%rsp) + vpshufd \$0xEE,$D0,$D4 + vmovdqu `16*5-64`($ctx),$D2 + vpshufd \$0x44,$D0,$D0 + vmovdqa $D4,-0x60(%r11) + vmovdqa $D0,0x30(%rsp) + vpshufd \$0xEE,$D1,$D3 + vmovdqu `16*6-64`($ctx),$D0 + vpshufd \$0x44,$D1,$D1 + vmovdqa $D3,-0x50(%r11) + vmovdqa $D1,0x40(%rsp) + vpshufd \$0xEE,$D2,$D4 + vmovdqu `16*7-64`($ctx),$D1 + vpshufd \$0x44,$D2,$D2 + vmovdqa $D4,-0x40(%r11) + vmovdqa $D2,0x50(%rsp) + vpshufd \$0xEE,$D0,$D3 + vmovdqu `16*8-64`($ctx),$D2 + vpshufd \$0x44,$D0,$D0 + vmovdqa $D3,-0x30(%r11) + vmovdqa $D0,0x60(%rsp) + vpshufd \$0xEE,$D1,$D4 + vpshufd \$0x44,$D1,$D1 + vmovdqa $D4,-0x20(%r11) + vmovdqa $D1,0x70(%rsp) + vpshufd \$0xEE,$D2,$D3 + vmovdqa 0x00(%rsp),$D4 # preload r0^2 + vpshufd \$0x44,$D2,$D2 + vmovdqa $D3,-0x10(%r11) + vmovdqa $D2,0x80(%rsp) + + jmp .Loop_avx + +.align 32 +.Loop_avx: + ################################################################ + # ((inp[0]*r^4+inp[2]*r^2+inp[4])*r^4+inp[6]*r^2 + # ((inp[1]*r^4+inp[3]*r^2+inp[5])*r^3+inp[7]*r + # \___________________/ + # ((inp[0]*r^4+inp[2]*r^2+inp[4])*r^4+inp[6]*r^2+inp[8])*r^2 + # ((inp[1]*r^4+inp[3]*r^2+inp[5])*r^4+inp[7]*r^2+inp[9])*r + # \___________________/ \____________________/ + # + # Note that we start with inp[2:3]*r^2. This is because it + # doesn't depend on reduction in previous iteration. + ################################################################ + # d4 = h4*r0 + h3*r1 + h2*r2 + h1*r3 + h0*r4 + # d3 = h3*r0 + h2*r1 + h1*r2 + h0*r3 + h4*5*r4 + # d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4 + # d1 = h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + h2*5*r4 + # d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4 + # + # though note that $Tx and $Hx are "reversed" in this section, + # and $D4 is preloaded with r0^2... + + vpmuludq $T0,$D4,$D0 # d0 = h0*r0 + vpmuludq $T1,$D4,$D1 # d1 = h1*r0 + vmovdqa $H2,0x20(%r11) # offload hash + vpmuludq $T2,$D4,$D2 # d3 = h2*r0 + vmovdqa 0x10(%rsp),$H2 # r1^2 + vpmuludq $T3,$D4,$D3 # d3 = h3*r0 + vpmuludq $T4,$D4,$D4 # d4 = h4*r0 + + vmovdqa $H0,0x00(%r11) # + vpmuludq 0x20(%rsp),$T4,$H0 # h4*s1 + vmovdqa $H1,0x10(%r11) # + vpmuludq $T3,$H2,$H1 # h3*r1 + vpaddq $H0,$D0,$D0 # d0 += h4*s1 + vpaddq $H1,$D4,$D4 # d4 += h3*r1 + vmovdqa $H3,0x30(%r11) # + vpmuludq $T2,$H2,$H0 # h2*r1 + vpmuludq $T1,$H2,$H1 # h1*r1 + vpaddq $H0,$D3,$D3 # d3 += h2*r1 + vmovdqa 0x30(%rsp),$H3 # r2^2 + vpaddq $H1,$D2,$D2 # d2 += h1*r1 + vmovdqa $H4,0x40(%r11) # + vpmuludq $T0,$H2,$H2 # h0*r1 + vpmuludq $T2,$H3,$H0 # h2*r2 + vpaddq $H2,$D1,$D1 # d1 += h0*r1 + + vmovdqa 0x40(%rsp),$H4 # s2^2 + vpaddq $H0,$D4,$D4 # d4 += h2*r2 + vpmuludq $T1,$H3,$H1 # h1*r2 + vpmuludq $T0,$H3,$H3 # h0*r2 + vpaddq $H1,$D3,$D3 # d3 += h1*r2 + vmovdqa 0x50(%rsp),$H2 # r3^2 + vpaddq $H3,$D2,$D2 # d2 += h0*r2 + vpmuludq $T4,$H4,$H0 # h4*s2 + vpmuludq $T3,$H4,$H4 # h3*s2 + vpaddq $H0,$D1,$D1 # d1 += h4*s2 + vmovdqa 0x60(%rsp),$H3 # s3^2 + vpaddq $H4,$D0,$D0 # d0 += h3*s2 + + vmovdqa 0x80(%rsp),$H4 # s4^2 + vpmuludq $T1,$H2,$H1 # h1*r3 + vpmuludq $T0,$H2,$H2 # h0*r3 + vpaddq $H1,$D4,$D4 # d4 += h1*r3 + vpaddq $H2,$D3,$D3 # d3 += h0*r3 + vpmuludq $T4,$H3,$H0 # h4*s3 + vpmuludq $T3,$H3,$H1 # h3*s3 + vpaddq $H0,$D2,$D2 # d2 += h4*s3 + vmovdqu 16*0($inp),$H0 # load input + vpaddq $H1,$D1,$D1 # d1 += h3*s3 + vpmuludq $T2,$H3,$H3 # h2*s3 + vpmuludq $T2,$H4,$T2 # h2*s4 + vpaddq $H3,$D0,$D0 # d0 += h2*s3 + + vmovdqu 16*1($inp),$H1 # + vpaddq $T2,$D1,$D1 # d1 += h2*s4 + vpmuludq $T3,$H4,$T3 # h3*s4 + vpmuludq $T4,$H4,$T4 # h4*s4 + vpsrldq \$6,$H0,$H2 # splat input + vpaddq $T3,$D2,$D2 # d2 += h3*s4 + vpaddq $T4,$D3,$D3 # d3 += h4*s4 + vpsrldq \$6,$H1,$H3 # + vpmuludq 0x70(%rsp),$T0,$T4 # h0*r4 + vpmuludq $T1,$H4,$T0 # h1*s4 + vpunpckhqdq $H1,$H0,$H4 # 4 + vpaddq $T4,$D4,$D4 # d4 += h0*r4 + vmovdqa -0x90(%r11),$T4 # r0^4 + vpaddq $T0,$D0,$D0 # d0 += h1*s4 + + vpunpcklqdq $H1,$H0,$H0 # 0:1 + vpunpcklqdq $H3,$H2,$H3 # 2:3 + + #vpsrlq \$40,$H4,$H4 # 4 + vpsrldq \$`40/8`,$H4,$H4 # 4 + vpsrlq \$26,$H0,$H1 + vpand $MASK,$H0,$H0 # 0 + vpsrlq \$4,$H3,$H2 + vpand $MASK,$H1,$H1 # 1 + vpand 0(%rcx),$H4,$H4 # .Lmask24 + vpsrlq \$30,$H3,$H3 + vpand $MASK,$H2,$H2 # 2 + vpand $MASK,$H3,$H3 # 3 + vpor 32(%rcx),$H4,$H4 # padbit, yes, always + + vpaddq 0x00(%r11),$H0,$H0 # add hash value + vpaddq 0x10(%r11),$H1,$H1 + vpaddq 0x20(%r11),$H2,$H2 + vpaddq 0x30(%r11),$H3,$H3 + vpaddq 0x40(%r11),$H4,$H4 + + lea 16*2($inp),%rax + lea 16*4($inp),$inp + sub \$64,$len + cmovc %rax,$inp + + ################################################################ + # Now we accumulate (inp[0:1]+hash)*r^4 + ################################################################ + # d4 = h4*r0 + h3*r1 + h2*r2 + h1*r3 + h0*r4 + # d3 = h3*r0 + h2*r1 + h1*r2 + h0*r3 + h4*5*r4 + # d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4 + # d1 = h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + h2*5*r4 + # d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4 + + vpmuludq $H0,$T4,$T0 # h0*r0 + vpmuludq $H1,$T4,$T1 # h1*r0 + vpaddq $T0,$D0,$D0 + vpaddq $T1,$D1,$D1 + vmovdqa -0x80(%r11),$T2 # r1^4 + vpmuludq $H2,$T4,$T0 # h2*r0 + vpmuludq $H3,$T4,$T1 # h3*r0 + vpaddq $T0,$D2,$D2 + vpaddq $T1,$D3,$D3 + vpmuludq $H4,$T4,$T4 # h4*r0 + vpmuludq -0x70(%r11),$H4,$T0 # h4*s1 + vpaddq $T4,$D4,$D4 + + vpaddq $T0,$D0,$D0 # d0 += h4*s1 + vpmuludq $H2,$T2,$T1 # h2*r1 + vpmuludq $H3,$T2,$T0 # h3*r1 + vpaddq $T1,$D3,$D3 # d3 += h2*r1 + vmovdqa -0x60(%r11),$T3 # r2^4 + vpaddq $T0,$D4,$D4 # d4 += h3*r1 + vpmuludq $H1,$T2,$T1 # h1*r1 + vpmuludq $H0,$T2,$T2 # h0*r1 + vpaddq $T1,$D2,$D2 # d2 += h1*r1 + vpaddq $T2,$D1,$D1 # d1 += h0*r1 + + vmovdqa -0x50(%r11),$T4 # s2^4 + vpmuludq $H2,$T3,$T0 # h2*r2 + vpmuludq $H1,$T3,$T1 # h1*r2 + vpaddq $T0,$D4,$D4 # d4 += h2*r2 + vpaddq $T1,$D3,$D3 # d3 += h1*r2 + vmovdqa -0x40(%r11),$T2 # r3^4 + vpmuludq $H0,$T3,$T3 # h0*r2 + vpmuludq $H4,$T4,$T0 # h4*s2 + vpaddq $T3,$D2,$D2 # d2 += h0*r2 + vpaddq $T0,$D1,$D1 # d1 += h4*s2 + vmovdqa -0x30(%r11),$T3 # s3^4 + vpmuludq $H3,$T4,$T4 # h3*s2 + vpmuludq $H1,$T2,$T1 # h1*r3 + vpaddq $T4,$D0,$D0 # d0 += h3*s2 + + vmovdqa -0x10(%r11),$T4 # s4^4 + vpaddq $T1,$D4,$D4 # d4 += h1*r3 + vpmuludq $H0,$T2,$T2 # h0*r3 + vpmuludq $H4,$T3,$T0 # h4*s3 + vpaddq $T2,$D3,$D3 # d3 += h0*r3 + vpaddq $T0,$D2,$D2 # d2 += h4*s3 + vmovdqu 16*2($inp),$T0 # load input + vpmuludq $H3,$T3,$T2 # h3*s3 + vpmuludq $H2,$T3,$T3 # h2*s3 + vpaddq $T2,$D1,$D1 # d1 += h3*s3 + vmovdqu 16*3($inp),$T1 # + vpaddq $T3,$D0,$D0 # d0 += h2*s3 + + vpmuludq $H2,$T4,$H2 # h2*s4 + vpmuludq $H3,$T4,$H3 # h3*s4 + vpsrldq \$6,$T0,$T2 # splat input + vpaddq $H2,$D1,$D1 # d1 += h2*s4 + vpmuludq $H4,$T4,$H4 # h4*s4 + vpsrldq \$6,$T1,$T3 # + vpaddq $H3,$D2,$H2 # h2 = d2 + h3*s4 + vpaddq $H4,$D3,$H3 # h3 = d3 + h4*s4 + vpmuludq -0x20(%r11),$H0,$H4 # h0*r4 + vpmuludq $H1,$T4,$H0 + vpunpckhqdq $T1,$T0,$T4 # 4 + vpaddq $H4,$D4,$H4 # h4 = d4 + h0*r4 + vpaddq $H0,$D0,$H0 # h0 = d0 + h1*s4 + + vpunpcklqdq $T1,$T0,$T0 # 0:1 + vpunpcklqdq $T3,$T2,$T3 # 2:3 + + #vpsrlq \$40,$T4,$T4 # 4 + vpsrldq \$`40/8`,$T4,$T4 # 4 + vpsrlq \$26,$T0,$T1 + vmovdqa 0x00(%rsp),$D4 # preload r0^2 + vpand $MASK,$T0,$T0 # 0 + vpsrlq \$4,$T3,$T2 + vpand $MASK,$T1,$T1 # 1 + vpand 0(%rcx),$T4,$T4 # .Lmask24 + vpsrlq \$30,$T3,$T3 + vpand $MASK,$T2,$T2 # 2 + vpand $MASK,$T3,$T3 # 3 + vpor 32(%rcx),$T4,$T4 # padbit, yes, always + + ################################################################ + # lazy reduction as discussed in "NEON crypto" by D.J. Bernstein + # and P. Schwabe + + vpsrlq \$26,$H3,$D3 + vpand $MASK,$H3,$H3 + vpaddq $D3,$H4,$H4 # h3 -> h4 + + vpsrlq \$26,$H0,$D0 + vpand $MASK,$H0,$H0 + vpaddq $D0,$D1,$H1 # h0 -> h1 + + vpsrlq \$26,$H4,$D0 + vpand $MASK,$H4,$H4 + + vpsrlq \$26,$H1,$D1 + vpand $MASK,$H1,$H1 + vpaddq $D1,$H2,$H2 # h1 -> h2 + + vpaddq $D0,$H0,$H0 + vpsllq \$2,$D0,$D0 + vpaddq $D0,$H0,$H0 # h4 -> h0 + + vpsrlq \$26,$H2,$D2 + vpand $MASK,$H2,$H2 + vpaddq $D2,$H3,$H3 # h2 -> h3 + + vpsrlq \$26,$H0,$D0 + vpand $MASK,$H0,$H0 + vpaddq $D0,$H1,$H1 # h0 -> h1 + + vpsrlq \$26,$H3,$D3 + vpand $MASK,$H3,$H3 + vpaddq $D3,$H4,$H4 # h3 -> h4 + + ja .Loop_avx + +.Lskip_loop_avx: + ################################################################ + # multiply (inp[0:1]+hash) or inp[2:3] by r^2:r^1 + + vpshufd \$0x10,$D4,$D4 # r0^n, xx12 -> x1x2 + add \$32,$len + jnz .Long_tail_avx + + vpaddq $H2,$T2,$T2 + vpaddq $H0,$T0,$T0 + vpaddq $H1,$T1,$T1 + vpaddq $H3,$T3,$T3 + vpaddq $H4,$T4,$T4 + +.Long_tail_avx: + vmovdqa $H2,0x20(%r11) + vmovdqa $H0,0x00(%r11) + vmovdqa $H1,0x10(%r11) + vmovdqa $H3,0x30(%r11) + vmovdqa $H4,0x40(%r11) + + # d4 = h4*r0 + h3*r1 + h2*r2 + h1*r3 + h0*r4 + # d3 = h3*r0 + h2*r1 + h1*r2 + h0*r3 + h4*5*r4 + # d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4 + # d1 = h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + h2*5*r4 + # d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4 + + vpmuludq $T2,$D4,$D2 # d2 = h2*r0 + vpmuludq $T0,$D4,$D0 # d0 = h0*r0 + vpshufd \$0x10,`16*1-64`($ctx),$H2 # r1^n + vpmuludq $T1,$D4,$D1 # d1 = h1*r0 + vpmuludq $T3,$D4,$D3 # d3 = h3*r0 + vpmuludq $T4,$D4,$D4 # d4 = h4*r0 + + vpmuludq $T3,$H2,$H0 # h3*r1 + vpaddq $H0,$D4,$D4 # d4 += h3*r1 + vpshufd \$0x10,`16*2-64`($ctx),$H3 # s1^n + vpmuludq $T2,$H2,$H1 # h2*r1 + vpaddq $H1,$D3,$D3 # d3 += h2*r1 + vpshufd \$0x10,`16*3-64`($ctx),$H4 # r2^n + vpmuludq $T1,$H2,$H0 # h1*r1 + vpaddq $H0,$D2,$D2 # d2 += h1*r1 + vpmuludq $T0,$H2,$H2 # h0*r1 + vpaddq $H2,$D1,$D1 # d1 += h0*r1 + vpmuludq $T4,$H3,$H3 # h4*s1 + vpaddq $H3,$D0,$D0 # d0 += h4*s1 + + vpshufd \$0x10,`16*4-64`($ctx),$H2 # s2^n + vpmuludq $T2,$H4,$H1 # h2*r2 + vpaddq $H1,$D4,$D4 # d4 += h2*r2 + vpmuludq $T1,$H4,$H0 # h1*r2 + vpaddq $H0,$D3,$D3 # d3 += h1*r2 + vpshufd \$0x10,`16*5-64`($ctx),$H3 # r3^n + vpmuludq $T0,$H4,$H4 # h0*r2 + vpaddq $H4,$D2,$D2 # d2 += h0*r2 + vpmuludq $T4,$H2,$H1 # h4*s2 + vpaddq $H1,$D1,$D1 # d1 += h4*s2 + vpshufd \$0x10,`16*6-64`($ctx),$H4 # s3^n + vpmuludq $T3,$H2,$H2 # h3*s2 + vpaddq $H2,$D0,$D0 # d0 += h3*s2 + + vpmuludq $T1,$H3,$H0 # h1*r3 + vpaddq $H0,$D4,$D4 # d4 += h1*r3 + vpmuludq $T0,$H3,$H3 # h0*r3 + vpaddq $H3,$D3,$D3 # d3 += h0*r3 + vpshufd \$0x10,`16*7-64`($ctx),$H2 # r4^n + vpmuludq $T4,$H4,$H1 # h4*s3 + vpaddq $H1,$D2,$D2 # d2 += h4*s3 + vpshufd \$0x10,`16*8-64`($ctx),$H3 # s4^n + vpmuludq $T3,$H4,$H0 # h3*s3 + vpaddq $H0,$D1,$D1 # d1 += h3*s3 + vpmuludq $T2,$H4,$H4 # h2*s3 + vpaddq $H4,$D0,$D0 # d0 += h2*s3 + + vpmuludq $T0,$H2,$H2 # h0*r4 + vpaddq $H2,$D4,$D4 # h4 = d4 + h0*r4 + vpmuludq $T4,$H3,$H1 # h4*s4 + vpaddq $H1,$D3,$D3 # h3 = d3 + h4*s4 + vpmuludq $T3,$H3,$H0 # h3*s4 + vpaddq $H0,$D2,$D2 # h2 = d2 + h3*s4 + vpmuludq $T2,$H3,$H1 # h2*s4 + vpaddq $H1,$D1,$D1 # h1 = d1 + h2*s4 + vpmuludq $T1,$H3,$H3 # h1*s4 + vpaddq $H3,$D0,$D0 # h0 = d0 + h1*s4 + + jz .Lshort_tail_avx + + vmovdqu 16*0($inp),$H0 # load input + vmovdqu 16*1($inp),$H1 + + vpsrldq \$6,$H0,$H2 # splat input + vpsrldq \$6,$H1,$H3 + vpunpckhqdq $H1,$H0,$H4 # 4 + vpunpcklqdq $H1,$H0,$H0 # 0:1 + vpunpcklqdq $H3,$H2,$H3 # 2:3 + + vpsrlq \$40,$H4,$H4 # 4 + vpsrlq \$26,$H0,$H1 + vpand $MASK,$H0,$H0 # 0 + vpsrlq \$4,$H3,$H2 + vpand $MASK,$H1,$H1 # 1 + vpsrlq \$30,$H3,$H3 + vpand $MASK,$H2,$H2 # 2 + vpand $MASK,$H3,$H3 # 3 + vpor 32(%rcx),$H4,$H4 # padbit, yes, always + + vpshufd \$0x32,`16*0-64`($ctx),$T4 # r0^n, 34xx -> x3x4 + vpaddq 0x00(%r11),$H0,$H0 + vpaddq 0x10(%r11),$H1,$H1 + vpaddq 0x20(%r11),$H2,$H2 + vpaddq 0x30(%r11),$H3,$H3 + vpaddq 0x40(%r11),$H4,$H4 + + ################################################################ + # multiply (inp[0:1]+hash) by r^4:r^3 and accumulate + + vpmuludq $H0,$T4,$T0 # h0*r0 + vpaddq $T0,$D0,$D0 # d0 += h0*r0 + vpmuludq $H1,$T4,$T1 # h1*r0 + vpaddq $T1,$D1,$D1 # d1 += h1*r0 + vpmuludq $H2,$T4,$T0 # h2*r0 + vpaddq $T0,$D2,$D2 # d2 += h2*r0 + vpshufd \$0x32,`16*1-64`($ctx),$T2 # r1^n + vpmuludq $H3,$T4,$T1 # h3*r0 + vpaddq $T1,$D3,$D3 # d3 += h3*r0 + vpmuludq $H4,$T4,$T4 # h4*r0 + vpaddq $T4,$D4,$D4 # d4 += h4*r0 + + vpmuludq $H3,$T2,$T0 # h3*r1 + vpaddq $T0,$D4,$D4 # d4 += h3*r1 + vpshufd \$0x32,`16*2-64`($ctx),$T3 # s1 + vpmuludq $H2,$T2,$T1 # h2*r1 + vpaddq $T1,$D3,$D3 # d3 += h2*r1 + vpshufd \$0x32,`16*3-64`($ctx),$T4 # r2 + vpmuludq $H1,$T2,$T0 # h1*r1 + vpaddq $T0,$D2,$D2 # d2 += h1*r1 + vpmuludq $H0,$T2,$T2 # h0*r1 + vpaddq $T2,$D1,$D1 # d1 += h0*r1 + vpmuludq $H4,$T3,$T3 # h4*s1 + vpaddq $T3,$D0,$D0 # d0 += h4*s1 + + vpshufd \$0x32,`16*4-64`($ctx),$T2 # s2 + vpmuludq $H2,$T4,$T1 # h2*r2 + vpaddq $T1,$D4,$D4 # d4 += h2*r2 + vpmuludq $H1,$T4,$T0 # h1*r2 + vpaddq $T0,$D3,$D3 # d3 += h1*r2 + vpshufd \$0x32,`16*5-64`($ctx),$T3 # r3 + vpmuludq $H0,$T4,$T4 # h0*r2 + vpaddq $T4,$D2,$D2 # d2 += h0*r2 + vpmuludq $H4,$T2,$T1 # h4*s2 + vpaddq $T1,$D1,$D1 # d1 += h4*s2 + vpshufd \$0x32,`16*6-64`($ctx),$T4 # s3 + vpmuludq $H3,$T2,$T2 # h3*s2 + vpaddq $T2,$D0,$D0 # d0 += h3*s2 + + vpmuludq $H1,$T3,$T0 # h1*r3 + vpaddq $T0,$D4,$D4 # d4 += h1*r3 + vpmuludq $H0,$T3,$T3 # h0*r3 + vpaddq $T3,$D3,$D3 # d3 += h0*r3 + vpshufd \$0x32,`16*7-64`($ctx),$T2 # r4 + vpmuludq $H4,$T4,$T1 # h4*s3 + vpaddq $T1,$D2,$D2 # d2 += h4*s3 + vpshufd \$0x32,`16*8-64`($ctx),$T3 # s4 + vpmuludq $H3,$T4,$T0 # h3*s3 + vpaddq $T0,$D1,$D1 # d1 += h3*s3 + vpmuludq $H2,$T4,$T4 # h2*s3 + vpaddq $T4,$D0,$D0 # d0 += h2*s3 + + vpmuludq $H0,$T2,$T2 # h0*r4 + vpaddq $T2,$D4,$D4 # d4 += h0*r4 + vpmuludq $H4,$T3,$T1 # h4*s4 + vpaddq $T1,$D3,$D3 # d3 += h4*s4 + vpmuludq $H3,$T3,$T0 # h3*s4 + vpaddq $T0,$D2,$D2 # d2 += h3*s4 + vpmuludq $H2,$T3,$T1 # h2*s4 + vpaddq $T1,$D1,$D1 # d1 += h2*s4 + vpmuludq $H1,$T3,$T3 # h1*s4 + vpaddq $T3,$D0,$D0 # d0 += h1*s4 + +.Lshort_tail_avx: + ################################################################ + # horizontal addition + + vpsrldq \$8,$D4,$T4 + vpsrldq \$8,$D3,$T3 + vpsrldq \$8,$D1,$T1 + vpsrldq \$8,$D0,$T0 + vpsrldq \$8,$D2,$T2 + vpaddq $T3,$D3,$D3 + vpaddq $T4,$D4,$D4 + vpaddq $T0,$D0,$D0 + vpaddq $T1,$D1,$D1 + vpaddq $T2,$D2,$D2 + + ################################################################ + # lazy reduction + + vpsrlq \$26,$D3,$H3 + vpand $MASK,$D3,$D3 + vpaddq $H3,$D4,$D4 # h3 -> h4 + + vpsrlq \$26,$D0,$H0 + vpand $MASK,$D0,$D0 + vpaddq $H0,$D1,$D1 # h0 -> h1 + + vpsrlq \$26,$D4,$H4 + vpand $MASK,$D4,$D4 + + vpsrlq \$26,$D1,$H1 + vpand $MASK,$D1,$D1 + vpaddq $H1,$D2,$D2 # h1 -> h2 + + vpaddq $H4,$D0,$D0 + vpsllq \$2,$H4,$H4 + vpaddq $H4,$D0,$D0 # h4 -> h0 + + vpsrlq \$26,$D2,$H2 + vpand $MASK,$D2,$D2 + vpaddq $H2,$D3,$D3 # h2 -> h3 + + vpsrlq \$26,$D0,$H0 + vpand $MASK,$D0,$D0 + vpaddq $H0,$D1,$D1 # h0 -> h1 + + vpsrlq \$26,$D3,$H3 + vpand $MASK,$D3,$D3 + vpaddq $H3,$D4,$D4 # h3 -> h4 + + vmovd $D0,`4*0-48-64`($ctx) # save partially reduced + vmovd $D1,`4*1-48-64`($ctx) + vmovd $D2,`4*2-48-64`($ctx) + vmovd $D3,`4*3-48-64`($ctx) + vmovd $D4,`4*4-48-64`($ctx) +___ +$code.=<<___ if ($win64); + vmovdqa 0x50(%r11),%xmm6 + vmovdqa 0x60(%r11),%xmm7 + vmovdqa 0x70(%r11),%xmm8 + vmovdqa 0x80(%r11),%xmm9 + vmovdqa 0x90(%r11),%xmm10 + vmovdqa 0xa0(%r11),%xmm11 + vmovdqa 0xb0(%r11),%xmm12 + vmovdqa 0xc0(%r11),%xmm13 + vmovdqa 0xd0(%r11),%xmm14 + vmovdqa 0xe0(%r11),%xmm15 + lea 0xf8(%r11),%rsp +.Ldo_avx_epilogue: +___ +$code.=<<___ if (!$win64); + lea 0x58(%r11),%rsp +___ +$code.=<<___; + vzeroupper + ret +.size poly1305_blocks_avx,.-poly1305_blocks_avx + +.type poly1305_emit_avx,\@function,3 +.align 32 +poly1305_emit_avx: + cmpl \$0,20($ctx) # is_base2_26? + je .Lemit + + mov 0($ctx),%eax # load hash value base 2^26 + mov 4($ctx),%ecx + mov 8($ctx),%r8d + mov 12($ctx),%r11d + mov 16($ctx),%r10d + + shl \$26,%rcx # base 2^26 -> base 2^64 + mov %r8,%r9 + shl \$52,%r8 + add %rcx,%rax + shr \$12,%r9 + add %rax,%r8 # h0 + adc \$0,%r9 + + shl \$14,%r11 + mov %r10,%rax + shr \$24,%r10 + add %r11,%r9 + shl \$40,%rax + add %rax,%r9 # h1 + adc \$0,%r10 # h2 + + mov %r10,%rax # could be partially reduced, so reduce + mov %r10,%rcx + and \$3,%r10 + shr \$2,%rax + and \$-4,%rcx + add %rcx,%rax + add %rax,%r8 + adc \$0,%r9 + + mov %r8,%rax + add \$5,%r8 # compare to modulus + mov %r9,%rcx + adc \$0,%r9 + adc \$0,%r10 + shr \$2,%r10 # did 130-bit value overfow? + cmovnz %r8,%rax + cmovnz %r9,%rcx + + add 0($nonce),%rax # accumulate nonce + adc 8($nonce),%rcx + mov %rax,0($mac) # write result + mov %rcx,8($mac) + + ret +.size poly1305_emit_avx,.-poly1305_emit_avx +___ + +if ($avx>1) { +my ($H0,$H1,$H2,$H3,$H4, $MASK, $T4,$T0,$T1,$T2,$T3, $D0,$D1,$D2,$D3,$D4) = + map("%ymm$_",(0..15)); +my $S4=$MASK; + +$code.=<<___; +.type poly1305_blocks_avx2,\@function,4 +.align 32 +poly1305_blocks_avx2: + mov 20($ctx),%r8d # is_base2_26 + cmp \$128,$len + jae .Lblocks_avx2 + test %r8d,%r8d + jz .Lblocks + +.Lblocks_avx2: + and \$-16,$len + jz .Lno_data_avx2 + + vzeroupper + + test %r8d,%r8d + jz .Lbase2_64_avx2 + + test \$63,$len + jz .Leven_avx2 + + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 +.Lblocks_avx2_body: + + mov $len,%r15 # reassign $len + + mov 0($ctx),$d1 # load hash value + mov 8($ctx),$d2 + mov 16($ctx),$h2#d + + mov 24($ctx),$r0 # load r + mov 32($ctx),$s1 + + ################################# base 2^26 -> base 2^64 + mov $d1#d,$h0#d + and \$-1<<31,$d1 + mov $d2,$r1 # borrow $r1 + mov $d2#d,$h1#d + and \$-1<<31,$d2 + + shr \$6,$d1 + shl \$52,$r1 + add $d1,$h0 + shr \$12,$h1 + shr \$18,$d2 + add $r1,$h0 + adc $d2,$h1 + + mov $h2,$d1 + shl \$40,$d1 + shr \$24,$h2 + add $d1,$h1 + adc \$0,$h2 # can be partially reduced... + + mov \$-4,$d2 # ... so reduce + mov $h2,$d1 + and $h2,$d2 + shr \$2,$d1 + and \$3,$h2 + add $d2,$d1 # =*5 + add $d1,$h0 + adc \$0,$h1 + + mov $s1,$r1 + mov $s1,%rax + shr \$2,$s1 + add $r1,$s1 # s1 = r1 + (r1 >> 2) + +.Lbase2_26_pre_avx2: + add 0($inp),$h0 # accumulate input + adc 8($inp),$h1 + lea 16($inp),$inp + adc $padbit,$h2 + sub \$16,%r15 + + call __poly1305_block + mov $r1,%rax + + test \$63,%r15 + jnz .Lbase2_26_pre_avx2 + + test $padbit,$padbit # if $padbit is zero, + jz .Lstore_base2_64_avx2 # store hash in base 2^64 format + + ################################# base 2^64 -> base 2^26 + mov $h0,%rax + mov $h0,%rdx + shr \$52,$h0 + mov $h1,$r0 + mov $h1,$r1 + shr \$26,%rdx + and \$0x3ffffff,%rax # h[0] + shl \$12,$r0 + and \$0x3ffffff,%rdx # h[1] + shr \$14,$h1 + or $r0,$h0 + shl \$24,$h2 + and \$0x3ffffff,$h0 # h[2] + shr \$40,$r1 + and \$0x3ffffff,$h1 # h[3] + or $r1,$h2 # h[4] + + test %r15,%r15 + jz .Lstore_base2_26_avx2 + + vmovd %rax#d,%x#$H0 + vmovd %rdx#d,%x#$H1 + vmovd $h0#d,%x#$H2 + vmovd $h1#d,%x#$H3 + vmovd $h2#d,%x#$H4 + jmp .Lproceed_avx2 + +.align 32 +.Lstore_base2_64_avx2: + mov $h0,0($ctx) + mov $h1,8($ctx) + mov $h2,16($ctx) # note that is_base2_26 is zeroed + jmp .Ldone_avx2 + +.align 16 +.Lstore_base2_26_avx2: + mov %rax#d,0($ctx) # store hash value base 2^26 + mov %rdx#d,4($ctx) + mov $h0#d,8($ctx) + mov $h1#d,12($ctx) + mov $h2#d,16($ctx) +.align 16 +.Ldone_avx2: + mov 0(%rsp),%r15 + mov 8(%rsp),%r14 + mov 16(%rsp),%r13 + mov 24(%rsp),%r12 + mov 32(%rsp),%rbp + mov 40(%rsp),%rbx + lea 48(%rsp),%rsp +.Lno_data_avx2: +.Lblocks_avx2_epilogue: + ret + +.align 32 +.Lbase2_64_avx2: + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 +.Lbase2_64_avx2_body: + + mov $len,%r15 # reassign $len + + mov 24($ctx),$r0 # load r + mov 32($ctx),$s1 + + mov 0($ctx),$h0 # load hash value + mov 8($ctx),$h1 + mov 16($ctx),$h2#d + + mov $s1,$r1 + mov $s1,%rax + shr \$2,$s1 + add $r1,$s1 # s1 = r1 + (r1 >> 2) + + test \$63,$len + jz .Linit_avx2 + +.Lbase2_64_pre_avx2: + add 0($inp),$h0 # accumulate input + adc 8($inp),$h1 + lea 16($inp),$inp + adc $padbit,$h2 + sub \$16,%r15 + + call __poly1305_block + mov $r1,%rax + + test \$63,%r15 + jnz .Lbase2_64_pre_avx2 + +.Linit_avx2: + ################################# base 2^64 -> base 2^26 + mov $h0,%rax + mov $h0,%rdx + shr \$52,$h0 + mov $h1,$d1 + mov $h1,$d2 + shr \$26,%rdx + and \$0x3ffffff,%rax # h[0] + shl \$12,$d1 + and \$0x3ffffff,%rdx # h[1] + shr \$14,$h1 + or $d1,$h0 + shl \$24,$h2 + and \$0x3ffffff,$h0 # h[2] + shr \$40,$d2 + and \$0x3ffffff,$h1 # h[3] + or $d2,$h2 # h[4] + + vmovd %rax#d,%x#$H0 + vmovd %rdx#d,%x#$H1 + vmovd $h0#d,%x#$H2 + vmovd $h1#d,%x#$H3 + vmovd $h2#d,%x#$H4 + movl \$1,20($ctx) # set is_base2_26 + + call __poly1305_init_avx + +.Lproceed_avx2: + mov %r15,$len + + mov 0(%rsp),%r15 + mov 8(%rsp),%r14 + mov 16(%rsp),%r13 + mov 24(%rsp),%r12 + mov 32(%rsp),%rbp + mov 40(%rsp),%rbx + lea 48(%rsp),%rax + lea 48(%rsp),%rsp +.Lbase2_64_avx2_epilogue: + jmp .Ldo_avx2 + +.align 32 +.Leven_avx2: + vmovd 4*0($ctx),%x#$H0 # load hash value base 2^26 + vmovd 4*1($ctx),%x#$H1 + vmovd 4*2($ctx),%x#$H2 + vmovd 4*3($ctx),%x#$H3 + vmovd 4*4($ctx),%x#$H4 + +.Ldo_avx2: +___ +$code.=<<___ if (!$win64); + lea -8(%rsp),%r11 + sub \$0x128,%rsp +___ +$code.=<<___ if ($win64); + lea -0xf8(%rsp),%r11 + sub \$0x1c8,%rsp + vmovdqa %xmm6,0x50(%r11) + vmovdqa %xmm7,0x60(%r11) + vmovdqa %xmm8,0x70(%r11) + vmovdqa %xmm9,0x80(%r11) + vmovdqa %xmm10,0x90(%r11) + vmovdqa %xmm11,0xa0(%r11) + vmovdqa %xmm12,0xb0(%r11) + vmovdqa %xmm13,0xc0(%r11) + vmovdqa %xmm14,0xd0(%r11) + vmovdqa %xmm15,0xe0(%r11) +.Ldo_avx2_body: +___ +$code.=<<___; + lea 48+64($ctx),$ctx # size optimization + lea .Lconst(%rip),%rcx + + # expand and copy pre-calculated table to stack + vmovdqu `16*0-64`($ctx),%x#$T2 + and \$-512,%rsp + vmovdqu `16*1-64`($ctx),%x#$T3 + vmovdqu `16*2-64`($ctx),%x#$T4 + vmovdqu `16*3-64`($ctx),%x#$D0 + vmovdqu `16*4-64`($ctx),%x#$D1 + vmovdqu `16*5-64`($ctx),%x#$D2 + vmovdqu `16*6-64`($ctx),%x#$D3 + vpermq \$0x15,$T2,$T2 # 00003412 -> 12343434 + vmovdqu `16*7-64`($ctx),%x#$D4 + vpermq \$0x15,$T3,$T3 + vpshufd \$0xc8,$T2,$T2 # 12343434 -> 14243444 + vmovdqu `16*8-64`($ctx),%x#$MASK + vpermq \$0x15,$T4,$T4 + vpshufd \$0xc8,$T3,$T3 + vmovdqa $T2,0x00(%rsp) + vpermq \$0x15,$D0,$D0 + vpshufd \$0xc8,$T4,$T4 + vmovdqa $T3,0x20(%rsp) + vpermq \$0x15,$D1,$D1 + vpshufd \$0xc8,$D0,$D0 + vmovdqa $T4,0x40(%rsp) + vpermq \$0x15,$D2,$D2 + vpshufd \$0xc8,$D1,$D1 + vmovdqa $D0,0x60(%rsp) + vpermq \$0x15,$D3,$D3 + vpshufd \$0xc8,$D2,$D2 + vmovdqa $D1,0x80(%rsp) + vpermq \$0x15,$D4,$D4 + vpshufd \$0xc8,$D3,$D3 + vmovdqa $D2,0xa0(%rsp) + vpermq \$0x15,$MASK,$MASK + vpshufd \$0xc8,$D4,$D4 + vmovdqa $D3,0xc0(%rsp) + vpshufd \$0xc8,$MASK,$MASK + vmovdqa $D4,0xe0(%rsp) + vmovdqa $MASK,0x100(%rsp) + vmovdqa 64(%rcx),$MASK # .Lmask26 + + ################################################################ + # load input + vmovdqu 16*0($inp),%x#$T0 + vmovdqu 16*1($inp),%x#$T1 + vinserti128 \$1,16*2($inp),$T0,$T0 + vinserti128 \$1,16*3($inp),$T1,$T1 + lea 16*4($inp),$inp + + vpsrldq \$6,$T0,$T2 # splat input + vpsrldq \$6,$T1,$T3 + vpunpckhqdq $T1,$T0,$T4 # 4 + vpunpcklqdq $T3,$T2,$T2 # 2:3 + vpunpcklqdq $T1,$T0,$T0 # 0:1 + + vpsrlq \$30,$T2,$T3 + vpsrlq \$4,$T2,$T2 + vpsrlq \$26,$T0,$T1 + vpsrlq \$40,$T4,$T4 # 4 + vpand $MASK,$T2,$T2 # 2 + vpand $MASK,$T0,$T0 # 0 + vpand $MASK,$T1,$T1 # 1 + vpand $MASK,$T3,$T3 # 3 + vpor 32(%rcx),$T4,$T4 # padbit, yes, always + + lea 0x90(%rsp),%rax # size optimization + vpaddq $H2,$T2,$H2 # accumulate input + sub \$64,$len + jz .Ltail_avx2 + jmp .Loop_avx2 + +.align 32 +.Loop_avx2: + ################################################################ + # ((inp[0]*r^4+r[4])*r^4+r[8])*r^4 + # ((inp[1]*r^4+r[5])*r^4+r[9])*r^3 + # ((inp[2]*r^4+r[6])*r^4+r[10])*r^2 + # ((inp[3]*r^4+r[7])*r^4+r[11])*r^1 + # \________/\________/ + ################################################################ + #vpaddq $H2,$T2,$H2 # accumulate input + vpaddq $H0,$T0,$H0 + vmovdqa `32*0`(%rsp),$T0 # r0^4 + vpaddq $H1,$T1,$H1 + vmovdqa `32*1`(%rsp),$T1 # r1^4 + vpaddq $H3,$T3,$H3 + vmovdqa `32*3`(%rsp),$T2 # r2^4 + vpaddq $H4,$T4,$H4 + vmovdqa `32*6-0x90`(%rax),$T3 # s3^4 + vmovdqa `32*8-0x90`(%rax),$S4 # s4^4 + + # d4 = h4*r0 + h3*r1 + h2*r2 + h1*r3 + h0*r4 + # d3 = h3*r0 + h2*r1 + h1*r2 + h0*r3 + h4*5*r4 + # d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4 + # d1 = h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + h2*5*r4 + # d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4 + # + # however, as h2 is "chronologically" first one available pull + # corresponding operations up, so it's + # + # d4 = h2*r2 + h4*r0 + h3*r1 + h1*r3 + h0*r4 + # d3 = h2*r1 + h3*r0 + h1*r2 + h0*r3 + h4*5*r4 + # d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4 + # d1 = h2*5*r4 + h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + # d0 = h2*5*r3 + h0*r0 + h4*5*r1 + h3*5*r2 + h1*5*r4 + + vpmuludq $H2,$T0,$D2 # d2 = h2*r0 + vpmuludq $H2,$T1,$D3 # d3 = h2*r1 + vpmuludq $H2,$T2,$D4 # d4 = h2*r2 + vpmuludq $H2,$T3,$D0 # d0 = h2*s3 + vpmuludq $H2,$S4,$D1 # d1 = h2*s4 + + vpmuludq $H0,$T1,$T4 # h0*r1 + vpmuludq $H1,$T1,$H2 # h1*r1, borrow $H2 as temp + vpaddq $T4,$D1,$D1 # d1 += h0*r1 + vpaddq $H2,$D2,$D2 # d2 += h1*r1 + vpmuludq $H3,$T1,$T4 # h3*r1 + vpmuludq `32*2`(%rsp),$H4,$H2 # h4*s1 + vpaddq $T4,$D4,$D4 # d4 += h3*r1 + vpaddq $H2,$D0,$D0 # d0 += h4*s1 + vmovdqa `32*4-0x90`(%rax),$T1 # s2 + + vpmuludq $H0,$T0,$T4 # h0*r0 + vpmuludq $H1,$T0,$H2 # h1*r0 + vpaddq $T4,$D0,$D0 # d0 += h0*r0 + vpaddq $H2,$D1,$D1 # d1 += h1*r0 + vpmuludq $H3,$T0,$T4 # h3*r0 + vpmuludq $H4,$T0,$H2 # h4*r0 + vmovdqu 16*0($inp),%x#$T0 # load input + vpaddq $T4,$D3,$D3 # d3 += h3*r0 + vpaddq $H2,$D4,$D4 # d4 += h4*r0 + vinserti128 \$1,16*2($inp),$T0,$T0 + + vpmuludq $H3,$T1,$T4 # h3*s2 + vpmuludq $H4,$T1,$H2 # h4*s2 + vmovdqu 16*1($inp),%x#$T1 + vpaddq $T4,$D0,$D0 # d0 += h3*s2 + vpaddq $H2,$D1,$D1 # d1 += h4*s2 + vmovdqa `32*5-0x90`(%rax),$H2 # r3 + vpmuludq $H1,$T2,$T4 # h1*r2 + vpmuludq $H0,$T2,$T2 # h0*r2 + vpaddq $T4,$D3,$D3 # d3 += h1*r2 + vpaddq $T2,$D2,$D2 # d2 += h0*r2 + vinserti128 \$1,16*3($inp),$T1,$T1 + lea 16*4($inp),$inp + + vpmuludq $H1,$H2,$T4 # h1*r3 + vpmuludq $H0,$H2,$H2 # h0*r3 + vpsrldq \$6,$T0,$T2 # splat input + vpaddq $T4,$D4,$D4 # d4 += h1*r3 + vpaddq $H2,$D3,$D3 # d3 += h0*r3 + vpmuludq $H3,$T3,$T4 # h3*s3 + vpmuludq $H4,$T3,$H2 # h4*s3 + vpsrldq \$6,$T1,$T3 + vpaddq $T4,$D1,$D1 # d1 += h3*s3 + vpaddq $H2,$D2,$D2 # d2 += h4*s3 + vpunpckhqdq $T1,$T0,$T4 # 4 + + vpmuludq $H3,$S4,$H3 # h3*s4 + vpmuludq $H4,$S4,$H4 # h4*s4 + vpunpcklqdq $T1,$T0,$T0 # 0:1 + vpaddq $H3,$D2,$H2 # h2 = d2 + h3*r4 + vpaddq $H4,$D3,$H3 # h3 = d3 + h4*r4 + vpunpcklqdq $T3,$T2,$T3 # 2:3 + vpmuludq `32*7-0x90`(%rax),$H0,$H4 # h0*r4 + vpmuludq $H1,$S4,$H0 # h1*s4 + vmovdqa 64(%rcx),$MASK # .Lmask26 + vpaddq $H4,$D4,$H4 # h4 = d4 + h0*r4 + vpaddq $H0,$D0,$H0 # h0 = d0 + h1*s4 + + ################################################################ + # lazy reduction (interleaved with tail of input splat) + + vpsrlq \$26,$H3,$D3 + vpand $MASK,$H3,$H3 + vpaddq $D3,$H4,$H4 # h3 -> h4 + + vpsrlq \$26,$H0,$D0 + vpand $MASK,$H0,$H0 + vpaddq $D0,$D1,$H1 # h0 -> h1 + + vpsrlq \$26,$H4,$D4 + vpand $MASK,$H4,$H4 + + vpsrlq \$4,$T3,$T2 + + vpsrlq \$26,$H1,$D1 + vpand $MASK,$H1,$H1 + vpaddq $D1,$H2,$H2 # h1 -> h2 + + vpaddq $D4,$H0,$H0 + vpsllq \$2,$D4,$D4 + vpaddq $D4,$H0,$H0 # h4 -> h0 + + vpand $MASK,$T2,$T2 # 2 + vpsrlq \$26,$T0,$T1 + + vpsrlq \$26,$H2,$D2 + vpand $MASK,$H2,$H2 + vpaddq $D2,$H3,$H3 # h2 -> h3 + + vpaddq $T2,$H2,$H2 # modulo-scheduled + vpsrlq \$30,$T3,$T3 + + vpsrlq \$26,$H0,$D0 + vpand $MASK,$H0,$H0 + vpaddq $D0,$H1,$H1 # h0 -> h1 + + vpsrlq \$40,$T4,$T4 # 4 + + vpsrlq \$26,$H3,$D3 + vpand $MASK,$H3,$H3 + vpaddq $D3,$H4,$H4 # h3 -> h4 + + vpand $MASK,$T0,$T0 # 0 + vpand $MASK,$T1,$T1 # 1 + vpand $MASK,$T3,$T3 # 3 + vpor 32(%rcx),$T4,$T4 # padbit, yes, always + + sub \$64,$len + jnz .Loop_avx2 + + .byte 0x66,0x90 +.Ltail_avx2: + ################################################################ + # while above multiplications were by r^4 in all lanes, in last + # iteration we multiply least significant lane by r^4 and most + # significant one by r, so copy of above except that references + # to the precomputed table are displaced by 4... + + #vpaddq $H2,$T2,$H2 # accumulate input + vpaddq $H0,$T0,$H0 + vmovdqu `32*0+4`(%rsp),$T0 # r0^4 + vpaddq $H1,$T1,$H1 + vmovdqu `32*1+4`(%rsp),$T1 # r1^4 + vpaddq $H3,$T3,$H3 + vmovdqu `32*3+4`(%rsp),$T2 # r2^4 + vpaddq $H4,$T4,$H4 + vmovdqu `32*6+4-0x90`(%rax),$T3 # s3^4 + vmovdqu `32*8+4-0x90`(%rax),$S4 # s4^4 + + vpmuludq $H2,$T0,$D2 # d2 = h2*r0 + vpmuludq $H2,$T1,$D3 # d3 = h2*r1 + vpmuludq $H2,$T2,$D4 # d4 = h2*r2 + vpmuludq $H2,$T3,$D0 # d0 = h2*s3 + vpmuludq $H2,$S4,$D1 # d1 = h2*s4 + + vpmuludq $H0,$T1,$T4 # h0*r1 + vpmuludq $H1,$T1,$H2 # h1*r1 + vpaddq $T4,$D1,$D1 # d1 += h0*r1 + vpaddq $H2,$D2,$D2 # d2 += h1*r1 + vpmuludq $H3,$T1,$T4 # h3*r1 + vpmuludq `32*2+4`(%rsp),$H4,$H2 # h4*s1 + vpaddq $T4,$D4,$D4 # d4 += h3*r1 + vpaddq $H2,$D0,$D0 # d0 += h4*s1 + + vpmuludq $H0,$T0,$T4 # h0*r0 + vpmuludq $H1,$T0,$H2 # h1*r0 + vpaddq $T4,$D0,$D0 # d0 += h0*r0 + vmovdqu `32*4+4-0x90`(%rax),$T1 # s2 + vpaddq $H2,$D1,$D1 # d1 += h1*r0 + vpmuludq $H3,$T0,$T4 # h3*r0 + vpmuludq $H4,$T0,$H2 # h4*r0 + vpaddq $T4,$D3,$D3 # d3 += h3*r0 + vpaddq $H2,$D4,$D4 # d4 += h4*r0 + + vpmuludq $H3,$T1,$T4 # h3*s2 + vpmuludq $H4,$T1,$H2 # h4*s2 + vpaddq $T4,$D0,$D0 # d0 += h3*s2 + vpaddq $H2,$D1,$D1 # d1 += h4*s2 + vmovdqu `32*5+4-0x90`(%rax),$H2 # r3 + vpmuludq $H1,$T2,$T4 # h1*r2 + vpmuludq $H0,$T2,$T2 # h0*r2 + vpaddq $T4,$D3,$D3 # d3 += h1*r2 + vpaddq $T2,$D2,$D2 # d2 += h0*r2 + + vpmuludq $H1,$H2,$T4 # h1*r3 + vpmuludq $H0,$H2,$H2 # h0*r3 + vpaddq $T4,$D4,$D4 # d4 += h1*r3 + vpaddq $H2,$D3,$D3 # d3 += h0*r3 + vpmuludq $H3,$T3,$T4 # h3*s3 + vpmuludq $H4,$T3,$H2 # h4*s3 + vpaddq $T4,$D1,$D1 # d1 += h3*s3 + vpaddq $H2,$D2,$D2 # d2 += h4*s3 + + vpmuludq $H3,$S4,$H3 # h3*s4 + vpmuludq $H4,$S4,$H4 # h4*s4 + vpaddq $H3,$D2,$H2 # h2 = d2 + h3*r4 + vpaddq $H4,$D3,$H3 # h3 = d3 + h4*r4 + vpmuludq `32*7+4-0x90`(%rax),$H0,$H4 # h0*r4 + vpmuludq $H1,$S4,$H0 # h1*s4 + vmovdqa 64(%rcx),$MASK # .Lmask26 + vpaddq $H4,$D4,$H4 # h4 = d4 + h0*r4 + vpaddq $H0,$D0,$H0 # h0 = d0 + h1*s4 + + ################################################################ + # horizontal addition + + vpsrldq \$8,$D1,$T1 + vpsrldq \$8,$H2,$T2 + vpsrldq \$8,$H3,$T3 + vpsrldq \$8,$H4,$T4 + vpsrldq \$8,$H0,$T0 + vpaddq $T1,$D1,$D1 + vpaddq $T2,$H2,$H2 + vpaddq $T3,$H3,$H3 + vpaddq $T4,$H4,$H4 + vpaddq $T0,$H0,$H0 + + vpermq \$0x2,$H3,$T3 + vpermq \$0x2,$H4,$T4 + vpermq \$0x2,$H0,$T0 + vpermq \$0x2,$D1,$T1 + vpermq \$0x2,$H2,$T2 + vpaddq $T3,$H3,$H3 + vpaddq $T4,$H4,$H4 + vpaddq $T0,$H0,$H0 + vpaddq $T1,$D1,$D1 + vpaddq $T2,$H2,$H2 + + ################################################################ + # lazy reduction + + vpsrlq \$26,$H3,$D3 + vpand $MASK,$H3,$H3 + vpaddq $D3,$H4,$H4 # h3 -> h4 + + vpsrlq \$26,$H0,$D0 + vpand $MASK,$H0,$H0 + vpaddq $D0,$D1,$H1 # h0 -> h1 + + vpsrlq \$26,$H4,$D4 + vpand $MASK,$H4,$H4 + + vpsrlq \$26,$H1,$D1 + vpand $MASK,$H1,$H1 + vpaddq $D1,$H2,$H2 # h1 -> h2 + + vpaddq $D4,$H0,$H0 + vpsllq \$2,$D4,$D4 + vpaddq $D4,$H0,$H0 # h4 -> h0 + + vpsrlq \$26,$H2,$D2 + vpand $MASK,$H2,$H2 + vpaddq $D2,$H3,$H3 # h2 -> h3 + + vpsrlq \$26,$H0,$D0 + vpand $MASK,$H0,$H0 + vpaddq $D0,$H1,$H1 # h0 -> h1 + + vpsrlq \$26,$H3,$D3 + vpand $MASK,$H3,$H3 + vpaddq $D3,$H4,$H4 # h3 -> h4 + + vmovd %x#$H0,`4*0-48-64`($ctx)# save partially reduced + vmovd %x#$H1,`4*1-48-64`($ctx) + vmovd %x#$H2,`4*2-48-64`($ctx) + vmovd %x#$H3,`4*3-48-64`($ctx) + vmovd %x#$H4,`4*4-48-64`($ctx) +___ +$code.=<<___ if ($win64); + vmovdqa 0x50(%r11),%xmm6 + vmovdqa 0x60(%r11),%xmm7 + vmovdqa 0x70(%r11),%xmm8 + vmovdqa 0x80(%r11),%xmm9 + vmovdqa 0x90(%r11),%xmm10 + vmovdqa 0xa0(%r11),%xmm11 + vmovdqa 0xb0(%r11),%xmm12 + vmovdqa 0xc0(%r11),%xmm13 + vmovdqa 0xd0(%r11),%xmm14 + vmovdqa 0xe0(%r11),%xmm15 + lea 0xf8(%r11),%rsp +.Ldo_avx2_epilogue: +___ +$code.=<<___ if (!$win64); + lea 8(%r11),%rsp +___ +$code.=<<___; + vzeroupper + ret +.size poly1305_blocks_avx2,.-poly1305_blocks_avx2 +___ +} +$code.=<<___; +.align 64 +.Lconst: +.Lmask24: +.long 0x0ffffff,0,0x0ffffff,0,0x0ffffff,0,0x0ffffff,0 +.L129: +.long 1<<24,0,1<<24,0,1<<24,0,1<<24,0 +.Lmask26: +.long 0x3ffffff,0,0x3ffffff,0,0x3ffffff,0,0x3ffffff,0 +.Lfive: +.long 5,0,5,0,5,0,5,0 +___ +} + +$code.=<<___; +.asciz "Poly1305 for x86_64, CRYPTOGAMS by " +.align 16 +___ + +# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame, +# CONTEXT *context,DISPATCHER_CONTEXT *disp) +if ($win64) { +$rec="%rcx"; +$frame="%rdx"; +$context="%r8"; +$disp="%r9"; + +$code.=<<___; +.extern __imp_RtlVirtualUnwind +.type se_handler,\@abi-omnipotent +.align 16 +se_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + mov 8($disp),%rsi # disp->ImageBase + mov 56($disp),%r11 # disp->HandlerData + + mov 0(%r11),%r10d # HandlerData[0] + lea (%rsi,%r10),%r10 # prologue label + cmp %r10,%rbx # context->Rip<.Lprologue + jb .Lcommon_seh_tail + + mov 152($context),%rax # pull context->Rsp + + mov 4(%r11),%r10d # HandlerData[1] + lea (%rsi,%r10),%r10 # epilogue label + cmp %r10,%rbx # context->Rip>=.Lepilogue + jae .Lcommon_seh_tail + + lea 48(%rax),%rax + + mov -8(%rax),%rbx + mov -16(%rax),%rbp + mov -24(%rax),%r12 + mov -32(%rax),%r13 + mov -40(%rax),%r14 + mov -48(%rax),%r15 + mov %rbx,144($context) # restore context->Rbx + mov %rbp,160($context) # restore context->Rbp + mov %r12,216($context) # restore context->R12 + mov %r13,224($context) # restore context->R13 + mov %r14,232($context) # restore context->R14 + mov %r15,240($context) # restore context->R14 + + jmp .Lcommon_seh_tail +.size se_handler,.-se_handler + +.type avx_handler,\@abi-omnipotent +.align 16 +avx_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + mov 8($disp),%rsi # disp->ImageBase + mov 56($disp),%r11 # disp->HandlerData + + mov 0(%r11),%r10d # HandlerData[0] + lea (%rsi,%r10),%r10 # prologue label + cmp %r10,%rbx # context->RipRsp + + mov 4(%r11),%r10d # HandlerData[1] + lea (%rsi,%r10),%r10 # epilogue label + cmp %r10,%rbx # context->Rip>=epilogue label + jae .Lcommon_seh_tail + + mov 208($context),%rax # pull context->R11 + + lea 0x50(%rax),%rsi + lea 0xf8(%rax),%rax + lea 512($context),%rdi # &context.Xmm6 + mov \$20,%ecx + .long 0xa548f3fc # cld; rep movsq + +.Lcommon_seh_tail: + mov 8(%rax),%rdi + mov 16(%rax),%rsi + mov %rax,152($context) # restore context->Rsp + mov %rsi,168($context) # restore context->Rsi + mov %rdi,176($context) # restore context->Rdi + + mov 40($disp),%rdi # disp->ContextRecord + mov $context,%rsi # context + mov \$154,%ecx # sizeof(CONTEXT) + .long 0xa548f3fc # cld; rep movsq + + mov $disp,%rsi + xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER + mov 8(%rsi),%rdx # arg2, disp->ImageBase + mov 0(%rsi),%r8 # arg3, disp->ControlPc + mov 16(%rsi),%r9 # arg4, disp->FunctionEntry + mov 40(%rsi),%r10 # disp->ContextRecord + lea 56(%rsi),%r11 # &disp->HandlerData + lea 24(%rsi),%r12 # &disp->EstablisherFrame + mov %r10,32(%rsp) # arg5 + mov %r11,40(%rsp) # arg6 + mov %r12,48(%rsp) # arg7 + mov %rcx,56(%rsp) # arg8, (NULL) + call *__imp_RtlVirtualUnwind(%rip) + + mov \$1,%eax # ExceptionContinueSearch + add \$64,%rsp + popfq + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + pop %rdi + pop %rsi + ret +.size avx_handler,.-avx_handler + +.section .pdata +.align 4 + .rva .LSEH_begin_poly1305_init + .rva .LSEH_end_poly1305_init + .rva .LSEH_info_poly1305_init + + .rva .LSEH_begin_poly1305_blocks + .rva .LSEH_end_poly1305_blocks + .rva .LSEH_info_poly1305_blocks + + .rva .LSEH_begin_poly1305_emit + .rva .LSEH_end_poly1305_emit + .rva .LSEH_info_poly1305_emit +___ +$code.=<<___ if ($avx); + .rva .LSEH_begin_poly1305_blocks_avx + .rva .Lbase2_64_avx + .rva .LSEH_info_poly1305_blocks_avx_1 + + .rva .Lbase2_64_avx + .rva .Leven_avx + .rva .LSEH_info_poly1305_blocks_avx_2 + + .rva .Leven_avx + .rva .LSEH_end_poly1305_blocks_avx + .rva .LSEH_info_poly1305_blocks_avx_3 + + .rva .LSEH_begin_poly1305_emit_avx + .rva .LSEH_end_poly1305_emit_avx + .rva .LSEH_info_poly1305_emit_avx +___ +$code.=<<___ if ($avx>1); + .rva .LSEH_begin_poly1305_blocks_avx2 + .rva .Lbase2_64_avx2 + .rva .LSEH_info_poly1305_blocks_avx2_1 + + .rva .Lbase2_64_avx2 + .rva .Leven_avx2 + .rva .LSEH_info_poly1305_blocks_avx2_2 + + .rva .Leven_avx2 + .rva .LSEH_end_poly1305_blocks_avx2 + .rva .LSEH_info_poly1305_blocks_avx2_3 +___ +$code.=<<___; +.section .xdata +.align 8 +.LSEH_info_poly1305_init: + .byte 9,0,0,0 + .rva se_handler + .rva .LSEH_begin_poly1305_init,.LSEH_begin_poly1305_init + +.LSEH_info_poly1305_blocks: + .byte 9,0,0,0 + .rva se_handler + .rva .Lblocks_body,.Lblocks_epilogue + +.LSEH_info_poly1305_emit: + .byte 9,0,0,0 + .rva se_handler + .rva .LSEH_begin_poly1305_emit,.LSEH_begin_poly1305_emit +___ +$code.=<<___ if ($avx); +.LSEH_info_poly1305_blocks_avx_1: + .byte 9,0,0,0 + .rva se_handler + .rva .Lblocks_avx_body,.Lblocks_avx_epilogue # HandlerData[] + +.LSEH_info_poly1305_blocks_avx_2: + .byte 9,0,0,0 + .rva se_handler + .rva .Lbase2_64_avx_body,.Lbase2_64_avx_epilogue # HandlerData[] + +.LSEH_info_poly1305_blocks_avx_3: + .byte 9,0,0,0 + .rva avx_handler + .rva .Ldo_avx_body,.Ldo_avx_epilogue # HandlerData[] + +.LSEH_info_poly1305_emit_avx: + .byte 9,0,0,0 + .rva se_handler + .rva .LSEH_begin_poly1305_emit_avx,.LSEH_begin_poly1305_emit_avx +___ +$code.=<<___ if ($avx>1); +.LSEH_info_poly1305_blocks_avx2_1: + .byte 9,0,0,0 + .rva se_handler + .rva .Lblocks_avx2_body,.Lblocks_avx2_epilogue # HandlerData[] + +.LSEH_info_poly1305_blocks_avx2_2: + .byte 9,0,0,0 + .rva se_handler + .rva .Lbase2_64_avx2_body,.Lbase2_64_avx2_epilogue # HandlerData[] + +.LSEH_info_poly1305_blocks_avx2_3: + .byte 9,0,0,0 + .rva avx_handler + .rva .Ldo_avx2_body,.Ldo_avx2_epilogue # HandlerData[] +___ +} + +foreach (split('\n',$code)) { + s/\`([^\`]*)\`/eval($1)/ge; + s/%r([a-z]+)#d/%e$1/g; + s/%r([0-9]+)#d/%r$1d/g; + s/%x#%y/%x/g; + + print $_,"\n"; +} +close STDOUT; diff --git a/external/boringssl/crypto/poly1305/internal.h b/external/boringssl/crypto/poly1305/internal.h new file mode 100644 index 0000000000..df6769ea4c --- /dev/null +++ b/external/boringssl/crypto/poly1305/internal.h @@ -0,0 +1,40 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_POLY1305_INTERNAL_H +#define OPENSSL_HEADER_POLY1305_INTERNAL_H + +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +#if defined(OPENSSL_ARM) && !defined(OPENSSL_NO_ASM) +void CRYPTO_poly1305_init_neon(poly1305_state *state, const uint8_t key[32]); + +void CRYPTO_poly1305_update_neon(poly1305_state *state, const uint8_t *in, + size_t in_len); + +void CRYPTO_poly1305_finish_neon(poly1305_state *state, uint8_t mac[16]); +#endif + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_POLY1305_INTERNAL_H */ diff --git a/external/boringssl/crypto/poly1305/poly1305.c b/external/boringssl/crypto/poly1305/poly1305.c new file mode 100644 index 0000000000..dc2d6a68a9 --- /dev/null +++ b/external/boringssl/crypto/poly1305/poly1305.c @@ -0,0 +1,324 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +/* This implementation of poly1305 is by Andrew Moon + * (https://github.com/floodyberry/poly1305-donna) and released as public + * domain. */ + +#include + +#include + +#include + +#include "internal.h" + + +#if defined(OPENSSL_WINDOWS) || !defined(OPENSSL_X86_64) + +#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64) || defined(OPENSSL_ARM) +/* We can assume little-endian. */ +static uint32_t U8TO32_LE(const uint8_t *m) { + uint32_t r; + memcpy(&r, m, sizeof(r)); + return r; +} + +static void U32TO8_LE(uint8_t *m, uint32_t v) { memcpy(m, &v, sizeof(v)); } +#else +static uint32_t U8TO32_LE(const uint8_t *m) { + return (uint32_t)m[0] | (uint32_t)m[1] << 8 | (uint32_t)m[2] << 16 | + (uint32_t)m[3] << 24; +} + +static void U32TO8_LE(uint8_t *m, uint32_t v) { + m[0] = v; + m[1] = v >> 8; + m[2] = v >> 16; + m[3] = v >> 24; +} +#endif + +static uint64_t mul32x32_64(uint32_t a, uint32_t b) { return (uint64_t)a * b; } + +struct poly1305_state_st { + uint32_t r0, r1, r2, r3, r4; + uint32_t s1, s2, s3, s4; + uint32_t h0, h1, h2, h3, h4; + uint8_t buf[16]; + unsigned int buf_used; + uint8_t key[16]; +}; + +/* poly1305_blocks updates |state| given some amount of input data. This + * function may only be called with a |len| that is not a multiple of 16 at the + * end of the data. Otherwise the input must be buffered into 16 byte blocks. */ +static void poly1305_update(struct poly1305_state_st *state, const uint8_t *in, + size_t len) { + uint32_t t0, t1, t2, t3; + uint64_t t[5]; + uint32_t b; + uint64_t c; + size_t j; + uint8_t mp[16]; + + if (len < 16) { + goto poly1305_donna_atmost15bytes; + } + +poly1305_donna_16bytes: + t0 = U8TO32_LE(in); + t1 = U8TO32_LE(in + 4); + t2 = U8TO32_LE(in + 8); + t3 = U8TO32_LE(in + 12); + + in += 16; + len -= 16; + + state->h0 += t0 & 0x3ffffff; + state->h1 += ((((uint64_t)t1 << 32) | t0) >> 26) & 0x3ffffff; + state->h2 += ((((uint64_t)t2 << 32) | t1) >> 20) & 0x3ffffff; + state->h3 += ((((uint64_t)t3 << 32) | t2) >> 14) & 0x3ffffff; + state->h4 += (t3 >> 8) | (1 << 24); + +poly1305_donna_mul: + t[0] = mul32x32_64(state->h0, state->r0) + mul32x32_64(state->h1, state->s4) + + mul32x32_64(state->h2, state->s3) + mul32x32_64(state->h3, state->s2) + + mul32x32_64(state->h4, state->s1); + t[1] = mul32x32_64(state->h0, state->r1) + mul32x32_64(state->h1, state->r0) + + mul32x32_64(state->h2, state->s4) + mul32x32_64(state->h3, state->s3) + + mul32x32_64(state->h4, state->s2); + t[2] = mul32x32_64(state->h0, state->r2) + mul32x32_64(state->h1, state->r1) + + mul32x32_64(state->h2, state->r0) + mul32x32_64(state->h3, state->s4) + + mul32x32_64(state->h4, state->s3); + t[3] = mul32x32_64(state->h0, state->r3) + mul32x32_64(state->h1, state->r2) + + mul32x32_64(state->h2, state->r1) + mul32x32_64(state->h3, state->r0) + + mul32x32_64(state->h4, state->s4); + t[4] = mul32x32_64(state->h0, state->r4) + mul32x32_64(state->h1, state->r3) + + mul32x32_64(state->h2, state->r2) + mul32x32_64(state->h3, state->r1) + + mul32x32_64(state->h4, state->r0); + + state->h0 = (uint32_t)t[0] & 0x3ffffff; + c = (t[0] >> 26); + t[1] += c; + state->h1 = (uint32_t)t[1] & 0x3ffffff; + b = (uint32_t)(t[1] >> 26); + t[2] += b; + state->h2 = (uint32_t)t[2] & 0x3ffffff; + b = (uint32_t)(t[2] >> 26); + t[3] += b; + state->h3 = (uint32_t)t[3] & 0x3ffffff; + b = (uint32_t)(t[3] >> 26); + t[4] += b; + state->h4 = (uint32_t)t[4] & 0x3ffffff; + b = (uint32_t)(t[4] >> 26); + state->h0 += b * 5; + + if (len >= 16) { + goto poly1305_donna_16bytes; + } + +/* final bytes */ +poly1305_donna_atmost15bytes: + if (!len) { + return; + } + + for (j = 0; j < len; j++) { + mp[j] = in[j]; + } + mp[j++] = 1; + for (; j < 16; j++) { + mp[j] = 0; + } + len = 0; + + t0 = U8TO32_LE(mp + 0); + t1 = U8TO32_LE(mp + 4); + t2 = U8TO32_LE(mp + 8); + t3 = U8TO32_LE(mp + 12); + + state->h0 += t0 & 0x3ffffff; + state->h1 += ((((uint64_t)t1 << 32) | t0) >> 26) & 0x3ffffff; + state->h2 += ((((uint64_t)t2 << 32) | t1) >> 20) & 0x3ffffff; + state->h3 += ((((uint64_t)t3 << 32) | t2) >> 14) & 0x3ffffff; + state->h4 += (t3 >> 8); + + goto poly1305_donna_mul; +} + +void CRYPTO_poly1305_init(poly1305_state *statep, const uint8_t key[32]) { + struct poly1305_state_st *state = (struct poly1305_state_st *)statep; + uint32_t t0, t1, t2, t3; + +#if defined(OPENSSL_ARM) && !defined(OPENSSL_NO_ASM) + if (CRYPTO_is_NEON_capable()) { + CRYPTO_poly1305_init_neon(statep, key); + return; + } +#endif + + t0 = U8TO32_LE(key + 0); + t1 = U8TO32_LE(key + 4); + t2 = U8TO32_LE(key + 8); + t3 = U8TO32_LE(key + 12); + + /* precompute multipliers */ + state->r0 = t0 & 0x3ffffff; + t0 >>= 26; + t0 |= t1 << 6; + state->r1 = t0 & 0x3ffff03; + t1 >>= 20; + t1 |= t2 << 12; + state->r2 = t1 & 0x3ffc0ff; + t2 >>= 14; + t2 |= t3 << 18; + state->r3 = t2 & 0x3f03fff; + t3 >>= 8; + state->r4 = t3 & 0x00fffff; + + state->s1 = state->r1 * 5; + state->s2 = state->r2 * 5; + state->s3 = state->r3 * 5; + state->s4 = state->r4 * 5; + + /* init state */ + state->h0 = 0; + state->h1 = 0; + state->h2 = 0; + state->h3 = 0; + state->h4 = 0; + + state->buf_used = 0; + memcpy(state->key, key + 16, sizeof(state->key)); +} + +void CRYPTO_poly1305_update(poly1305_state *statep, const uint8_t *in, + size_t in_len) { + unsigned int i; + struct poly1305_state_st *state = (struct poly1305_state_st *)statep; + +#if defined(OPENSSL_ARM) && !defined(OPENSSL_NO_ASM) + if (CRYPTO_is_NEON_capable()) { + CRYPTO_poly1305_update_neon(statep, in, in_len); + return; + } +#endif + + if (state->buf_used) { + unsigned int todo = 16 - state->buf_used; + if (todo > in_len) { + todo = in_len; + } + for (i = 0; i < todo; i++) { + state->buf[state->buf_used + i] = in[i]; + } + state->buf_used += todo; + in_len -= todo; + in += todo; + + if (state->buf_used == 16) { + poly1305_update(state, state->buf, 16); + state->buf_used = 0; + } + } + + if (in_len >= 16) { + size_t todo = in_len & ~0xf; + poly1305_update(state, in, todo); + in += todo; + in_len &= 0xf; + } + + if (in_len) { + for (i = 0; i < in_len; i++) { + state->buf[i] = in[i]; + } + state->buf_used = in_len; + } +} + +void CRYPTO_poly1305_finish(poly1305_state *statep, uint8_t mac[16]) { + struct poly1305_state_st *state = (struct poly1305_state_st *)statep; + uint64_t f0, f1, f2, f3; + uint32_t g0, g1, g2, g3, g4; + uint32_t b, nb; + +#if defined(OPENSSL_ARM) && !defined(OPENSSL_NO_ASM) + if (CRYPTO_is_NEON_capable()) { + CRYPTO_poly1305_finish_neon(statep, mac); + return; + } +#endif + + if (state->buf_used) { + poly1305_update(state, state->buf, state->buf_used); + } + + b = state->h0 >> 26; + state->h0 = state->h0 & 0x3ffffff; + state->h1 += b; + b = state->h1 >> 26; + state->h1 = state->h1 & 0x3ffffff; + state->h2 += b; + b = state->h2 >> 26; + state->h2 = state->h2 & 0x3ffffff; + state->h3 += b; + b = state->h3 >> 26; + state->h3 = state->h3 & 0x3ffffff; + state->h4 += b; + b = state->h4 >> 26; + state->h4 = state->h4 & 0x3ffffff; + state->h0 += b * 5; + + g0 = state->h0 + 5; + b = g0 >> 26; + g0 &= 0x3ffffff; + g1 = state->h1 + b; + b = g1 >> 26; + g1 &= 0x3ffffff; + g2 = state->h2 + b; + b = g2 >> 26; + g2 &= 0x3ffffff; + g3 = state->h3 + b; + b = g3 >> 26; + g3 &= 0x3ffffff; + g4 = state->h4 + b - (1 << 26); + + b = (g4 >> 31) - 1; + nb = ~b; + state->h0 = (state->h0 & nb) | (g0 & b); + state->h1 = (state->h1 & nb) | (g1 & b); + state->h2 = (state->h2 & nb) | (g2 & b); + state->h3 = (state->h3 & nb) | (g3 & b); + state->h4 = (state->h4 & nb) | (g4 & b); + + f0 = ((state->h0) | (state->h1 << 26)) + (uint64_t)U8TO32_LE(&state->key[0]); + f1 = ((state->h1 >> 6) | (state->h2 << 20)) + + (uint64_t)U8TO32_LE(&state->key[4]); + f2 = ((state->h2 >> 12) | (state->h3 << 14)) + + (uint64_t)U8TO32_LE(&state->key[8]); + f3 = ((state->h3 >> 18) | (state->h4 << 8)) + + (uint64_t)U8TO32_LE(&state->key[12]); + + U32TO8_LE(&mac[0], f0); + f1 += (f0 >> 32); + U32TO8_LE(&mac[4], f1); + f2 += (f1 >> 32); + U32TO8_LE(&mac[8], f2); + f3 += (f2 >> 32); + U32TO8_LE(&mac[12], f3); +} + +#endif /* OPENSSL_WINDOWS || !OPENSSL_X86_64 */ diff --git a/external/boringssl/crypto/poly1305/poly1305_arm.c b/external/boringssl/crypto/poly1305/poly1305_arm.c new file mode 100644 index 0000000000..de31d6b277 --- /dev/null +++ b/external/boringssl/crypto/poly1305/poly1305_arm.c @@ -0,0 +1,304 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +/* This implementation was taken from the public domain, neon2 version in + * SUPERCOP by D. J. Bernstein and Peter Schwabe. */ + +#include + +#if defined(OPENSSL_ARM) && !defined(OPENSSL_NO_ASM) + +#include + +#include "../internal.h" +#include "internal.h" + + +typedef struct { + uint32_t v[12]; /* for alignment; only using 10 */ +} fe1305x2; + +#define addmulmod openssl_poly1305_neon2_addmulmod +#define blocks openssl_poly1305_neon2_blocks + +extern void addmulmod(fe1305x2 *r, const fe1305x2 *x, const fe1305x2 *y, + const fe1305x2 *c); + +extern int blocks(fe1305x2 *h, const fe1305x2 *precomp, const uint8_t *in, + unsigned int inlen); + +static void freeze(fe1305x2 *r) { + int i; + + uint32_t x0 = r->v[0]; + uint32_t x1 = r->v[2]; + uint32_t x2 = r->v[4]; + uint32_t x3 = r->v[6]; + uint32_t x4 = r->v[8]; + uint32_t y0; + uint32_t y1; + uint32_t y2; + uint32_t y3; + uint32_t y4; + uint32_t swap; + + for (i = 0; i < 3; ++i) { + x1 += x0 >> 26; + x0 &= 0x3ffffff; + x2 += x1 >> 26; + x1 &= 0x3ffffff; + x3 += x2 >> 26; + x2 &= 0x3ffffff; + x4 += x3 >> 26; + x3 &= 0x3ffffff; + x0 += 5 * (x4 >> 26); + x4 &= 0x3ffffff; + } + + y0 = x0 + 5; + y1 = x1 + (y0 >> 26); + y0 &= 0x3ffffff; + y2 = x2 + (y1 >> 26); + y1 &= 0x3ffffff; + y3 = x3 + (y2 >> 26); + y2 &= 0x3ffffff; + y4 = x4 + (y3 >> 26); + y3 &= 0x3ffffff; + swap = -(y4 >> 26); + y4 &= 0x3ffffff; + + y0 ^= x0; + y1 ^= x1; + y2 ^= x2; + y3 ^= x3; + y4 ^= x4; + + y0 &= swap; + y1 &= swap; + y2 &= swap; + y3 &= swap; + y4 &= swap; + + y0 ^= x0; + y1 ^= x1; + y2 ^= x2; + y3 ^= x3; + y4 ^= x4; + + r->v[0] = y0; + r->v[2] = y1; + r->v[4] = y2; + r->v[6] = y3; + r->v[8] = y4; +} + +static void fe1305x2_tobytearray(uint8_t *r, fe1305x2 *x) { + uint32_t x0 = x->v[0]; + uint32_t x1 = x->v[2]; + uint32_t x2 = x->v[4]; + uint32_t x3 = x->v[6]; + uint32_t x4 = x->v[8]; + + x1 += x0 >> 26; + x0 &= 0x3ffffff; + x2 += x1 >> 26; + x1 &= 0x3ffffff; + x3 += x2 >> 26; + x2 &= 0x3ffffff; + x4 += x3 >> 26; + x3 &= 0x3ffffff; + + *(uint32_t *)r = x0 + (x1 << 26); + *(uint32_t *)(r + 4) = (x1 >> 6) + (x2 << 20); + *(uint32_t *)(r + 8) = (x2 >> 12) + (x3 << 14); + *(uint32_t *)(r + 12) = (x3 >> 18) + (x4 << 8); +} + +/* load32 exists to avoid breaking strict aliasing rules in + * fe1305x2_frombytearray. */ +static uint32_t load32(uint8_t *t) { + uint32_t tmp; + memcpy(&tmp, t, sizeof(tmp)); + return tmp; +} + +static void fe1305x2_frombytearray(fe1305x2 *r, const uint8_t *x, + unsigned long long xlen) { + unsigned i; + uint8_t t[17]; + + for (i = 0; (i < 16) && (i < xlen); i++) { + t[i] = x[i]; + } + xlen -= i; + x += i; + t[i++] = 1; + for (; i < 17; i++) { + t[i] = 0; + } + + r->v[0] = 0x3ffffff & load32(t); + r->v[2] = 0x3ffffff & (load32(t + 3) >> 2); + r->v[4] = 0x3ffffff & (load32(t + 6) >> 4); + r->v[6] = 0x3ffffff & (load32(t + 9) >> 6); + r->v[8] = load32(t + 13); + + if (xlen) { + for (i = 0; (i < 16) && (i < xlen); i++) { + t[i] = x[i]; + } + t[i++] = 1; + for (; i < 17; i++) { + t[i] = 0; + } + + r->v[1] = 0x3ffffff & load32(t); + r->v[3] = 0x3ffffff & (load32(t + 3) >> 2); + r->v[5] = 0x3ffffff & (load32(t + 6) >> 4); + r->v[7] = 0x3ffffff & (load32(t + 9) >> 6); + r->v[9] = load32(t + 13); + } else { + r->v[1] = r->v[3] = r->v[5] = r->v[7] = r->v[9] = 0; + } +} + +static const alignas(16) fe1305x2 zero; + +struct poly1305_state_st { + uint8_t data[sizeof(fe1305x2[5]) + 128]; + uint8_t buf[32]; + unsigned int buf_used; + uint8_t key[16]; +}; + +void CRYPTO_poly1305_init_neon(poly1305_state *state, const uint8_t key[32]) { + struct poly1305_state_st *st = (struct poly1305_state_st *)(state); + fe1305x2 *const r = (fe1305x2 *)(st->data + (15 & (-(int)st->data))); + fe1305x2 *const h = r + 1; + fe1305x2 *const c = h + 1; + fe1305x2 *const precomp = c + 1; + unsigned int j; + + r->v[1] = r->v[0] = 0x3ffffff & *(uint32_t *)key; + r->v[3] = r->v[2] = 0x3ffff03 & ((*(uint32_t *)(key + 3)) >> 2); + r->v[5] = r->v[4] = 0x3ffc0ff & ((*(uint32_t *)(key + 6)) >> 4); + r->v[7] = r->v[6] = 0x3f03fff & ((*(uint32_t *)(key + 9)) >> 6); + r->v[9] = r->v[8] = 0x00fffff & ((*(uint32_t *)(key + 12)) >> 8); + + for (j = 0; j < 10; j++) { + h->v[j] = 0; /* XXX: should fast-forward a bit */ + } + + addmulmod(precomp, r, r, &zero); /* precompute r^2 */ + addmulmod(precomp + 1, precomp, precomp, &zero); /* precompute r^4 */ + + memcpy(st->key, key + 16, 16); + st->buf_used = 0; +} + +void CRYPTO_poly1305_update_neon(poly1305_state *state, const uint8_t *in, + size_t in_len) { + struct poly1305_state_st *st = (struct poly1305_state_st *)(state); + fe1305x2 *const r = (fe1305x2 *)(st->data + (15 & (-(int)st->data))); + fe1305x2 *const h = r + 1; + fe1305x2 *const c = h + 1; + fe1305x2 *const precomp = c + 1; + unsigned int i; + + if (st->buf_used) { + unsigned int todo = 32 - st->buf_used; + if (todo > in_len) { + todo = in_len; + } + for (i = 0; i < todo; i++) { + st->buf[st->buf_used + i] = in[i]; + } + st->buf_used += todo; + in_len -= todo; + in += todo; + + if (st->buf_used == sizeof(st->buf) && in_len) { + addmulmod(h, h, precomp, &zero); + fe1305x2_frombytearray(c, st->buf, sizeof(st->buf)); + for (i = 0; i < 10; i++) { + h->v[i] += c->v[i]; + } + st->buf_used = 0; + } + } + + while (in_len > 32) { + unsigned int tlen = 1048576; + if (in_len < tlen) { + tlen = in_len; + } + tlen -= blocks(h, precomp, in, tlen); + in_len -= tlen; + in += tlen; + } + + if (in_len) { + for (i = 0; i < in_len; i++) { + st->buf[i] = in[i]; + } + st->buf_used = in_len; + } +} + +void CRYPTO_poly1305_finish_neon(poly1305_state *state, uint8_t mac[16]) { + struct poly1305_state_st *st = (struct poly1305_state_st *)(state); + fe1305x2 *const r = (fe1305x2 *)(st->data + (15 & (-(int)st->data))); + fe1305x2 *const h = r + 1; + fe1305x2 *const c = h + 1; + fe1305x2 *const precomp = c + 1; + + addmulmod(h, h, precomp, &zero); + + if (st->buf_used > 16) { + fe1305x2_frombytearray(c, st->buf, st->buf_used); + precomp->v[1] = r->v[1]; + precomp->v[3] = r->v[3]; + precomp->v[5] = r->v[5]; + precomp->v[7] = r->v[7]; + precomp->v[9] = r->v[9]; + addmulmod(h, h, precomp, c); + } else if (st->buf_used > 0) { + fe1305x2_frombytearray(c, st->buf, st->buf_used); + r->v[1] = 1; + r->v[3] = 0; + r->v[5] = 0; + r->v[7] = 0; + r->v[9] = 0; + addmulmod(h, h, r, c); + } + + h->v[0] += h->v[1]; + h->v[2] += h->v[3]; + h->v[4] += h->v[5]; + h->v[6] += h->v[7]; + h->v[8] += h->v[9]; + freeze(h); + + fe1305x2_frombytearray(c, st->key, 16); + c->v[8] ^= (1 << 24); + + h->v[0] += c->v[0]; + h->v[2] += c->v[2]; + h->v[4] += c->v[4]; + h->v[6] += c->v[6]; + h->v[8] += c->v[8]; + fe1305x2_tobytearray(mac, h); +} + +#endif /* OPENSSL_ARM && !OPENSSL_NO_ASM */ diff --git a/external/boringssl/crypto/poly1305/poly1305_arm_asm.S b/external/boringssl/crypto/poly1305/poly1305_arm_asm.S new file mode 100644 index 0000000000..e16f83bdd0 --- /dev/null +++ b/external/boringssl/crypto/poly1305/poly1305_arm_asm.S @@ -0,0 +1,2015 @@ +#if defined(__arm__) && !defined(OPENSSL_NO_ASM) + +# This implementation was taken from the public domain, neon2 version in +# SUPERCOP by D. J. Bernstein and Peter Schwabe. + +# qhasm: int32 input_0 + +# qhasm: int32 input_1 + +# qhasm: int32 input_2 + +# qhasm: int32 input_3 + +# qhasm: stack32 input_4 + +# qhasm: stack32 input_5 + +# qhasm: stack32 input_6 + +# qhasm: stack32 input_7 + +# qhasm: int32 caller_r4 + +# qhasm: int32 caller_r5 + +# qhasm: int32 caller_r6 + +# qhasm: int32 caller_r7 + +# qhasm: int32 caller_r8 + +# qhasm: int32 caller_r9 + +# qhasm: int32 caller_r10 + +# qhasm: int32 caller_r11 + +# qhasm: int32 caller_r12 + +# qhasm: int32 caller_r14 + +# qhasm: reg128 caller_q4 + +# qhasm: reg128 caller_q5 + +# qhasm: reg128 caller_q6 + +# qhasm: reg128 caller_q7 + +# qhasm: startcode +.fpu neon +.text + +# qhasm: reg128 r0 + +# qhasm: reg128 r1 + +# qhasm: reg128 r2 + +# qhasm: reg128 r3 + +# qhasm: reg128 r4 + +# qhasm: reg128 x01 + +# qhasm: reg128 x23 + +# qhasm: reg128 x4 + +# qhasm: reg128 y0 + +# qhasm: reg128 y12 + +# qhasm: reg128 y34 + +# qhasm: reg128 5y12 + +# qhasm: reg128 5y34 + +# qhasm: stack128 y0_stack + +# qhasm: stack128 y12_stack + +# qhasm: stack128 y34_stack + +# qhasm: stack128 5y12_stack + +# qhasm: stack128 5y34_stack + +# qhasm: reg128 z0 + +# qhasm: reg128 z12 + +# qhasm: reg128 z34 + +# qhasm: reg128 5z12 + +# qhasm: reg128 5z34 + +# qhasm: stack128 z0_stack + +# qhasm: stack128 z12_stack + +# qhasm: stack128 z34_stack + +# qhasm: stack128 5z12_stack + +# qhasm: stack128 5z34_stack + +# qhasm: stack128 two24 + +# qhasm: int32 ptr + +# qhasm: reg128 c01 + +# qhasm: reg128 c23 + +# qhasm: reg128 d01 + +# qhasm: reg128 d23 + +# qhasm: reg128 t0 + +# qhasm: reg128 t1 + +# qhasm: reg128 t2 + +# qhasm: reg128 t3 + +# qhasm: reg128 t4 + +# qhasm: reg128 mask + +# qhasm: reg128 u0 + +# qhasm: reg128 u1 + +# qhasm: reg128 u2 + +# qhasm: reg128 u3 + +# qhasm: reg128 u4 + +# qhasm: reg128 v01 + +# qhasm: reg128 mid + +# qhasm: reg128 v23 + +# qhasm: reg128 v4 + +# qhasm: int32 len + +# qhasm: qpushenter crypto_onetimeauth_poly1305_neon2_blocks +.align 4 +.global openssl_poly1305_neon2_blocks +.hidden openssl_poly1305_neon2_blocks +.type openssl_poly1305_neon2_blocks STT_FUNC +openssl_poly1305_neon2_blocks: +vpush {q4,q5,q6,q7} +mov r12,sp +sub sp,sp,#192 +bic sp,sp,#31 + +# qhasm: len = input_3 +# asm 1: mov >len=int32#4,len=r3,y12=reg128#2%bot->y12=reg128#2%top},[y12=d2->y12=d3},[y34=reg128#3%bot->y34=reg128#3%top},[y34=d4->y34=d5},[input_1=int32#2,input_1=r1,z12=reg128#5%bot->z12=reg128#5%top},[z12=d8->z12=d9},[z34=reg128#6%bot->z34=reg128#6%top},[z34=d10->z34=d11},[mask=reg128#7,#0xffffffff +# asm 2: vmov.i64 >mask=q6,#0xffffffff +vmov.i64 q6,#0xffffffff + +# qhasm: 2x u4 = 0xff +# asm 1: vmov.i64 >u4=reg128#8,#0xff +# asm 2: vmov.i64 >u4=q7,#0xff +vmov.i64 q7,#0xff + +# qhasm: x01 aligned= mem128[input_0];input_0+=16 +# asm 1: vld1.8 {>x01=reg128#9%bot->x01=reg128#9%top},[x01=d16->x01=d17},[x23=reg128#10%bot->x23=reg128#10%top},[x23=d18->x23=d19},[input_0=int32#1,input_0=r0,>=6 +# asm 1: vshr.u64 >mask=reg128#7,mask=q6,>= 7 +# asm 1: vshr.u64 >u4=reg128#8,u4=q7,5y12=reg128#12,5y12=q11,5y34=reg128#13,5y34=q12,5y12=reg128#12,<5y12=reg128#12,5y12=q11,<5y12=q11,5y34=reg128#13,<5y34=reg128#13,5y34=q12,<5y34=q12,u4=reg128#8,u4=q7,5z12=reg128#14,5z12=q13,5z34=reg128#15,5z34=q14,5z12=reg128#14,<5z12=reg128#14,5z12=q13,<5z12=q13,5z34=reg128#15,<5z34=reg128#15,5z34=q14,<5z34=q14,ptr=int32#2,ptr=r1,r4=reg128#16,r4=q15,r0=reg128#8,r0=q7,ptr=int32#2,ptr=r1,ptr=int32#2,ptr=r1,ptr=int32#2,ptr=r1,ptr=int32#2,ptr=r1,ptr=int32#2,ptr=r1,ptr=int32#2,ptr=r1,ptr=int32#2,<5y12_stack=stack128#5 +# asm 2: lea >ptr=r1,<5y12_stack=[sp,#64] +add r1,sp,#64 + +# qhasm: mem128[ptr] aligned= 5y12 +# asm 1: vst1.8 {<5y12=reg128#12%bot-<5y12=reg128#12%top},[ptr=int32#2,<5y34_stack=stack128#6 +# asm 2: lea >ptr=r1,<5y34_stack=[sp,#80] +add r1,sp,#80 + +# qhasm: mem128[ptr] aligned= 5y34 +# asm 1: vst1.8 {<5y34=reg128#13%bot-<5y34=reg128#13%top},[ptr=int32#2,<5z12_stack=stack128#10 +# asm 2: lea >ptr=r1,<5z12_stack=[sp,#144] +add r1,sp,#144 + +# qhasm: mem128[ptr] aligned= 5z12 +# asm 1: vst1.8 {<5z12=reg128#14%bot-<5z12=reg128#14%top},[ptr=int32#2,<5z34_stack=stack128#11 +# asm 2: lea >ptr=r1,<5z34_stack=[sp,#160] +add r1,sp,#160 + +# qhasm: mem128[ptr] aligned= 5z34 +# asm 1: vst1.8 {<5z34=reg128#15%bot-<5z34=reg128#15%top},[? len - 64 +# asm 1: cmp +bls ._below64bytes + +# qhasm: input_2 += 32 +# asm 1: add >input_2=int32#2,input_2=r1,c01=reg128#1%bot->c01=reg128#1%top},[c01=d0->c01=d1},[c23=reg128#2%bot->c23=reg128#2%top},[c23=d2->c23=d3},[ptr=int32#3,ptr=r2,z12=reg128#3%bot->z12=reg128#3%top},[z12=d4->z12=d5},[ptr=int32#3,ptr=r2,z0=reg128#4%bot->z0=reg128#4%top},[z0=d6->z0=d7},[r3=reg128#5,r3=q4,input_2=int32#2,input_2=r1,ptr=int32#3,<5z34_stack=stack128#11 +# asm 2: lea >ptr=r2,<5z34_stack=[sp,#160] +add r2,sp,#160 + +# qhasm: 5z34 aligned= mem128[ptr] +# asm 1: vld1.8 {>5z34=reg128#6%bot->5z34=reg128#6%top},[5z34=d10->5z34=d11},[r0=reg128#8,r0=q7,r2=reg128#14,r2=q13,d01=reg128#12%bot->d01=reg128#12%top},[d01=d22->d01=d23},[r1=reg128#15,r1=q14,ptr=int32#3,<5z12_stack=stack128#10 +# asm 2: lea >ptr=r2,<5z12_stack=[sp,#144] +add r2,sp,#144 + +# qhasm: 5z12 aligned= mem128[ptr] +# asm 1: vld1.8 {>5z12=reg128#1%bot->5z12=reg128#1%top},[5z12=d0->5z12=d1},[d23=reg128#2%bot->d23=reg128#2%top},[d23=d2->d23=d3},[input_2=int32#2,input_2=r1,> 40 +# asm 1: vshr.u64 >v4=reg128#4,v4=q3,> 14; v23[3] = d23[2,3] unsigned>> 14 +# asm 1: vshrn.u64 > 26; v01[3] = d01[2,3] unsigned>> 26 +# asm 1: vshrn.u64 > 20; v23[1] = mid[2,3] unsigned>> 20 +# asm 1: vshrn.u64 ptr=int32#3,ptr=r2,y34=reg128#3%bot->y34=reg128#3%top},[y34=d4->y34=d5},[ptr=int32#3,ptr=r2,y12=reg128#2%bot->y12=reg128#2%top},[y12=d2->y12=d3},[ptr=int32#3,ptr=r2,y0=reg128#1%bot->y0=reg128#1%top},[y0=d0->y0=d1},[ptr=int32#3,<5y34_stack=stack128#6 +# asm 2: lea >ptr=r2,<5y34_stack=[sp,#80] +add r2,sp,#80 + +# qhasm: 5y34 aligned= mem128[ptr] +# asm 1: vld1.8 {>5y34=reg128#13%bot->5y34=reg128#13%top},[5y34=d24->5y34=d25},[ptr=int32#3,<5y12_stack=stack128#5 +# asm 2: lea >ptr=r2,<5y12_stack=[sp,#64] +add r2,sp,#64 + +# qhasm: 5y12 aligned= mem128[ptr] +# asm 1: vld1.8 {>5y12=reg128#12%bot->5y12=reg128#12%top},[5y12=d22->5y12=d23},[ptr=int32#3,ptr=r2,> 26 +# asm 1: vshr.u64 >t1=reg128#4,t1=q3,len=int32#4,len=r3,r0=reg128#6,r0=q5,r1=reg128#4,r1=q3,> 26 +# asm 1: vshr.u64 >t4=reg128#8,t4=q7,r3=reg128#5,r3=q4,x4=reg128#8,x4=q7,r4=reg128#16%bot->r4=reg128#16%top},[r4=d30->r4=d31},[> 26 +# asm 1: vshr.u64 >t2=reg128#9,t2=q8,r1=reg128#4,r1=q3,> 26 +# asm 1: vshr.u64 >t0=reg128#10,t0=q9,r2=reg128#9,r2=q8,x4=reg128#11,x4=q10,x01=reg128#6,x01=q5,r0=reg128#8%bot->r0=reg128#8%top},[r0=d14->r0=d15},[ptr=int32#3,ptr=r2,t0=reg128#10,t0=q9,> 26 +# asm 1: vshr.u64 >t3=reg128#14,t3=q13,x01=reg128#15,x01=q14,z34=reg128#6%bot->z34=reg128#6%top},[z34=d10->z34=d11},[x23=reg128#10,x23=q9,r3=reg128#5,r3=q4,input_2=int32#2,input_2=r1,> 26 +# asm 1: vshr.u64 >t1=reg128#14,t1=q13,x01=reg128#9,x01=q8,r1=reg128#4,r1=q3,> 26 +# asm 1: vshr.u64 >t4=reg128#14,t4=q13,r3=reg128#5,r3=q4,x4=reg128#11,x4=q10,? len - 64 +# asm 1: cmp +bhi ._mainloop2 + +# qhasm: input_2 -= 32 +# asm 1: sub >input_2=int32#3,input_2=r2,? len - 32 +# asm 1: cmp +bls ._end + +# qhasm: mainloop: +._mainloop: + +# qhasm: new r0 + +# qhasm: ptr = &two24 +# asm 1: lea >ptr=int32#2,ptr=r1,r4=reg128#5%bot->r4=reg128#5%top},[r4=d8->r4=d9},[u4=reg128#6%bot->u4=reg128#6%top},[u4=d10->u4=d11},[c01=reg128#8%bot->c01=reg128#8%top},[c01=d14->c01=d15},[c23=reg128#14%bot->c23=reg128#14%top},[c23=d26->c23=d27},[r0=reg128#4,r0=q3,r3=reg128#6,r3=q5,r1=reg128#14,r1=q13,r2=reg128#8,r2=q7,> 26 +# asm 1: vshr.u64 >t1=reg128#9,t1=q8,r0=reg128#4,r0=q3,r1=reg128#9,r1=q8,> 26 +# asm 1: vshr.u64 >t4=reg128#10,t4=q9,r3=reg128#6,r3=q5,r4=reg128#5,r4=q4,> 26 +# asm 1: vshr.u64 >t2=reg128#10,t2=q9,r1=reg128#11,r1=q10,> 26 +# asm 1: vshr.u64 >t0=reg128#9,t0=q8,r2=reg128#8,r2=q7,r4=reg128#5,r4=q4,r0=reg128#4,r0=q3,t0=reg128#9,t0=q8,> 26 +# asm 1: vshr.u64 >t3=reg128#14,t3=q13,r0=reg128#4,r0=q3,x23=reg128#10,x23=q9,r3=reg128#6,r3=q5,> 26 +# asm 1: vshr.u64 >t1=reg128#8,t1=q7,x01=reg128#9,x01=q8,r1=reg128#4,r1=q3,> 26 +# asm 1: vshr.u64 >t4=reg128#8,t4=q7,r3=reg128#6,r3=q5,x4=reg128#11,x4=q10,len=int32#4,len=r3,? len - 32 +# asm 1: cmp +bhi ._mainloop + +# qhasm: end: +._end: + +# qhasm: mem128[input_0] = x01;input_0+=16 +# asm 1: vst1.8 {len=int32#1,len=r0,mask=reg128#1,#0xffffffff +# asm 2: vmov.i64 >mask=q0,#0xffffffff +vmov.i64 q0,#0xffffffff + +# qhasm: y01 aligned= mem128[input_2];input_2+=16 +# asm 1: vld1.8 {>y01=reg128#2%bot->y01=reg128#2%top},[y01=d2->y01=d3},[_5y01=reg128#3,_5y01=q2,y23=reg128#4%bot->y23=reg128#4%top},[y23=d6->y23=d7},[_5y23=reg128#9,_5y23=q8,_5y4=reg128#11,_5y4=q10,x01=reg128#12%bot->x01=reg128#12%top},[x01=d22->x01=d23},[_5y01=reg128#3,<_5y01=reg128#3,_5y01=q2,<_5y01=q2,x23=reg128#13%bot->x23=reg128#13%top},[x23=d24->x23=d25},[_5y23=reg128#9,<_5y23=reg128#9,_5y23=q8,<_5y23=q8,_5y4=reg128#11,<_5y4=reg128#11,_5y4=q10,<_5y4=q10,c01=reg128#14%bot->c01=reg128#14%top},[c01=d26->c01=d27},[x01=reg128#12,x01=q11,c23=reg128#14%bot->c23=reg128#14%top},[c23=d26->c23=d27},[x23=reg128#13,x23=q12,>=6 +# asm 1: vshr.u64 >mask=reg128#1,mask=q0,x4=reg128#14,x4=q13,r0=reg128#15,r0=q14,r1=reg128#3,r1=q2,r2=reg128#16,r2=q15,r3=reg128#9,r3=q8,r4=reg128#10,r4=q9,> 26 +# asm 1: vshr.u64 >t1=reg128#2,t1=q1,r0=reg128#4,r0=q3,r1=reg128#2,r1=q1,> 26 +# asm 1: vshr.u64 >t4=reg128#3,t4=q2,r3=reg128#9,r3=q8,r4=reg128#3,r4=q2,> 26 +# asm 1: vshr.u64 >t2=reg128#10,t2=q9,r1=reg128#2,r1=q1,> 26 +# asm 1: vshr.u64 >t0=reg128#11,t0=q10,r2=reg128#10,r2=q9,r4=reg128#3,r4=q2,r0=reg128#4,r0=q3,t0=reg128#11,t0=q10,> 26 +# asm 1: vshr.u64 >t3=reg128#12,t3=q11,r0=reg128#4,r0=q3,x23=reg128#10,x23=q9,r3=reg128#9,r3=q8,> 26 +# asm 1: vshr.u64 >t1=reg128#11,t1=q10,x01=reg128#4,x01=q3,r1=reg128#2,r1=q1,> 26 +# asm 1: vshr.u64 >t4=reg128#11,t4=q10,r3=reg128#1,r3=q0,x4=reg128#3,x4=q2, +#include + +#include + +#include +#include + +#include "../internal.h" +#include "../test/file_test.h" + + +static bool TestSIMD(FileTest *t, unsigned excess, + const std::vector &key, + const std::vector &in, + const std::vector &mac) { + poly1305_state state; + CRYPTO_poly1305_init(&state, key.data()); + + size_t done = 0; + + // Feed 16 bytes in. Some implementations begin in non-SIMD mode and upgrade + // on-demand. Stress the upgrade path. + size_t todo = 16; + if (todo > in.size()) { + todo = in.size(); + } + CRYPTO_poly1305_update(&state, in.data(), todo); + done += todo; + + for (;;) { + // Feed 128 + |excess| bytes to test SIMD mode. + if (done + 128 + excess > in.size()) { + break; + } + CRYPTO_poly1305_update(&state, in.data() + done, 128 + excess); + done += 128 + excess; + + // Feed |excess| bytes to ensure SIMD mode can handle short inputs. + if (done + excess > in.size()) { + break; + } + CRYPTO_poly1305_update(&state, in.data() + done, excess); + done += excess; + } + + // Consume the remainder and finish. + CRYPTO_poly1305_update(&state, in.data() + done, in.size() - done); + + // |CRYPTO_poly1305_finish| requires a 16-byte-aligned output. + alignas(16) uint8_t out[16]; + CRYPTO_poly1305_finish(&state, out); + if (!t->ExpectBytesEqual(mac.data(), mac.size(), out, 16)) { + t->PrintLine("SIMD pattern %u failed.", excess); + return false; + } + + return true; +} + +static bool TestPoly1305(FileTest *t, void *arg) { + std::vector key, in, mac; + if (!t->GetBytes(&key, "Key") || + !t->GetBytes(&in, "Input") || + !t->GetBytes(&mac, "MAC")) { + return false; + } + if (key.size() != 32 || mac.size() != 16) { + t->PrintLine("Invalid test"); + return false; + } + + // Test single-shot operation. + poly1305_state state; + CRYPTO_poly1305_init(&state, key.data()); + CRYPTO_poly1305_update(&state, in.data(), in.size()); + // |CRYPTO_poly1305_finish| requires a 16-byte-aligned output. + alignas(16) uint8_t out[16]; + CRYPTO_poly1305_finish(&state, out); + if (!t->ExpectBytesEqual(out, 16, mac.data(), mac.size())) { + t->PrintLine("Single-shot Poly1305 failed."); + return false; + } + + // Test streaming byte-by-byte. + CRYPTO_poly1305_init(&state, key.data()); + for (size_t i = 0; i < in.size(); i++) { + CRYPTO_poly1305_update(&state, &in[i], 1); + } + CRYPTO_poly1305_finish(&state, out); + if (!t->ExpectBytesEqual(mac.data(), mac.size(), out, 16)) { + t->PrintLine("Streaming Poly1305 failed."); + return false; + } + + // Test SIMD stress patterns. OpenSSL's AVX2 assembly needs a multiple of + // four blocks, so test up to three blocks of excess. + if (!TestSIMD(t, 0, key, in, mac) || + !TestSIMD(t, 16, key, in, mac) || + !TestSIMD(t, 32, key, in, mac) || + !TestSIMD(t, 48, key, in, mac)) { + return false; + } + + return true; +} + +int main(int argc, char **argv) { + CRYPTO_library_init(); + + if (argc != 2) { + fprintf(stderr, "%s \n", argv[0]); + return 1; + } + + return FileTestMain(TestPoly1305, nullptr, argv[1]); +} diff --git a/external/boringssl/crypto/poly1305/poly1305_tests.txt b/external/boringssl/crypto/poly1305/poly1305_tests.txt new file mode 100644 index 0000000000..611007a05f --- /dev/null +++ b/external/boringssl/crypto/poly1305/poly1305_tests.txt @@ -0,0 +1,159 @@ +# RFC 7539, section 2.5.2. + +Key = 85d6be7857556d337f4452fe42d506a80103808afb0db2fd4abff6af4149f51b +Input = "Cryptographic Forum Research Group" +MAC = a8061dc1305136c6c22b8baf0c0127a9 + + +# RFC 7539, section A.3. + +Key = 0000000000000000000000000000000000000000000000000000000000000000 +Input = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +MAC = 00000000000000000000000000000000 + +Key = 0000000000000000000000000000000036e5f6b5c5e06070f0efca96227a863e +Input = 416e79207375626d697373696f6e20746f20746865204945544620696e74656e6465642062792074686520436f6e7472696275746f7220666f72207075626c69636174696f6e20617320616c6c206f722070617274206f6620616e204945544620496e7465726e65742d4472616674206f722052464320616e6420616e792073746174656d656e74206d6164652077697468696e2074686520636f6e74657874206f6620616e204945544620616374697669747920697320636f6e7369646572656420616e20224945544620436f6e747269627574696f6e222e20537563682073746174656d656e747320696e636c756465206f72616c2073746174656d656e747320696e20494554462073657373696f6e732c2061732077656c6c206173207772697474656e20616e6420656c656374726f6e696320636f6d6d756e69636174696f6e73206d61646520617420616e792074696d65206f7220706c6163652c207768696368206172652061646472657373656420746f +MAC = 36e5f6b5c5e06070f0efca96227a863e + +Key = 36e5f6b5c5e06070f0efca96227a863e00000000000000000000000000000000 +Input = 416e79207375626d697373696f6e20746f20746865204945544620696e74656e6465642062792074686520436f6e7472696275746f7220666f72207075626c69636174696f6e20617320616c6c206f722070617274206f6620616e204945544620496e7465726e65742d4472616674206f722052464320616e6420616e792073746174656d656e74206d6164652077697468696e2074686520636f6e74657874206f6620616e204945544620616374697669747920697320636f6e7369646572656420616e20224945544620436f6e747269627574696f6e222e20537563682073746174656d656e747320696e636c756465206f72616c2073746174656d656e747320696e20494554462073657373696f6e732c2061732077656c6c206173207772697474656e20616e6420656c656374726f6e696320636f6d6d756e69636174696f6e73206d61646520617420616e792074696d65206f7220706c6163652c207768696368206172652061646472657373656420746f +MAC = f3477e7cd95417af89a6b8794c310cf0 + +Key = 1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0 +Input = 2754776173206272696c6c69672c20616e642074686520736c6974687920746f7665730a446964206779726520616e642067696d626c6520696e2074686520776162653a0a416c6c206d696d737920776572652074686520626f726f676f7665732c0a416e6420746865206d6f6d65207261746873206f757467726162652e +MAC = 4541669a7eaaee61e708dc7cbcc5eb62 + +Key = 0200000000000000000000000000000000000000000000000000000000000000 +Input = ffffffffffffffffffffffffffffffff +MAC = 03000000000000000000000000000000 + +Key = 02000000000000000000000000000000ffffffffffffffffffffffffffffffff +Input = 02000000000000000000000000000000 +MAC = 03000000000000000000000000000000 + +Key = 0100000000000000000000000000000000000000000000000000000000000000 +Input = fffffffffffffffffffffffffffffffff0ffffffffffffffffffffffffffffff11000000000000000000000000000000 +MAC = 05000000000000000000000000000000 + +Key = 0100000000000000000000000000000000000000000000000000000000000000 +Input = fffffffffffffffffffffffffffffffffbfefefefefefefefefefefefefefefe01010101010101010101010101010101 +MAC = 00000000000000000000000000000000 + +Key = 0200000000000000000000000000000000000000000000000000000000000000 +Input = fdffffffffffffffffffffffffffffff +MAC = faffffffffffffffffffffffffffffff + +Key = 0100000000000000040000000000000000000000000000000000000000000000 +Input = e33594d7505e43b900000000000000003394d7505e4379cd01000000000000000000000000000000000000000000000001000000000000000000000000000000 +MAC = 14000000000000005500000000000000 + +Key = 0100000000000000040000000000000000000000000000000000000000000000 +Input = e33594d7505e43b900000000000000003394d7505e4379cd010000000000000000000000000000000000000000000000 +MAC = 13000000000000000000000000000000 + + +# Additional test vectors that are long enough to ensure OpenSSL's SIMD +# assembly is fully tested. + +# Length 2048. +Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f +Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfed +MAC = 69d28f73dd09d39a92aa179da354b7ea + +# Length 2049. +Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f +Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc8 +MAC = d6a26654b88572e875d9661c83471c1b + +# Length 2050. +Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f +Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852 +MAC = 9fbbb7f7adcd0cd5b46a4a520b22499a + +# Length 2051. +Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f +Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f5 +MAC = eb7cdceb97ade2a07622f8f5a4b1ce15 + +# Length 2052. +Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f +Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f590 +MAC = d41c310927cd92e14784ea78b85503db + +# Length 2053. +Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f +Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073 +MAC = 16af133c423f783a14c49d9f526384cf + +# Length 2054. +Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f +Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073f4 +MAC = 00c75db8f0636b22f195645b03091f5f + +# Length 2055. +Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f +Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073f434 +MAC = 4a532bc740f581555831345f3b75bf33 + +# Length 2056. +Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f +Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073f4347a +MAC = 698c7d32c5923871d124a2479e521706 + +# Length 2057. +Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f +Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073f4347a8c +MAC = a677187dbf3c927aeeafb9ebce0f61dc + +# Length 2058. +Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f +Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073f4347a8c8a +MAC = 201fed7eee981b31d2cc42ff6c38141a + +# Length 2059. +Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f +Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073f4347a8c8a28 +MAC = 0c3d3d01a37f347c4f7c5826bcafb3e1 + +# Length 2060. +Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f +Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073f4347a8c8a28c9 +MAC = 33a4e0e0bed7c84c5cc5dd4784410f07 + +# Length 2061. +Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f +Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073f4347a8c8a28c99e +MAC = 8e41c40a2f8ec58fe594f3a3a2de4ae1 + +# Length 2062. +Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f +Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073f4347a8c8a28c99e21 +MAC = c6e5d1810fd878ac6b844c66cef36a22 + +# Length 2063. +Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f +Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073f4347a8c8a28c99e21df +MAC = f6eaae369c3cb5c05748e8d919178e00 + +# Regression test for https://rt.openssl.org/Ticket/Display.html?id=4439 +Key = 2d773be37adb1e4d683bf0075e79c4ee037918535a7f99ccb7040fb5f5f43aea +Input = 89dab80b7717c1db5db437860a3f70218e93e1b8f461fb677f16f35f6f87e2a91c99bc3a47ace47640cc95c345be5ecca5a3523c35cc01893af0b64a620334270372ec12482d1b1e363561698a578b359803495bb4e2ef1930b17a5190b580f141300df30adbeca28f6427a8bc1a999fd51c554a017d095d8c3e3127daf9f595 +MAC = c85d15ed44c378d6b00e23064c7bcd51 + +# Regression tests for https://rt.openssl.org/Ticket/Display.html?id=4483 + +Key = 7f1b02640000000000000000000000000000000000000000cccccccccccccccc +Input = cccccccccccccccccccccccccccccccccccccccccccccccccc80ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccceccccccccccccccccccccccccccccccccccccc5cccccccccccccccccccccccccccccccccccccccccce3ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccaccccccccccccccccccccce6cccccccccc000000afccccccccccccccccccfffffff5000000000000000000000000000000000000000000000000000000ffffffe70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000719205a8521dfc +MAC = 8559b876eceed66eb37798c0457baff9 + +Key = e00016000000000000000000000000000000aaaaaaaaaaaaaaaaaaaaaaaaaaaa +Input = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa000000000000000000800264 +MAC = 00bd1258978e205444c9aaaa82006fed + +Key = 0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c +Input = 02fc +MAC = 06120c0c0c0c0c0c0c0c0c0c0c0c0c0c + +Key = 00ff000000000000000000000000000000000000001e00000000000000007b7b +Input = 7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7a7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b5c7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b6e7b007b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7a7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b5c7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b6e7b001300000000b300000000000000000000000000000000000000000000f20000000000000000000000000000000000002000efff0009000000000000000000000000100000000009000000640000000000000000000000001300000000b300000000000000000000000000000000000000000000f20000000000000000000000000000000000002000efff00090000000000000000007a000010000000000900000064000000000000000000000000000000000000000000000000fc +MAC = 33205bbf9e9f8f7212ab9e2ab9b7e4a5 diff --git a/external/boringssl/crypto/poly1305/poly1305_vec.c b/external/boringssl/crypto/poly1305/poly1305_vec.c new file mode 100644 index 0000000000..3045a2f1b7 --- /dev/null +++ b/external/boringssl/crypto/poly1305/poly1305_vec.c @@ -0,0 +1,890 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +/* This implementation of poly1305 is by Andrew Moon + * (https://github.com/floodyberry/poly1305-donna) and released as public + * domain. It implements SIMD vectorization based on the algorithm described in + * http://cr.yp.to/papers.html#neoncrypto. Unrolled to 2 powers, i.e. 64 byte + * block size */ + +#include + +#include "../internal.h" + + +#if !defined(OPENSSL_WINDOWS) && defined(OPENSSL_X86_64) + +#include + +#define U8TO64_LE(m) (*(const uint64_t *)(m)) +#define U8TO32_LE(m) (*(const uint32_t *)(m)) +#define U64TO8_LE(m, v) (*(uint64_t *)(m)) = v + +typedef __m128i xmmi; + +static const alignas(16) uint32_t poly1305_x64_sse2_message_mask[4] = { + (1 << 26) - 1, 0, (1 << 26) - 1, 0}; +static const alignas(16) uint32_t poly1305_x64_sse2_5[4] = {5, 0, 5, 0}; +static const alignas(16) uint32_t poly1305_x64_sse2_1shl128[4] = { + (1 << 24), 0, (1 << 24), 0}; + +static inline uint128_t add128(uint128_t a, uint128_t b) { return a + b; } + +static inline uint128_t add128_64(uint128_t a, uint64_t b) { return a + b; } + +static inline uint128_t mul64x64_128(uint64_t a, uint64_t b) { + return (uint128_t)a * b; +} + +static inline uint64_t lo128(uint128_t a) { return (uint64_t)a; } + +static inline uint64_t shr128(uint128_t v, const int shift) { + return (uint64_t)(v >> shift); +} + +static inline uint64_t shr128_pair(uint64_t hi, uint64_t lo, const int shift) { + return (uint64_t)((((uint128_t)hi << 64) | lo) >> shift); +} + +typedef struct poly1305_power_t { + union { + xmmi v; + uint64_t u[2]; + uint32_t d[4]; + } R20, R21, R22, R23, R24, S21, S22, S23, S24; +} poly1305_power; + +typedef struct poly1305_state_internal_t { + poly1305_power P[2]; /* 288 bytes, top 32 bit halves unused = 144 + bytes of free storage */ + union { + xmmi H[5]; /* 80 bytes */ + uint64_t HH[10]; + }; + /* uint64_t r0,r1,r2; [24 bytes] */ + /* uint64_t pad0,pad1; [16 bytes] */ + uint64_t started; /* 8 bytes */ + uint64_t leftover; /* 8 bytes */ + uint8_t buffer[64]; /* 64 bytes */ +} poly1305_state_internal; /* 448 bytes total + 63 bytes for + alignment = 511 bytes raw */ + +static inline poly1305_state_internal *poly1305_aligned_state( + poly1305_state *state) { + return (poly1305_state_internal *)(((uint64_t)state + 63) & ~63); +} + +/* copy 0-63 bytes */ +static inline void +poly1305_block_copy(uint8_t *dst, const uint8_t *src, size_t bytes) { + size_t offset = src - dst; + if (bytes & 32) { + _mm_storeu_si128((xmmi *)(dst + 0), + _mm_loadu_si128((const xmmi *)(dst + offset + 0))); + _mm_storeu_si128((xmmi *)(dst + 16), + _mm_loadu_si128((const xmmi *)(dst + offset + 16))); + dst += 32; + } + if (bytes & 16) { + _mm_storeu_si128((xmmi *)dst, _mm_loadu_si128((const xmmi *)(dst + offset))); + dst += 16; + } + if (bytes & 8) { + *(uint64_t *)dst = *(const uint64_t *)(dst + offset); + dst += 8; + } + if (bytes & 4) { + *(uint32_t *)dst = *(const uint32_t *)(dst + offset); + dst += 4; + } + if (bytes & 2) { + *(uint16_t *)dst = *(uint16_t *)(dst + offset); + dst += 2; + } + if (bytes & 1) { + *(uint8_t *)dst = *(uint8_t *)(dst + offset); + } +} + +/* zero 0-15 bytes */ +static inline void poly1305_block_zero(uint8_t *dst, size_t bytes) { + if (bytes & 8) { + *(uint64_t *)dst = 0; + dst += 8; + } + if (bytes & 4) { + *(uint32_t *)dst = 0; + dst += 4; + } + if (bytes & 2) { + *(uint16_t *)dst = 0; + dst += 2; + } + if (bytes & 1) { + *(uint8_t *)dst = 0; + } +} + +static inline size_t poly1305_min(size_t a, size_t b) { + return (a < b) ? a : b; +} + +void CRYPTO_poly1305_init(poly1305_state *state, const uint8_t key[32]) { + poly1305_state_internal *st = poly1305_aligned_state(state); + poly1305_power *p; + uint64_t r0, r1, r2; + uint64_t t0, t1; + + /* clamp key */ + t0 = U8TO64_LE(key + 0); + t1 = U8TO64_LE(key + 8); + r0 = t0 & 0xffc0fffffff; + t0 >>= 44; + t0 |= t1 << 20; + r1 = t0 & 0xfffffc0ffff; + t1 >>= 24; + r2 = t1 & 0x00ffffffc0f; + + /* store r in un-used space of st->P[1] */ + p = &st->P[1]; + p->R20.d[1] = (uint32_t)(r0); + p->R20.d[3] = (uint32_t)(r0 >> 32); + p->R21.d[1] = (uint32_t)(r1); + p->R21.d[3] = (uint32_t)(r1 >> 32); + p->R22.d[1] = (uint32_t)(r2); + p->R22.d[3] = (uint32_t)(r2 >> 32); + + /* store pad */ + p->R23.d[1] = U8TO32_LE(key + 16); + p->R23.d[3] = U8TO32_LE(key + 20); + p->R24.d[1] = U8TO32_LE(key + 24); + p->R24.d[3] = U8TO32_LE(key + 28); + + /* H = 0 */ + st->H[0] = _mm_setzero_si128(); + st->H[1] = _mm_setzero_si128(); + st->H[2] = _mm_setzero_si128(); + st->H[3] = _mm_setzero_si128(); + st->H[4] = _mm_setzero_si128(); + + st->started = 0; + st->leftover = 0; +} + +static void poly1305_first_block(poly1305_state_internal *st, + const uint8_t *m) { + const xmmi MMASK = _mm_load_si128((const xmmi *)poly1305_x64_sse2_message_mask); + const xmmi FIVE = _mm_load_si128((const xmmi *)poly1305_x64_sse2_5); + const xmmi HIBIT = _mm_load_si128((const xmmi *)poly1305_x64_sse2_1shl128); + xmmi T5, T6; + poly1305_power *p; + uint128_t d[3]; + uint64_t r0, r1, r2; + uint64_t r20, r21, r22, s22; + uint64_t pad0, pad1; + uint64_t c; + uint64_t i; + + /* pull out stored info */ + p = &st->P[1]; + + r0 = ((uint64_t)p->R20.d[3] << 32) | (uint64_t)p->R20.d[1]; + r1 = ((uint64_t)p->R21.d[3] << 32) | (uint64_t)p->R21.d[1]; + r2 = ((uint64_t)p->R22.d[3] << 32) | (uint64_t)p->R22.d[1]; + pad0 = ((uint64_t)p->R23.d[3] << 32) | (uint64_t)p->R23.d[1]; + pad1 = ((uint64_t)p->R24.d[3] << 32) | (uint64_t)p->R24.d[1]; + + /* compute powers r^2,r^4 */ + r20 = r0; + r21 = r1; + r22 = r2; + for (i = 0; i < 2; i++) { + s22 = r22 * (5 << 2); + + d[0] = add128(mul64x64_128(r20, r20), mul64x64_128(r21 * 2, s22)); + d[1] = add128(mul64x64_128(r22, s22), mul64x64_128(r20 * 2, r21)); + d[2] = add128(mul64x64_128(r21, r21), mul64x64_128(r22 * 2, r20)); + + r20 = lo128(d[0]) & 0xfffffffffff; + c = shr128(d[0], 44); + d[1] = add128_64(d[1], c); + r21 = lo128(d[1]) & 0xfffffffffff; + c = shr128(d[1], 44); + d[2] = add128_64(d[2], c); + r22 = lo128(d[2]) & 0x3ffffffffff; + c = shr128(d[2], 42); + r20 += c * 5; + c = (r20 >> 44); + r20 = r20 & 0xfffffffffff; + r21 += c; + + p->R20.v = _mm_shuffle_epi32(_mm_cvtsi32_si128((uint32_t)(r20)&0x3ffffff), + _MM_SHUFFLE(1, 0, 1, 0)); + p->R21.v = _mm_shuffle_epi32( + _mm_cvtsi32_si128((uint32_t)((r20 >> 26) | (r21 << 18)) & 0x3ffffff), + _MM_SHUFFLE(1, 0, 1, 0)); + p->R22.v = + _mm_shuffle_epi32(_mm_cvtsi32_si128((uint32_t)((r21 >> 8)) & 0x3ffffff), + _MM_SHUFFLE(1, 0, 1, 0)); + p->R23.v = _mm_shuffle_epi32( + _mm_cvtsi32_si128((uint32_t)((r21 >> 34) | (r22 << 10)) & 0x3ffffff), + _MM_SHUFFLE(1, 0, 1, 0)); + p->R24.v = _mm_shuffle_epi32(_mm_cvtsi32_si128((uint32_t)((r22 >> 16))), + _MM_SHUFFLE(1, 0, 1, 0)); + p->S21.v = _mm_mul_epu32(p->R21.v, FIVE); + p->S22.v = _mm_mul_epu32(p->R22.v, FIVE); + p->S23.v = _mm_mul_epu32(p->R23.v, FIVE); + p->S24.v = _mm_mul_epu32(p->R24.v, FIVE); + p--; + } + + /* put saved info back */ + p = &st->P[1]; + p->R20.d[1] = (uint32_t)(r0); + p->R20.d[3] = (uint32_t)(r0 >> 32); + p->R21.d[1] = (uint32_t)(r1); + p->R21.d[3] = (uint32_t)(r1 >> 32); + p->R22.d[1] = (uint32_t)(r2); + p->R22.d[3] = (uint32_t)(r2 >> 32); + p->R23.d[1] = (uint32_t)(pad0); + p->R23.d[3] = (uint32_t)(pad0 >> 32); + p->R24.d[1] = (uint32_t)(pad1); + p->R24.d[3] = (uint32_t)(pad1 >> 32); + + /* H = [Mx,My] */ + T5 = _mm_unpacklo_epi64(_mm_loadl_epi64((const xmmi *)(m + 0)), + _mm_loadl_epi64((const xmmi *)(m + 16))); + T6 = _mm_unpacklo_epi64(_mm_loadl_epi64((const xmmi *)(m + 8)), + _mm_loadl_epi64((const xmmi *)(m + 24))); + st->H[0] = _mm_and_si128(MMASK, T5); + st->H[1] = _mm_and_si128(MMASK, _mm_srli_epi64(T5, 26)); + T5 = _mm_or_si128(_mm_srli_epi64(T5, 52), _mm_slli_epi64(T6, 12)); + st->H[2] = _mm_and_si128(MMASK, T5); + st->H[3] = _mm_and_si128(MMASK, _mm_srli_epi64(T5, 26)); + st->H[4] = _mm_or_si128(_mm_srli_epi64(T6, 40), HIBIT); +} + +static void poly1305_blocks(poly1305_state_internal *st, const uint8_t *m, + size_t bytes) { + const xmmi MMASK = _mm_load_si128((const xmmi *)poly1305_x64_sse2_message_mask); + const xmmi FIVE = _mm_load_si128((const xmmi *)poly1305_x64_sse2_5); + const xmmi HIBIT = _mm_load_si128((const xmmi *)poly1305_x64_sse2_1shl128); + + poly1305_power *p; + xmmi H0, H1, H2, H3, H4; + xmmi T0, T1, T2, T3, T4, T5, T6; + xmmi M0, M1, M2, M3, M4; + xmmi C1, C2; + + H0 = st->H[0]; + H1 = st->H[1]; + H2 = st->H[2]; + H3 = st->H[3]; + H4 = st->H[4]; + + while (bytes >= 64) { + /* H *= [r^4,r^4] */ + p = &st->P[0]; + T0 = _mm_mul_epu32(H0, p->R20.v); + T1 = _mm_mul_epu32(H0, p->R21.v); + T2 = _mm_mul_epu32(H0, p->R22.v); + T3 = _mm_mul_epu32(H0, p->R23.v); + T4 = _mm_mul_epu32(H0, p->R24.v); + T5 = _mm_mul_epu32(H1, p->S24.v); + T6 = _mm_mul_epu32(H1, p->R20.v); + T0 = _mm_add_epi64(T0, T5); + T1 = _mm_add_epi64(T1, T6); + T5 = _mm_mul_epu32(H2, p->S23.v); + T6 = _mm_mul_epu32(H2, p->S24.v); + T0 = _mm_add_epi64(T0, T5); + T1 = _mm_add_epi64(T1, T6); + T5 = _mm_mul_epu32(H3, p->S22.v); + T6 = _mm_mul_epu32(H3, p->S23.v); + T0 = _mm_add_epi64(T0, T5); + T1 = _mm_add_epi64(T1, T6); + T5 = _mm_mul_epu32(H4, p->S21.v); + T6 = _mm_mul_epu32(H4, p->S22.v); + T0 = _mm_add_epi64(T0, T5); + T1 = _mm_add_epi64(T1, T6); + T5 = _mm_mul_epu32(H1, p->R21.v); + T6 = _mm_mul_epu32(H1, p->R22.v); + T2 = _mm_add_epi64(T2, T5); + T3 = _mm_add_epi64(T3, T6); + T5 = _mm_mul_epu32(H2, p->R20.v); + T6 = _mm_mul_epu32(H2, p->R21.v); + T2 = _mm_add_epi64(T2, T5); + T3 = _mm_add_epi64(T3, T6); + T5 = _mm_mul_epu32(H3, p->S24.v); + T6 = _mm_mul_epu32(H3, p->R20.v); + T2 = _mm_add_epi64(T2, T5); + T3 = _mm_add_epi64(T3, T6); + T5 = _mm_mul_epu32(H4, p->S23.v); + T6 = _mm_mul_epu32(H4, p->S24.v); + T2 = _mm_add_epi64(T2, T5); + T3 = _mm_add_epi64(T3, T6); + T5 = _mm_mul_epu32(H1, p->R23.v); + T4 = _mm_add_epi64(T4, T5); + T5 = _mm_mul_epu32(H2, p->R22.v); + T4 = _mm_add_epi64(T4, T5); + T5 = _mm_mul_epu32(H3, p->R21.v); + T4 = _mm_add_epi64(T4, T5); + T5 = _mm_mul_epu32(H4, p->R20.v); + T4 = _mm_add_epi64(T4, T5); + + /* H += [Mx,My]*[r^2,r^2] */ + T5 = _mm_unpacklo_epi64(_mm_loadl_epi64((const xmmi *)(m + 0)), + _mm_loadl_epi64((const xmmi *)(m + 16))); + T6 = _mm_unpacklo_epi64(_mm_loadl_epi64((const xmmi *)(m + 8)), + _mm_loadl_epi64((const xmmi *)(m + 24))); + M0 = _mm_and_si128(MMASK, T5); + M1 = _mm_and_si128(MMASK, _mm_srli_epi64(T5, 26)); + T5 = _mm_or_si128(_mm_srli_epi64(T5, 52), _mm_slli_epi64(T6, 12)); + M2 = _mm_and_si128(MMASK, T5); + M3 = _mm_and_si128(MMASK, _mm_srli_epi64(T5, 26)); + M4 = _mm_or_si128(_mm_srli_epi64(T6, 40), HIBIT); + + p = &st->P[1]; + T5 = _mm_mul_epu32(M0, p->R20.v); + T6 = _mm_mul_epu32(M0, p->R21.v); + T0 = _mm_add_epi64(T0, T5); + T1 = _mm_add_epi64(T1, T6); + T5 = _mm_mul_epu32(M1, p->S24.v); + T6 = _mm_mul_epu32(M1, p->R20.v); + T0 = _mm_add_epi64(T0, T5); + T1 = _mm_add_epi64(T1, T6); + T5 = _mm_mul_epu32(M2, p->S23.v); + T6 = _mm_mul_epu32(M2, p->S24.v); + T0 = _mm_add_epi64(T0, T5); + T1 = _mm_add_epi64(T1, T6); + T5 = _mm_mul_epu32(M3, p->S22.v); + T6 = _mm_mul_epu32(M3, p->S23.v); + T0 = _mm_add_epi64(T0, T5); + T1 = _mm_add_epi64(T1, T6); + T5 = _mm_mul_epu32(M4, p->S21.v); + T6 = _mm_mul_epu32(M4, p->S22.v); + T0 = _mm_add_epi64(T0, T5); + T1 = _mm_add_epi64(T1, T6); + T5 = _mm_mul_epu32(M0, p->R22.v); + T6 = _mm_mul_epu32(M0, p->R23.v); + T2 = _mm_add_epi64(T2, T5); + T3 = _mm_add_epi64(T3, T6); + T5 = _mm_mul_epu32(M1, p->R21.v); + T6 = _mm_mul_epu32(M1, p->R22.v); + T2 = _mm_add_epi64(T2, T5); + T3 = _mm_add_epi64(T3, T6); + T5 = _mm_mul_epu32(M2, p->R20.v); + T6 = _mm_mul_epu32(M2, p->R21.v); + T2 = _mm_add_epi64(T2, T5); + T3 = _mm_add_epi64(T3, T6); + T5 = _mm_mul_epu32(M3, p->S24.v); + T6 = _mm_mul_epu32(M3, p->R20.v); + T2 = _mm_add_epi64(T2, T5); + T3 = _mm_add_epi64(T3, T6); + T5 = _mm_mul_epu32(M4, p->S23.v); + T6 = _mm_mul_epu32(M4, p->S24.v); + T2 = _mm_add_epi64(T2, T5); + T3 = _mm_add_epi64(T3, T6); + T5 = _mm_mul_epu32(M0, p->R24.v); + T4 = _mm_add_epi64(T4, T5); + T5 = _mm_mul_epu32(M1, p->R23.v); + T4 = _mm_add_epi64(T4, T5); + T5 = _mm_mul_epu32(M2, p->R22.v); + T4 = _mm_add_epi64(T4, T5); + T5 = _mm_mul_epu32(M3, p->R21.v); + T4 = _mm_add_epi64(T4, T5); + T5 = _mm_mul_epu32(M4, p->R20.v); + T4 = _mm_add_epi64(T4, T5); + + /* H += [Mx,My] */ + T5 = _mm_unpacklo_epi64(_mm_loadl_epi64((const xmmi *)(m + 32)), + _mm_loadl_epi64((const xmmi *)(m + 48))); + T6 = _mm_unpacklo_epi64(_mm_loadl_epi64((const xmmi *)(m + 40)), + _mm_loadl_epi64((const xmmi *)(m + 56))); + M0 = _mm_and_si128(MMASK, T5); + M1 = _mm_and_si128(MMASK, _mm_srli_epi64(T5, 26)); + T5 = _mm_or_si128(_mm_srli_epi64(T5, 52), _mm_slli_epi64(T6, 12)); + M2 = _mm_and_si128(MMASK, T5); + M3 = _mm_and_si128(MMASK, _mm_srli_epi64(T5, 26)); + M4 = _mm_or_si128(_mm_srli_epi64(T6, 40), HIBIT); + + T0 = _mm_add_epi64(T0, M0); + T1 = _mm_add_epi64(T1, M1); + T2 = _mm_add_epi64(T2, M2); + T3 = _mm_add_epi64(T3, M3); + T4 = _mm_add_epi64(T4, M4); + + /* reduce */ + C1 = _mm_srli_epi64(T0, 26); + C2 = _mm_srli_epi64(T3, 26); + T0 = _mm_and_si128(T0, MMASK); + T3 = _mm_and_si128(T3, MMASK); + T1 = _mm_add_epi64(T1, C1); + T4 = _mm_add_epi64(T4, C2); + C1 = _mm_srli_epi64(T1, 26); + C2 = _mm_srli_epi64(T4, 26); + T1 = _mm_and_si128(T1, MMASK); + T4 = _mm_and_si128(T4, MMASK); + T2 = _mm_add_epi64(T2, C1); + T0 = _mm_add_epi64(T0, _mm_mul_epu32(C2, FIVE)); + C1 = _mm_srli_epi64(T2, 26); + C2 = _mm_srli_epi64(T0, 26); + T2 = _mm_and_si128(T2, MMASK); + T0 = _mm_and_si128(T0, MMASK); + T3 = _mm_add_epi64(T3, C1); + T1 = _mm_add_epi64(T1, C2); + C1 = _mm_srli_epi64(T3, 26); + T3 = _mm_and_si128(T3, MMASK); + T4 = _mm_add_epi64(T4, C1); + + /* H = (H*[r^4,r^4] + [Mx,My]*[r^2,r^2] + [Mx,My]) */ + H0 = T0; + H1 = T1; + H2 = T2; + H3 = T3; + H4 = T4; + + m += 64; + bytes -= 64; + } + + st->H[0] = H0; + st->H[1] = H1; + st->H[2] = H2; + st->H[3] = H3; + st->H[4] = H4; +} + +static size_t poly1305_combine(poly1305_state_internal *st, const uint8_t *m, + size_t bytes) { + const xmmi MMASK = _mm_load_si128((const xmmi *)poly1305_x64_sse2_message_mask); + const xmmi HIBIT = _mm_load_si128((const xmmi *)poly1305_x64_sse2_1shl128); + const xmmi FIVE = _mm_load_si128((const xmmi *)poly1305_x64_sse2_5); + + poly1305_power *p; + xmmi H0, H1, H2, H3, H4; + xmmi M0, M1, M2, M3, M4; + xmmi T0, T1, T2, T3, T4, T5, T6; + xmmi C1, C2; + + uint64_t r0, r1, r2; + uint64_t t0, t1, t2, t3, t4; + uint64_t c; + size_t consumed = 0; + + H0 = st->H[0]; + H1 = st->H[1]; + H2 = st->H[2]; + H3 = st->H[3]; + H4 = st->H[4]; + + /* p = [r^2,r^2] */ + p = &st->P[1]; + + if (bytes >= 32) { + /* H *= [r^2,r^2] */ + T0 = _mm_mul_epu32(H0, p->R20.v); + T1 = _mm_mul_epu32(H0, p->R21.v); + T2 = _mm_mul_epu32(H0, p->R22.v); + T3 = _mm_mul_epu32(H0, p->R23.v); + T4 = _mm_mul_epu32(H0, p->R24.v); + T5 = _mm_mul_epu32(H1, p->S24.v); + T6 = _mm_mul_epu32(H1, p->R20.v); + T0 = _mm_add_epi64(T0, T5); + T1 = _mm_add_epi64(T1, T6); + T5 = _mm_mul_epu32(H2, p->S23.v); + T6 = _mm_mul_epu32(H2, p->S24.v); + T0 = _mm_add_epi64(T0, T5); + T1 = _mm_add_epi64(T1, T6); + T5 = _mm_mul_epu32(H3, p->S22.v); + T6 = _mm_mul_epu32(H3, p->S23.v); + T0 = _mm_add_epi64(T0, T5); + T1 = _mm_add_epi64(T1, T6); + T5 = _mm_mul_epu32(H4, p->S21.v); + T6 = _mm_mul_epu32(H4, p->S22.v); + T0 = _mm_add_epi64(T0, T5); + T1 = _mm_add_epi64(T1, T6); + T5 = _mm_mul_epu32(H1, p->R21.v); + T6 = _mm_mul_epu32(H1, p->R22.v); + T2 = _mm_add_epi64(T2, T5); + T3 = _mm_add_epi64(T3, T6); + T5 = _mm_mul_epu32(H2, p->R20.v); + T6 = _mm_mul_epu32(H2, p->R21.v); + T2 = _mm_add_epi64(T2, T5); + T3 = _mm_add_epi64(T3, T6); + T5 = _mm_mul_epu32(H3, p->S24.v); + T6 = _mm_mul_epu32(H3, p->R20.v); + T2 = _mm_add_epi64(T2, T5); + T3 = _mm_add_epi64(T3, T6); + T5 = _mm_mul_epu32(H4, p->S23.v); + T6 = _mm_mul_epu32(H4, p->S24.v); + T2 = _mm_add_epi64(T2, T5); + T3 = _mm_add_epi64(T3, T6); + T5 = _mm_mul_epu32(H1, p->R23.v); + T4 = _mm_add_epi64(T4, T5); + T5 = _mm_mul_epu32(H2, p->R22.v); + T4 = _mm_add_epi64(T4, T5); + T5 = _mm_mul_epu32(H3, p->R21.v); + T4 = _mm_add_epi64(T4, T5); + T5 = _mm_mul_epu32(H4, p->R20.v); + T4 = _mm_add_epi64(T4, T5); + + /* H += [Mx,My] */ + T5 = _mm_unpacklo_epi64(_mm_loadl_epi64((const xmmi *)(m + 0)), + _mm_loadl_epi64((const xmmi *)(m + 16))); + T6 = _mm_unpacklo_epi64(_mm_loadl_epi64((const xmmi *)(m + 8)), + _mm_loadl_epi64((const xmmi *)(m + 24))); + M0 = _mm_and_si128(MMASK, T5); + M1 = _mm_and_si128(MMASK, _mm_srli_epi64(T5, 26)); + T5 = _mm_or_si128(_mm_srli_epi64(T5, 52), _mm_slli_epi64(T6, 12)); + M2 = _mm_and_si128(MMASK, T5); + M3 = _mm_and_si128(MMASK, _mm_srli_epi64(T5, 26)); + M4 = _mm_or_si128(_mm_srli_epi64(T6, 40), HIBIT); + + T0 = _mm_add_epi64(T0, M0); + T1 = _mm_add_epi64(T1, M1); + T2 = _mm_add_epi64(T2, M2); + T3 = _mm_add_epi64(T3, M3); + T4 = _mm_add_epi64(T4, M4); + + /* reduce */ + C1 = _mm_srli_epi64(T0, 26); + C2 = _mm_srli_epi64(T3, 26); + T0 = _mm_and_si128(T0, MMASK); + T3 = _mm_and_si128(T3, MMASK); + T1 = _mm_add_epi64(T1, C1); + T4 = _mm_add_epi64(T4, C2); + C1 = _mm_srli_epi64(T1, 26); + C2 = _mm_srli_epi64(T4, 26); + T1 = _mm_and_si128(T1, MMASK); + T4 = _mm_and_si128(T4, MMASK); + T2 = _mm_add_epi64(T2, C1); + T0 = _mm_add_epi64(T0, _mm_mul_epu32(C2, FIVE)); + C1 = _mm_srli_epi64(T2, 26); + C2 = _mm_srli_epi64(T0, 26); + T2 = _mm_and_si128(T2, MMASK); + T0 = _mm_and_si128(T0, MMASK); + T3 = _mm_add_epi64(T3, C1); + T1 = _mm_add_epi64(T1, C2); + C1 = _mm_srli_epi64(T3, 26); + T3 = _mm_and_si128(T3, MMASK); + T4 = _mm_add_epi64(T4, C1); + + /* H = (H*[r^2,r^2] + [Mx,My]) */ + H0 = T0; + H1 = T1; + H2 = T2; + H3 = T3; + H4 = T4; + + consumed = 32; + } + + /* finalize, H *= [r^2,r] */ + r0 = ((uint64_t)p->R20.d[3] << 32) | (uint64_t)p->R20.d[1]; + r1 = ((uint64_t)p->R21.d[3] << 32) | (uint64_t)p->R21.d[1]; + r2 = ((uint64_t)p->R22.d[3] << 32) | (uint64_t)p->R22.d[1]; + + p->R20.d[2] = (uint32_t)(r0)&0x3ffffff; + p->R21.d[2] = (uint32_t)((r0 >> 26) | (r1 << 18)) & 0x3ffffff; + p->R22.d[2] = (uint32_t)((r1 >> 8)) & 0x3ffffff; + p->R23.d[2] = (uint32_t)((r1 >> 34) | (r2 << 10)) & 0x3ffffff; + p->R24.d[2] = (uint32_t)((r2 >> 16)); + p->S21.d[2] = p->R21.d[2] * 5; + p->S22.d[2] = p->R22.d[2] * 5; + p->S23.d[2] = p->R23.d[2] * 5; + p->S24.d[2] = p->R24.d[2] * 5; + + /* H *= [r^2,r] */ + T0 = _mm_mul_epu32(H0, p->R20.v); + T1 = _mm_mul_epu32(H0, p->R21.v); + T2 = _mm_mul_epu32(H0, p->R22.v); + T3 = _mm_mul_epu32(H0, p->R23.v); + T4 = _mm_mul_epu32(H0, p->R24.v); + T5 = _mm_mul_epu32(H1, p->S24.v); + T6 = _mm_mul_epu32(H1, p->R20.v); + T0 = _mm_add_epi64(T0, T5); + T1 = _mm_add_epi64(T1, T6); + T5 = _mm_mul_epu32(H2, p->S23.v); + T6 = _mm_mul_epu32(H2, p->S24.v); + T0 = _mm_add_epi64(T0, T5); + T1 = _mm_add_epi64(T1, T6); + T5 = _mm_mul_epu32(H3, p->S22.v); + T6 = _mm_mul_epu32(H3, p->S23.v); + T0 = _mm_add_epi64(T0, T5); + T1 = _mm_add_epi64(T1, T6); + T5 = _mm_mul_epu32(H4, p->S21.v); + T6 = _mm_mul_epu32(H4, p->S22.v); + T0 = _mm_add_epi64(T0, T5); + T1 = _mm_add_epi64(T1, T6); + T5 = _mm_mul_epu32(H1, p->R21.v); + T6 = _mm_mul_epu32(H1, p->R22.v); + T2 = _mm_add_epi64(T2, T5); + T3 = _mm_add_epi64(T3, T6); + T5 = _mm_mul_epu32(H2, p->R20.v); + T6 = _mm_mul_epu32(H2, p->R21.v); + T2 = _mm_add_epi64(T2, T5); + T3 = _mm_add_epi64(T3, T6); + T5 = _mm_mul_epu32(H3, p->S24.v); + T6 = _mm_mul_epu32(H3, p->R20.v); + T2 = _mm_add_epi64(T2, T5); + T3 = _mm_add_epi64(T3, T6); + T5 = _mm_mul_epu32(H4, p->S23.v); + T6 = _mm_mul_epu32(H4, p->S24.v); + T2 = _mm_add_epi64(T2, T5); + T3 = _mm_add_epi64(T3, T6); + T5 = _mm_mul_epu32(H1, p->R23.v); + T4 = _mm_add_epi64(T4, T5); + T5 = _mm_mul_epu32(H2, p->R22.v); + T4 = _mm_add_epi64(T4, T5); + T5 = _mm_mul_epu32(H3, p->R21.v); + T4 = _mm_add_epi64(T4, T5); + T5 = _mm_mul_epu32(H4, p->R20.v); + T4 = _mm_add_epi64(T4, T5); + + C1 = _mm_srli_epi64(T0, 26); + C2 = _mm_srli_epi64(T3, 26); + T0 = _mm_and_si128(T0, MMASK); + T3 = _mm_and_si128(T3, MMASK); + T1 = _mm_add_epi64(T1, C1); + T4 = _mm_add_epi64(T4, C2); + C1 = _mm_srli_epi64(T1, 26); + C2 = _mm_srli_epi64(T4, 26); + T1 = _mm_and_si128(T1, MMASK); + T4 = _mm_and_si128(T4, MMASK); + T2 = _mm_add_epi64(T2, C1); + T0 = _mm_add_epi64(T0, _mm_mul_epu32(C2, FIVE)); + C1 = _mm_srli_epi64(T2, 26); + C2 = _mm_srli_epi64(T0, 26); + T2 = _mm_and_si128(T2, MMASK); + T0 = _mm_and_si128(T0, MMASK); + T3 = _mm_add_epi64(T3, C1); + T1 = _mm_add_epi64(T1, C2); + C1 = _mm_srli_epi64(T3, 26); + T3 = _mm_and_si128(T3, MMASK); + T4 = _mm_add_epi64(T4, C1); + + /* H = H[0]+H[1] */ + H0 = _mm_add_epi64(T0, _mm_srli_si128(T0, 8)); + H1 = _mm_add_epi64(T1, _mm_srli_si128(T1, 8)); + H2 = _mm_add_epi64(T2, _mm_srli_si128(T2, 8)); + H3 = _mm_add_epi64(T3, _mm_srli_si128(T3, 8)); + H4 = _mm_add_epi64(T4, _mm_srli_si128(T4, 8)); + + t0 = _mm_cvtsi128_si32(H0); + c = (t0 >> 26); + t0 &= 0x3ffffff; + t1 = _mm_cvtsi128_si32(H1) + c; + c = (t1 >> 26); + t1 &= 0x3ffffff; + t2 = _mm_cvtsi128_si32(H2) + c; + c = (t2 >> 26); + t2 &= 0x3ffffff; + t3 = _mm_cvtsi128_si32(H3) + c; + c = (t3 >> 26); + t3 &= 0x3ffffff; + t4 = _mm_cvtsi128_si32(H4) + c; + c = (t4 >> 26); + t4 &= 0x3ffffff; + t0 = t0 + (c * 5); + c = (t0 >> 26); + t0 &= 0x3ffffff; + t1 = t1 + c; + + st->HH[0] = ((t0) | (t1 << 26)) & UINT64_C(0xfffffffffff); + st->HH[1] = ((t1 >> 18) | (t2 << 8) | (t3 << 34)) & UINT64_C(0xfffffffffff); + st->HH[2] = ((t3 >> 10) | (t4 << 16)) & UINT64_C(0x3ffffffffff); + + return consumed; +} + +void CRYPTO_poly1305_update(poly1305_state *state, const uint8_t *m, + size_t bytes) { + poly1305_state_internal *st = poly1305_aligned_state(state); + size_t want; + + /* need at least 32 initial bytes to start the accelerated branch */ + if (!st->started) { + if ((st->leftover == 0) && (bytes > 32)) { + poly1305_first_block(st, m); + m += 32; + bytes -= 32; + } else { + want = poly1305_min(32 - st->leftover, bytes); + poly1305_block_copy(st->buffer + st->leftover, m, want); + bytes -= want; + m += want; + st->leftover += want; + if ((st->leftover < 32) || (bytes == 0)) { + return; + } + poly1305_first_block(st, st->buffer); + st->leftover = 0; + } + st->started = 1; + } + + /* handle leftover */ + if (st->leftover) { + want = poly1305_min(64 - st->leftover, bytes); + poly1305_block_copy(st->buffer + st->leftover, m, want); + bytes -= want; + m += want; + st->leftover += want; + if (st->leftover < 64) { + return; + } + poly1305_blocks(st, st->buffer, 64); + st->leftover = 0; + } + + /* process 64 byte blocks */ + if (bytes >= 64) { + want = (bytes & ~63); + poly1305_blocks(st, m, want); + m += want; + bytes -= want; + } + + if (bytes) { + poly1305_block_copy(st->buffer + st->leftover, m, bytes); + st->leftover += bytes; + } +} + +void CRYPTO_poly1305_finish(poly1305_state *state, uint8_t mac[16]) { + poly1305_state_internal *st = poly1305_aligned_state(state); + size_t leftover = st->leftover; + uint8_t *m = st->buffer; + uint128_t d[3]; + uint64_t h0, h1, h2; + uint64_t t0, t1; + uint64_t g0, g1, g2, c, nc; + uint64_t r0, r1, r2, s1, s2; + poly1305_power *p; + + if (st->started) { + size_t consumed = poly1305_combine(st, m, leftover); + leftover -= consumed; + m += consumed; + } + + /* st->HH will either be 0 or have the combined result */ + h0 = st->HH[0]; + h1 = st->HH[1]; + h2 = st->HH[2]; + + p = &st->P[1]; + r0 = ((uint64_t)p->R20.d[3] << 32) | (uint64_t)p->R20.d[1]; + r1 = ((uint64_t)p->R21.d[3] << 32) | (uint64_t)p->R21.d[1]; + r2 = ((uint64_t)p->R22.d[3] << 32) | (uint64_t)p->R22.d[1]; + s1 = r1 * (5 << 2); + s2 = r2 * (5 << 2); + + if (leftover < 16) { + goto poly1305_donna_atmost15bytes; + } + +poly1305_donna_atleast16bytes: + t0 = U8TO64_LE(m + 0); + t1 = U8TO64_LE(m + 8); + h0 += t0 & 0xfffffffffff; + t0 = shr128_pair(t1, t0, 44); + h1 += t0 & 0xfffffffffff; + h2 += (t1 >> 24) | ((uint64_t)1 << 40); + +poly1305_donna_mul: + d[0] = add128(add128(mul64x64_128(h0, r0), mul64x64_128(h1, s2)), + mul64x64_128(h2, s1)); + d[1] = add128(add128(mul64x64_128(h0, r1), mul64x64_128(h1, r0)), + mul64x64_128(h2, s2)); + d[2] = add128(add128(mul64x64_128(h0, r2), mul64x64_128(h1, r1)), + mul64x64_128(h2, r0)); + h0 = lo128(d[0]) & 0xfffffffffff; + c = shr128(d[0], 44); + d[1] = add128_64(d[1], c); + h1 = lo128(d[1]) & 0xfffffffffff; + c = shr128(d[1], 44); + d[2] = add128_64(d[2], c); + h2 = lo128(d[2]) & 0x3ffffffffff; + c = shr128(d[2], 42); + h0 += c * 5; + + m += 16; + leftover -= 16; + if (leftover >= 16) { + goto poly1305_donna_atleast16bytes; + } + +/* final bytes */ +poly1305_donna_atmost15bytes: + if (!leftover) { + goto poly1305_donna_finish; + } + + m[leftover++] = 1; + poly1305_block_zero(m + leftover, 16 - leftover); + leftover = 16; + + t0 = U8TO64_LE(m + 0); + t1 = U8TO64_LE(m + 8); + h0 += t0 & 0xfffffffffff; + t0 = shr128_pair(t1, t0, 44); + h1 += t0 & 0xfffffffffff; + h2 += (t1 >> 24); + + goto poly1305_donna_mul; + +poly1305_donna_finish: + c = (h0 >> 44); + h0 &= 0xfffffffffff; + h1 += c; + c = (h1 >> 44); + h1 &= 0xfffffffffff; + h2 += c; + c = (h2 >> 42); + h2 &= 0x3ffffffffff; + h0 += c * 5; + + g0 = h0 + 5; + c = (g0 >> 44); + g0 &= 0xfffffffffff; + g1 = h1 + c; + c = (g1 >> 44); + g1 &= 0xfffffffffff; + g2 = h2 + c - ((uint64_t)1 << 42); + + c = (g2 >> 63) - 1; + nc = ~c; + h0 = (h0 & nc) | (g0 & c); + h1 = (h1 & nc) | (g1 & c); + h2 = (h2 & nc) | (g2 & c); + + /* pad */ + t0 = ((uint64_t)p->R23.d[3] << 32) | (uint64_t)p->R23.d[1]; + t1 = ((uint64_t)p->R24.d[3] << 32) | (uint64_t)p->R24.d[1]; + h0 += (t0 & 0xfffffffffff); + c = (h0 >> 44); + h0 &= 0xfffffffffff; + t0 = shr128_pair(t1, t0, 44); + h1 += (t0 & 0xfffffffffff) + c; + c = (h1 >> 44); + h1 &= 0xfffffffffff; + t1 = (t1 >> 24); + h2 += (t1)+c; + + U64TO8_LE(mac + 0, ((h0) | (h1 << 44))); + U64TO8_LE(mac + 8, ((h1 >> 20) | (h2 << 24))); +} + +#endif /* !OPENSSL_WINDOWS && OPENSSL_X86_64 */ diff --git a/external/boringssl/crypto/rand/CMakeLists.txt b/external/boringssl/crypto/rand/CMakeLists.txt new file mode 100644 index 0000000000..c66d2eeb85 --- /dev/null +++ b/external/boringssl/crypto/rand/CMakeLists.txt @@ -0,0 +1,24 @@ +include_directories(../../include) + +if (${ARCH} STREQUAL "x86_64") + set( + RAND_ARCH_SOURCES + + rdrand-x86_64.${ASM_EXT} + ) +endif() + +add_library( + rand + + OBJECT + + deterministic.c + rand.c + urandom.c + windows.c + + ${RAND_ARCH_SOURCES} +) + +perlasm(rdrand-x86_64.${ASM_EXT} asm/rdrand-x86_64.pl) diff --git a/external/boringssl/crypto/rand/asm/rdrand-x86_64.pl b/external/boringssl/crypto/rand/asm/rdrand-x86_64.pl new file mode 100644 index 0000000000..c32a55c4b9 --- /dev/null +++ b/external/boringssl/crypto/rand/asm/rdrand-x86_64.pl @@ -0,0 +1,75 @@ +#!/usr/bin/env perl + +# Copyright (c) 2015, Google Inc. +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +$flavour = shift; +$output = shift; +if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or +die "can't locate x86_64-xlate.pl"; + +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; + +print<<___; +.text + +# CRYPTO_rdrand writes eight bytes of random data from the hardware RNG to +# |out|. It returns one on success or zero on hardware failure. +# int CRYPTO_rdrand(uint8_t out[8]); +.globl CRYPTO_rdrand +.type CRYPTO_rdrand,\@function,1 +.align 16 +CRYPTO_rdrand: + xorq %rax, %rax + # This is rdrand %rcx. It sets rcx to a random value and sets the carry + # flag on success. + .byte 0x48, 0x0f, 0xc7, 0xf1 + # An add-with-carry of zero effectively sets %rax to the carry flag. + adcq %rax, %rax + movq %rcx, 0(%rdi) + retq + +# CRYPTO_rdrand_multiple8_buf fills |len| bytes at |buf| with random data from +# the hardware RNG. The |len| argument must be a multiple of eight. It returns +# one on success and zero on hardware failure. +# int CRYPTO_rdrand_multiple8_buf(uint8_t *buf, size_t len); +.globl CRYPTO_rdrand_multiple8_buf +.type CRYPTO_rdrand_multiple8_buf,\@function,2 +.align 16 +CRYPTO_rdrand_multiple8_buf: + test %rsi, %rsi + jz .Lout + movq \$8, %rdx +.Lloop: + # This is rdrand %rcx. It sets rcx to a random value and sets the carry + # flag on success. + .byte 0x48, 0x0f, 0xc7, 0xf1 + jnc .Lerr + movq %rcx, 0(%rdi) + addq %rdx, %rdi + subq %rdx, %rsi + jnz .Lloop +.Lout: + movq \$1, %rax + retq +.Lerr: + xorq %rax, %rax + retq +___ + +close STDOUT; # flush diff --git a/external/boringssl/crypto/rand/deterministic.c b/external/boringssl/crypto/rand/deterministic.c new file mode 100644 index 0000000000..e6b7bb7eca --- /dev/null +++ b/external/boringssl/crypto/rand/deterministic.c @@ -0,0 +1,49 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#if defined(BORINGSSL_UNSAFE_FUZZER_MODE) + +#include + +#include + +#include "internal.h" + + +/* g_num_calls is the number of calls to |CRYPTO_sysrand| that have occured. + * + * TODO(davidben): This is intentionally not thread-safe. If the fuzzer mode is + * ever used in a multi-threaded program, replace this with a thread-local. (A + * mutex would not be deterministic.) */ +static uint64_t g_num_calls = 0; + +void RAND_cleanup(void) {} + +void RAND_reset_for_fuzzing(void) { g_num_calls = 0; } + +void CRYPTO_sysrand(uint8_t *out, size_t requested) { + static const uint8_t kZeroKey[32]; + + uint8_t nonce[12]; + memset(nonce, 0, sizeof(nonce)); + memcpy(nonce, &g_num_calls, sizeof(g_num_calls)); + + memset(out, 0, requested); + CRYPTO_chacha_20(out, out, requested, kZeroKey, nonce, 0); + g_num_calls++; +} + +#endif /* BORINGSSL_UNSAFE_FUZZER_MODE */ diff --git a/external/boringssl/crypto/rand/internal.h b/external/boringssl/crypto/rand/internal.h new file mode 100644 index 0000000000..dcff3aa6ee --- /dev/null +++ b/external/boringssl/crypto/rand/internal.h @@ -0,0 +1,32 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_CRYPTO_RAND_INTERNAL_H +#define OPENSSL_HEADER_CRYPTO_RAND_INTERNAL_H + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* CRYPTO_sysrand fills |len| bytes at |buf| with entropy from the operating + * system. */ +void CRYPTO_sysrand(uint8_t *buf, size_t len); + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_CRYPTO_RAND_INTERNAL_H */ diff --git a/external/boringssl/crypto/rand/rand.c b/external/boringssl/crypto/rand/rand.c new file mode 100644 index 0000000000..5a1bec2ef5 --- /dev/null +++ b/external/boringssl/crypto/rand/rand.c @@ -0,0 +1,242 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include +#include +#include + +#include +#include +#include + +#include "internal.h" +#include "../internal.h" + + +/* It's assumed that the operating system always has an unfailing source of + * entropy which is accessed via |CRYPTO_sysrand|. (If the operating system + * entropy source fails, it's up to |CRYPTO_sysrand| to abort the process—we + * don't try to handle it.) + * + * In addition, the hardware may provide a low-latency RNG. Intel's rdrand + * instruction is the canonical example of this. When a hardware RNG is + * available we don't need to worry about an RNG failure arising from fork()ing + * the process or moving a VM, so we can keep thread-local RNG state and XOR + * the hardware entropy in. + * + * (We assume that the OS entropy is safe from fork()ing and VM duplication. + * This might be a bit of a leap of faith, esp on Windows, but there's nothing + * that we can do about it.) */ + +/* rand_thread_state contains the per-thread state for the RNG. This is only + * used if the system has support for a hardware RNG. */ +struct rand_thread_state { + uint8_t key[32]; + uint64_t calls_used; + size_t bytes_used; + uint8_t partial_block[64]; + unsigned partial_block_used; +}; + +/* kMaxCallsPerRefresh is the maximum number of |RAND_bytes| calls that we'll + * serve before reading a new key from the operating system. This only applies + * if we have a hardware RNG. */ +static const unsigned kMaxCallsPerRefresh = 1024; + +/* kMaxBytesPerRefresh is the maximum number of bytes that we'll return from + * |RAND_bytes| before reading a new key from the operating system. This only + * applies if we have a hardware RNG. */ +static const uint64_t kMaxBytesPerRefresh = 1024 * 1024; + +/* rand_thread_state_free frees a |rand_thread_state|. This is called when a + * thread exits. */ +static void rand_thread_state_free(void *state) { + if (state == NULL) { + return; + } + + OPENSSL_cleanse(state, sizeof(struct rand_thread_state)); + OPENSSL_free(state); +} + +#if defined(OPENSSL_X86_64) && !defined(OPENSSL_NO_ASM) && \ + !defined(BORINGSSL_UNSAFE_FUZZER_MODE) + +/* These functions are defined in asm/rdrand-x86_64.pl */ +extern int CRYPTO_rdrand(uint8_t out[8]); +extern int CRYPTO_rdrand_multiple8_buf(uint8_t *buf, size_t len); + +static int have_rdrand(void) { + return (OPENSSL_ia32cap_P[1] & (1u << 30)) != 0; +} + +static int hwrand(uint8_t *buf, size_t len) { + if (!have_rdrand()) { + return 0; + } + + const size_t len_multiple8 = len & ~7; + if (!CRYPTO_rdrand_multiple8_buf(buf, len_multiple8)) { + return 0; + } + len -= len_multiple8; + + if (len != 0) { + assert(len < 8); + + uint8_t rand_buf[8]; + if (!CRYPTO_rdrand(rand_buf)) { + return 0; + } + memcpy(buf + len_multiple8, rand_buf, len); + } + + return 1; +} + +#else + +static int hwrand(uint8_t *buf, size_t len) { + return 0; +} + +#endif + +int RAND_bytes(uint8_t *buf, size_t len) { + if (len == 0) { + return 1; + } + + if (!hwrand(buf, len)) { + /* Without a hardware RNG to save us from address-space duplication, the OS + * entropy is used directly. */ + CRYPTO_sysrand(buf, len); + return 1; + } + + struct rand_thread_state *state = + CRYPTO_get_thread_local(OPENSSL_THREAD_LOCAL_RAND); + if (state == NULL) { + state = OPENSSL_malloc(sizeof(struct rand_thread_state)); + if (state == NULL || + !CRYPTO_set_thread_local(OPENSSL_THREAD_LOCAL_RAND, state, + rand_thread_state_free)) { + CRYPTO_sysrand(buf, len); + return 1; + } + + memset(state->partial_block, 0, sizeof(state->partial_block)); + state->calls_used = kMaxCallsPerRefresh; + } + + if (state->calls_used >= kMaxCallsPerRefresh || + state->bytes_used >= kMaxBytesPerRefresh) { + CRYPTO_sysrand(state->key, sizeof(state->key)); + state->calls_used = 0; + state->bytes_used = 0; + state->partial_block_used = sizeof(state->partial_block); + } + + if (len >= sizeof(state->partial_block)) { + size_t remaining = len; + while (remaining > 0) { + /* kMaxBytesPerCall is only 2GB, while ChaCha can handle 256GB. But this + * is sufficient and easier on 32-bit. */ + static const size_t kMaxBytesPerCall = 0x80000000; + size_t todo = remaining; + if (todo > kMaxBytesPerCall) { + todo = kMaxBytesPerCall; + } + uint8_t nonce[12]; + memset(nonce, 0, 4); + memcpy(nonce + 4, &state->calls_used, sizeof(state->calls_used)); + CRYPTO_chacha_20(buf, buf, todo, state->key, nonce, 0); + buf += todo; + remaining -= todo; + state->calls_used++; + } + } else { + if (sizeof(state->partial_block) - state->partial_block_used < len) { + uint8_t nonce[12]; + memset(nonce, 0, 4); + memcpy(nonce + 4, &state->calls_used, sizeof(state->calls_used)); + CRYPTO_chacha_20(state->partial_block, state->partial_block, + sizeof(state->partial_block), state->key, nonce, 0); + state->partial_block_used = 0; + } + + unsigned i; + for (i = 0; i < len; i++) { + buf[i] ^= state->partial_block[state->partial_block_used++]; + } + state->calls_used++; + } + state->bytes_used += len; + + return 1; +} + +int RAND_pseudo_bytes(uint8_t *buf, size_t len) { + return RAND_bytes(buf, len); +} + +void RAND_seed(const void *buf, int num) { + /* OpenSSH calls |RAND_seed| before jailing on the assumption that any needed + * file descriptors etc will be opened. */ + uint8_t unused; + RAND_bytes(&unused, sizeof(unused)); +} + +int RAND_load_file(const char *path, long num) { + if (num < 0) { /* read the "whole file" */ + return 1; + } else if (num <= INT_MAX) { + return (int) num; + } else { + return INT_MAX; + } +} + +const char *RAND_file_name(char *buf, size_t num) { return NULL; } + +void RAND_add(const void *buf, int num, double entropy) {} + +int RAND_egd(const char *path) { + return 255; +} + +int RAND_poll(void) { + return 1; +} + +int RAND_status(void) { + return 1; +} + +static const struct rand_meth_st kSSLeayMethod = { + RAND_seed, + RAND_bytes, + RAND_cleanup, + RAND_add, + RAND_pseudo_bytes, + RAND_status, +}; + +RAND_METHOD *RAND_SSLeay(void) { + return (RAND_METHOD*) &kSSLeayMethod; +} + +void RAND_set_rand_method(const RAND_METHOD *method) {} diff --git a/external/boringssl/crypto/rand/urandom.c b/external/boringssl/crypto/rand/urandom.c new file mode 100644 index 0000000000..434fe4317c --- /dev/null +++ b/external/boringssl/crypto/rand/urandom.c @@ -0,0 +1,223 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#if !defined(OPENSSL_WINDOWS) && !defined(BORINGSSL_UNSAFE_FUZZER_MODE) + +#include +#include +#include +#include +#include + +#include +#include + +#include "internal.h" +#include "../internal.h" + + +/* This file implements a PRNG by reading from /dev/urandom, optionally with a + * buffer, which is unsafe across |fork|. */ + +#define BUF_SIZE 4096 + +/* rand_buffer contains unused, random bytes, some of which may have been + * consumed already. */ +struct rand_buffer { + size_t used; + uint8_t rand[BUF_SIZE]; +}; + +/* requested_lock is used to protect the |*_requested| variables. */ +static struct CRYPTO_STATIC_MUTEX requested_lock = CRYPTO_STATIC_MUTEX_INIT; + +/* urandom_fd_requested is set by |RAND_set_urandom_fd|. It's protected by + * |requested_lock|. */ +static int urandom_fd_requested = -2; + +/* urandom_fd is a file descriptor to /dev/urandom. It's protected by |once|. */ +static int urandom_fd = -2; + +/* urandom_buffering_requested is set by |RAND_enable_fork_unsafe_buffering|. + * It's protected by |requested_lock|. */ +static int urandom_buffering_requested = 0; + +/* urandom_buffering controls whether buffering is enabled (1) or not (0). This + * is protected by |once|. */ +static int urandom_buffering = 0; + +static CRYPTO_once_t once = CRYPTO_ONCE_INIT; + +/* init_once initializes the state of this module to values previously + * requested. This is the only function that modifies |urandom_fd| and + * |urandom_buffering|, whose values may be read safely after calling the + * once. */ +static void init_once(void) { + CRYPTO_STATIC_MUTEX_lock_read(&requested_lock); + urandom_buffering = urandom_buffering_requested; + int fd = urandom_fd_requested; + CRYPTO_STATIC_MUTEX_unlock_read(&requested_lock); + + if (fd == -2) { + do { + fd = open("/dev/urandom", O_RDONLY); + } while (fd == -1 && errno == EINTR); + } + + if (fd < 0) { + abort(); + } + + int flags = fcntl(fd, F_GETFD); + if (flags == -1) { + /* Native Client doesn't implement |fcntl|. */ + if (errno != ENOSYS) { + abort(); + } + } else { + flags |= FD_CLOEXEC; + if (fcntl(fd, F_SETFD, flags) == -1) { + abort(); + } + } + urandom_fd = fd; +} + +void RAND_cleanup(void) {} + +void RAND_set_urandom_fd(int fd) { + fd = dup(fd); + if (fd < 0) { + abort(); + } + + CRYPTO_STATIC_MUTEX_lock_write(&requested_lock); + urandom_fd_requested = fd; + CRYPTO_STATIC_MUTEX_unlock_write(&requested_lock); + + CRYPTO_once(&once, init_once); + if (urandom_fd != fd) { + abort(); // Already initialized. + } +} + +void RAND_enable_fork_unsafe_buffering(int fd) { + if (fd >= 0) { + fd = dup(fd); + if (fd < 0) { + abort(); + } + } else { + fd = -2; + } + + CRYPTO_STATIC_MUTEX_lock_write(&requested_lock); + urandom_buffering_requested = 1; + urandom_fd_requested = fd; + CRYPTO_STATIC_MUTEX_unlock_write(&requested_lock); + + CRYPTO_once(&once, init_once); + if (urandom_buffering != 1 || (fd >= 0 && urandom_fd != fd)) { + abort(); // Already initialized. + } +} + +static struct rand_buffer *get_thread_local_buffer(void) { + struct rand_buffer *buf = + CRYPTO_get_thread_local(OPENSSL_THREAD_LOCAL_URANDOM_BUF); + if (buf != NULL) { + return buf; + } + + buf = OPENSSL_malloc(sizeof(struct rand_buffer)); + if (buf == NULL) { + return NULL; + } + buf->used = BUF_SIZE; /* To trigger a |read_full| on first use. */ + if (!CRYPTO_set_thread_local(OPENSSL_THREAD_LOCAL_URANDOM_BUF, buf, + OPENSSL_free)) { + OPENSSL_free(buf); + return NULL; + } + + return buf; +} + +/* read_full reads exactly |len| bytes from |fd| into |out| and returns 1. In + * the case of an error it returns 0. */ +static char read_full(int fd, uint8_t *out, size_t len) { + ssize_t r; + + while (len > 0) { + do { + r = read(fd, out, len); + } while (r == -1 && errno == EINTR); + + if (r <= 0) { + return 0; + } + out += r; + len -= r; + } + + return 1; +} + +/* read_from_buffer reads |requested| random bytes from the buffer into |out|, + * refilling it if necessary to satisfy the request. */ +static void read_from_buffer(struct rand_buffer *buf, + uint8_t *out, size_t requested) { + size_t remaining = BUF_SIZE - buf->used; + + while (requested > remaining) { + memcpy(out, &buf->rand[buf->used], remaining); + buf->used += remaining; + out += remaining; + requested -= remaining; + + if (!read_full(urandom_fd, buf->rand, BUF_SIZE)) { + abort(); + return; + } + buf->used = 0; + remaining = BUF_SIZE; + } + + memcpy(out, &buf->rand[buf->used], requested); + buf->used += requested; +} + +/* CRYPTO_sysrand puts |requested| random bytes into |out|. */ +void CRYPTO_sysrand(uint8_t *out, size_t requested) { + if (requested == 0) { + return; + } + + CRYPTO_once(&once, init_once); + if (urandom_buffering && requested < BUF_SIZE) { + struct rand_buffer *buf = get_thread_local_buffer(); + if (buf != NULL) { + read_from_buffer(buf, out, requested); + return; + } + } + + if (!read_full(urandom_fd, out, requested)) { + abort(); + } +} + +#endif /* !OPENSSL_WINDOWS && !BORINGSSL_UNSAFE_FUZZER_MODE */ diff --git a/external/boringssl/crypto/rand/windows.c b/external/boringssl/crypto/rand/windows.c new file mode 100644 index 0000000000..5a9a96b417 --- /dev/null +++ b/external/boringssl/crypto/rand/windows.c @@ -0,0 +1,56 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#if defined(OPENSSL_WINDOWS) && !defined(BORINGSSL_UNSAFE_FUZZER_MODE) + +#include +#include + +OPENSSL_MSVC_PRAGMA(warning(push, 3)) + +#include + +/* #define needed to link in RtlGenRandom(), a.k.a. SystemFunction036. See the + * "Community Additions" comment on MSDN here: + * http://msdn.microsoft.com/en-us/library/windows/desktop/aa387694.aspx */ +#define SystemFunction036 NTAPI SystemFunction036 +#include +#undef SystemFunction036 + +OPENSSL_MSVC_PRAGMA(warning(pop)) + +#include "internal.h" + + +void RAND_cleanup(void) { +} + +void CRYPTO_sysrand(uint8_t *out, size_t requested) { + while (requested > 0) { + ULONG output_bytes_this_pass = ULONG_MAX; + if (requested < output_bytes_this_pass) { + output_bytes_this_pass = requested; + } + if (RtlGenRandom(out, output_bytes_this_pass) == FALSE) { + abort(); + } + requested -= output_bytes_this_pass; + out += output_bytes_this_pass; + } + return; +} + +#endif /* OPENSSL_WINDOWS && !BORINGSSL_UNSAFE_FUZZER_MODE */ diff --git a/external/boringssl/crypto/rc4/CMakeLists.txt b/external/boringssl/crypto/rc4/CMakeLists.txt new file mode 100644 index 0000000000..151773a799 --- /dev/null +++ b/external/boringssl/crypto/rc4/CMakeLists.txt @@ -0,0 +1,29 @@ +include_directories(../../include) + +if (${ARCH} STREQUAL "x86_64") + set( + RC4_ARCH_SOURCES + + rc4-x86_64.${ASM_EXT} + ) +endif() + +if (${ARCH} STREQUAL "x86") + set( + RC4_ARCH_SOURCES + + rc4-586.${ASM_EXT} + ) +endif() + +add_library( + rc4 + + OBJECT + + rc4.c + ${RC4_ARCH_SOURCES} +) + +perlasm(rc4-x86_64.${ASM_EXT} asm/rc4-x86_64.pl) +perlasm(rc4-586.${ASM_EXT} asm/rc4-586.pl) diff --git a/external/boringssl/crypto/rc4/asm/rc4-586.pl b/external/boringssl/crypto/rc4/asm/rc4-586.pl new file mode 100644 index 0000000000..8d3ccb72ab --- /dev/null +++ b/external/boringssl/crypto/rc4/asm/rc4-586.pl @@ -0,0 +1,388 @@ +#!/usr/bin/env perl + +# ==================================================================== +# [Re]written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== + +# At some point it became apparent that the original SSLeay RC4 +# assembler implementation performs suboptimally on latest IA-32 +# microarchitectures. After re-tuning performance has changed as +# following: +# +# Pentium -10% +# Pentium III +12% +# AMD +50%(*) +# P4 +250%(**) +# +# (*) This number is actually a trade-off:-) It's possible to +# achieve +72%, but at the cost of -48% off PIII performance. +# In other words code performing further 13% faster on AMD +# would perform almost 2 times slower on Intel PIII... +# For reference! This code delivers ~80% of rc4-amd64.pl +# performance on the same Opteron machine. +# (**) This number requires compressed key schedule set up by +# RC4_set_key [see commentary below for further details]. +# +# + +# May 2011 +# +# Optimize for Core2 and Westmere [and incidentally Opteron]. Current +# performance in cycles per processed byte (less is better) and +# improvement relative to previous version of this module is: +# +# Pentium 10.2 # original numbers +# Pentium III 7.8(*) +# Intel P4 7.5 +# +# Opteron 6.1/+20% # new MMX numbers +# Core2 5.3/+67%(**) +# Westmere 5.1/+94%(**) +# Sandy Bridge 5.0/+8% +# Atom 12.6/+6% +# +# (*) PIII can actually deliver 6.6 cycles per byte with MMX code, +# but this specific code performs poorly on Core2. And vice +# versa, below MMX/SSE code delivering 5.8/7.1 on Core2 performs +# poorly on PIII, at 8.0/14.5:-( As PIII is not a "hot" CPU +# [anymore], I chose to discard PIII-specific code path and opt +# for original IALU-only code, which is why MMX/SSE code path +# is guarded by SSE2 bit (see below), not MMX/SSE. +# (**) Performance vs. block size on Core2 and Westmere had a maximum +# at ... 64 bytes block size. And it was quite a maximum, 40-60% +# in comparison to largest 8KB block size. Above improvement +# coefficients are for the largest block size. + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +push(@INC,"${dir}","${dir}../../perlasm"); +require "x86asm.pl"; + +&asm_init($ARGV[0],"rc4-586.pl",$x86only = $ARGV[$#ARGV] eq "386"); + +$xx="eax"; +$yy="ebx"; +$tx="ecx"; +$ty="edx"; +$inp="esi"; +$out="ebp"; +$dat="edi"; + +sub RC4_loop { + my $i=shift; + my $func = ($i==0)?*mov:*or; + + &add (&LB($yy),&LB($tx)); + &mov ($ty,&DWP(0,$dat,$yy,4)); + &mov (&DWP(0,$dat,$yy,4),$tx); + &mov (&DWP(0,$dat,$xx,4),$ty); + &add ($ty,$tx); + &inc (&LB($xx)); + &and ($ty,0xff); + &ror ($out,8) if ($i!=0); + if ($i<3) { + &mov ($tx,&DWP(0,$dat,$xx,4)); + } else { + &mov ($tx,&wparam(3)); # reload [re-biased] out + } + &$func ($out,&DWP(0,$dat,$ty,4)); +} + +if ($alt=0) { + # >20% faster on Atom and Sandy Bridge[!], 8% faster on Opteron, + # but ~40% slower on Core2 and Westmere... Attempt to add movz + # brings down Opteron by 25%, Atom and Sandy Bridge by 15%, yet + # on Core2 with movz it's almost 20% slower than below alternative + # code... Yes, it's a total mess... + my @XX=($xx,$out); + $RC4_loop_mmx = sub { # SSE actually... + my $i=shift; + my $j=$i<=0?0:$i>>1; + my $mm=$i<=0?"mm0":"mm".($i&1); + + &add (&LB($yy),&LB($tx)); + &lea (@XX[1],&DWP(1,@XX[0])); + &pxor ("mm2","mm0") if ($i==0); + &psllq ("mm1",8) if ($i==0); + &and (@XX[1],0xff); + &pxor ("mm0","mm0") if ($i<=0); + &mov ($ty,&DWP(0,$dat,$yy,4)); + &mov (&DWP(0,$dat,$yy,4),$tx); + &pxor ("mm1","mm2") if ($i==0); + &mov (&DWP(0,$dat,$XX[0],4),$ty); + &add (&LB($ty),&LB($tx)); + &movd (@XX[0],"mm7") if ($i==0); + &mov ($tx,&DWP(0,$dat,@XX[1],4)); + &pxor ("mm1","mm1") if ($i==1); + &movq ("mm2",&QWP(0,$inp)) if ($i==1); + &movq (&QWP(-8,(@XX[0],$inp)),"mm1") if ($i==0); + &pinsrw ($mm,&DWP(0,$dat,$ty,4),$j); + + push (@XX,shift(@XX)) if ($i>=0); + } +} else { + # Using pinsrw here improves performane on Intel CPUs by 2-3%, but + # brings down AMD by 7%... + $RC4_loop_mmx = sub { + my $i=shift; + + &add (&LB($yy),&LB($tx)); + &psllq ("mm1",8*(($i-1)&7)) if (abs($i)!=1); + &mov ($ty,&DWP(0,$dat,$yy,4)); + &mov (&DWP(0,$dat,$yy,4),$tx); + &mov (&DWP(0,$dat,$xx,4),$ty); + &inc ($xx); + &add ($ty,$tx); + &movz ($xx,&LB($xx)); # (*) + &movz ($ty,&LB($ty)); # (*) + &pxor ("mm2",$i==1?"mm0":"mm1") if ($i>=0); + &movq ("mm0",&QWP(0,$inp)) if ($i<=0); + &movq (&QWP(-8,($out,$inp)),"mm2") if ($i==0); + &mov ($tx,&DWP(0,$dat,$xx,4)); + &movd ($i>0?"mm1":"mm2",&DWP(0,$dat,$ty,4)); + + # (*) This is the key to Core2 and Westmere performance. + # Whithout movz out-of-order execution logic confuses + # itself and fails to reorder loads and stores. Problem + # appears to be fixed in Sandy Bridge... + } +} + +&external_label("OPENSSL_ia32cap_P"); + +# void asm_RC4(RC4_KEY *key,size_t len,const unsigned char *inp,unsigned char *out); +&function_begin("asm_RC4"); + &mov ($dat,&wparam(0)); # load key schedule pointer + &mov ($ty, &wparam(1)); # load len + &mov ($inp,&wparam(2)); # load inp + &mov ($out,&wparam(3)); # load out + + &xor ($xx,$xx); # avoid partial register stalls + &xor ($yy,$yy); + + &cmp ($ty,0); # safety net + &je (&label("abort")); + + &mov (&LB($xx),&BP(0,$dat)); # load key->x + &mov (&LB($yy),&BP(4,$dat)); # load key->y + &add ($dat,8); + + &lea ($tx,&DWP(0,$inp,$ty)); + &sub ($out,$inp); # re-bias out + &mov (&wparam(1),$tx); # save input+len + + &inc (&LB($xx)); + + # detect compressed key schedule... + &cmp (&DWP(256,$dat),-1); + &je (&label("RC4_CHAR")); + + &mov ($tx,&DWP(0,$dat,$xx,4)); + + &and ($ty,-4); # how many 4-byte chunks? + &jz (&label("loop1")); + + &mov (&wparam(3),$out); # $out as accumulator in these loops + if ($x86only) { + &jmp (&label("go4loop4")); + } else { + &test ($ty,-8); + &jz (&label("go4loop4")); + + &picmeup($out,"OPENSSL_ia32cap_P"); + &bt (&DWP(0,$out),26); # check SSE2 bit [could have been MMX] + &jnc (&label("go4loop4")); + + &mov ($out,&wparam(3)) if (!$alt); + &movd ("mm7",&wparam(3)) if ($alt); + &and ($ty,-8); + &lea ($ty,&DWP(-8,$inp,$ty)); + &mov (&DWP(-4,$dat),$ty); # save input+(len/8)*8-8 + + &$RC4_loop_mmx(-1); + &jmp(&label("loop_mmx_enter")); + + &set_label("loop_mmx",16); + &$RC4_loop_mmx(0); + &set_label("loop_mmx_enter"); + for ($i=1;$i<8;$i++) { &$RC4_loop_mmx($i); } + &mov ($ty,$yy); + &xor ($yy,$yy); # this is second key to Core2 + &mov (&LB($yy),&LB($ty)); # and Westmere performance... + &cmp ($inp,&DWP(-4,$dat)); + &lea ($inp,&DWP(8,$inp)); + &jb (&label("loop_mmx")); + + if ($alt) { + &movd ($out,"mm7"); + &pxor ("mm2","mm0"); + &psllq ("mm1",8); + &pxor ("mm1","mm2"); + &movq (&QWP(-8,$out,$inp),"mm1"); + } else { + &psllq ("mm1",56); + &pxor ("mm2","mm1"); + &movq (&QWP(-8,$out,$inp),"mm2"); + } + &emms (); + + &cmp ($inp,&wparam(1)); # compare to input+len + &je (&label("done")); + &jmp (&label("loop1")); + } + +&set_label("go4loop4",16); + &lea ($ty,&DWP(-4,$inp,$ty)); + &mov (&wparam(2),$ty); # save input+(len/4)*4-4 + + &set_label("loop4"); + for ($i=0;$i<4;$i++) { RC4_loop($i); } + &ror ($out,8); + &xor ($out,&DWP(0,$inp)); + &cmp ($inp,&wparam(2)); # compare to input+(len/4)*4-4 + &mov (&DWP(0,$tx,$inp),$out);# $tx holds re-biased out here + &lea ($inp,&DWP(4,$inp)); + &mov ($tx,&DWP(0,$dat,$xx,4)); + &jb (&label("loop4")); + + &cmp ($inp,&wparam(1)); # compare to input+len + &je (&label("done")); + &mov ($out,&wparam(3)); # restore $out + + &set_label("loop1",16); + &add (&LB($yy),&LB($tx)); + &mov ($ty,&DWP(0,$dat,$yy,4)); + &mov (&DWP(0,$dat,$yy,4),$tx); + &mov (&DWP(0,$dat,$xx,4),$ty); + &add ($ty,$tx); + &inc (&LB($xx)); + &and ($ty,0xff); + &mov ($ty,&DWP(0,$dat,$ty,4)); + &xor (&LB($ty),&BP(0,$inp)); + &lea ($inp,&DWP(1,$inp)); + &mov ($tx,&DWP(0,$dat,$xx,4)); + &cmp ($inp,&wparam(1)); # compare to input+len + &mov (&BP(-1,$out,$inp),&LB($ty)); + &jb (&label("loop1")); + + &jmp (&label("done")); + +# this is essentially Intel P4 specific codepath... +&set_label("RC4_CHAR",16); + &movz ($tx,&BP(0,$dat,$xx)); + # strangely enough unrolled loop performs over 20% slower... + &set_label("cloop1"); + &add (&LB($yy),&LB($tx)); + &movz ($ty,&BP(0,$dat,$yy)); + &mov (&BP(0,$dat,$yy),&LB($tx)); + &mov (&BP(0,$dat,$xx),&LB($ty)); + &add (&LB($ty),&LB($tx)); + &movz ($ty,&BP(0,$dat,$ty)); + &add (&LB($xx),1); + &xor (&LB($ty),&BP(0,$inp)); + &lea ($inp,&DWP(1,$inp)); + &movz ($tx,&BP(0,$dat,$xx)); + &cmp ($inp,&wparam(1)); + &mov (&BP(-1,$out,$inp),&LB($ty)); + &jb (&label("cloop1")); + +&set_label("done"); + &dec (&LB($xx)); + &mov (&DWP(-4,$dat),$yy); # save key->y + &mov (&BP(-8,$dat),&LB($xx)); # save key->x +&set_label("abort"); +&function_end("asm_RC4"); + +######################################################################## + +$inp="esi"; +$out="edi"; +$idi="ebp"; +$ido="ecx"; +$idx="edx"; + +# void asm_RC4_set_key(RC4_KEY *key,int len,const unsigned char *data); +&function_begin("asm_RC4_set_key"); + &mov ($out,&wparam(0)); # load key + &mov ($idi,&wparam(1)); # load len + &mov ($inp,&wparam(2)); # load data + &picmeup($idx,"OPENSSL_ia32cap_P"); + + &lea ($out,&DWP(2*4,$out)); # &key->data + &lea ($inp,&DWP(0,$inp,$idi)); # $inp to point at the end + &neg ($idi); + &xor ("eax","eax"); + &mov (&DWP(-4,$out),$idi); # borrow key->y + + &bt (&DWP(0,$idx),20); # check for bit#20 + &jc (&label("c1stloop")); + +&set_label("w1stloop",16); + &mov (&DWP(0,$out,"eax",4),"eax"); # key->data[i]=i; + &add (&LB("eax"),1); # i++; + &jnc (&label("w1stloop")); + + &xor ($ido,$ido); + &xor ($idx,$idx); + +&set_label("w2ndloop",16); + &mov ("eax",&DWP(0,$out,$ido,4)); + &add (&LB($idx),&BP(0,$inp,$idi)); + &add (&LB($idx),&LB("eax")); + &add ($idi,1); + &mov ("ebx",&DWP(0,$out,$idx,4)); + &jnz (&label("wnowrap")); + &mov ($idi,&DWP(-4,$out)); + &set_label("wnowrap"); + &mov (&DWP(0,$out,$idx,4),"eax"); + &mov (&DWP(0,$out,$ido,4),"ebx"); + &add (&LB($ido),1); + &jnc (&label("w2ndloop")); +&jmp (&label("exit")); + +# Unlike all other x86 [and x86_64] implementations, Intel P4 core +# [including EM64T] was found to perform poorly with above "32-bit" key +# schedule, a.k.a. RC4_INT. Performance improvement for IA-32 hand-coded +# assembler turned out to be 3.5x if re-coded for compressed 8-bit one, +# a.k.a. RC4_CHAR! It's however inappropriate to just switch to 8-bit +# schedule for x86[_64], because non-P4 implementations suffer from +# significant performance losses then, e.g. PIII exhibits >2x +# deterioration, and so does Opteron. In order to assure optimal +# all-round performance, we detect P4 at run-time and set up compressed +# key schedule, which is recognized by RC4 procedure. + +&set_label("c1stloop",16); + &mov (&BP(0,$out,"eax"),&LB("eax")); # key->data[i]=i; + &add (&LB("eax"),1); # i++; + &jnc (&label("c1stloop")); + + &xor ($ido,$ido); + &xor ($idx,$idx); + &xor ("ebx","ebx"); + +&set_label("c2ndloop",16); + &mov (&LB("eax"),&BP(0,$out,$ido)); + &add (&LB($idx),&BP(0,$inp,$idi)); + &add (&LB($idx),&LB("eax")); + &add ($idi,1); + &mov (&LB("ebx"),&BP(0,$out,$idx)); + &jnz (&label("cnowrap")); + &mov ($idi,&DWP(-4,$out)); + &set_label("cnowrap"); + &mov (&BP(0,$out,$idx),&LB("eax")); + &mov (&BP(0,$out,$ido),&LB("ebx")); + &add (&LB($ido),1); + &jnc (&label("c2ndloop")); + + &mov (&DWP(256,$out),-1); # mark schedule as compressed + +&set_label("exit"); + &xor ("eax","eax"); + &mov (&DWP(-8,$out),"eax"); # key->x=0; + &mov (&DWP(-4,$out),"eax"); # key->y=0; +&function_end("asm_RC4_set_key"); + +&asm_finish(); + diff --git a/external/boringssl/crypto/rc4/asm/rc4-x86_64.pl b/external/boringssl/crypto/rc4/asm/rc4-x86_64.pl new file mode 100644 index 0000000000..cef6268914 --- /dev/null +++ b/external/boringssl/crypto/rc4/asm/rc4-x86_64.pl @@ -0,0 +1,653 @@ +#!/usr/bin/env perl +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# July 2004 +# +# 2.22x RC4 tune-up:-) It should be noted though that my hand [as in +# "hand-coded assembler"] doesn't stand for the whole improvement +# coefficient. It turned out that eliminating RC4_CHAR from config +# line results in ~40% improvement (yes, even for C implementation). +# Presumably it has everything to do with AMD cache architecture and +# RAW or whatever penalties. Once again! The module *requires* config +# line *without* RC4_CHAR! As for coding "secret," I bet on partial +# register arithmetics. For example instead of 'inc %r8; and $255,%r8' +# I simply 'inc %r8b'. Even though optimization manual discourages +# to operate on partial registers, it turned out to be the best bet. +# At least for AMD... How IA32E would perform remains to be seen... + +# November 2004 +# +# As was shown by Marc Bevand reordering of couple of load operations +# results in even higher performance gain of 3.3x:-) At least on +# Opteron... For reference, 1x in this case is RC4_CHAR C-code +# compiled with gcc 3.3.2, which performs at ~54MBps per 1GHz clock. +# Latter means that if you want to *estimate* what to expect from +# *your* Opteron, then multiply 54 by 3.3 and clock frequency in GHz. + +# November 2004 +# +# Intel P4 EM64T core was found to run the AMD64 code really slow... +# The only way to achieve comparable performance on P4 was to keep +# RC4_CHAR. Kind of ironic, huh? As it's apparently impossible to +# compose blended code, which would perform even within 30% marginal +# on either AMD and Intel platforms, I implement both cases. See +# rc4_skey.c for further details... + +# April 2005 +# +# P4 EM64T core appears to be "allergic" to 64-bit inc/dec. Replacing +# those with add/sub results in 50% performance improvement of folded +# loop... + +# May 2005 +# +# As was shown by Zou Nanhai loop unrolling can improve Intel EM64T +# performance by >30% [unlike P4 32-bit case that is]. But this is +# provided that loads are reordered even more aggressively! Both code +# pathes, AMD64 and EM64T, reorder loads in essentially same manner +# as my IA-64 implementation. On Opteron this resulted in modest 5% +# improvement [I had to test it], while final Intel P4 performance +# achieves respectful 432MBps on 2.8GHz processor now. For reference. +# If executed on Xeon, current RC4_CHAR code-path is 2.7x faster than +# RC4_INT code-path. While if executed on Opteron, it's only 25% +# slower than the RC4_INT one [meaning that if CPU µ-arch detection +# is not implemented, then this final RC4_CHAR code-path should be +# preferred, as it provides better *all-round* performance]. + +# March 2007 +# +# Intel Core2 was observed to perform poorly on both code paths:-( It +# apparently suffers from some kind of partial register stall, which +# occurs in 64-bit mode only [as virtually identical 32-bit loop was +# observed to outperform 64-bit one by almost 50%]. Adding two movzb to +# cloop1 boosts its performance by 80%! This loop appears to be optimal +# fit for Core2 and therefore the code was modified to skip cloop8 on +# this CPU. + +# May 2010 +# +# Intel Westmere was observed to perform suboptimally. Adding yet +# another movzb to cloop1 improved performance by almost 50%! Core2 +# performance is improved too, but nominally... + +# May 2011 +# +# The only code path that was not modified is P4-specific one. Non-P4 +# Intel code path optimization is heavily based on submission by Maxim +# Perminov, Maxim Locktyukhin and Jim Guilford of Intel. I've used +# some of the ideas even in attempt to optmize the original RC4_INT +# code path... Current performance in cycles per processed byte (less +# is better) and improvement coefficients relative to previous +# version of this module are: +# +# Opteron 5.3/+0%(*) +# P4 6.5 +# Core2 6.2/+15%(**) +# Westmere 4.2/+60% +# Sandy Bridge 4.2/+120% +# Atom 9.3/+80% +# +# (*) But corresponding loop has less instructions, which should have +# positive effect on upcoming Bulldozer, which has one less ALU. +# For reference, Intel code runs at 6.8 cpb rate on Opteron. +# (**) Note that Core2 result is ~15% lower than corresponding result +# for 32-bit code, meaning that it's possible to improve it, +# but more than likely at the cost of the others (see rc4-586.pl +# to get the idea)... + +$flavour = shift; +$output = shift; +if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } + +$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or +die "can't locate x86_64-xlate.pl"; + +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; + +$dat="%rdi"; # arg1 +$len="%rsi"; # arg2 +$inp="%rdx"; # arg3 +$out="%rcx"; # arg4 + +{ +$code=<<___; +.text +.extern OPENSSL_ia32cap_P + +.globl asm_RC4 +.type asm_RC4,\@function,4 +.align 16 +asm_RC4: + or $len,$len + jne .Lentry + ret +.Lentry: + push %rbx + push %r12 + push %r13 +.Lprologue: + mov $len,%r11 + mov $inp,%r12 + mov $out,%r13 +___ +my $len="%r11"; # reassign input arguments +my $inp="%r12"; +my $out="%r13"; + +my @XX=("%r10","%rsi"); +my @TX=("%rax","%rbx"); +my $YY="%rcx"; +my $TY="%rdx"; + +$code.=<<___; + xor $XX[0],$XX[0] + xor $YY,$YY + + lea 8($dat),$dat + mov -8($dat),$XX[0]#b + mov -4($dat),$YY#b + cmpl \$-1,256($dat) + je .LRC4_CHAR + mov OPENSSL_ia32cap_P(%rip),%r8d + xor $TX[1],$TX[1] + inc $XX[0]#b + sub $XX[0],$TX[1] + sub $inp,$out + movl ($dat,$XX[0],4),$TX[0]#d + test \$-16,$len + jz .Lloop1 + bt \$30,%r8d # Intel CPU? + jc .Lintel + and \$7,$TX[1] + lea 1($XX[0]),$XX[1] + jz .Loop8 + sub $TX[1],$len +.Loop8_warmup: + add $TX[0]#b,$YY#b + movl ($dat,$YY,4),$TY#d + movl $TX[0]#d,($dat,$YY,4) + movl $TY#d,($dat,$XX[0],4) + add $TY#b,$TX[0]#b + inc $XX[0]#b + movl ($dat,$TX[0],4),$TY#d + movl ($dat,$XX[0],4),$TX[0]#d + xorb ($inp),$TY#b + movb $TY#b,($out,$inp) + lea 1($inp),$inp + dec $TX[1] + jnz .Loop8_warmup + + lea 1($XX[0]),$XX[1] + jmp .Loop8 +.align 16 +.Loop8: +___ +for ($i=0;$i<8;$i++) { +$code.=<<___ if ($i==7); + add \$8,$XX[1]#b +___ +$code.=<<___; + add $TX[0]#b,$YY#b + movl ($dat,$YY,4),$TY#d + movl $TX[0]#d,($dat,$YY,4) + movl `4*($i==7?-1:$i)`($dat,$XX[1],4),$TX[1]#d + ror \$8,%r8 # ror is redundant when $i=0 + movl $TY#d,4*$i($dat,$XX[0],4) + add $TX[0]#b,$TY#b + movb ($dat,$TY,4),%r8b +___ +push(@TX,shift(@TX)); #push(@XX,shift(@XX)); # "rotate" registers +} +$code.=<<___; + add \$8,$XX[0]#b + ror \$8,%r8 + sub \$8,$len + + xor ($inp),%r8 + mov %r8,($out,$inp) + lea 8($inp),$inp + + test \$-8,$len + jnz .Loop8 + cmp \$0,$len + jne .Lloop1 + jmp .Lexit + +.align 16 +.Lintel: + test \$-32,$len + jz .Lloop1 + and \$15,$TX[1] + jz .Loop16_is_hot + sub $TX[1],$len +.Loop16_warmup: + add $TX[0]#b,$YY#b + movl ($dat,$YY,4),$TY#d + movl $TX[0]#d,($dat,$YY,4) + movl $TY#d,($dat,$XX[0],4) + add $TY#b,$TX[0]#b + inc $XX[0]#b + movl ($dat,$TX[0],4),$TY#d + movl ($dat,$XX[0],4),$TX[0]#d + xorb ($inp),$TY#b + movb $TY#b,($out,$inp) + lea 1($inp),$inp + dec $TX[1] + jnz .Loop16_warmup + + mov $YY,$TX[1] + xor $YY,$YY + mov $TX[1]#b,$YY#b + +.Loop16_is_hot: + lea ($dat,$XX[0],4),$XX[1] +___ +sub RC4_loop { + my $i=shift; + my $j=$i<0?0:$i; + my $xmm="%xmm".($j&1); + + $code.=" add \$16,$XX[0]#b\n" if ($i==15); + $code.=" movdqu ($inp),%xmm2\n" if ($i==15); + $code.=" add $TX[0]#b,$YY#b\n" if ($i<=0); + $code.=" movl ($dat,$YY,4),$TY#d\n"; + $code.=" pxor %xmm0,%xmm2\n" if ($i==0); + $code.=" psllq \$8,%xmm1\n" if ($i==0); + $code.=" pxor $xmm,$xmm\n" if ($i<=1); + $code.=" movl $TX[0]#d,($dat,$YY,4)\n"; + $code.=" add $TY#b,$TX[0]#b\n"; + $code.=" movl `4*($j+1)`($XX[1]),$TX[1]#d\n" if ($i<15); + $code.=" movz $TX[0]#b,$TX[0]#d\n"; + $code.=" movl $TY#d,4*$j($XX[1])\n"; + $code.=" pxor %xmm1,%xmm2\n" if ($i==0); + $code.=" lea ($dat,$XX[0],4),$XX[1]\n" if ($i==15); + $code.=" add $TX[1]#b,$YY#b\n" if ($i<15); + $code.=" pinsrw \$`($j>>1)&7`,($dat,$TX[0],4),$xmm\n"; + $code.=" movdqu %xmm2,($out,$inp)\n" if ($i==0); + $code.=" lea 16($inp),$inp\n" if ($i==0); + $code.=" movl ($XX[1]),$TX[1]#d\n" if ($i==15); +} + RC4_loop(-1); +$code.=<<___; + jmp .Loop16_enter +.align 16 +.Loop16: +___ + +for ($i=0;$i<16;$i++) { + $code.=".Loop16_enter:\n" if ($i==1); + RC4_loop($i); + push(@TX,shift(@TX)); # "rotate" registers +} +$code.=<<___; + mov $YY,$TX[1] + xor $YY,$YY # keyword to partial register + sub \$16,$len + mov $TX[1]#b,$YY#b + test \$-16,$len + jnz .Loop16 + + psllq \$8,%xmm1 + pxor %xmm0,%xmm2 + pxor %xmm1,%xmm2 + movdqu %xmm2,($out,$inp) + lea 16($inp),$inp + + cmp \$0,$len + jne .Lloop1 + jmp .Lexit + +.align 16 +.Lloop1: + add $TX[0]#b,$YY#b + movl ($dat,$YY,4),$TY#d + movl $TX[0]#d,($dat,$YY,4) + movl $TY#d,($dat,$XX[0],4) + add $TY#b,$TX[0]#b + inc $XX[0]#b + movl ($dat,$TX[0],4),$TY#d + movl ($dat,$XX[0],4),$TX[0]#d + xorb ($inp),$TY#b + movb $TY#b,($out,$inp) + lea 1($inp),$inp + dec $len + jnz .Lloop1 + jmp .Lexit + +.align 16 +.LRC4_CHAR: + add \$1,$XX[0]#b + movzb ($dat,$XX[0]),$TX[0]#d + test \$-8,$len + jz .Lcloop1 + jmp .Lcloop8 +.align 16 +.Lcloop8: + mov ($inp),%r8d + mov 4($inp),%r9d +___ +# unroll 2x4-wise, because 64-bit rotates kill Intel P4... +for ($i=0;$i<4;$i++) { +$code.=<<___; + add $TX[0]#b,$YY#b + lea 1($XX[0]),$XX[1] + movzb ($dat,$YY),$TY#d + movzb $XX[1]#b,$XX[1]#d + movzb ($dat,$XX[1]),$TX[1]#d + movb $TX[0]#b,($dat,$YY) + cmp $XX[1],$YY + movb $TY#b,($dat,$XX[0]) + jne .Lcmov$i # Intel cmov is sloooow... + mov $TX[0],$TX[1] +.Lcmov$i: + add $TX[0]#b,$TY#b + xor ($dat,$TY),%r8b + ror \$8,%r8d +___ +push(@TX,shift(@TX)); push(@XX,shift(@XX)); # "rotate" registers +} +for ($i=4;$i<8;$i++) { +$code.=<<___; + add $TX[0]#b,$YY#b + lea 1($XX[0]),$XX[1] + movzb ($dat,$YY),$TY#d + movzb $XX[1]#b,$XX[1]#d + movzb ($dat,$XX[1]),$TX[1]#d + movb $TX[0]#b,($dat,$YY) + cmp $XX[1],$YY + movb $TY#b,($dat,$XX[0]) + jne .Lcmov$i # Intel cmov is sloooow... + mov $TX[0],$TX[1] +.Lcmov$i: + add $TX[0]#b,$TY#b + xor ($dat,$TY),%r9b + ror \$8,%r9d +___ +push(@TX,shift(@TX)); push(@XX,shift(@XX)); # "rotate" registers +} +$code.=<<___; + lea -8($len),$len + mov %r8d,($out) + lea 8($inp),$inp + mov %r9d,4($out) + lea 8($out),$out + + test \$-8,$len + jnz .Lcloop8 + cmp \$0,$len + jne .Lcloop1 + jmp .Lexit +___ +$code.=<<___; +.align 16 +.Lcloop1: + add $TX[0]#b,$YY#b + movzb $YY#b,$YY#d + movzb ($dat,$YY),$TY#d + movb $TX[0]#b,($dat,$YY) + movb $TY#b,($dat,$XX[0]) + add $TX[0]#b,$TY#b + add \$1,$XX[0]#b + movzb $TY#b,$TY#d + movzb $XX[0]#b,$XX[0]#d + movzb ($dat,$TY),$TY#d + movzb ($dat,$XX[0]),$TX[0]#d + xorb ($inp),$TY#b + lea 1($inp),$inp + movb $TY#b,($out) + lea 1($out),$out + sub \$1,$len + jnz .Lcloop1 + jmp .Lexit + +.align 16 +.Lexit: + sub \$1,$XX[0]#b + movl $XX[0]#d,-8($dat) + movl $YY#d,-4($dat) + + mov (%rsp),%r13 + mov 8(%rsp),%r12 + mov 16(%rsp),%rbx + add \$24,%rsp +.Lepilogue: + ret +.size asm_RC4,.-asm_RC4 +___ +} + +$idx="%r8"; +$ido="%r9"; + +$code.=<<___; +.globl asm_RC4_set_key +.type asm_RC4_set_key,\@function,3 +.align 16 +asm_RC4_set_key: + lea 8($dat),$dat + lea ($inp,$len),$inp + neg $len + mov $len,%rcx + xor %eax,%eax + xor $ido,$ido + xor %r10,%r10 + xor %r11,%r11 + + mov OPENSSL_ia32cap_P(%rip),$idx#d + bt \$20,$idx#d # RC4_CHAR? + jc .Lc1stloop + jmp .Lw1stloop + +.align 16 +.Lw1stloop: + mov %eax,($dat,%rax,4) + add \$1,%al + jnc .Lw1stloop + + xor $ido,$ido + xor $idx,$idx +.align 16 +.Lw2ndloop: + mov ($dat,$ido,4),%r10d + add ($inp,$len,1),$idx#b + add %r10b,$idx#b + add \$1,$len + mov ($dat,$idx,4),%r11d + cmovz %rcx,$len + mov %r10d,($dat,$idx,4) + mov %r11d,($dat,$ido,4) + add \$1,$ido#b + jnc .Lw2ndloop + jmp .Lexit_key + +.align 16 +.Lc1stloop: + mov %al,($dat,%rax) + add \$1,%al + jnc .Lc1stloop + + xor $ido,$ido + xor $idx,$idx +.align 16 +.Lc2ndloop: + mov ($dat,$ido),%r10b + add ($inp,$len),$idx#b + add %r10b,$idx#b + add \$1,$len + mov ($dat,$idx),%r11b + jnz .Lcnowrap + mov %rcx,$len +.Lcnowrap: + mov %r10b,($dat,$idx) + mov %r11b,($dat,$ido) + add \$1,$ido#b + jnc .Lc2ndloop + movl \$-1,256($dat) + +.align 16 +.Lexit_key: + xor %eax,%eax + mov %eax,-8($dat) + mov %eax,-4($dat) + ret +.size asm_RC4_set_key,.-asm_RC4_set_key +___ + +# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame, +# CONTEXT *context,DISPATCHER_CONTEXT *disp) +if ($win64) { +$rec="%rcx"; +$frame="%rdx"; +$context="%r8"; +$disp="%r9"; + +$code.=<<___; +.extern __imp_RtlVirtualUnwind +.type stream_se_handler,\@abi-omnipotent +.align 16 +stream_se_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + lea .Lprologue(%rip),%r10 + cmp %r10,%rbx # context->RipRsp + + lea .Lepilogue(%rip),%r10 + cmp %r10,%rbx # context->Rip>=epilogue label + jae .Lin_prologue + + lea 24(%rax),%rax + + mov -8(%rax),%rbx + mov -16(%rax),%r12 + mov -24(%rax),%r13 + mov %rbx,144($context) # restore context->Rbx + mov %r12,216($context) # restore context->R12 + mov %r13,224($context) # restore context->R13 + +.Lin_prologue: + mov 8(%rax),%rdi + mov 16(%rax),%rsi + mov %rax,152($context) # restore context->Rsp + mov %rsi,168($context) # restore context->Rsi + mov %rdi,176($context) # restore context->Rdi + + jmp .Lcommon_seh_exit +.size stream_se_handler,.-stream_se_handler + +.type key_se_handler,\@abi-omnipotent +.align 16 +key_se_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 152($context),%rax # pull context->Rsp + mov 8(%rax),%rdi + mov 16(%rax),%rsi + mov %rsi,168($context) # restore context->Rsi + mov %rdi,176($context) # restore context->Rdi + +.Lcommon_seh_exit: + + mov 40($disp),%rdi # disp->ContextRecord + mov $context,%rsi # context + mov \$154,%ecx # sizeof(CONTEXT) + .long 0xa548f3fc # cld; rep movsq + + mov $disp,%rsi + xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER + mov 8(%rsi),%rdx # arg2, disp->ImageBase + mov 0(%rsi),%r8 # arg3, disp->ControlPc + mov 16(%rsi),%r9 # arg4, disp->FunctionEntry + mov 40(%rsi),%r10 # disp->ContextRecord + lea 56(%rsi),%r11 # &disp->HandlerData + lea 24(%rsi),%r12 # &disp->EstablisherFrame + mov %r10,32(%rsp) # arg5 + mov %r11,40(%rsp) # arg6 + mov %r12,48(%rsp) # arg7 + mov %rcx,56(%rsp) # arg8, (NULL) + call *__imp_RtlVirtualUnwind(%rip) + + mov \$1,%eax # ExceptionContinueSearch + add \$64,%rsp + popfq + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + pop %rdi + pop %rsi + ret +.size key_se_handler,.-key_se_handler + +.section .pdata +.align 4 + .rva .LSEH_begin_asm_RC4 + .rva .LSEH_end_asm_RC4 + .rva .LSEH_info_asm_RC4 + + .rva .LSEH_begin_asm_RC4_set_key + .rva .LSEH_end_asm_RC4_set_key + .rva .LSEH_info_asm_RC4_set_key + +.section .xdata +.align 8 +.LSEH_info_asm_RC4: + .byte 9,0,0,0 + .rva stream_se_handler +.LSEH_info_asm_RC4_set_key: + .byte 9,0,0,0 + .rva key_se_handler +___ +} + +sub reg_part { +my ($reg,$conv)=@_; + if ($reg =~ /%r[0-9]+/) { $reg .= $conv; } + elsif ($conv eq "b") { $reg =~ s/%[er]([^x]+)x?/%$1l/; } + elsif ($conv eq "w") { $reg =~ s/%[er](.+)/%$1/; } + elsif ($conv eq "d") { $reg =~ s/%[er](.+)/%e$1/; } + return $reg; +} + +$code =~ s/(%[a-z0-9]+)#([bwd])/reg_part($1,$2)/gem; +$code =~ s/\`([^\`]*)\`/eval $1/gem; + +print $code; + +close STDOUT; diff --git a/external/boringssl/crypto/rc4/rc4.c b/external/boringssl/crypto/rc4/rc4.c new file mode 100644 index 0000000000..b8e1d9f0da --- /dev/null +++ b/external/boringssl/crypto/rc4/rc4.c @@ -0,0 +1,283 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#if defined(OPENSSL_NO_ASM) || \ + (!defined(OPENSSL_X86_64) && !defined(OPENSSL_X86)) + +#if defined(OPENSSL_64_BIT) +#define RC4_CHUNK uint64_t +#elif defined(OPENSSL_32_BIT) +#define RC4_CHUNK uint32_t +#else +#error "Unknown word size" +#endif + + +/* RC4 as implemented from a posting from + * Newsgroups: sci.crypt + * From: sterndark@netcom.com (David Sterndark) + * Subject: RC4 Algorithm revealed. + * Message-ID: + * Date: Wed, 14 Sep 1994 06:35:31 GMT */ + +void RC4(RC4_KEY *key, size_t len, const uint8_t *in, uint8_t *out) { + uint32_t *d; + uint32_t x, y, tx, ty; + size_t i; + + x = key->x; + y = key->y; + d = key->data; + +#define RC4_STEP \ + (x = (x + 1) & 0xff, tx = d[x], y = (tx + y) & 0xff, ty = d[y], d[y] = tx, \ + d[x] = ty, (RC4_CHUNK)d[(tx + ty) & 0xff]) + + if ((((size_t)in & (sizeof(RC4_CHUNK) - 1)) | + ((size_t)out & (sizeof(RC4_CHUNK) - 1))) == 0) { + RC4_CHUNK ichunk, otp; + const union { + long one; + char little; + } is_endian = {1}; + + /* I reckon we can afford to implement both endian + * cases and to decide which way to take at run-time + * because the machine code appears to be very compact + * and redundant 1-2KB is perfectly tolerable (i.e. + * in case the compiler fails to eliminate it:-). By + * suggestion from Terrel Larson + * who also stands for the is_endian union:-) + * + * Special notes. + * + * - is_endian is declared automatic as doing otherwise + * (declaring static) prevents gcc from eliminating + * the redundant code; + * - compilers (those I've tried) don't seem to have + * problems eliminating either the operators guarded + * by "if (sizeof(RC4_CHUNK)==8)" or the condition + * expressions themselves so I've got 'em to replace + * corresponding #ifdefs from the previous version; + * - I chose to let the redundant switch cases when + * sizeof(RC4_CHUNK)!=8 be (were also #ifdefed + * before); + * - in case you wonder "&(sizeof(RC4_CHUNK)*8-1)" in + * [LB]ESHFT guards against "shift is out of range" + * warnings when sizeof(RC4_CHUNK)!=8 + * + * */ + if (!is_endian.little) { /* BIG-ENDIAN CASE */ +#define BESHFT(c) \ + (((sizeof(RC4_CHUNK) - (c) - 1) * 8) & (sizeof(RC4_CHUNK) * 8 - 1)) + for (; len & (0 - sizeof(RC4_CHUNK)); len -= sizeof(RC4_CHUNK)) { + ichunk = *(RC4_CHUNK *)in; + otp = RC4_STEP << BESHFT(0); + otp |= RC4_STEP << BESHFT(1); + otp |= RC4_STEP << BESHFT(2); + otp |= RC4_STEP << BESHFT(3); +#if defined(OPENSSL_64_BIT) + otp |= RC4_STEP << BESHFT(4); + otp |= RC4_STEP << BESHFT(5); + otp |= RC4_STEP << BESHFT(6); + otp |= RC4_STEP << BESHFT(7); +#endif + *(RC4_CHUNK *)out = otp ^ ichunk; + in += sizeof(RC4_CHUNK); + out += sizeof(RC4_CHUNK); + } + } else { /* LITTLE-ENDIAN CASE */ +#define LESHFT(c) (((c) * 8) & (sizeof(RC4_CHUNK) * 8 - 1)) + for (; len & (0 - sizeof(RC4_CHUNK)); len -= sizeof(RC4_CHUNK)) { + ichunk = *(RC4_CHUNK *)in; + otp = RC4_STEP; + otp |= RC4_STEP << 8; + otp |= RC4_STEP << 16; + otp |= RC4_STEP << 24; +#if defined(OPENSSL_64_BIT) + otp |= RC4_STEP << LESHFT(4); + otp |= RC4_STEP << LESHFT(5); + otp |= RC4_STEP << LESHFT(6); + otp |= RC4_STEP << LESHFT(7); +#endif + *(RC4_CHUNK *)out = otp ^ ichunk; + in += sizeof(RC4_CHUNK); + out += sizeof(RC4_CHUNK); + } + } + } +#define LOOP(in, out) \ + x = ((x + 1) & 0xff); \ + tx = d[x]; \ + y = (tx + y) & 0xff; \ + d[x] = ty = d[y]; \ + d[y] = tx; \ + (out) = d[(tx + ty) & 0xff] ^ (in); + +#ifndef RC4_INDEX +#define RC4_LOOP(a, b, i) LOOP(*((a)++), *((b)++)) +#else +#define RC4_LOOP(a, b, i) LOOP(a[i], b[i]) +#endif + + i = len >> 3; + if (i) { + for (;;) { + RC4_LOOP(in, out, 0); + RC4_LOOP(in, out, 1); + RC4_LOOP(in, out, 2); + RC4_LOOP(in, out, 3); + RC4_LOOP(in, out, 4); + RC4_LOOP(in, out, 5); + RC4_LOOP(in, out, 6); + RC4_LOOP(in, out, 7); +#ifdef RC4_INDEX + in += 8; + out += 8; +#endif + if (--i == 0) { + break; + } + } + } + i = len & 0x07; + if (i) { + for (;;) { + RC4_LOOP(in, out, 0); + if (--i == 0) { + break; + } + RC4_LOOP(in, out, 1); + if (--i == 0) { + break; + } + RC4_LOOP(in, out, 2); + if (--i == 0) { + break; + } + RC4_LOOP(in, out, 3); + if (--i == 0) { + break; + } + RC4_LOOP(in, out, 4); + if (--i == 0) { + break; + } + RC4_LOOP(in, out, 5); + if (--i == 0) { + break; + } + RC4_LOOP(in, out, 6); + if (--i == 0) { + break; + } + } + } + key->x = x; + key->y = y; +} + +void RC4_set_key(RC4_KEY *rc4key, unsigned len, const uint8_t *key) { + uint32_t tmp; + unsigned i, id1, id2; + uint32_t *d; + + d = &rc4key->data[0]; + rc4key->x = 0; + rc4key->y = 0; + id1 = id2 = 0; + +#define SK_LOOP(d, n) \ + { \ + tmp = d[(n)]; \ + id2 = (key[id1] + tmp + id2) & 0xff; \ + if (++id1 == len) \ + id1 = 0; \ + d[(n)] = d[id2]; \ + d[id2] = tmp; \ + } + + for (i = 0; i < 256; i++) { + d[i] = i; + } + for (i = 0; i < 256; i += 4) { + SK_LOOP(d, i + 0); + SK_LOOP(d, i + 1); + SK_LOOP(d, i + 2); + SK_LOOP(d, i + 3); + } +} + +#else + +/* In this case several functions are provided by asm code. However, one cannot + * control asm symbol visibility with command line flags and such so they are + * always hidden and wrapped by these C functions, which can be so + * controlled. */ + +void asm_RC4(RC4_KEY *key, size_t len, const uint8_t *in, uint8_t *out); +void RC4(RC4_KEY *key, size_t len, const uint8_t *in, uint8_t *out) { + asm_RC4(key, len, in, out); +} + +void asm_RC4_set_key(RC4_KEY *rc4key, unsigned len, const uint8_t *key); +void RC4_set_key(RC4_KEY *rc4key, unsigned len, const uint8_t *key) { + asm_RC4_set_key(rc4key, len, key); +} + +#endif /* OPENSSL_NO_ASM || (!OPENSSL_X86_64 && !OPENSSL_X86) */ diff --git a/external/boringssl/crypto/refcount_c11.c b/external/boringssl/crypto/refcount_c11.c new file mode 100644 index 0000000000..fbc0343d67 --- /dev/null +++ b/external/boringssl/crypto/refcount_c11.c @@ -0,0 +1,67 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include "internal.h" + + +#if defined(OPENSSL_C11_ATOMIC) + +#include +#include +#include +#include + +#include + + +/* See comment above the typedef of CRYPTO_refcount_t about these tests. */ +static_assert(alignof(CRYPTO_refcount_t) == alignof(_Atomic CRYPTO_refcount_t), + "_Atomic alters the needed alignment of a reference count"); +static_assert(sizeof(CRYPTO_refcount_t) == sizeof(_Atomic CRYPTO_refcount_t), + "_Atomic alters the size of a reference count"); + +static_assert((CRYPTO_refcount_t)-1 == CRYPTO_REFCOUNT_MAX, + "CRYPTO_REFCOUNT_MAX is incorrect"); + +void CRYPTO_refcount_inc(CRYPTO_refcount_t *in_count) { + _Atomic CRYPTO_refcount_t *count = (_Atomic CRYPTO_refcount_t *) in_count; + uint32_t expected = atomic_load(count); + + while (expected != CRYPTO_REFCOUNT_MAX) { + uint32_t new_value = expected + 1; + if (atomic_compare_exchange_weak(count, &expected, new_value)) { + break; + } + } +} + +int CRYPTO_refcount_dec_and_test_zero(CRYPTO_refcount_t *in_count) { + _Atomic CRYPTO_refcount_t *count = (_Atomic CRYPTO_refcount_t *)in_count; + uint32_t expected = atomic_load(count); + + for (;;) { + if (expected == 0) { + abort(); + } else if (expected == CRYPTO_REFCOUNT_MAX) { + return 0; + } else { + const uint32_t new_value = expected - 1; + if (atomic_compare_exchange_weak(count, &expected, new_value)) { + return new_value == 0; + } + } + } +} + +#endif /* OPENSSL_C11_ATOMIC */ diff --git a/external/boringssl/crypto/refcount_lock.c b/external/boringssl/crypto/refcount_lock.c new file mode 100644 index 0000000000..ea6a06d39f --- /dev/null +++ b/external/boringssl/crypto/refcount_lock.c @@ -0,0 +1,53 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include "internal.h" + +#include + +#include + + +#if !defined(OPENSSL_C11_ATOMIC) + +OPENSSL_COMPILE_ASSERT((CRYPTO_refcount_t)-1 == CRYPTO_REFCOUNT_MAX, + CRYPTO_REFCOUNT_MAX_is_incorrect); + +static struct CRYPTO_STATIC_MUTEX g_refcount_lock = CRYPTO_STATIC_MUTEX_INIT; + +void CRYPTO_refcount_inc(CRYPTO_refcount_t *count) { + CRYPTO_STATIC_MUTEX_lock_write(&g_refcount_lock); + if (*count < CRYPTO_REFCOUNT_MAX) { + (*count)++; + } + CRYPTO_STATIC_MUTEX_unlock_write(&g_refcount_lock); +} + +int CRYPTO_refcount_dec_and_test_zero(CRYPTO_refcount_t *count) { + int ret; + + CRYPTO_STATIC_MUTEX_lock_write(&g_refcount_lock); + if (*count == 0) { + abort(); + } + if (*count < CRYPTO_REFCOUNT_MAX) { + (*count)--; + } + ret = (*count == 0); + CRYPTO_STATIC_MUTEX_unlock_write(&g_refcount_lock); + + return ret; +} + +#endif /* OPENSSL_C11_ATOMIC */ diff --git a/external/boringssl/crypto/refcount_test.c b/external/boringssl/crypto/refcount_test.c new file mode 100644 index 0000000000..97bfbd6fa1 --- /dev/null +++ b/external/boringssl/crypto/refcount_test.c @@ -0,0 +1,59 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include "internal.h" + +#include + +#include + + +int main(int argc, char **argv) { + CRYPTO_refcount_t count = 0; + + CRYPTO_refcount_inc(&count); + if (count != 1) { + fprintf(stderr, "Incrementing reference count did not work.\n"); + return 1; + } + if (!CRYPTO_refcount_dec_and_test_zero(&count) || count != 0) { + fprintf(stderr, "Decrementing reference count to zero did not work.\n"); + return 1; + } + + count = CRYPTO_REFCOUNT_MAX; + CRYPTO_refcount_inc(&count); + if (count != CRYPTO_REFCOUNT_MAX) { + fprintf(stderr, "Count did not saturate correctly when incrementing.\n"); + return 1; + } + if (CRYPTO_refcount_dec_and_test_zero(&count) || + count != CRYPTO_REFCOUNT_MAX) { + fprintf(stderr, "Count did not saturate correctly when decrementing.\n"); + return 1; + } + + count = 2; + if (CRYPTO_refcount_dec_and_test_zero(&count)) { + fprintf(stderr, "Decrementing two resulted in zero!\n"); + return 1; + } + if (count != 1) { + fprintf(stderr, "Decrementing two did not produce one!"); + return 1; + } + + printf("PASS\n"); + return 0; +} diff --git a/external/boringssl/crypto/rsa/CMakeLists.txt b/external/boringssl/crypto/rsa/CMakeLists.txt new file mode 100644 index 0000000000..23db9a7aae --- /dev/null +++ b/external/boringssl/crypto/rsa/CMakeLists.txt @@ -0,0 +1,26 @@ +include_directories(../../include) + +add_library( + rsa + + OBJECT + + rsa.c + rsa_impl.c + blinding.c + padding.c + rsa_asn1.c +) + +if(ENABLE_TESTS) +add_executable( + rsa_test + + rsa_test.cc + + $ +) + +target_link_libraries(rsa_test crypto) +add_dependencies(all_tests rsa_test) +endif() \ No newline at end of file diff --git a/external/boringssl/crypto/rsa/blinding.c b/external/boringssl/crypto/rsa/blinding.c new file mode 100644 index 0000000000..d9d90c2b47 --- /dev/null +++ b/external/boringssl/crypto/rsa/blinding.c @@ -0,0 +1,267 @@ +/* ==================================================================== + * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + * Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include +#include +#include + +#include "internal.h" + + +#define BN_BLINDING_COUNTER 32 + +struct bn_blinding_st { + BIGNUM *A; /* The base blinding factor, Montgomery-encoded. */ + BIGNUM *Ai; /* The inverse of the blinding factor, Montgomery-encoded. */ + unsigned counter; +}; + +static int bn_blinding_create_param(BN_BLINDING *b, const BIGNUM *e, + const BN_MONT_CTX *mont, BN_CTX *ctx); + +BN_BLINDING *BN_BLINDING_new(void) { + BN_BLINDING *ret = OPENSSL_malloc(sizeof(BN_BLINDING)); + if (ret == NULL) { + OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE); + return NULL; + } + memset(ret, 0, sizeof(BN_BLINDING)); + + ret->A = BN_new(); + if (ret->A == NULL) { + goto err; + } + + ret->Ai = BN_new(); + if (ret->Ai == NULL) { + goto err; + } + + /* The blinding values need to be created before this blinding can be used. */ + ret->counter = BN_BLINDING_COUNTER - 1; + + return ret; + +err: + BN_BLINDING_free(ret); + return NULL; +} + +void BN_BLINDING_free(BN_BLINDING *r) { + if (r == NULL) { + return; + } + + BN_free(r->A); + BN_free(r->Ai); + OPENSSL_free(r); +} + +static int bn_blinding_update(BN_BLINDING *b, const BIGNUM *e, + const BN_MONT_CTX *mont, BN_CTX *ctx) { + if (++b->counter == BN_BLINDING_COUNTER) { + /* re-create blinding parameters */ + if (!bn_blinding_create_param(b, e, mont, ctx)) { + goto err; + } + b->counter = 0; + } else { + if (!BN_mod_mul_montgomery(b->A, b->A, b->A, mont, ctx) || + !BN_mod_mul_montgomery(b->Ai, b->Ai, b->Ai, mont, ctx)) { + goto err; + } + } + + return 1; + +err: + /* |A| and |Ai| may be in an inconsistent state so they both need to be + * replaced the next time this blinding is used. Note that this is only + * sufficient because support for |BN_BLINDING_NO_UPDATE| and + * |BN_BLINDING_NO_RECREATE| was previously dropped. */ + b->counter = BN_BLINDING_COUNTER - 1; + + return 0; +} + +int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *b, const BIGNUM *e, + const BN_MONT_CTX *mont, BN_CTX *ctx) { + /* |n| is not Montgomery-encoded and |b->A| is. |BN_mod_mul_montgomery| + * cancels one Montgomery factor, so the resulting value of |n| is unencoded. + */ + if (!bn_blinding_update(b, e, mont, ctx) || + !BN_mod_mul_montgomery(n, n, b->A, mont, ctx)) { + return 0; + } + + return 1; +} + +int BN_BLINDING_invert(BIGNUM *n, const BN_BLINDING *b, BN_MONT_CTX *mont, + BN_CTX *ctx) { + /* |n| is not Montgomery-encoded and |b->A| is. |BN_mod_mul_montgomery| + * cancels one Montgomery factor, so the resulting value of |n| is unencoded. + */ + return BN_mod_mul_montgomery(n, n, b->Ai, mont, ctx); +} + +static int bn_blinding_create_param(BN_BLINDING *b, const BIGNUM *e, + const BN_MONT_CTX *mont, BN_CTX *ctx) { + BIGNUM mont_N_consttime; + BN_init(&mont_N_consttime); + BN_with_flags(&mont_N_consttime, &mont->N, BN_FLG_CONSTTIME); + int retry_counter = 32; + + do { + if (!BN_rand_range(b->A, &mont->N)) { + OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR); + return 0; + } + + /* |BN_from_montgomery| + |BN_mod_inverse_no_branch| is equivalent to, but + * more efficient than, |BN_mod_inverse_no_branch| + |BN_to_montgomery|. */ + if (!BN_from_montgomery(b->Ai, b->A, mont, ctx)) { + OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR); + return 0; + } + + int no_inverse; + if (BN_mod_inverse_ex(b->Ai, &no_inverse, b->Ai, &mont_N_consttime, ctx) == + NULL) { + /* this should almost never happen for good RSA keys */ + if (no_inverse) { + if (retry_counter-- == 0) { + OPENSSL_PUT_ERROR(RSA, RSA_R_TOO_MANY_ITERATIONS); + return 0; + } + ERR_clear_error(); + } else { + OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR); + return 0; + } + } else { + break; + } + } while (1); + + if (!BN_mod_exp_mont(b->A, b->A, e, &mont->N, ctx, mont)) { + OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR); + return 0; + } + + if (!BN_to_montgomery(b->A, b->A, mont, ctx)) { + OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR); + return 0; + } + + return 1; +} diff --git a/external/boringssl/crypto/rsa/internal.h b/external/boringssl/crypto/rsa/internal.h new file mode 100644 index 0000000000..c6ea97f09b --- /dev/null +++ b/external/boringssl/crypto/rsa/internal.h @@ -0,0 +1,148 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_RSA_INTERNAL_H +#define OPENSSL_HEADER_RSA_INTERNAL_H + +#include + + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* Default implementations of RSA operations. */ + +extern const RSA_METHOD RSA_default_method; + +size_t rsa_default_size(const RSA *rsa); +int rsa_default_encrypt(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out, + const uint8_t *in, size_t in_len, int padding); +int rsa_default_sign_raw(RSA *rsa, size_t *out_len, uint8_t *out, + size_t max_out, const uint8_t *in, size_t in_len, + int padding); +int rsa_default_decrypt(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out, + const uint8_t *in, size_t in_len, int padding); +int rsa_default_private_transform(RSA *rsa, uint8_t *out, const uint8_t *in, + size_t len); +int rsa_default_multi_prime_keygen(RSA *rsa, int bits, int num_primes, + BIGNUM *e_value, BN_GENCB *cb); +int rsa_default_keygen(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb); + + +#define RSA_PKCS1_PADDING_SIZE 11 + + +BN_BLINDING *BN_BLINDING_new(void); +void BN_BLINDING_free(BN_BLINDING *b); +int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *b, const BIGNUM *e, + const BN_MONT_CTX *mont_ctx, BN_CTX *ctx); +int BN_BLINDING_invert(BIGNUM *n, const BN_BLINDING *b, BN_MONT_CTX *mont_ctx, + BN_CTX *ctx); + + +int RSA_padding_add_PKCS1_type_1(uint8_t *to, unsigned to_len, + const uint8_t *from, unsigned from_len); +int RSA_padding_check_PKCS1_type_1(uint8_t *to, unsigned to_len, + const uint8_t *from, unsigned from_len); +int RSA_padding_add_PKCS1_type_2(uint8_t *to, unsigned to_len, + const uint8_t *from, unsigned from_len); +int RSA_padding_check_PKCS1_type_2(uint8_t *to, unsigned to_len, + const uint8_t *from, unsigned from_len); +int RSA_padding_add_PKCS1_OAEP_mgf1(uint8_t *to, unsigned to_len, + const uint8_t *from, unsigned from_len, + const uint8_t *param, unsigned plen, + const EVP_MD *md, const EVP_MD *mgf1md); +int RSA_padding_check_PKCS1_OAEP_mgf1(uint8_t *to, unsigned to_len, + const uint8_t *from, unsigned from_len, + const uint8_t *param, unsigned plen, + const EVP_MD *md, const EVP_MD *mgf1md); +int RSA_padding_add_none(uint8_t *to, unsigned to_len, const uint8_t *from, + unsigned from_len); + +/* RSA_private_transform calls either the method-specific |private_transform| + * function (if given) or the generic one. See the comment for + * |private_transform| in |rsa_meth_st|. */ +int RSA_private_transform(RSA *rsa, uint8_t *out, const uint8_t *in, + size_t len); + + +/* RSA_additional_prime contains information about the third, forth etc prime + * in a multi-prime RSA key. */ +typedef struct RSA_additional_prime_st { + BIGNUM *prime; + /* exp is d^{prime-1} mod prime */ + BIGNUM *exp; + /* coeff is such that r×coeff ≡ 1 mod prime. */ + BIGNUM *coeff; + + /* Values below here are not in the ASN.1 serialisation. */ + + /* r is the product of all primes (including p and q) prior to this one. */ + BIGNUM *r; + /* mont is a |BN_MONT_CTX| modulo |prime|. */ + BN_MONT_CTX *mont; +} RSA_additional_prime; + +void RSA_additional_prime_free(RSA_additional_prime *ap); + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_RSA_INTERNAL_H */ diff --git a/external/boringssl/crypto/rsa/padding.c b/external/boringssl/crypto/rsa/padding.c new file mode 100644 index 0000000000..12147ea4f8 --- /dev/null +++ b/external/boringssl/crypto/rsa/padding.c @@ -0,0 +1,706 @@ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 2005. + */ +/* ==================================================================== + * Copyright (c) 2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "internal.h" +#include "../internal.h" + +/* TODO(fork): don't the check functions have to be constant time? */ + +int RSA_padding_add_PKCS1_type_1(uint8_t *to, unsigned to_len, + const uint8_t *from, unsigned from_len) { + unsigned j; + + if (to_len < RSA_PKCS1_PADDING_SIZE) { + OPENSSL_PUT_ERROR(RSA, RSA_R_KEY_SIZE_TOO_SMALL); + return 0; + } + + if (from_len > to_len - RSA_PKCS1_PADDING_SIZE) { + OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE); + return 0; + } + + uint8_t *p = to; + + *(p++) = 0; + *(p++) = 1; /* Private Key BT (Block Type) */ + + /* pad out with 0xff data */ + j = to_len - 3 - from_len; + memset(p, 0xff, j); + p += j; + *(p++) = 0; + memcpy(p, from, from_len); + return 1; +} + +int RSA_padding_check_PKCS1_type_1(uint8_t *to, unsigned to_len, + const uint8_t *from, unsigned from_len) { + unsigned i, j; + const uint8_t *p; + + if (from_len < 2) { + OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_SMALL); + return -1; + } + + p = from; + if ((*(p++) != 0) || (*(p++) != 1)) { + OPENSSL_PUT_ERROR(RSA, RSA_R_BLOCK_TYPE_IS_NOT_01); + return -1; + } + + /* scan over padding data */ + j = from_len - 2; /* one for leading 00, one for type. */ + for (i = 0; i < j; i++) { + /* should decrypt to 0xff */ + if (*p != 0xff) { + if (*p == 0) { + p++; + break; + } else { + OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_FIXED_HEADER_DECRYPT); + return -1; + } + } + p++; + } + + if (i == j) { + OPENSSL_PUT_ERROR(RSA, RSA_R_NULL_BEFORE_BLOCK_MISSING); + return -1; + } + + if (i < 8) { + OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_PAD_BYTE_COUNT); + return -1; + } + i++; /* Skip over the '\0' */ + j -= i; + if (j > to_len) { + OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE); + return -1; + } + memcpy(to, p, j); + + return j; +} + +int RSA_padding_add_PKCS1_type_2(uint8_t *to, unsigned to_len, + const uint8_t *from, unsigned from_len) { + unsigned i, j; + + if (to_len < RSA_PKCS1_PADDING_SIZE) { + OPENSSL_PUT_ERROR(RSA, RSA_R_KEY_SIZE_TOO_SMALL); + return 0; + } + + if (from_len > to_len - RSA_PKCS1_PADDING_SIZE) { + OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE); + return 0; + } + + uint8_t *p = to; + + *(p++) = 0; + *(p++) = 2; /* Public Key BT (Block Type) */ + + /* pad out with non-zero random data */ + j = to_len - 3 - from_len; + + if (!RAND_bytes(p, j)) { + return 0; + } + + for (i = 0; i < j; i++) { + while (*p == 0) { + if (!RAND_bytes(p, 1)) { + return 0; + } + } + p++; + } + + *(p++) = 0; + + memcpy(p, from, from_len); + return 1; +} + +int RSA_padding_check_PKCS1_type_2(uint8_t *to, unsigned to_len, + const uint8_t *from, unsigned from_len) { + if (from_len == 0) { + OPENSSL_PUT_ERROR(RSA, RSA_R_EMPTY_PUBLIC_KEY); + return -1; + } + + /* PKCS#1 v1.5 decryption. See "PKCS #1 v2.2: RSA Cryptography + * Standard", section 7.2.2. */ + if (from_len < RSA_PKCS1_PADDING_SIZE) { + /* |from| is zero-padded to the size of the RSA modulus, a public value, so + * this can be rejected in non-constant time. */ + OPENSSL_PUT_ERROR(RSA, RSA_R_KEY_SIZE_TOO_SMALL); + return -1; + } + + unsigned first_byte_is_zero = constant_time_eq(from[0], 0); + unsigned second_byte_is_two = constant_time_eq(from[1], 2); + + unsigned i, zero_index = 0, looking_for_index = ~0u; + for (i = 2; i < from_len; i++) { + unsigned equals0 = constant_time_is_zero(from[i]); + zero_index = constant_time_select(looking_for_index & equals0, (unsigned)i, + zero_index); + looking_for_index = constant_time_select(equals0, 0, looking_for_index); + } + + /* The input must begin with 00 02. */ + unsigned valid_index = first_byte_is_zero; + valid_index &= second_byte_is_two; + + /* We must have found the end of PS. */ + valid_index &= ~looking_for_index; + + /* PS must be at least 8 bytes long, and it starts two bytes into |from|. */ + valid_index &= constant_time_ge(zero_index, 2 + 8); + + /* Skip the zero byte. */ + zero_index++; + + /* NOTE: Although this logic attempts to be constant time, the API contracts + * of this function and |RSA_decrypt| with |RSA_PKCS1_PADDING| make it + * impossible to completely avoid Bleichenbacher's attack. Consumers should + * use |RSA_unpad_key_pkcs1|. */ + if (!valid_index) { + OPENSSL_PUT_ERROR(RSA, RSA_R_PKCS_DECODING_ERROR); + return -1; + } + + const unsigned msg_len = from_len - zero_index; + if (msg_len > to_len) { + /* This shouldn't happen because this function is always called with + * |to_len| as the key size and |from_len| is bounded by the key size. */ + OPENSSL_PUT_ERROR(RSA, RSA_R_PKCS_DECODING_ERROR); + return -1; + } + + if (msg_len > INT_MAX) { + OPENSSL_PUT_ERROR(RSA, ERR_R_OVERFLOW); + return -1; + } + + memcpy(to, &from[zero_index], msg_len); + return (int)msg_len; +} + +int RSA_padding_add_none(uint8_t *to, unsigned to_len, const uint8_t *from, + unsigned from_len) { + if (from_len > to_len) { + OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE); + return 0; + } + + if (from_len < to_len) { + OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_SMALL_FOR_KEY_SIZE); + return 0; + } + + memcpy(to, from, from_len); + return 1; +} + +static int PKCS1_MGF1(uint8_t *mask, unsigned len, const uint8_t *seed, + unsigned seedlen, const EVP_MD *dgst) { + unsigned outlen = 0; + uint32_t i; + uint8_t cnt[4]; + EVP_MD_CTX c; + uint8_t md[EVP_MAX_MD_SIZE]; + unsigned mdlen; + int ret = -1; + + EVP_MD_CTX_init(&c); + mdlen = EVP_MD_size(dgst); + + for (i = 0; outlen < len; i++) { + cnt[0] = (uint8_t)((i >> 24) & 255); + cnt[1] = (uint8_t)((i >> 16) & 255); + cnt[2] = (uint8_t)((i >> 8)) & 255; + cnt[3] = (uint8_t)(i & 255); + if (!EVP_DigestInit_ex(&c, dgst, NULL) || + !EVP_DigestUpdate(&c, seed, seedlen) || + !EVP_DigestUpdate(&c, cnt, 4)) { + goto err; + } + + if (outlen + mdlen <= len) { + if (!EVP_DigestFinal_ex(&c, mask + outlen, NULL)) { + goto err; + } + outlen += mdlen; + } else { + if (!EVP_DigestFinal_ex(&c, md, NULL)) { + goto err; + } + memcpy(mask + outlen, md, len - outlen); + outlen = len; + } + } + ret = 0; + +err: + EVP_MD_CTX_cleanup(&c); + return ret; +} + +int RSA_padding_add_PKCS1_OAEP_mgf1(uint8_t *to, unsigned to_len, + const uint8_t *from, unsigned from_len, + const uint8_t *param, unsigned param_len, + const EVP_MD *md, const EVP_MD *mgf1md) { + unsigned i, emlen, mdlen; + uint8_t *db, *seed; + uint8_t *dbmask = NULL, seedmask[EVP_MAX_MD_SIZE]; + int ret = 0; + + if (md == NULL) { + md = EVP_sha1(); + } + if (mgf1md == NULL) { + mgf1md = md; + } + + mdlen = EVP_MD_size(md); + + if (to_len < 2 * mdlen + 2) { + OPENSSL_PUT_ERROR(RSA, RSA_R_KEY_SIZE_TOO_SMALL); + return 0; + } + + emlen = to_len - 1; + if (from_len > emlen - 2 * mdlen - 1) { + OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE); + return 0; + } + + if (emlen < 2 * mdlen + 1) { + OPENSSL_PUT_ERROR(RSA, RSA_R_KEY_SIZE_TOO_SMALL); + return 0; + } + + to[0] = 0; + seed = to + 1; + db = to + mdlen + 1; + + if (!EVP_Digest(param, param_len, db, NULL, md, NULL)) { + return 0; + } + memset(db + mdlen, 0, emlen - from_len - 2 * mdlen - 1); + db[emlen - from_len - mdlen - 1] = 0x01; + memcpy(db + emlen - from_len - mdlen, from, from_len); + if (!RAND_bytes(seed, mdlen)) { + return 0; + } + + dbmask = OPENSSL_malloc(emlen - mdlen); + if (dbmask == NULL) { + OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE); + return 0; + } + + if (PKCS1_MGF1(dbmask, emlen - mdlen, seed, mdlen, mgf1md) < 0) { + goto out; + } + for (i = 0; i < emlen - mdlen; i++) { + db[i] ^= dbmask[i]; + } + + if (PKCS1_MGF1(seedmask, mdlen, db, emlen - mdlen, mgf1md) < 0) { + goto out; + } + for (i = 0; i < mdlen; i++) { + seed[i] ^= seedmask[i]; + } + ret = 1; + +out: + OPENSSL_free(dbmask); + return ret; +} + +int RSA_padding_check_PKCS1_OAEP_mgf1(uint8_t *to, unsigned to_len, + const uint8_t *from, unsigned from_len, + const uint8_t *param, unsigned param_len, + const EVP_MD *md, const EVP_MD *mgf1md) { + unsigned i, dblen, mlen = -1, mdlen, bad, looking_for_one_byte, one_index = 0; + const uint8_t *maskeddb, *maskedseed; + uint8_t *db = NULL, seed[EVP_MAX_MD_SIZE], phash[EVP_MAX_MD_SIZE]; + + if (md == NULL) { + md = EVP_sha1(); + } + if (mgf1md == NULL) { + mgf1md = md; + } + + mdlen = EVP_MD_size(md); + + /* The encoded message is one byte smaller than the modulus to ensure that it + * doesn't end up greater than the modulus. Thus there's an extra "+1" here + * compared to https://tools.ietf.org/html/rfc2437#section-9.1.1.2. */ + if (from_len < 1 + 2*mdlen + 1) { + /* 'from_len' is the length of the modulus, i.e. does not depend on the + * particular ciphertext. */ + goto decoding_err; + } + + dblen = from_len - mdlen - 1; + db = OPENSSL_malloc(dblen); + if (db == NULL) { + OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE); + goto err; + } + + maskedseed = from + 1; + maskeddb = from + 1 + mdlen; + + if (PKCS1_MGF1(seed, mdlen, maskeddb, dblen, mgf1md)) { + goto err; + } + for (i = 0; i < mdlen; i++) { + seed[i] ^= maskedseed[i]; + } + + if (PKCS1_MGF1(db, dblen, seed, mdlen, mgf1md)) { + goto err; + } + for (i = 0; i < dblen; i++) { + db[i] ^= maskeddb[i]; + } + + if (!EVP_Digest(param, param_len, phash, NULL, md, NULL)) { + goto err; + } + + bad = ~constant_time_is_zero(CRYPTO_memcmp(db, phash, mdlen)); + bad |= ~constant_time_is_zero(from[0]); + + looking_for_one_byte = ~0u; + for (i = mdlen; i < dblen; i++) { + unsigned equals1 = constant_time_eq(db[i], 1); + unsigned equals0 = constant_time_eq(db[i], 0); + one_index = constant_time_select(looking_for_one_byte & equals1, i, + one_index); + looking_for_one_byte = + constant_time_select(equals1, 0, looking_for_one_byte); + bad |= looking_for_one_byte & ~equals0; + } + + bad |= looking_for_one_byte; + + if (bad) { + goto decoding_err; + } + + one_index++; + mlen = dblen - one_index; + if (to_len < mlen) { + OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE); + mlen = -1; + } else { + memcpy(to, db + one_index, mlen); + } + + OPENSSL_free(db); + return mlen; + +decoding_err: + /* to avoid chosen ciphertext attacks, the error message should not reveal + * which kind of decoding error happened */ + OPENSSL_PUT_ERROR(RSA, RSA_R_OAEP_DECODING_ERROR); + err: + OPENSSL_free(db); + return -1; +} + +static const unsigned char zeroes[] = {0,0,0,0,0,0,0,0}; + +int RSA_verify_PKCS1_PSS_mgf1(RSA *rsa, const uint8_t *mHash, + const EVP_MD *Hash, const EVP_MD *mgf1Hash, + const uint8_t *EM, int sLen) { + int i; + int ret = 0; + int maskedDBLen, MSBits, emLen; + size_t hLen; + const uint8_t *H; + uint8_t *DB = NULL; + EVP_MD_CTX ctx; + uint8_t H_[EVP_MAX_MD_SIZE]; + EVP_MD_CTX_init(&ctx); + + if (mgf1Hash == NULL) { + mgf1Hash = Hash; + } + + hLen = EVP_MD_size(Hash); + + /* Negative sLen has special meanings: + * -1 sLen == hLen + * -2 salt length is autorecovered from signature + * -N reserved */ + if (sLen == -1) { + sLen = hLen; + } else if (sLen == -2) { + sLen = -2; + } else if (sLen < -2) { + OPENSSL_PUT_ERROR(RSA, RSA_R_SLEN_CHECK_FAILED); + goto err; + } + + MSBits = (BN_num_bits(rsa->n) - 1) & 0x7; + emLen = RSA_size(rsa); + if (EM[0] & (0xFF << MSBits)) { + OPENSSL_PUT_ERROR(RSA, RSA_R_FIRST_OCTET_INVALID); + goto err; + } + if (MSBits == 0) { + EM++; + emLen--; + } + if (emLen < ((int)hLen + sLen + 2)) { + /* sLen can be small negative */ + OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE); + goto err; + } + if (EM[emLen - 1] != 0xbc) { + OPENSSL_PUT_ERROR(RSA, RSA_R_LAST_OCTET_INVALID); + goto err; + } + maskedDBLen = emLen - hLen - 1; + H = EM + maskedDBLen; + DB = OPENSSL_malloc(maskedDBLen); + if (!DB) { + OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE); + goto err; + } + if (PKCS1_MGF1(DB, maskedDBLen, H, hLen, mgf1Hash) < 0) { + goto err; + } + for (i = 0; i < maskedDBLen; i++) { + DB[i] ^= EM[i]; + } + if (MSBits) { + DB[0] &= 0xFF >> (8 - MSBits); + } + for (i = 0; DB[i] == 0 && i < (maskedDBLen - 1); i++) { + ; + } + if (DB[i++] != 0x1) { + OPENSSL_PUT_ERROR(RSA, RSA_R_SLEN_RECOVERY_FAILED); + goto err; + } + if (sLen >= 0 && (maskedDBLen - i) != sLen) { + OPENSSL_PUT_ERROR(RSA, RSA_R_SLEN_CHECK_FAILED); + goto err; + } + if (!EVP_DigestInit_ex(&ctx, Hash, NULL) || + !EVP_DigestUpdate(&ctx, zeroes, sizeof zeroes) || + !EVP_DigestUpdate(&ctx, mHash, hLen)) { + goto err; + } + if (maskedDBLen - i) { + if (!EVP_DigestUpdate(&ctx, DB + i, maskedDBLen - i)) { + goto err; + } + } + if (!EVP_DigestFinal_ex(&ctx, H_, NULL)) { + goto err; + } + if (memcmp(H_, H, hLen)) { + OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_SIGNATURE); + ret = 0; + } else { + ret = 1; + } + +err: + OPENSSL_free(DB); + EVP_MD_CTX_cleanup(&ctx); + + return ret; +} + +int RSA_padding_add_PKCS1_PSS_mgf1(RSA *rsa, unsigned char *EM, + const unsigned char *mHash, + const EVP_MD *Hash, const EVP_MD *mgf1Hash, + int sLen) { + int i; + int ret = 0; + size_t maskedDBLen, MSBits, emLen; + size_t hLen; + unsigned char *H, *salt = NULL, *p; + EVP_MD_CTX ctx; + + if (mgf1Hash == NULL) { + mgf1Hash = Hash; + } + + hLen = EVP_MD_size(Hash); + + /* Negative sLen has special meanings: + * -1 sLen == hLen + * -2 salt length is maximized + * -N reserved */ + if (sLen == -1) { + sLen = hLen; + } else if (sLen == -2) { + sLen = -2; + } else if (sLen < -2) { + OPENSSL_PUT_ERROR(RSA, RSA_R_SLEN_CHECK_FAILED); + goto err; + } + + if (BN_is_zero(rsa->n)) { + OPENSSL_PUT_ERROR(RSA, RSA_R_EMPTY_PUBLIC_KEY); + goto err; + } + + MSBits = (BN_num_bits(rsa->n) - 1) & 0x7; + emLen = RSA_size(rsa); + if (MSBits == 0) { + assert(emLen >= 1); + *EM++ = 0; + emLen--; + } + if (sLen == -2) { + if (emLen < hLen + 2) { + OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE); + goto err; + } + sLen = emLen - hLen - 2; + } else if (emLen < hLen + sLen + 2) { + OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE); + goto err; + } + if (sLen > 0) { + salt = OPENSSL_malloc(sLen); + if (!salt) { + OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE); + goto err; + } + if (!RAND_bytes(salt, sLen)) { + goto err; + } + } + maskedDBLen = emLen - hLen - 1; + H = EM + maskedDBLen; + EVP_MD_CTX_init(&ctx); + if (!EVP_DigestInit_ex(&ctx, Hash, NULL) || + !EVP_DigestUpdate(&ctx, zeroes, sizeof zeroes) || + !EVP_DigestUpdate(&ctx, mHash, hLen)) { + goto err; + } + if (sLen && !EVP_DigestUpdate(&ctx, salt, sLen)) { + goto err; + } + if (!EVP_DigestFinal_ex(&ctx, H, NULL)) { + goto err; + } + EVP_MD_CTX_cleanup(&ctx); + + /* Generate dbMask in place then perform XOR on it */ + if (PKCS1_MGF1(EM, maskedDBLen, H, hLen, mgf1Hash)) { + goto err; + } + + p = EM; + + /* Initial PS XORs with all zeroes which is a NOP so just update + * pointer. Note from a test above this value is guaranteed to + * be non-negative. */ + p += emLen - sLen - hLen - 2; + *p++ ^= 0x1; + if (sLen > 0) { + for (i = 0; i < sLen; i++) { + *p++ ^= salt[i]; + } + } + if (MSBits) { + EM[0] &= 0xFF >> (8 - MSBits); + } + + /* H is already in place so just set final 0xbc */ + + EM[emLen - 1] = 0xbc; + + ret = 1; + +err: + OPENSSL_free(salt); + + return ret; +} diff --git a/external/boringssl/crypto/rsa/rsa.c b/external/boringssl/crypto/rsa/rsa.c new file mode 100644 index 0000000000..e5f98916fb --- /dev/null +++ b/external/boringssl/crypto/rsa/rsa.c @@ -0,0 +1,794 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "internal.h" +#include "../internal.h" + + +static CRYPTO_EX_DATA_CLASS g_ex_data_class = CRYPTO_EX_DATA_CLASS_INIT; + +RSA *RSA_new(void) { return RSA_new_method(NULL); } + +RSA *RSA_new_method(const ENGINE *engine) { + RSA *rsa = OPENSSL_malloc(sizeof(RSA)); + if (rsa == NULL) { + OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE); + return NULL; + } + + memset(rsa, 0, sizeof(RSA)); + + if (engine) { + rsa->meth = ENGINE_get_RSA_method(engine); + } + + if (rsa->meth == NULL) { + rsa->meth = (RSA_METHOD*) &RSA_default_method; + } + METHOD_ref(rsa->meth); + + rsa->references = 1; + rsa->flags = rsa->meth->flags; + CRYPTO_MUTEX_init(&rsa->lock); + CRYPTO_new_ex_data(&rsa->ex_data); + + if (rsa->meth->init && !rsa->meth->init(rsa)) { + CRYPTO_free_ex_data(&g_ex_data_class, rsa, &rsa->ex_data); + CRYPTO_MUTEX_cleanup(&rsa->lock); + METHOD_unref(rsa->meth); + OPENSSL_free(rsa); + return NULL; + } + + return rsa; +} + +void RSA_additional_prime_free(RSA_additional_prime *ap) { + if (ap == NULL) { + return; + } + + BN_clear_free(ap->prime); + BN_clear_free(ap->exp); + BN_clear_free(ap->coeff); + BN_clear_free(ap->r); + BN_MONT_CTX_free(ap->mont); + OPENSSL_free(ap); +} + +void RSA_free(RSA *rsa) { + unsigned u; + + if (rsa == NULL) { + return; + } + + if (!CRYPTO_refcount_dec_and_test_zero(&rsa->references)) { + return; + } + + if (rsa->meth->finish) { + rsa->meth->finish(rsa); + } + METHOD_unref(rsa->meth); + + CRYPTO_free_ex_data(&g_ex_data_class, rsa, &rsa->ex_data); + + BN_clear_free(rsa->n); + BN_clear_free(rsa->e); + BN_clear_free(rsa->d); + BN_clear_free(rsa->p); + BN_clear_free(rsa->q); + BN_clear_free(rsa->dmp1); + BN_clear_free(rsa->dmq1); + BN_clear_free(rsa->iqmp); + BN_MONT_CTX_free(rsa->mont_n); + BN_MONT_CTX_free(rsa->mont_p); + BN_MONT_CTX_free(rsa->mont_q); + for (u = 0; u < rsa->num_blindings; u++) { + BN_BLINDING_free(rsa->blindings[u]); + } + OPENSSL_free(rsa->blindings); + OPENSSL_free(rsa->blindings_inuse); + if (rsa->additional_primes != NULL) { + sk_RSA_additional_prime_pop_free(rsa->additional_primes, + RSA_additional_prime_free); + } + CRYPTO_MUTEX_cleanup(&rsa->lock); + OPENSSL_free(rsa); +} + +int RSA_up_ref(RSA *rsa) { + CRYPTO_refcount_inc(&rsa->references); + return 1; +} + +int RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb) { + if (rsa->meth->keygen) { + return rsa->meth->keygen(rsa, bits, e_value, cb); + } + + return rsa_default_keygen(rsa, bits, e_value, cb); +} + +int RSA_generate_multi_prime_key(RSA *rsa, int bits, int num_primes, + BIGNUM *e_value, BN_GENCB *cb) { + if (rsa->meth->multi_prime_keygen) { + return rsa->meth->multi_prime_keygen(rsa, bits, num_primes, e_value, cb); + } + + return rsa_default_multi_prime_keygen(rsa, bits, num_primes, e_value, cb); +} + +int RSA_encrypt(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out, + const uint8_t *in, size_t in_len, int padding) { + if (rsa->meth->encrypt) { + return rsa->meth->encrypt(rsa, out_len, out, max_out, in, in_len, padding); + } + + return rsa_default_encrypt(rsa, out_len, out, max_out, in, in_len, padding); +} + +int RSA_public_encrypt(size_t flen, const uint8_t *from, uint8_t *to, RSA *rsa, + int padding) { + size_t out_len; + + if (!RSA_encrypt(rsa, &out_len, to, RSA_size(rsa), from, flen, padding)) { + return -1; + } + + if (out_len > INT_MAX) { + OPENSSL_PUT_ERROR(RSA, ERR_R_OVERFLOW); + return -1; + } + return out_len; +} + +int RSA_sign_raw(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out, + const uint8_t *in, size_t in_len, int padding) { + if (rsa->meth->sign_raw) { + return rsa->meth->sign_raw(rsa, out_len, out, max_out, in, in_len, padding); + } + + return rsa_default_sign_raw(rsa, out_len, out, max_out, in, in_len, padding); +} + +int RSA_private_encrypt(size_t flen, const uint8_t *from, uint8_t *to, RSA *rsa, + int padding) { + size_t out_len; + + if (!RSA_sign_raw(rsa, &out_len, to, RSA_size(rsa), from, flen, padding)) { + return -1; + } + + if (out_len > INT_MAX) { + OPENSSL_PUT_ERROR(RSA, ERR_R_OVERFLOW); + return -1; + } + return out_len; +} + +int RSA_decrypt(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out, + const uint8_t *in, size_t in_len, int padding) { + if (rsa->meth->decrypt) { + return rsa->meth->decrypt(rsa, out_len, out, max_out, in, in_len, padding); + } + + return rsa_default_decrypt(rsa, out_len, out, max_out, in, in_len, padding); +} + +int RSA_private_decrypt(size_t flen, const uint8_t *from, uint8_t *to, RSA *rsa, + int padding) { + size_t out_len; + + if (!RSA_decrypt(rsa, &out_len, to, RSA_size(rsa), from, flen, padding)) { + return -1; + } + + if (out_len > INT_MAX) { + OPENSSL_PUT_ERROR(RSA, ERR_R_OVERFLOW); + return -1; + } + return out_len; +} + +int RSA_public_decrypt(size_t flen, const uint8_t *from, uint8_t *to, RSA *rsa, + int padding) { + size_t out_len; + + if (!RSA_verify_raw(rsa, &out_len, to, RSA_size(rsa), from, flen, padding)) { + return -1; + } + + if (out_len > INT_MAX) { + OPENSSL_PUT_ERROR(RSA, ERR_R_OVERFLOW); + return -1; + } + return out_len; +} + +unsigned RSA_size(const RSA *rsa) { + if (rsa->meth->size) { + return rsa->meth->size(rsa); + } + + return rsa_default_size(rsa); +} + +int RSA_is_opaque(const RSA *rsa) { + return rsa->meth && (rsa->meth->flags & RSA_FLAG_OPAQUE); +} + +int RSA_supports_digest(const RSA *rsa, const EVP_MD *md) { + if (rsa->meth && rsa->meth->supports_digest) { + return rsa->meth->supports_digest(rsa, md); + } + return 1; +} + +int RSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_unused *unused, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) { + int index; + if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp, dup_func, + free_func)) { + return -1; + } + return index; +} + +int RSA_set_ex_data(RSA *d, int idx, void *arg) { + return CRYPTO_set_ex_data(&d->ex_data, idx, arg); +} + +void *RSA_get_ex_data(const RSA *d, int idx) { + return CRYPTO_get_ex_data(&d->ex_data, idx); +} + +/* SSL_SIG_LENGTH is the size of an SSL/TLS (prior to TLS 1.2) signature: it's + * the length of an MD5 and SHA1 hash. */ +static const unsigned SSL_SIG_LENGTH = 36; + +/* pkcs1_sig_prefix contains the ASN.1, DER encoded prefix for a hash that is + * to be signed with PKCS#1. */ +struct pkcs1_sig_prefix { + /* nid identifies the hash function. */ + int nid; + /* len is the number of bytes of |bytes| which are valid. */ + uint8_t len; + /* bytes contains the DER bytes. */ + uint8_t bytes[19]; +}; + +/* kPKCS1SigPrefixes contains the ASN.1 prefixes for PKCS#1 signatures with + * different hash functions. */ +static const struct pkcs1_sig_prefix kPKCS1SigPrefixes[] = { + { + NID_md5, + 18, + {0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x02, 0x05, 0x05, 0x00, 0x04, 0x10}, + }, + { + NID_sha1, + 15, + {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, + 0x00, 0x04, 0x14}, + }, + { + NID_sha224, + 19, + {0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, + 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1c}, + }, + { + NID_sha256, + 19, + {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, + 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20}, + }, + { + NID_sha384, + 19, + {0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, + 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30}, + }, + { + NID_sha512, + 19, + {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, + 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40}, + }, + { + NID_undef, 0, {0}, + }, +}; + +int RSA_add_pkcs1_prefix(uint8_t **out_msg, size_t *out_msg_len, + int *is_alloced, int hash_nid, const uint8_t *msg, + size_t msg_len) { + unsigned i; + + if (hash_nid == NID_md5_sha1) { + /* Special case: SSL signature, just check the length. */ + if (msg_len != SSL_SIG_LENGTH) { + OPENSSL_PUT_ERROR(RSA, RSA_R_INVALID_MESSAGE_LENGTH); + return 0; + } + + *out_msg = (uint8_t*) msg; + *out_msg_len = SSL_SIG_LENGTH; + *is_alloced = 0; + return 1; + } + + for (i = 0; kPKCS1SigPrefixes[i].nid != NID_undef; i++) { + const struct pkcs1_sig_prefix *sig_prefix = &kPKCS1SigPrefixes[i]; + if (sig_prefix->nid != hash_nid) { + continue; + } + + const uint8_t* prefix = sig_prefix->bytes; + unsigned prefix_len = sig_prefix->len; + unsigned signed_msg_len; + uint8_t *signed_msg; + + signed_msg_len = prefix_len + msg_len; + if (signed_msg_len < prefix_len) { + OPENSSL_PUT_ERROR(RSA, RSA_R_TOO_LONG); + return 0; + } + + signed_msg = OPENSSL_malloc(signed_msg_len); + if (!signed_msg) { + OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE); + return 0; + } + + memcpy(signed_msg, prefix, prefix_len); + memcpy(signed_msg + prefix_len, msg, msg_len); + + *out_msg = signed_msg; + *out_msg_len = signed_msg_len; + *is_alloced = 1; + + return 1; + } + + OPENSSL_PUT_ERROR(RSA, RSA_R_UNKNOWN_ALGORITHM_TYPE); + return 0; +} + +int RSA_sign(int hash_nid, const uint8_t *in, unsigned in_len, uint8_t *out, + unsigned *out_len, RSA *rsa) { + const unsigned rsa_size = RSA_size(rsa); + int ret = 0; + uint8_t *signed_msg; + size_t signed_msg_len; + int signed_msg_is_alloced = 0; + size_t size_t_out_len; + + if (rsa->meth->sign) { + return rsa->meth->sign(hash_nid, in, in_len, out, out_len, rsa); + } + + if (!RSA_add_pkcs1_prefix(&signed_msg, &signed_msg_len, + &signed_msg_is_alloced, hash_nid, in, in_len)) { + return 0; + } + + if (rsa_size < RSA_PKCS1_PADDING_SIZE || + signed_msg_len > rsa_size - RSA_PKCS1_PADDING_SIZE) { + OPENSSL_PUT_ERROR(RSA, RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY); + goto finish; + } + + if (RSA_sign_raw(rsa, &size_t_out_len, out, rsa_size, signed_msg, + signed_msg_len, RSA_PKCS1_PADDING)) { + *out_len = size_t_out_len; + ret = 1; + } + +finish: + if (signed_msg_is_alloced) { + OPENSSL_free(signed_msg); + } + return ret; +} + +int RSA_verify(int hash_nid, const uint8_t *msg, size_t msg_len, + const uint8_t *sig, size_t sig_len, RSA *rsa) { + if (rsa->n == NULL || rsa->e == NULL) { + OPENSSL_PUT_ERROR(RSA, RSA_R_VALUE_MISSING); + return 0; + } + + const size_t rsa_size = RSA_size(rsa); + uint8_t *buf = NULL; + int ret = 0; + uint8_t *signed_msg = NULL; + size_t signed_msg_len, len; + int signed_msg_is_alloced = 0; + + if (hash_nid == NID_md5_sha1 && msg_len != SSL_SIG_LENGTH) { + OPENSSL_PUT_ERROR(RSA, RSA_R_INVALID_MESSAGE_LENGTH); + return 0; + } + + buf = OPENSSL_malloc(rsa_size); + if (!buf) { + OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE); + return 0; + } + + if (!RSA_verify_raw(rsa, &len, buf, rsa_size, sig, sig_len, + RSA_PKCS1_PADDING)) { + goto out; + } + + if (!RSA_add_pkcs1_prefix(&signed_msg, &signed_msg_len, + &signed_msg_is_alloced, hash_nid, msg, msg_len)) { + goto out; + } + + if (len != signed_msg_len || memcmp(buf, signed_msg, len) != 0) { + OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_SIGNATURE); + goto out; + } + + ret = 1; + +out: + OPENSSL_free(buf); + if (signed_msg_is_alloced) { + OPENSSL_free(signed_msg); + } + return ret; +} + +static void bn_free_and_null(BIGNUM **bn) { + BN_free(*bn); + *bn = NULL; +} + +int RSA_check_key(const RSA *key) { + BIGNUM n, pm1, qm1, lcm, gcd, de, dmp1, dmq1, iqmp; + BN_CTX *ctx; + int ok = 0, has_crt_values; + + if (RSA_is_opaque(key)) { + /* Opaque keys can't be checked. */ + return 1; + } + + if ((key->p != NULL) != (key->q != NULL)) { + OPENSSL_PUT_ERROR(RSA, RSA_R_ONLY_ONE_OF_P_Q_GIVEN); + return 0; + } + + if (!key->n || !key->e) { + OPENSSL_PUT_ERROR(RSA, RSA_R_VALUE_MISSING); + return 0; + } + + if (!key->d || !key->p) { + /* For a public key, or without p and q, there's nothing that can be + * checked. */ + return 1; + } + + ctx = BN_CTX_new(); + if (ctx == NULL) { + OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE); + return 0; + } + + BN_init(&n); + BN_init(&pm1); + BN_init(&qm1); + BN_init(&lcm); + BN_init(&gcd); + BN_init(&de); + BN_init(&dmp1); + BN_init(&dmq1); + BN_init(&iqmp); + + if (!BN_mul(&n, key->p, key->q, ctx) || + /* lcm = lcm(prime-1, for all primes) */ + !BN_sub(&pm1, key->p, BN_value_one()) || + !BN_sub(&qm1, key->q, BN_value_one()) || + !BN_mul(&lcm, &pm1, &qm1, ctx) || + !BN_gcd(&gcd, &pm1, &qm1, ctx)) { + OPENSSL_PUT_ERROR(RSA, ERR_LIB_BN); + goto out; + } + + size_t num_additional_primes = 0; + if (key->additional_primes != NULL) { + num_additional_primes = sk_RSA_additional_prime_num(key->additional_primes); + } + + size_t i; + for (i = 0; i < num_additional_primes; i++) { + const RSA_additional_prime *ap = + sk_RSA_additional_prime_value(key->additional_primes, i); + if (!BN_mul(&n, &n, ap->prime, ctx) || + !BN_sub(&pm1, ap->prime, BN_value_one()) || + !BN_mul(&lcm, &lcm, &pm1, ctx) || + !BN_gcd(&gcd, &gcd, &pm1, ctx)) { + OPENSSL_PUT_ERROR(RSA, ERR_LIB_BN); + goto out; + } + } + + if (!BN_div(&lcm, NULL, &lcm, &gcd, ctx) || + !BN_gcd(&gcd, &pm1, &qm1, ctx) || + /* de = d*e mod lcm(prime-1, for all primes). */ + !BN_mod_mul(&de, key->d, key->e, &lcm, ctx)) { + OPENSSL_PUT_ERROR(RSA, ERR_LIB_BN); + goto out; + } + + if (BN_cmp(&n, key->n) != 0) { + OPENSSL_PUT_ERROR(RSA, RSA_R_N_NOT_EQUAL_P_Q); + goto out; + } + + if (!BN_is_one(&de)) { + OPENSSL_PUT_ERROR(RSA, RSA_R_D_E_NOT_CONGRUENT_TO_1); + goto out; + } + + has_crt_values = key->dmp1 != NULL; + if (has_crt_values != (key->dmq1 != NULL) || + has_crt_values != (key->iqmp != NULL)) { + OPENSSL_PUT_ERROR(RSA, RSA_R_INCONSISTENT_SET_OF_CRT_VALUES); + goto out; + } + + if (has_crt_values && num_additional_primes == 0) { + if (/* dmp1 = d mod (p-1) */ + !BN_mod(&dmp1, key->d, &pm1, ctx) || + /* dmq1 = d mod (q-1) */ + !BN_mod(&dmq1, key->d, &qm1, ctx) || + /* iqmp = q^-1 mod p */ + !BN_mod_inverse(&iqmp, key->q, key->p, ctx)) { + OPENSSL_PUT_ERROR(RSA, ERR_LIB_BN); + goto out; + } + + if (BN_cmp(&dmp1, key->dmp1) != 0 || + BN_cmp(&dmq1, key->dmq1) != 0 || + BN_cmp(&iqmp, key->iqmp) != 0) { + OPENSSL_PUT_ERROR(RSA, RSA_R_CRT_VALUES_INCORRECT); + goto out; + } + } + + ok = 1; + +out: + BN_free(&n); + BN_free(&pm1); + BN_free(&qm1); + BN_free(&lcm); + BN_free(&gcd); + BN_free(&de); + BN_free(&dmp1); + BN_free(&dmq1); + BN_free(&iqmp); + BN_CTX_free(ctx); + + return ok; +} + +int RSA_recover_crt_params(RSA *rsa) { + BN_CTX *ctx; + BIGNUM *totient, *rem, *multiple, *p_plus_q, *p_minus_q; + int ok = 0; + + if (rsa->n == NULL || rsa->e == NULL || rsa->d == NULL) { + OPENSSL_PUT_ERROR(RSA, RSA_R_EMPTY_PUBLIC_KEY); + return 0; + } + + if (rsa->p || rsa->q || rsa->dmp1 || rsa->dmq1 || rsa->iqmp) { + OPENSSL_PUT_ERROR(RSA, RSA_R_CRT_PARAMS_ALREADY_GIVEN); + return 0; + } + + if (rsa->additional_primes != NULL) { + OPENSSL_PUT_ERROR(RSA, RSA_R_CANNOT_RECOVER_MULTI_PRIME_KEY); + return 0; + } + + /* This uses the algorithm from section 9B of the RSA paper: + * http://people.csail.mit.edu/rivest/Rsapaper.pdf */ + + ctx = BN_CTX_new(); + if (ctx == NULL) { + OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE); + return 0; + } + + BN_CTX_start(ctx); + totient = BN_CTX_get(ctx); + rem = BN_CTX_get(ctx); + multiple = BN_CTX_get(ctx); + p_plus_q = BN_CTX_get(ctx); + p_minus_q = BN_CTX_get(ctx); + + if (totient == NULL || rem == NULL || multiple == NULL || p_plus_q == NULL || + p_minus_q == NULL) { + OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE); + goto err; + } + + /* ed-1 is a small multiple of φ(n). */ + if (!BN_mul(totient, rsa->e, rsa->d, ctx) || + !BN_sub_word(totient, 1) || + /* φ(n) = + * pq - p - q + 1 = + * n - (p + q) + 1 + * + * Thus n is a reasonable estimate for φ(n). So, (ed-1)/n will be very + * close. But, when we calculate the quotient, we'll be truncating it + * because we discard the remainder. Thus (ed-1)/multiple will be >= n, + * which the totient cannot be. So we add one to the estimate. + * + * Consider ed-1 as: + * + * multiple * (n - (p+q) + 1) = + * multiple*n - multiple*(p+q) + multiple + * + * When we divide by n, the first term becomes multiple and, since + * multiple and p+q is tiny compared to n, the second and third terms can + * be ignored. Thus I claim that subtracting one from the estimate is + * sufficient. */ + !BN_div(multiple, NULL, totient, rsa->n, ctx) || + !BN_add_word(multiple, 1) || + !BN_div(totient, rem, totient, multiple, ctx)) { + OPENSSL_PUT_ERROR(RSA, ERR_R_BN_LIB); + goto err; + } + + if (!BN_is_zero(rem)) { + OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_RSA_PARAMETERS); + goto err; + } + + rsa->p = BN_new(); + rsa->q = BN_new(); + rsa->dmp1 = BN_new(); + rsa->dmq1 = BN_new(); + rsa->iqmp = BN_new(); + if (rsa->p == NULL || rsa->q == NULL || rsa->dmp1 == NULL || rsa->dmq1 == + NULL || rsa->iqmp == NULL) { + OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE); + goto err; + } + + /* φ(n) = n - (p + q) + 1 => + * n - totient + 1 = p + q */ + if (!BN_sub(p_plus_q, rsa->n, totient) || + !BN_add_word(p_plus_q, 1) || + /* p - q = sqrt((p+q)^2 - 4n) */ + !BN_sqr(rem, p_plus_q, ctx) || + !BN_lshift(multiple, rsa->n, 2) || + !BN_sub(rem, rem, multiple) || + !BN_sqrt(p_minus_q, rem, ctx) || + /* q is 1/2 (p+q)-(p-q) */ + !BN_sub(rsa->q, p_plus_q, p_minus_q) || + !BN_rshift1(rsa->q, rsa->q) || + !BN_div(rsa->p, NULL, rsa->n, rsa->q, ctx) || + !BN_mul(multiple, rsa->p, rsa->q, ctx)) { + OPENSSL_PUT_ERROR(RSA, ERR_R_BN_LIB); + goto err; + } + + if (BN_cmp(multiple, rsa->n) != 0) { + OPENSSL_PUT_ERROR(RSA, RSA_R_INTERNAL_ERROR); + goto err; + } + + if (!BN_sub(rem, rsa->p, BN_value_one()) || + !BN_mod(rsa->dmp1, rsa->d, rem, ctx) || + !BN_sub(rem, rsa->q, BN_value_one()) || + !BN_mod(rsa->dmq1, rsa->d, rem, ctx) || + !BN_mod_inverse(rsa->iqmp, rsa->q, rsa->p, ctx)) { + OPENSSL_PUT_ERROR(RSA, ERR_R_BN_LIB); + goto err; + } + + ok = 1; + +err: + BN_CTX_end(ctx); + BN_CTX_free(ctx); + if (!ok) { + bn_free_and_null(&rsa->p); + bn_free_and_null(&rsa->q); + bn_free_and_null(&rsa->dmp1); + bn_free_and_null(&rsa->dmq1); + bn_free_and_null(&rsa->iqmp); + } + return ok; +} + +int RSA_private_transform(RSA *rsa, uint8_t *out, const uint8_t *in, + size_t len) { + if (rsa->meth->private_transform) { + return rsa->meth->private_transform(rsa, out, in, len); + } + + return rsa_default_private_transform(rsa, out, in, len); +} + +int RSA_blinding_on(RSA *rsa, BN_CTX *ctx) { + return 1; +} diff --git a/external/boringssl/crypto/rsa/rsa_asn1.c b/external/boringssl/crypto/rsa/rsa_asn1.c new file mode 100644 index 0000000000..d14ecaee9a --- /dev/null +++ b/external/boringssl/crypto/rsa/rsa_asn1.c @@ -0,0 +1,445 @@ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 2000-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include "internal.h" +#include "../bytestring/internal.h" + + +static int parse_integer_buggy(CBS *cbs, BIGNUM **out, int buggy) { + assert(*out == NULL); + *out = BN_new(); + if (*out == NULL) { + return 0; + } + if (buggy) { + return BN_parse_asn1_unsigned_buggy(cbs, *out); + } + return BN_parse_asn1_unsigned(cbs, *out); +} + +static int parse_integer(CBS *cbs, BIGNUM **out) { + return parse_integer_buggy(cbs, out, 0 /* not buggy */); +} + +static int marshal_integer(CBB *cbb, BIGNUM *bn) { + if (bn == NULL) { + /* An RSA object may be missing some components. */ + OPENSSL_PUT_ERROR(RSA, RSA_R_VALUE_MISSING); + return 0; + } + return BN_marshal_asn1(cbb, bn); +} + +static RSA *parse_public_key(CBS *cbs, int buggy) { + RSA *ret = RSA_new(); + if (ret == NULL) { + return NULL; + } + CBS child; + if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) || + !parse_integer_buggy(&child, &ret->n, buggy) || + !parse_integer(&child, &ret->e) || + CBS_len(&child) != 0) { + OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_ENCODING); + RSA_free(ret); + return NULL; + } + + if (!BN_is_odd(ret->e) || + BN_num_bits(ret->e) < 2) { + OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_RSA_PARAMETERS); + RSA_free(ret); + return NULL; + } + + return ret; +} + +RSA *RSA_parse_public_key(CBS *cbs) { + return parse_public_key(cbs, 0 /* not buggy */); +} + +RSA *RSA_parse_public_key_buggy(CBS *cbs) { + /* Estonian IDs issued between September 2014 to September 2015 are + * broken. See https://crbug.com/532048 and https://crbug.com/534766. + * + * TODO(davidben): Remove this code and callers in March 2016. */ + return parse_public_key(cbs, 1 /* buggy */); +} + +RSA *RSA_public_key_from_bytes(const uint8_t *in, size_t in_len) { + CBS cbs; + CBS_init(&cbs, in, in_len); + RSA *ret = RSA_parse_public_key(&cbs); + if (ret == NULL || CBS_len(&cbs) != 0) { + OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_ENCODING); + RSA_free(ret); + return NULL; + } + return ret; +} + +int RSA_marshal_public_key(CBB *cbb, const RSA *rsa) { + CBB child; + if (!CBB_add_asn1(cbb, &child, CBS_ASN1_SEQUENCE) || + !marshal_integer(&child, rsa->n) || + !marshal_integer(&child, rsa->e) || + !CBB_flush(cbb)) { + OPENSSL_PUT_ERROR(RSA, RSA_R_ENCODE_ERROR); + return 0; + } + return 1; +} + +int RSA_public_key_to_bytes(uint8_t **out_bytes, size_t *out_len, + const RSA *rsa) { + CBB cbb; + CBB_zero(&cbb); + if (!CBB_init(&cbb, 0) || + !RSA_marshal_public_key(&cbb, rsa) || + !CBB_finish(&cbb, out_bytes, out_len)) { + OPENSSL_PUT_ERROR(RSA, RSA_R_ENCODE_ERROR); + CBB_cleanup(&cbb); + return 0; + } + return 1; +} + +/* kVersionTwoPrime and kVersionMulti are the supported values of the version + * field of an RSAPrivateKey structure (RFC 3447). */ +static const uint64_t kVersionTwoPrime = 0; +static const uint64_t kVersionMulti = 1; + +/* rsa_parse_additional_prime parses a DER-encoded OtherPrimeInfo from |cbs| and + * advances |cbs|. It returns a newly-allocated |RSA_additional_prime| on + * success or NULL on error. The |r| and |mont| fields of the result are set to + * NULL. */ +static RSA_additional_prime *rsa_parse_additional_prime(CBS *cbs) { + RSA_additional_prime *ret = OPENSSL_malloc(sizeof(RSA_additional_prime)); + if (ret == NULL) { + OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE); + return 0; + } + memset(ret, 0, sizeof(RSA_additional_prime)); + + CBS child; + if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) || + !parse_integer(&child, &ret->prime) || + !parse_integer(&child, &ret->exp) || + !parse_integer(&child, &ret->coeff) || + CBS_len(&child) != 0) { + OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_ENCODING); + RSA_additional_prime_free(ret); + return NULL; + } + + return ret; +} + +RSA *RSA_parse_private_key(CBS *cbs) { + BN_CTX *ctx = NULL; + BIGNUM *product_of_primes_so_far = NULL; + RSA *ret = RSA_new(); + if (ret == NULL) { + return NULL; + } + + CBS child; + uint64_t version; + if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) || + !CBS_get_asn1_uint64(&child, &version)) { + OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_ENCODING); + goto err; + } + + if (version != kVersionTwoPrime && version != kVersionMulti) { + OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_VERSION); + goto err; + } + + if (!parse_integer(&child, &ret->n) || + !parse_integer(&child, &ret->e) || + !parse_integer(&child, &ret->d) || + !parse_integer(&child, &ret->p) || + !parse_integer(&child, &ret->q) || + !parse_integer(&child, &ret->dmp1) || + !parse_integer(&child, &ret->dmq1) || + !parse_integer(&child, &ret->iqmp)) { + goto err; + } + + if (version == kVersionMulti) { + /* Although otherPrimeInfos is written as OPTIONAL in RFC 3447, it later + * says "[otherPrimeInfos] shall be omitted if version is 0 and shall + * contain at least one instance of OtherPrimeInfo if version is 1." The + * OPTIONAL is just so both versions share a single definition. */ + CBS other_prime_infos; + if (!CBS_get_asn1(&child, &other_prime_infos, CBS_ASN1_SEQUENCE) || + CBS_len(&other_prime_infos) == 0) { + OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_ENCODING); + goto err; + } + ret->additional_primes = sk_RSA_additional_prime_new_null(); + if (ret->additional_primes == NULL) { + OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE); + goto err; + } + + ctx = BN_CTX_new(); + product_of_primes_so_far = BN_new(); + if (ctx == NULL || + product_of_primes_so_far == NULL || + !BN_mul(product_of_primes_so_far, ret->p, ret->q, ctx)) { + goto err; + } + + while (CBS_len(&other_prime_infos) > 0) { + RSA_additional_prime *ap = rsa_parse_additional_prime(&other_prime_infos); + if (ap == NULL) { + goto err; + } + if (!sk_RSA_additional_prime_push(ret->additional_primes, ap)) { + OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE); + RSA_additional_prime_free(ap); + goto err; + } + ap->r = BN_dup(product_of_primes_so_far); + if (ap->r == NULL || + !BN_mul(product_of_primes_so_far, product_of_primes_so_far, + ap->prime, ctx)) { + goto err; + } + } + } + + if (CBS_len(&child) != 0) { + OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_ENCODING); + goto err; + } + + BN_CTX_free(ctx); + BN_free(product_of_primes_so_far); + return ret; + +err: + BN_CTX_free(ctx); + BN_free(product_of_primes_so_far); + RSA_free(ret); + return NULL; +} + +RSA *RSA_private_key_from_bytes(const uint8_t *in, size_t in_len) { + CBS cbs; + CBS_init(&cbs, in, in_len); + RSA *ret = RSA_parse_private_key(&cbs); + if (ret == NULL || CBS_len(&cbs) != 0) { + OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_ENCODING); + RSA_free(ret); + return NULL; + } + return ret; +} + +int RSA_marshal_private_key(CBB *cbb, const RSA *rsa) { + const int is_multiprime = + sk_RSA_additional_prime_num(rsa->additional_primes) > 0; + + CBB child; + if (!CBB_add_asn1(cbb, &child, CBS_ASN1_SEQUENCE) || + !CBB_add_asn1_uint64(&child, + is_multiprime ? kVersionMulti : kVersionTwoPrime) || + !marshal_integer(&child, rsa->n) || + !marshal_integer(&child, rsa->e) || + !marshal_integer(&child, rsa->d) || + !marshal_integer(&child, rsa->p) || + !marshal_integer(&child, rsa->q) || + !marshal_integer(&child, rsa->dmp1) || + !marshal_integer(&child, rsa->dmq1) || + !marshal_integer(&child, rsa->iqmp)) { + OPENSSL_PUT_ERROR(RSA, RSA_R_ENCODE_ERROR); + return 0; + } + + if (is_multiprime) { + CBB other_prime_infos; + if (!CBB_add_asn1(&child, &other_prime_infos, CBS_ASN1_SEQUENCE)) { + OPENSSL_PUT_ERROR(RSA, RSA_R_ENCODE_ERROR); + return 0; + } + size_t i; + for (i = 0; i < sk_RSA_additional_prime_num(rsa->additional_primes); i++) { + RSA_additional_prime *ap = + sk_RSA_additional_prime_value(rsa->additional_primes, i); + CBB other_prime_info; + if (!CBB_add_asn1(&other_prime_infos, &other_prime_info, + CBS_ASN1_SEQUENCE) || + !marshal_integer(&other_prime_info, ap->prime) || + !marshal_integer(&other_prime_info, ap->exp) || + !marshal_integer(&other_prime_info, ap->coeff)) { + OPENSSL_PUT_ERROR(RSA, RSA_R_ENCODE_ERROR); + return 0; + } + } + } + + if (!CBB_flush(cbb)) { + OPENSSL_PUT_ERROR(RSA, RSA_R_ENCODE_ERROR); + return 0; + } + return 1; +} + +int RSA_private_key_to_bytes(uint8_t **out_bytes, size_t *out_len, + const RSA *rsa) { + CBB cbb; + CBB_zero(&cbb); + if (!CBB_init(&cbb, 0) || + !RSA_marshal_private_key(&cbb, rsa) || + !CBB_finish(&cbb, out_bytes, out_len)) { + OPENSSL_PUT_ERROR(RSA, RSA_R_ENCODE_ERROR); + CBB_cleanup(&cbb); + return 0; + } + return 1; +} + +RSA *d2i_RSAPublicKey(RSA **out, const uint8_t **inp, long len) { + if (len < 0) { + return NULL; + } + CBS cbs; + CBS_init(&cbs, *inp, (size_t)len); + RSA *ret = RSA_parse_public_key(&cbs); + if (ret == NULL) { + return NULL; + } + if (out != NULL) { + RSA_free(*out); + *out = ret; + } + *inp = CBS_data(&cbs); + return ret; +} + +int i2d_RSAPublicKey(const RSA *in, uint8_t **outp) { + CBB cbb; + if (!CBB_init(&cbb, 0) || + !RSA_marshal_public_key(&cbb, in)) { + CBB_cleanup(&cbb); + return -1; + } + return CBB_finish_i2d(&cbb, outp); +} + +RSA *d2i_RSAPrivateKey(RSA **out, const uint8_t **inp, long len) { + if (len < 0) { + return NULL; + } + CBS cbs; + CBS_init(&cbs, *inp, (size_t)len); + RSA *ret = RSA_parse_private_key(&cbs); + if (ret == NULL) { + return NULL; + } + if (out != NULL) { + RSA_free(*out); + *out = ret; + } + *inp = CBS_data(&cbs); + return ret; +} + +int i2d_RSAPrivateKey(const RSA *in, uint8_t **outp) { + CBB cbb; + if (!CBB_init(&cbb, 0) || + !RSA_marshal_private_key(&cbb, in)) { + CBB_cleanup(&cbb); + return -1; + } + return CBB_finish_i2d(&cbb, outp); +} + +RSA *RSAPublicKey_dup(const RSA *rsa) { + uint8_t *der; + size_t der_len; + if (!RSA_public_key_to_bytes(&der, &der_len, rsa)) { + return NULL; + } + RSA *ret = RSA_public_key_from_bytes(der, der_len); + OPENSSL_free(der); + return ret; +} + +RSA *RSAPrivateKey_dup(const RSA *rsa) { + uint8_t *der; + size_t der_len; + if (!RSA_private_key_to_bytes(&der, &der_len, rsa)) { + return NULL; + } + RSA *ret = RSA_private_key_from_bytes(der, der_len); + OPENSSL_free(der); + return ret; +} diff --git a/external/boringssl/crypto/rsa/rsa_impl.c b/external/boringssl/crypto/rsa/rsa_impl.c new file mode 100644 index 0000000000..af44a3d546 --- /dev/null +++ b/external/boringssl/crypto/rsa/rsa_impl.c @@ -0,0 +1,1140 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +#include +#include +#include +#include + +#include "internal.h" +#include "../internal.h" + + +static int check_modulus_and_exponent_sizes(const RSA *rsa) { + unsigned rsa_bits = BN_num_bits(rsa->n); + + if (rsa_bits > 16 * 1024) { + OPENSSL_PUT_ERROR(RSA, RSA_R_MODULUS_TOO_LARGE); + return 0; + } + + /* Mitigate DoS attacks by limiting the exponent size. 33 bits was chosen as + * the limit based on the recommendations in [1] and [2]. Windows CryptoAPI + * doesn't support values larger than 32 bits [3], so it is unlikely that + * exponents larger than 32 bits are being used for anything Windows commonly + * does. + * + * [1] https://www.imperialviolet.org/2012/03/16/rsae.html + * [2] https://www.imperialviolet.org/2012/03/17/rsados.html + * [3] https://msdn.microsoft.com/en-us/library/aa387685(VS.85).aspx */ + static const unsigned kMaxExponentBits = 33; + + if (BN_num_bits(rsa->e) > kMaxExponentBits) { + OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_E_VALUE); + return 0; + } + + /* Verify |n > e|. Comparing |rsa_bits| to |kMaxExponentBits| is a small + * shortcut to comparing |n| and |e| directly. In reality, |kMaxExponentBits| + * is much smaller than the minimum RSA key size that any application should + * accept. */ + if (rsa_bits <= kMaxExponentBits) { + OPENSSL_PUT_ERROR(RSA, RSA_R_KEY_SIZE_TOO_SMALL); + return 0; + } + assert(BN_ucmp(rsa->n, rsa->e) > 0); + + return 1; +} + +size_t rsa_default_size(const RSA *rsa) { + return BN_num_bytes(rsa->n); +} + +int rsa_default_encrypt(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out, + const uint8_t *in, size_t in_len, int padding) { + const unsigned rsa_size = RSA_size(rsa); + BIGNUM *f, *result; + uint8_t *buf = NULL; + BN_CTX *ctx = NULL; + int i, ret = 0; + + if (max_out < rsa_size) { + OPENSSL_PUT_ERROR(RSA, RSA_R_OUTPUT_BUFFER_TOO_SMALL); + return 0; + } + + if (!check_modulus_and_exponent_sizes(rsa)) { + return 0; + } + + ctx = BN_CTX_new(); + if (ctx == NULL) { + goto err; + } + + BN_CTX_start(ctx); + f = BN_CTX_get(ctx); + result = BN_CTX_get(ctx); + buf = OPENSSL_malloc(rsa_size); + if (!f || !result || !buf) { + OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE); + goto err; + } + + switch (padding) { + case RSA_PKCS1_PADDING: + i = RSA_padding_add_PKCS1_type_2(buf, rsa_size, in, in_len); + break; + case RSA_PKCS1_OAEP_PADDING: + /* Use the default parameters: SHA-1 for both hashes and no label. */ + i = RSA_padding_add_PKCS1_OAEP_mgf1(buf, rsa_size, in, in_len, + NULL, 0, NULL, NULL); + break; + case RSA_NO_PADDING: + i = RSA_padding_add_none(buf, rsa_size, in, in_len); + break; + default: + OPENSSL_PUT_ERROR(RSA, RSA_R_UNKNOWN_PADDING_TYPE); + goto err; + } + + if (i <= 0) { + goto err; + } + + if (BN_bin2bn(buf, rsa_size, f) == NULL) { + goto err; + } + + if (BN_ucmp(f, rsa->n) >= 0) { + /* usually the padding functions would catch this */ + OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE_FOR_MODULUS); + goto err; + } + + if (!BN_MONT_CTX_set_locked(&rsa->mont_n, &rsa->lock, rsa->n, ctx) || + !BN_mod_exp_mont(result, f, rsa->e, rsa->n, ctx, rsa->mont_n)) { + goto err; + } + + /* put in leading 0 bytes if the number is less than the length of the + * modulus */ + if (!BN_bn2bin_padded(out, rsa_size, result)) { + OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR); + goto err; + } + + *out_len = rsa_size; + ret = 1; + +err: + if (ctx != NULL) { + BN_CTX_end(ctx); + BN_CTX_free(ctx); + } + if (buf != NULL) { + OPENSSL_cleanse(buf, rsa_size); + OPENSSL_free(buf); + } + + return ret; +} + +/* MAX_BLINDINGS_PER_RSA defines the maximum number of cached BN_BLINDINGs per + * RSA*. Then this limit is exceeded, BN_BLINDING objects will be created and + * destroyed as needed. */ +#define MAX_BLINDINGS_PER_RSA 1024 + +/* rsa_blinding_get returns a BN_BLINDING to use with |rsa|. It does this by + * allocating one of the cached BN_BLINDING objects in |rsa->blindings|. If + * none are free, the cache will be extended by a extra element and the new + * BN_BLINDING is returned. + * + * On success, the index of the assigned BN_BLINDING is written to + * |*index_used| and must be passed to |rsa_blinding_release| when finished. */ +static BN_BLINDING *rsa_blinding_get(RSA *rsa, unsigned *index_used, + BN_CTX *ctx) { + assert(ctx != NULL); + assert(rsa->mont_n != NULL); + + BN_BLINDING *ret = NULL; + BN_BLINDING **new_blindings; + uint8_t *new_blindings_inuse; + char overflow = 0; + + CRYPTO_MUTEX_lock_write(&rsa->lock); + + unsigned i; + for (i = 0; i < rsa->num_blindings; i++) { + if (rsa->blindings_inuse[i] == 0) { + rsa->blindings_inuse[i] = 1; + ret = rsa->blindings[i]; + *index_used = i; + break; + } + } + + if (ret != NULL) { + CRYPTO_MUTEX_unlock_write(&rsa->lock); + return ret; + } + + overflow = rsa->num_blindings >= MAX_BLINDINGS_PER_RSA; + + /* We didn't find a free BN_BLINDING to use so increase the length of + * the arrays by one and use the newly created element. */ + + CRYPTO_MUTEX_unlock_write(&rsa->lock); + ret = BN_BLINDING_new(); + if (ret == NULL) { + return NULL; + } + + if (overflow) { + /* We cannot add any more cached BN_BLINDINGs so we use |ret| + * and mark it for destruction in |rsa_blinding_release|. */ + *index_used = MAX_BLINDINGS_PER_RSA; + return ret; + } + + CRYPTO_MUTEX_lock_write(&rsa->lock); + + new_blindings = + OPENSSL_malloc(sizeof(BN_BLINDING *) * (rsa->num_blindings + 1)); + if (new_blindings == NULL) { + goto err1; + } + memcpy(new_blindings, rsa->blindings, + sizeof(BN_BLINDING *) * rsa->num_blindings); + new_blindings[rsa->num_blindings] = ret; + + new_blindings_inuse = OPENSSL_malloc(rsa->num_blindings + 1); + if (new_blindings_inuse == NULL) { + goto err2; + } + memcpy(new_blindings_inuse, rsa->blindings_inuse, rsa->num_blindings); + new_blindings_inuse[rsa->num_blindings] = 1; + *index_used = rsa->num_blindings; + + OPENSSL_free(rsa->blindings); + rsa->blindings = new_blindings; + OPENSSL_free(rsa->blindings_inuse); + rsa->blindings_inuse = new_blindings_inuse; + rsa->num_blindings++; + + CRYPTO_MUTEX_unlock_write(&rsa->lock); + return ret; + +err2: + OPENSSL_free(new_blindings); + +err1: + CRYPTO_MUTEX_unlock_write(&rsa->lock); + BN_BLINDING_free(ret); + return NULL; +} + +/* rsa_blinding_release marks the cached BN_BLINDING at the given index as free + * for other threads to use. */ +static void rsa_blinding_release(RSA *rsa, BN_BLINDING *blinding, + unsigned blinding_index) { + if (blinding_index == MAX_BLINDINGS_PER_RSA) { + /* This blinding wasn't cached. */ + BN_BLINDING_free(blinding); + return; + } + + CRYPTO_MUTEX_lock_write(&rsa->lock); + rsa->blindings_inuse[blinding_index] = 0; + CRYPTO_MUTEX_unlock_write(&rsa->lock); +} + +/* signing */ +int rsa_default_sign_raw(RSA *rsa, size_t *out_len, uint8_t *out, + size_t max_out, const uint8_t *in, size_t in_len, + int padding) { + const unsigned rsa_size = RSA_size(rsa); + uint8_t *buf = NULL; + int i, ret = 0; + + if (max_out < rsa_size) { + OPENSSL_PUT_ERROR(RSA, RSA_R_OUTPUT_BUFFER_TOO_SMALL); + return 0; + } + + buf = OPENSSL_malloc(rsa_size); + if (buf == NULL) { + OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE); + goto err; + } + + switch (padding) { + case RSA_PKCS1_PADDING: + i = RSA_padding_add_PKCS1_type_1(buf, rsa_size, in, in_len); + break; + case RSA_NO_PADDING: + i = RSA_padding_add_none(buf, rsa_size, in, in_len); + break; + default: + OPENSSL_PUT_ERROR(RSA, RSA_R_UNKNOWN_PADDING_TYPE); + goto err; + } + + if (i <= 0) { + goto err; + } + + if (!RSA_private_transform(rsa, out, buf, rsa_size)) { + goto err; + } + + *out_len = rsa_size; + ret = 1; + +err: + if (buf != NULL) { + OPENSSL_cleanse(buf, rsa_size); + OPENSSL_free(buf); + } + + return ret; +} + +int rsa_default_decrypt(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out, + const uint8_t *in, size_t in_len, int padding) { + const unsigned rsa_size = RSA_size(rsa); + int r = -1; + uint8_t *buf = NULL; + int ret = 0; + + if (max_out < rsa_size) { + OPENSSL_PUT_ERROR(RSA, RSA_R_OUTPUT_BUFFER_TOO_SMALL); + return 0; + } + + if (padding == RSA_NO_PADDING) { + buf = out; + } else { + /* Allocate a temporary buffer to hold the padded plaintext. */ + buf = OPENSSL_malloc(rsa_size); + if (buf == NULL) { + OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE); + goto err; + } + } + + if (in_len != rsa_size) { + OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_LEN_NOT_EQUAL_TO_MOD_LEN); + goto err; + } + + if (!RSA_private_transform(rsa, buf, in, rsa_size)) { + goto err; + } + + switch (padding) { + case RSA_PKCS1_PADDING: + r = RSA_padding_check_PKCS1_type_2(out, rsa_size, buf, rsa_size); + break; + case RSA_PKCS1_OAEP_PADDING: + /* Use the default parameters: SHA-1 for both hashes and no label. */ + r = RSA_padding_check_PKCS1_OAEP_mgf1(out, rsa_size, buf, rsa_size, + NULL, 0, NULL, NULL); + break; + case RSA_NO_PADDING: + r = rsa_size; + break; + default: + OPENSSL_PUT_ERROR(RSA, RSA_R_UNKNOWN_PADDING_TYPE); + goto err; + } + + if (r < 0) { + OPENSSL_PUT_ERROR(RSA, RSA_R_PADDING_CHECK_FAILED); + } else { + *out_len = r; + ret = 1; + } + +err: + if (padding != RSA_NO_PADDING && buf != NULL) { + OPENSSL_cleanse(buf, rsa_size); + OPENSSL_free(buf); + } + + return ret; +} + +static int mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx); + +int RSA_verify_raw(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out, + const uint8_t *in, size_t in_len, int padding) { + if (rsa->n == NULL || rsa->e == NULL) { + OPENSSL_PUT_ERROR(RSA, RSA_R_VALUE_MISSING); + return 0; + } + + const unsigned rsa_size = RSA_size(rsa); + BIGNUM *f, *result; + int r = -1; + + if (max_out < rsa_size) { + OPENSSL_PUT_ERROR(RSA, RSA_R_OUTPUT_BUFFER_TOO_SMALL); + return 0; + } + + if (in_len != rsa_size) { + OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_LEN_NOT_EQUAL_TO_MOD_LEN); + return 0; + } + + if (!check_modulus_and_exponent_sizes(rsa)) { + return 0; + } + + BN_CTX *ctx = BN_CTX_new(); + if (ctx == NULL) { + return 0; + } + + int ret = 0; + uint8_t *buf = NULL; + + BN_CTX_start(ctx); + f = BN_CTX_get(ctx); + result = BN_CTX_get(ctx); + if (f == NULL || result == NULL) { + OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (padding == RSA_NO_PADDING) { + buf = out; + } else { + /* Allocate a temporary buffer to hold the padded plaintext. */ + buf = OPENSSL_malloc(rsa_size); + if (buf == NULL) { + OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE); + goto err; + } + } + + if (BN_bin2bn(in, in_len, f) == NULL) { + goto err; + } + + if (BN_ucmp(f, rsa->n) >= 0) { + OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE_FOR_MODULUS); + goto err; + } + + if (!BN_MONT_CTX_set_locked(&rsa->mont_n, &rsa->lock, rsa->n, ctx) || + !BN_mod_exp_mont(result, f, rsa->e, rsa->n, ctx, rsa->mont_n)) { + goto err; + } + + if (!BN_bn2bin_padded(buf, rsa_size, result)) { + OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR); + goto err; + } + + switch (padding) { + case RSA_PKCS1_PADDING: + r = RSA_padding_check_PKCS1_type_1(out, rsa_size, buf, rsa_size); + break; + case RSA_NO_PADDING: + r = rsa_size; + break; + default: + OPENSSL_PUT_ERROR(RSA, RSA_R_UNKNOWN_PADDING_TYPE); + goto err; + } + + if (r < 0) { + OPENSSL_PUT_ERROR(RSA, RSA_R_PADDING_CHECK_FAILED); + } else { + *out_len = r; + ret = 1; + } + +err: + BN_CTX_end(ctx); + BN_CTX_free(ctx); + if (buf != out) { + OPENSSL_free(buf); + } + return ret; +} + +int rsa_default_private_transform(RSA *rsa, uint8_t *out, const uint8_t *in, + size_t len) { + BIGNUM *f, *result; + BN_CTX *ctx = NULL; + unsigned blinding_index = 0; + BN_BLINDING *blinding = NULL; + int ret = 0; + + ctx = BN_CTX_new(); + if (ctx == NULL) { + goto err; + } + BN_CTX_start(ctx); + f = BN_CTX_get(ctx); + result = BN_CTX_get(ctx); + + if (f == NULL || result == NULL) { + OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (BN_bin2bn(in, len, f) == NULL) { + goto err; + } + + if (BN_ucmp(f, rsa->n) >= 0) { + /* Usually the padding functions would catch this. */ + OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE_FOR_MODULUS); + goto err; + } + + if (!BN_MONT_CTX_set_locked(&rsa->mont_n, &rsa->lock, rsa->n, ctx)) { + OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR); + goto err; + } + + /* We cannot do blinding or verification without |e|, and continuing without + * those countermeasures is dangerous. However, the Java/Android RSA API + * requires support for keys where only |d| and |n| (and not |e|) are known. + * The callers that require that bad behavior set |RSA_FLAG_NO_BLINDING|. */ + int disable_security = (rsa->flags & RSA_FLAG_NO_BLINDING) && rsa->e == NULL; + + if (!disable_security) { + /* Keys without public exponents must have blinding explicitly disabled to + * be used. */ + if (rsa->e == NULL) { + OPENSSL_PUT_ERROR(RSA, RSA_R_NO_PUBLIC_EXPONENT); + goto err; + } + + blinding = rsa_blinding_get(rsa, &blinding_index, ctx); + if (blinding == NULL) { + OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR); + goto err; + } + if (!BN_BLINDING_convert(f, blinding, rsa->e, rsa->mont_n, ctx)) { + goto err; + } + } + + if (rsa->p != NULL && rsa->q != NULL && rsa->e != NULL && rsa->dmp1 != NULL && + rsa->dmq1 != NULL && rsa->iqmp != NULL) { + if (!mod_exp(result, f, rsa, ctx)) { + goto err; + } + } else { + BIGNUM local_d; + BIGNUM *d = NULL; + + BN_init(&local_d); + d = &local_d; + BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME); + + if (!BN_mod_exp_mont_consttime(result, f, d, rsa->n, ctx, rsa->mont_n)) { + goto err; + } + } + + /* Verify the result to protect against fault attacks as described in the + * 1997 paper "On the Importance of Checking Cryptographic Protocols for + * Faults" by Dan Boneh, Richard A. DeMillo, and Richard J. Lipton. Some + * implementations do this only when the CRT is used, but we do it in all + * cases. Section 6 of the aforementioned paper describes an attack that + * works when the CRT isn't used. That attack is much less likely to succeed + * than the CRT attack, but there have likely been improvements since 1997. + * + * This check is cheap assuming |e| is small; it almost always is. */ + if (!disable_security) { + BIGNUM *vrfy = BN_CTX_get(ctx); + if (vrfy == NULL || + !BN_mod_exp_mont(vrfy, result, rsa->e, rsa->n, ctx, rsa->mont_n) || + !BN_equal_consttime(vrfy, f)) { + OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR); + goto err; + } + + if (!BN_BLINDING_invert(result, blinding, rsa->mont_n, ctx)) { + goto err; + } + } + + if (!BN_bn2bin_padded(out, len, result)) { + OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR); + goto err; + } + + ret = 1; + +err: + if (ctx != NULL) { + BN_CTX_end(ctx); + BN_CTX_free(ctx); + } + if (blinding != NULL) { + rsa_blinding_release(rsa, blinding, blinding_index); + } + + return ret; +} + +static int mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) { + assert(ctx != NULL); + + assert(rsa->n != NULL); + assert(rsa->e != NULL); + assert(rsa->d != NULL); + assert(rsa->p != NULL); + assert(rsa->q != NULL); + assert(rsa->dmp1 != NULL); + assert(rsa->dmq1 != NULL); + assert(rsa->iqmp != NULL); + + BIGNUM *r1, *m1, *vrfy; + BIGNUM local_dmp1, local_dmq1, local_c, local_r1; + BIGNUM *dmp1, *dmq1, *c, *pr1; + int ret = 0; + size_t i, num_additional_primes = 0; + + if (rsa->additional_primes != NULL) { + num_additional_primes = sk_RSA_additional_prime_num(rsa->additional_primes); + } + + BN_CTX_start(ctx); + r1 = BN_CTX_get(ctx); + m1 = BN_CTX_get(ctx); + vrfy = BN_CTX_get(ctx); + if (r1 == NULL || + m1 == NULL || + vrfy == NULL) { + goto err; + } + + { + BIGNUM local_p, local_q; + BIGNUM *p = NULL, *q = NULL; + + /* Make sure BN_mod_inverse in Montgomery intialization uses the + * BN_FLG_CONSTTIME flag. */ + BN_init(&local_p); + p = &local_p; + BN_with_flags(p, rsa->p, BN_FLG_CONSTTIME); + + BN_init(&local_q); + q = &local_q; + BN_with_flags(q, rsa->q, BN_FLG_CONSTTIME); + + if (!BN_MONT_CTX_set_locked(&rsa->mont_p, &rsa->lock, p, ctx) || + !BN_MONT_CTX_set_locked(&rsa->mont_q, &rsa->lock, q, ctx)) { + goto err; + } + } + + if (!BN_MONT_CTX_set_locked(&rsa->mont_n, &rsa->lock, rsa->n, ctx)) { + goto err; + } + + /* compute I mod q */ + c = &local_c; + BN_with_flags(c, I, BN_FLG_CONSTTIME); + if (!BN_mod(r1, c, rsa->q, ctx)) { + goto err; + } + + /* compute r1^dmq1 mod q */ + dmq1 = &local_dmq1; + BN_with_flags(dmq1, rsa->dmq1, BN_FLG_CONSTTIME); + if (!BN_mod_exp_mont_consttime(m1, r1, dmq1, rsa->q, ctx, rsa->mont_q)) { + goto err; + } + + /* compute I mod p */ + c = &local_c; + BN_with_flags(c, I, BN_FLG_CONSTTIME); + if (!BN_mod(r1, c, rsa->p, ctx)) { + goto err; + } + + /* compute r1^dmp1 mod p */ + dmp1 = &local_dmp1; + BN_with_flags(dmp1, rsa->dmp1, BN_FLG_CONSTTIME); + if (!BN_mod_exp_mont_consttime(r0, r1, dmp1, rsa->p, ctx, rsa->mont_p)) { + goto err; + } + + if (!BN_sub(r0, r0, m1)) { + goto err; + } + /* This will help stop the size of r0 increasing, which does + * affect the multiply if it optimised for a power of 2 size */ + if (BN_is_negative(r0)) { + if (!BN_add(r0, r0, rsa->p)) { + goto err; + } + } + + if (!BN_mul(r1, r0, rsa->iqmp, ctx)) { + goto err; + } + + /* Turn BN_FLG_CONSTTIME flag on before division operation */ + pr1 = &local_r1; + BN_with_flags(pr1, r1, BN_FLG_CONSTTIME); + + if (!BN_mod(r0, pr1, rsa->p, ctx)) { + goto err; + } + + /* If p < q it is occasionally possible for the correction of + * adding 'p' if r0 is negative above to leave the result still + * negative. This can break the private key operations: the following + * second correction should *always* correct this rare occurrence. + * This will *never* happen with OpenSSL generated keys because + * they ensure p > q [steve] */ + if (BN_is_negative(r0)) { + if (!BN_add(r0, r0, rsa->p)) { + goto err; + } + } + if (!BN_mul(r1, r0, rsa->q, ctx)) { + goto err; + } + if (!BN_add(r0, r1, m1)) { + goto err; + } + + for (i = 0; i < num_additional_primes; i++) { + /* multi-prime RSA. */ + BIGNUM local_exp, local_prime; + BIGNUM *exp = &local_exp, *prime = &local_prime; + RSA_additional_prime *ap = + sk_RSA_additional_prime_value(rsa->additional_primes, i); + + BN_with_flags(exp, ap->exp, BN_FLG_CONSTTIME); + BN_with_flags(prime, ap->prime, BN_FLG_CONSTTIME); + + /* c will already point to a BIGNUM with the correct flags. */ + if (!BN_mod(r1, c, prime, ctx)) { + goto err; + } + + if (!BN_MONT_CTX_set_locked(&ap->mont, &rsa->lock, prime, ctx) || + !BN_mod_exp_mont_consttime(m1, r1, exp, prime, ctx, ap->mont)) { + goto err; + } + + BN_set_flags(m1, BN_FLG_CONSTTIME); + + if (!BN_sub(m1, m1, r0) || + !BN_mul(m1, m1, ap->coeff, ctx) || + !BN_mod(m1, m1, prime, ctx) || + (BN_is_negative(m1) && !BN_add(m1, m1, prime)) || + !BN_mul(m1, m1, ap->r, ctx) || + !BN_add(r0, r0, m1)) { + goto err; + } + } + + ret = 1; + +err: + BN_CTX_end(ctx); + return ret; +} + +int rsa_default_multi_prime_keygen(RSA *rsa, int bits, int num_primes, + BIGNUM *e_value, BN_GENCB *cb) { + BIGNUM *r0 = NULL, *r1 = NULL, *r2 = NULL, *r3 = NULL, *tmp; + BIGNUM local_r0, local_d, local_p; + BIGNUM *pr0, *d, *p; + int prime_bits, ok = -1, n = 0, i, j; + BN_CTX *ctx = NULL; + STACK_OF(RSA_additional_prime) *additional_primes = NULL; + + if (num_primes < 2) { + ok = 0; /* we set our own err */ + OPENSSL_PUT_ERROR(RSA, RSA_R_MUST_HAVE_AT_LEAST_TWO_PRIMES); + goto err; + } + + ctx = BN_CTX_new(); + if (ctx == NULL) { + goto err; + } + BN_CTX_start(ctx); + r0 = BN_CTX_get(ctx); + r1 = BN_CTX_get(ctx); + r2 = BN_CTX_get(ctx); + r3 = BN_CTX_get(ctx); + if (r0 == NULL || r1 == NULL || r2 == NULL || r3 == NULL) { + goto err; + } + + if (num_primes > 2) { + additional_primes = sk_RSA_additional_prime_new_null(); + if (additional_primes == NULL) { + goto err; + } + } + + for (i = 2; i < num_primes; i++) { + RSA_additional_prime *ap = OPENSSL_malloc(sizeof(RSA_additional_prime)); + if (ap == NULL) { + goto err; + } + memset(ap, 0, sizeof(RSA_additional_prime)); + ap->prime = BN_new(); + ap->exp = BN_new(); + ap->coeff = BN_new(); + ap->r = BN_new(); + if (ap->prime == NULL || + ap->exp == NULL || + ap->coeff == NULL || + ap->r == NULL || + !sk_RSA_additional_prime_push(additional_primes, ap)) { + RSA_additional_prime_free(ap); + goto err; + } + } + + /* We need the RSA components non-NULL */ + if (!rsa->n && ((rsa->n = BN_new()) == NULL)) { + goto err; + } + if (!rsa->d && ((rsa->d = BN_new()) == NULL)) { + goto err; + } + if (!rsa->e && ((rsa->e = BN_new()) == NULL)) { + goto err; + } + if (!rsa->p && ((rsa->p = BN_new()) == NULL)) { + goto err; + } + if (!rsa->q && ((rsa->q = BN_new()) == NULL)) { + goto err; + } + if (!rsa->dmp1 && ((rsa->dmp1 = BN_new()) == NULL)) { + goto err; + } + if (!rsa->dmq1 && ((rsa->dmq1 = BN_new()) == NULL)) { + goto err; + } + if (!rsa->iqmp && ((rsa->iqmp = BN_new()) == NULL)) { + goto err; + } + + if (!BN_copy(rsa->e, e_value)) { + goto err; + } + + /* generate p and q */ + prime_bits = (bits + (num_primes - 1)) / num_primes; + for (;;) { + if (!BN_generate_prime_ex(rsa->p, prime_bits, 0, NULL, NULL, cb) || + !BN_sub(r2, rsa->p, BN_value_one()) || + !BN_gcd(r1, r2, rsa->e, ctx)) { + goto err; + } + if (BN_is_one(r1)) { + break; + } + if (!BN_GENCB_call(cb, 2, n++)) { + goto err; + } + } + if (!BN_GENCB_call(cb, 3, 0)) { + goto err; + } + prime_bits = ((bits - prime_bits) + (num_primes - 2)) / (num_primes - 1); + for (;;) { + /* When generating ridiculously small keys, we can get stuck + * continually regenerating the same prime values. Check for + * this and bail if it happens 3 times. */ + unsigned int degenerate = 0; + do { + if (!BN_generate_prime_ex(rsa->q, prime_bits, 0, NULL, NULL, cb)) { + goto err; + } + } while ((BN_cmp(rsa->p, rsa->q) == 0) && (++degenerate < 3)); + if (degenerate == 3) { + ok = 0; /* we set our own err */ + OPENSSL_PUT_ERROR(RSA, RSA_R_KEY_SIZE_TOO_SMALL); + goto err; + } + if (!BN_sub(r2, rsa->q, BN_value_one()) || + !BN_gcd(r1, r2, rsa->e, ctx)) { + goto err; + } + if (BN_is_one(r1)) { + break; + } + if (!BN_GENCB_call(cb, 2, n++)) { + goto err; + } + } + + if (!BN_GENCB_call(cb, 3, 1) || + !BN_mul(rsa->n, rsa->p, rsa->q, ctx)) { + goto err; + } + + for (i = 2; i < num_primes; i++) { + RSA_additional_prime *ap = + sk_RSA_additional_prime_value(additional_primes, i - 2); + prime_bits = ((bits - BN_num_bits(rsa->n)) + (num_primes - (i + 1))) / + (num_primes - i); + + for (;;) { + if (!BN_generate_prime_ex(ap->prime, prime_bits, 0, NULL, NULL, cb)) { + goto err; + } + if (BN_cmp(rsa->p, ap->prime) == 0 || + BN_cmp(rsa->q, ap->prime) == 0) { + continue; + } + + for (j = 0; j < i - 2; j++) { + if (BN_cmp(sk_RSA_additional_prime_value(additional_primes, j)->prime, + ap->prime) == 0) { + break; + } + } + if (j != i - 2) { + continue; + } + + if (!BN_sub(r2, ap->prime, BN_value_one()) || + !BN_gcd(r1, r2, rsa->e, ctx)) { + goto err; + } + + if (!BN_is_one(r1)) { + continue; + } + if (i != num_primes - 1) { + break; + } + + /* For the last prime we'll check that it makes n large enough. In the + * two prime case this isn't a problem because we generate primes with + * the top two bits set and so the product is always of the expected + * size. In the multi prime case, this doesn't follow. */ + if (!BN_mul(r1, rsa->n, ap->prime, ctx)) { + goto err; + } + if (BN_num_bits(r1) == (unsigned) bits) { + break; + } + + if (!BN_GENCB_call(cb, 2, n++)) { + goto err; + } + } + + /* ap->r is is the product of all the primes prior to the current one + * (including p and q). */ + if (!BN_copy(ap->r, rsa->n)) { + goto err; + } + if (i == num_primes - 1) { + /* In the case of the last prime, we calculated n as |r1| in the loop + * above. */ + if (!BN_copy(rsa->n, r1)) { + goto err; + } + } else if (!BN_mul(rsa->n, rsa->n, ap->prime, ctx)) { + goto err; + } + + if (!BN_GENCB_call(cb, 3, 1)) { + goto err; + } + } + + if (BN_cmp(rsa->p, rsa->q) < 0) { + tmp = rsa->p; + rsa->p = rsa->q; + rsa->q = tmp; + } + + /* calculate d */ + if (!BN_sub(r1, rsa->p, BN_value_one())) { + goto err; /* p-1 */ + } + if (!BN_sub(r2, rsa->q, BN_value_one())) { + goto err; /* q-1 */ + } + if (!BN_mul(r0, r1, r2, ctx)) { + goto err; /* (p-1)(q-1) */ + } + for (i = 2; i < num_primes; i++) { + RSA_additional_prime *ap = + sk_RSA_additional_prime_value(additional_primes, i - 2); + if (!BN_sub(r3, ap->prime, BN_value_one()) || + !BN_mul(r0, r0, r3, ctx)) { + goto err; + } + } + pr0 = &local_r0; + BN_with_flags(pr0, r0, BN_FLG_CONSTTIME); + if (!BN_mod_inverse(rsa->d, rsa->e, pr0, ctx)) { + goto err; /* d */ + } + + /* set up d for correct BN_FLG_CONSTTIME flag */ + d = &local_d; + BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME); + + /* calculate d mod (p-1) */ + if (!BN_mod(rsa->dmp1, d, r1, ctx)) { + goto err; + } + + /* calculate d mod (q-1) */ + if (!BN_mod(rsa->dmq1, d, r2, ctx)) { + goto err; + } + + /* calculate inverse of q mod p */ + p = &local_p; + BN_with_flags(p, rsa->p, BN_FLG_CONSTTIME); + + if (!BN_mod_inverse(rsa->iqmp, rsa->q, p, ctx)) { + goto err; + } + + for (i = 2; i < num_primes; i++) { + RSA_additional_prime *ap = + sk_RSA_additional_prime_value(additional_primes, i - 2); + if (!BN_sub(ap->exp, ap->prime, BN_value_one()) || + !BN_mod(ap->exp, rsa->d, ap->exp, ctx) || + !BN_mod_inverse(ap->coeff, ap->r, ap->prime, ctx)) { + goto err; + } + } + + ok = 1; + rsa->additional_primes = additional_primes; + additional_primes = NULL; + +err: + if (ok == -1) { + OPENSSL_PUT_ERROR(RSA, ERR_LIB_BN); + ok = 0; + } + if (ctx != NULL) { + BN_CTX_end(ctx); + BN_CTX_free(ctx); + } + sk_RSA_additional_prime_pop_free(additional_primes, + RSA_additional_prime_free); + return ok; +} + +int rsa_default_keygen(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb) { + return rsa_default_multi_prime_keygen(rsa, bits, 2 /* num primes */, e_value, + cb); +} + +/* All of the methods are NULL to make it easier for the compiler/linker to drop + * unused functions. The wrapper functions will select the appropriate + * |rsa_default_*| implementation. */ +const RSA_METHOD RSA_default_method = { + { + 0 /* references */, + 1 /* is_static */, + }, + NULL /* app_data */, + + NULL /* init */, + NULL /* finish (defaults to rsa_default_finish) */, + + NULL /* size (defaults to rsa_default_size) */, + + NULL /* sign */, + NULL /* verify */, + + NULL /* encrypt (defaults to rsa_default_encrypt) */, + NULL /* sign_raw (defaults to rsa_default_sign_raw) */, + NULL /* decrypt (defaults to rsa_default_decrypt) */, + NULL /* verify_raw (defaults to rsa_default_verify_raw) */, + + NULL /* private_transform (defaults to rsa_default_private_transform) */, + + NULL /* mod_exp (ignored) */, + NULL /* bn_mod_exp (ignored) */, + + RSA_FLAG_CACHE_PUBLIC | RSA_FLAG_CACHE_PRIVATE, + + NULL /* keygen (defaults to rsa_default_keygen) */, + NULL /* multi_prime_keygen (defaults to rsa_default_multi_prime_keygen) */, + + NULL /* supports_digest */, +}; diff --git a/external/boringssl/crypto/rsa/rsa_test.cc b/external/boringssl/crypto/rsa/rsa_test.cc new file mode 100644 index 0000000000..62177a4c37 --- /dev/null +++ b/external/boringssl/crypto/rsa/rsa_test.cc @@ -0,0 +1,954 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include "../test/scoped_types.h" + + +// kPlaintext is a sample plaintext. +static const uint8_t kPlaintext[] = "\x54\x85\x9b\x34\x2c\x49\xea\x2a"; +static const size_t kPlaintextLen = sizeof(kPlaintext) - 1; + +// kKey1 is a DER-encoded RSAPrivateKey. +static const uint8_t kKey1[] = + "\x30\x82\x01\x38\x02\x01\x00\x02\x41\x00\xaa\x36\xab\xce\x88\xac\xfd\xff" + "\x55\x52\x3c\x7f\xc4\x52\x3f\x90\xef\xa0\x0d\xf3\x77\x4a\x25\x9f\x2e\x62" + "\xb4\xc5\xd9\x9c\xb5\xad\xb3\x00\xa0\x28\x5e\x53\x01\x93\x0e\x0c\x70\xfb" + "\x68\x76\x93\x9c\xe6\x16\xce\x62\x4a\x11\xe0\x08\x6d\x34\x1e\xbc\xac\xa0" + "\xa1\xf5\x02\x01\x11\x02\x40\x0a\x03\x37\x48\x62\x64\x87\x69\x5f\x5f\x30" + "\xbc\x38\xb9\x8b\x44\xc2\xcd\x2d\xff\x43\x40\x98\xcd\x20\xd8\xa1\x38\xd0" + "\x90\xbf\x64\x79\x7c\x3f\xa7\xa2\xcd\xcb\x3c\xd1\xe0\xbd\xba\x26\x54\xb4" + "\xf9\xdf\x8e\x8a\xe5\x9d\x73\x3d\x9f\x33\xb3\x01\x62\x4a\xfd\x1d\x51\x02" + "\x21\x00\xd8\x40\xb4\x16\x66\xb4\x2e\x92\xea\x0d\xa3\xb4\x32\x04\xb5\xcf" + "\xce\x33\x52\x52\x4d\x04\x16\xa5\xa4\x41\xe7\x00\xaf\x46\x12\x0d\x02\x21" + "\x00\xc9\x7f\xb1\xf0\x27\xf4\x53\xf6\x34\x12\x33\xea\xaa\xd1\xd9\x35\x3f" + "\x6c\x42\xd0\x88\x66\xb1\xd0\x5a\x0f\x20\x35\x02\x8b\x9d\x89\x02\x20\x59" + "\x0b\x95\x72\xa2\xc2\xa9\xc4\x06\x05\x9d\xc2\xab\x2f\x1d\xaf\xeb\x7e\x8b" + "\x4f\x10\xa7\x54\x9e\x8e\xed\xf5\xb4\xfc\xe0\x9e\x05\x02\x21\x00\x8e\x3c" + "\x05\x21\xfe\x15\xe0\xea\x06\xa3\x6f\xf0\xf1\x0c\x99\x52\xc3\x5b\x7a\x75" + "\x14\xfd\x32\x38\xb8\x0a\xad\x52\x98\x62\x8d\x51\x02\x20\x36\x3f\xf7\x18" + "\x9d\xa8\xe9\x0b\x1d\x34\x1f\x71\xd0\x9b\x76\xa8\xa9\x43\xe1\x1d\x10\xb2" + "\x4d\x24\x9f\x2d\xea\xfe\xf8\x0c\x18\x26"; + +// kOAEPCiphertext1 is a sample encryption of |kPlaintext| with |kKey1| using +// RSA OAEP. +static const uint8_t kOAEPCiphertext1[] = + "\x1b\x8f\x05\xf9\xca\x1a\x79\x52\x6e\x53\xf3\xcc\x51\x4f\xdb\x89\x2b\xfb" + "\x91\x93\x23\x1e\x78\xb9\x92\xe6\x8d\x50\xa4\x80\xcb\x52\x33\x89\x5c\x74" + "\x95\x8d\x5d\x02\xab\x8c\x0f\xd0\x40\xeb\x58\x44\xb0\x05\xc3\x9e\xd8\x27" + "\x4a\x9d\xbf\xa8\x06\x71\x40\x94\x39\xd2"; + +// kKey2 is a DER-encoded RSAPrivateKey. +static const uint8_t kKey2[] = + "\x30\x81\xfb\x02\x01\x00\x02\x33\x00\xa3\x07\x9a\x90\xdf\x0d\xfd\x72\xac" + "\x09\x0c\xcc\x2a\x78\xb8\x74\x13\x13\x3e\x40\x75\x9c\x98\xfa\xf8\x20\x4f" + "\x35\x8a\x0b\x26\x3c\x67\x70\xe7\x83\xa9\x3b\x69\x71\xb7\x37\x79\xd2\x71" + "\x7b\xe8\x34\x77\xcf\x02\x01\x03\x02\x32\x6c\xaf\xbc\x60\x94\xb3\xfe\x4c" + "\x72\xb0\xb3\x32\xc6\xfb\x25\xa2\xb7\x62\x29\x80\x4e\x68\x65\xfc\xa4\x5a" + "\x74\xdf\x0f\x8f\xb8\x41\x3b\x52\xc0\xd0\xe5\x3d\x9b\x59\x0f\xf1\x9b\xe7" + "\x9f\x49\xdd\x21\xe5\xeb\x02\x1a\x00\xcf\x20\x35\x02\x8b\x9d\x86\x98\x40" + "\xb4\x16\x66\xb4\x2e\x92\xea\x0d\xa3\xb4\x32\x04\xb5\xcf\xce\x91\x02\x1a" + "\x00\xc9\x7f\xb1\xf0\x27\xf4\x53\xf6\x34\x12\x33\xea\xaa\xd1\xd9\x35\x3f" + "\x6c\x42\xd0\x88\x66\xb1\xd0\x5f\x02\x1a\x00\x8a\x15\x78\xac\x5d\x13\xaf" + "\x10\x2b\x22\xb9\x99\xcd\x74\x61\xf1\x5e\x6d\x22\xcc\x03\x23\xdf\xdf\x0b" + "\x02\x1a\x00\x86\x55\x21\x4a\xc5\x4d\x8d\x4e\xcd\x61\x77\xf1\xc7\x36\x90" + "\xce\x2a\x48\x2c\x8b\x05\x99\xcb\xe0\x3f\x02\x1a\x00\x83\xef\xef\xb8\xa9" + "\xa4\x0d\x1d\xb6\xed\x98\xad\x84\xed\x13\x35\xdc\xc1\x08\xf3\x22\xd0\x57" + "\xcf\x8d"; + +// kOAEPCiphertext2 is a sample encryption of |kPlaintext| with |kKey2| using +// RSA OAEP. +static const uint8_t kOAEPCiphertext2[] = + "\x14\xbd\xdd\x28\xc9\x83\x35\x19\x23\x80\xe8\xe5\x49\xb1\x58\x2a\x8b\x40" + "\xb4\x48\x6d\x03\xa6\xa5\x31\x1f\x1f\xd5\xf0\xa1\x80\xe4\x17\x53\x03\x29" + "\xa9\x34\x90\x74\xb1\x52\x13\x54\x29\x08\x24\x52\x62\x51"; + +// kKey3 is a DER-encoded RSAPrivateKey. +static const uint8_t kKey3[] = + "\x30\x82\x02\x5b\x02\x01\x00\x02\x81\x81\x00\xbb\xf8\x2f\x09\x06\x82\xce" + "\x9c\x23\x38\xac\x2b\x9d\xa8\x71\xf7\x36\x8d\x07\xee\xd4\x10\x43\xa4\x40" + "\xd6\xb6\xf0\x74\x54\xf5\x1f\xb8\xdf\xba\xaf\x03\x5c\x02\xab\x61\xea\x48" + "\xce\xeb\x6f\xcd\x48\x76\xed\x52\x0d\x60\xe1\xec\x46\x19\x71\x9d\x8a\x5b" + "\x8b\x80\x7f\xaf\xb8\xe0\xa3\xdf\xc7\x37\x72\x3e\xe6\xb4\xb7\xd9\x3a\x25" + "\x84\xee\x6a\x64\x9d\x06\x09\x53\x74\x88\x34\xb2\x45\x45\x98\x39\x4e\xe0" + "\xaa\xb1\x2d\x7b\x61\xa5\x1f\x52\x7a\x9a\x41\xf6\xc1\x68\x7f\xe2\x53\x72" + "\x98\xca\x2a\x8f\x59\x46\xf8\xe5\xfd\x09\x1d\xbd\xcb\x02\x01\x11\x02\x81" + "\x81\x00\xa5\xda\xfc\x53\x41\xfa\xf2\x89\xc4\xb9\x88\xdb\x30\xc1\xcd\xf8" + "\x3f\x31\x25\x1e\x06\x68\xb4\x27\x84\x81\x38\x01\x57\x96\x41\xb2\x94\x10" + "\xb3\xc7\x99\x8d\x6b\xc4\x65\x74\x5e\x5c\x39\x26\x69\xd6\x87\x0d\xa2\xc0" + "\x82\xa9\x39\xe3\x7f\xdc\xb8\x2e\xc9\x3e\xda\xc9\x7f\xf3\xad\x59\x50\xac" + "\xcf\xbc\x11\x1c\x76\xf1\xa9\x52\x94\x44\xe5\x6a\xaf\x68\xc5\x6c\x09\x2c" + "\xd3\x8d\xc3\xbe\xf5\xd2\x0a\x93\x99\x26\xed\x4f\x74\xa1\x3e\xdd\xfb\xe1" + "\xa1\xce\xcc\x48\x94\xaf\x94\x28\xc2\xb7\xb8\x88\x3f\xe4\x46\x3a\x4b\xc8" + "\x5b\x1c\xb3\xc1\x02\x41\x00\xee\xcf\xae\x81\xb1\xb9\xb3\xc9\x08\x81\x0b" + "\x10\xa1\xb5\x60\x01\x99\xeb\x9f\x44\xae\xf4\xfd\xa4\x93\xb8\x1a\x9e\x3d" + "\x84\xf6\x32\x12\x4e\xf0\x23\x6e\x5d\x1e\x3b\x7e\x28\xfa\xe7\xaa\x04\x0a" + "\x2d\x5b\x25\x21\x76\x45\x9d\x1f\x39\x75\x41\xba\x2a\x58\xfb\x65\x99\x02" + "\x41\x00\xc9\x7f\xb1\xf0\x27\xf4\x53\xf6\x34\x12\x33\xea\xaa\xd1\xd9\x35" + "\x3f\x6c\x42\xd0\x88\x66\xb1\xd0\x5a\x0f\x20\x35\x02\x8b\x9d\x86\x98\x40" + "\xb4\x16\x66\xb4\x2e\x92\xea\x0d\xa3\xb4\x32\x04\xb5\xcf\xce\x33\x52\x52" + "\x4d\x04\x16\xa5\xa4\x41\xe7\x00\xaf\x46\x15\x03\x02\x40\x54\x49\x4c\xa6" + "\x3e\xba\x03\x37\xe4\xe2\x40\x23\xfc\xd6\x9a\x5a\xeb\x07\xdd\xdc\x01\x83" + "\xa4\xd0\xac\x9b\x54\xb0\x51\xf2\xb1\x3e\xd9\x49\x09\x75\xea\xb7\x74\x14" + "\xff\x59\xc1\xf7\x69\x2e\x9a\x2e\x20\x2b\x38\xfc\x91\x0a\x47\x41\x74\xad" + "\xc9\x3c\x1f\x67\xc9\x81\x02\x40\x47\x1e\x02\x90\xff\x0a\xf0\x75\x03\x51" + "\xb7\xf8\x78\x86\x4c\xa9\x61\xad\xbd\x3a\x8a\x7e\x99\x1c\x5c\x05\x56\xa9" + "\x4c\x31\x46\xa7\xf9\x80\x3f\x8f\x6f\x8a\xe3\x42\xe9\x31\xfd\x8a\xe4\x7a" + "\x22\x0d\x1b\x99\xa4\x95\x84\x98\x07\xfe\x39\xf9\x24\x5a\x98\x36\xda\x3d" + "\x02\x41\x00\xb0\x6c\x4f\xda\xbb\x63\x01\x19\x8d\x26\x5b\xdb\xae\x94\x23" + "\xb3\x80\xf2\x71\xf7\x34\x53\x88\x50\x93\x07\x7f\xcd\x39\xe2\x11\x9f\xc9" + "\x86\x32\x15\x4f\x58\x83\xb1\x67\xa9\x67\xbf\x40\x2b\x4e\x9e\x2e\x0f\x96" + "\x56\xe6\x98\xea\x36\x66\xed\xfb\x25\x79\x80\x39\xf7"; + +// kOAEPCiphertext3 is a sample encryption of |kPlaintext| with |kKey3| using +// RSA OAEP. +static const uint8_t kOAEPCiphertext3[] = + "\xb8\x24\x6b\x56\xa6\xed\x58\x81\xae\xb5\x85\xd9\xa2\x5b\x2a\xd7\x90\xc4" + "\x17\xe0\x80\x68\x1b\xf1\xac\x2b\xc3\xde\xb6\x9d\x8b\xce\xf0\xc4\x36\x6f" + "\xec\x40\x0a\xf0\x52\xa7\x2e\x9b\x0e\xff\xb5\xb3\xf2\xf1\x92\xdb\xea\xca" + "\x03\xc1\x27\x40\x05\x71\x13\xbf\x1f\x06\x69\xac\x22\xe9\xf3\xa7\x85\x2e" + "\x3c\x15\xd9\x13\xca\xb0\xb8\x86\x3a\x95\xc9\x92\x94\xce\x86\x74\x21\x49" + "\x54\x61\x03\x46\xf4\xd4\x74\xb2\x6f\x7c\x48\xb4\x2e\xe6\x8e\x1f\x57\x2a" + "\x1f\xc4\x02\x6a\xc4\x56\xb4\xf5\x9f\x7b\x62\x1e\xa1\xb9\xd8\x8f\x64\x20" + "\x2f\xb1"; + +static const uint8_t kTwoPrimeKey[] = + "\x30\x82\x04\xa1\x02\x01\x00\x02\x82\x01\x01\x00\x93\x3a\x4f\xc9\x6a\x0a" + "\x6b\x28\x04\xfa\xb7\x05\x56\xdf\xa0\xaa\x4f\xaa\xab\x94\xa0\xa9\x25\xef" + "\xc5\x96\xd2\xd4\x66\x16\x62\x2c\x13\x7b\x91\xd0\x36\x0a\x10\x11\x6d\x7a" + "\x91\xb6\xe4\x74\x57\xc1\x3d\x7a\xbe\x24\x05\x3a\x04\x0b\x73\x91\x53\xb1" + "\x74\x10\xe1\x87\xdc\x91\x28\x9c\x1e\xe5\xf2\xb9\xfc\xa2\x48\x34\xb6\x78" + "\xed\x6d\x95\xfb\xf2\xc0\x4e\x1c\xa4\x15\x00\x3c\x8a\x68\x2b\xd6\xce\xd5" + "\xb3\x9f\x66\x02\xa7\x0d\x08\xa3\x23\x9b\xe5\x36\x96\x13\x22\xf9\x69\xa6" + "\x87\x88\x9b\x85\x3f\x83\x9c\xab\x1a\x1b\x6d\x8d\x16\xf4\x5e\xbd\xee\x4b" + "\x59\x56\xf8\x9d\x58\xcd\xd2\x83\x85\x59\x43\x84\x63\x4f\xe6\x1a\x86\x66" + "\x0d\xb5\xa0\x87\x89\xb6\x13\x82\x43\xda\x34\x92\x3b\x68\xc4\x95\x71\x2f" + "\x15\xc2\xe0\x43\x67\x3c\x08\x00\x36\x10\xc3\xb4\x46\x4c\x4e\x6e\xf5\x44" + "\xa9\x04\x44\x9d\xce\xc7\x05\x79\xee\x11\xcf\xaf\x2c\xd7\x9a\x32\xd3\xa5" + "\x30\xd4\x3a\x78\x43\x37\x74\x22\x90\x24\x04\x11\xd7\x95\x08\x52\xa4\x71" + "\x41\x68\x94\xb0\xa0\xc3\xec\x4e\xd2\xc4\x30\x71\x98\x64\x9c\xe3\x7c\x76" + "\xef\x33\xa3\x2b\xb1\x87\x63\xd2\x5c\x09\xfc\x90\x2d\x92\xf4\x57\x02\x01" + "\x03\x02\x82\x01\x00\x62\x26\xdf\xdb\x9c\x06\xf2\x1a\xad\xfc\x7a\x03\x8f" + "\x3f\xc0\x71\x8a\x71\xc7\xb8\x6b\x1b\x6e\x9f\xd9\x0f\x37\x38\x44\x0e\xec" + "\x1d\x62\x52\x61\x35\x79\x5c\x0a\xb6\x48\xfc\x61\x24\x98\x4d\x8f\xd6\x28" + "\xfc\x7e\xc2\xae\x26\xad\x5c\xf7\xb6\x37\xcb\xa2\xb5\xeb\xaf\xe8\x60\xc5" + "\xbd\x69\xee\xa1\xd1\x53\x16\xda\xcd\xce\xfb\x48\xf3\xb9\x52\xa1\xd5\x89" + "\x68\x6d\x63\x55\x7d\xb1\x9a\xc7\xe4\x89\xe3\xcd\x14\xee\xac\x6f\x5e\x05" + "\xc2\x17\xbd\x43\x79\xb9\x62\x17\x50\xf1\x19\xaf\xb0\x67\xae\x2a\x57\xbd" + "\xc7\x66\xbc\xf3\xb3\x64\xa1\xe3\x16\x74\x9e\xea\x02\x5c\xab\x94\xd8\x97" + "\x02\x42\x0c\x2c\xba\x54\xb9\xaf\xe0\x45\x93\xad\x7f\xb3\x10\x6a\x96\x50" + "\x4b\xaf\xcf\xc8\x27\x62\x2d\x83\xe9\x26\xc6\x94\xc1\xef\x5c\x8e\x06\x42" + "\x53\xe5\x56\xaf\xc2\x99\x01\xaa\x9a\x71\xbc\xe8\x21\x33\x2a\x2d\xa3\x36" + "\xac\x1b\x86\x19\xf8\xcd\x1f\x80\xa4\x26\x98\xb8\x9f\x62\x62\xd5\x1a\x7f" + "\xee\xdb\xdf\x81\xd3\x21\xdb\x33\x92\xee\xff\xe2\x2f\x32\x77\x73\x6a\x58" + "\xab\x21\xf3\xe3\xe1\xbc\x4f\x12\x72\xa6\xb5\xc2\xfb\x27\x9e\xc8\xca\xab" + "\x64\xa0\x87\x07\x9d\xef\xca\x0f\xdb\x02\x81\x81\x00\xe6\xd3\x4d\xc0\xa1" + "\x91\x0e\x62\xfd\xb0\xdd\xc6\x30\xb8\x8c\xcb\x14\xc1\x4b\x69\x30\xdd\xcd" + "\x86\x67\xcb\x37\x14\xc5\x03\xd2\xb4\x69\xab\x3d\xe5\x16\x81\x0f\xe5\x50" + "\xf4\x18\xb1\xec\xbc\x71\xe9\x80\x99\x06\xe4\xa3\xfe\x44\x84\x4a\x2d\x1e" + "\x07\x7f\x22\x70\x6d\x4f\xd4\x93\x0b\x8b\x99\xce\x1e\xab\xcd\x4c\xd2\xd3" + "\x10\x47\x5c\x09\x9f\x6d\x82\xc0\x08\x75\xe3\x3d\x83\xc2\x19\x50\x29\xec" + "\x1f\x84\x29\xcc\xf1\x56\xee\xbd\x54\x5d\xe6\x19\xdf\x0d\x1c\xa4\xbb\x0a" + "\xfe\x84\x44\x29\x1d\xf9\x5c\x80\x96\x5b\x24\xb4\xf7\x02\x1b\x02\x81\x81" + "\x00\xa3\x48\xf1\x9c\x58\xc2\x5f\x38\xfb\xd8\x12\x39\xf1\x8e\x73\xa1\xcf" + "\x78\x12\xe0\xed\x2a\xbb\xef\xac\x23\xb2\xbf\xd6\x0c\xe9\x6e\x1e\xab\xea" + "\x3f\x68\x36\xa7\x1f\xe5\xab\xe0\x86\xa5\x76\x32\x98\xdd\x75\xb5\x2b\xbc" + "\xcb\x8a\x03\x00\x7c\x2e\xca\xf8\xbc\x19\xe4\xe3\xa3\x31\xbd\x1d\x20\x2b" + "\x09\xad\x6f\x4c\xed\x48\xd4\xdf\x87\xf9\xf0\x46\xb9\x86\x4c\x4b\x71\xe7" + "\x48\x78\xdc\xed\xc7\x82\x02\x44\xd3\xa6\xb3\x10\x5f\x62\x81\xfc\xb8\xe4" + "\x0e\xf4\x1a\xdd\xab\x3f\xbc\x63\x79\x5b\x39\x69\x5e\xea\xa9\x15\xfe\x90" + "\xec\xda\x75\x02\x81\x81\x00\x99\xe2\x33\xd5\xc1\x0b\x5e\xec\xa9\x20\x93" + "\xd9\x75\xd0\x5d\xdc\xb8\x80\xdc\xf0\xcb\x3e\x89\x04\x45\x32\x24\xb8\x83" + "\x57\xe1\xcd\x9b\xc7\x7e\x98\xb9\xab\x5f\xee\x35\xf8\x10\x76\x9d\xd2\xf6" + "\x9b\xab\x10\xaf\x43\x17\xfe\xd8\x58\x31\x73\x69\x5a\x54\xc1\xa0\x48\xdf" + "\xe3\x0c\xb2\x5d\x11\x34\x14\x72\x88\xdd\xe1\xe2\x0a\xda\x3d\x5b\xbf\x9e" + "\x57\x2a\xb0\x4e\x97\x7e\x57\xd6\xbb\x8a\xc6\x9d\x6a\x58\x1b\xdd\xf6\x39" + "\xf4\x7e\x38\x3e\x99\x66\x94\xb3\x68\x6d\xd2\x07\x54\x58\x2d\x70\xbe\xa6" + "\x3d\xab\x0e\xe7\x6d\xcd\xfa\x01\x67\x02\x81\x80\x6c\xdb\x4b\xbd\x90\x81" + "\x94\xd0\xa7\xe5\x61\x7b\xf6\x5e\xf7\xc1\x34\xfa\xb7\x40\x9e\x1c\x7d\x4a" + "\x72\xc2\x77\x2a\x8e\xb3\x46\x49\x69\xc7\xf1\x7f\x9a\xcf\x1a\x15\x43\xc7" + "\xeb\x04\x6e\x4e\xcc\x65\xe8\xf9\x23\x72\x7d\xdd\x06\xac\xaa\xfd\x74\x87" + "\x50\x7d\x66\x98\x97\xc2\x21\x28\xbe\x15\x72\x06\x73\x9f\x88\x9e\x30\x8d" + "\xea\x5a\xa6\xa0\x2f\x26\x59\x88\x32\x4b\xef\x85\xa5\xe8\x9e\x85\x01\x56" + "\xd8\x8d\x19\xcc\xb5\x94\xec\x56\xa8\x7b\x42\xb4\xa2\xbc\x93\xc7\x7f\xd2" + "\xec\xfb\x92\x26\x46\x3f\x47\x1b\x63\xff\x0b\x48\x91\xa3\x02\x81\x80\x2c" + "\x4a\xb9\xa4\x46\x7b\xff\x50\x7e\xbf\x60\x47\x3b\x2b\x66\x82\xdc\x0e\x53" + "\x65\x71\xe9\xda\x2a\xb8\x32\x93\x42\xb7\xff\xea\x67\x66\xf1\xbc\x87\x28" + "\x65\x29\x79\xca\xab\x93\x56\xda\x95\xc1\x26\x44\x3d\x27\xc1\x91\xc6\x9b" + "\xd9\xec\x9d\xb7\x49\xe7\x16\xee\x99\x87\x50\x95\x81\xd4\x5c\x5b\x5a\x5d" + "\x0a\x43\xa5\xa7\x8f\x5a\x80\x49\xa0\xb7\x10\x85\xc7\xf4\x42\x34\x86\xb6" + "\x5f\x3f\x88\x9e\xc7\xf5\x59\x29\x39\x68\x48\xf2\xd7\x08\x5b\x92\x8e\x6b" + "\xea\xa5\x63\x5f\xc0\xfb\xe4\xe1\xb2\x7d\xb7\x40\xe9\x55\x06\xbf\x58\x25" + "\x6f"; + +static const uint8_t kTwoPrimeEncryptedMessage[] = { + 0x63, 0x0a, 0x30, 0x45, 0x43, 0x11, 0x45, 0xb7, 0x99, 0x67, 0x90, 0x35, + 0x37, 0x27, 0xff, 0xbc, 0xe0, 0xbf, 0xa6, 0xd1, 0x47, 0x50, 0xbb, 0x6c, + 0x1c, 0xaa, 0x66, 0xf2, 0xff, 0x9d, 0x9a, 0xa6, 0xb4, 0x16, 0x63, 0xb0, + 0xa1, 0x7c, 0x7c, 0x0c, 0xef, 0xb3, 0x66, 0x52, 0x42, 0xd7, 0x5e, 0xf3, + 0xa4, 0x15, 0x33, 0x40, 0x43, 0xe8, 0xb1, 0xfc, 0xe0, 0x42, 0x83, 0x46, + 0x28, 0xce, 0xde, 0x7b, 0x01, 0xeb, 0x28, 0x92, 0x70, 0xdf, 0x8d, 0x54, + 0x9e, 0xed, 0x23, 0xb4, 0x78, 0xc3, 0xca, 0x85, 0x53, 0x48, 0xd6, 0x8a, + 0x87, 0xf7, 0x69, 0xcd, 0x82, 0x8c, 0x4f, 0x5c, 0x05, 0x55, 0xa6, 0x78, + 0x89, 0xab, 0x4c, 0xd8, 0xa9, 0xd6, 0xa5, 0xf4, 0x29, 0x4c, 0x23, 0xc8, + 0xcf, 0xf0, 0x4c, 0x64, 0x6b, 0x4e, 0x02, 0x17, 0x69, 0xd6, 0x47, 0x83, + 0x30, 0x43, 0x02, 0x29, 0xda, 0xda, 0x75, 0x3b, 0xd7, 0xa7, 0x2b, 0x31, + 0xb3, 0xe9, 0x71, 0xa4, 0x41, 0xf7, 0x26, 0x9b, 0xcd, 0x23, 0xfa, 0x45, + 0x3c, 0x9b, 0x7d, 0x28, 0xf7, 0xf9, 0x67, 0x04, 0xba, 0xfc, 0x46, 0x75, + 0x11, 0x3c, 0xd5, 0x27, 0x43, 0x53, 0xb1, 0xb6, 0x9e, 0x18, 0xeb, 0x11, + 0xb4, 0x25, 0x20, 0x30, 0x0b, 0xe0, 0x1c, 0x17, 0x36, 0x22, 0x10, 0x0f, + 0x99, 0xb5, 0x50, 0x14, 0x73, 0x07, 0xf0, 0x2f, 0x5d, 0x4c, 0xe3, 0xf2, + 0x86, 0xc2, 0x05, 0xc8, 0x38, 0xed, 0xeb, 0x2a, 0x4a, 0xab, 0x76, 0xe3, + 0x1a, 0x75, 0x44, 0xf7, 0x6e, 0x94, 0xdc, 0x25, 0x62, 0x7e, 0x31, 0xca, + 0xc2, 0x73, 0x51, 0xb5, 0x03, 0xfb, 0xf9, 0xf6, 0xb5, 0x8d, 0x4e, 0x6c, + 0x21, 0x0e, 0xf9, 0x97, 0x26, 0x57, 0xf3, 0x52, 0x72, 0x07, 0xf8, 0xb4, + 0xcd, 0xb4, 0x39, 0xcf, 0xbf, 0x78, 0xcc, 0xb6, 0x87, 0xf9, 0xb7, 0x8b, + 0x6a, 0xce, 0x9f, 0xc8, +}; + +static const uint8_t kThreePrimeKey[] = + "\x30\x82\x04\xd7\x02\x01\x01\x02\x82\x01\x00\x62\x91\xe9\xea\xb3\x5d\x6c" + "\x29\xae\x21\x83\xbb\xb5\x82\xb1\x9e\xea\xe0\x64\x5b\x1e\x2f\x5e\x2c\x0a" + "\x80\x3d\x29\xd4\xfa\x9a\xe7\x44\xe6\x21\xbd\x98\xc0\x3d\xe0\x53\x59\xae" + "\xd3\x3e\xfe\xc4\xc2\xc4\x5a\x5a\x89\x07\xf4\x4f\xdc\xb0\x6a\xd4\x3e\x99" + "\x7d\x7a\x97\x26\x4e\xe1\x93\xca\x6e\xed\x07\xfc\xb4\xfa\x95\x1e\x73\x7b" + "\x86\x08\x6a\xb9\xd4\x29\xb0\x7e\x59\xb7\x9d\x7b\xeb\x67\x6e\xf0\xbb\x5e" + "\xcf\xb9\xcd\x58\x93\xf0\xe7\x88\x17\x6c\x0d\x76\x1e\xb9\x27\x9a\x4d\x02" + "\x16\xb6\x49\x6d\xa7\x83\x23\x4d\x02\x48\x0c\x0c\x1f\x0e\x85\x21\xe3\x06" + "\x76\x0a\x73\xe6\xc1\x21\xfa\x30\x18\x78\x29\x5c\x31\xd0\x29\xae\x6f\x7d" + "\x87\xd8\x2f\x16\xfa\xbc\x67\x8a\x94\x71\x59\x9b\xec\x22\x40\x55\x9f\xc2" + "\x94\xb5\xbd\x78\x01\xc9\xef\x18\xc8\x6d\x0d\xdc\x53\x42\xb2\x5c\xab\x65" + "\x05\xbd\x35\x08\x85\x1b\xf8\xe9\x47\xbc\xfe\xc5\xae\x47\x29\x63\x44\x8e" + "\x4d\xb7\x47\xab\x0d\xd8\x76\x68\x4f\xc7\x07\x02\xe4\x86\xb0\xcf\xd8\x19" + "\xad\xf4\x85\x76\x8b\x3b\x4e\x40\x8d\x29\x7a\x8a\x07\x36\xf3\x78\xae\x17" + "\xa6\x8f\x53\x58\x65\x4c\x86\x9e\xd7\x8b\xec\x38\x4f\x99\xc7\x02\x01\x03" + "\x02\x82\x01\x00\x41\xb6\x9b\xf1\xcc\xe8\xf2\xc6\x74\x16\x57\xd2\x79\x01" + "\xcb\xbf\x47\x40\x42\xe7\x69\x74\xe9\x72\xb1\xaa\xd3\x71\x38\xa7\x11\xef" + "\x83\x44\x16\x7e\x65\xd5\x7e\x95\x8c\xe6\x74\x8c\xd4\xa9\xd8\x81\xd8\x3c" + "\x3c\x5b\x5a\xa2\xdf\xe8\x75\x9c\x8d\x7f\x10\xfe\x51\xba\x19\x89\xeb\xb7" + "\xdc\x49\xf3\x5a\xa8\x78\xa7\x0e\x14\x4c\xfd\x04\x05\x9c\x7b\xe2\xc5\xa3" + "\x04\xee\xd9\x4c\xfd\x7d\x47\xb0\x0d\x9b\x3d\x70\x91\x81\x2c\xab\x2b\x87" + "\xad\x11\x68\x24\xfc\x2b\xd4\xee\x5e\x28\xeb\x6d\xab\xde\x0f\x77\x15\x58" + "\x76\x39\xc9\x59\x3a\x7f\x19\x9d\xc6\x7e\x86\xe4\xd5\x38\x70\x9e\xae\xb9" + "\xfb\x33\x33\xd1\x0c\x2d\xab\x01\x20\xe1\x8b\x29\x99\xd3\xeb\x87\x05\x72" + "\xaa\x43\x58\x64\x8e\x9e\x31\xdb\x45\x9b\x2b\xac\x58\x80\x5d\x33\xa2\x43" + "\x05\x96\xcc\xca\x2d\x04\x5f\xd6\xb7\x3d\x8b\x8f\x2d\xa3\xa5\xf8\x73\xf5" + "\xd7\xc0\x19\xff\x10\xe6\xee\x3a\x26\x2f\xe1\x64\x3d\x11\xcd\x2d\xe4\x0a" + "\x84\x27\xe3\xcb\x16\x62\x19\xe7\xe3\x0d\x13\xe8\x09\x5a\x53\xd0\x20\x56" + "\x15\xf5\xb3\x67\xac\xa1\xb5\x94\x6b\xab\xdc\x71\xc7\xbf\x0a\xde\x76\xf5" + "\x03\xa0\x30\xd8\x27\x9d\x00\x2b\x02\x57\x00\xf1\x4f\xc2\x86\x13\x06\x17" + "\xf7\x69\x7e\x37\xdf\x67\xc5\x32\xa0\x74\x1c\x32\x69\x0f\x9f\x08\x88\x24" + "\xb1\x51\xbc\xbc\x92\xba\x73\x1f\x9c\x75\xc2\x14\x6d\x4f\xc4\x5a\xcf\xda" + "\x44\x35\x00\x6b\x42\x3b\x9f\x14\xf1\x05\xb3\x51\x22\xb6\xbe\x9c\xe0\xc1" + "\x5c\x48\x61\xdf\x4e\x4c\x72\xb8\x05\x35\x7c\xac\xf1\xbb\xa0\x3b\x2a\xea" + "\xf7\x86\xe9\xd2\xff\x1e\x1d\x02\x56\x00\xca\xb1\x39\xf6\xa2\xc6\x3b\x65" + "\x45\x2f\x39\x00\xcd\x6e\xd6\x55\xf7\x71\x37\x89\xc2\xe7\x7a\xc0\x1a\xa6" + "\x2f\xea\x17\x7c\xaa\x2a\x91\x8f\xd4\xc7\x50\x8b\xab\x8e\x99\x3b\x33\x91" + "\xbc\x02\x10\x58\x4b\x58\x40\x9b\xc4\x8f\x48\x2b\xa7\x44\xfd\x07\x04\xf0" + "\x98\x67\x56\xea\x25\x92\x8b\x2e\x4b\x4a\xa1\xd3\xc2\xa4\xb4\x9b\x59\x70" + "\x32\xa6\xd8\x8b\xd9\x02\x57\x00\xa0\xdf\xd7\x04\x0c\xae\xba\xa4\xf0\xfe" + "\xcf\xea\x45\x2e\x21\xc0\x4d\x68\x21\x9b\x5f\xbf\x5b\x05\x6d\xcb\x8b\xd3" + "\x28\x61\xd1\xa2\x15\x12\xf9\x2c\x0d\x9e\x35\x2d\x91\xdf\xe6\xd8\x23\x55" + "\x9c\xd6\xd2\x6a\x0d\xf6\x03\xcc\xe0\xc1\xcf\x29\xbd\xeb\x2b\x92\xda\xeb" + "\xea\x34\x32\xf7\x25\x58\xce\x53\x1d\xf6\x7d\x15\x7c\xc7\x47\x4f\xaf\x46" + "\x8c\xaa\x14\x13\x02\x56\x00\x87\x20\xd1\x4f\x17\x2e\xd2\x43\x83\x74\xd0" + "\xab\x33\x9f\x39\x8e\xa4\xf6\x25\x06\x81\xef\xa7\x2a\xbc\x6e\xca\x9c\x0f" + "\xa8\x71\x71\xb6\x5f\xe3\x2f\x8b\x07\xc7\xb4\x66\x27\x77\xb6\x7d\x56\xb5" + "\x90\x32\x3a\xd5\xbd\x2d\xb4\xda\xc7\xc4\xd8\xa8\xaf\x58\xa0\x65\x9a\x39" + "\xf1\x6e\x61\xb2\x1e\xdc\xdc\x6b\xe2\x81\xc3\x23\x12\x3b\xa0\x21\xc4\x90" + "\x5d\x3b\x02\x57\x00\xe6\x8a\xaa\xb8\x6d\x2c\x81\x43\xb5\xd6\xa0\x2b\x42" + "\x49\xa9\x0a\x51\xfa\x18\xc8\x32\xea\x54\x18\xf3\x60\xc2\xb5\x4a\x43\x05" + "\x93\x9c\x01\xd9\x28\xed\x73\xfa\x82\xbc\x12\x64\xcb\xc4\x24\xa9\x3e\xae" + "\x7c\x4b\x8f\x94\x57\x7b\x14\x10\x41\xdc\x62\x12\x8c\xb2\x4a\x7c\xf6\x53" + "\xd4\xc6\xe4\xda\xd1\xa2\x00\x0e\x3d\x30\xf7\x05\x4f\x1d\x82\xbc\x52\xd9" + "\xb1\x30\x82\x01\x0a\x30\x82\x01\x06\x02\x56\x00\x84\x12\x4f\xf7\x3b\x65" + "\x53\x34\x6c\x6c\x4d\x77\xdf\xfd\x1f\xb6\x16\xe2\x25\x15\xca\xc9\xc1\x41" + "\x9a\x50\xda\xeb\x88\x4f\x3d\xb3\x01\x00\x44\xc4\xac\xe7\x14\x62\xa6\x56" + "\xde\xc5\xb7\xc3\x1d\x07\xbd\x7d\x64\xc5\x7e\x45\x25\x56\xed\x7a\xd2\x14" + "\xdb\x4e\x27\xd4\x1f\xf8\x94\xa7\xef\x07\xce\xdb\x24\xb7\xdd\x71\x5c\x63" + "\xc9\x33\xfe\xde\x40\x52\xeb\x02\x55\x58\x0c\x35\x4f\x7c\xee\x37\x78\x48" + "\x48\x33\xa5\x3f\xfe\x15\x24\x0f\x41\x6e\x0e\x87\x31\x2b\x81\x11\x8b\x3c" + "\x9d\x05\x8a\x29\x22\x00\xaa\xd8\x83\x1d\xef\x62\xec\x6e\xe4\x94\x83\xcf" + "\xd7\x68\xaf\xd3\xa8\xed\xd8\xfe\xd8\xc3\x8f\x48\xfc\x8c\x0d\xe7\x89\x6f" + "\xe2\xbf\xfb\x0d\xc5\x4a\x05\x34\x92\x18\x7a\x93\xa0\xe8\x42\x86\x22\xa9" + "\xe9\x80\x37\x47\x02\x55\x60\x76\xab\xde\x2b\xf5\xa2\x2c\xaa\x0c\x99\x81" + "\xee\x72\x2c\x7d\x22\x59\x2a\x35\xea\x50\x4e\x47\x6b\x92\x2d\x30\xa1\x01" + "\xa5\x9e\x26\x6e\x27\xca\xf5\xf2\x87\x5d\x31\xaf\xe9\x32\xcd\x10\xfd\x4d" + "\xdb\xf9\x86\x05\x12\x1b\x01\x84\x55\x97\x5f\xe2\x78\x27\xd9\xe4\x26\x7d" + "\xab\x0e\xe0\x1b\x6f\xcb\x4b\x14\xdd\xdc\xdc\x8b\xe8\x9f\xd0\x62\x96\xca" + "\xcf"; + +static const uint8_t kThreePrimeEncryptedMessage[] = { + 0x58, 0xd9, 0xea, 0x8a, 0xf6, 0x3d, 0xb4, 0xd9, 0xf7, 0xbb, 0x02, 0xc5, + 0x58, 0xd2, 0xa9, 0x46, 0x80, 0x70, 0x70, 0x16, 0x07, 0x64, 0x32, 0x4c, + 0x4e, 0x92, 0x61, 0xb7, 0xff, 0x92, 0xdc, 0xfc, 0xf8, 0xf0, 0x2c, 0x84, + 0x56, 0xbc, 0xe5, 0x93, 0x76, 0xe5, 0xa3, 0x72, 0x98, 0xf2, 0xdf, 0xef, + 0x99, 0x53, 0xf6, 0xd8, 0x4b, 0x09, 0xac, 0xa9, 0xa3, 0xdb, 0x63, 0xa1, + 0xb5, 0x09, 0x8e, 0x40, 0x84, 0x8f, 0x4d, 0xd5, 0x1d, 0xac, 0x6c, 0xaa, + 0x6b, 0x15, 0xe7, 0xb1, 0x0c, 0x67, 0xd2, 0xb2, 0x81, 0x58, 0x30, 0x0e, + 0x18, 0x27, 0xa1, 0x9b, 0x96, 0xad, 0xae, 0x76, 0x1a, 0x32, 0xf7, 0x10, + 0x0b, 0x53, 0x85, 0x31, 0xd6, 0x2a, 0xf6, 0x1c, 0x9f, 0xc2, 0xc7, 0xb1, + 0x05, 0x63, 0x0b, 0xa5, 0x07, 0x1f, 0x1c, 0x01, 0xf0, 0xe0, 0x06, 0xea, + 0x20, 0x69, 0x41, 0x19, 0x57, 0x92, 0x17, 0xf7, 0x0c, 0x5c, 0x66, 0x75, + 0x0e, 0xe5, 0xb3, 0xf1, 0x67, 0x3b, 0x27, 0x47, 0xb2, 0x8e, 0x1c, 0xb6, + 0x3f, 0xdd, 0x76, 0x42, 0x31, 0x13, 0x68, 0x96, 0xdf, 0x3b, 0xd4, 0x87, + 0xd9, 0x16, 0x44, 0x71, 0x52, 0x2e, 0x54, 0x3e, 0x09, 0xcd, 0x71, 0xc1, + 0x1e, 0x5e, 0x96, 0x13, 0xc9, 0x1e, 0xa4, 0xe6, 0xe6, 0x97, 0x2c, 0x6b, + 0xf2, 0xa9, 0x5c, 0xc6, 0x60, 0x2a, 0xbc, 0x82, 0xf8, 0xcb, 0xd4, 0xd7, + 0xea, 0x8a, 0xa1, 0x8a, 0xd9, 0xa5, 0x14, 0x8b, 0x9e, 0xf9, 0x25, 0x02, + 0xd2, 0xab, 0x0c, 0x42, 0xca, 0x2d, 0x45, 0xa3, 0x56, 0x5e, 0xa2, 0x2a, + 0xc8, 0x60, 0xa5, 0x87, 0x5d, 0x85, 0x5c, 0xde, 0xc7, 0xa2, 0x47, 0xc3, + 0x99, 0x29, 0x23, 0x79, 0x36, 0x88, 0xad, 0x40, 0x3e, 0x27, 0x7d, 0xf0, + 0xb6, 0xfa, 0x95, 0x20, 0x3c, 0xec, 0xfc, 0x56, 0x3b, 0x20, 0x91, 0xee, + 0x98, 0x10, 0x2c, 0x82, +}; + +static const uint8_t kSixPrimeKey[] = + "\x30\x82\x05\x20\x02\x01\x01\x02\x82\x01\x00\x1c\x04\x39\x44\xb9\xb8\x71" + "\x1c\x1c\xf7\xdc\x11\x1b\x85\x3b\x2b\xe8\xa6\xeb\xeb\xe9\xb6\x86\x97\x73" + "\x5d\x75\x46\xd1\x35\x25\xf8\x30\x9a\xc3\x57\x44\x89\xa6\x44\x59\xe3\x3a" + "\x60\xb5\x33\x84\x72\xa4\x03\xc5\x1a\x20\x98\x70\xbd\xe8\x3b\xc1\x9b\x8a" + "\x3a\x24\x45\xb6\x6a\x73\xb4\xd0\x6c\x18\xc6\xa7\x94\xd3\x24\x70\xf0\x2d" + "\x0c\xa5\xb2\x3b\xc5\x33\x90\x9d\x56\x8d\x33\xf6\x93\x7d\xa7\x95\x88\x05" + "\xdf\xf5\x65\x58\xb9\x5b\xd3\x07\x9c\x16\x8e\x74\xfc\xb8\x76\xaf\x62\x99" + "\x6c\xd4\xc5\xb3\x69\xe5\x64\xdf\x38\x00\x25\x24\xe9\xb1\x4a\x85\xa6\xf4" + "\xb6\x23\x68\x67\x4a\x2c\xbd\x9d\x01\x3b\x04\x8c\x70\x94\x82\x76\x45\x0c" + "\x8b\x95\x8a\x07\x1c\x32\xe7\x09\x97\x3a\xfd\xca\x57\xe9\x57\x0c\xae\x2b" + "\xa3\x25\xd1\xf2\x0d\x34\xa1\xe6\x2f\x7b\x1b\x36\x53\x83\x95\xb9\x26\x6e" + "\x4f\x36\x26\xf8\x47\xae\xdf\xe8\x4d\xf6\xb2\xff\x03\x23\x74\xfa\xa5\x6d" + "\xcb\xcb\x80\x12\xc3\x77\xf0\x19\xb7\xf2\x6b\x19\x5c\xde\x0a\xd7\xee\x8c" + "\x48\x2f\x50\x24\xa5\x2e\xcc\x2a\xed\xc2\x35\xe0\x3d\x29\x31\x17\xd6\x8f" + "\x44\xaa\x5b\x33\xbd\xb4\x88\x87\xd9\x29\x3f\x94\xe7\x75\xe3\x02\x01\x03" + "\x02\x82\x01\x00\x12\xad\x7b\x83\x26\x7a\xf6\x12\xbd\xfa\x92\xb6\x12\x58" + "\xd2\x1d\x45\xc4\x9d\x47\xf1\x24\x59\xba\x4c\xe8\xf8\xd9\xe0\xce\x19\x50" + "\x20\x67\x2c\xe4\xd8\x5b\xc4\x2d\x91\x41\xeb\x05\x4f\xf4\xb4\x20\xc7\xbc" + "\xd6\xe2\x5c\xa0\x27\xcf\xb8\xb3\x3b\x5c\xeb\x5e\x96\xb7\x99\x4b\x8a\xc3" + "\x70\xaf\x7f\xd8\x5f\xeb\xcb\x1a\x79\x44\x68\x97\x84\xd8\x29\x87\x64\xba" + "\x18\x2e\x95\x66\x1a\x7d\xd9\x35\x3a\x5c\x92\x7a\x81\x1b\x6c\xa9\xf8\xfa" + "\x05\x23\x18\x5b\xb2\xf8\x77\x1c\xc5\x1b\x7d\x26\x5f\x48\x69\x1b\xc4\x34" + "\xef\x6e\xa1\x15\xd2\xb2\xac\xb8\xa8\xed\x1e\xee\xdc\xb5\xb9\x5c\x79\x25" + "\x48\xbb\xe5\x9d\xd8\xe5\xe2\x94\xdf\xd5\x32\x22\x84\xbf\xc2\xaa\xa4\x54" + "\xbb\x29\xdb\x13\x4a\x28\x3d\x83\x3a\xff\xa3\xae\x38\x08\xfc\x36\x84\x91" + "\x30\xd1\xfd\x82\x64\xf1\x0f\xae\xba\xd7\x9a\x43\x58\x03\x5e\x5f\x01\xcb" + "\x8b\x90\x8d\x77\x34\x6f\x37\x40\xb6\x6d\x22\x23\x90\xb2\xfd\x32\xb5\x96" + "\x45\xbf\xae\x8c\xc4\x62\x03\x6c\x68\x90\x59\x31\x1a\xcb\xfb\xa4\x0b\x94" + "\x15\x13\xda\x1a\x8d\xa7\x0b\x34\x62\x93\xea\xbe\x6e\x71\xc2\x1d\xc8\x9d" + "\xac\x66\xcc\x31\x87\xff\x99\xab\x02\x2c\x00\xa5\x57\x41\x66\x87\x68\x02" + "\x6a\xdf\x97\xb0\xfe\x6b\x34\xc4\x33\x88\x2b\xce\x82\xaf\x2d\x33\x5a\xad" + "\x75\x2d\xac\xa5\xd6\x3a\x2d\x65\x43\x68\xfb\x44\x9e\xb8\x25\x05\xed\x97" + "\x02\x2c\x00\xd2\x77\x34\x24\xac\x60\x9a\xc4\x68\x34\xe5\x6a\xa3\xdc\xe2" + "\xb0\x58\x5c\x35\x83\x5a\xc7\xa7\xc1\x0b\x7e\x9e\xa5\x85\x32\x47\x93\x22" + "\xee\xb6\x59\xe9\xe3\x61\x94\xd0\x0e\xcb\x02\x2b\x6e\x3a\x2b\x99\xaf\x9a" + "\xac\x47\x3f\xba\x75\xfe\xf2\x23\x2d\x77\xb0\x1d\x34\x57\x1f\x73\x77\x91" + "\xc8\xf8\xc9\x1d\xc3\xe4\x26\xc8\xee\x2c\xf0\xa7\x83\x14\x7a\xc3\x59\x49" + "\x0f\x02\x2c\x00\x8c\x4f\x78\x18\x72\xeb\x11\xd8\x45\x78\x98\xf1\xc2\x93" + "\x41\xca\xe5\x92\xce\x57\x91\xda\x6f\xd6\x07\xa9\xbf\x19\x03\x76\xda\x62" + "\x17\x49\xce\xe6\x9b\xec\xeb\xb8\x8a\xb4\x87\x02\x2c\x00\xa3\xc2\x29\xa6" + "\xa7\xe1\x3c\xe9\xcf\x0f\x50\x51\x1c\xcc\xc8\x5b\x08\x9c\x97\x24\x3a\x86" + "\x23\xa8\x0b\xbb\x54\xa6\xb9\x70\x3d\x1d\xd0\x1b\xa3\xac\xd9\xb2\x03\x80" + "\xd7\x67\xec\x30\x82\x02\x29\x30\x81\x88\x02\x2c\x00\x97\x5d\x3b\xf2\xcc" + "\xba\xd9\x77\x67\xaa\xd2\x22\xa7\xa3\x49\x08\xc7\xb8\x27\xa1\x59\x4b\xa7" + "\xa5\xd2\x74\x05\xe7\x5a\x35\xd7\x25\x79\x18\x20\x8a\x25\xec\x3b\x52\xaf" + "\xcb\xdb\x02\x2b\x64\xe8\xd2\xa1\xdd\xd1\xe6\x4f\x9a\x71\xe1\x6c\x6f\xc2" + "\x30\xb0\x85\x25\x6f\xc0\xe6\x32\x6f\xc3\xe1\xa2\xae\x9a\x3c\x23\xe4\xc3" + "\xa6\x10\x15\xb1\x6e\x9d\x7c\xe1\xca\x87\xe7\x02\x2b\x5e\xef\x25\x29\xed" + "\xf6\x52\x15\xd3\x60\xb6\x88\xcf\x0f\xe2\x24\xa4\x04\x97\x9c\x9d\x58\x13" + "\xbb\x00\x6d\x39\xf6\xad\x21\x7e\x56\x2c\x2e\x06\x06\xc4\x6d\x44\xac\x79" + "\x1f\xe5\x30\x81\x89\x02\x2c\x00\xdb\xf1\x78\xf9\xa4\x94\xea\x39\x8a\x3f" + "\x23\x48\x2a\x23\x8f\xd2\x18\x97\xd2\xdf\x0f\xb8\x2b\x33\xa0\xe8\x8f\xbc" + "\x4e\x42\xfd\x54\xc7\x0f\xde\xba\x6d\xba\x96\xa7\xce\x67\x3d\x02\x2c\x00" + "\x92\xa0\xfb\x51\x18\x63\x46\xd1\x06\xd4\xc2\x30\x1c\x17\xb5\x36\xbb\x0f" + "\xe1\xea\x0a\x7a\xc7\x77\xc0\x9b\x0a\x7d\x89\x81\xfe\x38\x84\xb5\x3f\x26" + "\xf3\xd1\xb9\xc5\x34\x44\xd3\x02\x2b\x4c\xbd\x1d\x44\xc8\x19\x23\xd8\xb3" + "\x96\x66\x4b\x62\xcb\x3e\xe6\x6c\x11\xdf\xb2\x92\xd3\xc8\x34\xb9\xa6\x5a" + "\x2f\x19\xf4\x0b\xb2\xe6\x8e\xa6\xaf\xa3\xae\xa4\xb3\x92\xc4\x79\x30\x81" + "\x85\x02\x2b\x00\x89\xab\x30\xfc\x7b\x37\x94\x11\x9f\x4d\x31\x3b\xac\x09" + "\x57\xe6\x64\xec\xa0\xc8\xf8\x04\x1a\xf9\x2a\xa4\x4b\x36\x18\xbb\x5f\xdc" + "\xcd\xf0\xc8\xcb\x97\xd1\xdf\x13\x12\x3f\x02\x2a\x5b\xc7\x75\xfd\xa7\x7a" + "\x62\xb6\x6a\x33\x76\x27\xc8\x06\x3a\x99\x98\x9d\xc0\x85\xfa\xad\x67\x50" + "\xc7\x18\x32\x24\x10\x7c\xea\x93\x33\xf5\xdb\x32\x65\x36\x94\xb7\x61\x7f" + "\x02\x2a\x16\x6c\x96\xa1\x50\x6f\x3a\x92\xc0\x75\x43\xb5\x6b\x9c\x17\x09" + "\xd3\xf0\x67\x69\x45\x92\xfb\x7b\x50\xa8\x42\x9b\x33\x92\xab\xd5\xe6\x49" + "\xb3\x26\x99\x55\x16\x3a\x39\x63\x30\x81\x87\x02\x2b\x00\xc1\x25\x19\x1d" + "\x6e\x18\xcb\x2d\x64\xe2\xe6\xb6\x1c\xe4\xaa\x9c\xb9\xee\x18\xd4\xf7\x5f" + "\x66\x40\xf0\xe1\x31\x38\xf2\x53\x00\x8b\xcc\xe4\x0d\xb7\x81\xb4\xe6\x1c" + "\x19\xaf\x02\x2b\x00\x80\xc3\x66\x13\x9e\xbb\x32\x1e\x43\x41\xef\x24\x13" + "\x43\x1c\x68\x7b\xf4\x10\x8d\xfa\x3f\x99\x80\xa0\x96\x20\xd0\xa1\x8c\xab" + "\x07\xdd\xed\x5e\x7a\x56\x78\x99\x68\x11\x1f\x02\x2b\x00\xb0\x59\xea\x67" + "\x93\x42\xbf\x07\x54\x38\x41\xcb\x73\xa4\x0e\xc2\xae\x56\x19\x41\xc9\x8a" + "\xb2\x2f\xa8\x0a\xb1\x4e\x12\x39\x2e\xc0\x94\x9a\xc6\xa3\xe4\xaf\x8a\x16" + "\x06\xb8"; + +static const uint8_t kSixPrimeEncryptedMessage[] = { + 0x0a, 0xcb, 0x6c, 0x02, 0x9d, 0x1a, 0x7c, 0xf3, 0x4e, 0xff, 0x16, 0x88, + 0xee, 0x22, 0x1d, 0x8d, 0xd2, 0xfd, 0xde, 0x83, 0xb3, 0xd9, 0x35, 0x2c, + 0x82, 0xe0, 0xff, 0xe6, 0x79, 0x6d, 0x06, 0x21, 0x74, 0xa8, 0x04, 0x0c, + 0xe2, 0xd3, 0x98, 0x3f, 0xbf, 0xd0, 0xe9, 0x88, 0x24, 0xe2, 0x05, 0xa4, + 0x45, 0x51, 0x87, 0x6b, 0x1c, 0xef, 0x5f, 0x2d, 0x61, 0xb6, 0xf1, 0x4c, + 0x1f, 0x3d, 0xbf, 0x4b, 0xf2, 0xda, 0x09, 0x97, 0x81, 0xde, 0x91, 0xb7, + 0x0d, 0xb4, 0xc2, 0xab, 0x41, 0x64, 0x9d, 0xd9, 0x39, 0x46, 0x79, 0x66, + 0x43, 0xf1, 0x34, 0x21, 0x56, 0x2f, 0xc6, 0x68, 0x40, 0x4a, 0x2d, 0x73, + 0x96, 0x50, 0xe1, 0xb0, 0xaf, 0x49, 0x39, 0xb4, 0xf0, 0x3a, 0x78, 0x38, + 0x70, 0xa9, 0x91, 0x5d, 0x5e, 0x07, 0xf4, 0xec, 0xbb, 0xc4, 0xe5, 0x8a, + 0xb8, 0x06, 0xba, 0xdf, 0xc6, 0x48, 0x78, 0x4b, 0xca, 0x2a, 0x8a, 0x92, + 0x64, 0xe3, 0xa6, 0xae, 0x87, 0x97, 0x12, 0x16, 0x46, 0x67, 0x59, 0xdf, + 0xf2, 0xf3, 0x89, 0x6f, 0xe8, 0xa9, 0x13, 0x57, 0x63, 0x4e, 0x07, 0x98, + 0xcc, 0x73, 0xa0, 0x84, 0x9d, 0xe8, 0xb3, 0x50, 0x59, 0xb5, 0x51, 0xb3, + 0x41, 0x7d, 0x55, 0xfe, 0xd9, 0xf0, 0xc6, 0xff, 0x6e, 0x96, 0x4f, 0x22, + 0xb2, 0x0d, 0x6b, 0xc9, 0x83, 0x2d, 0x98, 0x98, 0xb2, 0xd1, 0xb7, 0xe4, + 0x50, 0x83, 0x1a, 0xa9, 0x02, 0x9f, 0xaf, 0x54, 0x74, 0x2a, 0x2c, 0x63, + 0x10, 0x79, 0x45, 0x5c, 0x95, 0x0d, 0xa1, 0x9b, 0x55, 0xf3, 0x1e, 0xb7, + 0x56, 0x59, 0xf1, 0x59, 0x8d, 0xd6, 0x15, 0x89, 0xf6, 0xfe, 0xc0, 0x00, + 0xdd, 0x1f, 0x2b, 0xf0, 0xf7, 0x5d, 0x64, 0x84, 0x76, 0xd3, 0xc2, 0x92, + 0x35, 0xac, 0xb5, 0xf9, 0xf6, 0xa8, 0x05, 0x89, 0x4c, 0x95, 0x41, 0x4e, + 0x34, 0x25, 0x11, 0x14, +}; + +// kEstonianRSAKey is an RSAPublicKey encoded with a negative modulus. See +// https://crbug.com/532048. +static const uint8_t kEstonianRSAKey[] = { + 0x30, 0x82, 0x01, 0x09, 0x02, 0x82, 0x01, 0x00, 0x96, 0xa6, 0x2e, 0x9c, + 0x4e, 0x6a, 0xc3, 0xcc, 0xcd, 0x8f, 0x70, 0xc3, 0x55, 0xbf, 0x5e, 0x9c, + 0xd4, 0xf3, 0x17, 0xc3, 0x97, 0x70, 0xae, 0xdf, 0x12, 0x5c, 0x15, 0x80, + 0x03, 0xef, 0x2b, 0x18, 0x9d, 0x6a, 0xcb, 0x52, 0x22, 0xc1, 0x81, 0xb8, + 0x7e, 0x61, 0xe8, 0x0f, 0x79, 0x24, 0x0f, 0x82, 0x70, 0x24, 0x4e, 0x29, + 0x20, 0x05, 0x54, 0xeb, 0xd4, 0xa9, 0x65, 0x59, 0xb6, 0x3c, 0x75, 0x95, + 0x2f, 0x4c, 0xf6, 0x9d, 0xd1, 0xaf, 0x5f, 0x14, 0x14, 0xe7, 0x25, 0xea, + 0xa5, 0x47, 0x5d, 0xc6, 0x3e, 0x28, 0x8d, 0xdc, 0x54, 0x87, 0x2a, 0x7c, + 0x10, 0xe9, 0xc6, 0x76, 0x2d, 0xe7, 0x79, 0xd8, 0x0e, 0xbb, 0xa9, 0xac, + 0xb5, 0x18, 0x98, 0xd6, 0x47, 0x6e, 0x06, 0x70, 0xbf, 0x9e, 0x82, 0x25, + 0x95, 0x4e, 0xfd, 0x70, 0xd7, 0x73, 0x45, 0x2e, 0xc1, 0x1f, 0x7a, 0x9a, + 0x9d, 0x60, 0xc0, 0x1f, 0x67, 0x06, 0x2a, 0x4e, 0x87, 0x3f, 0x19, 0x88, + 0x69, 0x64, 0x4d, 0x9f, 0x75, 0xf5, 0xd3, 0x1a, 0x41, 0x3d, 0x35, 0x17, + 0xb6, 0xd1, 0x44, 0x0d, 0x25, 0x8b, 0xe7, 0x94, 0x39, 0xb0, 0x7c, 0xaf, + 0x3e, 0x6a, 0xfa, 0x8d, 0x90, 0x21, 0x0f, 0x8a, 0x43, 0x94, 0x37, 0x7c, + 0x2a, 0x15, 0x4c, 0xa0, 0xfa, 0xa9, 0x2f, 0x21, 0xa6, 0x6f, 0x8e, 0x2f, + 0x89, 0xbc, 0xbb, 0x33, 0xf8, 0x31, 0xfc, 0xdf, 0xcd, 0x68, 0x9a, 0xbc, + 0x75, 0x06, 0x95, 0xf1, 0x3d, 0xef, 0xca, 0x76, 0x27, 0xd2, 0xba, 0x8e, + 0x0e, 0x1c, 0x43, 0xd7, 0x70, 0xb9, 0xc6, 0x15, 0xca, 0xd5, 0x4d, 0x87, + 0xb9, 0xd1, 0xae, 0xde, 0x69, 0x73, 0x00, 0x2a, 0x97, 0x51, 0x4b, 0x30, + 0x01, 0xc2, 0x85, 0xd0, 0x05, 0xcc, 0x2e, 0xe8, 0xc7, 0x42, 0xe7, 0x94, + 0x51, 0xe3, 0xf5, 0x19, 0x35, 0xdc, 0x57, 0x96, 0xe7, 0xd9, 0xb4, 0x49, + 0x02, 0x03, 0x01, 0x00, 0x01, +}; + +// kExponent1RSAKey is an RSAPublicKey encoded with an exponent of 1. See +// https://crbug.com/541257 +static const uint8_t kExponent1RSAKey[] = { + 0x30, 0x82, 0x01, 0x08, 0x02, 0x82, 0x01, 0x01, 0x00, 0xcf, 0x86, 0x9a, + 0x7d, 0x5c, 0x9f, 0xbd, 0x33, 0xbb, 0xc2, 0xb1, 0x06, 0xa8, 0x3e, 0xc5, + 0x18, 0xf3, 0x01, 0x04, 0xdd, 0x7a, 0x38, 0x0e, 0x8e, 0x8d, 0x10, 0xaa, + 0xf8, 0x64, 0x49, 0x82, 0xa6, 0x16, 0x9d, 0xd9, 0xae, 0x5e, 0x7f, 0x9b, + 0x53, 0xcb, 0xbb, 0x29, 0xda, 0x98, 0x47, 0x26, 0x88, 0x2e, 0x1d, 0x64, + 0xb3, 0xbc, 0x7e, 0x96, 0x3a, 0xa7, 0xd6, 0x87, 0xf6, 0xf5, 0x3f, 0xa7, + 0x3b, 0xd3, 0xc5, 0xd5, 0x61, 0x3c, 0x63, 0x05, 0xf9, 0xbc, 0x64, 0x1d, + 0x71, 0x65, 0xf5, 0xc8, 0xe8, 0x64, 0x41, 0x35, 0x88, 0x81, 0x6b, 0x2a, + 0x24, 0xbb, 0xdd, 0x9f, 0x75, 0x4f, 0xea, 0x35, 0xe5, 0x32, 0x76, 0x5a, + 0x8b, 0x7a, 0xb5, 0x92, 0x65, 0x34, 0xb7, 0x88, 0x42, 0x5d, 0x41, 0x0b, + 0xd1, 0x00, 0x2d, 0x43, 0x47, 0x55, 0x60, 0x3c, 0x0e, 0x60, 0x04, 0x5c, + 0x88, 0x13, 0xc7, 0x42, 0x55, 0x16, 0x31, 0x32, 0x81, 0xba, 0xde, 0xa9, + 0x56, 0xeb, 0xdb, 0x66, 0x7f, 0x31, 0xba, 0xe8, 0x87, 0x1a, 0xcc, 0xad, + 0x90, 0x86, 0x4b, 0xa7, 0x6d, 0xd5, 0xc1, 0xb7, 0xe7, 0x67, 0x56, 0x41, + 0xf7, 0x03, 0xb3, 0x09, 0x61, 0x63, 0xb5, 0xb0, 0x19, 0x7b, 0xc5, 0x91, + 0xc8, 0x96, 0x5b, 0x6a, 0x80, 0xa1, 0x53, 0x0f, 0x9a, 0x47, 0xb5, 0x9a, + 0x44, 0x53, 0xbd, 0x93, 0xe3, 0xe4, 0xce, 0x0c, 0x17, 0x11, 0x51, 0x1d, + 0xfd, 0x6c, 0x74, 0xe4, 0xec, 0x2a, 0xce, 0x57, 0x27, 0xcc, 0x83, 0x98, + 0x08, 0x32, 0x2c, 0xd5, 0x75, 0xa9, 0x27, 0xfe, 0xaa, 0x5e, 0x48, 0xc9, + 0x46, 0x9a, 0x29, 0x3f, 0xe6, 0x01, 0x4d, 0x97, 0x4a, 0x70, 0xd1, 0x5d, + 0xf8, 0xc0, 0x0b, 0x23, 0xcb, 0xbe, 0xf5, 0x70, 0x0b, 0xc2, 0xf2, 0xc0, + 0x33, 0x9c, 0xc4, 0x8b, 0x39, 0x7e, 0x3d, 0xc6, 0x23, 0x39, 0x9a, 0x98, + 0xdd, 0x02, 0x01, 0x01, +}; + +static bool TestRSA(const uint8_t *der, size_t der_len, + const uint8_t *oaep_ciphertext, + size_t oaep_ciphertext_len) { + ScopedRSA key(RSA_private_key_from_bytes(der, der_len)); + if (!key) { + return false; + } + + if (!RSA_check_key(key.get())) { + fprintf(stderr, "RSA_check_key failed\n"); + return false; + } + + uint8_t ciphertext[256]; + + size_t ciphertext_len = 0; + if (!RSA_encrypt(key.get(), &ciphertext_len, ciphertext, sizeof(ciphertext), + kPlaintext, kPlaintextLen, RSA_PKCS1_PADDING) || + ciphertext_len != RSA_size(key.get())) { + fprintf(stderr, "PKCS#1 v1.5 encryption failed!\n"); + return false; + } + + uint8_t plaintext[256]; + size_t plaintext_len = 0; + if (!RSA_decrypt(key.get(), &plaintext_len, plaintext, sizeof(plaintext), + ciphertext, ciphertext_len, RSA_PKCS1_PADDING) || + plaintext_len != kPlaintextLen || + memcmp(plaintext, kPlaintext, plaintext_len) != 0) { + fprintf(stderr, "PKCS#1 v1.5 decryption failed!\n"); + return false; + } + + ciphertext_len = 0; + if (!RSA_encrypt(key.get(), &ciphertext_len, ciphertext, sizeof(ciphertext), + kPlaintext, kPlaintextLen, RSA_PKCS1_OAEP_PADDING) || + ciphertext_len != RSA_size(key.get())) { + fprintf(stderr, "OAEP encryption failed!\n"); + return false; + } + + plaintext_len = 0; + if (!RSA_decrypt(key.get(), &plaintext_len, plaintext, sizeof(plaintext), + ciphertext, ciphertext_len, RSA_PKCS1_OAEP_PADDING) || + plaintext_len != kPlaintextLen || + memcmp(plaintext, kPlaintext, plaintext_len) != 0) { + fprintf(stderr, "OAEP decryption (encrypted data) failed!\n"); + return false; + } + + // |oaep_ciphertext| should decrypt to |kPlaintext|. + plaintext_len = 0; + if (!RSA_decrypt(key.get(), &plaintext_len, plaintext, sizeof(plaintext), + oaep_ciphertext, oaep_ciphertext_len, + RSA_PKCS1_OAEP_PADDING) || + plaintext_len != kPlaintextLen || + memcmp(plaintext, kPlaintext, plaintext_len) != 0) { + fprintf(stderr, "OAEP decryption (test vector data) failed!\n"); + return false; + } + + // Try decrypting corrupted ciphertexts. + memcpy(ciphertext, oaep_ciphertext, oaep_ciphertext_len); + for (size_t i = 0; i < oaep_ciphertext_len; i++) { + ciphertext[i] ^= 1; + if (RSA_decrypt(key.get(), &plaintext_len, plaintext, sizeof(plaintext), + ciphertext, oaep_ciphertext_len, RSA_PKCS1_OAEP_PADDING)) { + fprintf(stderr, "Corrupt data decrypted!\n"); + return false; + } + ERR_clear_error(); + ciphertext[i] ^= 1; + } + + // Test truncated ciphertexts. + for (size_t len = 0; len < oaep_ciphertext_len; len++) { + if (RSA_decrypt(key.get(), &plaintext_len, plaintext, sizeof(plaintext), + ciphertext, len, RSA_PKCS1_OAEP_PADDING)) { + fprintf(stderr, "Corrupt data decrypted!\n"); + return false; + } + ERR_clear_error(); + } + + return true; +} + +static bool TestMultiPrimeKey(int nprimes, const uint8_t *der, size_t der_size, + const uint8_t *enc, size_t enc_size) { + ScopedRSA rsa(d2i_RSAPrivateKey(nullptr, &der, der_size)); + if (!rsa) { + fprintf(stderr, "%d-prime key failed to parse.\n", nprimes); + ERR_print_errors_fp(stderr); + return false; + } + + if (!RSA_check_key(rsa.get())) { + fprintf(stderr, "RSA_check_key failed for %d-prime key.\n", nprimes); + ERR_print_errors_fp(stderr); + return false; + } + + uint8_t out[256]; + size_t out_len; + if (!RSA_decrypt(rsa.get(), &out_len, out, sizeof(out), enc, enc_size, + RSA_PKCS1_PADDING) || + out_len != 11 || + memcmp(out, "hello world", 11) != 0) { + fprintf(stderr, "%d-prime key failed to decrypt.\n", nprimes); + ERR_print_errors_fp(stderr); + return false; + } + + return true; +} + +static bool TestMultiPrimeKeygen() { + static const char kMessage[] = "Hello world."; + static const size_t kBits = 1024; + uint8_t encrypted[kBits / 8], decrypted[kBits / 8]; + size_t encrypted_len, decrypted_len; + + ScopedRSA rsa(RSA_new()); + ScopedBIGNUM e(BN_new()); + if (!rsa || !e || + !BN_set_word(e.get(), RSA_F4) || + !RSA_generate_multi_prime_key(rsa.get(), kBits, 3, e.get(), nullptr) || + !RSA_check_key(rsa.get()) || + !RSA_encrypt(rsa.get(), &encrypted_len, encrypted, sizeof(encrypted), + (const uint8_t *)kMessage, sizeof(kMessage), + RSA_PKCS1_PADDING) || + !RSA_decrypt(rsa.get(), &decrypted_len, decrypted, sizeof(decrypted), + encrypted, encrypted_len, RSA_PKCS1_PADDING) || + decrypted_len != sizeof(kMessage) || + memcmp(decrypted, kMessage, sizeof(kMessage)) != 0) { + ERR_print_errors_fp(stderr); + return false; + } + + return true; +} + +static bool TestBadKey() { + ScopedRSA key(RSA_new()); + ScopedBIGNUM e(BN_new()); + + if (!key || !e || !BN_set_word(e.get(), RSA_F4)) { + return false; + } + + if (!RSA_generate_key_ex(key.get(), 512, e.get(), nullptr)) { + fprintf(stderr, "RSA_generate_key_ex failed.\n"); + ERR_print_errors_fp(stderr); + return false; + } + + if (!BN_add(key->p, key->p, BN_value_one())) { + fprintf(stderr, "BN error.\n"); + ERR_print_errors_fp(stderr); + return false; + } + + if (RSA_check_key(key.get())) { + fprintf(stderr, "RSA_check_key passed with invalid key!\n"); + return false; + } + + ERR_clear_error(); + return true; +} + +static bool TestOnlyDGiven() { + static const char kN[] = + "00e77bbf3889d4ef36a9a25d4d69f3f632eb4362214c74517da6d6aeaa9bd09ac42b2662" + "1cd88f3a6eb013772fc3bf9f83914b6467231c630202c35b3e5808c659"; + static const char kE[] = "010001"; + static const char kD[] = + "0365db9eb6d73b53b015c40cd8db4de7dd7035c68b5ac1bf786d7a4ee2cea316eaeca21a" + "73ac365e58713195f2ae9849348525ca855386b6d028e437a9495a01"; + + uint8_t buf[64]; + unsigned buf_len = sizeof(buf); + ScopedRSA key(RSA_new()); + if (!key || + !BN_hex2bn(&key->n, kN) || + !BN_hex2bn(&key->e, kE) || + !BN_hex2bn(&key->d, kD) || + RSA_size(key.get()) > sizeof(buf)) { + return false; + } + + if (!RSA_check_key(key.get())) { + fprintf(stderr, "RSA_check_key failed with only n, d, and e given.\n"); + ERR_print_errors_fp(stderr); + return false; + } + + const uint8_t kDummyHash[16] = {0}; + + if (!RSA_sign(NID_sha256, kDummyHash, sizeof(kDummyHash), buf, &buf_len, + key.get())) { + fprintf(stderr, "RSA_sign failed with only n, d, and e given.\n"); + ERR_print_errors_fp(stderr); + return false; + } + + if (!RSA_verify(NID_sha256, kDummyHash, sizeof(kDummyHash), buf, buf_len, + key.get())) { + fprintf(stderr, "RSA_verify failed with only n, d, and e given.\n"); + ERR_print_errors_fp(stderr); + return false; + } + + // Keys without the public exponent must continue to work when blinding is + // disabled to support Java's RSAPrivateKeySpec API. See + // https://bugs.chromium.org/p/boringssl/issues/detail?id=12. + ScopedRSA key2(RSA_new()); + if (!key2 || + !BN_hex2bn(&key2->n, kN) || + !BN_hex2bn(&key2->d, kD)) { + return false; + } + key2->flags |= RSA_FLAG_NO_BLINDING; + + if (RSA_size(key2.get()) > sizeof(buf)) { + return false; + } + + if (!RSA_sign(NID_sha256, kDummyHash, sizeof(kDummyHash), buf, &buf_len, + key2.get())) { + fprintf(stderr, "RSA_sign failed with only n and d given.\n"); + ERR_print_errors_fp(stderr); + return false; + } + + // Verify the signature with |key|. |key2| has no public exponent. + if (!RSA_verify(NID_sha256, kDummyHash, sizeof(kDummyHash), buf, buf_len, + key.get())) { + fprintf(stderr, + "Could not verify signature produced from key with only n and d " + "given.\n"); + ERR_print_errors_fp(stderr); + return false; + } + + return true; +} + +static bool TestRecoverCRTParams() { + ScopedBIGNUM e(BN_new()); + if (!e || !BN_set_word(e.get(), RSA_F4)) { + return false; + } + + ERR_clear_error(); + + for (unsigned i = 0; i < 1; i++) { + ScopedRSA key1(RSA_new()); + if (!key1 || + !RSA_generate_key_ex(key1.get(), 512, e.get(), nullptr)) { + fprintf(stderr, "RSA_generate_key_ex failed.\n"); + ERR_print_errors_fp(stderr); + return false; + } + + if (!RSA_check_key(key1.get())) { + fprintf(stderr, "RSA_check_key failed with original key.\n"); + ERR_print_errors_fp(stderr); + return false; + } + + ScopedRSA key2(RSA_new()); + if (!key2) { + return false; + } + key2->n = BN_dup(key1->n); + key2->e = BN_dup(key1->e); + key2->d = BN_dup(key1->d); + if (key2->n == nullptr || key2->e == nullptr || key2->d == nullptr) { + return false; + } + + if (!RSA_recover_crt_params(key2.get())) { + fprintf(stderr, "RSA_recover_crt_params failed.\n"); + ERR_print_errors_fp(stderr); + return false; + } + + uint8_t buf[128]; + unsigned buf_len = sizeof(buf); + if (RSA_size(key2.get()) > buf_len) { + return false; + } + + if (!RSA_check_key(key2.get())) { + fprintf(stderr, "RSA_check_key failed with recovered key.\n"); + ERR_print_errors_fp(stderr); + return false; + } + + const uint8_t kDummyHash[16] = {0}; + if (!RSA_sign(NID_sha256, kDummyHash, sizeof(kDummyHash), buf, &buf_len, + key2.get())) { + fprintf(stderr, "RSA_sign failed with recovered key.\n"); + ERR_print_errors_fp(stderr); + return false; + } + + if (!RSA_verify(NID_sha256, kDummyHash, sizeof(kDummyHash), buf, buf_len, + key2.get())) { + fprintf(stderr, "RSA_verify failed with recovered key.\n"); + ERR_print_errors_fp(stderr); + return false; + } + } + + return true; +} + +static bool TestASN1() { + // Test that private keys may be decoded. + ScopedRSA rsa(RSA_private_key_from_bytes(kKey1, sizeof(kKey1) - 1)); + if (!rsa) { + return false; + } + + // Test that the serialization round-trips. + uint8_t *der; + size_t der_len; + if (!RSA_private_key_to_bytes(&der, &der_len, rsa.get())) { + return false; + } + ScopedOpenSSLBytes delete_der(der); + if (der_len != sizeof(kKey1) - 1 || memcmp(der, kKey1, der_len) != 0) { + return false; + } + + // Test that serializing public keys works. + if (!RSA_public_key_to_bytes(&der, &der_len, rsa.get())) { + return false; + } + delete_der.reset(der); + + // Public keys may be parsed back out. + rsa.reset(RSA_public_key_from_bytes(der, der_len)); + if (!rsa || rsa->p != NULL || rsa->q != NULL) { + return false; + } + + // Serializing the result round-trips. + uint8_t *der2; + size_t der2_len; + if (!RSA_public_key_to_bytes(&der2, &der2_len, rsa.get())) { + return false; + } + ScopedOpenSSLBytes delete_der2(der2); + if (der_len != der2_len || memcmp(der, der2, der_len) != 0) { + return false; + } + + // Public keys cannot be serialized as private keys. + if (RSA_private_key_to_bytes(&der, &der_len, rsa.get())) { + OPENSSL_free(der); + return false; + } + ERR_clear_error(); + + // Public keys with negative moduli are invalid. + rsa.reset(RSA_public_key_from_bytes(kEstonianRSAKey, + sizeof(kEstonianRSAKey))); + if (rsa) { + return false; + } + ERR_clear_error(); + + // But |RSA_parse_public_key_buggy| will accept it. + CBS cbs; + CBS_init(&cbs, kEstonianRSAKey, sizeof(kEstonianRSAKey)); + rsa.reset(RSA_parse_public_key_buggy(&cbs)); + if (!rsa || CBS_len(&cbs) != 0) { + return false; + } + + return true; +} + +static bool TestBadExponent() { + ScopedRSA rsa(RSA_public_key_from_bytes(kExponent1RSAKey, + sizeof(kExponent1RSAKey))); + + if (rsa) { + fprintf(stderr, "kExponent1RSAKey parsed but should have failed.\n"); + return false; + } + + ERR_clear_error(); + return true; +} + +int main(int argc, char *argv[]) { + CRYPTO_library_init(); + + if (!TestRSA(kKey1, sizeof(kKey1) - 1, kOAEPCiphertext1, + sizeof(kOAEPCiphertext1) - 1) || + !TestRSA(kKey2, sizeof(kKey2) - 1, kOAEPCiphertext2, + sizeof(kOAEPCiphertext2) - 1) || + !TestRSA(kKey3, sizeof(kKey3) - 1, kOAEPCiphertext3, + sizeof(kOAEPCiphertext3) - 1) || + !TestOnlyDGiven() || + !TestRecoverCRTParams() || + !TestBadKey() || + !TestMultiPrimeKey(2, kTwoPrimeKey, sizeof(kTwoPrimeKey) - 1, + kTwoPrimeEncryptedMessage, + sizeof(kTwoPrimeEncryptedMessage)) || + !TestMultiPrimeKey(3, kThreePrimeKey, sizeof(kThreePrimeKey) - 1, + kThreePrimeEncryptedMessage, + sizeof(kThreePrimeEncryptedMessage)) || + !TestMultiPrimeKey(6, kSixPrimeKey, sizeof(kSixPrimeKey) - 1, + kSixPrimeEncryptedMessage, + sizeof(kSixPrimeEncryptedMessage)) || + !TestMultiPrimeKeygen() || + !TestASN1() || + !TestBadExponent()) { + return 1; + } + + printf("PASS\n"); + return 0; +} diff --git a/external/boringssl/crypto/sha/CMakeLists.txt b/external/boringssl/crypto/sha/CMakeLists.txt new file mode 100644 index 0000000000..ecff09b82a --- /dev/null +++ b/external/boringssl/crypto/sha/CMakeLists.txt @@ -0,0 +1,66 @@ +include_directories(../../include) + +if (${ARCH} STREQUAL "x86_64") + set( + SHA_ARCH_SOURCES + + sha1-x86_64.${ASM_EXT} + sha256-x86_64.${ASM_EXT} + sha512-x86_64.${ASM_EXT} + ) +endif() + +if (${ARCH} STREQUAL "x86") + set( + SHA_ARCH_SOURCES + + sha1-586.${ASM_EXT} + sha256-586.${ASM_EXT} + sha512-586.${ASM_EXT} + ) +endif() + +if (${ARCH} STREQUAL "arm") + set( + SHA_ARCH_SOURCES + + sha1-armv4-large.${ASM_EXT} + sha256-armv4.${ASM_EXT} + sha512-armv4.${ASM_EXT} + ) +endif() + +if (${ARCH} STREQUAL "aarch64") + set( + SHA_ARCH_SOURCES + + sha1-armv8.${ASM_EXT} + sha256-armv8.${ASM_EXT} + sha512-armv8.${ASM_EXT} + ) +endif() + +add_library( + sha + + OBJECT + + sha1.c + sha256.c + sha512.c + + ${SHA_ARCH_SOURCES} +) + +perlasm(sha1-x86_64.${ASM_EXT} asm/sha1-x86_64.pl) +perlasm(sha256-x86_64.${ASM_EXT} asm/sha512-x86_64.pl sha256) +perlasm(sha512-x86_64.${ASM_EXT} asm/sha512-x86_64.pl sha512) +perlasm(sha1-586.${ASM_EXT} asm/sha1-586.pl) +perlasm(sha256-586.${ASM_EXT} asm/sha256-586.pl) +perlasm(sha512-586.${ASM_EXT} asm/sha512-586.pl) +perlasm(sha1-armv4-large.${ASM_EXT} asm/sha1-armv4-large.pl) +perlasm(sha256-armv4.${ASM_EXT} asm/sha256-armv4.pl) +perlasm(sha512-armv4.${ASM_EXT} asm/sha512-armv4.pl) +perlasm(sha1-armv8.${ASM_EXT} asm/sha1-armv8.pl) +perlasm(sha256-armv8.${ASM_EXT} asm/sha512-armv8.pl sha256) +perlasm(sha512-armv8.${ASM_EXT} asm/sha512-armv8.pl sha512) diff --git a/external/boringssl/crypto/sha/asm/sha1-586.pl b/external/boringssl/crypto/sha/asm/sha1-586.pl new file mode 100644 index 0000000000..35142737ed --- /dev/null +++ b/external/boringssl/crypto/sha/asm/sha1-586.pl @@ -0,0 +1,1471 @@ +#!/usr/bin/env perl + +# ==================================================================== +# [Re]written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== + +# "[Re]written" was achieved in two major overhauls. In 2004 BODY_* +# functions were re-implemented to address P4 performance issue [see +# commentary below], and in 2006 the rest was rewritten in order to +# gain freedom to liberate licensing terms. + +# January, September 2004. +# +# It was noted that Intel IA-32 C compiler generates code which +# performs ~30% *faster* on P4 CPU than original *hand-coded* +# SHA1 assembler implementation. To address this problem (and +# prove that humans are still better than machines:-), the +# original code was overhauled, which resulted in following +# performance changes: +# +# compared with original compared with Intel cc +# assembler impl. generated code +# Pentium -16% +48% +# PIII/AMD +8% +16% +# P4 +85%(!) +45% +# +# As you can see Pentium came out as looser:-( Yet I reckoned that +# improvement on P4 outweights the loss and incorporate this +# re-tuned code to 0.9.7 and later. +# ---------------------------------------------------------------- +# + +# August 2009. +# +# George Spelvin has tipped that F_40_59(b,c,d) can be rewritten as +# '(c&d) + (b&(c^d))', which allows to accumulate partial results +# and lighten "pressure" on scratch registers. This resulted in +# >12% performance improvement on contemporary AMD cores (with no +# degradation on other CPUs:-). Also, the code was revised to maximize +# "distance" between instructions producing input to 'lea' instruction +# and the 'lea' instruction itself, which is essential for Intel Atom +# core and resulted in ~15% improvement. + +# October 2010. +# +# Add SSSE3, Supplemental[!] SSE3, implementation. The idea behind it +# is to offload message schedule denoted by Wt in NIST specification, +# or Xupdate in OpenSSL source, to SIMD unit. The idea is not novel, +# and in SSE2 context was first explored by Dean Gaudet in 2004, see +# http://arctic.org/~dean/crypto/sha1.html. Since then several things +# have changed that made it interesting again: +# +# a) XMM units became faster and wider; +# b) instruction set became more versatile; +# c) an important observation was made by Max Locktykhin, which made +# it possible to reduce amount of instructions required to perform +# the operation in question, for further details see +# http://software.intel.com/en-us/articles/improving-the-performance-of-the-secure-hash-algorithm-1/. + +# April 2011. +# +# Add AVX code path, probably most controversial... The thing is that +# switch to AVX alone improves performance by as little as 4% in +# comparison to SSSE3 code path. But below result doesn't look like +# 4% improvement... Trouble is that Sandy Bridge decodes 'ro[rl]' as +# pair of µ-ops, and it's the additional µ-ops, two per round, that +# make it run slower than Core2 and Westmere. But 'sh[rl]d' is decoded +# as single µ-op by Sandy Bridge and it's replacing 'ro[rl]' with +# equivalent 'sh[rl]d' that is responsible for the impressive 5.1 +# cycles per processed byte. But 'sh[rl]d' is not something that used +# to be fast, nor does it appear to be fast in upcoming Bulldozer +# [according to its optimization manual]. Which is why AVX code path +# is guarded by *both* AVX and synthetic bit denoting Intel CPUs. +# One can argue that it's unfair to AMD, but without 'sh[rl]d' it +# makes no sense to keep the AVX code path. If somebody feels that +# strongly, it's probably more appropriate to discuss possibility of +# using vector rotate XOP on AMD... + +# March 2014. +# +# Add support for Intel SHA Extensions. + +###################################################################### +# Current performance is summarized in following table. Numbers are +# CPU clock cycles spent to process single byte (less is better). +# +# x86 SSSE3 AVX +# Pentium 15.7 - +# PIII 11.5 - +# P4 10.6 - +# AMD K8 7.1 - +# Core2 7.3 6.0/+22% - +# Westmere 7.3 5.5/+33% - +# Sandy Bridge 8.8 6.2/+40% 5.1(**)/+73% +# Ivy Bridge 7.2 4.8/+51% 4.7(**)/+53% +# Haswell 6.5 4.3/+51% 4.1(**)/+58% +# Bulldozer 11.6 6.0/+92% +# VIA Nano 10.6 7.5/+41% +# Atom 12.5 9.3(*)/+35% +# Silvermont 14.5 9.9(*)/+46% +# +# (*) Loop is 1056 instructions long and expected result is ~8.25. +# The discrepancy is because of front-end limitations, so +# called MS-ROM penalties, and on Silvermont even rotate's +# limited parallelism. +# +# (**) As per above comment, the result is for AVX *plus* sh[rl]d. + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +push(@INC,"${dir}","${dir}../../perlasm"); +require "x86asm.pl"; + +&asm_init($ARGV[0],"sha1-586.pl",$ARGV[$#ARGV] eq "386"); + +$xmm=$ymm=0; +for (@ARGV) { $xmm=1 if (/-DOPENSSL_IA32_SSE2/); } + +# In upstream, this is controlled by shelling out to the compiler to check +# versions, but BoringSSL is intended to be used with pre-generated perlasm +# output, so this isn't useful anyway. +$ymm = 1; + +$ymm = 0 unless ($xmm); + +$shaext=$xmm; ### set to zero if compiling for 1.0.1 + +# TODO(davidben): Consider enabling the Intel SHA Extensions code once it's +# been tested. +$shaext = 0; + +&external_label("OPENSSL_ia32cap_P") if ($xmm); + + +$A="eax"; +$B="ebx"; +$C="ecx"; +$D="edx"; +$E="edi"; +$T="esi"; +$tmp1="ebp"; + +@V=($A,$B,$C,$D,$E,$T); + +$alt=0; # 1 denotes alternative IALU implementation, which performs + # 8% *worse* on P4, same on Westmere and Atom, 2% better on + # Sandy Bridge... + +sub BODY_00_15 + { + local($n,$a,$b,$c,$d,$e,$f)=@_; + + &comment("00_15 $n"); + + &mov($f,$c); # f to hold F_00_19(b,c,d) + if ($n==0) { &mov($tmp1,$a); } + else { &mov($a,$tmp1); } + &rotl($tmp1,5); # tmp1=ROTATE(a,5) + &xor($f,$d); + &add($tmp1,$e); # tmp1+=e; + &mov($e,&swtmp($n%16)); # e becomes volatile and is loaded + # with xi, also note that e becomes + # f in next round... + &and($f,$b); + &rotr($b,2); # b=ROTATE(b,30) + &xor($f,$d); # f holds F_00_19(b,c,d) + &lea($tmp1,&DWP(0x5a827999,$tmp1,$e)); # tmp1+=K_00_19+xi + + if ($n==15) { &mov($e,&swtmp(($n+1)%16));# pre-fetch f for next round + &add($f,$tmp1); } # f+=tmp1 + else { &add($tmp1,$f); } # f becomes a in next round + &mov($tmp1,$a) if ($alt && $n==15); + } + +sub BODY_16_19 + { + local($n,$a,$b,$c,$d,$e,$f)=@_; + + &comment("16_19 $n"); + +if ($alt) { + &xor($c,$d); + &xor($f,&swtmp(($n+2)%16)); # f to hold Xupdate(xi,xa,xb,xc,xd) + &and($tmp1,$c); # tmp1 to hold F_00_19(b,c,d), b&=c^d + &xor($f,&swtmp(($n+8)%16)); + &xor($tmp1,$d); # tmp1=F_00_19(b,c,d) + &xor($f,&swtmp(($n+13)%16)); # f holds xa^xb^xc^xd + &rotl($f,1); # f=ROTATE(f,1) + &add($e,$tmp1); # e+=F_00_19(b,c,d) + &xor($c,$d); # restore $c + &mov($tmp1,$a); # b in next round + &rotr($b,$n==16?2:7); # b=ROTATE(b,30) + &mov(&swtmp($n%16),$f); # xi=f + &rotl($a,5); # ROTATE(a,5) + &lea($f,&DWP(0x5a827999,$f,$e));# f+=F_00_19(b,c,d)+e + &mov($e,&swtmp(($n+1)%16)); # pre-fetch f for next round + &add($f,$a); # f+=ROTATE(a,5) +} else { + &mov($tmp1,$c); # tmp1 to hold F_00_19(b,c,d) + &xor($f,&swtmp(($n+2)%16)); # f to hold Xupdate(xi,xa,xb,xc,xd) + &xor($tmp1,$d); + &xor($f,&swtmp(($n+8)%16)); + &and($tmp1,$b); + &xor($f,&swtmp(($n+13)%16)); # f holds xa^xb^xc^xd + &rotl($f,1); # f=ROTATE(f,1) + &xor($tmp1,$d); # tmp1=F_00_19(b,c,d) + &add($e,$tmp1); # e+=F_00_19(b,c,d) + &mov($tmp1,$a); + &rotr($b,2); # b=ROTATE(b,30) + &mov(&swtmp($n%16),$f); # xi=f + &rotl($tmp1,5); # ROTATE(a,5) + &lea($f,&DWP(0x5a827999,$f,$e));# f+=F_00_19(b,c,d)+e + &mov($e,&swtmp(($n+1)%16)); # pre-fetch f for next round + &add($f,$tmp1); # f+=ROTATE(a,5) +} + } + +sub BODY_20_39 + { + local($n,$a,$b,$c,$d,$e,$f)=@_; + local $K=($n<40)?0x6ed9eba1:0xca62c1d6; + + &comment("20_39 $n"); + +if ($alt) { + &xor($tmp1,$c); # tmp1 to hold F_20_39(b,c,d), b^=c + &xor($f,&swtmp(($n+2)%16)); # f to hold Xupdate(xi,xa,xb,xc,xd) + &xor($tmp1,$d); # tmp1 holds F_20_39(b,c,d) + &xor($f,&swtmp(($n+8)%16)); + &add($e,$tmp1); # e+=F_20_39(b,c,d) + &xor($f,&swtmp(($n+13)%16)); # f holds xa^xb^xc^xd + &rotl($f,1); # f=ROTATE(f,1) + &mov($tmp1,$a); # b in next round + &rotr($b,7); # b=ROTATE(b,30) + &mov(&swtmp($n%16),$f) if($n<77);# xi=f + &rotl($a,5); # ROTATE(a,5) + &xor($b,$c) if($n==39);# warm up for BODY_40_59 + &and($tmp1,$b) if($n==39); + &lea($f,&DWP($K,$f,$e)); # f+=e+K_XX_YY + &mov($e,&swtmp(($n+1)%16)) if($n<79);# pre-fetch f for next round + &add($f,$a); # f+=ROTATE(a,5) + &rotr($a,5) if ($n==79); +} else { + &mov($tmp1,$b); # tmp1 to hold F_20_39(b,c,d) + &xor($f,&swtmp(($n+2)%16)); # f to hold Xupdate(xi,xa,xb,xc,xd) + &xor($tmp1,$c); + &xor($f,&swtmp(($n+8)%16)); + &xor($tmp1,$d); # tmp1 holds F_20_39(b,c,d) + &xor($f,&swtmp(($n+13)%16)); # f holds xa^xb^xc^xd + &rotl($f,1); # f=ROTATE(f,1) + &add($e,$tmp1); # e+=F_20_39(b,c,d) + &rotr($b,2); # b=ROTATE(b,30) + &mov($tmp1,$a); + &rotl($tmp1,5); # ROTATE(a,5) + &mov(&swtmp($n%16),$f) if($n<77);# xi=f + &lea($f,&DWP($K,$f,$e)); # f+=e+K_XX_YY + &mov($e,&swtmp(($n+1)%16)) if($n<79);# pre-fetch f for next round + &add($f,$tmp1); # f+=ROTATE(a,5) +} + } + +sub BODY_40_59 + { + local($n,$a,$b,$c,$d,$e,$f)=@_; + + &comment("40_59 $n"); + +if ($alt) { + &add($e,$tmp1); # e+=b&(c^d) + &xor($f,&swtmp(($n+2)%16)); # f to hold Xupdate(xi,xa,xb,xc,xd) + &mov($tmp1,$d); + &xor($f,&swtmp(($n+8)%16)); + &xor($c,$d); # restore $c + &xor($f,&swtmp(($n+13)%16)); # f holds xa^xb^xc^xd + &rotl($f,1); # f=ROTATE(f,1) + &and($tmp1,$c); + &rotr($b,7); # b=ROTATE(b,30) + &add($e,$tmp1); # e+=c&d + &mov($tmp1,$a); # b in next round + &mov(&swtmp($n%16),$f); # xi=f + &rotl($a,5); # ROTATE(a,5) + &xor($b,$c) if ($n<59); + &and($tmp1,$b) if ($n<59);# tmp1 to hold F_40_59(b,c,d) + &lea($f,&DWP(0x8f1bbcdc,$f,$e));# f+=K_40_59+e+(b&(c^d)) + &mov($e,&swtmp(($n+1)%16)); # pre-fetch f for next round + &add($f,$a); # f+=ROTATE(a,5) +} else { + &mov($tmp1,$c); # tmp1 to hold F_40_59(b,c,d) + &xor($f,&swtmp(($n+2)%16)); # f to hold Xupdate(xi,xa,xb,xc,xd) + &xor($tmp1,$d); + &xor($f,&swtmp(($n+8)%16)); + &and($tmp1,$b); + &xor($f,&swtmp(($n+13)%16)); # f holds xa^xb^xc^xd + &rotl($f,1); # f=ROTATE(f,1) + &add($tmp1,$e); # b&(c^d)+=e + &rotr($b,2); # b=ROTATE(b,30) + &mov($e,$a); # e becomes volatile + &rotl($e,5); # ROTATE(a,5) + &mov(&swtmp($n%16),$f); # xi=f + &lea($f,&DWP(0x8f1bbcdc,$f,$tmp1));# f+=K_40_59+e+(b&(c^d)) + &mov($tmp1,$c); + &add($f,$e); # f+=ROTATE(a,5) + &and($tmp1,$d); + &mov($e,&swtmp(($n+1)%16)); # pre-fetch f for next round + &add($f,$tmp1); # f+=c&d +} + } + +&function_begin("sha1_block_data_order"); +if ($xmm) { + &static_label("shaext_shortcut") if ($shaext); + &static_label("ssse3_shortcut"); + &static_label("avx_shortcut") if ($ymm); + &static_label("K_XX_XX"); + + &call (&label("pic_point")); # make it PIC! + &set_label("pic_point"); + &blindpop($tmp1); + &picmeup($T,"OPENSSL_ia32cap_P",$tmp1,&label("pic_point")); + &lea ($tmp1,&DWP(&label("K_XX_XX")."-".&label("pic_point"),$tmp1)); + + &mov ($A,&DWP(0,$T)); + &mov ($D,&DWP(4,$T)); + &test ($D,1<<9); # check SSSE3 bit + &jz (&label("x86")); + &mov ($C,&DWP(8,$T)); + &test ($A,1<<24); # check FXSR bit + &jz (&label("x86")); + if ($shaext) { + &test ($C,1<<29); # check SHA bit + &jnz (&label("shaext_shortcut")); + } + if ($ymm) { + &and ($D,1<<28); # mask AVX bit + &and ($A,1<<30); # mask "Intel CPU" bit + &or ($A,$D); + &cmp ($A,1<<28|1<<30); + &je (&label("avx_shortcut")); + } + &jmp (&label("ssse3_shortcut")); + &set_label("x86",16); +} + &mov($tmp1,&wparam(0)); # SHA_CTX *c + &mov($T,&wparam(1)); # const void *input + &mov($A,&wparam(2)); # size_t num + &stack_push(16+3); # allocate X[16] + &shl($A,6); + &add($A,$T); + &mov(&wparam(2),$A); # pointer beyond the end of input + &mov($E,&DWP(16,$tmp1));# pre-load E + &jmp(&label("loop")); + +&set_label("loop",16); + + # copy input chunk to X, but reversing byte order! + for ($i=0; $i<16; $i+=4) + { + &mov($A,&DWP(4*($i+0),$T)); + &mov($B,&DWP(4*($i+1),$T)); + &mov($C,&DWP(4*($i+2),$T)); + &mov($D,&DWP(4*($i+3),$T)); + &bswap($A); + &bswap($B); + &bswap($C); + &bswap($D); + &mov(&swtmp($i+0),$A); + &mov(&swtmp($i+1),$B); + &mov(&swtmp($i+2),$C); + &mov(&swtmp($i+3),$D); + } + &mov(&wparam(1),$T); # redundant in 1st spin + + &mov($A,&DWP(0,$tmp1)); # load SHA_CTX + &mov($B,&DWP(4,$tmp1)); + &mov($C,&DWP(8,$tmp1)); + &mov($D,&DWP(12,$tmp1)); + # E is pre-loaded + + for($i=0;$i<16;$i++) { &BODY_00_15($i,@V); unshift(@V,pop(@V)); } + for(;$i<20;$i++) { &BODY_16_19($i,@V); unshift(@V,pop(@V)); } + for(;$i<40;$i++) { &BODY_20_39($i,@V); unshift(@V,pop(@V)); } + for(;$i<60;$i++) { &BODY_40_59($i,@V); unshift(@V,pop(@V)); } + for(;$i<80;$i++) { &BODY_20_39($i,@V); unshift(@V,pop(@V)); } + + (($V[5] eq $D) and ($V[0] eq $E)) or die; # double-check + + &mov($tmp1,&wparam(0)); # re-load SHA_CTX* + &mov($D,&wparam(1)); # D is last "T" and is discarded + + &add($E,&DWP(0,$tmp1)); # E is last "A"... + &add($T,&DWP(4,$tmp1)); + &add($A,&DWP(8,$tmp1)); + &add($B,&DWP(12,$tmp1)); + &add($C,&DWP(16,$tmp1)); + + &mov(&DWP(0,$tmp1),$E); # update SHA_CTX + &add($D,64); # advance input pointer + &mov(&DWP(4,$tmp1),$T); + &cmp($D,&wparam(2)); # have we reached the end yet? + &mov(&DWP(8,$tmp1),$A); + &mov($E,$C); # C is last "E" which needs to be "pre-loaded" + &mov(&DWP(12,$tmp1),$B); + &mov($T,$D); # input pointer + &mov(&DWP(16,$tmp1),$C); + &jb(&label("loop")); + + &stack_pop(16+3); +&function_end("sha1_block_data_order"); + +if ($xmm) { +if ($shaext) { +###################################################################### +# Intel SHA Extensions implementation of SHA1 update function. +# +my ($ctx,$inp,$num)=("edi","esi","ecx"); +my ($ABCD,$E,$E_,$BSWAP)=map("xmm$_",(0..3)); +my @MSG=map("xmm$_",(4..7)); + +sub sha1rnds4 { + my ($dst,$src,$imm)=@_; + if ("$dst:$src" =~ /xmm([0-7]):xmm([0-7])/) + { &data_byte(0x0f,0x3a,0xcc,0xc0|($1<<3)|$2,$imm); } +} +sub sha1op38 { + my ($opcodelet,$dst,$src)=@_; + if ("$dst:$src" =~ /xmm([0-7]):xmm([0-7])/) + { &data_byte(0x0f,0x38,$opcodelet,0xc0|($1<<3)|$2); } +} +sub sha1nexte { sha1op38(0xc8,@_); } +sub sha1msg1 { sha1op38(0xc9,@_); } +sub sha1msg2 { sha1op38(0xca,@_); } + +&function_begin("_sha1_block_data_order_shaext"); + &call (&label("pic_point")); # make it PIC! + &set_label("pic_point"); + &blindpop($tmp1); + &lea ($tmp1,&DWP(&label("K_XX_XX")."-".&label("pic_point"),$tmp1)); +&set_label("shaext_shortcut"); + &mov ($ctx,&wparam(0)); + &mov ("ebx","esp"); + &mov ($inp,&wparam(1)); + &mov ($num,&wparam(2)); + &sub ("esp",32); + + &movdqu ($ABCD,&QWP(0,$ctx)); + &movd ($E,&DWP(16,$ctx)); + &and ("esp",-32); + &movdqa ($BSWAP,&QWP(0x50,$tmp1)); # byte-n-word swap + + &movdqu (@MSG[0],&QWP(0,$inp)); + &pshufd ($ABCD,$ABCD,0b00011011); # flip word order + &movdqu (@MSG[1],&QWP(0x10,$inp)); + &pshufd ($E,$E,0b00011011); # flip word order + &movdqu (@MSG[2],&QWP(0x20,$inp)); + &pshufb (@MSG[0],$BSWAP); + &movdqu (@MSG[3],&QWP(0x30,$inp)); + &pshufb (@MSG[1],$BSWAP); + &pshufb (@MSG[2],$BSWAP); + &pshufb (@MSG[3],$BSWAP); + &jmp (&label("loop_shaext")); + +&set_label("loop_shaext",16); + &dec ($num); + &lea ("eax",&DWP(0x40,$inp)); + &movdqa (&QWP(0,"esp"),$E); # offload $E + &paddd ($E,@MSG[0]); + &cmovne ($inp,"eax"); + &movdqa (&QWP(16,"esp"),$ABCD); # offload $ABCD + +for($i=0;$i<20-4;$i+=2) { + &sha1msg1 (@MSG[0],@MSG[1]); + &movdqa ($E_,$ABCD); + &sha1rnds4 ($ABCD,$E,int($i/5)); # 0-3... + &sha1nexte ($E_,@MSG[1]); + &pxor (@MSG[0],@MSG[2]); + &sha1msg1 (@MSG[1],@MSG[2]); + &sha1msg2 (@MSG[0],@MSG[3]); + + &movdqa ($E,$ABCD); + &sha1rnds4 ($ABCD,$E_,int(($i+1)/5)); + &sha1nexte ($E,@MSG[2]); + &pxor (@MSG[1],@MSG[3]); + &sha1msg2 (@MSG[1],@MSG[0]); + + push(@MSG,shift(@MSG)); push(@MSG,shift(@MSG)); +} + &movdqu (@MSG[0],&QWP(0,$inp)); + &movdqa ($E_,$ABCD); + &sha1rnds4 ($ABCD,$E,3); # 64-67 + &sha1nexte ($E_,@MSG[1]); + &movdqu (@MSG[1],&QWP(0x10,$inp)); + &pshufb (@MSG[0],$BSWAP); + + &movdqa ($E,$ABCD); + &sha1rnds4 ($ABCD,$E_,3); # 68-71 + &sha1nexte ($E,@MSG[2]); + &movdqu (@MSG[2],&QWP(0x20,$inp)); + &pshufb (@MSG[1],$BSWAP); + + &movdqa ($E_,$ABCD); + &sha1rnds4 ($ABCD,$E,3); # 72-75 + &sha1nexte ($E_,@MSG[3]); + &movdqu (@MSG[3],&QWP(0x30,$inp)); + &pshufb (@MSG[2],$BSWAP); + + &movdqa ($E,$ABCD); + &sha1rnds4 ($ABCD,$E_,3); # 76-79 + &movdqa ($E_,&QWP(0,"esp")); + &pshufb (@MSG[3],$BSWAP); + &sha1nexte ($E,$E_); + &paddd ($ABCD,&QWP(16,"esp")); + + &jnz (&label("loop_shaext")); + + &pshufd ($ABCD,$ABCD,0b00011011); + &pshufd ($E,$E,0b00011011); + &movdqu (&QWP(0,$ctx),$ABCD) + &movd (&DWP(16,$ctx),$E); + &mov ("esp","ebx"); +&function_end("_sha1_block_data_order_shaext"); +} +###################################################################### +# The SSSE3 implementation. +# +# %xmm[0-7] are used as ring @X[] buffer containing quadruples of last +# 32 elements of the message schedule or Xupdate outputs. First 4 +# quadruples are simply byte-swapped input, next 4 are calculated +# according to method originally suggested by Dean Gaudet (modulo +# being implemented in SSSE3). Once 8 quadruples or 32 elements are +# collected, it switches to routine proposed by Max Locktyukhin. +# +# Calculations inevitably require temporary reqisters, and there are +# no %xmm registers left to spare. For this reason part of the ring +# buffer, X[2..4] to be specific, is offloaded to 3 quadriples ring +# buffer on the stack. Keep in mind that X[2] is alias X[-6], X[3] - +# X[-5], and X[4] - X[-4]... +# +# Another notable optimization is aggressive stack frame compression +# aiming to minimize amount of 9-byte instructions... +# +# Yet another notable optimization is "jumping" $B variable. It means +# that there is no register permanently allocated for $B value. This +# allowed to eliminate one instruction from body_20_39... +# +my $Xi=4; # 4xSIMD Xupdate round, start pre-seeded +my @X=map("xmm$_",(4..7,0..3)); # pre-seeded for $Xi=4 +my @V=($A,$B,$C,$D,$E); +my $j=0; # hash round +my $rx=0; +my @T=($T,$tmp1); +my $inp; + +my $_rol=sub { &rol(@_) }; +my $_ror=sub { &ror(@_) }; + +&function_begin("_sha1_block_data_order_ssse3"); + &call (&label("pic_point")); # make it PIC! + &set_label("pic_point"); + &blindpop($tmp1); + &lea ($tmp1,&DWP(&label("K_XX_XX")."-".&label("pic_point"),$tmp1)); +&set_label("ssse3_shortcut"); + + &movdqa (@X[3],&QWP(0,$tmp1)); # K_00_19 + &movdqa (@X[4],&QWP(16,$tmp1)); # K_20_39 + &movdqa (@X[5],&QWP(32,$tmp1)); # K_40_59 + &movdqa (@X[6],&QWP(48,$tmp1)); # K_60_79 + &movdqa (@X[2],&QWP(64,$tmp1)); # pbswap mask + + &mov ($E,&wparam(0)); # load argument block + &mov ($inp=@T[1],&wparam(1)); + &mov ($D,&wparam(2)); + &mov (@T[0],"esp"); + + # stack frame layout + # + # +0 X[0]+K X[1]+K X[2]+K X[3]+K # XMM->IALU xfer area + # X[4]+K X[5]+K X[6]+K X[7]+K + # X[8]+K X[9]+K X[10]+K X[11]+K + # X[12]+K X[13]+K X[14]+K X[15]+K + # + # +64 X[0] X[1] X[2] X[3] # XMM->XMM backtrace area + # X[4] X[5] X[6] X[7] + # X[8] X[9] X[10] X[11] # even borrowed for K_00_19 + # + # +112 K_20_39 K_20_39 K_20_39 K_20_39 # constants + # K_40_59 K_40_59 K_40_59 K_40_59 + # K_60_79 K_60_79 K_60_79 K_60_79 + # K_00_19 K_00_19 K_00_19 K_00_19 + # pbswap mask + # + # +192 ctx # argument block + # +196 inp + # +200 end + # +204 esp + &sub ("esp",208); + &and ("esp",-64); + + &movdqa (&QWP(112+0,"esp"),@X[4]); # copy constants + &movdqa (&QWP(112+16,"esp"),@X[5]); + &movdqa (&QWP(112+32,"esp"),@X[6]); + &shl ($D,6); # len*64 + &movdqa (&QWP(112+48,"esp"),@X[3]); + &add ($D,$inp); # end of input + &movdqa (&QWP(112+64,"esp"),@X[2]); + &add ($inp,64); + &mov (&DWP(192+0,"esp"),$E); # save argument block + &mov (&DWP(192+4,"esp"),$inp); + &mov (&DWP(192+8,"esp"),$D); + &mov (&DWP(192+12,"esp"),@T[0]); # save original %esp + + &mov ($A,&DWP(0,$E)); # load context + &mov ($B,&DWP(4,$E)); + &mov ($C,&DWP(8,$E)); + &mov ($D,&DWP(12,$E)); + &mov ($E,&DWP(16,$E)); + &mov (@T[0],$B); # magic seed + + &movdqu (@X[-4&7],&QWP(-64,$inp)); # load input to %xmm[0-3] + &movdqu (@X[-3&7],&QWP(-48,$inp)); + &movdqu (@X[-2&7],&QWP(-32,$inp)); + &movdqu (@X[-1&7],&QWP(-16,$inp)); + &pshufb (@X[-4&7],@X[2]); # byte swap + &pshufb (@X[-3&7],@X[2]); + &pshufb (@X[-2&7],@X[2]); + &movdqa (&QWP(112-16,"esp"),@X[3]); # borrow last backtrace slot + &pshufb (@X[-1&7],@X[2]); + &paddd (@X[-4&7],@X[3]); # add K_00_19 + &paddd (@X[-3&7],@X[3]); + &paddd (@X[-2&7],@X[3]); + &movdqa (&QWP(0,"esp"),@X[-4&7]); # X[]+K xfer to IALU + &psubd (@X[-4&7],@X[3]); # restore X[] + &movdqa (&QWP(0+16,"esp"),@X[-3&7]); + &psubd (@X[-3&7],@X[3]); + &movdqa (&QWP(0+32,"esp"),@X[-2&7]); + &mov (@T[1],$C); + &psubd (@X[-2&7],@X[3]); + &xor (@T[1],$D); + &pshufd (@X[0],@X[-4&7],0xee); # was &movdqa (@X[0],@X[-3&7]); + &and (@T[0],@T[1]); + &jmp (&label("loop")); + +###################################################################### +# SSE instruction sequence is first broken to groups of indepentent +# instructions, independent in respect to their inputs and shifter +# (not all architectures have more than one). Then IALU instructions +# are "knitted in" between the SSE groups. Distance is maintained for +# SSE latency of 2 in hope that it fits better upcoming AMD Bulldozer +# [which allegedly also implements SSSE3]... +# +# Temporary registers usage. X[2] is volatile at the entry and at the +# end is restored from backtrace ring buffer. X[3] is expected to +# contain current K_XX_XX constant and is used to caclulate X[-1]+K +# from previous round, it becomes volatile the moment the value is +# saved to stack for transfer to IALU. X[4] becomes volatile whenever +# X[-4] is accumulated and offloaded to backtrace ring buffer, at the +# end it is loaded with next K_XX_XX [which becomes X[3] in next +# round]... +# +sub Xupdate_ssse3_16_31() # recall that $Xi starts wtih 4 +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); # 40 instructions + my ($a,$b,$c,$d,$e); + + eval(shift(@insns)); # ror + eval(shift(@insns)); + eval(shift(@insns)); + &punpcklqdq(@X[0],@X[-3&7]); # compose "X[-14]" in "X[0]", was &palignr(@X[0],@X[-4&7],8); + &movdqa (@X[2],@X[-1&7]); + eval(shift(@insns)); + eval(shift(@insns)); + + &paddd (@X[3],@X[-1&7]); + &movdqa (&QWP(64+16*(($Xi-4)%3),"esp"),@X[-4&7]);# save X[] to backtrace buffer + eval(shift(@insns)); # rol + eval(shift(@insns)); + &psrldq (@X[2],4); # "X[-3]", 3 dwords + eval(shift(@insns)); + eval(shift(@insns)); + &pxor (@X[0],@X[-4&7]); # "X[0]"^="X[-16]" + eval(shift(@insns)); + eval(shift(@insns)); # ror + + &pxor (@X[2],@X[-2&7]); # "X[-3]"^"X[-8]" + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &pxor (@X[0],@X[2]); # "X[0]"^="X[-3]"^"X[-8]" + eval(shift(@insns)); + eval(shift(@insns)); # rol + &movdqa (&QWP(0+16*(($Xi-1)&3),"esp"),@X[3]); # X[]+K xfer to IALU + eval(shift(@insns)); + eval(shift(@insns)); + + &movdqa (@X[4],@X[0]); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # ror + &movdqa (@X[2],@X[0]); + eval(shift(@insns)); + + &pslldq (@X[4],12); # "X[0]"<<96, extract one dword + &paddd (@X[0],@X[0]); + eval(shift(@insns)); + eval(shift(@insns)); + + &psrld (@X[2],31); + eval(shift(@insns)); + eval(shift(@insns)); # rol + &movdqa (@X[3],@X[4]); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &psrld (@X[4],30); + eval(shift(@insns)); + eval(shift(@insns)); # ror + &por (@X[0],@X[2]); # "X[0]"<<<=1 + eval(shift(@insns)); + &movdqa (@X[2],&QWP(64+16*(($Xi-6)%3),"esp")) if ($Xi>5); # restore X[] from backtrace buffer + eval(shift(@insns)); + eval(shift(@insns)); + + &pslld (@X[3],2); + eval(shift(@insns)); + eval(shift(@insns)); # rol + &pxor (@X[0],@X[4]); + &movdqa (@X[4],&QWP(112-16+16*(($Xi)/5),"esp")); # K_XX_XX + eval(shift(@insns)); + eval(shift(@insns)); + + &pxor (@X[0],@X[3]); # "X[0]"^=("X[0]"<<96)<<<2 + &pshufd (@X[1],@X[-3&7],0xee) if ($Xi<7); # was &movdqa (@X[1],@X[-2&7]) + &pshufd (@X[3],@X[-1&7],0xee) if ($Xi==7); + eval(shift(@insns)); + eval(shift(@insns)); + + foreach (@insns) { eval; } # remaining instructions [if any] + + $Xi++; push(@X,shift(@X)); # "rotate" X[] +} + +sub Xupdate_ssse3_32_79() +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); # 32 to 44 instructions + my ($a,$b,$c,$d,$e); + + eval(shift(@insns)); # body_20_39 + &pxor (@X[0],@X[-4&7]); # "X[0]"="X[-32]"^"X[-16]" + &punpcklqdq(@X[2],@X[-1&7]); # compose "X[-6]", was &palignr(@X[2],@X[-2&7],8) + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # rol + + &pxor (@X[0],@X[-7&7]); # "X[0]"^="X[-28]" + &movdqa (&QWP(64+16*(($Xi-4)%3),"esp"),@X[-4&7]); # save X[] to backtrace buffer + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)) if (@insns[0] =~ /_rol/); + if ($Xi%5) { + &movdqa (@X[4],@X[3]); # "perpetuate" K_XX_XX... + } else { # ... or load next one + &movdqa (@X[4],&QWP(112-16+16*($Xi/5),"esp")); + } + eval(shift(@insns)); # ror + &paddd (@X[3],@X[-1&7]); + eval(shift(@insns)); + + &pxor (@X[0],@X[2]); # "X[0]"^="X[-6]" + eval(shift(@insns)); # body_20_39 + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # rol + + &movdqa (@X[2],@X[0]); + &movdqa (&QWP(0+16*(($Xi-1)&3),"esp"),@X[3]); # X[]+K xfer to IALU + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # ror + eval(shift(@insns)); + eval(shift(@insns)) if (@insns[0] =~ /_rol/); + + &pslld (@X[0],2); + eval(shift(@insns)); # body_20_39 + eval(shift(@insns)); + &psrld (@X[2],30); + eval(shift(@insns)); + eval(shift(@insns)); # rol + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # ror + eval(shift(@insns)); + eval(shift(@insns)) if (@insns[1] =~ /_rol/); + eval(shift(@insns)) if (@insns[0] =~ /_rol/); + + &por (@X[0],@X[2]); # "X[0]"<<<=2 + eval(shift(@insns)); # body_20_39 + eval(shift(@insns)); + &movdqa (@X[2],&QWP(64+16*(($Xi-6)%3),"esp")) if($Xi<19); # restore X[] from backtrace buffer + eval(shift(@insns)); + eval(shift(@insns)); # rol + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # ror + &pshufd (@X[3],@X[-1],0xee) if ($Xi<19); # was &movdqa (@X[3],@X[0]) + eval(shift(@insns)); + + foreach (@insns) { eval; } # remaining instructions + + $Xi++; push(@X,shift(@X)); # "rotate" X[] +} + +sub Xuplast_ssse3_80() +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); # 32 instructions + my ($a,$b,$c,$d,$e); + + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &paddd (@X[3],@X[-1&7]); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &movdqa (&QWP(0+16*(($Xi-1)&3),"esp"),@X[3]); # X[]+K xfer IALU + + foreach (@insns) { eval; } # remaining instructions + + &mov ($inp=@T[1],&DWP(192+4,"esp")); + &cmp ($inp,&DWP(192+8,"esp")); + &je (&label("done")); + + &movdqa (@X[3],&QWP(112+48,"esp")); # K_00_19 + &movdqa (@X[2],&QWP(112+64,"esp")); # pbswap mask + &movdqu (@X[-4&7],&QWP(0,$inp)); # load input + &movdqu (@X[-3&7],&QWP(16,$inp)); + &movdqu (@X[-2&7],&QWP(32,$inp)); + &movdqu (@X[-1&7],&QWP(48,$inp)); + &add ($inp,64); + &pshufb (@X[-4&7],@X[2]); # byte swap + &mov (&DWP(192+4,"esp"),$inp); + &movdqa (&QWP(112-16,"esp"),@X[3]); # borrow last backtrace slot + + $Xi=0; +} + +sub Xloop_ssse3() +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); # 32 instructions + my ($a,$b,$c,$d,$e); + + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &pshufb (@X[($Xi-3)&7],@X[2]); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &paddd (@X[($Xi-4)&7],@X[3]); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &movdqa (&QWP(0+16*$Xi,"esp"),@X[($Xi-4)&7]); # X[]+K xfer to IALU + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &psubd (@X[($Xi-4)&7],@X[3]); + + foreach (@insns) { eval; } + $Xi++; +} + +sub Xtail_ssse3() +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); # 32 instructions + my ($a,$b,$c,$d,$e); + + foreach (@insns) { eval; } +} + +sub body_00_19 () { # ((c^d)&b)^d + # on start @T[0]=(c^d)&b + return &body_20_39() if ($rx==19); $rx++; + ( + '($a,$b,$c,$d,$e)=@V;'. + '&$_ror ($b,$j?7:2);', # $b>>>2 + '&xor (@T[0],$d);', + '&mov (@T[1],$a);', # $b in next round + + '&add ($e,&DWP(4*($j&15),"esp"));', # X[]+K xfer + '&xor ($b,$c);', # $c^$d for next round + + '&$_rol ($a,5);', + '&add ($e,@T[0]);', + '&and (@T[1],$b);', # ($b&($c^$d)) for next round + + '&xor ($b,$c);', # restore $b + '&add ($e,$a);' .'$j++; unshift(@V,pop(@V)); unshift(@T,pop(@T));' + ); +} + +sub body_20_39 () { # b^d^c + # on entry @T[0]=b^d + return &body_40_59() if ($rx==39); $rx++; + ( + '($a,$b,$c,$d,$e)=@V;'. + '&add ($e,&DWP(4*($j&15),"esp"));', # X[]+K xfer + '&xor (@T[0],$d) if($j==19);'. + '&xor (@T[0],$c) if($j> 19);', # ($b^$d^$c) + '&mov (@T[1],$a);', # $b in next round + + '&$_rol ($a,5);', + '&add ($e,@T[0]);', + '&xor (@T[1],$c) if ($j< 79);', # $b^$d for next round + + '&$_ror ($b,7);', # $b>>>2 + '&add ($e,$a);' .'$j++; unshift(@V,pop(@V)); unshift(@T,pop(@T));' + ); +} + +sub body_40_59 () { # ((b^c)&(c^d))^c + # on entry @T[0]=(b^c), (c^=d) + $rx++; + ( + '($a,$b,$c,$d,$e)=@V;'. + '&add ($e,&DWP(4*($j&15),"esp"));', # X[]+K xfer + '&and (@T[0],$c) if ($j>=40);', # (b^c)&(c^d) + '&xor ($c,$d) if ($j>=40);', # restore $c + + '&$_ror ($b,7);', # $b>>>2 + '&mov (@T[1],$a);', # $b for next round + '&xor (@T[0],$c);', + + '&$_rol ($a,5);', + '&add ($e,@T[0]);', + '&xor (@T[1],$c) if ($j==59);'. + '&xor (@T[1],$b) if ($j< 59);', # b^c for next round + + '&xor ($b,$c) if ($j< 59);', # c^d for next round + '&add ($e,$a);' .'$j++; unshift(@V,pop(@V)); unshift(@T,pop(@T));' + ); +} +###### +sub bodyx_00_19 () { # ((c^d)&b)^d + # on start @T[0]=(b&c)^(~b&d), $e+=X[]+K + return &bodyx_20_39() if ($rx==19); $rx++; + ( + '($a,$b,$c,$d,$e)=@V;'. + + '&rorx ($b,$b,2) if ($j==0);'. # $b>>>2 + '&rorx ($b,@T[1],7) if ($j!=0);', # $b>>>2 + '&lea ($e,&DWP(0,$e,@T[0]));', + '&rorx (@T[0],$a,5);', + + '&andn (@T[1],$a,$c);', + '&and ($a,$b)', + '&add ($d,&DWP(4*(($j+1)&15),"esp"));', # X[]+K xfer + + '&xor (@T[1],$a)', + '&add ($e,@T[0]);' .'$j++; unshift(@V,pop(@V)); unshift(@T,pop(@T));' + ); +} + +sub bodyx_20_39 () { # b^d^c + # on start $b=b^c^d + return &bodyx_40_59() if ($rx==39); $rx++; + ( + '($a,$b,$c,$d,$e)=@V;'. + + '&add ($e,($j==19?@T[0]:$b))', + '&rorx ($b,@T[1],7);', # $b>>>2 + '&rorx (@T[0],$a,5);', + + '&xor ($a,$b) if ($j<79);', + '&add ($d,&DWP(4*(($j+1)&15),"esp")) if ($j<79);', # X[]+K xfer + '&xor ($a,$c) if ($j<79);', + '&add ($e,@T[0]);' .'$j++; unshift(@V,pop(@V)); unshift(@T,pop(@T));' + ); +} + +sub bodyx_40_59 () { # ((b^c)&(c^d))^c + # on start $b=((b^c)&(c^d))^c + return &bodyx_20_39() if ($rx==59); $rx++; + ( + '($a,$b,$c,$d,$e)=@V;'. + + '&rorx (@T[0],$a,5)', + '&lea ($e,&DWP(0,$e,$b))', + '&rorx ($b,@T[1],7)', # $b>>>2 + '&add ($d,&DWP(4*(($j+1)&15),"esp"))', # X[]+K xfer + + '&mov (@T[1],$c)', + '&xor ($a,$b)', # b^c for next round + '&xor (@T[1],$b)', # c^d for next round + + '&and ($a,@T[1])', + '&add ($e,@T[0])', + '&xor ($a,$b)' .'$j++; unshift(@V,pop(@V)); unshift(@T,pop(@T));' + ); +} + +&set_label("loop",16); + &Xupdate_ssse3_16_31(\&body_00_19); + &Xupdate_ssse3_16_31(\&body_00_19); + &Xupdate_ssse3_16_31(\&body_00_19); + &Xupdate_ssse3_16_31(\&body_00_19); + &Xupdate_ssse3_32_79(\&body_00_19); + &Xupdate_ssse3_32_79(\&body_20_39); + &Xupdate_ssse3_32_79(\&body_20_39); + &Xupdate_ssse3_32_79(\&body_20_39); + &Xupdate_ssse3_32_79(\&body_20_39); + &Xupdate_ssse3_32_79(\&body_20_39); + &Xupdate_ssse3_32_79(\&body_40_59); + &Xupdate_ssse3_32_79(\&body_40_59); + &Xupdate_ssse3_32_79(\&body_40_59); + &Xupdate_ssse3_32_79(\&body_40_59); + &Xupdate_ssse3_32_79(\&body_40_59); + &Xupdate_ssse3_32_79(\&body_20_39); + &Xuplast_ssse3_80(\&body_20_39); # can jump to "done" + + $saved_j=$j; @saved_V=@V; + + &Xloop_ssse3(\&body_20_39); + &Xloop_ssse3(\&body_20_39); + &Xloop_ssse3(\&body_20_39); + + &mov (@T[1],&DWP(192,"esp")); # update context + &add ($A,&DWP(0,@T[1])); + &add (@T[0],&DWP(4,@T[1])); # $b + &add ($C,&DWP(8,@T[1])); + &mov (&DWP(0,@T[1]),$A); + &add ($D,&DWP(12,@T[1])); + &mov (&DWP(4,@T[1]),@T[0]); + &add ($E,&DWP(16,@T[1])); + &mov (&DWP(8,@T[1]),$C); + &mov ($B,$C); + &mov (&DWP(12,@T[1]),$D); + &xor ($B,$D); + &mov (&DWP(16,@T[1]),$E); + &mov (@T[1],@T[0]); + &pshufd (@X[0],@X[-4&7],0xee); # was &movdqa (@X[0],@X[-3&7]); + &and (@T[0],$B); + &mov ($B,$T[1]); + + &jmp (&label("loop")); + +&set_label("done",16); $j=$saved_j; @V=@saved_V; + + &Xtail_ssse3(\&body_20_39); + &Xtail_ssse3(\&body_20_39); + &Xtail_ssse3(\&body_20_39); + + &mov (@T[1],&DWP(192,"esp")); # update context + &add ($A,&DWP(0,@T[1])); + &mov ("esp",&DWP(192+12,"esp")); # restore %esp + &add (@T[0],&DWP(4,@T[1])); # $b + &add ($C,&DWP(8,@T[1])); + &mov (&DWP(0,@T[1]),$A); + &add ($D,&DWP(12,@T[1])); + &mov (&DWP(4,@T[1]),@T[0]); + &add ($E,&DWP(16,@T[1])); + &mov (&DWP(8,@T[1]),$C); + &mov (&DWP(12,@T[1]),$D); + &mov (&DWP(16,@T[1]),$E); + +&function_end("_sha1_block_data_order_ssse3"); + +$rx=0; # reset + +if ($ymm) { +my $Xi=4; # 4xSIMD Xupdate round, start pre-seeded +my @X=map("xmm$_",(4..7,0..3)); # pre-seeded for $Xi=4 +my @V=($A,$B,$C,$D,$E); +my $j=0; # hash round +my @T=($T,$tmp1); +my $inp; + +my $_rol=sub { &shld(@_[0],@_) }; +my $_ror=sub { &shrd(@_[0],@_) }; + +&function_begin("_sha1_block_data_order_avx"); + &call (&label("pic_point")); # make it PIC! + &set_label("pic_point"); + &blindpop($tmp1); + &lea ($tmp1,&DWP(&label("K_XX_XX")."-".&label("pic_point"),$tmp1)); +&set_label("avx_shortcut"); + &vzeroall(); + + &vmovdqa(@X[3],&QWP(0,$tmp1)); # K_00_19 + &vmovdqa(@X[4],&QWP(16,$tmp1)); # K_20_39 + &vmovdqa(@X[5],&QWP(32,$tmp1)); # K_40_59 + &vmovdqa(@X[6],&QWP(48,$tmp1)); # K_60_79 + &vmovdqa(@X[2],&QWP(64,$tmp1)); # pbswap mask + + &mov ($E,&wparam(0)); # load argument block + &mov ($inp=@T[1],&wparam(1)); + &mov ($D,&wparam(2)); + &mov (@T[0],"esp"); + + # stack frame layout + # + # +0 X[0]+K X[1]+K X[2]+K X[3]+K # XMM->IALU xfer area + # X[4]+K X[5]+K X[6]+K X[7]+K + # X[8]+K X[9]+K X[10]+K X[11]+K + # X[12]+K X[13]+K X[14]+K X[15]+K + # + # +64 X[0] X[1] X[2] X[3] # XMM->XMM backtrace area + # X[4] X[5] X[6] X[7] + # X[8] X[9] X[10] X[11] # even borrowed for K_00_19 + # + # +112 K_20_39 K_20_39 K_20_39 K_20_39 # constants + # K_40_59 K_40_59 K_40_59 K_40_59 + # K_60_79 K_60_79 K_60_79 K_60_79 + # K_00_19 K_00_19 K_00_19 K_00_19 + # pbswap mask + # + # +192 ctx # argument block + # +196 inp + # +200 end + # +204 esp + &sub ("esp",208); + &and ("esp",-64); + + &vmovdqa(&QWP(112+0,"esp"),@X[4]); # copy constants + &vmovdqa(&QWP(112+16,"esp"),@X[5]); + &vmovdqa(&QWP(112+32,"esp"),@X[6]); + &shl ($D,6); # len*64 + &vmovdqa(&QWP(112+48,"esp"),@X[3]); + &add ($D,$inp); # end of input + &vmovdqa(&QWP(112+64,"esp"),@X[2]); + &add ($inp,64); + &mov (&DWP(192+0,"esp"),$E); # save argument block + &mov (&DWP(192+4,"esp"),$inp); + &mov (&DWP(192+8,"esp"),$D); + &mov (&DWP(192+12,"esp"),@T[0]); # save original %esp + + &mov ($A,&DWP(0,$E)); # load context + &mov ($B,&DWP(4,$E)); + &mov ($C,&DWP(8,$E)); + &mov ($D,&DWP(12,$E)); + &mov ($E,&DWP(16,$E)); + &mov (@T[0],$B); # magic seed + + &vmovdqu(@X[-4&7],&QWP(-64,$inp)); # load input to %xmm[0-3] + &vmovdqu(@X[-3&7],&QWP(-48,$inp)); + &vmovdqu(@X[-2&7],&QWP(-32,$inp)); + &vmovdqu(@X[-1&7],&QWP(-16,$inp)); + &vpshufb(@X[-4&7],@X[-4&7],@X[2]); # byte swap + &vpshufb(@X[-3&7],@X[-3&7],@X[2]); + &vpshufb(@X[-2&7],@X[-2&7],@X[2]); + &vmovdqa(&QWP(112-16,"esp"),@X[3]); # borrow last backtrace slot + &vpshufb(@X[-1&7],@X[-1&7],@X[2]); + &vpaddd (@X[0],@X[-4&7],@X[3]); # add K_00_19 + &vpaddd (@X[1],@X[-3&7],@X[3]); + &vpaddd (@X[2],@X[-2&7],@X[3]); + &vmovdqa(&QWP(0,"esp"),@X[0]); # X[]+K xfer to IALU + &mov (@T[1],$C); + &vmovdqa(&QWP(0+16,"esp"),@X[1]); + &xor (@T[1],$D); + &vmovdqa(&QWP(0+32,"esp"),@X[2]); + &and (@T[0],@T[1]); + &jmp (&label("loop")); + +sub Xupdate_avx_16_31() # recall that $Xi starts wtih 4 +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); # 40 instructions + my ($a,$b,$c,$d,$e); + + eval(shift(@insns)); + eval(shift(@insns)); + &vpalignr(@X[0],@X[-3&7],@X[-4&7],8); # compose "X[-14]" in "X[0]" + eval(shift(@insns)); + eval(shift(@insns)); + + &vpaddd (@X[3],@X[3],@X[-1&7]); + &vmovdqa (&QWP(64+16*(($Xi-4)%3),"esp"),@X[-4&7]);# save X[] to backtrace buffer + eval(shift(@insns)); + eval(shift(@insns)); + &vpsrldq(@X[2],@X[-1&7],4); # "X[-3]", 3 dwords + eval(shift(@insns)); + eval(shift(@insns)); + &vpxor (@X[0],@X[0],@X[-4&7]); # "X[0]"^="X[-16]" + eval(shift(@insns)); + eval(shift(@insns)); + + &vpxor (@X[2],@X[2],@X[-2&7]); # "X[-3]"^"X[-8]" + eval(shift(@insns)); + eval(shift(@insns)); + &vmovdqa (&QWP(0+16*(($Xi-1)&3),"esp"),@X[3]); # X[]+K xfer to IALU + eval(shift(@insns)); + eval(shift(@insns)); + + &vpxor (@X[0],@X[0],@X[2]); # "X[0]"^="X[-3]"^"X[-8]" + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &vpsrld (@X[2],@X[0],31); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &vpslldq(@X[4],@X[0],12); # "X[0]"<<96, extract one dword + &vpaddd (@X[0],@X[0],@X[0]); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &vpsrld (@X[3],@X[4],30); + &vpor (@X[0],@X[0],@X[2]); # "X[0]"<<<=1 + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &vpslld (@X[4],@X[4],2); + &vmovdqa (@X[2],&QWP(64+16*(($Xi-6)%3),"esp")) if ($Xi>5); # restore X[] from backtrace buffer + eval(shift(@insns)); + eval(shift(@insns)); + &vpxor (@X[0],@X[0],@X[3]); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &vpxor (@X[0],@X[0],@X[4]); # "X[0]"^=("X[0]"<<96)<<<2 + eval(shift(@insns)); + eval(shift(@insns)); + &vmovdqa (@X[4],&QWP(112-16+16*(($Xi)/5),"esp")); # K_XX_XX + eval(shift(@insns)); + eval(shift(@insns)); + + foreach (@insns) { eval; } # remaining instructions [if any] + + $Xi++; push(@X,shift(@X)); # "rotate" X[] +} + +sub Xupdate_avx_32_79() +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); # 32 to 44 instructions + my ($a,$b,$c,$d,$e); + + &vpalignr(@X[2],@X[-1&7],@X[-2&7],8); # compose "X[-6]" + &vpxor (@X[0],@X[0],@X[-4&7]); # "X[0]"="X[-32]"^"X[-16]" + eval(shift(@insns)); # body_20_39 + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # rol + + &vpxor (@X[0],@X[0],@X[-7&7]); # "X[0]"^="X[-28]" + &vmovdqa (&QWP(64+16*(($Xi-4)%3),"esp"),@X[-4&7]); # save X[] to backtrace buffer + eval(shift(@insns)); + eval(shift(@insns)); + if ($Xi%5) { + &vmovdqa (@X[4],@X[3]); # "perpetuate" K_XX_XX... + } else { # ... or load next one + &vmovdqa (@X[4],&QWP(112-16+16*($Xi/5),"esp")); + } + &vpaddd (@X[3],@X[3],@X[-1&7]); + eval(shift(@insns)); # ror + eval(shift(@insns)); + + &vpxor (@X[0],@X[0],@X[2]); # "X[0]"^="X[-6]" + eval(shift(@insns)); # body_20_39 + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # rol + + &vpsrld (@X[2],@X[0],30); + &vmovdqa (&QWP(0+16*(($Xi-1)&3),"esp"),@X[3]); # X[]+K xfer to IALU + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # ror + eval(shift(@insns)); + + &vpslld (@X[0],@X[0],2); + eval(shift(@insns)); # body_20_39 + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # rol + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # ror + eval(shift(@insns)); + + &vpor (@X[0],@X[0],@X[2]); # "X[0]"<<<=2 + eval(shift(@insns)); # body_20_39 + eval(shift(@insns)); + &vmovdqa (@X[2],&QWP(64+16*(($Xi-6)%3),"esp")) if($Xi<19); # restore X[] from backtrace buffer + eval(shift(@insns)); + eval(shift(@insns)); # rol + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # ror + eval(shift(@insns)); + + foreach (@insns) { eval; } # remaining instructions + + $Xi++; push(@X,shift(@X)); # "rotate" X[] +} + +sub Xuplast_avx_80() +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); # 32 instructions + my ($a,$b,$c,$d,$e); + + eval(shift(@insns)); + &vpaddd (@X[3],@X[3],@X[-1&7]); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &vmovdqa (&QWP(0+16*(($Xi-1)&3),"esp"),@X[3]); # X[]+K xfer IALU + + foreach (@insns) { eval; } # remaining instructions + + &mov ($inp=@T[1],&DWP(192+4,"esp")); + &cmp ($inp,&DWP(192+8,"esp")); + &je (&label("done")); + + &vmovdqa(@X[3],&QWP(112+48,"esp")); # K_00_19 + &vmovdqa(@X[2],&QWP(112+64,"esp")); # pbswap mask + &vmovdqu(@X[-4&7],&QWP(0,$inp)); # load input + &vmovdqu(@X[-3&7],&QWP(16,$inp)); + &vmovdqu(@X[-2&7],&QWP(32,$inp)); + &vmovdqu(@X[-1&7],&QWP(48,$inp)); + &add ($inp,64); + &vpshufb(@X[-4&7],@X[-4&7],@X[2]); # byte swap + &mov (&DWP(192+4,"esp"),$inp); + &vmovdqa(&QWP(112-16,"esp"),@X[3]); # borrow last backtrace slot + + $Xi=0; +} + +sub Xloop_avx() +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); # 32 instructions + my ($a,$b,$c,$d,$e); + + eval(shift(@insns)); + eval(shift(@insns)); + &vpshufb (@X[($Xi-3)&7],@X[($Xi-3)&7],@X[2]); + eval(shift(@insns)); + eval(shift(@insns)); + &vpaddd (@X[$Xi&7],@X[($Xi-4)&7],@X[3]); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vmovdqa (&QWP(0+16*$Xi,"esp"),@X[$Xi&7]); # X[]+K xfer to IALU + eval(shift(@insns)); + eval(shift(@insns)); + + foreach (@insns) { eval; } + $Xi++; +} + +sub Xtail_avx() +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); # 32 instructions + my ($a,$b,$c,$d,$e); + + foreach (@insns) { eval; } +} + +&set_label("loop",16); + &Xupdate_avx_16_31(\&body_00_19); + &Xupdate_avx_16_31(\&body_00_19); + &Xupdate_avx_16_31(\&body_00_19); + &Xupdate_avx_16_31(\&body_00_19); + &Xupdate_avx_32_79(\&body_00_19); + &Xupdate_avx_32_79(\&body_20_39); + &Xupdate_avx_32_79(\&body_20_39); + &Xupdate_avx_32_79(\&body_20_39); + &Xupdate_avx_32_79(\&body_20_39); + &Xupdate_avx_32_79(\&body_20_39); + &Xupdate_avx_32_79(\&body_40_59); + &Xupdate_avx_32_79(\&body_40_59); + &Xupdate_avx_32_79(\&body_40_59); + &Xupdate_avx_32_79(\&body_40_59); + &Xupdate_avx_32_79(\&body_40_59); + &Xupdate_avx_32_79(\&body_20_39); + &Xuplast_avx_80(\&body_20_39); # can jump to "done" + + $saved_j=$j; @saved_V=@V; + + &Xloop_avx(\&body_20_39); + &Xloop_avx(\&body_20_39); + &Xloop_avx(\&body_20_39); + + &mov (@T[1],&DWP(192,"esp")); # update context + &add ($A,&DWP(0,@T[1])); + &add (@T[0],&DWP(4,@T[1])); # $b + &add ($C,&DWP(8,@T[1])); + &mov (&DWP(0,@T[1]),$A); + &add ($D,&DWP(12,@T[1])); + &mov (&DWP(4,@T[1]),@T[0]); + &add ($E,&DWP(16,@T[1])); + &mov ($B,$C); + &mov (&DWP(8,@T[1]),$C); + &xor ($B,$D); + &mov (&DWP(12,@T[1]),$D); + &mov (&DWP(16,@T[1]),$E); + &mov (@T[1],@T[0]); + &and (@T[0],$B); + &mov ($B,@T[1]); + + &jmp (&label("loop")); + +&set_label("done",16); $j=$saved_j; @V=@saved_V; + + &Xtail_avx(\&body_20_39); + &Xtail_avx(\&body_20_39); + &Xtail_avx(\&body_20_39); + + &vzeroall(); + + &mov (@T[1],&DWP(192,"esp")); # update context + &add ($A,&DWP(0,@T[1])); + &mov ("esp",&DWP(192+12,"esp")); # restore %esp + &add (@T[0],&DWP(4,@T[1])); # $b + &add ($C,&DWP(8,@T[1])); + &mov (&DWP(0,@T[1]),$A); + &add ($D,&DWP(12,@T[1])); + &mov (&DWP(4,@T[1]),@T[0]); + &add ($E,&DWP(16,@T[1])); + &mov (&DWP(8,@T[1]),$C); + &mov (&DWP(12,@T[1]),$D); + &mov (&DWP(16,@T[1]),$E); +&function_end("_sha1_block_data_order_avx"); +} +&set_label("K_XX_XX",64); +&data_word(0x5a827999,0x5a827999,0x5a827999,0x5a827999); # K_00_19 +&data_word(0x6ed9eba1,0x6ed9eba1,0x6ed9eba1,0x6ed9eba1); # K_20_39 +&data_word(0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc); # K_40_59 +&data_word(0xca62c1d6,0xca62c1d6,0xca62c1d6,0xca62c1d6); # K_60_79 +&data_word(0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f); # pbswap mask +&data_byte(0xf,0xe,0xd,0xc,0xb,0xa,0x9,0x8,0x7,0x6,0x5,0x4,0x3,0x2,0x1,0x0); +} +&asciz("SHA1 block transform for x86, CRYPTOGAMS by "); + +&asm_finish(); diff --git a/external/boringssl/crypto/sha/asm/sha1-armv4-large.pl b/external/boringssl/crypto/sha/asm/sha1-armv4-large.pl new file mode 100644 index 0000000000..64e2ed6112 --- /dev/null +++ b/external/boringssl/crypto/sha/asm/sha1-armv4-large.pl @@ -0,0 +1,701 @@ +#!/usr/bin/env perl + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== + +# sha1_block procedure for ARMv4. +# +# January 2007. + +# Size/performance trade-off +# ==================================================================== +# impl size in bytes comp cycles[*] measured performance +# ==================================================================== +# thumb 304 3212 4420 +# armv4-small 392/+29% 1958/+64% 2250/+96% +# armv4-compact 740/+89% 1552/+26% 1840/+22% +# armv4-large 1420/+92% 1307/+19% 1370/+34%[***] +# full unroll ~5100/+260% ~1260/+4% ~1300/+5% +# ==================================================================== +# thumb = same as 'small' but in Thumb instructions[**] and +# with recurring code in two private functions; +# small = detached Xload/update, loops are folded; +# compact = detached Xload/update, 5x unroll; +# large = interleaved Xload/update, 5x unroll; +# full unroll = interleaved Xload/update, full unroll, estimated[!]; +# +# [*] Manually counted instructions in "grand" loop body. Measured +# performance is affected by prologue and epilogue overhead, +# i-cache availability, branch penalties, etc. +# [**] While each Thumb instruction is twice smaller, they are not as +# diverse as ARM ones: e.g., there are only two arithmetic +# instructions with 3 arguments, no [fixed] rotate, addressing +# modes are limited. As result it takes more instructions to do +# the same job in Thumb, therefore the code is never twice as +# small and always slower. +# [***] which is also ~35% better than compiler generated code. Dual- +# issue Cortex A8 core was measured to process input block in +# ~990 cycles. + +# August 2010. +# +# Rescheduling for dual-issue pipeline resulted in 13% improvement on +# Cortex A8 core and in absolute terms ~870 cycles per input block +# [or 13.6 cycles per byte]. + +# February 2011. +# +# Profiler-assisted and platform-specific optimization resulted in 10% +# improvement on Cortex A8 core and 12.2 cycles per byte. + +# September 2013. +# +# Add NEON implementation (see sha1-586.pl for background info). On +# Cortex A8 it was measured to process one byte in 6.7 cycles or >80% +# faster than integer-only code. Because [fully unrolled] NEON code +# is ~2.5x larger and there are some redundant instructions executed +# when processing last block, improvement is not as big for smallest +# blocks, only ~30%. Snapdragon S4 is a tad faster, 6.4 cycles per +# byte, which is also >80% faster than integer-only code. Cortex-A15 +# is even faster spending 5.6 cycles per byte outperforming integer- +# only code by factor of 2. + +# May 2014. +# +# Add ARMv8 code path performing at 2.35 cpb on Apple A7. + +$flavour = shift; +if ($flavour=~/^\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; } +else { while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {} } + +if ($flavour && $flavour ne "void") { + $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; + ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or + ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or + die "can't locate arm-xlate.pl"; + + open STDOUT,"| \"$^X\" $xlate $flavour $output"; +} else { + open STDOUT,">$output"; +} + +$ctx="r0"; +$inp="r1"; +$len="r2"; +$a="r3"; +$b="r4"; +$c="r5"; +$d="r6"; +$e="r7"; +$K="r8"; +$t0="r9"; +$t1="r10"; +$t2="r11"; +$t3="r12"; +$Xi="r14"; +@V=($a,$b,$c,$d,$e); + +sub Xupdate { +my ($a,$b,$c,$d,$e,$opt1,$opt2)=@_; +$code.=<<___; + ldr $t0,[$Xi,#15*4] + ldr $t1,[$Xi,#13*4] + ldr $t2,[$Xi,#7*4] + add $e,$K,$e,ror#2 @ E+=K_xx_xx + ldr $t3,[$Xi,#2*4] + eor $t0,$t0,$t1 + eor $t2,$t2,$t3 @ 1 cycle stall + eor $t1,$c,$d @ F_xx_xx + mov $t0,$t0,ror#31 + add $e,$e,$a,ror#27 @ E+=ROR(A,27) + eor $t0,$t0,$t2,ror#31 + str $t0,[$Xi,#-4]! + $opt1 @ F_xx_xx + $opt2 @ F_xx_xx + add $e,$e,$t0 @ E+=X[i] +___ +} + +sub BODY_00_15 { +my ($a,$b,$c,$d,$e)=@_; +$code.=<<___; +#if __ARM_ARCH__<7 + ldrb $t1,[$inp,#2] + ldrb $t0,[$inp,#3] + ldrb $t2,[$inp,#1] + add $e,$K,$e,ror#2 @ E+=K_00_19 + ldrb $t3,[$inp],#4 + orr $t0,$t0,$t1,lsl#8 + eor $t1,$c,$d @ F_xx_xx + orr $t0,$t0,$t2,lsl#16 + add $e,$e,$a,ror#27 @ E+=ROR(A,27) + orr $t0,$t0,$t3,lsl#24 +#else + ldr $t0,[$inp],#4 @ handles unaligned + add $e,$K,$e,ror#2 @ E+=K_00_19 + eor $t1,$c,$d @ F_xx_xx + add $e,$e,$a,ror#27 @ E+=ROR(A,27) +#ifdef __ARMEL__ + rev $t0,$t0 @ byte swap +#endif +#endif + and $t1,$b,$t1,ror#2 + add $e,$e,$t0 @ E+=X[i] + eor $t1,$t1,$d,ror#2 @ F_00_19(B,C,D) + str $t0,[$Xi,#-4]! + add $e,$e,$t1 @ E+=F_00_19(B,C,D) +___ +} + +sub BODY_16_19 { +my ($a,$b,$c,$d,$e)=@_; + &Xupdate(@_,"and $t1,$b,$t1,ror#2"); +$code.=<<___; + eor $t1,$t1,$d,ror#2 @ F_00_19(B,C,D) + add $e,$e,$t1 @ E+=F_00_19(B,C,D) +___ +} + +sub BODY_20_39 { +my ($a,$b,$c,$d,$e)=@_; + &Xupdate(@_,"eor $t1,$b,$t1,ror#2"); +$code.=<<___; + add $e,$e,$t1 @ E+=F_20_39(B,C,D) +___ +} + +sub BODY_40_59 { +my ($a,$b,$c,$d,$e)=@_; + &Xupdate(@_,"and $t1,$b,$t1,ror#2","and $t2,$c,$d"); +$code.=<<___; + add $e,$e,$t1 @ E+=F_40_59(B,C,D) + add $e,$e,$t2,ror#2 +___ +} + +$code=<<___; +#include + +.text +.code 32 + +.global sha1_block_data_order +.type sha1_block_data_order,%function + +.align 5 +sha1_block_data_order: +#if __ARM_MAX_ARCH__>=7 + sub r3,pc,#8 @ sha1_block_data_order + ldr r12,.LOPENSSL_armcap + ldr r12,[r3,r12] @ OPENSSL_armcap_P +#ifdef __APPLE__ + ldr r12,[r12] +#endif + tst r12,#ARMV8_SHA1 + bne .LARMv8 + tst r12,#ARMV7_NEON + bne .LNEON +#endif + stmdb sp!,{r4-r12,lr} + add $len,$inp,$len,lsl#6 @ $len to point at the end of $inp + ldmia $ctx,{$a,$b,$c,$d,$e} +.Lloop: + ldr $K,.LK_00_19 + mov $Xi,sp + sub sp,sp,#15*4 + mov $c,$c,ror#30 + mov $d,$d,ror#30 + mov $e,$e,ror#30 @ [6] +.L_00_15: +___ +for($i=0;$i<5;$i++) { + &BODY_00_15(@V); unshift(@V,pop(@V)); +} +$code.=<<___; + teq $Xi,sp + bne .L_00_15 @ [((11+4)*5+2)*3] + sub sp,sp,#25*4 +___ + &BODY_00_15(@V); unshift(@V,pop(@V)); + &BODY_16_19(@V); unshift(@V,pop(@V)); + &BODY_16_19(@V); unshift(@V,pop(@V)); + &BODY_16_19(@V); unshift(@V,pop(@V)); + &BODY_16_19(@V); unshift(@V,pop(@V)); +$code.=<<___; + + ldr $K,.LK_20_39 @ [+15+16*4] + cmn sp,#0 @ [+3], clear carry to denote 20_39 +.L_20_39_or_60_79: +___ +for($i=0;$i<5;$i++) { + &BODY_20_39(@V); unshift(@V,pop(@V)); +} +$code.=<<___; + teq $Xi,sp @ preserve carry + bne .L_20_39_or_60_79 @ [+((12+3)*5+2)*4] + bcs .L_done @ [+((12+3)*5+2)*4], spare 300 bytes + + ldr $K,.LK_40_59 + sub sp,sp,#20*4 @ [+2] +.L_40_59: +___ +for($i=0;$i<5;$i++) { + &BODY_40_59(@V); unshift(@V,pop(@V)); +} +$code.=<<___; + teq $Xi,sp + bne .L_40_59 @ [+((12+5)*5+2)*4] + + ldr $K,.LK_60_79 + sub sp,sp,#20*4 + cmp sp,#0 @ set carry to denote 60_79 + b .L_20_39_or_60_79 @ [+4], spare 300 bytes +.L_done: + add sp,sp,#80*4 @ "deallocate" stack frame + ldmia $ctx,{$K,$t0,$t1,$t2,$t3} + add $a,$K,$a + add $b,$t0,$b + add $c,$t1,$c,ror#2 + add $d,$t2,$d,ror#2 + add $e,$t3,$e,ror#2 + stmia $ctx,{$a,$b,$c,$d,$e} + teq $inp,$len + bne .Lloop @ [+18], total 1307 + +#if __ARM_ARCH__>=5 + ldmia sp!,{r4-r12,pc} +#else + ldmia sp!,{r4-r12,lr} + tst lr,#1 + moveq pc,lr @ be binary compatible with V4, yet + bx lr @ interoperable with Thumb ISA:-) +#endif +.size sha1_block_data_order,.-sha1_block_data_order + +.align 5 +.LK_00_19: .word 0x5a827999 +.LK_20_39: .word 0x6ed9eba1 +.LK_40_59: .word 0x8f1bbcdc +.LK_60_79: .word 0xca62c1d6 +#if __ARM_MAX_ARCH__>=7 +.LOPENSSL_armcap: +.word OPENSSL_armcap_P-sha1_block_data_order +#endif +.asciz "SHA1 block transform for ARMv4/NEON/ARMv8, CRYPTOGAMS by " +.align 5 +___ +##################################################################### +# NEON stuff +# +{{{ +my @V=($a,$b,$c,$d,$e); +my ($K_XX_XX,$Ki,$t0,$t1,$Xfer,$saved_sp)=map("r$_",(8..12,14)); +my $Xi=4; +my @X=map("q$_",(8..11,0..3)); +my @Tx=("q12","q13"); +my ($K,$zero)=("q14","q15"); +my $j=0; + +sub AUTOLOAD() # thunk [simplified] x86-style perlasm +{ my $opcode = $AUTOLOAD; $opcode =~ s/.*:://; $opcode =~ s/_/\./; + my $arg = pop; + $arg = "#$arg" if ($arg*1 eq $arg); + $code .= "\t$opcode\t".join(',',@_,$arg)."\n"; +} + +sub body_00_19 () { + ( + '($a,$b,$c,$d,$e)=@V;'. # '$code.="@ $j\n";'. + '&bic ($t0,$d,$b)', + '&add ($e,$e,$Ki)', # e+=X[i]+K + '&and ($t1,$c,$b)', + '&ldr ($Ki,sprintf "[sp,#%d]",4*(($j+1)&15))', + '&add ($e,$e,$a,"ror#27")', # e+=ROR(A,27) + '&eor ($t1,$t1,$t0)', # F_00_19 + '&mov ($b,$b,"ror#2")', # b=ROR(b,2) + '&add ($e,$e,$t1);'. # e+=F_00_19 + '$j++; unshift(@V,pop(@V));' + ) +} +sub body_20_39 () { + ( + '($a,$b,$c,$d,$e)=@V;'. # '$code.="@ $j\n";'. + '&eor ($t0,$b,$d)', + '&add ($e,$e,$Ki)', # e+=X[i]+K + '&ldr ($Ki,sprintf "[sp,#%d]",4*(($j+1)&15)) if ($j<79)', + '&eor ($t1,$t0,$c)', # F_20_39 + '&add ($e,$e,$a,"ror#27")', # e+=ROR(A,27) + '&mov ($b,$b,"ror#2")', # b=ROR(b,2) + '&add ($e,$e,$t1);'. # e+=F_20_39 + '$j++; unshift(@V,pop(@V));' + ) +} +sub body_40_59 () { + ( + '($a,$b,$c,$d,$e)=@V;'. # '$code.="@ $j\n";'. + '&add ($e,$e,$Ki)', # e+=X[i]+K + '&and ($t0,$c,$d)', + '&ldr ($Ki,sprintf "[sp,#%d]",4*(($j+1)&15))', + '&add ($e,$e,$a,"ror#27")', # e+=ROR(A,27) + '&eor ($t1,$c,$d)', + '&add ($e,$e,$t0)', + '&and ($t1,$t1,$b)', + '&mov ($b,$b,"ror#2")', # b=ROR(b,2) + '&add ($e,$e,$t1);'. # e+=F_40_59 + '$j++; unshift(@V,pop(@V));' + ) +} + +sub Xupdate_16_31 () +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); + my ($a,$b,$c,$d,$e); + + &vext_8 (@X[0],@X[-4&7],@X[-3&7],8); # compose "X[-14]" in "X[0]" + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vadd_i32 (@Tx[1],@X[-1&7],$K); + eval(shift(@insns)); + &vld1_32 ("{$K\[]}","[$K_XX_XX,:32]!") if ($Xi%5==0); + eval(shift(@insns)); + &vext_8 (@Tx[0],@X[-1&7],$zero,4); # "X[-3]", 3 words + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &veor (@X[0],@X[0],@X[-4&7]); # "X[0]"^="X[-16]" + eval(shift(@insns)); + eval(shift(@insns)); + &veor (@Tx[0],@Tx[0],@X[-2&7]); # "X[-3]"^"X[-8]" + eval(shift(@insns)); + eval(shift(@insns)); + &veor (@Tx[0],@Tx[0],@X[0]); # "X[0]"^="X[-3]"^"X[-8] + eval(shift(@insns)); + eval(shift(@insns)); + &vst1_32 ("{@Tx[1]}","[$Xfer,:128]!"); # X[]+K xfer + &sub ($Xfer,$Xfer,64) if ($Xi%4==0); + eval(shift(@insns)); + eval(shift(@insns)); + &vext_8 (@Tx[1],$zero,@Tx[0],4); # "X[0]"<<96, extract one dword + eval(shift(@insns)); + eval(shift(@insns)); + &vadd_i32 (@X[0],@Tx[0],@Tx[0]); + eval(shift(@insns)); + eval(shift(@insns)); + &vsri_32 (@X[0],@Tx[0],31); # "X[0]"<<<=1 + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vshr_u32 (@Tx[0],@Tx[1],30); + eval(shift(@insns)); + eval(shift(@insns)); + &vshl_u32 (@Tx[1],@Tx[1],2); + eval(shift(@insns)); + eval(shift(@insns)); + &veor (@X[0],@X[0],@Tx[0]); + eval(shift(@insns)); + eval(shift(@insns)); + &veor (@X[0],@X[0],@Tx[1]); # "X[0]"^=("X[0]">>96)<<<2 + + foreach (@insns) { eval; } # remaining instructions [if any] + + $Xi++; push(@X,shift(@X)); # "rotate" X[] +} + +sub Xupdate_32_79 () +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); + my ($a,$b,$c,$d,$e); + + &vext_8 (@Tx[0],@X[-2&7],@X[-1&7],8); # compose "X[-6]" + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &veor (@X[0],@X[0],@X[-4&7]); # "X[0]"="X[-32]"^"X[-16]" + eval(shift(@insns)); + eval(shift(@insns)); + &veor (@X[0],@X[0],@X[-7&7]); # "X[0]"^="X[-28]" + eval(shift(@insns)); + eval(shift(@insns)); + &vadd_i32 (@Tx[1],@X[-1&7],$K); + eval(shift(@insns)); + &vld1_32 ("{$K\[]}","[$K_XX_XX,:32]!") if ($Xi%5==0); + eval(shift(@insns)); + &veor (@Tx[0],@Tx[0],@X[0]); # "X[-6]"^="X[0]" + eval(shift(@insns)); + eval(shift(@insns)); + &vshr_u32 (@X[0],@Tx[0],30); + eval(shift(@insns)); + eval(shift(@insns)); + &vst1_32 ("{@Tx[1]}","[$Xfer,:128]!"); # X[]+K xfer + &sub ($Xfer,$Xfer,64) if ($Xi%4==0); + eval(shift(@insns)); + eval(shift(@insns)); + &vsli_32 (@X[0],@Tx[0],2); # "X[0]"="X[-6]"<<<2 + + foreach (@insns) { eval; } # remaining instructions [if any] + + $Xi++; push(@X,shift(@X)); # "rotate" X[] +} + +sub Xuplast_80 () +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); + my ($a,$b,$c,$d,$e); + + &vadd_i32 (@Tx[1],@X[-1&7],$K); + eval(shift(@insns)); + eval(shift(@insns)); + &vst1_32 ("{@Tx[1]}","[$Xfer,:128]!"); + &sub ($Xfer,$Xfer,64); + + &teq ($inp,$len); + &sub ($K_XX_XX,$K_XX_XX,16); # rewind $K_XX_XX + &subeq ($inp,$inp,64); # reload last block to avoid SEGV + &vld1_8 ("{@X[-4&7]-@X[-3&7]}","[$inp]!"); + eval(shift(@insns)); + eval(shift(@insns)); + &vld1_8 ("{@X[-2&7]-@X[-1&7]}","[$inp]!"); + eval(shift(@insns)); + eval(shift(@insns)); + &vld1_32 ("{$K\[]}","[$K_XX_XX,:32]!"); # load K_00_19 + eval(shift(@insns)); + eval(shift(@insns)); + &vrev32_8 (@X[-4&7],@X[-4&7]); + + foreach (@insns) { eval; } # remaining instructions + + $Xi=0; +} + +sub Xloop() +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); + my ($a,$b,$c,$d,$e); + + &vrev32_8 (@X[($Xi-3)&7],@X[($Xi-3)&7]); + eval(shift(@insns)); + eval(shift(@insns)); + &vadd_i32 (@X[$Xi&7],@X[($Xi-4)&7],$K); + eval(shift(@insns)); + eval(shift(@insns)); + &vst1_32 ("{@X[$Xi&7]}","[$Xfer,:128]!");# X[]+K xfer to IALU + + foreach (@insns) { eval; } + + $Xi++; +} + +$code.=<<___; +#if __ARM_MAX_ARCH__>=7 +.arch armv7-a +.fpu neon + +.type sha1_block_data_order_neon,%function +.align 4 +sha1_block_data_order_neon: +.LNEON: + stmdb sp!,{r4-r12,lr} + add $len,$inp,$len,lsl#6 @ $len to point at the end of $inp + @ dmb @ errata #451034 on early Cortex A8 + @ vstmdb sp!,{d8-d15} @ ABI specification says so + mov $saved_sp,sp + sub sp,sp,#64 @ alloca + adr $K_XX_XX,.LK_00_19 + bic sp,sp,#15 @ align for 128-bit stores + + ldmia $ctx,{$a,$b,$c,$d,$e} @ load context + mov $Xfer,sp + + vld1.8 {@X[-4&7]-@X[-3&7]},[$inp]! @ handles unaligned + veor $zero,$zero,$zero + vld1.8 {@X[-2&7]-@X[-1&7]},[$inp]! + vld1.32 {${K}\[]},[$K_XX_XX,:32]! @ load K_00_19 + vrev32.8 @X[-4&7],@X[-4&7] @ yes, even on + vrev32.8 @X[-3&7],@X[-3&7] @ big-endian... + vrev32.8 @X[-2&7],@X[-2&7] + vadd.i32 @X[0],@X[-4&7],$K + vrev32.8 @X[-1&7],@X[-1&7] + vadd.i32 @X[1],@X[-3&7],$K + vst1.32 {@X[0]},[$Xfer,:128]! + vadd.i32 @X[2],@X[-2&7],$K + vst1.32 {@X[1]},[$Xfer,:128]! + vst1.32 {@X[2]},[$Xfer,:128]! + ldr $Ki,[sp] @ big RAW stall + +.Loop_neon: +___ + &Xupdate_16_31(\&body_00_19); + &Xupdate_16_31(\&body_00_19); + &Xupdate_16_31(\&body_00_19); + &Xupdate_16_31(\&body_00_19); + &Xupdate_32_79(\&body_00_19); + &Xupdate_32_79(\&body_20_39); + &Xupdate_32_79(\&body_20_39); + &Xupdate_32_79(\&body_20_39); + &Xupdate_32_79(\&body_20_39); + &Xupdate_32_79(\&body_20_39); + &Xupdate_32_79(\&body_40_59); + &Xupdate_32_79(\&body_40_59); + &Xupdate_32_79(\&body_40_59); + &Xupdate_32_79(\&body_40_59); + &Xupdate_32_79(\&body_40_59); + &Xupdate_32_79(\&body_20_39); + &Xuplast_80(\&body_20_39); + &Xloop(\&body_20_39); + &Xloop(\&body_20_39); + &Xloop(\&body_20_39); +$code.=<<___; + ldmia $ctx,{$Ki,$t0,$t1,$Xfer} @ accumulate context + add $a,$a,$Ki + ldr $Ki,[$ctx,#16] + add $b,$b,$t0 + add $c,$c,$t1 + add $d,$d,$Xfer + moveq sp,$saved_sp + add $e,$e,$Ki + ldrne $Ki,[sp] + stmia $ctx,{$a,$b,$c,$d,$e} + addne $Xfer,sp,#3*16 + bne .Loop_neon + + @ vldmia sp!,{d8-d15} + ldmia sp!,{r4-r12,pc} +.size sha1_block_data_order_neon,.-sha1_block_data_order_neon +#endif +___ +}}} +##################################################################### +# ARMv8 stuff +# +{{{ +my ($ABCD,$E,$E0,$E1)=map("q$_",(0..3)); +my @MSG=map("q$_",(4..7)); +my @Kxx=map("q$_",(8..11)); +my ($W0,$W1,$ABCD_SAVE)=map("q$_",(12..14)); + +$code.=<<___; +#if __ARM_MAX_ARCH__>=7 +.type sha1_block_data_order_armv8,%function +.align 5 +sha1_block_data_order_armv8: +.LARMv8: + vstmdb sp!,{d8-d15} @ ABI specification says so + + veor $E,$E,$E + adr r3,.LK_00_19 + vld1.32 {$ABCD},[$ctx]! + vld1.32 {$E\[0]},[$ctx] + sub $ctx,$ctx,#16 + vld1.32 {@Kxx[0]\[]},[r3,:32]! + vld1.32 {@Kxx[1]\[]},[r3,:32]! + vld1.32 {@Kxx[2]\[]},[r3,:32]! + vld1.32 {@Kxx[3]\[]},[r3,:32] + +.Loop_v8: + vld1.8 {@MSG[0]-@MSG[1]},[$inp]! + vld1.8 {@MSG[2]-@MSG[3]},[$inp]! + vrev32.8 @MSG[0],@MSG[0] + vrev32.8 @MSG[1],@MSG[1] + + vadd.i32 $W0,@Kxx[0],@MSG[0] + vrev32.8 @MSG[2],@MSG[2] + vmov $ABCD_SAVE,$ABCD @ offload + subs $len,$len,#1 + + vadd.i32 $W1,@Kxx[0],@MSG[1] + vrev32.8 @MSG[3],@MSG[3] + sha1h $E1,$ABCD @ 0 + sha1c $ABCD,$E,$W0 + vadd.i32 $W0,@Kxx[$j],@MSG[2] + sha1su0 @MSG[0],@MSG[1],@MSG[2] +___ +for ($j=0,$i=1;$i<20-3;$i++) { +my $f=("c","p","m","p")[$i/5]; +$code.=<<___; + sha1h $E0,$ABCD @ $i + sha1$f $ABCD,$E1,$W1 + vadd.i32 $W1,@Kxx[$j],@MSG[3] + sha1su1 @MSG[0],@MSG[3] +___ +$code.=<<___ if ($i<20-4); + sha1su0 @MSG[1],@MSG[2],@MSG[3] +___ + ($E0,$E1)=($E1,$E0); ($W0,$W1)=($W1,$W0); + push(@MSG,shift(@MSG)); $j++ if ((($i+3)%5)==0); +} +$code.=<<___; + sha1h $E0,$ABCD @ $i + sha1p $ABCD,$E1,$W1 + vadd.i32 $W1,@Kxx[$j],@MSG[3] + + sha1h $E1,$ABCD @ 18 + sha1p $ABCD,$E0,$W0 + + sha1h $E0,$ABCD @ 19 + sha1p $ABCD,$E1,$W1 + + vadd.i32 $E,$E,$E0 + vadd.i32 $ABCD,$ABCD,$ABCD_SAVE + bne .Loop_v8 + + vst1.32 {$ABCD},[$ctx]! + vst1.32 {$E\[0]},[$ctx] + + vldmia sp!,{d8-d15} + ret @ bx lr +.size sha1_block_data_order_armv8,.-sha1_block_data_order_armv8 +#endif +___ +}}} +$code.=<<___; +#if __ARM_MAX_ARCH__>=7 +.comm OPENSSL_armcap_P,4,4 +.hidden OPENSSL_armcap_P +#endif +___ + +{ my %opcode = ( + "sha1c" => 0xf2000c40, "sha1p" => 0xf2100c40, + "sha1m" => 0xf2200c40, "sha1su0" => 0xf2300c40, + "sha1h" => 0xf3b902c0, "sha1su1" => 0xf3ba0380 ); + + sub unsha1 { + my ($mnemonic,$arg)=@_; + + if ($arg =~ m/q([0-9]+)(?:,\s*q([0-9]+))?,\s*q([0-9]+)/o) { + my $word = $opcode{$mnemonic}|(($1&7)<<13)|(($1&8)<<19) + |(($2&7)<<17)|(($2&8)<<4) + |(($3&7)<<1) |(($3&8)<<2); + # since ARMv7 instructions are always encoded little-endian. + # correct solution is to use .inst directive, but older + # assemblers don't implement it:-( + sprintf ".byte\t0x%02x,0x%02x,0x%02x,0x%02x\t@ %s %s", + $word&0xff,($word>>8)&0xff, + ($word>>16)&0xff,($word>>24)&0xff, + $mnemonic,$arg; + } + } +} + +foreach (split($/,$code)) { + s/{q([0-9]+)\[\]}/sprintf "{d%d[],d%d[]}",2*$1,2*$1+1/eo or + s/{q([0-9]+)\[0\]}/sprintf "{d%d[0]}",2*$1/eo; + + s/\b(sha1\w+)\s+(q.*)/unsha1($1,$2)/geo; + + s/\bret\b/bx lr/o or + s/\bbx\s+lr\b/.word\t0xe12fff1e/o; # make it possible to compile with -march=armv4 + + print $_,$/; +} + +close STDOUT; # enforce flush diff --git a/external/boringssl/crypto/sha/asm/sha1-armv8.pl b/external/boringssl/crypto/sha/asm/sha1-armv8.pl new file mode 100644 index 0000000000..1c4fe4a21d --- /dev/null +++ b/external/boringssl/crypto/sha/asm/sha1-armv8.pl @@ -0,0 +1,347 @@ +#!/usr/bin/env perl +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# SHA1 for ARMv8. +# +# Performance in cycles per processed byte and improvement coefficient +# over code generated with "default" compiler: +# +# hardware-assisted software(*) +# Apple A7 2.31 4.13 (+14%) +# Cortex-A53 2.24 8.03 (+97%) +# Cortex-A57 2.35 7.88 (+74%) +# Denver 2.13 3.97 (+0%)(**) +# X-Gene 8.80 (+200%) +# +# (*) Software results are presented mostly for reference purposes. +# (**) Keep in mind that Denver relies on binary translation, which +# optimizes compiler output at run-time. + +$flavour = shift; +$output = shift; + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or +die "can't locate arm-xlate.pl"; + +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; + +($ctx,$inp,$num)=("x0","x1","x2"); +@Xw=map("w$_",(3..17,19)); +@Xx=map("x$_",(3..17,19)); +@V=($A,$B,$C,$D,$E)=map("w$_",(20..24)); +($t0,$t1,$t2,$K)=map("w$_",(25..28)); + + +sub BODY_00_19 { +my ($i,$a,$b,$c,$d,$e)=@_; +my $j=($i+2)&15; + +$code.=<<___ if ($i<15 && !($i&1)); + lsr @Xx[$i+1],@Xx[$i],#32 +___ +$code.=<<___ if ($i<14 && !($i&1)); + ldr @Xx[$i+2],[$inp,#`($i+2)*4-64`] +___ +$code.=<<___ if ($i<14 && ($i&1)); +#ifdef __ARMEB__ + ror @Xx[$i+1],@Xx[$i+1],#32 +#else + rev32 @Xx[$i+1],@Xx[$i+1] +#endif +___ +$code.=<<___ if ($i<14); + bic $t0,$d,$b + and $t1,$c,$b + ror $t2,$a,#27 + add $d,$d,$K // future e+=K + orr $t0,$t0,$t1 + add $e,$e,$t2 // e+=rot(a,5) + ror $b,$b,#2 + add $d,$d,@Xw[($i+1)&15] // future e+=X[i] + add $e,$e,$t0 // e+=F(b,c,d) +___ +$code.=<<___ if ($i==19); + movz $K,#0xeba1 + movk $K,#0x6ed9,lsl#16 +___ +$code.=<<___ if ($i>=14); + eor @Xw[$j],@Xw[$j],@Xw[($j+2)&15] + bic $t0,$d,$b + and $t1,$c,$b + ror $t2,$a,#27 + eor @Xw[$j],@Xw[$j],@Xw[($j+8)&15] + add $d,$d,$K // future e+=K + orr $t0,$t0,$t1 + add $e,$e,$t2 // e+=rot(a,5) + eor @Xw[$j],@Xw[$j],@Xw[($j+13)&15] + ror $b,$b,#2 + add $d,$d,@Xw[($i+1)&15] // future e+=X[i] + add $e,$e,$t0 // e+=F(b,c,d) + ror @Xw[$j],@Xw[$j],#31 +___ +} + +sub BODY_40_59 { +my ($i,$a,$b,$c,$d,$e)=@_; +my $j=($i+2)&15; + +$code.=<<___ if ($i==59); + movz $K,#0xc1d6 + movk $K,#0xca62,lsl#16 +___ +$code.=<<___; + orr $t0,$b,$c + and $t1,$b,$c + eor @Xw[$j],@Xw[$j],@Xw[($j+2)&15] + ror $t2,$a,#27 + and $t0,$t0,$d + add $d,$d,$K // future e+=K + eor @Xw[$j],@Xw[$j],@Xw[($j+8)&15] + add $e,$e,$t2 // e+=rot(a,5) + orr $t0,$t0,$t1 + ror $b,$b,#2 + eor @Xw[$j],@Xw[$j],@Xw[($j+13)&15] + add $d,$d,@Xw[($i+1)&15] // future e+=X[i] + add $e,$e,$t0 // e+=F(b,c,d) + ror @Xw[$j],@Xw[$j],#31 +___ +} + +sub BODY_20_39 { +my ($i,$a,$b,$c,$d,$e)=@_; +my $j=($i+2)&15; + +$code.=<<___ if ($i==39); + movz $K,#0xbcdc + movk $K,#0x8f1b,lsl#16 +___ +$code.=<<___ if ($i<78); + eor @Xw[$j],@Xw[$j],@Xw[($j+2)&15] + eor $t0,$d,$b + ror $t2,$a,#27 + add $d,$d,$K // future e+=K + eor @Xw[$j],@Xw[$j],@Xw[($j+8)&15] + eor $t0,$t0,$c + add $e,$e,$t2 // e+=rot(a,5) + ror $b,$b,#2 + eor @Xw[$j],@Xw[$j],@Xw[($j+13)&15] + add $d,$d,@Xw[($i+1)&15] // future e+=X[i] + add $e,$e,$t0 // e+=F(b,c,d) + ror @Xw[$j],@Xw[$j],#31 +___ +$code.=<<___ if ($i==78); + ldp @Xw[1],@Xw[2],[$ctx] + eor $t0,$d,$b + ror $t2,$a,#27 + add $d,$d,$K // future e+=K + eor $t0,$t0,$c + add $e,$e,$t2 // e+=rot(a,5) + ror $b,$b,#2 + add $d,$d,@Xw[($i+1)&15] // future e+=X[i] + add $e,$e,$t0 // e+=F(b,c,d) +___ +$code.=<<___ if ($i==79); + ldp @Xw[3],@Xw[4],[$ctx,#8] + eor $t0,$d,$b + ror $t2,$a,#27 + eor $t0,$t0,$c + add $e,$e,$t2 // e+=rot(a,5) + ror $b,$b,#2 + ldr @Xw[5],[$ctx,#16] + add $e,$e,$t0 // e+=F(b,c,d) +___ +} + +$code.=<<___; +#include + +.text + +.extern OPENSSL_armcap_P +.globl sha1_block_data_order +.type sha1_block_data_order,%function +.align 6 +sha1_block_data_order: + ldr x16,.LOPENSSL_armcap_P + adr x17,.LOPENSSL_armcap_P + add x16,x16,x17 + ldr w16,[x16] + tst w16,#ARMV8_SHA1 + b.ne .Lv8_entry + + stp x29,x30,[sp,#-96]! + add x29,sp,#0 + stp x19,x20,[sp,#16] + stp x21,x22,[sp,#32] + stp x23,x24,[sp,#48] + stp x25,x26,[sp,#64] + stp x27,x28,[sp,#80] + + ldp $A,$B,[$ctx] + ldp $C,$D,[$ctx,#8] + ldr $E,[$ctx,#16] + +.Loop: + ldr @Xx[0],[$inp],#64 + movz $K,#0x7999 + sub $num,$num,#1 + movk $K,#0x5a82,lsl#16 +#ifdef __ARMEB__ + ror $Xx[0],@Xx[0],#32 +#else + rev32 @Xx[0],@Xx[0] +#endif + add $E,$E,$K // warm it up + add $E,$E,@Xw[0] +___ +for($i=0;$i<20;$i++) { &BODY_00_19($i,@V); unshift(@V,pop(@V)); } +for(;$i<40;$i++) { &BODY_20_39($i,@V); unshift(@V,pop(@V)); } +for(;$i<60;$i++) { &BODY_40_59($i,@V); unshift(@V,pop(@V)); } +for(;$i<80;$i++) { &BODY_20_39($i,@V); unshift(@V,pop(@V)); } +$code.=<<___; + add $B,$B,@Xw[2] + add $C,$C,@Xw[3] + add $A,$A,@Xw[1] + add $D,$D,@Xw[4] + add $E,$E,@Xw[5] + stp $A,$B,[$ctx] + stp $C,$D,[$ctx,#8] + str $E,[$ctx,#16] + cbnz $num,.Loop + + ldp x19,x20,[sp,#16] + ldp x21,x22,[sp,#32] + ldp x23,x24,[sp,#48] + ldp x25,x26,[sp,#64] + ldp x27,x28,[sp,#80] + ldr x29,[sp],#96 + ret +.size sha1_block_data_order,.-sha1_block_data_order +___ +{{{ +my ($ABCD,$E,$E0,$E1)=map("v$_.16b",(0..3)); +my @MSG=map("v$_.16b",(4..7)); +my @Kxx=map("v$_.4s",(16..19)); +my ($W0,$W1)=("v20.4s","v21.4s"); +my $ABCD_SAVE="v22.16b"; + +$code.=<<___; +.type sha1_block_armv8,%function +.align 6 +sha1_block_armv8: +.Lv8_entry: + stp x29,x30,[sp,#-16]! + add x29,sp,#0 + + adr x4,.Lconst + eor $E,$E,$E + ld1.32 {$ABCD},[$ctx],#16 + ld1.32 {$E}[0],[$ctx] + sub $ctx,$ctx,#16 + ld1.32 {@Kxx[0]-@Kxx[3]},[x4] + +.Loop_hw: + ld1 {@MSG[0]-@MSG[3]},[$inp],#64 + sub $num,$num,#1 + rev32 @MSG[0],@MSG[0] + rev32 @MSG[1],@MSG[1] + + add.i32 $W0,@Kxx[0],@MSG[0] + rev32 @MSG[2],@MSG[2] + orr $ABCD_SAVE,$ABCD,$ABCD // offload + + add.i32 $W1,@Kxx[0],@MSG[1] + rev32 @MSG[3],@MSG[3] + sha1h $E1,$ABCD + sha1c $ABCD,$E,$W0 // 0 + add.i32 $W0,@Kxx[$j],@MSG[2] + sha1su0 @MSG[0],@MSG[1],@MSG[2] +___ +for ($j=0,$i=1;$i<20-3;$i++) { +my $f=("c","p","m","p")[$i/5]; +$code.=<<___; + sha1h $E0,$ABCD // $i + sha1$f $ABCD,$E1,$W1 + add.i32 $W1,@Kxx[$j],@MSG[3] + sha1su1 @MSG[0],@MSG[3] +___ +$code.=<<___ if ($i<20-4); + sha1su0 @MSG[1],@MSG[2],@MSG[3] +___ + ($E0,$E1)=($E1,$E0); ($W0,$W1)=($W1,$W0); + push(@MSG,shift(@MSG)); $j++ if ((($i+3)%5)==0); +} +$code.=<<___; + sha1h $E0,$ABCD // $i + sha1p $ABCD,$E1,$W1 + add.i32 $W1,@Kxx[$j],@MSG[3] + + sha1h $E1,$ABCD // 18 + sha1p $ABCD,$E0,$W0 + + sha1h $E0,$ABCD // 19 + sha1p $ABCD,$E1,$W1 + + add.i32 $E,$E,$E0 + add.i32 $ABCD,$ABCD,$ABCD_SAVE + + cbnz $num,.Loop_hw + + st1.32 {$ABCD},[$ctx],#16 + st1.32 {$E}[0],[$ctx] + + ldr x29,[sp],#16 + ret +.size sha1_block_armv8,.-sha1_block_armv8 +.align 6 +.Lconst: +.long 0x5a827999,0x5a827999,0x5a827999,0x5a827999 //K_00_19 +.long 0x6ed9eba1,0x6ed9eba1,0x6ed9eba1,0x6ed9eba1 //K_20_39 +.long 0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc //K_40_59 +.long 0xca62c1d6,0xca62c1d6,0xca62c1d6,0xca62c1d6 //K_60_79 +.LOPENSSL_armcap_P: +.quad OPENSSL_armcap_P-. +.asciz "SHA1 block transform for ARMv8, CRYPTOGAMS by " +.align 2 +.comm OPENSSL_armcap_P,4,4 +___ +}}} + +{ my %opcode = ( + "sha1c" => 0x5e000000, "sha1p" => 0x5e001000, + "sha1m" => 0x5e002000, "sha1su0" => 0x5e003000, + "sha1h" => 0x5e280800, "sha1su1" => 0x5e281800 ); + + sub unsha1 { + my ($mnemonic,$arg)=@_; + + $arg =~ m/[qv]([0-9]+)[^,]*,\s*[qv]([0-9]+)[^,]*(?:,\s*[qv]([0-9]+))?/o + && + sprintf ".inst\t0x%08x\t//%s %s", + $opcode{$mnemonic}|$1|($2<<5)|($3<<16), + $mnemonic,$arg; + } +} + +foreach(split("\n",$code)) { + + s/\`([^\`]*)\`/eval($1)/geo; + + s/\b(sha1\w+)\s+([qv].*)/unsha1($1,$2)/geo; + + s/\.\w?32\b//o and s/\.16b/\.4s/go; + m/(ld|st)1[^\[]+\[0\]/o and s/\.4s/\.s/go; + + print $_,"\n"; +} + +close STDOUT; diff --git a/external/boringssl/crypto/sha/asm/sha1-x86_64.pl b/external/boringssl/crypto/sha/asm/sha1-x86_64.pl new file mode 100644 index 0000000000..4895f922ae --- /dev/null +++ b/external/boringssl/crypto/sha/asm/sha1-x86_64.pl @@ -0,0 +1,2059 @@ +#!/usr/bin/env perl +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# sha1_block procedure for x86_64. +# +# It was brought to my attention that on EM64T compiler-generated code +# was far behind 32-bit assembler implementation. This is unlike on +# Opteron where compiler-generated code was only 15% behind 32-bit +# assembler, which originally made it hard to motivate the effort. +# There was suggestion to mechanically translate 32-bit code, but I +# dismissed it, reasoning that x86_64 offers enough register bank +# capacity to fully utilize SHA-1 parallelism. Therefore this fresh +# implementation:-) However! While 64-bit code does perform better +# on Opteron, I failed to beat 32-bit assembler on EM64T core. Well, +# x86_64 does offer larger *addressable* bank, but out-of-order core +# reaches for even more registers through dynamic aliasing, and EM64T +# core must have managed to run-time optimize even 32-bit code just as +# good as 64-bit one. Performance improvement is summarized in the +# following table: +# +# gcc 3.4 32-bit asm cycles/byte +# Opteron +45% +20% 6.8 +# Xeon P4 +65% +0% 9.9 +# Core2 +60% +10% 7.0 + +# August 2009. +# +# The code was revised to minimize code size and to maximize +# "distance" between instructions producing input to 'lea' +# instruction and the 'lea' instruction itself, which is essential +# for Intel Atom core. + +# October 2010. +# +# Add SSSE3, Supplemental[!] SSE3, implementation. The idea behind it +# is to offload message schedule denoted by Wt in NIST specification, +# or Xupdate in OpenSSL source, to SIMD unit. See sha1-586.pl module +# for background and implementation details. The only difference from +# 32-bit code is that 64-bit code doesn't have to spill @X[] elements +# to free temporary registers. + +# April 2011. +# +# Add AVX code path. See sha1-586.pl for further information. + +# May 2013. +# +# Add AVX2+BMI code path. Initial attempt (utilizing BMI instructions +# and loading pair of consecutive blocks to 256-bit %ymm registers) +# did not provide impressive performance improvement till a crucial +# hint regarding the number of Xupdate iterations to pre-compute in +# advance was provided by Ilya Albrekht of Intel Corp. + +# March 2014. +# +# Add support for Intel SHA Extensions. + +###################################################################### +# Current performance is summarized in following table. Numbers are +# CPU clock cycles spent to process single byte (less is better). +# +# x86_64 SSSE3 AVX[2] +# P4 9.05 - +# Opteron 6.26 - +# Core2 6.55 6.05/+8% - +# Westmere 6.73 5.30/+27% - +# Sandy Bridge 7.70 6.10/+26% 4.99/+54% +# Ivy Bridge 6.06 4.67/+30% 4.60/+32% +# Haswell 5.45 4.15/+31% 3.57/+53% +# Bulldozer 9.11 5.95/+53% +# VIA Nano 9.32 7.15/+30% +# Atom 10.3 9.17/+12% +# Silvermont 13.1(*) 9.37/+40% +# +# (*) obviously suboptimal result, nothing was done about it, +# because SSSE3 code is compiled unconditionally; + +$flavour = shift; +$output = shift; +if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } + +$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or +die "can't locate x86_64-xlate.pl"; + +# In upstream, this is controlled by shelling out to the compiler to check +# versions, but BoringSSL is intended to be used with pre-generated perlasm +# output, so this isn't useful anyway. +# +# TODO(davidben): Enable AVX2 code after testing by setting $avx to 2. Is it +# necessary to disable AVX2 code when SHA Extensions code is disabled? Upstream +# did not tie them together until after $shaext was added. +$avx = 1; + +# TODO(davidben): Consider enabling the Intel SHA Extensions code once it's +# been tested. +$shaext=0; ### set to zero if compiling for 1.0.1 +$avx=1 if (!$shaext && $avx); + +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; + +$ctx="%rdi"; # 1st arg +$inp="%rsi"; # 2nd arg +$num="%rdx"; # 3rd arg + +# reassign arguments in order to produce more compact code +$ctx="%r8"; +$inp="%r9"; +$num="%r10"; + +$t0="%eax"; +$t1="%ebx"; +$t2="%ecx"; +@xi=("%edx","%ebp","%r14d"); +$A="%esi"; +$B="%edi"; +$C="%r11d"; +$D="%r12d"; +$E="%r13d"; + +@V=($A,$B,$C,$D,$E); + +sub BODY_00_19 { +my ($i,$a,$b,$c,$d,$e)=@_; +my $j=$i+1; +$code.=<<___ if ($i==0); + mov `4*$i`($inp),$xi[0] + bswap $xi[0] +___ +$code.=<<___ if ($i<15); + mov `4*$j`($inp),$xi[1] + mov $d,$t0 + mov $xi[0],`4*$i`(%rsp) + mov $a,$t2 + bswap $xi[1] + xor $c,$t0 + rol \$5,$t2 + and $b,$t0 + lea 0x5a827999($xi[0],$e),$e + add $t2,$e + xor $d,$t0 + rol \$30,$b + add $t0,$e +___ +$code.=<<___ if ($i>=15); + xor `4*($j%16)`(%rsp),$xi[1] + mov $d,$t0 + mov $xi[0],`4*($i%16)`(%rsp) + mov $a,$t2 + xor `4*(($j+2)%16)`(%rsp),$xi[1] + xor $c,$t0 + rol \$5,$t2 + xor `4*(($j+8)%16)`(%rsp),$xi[1] + and $b,$t0 + lea 0x5a827999($xi[0],$e),$e + rol \$30,$b + xor $d,$t0 + add $t2,$e + rol \$1,$xi[1] + add $t0,$e +___ +push(@xi,shift(@xi)); +} + +sub BODY_20_39 { +my ($i,$a,$b,$c,$d,$e)=@_; +my $j=$i+1; +my $K=($i<40)?0x6ed9eba1:0xca62c1d6; +$code.=<<___ if ($i<79); + xor `4*($j%16)`(%rsp),$xi[1] + mov $b,$t0 + `"mov $xi[0],".4*($i%16)."(%rsp)" if ($i<72)` + mov $a,$t2 + xor `4*(($j+2)%16)`(%rsp),$xi[1] + xor $d,$t0 + rol \$5,$t2 + xor `4*(($j+8)%16)`(%rsp),$xi[1] + lea $K($xi[0],$e),$e + xor $c,$t0 + add $t2,$e + rol \$30,$b + add $t0,$e + rol \$1,$xi[1] +___ +$code.=<<___ if ($i==79); + mov $b,$t0 + mov $a,$t2 + xor $d,$t0 + lea $K($xi[0],$e),$e + rol \$5,$t2 + xor $c,$t0 + add $t2,$e + rol \$30,$b + add $t0,$e +___ +push(@xi,shift(@xi)); +} + +sub BODY_40_59 { +my ($i,$a,$b,$c,$d,$e)=@_; +my $j=$i+1; +$code.=<<___; + xor `4*($j%16)`(%rsp),$xi[1] + mov $d,$t0 + mov $xi[0],`4*($i%16)`(%rsp) + mov $d,$t1 + xor `4*(($j+2)%16)`(%rsp),$xi[1] + and $c,$t0 + mov $a,$t2 + xor `4*(($j+8)%16)`(%rsp),$xi[1] + lea 0x8f1bbcdc($xi[0],$e),$e + xor $c,$t1 + rol \$5,$t2 + add $t0,$e + rol \$1,$xi[1] + and $b,$t1 + add $t2,$e + rol \$30,$b + add $t1,$e +___ +push(@xi,shift(@xi)); +} + +$code.=<<___; +.text +.extern OPENSSL_ia32cap_P + +.globl sha1_block_data_order +.type sha1_block_data_order,\@function,3 +.align 16 +sha1_block_data_order: + mov OPENSSL_ia32cap_P+0(%rip),%r9d + mov OPENSSL_ia32cap_P+4(%rip),%r8d + mov OPENSSL_ia32cap_P+8(%rip),%r10d + test \$`1<<9`,%r8d # check SSSE3 bit + jz .Lialu +___ +$code.=<<___ if ($shaext); + test \$`1<<29`,%r10d # check SHA bit + jnz _shaext_shortcut +___ +$code.=<<___ if ($avx>1); + and \$`1<<3|1<<5|1<<8`,%r10d # check AVX2+BMI1+BMI2 + cmp \$`1<<3|1<<5|1<<8`,%r10d + je _avx2_shortcut +___ +$code.=<<___ if ($avx); + and \$`1<<28`,%r8d # mask AVX bit + and \$`1<<30`,%r9d # mask "Intel CPU" bit + or %r9d,%r8d + cmp \$`1<<28|1<<30`,%r8d + je _avx_shortcut +___ +$code.=<<___; + jmp _ssse3_shortcut + +.align 16 +.Lialu: + mov %rsp,%rax + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + mov %rdi,$ctx # reassigned argument + sub \$`8+16*4`,%rsp + mov %rsi,$inp # reassigned argument + and \$-64,%rsp + mov %rdx,$num # reassigned argument + mov %rax,`16*4`(%rsp) +.Lprologue: + + mov 0($ctx),$A + mov 4($ctx),$B + mov 8($ctx),$C + mov 12($ctx),$D + mov 16($ctx),$E + jmp .Lloop + +.align 16 +.Lloop: +___ +for($i=0;$i<20;$i++) { &BODY_00_19($i,@V); unshift(@V,pop(@V)); } +for(;$i<40;$i++) { &BODY_20_39($i,@V); unshift(@V,pop(@V)); } +for(;$i<60;$i++) { &BODY_40_59($i,@V); unshift(@V,pop(@V)); } +for(;$i<80;$i++) { &BODY_20_39($i,@V); unshift(@V,pop(@V)); } +$code.=<<___; + add 0($ctx),$A + add 4($ctx),$B + add 8($ctx),$C + add 12($ctx),$D + add 16($ctx),$E + mov $A,0($ctx) + mov $B,4($ctx) + mov $C,8($ctx) + mov $D,12($ctx) + mov $E,16($ctx) + + sub \$1,$num + lea `16*4`($inp),$inp + jnz .Lloop + + mov `16*4`(%rsp),%rsi + mov -40(%rsi),%r14 + mov -32(%rsi),%r13 + mov -24(%rsi),%r12 + mov -16(%rsi),%rbp + mov -8(%rsi),%rbx + lea (%rsi),%rsp +.Lepilogue: + ret +.size sha1_block_data_order,.-sha1_block_data_order +___ +if ($shaext) {{{ +###################################################################### +# Intel SHA Extensions implementation of SHA1 update function. +# +my ($ctx,$inp,$num)=("%rdi","%rsi","%rdx"); +my ($ABCD,$E,$E_,$BSWAP,$ABCD_SAVE,$E_SAVE)=map("%xmm$_",(0..3,8,9)); +my @MSG=map("%xmm$_",(4..7)); + +$code.=<<___; +.type sha1_block_data_order_shaext,\@function,3 +.align 32 +sha1_block_data_order_shaext: +_shaext_shortcut: +___ +$code.=<<___ if ($win64); + lea `-8-4*16`(%rsp),%rsp + movaps %xmm6,-8-4*16(%rax) + movaps %xmm7,-8-3*16(%rax) + movaps %xmm8,-8-2*16(%rax) + movaps %xmm9,-8-1*16(%rax) +.Lprologue_shaext: +___ +$code.=<<___; + movdqu ($ctx),$ABCD + movd 16($ctx),$E + movdqa K_XX_XX+0xa0(%rip),$BSWAP # byte-n-word swap + + movdqu ($inp),@MSG[0] + pshufd \$0b00011011,$ABCD,$ABCD # flip word order + movdqu 0x10($inp),@MSG[1] + pshufd \$0b00011011,$E,$E # flip word order + movdqu 0x20($inp),@MSG[2] + pshufb $BSWAP,@MSG[0] + movdqu 0x30($inp),@MSG[3] + pshufb $BSWAP,@MSG[1] + pshufb $BSWAP,@MSG[2] + movdqa $E,$E_SAVE # offload $E + pshufb $BSWAP,@MSG[3] + jmp .Loop_shaext + +.align 16 +.Loop_shaext: + dec $num + lea 0x40($inp),%rax # next input block + paddd @MSG[0],$E + cmovne %rax,$inp + movdqa $ABCD,$ABCD_SAVE # offload $ABCD +___ +for($i=0;$i<20-4;$i+=2) { +$code.=<<___; + sha1msg1 @MSG[1],@MSG[0] + movdqa $ABCD,$E_ + sha1rnds4 \$`int($i/5)`,$E,$ABCD # 0-3... + sha1nexte @MSG[1],$E_ + pxor @MSG[2],@MSG[0] + sha1msg1 @MSG[2],@MSG[1] + sha1msg2 @MSG[3],@MSG[0] + + movdqa $ABCD,$E + sha1rnds4 \$`int(($i+1)/5)`,$E_,$ABCD + sha1nexte @MSG[2],$E + pxor @MSG[3],@MSG[1] + sha1msg2 @MSG[0],@MSG[1] +___ + push(@MSG,shift(@MSG)); push(@MSG,shift(@MSG)); +} +$code.=<<___; + movdqu ($inp),@MSG[0] + movdqa $ABCD,$E_ + sha1rnds4 \$3,$E,$ABCD # 64-67 + sha1nexte @MSG[1],$E_ + movdqu 0x10($inp),@MSG[1] + pshufb $BSWAP,@MSG[0] + + movdqa $ABCD,$E + sha1rnds4 \$3,$E_,$ABCD # 68-71 + sha1nexte @MSG[2],$E + movdqu 0x20($inp),@MSG[2] + pshufb $BSWAP,@MSG[1] + + movdqa $ABCD,$E_ + sha1rnds4 \$3,$E,$ABCD # 72-75 + sha1nexte @MSG[3],$E_ + movdqu 0x30($inp),@MSG[3] + pshufb $BSWAP,@MSG[2] + + movdqa $ABCD,$E + sha1rnds4 \$3,$E_,$ABCD # 76-79 + sha1nexte $E_SAVE,$E + pshufb $BSWAP,@MSG[3] + + paddd $ABCD_SAVE,$ABCD + movdqa $E,$E_SAVE # offload $E + + jnz .Loop_shaext + + pshufd \$0b00011011,$ABCD,$ABCD + pshufd \$0b00011011,$E,$E + movdqu $ABCD,($ctx) + movd $E,16($ctx) +___ +$code.=<<___ if ($win64); + movaps -8-4*16(%rax),%xmm6 + movaps -8-3*16(%rax),%xmm7 + movaps -8-2*16(%rax),%xmm8 + movaps -8-1*16(%rax),%xmm9 + mov %rax,%rsp +.Lepilogue_shaext: +___ +$code.=<<___; + ret +.size sha1_block_data_order_shaext,.-sha1_block_data_order_shaext +___ +}}} +{{{ +my $Xi=4; +my @X=map("%xmm$_",(4..7,0..3)); +my @Tx=map("%xmm$_",(8..10)); +my $Kx="%xmm11"; +my @V=($A,$B,$C,$D,$E)=("%eax","%ebx","%ecx","%edx","%ebp"); # size optimization +my @T=("%esi","%edi"); +my $j=0; +my $rx=0; +my $K_XX_XX="%r11"; + +my $_rol=sub { &rol(@_) }; +my $_ror=sub { &ror(@_) }; + +{ my $sn; +sub align32() { + ++$sn; +$code.=<<___; + jmp .Lalign32_$sn # see "Decoded ICache" in manual +.align 32 +.Lalign32_$sn: +___ +} +} + +$code.=<<___; +.type sha1_block_data_order_ssse3,\@function,3 +.align 16 +sha1_block_data_order_ssse3: +_ssse3_shortcut: + mov %rsp,%rax + push %rbx + push %rbp + push %r12 + push %r13 # redundant, done to share Win64 SE handler + push %r14 + lea `-64-($win64?6*16:0)`(%rsp),%rsp +___ +$code.=<<___ if ($win64); + movaps %xmm6,-40-6*16(%rax) + movaps %xmm7,-40-5*16(%rax) + movaps %xmm8,-40-4*16(%rax) + movaps %xmm9,-40-3*16(%rax) + movaps %xmm10,-40-2*16(%rax) + movaps %xmm11,-40-1*16(%rax) +.Lprologue_ssse3: +___ +$code.=<<___; + mov %rax,%r14 # original %rsp + and \$-64,%rsp + mov %rdi,$ctx # reassigned argument + mov %rsi,$inp # reassigned argument + mov %rdx,$num # reassigned argument + + shl \$6,$num + add $inp,$num + lea K_XX_XX+64(%rip),$K_XX_XX + + mov 0($ctx),$A # load context + mov 4($ctx),$B + mov 8($ctx),$C + mov 12($ctx),$D + mov $B,@T[0] # magic seed + mov 16($ctx),$E + mov $C,@T[1] + xor $D,@T[1] + and @T[1],@T[0] + + movdqa 64($K_XX_XX),@X[2] # pbswap mask + movdqa -64($K_XX_XX),@Tx[1] # K_00_19 + movdqu 0($inp),@X[-4&7] # load input to %xmm[0-3] + movdqu 16($inp),@X[-3&7] + movdqu 32($inp),@X[-2&7] + movdqu 48($inp),@X[-1&7] + pshufb @X[2],@X[-4&7] # byte swap + pshufb @X[2],@X[-3&7] + pshufb @X[2],@X[-2&7] + add \$64,$inp + paddd @Tx[1],@X[-4&7] # add K_00_19 + pshufb @X[2],@X[-1&7] + paddd @Tx[1],@X[-3&7] + paddd @Tx[1],@X[-2&7] + movdqa @X[-4&7],0(%rsp) # X[]+K xfer to IALU + psubd @Tx[1],@X[-4&7] # restore X[] + movdqa @X[-3&7],16(%rsp) + psubd @Tx[1],@X[-3&7] + movdqa @X[-2&7],32(%rsp) + psubd @Tx[1],@X[-2&7] + jmp .Loop_ssse3 +___ + +sub AUTOLOAD() # thunk [simplified] 32-bit style perlasm +{ my $opcode = $AUTOLOAD; $opcode =~ s/.*:://; + my $arg = pop; + $arg = "\$$arg" if ($arg*1 eq $arg); + $code .= "\t$opcode\t".join(',',$arg,reverse @_)."\n"; +} + +sub Xupdate_ssse3_16_31() # recall that $Xi starts wtih 4 +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); # 40 instructions + my ($a,$b,$c,$d,$e); + + eval(shift(@insns)); # ror + &pshufd (@X[0],@X[-4&7],0xee); # was &movdqa (@X[0],@X[-3&7]); + eval(shift(@insns)); + &movdqa (@Tx[0],@X[-1&7]); + &paddd (@Tx[1],@X[-1&7]); + eval(shift(@insns)); + eval(shift(@insns)); + + &punpcklqdq(@X[0],@X[-3&7]); # compose "X[-14]" in "X[0]", was &palignr(@X[0],@X[-4&7],8); + eval(shift(@insns)); + eval(shift(@insns)); # rol + eval(shift(@insns)); + &psrldq (@Tx[0],4); # "X[-3]", 3 dwords + eval(shift(@insns)); + eval(shift(@insns)); + + &pxor (@X[0],@X[-4&7]); # "X[0]"^="X[-16]" + eval(shift(@insns)); + eval(shift(@insns)); # ror + &pxor (@Tx[0],@X[-2&7]); # "X[-3]"^"X[-8]" + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &pxor (@X[0],@Tx[0]); # "X[0]"^="X[-3]"^"X[-8]" + eval(shift(@insns)); + eval(shift(@insns)); # rol + &movdqa (eval(16*(($Xi-1)&3))."(%rsp)",@Tx[1]); # X[]+K xfer to IALU + eval(shift(@insns)); + eval(shift(@insns)); + + &movdqa (@Tx[2],@X[0]); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # ror + &movdqa (@Tx[0],@X[0]); + eval(shift(@insns)); + + &pslldq (@Tx[2],12); # "X[0]"<<96, extract one dword + &paddd (@X[0],@X[0]); + eval(shift(@insns)); + eval(shift(@insns)); + + &psrld (@Tx[0],31); + eval(shift(@insns)); + eval(shift(@insns)); # rol + eval(shift(@insns)); + &movdqa (@Tx[1],@Tx[2]); + eval(shift(@insns)); + eval(shift(@insns)); + + &psrld (@Tx[2],30); + eval(shift(@insns)); + eval(shift(@insns)); # ror + &por (@X[0],@Tx[0]); # "X[0]"<<<=1 + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &pslld (@Tx[1],2); + &pxor (@X[0],@Tx[2]); + eval(shift(@insns)); + &movdqa (@Tx[2],eval(2*16*(($Xi)/5)-64)."($K_XX_XX)"); # K_XX_XX + eval(shift(@insns)); # rol + eval(shift(@insns)); + eval(shift(@insns)); + + &pxor (@X[0],@Tx[1]); # "X[0]"^=("X[0]">>96)<<<2 + &pshufd (@Tx[1],@X[-1&7],0xee) if ($Xi==7); # was &movdqa (@Tx[0],@X[-1&7]) in Xupdate_ssse3_32_79 + + foreach (@insns) { eval; } # remaining instructions [if any] + + $Xi++; push(@X,shift(@X)); # "rotate" X[] + push(@Tx,shift(@Tx)); +} + +sub Xupdate_ssse3_32_79() +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); # 32 to 44 instructions + my ($a,$b,$c,$d,$e); + + eval(shift(@insns)) if ($Xi==8); + &pxor (@X[0],@X[-4&7]); # "X[0]"="X[-32]"^"X[-16]" + eval(shift(@insns)) if ($Xi==8); + eval(shift(@insns)); # body_20_39 + eval(shift(@insns)); + eval(shift(@insns)) if (@insns[1] =~ /_ror/); + eval(shift(@insns)) if (@insns[0] =~ /_ror/); + &punpcklqdq(@Tx[0],@X[-1&7]); # compose "X[-6]", was &palignr(@Tx[0],@X[-2&7],8); + eval(shift(@insns)); + eval(shift(@insns)); # rol + + &pxor (@X[0],@X[-7&7]); # "X[0]"^="X[-28]" + eval(shift(@insns)); + eval(shift(@insns)); + if ($Xi%5) { + &movdqa (@Tx[2],@Tx[1]);# "perpetuate" K_XX_XX... + } else { # ... or load next one + &movdqa (@Tx[2],eval(2*16*($Xi/5)-64)."($K_XX_XX)"); + } + eval(shift(@insns)); # ror + &paddd (@Tx[1],@X[-1&7]); + eval(shift(@insns)); + + &pxor (@X[0],@Tx[0]); # "X[0]"^="X[-6]" + eval(shift(@insns)); # body_20_39 + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # rol + eval(shift(@insns)) if (@insns[0] =~ /_ror/); + + &movdqa (@Tx[0],@X[0]); + eval(shift(@insns)); + eval(shift(@insns)); + &movdqa (eval(16*(($Xi-1)&3))."(%rsp)",@Tx[1]); # X[]+K xfer to IALU + eval(shift(@insns)); # ror + eval(shift(@insns)); + eval(shift(@insns)); # body_20_39 + + &pslld (@X[0],2); + eval(shift(@insns)); + eval(shift(@insns)); + &psrld (@Tx[0],30); + eval(shift(@insns)) if (@insns[0] =~ /_rol/);# rol + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # ror + + &por (@X[0],@Tx[0]); # "X[0]"<<<=2 + eval(shift(@insns)); + eval(shift(@insns)); # body_20_39 + eval(shift(@insns)) if (@insns[1] =~ /_rol/); + eval(shift(@insns)) if (@insns[0] =~ /_rol/); + &pshufd(@Tx[1],@X[-1&7],0xee) if ($Xi<19); # was &movdqa (@Tx[1],@X[0]) + eval(shift(@insns)); + eval(shift(@insns)); # rol + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # rol + eval(shift(@insns)); + + foreach (@insns) { eval; } # remaining instructions + + $Xi++; push(@X,shift(@X)); # "rotate" X[] + push(@Tx,shift(@Tx)); +} + +sub Xuplast_ssse3_80() +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); # 32 instructions + my ($a,$b,$c,$d,$e); + + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &paddd (@Tx[1],@X[-1&7]); + eval(shift(@insns)); + eval(shift(@insns)); + + &movdqa (eval(16*(($Xi-1)&3))."(%rsp)",@Tx[1]); # X[]+K xfer IALU + + foreach (@insns) { eval; } # remaining instructions + + &cmp ($inp,$num); + &je (".Ldone_ssse3"); + + unshift(@Tx,pop(@Tx)); + + &movdqa (@X[2],"64($K_XX_XX)"); # pbswap mask + &movdqa (@Tx[1],"-64($K_XX_XX)"); # K_00_19 + &movdqu (@X[-4&7],"0($inp)"); # load input + &movdqu (@X[-3&7],"16($inp)"); + &movdqu (@X[-2&7],"32($inp)"); + &movdqu (@X[-1&7],"48($inp)"); + &pshufb (@X[-4&7],@X[2]); # byte swap + &add ($inp,64); + + $Xi=0; +} + +sub Xloop_ssse3() +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); # 32 instructions + my ($a,$b,$c,$d,$e); + + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &pshufb (@X[($Xi-3)&7],@X[2]); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &paddd (@X[($Xi-4)&7],@Tx[1]); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &movdqa (eval(16*$Xi)."(%rsp)",@X[($Xi-4)&7]); # X[]+K xfer to IALU + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &psubd (@X[($Xi-4)&7],@Tx[1]); + + foreach (@insns) { eval; } + $Xi++; +} + +sub Xtail_ssse3() +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); # 32 instructions + my ($a,$b,$c,$d,$e); + + foreach (@insns) { eval; } +} + +sub body_00_19 () { # ((c^d)&b)^d + # on start @T[0]=(c^d)&b + return &body_20_39() if ($rx==19); $rx++; + ( + '($a,$b,$c,$d,$e)=@V;'. + '&$_ror ($b,$j?7:2)', # $b>>>2 + '&xor (@T[0],$d)', + '&mov (@T[1],$a)', # $b for next round + + '&add ($e,eval(4*($j&15))."(%rsp)")', # X[]+K xfer + '&xor ($b,$c)', # $c^$d for next round + + '&$_rol ($a,5)', + '&add ($e,@T[0])', + '&and (@T[1],$b)', # ($b&($c^$d)) for next round + + '&xor ($b,$c)', # restore $b + '&add ($e,$a);' .'$j++; unshift(@V,pop(@V)); unshift(@T,pop(@T));' + ); +} + +sub body_20_39 () { # b^d^c + # on entry @T[0]=b^d + return &body_40_59() if ($rx==39); $rx++; + ( + '($a,$b,$c,$d,$e)=@V;'. + '&add ($e,eval(4*($j&15))."(%rsp)")', # X[]+K xfer + '&xor (@T[0],$d) if($j==19);'. + '&xor (@T[0],$c) if($j> 19)', # ($b^$d^$c) + '&mov (@T[1],$a)', # $b for next round + + '&$_rol ($a,5)', + '&add ($e,@T[0])', + '&xor (@T[1],$c) if ($j< 79)', # $b^$d for next round + + '&$_ror ($b,7)', # $b>>>2 + '&add ($e,$a);' .'$j++; unshift(@V,pop(@V)); unshift(@T,pop(@T));' + ); +} + +sub body_40_59 () { # ((b^c)&(c^d))^c + # on entry @T[0]=(b^c), (c^=d) + $rx++; + ( + '($a,$b,$c,$d,$e)=@V;'. + '&add ($e,eval(4*($j&15))."(%rsp)")', # X[]+K xfer + '&and (@T[0],$c) if ($j>=40)', # (b^c)&(c^d) + '&xor ($c,$d) if ($j>=40)', # restore $c + + '&$_ror ($b,7)', # $b>>>2 + '&mov (@T[1],$a)', # $b for next round + '&xor (@T[0],$c)', + + '&$_rol ($a,5)', + '&add ($e,@T[0])', + '&xor (@T[1],$c) if ($j==59);'. + '&xor (@T[1],$b) if ($j< 59)', # b^c for next round + + '&xor ($b,$c) if ($j< 59)', # c^d for next round + '&add ($e,$a);' .'$j++; unshift(@V,pop(@V)); unshift(@T,pop(@T));' + ); +} +$code.=<<___; +.align 16 +.Loop_ssse3: +___ + &Xupdate_ssse3_16_31(\&body_00_19); + &Xupdate_ssse3_16_31(\&body_00_19); + &Xupdate_ssse3_16_31(\&body_00_19); + &Xupdate_ssse3_16_31(\&body_00_19); + &Xupdate_ssse3_32_79(\&body_00_19); + &Xupdate_ssse3_32_79(\&body_20_39); + &Xupdate_ssse3_32_79(\&body_20_39); + &Xupdate_ssse3_32_79(\&body_20_39); + &Xupdate_ssse3_32_79(\&body_20_39); + &Xupdate_ssse3_32_79(\&body_20_39); + &Xupdate_ssse3_32_79(\&body_40_59); + &Xupdate_ssse3_32_79(\&body_40_59); + &Xupdate_ssse3_32_79(\&body_40_59); + &Xupdate_ssse3_32_79(\&body_40_59); + &Xupdate_ssse3_32_79(\&body_40_59); + &Xupdate_ssse3_32_79(\&body_20_39); + &Xuplast_ssse3_80(\&body_20_39); # can jump to "done" + + $saved_j=$j; @saved_V=@V; + + &Xloop_ssse3(\&body_20_39); + &Xloop_ssse3(\&body_20_39); + &Xloop_ssse3(\&body_20_39); + +$code.=<<___; + add 0($ctx),$A # update context + add 4($ctx),@T[0] + add 8($ctx),$C + add 12($ctx),$D + mov $A,0($ctx) + add 16($ctx),$E + mov @T[0],4($ctx) + mov @T[0],$B # magic seed + mov $C,8($ctx) + mov $C,@T[1] + mov $D,12($ctx) + xor $D,@T[1] + mov $E,16($ctx) + and @T[1],@T[0] + jmp .Loop_ssse3 + +.align 16 +.Ldone_ssse3: +___ + $j=$saved_j; @V=@saved_V; + + &Xtail_ssse3(\&body_20_39); + &Xtail_ssse3(\&body_20_39); + &Xtail_ssse3(\&body_20_39); + +$code.=<<___; + add 0($ctx),$A # update context + add 4($ctx),@T[0] + add 8($ctx),$C + mov $A,0($ctx) + add 12($ctx),$D + mov @T[0],4($ctx) + add 16($ctx),$E + mov $C,8($ctx) + mov $D,12($ctx) + mov $E,16($ctx) +___ +$code.=<<___ if ($win64); + movaps -40-6*16(%r14),%xmm6 + movaps -40-5*16(%r14),%xmm7 + movaps -40-4*16(%r14),%xmm8 + movaps -40-3*16(%r14),%xmm9 + movaps -40-2*16(%r14),%xmm10 + movaps -40-1*16(%r14),%xmm11 +___ +$code.=<<___; + lea (%r14),%rsi + mov -40(%rsi),%r14 + mov -32(%rsi),%r13 + mov -24(%rsi),%r12 + mov -16(%rsi),%rbp + mov -8(%rsi),%rbx + lea (%rsi),%rsp +.Lepilogue_ssse3: + ret +.size sha1_block_data_order_ssse3,.-sha1_block_data_order_ssse3 +___ + +if ($avx) { +$Xi=4; # reset variables +@X=map("%xmm$_",(4..7,0..3)); +@Tx=map("%xmm$_",(8..10)); +$j=0; +$rx=0; + +my $done_avx_label=".Ldone_avx"; + +my $_rol=sub { &shld(@_[0],@_) }; +my $_ror=sub { &shrd(@_[0],@_) }; + +$code.=<<___; +.type sha1_block_data_order_avx,\@function,3 +.align 16 +sha1_block_data_order_avx: +_avx_shortcut: + mov %rsp,%rax + push %rbx + push %rbp + push %r12 + push %r13 # redundant, done to share Win64 SE handler + push %r14 + lea `-64-($win64?6*16:0)`(%rsp),%rsp + vzeroupper +___ +$code.=<<___ if ($win64); + vmovaps %xmm6,-40-6*16(%rax) + vmovaps %xmm7,-40-5*16(%rax) + vmovaps %xmm8,-40-4*16(%rax) + vmovaps %xmm9,-40-3*16(%rax) + vmovaps %xmm10,-40-2*16(%rax) + vmovaps %xmm11,-40-1*16(%rax) +.Lprologue_avx: +___ +$code.=<<___; + mov %rax,%r14 # original %rsp + and \$-64,%rsp + mov %rdi,$ctx # reassigned argument + mov %rsi,$inp # reassigned argument + mov %rdx,$num # reassigned argument + + shl \$6,$num + add $inp,$num + lea K_XX_XX+64(%rip),$K_XX_XX + + mov 0($ctx),$A # load context + mov 4($ctx),$B + mov 8($ctx),$C + mov 12($ctx),$D + mov $B,@T[0] # magic seed + mov 16($ctx),$E + mov $C,@T[1] + xor $D,@T[1] + and @T[1],@T[0] + + vmovdqa 64($K_XX_XX),@X[2] # pbswap mask + vmovdqa -64($K_XX_XX),$Kx # K_00_19 + vmovdqu 0($inp),@X[-4&7] # load input to %xmm[0-3] + vmovdqu 16($inp),@X[-3&7] + vmovdqu 32($inp),@X[-2&7] + vmovdqu 48($inp),@X[-1&7] + vpshufb @X[2],@X[-4&7],@X[-4&7] # byte swap + add \$64,$inp + vpshufb @X[2],@X[-3&7],@X[-3&7] + vpshufb @X[2],@X[-2&7],@X[-2&7] + vpshufb @X[2],@X[-1&7],@X[-1&7] + vpaddd $Kx,@X[-4&7],@X[0] # add K_00_19 + vpaddd $Kx,@X[-3&7],@X[1] + vpaddd $Kx,@X[-2&7],@X[2] + vmovdqa @X[0],0(%rsp) # X[]+K xfer to IALU + vmovdqa @X[1],16(%rsp) + vmovdqa @X[2],32(%rsp) + jmp .Loop_avx +___ + +sub Xupdate_avx_16_31() # recall that $Xi starts wtih 4 +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); # 40 instructions + my ($a,$b,$c,$d,$e); + + eval(shift(@insns)); + eval(shift(@insns)); + &vpalignr(@X[0],@X[-3&7],@X[-4&7],8); # compose "X[-14]" in "X[0]" + eval(shift(@insns)); + eval(shift(@insns)); + + &vpaddd (@Tx[1],$Kx,@X[-1&7]); + eval(shift(@insns)); + eval(shift(@insns)); + &vpsrldq(@Tx[0],@X[-1&7],4); # "X[-3]", 3 dwords + eval(shift(@insns)); + eval(shift(@insns)); + &vpxor (@X[0],@X[0],@X[-4&7]); # "X[0]"^="X[-16]" + eval(shift(@insns)); + eval(shift(@insns)); + + &vpxor (@Tx[0],@Tx[0],@X[-2&7]); # "X[-3]"^"X[-8]" + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &vpxor (@X[0],@X[0],@Tx[0]); # "X[0]"^="X[-3]"^"X[-8]" + eval(shift(@insns)); + eval(shift(@insns)); + &vmovdqa (eval(16*(($Xi-1)&3))."(%rsp)",@Tx[1]); # X[]+K xfer to IALU + eval(shift(@insns)); + eval(shift(@insns)); + + &vpsrld (@Tx[0],@X[0],31); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &vpslldq(@Tx[2],@X[0],12); # "X[0]"<<96, extract one dword + &vpaddd (@X[0],@X[0],@X[0]); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &vpsrld (@Tx[1],@Tx[2],30); + &vpor (@X[0],@X[0],@Tx[0]); # "X[0]"<<<=1 + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &vpslld (@Tx[2],@Tx[2],2); + &vpxor (@X[0],@X[0],@Tx[1]); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &vpxor (@X[0],@X[0],@Tx[2]); # "X[0]"^=("X[0]">>96)<<<2 + eval(shift(@insns)); + eval(shift(@insns)); + &vmovdqa ($Kx,eval(2*16*(($Xi)/5)-64)."($K_XX_XX)") if ($Xi%5==0); # K_XX_XX + eval(shift(@insns)); + eval(shift(@insns)); + + + foreach (@insns) { eval; } # remaining instructions [if any] + + $Xi++; push(@X,shift(@X)); # "rotate" X[] +} + +sub Xupdate_avx_32_79() +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); # 32 to 44 instructions + my ($a,$b,$c,$d,$e); + + &vpalignr(@Tx[0],@X[-1&7],@X[-2&7],8); # compose "X[-6]" + &vpxor (@X[0],@X[0],@X[-4&7]); # "X[0]"="X[-32]"^"X[-16]" + eval(shift(@insns)); # body_20_39 + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # rol + + &vpxor (@X[0],@X[0],@X[-7&7]); # "X[0]"^="X[-28]" + eval(shift(@insns)); + eval(shift(@insns)) if (@insns[0] !~ /&ro[rl]/); + &vpaddd (@Tx[1],$Kx,@X[-1&7]); + &vmovdqa ($Kx,eval(2*16*($Xi/5)-64)."($K_XX_XX)") if ($Xi%5==0); + eval(shift(@insns)); # ror + eval(shift(@insns)); + + &vpxor (@X[0],@X[0],@Tx[0]); # "X[0]"^="X[-6]" + eval(shift(@insns)); # body_20_39 + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # rol + + &vpsrld (@Tx[0],@X[0],30); + &vmovdqa (eval(16*(($Xi-1)&3))."(%rsp)",@Tx[1]); # X[]+K xfer to IALU + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # ror + eval(shift(@insns)); + + &vpslld (@X[0],@X[0],2); + eval(shift(@insns)); # body_20_39 + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # rol + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # ror + eval(shift(@insns)); + + &vpor (@X[0],@X[0],@Tx[0]); # "X[0]"<<<=2 + eval(shift(@insns)); # body_20_39 + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # rol + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # rol + eval(shift(@insns)); + + foreach (@insns) { eval; } # remaining instructions + + $Xi++; push(@X,shift(@X)); # "rotate" X[] +} + +sub Xuplast_avx_80() +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); # 32 instructions + my ($a,$b,$c,$d,$e); + + eval(shift(@insns)); + &vpaddd (@Tx[1],$Kx,@X[-1&7]); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &vmovdqa (eval(16*(($Xi-1)&3))."(%rsp)",@Tx[1]); # X[]+K xfer IALU + + foreach (@insns) { eval; } # remaining instructions + + &cmp ($inp,$num); + &je ($done_avx_label); + + &vmovdqa(@X[2],"64($K_XX_XX)"); # pbswap mask + &vmovdqa($Kx,"-64($K_XX_XX)"); # K_00_19 + &vmovdqu(@X[-4&7],"0($inp)"); # load input + &vmovdqu(@X[-3&7],"16($inp)"); + &vmovdqu(@X[-2&7],"32($inp)"); + &vmovdqu(@X[-1&7],"48($inp)"); + &vpshufb(@X[-4&7],@X[-4&7],@X[2]); # byte swap + &add ($inp,64); + + $Xi=0; +} + +sub Xloop_avx() +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); # 32 instructions + my ($a,$b,$c,$d,$e); + + eval(shift(@insns)); + eval(shift(@insns)); + &vpshufb(@X[($Xi-3)&7],@X[($Xi-3)&7],@X[2]); + eval(shift(@insns)); + eval(shift(@insns)); + &vpaddd (@X[$Xi&7],@X[($Xi-4)&7],$Kx); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vmovdqa(eval(16*$Xi)."(%rsp)",@X[$Xi&7]); # X[]+K xfer to IALU + eval(shift(@insns)); + eval(shift(@insns)); + + foreach (@insns) { eval; } + $Xi++; +} + +sub Xtail_avx() +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); # 32 instructions + my ($a,$b,$c,$d,$e); + + foreach (@insns) { eval; } +} + +$code.=<<___; +.align 16 +.Loop_avx: +___ + &Xupdate_avx_16_31(\&body_00_19); + &Xupdate_avx_16_31(\&body_00_19); + &Xupdate_avx_16_31(\&body_00_19); + &Xupdate_avx_16_31(\&body_00_19); + &Xupdate_avx_32_79(\&body_00_19); + &Xupdate_avx_32_79(\&body_20_39); + &Xupdate_avx_32_79(\&body_20_39); + &Xupdate_avx_32_79(\&body_20_39); + &Xupdate_avx_32_79(\&body_20_39); + &Xupdate_avx_32_79(\&body_20_39); + &Xupdate_avx_32_79(\&body_40_59); + &Xupdate_avx_32_79(\&body_40_59); + &Xupdate_avx_32_79(\&body_40_59); + &Xupdate_avx_32_79(\&body_40_59); + &Xupdate_avx_32_79(\&body_40_59); + &Xupdate_avx_32_79(\&body_20_39); + &Xuplast_avx_80(\&body_20_39); # can jump to "done" + + $saved_j=$j; @saved_V=@V; + + &Xloop_avx(\&body_20_39); + &Xloop_avx(\&body_20_39); + &Xloop_avx(\&body_20_39); + +$code.=<<___; + add 0($ctx),$A # update context + add 4($ctx),@T[0] + add 8($ctx),$C + add 12($ctx),$D + mov $A,0($ctx) + add 16($ctx),$E + mov @T[0],4($ctx) + mov @T[0],$B # magic seed + mov $C,8($ctx) + mov $C,@T[1] + mov $D,12($ctx) + xor $D,@T[1] + mov $E,16($ctx) + and @T[1],@T[0] + jmp .Loop_avx + +.align 16 +$done_avx_label: +___ + $j=$saved_j; @V=@saved_V; + + &Xtail_avx(\&body_20_39); + &Xtail_avx(\&body_20_39); + &Xtail_avx(\&body_20_39); + +$code.=<<___; + vzeroupper + + add 0($ctx),$A # update context + add 4($ctx),@T[0] + add 8($ctx),$C + mov $A,0($ctx) + add 12($ctx),$D + mov @T[0],4($ctx) + add 16($ctx),$E + mov $C,8($ctx) + mov $D,12($ctx) + mov $E,16($ctx) +___ +$code.=<<___ if ($win64); + movaps -40-6*16(%r14),%xmm6 + movaps -40-5*16(%r14),%xmm7 + movaps -40-4*16(%r14),%xmm8 + movaps -40-3*16(%r14),%xmm9 + movaps -40-2*16(%r14),%xmm10 + movaps -40-1*16(%r14),%xmm11 +___ +$code.=<<___; + lea (%r14),%rsi + mov -40(%rsi),%r14 + mov -32(%rsi),%r13 + mov -24(%rsi),%r12 + mov -16(%rsi),%rbp + mov -8(%rsi),%rbx + lea (%rsi),%rsp +.Lepilogue_avx: + ret +.size sha1_block_data_order_avx,.-sha1_block_data_order_avx +___ + +if ($avx>1) { +use integer; +$Xi=4; # reset variables +@X=map("%ymm$_",(4..7,0..3)); +@Tx=map("%ymm$_",(8..10)); +$Kx="%ymm11"; +$j=0; + +my @ROTX=("%eax","%ebp","%ebx","%ecx","%edx","%esi"); +my ($a5,$t0)=("%r12d","%edi"); + +my ($A,$F,$B,$C,$D,$E)=@ROTX; +my $rx=0; +my $frame="%r13"; + +$code.=<<___; +.type sha1_block_data_order_avx2,\@function,3 +.align 16 +sha1_block_data_order_avx2: +_avx2_shortcut: + mov %rsp,%rax + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + vzeroupper +___ +$code.=<<___ if ($win64); + lea -6*16(%rsp),%rsp + vmovaps %xmm6,-40-6*16(%rax) + vmovaps %xmm7,-40-5*16(%rax) + vmovaps %xmm8,-40-4*16(%rax) + vmovaps %xmm9,-40-3*16(%rax) + vmovaps %xmm10,-40-2*16(%rax) + vmovaps %xmm11,-40-1*16(%rax) +.Lprologue_avx2: +___ +$code.=<<___; + mov %rax,%r14 # original %rsp + mov %rdi,$ctx # reassigned argument + mov %rsi,$inp # reassigned argument + mov %rdx,$num # reassigned argument + + lea -640(%rsp),%rsp + shl \$6,$num + lea 64($inp),$frame + and \$-128,%rsp + add $inp,$num + lea K_XX_XX+64(%rip),$K_XX_XX + + mov 0($ctx),$A # load context + cmp $num,$frame + cmovae $inp,$frame # next or same block + mov 4($ctx),$F + mov 8($ctx),$C + mov 12($ctx),$D + mov 16($ctx),$E + vmovdqu 64($K_XX_XX),@X[2] # pbswap mask + + vmovdqu ($inp),%xmm0 + vmovdqu 16($inp),%xmm1 + vmovdqu 32($inp),%xmm2 + vmovdqu 48($inp),%xmm3 + lea 64($inp),$inp + vinserti128 \$1,($frame),@X[-4&7],@X[-4&7] + vinserti128 \$1,16($frame),@X[-3&7],@X[-3&7] + vpshufb @X[2],@X[-4&7],@X[-4&7] + vinserti128 \$1,32($frame),@X[-2&7],@X[-2&7] + vpshufb @X[2],@X[-3&7],@X[-3&7] + vinserti128 \$1,48($frame),@X[-1&7],@X[-1&7] + vpshufb @X[2],@X[-2&7],@X[-2&7] + vmovdqu -64($K_XX_XX),$Kx # K_00_19 + vpshufb @X[2],@X[-1&7],@X[-1&7] + + vpaddd $Kx,@X[-4&7],@X[0] # add K_00_19 + vpaddd $Kx,@X[-3&7],@X[1] + vmovdqu @X[0],0(%rsp) # X[]+K xfer to IALU + vpaddd $Kx,@X[-2&7],@X[2] + vmovdqu @X[1],32(%rsp) + vpaddd $Kx,@X[-1&7],@X[3] + vmovdqu @X[2],64(%rsp) + vmovdqu @X[3],96(%rsp) +___ +for (;$Xi<8;$Xi++) { # Xupdate_avx2_16_31 + use integer; + + &vpalignr(@X[0],@X[-3&7],@X[-4&7],8); # compose "X[-14]" in "X[0]" + &vpsrldq(@Tx[0],@X[-1&7],4); # "X[-3]", 3 dwords + &vpxor (@X[0],@X[0],@X[-4&7]); # "X[0]"^="X[-16]" + &vpxor (@Tx[0],@Tx[0],@X[-2&7]); # "X[-3]"^"X[-8]" + &vpxor (@X[0],@X[0],@Tx[0]); # "X[0]"^="X[-3]"^"X[-8]" + &vpsrld (@Tx[0],@X[0],31); + &vmovdqu($Kx,eval(2*16*(($Xi)/5)-64)."($K_XX_XX)") if ($Xi%5==0); # K_XX_XX + &vpslldq(@Tx[2],@X[0],12); # "X[0]"<<96, extract one dword + &vpaddd (@X[0],@X[0],@X[0]); + &vpsrld (@Tx[1],@Tx[2],30); + &vpor (@X[0],@X[0],@Tx[0]); # "X[0]"<<<=1 + &vpslld (@Tx[2],@Tx[2],2); + &vpxor (@X[0],@X[0],@Tx[1]); + &vpxor (@X[0],@X[0],@Tx[2]); # "X[0]"^=("X[0]">>96)<<<2 + &vpaddd (@Tx[1],@X[0],$Kx); + &vmovdqu("32*$Xi(%rsp)",@Tx[1]); # X[]+K xfer to IALU + + push(@X,shift(@X)); # "rotate" X[] +} +$code.=<<___; + lea 128(%rsp),$frame + jmp .Loop_avx2 +.align 32 +.Loop_avx2: + rorx \$2,$F,$B + andn $D,$F,$t0 + and $C,$F + xor $t0,$F +___ +sub bodyx_00_19 () { # 8 instructions, 3 cycles critical path + # at start $f=(b&c)^(~b&d), $b>>>=2 + return &bodyx_20_39() if ($rx==19); $rx++; + ( + '($a,$f,$b,$c,$d,$e)=@ROTX;'. + + '&add ($e,((32*($j/4)+4*($j%4))%256-128)."($frame)");'. # e+=X[i]+K + '&lea ($frame,"256($frame)") if ($j%32==31);', + '&andn ($t0,$a,$c)', # ~b&d for next round + + '&add ($e,$f)', # e+=(b&c)^(~b&d) + '&rorx ($a5,$a,27)', # a<<<5 + '&rorx ($f,$a,2)', # b>>>2 for next round + '&and ($a,$b)', # b&c for next round + + '&add ($e,$a5)', # e+=a<<<5 + '&xor ($a,$t0);'. # f=(b&c)^(~b&d) for next round + + 'unshift(@ROTX,pop(@ROTX)); $j++;' + ) +} + +sub bodyx_20_39 () { # 7 instructions, 2 cycles critical path + # on entry $f=b^c^d, $b>>>=2 + return &bodyx_40_59() if ($rx==39); $rx++; + ( + '($a,$f,$b,$c,$d,$e)=@ROTX;'. + + '&add ($e,((32*($j/4)+4*($j%4))%256-128)."($frame)");'. # e+=X[i]+K + '&lea ($frame,"256($frame)") if ($j%32==31);', + + '&lea ($e,"($e,$f)")', # e+=b^c^d + '&rorx ($a5,$a,27)', # a<<<5 + '&rorx ($f,$a,2) if ($j<79)', # b>>>2 in next round + '&xor ($a,$b) if ($j<79)', # b^c for next round + + '&add ($e,$a5)', # e+=a<<<5 + '&xor ($a,$c) if ($j<79);'. # f=b^c^d for next round + + 'unshift(@ROTX,pop(@ROTX)); $j++;' + ) +} + +sub bodyx_40_59 () { # 10 instructions, 3 cycles critical path + # on entry $f=((b^c)&(c^d)), $b>>>=2 + $rx++; + ( + '($a,$f,$b,$c,$d,$e)=@ROTX;'. + + '&add ($e,((32*($j/4)+4*($j%4))%256-128)."($frame)");'. # e+=X[i]+K + '&lea ($frame,"256($frame)") if ($j%32==31);', + '&xor ($f,$c) if ($j>39)', # (b^c)&(c^d)^c + '&mov ($t0,$b) if ($j<59)', # count on zero latency + '&xor ($t0,$c) if ($j<59)', # c^d for next round + + '&lea ($e,"($e,$f)")', # e+=(b^c)&(c^d)^c + '&rorx ($a5,$a,27)', # a<<<5 + '&rorx ($f,$a,2)', # b>>>2 in next round + '&xor ($a,$b)', # b^c for next round + + '&add ($e,$a5)', # e+=a<<<5 + '&and ($a,$t0) if ($j< 59);'. # f=(b^c)&(c^d) for next round + '&xor ($a,$c) if ($j==59);'. # f=b^c^d for next round + + 'unshift(@ROTX,pop(@ROTX)); $j++;' + ) +} + +sub Xupdate_avx2_16_31() # recall that $Xi starts wtih 4 +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body,&$body); # 35 instructions + my ($a,$b,$c,$d,$e); + + &vpalignr(@X[0],@X[-3&7],@X[-4&7],8); # compose "X[-14]" in "X[0]" + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &vpsrldq(@Tx[0],@X[-1&7],4); # "X[-3]", 3 dwords + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &vpxor (@X[0],@X[0],@X[-4&7]); # "X[0]"^="X[-16]" + &vpxor (@Tx[0],@Tx[0],@X[-2&7]); # "X[-3]"^"X[-8]" + eval(shift(@insns)); + eval(shift(@insns)); + + &vpxor (@X[0],@X[0],@Tx[0]); # "X[0]"^="X[-3]"^"X[-8]" + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &vpsrld (@Tx[0],@X[0],31); + &vmovdqu($Kx,eval(2*16*(($Xi)/5)-64)."($K_XX_XX)") if ($Xi%5==0); # K_XX_XX + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &vpslldq(@Tx[2],@X[0],12); # "X[0]"<<96, extract one dword + &vpaddd (@X[0],@X[0],@X[0]); + eval(shift(@insns)); + eval(shift(@insns)); + + &vpsrld (@Tx[1],@Tx[2],30); + &vpor (@X[0],@X[0],@Tx[0]); # "X[0]"<<<=1 + eval(shift(@insns)); + eval(shift(@insns)); + + &vpslld (@Tx[2],@Tx[2],2); + &vpxor (@X[0],@X[0],@Tx[1]); + eval(shift(@insns)); + eval(shift(@insns)); + + &vpxor (@X[0],@X[0],@Tx[2]); # "X[0]"^=("X[0]">>96)<<<2 + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &vpaddd (@Tx[1],@X[0],$Kx); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vmovdqu(eval(32*($Xi))."(%rsp)",@Tx[1]); # X[]+K xfer to IALU + + foreach (@insns) { eval; } # remaining instructions [if any] + + $Xi++; + push(@X,shift(@X)); # "rotate" X[] +} + +sub Xupdate_avx2_32_79() +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body,&$body); # 35 to 50 instructions + my ($a,$b,$c,$d,$e); + + &vpalignr(@Tx[0],@X[-1&7],@X[-2&7],8); # compose "X[-6]" + &vpxor (@X[0],@X[0],@X[-4&7]); # "X[0]"="X[-32]"^"X[-16]" + eval(shift(@insns)); + eval(shift(@insns)); + + &vpxor (@X[0],@X[0],@X[-7&7]); # "X[0]"^="X[-28]" + &vmovdqu($Kx,eval(2*16*($Xi/5)-64)."($K_XX_XX)") if ($Xi%5==0); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &vpxor (@X[0],@X[0],@Tx[0]); # "X[0]"^="X[-6]" + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &vpsrld (@Tx[0],@X[0],30); + &vpslld (@X[0],@X[0],2); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + #&vpslld (@X[0],@X[0],2); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &vpor (@X[0],@X[0],@Tx[0]); # "X[0]"<<<=2 + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &vpaddd (@Tx[1],@X[0],$Kx); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &vmovdqu("32*$Xi(%rsp)",@Tx[1]); # X[]+K xfer to IALU + + foreach (@insns) { eval; } # remaining instructions + + $Xi++; + push(@X,shift(@X)); # "rotate" X[] +} + +sub Xloop_avx2() +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body,&$body); # 32 instructions + my ($a,$b,$c,$d,$e); + + foreach (@insns) { eval; } +} + + &align32(); + &Xupdate_avx2_32_79(\&bodyx_00_19); + &Xupdate_avx2_32_79(\&bodyx_00_19); + &Xupdate_avx2_32_79(\&bodyx_00_19); + &Xupdate_avx2_32_79(\&bodyx_00_19); + + &Xupdate_avx2_32_79(\&bodyx_20_39); + &Xupdate_avx2_32_79(\&bodyx_20_39); + &Xupdate_avx2_32_79(\&bodyx_20_39); + &Xupdate_avx2_32_79(\&bodyx_20_39); + + &align32(); + &Xupdate_avx2_32_79(\&bodyx_40_59); + &Xupdate_avx2_32_79(\&bodyx_40_59); + &Xupdate_avx2_32_79(\&bodyx_40_59); + &Xupdate_avx2_32_79(\&bodyx_40_59); + + &Xloop_avx2(\&bodyx_20_39); + &Xloop_avx2(\&bodyx_20_39); + &Xloop_avx2(\&bodyx_20_39); + &Xloop_avx2(\&bodyx_20_39); + +$code.=<<___; + lea 128($inp),$frame + lea 128($inp),%rdi # borrow $t0 + cmp $num,$frame + cmovae $inp,$frame # next or previous block + + # output is d-e-[a]-f-b-c => A=d,F=e,C=f,D=b,E=c + add 0($ctx),@ROTX[0] # update context + add 4($ctx),@ROTX[1] + add 8($ctx),@ROTX[3] + mov @ROTX[0],0($ctx) + add 12($ctx),@ROTX[4] + mov @ROTX[1],4($ctx) + mov @ROTX[0],$A # A=d + add 16($ctx),@ROTX[5] + mov @ROTX[3],$a5 + mov @ROTX[3],8($ctx) + mov @ROTX[4],$D # D=b + #xchg @ROTX[5],$F # F=c, C=f + mov @ROTX[4],12($ctx) + mov @ROTX[1],$F # F=e + mov @ROTX[5],16($ctx) + #mov $F,16($ctx) + mov @ROTX[5],$E # E=c + mov $a5,$C # C=f + #xchg $F,$E # E=c, F=e + + cmp $num,$inp + je .Ldone_avx2 +___ + +$Xi=4; # reset variables +@X=map("%ymm$_",(4..7,0..3)); + +$code.=<<___; + vmovdqu 64($K_XX_XX),@X[2] # pbswap mask + cmp $num,%rdi # borrowed $t0 + ja .Last_avx2 + + vmovdqu -64(%rdi),%xmm0 # low part of @X[-4&7] + vmovdqu -48(%rdi),%xmm1 + vmovdqu -32(%rdi),%xmm2 + vmovdqu -16(%rdi),%xmm3 + vinserti128 \$1,0($frame),@X[-4&7],@X[-4&7] + vinserti128 \$1,16($frame),@X[-3&7],@X[-3&7] + vinserti128 \$1,32($frame),@X[-2&7],@X[-2&7] + vinserti128 \$1,48($frame),@X[-1&7],@X[-1&7] + jmp .Last_avx2 + +.align 32 +.Last_avx2: + lea 128+16(%rsp),$frame + rorx \$2,$F,$B + andn $D,$F,$t0 + and $C,$F + xor $t0,$F + sub \$-128,$inp +___ + $rx=$j=0; @ROTX=($A,$F,$B,$C,$D,$E); + + &Xloop_avx2 (\&bodyx_00_19); + &Xloop_avx2 (\&bodyx_00_19); + &Xloop_avx2 (\&bodyx_00_19); + &Xloop_avx2 (\&bodyx_00_19); + + &Xloop_avx2 (\&bodyx_20_39); + &vmovdqu ($Kx,"-64($K_XX_XX)"); # K_00_19 + &vpshufb (@X[-4&7],@X[-4&7],@X[2]); # byte swap + &Xloop_avx2 (\&bodyx_20_39); + &vpshufb (@X[-3&7],@X[-3&7],@X[2]); + &vpaddd (@Tx[0],@X[-4&7],$Kx); # add K_00_19 + &Xloop_avx2 (\&bodyx_20_39); + &vmovdqu ("0(%rsp)",@Tx[0]); + &vpshufb (@X[-2&7],@X[-2&7],@X[2]); + &vpaddd (@Tx[1],@X[-3&7],$Kx); + &Xloop_avx2 (\&bodyx_20_39); + &vmovdqu ("32(%rsp)",@Tx[1]); + &vpshufb (@X[-1&7],@X[-1&7],@X[2]); + &vpaddd (@X[2],@X[-2&7],$Kx); + + &Xloop_avx2 (\&bodyx_40_59); + &align32 (); + &vmovdqu ("64(%rsp)",@X[2]); + &vpaddd (@X[3],@X[-1&7],$Kx); + &Xloop_avx2 (\&bodyx_40_59); + &vmovdqu ("96(%rsp)",@X[3]); + &Xloop_avx2 (\&bodyx_40_59); + &Xupdate_avx2_16_31(\&bodyx_40_59); + + &Xupdate_avx2_16_31(\&bodyx_20_39); + &Xupdate_avx2_16_31(\&bodyx_20_39); + &Xupdate_avx2_16_31(\&bodyx_20_39); + &Xloop_avx2 (\&bodyx_20_39); + +$code.=<<___; + lea 128(%rsp),$frame + + # output is d-e-[a]-f-b-c => A=d,F=e,C=f,D=b,E=c + add 0($ctx),@ROTX[0] # update context + add 4($ctx),@ROTX[1] + add 8($ctx),@ROTX[3] + mov @ROTX[0],0($ctx) + add 12($ctx),@ROTX[4] + mov @ROTX[1],4($ctx) + mov @ROTX[0],$A # A=d + add 16($ctx),@ROTX[5] + mov @ROTX[3],$a5 + mov @ROTX[3],8($ctx) + mov @ROTX[4],$D # D=b + #xchg @ROTX[5],$F # F=c, C=f + mov @ROTX[4],12($ctx) + mov @ROTX[1],$F # F=e + mov @ROTX[5],16($ctx) + #mov $F,16($ctx) + mov @ROTX[5],$E # E=c + mov $a5,$C # C=f + #xchg $F,$E # E=c, F=e + + cmp $num,$inp + jbe .Loop_avx2 + +.Ldone_avx2: + vzeroupper +___ +$code.=<<___ if ($win64); + movaps -40-6*16(%r14),%xmm6 + movaps -40-5*16(%r14),%xmm7 + movaps -40-4*16(%r14),%xmm8 + movaps -40-3*16(%r14),%xmm9 + movaps -40-2*16(%r14),%xmm10 + movaps -40-1*16(%r14),%xmm11 +___ +$code.=<<___; + lea (%r14),%rsi + mov -40(%rsi),%r14 + mov -32(%rsi),%r13 + mov -24(%rsi),%r12 + mov -16(%rsi),%rbp + mov -8(%rsi),%rbx + lea (%rsi),%rsp +.Lepilogue_avx2: + ret +.size sha1_block_data_order_avx2,.-sha1_block_data_order_avx2 +___ +} +} +$code.=<<___; +.align 64 +K_XX_XX: +.long 0x5a827999,0x5a827999,0x5a827999,0x5a827999 # K_00_19 +.long 0x5a827999,0x5a827999,0x5a827999,0x5a827999 # K_00_19 +.long 0x6ed9eba1,0x6ed9eba1,0x6ed9eba1,0x6ed9eba1 # K_20_39 +.long 0x6ed9eba1,0x6ed9eba1,0x6ed9eba1,0x6ed9eba1 # K_20_39 +.long 0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc # K_40_59 +.long 0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc # K_40_59 +.long 0xca62c1d6,0xca62c1d6,0xca62c1d6,0xca62c1d6 # K_60_79 +.long 0xca62c1d6,0xca62c1d6,0xca62c1d6,0xca62c1d6 # K_60_79 +.long 0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f # pbswap mask +.long 0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f # pbswap mask +.byte 0xf,0xe,0xd,0xc,0xb,0xa,0x9,0x8,0x7,0x6,0x5,0x4,0x3,0x2,0x1,0x0 +___ +}}} +$code.=<<___; +.asciz "SHA1 block transform for x86_64, CRYPTOGAMS by " +.align 64 +___ + +# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame, +# CONTEXT *context,DISPATCHER_CONTEXT *disp) +if ($win64) { +$rec="%rcx"; +$frame="%rdx"; +$context="%r8"; +$disp="%r9"; + +$code.=<<___; +.extern __imp_RtlVirtualUnwind +.type se_handler,\@abi-omnipotent +.align 16 +se_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + lea .Lprologue(%rip),%r10 + cmp %r10,%rbx # context->Rip<.Lprologue + jb .Lcommon_seh_tail + + mov 152($context),%rax # pull context->Rsp + + lea .Lepilogue(%rip),%r10 + cmp %r10,%rbx # context->Rip>=.Lepilogue + jae .Lcommon_seh_tail + + mov `16*4`(%rax),%rax # pull saved stack pointer + + mov -8(%rax),%rbx + mov -16(%rax),%rbp + mov -24(%rax),%r12 + mov -32(%rax),%r13 + mov -40(%rax),%r14 + mov %rbx,144($context) # restore context->Rbx + mov %rbp,160($context) # restore context->Rbp + mov %r12,216($context) # restore context->R12 + mov %r13,224($context) # restore context->R13 + mov %r14,232($context) # restore context->R14 + + jmp .Lcommon_seh_tail +.size se_handler,.-se_handler +___ + +$code.=<<___ if ($shaext); +.type shaext_handler,\@abi-omnipotent +.align 16 +shaext_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + lea .Lprologue_shaext(%rip),%r10 + cmp %r10,%rbx # context->Rip<.Lprologue + jb .Lcommon_seh_tail + + lea .Lepilogue_shaext(%rip),%r10 + cmp %r10,%rbx # context->Rip>=.Lepilogue + jae .Lcommon_seh_tail + + lea -8-4*16(%rax),%rsi + lea 512($context),%rdi # &context.Xmm6 + mov \$8,%ecx + .long 0xa548f3fc # cld; rep movsq + + jmp .Lcommon_seh_tail +.size shaext_handler,.-shaext_handler +___ + +$code.=<<___; +.type ssse3_handler,\@abi-omnipotent +.align 16 +ssse3_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + mov 8($disp),%rsi # disp->ImageBase + mov 56($disp),%r11 # disp->HandlerData + + mov 0(%r11),%r10d # HandlerData[0] + lea (%rsi,%r10),%r10 # prologue label + cmp %r10,%rbx # context->RipRsp + + mov 4(%r11),%r10d # HandlerData[1] + lea (%rsi,%r10),%r10 # epilogue label + cmp %r10,%rbx # context->Rip>=epilogue label + jae .Lcommon_seh_tail + + mov 232($context),%rax # pull context->R14 + + lea -40-6*16(%rax),%rsi + lea 512($context),%rdi # &context.Xmm6 + mov \$12,%ecx + .long 0xa548f3fc # cld; rep movsq + + mov -8(%rax),%rbx + mov -16(%rax),%rbp + mov -24(%rax),%r12 + mov -32(%rax),%r13 + mov -40(%rax),%r14 + mov %rbx,144($context) # restore context->Rbx + mov %rbp,160($context) # restore context->Rbp + mov %r12,216($context) # restore cotnext->R12 + mov %r13,224($context) # restore cotnext->R13 + mov %r14,232($context) # restore cotnext->R14 + +.Lcommon_seh_tail: + mov 8(%rax),%rdi + mov 16(%rax),%rsi + mov %rax,152($context) # restore context->Rsp + mov %rsi,168($context) # restore context->Rsi + mov %rdi,176($context) # restore context->Rdi + + mov 40($disp),%rdi # disp->ContextRecord + mov $context,%rsi # context + mov \$154,%ecx # sizeof(CONTEXT) + .long 0xa548f3fc # cld; rep movsq + + mov $disp,%rsi + xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER + mov 8(%rsi),%rdx # arg2, disp->ImageBase + mov 0(%rsi),%r8 # arg3, disp->ControlPc + mov 16(%rsi),%r9 # arg4, disp->FunctionEntry + mov 40(%rsi),%r10 # disp->ContextRecord + lea 56(%rsi),%r11 # &disp->HandlerData + lea 24(%rsi),%r12 # &disp->EstablisherFrame + mov %r10,32(%rsp) # arg5 + mov %r11,40(%rsp) # arg6 + mov %r12,48(%rsp) # arg7 + mov %rcx,56(%rsp) # arg8, (NULL) + call *__imp_RtlVirtualUnwind(%rip) + + mov \$1,%eax # ExceptionContinueSearch + add \$64,%rsp + popfq + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + pop %rdi + pop %rsi + ret +.size ssse3_handler,.-ssse3_handler + +.section .pdata +.align 4 + .rva .LSEH_begin_sha1_block_data_order + .rva .LSEH_end_sha1_block_data_order + .rva .LSEH_info_sha1_block_data_order +___ +$code.=<<___ if ($shaext); + .rva .LSEH_begin_sha1_block_data_order_shaext + .rva .LSEH_end_sha1_block_data_order_shaext + .rva .LSEH_info_sha1_block_data_order_shaext +___ +$code.=<<___; + .rva .LSEH_begin_sha1_block_data_order_ssse3 + .rva .LSEH_end_sha1_block_data_order_ssse3 + .rva .LSEH_info_sha1_block_data_order_ssse3 +___ +$code.=<<___ if ($avx); + .rva .LSEH_begin_sha1_block_data_order_avx + .rva .LSEH_end_sha1_block_data_order_avx + .rva .LSEH_info_sha1_block_data_order_avx +___ +$code.=<<___ if ($avx>1); + .rva .LSEH_begin_sha1_block_data_order_avx2 + .rva .LSEH_end_sha1_block_data_order_avx2 + .rva .LSEH_info_sha1_block_data_order_avx2 +___ +$code.=<<___; +.section .xdata +.align 8 +.LSEH_info_sha1_block_data_order: + .byte 9,0,0,0 + .rva se_handler +___ +$code.=<<___ if ($shaext); +.LSEH_info_sha1_block_data_order_shaext: + .byte 9,0,0,0 + .rva shaext_handler +___ +$code.=<<___; +.LSEH_info_sha1_block_data_order_ssse3: + .byte 9,0,0,0 + .rva ssse3_handler + .rva .Lprologue_ssse3,.Lepilogue_ssse3 # HandlerData[] +___ +$code.=<<___ if ($avx); +.LSEH_info_sha1_block_data_order_avx: + .byte 9,0,0,0 + .rva ssse3_handler + .rva .Lprologue_avx,.Lepilogue_avx # HandlerData[] +___ +$code.=<<___ if ($avx>1); +.LSEH_info_sha1_block_data_order_avx2: + .byte 9,0,0,0 + .rva ssse3_handler + .rva .Lprologue_avx2,.Lepilogue_avx2 # HandlerData[] +___ +} + +#################################################################### + +sub sha1rnds4 { + if (@_[0] =~ /\$([x0-9a-f]+),\s*%xmm([0-7]),\s*%xmm([0-7])/) { + my @opcode=(0x0f,0x3a,0xcc); + push @opcode,0xc0|($2&7)|(($3&7)<<3); # ModR/M + my $c=$1; + push @opcode,$c=~/^0/?oct($c):$c; + return ".byte\t".join(',',@opcode); + } else { + return "sha1rnds4\t".@_[0]; + } +} + +sub sha1op38 { + my $instr = shift; + my %opcodelet = ( + "sha1nexte" => 0xc8, + "sha1msg1" => 0xc9, + "sha1msg2" => 0xca ); + + if (defined($opcodelet{$instr}) && @_[0] =~ /%xmm([0-9]+),\s*%xmm([0-9]+)/) { + my @opcode=(0x0f,0x38); + my $rex=0; + $rex|=0x04 if ($2>=8); + $rex|=0x01 if ($1>=8); + unshift @opcode,0x40|$rex if ($rex); + push @opcode,$opcodelet{$instr}; + push @opcode,0xc0|($1&7)|(($2&7)<<3); # ModR/M + return ".byte\t".join(',',@opcode); + } else { + return $instr."\t".@_[0]; + } +} + +foreach (split("\n",$code)) { + s/\`([^\`]*)\`/eval $1/geo; + + s/\b(sha1rnds4)\s+(.*)/sha1rnds4($2)/geo or + s/\b(sha1[^\s]*)\s+(.*)/sha1op38($1,$2)/geo; + + print $_,"\n"; +} +close STDOUT; diff --git a/external/boringssl/crypto/sha/asm/sha256-586.pl b/external/boringssl/crypto/sha/asm/sha256-586.pl new file mode 100644 index 0000000000..fa8f264d3d --- /dev/null +++ b/external/boringssl/crypto/sha/asm/sha256-586.pl @@ -0,0 +1,1275 @@ +#!/usr/bin/env perl +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# SHA256 block transform for x86. September 2007. +# +# Performance improvement over compiler generated code varies from +# 10% to 40% [see below]. Not very impressive on some µ-archs, but +# it's 5 times smaller and optimizies amount of writes. +# +# May 2012. +# +# Optimization including two of Pavel Semjanov's ideas, alternative +# Maj and full unroll, resulted in ~20-25% improvement on most CPUs, +# ~7% on Pentium, ~40% on Atom. As fully unrolled loop body is almost +# 15x larger, 8KB vs. 560B, it's fired only for longer inputs. But not +# on P4, where it kills performance, nor Sandy Bridge, where folded +# loop is approximately as fast... +# +# June 2012. +# +# Add AMD XOP-specific code path, >30% improvement on Bulldozer over +# May version, >60% over original. Add AVX+shrd code path, >25% +# improvement on Sandy Bridge over May version, 60% over original. +# +# May 2013. +# +# Replace AMD XOP code path with SSSE3 to cover more processors. +# (Biggest improvement coefficient is on upcoming Atom Silvermont, +# not shown.) Add AVX+BMI code path. +# +# March 2014. +# +# Add support for Intel SHA Extensions. +# +# Performance in clock cycles per processed byte (less is better): +# +# gcc icc x86 asm(*) SIMD x86_64 asm(**) +# Pentium 46 57 40/38 - - +# PIII 36 33 27/24 - - +# P4 41 38 28 - 17.3 +# AMD K8 27 25 19/15.5 - 14.9 +# Core2 26 23 18/15.6 14.3 13.8 +# Westmere 27 - 19/15.7 13.4 12.3 +# Sandy Bridge 25 - 15.9 12.4 11.6 +# Ivy Bridge 24 - 15.0 11.4 10.3 +# Haswell 22 - 13.9 9.46 7.80 +# Bulldozer 36 - 27/22 17.0 13.6 +# VIA Nano 36 - 25/22 16.8 16.5 +# Atom 50 - 30/25 21.9 18.9 +# Silvermont 40 - 34/31 22.9 20.6 +# +# (*) numbers after slash are for unrolled loop, where applicable; +# (**) x86_64 assembly performance is presented for reference +# purposes, results are best-available; + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +push(@INC,"${dir}","${dir}../../perlasm"); +require "x86asm.pl"; + +&asm_init($ARGV[0],"sha512-586.pl",$ARGV[$#ARGV] eq "386"); + +$xmm=$avx=0; +for (@ARGV) { $xmm=1 if (/-DOPENSSL_IA32_SSE2/); } + +# In upstream, this is controlled by shelling out to the compiler to check +# versions, but BoringSSL is intended to be used with pre-generated perlasm +# output, so this isn't useful anyway. +# +# TODO(davidben): Enable AVX2 code after testing by setting $avx to 2. +$avx = 1; + +$avx = 0 unless ($xmm); + +$shaext=$xmm; ### set to zero if compiling for 1.0.1 + +# TODO(davidben): Consider enabling the Intel SHA Extensions code once it's +# been tested. +$shaext = 0; + +$unroll_after = 64*4; # If pre-evicted from L1P cache first spin of + # fully unrolled loop was measured to run about + # 3-4x slower. If slowdown coefficient is N and + # unrolled loop is m times faster, then you break + # even at (N-1)/(m-1) blocks. Then it needs to be + # adjusted for probability of code being evicted, + # code size/cache size=1/4. Typical m is 1.15... + +$A="eax"; +$E="edx"; +$T="ebx"; +$Aoff=&DWP(4,"esp"); +$Boff=&DWP(8,"esp"); +$Coff=&DWP(12,"esp"); +$Doff=&DWP(16,"esp"); +$Eoff=&DWP(20,"esp"); +$Foff=&DWP(24,"esp"); +$Goff=&DWP(28,"esp"); +$Hoff=&DWP(32,"esp"); +$Xoff=&DWP(36,"esp"); +$K256="ebp"; + +sub BODY_16_63() { + &mov ($T,"ecx"); # "ecx" is preloaded + &mov ("esi",&DWP(4*(9+15+16-14),"esp")); + &ror ("ecx",18-7); + &mov ("edi","esi"); + &ror ("esi",19-17); + &xor ("ecx",$T); + &shr ($T,3); + &ror ("ecx",7); + &xor ("esi","edi"); + &xor ($T,"ecx"); # T = sigma0(X[-15]) + &ror ("esi",17); + &add ($T,&DWP(4*(9+15+16),"esp")); # T += X[-16] + &shr ("edi",10); + &add ($T,&DWP(4*(9+15+16-9),"esp")); # T += X[-7] + #&xor ("edi","esi") # sigma1(X[-2]) + # &add ($T,"edi"); # T += sigma1(X[-2]) + # &mov (&DWP(4*(9+15),"esp"),$T); # save X[0] + + &BODY_00_15(1); +} +sub BODY_00_15() { + my $in_16_63=shift; + + &mov ("ecx",$E); + &xor ("edi","esi") if ($in_16_63); # sigma1(X[-2]) + &mov ("esi",$Foff); + &ror ("ecx",25-11); + &add ($T,"edi") if ($in_16_63); # T += sigma1(X[-2]) + &mov ("edi",$Goff); + &xor ("ecx",$E); + &xor ("esi","edi"); + &mov ($T,&DWP(4*(9+15),"esp")) if (!$in_16_63); + &mov (&DWP(4*(9+15),"esp"),$T) if ($in_16_63); # save X[0] + &ror ("ecx",11-6); + &and ("esi",$E); + &mov ($Eoff,$E); # modulo-scheduled + &xor ($E,"ecx"); + &add ($T,$Hoff); # T += h + &xor ("esi","edi"); # Ch(e,f,g) + &ror ($E,6); # Sigma1(e) + &mov ("ecx",$A); + &add ($T,"esi"); # T += Ch(e,f,g) + + &ror ("ecx",22-13); + &add ($T,$E); # T += Sigma1(e) + &mov ("edi",$Boff); + &xor ("ecx",$A); + &mov ($Aoff,$A); # modulo-scheduled + &lea ("esp",&DWP(-4,"esp")); + &ror ("ecx",13-2); + &mov ("esi",&DWP(0,$K256)); + &xor ("ecx",$A); + &mov ($E,$Eoff); # e in next iteration, d in this one + &xor ($A,"edi"); # a ^= b + &ror ("ecx",2); # Sigma0(a) + + &add ($T,"esi"); # T+= K[i] + &mov (&DWP(0,"esp"),$A); # (b^c) in next round + &add ($E,$T); # d += T + &and ($A,&DWP(4,"esp")); # a &= (b^c) + &add ($T,"ecx"); # T += Sigma0(a) + &xor ($A,"edi"); # h = Maj(a,b,c) = Ch(a^b,c,b) + &mov ("ecx",&DWP(4*(9+15+16-1),"esp")) if ($in_16_63); # preload T + &add ($K256,4); + &add ($A,$T); # h += T +} + +&external_label("OPENSSL_ia32cap_P") if (!$i386); + +&function_begin("sha256_block_data_order"); + &mov ("esi",wparam(0)); # ctx + &mov ("edi",wparam(1)); # inp + &mov ("eax",wparam(2)); # num + &mov ("ebx","esp"); # saved sp + + &call (&label("pic_point")); # make it PIC! +&set_label("pic_point"); + &blindpop($K256); + &lea ($K256,&DWP(&label("K256")."-".&label("pic_point"),$K256)); + + &sub ("esp",16); + &and ("esp",-64); + + &shl ("eax",6); + &add ("eax","edi"); + &mov (&DWP(0,"esp"),"esi"); # ctx + &mov (&DWP(4,"esp"),"edi"); # inp + &mov (&DWP(8,"esp"),"eax"); # inp+num*128 + &mov (&DWP(12,"esp"),"ebx"); # saved sp + if (!$i386 && $xmm) { + &picmeup("edx","OPENSSL_ia32cap_P",$K256,&label("K256")); + &mov ("ecx",&DWP(0,"edx")); + &mov ("ebx",&DWP(4,"edx")); + &test ("ecx",1<<20); # check for P4 + &jnz (&label("loop")); + &mov ("edx",&DWP(8,"edx")) if ($xmm); + &test ("ecx",1<<24); # check for FXSR + &jz ($unroll_after?&label("no_xmm"):&label("loop")); + &and ("ecx",1<<30); # mask "Intel CPU" bit + &and ("ebx",1<<28|1<<9); # mask AVX and SSSE3 bits + &test ("edx",1<<29) if ($shaext); # check for SHA + &jnz (&label("shaext")) if ($shaext); + &or ("ecx","ebx"); + &and ("ecx",1<<28|1<<30); + &cmp ("ecx",1<<28|1<<30); + if ($xmm) { + &je (&label("AVX")) if ($avx); + &test ("ebx",1<<9); # check for SSSE3 + &jnz (&label("SSSE3")); + } else { + &je (&label("loop_shrd")); + } + if ($unroll_after) { +&set_label("no_xmm"); + &sub ("eax","edi"); + &cmp ("eax",$unroll_after); + &jae (&label("unrolled")); + } } + &jmp (&label("loop")); + +sub COMPACT_LOOP() { +my $suffix=shift; + +&set_label("loop$suffix",$suffix?32:16); + # copy input block to stack reversing byte and dword order + for($i=0;$i<4;$i++) { + &mov ("eax",&DWP($i*16+0,"edi")); + &mov ("ebx",&DWP($i*16+4,"edi")); + &mov ("ecx",&DWP($i*16+8,"edi")); + &bswap ("eax"); + &mov ("edx",&DWP($i*16+12,"edi")); + &bswap ("ebx"); + &push ("eax"); + &bswap ("ecx"); + &push ("ebx"); + &bswap ("edx"); + &push ("ecx"); + &push ("edx"); + } + &add ("edi",64); + &lea ("esp",&DWP(-4*9,"esp"));# place for A,B,C,D,E,F,G,H + &mov (&DWP(4*(9+16)+4,"esp"),"edi"); + + # copy ctx->h[0-7] to A,B,C,D,E,F,G,H on stack + &mov ($A,&DWP(0,"esi")); + &mov ("ebx",&DWP(4,"esi")); + &mov ("ecx",&DWP(8,"esi")); + &mov ("edi",&DWP(12,"esi")); + # &mov ($Aoff,$A); + &mov ($Boff,"ebx"); + &xor ("ebx","ecx"); + &mov ($Coff,"ecx"); + &mov ($Doff,"edi"); + &mov (&DWP(0,"esp"),"ebx"); # magic + &mov ($E,&DWP(16,"esi")); + &mov ("ebx",&DWP(20,"esi")); + &mov ("ecx",&DWP(24,"esi")); + &mov ("edi",&DWP(28,"esi")); + # &mov ($Eoff,$E); + &mov ($Foff,"ebx"); + &mov ($Goff,"ecx"); + &mov ($Hoff,"edi"); + +&set_label("00_15$suffix",16); + + &BODY_00_15(); + + &cmp ("esi",0xc19bf174); + &jne (&label("00_15$suffix")); + + &mov ("ecx",&DWP(4*(9+15+16-1),"esp")); # preloaded in BODY_00_15(1) + &jmp (&label("16_63$suffix")); + +&set_label("16_63$suffix",16); + + &BODY_16_63(); + + &cmp ("esi",0xc67178f2); + &jne (&label("16_63$suffix")); + + &mov ("esi",&DWP(4*(9+16+64)+0,"esp"));#ctx + # &mov ($A,$Aoff); + &mov ("ebx",$Boff); + # &mov ("edi",$Coff); + &mov ("ecx",$Doff); + &add ($A,&DWP(0,"esi")); + &add ("ebx",&DWP(4,"esi")); + &add ("edi",&DWP(8,"esi")); + &add ("ecx",&DWP(12,"esi")); + &mov (&DWP(0,"esi"),$A); + &mov (&DWP(4,"esi"),"ebx"); + &mov (&DWP(8,"esi"),"edi"); + &mov (&DWP(12,"esi"),"ecx"); + # &mov ($E,$Eoff); + &mov ("eax",$Foff); + &mov ("ebx",$Goff); + &mov ("ecx",$Hoff); + &mov ("edi",&DWP(4*(9+16+64)+4,"esp"));#inp + &add ($E,&DWP(16,"esi")); + &add ("eax",&DWP(20,"esi")); + &add ("ebx",&DWP(24,"esi")); + &add ("ecx",&DWP(28,"esi")); + &mov (&DWP(16,"esi"),$E); + &mov (&DWP(20,"esi"),"eax"); + &mov (&DWP(24,"esi"),"ebx"); + &mov (&DWP(28,"esi"),"ecx"); + + &lea ("esp",&DWP(4*(9+16+64),"esp"));# destroy frame + &sub ($K256,4*64); # rewind K + + &cmp ("edi",&DWP(8,"esp")); # are we done yet? + &jb (&label("loop$suffix")); +} + &COMPACT_LOOP(); + &mov ("esp",&DWP(12,"esp")); # restore sp +&function_end_A(); + if (!$i386 && !$xmm) { + # ~20% improvement on Sandy Bridge + local *ror = sub { &shrd(@_[0],@_) }; + &COMPACT_LOOP("_shrd"); + &mov ("esp",&DWP(12,"esp")); # restore sp +&function_end_A(); + } + +&set_label("K256",64); # Yes! I keep it in the code segment! +@K256=( 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5, + 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5, + 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3, + 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174, + 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc, + 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da, + 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7, + 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967, + 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13, + 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85, + 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3, + 0xd192e819,0xd6990624,0xf40e3585,0x106aa070, + 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5, + 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3, + 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208, + 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 ); +&data_word(@K256); +&data_word(0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f); # byte swap mask +&asciz("SHA256 block transform for x86, CRYPTOGAMS by "); + +($a,$b,$c,$d,$e,$f,$g,$h)=(0..7); # offsets +sub off { &DWP(4*(((shift)-$i)&7),"esp"); } + +if (!$i386 && $unroll_after) { +my @AH=($A,$K256); + +&set_label("unrolled",16); + &lea ("esp",&DWP(-96,"esp")); + # copy ctx->h[0-7] to A,B,C,D,E,F,G,H on stack + &mov ($AH[0],&DWP(0,"esi")); + &mov ($AH[1],&DWP(4,"esi")); + &mov ("ecx",&DWP(8,"esi")); + &mov ("ebx",&DWP(12,"esi")); + #&mov (&DWP(0,"esp"),$AH[0]); + &mov (&DWP(4,"esp"),$AH[1]); + &xor ($AH[1],"ecx"); # magic + &mov (&DWP(8,"esp"),"ecx"); + &mov (&DWP(12,"esp"),"ebx"); + &mov ($E,&DWP(16,"esi")); + &mov ("ebx",&DWP(20,"esi")); + &mov ("ecx",&DWP(24,"esi")); + &mov ("esi",&DWP(28,"esi")); + #&mov (&DWP(16,"esp"),$E); + &mov (&DWP(20,"esp"),"ebx"); + &mov (&DWP(24,"esp"),"ecx"); + &mov (&DWP(28,"esp"),"esi"); + &jmp (&label("grand_loop")); + +&set_label("grand_loop",16); + # copy input block to stack reversing byte order + for($i=0;$i<5;$i++) { + &mov ("ebx",&DWP(12*$i+0,"edi")); + &mov ("ecx",&DWP(12*$i+4,"edi")); + &bswap ("ebx"); + &mov ("esi",&DWP(12*$i+8,"edi")); + &bswap ("ecx"); + &mov (&DWP(32+12*$i+0,"esp"),"ebx"); + &bswap ("esi"); + &mov (&DWP(32+12*$i+4,"esp"),"ecx"); + &mov (&DWP(32+12*$i+8,"esp"),"esi"); + } + &mov ("ebx",&DWP($i*12,"edi")); + &add ("edi",64); + &bswap ("ebx"); + &mov (&DWP(96+4,"esp"),"edi"); + &mov (&DWP(32+12*$i,"esp"),"ebx"); + + my ($t1,$t2) = ("ecx","esi"); + + for ($i=0;$i<64;$i++) { + + if ($i>=16) { + &mov ($T,$t1); # $t1 is preloaded + # &mov ($t2,&DWP(32+4*(($i+14)&15),"esp")); + &ror ($t1,18-7); + &mov ("edi",$t2); + &ror ($t2,19-17); + &xor ($t1,$T); + &shr ($T,3); + &ror ($t1,7); + &xor ($t2,"edi"); + &xor ($T,$t1); # T = sigma0(X[-15]) + &ror ($t2,17); + &add ($T,&DWP(32+4*($i&15),"esp")); # T += X[-16] + &shr ("edi",10); + &add ($T,&DWP(32+4*(($i+9)&15),"esp")); # T += X[-7] + #&xor ("edi",$t2) # sigma1(X[-2]) + # &add ($T,"edi"); # T += sigma1(X[-2]) + # &mov (&DWP(4*(9+15),"esp"),$T); # save X[0] + } + &mov ($t1,$E); + &xor ("edi",$t2) if ($i>=16); # sigma1(X[-2]) + &mov ($t2,&off($f)); + &ror ($E,25-11); + &add ($T,"edi") if ($i>=16); # T += sigma1(X[-2]) + &mov ("edi",&off($g)); + &xor ($E,$t1); + &mov ($T,&DWP(32+4*($i&15),"esp")) if ($i<16); # X[i] + &mov (&DWP(32+4*($i&15),"esp"),$T) if ($i>=16 && $i<62); # save X[0] + &xor ($t2,"edi"); + &ror ($E,11-6); + &and ($t2,$t1); + &mov (&off($e),$t1); # save $E, modulo-scheduled + &xor ($E,$t1); + &add ($T,&off($h)); # T += h + &xor ("edi",$t2); # Ch(e,f,g) + &ror ($E,6); # Sigma1(e) + &mov ($t1,$AH[0]); + &add ($T,"edi"); # T += Ch(e,f,g) + + &ror ($t1,22-13); + &mov ($t2,$AH[0]); + &mov ("edi",&off($b)); + &xor ($t1,$AH[0]); + &mov (&off($a),$AH[0]); # save $A, modulo-scheduled + &xor ($AH[0],"edi"); # a ^= b, (b^c) in next round + &ror ($t1,13-2); + &and ($AH[1],$AH[0]); # (b^c) &= (a^b) + &lea ($E,&DWP(@K256[$i],$T,$E)); # T += Sigma1(1)+K[i] + &xor ($t1,$t2); + &xor ($AH[1],"edi"); # h = Maj(a,b,c) = Ch(a^b,c,b) + &mov ($t2,&DWP(32+4*(($i+2)&15),"esp")) if ($i>=15 && $i<63); + &ror ($t1,2); # Sigma0(a) + + &add ($AH[1],$E); # h += T + &add ($E,&off($d)); # d += T + &add ($AH[1],$t1); # h += Sigma0(a) + &mov ($t1,&DWP(32+4*(($i+15)&15),"esp")) if ($i>=15 && $i<63); + + @AH = reverse(@AH); # rotate(a,h) + ($t1,$t2) = ($t2,$t1); # rotate(t1,t2) + } + &mov ("esi",&DWP(96,"esp")); #ctx + #&mov ($AH[0],&DWP(0,"esp")); + &xor ($AH[1],"edi"); #&mov ($AH[1],&DWP(4,"esp")); + #&mov ("edi", &DWP(8,"esp")); + &mov ("ecx",&DWP(12,"esp")); + &add ($AH[0],&DWP(0,"esi")); + &add ($AH[1],&DWP(4,"esi")); + &add ("edi",&DWP(8,"esi")); + &add ("ecx",&DWP(12,"esi")); + &mov (&DWP(0,"esi"),$AH[0]); + &mov (&DWP(4,"esi"),$AH[1]); + &mov (&DWP(8,"esi"),"edi"); + &mov (&DWP(12,"esi"),"ecx"); + #&mov (&DWP(0,"esp"),$AH[0]); + &mov (&DWP(4,"esp"),$AH[1]); + &xor ($AH[1],"edi"); # magic + &mov (&DWP(8,"esp"),"edi"); + &mov (&DWP(12,"esp"),"ecx"); + #&mov ($E,&DWP(16,"esp")); + &mov ("edi",&DWP(20,"esp")); + &mov ("ebx",&DWP(24,"esp")); + &mov ("ecx",&DWP(28,"esp")); + &add ($E,&DWP(16,"esi")); + &add ("edi",&DWP(20,"esi")); + &add ("ebx",&DWP(24,"esi")); + &add ("ecx",&DWP(28,"esi")); + &mov (&DWP(16,"esi"),$E); + &mov (&DWP(20,"esi"),"edi"); + &mov (&DWP(24,"esi"),"ebx"); + &mov (&DWP(28,"esi"),"ecx"); + #&mov (&DWP(16,"esp"),$E); + &mov (&DWP(20,"esp"),"edi"); + &mov ("edi",&DWP(96+4,"esp")); # inp + &mov (&DWP(24,"esp"),"ebx"); + &mov (&DWP(28,"esp"),"ecx"); + + &cmp ("edi",&DWP(96+8,"esp")); # are we done yet? + &jb (&label("grand_loop")); + + &mov ("esp",&DWP(96+12,"esp")); # restore sp +&function_end_A(); +} + if (!$i386 && $xmm) {{{ +if ($shaext) { +###################################################################### +# Intel SHA Extensions implementation of SHA256 update function. +# +my ($ctx,$inp,$end)=("esi","edi","eax"); +my ($Wi,$ABEF,$CDGH,$TMP)=map("xmm$_",(0..2,7)); +my @MSG=map("xmm$_",(3..6)); + +sub sha256op38 { + my ($opcodelet,$dst,$src)=@_; + if ("$dst:$src" =~ /xmm([0-7]):xmm([0-7])/) + { &data_byte(0x0f,0x38,$opcodelet,0xc0|($1<<3)|$2); } +} +sub sha256rnds2 { sha256op38(0xcb,@_); } +sub sha256msg1 { sha256op38(0xcc,@_); } +sub sha256msg2 { sha256op38(0xcd,@_); } + +&set_label("shaext",32); + &sub ("esp",32); + + &movdqu ($ABEF,&QWP(0,$ctx)); # DCBA + &lea ($K256,&DWP(0x80,$K256)); + &movdqu ($CDGH,&QWP(16,$ctx)); # HGFE + &movdqa ($TMP,&QWP(0x100-0x80,$K256)); # byte swap mask + + &pshufd ($Wi,$ABEF,0x1b); # ABCD + &pshufd ($ABEF,$ABEF,0xb1); # CDAB + &pshufd ($CDGH,$CDGH,0x1b); # EFGH + &palignr ($ABEF,$CDGH,8); # ABEF + &punpcklqdq ($CDGH,$Wi); # CDGH + &jmp (&label("loop_shaext")); + +&set_label("loop_shaext",16); + &movdqu (@MSG[0],&QWP(0,$inp)); + &movdqu (@MSG[1],&QWP(0x10,$inp)); + &movdqu (@MSG[2],&QWP(0x20,$inp)); + &pshufb (@MSG[0],$TMP); + &movdqu (@MSG[3],&QWP(0x30,$inp)); + &movdqa (&QWP(16,"esp"),$CDGH); # offload + + &movdqa ($Wi,&QWP(0*16-0x80,$K256)); + &paddd ($Wi,@MSG[0]); + &pshufb (@MSG[1],$TMP); + &sha256rnds2 ($CDGH,$ABEF); # 0-3 + &pshufd ($Wi,$Wi,0x0e); + &nop (); + &movdqa (&QWP(0,"esp"),$ABEF); # offload + &sha256rnds2 ($ABEF,$CDGH); + + &movdqa ($Wi,&QWP(1*16-0x80,$K256)); + &paddd ($Wi,@MSG[1]); + &pshufb (@MSG[2],$TMP); + &sha256rnds2 ($CDGH,$ABEF); # 4-7 + &pshufd ($Wi,$Wi,0x0e); + &lea ($inp,&DWP(0x40,$inp)); + &sha256msg1 (@MSG[0],@MSG[1]); + &sha256rnds2 ($ABEF,$CDGH); + + &movdqa ($Wi,&QWP(2*16-0x80,$K256)); + &paddd ($Wi,@MSG[2]); + &pshufb (@MSG[3],$TMP); + &sha256rnds2 ($CDGH,$ABEF); # 8-11 + &pshufd ($Wi,$Wi,0x0e); + &movdqa ($TMP,@MSG[3]); + &palignr ($TMP,@MSG[2],4); + &nop (); + &paddd (@MSG[0],$TMP); + &sha256msg1 (@MSG[1],@MSG[2]); + &sha256rnds2 ($ABEF,$CDGH); + + &movdqa ($Wi,&QWP(3*16-0x80,$K256)); + &paddd ($Wi,@MSG[3]); + &sha256msg2 (@MSG[0],@MSG[3]); + &sha256rnds2 ($CDGH,$ABEF); # 12-15 + &pshufd ($Wi,$Wi,0x0e); + &movdqa ($TMP,@MSG[0]); + &palignr ($TMP,@MSG[3],4); + &nop (); + &paddd (@MSG[1],$TMP); + &sha256msg1 (@MSG[2],@MSG[3]); + &sha256rnds2 ($ABEF,$CDGH); + +for($i=4;$i<16-3;$i++) { + &movdqa ($Wi,&QWP($i*16-0x80,$K256)); + &paddd ($Wi,@MSG[0]); + &sha256msg2 (@MSG[1],@MSG[0]); + &sha256rnds2 ($CDGH,$ABEF); # 16-19... + &pshufd ($Wi,$Wi,0x0e); + &movdqa ($TMP,@MSG[1]); + &palignr ($TMP,@MSG[0],4); + &nop (); + &paddd (@MSG[2],$TMP); + &sha256msg1 (@MSG[3],@MSG[0]); + &sha256rnds2 ($ABEF,$CDGH); + + push(@MSG,shift(@MSG)); +} + &movdqa ($Wi,&QWP(13*16-0x80,$K256)); + &paddd ($Wi,@MSG[0]); + &sha256msg2 (@MSG[1],@MSG[0]); + &sha256rnds2 ($CDGH,$ABEF); # 52-55 + &pshufd ($Wi,$Wi,0x0e); + &movdqa ($TMP,@MSG[1]) + &palignr ($TMP,@MSG[0],4); + &sha256rnds2 ($ABEF,$CDGH); + &paddd (@MSG[2],$TMP); + + &movdqa ($Wi,&QWP(14*16-0x80,$K256)); + &paddd ($Wi,@MSG[1]); + &sha256rnds2 ($CDGH,$ABEF); # 56-59 + &pshufd ($Wi,$Wi,0x0e); + &sha256msg2 (@MSG[2],@MSG[1]); + &movdqa ($TMP,&QWP(0x100-0x80,$K256)); # byte swap mask + &sha256rnds2 ($ABEF,$CDGH); + + &movdqa ($Wi,&QWP(15*16-0x80,$K256)); + &paddd ($Wi,@MSG[2]); + &nop (); + &sha256rnds2 ($CDGH,$ABEF); # 60-63 + &pshufd ($Wi,$Wi,0x0e); + &cmp ($end,$inp); + &nop (); + &sha256rnds2 ($ABEF,$CDGH); + + &paddd ($CDGH,&QWP(16,"esp")); + &paddd ($ABEF,&QWP(0,"esp")); + &jnz (&label("loop_shaext")); + + &pshufd ($CDGH,$CDGH,0xb1); # DCHG + &pshufd ($TMP,$ABEF,0x1b); # FEBA + &pshufd ($ABEF,$ABEF,0xb1); # BAFE + &punpckhqdq ($ABEF,$CDGH); # DCBA + &palignr ($CDGH,$TMP,8); # HGFE + + &mov ("esp",&DWP(32+12,"esp")); + &movdqu (&QWP(0,$ctx),$ABEF); + &movdqu (&QWP(16,$ctx),$CDGH); +&function_end_A(); +} + +my @X = map("xmm$_",(0..3)); +my ($t0,$t1,$t2,$t3) = map("xmm$_",(4..7)); +my @AH = ($A,$T); + +&set_label("SSSE3",32); + &lea ("esp",&DWP(-96,"esp")); + # copy ctx->h[0-7] to A,B,C,D,E,F,G,H on stack + &mov ($AH[0],&DWP(0,"esi")); + &mov ($AH[1],&DWP(4,"esi")); + &mov ("ecx",&DWP(8,"esi")); + &mov ("edi",&DWP(12,"esi")); + #&mov (&DWP(0,"esp"),$AH[0]); + &mov (&DWP(4,"esp"),$AH[1]); + &xor ($AH[1],"ecx"); # magic + &mov (&DWP(8,"esp"),"ecx"); + &mov (&DWP(12,"esp"),"edi"); + &mov ($E,&DWP(16,"esi")); + &mov ("edi",&DWP(20,"esi")); + &mov ("ecx",&DWP(24,"esi")); + &mov ("esi",&DWP(28,"esi")); + #&mov (&DWP(16,"esp"),$E); + &mov (&DWP(20,"esp"),"edi"); + &mov ("edi",&DWP(96+4,"esp")); # inp + &mov (&DWP(24,"esp"),"ecx"); + &mov (&DWP(28,"esp"),"esi"); + &movdqa ($t3,&QWP(256,$K256)); + &jmp (&label("grand_ssse3")); + +&set_label("grand_ssse3",16); + # load input, reverse byte order, add K256[0..15], save to stack + &movdqu (@X[0],&QWP(0,"edi")); + &movdqu (@X[1],&QWP(16,"edi")); + &movdqu (@X[2],&QWP(32,"edi")); + &movdqu (@X[3],&QWP(48,"edi")); + &add ("edi",64); + &pshufb (@X[0],$t3); + &mov (&DWP(96+4,"esp"),"edi"); + &pshufb (@X[1],$t3); + &movdqa ($t0,&QWP(0,$K256)); + &pshufb (@X[2],$t3); + &movdqa ($t1,&QWP(16,$K256)); + &paddd ($t0,@X[0]); + &pshufb (@X[3],$t3); + &movdqa ($t2,&QWP(32,$K256)); + &paddd ($t1,@X[1]); + &movdqa ($t3,&QWP(48,$K256)); + &movdqa (&QWP(32+0,"esp"),$t0); + &paddd ($t2,@X[2]); + &movdqa (&QWP(32+16,"esp"),$t1); + &paddd ($t3,@X[3]); + &movdqa (&QWP(32+32,"esp"),$t2); + &movdqa (&QWP(32+48,"esp"),$t3); + &jmp (&label("ssse3_00_47")); + +&set_label("ssse3_00_47",16); + &add ($K256,64); + +sub SSSE3_00_47 () { +my $j = shift; +my $body = shift; +my @X = @_; +my @insns = (&$body,&$body,&$body,&$body); # 120 instructions + + eval(shift(@insns)); + &movdqa ($t0,@X[1]); + eval(shift(@insns)); # @ + eval(shift(@insns)); + &movdqa ($t3,@X[3]); + eval(shift(@insns)); + eval(shift(@insns)); + &palignr ($t0,@X[0],4); # X[1..4] + eval(shift(@insns)); + eval(shift(@insns)); # @ + eval(shift(@insns)); + &palignr ($t3,@X[2],4); # X[9..12] + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &movdqa ($t1,$t0); + eval(shift(@insns)); # @ + eval(shift(@insns)); + &movdqa ($t2,$t0); + eval(shift(@insns)); + eval(shift(@insns)); + &psrld ($t0,3); + eval(shift(@insns)); + eval(shift(@insns)); # @ + &paddd (@X[0],$t3); # X[0..3] += X[9..12] + eval(shift(@insns)); + eval(shift(@insns)); + &psrld ($t2,7); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # @ + eval(shift(@insns)); + &pshufd ($t3,@X[3],0b11111010); # X[14..15] + eval(shift(@insns)); + eval(shift(@insns)); + &pslld ($t1,32-18); + eval(shift(@insns)); + eval(shift(@insns)); # @ + &pxor ($t0,$t2); + eval(shift(@insns)); + eval(shift(@insns)); + &psrld ($t2,18-7); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # @ + &pxor ($t0,$t1); + eval(shift(@insns)); + eval(shift(@insns)); + &pslld ($t1,18-7); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # @ + &pxor ($t0,$t2); + eval(shift(@insns)); + eval(shift(@insns)); + &movdqa ($t2,$t3); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # @ + &pxor ($t0,$t1); # sigma0(X[1..4]) + eval(shift(@insns)); + eval(shift(@insns)); + &psrld ($t3,10); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # @ + &paddd (@X[0],$t0); # X[0..3] += sigma0(X[1..4]) + eval(shift(@insns)); + eval(shift(@insns)); + &psrlq ($t2,17); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # @ + &pxor ($t3,$t2); + eval(shift(@insns)); + eval(shift(@insns)); + &psrlq ($t2,19-17); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # @ + &pxor ($t3,$t2); + eval(shift(@insns)); + eval(shift(@insns)); + &pshufd ($t3,$t3,0b10000000); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # @ + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # @ + eval(shift(@insns)); + &psrldq ($t3,8); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &paddd (@X[0],$t3); # X[0..1] += sigma1(X[14..15]) + eval(shift(@insns)); # @ + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # @ + eval(shift(@insns)); + &pshufd ($t3,@X[0],0b01010000); # X[16..17] + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &movdqa ($t2,$t3); + eval(shift(@insns)); # @ + &psrld ($t3,10); + eval(shift(@insns)); + &psrlq ($t2,17); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # @ + &pxor ($t3,$t2); + eval(shift(@insns)); + eval(shift(@insns)); + &psrlq ($t2,19-17); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # @ + &pxor ($t3,$t2); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &pshufd ($t3,$t3,0b00001000); + eval(shift(@insns)); + eval(shift(@insns)); # @ + &movdqa ($t2,&QWP(16*$j,$K256)); + eval(shift(@insns)); + eval(shift(@insns)); + &pslldq ($t3,8); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # @ + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # @ + &paddd (@X[0],$t3); # X[2..3] += sigma1(X[16..17]) + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &paddd ($t2,@X[0]); + eval(shift(@insns)); # @ + + foreach (@insns) { eval; } # remaining instructions + + &movdqa (&QWP(32+16*$j,"esp"),$t2); +} + +sub body_00_15 () { + ( + '&mov ("ecx",$E);', + '&ror ($E,25-11);', + '&mov ("esi",&off($f));', + '&xor ($E,"ecx");', + '&mov ("edi",&off($g));', + '&xor ("esi","edi");', + '&ror ($E,11-6);', + '&and ("esi","ecx");', + '&mov (&off($e),"ecx");', # save $E, modulo-scheduled + '&xor ($E,"ecx");', + '&xor ("edi","esi");', # Ch(e,f,g) + '&ror ($E,6);', # T = Sigma1(e) + '&mov ("ecx",$AH[0]);', + '&add ($E,"edi");', # T += Ch(e,f,g) + '&mov ("edi",&off($b));', + '&mov ("esi",$AH[0]);', + + '&ror ("ecx",22-13);', + '&mov (&off($a),$AH[0]);', # save $A, modulo-scheduled + '&xor ("ecx",$AH[0]);', + '&xor ($AH[0],"edi");', # a ^= b, (b^c) in next round + '&add ($E,&off($h));', # T += h + '&ror ("ecx",13-2);', + '&and ($AH[1],$AH[0]);', # (b^c) &= (a^b) + '&xor ("ecx","esi");', + '&add ($E,&DWP(32+4*($i&15),"esp"));', # T += K[i]+X[i] + '&xor ($AH[1],"edi");', # h = Maj(a,b,c) = Ch(a^b,c,b) + '&ror ("ecx",2);', # Sigma0(a) + + '&add ($AH[1],$E);', # h += T + '&add ($E,&off($d));', # d += T + '&add ($AH[1],"ecx");'. # h += Sigma0(a) + + '@AH = reverse(@AH); $i++;' # rotate(a,h) + ); +} + + for ($i=0,$j=0; $j<4; $j++) { + &SSSE3_00_47($j,\&body_00_15,@X); + push(@X,shift(@X)); # rotate(@X) + } + &cmp (&DWP(16*$j,$K256),0x00010203); + &jne (&label("ssse3_00_47")); + + for ($i=0; $i<16; ) { + foreach(body_00_15()) { eval; } + } + + &mov ("esi",&DWP(96,"esp")); #ctx + #&mov ($AH[0],&DWP(0,"esp")); + &xor ($AH[1],"edi"); #&mov ($AH[1],&DWP(4,"esp")); + #&mov ("edi", &DWP(8,"esp")); + &mov ("ecx",&DWP(12,"esp")); + &add ($AH[0],&DWP(0,"esi")); + &add ($AH[1],&DWP(4,"esi")); + &add ("edi",&DWP(8,"esi")); + &add ("ecx",&DWP(12,"esi")); + &mov (&DWP(0,"esi"),$AH[0]); + &mov (&DWP(4,"esi"),$AH[1]); + &mov (&DWP(8,"esi"),"edi"); + &mov (&DWP(12,"esi"),"ecx"); + #&mov (&DWP(0,"esp"),$AH[0]); + &mov (&DWP(4,"esp"),$AH[1]); + &xor ($AH[1],"edi"); # magic + &mov (&DWP(8,"esp"),"edi"); + &mov (&DWP(12,"esp"),"ecx"); + #&mov ($E,&DWP(16,"esp")); + &mov ("edi",&DWP(20,"esp")); + &mov ("ecx",&DWP(24,"esp")); + &add ($E,&DWP(16,"esi")); + &add ("edi",&DWP(20,"esi")); + &add ("ecx",&DWP(24,"esi")); + &mov (&DWP(16,"esi"),$E); + &mov (&DWP(20,"esi"),"edi"); + &mov (&DWP(20,"esp"),"edi"); + &mov ("edi",&DWP(28,"esp")); + &mov (&DWP(24,"esi"),"ecx"); + #&mov (&DWP(16,"esp"),$E); + &add ("edi",&DWP(28,"esi")); + &mov (&DWP(24,"esp"),"ecx"); + &mov (&DWP(28,"esi"),"edi"); + &mov (&DWP(28,"esp"),"edi"); + &mov ("edi",&DWP(96+4,"esp")); # inp + + &movdqa ($t3,&QWP(64,$K256)); + &sub ($K256,3*64); # rewind K + &cmp ("edi",&DWP(96+8,"esp")); # are we done yet? + &jb (&label("grand_ssse3")); + + &mov ("esp",&DWP(96+12,"esp")); # restore sp +&function_end_A(); + if ($avx) { +&set_label("AVX",32); + if ($avx>1) { + &and ("edx",1<<8|1<<3); # check for BMI2+BMI1 + &cmp ("edx",1<<8|1<<3); + &je (&label("AVX_BMI")); + } + &lea ("esp",&DWP(-96,"esp")); + &vzeroall (); + # copy ctx->h[0-7] to A,B,C,D,E,F,G,H on stack + &mov ($AH[0],&DWP(0,"esi")); + &mov ($AH[1],&DWP(4,"esi")); + &mov ("ecx",&DWP(8,"esi")); + &mov ("edi",&DWP(12,"esi")); + #&mov (&DWP(0,"esp"),$AH[0]); + &mov (&DWP(4,"esp"),$AH[1]); + &xor ($AH[1],"ecx"); # magic + &mov (&DWP(8,"esp"),"ecx"); + &mov (&DWP(12,"esp"),"edi"); + &mov ($E,&DWP(16,"esi")); + &mov ("edi",&DWP(20,"esi")); + &mov ("ecx",&DWP(24,"esi")); + &mov ("esi",&DWP(28,"esi")); + #&mov (&DWP(16,"esp"),$E); + &mov (&DWP(20,"esp"),"edi"); + &mov ("edi",&DWP(96+4,"esp")); # inp + &mov (&DWP(24,"esp"),"ecx"); + &mov (&DWP(28,"esp"),"esi"); + &vmovdqa ($t3,&QWP(256,$K256)); + &jmp (&label("grand_avx")); + +&set_label("grand_avx",32); + # load input, reverse byte order, add K256[0..15], save to stack + &vmovdqu (@X[0],&QWP(0,"edi")); + &vmovdqu (@X[1],&QWP(16,"edi")); + &vmovdqu (@X[2],&QWP(32,"edi")); + &vmovdqu (@X[3],&QWP(48,"edi")); + &add ("edi",64); + &vpshufb (@X[0],@X[0],$t3); + &mov (&DWP(96+4,"esp"),"edi"); + &vpshufb (@X[1],@X[1],$t3); + &vpshufb (@X[2],@X[2],$t3); + &vpaddd ($t0,@X[0],&QWP(0,$K256)); + &vpshufb (@X[3],@X[3],$t3); + &vpaddd ($t1,@X[1],&QWP(16,$K256)); + &vpaddd ($t2,@X[2],&QWP(32,$K256)); + &vpaddd ($t3,@X[3],&QWP(48,$K256)); + &vmovdqa (&QWP(32+0,"esp"),$t0); + &vmovdqa (&QWP(32+16,"esp"),$t1); + &vmovdqa (&QWP(32+32,"esp"),$t2); + &vmovdqa (&QWP(32+48,"esp"),$t3); + &jmp (&label("avx_00_47")); + +&set_label("avx_00_47",16); + &add ($K256,64); + +sub Xupdate_AVX () { + ( + '&vpalignr ($t0,@X[1],@X[0],4);', # X[1..4] + '&vpalignr ($t3,@X[3],@X[2],4);', # X[9..12] + '&vpsrld ($t2,$t0,7);', + '&vpaddd (@X[0],@X[0],$t3);', # X[0..3] += X[9..16] + '&vpsrld ($t3,$t0,3);', + '&vpslld ($t1,$t0,14);', + '&vpxor ($t0,$t3,$t2);', + '&vpshufd ($t3,@X[3],0b11111010)',# X[14..15] + '&vpsrld ($t2,$t2,18-7);', + '&vpxor ($t0,$t0,$t1);', + '&vpslld ($t1,$t1,25-14);', + '&vpxor ($t0,$t0,$t2);', + '&vpsrld ($t2,$t3,10);', + '&vpxor ($t0,$t0,$t1);', # sigma0(X[1..4]) + '&vpsrlq ($t1,$t3,17);', + '&vpaddd (@X[0],@X[0],$t0);', # X[0..3] += sigma0(X[1..4]) + '&vpxor ($t2,$t2,$t1);', + '&vpsrlq ($t3,$t3,19);', + '&vpxor ($t2,$t2,$t3);', # sigma1(X[14..15] + '&vpshufd ($t3,$t2,0b10000100);', + '&vpsrldq ($t3,$t3,8);', + '&vpaddd (@X[0],@X[0],$t3);', # X[0..1] += sigma1(X[14..15]) + '&vpshufd ($t3,@X[0],0b01010000)',# X[16..17] + '&vpsrld ($t2,$t3,10);', + '&vpsrlq ($t1,$t3,17);', + '&vpxor ($t2,$t2,$t1);', + '&vpsrlq ($t3,$t3,19);', + '&vpxor ($t2,$t2,$t3);', # sigma1(X[16..17] + '&vpshufd ($t3,$t2,0b11101000);', + '&vpslldq ($t3,$t3,8);', + '&vpaddd (@X[0],@X[0],$t3);' # X[2..3] += sigma1(X[16..17]) + ); +} + +local *ror = sub { &shrd(@_[0],@_) }; +sub AVX_00_47 () { +my $j = shift; +my $body = shift; +my @X = @_; +my @insns = (&$body,&$body,&$body,&$body); # 120 instructions +my $insn; + + foreach (Xupdate_AVX()) { # 31 instructions + eval; + eval(shift(@insns)); + eval(shift(@insns)); + eval($insn = shift(@insns)); + eval(shift(@insns)) if ($insn =~ /rorx/ && @insns[0] =~ /rorx/); + } + &vpaddd ($t2,@X[0],&QWP(16*$j,$K256)); + foreach (@insns) { eval; } # remaining instructions + &vmovdqa (&QWP(32+16*$j,"esp"),$t2); +} + + for ($i=0,$j=0; $j<4; $j++) { + &AVX_00_47($j,\&body_00_15,@X); + push(@X,shift(@X)); # rotate(@X) + } + &cmp (&DWP(16*$j,$K256),0x00010203); + &jne (&label("avx_00_47")); + + for ($i=0; $i<16; ) { + foreach(body_00_15()) { eval; } + } + + &mov ("esi",&DWP(96,"esp")); #ctx + #&mov ($AH[0],&DWP(0,"esp")); + &xor ($AH[1],"edi"); #&mov ($AH[1],&DWP(4,"esp")); + #&mov ("edi", &DWP(8,"esp")); + &mov ("ecx",&DWP(12,"esp")); + &add ($AH[0],&DWP(0,"esi")); + &add ($AH[1],&DWP(4,"esi")); + &add ("edi",&DWP(8,"esi")); + &add ("ecx",&DWP(12,"esi")); + &mov (&DWP(0,"esi"),$AH[0]); + &mov (&DWP(4,"esi"),$AH[1]); + &mov (&DWP(8,"esi"),"edi"); + &mov (&DWP(12,"esi"),"ecx"); + #&mov (&DWP(0,"esp"),$AH[0]); + &mov (&DWP(4,"esp"),$AH[1]); + &xor ($AH[1],"edi"); # magic + &mov (&DWP(8,"esp"),"edi"); + &mov (&DWP(12,"esp"),"ecx"); + #&mov ($E,&DWP(16,"esp")); + &mov ("edi",&DWP(20,"esp")); + &mov ("ecx",&DWP(24,"esp")); + &add ($E,&DWP(16,"esi")); + &add ("edi",&DWP(20,"esi")); + &add ("ecx",&DWP(24,"esi")); + &mov (&DWP(16,"esi"),$E); + &mov (&DWP(20,"esi"),"edi"); + &mov (&DWP(20,"esp"),"edi"); + &mov ("edi",&DWP(28,"esp")); + &mov (&DWP(24,"esi"),"ecx"); + #&mov (&DWP(16,"esp"),$E); + &add ("edi",&DWP(28,"esi")); + &mov (&DWP(24,"esp"),"ecx"); + &mov (&DWP(28,"esi"),"edi"); + &mov (&DWP(28,"esp"),"edi"); + &mov ("edi",&DWP(96+4,"esp")); # inp + + &vmovdqa ($t3,&QWP(64,$K256)); + &sub ($K256,3*64); # rewind K + &cmp ("edi",&DWP(96+8,"esp")); # are we done yet? + &jb (&label("grand_avx")); + + &mov ("esp",&DWP(96+12,"esp")); # restore sp + &vzeroall (); +&function_end_A(); + if ($avx>1) { +sub bodyx_00_15 () { # +10% + ( + '&rorx ("ecx",$E,6)', + '&rorx ("esi",$E,11)', + '&mov (&off($e),$E)', # save $E, modulo-scheduled + '&rorx ("edi",$E,25)', + '&xor ("ecx","esi")', + '&andn ("esi",$E,&off($g))', + '&xor ("ecx","edi")', # Sigma1(e) + '&and ($E,&off($f))', + '&mov (&off($a),$AH[0]);', # save $A, modulo-scheduled + '&or ($E,"esi")', # T = Ch(e,f,g) + + '&rorx ("edi",$AH[0],2)', + '&rorx ("esi",$AH[0],13)', + '&lea ($E,&DWP(0,$E,"ecx"))', # T += Sigma1(e) + '&rorx ("ecx",$AH[0],22)', + '&xor ("esi","edi")', + '&mov ("edi",&off($b))', + '&xor ("ecx","esi")', # Sigma0(a) + + '&xor ($AH[0],"edi")', # a ^= b, (b^c) in next round + '&add ($E,&off($h))', # T += h + '&and ($AH[1],$AH[0])', # (b^c) &= (a^b) + '&add ($E,&DWP(32+4*($i&15),"esp"))', # T += K[i]+X[i] + '&xor ($AH[1],"edi")', # h = Maj(a,b,c) = Ch(a^b,c,b) + + '&add ("ecx",$E)', # h += T + '&add ($E,&off($d))', # d += T + '&lea ($AH[1],&DWP(0,$AH[1],"ecx"));'. # h += Sigma0(a) + + '@AH = reverse(@AH); $i++;' # rotate(a,h) + ); +} + +&set_label("AVX_BMI",32); + &lea ("esp",&DWP(-96,"esp")); + &vzeroall (); + # copy ctx->h[0-7] to A,B,C,D,E,F,G,H on stack + &mov ($AH[0],&DWP(0,"esi")); + &mov ($AH[1],&DWP(4,"esi")); + &mov ("ecx",&DWP(8,"esi")); + &mov ("edi",&DWP(12,"esi")); + #&mov (&DWP(0,"esp"),$AH[0]); + &mov (&DWP(4,"esp"),$AH[1]); + &xor ($AH[1],"ecx"); # magic + &mov (&DWP(8,"esp"),"ecx"); + &mov (&DWP(12,"esp"),"edi"); + &mov ($E,&DWP(16,"esi")); + &mov ("edi",&DWP(20,"esi")); + &mov ("ecx",&DWP(24,"esi")); + &mov ("esi",&DWP(28,"esi")); + #&mov (&DWP(16,"esp"),$E); + &mov (&DWP(20,"esp"),"edi"); + &mov ("edi",&DWP(96+4,"esp")); # inp + &mov (&DWP(24,"esp"),"ecx"); + &mov (&DWP(28,"esp"),"esi"); + &vmovdqa ($t3,&QWP(256,$K256)); + &jmp (&label("grand_avx_bmi")); + +&set_label("grand_avx_bmi",32); + # load input, reverse byte order, add K256[0..15], save to stack + &vmovdqu (@X[0],&QWP(0,"edi")); + &vmovdqu (@X[1],&QWP(16,"edi")); + &vmovdqu (@X[2],&QWP(32,"edi")); + &vmovdqu (@X[3],&QWP(48,"edi")); + &add ("edi",64); + &vpshufb (@X[0],@X[0],$t3); + &mov (&DWP(96+4,"esp"),"edi"); + &vpshufb (@X[1],@X[1],$t3); + &vpshufb (@X[2],@X[2],$t3); + &vpaddd ($t0,@X[0],&QWP(0,$K256)); + &vpshufb (@X[3],@X[3],$t3); + &vpaddd ($t1,@X[1],&QWP(16,$K256)); + &vpaddd ($t2,@X[2],&QWP(32,$K256)); + &vpaddd ($t3,@X[3],&QWP(48,$K256)); + &vmovdqa (&QWP(32+0,"esp"),$t0); + &vmovdqa (&QWP(32+16,"esp"),$t1); + &vmovdqa (&QWP(32+32,"esp"),$t2); + &vmovdqa (&QWP(32+48,"esp"),$t3); + &jmp (&label("avx_bmi_00_47")); + +&set_label("avx_bmi_00_47",16); + &add ($K256,64); + + for ($i=0,$j=0; $j<4; $j++) { + &AVX_00_47($j,\&bodyx_00_15,@X); + push(@X,shift(@X)); # rotate(@X) + } + &cmp (&DWP(16*$j,$K256),0x00010203); + &jne (&label("avx_bmi_00_47")); + + for ($i=0; $i<16; ) { + foreach(bodyx_00_15()) { eval; } + } + + &mov ("esi",&DWP(96,"esp")); #ctx + #&mov ($AH[0],&DWP(0,"esp")); + &xor ($AH[1],"edi"); #&mov ($AH[1],&DWP(4,"esp")); + #&mov ("edi", &DWP(8,"esp")); + &mov ("ecx",&DWP(12,"esp")); + &add ($AH[0],&DWP(0,"esi")); + &add ($AH[1],&DWP(4,"esi")); + &add ("edi",&DWP(8,"esi")); + &add ("ecx",&DWP(12,"esi")); + &mov (&DWP(0,"esi"),$AH[0]); + &mov (&DWP(4,"esi"),$AH[1]); + &mov (&DWP(8,"esi"),"edi"); + &mov (&DWP(12,"esi"),"ecx"); + #&mov (&DWP(0,"esp"),$AH[0]); + &mov (&DWP(4,"esp"),$AH[1]); + &xor ($AH[1],"edi"); # magic + &mov (&DWP(8,"esp"),"edi"); + &mov (&DWP(12,"esp"),"ecx"); + #&mov ($E,&DWP(16,"esp")); + &mov ("edi",&DWP(20,"esp")); + &mov ("ecx",&DWP(24,"esp")); + &add ($E,&DWP(16,"esi")); + &add ("edi",&DWP(20,"esi")); + &add ("ecx",&DWP(24,"esi")); + &mov (&DWP(16,"esi"),$E); + &mov (&DWP(20,"esi"),"edi"); + &mov (&DWP(20,"esp"),"edi"); + &mov ("edi",&DWP(28,"esp")); + &mov (&DWP(24,"esi"),"ecx"); + #&mov (&DWP(16,"esp"),$E); + &add ("edi",&DWP(28,"esi")); + &mov (&DWP(24,"esp"),"ecx"); + &mov (&DWP(28,"esi"),"edi"); + &mov (&DWP(28,"esp"),"edi"); + &mov ("edi",&DWP(96+4,"esp")); # inp + + &vmovdqa ($t3,&QWP(64,$K256)); + &sub ($K256,3*64); # rewind K + &cmp ("edi",&DWP(96+8,"esp")); # are we done yet? + &jb (&label("grand_avx_bmi")); + + &mov ("esp",&DWP(96+12,"esp")); # restore sp + &vzeroall (); +&function_end_A(); + } + } + }}} +&function_end_B("sha256_block_data_order"); + +&asm_finish(); diff --git a/external/boringssl/crypto/sha/asm/sha256-armv4.pl b/external/boringssl/crypto/sha/asm/sha256-armv4.pl new file mode 100644 index 0000000000..7e071474e1 --- /dev/null +++ b/external/boringssl/crypto/sha/asm/sha256-armv4.pl @@ -0,0 +1,735 @@ +#!/usr/bin/env perl + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# +# Permission to use under GPL terms is granted. +# ==================================================================== + +# SHA256 block procedure for ARMv4. May 2007. + +# Performance is ~2x better than gcc 3.4 generated code and in "abso- +# lute" terms is ~2250 cycles per 64-byte block or ~35 cycles per +# byte [on single-issue Xscale PXA250 core]. + +# July 2010. +# +# Rescheduling for dual-issue pipeline resulted in 22% improvement on +# Cortex A8 core and ~20 cycles per processed byte. + +# February 2011. +# +# Profiler-assisted and platform-specific optimization resulted in 16% +# improvement on Cortex A8 core and ~15.4 cycles per processed byte. + +# September 2013. +# +# Add NEON implementation. On Cortex A8 it was measured to process one +# byte in 12.5 cycles or 23% faster than integer-only code. Snapdragon +# S4 does it in 12.5 cycles too, but it's 50% faster than integer-only +# code (meaning that latter performs sub-optimally, nothing was done +# about it). + +# May 2014. +# +# Add ARMv8 code path performing at 2.0 cpb on Apple A7. + +$flavour = shift; +if ($flavour=~/^\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; } +else { while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {} } + +if ($flavour && $flavour ne "void") { + $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; + ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or + ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or + die "can't locate arm-xlate.pl"; + + open STDOUT,"| \"$^X\" $xlate $flavour $output"; +} else { + open STDOUT,">$output"; +} + +$ctx="r0"; $t0="r0"; +$inp="r1"; $t4="r1"; +$len="r2"; $t1="r2"; +$T1="r3"; $t3="r3"; +$A="r4"; +$B="r5"; +$C="r6"; +$D="r7"; +$E="r8"; +$F="r9"; +$G="r10"; +$H="r11"; +@V=($A,$B,$C,$D,$E,$F,$G,$H); +$t2="r12"; +$Ktbl="r14"; + +@Sigma0=( 2,13,22); +@Sigma1=( 6,11,25); +@sigma0=( 7,18, 3); +@sigma1=(17,19,10); + +sub BODY_00_15 { +my ($i,$a,$b,$c,$d,$e,$f,$g,$h) = @_; + +$code.=<<___ if ($i<16); +#if __ARM_ARCH__>=7 + @ ldr $t1,[$inp],#4 @ $i +# if $i==15 + str $inp,[sp,#17*4] @ make room for $t4 +# endif + eor $t0,$e,$e,ror#`$Sigma1[1]-$Sigma1[0]` + add $a,$a,$t2 @ h+=Maj(a,b,c) from the past + eor $t0,$t0,$e,ror#`$Sigma1[2]-$Sigma1[0]` @ Sigma1(e) +# ifndef __ARMEB__ + rev $t1,$t1 +# endif +#else + @ ldrb $t1,[$inp,#3] @ $i + add $a,$a,$t2 @ h+=Maj(a,b,c) from the past + ldrb $t2,[$inp,#2] + ldrb $t0,[$inp,#1] + orr $t1,$t1,$t2,lsl#8 + ldrb $t2,[$inp],#4 + orr $t1,$t1,$t0,lsl#16 +# if $i==15 + str $inp,[sp,#17*4] @ make room for $t4 +# endif + eor $t0,$e,$e,ror#`$Sigma1[1]-$Sigma1[0]` + orr $t1,$t1,$t2,lsl#24 + eor $t0,$t0,$e,ror#`$Sigma1[2]-$Sigma1[0]` @ Sigma1(e) +#endif +___ +$code.=<<___; + ldr $t2,[$Ktbl],#4 @ *K256++ + add $h,$h,$t1 @ h+=X[i] + str $t1,[sp,#`$i%16`*4] + eor $t1,$f,$g + add $h,$h,$t0,ror#$Sigma1[0] @ h+=Sigma1(e) + and $t1,$t1,$e + add $h,$h,$t2 @ h+=K256[i] + eor $t1,$t1,$g @ Ch(e,f,g) + eor $t0,$a,$a,ror#`$Sigma0[1]-$Sigma0[0]` + add $h,$h,$t1 @ h+=Ch(e,f,g) +#if $i==31 + and $t2,$t2,#0xff + cmp $t2,#0xf2 @ done? +#endif +#if $i<15 +# if __ARM_ARCH__>=7 + ldr $t1,[$inp],#4 @ prefetch +# else + ldrb $t1,[$inp,#3] +# endif + eor $t2,$a,$b @ a^b, b^c in next round +#else + ldr $t1,[sp,#`($i+2)%16`*4] @ from future BODY_16_xx + eor $t2,$a,$b @ a^b, b^c in next round + ldr $t4,[sp,#`($i+15)%16`*4] @ from future BODY_16_xx +#endif + eor $t0,$t0,$a,ror#`$Sigma0[2]-$Sigma0[0]` @ Sigma0(a) + and $t3,$t3,$t2 @ (b^c)&=(a^b) + add $d,$d,$h @ d+=h + eor $t3,$t3,$b @ Maj(a,b,c) + add $h,$h,$t0,ror#$Sigma0[0] @ h+=Sigma0(a) + @ add $h,$h,$t3 @ h+=Maj(a,b,c) +___ + ($t2,$t3)=($t3,$t2); +} + +sub BODY_16_XX { +my ($i,$a,$b,$c,$d,$e,$f,$g,$h) = @_; + +$code.=<<___; + @ ldr $t1,[sp,#`($i+1)%16`*4] @ $i + @ ldr $t4,[sp,#`($i+14)%16`*4] + mov $t0,$t1,ror#$sigma0[0] + add $a,$a,$t2 @ h+=Maj(a,b,c) from the past + mov $t2,$t4,ror#$sigma1[0] + eor $t0,$t0,$t1,ror#$sigma0[1] + eor $t2,$t2,$t4,ror#$sigma1[1] + eor $t0,$t0,$t1,lsr#$sigma0[2] @ sigma0(X[i+1]) + ldr $t1,[sp,#`($i+0)%16`*4] + eor $t2,$t2,$t4,lsr#$sigma1[2] @ sigma1(X[i+14]) + ldr $t4,[sp,#`($i+9)%16`*4] + + add $t2,$t2,$t0 + eor $t0,$e,$e,ror#`$Sigma1[1]-$Sigma1[0]` @ from BODY_00_15 + add $t1,$t1,$t2 + eor $t0,$t0,$e,ror#`$Sigma1[2]-$Sigma1[0]` @ Sigma1(e) + add $t1,$t1,$t4 @ X[i] +___ + &BODY_00_15(@_); +} + +$code=<<___; +#ifndef __KERNEL__ +# include +#else +# define __ARM_ARCH__ __LINUX_ARM_ARCH__ +# define __ARM_MAX_ARCH__ 7 +#endif + +.text +#if __ARM_ARCH__<7 +.code 32 +#else +.syntax unified +# if defined(__thumb2__) && !defined(__APPLE__) +# define adrl adr +.thumb +# else +.code 32 +# endif +#endif + +.type K256,%object +.align 5 +K256: +.word 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5 +.word 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5 +.word 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3 +.word 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174 +.word 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc +.word 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da +.word 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7 +.word 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967 +.word 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13 +.word 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85 +.word 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3 +.word 0xd192e819,0xd6990624,0xf40e3585,0x106aa070 +.word 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5 +.word 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3 +.word 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208 +.word 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 +.size K256,.-K256 +.word 0 @ terminator +#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__) +.LOPENSSL_armcap: +.word OPENSSL_armcap_P-.Lsha256_block_data_order +#endif +.align 5 + +.global sha256_block_data_order +.type sha256_block_data_order,%function +sha256_block_data_order: +.Lsha256_block_data_order: +#if __ARM_ARCH__<7 + sub r3,pc,#8 @ sha256_block_data_order +#else + adr r3,sha256_block_data_order +#endif +#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__) + ldr r12,.LOPENSSL_armcap + ldr r12,[r3,r12] @ OPENSSL_armcap_P +#ifdef __APPLE__ + ldr r12,[r12] +#endif + tst r12,#ARMV8_SHA256 + bne .LARMv8 + tst r12,#ARMV7_NEON + bne .LNEON +#endif + add $len,$inp,$len,lsl#6 @ len to point at the end of inp + stmdb sp!,{$ctx,$inp,$len,r4-r11,lr} + ldmia $ctx,{$A,$B,$C,$D,$E,$F,$G,$H} + sub $Ktbl,r3,#256+32 @ K256 + sub sp,sp,#16*4 @ alloca(X[16]) +.Loop: +# if __ARM_ARCH__>=7 + ldr $t1,[$inp],#4 +# else + ldrb $t1,[$inp,#3] +# endif + eor $t3,$B,$C @ magic + eor $t2,$t2,$t2 +___ +for($i=0;$i<16;$i++) { &BODY_00_15($i,@V); unshift(@V,pop(@V)); } +$code.=".Lrounds_16_xx:\n"; +for (;$i<32;$i++) { &BODY_16_XX($i,@V); unshift(@V,pop(@V)); } +$code.=<<___; +#if __ARM_ARCH__>=7 + ite eq @ Thumb2 thing, sanity check in ARM +#endif + ldreq $t3,[sp,#16*4] @ pull ctx + bne .Lrounds_16_xx + + add $A,$A,$t2 @ h+=Maj(a,b,c) from the past + ldr $t0,[$t3,#0] + ldr $t1,[$t3,#4] + ldr $t2,[$t3,#8] + add $A,$A,$t0 + ldr $t0,[$t3,#12] + add $B,$B,$t1 + ldr $t1,[$t3,#16] + add $C,$C,$t2 + ldr $t2,[$t3,#20] + add $D,$D,$t0 + ldr $t0,[$t3,#24] + add $E,$E,$t1 + ldr $t1,[$t3,#28] + add $F,$F,$t2 + ldr $inp,[sp,#17*4] @ pull inp + ldr $t2,[sp,#18*4] @ pull inp+len + add $G,$G,$t0 + add $H,$H,$t1 + stmia $t3,{$A,$B,$C,$D,$E,$F,$G,$H} + cmp $inp,$t2 + sub $Ktbl,$Ktbl,#256 @ rewind Ktbl + bne .Loop + + add sp,sp,#`16+3`*4 @ destroy frame +#if __ARM_ARCH__>=5 + ldmia sp!,{r4-r11,pc} +#else + ldmia sp!,{r4-r11,lr} + tst lr,#1 + moveq pc,lr @ be binary compatible with V4, yet + bx lr @ interoperable with Thumb ISA:-) +#endif +.size sha256_block_data_order,.-sha256_block_data_order +___ +###################################################################### +# NEON stuff +# +{{{ +my @X=map("q$_",(0..3)); +my ($T0,$T1,$T2,$T3,$T4,$T5)=("q8","q9","q10","q11","d24","d25"); +my $Xfer=$t4; +my $j=0; + +sub Dlo() { shift=~m|q([1]?[0-9])|?"d".($1*2):""; } +sub Dhi() { shift=~m|q([1]?[0-9])|?"d".($1*2+1):""; } + +sub AUTOLOAD() # thunk [simplified] x86-style perlasm +{ my $opcode = $AUTOLOAD; $opcode =~ s/.*:://; $opcode =~ s/_/\./; + my $arg = pop; + $arg = "#$arg" if ($arg*1 eq $arg); + $code .= "\t$opcode\t".join(',',@_,$arg)."\n"; +} + +sub Xupdate() +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); + my ($a,$b,$c,$d,$e,$f,$g,$h); + + &vext_8 ($T0,@X[0],@X[1],4); # X[1..4] + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vext_8 ($T1,@X[2],@X[3],4); # X[9..12] + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vshr_u32 ($T2,$T0,$sigma0[0]); + eval(shift(@insns)); + eval(shift(@insns)); + &vadd_i32 (@X[0],@X[0],$T1); # X[0..3] += X[9..12] + eval(shift(@insns)); + eval(shift(@insns)); + &vshr_u32 ($T1,$T0,$sigma0[2]); + eval(shift(@insns)); + eval(shift(@insns)); + &vsli_32 ($T2,$T0,32-$sigma0[0]); + eval(shift(@insns)); + eval(shift(@insns)); + &vshr_u32 ($T3,$T0,$sigma0[1]); + eval(shift(@insns)); + eval(shift(@insns)); + &veor ($T1,$T1,$T2); + eval(shift(@insns)); + eval(shift(@insns)); + &vsli_32 ($T3,$T0,32-$sigma0[1]); + eval(shift(@insns)); + eval(shift(@insns)); + &vshr_u32 ($T4,&Dhi(@X[3]),$sigma1[0]); + eval(shift(@insns)); + eval(shift(@insns)); + &veor ($T1,$T1,$T3); # sigma0(X[1..4]) + eval(shift(@insns)); + eval(shift(@insns)); + &vsli_32 ($T4,&Dhi(@X[3]),32-$sigma1[0]); + eval(shift(@insns)); + eval(shift(@insns)); + &vshr_u32 ($T5,&Dhi(@X[3]),$sigma1[2]); + eval(shift(@insns)); + eval(shift(@insns)); + &vadd_i32 (@X[0],@X[0],$T1); # X[0..3] += sigma0(X[1..4]) + eval(shift(@insns)); + eval(shift(@insns)); + &veor ($T5,$T5,$T4); + eval(shift(@insns)); + eval(shift(@insns)); + &vshr_u32 ($T4,&Dhi(@X[3]),$sigma1[1]); + eval(shift(@insns)); + eval(shift(@insns)); + &vsli_32 ($T4,&Dhi(@X[3]),32-$sigma1[1]); + eval(shift(@insns)); + eval(shift(@insns)); + &veor ($T5,$T5,$T4); # sigma1(X[14..15]) + eval(shift(@insns)); + eval(shift(@insns)); + &vadd_i32 (&Dlo(@X[0]),&Dlo(@X[0]),$T5);# X[0..1] += sigma1(X[14..15]) + eval(shift(@insns)); + eval(shift(@insns)); + &vshr_u32 ($T4,&Dlo(@X[0]),$sigma1[0]); + eval(shift(@insns)); + eval(shift(@insns)); + &vsli_32 ($T4,&Dlo(@X[0]),32-$sigma1[0]); + eval(shift(@insns)); + eval(shift(@insns)); + &vshr_u32 ($T5,&Dlo(@X[0]),$sigma1[2]); + eval(shift(@insns)); + eval(shift(@insns)); + &veor ($T5,$T5,$T4); + eval(shift(@insns)); + eval(shift(@insns)); + &vshr_u32 ($T4,&Dlo(@X[0]),$sigma1[1]); + eval(shift(@insns)); + eval(shift(@insns)); + &vld1_32 ("{$T0}","[$Ktbl,:128]!"); + eval(shift(@insns)); + eval(shift(@insns)); + &vsli_32 ($T4,&Dlo(@X[0]),32-$sigma1[1]); + eval(shift(@insns)); + eval(shift(@insns)); + &veor ($T5,$T5,$T4); # sigma1(X[16..17]) + eval(shift(@insns)); + eval(shift(@insns)); + &vadd_i32 (&Dhi(@X[0]),&Dhi(@X[0]),$T5);# X[2..3] += sigma1(X[16..17]) + eval(shift(@insns)); + eval(shift(@insns)); + &vadd_i32 ($T0,$T0,@X[0]); + while($#insns>=2) { eval(shift(@insns)); } + &vst1_32 ("{$T0}","[$Xfer,:128]!"); + eval(shift(@insns)); + eval(shift(@insns)); + + push(@X,shift(@X)); # "rotate" X[] +} + +sub Xpreload() +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); + my ($a,$b,$c,$d,$e,$f,$g,$h); + + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vld1_32 ("{$T0}","[$Ktbl,:128]!"); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vrev32_8 (@X[0],@X[0]); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vadd_i32 ($T0,$T0,@X[0]); + foreach (@insns) { eval; } # remaining instructions + &vst1_32 ("{$T0}","[$Xfer,:128]!"); + + push(@X,shift(@X)); # "rotate" X[] +} + +sub body_00_15 () { + ( + '($a,$b,$c,$d,$e,$f,$g,$h)=@V;'. + '&add ($h,$h,$t1)', # h+=X[i]+K[i] + '&eor ($t1,$f,$g)', + '&eor ($t0,$e,$e,"ror#".($Sigma1[1]-$Sigma1[0]))', + '&add ($a,$a,$t2)', # h+=Maj(a,b,c) from the past + '&and ($t1,$t1,$e)', + '&eor ($t2,$t0,$e,"ror#".($Sigma1[2]-$Sigma1[0]))', # Sigma1(e) + '&eor ($t0,$a,$a,"ror#".($Sigma0[1]-$Sigma0[0]))', + '&eor ($t1,$t1,$g)', # Ch(e,f,g) + '&add ($h,$h,$t2,"ror#$Sigma1[0]")', # h+=Sigma1(e) + '&eor ($t2,$a,$b)', # a^b, b^c in next round + '&eor ($t0,$t0,$a,"ror#".($Sigma0[2]-$Sigma0[0]))', # Sigma0(a) + '&add ($h,$h,$t1)', # h+=Ch(e,f,g) + '&ldr ($t1,sprintf "[sp,#%d]",4*(($j+1)&15)) if (($j&15)!=15);'. + '&ldr ($t1,"[$Ktbl]") if ($j==15);'. + '&ldr ($t1,"[sp,#64]") if ($j==31)', + '&and ($t3,$t3,$t2)', # (b^c)&=(a^b) + '&add ($d,$d,$h)', # d+=h + '&add ($h,$h,$t0,"ror#$Sigma0[0]");'. # h+=Sigma0(a) + '&eor ($t3,$t3,$b)', # Maj(a,b,c) + '$j++; unshift(@V,pop(@V)); ($t2,$t3)=($t3,$t2);' + ) +} + +$code.=<<___; +#if __ARM_MAX_ARCH__>=7 +.arch armv7-a +.fpu neon + +.global sha256_block_data_order_neon +.type sha256_block_data_order_neon,%function +.align 4 +sha256_block_data_order_neon: +.LNEON: + stmdb sp!,{r4-r12,lr} + + sub $H,sp,#16*4+16 + adrl $Ktbl,K256 + bic $H,$H,#15 @ align for 128-bit stores + mov $t2,sp + mov sp,$H @ alloca + add $len,$inp,$len,lsl#6 @ len to point at the end of inp + + vld1.8 {@X[0]},[$inp]! + vld1.8 {@X[1]},[$inp]! + vld1.8 {@X[2]},[$inp]! + vld1.8 {@X[3]},[$inp]! + vld1.32 {$T0},[$Ktbl,:128]! + vld1.32 {$T1},[$Ktbl,:128]! + vld1.32 {$T2},[$Ktbl,:128]! + vld1.32 {$T3},[$Ktbl,:128]! + vrev32.8 @X[0],@X[0] @ yes, even on + str $ctx,[sp,#64] + vrev32.8 @X[1],@X[1] @ big-endian + str $inp,[sp,#68] + mov $Xfer,sp + vrev32.8 @X[2],@X[2] + str $len,[sp,#72] + vrev32.8 @X[3],@X[3] + str $t2,[sp,#76] @ save original sp + vadd.i32 $T0,$T0,@X[0] + vadd.i32 $T1,$T1,@X[1] + vst1.32 {$T0},[$Xfer,:128]! + vadd.i32 $T2,$T2,@X[2] + vst1.32 {$T1},[$Xfer,:128]! + vadd.i32 $T3,$T3,@X[3] + vst1.32 {$T2},[$Xfer,:128]! + vst1.32 {$T3},[$Xfer,:128]! + + ldmia $ctx,{$A-$H} + sub $Xfer,$Xfer,#64 + ldr $t1,[sp,#0] + eor $t2,$t2,$t2 + eor $t3,$B,$C + b .L_00_48 + +.align 4 +.L_00_48: +___ + &Xupdate(\&body_00_15); + &Xupdate(\&body_00_15); + &Xupdate(\&body_00_15); + &Xupdate(\&body_00_15); +$code.=<<___; + teq $t1,#0 @ check for K256 terminator + ldr $t1,[sp,#0] + sub $Xfer,$Xfer,#64 + bne .L_00_48 + + ldr $inp,[sp,#68] + ldr $t0,[sp,#72] + sub $Ktbl,$Ktbl,#256 @ rewind $Ktbl + teq $inp,$t0 + it eq + subeq $inp,$inp,#64 @ avoid SEGV + vld1.8 {@X[0]},[$inp]! @ load next input block + vld1.8 {@X[1]},[$inp]! + vld1.8 {@X[2]},[$inp]! + vld1.8 {@X[3]},[$inp]! + it ne + strne $inp,[sp,#68] + mov $Xfer,sp +___ + &Xpreload(\&body_00_15); + &Xpreload(\&body_00_15); + &Xpreload(\&body_00_15); + &Xpreload(\&body_00_15); +$code.=<<___; + ldr $t0,[$t1,#0] + add $A,$A,$t2 @ h+=Maj(a,b,c) from the past + ldr $t2,[$t1,#4] + ldr $t3,[$t1,#8] + ldr $t4,[$t1,#12] + add $A,$A,$t0 @ accumulate + ldr $t0,[$t1,#16] + add $B,$B,$t2 + ldr $t2,[$t1,#20] + add $C,$C,$t3 + ldr $t3,[$t1,#24] + add $D,$D,$t4 + ldr $t4,[$t1,#28] + add $E,$E,$t0 + str $A,[$t1],#4 + add $F,$F,$t2 + str $B,[$t1],#4 + add $G,$G,$t3 + str $C,[$t1],#4 + add $H,$H,$t4 + str $D,[$t1],#4 + stmia $t1,{$E-$H} + + ittte ne + movne $Xfer,sp + ldrne $t1,[sp,#0] + eorne $t2,$t2,$t2 + ldreq sp,[sp,#76] @ restore original sp + itt ne + eorne $t3,$B,$C + bne .L_00_48 + + ldmia sp!,{r4-r12,pc} +.size sha256_block_data_order_neon,.-sha256_block_data_order_neon +#endif +___ +}}} +###################################################################### +# ARMv8 stuff +# +{{{ +my ($ABCD,$EFGH,$abcd)=map("q$_",(0..2)); +my @MSG=map("q$_",(8..11)); +my ($W0,$W1,$ABCD_SAVE,$EFGH_SAVE)=map("q$_",(12..15)); +my $Ktbl="r3"; + +$code.=<<___; +#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__) + +# if defined(__thumb2__) && !defined(__APPLE__) +# define INST(a,b,c,d) .byte c,d|0xc,a,b +# else +# define INST(a,b,c,d) .byte a,b,c,d +# endif + +.type sha256_block_data_order_armv8,%function +.align 5 +sha256_block_data_order_armv8: +.LARMv8: + vld1.32 {$ABCD,$EFGH},[$ctx] +# ifdef __APPLE__ + sub $Ktbl,$Ktbl,#256+32 +# elif defined(__thumb2__) + adr $Ktbl,.LARMv8 + sub $Ktbl,$Ktbl,#.LARMv8-K256 +# else + adrl $Ktbl,K256 +# endif + add $len,$inp,$len,lsl#6 @ len to point at the end of inp + +.Loop_v8: + vld1.8 {@MSG[0]-@MSG[1]},[$inp]! + vld1.8 {@MSG[2]-@MSG[3]},[$inp]! + vld1.32 {$W0},[$Ktbl]! + vrev32.8 @MSG[0],@MSG[0] + vrev32.8 @MSG[1],@MSG[1] + vrev32.8 @MSG[2],@MSG[2] + vrev32.8 @MSG[3],@MSG[3] + vmov $ABCD_SAVE,$ABCD @ offload + vmov $EFGH_SAVE,$EFGH + teq $inp,$len +___ +for($i=0;$i<12;$i++) { +$code.=<<___; + vld1.32 {$W1},[$Ktbl]! + vadd.i32 $W0,$W0,@MSG[0] + sha256su0 @MSG[0],@MSG[1] + vmov $abcd,$ABCD + sha256h $ABCD,$EFGH,$W0 + sha256h2 $EFGH,$abcd,$W0 + sha256su1 @MSG[0],@MSG[2],@MSG[3] +___ + ($W0,$W1)=($W1,$W0); push(@MSG,shift(@MSG)); +} +$code.=<<___; + vld1.32 {$W1},[$Ktbl]! + vadd.i32 $W0,$W0,@MSG[0] + vmov $abcd,$ABCD + sha256h $ABCD,$EFGH,$W0 + sha256h2 $EFGH,$abcd,$W0 + + vld1.32 {$W0},[$Ktbl]! + vadd.i32 $W1,$W1,@MSG[1] + vmov $abcd,$ABCD + sha256h $ABCD,$EFGH,$W1 + sha256h2 $EFGH,$abcd,$W1 + + vld1.32 {$W1},[$Ktbl] + vadd.i32 $W0,$W0,@MSG[2] + sub $Ktbl,$Ktbl,#256-16 @ rewind + vmov $abcd,$ABCD + sha256h $ABCD,$EFGH,$W0 + sha256h2 $EFGH,$abcd,$W0 + + vadd.i32 $W1,$W1,@MSG[3] + vmov $abcd,$ABCD + sha256h $ABCD,$EFGH,$W1 + sha256h2 $EFGH,$abcd,$W1 + + vadd.i32 $ABCD,$ABCD,$ABCD_SAVE + vadd.i32 $EFGH,$EFGH,$EFGH_SAVE + it ne + bne .Loop_v8 + + vst1.32 {$ABCD,$EFGH},[$ctx] + + ret @ bx lr +.size sha256_block_data_order_armv8,.-sha256_block_data_order_armv8 +#endif +___ +}}} +$code.=<<___; +.asciz "SHA256 block transform for ARMv4/NEON/ARMv8, CRYPTOGAMS by " +.align 2 +#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__) +.comm OPENSSL_armcap_P,4,4 +.hidden OPENSSL_armcap_P +#endif +___ + +open SELF,$0; +while() { + next if (/^#!/); + last if (!s/^#/@/ and !/^$/); + print; +} +close SELF; + +{ my %opcode = ( + "sha256h" => 0xf3000c40, "sha256h2" => 0xf3100c40, + "sha256su0" => 0xf3ba03c0, "sha256su1" => 0xf3200c40 ); + + sub unsha256 { + my ($mnemonic,$arg)=@_; + + if ($arg =~ m/q([0-9]+)(?:,\s*q([0-9]+))?,\s*q([0-9]+)/o) { + my $word = $opcode{$mnemonic}|(($1&7)<<13)|(($1&8)<<19) + |(($2&7)<<17)|(($2&8)<<4) + |(($3&7)<<1) |(($3&8)<<2); + # since ARMv7 instructions are always encoded little-endian. + # correct solution is to use .inst directive, but older + # assemblers don't implement it:-( + sprintf "INST(0x%02x,0x%02x,0x%02x,0x%02x)\t@ %s %s", + $word&0xff,($word>>8)&0xff, + ($word>>16)&0xff,($word>>24)&0xff, + $mnemonic,$arg; + } + } +} + +foreach (split($/,$code)) { + + s/\`([^\`]*)\`/eval $1/geo; + + s/\b(sha256\w+)\s+(q.*)/unsha256($1,$2)/geo; + + s/\bret\b/bx lr/go or + s/\bbx\s+lr\b/.word\t0xe12fff1e/go; # make it possible to compile with -march=armv4 + + print $_,"\n"; +} + +close STDOUT; # enforce flush diff --git a/external/boringssl/crypto/sha/asm/sha512-586.pl b/external/boringssl/crypto/sha/asm/sha512-586.pl new file mode 100644 index 0000000000..2f6a202c37 --- /dev/null +++ b/external/boringssl/crypto/sha/asm/sha512-586.pl @@ -0,0 +1,911 @@ +#!/usr/bin/env perl +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# SHA512 block transform for x86. September 2007. +# +# May 2013. +# +# Add SSSE3 code path, 20-25% improvement [over original SSE2 code]. +# +# Performance in clock cycles per processed byte (less is better): +# +# gcc icc x86 asm SIMD(*) x86_64(**) +# Pentium 100 97 61 - - +# PIII 75 77 56 - - +# P4 116 95 82 34.6 30.8 +# AMD K8 54 55 36 20.7 9.57 +# Core2 66 57 40 15.9 9.97 +# Westmere 70 - 38 12.2 9.58 +# Sandy Bridge 58 - 35 11.9 11.2 +# Ivy Bridge 50 - 33 11.5 8.17 +# Haswell 46 - 29 11.3 7.66 +# Bulldozer 121 - 50 14.0 13.5 +# VIA Nano 91 - 52 33 14.7 +# Atom 126 - 68 48(***) 14.7 +# Silvermont 97 - 58 42(***) 17.5 +# +# (*) whichever best applicable. +# (**) x86_64 assembler performance is presented for reference +# purposes, the results are for integer-only code. +# (***) paddq is increadibly slow on Atom. +# +# IALU code-path is optimized for elder Pentiums. On vanilla Pentium +# performance improvement over compiler generated code reaches ~60%, +# while on PIII - ~35%. On newer µ-archs improvement varies from 15% +# to 50%, but it's less important as they are expected to execute SSE2 +# code-path, which is commonly ~2-3x faster [than compiler generated +# code]. SSE2 code-path is as fast as original sha512-sse2.pl, even +# though it does not use 128-bit operations. The latter means that +# SSE2-aware kernel is no longer required to execute the code. Another +# difference is that new code optimizes amount of writes, but at the +# cost of increased data cache "footprint" by 1/2KB. + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +push(@INC,"${dir}","${dir}../../perlasm"); +require "x86asm.pl"; + +&asm_init($ARGV[0],"sha512-586.pl",$ARGV[$#ARGV] eq "386"); + +$sse2=0; +for (@ARGV) { $sse2=1 if (/-DOPENSSL_IA32_SSE2/); } + +&external_label("OPENSSL_ia32cap_P") if ($sse2); + +$Tlo=&DWP(0,"esp"); $Thi=&DWP(4,"esp"); +$Alo=&DWP(8,"esp"); $Ahi=&DWP(8+4,"esp"); +$Blo=&DWP(16,"esp"); $Bhi=&DWP(16+4,"esp"); +$Clo=&DWP(24,"esp"); $Chi=&DWP(24+4,"esp"); +$Dlo=&DWP(32,"esp"); $Dhi=&DWP(32+4,"esp"); +$Elo=&DWP(40,"esp"); $Ehi=&DWP(40+4,"esp"); +$Flo=&DWP(48,"esp"); $Fhi=&DWP(48+4,"esp"); +$Glo=&DWP(56,"esp"); $Ghi=&DWP(56+4,"esp"); +$Hlo=&DWP(64,"esp"); $Hhi=&DWP(64+4,"esp"); +$K512="ebp"; + +$Asse2=&QWP(0,"esp"); +$Bsse2=&QWP(8,"esp"); +$Csse2=&QWP(16,"esp"); +$Dsse2=&QWP(24,"esp"); +$Esse2=&QWP(32,"esp"); +$Fsse2=&QWP(40,"esp"); +$Gsse2=&QWP(48,"esp"); +$Hsse2=&QWP(56,"esp"); + +$A="mm0"; # B-D and +$E="mm4"; # F-H are commonly loaded to respectively mm1-mm3 and + # mm5-mm7, but it's done on on-demand basis... +$BxC="mm2"; # ... except for B^C + +sub BODY_00_15_sse2 { + my $phase=shift; + + #&movq ("mm5",$Fsse2); # load f + #&movq ("mm6",$Gsse2); # load g + + &movq ("mm1",$E); # %mm1 is sliding right + &pxor ("mm5","mm6"); # f^=g + &psrlq ("mm1",14); + &movq ($Esse2,$E); # modulo-scheduled save e + &pand ("mm5",$E); # f&=e + &psllq ($E,23); # $E is sliding left + &movq ($A,"mm3") if ($phase<2); + &movq (&QWP(8*9,"esp"),"mm7") # save X[i] + &movq ("mm3","mm1"); # %mm3 is T1 + &psrlq ("mm1",4); + &pxor ("mm5","mm6"); # Ch(e,f,g) + &pxor ("mm3",$E); + &psllq ($E,23); + &pxor ("mm3","mm1"); + &movq ($Asse2,$A); # modulo-scheduled save a + &paddq ("mm7","mm5"); # X[i]+=Ch(e,f,g) + &pxor ("mm3",$E); + &psrlq ("mm1",23); + &paddq ("mm7",$Hsse2); # X[i]+=h + &pxor ("mm3","mm1"); + &psllq ($E,4); + &paddq ("mm7",QWP(0,$K512)); # X[i]+=K512[i] + &pxor ("mm3",$E); # T1=Sigma1_512(e) + + &movq ($E,$Dsse2); # e = load d, e in next round + &paddq ("mm3","mm7"); # T1+=X[i] + &movq ("mm5",$A); # %mm5 is sliding right + &psrlq ("mm5",28); + &paddq ($E,"mm3"); # d += T1 + &movq ("mm6",$A); # %mm6 is sliding left + &movq ("mm7","mm5"); + &psllq ("mm6",25); + &movq ("mm1",$Bsse2); # load b + &psrlq ("mm5",6); + &pxor ("mm7","mm6"); + &sub ("esp",8); + &psllq ("mm6",5); + &pxor ("mm7","mm5"); + &pxor ($A,"mm1"); # a^b, b^c in next round + &psrlq ("mm5",5); + &pxor ("mm7","mm6"); + &pand ($BxC,$A); # (b^c)&(a^b) + &psllq ("mm6",6); + &pxor ("mm7","mm5"); + &pxor ($BxC,"mm1"); # [h=]Maj(a,b,c) + &pxor ("mm6","mm7"); # Sigma0_512(a) + &movq ("mm7",&QWP(8*(9+16-1),"esp")) if ($phase!=0); # pre-fetch + &movq ("mm5",$Fsse2) if ($phase==0); # load f + + if ($phase>1) { + &paddq ($BxC,"mm6"); # h+=Sigma0(a) + &add ($K512,8); + #&paddq ($BxC,"mm3"); # h+=T1 + + ($A,$BxC) = ($BxC,$A); # rotate registers + } else { + &paddq ("mm3",$BxC); # T1+=Maj(a,b,c) + &movq ($BxC,$A); + &add ($K512,8); + &paddq ("mm3","mm6"); # T1+=Sigma0(a) + &movq ("mm6",$Gsse2) if ($phase==0); # load g + #&movq ($A,"mm3"); # h=T1 + } +} + +sub BODY_00_15_x86 { + #define Sigma1(x) (ROTR((x),14) ^ ROTR((x),18) ^ ROTR((x),41)) + # LO lo>>14^hi<<18 ^ lo>>18^hi<<14 ^ hi>>9^lo<<23 + # HI hi>>14^lo<<18 ^ hi>>18^lo<<14 ^ lo>>9^hi<<23 + &mov ("ecx",$Elo); + &mov ("edx",$Ehi); + &mov ("esi","ecx"); + + &shr ("ecx",9); # lo>>9 + &mov ("edi","edx"); + &shr ("edx",9); # hi>>9 + &mov ("ebx","ecx"); + &shl ("esi",14); # lo<<14 + &mov ("eax","edx"); + &shl ("edi",14); # hi<<14 + &xor ("ebx","esi"); + + &shr ("ecx",14-9); # lo>>14 + &xor ("eax","edi"); + &shr ("edx",14-9); # hi>>14 + &xor ("eax","ecx"); + &shl ("esi",18-14); # lo<<18 + &xor ("ebx","edx"); + &shl ("edi",18-14); # hi<<18 + &xor ("ebx","esi"); + + &shr ("ecx",18-14); # lo>>18 + &xor ("eax","edi"); + &shr ("edx",18-14); # hi>>18 + &xor ("eax","ecx"); + &shl ("esi",23-18); # lo<<23 + &xor ("ebx","edx"); + &shl ("edi",23-18); # hi<<23 + &xor ("eax","esi"); + &xor ("ebx","edi"); # T1 = Sigma1(e) + + &mov ("ecx",$Flo); + &mov ("edx",$Fhi); + &mov ("esi",$Glo); + &mov ("edi",$Ghi); + &add ("eax",$Hlo); + &adc ("ebx",$Hhi); # T1 += h + &xor ("ecx","esi"); + &xor ("edx","edi"); + &and ("ecx",$Elo); + &and ("edx",$Ehi); + &add ("eax",&DWP(8*(9+15)+0,"esp")); + &adc ("ebx",&DWP(8*(9+15)+4,"esp")); # T1 += X[0] + &xor ("ecx","esi"); + &xor ("edx","edi"); # Ch(e,f,g) = (f^g)&e)^g + + &mov ("esi",&DWP(0,$K512)); + &mov ("edi",&DWP(4,$K512)); # K[i] + &add ("eax","ecx"); + &adc ("ebx","edx"); # T1 += Ch(e,f,g) + &mov ("ecx",$Dlo); + &mov ("edx",$Dhi); + &add ("eax","esi"); + &adc ("ebx","edi"); # T1 += K[i] + &mov ($Tlo,"eax"); + &mov ($Thi,"ebx"); # put T1 away + &add ("eax","ecx"); + &adc ("ebx","edx"); # d += T1 + + #define Sigma0(x) (ROTR((x),28) ^ ROTR((x),34) ^ ROTR((x),39)) + # LO lo>>28^hi<<4 ^ hi>>2^lo<<30 ^ hi>>7^lo<<25 + # HI hi>>28^lo<<4 ^ lo>>2^hi<<30 ^ lo>>7^hi<<25 + &mov ("ecx",$Alo); + &mov ("edx",$Ahi); + &mov ($Dlo,"eax"); + &mov ($Dhi,"ebx"); + &mov ("esi","ecx"); + + &shr ("ecx",2); # lo>>2 + &mov ("edi","edx"); + &shr ("edx",2); # hi>>2 + &mov ("ebx","ecx"); + &shl ("esi",4); # lo<<4 + &mov ("eax","edx"); + &shl ("edi",4); # hi<<4 + &xor ("ebx","esi"); + + &shr ("ecx",7-2); # lo>>7 + &xor ("eax","edi"); + &shr ("edx",7-2); # hi>>7 + &xor ("ebx","ecx"); + &shl ("esi",25-4); # lo<<25 + &xor ("eax","edx"); + &shl ("edi",25-4); # hi<<25 + &xor ("eax","esi"); + + &shr ("ecx",28-7); # lo>>28 + &xor ("ebx","edi"); + &shr ("edx",28-7); # hi>>28 + &xor ("eax","ecx"); + &shl ("esi",30-25); # lo<<30 + &xor ("ebx","edx"); + &shl ("edi",30-25); # hi<<30 + &xor ("eax","esi"); + &xor ("ebx","edi"); # Sigma0(a) + + &mov ("ecx",$Alo); + &mov ("edx",$Ahi); + &mov ("esi",$Blo); + &mov ("edi",$Bhi); + &add ("eax",$Tlo); + &adc ("ebx",$Thi); # T1 = Sigma0(a)+T1 + &or ("ecx","esi"); + &or ("edx","edi"); + &and ("ecx",$Clo); + &and ("edx",$Chi); + &and ("esi",$Alo); + &and ("edi",$Ahi); + &or ("ecx","esi"); + &or ("edx","edi"); # Maj(a,b,c) = ((a|b)&c)|(a&b) + + &add ("eax","ecx"); + &adc ("ebx","edx"); # T1 += Maj(a,b,c) + &mov ($Tlo,"eax"); + &mov ($Thi,"ebx"); + + &mov (&LB("edx"),&BP(0,$K512)); # pre-fetch LSB of *K + &sub ("esp",8); + &lea ($K512,&DWP(8,$K512)); # K++ +} + + +&function_begin("sha512_block_data_order"); + &mov ("esi",wparam(0)); # ctx + &mov ("edi",wparam(1)); # inp + &mov ("eax",wparam(2)); # num + &mov ("ebx","esp"); # saved sp + + &call (&label("pic_point")); # make it PIC! +&set_label("pic_point"); + &blindpop($K512); + &lea ($K512,&DWP(&label("K512")."-".&label("pic_point"),$K512)); + + &sub ("esp",16); + &and ("esp",-64); + + &shl ("eax",7); + &add ("eax","edi"); + &mov (&DWP(0,"esp"),"esi"); # ctx + &mov (&DWP(4,"esp"),"edi"); # inp + &mov (&DWP(8,"esp"),"eax"); # inp+num*128 + &mov (&DWP(12,"esp"),"ebx"); # saved sp + +if ($sse2) { + &picmeup("edx","OPENSSL_ia32cap_P",$K512,&label("K512")); + &mov ("ecx",&DWP(0,"edx")); + &test ("ecx",1<<26); + &jz (&label("loop_x86")); + + &mov ("edx",&DWP(4,"edx")); + + # load ctx->h[0-7] + &movq ($A,&QWP(0,"esi")); + &and ("ecx",1<<24); # XMM registers availability + &movq ("mm1",&QWP(8,"esi")); + &and ("edx",1<<9); # SSSE3 bit + &movq ($BxC,&QWP(16,"esi")); + &or ("ecx","edx"); + &movq ("mm3",&QWP(24,"esi")); + &movq ($E,&QWP(32,"esi")); + &movq ("mm5",&QWP(40,"esi")); + &movq ("mm6",&QWP(48,"esi")); + &movq ("mm7",&QWP(56,"esi")); + &cmp ("ecx",1<<24|1<<9); + &je (&label("SSSE3")); + &sub ("esp",8*10); + &jmp (&label("loop_sse2")); + +&set_label("loop_sse2",16); + #&movq ($Asse2,$A); + &movq ($Bsse2,"mm1"); + &movq ($Csse2,$BxC); + &movq ($Dsse2,"mm3"); + #&movq ($Esse2,$E); + &movq ($Fsse2,"mm5"); + &movq ($Gsse2,"mm6"); + &pxor ($BxC,"mm1"); # magic + &movq ($Hsse2,"mm7"); + &movq ("mm3",$A); # magic + + &mov ("eax",&DWP(0,"edi")); + &mov ("ebx",&DWP(4,"edi")); + &add ("edi",8); + &mov ("edx",15); # counter + &bswap ("eax"); + &bswap ("ebx"); + &jmp (&label("00_14_sse2")); + +&set_label("00_14_sse2",16); + &movd ("mm1","eax"); + &mov ("eax",&DWP(0,"edi")); + &movd ("mm7","ebx"); + &mov ("ebx",&DWP(4,"edi")); + &add ("edi",8); + &bswap ("eax"); + &bswap ("ebx"); + &punpckldq("mm7","mm1"); + + &BODY_00_15_sse2(); + + &dec ("edx"); + &jnz (&label("00_14_sse2")); + + &movd ("mm1","eax"); + &movd ("mm7","ebx"); + &punpckldq("mm7","mm1"); + + &BODY_00_15_sse2(1); + + &pxor ($A,$A); # A is in %mm3 + &mov ("edx",32); # counter + &jmp (&label("16_79_sse2")); + +&set_label("16_79_sse2",16); + for ($j=0;$j<2;$j++) { # 2x unroll + #&movq ("mm7",&QWP(8*(9+16-1),"esp")); # prefetched in BODY_00_15 + &movq ("mm5",&QWP(8*(9+16-14),"esp")); + &movq ("mm1","mm7"); + &psrlq ("mm7",1); + &movq ("mm6","mm5"); + &psrlq ("mm5",6); + &psllq ("mm1",56); + &paddq ($A,"mm3"); # from BODY_00_15 + &movq ("mm3","mm7"); + &psrlq ("mm7",7-1); + &pxor ("mm3","mm1"); + &psllq ("mm1",63-56); + &pxor ("mm3","mm7"); + &psrlq ("mm7",8-7); + &pxor ("mm3","mm1"); + &movq ("mm1","mm5"); + &psrlq ("mm5",19-6); + &pxor ("mm7","mm3"); # sigma0 + + &psllq ("mm6",3); + &pxor ("mm1","mm5"); + &paddq ("mm7",&QWP(8*(9+16),"esp")); + &pxor ("mm1","mm6"); + &psrlq ("mm5",61-19); + &paddq ("mm7",&QWP(8*(9+16-9),"esp")); + &pxor ("mm1","mm5"); + &psllq ("mm6",45-3); + &movq ("mm5",$Fsse2); # load f + &pxor ("mm1","mm6"); # sigma1 + &movq ("mm6",$Gsse2); # load g + + &paddq ("mm7","mm1"); # X[i] + #&movq (&QWP(8*9,"esp"),"mm7"); # moved to BODY_00_15 + + &BODY_00_15_sse2(2); + } + &dec ("edx"); + &jnz (&label("16_79_sse2")); + + #&movq ($A,$Asse2); + &paddq ($A,"mm3"); # from BODY_00_15 + &movq ("mm1",$Bsse2); + #&movq ($BxC,$Csse2); + &movq ("mm3",$Dsse2); + #&movq ($E,$Esse2); + &movq ("mm5",$Fsse2); + &movq ("mm6",$Gsse2); + &movq ("mm7",$Hsse2); + + &pxor ($BxC,"mm1"); # de-magic + &paddq ($A,&QWP(0,"esi")); + &paddq ("mm1",&QWP(8,"esi")); + &paddq ($BxC,&QWP(16,"esi")); + &paddq ("mm3",&QWP(24,"esi")); + &paddq ($E,&QWP(32,"esi")); + &paddq ("mm5",&QWP(40,"esi")); + &paddq ("mm6",&QWP(48,"esi")); + &paddq ("mm7",&QWP(56,"esi")); + + &mov ("eax",8*80); + &movq (&QWP(0,"esi"),$A); + &movq (&QWP(8,"esi"),"mm1"); + &movq (&QWP(16,"esi"),$BxC); + &movq (&QWP(24,"esi"),"mm3"); + &movq (&QWP(32,"esi"),$E); + &movq (&QWP(40,"esi"),"mm5"); + &movq (&QWP(48,"esi"),"mm6"); + &movq (&QWP(56,"esi"),"mm7"); + + &lea ("esp",&DWP(0,"esp","eax")); # destroy frame + &sub ($K512,"eax"); # rewind K + + &cmp ("edi",&DWP(8*10+8,"esp")); # are we done yet? + &jb (&label("loop_sse2")); + + &mov ("esp",&DWP(8*10+12,"esp")); # restore sp + &emms (); +&function_end_A(); + +&set_label("SSSE3",32); +{ my ($cnt,$frame)=("ecx","edx"); + my @X=map("xmm$_",(0..7)); + my $j; + my $i=0; + + &lea ($frame,&DWP(-64,"esp")); + &sub ("esp",256); + + # fixed stack frame layout + # + # +0 A B C D E F G H # backing store + # +64 X[0]+K[i] .. X[15]+K[i] # XMM->MM xfer area + # +192 # XMM off-load ring buffer + # +256 # saved parameters + + &movdqa (@X[1],&QWP(80*8,$K512)); # byte swap mask + &movdqu (@X[0],&QWP(0,"edi")); + &pshufb (@X[0],@X[1]); + for ($j=0;$j<8;$j++) { + &movdqa (&QWP(16*(($j-1)%4),$frame),@X[3]) if ($j>4); # off-load + &movdqa (@X[3],&QWP(16*($j%8),$K512)); + &movdqa (@X[2],@X[1]) if ($j<7); # perpetuate byte swap mask + &movdqu (@X[1],&QWP(16*($j+1),"edi")) if ($j<7); # next input + &movdqa (@X[1],&QWP(16*(($j+1)%4),$frame)) if ($j==7);# restore @X[0] + &paddq (@X[3],@X[0]); + &pshufb (@X[1],@X[2]) if ($j<7); + &movdqa (&QWP(16*($j%8)-128,$frame),@X[3]); # xfer X[i]+K[i] + + push(@X,shift(@X)); # rotate(@X) + } + #&jmp (&label("loop_ssse3")); + &nop (); + +&set_label("loop_ssse3",32); + &movdqa (@X[2],&QWP(16*(($j+1)%4),$frame)); # pre-restore @X[1] + &movdqa (&QWP(16*(($j-1)%4),$frame),@X[3]); # off-load @X[3] + &lea ($K512,&DWP(16*8,$K512)); + + #&movq ($Asse2,$A); # off-load A-H + &movq ($Bsse2,"mm1"); + &mov ("ebx","edi"); + &movq ($Csse2,$BxC); + &lea ("edi",&DWP(128,"edi")); # advance input + &movq ($Dsse2,"mm3"); + &cmp ("edi","eax"); + #&movq ($Esse2,$E); + &movq ($Fsse2,"mm5"); + &cmovb ("ebx","edi"); + &movq ($Gsse2,"mm6"); + &mov ("ecx",4); # loop counter + &pxor ($BxC,"mm1"); # magic + &movq ($Hsse2,"mm7"); + &pxor ("mm3","mm3"); # magic + + &jmp (&label("00_47_ssse3")); + +sub BODY_00_15_ssse3 { # "phase-less" copy of BODY_00_15_sse2 + ( + '&movq ("mm1",$E)', # %mm1 is sliding right + '&movq ("mm7",&QWP(((-8*$i)%128)-128,$frame))',# X[i]+K[i] + '&pxor ("mm5","mm6")', # f^=g + '&psrlq ("mm1",14)', + '&movq (&QWP(8*($i+4)%64,"esp"),$E)', # modulo-scheduled save e + '&pand ("mm5",$E)', # f&=e + '&psllq ($E,23)', # $E is sliding left + '&paddq ($A,"mm3")', # [h+=Maj(a,b,c)] + '&movq ("mm3","mm1")', # %mm3 is T1 + '&psrlq("mm1",4)', + '&pxor ("mm5","mm6")', # Ch(e,f,g) + '&pxor ("mm3",$E)', + '&psllq($E,23)', + '&pxor ("mm3","mm1")', + '&movq (&QWP(8*$i%64,"esp"),$A)', # modulo-scheduled save a + '&paddq("mm7","mm5")', # X[i]+=Ch(e,f,g) + '&pxor ("mm3",$E)', + '&psrlq("mm1",23)', + '&paddq("mm7",&QWP(8*($i+7)%64,"esp"))', # X[i]+=h + '&pxor ("mm3","mm1")', + '&psllq($E,4)', + '&pxor ("mm3",$E)', # T1=Sigma1_512(e) + + '&movq ($E,&QWP(8*($i+3)%64,"esp"))', # e = load d, e in next round + '&paddq ("mm3","mm7")', # T1+=X[i] + '&movq ("mm5",$A)', # %mm5 is sliding right + '&psrlq("mm5",28)', + '&paddq ($E,"mm3")', # d += T1 + '&movq ("mm6",$A)', # %mm6 is sliding left + '&movq ("mm7","mm5")', + '&psllq("mm6",25)', + '&movq ("mm1",&QWP(8*($i+1)%64,"esp"))', # load b + '&psrlq("mm5",6)', + '&pxor ("mm7","mm6")', + '&psllq("mm6",5)', + '&pxor ("mm7","mm5")', + '&pxor ($A,"mm1")', # a^b, b^c in next round + '&psrlq("mm5",5)', + '&pxor ("mm7","mm6")', + '&pand ($BxC,$A)', # (b^c)&(a^b) + '&psllq("mm6",6)', + '&pxor ("mm7","mm5")', + '&pxor ($BxC,"mm1")', # [h=]Maj(a,b,c) + '&pxor ("mm6","mm7")', # Sigma0_512(a) + '&movq ("mm5",&QWP(8*($i+5-1)%64,"esp"))', # pre-load f + '&paddq ($BxC,"mm6")', # h+=Sigma0(a) + '&movq ("mm6",&QWP(8*($i+6-1)%64,"esp"))', # pre-load g + + '($A,$BxC) = ($BxC,$A); $i--;' + ); +} + +&set_label("00_47_ssse3",32); + + for(;$j<16;$j++) { + my ($t0,$t2,$t1)=@X[2..4]; + my @insns = (&BODY_00_15_ssse3(),&BODY_00_15_ssse3()); + + &movdqa ($t2,@X[5]); + &movdqa (@X[1],$t0); # restore @X[1] + &palignr ($t0,@X[0],8); # X[1..2] + &movdqa (&QWP(16*($j%4),$frame),@X[4]); # off-load @X[4] + &palignr ($t2,@X[4],8); # X[9..10] + + &movdqa ($t1,$t0); + &psrlq ($t0,7); + &paddq (@X[0],$t2); # X[0..1] += X[9..10] + &movdqa ($t2,$t1); + &psrlq ($t1,1); + &psllq ($t2,64-8); + &pxor ($t0,$t1); + &psrlq ($t1,8-1); + &pxor ($t0,$t2); + &psllq ($t2,8-1); + &pxor ($t0,$t1); + &movdqa ($t1,@X[7]); + &pxor ($t0,$t2); # sigma0(X[1..2]) + &movdqa ($t2,@X[7]); + &psrlq ($t1,6); + &paddq (@X[0],$t0); # X[0..1] += sigma0(X[1..2]) + + &movdqa ($t0,@X[7]); + &psrlq ($t2,19); + &psllq ($t0,64-61); + &pxor ($t1,$t2); + &psrlq ($t2,61-19); + &pxor ($t1,$t0); + &psllq ($t0,61-19); + &pxor ($t1,$t2); + &movdqa ($t2,&QWP(16*(($j+2)%4),$frame));# pre-restore @X[1] + &pxor ($t1,$t0); # sigma0(X[1..2]) + &movdqa ($t0,&QWP(16*($j%8),$K512)); + eval(shift(@insns)); + &paddq (@X[0],$t1); # X[0..1] += sigma0(X[14..15]) + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &paddq ($t0,@X[0]); + foreach(@insns) { eval; } + &movdqa (&QWP(16*($j%8)-128,$frame),$t0);# xfer X[i]+K[i] + + push(@X,shift(@X)); # rotate(@X) + } + &lea ($K512,&DWP(16*8,$K512)); + &dec ("ecx"); + &jnz (&label("00_47_ssse3")); + + &movdqa (@X[1],&QWP(0,$K512)); # byte swap mask + &lea ($K512,&DWP(-80*8,$K512)); # rewind + &movdqu (@X[0],&QWP(0,"ebx")); + &pshufb (@X[0],@X[1]); + + for ($j=0;$j<8;$j++) { # load next or same block + my @insns = (&BODY_00_15_ssse3(),&BODY_00_15_ssse3()); + + &movdqa (&QWP(16*(($j-1)%4),$frame),@X[3]) if ($j>4); # off-load + &movdqa (@X[3],&QWP(16*($j%8),$K512)); + &movdqa (@X[2],@X[1]) if ($j<7); # perpetuate byte swap mask + &movdqu (@X[1],&QWP(16*($j+1),"ebx")) if ($j<7); # next input + &movdqa (@X[1],&QWP(16*(($j+1)%4),$frame)) if ($j==7);# restore @X[0] + &paddq (@X[3],@X[0]); + &pshufb (@X[1],@X[2]) if ($j<7); + foreach(@insns) { eval; } + &movdqa (&QWP(16*($j%8)-128,$frame),@X[3]);# xfer X[i]+K[i] + + push(@X,shift(@X)); # rotate(@X) + } + + #&movq ($A,$Asse2); # load A-H + &movq ("mm1",$Bsse2); + &paddq ($A,"mm3"); # from BODY_00_15 + #&movq ($BxC,$Csse2); + &movq ("mm3",$Dsse2); + #&movq ($E,$Esse2); + #&movq ("mm5",$Fsse2); + #&movq ("mm6",$Gsse2); + &movq ("mm7",$Hsse2); + + &pxor ($BxC,"mm1"); # de-magic + &paddq ($A,&QWP(0,"esi")); + &paddq ("mm1",&QWP(8,"esi")); + &paddq ($BxC,&QWP(16,"esi")); + &paddq ("mm3",&QWP(24,"esi")); + &paddq ($E,&QWP(32,"esi")); + &paddq ("mm5",&QWP(40,"esi")); + &paddq ("mm6",&QWP(48,"esi")); + &paddq ("mm7",&QWP(56,"esi")); + + &movq (&QWP(0,"esi"),$A); + &movq (&QWP(8,"esi"),"mm1"); + &movq (&QWP(16,"esi"),$BxC); + &movq (&QWP(24,"esi"),"mm3"); + &movq (&QWP(32,"esi"),$E); + &movq (&QWP(40,"esi"),"mm5"); + &movq (&QWP(48,"esi"),"mm6"); + &movq (&QWP(56,"esi"),"mm7"); + + &cmp ("edi","eax") # are we done yet? + &jb (&label("loop_ssse3")); + + &mov ("esp",&DWP(64+12,$frame)); # restore sp + &emms (); +} +&function_end_A(); +} +&set_label("loop_x86",16); + # copy input block to stack reversing byte and qword order + for ($i=0;$i<8;$i++) { + &mov ("eax",&DWP($i*16+0,"edi")); + &mov ("ebx",&DWP($i*16+4,"edi")); + &mov ("ecx",&DWP($i*16+8,"edi")); + &mov ("edx",&DWP($i*16+12,"edi")); + &bswap ("eax"); + &bswap ("ebx"); + &bswap ("ecx"); + &bswap ("edx"); + &push ("eax"); + &push ("ebx"); + &push ("ecx"); + &push ("edx"); + } + &add ("edi",128); + &sub ("esp",9*8); # place for T,A,B,C,D,E,F,G,H + &mov (&DWP(8*(9+16)+4,"esp"),"edi"); + + # copy ctx->h[0-7] to A,B,C,D,E,F,G,H on stack + &lea ("edi",&DWP(8,"esp")); + &mov ("ecx",16); + &data_word(0xA5F3F689); # rep movsd + +&set_label("00_15_x86",16); + &BODY_00_15_x86(); + + &cmp (&LB("edx"),0x94); + &jne (&label("00_15_x86")); + +&set_label("16_79_x86",16); + #define sigma0(x) (ROTR((x),1) ^ ROTR((x),8) ^ ((x)>>7)) + # LO lo>>1^hi<<31 ^ lo>>8^hi<<24 ^ lo>>7^hi<<25 + # HI hi>>1^lo<<31 ^ hi>>8^lo<<24 ^ hi>>7 + &mov ("ecx",&DWP(8*(9+15+16-1)+0,"esp")); + &mov ("edx",&DWP(8*(9+15+16-1)+4,"esp")); + &mov ("esi","ecx"); + + &shr ("ecx",1); # lo>>1 + &mov ("edi","edx"); + &shr ("edx",1); # hi>>1 + &mov ("eax","ecx"); + &shl ("esi",24); # lo<<24 + &mov ("ebx","edx"); + &shl ("edi",24); # hi<<24 + &xor ("ebx","esi"); + + &shr ("ecx",7-1); # lo>>7 + &xor ("eax","edi"); + &shr ("edx",7-1); # hi>>7 + &xor ("eax","ecx"); + &shl ("esi",31-24); # lo<<31 + &xor ("ebx","edx"); + &shl ("edi",25-24); # hi<<25 + &xor ("ebx","esi"); + + &shr ("ecx",8-7); # lo>>8 + &xor ("eax","edi"); + &shr ("edx",8-7); # hi>>8 + &xor ("eax","ecx"); + &shl ("edi",31-25); # hi<<31 + &xor ("ebx","edx"); + &xor ("eax","edi"); # T1 = sigma0(X[-15]) + + &mov (&DWP(0,"esp"),"eax"); + &mov (&DWP(4,"esp"),"ebx"); # put T1 away + + #define sigma1(x) (ROTR((x),19) ^ ROTR((x),61) ^ ((x)>>6)) + # LO lo>>19^hi<<13 ^ hi>>29^lo<<3 ^ lo>>6^hi<<26 + # HI hi>>19^lo<<13 ^ lo>>29^hi<<3 ^ hi>>6 + &mov ("ecx",&DWP(8*(9+15+16-14)+0,"esp")); + &mov ("edx",&DWP(8*(9+15+16-14)+4,"esp")); + &mov ("esi","ecx"); + + &shr ("ecx",6); # lo>>6 + &mov ("edi","edx"); + &shr ("edx",6); # hi>>6 + &mov ("eax","ecx"); + &shl ("esi",3); # lo<<3 + &mov ("ebx","edx"); + &shl ("edi",3); # hi<<3 + &xor ("eax","esi"); + + &shr ("ecx",19-6); # lo>>19 + &xor ("ebx","edi"); + &shr ("edx",19-6); # hi>>19 + &xor ("eax","ecx"); + &shl ("esi",13-3); # lo<<13 + &xor ("ebx","edx"); + &shl ("edi",13-3); # hi<<13 + &xor ("ebx","esi"); + + &shr ("ecx",29-19); # lo>>29 + &xor ("eax","edi"); + &shr ("edx",29-19); # hi>>29 + &xor ("ebx","ecx"); + &shl ("edi",26-13); # hi<<26 + &xor ("eax","edx"); + &xor ("eax","edi"); # sigma1(X[-2]) + + &mov ("ecx",&DWP(8*(9+15+16)+0,"esp")); + &mov ("edx",&DWP(8*(9+15+16)+4,"esp")); + &add ("eax",&DWP(0,"esp")); + &adc ("ebx",&DWP(4,"esp")); # T1 = sigma1(X[-2])+T1 + &mov ("esi",&DWP(8*(9+15+16-9)+0,"esp")); + &mov ("edi",&DWP(8*(9+15+16-9)+4,"esp")); + &add ("eax","ecx"); + &adc ("ebx","edx"); # T1 += X[-16] + &add ("eax","esi"); + &adc ("ebx","edi"); # T1 += X[-7] + &mov (&DWP(8*(9+15)+0,"esp"),"eax"); + &mov (&DWP(8*(9+15)+4,"esp"),"ebx"); # save X[0] + + &BODY_00_15_x86(); + + &cmp (&LB("edx"),0x17); + &jne (&label("16_79_x86")); + + &mov ("esi",&DWP(8*(9+16+80)+0,"esp"));# ctx + &mov ("edi",&DWP(8*(9+16+80)+4,"esp"));# inp + for($i=0;$i<4;$i++) { + &mov ("eax",&DWP($i*16+0,"esi")); + &mov ("ebx",&DWP($i*16+4,"esi")); + &mov ("ecx",&DWP($i*16+8,"esi")); + &mov ("edx",&DWP($i*16+12,"esi")); + &add ("eax",&DWP(8+($i*16)+0,"esp")); + &adc ("ebx",&DWP(8+($i*16)+4,"esp")); + &mov (&DWP($i*16+0,"esi"),"eax"); + &mov (&DWP($i*16+4,"esi"),"ebx"); + &add ("ecx",&DWP(8+($i*16)+8,"esp")); + &adc ("edx",&DWP(8+($i*16)+12,"esp")); + &mov (&DWP($i*16+8,"esi"),"ecx"); + &mov (&DWP($i*16+12,"esi"),"edx"); + } + &add ("esp",8*(9+16+80)); # destroy frame + &sub ($K512,8*80); # rewind K + + &cmp ("edi",&DWP(8,"esp")); # are we done yet? + &jb (&label("loop_x86")); + + &mov ("esp",&DWP(12,"esp")); # restore sp +&function_end_A(); + +&set_label("K512",64); # Yes! I keep it in the code segment! + &data_word(0xd728ae22,0x428a2f98); # u64 + &data_word(0x23ef65cd,0x71374491); # u64 + &data_word(0xec4d3b2f,0xb5c0fbcf); # u64 + &data_word(0x8189dbbc,0xe9b5dba5); # u64 + &data_word(0xf348b538,0x3956c25b); # u64 + &data_word(0xb605d019,0x59f111f1); # u64 + &data_word(0xaf194f9b,0x923f82a4); # u64 + &data_word(0xda6d8118,0xab1c5ed5); # u64 + &data_word(0xa3030242,0xd807aa98); # u64 + &data_word(0x45706fbe,0x12835b01); # u64 + &data_word(0x4ee4b28c,0x243185be); # u64 + &data_word(0xd5ffb4e2,0x550c7dc3); # u64 + &data_word(0xf27b896f,0x72be5d74); # u64 + &data_word(0x3b1696b1,0x80deb1fe); # u64 + &data_word(0x25c71235,0x9bdc06a7); # u64 + &data_word(0xcf692694,0xc19bf174); # u64 + &data_word(0x9ef14ad2,0xe49b69c1); # u64 + &data_word(0x384f25e3,0xefbe4786); # u64 + &data_word(0x8b8cd5b5,0x0fc19dc6); # u64 + &data_word(0x77ac9c65,0x240ca1cc); # u64 + &data_word(0x592b0275,0x2de92c6f); # u64 + &data_word(0x6ea6e483,0x4a7484aa); # u64 + &data_word(0xbd41fbd4,0x5cb0a9dc); # u64 + &data_word(0x831153b5,0x76f988da); # u64 + &data_word(0xee66dfab,0x983e5152); # u64 + &data_word(0x2db43210,0xa831c66d); # u64 + &data_word(0x98fb213f,0xb00327c8); # u64 + &data_word(0xbeef0ee4,0xbf597fc7); # u64 + &data_word(0x3da88fc2,0xc6e00bf3); # u64 + &data_word(0x930aa725,0xd5a79147); # u64 + &data_word(0xe003826f,0x06ca6351); # u64 + &data_word(0x0a0e6e70,0x14292967); # u64 + &data_word(0x46d22ffc,0x27b70a85); # u64 + &data_word(0x5c26c926,0x2e1b2138); # u64 + &data_word(0x5ac42aed,0x4d2c6dfc); # u64 + &data_word(0x9d95b3df,0x53380d13); # u64 + &data_word(0x8baf63de,0x650a7354); # u64 + &data_word(0x3c77b2a8,0x766a0abb); # u64 + &data_word(0x47edaee6,0x81c2c92e); # u64 + &data_word(0x1482353b,0x92722c85); # u64 + &data_word(0x4cf10364,0xa2bfe8a1); # u64 + &data_word(0xbc423001,0xa81a664b); # u64 + &data_word(0xd0f89791,0xc24b8b70); # u64 + &data_word(0x0654be30,0xc76c51a3); # u64 + &data_word(0xd6ef5218,0xd192e819); # u64 + &data_word(0x5565a910,0xd6990624); # u64 + &data_word(0x5771202a,0xf40e3585); # u64 + &data_word(0x32bbd1b8,0x106aa070); # u64 + &data_word(0xb8d2d0c8,0x19a4c116); # u64 + &data_word(0x5141ab53,0x1e376c08); # u64 + &data_word(0xdf8eeb99,0x2748774c); # u64 + &data_word(0xe19b48a8,0x34b0bcb5); # u64 + &data_word(0xc5c95a63,0x391c0cb3); # u64 + &data_word(0xe3418acb,0x4ed8aa4a); # u64 + &data_word(0x7763e373,0x5b9cca4f); # u64 + &data_word(0xd6b2b8a3,0x682e6ff3); # u64 + &data_word(0x5defb2fc,0x748f82ee); # u64 + &data_word(0x43172f60,0x78a5636f); # u64 + &data_word(0xa1f0ab72,0x84c87814); # u64 + &data_word(0x1a6439ec,0x8cc70208); # u64 + &data_word(0x23631e28,0x90befffa); # u64 + &data_word(0xde82bde9,0xa4506ceb); # u64 + &data_word(0xb2c67915,0xbef9a3f7); # u64 + &data_word(0xe372532b,0xc67178f2); # u64 + &data_word(0xea26619c,0xca273ece); # u64 + &data_word(0x21c0c207,0xd186b8c7); # u64 + &data_word(0xcde0eb1e,0xeada7dd6); # u64 + &data_word(0xee6ed178,0xf57d4f7f); # u64 + &data_word(0x72176fba,0x06f067aa); # u64 + &data_word(0xa2c898a6,0x0a637dc5); # u64 + &data_word(0xbef90dae,0x113f9804); # u64 + &data_word(0x131c471b,0x1b710b35); # u64 + &data_word(0x23047d84,0x28db77f5); # u64 + &data_word(0x40c72493,0x32caab7b); # u64 + &data_word(0x15c9bebc,0x3c9ebe0a); # u64 + &data_word(0x9c100d4c,0x431d67c4); # u64 + &data_word(0xcb3e42b6,0x4cc5d4be); # u64 + &data_word(0xfc657e2a,0x597f299c); # u64 + &data_word(0x3ad6faec,0x5fcb6fab); # u64 + &data_word(0x4a475817,0x6c44198c); # u64 + + &data_word(0x04050607,0x00010203); # byte swap + &data_word(0x0c0d0e0f,0x08090a0b); # mask +&function_end_B("sha512_block_data_order"); +&asciz("SHA512 block transform for x86, CRYPTOGAMS by "); + +&asm_finish(); diff --git a/external/boringssl/crypto/sha/asm/sha512-armv4.pl b/external/boringssl/crypto/sha/asm/sha512-armv4.pl new file mode 100644 index 0000000000..15d50f2817 --- /dev/null +++ b/external/boringssl/crypto/sha/asm/sha512-armv4.pl @@ -0,0 +1,666 @@ +#!/usr/bin/env perl + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# +# Permission to use under GPL terms is granted. +# ==================================================================== + +# SHA512 block procedure for ARMv4. September 2007. + +# This code is ~4.5 (four and a half) times faster than code generated +# by gcc 3.4 and it spends ~72 clock cycles per byte [on single-issue +# Xscale PXA250 core]. +# +# July 2010. +# +# Rescheduling for dual-issue pipeline resulted in 6% improvement on +# Cortex A8 core and ~40 cycles per processed byte. + +# February 2011. +# +# Profiler-assisted and platform-specific optimization resulted in 7% +# improvement on Coxtex A8 core and ~38 cycles per byte. + +# March 2011. +# +# Add NEON implementation. On Cortex A8 it was measured to process +# one byte in 23.3 cycles or ~60% faster than integer-only code. + +# August 2012. +# +# Improve NEON performance by 12% on Snapdragon S4. In absolute +# terms it's 22.6 cycles per byte, which is disappointing result. +# Technical writers asserted that 3-way S4 pipeline can sustain +# multiple NEON instructions per cycle, but dual NEON issue could +# not be observed, see http://www.openssl.org/~appro/Snapdragon-S4.html +# for further details. On side note Cortex-A15 processes one byte in +# 16 cycles. + +# Byte order [in]dependence. ========================================= +# +# Originally caller was expected to maintain specific *dword* order in +# h[0-7], namely with most significant dword at *lower* address, which +# was reflected in below two parameters as 0 and 4. Now caller is +# expected to maintain native byte order for whole 64-bit values. +$hi="HI"; +$lo="LO"; +# ==================================================================== + +$flavour = shift; +if ($flavour=~/^\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; } +else { while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {} } + +if ($flavour && $flavour ne "void") { + $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; + ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or + ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or + die "can't locate arm-xlate.pl"; + + open STDOUT,"| \"$^X\" $xlate $flavour $output"; +} else { + open STDOUT,">$output"; +} + +$ctx="r0"; # parameter block +$inp="r1"; +$len="r2"; + +$Tlo="r3"; +$Thi="r4"; +$Alo="r5"; +$Ahi="r6"; +$Elo="r7"; +$Ehi="r8"; +$t0="r9"; +$t1="r10"; +$t2="r11"; +$t3="r12"; +############ r13 is stack pointer +$Ktbl="r14"; +############ r15 is program counter + +$Aoff=8*0; +$Boff=8*1; +$Coff=8*2; +$Doff=8*3; +$Eoff=8*4; +$Foff=8*5; +$Goff=8*6; +$Hoff=8*7; +$Xoff=8*8; + +sub BODY_00_15() { +my $magic = shift; +$code.=<<___; + @ Sigma1(x) (ROTR((x),14) ^ ROTR((x),18) ^ ROTR((x),41)) + @ LO lo>>14^hi<<18 ^ lo>>18^hi<<14 ^ hi>>9^lo<<23 + @ HI hi>>14^lo<<18 ^ hi>>18^lo<<14 ^ lo>>9^hi<<23 + mov $t0,$Elo,lsr#14 + str $Tlo,[sp,#$Xoff+0] + mov $t1,$Ehi,lsr#14 + str $Thi,[sp,#$Xoff+4] + eor $t0,$t0,$Ehi,lsl#18 + ldr $t2,[sp,#$Hoff+0] @ h.lo + eor $t1,$t1,$Elo,lsl#18 + ldr $t3,[sp,#$Hoff+4] @ h.hi + eor $t0,$t0,$Elo,lsr#18 + eor $t1,$t1,$Ehi,lsr#18 + eor $t0,$t0,$Ehi,lsl#14 + eor $t1,$t1,$Elo,lsl#14 + eor $t0,$t0,$Ehi,lsr#9 + eor $t1,$t1,$Elo,lsr#9 + eor $t0,$t0,$Elo,lsl#23 + eor $t1,$t1,$Ehi,lsl#23 @ Sigma1(e) + adds $Tlo,$Tlo,$t0 + ldr $t0,[sp,#$Foff+0] @ f.lo + adc $Thi,$Thi,$t1 @ T += Sigma1(e) + ldr $t1,[sp,#$Foff+4] @ f.hi + adds $Tlo,$Tlo,$t2 + ldr $t2,[sp,#$Goff+0] @ g.lo + adc $Thi,$Thi,$t3 @ T += h + ldr $t3,[sp,#$Goff+4] @ g.hi + + eor $t0,$t0,$t2 + str $Elo,[sp,#$Eoff+0] + eor $t1,$t1,$t3 + str $Ehi,[sp,#$Eoff+4] + and $t0,$t0,$Elo + str $Alo,[sp,#$Aoff+0] + and $t1,$t1,$Ehi + str $Ahi,[sp,#$Aoff+4] + eor $t0,$t0,$t2 + ldr $t2,[$Ktbl,#$lo] @ K[i].lo + eor $t1,$t1,$t3 @ Ch(e,f,g) + ldr $t3,[$Ktbl,#$hi] @ K[i].hi + + adds $Tlo,$Tlo,$t0 + ldr $Elo,[sp,#$Doff+0] @ d.lo + adc $Thi,$Thi,$t1 @ T += Ch(e,f,g) + ldr $Ehi,[sp,#$Doff+4] @ d.hi + adds $Tlo,$Tlo,$t2 + and $t0,$t2,#0xff + adc $Thi,$Thi,$t3 @ T += K[i] + adds $Elo,$Elo,$Tlo + ldr $t2,[sp,#$Boff+0] @ b.lo + adc $Ehi,$Ehi,$Thi @ d += T + teq $t0,#$magic + + ldr $t3,[sp,#$Coff+0] @ c.lo +#if __ARM_ARCH__>=7 + it eq @ Thumb2 thing, sanity check in ARM +#endif + orreq $Ktbl,$Ktbl,#1 + @ Sigma0(x) (ROTR((x),28) ^ ROTR((x),34) ^ ROTR((x),39)) + @ LO lo>>28^hi<<4 ^ hi>>2^lo<<30 ^ hi>>7^lo<<25 + @ HI hi>>28^lo<<4 ^ lo>>2^hi<<30 ^ lo>>7^hi<<25 + mov $t0,$Alo,lsr#28 + mov $t1,$Ahi,lsr#28 + eor $t0,$t0,$Ahi,lsl#4 + eor $t1,$t1,$Alo,lsl#4 + eor $t0,$t0,$Ahi,lsr#2 + eor $t1,$t1,$Alo,lsr#2 + eor $t0,$t0,$Alo,lsl#30 + eor $t1,$t1,$Ahi,lsl#30 + eor $t0,$t0,$Ahi,lsr#7 + eor $t1,$t1,$Alo,lsr#7 + eor $t0,$t0,$Alo,lsl#25 + eor $t1,$t1,$Ahi,lsl#25 @ Sigma0(a) + adds $Tlo,$Tlo,$t0 + and $t0,$Alo,$t2 + adc $Thi,$Thi,$t1 @ T += Sigma0(a) + + ldr $t1,[sp,#$Boff+4] @ b.hi + orr $Alo,$Alo,$t2 + ldr $t2,[sp,#$Coff+4] @ c.hi + and $Alo,$Alo,$t3 + and $t3,$Ahi,$t1 + orr $Ahi,$Ahi,$t1 + orr $Alo,$Alo,$t0 @ Maj(a,b,c).lo + and $Ahi,$Ahi,$t2 + adds $Alo,$Alo,$Tlo + orr $Ahi,$Ahi,$t3 @ Maj(a,b,c).hi + sub sp,sp,#8 + adc $Ahi,$Ahi,$Thi @ h += T + tst $Ktbl,#1 + add $Ktbl,$Ktbl,#8 +___ +} +$code=<<___; +#ifndef __KERNEL__ +# include +# define VFP_ABI_PUSH vstmdb sp!,{d8-d15} +# define VFP_ABI_POP vldmia sp!,{d8-d15} +#else +# define __ARM_ARCH__ __LINUX_ARM_ARCH__ +# define __ARM_MAX_ARCH__ 7 +# define VFP_ABI_PUSH +# define VFP_ABI_POP +#endif + +#ifdef __ARMEL__ +# define LO 0 +# define HI 4 +# define WORD64(hi0,lo0,hi1,lo1) .word lo0,hi0, lo1,hi1 +#else +# define HI 0 +# define LO 4 +# define WORD64(hi0,lo0,hi1,lo1) .word hi0,lo0, hi1,lo1 +#endif + +.text +#if __ARM_ARCH__<7 || defined(__APPLE__) +.code 32 +#else +.syntax unified +# ifdef __thumb2__ +# define adrl adr +.thumb +# else +.code 32 +# endif +#endif + +.type K512,%object +.align 5 +K512: +WORD64(0x428a2f98,0xd728ae22, 0x71374491,0x23ef65cd) +WORD64(0xb5c0fbcf,0xec4d3b2f, 0xe9b5dba5,0x8189dbbc) +WORD64(0x3956c25b,0xf348b538, 0x59f111f1,0xb605d019) +WORD64(0x923f82a4,0xaf194f9b, 0xab1c5ed5,0xda6d8118) +WORD64(0xd807aa98,0xa3030242, 0x12835b01,0x45706fbe) +WORD64(0x243185be,0x4ee4b28c, 0x550c7dc3,0xd5ffb4e2) +WORD64(0x72be5d74,0xf27b896f, 0x80deb1fe,0x3b1696b1) +WORD64(0x9bdc06a7,0x25c71235, 0xc19bf174,0xcf692694) +WORD64(0xe49b69c1,0x9ef14ad2, 0xefbe4786,0x384f25e3) +WORD64(0x0fc19dc6,0x8b8cd5b5, 0x240ca1cc,0x77ac9c65) +WORD64(0x2de92c6f,0x592b0275, 0x4a7484aa,0x6ea6e483) +WORD64(0x5cb0a9dc,0xbd41fbd4, 0x76f988da,0x831153b5) +WORD64(0x983e5152,0xee66dfab, 0xa831c66d,0x2db43210) +WORD64(0xb00327c8,0x98fb213f, 0xbf597fc7,0xbeef0ee4) +WORD64(0xc6e00bf3,0x3da88fc2, 0xd5a79147,0x930aa725) +WORD64(0x06ca6351,0xe003826f, 0x14292967,0x0a0e6e70) +WORD64(0x27b70a85,0x46d22ffc, 0x2e1b2138,0x5c26c926) +WORD64(0x4d2c6dfc,0x5ac42aed, 0x53380d13,0x9d95b3df) +WORD64(0x650a7354,0x8baf63de, 0x766a0abb,0x3c77b2a8) +WORD64(0x81c2c92e,0x47edaee6, 0x92722c85,0x1482353b) +WORD64(0xa2bfe8a1,0x4cf10364, 0xa81a664b,0xbc423001) +WORD64(0xc24b8b70,0xd0f89791, 0xc76c51a3,0x0654be30) +WORD64(0xd192e819,0xd6ef5218, 0xd6990624,0x5565a910) +WORD64(0xf40e3585,0x5771202a, 0x106aa070,0x32bbd1b8) +WORD64(0x19a4c116,0xb8d2d0c8, 0x1e376c08,0x5141ab53) +WORD64(0x2748774c,0xdf8eeb99, 0x34b0bcb5,0xe19b48a8) +WORD64(0x391c0cb3,0xc5c95a63, 0x4ed8aa4a,0xe3418acb) +WORD64(0x5b9cca4f,0x7763e373, 0x682e6ff3,0xd6b2b8a3) +WORD64(0x748f82ee,0x5defb2fc, 0x78a5636f,0x43172f60) +WORD64(0x84c87814,0xa1f0ab72, 0x8cc70208,0x1a6439ec) +WORD64(0x90befffa,0x23631e28, 0xa4506ceb,0xde82bde9) +WORD64(0xbef9a3f7,0xb2c67915, 0xc67178f2,0xe372532b) +WORD64(0xca273ece,0xea26619c, 0xd186b8c7,0x21c0c207) +WORD64(0xeada7dd6,0xcde0eb1e, 0xf57d4f7f,0xee6ed178) +WORD64(0x06f067aa,0x72176fba, 0x0a637dc5,0xa2c898a6) +WORD64(0x113f9804,0xbef90dae, 0x1b710b35,0x131c471b) +WORD64(0x28db77f5,0x23047d84, 0x32caab7b,0x40c72493) +WORD64(0x3c9ebe0a,0x15c9bebc, 0x431d67c4,0x9c100d4c) +WORD64(0x4cc5d4be,0xcb3e42b6, 0x597f299c,0xfc657e2a) +WORD64(0x5fcb6fab,0x3ad6faec, 0x6c44198c,0x4a475817) +.size K512,.-K512 +#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__) +.LOPENSSL_armcap: +.word OPENSSL_armcap_P-.Lsha512_block_data_order +.skip 32-4 +#else +.skip 32 +#endif + +.global sha512_block_data_order +.type sha512_block_data_order,%function +sha512_block_data_order: +.Lsha512_block_data_order: +#if __ARM_ARCH__<7 + sub r3,pc,#8 @ sha512_block_data_order +#else + adr r3,sha512_block_data_order +#endif +#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__) + ldr r12,.LOPENSSL_armcap + ldr r12,[r3,r12] @ OPENSSL_armcap_P +#ifdef __APPLE__ + ldr r12,[r12] +#endif + tst r12,#ARMV7_NEON + bne .LNEON +#endif + add $len,$inp,$len,lsl#7 @ len to point at the end of inp + stmdb sp!,{r4-r12,lr} + sub $Ktbl,r3,#672 @ K512 + sub sp,sp,#9*8 + + ldr $Elo,[$ctx,#$Eoff+$lo] + ldr $Ehi,[$ctx,#$Eoff+$hi] + ldr $t0, [$ctx,#$Goff+$lo] + ldr $t1, [$ctx,#$Goff+$hi] + ldr $t2, [$ctx,#$Hoff+$lo] + ldr $t3, [$ctx,#$Hoff+$hi] +.Loop: + str $t0, [sp,#$Goff+0] + str $t1, [sp,#$Goff+4] + str $t2, [sp,#$Hoff+0] + str $t3, [sp,#$Hoff+4] + ldr $Alo,[$ctx,#$Aoff+$lo] + ldr $Ahi,[$ctx,#$Aoff+$hi] + ldr $Tlo,[$ctx,#$Boff+$lo] + ldr $Thi,[$ctx,#$Boff+$hi] + ldr $t0, [$ctx,#$Coff+$lo] + ldr $t1, [$ctx,#$Coff+$hi] + ldr $t2, [$ctx,#$Doff+$lo] + ldr $t3, [$ctx,#$Doff+$hi] + str $Tlo,[sp,#$Boff+0] + str $Thi,[sp,#$Boff+4] + str $t0, [sp,#$Coff+0] + str $t1, [sp,#$Coff+4] + str $t2, [sp,#$Doff+0] + str $t3, [sp,#$Doff+4] + ldr $Tlo,[$ctx,#$Foff+$lo] + ldr $Thi,[$ctx,#$Foff+$hi] + str $Tlo,[sp,#$Foff+0] + str $Thi,[sp,#$Foff+4] + +.L00_15: +#if __ARM_ARCH__<7 + ldrb $Tlo,[$inp,#7] + ldrb $t0, [$inp,#6] + ldrb $t1, [$inp,#5] + ldrb $t2, [$inp,#4] + ldrb $Thi,[$inp,#3] + ldrb $t3, [$inp,#2] + orr $Tlo,$Tlo,$t0,lsl#8 + ldrb $t0, [$inp,#1] + orr $Tlo,$Tlo,$t1,lsl#16 + ldrb $t1, [$inp],#8 + orr $Tlo,$Tlo,$t2,lsl#24 + orr $Thi,$Thi,$t3,lsl#8 + orr $Thi,$Thi,$t0,lsl#16 + orr $Thi,$Thi,$t1,lsl#24 +#else + ldr $Tlo,[$inp,#4] + ldr $Thi,[$inp],#8 +#ifdef __ARMEL__ + rev $Tlo,$Tlo + rev $Thi,$Thi +#endif +#endif +___ + &BODY_00_15(0x94); +$code.=<<___; + tst $Ktbl,#1 + beq .L00_15 + ldr $t0,[sp,#`$Xoff+8*(16-1)`+0] + ldr $t1,[sp,#`$Xoff+8*(16-1)`+4] + bic $Ktbl,$Ktbl,#1 +.L16_79: + @ sigma0(x) (ROTR((x),1) ^ ROTR((x),8) ^ ((x)>>7)) + @ LO lo>>1^hi<<31 ^ lo>>8^hi<<24 ^ lo>>7^hi<<25 + @ HI hi>>1^lo<<31 ^ hi>>8^lo<<24 ^ hi>>7 + mov $Tlo,$t0,lsr#1 + ldr $t2,[sp,#`$Xoff+8*(16-14)`+0] + mov $Thi,$t1,lsr#1 + ldr $t3,[sp,#`$Xoff+8*(16-14)`+4] + eor $Tlo,$Tlo,$t1,lsl#31 + eor $Thi,$Thi,$t0,lsl#31 + eor $Tlo,$Tlo,$t0,lsr#8 + eor $Thi,$Thi,$t1,lsr#8 + eor $Tlo,$Tlo,$t1,lsl#24 + eor $Thi,$Thi,$t0,lsl#24 + eor $Tlo,$Tlo,$t0,lsr#7 + eor $Thi,$Thi,$t1,lsr#7 + eor $Tlo,$Tlo,$t1,lsl#25 + + @ sigma1(x) (ROTR((x),19) ^ ROTR((x),61) ^ ((x)>>6)) + @ LO lo>>19^hi<<13 ^ hi>>29^lo<<3 ^ lo>>6^hi<<26 + @ HI hi>>19^lo<<13 ^ lo>>29^hi<<3 ^ hi>>6 + mov $t0,$t2,lsr#19 + mov $t1,$t3,lsr#19 + eor $t0,$t0,$t3,lsl#13 + eor $t1,$t1,$t2,lsl#13 + eor $t0,$t0,$t3,lsr#29 + eor $t1,$t1,$t2,lsr#29 + eor $t0,$t0,$t2,lsl#3 + eor $t1,$t1,$t3,lsl#3 + eor $t0,$t0,$t2,lsr#6 + eor $t1,$t1,$t3,lsr#6 + ldr $t2,[sp,#`$Xoff+8*(16-9)`+0] + eor $t0,$t0,$t3,lsl#26 + + ldr $t3,[sp,#`$Xoff+8*(16-9)`+4] + adds $Tlo,$Tlo,$t0 + ldr $t0,[sp,#`$Xoff+8*16`+0] + adc $Thi,$Thi,$t1 + + ldr $t1,[sp,#`$Xoff+8*16`+4] + adds $Tlo,$Tlo,$t2 + adc $Thi,$Thi,$t3 + adds $Tlo,$Tlo,$t0 + adc $Thi,$Thi,$t1 +___ + &BODY_00_15(0x17); +$code.=<<___; +#if __ARM_ARCH__>=7 + ittt eq @ Thumb2 thing, sanity check in ARM +#endif + ldreq $t0,[sp,#`$Xoff+8*(16-1)`+0] + ldreq $t1,[sp,#`$Xoff+8*(16-1)`+4] + beq .L16_79 + bic $Ktbl,$Ktbl,#1 + + ldr $Tlo,[sp,#$Boff+0] + ldr $Thi,[sp,#$Boff+4] + ldr $t0, [$ctx,#$Aoff+$lo] + ldr $t1, [$ctx,#$Aoff+$hi] + ldr $t2, [$ctx,#$Boff+$lo] + ldr $t3, [$ctx,#$Boff+$hi] + adds $t0,$Alo,$t0 + str $t0, [$ctx,#$Aoff+$lo] + adc $t1,$Ahi,$t1 + str $t1, [$ctx,#$Aoff+$hi] + adds $t2,$Tlo,$t2 + str $t2, [$ctx,#$Boff+$lo] + adc $t3,$Thi,$t3 + str $t3, [$ctx,#$Boff+$hi] + + ldr $Alo,[sp,#$Coff+0] + ldr $Ahi,[sp,#$Coff+4] + ldr $Tlo,[sp,#$Doff+0] + ldr $Thi,[sp,#$Doff+4] + ldr $t0, [$ctx,#$Coff+$lo] + ldr $t1, [$ctx,#$Coff+$hi] + ldr $t2, [$ctx,#$Doff+$lo] + ldr $t3, [$ctx,#$Doff+$hi] + adds $t0,$Alo,$t0 + str $t0, [$ctx,#$Coff+$lo] + adc $t1,$Ahi,$t1 + str $t1, [$ctx,#$Coff+$hi] + adds $t2,$Tlo,$t2 + str $t2, [$ctx,#$Doff+$lo] + adc $t3,$Thi,$t3 + str $t3, [$ctx,#$Doff+$hi] + + ldr $Tlo,[sp,#$Foff+0] + ldr $Thi,[sp,#$Foff+4] + ldr $t0, [$ctx,#$Eoff+$lo] + ldr $t1, [$ctx,#$Eoff+$hi] + ldr $t2, [$ctx,#$Foff+$lo] + ldr $t3, [$ctx,#$Foff+$hi] + adds $Elo,$Elo,$t0 + str $Elo,[$ctx,#$Eoff+$lo] + adc $Ehi,$Ehi,$t1 + str $Ehi,[$ctx,#$Eoff+$hi] + adds $t2,$Tlo,$t2 + str $t2, [$ctx,#$Foff+$lo] + adc $t3,$Thi,$t3 + str $t3, [$ctx,#$Foff+$hi] + + ldr $Alo,[sp,#$Goff+0] + ldr $Ahi,[sp,#$Goff+4] + ldr $Tlo,[sp,#$Hoff+0] + ldr $Thi,[sp,#$Hoff+4] + ldr $t0, [$ctx,#$Goff+$lo] + ldr $t1, [$ctx,#$Goff+$hi] + ldr $t2, [$ctx,#$Hoff+$lo] + ldr $t3, [$ctx,#$Hoff+$hi] + adds $t0,$Alo,$t0 + str $t0, [$ctx,#$Goff+$lo] + adc $t1,$Ahi,$t1 + str $t1, [$ctx,#$Goff+$hi] + adds $t2,$Tlo,$t2 + str $t2, [$ctx,#$Hoff+$lo] + adc $t3,$Thi,$t3 + str $t3, [$ctx,#$Hoff+$hi] + + add sp,sp,#640 + sub $Ktbl,$Ktbl,#640 + + teq $inp,$len + bne .Loop + + add sp,sp,#8*9 @ destroy frame +#if __ARM_ARCH__>=5 + ldmia sp!,{r4-r12,pc} +#else + ldmia sp!,{r4-r12,lr} + tst lr,#1 + moveq pc,lr @ be binary compatible with V4, yet + bx lr @ interoperable with Thumb ISA:-) +#endif +.size sha512_block_data_order,.-sha512_block_data_order +___ + +{ +my @Sigma0=(28,34,39); +my @Sigma1=(14,18,41); +my @sigma0=(1, 8, 7); +my @sigma1=(19,61,6); + +my $Ktbl="r3"; +my $cnt="r12"; # volatile register known as ip, intra-procedure-call scratch + +my @X=map("d$_",(0..15)); +my @V=($A,$B,$C,$D,$E,$F,$G,$H)=map("d$_",(16..23)); + +sub NEON_00_15() { +my $i=shift; +my ($a,$b,$c,$d,$e,$f,$g,$h)=@_; +my ($t0,$t1,$t2,$T1,$K,$Ch,$Maj)=map("d$_",(24..31)); # temps + +$code.=<<___ if ($i<16 || $i&1); + vshr.u64 $t0,$e,#@Sigma1[0] @ $i +#if $i<16 + vld1.64 {@X[$i%16]},[$inp]! @ handles unaligned +#endif + vshr.u64 $t1,$e,#@Sigma1[1] +#if $i>0 + vadd.i64 $a,$Maj @ h+=Maj from the past +#endif + vshr.u64 $t2,$e,#@Sigma1[2] +___ +$code.=<<___; + vld1.64 {$K},[$Ktbl,:64]! @ K[i++] + vsli.64 $t0,$e,#`64-@Sigma1[0]` + vsli.64 $t1,$e,#`64-@Sigma1[1]` + vmov $Ch,$e + vsli.64 $t2,$e,#`64-@Sigma1[2]` +#if $i<16 && defined(__ARMEL__) + vrev64.8 @X[$i],@X[$i] +#endif + veor $t1,$t0 + vbsl $Ch,$f,$g @ Ch(e,f,g) + vshr.u64 $t0,$a,#@Sigma0[0] + veor $t2,$t1 @ Sigma1(e) + vadd.i64 $T1,$Ch,$h + vshr.u64 $t1,$a,#@Sigma0[1] + vsli.64 $t0,$a,#`64-@Sigma0[0]` + vadd.i64 $T1,$t2 + vshr.u64 $t2,$a,#@Sigma0[2] + vadd.i64 $K,@X[$i%16] + vsli.64 $t1,$a,#`64-@Sigma0[1]` + veor $Maj,$a,$b + vsli.64 $t2,$a,#`64-@Sigma0[2]` + veor $h,$t0,$t1 + vadd.i64 $T1,$K + vbsl $Maj,$c,$b @ Maj(a,b,c) + veor $h,$t2 @ Sigma0(a) + vadd.i64 $d,$T1 + vadd.i64 $Maj,$T1 + @ vadd.i64 $h,$Maj +___ +} + +sub NEON_16_79() { +my $i=shift; + +if ($i&1) { &NEON_00_15($i,@_); return; } + +# 2x-vectorized, therefore runs every 2nd round +my @X=map("q$_",(0..7)); # view @X as 128-bit vector +my ($t0,$t1,$s0,$s1) = map("q$_",(12..15)); # temps +my ($d0,$d1,$d2) = map("d$_",(24..26)); # temps from NEON_00_15 +my $e=@_[4]; # $e from NEON_00_15 +$i /= 2; +$code.=<<___; + vshr.u64 $t0,@X[($i+7)%8],#@sigma1[0] + vshr.u64 $t1,@X[($i+7)%8],#@sigma1[1] + vadd.i64 @_[0],d30 @ h+=Maj from the past + vshr.u64 $s1,@X[($i+7)%8],#@sigma1[2] + vsli.64 $t0,@X[($i+7)%8],#`64-@sigma1[0]` + vext.8 $s0,@X[$i%8],@X[($i+1)%8],#8 @ X[i+1] + vsli.64 $t1,@X[($i+7)%8],#`64-@sigma1[1]` + veor $s1,$t0 + vshr.u64 $t0,$s0,#@sigma0[0] + veor $s1,$t1 @ sigma1(X[i+14]) + vshr.u64 $t1,$s0,#@sigma0[1] + vadd.i64 @X[$i%8],$s1 + vshr.u64 $s1,$s0,#@sigma0[2] + vsli.64 $t0,$s0,#`64-@sigma0[0]` + vsli.64 $t1,$s0,#`64-@sigma0[1]` + vext.8 $s0,@X[($i+4)%8],@X[($i+5)%8],#8 @ X[i+9] + veor $s1,$t0 + vshr.u64 $d0,$e,#@Sigma1[0] @ from NEON_00_15 + vadd.i64 @X[$i%8],$s0 + vshr.u64 $d1,$e,#@Sigma1[1] @ from NEON_00_15 + veor $s1,$t1 @ sigma0(X[i+1]) + vshr.u64 $d2,$e,#@Sigma1[2] @ from NEON_00_15 + vadd.i64 @X[$i%8],$s1 +___ + &NEON_00_15(2*$i,@_); +} + +$code.=<<___; +#if __ARM_MAX_ARCH__>=7 +.arch armv7-a +.fpu neon + +.global sha512_block_data_order_neon +.type sha512_block_data_order_neon,%function +.align 4 +sha512_block_data_order_neon: +.LNEON: + dmb @ errata #451034 on early Cortex A8 + add $len,$inp,$len,lsl#7 @ len to point at the end of inp + adr $Ktbl,K512 + VFP_ABI_PUSH + vldmia $ctx,{$A-$H} @ load context +.Loop_neon: +___ +for($i=0;$i<16;$i++) { &NEON_00_15($i,@V); unshift(@V,pop(@V)); } +$code.=<<___; + mov $cnt,#4 +.L16_79_neon: + subs $cnt,#1 +___ +for(;$i<32;$i++) { &NEON_16_79($i,@V); unshift(@V,pop(@V)); } +$code.=<<___; + bne .L16_79_neon + + vadd.i64 $A,d30 @ h+=Maj from the past + vldmia $ctx,{d24-d31} @ load context to temp + vadd.i64 q8,q12 @ vectorized accumulate + vadd.i64 q9,q13 + vadd.i64 q10,q14 + vadd.i64 q11,q15 + vstmia $ctx,{$A-$H} @ save context + teq $inp,$len + sub $Ktbl,#640 @ rewind K512 + bne .Loop_neon + + VFP_ABI_POP + ret @ bx lr +.size sha512_block_data_order_neon,.-sha512_block_data_order_neon +#endif +___ +} +$code.=<<___; +.asciz "SHA512 block transform for ARMv4/NEON, CRYPTOGAMS by " +.align 2 +#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__) +.comm OPENSSL_armcap_P,4,4 +.hidden OPENSSL_armcap_P +#endif +___ + +$code =~ s/\`([^\`]*)\`/eval $1/gem; +$code =~ s/\bbx\s+lr\b/.word\t0xe12fff1e/gm; # make it possible to compile with -march=armv4 +$code =~ s/\bret\b/bx lr/gm; + +open SELF,$0; +while() { + next if (/^#!/); + last if (!s/^#/@/ and !/^$/); + print; +} +close SELF; + +print $code; +close STDOUT; # enforce flush diff --git a/external/boringssl/crypto/sha/asm/sha512-armv8.pl b/external/boringssl/crypto/sha/asm/sha512-armv8.pl new file mode 100644 index 0000000000..40eb17a711 --- /dev/null +++ b/external/boringssl/crypto/sha/asm/sha512-armv8.pl @@ -0,0 +1,436 @@ +#!/usr/bin/env perl +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# SHA256/512 for ARMv8. +# +# Performance in cycles per processed byte and improvement coefficient +# over code generated with "default" compiler: +# +# SHA256-hw SHA256(*) SHA512 +# Apple A7 1.97 10.5 (+33%) 6.73 (-1%(**)) +# Cortex-A53 2.38 15.5 (+115%) 10.0 (+150%(***)) +# Cortex-A57 2.31 11.6 (+86%) 7.51 (+260%(***)) +# Denver 2.01 10.5 (+26%) 6.70 (+8%) +# X-Gene 20.0 (+100%) 12.8 (+300%(***)) +# +# (*) Software SHA256 results are of lesser relevance, presented +# mostly for informational purposes. +# (**) The result is a trade-off: it's possible to improve it by +# 10% (or by 1 cycle per round), but at the cost of 20% loss +# on Cortex-A53 (or by 4 cycles per round). +# (***) Super-impressive coefficients over gcc-generated code are +# indication of some compiler "pathology", most notably code +# generated with -mgeneral-regs-only is significanty faster +# and the gap is only 40-90%. + +$flavour=shift; +# Unlike most perlasm files, sha512-armv8.pl takes an additional argument to +# determine which hash function to emit. This differs from upstream OpenSSL so +# that the script may continue to output to stdout. +$variant=shift; +$output=shift; + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or +die "can't locate arm-xlate.pl"; + +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; + +if ($variant eq "sha512") { + $BITS=512; + $SZ=8; + @Sigma0=(28,34,39); + @Sigma1=(14,18,41); + @sigma0=(1, 8, 7); + @sigma1=(19,61, 6); + $rounds=80; + $reg_t="x"; +} elsif ($variant eq "sha256") { + $BITS=256; + $SZ=4; + @Sigma0=( 2,13,22); + @Sigma1=( 6,11,25); + @sigma0=( 7,18, 3); + @sigma1=(17,19,10); + $rounds=64; + $reg_t="w"; +} else { + die "Unknown variant: $variant"; +} + +$func="sha${BITS}_block_data_order"; + +($ctx,$inp,$num,$Ktbl)=map("x$_",(0..2,30)); + +@X=map("$reg_t$_",(3..15,0..2)); +@V=($A,$B,$C,$D,$E,$F,$G,$H)=map("$reg_t$_",(20..27)); +($t0,$t1,$t2,$t3)=map("$reg_t$_",(16,17,19,28)); + +sub BODY_00_xx { +my ($i,$a,$b,$c,$d,$e,$f,$g,$h)=@_; +my $j=($i+1)&15; +my ($T0,$T1,$T2)=(@X[($i-8)&15],@X[($i-9)&15],@X[($i-10)&15]); + $T0=@X[$i+3] if ($i<11); + +$code.=<<___ if ($i<16); +#ifndef __ARMEB__ + rev @X[$i],@X[$i] // $i +#endif +___ +$code.=<<___ if ($i<13 && ($i&1)); + ldp @X[$i+1],@X[$i+2],[$inp],#2*$SZ +___ +$code.=<<___ if ($i==13); + ldp @X[14],@X[15],[$inp] +___ +$code.=<<___ if ($i>=14); + ldr @X[($i-11)&15],[sp,#`$SZ*(($i-11)%4)`] +___ +$code.=<<___ if ($i>0 && $i<16); + add $a,$a,$t1 // h+=Sigma0(a) +___ +$code.=<<___ if ($i>=11); + str @X[($i-8)&15],[sp,#`$SZ*(($i-8)%4)`] +___ +# While ARMv8 specifies merged rotate-n-logical operation such as +# 'eor x,y,z,ror#n', it was found to negatively affect performance +# on Apple A7. The reason seems to be that it requires even 'y' to +# be available earlier. This means that such merged instruction is +# not necessarily best choice on critical path... On the other hand +# Cortex-A5x handles merged instructions much better than disjoint +# rotate and logical... See (**) footnote above. +$code.=<<___ if ($i<15); + ror $t0,$e,#$Sigma1[0] + add $h,$h,$t2 // h+=K[i] + eor $T0,$e,$e,ror#`$Sigma1[2]-$Sigma1[1]` + and $t1,$f,$e + bic $t2,$g,$e + add $h,$h,@X[$i&15] // h+=X[i] + orr $t1,$t1,$t2 // Ch(e,f,g) + eor $t2,$a,$b // a^b, b^c in next round + eor $t0,$t0,$T0,ror#$Sigma1[1] // Sigma1(e) + ror $T0,$a,#$Sigma0[0] + add $h,$h,$t1 // h+=Ch(e,f,g) + eor $t1,$a,$a,ror#`$Sigma0[2]-$Sigma0[1]` + add $h,$h,$t0 // h+=Sigma1(e) + and $t3,$t3,$t2 // (b^c)&=(a^b) + add $d,$d,$h // d+=h + eor $t3,$t3,$b // Maj(a,b,c) + eor $t1,$T0,$t1,ror#$Sigma0[1] // Sigma0(a) + add $h,$h,$t3 // h+=Maj(a,b,c) + ldr $t3,[$Ktbl],#$SZ // *K++, $t2 in next round + //add $h,$h,$t1 // h+=Sigma0(a) +___ +$code.=<<___ if ($i>=15); + ror $t0,$e,#$Sigma1[0] + add $h,$h,$t2 // h+=K[i] + ror $T1,@X[($j+1)&15],#$sigma0[0] + and $t1,$f,$e + ror $T2,@X[($j+14)&15],#$sigma1[0] + bic $t2,$g,$e + ror $T0,$a,#$Sigma0[0] + add $h,$h,@X[$i&15] // h+=X[i] + eor $t0,$t0,$e,ror#$Sigma1[1] + eor $T1,$T1,@X[($j+1)&15],ror#$sigma0[1] + orr $t1,$t1,$t2 // Ch(e,f,g) + eor $t2,$a,$b // a^b, b^c in next round + eor $t0,$t0,$e,ror#$Sigma1[2] // Sigma1(e) + eor $T0,$T0,$a,ror#$Sigma0[1] + add $h,$h,$t1 // h+=Ch(e,f,g) + and $t3,$t3,$t2 // (b^c)&=(a^b) + eor $T2,$T2,@X[($j+14)&15],ror#$sigma1[1] + eor $T1,$T1,@X[($j+1)&15],lsr#$sigma0[2] // sigma0(X[i+1]) + add $h,$h,$t0 // h+=Sigma1(e) + eor $t3,$t3,$b // Maj(a,b,c) + eor $t1,$T0,$a,ror#$Sigma0[2] // Sigma0(a) + eor $T2,$T2,@X[($j+14)&15],lsr#$sigma1[2] // sigma1(X[i+14]) + add @X[$j],@X[$j],@X[($j+9)&15] + add $d,$d,$h // d+=h + add $h,$h,$t3 // h+=Maj(a,b,c) + ldr $t3,[$Ktbl],#$SZ // *K++, $t2 in next round + add @X[$j],@X[$j],$T1 + add $h,$h,$t1 // h+=Sigma0(a) + add @X[$j],@X[$j],$T2 +___ + ($t2,$t3)=($t3,$t2); +} + +$code.=<<___; +#include + +.text + +.extern OPENSSL_armcap_P +.globl $func +.type $func,%function +.align 6 +$func: +___ +$code.=<<___ if ($SZ==4); + ldr x16,.LOPENSSL_armcap_P + adr x17,.LOPENSSL_armcap_P + add x16,x16,x17 + ldr w16,[x16] + tst w16,#ARMV8_SHA256 + b.ne .Lv8_entry +___ +$code.=<<___; + stp x29,x30,[sp,#-128]! + add x29,sp,#0 + + stp x19,x20,[sp,#16] + stp x21,x22,[sp,#32] + stp x23,x24,[sp,#48] + stp x25,x26,[sp,#64] + stp x27,x28,[sp,#80] + sub sp,sp,#4*$SZ + + ldp $A,$B,[$ctx] // load context + ldp $C,$D,[$ctx,#2*$SZ] + ldp $E,$F,[$ctx,#4*$SZ] + add $num,$inp,$num,lsl#`log(16*$SZ)/log(2)` // end of input + ldp $G,$H,[$ctx,#6*$SZ] + adr $Ktbl,.LK$BITS + stp $ctx,$num,[x29,#96] + +.Loop: + ldp @X[0],@X[1],[$inp],#2*$SZ + ldr $t2,[$Ktbl],#$SZ // *K++ + eor $t3,$B,$C // magic seed + str $inp,[x29,#112] +___ +for ($i=0;$i<16;$i++) { &BODY_00_xx($i,@V); unshift(@V,pop(@V)); } +$code.=".Loop_16_xx:\n"; +for (;$i<32;$i++) { &BODY_00_xx($i,@V); unshift(@V,pop(@V)); } +$code.=<<___; + cbnz $t2,.Loop_16_xx + + ldp $ctx,$num,[x29,#96] + ldr $inp,[x29,#112] + sub $Ktbl,$Ktbl,#`$SZ*($rounds+1)` // rewind + + ldp @X[0],@X[1],[$ctx] + ldp @X[2],@X[3],[$ctx,#2*$SZ] + add $inp,$inp,#14*$SZ // advance input pointer + ldp @X[4],@X[5],[$ctx,#4*$SZ] + add $A,$A,@X[0] + ldp @X[6],@X[7],[$ctx,#6*$SZ] + add $B,$B,@X[1] + add $C,$C,@X[2] + add $D,$D,@X[3] + stp $A,$B,[$ctx] + add $E,$E,@X[4] + add $F,$F,@X[5] + stp $C,$D,[$ctx,#2*$SZ] + add $G,$G,@X[6] + add $H,$H,@X[7] + cmp $inp,$num + stp $E,$F,[$ctx,#4*$SZ] + stp $G,$H,[$ctx,#6*$SZ] + b.ne .Loop + + ldp x19,x20,[x29,#16] + add sp,sp,#4*$SZ + ldp x21,x22,[x29,#32] + ldp x23,x24,[x29,#48] + ldp x25,x26,[x29,#64] + ldp x27,x28,[x29,#80] + ldp x29,x30,[sp],#128 + ret +.size $func,.-$func + +.align 6 +.type .LK$BITS,%object +.LK$BITS: +___ +$code.=<<___ if ($SZ==8); + .quad 0x428a2f98d728ae22,0x7137449123ef65cd + .quad 0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc + .quad 0x3956c25bf348b538,0x59f111f1b605d019 + .quad 0x923f82a4af194f9b,0xab1c5ed5da6d8118 + .quad 0xd807aa98a3030242,0x12835b0145706fbe + .quad 0x243185be4ee4b28c,0x550c7dc3d5ffb4e2 + .quad 0x72be5d74f27b896f,0x80deb1fe3b1696b1 + .quad 0x9bdc06a725c71235,0xc19bf174cf692694 + .quad 0xe49b69c19ef14ad2,0xefbe4786384f25e3 + .quad 0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65 + .quad 0x2de92c6f592b0275,0x4a7484aa6ea6e483 + .quad 0x5cb0a9dcbd41fbd4,0x76f988da831153b5 + .quad 0x983e5152ee66dfab,0xa831c66d2db43210 + .quad 0xb00327c898fb213f,0xbf597fc7beef0ee4 + .quad 0xc6e00bf33da88fc2,0xd5a79147930aa725 + .quad 0x06ca6351e003826f,0x142929670a0e6e70 + .quad 0x27b70a8546d22ffc,0x2e1b21385c26c926 + .quad 0x4d2c6dfc5ac42aed,0x53380d139d95b3df + .quad 0x650a73548baf63de,0x766a0abb3c77b2a8 + .quad 0x81c2c92e47edaee6,0x92722c851482353b + .quad 0xa2bfe8a14cf10364,0xa81a664bbc423001 + .quad 0xc24b8b70d0f89791,0xc76c51a30654be30 + .quad 0xd192e819d6ef5218,0xd69906245565a910 + .quad 0xf40e35855771202a,0x106aa07032bbd1b8 + .quad 0x19a4c116b8d2d0c8,0x1e376c085141ab53 + .quad 0x2748774cdf8eeb99,0x34b0bcb5e19b48a8 + .quad 0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb + .quad 0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3 + .quad 0x748f82ee5defb2fc,0x78a5636f43172f60 + .quad 0x84c87814a1f0ab72,0x8cc702081a6439ec + .quad 0x90befffa23631e28,0xa4506cebde82bde9 + .quad 0xbef9a3f7b2c67915,0xc67178f2e372532b + .quad 0xca273eceea26619c,0xd186b8c721c0c207 + .quad 0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178 + .quad 0x06f067aa72176fba,0x0a637dc5a2c898a6 + .quad 0x113f9804bef90dae,0x1b710b35131c471b + .quad 0x28db77f523047d84,0x32caab7b40c72493 + .quad 0x3c9ebe0a15c9bebc,0x431d67c49c100d4c + .quad 0x4cc5d4becb3e42b6,0x597f299cfc657e2a + .quad 0x5fcb6fab3ad6faec,0x6c44198c4a475817 + .quad 0 // terminator +___ +$code.=<<___ if ($SZ==4); + .long 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5 + .long 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5 + .long 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3 + .long 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174 + .long 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc + .long 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da + .long 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7 + .long 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967 + .long 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13 + .long 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85 + .long 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3 + .long 0xd192e819,0xd6990624,0xf40e3585,0x106aa070 + .long 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5 + .long 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3 + .long 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208 + .long 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 + .long 0 //terminator +___ +$code.=<<___; +.size .LK$BITS,.-.LK$BITS +.align 3 +.LOPENSSL_armcap_P: + .quad OPENSSL_armcap_P-. +.asciz "SHA$BITS block transform for ARMv8, CRYPTOGAMS by " +.align 2 +___ + +if ($SZ==4) { +my $Ktbl="x3"; + +my ($ABCD,$EFGH,$abcd)=map("v$_.16b",(0..2)); +my @MSG=map("v$_.16b",(4..7)); +my ($W0,$W1)=("v16.4s","v17.4s"); +my ($ABCD_SAVE,$EFGH_SAVE)=("v18.16b","v19.16b"); + +$code.=<<___; +.type sha256_block_armv8,%function +.align 6 +sha256_block_armv8: +.Lv8_entry: + stp x29,x30,[sp,#-16]! + add x29,sp,#0 + + ld1.32 {$ABCD,$EFGH},[$ctx] + adr $Ktbl,.LK256 + +.Loop_hw: + ld1 {@MSG[0]-@MSG[3]},[$inp],#64 + sub $num,$num,#1 + ld1.32 {$W0},[$Ktbl],#16 + rev32 @MSG[0],@MSG[0] + rev32 @MSG[1],@MSG[1] + rev32 @MSG[2],@MSG[2] + rev32 @MSG[3],@MSG[3] + orr $ABCD_SAVE,$ABCD,$ABCD // offload + orr $EFGH_SAVE,$EFGH,$EFGH +___ +for($i=0;$i<12;$i++) { +$code.=<<___; + ld1.32 {$W1},[$Ktbl],#16 + add.i32 $W0,$W0,@MSG[0] + sha256su0 @MSG[0],@MSG[1] + orr $abcd,$ABCD,$ABCD + sha256h $ABCD,$EFGH,$W0 + sha256h2 $EFGH,$abcd,$W0 + sha256su1 @MSG[0],@MSG[2],@MSG[3] +___ + ($W0,$W1)=($W1,$W0); push(@MSG,shift(@MSG)); +} +$code.=<<___; + ld1.32 {$W1},[$Ktbl],#16 + add.i32 $W0,$W0,@MSG[0] + orr $abcd,$ABCD,$ABCD + sha256h $ABCD,$EFGH,$W0 + sha256h2 $EFGH,$abcd,$W0 + + ld1.32 {$W0},[$Ktbl],#16 + add.i32 $W1,$W1,@MSG[1] + orr $abcd,$ABCD,$ABCD + sha256h $ABCD,$EFGH,$W1 + sha256h2 $EFGH,$abcd,$W1 + + ld1.32 {$W1},[$Ktbl] + add.i32 $W0,$W0,@MSG[2] + sub $Ktbl,$Ktbl,#$rounds*$SZ-16 // rewind + orr $abcd,$ABCD,$ABCD + sha256h $ABCD,$EFGH,$W0 + sha256h2 $EFGH,$abcd,$W0 + + add.i32 $W1,$W1,@MSG[3] + orr $abcd,$ABCD,$ABCD + sha256h $ABCD,$EFGH,$W1 + sha256h2 $EFGH,$abcd,$W1 + + add.i32 $ABCD,$ABCD,$ABCD_SAVE + add.i32 $EFGH,$EFGH,$EFGH_SAVE + + cbnz $num,.Loop_hw + + st1.32 {$ABCD,$EFGH},[$ctx] + + ldr x29,[sp],#16 + ret +.size sha256_block_armv8,.-sha256_block_armv8 +___ +} + +$code.=<<___; +.comm OPENSSL_armcap_P,4,4 +___ + +{ my %opcode = ( + "sha256h" => 0x5e004000, "sha256h2" => 0x5e005000, + "sha256su0" => 0x5e282800, "sha256su1" => 0x5e006000 ); + + sub unsha256 { + my ($mnemonic,$arg)=@_; + + $arg =~ m/[qv]([0-9]+)[^,]*,\s*[qv]([0-9]+)[^,]*(?:,\s*[qv]([0-9]+))?/o + && + sprintf ".inst\t0x%08x\t//%s %s", + $opcode{$mnemonic}|$1|($2<<5)|($3<<16), + $mnemonic,$arg; + } +} + +foreach(split("\n",$code)) { + + s/\`([^\`]*)\`/eval($1)/geo; + + s/\b(sha256\w+)\s+([qv].*)/unsha256($1,$2)/geo; + + s/\.\w?32\b//o and s/\.16b/\.4s/go; + m/(ld|st)1[^\[]+\[0\]/o and s/\.4s/\.s/go; + + print $_,"\n"; +} + +close STDOUT; diff --git a/external/boringssl/crypto/sha/asm/sha512-x86_64.pl b/external/boringssl/crypto/sha/asm/sha512-x86_64.pl new file mode 100644 index 0000000000..2bc33c65a6 --- /dev/null +++ b/external/boringssl/crypto/sha/asm/sha512-x86_64.pl @@ -0,0 +1,2390 @@ +#!/usr/bin/env perl +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. Rights for redistribution and usage in source and binary +# forms are granted according to the OpenSSL license. +# ==================================================================== +# +# sha256/512_block procedure for x86_64. +# +# 40% improvement over compiler-generated code on Opteron. On EM64T +# sha256 was observed to run >80% faster and sha512 - >40%. No magical +# tricks, just straight implementation... I really wonder why gcc +# [being armed with inline assembler] fails to generate as fast code. +# The only thing which is cool about this module is that it's very +# same instruction sequence used for both SHA-256 and SHA-512. In +# former case the instructions operate on 32-bit operands, while in +# latter - on 64-bit ones. All I had to do is to get one flavor right, +# the other one passed the test right away:-) +# +# sha256_block runs in ~1005 cycles on Opteron, which gives you +# asymptotic performance of 64*1000/1005=63.7MBps times CPU clock +# frequency in GHz. sha512_block runs in ~1275 cycles, which results +# in 128*1000/1275=100MBps per GHz. Is there room for improvement? +# Well, if you compare it to IA-64 implementation, which maintains +# X[16] in register bank[!], tends to 4 instructions per CPU clock +# cycle and runs in 1003 cycles, 1275 is very good result for 3-way +# issue Opteron pipeline and X[16] maintained in memory. So that *if* +# there is a way to improve it, *then* the only way would be to try to +# offload X[16] updates to SSE unit, but that would require "deeper" +# loop unroll, which in turn would naturally cause size blow-up, not +# to mention increased complexity! And once again, only *if* it's +# actually possible to noticeably improve overall ILP, instruction +# level parallelism, on a given CPU implementation in this case. +# +# Special note on Intel EM64T. While Opteron CPU exhibits perfect +# perfromance ratio of 1.5 between 64- and 32-bit flavors [see above], +# [currently available] EM64T CPUs apparently are far from it. On the +# contrary, 64-bit version, sha512_block, is ~30% *slower* than 32-bit +# sha256_block:-( This is presumably because 64-bit shifts/rotates +# apparently are not atomic instructions, but implemented in microcode. +# +# May 2012. +# +# Optimization including one of Pavel Semjanov's ideas, alternative +# Maj, resulted in >=5% improvement on most CPUs, +20% SHA256 and +# unfortunately -2% SHA512 on P4 [which nobody should care about +# that much]. +# +# June 2012. +# +# Add SIMD code paths, see below for improvement coefficients. SSSE3 +# code path was not attempted for SHA512, because improvement is not +# estimated to be high enough, noticeably less than 9%, to justify +# the effort, not on pre-AVX processors. [Obviously with exclusion +# for VIA Nano, but it has SHA512 instruction that is faster and +# should be used instead.] For reference, corresponding estimated +# upper limit for improvement for SSSE3 SHA256 is 28%. The fact that +# higher coefficients are observed on VIA Nano and Bulldozer has more +# to do with specifics of their architecture [which is topic for +# separate discussion]. +# +# November 2012. +# +# Add AVX2 code path. Two consecutive input blocks are loaded to +# 256-bit %ymm registers, with data from first block to least +# significant 128-bit halves and data from second to most significant. +# The data is then processed with same SIMD instruction sequence as +# for AVX, but with %ymm as operands. Side effect is increased stack +# frame, 448 additional bytes in SHA256 and 1152 in SHA512, and 1.2KB +# code size increase. +# +# March 2014. +# +# Add support for Intel SHA Extensions. + +###################################################################### +# Current performance in cycles per processed byte (less is better): +# +# SHA256 SSSE3 AVX/XOP(*) SHA512 AVX/XOP(*) +# +# AMD K8 14.9 - - 9.57 - +# P4 17.3 - - 30.8 - +# Core 2 15.6 13.8(+13%) - 9.97 - +# Westmere 14.8 12.3(+19%) - 9.58 - +# Sandy Bridge 17.4 14.2(+23%) 11.6(+50%(**)) 11.2 8.10(+38%(**)) +# Ivy Bridge 12.6 10.5(+20%) 10.3(+22%) 8.17 7.22(+13%) +# Haswell 12.2 9.28(+31%) 7.80(+56%) 7.66 5.40(+42%) +# Bulldozer 21.1 13.6(+54%) 13.6(+54%(***)) 13.5 8.58(+57%) +# VIA Nano 23.0 16.5(+39%) - 14.7 - +# Atom 23.0 18.9(+22%) - 14.7 - +# Silvermont 27.4 20.6(+33%) - 17.5 - +# +# (*) whichever best applicable; +# (**) switch from ror to shrd stands for fair share of improvement; +# (***) execution time is fully determined by remaining integer-only +# part, body_00_15; reducing the amount of SIMD instructions +# below certain limit makes no difference/sense; to conserve +# space SHA256 XOP code path is therefore omitted; + +$flavour = shift; +$output = shift; +if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } + +$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or +die "can't locate x86_64-xlate.pl"; + +# In upstream, this is controlled by shelling out to the compiler to check +# versions, but BoringSSL is intended to be used with pre-generated perlasm +# output, so this isn't useful anyway. +# +# TODO(davidben): Enable AVX2 code after testing by setting $avx to 2. Is it +# necessary to disable AVX2 code when SHA Extensions code is disabled? Upstream +# did not tie them together until after $shaext was added. +$avx = 1; + +# TODO(davidben): Consider enabling the Intel SHA Extensions code once it's +# been tested. +$shaext=0; ### set to zero if compiling for 1.0.1 +$avx=1 if (!$shaext && $avx); + +open OUT,"| \"$^X\" $xlate $flavour"; +*STDOUT=*OUT; + +if ($output =~ /512/) { + $func="sha512_block_data_order"; + $TABLE="K512"; + $SZ=8; + @ROT=($A,$B,$C,$D,$E,$F,$G,$H)=("%rax","%rbx","%rcx","%rdx", + "%r8", "%r9", "%r10","%r11"); + ($T1,$a0,$a1,$a2,$a3)=("%r12","%r13","%r14","%r15","%rdi"); + @Sigma0=(28,34,39); + @Sigma1=(14,18,41); + @sigma0=(1, 8, 7); + @sigma1=(19,61, 6); + $rounds=80; +} else { + $func="sha256_block_data_order"; + $TABLE="K256"; + $SZ=4; + @ROT=($A,$B,$C,$D,$E,$F,$G,$H)=("%eax","%ebx","%ecx","%edx", + "%r8d","%r9d","%r10d","%r11d"); + ($T1,$a0,$a1,$a2,$a3)=("%r12d","%r13d","%r14d","%r15d","%edi"); + @Sigma0=( 2,13,22); + @Sigma1=( 6,11,25); + @sigma0=( 7,18, 3); + @sigma1=(17,19,10); + $rounds=64; +} + +$ctx="%rdi"; # 1st arg, zapped by $a3 +$inp="%rsi"; # 2nd arg +$Tbl="%rbp"; + +$_ctx="16*$SZ+0*8(%rsp)"; +$_inp="16*$SZ+1*8(%rsp)"; +$_end="16*$SZ+2*8(%rsp)"; +$_rsp="16*$SZ+3*8(%rsp)"; +$framesz="16*$SZ+4*8"; + + +sub ROUND_00_15() +{ my ($i,$a,$b,$c,$d,$e,$f,$g,$h) = @_; + my $STRIDE=$SZ; + $STRIDE += 16 if ($i%(16/$SZ)==(16/$SZ-1)); + +$code.=<<___; + ror \$`$Sigma1[2]-$Sigma1[1]`,$a0 + mov $f,$a2 + + xor $e,$a0 + ror \$`$Sigma0[2]-$Sigma0[1]`,$a1 + xor $g,$a2 # f^g + + mov $T1,`$SZ*($i&0xf)`(%rsp) + xor $a,$a1 + and $e,$a2 # (f^g)&e + + ror \$`$Sigma1[1]-$Sigma1[0]`,$a0 + add $h,$T1 # T1+=h + xor $g,$a2 # Ch(e,f,g)=((f^g)&e)^g + + ror \$`$Sigma0[1]-$Sigma0[0]`,$a1 + xor $e,$a0 + add $a2,$T1 # T1+=Ch(e,f,g) + + mov $a,$a2 + add ($Tbl),$T1 # T1+=K[round] + xor $a,$a1 + + xor $b,$a2 # a^b, b^c in next round + ror \$$Sigma1[0],$a0 # Sigma1(e) + mov $b,$h + + and $a2,$a3 + ror \$$Sigma0[0],$a1 # Sigma0(a) + add $a0,$T1 # T1+=Sigma1(e) + + xor $a3,$h # h=Maj(a,b,c)=Ch(a^b,c,b) + add $T1,$d # d+=T1 + add $T1,$h # h+=T1 + + lea $STRIDE($Tbl),$Tbl # round++ +___ +$code.=<<___ if ($i<15); + add $a1,$h # h+=Sigma0(a) +___ + ($a2,$a3) = ($a3,$a2); +} + +sub ROUND_16_XX() +{ my ($i,$a,$b,$c,$d,$e,$f,$g,$h) = @_; + +$code.=<<___; + mov `$SZ*(($i+1)&0xf)`(%rsp),$a0 + mov `$SZ*(($i+14)&0xf)`(%rsp),$a2 + + mov $a0,$T1 + ror \$`$sigma0[1]-$sigma0[0]`,$a0 + add $a1,$a # modulo-scheduled h+=Sigma0(a) + mov $a2,$a1 + ror \$`$sigma1[1]-$sigma1[0]`,$a2 + + xor $T1,$a0 + shr \$$sigma0[2],$T1 + ror \$$sigma0[0],$a0 + xor $a1,$a2 + shr \$$sigma1[2],$a1 + + ror \$$sigma1[0],$a2 + xor $a0,$T1 # sigma0(X[(i+1)&0xf]) + xor $a1,$a2 # sigma1(X[(i+14)&0xf]) + add `$SZ*(($i+9)&0xf)`(%rsp),$T1 + + add `$SZ*($i&0xf)`(%rsp),$T1 + mov $e,$a0 + add $a2,$T1 + mov $a,$a1 +___ + &ROUND_00_15(@_); +} + +$code=<<___; +.text + +.extern OPENSSL_ia32cap_P +.globl $func +.type $func,\@function,3 +.align 16 +$func: +___ +$code.=<<___ if ($SZ==4 || $avx); + lea OPENSSL_ia32cap_P(%rip),%r11 + mov 0(%r11),%r9d + mov 4(%r11),%r10d + mov 8(%r11),%r11d +___ +$code.=<<___ if ($SZ==4 && $shaext); + test \$`1<<29`,%r11d # check for SHA + jnz _shaext_shortcut +___ +$code.=<<___ if ($avx && $SZ==8); + test \$`1<<11`,%r10d # check for XOP + jnz .Lxop_shortcut +___ +$code.=<<___ if ($avx>1); + and \$`1<<8|1<<5|1<<3`,%r11d # check for BMI2+AVX2+BMI1 + cmp \$`1<<8|1<<5|1<<3`,%r11d + je .Lavx2_shortcut +___ +$code.=<<___ if ($avx); + and \$`1<<30`,%r9d # mask "Intel CPU" bit + and \$`1<<28|1<<9`,%r10d # mask AVX and SSSE3 bits + or %r9d,%r10d + cmp \$`1<<28|1<<9|1<<30`,%r10d + je .Lavx_shortcut +___ +$code.=<<___ if ($SZ==4); + test \$`1<<9`,%r10d + jnz .Lssse3_shortcut +___ +$code.=<<___; + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + mov %rsp,%r11 # copy %rsp + shl \$4,%rdx # num*16 + sub \$$framesz,%rsp + lea ($inp,%rdx,$SZ),%rdx # inp+num*16*$SZ + and \$-64,%rsp # align stack frame + mov $ctx,$_ctx # save ctx, 1st arg + mov $inp,$_inp # save inp, 2nd arh + mov %rdx,$_end # save end pointer, "3rd" arg + mov %r11,$_rsp # save copy of %rsp +.Lprologue: + + mov $SZ*0($ctx),$A + mov $SZ*1($ctx),$B + mov $SZ*2($ctx),$C + mov $SZ*3($ctx),$D + mov $SZ*4($ctx),$E + mov $SZ*5($ctx),$F + mov $SZ*6($ctx),$G + mov $SZ*7($ctx),$H + jmp .Lloop + +.align 16 +.Lloop: + mov $B,$a3 + lea $TABLE(%rip),$Tbl + xor $C,$a3 # magic +___ + for($i=0;$i<16;$i++) { + $code.=" mov $SZ*$i($inp),$T1\n"; + $code.=" mov @ROT[4],$a0\n"; + $code.=" mov @ROT[0],$a1\n"; + $code.=" bswap $T1\n"; + &ROUND_00_15($i,@ROT); + unshift(@ROT,pop(@ROT)); + } +$code.=<<___; + jmp .Lrounds_16_xx +.align 16 +.Lrounds_16_xx: +___ + for(;$i<32;$i++) { + &ROUND_16_XX($i,@ROT); + unshift(@ROT,pop(@ROT)); + } + +$code.=<<___; + cmpb \$0,`$SZ-1`($Tbl) + jnz .Lrounds_16_xx + + mov $_ctx,$ctx + add $a1,$A # modulo-scheduled h+=Sigma0(a) + lea 16*$SZ($inp),$inp + + add $SZ*0($ctx),$A + add $SZ*1($ctx),$B + add $SZ*2($ctx),$C + add $SZ*3($ctx),$D + add $SZ*4($ctx),$E + add $SZ*5($ctx),$F + add $SZ*6($ctx),$G + add $SZ*7($ctx),$H + + cmp $_end,$inp + + mov $A,$SZ*0($ctx) + mov $B,$SZ*1($ctx) + mov $C,$SZ*2($ctx) + mov $D,$SZ*3($ctx) + mov $E,$SZ*4($ctx) + mov $F,$SZ*5($ctx) + mov $G,$SZ*6($ctx) + mov $H,$SZ*7($ctx) + jb .Lloop + + mov $_rsp,%rsi + mov (%rsi),%r15 + mov 8(%rsi),%r14 + mov 16(%rsi),%r13 + mov 24(%rsi),%r12 + mov 32(%rsi),%rbp + mov 40(%rsi),%rbx + lea 48(%rsi),%rsp +.Lepilogue: + ret +.size $func,.-$func +___ + +if ($SZ==4) { +$code.=<<___; +.align 64 +.type $TABLE,\@object +$TABLE: + .long 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5 + .long 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5 + .long 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5 + .long 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5 + .long 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3 + .long 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3 + .long 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174 + .long 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174 + .long 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc + .long 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc + .long 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da + .long 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da + .long 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7 + .long 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7 + .long 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967 + .long 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967 + .long 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13 + .long 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13 + .long 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85 + .long 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85 + .long 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3 + .long 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3 + .long 0xd192e819,0xd6990624,0xf40e3585,0x106aa070 + .long 0xd192e819,0xd6990624,0xf40e3585,0x106aa070 + .long 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5 + .long 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5 + .long 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3 + .long 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3 + .long 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208 + .long 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208 + .long 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 + .long 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 + + .long 0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f + .long 0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f + .long 0x03020100,0x0b0a0908,0xffffffff,0xffffffff + .long 0x03020100,0x0b0a0908,0xffffffff,0xffffffff + .long 0xffffffff,0xffffffff,0x03020100,0x0b0a0908 + .long 0xffffffff,0xffffffff,0x03020100,0x0b0a0908 + .asciz "SHA256 block transform for x86_64, CRYPTOGAMS by " +___ +} else { +$code.=<<___; +.align 64 +.type $TABLE,\@object +$TABLE: + .quad 0x428a2f98d728ae22,0x7137449123ef65cd + .quad 0x428a2f98d728ae22,0x7137449123ef65cd + .quad 0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc + .quad 0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc + .quad 0x3956c25bf348b538,0x59f111f1b605d019 + .quad 0x3956c25bf348b538,0x59f111f1b605d019 + .quad 0x923f82a4af194f9b,0xab1c5ed5da6d8118 + .quad 0x923f82a4af194f9b,0xab1c5ed5da6d8118 + .quad 0xd807aa98a3030242,0x12835b0145706fbe + .quad 0xd807aa98a3030242,0x12835b0145706fbe + .quad 0x243185be4ee4b28c,0x550c7dc3d5ffb4e2 + .quad 0x243185be4ee4b28c,0x550c7dc3d5ffb4e2 + .quad 0x72be5d74f27b896f,0x80deb1fe3b1696b1 + .quad 0x72be5d74f27b896f,0x80deb1fe3b1696b1 + .quad 0x9bdc06a725c71235,0xc19bf174cf692694 + .quad 0x9bdc06a725c71235,0xc19bf174cf692694 + .quad 0xe49b69c19ef14ad2,0xefbe4786384f25e3 + .quad 0xe49b69c19ef14ad2,0xefbe4786384f25e3 + .quad 0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65 + .quad 0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65 + .quad 0x2de92c6f592b0275,0x4a7484aa6ea6e483 + .quad 0x2de92c6f592b0275,0x4a7484aa6ea6e483 + .quad 0x5cb0a9dcbd41fbd4,0x76f988da831153b5 + .quad 0x5cb0a9dcbd41fbd4,0x76f988da831153b5 + .quad 0x983e5152ee66dfab,0xa831c66d2db43210 + .quad 0x983e5152ee66dfab,0xa831c66d2db43210 + .quad 0xb00327c898fb213f,0xbf597fc7beef0ee4 + .quad 0xb00327c898fb213f,0xbf597fc7beef0ee4 + .quad 0xc6e00bf33da88fc2,0xd5a79147930aa725 + .quad 0xc6e00bf33da88fc2,0xd5a79147930aa725 + .quad 0x06ca6351e003826f,0x142929670a0e6e70 + .quad 0x06ca6351e003826f,0x142929670a0e6e70 + .quad 0x27b70a8546d22ffc,0x2e1b21385c26c926 + .quad 0x27b70a8546d22ffc,0x2e1b21385c26c926 + .quad 0x4d2c6dfc5ac42aed,0x53380d139d95b3df + .quad 0x4d2c6dfc5ac42aed,0x53380d139d95b3df + .quad 0x650a73548baf63de,0x766a0abb3c77b2a8 + .quad 0x650a73548baf63de,0x766a0abb3c77b2a8 + .quad 0x81c2c92e47edaee6,0x92722c851482353b + .quad 0x81c2c92e47edaee6,0x92722c851482353b + .quad 0xa2bfe8a14cf10364,0xa81a664bbc423001 + .quad 0xa2bfe8a14cf10364,0xa81a664bbc423001 + .quad 0xc24b8b70d0f89791,0xc76c51a30654be30 + .quad 0xc24b8b70d0f89791,0xc76c51a30654be30 + .quad 0xd192e819d6ef5218,0xd69906245565a910 + .quad 0xd192e819d6ef5218,0xd69906245565a910 + .quad 0xf40e35855771202a,0x106aa07032bbd1b8 + .quad 0xf40e35855771202a,0x106aa07032bbd1b8 + .quad 0x19a4c116b8d2d0c8,0x1e376c085141ab53 + .quad 0x19a4c116b8d2d0c8,0x1e376c085141ab53 + .quad 0x2748774cdf8eeb99,0x34b0bcb5e19b48a8 + .quad 0x2748774cdf8eeb99,0x34b0bcb5e19b48a8 + .quad 0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb + .quad 0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb + .quad 0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3 + .quad 0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3 + .quad 0x748f82ee5defb2fc,0x78a5636f43172f60 + .quad 0x748f82ee5defb2fc,0x78a5636f43172f60 + .quad 0x84c87814a1f0ab72,0x8cc702081a6439ec + .quad 0x84c87814a1f0ab72,0x8cc702081a6439ec + .quad 0x90befffa23631e28,0xa4506cebde82bde9 + .quad 0x90befffa23631e28,0xa4506cebde82bde9 + .quad 0xbef9a3f7b2c67915,0xc67178f2e372532b + .quad 0xbef9a3f7b2c67915,0xc67178f2e372532b + .quad 0xca273eceea26619c,0xd186b8c721c0c207 + .quad 0xca273eceea26619c,0xd186b8c721c0c207 + .quad 0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178 + .quad 0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178 + .quad 0x06f067aa72176fba,0x0a637dc5a2c898a6 + .quad 0x06f067aa72176fba,0x0a637dc5a2c898a6 + .quad 0x113f9804bef90dae,0x1b710b35131c471b + .quad 0x113f9804bef90dae,0x1b710b35131c471b + .quad 0x28db77f523047d84,0x32caab7b40c72493 + .quad 0x28db77f523047d84,0x32caab7b40c72493 + .quad 0x3c9ebe0a15c9bebc,0x431d67c49c100d4c + .quad 0x3c9ebe0a15c9bebc,0x431d67c49c100d4c + .quad 0x4cc5d4becb3e42b6,0x597f299cfc657e2a + .quad 0x4cc5d4becb3e42b6,0x597f299cfc657e2a + .quad 0x5fcb6fab3ad6faec,0x6c44198c4a475817 + .quad 0x5fcb6fab3ad6faec,0x6c44198c4a475817 + + .quad 0x0001020304050607,0x08090a0b0c0d0e0f + .quad 0x0001020304050607,0x08090a0b0c0d0e0f + .asciz "SHA512 block transform for x86_64, CRYPTOGAMS by " +___ +} + +###################################################################### +# SIMD code paths +# +if ($SZ==4 && $shaext) {{{ +###################################################################### +# Intel SHA Extensions implementation of SHA256 update function. +# +my ($ctx,$inp,$num,$Tbl)=("%rdi","%rsi","%rdx","%rcx"); + +my ($Wi,$ABEF,$CDGH,$TMP,$BSWAP,$ABEF_SAVE,$CDGH_SAVE)=map("%xmm$_",(0..2,7..10)); +my @MSG=map("%xmm$_",(3..6)); + +$code.=<<___; +.type sha256_block_data_order_shaext,\@function,3 +.align 64 +sha256_block_data_order_shaext: +_shaext_shortcut: +___ +$code.=<<___ if ($win64); + lea `-8-5*16`(%rsp),%rsp + movaps %xmm6,-8-5*16(%rax) + movaps %xmm7,-8-4*16(%rax) + movaps %xmm8,-8-3*16(%rax) + movaps %xmm9,-8-2*16(%rax) + movaps %xmm10,-8-1*16(%rax) +.Lprologue_shaext: +___ +$code.=<<___; + lea K256+0x80(%rip),$Tbl + movdqu ($ctx),$ABEF # DCBA + movdqu 16($ctx),$CDGH # HGFE + movdqa 0x200-0x80($Tbl),$TMP # byte swap mask + + pshufd \$0x1b,$ABEF,$Wi # ABCD + pshufd \$0xb1,$ABEF,$ABEF # CDAB + pshufd \$0x1b,$CDGH,$CDGH # EFGH + movdqa $TMP,$BSWAP # offload + palignr \$8,$CDGH,$ABEF # ABEF + punpcklqdq $Wi,$CDGH # CDGH + jmp .Loop_shaext + +.align 16 +.Loop_shaext: + movdqu ($inp),@MSG[0] + movdqu 0x10($inp),@MSG[1] + movdqu 0x20($inp),@MSG[2] + pshufb $TMP,@MSG[0] + movdqu 0x30($inp),@MSG[3] + + movdqa 0*32-0x80($Tbl),$Wi + paddd @MSG[0],$Wi + pshufb $TMP,@MSG[1] + movdqa $CDGH,$CDGH_SAVE # offload + sha256rnds2 $ABEF,$CDGH # 0-3 + pshufd \$0x0e,$Wi,$Wi + nop + movdqa $ABEF,$ABEF_SAVE # offload + sha256rnds2 $CDGH,$ABEF + + movdqa 1*32-0x80($Tbl),$Wi + paddd @MSG[1],$Wi + pshufb $TMP,@MSG[2] + sha256rnds2 $ABEF,$CDGH # 4-7 + pshufd \$0x0e,$Wi,$Wi + lea 0x40($inp),$inp + sha256msg1 @MSG[1],@MSG[0] + sha256rnds2 $CDGH,$ABEF + + movdqa 2*32-0x80($Tbl),$Wi + paddd @MSG[2],$Wi + pshufb $TMP,@MSG[3] + sha256rnds2 $ABEF,$CDGH # 8-11 + pshufd \$0x0e,$Wi,$Wi + movdqa @MSG[3],$TMP + palignr \$4,@MSG[2],$TMP + nop + paddd $TMP,@MSG[0] + sha256msg1 @MSG[2],@MSG[1] + sha256rnds2 $CDGH,$ABEF + + movdqa 3*32-0x80($Tbl),$Wi + paddd @MSG[3],$Wi + sha256msg2 @MSG[3],@MSG[0] + sha256rnds2 $ABEF,$CDGH # 12-15 + pshufd \$0x0e,$Wi,$Wi + movdqa @MSG[0],$TMP + palignr \$4,@MSG[3],$TMP + nop + paddd $TMP,@MSG[1] + sha256msg1 @MSG[3],@MSG[2] + sha256rnds2 $CDGH,$ABEF +___ +for($i=4;$i<16-3;$i++) { +$code.=<<___; + movdqa $i*32-0x80($Tbl),$Wi + paddd @MSG[0],$Wi + sha256msg2 @MSG[0],@MSG[1] + sha256rnds2 $ABEF,$CDGH # 16-19... + pshufd \$0x0e,$Wi,$Wi + movdqa @MSG[1],$TMP + palignr \$4,@MSG[0],$TMP + nop + paddd $TMP,@MSG[2] + sha256msg1 @MSG[0],@MSG[3] + sha256rnds2 $CDGH,$ABEF +___ + push(@MSG,shift(@MSG)); +} +$code.=<<___; + movdqa 13*32-0x80($Tbl),$Wi + paddd @MSG[0],$Wi + sha256msg2 @MSG[0],@MSG[1] + sha256rnds2 $ABEF,$CDGH # 52-55 + pshufd \$0x0e,$Wi,$Wi + movdqa @MSG[1],$TMP + palignr \$4,@MSG[0],$TMP + sha256rnds2 $CDGH,$ABEF + paddd $TMP,@MSG[2] + + movdqa 14*32-0x80($Tbl),$Wi + paddd @MSG[1],$Wi + sha256rnds2 $ABEF,$CDGH # 56-59 + pshufd \$0x0e,$Wi,$Wi + sha256msg2 @MSG[1],@MSG[2] + movdqa $BSWAP,$TMP + sha256rnds2 $CDGH,$ABEF + + movdqa 15*32-0x80($Tbl),$Wi + paddd @MSG[2],$Wi + nop + sha256rnds2 $ABEF,$CDGH # 60-63 + pshufd \$0x0e,$Wi,$Wi + dec $num + nop + sha256rnds2 $CDGH,$ABEF + + paddd $CDGH_SAVE,$CDGH + paddd $ABEF_SAVE,$ABEF + jnz .Loop_shaext + + pshufd \$0xb1,$CDGH,$CDGH # DCHG + pshufd \$0x1b,$ABEF,$TMP # FEBA + pshufd \$0xb1,$ABEF,$ABEF # BAFE + punpckhqdq $CDGH,$ABEF # DCBA + palignr \$8,$TMP,$CDGH # HGFE + + movdqu $ABEF,($ctx) + movdqu $CDGH,16($ctx) +___ +$code.=<<___ if ($win64); + movaps -8-5*16(%rax),%xmm6 + movaps -8-4*16(%rax),%xmm7 + movaps -8-3*16(%rax),%xmm8 + movaps -8-2*16(%rax),%xmm9 + movaps -8-1*16(%rax),%xmm10 + mov %rax,%rsp +.Lepilogue_shaext: +___ +$code.=<<___; + ret +.size sha256_block_data_order_shaext,.-sha256_block_data_order_shaext +___ +}}} +{{{ + +my $a4=$T1; +my ($a,$b,$c,$d,$e,$f,$g,$h); + +sub AUTOLOAD() # thunk [simplified] 32-bit style perlasm +{ my $opcode = $AUTOLOAD; $opcode =~ s/.*:://; + my $arg = pop; + $arg = "\$$arg" if ($arg*1 eq $arg); + $code .= "\t$opcode\t".join(',',$arg,reverse @_)."\n"; +} + +sub body_00_15 () { + ( + '($a,$b,$c,$d,$e,$f,$g,$h)=@ROT;'. + + '&ror ($a0,$Sigma1[2]-$Sigma1[1])', + '&mov ($a,$a1)', + '&mov ($a4,$f)', + + '&ror ($a1,$Sigma0[2]-$Sigma0[1])', + '&xor ($a0,$e)', + '&xor ($a4,$g)', # f^g + + '&ror ($a0,$Sigma1[1]-$Sigma1[0])', + '&xor ($a1,$a)', + '&and ($a4,$e)', # (f^g)&e + + '&xor ($a0,$e)', + '&add ($h,$SZ*($i&15)."(%rsp)")', # h+=X[i]+K[i] + '&mov ($a2,$a)', + + '&xor ($a4,$g)', # Ch(e,f,g)=((f^g)&e)^g + '&ror ($a1,$Sigma0[1]-$Sigma0[0])', + '&xor ($a2,$b)', # a^b, b^c in next round + + '&add ($h,$a4)', # h+=Ch(e,f,g) + '&ror ($a0,$Sigma1[0])', # Sigma1(e) + '&and ($a3,$a2)', # (b^c)&(a^b) + + '&xor ($a1,$a)', + '&add ($h,$a0)', # h+=Sigma1(e) + '&xor ($a3,$b)', # Maj(a,b,c)=Ch(a^b,c,b) + + '&ror ($a1,$Sigma0[0])', # Sigma0(a) + '&add ($d,$h)', # d+=h + '&add ($h,$a3)', # h+=Maj(a,b,c) + + '&mov ($a0,$d)', + '&add ($a1,$h);'. # h+=Sigma0(a) + '($a2,$a3) = ($a3,$a2); unshift(@ROT,pop(@ROT)); $i++;' + ); +} + +###################################################################### +# SSSE3 code path +# +if ($SZ==4) { # SHA256 only +my @X = map("%xmm$_",(0..3)); +my ($t0,$t1,$t2,$t3, $t4,$t5) = map("%xmm$_",(4..9)); + +$code.=<<___; +.type ${func}_ssse3,\@function,3 +.align 64 +${func}_ssse3: +.Lssse3_shortcut: + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + mov %rsp,%r11 # copy %rsp + shl \$4,%rdx # num*16 + sub \$`$framesz+$win64*16*4`,%rsp + lea ($inp,%rdx,$SZ),%rdx # inp+num*16*$SZ + and \$-64,%rsp # align stack frame + mov $ctx,$_ctx # save ctx, 1st arg + mov $inp,$_inp # save inp, 2nd arh + mov %rdx,$_end # save end pointer, "3rd" arg + mov %r11,$_rsp # save copy of %rsp +___ +$code.=<<___ if ($win64); + movaps %xmm6,16*$SZ+32(%rsp) + movaps %xmm7,16*$SZ+48(%rsp) + movaps %xmm8,16*$SZ+64(%rsp) + movaps %xmm9,16*$SZ+80(%rsp) +___ +$code.=<<___; +.Lprologue_ssse3: + + mov $SZ*0($ctx),$A + mov $SZ*1($ctx),$B + mov $SZ*2($ctx),$C + mov $SZ*3($ctx),$D + mov $SZ*4($ctx),$E + mov $SZ*5($ctx),$F + mov $SZ*6($ctx),$G + mov $SZ*7($ctx),$H +___ + +$code.=<<___; + #movdqa $TABLE+`$SZ*2*$rounds`+32(%rip),$t4 + #movdqa $TABLE+`$SZ*2*$rounds`+64(%rip),$t5 + jmp .Lloop_ssse3 +.align 16 +.Lloop_ssse3: + movdqa $TABLE+`$SZ*2*$rounds`(%rip),$t3 + movdqu 0x00($inp),@X[0] + movdqu 0x10($inp),@X[1] + movdqu 0x20($inp),@X[2] + pshufb $t3,@X[0] + movdqu 0x30($inp),@X[3] + lea $TABLE(%rip),$Tbl + pshufb $t3,@X[1] + movdqa 0x00($Tbl),$t0 + movdqa 0x20($Tbl),$t1 + pshufb $t3,@X[2] + paddd @X[0],$t0 + movdqa 0x40($Tbl),$t2 + pshufb $t3,@X[3] + movdqa 0x60($Tbl),$t3 + paddd @X[1],$t1 + paddd @X[2],$t2 + paddd @X[3],$t3 + movdqa $t0,0x00(%rsp) + mov $A,$a1 + movdqa $t1,0x10(%rsp) + mov $B,$a3 + movdqa $t2,0x20(%rsp) + xor $C,$a3 # magic + movdqa $t3,0x30(%rsp) + mov $E,$a0 + jmp .Lssse3_00_47 + +.align 16 +.Lssse3_00_47: + sub \$`-16*2*$SZ`,$Tbl # size optimization +___ +sub Xupdate_256_SSSE3 () { + ( + '&movdqa ($t0,@X[1]);', + '&movdqa ($t3,@X[3])', + '&palignr ($t0,@X[0],$SZ)', # X[1..4] + '&palignr ($t3,@X[2],$SZ);', # X[9..12] + '&movdqa ($t1,$t0)', + '&movdqa ($t2,$t0);', + '&psrld ($t0,$sigma0[2])', + '&paddd (@X[0],$t3);', # X[0..3] += X[9..12] + '&psrld ($t2,$sigma0[0])', + '&pshufd ($t3,@X[3],0b11111010)',# X[14..15] + '&pslld ($t1,8*$SZ-$sigma0[1]);'. + '&pxor ($t0,$t2)', + '&psrld ($t2,$sigma0[1]-$sigma0[0]);'. + '&pxor ($t0,$t1)', + '&pslld ($t1,$sigma0[1]-$sigma0[0]);'. + '&pxor ($t0,$t2);', + '&movdqa ($t2,$t3)', + '&pxor ($t0,$t1);', # sigma0(X[1..4]) + '&psrld ($t3,$sigma1[2])', + '&paddd (@X[0],$t0);', # X[0..3] += sigma0(X[1..4]) + '&psrlq ($t2,$sigma1[0])', + '&pxor ($t3,$t2);', + '&psrlq ($t2,$sigma1[1]-$sigma1[0])', + '&pxor ($t3,$t2)', + '&pshufb ($t3,$t4)', # sigma1(X[14..15]) + '&paddd (@X[0],$t3)', # X[0..1] += sigma1(X[14..15]) + '&pshufd ($t3,@X[0],0b01010000)',# X[16..17] + '&movdqa ($t2,$t3);', + '&psrld ($t3,$sigma1[2])', + '&psrlq ($t2,$sigma1[0])', + '&pxor ($t3,$t2);', + '&psrlq ($t2,$sigma1[1]-$sigma1[0])', + '&pxor ($t3,$t2);', + '&movdqa ($t2,16*2*$j."($Tbl)")', + '&pshufb ($t3,$t5)', + '&paddd (@X[0],$t3)' # X[2..3] += sigma1(X[16..17]) + ); +} + +sub SSSE3_256_00_47 () { +my $j = shift; +my $body = shift; +my @X = @_; +my @insns = (&$body,&$body,&$body,&$body); # 104 instructions + + if (0) { + foreach (Xupdate_256_SSSE3()) { # 36 instructions + eval; + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + } + } else { # squeeze extra 4% on Westmere and 19% on Atom + eval(shift(@insns)); #@ + &movdqa ($t0,@X[1]); + eval(shift(@insns)); + eval(shift(@insns)); + &movdqa ($t3,@X[3]); + eval(shift(@insns)); #@ + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); #@ + eval(shift(@insns)); + &palignr ($t0,@X[0],$SZ); # X[1..4] + eval(shift(@insns)); + eval(shift(@insns)); + &palignr ($t3,@X[2],$SZ); # X[9..12] + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); #@ + &movdqa ($t1,$t0); + eval(shift(@insns)); + eval(shift(@insns)); + &movdqa ($t2,$t0); + eval(shift(@insns)); #@ + eval(shift(@insns)); + &psrld ($t0,$sigma0[2]); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &paddd (@X[0],$t3); # X[0..3] += X[9..12] + eval(shift(@insns)); #@ + eval(shift(@insns)); + &psrld ($t2,$sigma0[0]); + eval(shift(@insns)); + eval(shift(@insns)); + &pshufd ($t3,@X[3],0b11111010); # X[4..15] + eval(shift(@insns)); + eval(shift(@insns)); #@ + &pslld ($t1,8*$SZ-$sigma0[1]); + eval(shift(@insns)); + eval(shift(@insns)); + &pxor ($t0,$t2); + eval(shift(@insns)); #@ + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); #@ + &psrld ($t2,$sigma0[1]-$sigma0[0]); + eval(shift(@insns)); + &pxor ($t0,$t1); + eval(shift(@insns)); + eval(shift(@insns)); + &pslld ($t1,$sigma0[1]-$sigma0[0]); + eval(shift(@insns)); + eval(shift(@insns)); + &pxor ($t0,$t2); + eval(shift(@insns)); + eval(shift(@insns)); #@ + &movdqa ($t2,$t3); + eval(shift(@insns)); + eval(shift(@insns)); + &pxor ($t0,$t1); # sigma0(X[1..4]) + eval(shift(@insns)); #@ + eval(shift(@insns)); + eval(shift(@insns)); + &psrld ($t3,$sigma1[2]); + eval(shift(@insns)); + eval(shift(@insns)); + &paddd (@X[0],$t0); # X[0..3] += sigma0(X[1..4]) + eval(shift(@insns)); #@ + eval(shift(@insns)); + &psrlq ($t2,$sigma1[0]); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &pxor ($t3,$t2); + eval(shift(@insns)); #@ + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); #@ + &psrlq ($t2,$sigma1[1]-$sigma1[0]); + eval(shift(@insns)); + eval(shift(@insns)); + &pxor ($t3,$t2); + eval(shift(@insns)); #@ + eval(shift(@insns)); + eval(shift(@insns)); + #&pshufb ($t3,$t4); # sigma1(X[14..15]) + &pshufd ($t3,$t3,0b10000000); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &psrldq ($t3,8); + eval(shift(@insns)); + eval(shift(@insns)); #@ + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); #@ + &paddd (@X[0],$t3); # X[0..1] += sigma1(X[14..15]) + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &pshufd ($t3,@X[0],0b01010000); # X[16..17] + eval(shift(@insns)); + eval(shift(@insns)); #@ + eval(shift(@insns)); + &movdqa ($t2,$t3); + eval(shift(@insns)); + eval(shift(@insns)); + &psrld ($t3,$sigma1[2]); + eval(shift(@insns)); + eval(shift(@insns)); #@ + &psrlq ($t2,$sigma1[0]); + eval(shift(@insns)); + eval(shift(@insns)); + &pxor ($t3,$t2); + eval(shift(@insns)); #@ + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); #@ + eval(shift(@insns)); + &psrlq ($t2,$sigma1[1]-$sigma1[0]); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &pxor ($t3,$t2); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); #@ + #&pshufb ($t3,$t5); + &pshufd ($t3,$t3,0b00001000); + eval(shift(@insns)); + eval(shift(@insns)); + &movdqa ($t2,16*2*$j."($Tbl)"); + eval(shift(@insns)); #@ + eval(shift(@insns)); + &pslldq ($t3,8); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &paddd (@X[0],$t3); # X[2..3] += sigma1(X[16..17]) + eval(shift(@insns)); #@ + eval(shift(@insns)); + eval(shift(@insns)); + } + &paddd ($t2,@X[0]); + foreach (@insns) { eval; } # remaining instructions + &movdqa (16*$j."(%rsp)",$t2); +} + + for ($i=0,$j=0; $j<4; $j++) { + &SSSE3_256_00_47($j,\&body_00_15,@X); + push(@X,shift(@X)); # rotate(@X) + } + &cmpb ($SZ-1+16*2*$SZ."($Tbl)",0); + &jne (".Lssse3_00_47"); + + for ($i=0; $i<16; ) { + foreach(body_00_15()) { eval; } + } +$code.=<<___; + mov $_ctx,$ctx + mov $a1,$A + + add $SZ*0($ctx),$A + lea 16*$SZ($inp),$inp + add $SZ*1($ctx),$B + add $SZ*2($ctx),$C + add $SZ*3($ctx),$D + add $SZ*4($ctx),$E + add $SZ*5($ctx),$F + add $SZ*6($ctx),$G + add $SZ*7($ctx),$H + + cmp $_end,$inp + + mov $A,$SZ*0($ctx) + mov $B,$SZ*1($ctx) + mov $C,$SZ*2($ctx) + mov $D,$SZ*3($ctx) + mov $E,$SZ*4($ctx) + mov $F,$SZ*5($ctx) + mov $G,$SZ*6($ctx) + mov $H,$SZ*7($ctx) + jb .Lloop_ssse3 + + mov $_rsp,%rsi +___ +$code.=<<___ if ($win64); + movaps 16*$SZ+32(%rsp),%xmm6 + movaps 16*$SZ+48(%rsp),%xmm7 + movaps 16*$SZ+64(%rsp),%xmm8 + movaps 16*$SZ+80(%rsp),%xmm9 +___ +$code.=<<___; + mov (%rsi),%r15 + mov 8(%rsi),%r14 + mov 16(%rsi),%r13 + mov 24(%rsi),%r12 + mov 32(%rsi),%rbp + mov 40(%rsi),%rbx + lea 48(%rsi),%rsp +.Lepilogue_ssse3: + ret +.size ${func}_ssse3,.-${func}_ssse3 +___ +} + +if ($avx) {{ +###################################################################### +# XOP code path +# +if ($SZ==8) { # SHA512 only +$code.=<<___; +.type ${func}_xop,\@function,3 +.align 64 +${func}_xop: +.Lxop_shortcut: + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + mov %rsp,%r11 # copy %rsp + shl \$4,%rdx # num*16 + sub \$`$framesz+$win64*16*($SZ==4?4:6)`,%rsp + lea ($inp,%rdx,$SZ),%rdx # inp+num*16*$SZ + and \$-64,%rsp # align stack frame + mov $ctx,$_ctx # save ctx, 1st arg + mov $inp,$_inp # save inp, 2nd arh + mov %rdx,$_end # save end pointer, "3rd" arg + mov %r11,$_rsp # save copy of %rsp +___ +$code.=<<___ if ($win64); + movaps %xmm6,16*$SZ+32(%rsp) + movaps %xmm7,16*$SZ+48(%rsp) + movaps %xmm8,16*$SZ+64(%rsp) + movaps %xmm9,16*$SZ+80(%rsp) +___ +$code.=<<___ if ($win64 && $SZ>4); + movaps %xmm10,16*$SZ+96(%rsp) + movaps %xmm11,16*$SZ+112(%rsp) +___ +$code.=<<___; +.Lprologue_xop: + + vzeroupper + mov $SZ*0($ctx),$A + mov $SZ*1($ctx),$B + mov $SZ*2($ctx),$C + mov $SZ*3($ctx),$D + mov $SZ*4($ctx),$E + mov $SZ*5($ctx),$F + mov $SZ*6($ctx),$G + mov $SZ*7($ctx),$H + jmp .Lloop_xop +___ + if ($SZ==4) { # SHA256 + my @X = map("%xmm$_",(0..3)); + my ($t0,$t1,$t2,$t3) = map("%xmm$_",(4..7)); + +$code.=<<___; +.align 16 +.Lloop_xop: + vmovdqa $TABLE+`$SZ*2*$rounds`(%rip),$t3 + vmovdqu 0x00($inp),@X[0] + vmovdqu 0x10($inp),@X[1] + vmovdqu 0x20($inp),@X[2] + vmovdqu 0x30($inp),@X[3] + vpshufb $t3,@X[0],@X[0] + lea $TABLE(%rip),$Tbl + vpshufb $t3,@X[1],@X[1] + vpshufb $t3,@X[2],@X[2] + vpaddd 0x00($Tbl),@X[0],$t0 + vpshufb $t3,@X[3],@X[3] + vpaddd 0x20($Tbl),@X[1],$t1 + vpaddd 0x40($Tbl),@X[2],$t2 + vpaddd 0x60($Tbl),@X[3],$t3 + vmovdqa $t0,0x00(%rsp) + mov $A,$a1 + vmovdqa $t1,0x10(%rsp) + mov $B,$a3 + vmovdqa $t2,0x20(%rsp) + xor $C,$a3 # magic + vmovdqa $t3,0x30(%rsp) + mov $E,$a0 + jmp .Lxop_00_47 + +.align 16 +.Lxop_00_47: + sub \$`-16*2*$SZ`,$Tbl # size optimization +___ +sub XOP_256_00_47 () { +my $j = shift; +my $body = shift; +my @X = @_; +my @insns = (&$body,&$body,&$body,&$body); # 104 instructions + + &vpalignr ($t0,@X[1],@X[0],$SZ); # X[1..4] + eval(shift(@insns)); + eval(shift(@insns)); + &vpalignr ($t3,@X[3],@X[2],$SZ); # X[9..12] + eval(shift(@insns)); + eval(shift(@insns)); + &vprotd ($t1,$t0,8*$SZ-$sigma0[1]); + eval(shift(@insns)); + eval(shift(@insns)); + &vpsrld ($t0,$t0,$sigma0[2]); + eval(shift(@insns)); + eval(shift(@insns)); + &vpaddd (@X[0],@X[0],$t3); # X[0..3] += X[9..12] + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vprotd ($t2,$t1,$sigma0[1]-$sigma0[0]); + eval(shift(@insns)); + eval(shift(@insns)); + &vpxor ($t0,$t0,$t1); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vprotd ($t3,@X[3],8*$SZ-$sigma1[1]); + eval(shift(@insns)); + eval(shift(@insns)); + &vpxor ($t0,$t0,$t2); # sigma0(X[1..4]) + eval(shift(@insns)); + eval(shift(@insns)); + &vpsrld ($t2,@X[3],$sigma1[2]); + eval(shift(@insns)); + eval(shift(@insns)); + &vpaddd (@X[0],@X[0],$t0); # X[0..3] += sigma0(X[1..4]) + eval(shift(@insns)); + eval(shift(@insns)); + &vprotd ($t1,$t3,$sigma1[1]-$sigma1[0]); + eval(shift(@insns)); + eval(shift(@insns)); + &vpxor ($t3,$t3,$t2); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vpxor ($t3,$t3,$t1); # sigma1(X[14..15]) + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vpsrldq ($t3,$t3,8); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vpaddd (@X[0],@X[0],$t3); # X[0..1] += sigma1(X[14..15]) + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vprotd ($t3,@X[0],8*$SZ-$sigma1[1]); + eval(shift(@insns)); + eval(shift(@insns)); + &vpsrld ($t2,@X[0],$sigma1[2]); + eval(shift(@insns)); + eval(shift(@insns)); + &vprotd ($t1,$t3,$sigma1[1]-$sigma1[0]); + eval(shift(@insns)); + eval(shift(@insns)); + &vpxor ($t3,$t3,$t2); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vpxor ($t3,$t3,$t1); # sigma1(X[16..17]) + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vpslldq ($t3,$t3,8); # 22 instructions + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vpaddd (@X[0],@X[0],$t3); # X[2..3] += sigma1(X[16..17]) + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vpaddd ($t2,@X[0],16*2*$j."($Tbl)"); + foreach (@insns) { eval; } # remaining instructions + &vmovdqa (16*$j."(%rsp)",$t2); +} + + for ($i=0,$j=0; $j<4; $j++) { + &XOP_256_00_47($j,\&body_00_15,@X); + push(@X,shift(@X)); # rotate(@X) + } + &cmpb ($SZ-1+16*2*$SZ."($Tbl)",0); + &jne (".Lxop_00_47"); + + for ($i=0; $i<16; ) { + foreach(body_00_15()) { eval; } + } + + } else { # SHA512 + my @X = map("%xmm$_",(0..7)); + my ($t0,$t1,$t2,$t3) = map("%xmm$_",(8..11)); + +$code.=<<___; +.align 16 +.Lloop_xop: + vmovdqa $TABLE+`$SZ*2*$rounds`(%rip),$t3 + vmovdqu 0x00($inp),@X[0] + lea $TABLE+0x80(%rip),$Tbl # size optimization + vmovdqu 0x10($inp),@X[1] + vmovdqu 0x20($inp),@X[2] + vpshufb $t3,@X[0],@X[0] + vmovdqu 0x30($inp),@X[3] + vpshufb $t3,@X[1],@X[1] + vmovdqu 0x40($inp),@X[4] + vpshufb $t3,@X[2],@X[2] + vmovdqu 0x50($inp),@X[5] + vpshufb $t3,@X[3],@X[3] + vmovdqu 0x60($inp),@X[6] + vpshufb $t3,@X[4],@X[4] + vmovdqu 0x70($inp),@X[7] + vpshufb $t3,@X[5],@X[5] + vpaddq -0x80($Tbl),@X[0],$t0 + vpshufb $t3,@X[6],@X[6] + vpaddq -0x60($Tbl),@X[1],$t1 + vpshufb $t3,@X[7],@X[7] + vpaddq -0x40($Tbl),@X[2],$t2 + vpaddq -0x20($Tbl),@X[3],$t3 + vmovdqa $t0,0x00(%rsp) + vpaddq 0x00($Tbl),@X[4],$t0 + vmovdqa $t1,0x10(%rsp) + vpaddq 0x20($Tbl),@X[5],$t1 + vmovdqa $t2,0x20(%rsp) + vpaddq 0x40($Tbl),@X[6],$t2 + vmovdqa $t3,0x30(%rsp) + vpaddq 0x60($Tbl),@X[7],$t3 + vmovdqa $t0,0x40(%rsp) + mov $A,$a1 + vmovdqa $t1,0x50(%rsp) + mov $B,$a3 + vmovdqa $t2,0x60(%rsp) + xor $C,$a3 # magic + vmovdqa $t3,0x70(%rsp) + mov $E,$a0 + jmp .Lxop_00_47 + +.align 16 +.Lxop_00_47: + add \$`16*2*$SZ`,$Tbl +___ +sub XOP_512_00_47 () { +my $j = shift; +my $body = shift; +my @X = @_; +my @insns = (&$body,&$body); # 52 instructions + + &vpalignr ($t0,@X[1],@X[0],$SZ); # X[1..2] + eval(shift(@insns)); + eval(shift(@insns)); + &vpalignr ($t3,@X[5],@X[4],$SZ); # X[9..10] + eval(shift(@insns)); + eval(shift(@insns)); + &vprotq ($t1,$t0,8*$SZ-$sigma0[1]); + eval(shift(@insns)); + eval(shift(@insns)); + &vpsrlq ($t0,$t0,$sigma0[2]); + eval(shift(@insns)); + eval(shift(@insns)); + &vpaddq (@X[0],@X[0],$t3); # X[0..1] += X[9..10] + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vprotq ($t2,$t1,$sigma0[1]-$sigma0[0]); + eval(shift(@insns)); + eval(shift(@insns)); + &vpxor ($t0,$t0,$t1); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vprotq ($t3,@X[7],8*$SZ-$sigma1[1]); + eval(shift(@insns)); + eval(shift(@insns)); + &vpxor ($t0,$t0,$t2); # sigma0(X[1..2]) + eval(shift(@insns)); + eval(shift(@insns)); + &vpsrlq ($t2,@X[7],$sigma1[2]); + eval(shift(@insns)); + eval(shift(@insns)); + &vpaddq (@X[0],@X[0],$t0); # X[0..1] += sigma0(X[1..2]) + eval(shift(@insns)); + eval(shift(@insns)); + &vprotq ($t1,$t3,$sigma1[1]-$sigma1[0]); + eval(shift(@insns)); + eval(shift(@insns)); + &vpxor ($t3,$t3,$t2); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vpxor ($t3,$t3,$t1); # sigma1(X[14..15]) + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vpaddq (@X[0],@X[0],$t3); # X[0..1] += sigma1(X[14..15]) + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vpaddq ($t2,@X[0],16*2*$j-0x80."($Tbl)"); + foreach (@insns) { eval; } # remaining instructions + &vmovdqa (16*$j."(%rsp)",$t2); +} + + for ($i=0,$j=0; $j<8; $j++) { + &XOP_512_00_47($j,\&body_00_15,@X); + push(@X,shift(@X)); # rotate(@X) + } + &cmpb ($SZ-1+16*2*$SZ-0x80."($Tbl)",0); + &jne (".Lxop_00_47"); + + for ($i=0; $i<16; ) { + foreach(body_00_15()) { eval; } + } +} +$code.=<<___; + mov $_ctx,$ctx + mov $a1,$A + + add $SZ*0($ctx),$A + lea 16*$SZ($inp),$inp + add $SZ*1($ctx),$B + add $SZ*2($ctx),$C + add $SZ*3($ctx),$D + add $SZ*4($ctx),$E + add $SZ*5($ctx),$F + add $SZ*6($ctx),$G + add $SZ*7($ctx),$H + + cmp $_end,$inp + + mov $A,$SZ*0($ctx) + mov $B,$SZ*1($ctx) + mov $C,$SZ*2($ctx) + mov $D,$SZ*3($ctx) + mov $E,$SZ*4($ctx) + mov $F,$SZ*5($ctx) + mov $G,$SZ*6($ctx) + mov $H,$SZ*7($ctx) + jb .Lloop_xop + + mov $_rsp,%rsi + vzeroupper +___ +$code.=<<___ if ($win64); + movaps 16*$SZ+32(%rsp),%xmm6 + movaps 16*$SZ+48(%rsp),%xmm7 + movaps 16*$SZ+64(%rsp),%xmm8 + movaps 16*$SZ+80(%rsp),%xmm9 +___ +$code.=<<___ if ($win64 && $SZ>4); + movaps 16*$SZ+96(%rsp),%xmm10 + movaps 16*$SZ+112(%rsp),%xmm11 +___ +$code.=<<___; + mov (%rsi),%r15 + mov 8(%rsi),%r14 + mov 16(%rsi),%r13 + mov 24(%rsi),%r12 + mov 32(%rsi),%rbp + mov 40(%rsi),%rbx + lea 48(%rsi),%rsp +.Lepilogue_xop: + ret +.size ${func}_xop,.-${func}_xop +___ +} +###################################################################### +# AVX+shrd code path +# +local *ror = sub { &shrd(@_[0],@_) }; + +$code.=<<___; +.type ${func}_avx,\@function,3 +.align 64 +${func}_avx: +.Lavx_shortcut: + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + mov %rsp,%r11 # copy %rsp + shl \$4,%rdx # num*16 + sub \$`$framesz+$win64*16*($SZ==4?4:6)`,%rsp + lea ($inp,%rdx,$SZ),%rdx # inp+num*16*$SZ + and \$-64,%rsp # align stack frame + mov $ctx,$_ctx # save ctx, 1st arg + mov $inp,$_inp # save inp, 2nd arh + mov %rdx,$_end # save end pointer, "3rd" arg + mov %r11,$_rsp # save copy of %rsp +___ +$code.=<<___ if ($win64); + movaps %xmm6,16*$SZ+32(%rsp) + movaps %xmm7,16*$SZ+48(%rsp) + movaps %xmm8,16*$SZ+64(%rsp) + movaps %xmm9,16*$SZ+80(%rsp) +___ +$code.=<<___ if ($win64 && $SZ>4); + movaps %xmm10,16*$SZ+96(%rsp) + movaps %xmm11,16*$SZ+112(%rsp) +___ +$code.=<<___; +.Lprologue_avx: + + vzeroupper + mov $SZ*0($ctx),$A + mov $SZ*1($ctx),$B + mov $SZ*2($ctx),$C + mov $SZ*3($ctx),$D + mov $SZ*4($ctx),$E + mov $SZ*5($ctx),$F + mov $SZ*6($ctx),$G + mov $SZ*7($ctx),$H +___ + if ($SZ==4) { # SHA256 + my @X = map("%xmm$_",(0..3)); + my ($t0,$t1,$t2,$t3, $t4,$t5) = map("%xmm$_",(4..9)); + +$code.=<<___; + vmovdqa $TABLE+`$SZ*2*$rounds`+32(%rip),$t4 + vmovdqa $TABLE+`$SZ*2*$rounds`+64(%rip),$t5 + jmp .Lloop_avx +.align 16 +.Lloop_avx: + vmovdqa $TABLE+`$SZ*2*$rounds`(%rip),$t3 + vmovdqu 0x00($inp),@X[0] + vmovdqu 0x10($inp),@X[1] + vmovdqu 0x20($inp),@X[2] + vmovdqu 0x30($inp),@X[3] + vpshufb $t3,@X[0],@X[0] + lea $TABLE(%rip),$Tbl + vpshufb $t3,@X[1],@X[1] + vpshufb $t3,@X[2],@X[2] + vpaddd 0x00($Tbl),@X[0],$t0 + vpshufb $t3,@X[3],@X[3] + vpaddd 0x20($Tbl),@X[1],$t1 + vpaddd 0x40($Tbl),@X[2],$t2 + vpaddd 0x60($Tbl),@X[3],$t3 + vmovdqa $t0,0x00(%rsp) + mov $A,$a1 + vmovdqa $t1,0x10(%rsp) + mov $B,$a3 + vmovdqa $t2,0x20(%rsp) + xor $C,$a3 # magic + vmovdqa $t3,0x30(%rsp) + mov $E,$a0 + jmp .Lavx_00_47 + +.align 16 +.Lavx_00_47: + sub \$`-16*2*$SZ`,$Tbl # size optimization +___ +sub Xupdate_256_AVX () { + ( + '&vpalignr ($t0,@X[1],@X[0],$SZ)', # X[1..4] + '&vpalignr ($t3,@X[3],@X[2],$SZ)', # X[9..12] + '&vpsrld ($t2,$t0,$sigma0[0]);', + '&vpaddd (@X[0],@X[0],$t3)', # X[0..3] += X[9..12] + '&vpsrld ($t3,$t0,$sigma0[2])', + '&vpslld ($t1,$t0,8*$SZ-$sigma0[1]);', + '&vpxor ($t0,$t3,$t2)', + '&vpshufd ($t3,@X[3],0b11111010)',# X[14..15] + '&vpsrld ($t2,$t2,$sigma0[1]-$sigma0[0]);', + '&vpxor ($t0,$t0,$t1)', + '&vpslld ($t1,$t1,$sigma0[1]-$sigma0[0]);', + '&vpxor ($t0,$t0,$t2)', + '&vpsrld ($t2,$t3,$sigma1[2]);', + '&vpxor ($t0,$t0,$t1)', # sigma0(X[1..4]) + '&vpsrlq ($t3,$t3,$sigma1[0]);', + '&vpaddd (@X[0],@X[0],$t0)', # X[0..3] += sigma0(X[1..4]) + '&vpxor ($t2,$t2,$t3);', + '&vpsrlq ($t3,$t3,$sigma1[1]-$sigma1[0])', + '&vpxor ($t2,$t2,$t3)', + '&vpshufb ($t2,$t2,$t4)', # sigma1(X[14..15]) + '&vpaddd (@X[0],@X[0],$t2)', # X[0..1] += sigma1(X[14..15]) + '&vpshufd ($t3,@X[0],0b01010000)',# X[16..17] + '&vpsrld ($t2,$t3,$sigma1[2])', + '&vpsrlq ($t3,$t3,$sigma1[0])', + '&vpxor ($t2,$t2,$t3);', + '&vpsrlq ($t3,$t3,$sigma1[1]-$sigma1[0])', + '&vpxor ($t2,$t2,$t3)', + '&vpshufb ($t2,$t2,$t5)', + '&vpaddd (@X[0],@X[0],$t2)' # X[2..3] += sigma1(X[16..17]) + ); +} + +sub AVX_256_00_47 () { +my $j = shift; +my $body = shift; +my @X = @_; +my @insns = (&$body,&$body,&$body,&$body); # 104 instructions + + foreach (Xupdate_256_AVX()) { # 29 instructions + eval; + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + } + &vpaddd ($t2,@X[0],16*2*$j."($Tbl)"); + foreach (@insns) { eval; } # remaining instructions + &vmovdqa (16*$j."(%rsp)",$t2); +} + + for ($i=0,$j=0; $j<4; $j++) { + &AVX_256_00_47($j,\&body_00_15,@X); + push(@X,shift(@X)); # rotate(@X) + } + &cmpb ($SZ-1+16*2*$SZ."($Tbl)",0); + &jne (".Lavx_00_47"); + + for ($i=0; $i<16; ) { + foreach(body_00_15()) { eval; } + } + + } else { # SHA512 + my @X = map("%xmm$_",(0..7)); + my ($t0,$t1,$t2,$t3) = map("%xmm$_",(8..11)); + +$code.=<<___; + jmp .Lloop_avx +.align 16 +.Lloop_avx: + vmovdqa $TABLE+`$SZ*2*$rounds`(%rip),$t3 + vmovdqu 0x00($inp),@X[0] + lea $TABLE+0x80(%rip),$Tbl # size optimization + vmovdqu 0x10($inp),@X[1] + vmovdqu 0x20($inp),@X[2] + vpshufb $t3,@X[0],@X[0] + vmovdqu 0x30($inp),@X[3] + vpshufb $t3,@X[1],@X[1] + vmovdqu 0x40($inp),@X[4] + vpshufb $t3,@X[2],@X[2] + vmovdqu 0x50($inp),@X[5] + vpshufb $t3,@X[3],@X[3] + vmovdqu 0x60($inp),@X[6] + vpshufb $t3,@X[4],@X[4] + vmovdqu 0x70($inp),@X[7] + vpshufb $t3,@X[5],@X[5] + vpaddq -0x80($Tbl),@X[0],$t0 + vpshufb $t3,@X[6],@X[6] + vpaddq -0x60($Tbl),@X[1],$t1 + vpshufb $t3,@X[7],@X[7] + vpaddq -0x40($Tbl),@X[2],$t2 + vpaddq -0x20($Tbl),@X[3],$t3 + vmovdqa $t0,0x00(%rsp) + vpaddq 0x00($Tbl),@X[4],$t0 + vmovdqa $t1,0x10(%rsp) + vpaddq 0x20($Tbl),@X[5],$t1 + vmovdqa $t2,0x20(%rsp) + vpaddq 0x40($Tbl),@X[6],$t2 + vmovdqa $t3,0x30(%rsp) + vpaddq 0x60($Tbl),@X[7],$t3 + vmovdqa $t0,0x40(%rsp) + mov $A,$a1 + vmovdqa $t1,0x50(%rsp) + mov $B,$a3 + vmovdqa $t2,0x60(%rsp) + xor $C,$a3 # magic + vmovdqa $t3,0x70(%rsp) + mov $E,$a0 + jmp .Lavx_00_47 + +.align 16 +.Lavx_00_47: + add \$`16*2*$SZ`,$Tbl +___ +sub Xupdate_512_AVX () { + ( + '&vpalignr ($t0,@X[1],@X[0],$SZ)', # X[1..2] + '&vpalignr ($t3,@X[5],@X[4],$SZ)', # X[9..10] + '&vpsrlq ($t2,$t0,$sigma0[0])', + '&vpaddq (@X[0],@X[0],$t3);', # X[0..1] += X[9..10] + '&vpsrlq ($t3,$t0,$sigma0[2])', + '&vpsllq ($t1,$t0,8*$SZ-$sigma0[1]);', + '&vpxor ($t0,$t3,$t2)', + '&vpsrlq ($t2,$t2,$sigma0[1]-$sigma0[0]);', + '&vpxor ($t0,$t0,$t1)', + '&vpsllq ($t1,$t1,$sigma0[1]-$sigma0[0]);', + '&vpxor ($t0,$t0,$t2)', + '&vpsrlq ($t3,@X[7],$sigma1[2]);', + '&vpxor ($t0,$t0,$t1)', # sigma0(X[1..2]) + '&vpsllq ($t2,@X[7],8*$SZ-$sigma1[1]);', + '&vpaddq (@X[0],@X[0],$t0)', # X[0..1] += sigma0(X[1..2]) + '&vpsrlq ($t1,@X[7],$sigma1[0]);', + '&vpxor ($t3,$t3,$t2)', + '&vpsllq ($t2,$t2,$sigma1[1]-$sigma1[0]);', + '&vpxor ($t3,$t3,$t1)', + '&vpsrlq ($t1,$t1,$sigma1[1]-$sigma1[0]);', + '&vpxor ($t3,$t3,$t2)', + '&vpxor ($t3,$t3,$t1)', # sigma1(X[14..15]) + '&vpaddq (@X[0],@X[0],$t3)', # X[0..1] += sigma1(X[14..15]) + ); +} + +sub AVX_512_00_47 () { +my $j = shift; +my $body = shift; +my @X = @_; +my @insns = (&$body,&$body); # 52 instructions + + foreach (Xupdate_512_AVX()) { # 23 instructions + eval; + eval(shift(@insns)); + eval(shift(@insns)); + } + &vpaddq ($t2,@X[0],16*2*$j-0x80."($Tbl)"); + foreach (@insns) { eval; } # remaining instructions + &vmovdqa (16*$j."(%rsp)",$t2); +} + + for ($i=0,$j=0; $j<8; $j++) { + &AVX_512_00_47($j,\&body_00_15,@X); + push(@X,shift(@X)); # rotate(@X) + } + &cmpb ($SZ-1+16*2*$SZ-0x80."($Tbl)",0); + &jne (".Lavx_00_47"); + + for ($i=0; $i<16; ) { + foreach(body_00_15()) { eval; } + } +} +$code.=<<___; + mov $_ctx,$ctx + mov $a1,$A + + add $SZ*0($ctx),$A + lea 16*$SZ($inp),$inp + add $SZ*1($ctx),$B + add $SZ*2($ctx),$C + add $SZ*3($ctx),$D + add $SZ*4($ctx),$E + add $SZ*5($ctx),$F + add $SZ*6($ctx),$G + add $SZ*7($ctx),$H + + cmp $_end,$inp + + mov $A,$SZ*0($ctx) + mov $B,$SZ*1($ctx) + mov $C,$SZ*2($ctx) + mov $D,$SZ*3($ctx) + mov $E,$SZ*4($ctx) + mov $F,$SZ*5($ctx) + mov $G,$SZ*6($ctx) + mov $H,$SZ*7($ctx) + jb .Lloop_avx + + mov $_rsp,%rsi + vzeroupper +___ +$code.=<<___ if ($win64); + movaps 16*$SZ+32(%rsp),%xmm6 + movaps 16*$SZ+48(%rsp),%xmm7 + movaps 16*$SZ+64(%rsp),%xmm8 + movaps 16*$SZ+80(%rsp),%xmm9 +___ +$code.=<<___ if ($win64 && $SZ>4); + movaps 16*$SZ+96(%rsp),%xmm10 + movaps 16*$SZ+112(%rsp),%xmm11 +___ +$code.=<<___; + mov (%rsi),%r15 + mov 8(%rsi),%r14 + mov 16(%rsi),%r13 + mov 24(%rsi),%r12 + mov 32(%rsi),%rbp + mov 40(%rsi),%rbx + lea 48(%rsi),%rsp +.Lepilogue_avx: + ret +.size ${func}_avx,.-${func}_avx +___ + +if ($avx>1) {{ +###################################################################### +# AVX2+BMI code path +# +my $a5=$SZ==4?"%esi":"%rsi"; # zap $inp +my $PUSH8=8*2*$SZ; +use integer; + +sub bodyx_00_15 () { + # at start $a1 should be zero, $a3 - $b^$c and $a4 copy of $f + ( + '($a,$b,$c,$d,$e,$f,$g,$h)=@ROT;'. + + '&add ($h,(32*($i/(16/$SZ))+$SZ*($i%(16/$SZ)))%$PUSH8.$base)', # h+=X[i]+K[i] + '&and ($a4,$e)', # f&e + '&rorx ($a0,$e,$Sigma1[2])', + '&rorx ($a2,$e,$Sigma1[1])', + + '&lea ($a,"($a,$a1)")', # h+=Sigma0(a) from the past + '&lea ($h,"($h,$a4)")', + '&andn ($a4,$e,$g)', # ~e&g + '&xor ($a0,$a2)', + + '&rorx ($a1,$e,$Sigma1[0])', + '&lea ($h,"($h,$a4)")', # h+=Ch(e,f,g)=(e&f)+(~e&g) + '&xor ($a0,$a1)', # Sigma1(e) + '&mov ($a2,$a)', + + '&rorx ($a4,$a,$Sigma0[2])', + '&lea ($h,"($h,$a0)")', # h+=Sigma1(e) + '&xor ($a2,$b)', # a^b, b^c in next round + '&rorx ($a1,$a,$Sigma0[1])', + + '&rorx ($a0,$a,$Sigma0[0])', + '&lea ($d,"($d,$h)")', # d+=h + '&and ($a3,$a2)', # (b^c)&(a^b) + '&xor ($a1,$a4)', + + '&xor ($a3,$b)', # Maj(a,b,c)=Ch(a^b,c,b) + '&xor ($a1,$a0)', # Sigma0(a) + '&lea ($h,"($h,$a3)");'. # h+=Maj(a,b,c) + '&mov ($a4,$e)', # copy of f in future + + '($a2,$a3) = ($a3,$a2); unshift(@ROT,pop(@ROT)); $i++;' + ); + # and at the finish one has to $a+=$a1 +} + +$code.=<<___; +.type ${func}_avx2,\@function,3 +.align 64 +${func}_avx2: +.Lavx2_shortcut: + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + mov %rsp,%r11 # copy %rsp + sub \$`2*$SZ*$rounds+4*8+$win64*16*($SZ==4?4:6)`,%rsp + shl \$4,%rdx # num*16 + and \$-256*$SZ,%rsp # align stack frame + lea ($inp,%rdx,$SZ),%rdx # inp+num*16*$SZ + add \$`2*$SZ*($rounds-8)`,%rsp + mov $ctx,$_ctx # save ctx, 1st arg + mov $inp,$_inp # save inp, 2nd arh + mov %rdx,$_end # save end pointer, "3rd" arg + mov %r11,$_rsp # save copy of %rsp +___ +$code.=<<___ if ($win64); + movaps %xmm6,16*$SZ+32(%rsp) + movaps %xmm7,16*$SZ+48(%rsp) + movaps %xmm8,16*$SZ+64(%rsp) + movaps %xmm9,16*$SZ+80(%rsp) +___ +$code.=<<___ if ($win64 && $SZ>4); + movaps %xmm10,16*$SZ+96(%rsp) + movaps %xmm11,16*$SZ+112(%rsp) +___ +$code.=<<___; +.Lprologue_avx2: + + vzeroupper + sub \$-16*$SZ,$inp # inp++, size optimization + mov $SZ*0($ctx),$A + mov $inp,%r12 # borrow $T1 + mov $SZ*1($ctx),$B + cmp %rdx,$inp # $_end + mov $SZ*2($ctx),$C + cmove %rsp,%r12 # next block or random data + mov $SZ*3($ctx),$D + mov $SZ*4($ctx),$E + mov $SZ*5($ctx),$F + mov $SZ*6($ctx),$G + mov $SZ*7($ctx),$H +___ + if ($SZ==4) { # SHA256 + my @X = map("%ymm$_",(0..3)); + my ($t0,$t1,$t2,$t3, $t4,$t5) = map("%ymm$_",(4..9)); + +$code.=<<___; + vmovdqa $TABLE+`$SZ*2*$rounds`+32(%rip),$t4 + vmovdqa $TABLE+`$SZ*2*$rounds`+64(%rip),$t5 + jmp .Loop_avx2 +.align 16 +.Loop_avx2: + vmovdqa $TABLE+`$SZ*2*$rounds`(%rip),$t3 + vmovdqu -16*$SZ+0($inp),%xmm0 + vmovdqu -16*$SZ+16($inp),%xmm1 + vmovdqu -16*$SZ+32($inp),%xmm2 + vmovdqu -16*$SZ+48($inp),%xmm3 + #mov $inp,$_inp # offload $inp + vinserti128 \$1,(%r12),@X[0],@X[0] + vinserti128 \$1,16(%r12),@X[1],@X[1] + vpshufb $t3,@X[0],@X[0] + vinserti128 \$1,32(%r12),@X[2],@X[2] + vpshufb $t3,@X[1],@X[1] + vinserti128 \$1,48(%r12),@X[3],@X[3] + + lea $TABLE(%rip),$Tbl + vpshufb $t3,@X[2],@X[2] + vpaddd 0x00($Tbl),@X[0],$t0 + vpshufb $t3,@X[3],@X[3] + vpaddd 0x20($Tbl),@X[1],$t1 + vpaddd 0x40($Tbl),@X[2],$t2 + vpaddd 0x60($Tbl),@X[3],$t3 + vmovdqa $t0,0x00(%rsp) + xor $a1,$a1 + vmovdqa $t1,0x20(%rsp) + lea -$PUSH8(%rsp),%rsp + mov $B,$a3 + vmovdqa $t2,0x00(%rsp) + xor $C,$a3 # magic + vmovdqa $t3,0x20(%rsp) + mov $F,$a4 + sub \$-16*2*$SZ,$Tbl # size optimization + jmp .Lavx2_00_47 + +.align 16 +.Lavx2_00_47: +___ + +sub AVX2_256_00_47 () { +my $j = shift; +my $body = shift; +my @X = @_; +my @insns = (&$body,&$body,&$body,&$body); # 96 instructions +my $base = "+2*$PUSH8(%rsp)"; + + &lea ("%rsp","-$PUSH8(%rsp)") if (($j%2)==0); + foreach (Xupdate_256_AVX()) { # 29 instructions + eval; + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + } + &vpaddd ($t2,@X[0],16*2*$j."($Tbl)"); + foreach (@insns) { eval; } # remaining instructions + &vmovdqa ((32*$j)%$PUSH8."(%rsp)",$t2); +} + + for ($i=0,$j=0; $j<4; $j++) { + &AVX2_256_00_47($j,\&bodyx_00_15,@X); + push(@X,shift(@X)); # rotate(@X) + } + &lea ($Tbl,16*2*$SZ."($Tbl)"); + &cmpb (($SZ-1)."($Tbl)",0); + &jne (".Lavx2_00_47"); + + for ($i=0; $i<16; ) { + my $base=$i<8?"+$PUSH8(%rsp)":"(%rsp)"; + foreach(bodyx_00_15()) { eval; } + } + } else { # SHA512 + my @X = map("%ymm$_",(0..7)); + my ($t0,$t1,$t2,$t3) = map("%ymm$_",(8..11)); + +$code.=<<___; + jmp .Loop_avx2 +.align 16 +.Loop_avx2: + vmovdqu -16*$SZ($inp),%xmm0 + vmovdqu -16*$SZ+16($inp),%xmm1 + vmovdqu -16*$SZ+32($inp),%xmm2 + lea $TABLE+0x80(%rip),$Tbl # size optimization + vmovdqu -16*$SZ+48($inp),%xmm3 + vmovdqu -16*$SZ+64($inp),%xmm4 + vmovdqu -16*$SZ+80($inp),%xmm5 + vmovdqu -16*$SZ+96($inp),%xmm6 + vmovdqu -16*$SZ+112($inp),%xmm7 + #mov $inp,$_inp # offload $inp + vmovdqa `$SZ*2*$rounds-0x80`($Tbl),$t2 + vinserti128 \$1,(%r12),@X[0],@X[0] + vinserti128 \$1,16(%r12),@X[1],@X[1] + vpshufb $t2,@X[0],@X[0] + vinserti128 \$1,32(%r12),@X[2],@X[2] + vpshufb $t2,@X[1],@X[1] + vinserti128 \$1,48(%r12),@X[3],@X[3] + vpshufb $t2,@X[2],@X[2] + vinserti128 \$1,64(%r12),@X[4],@X[4] + vpshufb $t2,@X[3],@X[3] + vinserti128 \$1,80(%r12),@X[5],@X[5] + vpshufb $t2,@X[4],@X[4] + vinserti128 \$1,96(%r12),@X[6],@X[6] + vpshufb $t2,@X[5],@X[5] + vinserti128 \$1,112(%r12),@X[7],@X[7] + + vpaddq -0x80($Tbl),@X[0],$t0 + vpshufb $t2,@X[6],@X[6] + vpaddq -0x60($Tbl),@X[1],$t1 + vpshufb $t2,@X[7],@X[7] + vpaddq -0x40($Tbl),@X[2],$t2 + vpaddq -0x20($Tbl),@X[3],$t3 + vmovdqa $t0,0x00(%rsp) + vpaddq 0x00($Tbl),@X[4],$t0 + vmovdqa $t1,0x20(%rsp) + vpaddq 0x20($Tbl),@X[5],$t1 + vmovdqa $t2,0x40(%rsp) + vpaddq 0x40($Tbl),@X[6],$t2 + vmovdqa $t3,0x60(%rsp) + lea -$PUSH8(%rsp),%rsp + vpaddq 0x60($Tbl),@X[7],$t3 + vmovdqa $t0,0x00(%rsp) + xor $a1,$a1 + vmovdqa $t1,0x20(%rsp) + mov $B,$a3 + vmovdqa $t2,0x40(%rsp) + xor $C,$a3 # magic + vmovdqa $t3,0x60(%rsp) + mov $F,$a4 + add \$16*2*$SZ,$Tbl + jmp .Lavx2_00_47 + +.align 16 +.Lavx2_00_47: +___ + +sub AVX2_512_00_47 () { +my $j = shift; +my $body = shift; +my @X = @_; +my @insns = (&$body,&$body); # 48 instructions +my $base = "+2*$PUSH8(%rsp)"; + + &lea ("%rsp","-$PUSH8(%rsp)") if (($j%4)==0); + foreach (Xupdate_512_AVX()) { # 23 instructions + eval; + if ($_ !~ /\;$/) { + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + } + } + &vpaddq ($t2,@X[0],16*2*$j-0x80."($Tbl)"); + foreach (@insns) { eval; } # remaining instructions + &vmovdqa ((32*$j)%$PUSH8."(%rsp)",$t2); +} + + for ($i=0,$j=0; $j<8; $j++) { + &AVX2_512_00_47($j,\&bodyx_00_15,@X); + push(@X,shift(@X)); # rotate(@X) + } + &lea ($Tbl,16*2*$SZ."($Tbl)"); + &cmpb (($SZ-1-0x80)."($Tbl)",0); + &jne (".Lavx2_00_47"); + + for ($i=0; $i<16; ) { + my $base=$i<8?"+$PUSH8(%rsp)":"(%rsp)"; + foreach(bodyx_00_15()) { eval; } + } +} +$code.=<<___; + mov `2*$SZ*$rounds`(%rsp),$ctx # $_ctx + add $a1,$A + #mov `2*$SZ*$rounds+8`(%rsp),$inp # $_inp + lea `2*$SZ*($rounds-8)`(%rsp),$Tbl + + add $SZ*0($ctx),$A + add $SZ*1($ctx),$B + add $SZ*2($ctx),$C + add $SZ*3($ctx),$D + add $SZ*4($ctx),$E + add $SZ*5($ctx),$F + add $SZ*6($ctx),$G + add $SZ*7($ctx),$H + + mov $A,$SZ*0($ctx) + mov $B,$SZ*1($ctx) + mov $C,$SZ*2($ctx) + mov $D,$SZ*3($ctx) + mov $E,$SZ*4($ctx) + mov $F,$SZ*5($ctx) + mov $G,$SZ*6($ctx) + mov $H,$SZ*7($ctx) + + cmp `$PUSH8+2*8`($Tbl),$inp # $_end + je .Ldone_avx2 + + xor $a1,$a1 + mov $B,$a3 + xor $C,$a3 # magic + mov $F,$a4 + jmp .Lower_avx2 +.align 16 +.Lower_avx2: +___ + for ($i=0; $i<8; ) { + my $base="+16($Tbl)"; + foreach(bodyx_00_15()) { eval; } + } +$code.=<<___; + lea -$PUSH8($Tbl),$Tbl + cmp %rsp,$Tbl + jae .Lower_avx2 + + mov `2*$SZ*$rounds`(%rsp),$ctx # $_ctx + add $a1,$A + #mov `2*$SZ*$rounds+8`(%rsp),$inp # $_inp + lea `2*$SZ*($rounds-8)`(%rsp),%rsp + + add $SZ*0($ctx),$A + add $SZ*1($ctx),$B + add $SZ*2($ctx),$C + add $SZ*3($ctx),$D + add $SZ*4($ctx),$E + add $SZ*5($ctx),$F + lea `2*16*$SZ`($inp),$inp # inp+=2 + add $SZ*6($ctx),$G + mov $inp,%r12 + add $SZ*7($ctx),$H + cmp $_end,$inp + + mov $A,$SZ*0($ctx) + cmove %rsp,%r12 # next block or stale data + mov $B,$SZ*1($ctx) + mov $C,$SZ*2($ctx) + mov $D,$SZ*3($ctx) + mov $E,$SZ*4($ctx) + mov $F,$SZ*5($ctx) + mov $G,$SZ*6($ctx) + mov $H,$SZ*7($ctx) + + jbe .Loop_avx2 + lea (%rsp),$Tbl + +.Ldone_avx2: + lea ($Tbl),%rsp + mov $_rsp,%rsi + vzeroupper +___ +$code.=<<___ if ($win64); + movaps 16*$SZ+32(%rsp),%xmm6 + movaps 16*$SZ+48(%rsp),%xmm7 + movaps 16*$SZ+64(%rsp),%xmm8 + movaps 16*$SZ+80(%rsp),%xmm9 +___ +$code.=<<___ if ($win64 && $SZ>4); + movaps 16*$SZ+96(%rsp),%xmm10 + movaps 16*$SZ+112(%rsp),%xmm11 +___ +$code.=<<___; + mov (%rsi),%r15 + mov 8(%rsi),%r14 + mov 16(%rsi),%r13 + mov 24(%rsi),%r12 + mov 32(%rsi),%rbp + mov 40(%rsi),%rbx + lea 48(%rsi),%rsp +.Lepilogue_avx2: + ret +.size ${func}_avx2,.-${func}_avx2 +___ +}} +}}}}} + +# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame, +# CONTEXT *context,DISPATCHER_CONTEXT *disp) +if ($win64) { +$rec="%rcx"; +$frame="%rdx"; +$context="%r8"; +$disp="%r9"; + +$code.=<<___; +.extern __imp_RtlVirtualUnwind +.type se_handler,\@abi-omnipotent +.align 16 +se_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + mov 8($disp),%rsi # disp->ImageBase + mov 56($disp),%r11 # disp->HanderlData + + mov 0(%r11),%r10d # HandlerData[0] + lea (%rsi,%r10),%r10 # prologue label + cmp %r10,%rbx # context->RipRsp + + mov 4(%r11),%r10d # HandlerData[1] + lea (%rsi,%r10),%r10 # epilogue label + cmp %r10,%rbx # context->Rip>=epilogue label + jae .Lin_prologue +___ +$code.=<<___ if ($avx>1); + lea .Lavx2_shortcut(%rip),%r10 + cmp %r10,%rbx # context->RipRbx + mov %rbp,160($context) # restore context->Rbp + mov %r12,216($context) # restore context->R12 + mov %r13,224($context) # restore context->R13 + mov %r14,232($context) # restore context->R14 + mov %r15,240($context) # restore context->R15 + + lea .Lepilogue(%rip),%r10 + cmp %r10,%rbx + jb .Lin_prologue # non-AVX code + + lea 16*$SZ+4*8(%rsi),%rsi # Xmm6- save area + lea 512($context),%rdi # &context.Xmm6 + mov \$`$SZ==4?8:12`,%ecx + .long 0xa548f3fc # cld; rep movsq + +.Lin_prologue: + mov 8(%rax),%rdi + mov 16(%rax),%rsi + mov %rax,152($context) # restore context->Rsp + mov %rsi,168($context) # restore context->Rsi + mov %rdi,176($context) # restore context->Rdi + + mov 40($disp),%rdi # disp->ContextRecord + mov $context,%rsi # context + mov \$154,%ecx # sizeof(CONTEXT) + .long 0xa548f3fc # cld; rep movsq + + mov $disp,%rsi + xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER + mov 8(%rsi),%rdx # arg2, disp->ImageBase + mov 0(%rsi),%r8 # arg3, disp->ControlPc + mov 16(%rsi),%r9 # arg4, disp->FunctionEntry + mov 40(%rsi),%r10 # disp->ContextRecord + lea 56(%rsi),%r11 # &disp->HandlerData + lea 24(%rsi),%r12 # &disp->EstablisherFrame + mov %r10,32(%rsp) # arg5 + mov %r11,40(%rsp) # arg6 + mov %r12,48(%rsp) # arg7 + mov %rcx,56(%rsp) # arg8, (NULL) + call *__imp_RtlVirtualUnwind(%rip) + + mov \$1,%eax # ExceptionContinueSearch + add \$64,%rsp + popfq + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + pop %rdi + pop %rsi + ret +.size se_handler,.-se_handler +___ + +$code.=<<___ if ($SZ==4 && $shaext); +.type shaext_handler,\@abi-omnipotent +.align 16 +shaext_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + lea .Lprologue_shaext(%rip),%r10 + cmp %r10,%rbx # context->Rip<.Lprologue + jb .Lin_prologue + + lea .Lepilogue_shaext(%rip),%r10 + cmp %r10,%rbx # context->Rip>=.Lepilogue + jae .Lin_prologue + + lea -8-5*16(%rax),%rsi + lea 512($context),%rdi # &context.Xmm6 + mov \$10,%ecx + .long 0xa548f3fc # cld; rep movsq + + jmp .Lin_prologue +.size shaext_handler,.-shaext_handler +___ + +$code.=<<___; +.section .pdata +.align 4 + .rva .LSEH_begin_$func + .rva .LSEH_end_$func + .rva .LSEH_info_$func +___ +$code.=<<___ if ($SZ==4 && $shaext); + .rva .LSEH_begin_${func}_shaext + .rva .LSEH_end_${func}_shaext + .rva .LSEH_info_${func}_shaext +___ +$code.=<<___ if ($SZ==4); + .rva .LSEH_begin_${func}_ssse3 + .rva .LSEH_end_${func}_ssse3 + .rva .LSEH_info_${func}_ssse3 +___ +$code.=<<___ if ($avx && $SZ==8); + .rva .LSEH_begin_${func}_xop + .rva .LSEH_end_${func}_xop + .rva .LSEH_info_${func}_xop +___ +$code.=<<___ if ($avx); + .rva .LSEH_begin_${func}_avx + .rva .LSEH_end_${func}_avx + .rva .LSEH_info_${func}_avx +___ +$code.=<<___ if ($avx>1); + .rva .LSEH_begin_${func}_avx2 + .rva .LSEH_end_${func}_avx2 + .rva .LSEH_info_${func}_avx2 +___ +$code.=<<___; +.section .xdata +.align 8 +.LSEH_info_$func: + .byte 9,0,0,0 + .rva se_handler + .rva .Lprologue,.Lepilogue # HandlerData[] +___ +$code.=<<___ if ($SZ==4 && $shaext); +.LSEH_info_${func}_shaext: + .byte 9,0,0,0 + .rva shaext_handler +___ +$code.=<<___ if ($SZ==4); +.LSEH_info_${func}_ssse3: + .byte 9,0,0,0 + .rva se_handler + .rva .Lprologue_ssse3,.Lepilogue_ssse3 # HandlerData[] +___ +$code.=<<___ if ($avx && $SZ==8); +.LSEH_info_${func}_xop: + .byte 9,0,0,0 + .rva se_handler + .rva .Lprologue_xop,.Lepilogue_xop # HandlerData[] +___ +$code.=<<___ if ($avx); +.LSEH_info_${func}_avx: + .byte 9,0,0,0 + .rva se_handler + .rva .Lprologue_avx,.Lepilogue_avx # HandlerData[] +___ +$code.=<<___ if ($avx>1); +.LSEH_info_${func}_avx2: + .byte 9,0,0,0 + .rva se_handler + .rva .Lprologue_avx2,.Lepilogue_avx2 # HandlerData[] +___ +} + +sub sha256op38 { + my $instr = shift; + my %opcodelet = ( + "sha256rnds2" => 0xcb, + "sha256msg1" => 0xcc, + "sha256msg2" => 0xcd ); + + if (defined($opcodelet{$instr}) && @_[0] =~ /%xmm([0-7]),\s*%xmm([0-7])/) { + my @opcode=(0x0f,0x38); + push @opcode,$opcodelet{$instr}; + push @opcode,0xc0|($1&7)|(($2&7)<<3); # ModR/M + return ".byte\t".join(',',@opcode); + } else { + return $instr."\t".@_[0]; + } +} + +foreach (split("\n",$code)) { + s/\`([^\`]*)\`/eval $1/geo; + + s/\b(sha256[^\s]*)\s+(.*)/sha256op38($1,$2)/geo; + + print $_,"\n"; +} +close STDOUT; diff --git a/external/boringssl/crypto/sha/sha1.c b/external/boringssl/crypto/sha/sha1.c new file mode 100644 index 0000000000..74e841caff --- /dev/null +++ b/external/boringssl/crypto/sha/sha1.c @@ -0,0 +1,337 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include + + +#if !defined(OPENSSL_NO_ASM) && \ + (defined(OPENSSL_X86) || defined(OPENSSL_X86_64) || \ + defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)) +#define SHA1_ASM +#endif + +int SHA1_Init(SHA_CTX *sha) { + memset(sha, 0, sizeof(SHA_CTX)); + sha->h[0] = 0x67452301UL; + sha->h[1] = 0xefcdab89UL; + sha->h[2] = 0x98badcfeUL; + sha->h[3] = 0x10325476UL; + sha->h[4] = 0xc3d2e1f0UL; + return 1; +} + +uint8_t *SHA1(const uint8_t *data, size_t len, uint8_t *out) { + SHA_CTX ctx; + static uint8_t buf[SHA_DIGEST_LENGTH]; + + /* TODO(fork): remove this static buffer. */ + if (out == NULL) { + out = buf; + } + if (!SHA1_Init(&ctx)) { + return NULL; + } + SHA1_Update(&ctx, data, len); + SHA1_Final(out, &ctx); + OPENSSL_cleanse(&ctx, sizeof(ctx)); + return out; +} + +#define DATA_ORDER_IS_BIG_ENDIAN + +#define HASH_CTX SHA_CTX +#define HASH_CBLOCK 64 +#define HASH_MAKE_STRING(c, s) \ + do { \ + uint32_t ll; \ + ll = (c)->h[0]; \ + HOST_l2c(ll, (s)); \ + ll = (c)->h[1]; \ + HOST_l2c(ll, (s)); \ + ll = (c)->h[2]; \ + HOST_l2c(ll, (s)); \ + ll = (c)->h[3]; \ + HOST_l2c(ll, (s)); \ + ll = (c)->h[4]; \ + HOST_l2c(ll, (s)); \ + } while (0) + +#define HASH_UPDATE SHA1_Update +#define HASH_TRANSFORM SHA1_Transform +#define HASH_FINAL SHA1_Final +#define HASH_BLOCK_DATA_ORDER sha1_block_data_order +#define ROTATE(a, n) (((a) << (n)) | ((a) >> (32 - (n)))) +#define Xupdate(a, ix, ia, ib, ic, id) \ + ((a) = (ia ^ ib ^ ic ^ id), ix = (a) = ROTATE((a), 1)) + +#ifndef SHA1_ASM +static +#endif +void sha1_block_data_order(uint32_t *state, const uint8_t *data, size_t num); + +#include "../digest/md32_common.h" + +#define K_00_19 0x5a827999UL +#define K_20_39 0x6ed9eba1UL +#define K_40_59 0x8f1bbcdcUL +#define K_60_79 0xca62c1d6UL + +/* As pointed out by Wei Dai , F() below can be simplified + * to the code in F_00_19. Wei attributes these optimisations to Peter + * Gutmann's SHS code, and he attributes it to Rich Schroeppel. #define + * F(x,y,z) (((x) & (y)) | ((~(x)) & (z))) I've just become aware of another + * tweak to be made, again from Wei Dai, in F_40_59, (x&a)|(y&a) -> (x|y)&a */ +#define F_00_19(b, c, d) ((((c) ^ (d)) & (b)) ^ (d)) +#define F_20_39(b, c, d) ((b) ^ (c) ^ (d)) +#define F_40_59(b, c, d) (((b) & (c)) | (((b) | (c)) & (d))) +#define F_60_79(b, c, d) F_20_39(b, c, d) + +#define BODY_00_15(i, a, b, c, d, e, f, xi) \ + (f) = xi + (e) + K_00_19 + ROTATE((a), 5) + F_00_19((b), (c), (d)); \ + (b) = ROTATE((b), 30); + +#define BODY_16_19(i, a, b, c, d, e, f, xi, xa, xb, xc, xd) \ + Xupdate(f, xi, xa, xb, xc, xd); \ + (f) += (e) + K_00_19 + ROTATE((a), 5) + F_00_19((b), (c), (d)); \ + (b) = ROTATE((b), 30); + +#define BODY_20_31(i, a, b, c, d, e, f, xi, xa, xb, xc, xd) \ + Xupdate(f, xi, xa, xb, xc, xd); \ + (f) += (e) + K_20_39 + ROTATE((a), 5) + F_20_39((b), (c), (d)); \ + (b) = ROTATE((b), 30); + +#define BODY_32_39(i, a, b, c, d, e, f, xa, xb, xc, xd) \ + Xupdate(f, xa, xa, xb, xc, xd); \ + (f) += (e) + K_20_39 + ROTATE((a), 5) + F_20_39((b), (c), (d)); \ + (b) = ROTATE((b), 30); + +#define BODY_40_59(i, a, b, c, d, e, f, xa, xb, xc, xd) \ + Xupdate(f, xa, xa, xb, xc, xd); \ + (f) += (e) + K_40_59 + ROTATE((a), 5) + F_40_59((b), (c), (d)); \ + (b) = ROTATE((b), 30); + +#define BODY_60_79(i, a, b, c, d, e, f, xa, xb, xc, xd) \ + Xupdate(f, xa, xa, xb, xc, xd); \ + (f) = xa + (e) + K_60_79 + ROTATE((a), 5) + F_60_79((b), (c), (d)); \ + (b) = ROTATE((b), 30); + +#ifdef X +#undef X +#endif + +/* Originally X was an array. As it's automatic it's natural +* to expect RISC compiler to accomodate at least part of it in +* the register bank, isn't it? Unfortunately not all compilers +* "find" this expectation reasonable:-( On order to make such +* compilers generate better code I replace X[] with a bunch of +* X0, X1, etc. See the function body below... +* */ +#define X(i) XX##i + +#if !defined(SHA1_ASM) +static void sha1_block_data_order(uint32_t *state, const uint8_t *data, + size_t num) { + register uint32_t A, B, C, D, E, T, l; + uint32_t XX0, XX1, XX2, XX3, XX4, XX5, XX6, XX7, XX8, XX9, XX10, + XX11, XX12, XX13, XX14, XX15; + + A = state[0]; + B = state[1]; + C = state[2]; + D = state[3]; + E = state[4]; + + for (;;) { + (void)HOST_c2l(data, l); + X(0) = l; + (void)HOST_c2l(data, l); + X(1) = l; + BODY_00_15(0, A, B, C, D, E, T, X(0)); + (void)HOST_c2l(data, l); + X(2) = l; + BODY_00_15(1, T, A, B, C, D, E, X(1)); + (void)HOST_c2l(data, l); + X(3) = l; + BODY_00_15(2, E, T, A, B, C, D, X(2)); + (void)HOST_c2l(data, l); + X(4) = l; + BODY_00_15(3, D, E, T, A, B, C, X(3)); + (void)HOST_c2l(data, l); + X(5) = l; + BODY_00_15(4, C, D, E, T, A, B, X(4)); + (void)HOST_c2l(data, l); + X(6) = l; + BODY_00_15(5, B, C, D, E, T, A, X(5)); + (void)HOST_c2l(data, l); + X(7) = l; + BODY_00_15(6, A, B, C, D, E, T, X(6)); + (void)HOST_c2l(data, l); + X(8) = l; + BODY_00_15(7, T, A, B, C, D, E, X(7)); + (void)HOST_c2l(data, l); + X(9) = l; + BODY_00_15(8, E, T, A, B, C, D, X(8)); + (void)HOST_c2l(data, l); + X(10) = l; + BODY_00_15(9, D, E, T, A, B, C, X(9)); + (void)HOST_c2l(data, l); + X(11) = l; + BODY_00_15(10, C, D, E, T, A, B, X(10)); + (void)HOST_c2l(data, l); + X(12) = l; + BODY_00_15(11, B, C, D, E, T, A, X(11)); + (void)HOST_c2l(data, l); + X(13) = l; + BODY_00_15(12, A, B, C, D, E, T, X(12)); + (void)HOST_c2l(data, l); + X(14) = l; + BODY_00_15(13, T, A, B, C, D, E, X(13)); + (void)HOST_c2l(data, l); + X(15) = l; + BODY_00_15(14, E, T, A, B, C, D, X(14)); + BODY_00_15(15, D, E, T, A, B, C, X(15)); + + BODY_16_19(16, C, D, E, T, A, B, X(0), X(0), X(2), X(8), X(13)); + BODY_16_19(17, B, C, D, E, T, A, X(1), X(1), X(3), X(9), X(14)); + BODY_16_19(18, A, B, C, D, E, T, X(2), X(2), X(4), X(10), X(15)); + BODY_16_19(19, T, A, B, C, D, E, X(3), X(3), X(5), X(11), X(0)); + + BODY_20_31(20, E, T, A, B, C, D, X(4), X(4), X(6), X(12), X(1)); + BODY_20_31(21, D, E, T, A, B, C, X(5), X(5), X(7), X(13), X(2)); + BODY_20_31(22, C, D, E, T, A, B, X(6), X(6), X(8), X(14), X(3)); + BODY_20_31(23, B, C, D, E, T, A, X(7), X(7), X(9), X(15), X(4)); + BODY_20_31(24, A, B, C, D, E, T, X(8), X(8), X(10), X(0), X(5)); + BODY_20_31(25, T, A, B, C, D, E, X(9), X(9), X(11), X(1), X(6)); + BODY_20_31(26, E, T, A, B, C, D, X(10), X(10), X(12), X(2), X(7)); + BODY_20_31(27, D, E, T, A, B, C, X(11), X(11), X(13), X(3), X(8)); + BODY_20_31(28, C, D, E, T, A, B, X(12), X(12), X(14), X(4), X(9)); + BODY_20_31(29, B, C, D, E, T, A, X(13), X(13), X(15), X(5), X(10)); + BODY_20_31(30, A, B, C, D, E, T, X(14), X(14), X(0), X(6), X(11)); + BODY_20_31(31, T, A, B, C, D, E, X(15), X(15), X(1), X(7), X(12)); + + BODY_32_39(32, E, T, A, B, C, D, X(0), X(2), X(8), X(13)); + BODY_32_39(33, D, E, T, A, B, C, X(1), X(3), X(9), X(14)); + BODY_32_39(34, C, D, E, T, A, B, X(2), X(4), X(10), X(15)); + BODY_32_39(35, B, C, D, E, T, A, X(3), X(5), X(11), X(0)); + BODY_32_39(36, A, B, C, D, E, T, X(4), X(6), X(12), X(1)); + BODY_32_39(37, T, A, B, C, D, E, X(5), X(7), X(13), X(2)); + BODY_32_39(38, E, T, A, B, C, D, X(6), X(8), X(14), X(3)); + BODY_32_39(39, D, E, T, A, B, C, X(7), X(9), X(15), X(4)); + + BODY_40_59(40, C, D, E, T, A, B, X(8), X(10), X(0), X(5)); + BODY_40_59(41, B, C, D, E, T, A, X(9), X(11), X(1), X(6)); + BODY_40_59(42, A, B, C, D, E, T, X(10), X(12), X(2), X(7)); + BODY_40_59(43, T, A, B, C, D, E, X(11), X(13), X(3), X(8)); + BODY_40_59(44, E, T, A, B, C, D, X(12), X(14), X(4), X(9)); + BODY_40_59(45, D, E, T, A, B, C, X(13), X(15), X(5), X(10)); + BODY_40_59(46, C, D, E, T, A, B, X(14), X(0), X(6), X(11)); + BODY_40_59(47, B, C, D, E, T, A, X(15), X(1), X(7), X(12)); + BODY_40_59(48, A, B, C, D, E, T, X(0), X(2), X(8), X(13)); + BODY_40_59(49, T, A, B, C, D, E, X(1), X(3), X(9), X(14)); + BODY_40_59(50, E, T, A, B, C, D, X(2), X(4), X(10), X(15)); + BODY_40_59(51, D, E, T, A, B, C, X(3), X(5), X(11), X(0)); + BODY_40_59(52, C, D, E, T, A, B, X(4), X(6), X(12), X(1)); + BODY_40_59(53, B, C, D, E, T, A, X(5), X(7), X(13), X(2)); + BODY_40_59(54, A, B, C, D, E, T, X(6), X(8), X(14), X(3)); + BODY_40_59(55, T, A, B, C, D, E, X(7), X(9), X(15), X(4)); + BODY_40_59(56, E, T, A, B, C, D, X(8), X(10), X(0), X(5)); + BODY_40_59(57, D, E, T, A, B, C, X(9), X(11), X(1), X(6)); + BODY_40_59(58, C, D, E, T, A, B, X(10), X(12), X(2), X(7)); + BODY_40_59(59, B, C, D, E, T, A, X(11), X(13), X(3), X(8)); + + BODY_60_79(60, A, B, C, D, E, T, X(12), X(14), X(4), X(9)); + BODY_60_79(61, T, A, B, C, D, E, X(13), X(15), X(5), X(10)); + BODY_60_79(62, E, T, A, B, C, D, X(14), X(0), X(6), X(11)); + BODY_60_79(63, D, E, T, A, B, C, X(15), X(1), X(7), X(12)); + BODY_60_79(64, C, D, E, T, A, B, X(0), X(2), X(8), X(13)); + BODY_60_79(65, B, C, D, E, T, A, X(1), X(3), X(9), X(14)); + BODY_60_79(66, A, B, C, D, E, T, X(2), X(4), X(10), X(15)); + BODY_60_79(67, T, A, B, C, D, E, X(3), X(5), X(11), X(0)); + BODY_60_79(68, E, T, A, B, C, D, X(4), X(6), X(12), X(1)); + BODY_60_79(69, D, E, T, A, B, C, X(5), X(7), X(13), X(2)); + BODY_60_79(70, C, D, E, T, A, B, X(6), X(8), X(14), X(3)); + BODY_60_79(71, B, C, D, E, T, A, X(7), X(9), X(15), X(4)); + BODY_60_79(72, A, B, C, D, E, T, X(8), X(10), X(0), X(5)); + BODY_60_79(73, T, A, B, C, D, E, X(9), X(11), X(1), X(6)); + BODY_60_79(74, E, T, A, B, C, D, X(10), X(12), X(2), X(7)); + BODY_60_79(75, D, E, T, A, B, C, X(11), X(13), X(3), X(8)); + BODY_60_79(76, C, D, E, T, A, B, X(12), X(14), X(4), X(9)); + BODY_60_79(77, B, C, D, E, T, A, X(13), X(15), X(5), X(10)); + BODY_60_79(78, A, B, C, D, E, T, X(14), X(0), X(6), X(11)); + BODY_60_79(79, T, A, B, C, D, E, X(15), X(1), X(7), X(12)); + + state[0] = (state[0] + E) & 0xffffffffL; + state[1] = (state[1] + T) & 0xffffffffL; + state[2] = (state[2] + A) & 0xffffffffL; + state[3] = (state[3] + B) & 0xffffffffL; + state[4] = (state[4] + C) & 0xffffffffL; + + if (--num == 0) { + break; + } + + A = state[0]; + B = state[1]; + C = state[2]; + D = state[3]; + E = state[4]; + } +} +#endif diff --git a/external/boringssl/crypto/sha/sha256.c b/external/boringssl/crypto/sha/sha256.c new file mode 100644 index 0000000000..58f7c42c36 --- /dev/null +++ b/external/boringssl/crypto/sha/sha256.c @@ -0,0 +1,327 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include + + +#if !defined(OPENSSL_NO_ASM) && \ + (defined(OPENSSL_X86) || defined(OPENSSL_X86_64) || \ + defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)) +#define SHA256_ASM +#endif + +int SHA224_Init(SHA256_CTX *sha) { + memset(sha, 0, sizeof(SHA256_CTX)); + sha->h[0] = 0xc1059ed8UL; + sha->h[1] = 0x367cd507UL; + sha->h[2] = 0x3070dd17UL; + sha->h[3] = 0xf70e5939UL; + sha->h[4] = 0xffc00b31UL; + sha->h[5] = 0x68581511UL; + sha->h[6] = 0x64f98fa7UL; + sha->h[7] = 0xbefa4fa4UL; + sha->md_len = SHA224_DIGEST_LENGTH; + return 1; +} + +int SHA256_Init(SHA256_CTX *sha) { + memset(sha, 0, sizeof(SHA256_CTX)); + sha->h[0] = 0x6a09e667UL; + sha->h[1] = 0xbb67ae85UL; + sha->h[2] = 0x3c6ef372UL; + sha->h[3] = 0xa54ff53aUL; + sha->h[4] = 0x510e527fUL; + sha->h[5] = 0x9b05688cUL; + sha->h[6] = 0x1f83d9abUL; + sha->h[7] = 0x5be0cd19UL; + sha->md_len = SHA256_DIGEST_LENGTH; + return 1; +} + +uint8_t *SHA224(const uint8_t *data, size_t len, uint8_t *out) { + SHA256_CTX ctx; + static uint8_t buf[SHA224_DIGEST_LENGTH]; + + /* TODO(fork): remove this static buffer. */ + if (out == NULL) { + out = buf; + } + SHA224_Init(&ctx); + SHA224_Update(&ctx, data, len); + SHA224_Final(out, &ctx); + OPENSSL_cleanse(&ctx, sizeof(ctx)); + return out; +} + +uint8_t *SHA256(const uint8_t *data, size_t len, uint8_t *out) { + SHA256_CTX ctx; + static uint8_t buf[SHA256_DIGEST_LENGTH]; + + /* TODO(fork): remove this static buffer. */ + if (out == NULL) { + out = buf; + } + SHA256_Init(&ctx); + SHA256_Update(&ctx, data, len); + SHA256_Final(out, &ctx); + OPENSSL_cleanse(&ctx, sizeof(ctx)); + return out; +} + +int SHA224_Update(SHA256_CTX *ctx, const void *data, size_t len) { + return SHA256_Update(ctx, data, len); +} + +int SHA224_Final(uint8_t *md, SHA256_CTX *ctx) { + return SHA256_Final(md, ctx); +} + +#define DATA_ORDER_IS_BIG_ENDIAN + +#define HASH_CTX SHA256_CTX +#define HASH_CBLOCK 64 + +/* Note that FIPS180-2 discusses "Truncation of the Hash Function Output." + * default: case below covers for it. It's not clear however if it's permitted + * to truncate to amount of bytes not divisible by 4. I bet not, but if it is, + * then default: case shall be extended. For reference. Idea behind separate + * cases for pre-defined lenghts is to let the compiler decide if it's + * appropriate to unroll small loops. + * + * TODO(davidben): The small |md_len| case is one of the few places a low-level + * hash 'final' function can fail. This should never happen. */ +#define HASH_MAKE_STRING(c, s) \ + do { \ + uint32_t ll; \ + unsigned int nn; \ + switch ((c)->md_len) { \ + case SHA224_DIGEST_LENGTH: \ + for (nn = 0; nn < SHA224_DIGEST_LENGTH / 4; nn++) { \ + ll = (c)->h[nn]; \ + HOST_l2c(ll, (s)); \ + } \ + break; \ + case SHA256_DIGEST_LENGTH: \ + for (nn = 0; nn < SHA256_DIGEST_LENGTH / 4; nn++) { \ + ll = (c)->h[nn]; \ + HOST_l2c(ll, (s)); \ + } \ + break; \ + default: \ + if ((c)->md_len > SHA256_DIGEST_LENGTH) { \ + return 0; \ + } \ + for (nn = 0; nn < (c)->md_len / 4; nn++) { \ + ll = (c)->h[nn]; \ + HOST_l2c(ll, (s)); \ + } \ + break; \ + } \ + } while (0) + + +#define HASH_UPDATE SHA256_Update +#define HASH_TRANSFORM SHA256_Transform +#define HASH_FINAL SHA256_Final +#define HASH_BLOCK_DATA_ORDER sha256_block_data_order +#ifndef SHA256_ASM +static +#endif +void sha256_block_data_order(uint32_t *state, const uint8_t *in, size_t num); + +#include "../digest/md32_common.h" + +#ifndef SHA256_ASM +static const uint32_t K256[64] = { + 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL, + 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL, + 0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, + 0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, + 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL, + 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL, + 0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, + 0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, + 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL, + 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL, + 0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, + 0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, + 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL}; + +#define ROTATE(a, n) (((a) << (n)) | ((a) >> (32 - (n)))) + +/* FIPS specification refers to right rotations, while our ROTATE macro + * is left one. This is why you might notice that rotation coefficients + * differ from those observed in FIPS document by 32-N... */ +#define Sigma0(x) (ROTATE((x), 30) ^ ROTATE((x), 19) ^ ROTATE((x), 10)) +#define Sigma1(x) (ROTATE((x), 26) ^ ROTATE((x), 21) ^ ROTATE((x), 7)) +#define sigma0(x) (ROTATE((x), 25) ^ ROTATE((x), 14) ^ ((x) >> 3)) +#define sigma1(x) (ROTATE((x), 15) ^ ROTATE((x), 13) ^ ((x) >> 10)) + +#define Ch(x, y, z) (((x) & (y)) ^ ((~(x)) & (z))) +#define Maj(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) + +#define ROUND_00_15(i, a, b, c, d, e, f, g, h) \ + do { \ + T1 += h + Sigma1(e) + Ch(e, f, g) + K256[i]; \ + h = Sigma0(a) + Maj(a, b, c); \ + d += T1; \ + h += T1; \ + } while (0) + +#define ROUND_16_63(i, a, b, c, d, e, f, g, h, X) \ + do { \ + s0 = X[(i + 1) & 0x0f]; \ + s0 = sigma0(s0); \ + s1 = X[(i + 14) & 0x0f]; \ + s1 = sigma1(s1); \ + T1 = X[(i) & 0x0f] += s0 + s1 + X[(i + 9) & 0x0f]; \ + ROUND_00_15(i, a, b, c, d, e, f, g, h); \ + } while (0) + +static void sha256_block_data_order(uint32_t *state, const uint8_t *data, + size_t num) { + uint32_t a, b, c, d, e, f, g, h, s0, s1, T1; + uint32_t X[16]; + int i; + + while (num--) { + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + f = state[5]; + g = state[6]; + h = state[7]; + + uint32_t l; + + HOST_c2l(data, l); + T1 = X[0] = l; + ROUND_00_15(0, a, b, c, d, e, f, g, h); + HOST_c2l(data, l); + T1 = X[1] = l; + ROUND_00_15(1, h, a, b, c, d, e, f, g); + HOST_c2l(data, l); + T1 = X[2] = l; + ROUND_00_15(2, g, h, a, b, c, d, e, f); + HOST_c2l(data, l); + T1 = X[3] = l; + ROUND_00_15(3, f, g, h, a, b, c, d, e); + HOST_c2l(data, l); + T1 = X[4] = l; + ROUND_00_15(4, e, f, g, h, a, b, c, d); + HOST_c2l(data, l); + T1 = X[5] = l; + ROUND_00_15(5, d, e, f, g, h, a, b, c); + HOST_c2l(data, l); + T1 = X[6] = l; + ROUND_00_15(6, c, d, e, f, g, h, a, b); + HOST_c2l(data, l); + T1 = X[7] = l; + ROUND_00_15(7, b, c, d, e, f, g, h, a); + HOST_c2l(data, l); + T1 = X[8] = l; + ROUND_00_15(8, a, b, c, d, e, f, g, h); + HOST_c2l(data, l); + T1 = X[9] = l; + ROUND_00_15(9, h, a, b, c, d, e, f, g); + HOST_c2l(data, l); + T1 = X[10] = l; + ROUND_00_15(10, g, h, a, b, c, d, e, f); + HOST_c2l(data, l); + T1 = X[11] = l; + ROUND_00_15(11, f, g, h, a, b, c, d, e); + HOST_c2l(data, l); + T1 = X[12] = l; + ROUND_00_15(12, e, f, g, h, a, b, c, d); + HOST_c2l(data, l); + T1 = X[13] = l; + ROUND_00_15(13, d, e, f, g, h, a, b, c); + HOST_c2l(data, l); + T1 = X[14] = l; + ROUND_00_15(14, c, d, e, f, g, h, a, b); + HOST_c2l(data, l); + T1 = X[15] = l; + ROUND_00_15(15, b, c, d, e, f, g, h, a); + + for (i = 16; i < 64; i += 8) { + ROUND_16_63(i + 0, a, b, c, d, e, f, g, h, X); + ROUND_16_63(i + 1, h, a, b, c, d, e, f, g, X); + ROUND_16_63(i + 2, g, h, a, b, c, d, e, f, X); + ROUND_16_63(i + 3, f, g, h, a, b, c, d, e, X); + ROUND_16_63(i + 4, e, f, g, h, a, b, c, d, X); + ROUND_16_63(i + 5, d, e, f, g, h, a, b, c, X); + ROUND_16_63(i + 6, c, d, e, f, g, h, a, b, X); + ROUND_16_63(i + 7, b, c, d, e, f, g, h, a, X); + } + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + state[5] += f; + state[6] += g; + state[7] += h; + } +} + +#endif /* SHA256_ASM */ diff --git a/external/boringssl/crypto/sha/sha512.c b/external/boringssl/crypto/sha/sha512.c new file mode 100644 index 0000000000..f473046345 --- /dev/null +++ b/external/boringssl/crypto/sha/sha512.c @@ -0,0 +1,607 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include + + +/* IMPLEMENTATION NOTES. + * + * The 32-bit hash algorithms share a common byte-order neutral collector and + * padding function implementations that operate on unaligned data, + * ../md32_common.h. This SHA-512 implementation does not. Reasons + * [in reverse order] are: + * + * - It's the only 64-bit hash algorithm for the moment of this writing, + * there is no need for common collector/padding implementation [yet]; + * - By supporting only a transform function that operates on *aligned* data + * the collector/padding function is simpler and easier to optimize. */ + +#if !defined(OPENSSL_NO_ASM) && \ + (defined(OPENSSL_X86) || defined(OPENSSL_X86_64) || \ + defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)) +#define SHA512_ASM +#endif + +#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64) || \ + defined(__ARM_FEATURE_UNALIGNED) +#define SHA512_BLOCK_CAN_MANAGE_UNALIGNED_DATA +#endif + +int SHA384_Init(SHA512_CTX *sha) { + sha->h[0] = UINT64_C(0xcbbb9d5dc1059ed8); + sha->h[1] = UINT64_C(0x629a292a367cd507); + sha->h[2] = UINT64_C(0x9159015a3070dd17); + sha->h[3] = UINT64_C(0x152fecd8f70e5939); + sha->h[4] = UINT64_C(0x67332667ffc00b31); + sha->h[5] = UINT64_C(0x8eb44a8768581511); + sha->h[6] = UINT64_C(0xdb0c2e0d64f98fa7); + sha->h[7] = UINT64_C(0x47b5481dbefa4fa4); + + sha->Nl = 0; + sha->Nh = 0; + sha->num = 0; + sha->md_len = SHA384_DIGEST_LENGTH; + return 1; +} + + +int SHA512_Init(SHA512_CTX *sha) { + sha->h[0] = UINT64_C(0x6a09e667f3bcc908); + sha->h[1] = UINT64_C(0xbb67ae8584caa73b); + sha->h[2] = UINT64_C(0x3c6ef372fe94f82b); + sha->h[3] = UINT64_C(0xa54ff53a5f1d36f1); + sha->h[4] = UINT64_C(0x510e527fade682d1); + sha->h[5] = UINT64_C(0x9b05688c2b3e6c1f); + sha->h[6] = UINT64_C(0x1f83d9abfb41bd6b); + sha->h[7] = UINT64_C(0x5be0cd19137e2179); + + sha->Nl = 0; + sha->Nh = 0; + sha->num = 0; + sha->md_len = SHA512_DIGEST_LENGTH; + return 1; +} + +uint8_t *SHA384(const uint8_t *data, size_t len, uint8_t *out) { + SHA512_CTX ctx; + static uint8_t buf[SHA384_DIGEST_LENGTH]; + + /* TODO(fork): remove this static buffer. */ + if (out == NULL) { + out = buf; + } + + SHA384_Init(&ctx); + SHA384_Update(&ctx, data, len); + SHA384_Final(out, &ctx); + OPENSSL_cleanse(&ctx, sizeof(ctx)); + return out; +} + +uint8_t *SHA512(const uint8_t *data, size_t len, uint8_t *out) { + SHA512_CTX ctx; + static uint8_t buf[SHA512_DIGEST_LENGTH]; + + /* TODO(fork): remove this static buffer. */ + if (out == NULL) { + out = buf; + } + SHA512_Init(&ctx); + SHA512_Update(&ctx, data, len); + SHA512_Final(out, &ctx); + OPENSSL_cleanse(&ctx, sizeof(ctx)); + return out; +} + +#if !defined(SHA512_ASM) +static +#endif +void sha512_block_data_order(uint64_t *state, const uint64_t *W, size_t num); + + +int SHA384_Final(uint8_t *md, SHA512_CTX *sha) { + return SHA512_Final(md, sha); +} + +int SHA384_Update(SHA512_CTX *sha, const void *data, size_t len) { + return SHA512_Update(sha, data, len); +} + +void SHA512_Transform(SHA512_CTX *c, const uint8_t *data) { +#ifndef SHA512_BLOCK_CAN_MANAGE_UNALIGNED_DATA + if ((size_t)data % sizeof(c->u.d[0]) != 0) { + memcpy(c->u.p, data, sizeof(c->u.p)); + data = c->u.p; + } +#endif + sha512_block_data_order(c->h, (uint64_t *)data, 1); +} + +int SHA512_Update(SHA512_CTX *c, const void *in_data, size_t len) { + uint64_t l; + uint8_t *p = c->u.p; + const uint8_t *data = (const uint8_t *)in_data; + + if (len == 0) { + return 1; + } + + l = (c->Nl + (((uint64_t)len) << 3)) & UINT64_C(0xffffffffffffffff); + if (l < c->Nl) { + c->Nh++; + } + if (sizeof(len) >= 8) { + c->Nh += (((uint64_t)len) >> 61); + } + c->Nl = l; + + if (c->num != 0) { + size_t n = sizeof(c->u) - c->num; + + if (len < n) { + memcpy(p + c->num, data, len); + c->num += (unsigned int)len; + return 1; + } else { + memcpy(p + c->num, data, n), c->num = 0; + len -= n; + data += n; + sha512_block_data_order(c->h, (uint64_t *)p, 1); + } + } + + if (len >= sizeof(c->u)) { +#ifndef SHA512_BLOCK_CAN_MANAGE_UNALIGNED_DATA + if ((size_t)data % sizeof(c->u.d[0]) != 0) { + while (len >= sizeof(c->u)) { + memcpy(p, data, sizeof(c->u)); + sha512_block_data_order(c->h, (uint64_t *)p, 1); + len -= sizeof(c->u); + data += sizeof(c->u); + } + } else +#endif + { + sha512_block_data_order(c->h, (uint64_t *)data, len / sizeof(c->u)); + data += len; + len %= sizeof(c->u); + data -= len; + } + } + + if (len != 0) { + memcpy(p, data, len); + c->num = (int)len; + } + + return 1; +} + +int SHA512_Final(uint8_t *md, SHA512_CTX *sha) { + uint8_t *p = (uint8_t *)sha->u.p; + size_t n = sha->num; + + p[n] = 0x80; /* There always is a room for one */ + n++; + if (n > (sizeof(sha->u) - 16)) { + memset(p + n, 0, sizeof(sha->u) - n); + n = 0; + sha512_block_data_order(sha->h, (uint64_t *)p, 1); + } + + memset(p + n, 0, sizeof(sha->u) - 16 - n); + p[sizeof(sha->u) - 1] = (uint8_t)(sha->Nl); + p[sizeof(sha->u) - 2] = (uint8_t)(sha->Nl >> 8); + p[sizeof(sha->u) - 3] = (uint8_t)(sha->Nl >> 16); + p[sizeof(sha->u) - 4] = (uint8_t)(sha->Nl >> 24); + p[sizeof(sha->u) - 5] = (uint8_t)(sha->Nl >> 32); + p[sizeof(sha->u) - 6] = (uint8_t)(sha->Nl >> 40); + p[sizeof(sha->u) - 7] = (uint8_t)(sha->Nl >> 48); + p[sizeof(sha->u) - 8] = (uint8_t)(sha->Nl >> 56); + p[sizeof(sha->u) - 9] = (uint8_t)(sha->Nh); + p[sizeof(sha->u) - 10] = (uint8_t)(sha->Nh >> 8); + p[sizeof(sha->u) - 11] = (uint8_t)(sha->Nh >> 16); + p[sizeof(sha->u) - 12] = (uint8_t)(sha->Nh >> 24); + p[sizeof(sha->u) - 13] = (uint8_t)(sha->Nh >> 32); + p[sizeof(sha->u) - 14] = (uint8_t)(sha->Nh >> 40); + p[sizeof(sha->u) - 15] = (uint8_t)(sha->Nh >> 48); + p[sizeof(sha->u) - 16] = (uint8_t)(sha->Nh >> 56); + + sha512_block_data_order(sha->h, (uint64_t *)p, 1); + + if (md == NULL) { + /* TODO(davidben): This NULL check is absent in other low-level hash 'final' + * functions and is one of the few places one can fail. */ + return 0; + } + + switch (sha->md_len) { + /* Let compiler decide if it's appropriate to unroll... */ + case SHA384_DIGEST_LENGTH: + for (n = 0; n < SHA384_DIGEST_LENGTH / 8; n++) { + uint64_t t = sha->h[n]; + + *(md++) = (uint8_t)(t >> 56); + *(md++) = (uint8_t)(t >> 48); + *(md++) = (uint8_t)(t >> 40); + *(md++) = (uint8_t)(t >> 32); + *(md++) = (uint8_t)(t >> 24); + *(md++) = (uint8_t)(t >> 16); + *(md++) = (uint8_t)(t >> 8); + *(md++) = (uint8_t)(t); + } + break; + case SHA512_DIGEST_LENGTH: + for (n = 0; n < SHA512_DIGEST_LENGTH / 8; n++) { + uint64_t t = sha->h[n]; + + *(md++) = (uint8_t)(t >> 56); + *(md++) = (uint8_t)(t >> 48); + *(md++) = (uint8_t)(t >> 40); + *(md++) = (uint8_t)(t >> 32); + *(md++) = (uint8_t)(t >> 24); + *(md++) = (uint8_t)(t >> 16); + *(md++) = (uint8_t)(t >> 8); + *(md++) = (uint8_t)(t); + } + break; + /* ... as well as make sure md_len is not abused. */ + default: + /* TODO(davidben): This bad |md_len| case is one of the few places a + * low-level hash 'final' function can fail. This should never happen. */ + return 0; + } + + return 1; +} + +#ifndef SHA512_ASM +static const uint64_t K512[80] = { + UINT64_C(0x428a2f98d728ae22), UINT64_C(0x7137449123ef65cd), + UINT64_C(0xb5c0fbcfec4d3b2f), UINT64_C(0xe9b5dba58189dbbc), + UINT64_C(0x3956c25bf348b538), UINT64_C(0x59f111f1b605d019), + UINT64_C(0x923f82a4af194f9b), UINT64_C(0xab1c5ed5da6d8118), + UINT64_C(0xd807aa98a3030242), UINT64_C(0x12835b0145706fbe), + UINT64_C(0x243185be4ee4b28c), UINT64_C(0x550c7dc3d5ffb4e2), + UINT64_C(0x72be5d74f27b896f), UINT64_C(0x80deb1fe3b1696b1), + UINT64_C(0x9bdc06a725c71235), UINT64_C(0xc19bf174cf692694), + UINT64_C(0xe49b69c19ef14ad2), UINT64_C(0xefbe4786384f25e3), + UINT64_C(0x0fc19dc68b8cd5b5), UINT64_C(0x240ca1cc77ac9c65), + UINT64_C(0x2de92c6f592b0275), UINT64_C(0x4a7484aa6ea6e483), + UINT64_C(0x5cb0a9dcbd41fbd4), UINT64_C(0x76f988da831153b5), + UINT64_C(0x983e5152ee66dfab), UINT64_C(0xa831c66d2db43210), + UINT64_C(0xb00327c898fb213f), UINT64_C(0xbf597fc7beef0ee4), + UINT64_C(0xc6e00bf33da88fc2), UINT64_C(0xd5a79147930aa725), + UINT64_C(0x06ca6351e003826f), UINT64_C(0x142929670a0e6e70), + UINT64_C(0x27b70a8546d22ffc), UINT64_C(0x2e1b21385c26c926), + UINT64_C(0x4d2c6dfc5ac42aed), UINT64_C(0x53380d139d95b3df), + UINT64_C(0x650a73548baf63de), UINT64_C(0x766a0abb3c77b2a8), + UINT64_C(0x81c2c92e47edaee6), UINT64_C(0x92722c851482353b), + UINT64_C(0xa2bfe8a14cf10364), UINT64_C(0xa81a664bbc423001), + UINT64_C(0xc24b8b70d0f89791), UINT64_C(0xc76c51a30654be30), + UINT64_C(0xd192e819d6ef5218), UINT64_C(0xd69906245565a910), + UINT64_C(0xf40e35855771202a), UINT64_C(0x106aa07032bbd1b8), + UINT64_C(0x19a4c116b8d2d0c8), UINT64_C(0x1e376c085141ab53), + UINT64_C(0x2748774cdf8eeb99), UINT64_C(0x34b0bcb5e19b48a8), + UINT64_C(0x391c0cb3c5c95a63), UINT64_C(0x4ed8aa4ae3418acb), + UINT64_C(0x5b9cca4f7763e373), UINT64_C(0x682e6ff3d6b2b8a3), + UINT64_C(0x748f82ee5defb2fc), UINT64_C(0x78a5636f43172f60), + UINT64_C(0x84c87814a1f0ab72), UINT64_C(0x8cc702081a6439ec), + UINT64_C(0x90befffa23631e28), UINT64_C(0xa4506cebde82bde9), + UINT64_C(0xbef9a3f7b2c67915), UINT64_C(0xc67178f2e372532b), + UINT64_C(0xca273eceea26619c), UINT64_C(0xd186b8c721c0c207), + UINT64_C(0xeada7dd6cde0eb1e), UINT64_C(0xf57d4f7fee6ed178), + UINT64_C(0x06f067aa72176fba), UINT64_C(0x0a637dc5a2c898a6), + UINT64_C(0x113f9804bef90dae), UINT64_C(0x1b710b35131c471b), + UINT64_C(0x28db77f523047d84), UINT64_C(0x32caab7b40c72493), + UINT64_C(0x3c9ebe0a15c9bebc), UINT64_C(0x431d67c49c100d4c), + UINT64_C(0x4cc5d4becb3e42b6), UINT64_C(0x597f299cfc657e2a), + UINT64_C(0x5fcb6fab3ad6faec), UINT64_C(0x6c44198c4a475817), +}; + +#if defined(__GNUC__) && __GNUC__ >= 2 && !defined(OPENSSL_NO_ASM) +#if defined(__x86_64) || defined(__x86_64__) +#define ROTR(a, n) \ + ({ \ + uint64_t ret; \ + __asm__("rorq %1, %0" : "=r"(ret) : "J"(n), "0"(a) : "cc"); \ + ret; \ + }) +#define PULL64(x) \ + ({ \ + uint64_t ret = *((const uint64_t *)(&(x))); \ + __asm__("bswapq %0" : "=r"(ret) : "0"(ret)); \ + ret; \ + }) +#elif(defined(__i386) || defined(__i386__)) +#define PULL64(x) \ + ({ \ + const unsigned int *p = (const unsigned int *)(&(x)); \ + unsigned int hi = p[0], lo = p[1]; \ + __asm__("bswapl %0; bswapl %1;" : "=r"(lo), "=r"(hi) : "0"(lo), "1"(hi)); \ + ((uint64_t)hi) << 32 | lo; \ + }) +#elif(defined(_ARCH_PPC) && defined(__64BIT__)) || defined(_ARCH_PPC64) +#define ROTR(a, n) \ + ({ \ + uint64_t ret; \ + __asm__("rotrdi %0, %1, %2" : "=r"(ret) : "r"(a), "K"(n)); \ + ret; \ + }) +#elif defined(__aarch64__) +#define ROTR(a, n) \ + ({ \ + uint64_t ret; \ + __asm__("ror %0, %1, %2" : "=r"(ret) : "r"(a), "I"(n)); \ + ret; \ + }) +#if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \ + __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +#define PULL64(x) \ + ({ \ + uint64_t ret; \ + __asm__("rev %0, %1" : "=r"(ret) : "r"(*((const uint64_t *)(&(x))))); \ + ret; \ + }) +#endif +#endif +#elif defined(_MSC_VER) +#if defined(_WIN64) /* applies to both IA-64 and AMD64 */ +#pragma intrinsic(_rotr64) +#define ROTR(a, n) _rotr64((a), n) +#endif +#if defined(_M_IX86) && !defined(OPENSSL_NO_ASM) +static uint64_t __fastcall __pull64be(const void *x) { + _asm mov edx, [ecx + 0] + _asm mov eax, [ecx + 4] + _asm bswap edx + _asm bswap eax +} +#define PULL64(x) __pull64be(&(x)) +#if _MSC_VER <= 1200 +#pragma inline_depth(0) +#endif +#endif +#endif + +#ifndef PULL64 +#define B(x, j) \ + (((uint64_t)(*(((const uint8_t *)(&x)) + j))) << ((7 - j) * 8)) +#define PULL64(x) \ + (B(x, 0) | B(x, 1) | B(x, 2) | B(x, 3) | B(x, 4) | B(x, 5) | B(x, 6) | \ + B(x, 7)) +#endif + +#ifndef ROTR +#define ROTR(x, s) (((x) >> s) | (x) << (64 - s)) +#endif + +#define Sigma0(x) (ROTR((x), 28) ^ ROTR((x), 34) ^ ROTR((x), 39)) +#define Sigma1(x) (ROTR((x), 14) ^ ROTR((x), 18) ^ ROTR((x), 41)) +#define sigma0(x) (ROTR((x), 1) ^ ROTR((x), 8) ^ ((x) >> 7)) +#define sigma1(x) (ROTR((x), 19) ^ ROTR((x), 61) ^ ((x) >> 6)) + +#define Ch(x, y, z) (((x) & (y)) ^ ((~(x)) & (z))) +#define Maj(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) + + +#if defined(__i386) || defined(__i386__) || defined(_M_IX86) +/* + * This code should give better results on 32-bit CPU with less than + * ~24 registers, both size and performance wise... + */ +static void sha512_block_data_order(uint64_t *state, const uint64_t *W, + size_t num) { + uint64_t A, E, T; + uint64_t X[9 + 80], *F; + int i; + + while (num--) { + F = X + 80; + A = state[0]; + F[1] = state[1]; + F[2] = state[2]; + F[3] = state[3]; + E = state[4]; + F[5] = state[5]; + F[6] = state[6]; + F[7] = state[7]; + + for (i = 0; i < 16; i++, F--) { + T = PULL64(W[i]); + F[0] = A; + F[4] = E; + F[8] = T; + T += F[7] + Sigma1(E) + Ch(E, F[5], F[6]) + K512[i]; + E = F[3] + T; + A = T + Sigma0(A) + Maj(A, F[1], F[2]); + } + + for (; i < 80; i++, F--) { + T = sigma0(F[8 + 16 - 1]); + T += sigma1(F[8 + 16 - 14]); + T += F[8 + 16] + F[8 + 16 - 9]; + + F[0] = A; + F[4] = E; + F[8] = T; + T += F[7] + Sigma1(E) + Ch(E, F[5], F[6]) + K512[i]; + E = F[3] + T; + A = T + Sigma0(A) + Maj(A, F[1], F[2]); + } + + state[0] += A; + state[1] += F[1]; + state[2] += F[2]; + state[3] += F[3]; + state[4] += E; + state[5] += F[5]; + state[6] += F[6]; + state[7] += F[7]; + + W += 16; + } +} + +#else + +#define ROUND_00_15(i, a, b, c, d, e, f, g, h) \ + do { \ + T1 += h + Sigma1(e) + Ch(e, f, g) + K512[i]; \ + h = Sigma0(a) + Maj(a, b, c); \ + d += T1; \ + h += T1; \ + } while (0) + +#define ROUND_16_80(i, j, a, b, c, d, e, f, g, h, X) \ + do { \ + s0 = X[(j + 1) & 0x0f]; \ + s0 = sigma0(s0); \ + s1 = X[(j + 14) & 0x0f]; \ + s1 = sigma1(s1); \ + T1 = X[(j) & 0x0f] += s0 + s1 + X[(j + 9) & 0x0f]; \ + ROUND_00_15(i + j, a, b, c, d, e, f, g, h); \ + } while (0) + +static void sha512_block_data_order(uint64_t *state, const uint64_t *W, + size_t num) { + uint64_t a, b, c, d, e, f, g, h, s0, s1, T1; + uint64_t X[16]; + int i; + + while (num--) { + + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + f = state[5]; + g = state[6]; + h = state[7]; + + T1 = X[0] = PULL64(W[0]); + ROUND_00_15(0, a, b, c, d, e, f, g, h); + T1 = X[1] = PULL64(W[1]); + ROUND_00_15(1, h, a, b, c, d, e, f, g); + T1 = X[2] = PULL64(W[2]); + ROUND_00_15(2, g, h, a, b, c, d, e, f); + T1 = X[3] = PULL64(W[3]); + ROUND_00_15(3, f, g, h, a, b, c, d, e); + T1 = X[4] = PULL64(W[4]); + ROUND_00_15(4, e, f, g, h, a, b, c, d); + T1 = X[5] = PULL64(W[5]); + ROUND_00_15(5, d, e, f, g, h, a, b, c); + T1 = X[6] = PULL64(W[6]); + ROUND_00_15(6, c, d, e, f, g, h, a, b); + T1 = X[7] = PULL64(W[7]); + ROUND_00_15(7, b, c, d, e, f, g, h, a); + T1 = X[8] = PULL64(W[8]); + ROUND_00_15(8, a, b, c, d, e, f, g, h); + T1 = X[9] = PULL64(W[9]); + ROUND_00_15(9, h, a, b, c, d, e, f, g); + T1 = X[10] = PULL64(W[10]); + ROUND_00_15(10, g, h, a, b, c, d, e, f); + T1 = X[11] = PULL64(W[11]); + ROUND_00_15(11, f, g, h, a, b, c, d, e); + T1 = X[12] = PULL64(W[12]); + ROUND_00_15(12, e, f, g, h, a, b, c, d); + T1 = X[13] = PULL64(W[13]); + ROUND_00_15(13, d, e, f, g, h, a, b, c); + T1 = X[14] = PULL64(W[14]); + ROUND_00_15(14, c, d, e, f, g, h, a, b); + T1 = X[15] = PULL64(W[15]); + ROUND_00_15(15, b, c, d, e, f, g, h, a); + + for (i = 16; i < 80; i += 16) { + ROUND_16_80(i, 0, a, b, c, d, e, f, g, h, X); + ROUND_16_80(i, 1, h, a, b, c, d, e, f, g, X); + ROUND_16_80(i, 2, g, h, a, b, c, d, e, f, X); + ROUND_16_80(i, 3, f, g, h, a, b, c, d, e, X); + ROUND_16_80(i, 4, e, f, g, h, a, b, c, d, X); + ROUND_16_80(i, 5, d, e, f, g, h, a, b, c, X); + ROUND_16_80(i, 6, c, d, e, f, g, h, a, b, X); + ROUND_16_80(i, 7, b, c, d, e, f, g, h, a, X); + ROUND_16_80(i, 8, a, b, c, d, e, f, g, h, X); + ROUND_16_80(i, 9, h, a, b, c, d, e, f, g, X); + ROUND_16_80(i, 10, g, h, a, b, c, d, e, f, X); + ROUND_16_80(i, 11, f, g, h, a, b, c, d, e, X); + ROUND_16_80(i, 12, e, f, g, h, a, b, c, d, X); + ROUND_16_80(i, 13, d, e, f, g, h, a, b, c, X); + ROUND_16_80(i, 14, c, d, e, f, g, h, a, b, X); + ROUND_16_80(i, 15, b, c, d, e, f, g, h, a, X); + } + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + state[5] += f; + state[6] += g; + state[7] += h; + + W += 16; + } +} + +#endif + +#endif /* SHA512_ASM */ diff --git a/external/boringssl/crypto/stack/CMakeLists.txt b/external/boringssl/crypto/stack/CMakeLists.txt new file mode 100644 index 0000000000..dcd8ef49e0 --- /dev/null +++ b/external/boringssl/crypto/stack/CMakeLists.txt @@ -0,0 +1,9 @@ +include_directories(../../include) + +add_library( + stack + + OBJECT + + stack.c +) diff --git a/external/boringssl/crypto/stack/make_macros.sh b/external/boringssl/crypto/stack/make_macros.sh new file mode 100644 index 0000000000..3c3691b316 --- /dev/null +++ b/external/boringssl/crypto/stack/make_macros.sh @@ -0,0 +1,114 @@ +#!/bin/sh + +include_dir=../../include/openssl + +cat > "${include_dir}/stack_macros.h" << EOF +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#if !defined(IN_STACK_H) +#error "Don't include this file directly. Include stack.h." +#endif + +EOF + +output_stack () { + type=$1 + ptrtype=$2 + + cat >> "${include_dir}/stack_macros.h" << EOF +/* ${type} */ +#define sk_${type}_new(comp)\\ + ((STACK_OF(${type})*) sk_new(CHECKED_CAST(stack_cmp_func, int (*) (const ${ptrtype} *a, const ${ptrtype} *b), comp))) + +#define sk_${type}_new_null()\\ + ((STACK_OF(${type})*) sk_new_null()) + +#define sk_${type}_num(sk)\\ + sk_num(CHECKED_CAST(const _STACK*, const STACK_OF(${type})*, sk)) + +#define sk_${type}_zero(sk)\\ + sk_zero(CHECKED_CAST(_STACK*, STACK_OF(${type})*, sk)); + +#define sk_${type}_value(sk, i)\\ + ((${ptrtype}) sk_value(CHECKED_CAST(const _STACK*, const STACK_OF(${type})*, sk), (i))) + +#define sk_${type}_set(sk, i, p)\\ + ((${ptrtype}) sk_set(CHECKED_CAST(_STACK*, STACK_OF(${type})*, sk), (i), CHECKED_CAST(void*, ${ptrtype}, p))) + +#define sk_${type}_free(sk)\\ + sk_free(CHECKED_CAST(_STACK*, STACK_OF(${type})*, sk)) + +#define sk_${type}_pop_free(sk, free_func)\\ + sk_pop_free(CHECKED_CAST(_STACK*, STACK_OF(${type})*, sk), CHECKED_CAST(void (*) (void*), void (*) (${ptrtype}), free_func)) + +#define sk_${type}_insert(sk, p, where)\\ + sk_insert(CHECKED_CAST(_STACK*, STACK_OF(${type})*, sk), CHECKED_CAST(void*, ${ptrtype}, p), (where)) + +#define sk_${type}_delete(sk, where)\\ + ((${ptrtype}) sk_delete(CHECKED_CAST(_STACK*, STACK_OF(${type})*, sk), (where))) + +#define sk_${type}_delete_ptr(sk, p)\\ + ((${ptrtype}) sk_delete_ptr(CHECKED_CAST(_STACK*, STACK_OF(${type})*, sk), CHECKED_CAST(void*, ${ptrtype}, p))) + +#define sk_${type}_find(sk, out_index, p)\\ + sk_find(CHECKED_CAST(_STACK*, STACK_OF(${type})*, sk), (out_index), CHECKED_CAST(void*, ${ptrtype}, p)) + +#define sk_${type}_shift(sk)\\ + ((${ptrtype}) sk_shift(CHECKED_CAST(_STACK*, STACK_OF(${type})*, sk))) + +#define sk_${type}_push(sk, p)\\ + sk_push(CHECKED_CAST(_STACK*, STACK_OF(${type})*, sk), CHECKED_CAST(void*, ${ptrtype}, p)) + +#define sk_${type}_pop(sk)\\ + ((${ptrtype}) sk_pop(CHECKED_CAST(_STACK*, STACK_OF(${type})*, sk))) + +#define sk_${type}_dup(sk)\\ + ((STACK_OF(${type})*) sk_dup(CHECKED_CAST(const _STACK*, const STACK_OF(${type})*, sk))) + +#define sk_${type}_sort(sk)\\ + sk_sort(CHECKED_CAST(_STACK*, STACK_OF(${type})*, sk)) + +#define sk_${type}_is_sorted(sk)\\ + sk_is_sorted(CHECKED_CAST(const _STACK*, const STACK_OF(${type})*, sk)) + +#define sk_${type}_set_cmp_func(sk, comp)\\ + ((int (*) (const ${type} **a, const ${type} **b)) sk_set_cmp_func(CHECKED_CAST(_STACK*, STACK_OF(${type})*, sk), CHECKED_CAST(stack_cmp_func, int (*) (const ${type} **a, const ${type} **b), comp))) + +#define sk_${type}_deep_copy(sk, copy_func, free_func)\\ +((STACK_OF(${type})*) sk_deep_copy(CHECKED_CAST(const _STACK*, const STACK_OF(${type})*, sk), CHECKED_CAST(void* (*) (void*), ${ptrtype} (*) (${ptrtype}), copy_func), CHECKED_CAST(void (*) (void*), void (*) (${ptrtype}), free_func))) + +EOF +} + +stack_types=$(cat "${include_dir}/stack.h" | grep '^ \* STACK_OF:' | sed -e 's/.*STACK_OF://' -e 's/ .*//') +const_stack_types=$(cat "${include_dir}/stack.h" | grep '^ \* CONST_STACK_OF:' | sed -e 's/.*CONST_STACK_OF://' -e 's/ .*//') +special_stack_types=$(cat "${include_dir}/stack.h" | grep '^ \* SPECIAL_STACK_OF:' | sed -e 's/.*SPECIAL_STACK_OF://' -e 's/ .*//') + +for type in $stack_types; do + echo Stack of ${type} + output_stack "${type}" "${type} *" +done + +for type in $const_stack_types; do + echo Stack of ${type} + output_stack "${type}" "const ${type} *" +done + +for type in $special_stack_types; do + echo Stack of ${type} + output_stack "${type}" "${type}" +done + +clang-format -i "${include_dir}/stack_macros.h" diff --git a/external/boringssl/crypto/stack/stack.c b/external/boringssl/crypto/stack/stack.c new file mode 100644 index 0000000000..e8932217bd --- /dev/null +++ b/external/boringssl/crypto/stack/stack.c @@ -0,0 +1,386 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include + +/* kMinSize is the number of pointers that will be initially allocated in a new + * stack. */ +static const size_t kMinSize = 4; + +_STACK *sk_new(stack_cmp_func comp) { + _STACK *ret; + + ret = OPENSSL_malloc(sizeof(_STACK)); + if (ret == NULL) { + goto err; + } + memset(ret, 0, sizeof(_STACK)); + + ret->data = OPENSSL_malloc(sizeof(void *) * kMinSize); + if (ret->data == NULL) { + goto err; + } + + memset(ret->data, 0, sizeof(void *) * kMinSize); + + ret->comp = comp; + ret->num_alloc = kMinSize; + + return ret; + +err: + OPENSSL_free(ret); + return NULL; +} + +_STACK *sk_new_null(void) { return sk_new(NULL); } + +size_t sk_num(const _STACK *sk) { + if (sk == NULL) { + return 0; + } + return sk->num; +} + +void sk_zero(_STACK *sk) { + if (sk == NULL || sk->num == 0) { + return; + } + memset(sk->data, 0, sizeof(void*) * sk->num); + sk->num = 0; + sk->sorted = 0; +} + +void *sk_value(const _STACK *sk, size_t i) { + if (!sk || i >= sk->num) { + return NULL; + } + return sk->data[i]; +} + +void *sk_set(_STACK *sk, size_t i, void *value) { + if (!sk || i >= sk->num) { + return NULL; + } + return sk->data[i] = value; +} + +void sk_free(_STACK *sk) { + if (sk == NULL) { + return; + } + OPENSSL_free(sk->data); + OPENSSL_free(sk); +} + +void sk_pop_free(_STACK *sk, void (*func)(void *)) { + size_t i; + + if (sk == NULL) { + return; + } + + for (i = 0; i < sk->num; i++) { + if (sk->data[i] != NULL) { + func(sk->data[i]); + } + } + sk_free(sk); +} + +size_t sk_insert(_STACK *sk, void *p, size_t where) { + if (sk == NULL) { + return 0; + } + + if (sk->num_alloc <= sk->num + 1) { + /* Attempt to double the size of the array. */ + size_t new_alloc = sk->num_alloc << 1; + size_t alloc_size = new_alloc * sizeof(void *); + void **data; + + /* If the doubling overflowed, try to increment. */ + if (new_alloc < sk->num_alloc || alloc_size / sizeof(void *) != new_alloc) { + new_alloc = sk->num_alloc + 1; + alloc_size = new_alloc * sizeof(void *); + } + + /* If the increment also overflowed, fail. */ + if (new_alloc < sk->num_alloc || alloc_size / sizeof(void *) != new_alloc) { + return 0; + } + + data = OPENSSL_realloc(sk->data, alloc_size); + if (data == NULL) { + return 0; + } + + sk->data = data; + sk->num_alloc = new_alloc; + } + + if (where >= sk->num) { + sk->data[sk->num] = p; + } else { + memmove(&sk->data[where + 1], &sk->data[where], + sizeof(void *) * (sk->num - where)); + sk->data[where] = p; + } + + sk->num++; + sk->sorted = 0; + + return sk->num; +} + +void *sk_delete(_STACK *sk, size_t where) { + void *ret; + + if (!sk || where >= sk->num) { + return NULL; + } + + ret = sk->data[where]; + + if (where != sk->num - 1) { + memmove(&sk->data[where], &sk->data[where + 1], + sizeof(void *) * (sk->num - where - 1)); + } + + sk->num--; + return ret; +} + +void *sk_delete_ptr(_STACK *sk, void *p) { + size_t i; + + if (sk == NULL) { + return NULL; + } + + for (i = 0; i < sk->num; i++) { + if (sk->data[i] == p) { + return sk_delete(sk, i); + } + } + + return NULL; +} + +int sk_find(_STACK *sk, size_t *out_index, void *p) { + const void *const *r; + size_t i; + int (*comp_func)(const void *,const void *); + + if (sk == NULL) { + return 0; + } + + if (sk->comp == NULL) { + /* Use pointer equality when no comparison function has been set. */ + for (i = 0; i < sk->num; i++) { + if (sk->data[i] == p) { + if (out_index) { + *out_index = i; + } + return 1; + } + } + return 0; + } + + if (p == NULL) { + return 0; + } + + sk_sort(sk); + + /* sk->comp is a function that takes pointers to pointers to elements, but + * qsort and bsearch take a comparison function that just takes pointers to + * elements. However, since we're passing an array of pointers to + * qsort/bsearch, we can just cast the comparison function and everything + * works. */ + comp_func=(int (*)(const void *,const void *))(sk->comp); + r = bsearch(&p, sk->data, sk->num, sizeof(void *), comp_func); + if (r == NULL) { + return 0; + } + i = ((void **)r) - sk->data; + /* This function always returns the first result. */ + while (i > 0 && sk->comp((const void**) &p, (const void**) &sk->data[i-1]) == 0) { + i--; + } + if (out_index) { + *out_index = i; + } + return 1; +} + +void *sk_shift(_STACK *sk) { + if (sk == NULL) { + return NULL; + } + if (sk->num == 0) { + return NULL; + } + return sk_delete(sk, 0); +} + +size_t sk_push(_STACK *sk, void *p) { return (sk_insert(sk, p, sk->num)); } + +void *sk_pop(_STACK *sk) { + if (sk == NULL) { + return NULL; + } + if (sk->num == 0) { + return NULL; + } + return sk_delete(sk, sk->num - 1); +} + +_STACK *sk_dup(const _STACK *sk) { + _STACK *ret; + void **s; + + if (sk == NULL) { + return NULL; + } + + ret = sk_new(sk->comp); + if (ret == NULL) { + goto err; + } + + s = (void **)OPENSSL_realloc(ret->data, sizeof(void *) * sk->num_alloc); + if (s == NULL) { + goto err; + } + ret->data = s; + + ret->num = sk->num; + memcpy(ret->data, sk->data, sizeof(void *) * sk->num); + ret->sorted = sk->sorted; + ret->num_alloc = sk->num_alloc; + ret->comp = sk->comp; + return ret; + +err: + sk_free(ret); + return NULL; +} + +void sk_sort(_STACK *sk) { + int (*comp_func)(const void *,const void *); + + if (sk == NULL || sk->comp == NULL || sk->sorted) { + return; + } + + /* See the comment in sk_find about this cast. */ + comp_func = (int (*)(const void *, const void *))(sk->comp); + qsort(sk->data, sk->num, sizeof(void *), comp_func); + sk->sorted = 1; +} + +int sk_is_sorted(const _STACK *sk) { + if (!sk) { + return 1; + } + return sk->sorted; +} + +stack_cmp_func sk_set_cmp_func(_STACK *sk, stack_cmp_func comp) { + stack_cmp_func old = sk->comp; + + if (sk->comp != comp) { + sk->sorted = 0; + } + sk->comp = comp; + + return old; +} + +_STACK *sk_deep_copy(const _STACK *sk, void *(*copy_func)(void *), + void (*free_func)(void *)) { + _STACK *ret = sk_dup(sk); + if (ret == NULL) { + return NULL; + } + + size_t i; + for (i = 0; i < ret->num; i++) { + if (ret->data[i] == NULL) { + continue; + } + ret->data[i] = copy_func(ret->data[i]); + if (ret->data[i] == NULL) { + size_t j; + for (j = 0; j < i; j++) { + if (ret->data[j] != NULL) { + free_func(ret->data[j]); + } + } + sk_free(ret); + return NULL; + } + } + + return ret; +} diff --git a/external/boringssl/crypto/test/CMakeLists.txt b/external/boringssl/crypto/test/CMakeLists.txt new file mode 100644 index 0000000000..8c75314339 --- /dev/null +++ b/external/boringssl/crypto/test/CMakeLists.txt @@ -0,0 +1,9 @@ +add_library( + test_support + + OBJECT + + file_test.cc + malloc.cc + test_util.cc +) diff --git a/external/boringssl/crypto/test/file_test.cc b/external/boringssl/crypto/test/file_test.cc new file mode 100644 index 0000000000..d684aa09fe --- /dev/null +++ b/external/boringssl/crypto/test/file_test.cc @@ -0,0 +1,302 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include "file_test.h" + +#include + +#include +#include +#include +#include +#include + +#include + + +FileTest::FileTest(const char *path) { + file_ = fopen(path, "r"); + if (file_ == nullptr) { + fprintf(stderr, "Could not open file %s: %s.\n", path, strerror(errno)); + } +} + +FileTest::~FileTest() { + if (file_ != nullptr) { + fclose(file_); + } +} + +// FindDelimiter returns a pointer to the first '=' or ':' in |str| or nullptr +// if there is none. +static const char *FindDelimiter(const char *str) { + while (*str) { + if (*str == ':' || *str == '=') { + return str; + } + str++; + } + return nullptr; +} + +// StripSpace returns a string containing up to |len| characters from |str| with +// leading and trailing whitespace removed. +static std::string StripSpace(const char *str, size_t len) { + // Remove leading space. + while (len > 0 && isspace(*str)) { + str++; + len--; + } + while (len > 0 && isspace(str[len-1])) { + len--; + } + return std::string(str, len); +} + +FileTest::ReadResult FileTest::ReadNext() { + // If the previous test had unused attributes, it is an error. + if (!unused_attributes_.empty()) { + for (const std::string &key : unused_attributes_) { + PrintLine("Unused attribute: %s", key.c_str()); + } + return kReadError; + } + + ClearTest(); + + static const size_t kBufLen = 64 + 8192*2; + std::unique_ptr buf(new char[kBufLen]); + + while (true) { + // Read the next line. + if (fgets(buf.get(), kBufLen, file_) == nullptr) { + if (feof(file_)) { + // EOF is a valid terminator for a test. + return start_line_ > 0 ? kReadSuccess : kReadEOF; + } + fprintf(stderr, "Error reading from input.\n"); + return kReadError; + } + + line_++; + size_t len = strlen(buf.get()); + // Check for truncation. + if (len > 0 && buf[len - 1] != '\n' && !feof(file_)) { + fprintf(stderr, "Line %u too long.\n", line_); + return kReadError; + } + + if (buf[0] == '\n' || buf[0] == '\0') { + // Empty lines delimit tests. + if (start_line_ > 0) { + return kReadSuccess; + } + } else if (buf[0] != '#') { // Comment lines are ignored. + // Parse the line as an attribute. + const char *delimiter = FindDelimiter(buf.get()); + if (delimiter == nullptr) { + fprintf(stderr, "Line %u: Could not parse attribute.\n", line_); + return kReadError; + } + std::string key = StripSpace(buf.get(), delimiter - buf.get()); + std::string value = StripSpace(delimiter + 1, + buf.get() + len - delimiter - 1); + + unused_attributes_.insert(key); + attributes_[key] = value; + if (start_line_ == 0) { + // This is the start of a test. + type_ = key; + parameter_ = value; + start_line_ = line_; + } + } + } +} + +void FileTest::PrintLine(const char *format, ...) { + va_list args; + va_start(args, format); + + fprintf(stderr, "Line %u: ", start_line_); + vfprintf(stderr, format, args); + fprintf(stderr, "\n"); + + va_end(args); +} + +const std::string &FileTest::GetType() { + OnKeyUsed(type_); + return type_; +} + +const std::string &FileTest::GetParameter() { + OnKeyUsed(type_); + return parameter_; +} + +bool FileTest::HasAttribute(const std::string &key) { + OnKeyUsed(key); + return attributes_.count(key) > 0; +} + +bool FileTest::GetAttribute(std::string *out_value, const std::string &key) { + OnKeyUsed(key); + auto iter = attributes_.find(key); + if (iter == attributes_.end()) { + PrintLine("Missing attribute '%s'.", key.c_str()); + return false; + } + *out_value = iter->second; + return true; +} + +const std::string &FileTest::GetAttributeOrDie(const std::string &key) { + if (!HasAttribute(key)) { + abort(); + } + return attributes_[key]; +} + +static bool FromHexDigit(uint8_t *out, char c) { + if ('0' <= c && c <= '9') { + *out = c - '0'; + return true; + } + if ('a' <= c && c <= 'f') { + *out = c - 'a' + 10; + return true; + } + if ('A' <= c && c <= 'F') { + *out = c - 'A' + 10; + return true; + } + return false; +} + +bool FileTest::GetBytes(std::vector *out, const std::string &key) { + std::string value; + if (!GetAttribute(&value, key)) { + return false; + } + + if (value.size() >= 2 && value[0] == '"' && value[value.size() - 1] == '"') { + out->assign(value.begin() + 1, value.end() - 1); + return true; + } + + if (value.size() % 2 != 0) { + PrintLine("Error decoding value: %s", value.c_str()); + return false; + } + out->clear(); + out->reserve(value.size() / 2); + for (size_t i = 0; i < value.size(); i += 2) { + uint8_t hi, lo; + if (!FromHexDigit(&hi, value[i]) || !FromHexDigit(&lo, value[i+1])) { + PrintLine("Error decoding value: %s", value.c_str()); + return false; + } + out->push_back((hi << 4) | lo); + } + return true; +} + +static std::string EncodeHex(const uint8_t *in, size_t in_len) { + static const char kHexDigits[] = "0123456789abcdef"; + std::string ret; + ret.reserve(in_len * 2); + for (size_t i = 0; i < in_len; i++) { + ret += kHexDigits[in[i] >> 4]; + ret += kHexDigits[in[i] & 0xf]; + } + return ret; +} + +bool FileTest::ExpectBytesEqual(const uint8_t *expected, size_t expected_len, + const uint8_t *actual, size_t actual_len) { + if (expected_len == actual_len && + memcmp(expected, actual, expected_len) == 0) { + return true; + } + + std::string expected_hex = EncodeHex(expected, expected_len); + std::string actual_hex = EncodeHex(actual, actual_len); + PrintLine("Expected: %s", expected_hex.c_str()); + PrintLine("Actual: %s", actual_hex.c_str()); + return false; +} + +void FileTest::ClearTest() { + start_line_ = 0; + type_.clear(); + parameter_.clear(); + attributes_.clear(); + unused_attributes_.clear(); +} + +void FileTest::OnKeyUsed(const std::string &key) { + unused_attributes_.erase(key); +} + +int FileTestMain(bool (*run_test)(FileTest *t, void *arg), void *arg, + const char *path) { + FileTest t(path); + if (!t.is_open()) { + return 1; + } + + bool failed = false; + while (true) { + FileTest::ReadResult ret = t.ReadNext(); + if (ret == FileTest::kReadError) { + return 1; + } else if (ret == FileTest::kReadEOF) { + break; + } + + bool result = run_test(&t, arg); + if (t.HasAttribute("Error")) { + if (result) { + t.PrintLine("Operation unexpectedly succeeded."); + failed = true; + continue; + } + uint32_t err = ERR_peek_error(); + if (ERR_reason_error_string(err) != t.GetAttributeOrDie("Error")) { + t.PrintLine("Unexpected error; wanted '%s', got '%s'.", + t.GetAttributeOrDie("Error").c_str(), + ERR_reason_error_string(err)); + failed = true; + ERR_clear_error(); + continue; + } + ERR_clear_error(); + } else if (!result) { + // In case the test itself doesn't print output, print something so the + // line number is reported. + t.PrintLine("Test failed"); + ERR_print_errors_fp(stderr); + failed = true; + continue; + } + } + + if (failed) { + return 1; + } + + printf("PASS\n"); + return 0; +} diff --git a/external/boringssl/crypto/test/file_test.h b/external/boringssl/crypto/test/file_test.h new file mode 100644 index 0000000000..a8591277d5 --- /dev/null +++ b/external/boringssl/crypto/test/file_test.h @@ -0,0 +1,157 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_CRYPTO_TEST_FILE_TEST_H +#define OPENSSL_HEADER_CRYPTO_TEST_FILE_TEST_H + +#include + +#include +#include + +OPENSSL_MSVC_PRAGMA(warning(push)) +OPENSSL_MSVC_PRAGMA(warning(disable: 4702)) + +#include +#include +#include +#include + +OPENSSL_MSVC_PRAGMA(warning(pop)) + +// File-based test framework. +// +// This module provides a file-based test framework. The file format is based on +// that of OpenSSL upstream's evp_test and BoringSSL's aead_test. Each input +// file is a sequence of attributes and blank lines. +// +// Each attribute has the form: +// +// Name = Value +// +// Either '=' or ':' may be used to delimit the name from the value. Both the +// name and value have leading and trailing spaces stripped. +// +// Lines beginning with # are ignored. +// +// A test is a sequence of one or more attributes followed by a blank line. +// Blank lines are otherwise ignored. For tests that process multiple kinds of +// test cases, the first attribute is parsed out as the test's type and +// parameter. Otherwise, attributes are unordered. The first attribute is also +// included in the set of attributes, so tests which do not dispatch may ignore +// this mechanism. +// +// Functions in this module freely output to |stderr| on failure. Tests should +// also do so, and it is recommended they include the corresponding test's line +// number in any output. |PrintLine| does this automatically. +// +// Each attribute in a test must be consumed. When a test completes, if any +// attributes haven't been processed, the framework reports an error. + + +class FileTest { + public: + explicit FileTest(const char *path); + ~FileTest(); + + // is_open returns true if the file was successfully opened. + bool is_open() const { return file_ != nullptr; } + + enum ReadResult { + kReadSuccess, + kReadEOF, + kReadError, + }; + + // ReadNext reads the next test from the file. It returns |kReadSuccess| if + // successfully reading a test and |kReadEOF| at the end of the file. On + // error or if the previous test had unconsumed attributes, it returns + // |kReadError|. + ReadResult ReadNext(); + + // PrintLine is a variant of printf which prepends the line number and appends + // a trailing newline. + void PrintLine(const char *format, ...) OPENSSL_PRINTF_FORMAT_FUNC(2, 3); + + unsigned start_line() const { return start_line_; } + + // GetType returns the name of the first attribute of the current test. + const std::string &GetType(); + // GetParameter returns the value of the first attribute of the current test. + const std::string &GetParameter(); + + // HasAttribute returns true if the current test has an attribute named |key|. + bool HasAttribute(const std::string &key); + + // GetAttribute looks up the attribute with key |key|. It sets |*out_value| to + // the value and returns true if it exists and returns false with an error to + // |stderr| otherwise. + bool GetAttribute(std::string *out_value, const std::string &key); + + // GetAttributeOrDie looks up the attribute with key |key| and aborts if it is + // missing. It should only be used after a |HasAttribute| call. + const std::string &GetAttributeOrDie(const std::string &key); + + // GetBytes looks up the attribute with key |key| and decodes it as a byte + // string. On success, it writes the result to |*out| and returns + // true. Otherwise it returns false with an error to |stderr|. The value may + // be either a hexadecimal string or a quoted ASCII string. It returns true on + // success and returns false with an error to |stderr| on failure. + bool GetBytes(std::vector *out, const std::string &key); + + // ExpectBytesEqual returns true if |expected| and |actual| are equal. + // Otherwise, it returns false and prints a message to |stderr|. + bool ExpectBytesEqual(const uint8_t *expected, size_t expected_len, + const uint8_t *actual, size_t actual_len); + + private: + void ClearTest(); + void OnKeyUsed(const std::string &key); + + FILE *file_ = nullptr; + // line_ is the number of lines read. + unsigned line_ = 0; + + // start_line_ is the line number of the first attribute of the test. + unsigned start_line_ = 0; + // type_ is the name of the first attribute of the test. + std::string type_; + // parameter_ is the value of the first attribute. + std::string parameter_; + // attributes_ contains all attributes in the test, including the first. + std::map attributes_; + + // unused_attributes_ is the set of attributes that have been queried. + std::set unused_attributes_; + + FileTest(const FileTest&) = delete; + FileTest &operator=(const FileTest&) = delete; +}; + +// FileTestMain runs a file-based test out of |path| and returns an exit code +// suitable to return out of |main|. |run_test| should return true on pass and +// false on failure. FileTestMain also implements common handling of the 'Error' +// attribute. A test with that attribute is expected to fail. The value of the +// attribute is the reason string of the expected OpenSSL error code. +// +// Tests are guaranteed to run serially and may affect global state if need be. +// It is legal to use "tests" which, for example, import a private key into a +// list of keys. This may be used to initialize a shared set of keys for many +// tests. However, if one test fails, the framework will continue to run +// subsequent tests. +int FileTestMain(bool (*run_test)(FileTest *t, void *arg), void *arg, + const char *path); + + +#endif /* OPENSSL_HEADER_CRYPTO_TEST_FILE_TEST_H */ diff --git a/external/boringssl/crypto/test/malloc.cc b/external/boringssl/crypto/test/malloc.cc new file mode 100644 index 0000000000..898f2a7c95 --- /dev/null +++ b/external/boringssl/crypto/test/malloc.cc @@ -0,0 +1,150 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#if defined(__has_feature) +#if __has_feature(address_sanitizer) || __has_feature(memory_sanitizer) +#define OPENSSL_ASAN +#endif +#endif + +#if defined(__GLIBC__) && !defined(__UCLIBC__) +#define OPENSSL_GLIBC +#endif + +// This file isn't built on ARM or Aarch64 because we link statically in those +// builds and trying to override malloc in a static link doesn't work. It also +// requires glibc. It's also disabled on ASan builds as this interferes with +// ASan's malloc interceptor. +// +// TODO(davidben): See if this and ASan's and MSan's interceptors can be made to +// coexist. +#if defined(__linux__) && defined(OPENSSL_GLIBC) && !defined(OPENSSL_ARM) && \ + !defined(OPENSSL_AARCH64) && !defined(OPENSSL_ASAN) + +#include +#include +#include +#include +#include +#include + +#include + + +/* This file defines overrides for the standard allocation functions that allow + * a given allocation to be made to fail for testing. If the program is run + * with MALLOC_NUMBER_TO_FAIL set to a base-10 number then that allocation will + * return NULL. If MALLOC_BREAK_ON_FAIL is also defined then the allocation + * will signal SIGTRAP rather than return NULL. + * + * This code is not thread safe. */ + +static uint64_t current_malloc_count = 0; +static uint64_t malloc_number_to_fail = 0; +static char failure_enabled = 0, break_on_fail = 0; +static int in_call = 0; + +extern "C" { +/* These are other names for the standard allocation functions. */ +extern void *__libc_malloc(size_t size); +extern void *__libc_calloc(size_t num_elems, size_t size); +extern void *__libc_realloc(void *ptr, size_t size); +} + +static void exit_handler(void) { + if (failure_enabled && current_malloc_count > malloc_number_to_fail) { + _exit(88); + } +} + +static void cpp_new_handler() { + // Return to try again. It won't fail a second time. + return; +} + +/* should_fail_allocation returns true if the current allocation should fail. */ +static int should_fail_allocation() { + static int init = 0; + char should_fail; + + if (in_call) { + return 0; + } + + in_call = 1; + + if (!init) { + const char *env = getenv("MALLOC_NUMBER_TO_FAIL"); + if (env != NULL && env[0] != 0) { + char *endptr; + malloc_number_to_fail = strtoull(env, &endptr, 10); + if (*endptr == 0) { + failure_enabled = 1; + atexit(exit_handler); + std::set_new_handler(cpp_new_handler); + } + } + break_on_fail = (NULL != getenv("MALLOC_BREAK_ON_FAIL")); + init = 1; + } + + in_call = 0; + + if (!failure_enabled) { + return 0; + } + + should_fail = (current_malloc_count == malloc_number_to_fail); + current_malloc_count++; + + if (should_fail && break_on_fail) { + raise(SIGTRAP); + } + return should_fail; +} + +extern "C" { + +void *malloc(size_t size) { + if (should_fail_allocation()) { + errno = ENOMEM; + return NULL; + } + + return __libc_malloc(size); +} + +void *calloc(size_t num_elems, size_t size) { + if (should_fail_allocation()) { + errno = ENOMEM; + return NULL; + } + + return __libc_calloc(num_elems, size); +} + +void *realloc(void *ptr, size_t size) { + if (should_fail_allocation()) { + errno = ENOMEM; + return NULL; + } + + return __libc_realloc(ptr, size); +} + +} // extern "C" + +#endif /* defined(linux) && GLIBC && !ARM && !AARCH64 && !ASAN */ diff --git a/external/boringssl/crypto/test/scoped_types.h b/external/boringssl/crypto/test/scoped_types.h new file mode 100644 index 0000000000..2a2c371364 --- /dev/null +++ b/external/boringssl/crypto/test/scoped_types.h @@ -0,0 +1,145 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_CRYPTO_TEST_SCOPED_TYPES_H +#define OPENSSL_HEADER_CRYPTO_TEST_SCOPED_TYPES_H + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +template +struct OpenSSLDeleter { + void operator()(T *obj) { + func(obj); + } +}; + +template +struct OpenSSLStackDeleter { + void operator()(StackType *obj) { + sk_pop_free(reinterpret_cast<_STACK*>(obj), + reinterpret_cast(func)); + } +}; + +template +struct OpenSSLFree { + void operator()(T *buf) { + OPENSSL_free(buf); + } +}; + +struct FileCloser { + void operator()(FILE *file) { + fclose(file); + } +}; + +template +using ScopedOpenSSLType = std::unique_ptr>; + +template +using ScopedOpenSSLStack = + std::unique_ptr>; + +template +class ScopedOpenSSLContext { + public: + ScopedOpenSSLContext() { + init_func(&ctx_); + } + ~ScopedOpenSSLContext() { + cleanup_func(&ctx_); + } + + T *get() { return &ctx_; } + const T *get() const { return &ctx_; } + + void Reset() { + cleanup_func(&ctx_); + init_func(&ctx_); + } + + private: + T ctx_; +}; + +using ScopedASN1_TYPE = ScopedOpenSSLType; +using ScopedBIO = ScopedOpenSSLType; +using ScopedBIGNUM = ScopedOpenSSLType; +using ScopedBN_CTX = ScopedOpenSSLType; +using ScopedBN_MONT_CTX = ScopedOpenSSLType; +using ScopedCMAC_CTX = ScopedOpenSSLType; +using ScopedDH = ScopedOpenSSLType; +using ScopedECDSA_SIG = ScopedOpenSSLType; +using ScopedEC_GROUP = ScopedOpenSSLType; +using ScopedEC_KEY = ScopedOpenSSLType; +using ScopedEC_POINT = ScopedOpenSSLType; +using ScopedEVP_PKEY = ScopedOpenSSLType; +using ScopedEVP_PKEY_CTX = ScopedOpenSSLType; +using ScopedNEWHOPE_POLY = ScopedOpenSSLType; +using ScopedPKCS8_PRIV_KEY_INFO = ScopedOpenSSLType; +using ScopedPKCS12 = ScopedOpenSSLType; +using ScopedSPAKE2_CTX = ScopedOpenSSLType; +using ScopedRSA = ScopedOpenSSLType; +using ScopedX509 = ScopedOpenSSLType; +using ScopedX509_ALGOR = ScopedOpenSSLType; +using ScopedX509_SIG = ScopedOpenSSLType; +using ScopedX509_STORE_CTX = ScopedOpenSSLType; + +using ScopedX509Stack = ScopedOpenSSLStack; + +using ScopedCBB = ScopedOpenSSLContext; +using ScopedEVP_AEAD_CTX = ScopedOpenSSLContext; +using ScopedEVP_CIPHER_CTX = ScopedOpenSSLContext; +using ScopedEVP_MD_CTX = ScopedOpenSSLContext; +using ScopedHMAC_CTX = ScopedOpenSSLContext; + +using ScopedOpenSSLBytes = std::unique_ptr>; +using ScopedOpenSSLString = std::unique_ptr>; + +using ScopedFILE = std::unique_ptr; + +#endif // OPENSSL_HEADER_CRYPTO_TEST_SCOPED_TYPES_H diff --git a/external/boringssl/crypto/test/test_util.cc b/external/boringssl/crypto/test/test_util.cc new file mode 100644 index 0000000000..8021aaa864 --- /dev/null +++ b/external/boringssl/crypto/test/test_util.cc @@ -0,0 +1,30 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include + +#include "test_util.h" + + +void hexdump(FILE *fp, const char *msg, const void *in, size_t len) { + const uint8_t *data = reinterpret_cast(in); + size_t i; + + fputs(msg, fp); + for (i = 0; i < len; i++) { + fprintf(fp, "%02x", data[i]); + } + fputs("\n", fp); +} diff --git a/external/boringssl/crypto/test/test_util.h b/external/boringssl/crypto/test/test_util.h new file mode 100644 index 0000000000..972e206517 --- /dev/null +++ b/external/boringssl/crypto/test/test_util.h @@ -0,0 +1,35 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_CRYPTO_TEST_TEST_UTIL_H +#define OPENSSL_HEADER_CRYPTO_TEST_TEST_UTIL_H + +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* hexdump writes |msg| to |fp| followed by the hex encoding of |len| bytes + * from |in|. */ +void hexdump(FILE *fp, const char *msg, const void *in, size_t len); + + +#if defined(__cplusplus) +} +#endif + +#endif /* OPENSSL_HEADER_CRYPTO_TEST_TEST_UTIL_H */ diff --git a/external/boringssl/crypto/thread.c b/external/boringssl/crypto/thread.c new file mode 100644 index 0000000000..373f8dbca4 --- /dev/null +++ b/external/boringssl/crypto/thread.c @@ -0,0 +1,122 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#if !defined(OPENSSL_WINDOWS) +#include +#else +OPENSSL_MSVC_PRAGMA(warning(push, 3)) +#include +OPENSSL_MSVC_PRAGMA(warning(pop)) +#endif + +#include + + +int CRYPTO_num_locks(void) { return 1; } + +void CRYPTO_set_locking_callback(void (*func)(int mode, int lock_num, + const char *file, int line)) {} + +void (*CRYPTO_get_locking_callback(void))(int mode, int lock_num, + const char *file, int line) { + return NULL; +} + +void CRYPTO_set_add_lock_callback(int (*func)(int *num, int mount, int lock_num, + const char *file, int line)) {} + +const char *CRYPTO_get_lock_name(int lock_num) { + return "No old-style OpenSSL locks anymore"; +} + +int CRYPTO_THREADID_set_callback(void (*func)(CRYPTO_THREADID *)) { return 1; } + +void CRYPTO_THREADID_set_numeric(CRYPTO_THREADID *id, unsigned long val) {} + +void CRYPTO_THREADID_set_pointer(CRYPTO_THREADID *id, void *ptr) {} + +void CRYPTO_THREADID_current(CRYPTO_THREADID *id) {} + +void CRYPTO_set_id_callback(unsigned long (*func)(void)) {} + +void CRYPTO_set_dynlock_create_callback(struct CRYPTO_dynlock_value *( + *dyn_create_function)(const char *file, int line)) {} + +void CRYPTO_set_dynlock_lock_callback(void (*dyn_lock_function)( + int mode, struct CRYPTO_dynlock_value *l, const char *file, int line)) {} + +void CRYPTO_set_dynlock_destroy_callback(void (*dyn_destroy_function)( + struct CRYPTO_dynlock_value *l, const char *file, int line)) {} + +struct CRYPTO_dynlock_value *(*CRYPTO_get_dynlock_create_callback(void))( + const char *file, int line) { + return NULL; +} + +void (*CRYPTO_get_dynlock_lock_callback(void))(int mode, + struct CRYPTO_dynlock_value *l, + const char *file, int line) { + return NULL; +} + +void (*CRYPTO_get_dynlock_destroy_callback(void))( + struct CRYPTO_dynlock_value *l, const char *file, int line) { + return NULL; +} diff --git a/external/boringssl/crypto/thread_none.c b/external/boringssl/crypto/thread_none.c new file mode 100644 index 0000000000..85768b4bf6 --- /dev/null +++ b/external/boringssl/crypto/thread_none.c @@ -0,0 +1,59 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include "internal.h" + +#if defined(OPENSSL_NO_THREADS) + +void CRYPTO_MUTEX_init(CRYPTO_MUTEX *lock) {} + +void CRYPTO_MUTEX_lock_read(CRYPTO_MUTEX *lock) {} + +void CRYPTO_MUTEX_lock_write(CRYPTO_MUTEX *lock) {} + +void CRYPTO_MUTEX_unlock_read(CRYPTO_MUTEX *lock) {} + +void CRYPTO_MUTEX_unlock_write(CRYPTO_MUTEX *lock) {} + +void CRYPTO_MUTEX_cleanup(CRYPTO_MUTEX *lock) {} + +void CRYPTO_STATIC_MUTEX_lock_read(struct CRYPTO_STATIC_MUTEX *lock) {} + +void CRYPTO_STATIC_MUTEX_lock_write(struct CRYPTO_STATIC_MUTEX *lock) {} + +void CRYPTO_STATIC_MUTEX_unlock_read(struct CRYPTO_STATIC_MUTEX *lock) {} + +void CRYPTO_STATIC_MUTEX_unlock_write(struct CRYPTO_STATIC_MUTEX *lock) {} + +void CRYPTO_once(CRYPTO_once_t *once, void (*init)(void)) { + if (*once) { + return; + } + *once = 1; + init(); +} + +static void *g_thread_locals[NUM_OPENSSL_THREAD_LOCALS]; + +void *CRYPTO_get_thread_local(thread_local_data_t index) { + return g_thread_locals[index]; +} + +int CRYPTO_set_thread_local(thread_local_data_t index, void *value, + thread_local_destructor_t destructor) { + g_thread_locals[index] = value; + return 1; +} + +#endif /* OPENSSL_NO_THREADS */ diff --git a/external/boringssl/crypto/thread_pthread.c b/external/boringssl/crypto/thread_pthread.c new file mode 100644 index 0000000000..2baa2b4dd4 --- /dev/null +++ b/external/boringssl/crypto/thread_pthread.c @@ -0,0 +1,176 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include "internal.h" + +#if !defined(OPENSSL_WINDOWS) && !defined(OPENSSL_NO_THREADS) + +#include +#include +#include + +#include +#include + + +OPENSSL_COMPILE_ASSERT(sizeof(CRYPTO_MUTEX) >= sizeof(pthread_rwlock_t), + CRYPTO_MUTEX_too_small); + +void CRYPTO_MUTEX_init(CRYPTO_MUTEX *lock) { + if (pthread_rwlock_init((pthread_rwlock_t *) lock, NULL) != 0) { + abort(); + } +} + +void CRYPTO_MUTEX_lock_read(CRYPTO_MUTEX *lock) { + if (pthread_rwlock_rdlock((pthread_rwlock_t *) lock) != 0) { + abort(); + } +} + +void CRYPTO_MUTEX_lock_write(CRYPTO_MUTEX *lock) { + if (pthread_rwlock_wrlock((pthread_rwlock_t *) lock) != 0) { + abort(); + } +} + +void CRYPTO_MUTEX_unlock_read(CRYPTO_MUTEX *lock) { + if (pthread_rwlock_unlock((pthread_rwlock_t *) lock) != 0) { + abort(); + } +} + +void CRYPTO_MUTEX_unlock_write(CRYPTO_MUTEX *lock) { + if (pthread_rwlock_unlock((pthread_rwlock_t *) lock) != 0) { + abort(); + } +} + +void CRYPTO_MUTEX_cleanup(CRYPTO_MUTEX *lock) { + pthread_rwlock_destroy((pthread_rwlock_t *) lock); +} + +void CRYPTO_STATIC_MUTEX_lock_read(struct CRYPTO_STATIC_MUTEX *lock) { + if (pthread_rwlock_rdlock(&lock->lock) != 0) { + abort(); + } +} + +void CRYPTO_STATIC_MUTEX_lock_write(struct CRYPTO_STATIC_MUTEX *lock) { + if (pthread_rwlock_wrlock(&lock->lock) != 0) { + abort(); + } +} + +void CRYPTO_STATIC_MUTEX_unlock_read(struct CRYPTO_STATIC_MUTEX *lock) { + if (pthread_rwlock_unlock(&lock->lock) != 0) { + abort(); + } +} + +void CRYPTO_STATIC_MUTEX_unlock_write(struct CRYPTO_STATIC_MUTEX *lock) { + if (pthread_rwlock_unlock(&lock->lock) != 0) { + abort(); + } +} + +void CRYPTO_once(CRYPTO_once_t *once, void (*init)(void)) { + if (pthread_once(once, init) != 0) { + abort(); + } +} + +static pthread_mutex_t g_destructors_lock = PTHREAD_MUTEX_INITIALIZER; +static thread_local_destructor_t g_destructors[NUM_OPENSSL_THREAD_LOCALS]; + +static void thread_local_destructor(void *arg) { + if (arg == NULL) { + return; + } + + thread_local_destructor_t destructors[NUM_OPENSSL_THREAD_LOCALS]; + if (pthread_mutex_lock(&g_destructors_lock) != 0) { + return; + } + memcpy(destructors, g_destructors, sizeof(destructors)); + pthread_mutex_unlock(&g_destructors_lock); + + unsigned i; + void **pointers = arg; + for (i = 0; i < NUM_OPENSSL_THREAD_LOCALS; i++) { + if (destructors[i] != NULL) { + destructors[i](pointers[i]); + } + } + + OPENSSL_free(pointers); +} + +static pthread_once_t g_thread_local_init_once = PTHREAD_ONCE_INIT; +static pthread_key_t g_thread_local_key; +static int g_thread_local_failed = 0; + +static void thread_local_init(void) { + g_thread_local_failed = + pthread_key_create(&g_thread_local_key, thread_local_destructor) != 0; +} + +void *CRYPTO_get_thread_local(thread_local_data_t index) { + CRYPTO_once(&g_thread_local_init_once, thread_local_init); + if (g_thread_local_failed) { + return NULL; + } + + void **pointers = pthread_getspecific(g_thread_local_key); + if (pointers == NULL) { + return NULL; + } + return pointers[index]; +} + +int CRYPTO_set_thread_local(thread_local_data_t index, void *value, + thread_local_destructor_t destructor) { + CRYPTO_once(&g_thread_local_init_once, thread_local_init); + if (g_thread_local_failed) { + destructor(value); + return 0; + } + + void **pointers = pthread_getspecific(g_thread_local_key); + if (pointers == NULL) { + pointers = OPENSSL_malloc(sizeof(void *) * NUM_OPENSSL_THREAD_LOCALS); + if (pointers == NULL) { + destructor(value); + return 0; + } + memset(pointers, 0, sizeof(void *) * NUM_OPENSSL_THREAD_LOCALS); + if (pthread_setspecific(g_thread_local_key, pointers) != 0) { + OPENSSL_free(pointers); + destructor(value); + return 0; + } + } + + if (pthread_mutex_lock(&g_destructors_lock) != 0) { + destructor(value); + return 0; + } + g_destructors[index] = destructor; + pthread_mutex_unlock(&g_destructors_lock); + + pointers[index] = value; + return 1; +} + +#endif /* !OPENSSL_WINDOWS && !OPENSSL_NO_THREADS */ diff --git a/external/boringssl/crypto/thread_test.c b/external/boringssl/crypto/thread_test.c new file mode 100644 index 0000000000..12ca2ec026 --- /dev/null +++ b/external/boringssl/crypto/thread_test.c @@ -0,0 +1,217 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include "internal.h" + +#include + + +#if !defined(OPENSSL_NO_THREADS) + +#if defined(OPENSSL_WINDOWS) + +OPENSSL_MSVC_PRAGMA(warning(push, 3)) +#include +OPENSSL_MSVC_PRAGMA(warning(pop)) + +typedef HANDLE thread_t; + +static DWORD WINAPI thread_run(LPVOID arg) { + void (*thread_func)(void); + /* VC really doesn't like casting between data and function pointers. */ + memcpy(&thread_func, &arg, sizeof(thread_func)); + thread_func(); + return 0; +} + +static int run_thread(thread_t *out_thread, void (*thread_func)(void)) { + void *arg; + /* VC really doesn't like casting between data and function pointers. */ + memcpy(&arg, &thread_func, sizeof(arg)); + + *out_thread = CreateThread(NULL /* security attributes */, + 0 /* default stack size */, thread_run, arg, + 0 /* run immediately */, NULL /* ignore id */); + return *out_thread != NULL; +} + +static int wait_for_thread(thread_t thread) { + return WaitForSingleObject(thread, INFINITE) == 0; +} + +#else + +#include +#include +#include + +typedef pthread_t thread_t; + +static void *thread_run(void *arg) { + void (*thread_func)(void) = arg; + thread_func(); + return NULL; +} + +static int run_thread(thread_t *out_thread, void (*thread_func)(void)) { + return pthread_create(out_thread, NULL /* default attributes */, thread_run, + thread_func) == 0; +} + +static int wait_for_thread(thread_t thread) { + return pthread_join(thread, NULL) == 0; +} + +#endif /* OPENSSL_WINDOWS */ + +static unsigned g_once_init_called = 0; + +static void once_init(void) { + g_once_init_called++; + + /* Sleep briefly so one |call_once_thread| instance will call |CRYPTO_once| + * while the other is running this function. */ +#if defined(OPENSSL_WINDOWS) + Sleep(1 /* milliseconds */); +#else + struct timespec req; + memset(&req, 0, sizeof(req)); + req.tv_nsec = 1000000; + nanosleep(&req, NULL); +#endif +} + +static CRYPTO_once_t g_test_once = CRYPTO_ONCE_INIT; + +static void call_once_thread(void) { + CRYPTO_once(&g_test_once, once_init); +} + +static int test_once(void) { + if (g_once_init_called != 0) { + fprintf(stderr, "g_once_init_called was non-zero at start.\n"); + return 0; + } + + thread_t thread1, thread2; + if (!run_thread(&thread1, call_once_thread) || + !run_thread(&thread2, call_once_thread) || + !wait_for_thread(thread1) || + !wait_for_thread(thread2)) { + fprintf(stderr, "thread failed.\n"); + return 0; + } + + CRYPTO_once(&g_test_once, once_init); + + if (g_once_init_called != 1) { + fprintf(stderr, "Expected init function to be called once, but found %u.\n", + g_once_init_called); + return 0; + } + + return 1; +} + + +static int g_test_thread_ok = 0; +static unsigned g_destructor_called_count = 0; + +static void thread_local_destructor(void *arg) { + if (arg == NULL) { + return; + } + + unsigned *count = arg; + (*count)++; +} + +static void thread_local_test_thread(void) { + void *ptr = CRYPTO_get_thread_local(OPENSSL_THREAD_LOCAL_TEST); + if (ptr != NULL) { + return; + } + + if (!CRYPTO_set_thread_local(OPENSSL_THREAD_LOCAL_TEST, + &g_destructor_called_count, + thread_local_destructor)) { + return; + } + + if (CRYPTO_get_thread_local(OPENSSL_THREAD_LOCAL_TEST) != + &g_destructor_called_count) { + return; + } + + g_test_thread_ok = 1; +} + +static void thread_local_test2_thread(void) {} + +static int test_thread_local(void) { + void *ptr = CRYPTO_get_thread_local(OPENSSL_THREAD_LOCAL_TEST); + if (ptr != NULL) { + fprintf(stderr, "Thread-local data was non-NULL at start.\n"); + } + + thread_t thread; + if (!run_thread(&thread, thread_local_test_thread) || + !wait_for_thread(thread)) { + fprintf(stderr, "thread failed.\n"); + return 0; + } + + if (!g_test_thread_ok) { + fprintf(stderr, "Thread-local data didn't work in thread.\n"); + return 0; + } + + if (g_destructor_called_count != 1) { + fprintf(stderr, + "Destructor should have been called once, but actually called %u " + "times.\n", + g_destructor_called_count); + return 0; + } + + /* thread_local_test2_thread doesn't do anything, but it tests that the + * thread destructor function works even if thread-local storage wasn't used + * for a thread. */ + if (!run_thread(&thread, thread_local_test2_thread) || + !wait_for_thread(thread)) { + fprintf(stderr, "thread failed.\n"); + return 0; + } + + return 1; +} + +int main(int argc, char **argv) { + if (!test_once() || + !test_thread_local()) { + return 1; + } + + printf("PASS\n"); + return 0; +} + +#else /* OPENSSL_NO_THREADS */ + +int main(int argc, char **argv) { + printf("PASS\n"); + return 0; +} + +#endif diff --git a/external/boringssl/crypto/thread_win.c b/external/boringssl/crypto/thread_win.c new file mode 100644 index 0000000000..c7a90f7e72 --- /dev/null +++ b/external/boringssl/crypto/thread_win.c @@ -0,0 +1,237 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include "internal.h" + +#if defined(OPENSSL_WINDOWS) && !defined(OPENSSL_NO_THREADS) + +OPENSSL_MSVC_PRAGMA(warning(push, 3)) +#include +OPENSSL_MSVC_PRAGMA(warning(pop)) + +#include +#include + +#include +#include + + +OPENSSL_COMPILE_ASSERT(sizeof(CRYPTO_MUTEX) >= sizeof(SRWLOCK), + CRYPTO_MUTEX_too_small); + +static BOOL CALLBACK call_once_init(INIT_ONCE *once, void *arg, void **out) { + void (**init)(void) = (void (**)(void))arg; + (**init)(); + return TRUE; +} + +void CRYPTO_once(CRYPTO_once_t *once, void (*init)(void)) { + if (!InitOnceExecuteOnce(once, call_once_init, &init, NULL)) { + abort(); + } +} + +void CRYPTO_MUTEX_init(CRYPTO_MUTEX *lock) { + InitializeSRWLock((SRWLOCK *) lock); +} + +void CRYPTO_MUTEX_lock_read(CRYPTO_MUTEX *lock) { + AcquireSRWLockShared((SRWLOCK *) lock); +} + +void CRYPTO_MUTEX_lock_write(CRYPTO_MUTEX *lock) { + AcquireSRWLockExclusive((SRWLOCK *) lock); +} + +void CRYPTO_MUTEX_unlock_read(CRYPTO_MUTEX *lock) { + ReleaseSRWLockShared((SRWLOCK *) lock); +} + +void CRYPTO_MUTEX_unlock_write(CRYPTO_MUTEX *lock) { + ReleaseSRWLockExclusive((SRWLOCK *) lock); +} + +void CRYPTO_MUTEX_cleanup(CRYPTO_MUTEX *lock) { + /* SRWLOCKs require no cleanup. */ +} + +void CRYPTO_STATIC_MUTEX_lock_read(struct CRYPTO_STATIC_MUTEX *lock) { + AcquireSRWLockShared(&lock->lock); +} + +void CRYPTO_STATIC_MUTEX_lock_write(struct CRYPTO_STATIC_MUTEX *lock) { + AcquireSRWLockExclusive(&lock->lock); +} + +void CRYPTO_STATIC_MUTEX_unlock_read(struct CRYPTO_STATIC_MUTEX *lock) { + ReleaseSRWLockShared(&lock->lock); +} + +void CRYPTO_STATIC_MUTEX_unlock_write(struct CRYPTO_STATIC_MUTEX *lock) { + ReleaseSRWLockExclusive(&lock->lock); +} + +static CRITICAL_SECTION g_destructors_lock; +static thread_local_destructor_t g_destructors[NUM_OPENSSL_THREAD_LOCALS]; + +static CRYPTO_once_t g_thread_local_init_once = CRYPTO_ONCE_INIT; +static DWORD g_thread_local_key; +static int g_thread_local_failed; + +static void thread_local_init(void) { + if (!InitializeCriticalSectionAndSpinCount(&g_destructors_lock, 0x400)) { + g_thread_local_failed = 1; + return; + } + g_thread_local_key = TlsAlloc(); + g_thread_local_failed = (g_thread_local_key == TLS_OUT_OF_INDEXES); +} + +static void NTAPI thread_local_destructor(PVOID module, DWORD reason, + PVOID reserved) { + /* Only free memory on |DLL_THREAD_DETACH|, not |DLL_PROCESS_DETACH|. In + * VS2015's debug runtime, the C runtime has been unloaded by the time + * |DLL_PROCESS_DETACH| runs. See https://crbug.com/575795. This is consistent + * with |pthread_key_create| which does not call destructors on process exit, + * only thread exit. */ + if (reason != DLL_THREAD_DETACH) { + return; + } + + CRYPTO_once(&g_thread_local_init_once, thread_local_init); + if (g_thread_local_failed) { + return; + } + + void **pointers = (void**) TlsGetValue(g_thread_local_key); + if (pointers == NULL) { + return; + } + + thread_local_destructor_t destructors[NUM_OPENSSL_THREAD_LOCALS]; + + EnterCriticalSection(&g_destructors_lock); + memcpy(destructors, g_destructors, sizeof(destructors)); + LeaveCriticalSection(&g_destructors_lock); + + unsigned i; + for (i = 0; i < NUM_OPENSSL_THREAD_LOCALS; i++) { + if (destructors[i] != NULL) { + destructors[i](pointers[i]); + } + } + + OPENSSL_free(pointers); +} + +/* Thread Termination Callbacks. + * + * Windows doesn't support a per-thread destructor with its TLS primitives. + * So, we build it manually by inserting a function to be called on each + * thread's exit. This magic is from http://www.codeproject.com/threads/tls.asp + * and it works for VC++ 7.0 and later. + * + * Force a reference to _tls_used to make the linker create the TLS directory + * if it's not already there. (E.g. if __declspec(thread) is not used). Force + * a reference to p_thread_callback_boringssl to prevent whole program + * optimization from discarding the variable. */ +#ifdef _WIN64 +#pragma comment(linker, "/INCLUDE:_tls_used") +#pragma comment(linker, "/INCLUDE:p_thread_callback_boringssl") +#else +#pragma comment(linker, "/INCLUDE:__tls_used") +#pragma comment(linker, "/INCLUDE:_p_thread_callback_boringssl") +#endif + +/* .CRT$XLA to .CRT$XLZ is an array of PIMAGE_TLS_CALLBACK pointers that are + * called automatically by the OS loader code (not the CRT) when the module is + * loaded and on thread creation. They are NOT called if the module has been + * loaded by a LoadLibrary() call. It must have implicitly been loaded at + * process startup. + * + * By implicitly loaded, I mean that it is directly referenced by the main EXE + * or by one of its dependent DLLs. Delay-loaded DLL doesn't count as being + * implicitly loaded. + * + * See VC\crt\src\tlssup.c for reference. */ + +/* The linker must not discard p_thread_callback_boringssl. (We force a reference + * to this variable with a linker /INCLUDE:symbol pragma to ensure that.) If + * this variable is discarded, the OnThreadExit function will never be + * called. */ +#ifdef _WIN64 + +/* .CRT section is merged with .rdata on x64 so it must be constant data. */ +#pragma const_seg(".CRT$XLC") +/* When defining a const variable, it must have external linkage to be sure the + * linker doesn't discard it. */ +extern const PIMAGE_TLS_CALLBACK p_thread_callback_boringssl; +const PIMAGE_TLS_CALLBACK p_thread_callback_boringssl = thread_local_destructor; +/* Reset the default section. */ +#pragma const_seg() + +#else + +#pragma data_seg(".CRT$XLC") +PIMAGE_TLS_CALLBACK p_thread_callback_boringssl = thread_local_destructor; +/* Reset the default section. */ +#pragma data_seg() + +#endif /* _WIN64 */ + +void *CRYPTO_get_thread_local(thread_local_data_t index) { + CRYPTO_once(&g_thread_local_init_once, thread_local_init); + if (g_thread_local_failed) { + return NULL; + } + + void **pointers = TlsGetValue(g_thread_local_key); + if (pointers == NULL) { + return NULL; + } + return pointers[index]; +} + +int CRYPTO_set_thread_local(thread_local_data_t index, void *value, + thread_local_destructor_t destructor) { + CRYPTO_once(&g_thread_local_init_once, thread_local_init); + if (g_thread_local_failed) { + destructor(value); + return 0; + } + + void **pointers = TlsGetValue(g_thread_local_key); + if (pointers == NULL) { + pointers = OPENSSL_malloc(sizeof(void *) * NUM_OPENSSL_THREAD_LOCALS); + if (pointers == NULL) { + destructor(value); + return 0; + } + memset(pointers, 0, sizeof(void *) * NUM_OPENSSL_THREAD_LOCALS); + if (TlsSetValue(g_thread_local_key, pointers) == 0) { + OPENSSL_free(pointers); + destructor(value); + return 0; + } + } + + EnterCriticalSection(&g_destructors_lock); + g_destructors[index] = destructor; + LeaveCriticalSection(&g_destructors_lock); + + pointers[index] = value; + return 1; +} + +#endif /* OPENSSL_WINDOWS && !OPENSSL_NO_THREADS */ diff --git a/external/boringssl/crypto/time_support.c b/external/boringssl/crypto/time_support.c new file mode 100644 index 0000000000..ae0f49635d --- /dev/null +++ b/external/boringssl/crypto/time_support.c @@ -0,0 +1,206 @@ +/* Written by Richard Levitte (richard@levitte.org) for the OpenSSL + * project 2001. + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 2008. + */ +/* ==================================================================== + * Copyright (c) 2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#if !defined(_POSIX_C_SOURCE) +#define _POSIX_C_SOURCE 201410L /* for gmtime_r */ +#endif + +#include + +#include + + +#define SECS_PER_DAY (24 * 60 * 60) + +struct tm *OPENSSL_gmtime(const time_t *time, struct tm *result) { +#if defined(OPENSSL_WINDOWS) + if (gmtime_s(result, time)) { + return NULL; + } + return result; +#else + return gmtime_r(time, result); +#endif +} + +/* Convert date to and from julian day Uses Fliegel & Van Flandern algorithm */ +static long date_to_julian(int y, int m, int d) { + return (1461 * (y + 4800 + (m - 14) / 12)) / 4 + + (367 * (m - 2 - 12 * ((m - 14) / 12))) / 12 - + (3 * ((y + 4900 + (m - 14) / 12) / 100)) / 4 + d - 32075; +} + +static void julian_to_date(long jd, int *y, int *m, int *d) { + long L = jd + 68569; + long n = (4 * L) / 146097; + long i, j; + + L = L - (146097 * n + 3) / 4; + i = (4000 * (L + 1)) / 1461001; + L = L - (1461 * i) / 4 + 31; + j = (80 * L) / 2447; + *d = L - (2447 * j) / 80; + L = j / 11; + *m = j + 2 - (12 * L); + *y = 100 * (n - 49) + i + L; +} + +/* Convert tm structure and offset into julian day and seconds */ +static int julian_adj(const struct tm *tm, int off_day, long offset_sec, + long *pday, int *psec) { + int offset_hms, offset_day; + long time_jd; + int time_year, time_month, time_day; + /* split offset into days and day seconds */ + offset_day = offset_sec / SECS_PER_DAY; + /* Avoid sign issues with % operator */ + offset_hms = offset_sec - (offset_day * SECS_PER_DAY); + offset_day += off_day; + /* Add current time seconds to offset */ + offset_hms += tm->tm_hour * 3600 + tm->tm_min * 60 + tm->tm_sec; + /* Adjust day seconds if overflow */ + if (offset_hms >= SECS_PER_DAY) { + offset_day++; + offset_hms -= SECS_PER_DAY; + } else if (offset_hms < 0) { + offset_day--; + offset_hms += SECS_PER_DAY; + } + + /* Convert date of time structure into a Julian day number. */ + + time_year = tm->tm_year + 1900; + time_month = tm->tm_mon + 1; + time_day = tm->tm_mday; + + time_jd = date_to_julian(time_year, time_month, time_day); + + /* Work out Julian day of new date */ + time_jd += offset_day; + + if (time_jd < 0) { + return 0; + } + + *pday = time_jd; + *psec = offset_hms; + return 1; +} + +int OPENSSL_gmtime_adj(struct tm *tm, int off_day, long offset_sec) { + int time_sec, time_year, time_month, time_day; + long time_jd; + + /* Convert time and offset into julian day and seconds */ + if (!julian_adj(tm, off_day, offset_sec, &time_jd, &time_sec)) { + return 0; + } + + /* Convert Julian day back to date */ + + julian_to_date(time_jd, &time_year, &time_month, &time_day); + + if (time_year < 1900 || time_year > 9999) { + return 0; + } + + /* Update tm structure */ + + tm->tm_year = time_year - 1900; + tm->tm_mon = time_month - 1; + tm->tm_mday = time_day; + + tm->tm_hour = time_sec / 3600; + tm->tm_min = (time_sec / 60) % 60; + tm->tm_sec = time_sec % 60; + + return 1; +} + +int OPENSSL_gmtime_diff(int *pday, int *psec, const struct tm *from, + const struct tm *to) { + int from_sec, to_sec, diff_sec; + long from_jd, to_jd, diff_day; + + if (!julian_adj(from, 0, 0, &from_jd, &from_sec)) { + return 0; + } + if (!julian_adj(to, 0, 0, &to_jd, &to_sec)) { + return 0; + } + + diff_day = to_jd - from_jd; + diff_sec = to_sec - from_sec; + /* Adjust differences so both positive or both negative */ + if (diff_day > 0 && diff_sec < 0) { + diff_day--; + diff_sec += SECS_PER_DAY; + } + if (diff_day < 0 && diff_sec > 0) { + diff_day++; + diff_sec -= SECS_PER_DAY; + } + + if (pday) { + *pday = (int)diff_day; + } + if (psec) { + *psec = diff_sec; + } + + return 1; +} diff --git a/external/boringssl/crypto/x509/CMakeLists.txt b/external/boringssl/crypto/x509/CMakeLists.txt new file mode 100644 index 0000000000..bc86786072 --- /dev/null +++ b/external/boringssl/crypto/x509/CMakeLists.txt @@ -0,0 +1,81 @@ +include_directories(../../include) + +add_library( + x509 + + OBJECT + + a_digest.c + a_sign.c + a_strex.c + a_verify.c + algorithm.c + asn1_gen.c + by_dir.c + by_file.c + i2d_pr.c + pkcs7.c + rsa_pss.c + t_crl.c + t_req.c + t_x509.c + t_x509a.c + x509.c + x509_att.c + x509_cmp.c + x509_d2.c + x509_def.c + x509_ext.c + x509_lu.c + x509_obj.c + x509_r2x.c + x509_req.c + x509_set.c + x509_trs.c + x509_txt.c + x509_v3.c + x509_vfy.c + x509_vpm.c + x509cset.c + x509name.c + x509rset.c + x509spki.c + x509type.c + x_algor.c + x_all.c + x_attrib.c + x_crl.c + x_exten.c + x_info.c + x_name.c + x_pkey.c + x_pubkey.c + x_req.c + x_sig.c + x_spki.c + x_val.c + x_x509.c + x_x509a.c +) + +if(ENABLE_TESTS) +add_executable( + pkcs7_test + + pkcs7_test.c + + $ +) + +add_executable( + x509_test + + x509_test.cc + + $ +) + +target_link_libraries(pkcs7_test crypto) +target_link_libraries(x509_test crypto) +add_dependencies(all_tests pkcs7_test x509_test) +endif() diff --git a/external/boringssl/crypto/x509/a_digest.c b/external/boringssl/crypto/x509/a_digest.c new file mode 100644 index 0000000000..b88d6ac79c --- /dev/null +++ b/external/boringssl/crypto/x509/a_digest.c @@ -0,0 +1,96 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include +#include +#include + +int ASN1_digest(i2d_of_void *i2d, const EVP_MD *type, char *data, + unsigned char *md, unsigned int *len) +{ + int i, ret; + unsigned char *str, *p; + + i = i2d(data, NULL); + if ((str = (unsigned char *)OPENSSL_malloc(i)) == NULL) { + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + return (0); + } + p = str; + i2d(data, &p); + + ret = EVP_Digest(str, i, md, len, type, NULL); + OPENSSL_free(str); + return ret; +} + +int ASN1_item_digest(const ASN1_ITEM *it, const EVP_MD *type, void *asn, + unsigned char *md, unsigned int *len) +{ + int i, ret; + unsigned char *str = NULL; + + i = ASN1_item_i2d(asn, &str, it); + if (!str) + return (0); + + ret = EVP_Digest(str, i, md, len, type, NULL); + OPENSSL_free(str); + return ret; +} diff --git a/external/boringssl/crypto/x509/a_sign.c b/external/boringssl/crypto/x509/a_sign.c new file mode 100644 index 0000000000..13a3ac25e8 --- /dev/null +++ b/external/boringssl/crypto/x509/a_sign.c @@ -0,0 +1,135 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include +#include +#include +#include +#include +#include +#include + +#include "internal.h" + +int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1, + X509_ALGOR *algor2, ASN1_BIT_STRING *signature, void *asn, + EVP_PKEY *pkey, const EVP_MD *type) +{ + EVP_MD_CTX ctx; + EVP_MD_CTX_init(&ctx); + if (!EVP_DigestSignInit(&ctx, NULL, type, NULL, pkey)) { + EVP_MD_CTX_cleanup(&ctx); + return 0; + } + return ASN1_item_sign_ctx(it, algor1, algor2, signature, asn, &ctx); +} + +int ASN1_item_sign_ctx(const ASN1_ITEM *it, + X509_ALGOR *algor1, X509_ALGOR *algor2, + ASN1_BIT_STRING *signature, void *asn, EVP_MD_CTX *ctx) +{ + EVP_PKEY *pkey; + unsigned char *buf_in = NULL, *buf_out = NULL; + size_t inl = 0, outl = 0, outll = 0; + + pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx); + + /* Write out the requested copies of the AlgorithmIdentifier. */ + if (algor1 && !x509_digest_sign_algorithm(ctx, algor1)) { + goto err; + } + if (algor2 && !x509_digest_sign_algorithm(ctx, algor2)) { + goto err; + } + + inl = ASN1_item_i2d(asn, &buf_in, it); + outll = outl = EVP_PKEY_size(pkey); + buf_out = OPENSSL_malloc((unsigned int)outl); + if ((buf_in == NULL) || (buf_out == NULL)) { + outl = 0; + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (!EVP_DigestSignUpdate(ctx, buf_in, inl) + || !EVP_DigestSignFinal(ctx, buf_out, &outl)) { + outl = 0; + OPENSSL_PUT_ERROR(X509, ERR_R_EVP_LIB); + goto err; + } + if (signature->data != NULL) + OPENSSL_free(signature->data); + signature->data = buf_out; + buf_out = NULL; + signature->length = outl; + /* + * In the interests of compatibility, I'll make sure that the bit string + * has a 'not-used bits' value of 0 + */ + signature->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); + signature->flags |= ASN1_STRING_FLAG_BITS_LEFT; + err: + EVP_MD_CTX_cleanup(ctx); + if (buf_in != NULL) { + OPENSSL_cleanse((char *)buf_in, (unsigned int)inl); + OPENSSL_free(buf_in); + } + if (buf_out != NULL) { + OPENSSL_cleanse((char *)buf_out, outll); + OPENSSL_free(buf_out); + } + return (outl); +} diff --git a/external/boringssl/crypto/x509/a_strex.c b/external/boringssl/crypto/x509/a_strex.c new file mode 100644 index 0000000000..aa2501a48f --- /dev/null +++ b/external/boringssl/crypto/x509/a_strex.c @@ -0,0 +1,633 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include +#include +#include + +#include "charmap.h" + +/* + * ASN1_STRING_print_ex() and X509_NAME_print_ex(). Enhanced string and name + * printing routines handling multibyte characters, RFC2253 and a host of + * other options. + */ + +#define CHARTYPE_BS_ESC (ASN1_STRFLGS_ESC_2253 | CHARTYPE_FIRST_ESC_2253 | CHARTYPE_LAST_ESC_2253) + +#define ESC_FLAGS (ASN1_STRFLGS_ESC_2253 | \ + ASN1_STRFLGS_ESC_QUOTE | \ + ASN1_STRFLGS_ESC_CTRL | \ + ASN1_STRFLGS_ESC_MSB) + +static int send_bio_chars(void *arg, const void *buf, int len) +{ + if (!arg) + return 1; + if (BIO_write(arg, buf, len) != len) + return 0; + return 1; +} + +static int send_fp_chars(void *arg, const void *buf, int len) +{ + if (!arg) + return 1; + if (fwrite(buf, 1, len, arg) != (unsigned int)len) + return 0; + return 1; +} + +typedef int char_io (void *arg, const void *buf, int len); + +/* + * This function handles display of strings, one character at a time. It is + * passed an unsigned long for each character because it could come from 2 or + * even 4 byte forms. + */ + +#define HEX_SIZE(type) (sizeof(type)*2) + +static int do_esc_char(unsigned long c, unsigned char flags, char *do_quotes, + char_io *io_ch, void *arg) +{ + unsigned char chflgs, chtmp; + char tmphex[HEX_SIZE(long) + 3]; + + if (c > 0xffffffffL) + return -1; + if (c > 0xffff) { + BIO_snprintf(tmphex, sizeof tmphex, "\\W%08lX", c); + if (!io_ch(arg, tmphex, 10)) + return -1; + return 10; + } + if (c > 0xff) { + BIO_snprintf(tmphex, sizeof tmphex, "\\U%04lX", c); + if (!io_ch(arg, tmphex, 6)) + return -1; + return 6; + } + chtmp = (unsigned char)c; + if (chtmp > 0x7f) + chflgs = flags & ASN1_STRFLGS_ESC_MSB; + else + chflgs = char_type[chtmp] & flags; + if (chflgs & CHARTYPE_BS_ESC) { + /* If we don't escape with quotes, signal we need quotes */ + if (chflgs & ASN1_STRFLGS_ESC_QUOTE) { + if (do_quotes) + *do_quotes = 1; + if (!io_ch(arg, &chtmp, 1)) + return -1; + return 1; + } + if (!io_ch(arg, "\\", 1)) + return -1; + if (!io_ch(arg, &chtmp, 1)) + return -1; + return 2; + } + if (chflgs & (ASN1_STRFLGS_ESC_CTRL | ASN1_STRFLGS_ESC_MSB)) { + BIO_snprintf(tmphex, 11, "\\%02X", chtmp); + if (!io_ch(arg, tmphex, 3)) + return -1; + return 3; + } + /* + * If we get this far and do any escaping at all must escape the escape + * character itself: backslash. + */ + if (chtmp == '\\' && flags & ESC_FLAGS) { + if (!io_ch(arg, "\\\\", 2)) + return -1; + return 2; + } + if (!io_ch(arg, &chtmp, 1)) + return -1; + return 1; +} + +#define BUF_TYPE_WIDTH_MASK 0x7 +#define BUF_TYPE_CONVUTF8 0x8 + +/* + * This function sends each character in a buffer to do_esc_char(). It + * interprets the content formats and converts to or from UTF8 as + * appropriate. + */ + +static int do_buf(unsigned char *buf, int buflen, + int type, unsigned char flags, char *quotes, char_io *io_ch, + void *arg) +{ + int i, outlen, len; + unsigned char orflags, *p, *q; + unsigned long c; + p = buf; + q = buf + buflen; + outlen = 0; + while (p != q) { + if (p == buf && flags & ASN1_STRFLGS_ESC_2253) + orflags = CHARTYPE_FIRST_ESC_2253; + else + orflags = 0; + switch (type & BUF_TYPE_WIDTH_MASK) { + case 4: + c = ((unsigned long)*p++) << 24; + c |= ((unsigned long)*p++) << 16; + c |= ((unsigned long)*p++) << 8; + c |= *p++; + break; + + case 2: + c = ((unsigned long)*p++) << 8; + c |= *p++; + break; + + case 1: + c = *p++; + break; + + case 0: + i = UTF8_getc(p, buflen, &c); + if (i < 0) + return -1; /* Invalid UTF8String */ + p += i; + break; + default: + return -1; /* invalid width */ + } + if (p == q && flags & ASN1_STRFLGS_ESC_2253) + orflags = CHARTYPE_LAST_ESC_2253; + if (type & BUF_TYPE_CONVUTF8) { + unsigned char utfbuf[6]; + int utflen; + utflen = UTF8_putc(utfbuf, sizeof utfbuf, c); + for (i = 0; i < utflen; i++) { + /* + * We don't need to worry about setting orflags correctly + * because if utflen==1 its value will be correct anyway + * otherwise each character will be > 0x7f and so the + * character will never be escaped on first and last. + */ + len = + do_esc_char(utfbuf[i], (unsigned char)(flags | orflags), + quotes, io_ch, arg); + if (len < 0) + return -1; + outlen += len; + } + } else { + len = + do_esc_char(c, (unsigned char)(flags | orflags), quotes, + io_ch, arg); + if (len < 0) + return -1; + outlen += len; + } + } + return outlen; +} + +/* This function hex dumps a buffer of characters */ + +static int do_hex_dump(char_io *io_ch, void *arg, unsigned char *buf, + int buflen) +{ + static const char hexdig[] = "0123456789ABCDEF"; + unsigned char *p, *q; + char hextmp[2]; + if (arg) { + p = buf; + q = buf + buflen; + while (p != q) { + hextmp[0] = hexdig[*p >> 4]; + hextmp[1] = hexdig[*p & 0xf]; + if (!io_ch(arg, hextmp, 2)) + return -1; + p++; + } + } + return buflen << 1; +} + +/* + * "dump" a string. This is done when the type is unknown, or the flags + * request it. We can either dump the content octets or the entire DER + * encoding. This uses the RFC2253 #01234 format. + */ + +static int do_dump(unsigned long lflags, char_io *io_ch, void *arg, + ASN1_STRING *str) +{ + /* + * Placing the ASN1_STRING in a temp ASN1_TYPE allows the DER encoding to + * readily obtained + */ + ASN1_TYPE t; + unsigned char *der_buf, *p; + int outlen, der_len; + + if (!io_ch(arg, "#", 1)) + return -1; + /* If we don't dump DER encoding just dump content octets */ + if (!(lflags & ASN1_STRFLGS_DUMP_DER)) { + outlen = do_hex_dump(io_ch, arg, str->data, str->length); + if (outlen < 0) + return -1; + return outlen + 1; + } + t.type = str->type; + t.value.ptr = (char *)str; + der_len = i2d_ASN1_TYPE(&t, NULL); + der_buf = OPENSSL_malloc(der_len); + if (!der_buf) + return -1; + p = der_buf; + i2d_ASN1_TYPE(&t, &p); + outlen = do_hex_dump(io_ch, arg, der_buf, der_len); + OPENSSL_free(der_buf); + if (outlen < 0) + return -1; + return outlen + 1; +} + +/* + * Lookup table to convert tags to character widths, 0 = UTF8 encoded, -1 is + * used for non string types otherwise it is the number of bytes per + * character + */ + +static const signed char tag2nbyte[] = { + -1, -1, -1, -1, -1, /* 0-4 */ + -1, -1, -1, -1, -1, /* 5-9 */ + -1, -1, 0, -1, /* 10-13 */ + -1, -1, -1, -1, /* 15-17 */ + -1, 1, 1, /* 18-20 */ + -1, 1, 1, 1, /* 21-24 */ + -1, 1, -1, /* 25-27 */ + 4, -1, 2 /* 28-30 */ +}; + +/* + * This is the main function, print out an ASN1_STRING taking note of various + * escape and display options. Returns number of characters written or -1 if + * an error occurred. + */ + +static int do_print_ex(char_io *io_ch, void *arg, unsigned long lflags, + ASN1_STRING *str) +{ + int outlen, len; + int type; + char quotes; + unsigned char flags; + quotes = 0; + /* Keep a copy of escape flags */ + flags = (unsigned char)(lflags & ESC_FLAGS); + + type = str->type; + + outlen = 0; + + if (lflags & ASN1_STRFLGS_SHOW_TYPE) { + const char *tagname; + tagname = ASN1_tag2str(type); + outlen += strlen(tagname); + if (!io_ch(arg, tagname, outlen) || !io_ch(arg, ":", 1)) + return -1; + outlen++; + } + + /* Decide what to do with type, either dump content or display it */ + + /* Dump everything */ + if (lflags & ASN1_STRFLGS_DUMP_ALL) + type = -1; + /* Ignore the string type */ + else if (lflags & ASN1_STRFLGS_IGNORE_TYPE) + type = 1; + else { + /* Else determine width based on type */ + if ((type > 0) && (type < 31)) + type = tag2nbyte[type]; + else + type = -1; + if ((type == -1) && !(lflags & ASN1_STRFLGS_DUMP_UNKNOWN)) + type = 1; + } + + if (type == -1) { + len = do_dump(lflags, io_ch, arg, str); + if (len < 0) + return -1; + outlen += len; + return outlen; + } + + if (lflags & ASN1_STRFLGS_UTF8_CONVERT) { + /* + * Note: if string is UTF8 and we want to convert to UTF8 then we + * just interpret it as 1 byte per character to avoid converting + * twice. + */ + if (!type) + type = 1; + else + type |= BUF_TYPE_CONVUTF8; + } + + len = do_buf(str->data, str->length, type, flags, "es, io_ch, NULL); + if (len < 0) + return -1; + outlen += len; + if (quotes) + outlen += 2; + if (!arg) + return outlen; + if (quotes && !io_ch(arg, "\"", 1)) + return -1; + if (do_buf(str->data, str->length, type, flags, NULL, io_ch, arg) < 0) + return -1; + if (quotes && !io_ch(arg, "\"", 1)) + return -1; + return outlen; +} + +/* Used for line indenting: print 'indent' spaces */ + +static int do_indent(char_io *io_ch, void *arg, int indent) +{ + int i; + for (i = 0; i < indent; i++) + if (!io_ch(arg, " ", 1)) + return 0; + return 1; +} + +#define FN_WIDTH_LN 25 +#define FN_WIDTH_SN 10 + +static int do_name_ex(char_io *io_ch, void *arg, X509_NAME *n, + int indent, unsigned long flags) +{ + int i, prev = -1, orflags, cnt; + int fn_opt, fn_nid; + ASN1_OBJECT *fn; + ASN1_STRING *val; + X509_NAME_ENTRY *ent; + char objtmp[80]; + const char *objbuf; + int outlen, len; + const char *sep_dn, *sep_mv, *sep_eq; + int sep_dn_len, sep_mv_len, sep_eq_len; + if (indent < 0) + indent = 0; + outlen = indent; + if (!do_indent(io_ch, arg, indent)) + return -1; + switch (flags & XN_FLAG_SEP_MASK) { + case XN_FLAG_SEP_MULTILINE: + sep_dn = "\n"; + sep_dn_len = 1; + sep_mv = " + "; + sep_mv_len = 3; + break; + + case XN_FLAG_SEP_COMMA_PLUS: + sep_dn = ","; + sep_dn_len = 1; + sep_mv = "+"; + sep_mv_len = 1; + indent = 0; + break; + + case XN_FLAG_SEP_CPLUS_SPC: + sep_dn = ", "; + sep_dn_len = 2; + sep_mv = " + "; + sep_mv_len = 3; + indent = 0; + break; + + case XN_FLAG_SEP_SPLUS_SPC: + sep_dn = "; "; + sep_dn_len = 2; + sep_mv = " + "; + sep_mv_len = 3; + indent = 0; + break; + + default: + return -1; + } + + if (flags & XN_FLAG_SPC_EQ) { + sep_eq = " = "; + sep_eq_len = 3; + } else { + sep_eq = "="; + sep_eq_len = 1; + } + + fn_opt = flags & XN_FLAG_FN_MASK; + + cnt = X509_NAME_entry_count(n); + for (i = 0; i < cnt; i++) { + if (flags & XN_FLAG_DN_REV) + ent = X509_NAME_get_entry(n, cnt - i - 1); + else + ent = X509_NAME_get_entry(n, i); + if (prev != -1) { + if (prev == ent->set) { + if (!io_ch(arg, sep_mv, sep_mv_len)) + return -1; + outlen += sep_mv_len; + } else { + if (!io_ch(arg, sep_dn, sep_dn_len)) + return -1; + outlen += sep_dn_len; + if (!do_indent(io_ch, arg, indent)) + return -1; + outlen += indent; + } + } + prev = ent->set; + fn = X509_NAME_ENTRY_get_object(ent); + val = X509_NAME_ENTRY_get_data(ent); + fn_nid = OBJ_obj2nid(fn); + if (fn_opt != XN_FLAG_FN_NONE) { + int objlen, fld_len; + if ((fn_opt == XN_FLAG_FN_OID) || (fn_nid == NID_undef)) { + OBJ_obj2txt(objtmp, sizeof objtmp, fn, 1); + fld_len = 0; /* XXX: what should this be? */ + objbuf = objtmp; + } else { + if (fn_opt == XN_FLAG_FN_SN) { + fld_len = FN_WIDTH_SN; + objbuf = OBJ_nid2sn(fn_nid); + } else if (fn_opt == XN_FLAG_FN_LN) { + fld_len = FN_WIDTH_LN; + objbuf = OBJ_nid2ln(fn_nid); + } else { + fld_len = 0; /* XXX: what should this be? */ + objbuf = ""; + } + } + objlen = strlen(objbuf); + if (!io_ch(arg, objbuf, objlen)) + return -1; + if ((objlen < fld_len) && (flags & XN_FLAG_FN_ALIGN)) { + if (!do_indent(io_ch, arg, fld_len - objlen)) + return -1; + outlen += fld_len - objlen; + } + if (!io_ch(arg, sep_eq, sep_eq_len)) + return -1; + outlen += objlen + sep_eq_len; + } + /* + * If the field name is unknown then fix up the DER dump flag. We + * might want to limit this further so it will DER dump on anything + * other than a few 'standard' fields. + */ + if ((fn_nid == NID_undef) && (flags & XN_FLAG_DUMP_UNKNOWN_FIELDS)) + orflags = ASN1_STRFLGS_DUMP_ALL; + else + orflags = 0; + + len = do_print_ex(io_ch, arg, flags | orflags, val); + if (len < 0) + return -1; + outlen += len; + } + return outlen; +} + +/* Wrappers round the main functions */ + +int X509_NAME_print_ex(BIO *out, X509_NAME *nm, int indent, + unsigned long flags) +{ + if (flags == XN_FLAG_COMPAT) + return X509_NAME_print(out, nm, indent); + return do_name_ex(send_bio_chars, out, nm, indent, flags); +} + +#ifndef OPENSSL_NO_FP_API +int X509_NAME_print_ex_fp(FILE *fp, X509_NAME *nm, int indent, + unsigned long flags) +{ + if (flags == XN_FLAG_COMPAT) { + BIO *btmp; + int ret; + btmp = BIO_new_fp(fp, BIO_NOCLOSE); + if (!btmp) + return -1; + ret = X509_NAME_print(btmp, nm, indent); + BIO_free(btmp); + return ret; + } + return do_name_ex(send_fp_chars, fp, nm, indent, flags); +} +#endif + +int ASN1_STRING_print_ex(BIO *out, ASN1_STRING *str, unsigned long flags) +{ + return do_print_ex(send_bio_chars, out, flags, str); +} + +#ifndef OPENSSL_NO_FP_API +int ASN1_STRING_print_ex_fp(FILE *fp, ASN1_STRING *str, unsigned long flags) +{ + return do_print_ex(send_fp_chars, fp, flags, str); +} +#endif + +/* + * Utility function: convert any string type to UTF8, returns number of bytes + * in output string or a negative error code + */ + +int ASN1_STRING_to_UTF8(unsigned char **out, ASN1_STRING *in) +{ + ASN1_STRING stmp, *str = &stmp; + int mbflag, type, ret; + if (!in) + return -1; + type = in->type; + if ((type < 0) || (type > 30)) + return -1; + mbflag = tag2nbyte[type]; + if (mbflag == -1) + return -1; + mbflag |= MBSTRING_FLAG; + stmp.data = NULL; + stmp.length = 0; + stmp.flags = 0; + ret = + ASN1_mbstring_copy(&str, in->data, in->length, mbflag, + B_ASN1_UTF8STRING); + if (ret < 0) + return ret; + *out = stmp.data; + return stmp.length; +} diff --git a/external/boringssl/crypto/x509/a_verify.c b/external/boringssl/crypto/x509/a_verify.c new file mode 100644 index 0000000000..5a9adb651f --- /dev/null +++ b/external/boringssl/crypto/x509/a_verify.c @@ -0,0 +1,127 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "internal.h" + +int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a, + ASN1_BIT_STRING *signature, void *asn, EVP_PKEY *pkey) +{ + EVP_MD_CTX ctx; + uint8_t *buf_in = NULL; + int ret = 0, inl; + + if (!pkey) { + OPENSSL_PUT_ERROR(X509, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (signature->type == V_ASN1_BIT_STRING && signature->flags & 0x7) { + OPENSSL_PUT_ERROR(X509, X509_R_INVALID_BIT_STRING_BITS_LEFT); + return 0; + } + + EVP_MD_CTX_init(&ctx); + + if (!x509_digest_verify_init(&ctx, a, pkey)) { + goto err; + } + + inl = ASN1_item_i2d(asn, &buf_in, it); + + if (buf_in == NULL) { + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (!EVP_DigestVerifyUpdate(&ctx, buf_in, inl)) { + OPENSSL_cleanse(buf_in, (unsigned int)inl); + OPENSSL_free(buf_in); + OPENSSL_PUT_ERROR(X509, ERR_R_EVP_LIB); + goto err; + } + + OPENSSL_cleanse(buf_in, (unsigned int)inl); + OPENSSL_free(buf_in); + + if (EVP_DigestVerifyFinal(&ctx, signature->data, + (size_t)signature->length) <= 0) { + OPENSSL_PUT_ERROR(X509, ERR_R_EVP_LIB); + goto err; + } + /* + * we don't need to zero the 'ctx' because we just checked public + * information + */ + /* memset(&ctx,0,sizeof(ctx)); */ + ret = 1; + err: + EVP_MD_CTX_cleanup(&ctx); + return ret; +} diff --git a/external/boringssl/crypto/x509/algorithm.c b/external/boringssl/crypto/x509/algorithm.c new file mode 100644 index 0000000000..78ae882b80 --- /dev/null +++ b/external/boringssl/crypto/x509/algorithm.c @@ -0,0 +1,137 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include +#include +#include +#include + +#include "internal.h" + + +int x509_digest_sign_algorithm(EVP_MD_CTX *ctx, X509_ALGOR *algor) { + const EVP_MD *digest = EVP_MD_CTX_md(ctx); + EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx); + if (digest == NULL || pkey == NULL) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_CONTEXT_NOT_INITIALISED); + return 0; + } + + if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA) { + int pad_mode; + if (!EVP_PKEY_CTX_get_rsa_padding(ctx->pctx, &pad_mode)) { + return 0; + } + /* RSA-PSS has special signature algorithm logic. */ + if (pad_mode == RSA_PKCS1_PSS_PADDING) { + return x509_rsa_ctx_to_pss(ctx, algor); + } + } + + /* Default behavior: look up the OID for the algorithm/hash pair and encode + * that. */ + int sign_nid; + if (!OBJ_find_sigid_by_algs(&sign_nid, EVP_MD_type(digest), + EVP_PKEY_id(pkey))) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED); + return 0; + } + + /* RSA signature algorithms include an explicit NULL parameter. Others omit + * it. */ + int paramtype = + (EVP_PKEY_id(pkey) == EVP_PKEY_RSA) ? V_ASN1_NULL : V_ASN1_UNDEF; + X509_ALGOR_set0(algor, OBJ_nid2obj(sign_nid), paramtype, NULL); + return 1; +} + +int x509_digest_verify_init(EVP_MD_CTX *ctx, X509_ALGOR *sigalg, + EVP_PKEY *pkey) { + /* Convert the signature OID into digest and public key OIDs. */ + int sigalg_nid = OBJ_obj2nid(sigalg->algorithm); + int digest_nid, pkey_nid; + if (!OBJ_find_sigid_algs(sigalg_nid, &digest_nid, &pkey_nid)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM); + return 0; + } + + /* Check the public key OID matches the public key type. */ + if (pkey_nid != EVP_PKEY_id(pkey)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_WRONG_PUBLIC_KEY_TYPE); + return 0; + } + + /* NID_undef signals that there are custom parameters to set. */ + if (digest_nid == NID_undef) { + if (sigalg_nid != NID_rsassaPss) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM); + return 0; + } + return x509_rsa_pss_to_ctx(ctx, sigalg, pkey); + } + + /* Otherwise, initialize with the digest from the OID. */ + const EVP_MD *digest = EVP_get_digestbynid(digest_nid); + if (digest == NULL) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM); + return 0; + } + + return EVP_DigestVerifyInit(ctx, NULL, digest, NULL, pkey); +} diff --git a/external/boringssl/crypto/x509/asn1_gen.c b/external/boringssl/crypto/x509/asn1_gen.c new file mode 100644 index 0000000000..03a0ab9feb --- /dev/null +++ b/external/boringssl/crypto/x509/asn1_gen.c @@ -0,0 +1,818 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include +#include +#include +#include +#include + +#include "../internal.h" + +/* + * Although this file is in crypto/x509 for layering purposes, it emits + * errors from the ASN.1 module for OpenSSL compatibility. + */ + +#define ASN1_GEN_FLAG 0x10000 +#define ASN1_GEN_FLAG_IMP (ASN1_GEN_FLAG|1) +#define ASN1_GEN_FLAG_EXP (ASN1_GEN_FLAG|2) +#define ASN1_GEN_FLAG_TAG (ASN1_GEN_FLAG|3) +#define ASN1_GEN_FLAG_BITWRAP (ASN1_GEN_FLAG|4) +#define ASN1_GEN_FLAG_OCTWRAP (ASN1_GEN_FLAG|5) +#define ASN1_GEN_FLAG_SEQWRAP (ASN1_GEN_FLAG|6) +#define ASN1_GEN_FLAG_SETWRAP (ASN1_GEN_FLAG|7) +#define ASN1_GEN_FLAG_FORMAT (ASN1_GEN_FLAG|8) + +#define ASN1_GEN_STR(str,val) {str, sizeof(str) - 1, val} + +#define ASN1_FLAG_EXP_MAX 20 + +/* Input formats */ + +/* ASCII: default */ +#define ASN1_GEN_FORMAT_ASCII 1 +/* UTF8 */ +#define ASN1_GEN_FORMAT_UTF8 2 +/* Hex */ +#define ASN1_GEN_FORMAT_HEX 3 +/* List of bits */ +#define ASN1_GEN_FORMAT_BITLIST 4 + +struct tag_name_st { + const char *strnam; + int len; + int tag; +}; + +typedef struct { + int exp_tag; + int exp_class; + int exp_constructed; + int exp_pad; + long exp_len; +} tag_exp_type; + +typedef struct { + int imp_tag; + int imp_class; + int utype; + int format; + const char *str; + tag_exp_type exp_list[ASN1_FLAG_EXP_MAX]; + int exp_count; +} tag_exp_arg; + +static int bitstr_cb(const char *elem, int len, void *bitstr); +static int asn1_cb(const char *elem, int len, void *bitstr); +static int append_exp(tag_exp_arg *arg, int exp_tag, int exp_class, + int exp_constructed, int exp_pad, int imp_ok); +static int parse_tagging(const char *vstart, int vlen, int *ptag, + int *pclass); +static ASN1_TYPE *asn1_multi(int utype, const char *section, X509V3_CTX *cnf); +static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype); +static int asn1_str2tag(const char *tagstr, int len); + +ASN1_TYPE *ASN1_generate_nconf(char *str, CONF *nconf) +{ + X509V3_CTX cnf; + + if (!nconf) + return ASN1_generate_v3(str, NULL); + + X509V3_set_nconf(&cnf, nconf); + return ASN1_generate_v3(str, &cnf); +} + +ASN1_TYPE *ASN1_generate_v3(char *str, X509V3_CTX *cnf) +{ + ASN1_TYPE *ret; + tag_exp_arg asn1_tags; + tag_exp_type *etmp; + + int i, len; + + unsigned char *orig_der = NULL, *new_der = NULL; + const unsigned char *cpy_start; + unsigned char *p; + const unsigned char *cp; + int cpy_len; + long hdr_len = 0; + int hdr_constructed = 0, hdr_tag, hdr_class; + int r; + + asn1_tags.imp_tag = -1; + asn1_tags.imp_class = -1; + asn1_tags.format = ASN1_GEN_FORMAT_ASCII; + asn1_tags.exp_count = 0; + if (CONF_parse_list(str, ',', 1, asn1_cb, &asn1_tags) != 0) + return NULL; + + if ((asn1_tags.utype == V_ASN1_SEQUENCE) + || (asn1_tags.utype == V_ASN1_SET)) { + if (!cnf) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG); + return NULL; + } + ret = asn1_multi(asn1_tags.utype, asn1_tags.str, cnf); + } else + ret = asn1_str2type(asn1_tags.str, asn1_tags.format, asn1_tags.utype); + + if (!ret) + return NULL; + + /* If no tagging return base type */ + if ((asn1_tags.imp_tag == -1) && (asn1_tags.exp_count == 0)) + return ret; + + /* Generate the encoding */ + cpy_len = i2d_ASN1_TYPE(ret, &orig_der); + ASN1_TYPE_free(ret); + ret = NULL; + /* Set point to start copying for modified encoding */ + cpy_start = orig_der; + + /* Do we need IMPLICIT tagging? */ + if (asn1_tags.imp_tag != -1) { + /* If IMPLICIT we will replace the underlying tag */ + /* Skip existing tag+len */ + r = ASN1_get_object(&cpy_start, &hdr_len, &hdr_tag, &hdr_class, + cpy_len); + if (r & 0x80) + goto err; + /* Update copy length */ + cpy_len -= cpy_start - orig_der; + /* + * For IMPLICIT tagging the length should match the original length + * and constructed flag should be consistent. + */ + if (r & 0x1) { + /* Indefinite length constructed */ + hdr_constructed = 2; + hdr_len = 0; + } else + /* Just retain constructed flag */ + hdr_constructed = r & V_ASN1_CONSTRUCTED; + /* + * Work out new length with IMPLICIT tag: ignore constructed because + * it will mess up if indefinite length + */ + len = ASN1_object_size(0, hdr_len, asn1_tags.imp_tag); + } else + len = cpy_len; + + /* Work out length in any EXPLICIT, starting from end */ + + for (i = 0, etmp = asn1_tags.exp_list + asn1_tags.exp_count - 1; + i < asn1_tags.exp_count; i++, etmp--) { + /* Content length: number of content octets + any padding */ + len += etmp->exp_pad; + etmp->exp_len = len; + /* Total object length: length including new header */ + len = ASN1_object_size(0, len, etmp->exp_tag); + } + + /* Allocate buffer for new encoding */ + + new_der = OPENSSL_malloc(len); + if (!new_der) + goto err; + + /* Generate tagged encoding */ + + p = new_der; + + /* Output explicit tags first */ + + for (i = 0, etmp = asn1_tags.exp_list; i < asn1_tags.exp_count; + i++, etmp++) { + ASN1_put_object(&p, etmp->exp_constructed, etmp->exp_len, + etmp->exp_tag, etmp->exp_class); + if (etmp->exp_pad) + *p++ = 0; + } + + /* If IMPLICIT, output tag */ + + if (asn1_tags.imp_tag != -1) { + if (asn1_tags.imp_class == V_ASN1_UNIVERSAL + && (asn1_tags.imp_tag == V_ASN1_SEQUENCE + || asn1_tags.imp_tag == V_ASN1_SET)) + hdr_constructed = V_ASN1_CONSTRUCTED; + ASN1_put_object(&p, hdr_constructed, hdr_len, + asn1_tags.imp_tag, asn1_tags.imp_class); + } + + /* Copy across original encoding */ + memcpy(p, cpy_start, cpy_len); + + cp = new_der; + + /* Obtain new ASN1_TYPE structure */ + ret = d2i_ASN1_TYPE(NULL, &cp, len); + + err: + if (orig_der) + OPENSSL_free(orig_der); + if (new_der) + OPENSSL_free(new_der); + + return ret; + +} + +static int asn1_cb(const char *elem, int len, void *bitstr) +{ + tag_exp_arg *arg = bitstr; + int i; + int utype; + int vlen = 0; + const char *p, *vstart = NULL; + + int tmp_tag, tmp_class; + + if (elem == NULL) + return 0; + + for (i = 0, p = elem; i < len; p++, i++) { + /* Look for the ':' in name value pairs */ + if (*p == ':') { + vstart = p + 1; + vlen = len - (vstart - elem); + len = p - elem; + break; + } + } + + utype = asn1_str2tag(elem, len); + + if (utype == -1) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_TAG); + ERR_add_error_data(2, "tag=", elem); + return -1; + } + + /* If this is not a modifier mark end of string and exit */ + if (!(utype & ASN1_GEN_FLAG)) { + arg->utype = utype; + arg->str = vstart; + /* If no value and not end of string, error */ + if (!vstart && elem[len]) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_VALUE); + return -1; + } + return 0; + } + + switch (utype) { + + case ASN1_GEN_FLAG_IMP: + /* Check for illegal multiple IMPLICIT tagging */ + if (arg->imp_tag != -1) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_NESTED_TAGGING); + return -1; + } + if (!parse_tagging(vstart, vlen, &arg->imp_tag, &arg->imp_class)) + return -1; + break; + + case ASN1_GEN_FLAG_EXP: + + if (!parse_tagging(vstart, vlen, &tmp_tag, &tmp_class)) + return -1; + if (!append_exp(arg, tmp_tag, tmp_class, 1, 0, 0)) + return -1; + break; + + case ASN1_GEN_FLAG_SEQWRAP: + if (!append_exp(arg, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL, 1, 0, 1)) + return -1; + break; + + case ASN1_GEN_FLAG_SETWRAP: + if (!append_exp(arg, V_ASN1_SET, V_ASN1_UNIVERSAL, 1, 0, 1)) + return -1; + break; + + case ASN1_GEN_FLAG_BITWRAP: + if (!append_exp(arg, V_ASN1_BIT_STRING, V_ASN1_UNIVERSAL, 0, 1, 1)) + return -1; + break; + + case ASN1_GEN_FLAG_OCTWRAP: + if (!append_exp(arg, V_ASN1_OCTET_STRING, V_ASN1_UNIVERSAL, 0, 0, 1)) + return -1; + break; + + case ASN1_GEN_FLAG_FORMAT: + if (!vstart) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_FORMAT); + return -1; + } + if (!strncmp(vstart, "ASCII", 5)) + arg->format = ASN1_GEN_FORMAT_ASCII; + else if (!strncmp(vstart, "UTF8", 4)) + arg->format = ASN1_GEN_FORMAT_UTF8; + else if (!strncmp(vstart, "HEX", 3)) + arg->format = ASN1_GEN_FORMAT_HEX; + else if (!strncmp(vstart, "BITLIST", 7)) + arg->format = ASN1_GEN_FORMAT_BITLIST; + else { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_FORMAT); + return -1; + } + break; + + } + + return 1; + +} + +static int parse_tagging(const char *vstart, int vlen, int *ptag, int *pclass) +{ + char erch[2]; + long tag_num; + char *eptr; + if (!vstart) + return 0; + tag_num = strtoul(vstart, &eptr, 10); + /* Check we haven't gone past max length: should be impossible */ + if (eptr && *eptr && (eptr > vstart + vlen)) + return 0; + if (tag_num < 0) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_NUMBER); + return 0; + } + *ptag = tag_num; + /* If we have non numeric characters, parse them */ + if (eptr) + vlen -= eptr - vstart; + else + vlen = 0; + if (vlen) { + switch (*eptr) { + + case 'U': + *pclass = V_ASN1_UNIVERSAL; + break; + + case 'A': + *pclass = V_ASN1_APPLICATION; + break; + + case 'P': + *pclass = V_ASN1_PRIVATE; + break; + + case 'C': + *pclass = V_ASN1_CONTEXT_SPECIFIC; + break; + + default: + erch[0] = *eptr; + erch[1] = 0; + OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_MODIFIER); + ERR_add_error_data(2, "Char=", erch); + return 0; + break; + + } + } else + *pclass = V_ASN1_CONTEXT_SPECIFIC; + + return 1; + +} + +/* Handle multiple types: SET and SEQUENCE */ + +static ASN1_TYPE *asn1_multi(int utype, const char *section, X509V3_CTX *cnf) +{ + ASN1_TYPE *ret = NULL; + STACK_OF(ASN1_TYPE) *sk = NULL; + STACK_OF(CONF_VALUE) *sect = NULL; + unsigned char *der = NULL; + int derlen; + size_t i; + sk = sk_ASN1_TYPE_new_null(); + if (!sk) + goto bad; + if (section) { + if (!cnf) + goto bad; + sect = X509V3_get_section(cnf, (char *)section); + if (!sect) + goto bad; + for (i = 0; i < sk_CONF_VALUE_num(sect); i++) { + ASN1_TYPE *typ = + ASN1_generate_v3(sk_CONF_VALUE_value(sect, i)->value, cnf); + if (!typ) + goto bad; + if (!sk_ASN1_TYPE_push(sk, typ)) + goto bad; + } + } + + /* + * Now we has a STACK of the components, convert to the correct form + */ + + if (utype == V_ASN1_SET) + derlen = i2d_ASN1_SET_ANY(sk, &der); + else + derlen = i2d_ASN1_SEQUENCE_ANY(sk, &der); + + if (derlen < 0) + goto bad; + + if (!(ret = ASN1_TYPE_new())) + goto bad; + + if (!(ret->value.asn1_string = ASN1_STRING_type_new(utype))) + goto bad; + + ret->type = utype; + + ret->value.asn1_string->data = der; + ret->value.asn1_string->length = derlen; + + der = NULL; + + bad: + + if (der) + OPENSSL_free(der); + + if (sk) + sk_ASN1_TYPE_pop_free(sk, ASN1_TYPE_free); + if (sect) + X509V3_section_free(cnf, sect); + + return ret; +} + +static int append_exp(tag_exp_arg *arg, int exp_tag, int exp_class, + int exp_constructed, int exp_pad, int imp_ok) +{ + tag_exp_type *exp_tmp; + /* Can only have IMPLICIT if permitted */ + if ((arg->imp_tag != -1) && !imp_ok) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_IMPLICIT_TAG); + return 0; + } + + if (arg->exp_count == ASN1_FLAG_EXP_MAX) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_DEPTH_EXCEEDED); + return 0; + } + + exp_tmp = &arg->exp_list[arg->exp_count++]; + + /* + * If IMPLICIT set tag to implicit value then reset implicit tag since it + * has been used. + */ + if (arg->imp_tag != -1) { + exp_tmp->exp_tag = arg->imp_tag; + exp_tmp->exp_class = arg->imp_class; + arg->imp_tag = -1; + arg->imp_class = -1; + } else { + exp_tmp->exp_tag = exp_tag; + exp_tmp->exp_class = exp_class; + } + exp_tmp->exp_constructed = exp_constructed; + exp_tmp->exp_pad = exp_pad; + + return 1; +} + +static int asn1_str2tag(const char *tagstr, int len) +{ + unsigned int i; + static const struct tag_name_st *tntmp, tnst[] = { + ASN1_GEN_STR("BOOL", V_ASN1_BOOLEAN), + ASN1_GEN_STR("BOOLEAN", V_ASN1_BOOLEAN), + ASN1_GEN_STR("NULL", V_ASN1_NULL), + ASN1_GEN_STR("INT", V_ASN1_INTEGER), + ASN1_GEN_STR("INTEGER", V_ASN1_INTEGER), + ASN1_GEN_STR("ENUM", V_ASN1_ENUMERATED), + ASN1_GEN_STR("ENUMERATED", V_ASN1_ENUMERATED), + ASN1_GEN_STR("OID", V_ASN1_OBJECT), + ASN1_GEN_STR("OBJECT", V_ASN1_OBJECT), + ASN1_GEN_STR("UTCTIME", V_ASN1_UTCTIME), + ASN1_GEN_STR("UTC", V_ASN1_UTCTIME), + ASN1_GEN_STR("GENERALIZEDTIME", V_ASN1_GENERALIZEDTIME), + ASN1_GEN_STR("GENTIME", V_ASN1_GENERALIZEDTIME), + ASN1_GEN_STR("OCT", V_ASN1_OCTET_STRING), + ASN1_GEN_STR("OCTETSTRING", V_ASN1_OCTET_STRING), + ASN1_GEN_STR("BITSTR", V_ASN1_BIT_STRING), + ASN1_GEN_STR("BITSTRING", V_ASN1_BIT_STRING), + ASN1_GEN_STR("UNIVERSALSTRING", V_ASN1_UNIVERSALSTRING), + ASN1_GEN_STR("UNIV", V_ASN1_UNIVERSALSTRING), + ASN1_GEN_STR("IA5", V_ASN1_IA5STRING), + ASN1_GEN_STR("IA5STRING", V_ASN1_IA5STRING), + ASN1_GEN_STR("UTF8", V_ASN1_UTF8STRING), + ASN1_GEN_STR("UTF8String", V_ASN1_UTF8STRING), + ASN1_GEN_STR("BMP", V_ASN1_BMPSTRING), + ASN1_GEN_STR("BMPSTRING", V_ASN1_BMPSTRING), + ASN1_GEN_STR("VISIBLESTRING", V_ASN1_VISIBLESTRING), + ASN1_GEN_STR("VISIBLE", V_ASN1_VISIBLESTRING), + ASN1_GEN_STR("PRINTABLESTRING", V_ASN1_PRINTABLESTRING), + ASN1_GEN_STR("PRINTABLE", V_ASN1_PRINTABLESTRING), + ASN1_GEN_STR("T61", V_ASN1_T61STRING), + ASN1_GEN_STR("T61STRING", V_ASN1_T61STRING), + ASN1_GEN_STR("TELETEXSTRING", V_ASN1_T61STRING), + ASN1_GEN_STR("GeneralString", V_ASN1_GENERALSTRING), + ASN1_GEN_STR("GENSTR", V_ASN1_GENERALSTRING), + ASN1_GEN_STR("NUMERIC", V_ASN1_NUMERICSTRING), + ASN1_GEN_STR("NUMERICSTRING", V_ASN1_NUMERICSTRING), + + /* Special cases */ + ASN1_GEN_STR("SEQUENCE", V_ASN1_SEQUENCE), + ASN1_GEN_STR("SEQ", V_ASN1_SEQUENCE), + ASN1_GEN_STR("SET", V_ASN1_SET), + /* type modifiers */ + /* Explicit tag */ + ASN1_GEN_STR("EXP", ASN1_GEN_FLAG_EXP), + ASN1_GEN_STR("EXPLICIT", ASN1_GEN_FLAG_EXP), + /* Implicit tag */ + ASN1_GEN_STR("IMP", ASN1_GEN_FLAG_IMP), + ASN1_GEN_STR("IMPLICIT", ASN1_GEN_FLAG_IMP), + /* OCTET STRING wrapper */ + ASN1_GEN_STR("OCTWRAP", ASN1_GEN_FLAG_OCTWRAP), + /* SEQUENCE wrapper */ + ASN1_GEN_STR("SEQWRAP", ASN1_GEN_FLAG_SEQWRAP), + /* SET wrapper */ + ASN1_GEN_STR("SETWRAP", ASN1_GEN_FLAG_SETWRAP), + /* BIT STRING wrapper */ + ASN1_GEN_STR("BITWRAP", ASN1_GEN_FLAG_BITWRAP), + ASN1_GEN_STR("FORM", ASN1_GEN_FLAG_FORMAT), + ASN1_GEN_STR("FORMAT", ASN1_GEN_FLAG_FORMAT), + }; + + if (len == -1) + len = strlen(tagstr); + + tntmp = tnst; + for (i = 0; i < sizeof(tnst) / sizeof(struct tag_name_st); i++, tntmp++) { + if ((len == tntmp->len) && !strncmp(tntmp->strnam, tagstr, len)) + return tntmp->tag; + } + + return -1; +} + +static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype) +{ + ASN1_TYPE *atmp = NULL; + + CONF_VALUE vtmp; + + unsigned char *rdata; + long rdlen; + + int no_unused = 1; + + if (!(atmp = ASN1_TYPE_new())) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + return NULL; + } + + if (!str) + str = ""; + + switch (utype) { + + case V_ASN1_NULL: + if (str && *str) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_NULL_VALUE); + goto bad_form; + } + break; + + case V_ASN1_BOOLEAN: + if (format != ASN1_GEN_FORMAT_ASCII) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_NOT_ASCII_FORMAT); + goto bad_form; + } + vtmp.name = NULL; + vtmp.section = NULL; + vtmp.value = (char *)str; + if (!X509V3_get_value_bool(&vtmp, &atmp->value.boolean)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_BOOLEAN); + goto bad_str; + } + break; + + case V_ASN1_INTEGER: + case V_ASN1_ENUMERATED: + if (format != ASN1_GEN_FORMAT_ASCII) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_INTEGER_NOT_ASCII_FORMAT); + goto bad_form; + } + if (!(atmp->value.integer = s2i_ASN1_INTEGER(NULL, (char *)str))) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_INTEGER); + goto bad_str; + } + break; + + case V_ASN1_OBJECT: + if (format != ASN1_GEN_FORMAT_ASCII) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_OBJECT_NOT_ASCII_FORMAT); + goto bad_form; + } + if (!(atmp->value.object = OBJ_txt2obj(str, 0))) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_OBJECT); + goto bad_str; + } + break; + + case V_ASN1_UTCTIME: + case V_ASN1_GENERALIZEDTIME: + if (format != ASN1_GEN_FORMAT_ASCII) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_TIME_NOT_ASCII_FORMAT); + goto bad_form; + } + if (!(atmp->value.asn1_string = ASN1_STRING_new())) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + goto bad_str; + } + if (!ASN1_STRING_set(atmp->value.asn1_string, str, -1)) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + goto bad_str; + } + atmp->value.asn1_string->type = utype; + if (!ASN1_TIME_check(atmp->value.asn1_string)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_TIME_VALUE); + goto bad_str; + } + + break; + + case V_ASN1_BMPSTRING: + case V_ASN1_PRINTABLESTRING: + case V_ASN1_IA5STRING: + case V_ASN1_T61STRING: + case V_ASN1_UTF8STRING: + case V_ASN1_VISIBLESTRING: + case V_ASN1_UNIVERSALSTRING: + case V_ASN1_GENERALSTRING: + case V_ASN1_NUMERICSTRING: + + if (format == ASN1_GEN_FORMAT_ASCII) + format = MBSTRING_ASC; + else if (format == ASN1_GEN_FORMAT_UTF8) + format = MBSTRING_UTF8; + else { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_FORMAT); + goto bad_form; + } + + if (ASN1_mbstring_copy(&atmp->value.asn1_string, (unsigned char *)str, + -1, format, ASN1_tag2bit(utype)) <= 0) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + goto bad_str; + } + + break; + + case V_ASN1_BIT_STRING: + + case V_ASN1_OCTET_STRING: + + if (!(atmp->value.asn1_string = ASN1_STRING_new())) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + goto bad_form; + } + + if (format == ASN1_GEN_FORMAT_HEX) { + + if (!(rdata = string_to_hex((char *)str, &rdlen))) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_HEX); + goto bad_str; + } + + atmp->value.asn1_string->data = rdata; + atmp->value.asn1_string->length = rdlen; + atmp->value.asn1_string->type = utype; + + } else if (format == ASN1_GEN_FORMAT_ASCII) + ASN1_STRING_set(atmp->value.asn1_string, str, -1); + else if ((format == ASN1_GEN_FORMAT_BITLIST) + && (utype == V_ASN1_BIT_STRING)) { + if (!CONF_parse_list + (str, ',', 1, bitstr_cb, atmp->value.bit_string)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_LIST_ERROR); + goto bad_str; + } + no_unused = 0; + + } else { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_BITSTRING_FORMAT); + goto bad_form; + } + + if ((utype == V_ASN1_BIT_STRING) && no_unused) { + atmp->value.asn1_string->flags + &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); + atmp->value.asn1_string->flags |= ASN1_STRING_FLAG_BITS_LEFT; + } + + break; + + default: + OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNSUPPORTED_TYPE); + goto bad_str; + break; + } + + atmp->type = utype; + return atmp; + + bad_str: + ERR_add_error_data(2, "string=", str); + bad_form: + + ASN1_TYPE_free(atmp); + return NULL; + +} + +static int bitstr_cb(const char *elem, int len, void *bitstr) +{ + long bitnum; + char *eptr; + if (!elem) + return 0; + bitnum = strtoul(elem, &eptr, 10); + if (eptr && *eptr && (eptr != elem + len)) + return 0; + if (bitnum < 0) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_NUMBER); + return 0; + } + if (!ASN1_BIT_STRING_set_bit(bitstr, bitnum, 1)) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + return 0; + } + return 1; +} diff --git a/external/boringssl/crypto/x509/by_dir.c b/external/boringssl/crypto/x509/by_dir.c new file mode 100644 index 0000000000..4445b058a2 --- /dev/null +++ b/external/boringssl/crypto/x509/by_dir.c @@ -0,0 +1,453 @@ +/* crypto/x509/by_dir.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "../internal.h" + +typedef struct lookup_dir_hashes_st { + unsigned long hash; + int suffix; +} BY_DIR_HASH; + +typedef struct lookup_dir_entry_st { + char *dir; + int dir_type; + STACK_OF(BY_DIR_HASH) *hashes; +} BY_DIR_ENTRY; + +typedef struct lookup_dir_st { + BUF_MEM *buffer; + STACK_OF(BY_DIR_ENTRY) *dirs; +} BY_DIR; + +DECLARE_STACK_OF(BY_DIR_HASH) +DECLARE_STACK_OF(BY_DIR_ENTRY) + +static int dir_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl, + char **ret); +static int new_dir(X509_LOOKUP *lu); +static void free_dir(X509_LOOKUP *lu); +static int add_cert_dir(BY_DIR *ctx, const char *dir, int type); +static int get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name, + X509_OBJECT *ret); +static X509_LOOKUP_METHOD x509_dir_lookup = { + "Load certs from files in a directory", + new_dir, /* new */ + free_dir, /* free */ + NULL, /* init */ + NULL, /* shutdown */ + dir_ctrl, /* ctrl */ + get_cert_by_subject, /* get_by_subject */ + NULL, /* get_by_issuer_serial */ + NULL, /* get_by_fingerprint */ + NULL, /* get_by_alias */ +}; + +X509_LOOKUP_METHOD *X509_LOOKUP_hash_dir(void) +{ + return (&x509_dir_lookup); +} + +static int dir_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl, + char **retp) +{ + int ret = 0; + BY_DIR *ld; + char *dir = NULL; + + ld = (BY_DIR *)ctx->method_data; + + switch (cmd) { + case X509_L_ADD_DIR: + if (argl == X509_FILETYPE_DEFAULT) { + dir = (char *)getenv(X509_get_default_cert_dir_env()); + if (dir) + ret = add_cert_dir(ld, dir, X509_FILETYPE_PEM); + else + ret = add_cert_dir(ld, X509_get_default_cert_dir(), + X509_FILETYPE_PEM); + if (!ret) { + OPENSSL_PUT_ERROR(X509, X509_R_LOADING_CERT_DIR); + } + } else + ret = add_cert_dir(ld, argp, (int)argl); + break; + } + return (ret); +} + +static int new_dir(X509_LOOKUP *lu) +{ + BY_DIR *a; + + if ((a = (BY_DIR *)OPENSSL_malloc(sizeof(BY_DIR))) == NULL) + return (0); + if ((a->buffer = BUF_MEM_new()) == NULL) { + OPENSSL_free(a); + return (0); + } + a->dirs = NULL; + lu->method_data = (char *)a; + return (1); +} + +static void by_dir_hash_free(BY_DIR_HASH *hash) +{ + OPENSSL_free(hash); +} + +static int by_dir_hash_cmp(const BY_DIR_HASH **a, const BY_DIR_HASH **b) +{ + if ((*a)->hash > (*b)->hash) + return 1; + if ((*a)->hash < (*b)->hash) + return -1; + return 0; +} + +static void by_dir_entry_free(BY_DIR_ENTRY *ent) +{ + if (ent->dir) + OPENSSL_free(ent->dir); + if (ent->hashes) + sk_BY_DIR_HASH_pop_free(ent->hashes, by_dir_hash_free); + OPENSSL_free(ent); +} + +static void free_dir(X509_LOOKUP *lu) +{ + BY_DIR *a; + + a = (BY_DIR *)lu->method_data; + if (a->dirs != NULL) + sk_BY_DIR_ENTRY_pop_free(a->dirs, by_dir_entry_free); + if (a->buffer != NULL) + BUF_MEM_free(a->buffer); + OPENSSL_free(a); +} + +static int add_cert_dir(BY_DIR *ctx, const char *dir, int type) +{ + size_t j, len; + const char *s, *ss, *p; + + if (dir == NULL || !*dir) { + OPENSSL_PUT_ERROR(X509, X509_R_INVALID_DIRECTORY); + return 0; + } + + s = dir; + p = s; + do { + if ((*p == ':') || (*p == '\0')) { + BY_DIR_ENTRY *ent; + ss = s; + s = p + 1; + len = p - ss; + if (len == 0) + continue; + for (j = 0; j < sk_BY_DIR_ENTRY_num(ctx->dirs); j++) { + ent = sk_BY_DIR_ENTRY_value(ctx->dirs, j); + if (strlen(ent->dir) == len && + strncmp(ent->dir, ss, len) == 0) + break; + } + if (j < sk_BY_DIR_ENTRY_num(ctx->dirs)) + continue; + if (ctx->dirs == NULL) { + ctx->dirs = sk_BY_DIR_ENTRY_new_null(); + if (!ctx->dirs) { + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + return 0; + } + } + ent = OPENSSL_malloc(sizeof(BY_DIR_ENTRY)); + if (!ent) + return 0; + ent->dir_type = type; + ent->hashes = sk_BY_DIR_HASH_new(by_dir_hash_cmp); + ent->dir = OPENSSL_malloc(len + 1); + if (!ent->dir || !ent->hashes) { + by_dir_entry_free(ent); + return 0; + } + strncpy(ent->dir, ss, len); + ent->dir[len] = '\0'; + if (!sk_BY_DIR_ENTRY_push(ctx->dirs, ent)) { + by_dir_entry_free(ent); + return 0; + } + } + } while (*p++ != '\0'); + return 1; +} + +/* + * g_ent_hashes_lock protects the |hashes| member of all |BY_DIR_ENTRY| + * objects. + */ +static struct CRYPTO_STATIC_MUTEX g_ent_hashes_lock = + CRYPTO_STATIC_MUTEX_INIT; + +static int get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name, + X509_OBJECT *ret) +{ + BY_DIR *ctx; + union { + struct { + X509 st_x509; + X509_CINF st_x509_cinf; + } x509; + struct { + X509_CRL st_crl; + X509_CRL_INFO st_crl_info; + } crl; + } data; + int ok = 0; + size_t i; + int j, k; + unsigned long h; + unsigned long hash_array[2]; + int hash_index; + BUF_MEM *b = NULL; + X509_OBJECT stmp, *tmp; + const char *postfix = ""; + + if (name == NULL) + return (0); + + stmp.type = type; + if (type == X509_LU_X509) { + data.x509.st_x509.cert_info = &data.x509.st_x509_cinf; + data.x509.st_x509_cinf.subject = name; + stmp.data.x509 = &data.x509.st_x509; + postfix = ""; + } else if (type == X509_LU_CRL) { + data.crl.st_crl.crl = &data.crl.st_crl_info; + data.crl.st_crl_info.issuer = name; + stmp.data.crl = &data.crl.st_crl; + postfix = "r"; + } else { + OPENSSL_PUT_ERROR(X509, X509_R_WRONG_LOOKUP_TYPE); + goto finish; + } + + if ((b = BUF_MEM_new()) == NULL) { + OPENSSL_PUT_ERROR(X509, ERR_R_BUF_LIB); + goto finish; + } + + ctx = (BY_DIR *)xl->method_data; + + hash_array[0] = X509_NAME_hash(name); + hash_array[1] = X509_NAME_hash_old(name); + for (hash_index = 0; hash_index < 2; ++hash_index) { + h = hash_array[hash_index]; + for (i = 0; i < sk_BY_DIR_ENTRY_num(ctx->dirs); i++) { + BY_DIR_ENTRY *ent; + size_t idx; + BY_DIR_HASH htmp, *hent; + ent = sk_BY_DIR_ENTRY_value(ctx->dirs, i); + j = strlen(ent->dir) + 1 + 8 + 6 + 1 + 1; + if (!BUF_MEM_grow(b, j)) { + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + goto finish; + } + if (type == X509_LU_CRL && ent->hashes) { + htmp.hash = h; + CRYPTO_STATIC_MUTEX_lock_read(&g_ent_hashes_lock); + if (sk_BY_DIR_HASH_find(ent->hashes, &idx, &htmp)) { + hent = sk_BY_DIR_HASH_value(ent->hashes, idx); + k = hent->suffix; + } else { + hent = NULL; + k = 0; + } + CRYPTO_STATIC_MUTEX_unlock_read(&g_ent_hashes_lock); + } else { + k = 0; + hent = NULL; + } + for (;;) { + char c = '/'; +#ifdef OPENSSL_SYS_VMS + c = ent->dir[strlen(ent->dir) - 1]; + if (c != ':' && c != '>' && c != ']') { + /* + * If no separator is present, we assume the directory + * specifier is a logical name, and add a colon. We + * really should use better VMS routines for merging + * things like this, but this will do for now... -- + * Richard Levitte + */ + c = ':'; + } else { + c = '\0'; + } +#endif + if (c == '\0') { + /* + * This is special. When c == '\0', no directory + * separator should be added. + */ + BIO_snprintf(b->data, b->max, + "%s%08lx.%s%d", ent->dir, h, postfix, k); + } else { + BIO_snprintf(b->data, b->max, + "%s%c%08lx.%s%d", ent->dir, c, h, + postfix, k); + } +#ifndef OPENSSL_NO_POSIX_IO +# ifdef _WIN32 +# define stat _stat +# endif + { + struct stat st; + if (stat(b->data, &st) < 0) + break; + } +#endif + /* found one. */ + if (type == X509_LU_X509) { + if ((X509_load_cert_file(xl, b->data, + ent->dir_type)) == 0) + break; + } else if (type == X509_LU_CRL) { + if ((X509_load_crl_file(xl, b->data, ent->dir_type)) == 0) + break; + } + /* else case will caught higher up */ + k++; + } + + /* + * we have added it to the cache so now pull it out again + */ + CRYPTO_MUTEX_lock_write(&xl->store_ctx->objs_lock); + tmp = NULL; + if (sk_X509_OBJECT_find(xl->store_ctx->objs, &idx, &stmp)) { + tmp = sk_X509_OBJECT_value(xl->store_ctx->objs, idx); + } + CRYPTO_MUTEX_unlock_write(&xl->store_ctx->objs_lock); + + /* + * If a CRL, update the last file suffix added for this + */ + + if (type == X509_LU_CRL) { + CRYPTO_STATIC_MUTEX_lock_write(&g_ent_hashes_lock); + /* + * Look for entry again in case another thread added an entry + * first. + */ + if (!hent) { + htmp.hash = h; + if (sk_BY_DIR_HASH_find(ent->hashes, &idx, &htmp)) + hent = sk_BY_DIR_HASH_value(ent->hashes, idx); + } + if (!hent) { + hent = OPENSSL_malloc(sizeof(BY_DIR_HASH)); + if (hent == NULL) { + CRYPTO_STATIC_MUTEX_unlock_write(&g_ent_hashes_lock); + ok = 0; + goto finish; + } + hent->hash = h; + hent->suffix = k; + if (!sk_BY_DIR_HASH_push(ent->hashes, hent)) { + CRYPTO_STATIC_MUTEX_unlock_write(&g_ent_hashes_lock); + OPENSSL_free(hent); + ok = 0; + goto finish; + } + } else if (hent->suffix < k) + hent->suffix = k; + + CRYPTO_STATIC_MUTEX_unlock_write(&g_ent_hashes_lock); + } + + if (tmp != NULL) { + ok = 1; + ret->type = tmp->type; + memcpy(&ret->data, &tmp->data, sizeof(ret->data)); + /* + * If we were going to up the reference count, we would need + * to do it on a perl 'type' basis + */ + /* + * CRYPTO_add(&tmp->data.x509->references,1, + * CRYPTO_LOCK_X509); + */ + goto finish; + } + } + } + finish: + if (b != NULL) + BUF_MEM_free(b); + return (ok); +} diff --git a/external/boringssl/crypto/x509/by_file.c b/external/boringssl/crypto/x509/by_file.c new file mode 100644 index 0000000000..ebeb72e5e8 --- /dev/null +++ b/external/boringssl/crypto/x509/by_file.c @@ -0,0 +1,275 @@ +/* crypto/x509/by_file.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include +#include +#include +#include + +#ifndef OPENSSL_NO_STDIO + +static int by_file_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, + long argl, char **ret); +static X509_LOOKUP_METHOD x509_file_lookup = { + "Load file into cache", + NULL, /* new */ + NULL, /* free */ + NULL, /* init */ + NULL, /* shutdown */ + by_file_ctrl, /* ctrl */ + NULL, /* get_by_subject */ + NULL, /* get_by_issuer_serial */ + NULL, /* get_by_fingerprint */ + NULL, /* get_by_alias */ +}; + +X509_LOOKUP_METHOD *X509_LOOKUP_file(void) +{ + return (&x509_file_lookup); +} + +static int by_file_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, + long argl, char **ret) +{ + int ok = 0; + char *file; + + switch (cmd) { + case X509_L_FILE_LOAD: + if (argl == X509_FILETYPE_DEFAULT) { + file = (char *)getenv(X509_get_default_cert_file_env()); + if (file) + ok = (X509_load_cert_crl_file(ctx, file, + X509_FILETYPE_PEM) != 0); + + else + ok = (X509_load_cert_crl_file + (ctx, X509_get_default_cert_file(), + X509_FILETYPE_PEM) != 0); + + if (!ok) { + OPENSSL_PUT_ERROR(X509, X509_R_LOADING_DEFAULTS); + } + } else { + if (argl == X509_FILETYPE_PEM) + ok = (X509_load_cert_crl_file(ctx, argp, + X509_FILETYPE_PEM) != 0); + else + ok = (X509_load_cert_file(ctx, argp, (int)argl) != 0); + } + break; + } + return (ok); +} + +int X509_load_cert_file(X509_LOOKUP *ctx, const char *file, int type) +{ + int ret = 0; + BIO *in = NULL; + int i, count = 0; + X509 *x = NULL; + + if (file == NULL) + return (1); + in = BIO_new(BIO_s_file()); + + if ((in == NULL) || (BIO_read_filename(in, file) <= 0)) { + OPENSSL_PUT_ERROR(X509, ERR_R_SYS_LIB); + goto err; + } + + if (type == X509_FILETYPE_PEM) { + for (;;) { + x = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL); + if (x == NULL) { + if ((ERR_GET_REASON(ERR_peek_last_error()) == + PEM_R_NO_START_LINE) && (count > 0)) { + ERR_clear_error(); + break; + } else { + OPENSSL_PUT_ERROR(X509, ERR_R_PEM_LIB); + goto err; + } + } + i = X509_STORE_add_cert(ctx->store_ctx, x); + if (!i) + goto err; + count++; + X509_free(x); + x = NULL; + } + ret = count; + } else if (type == X509_FILETYPE_ASN1) { + x = d2i_X509_bio(in, NULL); + if (x == NULL) { + OPENSSL_PUT_ERROR(X509, ERR_R_ASN1_LIB); + goto err; + } + i = X509_STORE_add_cert(ctx->store_ctx, x); + if (!i) + goto err; + ret = i; + } else { + OPENSSL_PUT_ERROR(X509, X509_R_BAD_X509_FILETYPE); + goto err; + } + err: + if (x != NULL) + X509_free(x); + if (in != NULL) + BIO_free(in); + return (ret); +} + +int X509_load_crl_file(X509_LOOKUP *ctx, const char *file, int type) +{ + int ret = 0; + BIO *in = NULL; + int i, count = 0; + X509_CRL *x = NULL; + + if (file == NULL) + return (1); + in = BIO_new(BIO_s_file()); + + if ((in == NULL) || (BIO_read_filename(in, file) <= 0)) { + OPENSSL_PUT_ERROR(X509, ERR_R_SYS_LIB); + goto err; + } + + if (type == X509_FILETYPE_PEM) { + for (;;) { + x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL); + if (x == NULL) { + if ((ERR_GET_REASON(ERR_peek_last_error()) == + PEM_R_NO_START_LINE) && (count > 0)) { + ERR_clear_error(); + break; + } else { + OPENSSL_PUT_ERROR(X509, ERR_R_PEM_LIB); + goto err; + } + } + i = X509_STORE_add_crl(ctx->store_ctx, x); + if (!i) + goto err; + count++; + X509_CRL_free(x); + x = NULL; + } + ret = count; + } else if (type == X509_FILETYPE_ASN1) { + x = d2i_X509_CRL_bio(in, NULL); + if (x == NULL) { + OPENSSL_PUT_ERROR(X509, ERR_R_ASN1_LIB); + goto err; + } + i = X509_STORE_add_crl(ctx->store_ctx, x); + if (!i) + goto err; + ret = i; + } else { + OPENSSL_PUT_ERROR(X509, X509_R_BAD_X509_FILETYPE); + goto err; + } + err: + if (x != NULL) + X509_CRL_free(x); + if (in != NULL) + BIO_free(in); + return (ret); +} + +int X509_load_cert_crl_file(X509_LOOKUP *ctx, const char *file, int type) +{ + STACK_OF(X509_INFO) *inf; + X509_INFO *itmp; + BIO *in; + size_t i; + int count = 0; + if (type != X509_FILETYPE_PEM) + return X509_load_cert_file(ctx, file, type); + in = BIO_new_file(file, "r"); + if (!in) { + OPENSSL_PUT_ERROR(X509, ERR_R_SYS_LIB); + return 0; + } + inf = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL); + BIO_free(in); + if (!inf) { + OPENSSL_PUT_ERROR(X509, ERR_R_PEM_LIB); + return 0; + } + for (i = 0; i < sk_X509_INFO_num(inf); i++) { + itmp = sk_X509_INFO_value(inf, i); + if (itmp->x509) { + X509_STORE_add_cert(ctx->store_ctx, itmp->x509); + count++; + } + if (itmp->crl) { + X509_STORE_add_crl(ctx->store_ctx, itmp->crl); + count++; + } + } + sk_X509_INFO_pop_free(inf, X509_INFO_free); + return count; +} + +#endif /* OPENSSL_NO_STDIO */ diff --git a/external/boringssl/crypto/x509/charmap.h b/external/boringssl/crypto/x509/charmap.h new file mode 100644 index 0000000000..3305ad146b --- /dev/null +++ b/external/boringssl/crypto/x509/charmap.h @@ -0,0 +1,15 @@ +/* + * Auto generated with chartype.pl script. Mask of various character + * properties + */ + +static const unsigned char char_type[] = { + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 120, 0, 1, 40, 0, 0, 0, 16, 16, 16, 0, 25, 25, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 9, 9, 16, 9, 16, + 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 1, 0, 0, 0, + 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 2 +}; diff --git a/external/boringssl/crypto/x509/i2d_pr.c b/external/boringssl/crypto/x509/i2d_pr.c new file mode 100644 index 0000000000..c3fb8a8a63 --- /dev/null +++ b/external/boringssl/crypto/x509/i2d_pr.c @@ -0,0 +1,83 @@ +/* crypto/asn1/i2d_pr.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include +#include +#include +#include +#include +#include + + +int i2d_PrivateKey(const EVP_PKEY *a, uint8_t **pp) +{ + switch (EVP_PKEY_id(a)) { + case EVP_PKEY_RSA: + return i2d_RSAPrivateKey(a->pkey.rsa, pp); + case EVP_PKEY_EC: + return i2d_ECPrivateKey(a->pkey.ec, pp); + case EVP_PKEY_DSA: + return i2d_DSAPrivateKey(a->pkey.dsa, pp); + default: + /* + * Although this file is in crypto/x509 for layering reasons, it emits + * an error code from ASN1 for OpenSSL compatibility. + */ + OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE); + return -1; + } +} diff --git a/external/boringssl/crypto/x509/internal.h b/external/boringssl/crypto/x509/internal.h new file mode 100644 index 0000000000..4957c1e147 --- /dev/null +++ b/external/boringssl/crypto/x509/internal.h @@ -0,0 +1,66 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_X509_INTERNAL_H +#define OPENSSL_HEADER_X509_INTERNAL_H + +#include +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* RSA-PSS functions. */ + +/* x509_rsa_pss_to_ctx configures |ctx| for an RSA-PSS operation based on + * signature algorithm parameters in |sigalg| (which must have type + * |NID_rsassaPss|) and key |pkey|. It returns one on success and zero on + * error. */ +int x509_rsa_pss_to_ctx(EVP_MD_CTX *ctx, X509_ALGOR *sigalg, EVP_PKEY *pkey); + +/* x509_rsa_pss_to_ctx sets |algor| to the signature algorithm parameters for + * |ctx|, which must have been configured for an RSA-PSS signing operation. It + * returns one on success and zero on error. */ +int x509_rsa_ctx_to_pss(EVP_MD_CTX *ctx, X509_ALGOR *algor); + +/* x509_print_rsa_pss_params prints a human-readable representation of RSA-PSS + * parameters in |sigalg| to |bp|. It returns one on success and zero on + * error. */ +int x509_print_rsa_pss_params(BIO *bp, const X509_ALGOR *sigalg, int indent, + ASN1_PCTX *pctx); + + +/* Signature algorithm functions. */ + +/* x509_digest_sign_algorithm encodes the signing parameters of |ctx| as an + * AlgorithmIdentifer and saves the result in |algor|. It returns one on + * success, or zero on error. */ +int x509_digest_sign_algorithm(EVP_MD_CTX *ctx, X509_ALGOR *algor); + +/* x509_digest_verify_init sets up |ctx| for a signature verification operation + * with public key |pkey| and parameters from |algor|. The |ctx| argument must + * have been initialised with |EVP_MD_CTX_init|. It returns one on success, or + * zero on error. */ +int x509_digest_verify_init(EVP_MD_CTX *ctx, X509_ALGOR *sigalg, + EVP_PKEY *pkey); + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_X509_INTERNAL_H */ diff --git a/external/boringssl/crypto/x509/pkcs7.c b/external/boringssl/crypto/x509/pkcs7.c new file mode 100644 index 0000000000..9e6a52f26e --- /dev/null +++ b/external/boringssl/crypto/x509/pkcs7.c @@ -0,0 +1,353 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "../bytestring/internal.h" + + +/* pkcs7_parse_header reads the non-certificate/non-CRL prefix of a PKCS#7 + * SignedData blob from |cbs| and sets |*out| to point to the rest of the + * input. If the input is in BER format, then |*der_bytes| will be set to a + * pointer that needs to be freed by the caller once they have finished + * processing |*out| (which will be pointing into |*der_bytes|). + * + * It returns one on success or zero on error. On error, |*der_bytes| is + * NULL. */ +static int pkcs7_parse_header(uint8_t **der_bytes, CBS *out, CBS *cbs) { + size_t der_len; + CBS in, content_info, content_type, wrapped_signed_data, signed_data; + uint64_t version; + + /* The input may be in BER format. */ + *der_bytes = NULL; + if (!CBS_asn1_ber_to_der(cbs, der_bytes, &der_len)) { + return 0; + } + if (*der_bytes != NULL) { + CBS_init(&in, *der_bytes, der_len); + } else { + CBS_init(&in, CBS_data(cbs), CBS_len(cbs)); + } + + /* See https://tools.ietf.org/html/rfc2315#section-7 */ + if (!CBS_get_asn1(&in, &content_info, CBS_ASN1_SEQUENCE) || + !CBS_get_asn1(&content_info, &content_type, CBS_ASN1_OBJECT)) { + goto err; + } + + if (OBJ_cbs2nid(&content_type) != NID_pkcs7_signed) { + OPENSSL_PUT_ERROR(X509, X509_R_NOT_PKCS7_SIGNED_DATA); + goto err; + } + + /* See https://tools.ietf.org/html/rfc2315#section-9.1 */ + if (!CBS_get_asn1(&content_info, &wrapped_signed_data, + CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) || + !CBS_get_asn1(&wrapped_signed_data, &signed_data, CBS_ASN1_SEQUENCE) || + !CBS_get_asn1_uint64(&signed_data, &version) || + !CBS_get_asn1(&signed_data, NULL /* digests */, CBS_ASN1_SET) || + !CBS_get_asn1(&signed_data, NULL /* content */, CBS_ASN1_SEQUENCE)) { + goto err; + } + + if (version < 1) { + OPENSSL_PUT_ERROR(X509, X509_R_BAD_PKCS7_VERSION); + goto err; + } + + CBS_init(out, CBS_data(&signed_data), CBS_len(&signed_data)); + return 1; + +err: + if (*der_bytes) { + OPENSSL_free(*der_bytes); + *der_bytes = NULL; + } + + return 0; +} + +int PKCS7_get_certificates(STACK_OF(X509) *out_certs, CBS *cbs) { + CBS signed_data, certificates; + uint8_t *der_bytes = NULL; + int ret = 0; + const size_t initial_certs_len = sk_X509_num(out_certs); + + if (!pkcs7_parse_header(&der_bytes, &signed_data, cbs)) { + return 0; + } + + /* See https://tools.ietf.org/html/rfc2315#section-9.1 */ + if (!CBS_get_asn1(&signed_data, &certificates, + CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) { + OPENSSL_PUT_ERROR(X509, X509_R_NO_CERTIFICATES_INCLUDED); + goto err; + } + + while (CBS_len(&certificates) > 0) { + CBS cert; + X509 *x509; + const uint8_t *inp; + + if (!CBS_get_asn1_element(&certificates, &cert, CBS_ASN1_SEQUENCE)) { + goto err; + } + + if (CBS_len(&cert) > LONG_MAX) { + goto err; + } + inp = CBS_data(&cert); + x509 = d2i_X509(NULL, &inp, (long)CBS_len(&cert)); + if (!x509) { + goto err; + } + + assert(inp == CBS_data(&cert) + CBS_len(&cert)); + + if (sk_X509_push(out_certs, x509) == 0) { + X509_free(x509); + goto err; + } + } + + ret = 1; + +err: + if (der_bytes) { + OPENSSL_free(der_bytes); + } + + if (!ret) { + while (sk_X509_num(out_certs) != initial_certs_len) { + X509 *x509 = sk_X509_pop(out_certs); + X509_free(x509); + } + } + + return ret; +} + +int PKCS7_get_CRLs(STACK_OF(X509_CRL) *out_crls, CBS *cbs) { + CBS signed_data, crls; + uint8_t *der_bytes = NULL; + int ret = 0; + const size_t initial_crls_len = sk_X509_CRL_num(out_crls); + + if (!pkcs7_parse_header(&der_bytes, &signed_data, cbs)) { + return 0; + } + + /* See https://tools.ietf.org/html/rfc2315#section-9.1 */ + + /* Even if only CRLs are included, there may be an empty certificates block. + * OpenSSL does this, for example. */ + if (CBS_peek_asn1_tag(&signed_data, + CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) && + !CBS_get_asn1(&signed_data, NULL /* certificates */, + CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) { + goto err; + } + + if (!CBS_get_asn1(&signed_data, &crls, + CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1)) { + OPENSSL_PUT_ERROR(X509, X509_R_NO_CRLS_INCLUDED); + goto err; + } + + while (CBS_len(&crls) > 0) { + CBS crl_data; + X509_CRL *crl; + const uint8_t *inp; + + if (!CBS_get_asn1_element(&crls, &crl_data, CBS_ASN1_SEQUENCE)) { + goto err; + } + + if (CBS_len(&crl_data) > LONG_MAX) { + goto err; + } + inp = CBS_data(&crl_data); + crl = d2i_X509_CRL(NULL, &inp, (long)CBS_len(&crl_data)); + if (!crl) { + goto err; + } + + assert(inp == CBS_data(&crl_data) + CBS_len(&crl_data)); + + if (sk_X509_CRL_push(out_crls, crl) == 0) { + X509_CRL_free(crl); + goto err; + } + } + + ret = 1; + +err: + if (der_bytes) { + OPENSSL_free(der_bytes); + } + + if (!ret) { + while (sk_X509_CRL_num(out_crls) != initial_crls_len) { + X509_CRL_free(sk_X509_CRL_pop(out_crls)); + } + } + + return ret; +} + +int PKCS7_get_PEM_certificates(STACK_OF(X509) *out_certs, BIO *pem_bio) { + uint8_t *data; + long len; + int ret; + + /* Even though we pass PEM_STRING_PKCS7 as the expected PEM type here, PEM + * internally will actually allow several other values too, including + * "CERTIFICATE". */ + if (!PEM_bytes_read_bio(&data, &len, NULL /* PEM type output */, + PEM_STRING_PKCS7, pem_bio, + NULL /* password callback */, + NULL /* password callback argument */)) { + return 0; + } + + CBS cbs; + CBS_init(&cbs, data, len); + ret = PKCS7_get_certificates(out_certs, &cbs); + OPENSSL_free(data); + return ret; +} + +int PKCS7_get_PEM_CRLs(STACK_OF(X509_CRL) *out_crls, BIO *pem_bio) { + uint8_t *data; + long len; + int ret; + + /* Even though we pass PEM_STRING_PKCS7 as the expected PEM type here, PEM + * internally will actually allow several other values too, including + * "CERTIFICATE". */ + if (!PEM_bytes_read_bio(&data, &len, NULL /* PEM type output */, + PEM_STRING_PKCS7, pem_bio, + NULL /* password callback */, + NULL /* password callback argument */)) { + return 0; + } + + CBS cbs; + CBS_init(&cbs, data, len); + ret = PKCS7_get_CRLs(out_crls, &cbs); + OPENSSL_free(data); + return ret; +} + +/* pkcs7_bundle writes a PKCS#7, SignedData structure to |out| and then calls + * |cb| with a CBB to which certificate or CRL data can be written, and the + * opaque context pointer, |arg|. The callback can return zero to indicate an + * error. + * + * pkcs7_bundle returns one on success or zero on error. */ +static int pkcs7_bundle(CBB *out, int (*cb)(CBB *out, const void *arg), + const void *arg) { + CBB outer_seq, wrapped_seq, seq, version_bytes, digest_algos_set, + content_info; + + /* See https://tools.ietf.org/html/rfc2315#section-7 */ + if (!CBB_add_asn1(out, &outer_seq, CBS_ASN1_SEQUENCE) || + !OBJ_nid2cbb(&outer_seq, NID_pkcs7_signed) || + !CBB_add_asn1(&outer_seq, &wrapped_seq, + CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) || + /* See https://tools.ietf.org/html/rfc2315#section-9.1 */ + !CBB_add_asn1(&wrapped_seq, &seq, CBS_ASN1_SEQUENCE) || + !CBB_add_asn1(&seq, &version_bytes, CBS_ASN1_INTEGER) || + !CBB_add_u8(&version_bytes, 1) || + !CBB_add_asn1(&seq, &digest_algos_set, CBS_ASN1_SET) || + !CBB_add_asn1(&seq, &content_info, CBS_ASN1_SEQUENCE) || + !OBJ_nid2cbb(&content_info, NID_pkcs7_data) || + !cb(&seq, arg)) { + return 0; + } + + return CBB_flush(out); +} + +static int pkcs7_bundle_certificates_cb(CBB *out, const void *arg) { + const STACK_OF(X509) *certs = arg; + size_t i; + CBB certificates; + + /* See https://tools.ietf.org/html/rfc2315#section-9.1 */ + if (!CBB_add_asn1(out, &certificates, + CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) { + return 0; + } + + for (i = 0; i < sk_X509_num(certs); i++) { + X509 *x509 = sk_X509_value(certs, i); + uint8_t *buf; + int len = i2d_X509(x509, NULL); + + if (len < 0 || + !CBB_add_space(&certificates, &buf, len) || + i2d_X509(x509, &buf) < 0) { + return 0; + } + } + + return CBB_flush(out); +} + +int PKCS7_bundle_certificates(CBB *out, const STACK_OF(X509) *certs) { + return pkcs7_bundle(out, pkcs7_bundle_certificates_cb, certs); +} + +static int pkcs7_bundle_crls_cb(CBB *out, const void *arg) { + const STACK_OF(X509_CRL) *crls = arg; + size_t i; + CBB crl_data; + + /* See https://tools.ietf.org/html/rfc2315#section-9.1 */ + if (!CBB_add_asn1(out, &crl_data, + CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1)) { + return 0; + } + + for (i = 0; i < sk_X509_CRL_num(crls); i++) { + X509_CRL *crl = sk_X509_CRL_value(crls, i); + uint8_t *buf; + int len = i2d_X509_CRL(crl, NULL); + + if (len < 0 || + !CBB_add_space(&crl_data, &buf, len) || + i2d_X509_CRL(crl, &buf) < 0) { + return 0; + } + } + + return CBB_flush(out); +} + +int PKCS7_bundle_CRLs(CBB *out, const STACK_OF(X509_CRL) *crls) { + return pkcs7_bundle(out, pkcs7_bundle_crls_cb, crls); +} diff --git a/external/boringssl/crypto/x509/pkcs7_test.c b/external/boringssl/crypto/x509/pkcs7_test.c new file mode 100644 index 0000000000..bebcbd9555 --- /dev/null +++ b/external/boringssl/crypto/x509/pkcs7_test.c @@ -0,0 +1,656 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "../test/test_util.h" + + +/* kPKCS7NSS contains the certificate chain of mail.google.com, as saved by NSS + * using the Chrome UI. */ +static const uint8_t kPKCS7NSS[] = { + 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, + 0x02, 0xa0, 0x80, 0x30, 0x80, 0x02, 0x01, 0x01, 0x31, 0x00, 0x30, 0x80, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0x00, + 0x00, 0xa0, 0x82, 0x0b, 0x1e, 0x30, 0x82, 0x03, 0x54, 0x30, 0x82, 0x02, + 0x3c, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x02, 0x34, 0x56, 0x30, + 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, + 0x05, 0x00, 0x30, 0x42, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, + 0x04, 0x0a, 0x13, 0x0d, 0x47, 0x65, 0x6f, 0x54, 0x72, 0x75, 0x73, 0x74, + 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x12, 0x47, 0x65, 0x6f, 0x54, 0x72, 0x75, 0x73, 0x74, + 0x20, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x43, 0x41, 0x30, 0x1e, + 0x17, 0x0d, 0x30, 0x32, 0x30, 0x35, 0x32, 0x31, 0x30, 0x34, 0x30, 0x30, + 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x32, 0x32, 0x30, 0x35, 0x32, 0x31, 0x30, + 0x34, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x42, 0x31, 0x0b, 0x30, 0x09, + 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, + 0x14, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0d, 0x47, 0x65, 0x6f, 0x54, + 0x72, 0x75, 0x73, 0x74, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x1b, 0x30, + 0x19, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x12, 0x47, 0x65, 0x6f, 0x54, + 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, + 0x43, 0x41, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, + 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xda, + 0xcc, 0x18, 0x63, 0x30, 0xfd, 0xf4, 0x17, 0x23, 0x1a, 0x56, 0x7e, 0x5b, + 0xdf, 0x3c, 0x6c, 0x38, 0xe4, 0x71, 0xb7, 0x78, 0x91, 0xd4, 0xbc, 0xa1, + 0xd8, 0x4c, 0xf8, 0xa8, 0x43, 0xb6, 0x03, 0xe9, 0x4d, 0x21, 0x07, 0x08, + 0x88, 0xda, 0x58, 0x2f, 0x66, 0x39, 0x29, 0xbd, 0x05, 0x78, 0x8b, 0x9d, + 0x38, 0xe8, 0x05, 0xb7, 0x6a, 0x7e, 0x71, 0xa4, 0xe6, 0xc4, 0x60, 0xa6, + 0xb0, 0xef, 0x80, 0xe4, 0x89, 0x28, 0x0f, 0x9e, 0x25, 0xd6, 0xed, 0x83, + 0xf3, 0xad, 0xa6, 0x91, 0xc7, 0x98, 0xc9, 0x42, 0x18, 0x35, 0x14, 0x9d, + 0xad, 0x98, 0x46, 0x92, 0x2e, 0x4f, 0xca, 0xf1, 0x87, 0x43, 0xc1, 0x16, + 0x95, 0x57, 0x2d, 0x50, 0xef, 0x89, 0x2d, 0x80, 0x7a, 0x57, 0xad, 0xf2, + 0xee, 0x5f, 0x6b, 0xd2, 0x00, 0x8d, 0xb9, 0x14, 0xf8, 0x14, 0x15, 0x35, + 0xd9, 0xc0, 0x46, 0xa3, 0x7b, 0x72, 0xc8, 0x91, 0xbf, 0xc9, 0x55, 0x2b, + 0xcd, 0xd0, 0x97, 0x3e, 0x9c, 0x26, 0x64, 0xcc, 0xdf, 0xce, 0x83, 0x19, + 0x71, 0xca, 0x4e, 0xe6, 0xd4, 0xd5, 0x7b, 0xa9, 0x19, 0xcd, 0x55, 0xde, + 0xc8, 0xec, 0xd2, 0x5e, 0x38, 0x53, 0xe5, 0x5c, 0x4f, 0x8c, 0x2d, 0xfe, + 0x50, 0x23, 0x36, 0xfc, 0x66, 0xe6, 0xcb, 0x8e, 0xa4, 0x39, 0x19, 0x00, + 0xb7, 0x95, 0x02, 0x39, 0x91, 0x0b, 0x0e, 0xfe, 0x38, 0x2e, 0xd1, 0x1d, + 0x05, 0x9a, 0xf6, 0x4d, 0x3e, 0x6f, 0x0f, 0x07, 0x1d, 0xaf, 0x2c, 0x1e, + 0x8f, 0x60, 0x39, 0xe2, 0xfa, 0x36, 0x53, 0x13, 0x39, 0xd4, 0x5e, 0x26, + 0x2b, 0xdb, 0x3d, 0xa8, 0x14, 0xbd, 0x32, 0xeb, 0x18, 0x03, 0x28, 0x52, + 0x04, 0x71, 0xe5, 0xab, 0x33, 0x3d, 0xe1, 0x38, 0xbb, 0x07, 0x36, 0x84, + 0x62, 0x9c, 0x79, 0xea, 0x16, 0x30, 0xf4, 0x5f, 0xc0, 0x2b, 0xe8, 0x71, + 0x6b, 0xe4, 0xf9, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x53, 0x30, 0x51, + 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, + 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, + 0x04, 0x16, 0x04, 0x14, 0xc0, 0x7a, 0x98, 0x68, 0x8d, 0x89, 0xfb, 0xab, + 0x05, 0x64, 0x0c, 0x11, 0x7d, 0xaa, 0x7d, 0x65, 0xb8, 0xca, 0xcc, 0x4e, + 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, + 0x14, 0xc0, 0x7a, 0x98, 0x68, 0x8d, 0x89, 0xfb, 0xab, 0x05, 0x64, 0x0c, + 0x11, 0x7d, 0xaa, 0x7d, 0x65, 0xb8, 0xca, 0xcc, 0x4e, 0x30, 0x0d, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, + 0x03, 0x82, 0x01, 0x01, 0x00, 0x35, 0xe3, 0x29, 0x6a, 0xe5, 0x2f, 0x5d, + 0x54, 0x8e, 0x29, 0x50, 0x94, 0x9f, 0x99, 0x1a, 0x14, 0xe4, 0x8f, 0x78, + 0x2a, 0x62, 0x94, 0xa2, 0x27, 0x67, 0x9e, 0xd0, 0xcf, 0x1a, 0x5e, 0x47, + 0xe9, 0xc1, 0xb2, 0xa4, 0xcf, 0xdd, 0x41, 0x1a, 0x05, 0x4e, 0x9b, 0x4b, + 0xee, 0x4a, 0x6f, 0x55, 0x52, 0xb3, 0x24, 0xa1, 0x37, 0x0a, 0xeb, 0x64, + 0x76, 0x2a, 0x2e, 0x2c, 0xf3, 0xfd, 0x3b, 0x75, 0x90, 0xbf, 0xfa, 0x71, + 0xd8, 0xc7, 0x3d, 0x37, 0xd2, 0xb5, 0x05, 0x95, 0x62, 0xb9, 0xa6, 0xde, + 0x89, 0x3d, 0x36, 0x7b, 0x38, 0x77, 0x48, 0x97, 0xac, 0xa6, 0x20, 0x8f, + 0x2e, 0xa6, 0xc9, 0x0c, 0xc2, 0xb2, 0x99, 0x45, 0x00, 0xc7, 0xce, 0x11, + 0x51, 0x22, 0x22, 0xe0, 0xa5, 0xea, 0xb6, 0x15, 0x48, 0x09, 0x64, 0xea, + 0x5e, 0x4f, 0x74, 0xf7, 0x05, 0x3e, 0xc7, 0x8a, 0x52, 0x0c, 0xdb, 0x15, + 0xb4, 0xbd, 0x6d, 0x9b, 0xe5, 0xc6, 0xb1, 0x54, 0x68, 0xa9, 0xe3, 0x69, + 0x90, 0xb6, 0x9a, 0xa5, 0x0f, 0xb8, 0xb9, 0x3f, 0x20, 0x7d, 0xae, 0x4a, + 0xb5, 0xb8, 0x9c, 0xe4, 0x1d, 0xb6, 0xab, 0xe6, 0x94, 0xa5, 0xc1, 0xc7, + 0x83, 0xad, 0xdb, 0xf5, 0x27, 0x87, 0x0e, 0x04, 0x6c, 0xd5, 0xff, 0xdd, + 0xa0, 0x5d, 0xed, 0x87, 0x52, 0xb7, 0x2b, 0x15, 0x02, 0xae, 0x39, 0xa6, + 0x6a, 0x74, 0xe9, 0xda, 0xc4, 0xe7, 0xbc, 0x4d, 0x34, 0x1e, 0xa9, 0x5c, + 0x4d, 0x33, 0x5f, 0x92, 0x09, 0x2f, 0x88, 0x66, 0x5d, 0x77, 0x97, 0xc7, + 0x1d, 0x76, 0x13, 0xa9, 0xd5, 0xe5, 0xf1, 0x16, 0x09, 0x11, 0x35, 0xd5, + 0xac, 0xdb, 0x24, 0x71, 0x70, 0x2c, 0x98, 0x56, 0x0b, 0xd9, 0x17, 0xb4, + 0xd1, 0xe3, 0x51, 0x2b, 0x5e, 0x75, 0xe8, 0xd5, 0xd0, 0xdc, 0x4f, 0x34, + 0xed, 0xc2, 0x05, 0x66, 0x80, 0xa1, 0xcb, 0xe6, 0x33, 0x30, 0x82, 0x03, + 0xba, 0x30, 0x82, 0x02, 0xa2, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, + 0x3e, 0xa3, 0xe4, 0x78, 0x99, 0x38, 0x13, 0x9d, 0x30, 0x0d, 0x06, 0x09, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, + 0x49, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, + 0x0a, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x31, + 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1c, 0x47, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, + 0x74, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, + 0x47, 0x32, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x37, 0x31, 0x36, + 0x31, 0x32, 0x32, 0x31, 0x34, 0x30, 0x5a, 0x17, 0x0d, 0x31, 0x34, 0x31, + 0x30, 0x31, 0x34, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x69, + 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, + 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, + 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x16, + 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x0d, 0x4d, 0x6f, 0x75, + 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x56, 0x69, 0x65, 0x77, 0x31, 0x13, + 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x47, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x31, 0x18, 0x30, 0x16, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0f, 0x6d, 0x61, 0x69, 0x6c, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x59, 0x30, + 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, + 0xb2, 0x68, 0x6e, 0x3f, 0x03, 0x9e, 0x43, 0x85, 0x16, 0xb7, 0x89, 0x0b, + 0x16, 0x2a, 0xbe, 0x26, 0x36, 0xdd, 0x68, 0x0a, 0x53, 0x4e, 0x20, 0x40, + 0xf8, 0xd1, 0xdd, 0x63, 0xcb, 0x46, 0x73, 0x09, 0x96, 0x36, 0xde, 0x2c, + 0x45, 0x71, 0x2e, 0x8a, 0x79, 0xeb, 0x40, 0x2f, 0x65, 0x83, 0x81, 0xdb, + 0x37, 0x03, 0x84, 0xa1, 0x9a, 0xd0, 0x22, 0x3b, 0x73, 0x38, 0x45, 0xd3, + 0xd5, 0x91, 0xb2, 0x52, 0xa3, 0x82, 0x01, 0x4f, 0x30, 0x82, 0x01, 0x4b, + 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x16, 0x30, 0x14, 0x06, + 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0x06, 0x08, 0x2b, + 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x30, 0x1a, 0x06, 0x03, 0x55, + 0x1d, 0x11, 0x04, 0x13, 0x30, 0x11, 0x82, 0x0f, 0x6d, 0x61, 0x69, 0x6c, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, + 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x07, 0x80, + 0x30, 0x68, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, + 0x04, 0x5c, 0x30, 0x5a, 0x30, 0x2b, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, + 0x05, 0x07, 0x30, 0x02, 0x86, 0x1f, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, + 0x2f, 0x70, 0x6b, 0x69, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x63, 0x6f, 0x6d, 0x2f, 0x47, 0x49, 0x41, 0x47, 0x32, 0x2e, 0x63, 0x72, + 0x74, 0x30, 0x2b, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, + 0x01, 0x86, 0x1f, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x6c, + 0x69, 0x65, 0x6e, 0x74, 0x73, 0x31, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x30, 0x1d, + 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x75, 0xc6, 0xb0, + 0x4a, 0x46, 0x61, 0x83, 0xff, 0x91, 0x46, 0x45, 0x35, 0xa7, 0x0f, 0xd0, + 0x5b, 0xe9, 0xdd, 0x94, 0x1b, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, + 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1f, 0x06, 0x03, 0x55, + 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x4a, 0xdd, 0x06, 0x16, + 0x1b, 0xbc, 0xf6, 0x68, 0xb5, 0x76, 0xf5, 0x81, 0xb6, 0xbb, 0x62, 0x1a, + 0xba, 0x5a, 0x81, 0x2f, 0x30, 0x17, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, + 0x10, 0x30, 0x0e, 0x30, 0x0c, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, + 0xd6, 0x79, 0x02, 0x05, 0x01, 0x30, 0x30, 0x06, 0x03, 0x55, 0x1d, 0x1f, + 0x04, 0x29, 0x30, 0x27, 0x30, 0x25, 0xa0, 0x23, 0xa0, 0x21, 0x86, 0x1f, + 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x70, 0x6b, 0x69, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x47, 0x49, + 0x41, 0x47, 0x32, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x0d, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, + 0x01, 0x01, 0x00, 0x7f, 0x41, 0xf5, 0x57, 0x18, 0x3c, 0x75, 0xf5, 0x23, + 0x66, 0xc3, 0xf0, 0xf2, 0x3e, 0x70, 0x34, 0x56, 0xca, 0x78, 0xec, 0xc7, + 0x81, 0x58, 0x0d, 0xdf, 0xf0, 0xfd, 0x86, 0xe6, 0xe6, 0x50, 0x3d, 0xf6, + 0x09, 0x9a, 0x4d, 0xca, 0x60, 0x37, 0x9a, 0xd4, 0xca, 0x51, 0x7c, 0xf0, + 0x66, 0x23, 0xea, 0x5e, 0x6a, 0x6f, 0x7b, 0xa6, 0x7a, 0x38, 0x97, 0x42, + 0x58, 0x1a, 0x1b, 0x42, 0xae, 0x28, 0xde, 0x18, 0x7f, 0xcc, 0x76, 0x18, + 0x58, 0x05, 0xbf, 0xea, 0xef, 0x14, 0xad, 0x34, 0xe5, 0x5f, 0x25, 0xab, + 0xa1, 0x5f, 0x78, 0x5b, 0x6f, 0xe6, 0x69, 0xd8, 0x74, 0x8c, 0x19, 0x59, + 0xb0, 0x1a, 0xfb, 0x8e, 0xdf, 0x61, 0xac, 0xeb, 0x2b, 0x0a, 0x1c, 0xab, + 0x30, 0x0d, 0x64, 0x25, 0x78, 0xdf, 0x81, 0x71, 0xe3, 0xbd, 0xde, 0x9c, + 0x3f, 0xdd, 0xe9, 0xf8, 0xb6, 0x98, 0x2d, 0x13, 0xa3, 0x7b, 0x14, 0x6f, + 0xe3, 0x8b, 0xfc, 0x4e, 0x31, 0x26, 0xba, 0x10, 0xb4, 0x12, 0xe9, 0xc9, + 0x49, 0x60, 0xf0, 0xaa, 0x1f, 0x44, 0x68, 0x19, 0xd2, 0xb3, 0xc8, 0x46, + 0x22, 0x6b, 0xe1, 0x21, 0x77, 0xfd, 0x72, 0x33, 0x13, 0x21, 0x27, 0x81, + 0xe4, 0x7a, 0xc9, 0xe4, 0x1c, 0x05, 0x04, 0x73, 0x13, 0xda, 0x47, 0xfe, + 0x59, 0x41, 0x9c, 0x11, 0xc5, 0xf6, 0xb5, 0xd0, 0x01, 0xcb, 0x40, 0x19, + 0xf5, 0xfe, 0xb3, 0x3c, 0x1f, 0x61, 0x8f, 0x4d, 0xdb, 0x81, 0x2a, 0x8a, + 0xed, 0xb8, 0x53, 0xc7, 0x19, 0x6b, 0xfa, 0x8b, 0xfc, 0xe3, 0x2e, 0x12, + 0x4e, 0xbd, 0xc5, 0x44, 0x9d, 0x1c, 0x7f, 0x3b, 0x09, 0x51, 0xd7, 0x0a, + 0x0f, 0x22, 0x0a, 0xfd, 0x8c, 0x90, 0x14, 0xed, 0x10, 0xcb, 0x50, 0xcf, + 0xa5, 0x45, 0xce, 0xb0, 0x21, 0x28, 0xcb, 0xd6, 0xf5, 0x6e, 0xb2, 0x3e, + 0xfa, 0x35, 0x0c, 0x3d, 0x09, 0x0d, 0x81, 0x30, 0x82, 0x04, 0x04, 0x30, + 0x82, 0x02, 0xec, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x02, 0x3a, + 0x69, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x01, 0x05, 0x05, 0x00, 0x30, 0x42, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, + 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, + 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0d, 0x47, 0x65, 0x6f, 0x54, 0x72, 0x75, + 0x73, 0x74, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x1b, 0x30, 0x19, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x12, 0x47, 0x65, 0x6f, 0x54, 0x72, 0x75, + 0x73, 0x74, 0x20, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x43, 0x41, + 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x33, 0x30, 0x34, 0x30, 0x35, 0x31, 0x35, + 0x31, 0x35, 0x35, 0x35, 0x5a, 0x17, 0x0d, 0x31, 0x35, 0x30, 0x34, 0x30, + 0x34, 0x31, 0x35, 0x31, 0x35, 0x35, 0x35, 0x5a, 0x30, 0x49, 0x31, 0x0b, + 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, + 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x47, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x31, 0x25, 0x30, 0x23, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1c, 0x47, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x41, + 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, 0x47, 0x32, 0x30, + 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, + 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0x9c, 0x2a, 0x04, 0x77, + 0x5c, 0xd8, 0x50, 0x91, 0x3a, 0x06, 0xa3, 0x82, 0xe0, 0xd8, 0x50, 0x48, + 0xbc, 0x89, 0x3f, 0xf1, 0x19, 0x70, 0x1a, 0x88, 0x46, 0x7e, 0xe0, 0x8f, + 0xc5, 0xf1, 0x89, 0xce, 0x21, 0xee, 0x5a, 0xfe, 0x61, 0x0d, 0xb7, 0x32, + 0x44, 0x89, 0xa0, 0x74, 0x0b, 0x53, 0x4f, 0x55, 0xa4, 0xce, 0x82, 0x62, + 0x95, 0xee, 0xeb, 0x59, 0x5f, 0xc6, 0xe1, 0x05, 0x80, 0x12, 0xc4, 0x5e, + 0x94, 0x3f, 0xbc, 0x5b, 0x48, 0x38, 0xf4, 0x53, 0xf7, 0x24, 0xe6, 0xfb, + 0x91, 0xe9, 0x15, 0xc4, 0xcf, 0xf4, 0x53, 0x0d, 0xf4, 0x4a, 0xfc, 0x9f, + 0x54, 0xde, 0x7d, 0xbe, 0xa0, 0x6b, 0x6f, 0x87, 0xc0, 0xd0, 0x50, 0x1f, + 0x28, 0x30, 0x03, 0x40, 0xda, 0x08, 0x73, 0x51, 0x6c, 0x7f, 0xff, 0x3a, + 0x3c, 0xa7, 0x37, 0x06, 0x8e, 0xbd, 0x4b, 0x11, 0x04, 0xeb, 0x7d, 0x24, + 0xde, 0xe6, 0xf9, 0xfc, 0x31, 0x71, 0xfb, 0x94, 0xd5, 0x60, 0xf3, 0x2e, + 0x4a, 0xaf, 0x42, 0xd2, 0xcb, 0xea, 0xc4, 0x6a, 0x1a, 0xb2, 0xcc, 0x53, + 0xdd, 0x15, 0x4b, 0x8b, 0x1f, 0xc8, 0x19, 0x61, 0x1f, 0xcd, 0x9d, 0xa8, + 0x3e, 0x63, 0x2b, 0x84, 0x35, 0x69, 0x65, 0x84, 0xc8, 0x19, 0xc5, 0x46, + 0x22, 0xf8, 0x53, 0x95, 0xbe, 0xe3, 0x80, 0x4a, 0x10, 0xc6, 0x2a, 0xec, + 0xba, 0x97, 0x20, 0x11, 0xc7, 0x39, 0x99, 0x10, 0x04, 0xa0, 0xf0, 0x61, + 0x7a, 0x95, 0x25, 0x8c, 0x4e, 0x52, 0x75, 0xe2, 0xb6, 0xed, 0x08, 0xca, + 0x14, 0xfc, 0xce, 0x22, 0x6a, 0xb3, 0x4e, 0xcf, 0x46, 0x03, 0x97, 0x97, + 0x03, 0x7e, 0xc0, 0xb1, 0xde, 0x7b, 0xaf, 0x45, 0x33, 0xcf, 0xba, 0x3e, + 0x71, 0xb7, 0xde, 0xf4, 0x25, 0x25, 0xc2, 0x0d, 0x35, 0x89, 0x9d, 0x9d, + 0xfb, 0x0e, 0x11, 0x79, 0x89, 0x1e, 0x37, 0xc5, 0xaf, 0x8e, 0x72, 0x69, + 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xfb, 0x30, 0x81, 0xf8, 0x30, + 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, + 0xc0, 0x7a, 0x98, 0x68, 0x8d, 0x89, 0xfb, 0xab, 0x05, 0x64, 0x0c, 0x11, + 0x7d, 0xaa, 0x7d, 0x65, 0xb8, 0xca, 0xcc, 0x4e, 0x30, 0x1d, 0x06, 0x03, + 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x4a, 0xdd, 0x06, 0x16, 0x1b, + 0xbc, 0xf6, 0x68, 0xb5, 0x76, 0xf5, 0x81, 0xb6, 0xbb, 0x62, 0x1a, 0xba, + 0x5a, 0x81, 0x2f, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, + 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x00, 0x30, + 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, + 0x02, 0x01, 0x06, 0x30, 0x3a, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x33, + 0x30, 0x31, 0x30, 0x2f, 0xa0, 0x2d, 0xa0, 0x2b, 0x86, 0x29, 0x68, 0x74, + 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e, 0x67, 0x65, 0x6f, + 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x72, + 0x6c, 0x73, 0x2f, 0x67, 0x74, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x2e, + 0x63, 0x72, 0x6c, 0x30, 0x3d, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, + 0x07, 0x01, 0x01, 0x04, 0x31, 0x30, 0x2f, 0x30, 0x2d, 0x06, 0x08, 0x2b, + 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x21, 0x68, 0x74, 0x74, + 0x70, 0x3a, 0x2f, 0x2f, 0x67, 0x74, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, + 0x2d, 0x6f, 0x63, 0x73, 0x70, 0x2e, 0x67, 0x65, 0x6f, 0x74, 0x72, 0x75, + 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x17, 0x06, 0x03, 0x55, 0x1d, + 0x20, 0x04, 0x10, 0x30, 0x0e, 0x30, 0x0c, 0x06, 0x0a, 0x2b, 0x06, 0x01, + 0x04, 0x01, 0xd6, 0x79, 0x02, 0x05, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, + 0x01, 0x01, 0x00, 0x36, 0xd7, 0x06, 0x80, 0x11, 0x27, 0xad, 0x2a, 0x14, + 0x9b, 0x38, 0x77, 0xb3, 0x23, 0xa0, 0x75, 0x58, 0xbb, 0xb1, 0x7e, 0x83, + 0x42, 0xba, 0x72, 0xda, 0x1e, 0xd8, 0x8e, 0x36, 0x06, 0x97, 0xe0, 0xf0, + 0x95, 0x3b, 0x37, 0xfd, 0x1b, 0x42, 0x58, 0xfe, 0x22, 0xc8, 0x6b, 0xbd, + 0x38, 0x5e, 0xd1, 0x3b, 0x25, 0x6e, 0x12, 0xeb, 0x5e, 0x67, 0x76, 0x46, + 0x40, 0x90, 0xda, 0x14, 0xc8, 0x78, 0x0d, 0xed, 0x95, 0x66, 0xda, 0x8e, + 0x86, 0x6f, 0x80, 0xa1, 0xba, 0x56, 0x32, 0x95, 0x86, 0xdc, 0xdc, 0x6a, + 0xca, 0x04, 0x8c, 0x5b, 0x7f, 0xf6, 0xbf, 0xcc, 0x6f, 0x85, 0x03, 0x58, + 0xc3, 0x68, 0x51, 0x13, 0xcd, 0xfd, 0xc8, 0xf7, 0x79, 0x3d, 0x99, 0x35, + 0xf0, 0x56, 0xa3, 0xbd, 0xe0, 0x59, 0xed, 0x4f, 0x44, 0x09, 0xa3, 0x9e, + 0x38, 0x7a, 0xf6, 0x46, 0xd1, 0x1d, 0x12, 0x9d, 0x4f, 0xbe, 0xd0, 0x40, + 0xfc, 0x55, 0xfe, 0x06, 0x5e, 0x3c, 0xda, 0x1c, 0x56, 0xbd, 0x96, 0x51, + 0x7b, 0x6f, 0x57, 0x2a, 0xdb, 0xa2, 0xaa, 0x96, 0xdc, 0x8c, 0x74, 0xc2, + 0x95, 0xbe, 0xf0, 0x6e, 0x95, 0x13, 0xff, 0x17, 0xf0, 0x3c, 0xac, 0xb2, + 0x10, 0x8d, 0xcc, 0x73, 0xfb, 0xe8, 0x8f, 0x02, 0xc6, 0xf0, 0xfb, 0x33, + 0xb3, 0x95, 0x3b, 0xe3, 0xc2, 0xcb, 0x68, 0x58, 0x73, 0xdb, 0xa8, 0x24, + 0x62, 0x3b, 0x06, 0x35, 0x9d, 0x0d, 0xa9, 0x33, 0xbd, 0x78, 0x03, 0x90, + 0x2e, 0x4c, 0x78, 0x5d, 0x50, 0x3a, 0x81, 0xd4, 0xee, 0xa0, 0xc8, 0x70, + 0x38, 0xdc, 0xb2, 0xf9, 0x67, 0xfa, 0x87, 0x40, 0x5d, 0x61, 0xc0, 0x51, + 0x8f, 0x6b, 0x83, 0x6b, 0xcd, 0x05, 0x3a, 0xca, 0xe1, 0xa7, 0x05, 0x78, + 0xfc, 0xca, 0xda, 0x94, 0xd0, 0x2c, 0x08, 0x3d, 0x7e, 0x16, 0x79, 0xc8, + 0xa0, 0x50, 0x20, 0x24, 0x54, 0x33, 0x71, 0x31, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, +}; + +/* kPKCS7Windows is the Equifax root certificate, as exported by Windows 7. */ +static const uint8_t kPKCS7Windows[] = { + 0x30, 0x82, 0x02, 0xb1, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x07, 0x02, 0xa0, 0x82, 0x02, 0xa2, 0x30, 0x82, 0x02, 0x9e, 0x02, + 0x01, 0x01, 0x31, 0x00, 0x30, 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x82, 0x02, 0x86, 0x30, 0x82, 0x02, + 0x82, 0x30, 0x82, 0x01, 0xeb, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, + 0x04, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x01, 0x04, 0x05, 0x00, 0x30, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, + 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x1c, 0x30, 0x1a, 0x06, + 0x03, 0x55, 0x04, 0x0a, 0x13, 0x13, 0x45, 0x71, 0x75, 0x69, 0x66, 0x61, + 0x78, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x49, 0x6e, 0x63, + 0x2e, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1d, + 0x45, 0x71, 0x75, 0x69, 0x66, 0x61, 0x78, 0x20, 0x53, 0x65, 0x63, 0x75, + 0x72, 0x65, 0x20, 0x65, 0x42, 0x75, 0x73, 0x69, 0x6e, 0x65, 0x73, 0x73, + 0x20, 0x43, 0x41, 0x2d, 0x31, 0x30, 0x1e, 0x17, 0x0d, 0x39, 0x39, 0x30, + 0x36, 0x32, 0x31, 0x30, 0x34, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, + 0x32, 0x30, 0x30, 0x36, 0x32, 0x31, 0x30, 0x34, 0x30, 0x30, 0x30, 0x30, + 0x5a, 0x30, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, + 0x0a, 0x13, 0x13, 0x45, 0x71, 0x75, 0x69, 0x66, 0x61, 0x78, 0x20, 0x53, + 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x26, + 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1d, 0x45, 0x71, 0x75, + 0x69, 0x66, 0x61, 0x78, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, + 0x65, 0x42, 0x75, 0x73, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x20, 0x43, 0x41, + 0x2d, 0x31, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, + 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xce, 0x2f, 0x19, 0xbc, 0x17, + 0xb7, 0x77, 0xde, 0x93, 0xa9, 0x5f, 0x5a, 0x0d, 0x17, 0x4f, 0x34, 0x1a, + 0x0c, 0x98, 0xf4, 0x22, 0xd9, 0x59, 0xd4, 0xc4, 0x68, 0x46, 0xf0, 0xb4, + 0x35, 0xc5, 0x85, 0x03, 0x20, 0xc6, 0xaf, 0x45, 0xa5, 0x21, 0x51, 0x45, + 0x41, 0xeb, 0x16, 0x58, 0x36, 0x32, 0x6f, 0xe2, 0x50, 0x62, 0x64, 0xf9, + 0xfd, 0x51, 0x9c, 0xaa, 0x24, 0xd9, 0xf4, 0x9d, 0x83, 0x2a, 0x87, 0x0a, + 0x21, 0xd3, 0x12, 0x38, 0x34, 0x6c, 0x8d, 0x00, 0x6e, 0x5a, 0xa0, 0xd9, + 0x42, 0xee, 0x1a, 0x21, 0x95, 0xf9, 0x52, 0x4c, 0x55, 0x5a, 0xc5, 0x0f, + 0x38, 0x4f, 0x46, 0xfa, 0x6d, 0xf8, 0x2e, 0x35, 0xd6, 0x1d, 0x7c, 0xeb, + 0xe2, 0xf0, 0xb0, 0x75, 0x80, 0xc8, 0xa9, 0x13, 0xac, 0xbe, 0x88, 0xef, + 0x3a, 0x6e, 0xab, 0x5f, 0x2a, 0x38, 0x62, 0x02, 0xb0, 0x12, 0x7b, 0xfe, + 0x8f, 0xa6, 0x03, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x66, 0x30, 0x64, + 0x30, 0x11, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, + 0x01, 0x04, 0x04, 0x03, 0x02, 0x00, 0x07, 0x30, 0x0f, 0x06, 0x03, 0x55, + 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, + 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, + 0x14, 0x4a, 0x78, 0x32, 0x52, 0x11, 0xdb, 0x59, 0x16, 0x36, 0x5e, 0xdf, + 0xc1, 0x14, 0x36, 0x40, 0x6a, 0x47, 0x7c, 0x4c, 0xa1, 0x30, 0x1d, 0x06, + 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x4a, 0x78, 0x32, 0x52, + 0x11, 0xdb, 0x59, 0x16, 0x36, 0x5e, 0xdf, 0xc1, 0x14, 0x36, 0x40, 0x6a, + 0x47, 0x7c, 0x4c, 0xa1, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x04, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x75, + 0x5b, 0xa8, 0x9b, 0x03, 0x11, 0xe6, 0xe9, 0x56, 0x4c, 0xcd, 0xf9, 0xa9, + 0x4c, 0xc0, 0x0d, 0x9a, 0xf3, 0xcc, 0x65, 0x69, 0xe6, 0x25, 0x76, 0xcc, + 0x59, 0xb7, 0xd6, 0x54, 0xc3, 0x1d, 0xcd, 0x99, 0xac, 0x19, 0xdd, 0xb4, + 0x85, 0xd5, 0xe0, 0x3d, 0xfc, 0x62, 0x20, 0xa7, 0x84, 0x4b, 0x58, 0x65, + 0xf1, 0xe2, 0xf9, 0x95, 0x21, 0x3f, 0xf5, 0xd4, 0x7e, 0x58, 0x1e, 0x47, + 0x87, 0x54, 0x3e, 0x58, 0xa1, 0xb5, 0xb5, 0xf8, 0x2a, 0xef, 0x71, 0xe7, + 0xbc, 0xc3, 0xf6, 0xb1, 0x49, 0x46, 0xe2, 0xd7, 0xa0, 0x6b, 0xe5, 0x56, + 0x7a, 0x9a, 0x27, 0x98, 0x7c, 0x46, 0x62, 0x14, 0xe7, 0xc9, 0xfc, 0x6e, + 0x03, 0x12, 0x79, 0x80, 0x38, 0x1d, 0x48, 0x82, 0x8d, 0xfc, 0x17, 0xfe, + 0x2a, 0x96, 0x2b, 0xb5, 0x62, 0xa6, 0xa6, 0x3d, 0xbd, 0x7f, 0x92, 0x59, + 0xcd, 0x5a, 0x2a, 0x82, 0xb2, 0x37, 0x79, 0x31, 0x00, +}; + +/* kOpenSSLCRL is the Equifax CRL, converted to PKCS#7 form by: + * openssl crl2pkcs7 -inform DER -in secureca.crl */ +static const uint8_t kOpenSSLCRL[] = { + 0x30, 0x82, 0x03, 0x85, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x07, 0x02, 0xa0, 0x82, 0x03, 0x76, 0x30, 0x82, 0x03, 0x72, 0x02, + 0x01, 0x01, 0x31, 0x00, 0x30, 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x00, 0xa1, 0x82, 0x03, 0x58, 0x30, + 0x82, 0x03, 0x54, 0x30, 0x82, 0x02, 0xbd, 0x30, 0x0d, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x4e, + 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, + 0x53, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x07, + 0x45, 0x71, 0x75, 0x69, 0x66, 0x61, 0x78, 0x31, 0x2d, 0x30, 0x2b, 0x06, + 0x03, 0x55, 0x04, 0x0b, 0x13, 0x24, 0x45, 0x71, 0x75, 0x69, 0x66, 0x61, + 0x78, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, + 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x17, 0x0d, 0x31, 0x35, 0x30, 0x32, + 0x32, 0x37, 0x30, 0x31, 0x32, 0x33, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x31, + 0x35, 0x30, 0x33, 0x30, 0x39, 0x30, 0x31, 0x32, 0x33, 0x30, 0x30, 0x5a, + 0x30, 0x82, 0x02, 0x3c, 0x30, 0x14, 0x02, 0x03, 0x0f, 0x58, 0xe4, 0x17, + 0x0d, 0x31, 0x34, 0x30, 0x34, 0x32, 0x37, 0x30, 0x38, 0x31, 0x39, 0x32, + 0x32, 0x5a, 0x30, 0x14, 0x02, 0x03, 0x14, 0x76, 0x19, 0x17, 0x0d, 0x31, + 0x34, 0x30, 0x36, 0x31, 0x38, 0x31, 0x35, 0x30, 0x30, 0x30, 0x33, 0x5a, + 0x30, 0x14, 0x02, 0x03, 0x0f, 0x9a, 0xfb, 0x17, 0x0d, 0x31, 0x34, 0x30, + 0x34, 0x32, 0x39, 0x31, 0x38, 0x30, 0x39, 0x31, 0x37, 0x5a, 0x30, 0x14, + 0x02, 0x03, 0x14, 0x8b, 0xc0, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x37, 0x30, + 0x39, 0x31, 0x39, 0x34, 0x36, 0x33, 0x33, 0x5a, 0x30, 0x14, 0x02, 0x03, + 0x14, 0xe4, 0x9c, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x34, 0x31, 0x36, 0x32, + 0x33, 0x33, 0x39, 0x33, 0x35, 0x5a, 0x30, 0x14, 0x02, 0x03, 0x0f, 0x86, + 0x07, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x35, 0x32, 0x31, 0x31, 0x35, 0x35, + 0x30, 0x35, 0x33, 0x5a, 0x30, 0x14, 0x02, 0x03, 0x12, 0xe2, 0x29, 0x17, + 0x0d, 0x31, 0x34, 0x30, 0x36, 0x31, 0x37, 0x31, 0x38, 0x35, 0x35, 0x31, + 0x35, 0x5a, 0x30, 0x14, 0x02, 0x03, 0x0d, 0x42, 0x66, 0x17, 0x0d, 0x31, + 0x32, 0x30, 0x36, 0x32, 0x37, 0x31, 0x37, 0x31, 0x30, 0x35, 0x33, 0x5a, + 0x30, 0x14, 0x02, 0x03, 0x03, 0x1e, 0x33, 0x17, 0x0d, 0x30, 0x32, 0x30, + 0x35, 0x31, 0x35, 0x31, 0x33, 0x30, 0x36, 0x31, 0x31, 0x5a, 0x30, 0x14, + 0x02, 0x03, 0x12, 0xe2, 0x23, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x36, 0x30, + 0x36, 0x32, 0x30, 0x34, 0x30, 0x32, 0x31, 0x5a, 0x30, 0x14, 0x02, 0x03, + 0x13, 0x9c, 0xab, 0x17, 0x0d, 0x31, 0x30, 0x30, 0x37, 0x32, 0x39, 0x31, + 0x36, 0x34, 0x34, 0x33, 0x39, 0x5a, 0x30, 0x14, 0x02, 0x03, 0x12, 0xc6, + 0x0a, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x36, 0x30, 0x36, 0x32, 0x32, 0x32, + 0x31, 0x33, 0x39, 0x5a, 0x30, 0x14, 0x02, 0x03, 0x03, 0x25, 0x85, 0x17, + 0x0d, 0x30, 0x32, 0x30, 0x35, 0x31, 0x34, 0x31, 0x38, 0x31, 0x31, 0x35, + 0x37, 0x5a, 0x30, 0x14, 0x02, 0x03, 0x14, 0x86, 0xe6, 0x17, 0x0d, 0x31, + 0x34, 0x30, 0x37, 0x32, 0x35, 0x30, 0x32, 0x30, 0x30, 0x33, 0x38, 0x5a, + 0x30, 0x14, 0x02, 0x03, 0x13, 0x9c, 0xa1, 0x17, 0x0d, 0x31, 0x30, 0x30, + 0x37, 0x32, 0x39, 0x31, 0x36, 0x34, 0x37, 0x33, 0x32, 0x5a, 0x30, 0x14, + 0x02, 0x03, 0x15, 0x4d, 0x5c, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x34, 0x33, + 0x30, 0x30, 0x30, 0x30, 0x34, 0x34, 0x32, 0x5a, 0x30, 0x14, 0x02, 0x03, + 0x0f, 0xfa, 0x2d, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x36, 0x31, 0x37, 0x31, + 0x38, 0x35, 0x30, 0x31, 0x31, 0x5a, 0x30, 0x14, 0x02, 0x03, 0x13, 0x75, + 0x55, 0x17, 0x0d, 0x31, 0x35, 0x30, 0x31, 0x31, 0x38, 0x30, 0x32, 0x32, + 0x31, 0x33, 0x33, 0x5a, 0x30, 0x14, 0x02, 0x03, 0x0f, 0x56, 0x96, 0x17, + 0x0d, 0x31, 0x34, 0x30, 0x36, 0x32, 0x34, 0x31, 0x32, 0x33, 0x31, 0x30, + 0x32, 0x5a, 0x30, 0x14, 0x02, 0x03, 0x0b, 0x80, 0x8a, 0x17, 0x0d, 0x31, + 0x32, 0x30, 0x36, 0x32, 0x37, 0x31, 0x37, 0x31, 0x30, 0x32, 0x35, 0x5a, + 0x30, 0x14, 0x02, 0x03, 0x0f, 0x94, 0x16, 0x17, 0x0d, 0x31, 0x30, 0x30, + 0x33, 0x30, 0x31, 0x31, 0x33, 0x34, 0x35, 0x33, 0x31, 0x5a, 0x30, 0x14, + 0x02, 0x03, 0x14, 0x16, 0xb3, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x36, 0x31, + 0x38, 0x31, 0x34, 0x33, 0x32, 0x35, 0x36, 0x5a, 0x30, 0x14, 0x02, 0x03, + 0x0a, 0xe1, 0x85, 0x17, 0x0d, 0x31, 0x32, 0x30, 0x36, 0x32, 0x37, 0x31, + 0x37, 0x31, 0x30, 0x31, 0x37, 0x5a, 0x30, 0x14, 0x02, 0x03, 0x14, 0xcc, + 0x3e, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x37, 0x31, 0x31, 0x31, 0x32, 0x35, + 0x35, 0x33, 0x31, 0x5a, 0x30, 0x14, 0x02, 0x03, 0x10, 0x5b, 0xcb, 0x17, + 0x0d, 0x31, 0x30, 0x30, 0x37, 0x33, 0x30, 0x32, 0x31, 0x33, 0x31, 0x32, + 0x30, 0x5a, 0x30, 0x14, 0x02, 0x03, 0x15, 0x6a, 0x1f, 0x17, 0x0d, 0x31, + 0x34, 0x30, 0x32, 0x32, 0x36, 0x31, 0x32, 0x33, 0x35, 0x31, 0x39, 0x5a, + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, + 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x1d, 0x5c, 0x27, 0x07, 0x11, + 0x03, 0xf2, 0x00, 0xbd, 0xf4, 0x46, 0x3e, 0x71, 0xfd, 0x10, 0x84, 0x83, + 0xd9, 0xd2, 0xd2, 0x19, 0xa0, 0x20, 0xf7, 0x1a, 0x43, 0x3d, 0xac, 0xda, + 0x33, 0xfc, 0xb7, 0x42, 0x60, 0x1a, 0xa4, 0xa8, 0xb2, 0x07, 0x5c, 0x51, + 0x16, 0xc0, 0x42, 0x80, 0x0a, 0x0f, 0xf0, 0x47, 0x5b, 0x4b, 0x78, 0x90, + 0xaf, 0xc7, 0xac, 0x48, 0xf8, 0xca, 0x3c, 0x13, 0x5e, 0xf6, 0xd1, 0x88, + 0xae, 0x55, 0xa3, 0x0c, 0x8a, 0x62, 0x47, 0x29, 0xf8, 0x72, 0xb8, 0x24, + 0x17, 0xaf, 0xb2, 0x06, 0x1e, 0xa7, 0x72, 0x76, 0xab, 0x96, 0x1d, 0xe0, + 0x7c, 0xd4, 0x0c, 0x42, 0x82, 0x3d, 0x4a, 0x8e, 0x15, 0x77, 0x2f, 0x3c, + 0x2a, 0x8c, 0x3a, 0x04, 0x10, 0x55, 0xdc, 0xbb, 0xba, 0xb1, 0x91, 0xee, + 0x7b, 0xe7, 0x23, 0xc5, 0x71, 0x13, 0xae, 0x6b, 0x21, 0x35, 0xd3, 0x64, + 0xf0, 0x00, 0x54, 0x31, 0x00, +}; + +/* kPEMCert is the result of exporting the mail.google.com certificate from + * Chrome and then running it through: + * openssl pkcs7 -inform DER -in mail.google.com -outform PEM */ +static const char kPEMCert[] = + "-----BEGIN PKCS7-----\n" + "MIID+wYJKoZIhvcNAQcCoIID7DCCA+gCAQExADALBgkqhkiG9w0BBwGgggPQMIID\n" + "zDCCArSgAwIBAgIIWesoywKxoNQwDQYJKoZIhvcNAQELBQAwSTELMAkGA1UEBhMC\n" + "VVMxEzARBgNVBAoTCkdvb2dsZSBJbmMxJTAjBgNVBAMTHEdvb2dsZSBJbnRlcm5l\n" + "dCBBdXRob3JpdHkgRzIwHhcNMTUwMjExMTQxNTA2WhcNMTUwNTEyMDAwMDAwWjBp\n" + "MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91\n" + "bnRhaW4gVmlldzETMBEGA1UECgwKR29vZ2xlIEluYzEYMBYGA1UEAwwPbWFpbC5n\n" + "b29nbGUuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE7MdALmCkcRRf/tzQ\n" + "a8eu3J7S5CTQa5ns0ReF9ktlbB1RL56BVGAu4p7BrT32D6gDpiggXq3gxN81A0TG\n" + "C2yICKOCAWEwggFdMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAsBgNV\n" + "HREEJTAjgg9tYWlsLmdvb2dsZS5jb22CEGluYm94Lmdvb2dsZS5jb20wCwYDVR0P\n" + "BAQDAgeAMGgGCCsGAQUFBwEBBFwwWjArBggrBgEFBQcwAoYfaHR0cDovL3BraS5n\n" + "b29nbGUuY29tL0dJQUcyLmNydDArBggrBgEFBQcwAYYfaHR0cDovL2NsaWVudHMx\n" + "Lmdvb2dsZS5jb20vb2NzcDAdBgNVHQ4EFgQUQqsYsRoWLiG6qmV2N1mpYaHawxAw\n" + "DAYDVR0TAQH/BAIwADAfBgNVHSMEGDAWgBRK3QYWG7z2aLV29YG2u2IaulqBLzAX\n" + "BgNVHSAEEDAOMAwGCisGAQQB1nkCBQEwMAYDVR0fBCkwJzAloCOgIYYfaHR0cDov\n" + "L3BraS5nb29nbGUuY29tL0dJQUcyLmNybDANBgkqhkiG9w0BAQsFAAOCAQEAKNh3\n" + "isNuGBisPKVlekOsZR6S8oP/fS/xt6Hqvg0EwFXvhxoJ40rxAB2LMykY17e+ln3P\n" + "MwBBlRkwY1btcDT15JwzgaZb38rq/r+Pkb5Qgmx/InA/pw0QHDtwHQp5uXZuvu6p\n" + "J/SlCwyq7EOvByWdVQcMU/dhGa3idXEkn/zwfqcG6YjdWKoDmXWZYv3RiP3wJcRB\n" + "9+3U1wOe3uebnZLRWO6/w0to1XY8TFHklyw5rwIE5sbxOx5N3Ne8+GgPrUDvGAz0\n" + "rAUKnh3b7GNXL1qlZh2qkhB6rUzvtPpg397Asg3xVtExCHOk4zPqzzicttoEbVVy\n" + "0T8rIMUNwC4Beh4JVjEA\n" + "-----END PKCS7-----\n"; + +/* kPEMCRL is the result of downloading the Equifax CRL and running: + openssl crl2pkcs7 -inform DER -in secureca.crl */ +static const char kPEMCRL[] = + "-----BEGIN PKCS7-----\n" + "MIIDhQYJKoZIhvcNAQcCoIIDdjCCA3ICAQExADALBgkqhkiG9w0BBwGgAKGCA1gw\n" + "ggNUMIICvTANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEQMA4GA1UEChMH\n" + "RXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlmaWNhdGUgQXV0\n" + "aG9yaXR5Fw0xNTAyMjcwMTIzMDBaFw0xNTAzMDkwMTIzMDBaMIICPDAUAgMPWOQX\n" + "DTE0MDQyNzA4MTkyMlowFAIDFHYZFw0xNDA2MTgxNTAwMDNaMBQCAw+a+xcNMTQw\n" + "NDI5MTgwOTE3WjAUAgMUi8AXDTE0MDcwOTE5NDYzM1owFAIDFOScFw0xNDA0MTYy\n" + "MzM5MzVaMBQCAw+GBxcNMTQwNTIxMTU1MDUzWjAUAgMS4ikXDTE0MDYxNzE4NTUx\n" + "NVowFAIDDUJmFw0xMjA2MjcxNzEwNTNaMBQCAwMeMxcNMDIwNTE1MTMwNjExWjAU\n" + "AgMS4iMXDTE0MDYwNjIwNDAyMVowFAIDE5yrFw0xMDA3MjkxNjQ0MzlaMBQCAxLG\n" + "ChcNMTQwNjA2MjIyMTM5WjAUAgMDJYUXDTAyMDUxNDE4MTE1N1owFAIDFIbmFw0x\n" + "NDA3MjUwMjAwMzhaMBQCAxOcoRcNMTAwNzI5MTY0NzMyWjAUAgMVTVwXDTE0MDQz\n" + "MDAwMDQ0MlowFAIDD/otFw0xNDA2MTcxODUwMTFaMBQCAxN1VRcNMTUwMTE4MDIy\n" + "MTMzWjAUAgMPVpYXDTE0MDYyNDEyMzEwMlowFAIDC4CKFw0xMjA2MjcxNzEwMjVa\n" + "MBQCAw+UFhcNMTAwMzAxMTM0NTMxWjAUAgMUFrMXDTE0MDYxODE0MzI1NlowFAID\n" + "CuGFFw0xMjA2MjcxNzEwMTdaMBQCAxTMPhcNMTQwNzExMTI1NTMxWjAUAgMQW8sX\n" + "DTEwMDczMDIxMzEyMFowFAIDFWofFw0xNDAyMjYxMjM1MTlaMA0GCSqGSIb3DQEB\n" + "BQUAA4GBAB1cJwcRA/IAvfRGPnH9EISD2dLSGaAg9xpDPazaM/y3QmAapKiyB1xR\n" + "FsBCgAoP8EdbS3iQr8esSPjKPBNe9tGIrlWjDIpiRyn4crgkF6+yBh6ncnarlh3g\n" + "fNQMQoI9So4Vdy88Kow6BBBV3Lu6sZHue+cjxXETrmshNdNk8ABUMQA=\n" + "-----END PKCS7-----\n"; + +static int test_cert_reparse(const uint8_t *der_bytes, size_t der_len) { + CBS pkcs7; + CBB cbb; + STACK_OF(X509) *certs = sk_X509_new_null(); + STACK_OF(X509) *certs2 = sk_X509_new_null(); + uint8_t *result_data, *result2_data; + size_t result_len, result2_len, i; + + CBS_init(&pkcs7, der_bytes, der_len); + if (!PKCS7_get_certificates(certs, &pkcs7)) { + fprintf(stderr, "PKCS7_get_certificates failed.\n"); + return 0; + } + + CBB_init(&cbb, der_len); + if (!PKCS7_bundle_certificates(&cbb, certs) || + !CBB_finish(&cbb, &result_data, &result_len)) { + fprintf(stderr, "PKCS7_bundle_certificates failed.\n"); + return 0; + } + + CBS_init(&pkcs7, result_data, result_len); + if (!PKCS7_get_certificates(certs2, &pkcs7)) { + fprintf(stderr, "PKCS7_get_certificates reparse failed.\n"); + return 0; + } + + if (sk_X509_num(certs) != sk_X509_num(certs2)) { + fprintf(stderr, "Number of certs in results differ.\n"); + return 0; + } + + for (i = 0; i < sk_X509_num(certs); i++) { + X509 *a = sk_X509_value(certs, i); + X509 *b = sk_X509_value(certs2, i); + + if (X509_cmp(a, b) != 0) { + fprintf(stderr, "Certificate %zu differs.\n", i); + return 0; + } + } + + CBB_init(&cbb, der_len); + if (!PKCS7_bundle_certificates(&cbb, certs2) || + !CBB_finish(&cbb, &result2_data, &result2_len)) { + fprintf(stderr, + "PKCS7_bundle_certificates failed the second time.\n"); + return 0; + } + + if (result_len != result2_len || + memcmp(result_data, result2_data, result_len) != 0) { + fprintf(stderr, "Serialisation is not stable.\n"); + return 0; + } + + OPENSSL_free(result_data); + OPENSSL_free(result2_data); + sk_X509_pop_free(certs, X509_free); + sk_X509_pop_free(certs2, X509_free); + + return 1; +} + +static int test_crl_reparse(const uint8_t *der_bytes, size_t der_len) { + CBS pkcs7; + CBB cbb; + STACK_OF(X509_CRL) *crls = sk_X509_CRL_new_null(); + STACK_OF(X509_CRL) *crls2 = sk_X509_CRL_new_null(); + uint8_t *result_data, *result2_data; + size_t result_len, result2_len, i; + + CBS_init(&pkcs7, der_bytes, der_len); + if (!PKCS7_get_CRLs(crls, &pkcs7)) { + fprintf(stderr, "PKCS7_get_CRLs failed.\n"); + return 0; + } + + CBB_init(&cbb, der_len); + if (!PKCS7_bundle_CRLs(&cbb, crls) || + !CBB_finish(&cbb, &result_data, &result_len)) { + fprintf(stderr, "PKCS7_bundle_CRLs failed.\n"); + return 0; + } + + CBS_init(&pkcs7, result_data, result_len); + if (!PKCS7_get_CRLs(crls2, &pkcs7)) { + fprintf(stderr, "PKCS7_get_CRLs reparse failed.\n"); + return 0; + } + + if (sk_X509_CRL_num(crls) != sk_X509_CRL_num(crls)) { + fprintf(stderr, "Number of CRLs in results differ.\n"); + return 0; + } + + for (i = 0; i < sk_X509_CRL_num(crls); i++) { + X509_CRL *a = sk_X509_CRL_value(crls, i); + X509_CRL *b = sk_X509_CRL_value(crls2, i); + + if (X509_CRL_cmp(a, b) != 0) { + fprintf(stderr, "CRL %zu differs.\n", i); + return 0; + } + } + + CBB_init(&cbb, der_len); + if (!PKCS7_bundle_CRLs(&cbb, crls2) || + !CBB_finish(&cbb, &result2_data, &result2_len)) { + fprintf(stderr, + "PKCS7_bundle_CRLs failed the second time.\n"); + return 0; + } + + if (result_len != result2_len || + memcmp(result_data, result2_data, result_len) != 0) { + fprintf(stderr, "Serialisation is not stable.\n"); + return 0; + } + + OPENSSL_free(result_data); + OPENSSL_free(result2_data); + sk_X509_CRL_pop_free(crls, X509_CRL_free); + sk_X509_CRL_pop_free(crls2, X509_CRL_free); + + return 1; +} + +static int test_pem_certs(const char *pem) { + BIO *bio = BIO_new_mem_buf(pem, strlen(pem)); + STACK_OF(X509) *certs = sk_X509_new_null(); + + if (!PKCS7_get_PEM_certificates(certs, bio)) { + fprintf(stderr, "PKCS7_get_PEM_certificates failed.\n"); + return 0; + } + + if (sk_X509_num(certs) != 1) { + fprintf(stderr, + "Bad number of certificates from PKCS7_get_PEM_certificates: %zu\n", + sk_X509_num(certs)); + return 0; + } + + BIO_free(bio); + sk_X509_pop_free(certs, X509_free); + + return 1; +} + +static int test_pem_crls(const char *pem) { + BIO *bio = BIO_new_mem_buf(pem, strlen(pem)); + STACK_OF(X509_CRL) *crls = sk_X509_CRL_new_null(); + + if (!PKCS7_get_PEM_CRLs(crls, bio)) { + fprintf(stderr, "PKCS7_get_PEM_CRLs failed.\n"); + return 0; + } + + if (sk_X509_CRL_num(crls) != 1) { + fprintf(stderr, "Bad number of CRLs from PKCS7_get_PEM_CRLs: %zu\n", + sk_X509_CRL_num(crls)); + return 0; + } + + BIO_free(bio); + sk_X509_CRL_pop_free(crls, X509_CRL_free); + + return 1; +} + +int main(void) { + CRYPTO_library_init(); + + if (!test_cert_reparse(kPKCS7NSS, sizeof(kPKCS7NSS)) || + !test_cert_reparse(kPKCS7Windows, sizeof(kPKCS7Windows)) || + !test_crl_reparse(kOpenSSLCRL, sizeof(kOpenSSLCRL)) || + !test_pem_certs(kPEMCert) || + !test_pem_crls(kPEMCRL)) { + return 1; + } + + printf("PASS\n"); + return 0; +} diff --git a/external/boringssl/crypto/x509/rsa_pss.c b/external/boringssl/crypto/x509/rsa_pss.c new file mode 100644 index 0000000000..1ae01a3d26 --- /dev/null +++ b/external/boringssl/crypto/x509/rsa_pss.c @@ -0,0 +1,385 @@ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 2006. + */ +/* ==================================================================== + * Copyright (c) 2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include "internal.h" + + +ASN1_SEQUENCE(RSA_PSS_PARAMS) = { + ASN1_EXP_OPT(RSA_PSS_PARAMS, hashAlgorithm, X509_ALGOR,0), + ASN1_EXP_OPT(RSA_PSS_PARAMS, maskGenAlgorithm, X509_ALGOR,1), + ASN1_EXP_OPT(RSA_PSS_PARAMS, saltLength, ASN1_INTEGER,2), + ASN1_EXP_OPT(RSA_PSS_PARAMS, trailerField, ASN1_INTEGER,3), +} ASN1_SEQUENCE_END(RSA_PSS_PARAMS); + +IMPLEMENT_ASN1_FUNCTIONS(RSA_PSS_PARAMS); + + +/* Given an MGF1 Algorithm ID decode to an Algorithm Identifier */ +static X509_ALGOR *rsa_mgf1_decode(X509_ALGOR *alg) { + if (alg == NULL || alg->parameter == NULL || + OBJ_obj2nid(alg->algorithm) != NID_mgf1 || + alg->parameter->type != V_ASN1_SEQUENCE) { + return NULL; + } + + const uint8_t *p = alg->parameter->value.sequence->data; + int plen = alg->parameter->value.sequence->length; + return d2i_X509_ALGOR(NULL, &p, plen); +} + +static RSA_PSS_PARAMS *rsa_pss_decode(const X509_ALGOR *alg, + X509_ALGOR **pmaskHash) { + *pmaskHash = NULL; + + if (alg->parameter == NULL || alg->parameter->type != V_ASN1_SEQUENCE) { + return NULL; + } + + const uint8_t *p = alg->parameter->value.sequence->data; + int plen = alg->parameter->value.sequence->length; + RSA_PSS_PARAMS *pss = d2i_RSA_PSS_PARAMS(NULL, &p, plen); + if (pss == NULL) { + return NULL; + } + + *pmaskHash = rsa_mgf1_decode(pss->maskGenAlgorithm); + return pss; +} + +/* allocate and set algorithm ID from EVP_MD, default SHA1 */ +static int rsa_md_to_algor(X509_ALGOR **palg, const EVP_MD *md) { + if (EVP_MD_type(md) == NID_sha1) { + return 1; + } + *palg = X509_ALGOR_new(); + if (*palg == NULL) { + return 0; + } + X509_ALGOR_set_md(*palg, md); + return 1; +} + +/* Allocate and set MGF1 algorithm ID from EVP_MD */ +static int rsa_md_to_mgf1(X509_ALGOR **palg, const EVP_MD *mgf1md) { + X509_ALGOR *algtmp = NULL; + ASN1_STRING *stmp = NULL; + *palg = NULL; + + if (EVP_MD_type(mgf1md) == NID_sha1) { + return 1; + } + /* need to embed algorithm ID inside another */ + if (!rsa_md_to_algor(&algtmp, mgf1md) || + !ASN1_item_pack(algtmp, ASN1_ITEM_rptr(X509_ALGOR), &stmp)) { + goto err; + } + *palg = X509_ALGOR_new(); + if (!*palg) { + goto err; + } + X509_ALGOR_set0(*palg, OBJ_nid2obj(NID_mgf1), V_ASN1_SEQUENCE, stmp); + stmp = NULL; + +err: + ASN1_STRING_free(stmp); + X509_ALGOR_free(algtmp); + if (*palg) { + return 1; + } + + return 0; +} + +/* convert algorithm ID to EVP_MD, default SHA1 */ +static const EVP_MD *rsa_algor_to_md(X509_ALGOR *alg) { + const EVP_MD *md; + if (!alg) { + return EVP_sha1(); + } + md = EVP_get_digestbyobj(alg->algorithm); + if (md == NULL) { + OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS); + } + return md; +} + +/* convert MGF1 algorithm ID to EVP_MD, default SHA1 */ +static const EVP_MD *rsa_mgf1_to_md(X509_ALGOR *alg, X509_ALGOR *maskHash) { + const EVP_MD *md; + if (!alg) { + return EVP_sha1(); + } + /* Check mask and lookup mask hash algorithm */ + if (OBJ_obj2nid(alg->algorithm) != NID_mgf1 || + maskHash == NULL) { + OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS); + return NULL; + } + md = EVP_get_digestbyobj(maskHash->algorithm); + if (md == NULL) { + OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS); + return NULL; + } + return md; +} + +int x509_rsa_ctx_to_pss(EVP_MD_CTX *ctx, X509_ALGOR *algor) { + const EVP_MD *sigmd, *mgf1md; + int saltlen; + if (!EVP_PKEY_CTX_get_signature_md(ctx->pctx, &sigmd) || + !EVP_PKEY_CTX_get_rsa_mgf1_md(ctx->pctx, &mgf1md) || + !EVP_PKEY_CTX_get_rsa_pss_saltlen(ctx->pctx, &saltlen)) { + return 0; + } + + EVP_PKEY *pk = EVP_PKEY_CTX_get0_pkey(ctx->pctx); + if (saltlen == -1) { + saltlen = EVP_MD_size(sigmd); + } else if (saltlen == -2) { + saltlen = EVP_PKEY_size(pk) - EVP_MD_size(sigmd) - 2; + if (((EVP_PKEY_bits(pk) - 1) & 0x7) == 0) { + saltlen--; + } + } else { + return 0; + } + + int ret = 0; + ASN1_STRING *os = NULL; + RSA_PSS_PARAMS *pss = RSA_PSS_PARAMS_new(); + if (!pss) { + goto err; + } + + if (saltlen != 20) { + pss->saltLength = ASN1_INTEGER_new(); + if (!pss->saltLength || + !ASN1_INTEGER_set(pss->saltLength, saltlen)) { + goto err; + } + } + + if (!rsa_md_to_algor(&pss->hashAlgorithm, sigmd) || + !rsa_md_to_mgf1(&pss->maskGenAlgorithm, mgf1md)) { + goto err; + } + + /* Finally create string with pss parameter encoding. */ + if (!ASN1_item_pack(pss, ASN1_ITEM_rptr(RSA_PSS_PARAMS), &os)) { + goto err; + } + + X509_ALGOR_set0(algor, OBJ_nid2obj(NID_rsassaPss), V_ASN1_SEQUENCE, os); + os = NULL; + ret = 1; + +err: + RSA_PSS_PARAMS_free(pss); + ASN1_STRING_free(os); + return ret; +} + +int x509_rsa_pss_to_ctx(EVP_MD_CTX *ctx, X509_ALGOR *sigalg, EVP_PKEY *pkey) { + assert(OBJ_obj2nid(sigalg->algorithm) == NID_rsassaPss); + + /* Decode PSS parameters */ + int ret = 0; + X509_ALGOR *maskHash; + RSA_PSS_PARAMS *pss = rsa_pss_decode(sigalg, &maskHash); + if (pss == NULL) { + OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS); + goto err; + } + + const EVP_MD *mgf1md = rsa_mgf1_to_md(pss->maskGenAlgorithm, maskHash); + const EVP_MD *md = rsa_algor_to_md(pss->hashAlgorithm); + if (mgf1md == NULL || md == NULL) { + goto err; + } + + int saltlen = 20; + if (pss->saltLength != NULL) { + saltlen = ASN1_INTEGER_get(pss->saltLength); + + /* Could perform more salt length sanity checks but the main + * RSA routines will trap other invalid values anyway. */ + if (saltlen < 0) { + OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS); + goto err; + } + } + + /* low-level routines support only trailer field 0xbc (value 1) + * and PKCS#1 says we should reject any other value anyway. */ + if (pss->trailerField != NULL && ASN1_INTEGER_get(pss->trailerField) != 1) { + OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS); + goto err; + } + + EVP_PKEY_CTX *pkctx; + if (!EVP_DigestVerifyInit(ctx, &pkctx, md, NULL, pkey) || + !EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_PSS_PADDING) || + !EVP_PKEY_CTX_set_rsa_pss_saltlen(pkctx, saltlen) || + !EVP_PKEY_CTX_set_rsa_mgf1_md(pkctx, mgf1md)) { + goto err; + } + + ret = 1; + +err: + RSA_PSS_PARAMS_free(pss); + X509_ALGOR_free(maskHash); + return ret; +} + +int x509_print_rsa_pss_params(BIO *bp, const X509_ALGOR *sigalg, int indent, + ASN1_PCTX *pctx) { + assert(OBJ_obj2nid(sigalg->algorithm) == NID_rsassaPss); + + int rv = 0; + X509_ALGOR *maskHash; + RSA_PSS_PARAMS *pss = rsa_pss_decode(sigalg, &maskHash); + if (!pss) { + if (BIO_puts(bp, " (INVALID PSS PARAMETERS)\n") <= 0) { + goto err; + } + rv = 1; + goto err; + } + + if (BIO_puts(bp, "\n") <= 0 || + !BIO_indent(bp, indent, 128) || + BIO_puts(bp, "Hash Algorithm: ") <= 0) { + goto err; + } + + if (pss->hashAlgorithm) { + if (i2a_ASN1_OBJECT(bp, pss->hashAlgorithm->algorithm) <= 0) { + goto err; + } + } else if (BIO_puts(bp, "sha1 (default)") <= 0) { + goto err; + } + + if (BIO_puts(bp, "\n") <= 0 || + !BIO_indent(bp, indent, 128) || + BIO_puts(bp, "Mask Algorithm: ") <= 0) { + goto err; + } + + if (pss->maskGenAlgorithm) { + if (i2a_ASN1_OBJECT(bp, pss->maskGenAlgorithm->algorithm) <= 0 || + BIO_puts(bp, " with ") <= 0) { + goto err; + } + + if (maskHash) { + if (i2a_ASN1_OBJECT(bp, maskHash->algorithm) <= 0) { + goto err; + } + } else if (BIO_puts(bp, "INVALID") <= 0) { + goto err; + } + } else if (BIO_puts(bp, "mgf1 with sha1 (default)") <= 0) { + goto err; + } + BIO_puts(bp, "\n"); + + if (!BIO_indent(bp, indent, 128) || + BIO_puts(bp, "Salt Length: 0x") <= 0) { + goto err; + } + + if (pss->saltLength) { + if (i2a_ASN1_INTEGER(bp, pss->saltLength) <= 0) { + goto err; + } + } else if (BIO_puts(bp, "14 (default)") <= 0) { + goto err; + } + BIO_puts(bp, "\n"); + + if (!BIO_indent(bp, indent, 128) || + BIO_puts(bp, "Trailer Field: 0x") <= 0) { + goto err; + } + + if (pss->trailerField) { + if (i2a_ASN1_INTEGER(bp, pss->trailerField) <= 0) { + goto err; + } + } else if (BIO_puts(bp, "BC (default)") <= 0) { + goto err; + } + BIO_puts(bp, "\n"); + + rv = 1; + +err: + RSA_PSS_PARAMS_free(pss); + X509_ALGOR_free(maskHash); + return rv; +} diff --git a/external/boringssl/crypto/x509/t_crl.c b/external/boringssl/crypto/x509/t_crl.c new file mode 100644 index 0000000000..6c347cb845 --- /dev/null +++ b/external/boringssl/crypto/x509/t_crl.c @@ -0,0 +1,128 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include +#include +#include +#include +#include +#include + +#ifndef OPENSSL_NO_FP_API +int X509_CRL_print_fp(FILE *fp, X509_CRL *x) +{ + BIO *b; + int ret; + + if ((b = BIO_new(BIO_s_file())) == NULL) { + OPENSSL_PUT_ERROR(X509, ERR_R_BUF_LIB); + return (0); + } + BIO_set_fp(b, fp, BIO_NOCLOSE); + ret = X509_CRL_print(b, x); + BIO_free(b); + return (ret); +} +#endif + +int X509_CRL_print(BIO *out, X509_CRL *x) +{ + STACK_OF(X509_REVOKED) *rev; + X509_REVOKED *r; + long l; + size_t i; + char *p; + + BIO_printf(out, "Certificate Revocation List (CRL):\n"); + l = X509_CRL_get_version(x); + BIO_printf(out, "%8sVersion %lu (0x%lx)\n", "", l + 1, l); + X509_signature_print(out, x->sig_alg, NULL); + p = X509_NAME_oneline(X509_CRL_get_issuer(x), NULL, 0); + BIO_printf(out, "%8sIssuer: %s\n", "", p); + OPENSSL_free(p); + BIO_printf(out, "%8sLast Update: ", ""); + ASN1_TIME_print(out, X509_CRL_get_lastUpdate(x)); + BIO_printf(out, "\n%8sNext Update: ", ""); + if (X509_CRL_get_nextUpdate(x)) + ASN1_TIME_print(out, X509_CRL_get_nextUpdate(x)); + else + BIO_printf(out, "NONE"); + BIO_printf(out, "\n"); + + X509V3_extensions_print(out, "CRL extensions", x->crl->extensions, 0, 8); + + rev = X509_CRL_get_REVOKED(x); + + if (sk_X509_REVOKED_num(rev) > 0) + BIO_printf(out, "Revoked Certificates:\n"); + else + BIO_printf(out, "No Revoked Certificates.\n"); + + for (i = 0; i < sk_X509_REVOKED_num(rev); i++) { + r = sk_X509_REVOKED_value(rev, i); + BIO_printf(out, " Serial Number: "); + i2a_ASN1_INTEGER(out, r->serialNumber); + BIO_printf(out, "\n Revocation Date: "); + ASN1_TIME_print(out, r->revocationDate); + BIO_printf(out, "\n"); + X509V3_extensions_print(out, "CRL entry extensions", + r->extensions, 0, 8); + } + X509_signature_print(out, x->sig_alg, x->signature); + + return 1; + +} diff --git a/external/boringssl/crypto/x509/t_req.c b/external/boringssl/crypto/x509/t_req.c new file mode 100644 index 0000000000..39c836ccc6 --- /dev/null +++ b/external/boringssl/crypto/x509/t_req.c @@ -0,0 +1,246 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include +#include +#include +#include +#include + + +int X509_REQ_print_fp(FILE *fp, X509_REQ *x) { + BIO *bio = BIO_new(BIO_s_file()); + if (bio == NULL) { + OPENSSL_PUT_ERROR(X509, ERR_R_BUF_LIB); + return 0; + } + + BIO_set_fp(bio, fp, BIO_NOCLOSE); + int ret = X509_REQ_print(bio, x); + BIO_free(bio); + return ret; +} + +int X509_REQ_print_ex(BIO *bio, X509_REQ *x, unsigned long nmflags, + unsigned long cflag) { + long l; + EVP_PKEY *pkey; + STACK_OF(X509_ATTRIBUTE) * sk; + char mlch = ' '; + + int nmindent = 0; + + if ((nmflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) { + mlch = '\n'; + nmindent = 12; + } + + if (nmflags == X509_FLAG_COMPAT) { + nmindent = 16; + } + + X509_REQ_INFO *ri = x->req_info; + if (!(cflag & X509_FLAG_NO_HEADER)) { + if (BIO_write(bio, "Certificate Request:\n", 21) <= 0 || + BIO_write(bio, " Data:\n", 10) <= 0) { + goto err; + } + } + if (!(cflag & X509_FLAG_NO_VERSION)) { + l = X509_REQ_get_version(x); + if (BIO_printf(bio, "%8sVersion: %ld (0x%lx)\n", "", l + 1, l) <= 0) { + goto err; + } + } + if (!(cflag & X509_FLAG_NO_SUBJECT)) { + if (BIO_printf(bio, " Subject:%c", mlch) <= 0 || + X509_NAME_print_ex(bio, ri->subject, nmindent, nmflags) < 0 || + BIO_write(bio, "\n", 1) <= 0) { + goto err; + } + } + if (!(cflag & X509_FLAG_NO_PUBKEY)) { + if (BIO_write(bio, " Subject Public Key Info:\n", 33) <= 0 || + BIO_printf(bio, "%12sPublic Key Algorithm: ", "") <= 0 || + i2a_ASN1_OBJECT(bio, ri->pubkey->algor->algorithm) <= 0 || + BIO_puts(bio, "\n") <= 0) { + goto err; + } + + pkey = X509_REQ_get_pubkey(x); + if (pkey == NULL) { + BIO_printf(bio, "%12sUnable to load Public Key\n", ""); + ERR_print_errors(bio); + } else { + EVP_PKEY_print_public(bio, pkey, 16, NULL); + EVP_PKEY_free(pkey); + } + } + + if (!(cflag & X509_FLAG_NO_ATTRIBUTES)) { + if (BIO_printf(bio, "%8sAttributes:\n", "") <= 0) { + goto err; + } + + sk = x->req_info->attributes; + if (sk_X509_ATTRIBUTE_num(sk) == 0) { + if (BIO_printf(bio, "%12sa0:00\n", "") <= 0) { + goto err; + } + } else { + size_t i; + for (i = 0; i < sk_X509_ATTRIBUTE_num(sk); i++) { + X509_ATTRIBUTE *a = sk_X509_ATTRIBUTE_value(sk, i); + ASN1_OBJECT *aobj = X509_ATTRIBUTE_get0_object(a); + + if (X509_REQ_extension_nid(OBJ_obj2nid(aobj))) { + continue; + } + + if (BIO_printf(bio, "%12s", "") <= 0) { + goto err; + } + + const int num_attrs = X509_ATTRIBUTE_count(a); + const int obj_str_len = i2a_ASN1_OBJECT(bio, aobj); + if (obj_str_len <= 0) { + if (BIO_puts(bio, "(Unable to print attribute ID.)\n") < 0) { + goto err; + } else { + continue; + } + } + + int j; + for (j = 0; j < num_attrs; j++) { + const ASN1_TYPE *at = X509_ATTRIBUTE_get0_type(a, j); + const int type = at->type; + ASN1_BIT_STRING *bs = at->value.asn1_string; + + int k; + for (k = 25 - obj_str_len; k > 0; k--) { + if (BIO_write(bio, " ", 1) != 1) { + goto err; + } + } + + if (BIO_puts(bio, ":") <= 0) { + goto err; + } + + if (type == V_ASN1_PRINTABLESTRING || + type == V_ASN1_UTF8STRING || + type == V_ASN1_IA5STRING || + type == V_ASN1_T61STRING) { + if (BIO_write(bio, (char *)bs->data, bs->length) != bs->length) { + goto err; + } + BIO_puts(bio, "\n"); + } else { + BIO_puts(bio, "unable to print attribute\n"); + } + } + } + } + } + + if (!(cflag & X509_FLAG_NO_EXTENSIONS)) { + STACK_OF(X509_EXTENSION) *exts = X509_REQ_get_extensions(x); + if (exts) { + BIO_printf(bio, "%8sRequested Extensions:\n", ""); + + size_t i; + for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) { + X509_EXTENSION *ex = sk_X509_EXTENSION_value(exts, i); + if (BIO_printf(bio, "%12s", "") <= 0) { + goto err; + } + ASN1_OBJECT *obj = X509_EXTENSION_get_object(ex); + i2a_ASN1_OBJECT(bio, obj); + const int is_critical = X509_EXTENSION_get_critical(ex); + if (BIO_printf(bio, ": %s\n", is_critical ? "critical" : "") <= 0) { + goto err; + } + if (!X509V3_EXT_print(bio, ex, cflag, 16)) { + BIO_printf(bio, "%16s", ""); + ASN1_STRING_print(bio, X509_EXTENSION_get_data(ex)); + } + if (BIO_write(bio, "\n", 1) <= 0) { + goto err; + } + } + sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); + } + } + + if (!(cflag & X509_FLAG_NO_SIGDUMP) && + !X509_signature_print(bio, x->sig_alg, x->signature)) { + goto err; + } + + return 1; + +err: + OPENSSL_PUT_ERROR(X509, ERR_R_BUF_LIB); + return 0; +} + +int X509_REQ_print(BIO *bio, X509_REQ *req) { + return X509_REQ_print_ex(bio, req, XN_FLAG_COMPAT, X509_FLAG_COMPAT); +} diff --git a/external/boringssl/crypto/x509/t_x509.c b/external/boringssl/crypto/x509/t_x509.c new file mode 100644 index 0000000000..1fba9b4335 --- /dev/null +++ b/external/boringssl/crypto/x509/t_x509.c @@ -0,0 +1,506 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "internal.h" + + +#ifndef OPENSSL_NO_FP_API +int X509_print_ex_fp(FILE *fp, X509 *x, unsigned long nmflag, + unsigned long cflag) +{ + BIO *b; + int ret; + + if ((b = BIO_new(BIO_s_file())) == NULL) { + OPENSSL_PUT_ERROR(X509, ERR_R_BUF_LIB); + return (0); + } + BIO_set_fp(b, fp, BIO_NOCLOSE); + ret = X509_print_ex(b, x, nmflag, cflag); + BIO_free(b); + return (ret); +} + +int X509_print_fp(FILE *fp, X509 *x) +{ + return X509_print_ex_fp(fp, x, XN_FLAG_COMPAT, X509_FLAG_COMPAT); +} +#endif + +int X509_print(BIO *bp, X509 *x) +{ + return X509_print_ex(bp, x, XN_FLAG_COMPAT, X509_FLAG_COMPAT); +} + +int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags, + unsigned long cflag) +{ + long l; + int ret = 0, i; + char *m = NULL, mlch = ' '; + int nmindent = 0; + X509_CINF *ci; + ASN1_INTEGER *bs; + EVP_PKEY *pkey = NULL; + const char *neg; + + if ((nmflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) { + mlch = '\n'; + nmindent = 12; + } + + if (nmflags == X509_FLAG_COMPAT) + nmindent = 16; + + ci = x->cert_info; + if (!(cflag & X509_FLAG_NO_HEADER)) { + if (BIO_write(bp, "Certificate:\n", 13) <= 0) + goto err; + if (BIO_write(bp, " Data:\n", 10) <= 0) + goto err; + } + if (!(cflag & X509_FLAG_NO_VERSION)) { + l = X509_get_version(x); + if (BIO_printf(bp, "%8sVersion: %lu (0x%lx)\n", "", l + 1, l) <= 0) + goto err; + } + if (!(cflag & X509_FLAG_NO_SERIAL)) { + + if (BIO_write(bp, " Serial Number:", 22) <= 0) + goto err; + + bs = X509_get_serialNumber(x); + if (bs->length < (int)sizeof(long) + || (bs->length == sizeof(long) && (bs->data[0] & 0x80) == 0)) { + l = ASN1_INTEGER_get(bs); + if (bs->type == V_ASN1_NEG_INTEGER) { + l = -l; + neg = "-"; + } else + neg = ""; + if (BIO_printf(bp, " %s%lu (%s0x%lx)\n", neg, l, neg, l) <= 0) + goto err; + } else { + neg = (bs->type == V_ASN1_NEG_INTEGER) ? " (Negative)" : ""; + if (BIO_printf(bp, "\n%12s%s", "", neg) <= 0) + goto err; + + for (i = 0; i < bs->length; i++) { + if (BIO_printf(bp, "%02x%c", bs->data[i], + ((i + 1 == bs->length) ? '\n' : ':')) <= 0) + goto err; + } + } + + } + + if (!(cflag & X509_FLAG_NO_SIGNAME)) { + if (X509_signature_print(bp, ci->signature, NULL) <= 0) + goto err; + } + + if (!(cflag & X509_FLAG_NO_ISSUER)) { + if (BIO_printf(bp, " Issuer:%c", mlch) <= 0) + goto err; + if (X509_NAME_print_ex(bp, X509_get_issuer_name(x), nmindent, nmflags) + < 0) + goto err; + if (BIO_write(bp, "\n", 1) <= 0) + goto err; + } + if (!(cflag & X509_FLAG_NO_VALIDITY)) { + if (BIO_write(bp, " Validity\n", 17) <= 0) + goto err; + if (BIO_write(bp, " Not Before: ", 24) <= 0) + goto err; + if (!ASN1_TIME_print(bp, X509_get_notBefore(x))) + goto err; + if (BIO_write(bp, "\n Not After : ", 25) <= 0) + goto err; + if (!ASN1_TIME_print(bp, X509_get_notAfter(x))) + goto err; + if (BIO_write(bp, "\n", 1) <= 0) + goto err; + } + if (!(cflag & X509_FLAG_NO_SUBJECT)) { + if (BIO_printf(bp, " Subject:%c", mlch) <= 0) + goto err; + if (X509_NAME_print_ex + (bp, X509_get_subject_name(x), nmindent, nmflags) < 0) + goto err; + if (BIO_write(bp, "\n", 1) <= 0) + goto err; + } + if (!(cflag & X509_FLAG_NO_PUBKEY)) { + if (BIO_write(bp, " Subject Public Key Info:\n", 33) <= 0) + goto err; + if (BIO_printf(bp, "%12sPublic Key Algorithm: ", "") <= 0) + goto err; + if (i2a_ASN1_OBJECT(bp, ci->key->algor->algorithm) <= 0) + goto err; + if (BIO_puts(bp, "\n") <= 0) + goto err; + + pkey = X509_get_pubkey(x); + if (pkey == NULL) { + BIO_printf(bp, "%12sUnable to load Public Key\n", ""); + BIO_print_errors(bp); + } else { + EVP_PKEY_print_public(bp, pkey, 16, NULL); + EVP_PKEY_free(pkey); + } + } + + if (!(cflag & X509_FLAG_NO_IDS)) { + if (ci->issuerUID) { + if (BIO_printf(bp, "%8sIssuer Unique ID: ", "") <= 0) + goto err; + if (!X509_signature_dump(bp, ci->issuerUID, 12)) + goto err; + } + if (ci->subjectUID) { + if (BIO_printf(bp, "%8sSubject Unique ID: ", "") <= 0) + goto err; + if (!X509_signature_dump(bp, ci->subjectUID, 12)) + goto err; + } + } + + if (!(cflag & X509_FLAG_NO_EXTENSIONS)) + X509V3_extensions_print(bp, "X509v3 extensions", + ci->extensions, cflag, 8); + + if (!(cflag & X509_FLAG_NO_SIGDUMP)) { + if (X509_signature_print(bp, x->sig_alg, x->signature) <= 0) + goto err; + } + if (!(cflag & X509_FLAG_NO_AUX)) { + if (!X509_CERT_AUX_print(bp, x->aux, 0)) + goto err; + } + ret = 1; + err: + if (m != NULL) + OPENSSL_free(m); + return (ret); +} + +int X509_ocspid_print(BIO *bp, X509 *x) +{ + unsigned char *der = NULL; + unsigned char *dertmp; + int derlen; + int i; + unsigned char SHA1md[SHA_DIGEST_LENGTH]; + + /* + * display the hash of the subject as it would appear in OCSP requests + */ + if (BIO_printf(bp, " Subject OCSP hash: ") <= 0) + goto err; + derlen = i2d_X509_NAME(x->cert_info->subject, NULL); + if ((der = dertmp = (unsigned char *)OPENSSL_malloc(derlen)) == NULL) + goto err; + i2d_X509_NAME(x->cert_info->subject, &dertmp); + + if (!EVP_Digest(der, derlen, SHA1md, NULL, EVP_sha1(), NULL)) + goto err; + for (i = 0; i < SHA_DIGEST_LENGTH; i++) { + if (BIO_printf(bp, "%02X", SHA1md[i]) <= 0) + goto err; + } + OPENSSL_free(der); + der = NULL; + + /* + * display the hash of the public key as it would appear in OCSP requests + */ + if (BIO_printf(bp, "\n Public key OCSP hash: ") <= 0) + goto err; + + if (!EVP_Digest(x->cert_info->key->public_key->data, + x->cert_info->key->public_key->length, + SHA1md, NULL, EVP_sha1(), NULL)) + goto err; + for (i = 0; i < SHA_DIGEST_LENGTH; i++) { + if (BIO_printf(bp, "%02X", SHA1md[i]) <= 0) + goto err; + } + BIO_printf(bp, "\n"); + + return (1); + err: + if (der != NULL) + OPENSSL_free(der); + return (0); +} + +int X509_signature_print(BIO *bp, X509_ALGOR *sigalg, ASN1_STRING *sig) +{ + if (BIO_puts(bp, " Signature Algorithm: ") <= 0) + return 0; + if (i2a_ASN1_OBJECT(bp, sigalg->algorithm) <= 0) + return 0; + + /* RSA-PSS signatures have parameters to print. */ + int sig_nid = OBJ_obj2nid(sigalg->algorithm); + if (sig_nid == NID_rsassaPss && + !x509_print_rsa_pss_params(bp, sigalg, 9, 0)) { + return 0; + } + + if (sig) + return X509_signature_dump(bp, sig, 9); + else if (BIO_puts(bp, "\n") <= 0) + return 0; + return 1; +} + +int ASN1_STRING_print(BIO *bp, const ASN1_STRING *v) +{ + int i, n; + char buf[80]; + const char *p; + + if (v == NULL) + return (0); + n = 0; + p = (const char *)v->data; + for (i = 0; i < v->length; i++) { + if ((p[i] > '~') || ((p[i] < ' ') && + (p[i] != '\n') && (p[i] != '\r'))) + buf[n] = '.'; + else + buf[n] = p[i]; + n++; + if (n >= 80) { + if (BIO_write(bp, buf, n) <= 0) + return (0); + n = 0; + } + } + if (n > 0) + if (BIO_write(bp, buf, n) <= 0) + return (0); + return (1); +} + +int ASN1_TIME_print(BIO *bp, const ASN1_TIME *tm) +{ + if (tm->type == V_ASN1_UTCTIME) + return ASN1_UTCTIME_print(bp, tm); + if (tm->type == V_ASN1_GENERALIZEDTIME) + return ASN1_GENERALIZEDTIME_print(bp, tm); + BIO_write(bp, "Bad time value", 14); + return (0); +} + +static const char *const mon[12] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" +}; + +int ASN1_GENERALIZEDTIME_print(BIO *bp, const ASN1_GENERALIZEDTIME *tm) +{ + char *v; + int gmt = 0; + int i; + int y = 0, M = 0, d = 0, h = 0, m = 0, s = 0; + char *f = NULL; + int f_len = 0; + + i = tm->length; + v = (char *)tm->data; + + if (i < 12) + goto err; + if (v[i - 1] == 'Z') + gmt = 1; + for (i = 0; i < 12; i++) + if ((v[i] > '9') || (v[i] < '0')) + goto err; + y = (v[0] - '0') * 1000 + (v[1] - '0') * 100 + (v[2] - '0') * 10 + (v[3] - + '0'); + M = (v[4] - '0') * 10 + (v[5] - '0'); + if ((M > 12) || (M < 1)) + goto err; + d = (v[6] - '0') * 10 + (v[7] - '0'); + h = (v[8] - '0') * 10 + (v[9] - '0'); + m = (v[10] - '0') * 10 + (v[11] - '0'); + if (tm->length >= 14 && + (v[12] >= '0') && (v[12] <= '9') && + (v[13] >= '0') && (v[13] <= '9')) { + s = (v[12] - '0') * 10 + (v[13] - '0'); + /* Check for fractions of seconds. */ + if (tm->length >= 15 && v[14] == '.') { + int l = tm->length; + f = &v[14]; /* The decimal point. */ + f_len = 1; + while (14 + f_len < l && f[f_len] >= '0' && f[f_len] <= '9') + ++f_len; + } + } + + if (BIO_printf(bp, "%s %2d %02d:%02d:%02d%.*s %d%s", + mon[M - 1], d, h, m, s, f_len, f, y, + (gmt) ? " GMT" : "") <= 0) + return (0); + else + return (1); + err: + BIO_write(bp, "Bad time value", 14); + return (0); +} + +int ASN1_UTCTIME_print(BIO *bp, const ASN1_UTCTIME *tm) +{ + const char *v; + int gmt = 0; + int i; + int y = 0, M = 0, d = 0, h = 0, m = 0, s = 0; + + i = tm->length; + v = (const char *)tm->data; + + if (i < 10) + goto err; + if (v[i - 1] == 'Z') + gmt = 1; + for (i = 0; i < 10; i++) + if ((v[i] > '9') || (v[i] < '0')) + goto err; + y = (v[0] - '0') * 10 + (v[1] - '0'); + if (y < 50) + y += 100; + M = (v[2] - '0') * 10 + (v[3] - '0'); + if ((M > 12) || (M < 1)) + goto err; + d = (v[4] - '0') * 10 + (v[5] - '0'); + h = (v[6] - '0') * 10 + (v[7] - '0'); + m = (v[8] - '0') * 10 + (v[9] - '0'); + if (tm->length >= 12 && + (v[10] >= '0') && (v[10] <= '9') && (v[11] >= '0') && (v[11] <= '9')) + s = (v[10] - '0') * 10 + (v[11] - '0'); + + if (BIO_printf(bp, "%s %2d %02d:%02d:%02d %d%s", + mon[M - 1], d, h, m, s, y + 1900, + (gmt) ? " GMT" : "") <= 0) + return (0); + else + return (1); + err: + BIO_write(bp, "Bad time value", 14); + return (0); +} + +int X509_NAME_print(BIO *bp, X509_NAME *name, int obase) +{ + char *s, *c, *b; + int ret = 0, l, i; + + l = 80 - 2 - obase; + + b = X509_NAME_oneline(name, NULL, 0); + if (!b) + return 0; + if (!*b) { + OPENSSL_free(b); + return 1; + } + s = b + 1; /* skip the first slash */ + + c = s; + for (;;) { + if (((*s == '/') && + ((s[1] >= 'A') && (s[1] <= 'Z') && ((s[2] == '=') || + ((s[2] >= 'A') + && (s[2] <= 'Z') + && (s[3] == '=')) + ))) || (*s == '\0')) { + i = s - c; + if (BIO_write(bp, c, i) != i) + goto err; + c = s + 1; /* skip following slash */ + if (*s != '\0') { + if (BIO_write(bp, ", ", 2) != 2) + goto err; + } + l--; + } + if (*s == '\0') + break; + s++; + l--; + } + + ret = 1; + if (0) { + err: + OPENSSL_PUT_ERROR(X509, ERR_R_BUF_LIB); + } + OPENSSL_free(b); + return (ret); +} diff --git a/external/boringssl/crypto/x509/t_x509a.c b/external/boringssl/crypto/x509/t_x509a.c new file mode 100644 index 0000000000..54368286ba --- /dev/null +++ b/external/boringssl/crypto/x509/t_x509a.c @@ -0,0 +1,111 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include +#include +#include +#include +#include + +/* X509_CERT_AUX and string set routines */ + +int X509_CERT_AUX_print(BIO *out, X509_CERT_AUX *aux, int indent) +{ + char oidstr[80], first; + size_t i; + int j; + if (!aux) + return 1; + if (aux->trust) { + first = 1; + BIO_printf(out, "%*sTrusted Uses:\n%*s", indent, "", indent + 2, ""); + for (i = 0; i < sk_ASN1_OBJECT_num(aux->trust); i++) { + if (!first) + BIO_puts(out, ", "); + else + first = 0; + OBJ_obj2txt(oidstr, sizeof oidstr, + sk_ASN1_OBJECT_value(aux->trust, i), 0); + BIO_puts(out, oidstr); + } + BIO_puts(out, "\n"); + } else + BIO_printf(out, "%*sNo Trusted Uses.\n", indent, ""); + if (aux->reject) { + first = 1; + BIO_printf(out, "%*sRejected Uses:\n%*s", indent, "", indent + 2, ""); + for (i = 0; i < sk_ASN1_OBJECT_num(aux->reject); i++) { + if (!first) + BIO_puts(out, ", "); + else + first = 0; + OBJ_obj2txt(oidstr, sizeof oidstr, + sk_ASN1_OBJECT_value(aux->reject, i), 0); + BIO_puts(out, oidstr); + } + BIO_puts(out, "\n"); + } else + BIO_printf(out, "%*sNo Rejected Uses.\n", indent, ""); + if (aux->alias) + BIO_printf(out, "%*sAlias: %s\n", indent, "", aux->alias->data); + if (aux->keyid) { + BIO_printf(out, "%*sKey Id: ", indent, ""); + for (j = 0; j < aux->keyid->length; j++) + BIO_printf(out, "%s%02X", j ? ":" : "", aux->keyid->data[j]); + BIO_write(out, "\n", 1); + } + return 1; +} diff --git a/external/boringssl/crypto/x509/vpm_int.h b/external/boringssl/crypto/x509/vpm_int.h new file mode 100644 index 0000000000..9c55defc51 --- /dev/null +++ b/external/boringssl/crypto/x509/vpm_int.h @@ -0,0 +1,70 @@ +/* vpm_int.h */ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project + * 2013. + */ +/* ==================================================================== + * Copyright (c) 2013 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +/* internal only structure to hold additional X509_VERIFY_PARAM data */ + +struct X509_VERIFY_PARAM_ID_st { + STACK_OF(OPENSSL_STRING) *hosts; /* Set of acceptable names */ + unsigned int hostflags; /* Flags to control matching features */ + char *peername; /* Matching hostname in peer certificate */ + char *email; /* If not NULL email address to match */ + size_t emaillen; + unsigned char *ip; /* If not NULL IP address to match */ + size_t iplen; /* Length of IP address */ +}; diff --git a/external/boringssl/crypto/x509/x509.c b/external/boringssl/crypto/x509/x509.c new file mode 100644 index 0000000000..188fd49634 --- /dev/null +++ b/external/boringssl/crypto/x509/x509.c @@ -0,0 +1,157 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include +#include + + +/* |X509_R_UNSUPPORTED_ALGORITHM| is no longer emitted, but continue to define + * it to avoid downstream churn. */ +OPENSSL_DECLARE_ERROR_REASON(X509, UNSUPPORTED_ALGORITHM) + +int PKCS8_pkey_set0(PKCS8_PRIV_KEY_INFO *priv, ASN1_OBJECT *aobj, int version, + int ptype, void *pval, uint8_t *penc, int penclen) { + uint8_t **ppenc = NULL; + if (version >= 0) { + if (!ASN1_INTEGER_set(priv->version, version)) { + return 0; + } + } + + if (penc) { + int pmtype; + ASN1_OCTET_STRING *oct; + + oct = ASN1_OCTET_STRING_new(); + if (!oct) { + return 0; + } + oct->data = penc; + ppenc = &oct->data; + oct->length = penclen; + if (priv->broken == PKCS8_NO_OCTET) { + pmtype = V_ASN1_SEQUENCE; + } else { + pmtype = V_ASN1_OCTET_STRING; + } + ASN1_TYPE_set(priv->pkey, pmtype, oct); + } + + if (!X509_ALGOR_set0(priv->pkeyalg, aobj, ptype, pval)) { + /* If call fails do not swallow 'enc' */ + if (ppenc) { + *ppenc = NULL; + } + return 0; + } + + return 1; +} + +int PKCS8_pkey_get0(ASN1_OBJECT **ppkalg, const uint8_t **pk, int *ppklen, + X509_ALGOR **pa, PKCS8_PRIV_KEY_INFO *p8) { + if (ppkalg) { + *ppkalg = p8->pkeyalg->algorithm; + } + + if (p8->pkey->type == V_ASN1_OCTET_STRING) { + p8->broken = PKCS8_OK; + if (pk) { + *pk = p8->pkey->value.octet_string->data; + *ppklen = p8->pkey->value.octet_string->length; + } + } else if (p8->pkey->type == V_ASN1_SEQUENCE) { + p8->broken = PKCS8_NO_OCTET; + if (pk) { + *pk = p8->pkey->value.sequence->data; + *ppklen = p8->pkey->value.sequence->length; + } + } else { + return 0; + } + + if (pa) { + *pa = p8->pkeyalg; + } + return 1; +} + +int X509_signature_dump(BIO *bp, const ASN1_STRING *sig, int indent) { + const uint8_t *s; + int i, n; + + n = sig->length; + s = sig->data; + for (i = 0; i < n; i++) { + if ((i % 18) == 0) { + if (BIO_write(bp, "\n", 1) <= 0 || + BIO_indent(bp, indent, indent) <= 0) { + return 0; + } + } + if (BIO_printf(bp, "%02x%s", s[i], ((i + 1) == n) ? "" : ":") <= 0) { + return 0; + } + } + if (BIO_write(bp, "\n", 1) != 1) { + return 0; + } + + return 1; +} diff --git a/external/boringssl/crypto/x509/x509_att.c b/external/boringssl/crypto/x509/x509_att.c new file mode 100644 index 0000000000..b83d32f925 --- /dev/null +++ b/external/boringssl/crypto/x509/x509_att.c @@ -0,0 +1,375 @@ +/* crypto/x509/x509_att.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include +#include +#include +#include +#include +#include + +int X509at_get_attr_count(const STACK_OF(X509_ATTRIBUTE) *x) +{ + return sk_X509_ATTRIBUTE_num(x); +} + +int X509at_get_attr_by_NID(const STACK_OF(X509_ATTRIBUTE) *x, int nid, + int lastpos) +{ + const ASN1_OBJECT *obj; + + obj = OBJ_nid2obj(nid); + if (obj == NULL) + return (-2); + return (X509at_get_attr_by_OBJ(x, obj, lastpos)); +} + +int X509at_get_attr_by_OBJ(const STACK_OF(X509_ATTRIBUTE) *sk, + const ASN1_OBJECT *obj, int lastpos) +{ + int n; + X509_ATTRIBUTE *ex; + + if (sk == NULL) + return (-1); + lastpos++; + if (lastpos < 0) + lastpos = 0; + n = sk_X509_ATTRIBUTE_num(sk); + for (; lastpos < n; lastpos++) { + ex = sk_X509_ATTRIBUTE_value(sk, lastpos); + if (OBJ_cmp(ex->object, obj) == 0) + return (lastpos); + } + return (-1); +} + +X509_ATTRIBUTE *X509at_get_attr(const STACK_OF(X509_ATTRIBUTE) *x, int loc) +{ + if (x == NULL || loc < 0 || sk_X509_ATTRIBUTE_num(x) <= (size_t)loc) + return NULL; + else + return sk_X509_ATTRIBUTE_value(x, loc); +} + +X509_ATTRIBUTE *X509at_delete_attr(STACK_OF(X509_ATTRIBUTE) *x, int loc) +{ + X509_ATTRIBUTE *ret; + + if (x == NULL || loc < 0 || sk_X509_ATTRIBUTE_num(x) <= (size_t)loc) + return (NULL); + ret = sk_X509_ATTRIBUTE_delete(x, loc); + return (ret); +} + +STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr(STACK_OF(X509_ATTRIBUTE) **x, + X509_ATTRIBUTE *attr) +{ + X509_ATTRIBUTE *new_attr = NULL; + STACK_OF(X509_ATTRIBUTE) *sk = NULL; + + if (x == NULL) { + OPENSSL_PUT_ERROR(X509, ERR_R_PASSED_NULL_PARAMETER); + goto err2; + } + + if (*x == NULL) { + if ((sk = sk_X509_ATTRIBUTE_new_null()) == NULL) + goto err; + } else + sk = *x; + + if ((new_attr = X509_ATTRIBUTE_dup(attr)) == NULL) + goto err2; + if (!sk_X509_ATTRIBUTE_push(sk, new_attr)) + goto err; + if (*x == NULL) + *x = sk; + return (sk); + err: + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + err2: + if (new_attr != NULL) + X509_ATTRIBUTE_free(new_attr); + if (sk != NULL) + sk_X509_ATTRIBUTE_free(sk); + return (NULL); +} + +STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_OBJ(STACK_OF(X509_ATTRIBUTE) + **x, const ASN1_OBJECT *obj, + int type, + const unsigned char *bytes, + int len) +{ + X509_ATTRIBUTE *attr; + STACK_OF(X509_ATTRIBUTE) *ret; + attr = X509_ATTRIBUTE_create_by_OBJ(NULL, obj, type, bytes, len); + if (!attr) + return 0; + ret = X509at_add1_attr(x, attr); + X509_ATTRIBUTE_free(attr); + return ret; +} + +STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_NID(STACK_OF(X509_ATTRIBUTE) + **x, int nid, int type, + const unsigned char *bytes, + int len) +{ + X509_ATTRIBUTE *attr; + STACK_OF(X509_ATTRIBUTE) *ret; + attr = X509_ATTRIBUTE_create_by_NID(NULL, nid, type, bytes, len); + if (!attr) + return 0; + ret = X509at_add1_attr(x, attr); + X509_ATTRIBUTE_free(attr); + return ret; +} + +STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_txt(STACK_OF(X509_ATTRIBUTE) + **x, const char *attrname, + int type, + const unsigned char *bytes, + int len) +{ + X509_ATTRIBUTE *attr; + STACK_OF(X509_ATTRIBUTE) *ret; + attr = X509_ATTRIBUTE_create_by_txt(NULL, attrname, type, bytes, len); + if (!attr) + return 0; + ret = X509at_add1_attr(x, attr); + X509_ATTRIBUTE_free(attr); + return ret; +} + +void *X509at_get0_data_by_OBJ(STACK_OF(X509_ATTRIBUTE) *x, + ASN1_OBJECT *obj, int lastpos, int type) +{ + int i; + X509_ATTRIBUTE *at; + i = X509at_get_attr_by_OBJ(x, obj, lastpos); + if (i == -1) + return NULL; + if ((lastpos <= -2) && (X509at_get_attr_by_OBJ(x, obj, i) != -1)) + return NULL; + at = X509at_get_attr(x, i); + if (lastpos <= -3 && (X509_ATTRIBUTE_count(at) != 1)) + return NULL; + return X509_ATTRIBUTE_get0_data(at, 0, type, NULL); +} + +X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_NID(X509_ATTRIBUTE **attr, int nid, + int atrtype, const void *data, + int len) +{ + const ASN1_OBJECT *obj; + + obj = OBJ_nid2obj(nid); + if (obj == NULL) { + OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_NID); + return (NULL); + } + return X509_ATTRIBUTE_create_by_OBJ(attr, obj, atrtype, data, len); +} + +X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_OBJ(X509_ATTRIBUTE **attr, + const ASN1_OBJECT *obj, + int atrtype, const void *data, + int len) +{ + X509_ATTRIBUTE *ret; + + if ((attr == NULL) || (*attr == NULL)) { + if ((ret = X509_ATTRIBUTE_new()) == NULL) { + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + return (NULL); + } + } else + ret = *attr; + + if (!X509_ATTRIBUTE_set1_object(ret, obj)) + goto err; + if (!X509_ATTRIBUTE_set1_data(ret, atrtype, data, len)) + goto err; + + if ((attr != NULL) && (*attr == NULL)) + *attr = ret; + return (ret); + err: + if ((attr == NULL) || (ret != *attr)) + X509_ATTRIBUTE_free(ret); + return (NULL); +} + +X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_txt(X509_ATTRIBUTE **attr, + const char *atrname, int type, + const unsigned char *bytes, + int len) +{ + ASN1_OBJECT *obj; + X509_ATTRIBUTE *nattr; + + obj = OBJ_txt2obj(atrname, 0); + if (obj == NULL) { + OPENSSL_PUT_ERROR(X509, X509_R_INVALID_FIELD_NAME); + ERR_add_error_data(2, "name=", atrname); + return (NULL); + } + nattr = X509_ATTRIBUTE_create_by_OBJ(attr, obj, type, bytes, len); + ASN1_OBJECT_free(obj); + return nattr; +} + +int X509_ATTRIBUTE_set1_object(X509_ATTRIBUTE *attr, const ASN1_OBJECT *obj) +{ + if ((attr == NULL) || (obj == NULL)) + return (0); + ASN1_OBJECT_free(attr->object); + attr->object = OBJ_dup(obj); + return attr->object != NULL; +} + +int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype, + const void *data, int len) +{ + ASN1_TYPE *ttmp; + ASN1_STRING *stmp = NULL; + int atype = 0; + if (!attr) + return 0; + if (attrtype & MBSTRING_FLAG) { + stmp = ASN1_STRING_set_by_NID(NULL, data, len, attrtype, + OBJ_obj2nid(attr->object)); + if (!stmp) { + OPENSSL_PUT_ERROR(X509, ERR_R_ASN1_LIB); + return 0; + } + atype = stmp->type; + } else if (len != -1) { + if (!(stmp = ASN1_STRING_type_new(attrtype))) + goto err; + if (!ASN1_STRING_set(stmp, data, len)) + goto err; + atype = attrtype; + } + if (!(attr->value.set = sk_ASN1_TYPE_new_null())) + goto err; + attr->single = 0; + /* + * This is a bit naughty because the attribute should really have at + * least one value but some types use and zero length SET and require + * this. + */ + if (attrtype == 0) + return 1; + if (!(ttmp = ASN1_TYPE_new())) + goto err; + if ((len == -1) && !(attrtype & MBSTRING_FLAG)) { + if (!ASN1_TYPE_set1(ttmp, attrtype, data)) + goto err; + } else + ASN1_TYPE_set(ttmp, atype, stmp); + if (!sk_ASN1_TYPE_push(attr->value.set, ttmp)) + goto err; + return 1; + err: + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + return 0; +} + +int X509_ATTRIBUTE_count(X509_ATTRIBUTE *attr) +{ + if (!attr->single) + return sk_ASN1_TYPE_num(attr->value.set); + if (attr->value.single) + return 1; + return 0; +} + +ASN1_OBJECT *X509_ATTRIBUTE_get0_object(X509_ATTRIBUTE *attr) +{ + if (attr == NULL) + return (NULL); + return (attr->object); +} + +void *X509_ATTRIBUTE_get0_data(X509_ATTRIBUTE *attr, int idx, + int atrtype, void *data) +{ + ASN1_TYPE *ttmp; + ttmp = X509_ATTRIBUTE_get0_type(attr, idx); + if (!ttmp) + return NULL; + if (atrtype != ASN1_TYPE_get(ttmp)) { + OPENSSL_PUT_ERROR(X509, X509_R_WRONG_TYPE); + return NULL; + } + return ttmp->value.ptr; +} + +ASN1_TYPE *X509_ATTRIBUTE_get0_type(X509_ATTRIBUTE *attr, int idx) +{ + if (attr == NULL) + return (NULL); + if (idx >= X509_ATTRIBUTE_count(attr)) + return NULL; + if (!attr->single) + return sk_ASN1_TYPE_value(attr->value.set, idx); + else + return attr->value.single; +} diff --git a/external/boringssl/crypto/x509/x509_cmp.c b/external/boringssl/crypto/x509/x509_cmp.c new file mode 100644 index 0000000000..32862ebc9c --- /dev/null +++ b/external/boringssl/crypto/x509/x509_cmp.c @@ -0,0 +1,474 @@ +/* crypto/x509/x509_cmp.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int X509_issuer_and_serial_cmp(const X509 *a, const X509 *b) +{ + int i; + X509_CINF *ai, *bi; + + ai = a->cert_info; + bi = b->cert_info; + i = M_ASN1_INTEGER_cmp(ai->serialNumber, bi->serialNumber); + if (i) + return (i); + return (X509_NAME_cmp(ai->issuer, bi->issuer)); +} + +unsigned long X509_issuer_and_serial_hash(X509 *a) +{ + unsigned long ret = 0; + EVP_MD_CTX ctx; + unsigned char md[16]; + char *f; + + EVP_MD_CTX_init(&ctx); + f = X509_NAME_oneline(a->cert_info->issuer, NULL, 0); + if (!EVP_DigestInit_ex(&ctx, EVP_md5(), NULL)) + goto err; + if (!EVP_DigestUpdate(&ctx, (unsigned char *)f, strlen(f))) + goto err; + OPENSSL_free(f); + if (!EVP_DigestUpdate + (&ctx, (unsigned char *)a->cert_info->serialNumber->data, + (unsigned long)a->cert_info->serialNumber->length)) + goto err; + if (!EVP_DigestFinal_ex(&ctx, &(md[0]), NULL)) + goto err; + ret = (((unsigned long)md[0]) | ((unsigned long)md[1] << 8L) | + ((unsigned long)md[2] << 16L) | ((unsigned long)md[3] << 24L) + ) & 0xffffffffL; + err: + EVP_MD_CTX_cleanup(&ctx); + return (ret); +} + +int X509_issuer_name_cmp(const X509 *a, const X509 *b) +{ + return (X509_NAME_cmp(a->cert_info->issuer, b->cert_info->issuer)); +} + +int X509_subject_name_cmp(const X509 *a, const X509 *b) +{ + return (X509_NAME_cmp(a->cert_info->subject, b->cert_info->subject)); +} + +int X509_CRL_cmp(const X509_CRL *a, const X509_CRL *b) +{ + return (X509_NAME_cmp(a->crl->issuer, b->crl->issuer)); +} + +int X509_CRL_match(const X509_CRL *a, const X509_CRL *b) +{ + return memcmp(a->sha1_hash, b->sha1_hash, 20); +} + +X509_NAME *X509_get_issuer_name(X509 *a) +{ + return (a->cert_info->issuer); +} + +unsigned long X509_issuer_name_hash(X509 *x) +{ + return (X509_NAME_hash(x->cert_info->issuer)); +} + +unsigned long X509_issuer_name_hash_old(X509 *x) +{ + return (X509_NAME_hash_old(x->cert_info->issuer)); +} + +X509_NAME *X509_get_subject_name(X509 *a) +{ + return (a->cert_info->subject); +} + +ASN1_INTEGER *X509_get_serialNumber(X509 *a) +{ + return (a->cert_info->serialNumber); +} + +unsigned long X509_subject_name_hash(X509 *x) +{ + return (X509_NAME_hash(x->cert_info->subject)); +} + +unsigned long X509_subject_name_hash_old(X509 *x) +{ + return (X509_NAME_hash_old(x->cert_info->subject)); +} + +/* + * Compare two certificates: they must be identical for this to work. NB: + * Although "cmp" operations are generally prototyped to take "const" + * arguments (eg. for use in STACKs), the way X509 handling is - these + * operations may involve ensuring the hashes are up-to-date and ensuring + * certain cert information is cached. So this is the point where the + * "depth-first" constification tree has to halt with an evil cast. + */ +int X509_cmp(const X509 *a, const X509 *b) +{ + int rv; + /* ensure hash is valid */ + X509_check_purpose((X509 *)a, -1, 0); + X509_check_purpose((X509 *)b, -1, 0); + + rv = memcmp(a->sha1_hash, b->sha1_hash, SHA_DIGEST_LENGTH); + if (rv) + return rv; + /* Check for match against stored encoding too */ + if (!a->cert_info->enc.modified && !b->cert_info->enc.modified) { + rv = (int)(a->cert_info->enc.len - b->cert_info->enc.len); + if (rv) + return rv; + return memcmp(a->cert_info->enc.enc, b->cert_info->enc.enc, + a->cert_info->enc.len); + } + return rv; +} + +int X509_NAME_cmp(const X509_NAME *a, const X509_NAME *b) +{ + int ret; + + /* Ensure canonical encoding is present and up to date */ + + if (!a->canon_enc || a->modified) { + ret = i2d_X509_NAME((X509_NAME *)a, NULL); + if (ret < 0) + return -2; + } + + if (!b->canon_enc || b->modified) { + ret = i2d_X509_NAME((X509_NAME *)b, NULL); + if (ret < 0) + return -2; + } + + ret = a->canon_enclen - b->canon_enclen; + + if (ret) + return ret; + + return memcmp(a->canon_enc, b->canon_enc, a->canon_enclen); + +} + +unsigned long X509_NAME_hash(X509_NAME *x) +{ + unsigned long ret = 0; + unsigned char md[SHA_DIGEST_LENGTH]; + + /* Make sure X509_NAME structure contains valid cached encoding */ + i2d_X509_NAME(x, NULL); + if (!EVP_Digest(x->canon_enc, x->canon_enclen, md, NULL, EVP_sha1(), + NULL)) + return 0; + + ret = (((unsigned long)md[0]) | ((unsigned long)md[1] << 8L) | + ((unsigned long)md[2] << 16L) | ((unsigned long)md[3] << 24L) + ) & 0xffffffffL; + return (ret); +} + +/* + * I now DER encode the name and hash it. Since I cache the DER encoding, + * this is reasonably efficient. + */ + +unsigned long X509_NAME_hash_old(X509_NAME *x) +{ + EVP_MD_CTX md_ctx; + unsigned long ret = 0; + unsigned char md[16]; + + /* Make sure X509_NAME structure contains valid cached encoding */ + i2d_X509_NAME(x, NULL); + EVP_MD_CTX_init(&md_ctx); + /* EVP_MD_CTX_set_flags(&md_ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); */ + if (EVP_DigestInit_ex(&md_ctx, EVP_md5(), NULL) + && EVP_DigestUpdate(&md_ctx, x->bytes->data, x->bytes->length) + && EVP_DigestFinal_ex(&md_ctx, md, NULL)) + ret = (((unsigned long)md[0]) | ((unsigned long)md[1] << 8L) | + ((unsigned long)md[2] << 16L) | ((unsigned long)md[3] << 24L) + ) & 0xffffffffL; + EVP_MD_CTX_cleanup(&md_ctx); + + return (ret); +} + +/* Search a stack of X509 for a match */ +X509 *X509_find_by_issuer_and_serial(STACK_OF(X509) *sk, X509_NAME *name, + ASN1_INTEGER *serial) +{ + size_t i; + X509_CINF cinf; + X509 x, *x509 = NULL; + + if (!sk) + return NULL; + + x.cert_info = &cinf; + cinf.serialNumber = serial; + cinf.issuer = name; + + for (i = 0; i < sk_X509_num(sk); i++) { + x509 = sk_X509_value(sk, i); + if (X509_issuer_and_serial_cmp(x509, &x) == 0) + return (x509); + } + return (NULL); +} + +X509 *X509_find_by_subject(STACK_OF(X509) *sk, X509_NAME *name) +{ + X509 *x509; + size_t i; + + for (i = 0; i < sk_X509_num(sk); i++) { + x509 = sk_X509_value(sk, i); + if (X509_NAME_cmp(X509_get_subject_name(x509), name) == 0) + return (x509); + } + return (NULL); +} + +EVP_PKEY *X509_get_pubkey(X509 *x) +{ + if ((x == NULL) || (x->cert_info == NULL)) + return (NULL); + return (X509_PUBKEY_get(x->cert_info->key)); +} + +ASN1_BIT_STRING *X509_get0_pubkey_bitstr(const X509 *x) +{ + if (!x) + return NULL; + return x->cert_info->key->public_key; +} + +int X509_check_private_key(X509 *x, EVP_PKEY *k) +{ + EVP_PKEY *xk; + int ret; + + xk = X509_get_pubkey(x); + + if (xk) + ret = EVP_PKEY_cmp(xk, k); + else + ret = -2; + + switch (ret) { + case 1: + break; + case 0: + OPENSSL_PUT_ERROR(X509, X509_R_KEY_VALUES_MISMATCH); + break; + case -1: + OPENSSL_PUT_ERROR(X509, X509_R_KEY_TYPE_MISMATCH); + break; + case -2: + OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_KEY_TYPE); + } + if (xk) + EVP_PKEY_free(xk); + if (ret > 0) + return 1; + return 0; +} + +/* + * Check a suite B algorithm is permitted: pass in a public key and the NID + * of its signature (or 0 if no signature). The pflags is a pointer to a + * flags field which must contain the suite B verification flags. + */ + +static int check_suite_b(EVP_PKEY *pkey, int sign_nid, unsigned long *pflags) +{ + const EC_GROUP *grp = NULL; + int curve_nid; + if (pkey && pkey->type == EVP_PKEY_EC) + grp = EC_KEY_get0_group(pkey->pkey.ec); + if (!grp) + return X509_V_ERR_SUITE_B_INVALID_ALGORITHM; + curve_nid = EC_GROUP_get_curve_name(grp); + /* Check curve is consistent with LOS */ + if (curve_nid == NID_secp384r1) { /* P-384 */ + /* + * Check signature algorithm is consistent with curve. + */ + if (sign_nid != -1 && sign_nid != NID_ecdsa_with_SHA384) + return X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM; + if (!(*pflags & X509_V_FLAG_SUITEB_192_LOS)) + return X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED; + /* If we encounter P-384 we cannot use P-256 later */ + *pflags &= ~X509_V_FLAG_SUITEB_128_LOS_ONLY; + } else if (curve_nid == NID_X9_62_prime256v1) { /* P-256 */ + if (sign_nid != -1 && sign_nid != NID_ecdsa_with_SHA256) + return X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM; + if (!(*pflags & X509_V_FLAG_SUITEB_128_LOS_ONLY)) + return X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED; + } else + return X509_V_ERR_SUITE_B_INVALID_CURVE; + + return X509_V_OK; +} + +int X509_chain_check_suiteb(int *perror_depth, X509 *x, STACK_OF(X509) *chain, + unsigned long flags) +{ + int rv, sign_nid; + size_t i; + EVP_PKEY *pk = NULL; + unsigned long tflags; + if (!(flags & X509_V_FLAG_SUITEB_128_LOS)) + return X509_V_OK; + tflags = flags; + /* If no EE certificate passed in must be first in chain */ + if (x == NULL) { + x = sk_X509_value(chain, 0); + i = 1; + } else + i = 0; + + if (X509_get_version(x) != 2) { + rv = X509_V_ERR_SUITE_B_INVALID_VERSION; + /* Correct error depth */ + i = 0; + goto end; + } + + pk = X509_get_pubkey(x); + /* Check EE key only */ + rv = check_suite_b(pk, -1, &tflags); + if (rv != X509_V_OK) { + /* Correct error depth */ + i = 0; + goto end; + } + for (; i < sk_X509_num(chain); i++) { + sign_nid = X509_get_signature_nid(x); + x = sk_X509_value(chain, i); + if (X509_get_version(x) != 2) { + rv = X509_V_ERR_SUITE_B_INVALID_VERSION; + goto end; + } + EVP_PKEY_free(pk); + pk = X509_get_pubkey(x); + rv = check_suite_b(pk, sign_nid, &tflags); + if (rv != X509_V_OK) + goto end; + } + + /* Final check: root CA signature */ + rv = check_suite_b(pk, X509_get_signature_nid(x), &tflags); + end: + if (pk) + EVP_PKEY_free(pk); + if (rv != X509_V_OK) { + /* Invalid signature or LOS errors are for previous cert */ + if ((rv == X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM + || rv == X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED) && i) + i--; + /* + * If we have LOS error and flags changed then we are signing P-384 + * with P-256. Use more meaninggul error. + */ + if (rv == X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED && flags != tflags) + rv = X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256; + if (perror_depth) + *perror_depth = i; + } + return rv; +} + +int X509_CRL_check_suiteb(X509_CRL *crl, EVP_PKEY *pk, unsigned long flags) +{ + int sign_nid; + if (!(flags & X509_V_FLAG_SUITEB_128_LOS)) + return X509_V_OK; + sign_nid = OBJ_obj2nid(crl->crl->sig_alg->algorithm); + return check_suite_b(pk, sign_nid, &flags); +} + +/* + * Not strictly speaking an "up_ref" as a STACK doesn't have a reference + * count but it has the same effect by duping the STACK and upping the ref of + * each X509 structure. + */ +STACK_OF(X509) *X509_chain_up_ref(STACK_OF(X509) *chain) +{ + STACK_OF(X509) *ret; + size_t i; + ret = sk_X509_dup(chain); + for (i = 0; i < sk_X509_num(ret); i++) { + X509_up_ref(sk_X509_value(ret, i)); + } + return ret; +} diff --git a/external/boringssl/crypto/x509/x509_d2.c b/external/boringssl/crypto/x509/x509_d2.c new file mode 100644 index 0000000000..69ae54ed8a --- /dev/null +++ b/external/boringssl/crypto/x509/x509_d2.c @@ -0,0 +1,106 @@ +/* crypto/x509/x509_d2.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include +#include + +#ifndef OPENSSL_NO_STDIO +int X509_STORE_set_default_paths(X509_STORE *ctx) +{ + X509_LOOKUP *lookup; + + lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_file()); + if (lookup == NULL) + return (0); + X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT); + + lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_hash_dir()); + if (lookup == NULL) + return (0); + X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT); + + /* clear any errors */ + ERR_clear_error(); + + return (1); +} + +int X509_STORE_load_locations(X509_STORE *ctx, const char *file, + const char *path) +{ + X509_LOOKUP *lookup; + + if (file != NULL) { + lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_file()); + if (lookup == NULL) + return (0); + if (X509_LOOKUP_load_file(lookup, file, X509_FILETYPE_PEM) != 1) + return (0); + } + if (path != NULL) { + lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_hash_dir()); + if (lookup == NULL) + return (0); + if (X509_LOOKUP_add_dir(lookup, path, X509_FILETYPE_PEM) != 1) + return (0); + } + if ((path == NULL) && (file == NULL)) + return (0); + return (1); +} + +#endif diff --git a/external/boringssl/crypto/x509/x509_def.c b/external/boringssl/crypto/x509/x509_def.c new file mode 100644 index 0000000000..2bf2240c35 --- /dev/null +++ b/external/boringssl/crypto/x509/x509_def.c @@ -0,0 +1,98 @@ +/* crypto/x509/x509_def.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +/* TODO(fork): cleanup */ + +#define OPENSSLDIR "/etc/ssl" +#define X509_CERT_AREA OPENSSLDIR +#define X509_CERT_DIR OPENSSLDIR "/certs" +#define X509_CERT_FILE OPENSSLDIR "/cert.pem" +#define X509_PRIVATE_DIR OPENSSLDIR "/private" +#define X509_CERT_DIR_EVP "SSL_CERT_DIR" +#define X509_CERT_FILE_EVP "SSL_CERT_FILE" + +const char *X509_get_default_private_dir(void) +{ + return (X509_PRIVATE_DIR); +} + +const char *X509_get_default_cert_area(void) +{ + return (X509_CERT_AREA); +} + +const char *X509_get_default_cert_dir(void) +{ + return (X509_CERT_DIR); +} + +const char *X509_get_default_cert_file(void) +{ + return (X509_CERT_FILE); +} + +const char *X509_get_default_cert_dir_env(void) +{ + return (X509_CERT_DIR_EVP); +} + +const char *X509_get_default_cert_file_env(void) +{ + return (X509_CERT_FILE_EVP); +} diff --git a/external/boringssl/crypto/x509/x509_ext.c b/external/boringssl/crypto/x509/x509_ext.c new file mode 100644 index 0000000000..a329f6fab4 --- /dev/null +++ b/external/boringssl/crypto/x509/x509_ext.c @@ -0,0 +1,206 @@ +/* crypto/x509/x509_ext.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include +#include +#include +#include +#include +#include + +int X509_CRL_get_ext_count(X509_CRL *x) +{ + return (X509v3_get_ext_count(x->crl->extensions)); +} + +int X509_CRL_get_ext_by_NID(X509_CRL *x, int nid, int lastpos) +{ + return (X509v3_get_ext_by_NID(x->crl->extensions, nid, lastpos)); +} + +int X509_CRL_get_ext_by_OBJ(X509_CRL *x, ASN1_OBJECT *obj, int lastpos) +{ + return (X509v3_get_ext_by_OBJ(x->crl->extensions, obj, lastpos)); +} + +int X509_CRL_get_ext_by_critical(X509_CRL *x, int crit, int lastpos) +{ + return (X509v3_get_ext_by_critical(x->crl->extensions, crit, lastpos)); +} + +X509_EXTENSION *X509_CRL_get_ext(X509_CRL *x, int loc) +{ + return (X509v3_get_ext(x->crl->extensions, loc)); +} + +X509_EXTENSION *X509_CRL_delete_ext(X509_CRL *x, int loc) +{ + return (X509v3_delete_ext(x->crl->extensions, loc)); +} + +void *X509_CRL_get_ext_d2i(X509_CRL *x, int nid, int *crit, int *idx) +{ + return X509V3_get_d2i(x->crl->extensions, nid, crit, idx); +} + +int X509_CRL_add1_ext_i2d(X509_CRL *x, int nid, void *value, int crit, + unsigned long flags) +{ + return X509V3_add1_i2d(&x->crl->extensions, nid, value, crit, flags); +} + +int X509_CRL_add_ext(X509_CRL *x, X509_EXTENSION *ex, int loc) +{ + return (X509v3_add_ext(&(x->crl->extensions), ex, loc) != NULL); +} + +int X509_get_ext_count(X509 *x) +{ + return (X509v3_get_ext_count(x->cert_info->extensions)); +} + +int X509_get_ext_by_NID(X509 *x, int nid, int lastpos) +{ + return (X509v3_get_ext_by_NID(x->cert_info->extensions, nid, lastpos)); +} + +int X509_get_ext_by_OBJ(X509 *x, ASN1_OBJECT *obj, int lastpos) +{ + return (X509v3_get_ext_by_OBJ(x->cert_info->extensions, obj, lastpos)); +} + +int X509_get_ext_by_critical(X509 *x, int crit, int lastpos) +{ + return (X509v3_get_ext_by_critical + (x->cert_info->extensions, crit, lastpos)); +} + +X509_EXTENSION *X509_get_ext(X509 *x, int loc) +{ + return (X509v3_get_ext(x->cert_info->extensions, loc)); +} + +X509_EXTENSION *X509_delete_ext(X509 *x, int loc) +{ + return (X509v3_delete_ext(x->cert_info->extensions, loc)); +} + +int X509_add_ext(X509 *x, X509_EXTENSION *ex, int loc) +{ + return (X509v3_add_ext(&(x->cert_info->extensions), ex, loc) != NULL); +} + +void *X509_get_ext_d2i(X509 *x, int nid, int *crit, int *idx) +{ + return X509V3_get_d2i(x->cert_info->extensions, nid, crit, idx); +} + +int X509_add1_ext_i2d(X509 *x, int nid, void *value, int crit, + unsigned long flags) +{ + return X509V3_add1_i2d(&x->cert_info->extensions, nid, value, crit, + flags); +} + +int X509_REVOKED_get_ext_count(X509_REVOKED *x) +{ + return (X509v3_get_ext_count(x->extensions)); +} + +int X509_REVOKED_get_ext_by_NID(X509_REVOKED *x, int nid, int lastpos) +{ + return (X509v3_get_ext_by_NID(x->extensions, nid, lastpos)); +} + +int X509_REVOKED_get_ext_by_OBJ(X509_REVOKED *x, ASN1_OBJECT *obj, + int lastpos) +{ + return (X509v3_get_ext_by_OBJ(x->extensions, obj, lastpos)); +} + +int X509_REVOKED_get_ext_by_critical(X509_REVOKED *x, int crit, int lastpos) +{ + return (X509v3_get_ext_by_critical(x->extensions, crit, lastpos)); +} + +X509_EXTENSION *X509_REVOKED_get_ext(X509_REVOKED *x, int loc) +{ + return (X509v3_get_ext(x->extensions, loc)); +} + +X509_EXTENSION *X509_REVOKED_delete_ext(X509_REVOKED *x, int loc) +{ + return (X509v3_delete_ext(x->extensions, loc)); +} + +int X509_REVOKED_add_ext(X509_REVOKED *x, X509_EXTENSION *ex, int loc) +{ + return (X509v3_add_ext(&(x->extensions), ex, loc) != NULL); +} + +void *X509_REVOKED_get_ext_d2i(X509_REVOKED *x, int nid, int *crit, int *idx) +{ + return X509V3_get_d2i(x->extensions, nid, crit, idx); +} + +int X509_REVOKED_add1_ext_i2d(X509_REVOKED *x, int nid, void *value, int crit, + unsigned long flags) +{ + return X509V3_add1_i2d(&x->extensions, nid, value, crit, flags); +} + +IMPLEMENT_ASN1_SET_OF(X509_EXTENSION) diff --git a/external/boringssl/crypto/x509/x509_lu.c b/external/boringssl/crypto/x509/x509_lu.c new file mode 100644 index 0000000000..9f427dea78 --- /dev/null +++ b/external/boringssl/crypto/x509/x509_lu.c @@ -0,0 +1,688 @@ +/* crypto/x509/x509_lu.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include +#include +#include +#include +#include + +#include "../internal.h" + +X509_LOOKUP *X509_LOOKUP_new(X509_LOOKUP_METHOD *method) +{ + X509_LOOKUP *ret; + + ret = (X509_LOOKUP *)OPENSSL_malloc(sizeof(X509_LOOKUP)); + if (ret == NULL) + return NULL; + + ret->init = 0; + ret->skip = 0; + ret->method = method; + ret->method_data = NULL; + ret->store_ctx = NULL; + if ((method->new_item != NULL) && !method->new_item(ret)) { + OPENSSL_free(ret); + return NULL; + } + return ret; +} + +void X509_LOOKUP_free(X509_LOOKUP *ctx) +{ + if (ctx == NULL) + return; + if ((ctx->method != NULL) && (ctx->method->free != NULL)) + (*ctx->method->free) (ctx); + OPENSSL_free(ctx); +} + +int X509_LOOKUP_init(X509_LOOKUP *ctx) +{ + if (ctx->method == NULL) + return 0; + if (ctx->method->init != NULL) + return ctx->method->init(ctx); + else + return 1; +} + +int X509_LOOKUP_shutdown(X509_LOOKUP *ctx) +{ + if (ctx->method == NULL) + return 0; + if (ctx->method->shutdown != NULL) + return ctx->method->shutdown(ctx); + else + return 1; +} + +int X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, long argl, + char **ret) +{ + if (ctx->method == NULL) + return -1; + if (ctx->method->ctrl != NULL) + return ctx->method->ctrl(ctx, cmd, argc, argl, ret); + else + return 1; +} + +int X509_LOOKUP_by_subject(X509_LOOKUP *ctx, int type, X509_NAME *name, + X509_OBJECT *ret) +{ + if ((ctx->method == NULL) || (ctx->method->get_by_subject == NULL)) + return 0; + if (ctx->skip) + return 0; + return ctx->method->get_by_subject(ctx, type, name, ret) > 0; +} + +int X509_LOOKUP_by_issuer_serial(X509_LOOKUP *ctx, int type, X509_NAME *name, + ASN1_INTEGER *serial, X509_OBJECT *ret) +{ + if ((ctx->method == NULL) || (ctx->method->get_by_issuer_serial == NULL)) + return 0; + return ctx->method->get_by_issuer_serial(ctx, type, name, serial, ret) > 0; +} + +int X509_LOOKUP_by_fingerprint(X509_LOOKUP *ctx, int type, + unsigned char *bytes, int len, + X509_OBJECT *ret) +{ + if ((ctx->method == NULL) || (ctx->method->get_by_fingerprint == NULL)) + return 0; + return ctx->method->get_by_fingerprint(ctx, type, bytes, len, ret) > 0; +} + +int X509_LOOKUP_by_alias(X509_LOOKUP *ctx, int type, char *str, int len, + X509_OBJECT *ret) +{ + if ((ctx->method == NULL) || (ctx->method->get_by_alias == NULL)) + return 0; + return ctx->method->get_by_alias(ctx, type, str, len, ret) > 0; +} + +static int x509_object_cmp(const X509_OBJECT **a, const X509_OBJECT **b) +{ + int ret; + + ret = ((*a)->type - (*b)->type); + if (ret) + return ret; + switch ((*a)->type) { + case X509_LU_X509: + ret = X509_subject_name_cmp((*a)->data.x509, (*b)->data.x509); + break; + case X509_LU_CRL: + ret = X509_CRL_cmp((*a)->data.crl, (*b)->data.crl); + break; + default: + /* abort(); */ + return 0; + } + return ret; +} + +X509_STORE *X509_STORE_new(void) +{ + X509_STORE *ret; + + if ((ret = (X509_STORE *)OPENSSL_malloc(sizeof(X509_STORE))) == NULL) + return NULL; + memset(ret, 0, sizeof(*ret)); + CRYPTO_MUTEX_init(&ret->objs_lock); + ret->objs = sk_X509_OBJECT_new(x509_object_cmp); + if (ret->objs == NULL) + goto err; + ret->cache = 1; + ret->get_cert_methods = sk_X509_LOOKUP_new_null(); + if (ret->get_cert_methods == NULL) + goto err; + ret->param = X509_VERIFY_PARAM_new(); + if (ret->param == NULL) + goto err; + + ret->references = 1; + return ret; + err: + if (ret) { + CRYPTO_MUTEX_cleanup(&ret->objs_lock); + if (ret->param) + X509_VERIFY_PARAM_free(ret->param); + if (ret->get_cert_methods) + sk_X509_LOOKUP_free(ret->get_cert_methods); + if (ret->objs) + sk_X509_OBJECT_free(ret->objs); + OPENSSL_free(ret); + } + return NULL; +} + +void X509_STORE_up_ref(X509_STORE *store) +{ + CRYPTO_refcount_inc(&store->references); +} + +static void cleanup(X509_OBJECT *a) +{ + if (a == NULL) { + return; + } + if (a->type == X509_LU_X509) { + X509_free(a->data.x509); + } else if (a->type == X509_LU_CRL) { + X509_CRL_free(a->data.crl); + } else { + /* abort(); */ + } + + OPENSSL_free(a); +} + +void X509_STORE_free(X509_STORE *vfy) +{ + size_t j; + STACK_OF(X509_LOOKUP) *sk; + X509_LOOKUP *lu; + + if (vfy == NULL) + return; + + if (!CRYPTO_refcount_dec_and_test_zero(&vfy->references)) { + return; + } + + CRYPTO_MUTEX_cleanup(&vfy->objs_lock); + + sk = vfy->get_cert_methods; + for (j = 0; j < sk_X509_LOOKUP_num(sk); j++) { + lu = sk_X509_LOOKUP_value(sk, j); + X509_LOOKUP_shutdown(lu); + X509_LOOKUP_free(lu); + } + sk_X509_LOOKUP_free(sk); + sk_X509_OBJECT_pop_free(vfy->objs, cleanup); + + if (vfy->param) + X509_VERIFY_PARAM_free(vfy->param); + OPENSSL_free(vfy); +} + +X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m) +{ + size_t i; + STACK_OF(X509_LOOKUP) *sk; + X509_LOOKUP *lu; + + sk = v->get_cert_methods; + for (i = 0; i < sk_X509_LOOKUP_num(sk); i++) { + lu = sk_X509_LOOKUP_value(sk, i); + if (m == lu->method) { + return lu; + } + } + /* a new one */ + lu = X509_LOOKUP_new(m); + if (lu == NULL) + return NULL; + else { + lu->store_ctx = v; + if (sk_X509_LOOKUP_push(v->get_cert_methods, lu)) + return lu; + else { + X509_LOOKUP_free(lu); + return NULL; + } + } +} + +int X509_STORE_get_by_subject(X509_STORE_CTX *vs, int type, X509_NAME *name, + X509_OBJECT *ret) +{ + X509_STORE *ctx = vs->ctx; + X509_LOOKUP *lu; + X509_OBJECT stmp, *tmp; + int i; + + CRYPTO_MUTEX_lock_write(&ctx->objs_lock); + tmp = X509_OBJECT_retrieve_by_subject(ctx->objs, type, name); + CRYPTO_MUTEX_unlock_write(&ctx->objs_lock); + + if (tmp == NULL || type == X509_LU_CRL) { + for (i = 0; i < (int)sk_X509_LOOKUP_num(ctx->get_cert_methods); i++) { + lu = sk_X509_LOOKUP_value(ctx->get_cert_methods, i); + if (X509_LOOKUP_by_subject(lu, type, name, &stmp)) { + tmp = &stmp; + break; + } + } + if (tmp == NULL) + return 0; + } + + /* + * if (ret->data.ptr != NULL) X509_OBJECT_free_contents(ret); + */ + + ret->type = tmp->type; + ret->data.ptr = tmp->data.ptr; + + X509_OBJECT_up_ref_count(ret); + + return 1; +} + +int X509_STORE_add_cert(X509_STORE *ctx, X509 *x) +{ + X509_OBJECT *obj; + int ret = 1; + + if (x == NULL) + return 0; + obj = (X509_OBJECT *)OPENSSL_malloc(sizeof(X509_OBJECT)); + if (obj == NULL) { + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + return 0; + } + obj->type = X509_LU_X509; + obj->data.x509 = x; + + CRYPTO_MUTEX_lock_write(&ctx->objs_lock); + + X509_OBJECT_up_ref_count(obj); + + if (X509_OBJECT_retrieve_match(ctx->objs, obj)) { + X509_OBJECT_free_contents(obj); + OPENSSL_free(obj); + OPENSSL_PUT_ERROR(X509, X509_R_CERT_ALREADY_IN_HASH_TABLE); + ret = 0; + } else + sk_X509_OBJECT_push(ctx->objs, obj); + + CRYPTO_MUTEX_unlock_write(&ctx->objs_lock); + + return ret; +} + +int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x) +{ + X509_OBJECT *obj; + int ret = 1; + + if (x == NULL) + return 0; + obj = (X509_OBJECT *)OPENSSL_malloc(sizeof(X509_OBJECT)); + if (obj == NULL) { + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + return 0; + } + obj->type = X509_LU_CRL; + obj->data.crl = x; + + CRYPTO_MUTEX_lock_write(&ctx->objs_lock); + + X509_OBJECT_up_ref_count(obj); + + if (X509_OBJECT_retrieve_match(ctx->objs, obj)) { + X509_OBJECT_free_contents(obj); + OPENSSL_free(obj); + OPENSSL_PUT_ERROR(X509, X509_R_CERT_ALREADY_IN_HASH_TABLE); + ret = 0; + } else + sk_X509_OBJECT_push(ctx->objs, obj); + + CRYPTO_MUTEX_unlock_write(&ctx->objs_lock); + + return ret; +} + +void X509_OBJECT_up_ref_count(X509_OBJECT *a) +{ + switch (a->type) { + case X509_LU_X509: + X509_up_ref(a->data.x509); + break; + case X509_LU_CRL: + X509_CRL_up_ref(a->data.crl); + break; + } +} + +void X509_OBJECT_free_contents(X509_OBJECT *a) +{ + switch (a->type) { + case X509_LU_X509: + X509_free(a->data.x509); + break; + case X509_LU_CRL: + X509_CRL_free(a->data.crl); + break; + } +} + +static int x509_object_idx_cnt(STACK_OF(X509_OBJECT) *h, int type, + X509_NAME *name, int *pnmatch) +{ + X509_OBJECT stmp; + X509 x509_s; + X509_CINF cinf_s; + X509_CRL crl_s; + X509_CRL_INFO crl_info_s; + + stmp.type = type; + switch (type) { + case X509_LU_X509: + stmp.data.x509 = &x509_s; + x509_s.cert_info = &cinf_s; + cinf_s.subject = name; + break; + case X509_LU_CRL: + stmp.data.crl = &crl_s; + crl_s.crl = &crl_info_s; + crl_info_s.issuer = name; + break; + default: + /* abort(); */ + return -1; + } + + size_t idx; + if (!sk_X509_OBJECT_find(h, &idx, &stmp)) + return -1; + + if (pnmatch != NULL) { + int tidx; + const X509_OBJECT *tobj, *pstmp; + *pnmatch = 1; + pstmp = &stmp; + for (tidx = idx + 1; tidx < (int)sk_X509_OBJECT_num(h); tidx++) { + tobj = sk_X509_OBJECT_value(h, tidx); + if (x509_object_cmp(&tobj, &pstmp)) + break; + (*pnmatch)++; + } + } + + return idx; +} + +int X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, int type, + X509_NAME *name) +{ + return x509_object_idx_cnt(h, type, name, NULL); +} + +X509_OBJECT *X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h, + int type, X509_NAME *name) +{ + int idx; + idx = X509_OBJECT_idx_by_subject(h, type, name); + if (idx == -1) + return NULL; + return sk_X509_OBJECT_value(h, idx); +} + +STACK_OF (X509) * X509_STORE_get1_certs(X509_STORE_CTX *ctx, X509_NAME *nm) +{ + int i, idx, cnt; + STACK_OF(X509) *sk; + X509 *x; + X509_OBJECT *obj; + sk = sk_X509_new_null(); + if (sk == NULL) + return NULL; + CRYPTO_MUTEX_lock_write(&ctx->ctx->objs_lock); + idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_X509, nm, &cnt); + if (idx < 0) { + /* + * Nothing found in cache: do lookup to possibly add new objects to + * cache + */ + X509_OBJECT xobj; + CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock); + if (!X509_STORE_get_by_subject(ctx, X509_LU_X509, nm, &xobj)) { + sk_X509_free(sk); + return NULL; + } + X509_OBJECT_free_contents(&xobj); + CRYPTO_MUTEX_lock_write(&ctx->ctx->objs_lock); + idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_X509, nm, &cnt); + if (idx < 0) { + CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock); + sk_X509_free(sk); + return NULL; + } + } + for (i = 0; i < cnt; i++, idx++) { + obj = sk_X509_OBJECT_value(ctx->ctx->objs, idx); + x = obj->data.x509; + if (!sk_X509_push(sk, X509_up_ref(x))) { + CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock); + X509_free(x); + sk_X509_pop_free(sk, X509_free); + return NULL; + } + } + CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock); + return sk; + +} + +STACK_OF (X509_CRL) * X509_STORE_get1_crls(X509_STORE_CTX *ctx, X509_NAME *nm) +{ + int i, idx, cnt; + STACK_OF(X509_CRL) *sk; + X509_CRL *x; + X509_OBJECT *obj, xobj; + sk = sk_X509_CRL_new_null(); + if (sk == NULL) + return NULL; + + /* Always do lookup to possibly add new CRLs to cache. */ + if (!X509_STORE_get_by_subject(ctx, X509_LU_CRL, nm, &xobj)) { + sk_X509_CRL_free(sk); + return NULL; + } + X509_OBJECT_free_contents(&xobj); + CRYPTO_MUTEX_lock_write(&ctx->ctx->objs_lock); + idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_CRL, nm, &cnt); + if (idx < 0) { + CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock); + sk_X509_CRL_free(sk); + return NULL; + } + + for (i = 0; i < cnt; i++, idx++) { + obj = sk_X509_OBJECT_value(ctx->ctx->objs, idx); + x = obj->data.crl; + X509_CRL_up_ref(x); + if (!sk_X509_CRL_push(sk, x)) { + CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock); + X509_CRL_free(x); + sk_X509_CRL_pop_free(sk, X509_CRL_free); + return NULL; + } + } + CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock); + return sk; +} + +X509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h, + X509_OBJECT *x) +{ + size_t idx, i; + X509_OBJECT *obj; + + if (!sk_X509_OBJECT_find(h, &idx, x)) { + return NULL; + } + if ((x->type != X509_LU_X509) && (x->type != X509_LU_CRL)) + return sk_X509_OBJECT_value(h, idx); + for (i = idx; i < sk_X509_OBJECT_num(h); i++) { + obj = sk_X509_OBJECT_value(h, i); + if (x509_object_cmp + ((const X509_OBJECT **)&obj, (const X509_OBJECT **)&x)) + return NULL; + if (x->type == X509_LU_X509) { + if (!X509_cmp(obj->data.x509, x->data.x509)) + return obj; + } else if (x->type == X509_LU_CRL) { + if (!X509_CRL_match(obj->data.crl, x->data.crl)) + return obj; + } else + return obj; + } + return NULL; +} + +/* + * Try to get issuer certificate from store. Due to limitations of the API + * this can only retrieve a single certificate matching a given subject name. + * However it will fill the cache with all matching certificates, so we can + * examine the cache for all matches. Return values are: 1 lookup + * successful. 0 certificate not found. -1 some other error. + */ +int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x) +{ + X509_NAME *xn; + X509_OBJECT obj, *pobj; + int idx, ret; + size_t i; + xn = X509_get_issuer_name(x); + if (!X509_STORE_get_by_subject(ctx, X509_LU_X509, xn, &obj)) + return 0; + /* If certificate matches all OK */ + if (ctx->check_issued(ctx, x, obj.data.x509)) { + *issuer = obj.data.x509; + return 1; + } + X509_OBJECT_free_contents(&obj); + + /* Else find index of first cert accepted by 'check_issued' */ + ret = 0; + CRYPTO_MUTEX_lock_write(&ctx->ctx->objs_lock); + idx = X509_OBJECT_idx_by_subject(ctx->ctx->objs, X509_LU_X509, xn); + if (idx != -1) { /* should be true as we've had at least one + * match */ + /* Look through all matching certs for suitable issuer */ + for (i = idx; i < sk_X509_OBJECT_num(ctx->ctx->objs); i++) { + pobj = sk_X509_OBJECT_value(ctx->ctx->objs, i); + /* See if we've run past the matches */ + if (pobj->type != X509_LU_X509) + break; + if (X509_NAME_cmp(xn, X509_get_subject_name(pobj->data.x509))) + break; + if (ctx->check_issued(ctx, x, pobj->data.x509)) { + *issuer = pobj->data.x509; + X509_OBJECT_up_ref_count(pobj); + ret = 1; + break; + } + } + } + CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock); + return ret; +} + +int X509_STORE_set_flags(X509_STORE *ctx, unsigned long flags) +{ + return X509_VERIFY_PARAM_set_flags(ctx->param, flags); +} + +int X509_STORE_set_depth(X509_STORE *ctx, int depth) +{ + X509_VERIFY_PARAM_set_depth(ctx->param, depth); + return 1; +} + +int X509_STORE_set_purpose(X509_STORE *ctx, int purpose) +{ + return X509_VERIFY_PARAM_set_purpose(ctx->param, purpose); +} + +int X509_STORE_set_trust(X509_STORE *ctx, int trust) +{ + return X509_VERIFY_PARAM_set_trust(ctx->param, trust); +} + +int X509_STORE_set1_param(X509_STORE *ctx, X509_VERIFY_PARAM *param) +{ + return X509_VERIFY_PARAM_set1(ctx->param, param); +} + +void X509_STORE_set_verify_cb(X509_STORE *ctx, + int (*verify_cb) (int, X509_STORE_CTX *)) +{ + ctx->verify_cb = verify_cb; +} + +void X509_STORE_set_lookup_crls_cb(X509_STORE *ctx, + STACK_OF (X509_CRL) * + (*cb) (X509_STORE_CTX *ctx, X509_NAME *nm)) +{ + ctx->lookup_crls = cb; +} + +X509_STORE *X509_STORE_CTX_get0_store(X509_STORE_CTX *ctx) +{ + return ctx->ctx; +} diff --git a/external/boringssl/crypto/x509/x509_obj.c b/external/boringssl/crypto/x509/x509_obj.c new file mode 100644 index 0000000000..a7f31e0325 --- /dev/null +++ b/external/boringssl/crypto/x509/x509_obj.c @@ -0,0 +1,197 @@ +/* crypto/x509/x509_obj.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include +#include +#include +#include +#include + +/* + * Limit to ensure we don't overflow: much greater than + * anything enountered in practice. + */ + +#define NAME_ONELINE_MAX (1024 * 1024) + +char *X509_NAME_oneline(X509_NAME *a, char *buf, int len) +{ + X509_NAME_ENTRY *ne; + size_t i; + int n, lold, l, l1, l2, num, j, type; + const char *s; + char *p; + unsigned char *q; + BUF_MEM *b = NULL; + static const char hex[17] = "0123456789ABCDEF"; + int gs_doit[4]; + char tmp_buf[80]; + + if (buf == NULL) { + if ((b = BUF_MEM_new()) == NULL) + goto err; + if (!BUF_MEM_grow(b, 200)) + goto err; + b->data[0] = '\0'; + len = 200; + } else if (len <= 0) { + return NULL; + } + if (a == NULL) { + if (b) { + buf = b->data; + OPENSSL_free(b); + } + strncpy(buf, "NO X509_NAME", len); + buf[len - 1] = '\0'; + return buf; + } + + len--; /* space for '\0' */ + l = 0; + for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) { + ne = sk_X509_NAME_ENTRY_value(a->entries, i); + n = OBJ_obj2nid(ne->object); + if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) { + i2t_ASN1_OBJECT(tmp_buf, sizeof(tmp_buf), ne->object); + s = tmp_buf; + } + l1 = strlen(s); + + type = ne->value->type; + num = ne->value->length; + if (num > NAME_ONELINE_MAX) { + OPENSSL_PUT_ERROR(X509, X509_R_NAME_TOO_LONG); + goto end; + } + q = ne->value->data; + + if ((type == V_ASN1_GENERALSTRING) && ((num % 4) == 0)) { + gs_doit[0] = gs_doit[1] = gs_doit[2] = gs_doit[3] = 0; + for (j = 0; j < num; j++) + if (q[j] != 0) + gs_doit[j & 3] = 1; + + if (gs_doit[0] | gs_doit[1] | gs_doit[2]) + gs_doit[0] = gs_doit[1] = gs_doit[2] = gs_doit[3] = 1; + else { + gs_doit[0] = gs_doit[1] = gs_doit[2] = 0; + gs_doit[3] = 1; + } + } else + gs_doit[0] = gs_doit[1] = gs_doit[2] = gs_doit[3] = 1; + + for (l2 = j = 0; j < num; j++) { + if (!gs_doit[j & 3]) + continue; + l2++; + if ((q[j] < ' ') || (q[j] > '~')) + l2 += 3; + } + + lold = l; + l += 1 + l1 + 1 + l2; + if (l > NAME_ONELINE_MAX) { + OPENSSL_PUT_ERROR(X509, X509_R_NAME_TOO_LONG); + goto end; + } + if (b != NULL) { + if (!BUF_MEM_grow(b, l + 1)) + goto err; + p = &(b->data[lold]); + } else if (l > len) { + break; + } else + p = &(buf[lold]); + *(p++) = '/'; + memcpy(p, s, (unsigned int)l1); + p += l1; + *(p++) = '='; + + q = ne->value->data; + + for (j = 0; j < num; j++) { + if (!gs_doit[j & 3]) + continue; + n = q[j]; + if ((n < ' ') || (n > '~')) { + *(p++) = '\\'; + *(p++) = 'x'; + *(p++) = hex[(n >> 4) & 0x0f]; + *(p++) = hex[n & 0x0f]; + } else + *(p++) = n; + } + *p = '\0'; + } + if (b != NULL) { + p = b->data; + OPENSSL_free(b); + } else + p = buf; + if (i == 0) + *p = '\0'; + return (p); + err: + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + end: + BUF_MEM_free(b); + return (NULL); +} diff --git a/external/boringssl/crypto/x509/x509_r2x.c b/external/boringssl/crypto/x509/x509_r2x.c new file mode 100644 index 0000000000..83951a2e78 --- /dev/null +++ b/external/boringssl/crypto/x509/x509_r2x.c @@ -0,0 +1,113 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include +#include +#include +#include +#include +#include +#include +#include + +X509 *X509_REQ_to_X509(X509_REQ *r, int days, EVP_PKEY *pkey) +{ + X509 *ret = NULL; + X509_CINF *xi = NULL; + X509_NAME *xn; + + if ((ret = X509_new()) == NULL) { + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + goto err; + } + + /* duplicate the request */ + xi = ret->cert_info; + + if (sk_X509_ATTRIBUTE_num(r->req_info->attributes) != 0) { + if ((xi->version = M_ASN1_INTEGER_new()) == NULL) + goto err; + if (!ASN1_INTEGER_set(xi->version, 2)) + goto err; + /* + * xi->extensions=ri->attributes; <- bad, should not ever be done + * ri->attributes=NULL; + */ + } + + xn = X509_REQ_get_subject_name(r); + if (X509_set_subject_name(ret, X509_NAME_dup(xn)) == 0) + goto err; + if (X509_set_issuer_name(ret, X509_NAME_dup(xn)) == 0) + goto err; + + if (X509_gmtime_adj(xi->validity->notBefore, 0) == NULL) + goto err; + if (X509_gmtime_adj(xi->validity->notAfter, (long)60 * 60 * 24 * days) == + NULL) + goto err; + + X509_set_pubkey(ret, X509_REQ_get_pubkey(r)); + + if (!X509_sign(ret, pkey, EVP_md5())) + goto err; + if (0) { + err: + X509_free(ret); + ret = NULL; + } + return (ret); +} diff --git a/external/boringssl/crypto/x509/x509_req.c b/external/boringssl/crypto/x509/x509_req.c new file mode 100644 index 0000000000..69bc6f114d --- /dev/null +++ b/external/boringssl/crypto/x509/x509_req.c @@ -0,0 +1,322 @@ +/* crypto/x509/x509_req.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +X509_REQ *X509_to_X509_REQ(X509 *x, EVP_PKEY *pkey, const EVP_MD *md) +{ + X509_REQ *ret; + X509_REQ_INFO *ri; + int i; + EVP_PKEY *pktmp; + + ret = X509_REQ_new(); + if (ret == NULL) { + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + goto err; + } + + ri = ret->req_info; + + ri->version->length = 1; + ri->version->data = (unsigned char *)OPENSSL_malloc(1); + if (ri->version->data == NULL) + goto err; + ri->version->data[0] = 0; /* version == 0 */ + + if (!X509_REQ_set_subject_name(ret, X509_get_subject_name(x))) + goto err; + + pktmp = X509_get_pubkey(x); + if (pktmp == NULL) + goto err; + i = X509_REQ_set_pubkey(ret, pktmp); + EVP_PKEY_free(pktmp); + if (!i) + goto err; + + if (pkey != NULL) { + if (!X509_REQ_sign(ret, pkey, md)) + goto err; + } + return (ret); + err: + X509_REQ_free(ret); + return (NULL); +} + +EVP_PKEY *X509_REQ_get_pubkey(X509_REQ *req) +{ + if ((req == NULL) || (req->req_info == NULL)) + return (NULL); + return (X509_PUBKEY_get(req->req_info->pubkey)); +} + +int X509_REQ_check_private_key(X509_REQ *x, EVP_PKEY *k) +{ + EVP_PKEY *xk = NULL; + int ok = 0; + + xk = X509_REQ_get_pubkey(x); + switch (EVP_PKEY_cmp(xk, k)) { + case 1: + ok = 1; + break; + case 0: + OPENSSL_PUT_ERROR(X509, X509_R_KEY_VALUES_MISMATCH); + break; + case -1: + OPENSSL_PUT_ERROR(X509, X509_R_KEY_TYPE_MISMATCH); + break; + case -2: + if (k->type == EVP_PKEY_EC) { + OPENSSL_PUT_ERROR(X509, ERR_R_EC_LIB); + break; + } + if (k->type == EVP_PKEY_DH) { + /* No idea */ + OPENSSL_PUT_ERROR(X509, X509_R_CANT_CHECK_DH_KEY); + break; + } + OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_KEY_TYPE); + } + + EVP_PKEY_free(xk); + return (ok); +} + +/* + * It seems several organisations had the same idea of including a list of + * extensions in a certificate request. There are at least two OIDs that are + * used and there may be more: so the list is configurable. + */ + +static const int ext_nid_list[] = { NID_ext_req, NID_ms_ext_req, NID_undef }; + +static const int *ext_nids = ext_nid_list; + +int X509_REQ_extension_nid(int req_nid) +{ + int i, nid; + for (i = 0;; i++) { + nid = ext_nids[i]; + if (nid == NID_undef) + return 0; + else if (req_nid == nid) + return 1; + } +} + +const int *X509_REQ_get_extension_nids(void) +{ + return ext_nids; +} + +void X509_REQ_set_extension_nids(const int *nids) +{ + ext_nids = nids; +} + +STACK_OF(X509_EXTENSION) *X509_REQ_get_extensions(X509_REQ *req) +{ + X509_ATTRIBUTE *attr; + ASN1_TYPE *ext = NULL; + int idx; + const int *pnid; + const unsigned char *p; + + if ((req == NULL) || (req->req_info == NULL) || !ext_nids) + return (NULL); + for (pnid = ext_nids; *pnid != NID_undef; pnid++) { + idx = X509_REQ_get_attr_by_NID(req, *pnid, -1); + if (idx == -1) + continue; + attr = X509_REQ_get_attr(req, idx); + if (attr->single) + ext = attr->value.single; + else if (sk_ASN1_TYPE_num(attr->value.set)) + ext = sk_ASN1_TYPE_value(attr->value.set, 0); + break; + } + if (!ext || (ext->type != V_ASN1_SEQUENCE)) + return NULL; + p = ext->value.sequence->data; + return (STACK_OF(X509_EXTENSION) *) + ASN1_item_d2i(NULL, &p, ext->value.sequence->length, + ASN1_ITEM_rptr(X509_EXTENSIONS)); +} + +/* + * Add a STACK_OF extensions to a certificate request: allow alternative OIDs + * in case we want to create a non standard one. + */ + +int X509_REQ_add_extensions_nid(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts, + int nid) +{ + ASN1_TYPE *at = NULL; + X509_ATTRIBUTE *attr = NULL; + if (!(at = ASN1_TYPE_new()) || !(at->value.sequence = ASN1_STRING_new())) + goto err; + + at->type = V_ASN1_SEQUENCE; + /* Generate encoding of extensions */ + at->value.sequence->length = + ASN1_item_i2d((ASN1_VALUE *)exts, + &at->value.sequence->data, + ASN1_ITEM_rptr(X509_EXTENSIONS)); + if (!(attr = X509_ATTRIBUTE_new())) + goto err; + if (!(attr->value.set = sk_ASN1_TYPE_new_null())) + goto err; + if (!sk_ASN1_TYPE_push(attr->value.set, at)) + goto err; + at = NULL; + attr->single = 0; + attr->object = (ASN1_OBJECT *)OBJ_nid2obj(nid); + if (!req->req_info->attributes) { + if (!(req->req_info->attributes = sk_X509_ATTRIBUTE_new_null())) + goto err; + } + if (!sk_X509_ATTRIBUTE_push(req->req_info->attributes, attr)) + goto err; + return 1; + err: + X509_ATTRIBUTE_free(attr); + ASN1_TYPE_free(at); + return 0; +} + +/* This is the normal usage: use the "official" OID */ +int X509_REQ_add_extensions(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts) +{ + return X509_REQ_add_extensions_nid(req, exts, NID_ext_req); +} + +/* Request attribute functions */ + +int X509_REQ_get_attr_count(const X509_REQ *req) +{ + return X509at_get_attr_count(req->req_info->attributes); +} + +int X509_REQ_get_attr_by_NID(const X509_REQ *req, int nid, int lastpos) +{ + return X509at_get_attr_by_NID(req->req_info->attributes, nid, lastpos); +} + +int X509_REQ_get_attr_by_OBJ(const X509_REQ *req, ASN1_OBJECT *obj, + int lastpos) +{ + return X509at_get_attr_by_OBJ(req->req_info->attributes, obj, lastpos); +} + +X509_ATTRIBUTE *X509_REQ_get_attr(const X509_REQ *req, int loc) +{ + return X509at_get_attr(req->req_info->attributes, loc); +} + +X509_ATTRIBUTE *X509_REQ_delete_attr(X509_REQ *req, int loc) +{ + return X509at_delete_attr(req->req_info->attributes, loc); +} + +int X509_REQ_add1_attr(X509_REQ *req, X509_ATTRIBUTE *attr) +{ + if (X509at_add1_attr(&req->req_info->attributes, attr)) + return 1; + return 0; +} + +int X509_REQ_add1_attr_by_OBJ(X509_REQ *req, + const ASN1_OBJECT *obj, int type, + const unsigned char *bytes, int len) +{ + if (X509at_add1_attr_by_OBJ(&req->req_info->attributes, obj, + type, bytes, len)) + return 1; + return 0; +} + +int X509_REQ_add1_attr_by_NID(X509_REQ *req, + int nid, int type, + const unsigned char *bytes, int len) +{ + if (X509at_add1_attr_by_NID(&req->req_info->attributes, nid, + type, bytes, len)) + return 1; + return 0; +} + +int X509_REQ_add1_attr_by_txt(X509_REQ *req, + const char *attrname, int type, + const unsigned char *bytes, int len) +{ + if (X509at_add1_attr_by_txt(&req->req_info->attributes, attrname, + type, bytes, len)) + return 1; + return 0; +} diff --git a/external/boringssl/crypto/x509/x509_set.c b/external/boringssl/crypto/x509/x509_set.c new file mode 100644 index 0000000000..42e9cf0f15 --- /dev/null +++ b/external/boringssl/crypto/x509/x509_set.c @@ -0,0 +1,149 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include +#include +#include +#include +#include + +int X509_set_version(X509 *x, long version) +{ + if (x == NULL) + return (0); + if (version == 0) { + M_ASN1_INTEGER_free(x->cert_info->version); + x->cert_info->version = NULL; + return (1); + } + if (x->cert_info->version == NULL) { + if ((x->cert_info->version = M_ASN1_INTEGER_new()) == NULL) + return (0); + } + return (ASN1_INTEGER_set(x->cert_info->version, version)); +} + +int X509_set_serialNumber(X509 *x, ASN1_INTEGER *serial) +{ + ASN1_INTEGER *in; + + if (x == NULL) + return (0); + in = x->cert_info->serialNumber; + if (in != serial) { + in = M_ASN1_INTEGER_dup(serial); + if (in != NULL) { + M_ASN1_INTEGER_free(x->cert_info->serialNumber); + x->cert_info->serialNumber = in; + } + } + return (in != NULL); +} + +int X509_set_issuer_name(X509 *x, X509_NAME *name) +{ + if ((x == NULL) || (x->cert_info == NULL)) + return (0); + return (X509_NAME_set(&x->cert_info->issuer, name)); +} + +int X509_set_subject_name(X509 *x, X509_NAME *name) +{ + if ((x == NULL) || (x->cert_info == NULL)) + return (0); + return (X509_NAME_set(&x->cert_info->subject, name)); +} + +int X509_set_notBefore(X509 *x, const ASN1_TIME *tm) +{ + ASN1_TIME *in; + + if ((x == NULL) || (x->cert_info->validity == NULL)) + return (0); + in = x->cert_info->validity->notBefore; + if (in != tm) { + in = M_ASN1_TIME_dup(tm); + if (in != NULL) { + M_ASN1_TIME_free(x->cert_info->validity->notBefore); + x->cert_info->validity->notBefore = in; + } + } + return (in != NULL); +} + +int X509_set_notAfter(X509 *x, const ASN1_TIME *tm) +{ + ASN1_TIME *in; + + if ((x == NULL) || (x->cert_info->validity == NULL)) + return (0); + in = x->cert_info->validity->notAfter; + if (in != tm) { + in = M_ASN1_TIME_dup(tm); + if (in != NULL) { + M_ASN1_TIME_free(x->cert_info->validity->notAfter); + x->cert_info->validity->notAfter = in; + } + } + return (in != NULL); +} + +int X509_set_pubkey(X509 *x, EVP_PKEY *pkey) +{ + if ((x == NULL) || (x->cert_info == NULL)) + return (0); + return (X509_PUBKEY_set(&(x->cert_info->key), pkey)); +} diff --git a/external/boringssl/crypto/x509/x509_test.cc b/external/boringssl/crypto/x509/x509_test.cc new file mode 100644 index 0000000000..650163a8a5 --- /dev/null +++ b/external/boringssl/crypto/x509/x509_test.cc @@ -0,0 +1,472 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "../test/scoped_types.h" + + +static const char kCrossSigningRootPEM[] = +"-----BEGIN CERTIFICATE-----\n" +"MIICcTCCAdqgAwIBAgIIagJHiPvE0MowDQYJKoZIhvcNAQELBQAwPDEaMBgGA1UE\n" +"ChMRQm9yaW5nU1NMIFRFU1RJTkcxHjAcBgNVBAMTFUNyb3NzLXNpZ25pbmcgUm9v\n" +"dCBDQTAgFw0xNTAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowPDEaMBgGA1UE\n" +"ChMRQm9yaW5nU1NMIFRFU1RJTkcxHjAcBgNVBAMTFUNyb3NzLXNpZ25pbmcgUm9v\n" +"dCBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwo3qFvSB9Zmlbpzn9wJp\n" +"ikI75Rxkatez8VkLqyxbOhPYl2Haz8F5p1gDG96dCI6jcLGgu3AKT9uhEQyyUko5\n" +"EKYasazSeA9CQrdyhPg0mkTYVETnPM1W/ebid1YtqQbq1CMWlq2aTDoSGAReGFKP\n" +"RTdXAbuAXzpCfi/d8LqV13UCAwEAAaN6MHgwDgYDVR0PAQH/BAQDAgIEMB0GA1Ud\n" +"JQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAPBgNVHRMBAf8EBTADAQH/MBkGA1Ud\n" +"DgQSBBBHKHC7V3Z/3oLvEZx0RZRwMBsGA1UdIwQUMBKAEEcocLtXdn/egu8RnHRF\n" +"lHAwDQYJKoZIhvcNAQELBQADgYEAnglibsy6mGtpIXivtlcz4zIEnHw/lNW+r/eC\n" +"CY7evZTmOoOuC/x9SS3MF9vawt1HFUummWM6ZgErqVBOXIB4//ykrcCgf5ZbF5Hr\n" +"+3EFprKhBqYiXdD8hpBkrBoXwn85LPYWNd2TceCrx0YtLIprE2R5MB2RIq8y4Jk3\n" +"YFXvkME=\n" +"-----END CERTIFICATE-----\n"; + +static const char kRootCAPEM[] = +"-----BEGIN CERTIFICATE-----\n" +"MIICVTCCAb6gAwIBAgIIAj5CwoHlWuYwDQYJKoZIhvcNAQELBQAwLjEaMBgGA1UE\n" +"ChMRQm9yaW5nU1NMIFRFU1RJTkcxEDAOBgNVBAMTB1Jvb3QgQ0EwIBcNMTUwMTAx\n" +"MDAwMDAwWhgPMjEwMDAxMDEwMDAwMDBaMC4xGjAYBgNVBAoTEUJvcmluZ1NTTCBU\n" +"RVNUSU5HMRAwDgYDVQQDEwdSb290IENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB\n" +"iQKBgQDpDn8RDOZa5oaDcPZRBy4CeBH1siSSOO4mYgLHlPE+oXdqwI/VImi2XeJM\n" +"2uCFETXCknJJjYG0iJdrt/yyRFvZTQZw+QzGj+mz36NqhGxDWb6dstB2m8PX+plZ\n" +"w7jl81MDvUnWs8yiQ/6twgu5AbhWKZQDJKcNKCEpqa6UW0r5nwIDAQABo3oweDAO\n" +"BgNVHQ8BAf8EBAMCAgQwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA8G\n" +"A1UdEwEB/wQFMAMBAf8wGQYDVR0OBBIEEEA31wH7QC+4HH5UBCeMWQEwGwYDVR0j\n" +"BBQwEoAQQDfXAftAL7gcflQEJ4xZATANBgkqhkiG9w0BAQsFAAOBgQDXylEK77Za\n" +"kKeY6ZerrScWyZhrjIGtHFu09qVpdJEzrk87k2G7iHHR9CAvSofCgEExKtWNS9dN\n" +"+9WiZp/U48iHLk7qaYXdEuO07No4BYtXn+lkOykE+FUxmA4wvOF1cTd2tdj3MzX2\n" +"kfGIBAYhzGZWhY3JbhIfTEfY1PNM1pWChQ==\n" +"-----END CERTIFICATE-----\n"; + +static const char kRootCrossSignedPEM[] = +"-----BEGIN CERTIFICATE-----\n" +"MIICYzCCAcygAwIBAgIIAj5CwoHlWuYwDQYJKoZIhvcNAQELBQAwPDEaMBgGA1UE\n" +"ChMRQm9yaW5nU1NMIFRFU1RJTkcxHjAcBgNVBAMTFUNyb3NzLXNpZ25pbmcgUm9v\n" +"dCBDQTAgFw0xNTAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowLjEaMBgGA1UE\n" +"ChMRQm9yaW5nU1NMIFRFU1RJTkcxEDAOBgNVBAMTB1Jvb3QgQ0EwgZ8wDQYJKoZI\n" +"hvcNAQEBBQADgY0AMIGJAoGBAOkOfxEM5lrmhoNw9lEHLgJ4EfWyJJI47iZiAseU\n" +"8T6hd2rAj9UiaLZd4kza4IURNcKSckmNgbSIl2u3/LJEW9lNBnD5DMaP6bPfo2qE\n" +"bENZvp2y0Habw9f6mVnDuOXzUwO9SdazzKJD/q3CC7kBuFYplAMkpw0oISmprpRb\n" +"SvmfAgMBAAGjejB4MA4GA1UdDwEB/wQEAwICBDAdBgNVHSUEFjAUBggrBgEFBQcD\n" +"AQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUwAwEB/zAZBgNVHQ4EEgQQQDfXAftAL7gc\n" +"flQEJ4xZATAbBgNVHSMEFDASgBBHKHC7V3Z/3oLvEZx0RZRwMA0GCSqGSIb3DQEB\n" +"CwUAA4GBAErTxYJ0en9HVRHAAr5OO5wuk5Iq3VMc79TMyQLCXVL8YH8Uk7KEwv+q\n" +"9MEKZv2eR/Vfm4HlXlUuIqfgUXbwrAYC/YVVX86Wnbpy/jc73NYVCq8FEZeO+0XU\n" +"90SWAPDdp+iL7aZdimnMtG1qlM1edmz8AKbrhN/R3IbA2CL0nCWV\n" +"-----END CERTIFICATE-----\n"; + +static const char kIntermediatePEM[] = +"-----BEGIN CERTIFICATE-----\n" +"MIICXjCCAcegAwIBAgIJAKJMH+7rscPcMA0GCSqGSIb3DQEBCwUAMC4xGjAYBgNV\n" +"BAoTEUJvcmluZ1NTTCBURVNUSU5HMRAwDgYDVQQDEwdSb290IENBMCAXDTE1MDEw\n" +"MTAwMDAwMFoYDzIxMDAwMTAxMDAwMDAwWjA2MRowGAYDVQQKExFCb3JpbmdTU0wg\n" +"VEVTVElORzEYMBYGA1UEAxMPSW50ZXJtZWRpYXRlIENBMIGfMA0GCSqGSIb3DQEB\n" +"AQUAA4GNADCBiQKBgQC7YtI0l8ocTYJ0gKyXTtPL4iMJCNY4OcxXl48jkncVG1Hl\n" +"blicgNUa1r9m9YFtVkxvBinb8dXiUpEGhVg4awRPDcatlsBSEBuJkiZGYbRcAmSu\n" +"CmZYnf6u3aYQ18SU8WqVERPpE4cwVVs+6kwlzRw0+XDoZAczu8ZezVhCUc6NbQID\n" +"AQABo3oweDAOBgNVHQ8BAf8EBAMCAgQwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG\n" +"AQUFBwMCMA8GA1UdEwEB/wQFMAMBAf8wGQYDVR0OBBIEEIwaaKi1dttdV3sfjRSy\n" +"BqMwGwYDVR0jBBQwEoAQQDfXAftAL7gcflQEJ4xZATANBgkqhkiG9w0BAQsFAAOB\n" +"gQCvnolNWEHuQS8PFVVyuLR+FKBeUUdrVbSfHSzTqNAqQGp0C9fk5oCzDq6ZgTfY\n" +"ESXM4cJhb3IAnW0UM0NFsYSKQJ50JZL2L3z5ZLQhHdbs4RmODGoC40BVdnJ4/qgB\n" +"aGSh09eQRvAVmbVCviDK2ipkWNegdyI19jFfNP5uIkGlYg==\n" +"-----END CERTIFICATE-----\n"; + +static const char kIntermediateSelfSignedPEM[] = +"-----BEGIN CERTIFICATE-----\n" +"MIICZjCCAc+gAwIBAgIJAKJMH+7rscPcMA0GCSqGSIb3DQEBCwUAMDYxGjAYBgNV\n" +"BAoTEUJvcmluZ1NTTCBURVNUSU5HMRgwFgYDVQQDEw9JbnRlcm1lZGlhdGUgQ0Ew\n" +"IBcNMTUwMTAxMDAwMDAwWhgPMjEwMDAxMDEwMDAwMDBaMDYxGjAYBgNVBAoTEUJv\n" +"cmluZ1NTTCBURVNUSU5HMRgwFgYDVQQDEw9JbnRlcm1lZGlhdGUgQ0EwgZ8wDQYJ\n" +"KoZIhvcNAQEBBQADgY0AMIGJAoGBALti0jSXyhxNgnSArJdO08viIwkI1jg5zFeX\n" +"jyOSdxUbUeVuWJyA1RrWv2b1gW1WTG8GKdvx1eJSkQaFWDhrBE8Nxq2WwFIQG4mS\n" +"JkZhtFwCZK4KZlid/q7dphDXxJTxapURE+kThzBVWz7qTCXNHDT5cOhkBzO7xl7N\n" +"WEJRzo1tAgMBAAGjejB4MA4GA1UdDwEB/wQEAwICBDAdBgNVHSUEFjAUBggrBgEF\n" +"BQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUwAwEB/zAZBgNVHQ4EEgQQjBpoqLV2\n" +"211Xex+NFLIGozAbBgNVHSMEFDASgBCMGmiotXbbXVd7H40UsgajMA0GCSqGSIb3\n" +"DQEBCwUAA4GBALcccSrAQ0/EqQBsx0ZDTUydHXXNP2DrUkpUKmAXIe8McqIVSlkT\n" +"6H4xz7z8VRKBo9j+drjjtCw2i0CQc8aOLxRb5WJ8eVLnaW2XRlUqAzhF0CrulfVI\n" +"E4Vs6ZLU+fra1WAuIj6qFiigRja+3YkZArG8tMA9vtlhTX/g7YBZIkqH\n" +"-----END CERTIFICATE-----\n"; + +static const char kLeafPEM[] = +"-----BEGIN CERTIFICATE-----\n" +"MIICXjCCAcegAwIBAgIIWjO48ufpunYwDQYJKoZIhvcNAQELBQAwNjEaMBgGA1UE\n" +"ChMRQm9yaW5nU1NMIFRFU1RJTkcxGDAWBgNVBAMTD0ludGVybWVkaWF0ZSBDQTAg\n" +"Fw0xNTAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowMjEaMBgGA1UEChMRQm9y\n" +"aW5nU1NMIFRFU1RJTkcxFDASBgNVBAMTC2V4YW1wbGUuY29tMIGfMA0GCSqGSIb3\n" +"DQEBAQUAA4GNADCBiQKBgQDD0U0ZYgqShJ7oOjsyNKyVXEHqeafmk/bAoPqY/h1c\n" +"oPw2E8KmeqiUSoTPjG5IXSblOxcqpbAXgnjPzo8DI3GNMhAf8SYNYsoH7gc7Uy7j\n" +"5x8bUrisGnuTHqkqH6d4/e7ETJ7i3CpR8bvK16DggEvQTudLipz8FBHtYhFakfdh\n" +"TwIDAQABo3cwdTAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEG\n" +"CCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwGQYDVR0OBBIEEKN5pvbur7mlXjeMEYA0\n" +"4nUwGwYDVR0jBBQwEoAQjBpoqLV2211Xex+NFLIGozANBgkqhkiG9w0BAQsFAAOB\n" +"gQBj/p+JChp//LnXWC1k121LM/ii7hFzQzMrt70bny406SGz9jAjaPOX4S3gt38y\n" +"rhjpPukBlSzgQXFg66y6q5qp1nQTD1Cw6NkKBe9WuBlY3iYfmsf7WT8nhlT1CttU\n" +"xNCwyMX9mtdXdQicOfNjIGUCD5OLV5PgHFPRKiHHioBAhg==\n" +"-----END CERTIFICATE-----\n"; + +static const char kLeafNoKeyUsagePEM[] = +"-----BEGIN CERTIFICATE-----\n" +"MIICNTCCAZ6gAwIBAgIJAIFQGaLQ0G2mMA0GCSqGSIb3DQEBCwUAMDYxGjAYBgNV\n" +"BAoTEUJvcmluZ1NTTCBURVNUSU5HMRgwFgYDVQQDEw9JbnRlcm1lZGlhdGUgQ0Ew\n" +"IBcNMTUwMTAxMDAwMDAwWhgPMjEwMDAxMDEwMDAwMDBaMDcxGjAYBgNVBAoTEUJv\n" +"cmluZ1NTTCBURVNUSU5HMRkwFwYDVQQDExBldmlsLmV4YW1wbGUuY29tMIGfMA0G\n" +"CSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOKoZe75NPz77EOaMMl4/0s3PyQw++zJvp\n" +"ejHAxZiTPCJgMbEHLrSzNoHdopg+CLUH5bE4wTXM8w9Inv5P8OAFJt7gJuPUunmk\n" +"j+NoU3QfzOR6BroePcz1vXX9jyVHRs087M/sLqWRHu9IR+/A+UTcBaWaFiDVUxtJ\n" +"YOwFMwjNPQIDAQABo0gwRjAMBgNVHRMBAf8EAjAAMBkGA1UdDgQSBBBJfLEUWHq1\n" +"27rZ1AVx2J5GMBsGA1UdIwQUMBKAEIwaaKi1dttdV3sfjRSyBqMwDQYJKoZIhvcN\n" +"AQELBQADgYEALVKN2Y3LZJOtu6SxFIYKxbLaXhTGTdIjxipZhmbBRDFjbZjZZOTe\n" +"6Oo+VDNPYco4rBexK7umYXJyfTqoY0E8dbiImhTcGTEj7OAB3DbBomgU1AYe+t2D\n" +"uwBqh4Y3Eto+Zn4pMVsxGEfUpjzjZDel7bN1/oU/9KWPpDfywfUmjgk=\n" +"-----END CERTIFICATE-----\n"; + +static const char kForgeryPEM[] = +"-----BEGIN CERTIFICATE-----\n" +"MIICZzCCAdCgAwIBAgIIdTlMzQoKkeMwDQYJKoZIhvcNAQELBQAwNzEaMBgGA1UE\n" +"ChMRQm9yaW5nU1NMIFRFU1RJTkcxGTAXBgNVBAMTEGV2aWwuZXhhbXBsZS5jb20w\n" +"IBcNMTUwMTAxMDAwMDAwWhgPMjEwMDAxMDEwMDAwMDBaMDoxGjAYBgNVBAoTEUJv\n" +"cmluZ1NTTCBURVNUSU5HMRwwGgYDVQQDExNmb3JnZXJ5LmV4YW1wbGUuY29tMIGf\n" +"MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDADTwruBQZGb7Ay6s9HiYv5d1lwtEy\n" +"xQdA2Sy8Rn8uA20Q4KgqwVY7wzIZ+z5Butrsmwb70gdG1XU+yRaDeE7XVoW6jSpm\n" +"0sw35/5vJbTcL4THEFbnX0OPZnvpuZDFUkvVtq5kxpDWsVyM24G8EEq7kPih3Sa3\n" +"OMhXVXF8kso6UQIDAQABo3cwdTAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYI\n" +"KwYBBQUHAwEGCCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwGQYDVR0OBBIEEEYJ/WHM\n" +"8p64erPWIg4/liwwGwYDVR0jBBQwEoAQSXyxFFh6tdu62dQFcdieRjANBgkqhkiG\n" +"9w0BAQsFAAOBgQA+zH7bHPElWRWJvjxDqRexmYLn+D3Aivs8XgXQJsM94W0EzSUf\n" +"DSLfRgaQwcb2gg2xpDFoG+W0vc6O651uF23WGt5JaFFJJxqjII05IexfCNhuPmp4\n" +"4UZAXPttuJXpn74IY1tuouaM06B3vXKZR+/ityKmfJvSwxacmFcK+2ziAg==\n" +"-----END CERTIFICATE-----\n"; + +// kExamplePSSCert is an example RSA-PSS self-signed certificate, signed with +// the default hash functions. +static const char kExamplePSSCert[] = +"-----BEGIN CERTIFICATE-----\n" +"MIICYjCCAcagAwIBAgIJAI3qUyT6SIfzMBIGCSqGSIb3DQEBCjAFogMCAWowRTEL\n" +"MAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVy\n" +"bmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0xNDEwMDkxOTA5NTVaFw0xNTEwMDkxOTA5\n" +"NTVaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQK\n" +"DBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwgZ8wDQYJKoZIhvcNAQEBBQADgY0A\n" +"MIGJAoGBAPi4bIO0vNmoV8CltFl2jFQdeesiUgR+0zfrQf2D+fCmhRU0dXFahKg8\n" +"0u9aTtPel4rd/7vPCqqGkr64UOTNb4AzMHYTj8p73OxaymPHAyXvqIqDWHYg+hZ3\n" +"13mSYwFIGth7Z/FSVUlO1m5KXNd6NzYM3t2PROjCpywrta9kS2EHAgMBAAGjUDBO\n" +"MB0GA1UdDgQWBBTQQfuJQR6nrVrsNF1JEflVgXgfEzAfBgNVHSMEGDAWgBTQQfuJ\n" +"QR6nrVrsNF1JEflVgXgfEzAMBgNVHRMEBTADAQH/MBIGCSqGSIb3DQEBCjAFogMC\n" +"AWoDgYEASUy2RZcgNbNQZA0/7F+V1YTLEXwD16bm+iSVnzGwtexmQVEYIZG74K/w\n" +"xbdZQdTbpNJkp1QPjPfh0zsatw6dmt5QoZ8K8No0DjR9dgf+Wvv5WJvJUIQBoAVN\n" +"Z0IL+OQFz6+LcTHxD27JJCebrATXZA0wThGTQDm7crL+a+SujBY=\n" +"-----END CERTIFICATE-----\n"; + +// kBadPSSCertPEM is a self-signed RSA-PSS certificate with bad parameters. +static const char kBadPSSCertPEM[] = +"-----BEGIN CERTIFICATE-----\n" +"MIIDdjCCAjqgAwIBAgIJANcwZLyfEv7DMD4GCSqGSIb3DQEBCjAxoA0wCwYJYIZI\n" +"AWUDBAIBoRowGAYJKoZIhvcNAQEIMAsGCWCGSAFlAwQCAaIEAgIA3jAnMSUwIwYD\n" +"VQQDDBxUZXN0IEludmFsaWQgUFNTIGNlcnRpZmljYXRlMB4XDTE1MTEwNDE2MDIz\n" +"NVoXDTE1MTIwNDE2MDIzNVowJzElMCMGA1UEAwwcVGVzdCBJbnZhbGlkIFBTUyBj\n" +"ZXJ0aWZpY2F0ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMTaM7WH\n" +"qVCAGAIA+zL1KWvvASTrhlq+1ePdO7wsrWX2KiYoTYrJYTnxhLnn0wrHqApt79nL\n" +"IBG7cfShyZqFHOY/IzlYPMVt+gPo293gw96Fds5JBsjhjkyGnOyr9OUntFqvxDbT\n" +"IIFU7o9IdxD4edaqjRv+fegVE+B79pDk4s0ujsk6dULtCg9Rst0ucGFo19mr+b7k\n" +"dbfn8pZ72ZNDJPueVdrUAWw9oll61UcYfk75XdrLk6JlL41GrYHc8KlfXf43gGQq\n" +"QfrpHkg4Ih2cI6Wt2nhFGAzrlcorzLliQIUJRIhM8h4IgDfpBpaPdVQLqS2pFbXa\n" +"5eQjqiyJwak2vJ8CAwEAAaNQME4wHQYDVR0OBBYEFCt180N4oGUt5LbzBwQ4Ia+2\n" +"4V97MB8GA1UdIwQYMBaAFCt180N4oGUt5LbzBwQ4Ia+24V97MAwGA1UdEwQFMAMB\n" +"Af8wMQYJKoZIhvcNAQEKMCSgDTALBglghkgBZQMEAgGhDTALBgkqhkiG9w0BAQii\n" +"BAICAN4DggEBAAjBtm90lGxgddjc4Xu/nbXXFHVs2zVcHv/mqOZoQkGB9r/BVgLb\n" +"xhHrFZ2pHGElbUYPfifdS9ztB73e1d4J+P29o0yBqfd4/wGAc/JA8qgn6AAEO/Xn\n" +"plhFeTRJQtLZVl75CkHXgUGUd3h+ADvKtcBuW9dSUncaUrgNKR8u/h/2sMG38RWY\n" +"DzBddC/66YTa3r7KkVUfW7yqRQfELiGKdcm+bjlTEMsvS+EhHup9CzbpoCx2Fx9p\n" +"NPtFY3yEObQhmL1JyoCRWqBE75GzFPbRaiux5UpEkns+i3trkGssZzsOuVqHNTNZ\n" +"lC9+9hPHIoc9UMmAQNo1vGIW3NWVoeGbaJ8=\n" +"-----END CERTIFICATE-----\n"; + +static const char kRSAKey[] = +"-----BEGIN RSA PRIVATE KEY-----\n" +"MIICXgIBAAKBgQDYK8imMuRi/03z0K1Zi0WnvfFHvwlYeyK9Na6XJYaUoIDAtB92\n" +"kWdGMdAQhLciHnAjkXLI6W15OoV3gA/ElRZ1xUpxTMhjP6PyY5wqT5r6y8FxbiiF\n" +"KKAnHmUcrgfVW28tQ+0rkLGMryRtrukXOgXBv7gcrmU7G1jC2a7WqmeI8QIDAQAB\n" +"AoGBAIBy09Fd4DOq/Ijp8HeKuCMKTHqTW1xGHshLQ6jwVV2vWZIn9aIgmDsvkjCe\n" +"i6ssZvnbjVcwzSoByhjN8ZCf/i15HECWDFFh6gt0P5z0MnChwzZmvatV/FXCT0j+\n" +"WmGNB/gkehKjGXLLcjTb6dRYVJSCZhVuOLLcbWIV10gggJQBAkEA8S8sGe4ezyyZ\n" +"m4e9r95g6s43kPqtj5rewTsUxt+2n4eVodD+ZUlCULWVNAFLkYRTBCASlSrm9Xhj\n" +"QpmWAHJUkQJBAOVzQdFUaewLtdOJoPCtpYoY1zd22eae8TQEmpGOR11L6kbxLQsk\n" +"aMly/DOnOaa82tqAGTdqDEZgSNmCeKKknmECQAvpnY8GUOVAubGR6c+W90iBuQLj\n" +"LtFp/9ihd2w/PoDwrHZaoUYVcT4VSfJQog/k7kjE4MYXYWL8eEKg3WTWQNECQQDk\n" +"104Wi91Umd1PzF0ijd2jXOERJU1wEKe6XLkYYNHWQAe5l4J4MWj9OdxFXAxIuuR/\n" +"tfDwbqkta4xcux67//khAkEAvvRXLHTaa6VFzTaiiO8SaFsHV3lQyXOtMrBpB5jd\n" +"moZWgjHvB2W9Ckn7sDqsPB+U2tyX0joDdQEyuiMECDY8oQ==\n" +"-----END RSA PRIVATE KEY-----\n"; + + +// CertFromPEM parses the given, NUL-terminated pem block and returns an +// |X509*|. +static ScopedX509 CertFromPEM(const char *pem) { + ScopedBIO bio(BIO_new_mem_buf(pem, strlen(pem))); + return ScopedX509(PEM_read_bio_X509(bio.get(), nullptr, nullptr, nullptr)); +} + +// PrivateKeyFromPEM parses the given, NUL-terminated pem block and returns an +// |EVP_PKEY*|. +static ScopedEVP_PKEY PrivateKeyFromPEM(const char *pem) { + ScopedBIO bio(BIO_new_mem_buf(const_cast(pem), strlen(pem))); + return ScopedEVP_PKEY( + PEM_read_bio_PrivateKey(bio.get(), nullptr, nullptr, nullptr)); +} + +// CertsToStack converts a vector of |X509*| to an OpenSSL STACK_OF(X509*), +// bumping the reference counts for each certificate in question. +static STACK_OF(X509)* CertsToStack(const std::vector &certs) { + ScopedX509Stack stack(sk_X509_new_null()); + if (!stack) { + return nullptr; + } + for (auto cert : certs) { + if (!sk_X509_push(stack.get(), cert)) { + return nullptr; + } + X509_up_ref(cert); + } + + return stack.release(); +} + +static bool Verify(X509 *leaf, const std::vector &roots, + const std::vector &intermediates, + unsigned long flags = 0) { + ScopedX509Stack roots_stack(CertsToStack(roots)); + ScopedX509Stack intermediates_stack(CertsToStack(intermediates)); + if (!roots_stack || + !intermediates_stack) { + return false; + } + + ScopedX509_STORE_CTX ctx(X509_STORE_CTX_new()); + if (!ctx) { + return false; + } + if (!X509_STORE_CTX_init(ctx.get(), nullptr /* no X509_STORE */, leaf, + intermediates_stack.get())) { + return false; + } + + X509_STORE_CTX_trusted_stack(ctx.get(), roots_stack.get()); + + X509_VERIFY_PARAM *param = X509_VERIFY_PARAM_new(); + if (param == nullptr) { + return false; + } + X509_VERIFY_PARAM_set_time(param, 1452807555 /* Jan 14th, 2016 */); + X509_VERIFY_PARAM_set_depth(param, 16); + if (flags) { + X509_VERIFY_PARAM_set_flags(param, flags); + } + X509_STORE_CTX_set0_param(ctx.get(), param); + + ERR_clear_error(); + return X509_verify_cert(ctx.get()) == 1; +} + +static bool TestVerify() { + ScopedX509 cross_signing_root(CertFromPEM(kCrossSigningRootPEM)); + ScopedX509 root(CertFromPEM(kRootCAPEM)); + ScopedX509 root_cross_signed(CertFromPEM(kRootCrossSignedPEM)); + ScopedX509 intermediate(CertFromPEM(kIntermediatePEM)); + ScopedX509 intermediate_self_signed(CertFromPEM(kIntermediateSelfSignedPEM)); + ScopedX509 leaf(CertFromPEM(kLeafPEM)); + ScopedX509 leaf_no_key_usage(CertFromPEM(kLeafNoKeyUsagePEM)); + ScopedX509 forgery(CertFromPEM(kForgeryPEM)); + + if (!cross_signing_root || + !root || + !root_cross_signed || + !intermediate || + !intermediate_self_signed || + !leaf || + !leaf_no_key_usage || + !forgery) { + fprintf(stderr, "Failed to parse certificates\n"); + return false; + } + + std::vector empty; + if (Verify(leaf.get(), empty, empty)) { + fprintf(stderr, "Leaf verified with no roots!\n"); + return false; + } + + if (Verify(leaf.get(), empty, {intermediate.get()})) { + fprintf(stderr, "Leaf verified with no roots!\n"); + return false; + } + + if (!Verify(leaf.get(), {root.get()}, {intermediate.get()})) { + ERR_print_errors_fp(stderr); + fprintf(stderr, "Basic chain didn't verify.\n"); + return false; + } + + if (!Verify(leaf.get(), {cross_signing_root.get()}, + {intermediate.get(), root_cross_signed.get()})) { + ERR_print_errors_fp(stderr); + fprintf(stderr, "Cross-signed chain didn't verify.\n"); + return false; + } + + if (!Verify(leaf.get(), {cross_signing_root.get(), root.get()}, + {intermediate.get(), root_cross_signed.get()})) { + ERR_print_errors_fp(stderr); + fprintf(stderr, "Cross-signed chain with root didn't verify.\n"); + return false; + } + + /* This is the “altchains†test – we remove the cross-signing CA but include + * the cross-sign in the intermediates. */ + if (!Verify(leaf.get(), {root.get()}, + {intermediate.get(), root_cross_signed.get()})) { + ERR_print_errors_fp(stderr); + fprintf(stderr, "Chain with cross-sign didn't backtrack to find root.\n"); + return false; + } + + if (Verify(leaf.get(), {root.get()}, + {intermediate.get(), root_cross_signed.get()}, + X509_V_FLAG_NO_ALT_CHAINS)) { + fprintf(stderr, "Altchains test still passed when disabled.\n"); + return false; + } + + if (Verify(forgery.get(), {intermediate_self_signed.get()}, + {leaf_no_key_usage.get()})) { + fprintf(stderr, "Basic constraints weren't checked.\n"); + return false; + } + + /* Test that one cannot skip Basic Constraints checking with a contorted set + * of roots and intermediates. This is a regression test for CVE-2015-1793. */ + if (Verify(forgery.get(), + {intermediate_self_signed.get(), root_cross_signed.get()}, + {leaf_no_key_usage.get(), intermediate.get()})) { + fprintf(stderr, "Basic constraints weren't checked.\n"); + return false; + } + + return true; +} + +static bool TestPSS() { + ScopedX509 cert(CertFromPEM(kExamplePSSCert)); + if (!cert) { + return false; + } + + ScopedEVP_PKEY pkey(X509_get_pubkey(cert.get())); + if (!pkey) { + return false; + } + + if (!X509_verify(cert.get(), pkey.get())) { + fprintf(stderr, "Could not verify certificate.\n"); + return false; + } + return true; +} + +static bool TestBadPSSParameters() { + ScopedX509 cert(CertFromPEM(kBadPSSCertPEM)); + if (!cert) { + return false; + } + + ScopedEVP_PKEY pkey(X509_get_pubkey(cert.get())); + if (!pkey) { + return false; + } + + if (X509_verify(cert.get(), pkey.get())) { + fprintf(stderr, "Unexpectedly verified bad certificate.\n"); + return false; + } + ERR_clear_error(); + return true; +} + +static bool SignatureRoundTrips(EVP_MD_CTX *md_ctx, EVP_PKEY *pkey) { + // Make a certificate like signed with |md_ctx|'s settings.' + ScopedX509 cert(CertFromPEM(kLeafPEM)); + if (!cert || !X509_sign_ctx(cert.get(), md_ctx)) { + return false; + } + + // Ensure that |pkey| may still be used to verify the resulting signature. All + // settings in |md_ctx| must have been serialized appropriately. + return !!X509_verify(cert.get(), pkey); +} + +static bool TestSignCtx() { + ScopedEVP_PKEY pkey(PrivateKeyFromPEM(kRSAKey)); + if (!pkey) { + return false; + } + + // Test PKCS#1 v1.5. + ScopedEVP_MD_CTX md_ctx; + if (!EVP_DigestSignInit(md_ctx.get(), NULL, EVP_sha256(), NULL, pkey.get()) || + !SignatureRoundTrips(md_ctx.get(), pkey.get())) { + fprintf(stderr, "RSA PKCS#1 with SHA-256 failed\n"); + return false; + } + + // Test RSA-PSS with custom parameters. + md_ctx.Reset(); + EVP_PKEY_CTX *pkey_ctx; + if (!EVP_DigestSignInit(md_ctx.get(), &pkey_ctx, EVP_sha256(), NULL, + pkey.get()) || + !EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING) || + !EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, EVP_sha512()) || + !SignatureRoundTrips(md_ctx.get(), pkey.get())) { + fprintf(stderr, "RSA-PSS failed\n"); + return false; + } + + return true; +} + +int main(int argc, char **argv) { + CRYPTO_library_init(); + + if (!TestVerify() || + !TestPSS() || + !TestBadPSSParameters() || + !TestSignCtx()) { + return 1; + } + + printf("PASS\n"); + return 0; +} diff --git a/external/boringssl/crypto/x509/x509_trs.c b/external/boringssl/crypto/x509/x509_trs.c new file mode 100644 index 0000000000..c7dfcad60e --- /dev/null +++ b/external/boringssl/crypto/x509/x509_trs.c @@ -0,0 +1,326 @@ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project + * 1999. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include +#include +#include +#include +#include + +static int tr_cmp(const X509_TRUST **a, const X509_TRUST **b); +static void trtable_free(X509_TRUST *p); + +static int trust_1oidany(X509_TRUST *trust, X509 *x, int flags); +static int trust_1oid(X509_TRUST *trust, X509 *x, int flags); +static int trust_compat(X509_TRUST *trust, X509 *x, int flags); + +static int obj_trust(int id, X509 *x, int flags); +static int (*default_trust) (int id, X509 *x, int flags) = obj_trust; + +/* + * WARNING: the following table should be kept in order of trust and without + * any gaps so we can just subtract the minimum trust value to get an index + * into the table + */ + +static X509_TRUST trstandard[] = { + {X509_TRUST_COMPAT, 0, trust_compat, (char *)"compatible", 0, NULL}, + {X509_TRUST_SSL_CLIENT, 0, trust_1oidany, (char *)"SSL Client", + NID_client_auth, NULL}, + {X509_TRUST_SSL_SERVER, 0, trust_1oidany, (char *)"SSL Server", + NID_server_auth, NULL}, + {X509_TRUST_EMAIL, 0, trust_1oidany, (char *)"S/MIME email", + NID_email_protect, NULL}, + {X509_TRUST_OBJECT_SIGN, 0, trust_1oidany, (char *)"Object Signer", + NID_code_sign, NULL}, + {X509_TRUST_OCSP_SIGN, 0, trust_1oid, (char *)"OCSP responder", + NID_OCSP_sign, NULL}, + {X509_TRUST_OCSP_REQUEST, 0, trust_1oid, (char *)"OCSP request", + NID_ad_OCSP, NULL}, + {X509_TRUST_TSA, 0, trust_1oidany, (char *)"TSA server", NID_time_stamp, + NULL} +}; + +#define X509_TRUST_COUNT (sizeof(trstandard)/sizeof(X509_TRUST)) + +static STACK_OF(X509_TRUST) *trtable = NULL; + +static int tr_cmp(const X509_TRUST **a, const X509_TRUST **b) +{ + return (*a)->trust - (*b)->trust; +} + +int (*X509_TRUST_set_default(int (*trust) (int, X509 *, int))) (int, X509 *, + int) { + int (*oldtrust) (int, X509 *, int); + oldtrust = default_trust; + default_trust = trust; + return oldtrust; +} + +int X509_check_trust(X509 *x, int id, int flags) +{ + X509_TRUST *pt; + int idx; + if (id == -1) + return 1; + /* We get this as a default value */ + if (id == 0) { + int rv; + rv = obj_trust(NID_anyExtendedKeyUsage, x, 0); + if (rv != X509_TRUST_UNTRUSTED) + return rv; + return trust_compat(NULL, x, 0); + } + idx = X509_TRUST_get_by_id(id); + if (idx == -1) + return default_trust(id, x, flags); + pt = X509_TRUST_get0(idx); + return pt->check_trust(pt, x, flags); +} + +int X509_TRUST_get_count(void) +{ + if (!trtable) + return X509_TRUST_COUNT; + return sk_X509_TRUST_num(trtable) + X509_TRUST_COUNT; +} + +X509_TRUST *X509_TRUST_get0(int idx) +{ + if (idx < 0) + return NULL; + if (idx < (int)X509_TRUST_COUNT) + return trstandard + idx; + return sk_X509_TRUST_value(trtable, idx - X509_TRUST_COUNT); +} + +int X509_TRUST_get_by_id(int id) +{ + X509_TRUST tmp; + size_t idx; + + if ((id >= X509_TRUST_MIN) && (id <= X509_TRUST_MAX)) + return id - X509_TRUST_MIN; + tmp.trust = id; + if (!trtable) + return -1; + if (!sk_X509_TRUST_find(trtable, &idx, &tmp)) { + return -1; + } + return idx + X509_TRUST_COUNT; +} + +int X509_TRUST_set(int *t, int trust) +{ + if (X509_TRUST_get_by_id(trust) == -1) { + OPENSSL_PUT_ERROR(X509, X509_R_INVALID_TRUST); + return 0; + } + *t = trust; + return 1; +} + +int X509_TRUST_add(int id, int flags, int (*ck) (X509_TRUST *, X509 *, int), + char *name, int arg1, void *arg2) +{ + int idx; + X509_TRUST *trtmp; + char *name_dup; + + /* + * This is set according to what we change: application can't set it + */ + flags &= ~X509_TRUST_DYNAMIC; + /* This will always be set for application modified trust entries */ + flags |= X509_TRUST_DYNAMIC_NAME; + /* Get existing entry if any */ + idx = X509_TRUST_get_by_id(id); + /* Need a new entry */ + if (idx == -1) { + if (!(trtmp = OPENSSL_malloc(sizeof(X509_TRUST)))) { + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + return 0; + } + trtmp->flags = X509_TRUST_DYNAMIC; + } else + trtmp = X509_TRUST_get0(idx); + + /* Duplicate the supplied name. */ + name_dup = BUF_strdup(name); + if (name_dup == NULL) { + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + if (idx == -1) + OPENSSL_free(trtmp); + return 0; + } + + /* OPENSSL_free existing name if dynamic */ + if (trtmp->flags & X509_TRUST_DYNAMIC_NAME) + OPENSSL_free(trtmp->name); + trtmp->name = name_dup; + /* Keep the dynamic flag of existing entry */ + trtmp->flags &= X509_TRUST_DYNAMIC; + /* Set all other flags */ + trtmp->flags |= flags; + + trtmp->trust = id; + trtmp->check_trust = ck; + trtmp->arg1 = arg1; + trtmp->arg2 = arg2; + + /* If its a new entry manage the dynamic table */ + if (idx == -1) { + if (!trtable && !(trtable = sk_X509_TRUST_new(tr_cmp))) { + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + trtable_free(trtmp); + return 0; + } + if (!sk_X509_TRUST_push(trtable, trtmp)) { + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + trtable_free(trtmp); + return 0; + } + } + return 1; +} + +static void trtable_free(X509_TRUST *p) +{ + if (!p) + return; + if (p->flags & X509_TRUST_DYNAMIC) { + if (p->flags & X509_TRUST_DYNAMIC_NAME) + OPENSSL_free(p->name); + OPENSSL_free(p); + } +} + +void X509_TRUST_cleanup(void) +{ + unsigned int i; + for (i = 0; i < X509_TRUST_COUNT; i++) + trtable_free(trstandard + i); + sk_X509_TRUST_pop_free(trtable, trtable_free); + trtable = NULL; +} + +int X509_TRUST_get_flags(X509_TRUST *xp) +{ + return xp->flags; +} + +char *X509_TRUST_get0_name(X509_TRUST *xp) +{ + return xp->name; +} + +int X509_TRUST_get_trust(X509_TRUST *xp) +{ + return xp->trust; +} + +static int trust_1oidany(X509_TRUST *trust, X509 *x, int flags) +{ + if (x->aux && (x->aux->trust || x->aux->reject)) + return obj_trust(trust->arg1, x, flags); + /* + * we don't have any trust settings: for compatibility we return trusted + * if it is self signed + */ + return trust_compat(trust, x, flags); +} + +static int trust_1oid(X509_TRUST *trust, X509 *x, int flags) +{ + if (x->aux) + return obj_trust(trust->arg1, x, flags); + return X509_TRUST_UNTRUSTED; +} + +static int trust_compat(X509_TRUST *trust, X509 *x, int flags) +{ + X509_check_purpose(x, -1, 0); + if (x->ex_flags & EXFLAG_SS) + return X509_TRUST_TRUSTED; + else + return X509_TRUST_UNTRUSTED; +} + +static int obj_trust(int id, X509 *x, int flags) +{ + ASN1_OBJECT *obj; + size_t i; + X509_CERT_AUX *ax; + ax = x->aux; + if (!ax) + return X509_TRUST_UNTRUSTED; + if (ax->reject) { + for (i = 0; i < sk_ASN1_OBJECT_num(ax->reject); i++) { + obj = sk_ASN1_OBJECT_value(ax->reject, i); + if (OBJ_obj2nid(obj) == id) + return X509_TRUST_REJECTED; + } + } + if (ax->trust) { + for (i = 0; i < sk_ASN1_OBJECT_num(ax->trust); i++) { + obj = sk_ASN1_OBJECT_value(ax->trust, i); + if (OBJ_obj2nid(obj) == id) + return X509_TRUST_TRUSTED; + } + } + return X509_TRUST_UNTRUSTED; +} diff --git a/external/boringssl/crypto/x509/x509_txt.c b/external/boringssl/crypto/x509/x509_txt.c new file mode 100644 index 0000000000..17e6cdb9c2 --- /dev/null +++ b/external/boringssl/crypto/x509/x509_txt.c @@ -0,0 +1,211 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include +#include +#include +#include +#include +#include +#include +#include + +const char *X509_verify_cert_error_string(long n) +{ + static char buf[100]; + + switch ((int)n) { + case X509_V_OK: + return ("ok"); + case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: + return ("unable to get issuer certificate"); + case X509_V_ERR_UNABLE_TO_GET_CRL: + return ("unable to get certificate CRL"); + case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE: + return ("unable to decrypt certificate's signature"); + case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE: + return ("unable to decrypt CRL's signature"); + case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: + return ("unable to decode issuer public key"); + case X509_V_ERR_CERT_SIGNATURE_FAILURE: + return ("certificate signature failure"); + case X509_V_ERR_CRL_SIGNATURE_FAILURE: + return ("CRL signature failure"); + case X509_V_ERR_CERT_NOT_YET_VALID: + return ("certificate is not yet valid"); + case X509_V_ERR_CRL_NOT_YET_VALID: + return ("CRL is not yet valid"); + case X509_V_ERR_CERT_HAS_EXPIRED: + return ("certificate has expired"); + case X509_V_ERR_CRL_HAS_EXPIRED: + return ("CRL has expired"); + case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: + return ("format error in certificate's notBefore field"); + case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: + return ("format error in certificate's notAfter field"); + case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD: + return ("format error in CRL's lastUpdate field"); + case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD: + return ("format error in CRL's nextUpdate field"); + case X509_V_ERR_OUT_OF_MEM: + return ("out of memory"); + case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: + return ("self signed certificate"); + case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: + return ("self signed certificate in certificate chain"); + case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: + return ("unable to get local issuer certificate"); + case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: + return ("unable to verify the first certificate"); + case X509_V_ERR_CERT_CHAIN_TOO_LONG: + return ("certificate chain too long"); + case X509_V_ERR_CERT_REVOKED: + return ("certificate revoked"); + case X509_V_ERR_INVALID_CA: + return ("invalid CA certificate"); + case X509_V_ERR_INVALID_NON_CA: + return ("invalid non-CA certificate (has CA markings)"); + case X509_V_ERR_PATH_LENGTH_EXCEEDED: + return ("path length constraint exceeded"); + case X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED: + return ("proxy path length constraint exceeded"); + case X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED: + return + ("proxy certificates not allowed, please set the appropriate flag"); + case X509_V_ERR_INVALID_PURPOSE: + return ("unsupported certificate purpose"); + case X509_V_ERR_CERT_UNTRUSTED: + return ("certificate not trusted"); + case X509_V_ERR_CERT_REJECTED: + return ("certificate rejected"); + case X509_V_ERR_APPLICATION_VERIFICATION: + return ("application verification failure"); + case X509_V_ERR_SUBJECT_ISSUER_MISMATCH: + return ("subject issuer mismatch"); + case X509_V_ERR_AKID_SKID_MISMATCH: + return ("authority and subject key identifier mismatch"); + case X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH: + return ("authority and issuer serial number mismatch"); + case X509_V_ERR_KEYUSAGE_NO_CERTSIGN: + return ("key usage does not include certificate signing"); + case X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER: + return ("unable to get CRL issuer certificate"); + case X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION: + return ("unhandled critical extension"); + case X509_V_ERR_KEYUSAGE_NO_CRL_SIGN: + return ("key usage does not include CRL signing"); + case X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE: + return ("key usage does not include digital signature"); + case X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION: + return ("unhandled critical CRL extension"); + case X509_V_ERR_INVALID_EXTENSION: + return ("invalid or inconsistent certificate extension"); + case X509_V_ERR_INVALID_POLICY_EXTENSION: + return ("invalid or inconsistent certificate policy extension"); + case X509_V_ERR_NO_EXPLICIT_POLICY: + return ("no explicit policy"); + case X509_V_ERR_DIFFERENT_CRL_SCOPE: + return ("Different CRL scope"); + case X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE: + return ("Unsupported extension feature"); + case X509_V_ERR_UNNESTED_RESOURCE: + return ("RFC 3779 resource not subset of parent's resources"); + + case X509_V_ERR_PERMITTED_VIOLATION: + return ("permitted subtree violation"); + case X509_V_ERR_EXCLUDED_VIOLATION: + return ("excluded subtree violation"); + case X509_V_ERR_SUBTREE_MINMAX: + return ("name constraints minimum and maximum not supported"); + case X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE: + return ("unsupported name constraint type"); + case X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX: + return ("unsupported or invalid name constraint syntax"); + case X509_V_ERR_UNSUPPORTED_NAME_SYNTAX: + return ("unsupported or invalid name syntax"); + case X509_V_ERR_CRL_PATH_VALIDATION_ERROR: + return ("CRL path validation error"); + + case X509_V_ERR_SUITE_B_INVALID_VERSION: + return ("Suite B: certificate version invalid"); + case X509_V_ERR_SUITE_B_INVALID_ALGORITHM: + return ("Suite B: invalid public key algorithm"); + case X509_V_ERR_SUITE_B_INVALID_CURVE: + return ("Suite B: invalid ECC curve"); + case X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM: + return ("Suite B: invalid signature algorithm"); + case X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED: + return ("Suite B: curve not allowed for this LOS"); + case X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256: + return ("Suite B: cannot sign P-384 with P-256"); + + case X509_V_ERR_HOSTNAME_MISMATCH: + return ("Hostname mismatch"); + case X509_V_ERR_EMAIL_MISMATCH: + return ("Email address mismatch"); + case X509_V_ERR_IP_ADDRESS_MISMATCH: + return ("IP address mismatch"); + + case X509_V_ERR_INVALID_CALL: + return ("Invalid certificate verification context"); + case X509_V_ERR_STORE_LOOKUP: + return ("Issuer certificate lookup error"); + + default: + BIO_snprintf(buf, sizeof buf, "error number %ld", n); + return (buf); + } +} diff --git a/external/boringssl/crypto/x509/x509_v3.c b/external/boringssl/crypto/x509/x509_v3.c new file mode 100644 index 0000000000..ecbc0ddc0b --- /dev/null +++ b/external/boringssl/crypto/x509/x509_v3.c @@ -0,0 +1,278 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include +#include +#include +#include +#include +#include +#include + +int X509v3_get_ext_count(const STACK_OF(X509_EXTENSION) *x) +{ + if (x == NULL) + return (0); + return (sk_X509_EXTENSION_num(x)); +} + +int X509v3_get_ext_by_NID(const STACK_OF(X509_EXTENSION) *x, int nid, + int lastpos) +{ + const ASN1_OBJECT *obj; + + obj = OBJ_nid2obj(nid); + if (obj == NULL) + return (-2); + return (X509v3_get_ext_by_OBJ(x, obj, lastpos)); +} + +int X509v3_get_ext_by_OBJ(const STACK_OF(X509_EXTENSION) *sk, + const ASN1_OBJECT *obj, int lastpos) +{ + int n; + X509_EXTENSION *ex; + + if (sk == NULL) + return (-1); + lastpos++; + if (lastpos < 0) + lastpos = 0; + n = sk_X509_EXTENSION_num(sk); + for (; lastpos < n; lastpos++) { + ex = sk_X509_EXTENSION_value(sk, lastpos); + if (OBJ_cmp(ex->object, obj) == 0) + return (lastpos); + } + return (-1); +} + +int X509v3_get_ext_by_critical(const STACK_OF(X509_EXTENSION) *sk, int crit, + int lastpos) +{ + int n; + X509_EXTENSION *ex; + + if (sk == NULL) + return (-1); + lastpos++; + if (lastpos < 0) + lastpos = 0; + n = sk_X509_EXTENSION_num(sk); + for (; lastpos < n; lastpos++) { + ex = sk_X509_EXTENSION_value(sk, lastpos); + if (((ex->critical > 0) && crit) || ((ex->critical <= 0) && !crit)) + return (lastpos); + } + return (-1); +} + +X509_EXTENSION *X509v3_get_ext(const STACK_OF(X509_EXTENSION) *x, int loc) +{ + if (x == NULL || loc < 0 || sk_X509_EXTENSION_num(x) <= (size_t)loc) + return NULL; + else + return sk_X509_EXTENSION_value(x, loc); +} + +X509_EXTENSION *X509v3_delete_ext(STACK_OF(X509_EXTENSION) *x, int loc) +{ + X509_EXTENSION *ret; + + if (x == NULL || loc < 0 || sk_X509_EXTENSION_num(x) <= (size_t)loc) + return (NULL); + ret = sk_X509_EXTENSION_delete(x, loc); + return (ret); +} + +STACK_OF(X509_EXTENSION) *X509v3_add_ext(STACK_OF(X509_EXTENSION) **x, + X509_EXTENSION *ex, int loc) +{ + X509_EXTENSION *new_ex = NULL; + int n; + STACK_OF(X509_EXTENSION) *sk = NULL; + + if (x == NULL) { + OPENSSL_PUT_ERROR(X509, ERR_R_PASSED_NULL_PARAMETER); + goto err2; + } + + if (*x == NULL) { + if ((sk = sk_X509_EXTENSION_new_null()) == NULL) + goto err; + } else + sk = *x; + + n = sk_X509_EXTENSION_num(sk); + if (loc > n) + loc = n; + else if (loc < 0) + loc = n; + + if ((new_ex = X509_EXTENSION_dup(ex)) == NULL) + goto err2; + if (!sk_X509_EXTENSION_insert(sk, new_ex, loc)) + goto err; + if (*x == NULL) + *x = sk; + return (sk); + err: + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + err2: + if (new_ex != NULL) + X509_EXTENSION_free(new_ex); + if (sk != NULL) + sk_X509_EXTENSION_free(sk); + return (NULL); +} + +X509_EXTENSION *X509_EXTENSION_create_by_NID(X509_EXTENSION **ex, int nid, + int crit, + ASN1_OCTET_STRING *data) +{ + const ASN1_OBJECT *obj; + X509_EXTENSION *ret; + + obj = OBJ_nid2obj(nid); + if (obj == NULL) { + OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_NID); + return (NULL); + } + ret = X509_EXTENSION_create_by_OBJ(ex, obj, crit, data); + return (ret); +} + +X509_EXTENSION *X509_EXTENSION_create_by_OBJ(X509_EXTENSION **ex, + const ASN1_OBJECT *obj, int crit, + ASN1_OCTET_STRING *data) +{ + X509_EXTENSION *ret; + + if ((ex == NULL) || (*ex == NULL)) { + if ((ret = X509_EXTENSION_new()) == NULL) { + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + return (NULL); + } + } else + ret = *ex; + + if (!X509_EXTENSION_set_object(ret, obj)) + goto err; + if (!X509_EXTENSION_set_critical(ret, crit)) + goto err; + if (!X509_EXTENSION_set_data(ret, data)) + goto err; + + if ((ex != NULL) && (*ex == NULL)) + *ex = ret; + return (ret); + err: + if ((ex == NULL) || (ret != *ex)) + X509_EXTENSION_free(ret); + return (NULL); +} + +int X509_EXTENSION_set_object(X509_EXTENSION *ex, const ASN1_OBJECT *obj) +{ + if ((ex == NULL) || (obj == NULL)) + return (0); + ASN1_OBJECT_free(ex->object); + ex->object = OBJ_dup(obj); + return ex->object != NULL; +} + +int X509_EXTENSION_set_critical(X509_EXTENSION *ex, int crit) +{ + if (ex == NULL) + return (0); + ex->critical = (crit) ? 0xFF : -1; + return (1); +} + +int X509_EXTENSION_set_data(X509_EXTENSION *ex, ASN1_OCTET_STRING *data) +{ + int i; + + if (ex == NULL) + return (0); + i = M_ASN1_OCTET_STRING_set(ex->value, data->data, data->length); + if (!i) + return (0); + return (1); +} + +ASN1_OBJECT *X509_EXTENSION_get_object(X509_EXTENSION *ex) +{ + if (ex == NULL) + return (NULL); + return (ex->object); +} + +ASN1_OCTET_STRING *X509_EXTENSION_get_data(X509_EXTENSION *ex) +{ + if (ex == NULL) + return (NULL); + return (ex->value); +} + +int X509_EXTENSION_get_critical(X509_EXTENSION *ex) +{ + if (ex == NULL) + return (0); + if (ex->critical > 0) + return 1; + return 0; +} diff --git a/external/boringssl/crypto/x509/x509_vfy.c b/external/boringssl/crypto/x509/x509_vfy.c new file mode 100644 index 0000000000..520408feff --- /dev/null +++ b/external/boringssl/crypto/x509/x509_vfy.c @@ -0,0 +1,2434 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "vpm_int.h" +#include "../internal.h" + +static CRYPTO_EX_DATA_CLASS g_ex_data_class = + CRYPTO_EX_DATA_CLASS_INIT_WITH_APP_DATA; + +/* CRL score values */ + +/* No unhandled critical extensions */ + +#define CRL_SCORE_NOCRITICAL 0x100 + +/* certificate is within CRL scope */ + +#define CRL_SCORE_SCOPE 0x080 + +/* CRL times valid */ + +#define CRL_SCORE_TIME 0x040 + +/* Issuer name matches certificate */ + +#define CRL_SCORE_ISSUER_NAME 0x020 + +/* If this score or above CRL is probably valid */ + +#define CRL_SCORE_VALID (CRL_SCORE_NOCRITICAL|CRL_SCORE_TIME|CRL_SCORE_SCOPE) + +/* CRL issuer is certificate issuer */ + +#define CRL_SCORE_ISSUER_CERT 0x018 + +/* CRL issuer is on certificate path */ + +#define CRL_SCORE_SAME_PATH 0x008 + +/* CRL issuer matches CRL AKID */ + +#define CRL_SCORE_AKID 0x004 + +/* Have a delta CRL with valid times */ + +#define CRL_SCORE_TIME_DELTA 0x002 + +static int null_callback(int ok, X509_STORE_CTX *e); +static int check_issued(X509_STORE_CTX *ctx, X509 *x, X509 *issuer); +static X509 *find_issuer(X509_STORE_CTX *ctx, STACK_OF(X509) *sk, X509 *x); +static int check_chain_extensions(X509_STORE_CTX *ctx); +static int check_name_constraints(X509_STORE_CTX *ctx); +static int check_id(X509_STORE_CTX *ctx); +static int check_trust(X509_STORE_CTX *ctx); +static int check_revocation(X509_STORE_CTX *ctx); +static int check_cert(X509_STORE_CTX *ctx); +static int check_policy(X509_STORE_CTX *ctx); + +static int get_crl_score(X509_STORE_CTX *ctx, X509 **pissuer, + unsigned int *preasons, X509_CRL *crl, X509 *x); +static int get_crl_delta(X509_STORE_CTX *ctx, + X509_CRL **pcrl, X509_CRL **pdcrl, X509 *x); +static void get_delta_sk(X509_STORE_CTX *ctx, X509_CRL **dcrl, + int *pcrl_score, X509_CRL *base, + STACK_OF(X509_CRL) *crls); +static void crl_akid_check(X509_STORE_CTX *ctx, X509_CRL *crl, X509 **pissuer, + int *pcrl_score); +static int crl_crldp_check(X509 *x, X509_CRL *crl, int crl_score, + unsigned int *preasons); +static int check_crl_path(X509_STORE_CTX *ctx, X509 *x); +static int check_crl_chain(X509_STORE_CTX *ctx, + STACK_OF(X509) *cert_path, + STACK_OF(X509) *crl_path); + +static int internal_verify(X509_STORE_CTX *ctx); + +static int null_callback(int ok, X509_STORE_CTX *e) +{ + return ok; +} + +#if 0 +static int x509_subject_cmp(X509 **a, X509 **b) +{ + return X509_subject_name_cmp(*a, *b); +} +#endif +/* Return 1 is a certificate is self signed */ +static int cert_self_signed(X509 *x) +{ + X509_check_purpose(x, -1, 0); + if (x->ex_flags & EXFLAG_SS) + return 1; + else + return 0; +} + +/* Given a certificate try and find an exact match in the store */ + +static X509 *lookup_cert_match(X509_STORE_CTX *ctx, X509 *x) +{ + STACK_OF(X509) *certs; + X509 *xtmp = NULL; + size_t i; + /* Lookup all certs with matching subject name */ + certs = ctx->lookup_certs(ctx, X509_get_subject_name(x)); + if (certs == NULL) + return NULL; + /* Look for exact match */ + for (i = 0; i < sk_X509_num(certs); i++) { + xtmp = sk_X509_value(certs, i); + if (!X509_cmp(xtmp, x)) + break; + } + if (i < sk_X509_num(certs)) + X509_up_ref(xtmp); + else + xtmp = NULL; + sk_X509_pop_free(certs, X509_free); + return xtmp; +} + +int X509_verify_cert(X509_STORE_CTX *ctx) +{ + X509 *x, *xtmp, *xtmp2, *chain_ss = NULL; + int bad_chain = 0; + X509_VERIFY_PARAM *param = ctx->param; + int depth, i, ok = 0; + int num, j, retry, trust; + int (*cb) (int xok, X509_STORE_CTX *xctx); + STACK_OF(X509) *sktmp = NULL; + if (ctx->cert == NULL) { + OPENSSL_PUT_ERROR(X509, X509_R_NO_CERT_SET_FOR_US_TO_VERIFY); + ctx->error = X509_V_ERR_INVALID_CALL; + return -1; + } + if (ctx->chain != NULL) { + /* + * This X509_STORE_CTX has already been used to verify a cert. We + * cannot do another one. + */ + OPENSSL_PUT_ERROR(X509, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + ctx->error = X509_V_ERR_INVALID_CALL; + return -1; + } + + cb = ctx->verify_cb; + + /* + * first we make sure the chain we are going to build is present and that + * the first entry is in place + */ + ctx->chain = sk_X509_new_null(); + if (ctx->chain == NULL || !sk_X509_push(ctx->chain, ctx->cert)) { + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + ctx->error = X509_V_ERR_OUT_OF_MEM; + goto end; + } + X509_up_ref(ctx->cert); + ctx->last_untrusted = 1; + + /* We use a temporary STACK so we can chop and hack at it */ + if (ctx->untrusted != NULL + && (sktmp = sk_X509_dup(ctx->untrusted)) == NULL) { + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + ctx->error = X509_V_ERR_OUT_OF_MEM; + goto end; + } + + num = sk_X509_num(ctx->chain); + x = sk_X509_value(ctx->chain, num - 1); + depth = param->depth; + + for (;;) { + /* If we have enough, we break */ + if (depth < num) + break; /* FIXME: If this happens, we should take + * note of it and, if appropriate, use the + * X509_V_ERR_CERT_CHAIN_TOO_LONG error code + * later. */ + + /* If we are self signed, we break */ + if (cert_self_signed(x)) + break; + /* + * If asked see if we can find issuer in trusted store first + */ + if (ctx->param->flags & X509_V_FLAG_TRUSTED_FIRST) { + ok = ctx->get_issuer(&xtmp, ctx, x); + if (ok < 0) { + ctx->error = X509_V_ERR_STORE_LOOKUP; + goto end; + } + /* + * If successful for now free up cert so it will be picked up + * again later. + */ + if (ok > 0) { + X509_free(xtmp); + break; + } + } + + /* If we were passed a cert chain, use it first */ + if (ctx->untrusted != NULL) { + xtmp = find_issuer(ctx, sktmp, x); + if (xtmp != NULL) { + if (!sk_X509_push(ctx->chain, xtmp)) { + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + ctx->error = X509_V_ERR_OUT_OF_MEM; + ok = 0; + goto end; + } + X509_up_ref(xtmp); + (void)sk_X509_delete_ptr(sktmp, xtmp); + ctx->last_untrusted++; + x = xtmp; + num++; + /* + * reparse the full chain for the next one + */ + continue; + } + } + break; + } + + /* Remember how many untrusted certs we have */ + j = num; + /* + * at this point, chain should contain a list of untrusted certificates. + * We now need to add at least one trusted one, if possible, otherwise we + * complain. + */ + + do { + /* + * Examine last certificate in chain and see if it is self signed. + */ + i = sk_X509_num(ctx->chain); + x = sk_X509_value(ctx->chain, i - 1); + if (cert_self_signed(x)) { + /* we have a self signed certificate */ + if (sk_X509_num(ctx->chain) == 1) { + /* + * We have a single self signed certificate: see if we can + * find it in the store. We must have an exact match to avoid + * possible impersonation. + */ + ok = ctx->get_issuer(&xtmp, ctx, x); + if ((ok <= 0) || X509_cmp(x, xtmp)) { + ctx->error = X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT; + ctx->current_cert = x; + ctx->error_depth = i - 1; + if (ok == 1) + X509_free(xtmp); + bad_chain = 1; + ok = cb(0, ctx); + if (!ok) + goto end; + } else { + /* + * We have a match: replace certificate with store + * version so we get any trust settings. + */ + X509_free(x); + x = xtmp; + (void)sk_X509_set(ctx->chain, i - 1, x); + ctx->last_untrusted = 0; + } + } else { + /* + * extract and save self signed certificate for later use + */ + chain_ss = sk_X509_pop(ctx->chain); + ctx->last_untrusted--; + num--; + j--; + x = sk_X509_value(ctx->chain, num - 1); + } + } + /* We now lookup certs from the certificate store */ + for (;;) { + /* If we have enough, we break */ + if (depth < num) + break; + /* If we are self signed, we break */ + if (cert_self_signed(x)) + break; + ok = ctx->get_issuer(&xtmp, ctx, x); + + if (ok < 0) { + ctx->error = X509_V_ERR_STORE_LOOKUP; + goto end; + } + if (ok == 0) + break; + x = xtmp; + if (!sk_X509_push(ctx->chain, x)) { + X509_free(xtmp); + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + ctx->error = X509_V_ERR_OUT_OF_MEM; + ok = 0; + goto end; + } + num++; + } + + /* we now have our chain, lets check it... */ + trust = check_trust(ctx); + + /* If explicitly rejected error */ + if (trust == X509_TRUST_REJECTED) { + ok = 0; + goto end; + } + /* + * If it's not explicitly trusted then check if there is an alternative + * chain that could be used. We only do this if we haven't already + * checked via TRUSTED_FIRST and the user hasn't switched off alternate + * chain checking + */ + retry = 0; + if (trust != X509_TRUST_TRUSTED + && !(ctx->param->flags & X509_V_FLAG_TRUSTED_FIRST) + && !(ctx->param->flags & X509_V_FLAG_NO_ALT_CHAINS)) { + while (j-- > 1) { + xtmp2 = sk_X509_value(ctx->chain, j - 1); + ok = ctx->get_issuer(&xtmp, ctx, xtmp2); + if (ok < 0) + goto end; + /* Check if we found an alternate chain */ + if (ok > 0) { + /* + * Free up the found cert we'll add it again later + */ + X509_free(xtmp); + + /* + * Dump all the certs above this point - we've found an + * alternate chain + */ + while (num > j) { + xtmp = sk_X509_pop(ctx->chain); + X509_free(xtmp); + num--; + } + ctx->last_untrusted = sk_X509_num(ctx->chain); + retry = 1; + break; + } + } + } + } while (retry); + + /* + * If not explicitly trusted then indicate error unless it's a single + * self signed certificate in which case we've indicated an error already + * and set bad_chain == 1 + */ + if (trust != X509_TRUST_TRUSTED && !bad_chain) { + if ((chain_ss == NULL) || !ctx->check_issued(ctx, x, chain_ss)) { + if (ctx->last_untrusted >= num) + ctx->error = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY; + else + ctx->error = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT; + ctx->current_cert = x; + } else { + + sk_X509_push(ctx->chain, chain_ss); + num++; + ctx->last_untrusted = num; + ctx->current_cert = chain_ss; + ctx->error = X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN; + chain_ss = NULL; + } + + ctx->error_depth = num - 1; + bad_chain = 1; + ok = cb(0, ctx); + if (!ok) + goto end; + } + + /* We have the chain complete: now we need to check its purpose */ + ok = check_chain_extensions(ctx); + + if (!ok) + goto end; + + /* Check name constraints */ + + ok = check_name_constraints(ctx); + + if (!ok) + goto end; + + ok = check_id(ctx); + + if (!ok) + goto end; + + /* + * Check revocation status: we do this after copying parameters because + * they may be needed for CRL signature verification. + */ + + ok = ctx->check_revocation(ctx); + if (!ok) + goto end; + + int err = X509_chain_check_suiteb(&ctx->error_depth, NULL, ctx->chain, + ctx->param->flags); + if (err != X509_V_OK) { + ctx->error = err; + ctx->current_cert = sk_X509_value(ctx->chain, ctx->error_depth); + ok = cb(0, ctx); + if (!ok) + goto end; + } + + /* At this point, we have a chain and need to verify it */ + if (ctx->verify != NULL) + ok = ctx->verify(ctx); + else + ok = internal_verify(ctx); + if (!ok) + goto end; + + /* If we get this far evaluate policies */ + if (!bad_chain && (ctx->param->flags & X509_V_FLAG_POLICY_CHECK)) + ok = ctx->check_policy(ctx); + + end: + if (sktmp != NULL) + sk_X509_free(sktmp); + if (chain_ss != NULL) + X509_free(chain_ss); + + /* Safety net, error returns must set ctx->error */ + if (ok <= 0 && ctx->error == X509_V_OK) + ctx->error = X509_V_ERR_UNSPECIFIED; + return ok; +} + +/* + * Given a STACK_OF(X509) find the issuer of cert (if any) + */ + +static X509 *find_issuer(X509_STORE_CTX *ctx, STACK_OF(X509) *sk, X509 *x) +{ + size_t i; + X509 *issuer; + for (i = 0; i < sk_X509_num(sk); i++) { + issuer = sk_X509_value(sk, i); + if (ctx->check_issued(ctx, x, issuer)) + return issuer; + } + return NULL; +} + +/* Given a possible certificate and issuer check them */ + +static int check_issued(X509_STORE_CTX *ctx, X509 *x, X509 *issuer) +{ + int ret; + ret = X509_check_issued(issuer, x); + if (ret == X509_V_OK) + return 1; + /* If we haven't asked for issuer errors don't set ctx */ + if (!(ctx->param->flags & X509_V_FLAG_CB_ISSUER_CHECK)) + return 0; + + ctx->error = ret; + ctx->current_cert = x; + ctx->current_issuer = issuer; + return ctx->verify_cb(0, ctx); +} + +/* Alternative lookup method: look from a STACK stored in other_ctx */ + +static int get_issuer_sk(X509 **issuer, X509_STORE_CTX *ctx, X509 *x) +{ + *issuer = find_issuer(ctx, ctx->other_ctx, x); + if (*issuer) { + X509_up_ref(*issuer); + return 1; + } else + return 0; +} + +/* + * Check a certificate chains extensions for consistency with the supplied + * purpose + */ + +static int check_chain_extensions(X509_STORE_CTX *ctx) +{ + int i, ok = 0, must_be_ca, plen = 0; + X509 *x; + int (*cb) (int xok, X509_STORE_CTX *xctx); + int proxy_path_length = 0; + int purpose; + int allow_proxy_certs; + cb = ctx->verify_cb; + + /* + * must_be_ca can have 1 of 3 values: -1: we accept both CA and non-CA + * certificates, to allow direct use of self-signed certificates (which + * are marked as CA). 0: we only accept non-CA certificates. This is + * currently not used, but the possibility is present for future + * extensions. 1: we only accept CA certificates. This is currently used + * for all certificates in the chain except the leaf certificate. + */ + must_be_ca = -1; + + /* CRL path validation */ + if (ctx->parent) { + allow_proxy_certs = 0; + purpose = X509_PURPOSE_CRL_SIGN; + } else { + allow_proxy_certs = + ! !(ctx->param->flags & X509_V_FLAG_ALLOW_PROXY_CERTS); + /* + * A hack to keep people who don't want to modify their software + * happy + */ + if (getenv("OPENSSL_ALLOW_PROXY_CERTS")) + allow_proxy_certs = 1; + purpose = ctx->param->purpose; + } + + /* Check all untrusted certificates */ + for (i = 0; i < ctx->last_untrusted; i++) { + int ret; + x = sk_X509_value(ctx->chain, i); + if (!(ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL) + && (x->ex_flags & EXFLAG_CRITICAL)) { + ctx->error = X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION; + ctx->error_depth = i; + ctx->current_cert = x; + ok = cb(0, ctx); + if (!ok) + goto end; + } + if (!allow_proxy_certs && (x->ex_flags & EXFLAG_PROXY)) { + ctx->error = X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED; + ctx->error_depth = i; + ctx->current_cert = x; + ok = cb(0, ctx); + if (!ok) + goto end; + } + ret = X509_check_ca(x); + switch (must_be_ca) { + case -1: + if ((ctx->param->flags & X509_V_FLAG_X509_STRICT) + && (ret != 1) && (ret != 0)) { + ret = 0; + ctx->error = X509_V_ERR_INVALID_CA; + } else + ret = 1; + break; + case 0: + if (ret != 0) { + ret = 0; + ctx->error = X509_V_ERR_INVALID_NON_CA; + } else + ret = 1; + break; + default: + if ((ret == 0) + || ((ctx->param->flags & X509_V_FLAG_X509_STRICT) + && (ret != 1))) { + ret = 0; + ctx->error = X509_V_ERR_INVALID_CA; + } else + ret = 1; + break; + } + if (ret == 0) { + ctx->error_depth = i; + ctx->current_cert = x; + ok = cb(0, ctx); + if (!ok) + goto end; + } + if (ctx->param->purpose > 0) { + ret = X509_check_purpose(x, purpose, must_be_ca > 0); + if ((ret == 0) + || ((ctx->param->flags & X509_V_FLAG_X509_STRICT) + && (ret != 1))) { + ctx->error = X509_V_ERR_INVALID_PURPOSE; + ctx->error_depth = i; + ctx->current_cert = x; + ok = cb(0, ctx); + if (!ok) + goto end; + } + } + /* Check pathlen if not self issued */ + if ((i > 1) && !(x->ex_flags & EXFLAG_SI) + && (x->ex_pathlen != -1) + && (plen > (x->ex_pathlen + proxy_path_length + 1))) { + ctx->error = X509_V_ERR_PATH_LENGTH_EXCEEDED; + ctx->error_depth = i; + ctx->current_cert = x; + ok = cb(0, ctx); + if (!ok) + goto end; + } + /* Increment path length if not self issued */ + if (!(x->ex_flags & EXFLAG_SI)) + plen++; + /* + * If this certificate is a proxy certificate, the next certificate + * must be another proxy certificate or a EE certificate. If not, + * the next certificate must be a CA certificate. + */ + if (x->ex_flags & EXFLAG_PROXY) { + if (x->ex_pcpathlen != -1 && i > x->ex_pcpathlen) { + ctx->error = X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED; + ctx->error_depth = i; + ctx->current_cert = x; + ok = cb(0, ctx); + if (!ok) + goto end; + } + proxy_path_length++; + must_be_ca = 0; + } else + must_be_ca = 1; + } + ok = 1; + end: + return ok; +} + +static int check_name_constraints(X509_STORE_CTX *ctx) +{ + X509 *x; + int i, j, rv; + /* Check name constraints for all certificates */ + for (i = sk_X509_num(ctx->chain) - 1; i >= 0; i--) { + x = sk_X509_value(ctx->chain, i); + /* Ignore self issued certs unless last in chain */ + if (i && (x->ex_flags & EXFLAG_SI)) + continue; + /* + * Check against constraints for all certificates higher in chain + * including trust anchor. Trust anchor not strictly speaking needed + * but if it includes constraints it is to be assumed it expects them + * to be obeyed. + */ + for (j = sk_X509_num(ctx->chain) - 1; j > i; j--) { + NAME_CONSTRAINTS *nc = sk_X509_value(ctx->chain, j)->nc; + if (nc) { + rv = NAME_CONSTRAINTS_check(x, nc); + switch (rv) { + case X509_V_OK: + continue; + case X509_V_ERR_OUT_OF_MEM: + ctx->error = rv; + return 0; + default: + ctx->error = rv; + ctx->error_depth = i; + ctx->current_cert = x; + if (!ctx->verify_cb(0, ctx)) + return 0; + break; + } + } + } + } + return 1; +} + +static int check_id_error(X509_STORE_CTX *ctx, int errcode) +{ + ctx->error = errcode; + ctx->current_cert = ctx->cert; + ctx->error_depth = 0; + return ctx->verify_cb(0, ctx); +} + +static int check_hosts(X509 *x, X509_VERIFY_PARAM_ID *id) +{ + size_t i; + size_t n = sk_OPENSSL_STRING_num(id->hosts); + char *name; + + if (id->peername != NULL) { + OPENSSL_free(id->peername); + id->peername = NULL; + } + for (i = 0; i < n; ++i) { + name = sk_OPENSSL_STRING_value(id->hosts, i); + if (X509_check_host(x, name, strlen(name), id->hostflags, + &id->peername) > 0) + return 1; + } + return n == 0; +} + +static int check_id(X509_STORE_CTX *ctx) +{ + X509_VERIFY_PARAM *vpm = ctx->param; + X509_VERIFY_PARAM_ID *id = vpm->id; + X509 *x = ctx->cert; + if (id->hosts && check_hosts(x, id) <= 0) { + if (!check_id_error(ctx, X509_V_ERR_HOSTNAME_MISMATCH)) + return 0; + } + if (id->email && X509_check_email(x, id->email, id->emaillen, 0) <= 0) { + if (!check_id_error(ctx, X509_V_ERR_EMAIL_MISMATCH)) + return 0; + } + if (id->ip && X509_check_ip(x, id->ip, id->iplen, 0) <= 0) { + if (!check_id_error(ctx, X509_V_ERR_IP_ADDRESS_MISMATCH)) + return 0; + } + return 1; +} + +static int check_trust(X509_STORE_CTX *ctx) +{ + size_t i; + int ok; + X509 *x = NULL; + int (*cb) (int xok, X509_STORE_CTX *xctx); + cb = ctx->verify_cb; + /* Check all trusted certificates in chain */ + for (i = ctx->last_untrusted; i < sk_X509_num(ctx->chain); i++) { + x = sk_X509_value(ctx->chain, i); + ok = X509_check_trust(x, ctx->param->trust, 0); + /* If explicitly trusted return trusted */ + if (ok == X509_TRUST_TRUSTED) + return X509_TRUST_TRUSTED; + /* + * If explicitly rejected notify callback and reject if not + * overridden. + */ + if (ok == X509_TRUST_REJECTED) { + ctx->error_depth = i; + ctx->current_cert = x; + ctx->error = X509_V_ERR_CERT_REJECTED; + ok = cb(0, ctx); + if (!ok) + return X509_TRUST_REJECTED; + } + } + /* + * If we accept partial chains and have at least one trusted certificate + * return success. + */ + if (ctx->param->flags & X509_V_FLAG_PARTIAL_CHAIN) { + X509 *mx; + if (ctx->last_untrusted < (int)sk_X509_num(ctx->chain)) + return X509_TRUST_TRUSTED; + x = sk_X509_value(ctx->chain, 0); + mx = lookup_cert_match(ctx, x); + if (mx) { + (void)sk_X509_set(ctx->chain, 0, mx); + X509_free(x); + ctx->last_untrusted = 0; + return X509_TRUST_TRUSTED; + } + } + + /* + * If no trusted certs in chain at all return untrusted and allow + * standard (no issuer cert) etc errors to be indicated. + */ + return X509_TRUST_UNTRUSTED; +} + +static int check_revocation(X509_STORE_CTX *ctx) +{ + int i, last, ok; + if (!(ctx->param->flags & X509_V_FLAG_CRL_CHECK)) + return 1; + if (ctx->param->flags & X509_V_FLAG_CRL_CHECK_ALL) + last = sk_X509_num(ctx->chain) - 1; + else { + /* If checking CRL paths this isn't the EE certificate */ + if (ctx->parent) + return 1; + last = 0; + } + for (i = 0; i <= last; i++) { + ctx->error_depth = i; + ok = check_cert(ctx); + if (!ok) + return ok; + } + return 1; +} + +static int check_cert(X509_STORE_CTX *ctx) +{ + X509_CRL *crl = NULL, *dcrl = NULL; + X509 *x; + int ok = 0, cnum; + unsigned int last_reasons; + cnum = ctx->error_depth; + x = sk_X509_value(ctx->chain, cnum); + ctx->current_cert = x; + ctx->current_issuer = NULL; + ctx->current_crl_score = 0; + ctx->current_reasons = 0; + while (ctx->current_reasons != CRLDP_ALL_REASONS) { + last_reasons = ctx->current_reasons; + /* Try to retrieve relevant CRL */ + if (ctx->get_crl) + ok = ctx->get_crl(ctx, &crl, x); + else + ok = get_crl_delta(ctx, &crl, &dcrl, x); + /* + * If error looking up CRL, nothing we can do except notify callback + */ + if (!ok) { + ctx->error = X509_V_ERR_UNABLE_TO_GET_CRL; + ok = ctx->verify_cb(0, ctx); + goto err; + } + ctx->current_crl = crl; + ok = ctx->check_crl(ctx, crl); + if (!ok) + goto err; + + if (dcrl) { + ok = ctx->check_crl(ctx, dcrl); + if (!ok) + goto err; + ok = ctx->cert_crl(ctx, dcrl, x); + if (!ok) + goto err; + } else + ok = 1; + + /* Don't look in full CRL if delta reason is removefromCRL */ + if (ok != 2) { + ok = ctx->cert_crl(ctx, crl, x); + if (!ok) + goto err; + } + + X509_CRL_free(crl); + X509_CRL_free(dcrl); + crl = NULL; + dcrl = NULL; + /* + * If reasons not updated we wont get anywhere by another iteration, + * so exit loop. + */ + if (last_reasons == ctx->current_reasons) { + ctx->error = X509_V_ERR_UNABLE_TO_GET_CRL; + ok = ctx->verify_cb(0, ctx); + goto err; + } + } + err: + X509_CRL_free(crl); + X509_CRL_free(dcrl); + + ctx->current_crl = NULL; + return ok; + +} + +/* Check CRL times against values in X509_STORE_CTX */ + +static int check_crl_time(X509_STORE_CTX *ctx, X509_CRL *crl, int notify) +{ + time_t *ptime; + int i; + if (notify) + ctx->current_crl = crl; + if (ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME) + ptime = &ctx->param->check_time; + else + ptime = NULL; + + i = X509_cmp_time(X509_CRL_get_lastUpdate(crl), ptime); + if (i == 0) { + if (!notify) + return 0; + ctx->error = X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD; + if (!ctx->verify_cb(0, ctx)) + return 0; + } + + if (i > 0) { + if (!notify) + return 0; + ctx->error = X509_V_ERR_CRL_NOT_YET_VALID; + if (!ctx->verify_cb(0, ctx)) + return 0; + } + + if (X509_CRL_get_nextUpdate(crl)) { + i = X509_cmp_time(X509_CRL_get_nextUpdate(crl), ptime); + + if (i == 0) { + if (!notify) + return 0; + ctx->error = X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD; + if (!ctx->verify_cb(0, ctx)) + return 0; + } + /* Ignore expiry of base CRL is delta is valid */ + if ((i < 0) && !(ctx->current_crl_score & CRL_SCORE_TIME_DELTA)) { + if (!notify) + return 0; + ctx->error = X509_V_ERR_CRL_HAS_EXPIRED; + if (!ctx->verify_cb(0, ctx)) + return 0; + } + } + + if (notify) + ctx->current_crl = NULL; + + return 1; +} + +static int get_crl_sk(X509_STORE_CTX *ctx, X509_CRL **pcrl, X509_CRL **pdcrl, + X509 **pissuer, int *pscore, unsigned int *preasons, + STACK_OF(X509_CRL) *crls) +{ + int crl_score, best_score = *pscore; + size_t i; + unsigned int reasons, best_reasons = 0; + X509 *x = ctx->current_cert; + X509_CRL *crl, *best_crl = NULL; + X509 *crl_issuer = NULL, *best_crl_issuer = NULL; + + for (i = 0; i < sk_X509_CRL_num(crls); i++) { + crl = sk_X509_CRL_value(crls, i); + reasons = *preasons; + crl_score = get_crl_score(ctx, &crl_issuer, &reasons, crl, x); + + if (crl_score > best_score) { + best_crl = crl; + best_crl_issuer = crl_issuer; + best_score = crl_score; + best_reasons = reasons; + } + } + + if (best_crl) { + if (*pcrl) + X509_CRL_free(*pcrl); + *pcrl = best_crl; + *pissuer = best_crl_issuer; + *pscore = best_score; + *preasons = best_reasons; + X509_CRL_up_ref(best_crl); + if (*pdcrl) { + X509_CRL_free(*pdcrl); + *pdcrl = NULL; + } + get_delta_sk(ctx, pdcrl, pscore, best_crl, crls); + } + + if (best_score >= CRL_SCORE_VALID) + return 1; + + return 0; +} + +/* + * Compare two CRL extensions for delta checking purposes. They should be + * both present or both absent. If both present all fields must be identical. + */ + +static int crl_extension_match(X509_CRL *a, X509_CRL *b, int nid) +{ + ASN1_OCTET_STRING *exta, *extb; + int i; + i = X509_CRL_get_ext_by_NID(a, nid, -1); + if (i >= 0) { + /* Can't have multiple occurrences */ + if (X509_CRL_get_ext_by_NID(a, nid, i) != -1) + return 0; + exta = X509_EXTENSION_get_data(X509_CRL_get_ext(a, i)); + } else + exta = NULL; + + i = X509_CRL_get_ext_by_NID(b, nid, -1); + + if (i >= 0) { + + if (X509_CRL_get_ext_by_NID(b, nid, i) != -1) + return 0; + extb = X509_EXTENSION_get_data(X509_CRL_get_ext(b, i)); + } else + extb = NULL; + + if (!exta && !extb) + return 1; + + if (!exta || !extb) + return 0; + + if (ASN1_OCTET_STRING_cmp(exta, extb)) + return 0; + + return 1; +} + +/* See if a base and delta are compatible */ + +static int check_delta_base(X509_CRL *delta, X509_CRL *base) +{ + /* Delta CRL must be a delta */ + if (!delta->base_crl_number) + return 0; + /* Base must have a CRL number */ + if (!base->crl_number) + return 0; + /* Issuer names must match */ + if (X509_NAME_cmp(X509_CRL_get_issuer(base), X509_CRL_get_issuer(delta))) + return 0; + /* AKID and IDP must match */ + if (!crl_extension_match(delta, base, NID_authority_key_identifier)) + return 0; + if (!crl_extension_match(delta, base, NID_issuing_distribution_point)) + return 0; + /* Delta CRL base number must not exceed Full CRL number. */ + if (ASN1_INTEGER_cmp(delta->base_crl_number, base->crl_number) > 0) + return 0; + /* Delta CRL number must exceed full CRL number */ + if (ASN1_INTEGER_cmp(delta->crl_number, base->crl_number) > 0) + return 1; + return 0; +} + +/* + * For a given base CRL find a delta... maybe extend to delta scoring or + * retrieve a chain of deltas... + */ + +static void get_delta_sk(X509_STORE_CTX *ctx, X509_CRL **dcrl, int *pscore, + X509_CRL *base, STACK_OF(X509_CRL) *crls) +{ + X509_CRL *delta; + size_t i; + if (!(ctx->param->flags & X509_V_FLAG_USE_DELTAS)) + return; + if (!((ctx->current_cert->ex_flags | base->flags) & EXFLAG_FRESHEST)) + return; + for (i = 0; i < sk_X509_CRL_num(crls); i++) { + delta = sk_X509_CRL_value(crls, i); + if (check_delta_base(delta, base)) { + if (check_crl_time(ctx, delta, 0)) + *pscore |= CRL_SCORE_TIME_DELTA; + X509_CRL_up_ref(delta); + *dcrl = delta; + return; + } + } + *dcrl = NULL; +} + +/* + * For a given CRL return how suitable it is for the supplied certificate + * 'x'. The return value is a mask of several criteria. If the issuer is not + * the certificate issuer this is returned in *pissuer. The reasons mask is + * also used to determine if the CRL is suitable: if no new reasons the CRL + * is rejected, otherwise reasons is updated. + */ + +static int get_crl_score(X509_STORE_CTX *ctx, X509 **pissuer, + unsigned int *preasons, X509_CRL *crl, X509 *x) +{ + + int crl_score = 0; + unsigned int tmp_reasons = *preasons, crl_reasons; + + /* First see if we can reject CRL straight away */ + + /* Invalid IDP cannot be processed */ + if (crl->idp_flags & IDP_INVALID) + return 0; + /* Reason codes or indirect CRLs need extended CRL support */ + if (!(ctx->param->flags & X509_V_FLAG_EXTENDED_CRL_SUPPORT)) { + if (crl->idp_flags & (IDP_INDIRECT | IDP_REASONS)) + return 0; + } else if (crl->idp_flags & IDP_REASONS) { + /* If no new reasons reject */ + if (!(crl->idp_reasons & ~tmp_reasons)) + return 0; + } + /* Don't process deltas at this stage */ + else if (crl->base_crl_number) + return 0; + /* If issuer name doesn't match certificate need indirect CRL */ + if (X509_NAME_cmp(X509_get_issuer_name(x), X509_CRL_get_issuer(crl))) { + if (!(crl->idp_flags & IDP_INDIRECT)) + return 0; + } else + crl_score |= CRL_SCORE_ISSUER_NAME; + + if (!(crl->flags & EXFLAG_CRITICAL)) + crl_score |= CRL_SCORE_NOCRITICAL; + + /* Check expiry */ + if (check_crl_time(ctx, crl, 0)) + crl_score |= CRL_SCORE_TIME; + + /* Check authority key ID and locate certificate issuer */ + crl_akid_check(ctx, crl, pissuer, &crl_score); + + /* If we can't locate certificate issuer at this point forget it */ + + if (!(crl_score & CRL_SCORE_AKID)) + return 0; + + /* Check cert for matching CRL distribution points */ + + if (crl_crldp_check(x, crl, crl_score, &crl_reasons)) { + /* If no new reasons reject */ + if (!(crl_reasons & ~tmp_reasons)) + return 0; + tmp_reasons |= crl_reasons; + crl_score |= CRL_SCORE_SCOPE; + } + + *preasons = tmp_reasons; + + return crl_score; + +} + +static void crl_akid_check(X509_STORE_CTX *ctx, X509_CRL *crl, + X509 **pissuer, int *pcrl_score) +{ + X509 *crl_issuer = NULL; + X509_NAME *cnm = X509_CRL_get_issuer(crl); + int cidx = ctx->error_depth; + size_t i; + + if ((size_t)cidx != sk_X509_num(ctx->chain) - 1) + cidx++; + + crl_issuer = sk_X509_value(ctx->chain, cidx); + + if (X509_check_akid(crl_issuer, crl->akid) == X509_V_OK) { + if (*pcrl_score & CRL_SCORE_ISSUER_NAME) { + *pcrl_score |= CRL_SCORE_AKID | CRL_SCORE_ISSUER_CERT; + *pissuer = crl_issuer; + return; + } + } + + for (cidx++; cidx < (int)sk_X509_num(ctx->chain); cidx++) { + crl_issuer = sk_X509_value(ctx->chain, cidx); + if (X509_NAME_cmp(X509_get_subject_name(crl_issuer), cnm)) + continue; + if (X509_check_akid(crl_issuer, crl->akid) == X509_V_OK) { + *pcrl_score |= CRL_SCORE_AKID | CRL_SCORE_SAME_PATH; + *pissuer = crl_issuer; + return; + } + } + + /* Anything else needs extended CRL support */ + + if (!(ctx->param->flags & X509_V_FLAG_EXTENDED_CRL_SUPPORT)) + return; + + /* + * Otherwise the CRL issuer is not on the path. Look for it in the set of + * untrusted certificates. + */ + for (i = 0; i < sk_X509_num(ctx->untrusted); i++) { + crl_issuer = sk_X509_value(ctx->untrusted, i); + if (X509_NAME_cmp(X509_get_subject_name(crl_issuer), cnm)) + continue; + if (X509_check_akid(crl_issuer, crl->akid) == X509_V_OK) { + *pissuer = crl_issuer; + *pcrl_score |= CRL_SCORE_AKID; + return; + } + } +} + +/* + * Check the path of a CRL issuer certificate. This creates a new + * X509_STORE_CTX and populates it with most of the parameters from the + * parent. This could be optimised somewhat since a lot of path checking will + * be duplicated by the parent, but this will rarely be used in practice. + */ + +static int check_crl_path(X509_STORE_CTX *ctx, X509 *x) +{ + X509_STORE_CTX crl_ctx; + int ret; + /* Don't allow recursive CRL path validation */ + if (ctx->parent) + return 0; + if (!X509_STORE_CTX_init(&crl_ctx, ctx->ctx, x, ctx->untrusted)) + return -1; + + crl_ctx.crls = ctx->crls; + /* Copy verify params across */ + X509_STORE_CTX_set0_param(&crl_ctx, ctx->param); + + crl_ctx.parent = ctx; + crl_ctx.verify_cb = ctx->verify_cb; + + /* Verify CRL issuer */ + ret = X509_verify_cert(&crl_ctx); + + if (ret <= 0) + goto err; + + /* Check chain is acceptable */ + + ret = check_crl_chain(ctx, ctx->chain, crl_ctx.chain); + err: + X509_STORE_CTX_cleanup(&crl_ctx); + return ret; +} + +/* + * RFC3280 says nothing about the relationship between CRL path and + * certificate path, which could lead to situations where a certificate could + * be revoked or validated by a CA not authorised to do so. RFC5280 is more + * strict and states that the two paths must end in the same trust anchor, + * though some discussions remain... until this is resolved we use the + * RFC5280 version + */ + +static int check_crl_chain(X509_STORE_CTX *ctx, + STACK_OF(X509) *cert_path, + STACK_OF(X509) *crl_path) +{ + X509 *cert_ta, *crl_ta; + cert_ta = sk_X509_value(cert_path, sk_X509_num(cert_path) - 1); + crl_ta = sk_X509_value(crl_path, sk_X509_num(crl_path) - 1); + if (!X509_cmp(cert_ta, crl_ta)) + return 1; + return 0; +} + +/* + * Check for match between two dist point names: three separate cases. 1. + * Both are relative names and compare X509_NAME types. 2. One full, one + * relative. Compare X509_NAME to GENERAL_NAMES. 3. Both are full names and + * compare two GENERAL_NAMES. 4. One is NULL: automatic match. + */ + +static int idp_check_dp(DIST_POINT_NAME *a, DIST_POINT_NAME *b) +{ + X509_NAME *nm = NULL; + GENERAL_NAMES *gens = NULL; + GENERAL_NAME *gena, *genb; + size_t i, j; + if (!a || !b) + return 1; + if (a->type == 1) { + if (!a->dpname) + return 0; + /* Case 1: two X509_NAME */ + if (b->type == 1) { + if (!b->dpname) + return 0; + if (!X509_NAME_cmp(a->dpname, b->dpname)) + return 1; + else + return 0; + } + /* Case 2: set name and GENERAL_NAMES appropriately */ + nm = a->dpname; + gens = b->name.fullname; + } else if (b->type == 1) { + if (!b->dpname) + return 0; + /* Case 2: set name and GENERAL_NAMES appropriately */ + gens = a->name.fullname; + nm = b->dpname; + } + + /* Handle case 2 with one GENERAL_NAMES and one X509_NAME */ + if (nm) { + for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { + gena = sk_GENERAL_NAME_value(gens, i); + if (gena->type != GEN_DIRNAME) + continue; + if (!X509_NAME_cmp(nm, gena->d.directoryName)) + return 1; + } + return 0; + } + + /* Else case 3: two GENERAL_NAMES */ + + for (i = 0; i < sk_GENERAL_NAME_num(a->name.fullname); i++) { + gena = sk_GENERAL_NAME_value(a->name.fullname, i); + for (j = 0; j < sk_GENERAL_NAME_num(b->name.fullname); j++) { + genb = sk_GENERAL_NAME_value(b->name.fullname, j); + if (!GENERAL_NAME_cmp(gena, genb)) + return 1; + } + } + + return 0; + +} + +static int crldp_check_crlissuer(DIST_POINT *dp, X509_CRL *crl, int crl_score) +{ + size_t i; + X509_NAME *nm = X509_CRL_get_issuer(crl); + /* If no CRLissuer return is successful iff don't need a match */ + if (!dp->CRLissuer) + return ! !(crl_score & CRL_SCORE_ISSUER_NAME); + for (i = 0; i < sk_GENERAL_NAME_num(dp->CRLissuer); i++) { + GENERAL_NAME *gen = sk_GENERAL_NAME_value(dp->CRLissuer, i); + if (gen->type != GEN_DIRNAME) + continue; + if (!X509_NAME_cmp(gen->d.directoryName, nm)) + return 1; + } + return 0; +} + +/* Check CRLDP and IDP */ + +static int crl_crldp_check(X509 *x, X509_CRL *crl, int crl_score, + unsigned int *preasons) +{ + size_t i; + if (crl->idp_flags & IDP_ONLYATTR) + return 0; + if (x->ex_flags & EXFLAG_CA) { + if (crl->idp_flags & IDP_ONLYUSER) + return 0; + } else { + if (crl->idp_flags & IDP_ONLYCA) + return 0; + } + *preasons = crl->idp_reasons; + for (i = 0; i < sk_DIST_POINT_num(x->crldp); i++) { + DIST_POINT *dp = sk_DIST_POINT_value(x->crldp, i); + if (crldp_check_crlissuer(dp, crl, crl_score)) { + if (!crl->idp || idp_check_dp(dp->distpoint, crl->idp->distpoint)) { + *preasons &= dp->dp_reasons; + return 1; + } + } + } + if ((!crl->idp || !crl->idp->distpoint) + && (crl_score & CRL_SCORE_ISSUER_NAME)) + return 1; + return 0; +} + +/* + * Retrieve CRL corresponding to current certificate. If deltas enabled try + * to find a delta CRL too + */ + +static int get_crl_delta(X509_STORE_CTX *ctx, + X509_CRL **pcrl, X509_CRL **pdcrl, X509 *x) +{ + int ok; + X509 *issuer = NULL; + int crl_score = 0; + unsigned int reasons; + X509_CRL *crl = NULL, *dcrl = NULL; + STACK_OF(X509_CRL) *skcrl; + X509_NAME *nm = X509_get_issuer_name(x); + reasons = ctx->current_reasons; + ok = get_crl_sk(ctx, &crl, &dcrl, + &issuer, &crl_score, &reasons, ctx->crls); + + if (ok) + goto done; + + /* Lookup CRLs from store */ + + skcrl = ctx->lookup_crls(ctx, nm); + + /* If no CRLs found and a near match from get_crl_sk use that */ + if (!skcrl && crl) + goto done; + + get_crl_sk(ctx, &crl, &dcrl, &issuer, &crl_score, &reasons, skcrl); + + sk_X509_CRL_pop_free(skcrl, X509_CRL_free); + + done: + + /* If we got any kind of CRL use it and return success */ + if (crl) { + ctx->current_issuer = issuer; + ctx->current_crl_score = crl_score; + ctx->current_reasons = reasons; + *pcrl = crl; + *pdcrl = dcrl; + return 1; + } + + return 0; +} + +/* Check CRL validity */ +static int check_crl(X509_STORE_CTX *ctx, X509_CRL *crl) +{ + X509 *issuer = NULL; + EVP_PKEY *ikey = NULL; + int ok = 0, chnum, cnum; + cnum = ctx->error_depth; + chnum = sk_X509_num(ctx->chain) - 1; + /* if we have an alternative CRL issuer cert use that */ + if (ctx->current_issuer) + issuer = ctx->current_issuer; + + /* + * Else find CRL issuer: if not last certificate then issuer is next + * certificate in chain. + */ + else if (cnum < chnum) + issuer = sk_X509_value(ctx->chain, cnum + 1); + else { + issuer = sk_X509_value(ctx->chain, chnum); + /* If not self signed, can't check signature */ + if (!ctx->check_issued(ctx, issuer, issuer)) { + ctx->error = X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER; + ok = ctx->verify_cb(0, ctx); + if (!ok) + goto err; + } + } + + if (issuer) { + /* + * Skip most tests for deltas because they have already been done + */ + if (!crl->base_crl_number) { + /* Check for cRLSign bit if keyUsage present */ + if ((issuer->ex_flags & EXFLAG_KUSAGE) && + !(issuer->ex_kusage & KU_CRL_SIGN)) { + ctx->error = X509_V_ERR_KEYUSAGE_NO_CRL_SIGN; + ok = ctx->verify_cb(0, ctx); + if (!ok) + goto err; + } + + if (!(ctx->current_crl_score & CRL_SCORE_SCOPE)) { + ctx->error = X509_V_ERR_DIFFERENT_CRL_SCOPE; + ok = ctx->verify_cb(0, ctx); + if (!ok) + goto err; + } + + if (!(ctx->current_crl_score & CRL_SCORE_SAME_PATH)) { + if (check_crl_path(ctx, ctx->current_issuer) <= 0) { + ctx->error = X509_V_ERR_CRL_PATH_VALIDATION_ERROR; + ok = ctx->verify_cb(0, ctx); + if (!ok) + goto err; + } + } + + if (crl->idp_flags & IDP_INVALID) { + ctx->error = X509_V_ERR_INVALID_EXTENSION; + ok = ctx->verify_cb(0, ctx); + if (!ok) + goto err; + } + + } + + if (!(ctx->current_crl_score & CRL_SCORE_TIME)) { + ok = check_crl_time(ctx, crl, 1); + if (!ok) + goto err; + } + + /* Attempt to get issuer certificate public key */ + ikey = X509_get_pubkey(issuer); + + if (!ikey) { + ctx->error = X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY; + ok = ctx->verify_cb(0, ctx); + if (!ok) + goto err; + } else { + int rv; + rv = X509_CRL_check_suiteb(crl, ikey, ctx->param->flags); + if (rv != X509_V_OK) { + ctx->error = rv; + ok = ctx->verify_cb(0, ctx); + if (!ok) + goto err; + } + /* Verify CRL signature */ + if (X509_CRL_verify(crl, ikey) <= 0) { + ctx->error = X509_V_ERR_CRL_SIGNATURE_FAILURE; + ok = ctx->verify_cb(0, ctx); + if (!ok) + goto err; + } + } + } + + ok = 1; + + err: + EVP_PKEY_free(ikey); + return ok; +} + +/* Check certificate against CRL */ +static int cert_crl(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x) +{ + int ok; + X509_REVOKED *rev; + /* + * The rules changed for this... previously if a CRL contained unhandled + * critical extensions it could still be used to indicate a certificate + * was revoked. This has since been changed since critical extension can + * change the meaning of CRL entries. + */ + if (!(ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL) + && (crl->flags & EXFLAG_CRITICAL)) { + ctx->error = X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION; + ok = ctx->verify_cb(0, ctx); + if (!ok) + return 0; + } + /* + * Look for serial number of certificate in CRL If found make sure reason + * is not removeFromCRL. + */ + if (X509_CRL_get0_by_cert(crl, &rev, x)) { + if (rev->reason == CRL_REASON_REMOVE_FROM_CRL) + return 2; + ctx->error = X509_V_ERR_CERT_REVOKED; + ok = ctx->verify_cb(0, ctx); + if (!ok) + return 0; + } + + return 1; +} + +static int check_policy(X509_STORE_CTX *ctx) +{ + int ret; + if (ctx->parent) + return 1; + ret = X509_policy_check(&ctx->tree, &ctx->explicit_policy, ctx->chain, + ctx->param->policies, ctx->param->flags); + if (ret == 0) { + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + ctx->error = X509_V_ERR_OUT_OF_MEM; + return 0; + } + /* Invalid or inconsistent extensions */ + if (ret == -1) { + /* + * Locate certificates with bad extensions and notify callback. + */ + X509 *x; + size_t i; + for (i = 1; i < sk_X509_num(ctx->chain); i++) { + x = sk_X509_value(ctx->chain, i); + if (!(x->ex_flags & EXFLAG_INVALID_POLICY)) + continue; + ctx->current_cert = x; + ctx->error = X509_V_ERR_INVALID_POLICY_EXTENSION; + if (!ctx->verify_cb(0, ctx)) + return 0; + } + return 1; + } + if (ret == -2) { + ctx->current_cert = NULL; + ctx->error = X509_V_ERR_NO_EXPLICIT_POLICY; + return ctx->verify_cb(0, ctx); + } + + if (ctx->param->flags & X509_V_FLAG_NOTIFY_POLICY) { + ctx->current_cert = NULL; + /* + * Verification errors need to be "sticky", a callback may have allowed + * an SSL handshake to continue despite an error, and we must then + * remain in an error state. Therefore, we MUST NOT clear earlier + * verification errors by setting the error to X509_V_OK. + */ + if (!ctx->verify_cb(2, ctx)) + return 0; + } + + return 1; +} + +static int check_cert_time(X509_STORE_CTX *ctx, X509 *x) +{ + time_t *ptime; + int i; + + if (ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME) + ptime = &ctx->param->check_time; + else + ptime = NULL; + + i = X509_cmp_time(X509_get_notBefore(x), ptime); + if (i == 0) { + ctx->error = X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD; + ctx->current_cert = x; + if (!ctx->verify_cb(0, ctx)) + return 0; + } + + if (i > 0) { + ctx->error = X509_V_ERR_CERT_NOT_YET_VALID; + ctx->current_cert = x; + if (!ctx->verify_cb(0, ctx)) + return 0; + } + + i = X509_cmp_time(X509_get_notAfter(x), ptime); + if (i == 0) { + ctx->error = X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD; + ctx->current_cert = x; + if (!ctx->verify_cb(0, ctx)) + return 0; + } + + if (i < 0) { + ctx->error = X509_V_ERR_CERT_HAS_EXPIRED; + ctx->current_cert = x; + if (!ctx->verify_cb(0, ctx)) + return 0; + } + + return 1; +} + +static int internal_verify(X509_STORE_CTX *ctx) +{ + int ok = 0, n; + X509 *xs, *xi; + EVP_PKEY *pkey = NULL; + int (*cb) (int xok, X509_STORE_CTX *xctx); + + cb = ctx->verify_cb; + + n = sk_X509_num(ctx->chain); + ctx->error_depth = n - 1; + n--; + xi = sk_X509_value(ctx->chain, n); + + if (ctx->check_issued(ctx, xi, xi)) + xs = xi; + else { + if (ctx->param->flags & X509_V_FLAG_PARTIAL_CHAIN) { + xs = xi; + goto check_cert; + } + if (n <= 0) { + ctx->error = X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE; + ctx->current_cert = xi; + ok = cb(0, ctx); + goto end; + } else { + n--; + ctx->error_depth = n; + xs = sk_X509_value(ctx->chain, n); + } + } + +/* ctx->error=0; not needed */ + while (n >= 0) { + ctx->error_depth = n; + + /* + * Skip signature check for self signed certificates unless + * explicitly asked for. It doesn't add any security and just wastes + * time. + */ + if (!xs->valid + && (xs != xi + || (ctx->param->flags & X509_V_FLAG_CHECK_SS_SIGNATURE))) { + if ((pkey = X509_get_pubkey(xi)) == NULL) { + ctx->error = X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY; + ctx->current_cert = xi; + ok = (*cb) (0, ctx); + if (!ok) + goto end; + } else if (X509_verify(xs, pkey) <= 0) { + ctx->error = X509_V_ERR_CERT_SIGNATURE_FAILURE; + ctx->current_cert = xs; + ok = (*cb) (0, ctx); + if (!ok) { + EVP_PKEY_free(pkey); + goto end; + } + } + EVP_PKEY_free(pkey); + pkey = NULL; + } + + xs->valid = 1; + + check_cert: + ok = check_cert_time(ctx, xs); + if (!ok) + goto end; + + /* The last error (if any) is still in the error value */ + ctx->current_issuer = xi; + ctx->current_cert = xs; + ok = (*cb) (1, ctx); + if (!ok) + goto end; + + n--; + if (n >= 0) { + xi = xs; + xs = sk_X509_value(ctx->chain, n); + } + } + ok = 1; + end: + return ok; +} + +int X509_cmp_current_time(const ASN1_TIME *ctm) +{ + return X509_cmp_time(ctm, NULL); +} + +int X509_cmp_time(const ASN1_TIME *ctm, time_t *cmp_time) +{ + char *str; + ASN1_TIME atm; + long offset; + char buff1[24], buff2[24], *p; + int i, j, remaining; + + p = buff1; + remaining = ctm->length; + str = (char *)ctm->data; + /* + * Note that the following (historical) code allows much more slack in + * the time format than RFC5280. In RFC5280, the representation is fixed: + * UTCTime: YYMMDDHHMMSSZ GeneralizedTime: YYYYMMDDHHMMSSZ + */ + if (ctm->type == V_ASN1_UTCTIME) { + /* YYMMDDHHMM[SS]Z or YYMMDDHHMM[SS](+-)hhmm */ + int min_length = sizeof("YYMMDDHHMMZ") - 1; + int max_length = sizeof("YYMMDDHHMMSS+hhmm") - 1; + if (remaining < min_length || remaining > max_length) + return 0; + memcpy(p, str, 10); + p += 10; + str += 10; + remaining -= 10; + } else { + /* + * YYYYMMDDHHMM[SS[.fff]]Z or YYYYMMDDHHMM[SS[.f[f[f]]]](+-)hhmm + */ + int min_length = sizeof("YYYYMMDDHHMMZ") - 1; + int max_length = sizeof("YYYYMMDDHHMMSS.fff+hhmm") - 1; + if (remaining < min_length || remaining > max_length) + return 0; + memcpy(p, str, 12); + p += 12; + str += 12; + remaining -= 12; + } + + if ((*str == 'Z') || (*str == '-') || (*str == '+')) { + *(p++) = '0'; + *(p++) = '0'; + } else { + /* SS (seconds) */ + if (remaining < 2) + return 0; + *(p++) = *(str++); + *(p++) = *(str++); + remaining -= 2; + /* + * Skip any (up to three) fractional seconds... TODO(emilia): in + * RFC5280, fractional seconds are forbidden. Can we just kill them + * altogether? + */ + if (remaining && *str == '.') { + str++; + remaining--; + for (i = 0; i < 3 && remaining; i++, str++, remaining--) { + if (*str < '0' || *str > '9') + break; + } + } + + } + *(p++) = 'Z'; + *(p++) = '\0'; + + /* We now need either a terminating 'Z' or an offset. */ + if (!remaining) + return 0; + if (*str == 'Z') { + if (remaining != 1) + return 0; + offset = 0; + } else { + /* (+-)HHMM */ + if ((*str != '+') && (*str != '-')) + return 0; + /* + * Historical behaviour: the (+-)hhmm offset is forbidden in RFC5280. + */ + if (remaining != 5) + return 0; + if (str[1] < '0' || str[1] > '9' || str[2] < '0' || str[2] > '9' || + str[3] < '0' || str[3] > '9' || str[4] < '0' || str[4] > '9') + return 0; + offset = ((str[1] - '0') * 10 + (str[2] - '0')) * 60; + offset += (str[3] - '0') * 10 + (str[4] - '0'); + if (*str == '-') + offset = -offset; + } + atm.type = ctm->type; + atm.flags = 0; + atm.length = sizeof(buff2); + atm.data = (unsigned char *)buff2; + + if (X509_time_adj(&atm, offset * 60, cmp_time) == NULL) + return 0; + + if (ctm->type == V_ASN1_UTCTIME) { + i = (buff1[0] - '0') * 10 + (buff1[1] - '0'); + if (i < 50) + i += 100; /* cf. RFC 2459 */ + j = (buff2[0] - '0') * 10 + (buff2[1] - '0'); + if (j < 50) + j += 100; + + if (i < j) + return -1; + if (i > j) + return 1; + } + i = strcmp(buff1, buff2); + if (i == 0) /* wait a second then return younger :-) */ + return -1; + else + return i; +} + +ASN1_TIME *X509_gmtime_adj(ASN1_TIME *s, long adj) +{ + return X509_time_adj(s, adj, NULL); +} + +ASN1_TIME *X509_time_adj(ASN1_TIME *s, long offset_sec, time_t *in_tm) +{ + return X509_time_adj_ex(s, 0, offset_sec, in_tm); +} + +ASN1_TIME *X509_time_adj_ex(ASN1_TIME *s, + int offset_day, long offset_sec, time_t *in_tm) +{ + time_t t = 0; + + if (in_tm) + t = *in_tm; + else + time(&t); + + if (s && !(s->flags & ASN1_STRING_FLAG_MSTRING)) { + if (s->type == V_ASN1_UTCTIME) + return ASN1_UTCTIME_adj(s, t, offset_day, offset_sec); + if (s->type == V_ASN1_GENERALIZEDTIME) + return ASN1_GENERALIZEDTIME_adj(s, t, offset_day, offset_sec); + } + return ASN1_TIME_adj(s, t, offset_day, offset_sec); +} + +/* Make a delta CRL as the diff between two full CRLs */ + +X509_CRL *X509_CRL_diff(X509_CRL *base, X509_CRL *newer, + EVP_PKEY *skey, const EVP_MD *md, unsigned int flags) +{ + X509_CRL *crl = NULL; + int i; + size_t j; + STACK_OF(X509_REVOKED) *revs = NULL; + /* CRLs can't be delta already */ + if (base->base_crl_number || newer->base_crl_number) { + OPENSSL_PUT_ERROR(X509, X509_R_CRL_ALREADY_DELTA); + return NULL; + } + /* Base and new CRL must have a CRL number */ + if (!base->crl_number || !newer->crl_number) { + OPENSSL_PUT_ERROR(X509, X509_R_NO_CRL_NUMBER); + return NULL; + } + /* Issuer names must match */ + if (X509_NAME_cmp(X509_CRL_get_issuer(base), X509_CRL_get_issuer(newer))) { + OPENSSL_PUT_ERROR(X509, X509_R_ISSUER_MISMATCH); + return NULL; + } + /* AKID and IDP must match */ + if (!crl_extension_match(base, newer, NID_authority_key_identifier)) { + OPENSSL_PUT_ERROR(X509, X509_R_AKID_MISMATCH); + return NULL; + } + if (!crl_extension_match(base, newer, NID_issuing_distribution_point)) { + OPENSSL_PUT_ERROR(X509, X509_R_IDP_MISMATCH); + return NULL; + } + /* Newer CRL number must exceed full CRL number */ + if (ASN1_INTEGER_cmp(newer->crl_number, base->crl_number) <= 0) { + OPENSSL_PUT_ERROR(X509, X509_R_NEWER_CRL_NOT_NEWER); + return NULL; + } + /* CRLs must verify */ + if (skey && (X509_CRL_verify(base, skey) <= 0 || + X509_CRL_verify(newer, skey) <= 0)) { + OPENSSL_PUT_ERROR(X509, X509_R_CRL_VERIFY_FAILURE); + return NULL; + } + /* Create new CRL */ + crl = X509_CRL_new(); + if (!crl || !X509_CRL_set_version(crl, 1)) + goto memerr; + /* Set issuer name */ + if (!X509_CRL_set_issuer_name(crl, X509_CRL_get_issuer(newer))) + goto memerr; + + if (!X509_CRL_set_lastUpdate(crl, X509_CRL_get_lastUpdate(newer))) + goto memerr; + if (!X509_CRL_set_nextUpdate(crl, X509_CRL_get_nextUpdate(newer))) + goto memerr; + + /* Set base CRL number: must be critical */ + + if (!X509_CRL_add1_ext_i2d(crl, NID_delta_crl, base->crl_number, 1, 0)) + goto memerr; + + /* + * Copy extensions across from newest CRL to delta: this will set CRL + * number to correct value too. + */ + + for (i = 0; i < X509_CRL_get_ext_count(newer); i++) { + X509_EXTENSION *ext; + ext = X509_CRL_get_ext(newer, i); + if (!X509_CRL_add_ext(crl, ext, -1)) + goto memerr; + } + + /* Go through revoked entries, copying as needed */ + + revs = X509_CRL_get_REVOKED(newer); + + for (j = 0; j < sk_X509_REVOKED_num(revs); j++) { + X509_REVOKED *rvn, *rvtmp; + rvn = sk_X509_REVOKED_value(revs, j); + /* + * Add only if not also in base. TODO: need something cleverer here + * for some more complex CRLs covering multiple CAs. + */ + if (!X509_CRL_get0_by_serial(base, &rvtmp, rvn->serialNumber)) { + rvtmp = X509_REVOKED_dup(rvn); + if (!rvtmp) + goto memerr; + if (!X509_CRL_add0_revoked(crl, rvtmp)) { + X509_REVOKED_free(rvtmp); + goto memerr; + } + } + } + /* TODO: optionally prune deleted entries */ + + if (skey && md && !X509_CRL_sign(crl, skey, md)) + goto memerr; + + return crl; + + memerr: + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + if (crl) + X509_CRL_free(crl); + return NULL; +} + +int X509_STORE_CTX_get_ex_new_index(long argl, void *argp, + CRYPTO_EX_unused * unused, + CRYPTO_EX_dup *dup_func, + CRYPTO_EX_free *free_func) +{ + /* + * This function is (usually) called only once, by + * SSL_get_ex_data_X509_STORE_CTX_idx (ssl/ssl_cert.c). + */ + int index; + if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp, + dup_func, free_func)) { + return -1; + } + return index; +} + +int X509_STORE_CTX_set_ex_data(X509_STORE_CTX *ctx, int idx, void *data) +{ + return CRYPTO_set_ex_data(&ctx->ex_data, idx, data); +} + +void *X509_STORE_CTX_get_ex_data(X509_STORE_CTX *ctx, int idx) +{ + return CRYPTO_get_ex_data(&ctx->ex_data, idx); +} + +int X509_STORE_CTX_get_error(X509_STORE_CTX *ctx) +{ + return ctx->error; +} + +void X509_STORE_CTX_set_error(X509_STORE_CTX *ctx, int err) +{ + ctx->error = err; +} + +int X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx) +{ + return ctx->error_depth; +} + +X509 *X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx) +{ + return ctx->current_cert; +} + +STACK_OF(X509) *X509_STORE_CTX_get_chain(X509_STORE_CTX *ctx) +{ + return ctx->chain; +} + +STACK_OF(X509) *X509_STORE_CTX_get1_chain(X509_STORE_CTX *ctx) +{ + if (!ctx->chain) + return NULL; + return X509_chain_up_ref(ctx->chain); +} + +X509 *X509_STORE_CTX_get0_current_issuer(X509_STORE_CTX *ctx) +{ + return ctx->current_issuer; +} + +X509_CRL *X509_STORE_CTX_get0_current_crl(X509_STORE_CTX *ctx) +{ + return ctx->current_crl; +} + +X509_STORE_CTX *X509_STORE_CTX_get0_parent_ctx(X509_STORE_CTX *ctx) +{ + return ctx->parent; +} + +void X509_STORE_CTX_set_cert(X509_STORE_CTX *ctx, X509 *x) +{ + ctx->cert = x; +} + +void X509_STORE_CTX_set_chain(X509_STORE_CTX *ctx, STACK_OF(X509) *sk) +{ + ctx->untrusted = sk; +} + +void X509_STORE_CTX_set0_crls(X509_STORE_CTX *ctx, STACK_OF(X509_CRL) *sk) +{ + ctx->crls = sk; +} + +int X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose) +{ + return X509_STORE_CTX_purpose_inherit(ctx, 0, purpose, 0); +} + +int X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust) +{ + return X509_STORE_CTX_purpose_inherit(ctx, 0, 0, trust); +} + +/* + * This function is used to set the X509_STORE_CTX purpose and trust values. + * This is intended to be used when another structure has its own trust and + * purpose values which (if set) will be inherited by the ctx. If they aren't + * set then we will usually have a default purpose in mind which should then + * be used to set the trust value. An example of this is SSL use: an SSL + * structure will have its own purpose and trust settings which the + * application can set: if they aren't set then we use the default of SSL + * client/server. + */ + +int X509_STORE_CTX_purpose_inherit(X509_STORE_CTX *ctx, int def_purpose, + int purpose, int trust) +{ + int idx; + /* If purpose not set use default */ + if (!purpose) + purpose = def_purpose; + /* If we have a purpose then check it is valid */ + if (purpose) { + X509_PURPOSE *ptmp; + idx = X509_PURPOSE_get_by_id(purpose); + if (idx == -1) { + OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_PURPOSE_ID); + return 0; + } + ptmp = X509_PURPOSE_get0(idx); + if (ptmp->trust == X509_TRUST_DEFAULT) { + idx = X509_PURPOSE_get_by_id(def_purpose); + if (idx == -1) { + OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_PURPOSE_ID); + return 0; + } + ptmp = X509_PURPOSE_get0(idx); + } + /* If trust not set then get from purpose default */ + if (!trust) + trust = ptmp->trust; + } + if (trust) { + idx = X509_TRUST_get_by_id(trust); + if (idx == -1) { + OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_TRUST_ID); + return 0; + } + } + + if (purpose && !ctx->param->purpose) + ctx->param->purpose = purpose; + if (trust && !ctx->param->trust) + ctx->param->trust = trust; + return 1; +} + +X509_STORE_CTX *X509_STORE_CTX_new(void) +{ + X509_STORE_CTX *ctx; + ctx = (X509_STORE_CTX *)OPENSSL_malloc(sizeof(X509_STORE_CTX)); + if (!ctx) { + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + return NULL; + } + memset(ctx, 0, sizeof(X509_STORE_CTX)); + return ctx; +} + +void X509_STORE_CTX_free(X509_STORE_CTX *ctx) +{ + if (ctx == NULL) { + return; + } + X509_STORE_CTX_cleanup(ctx); + OPENSSL_free(ctx); +} + +int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509, + STACK_OF(X509) *chain) +{ + int ret = 1; + + memset(ctx, 0, sizeof(X509_STORE_CTX)); + ctx->ctx = store; + ctx->cert = x509; + ctx->untrusted = chain; + + CRYPTO_new_ex_data(&ctx->ex_data); + + ctx->param = X509_VERIFY_PARAM_new(); + if (!ctx->param) + goto err; + + /* + * Inherit callbacks and flags from X509_STORE if not set use defaults. + */ + + if (store) + ret = X509_VERIFY_PARAM_inherit(ctx->param, store->param); + else + ctx->param->inh_flags |= X509_VP_FLAG_DEFAULT | X509_VP_FLAG_ONCE; + + if (store) { + ctx->verify_cb = store->verify_cb; + ctx->cleanup = store->cleanup; + } else + ctx->cleanup = 0; + + if (ret) + ret = X509_VERIFY_PARAM_inherit(ctx->param, + X509_VERIFY_PARAM_lookup("default")); + + if (ret == 0) + goto err; + + if (store && store->check_issued) + ctx->check_issued = store->check_issued; + else + ctx->check_issued = check_issued; + + if (store && store->get_issuer) + ctx->get_issuer = store->get_issuer; + else + ctx->get_issuer = X509_STORE_CTX_get1_issuer; + + if (store && store->verify_cb) + ctx->verify_cb = store->verify_cb; + else + ctx->verify_cb = null_callback; + + if (store && store->verify) + ctx->verify = store->verify; + else + ctx->verify = internal_verify; + + if (store && store->check_revocation) + ctx->check_revocation = store->check_revocation; + else + ctx->check_revocation = check_revocation; + + if (store && store->get_crl) + ctx->get_crl = store->get_crl; + else + ctx->get_crl = NULL; + + if (store && store->check_crl) + ctx->check_crl = store->check_crl; + else + ctx->check_crl = check_crl; + + if (store && store->cert_crl) + ctx->cert_crl = store->cert_crl; + else + ctx->cert_crl = cert_crl; + + if (store && store->lookup_certs) + ctx->lookup_certs = store->lookup_certs; + else + ctx->lookup_certs = X509_STORE_get1_certs; + + if (store && store->lookup_crls) + ctx->lookup_crls = store->lookup_crls; + else + ctx->lookup_crls = X509_STORE_get1_crls; + + ctx->check_policy = check_policy; + + return 1; + + err: + CRYPTO_free_ex_data(&g_ex_data_class, ctx, &ctx->ex_data); + if (ctx->param != NULL) { + X509_VERIFY_PARAM_free(ctx->param); + } + + memset(ctx, 0, sizeof(X509_STORE_CTX)); + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + return 0; +} + +/* + * Set alternative lookup method: just a STACK of trusted certificates. This + * avoids X509_STORE nastiness where it isn't needed. + */ + +void X509_STORE_CTX_trusted_stack(X509_STORE_CTX *ctx, STACK_OF(X509) *sk) +{ + ctx->other_ctx = sk; + ctx->get_issuer = get_issuer_sk; +} + +void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx) +{ + /* We need to be idempotent because, unfortunately, |X509_STORE_CTX_free| + * also calls this function. */ + if (ctx->cleanup != NULL) { + ctx->cleanup(ctx); + ctx->cleanup = NULL; + } + if (ctx->param != NULL) { + if (ctx->parent == NULL) + X509_VERIFY_PARAM_free(ctx->param); + ctx->param = NULL; + } + if (ctx->tree != NULL) { + X509_policy_tree_free(ctx->tree); + ctx->tree = NULL; + } + if (ctx->chain != NULL) { + sk_X509_pop_free(ctx->chain, X509_free); + ctx->chain = NULL; + } + CRYPTO_free_ex_data(&g_ex_data_class, ctx, &(ctx->ex_data)); + memset(&ctx->ex_data, 0, sizeof(CRYPTO_EX_DATA)); +} + +void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth) +{ + X509_VERIFY_PARAM_set_depth(ctx->param, depth); +} + +void X509_STORE_CTX_set_flags(X509_STORE_CTX *ctx, unsigned long flags) +{ + X509_VERIFY_PARAM_set_flags(ctx->param, flags); +} + +void X509_STORE_CTX_set_time(X509_STORE_CTX *ctx, unsigned long flags, + time_t t) +{ + X509_VERIFY_PARAM_set_time(ctx->param, t); +} + +void X509_STORE_CTX_set_verify_cb(X509_STORE_CTX *ctx, + int (*verify_cb) (int, X509_STORE_CTX *)) +{ + ctx->verify_cb = verify_cb; +} + +X509_POLICY_TREE *X509_STORE_CTX_get0_policy_tree(X509_STORE_CTX *ctx) +{ + return ctx->tree; +} + +int X509_STORE_CTX_get_explicit_policy(X509_STORE_CTX *ctx) +{ + return ctx->explicit_policy; +} + +int X509_STORE_CTX_set_default(X509_STORE_CTX *ctx, const char *name) +{ + const X509_VERIFY_PARAM *param; + param = X509_VERIFY_PARAM_lookup(name); + if (!param) + return 0; + return X509_VERIFY_PARAM_inherit(ctx->param, param); +} + +X509_VERIFY_PARAM *X509_STORE_CTX_get0_param(X509_STORE_CTX *ctx) +{ + return ctx->param; +} + +void X509_STORE_CTX_set0_param(X509_STORE_CTX *ctx, X509_VERIFY_PARAM *param) +{ + if (ctx->param) + X509_VERIFY_PARAM_free(ctx->param); + ctx->param = param; +} + +IMPLEMENT_ASN1_SET_OF(X509) + +IMPLEMENT_ASN1_SET_OF(X509_ATTRIBUTE) diff --git a/external/boringssl/crypto/x509/x509_vpm.c b/external/boringssl/crypto/x509/x509_vpm.c new file mode 100644 index 0000000000..02a589888f --- /dev/null +++ b/external/boringssl/crypto/x509/x509_vpm.c @@ -0,0 +1,636 @@ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project + * 2004. + */ +/* ==================================================================== + * Copyright (c) 2004 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "vpm_int.h" + +/* X509_VERIFY_PARAM functions */ + +#define SET_HOST 0 +#define ADD_HOST 1 + +static char *str_copy(char *s) +{ + return OPENSSL_strdup(s); +} + +static void str_free(char *s) +{ + OPENSSL_free(s); +} + +#define string_stack_free(sk) sk_OPENSSL_STRING_pop_free(sk, str_free) + +static int int_x509_param_set_hosts(X509_VERIFY_PARAM_ID *id, int mode, + const char *name, size_t namelen) +{ + char *copy; + + /* + * Refuse names with embedded NUL bytes. + * XXX: Do we need to push an error onto the error stack? + */ + if (name && memchr(name, '\0', namelen)) + return 0; + + if (mode == SET_HOST && id->hosts) { + string_stack_free(id->hosts); + id->hosts = NULL; + } + if (name == NULL) + return 1; + + copy = BUF_strndup(name, namelen); + if (copy == NULL) + return 0; + + if (id->hosts == NULL && + (id->hosts = sk_OPENSSL_STRING_new_null()) == NULL) { + OPENSSL_free(copy); + return 0; + } + + if (!sk_OPENSSL_STRING_push(id->hosts, copy)) { + OPENSSL_free(copy); + if (sk_OPENSSL_STRING_num(id->hosts) == 0) { + sk_OPENSSL_STRING_free(id->hosts); + id->hosts = NULL; + } + return 0; + } + + return 1; +} + +static void x509_verify_param_zero(X509_VERIFY_PARAM *param) +{ + X509_VERIFY_PARAM_ID *paramid; + if (!param) + return; + param->name = NULL; + param->purpose = 0; + param->trust = 0; + /* + * param->inh_flags = X509_VP_FLAG_DEFAULT; + */ + param->inh_flags = 0; + param->flags = 0; + param->depth = -1; + if (param->policies) { + sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free); + param->policies = NULL; + } + paramid = param->id; + if (paramid->hosts) { + string_stack_free(paramid->hosts); + paramid->hosts = NULL; + } + if (paramid->peername) { + OPENSSL_free(paramid->peername); + paramid->peername = NULL; + } + if (paramid->email) { + OPENSSL_free(paramid->email); + paramid->email = NULL; + paramid->emaillen = 0; + } + if (paramid->ip) { + OPENSSL_free(paramid->ip); + paramid->ip = NULL; + paramid->iplen = 0; + } + +} + +X509_VERIFY_PARAM *X509_VERIFY_PARAM_new(void) +{ + X509_VERIFY_PARAM *param; + X509_VERIFY_PARAM_ID *paramid; + param = OPENSSL_malloc(sizeof(X509_VERIFY_PARAM)); + if (!param) + return NULL; + paramid = OPENSSL_malloc(sizeof(X509_VERIFY_PARAM_ID)); + if (!paramid) { + OPENSSL_free(param); + return NULL; + } + memset(param, 0, sizeof(X509_VERIFY_PARAM)); + memset(paramid, 0, sizeof(X509_VERIFY_PARAM_ID)); + param->id = paramid; + x509_verify_param_zero(param); + return param; +} + +void X509_VERIFY_PARAM_free(X509_VERIFY_PARAM *param) +{ + if (param == NULL) + return; + x509_verify_param_zero(param); + OPENSSL_free(param->id); + OPENSSL_free(param); +} + +/* + * This function determines how parameters are "inherited" from one structure + * to another. There are several different ways this can happen. 1. If a + * child structure needs to have its values initialized from a parent they are + * simply copied across. For example SSL_CTX copied to SSL. 2. If the + * structure should take on values only if they are currently unset. For + * example the values in an SSL structure will take appropriate value for SSL + * servers or clients but only if the application has not set new ones. The + * "inh_flags" field determines how this function behaves. Normally any + * values which are set in the default are not copied from the destination and + * verify flags are ORed together. If X509_VP_FLAG_DEFAULT is set then + * anything set in the source is copied to the destination. Effectively the + * values in "to" become default values which will be used only if nothing new + * is set in "from". If X509_VP_FLAG_OVERWRITE is set then all value are + * copied across whether they are set or not. Flags is still Ored though. If + * X509_VP_FLAG_RESET_FLAGS is set then the flags value is copied instead of + * ORed. If X509_VP_FLAG_LOCKED is set then no values are copied. If + * X509_VP_FLAG_ONCE is set then the current inh_flags setting is zeroed after + * the next call. + */ + +/* Macro to test if a field should be copied from src to dest */ + +#define test_x509_verify_param_copy(field, def) \ + (to_overwrite || \ + ((src->field != def) && (to_default || (dest->field == def)))) + +/* As above but for ID fields */ + +#define test_x509_verify_param_copy_id(idf, def) \ + test_x509_verify_param_copy(id->idf, def) + +/* Macro to test and copy a field if necessary */ + +#define x509_verify_param_copy(field, def) \ + if (test_x509_verify_param_copy(field, def)) \ + dest->field = src->field + +int X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *dest, + const X509_VERIFY_PARAM *src) +{ + unsigned long inh_flags; + int to_default, to_overwrite; + X509_VERIFY_PARAM_ID *id; + if (!src) + return 1; + id = src->id; + inh_flags = dest->inh_flags | src->inh_flags; + + if (inh_flags & X509_VP_FLAG_ONCE) + dest->inh_flags = 0; + + if (inh_flags & X509_VP_FLAG_LOCKED) + return 1; + + if (inh_flags & X509_VP_FLAG_DEFAULT) + to_default = 1; + else + to_default = 0; + + if (inh_flags & X509_VP_FLAG_OVERWRITE) + to_overwrite = 1; + else + to_overwrite = 0; + + x509_verify_param_copy(purpose, 0); + x509_verify_param_copy(trust, 0); + x509_verify_param_copy(depth, -1); + + /* If overwrite or check time not set, copy across */ + + if (to_overwrite || !(dest->flags & X509_V_FLAG_USE_CHECK_TIME)) { + dest->check_time = src->check_time; + dest->flags &= ~X509_V_FLAG_USE_CHECK_TIME; + /* Don't need to copy flag: that is done below */ + } + + if (inh_flags & X509_VP_FLAG_RESET_FLAGS) + dest->flags = 0; + + dest->flags |= src->flags; + + if (test_x509_verify_param_copy(policies, NULL)) { + if (!X509_VERIFY_PARAM_set1_policies(dest, src->policies)) + return 0; + } + + /* Copy the host flags if and only if we're copying the host list */ + if (test_x509_verify_param_copy_id(hosts, NULL)) { + if (dest->id->hosts) { + string_stack_free(dest->id->hosts); + dest->id->hosts = NULL; + } + if (id->hosts) { + dest->id->hosts = + sk_OPENSSL_STRING_deep_copy(id->hosts, str_copy, str_free); + if (dest->id->hosts == NULL) + return 0; + dest->id->hostflags = id->hostflags; + } + } + + if (test_x509_verify_param_copy_id(email, NULL)) { + if (!X509_VERIFY_PARAM_set1_email(dest, id->email, id->emaillen)) + return 0; + } + + if (test_x509_verify_param_copy_id(ip, NULL)) { + if (!X509_VERIFY_PARAM_set1_ip(dest, id->ip, id->iplen)) + return 0; + } + + return 1; +} + +int X509_VERIFY_PARAM_set1(X509_VERIFY_PARAM *to, + const X509_VERIFY_PARAM *from) +{ + unsigned long save_flags = to->inh_flags; + int ret; + to->inh_flags |= X509_VP_FLAG_DEFAULT; + ret = X509_VERIFY_PARAM_inherit(to, from); + to->inh_flags = save_flags; + return ret; +} + +static int int_x509_param_set1(char **pdest, size_t *pdestlen, + const char *src, size_t srclen) +{ + void *tmp; + if (src) { + if (srclen == 0) { + tmp = BUF_strdup(src); + srclen = strlen(src); + } else + tmp = BUF_memdup(src, srclen); + if (!tmp) + return 0; + } else { + tmp = NULL; + srclen = 0; + } + if (*pdest) + OPENSSL_free(*pdest); + *pdest = tmp; + if (pdestlen) + *pdestlen = srclen; + return 1; +} + +int X509_VERIFY_PARAM_set1_name(X509_VERIFY_PARAM *param, const char *name) +{ + if (param->name) + OPENSSL_free(param->name); + param->name = BUF_strdup(name); + if (param->name) + return 1; + return 0; +} + +int X509_VERIFY_PARAM_set_flags(X509_VERIFY_PARAM *param, unsigned long flags) +{ + param->flags |= flags; + if (flags & X509_V_FLAG_POLICY_MASK) + param->flags |= X509_V_FLAG_POLICY_CHECK; + return 1; +} + +int X509_VERIFY_PARAM_clear_flags(X509_VERIFY_PARAM *param, + unsigned long flags) +{ + param->flags &= ~flags; + return 1; +} + +unsigned long X509_VERIFY_PARAM_get_flags(X509_VERIFY_PARAM *param) +{ + return param->flags; +} + +int X509_VERIFY_PARAM_set_purpose(X509_VERIFY_PARAM *param, int purpose) +{ + return X509_PURPOSE_set(¶m->purpose, purpose); +} + +int X509_VERIFY_PARAM_set_trust(X509_VERIFY_PARAM *param, int trust) +{ + return X509_TRUST_set(¶m->trust, trust); +} + +void X509_VERIFY_PARAM_set_depth(X509_VERIFY_PARAM *param, int depth) +{ + param->depth = depth; +} + +void X509_VERIFY_PARAM_set_time(X509_VERIFY_PARAM *param, time_t t) +{ + param->check_time = t; + param->flags |= X509_V_FLAG_USE_CHECK_TIME; +} + +int X509_VERIFY_PARAM_add0_policy(X509_VERIFY_PARAM *param, + ASN1_OBJECT *policy) +{ + if (!param->policies) { + param->policies = sk_ASN1_OBJECT_new_null(); + if (!param->policies) + return 0; + } + if (!sk_ASN1_OBJECT_push(param->policies, policy)) + return 0; + return 1; +} + +int X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param, + STACK_OF(ASN1_OBJECT) *policies) +{ + size_t i; + ASN1_OBJECT *oid, *doid; + if (!param) + return 0; + if (param->policies) + sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free); + + if (!policies) { + param->policies = NULL; + return 1; + } + + param->policies = sk_ASN1_OBJECT_new_null(); + if (!param->policies) + return 0; + + for (i = 0; i < sk_ASN1_OBJECT_num(policies); i++) { + oid = sk_ASN1_OBJECT_value(policies, i); + doid = OBJ_dup(oid); + if (!doid) + return 0; + if (!sk_ASN1_OBJECT_push(param->policies, doid)) { + ASN1_OBJECT_free(doid); + return 0; + } + } + param->flags |= X509_V_FLAG_POLICY_CHECK; + return 1; +} + +int X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param, + const char *name, size_t namelen) +{ + return int_x509_param_set_hosts(param->id, SET_HOST, name, namelen); +} + +int X509_VERIFY_PARAM_add1_host(X509_VERIFY_PARAM *param, + const char *name, size_t namelen) +{ + return int_x509_param_set_hosts(param->id, ADD_HOST, name, namelen); +} + +void X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *param, + unsigned int flags) +{ + param->id->hostflags = flags; +} + +char *X509_VERIFY_PARAM_get0_peername(X509_VERIFY_PARAM *param) +{ + return param->id->peername; +} + +int X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param, + const char *email, size_t emaillen) +{ + return int_x509_param_set1(¶m->id->email, ¶m->id->emaillen, + email, emaillen); +} + +int X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param, + const unsigned char *ip, size_t iplen) +{ + if (iplen != 0 && iplen != 4 && iplen != 16) + return 0; + return int_x509_param_set1((char **)¶m->id->ip, ¶m->id->iplen, + (char *)ip, iplen); +} + +int X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM *param, const char *ipasc) +{ + unsigned char ipout[16]; + size_t iplen; + + iplen = (size_t)a2i_ipadd(ipout, ipasc); + if (iplen == 0) + return 0; + return X509_VERIFY_PARAM_set1_ip(param, ipout, iplen); +} + +int X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM *param) +{ + return param->depth; +} + +const char *X509_VERIFY_PARAM_get0_name(const X509_VERIFY_PARAM *param) +{ + return param->name; +} + +static const X509_VERIFY_PARAM_ID _empty_id = + { NULL, 0U, NULL, NULL, 0, NULL, 0 }; + +#define vpm_empty_id (X509_VERIFY_PARAM_ID *)&_empty_id + +/* + * Default verify parameters: these are used for various applications and can + * be overridden by the user specified table. NB: the 'name' field *must* be + * in alphabetical order because it will be searched using OBJ_search. + */ + +static const X509_VERIFY_PARAM default_table[] = { + { + (char *)"default", /* X509 default parameters */ + 0, /* Check time */ + 0, /* internal flags */ + 0, /* flags */ + 0, /* purpose */ + 0, /* trust */ + 100, /* depth */ + NULL, /* policies */ + vpm_empty_id}, + { + (char *)"pkcs7", /* S/MIME sign parameters */ + 0, /* Check time */ + 0, /* internal flags */ + 0, /* flags */ + X509_PURPOSE_SMIME_SIGN, /* purpose */ + X509_TRUST_EMAIL, /* trust */ + -1, /* depth */ + NULL, /* policies */ + vpm_empty_id}, + { + (char *)"smime_sign", /* S/MIME sign parameters */ + 0, /* Check time */ + 0, /* internal flags */ + 0, /* flags */ + X509_PURPOSE_SMIME_SIGN, /* purpose */ + X509_TRUST_EMAIL, /* trust */ + -1, /* depth */ + NULL, /* policies */ + vpm_empty_id}, + { + (char *)"ssl_client", /* SSL/TLS client parameters */ + 0, /* Check time */ + 0, /* internal flags */ + 0, /* flags */ + X509_PURPOSE_SSL_CLIENT, /* purpose */ + X509_TRUST_SSL_CLIENT, /* trust */ + -1, /* depth */ + NULL, /* policies */ + vpm_empty_id}, + { + (char *)"ssl_server", /* SSL/TLS server parameters */ + 0, /* Check time */ + 0, /* internal flags */ + 0, /* flags */ + X509_PURPOSE_SSL_SERVER, /* purpose */ + X509_TRUST_SSL_SERVER, /* trust */ + -1, /* depth */ + NULL, /* policies */ + vpm_empty_id} +}; + +static STACK_OF(X509_VERIFY_PARAM) *param_table = NULL; + +static int param_cmp(const X509_VERIFY_PARAM **a, const X509_VERIFY_PARAM **b) +{ + return strcmp((*a)->name, (*b)->name); +} + +int X509_VERIFY_PARAM_add0_table(X509_VERIFY_PARAM *param) +{ + X509_VERIFY_PARAM *ptmp; + if (!param_table) { + param_table = sk_X509_VERIFY_PARAM_new(param_cmp); + if (!param_table) + return 0; + } else { + size_t idx; + + if (sk_X509_VERIFY_PARAM_find(param_table, &idx, param)) { + ptmp = sk_X509_VERIFY_PARAM_value(param_table, idx); + X509_VERIFY_PARAM_free(ptmp); + (void)sk_X509_VERIFY_PARAM_delete(param_table, idx); + } + } + if (!sk_X509_VERIFY_PARAM_push(param_table, param)) + return 0; + return 1; +} + +int X509_VERIFY_PARAM_get_count(void) +{ + int num = sizeof(default_table) / sizeof(X509_VERIFY_PARAM); + if (param_table) + num += sk_X509_VERIFY_PARAM_num(param_table); + return num; +} + +const X509_VERIFY_PARAM *X509_VERIFY_PARAM_get0(int id) +{ + int num = sizeof(default_table) / sizeof(X509_VERIFY_PARAM); + if (id < num) + return default_table + id; + return sk_X509_VERIFY_PARAM_value(param_table, id - num); +} + +const X509_VERIFY_PARAM *X509_VERIFY_PARAM_lookup(const char *name) +{ + X509_VERIFY_PARAM pm; + unsigned i, limit; + + pm.name = (char *)name; + if (param_table) { + size_t idx; + if (sk_X509_VERIFY_PARAM_find(param_table, &idx, &pm)) + return sk_X509_VERIFY_PARAM_value(param_table, idx); + } + + limit = sizeof(default_table) / sizeof(X509_VERIFY_PARAM); + for (i = 0; i < limit; i++) { + if (strcmp(default_table[i].name, name) == 0) { + return &default_table[i]; + } + } + return NULL; +} + +void X509_VERIFY_PARAM_table_cleanup(void) +{ + if (param_table) + sk_X509_VERIFY_PARAM_pop_free(param_table, X509_VERIFY_PARAM_free); + param_table = NULL; +} diff --git a/external/boringssl/crypto/x509/x509cset.c b/external/boringssl/crypto/x509/x509cset.c new file mode 100644 index 0000000000..a292710ee8 --- /dev/null +++ b/external/boringssl/crypto/x509/x509cset.c @@ -0,0 +1,169 @@ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project + * 2001. + */ +/* ==================================================================== + * Copyright (c) 2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include +#include +#include +#include + +#include "../internal.h" + +int X509_CRL_set_version(X509_CRL *x, long version) +{ + if (x == NULL) + return (0); + if (x->crl->version == NULL) { + if ((x->crl->version = M_ASN1_INTEGER_new()) == NULL) + return (0); + } + return (ASN1_INTEGER_set(x->crl->version, version)); +} + +int X509_CRL_set_issuer_name(X509_CRL *x, X509_NAME *name) +{ + if ((x == NULL) || (x->crl == NULL)) + return (0); + return (X509_NAME_set(&x->crl->issuer, name)); +} + +int X509_CRL_set_lastUpdate(X509_CRL *x, const ASN1_TIME *tm) +{ + ASN1_TIME *in; + + if (x == NULL) + return (0); + in = x->crl->lastUpdate; + if (in != tm) { + in = M_ASN1_TIME_dup(tm); + if (in != NULL) { + M_ASN1_TIME_free(x->crl->lastUpdate); + x->crl->lastUpdate = in; + } + } + return (in != NULL); +} + +int X509_CRL_set_nextUpdate(X509_CRL *x, const ASN1_TIME *tm) +{ + ASN1_TIME *in; + + if (x == NULL) + return (0); + in = x->crl->nextUpdate; + if (in != tm) { + in = M_ASN1_TIME_dup(tm); + if (in != NULL) { + M_ASN1_TIME_free(x->crl->nextUpdate); + x->crl->nextUpdate = in; + } + } + return (in != NULL); +} + +int X509_CRL_sort(X509_CRL *c) +{ + size_t i; + X509_REVOKED *r; + /* + * sort the data so it will be written in serial number order + */ + sk_X509_REVOKED_sort(c->crl->revoked); + for (i = 0; i < sk_X509_REVOKED_num(c->crl->revoked); i++) { + r = sk_X509_REVOKED_value(c->crl->revoked, i); + r->sequence = i; + } + c->crl->enc.modified = 1; + return 1; +} + +void X509_CRL_up_ref(X509_CRL *crl) +{ + CRYPTO_refcount_inc(&crl->references); +} + +int X509_REVOKED_set_revocationDate(X509_REVOKED *x, ASN1_TIME *tm) +{ + ASN1_TIME *in; + + if (x == NULL) + return (0); + in = x->revocationDate; + if (in != tm) { + in = M_ASN1_TIME_dup(tm); + if (in != NULL) { + M_ASN1_TIME_free(x->revocationDate); + x->revocationDate = in; + } + } + return (in != NULL); +} + +int X509_REVOKED_set_serialNumber(X509_REVOKED *x, ASN1_INTEGER *serial) +{ + ASN1_INTEGER *in; + + if (x == NULL) + return (0); + in = x->serialNumber; + if (in != serial) { + in = M_ASN1_INTEGER_dup(serial); + if (in != NULL) { + M_ASN1_INTEGER_free(x->serialNumber); + x->serialNumber = in; + } + } + return (in != NULL); +} diff --git a/external/boringssl/crypto/x509/x509name.c b/external/boringssl/crypto/x509/x509name.c new file mode 100644 index 0000000000..050e16a84e --- /dev/null +++ b/external/boringssl/crypto/x509/x509name.c @@ -0,0 +1,386 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include +#include +#include +#include +#include + +int X509_NAME_get_text_by_NID(X509_NAME *name, int nid, char *buf, int len) +{ + const ASN1_OBJECT *obj; + + obj = OBJ_nid2obj(nid); + if (obj == NULL) + return (-1); + return (X509_NAME_get_text_by_OBJ(name, obj, buf, len)); +} + +int X509_NAME_get_text_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj, + char *buf, int len) +{ + int i; + ASN1_STRING *data; + + i = X509_NAME_get_index_by_OBJ(name, obj, -1); + if (i < 0) + return (-1); + data = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, i)); + i = (data->length > (len - 1)) ? (len - 1) : data->length; + if (buf == NULL) + return (data->length); + memcpy(buf, data->data, i); + buf[i] = '\0'; + return (i); +} + +int X509_NAME_entry_count(X509_NAME *name) +{ + if (name == NULL) + return (0); + return (sk_X509_NAME_ENTRY_num(name->entries)); +} + +int X509_NAME_get_index_by_NID(X509_NAME *name, int nid, int lastpos) +{ + const ASN1_OBJECT *obj; + + obj = OBJ_nid2obj(nid); + if (obj == NULL) + return (-2); + return (X509_NAME_get_index_by_OBJ(name, obj, lastpos)); +} + +/* NOTE: you should be passsing -1, not 0 as lastpos */ +int X509_NAME_get_index_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj, + int lastpos) +{ + int n; + X509_NAME_ENTRY *ne; + STACK_OF(X509_NAME_ENTRY) *sk; + + if (name == NULL) + return (-1); + if (lastpos < 0) + lastpos = -1; + sk = name->entries; + n = sk_X509_NAME_ENTRY_num(sk); + for (lastpos++; lastpos < n; lastpos++) { + ne = sk_X509_NAME_ENTRY_value(sk, lastpos); + if (OBJ_cmp(ne->object, obj) == 0) + return (lastpos); + } + return (-1); +} + +X509_NAME_ENTRY *X509_NAME_get_entry(X509_NAME *name, int loc) +{ + if (name == NULL || loc < 0 + || sk_X509_NAME_ENTRY_num(name->entries) <= (size_t)loc) + return (NULL); + else + return (sk_X509_NAME_ENTRY_value(name->entries, loc)); +} + +X509_NAME_ENTRY *X509_NAME_delete_entry(X509_NAME *name, int loc) +{ + X509_NAME_ENTRY *ret; + int i, n, set_prev, set_next; + STACK_OF(X509_NAME_ENTRY) *sk; + + if (name == NULL || loc < 0 + || sk_X509_NAME_ENTRY_num(name->entries) <= (size_t)loc) + return (NULL); + sk = name->entries; + ret = sk_X509_NAME_ENTRY_delete(sk, loc); + n = sk_X509_NAME_ENTRY_num(sk); + name->modified = 1; + if (loc == n) + return (ret); + + /* else we need to fixup the set field */ + if (loc != 0) + set_prev = (sk_X509_NAME_ENTRY_value(sk, loc - 1))->set; + else + set_prev = ret->set - 1; + set_next = sk_X509_NAME_ENTRY_value(sk, loc)->set; + + /* + * set_prev is the previous set set is the current set set_next is the + * following prev 1 1 1 1 1 1 1 1 set 1 1 2 2 next 1 1 2 2 2 2 3 2 so + * basically only if prev and next differ by 2, then re-number down by 1 + */ + if (set_prev + 1 < set_next) + for (i = loc; i < n; i++) + sk_X509_NAME_ENTRY_value(sk, i)->set--; + return (ret); +} + +int X509_NAME_add_entry_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj, int type, + unsigned char *bytes, int len, int loc, + int set) +{ + X509_NAME_ENTRY *ne; + int ret; + ne = X509_NAME_ENTRY_create_by_OBJ(NULL, obj, type, bytes, len); + if (!ne) + return 0; + ret = X509_NAME_add_entry(name, ne, loc, set); + X509_NAME_ENTRY_free(ne); + return ret; +} + +int X509_NAME_add_entry_by_NID(X509_NAME *name, int nid, int type, + unsigned char *bytes, int len, int loc, + int set) +{ + X509_NAME_ENTRY *ne; + int ret; + ne = X509_NAME_ENTRY_create_by_NID(NULL, nid, type, bytes, len); + if (!ne) + return 0; + ret = X509_NAME_add_entry(name, ne, loc, set); + X509_NAME_ENTRY_free(ne); + return ret; +} + +int X509_NAME_add_entry_by_txt(X509_NAME *name, const char *field, int type, + const unsigned char *bytes, int len, int loc, + int set) +{ + X509_NAME_ENTRY *ne; + int ret; + ne = X509_NAME_ENTRY_create_by_txt(NULL, field, type, bytes, len); + if (!ne) + return 0; + ret = X509_NAME_add_entry(name, ne, loc, set); + X509_NAME_ENTRY_free(ne); + return ret; +} + +/* + * if set is -1, append to previous set, 0 'a new one', and 1, prepend to the + * guy we are about to stomp on. + */ +int X509_NAME_add_entry(X509_NAME *name, X509_NAME_ENTRY *ne, int loc, + int set) +{ + X509_NAME_ENTRY *new_name = NULL; + int n, i, inc; + STACK_OF(X509_NAME_ENTRY) *sk; + + if (name == NULL) + return (0); + sk = name->entries; + n = sk_X509_NAME_ENTRY_num(sk); + if (loc > n) + loc = n; + else if (loc < 0) + loc = n; + + name->modified = 1; + + if (set == -1) { + if (loc == 0) { + set = 0; + inc = 1; + } else { + set = sk_X509_NAME_ENTRY_value(sk, loc - 1)->set; + inc = 0; + } + } else { /* if (set >= 0) */ + + if (loc >= n) { + if (loc != 0) + set = sk_X509_NAME_ENTRY_value(sk, loc - 1)->set + 1; + else + set = 0; + } else + set = sk_X509_NAME_ENTRY_value(sk, loc)->set; + inc = (set == 0) ? 1 : 0; + } + + if ((new_name = X509_NAME_ENTRY_dup(ne)) == NULL) + goto err; + new_name->set = set; + if (!sk_X509_NAME_ENTRY_insert(sk, new_name, loc)) { + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + goto err; + } + if (inc) { + n = sk_X509_NAME_ENTRY_num(sk); + for (i = loc + 1; i < n; i++) + sk_X509_NAME_ENTRY_value(sk, i - 1)->set += 1; + } + return (1); + err: + if (new_name != NULL) + X509_NAME_ENTRY_free(new_name); + return (0); +} + +X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_txt(X509_NAME_ENTRY **ne, + const char *field, int type, + const unsigned char *bytes, + int len) +{ + ASN1_OBJECT *obj; + X509_NAME_ENTRY *nentry; + + obj = OBJ_txt2obj(field, 0); + if (obj == NULL) { + OPENSSL_PUT_ERROR(X509, X509_R_INVALID_FIELD_NAME); + ERR_add_error_data(2, "name=", field); + return (NULL); + } + nentry = X509_NAME_ENTRY_create_by_OBJ(ne, obj, type, bytes, len); + ASN1_OBJECT_free(obj); + return nentry; +} + +X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_NID(X509_NAME_ENTRY **ne, int nid, + int type, unsigned char *bytes, + int len) +{ + const ASN1_OBJECT *obj = OBJ_nid2obj(nid); + if (obj == NULL) { + OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_NID); + return NULL; + } + return X509_NAME_ENTRY_create_by_OBJ(ne, obj, type, bytes, len); +} + +X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_OBJ(X509_NAME_ENTRY **ne, + const ASN1_OBJECT *obj, + int type, + const unsigned char *bytes, + int len) +{ + X509_NAME_ENTRY *ret; + + if ((ne == NULL) || (*ne == NULL)) { + if ((ret = X509_NAME_ENTRY_new()) == NULL) + return (NULL); + } else + ret = *ne; + + if (!X509_NAME_ENTRY_set_object(ret, obj)) + goto err; + if (!X509_NAME_ENTRY_set_data(ret, type, bytes, len)) + goto err; + + if ((ne != NULL) && (*ne == NULL)) + *ne = ret; + return (ret); + err: + if ((ne == NULL) || (ret != *ne)) + X509_NAME_ENTRY_free(ret); + return (NULL); +} + +int X509_NAME_ENTRY_set_object(X509_NAME_ENTRY *ne, const ASN1_OBJECT *obj) +{ + if ((ne == NULL) || (obj == NULL)) { + OPENSSL_PUT_ERROR(X509, ERR_R_PASSED_NULL_PARAMETER); + return (0); + } + ASN1_OBJECT_free(ne->object); + ne->object = OBJ_dup(obj); + return ((ne->object == NULL) ? 0 : 1); +} + +int X509_NAME_ENTRY_set_data(X509_NAME_ENTRY *ne, int type, + const unsigned char *bytes, int len) +{ + int i; + + if ((ne == NULL) || ((bytes == NULL) && (len != 0))) + return (0); + if ((type > 0) && (type & MBSTRING_FLAG)) + return ASN1_STRING_set_by_NID(&ne->value, bytes, + len, type, + OBJ_obj2nid(ne->object)) ? 1 : 0; + if (len < 0) + len = strlen((const char *)bytes); + i = ASN1_STRING_set(ne->value, bytes, len); + if (!i) + return (0); + if (type != V_ASN1_UNDEF) { + if (type == V_ASN1_APP_CHOOSE) + ne->value->type = ASN1_PRINTABLE_type(bytes, len); + else + ne->value->type = type; + } + return (1); +} + +ASN1_OBJECT *X509_NAME_ENTRY_get_object(X509_NAME_ENTRY *ne) +{ + if (ne == NULL) + return (NULL); + return (ne->object); +} + +ASN1_STRING *X509_NAME_ENTRY_get_data(X509_NAME_ENTRY *ne) +{ + if (ne == NULL) + return (NULL); + return (ne->value); +} diff --git a/external/boringssl/crypto/x509/x509rset.c b/external/boringssl/crypto/x509/x509rset.c new file mode 100644 index 0000000000..c4e6683dea --- /dev/null +++ b/external/boringssl/crypto/x509/x509rset.c @@ -0,0 +1,81 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include +#include +#include +#include + +int X509_REQ_set_version(X509_REQ *x, long version) +{ + if (x == NULL) + return (0); + return (ASN1_INTEGER_set(x->req_info->version, version)); +} + +int X509_REQ_set_subject_name(X509_REQ *x, X509_NAME *name) +{ + if ((x == NULL) || (x->req_info == NULL)) + return (0); + return (X509_NAME_set(&x->req_info->subject, name)); +} + +int X509_REQ_set_pubkey(X509_REQ *x, EVP_PKEY *pkey) +{ + if ((x == NULL) || (x->req_info == NULL)) + return (0); + return (X509_PUBKEY_set(&x->req_info->pubkey, pkey)); +} diff --git a/external/boringssl/crypto/x509/x509spki.c b/external/boringssl/crypto/x509/x509spki.c new file mode 100644 index 0000000000..4a9b95e769 --- /dev/null +++ b/external/boringssl/crypto/x509/x509spki.c @@ -0,0 +1,137 @@ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project + * 1999. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include +#include +#include + +int NETSCAPE_SPKI_set_pubkey(NETSCAPE_SPKI *x, EVP_PKEY *pkey) +{ + if ((x == NULL) || (x->spkac == NULL)) + return (0); + return (X509_PUBKEY_set(&(x->spkac->pubkey), pkey)); +} + +EVP_PKEY *NETSCAPE_SPKI_get_pubkey(NETSCAPE_SPKI *x) +{ + if ((x == NULL) || (x->spkac == NULL)) + return (NULL); + return (X509_PUBKEY_get(x->spkac->pubkey)); +} + +/* Load a Netscape SPKI from a base64 encoded string */ + +NETSCAPE_SPKI *NETSCAPE_SPKI_b64_decode(const char *str, int len) +{ + unsigned char *spki_der; + const unsigned char *p; + size_t spki_len; + NETSCAPE_SPKI *spki; + if (len <= 0) + len = strlen(str); + if (!EVP_DecodedLength(&spki_len, len)) { + OPENSSL_PUT_ERROR(X509, X509_R_BASE64_DECODE_ERROR); + return NULL; + } + if (!(spki_der = OPENSSL_malloc(spki_len))) { + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + return NULL; + } + if (!EVP_DecodeBase64 + (spki_der, &spki_len, spki_len, (const uint8_t *)str, len)) { + OPENSSL_PUT_ERROR(X509, X509_R_BASE64_DECODE_ERROR); + OPENSSL_free(spki_der); + return NULL; + } + p = spki_der; + spki = d2i_NETSCAPE_SPKI(NULL, &p, spki_len); + OPENSSL_free(spki_der); + return spki; +} + +/* Generate a base64 encoded string from an SPKI */ + +char *NETSCAPE_SPKI_b64_encode(NETSCAPE_SPKI *spki) +{ + unsigned char *der_spki, *p; + char *b64_str; + size_t b64_len; + int der_len; + der_len = i2d_NETSCAPE_SPKI(spki, NULL); + if (!EVP_EncodedLength(&b64_len, der_len)) { + OPENSSL_PUT_ERROR(X509, ERR_R_OVERFLOW); + return NULL; + } + der_spki = OPENSSL_malloc(der_len); + if (der_spki == NULL) { + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + return NULL; + } + b64_str = OPENSSL_malloc(b64_len); + if (b64_str == NULL) { + OPENSSL_free(der_spki); + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + return NULL; + } + p = der_spki; + i2d_NETSCAPE_SPKI(spki, &p); + EVP_EncodeBlock((unsigned char *)b64_str, der_spki, der_len); + OPENSSL_free(der_spki); + return b64_str; +} diff --git a/external/boringssl/crypto/x509/x509type.c b/external/boringssl/crypto/x509/x509type.c new file mode 100644 index 0000000000..d4f5a4dc35 --- /dev/null +++ b/external/boringssl/crypto/x509/x509type.c @@ -0,0 +1,126 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include +#include +#include + +int X509_certificate_type(X509 *x, EVP_PKEY *pkey) +{ + EVP_PKEY *pk; + int ret = 0, i; + + if (x == NULL) + return (0); + + if (pkey == NULL) + pk = X509_get_pubkey(x); + else + pk = pkey; + + if (pk == NULL) + return (0); + + switch (pk->type) { + case EVP_PKEY_RSA: + ret = EVP_PK_RSA | EVP_PKT_SIGN; +/* if (!sign only extension) */ + ret |= EVP_PKT_ENC; + break; + case EVP_PKEY_DSA: + ret = EVP_PK_DSA | EVP_PKT_SIGN; + break; + case EVP_PKEY_EC: + ret = EVP_PK_EC | EVP_PKT_SIGN | EVP_PKT_EXCH; + break; + case EVP_PKEY_DH: + ret = EVP_PK_DH | EVP_PKT_EXCH; + break; + case NID_id_GostR3410_94: + case NID_id_GostR3410_2001: + ret = EVP_PKT_EXCH | EVP_PKT_SIGN; + break; + default: + break; + } + + i = OBJ_obj2nid(x->sig_alg->algorithm); + if (i && OBJ_find_sigid_algs(i, NULL, &i)) { + + switch (i) { + case NID_rsaEncryption: + case NID_rsa: + ret |= EVP_PKS_RSA; + break; + case NID_dsa: + case NID_dsa_2: + ret |= EVP_PKS_DSA; + break; + case NID_X9_62_id_ecPublicKey: + ret |= EVP_PKS_EC; + break; + default: + break; + } + } + + if (EVP_PKEY_size(pk) <= 1024 / 8) /* /8 because it's 1024 bits we look + * for, not bytes */ + ret |= EVP_PKT_EXP; + if (pkey == NULL) + EVP_PKEY_free(pk); + return (ret); +} diff --git a/external/boringssl/crypto/x509/x_algor.c b/external/boringssl/crypto/x509/x_algor.c new file mode 100644 index 0000000000..abacd061df --- /dev/null +++ b/external/boringssl/crypto/x509/x_algor.c @@ -0,0 +1,151 @@ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project + * 2000. + */ +/* ==================================================================== + * Copyright (c) 2000 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include +#include +#include + + +ASN1_SEQUENCE(X509_ALGOR) = { + ASN1_SIMPLE(X509_ALGOR, algorithm, ASN1_OBJECT), + ASN1_OPT(X509_ALGOR, parameter, ASN1_ANY) +} ASN1_SEQUENCE_END(X509_ALGOR) + +ASN1_ITEM_TEMPLATE(X509_ALGORS) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, algorithms, X509_ALGOR) +ASN1_ITEM_TEMPLATE_END(X509_ALGORS) + +IMPLEMENT_ASN1_FUNCTIONS(X509_ALGOR) +IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(X509_ALGORS, X509_ALGORS, X509_ALGORS) +IMPLEMENT_ASN1_DUP_FUNCTION(X509_ALGOR) + +IMPLEMENT_ASN1_SET_OF(X509_ALGOR) + +int X509_ALGOR_set0(X509_ALGOR *alg, const ASN1_OBJECT *aobj, int ptype, + void *pval) +{ + if (!alg) + return 0; + if (ptype != V_ASN1_UNDEF) { + if (alg->parameter == NULL) + alg->parameter = ASN1_TYPE_new(); + if (alg->parameter == NULL) + return 0; + } + if (alg) { + if (alg->algorithm) + ASN1_OBJECT_free(alg->algorithm); + alg->algorithm = (ASN1_OBJECT *)aobj; + } + if (ptype == 0) + return 1; + if (ptype == V_ASN1_UNDEF) { + if (alg->parameter) { + ASN1_TYPE_free(alg->parameter); + alg->parameter = NULL; + } + } else + ASN1_TYPE_set(alg->parameter, ptype, pval); + return 1; +} + +void X509_ALGOR_get0(ASN1_OBJECT **paobj, int *pptype, void **ppval, + X509_ALGOR *algor) +{ + if (paobj) + *paobj = algor->algorithm; + if (pptype) { + if (algor->parameter == NULL) { + *pptype = V_ASN1_UNDEF; + return; + } else + *pptype = algor->parameter->type; + if (ppval) + *ppval = algor->parameter->value.ptr; + } +} + +/* Set up an X509_ALGOR DigestAlgorithmIdentifier from an EVP_MD */ + +void X509_ALGOR_set_md(X509_ALGOR *alg, const EVP_MD *md) +{ + int param_type; + + if (EVP_MD_flags(md) & EVP_MD_FLAG_DIGALGID_ABSENT) + param_type = V_ASN1_UNDEF; + else + param_type = V_ASN1_NULL; + + X509_ALGOR_set0(alg, OBJ_nid2obj(EVP_MD_type(md)), param_type, NULL); + +} + +/* + * X509_ALGOR_cmp returns 0 if |a| and |b| are equal and non-zero otherwise. + */ +int X509_ALGOR_cmp(const X509_ALGOR *a, const X509_ALGOR *b) +{ + int rv; + rv = OBJ_cmp(a->algorithm, b->algorithm); + if (rv) + return rv; + if (!a->parameter && !b->parameter) + return 0; + return ASN1_TYPE_cmp(a->parameter, b->parameter); +} diff --git a/external/boringssl/crypto/x509/x_all.c b/external/boringssl/crypto/x509/x_all.c new file mode 100644 index 0000000000..c430a7d31e --- /dev/null +++ b/external/boringssl/crypto/x509/x_all.c @@ -0,0 +1,501 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include +#include +#include +#include +#include +#include +#include +#include + +int X509_verify(X509 *a, EVP_PKEY *r) +{ + if (X509_ALGOR_cmp(a->sig_alg, a->cert_info->signature)) + return 0; + return (ASN1_item_verify(ASN1_ITEM_rptr(X509_CINF), a->sig_alg, + a->signature, a->cert_info, r)); +} + +int X509_REQ_verify(X509_REQ *a, EVP_PKEY *r) +{ + return (ASN1_item_verify(ASN1_ITEM_rptr(X509_REQ_INFO), + a->sig_alg, a->signature, a->req_info, r)); +} + +int X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md) +{ + x->cert_info->enc.modified = 1; + return (ASN1_item_sign(ASN1_ITEM_rptr(X509_CINF), x->cert_info->signature, + x->sig_alg, x->signature, x->cert_info, pkey, md)); +} + +int X509_sign_ctx(X509 *x, EVP_MD_CTX *ctx) +{ + x->cert_info->enc.modified = 1; + return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_CINF), + x->cert_info->signature, + x->sig_alg, x->signature, x->cert_info, ctx); +} + +int X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md) +{ + return (ASN1_item_sign(ASN1_ITEM_rptr(X509_REQ_INFO), x->sig_alg, NULL, + x->signature, x->req_info, pkey, md)); +} + +int X509_REQ_sign_ctx(X509_REQ *x, EVP_MD_CTX *ctx) +{ + return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_REQ_INFO), + x->sig_alg, NULL, x->signature, x->req_info, + ctx); +} + +int X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md) +{ + x->crl->enc.modified = 1; + return (ASN1_item_sign(ASN1_ITEM_rptr(X509_CRL_INFO), x->crl->sig_alg, + x->sig_alg, x->signature, x->crl, pkey, md)); +} + +int X509_CRL_sign_ctx(X509_CRL *x, EVP_MD_CTX *ctx) +{ + x->crl->enc.modified = 1; + return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_CRL_INFO), + x->crl->sig_alg, x->sig_alg, x->signature, + x->crl, ctx); +} + +int NETSCAPE_SPKI_sign(NETSCAPE_SPKI *x, EVP_PKEY *pkey, const EVP_MD *md) +{ + return (ASN1_item_sign(ASN1_ITEM_rptr(NETSCAPE_SPKAC), x->sig_algor, NULL, + x->signature, x->spkac, pkey, md)); +} + +int NETSCAPE_SPKI_verify(NETSCAPE_SPKI *x, EVP_PKEY *pkey) +{ + return (ASN1_item_verify(ASN1_ITEM_rptr(NETSCAPE_SPKAC), x->sig_algor, + x->signature, x->spkac, pkey)); +} + +#ifndef OPENSSL_NO_FP_API +X509 *d2i_X509_fp(FILE *fp, X509 **x509) +{ + return ASN1_item_d2i_fp(ASN1_ITEM_rptr(X509), fp, x509); +} + +int i2d_X509_fp(FILE *fp, X509 *x509) +{ + return ASN1_item_i2d_fp(ASN1_ITEM_rptr(X509), fp, x509); +} +#endif + +X509 *d2i_X509_bio(BIO *bp, X509 **x509) +{ + return ASN1_item_d2i_bio(ASN1_ITEM_rptr(X509), bp, x509); +} + +int i2d_X509_bio(BIO *bp, X509 *x509) +{ + return ASN1_item_i2d_bio(ASN1_ITEM_rptr(X509), bp, x509); +} + +#ifndef OPENSSL_NO_FP_API +X509_CRL *d2i_X509_CRL_fp(FILE *fp, X509_CRL **crl) +{ + return ASN1_item_d2i_fp(ASN1_ITEM_rptr(X509_CRL), fp, crl); +} + +int i2d_X509_CRL_fp(FILE *fp, X509_CRL *crl) +{ + return ASN1_item_i2d_fp(ASN1_ITEM_rptr(X509_CRL), fp, crl); +} +#endif + +X509_CRL *d2i_X509_CRL_bio(BIO *bp, X509_CRL **crl) +{ + return ASN1_item_d2i_bio(ASN1_ITEM_rptr(X509_CRL), bp, crl); +} + +int i2d_X509_CRL_bio(BIO *bp, X509_CRL *crl) +{ + return ASN1_item_i2d_bio(ASN1_ITEM_rptr(X509_CRL), bp, crl); +} + +#ifndef OPENSSL_NO_FP_API +X509_REQ *d2i_X509_REQ_fp(FILE *fp, X509_REQ **req) +{ + return ASN1_item_d2i_fp(ASN1_ITEM_rptr(X509_REQ), fp, req); +} + +int i2d_X509_REQ_fp(FILE *fp, X509_REQ *req) +{ + return ASN1_item_i2d_fp(ASN1_ITEM_rptr(X509_REQ), fp, req); +} +#endif + +X509_REQ *d2i_X509_REQ_bio(BIO *bp, X509_REQ **req) +{ + return ASN1_item_d2i_bio(ASN1_ITEM_rptr(X509_REQ), bp, req); +} + +int i2d_X509_REQ_bio(BIO *bp, X509_REQ *req) +{ + return ASN1_item_i2d_bio(ASN1_ITEM_rptr(X509_REQ), bp, req); +} + +#ifndef OPENSSL_NO_FP_API +RSA *d2i_RSAPrivateKey_fp(FILE *fp, RSA **rsa) +{ + return ASN1_d2i_fp_of(RSA, RSA_new, d2i_RSAPrivateKey, fp, rsa); +} + +int i2d_RSAPrivateKey_fp(FILE *fp, RSA *rsa) +{ + return ASN1_i2d_fp_of_const(RSA, i2d_RSAPrivateKey, fp, rsa); +} + +RSA *d2i_RSAPublicKey_fp(FILE *fp, RSA **rsa) +{ + return ASN1_d2i_fp_of(RSA, RSA_new, d2i_RSAPublicKey, fp, rsa); +} + +RSA *d2i_RSA_PUBKEY_fp(FILE *fp, RSA **rsa) +{ + return ASN1_d2i_fp((void *(*)(void)) + RSA_new, (D2I_OF(void)) d2i_RSA_PUBKEY, fp, + (void **)rsa); +} + +int i2d_RSAPublicKey_fp(FILE *fp, RSA *rsa) +{ + return ASN1_i2d_fp_of_const(RSA, i2d_RSAPublicKey, fp, rsa); +} + +int i2d_RSA_PUBKEY_fp(FILE *fp, RSA *rsa) +{ + return ASN1_i2d_fp((I2D_OF_const(void))i2d_RSA_PUBKEY, fp, rsa); +} +#endif + +RSA *d2i_RSAPrivateKey_bio(BIO *bp, RSA **rsa) +{ + return ASN1_d2i_bio_of(RSA, RSA_new, d2i_RSAPrivateKey, bp, rsa); +} + +int i2d_RSAPrivateKey_bio(BIO *bp, RSA *rsa) +{ + return ASN1_i2d_bio_of_const(RSA, i2d_RSAPrivateKey, bp, rsa); +} + +RSA *d2i_RSAPublicKey_bio(BIO *bp, RSA **rsa) +{ + return ASN1_d2i_bio_of(RSA, RSA_new, d2i_RSAPublicKey, bp, rsa); +} + +RSA *d2i_RSA_PUBKEY_bio(BIO *bp, RSA **rsa) +{ + return ASN1_d2i_bio_of(RSA, RSA_new, d2i_RSA_PUBKEY, bp, rsa); +} + +int i2d_RSAPublicKey_bio(BIO *bp, RSA *rsa) +{ + return ASN1_i2d_bio_of_const(RSA, i2d_RSAPublicKey, bp, rsa); +} + +int i2d_RSA_PUBKEY_bio(BIO *bp, RSA *rsa) +{ + return ASN1_i2d_bio_of_const(RSA, i2d_RSA_PUBKEY, bp, rsa); +} + +#ifndef OPENSSL_NO_DSA +# ifndef OPENSSL_NO_FP_API +DSA *d2i_DSAPrivateKey_fp(FILE *fp, DSA **dsa) +{ + return ASN1_d2i_fp_of(DSA, DSA_new, d2i_DSAPrivateKey, fp, dsa); +} + +int i2d_DSAPrivateKey_fp(FILE *fp, DSA *dsa) +{ + return ASN1_i2d_fp_of_const(DSA, i2d_DSAPrivateKey, fp, dsa); +} + +DSA *d2i_DSA_PUBKEY_fp(FILE *fp, DSA **dsa) +{ + return ASN1_d2i_fp_of(DSA, DSA_new, d2i_DSA_PUBKEY, fp, dsa); +} + +int i2d_DSA_PUBKEY_fp(FILE *fp, DSA *dsa) +{ + return ASN1_i2d_fp_of_const(DSA, i2d_DSA_PUBKEY, fp, dsa); +} +# endif + +DSA *d2i_DSAPrivateKey_bio(BIO *bp, DSA **dsa) +{ + return ASN1_d2i_bio_of(DSA, DSA_new, d2i_DSAPrivateKey, bp, dsa); +} + +int i2d_DSAPrivateKey_bio(BIO *bp, DSA *dsa) +{ + return ASN1_i2d_bio_of_const(DSA, i2d_DSAPrivateKey, bp, dsa); +} + +DSA *d2i_DSA_PUBKEY_bio(BIO *bp, DSA **dsa) +{ + return ASN1_d2i_bio_of(DSA, DSA_new, d2i_DSA_PUBKEY, bp, dsa); +} + +int i2d_DSA_PUBKEY_bio(BIO *bp, DSA *dsa) +{ + return ASN1_i2d_bio_of_const(DSA, i2d_DSA_PUBKEY, bp, dsa); +} + +#endif + +#ifndef OPENSSL_NO_FP_API +EC_KEY *d2i_EC_PUBKEY_fp(FILE *fp, EC_KEY **eckey) +{ + return ASN1_d2i_fp_of(EC_KEY, EC_KEY_new, d2i_EC_PUBKEY, fp, eckey); +} + +int i2d_EC_PUBKEY_fp(FILE *fp, EC_KEY *eckey) +{ + return ASN1_i2d_fp_of_const(EC_KEY, i2d_EC_PUBKEY, fp, eckey); +} + +EC_KEY *d2i_ECPrivateKey_fp(FILE *fp, EC_KEY **eckey) +{ + return ASN1_d2i_fp_of(EC_KEY, EC_KEY_new, d2i_ECPrivateKey, fp, eckey); +} + +int i2d_ECPrivateKey_fp(FILE *fp, EC_KEY *eckey) +{ + return ASN1_i2d_fp_of_const(EC_KEY, i2d_ECPrivateKey, fp, eckey); +} +#endif +EC_KEY *d2i_EC_PUBKEY_bio(BIO *bp, EC_KEY **eckey) +{ + return ASN1_d2i_bio_of(EC_KEY, EC_KEY_new, d2i_EC_PUBKEY, bp, eckey); +} + +int i2d_EC_PUBKEY_bio(BIO *bp, EC_KEY *ecdsa) +{ + return ASN1_i2d_bio_of_const(EC_KEY, i2d_EC_PUBKEY, bp, ecdsa); +} + +EC_KEY *d2i_ECPrivateKey_bio(BIO *bp, EC_KEY **eckey) +{ + return ASN1_d2i_bio_of(EC_KEY, EC_KEY_new, d2i_ECPrivateKey, bp, eckey); +} + +int i2d_ECPrivateKey_bio(BIO *bp, EC_KEY *eckey) +{ + return ASN1_i2d_bio_of_const(EC_KEY, i2d_ECPrivateKey, bp, eckey); +} + +int X509_pubkey_digest(const X509 *data, const EVP_MD *type, + unsigned char *md, unsigned int *len) +{ + ASN1_BIT_STRING *key; + key = X509_get0_pubkey_bitstr(data); + if (!key) + return 0; + return EVP_Digest(key->data, key->length, md, len, type, NULL); +} + +int X509_digest(const X509 *data, const EVP_MD *type, unsigned char *md, + unsigned int *len) +{ + return (ASN1_item_digest + (ASN1_ITEM_rptr(X509), type, (char *)data, md, len)); +} + +int X509_CRL_digest(const X509_CRL *data, const EVP_MD *type, + unsigned char *md, unsigned int *len) +{ + return (ASN1_item_digest + (ASN1_ITEM_rptr(X509_CRL), type, (char *)data, md, len)); +} + +int X509_REQ_digest(const X509_REQ *data, const EVP_MD *type, + unsigned char *md, unsigned int *len) +{ + return (ASN1_item_digest + (ASN1_ITEM_rptr(X509_REQ), type, (char *)data, md, len)); +} + +int X509_NAME_digest(const X509_NAME *data, const EVP_MD *type, + unsigned char *md, unsigned int *len) +{ + return (ASN1_item_digest + (ASN1_ITEM_rptr(X509_NAME), type, (char *)data, md, len)); +} + +#ifndef OPENSSL_NO_FP_API +X509_SIG *d2i_PKCS8_fp(FILE *fp, X509_SIG **p8) +{ + return ASN1_d2i_fp_of(X509_SIG, X509_SIG_new, d2i_X509_SIG, fp, p8); +} + +int i2d_PKCS8_fp(FILE *fp, X509_SIG *p8) +{ + return ASN1_i2d_fp_of(X509_SIG, i2d_X509_SIG, fp, p8); +} +#endif + +X509_SIG *d2i_PKCS8_bio(BIO *bp, X509_SIG **p8) +{ + return ASN1_d2i_bio_of(X509_SIG, X509_SIG_new, d2i_X509_SIG, bp, p8); +} + +int i2d_PKCS8_bio(BIO *bp, X509_SIG *p8) +{ + return ASN1_i2d_bio_of(X509_SIG, i2d_X509_SIG, bp, p8); +} + +#ifndef OPENSSL_NO_FP_API +PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_fp(FILE *fp, + PKCS8_PRIV_KEY_INFO **p8inf) +{ + return ASN1_d2i_fp_of(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_new, + d2i_PKCS8_PRIV_KEY_INFO, fp, p8inf); +} + +int i2d_PKCS8_PRIV_KEY_INFO_fp(FILE *fp, PKCS8_PRIV_KEY_INFO *p8inf) +{ + return ASN1_i2d_fp_of(PKCS8_PRIV_KEY_INFO, i2d_PKCS8_PRIV_KEY_INFO, fp, + p8inf); +} + +int i2d_PKCS8PrivateKeyInfo_fp(FILE *fp, EVP_PKEY *key) +{ + PKCS8_PRIV_KEY_INFO *p8inf; + int ret; + p8inf = EVP_PKEY2PKCS8(key); + if (!p8inf) + return 0; + ret = i2d_PKCS8_PRIV_KEY_INFO_fp(fp, p8inf); + PKCS8_PRIV_KEY_INFO_free(p8inf); + return ret; +} + +int i2d_PrivateKey_fp(FILE *fp, EVP_PKEY *pkey) +{ + return ASN1_i2d_fp_of_const(EVP_PKEY, i2d_PrivateKey, fp, pkey); +} + +EVP_PKEY *d2i_PrivateKey_fp(FILE *fp, EVP_PKEY **a) +{ + return ASN1_d2i_fp_of(EVP_PKEY, EVP_PKEY_new, d2i_AutoPrivateKey, fp, a); +} + +int i2d_PUBKEY_fp(FILE *fp, EVP_PKEY *pkey) +{ + return ASN1_i2d_fp_of_const(EVP_PKEY, i2d_PUBKEY, fp, pkey); +} + +EVP_PKEY *d2i_PUBKEY_fp(FILE *fp, EVP_PKEY **a) +{ + return ASN1_d2i_fp_of(EVP_PKEY, EVP_PKEY_new, d2i_PUBKEY, fp, a); +} + +PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_bio(BIO *bp, + PKCS8_PRIV_KEY_INFO **p8inf) +{ + return ASN1_d2i_bio_of(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_new, + d2i_PKCS8_PRIV_KEY_INFO, bp, p8inf); +} + +int i2d_PKCS8_PRIV_KEY_INFO_bio(BIO *bp, PKCS8_PRIV_KEY_INFO *p8inf) +{ + return ASN1_i2d_bio_of(PKCS8_PRIV_KEY_INFO, i2d_PKCS8_PRIV_KEY_INFO, bp, + p8inf); +} + +int i2d_PKCS8PrivateKeyInfo_bio(BIO *bp, EVP_PKEY *key) +{ + PKCS8_PRIV_KEY_INFO *p8inf; + int ret; + p8inf = EVP_PKEY2PKCS8(key); + if (!p8inf) + return 0; + ret = i2d_PKCS8_PRIV_KEY_INFO_bio(bp, p8inf); + PKCS8_PRIV_KEY_INFO_free(p8inf); + return ret; +} +#endif + +int i2d_PrivateKey_bio(BIO *bp, EVP_PKEY *pkey) +{ + return ASN1_i2d_bio_of_const(EVP_PKEY, i2d_PrivateKey, bp, pkey); +} + +EVP_PKEY *d2i_PrivateKey_bio(BIO *bp, EVP_PKEY **a) +{ + return ASN1_d2i_bio_of(EVP_PKEY, EVP_PKEY_new, d2i_AutoPrivateKey, bp, a); +} + +int i2d_PUBKEY_bio(BIO *bp, EVP_PKEY *pkey) +{ + return ASN1_i2d_bio_of_const(EVP_PKEY, i2d_PUBKEY, bp, pkey); +} + +EVP_PKEY *d2i_PUBKEY_bio(BIO *bp, EVP_PKEY **a) +{ + return ASN1_d2i_bio_of(EVP_PKEY, EVP_PKEY_new, d2i_PUBKEY, bp, a); +} diff --git a/external/boringssl/crypto/x509/x_attrib.c b/external/boringssl/crypto/x509/x_attrib.c new file mode 100644 index 0000000000..de8c95cc1c --- /dev/null +++ b/external/boringssl/crypto/x509/x_attrib.c @@ -0,0 +1,111 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include +#include +#include +#include + +/* + * X509_ATTRIBUTE: this has the following form: typedef struct + * x509_attributes_st { ASN1_OBJECT *object; int single; union { char *ptr; + * STACK_OF(ASN1_TYPE) *set; ASN1_TYPE *single; } value; } X509_ATTRIBUTE; + * this needs some extra thought because the CHOICE type is merged with the + * main structure and because the value can be anything at all we *must* try + * the SET OF first because the ASN1_ANY type will swallow anything including + * the whole SET OF structure. + */ + +ASN1_CHOICE(X509_ATTRIBUTE_SET) = { + ASN1_SET_OF(X509_ATTRIBUTE, value.set, ASN1_ANY), + ASN1_SIMPLE(X509_ATTRIBUTE, value.single, ASN1_ANY) +} ASN1_CHOICE_END_selector(X509_ATTRIBUTE, X509_ATTRIBUTE_SET, single) + +ASN1_SEQUENCE(X509_ATTRIBUTE) = { + ASN1_SIMPLE(X509_ATTRIBUTE, object, ASN1_OBJECT), + /* CHOICE type merged with parent */ + ASN1_EX_COMBINE(0, 0, X509_ATTRIBUTE_SET) +} ASN1_SEQUENCE_END(X509_ATTRIBUTE) + +IMPLEMENT_ASN1_FUNCTIONS(X509_ATTRIBUTE) +IMPLEMENT_ASN1_DUP_FUNCTION(X509_ATTRIBUTE) + +X509_ATTRIBUTE *X509_ATTRIBUTE_create(int nid, int atrtype, void *value) +{ + X509_ATTRIBUTE *ret = NULL; + ASN1_TYPE *val = NULL; + + if ((ret = X509_ATTRIBUTE_new()) == NULL) + return (NULL); + /* TODO(fork): const correctness. */ + ret->object = (ASN1_OBJECT *)OBJ_nid2obj(nid); + ret->single = 0; + if ((ret->value.set = sk_ASN1_TYPE_new_null()) == NULL) + goto err; + if ((val = ASN1_TYPE_new()) == NULL) + goto err; + if (!sk_ASN1_TYPE_push(ret->value.set, val)) + goto err; + + ASN1_TYPE_set(val, atrtype, value); + return (ret); + err: + if (ret != NULL) + X509_ATTRIBUTE_free(ret); + if (val != NULL) + ASN1_TYPE_free(val); + return (NULL); +} diff --git a/external/boringssl/crypto/x509/x_crl.c b/external/boringssl/crypto/x509/x_crl.c new file mode 100644 index 0000000000..934571dd54 --- /dev/null +++ b/external/boringssl/crypto/x509/x_crl.c @@ -0,0 +1,539 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../internal.h" + +/* + * Method to handle CRL access. In general a CRL could be very large (several + * Mb) and can consume large amounts of resources if stored in memory by + * multiple processes. This method allows general CRL operations to be + * redirected to more efficient callbacks: for example a CRL entry database. + */ + +#define X509_CRL_METHOD_DYNAMIC 1 + +struct x509_crl_method_st { + int flags; + int (*crl_init) (X509_CRL *crl); + int (*crl_free) (X509_CRL *crl); + int (*crl_lookup) (X509_CRL *crl, X509_REVOKED **ret, + ASN1_INTEGER *ser, X509_NAME *issuer); + int (*crl_verify) (X509_CRL *crl, EVP_PKEY *pk); +}; + +static int X509_REVOKED_cmp(const X509_REVOKED **a, const X509_REVOKED **b); +static void setup_idp(X509_CRL *crl, ISSUING_DIST_POINT *idp); + +ASN1_SEQUENCE(X509_REVOKED) = { + ASN1_SIMPLE(X509_REVOKED,serialNumber, ASN1_INTEGER), + ASN1_SIMPLE(X509_REVOKED,revocationDate, ASN1_TIME), + ASN1_SEQUENCE_OF_OPT(X509_REVOKED,extensions, X509_EXTENSION) +} ASN1_SEQUENCE_END(X509_REVOKED) + +static int def_crl_verify(X509_CRL *crl, EVP_PKEY *r); +static int def_crl_lookup(X509_CRL *crl, + X509_REVOKED **ret, ASN1_INTEGER *serial, + X509_NAME *issuer); + +static const X509_CRL_METHOD int_crl_meth = { + 0, + 0, 0, + def_crl_lookup, + def_crl_verify +}; + +static const X509_CRL_METHOD *default_crl_method = &int_crl_meth; + +/* + * The X509_CRL_INFO structure needs a bit of customisation. Since we cache + * the original encoding the signature wont be affected by reordering of the + * revoked field. + */ +static int crl_inf_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, + void *exarg) +{ + X509_CRL_INFO *a = (X509_CRL_INFO *)*pval; + + if (!a || !a->revoked) + return 1; + switch (operation) { + /* + * Just set cmp function here. We don't sort because that would + * affect the output of X509_CRL_print(). + */ + case ASN1_OP_D2I_POST: + (void)sk_X509_REVOKED_set_cmp_func(a->revoked, X509_REVOKED_cmp); + break; + } + return 1; +} + + +ASN1_SEQUENCE_enc(X509_CRL_INFO, enc, crl_inf_cb) = { + ASN1_OPT(X509_CRL_INFO, version, ASN1_INTEGER), + ASN1_SIMPLE(X509_CRL_INFO, sig_alg, X509_ALGOR), + ASN1_SIMPLE(X509_CRL_INFO, issuer, X509_NAME), + ASN1_SIMPLE(X509_CRL_INFO, lastUpdate, ASN1_TIME), + ASN1_OPT(X509_CRL_INFO, nextUpdate, ASN1_TIME), + ASN1_SEQUENCE_OF_OPT(X509_CRL_INFO, revoked, X509_REVOKED), + ASN1_EXP_SEQUENCE_OF_OPT(X509_CRL_INFO, extensions, X509_EXTENSION, 0) +} ASN1_SEQUENCE_END_enc(X509_CRL_INFO, X509_CRL_INFO) + +/* + * Set CRL entry issuer according to CRL certificate issuer extension. Check + * for unhandled critical CRL entry extensions. + */ + +static int crl_set_issuers(X509_CRL *crl) +{ + + size_t i, k; + int j; + GENERAL_NAMES *gens, *gtmp; + STACK_OF(X509_REVOKED) *revoked; + + revoked = X509_CRL_get_REVOKED(crl); + + gens = NULL; + for (i = 0; i < sk_X509_REVOKED_num(revoked); i++) { + X509_REVOKED *rev = sk_X509_REVOKED_value(revoked, i); + STACK_OF(X509_EXTENSION) *exts; + ASN1_ENUMERATED *reason; + X509_EXTENSION *ext; + gtmp = X509_REVOKED_get_ext_d2i(rev, + NID_certificate_issuer, &j, NULL); + if (!gtmp && (j != -1)) { + crl->flags |= EXFLAG_INVALID; + return 1; + } + + if (gtmp) { + gens = gtmp; + if (!crl->issuers) { + crl->issuers = sk_GENERAL_NAMES_new_null(); + if (!crl->issuers) + return 0; + } + if (!sk_GENERAL_NAMES_push(crl->issuers, gtmp)) + return 0; + } + rev->issuer = gens; + + reason = X509_REVOKED_get_ext_d2i(rev, NID_crl_reason, &j, NULL); + if (!reason && (j != -1)) { + crl->flags |= EXFLAG_INVALID; + return 1; + } + + if (reason) { + rev->reason = ASN1_ENUMERATED_get(reason); + ASN1_ENUMERATED_free(reason); + } else + rev->reason = CRL_REASON_NONE; + + /* Check for critical CRL entry extensions */ + + exts = rev->extensions; + + for (k = 0; k < sk_X509_EXTENSION_num(exts); k++) { + ext = sk_X509_EXTENSION_value(exts, k); + if (ext->critical > 0) { + if (OBJ_obj2nid(ext->object) == NID_certificate_issuer) + continue; + crl->flags |= EXFLAG_CRITICAL; + break; + } + } + + } + + return 1; + +} + +/* + * The X509_CRL structure needs a bit of customisation. Cache some extensions + * and hash of the whole CRL. + */ +static int crl_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, + void *exarg) +{ + X509_CRL *crl = (X509_CRL *)*pval; + STACK_OF(X509_EXTENSION) *exts; + X509_EXTENSION *ext; + size_t idx; + + switch (operation) { + case ASN1_OP_NEW_POST: + crl->idp = NULL; + crl->akid = NULL; + crl->flags = 0; + crl->idp_flags = 0; + crl->idp_reasons = CRLDP_ALL_REASONS; + crl->meth = default_crl_method; + crl->meth_data = NULL; + crl->issuers = NULL; + crl->crl_number = NULL; + crl->base_crl_number = NULL; + break; + + case ASN1_OP_D2I_POST: + X509_CRL_digest(crl, EVP_sha1(), crl->sha1_hash, NULL); + crl->idp = X509_CRL_get_ext_d2i(crl, + NID_issuing_distribution_point, NULL, + NULL); + if (crl->idp) + setup_idp(crl, crl->idp); + + crl->akid = X509_CRL_get_ext_d2i(crl, + NID_authority_key_identifier, NULL, + NULL); + + crl->crl_number = X509_CRL_get_ext_d2i(crl, + NID_crl_number, NULL, NULL); + + crl->base_crl_number = X509_CRL_get_ext_d2i(crl, + NID_delta_crl, NULL, + NULL); + /* Delta CRLs must have CRL number */ + if (crl->base_crl_number && !crl->crl_number) + crl->flags |= EXFLAG_INVALID; + + /* + * See if we have any unhandled critical CRL extensions and indicate + * this in a flag. We only currently handle IDP so anything else + * critical sets the flag. This code accesses the X509_CRL structure + * directly: applications shouldn't do this. + */ + + exts = crl->crl->extensions; + + for (idx = 0; idx < sk_X509_EXTENSION_num(exts); idx++) { + int nid; + ext = sk_X509_EXTENSION_value(exts, idx); + nid = OBJ_obj2nid(ext->object); + if (nid == NID_freshest_crl) + crl->flags |= EXFLAG_FRESHEST; + if (ext->critical > 0) { + /* We handle IDP and deltas */ + if ((nid == NID_issuing_distribution_point) + || (nid == NID_authority_key_identifier) + || (nid == NID_delta_crl)) + break;; + crl->flags |= EXFLAG_CRITICAL; + break; + } + } + + if (!crl_set_issuers(crl)) + return 0; + + if (crl->meth->crl_init) { + if (crl->meth->crl_init(crl) == 0) + return 0; + } + break; + + case ASN1_OP_FREE_POST: + if (crl->meth->crl_free) { + if (!crl->meth->crl_free(crl)) + return 0; + } + if (crl->akid) + AUTHORITY_KEYID_free(crl->akid); + if (crl->idp) + ISSUING_DIST_POINT_free(crl->idp); + ASN1_INTEGER_free(crl->crl_number); + ASN1_INTEGER_free(crl->base_crl_number); + sk_GENERAL_NAMES_pop_free(crl->issuers, GENERAL_NAMES_free); + break; + } + return 1; +} + +/* Convert IDP into a more convenient form */ + +static void setup_idp(X509_CRL *crl, ISSUING_DIST_POINT *idp) +{ + int idp_only = 0; + /* Set various flags according to IDP */ + crl->idp_flags |= IDP_PRESENT; + if (idp->onlyuser > 0) { + idp_only++; + crl->idp_flags |= IDP_ONLYUSER; + } + if (idp->onlyCA > 0) { + idp_only++; + crl->idp_flags |= IDP_ONLYCA; + } + if (idp->onlyattr > 0) { + idp_only++; + crl->idp_flags |= IDP_ONLYATTR; + } + + if (idp_only > 1) + crl->idp_flags |= IDP_INVALID; + + if (idp->indirectCRL > 0) + crl->idp_flags |= IDP_INDIRECT; + + if (idp->onlysomereasons) { + crl->idp_flags |= IDP_REASONS; + if (idp->onlysomereasons->length > 0) + crl->idp_reasons = idp->onlysomereasons->data[0]; + if (idp->onlysomereasons->length > 1) + crl->idp_reasons |= (idp->onlysomereasons->data[1] << 8); + crl->idp_reasons &= CRLDP_ALL_REASONS; + } + + DIST_POINT_set_dpname(idp->distpoint, X509_CRL_get_issuer(crl)); +} + +ASN1_SEQUENCE_ref(X509_CRL, crl_cb) = { + ASN1_SIMPLE(X509_CRL, crl, X509_CRL_INFO), + ASN1_SIMPLE(X509_CRL, sig_alg, X509_ALGOR), + ASN1_SIMPLE(X509_CRL, signature, ASN1_BIT_STRING) +} ASN1_SEQUENCE_END_ref(X509_CRL, X509_CRL) + +IMPLEMENT_ASN1_FUNCTIONS(X509_REVOKED) + +IMPLEMENT_ASN1_DUP_FUNCTION(X509_REVOKED) + +IMPLEMENT_ASN1_FUNCTIONS(X509_CRL_INFO) +IMPLEMENT_ASN1_FUNCTIONS(X509_CRL) +IMPLEMENT_ASN1_DUP_FUNCTION(X509_CRL) + +static int X509_REVOKED_cmp(const X509_REVOKED **a, const X509_REVOKED **b) +{ + return (ASN1_STRING_cmp((ASN1_STRING *)(*a)->serialNumber, + (ASN1_STRING *)(*b)->serialNumber)); +} + +int X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev) +{ + X509_CRL_INFO *inf; + inf = crl->crl; + if (!inf->revoked) + inf->revoked = sk_X509_REVOKED_new(X509_REVOKED_cmp); + if (!inf->revoked || !sk_X509_REVOKED_push(inf->revoked, rev)) { + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + return 0; + } + inf->enc.modified = 1; + return 1; +} + +int X509_CRL_verify(X509_CRL *crl, EVP_PKEY *r) +{ + if (crl->meth->crl_verify) + return crl->meth->crl_verify(crl, r); + return 0; +} + +int X509_CRL_get0_by_serial(X509_CRL *crl, + X509_REVOKED **ret, ASN1_INTEGER *serial) +{ + if (crl->meth->crl_lookup) + return crl->meth->crl_lookup(crl, ret, serial, NULL); + return 0; +} + +int X509_CRL_get0_by_cert(X509_CRL *crl, X509_REVOKED **ret, X509 *x) +{ + if (crl->meth->crl_lookup) + return crl->meth->crl_lookup(crl, ret, + X509_get_serialNumber(x), + X509_get_issuer_name(x)); + return 0; +} + +static int def_crl_verify(X509_CRL *crl, EVP_PKEY *r) +{ + return (ASN1_item_verify(ASN1_ITEM_rptr(X509_CRL_INFO), + crl->sig_alg, crl->signature, crl->crl, r)); +} + +static int crl_revoked_issuer_match(X509_CRL *crl, X509_NAME *nm, + X509_REVOKED *rev) +{ + size_t i; + + if (!rev->issuer) { + if (!nm) + return 1; + if (!X509_NAME_cmp(nm, X509_CRL_get_issuer(crl))) + return 1; + return 0; + } + + if (!nm) + nm = X509_CRL_get_issuer(crl); + + for (i = 0; i < sk_GENERAL_NAME_num(rev->issuer); i++) { + GENERAL_NAME *gen = sk_GENERAL_NAME_value(rev->issuer, i); + if (gen->type != GEN_DIRNAME) + continue; + if (!X509_NAME_cmp(nm, gen->d.directoryName)) + return 1; + } + return 0; + +} + +static struct CRYPTO_STATIC_MUTEX g_crl_sort_lock = CRYPTO_STATIC_MUTEX_INIT; + +static int def_crl_lookup(X509_CRL *crl, + X509_REVOKED **ret, ASN1_INTEGER *serial, + X509_NAME *issuer) +{ + X509_REVOKED rtmp, *rev; + size_t idx; + rtmp.serialNumber = serial; + /* + * Sort revoked into serial number order if not already sorted. Do this + * under a lock to avoid race condition. + */ + + CRYPTO_STATIC_MUTEX_lock_read(&g_crl_sort_lock); + const int is_sorted = sk_X509_REVOKED_is_sorted(crl->crl->revoked); + CRYPTO_STATIC_MUTEX_unlock_read(&g_crl_sort_lock); + + if (!is_sorted) { + CRYPTO_STATIC_MUTEX_lock_write(&g_crl_sort_lock); + if (!sk_X509_REVOKED_is_sorted(crl->crl->revoked)) { + sk_X509_REVOKED_sort(crl->crl->revoked); + } + CRYPTO_STATIC_MUTEX_unlock_write(&g_crl_sort_lock); + } + + if (!sk_X509_REVOKED_find(crl->crl->revoked, &idx, &rtmp)) + return 0; + /* Need to look for matching name */ + for (; idx < sk_X509_REVOKED_num(crl->crl->revoked); idx++) { + rev = sk_X509_REVOKED_value(crl->crl->revoked, idx); + if (ASN1_INTEGER_cmp(rev->serialNumber, serial)) + return 0; + if (crl_revoked_issuer_match(crl, issuer, rev)) { + if (ret) + *ret = rev; + if (rev->reason == CRL_REASON_REMOVE_FROM_CRL) + return 2; + return 1; + } + } + return 0; +} + +void X509_CRL_set_default_method(const X509_CRL_METHOD *meth) +{ + if (meth == NULL) + default_crl_method = &int_crl_meth; + else + default_crl_method = meth; +} + +X509_CRL_METHOD *X509_CRL_METHOD_new(int (*crl_init) (X509_CRL *crl), + int (*crl_free) (X509_CRL *crl), + int (*crl_lookup) (X509_CRL *crl, + X509_REVOKED **ret, + ASN1_INTEGER *ser, + X509_NAME *issuer), + int (*crl_verify) (X509_CRL *crl, + EVP_PKEY *pk)) +{ + X509_CRL_METHOD *m; + m = OPENSSL_malloc(sizeof(X509_CRL_METHOD)); + if (!m) + return NULL; + m->crl_init = crl_init; + m->crl_free = crl_free; + m->crl_lookup = crl_lookup; + m->crl_verify = crl_verify; + m->flags = X509_CRL_METHOD_DYNAMIC; + return m; +} + +void X509_CRL_METHOD_free(X509_CRL_METHOD *m) +{ + if (!(m->flags & X509_CRL_METHOD_DYNAMIC)) + return; + OPENSSL_free(m); +} + +void X509_CRL_set_meth_data(X509_CRL *crl, void *dat) +{ + crl->meth_data = dat; +} + +void *X509_CRL_get_meth_data(X509_CRL *crl) +{ + return crl->meth_data; +} + +IMPLEMENT_ASN1_SET_OF(X509_REVOKED) + +IMPLEMENT_ASN1_SET_OF(X509_CRL) diff --git a/external/boringssl/crypto/x509/x_exten.c b/external/boringssl/crypto/x509/x_exten.c new file mode 100644 index 0000000000..36403e4884 --- /dev/null +++ b/external/boringssl/crypto/x509/x_exten.c @@ -0,0 +1,75 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include +#include +#include +#include + + +ASN1_SEQUENCE(X509_EXTENSION) = { + ASN1_SIMPLE(X509_EXTENSION, object, ASN1_OBJECT), + ASN1_OPT(X509_EXTENSION, critical, ASN1_BOOLEAN), + ASN1_SIMPLE(X509_EXTENSION, value, ASN1_OCTET_STRING) +} ASN1_SEQUENCE_END(X509_EXTENSION) + +ASN1_ITEM_TEMPLATE(X509_EXTENSIONS) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, Extension, X509_EXTENSION) +ASN1_ITEM_TEMPLATE_END(X509_EXTENSIONS) + +IMPLEMENT_ASN1_FUNCTIONS(X509_EXTENSION) +IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(X509_EXTENSIONS, X509_EXTENSIONS, X509_EXTENSIONS) +IMPLEMENT_ASN1_DUP_FUNCTION(X509_EXTENSION) diff --git a/external/boringssl/crypto/x509/x_info.c b/external/boringssl/crypto/x509/x_info.c new file mode 100644 index 0000000000..177cd0eb58 --- /dev/null +++ b/external/boringssl/crypto/x509/x_info.c @@ -0,0 +1,98 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include +#include +#include + +X509_INFO *X509_INFO_new(void) +{ + X509_INFO *ret = NULL; + + ret = (X509_INFO *)OPENSSL_malloc(sizeof(X509_INFO)); + if (ret == NULL) { + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + return (NULL); + } + + ret->enc_cipher.cipher = NULL; + ret->enc_len = 0; + ret->enc_data = NULL; + + ret->x509 = NULL; + ret->crl = NULL; + ret->x_pkey = NULL; + return (ret); +} + +void X509_INFO_free(X509_INFO *x) +{ + if (x == NULL) + return; + + if (x->x509 != NULL) + X509_free(x->x509); + if (x->crl != NULL) + X509_CRL_free(x->crl); + if (x->x_pkey != NULL) + X509_PKEY_free(x->x_pkey); + if (x->enc_data != NULL) + OPENSSL_free(x->enc_data); + OPENSSL_free(x); +} diff --git a/external/boringssl/crypto/x509/x_name.c b/external/boringssl/crypto/x509/x_name.c new file mode 100644 index 0000000000..d7dbf80464 --- /dev/null +++ b/external/boringssl/crypto/x509/x_name.c @@ -0,0 +1,534 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../asn1/asn1_locl.h" + +typedef STACK_OF(X509_NAME_ENTRY) STACK_OF_X509_NAME_ENTRY; +DECLARE_STACK_OF(STACK_OF_X509_NAME_ENTRY) + +/* + * Maximum length of X509_NAME: much larger than anything we should + * ever see in practice. + */ + +#define X509_NAME_MAX (1024 * 1024) + +static int x509_name_ex_d2i(ASN1_VALUE **val, + const unsigned char **in, long len, + const ASN1_ITEM *it, + int tag, int aclass, char opt, ASN1_TLC *ctx); + +static int x509_name_ex_i2d(ASN1_VALUE **val, unsigned char **out, + const ASN1_ITEM *it, int tag, int aclass); +static int x509_name_ex_new(ASN1_VALUE **val, const ASN1_ITEM *it); +static void x509_name_ex_free(ASN1_VALUE **val, const ASN1_ITEM *it); + +static int x509_name_encode(X509_NAME *a); +static int x509_name_canon(X509_NAME *a); +static int asn1_string_canon(ASN1_STRING *out, ASN1_STRING *in); +static int i2d_name_canon(STACK_OF(STACK_OF_X509_NAME_ENTRY) * intname, + unsigned char **in); + +ASN1_SEQUENCE(X509_NAME_ENTRY) = { + ASN1_SIMPLE(X509_NAME_ENTRY, object, ASN1_OBJECT), + ASN1_SIMPLE(X509_NAME_ENTRY, value, ASN1_PRINTABLE) +} ASN1_SEQUENCE_END(X509_NAME_ENTRY) + +IMPLEMENT_ASN1_FUNCTIONS(X509_NAME_ENTRY) +IMPLEMENT_ASN1_DUP_FUNCTION(X509_NAME_ENTRY) + +/* + * For the "Name" type we need a SEQUENCE OF { SET OF X509_NAME_ENTRY } so + * declare two template wrappers for this + */ + +ASN1_ITEM_TEMPLATE(X509_NAME_ENTRIES) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SET_OF, 0, RDNS, X509_NAME_ENTRY) +ASN1_ITEM_TEMPLATE_END(X509_NAME_ENTRIES) + +ASN1_ITEM_TEMPLATE(X509_NAME_INTERNAL) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, Name, X509_NAME_ENTRIES) +ASN1_ITEM_TEMPLATE_END(X509_NAME_INTERNAL) + +/* + * Normally that's where it would end: we'd have two nested STACK structures + * representing the ASN1. Unfortunately X509_NAME uses a completely different + * form and caches encodings so we have to process the internal form and + * convert to the external form. + */ + +static const ASN1_EXTERN_FUNCS x509_name_ff = { + NULL, + x509_name_ex_new, + x509_name_ex_free, + 0, /* Default clear behaviour is OK */ + x509_name_ex_d2i, + x509_name_ex_i2d, + NULL, +}; + +IMPLEMENT_EXTERN_ASN1(X509_NAME, V_ASN1_SEQUENCE, x509_name_ff) + +IMPLEMENT_ASN1_FUNCTIONS(X509_NAME) + +IMPLEMENT_ASN1_DUP_FUNCTION(X509_NAME) + +static int x509_name_ex_new(ASN1_VALUE **val, const ASN1_ITEM *it) +{ + X509_NAME *ret = NULL; + ret = OPENSSL_malloc(sizeof(X509_NAME)); + if (!ret) + goto memerr; + if ((ret->entries = sk_X509_NAME_ENTRY_new_null()) == NULL) + goto memerr; + if ((ret->bytes = BUF_MEM_new()) == NULL) + goto memerr; + ret->canon_enc = NULL; + ret->canon_enclen = 0; + ret->modified = 1; + *val = (ASN1_VALUE *)ret; + return 1; + + memerr: + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + if (ret) { + if (ret->entries) + sk_X509_NAME_ENTRY_free(ret->entries); + OPENSSL_free(ret); + } + return 0; +} + +static void x509_name_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + X509_NAME *a; + if (!pval || !*pval) + return; + a = (X509_NAME *)*pval; + + BUF_MEM_free(a->bytes); + sk_X509_NAME_ENTRY_pop_free(a->entries, X509_NAME_ENTRY_free); + if (a->canon_enc) + OPENSSL_free(a->canon_enc); + OPENSSL_free(a); + *pval = NULL; +} + +static void local_sk_X509_NAME_ENTRY_free(STACK_OF(X509_NAME_ENTRY) *ne) +{ + sk_X509_NAME_ENTRY_free(ne); +} + +static void local_sk_X509_NAME_ENTRY_pop_free(STACK_OF(X509_NAME_ENTRY) *ne) +{ + sk_X509_NAME_ENTRY_pop_free(ne, X509_NAME_ENTRY_free); +} + +static int x509_name_ex_d2i(ASN1_VALUE **val, + const unsigned char **in, long len, + const ASN1_ITEM *it, int tag, int aclass, + char opt, ASN1_TLC *ctx) +{ + const unsigned char *p = *in, *q; + union { + STACK_OF(STACK_OF_X509_NAME_ENTRY) *s; + ASN1_VALUE *a; + } intname = { + NULL + }; + union { + X509_NAME *x; + ASN1_VALUE *a; + } nm = { + NULL + }; + size_t i, j; + int ret; + STACK_OF(X509_NAME_ENTRY) *entries; + X509_NAME_ENTRY *entry; + /* Bound the size of an X509_NAME we are willing to parse. */ + if (len > X509_NAME_MAX) { + len = X509_NAME_MAX; + } + q = p; + + /* Get internal representation of Name */ + ret = ASN1_item_ex_d2i(&intname.a, + &p, len, ASN1_ITEM_rptr(X509_NAME_INTERNAL), + tag, aclass, opt, ctx); + + if (ret <= 0) + return ret; + + if (*val) + x509_name_ex_free(val, NULL); + /* We've decoded it: now cache encoding */ + if (!x509_name_ex_new(&nm.a, NULL) || !BUF_MEM_grow(nm.x->bytes, p - q)) { + sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s, + local_sk_X509_NAME_ENTRY_pop_free); + goto err; + } + memcpy(nm.x->bytes->data, q, p - q); + + /* Convert internal representation to X509_NAME structure */ + for (i = 0; i < sk_STACK_OF_X509_NAME_ENTRY_num(intname.s); i++) { + entries = sk_STACK_OF_X509_NAME_ENTRY_value(intname.s, i); + for (j = 0; j < sk_X509_NAME_ENTRY_num(entries); j++) { + entry = sk_X509_NAME_ENTRY_value(entries, j); + entry->set = i; + if (!sk_X509_NAME_ENTRY_push(nm.x->entries, entry)) + goto err; + } + sk_X509_NAME_ENTRY_free(entries); + } + sk_STACK_OF_X509_NAME_ENTRY_free(intname.s); + ret = x509_name_canon(nm.x); + if (!ret) + goto err; + nm.x->modified = 0; + *val = nm.a; + *in = p; + return ret; + err: + if (nm.x != NULL) + X509_NAME_free(nm.x); + OPENSSL_PUT_ERROR(X509, ERR_R_ASN1_LIB); + return 0; +} + +static int x509_name_ex_i2d(ASN1_VALUE **val, unsigned char **out, + const ASN1_ITEM *it, int tag, int aclass) +{ + int ret; + X509_NAME *a = (X509_NAME *)*val; + if (a->modified) { + ret = x509_name_encode(a); + if (ret < 0) + return ret; + ret = x509_name_canon(a); + if (ret < 0) + return ret; + } + ret = a->bytes->length; + if (out != NULL) { + memcpy(*out, a->bytes->data, ret); + *out += ret; + } + return ret; +} + +static int x509_name_encode(X509_NAME *a) +{ + union { + STACK_OF(STACK_OF_X509_NAME_ENTRY) *s; + ASN1_VALUE *a; + } intname = { + NULL + }; + int len; + unsigned char *p; + STACK_OF(X509_NAME_ENTRY) *entries = NULL; + X509_NAME_ENTRY *entry; + int set = -1; + size_t i; + intname.s = sk_STACK_OF_X509_NAME_ENTRY_new_null(); + if (!intname.s) + goto memerr; + for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) { + entry = sk_X509_NAME_ENTRY_value(a->entries, i); + if (entry->set != set) { + entries = sk_X509_NAME_ENTRY_new_null(); + if (!entries) + goto memerr; + if (!sk_STACK_OF_X509_NAME_ENTRY_push(intname.s, entries)) + goto memerr; + set = entry->set; + } + if (!sk_X509_NAME_ENTRY_push(entries, entry)) + goto memerr; + } + len = ASN1_item_ex_i2d(&intname.a, NULL, + ASN1_ITEM_rptr(X509_NAME_INTERNAL), -1, -1); + if (!BUF_MEM_grow(a->bytes, len)) + goto memerr; + p = (unsigned char *)a->bytes->data; + ASN1_item_ex_i2d(&intname.a, + &p, ASN1_ITEM_rptr(X509_NAME_INTERNAL), -1, -1); + sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s, + local_sk_X509_NAME_ENTRY_free); + a->modified = 0; + return len; + memerr: + sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s, + local_sk_X509_NAME_ENTRY_free); + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + return -1; +} + +/* + * This function generates the canonical encoding of the Name structure. In + * it all strings are converted to UTF8, leading, trailing and multiple + * spaces collapsed, converted to lower case and the leading SEQUENCE header + * removed. In future we could also normalize the UTF8 too. By doing this + * comparison of Name structures can be rapidly perfomed by just using + * memcmp() of the canonical encoding. By omitting the leading SEQUENCE name + * constraints of type dirName can also be checked with a simple memcmp(). + */ + +static int x509_name_canon(X509_NAME *a) +{ + unsigned char *p; + STACK_OF(STACK_OF_X509_NAME_ENTRY) *intname = NULL; + STACK_OF(X509_NAME_ENTRY) *entries = NULL; + X509_NAME_ENTRY *entry, *tmpentry = NULL; + int set = -1, ret = 0; + size_t i; + + if (a->canon_enc) { + OPENSSL_free(a->canon_enc); + a->canon_enc = NULL; + } + /* Special case: empty X509_NAME => null encoding */ + if (sk_X509_NAME_ENTRY_num(a->entries) == 0) { + a->canon_enclen = 0; + return 1; + } + intname = sk_STACK_OF_X509_NAME_ENTRY_new_null(); + if (!intname) + goto err; + for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) { + entry = sk_X509_NAME_ENTRY_value(a->entries, i); + if (entry->set != set) { + entries = sk_X509_NAME_ENTRY_new_null(); + if (!entries) + goto err; + if (!sk_STACK_OF_X509_NAME_ENTRY_push(intname, entries)) { + sk_X509_NAME_ENTRY_free(entries); + goto err; + } + set = entry->set; + } + tmpentry = X509_NAME_ENTRY_new(); + if (tmpentry == NULL) + goto err; + tmpentry->object = OBJ_dup(entry->object); + if (!asn1_string_canon(tmpentry->value, entry->value)) + goto err; + if (!sk_X509_NAME_ENTRY_push(entries, tmpentry)) + goto err; + tmpentry = NULL; + } + + /* Finally generate encoding */ + + a->canon_enclen = i2d_name_canon(intname, NULL); + + p = OPENSSL_malloc(a->canon_enclen); + + if (!p) + goto err; + + a->canon_enc = p; + + i2d_name_canon(intname, &p); + + ret = 1; + + err: + + if (tmpentry) + X509_NAME_ENTRY_free(tmpentry); + if (intname) + sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname, + local_sk_X509_NAME_ENTRY_pop_free); + return ret; +} + +/* Bitmap of all the types of string that will be canonicalized. */ + +#define ASN1_MASK_CANON \ + (B_ASN1_UTF8STRING | B_ASN1_BMPSTRING | B_ASN1_UNIVERSALSTRING \ + | B_ASN1_PRINTABLESTRING | B_ASN1_T61STRING | B_ASN1_IA5STRING \ + | B_ASN1_VISIBLESTRING) + +static int asn1_string_canon(ASN1_STRING *out, ASN1_STRING *in) +{ + unsigned char *to, *from; + int len, i; + + /* If type not in bitmask just copy string across */ + if (!(ASN1_tag2bit(in->type) & ASN1_MASK_CANON)) { + if (!ASN1_STRING_copy(out, in)) + return 0; + return 1; + } + + out->type = V_ASN1_UTF8STRING; + out->length = ASN1_STRING_to_UTF8(&out->data, in); + if (out->length == -1) + return 0; + + to = out->data; + from = to; + + len = out->length; + + /* + * Convert string in place to canonical form. Ultimately we may need to + * handle a wider range of characters but for now ignore anything with + * MSB set and rely on the isspace() and tolower() functions. + */ + + /* Ignore leading spaces */ + while ((len > 0) && !(*from & 0x80) && isspace(*from)) { + from++; + len--; + } + + to = from + len; + + /* Ignore trailing spaces */ + while ((len > 0) && !(to[-1] & 0x80) && isspace(to[-1])) { + to--; + len--; + } + + to = out->data; + + i = 0; + while (i < len) { + /* If MSB set just copy across */ + if (*from & 0x80) { + *to++ = *from++; + i++; + } + /* Collapse multiple spaces */ + else if (isspace(*from)) { + /* Copy one space across */ + *to++ = ' '; + /* + * Ignore subsequent spaces. Note: don't need to check len here + * because we know the last character is a non-space so we can't + * overflow. + */ + do { + from++; + i++; + } + while (!(*from & 0x80) && isspace(*from)); + } else { + *to++ = tolower(*from); + from++; + i++; + } + } + + out->length = to - out->data; + + return 1; + +} + +static int i2d_name_canon(STACK_OF(STACK_OF_X509_NAME_ENTRY) * _intname, + unsigned char **in) +{ + int len, ltmp; + size_t i; + ASN1_VALUE *v; + STACK_OF(ASN1_VALUE) *intname = (STACK_OF(ASN1_VALUE) *)_intname; + + len = 0; + for (i = 0; i < sk_ASN1_VALUE_num(intname); i++) { + v = sk_ASN1_VALUE_value(intname, i); + ltmp = ASN1_item_ex_i2d(&v, in, + ASN1_ITEM_rptr(X509_NAME_ENTRIES), -1, -1); + if (ltmp < 0) + return ltmp; + len += ltmp; + } + return len; +} + +int X509_NAME_set(X509_NAME **xn, X509_NAME *name) +{ + X509_NAME *in; + + if (!xn || !name) + return (0); + + if (*xn != name) { + in = X509_NAME_dup(name); + if (in != NULL) { + X509_NAME_free(*xn); + *xn = in; + } + } + return (*xn != NULL); +} + +IMPLEMENT_ASN1_SET_OF(X509_NAME_ENTRY) diff --git a/external/boringssl/crypto/x509/x_pkey.c b/external/boringssl/crypto/x509/x_pkey.c new file mode 100644 index 0000000000..fc445954e6 --- /dev/null +++ b/external/boringssl/crypto/x509/x_pkey.c @@ -0,0 +1,103 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include +#include +#include +#include + +X509_PKEY *X509_PKEY_new(void) +{ + X509_PKEY *ret = OPENSSL_malloc(sizeof(X509_PKEY)); + if (ret == NULL) { + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + goto err; + } + memset(ret, 0, sizeof(X509_PKEY)); + + ret->enc_algor = X509_ALGOR_new(); + if (ret->enc_algor == NULL) + goto err; + ret->enc_pkey = M_ASN1_OCTET_STRING_new(); + if (ret->enc_pkey == NULL) + goto err; + return ret; + + err: + if (ret != NULL) + X509_PKEY_free(ret); + return NULL; +} + +void X509_PKEY_free(X509_PKEY *x) +{ + if (x == NULL) + return; + + if (x->enc_algor != NULL) + X509_ALGOR_free(x->enc_algor); + if (x->enc_pkey != NULL) + M_ASN1_OCTET_STRING_free(x->enc_pkey); + if (x->dec_pkey != NULL) + EVP_PKEY_free(x->dec_pkey); + if ((x->key_data != NULL) && (x->key_free)) + OPENSSL_free(x->key_data); + OPENSSL_free(x); +} diff --git a/external/boringssl/crypto/x509/x_pubkey.c b/external/boringssl/crypto/x509/x_pubkey.c new file mode 100644 index 0000000000..23534b2bfe --- /dev/null +++ b/external/boringssl/crypto/x509/x_pubkey.c @@ -0,0 +1,366 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../internal.h" + +/* Minor tweak to operation: free up EVP_PKEY */ +static int pubkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, + void *exarg) +{ + if (operation == ASN1_OP_FREE_POST) { + X509_PUBKEY *pubkey = (X509_PUBKEY *)*pval; + EVP_PKEY_free(pubkey->pkey); + } + return 1; +} + +ASN1_SEQUENCE_cb(X509_PUBKEY, pubkey_cb) = { + ASN1_SIMPLE(X509_PUBKEY, algor, X509_ALGOR), + ASN1_SIMPLE(X509_PUBKEY, public_key, ASN1_BIT_STRING) +} ASN1_SEQUENCE_END_cb(X509_PUBKEY, X509_PUBKEY) + +IMPLEMENT_ASN1_FUNCTIONS(X509_PUBKEY) + +int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey) +{ + X509_PUBKEY *pk = NULL; + uint8_t *spki = NULL; + size_t spki_len; + + if (x == NULL) + return (0); + + CBB cbb; + if (!CBB_init(&cbb, 0) || + !EVP_marshal_public_key(&cbb, pkey) || + !CBB_finish(&cbb, &spki, &spki_len) || + spki_len > LONG_MAX) { + CBB_cleanup(&cbb); + OPENSSL_PUT_ERROR(X509, X509_R_PUBLIC_KEY_ENCODE_ERROR); + goto error; + } + + const uint8_t *p = spki; + pk = d2i_X509_PUBKEY(NULL, &p, (long)spki_len); + if (pk == NULL || p != spki + spki_len) { + OPENSSL_PUT_ERROR(X509, X509_R_PUBLIC_KEY_DECODE_ERROR); + goto error; + } + + OPENSSL_free(spki); + X509_PUBKEY_free(*x); + *x = pk; + + return 1; + error: + X509_PUBKEY_free(pk); + OPENSSL_free(spki); + return 0; +} + +/* g_pubkey_lock is used to protect the initialisation of the |pkey| member of + * |X509_PUBKEY| objects. Really |X509_PUBKEY| should have a |CRYPTO_once_t| + * inside it for this, but |CRYPTO_once_t| is private and |X509_PUBKEY| is + * not. */ +static struct CRYPTO_STATIC_MUTEX g_pubkey_lock = CRYPTO_STATIC_MUTEX_INIT; + +EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key) +{ + EVP_PKEY *ret = NULL; + uint8_t *spki = NULL; + + if (key == NULL) + goto error; + + CRYPTO_STATIC_MUTEX_lock_read(&g_pubkey_lock); + if (key->pkey != NULL) { + CRYPTO_STATIC_MUTEX_unlock_read(&g_pubkey_lock); + return EVP_PKEY_up_ref(key->pkey); + } + CRYPTO_STATIC_MUTEX_unlock_read(&g_pubkey_lock); + + /* Re-encode the |X509_PUBKEY| to DER and parse it. */ + int spki_len = i2d_X509_PUBKEY(key, &spki); + if (spki_len < 0) { + goto error; + } + CBS cbs; + CBS_init(&cbs, spki, (size_t)spki_len); + ret = EVP_parse_public_key(&cbs); + if (ret == NULL || CBS_len(&cbs) != 0) { + OPENSSL_PUT_ERROR(X509, X509_R_PUBLIC_KEY_DECODE_ERROR); + goto error; + } + + /* Check to see if another thread set key->pkey first */ + CRYPTO_STATIC_MUTEX_lock_write(&g_pubkey_lock); + if (key->pkey) { + CRYPTO_STATIC_MUTEX_unlock_write(&g_pubkey_lock); + EVP_PKEY_free(ret); + ret = key->pkey; + } else { + key->pkey = ret; + CRYPTO_STATIC_MUTEX_unlock_write(&g_pubkey_lock); + } + + OPENSSL_free(spki); + return EVP_PKEY_up_ref(ret); + + error: + OPENSSL_free(spki); + EVP_PKEY_free(ret); + return NULL; +} + +/* + * Now two pseudo ASN1 routines that take an EVP_PKEY structure and encode or + * decode as X509_PUBKEY + */ + +EVP_PKEY *d2i_PUBKEY(EVP_PKEY **a, const unsigned char **pp, long length) +{ + X509_PUBKEY *xpk; + EVP_PKEY *pktmp; + xpk = d2i_X509_PUBKEY(NULL, pp, length); + if (!xpk) + return NULL; + pktmp = X509_PUBKEY_get(xpk); + X509_PUBKEY_free(xpk); + if (!pktmp) + return NULL; + if (a) { + EVP_PKEY_free(*a); + *a = pktmp; + } + return pktmp; +} + +int i2d_PUBKEY(const EVP_PKEY *a, unsigned char **pp) +{ + X509_PUBKEY *xpk = NULL; + int ret; + if (!a) + return 0; + if (!X509_PUBKEY_set(&xpk, (EVP_PKEY *)a)) + return 0; + ret = i2d_X509_PUBKEY(xpk, pp); + X509_PUBKEY_free(xpk); + return ret; +} + +/* + * The following are equivalents but which return RSA and DSA keys + */ +RSA *d2i_RSA_PUBKEY(RSA **a, const unsigned char **pp, long length) +{ + EVP_PKEY *pkey; + RSA *key; + const unsigned char *q; + q = *pp; + pkey = d2i_PUBKEY(NULL, &q, length); + if (!pkey) + return NULL; + key = EVP_PKEY_get1_RSA(pkey); + EVP_PKEY_free(pkey); + if (!key) + return NULL; + *pp = q; + if (a) { + RSA_free(*a); + *a = key; + } + return key; +} + +int i2d_RSA_PUBKEY(const RSA *a, unsigned char **pp) +{ + EVP_PKEY *pktmp; + int ret; + if (!a) + return 0; + pktmp = EVP_PKEY_new(); + if (!pktmp) { + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + return 0; + } + EVP_PKEY_set1_RSA(pktmp, (RSA *)a); + ret = i2d_PUBKEY(pktmp, pp); + EVP_PKEY_free(pktmp); + return ret; +} + +#ifndef OPENSSL_NO_DSA +DSA *d2i_DSA_PUBKEY(DSA **a, const unsigned char **pp, long length) +{ + EVP_PKEY *pkey; + DSA *key; + const unsigned char *q; + q = *pp; + pkey = d2i_PUBKEY(NULL, &q, length); + if (!pkey) + return NULL; + key = EVP_PKEY_get1_DSA(pkey); + EVP_PKEY_free(pkey); + if (!key) + return NULL; + *pp = q; + if (a) { + DSA_free(*a); + *a = key; + } + return key; +} + +int i2d_DSA_PUBKEY(const DSA *a, unsigned char **pp) +{ + EVP_PKEY *pktmp; + int ret; + if (!a) + return 0; + pktmp = EVP_PKEY_new(); + if (!pktmp) { + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + return 0; + } + EVP_PKEY_set1_DSA(pktmp, (DSA *)a); + ret = i2d_PUBKEY(pktmp, pp); + EVP_PKEY_free(pktmp); + return ret; +} +#endif + +EC_KEY *d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp, long length) +{ + EVP_PKEY *pkey; + EC_KEY *key; + const unsigned char *q; + q = *pp; + pkey = d2i_PUBKEY(NULL, &q, length); + if (!pkey) + return (NULL); + key = EVP_PKEY_get1_EC_KEY(pkey); + EVP_PKEY_free(pkey); + if (!key) + return (NULL); + *pp = q; + if (a) { + EC_KEY_free(*a); + *a = key; + } + return (key); +} + +int i2d_EC_PUBKEY(const EC_KEY *a, unsigned char **pp) +{ + EVP_PKEY *pktmp; + int ret; + if (!a) + return (0); + if ((pktmp = EVP_PKEY_new()) == NULL) { + OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); + return (0); + } + EVP_PKEY_set1_EC_KEY(pktmp, (EC_KEY *)a); + ret = i2d_PUBKEY(pktmp, pp); + EVP_PKEY_free(pktmp); + return (ret); +} + +int X509_PUBKEY_set0_param(X509_PUBKEY *pub, const ASN1_OBJECT *aobj, + int ptype, void *pval, + unsigned char *penc, int penclen) +{ + if (!X509_ALGOR_set0(pub->algor, aobj, ptype, pval)) + return 0; + if (penc) { + if (pub->public_key->data) + OPENSSL_free(pub->public_key->data); + pub->public_key->data = penc; + pub->public_key->length = penclen; + /* Set number of unused bits to zero */ + pub->public_key->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); + pub->public_key->flags |= ASN1_STRING_FLAG_BITS_LEFT; + } + return 1; +} + +int X509_PUBKEY_get0_param(ASN1_OBJECT **ppkalg, + const unsigned char **pk, int *ppklen, + X509_ALGOR **pa, X509_PUBKEY *pub) +{ + if (ppkalg) + *ppkalg = pub->algor->algorithm; + if (pk) { + *pk = pub->public_key->data; + *ppklen = pub->public_key->length; + } + if (pa) + *pa = pub->algor; + return 1; +} diff --git a/external/boringssl/crypto/x509/x_req.c b/external/boringssl/crypto/x509/x_req.c new file mode 100644 index 0000000000..5dfe19e5d8 --- /dev/null +++ b/external/boringssl/crypto/x509/x_req.c @@ -0,0 +1,109 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include +#include + +/* + * X509_REQ_INFO is handled in an unusual way to get round invalid encodings. + * Some broken certificate requests don't encode the attributes field if it + * is empty. This is in violation of PKCS#10 but we need to tolerate it. We + * do this by making the attributes field OPTIONAL then using the callback to + * initialise it to an empty STACK. This means that the field will be + * correctly encoded unless we NULL out the field. As a result we no longer + * need the req_kludge field because the information is now contained in the + * attributes field: 1. If it is NULL then it's the invalid omission. 2. If + * it is empty it is the correct encoding. 3. If it is not empty then some + * attributes are present. + */ + +static int rinf_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, + void *exarg) +{ + X509_REQ_INFO *rinf = (X509_REQ_INFO *)*pval; + + if (operation == ASN1_OP_NEW_POST) { + rinf->attributes = sk_X509_ATTRIBUTE_new_null(); + if (!rinf->attributes) + return 0; + } + return 1; +} + +ASN1_SEQUENCE_enc(X509_REQ_INFO, enc, rinf_cb) = { + ASN1_SIMPLE(X509_REQ_INFO, version, ASN1_INTEGER), + ASN1_SIMPLE(X509_REQ_INFO, subject, X509_NAME), + ASN1_SIMPLE(X509_REQ_INFO, pubkey, X509_PUBKEY), + /* This isn't really OPTIONAL but it gets round invalid + * encodings + */ + ASN1_IMP_SET_OF_OPT(X509_REQ_INFO, attributes, X509_ATTRIBUTE, 0) +} ASN1_SEQUENCE_END_enc(X509_REQ_INFO, X509_REQ_INFO) + +IMPLEMENT_ASN1_FUNCTIONS(X509_REQ_INFO) + +ASN1_SEQUENCE_ref(X509_REQ, 0) = { + ASN1_SIMPLE(X509_REQ, req_info, X509_REQ_INFO), + ASN1_SIMPLE(X509_REQ, sig_alg, X509_ALGOR), + ASN1_SIMPLE(X509_REQ, signature, ASN1_BIT_STRING) +} ASN1_SEQUENCE_END_ref(X509_REQ, X509_REQ) + +IMPLEMENT_ASN1_FUNCTIONS(X509_REQ) + +IMPLEMENT_ASN1_DUP_FUNCTION(X509_REQ) diff --git a/external/boringssl/crypto/x509/x_sig.c b/external/boringssl/crypto/x509/x_sig.c new file mode 100644 index 0000000000..e18024a72c --- /dev/null +++ b/external/boringssl/crypto/x509/x_sig.c @@ -0,0 +1,69 @@ +/* crypto/asn1/x_sig.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + + +ASN1_SEQUENCE(X509_SIG) = { + ASN1_SIMPLE(X509_SIG, algor, X509_ALGOR), + ASN1_SIMPLE(X509_SIG, digest, ASN1_OCTET_STRING) +} ASN1_SEQUENCE_END(X509_SIG) + +IMPLEMENT_ASN1_FUNCTIONS(X509_SIG) diff --git a/external/boringssl/crypto/x509/x_spki.c b/external/boringssl/crypto/x509/x_spki.c new file mode 100644 index 0000000000..86da6ddf1b --- /dev/null +++ b/external/boringssl/crypto/x509/x_spki.c @@ -0,0 +1,80 @@ +/* crypto/asn1/x_spki.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + + /* + * This module was send to me my Pat Richards who wrote it. + * It is under my Copyright with his permission. + */ + +#include +#include + + +ASN1_SEQUENCE(NETSCAPE_SPKAC) = { + ASN1_SIMPLE(NETSCAPE_SPKAC, pubkey, X509_PUBKEY), + ASN1_SIMPLE(NETSCAPE_SPKAC, challenge, ASN1_IA5STRING) +} ASN1_SEQUENCE_END(NETSCAPE_SPKAC) + +IMPLEMENT_ASN1_FUNCTIONS(NETSCAPE_SPKAC) + +ASN1_SEQUENCE(NETSCAPE_SPKI) = { + ASN1_SIMPLE(NETSCAPE_SPKI, spkac, NETSCAPE_SPKAC), + ASN1_SIMPLE(NETSCAPE_SPKI, sig_algor, X509_ALGOR), + ASN1_SIMPLE(NETSCAPE_SPKI, signature, ASN1_BIT_STRING) +} ASN1_SEQUENCE_END(NETSCAPE_SPKI) + +IMPLEMENT_ASN1_FUNCTIONS(NETSCAPE_SPKI) diff --git a/external/boringssl/crypto/x509/x_val.c b/external/boringssl/crypto/x509/x_val.c new file mode 100644 index 0000000000..ad4f7e140a --- /dev/null +++ b/external/boringssl/crypto/x509/x_val.c @@ -0,0 +1,69 @@ +/* crypto/asn1/x_val.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + + +ASN1_SEQUENCE(X509_VAL) = { + ASN1_SIMPLE(X509_VAL, notBefore, ASN1_TIME), + ASN1_SIMPLE(X509_VAL, notAfter, ASN1_TIME) +} ASN1_SEQUENCE_END(X509_VAL) + +IMPLEMENT_ASN1_FUNCTIONS(X509_VAL) diff --git a/external/boringssl/crypto/x509/x_x509.c b/external/boringssl/crypto/x509/x_x509.c new file mode 100644 index 0000000000..e21258d4fa --- /dev/null +++ b/external/boringssl/crypto/x509/x_x509.c @@ -0,0 +1,290 @@ +/* crypto/asn1/x_x509.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "../internal.h" + +static CRYPTO_EX_DATA_CLASS g_ex_data_class = CRYPTO_EX_DATA_CLASS_INIT; + +ASN1_SEQUENCE_enc(X509_CINF, enc, 0) = { + ASN1_EXP_OPT(X509_CINF, version, ASN1_INTEGER, 0), + ASN1_SIMPLE(X509_CINF, serialNumber, ASN1_INTEGER), + ASN1_SIMPLE(X509_CINF, signature, X509_ALGOR), + ASN1_SIMPLE(X509_CINF, issuer, X509_NAME), + ASN1_SIMPLE(X509_CINF, validity, X509_VAL), + ASN1_SIMPLE(X509_CINF, subject, X509_NAME), + ASN1_SIMPLE(X509_CINF, key, X509_PUBKEY), + ASN1_IMP_OPT(X509_CINF, issuerUID, ASN1_BIT_STRING, 1), + ASN1_IMP_OPT(X509_CINF, subjectUID, ASN1_BIT_STRING, 2), + ASN1_EXP_SEQUENCE_OF_OPT(X509_CINF, extensions, X509_EXTENSION, 3) +} ASN1_SEQUENCE_END_enc(X509_CINF, X509_CINF) + +IMPLEMENT_ASN1_FUNCTIONS(X509_CINF) +/* X509 top level structure needs a bit of customisation */ + +extern void policy_cache_free(X509_POLICY_CACHE *cache); + +static int x509_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, + void *exarg) +{ + X509 *ret = (X509 *)*pval; + + switch (operation) { + + case ASN1_OP_NEW_POST: + ret->valid = 0; + ret->name = NULL; + ret->ex_flags = 0; + ret->ex_pathlen = -1; + ret->skid = NULL; + ret->akid = NULL; + ret->aux = NULL; + ret->crldp = NULL; + CRYPTO_new_ex_data(&ret->ex_data); + break; + + case ASN1_OP_D2I_POST: + if (ret->name != NULL) + OPENSSL_free(ret->name); + ret->name = X509_NAME_oneline(ret->cert_info->subject, NULL, 0); + break; + + case ASN1_OP_FREE_POST: + CRYPTO_free_ex_data(&g_ex_data_class, ret, &ret->ex_data); + X509_CERT_AUX_free(ret->aux); + ASN1_OCTET_STRING_free(ret->skid); + AUTHORITY_KEYID_free(ret->akid); + CRL_DIST_POINTS_free(ret->crldp); + policy_cache_free(ret->policy_cache); + GENERAL_NAMES_free(ret->altname); + NAME_CONSTRAINTS_free(ret->nc); + + if (ret->name != NULL) + OPENSSL_free(ret->name); + break; + + } + + return 1; + +} + +ASN1_SEQUENCE_ref(X509, x509_cb) = { + ASN1_SIMPLE(X509, cert_info, X509_CINF), + ASN1_SIMPLE(X509, sig_alg, X509_ALGOR), + ASN1_SIMPLE(X509, signature, ASN1_BIT_STRING) +} ASN1_SEQUENCE_END_ref(X509, X509) + +IMPLEMENT_ASN1_FUNCTIONS(X509) + +IMPLEMENT_ASN1_DUP_FUNCTION(X509) + +X509 *X509_up_ref(X509 *x) +{ + CRYPTO_refcount_inc(&x->references); + return x; +} + +int X509_get_ex_new_index(long argl, void *argp, CRYPTO_EX_unused * unused, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) +{ + int index; + if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp, + dup_func, free_func)) { + return -1; + } + return index; +} + +int X509_set_ex_data(X509 *r, int idx, void *arg) +{ + return (CRYPTO_set_ex_data(&r->ex_data, idx, arg)); +} + +void *X509_get_ex_data(X509 *r, int idx) +{ + return (CRYPTO_get_ex_data(&r->ex_data, idx)); +} + +/* + * X509_AUX ASN1 routines. X509_AUX is the name given to a certificate with + * extra info tagged on the end. Since these functions set how a certificate + * is trusted they should only be used when the certificate comes from a + * reliable source such as local storage. + */ + +X509 *d2i_X509_AUX(X509 **a, const unsigned char **pp, long length) +{ + const unsigned char *q = *pp; + X509 *ret; + int freeret = 0; + + if (!a || *a == NULL) + freeret = 1; + ret = d2i_X509(a, &q, length); + /* If certificate unreadable then forget it */ + if (!ret) + return NULL; + /* update length */ + length -= q - *pp; + /* Parse auxiliary information if there is any. */ + if (length > 0 && !d2i_X509_CERT_AUX(&ret->aux, &q, length)) + goto err; + *pp = q; + return ret; + err: + if (freeret) { + X509_free(ret); + if (a) + *a = NULL; + } + return NULL; +} + +/* + * Serialize trusted certificate to *pp or just return the required buffer + * length if pp == NULL. We ultimately want to avoid modifying *pp in the + * error path, but that depends on similar hygiene in lower-level functions. + * Here we avoid compounding the problem. + */ +static int i2d_x509_aux_internal(X509 *a, unsigned char **pp) +{ + int length, tmplen; + unsigned char *start = pp != NULL ? *pp : NULL; + + assert(pp == NULL || *pp != NULL); + + /* + * This might perturb *pp on error, but fixing that belongs in i2d_X509() + * not here. It should be that if a == NULL length is zero, but we check + * both just in case. + */ + length = i2d_X509(a, pp); + if (length <= 0 || a == NULL) { + return length; + } + + tmplen = i2d_X509_CERT_AUX(a->aux, pp); + if (tmplen < 0) { + if (start != NULL) + *pp = start; + return tmplen; + } + length += tmplen; + + return length; +} + +/* + * Serialize trusted certificate to *pp, or just return the required buffer + * length if pp == NULL. + * + * When pp is not NULL, but *pp == NULL, we allocate the buffer, but since + * we're writing two ASN.1 objects back to back, we can't have i2d_X509() do + * the allocation, nor can we allow i2d_X509_CERT_AUX() to increment the + * allocated buffer. + */ +int i2d_X509_AUX(X509 *a, unsigned char **pp) +{ + int length; + unsigned char *tmp; + + /* Buffer provided by caller */ + if (pp == NULL || *pp != NULL) + return i2d_x509_aux_internal(a, pp); + + /* Obtain the combined length */ + if ((length = i2d_x509_aux_internal(a, NULL)) <= 0) + return length; + + /* Allocate requisite combined storage */ + *pp = tmp = OPENSSL_malloc(length); + if (tmp == NULL) + return -1; /* Push error onto error stack? */ + + /* Encode, but keep *pp at the originally malloced pointer */ + length = i2d_x509_aux_internal(a, &tmp); + if (length <= 0) { + OPENSSL_free(*pp); + *pp = NULL; + } + return length; +} + +void X509_get0_signature(ASN1_BIT_STRING **psig, X509_ALGOR **palg, + const X509 *x) +{ + if (psig) + *psig = x->signature; + if (palg) + *palg = x->sig_alg; +} + +int X509_get_signature_nid(const X509 *x) +{ + return OBJ_obj2nid(x->sig_alg->algorithm); +} diff --git a/external/boringssl/crypto/x509/x_x509a.c b/external/boringssl/crypto/x509/x_x509a.c new file mode 100644 index 0000000000..a63ee42241 --- /dev/null +++ b/external/boringssl/crypto/x509/x_x509a.c @@ -0,0 +1,205 @@ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project + * 1999. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include +#include +#include + +/* + * X509_CERT_AUX routines. These are used to encode additional user + * modifiable data about a certificate. This data is appended to the X509 + * encoding when the *_X509_AUX routines are used. This means that the + * "traditional" X509 routines will simply ignore the extra data. + */ + +static X509_CERT_AUX *aux_get(X509 *x); + +ASN1_SEQUENCE(X509_CERT_AUX) = { + ASN1_SEQUENCE_OF_OPT(X509_CERT_AUX, trust, ASN1_OBJECT), + ASN1_IMP_SEQUENCE_OF_OPT(X509_CERT_AUX, reject, ASN1_OBJECT, 0), + ASN1_OPT(X509_CERT_AUX, alias, ASN1_UTF8STRING), + ASN1_OPT(X509_CERT_AUX, keyid, ASN1_OCTET_STRING), + ASN1_IMP_SEQUENCE_OF_OPT(X509_CERT_AUX, other, X509_ALGOR, 1) +} ASN1_SEQUENCE_END(X509_CERT_AUX) + +IMPLEMENT_ASN1_FUNCTIONS(X509_CERT_AUX) + +static X509_CERT_AUX *aux_get(X509 *x) +{ + if (!x) + return NULL; + if (!x->aux && !(x->aux = X509_CERT_AUX_new())) + return NULL; + return x->aux; +} + +int X509_alias_set1(X509 *x, unsigned char *name, int len) +{ + X509_CERT_AUX *aux; + if (!name) { + if (!x || !x->aux || !x->aux->alias) + return 1; + ASN1_UTF8STRING_free(x->aux->alias); + x->aux->alias = NULL; + return 1; + } + if (!(aux = aux_get(x))) + return 0; + if (!aux->alias && !(aux->alias = ASN1_UTF8STRING_new())) + return 0; + return ASN1_STRING_set(aux->alias, name, len); +} + +int X509_keyid_set1(X509 *x, unsigned char *id, int len) +{ + X509_CERT_AUX *aux; + if (!id) { + if (!x || !x->aux || !x->aux->keyid) + return 1; + ASN1_OCTET_STRING_free(x->aux->keyid); + x->aux->keyid = NULL; + return 1; + } + if (!(aux = aux_get(x))) + return 0; + if (!aux->keyid && !(aux->keyid = ASN1_OCTET_STRING_new())) + return 0; + return ASN1_STRING_set(aux->keyid, id, len); +} + +unsigned char *X509_alias_get0(X509 *x, int *len) +{ + if (!x->aux || !x->aux->alias) + return NULL; + if (len) + *len = x->aux->alias->length; + return x->aux->alias->data; +} + +unsigned char *X509_keyid_get0(X509 *x, int *len) +{ + if (!x->aux || !x->aux->keyid) + return NULL; + if (len) + *len = x->aux->keyid->length; + return x->aux->keyid->data; +} + +int X509_add1_trust_object(X509 *x, ASN1_OBJECT *obj) +{ + ASN1_OBJECT *objtmp = OBJ_dup(obj); + if (objtmp == NULL) + goto err; + X509_CERT_AUX *aux = aux_get(x); + if (aux->trust == NULL) { + aux->trust = sk_ASN1_OBJECT_new_null(); + if (aux->trust == NULL) + goto err; + } + if (!sk_ASN1_OBJECT_push(aux->trust, objtmp)) + goto err; + return 1; + + err: + ASN1_OBJECT_free(objtmp); + return 0; +} + +int X509_add1_reject_object(X509 *x, ASN1_OBJECT *obj) +{ + ASN1_OBJECT *objtmp = OBJ_dup(obj); + if (objtmp == NULL) + goto err; + X509_CERT_AUX *aux = aux_get(x); + if (aux->reject == NULL) { + aux->reject = sk_ASN1_OBJECT_new_null(); + if (aux->reject == NULL) + goto err; + } + if (!sk_ASN1_OBJECT_push(aux->reject, objtmp)) + goto err; + return 1; + + err: + ASN1_OBJECT_free(objtmp); + return 0; +} + +void X509_trust_clear(X509 *x) +{ + if (x->aux && x->aux->trust) { + sk_ASN1_OBJECT_pop_free(x->aux->trust, ASN1_OBJECT_free); + x->aux->trust = NULL; + } +} + +void X509_reject_clear(X509 *x) +{ + if (x->aux && x->aux->reject) { + sk_ASN1_OBJECT_pop_free(x->aux->reject, ASN1_OBJECT_free); + x->aux->reject = NULL; + } +} + +ASN1_SEQUENCE(X509_CERT_PAIR) = { + ASN1_EXP_OPT(X509_CERT_PAIR, forward, X509, 0), + ASN1_EXP_OPT(X509_CERT_PAIR, reverse, X509, 1) +} ASN1_SEQUENCE_END(X509_CERT_PAIR) + +IMPLEMENT_ASN1_FUNCTIONS(X509_CERT_PAIR) diff --git a/external/boringssl/crypto/x509v3/CMakeLists.txt b/external/boringssl/crypto/x509v3/CMakeLists.txt new file mode 100644 index 0000000000..fb5b76b9aa --- /dev/null +++ b/external/boringssl/crypto/x509v3/CMakeLists.txt @@ -0,0 +1,68 @@ +include_directories(../../include) + +add_library( + x509v3 + + OBJECT + + # v3_addr.c - disabled by upstream by default. + # v3_asid.c - disabled by upstream by default. + # v3_ocsp.c - missing OCSP for now. + + pcy_cache.c + pcy_data.c + pcy_lib.c + pcy_map.c + pcy_node.c + pcy_tree.c + v3_akey.c + v3_akeya.c + v3_alt.c + v3_bcons.c + v3_bitst.c + v3_conf.c + v3_cpols.c + v3_crld.c + v3_enum.c + v3_extku.c + v3_genn.c + v3_ia5.c + v3_info.c + v3_int.c + v3_lib.c + v3_ncons.c + v3_pci.c + v3_pcia.c + v3_pcons.c + v3_pku.c + v3_pmaps.c + v3_prn.c + v3_purp.c + v3_skey.c + v3_sxnet.c + v3_utl.c +) + +if(ENABLE_TESTS) +add_executable( + v3name_test + + v3name_test.c + + $ +) + +target_link_libraries(v3name_test crypto) +add_dependencies(all_tests v3name_test) + +add_executable( + tab_test + + tab_test.c + + $ +) + +target_link_libraries(tab_test crypto) +add_dependencies(all_tests tab_test) +endif() diff --git a/external/boringssl/crypto/x509v3/ext_dat.h b/external/boringssl/crypto/x509v3/ext_dat.h new file mode 100644 index 0000000000..9ece19c50d --- /dev/null +++ b/external/boringssl/crypto/x509v3/ext_dat.h @@ -0,0 +1,135 @@ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project + * 1999. + */ +/* ==================================================================== + * Copyright (c) 1999-2004 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +/* This file contains a table of "standard" extensions */ + +extern const X509V3_EXT_METHOD v3_bcons, v3_nscert, v3_key_usage, v3_ext_ku; +extern const X509V3_EXT_METHOD v3_pkey_usage_period, v3_sxnet, v3_info, + v3_sinfo; +extern const X509V3_EXT_METHOD v3_ns_ia5_list[], v3_alt[], v3_skey_id, + v3_akey_id; +extern const X509V3_EXT_METHOD v3_crl_num, v3_crl_reason, v3_crl_invdate; +extern const X509V3_EXT_METHOD v3_delta_crl, v3_cpols, v3_crld, + v3_freshest_crl; +extern const X509V3_EXT_METHOD v3_ocsp_nonce, v3_ocsp_accresp, + v3_ocsp_acutoff; +extern const X509V3_EXT_METHOD v3_ocsp_crlid, v3_ocsp_nocheck, + v3_ocsp_serviceloc; +extern const X509V3_EXT_METHOD v3_crl_hold, v3_pci; +extern const X509V3_EXT_METHOD v3_policy_mappings, v3_policy_constraints; +extern const X509V3_EXT_METHOD v3_name_constraints, v3_inhibit_anyp, v3_idp; +extern const X509V3_EXT_METHOD v3_addr, v3_asid; + +/* + * This table will be searched using OBJ_bsearch so it *must* kept in order + * of the ext_nid values. + */ + +/* TODO(fork): OCSP support */ +#define OPENSSL_NO_OCSP + +static const X509V3_EXT_METHOD *const standard_exts[] = { + &v3_nscert, + &v3_ns_ia5_list[0], + &v3_ns_ia5_list[1], + &v3_ns_ia5_list[2], + &v3_ns_ia5_list[3], + &v3_ns_ia5_list[4], + &v3_ns_ia5_list[5], + &v3_ns_ia5_list[6], + &v3_skey_id, + &v3_key_usage, + &v3_pkey_usage_period, + &v3_alt[0], + &v3_alt[1], + &v3_bcons, + &v3_crl_num, + &v3_cpols, + &v3_akey_id, + &v3_crld, + &v3_ext_ku, + &v3_delta_crl, + &v3_crl_reason, +#ifndef OPENSSL_NO_OCSP + &v3_crl_invdate, +#endif + &v3_sxnet, + &v3_info, +#ifndef OPENSSL_NO_OCSP + &v3_ocsp_nonce, + &v3_ocsp_crlid, + &v3_ocsp_accresp, + &v3_ocsp_nocheck, + &v3_ocsp_acutoff, + &v3_ocsp_serviceloc, +#endif + &v3_sinfo, + &v3_policy_constraints, +#ifndef OPENSSL_NO_OCSP + &v3_crl_hold, +#endif + &v3_pci, + &v3_name_constraints, + &v3_policy_mappings, + &v3_inhibit_anyp, + &v3_idp, + &v3_alt[2], + &v3_freshest_crl, +}; + +/* Number of standard extensions */ + +#define STANDARD_EXTENSION_COUNT (sizeof(standard_exts)/sizeof(X509V3_EXT_METHOD *)) diff --git a/external/boringssl/crypto/x509v3/pcy_cache.c b/external/boringssl/crypto/x509v3/pcy_cache.c new file mode 100644 index 0000000000..b8a4be2740 --- /dev/null +++ b/external/boringssl/crypto/x509v3/pcy_cache.c @@ -0,0 +1,284 @@ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project + * 2004. + */ +/* ==================================================================== + * Copyright (c) 2004 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include +#include +#include +#include +#include + +#include "pcy_int.h" +#include "../internal.h" + +static int policy_data_cmp(const X509_POLICY_DATA **a, + const X509_POLICY_DATA **b); +static int policy_cache_set_int(long *out, ASN1_INTEGER *value); + +/* + * Set cache entry according to CertificatePolicies extension. Note: this + * destroys the passed CERTIFICATEPOLICIES structure. + */ + +static int policy_cache_create(X509 *x, + CERTIFICATEPOLICIES *policies, int crit) +{ + size_t i; + int ret = 0; + X509_POLICY_CACHE *cache = x->policy_cache; + X509_POLICY_DATA *data = NULL; + POLICYINFO *policy; + if (sk_POLICYINFO_num(policies) == 0) + goto bad_policy; + cache->data = sk_X509_POLICY_DATA_new(policy_data_cmp); + if (!cache->data) + goto bad_policy; + for (i = 0; i < sk_POLICYINFO_num(policies); i++) { + policy = sk_POLICYINFO_value(policies, i); + data = policy_data_new(policy, NULL, crit); + if (!data) + goto bad_policy; + /* + * Duplicate policy OIDs are illegal: reject if matches found. + */ + if (OBJ_obj2nid(data->valid_policy) == NID_any_policy) { + if (cache->anyPolicy) { + ret = -1; + goto bad_policy; + } + cache->anyPolicy = data; + } else if (sk_X509_POLICY_DATA_find(cache->data, NULL, data)) { + ret = -1; + goto bad_policy; + } else if (!sk_X509_POLICY_DATA_push(cache->data, data)) + goto bad_policy; + data = NULL; + } + ret = 1; + bad_policy: + if (ret == -1) + x->ex_flags |= EXFLAG_INVALID_POLICY; + if (data) + policy_data_free(data); + sk_POLICYINFO_pop_free(policies, POLICYINFO_free); + if (ret <= 0) { + sk_X509_POLICY_DATA_pop_free(cache->data, policy_data_free); + cache->data = NULL; + } + return ret; +} + +static int policy_cache_new(X509 *x) +{ + X509_POLICY_CACHE *cache; + ASN1_INTEGER *ext_any = NULL; + POLICY_CONSTRAINTS *ext_pcons = NULL; + CERTIFICATEPOLICIES *ext_cpols = NULL; + POLICY_MAPPINGS *ext_pmaps = NULL; + int i; + cache = OPENSSL_malloc(sizeof(X509_POLICY_CACHE)); + if (!cache) + return 0; + cache->anyPolicy = NULL; + cache->data = NULL; + cache->any_skip = -1; + cache->explicit_skip = -1; + cache->map_skip = -1; + + x->policy_cache = cache; + + /* + * Handle requireExplicitPolicy *first*. Need to process this even if we + * don't have any policies. + */ + ext_pcons = X509_get_ext_d2i(x, NID_policy_constraints, &i, NULL); + + if (!ext_pcons) { + if (i != -1) + goto bad_cache; + } else { + if (!ext_pcons->requireExplicitPolicy + && !ext_pcons->inhibitPolicyMapping) + goto bad_cache; + if (!policy_cache_set_int(&cache->explicit_skip, + ext_pcons->requireExplicitPolicy)) + goto bad_cache; + if (!policy_cache_set_int(&cache->map_skip, + ext_pcons->inhibitPolicyMapping)) + goto bad_cache; + } + + /* Process CertificatePolicies */ + + ext_cpols = X509_get_ext_d2i(x, NID_certificate_policies, &i, NULL); + /* + * If no CertificatePolicies extension or problem decoding then there is + * no point continuing because the valid policies will be NULL. + */ + if (!ext_cpols) { + /* If not absent some problem with extension */ + if (i != -1) + goto bad_cache; + return 1; + } + + i = policy_cache_create(x, ext_cpols, i); + + /* NB: ext_cpols freed by policy_cache_set_policies */ + + if (i <= 0) + return i; + + ext_pmaps = X509_get_ext_d2i(x, NID_policy_mappings, &i, NULL); + + if (!ext_pmaps) { + /* If not absent some problem with extension */ + if (i != -1) + goto bad_cache; + } else { + i = policy_cache_set_mapping(x, ext_pmaps); + if (i <= 0) + goto bad_cache; + } + + ext_any = X509_get_ext_d2i(x, NID_inhibit_any_policy, &i, NULL); + + if (!ext_any) { + if (i != -1) + goto bad_cache; + } else if (!policy_cache_set_int(&cache->any_skip, ext_any)) + goto bad_cache; + + if (0) { + bad_cache: + x->ex_flags |= EXFLAG_INVALID_POLICY; + } + + if (ext_pcons) + POLICY_CONSTRAINTS_free(ext_pcons); + + if (ext_any) + ASN1_INTEGER_free(ext_any); + + return 1; + +} + +void policy_cache_free(X509_POLICY_CACHE *cache) +{ + if (!cache) + return; + if (cache->anyPolicy) + policy_data_free(cache->anyPolicy); + if (cache->data) + sk_X509_POLICY_DATA_pop_free(cache->data, policy_data_free); + OPENSSL_free(cache); +} + +/* + * g_x509_policy_cache_lock is used to protect against concurrent calls to + * |policy_cache_new|. Ideally this would be done with a |CRYPTO_once_t| in + * the |X509| structure, but |CRYPTO_once_t| isn't public. + */ +static struct CRYPTO_STATIC_MUTEX g_x509_policy_cache_lock = + CRYPTO_STATIC_MUTEX_INIT; + +const X509_POLICY_CACHE *policy_cache_set(X509 *x) +{ + X509_POLICY_CACHE *cache; + + CRYPTO_STATIC_MUTEX_lock_read(&g_x509_policy_cache_lock); + cache = x->policy_cache; + CRYPTO_STATIC_MUTEX_unlock_read(&g_x509_policy_cache_lock); + + if (cache != NULL) + return cache; + + CRYPTO_STATIC_MUTEX_lock_write(&g_x509_policy_cache_lock); + if (x->policy_cache == NULL) + policy_cache_new(x); + cache = x->policy_cache; + CRYPTO_STATIC_MUTEX_unlock_write(&g_x509_policy_cache_lock); + + return cache; +} + +X509_POLICY_DATA *policy_cache_find_data(const X509_POLICY_CACHE *cache, + const ASN1_OBJECT *id) +{ + size_t idx; + X509_POLICY_DATA tmp; + + tmp.valid_policy = (ASN1_OBJECT *)id; + if (!sk_X509_POLICY_DATA_find(cache->data, &idx, &tmp)) + return NULL; + return sk_X509_POLICY_DATA_value(cache->data, idx); +} + +static int policy_data_cmp(const X509_POLICY_DATA **a, + const X509_POLICY_DATA **b) +{ + return OBJ_cmp((*a)->valid_policy, (*b)->valid_policy); +} + +static int policy_cache_set_int(long *out, ASN1_INTEGER *value) +{ + if (value == NULL) + return 1; + if (value->type == V_ASN1_NEG_INTEGER) + return 0; + *out = ASN1_INTEGER_get(value); + return 1; +} diff --git a/external/boringssl/crypto/x509v3/pcy_data.c b/external/boringssl/crypto/x509v3/pcy_data.c new file mode 100644 index 0000000000..498de4dd13 --- /dev/null +++ b/external/boringssl/crypto/x509v3/pcy_data.c @@ -0,0 +1,130 @@ +/* pcy_data.c */ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project + * 2004. + */ +/* ==================================================================== + * Copyright (c) 2004 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include +#include +#include +#include + +#include "pcy_int.h" + +/* Policy Node routines */ + +void policy_data_free(X509_POLICY_DATA *data) +{ + ASN1_OBJECT_free(data->valid_policy); + /* Don't free qualifiers if shared */ + if (!(data->flags & POLICY_DATA_FLAG_SHARED_QUALIFIERS)) + sk_POLICYQUALINFO_pop_free(data->qualifier_set, POLICYQUALINFO_free); + sk_ASN1_OBJECT_pop_free(data->expected_policy_set, ASN1_OBJECT_free); + OPENSSL_free(data); +} + +/* + * Create a data based on an existing policy. If 'id' is NULL use the oid in + * the policy, otherwise use 'id'. This behaviour covers the two types of + * data in RFC3280: data with from a CertificatePolcies extension and + * additional data with just the qualifiers of anyPolicy and ID from another + * source. + */ + +X509_POLICY_DATA *policy_data_new(POLICYINFO *policy, + const ASN1_OBJECT *cid, int crit) +{ + X509_POLICY_DATA *ret; + ASN1_OBJECT *id; + if (!policy && !cid) + return NULL; + if (cid) { + id = OBJ_dup(cid); + if (!id) + return NULL; + } else + id = NULL; + ret = OPENSSL_malloc(sizeof(X509_POLICY_DATA)); + if (!ret) + return NULL; + ret->expected_policy_set = sk_ASN1_OBJECT_new_null(); + if (!ret->expected_policy_set) { + OPENSSL_free(ret); + if (id) + ASN1_OBJECT_free(id); + return NULL; + } + + if (crit) + ret->flags = POLICY_DATA_FLAG_CRITICAL; + else + ret->flags = 0; + + if (id) + ret->valid_policy = id; + else { + ret->valid_policy = policy->policyid; + policy->policyid = NULL; + } + + if (policy) { + ret->qualifier_set = policy->qualifiers; + policy->qualifiers = NULL; + } else + ret->qualifier_set = NULL; + + return ret; +} diff --git a/external/boringssl/crypto/x509v3/pcy_int.h b/external/boringssl/crypto/x509v3/pcy_int.h new file mode 100644 index 0000000000..b5075f9edb --- /dev/null +++ b/external/boringssl/crypto/x509v3/pcy_int.h @@ -0,0 +1,217 @@ +/* pcy_int.h */ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project + * 2004. + */ +/* ==================================================================== + * Copyright (c) 2004 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +typedef struct X509_POLICY_DATA_st X509_POLICY_DATA; + +DECLARE_STACK_OF(X509_POLICY_DATA) + +/* Internal structures */ + +/* + * This structure and the field names correspond to the Policy 'node' of + * RFC3280. NB this structure contains no pointers to parent or child data: + * X509_POLICY_NODE contains that. This means that the main policy data can + * be kept static and cached with the certificate. + */ + +struct X509_POLICY_DATA_st { + unsigned int flags; + /* Policy OID and qualifiers for this data */ + ASN1_OBJECT *valid_policy; + STACK_OF(POLICYQUALINFO) *qualifier_set; + STACK_OF(ASN1_OBJECT) *expected_policy_set; +}; + +/* X509_POLICY_DATA flags values */ + +/* + * This flag indicates the structure has been mapped using a policy mapping + * extension. If policy mapping is not active its references get deleted. + */ + +#define POLICY_DATA_FLAG_MAPPED 0x1 + +/* + * This flag indicates the data doesn't correspond to a policy in Certificate + * Policies: it has been mapped to any policy. + */ + +#define POLICY_DATA_FLAG_MAPPED_ANY 0x2 + +/* AND with flags to see if any mapping has occurred */ + +#define POLICY_DATA_FLAG_MAP_MASK 0x3 + +/* qualifiers are shared and shouldn't be freed */ + +#define POLICY_DATA_FLAG_SHARED_QUALIFIERS 0x4 + +/* Parent node is an extra node and should be freed */ + +#define POLICY_DATA_FLAG_EXTRA_NODE 0x8 + +/* Corresponding CertificatePolicies is critical */ + +#define POLICY_DATA_FLAG_CRITICAL 0x10 + +/* This structure is cached with a certificate */ + +struct X509_POLICY_CACHE_st { + /* anyPolicy data or NULL if no anyPolicy */ + X509_POLICY_DATA *anyPolicy; + /* other policy data */ + STACK_OF(X509_POLICY_DATA) *data; + /* If InhibitAnyPolicy present this is its value or -1 if absent. */ + long any_skip; + /* + * If policyConstraints and requireExplicitPolicy present this is its + * value or -1 if absent. + */ + long explicit_skip; + /* + * If policyConstraints and policyMapping present this is its value or -1 + * if absent. + */ + long map_skip; +}; + +/* + * #define POLICY_CACHE_FLAG_CRITICAL POLICY_DATA_FLAG_CRITICAL + */ + +/* This structure represents the relationship between nodes */ + +struct X509_POLICY_NODE_st { + /* node data this refers to */ + const X509_POLICY_DATA *data; + /* Parent node */ + X509_POLICY_NODE *parent; + /* Number of child nodes */ + int nchild; +}; + +struct X509_POLICY_LEVEL_st { + /* Cert for this level */ + X509 *cert; + /* nodes at this level */ + STACK_OF(X509_POLICY_NODE) *nodes; + /* anyPolicy node */ + X509_POLICY_NODE *anyPolicy; + /* Extra data */ + /* + * STACK_OF(X509_POLICY_DATA) *extra_data; + */ + unsigned int flags; +}; + +struct X509_POLICY_TREE_st { + /* This is the tree 'level' data */ + X509_POLICY_LEVEL *levels; + int nlevel; + /* + * Extra policy data when additional nodes (not from the certificate) are + * required. + */ + STACK_OF(X509_POLICY_DATA) *extra_data; + /* This is the authority constained policy set */ + STACK_OF(X509_POLICY_NODE) *auth_policies; + STACK_OF(X509_POLICY_NODE) *user_policies; + unsigned int flags; +}; + +/* Set if anyPolicy present in user policies */ +#define POLICY_FLAG_ANY_POLICY 0x2 + +/* Useful macros */ + +#define node_data_critical(data) (data->flags & POLICY_DATA_FLAG_CRITICAL) +#define node_critical(node) node_data_critical(node->data) + +/* Internal functions */ + +X509_POLICY_DATA *policy_data_new(POLICYINFO *policy, const ASN1_OBJECT *id, + int crit); +void policy_data_free(X509_POLICY_DATA *data); + +X509_POLICY_DATA *policy_cache_find_data(const X509_POLICY_CACHE *cache, + const ASN1_OBJECT *id); +int policy_cache_set_mapping(X509 *x, POLICY_MAPPINGS *maps); + +STACK_OF(X509_POLICY_NODE) *policy_node_cmp_new(void); + +void policy_cache_init(void); + +void policy_cache_free(X509_POLICY_CACHE *cache); + +X509_POLICY_NODE *level_find_node(const X509_POLICY_LEVEL *level, + const X509_POLICY_NODE *parent, + const ASN1_OBJECT *id); + +X509_POLICY_NODE *tree_find_sk(STACK_OF(X509_POLICY_NODE) *sk, + const ASN1_OBJECT *id); + +X509_POLICY_NODE *level_add_node(X509_POLICY_LEVEL *level, + const X509_POLICY_DATA *data, + X509_POLICY_NODE *parent, + X509_POLICY_TREE *tree); +void policy_node_free(X509_POLICY_NODE *node); +int policy_node_match(const X509_POLICY_LEVEL *lvl, + const X509_POLICY_NODE *node, const ASN1_OBJECT *oid); + +const X509_POLICY_CACHE *policy_cache_set(X509 *x); diff --git a/external/boringssl/crypto/x509v3/pcy_lib.c b/external/boringssl/crypto/x509v3/pcy_lib.c new file mode 100644 index 0000000000..764f38f914 --- /dev/null +++ b/external/boringssl/crypto/x509v3/pcy_lib.c @@ -0,0 +1,164 @@ +/* pcy_lib.c */ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project + * 2004. + */ +/* ==================================================================== + * Copyright (c) 2004 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include +#include + +#include "pcy_int.h" + +/* accessor functions */ + +/* X509_POLICY_TREE stuff */ + +int X509_policy_tree_level_count(const X509_POLICY_TREE *tree) +{ + if (!tree) + return 0; + return tree->nlevel; +} + +X509_POLICY_LEVEL *X509_policy_tree_get0_level(const X509_POLICY_TREE *tree, + int i) +{ + if (!tree || (i < 0) || (i >= tree->nlevel)) + return NULL; + return tree->levels + i; +} + +STACK_OF(X509_POLICY_NODE) *X509_policy_tree_get0_policies(const + X509_POLICY_TREE + *tree) +{ + if (!tree) + return NULL; + return tree->auth_policies; +} + +STACK_OF(X509_POLICY_NODE) *X509_policy_tree_get0_user_policies(const + X509_POLICY_TREE + *tree) +{ + if (!tree) + return NULL; + if (tree->flags & POLICY_FLAG_ANY_POLICY) + return tree->auth_policies; + else + return tree->user_policies; +} + +/* X509_POLICY_LEVEL stuff */ + +int X509_policy_level_node_count(X509_POLICY_LEVEL *level) +{ + int n; + if (!level) + return 0; + if (level->anyPolicy) + n = 1; + else + n = 0; + if (level->nodes) + n += sk_X509_POLICY_NODE_num(level->nodes); + return n; +} + +X509_POLICY_NODE *X509_policy_level_get0_node(X509_POLICY_LEVEL *level, int i) +{ + if (!level) + return NULL; + if (level->anyPolicy) { + if (i == 0) + return level->anyPolicy; + i--; + } + return sk_X509_POLICY_NODE_value(level->nodes, i); +} + +/* X509_POLICY_NODE stuff */ + +const ASN1_OBJECT *X509_policy_node_get0_policy(const X509_POLICY_NODE *node) +{ + if (!node) + return NULL; + return node->data->valid_policy; +} + +#if 0 +int X509_policy_node_get_critical(const X509_POLICY_NODE *node) +{ + if (node_critical(node)) + return 1; + return 0; +} +#endif + +STACK_OF(POLICYQUALINFO) *X509_policy_node_get0_qualifiers(const + X509_POLICY_NODE + *node) +{ + if (!node) + return NULL; + return node->data->qualifier_set; +} + +const X509_POLICY_NODE *X509_policy_node_get0_parent(const X509_POLICY_NODE + *node) +{ + if (!node) + return NULL; + return node->parent; +} diff --git a/external/boringssl/crypto/x509v3/pcy_map.c b/external/boringssl/crypto/x509v3/pcy_map.c new file mode 100644 index 0000000000..7263c69200 --- /dev/null +++ b/external/boringssl/crypto/x509v3/pcy_map.c @@ -0,0 +1,130 @@ +/* pcy_map.c */ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project + * 2004. + */ +/* ==================================================================== + * Copyright (c) 2004 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include +#include +#include + +#include "pcy_int.h" + +/* + * Set policy mapping entries in cache. Note: this modifies the passed + * POLICY_MAPPINGS structure + */ + +int policy_cache_set_mapping(X509 *x, POLICY_MAPPINGS *maps) +{ + POLICY_MAPPING *map; + X509_POLICY_DATA *data; + X509_POLICY_CACHE *cache = x->policy_cache; + size_t i; + int ret = 0; + if (sk_POLICY_MAPPING_num(maps) == 0) { + ret = -1; + goto bad_mapping; + } + for (i = 0; i < sk_POLICY_MAPPING_num(maps); i++) { + map = sk_POLICY_MAPPING_value(maps, i); + /* Reject if map to or from anyPolicy */ + if ((OBJ_obj2nid(map->subjectDomainPolicy) == NID_any_policy) + || (OBJ_obj2nid(map->issuerDomainPolicy) == NID_any_policy)) { + ret = -1; + goto bad_mapping; + } + + /* Attempt to find matching policy data */ + data = policy_cache_find_data(cache, map->issuerDomainPolicy); + /* If we don't have anyPolicy can't map */ + if (!data && !cache->anyPolicy) + continue; + + /* Create a NODE from anyPolicy */ + if (!data) { + data = policy_data_new(NULL, map->issuerDomainPolicy, + cache->anyPolicy->flags + & POLICY_DATA_FLAG_CRITICAL); + if (!data) + goto bad_mapping; + data->qualifier_set = cache->anyPolicy->qualifier_set; + /* + * map->issuerDomainPolicy = NULL; + */ + data->flags |= POLICY_DATA_FLAG_MAPPED_ANY; + data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS; + if (!sk_X509_POLICY_DATA_push(cache->data, data)) { + policy_data_free(data); + goto bad_mapping; + } + } else + data->flags |= POLICY_DATA_FLAG_MAPPED; + if (!sk_ASN1_OBJECT_push(data->expected_policy_set, + map->subjectDomainPolicy)) + goto bad_mapping; + map->subjectDomainPolicy = NULL; + + } + + ret = 1; + bad_mapping: + if (ret == -1) + x->ex_flags |= EXFLAG_INVALID_POLICY; + sk_POLICY_MAPPING_pop_free(maps, POLICY_MAPPING_free); + return ret; + +} diff --git a/external/boringssl/crypto/x509v3/pcy_node.c b/external/boringssl/crypto/x509v3/pcy_node.c new file mode 100644 index 0000000000..cf4e79d8b0 --- /dev/null +++ b/external/boringssl/crypto/x509v3/pcy_node.c @@ -0,0 +1,188 @@ +/* pcy_node.c */ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project + * 2004. + */ +/* ==================================================================== + * Copyright (c) 2004 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include +#include +#include +#include +#include + +#include "pcy_int.h" + +static int node_cmp(const X509_POLICY_NODE **a, const X509_POLICY_NODE **b) +{ + return OBJ_cmp((*a)->data->valid_policy, (*b)->data->valid_policy); +} + +STACK_OF(X509_POLICY_NODE) *policy_node_cmp_new(void) +{ + return sk_X509_POLICY_NODE_new(node_cmp); +} + +X509_POLICY_NODE *tree_find_sk(STACK_OF(X509_POLICY_NODE) *nodes, + const ASN1_OBJECT *id) +{ + X509_POLICY_DATA n; + X509_POLICY_NODE l; + size_t idx; + + n.valid_policy = (ASN1_OBJECT *)id; + l.data = &n; + + if (!sk_X509_POLICY_NODE_find(nodes, &idx, &l)) + return NULL; + + return sk_X509_POLICY_NODE_value(nodes, idx); + +} + +X509_POLICY_NODE *level_find_node(const X509_POLICY_LEVEL *level, + const X509_POLICY_NODE *parent, + const ASN1_OBJECT *id) +{ + X509_POLICY_NODE *node; + size_t i; + for (i = 0; i < sk_X509_POLICY_NODE_num(level->nodes); i++) { + node = sk_X509_POLICY_NODE_value(level->nodes, i); + if (node->parent == parent) { + if (!OBJ_cmp(node->data->valid_policy, id)) + return node; + } + } + return NULL; +} + +X509_POLICY_NODE *level_add_node(X509_POLICY_LEVEL *level, + const X509_POLICY_DATA *data, + X509_POLICY_NODE *parent, + X509_POLICY_TREE *tree) +{ + X509_POLICY_NODE *node; + node = OPENSSL_malloc(sizeof(X509_POLICY_NODE)); + if (!node) + return NULL; + node->data = data; + node->parent = parent; + node->nchild = 0; + if (level) { + if (OBJ_obj2nid(data->valid_policy) == NID_any_policy) { + if (level->anyPolicy) + goto node_error; + level->anyPolicy = node; + } else { + + if (!level->nodes) + level->nodes = policy_node_cmp_new(); + if (!level->nodes) + goto node_error; + if (!sk_X509_POLICY_NODE_push(level->nodes, node)) + goto node_error; + } + } + + if (tree) { + if (!tree->extra_data) + tree->extra_data = sk_X509_POLICY_DATA_new_null(); + if (!tree->extra_data) + goto node_error; + if (!sk_X509_POLICY_DATA_push(tree->extra_data, data)) + goto node_error; + } + + if (parent) + parent->nchild++; + + return node; + + node_error: + policy_node_free(node); + return 0; + +} + +void policy_node_free(X509_POLICY_NODE *node) +{ + OPENSSL_free(node); +} + +/* + * See if a policy node matches a policy OID. If mapping enabled look through + * expected policy set otherwise just valid policy. + */ + +int policy_node_match(const X509_POLICY_LEVEL *lvl, + const X509_POLICY_NODE *node, const ASN1_OBJECT *oid) +{ + size_t i; + ASN1_OBJECT *policy_oid; + const X509_POLICY_DATA *x = node->data; + + if ((lvl->flags & X509_V_FLAG_INHIBIT_MAP) + || !(x->flags & POLICY_DATA_FLAG_MAP_MASK)) { + if (!OBJ_cmp(x->valid_policy, oid)) + return 1; + return 0; + } + + for (i = 0; i < sk_ASN1_OBJECT_num(x->expected_policy_set); i++) { + policy_oid = sk_ASN1_OBJECT_value(x->expected_policy_set, i); + if (!OBJ_cmp(policy_oid, oid)) + return 1; + } + return 0; + +} diff --git a/external/boringssl/crypto/x509v3/pcy_tree.c b/external/boringssl/crypto/x509v3/pcy_tree.c new file mode 100644 index 0000000000..e7484e52c6 --- /dev/null +++ b/external/boringssl/crypto/x509v3/pcy_tree.c @@ -0,0 +1,828 @@ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project + * 2004. + */ +/* ==================================================================== + * Copyright (c) 2004 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include "pcy_int.h" + +/* + * Enable this to print out the complete policy tree at various point during + * evaluation. + */ + +/* + * #define OPENSSL_POLICY_DEBUG + */ + +#ifdef OPENSSL_POLICY_DEBUG + +static void expected_print(BIO *err, X509_POLICY_LEVEL *lev, + X509_POLICY_NODE *node, int indent) +{ + if ((lev->flags & X509_V_FLAG_INHIBIT_MAP) + || !(node->data->flags & POLICY_DATA_FLAG_MAP_MASK)) + BIO_puts(err, " Not Mapped\n"); + else { + int i; + STACK_OF(ASN1_OBJECT) *pset = node->data->expected_policy_set; + ASN1_OBJECT *oid; + BIO_puts(err, " Expected: "); + for (i = 0; i < sk_ASN1_OBJECT_num(pset); i++) { + oid = sk_ASN1_OBJECT_value(pset, i); + if (i) + BIO_puts(err, ", "); + i2a_ASN1_OBJECT(err, oid); + } + BIO_puts(err, "\n"); + } +} + +static void tree_print(char *str, X509_POLICY_TREE *tree, + X509_POLICY_LEVEL *curr) +{ + X509_POLICY_LEVEL *plev; + X509_POLICY_NODE *node; + int i; + BIO *err; + err = BIO_new_fp(stderr, BIO_NOCLOSE); + if (!curr) + curr = tree->levels + tree->nlevel; + else + curr++; + BIO_printf(err, "Level print after %s\n", str); + BIO_printf(err, "Printing Up to Level %ld\n", curr - tree->levels); + for (plev = tree->levels; plev != curr; plev++) { + BIO_printf(err, "Level %ld, flags = %x\n", + plev - tree->levels, plev->flags); + for (i = 0; i < sk_X509_POLICY_NODE_num(plev->nodes); i++) { + node = sk_X509_POLICY_NODE_value(plev->nodes, i); + X509_POLICY_NODE_print(err, node, 2); + expected_print(err, plev, node, 2); + BIO_printf(err, " Flags: %x\n", node->data->flags); + } + if (plev->anyPolicy) + X509_POLICY_NODE_print(err, plev->anyPolicy, 2); + } + + BIO_free(err); + +} +#else + +# define tree_print(a,b,c) /* */ + +#endif + +/* + * Initialize policy tree. Return values: 0 Some internal error occured. -1 + * Inconsistent or invalid extensions in certificates. 1 Tree initialized + * OK. 2 Policy tree is empty. 5 Tree OK and requireExplicitPolicy true. 6 + * Tree empty and requireExplicitPolicy true. + */ + +static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs, + unsigned int flags) +{ + X509_POLICY_TREE *tree; + X509_POLICY_LEVEL *level; + const X509_POLICY_CACHE *cache; + X509_POLICY_DATA *data = NULL; + X509 *x; + int ret = 1; + int i, n; + int explicit_policy; + int any_skip; + int map_skip; + *ptree = NULL; + n = sk_X509_num(certs); + +#if 0 + /* Disable policy mapping for now... */ + flags |= X509_V_FLAG_INHIBIT_MAP; +#endif + + if (flags & X509_V_FLAG_EXPLICIT_POLICY) + explicit_policy = 0; + else + explicit_policy = n + 1; + + if (flags & X509_V_FLAG_INHIBIT_ANY) + any_skip = 0; + else + any_skip = n + 1; + + if (flags & X509_V_FLAG_INHIBIT_MAP) + map_skip = 0; + else + map_skip = n + 1; + + /* Can't do anything with just a trust anchor */ + if (n == 1) + return 1; + /* + * First setup policy cache in all certificates apart from the trust + * anchor. Note any bad cache results on the way. Also can calculate + * explicit_policy value at this point. + */ + for (i = n - 2; i >= 0; i--) { + x = sk_X509_value(certs, i); + X509_check_purpose(x, -1, -1); + cache = policy_cache_set(x); + /* If cache NULL something bad happened: return immediately */ + if (cache == NULL) + return 0; + /* + * If inconsistent extensions keep a note of it but continue + */ + if (x->ex_flags & EXFLAG_INVALID_POLICY) + ret = -1; + /* + * Otherwise if we have no data (hence no CertificatePolicies) and + * haven't already set an inconsistent code note it. + */ + else if ((ret == 1) && !cache->data) + ret = 2; + if (explicit_policy > 0) { + if (!(x->ex_flags & EXFLAG_SI)) + explicit_policy--; + if ((cache->explicit_skip != -1) + && (cache->explicit_skip < explicit_policy)) + explicit_policy = cache->explicit_skip; + } + } + + if (ret != 1) { + if (ret == 2 && !explicit_policy) + return 6; + return ret; + } + + /* If we get this far initialize the tree */ + + tree = OPENSSL_malloc(sizeof(X509_POLICY_TREE)); + + if (!tree) + return 0; + + tree->flags = 0; + tree->levels = OPENSSL_malloc(sizeof(X509_POLICY_LEVEL) * n); + tree->nlevel = 0; + tree->extra_data = NULL; + tree->auth_policies = NULL; + tree->user_policies = NULL; + + if (!tree->levels) { + OPENSSL_free(tree); + return 0; + } + + memset(tree->levels, 0, n * sizeof(X509_POLICY_LEVEL)); + + tree->nlevel = n; + + level = tree->levels; + + /* Root data: initialize to anyPolicy */ + + data = policy_data_new(NULL, OBJ_nid2obj(NID_any_policy), 0); + + if (!data || !level_add_node(level, data, NULL, tree)) + goto bad_tree; + + for (i = n - 2; i >= 0; i--) { + level++; + x = sk_X509_value(certs, i); + cache = policy_cache_set(x); + level->cert = X509_up_ref(x); + + if (!cache->anyPolicy) + level->flags |= X509_V_FLAG_INHIBIT_ANY; + + /* Determine inhibit any and inhibit map flags */ + if (any_skip == 0) { + /* + * Any matching allowed if certificate is self issued and not the + * last in the chain. + */ + if (!(x->ex_flags & EXFLAG_SI) || (i == 0)) + level->flags |= X509_V_FLAG_INHIBIT_ANY; + } else { + if (!(x->ex_flags & EXFLAG_SI)) + any_skip--; + if ((cache->any_skip >= 0) + && (cache->any_skip < any_skip)) + any_skip = cache->any_skip; + } + + if (map_skip == 0) + level->flags |= X509_V_FLAG_INHIBIT_MAP; + else { + if (!(x->ex_flags & EXFLAG_SI)) + map_skip--; + if ((cache->map_skip >= 0) + && (cache->map_skip < map_skip)) + map_skip = cache->map_skip; + } + + } + + *ptree = tree; + + if (explicit_policy) + return 1; + else + return 5; + + bad_tree: + + X509_policy_tree_free(tree); + + return 0; + +} + +static int tree_link_matching_nodes(X509_POLICY_LEVEL *curr, + const X509_POLICY_DATA *data) +{ + X509_POLICY_LEVEL *last = curr - 1; + X509_POLICY_NODE *node; + int matched = 0; + size_t i; + /* Iterate through all in nodes linking matches */ + for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++) { + node = sk_X509_POLICY_NODE_value(last->nodes, i); + if (policy_node_match(last, node, data->valid_policy)) { + if (!level_add_node(curr, data, node, NULL)) + return 0; + matched = 1; + } + } + if (!matched && last->anyPolicy) { + if (!level_add_node(curr, data, last->anyPolicy, NULL)) + return 0; + } + return 1; +} + +/* + * This corresponds to RFC3280 6.1.3(d)(1): link any data from + * CertificatePolicies onto matching parent or anyPolicy if no match. + */ + +static int tree_link_nodes(X509_POLICY_LEVEL *curr, + const X509_POLICY_CACHE *cache) +{ + size_t i; + X509_POLICY_DATA *data; + + for (i = 0; i < sk_X509_POLICY_DATA_num(cache->data); i++) { + data = sk_X509_POLICY_DATA_value(cache->data, i); + /* + * If a node is mapped any it doesn't have a corresponding + * CertificatePolicies entry. However such an identical node would + * be created if anyPolicy matching is enabled because there would be + * no match with the parent valid_policy_set. So we create link + * because then it will have the mapping flags right and we can prune + * it later. + */ +#if 0 + if ((data->flags & POLICY_DATA_FLAG_MAPPED_ANY) + && !(curr->flags & X509_V_FLAG_INHIBIT_ANY)) + continue; +#endif + /* Look for matching nodes in previous level */ + if (!tree_link_matching_nodes(curr, data)) + return 0; + } + return 1; +} + +/* + * This corresponds to RFC3280 6.1.3(d)(2): Create new data for any unmatched + * policies in the parent and link to anyPolicy. + */ + +static int tree_add_unmatched(X509_POLICY_LEVEL *curr, + const X509_POLICY_CACHE *cache, + const ASN1_OBJECT *id, + X509_POLICY_NODE *node, X509_POLICY_TREE *tree) +{ + X509_POLICY_DATA *data; + if (id == NULL) + id = node->data->valid_policy; + /* + * Create a new node with qualifiers from anyPolicy and id from unmatched + * node. + */ + data = policy_data_new(NULL, id, node_critical(node)); + + if (data == NULL) + return 0; + /* Curr may not have anyPolicy */ + data->qualifier_set = cache->anyPolicy->qualifier_set; + data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS; + if (!level_add_node(curr, data, node, tree)) { + policy_data_free(data); + return 0; + } + + return 1; +} + +static int tree_link_unmatched(X509_POLICY_LEVEL *curr, + const X509_POLICY_CACHE *cache, + X509_POLICY_NODE *node, X509_POLICY_TREE *tree) +{ + const X509_POLICY_LEVEL *last = curr - 1; + size_t i; + + if ((last->flags & X509_V_FLAG_INHIBIT_MAP) + || !(node->data->flags & POLICY_DATA_FLAG_MAPPED)) { + /* If no policy mapping: matched if one child present */ + if (node->nchild) + return 1; + if (!tree_add_unmatched(curr, cache, NULL, node, tree)) + return 0; + /* Add it */ + } else { + /* If mapping: matched if one child per expected policy set */ + STACK_OF(ASN1_OBJECT) *expset = node->data->expected_policy_set; + if ((size_t)node->nchild == sk_ASN1_OBJECT_num(expset)) + return 1; + /* Locate unmatched nodes */ + for (i = 0; i < sk_ASN1_OBJECT_num(expset); i++) { + ASN1_OBJECT *oid = sk_ASN1_OBJECT_value(expset, i); + if (level_find_node(curr, node, oid)) + continue; + if (!tree_add_unmatched(curr, cache, oid, node, tree)) + return 0; + } + + } + + return 1; + +} + +static int tree_link_any(X509_POLICY_LEVEL *curr, + const X509_POLICY_CACHE *cache, + X509_POLICY_TREE *tree) +{ + size_t i; + /* + * X509_POLICY_DATA *data; + */ + X509_POLICY_NODE *node; + X509_POLICY_LEVEL *last = curr - 1; + + for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++) { + node = sk_X509_POLICY_NODE_value(last->nodes, i); + + if (!tree_link_unmatched(curr, cache, node, tree)) + return 0; + +#if 0 + + /* + * Skip any node with any children: we only want unmathced nodes. + * Note: need something better for policy mapping because each node + * may have multiple children + */ + if (node->nchild) + continue; + + /* + * Create a new node with qualifiers from anyPolicy and id from + * unmatched node. + */ + data = policy_data_new(NULL, node->data->valid_policy, + node_critical(node)); + + if (data == NULL) + return 0; + /* Curr may not have anyPolicy */ + data->qualifier_set = cache->anyPolicy->qualifier_set; + data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS; + if (!level_add_node(curr, data, node, tree)) { + policy_data_free(data); + return 0; + } +#endif + + } + /* Finally add link to anyPolicy */ + if (last->anyPolicy) { + if (!level_add_node(curr, cache->anyPolicy, last->anyPolicy, NULL)) + return 0; + } + return 1; +} + +/* + * Prune the tree: delete any child mapped child data on the current level + * then proceed up the tree deleting any data with no children. If we ever + * have no data on a level we can halt because the tree will be empty. + */ + +static int tree_prune(X509_POLICY_TREE *tree, X509_POLICY_LEVEL *curr) +{ + STACK_OF(X509_POLICY_NODE) *nodes; + X509_POLICY_NODE *node; + int i; + nodes = curr->nodes; + if (curr->flags & X509_V_FLAG_INHIBIT_MAP) { + for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--) { + node = sk_X509_POLICY_NODE_value(nodes, i); + /* Delete any mapped data: see RFC3280 XXXX */ + if (node->data->flags & POLICY_DATA_FLAG_MAP_MASK) { + node->parent->nchild--; + OPENSSL_free(node); + (void)sk_X509_POLICY_NODE_delete(nodes, i); + } + } + } + + for (;;) { + --curr; + nodes = curr->nodes; + for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--) { + node = sk_X509_POLICY_NODE_value(nodes, i); + if (node->nchild == 0) { + node->parent->nchild--; + OPENSSL_free(node); + (void)sk_X509_POLICY_NODE_delete(nodes, i); + } + } + if (curr->anyPolicy && !curr->anyPolicy->nchild) { + if (curr->anyPolicy->parent) + curr->anyPolicy->parent->nchild--; + OPENSSL_free(curr->anyPolicy); + curr->anyPolicy = NULL; + } + if (curr == tree->levels) { + /* If we zapped anyPolicy at top then tree is empty */ + if (!curr->anyPolicy) + return 2; + return 1; + } + } + +} + +static int tree_add_auth_node(STACK_OF(X509_POLICY_NODE) **pnodes, + X509_POLICY_NODE *pcy) +{ + if (!*pnodes) { + *pnodes = policy_node_cmp_new(); + if (!*pnodes) + return 0; + } else if (sk_X509_POLICY_NODE_find(*pnodes, NULL, pcy)) + return 1; + + if (!sk_X509_POLICY_NODE_push(*pnodes, pcy)) + return 0; + + return 1; + +} + +/* + * Calculate the authority set based on policy tree. The 'pnodes' parameter + * is used as a store for the set of policy nodes used to calculate the user + * set. If the authority set is not anyPolicy then pnodes will just point to + * the authority set. If however the authority set is anyPolicy then the set + * of valid policies (other than anyPolicy) is store in pnodes. The return + * value of '2' is used in this case to indicate that pnodes should be freed. + */ + +static int tree_calculate_authority_set(X509_POLICY_TREE *tree, + STACK_OF(X509_POLICY_NODE) **pnodes) +{ + X509_POLICY_LEVEL *curr; + X509_POLICY_NODE *node, *anyptr; + STACK_OF(X509_POLICY_NODE) **addnodes; + int i; + size_t j; + curr = tree->levels + tree->nlevel - 1; + + /* If last level contains anyPolicy set is anyPolicy */ + if (curr->anyPolicy) { + if (!tree_add_auth_node(&tree->auth_policies, curr->anyPolicy)) + return 0; + addnodes = pnodes; + } else + /* Add policies to authority set */ + addnodes = &tree->auth_policies; + + curr = tree->levels; + for (i = 1; i < tree->nlevel; i++) { + /* + * If no anyPolicy node on this this level it can't appear on lower + * levels so end search. + */ + if (!(anyptr = curr->anyPolicy)) + break; + curr++; + for (j = 0; j < sk_X509_POLICY_NODE_num(curr->nodes); j++) { + node = sk_X509_POLICY_NODE_value(curr->nodes, j); + if ((node->parent == anyptr) + && !tree_add_auth_node(addnodes, node)) + return 0; + } + } + + if (addnodes == pnodes) + return 2; + + *pnodes = tree->auth_policies; + + return 1; +} + +static int tree_calculate_user_set(X509_POLICY_TREE *tree, + STACK_OF(ASN1_OBJECT) *policy_oids, + STACK_OF(X509_POLICY_NODE) *auth_nodes) +{ + size_t i; + X509_POLICY_NODE *node; + ASN1_OBJECT *oid; + + X509_POLICY_NODE *anyPolicy; + X509_POLICY_DATA *extra; + + /* + * Check if anyPolicy present in authority constrained policy set: this + * will happen if it is a leaf node. + */ + + if (sk_ASN1_OBJECT_num(policy_oids) <= 0) + return 1; + + anyPolicy = tree->levels[tree->nlevel - 1].anyPolicy; + + for (i = 0; i < sk_ASN1_OBJECT_num(policy_oids); i++) { + oid = sk_ASN1_OBJECT_value(policy_oids, i); + if (OBJ_obj2nid(oid) == NID_any_policy) { + tree->flags |= POLICY_FLAG_ANY_POLICY; + return 1; + } + } + + for (i = 0; i < sk_ASN1_OBJECT_num(policy_oids); i++) { + oid = sk_ASN1_OBJECT_value(policy_oids, i); + node = tree_find_sk(auth_nodes, oid); + if (!node) { + if (!anyPolicy) + continue; + /* + * Create a new node with policy ID from user set and qualifiers + * from anyPolicy. + */ + extra = policy_data_new(NULL, oid, node_critical(anyPolicy)); + if (!extra) + return 0; + extra->qualifier_set = anyPolicy->data->qualifier_set; + extra->flags = POLICY_DATA_FLAG_SHARED_QUALIFIERS + | POLICY_DATA_FLAG_EXTRA_NODE; + node = level_add_node(NULL, extra, anyPolicy->parent, tree); + } + if (!tree->user_policies) { + tree->user_policies = sk_X509_POLICY_NODE_new_null(); + if (!tree->user_policies) + return 1; + } + if (!sk_X509_POLICY_NODE_push(tree->user_policies, node)) + return 0; + } + return 1; + +} + +static int tree_evaluate(X509_POLICY_TREE *tree) +{ + int ret, i; + X509_POLICY_LEVEL *curr = tree->levels + 1; + const X509_POLICY_CACHE *cache; + + for (i = 1; i < tree->nlevel; i++, curr++) { + cache = policy_cache_set(curr->cert); + if (!tree_link_nodes(curr, cache)) + return 0; + + if (!(curr->flags & X509_V_FLAG_INHIBIT_ANY) + && !tree_link_any(curr, cache, tree)) + return 0; + tree_print("before tree_prune()", tree, curr); + ret = tree_prune(tree, curr); + if (ret != 1) + return ret; + } + + return 1; + +} + +static void exnode_free(X509_POLICY_NODE *node) +{ + if (node->data && (node->data->flags & POLICY_DATA_FLAG_EXTRA_NODE)) + OPENSSL_free(node); +} + +void X509_policy_tree_free(X509_POLICY_TREE *tree) +{ + X509_POLICY_LEVEL *curr; + int i; + + if (!tree) + return; + + sk_X509_POLICY_NODE_free(tree->auth_policies); + sk_X509_POLICY_NODE_pop_free(tree->user_policies, exnode_free); + + for (i = 0, curr = tree->levels; i < tree->nlevel; i++, curr++) { + if (curr->cert) + X509_free(curr->cert); + if (curr->nodes) + sk_X509_POLICY_NODE_pop_free(curr->nodes, policy_node_free); + if (curr->anyPolicy) + policy_node_free(curr->anyPolicy); + } + + if (tree->extra_data) + sk_X509_POLICY_DATA_pop_free(tree->extra_data, policy_data_free); + + OPENSSL_free(tree->levels); + OPENSSL_free(tree); + +} + +/* + * Application policy checking function. Return codes: 0 Internal Error. 1 + * Successful. -1 One or more certificates contain invalid or inconsistent + * extensions -2 User constrained policy set empty and requireExplicit true. + */ + +int X509_policy_check(X509_POLICY_TREE **ptree, int *pexplicit_policy, + STACK_OF(X509) *certs, + STACK_OF(ASN1_OBJECT) *policy_oids, unsigned int flags) +{ + int ret; + X509_POLICY_TREE *tree = NULL; + STACK_OF(X509_POLICY_NODE) *nodes, *auth_nodes = NULL; + *ptree = NULL; + + *pexplicit_policy = 0; + ret = tree_init(&tree, certs, flags); + + switch (ret) { + + /* Tree empty requireExplicit False: OK */ + case 2: + return 1; + + /* Some internal error */ + case -1: + return -1; + + /* Some internal error */ + case 0: + return 0; + + /* Tree empty requireExplicit True: Error */ + + case 6: + *pexplicit_policy = 1; + return -2; + + /* Tree OK requireExplicit True: OK and continue */ + case 5: + *pexplicit_policy = 1; + break; + + /* Tree OK: continue */ + + case 1: + if (!tree) + /* + * tree_init() returns success and a null tree + * if it's just looking at a trust anchor. + * I'm not sure that returning success here is + * correct, but I'm sure that reporting this + * as an internal error which our caller + * interprets as a malloc failure is wrong. + */ + return 1; + break; + } + + if (!tree) + goto error; + ret = tree_evaluate(tree); + + tree_print("tree_evaluate()", tree, NULL); + + if (ret <= 0) + goto error; + + /* Return value 2 means tree empty */ + if (ret == 2) { + X509_policy_tree_free(tree); + if (*pexplicit_policy) + return -2; + else + return 1; + } + + /* Tree is not empty: continue */ + + ret = tree_calculate_authority_set(tree, &auth_nodes); + + if (!ret) + goto error; + + if (!tree_calculate_user_set(tree, policy_oids, auth_nodes)) + goto error; + + if (ret == 2) + sk_X509_POLICY_NODE_free(auth_nodes); + + if (tree) + *ptree = tree; + + if (*pexplicit_policy) { + nodes = X509_policy_tree_get0_user_policies(tree); + if (sk_X509_POLICY_NODE_num(nodes) <= 0) + return -2; + } + + return 1; + + error: + + X509_policy_tree_free(tree); + + return 0; + +} diff --git a/external/boringssl/crypto/x509v3/tab_test.c b/external/boringssl/crypto/x509v3/tab_test.c new file mode 100644 index 0000000000..19005474e8 --- /dev/null +++ b/external/boringssl/crypto/x509v3/tab_test.c @@ -0,0 +1,108 @@ +/* tabtest.c */ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project + * 1999. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +/* + * Simple program to check the ext_dat.h is correct and print out problems if + * it is not. + */ + +#include + +#include +#include +#include +#include + +#if !defined(BORINGSSL_SHARED_LIBRARY) +# include "ext_dat.h" +#endif + +int main(void) +{ +#if !defined(BORINGSSL_SHARED_LIBRARY) + unsigned i; + int prev = -1, bad = 0; + const X509V3_EXT_METHOD *const *tmp; + CRYPTO_library_init(); + i = sizeof(standard_exts) / sizeof(X509V3_EXT_METHOD *); + if (i != STANDARD_EXTENSION_COUNT) + fprintf(stderr, "Extension number invalid expecting %d\n", i); + tmp = standard_exts; + for (i = 0; i < STANDARD_EXTENSION_COUNT; i++, tmp++) { + if ((*tmp)->ext_nid < prev) + bad = 1; + prev = (*tmp)->ext_nid; + + } + if (bad) { + tmp = standard_exts; + fprintf(stderr, "Extensions out of order!\n"); + for (i = 0; i < STANDARD_EXTENSION_COUNT; i++, tmp++) + printf("%d : %s\n", (*tmp)->ext_nid, OBJ_nid2sn((*tmp)->ext_nid)); + return 1; + } else { + printf("PASS\n"); + return 0; + } +#else + /* TODO(davidben): Fix this test in the shared library build. */ + printf("PASS\n"); + return 0; +#endif +} diff --git a/external/boringssl/crypto/x509v3/v3_akey.c b/external/boringssl/crypto/x509v3/v3_akey.c new file mode 100644 index 0000000000..4503e6155f --- /dev/null +++ b/external/boringssl/crypto/x509v3/v3_akey.c @@ -0,0 +1,204 @@ +/* v3_akey.c */ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project + * 1999. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_KEYID(X509V3_EXT_METHOD *method, + AUTHORITY_KEYID *akeyid, + STACK_OF(CONF_VALUE) + *extlist); +static AUTHORITY_KEYID *v2i_AUTHORITY_KEYID(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *values); + +const X509V3_EXT_METHOD v3_akey_id = { + NID_authority_key_identifier, + X509V3_EXT_MULTILINE, ASN1_ITEM_ref(AUTHORITY_KEYID), + 0, 0, 0, 0, + 0, 0, + (X509V3_EXT_I2V) i2v_AUTHORITY_KEYID, + (X509V3_EXT_V2I)v2i_AUTHORITY_KEYID, + 0, 0, + NULL +}; + +static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_KEYID(X509V3_EXT_METHOD *method, + AUTHORITY_KEYID *akeyid, + STACK_OF(CONF_VALUE) + *extlist) +{ + char *tmp; + if (akeyid->keyid) { + tmp = hex_to_string(akeyid->keyid->data, akeyid->keyid->length); + X509V3_add_value("keyid", tmp, &extlist); + OPENSSL_free(tmp); + } + if (akeyid->issuer) + extlist = i2v_GENERAL_NAMES(NULL, akeyid->issuer, extlist); + if (akeyid->serial) { + tmp = hex_to_string(akeyid->serial->data, akeyid->serial->length); + X509V3_add_value("serial", tmp, &extlist); + OPENSSL_free(tmp); + } + return extlist; +} + +/* + * Currently two options: keyid: use the issuers subject keyid, the value + * 'always' means its is an error if the issuer certificate doesn't have a + * key id. issuer: use the issuers cert issuer and serial number. The default + * is to only use this if keyid is not present. With the option 'always' this + * is always included. + */ + +static AUTHORITY_KEYID *v2i_AUTHORITY_KEYID(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *values) +{ + char keyid = 0, issuer = 0; + size_t i; + int j; + CONF_VALUE *cnf; + ASN1_OCTET_STRING *ikeyid = NULL; + X509_NAME *isname = NULL; + GENERAL_NAMES *gens = NULL; + GENERAL_NAME *gen = NULL; + ASN1_INTEGER *serial = NULL; + X509_EXTENSION *ext; + X509 *cert; + AUTHORITY_KEYID *akeyid; + + for (i = 0; i < sk_CONF_VALUE_num(values); i++) { + cnf = sk_CONF_VALUE_value(values, i); + if (!strcmp(cnf->name, "keyid")) { + keyid = 1; + if (cnf->value && !strcmp(cnf->value, "always")) + keyid = 2; + } else if (!strcmp(cnf->name, "issuer")) { + issuer = 1; + if (cnf->value && !strcmp(cnf->value, "always")) + issuer = 2; + } else { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNKNOWN_OPTION); + ERR_add_error_data(2, "name=", cnf->name); + return NULL; + } + } + + if (!ctx || !ctx->issuer_cert) { + if (ctx && (ctx->flags == CTX_TEST)) + return AUTHORITY_KEYID_new(); + OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_ISSUER_CERTIFICATE); + return NULL; + } + + cert = ctx->issuer_cert; + + if (keyid) { + j = X509_get_ext_by_NID(cert, NID_subject_key_identifier, -1); + if ((j >= 0) && (ext = X509_get_ext(cert, j))) + ikeyid = X509V3_EXT_d2i(ext); + if (keyid == 2 && !ikeyid) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNABLE_TO_GET_ISSUER_KEYID); + return NULL; + } + } + + if ((issuer && !ikeyid) || (issuer == 2)) { + isname = X509_NAME_dup(X509_get_issuer_name(cert)); + serial = M_ASN1_INTEGER_dup(X509_get_serialNumber(cert)); + if (!isname || !serial) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNABLE_TO_GET_ISSUER_DETAILS); + goto err; + } + } + + if (!(akeyid = AUTHORITY_KEYID_new())) + goto err; + + if (isname) { + if (!(gens = sk_GENERAL_NAME_new_null()) + || !(gen = GENERAL_NAME_new()) + || !sk_GENERAL_NAME_push(gens, gen)) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + goto err; + } + gen->type = GEN_DIRNAME; + gen->d.dirn = isname; + } + + akeyid->issuer = gens; + akeyid->serial = serial; + akeyid->keyid = ikeyid; + + return akeyid; + + err: + X509_NAME_free(isname); + M_ASN1_INTEGER_free(serial); + M_ASN1_OCTET_STRING_free(ikeyid); + return NULL; +} diff --git a/external/boringssl/crypto/x509v3/v3_akeya.c b/external/boringssl/crypto/x509v3/v3_akeya.c new file mode 100644 index 0000000000..844dee529f --- /dev/null +++ b/external/boringssl/crypto/x509v3/v3_akeya.c @@ -0,0 +1,72 @@ +/* v3_akey_asn1.c */ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project + * 1999. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include +#include +#include + + +ASN1_SEQUENCE(AUTHORITY_KEYID) = { + ASN1_IMP_OPT(AUTHORITY_KEYID, keyid, ASN1_OCTET_STRING, 0), + ASN1_IMP_SEQUENCE_OF_OPT(AUTHORITY_KEYID, issuer, GENERAL_NAME, 1), + ASN1_IMP_OPT(AUTHORITY_KEYID, serial, ASN1_INTEGER, 2) +} ASN1_SEQUENCE_END(AUTHORITY_KEYID) + +IMPLEMENT_ASN1_FUNCTIONS(AUTHORITY_KEYID) diff --git a/external/boringssl/crypto/x509v3/v3_alt.c b/external/boringssl/crypto/x509v3/v3_alt.c new file mode 100644 index 0000000000..152bd79f85 --- /dev/null +++ b/external/boringssl/crypto/x509v3/v3_alt.c @@ -0,0 +1,614 @@ +/* v3_alt.c */ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project. + */ +/* ==================================================================== + * Copyright (c) 1999-2003 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include +#include + +#include +#include +#include +#include +#include + +static GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *nval); +static GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *nval); +static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p); +static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens); +static int do_othername(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx); +static int do_dirname(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx); + +const X509V3_EXT_METHOD v3_alt[] = { + {NID_subject_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES), + 0, 0, 0, 0, + 0, 0, + (X509V3_EXT_I2V) i2v_GENERAL_NAMES, + (X509V3_EXT_V2I)v2i_subject_alt, + NULL, NULL, NULL}, + + {NID_issuer_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES), + 0, 0, 0, 0, + 0, 0, + (X509V3_EXT_I2V) i2v_GENERAL_NAMES, + (X509V3_EXT_V2I)v2i_issuer_alt, + NULL, NULL, NULL}, + + {NID_certificate_issuer, 0, ASN1_ITEM_ref(GENERAL_NAMES), + 0, 0, 0, 0, + 0, 0, + (X509V3_EXT_I2V) i2v_GENERAL_NAMES, + NULL, NULL, NULL, NULL}, +}; + +STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES(X509V3_EXT_METHOD *method, + GENERAL_NAMES *gens, + STACK_OF(CONF_VALUE) *ret) +{ + size_t i; + GENERAL_NAME *gen; + for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { + gen = sk_GENERAL_NAME_value(gens, i); + ret = i2v_GENERAL_NAME(method, gen, ret); + } + if (!ret) + return sk_CONF_VALUE_new_null(); + return ret; +} + +STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method, + GENERAL_NAME *gen, + STACK_OF(CONF_VALUE) *ret) +{ + unsigned char *p; + char oline[256], htmp[5]; + int i; + switch (gen->type) { + case GEN_OTHERNAME: + X509V3_add_value("othername", "", &ret); + break; + + case GEN_X400: + X509V3_add_value("X400Name", "", &ret); + break; + + case GEN_EDIPARTY: + X509V3_add_value("EdiPartyName", "", &ret); + break; + + case GEN_EMAIL: + X509V3_add_value_uchar("email", gen->d.ia5->data, &ret); + break; + + case GEN_DNS: + X509V3_add_value_uchar("DNS", gen->d.ia5->data, &ret); + break; + + case GEN_URI: + X509V3_add_value_uchar("URI", gen->d.ia5->data, &ret); + break; + + case GEN_DIRNAME: + X509_NAME_oneline(gen->d.dirn, oline, 256); + X509V3_add_value("DirName", oline, &ret); + break; + + case GEN_IPADD: + p = gen->d.ip->data; + if (gen->d.ip->length == 4) + BIO_snprintf(oline, sizeof oline, + "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); + else if (gen->d.ip->length == 16) { + oline[0] = 0; + for (i = 0; i < 8; i++) { + BIO_snprintf(htmp, sizeof htmp, "%X", p[0] << 8 | p[1]); + p += 2; + strcat(oline, htmp); + if (i != 7) + strcat(oline, ":"); + } + } else { + X509V3_add_value("IP Address", "", &ret); + break; + } + X509V3_add_value("IP Address", oline, &ret); + break; + + case GEN_RID: + i2t_ASN1_OBJECT(oline, 256, gen->d.rid); + X509V3_add_value("Registered ID", oline, &ret); + break; + } + return ret; +} + +int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen) +{ + unsigned char *p; + int i; + switch (gen->type) { + case GEN_OTHERNAME: + BIO_printf(out, "othername:"); + break; + + case GEN_X400: + BIO_printf(out, "X400Name:"); + break; + + case GEN_EDIPARTY: + /* Maybe fix this: it is supported now */ + BIO_printf(out, "EdiPartyName:"); + break; + + case GEN_EMAIL: + BIO_printf(out, "email:%s", gen->d.ia5->data); + break; + + case GEN_DNS: + BIO_printf(out, "DNS:%s", gen->d.ia5->data); + break; + + case GEN_URI: + BIO_printf(out, "URI:%s", gen->d.ia5->data); + break; + + case GEN_DIRNAME: + BIO_printf(out, "DirName: "); + X509_NAME_print_ex(out, gen->d.dirn, 0, XN_FLAG_ONELINE); + break; + + case GEN_IPADD: + p = gen->d.ip->data; + if (gen->d.ip->length == 4) + BIO_printf(out, "IP Address:%d.%d.%d.%d", p[0], p[1], p[2], p[3]); + else if (gen->d.ip->length == 16) { + BIO_printf(out, "IP Address"); + for (i = 0; i < 8; i++) { + BIO_printf(out, ":%X", p[0] << 8 | p[1]); + p += 2; + } + BIO_puts(out, "\n"); + } else { + BIO_printf(out, "IP Address:"); + break; + } + break; + + case GEN_RID: + BIO_printf(out, "Registered ID"); + i2a_ASN1_OBJECT(out, gen->d.rid); + break; + } + return 1; +} + +static GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *nval) +{ + GENERAL_NAMES *gens = NULL; + CONF_VALUE *cnf; + size_t i; + if (!(gens = sk_GENERAL_NAME_new_null())) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + return NULL; + } + for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { + cnf = sk_CONF_VALUE_value(nval, i); + if (!name_cmp(cnf->name, "issuer") && cnf->value && + !strcmp(cnf->value, "copy")) { + if (!copy_issuer(ctx, gens)) + goto err; + } else { + GENERAL_NAME *gen; + if (!(gen = v2i_GENERAL_NAME(method, ctx, cnf))) + goto err; + sk_GENERAL_NAME_push(gens, gen); + } + } + return gens; + err: + sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); + return NULL; +} + +/* Append subject altname of issuer to issuer alt name of subject */ + +static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens) +{ + GENERAL_NAMES *ialt; + GENERAL_NAME *gen; + X509_EXTENSION *ext; + int i; + size_t j; + if (ctx && (ctx->flags == CTX_TEST)) + return 1; + if (!ctx || !ctx->issuer_cert) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_ISSUER_DETAILS); + goto err; + } + i = X509_get_ext_by_NID(ctx->issuer_cert, NID_subject_alt_name, -1); + if (i < 0) + return 1; + if (!(ext = X509_get_ext(ctx->issuer_cert, i)) || + !(ialt = X509V3_EXT_d2i(ext))) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_ISSUER_DECODE_ERROR); + goto err; + } + + for (j = 0; j < sk_GENERAL_NAME_num(ialt); j++) { + gen = sk_GENERAL_NAME_value(ialt, j); + if (!sk_GENERAL_NAME_push(gens, gen)) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + goto err; + } + } + sk_GENERAL_NAME_free(ialt); + + return 1; + + err: + return 0; + +} + +static GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *nval) +{ + GENERAL_NAMES *gens = NULL; + CONF_VALUE *cnf; + size_t i; + if (!(gens = sk_GENERAL_NAME_new_null())) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + return NULL; + } + for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { + cnf = sk_CONF_VALUE_value(nval, i); + if (!name_cmp(cnf->name, "email") && cnf->value && + !strcmp(cnf->value, "copy")) { + if (!copy_email(ctx, gens, 0)) + goto err; + } else if (!name_cmp(cnf->name, "email") && cnf->value && + !strcmp(cnf->value, "move")) { + if (!copy_email(ctx, gens, 1)) + goto err; + } else { + GENERAL_NAME *gen; + if (!(gen = v2i_GENERAL_NAME(method, ctx, cnf))) + goto err; + sk_GENERAL_NAME_push(gens, gen); + } + } + return gens; + err: + sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); + return NULL; +} + +/* + * Copy any email addresses in a certificate or request to GENERAL_NAMES + */ + +static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p) +{ + X509_NAME *nm; + ASN1_IA5STRING *email = NULL; + X509_NAME_ENTRY *ne; + GENERAL_NAME *gen = NULL; + int i; + if (ctx != NULL && ctx->flags == CTX_TEST) + return 1; + if (!ctx || (!ctx->subject_cert && !ctx->subject_req)) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_SUBJECT_DETAILS); + goto err; + } + /* Find the subject name */ + if (ctx->subject_cert) + nm = X509_get_subject_name(ctx->subject_cert); + else + nm = X509_REQ_get_subject_name(ctx->subject_req); + + /* Now add any email address(es) to STACK */ + i = -1; + while ((i = X509_NAME_get_index_by_NID(nm, + NID_pkcs9_emailAddress, i)) >= 0) { + ne = X509_NAME_get_entry(nm, i); + email = M_ASN1_IA5STRING_dup(X509_NAME_ENTRY_get_data(ne)); + if (move_p) { + X509_NAME_delete_entry(nm, i); + X509_NAME_ENTRY_free(ne); + i--; + } + if (!email || !(gen = GENERAL_NAME_new())) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + goto err; + } + gen->d.ia5 = email; + email = NULL; + gen->type = GEN_EMAIL; + if (!sk_GENERAL_NAME_push(gens, gen)) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + goto err; + } + gen = NULL; + } + + return 1; + + err: + GENERAL_NAME_free(gen); + M_ASN1_IA5STRING_free(email); + return 0; + +} + +GENERAL_NAMES *v2i_GENERAL_NAMES(const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval) +{ + GENERAL_NAME *gen; + GENERAL_NAMES *gens = NULL; + CONF_VALUE *cnf; + size_t i; + if (!(gens = sk_GENERAL_NAME_new_null())) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + return NULL; + } + for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { + cnf = sk_CONF_VALUE_value(nval, i); + if (!(gen = v2i_GENERAL_NAME(method, ctx, cnf))) + goto err; + sk_GENERAL_NAME_push(gens, gen); + } + return gens; + err: + sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); + return NULL; +} + +GENERAL_NAME *v2i_GENERAL_NAME(const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, CONF_VALUE *cnf) +{ + return v2i_GENERAL_NAME_ex(NULL, method, ctx, cnf, 0); +} + +GENERAL_NAME *a2i_GENERAL_NAME(GENERAL_NAME *out, + const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, int gen_type, char *value, + int is_nc) +{ + char is_string = 0; + GENERAL_NAME *gen = NULL; + + if (!value) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_MISSING_VALUE); + return NULL; + } + + if (out) + gen = out; + else { + gen = GENERAL_NAME_new(); + if (gen == NULL) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + return NULL; + } + } + + switch (gen_type) { + case GEN_URI: + case GEN_EMAIL: + case GEN_DNS: + is_string = 1; + break; + + case GEN_RID: + { + ASN1_OBJECT *obj; + if (!(obj = OBJ_txt2obj(value, 0))) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_BAD_OBJECT); + ERR_add_error_data(2, "value=", value); + goto err; + } + gen->d.rid = obj; + } + break; + + case GEN_IPADD: + if (is_nc) + gen->d.ip = a2i_IPADDRESS_NC(value); + else + gen->d.ip = a2i_IPADDRESS(value); + if (gen->d.ip == NULL) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_BAD_IP_ADDRESS); + ERR_add_error_data(2, "value=", value); + goto err; + } + break; + + case GEN_DIRNAME: + if (!do_dirname(gen, value, ctx)) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_DIRNAME_ERROR); + goto err; + } + break; + + case GEN_OTHERNAME: + if (!do_othername(gen, value, ctx)) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_OTHERNAME_ERROR); + goto err; + } + break; + default: + OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNSUPPORTED_TYPE); + goto err; + } + + if (is_string) { + if (!(gen->d.ia5 = M_ASN1_IA5STRING_new()) || + !ASN1_STRING_set(gen->d.ia5, (unsigned char *)value, + strlen(value))) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + goto err; + } + } + + gen->type = gen_type; + + return gen; + + err: + if (!out) + GENERAL_NAME_free(gen); + return NULL; +} + +GENERAL_NAME *v2i_GENERAL_NAME_ex(GENERAL_NAME *out, + const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, CONF_VALUE *cnf, int is_nc) +{ + int type; + + char *name, *value; + + name = cnf->name; + value = cnf->value; + + if (!value) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_MISSING_VALUE); + return NULL; + } + + if (!name_cmp(name, "email")) + type = GEN_EMAIL; + else if (!name_cmp(name, "URI")) + type = GEN_URI; + else if (!name_cmp(name, "DNS")) + type = GEN_DNS; + else if (!name_cmp(name, "RID")) + type = GEN_RID; + else if (!name_cmp(name, "IP")) + type = GEN_IPADD; + else if (!name_cmp(name, "dirName")) + type = GEN_DIRNAME; + else if (!name_cmp(name, "otherName")) + type = GEN_OTHERNAME; + else { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNSUPPORTED_OPTION); + ERR_add_error_data(2, "name=", name); + return NULL; + } + + return a2i_GENERAL_NAME(out, method, ctx, type, value, is_nc); + +} + +static int do_othername(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx) +{ + char *objtmp = NULL, *p; + int objlen; + if (!(p = strchr(value, ';'))) + return 0; + if (!(gen->d.otherName = OTHERNAME_new())) + return 0; + /* + * Free this up because we will overwrite it. no need to free type_id + * because it is static + */ + ASN1_TYPE_free(gen->d.otherName->value); + if (!(gen->d.otherName->value = ASN1_generate_v3(p + 1, ctx))) + return 0; + objlen = p - value; + objtmp = OPENSSL_malloc(objlen + 1); + if (objtmp == NULL) + return 0; + strncpy(objtmp, value, objlen); + objtmp[objlen] = 0; + gen->d.otherName->type_id = OBJ_txt2obj(objtmp, 0); + OPENSSL_free(objtmp); + if (!gen->d.otherName->type_id) + return 0; + return 1; +} + +static int do_dirname(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx) +{ + int ret = 0; + STACK_OF(CONF_VALUE) *sk = NULL; + X509_NAME *nm = X509_NAME_new(); + if (nm == NULL) + goto err; + sk = X509V3_get_section(ctx, value); + if (sk == NULL) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_SECTION_NOT_FOUND); + ERR_add_error_data(2, "section=", value); + goto err; + } + /* FIXME: should allow other character types... */ + if (!X509V3_NAME_from_section(nm, sk, MBSTRING_ASC)) + goto err; + gen->d.dirn = nm; + ret = 1; + + err: + if (!ret) + X509_NAME_free(nm); + X509V3_section_free(ctx, sk); + return ret; +} diff --git a/external/boringssl/crypto/x509v3/v3_bcons.c b/external/boringssl/crypto/x509v3/v3_bcons.c new file mode 100644 index 0000000000..aefefdff77 --- /dev/null +++ b/external/boringssl/crypto/x509v3/v3_bcons.c @@ -0,0 +1,133 @@ +/* v3_bcons.c */ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project + * 1999. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +static STACK_OF(CONF_VALUE) *i2v_BASIC_CONSTRAINTS(X509V3_EXT_METHOD *method, + BASIC_CONSTRAINTS *bcons, + STACK_OF(CONF_VALUE) + *extlist); +static BASIC_CONSTRAINTS *v2i_BASIC_CONSTRAINTS(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *values); + +const X509V3_EXT_METHOD v3_bcons = { + NID_basic_constraints, 0, + ASN1_ITEM_ref(BASIC_CONSTRAINTS), + 0, 0, 0, 0, + 0, 0, + (X509V3_EXT_I2V) i2v_BASIC_CONSTRAINTS, + (X509V3_EXT_V2I)v2i_BASIC_CONSTRAINTS, + NULL, NULL, + NULL +}; + +ASN1_SEQUENCE(BASIC_CONSTRAINTS) = { + ASN1_OPT(BASIC_CONSTRAINTS, ca, ASN1_FBOOLEAN), + ASN1_OPT(BASIC_CONSTRAINTS, pathlen, ASN1_INTEGER) +} ASN1_SEQUENCE_END(BASIC_CONSTRAINTS) + +IMPLEMENT_ASN1_FUNCTIONS(BASIC_CONSTRAINTS) + +static STACK_OF(CONF_VALUE) *i2v_BASIC_CONSTRAINTS(X509V3_EXT_METHOD *method, + BASIC_CONSTRAINTS *bcons, + STACK_OF(CONF_VALUE) + *extlist) +{ + X509V3_add_value_bool("CA", bcons->ca, &extlist); + X509V3_add_value_int("pathlen", bcons->pathlen, &extlist); + return extlist; +} + +static BASIC_CONSTRAINTS *v2i_BASIC_CONSTRAINTS(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *values) +{ + BASIC_CONSTRAINTS *bcons = NULL; + CONF_VALUE *val; + size_t i; + if (!(bcons = BASIC_CONSTRAINTS_new())) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + return NULL; + } + for (i = 0; i < sk_CONF_VALUE_num(values); i++) { + val = sk_CONF_VALUE_value(values, i); + if (!strcmp(val->name, "CA")) { + if (!X509V3_get_value_bool(val, &bcons->ca)) + goto err; + } else if (!strcmp(val->name, "pathlen")) { + if (!X509V3_get_value_int(val, &bcons->pathlen)) + goto err; + } else { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NAME); + X509V3_conf_err(val); + goto err; + } + } + return bcons; + err: + BASIC_CONSTRAINTS_free(bcons); + return NULL; +} diff --git a/external/boringssl/crypto/x509v3/v3_bitst.c b/external/boringssl/crypto/x509v3/v3_bitst.c new file mode 100644 index 0000000000..86a8c3615b --- /dev/null +++ b/external/boringssl/crypto/x509v3/v3_bitst.c @@ -0,0 +1,141 @@ +/* v3_bitst.c */ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project + * 1999. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include +#include + +#include +#include +#include +#include + +static const BIT_STRING_BITNAME ns_cert_type_table[] = { + {0, "SSL Client", "client"}, + {1, "SSL Server", "server"}, + {2, "S/MIME", "email"}, + {3, "Object Signing", "objsign"}, + {4, "Unused", "reserved"}, + {5, "SSL CA", "sslCA"}, + {6, "S/MIME CA", "emailCA"}, + {7, "Object Signing CA", "objCA"}, + {-1, NULL, NULL} +}; + +static const BIT_STRING_BITNAME key_usage_type_table[] = { + {0, "Digital Signature", "digitalSignature"}, + {1, "Non Repudiation", "nonRepudiation"}, + {2, "Key Encipherment", "keyEncipherment"}, + {3, "Data Encipherment", "dataEncipherment"}, + {4, "Key Agreement", "keyAgreement"}, + {5, "Certificate Sign", "keyCertSign"}, + {6, "CRL Sign", "cRLSign"}, + {7, "Encipher Only", "encipherOnly"}, + {8, "Decipher Only", "decipherOnly"}, + {-1, NULL, NULL} +}; + +const X509V3_EXT_METHOD v3_nscert = +EXT_BITSTRING(NID_netscape_cert_type, ns_cert_type_table); +const X509V3_EXT_METHOD v3_key_usage = +EXT_BITSTRING(NID_key_usage, key_usage_type_table); + +STACK_OF(CONF_VALUE) *i2v_ASN1_BIT_STRING(X509V3_EXT_METHOD *method, + ASN1_BIT_STRING *bits, + STACK_OF(CONF_VALUE) *ret) +{ + const BIT_STRING_BITNAME *bnam; + for (bnam = method->usr_data; bnam->lname; bnam++) { + if (ASN1_BIT_STRING_get_bit(bits, bnam->bitnum)) + X509V3_add_value(bnam->lname, NULL, &ret); + } + return ret; +} + +ASN1_BIT_STRING *v2i_ASN1_BIT_STRING(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *nval) +{ + CONF_VALUE *val; + ASN1_BIT_STRING *bs; + size_t i; + const BIT_STRING_BITNAME *bnam; + if (!(bs = M_ASN1_BIT_STRING_new())) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + return NULL; + } + for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { + val = sk_CONF_VALUE_value(nval, i); + for (bnam = method->usr_data; bnam->lname; bnam++) { + if (!strcmp(bnam->sname, val->name) || + !strcmp(bnam->lname, val->name)) { + if (!ASN1_BIT_STRING_set_bit(bs, bnam->bitnum, 1)) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + M_ASN1_BIT_STRING_free(bs); + return NULL; + } + break; + } + } + if (!bnam->lname) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNKNOWN_BIT_STRING_ARGUMENT); + X509V3_conf_err(val); + M_ASN1_BIT_STRING_free(bs); + return NULL; + } + } + return bs; +} diff --git a/external/boringssl/crypto/x509v3/v3_conf.c b/external/boringssl/crypto/x509v3/v3_conf.c new file mode 100644 index 0000000000..66abca4e93 --- /dev/null +++ b/external/boringssl/crypto/x509v3/v3_conf.c @@ -0,0 +1,460 @@ +/* v3_conf.c */ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project + * 1999. + */ +/* ==================================================================== + * Copyright (c) 1999-2002 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +/* extension creation utilities */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "../internal.h" + +static int v3_check_critical(char **value); +static int v3_check_generic(char **value); +static X509_EXTENSION *do_ext_nconf(CONF *conf, X509V3_CTX *ctx, int ext_nid, + int crit, char *value); +static X509_EXTENSION *v3_generic_extension(const char *ext, char *value, + int crit, int type, + X509V3_CTX *ctx); +static X509_EXTENSION *do_ext_i2d(const X509V3_EXT_METHOD *method, + int ext_nid, int crit, void *ext_struc); +static unsigned char *generic_asn1(char *value, X509V3_CTX *ctx, + long *ext_len); +/* CONF *conf: Config file */ +/* char *name: Name */ +/* char *value: Value */ +X509_EXTENSION *X509V3_EXT_nconf(CONF *conf, X509V3_CTX *ctx, char *name, + char *value) +{ + int crit; + int ext_type; + X509_EXTENSION *ret; + crit = v3_check_critical(&value); + if ((ext_type = v3_check_generic(&value))) + return v3_generic_extension(name, value, crit, ext_type, ctx); + ret = do_ext_nconf(conf, ctx, OBJ_sn2nid(name), crit, value); + if (!ret) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_ERROR_IN_EXTENSION); + ERR_add_error_data(4, "name=", name, ", value=", value); + } + return ret; +} + +/* CONF *conf: Config file */ +/* char *value: Value */ +X509_EXTENSION *X509V3_EXT_nconf_nid(CONF *conf, X509V3_CTX *ctx, int ext_nid, + char *value) +{ + int crit; + int ext_type; + crit = v3_check_critical(&value); + if ((ext_type = v3_check_generic(&value))) + return v3_generic_extension(OBJ_nid2sn(ext_nid), + value, crit, ext_type, ctx); + return do_ext_nconf(conf, ctx, ext_nid, crit, value); +} + +/* CONF *conf: Config file */ +/* char *value: Value */ +static X509_EXTENSION *do_ext_nconf(CONF *conf, X509V3_CTX *ctx, int ext_nid, + int crit, char *value) +{ + const X509V3_EXT_METHOD *method; + X509_EXTENSION *ext; + STACK_OF(CONF_VALUE) *nval; + void *ext_struc; + if (ext_nid == NID_undef) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNKNOWN_EXTENSION_NAME); + return NULL; + } + if (!(method = X509V3_EXT_get_nid(ext_nid))) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNKNOWN_EXTENSION); + return NULL; + } + /* Now get internal extension representation based on type */ + if (method->v2i) { + if (*value == '@') + nval = NCONF_get_section(conf, value + 1); + else + nval = X509V3_parse_list(value); + if (sk_CONF_VALUE_num(nval) <= 0) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_EXTENSION_STRING); + ERR_add_error_data(4, "name=", OBJ_nid2sn(ext_nid), ",section=", + value); + return NULL; + } + ext_struc = method->v2i(method, ctx, nval); + if (*value != '@') + sk_CONF_VALUE_pop_free(nval, X509V3_conf_free); + if (!ext_struc) + return NULL; + } else if (method->s2i) { + if (!(ext_struc = method->s2i(method, ctx, value))) + return NULL; + } else if (method->r2i) { + if (!ctx->db || !ctx->db_meth) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_CONFIG_DATABASE); + return NULL; + } + if (!(ext_struc = method->r2i(method, ctx, value))) + return NULL; + } else { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_EXTENSION_SETTING_NOT_SUPPORTED); + ERR_add_error_data(2, "name=", OBJ_nid2sn(ext_nid)); + return NULL; + } + + ext = do_ext_i2d(method, ext_nid, crit, ext_struc); + if (method->it) + ASN1_item_free(ext_struc, ASN1_ITEM_ptr(method->it)); + else + method->ext_free(ext_struc); + return ext; + +} + +static X509_EXTENSION *do_ext_i2d(const X509V3_EXT_METHOD *method, + int ext_nid, int crit, void *ext_struc) +{ + unsigned char *ext_der; + int ext_len; + ASN1_OCTET_STRING *ext_oct; + X509_EXTENSION *ext; + /* Convert internal representation to DER */ + if (method->it) { + ext_der = NULL; + ext_len = + ASN1_item_i2d(ext_struc, &ext_der, ASN1_ITEM_ptr(method->it)); + if (ext_len < 0) + goto merr; + } else { + unsigned char *p; + ext_len = method->i2d(ext_struc, NULL); + if (!(ext_der = OPENSSL_malloc(ext_len))) + goto merr; + p = ext_der; + method->i2d(ext_struc, &p); + } + if (!(ext_oct = M_ASN1_OCTET_STRING_new())) + goto merr; + ext_oct->data = ext_der; + ext_oct->length = ext_len; + + ext = X509_EXTENSION_create_by_NID(NULL, ext_nid, crit, ext_oct); + if (!ext) + goto merr; + M_ASN1_OCTET_STRING_free(ext_oct); + + return ext; + + merr: + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + return NULL; + +} + +/* Given an internal structure, nid and critical flag create an extension */ + +X509_EXTENSION *X509V3_EXT_i2d(int ext_nid, int crit, void *ext_struc) +{ + const X509V3_EXT_METHOD *method; + if (!(method = X509V3_EXT_get_nid(ext_nid))) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNKNOWN_EXTENSION); + return NULL; + } + return do_ext_i2d(method, ext_nid, crit, ext_struc); +} + +/* Check the extension string for critical flag */ +static int v3_check_critical(char **value) +{ + char *p = *value; + if ((strlen(p) < 9) || strncmp(p, "critical,", 9)) + return 0; + p += 9; + while (isspace((unsigned char)*p)) + p++; + *value = p; + return 1; +} + +/* Check extension string for generic extension and return the type */ +static int v3_check_generic(char **value) +{ + int gen_type = 0; + char *p = *value; + if ((strlen(p) >= 4) && !strncmp(p, "DER:", 4)) { + p += 4; + gen_type = 1; + } else if ((strlen(p) >= 5) && !strncmp(p, "ASN1:", 5)) { + p += 5; + gen_type = 2; + } else + return 0; + + while (isspace((unsigned char)*p)) + p++; + *value = p; + return gen_type; +} + +/* Create a generic extension: for now just handle DER type */ +static X509_EXTENSION *v3_generic_extension(const char *ext, char *value, + int crit, int gen_type, + X509V3_CTX *ctx) +{ + unsigned char *ext_der = NULL; + long ext_len = 0; + ASN1_OBJECT *obj = NULL; + ASN1_OCTET_STRING *oct = NULL; + X509_EXTENSION *extension = NULL; + if (!(obj = OBJ_txt2obj(ext, 0))) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_EXTENSION_NAME_ERROR); + ERR_add_error_data(2, "name=", ext); + goto err; + } + + if (gen_type == 1) + ext_der = string_to_hex(value, &ext_len); + else if (gen_type == 2) + ext_der = generic_asn1(value, ctx, &ext_len); + + if (ext_der == NULL) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_EXTENSION_VALUE_ERROR); + ERR_add_error_data(2, "value=", value); + goto err; + } + + if (!(oct = M_ASN1_OCTET_STRING_new())) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + goto err; + } + + oct->data = ext_der; + oct->length = ext_len; + ext_der = NULL; + + extension = X509_EXTENSION_create_by_OBJ(NULL, obj, crit, oct); + + err: + ASN1_OBJECT_free(obj); + M_ASN1_OCTET_STRING_free(oct); + if (ext_der) + OPENSSL_free(ext_der); + return extension; + +} + +static unsigned char *generic_asn1(char *value, X509V3_CTX *ctx, + long *ext_len) +{ + ASN1_TYPE *typ; + unsigned char *ext_der = NULL; + typ = ASN1_generate_v3(value, ctx); + if (typ == NULL) + return NULL; + *ext_len = i2d_ASN1_TYPE(typ, &ext_der); + ASN1_TYPE_free(typ); + return ext_der; +} + +/* + * This is the main function: add a bunch of extensions based on a config + * file section to an extension STACK. + */ + +int X509V3_EXT_add_nconf_sk(CONF *conf, X509V3_CTX *ctx, char *section, + STACK_OF(X509_EXTENSION) **sk) +{ + X509_EXTENSION *ext; + STACK_OF(CONF_VALUE) *nval; + CONF_VALUE *val; + size_t i; + if (!(nval = NCONF_get_section(conf, section))) + return 0; + for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { + val = sk_CONF_VALUE_value(nval, i); + if (!(ext = X509V3_EXT_nconf(conf, ctx, val->name, val->value))) + return 0; + if (sk) + X509v3_add_ext(sk, ext, -1); + X509_EXTENSION_free(ext); + } + return 1; +} + +/* + * Convenience functions to add extensions to a certificate, CRL and request + */ + +int X509V3_EXT_add_nconf(CONF *conf, X509V3_CTX *ctx, char *section, + X509 *cert) +{ + STACK_OF(X509_EXTENSION) **sk = NULL; + if (cert) + sk = &cert->cert_info->extensions; + return X509V3_EXT_add_nconf_sk(conf, ctx, section, sk); +} + +/* Same as above but for a CRL */ + +int X509V3_EXT_CRL_add_nconf(CONF *conf, X509V3_CTX *ctx, char *section, + X509_CRL *crl) +{ + STACK_OF(X509_EXTENSION) **sk = NULL; + if (crl) + sk = &crl->crl->extensions; + return X509V3_EXT_add_nconf_sk(conf, ctx, section, sk); +} + +/* Add extensions to certificate request */ + +int X509V3_EXT_REQ_add_nconf(CONF *conf, X509V3_CTX *ctx, char *section, + X509_REQ *req) +{ + STACK_OF(X509_EXTENSION) *extlist = NULL, **sk = NULL; + int i; + if (req) + sk = &extlist; + i = X509V3_EXT_add_nconf_sk(conf, ctx, section, sk); + if (!i || !sk) + return i; + i = X509_REQ_add_extensions(req, extlist); + sk_X509_EXTENSION_pop_free(extlist, X509_EXTENSION_free); + return i; +} + +/* Config database functions */ + +char *X509V3_get_string(X509V3_CTX *ctx, char *name, char *section) +{ + if (!ctx->db || !ctx->db_meth || !ctx->db_meth->get_string) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_OPERATION_NOT_DEFINED); + return NULL; + } + if (ctx->db_meth->get_string) + return ctx->db_meth->get_string(ctx->db, name, section); + return NULL; +} + +STACK_OF(CONF_VALUE) *X509V3_get_section(X509V3_CTX *ctx, char *section) +{ + if (!ctx->db || !ctx->db_meth || !ctx->db_meth->get_section) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_OPERATION_NOT_DEFINED); + return NULL; + } + if (ctx->db_meth->get_section) + return ctx->db_meth->get_section(ctx->db, section); + return NULL; +} + +void X509V3_string_free(X509V3_CTX *ctx, char *str) +{ + if (!str) + return; + if (ctx->db_meth->free_string) + ctx->db_meth->free_string(ctx->db, str); +} + +void X509V3_section_free(X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *section) +{ + if (!section) + return; + if (ctx->db_meth->free_section) + ctx->db_meth->free_section(ctx->db, section); +} + +static char *nconf_get_string(void *db, char *section, char *value) +{ + /* TODO(fork): this should return a const value. */ + return (char *)NCONF_get_string(db, section, value); +} + +static STACK_OF(CONF_VALUE) *nconf_get_section(void *db, char *section) +{ + return NCONF_get_section(db, section); +} + +static const X509V3_CONF_METHOD nconf_method = { + nconf_get_string, + nconf_get_section, + NULL, + NULL +}; + +void X509V3_set_nconf(X509V3_CTX *ctx, CONF *conf) +{ + ctx->db_meth = &nconf_method; + ctx->db = conf; +} + +void X509V3_set_ctx(X509V3_CTX *ctx, X509 *issuer, X509 *subj, X509_REQ *req, + X509_CRL *crl, int flags) +{ + ctx->issuer_cert = issuer; + ctx->subject_cert = subj; + ctx->crl = crl; + ctx->subject_req = req; + ctx->flags = flags; +} diff --git a/external/boringssl/crypto/x509v3/v3_cpols.c b/external/boringssl/crypto/x509v3/v3_cpols.c new file mode 100644 index 0000000000..d67dcb08e7 --- /dev/null +++ b/external/boringssl/crypto/x509v3/v3_cpols.c @@ -0,0 +1,496 @@ +/* v3_cpols.c */ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project + * 1999. + */ +/* ==================================================================== + * Copyright (c) 1999-2004 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pcy_int.h" + +/* Certificate policies extension support: this one is a bit complex... */ + +static int i2r_certpol(X509V3_EXT_METHOD *method, STACK_OF(POLICYINFO) *pol, + BIO *out, int indent); +static STACK_OF(POLICYINFO) *r2i_certpol(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, char *value); +static void print_qualifiers(BIO *out, STACK_OF(POLICYQUALINFO) *quals, + int indent); +static void print_notice(BIO *out, USERNOTICE *notice, int indent); +static POLICYINFO *policy_section(X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *polstrs, int ia5org); +static POLICYQUALINFO *notice_section(X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *unot, int ia5org); +static int nref_nos(STACK_OF(ASN1_INTEGER) *nnums, STACK_OF(CONF_VALUE) *nos); + +const X509V3_EXT_METHOD v3_cpols = { + NID_certificate_policies, 0, ASN1_ITEM_ref(CERTIFICATEPOLICIES), + 0, 0, 0, 0, + 0, 0, + 0, 0, + (X509V3_EXT_I2R)i2r_certpol, + (X509V3_EXT_R2I)r2i_certpol, + NULL +}; + +ASN1_ITEM_TEMPLATE(CERTIFICATEPOLICIES) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, CERTIFICATEPOLICIES, POLICYINFO) +ASN1_ITEM_TEMPLATE_END(CERTIFICATEPOLICIES) + +IMPLEMENT_ASN1_FUNCTIONS(CERTIFICATEPOLICIES) + +ASN1_SEQUENCE(POLICYINFO) = { + ASN1_SIMPLE(POLICYINFO, policyid, ASN1_OBJECT), + ASN1_SEQUENCE_OF_OPT(POLICYINFO, qualifiers, POLICYQUALINFO) +} ASN1_SEQUENCE_END(POLICYINFO) + +IMPLEMENT_ASN1_FUNCTIONS(POLICYINFO) + +ASN1_ADB_TEMPLATE(policydefault) = ASN1_SIMPLE(POLICYQUALINFO, d.other, ASN1_ANY); + +ASN1_ADB(POLICYQUALINFO) = { + ADB_ENTRY(NID_id_qt_cps, ASN1_SIMPLE(POLICYQUALINFO, d.cpsuri, ASN1_IA5STRING)), + ADB_ENTRY(NID_id_qt_unotice, ASN1_SIMPLE(POLICYQUALINFO, d.usernotice, USERNOTICE)) +} ASN1_ADB_END(POLICYQUALINFO, 0, pqualid, 0, &policydefault_tt, NULL); + +ASN1_SEQUENCE(POLICYQUALINFO) = { + ASN1_SIMPLE(POLICYQUALINFO, pqualid, ASN1_OBJECT), + ASN1_ADB_OBJECT(POLICYQUALINFO) +} ASN1_SEQUENCE_END(POLICYQUALINFO) + +IMPLEMENT_ASN1_FUNCTIONS(POLICYQUALINFO) + +ASN1_SEQUENCE(USERNOTICE) = { + ASN1_OPT(USERNOTICE, noticeref, NOTICEREF), + ASN1_OPT(USERNOTICE, exptext, DISPLAYTEXT) +} ASN1_SEQUENCE_END(USERNOTICE) + +IMPLEMENT_ASN1_FUNCTIONS(USERNOTICE) + +ASN1_SEQUENCE(NOTICEREF) = { + ASN1_SIMPLE(NOTICEREF, organization, DISPLAYTEXT), + ASN1_SEQUENCE_OF(NOTICEREF, noticenos, ASN1_INTEGER) +} ASN1_SEQUENCE_END(NOTICEREF) + +IMPLEMENT_ASN1_FUNCTIONS(NOTICEREF) + +static STACK_OF(POLICYINFO) *r2i_certpol(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, char *value) +{ + STACK_OF(POLICYINFO) *pols = NULL; + char *pstr; + POLICYINFO *pol; + ASN1_OBJECT *pobj; + STACK_OF(CONF_VALUE) *vals; + CONF_VALUE *cnf; + size_t i; + int ia5org; + pols = sk_POLICYINFO_new_null(); + if (pols == NULL) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + return NULL; + } + vals = X509V3_parse_list(value); + if (vals == NULL) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_X509V3_LIB); + goto err; + } + ia5org = 0; + for (i = 0; i < sk_CONF_VALUE_num(vals); i++) { + cnf = sk_CONF_VALUE_value(vals, i); + if (cnf->value || !cnf->name) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_POLICY_IDENTIFIER); + X509V3_conf_err(cnf); + goto err; + } + pstr = cnf->name; + if (!strcmp(pstr, "ia5org")) { + ia5org = 1; + continue; + } else if (*pstr == '@') { + STACK_OF(CONF_VALUE) *polsect; + polsect = X509V3_get_section(ctx, pstr + 1); + if (!polsect) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_SECTION); + + X509V3_conf_err(cnf); + goto err; + } + pol = policy_section(ctx, polsect, ia5org); + X509V3_section_free(ctx, polsect); + if (!pol) + goto err; + } else { + if (!(pobj = OBJ_txt2obj(cnf->name, 0))) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER); + X509V3_conf_err(cnf); + goto err; + } + pol = POLICYINFO_new(); + if (pol == NULL) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + ASN1_OBJECT_free(pobj); + goto err; + } + pol->policyid = pobj; + } + if (!sk_POLICYINFO_push(pols, pol)) { + POLICYINFO_free(pol); + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + goto err; + } + } + sk_CONF_VALUE_pop_free(vals, X509V3_conf_free); + return pols; + err: + sk_CONF_VALUE_pop_free(vals, X509V3_conf_free); + sk_POLICYINFO_pop_free(pols, POLICYINFO_free); + return NULL; +} + +static POLICYINFO *policy_section(X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *polstrs, int ia5org) +{ + size_t i; + CONF_VALUE *cnf; + POLICYINFO *pol; + POLICYQUALINFO *qual; + if (!(pol = POLICYINFO_new())) + goto merr; + for (i = 0; i < sk_CONF_VALUE_num(polstrs); i++) { + cnf = sk_CONF_VALUE_value(polstrs, i); + if (!strcmp(cnf->name, "policyIdentifier")) { + ASN1_OBJECT *pobj; + if (!(pobj = OBJ_txt2obj(cnf->value, 0))) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER); + X509V3_conf_err(cnf); + goto err; + } + pol->policyid = pobj; + + } else if (!name_cmp(cnf->name, "CPS")) { + if (!pol->qualifiers) + pol->qualifiers = sk_POLICYQUALINFO_new_null(); + if (!(qual = POLICYQUALINFO_new())) + goto merr; + if (!sk_POLICYQUALINFO_push(pol->qualifiers, qual)) + goto merr; + /* TODO(fork): const correctness */ + qual->pqualid = (ASN1_OBJECT *)OBJ_nid2obj(NID_id_qt_cps); + if (qual->pqualid == NULL) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_INTERNAL_ERROR); + goto err; + } + qual->d.cpsuri = M_ASN1_IA5STRING_new(); + if (qual->d.cpsuri == NULL) { + goto err; + } + if (!ASN1_STRING_set(qual->d.cpsuri, cnf->value, + strlen(cnf->value))) + goto merr; + } else if (!name_cmp(cnf->name, "userNotice")) { + STACK_OF(CONF_VALUE) *unot; + if (*cnf->value != '@') { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_EXPECTED_A_SECTION_NAME); + X509V3_conf_err(cnf); + goto err; + } + unot = X509V3_get_section(ctx, cnf->value + 1); + if (!unot) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_SECTION); + + X509V3_conf_err(cnf); + goto err; + } + qual = notice_section(ctx, unot, ia5org); + X509V3_section_free(ctx, unot); + if (!qual) + goto err; + if (!pol->qualifiers) + pol->qualifiers = sk_POLICYQUALINFO_new_null(); + if (!sk_POLICYQUALINFO_push(pol->qualifiers, qual)) + goto merr; + } else { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OPTION); + + X509V3_conf_err(cnf); + goto err; + } + } + if (!pol->policyid) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_POLICY_IDENTIFIER); + goto err; + } + + return pol; + + merr: + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + + err: + POLICYINFO_free(pol); + return NULL; + +} + +static POLICYQUALINFO *notice_section(X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *unot, int ia5org) +{ + size_t i; + int ret; + CONF_VALUE *cnf; + USERNOTICE *not; + POLICYQUALINFO *qual; + if (!(qual = POLICYQUALINFO_new())) + goto merr; + /* TODO(fork): const correctness */ + qual->pqualid = (ASN1_OBJECT *)OBJ_nid2obj(NID_id_qt_unotice); + if (qual->pqualid == NULL) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_INTERNAL_ERROR); + goto err; + } + if (!(not = USERNOTICE_new())) + goto merr; + qual->d.usernotice = not; + for (i = 0; i < sk_CONF_VALUE_num(unot); i++) { + cnf = sk_CONF_VALUE_value(unot, i); + if (!strcmp(cnf->name, "explicitText")) { + not->exptext = M_ASN1_VISIBLESTRING_new(); + if (not->exptext == NULL) + goto merr; + if (!ASN1_STRING_set(not->exptext, cnf->value, + strlen(cnf->value))) + goto merr; + } else if (!strcmp(cnf->name, "organization")) { + NOTICEREF *nref; + if (!not->noticeref) { + if (!(nref = NOTICEREF_new())) + goto merr; + not->noticeref = nref; + } else + nref = not->noticeref; + if (ia5org) + nref->organization->type = V_ASN1_IA5STRING; + else + nref->organization->type = V_ASN1_VISIBLESTRING; + if (!ASN1_STRING_set(nref->organization, cnf->value, + strlen(cnf->value))) + goto merr; + } else if (!strcmp(cnf->name, "noticeNumbers")) { + NOTICEREF *nref; + STACK_OF(CONF_VALUE) *nos; + if (!not->noticeref) { + if (!(nref = NOTICEREF_new())) + goto merr; + not->noticeref = nref; + } else + nref = not->noticeref; + nos = X509V3_parse_list(cnf->value); + if (!nos || !sk_CONF_VALUE_num(nos)) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NUMBERS); + X509V3_conf_err(cnf); + goto err; + } + ret = nref_nos(nref->noticenos, nos); + sk_CONF_VALUE_pop_free(nos, X509V3_conf_free); + if (!ret) + goto err; + } else { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OPTION); + X509V3_conf_err(cnf); + goto err; + } + } + + if (not->noticeref && + (!not->noticeref->noticenos || !not->noticeref->organization)) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_NEED_ORGANIZATION_AND_NUMBERS); + goto err; + } + + return qual; + + merr: + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + + err: + POLICYQUALINFO_free(qual); + return NULL; +} + +static int nref_nos(STACK_OF(ASN1_INTEGER) *nnums, STACK_OF(CONF_VALUE) *nos) +{ + CONF_VALUE *cnf; + ASN1_INTEGER *aint; + + size_t i; + + for (i = 0; i < sk_CONF_VALUE_num(nos); i++) { + cnf = sk_CONF_VALUE_value(nos, i); + if (!(aint = s2i_ASN1_INTEGER(NULL, cnf->name))) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NUMBER); + goto err; + } + if (!sk_ASN1_INTEGER_push(nnums, aint)) + goto merr; + } + return 1; + + merr: + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + + err: + sk_ASN1_INTEGER_pop_free(nnums, ASN1_STRING_free); + return 0; +} + +static int i2r_certpol(X509V3_EXT_METHOD *method, STACK_OF(POLICYINFO) *pol, + BIO *out, int indent) +{ + size_t i; + POLICYINFO *pinfo; + /* First print out the policy OIDs */ + for (i = 0; i < sk_POLICYINFO_num(pol); i++) { + pinfo = sk_POLICYINFO_value(pol, i); + BIO_printf(out, "%*sPolicy: ", indent, ""); + i2a_ASN1_OBJECT(out, pinfo->policyid); + BIO_puts(out, "\n"); + if (pinfo->qualifiers) + print_qualifiers(out, pinfo->qualifiers, indent + 2); + } + return 1; +} + +static void print_qualifiers(BIO *out, STACK_OF(POLICYQUALINFO) *quals, + int indent) +{ + POLICYQUALINFO *qualinfo; + size_t i; + for (i = 0; i < sk_POLICYQUALINFO_num(quals); i++) { + qualinfo = sk_POLICYQUALINFO_value(quals, i); + switch (OBJ_obj2nid(qualinfo->pqualid)) { + case NID_id_qt_cps: + BIO_printf(out, "%*sCPS: %s\n", indent, "", + qualinfo->d.cpsuri->data); + break; + + case NID_id_qt_unotice: + BIO_printf(out, "%*sUser Notice:\n", indent, ""); + print_notice(out, qualinfo->d.usernotice, indent + 2); + break; + + default: + BIO_printf(out, "%*sUnknown Qualifier: ", indent + 2, ""); + + i2a_ASN1_OBJECT(out, qualinfo->pqualid); + BIO_puts(out, "\n"); + break; + } + } +} + +static void print_notice(BIO *out, USERNOTICE *notice, int indent) +{ + size_t i; + if (notice->noticeref) { + NOTICEREF *ref; + ref = notice->noticeref; + BIO_printf(out, "%*sOrganization: %s\n", indent, "", + ref->organization->data); + BIO_printf(out, "%*sNumber%s: ", indent, "", + sk_ASN1_INTEGER_num(ref->noticenos) > 1 ? "s" : ""); + for (i = 0; i < sk_ASN1_INTEGER_num(ref->noticenos); i++) { + ASN1_INTEGER *num; + char *tmp; + num = sk_ASN1_INTEGER_value(ref->noticenos, i); + if (i) + BIO_puts(out, ", "); + tmp = i2s_ASN1_INTEGER(NULL, num); + BIO_puts(out, tmp); + OPENSSL_free(tmp); + } + BIO_puts(out, "\n"); + } + if (notice->exptext) + BIO_printf(out, "%*sExplicit Text: %s\n", indent, "", + notice->exptext->data); +} + +void X509_POLICY_NODE_print(BIO *out, X509_POLICY_NODE *node, int indent) +{ + const X509_POLICY_DATA *dat = node->data; + + BIO_printf(out, "%*sPolicy: ", indent, ""); + + i2a_ASN1_OBJECT(out, dat->valid_policy); + BIO_puts(out, "\n"); + BIO_printf(out, "%*s%s\n", indent + 2, "", + node_data_critical(dat) ? "Critical" : "Non Critical"); + if (dat->qualifier_set) + print_qualifiers(out, dat->qualifier_set, indent + 2); + else + BIO_printf(out, "%*sNo Qualifiers\n", indent + 2, ""); +} diff --git a/external/boringssl/crypto/x509v3/v3_crld.c b/external/boringssl/crypto/x509v3/v3_crld.c new file mode 100644 index 0000000000..c93c44955d --- /dev/null +++ b/external/boringssl/crypto/x509v3/v3_crld.c @@ -0,0 +1,561 @@ +/* v3_crld.c */ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project + * 1999. + */ +/* ==================================================================== + * Copyright (c) 1999-2008 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +static void *v2i_crld(const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval); +static int i2r_crldp(const X509V3_EXT_METHOD *method, void *pcrldp, BIO *out, + int indent); + +const X509V3_EXT_METHOD v3_crld = { + NID_crl_distribution_points, 0, ASN1_ITEM_ref(CRL_DIST_POINTS), + 0, 0, 0, 0, + 0, 0, + 0, + v2i_crld, + i2r_crldp, 0, + NULL +}; + +const X509V3_EXT_METHOD v3_freshest_crl = { + NID_freshest_crl, 0, ASN1_ITEM_ref(CRL_DIST_POINTS), + 0, 0, 0, 0, + 0, 0, + 0, + v2i_crld, + i2r_crldp, 0, + NULL +}; + +static STACK_OF(GENERAL_NAME) *gnames_from_sectname(X509V3_CTX *ctx, + char *sect) +{ + STACK_OF(CONF_VALUE) *gnsect; + STACK_OF(GENERAL_NAME) *gens; + if (*sect == '@') + gnsect = X509V3_get_section(ctx, sect + 1); + else + gnsect = X509V3_parse_list(sect); + if (!gnsect) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_SECTION_NOT_FOUND); + return NULL; + } + gens = v2i_GENERAL_NAMES(NULL, ctx, gnsect); + if (*sect == '@') + X509V3_section_free(ctx, gnsect); + else + sk_CONF_VALUE_pop_free(gnsect, X509V3_conf_free); + return gens; +} + +static int set_dist_point_name(DIST_POINT_NAME **pdp, X509V3_CTX *ctx, + CONF_VALUE *cnf) +{ + STACK_OF(GENERAL_NAME) *fnm = NULL; + STACK_OF(X509_NAME_ENTRY) *rnm = NULL; + if (!strncmp(cnf->name, "fullname", 9)) { + fnm = gnames_from_sectname(ctx, cnf->value); + if (!fnm) + goto err; + } else if (!strcmp(cnf->name, "relativename")) { + int ret; + STACK_OF(CONF_VALUE) *dnsect; + X509_NAME *nm; + nm = X509_NAME_new(); + if (!nm) + return -1; + dnsect = X509V3_get_section(ctx, cnf->value); + if (!dnsect) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_SECTION_NOT_FOUND); + return -1; + } + ret = X509V3_NAME_from_section(nm, dnsect, MBSTRING_ASC); + X509V3_section_free(ctx, dnsect); + rnm = nm->entries; + nm->entries = NULL; + X509_NAME_free(nm); + if (!ret || sk_X509_NAME_ENTRY_num(rnm) <= 0) + goto err; + /* + * Since its a name fragment can't have more than one RDNSequence + */ + if (sk_X509_NAME_ENTRY_value(rnm, + sk_X509_NAME_ENTRY_num(rnm) - 1)->set) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_MULTIPLE_RDNS); + goto err; + } + } else + return 0; + + if (*pdp) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_DISTPOINT_ALREADY_SET); + goto err; + } + + *pdp = DIST_POINT_NAME_new(); + if (!*pdp) + goto err; + if (fnm) { + (*pdp)->type = 0; + (*pdp)->name.fullname = fnm; + } else { + (*pdp)->type = 1; + (*pdp)->name.relativename = rnm; + } + + return 1; + + err: + if (fnm) + sk_GENERAL_NAME_pop_free(fnm, GENERAL_NAME_free); + if (rnm) + sk_X509_NAME_ENTRY_pop_free(rnm, X509_NAME_ENTRY_free); + return -1; +} + +static const BIT_STRING_BITNAME reason_flags[] = { + {0, "Unused", "unused"}, + {1, "Key Compromise", "keyCompromise"}, + {2, "CA Compromise", "CACompromise"}, + {3, "Affiliation Changed", "affiliationChanged"}, + {4, "Superseded", "superseded"}, + {5, "Cessation Of Operation", "cessationOfOperation"}, + {6, "Certificate Hold", "certificateHold"}, + {7, "Privilege Withdrawn", "privilegeWithdrawn"}, + {8, "AA Compromise", "AACompromise"}, + {-1, NULL, NULL} +}; + +static int set_reasons(ASN1_BIT_STRING **preas, char *value) +{ + STACK_OF(CONF_VALUE) *rsk = NULL; + const BIT_STRING_BITNAME *pbn; + const char *bnam; + size_t i; + int ret = 0; + rsk = X509V3_parse_list(value); + if (!rsk) + return 0; + if (*preas) + return 0; + for (i = 0; i < sk_CONF_VALUE_num(rsk); i++) { + bnam = sk_CONF_VALUE_value(rsk, i)->name; + if (!*preas) { + *preas = ASN1_BIT_STRING_new(); + if (!*preas) + goto err; + } + for (pbn = reason_flags; pbn->lname; pbn++) { + if (!strcmp(pbn->sname, bnam)) { + if (!ASN1_BIT_STRING_set_bit(*preas, pbn->bitnum, 1)) + goto err; + break; + } + } + if (!pbn->lname) + goto err; + } + ret = 1; + + err: + sk_CONF_VALUE_pop_free(rsk, X509V3_conf_free); + return ret; +} + +static int print_reasons(BIO *out, const char *rname, + ASN1_BIT_STRING *rflags, int indent) +{ + int first = 1; + const BIT_STRING_BITNAME *pbn; + BIO_printf(out, "%*s%s:\n%*s", indent, "", rname, indent + 2, ""); + for (pbn = reason_flags; pbn->lname; pbn++) { + if (ASN1_BIT_STRING_get_bit(rflags, pbn->bitnum)) { + if (first) + first = 0; + else + BIO_puts(out, ", "); + BIO_puts(out, pbn->lname); + } + } + if (first) + BIO_puts(out, "\n"); + else + BIO_puts(out, "\n"); + return 1; +} + +static DIST_POINT *crldp_from_section(X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *nval) +{ + size_t i; + CONF_VALUE *cnf; + DIST_POINT *point = NULL; + point = DIST_POINT_new(); + if (!point) + goto err; + for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { + int ret; + cnf = sk_CONF_VALUE_value(nval, i); + ret = set_dist_point_name(&point->distpoint, ctx, cnf); + if (ret > 0) + continue; + if (ret < 0) + goto err; + if (!strcmp(cnf->name, "reasons")) { + if (!set_reasons(&point->reasons, cnf->value)) + goto err; + } else if (!strcmp(cnf->name, "CRLissuer")) { + point->CRLissuer = gnames_from_sectname(ctx, cnf->value); + if (!point->CRLissuer) + goto err; + } + } + + return point; + + err: + if (point) + DIST_POINT_free(point); + return NULL; +} + +static void *v2i_crld(const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval) +{ + STACK_OF(DIST_POINT) *crld = NULL; + GENERAL_NAMES *gens = NULL; + GENERAL_NAME *gen = NULL; + CONF_VALUE *cnf; + size_t i; + if (!(crld = sk_DIST_POINT_new_null())) + goto merr; + for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { + DIST_POINT *point; + cnf = sk_CONF_VALUE_value(nval, i); + if (!cnf->value) { + STACK_OF(CONF_VALUE) *dpsect; + dpsect = X509V3_get_section(ctx, cnf->name); + if (!dpsect) + goto err; + point = crldp_from_section(ctx, dpsect); + X509V3_section_free(ctx, dpsect); + if (!point) + goto err; + if (!sk_DIST_POINT_push(crld, point)) { + DIST_POINT_free(point); + goto merr; + } + } else { + if (!(gen = v2i_GENERAL_NAME(method, ctx, cnf))) + goto err; + if (!(gens = GENERAL_NAMES_new())) + goto merr; + if (!sk_GENERAL_NAME_push(gens, gen)) + goto merr; + gen = NULL; + if (!(point = DIST_POINT_new())) + goto merr; + if (!sk_DIST_POINT_push(crld, point)) { + DIST_POINT_free(point); + goto merr; + } + if (!(point->distpoint = DIST_POINT_NAME_new())) + goto merr; + point->distpoint->name.fullname = gens; + point->distpoint->type = 0; + gens = NULL; + } + } + return crld; + + merr: + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + err: + GENERAL_NAME_free(gen); + GENERAL_NAMES_free(gens); + sk_DIST_POINT_pop_free(crld, DIST_POINT_free); + return NULL; +} + +IMPLEMENT_ASN1_SET_OF(DIST_POINT) + +static int dpn_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, + void *exarg) +{ + DIST_POINT_NAME *dpn = (DIST_POINT_NAME *)*pval; + + switch (operation) { + case ASN1_OP_NEW_POST: + dpn->dpname = NULL; + break; + + case ASN1_OP_FREE_POST: + if (dpn->dpname) + X509_NAME_free(dpn->dpname); + break; + } + return 1; +} + + +ASN1_CHOICE_cb(DIST_POINT_NAME, dpn_cb) = { + ASN1_IMP_SEQUENCE_OF(DIST_POINT_NAME, name.fullname, GENERAL_NAME, 0), + ASN1_IMP_SET_OF(DIST_POINT_NAME, name.relativename, X509_NAME_ENTRY, 1) +} ASN1_CHOICE_END_cb(DIST_POINT_NAME, DIST_POINT_NAME, type) + + +IMPLEMENT_ASN1_FUNCTIONS(DIST_POINT_NAME) + +ASN1_SEQUENCE(DIST_POINT) = { + ASN1_EXP_OPT(DIST_POINT, distpoint, DIST_POINT_NAME, 0), + ASN1_IMP_OPT(DIST_POINT, reasons, ASN1_BIT_STRING, 1), + ASN1_IMP_SEQUENCE_OF_OPT(DIST_POINT, CRLissuer, GENERAL_NAME, 2) +} ASN1_SEQUENCE_END(DIST_POINT) + +IMPLEMENT_ASN1_FUNCTIONS(DIST_POINT) + +ASN1_ITEM_TEMPLATE(CRL_DIST_POINTS) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, CRLDistributionPoints, DIST_POINT) +ASN1_ITEM_TEMPLATE_END(CRL_DIST_POINTS) + +IMPLEMENT_ASN1_FUNCTIONS(CRL_DIST_POINTS) + +ASN1_SEQUENCE(ISSUING_DIST_POINT) = { + ASN1_EXP_OPT(ISSUING_DIST_POINT, distpoint, DIST_POINT_NAME, 0), + ASN1_IMP_OPT(ISSUING_DIST_POINT, onlyuser, ASN1_FBOOLEAN, 1), + ASN1_IMP_OPT(ISSUING_DIST_POINT, onlyCA, ASN1_FBOOLEAN, 2), + ASN1_IMP_OPT(ISSUING_DIST_POINT, onlysomereasons, ASN1_BIT_STRING, 3), + ASN1_IMP_OPT(ISSUING_DIST_POINT, indirectCRL, ASN1_FBOOLEAN, 4), + ASN1_IMP_OPT(ISSUING_DIST_POINT, onlyattr, ASN1_FBOOLEAN, 5) +} ASN1_SEQUENCE_END(ISSUING_DIST_POINT) + +IMPLEMENT_ASN1_FUNCTIONS(ISSUING_DIST_POINT) + +static int i2r_idp(const X509V3_EXT_METHOD *method, void *pidp, BIO *out, + int indent); +static void *v2i_idp(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *nval); + +const X509V3_EXT_METHOD v3_idp = { + NID_issuing_distribution_point, X509V3_EXT_MULTILINE, + ASN1_ITEM_ref(ISSUING_DIST_POINT), + 0, 0, 0, 0, + 0, 0, + 0, + v2i_idp, + i2r_idp, 0, + NULL +}; + +static void *v2i_idp(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *nval) +{ + ISSUING_DIST_POINT *idp = NULL; + CONF_VALUE *cnf; + char *name, *val; + size_t i; + int ret; + idp = ISSUING_DIST_POINT_new(); + if (!idp) + goto merr; + for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { + cnf = sk_CONF_VALUE_value(nval, i); + name = cnf->name; + val = cnf->value; + ret = set_dist_point_name(&idp->distpoint, ctx, cnf); + if (ret > 0) + continue; + if (ret < 0) + goto err; + if (!strcmp(name, "onlyuser")) { + if (!X509V3_get_value_bool(cnf, &idp->onlyuser)) + goto err; + } else if (!strcmp(name, "onlyCA")) { + if (!X509V3_get_value_bool(cnf, &idp->onlyCA)) + goto err; + } else if (!strcmp(name, "onlyAA")) { + if (!X509V3_get_value_bool(cnf, &idp->onlyattr)) + goto err; + } else if (!strcmp(name, "indirectCRL")) { + if (!X509V3_get_value_bool(cnf, &idp->indirectCRL)) + goto err; + } else if (!strcmp(name, "onlysomereasons")) { + if (!set_reasons(&idp->onlysomereasons, val)) + goto err; + } else { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NAME); + X509V3_conf_err(cnf); + goto err; + } + } + return idp; + + merr: + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + err: + ISSUING_DIST_POINT_free(idp); + return NULL; +} + +static int print_gens(BIO *out, STACK_OF(GENERAL_NAME) *gens, int indent) +{ + size_t i; + for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { + BIO_printf(out, "%*s", indent + 2, ""); + GENERAL_NAME_print(out, sk_GENERAL_NAME_value(gens, i)); + BIO_puts(out, "\n"); + } + return 1; +} + +static int print_distpoint(BIO *out, DIST_POINT_NAME *dpn, int indent) +{ + if (dpn->type == 0) { + BIO_printf(out, "%*sFull Name:\n", indent, ""); + print_gens(out, dpn->name.fullname, indent); + } else { + X509_NAME ntmp; + ntmp.entries = dpn->name.relativename; + BIO_printf(out, "%*sRelative Name:\n%*s", indent, "", indent + 2, ""); + X509_NAME_print_ex(out, &ntmp, 0, XN_FLAG_ONELINE); + BIO_puts(out, "\n"); + } + return 1; +} + +static int i2r_idp(const X509V3_EXT_METHOD *method, void *pidp, BIO *out, + int indent) +{ + ISSUING_DIST_POINT *idp = pidp; + if (idp->distpoint) + print_distpoint(out, idp->distpoint, indent); + if (idp->onlyuser > 0) + BIO_printf(out, "%*sOnly User Certificates\n", indent, ""); + if (idp->onlyCA > 0) + BIO_printf(out, "%*sOnly CA Certificates\n", indent, ""); + if (idp->indirectCRL > 0) + BIO_printf(out, "%*sIndirect CRL\n", indent, ""); + if (idp->onlysomereasons) + print_reasons(out, "Only Some Reasons", idp->onlysomereasons, indent); + if (idp->onlyattr > 0) + BIO_printf(out, "%*sOnly Attribute Certificates\n", indent, ""); + if (!idp->distpoint && (idp->onlyuser <= 0) && (idp->onlyCA <= 0) + && (idp->indirectCRL <= 0) && !idp->onlysomereasons + && (idp->onlyattr <= 0)) + BIO_printf(out, "%*s\n", indent, ""); + + return 1; +} + +static int i2r_crldp(const X509V3_EXT_METHOD *method, void *pcrldp, BIO *out, + int indent) +{ + STACK_OF(DIST_POINT) *crld = pcrldp; + DIST_POINT *point; + size_t i; + for (i = 0; i < sk_DIST_POINT_num(crld); i++) { + BIO_puts(out, "\n"); + point = sk_DIST_POINT_value(crld, i); + if (point->distpoint) + print_distpoint(out, point->distpoint, indent); + if (point->reasons) + print_reasons(out, "Reasons", point->reasons, indent); + if (point->CRLissuer) { + BIO_printf(out, "%*sCRL Issuer:\n", indent, ""); + print_gens(out, point->CRLissuer, indent); + } + } + return 1; +} + +int DIST_POINT_set_dpname(DIST_POINT_NAME *dpn, X509_NAME *iname) +{ + size_t i; + STACK_OF(X509_NAME_ENTRY) *frag; + X509_NAME_ENTRY *ne; + if (!dpn || (dpn->type != 1)) + return 1; + frag = dpn->name.relativename; + dpn->dpname = X509_NAME_dup(iname); + if (!dpn->dpname) + return 0; + for (i = 0; i < sk_X509_NAME_ENTRY_num(frag); i++) { + ne = sk_X509_NAME_ENTRY_value(frag, i); + if (!X509_NAME_add_entry(dpn->dpname, ne, -1, i ? 0 : 1)) { + X509_NAME_free(dpn->dpname); + dpn->dpname = NULL; + return 0; + } + } + /* generate cached encoding of name */ + if (i2d_X509_NAME(dpn->dpname, NULL) < 0) { + X509_NAME_free(dpn->dpname); + dpn->dpname = NULL; + return 0; + } + return 1; +} diff --git a/external/boringssl/crypto/x509v3/v3_enum.c b/external/boringssl/crypto/x509v3/v3_enum.c new file mode 100644 index 0000000000..6bfb232c5c --- /dev/null +++ b/external/boringssl/crypto/x509v3/v3_enum.c @@ -0,0 +1,100 @@ +/* v3_enum.c */ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project + * 1999. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include +#include + +static const ENUMERATED_NAMES crl_reasons[] = { + {CRL_REASON_UNSPECIFIED, "Unspecified", "unspecified"}, + {CRL_REASON_KEY_COMPROMISE, "Key Compromise", "keyCompromise"}, + {CRL_REASON_CA_COMPROMISE, "CA Compromise", "CACompromise"}, + {CRL_REASON_AFFILIATION_CHANGED, "Affiliation Changed", + "affiliationChanged"}, + {CRL_REASON_SUPERSEDED, "Superseded", "superseded"}, + {CRL_REASON_CESSATION_OF_OPERATION, + "Cessation Of Operation", "cessationOfOperation"}, + {CRL_REASON_CERTIFICATE_HOLD, "Certificate Hold", "certificateHold"}, + {CRL_REASON_REMOVE_FROM_CRL, "Remove From CRL", "removeFromCRL"}, + {CRL_REASON_PRIVILEGE_WITHDRAWN, "Privilege Withdrawn", + "privilegeWithdrawn"}, + {CRL_REASON_AA_COMPROMISE, "AA Compromise", "AACompromise"}, + {-1, NULL, NULL} +}; + +const X509V3_EXT_METHOD v3_crl_reason = { + NID_crl_reason, 0, ASN1_ITEM_ref(ASN1_ENUMERATED), + 0, 0, 0, 0, + (X509V3_EXT_I2S)i2s_ASN1_ENUMERATED_TABLE, + 0, + 0, 0, 0, 0, + (void *)crl_reasons +}; + +char *i2s_ASN1_ENUMERATED_TABLE(X509V3_EXT_METHOD *method, ASN1_ENUMERATED *e) +{ + const ENUMERATED_NAMES *enam; + long strval; + strval = ASN1_ENUMERATED_get(e); + for (enam = method->usr_data; enam->lname; enam++) { + if (strval == enam->bitnum) + return BUF_strdup(enam->lname); + } + return i2s_ASN1_ENUMERATED(method, e); +} diff --git a/external/boringssl/crypto/x509v3/v3_extku.c b/external/boringssl/crypto/x509v3/v3_extku.c new file mode 100644 index 0000000000..952e032c21 --- /dev/null +++ b/external/boringssl/crypto/x509v3/v3_extku.c @@ -0,0 +1,148 @@ +/* v3_extku.c */ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project + * 1999. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include +#include +#include +#include + +static void *v2i_EXTENDED_KEY_USAGE(const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *nval); +static STACK_OF(CONF_VALUE) *i2v_EXTENDED_KEY_USAGE(const X509V3_EXT_METHOD + *method, void *eku, STACK_OF(CONF_VALUE) + *extlist); + +const X509V3_EXT_METHOD v3_ext_ku = { + NID_ext_key_usage, 0, + ASN1_ITEM_ref(EXTENDED_KEY_USAGE), + 0, 0, 0, 0, + 0, 0, + i2v_EXTENDED_KEY_USAGE, + v2i_EXTENDED_KEY_USAGE, + 0, 0, + NULL +}; + +/* NB OCSP acceptable responses also is a SEQUENCE OF OBJECT */ +const X509V3_EXT_METHOD v3_ocsp_accresp = { + NID_id_pkix_OCSP_acceptableResponses, 0, + ASN1_ITEM_ref(EXTENDED_KEY_USAGE), + 0, 0, 0, 0, + 0, 0, + i2v_EXTENDED_KEY_USAGE, + v2i_EXTENDED_KEY_USAGE, + 0, 0, + NULL +}; + +ASN1_ITEM_TEMPLATE(EXTENDED_KEY_USAGE) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, EXTENDED_KEY_USAGE, ASN1_OBJECT) +ASN1_ITEM_TEMPLATE_END(EXTENDED_KEY_USAGE) + +IMPLEMENT_ASN1_FUNCTIONS(EXTENDED_KEY_USAGE) + +static STACK_OF(CONF_VALUE) *i2v_EXTENDED_KEY_USAGE(const X509V3_EXT_METHOD + *method, void *a, STACK_OF(CONF_VALUE) + *ext_list) +{ + EXTENDED_KEY_USAGE *eku = a; + size_t i; + ASN1_OBJECT *obj; + char obj_tmp[80]; + for (i = 0; i < sk_ASN1_OBJECT_num(eku); i++) { + obj = sk_ASN1_OBJECT_value(eku, i); + i2t_ASN1_OBJECT(obj_tmp, 80, obj); + X509V3_add_value(NULL, obj_tmp, &ext_list); + } + return ext_list; +} + +static void *v2i_EXTENDED_KEY_USAGE(const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *nval) +{ + EXTENDED_KEY_USAGE *extku; + char *extval; + ASN1_OBJECT *objtmp; + CONF_VALUE *val; + size_t i; + + if (!(extku = sk_ASN1_OBJECT_new_null())) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + return NULL; + } + + for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { + val = sk_CONF_VALUE_value(nval, i); + if (val->value) + extval = val->value; + else + extval = val->name; + if (!(objtmp = OBJ_txt2obj(extval, 0))) { + sk_ASN1_OBJECT_pop_free(extku, ASN1_OBJECT_free); + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER); + X509V3_conf_err(val); + return NULL; + } + sk_ASN1_OBJECT_push(extku, objtmp); + } + return extku; +} diff --git a/external/boringssl/crypto/x509v3/v3_genn.c b/external/boringssl/crypto/x509v3/v3_genn.c new file mode 100644 index 0000000000..2331cd490d --- /dev/null +++ b/external/boringssl/crypto/x509v3/v3_genn.c @@ -0,0 +1,250 @@ +/* v3_genn.c */ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project + * 1999. + */ +/* ==================================================================== + * Copyright (c) 1999-2008 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include +#include +#include + + +ASN1_SEQUENCE(OTHERNAME) = { + ASN1_SIMPLE(OTHERNAME, type_id, ASN1_OBJECT), + /* Maybe have a true ANY DEFINED BY later */ + ASN1_EXP(OTHERNAME, value, ASN1_ANY, 0) +} ASN1_SEQUENCE_END(OTHERNAME) + +IMPLEMENT_ASN1_FUNCTIONS(OTHERNAME) + +ASN1_SEQUENCE(EDIPARTYNAME) = { + ASN1_IMP_OPT(EDIPARTYNAME, nameAssigner, DIRECTORYSTRING, 0), + ASN1_IMP_OPT(EDIPARTYNAME, partyName, DIRECTORYSTRING, 1) +} ASN1_SEQUENCE_END(EDIPARTYNAME) + +IMPLEMENT_ASN1_FUNCTIONS(EDIPARTYNAME) + +ASN1_CHOICE(GENERAL_NAME) = { + ASN1_IMP(GENERAL_NAME, d.otherName, OTHERNAME, GEN_OTHERNAME), + ASN1_IMP(GENERAL_NAME, d.rfc822Name, ASN1_IA5STRING, GEN_EMAIL), + ASN1_IMP(GENERAL_NAME, d.dNSName, ASN1_IA5STRING, GEN_DNS), + /* Don't decode this */ + ASN1_IMP(GENERAL_NAME, d.x400Address, ASN1_SEQUENCE, GEN_X400), + /* X509_NAME is a CHOICE type so use EXPLICIT */ + ASN1_EXP(GENERAL_NAME, d.directoryName, X509_NAME, GEN_DIRNAME), + ASN1_IMP(GENERAL_NAME, d.ediPartyName, EDIPARTYNAME, GEN_EDIPARTY), + ASN1_IMP(GENERAL_NAME, d.uniformResourceIdentifier, ASN1_IA5STRING, GEN_URI), + ASN1_IMP(GENERAL_NAME, d.iPAddress, ASN1_OCTET_STRING, GEN_IPADD), + ASN1_IMP(GENERAL_NAME, d.registeredID, ASN1_OBJECT, GEN_RID) +} ASN1_CHOICE_END(GENERAL_NAME) + +IMPLEMENT_ASN1_FUNCTIONS(GENERAL_NAME) + +ASN1_ITEM_TEMPLATE(GENERAL_NAMES) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, GeneralNames, GENERAL_NAME) +ASN1_ITEM_TEMPLATE_END(GENERAL_NAMES) + +IMPLEMENT_ASN1_FUNCTIONS(GENERAL_NAMES) + +GENERAL_NAME *GENERAL_NAME_dup(GENERAL_NAME *a) +{ + return (GENERAL_NAME *)ASN1_dup((i2d_of_void *)i2d_GENERAL_NAME, + (d2i_of_void *)d2i_GENERAL_NAME, + (char *)a); +} + +/* Returns 0 if they are equal, != 0 otherwise. */ +int GENERAL_NAME_cmp(GENERAL_NAME *a, GENERAL_NAME *b) +{ + int result = -1; + + if (!a || !b || a->type != b->type) + return -1; + switch (a->type) { + case GEN_X400: + case GEN_EDIPARTY: + result = ASN1_TYPE_cmp(a->d.other, b->d.other); + break; + + case GEN_OTHERNAME: + result = OTHERNAME_cmp(a->d.otherName, b->d.otherName); + break; + + case GEN_EMAIL: + case GEN_DNS: + case GEN_URI: + result = ASN1_STRING_cmp(a->d.ia5, b->d.ia5); + break; + + case GEN_DIRNAME: + result = X509_NAME_cmp(a->d.dirn, b->d.dirn); + break; + + case GEN_IPADD: + result = ASN1_OCTET_STRING_cmp(a->d.ip, b->d.ip); + break; + + case GEN_RID: + result = OBJ_cmp(a->d.rid, b->d.rid); + break; + } + return result; +} + +/* Returns 0 if they are equal, != 0 otherwise. */ +int OTHERNAME_cmp(OTHERNAME *a, OTHERNAME *b) +{ + int result = -1; + + if (!a || !b) + return -1; + /* Check their type first. */ + if ((result = OBJ_cmp(a->type_id, b->type_id)) != 0) + return result; + /* Check the value. */ + result = ASN1_TYPE_cmp(a->value, b->value); + return result; +} + +void GENERAL_NAME_set0_value(GENERAL_NAME *a, int type, void *value) +{ + switch (type) { + case GEN_X400: + case GEN_EDIPARTY: + a->d.other = value; + break; + + case GEN_OTHERNAME: + a->d.otherName = value; + break; + + case GEN_EMAIL: + case GEN_DNS: + case GEN_URI: + a->d.ia5 = value; + break; + + case GEN_DIRNAME: + a->d.dirn = value; + break; + + case GEN_IPADD: + a->d.ip = value; + break; + + case GEN_RID: + a->d.rid = value; + break; + } + a->type = type; +} + +void *GENERAL_NAME_get0_value(GENERAL_NAME *a, int *ptype) +{ + if (ptype) + *ptype = a->type; + switch (a->type) { + case GEN_X400: + case GEN_EDIPARTY: + return a->d.other; + + case GEN_OTHERNAME: + return a->d.otherName; + + case GEN_EMAIL: + case GEN_DNS: + case GEN_URI: + return a->d.ia5; + + case GEN_DIRNAME: + return a->d.dirn; + + case GEN_IPADD: + return a->d.ip; + + case GEN_RID: + return a->d.rid; + + default: + return NULL; + } +} + +int GENERAL_NAME_set0_othername(GENERAL_NAME *gen, + ASN1_OBJECT *oid, ASN1_TYPE *value) +{ + OTHERNAME *oth; + oth = OTHERNAME_new(); + if (!oth) + return 0; + oth->type_id = oid; + oth->value = value; + GENERAL_NAME_set0_value(gen, GEN_OTHERNAME, oth); + return 1; +} + +int GENERAL_NAME_get0_otherName(GENERAL_NAME *gen, + ASN1_OBJECT **poid, ASN1_TYPE **pvalue) +{ + if (gen->type != GEN_OTHERNAME) + return 0; + if (poid) + *poid = gen->d.otherName->type_id; + if (pvalue) + *pvalue = gen->d.otherName->value; + return 1; +} diff --git a/external/boringssl/crypto/x509v3/v3_ia5.c b/external/boringssl/crypto/x509v3/v3_ia5.c new file mode 100644 index 0000000000..6fc6b59b5c --- /dev/null +++ b/external/boringssl/crypto/x509v3/v3_ia5.c @@ -0,0 +1,119 @@ +/* v3_ia5.c */ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project + * 1999. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +static char *i2s_ASN1_IA5STRING(X509V3_EXT_METHOD *method, + ASN1_IA5STRING *ia5); +static ASN1_IA5STRING *s2i_ASN1_IA5STRING(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, char *str); +const X509V3_EXT_METHOD v3_ns_ia5_list[] = { + EXT_IA5STRING(NID_netscape_base_url), + EXT_IA5STRING(NID_netscape_revocation_url), + EXT_IA5STRING(NID_netscape_ca_revocation_url), + EXT_IA5STRING(NID_netscape_renewal_url), + EXT_IA5STRING(NID_netscape_ca_policy_url), + EXT_IA5STRING(NID_netscape_ssl_server_name), + EXT_IA5STRING(NID_netscape_comment), + EXT_END +}; + +static char *i2s_ASN1_IA5STRING(X509V3_EXT_METHOD *method, + ASN1_IA5STRING *ia5) +{ + char *tmp; + if (!ia5 || !ia5->length) + return NULL; + if (!(tmp = OPENSSL_malloc(ia5->length + 1))) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + return NULL; + } + memcpy(tmp, ia5->data, ia5->length); + tmp[ia5->length] = 0; + return tmp; +} + +static ASN1_IA5STRING *s2i_ASN1_IA5STRING(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, char *str) +{ + ASN1_IA5STRING *ia5; + if (!str) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_ARGUMENT); + return NULL; + } + if (!(ia5 = M_ASN1_IA5STRING_new())) + goto err; + if (!ASN1_STRING_set((ASN1_STRING *)ia5, (unsigned char *)str, + strlen(str))) { + M_ASN1_IA5STRING_free(ia5); + goto err; + } + return ia5; + err: + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + return NULL; +} diff --git a/external/boringssl/crypto/x509v3/v3_info.c b/external/boringssl/crypto/x509v3/v3_info.c new file mode 100644 index 0000000000..482208d7c0 --- /dev/null +++ b/external/boringssl/crypto/x509v3/v3_info.c @@ -0,0 +1,212 @@ +/* v3_info.c */ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project + * 1999. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD + *method, AUTHORITY_INFO_ACCESS + *ainfo, STACK_OF(CONF_VALUE) + *ret); +static AUTHORITY_INFO_ACCESS *v2i_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD + *method, + X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) + *nval); + +const X509V3_EXT_METHOD v3_info = { NID_info_access, X509V3_EXT_MULTILINE, + ASN1_ITEM_ref(AUTHORITY_INFO_ACCESS), + 0, 0, 0, 0, + 0, 0, + (X509V3_EXT_I2V) i2v_AUTHORITY_INFO_ACCESS, + (X509V3_EXT_V2I)v2i_AUTHORITY_INFO_ACCESS, + 0, 0, + NULL +}; + +const X509V3_EXT_METHOD v3_sinfo = { NID_sinfo_access, X509V3_EXT_MULTILINE, + ASN1_ITEM_ref(AUTHORITY_INFO_ACCESS), + 0, 0, 0, 0, + 0, 0, + (X509V3_EXT_I2V) i2v_AUTHORITY_INFO_ACCESS, + (X509V3_EXT_V2I)v2i_AUTHORITY_INFO_ACCESS, + 0, 0, + NULL +}; + +ASN1_SEQUENCE(ACCESS_DESCRIPTION) = { + ASN1_SIMPLE(ACCESS_DESCRIPTION, method, ASN1_OBJECT), + ASN1_SIMPLE(ACCESS_DESCRIPTION, location, GENERAL_NAME) +} ASN1_SEQUENCE_END(ACCESS_DESCRIPTION) + +IMPLEMENT_ASN1_FUNCTIONS(ACCESS_DESCRIPTION) + +ASN1_ITEM_TEMPLATE(AUTHORITY_INFO_ACCESS) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, GeneralNames, ACCESS_DESCRIPTION) +ASN1_ITEM_TEMPLATE_END(AUTHORITY_INFO_ACCESS) + +IMPLEMENT_ASN1_FUNCTIONS(AUTHORITY_INFO_ACCESS) + +static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD + *method, AUTHORITY_INFO_ACCESS + *ainfo, STACK_OF(CONF_VALUE) + *ret) +{ + ACCESS_DESCRIPTION *desc; + size_t i; + int nlen; + char objtmp[80], *ntmp; + CONF_VALUE *vtmp; + for (i = 0; i < sk_ACCESS_DESCRIPTION_num(ainfo); i++) { + desc = sk_ACCESS_DESCRIPTION_value(ainfo, i); + ret = i2v_GENERAL_NAME(method, desc->location, ret); + if (!ret) + break; + vtmp = sk_CONF_VALUE_value(ret, i); + i2t_ASN1_OBJECT(objtmp, sizeof objtmp, desc->method); + nlen = strlen(objtmp) + strlen(vtmp->name) + 5; + ntmp = OPENSSL_malloc(nlen); + if (!ntmp) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + return NULL; + } + BUF_strlcpy(ntmp, objtmp, nlen); + BUF_strlcat(ntmp, " - ", nlen); + BUF_strlcat(ntmp, vtmp->name, nlen); + OPENSSL_free(vtmp->name); + vtmp->name = ntmp; + + } + if (!ret) + return sk_CONF_VALUE_new_null(); + return ret; +} + +static AUTHORITY_INFO_ACCESS *v2i_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD + *method, + X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) + *nval) +{ + AUTHORITY_INFO_ACCESS *ainfo = NULL; + CONF_VALUE *cnf, ctmp; + ACCESS_DESCRIPTION *acc; + size_t i; + int objlen; + char *objtmp, *ptmp; + if (!(ainfo = sk_ACCESS_DESCRIPTION_new_null())) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + return NULL; + } + for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { + cnf = sk_CONF_VALUE_value(nval, i); + if (!(acc = ACCESS_DESCRIPTION_new()) + || !sk_ACCESS_DESCRIPTION_push(ainfo, acc)) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + goto err; + } + ptmp = strchr(cnf->name, ';'); + if (!ptmp) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_SYNTAX); + goto err; + } + objlen = ptmp - cnf->name; + ctmp.name = ptmp + 1; + ctmp.value = cnf->value; + if (!v2i_GENERAL_NAME_ex(acc->location, method, ctx, &ctmp, 0)) + goto err; + if (!(objtmp = OPENSSL_malloc(objlen + 1))) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + goto err; + } + strncpy(objtmp, cnf->name, objlen); + objtmp[objlen] = 0; + acc->method = OBJ_txt2obj(objtmp, 0); + if (!acc->method) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_BAD_OBJECT); + ERR_add_error_data(2, "value=", objtmp); + OPENSSL_free(objtmp); + goto err; + } + OPENSSL_free(objtmp); + + } + return ainfo; + err: + sk_ACCESS_DESCRIPTION_pop_free(ainfo, ACCESS_DESCRIPTION_free); + return NULL; +} + +int i2a_ACCESS_DESCRIPTION(BIO *bp, ACCESS_DESCRIPTION *a) +{ + i2a_ASN1_OBJECT(bp, a->method); +#ifdef UNDEF + i2a_GENERAL_NAME(bp, a->location); +#endif + return 2; +} diff --git a/external/boringssl/crypto/x509v3/v3_int.c b/external/boringssl/crypto/x509v3/v3_int.c new file mode 100644 index 0000000000..7bde446c28 --- /dev/null +++ b/external/boringssl/crypto/x509v3/v3_int.c @@ -0,0 +1,91 @@ +/* v3_int.c */ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project + * 1999. + */ +/* ==================================================================== + * Copyright (c) 1999-2004 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include + +const X509V3_EXT_METHOD v3_crl_num = { + NID_crl_number, 0, ASN1_ITEM_ref(ASN1_INTEGER), + 0, 0, 0, 0, + (X509V3_EXT_I2S)i2s_ASN1_INTEGER, + 0, + 0, 0, 0, 0, NULL +}; + +const X509V3_EXT_METHOD v3_delta_crl = { + NID_delta_crl, 0, ASN1_ITEM_ref(ASN1_INTEGER), + 0, 0, 0, 0, + (X509V3_EXT_I2S)i2s_ASN1_INTEGER, + 0, + 0, 0, 0, 0, NULL +}; + +static void *s2i_asn1_int(X509V3_EXT_METHOD *meth, X509V3_CTX *ctx, + char *value) +{ + return s2i_ASN1_INTEGER(meth, value); +} + +const X509V3_EXT_METHOD v3_inhibit_anyp = { + NID_inhibit_any_policy, 0, ASN1_ITEM_ref(ASN1_INTEGER), + 0, 0, 0, 0, + (X509V3_EXT_I2S)i2s_ASN1_INTEGER, + (X509V3_EXT_S2I)s2i_asn1_int, + 0, 0, 0, 0, NULL +}; diff --git a/external/boringssl/crypto/x509v3/v3_lib.c b/external/boringssl/crypto/x509v3/v3_lib.c new file mode 100644 index 0000000000..c4718e33bb --- /dev/null +++ b/external/boringssl/crypto/x509v3/v3_lib.c @@ -0,0 +1,362 @@ +/* v3_lib.c */ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project + * 1999. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* X509 v3 extension utilities */ + +#include + +#include +#include +#include +#include +#include + +#include "ext_dat.h" +static STACK_OF(X509V3_EXT_METHOD) *ext_list = NULL; + +static void ext_list_free(X509V3_EXT_METHOD *ext); + +static int ext_stack_cmp(const X509V3_EXT_METHOD **a, + const X509V3_EXT_METHOD **b) +{ + return ((*a)->ext_nid - (*b)->ext_nid); +} + +int X509V3_EXT_add(X509V3_EXT_METHOD *ext) +{ + if (!ext_list && !(ext_list = sk_X509V3_EXT_METHOD_new(ext_stack_cmp))) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + ext_list_free(ext); + return 0; + } + if (!sk_X509V3_EXT_METHOD_push(ext_list, ext)) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + ext_list_free(ext); + return 0; + } + return 1; +} + +static int ext_cmp(const void *void_a, const void *void_b) +{ + const X509V3_EXT_METHOD **a = (const X509V3_EXT_METHOD **)void_a; + const X509V3_EXT_METHOD **b = (const X509V3_EXT_METHOD **)void_b; + return ext_stack_cmp(a, b); +} + +const X509V3_EXT_METHOD *X509V3_EXT_get_nid(int nid) +{ + X509V3_EXT_METHOD tmp; + const X509V3_EXT_METHOD *t = &tmp, *const *ret; + size_t idx; + + if (nid < 0) + return NULL; + tmp.ext_nid = nid; + ret = + bsearch(&t, standard_exts, STANDARD_EXTENSION_COUNT, + sizeof(X509V3_EXT_METHOD *), ext_cmp); + if (ret) + return *ret; + if (!ext_list) + return NULL; + + if (!sk_X509V3_EXT_METHOD_find(ext_list, &idx, &tmp)) + return NULL; + return sk_X509V3_EXT_METHOD_value(ext_list, idx); +} + +const X509V3_EXT_METHOD *X509V3_EXT_get(X509_EXTENSION *ext) +{ + int nid; + if ((nid = OBJ_obj2nid(ext->object)) == NID_undef) + return NULL; + return X509V3_EXT_get_nid(nid); +} + +int X509V3_EXT_free(int nid, void *ext_data) +{ + const X509V3_EXT_METHOD *ext_method = X509V3_EXT_get_nid(nid); + if (ext_method == NULL) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_CANNOT_FIND_FREE_FUNCTION); + return 0; + } + + if (ext_method->it != NULL) + ASN1_item_free(ext_data, ASN1_ITEM_ptr(ext_method->it)); + else if (ext_method->ext_free != NULL) + ext_method->ext_free(ext_data); + else { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_CANNOT_FIND_FREE_FUNCTION); + return 0; + } + + return 1; +} + +int X509V3_EXT_add_list(X509V3_EXT_METHOD *extlist) +{ + for (; extlist->ext_nid != -1; extlist++) + if (!X509V3_EXT_add(extlist)) + return 0; + return 1; +} + +int X509V3_EXT_add_alias(int nid_to, int nid_from) +{ + const X509V3_EXT_METHOD *ext; + X509V3_EXT_METHOD *tmpext; + + if (!(ext = X509V3_EXT_get_nid(nid_from))) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_EXTENSION_NOT_FOUND); + return 0; + } + if (! + (tmpext = + (X509V3_EXT_METHOD *)OPENSSL_malloc(sizeof(X509V3_EXT_METHOD)))) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + return 0; + } + *tmpext = *ext; + tmpext->ext_nid = nid_to; + tmpext->ext_flags |= X509V3_EXT_DYNAMIC; + return X509V3_EXT_add(tmpext); +} + +void X509V3_EXT_cleanup(void) +{ + sk_X509V3_EXT_METHOD_pop_free(ext_list, ext_list_free); + ext_list = NULL; +} + +static void ext_list_free(X509V3_EXT_METHOD *ext) +{ + if (ext->ext_flags & X509V3_EXT_DYNAMIC) + OPENSSL_free(ext); +} + +/* + * Legacy function: we don't need to add standard extensions any more because + * they are now kept in ext_dat.h. + */ + +int X509V3_add_standard_extensions(void) +{ + return 1; +} + +/* Return an extension internal structure */ + +void *X509V3_EXT_d2i(X509_EXTENSION *ext) +{ + const X509V3_EXT_METHOD *method; + const unsigned char *p; + + if (!(method = X509V3_EXT_get(ext))) + return NULL; + p = ext->value->data; + if (method->it) + return ASN1_item_d2i(NULL, &p, ext->value->length, + ASN1_ITEM_ptr(method->it)); + return method->d2i(NULL, &p, ext->value->length); +} + +/* + * Get critical flag and decoded version of extension from a NID. The "idx" + * variable returns the last found extension and can be used to retrieve + * multiple extensions of the same NID. However multiple extensions with the + * same NID is usually due to a badly encoded certificate so if idx is NULL + * we choke if multiple extensions exist. The "crit" variable is set to the + * critical value. The return value is the decoded extension or NULL on + * error. The actual error can have several different causes, the value of + * *crit reflects the cause: >= 0, extension found but not decoded (reflects + * critical value). -1 extension not found. -2 extension occurs more than + * once. + */ + +void *X509V3_get_d2i(STACK_OF(X509_EXTENSION) *x, int nid, int *crit, + int *idx) +{ + int lastpos; + size_t i; + X509_EXTENSION *ex, *found_ex = NULL; + if (!x) { + if (idx) + *idx = -1; + if (crit) + *crit = -1; + return NULL; + } + if (idx) + lastpos = *idx + 1; + else + lastpos = 0; + if (lastpos < 0) + lastpos = 0; + for (i = lastpos; i < sk_X509_EXTENSION_num(x); i++) { + ex = sk_X509_EXTENSION_value(x, i); + if (OBJ_obj2nid(ex->object) == nid) { + if (idx) { + *idx = i; + found_ex = ex; + break; + } else if (found_ex) { + /* Found more than one */ + if (crit) + *crit = -2; + return NULL; + } + found_ex = ex; + } + } + if (found_ex) { + /* Found it */ + if (crit) + *crit = X509_EXTENSION_get_critical(found_ex); + return X509V3_EXT_d2i(found_ex); + } + + /* Extension not found */ + if (idx) + *idx = -1; + if (crit) + *crit = -1; + return NULL; +} + +/* + * This function is a general extension append, replace and delete utility. + * The precise operation is governed by the 'flags' value. The 'crit' and + * 'value' arguments (if relevant) are the extensions internal structure. + */ + +int X509V3_add1_i2d(STACK_OF(X509_EXTENSION) **x, int nid, void *value, + int crit, unsigned long flags) +{ + int extidx = -1; + int errcode; + X509_EXTENSION *ext, *extmp; + unsigned long ext_op = flags & X509V3_ADD_OP_MASK; + + /* + * If appending we don't care if it exists, otherwise look for existing + * extension. + */ + if (ext_op != X509V3_ADD_APPEND) + extidx = X509v3_get_ext_by_NID(*x, nid, -1); + + /* See if extension exists */ + if (extidx >= 0) { + /* If keep existing, nothing to do */ + if (ext_op == X509V3_ADD_KEEP_EXISTING) + return 1; + /* If default then its an error */ + if (ext_op == X509V3_ADD_DEFAULT) { + errcode = X509V3_R_EXTENSION_EXISTS; + goto err; + } + /* If delete, just delete it */ + if (ext_op == X509V3_ADD_DELETE) { + if (!sk_X509_EXTENSION_delete(*x, extidx)) + return -1; + return 1; + } + } else { + /* + * If replace existing or delete, error since extension must exist + */ + if ((ext_op == X509V3_ADD_REPLACE_EXISTING) || + (ext_op == X509V3_ADD_DELETE)) { + errcode = X509V3_R_EXTENSION_NOT_FOUND; + goto err; + } + } + + /* + * If we get this far then we have to create an extension: could have + * some flags for alternative encoding schemes... + */ + + ext = X509V3_EXT_i2d(nid, crit, value); + + if (!ext) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_ERROR_CREATING_EXTENSION); + return 0; + } + + /* If extension exists replace it.. */ + if (extidx >= 0) { + extmp = sk_X509_EXTENSION_value(*x, extidx); + X509_EXTENSION_free(extmp); + if (!sk_X509_EXTENSION_set(*x, extidx, ext)) + return -1; + return 1; + } + + if (!*x && !(*x = sk_X509_EXTENSION_new_null())) + return -1; + if (!sk_X509_EXTENSION_push(*x, ext)) + return -1; + + return 1; + + err: + if (!(flags & X509V3_ADD_SILENT)) + OPENSSL_PUT_ERROR(X509V3, errcode); + return 0; +} diff --git a/external/boringssl/crypto/x509v3/v3_ncons.c b/external/boringssl/crypto/x509v3/v3_ncons.c new file mode 100644 index 0000000000..368ad27268 --- /dev/null +++ b/external/boringssl/crypto/x509v3/v3_ncons.c @@ -0,0 +1,482 @@ +/* v3_ncons.c */ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project. + */ +/* ==================================================================== + * Copyright (c) 2003 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +static void *v2i_NAME_CONSTRAINTS(const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *nval); +static int i2r_NAME_CONSTRAINTS(const X509V3_EXT_METHOD *method, void *a, + BIO *bp, int ind); +static int do_i2r_name_constraints(const X509V3_EXT_METHOD *method, + STACK_OF(GENERAL_SUBTREE) *trees, BIO *bp, + int ind, const char *name); +static int print_nc_ipadd(BIO *bp, ASN1_OCTET_STRING *ip); + +static int nc_match(GENERAL_NAME *gen, NAME_CONSTRAINTS *nc); +static int nc_match_single(GENERAL_NAME *sub, GENERAL_NAME *gen); +static int nc_dn(X509_NAME *sub, X509_NAME *nm); +static int nc_dns(ASN1_IA5STRING *sub, ASN1_IA5STRING *dns); +static int nc_email(ASN1_IA5STRING *sub, ASN1_IA5STRING *eml); +static int nc_uri(ASN1_IA5STRING *uri, ASN1_IA5STRING *base); + +const X509V3_EXT_METHOD v3_name_constraints = { + NID_name_constraints, 0, + ASN1_ITEM_ref(NAME_CONSTRAINTS), + 0, 0, 0, 0, + 0, 0, + 0, v2i_NAME_CONSTRAINTS, + i2r_NAME_CONSTRAINTS, 0, + NULL +}; + +ASN1_SEQUENCE(GENERAL_SUBTREE) = { + ASN1_SIMPLE(GENERAL_SUBTREE, base, GENERAL_NAME), + ASN1_IMP_OPT(GENERAL_SUBTREE, minimum, ASN1_INTEGER, 0), + ASN1_IMP_OPT(GENERAL_SUBTREE, maximum, ASN1_INTEGER, 1) +} ASN1_SEQUENCE_END(GENERAL_SUBTREE) + +ASN1_SEQUENCE(NAME_CONSTRAINTS) = { + ASN1_IMP_SEQUENCE_OF_OPT(NAME_CONSTRAINTS, permittedSubtrees, + GENERAL_SUBTREE, 0), + ASN1_IMP_SEQUENCE_OF_OPT(NAME_CONSTRAINTS, excludedSubtrees, + GENERAL_SUBTREE, 1), +} ASN1_SEQUENCE_END(NAME_CONSTRAINTS) + + +IMPLEMENT_ASN1_ALLOC_FUNCTIONS(GENERAL_SUBTREE) +IMPLEMENT_ASN1_ALLOC_FUNCTIONS(NAME_CONSTRAINTS) + +static void *v2i_NAME_CONSTRAINTS(const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval) +{ + size_t i; + CONF_VALUE tval, *val; + STACK_OF(GENERAL_SUBTREE) **ptree = NULL; + NAME_CONSTRAINTS *ncons = NULL; + GENERAL_SUBTREE *sub = NULL; + ncons = NAME_CONSTRAINTS_new(); + if (!ncons) + goto memerr; + for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { + val = sk_CONF_VALUE_value(nval, i); + if (!strncmp(val->name, "permitted", 9) && val->name[9]) { + ptree = &ncons->permittedSubtrees; + tval.name = val->name + 10; + } else if (!strncmp(val->name, "excluded", 8) && val->name[8]) { + ptree = &ncons->excludedSubtrees; + tval.name = val->name + 9; + } else { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_SYNTAX); + goto err; + } + tval.value = val->value; + sub = GENERAL_SUBTREE_new(); + if (!v2i_GENERAL_NAME_ex(sub->base, method, ctx, &tval, 1)) + goto err; + if (!*ptree) + *ptree = sk_GENERAL_SUBTREE_new_null(); + if (!*ptree || !sk_GENERAL_SUBTREE_push(*ptree, sub)) + goto memerr; + sub = NULL; + } + + return ncons; + + memerr: + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + err: + if (ncons) + NAME_CONSTRAINTS_free(ncons); + if (sub) + GENERAL_SUBTREE_free(sub); + + return NULL; +} + +static int i2r_NAME_CONSTRAINTS(const X509V3_EXT_METHOD *method, void *a, + BIO *bp, int ind) +{ + NAME_CONSTRAINTS *ncons = a; + do_i2r_name_constraints(method, ncons->permittedSubtrees, + bp, ind, "Permitted"); + do_i2r_name_constraints(method, ncons->excludedSubtrees, + bp, ind, "Excluded"); + return 1; +} + +static int do_i2r_name_constraints(const X509V3_EXT_METHOD *method, + STACK_OF(GENERAL_SUBTREE) *trees, + BIO *bp, int ind, const char *name) +{ + GENERAL_SUBTREE *tree; + size_t i; + if (sk_GENERAL_SUBTREE_num(trees) > 0) + BIO_printf(bp, "%*s%s:\n", ind, "", name); + for (i = 0; i < sk_GENERAL_SUBTREE_num(trees); i++) { + tree = sk_GENERAL_SUBTREE_value(trees, i); + BIO_printf(bp, "%*s", ind + 2, ""); + if (tree->base->type == GEN_IPADD) + print_nc_ipadd(bp, tree->base->d.ip); + else + GENERAL_NAME_print(bp, tree->base); + BIO_puts(bp, "\n"); + } + return 1; +} + +static int print_nc_ipadd(BIO *bp, ASN1_OCTET_STRING *ip) +{ + int i, len; + unsigned char *p; + p = ip->data; + len = ip->length; + BIO_puts(bp, "IP:"); + if (len == 8) { + BIO_printf(bp, "%d.%d.%d.%d/%d.%d.%d.%d", + p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); + } else if (len == 32) { + for (i = 0; i < 16; i++) { + BIO_printf(bp, "%X", p[0] << 8 | p[1]); + p += 2; + if (i == 7) + BIO_puts(bp, "/"); + else if (i != 15) + BIO_puts(bp, ":"); + } + } else + BIO_printf(bp, "IP Address:"); + return 1; +} + +/* + * Check a certificate conforms to a specified set of constraints. Return + * values: X509_V_OK: All constraints obeyed. + * X509_V_ERR_PERMITTED_VIOLATION: Permitted subtree violation. + * X509_V_ERR_EXCLUDED_VIOLATION: Excluded subtree violation. + * X509_V_ERR_SUBTREE_MINMAX: Min or max values present and matching type. + * X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE: Unsupported constraint type. + * X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX: bad unsupported constraint + * syntax. X509_V_ERR_UNSUPPORTED_NAME_SYNTAX: bad or unsupported syntax of + * name + * + */ + +int NAME_CONSTRAINTS_check(X509 *x, NAME_CONSTRAINTS *nc) +{ + int r, i; + size_t j; + X509_NAME *nm; + + nm = X509_get_subject_name(x); + + if (X509_NAME_entry_count(nm) > 0) { + GENERAL_NAME gntmp; + gntmp.type = GEN_DIRNAME; + gntmp.d.directoryName = nm; + + r = nc_match(&gntmp, nc); + + if (r != X509_V_OK) + return r; + + gntmp.type = GEN_EMAIL; + + /* Process any email address attributes in subject name */ + + for (i = -1;;) { + X509_NAME_ENTRY *ne; + i = X509_NAME_get_index_by_NID(nm, NID_pkcs9_emailAddress, i); + if (i == -1) + break; + ne = X509_NAME_get_entry(nm, i); + gntmp.d.rfc822Name = X509_NAME_ENTRY_get_data(ne); + if (gntmp.d.rfc822Name->type != V_ASN1_IA5STRING) + return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX; + + r = nc_match(&gntmp, nc); + + if (r != X509_V_OK) + return r; + } + + } + + for (j = 0; j < sk_GENERAL_NAME_num(x->altname); j++) { + GENERAL_NAME *gen = sk_GENERAL_NAME_value(x->altname, j); + r = nc_match(gen, nc); + if (r != X509_V_OK) + return r; + } + + return X509_V_OK; + +} + +static int nc_match(GENERAL_NAME *gen, NAME_CONSTRAINTS *nc) +{ + GENERAL_SUBTREE *sub; + int r, match = 0; + size_t i; + + /* + * Permitted subtrees: if any subtrees exist of matching the type at + * least one subtree must match. + */ + + for (i = 0; i < sk_GENERAL_SUBTREE_num(nc->permittedSubtrees); i++) { + sub = sk_GENERAL_SUBTREE_value(nc->permittedSubtrees, i); + if (gen->type != sub->base->type) + continue; + if (sub->minimum || sub->maximum) + return X509_V_ERR_SUBTREE_MINMAX; + /* If we already have a match don't bother trying any more */ + if (match == 2) + continue; + if (match == 0) + match = 1; + r = nc_match_single(gen, sub->base); + if (r == X509_V_OK) + match = 2; + else if (r != X509_V_ERR_PERMITTED_VIOLATION) + return r; + } + + if (match == 1) + return X509_V_ERR_PERMITTED_VIOLATION; + + /* Excluded subtrees: must not match any of these */ + + for (i = 0; i < sk_GENERAL_SUBTREE_num(nc->excludedSubtrees); i++) { + sub = sk_GENERAL_SUBTREE_value(nc->excludedSubtrees, i); + if (gen->type != sub->base->type) + continue; + if (sub->minimum || sub->maximum) + return X509_V_ERR_SUBTREE_MINMAX; + + r = nc_match_single(gen, sub->base); + if (r == X509_V_OK) + return X509_V_ERR_EXCLUDED_VIOLATION; + else if (r != X509_V_ERR_PERMITTED_VIOLATION) + return r; + + } + + return X509_V_OK; + +} + +static int nc_match_single(GENERAL_NAME *gen, GENERAL_NAME *base) +{ + switch (base->type) { + case GEN_DIRNAME: + return nc_dn(gen->d.directoryName, base->d.directoryName); + + case GEN_DNS: + return nc_dns(gen->d.dNSName, base->d.dNSName); + + case GEN_EMAIL: + return nc_email(gen->d.rfc822Name, base->d.rfc822Name); + + case GEN_URI: + return nc_uri(gen->d.uniformResourceIdentifier, + base->d.uniformResourceIdentifier); + + default: + return X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE; + } + +} + +/* + * directoryName name constraint matching. The canonical encoding of + * X509_NAME makes this comparison easy. It is matched if the subtree is a + * subset of the name. + */ + +static int nc_dn(X509_NAME *nm, X509_NAME *base) +{ + /* Ensure canonical encodings are up to date. */ + if (nm->modified && i2d_X509_NAME(nm, NULL) < 0) + return X509_V_ERR_OUT_OF_MEM; + if (base->modified && i2d_X509_NAME(base, NULL) < 0) + return X509_V_ERR_OUT_OF_MEM; + if (base->canon_enclen > nm->canon_enclen) + return X509_V_ERR_PERMITTED_VIOLATION; + if (memcmp(base->canon_enc, nm->canon_enc, base->canon_enclen)) + return X509_V_ERR_PERMITTED_VIOLATION; + return X509_V_OK; +} + +static int nc_dns(ASN1_IA5STRING *dns, ASN1_IA5STRING *base) +{ + char *baseptr = (char *)base->data; + char *dnsptr = (char *)dns->data; + /* Empty matches everything */ + if (!*baseptr) + return X509_V_OK; + /* + * Otherwise can add zero or more components on the left so compare RHS + * and if dns is longer and expect '.' as preceding character. + */ + if (dns->length > base->length) { + dnsptr += dns->length - base->length; + if (*baseptr != '.' && dnsptr[-1] != '.') + return X509_V_ERR_PERMITTED_VIOLATION; + } + + if (OPENSSL_strcasecmp(baseptr, dnsptr)) + return X509_V_ERR_PERMITTED_VIOLATION; + + return X509_V_OK; + +} + +static int nc_email(ASN1_IA5STRING *eml, ASN1_IA5STRING *base) +{ + const char *baseptr = (char *)base->data; + const char *emlptr = (char *)eml->data; + + const char *baseat = strchr(baseptr, '@'); + const char *emlat = strchr(emlptr, '@'); + if (!emlat) + return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX; + /* Special case: inital '.' is RHS match */ + if (!baseat && (*baseptr == '.')) { + if (eml->length > base->length) { + emlptr += eml->length - base->length; + if (!OPENSSL_strcasecmp(baseptr, emlptr)) + return X509_V_OK; + } + return X509_V_ERR_PERMITTED_VIOLATION; + } + + /* If we have anything before '@' match local part */ + + if (baseat) { + if (baseat != baseptr) { + if ((baseat - baseptr) != (emlat - emlptr)) + return X509_V_ERR_PERMITTED_VIOLATION; + /* Case sensitive match of local part */ + if (strncmp(baseptr, emlptr, emlat - emlptr)) + return X509_V_ERR_PERMITTED_VIOLATION; + } + /* Position base after '@' */ + baseptr = baseat + 1; + } + emlptr = emlat + 1; + /* Just have hostname left to match: case insensitive */ + if (OPENSSL_strcasecmp(baseptr, emlptr)) + return X509_V_ERR_PERMITTED_VIOLATION; + + return X509_V_OK; + +} + +static int nc_uri(ASN1_IA5STRING *uri, ASN1_IA5STRING *base) +{ + const char *baseptr = (char *)base->data; + const char *hostptr = (char *)uri->data; + const char *p = strchr(hostptr, ':'); + int hostlen; + /* Check for foo:// and skip past it */ + if (!p || (p[1] != '/') || (p[2] != '/')) + return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX; + hostptr = p + 3; + + /* Determine length of hostname part of URI */ + + /* Look for a port indicator as end of hostname first */ + + p = strchr(hostptr, ':'); + /* Otherwise look for trailing slash */ + if (!p) + p = strchr(hostptr, '/'); + + if (!p) + hostlen = strlen(hostptr); + else + hostlen = p - hostptr; + + if (hostlen == 0) + return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX; + + /* Special case: inital '.' is RHS match */ + if (*baseptr == '.') { + if (hostlen > base->length) { + p = hostptr + hostlen - base->length; + if (!OPENSSL_strncasecmp(p, baseptr, base->length)) + return X509_V_OK; + } + return X509_V_ERR_PERMITTED_VIOLATION; + } + + if ((base->length != (int)hostlen) + || OPENSSL_strncasecmp(hostptr, baseptr, hostlen)) + return X509_V_ERR_PERMITTED_VIOLATION; + + return X509_V_OK; + +} diff --git a/external/boringssl/crypto/x509v3/v3_pci.c b/external/boringssl/crypto/x509v3/v3_pci.c new file mode 100644 index 0000000000..220f65e116 --- /dev/null +++ b/external/boringssl/crypto/x509v3/v3_pci.c @@ -0,0 +1,317 @@ +/* v3_pci.c -*- mode:C; c-file-style: "eay" -*- */ +/* + * Contributed to the OpenSSL Project 2004 by Richard Levitte + * (richard@levitte.org) + */ +/* Copyright (c) 2004 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include + +#include +#include +#include +#include +#include + +static int i2r_pci(X509V3_EXT_METHOD *method, PROXY_CERT_INFO_EXTENSION *ext, + BIO *out, int indent); +static PROXY_CERT_INFO_EXTENSION *r2i_pci(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, char *str); + +const X509V3_EXT_METHOD v3_pci = + { NID_proxyCertInfo, 0, ASN1_ITEM_ref(PROXY_CERT_INFO_EXTENSION), + 0, 0, 0, 0, + 0, 0, + NULL, NULL, + (X509V3_EXT_I2R)i2r_pci, + (X509V3_EXT_R2I)r2i_pci, + NULL, +}; + +static int i2r_pci(X509V3_EXT_METHOD *method, PROXY_CERT_INFO_EXTENSION *pci, + BIO *out, int indent) +{ + BIO_printf(out, "%*sPath Length Constraint: ", indent, ""); + if (pci->pcPathLengthConstraint) + i2a_ASN1_INTEGER(out, pci->pcPathLengthConstraint); + else + BIO_printf(out, "infinite"); + BIO_puts(out, "\n"); + BIO_printf(out, "%*sPolicy Language: ", indent, ""); + i2a_ASN1_OBJECT(out, pci->proxyPolicy->policyLanguage); + BIO_puts(out, "\n"); + if (pci->proxyPolicy->policy && pci->proxyPolicy->policy->data) + BIO_printf(out, "%*sPolicy Text: %s\n", indent, "", + pci->proxyPolicy->policy->data); + return 1; +} + +static int process_pci_value(CONF_VALUE *val, + ASN1_OBJECT **language, ASN1_INTEGER **pathlen, + ASN1_OCTET_STRING **policy) +{ + int free_policy = 0; + + if (strcmp(val->name, "language") == 0) { + if (*language) { + OPENSSL_PUT_ERROR(X509V3, + X509V3_R_POLICY_LANGUAGE_ALREADY_DEFINED); + X509V3_conf_err(val); + return 0; + } + if (!(*language = OBJ_txt2obj(val->value, 0))) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER); + X509V3_conf_err(val); + return 0; + } + } else if (strcmp(val->name, "pathlen") == 0) { + if (*pathlen) { + OPENSSL_PUT_ERROR(X509V3, + X509V3_R_POLICY_PATH_LENGTH_ALREADY_DEFINED); + X509V3_conf_err(val); + return 0; + } + if (!X509V3_get_value_int(val, pathlen)) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_POLICY_PATH_LENGTH); + X509V3_conf_err(val); + return 0; + } + } else if (strcmp(val->name, "policy") == 0) { + unsigned char *tmp_data = NULL; + long val_len; + if (!*policy) { + *policy = ASN1_OCTET_STRING_new(); + if (!*policy) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + X509V3_conf_err(val); + return 0; + } + free_policy = 1; + } + if (strncmp(val->value, "hex:", 4) == 0) { + unsigned char *tmp_data2 = + string_to_hex(val->value + 4, &val_len); + + if (!tmp_data2) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_ILLEGAL_HEX_DIGIT); + X509V3_conf_err(val); + goto err; + } + + tmp_data = OPENSSL_realloc((*policy)->data, + (*policy)->length + val_len + 1); + if (tmp_data) { + (*policy)->data = tmp_data; + memcpy(&(*policy)->data[(*policy)->length], + tmp_data2, val_len); + (*policy)->length += val_len; + (*policy)->data[(*policy)->length] = '\0'; + } else { + OPENSSL_free(tmp_data2); + /* + * realloc failure implies the original data space is b0rked + * too! + */ + (*policy)->data = NULL; + (*policy)->length = 0; + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + X509V3_conf_err(val); + goto err; + } + OPENSSL_free(tmp_data2); + } else if (strncmp(val->value, "file:", 5) == 0) { + unsigned char buf[2048]; + int n; + BIO *b = BIO_new_file(val->value + 5, "r"); + if (!b) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_BIO_LIB); + X509V3_conf_err(val); + goto err; + } + while ((n = BIO_read(b, buf, sizeof(buf))) > 0 + || (n == 0 && BIO_should_retry(b))) { + if (!n) + continue; + + tmp_data = OPENSSL_realloc((*policy)->data, + (*policy)->length + n + 1); + + if (!tmp_data) + break; + + (*policy)->data = tmp_data; + memcpy(&(*policy)->data[(*policy)->length], buf, n); + (*policy)->length += n; + (*policy)->data[(*policy)->length] = '\0'; + } + BIO_free_all(b); + + if (n < 0) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_BIO_LIB); + X509V3_conf_err(val); + goto err; + } + } else if (strncmp(val->value, "text:", 5) == 0) { + val_len = strlen(val->value + 5); + tmp_data = OPENSSL_realloc((*policy)->data, + (*policy)->length + val_len + 1); + if (tmp_data) { + (*policy)->data = tmp_data; + memcpy(&(*policy)->data[(*policy)->length], + val->value + 5, val_len); + (*policy)->length += val_len; + (*policy)->data[(*policy)->length] = '\0'; + } else { + /* + * realloc failure implies the original data space is b0rked + * too! + */ + (*policy)->data = NULL; + (*policy)->length = 0; + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + X509V3_conf_err(val); + goto err; + } + } else { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INCORRECT_POLICY_SYNTAX_TAG); + X509V3_conf_err(val); + goto err; + } + if (!tmp_data) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + X509V3_conf_err(val); + goto err; + } + } + return 1; + err: + if (free_policy) { + ASN1_OCTET_STRING_free(*policy); + *policy = NULL; + } + return 0; +} + +static PROXY_CERT_INFO_EXTENSION *r2i_pci(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, char *value) +{ + PROXY_CERT_INFO_EXTENSION *pci = NULL; + STACK_OF(CONF_VALUE) *vals; + ASN1_OBJECT *language = NULL; + ASN1_INTEGER *pathlen = NULL; + ASN1_OCTET_STRING *policy = NULL; + size_t i, j; + int nid; + + vals = X509V3_parse_list(value); + for (i = 0; i < sk_CONF_VALUE_num(vals); i++) { + CONF_VALUE *cnf = sk_CONF_VALUE_value(vals, i); + if (!cnf->name || (*cnf->name != '@' && !cnf->value)) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_PROXY_POLICY_SETTING); + X509V3_conf_err(cnf); + goto err; + } + if (*cnf->name == '@') { + STACK_OF(CONF_VALUE) *sect; + int success_p = 1; + + sect = X509V3_get_section(ctx, cnf->name + 1); + if (!sect) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_SECTION); + X509V3_conf_err(cnf); + goto err; + } + for (j = 0; success_p && j < sk_CONF_VALUE_num(sect); j++) { + success_p = + process_pci_value(sk_CONF_VALUE_value(sect, j), + &language, &pathlen, &policy); + } + X509V3_section_free(ctx, sect); + if (!success_p) + goto err; + } else { + if (!process_pci_value(cnf, &language, &pathlen, &policy)) { + X509V3_conf_err(cnf); + goto err; + } + } + } + + /* Language is mandatory */ + if (!language) { + OPENSSL_PUT_ERROR(X509V3, + X509V3_R_NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED); + goto err; + } + nid = OBJ_obj2nid(language); + if ((nid == NID_Independent || nid == NID_id_ppl_inheritAll) && policy) { + OPENSSL_PUT_ERROR(X509V3, + X509V3_R_POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY); + goto err; + } + + pci = PROXY_CERT_INFO_EXTENSION_new(); + if (!pci) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + goto err; + } + + pci->proxyPolicy->policyLanguage = language; + language = NULL; + pci->proxyPolicy->policy = policy; + policy = NULL; + pci->pcPathLengthConstraint = pathlen; + pathlen = NULL; + goto end; + err: + if (language) { + ASN1_OBJECT_free(language); + language = NULL; + } + if (pathlen) { + ASN1_INTEGER_free(pathlen); + pathlen = NULL; + } + if (policy) { + ASN1_OCTET_STRING_free(policy); + policy = NULL; + } + if (pci) { + PROXY_CERT_INFO_EXTENSION_free(pci); + pci = NULL; + } + end: + sk_CONF_VALUE_pop_free(vals, X509V3_conf_free); + return pci; +} diff --git a/external/boringssl/crypto/x509v3/v3_pcia.c b/external/boringssl/crypto/x509v3/v3_pcia.c new file mode 100644 index 0000000000..3f285f30f5 --- /dev/null +++ b/external/boringssl/crypto/x509v3/v3_pcia.c @@ -0,0 +1,57 @@ +/* v3_pcia.c -*- mode:C; c-file-style: "eay" -*- */ +/* + * Contributed to the OpenSSL Project 2004 by Richard Levitte + * (richard@levitte.org) + */ +/* Copyright (c) 2004 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include + + +ASN1_SEQUENCE(PROXY_POLICY) = + { + ASN1_SIMPLE(PROXY_POLICY,policyLanguage,ASN1_OBJECT), + ASN1_OPT(PROXY_POLICY,policy,ASN1_OCTET_STRING) +} ASN1_SEQUENCE_END(PROXY_POLICY) + +IMPLEMENT_ASN1_FUNCTIONS(PROXY_POLICY) + +ASN1_SEQUENCE(PROXY_CERT_INFO_EXTENSION) = + { + ASN1_OPT(PROXY_CERT_INFO_EXTENSION,pcPathLengthConstraint,ASN1_INTEGER), + ASN1_SIMPLE(PROXY_CERT_INFO_EXTENSION,proxyPolicy,PROXY_POLICY) +} ASN1_SEQUENCE_END(PROXY_CERT_INFO_EXTENSION) + +IMPLEMENT_ASN1_FUNCTIONS(PROXY_CERT_INFO_EXTENSION) diff --git a/external/boringssl/crypto/x509v3/v3_pcons.c b/external/boringssl/crypto/x509v3/v3_pcons.c new file mode 100644 index 0000000000..1a4631432d --- /dev/null +++ b/external/boringssl/crypto/x509v3/v3_pcons.c @@ -0,0 +1,139 @@ +/* v3_pcons.c */ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project. + */ +/* ==================================================================== + * Copyright (c) 2003 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +static STACK_OF(CONF_VALUE) *i2v_POLICY_CONSTRAINTS(const X509V3_EXT_METHOD + *method, void *bcons, STACK_OF(CONF_VALUE) + *extlist); +static void *v2i_POLICY_CONSTRAINTS(const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *values); + +const X509V3_EXT_METHOD v3_policy_constraints = { + NID_policy_constraints, 0, + ASN1_ITEM_ref(POLICY_CONSTRAINTS), + 0, 0, 0, 0, + 0, 0, + i2v_POLICY_CONSTRAINTS, + v2i_POLICY_CONSTRAINTS, + NULL, NULL, + NULL +}; + +ASN1_SEQUENCE(POLICY_CONSTRAINTS) = { + ASN1_IMP_OPT(POLICY_CONSTRAINTS, requireExplicitPolicy, ASN1_INTEGER,0), + ASN1_IMP_OPT(POLICY_CONSTRAINTS, inhibitPolicyMapping, ASN1_INTEGER,1) +} ASN1_SEQUENCE_END(POLICY_CONSTRAINTS) + +IMPLEMENT_ASN1_ALLOC_FUNCTIONS(POLICY_CONSTRAINTS) + +static STACK_OF(CONF_VALUE) *i2v_POLICY_CONSTRAINTS(const X509V3_EXT_METHOD + *method, void *a, STACK_OF(CONF_VALUE) + *extlist) +{ + POLICY_CONSTRAINTS *pcons = a; + X509V3_add_value_int("Require Explicit Policy", + pcons->requireExplicitPolicy, &extlist); + X509V3_add_value_int("Inhibit Policy Mapping", + pcons->inhibitPolicyMapping, &extlist); + return extlist; +} + +static void *v2i_POLICY_CONSTRAINTS(const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *values) +{ + POLICY_CONSTRAINTS *pcons = NULL; + CONF_VALUE *val; + size_t i; + if (!(pcons = POLICY_CONSTRAINTS_new())) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + return NULL; + } + for (i = 0; i < sk_CONF_VALUE_num(values); i++) { + val = sk_CONF_VALUE_value(values, i); + if (!strcmp(val->name, "requireExplicitPolicy")) { + if (!X509V3_get_value_int(val, &pcons->requireExplicitPolicy)) + goto err; + } else if (!strcmp(val->name, "inhibitPolicyMapping")) { + if (!X509V3_get_value_int(val, &pcons->inhibitPolicyMapping)) + goto err; + } else { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NAME); + X509V3_conf_err(val); + goto err; + } + } + if (!pcons->inhibitPolicyMapping && !pcons->requireExplicitPolicy) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_ILLEGAL_EMPTY_EXTENSION); + goto err; + } + + return pcons; + err: + POLICY_CONSTRAINTS_free(pcons); + return NULL; +} diff --git a/external/boringssl/crypto/x509v3/v3_pku.c b/external/boringssl/crypto/x509v3/v3_pku.c new file mode 100644 index 0000000000..e4868b47d1 --- /dev/null +++ b/external/boringssl/crypto/x509v3/v3_pku.c @@ -0,0 +1,110 @@ +/* v3_pku.c */ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project + * 1999. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include +#include +#include +#include + +static int i2r_PKEY_USAGE_PERIOD(X509V3_EXT_METHOD *method, + PKEY_USAGE_PERIOD *usage, BIO *out, + int indent); +/* + * static PKEY_USAGE_PERIOD *v2i_PKEY_USAGE_PERIOD(X509V3_EXT_METHOD *method, + * X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *values); + */ +const X509V3_EXT_METHOD v3_pkey_usage_period = { + NID_private_key_usage_period, 0, ASN1_ITEM_ref(PKEY_USAGE_PERIOD), + 0, 0, 0, 0, + 0, 0, 0, 0, + (X509V3_EXT_I2R)i2r_PKEY_USAGE_PERIOD, NULL, + NULL +}; + +ASN1_SEQUENCE(PKEY_USAGE_PERIOD) = { + ASN1_IMP_OPT(PKEY_USAGE_PERIOD, notBefore, ASN1_GENERALIZEDTIME, 0), + ASN1_IMP_OPT(PKEY_USAGE_PERIOD, notAfter, ASN1_GENERALIZEDTIME, 1) +} ASN1_SEQUENCE_END(PKEY_USAGE_PERIOD) + +IMPLEMENT_ASN1_FUNCTIONS(PKEY_USAGE_PERIOD) + +static int i2r_PKEY_USAGE_PERIOD(X509V3_EXT_METHOD *method, + PKEY_USAGE_PERIOD *usage, BIO *out, + int indent) +{ + BIO_printf(out, "%*s", indent, ""); + if (usage->notBefore) { + BIO_write(out, "Not Before: ", 12); + ASN1_GENERALIZEDTIME_print(out, usage->notBefore); + if (usage->notAfter) + BIO_write(out, ", ", 2); + } + if (usage->notAfter) { + BIO_write(out, "Not After: ", 11); + ASN1_GENERALIZEDTIME_print(out, usage->notAfter); + } + return 1; +} + +/* + * static PKEY_USAGE_PERIOD *v2i_PKEY_USAGE_PERIOD(method, ctx, values) + * X509V3_EXT_METHOD *method; X509V3_CTX *ctx; STACK_OF(CONF_VALUE) *values; + * { return NULL; } + */ diff --git a/external/boringssl/crypto/x509v3/v3_pmaps.c b/external/boringssl/crypto/x509v3/v3_pmaps.c new file mode 100644 index 0000000000..caacdb2738 --- /dev/null +++ b/external/boringssl/crypto/x509v3/v3_pmaps.c @@ -0,0 +1,154 @@ +/* v3_pmaps.c */ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project. + */ +/* ==================================================================== + * Copyright (c) 2003 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include +#include +#include +#include + +static void *v2i_POLICY_MAPPINGS(const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval); +static STACK_OF(CONF_VALUE) *i2v_POLICY_MAPPINGS(const X509V3_EXT_METHOD + *method, void *pmps, STACK_OF(CONF_VALUE) + *extlist); + +const X509V3_EXT_METHOD v3_policy_mappings = { + NID_policy_mappings, 0, + ASN1_ITEM_ref(POLICY_MAPPINGS), + 0, 0, 0, 0, + 0, 0, + i2v_POLICY_MAPPINGS, + v2i_POLICY_MAPPINGS, + 0, 0, + NULL +}; + +ASN1_SEQUENCE(POLICY_MAPPING) = { + ASN1_SIMPLE(POLICY_MAPPING, issuerDomainPolicy, ASN1_OBJECT), + ASN1_SIMPLE(POLICY_MAPPING, subjectDomainPolicy, ASN1_OBJECT) +} ASN1_SEQUENCE_END(POLICY_MAPPING) + +ASN1_ITEM_TEMPLATE(POLICY_MAPPINGS) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, POLICY_MAPPINGS, + POLICY_MAPPING) +ASN1_ITEM_TEMPLATE_END(POLICY_MAPPINGS) + +IMPLEMENT_ASN1_ALLOC_FUNCTIONS(POLICY_MAPPING) + +static STACK_OF(CONF_VALUE) *i2v_POLICY_MAPPINGS(const X509V3_EXT_METHOD + *method, void *a, STACK_OF(CONF_VALUE) + *ext_list) +{ + POLICY_MAPPINGS *pmaps = a; + POLICY_MAPPING *pmap; + size_t i; + char obj_tmp1[80]; + char obj_tmp2[80]; + for (i = 0; i < sk_POLICY_MAPPING_num(pmaps); i++) { + pmap = sk_POLICY_MAPPING_value(pmaps, i); + i2t_ASN1_OBJECT(obj_tmp1, 80, pmap->issuerDomainPolicy); + i2t_ASN1_OBJECT(obj_tmp2, 80, pmap->subjectDomainPolicy); + X509V3_add_value(obj_tmp1, obj_tmp2, &ext_list); + } + return ext_list; +} + +static void *v2i_POLICY_MAPPINGS(const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval) +{ + POLICY_MAPPINGS *pmaps; + POLICY_MAPPING *pmap; + ASN1_OBJECT *obj1, *obj2; + CONF_VALUE *val; + size_t i; + + if (!(pmaps = sk_POLICY_MAPPING_new_null())) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + return NULL; + } + + for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { + val = sk_CONF_VALUE_value(nval, i); + if (!val->value || !val->name) { + sk_POLICY_MAPPING_pop_free(pmaps, POLICY_MAPPING_free); + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER); + X509V3_conf_err(val); + return NULL; + } + obj1 = OBJ_txt2obj(val->name, 0); + obj2 = OBJ_txt2obj(val->value, 0); + if (!obj1 || !obj2) { + sk_POLICY_MAPPING_pop_free(pmaps, POLICY_MAPPING_free); + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER); + X509V3_conf_err(val); + return NULL; + } + pmap = POLICY_MAPPING_new(); + if (!pmap) { + sk_POLICY_MAPPING_pop_free(pmaps, POLICY_MAPPING_free); + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + return NULL; + } + pmap->issuerDomainPolicy = obj1; + pmap->subjectDomainPolicy = obj2; + sk_POLICY_MAPPING_push(pmaps, pmap); + } + return pmaps; +} diff --git a/external/boringssl/crypto/x509v3/v3_prn.c b/external/boringssl/crypto/x509v3/v3_prn.c new file mode 100644 index 0000000000..2f5efcff07 --- /dev/null +++ b/external/boringssl/crypto/x509v3/v3_prn.c @@ -0,0 +1,229 @@ +/* v3_prn.c */ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project + * 1999. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +/* X509 v3 extension utilities */ + +#include + +#include +#include +#include +#include + +/* Extension printing routines */ + +static int unknown_ext_print(BIO *out, X509_EXTENSION *ext, + unsigned long flag, int indent, int supported); + +/* Print out a name+value stack */ + +void X509V3_EXT_val_prn(BIO *out, STACK_OF(CONF_VALUE) *val, int indent, + int ml) +{ + size_t i; + CONF_VALUE *nval; + if (!val) + return; + if (!ml || !sk_CONF_VALUE_num(val)) { + BIO_printf(out, "%*s", indent, ""); + if (!sk_CONF_VALUE_num(val)) + BIO_puts(out, "\n"); + } + for (i = 0; i < sk_CONF_VALUE_num(val); i++) { + if (ml) + BIO_printf(out, "%*s", indent, ""); + else if (i > 0) + BIO_printf(out, ", "); + nval = sk_CONF_VALUE_value(val, i); + if (!nval->name) + BIO_puts(out, nval->value); + else if (!nval->value) + BIO_puts(out, nval->name); + else + BIO_printf(out, "%s:%s", nval->name, nval->value); + if (ml) + BIO_puts(out, "\n"); + } +} + +/* Main routine: print out a general extension */ + +int X509V3_EXT_print(BIO *out, X509_EXTENSION *ext, unsigned long flag, + int indent) +{ + void *ext_str = NULL; + char *value = NULL; + const unsigned char *p; + const X509V3_EXT_METHOD *method; + STACK_OF(CONF_VALUE) *nval = NULL; + int ok = 1; + + if (!(method = X509V3_EXT_get(ext))) + return unknown_ext_print(out, ext, flag, indent, 0); + p = ext->value->data; + if (method->it) + ext_str = + ASN1_item_d2i(NULL, &p, ext->value->length, + ASN1_ITEM_ptr(method->it)); + else + ext_str = method->d2i(NULL, &p, ext->value->length); + + if (!ext_str) + return unknown_ext_print(out, ext, flag, indent, 1); + + if (method->i2s) { + if (!(value = method->i2s(method, ext_str))) { + ok = 0; + goto err; + } + BIO_printf(out, "%*s%s", indent, "", value); + } else if (method->i2v) { + if (!(nval = method->i2v(method, ext_str, NULL))) { + ok = 0; + goto err; + } + X509V3_EXT_val_prn(out, nval, indent, + method->ext_flags & X509V3_EXT_MULTILINE); + } else if (method->i2r) { + if (!method->i2r(method, ext_str, out, indent)) + ok = 0; + } else + ok = 0; + + err: + sk_CONF_VALUE_pop_free(nval, X509V3_conf_free); + if (value) + OPENSSL_free(value); + if (method->it) + ASN1_item_free(ext_str, ASN1_ITEM_ptr(method->it)); + else + method->ext_free(ext_str); + return ok; +} + +int X509V3_extensions_print(BIO *bp, const char *title, + STACK_OF(X509_EXTENSION) *exts, + unsigned long flag, int indent) +{ + size_t i; + int j; + + if (sk_X509_EXTENSION_num(exts) <= 0) + return 1; + + if (title) { + BIO_printf(bp, "%*s%s:\n", indent, "", title); + indent += 4; + } + + for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) { + ASN1_OBJECT *obj; + X509_EXTENSION *ex; + ex = sk_X509_EXTENSION_value(exts, i); + if (indent && BIO_printf(bp, "%*s", indent, "") <= 0) + return 0; + obj = X509_EXTENSION_get_object(ex); + i2a_ASN1_OBJECT(bp, obj); + j = X509_EXTENSION_get_critical(ex); + if (BIO_printf(bp, ": %s\n", j ? "critical" : "") <= 0) + return 0; + if (!X509V3_EXT_print(bp, ex, flag, indent + 4)) { + BIO_printf(bp, "%*s", indent + 4, ""); + M_ASN1_OCTET_STRING_print(bp, ex->value); + } + if (BIO_write(bp, "\n", 1) <= 0) + return 0; + } + return 1; +} + +static int unknown_ext_print(BIO *out, X509_EXTENSION *ext, + unsigned long flag, int indent, int supported) +{ + switch (flag & X509V3_EXT_UNKNOWN_MASK) { + + case X509V3_EXT_DEFAULT: + return 0; + + case X509V3_EXT_ERROR_UNKNOWN: + if (supported) + BIO_printf(out, "%*s", indent, ""); + else + BIO_printf(out, "%*s", indent, ""); + return 1; + + case X509V3_EXT_PARSE_UNKNOWN: + case X509V3_EXT_DUMP_UNKNOWN: + return BIO_hexdump(out, ext->value->data, ext->value->length, indent); + + default: + return 1; + } +} + +#ifndef OPENSSL_NO_FP_API +int X509V3_EXT_print_fp(FILE *fp, X509_EXTENSION *ext, int flag, int indent) +{ + BIO *bio_tmp; + int ret; + if (!(bio_tmp = BIO_new_fp(fp, BIO_NOCLOSE))) + return 0; + ret = X509V3_EXT_print(bio_tmp, ext, flag, indent); + BIO_free(bio_tmp); + return ret; +} +#endif diff --git a/external/boringssl/crypto/x509v3/v3_purp.c b/external/boringssl/crypto/x509v3/v3_purp.c new file mode 100644 index 0000000000..f9324d4e08 --- /dev/null +++ b/external/boringssl/crypto/x509v3/v3_purp.c @@ -0,0 +1,874 @@ +/* v3_purp.c */ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project + * 2001. + */ +/* ==================================================================== + * Copyright (c) 1999-2004 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../internal.h" + +#define V1_ROOT (EXFLAG_V1|EXFLAG_SS) +#define ku_reject(x, usage) \ + (((x)->ex_flags & EXFLAG_KUSAGE) && !((x)->ex_kusage & (usage))) +#define xku_reject(x, usage) \ + (((x)->ex_flags & EXFLAG_XKUSAGE) && !((x)->ex_xkusage & (usage))) +#define ns_reject(x, usage) \ + (((x)->ex_flags & EXFLAG_NSCERT) && !((x)->ex_nscert & (usage))) + +static void x509v3_cache_extensions(X509 *x); + +static int check_ssl_ca(const X509 *x); +static int check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x, + int ca); +static int check_purpose_ssl_server(const X509_PURPOSE *xp, const X509 *x, + int ca); +static int check_purpose_ns_ssl_server(const X509_PURPOSE *xp, const X509 *x, + int ca); +static int purpose_smime(const X509 *x, int ca); +static int check_purpose_smime_sign(const X509_PURPOSE *xp, const X509 *x, + int ca); +static int check_purpose_smime_encrypt(const X509_PURPOSE *xp, const X509 *x, + int ca); +static int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x, + int ca); +static int check_purpose_timestamp_sign(const X509_PURPOSE *xp, const X509 *x, + int ca); +static int no_check(const X509_PURPOSE *xp, const X509 *x, int ca); +static int ocsp_helper(const X509_PURPOSE *xp, const X509 *x, int ca); + +static int xp_cmp(const X509_PURPOSE **a, const X509_PURPOSE **b); +static void xptable_free(X509_PURPOSE *p); + +static X509_PURPOSE xstandard[] = { + {X509_PURPOSE_SSL_CLIENT, X509_TRUST_SSL_CLIENT, 0, + check_purpose_ssl_client, (char *)"SSL client", (char *)"sslclient", + NULL}, + {X509_PURPOSE_SSL_SERVER, X509_TRUST_SSL_SERVER, 0, + check_purpose_ssl_server, (char *)"SSL server", (char *)"sslserver", + NULL}, + {X509_PURPOSE_NS_SSL_SERVER, X509_TRUST_SSL_SERVER, 0, + check_purpose_ns_ssl_server, (char *)"Netscape SSL server", + (char *)"nssslserver", NULL}, + {X509_PURPOSE_SMIME_SIGN, X509_TRUST_EMAIL, 0, check_purpose_smime_sign, + (char *)"S/MIME signing", (char *)"smimesign", NULL}, + {X509_PURPOSE_SMIME_ENCRYPT, X509_TRUST_EMAIL, 0, + check_purpose_smime_encrypt, (char *)"S/MIME encryption", + (char *)"smimeencrypt", NULL}, + {X509_PURPOSE_CRL_SIGN, X509_TRUST_COMPAT, 0, check_purpose_crl_sign, + (char *)"CRL signing", (char *)"crlsign", NULL}, + {X509_PURPOSE_ANY, X509_TRUST_DEFAULT, 0, no_check, (char *)"Any Purpose", + (char *)"any", NULL}, + {X509_PURPOSE_OCSP_HELPER, X509_TRUST_COMPAT, 0, ocsp_helper, + (char *)"OCSP helper", (char *)"ocsphelper", NULL}, + {X509_PURPOSE_TIMESTAMP_SIGN, X509_TRUST_TSA, 0, + check_purpose_timestamp_sign, (char *)"Time Stamp signing", + (char *)"timestampsign", NULL}, +}; + +#define X509_PURPOSE_COUNT (sizeof(xstandard)/sizeof(X509_PURPOSE)) + +static STACK_OF(X509_PURPOSE) *xptable = NULL; + +static int xp_cmp(const X509_PURPOSE **a, const X509_PURPOSE **b) +{ + return (*a)->purpose - (*b)->purpose; +} + +/* + * As much as I'd like to make X509_check_purpose use a "const" X509* I + * really can't because it does recalculate hashes and do other non-const + * things. + */ +int X509_check_purpose(X509 *x, int id, int ca) +{ + int idx; + const X509_PURPOSE *pt; + if (!(x->ex_flags & EXFLAG_SET)) { + x509v3_cache_extensions(x); + } + if (id == -1) + return 1; + idx = X509_PURPOSE_get_by_id(id); + if (idx == -1) + return -1; + pt = X509_PURPOSE_get0(idx); + return pt->check_purpose(pt, x, ca); +} + +int X509_PURPOSE_set(int *p, int purpose) +{ + if (X509_PURPOSE_get_by_id(purpose) == -1) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_PURPOSE); + return 0; + } + *p = purpose; + return 1; +} + +int X509_PURPOSE_get_count(void) +{ + if (!xptable) + return X509_PURPOSE_COUNT; + return sk_X509_PURPOSE_num(xptable) + X509_PURPOSE_COUNT; +} + +X509_PURPOSE *X509_PURPOSE_get0(int idx) +{ + if (idx < 0) + return NULL; + if (idx < (int)X509_PURPOSE_COUNT) + return xstandard + idx; + return sk_X509_PURPOSE_value(xptable, idx - X509_PURPOSE_COUNT); +} + +int X509_PURPOSE_get_by_sname(char *sname) +{ + int i; + X509_PURPOSE *xptmp; + for (i = 0; i < X509_PURPOSE_get_count(); i++) { + xptmp = X509_PURPOSE_get0(i); + if (!strcmp(xptmp->sname, sname)) + return i; + } + return -1; +} + +int X509_PURPOSE_get_by_id(int purpose) +{ + X509_PURPOSE tmp; + size_t idx; + + if ((purpose >= X509_PURPOSE_MIN) && (purpose <= X509_PURPOSE_MAX)) + return purpose - X509_PURPOSE_MIN; + tmp.purpose = purpose; + if (!xptable) + return -1; + + if (!sk_X509_PURPOSE_find(xptable, &idx, &tmp)) + return -1; + return idx + X509_PURPOSE_COUNT; +} + +int X509_PURPOSE_add(int id, int trust, int flags, + int (*ck) (const X509_PURPOSE *, const X509 *, int), + char *name, char *sname, void *arg) +{ + int idx; + X509_PURPOSE *ptmp; + char *name_dup, *sname_dup; + + /* + * This is set according to what we change: application can't set it + */ + flags &= ~X509_PURPOSE_DYNAMIC; + /* This will always be set for application modified trust entries */ + flags |= X509_PURPOSE_DYNAMIC_NAME; + /* Get existing entry if any */ + idx = X509_PURPOSE_get_by_id(id); + /* Need a new entry */ + if (idx == -1) { + if (!(ptmp = OPENSSL_malloc(sizeof(X509_PURPOSE)))) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + return 0; + } + ptmp->flags = X509_PURPOSE_DYNAMIC; + } else + ptmp = X509_PURPOSE_get0(idx); + + /* Duplicate the supplied names. */ + name_dup = BUF_strdup(name); + sname_dup = BUF_strdup(sname); + if (name_dup == NULL || sname_dup == NULL) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + if (name_dup != NULL) + OPENSSL_free(name_dup); + if (sname_dup != NULL) + OPENSSL_free(sname_dup); + if (idx == -1) + OPENSSL_free(ptmp); + return 0; + } + + /* OPENSSL_free existing name if dynamic */ + if (ptmp->flags & X509_PURPOSE_DYNAMIC_NAME) { + OPENSSL_free(ptmp->name); + OPENSSL_free(ptmp->sname); + } + /* dup supplied name */ + ptmp->name = name_dup; + ptmp->sname = sname_dup; + /* Keep the dynamic flag of existing entry */ + ptmp->flags &= X509_PURPOSE_DYNAMIC; + /* Set all other flags */ + ptmp->flags |= flags; + + ptmp->purpose = id; + ptmp->trust = trust; + ptmp->check_purpose = ck; + ptmp->usr_data = arg; + + /* If its a new entry manage the dynamic table */ + if (idx == -1) { + if (!xptable && !(xptable = sk_X509_PURPOSE_new(xp_cmp))) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + xptable_free(ptmp); + return 0; + } + if (!sk_X509_PURPOSE_push(xptable, ptmp)) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + xptable_free(ptmp); + return 0; + } + } + return 1; +} + +static void xptable_free(X509_PURPOSE *p) +{ + if (!p) + return; + if (p->flags & X509_PURPOSE_DYNAMIC) { + if (p->flags & X509_PURPOSE_DYNAMIC_NAME) { + OPENSSL_free(p->name); + OPENSSL_free(p->sname); + } + OPENSSL_free(p); + } +} + +void X509_PURPOSE_cleanup(void) +{ + unsigned int i; + sk_X509_PURPOSE_pop_free(xptable, xptable_free); + for (i = 0; i < X509_PURPOSE_COUNT; i++) + xptable_free(xstandard + i); + xptable = NULL; +} + +int X509_PURPOSE_get_id(X509_PURPOSE *xp) +{ + return xp->purpose; +} + +char *X509_PURPOSE_get0_name(X509_PURPOSE *xp) +{ + return xp->name; +} + +char *X509_PURPOSE_get0_sname(X509_PURPOSE *xp) +{ + return xp->sname; +} + +int X509_PURPOSE_get_trust(X509_PURPOSE *xp) +{ + return xp->trust; +} + +static int nid_cmp(const void *void_a, const void *void_b) +{ + const int *a = void_a, *b = void_b; + + return *a - *b; +} + +int X509_supported_extension(X509_EXTENSION *ex) +{ + /* + * This table is a list of the NIDs of supported extensions: that is + * those which are used by the verify process. If an extension is + * critical and doesn't appear in this list then the verify process will + * normally reject the certificate. The list must be kept in numerical + * order because it will be searched using bsearch. + */ + + static const int supported_nids[] = { + NID_netscape_cert_type, /* 71 */ + NID_key_usage, /* 83 */ + NID_subject_alt_name, /* 85 */ + NID_basic_constraints, /* 87 */ + NID_certificate_policies, /* 89 */ + NID_ext_key_usage, /* 126 */ + NID_policy_constraints, /* 401 */ + NID_proxyCertInfo, /* 663 */ + NID_name_constraints, /* 666 */ + NID_policy_mappings, /* 747 */ + NID_inhibit_any_policy /* 748 */ + }; + + int ex_nid = OBJ_obj2nid(X509_EXTENSION_get_object(ex)); + + if (ex_nid == NID_undef) + return 0; + + if (bsearch + (&ex_nid, supported_nids, sizeof(supported_nids) / sizeof(int), + sizeof(int), nid_cmp) != NULL) + return 1; + return 0; +} + +static void setup_dp(X509 *x, DIST_POINT *dp) +{ + X509_NAME *iname = NULL; + size_t i; + if (dp->reasons) { + if (dp->reasons->length > 0) + dp->dp_reasons = dp->reasons->data[0]; + if (dp->reasons->length > 1) + dp->dp_reasons |= (dp->reasons->data[1] << 8); + dp->dp_reasons &= CRLDP_ALL_REASONS; + } else + dp->dp_reasons = CRLDP_ALL_REASONS; + if (!dp->distpoint || (dp->distpoint->type != 1)) + return; + for (i = 0; i < sk_GENERAL_NAME_num(dp->CRLissuer); i++) { + GENERAL_NAME *gen = sk_GENERAL_NAME_value(dp->CRLissuer, i); + if (gen->type == GEN_DIRNAME) { + iname = gen->d.directoryName; + break; + } + } + if (!iname) + iname = X509_get_issuer_name(x); + + DIST_POINT_set_dpname(dp->distpoint, iname); + +} + +static void setup_crldp(X509 *x) +{ + size_t i; + x->crldp = X509_get_ext_d2i(x, NID_crl_distribution_points, NULL, NULL); + for (i = 0; i < sk_DIST_POINT_num(x->crldp); i++) + setup_dp(x, sk_DIST_POINT_value(x->crldp, i)); +} + +/* + * g_x509_cache_extensions_lock is used to protect against concurrent calls + * to |x509v3_cache_extensions|. Ideally this would be done with a + * |CRYPTO_once_t| in the |X509| structure, but |CRYPTO_once_t| isn't public. + * Note: it's not entirely clear whether this lock is needed. Not all paths to + * this function took a lock in OpenSSL. + */ +static struct CRYPTO_STATIC_MUTEX g_x509_cache_extensions_lock = + CRYPTO_STATIC_MUTEX_INIT; + +static void x509v3_cache_extensions(X509 *x) +{ + BASIC_CONSTRAINTS *bs; + PROXY_CERT_INFO_EXTENSION *pci; + ASN1_BIT_STRING *usage; + ASN1_BIT_STRING *ns; + EXTENDED_KEY_USAGE *extusage; + X509_EXTENSION *ex; + size_t i; + int j; + + CRYPTO_STATIC_MUTEX_lock_write(&g_x509_cache_extensions_lock); + + if (x->ex_flags & EXFLAG_SET) { + CRYPTO_STATIC_MUTEX_unlock_write(&g_x509_cache_extensions_lock); + return; + } + + X509_digest(x, EVP_sha1(), x->sha1_hash, NULL); + /* V1 should mean no extensions ... */ + if (!X509_get_version(x)) + x->ex_flags |= EXFLAG_V1; + /* Handle basic constraints */ + if ((bs = X509_get_ext_d2i(x, NID_basic_constraints, NULL, NULL))) { + if (bs->ca) + x->ex_flags |= EXFLAG_CA; + if (bs->pathlen) { + if ((bs->pathlen->type == V_ASN1_NEG_INTEGER) + || !bs->ca) { + x->ex_flags |= EXFLAG_INVALID; + x->ex_pathlen = 0; + } else + x->ex_pathlen = ASN1_INTEGER_get(bs->pathlen); + } else + x->ex_pathlen = -1; + BASIC_CONSTRAINTS_free(bs); + x->ex_flags |= EXFLAG_BCONS; + } + /* Handle proxy certificates */ + if ((pci = X509_get_ext_d2i(x, NID_proxyCertInfo, NULL, NULL))) { + if (x->ex_flags & EXFLAG_CA + || X509_get_ext_by_NID(x, NID_subject_alt_name, -1) >= 0 + || X509_get_ext_by_NID(x, NID_issuer_alt_name, -1) >= 0) { + x->ex_flags |= EXFLAG_INVALID; + } + if (pci->pcPathLengthConstraint) { + x->ex_pcpathlen = ASN1_INTEGER_get(pci->pcPathLengthConstraint); + } else + x->ex_pcpathlen = -1; + PROXY_CERT_INFO_EXTENSION_free(pci); + x->ex_flags |= EXFLAG_PROXY; + } + /* Handle key usage */ + if ((usage = X509_get_ext_d2i(x, NID_key_usage, NULL, NULL))) { + if (usage->length > 0) { + x->ex_kusage = usage->data[0]; + if (usage->length > 1) + x->ex_kusage |= usage->data[1] << 8; + } else + x->ex_kusage = 0; + x->ex_flags |= EXFLAG_KUSAGE; + ASN1_BIT_STRING_free(usage); + } + x->ex_xkusage = 0; + if ((extusage = X509_get_ext_d2i(x, NID_ext_key_usage, NULL, NULL))) { + x->ex_flags |= EXFLAG_XKUSAGE; + for (i = 0; i < sk_ASN1_OBJECT_num(extusage); i++) { + switch (OBJ_obj2nid(sk_ASN1_OBJECT_value(extusage, i))) { + case NID_server_auth: + x->ex_xkusage |= XKU_SSL_SERVER; + break; + + case NID_client_auth: + x->ex_xkusage |= XKU_SSL_CLIENT; + break; + + case NID_email_protect: + x->ex_xkusage |= XKU_SMIME; + break; + + case NID_code_sign: + x->ex_xkusage |= XKU_CODE_SIGN; + break; + + case NID_ms_sgc: + case NID_ns_sgc: + x->ex_xkusage |= XKU_SGC; + break; + + case NID_OCSP_sign: + x->ex_xkusage |= XKU_OCSP_SIGN; + break; + + case NID_time_stamp: + x->ex_xkusage |= XKU_TIMESTAMP; + break; + + case NID_dvcs: + x->ex_xkusage |= XKU_DVCS; + break; + + case NID_anyExtendedKeyUsage: + x->ex_xkusage |= XKU_ANYEKU; + break; + } + } + sk_ASN1_OBJECT_pop_free(extusage, ASN1_OBJECT_free); + } + + if ((ns = X509_get_ext_d2i(x, NID_netscape_cert_type, NULL, NULL))) { + if (ns->length > 0) + x->ex_nscert = ns->data[0]; + else + x->ex_nscert = 0; + x->ex_flags |= EXFLAG_NSCERT; + ASN1_BIT_STRING_free(ns); + } + x->skid = X509_get_ext_d2i(x, NID_subject_key_identifier, NULL, NULL); + x->akid = X509_get_ext_d2i(x, NID_authority_key_identifier, NULL, NULL); + /* Does subject name match issuer ? */ + if (!X509_NAME_cmp(X509_get_subject_name(x), X509_get_issuer_name(x))) { + x->ex_flags |= EXFLAG_SI; + /* If SKID matches AKID also indicate self signed */ + if (X509_check_akid(x, x->akid) == X509_V_OK && + !ku_reject(x, KU_KEY_CERT_SIGN)) + x->ex_flags |= EXFLAG_SS; + } + x->altname = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL); + x->nc = X509_get_ext_d2i(x, NID_name_constraints, &j, NULL); + if (!x->nc && (j != -1)) + x->ex_flags |= EXFLAG_INVALID; + setup_crldp(x); + + for (j = 0; j < X509_get_ext_count(x); j++) { + ex = X509_get_ext(x, j); + if (OBJ_obj2nid(X509_EXTENSION_get_object(ex)) + == NID_freshest_crl) + x->ex_flags |= EXFLAG_FRESHEST; + if (!X509_EXTENSION_get_critical(ex)) + continue; + if (!X509_supported_extension(ex)) { + x->ex_flags |= EXFLAG_CRITICAL; + break; + } + } + x->ex_flags |= EXFLAG_SET; + + CRYPTO_STATIC_MUTEX_unlock_write(&g_x509_cache_extensions_lock); +} + +/* + * CA checks common to all purposes return codes: 0 not a CA 1 is a CA 2 + * basicConstraints absent so "maybe" a CA 3 basicConstraints absent but self + * signed V1. 4 basicConstraints absent but keyUsage present and keyCertSign + * asserted. + */ + +static int check_ca(const X509 *x) +{ + /* keyUsage if present should allow cert signing */ + if (ku_reject(x, KU_KEY_CERT_SIGN)) + return 0; + if (x->ex_flags & EXFLAG_BCONS) { + if (x->ex_flags & EXFLAG_CA) + return 1; + /* If basicConstraints says not a CA then say so */ + else + return 0; + } else { + /* we support V1 roots for... uh, I don't really know why. */ + if ((x->ex_flags & V1_ROOT) == V1_ROOT) + return 3; + /* + * If key usage present it must have certSign so tolerate it + */ + else if (x->ex_flags & EXFLAG_KUSAGE) + return 4; + /* Older certificates could have Netscape-specific CA types */ + else if (x->ex_flags & EXFLAG_NSCERT && x->ex_nscert & NS_ANY_CA) + return 5; + /* can this still be regarded a CA certificate? I doubt it */ + return 0; + } +} + +int X509_check_ca(X509 *x) +{ + if (!(x->ex_flags & EXFLAG_SET)) { + x509v3_cache_extensions(x); + } + + return check_ca(x); +} + +/* Check SSL CA: common checks for SSL client and server */ +static int check_ssl_ca(const X509 *x) +{ + int ca_ret; + ca_ret = check_ca(x); + if (!ca_ret) + return 0; + /* check nsCertType if present */ + if (ca_ret != 5 || x->ex_nscert & NS_SSL_CA) + return ca_ret; + else + return 0; +} + +static int check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x, + int ca) +{ + if (xku_reject(x, XKU_SSL_CLIENT)) + return 0; + if (ca) + return check_ssl_ca(x); + /* We need to do digital signatures or key agreement */ + if (ku_reject(x, KU_DIGITAL_SIGNATURE | KU_KEY_AGREEMENT)) + return 0; + /* nsCertType if present should allow SSL client use */ + if (ns_reject(x, NS_SSL_CLIENT)) + return 0; + return 1; +} + +/* + * Key usage needed for TLS/SSL server: digital signature, encipherment or + * key agreement. The ssl code can check this more thoroughly for individual + * key types. + */ +#define KU_TLS \ + KU_DIGITAL_SIGNATURE|KU_KEY_ENCIPHERMENT|KU_KEY_AGREEMENT + +static int check_purpose_ssl_server(const X509_PURPOSE *xp, const X509 *x, + int ca) +{ + if (xku_reject(x, XKU_SSL_SERVER | XKU_SGC)) + return 0; + if (ca) + return check_ssl_ca(x); + + if (ns_reject(x, NS_SSL_SERVER)) + return 0; + if (ku_reject(x, KU_TLS)) + return 0; + + return 1; + +} + +static int check_purpose_ns_ssl_server(const X509_PURPOSE *xp, const X509 *x, + int ca) +{ + int ret; + ret = check_purpose_ssl_server(xp, x, ca); + if (!ret || ca) + return ret; + /* We need to encipher or Netscape complains */ + if (ku_reject(x, KU_KEY_ENCIPHERMENT)) + return 0; + return ret; +} + +/* common S/MIME checks */ +static int purpose_smime(const X509 *x, int ca) +{ + if (xku_reject(x, XKU_SMIME)) + return 0; + if (ca) { + int ca_ret; + ca_ret = check_ca(x); + if (!ca_ret) + return 0; + /* check nsCertType if present */ + if (ca_ret != 5 || x->ex_nscert & NS_SMIME_CA) + return ca_ret; + else + return 0; + } + if (x->ex_flags & EXFLAG_NSCERT) { + if (x->ex_nscert & NS_SMIME) + return 1; + /* Workaround for some buggy certificates */ + if (x->ex_nscert & NS_SSL_CLIENT) + return 2; + return 0; + } + return 1; +} + +static int check_purpose_smime_sign(const X509_PURPOSE *xp, const X509 *x, + int ca) +{ + int ret; + ret = purpose_smime(x, ca); + if (!ret || ca) + return ret; + if (ku_reject(x, KU_DIGITAL_SIGNATURE | KU_NON_REPUDIATION)) + return 0; + return ret; +} + +static int check_purpose_smime_encrypt(const X509_PURPOSE *xp, const X509 *x, + int ca) +{ + int ret; + ret = purpose_smime(x, ca); + if (!ret || ca) + return ret; + if (ku_reject(x, KU_KEY_ENCIPHERMENT)) + return 0; + return ret; +} + +static int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x, + int ca) +{ + if (ca) { + int ca_ret; + if ((ca_ret = check_ca(x)) != 2) + return ca_ret; + else + return 0; + } + if (ku_reject(x, KU_CRL_SIGN)) + return 0; + return 1; +} + +/* + * OCSP helper: this is *not* a full OCSP check. It just checks that each CA + * is valid. Additional checks must be made on the chain. + */ + +static int ocsp_helper(const X509_PURPOSE *xp, const X509 *x, int ca) +{ + /* + * Must be a valid CA. Should we really support the "I don't know" value + * (2)? + */ + if (ca) + return check_ca(x); + /* leaf certificate is checked in OCSP_verify() */ + return 1; +} + +static int check_purpose_timestamp_sign(const X509_PURPOSE *xp, const X509 *x, + int ca) +{ + int i_ext; + + /* If ca is true we must return if this is a valid CA certificate. */ + if (ca) + return check_ca(x); + + /* + * Check the optional key usage field: + * if Key Usage is present, it must be one of digitalSignature + * and/or nonRepudiation (other values are not consistent and shall + * be rejected). + */ + if ((x->ex_flags & EXFLAG_KUSAGE) + && ((x->ex_kusage & ~(KU_NON_REPUDIATION | KU_DIGITAL_SIGNATURE)) || + !(x->ex_kusage & (KU_NON_REPUDIATION | KU_DIGITAL_SIGNATURE)))) + return 0; + + /* Only time stamp key usage is permitted and it's required. */ + if (!(x->ex_flags & EXFLAG_XKUSAGE) || x->ex_xkusage != XKU_TIMESTAMP) + return 0; + + /* Extended Key Usage MUST be critical */ + i_ext = X509_get_ext_by_NID((X509 *)x, NID_ext_key_usage, -1); + if (i_ext >= 0) { + X509_EXTENSION *ext = X509_get_ext((X509 *)x, i_ext); + if (!X509_EXTENSION_get_critical(ext)) + return 0; + } + + return 1; +} + +static int no_check(const X509_PURPOSE *xp, const X509 *x, int ca) +{ + return 1; +} + +/* + * Various checks to see if one certificate issued the second. This can be + * used to prune a set of possible issuer certificates which have been looked + * up using some simple method such as by subject name. These are: 1. Check + * issuer_name(subject) == subject_name(issuer) 2. If akid(subject) exists + * check it matches issuer 3. If key_usage(issuer) exists check it supports + * certificate signing returns 0 for OK, positive for reason for mismatch, + * reasons match codes for X509_verify_cert() + */ + +int X509_check_issued(X509 *issuer, X509 *subject) +{ + if (X509_NAME_cmp(X509_get_subject_name(issuer), + X509_get_issuer_name(subject))) + return X509_V_ERR_SUBJECT_ISSUER_MISMATCH; + x509v3_cache_extensions(issuer); + x509v3_cache_extensions(subject); + + if (subject->akid) { + int ret = X509_check_akid(issuer, subject->akid); + if (ret != X509_V_OK) + return ret; + } + + if (subject->ex_flags & EXFLAG_PROXY) { + if (ku_reject(issuer, KU_DIGITAL_SIGNATURE)) + return X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE; + } else if (ku_reject(issuer, KU_KEY_CERT_SIGN)) + return X509_V_ERR_KEYUSAGE_NO_CERTSIGN; + return X509_V_OK; +} + +int X509_check_akid(X509 *issuer, AUTHORITY_KEYID *akid) +{ + + if (!akid) + return X509_V_OK; + + /* Check key ids (if present) */ + if (akid->keyid && issuer->skid && + ASN1_OCTET_STRING_cmp(akid->keyid, issuer->skid)) + return X509_V_ERR_AKID_SKID_MISMATCH; + /* Check serial number */ + if (akid->serial && + ASN1_INTEGER_cmp(X509_get_serialNumber(issuer), akid->serial)) + return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH; + /* Check issuer name */ + if (akid->issuer) { + /* + * Ugh, for some peculiar reason AKID includes SEQUENCE OF + * GeneralName. So look for a DirName. There may be more than one but + * we only take any notice of the first. + */ + GENERAL_NAMES *gens; + GENERAL_NAME *gen; + X509_NAME *nm = NULL; + size_t i; + gens = akid->issuer; + for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { + gen = sk_GENERAL_NAME_value(gens, i); + if (gen->type == GEN_DIRNAME) { + nm = gen->d.dirn; + break; + } + } + if (nm && X509_NAME_cmp(nm, X509_get_issuer_name(issuer))) + return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH; + } + return X509_V_OK; +} diff --git a/external/boringssl/crypto/x509v3/v3_skey.c b/external/boringssl/crypto/x509v3/v3_skey.c new file mode 100644 index 0000000000..65f8287c1c --- /dev/null +++ b/external/boringssl/crypto/x509v3/v3_skey.c @@ -0,0 +1,152 @@ +/* v3_skey.c */ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project + * 1999. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include +#include + +#include +#include +#include +#include + +static ASN1_OCTET_STRING *s2i_skey_id(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, char *str); +const X509V3_EXT_METHOD v3_skey_id = { + NID_subject_key_identifier, 0, ASN1_ITEM_ref(ASN1_OCTET_STRING), + 0, 0, 0, 0, + (X509V3_EXT_I2S)i2s_ASN1_OCTET_STRING, + (X509V3_EXT_S2I)s2i_skey_id, + 0, 0, 0, 0, + NULL +}; + +char *i2s_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method, ASN1_OCTET_STRING *oct) +{ + return hex_to_string(oct->data, oct->length); +} + +ASN1_OCTET_STRING *s2i_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, char *str) +{ + ASN1_OCTET_STRING *oct; + long length; + + if (!(oct = M_ASN1_OCTET_STRING_new())) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + return NULL; + } + + if (!(oct->data = string_to_hex(str, &length))) { + M_ASN1_OCTET_STRING_free(oct); + return NULL; + } + + oct->length = length; + + return oct; + +} + +static ASN1_OCTET_STRING *s2i_skey_id(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, char *str) +{ + ASN1_OCTET_STRING *oct; + ASN1_BIT_STRING *pk; + unsigned char pkey_dig[EVP_MAX_MD_SIZE]; + unsigned int diglen; + + if (strcmp(str, "hash")) + return s2i_ASN1_OCTET_STRING(method, ctx, str); + + if (!(oct = M_ASN1_OCTET_STRING_new())) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + return NULL; + } + + if (ctx && (ctx->flags == CTX_TEST)) + return oct; + + if (!ctx || (!ctx->subject_req && !ctx->subject_cert)) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_PUBLIC_KEY); + goto err; + } + + if (ctx->subject_req) + pk = ctx->subject_req->req_info->pubkey->public_key; + else + pk = ctx->subject_cert->cert_info->key->public_key; + + if (!pk) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_PUBLIC_KEY); + goto err; + } + + if (!EVP_Digest + (pk->data, pk->length, pkey_dig, &diglen, EVP_sha1(), NULL)) + goto err; + + if (!M_ASN1_OCTET_STRING_set(oct, pkey_dig, diglen)) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + goto err; + } + + return oct; + + err: + M_ASN1_OCTET_STRING_free(oct); + return NULL; +} diff --git a/external/boringssl/crypto/x509v3/v3_sxnet.c b/external/boringssl/crypto/x509v3/v3_sxnet.c new file mode 100644 index 0000000000..51c5a676f0 --- /dev/null +++ b/external/boringssl/crypto/x509v3/v3_sxnet.c @@ -0,0 +1,274 @@ +/* v3_sxnet.c */ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project + * 1999. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +/* Support for Thawte strong extranet extension */ + +#define SXNET_TEST + +static int sxnet_i2r(X509V3_EXT_METHOD *method, SXNET *sx, BIO *out, + int indent); +#ifdef SXNET_TEST +static SXNET *sxnet_v2i(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *nval); +#endif +const X509V3_EXT_METHOD v3_sxnet = { + NID_sxnet, X509V3_EXT_MULTILINE, ASN1_ITEM_ref(SXNET), + 0, 0, 0, 0, + 0, 0, + 0, +#ifdef SXNET_TEST + (X509V3_EXT_V2I)sxnet_v2i, +#else + 0, +#endif + (X509V3_EXT_I2R)sxnet_i2r, + 0, + NULL +}; + +ASN1_SEQUENCE(SXNETID) = { + ASN1_SIMPLE(SXNETID, zone, ASN1_INTEGER), + ASN1_SIMPLE(SXNETID, user, ASN1_OCTET_STRING) +} ASN1_SEQUENCE_END(SXNETID) + +IMPLEMENT_ASN1_FUNCTIONS(SXNETID) + +ASN1_SEQUENCE(SXNET) = { + ASN1_SIMPLE(SXNET, version, ASN1_INTEGER), + ASN1_SEQUENCE_OF(SXNET, ids, SXNETID) +} ASN1_SEQUENCE_END(SXNET) + +IMPLEMENT_ASN1_FUNCTIONS(SXNET) + +static int sxnet_i2r(X509V3_EXT_METHOD *method, SXNET *sx, BIO *out, + int indent) +{ + long v; + char *tmp; + SXNETID *id; + size_t i; + v = ASN1_INTEGER_get(sx->version); + BIO_printf(out, "%*sVersion: %ld (0x%lX)", indent, "", v + 1, v); + for (i = 0; i < sk_SXNETID_num(sx->ids); i++) { + id = sk_SXNETID_value(sx->ids, i); + tmp = i2s_ASN1_INTEGER(NULL, id->zone); + BIO_printf(out, "\n%*sZone: %s, User: ", indent, "", tmp); + OPENSSL_free(tmp); + M_ASN1_OCTET_STRING_print(out, id->user); + } + return 1; +} + +#ifdef SXNET_TEST + +/* + * NBB: this is used for testing only. It should *not* be used for anything + * else because it will just take static IDs from the configuration file and + * they should really be separate values for each user. + */ + +static SXNET *sxnet_v2i(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *nval) +{ + CONF_VALUE *cnf; + SXNET *sx = NULL; + size_t i; + for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { + cnf = sk_CONF_VALUE_value(nval, i); + if (!SXNET_add_id_asc(&sx, cnf->name, cnf->value, -1)) + return NULL; + } + return sx; +} + +#endif + +/* Strong Extranet utility functions */ + +/* Add an id given the zone as an ASCII number */ + +int SXNET_add_id_asc(SXNET **psx, char *zone, char *user, int userlen) +{ + ASN1_INTEGER *izone = NULL; + if (!(izone = s2i_ASN1_INTEGER(NULL, zone))) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_ERROR_CONVERTING_ZONE); + return 0; + } + return SXNET_add_id_INTEGER(psx, izone, user, userlen); +} + +/* Add an id given the zone as an unsigned long */ + +int SXNET_add_id_ulong(SXNET **psx, unsigned long lzone, char *user, + int userlen) +{ + ASN1_INTEGER *izone = NULL; + if (!(izone = M_ASN1_INTEGER_new()) || !ASN1_INTEGER_set(izone, lzone)) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + M_ASN1_INTEGER_free(izone); + return 0; + } + return SXNET_add_id_INTEGER(psx, izone, user, userlen); + +} + +/* + * Add an id given the zone as an ASN1_INTEGER. Note this version uses the + * passed integer and doesn't make a copy so don't free it up afterwards. + */ + +int SXNET_add_id_INTEGER(SXNET **psx, ASN1_INTEGER *zone, char *user, + int userlen) +{ + SXNET *sx = NULL; + SXNETID *id = NULL; + if (!psx || !zone || !user) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_ARGUMENT); + return 0; + } + if (userlen == -1) + userlen = strlen(user); + if (userlen > 64) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_USER_TOO_LONG); + return 0; + } + if (!*psx) { + if (!(sx = SXNET_new())) + goto err; + if (!ASN1_INTEGER_set(sx->version, 0)) + goto err; + *psx = sx; + } else + sx = *psx; + if (SXNET_get_id_INTEGER(sx, zone)) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_DUPLICATE_ZONE_ID); + return 0; + } + + if (!(id = SXNETID_new())) + goto err; + if (userlen == -1) + userlen = strlen(user); + + if (!M_ASN1_OCTET_STRING_set(id->user, user, userlen)) + goto err; + if (!sk_SXNETID_push(sx->ids, id)) + goto err; + id->zone = zone; + return 1; + + err: + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + SXNETID_free(id); + SXNET_free(sx); + *psx = NULL; + return 0; +} + +ASN1_OCTET_STRING *SXNET_get_id_asc(SXNET *sx, char *zone) +{ + ASN1_INTEGER *izone = NULL; + ASN1_OCTET_STRING *oct; + if (!(izone = s2i_ASN1_INTEGER(NULL, zone))) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_ERROR_CONVERTING_ZONE); + return NULL; + } + oct = SXNET_get_id_INTEGER(sx, izone); + M_ASN1_INTEGER_free(izone); + return oct; +} + +ASN1_OCTET_STRING *SXNET_get_id_ulong(SXNET *sx, unsigned long lzone) +{ + ASN1_INTEGER *izone = NULL; + ASN1_OCTET_STRING *oct; + if (!(izone = M_ASN1_INTEGER_new()) || !ASN1_INTEGER_set(izone, lzone)) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + M_ASN1_INTEGER_free(izone); + return NULL; + } + oct = SXNET_get_id_INTEGER(sx, izone); + M_ASN1_INTEGER_free(izone); + return oct; +} + +ASN1_OCTET_STRING *SXNET_get_id_INTEGER(SXNET *sx, ASN1_INTEGER *zone) +{ + SXNETID *id; + size_t i; + for (i = 0; i < sk_SXNETID_num(sx->ids); i++) { + id = sk_SXNETID_value(sx->ids, i); + if (!M_ASN1_INTEGER_cmp(id->zone, zone)) + return id->user; + } + return NULL; +} + +IMPLEMENT_ASN1_SET_OF(SXNETID) diff --git a/external/boringssl/crypto/x509v3/v3_utl.c b/external/boringssl/crypto/x509v3/v3_utl.c new file mode 100644 index 0000000000..a238a20ec8 --- /dev/null +++ b/external/boringssl/crypto/x509v3/v3_utl.c @@ -0,0 +1,1327 @@ +/* v3_utl.c */ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project. + */ +/* ==================================================================== + * Copyright (c) 1999-2003 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* X509 v3 extension utilities */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "../conf/internal.h" + +static char *strip_spaces(char *name); +static int sk_strcmp(const OPENSSL_STRING *a, const OPENSSL_STRING *b); +static STACK_OF(OPENSSL_STRING) *get_email(X509_NAME *name, + GENERAL_NAMES *gens); +static void str_free(OPENSSL_STRING str); +static int append_ia5(STACK_OF(OPENSSL_STRING) **sk, ASN1_IA5STRING *email); + +static int ipv4_from_asc(unsigned char *v4, const char *in); +static int ipv6_from_asc(unsigned char *v6, const char *in); +static int ipv6_cb(const char *elem, int len, void *usr); +static int ipv6_hex(unsigned char *out, const char *in, int inlen); + +/* Add a CONF_VALUE name value pair to stack */ + +int X509V3_add_value(const char *name, const char *value, + STACK_OF(CONF_VALUE) **extlist) +{ + CONF_VALUE *vtmp = NULL; + char *tname = NULL, *tvalue = NULL; + if (name && !(tname = BUF_strdup(name))) + goto err; + if (value && !(tvalue = BUF_strdup(value))) + goto err; + if (!(vtmp = CONF_VALUE_new())) + goto err; + if (!*extlist && !(*extlist = sk_CONF_VALUE_new_null())) + goto err; + vtmp->section = NULL; + vtmp->name = tname; + vtmp->value = tvalue; + if (!sk_CONF_VALUE_push(*extlist, vtmp)) + goto err; + return 1; + err: + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + if (vtmp) + OPENSSL_free(vtmp); + if (tname) + OPENSSL_free(tname); + if (tvalue) + OPENSSL_free(tvalue); + return 0; +} + +int X509V3_add_value_uchar(const char *name, const unsigned char *value, + STACK_OF(CONF_VALUE) **extlist) +{ + return X509V3_add_value(name, (const char *)value, extlist); +} + +/* Free function for STACK_OF(CONF_VALUE) */ + +void X509V3_conf_free(CONF_VALUE *conf) +{ + if (!conf) + return; + if (conf->name) + OPENSSL_free(conf->name); + if (conf->value) + OPENSSL_free(conf->value); + if (conf->section) + OPENSSL_free(conf->section); + OPENSSL_free(conf); +} + +int X509V3_add_value_bool(const char *name, int asn1_bool, + STACK_OF(CONF_VALUE) **extlist) +{ + if (asn1_bool) + return X509V3_add_value(name, "TRUE", extlist); + return X509V3_add_value(name, "FALSE", extlist); +} + +int X509V3_add_value_bool_nf(char *name, int asn1_bool, + STACK_OF(CONF_VALUE) **extlist) +{ + if (asn1_bool) + return X509V3_add_value(name, "TRUE", extlist); + return 1; +} + +char *i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *method, ASN1_ENUMERATED *a) +{ + BIGNUM *bntmp = NULL; + char *strtmp = NULL; + if (!a) + return NULL; + if (!(bntmp = ASN1_ENUMERATED_to_BN(a, NULL)) || + !(strtmp = BN_bn2dec(bntmp))) + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + BN_free(bntmp); + return strtmp; +} + +char *i2s_ASN1_INTEGER(X509V3_EXT_METHOD *method, ASN1_INTEGER *a) +{ + BIGNUM *bntmp = NULL; + char *strtmp = NULL; + if (!a) + return NULL; + if (!(bntmp = ASN1_INTEGER_to_BN(a, NULL)) || + !(strtmp = BN_bn2dec(bntmp))) + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + BN_free(bntmp); + return strtmp; +} + +ASN1_INTEGER *s2i_ASN1_INTEGER(X509V3_EXT_METHOD *method, char *value) +{ + BIGNUM *bn = NULL; + ASN1_INTEGER *aint; + int isneg, ishex; + int ret; + if (!value) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_VALUE); + return 0; + } + bn = BN_new(); + if (value[0] == '-') { + value++; + isneg = 1; + } else + isneg = 0; + + if (value[0] == '0' && ((value[1] == 'x') || (value[1] == 'X'))) { + value += 2; + ishex = 1; + } else + ishex = 0; + + if (ishex) + ret = BN_hex2bn(&bn, value); + else + ret = BN_dec2bn(&bn, value); + + if (!ret || value[ret]) { + BN_free(bn); + OPENSSL_PUT_ERROR(X509V3, X509V3_R_BN_DEC2BN_ERROR); + return 0; + } + + if (isneg && BN_is_zero(bn)) + isneg = 0; + + aint = BN_to_ASN1_INTEGER(bn, NULL); + BN_free(bn); + if (!aint) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_BN_TO_ASN1_INTEGER_ERROR); + return 0; + } + if (isneg) + aint->type |= V_ASN1_NEG; + return aint; +} + +int X509V3_add_value_int(const char *name, ASN1_INTEGER *aint, + STACK_OF(CONF_VALUE) **extlist) +{ + char *strtmp; + int ret; + if (!aint) + return 1; + if (!(strtmp = i2s_ASN1_INTEGER(NULL, aint))) + return 0; + ret = X509V3_add_value(name, strtmp, extlist); + OPENSSL_free(strtmp); + return ret; +} + +int X509V3_get_value_bool(CONF_VALUE *value, int *asn1_bool) +{ + char *btmp; + if (!(btmp = value->value)) + goto err; + if (!strcmp(btmp, "TRUE") || !strcmp(btmp, "true") + || !strcmp(btmp, "Y") || !strcmp(btmp, "y") + || !strcmp(btmp, "YES") || !strcmp(btmp, "yes")) { + *asn1_bool = 0xff; + return 1; + } else if (!strcmp(btmp, "FALSE") || !strcmp(btmp, "false") + || !strcmp(btmp, "N") || !strcmp(btmp, "n") + || !strcmp(btmp, "NO") || !strcmp(btmp, "no")) { + *asn1_bool = 0; + return 1; + } + err: + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_BOOLEAN_STRING); + X509V3_conf_err(value); + return 0; +} + +int X509V3_get_value_int(CONF_VALUE *value, ASN1_INTEGER **aint) +{ + ASN1_INTEGER *itmp; + if (!(itmp = s2i_ASN1_INTEGER(NULL, value->value))) { + X509V3_conf_err(value); + return 0; + } + *aint = itmp; + return 1; +} + +#define HDR_NAME 1 +#define HDR_VALUE 2 + +/* + * #define DEBUG + */ + +STACK_OF(CONF_VALUE) *X509V3_parse_list(const char *line) +{ + char *p, *q, c; + char *ntmp, *vtmp; + STACK_OF(CONF_VALUE) *values = NULL; + char *linebuf; + int state; + /* We are going to modify the line so copy it first */ + linebuf = BUF_strdup(line); + if (linebuf == NULL) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + goto err; + } + state = HDR_NAME; + ntmp = NULL; + /* Go through all characters */ + for (p = linebuf, q = linebuf; (c = *p) && (c != '\r') && (c != '\n'); + p++) { + + switch (state) { + case HDR_NAME: + if (c == ':') { + state = HDR_VALUE; + *p = 0; + ntmp = strip_spaces(q); + if (!ntmp) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_NAME); + goto err; + } + q = p + 1; + } else if (c == ',') { + *p = 0; + ntmp = strip_spaces(q); + q = p + 1; +#if 0 + printf("%s\n", ntmp); +#endif + if (!ntmp) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_NAME); + goto err; + } + X509V3_add_value(ntmp, NULL, &values); + } + break; + + case HDR_VALUE: + if (c == ',') { + state = HDR_NAME; + *p = 0; + vtmp = strip_spaces(q); +#if 0 + printf("%s\n", ntmp); +#endif + if (!vtmp) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_VALUE); + goto err; + } + X509V3_add_value(ntmp, vtmp, &values); + ntmp = NULL; + q = p + 1; + } + + } + } + + if (state == HDR_VALUE) { + vtmp = strip_spaces(q); +#if 0 + printf("%s=%s\n", ntmp, vtmp); +#endif + if (!vtmp) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_VALUE); + goto err; + } + X509V3_add_value(ntmp, vtmp, &values); + } else { + ntmp = strip_spaces(q); +#if 0 + printf("%s\n", ntmp); +#endif + if (!ntmp) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_NAME); + goto err; + } + X509V3_add_value(ntmp, NULL, &values); + } + OPENSSL_free(linebuf); + return values; + + err: + OPENSSL_free(linebuf); + sk_CONF_VALUE_pop_free(values, X509V3_conf_free); + return NULL; + +} + +/* Delete leading and trailing spaces from a string */ +static char *strip_spaces(char *name) +{ + char *p, *q; + /* Skip over leading spaces */ + p = name; + while (*p && isspace((unsigned char)*p)) + p++; + if (!*p) + return NULL; + q = p + strlen(p) - 1; + while ((q != p) && isspace((unsigned char)*q)) + q--; + if (p != q) + q[1] = 0; + if (!*p) + return NULL; + return p; +} + +/* hex string utilities */ + +/* + * Given a buffer of length 'len' return a OPENSSL_malloc'ed string with its + * hex representation @@@ (Contents of buffer are always kept in ASCII, also + * on EBCDIC machines) + */ + +char *hex_to_string(const unsigned char *buffer, long len) +{ + char *tmp, *q; + const unsigned char *p; + int i; + static const char hexdig[] = "0123456789ABCDEF"; + if (!buffer || !len) + return NULL; + if (!(tmp = OPENSSL_malloc(len * 3 + 1))) { + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + return NULL; + } + q = tmp; + for (i = 0, p = buffer; i < len; i++, p++) { + *q++ = hexdig[(*p >> 4) & 0xf]; + *q++ = hexdig[*p & 0xf]; + *q++ = ':'; + } + q[-1] = 0; + + return tmp; +} + +/* + * Give a string of hex digits convert to a buffer + */ + +unsigned char *string_to_hex(const char *str, long *len) +{ + unsigned char *hexbuf, *q; + unsigned char ch, cl, *p; + if (!str) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_ARGUMENT); + return NULL; + } + if (!(hexbuf = OPENSSL_malloc(strlen(str) >> 1))) + goto err; + for (p = (unsigned char *)str, q = hexbuf; *p;) { + ch = *p++; + if (ch == ':') + continue; + cl = *p++; + if (!cl) { + OPENSSL_PUT_ERROR(X509V3, X509V3_R_ODD_NUMBER_OF_DIGITS); + OPENSSL_free(hexbuf); + return NULL; + } + if (isupper(ch)) + ch = tolower(ch); + if (isupper(cl)) + cl = tolower(cl); + + if ((ch >= '0') && (ch <= '9')) + ch -= '0'; + else if ((ch >= 'a') && (ch <= 'f')) + ch -= 'a' - 10; + else + goto badhex; + + if ((cl >= '0') && (cl <= '9')) + cl -= '0'; + else if ((cl >= 'a') && (cl <= 'f')) + cl -= 'a' - 10; + else + goto badhex; + + *q++ = (ch << 4) | cl; + } + + if (len) + *len = q - hexbuf; + + return hexbuf; + + err: + if (hexbuf) + OPENSSL_free(hexbuf); + OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); + return NULL; + + badhex: + OPENSSL_free(hexbuf); + OPENSSL_PUT_ERROR(X509V3, X509V3_R_ILLEGAL_HEX_DIGIT); + return NULL; + +} + +/* + * V2I name comparison function: returns zero if 'name' matches cmp or cmp.* + */ + +int name_cmp(const char *name, const char *cmp) +{ + int len, ret; + char c; + len = strlen(cmp); + if ((ret = strncmp(name, cmp, len))) + return ret; + c = name[len]; + if (!c || (c == '.')) + return 0; + return 1; +} + +static int sk_strcmp(const OPENSSL_STRING *a, const OPENSSL_STRING *b) +{ + return strcmp(*a, *b); +} + +STACK_OF(OPENSSL_STRING) *X509_get1_email(X509 *x) +{ + GENERAL_NAMES *gens; + STACK_OF(OPENSSL_STRING) *ret; + + gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL); + ret = get_email(X509_get_subject_name(x), gens); + sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); + return ret; +} + +STACK_OF(OPENSSL_STRING) *X509_get1_ocsp(X509 *x) +{ + AUTHORITY_INFO_ACCESS *info; + STACK_OF(OPENSSL_STRING) *ret = NULL; + size_t i; + + info = X509_get_ext_d2i(x, NID_info_access, NULL, NULL); + if (!info) + return NULL; + for (i = 0; i < sk_ACCESS_DESCRIPTION_num(info); i++) { + ACCESS_DESCRIPTION *ad = sk_ACCESS_DESCRIPTION_value(info, i); + if (OBJ_obj2nid(ad->method) == NID_ad_OCSP) { + if (ad->location->type == GEN_URI) { + if (!append_ia5 + (&ret, ad->location->d.uniformResourceIdentifier)) + break; + } + } + } + AUTHORITY_INFO_ACCESS_free(info); + return ret; +} + +STACK_OF(OPENSSL_STRING) *X509_REQ_get1_email(X509_REQ *x) +{ + GENERAL_NAMES *gens; + STACK_OF(X509_EXTENSION) *exts; + STACK_OF(OPENSSL_STRING) *ret; + + exts = X509_REQ_get_extensions(x); + gens = X509V3_get_d2i(exts, NID_subject_alt_name, NULL, NULL); + ret = get_email(X509_REQ_get_subject_name(x), gens); + sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); + sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); + return ret; +} + +static STACK_OF(OPENSSL_STRING) *get_email(X509_NAME *name, + GENERAL_NAMES *gens) +{ + STACK_OF(OPENSSL_STRING) *ret = NULL; + X509_NAME_ENTRY *ne; + ASN1_IA5STRING *email; + GENERAL_NAME *gen; + int i; + size_t j; + /* Now add any email address(es) to STACK */ + i = -1; + /* First supplied X509_NAME */ + while ((i = X509_NAME_get_index_by_NID(name, + NID_pkcs9_emailAddress, i)) >= 0) { + ne = X509_NAME_get_entry(name, i); + email = X509_NAME_ENTRY_get_data(ne); + if (!append_ia5(&ret, email)) + return NULL; + } + for (j = 0; j < sk_GENERAL_NAME_num(gens); j++) { + gen = sk_GENERAL_NAME_value(gens, j); + if (gen->type != GEN_EMAIL) + continue; + if (!append_ia5(&ret, gen->d.ia5)) + return NULL; + } + return ret; +} + +static void str_free(OPENSSL_STRING str) +{ + OPENSSL_free(str); +} + +static int append_ia5(STACK_OF(OPENSSL_STRING) **sk, ASN1_IA5STRING *email) +{ + char *emtmp; + /* First some sanity checks */ + if (email->type != V_ASN1_IA5STRING) + return 1; + if (!email->data || !email->length) + return 1; + if (!*sk) + *sk = sk_OPENSSL_STRING_new(sk_strcmp); + if (!*sk) + return 0; + /* Don't add duplicates */ + if (sk_OPENSSL_STRING_find(*sk, NULL, (char *)email->data)) + return 1; + emtmp = BUF_strdup((char *)email->data); + if (!emtmp || !sk_OPENSSL_STRING_push(*sk, emtmp)) { + X509_email_free(*sk); + *sk = NULL; + return 0; + } + return 1; +} + +void X509_email_free(STACK_OF(OPENSSL_STRING) *sk) +{ + sk_OPENSSL_STRING_pop_free(sk, str_free); +} + +typedef int (*equal_fn) (const unsigned char *pattern, size_t pattern_len, + const unsigned char *subject, size_t subject_len, + unsigned int flags); + +/* Skip pattern prefix to match "wildcard" subject */ +static void skip_prefix(const unsigned char **p, size_t *plen, + const unsigned char *subject, size_t subject_len, + unsigned int flags) +{ + const unsigned char *pattern = *p; + size_t pattern_len = *plen; + + /* + * If subject starts with a leading '.' followed by more octets, and + * pattern is longer, compare just an equal-length suffix with the + * full subject (starting at the '.'), provided the prefix contains + * no NULs. + */ + if ((flags & _X509_CHECK_FLAG_DOT_SUBDOMAINS) == 0) + return; + + while (pattern_len > subject_len && *pattern) { + if ((flags & X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS) && + *pattern == '.') + break; + ++pattern; + --pattern_len; + } + + /* Skip if entire prefix acceptable */ + if (pattern_len == subject_len) { + *p = pattern; + *plen = pattern_len; + } +} + +/* Compare while ASCII ignoring case. */ +static int equal_nocase(const unsigned char *pattern, size_t pattern_len, + const unsigned char *subject, size_t subject_len, + unsigned int flags) +{ + skip_prefix(&pattern, &pattern_len, subject, subject_len, flags); + if (pattern_len != subject_len) + return 0; + while (pattern_len) { + unsigned char l = *pattern; + unsigned char r = *subject; + /* The pattern must not contain NUL characters. */ + if (l == 0) + return 0; + if (l != r) { + if ('A' <= l && l <= 'Z') + l = (l - 'A') + 'a'; + if ('A' <= r && r <= 'Z') + r = (r - 'A') + 'a'; + if (l != r) + return 0; + } + ++pattern; + ++subject; + --pattern_len; + } + return 1; +} + +/* Compare using memcmp. */ +static int equal_case(const unsigned char *pattern, size_t pattern_len, + const unsigned char *subject, size_t subject_len, + unsigned int flags) +{ + skip_prefix(&pattern, &pattern_len, subject, subject_len, flags); + if (pattern_len != subject_len) + return 0; + return !memcmp(pattern, subject, pattern_len); +} + +/* + * RFC 5280, section 7.5, requires that only the domain is compared in a + * case-insensitive manner. + */ +static int equal_email(const unsigned char *a, size_t a_len, + const unsigned char *b, size_t b_len, + unsigned int unused_flags) +{ + size_t i = a_len; + if (a_len != b_len) + return 0; + /* + * We search backwards for the '@' character, so that we do not have to + * deal with quoted local-parts. The domain part is compared in a + * case-insensitive manner. + */ + while (i > 0) { + --i; + if (a[i] == '@' || b[i] == '@') { + if (!equal_nocase(a + i, a_len - i, b + i, a_len - i, 0)) + return 0; + break; + } + } + if (i == 0) + i = a_len; + return equal_case(a, i, b, i, 0); +} + +/* + * Compare the prefix and suffix with the subject, and check that the + * characters in-between are valid. + */ +static int wildcard_match(const unsigned char *prefix, size_t prefix_len, + const unsigned char *suffix, size_t suffix_len, + const unsigned char *subject, size_t subject_len, + unsigned int flags) +{ + const unsigned char *wildcard_start; + const unsigned char *wildcard_end; + const unsigned char *p; + int allow_multi = 0; + int allow_idna = 0; + + if (subject_len < prefix_len + suffix_len) + return 0; + if (!equal_nocase(prefix, prefix_len, subject, prefix_len, flags)) + return 0; + wildcard_start = subject + prefix_len; + wildcard_end = subject + (subject_len - suffix_len); + if (!equal_nocase(wildcard_end, suffix_len, suffix, suffix_len, flags)) + return 0; + /* + * If the wildcard makes up the entire first label, it must match at + * least one character. + */ + if (prefix_len == 0 && *suffix == '.') { + if (wildcard_start == wildcard_end) + return 0; + allow_idna = 1; + if (flags & X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS) + allow_multi = 1; + } + /* IDNA labels cannot match partial wildcards */ + if (!allow_idna && + subject_len >= 4 + && OPENSSL_strncasecmp((char *)subject, "xn--", 4) == 0) + return 0; + /* The wildcard may match a literal '*' */ + if (wildcard_end == wildcard_start + 1 && *wildcard_start == '*') + return 1; + /* + * Check that the part matched by the wildcard contains only + * permitted characters and only matches a single label unless + * allow_multi is set. + */ + for (p = wildcard_start; p != wildcard_end; ++p) + if (!(('0' <= *p && *p <= '9') || + ('A' <= *p && *p <= 'Z') || + ('a' <= *p && *p <= 'z') || + *p == '-' || (allow_multi && *p == '.'))) + return 0; + return 1; +} + +#define LABEL_START (1 << 0) +#define LABEL_END (1 << 1) +#define LABEL_HYPHEN (1 << 2) +#define LABEL_IDNA (1 << 3) + +static const unsigned char *valid_star(const unsigned char *p, size_t len, + unsigned int flags) +{ + const unsigned char *star = 0; + size_t i; + int state = LABEL_START; + int dots = 0; + for (i = 0; i < len; ++i) { + /* + * Locate first and only legal wildcard, either at the start + * or end of a non-IDNA first and not final label. + */ + if (p[i] == '*') { + int atstart = (state & LABEL_START); + int atend = (i == len - 1 || p[i + 1] == '.'); + /* + * At most one wildcard per pattern. + * No wildcards in IDNA labels. + * No wildcards after the first label. + */ + if (star != NULL || (state & LABEL_IDNA) != 0 || dots) + return NULL; + /* Only full-label '*.example.com' wildcards? */ + if ((flags & X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS) + && (!atstart || !atend)) + return NULL; + /* No 'foo*bar' wildcards */ + if (!atstart && !atend) + return NULL; + star = &p[i]; + state &= ~LABEL_START; + } else if ((state & LABEL_START) != 0) { + /* + * At the start of a label, skip any "xn--" and + * remain in the LABEL_START state, but set the + * IDNA label state + */ + if ((state & LABEL_IDNA) == 0 && len - i >= 4 + && OPENSSL_strncasecmp((char *)&p[i], "xn--", 4) == 0) { + i += 3; + state |= LABEL_IDNA; + continue; + } + /* Labels must start with a letter or digit */ + state &= ~LABEL_START; + if (('a' <= p[i] && p[i] <= 'z') + || ('A' <= p[i] && p[i] <= 'Z') + || ('0' <= p[i] && p[i] <= '9')) + continue; + return NULL; + } else if (('a' <= p[i] && p[i] <= 'z') + || ('A' <= p[i] && p[i] <= 'Z') + || ('0' <= p[i] && p[i] <= '9')) { + state &= LABEL_IDNA; + continue; + } else if (p[i] == '.') { + if (state & (LABEL_HYPHEN | LABEL_START)) + return NULL; + state = LABEL_START; + ++dots; + } else if (p[i] == '-') { + /* no domain/subdomain starts with '-' */ + if ((state & LABEL_START) != 0) + return NULL; + state |= LABEL_HYPHEN; + } else + return NULL; + } + + /* + * The final label must not end in a hyphen or ".", and + * there must be at least two dots after the star. + */ + if ((state & (LABEL_START | LABEL_HYPHEN)) != 0 || dots < 2) + return NULL; + return star; +} + +/* Compare using wildcards. */ +static int equal_wildcard(const unsigned char *pattern, size_t pattern_len, + const unsigned char *subject, size_t subject_len, + unsigned int flags) +{ + const unsigned char *star = NULL; + + /* + * Subject names starting with '.' can only match a wildcard pattern + * via a subject sub-domain pattern suffix match. + */ + if (!(subject_len > 1 && subject[0] == '.')) + star = valid_star(pattern, pattern_len, flags); + if (star == NULL) + return equal_nocase(pattern, pattern_len, + subject, subject_len, flags); + return wildcard_match(pattern, star - pattern, + star + 1, (pattern + pattern_len) - star - 1, + subject, subject_len, flags); +} + +/* + * Compare an ASN1_STRING to a supplied string. If they match return 1. If + * cmp_type > 0 only compare if string matches the type, otherwise convert it + * to UTF8. + */ + +static int do_check_string(ASN1_STRING *a, int cmp_type, equal_fn equal, + unsigned int flags, const char *b, size_t blen, + char **peername) +{ + int rv = 0; + + if (!a->data || !a->length) + return 0; + if (cmp_type > 0) { + if (cmp_type != a->type) + return 0; + if (cmp_type == V_ASN1_IA5STRING) + rv = equal(a->data, a->length, (unsigned char *)b, blen, flags); + else if (a->length == (int)blen && !memcmp(a->data, b, blen)) + rv = 1; + if (rv > 0 && peername) + *peername = BUF_strndup((char *)a->data, a->length); + } else { + int astrlen; + unsigned char *astr; + astrlen = ASN1_STRING_to_UTF8(&astr, a); + if (astrlen < 0) + return -1; + rv = equal(astr, astrlen, (unsigned char *)b, blen, flags); + if (rv > 0 && peername) + *peername = BUF_strndup((char *)astr, astrlen); + OPENSSL_free(astr); + } + return rv; +} + +static int do_x509_check(X509 *x, const char *chk, size_t chklen, + unsigned int flags, int check_type, char **peername) +{ + GENERAL_NAMES *gens = NULL; + X509_NAME *name = NULL; + size_t i; + int j; + int cnid = NID_undef; + int alt_type; + int san_present = 0; + int rv = 0; + equal_fn equal; + + /* See below, this flag is internal-only */ + flags &= ~_X509_CHECK_FLAG_DOT_SUBDOMAINS; + if (check_type == GEN_EMAIL) { + cnid = NID_pkcs9_emailAddress; + alt_type = V_ASN1_IA5STRING; + equal = equal_email; + } else if (check_type == GEN_DNS) { + cnid = NID_commonName; + /* Implicit client-side DNS sub-domain pattern */ + if (chklen > 1 && chk[0] == '.') + flags |= _X509_CHECK_FLAG_DOT_SUBDOMAINS; + alt_type = V_ASN1_IA5STRING; + if (flags & X509_CHECK_FLAG_NO_WILDCARDS) + equal = equal_nocase; + else + equal = equal_wildcard; + } else { + alt_type = V_ASN1_OCTET_STRING; + equal = equal_case; + } + + gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL); + if (gens) { + for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { + GENERAL_NAME *gen; + ASN1_STRING *cstr; + gen = sk_GENERAL_NAME_value(gens, i); + if (gen->type != check_type) + continue; + san_present = 1; + if (check_type == GEN_EMAIL) + cstr = gen->d.rfc822Name; + else if (check_type == GEN_DNS) + cstr = gen->d.dNSName; + else + cstr = gen->d.iPAddress; + /* Positive on success, negative on error! */ + if ((rv = do_check_string(cstr, alt_type, equal, flags, + chk, chklen, peername)) != 0) + break; + } + GENERAL_NAMES_free(gens); + if (rv != 0) + return rv; + if (cnid == NID_undef + || (san_present + && !(flags & X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT))) + return 0; + } + + /* We're done if CN-ID is not pertinent */ + if (cnid == NID_undef) + return 0; + + j = -1; + name = X509_get_subject_name(x); + while ((j = X509_NAME_get_index_by_NID(name, cnid, j)) >= 0) { + X509_NAME_ENTRY *ne; + ASN1_STRING *str; + ne = X509_NAME_get_entry(name, j); + str = X509_NAME_ENTRY_get_data(ne); + /* Positive on success, negative on error! */ + if ((rv = do_check_string(str, -1, equal, flags, + chk, chklen, peername)) != 0) + return rv; + } + return 0; +} + +int X509_check_host(X509 *x, const char *chk, size_t chklen, + unsigned int flags, char **peername) +{ + if (chk == NULL) + return -2; + if (memchr(chk, '\0', chklen)) + return -2; + return do_x509_check(x, chk, chklen, flags, GEN_DNS, peername); +} + +int X509_check_email(X509 *x, const char *chk, size_t chklen, + unsigned int flags) +{ + if (chk == NULL) + return -2; + if (memchr(chk, '\0', chklen)) + return -2; + return do_x509_check(x, chk, chklen, flags, GEN_EMAIL, NULL); +} + +int X509_check_ip(X509 *x, const unsigned char *chk, size_t chklen, + unsigned int flags) +{ + if (chk == NULL) + return -2; + return do_x509_check(x, (char *)chk, chklen, flags, GEN_IPADD, NULL); +} + +int X509_check_ip_asc(X509 *x, const char *ipasc, unsigned int flags) +{ + unsigned char ipout[16]; + size_t iplen; + + if (ipasc == NULL) + return -2; + iplen = (size_t)a2i_ipadd(ipout, ipasc); + if (iplen == 0) + return -2; + return do_x509_check(x, (char *)ipout, iplen, flags, GEN_IPADD, NULL); +} + +/* + * Convert IP addresses both IPv4 and IPv6 into an OCTET STRING compatible + * with RFC3280. + */ + +ASN1_OCTET_STRING *a2i_IPADDRESS(const char *ipasc) +{ + unsigned char ipout[16]; + ASN1_OCTET_STRING *ret; + int iplen; + + /* If string contains a ':' assume IPv6 */ + + iplen = a2i_ipadd(ipout, ipasc); + + if (!iplen) + return NULL; + + ret = ASN1_OCTET_STRING_new(); + if (!ret) + return NULL; + if (!ASN1_OCTET_STRING_set(ret, ipout, iplen)) { + ASN1_OCTET_STRING_free(ret); + return NULL; + } + return ret; +} + +ASN1_OCTET_STRING *a2i_IPADDRESS_NC(const char *ipasc) +{ + ASN1_OCTET_STRING *ret = NULL; + unsigned char ipout[32]; + char *iptmp = NULL, *p; + int iplen1, iplen2; + p = strchr(ipasc, '/'); + if (!p) + return NULL; + iptmp = BUF_strdup(ipasc); + if (!iptmp) + return NULL; + p = iptmp + (p - ipasc); + *p++ = 0; + + iplen1 = a2i_ipadd(ipout, iptmp); + + if (!iplen1) + goto err; + + iplen2 = a2i_ipadd(ipout + iplen1, p); + + OPENSSL_free(iptmp); + iptmp = NULL; + + if (!iplen2 || (iplen1 != iplen2)) + goto err; + + ret = ASN1_OCTET_STRING_new(); + if (!ret) + goto err; + if (!ASN1_OCTET_STRING_set(ret, ipout, iplen1 + iplen2)) + goto err; + + return ret; + + err: + if (iptmp) + OPENSSL_free(iptmp); + if (ret) + ASN1_OCTET_STRING_free(ret); + return NULL; +} + +int a2i_ipadd(unsigned char *ipout, const char *ipasc) +{ + /* If string contains a ':' assume IPv6 */ + + if (strchr(ipasc, ':')) { + if (!ipv6_from_asc(ipout, ipasc)) + return 0; + return 16; + } else { + if (!ipv4_from_asc(ipout, ipasc)) + return 0; + return 4; + } +} + +static int ipv4_from_asc(unsigned char *v4, const char *in) +{ + int a0, a1, a2, a3; + if (sscanf(in, "%d.%d.%d.%d", &a0, &a1, &a2, &a3) != 4) + return 0; + if ((a0 < 0) || (a0 > 255) || (a1 < 0) || (a1 > 255) + || (a2 < 0) || (a2 > 255) || (a3 < 0) || (a3 > 255)) + return 0; + v4[0] = a0; + v4[1] = a1; + v4[2] = a2; + v4[3] = a3; + return 1; +} + +typedef struct { + /* Temporary store for IPV6 output */ + unsigned char tmp[16]; + /* Total number of bytes in tmp */ + int total; + /* The position of a zero (corresponding to '::') */ + int zero_pos; + /* Number of zeroes */ + int zero_cnt; +} IPV6_STAT; + +static int ipv6_from_asc(unsigned char *v6, const char *in) +{ + IPV6_STAT v6stat; + v6stat.total = 0; + v6stat.zero_pos = -1; + v6stat.zero_cnt = 0; + /* + * Treat the IPv6 representation as a list of values separated by ':'. + * The presence of a '::' will parse as one, two or three zero length + * elements. + */ + if (!CONF_parse_list(in, ':', 0, ipv6_cb, &v6stat)) + return 0; + + /* Now for some sanity checks */ + + if (v6stat.zero_pos == -1) { + /* If no '::' must have exactly 16 bytes */ + if (v6stat.total != 16) + return 0; + } else { + /* If '::' must have less than 16 bytes */ + if (v6stat.total == 16) + return 0; + /* More than three zeroes is an error */ + if (v6stat.zero_cnt > 3) + return 0; + /* Can only have three zeroes if nothing else present */ + else if (v6stat.zero_cnt == 3) { + if (v6stat.total > 0) + return 0; + } + /* Can only have two zeroes if at start or end */ + else if (v6stat.zero_cnt == 2) { + if ((v6stat.zero_pos != 0) + && (v6stat.zero_pos != v6stat.total)) + return 0; + } else + /* Can only have one zero if *not* start or end */ + { + if ((v6stat.zero_pos == 0) + || (v6stat.zero_pos == v6stat.total)) + return 0; + } + } + + /* Format result */ + + if (v6stat.zero_pos >= 0) { + /* Copy initial part */ + memcpy(v6, v6stat.tmp, v6stat.zero_pos); + /* Zero middle */ + memset(v6 + v6stat.zero_pos, 0, 16 - v6stat.total); + /* Copy final part */ + if (v6stat.total != v6stat.zero_pos) + memcpy(v6 + v6stat.zero_pos + 16 - v6stat.total, + v6stat.tmp + v6stat.zero_pos, + v6stat.total - v6stat.zero_pos); + } else + memcpy(v6, v6stat.tmp, 16); + + return 1; +} + +static int ipv6_cb(const char *elem, int len, void *usr) +{ + IPV6_STAT *s = usr; + /* Error if 16 bytes written */ + if (s->total == 16) + return 0; + if (len == 0) { + /* Zero length element, corresponds to '::' */ + if (s->zero_pos == -1) + s->zero_pos = s->total; + /* If we've already got a :: its an error */ + else if (s->zero_pos != s->total) + return 0; + s->zero_cnt++; + } else { + /* If more than 4 characters could be final a.b.c.d form */ + if (len > 4) { + /* Need at least 4 bytes left */ + if (s->total > 12) + return 0; + /* Must be end of string */ + if (elem[len]) + return 0; + if (!ipv4_from_asc(s->tmp + s->total, elem)) + return 0; + s->total += 4; + } else { + if (!ipv6_hex(s->tmp + s->total, elem, len)) + return 0; + s->total += 2; + } + } + return 1; +} + +/* + * Convert a string of up to 4 hex digits into the corresponding IPv6 form. + */ + +static int ipv6_hex(unsigned char *out, const char *in, int inlen) +{ + unsigned char c; + unsigned int num = 0; + if (inlen > 4) + return 0; + while (inlen--) { + c = *in++; + num <<= 4; + if ((c >= '0') && (c <= '9')) + num |= c - '0'; + else if ((c >= 'A') && (c <= 'F')) + num |= c - 'A' + 10; + else if ((c >= 'a') && (c <= 'f')) + num |= c - 'a' + 10; + else + return 0; + } + out[0] = num >> 8; + out[1] = num & 0xff; + return 1; +} + +int X509V3_NAME_from_section(X509_NAME *nm, STACK_OF (CONF_VALUE) * dn_sk, + unsigned long chtype) +{ + CONF_VALUE *v; + int mval; + size_t i; + char *p, *type; + if (!nm) + return 0; + + for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++) { + v = sk_CONF_VALUE_value(dn_sk, i); + type = v->name; + /* + * Skip past any leading X. X: X, etc to allow for multiple instances + */ + for (p = type; *p; p++) + if ((*p == ':') || (*p == ',') || (*p == '.')) { + p++; + if (*p) + type = p; + break; + } + if (*type == '+') { + mval = -1; + type++; + } else + mval = 0; + if (!X509_NAME_add_entry_by_txt(nm, type, chtype, + (unsigned char *)v->value, -1, -1, + mval)) + return 0; + + } + return 1; +} diff --git a/external/boringssl/crypto/x509v3/v3name_test.c b/external/boringssl/crypto/x509v3/v3name_test.c new file mode 100644 index 0000000000..dadf488f53 --- /dev/null +++ b/external/boringssl/crypto/x509v3/v3name_test.c @@ -0,0 +1,410 @@ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project + * 1999. + */ +/* ==================================================================== + * Copyright (c) 1999-2004 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include +#include + +#include +#include +#include +#include + +static const char *const names[] = { + "a", "b", ".", "*", "@", + ".a", "a.", ".b", "b.", ".*", "*.", "*@", "@*", "a@", "@a", "b@", "..", + "-example.com", "example-.com", + "@@", "**", "*.com", "*com", "*.*.com", "*com", "com*", "*example.com", + "*@example.com", "test@*.example.com", "example.com", "www.example.com", + "test.www.example.com", "*.example.com", "*.www.example.com", + "test.*.example.com", "www.*.com", + ".www.example.com", "*www.example.com", + "example.net", "xn--rger-koa.example.com", + "*.xn--rger-koa.example.com", "www.xn--rger-koa.example.com", + "*.good--example.com", "www.good--example.com", + "*.xn--bar.com", "xn--foo.xn--bar.com", + "a.example.com", "b.example.com", + "postmaster@example.com", "Postmaster@example.com", + "postmaster@EXAMPLE.COM", + NULL +}; + +static const char *const exceptions[] = { + "set CN: host: [*.example.com] matches [a.example.com]", + "set CN: host: [*.example.com] matches [b.example.com]", + "set CN: host: [*.example.com] matches [www.example.com]", + "set CN: host: [*.example.com] matches [xn--rger-koa.example.com]", + "set CN: host: [*.www.example.com] matches [test.www.example.com]", + "set CN: host: [*.www.example.com] matches [.www.example.com]", + "set CN: host: [*www.example.com] matches [www.example.com]", + "set CN: host: [test.www.example.com] matches [.www.example.com]", + "set CN: host: [*.xn--rger-koa.example.com] matches [www.xn--rger-koa.example.com]", + "set CN: host: [*.xn--bar.com] matches [xn--foo.xn--bar.com]", + "set CN: host: [*.good--example.com] matches [www.good--example.com]", + "set CN: host-no-wildcards: [*.www.example.com] matches [.www.example.com]", + "set CN: host-no-wildcards: [test.www.example.com] matches [.www.example.com]", + "set emailAddress: email: [postmaster@example.com] does not match [Postmaster@example.com]", + "set emailAddress: email: [postmaster@EXAMPLE.COM] does not match [Postmaster@example.com]", + "set emailAddress: email: [Postmaster@example.com] does not match [postmaster@example.com]", + "set emailAddress: email: [Postmaster@example.com] does not match [postmaster@EXAMPLE.COM]", + "set dnsName: host: [*.example.com] matches [www.example.com]", + "set dnsName: host: [*.example.com] matches [a.example.com]", + "set dnsName: host: [*.example.com] matches [b.example.com]", + "set dnsName: host: [*.example.com] matches [xn--rger-koa.example.com]", + "set dnsName: host: [*.www.example.com] matches [test.www.example.com]", + "set dnsName: host-no-wildcards: [*.www.example.com] matches [.www.example.com]", + "set dnsName: host-no-wildcards: [test.www.example.com] matches [.www.example.com]", + "set dnsName: host: [*.www.example.com] matches [.www.example.com]", + "set dnsName: host: [*www.example.com] matches [www.example.com]", + "set dnsName: host: [test.www.example.com] matches [.www.example.com]", + "set dnsName: host: [*.xn--rger-koa.example.com] matches [www.xn--rger-koa.example.com]", + "set dnsName: host: [*.xn--bar.com] matches [xn--foo.xn--bar.com]", + "set dnsName: host: [*.good--example.com] matches [www.good--example.com]", + "set rfc822Name: email: [postmaster@example.com] does not match [Postmaster@example.com]", + "set rfc822Name: email: [Postmaster@example.com] does not match [postmaster@example.com]", + "set rfc822Name: email: [Postmaster@example.com] does not match [postmaster@EXAMPLE.COM]", + "set rfc822Name: email: [postmaster@EXAMPLE.COM] does not match [Postmaster@example.com]", + NULL +}; + +static int is_exception(const char *msg) +{ + const char *const *p; + for (p = exceptions; *p; ++p) + if (strcmp(msg, *p) == 0) + return 1; + return 0; +} + +static int set_cn(X509 *crt, ...) +{ + int ret = 0; + X509_NAME *n = NULL; + va_list ap; + va_start(ap, crt); + n = X509_NAME_new(); + if (n == NULL) + goto out; + while (1) { + int nid; + const char *name; + nid = va_arg(ap, int); + if (nid == 0) + break; + name = va_arg(ap, const char *); + if (!X509_NAME_add_entry_by_NID(n, nid, MBSTRING_ASC, + (unsigned char *)name, -1, -1, 1)) + goto out; + } + if (!X509_set_subject_name(crt, n)) + goto out; + ret = 1; + out: + X509_NAME_free(n); + va_end(ap); + return ret; +} + +/* + * int X509_add_ext(X509 *x, X509_EXTENSION *ex, int loc); X509_EXTENSION + * *X509_EXTENSION_create_by_NID(X509_EXTENSION **ex, int nid, int crit, + * ASN1_OCTET_STRING *data); int X509_add_ext(X509 *x, X509_EXTENSION *ex, + * int loc); + */ + +static int set_altname(X509 *crt, ...) +{ + int ret = 0; + GENERAL_NAMES *gens = NULL; + GENERAL_NAME *gen = NULL; + ASN1_IA5STRING *ia5 = NULL; + va_list ap; + va_start(ap, crt); + gens = sk_GENERAL_NAME_new_null(); + if (gens == NULL) + goto out; + while (1) { + int type; + const char *name; + type = va_arg(ap, int); + if (type == 0) + break; + name = va_arg(ap, const char *); + + gen = GENERAL_NAME_new(); + if (gen == NULL) + goto out; + ia5 = ASN1_IA5STRING_new(); + if (ia5 == NULL) + goto out; + if (!ASN1_STRING_set(ia5, name, -1)) + goto out; + switch (type) { + case GEN_EMAIL: + case GEN_DNS: + GENERAL_NAME_set0_value(gen, type, ia5); + ia5 = NULL; + break; + default: + abort(); + } + sk_GENERAL_NAME_push(gens, gen); + gen = NULL; + } + if (!X509_add1_ext_i2d(crt, NID_subject_alt_name, gens, 0, 0)) + goto out; + ret = 1; + out: + ASN1_IA5STRING_free(ia5); + GENERAL_NAME_free(gen); + GENERAL_NAMES_free(gens); + va_end(ap); + return ret; +} + +static int set_cn1(X509 *crt, const char *name) +{ + return set_cn(crt, NID_commonName, name, 0); +} + +static int set_cn_and_email(X509 *crt, const char *name) +{ + return set_cn(crt, NID_commonName, name, + NID_pkcs9_emailAddress, "dummy@example.com", 0); +} + +static int set_cn2(X509 *crt, const char *name) +{ + return set_cn(crt, NID_commonName, "dummy value", + NID_commonName, name, 0); +} + +static int set_cn3(X509 *crt, const char *name) +{ + return set_cn(crt, NID_commonName, name, + NID_commonName, "dummy value", 0); +} + +static int set_email1(X509 *crt, const char *name) +{ + return set_cn(crt, NID_pkcs9_emailAddress, name, 0); +} + +static int set_email2(X509 *crt, const char *name) +{ + return set_cn(crt, NID_pkcs9_emailAddress, "dummy@example.com", + NID_pkcs9_emailAddress, name, 0); +} + +static int set_email3(X509 *crt, const char *name) +{ + return set_cn(crt, NID_pkcs9_emailAddress, name, + NID_pkcs9_emailAddress, "dummy@example.com", 0); +} + +static int set_email_and_cn(X509 *crt, const char *name) +{ + return set_cn(crt, NID_pkcs9_emailAddress, name, + NID_commonName, "www.example.org", 0); +} + +static int set_altname_dns(X509 *crt, const char *name) +{ + return set_altname(crt, GEN_DNS, name, 0); +} + +static int set_altname_email(X509 *crt, const char *name) +{ + return set_altname(crt, GEN_EMAIL, name, 0); +} + +struct set_name_fn { + int (*fn) (X509 *, const char *); + const char *name; + int host; + int email; +}; + +static const struct set_name_fn name_fns[] = { + {set_cn1, "set CN", 1, 0}, + {set_cn2, "set CN", 1, 0}, + {set_cn3, "set CN", 1, 0}, + {set_cn_and_email, "set CN", 1, 0}, + {set_email1, "set emailAddress", 0, 1}, + {set_email2, "set emailAddress", 0, 1}, + {set_email3, "set emailAddress", 0, 1}, + {set_email_and_cn, "set emailAddress", 0, 1}, + {set_altname_dns, "set dnsName", 1, 0}, + {set_altname_email, "set rfc822Name", 0, 1}, + {NULL, NULL, 0, 0}, +}; + +static X509 *make_cert(void) +{ + X509 *ret = NULL; + X509 *crt = NULL; + X509_NAME *issuer = NULL; + crt = X509_new(); + if (crt == NULL) + goto out; + if (!X509_set_version(crt, 3)) + goto out; + ret = crt; + crt = NULL; + out: + X509_NAME_free(issuer); + return ret; +} + +static int errors; + +static void check_message(const struct set_name_fn *fn, const char *op, + const char *nameincert, int match, const char *name) +{ + char msg[1024]; + if (match < 0) + return; + BIO_snprintf(msg, sizeof(msg), "%s: %s: [%s] %s [%s]", + fn->name, op, nameincert, + match ? "matches" : "does not match", name); + if (is_exception(msg)) + return; + puts(msg); + ++errors; +} + +static void run_cert(X509 *crt, const char *nameincert, + const struct set_name_fn *fn) +{ + const char *const *pname = names; + while (*pname) { + int samename = OPENSSL_strcasecmp(nameincert, *pname) == 0; + size_t namelen = strlen(*pname); + char *name = malloc(namelen); + int match, ret; + memcpy(name, *pname, namelen); + + ret = X509_check_host(crt, name, namelen, 0, NULL); + match = -1; + if (ret < 0) { + fprintf(stderr, "internal error in X509_check_host"); + ++errors; + } else if (fn->host) { + if (ret == 1 && !samename) + match = 1; + if (ret == 0 && samename) + match = 0; + } else if (ret == 1) + match = 1; + check_message(fn, "host", nameincert, match, *pname); + + ret = X509_check_host(crt, name, namelen, + X509_CHECK_FLAG_NO_WILDCARDS, NULL); + match = -1; + if (ret < 0) { + fprintf(stderr, "internal error in X509_check_host"); + ++errors; + } else if (fn->host) { + if (ret == 1 && !samename) + match = 1; + if (ret == 0 && samename) + match = 0; + } else if (ret == 1) + match = 1; + check_message(fn, "host-no-wildcards", nameincert, match, *pname); + + ret = X509_check_email(crt, name, namelen, 0); + match = -1; + if (fn->email) { + if (ret && !samename) + match = 1; + if (!ret && samename && strchr(nameincert, '@') != NULL) + match = 0; + } else if (ret) + match = 1; + check_message(fn, "email", nameincert, match, *pname); + ++pname; + free(name); + } +} + +int main(void) +{ + CRYPTO_library_init(); + + const struct set_name_fn *pfn = name_fns; + while (pfn->name) { + const char *const *pname = names; + while (*pname) { + X509 *crt = make_cert(); + if (crt == NULL) { + fprintf(stderr, "make_cert failed\n"); + return 1; + } + if (!pfn->fn(crt, *pname)) { + fprintf(stderr, "X509 name setting failed\n"); + return 1; + } + run_cert(crt, *pname, pfn); + X509_free(crt); + ++pname; + } + ++pfn; + } + if (errors == 0) { + printf("PASS\n"); + } + return errors > 0 ? 1 : 0; +} diff --git a/external/boringssl/decrepit/CMakeLists.txt b/external/boringssl/decrepit/CMakeLists.txt new file mode 100644 index 0000000000..6a5462c2b6 --- /dev/null +++ b/external/boringssl/decrepit/CMakeLists.txt @@ -0,0 +1,35 @@ +add_subdirectory(bio) +add_subdirectory(blowfish) +add_subdirectory(cast) +add_subdirectory(des) +add_subdirectory(dh) +add_subdirectory(dsa) +add_subdirectory(evp) +add_subdirectory(obj) +add_subdirectory(rc4) +add_subdirectory(ripemd) +add_subdirectory(rsa) +add_subdirectory(ssl) +add_subdirectory(x509) +add_subdirectory(xts) + +add_library( + decrepit + + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ +) + +target_link_libraries(decrepit crypto ssl) diff --git a/external/boringssl/decrepit/bio/CMakeLists.txt b/external/boringssl/decrepit/bio/CMakeLists.txt new file mode 100644 index 0000000000..95d9231157 --- /dev/null +++ b/external/boringssl/decrepit/bio/CMakeLists.txt @@ -0,0 +1,9 @@ +include_directories(../../include) + +add_library( + bio_decrepit + + OBJECT + + base64_bio.c +) diff --git a/external/boringssl/decrepit/bio/base64_bio.c b/external/boringssl/decrepit/bio/base64_bio.c new file mode 100644 index 0000000000..8415bfedb4 --- /dev/null +++ b/external/boringssl/decrepit/bio/base64_bio.c @@ -0,0 +1,536 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + + +#define B64_BLOCK_SIZE 1024 +#define B64_BLOCK_SIZE2 768 +#define B64_NONE 0 +#define B64_ENCODE 1 +#define B64_DECODE 2 +#define EVP_ENCODE_LENGTH(l) (((l+2)/3*4)+(l/48+1)*2+80) + +typedef struct b64_struct { + int buf_len; + int buf_off; + int tmp_len; /* used to find the start when decoding */ + int tmp_nl; /* If true, scan until '\n' */ + int encode; + int start; /* have we started decoding yet? */ + int cont; /* <= 0 when finished */ + EVP_ENCODE_CTX base64; + char buf[EVP_ENCODE_LENGTH(B64_BLOCK_SIZE) + 10]; + char tmp[B64_BLOCK_SIZE]; +} BIO_B64_CTX; + +static int b64_new(BIO *bio) { + BIO_B64_CTX *ctx; + + ctx = OPENSSL_malloc(sizeof(*ctx)); + if (ctx == NULL) { + return 0; + } + + memset(ctx, 0, sizeof(*ctx)); + + ctx->cont = 1; + ctx->start = 1; + + bio->init = 1; + bio->ptr = (char *)ctx; + return 1; +} + +static int b64_free(BIO *bio) { + if (bio == NULL) { + return 0; + } + OPENSSL_free(bio->ptr); + bio->ptr = NULL; + bio->init = 0; + bio->flags = 0; + return 1; +} + +static int b64_read(BIO *b, char *out, int outl) { + int ret = 0, i, ii, j, k, x, n, num, ret_code = 0; + BIO_B64_CTX *ctx; + uint8_t *p, *q; + + if (out == NULL) { + return 0; + } + ctx = (BIO_B64_CTX *) b->ptr; + + if (ctx == NULL || b->next_bio == NULL) { + return 0; + } + + BIO_clear_retry_flags(b); + + if (ctx->encode != B64_DECODE) { + ctx->encode = B64_DECODE; + ctx->buf_len = 0; + ctx->buf_off = 0; + ctx->tmp_len = 0; + EVP_DecodeInit(&ctx->base64); + } + + /* First check if there are bytes decoded/encoded */ + if (ctx->buf_len > 0) { + assert(ctx->buf_len >= ctx->buf_off); + i = ctx->buf_len - ctx->buf_off; + if (i > outl) { + i = outl; + } + assert(ctx->buf_off + i < (int)sizeof(ctx->buf)); + memcpy(out, &ctx->buf[ctx->buf_off], i); + ret = i; + out += i; + outl -= i; + ctx->buf_off += i; + if (ctx->buf_len == ctx->buf_off) { + ctx->buf_len = 0; + ctx->buf_off = 0; + } + } + + /* At this point, we have room of outl bytes and an empty buffer, so we + * should read in some more. */ + + ret_code = 0; + while (outl > 0) { + if (ctx->cont <= 0) { + break; + } + + i = BIO_read(b->next_bio, &(ctx->tmp[ctx->tmp_len]), + B64_BLOCK_SIZE - ctx->tmp_len); + + if (i <= 0) { + ret_code = i; + + /* Should we continue next time we are called? */ + if (!BIO_should_retry(b->next_bio)) { + ctx->cont = i; + /* If buffer empty break */ + if (ctx->tmp_len == 0) { + break; + } else { + /* Fall through and process what we have */ + i = 0; + } + } else { + /* else we retry and add more data to buffer */ + break; + } + } + i += ctx->tmp_len; + ctx->tmp_len = i; + + /* We need to scan, a line at a time until we have a valid line if we are + * starting. */ + if (ctx->start && (BIO_test_flags(b, BIO_FLAGS_BASE64_NO_NL))) { + /* ctx->start = 1; */ + ctx->tmp_len = 0; + } else if (ctx->start) { + q = p = (uint8_t *)ctx->tmp; + num = 0; + for (j = 0; j < i; j++) { + if (*(q++) != '\n') { + continue; + } + + /* due to a previous very long line, we need to keep on scanning for a + * '\n' before we even start looking for base64 encoded stuff. */ + if (ctx->tmp_nl) { + p = q; + ctx->tmp_nl = 0; + continue; + } + + k = EVP_DecodeUpdate(&(ctx->base64), (uint8_t *)ctx->buf, &num, p, + q - p); + + if (k <= 0 && num == 0 && ctx->start) { + EVP_DecodeInit(&ctx->base64); + } else { + if (p != (uint8_t *)&(ctx->tmp[0])) { + i -= (p - (uint8_t *)&(ctx->tmp[0])); + for (x = 0; x < i; x++) { + ctx->tmp[x] = p[x]; + } + } + EVP_DecodeInit(&ctx->base64); + ctx->start = 0; + break; + } + p = q; + } + + /* we fell off the end without starting */ + if (j == i && num == 0) { + /* Is this is one long chunk?, if so, keep on reading until a new + * line. */ + if (p == (uint8_t *)&(ctx->tmp[0])) { + /* Check buffer full */ + if (i == B64_BLOCK_SIZE) { + ctx->tmp_nl = 1; + ctx->tmp_len = 0; + } + } else if (p != q) { /* finished on a '\n' */ + n = q - p; + for (ii = 0; ii < n; ii++) { + ctx->tmp[ii] = p[ii]; + } + ctx->tmp_len = n; + } + /* else finished on a '\n' */ + continue; + } else { + ctx->tmp_len = 0; + } + } else if (i < B64_BLOCK_SIZE && ctx->cont > 0) { + /* If buffer isn't full and we can retry then restart to read in more + * data. */ + continue; + } + + if (BIO_test_flags(b, BIO_FLAGS_BASE64_NO_NL)) { + int z, jj; + + jj = i & ~3; /* process per 4 */ + z = EVP_DecodeBlock((uint8_t *)ctx->buf, (uint8_t *)ctx->tmp, jj); + if (jj > 2) { + if (ctx->tmp[jj - 1] == '=') { + z--; + if (ctx->tmp[jj - 2] == '=') { + z--; + } + } + } + /* z is now number of output bytes and jj is the number consumed. */ + if (jj != i) { + memmove(ctx->tmp, &ctx->tmp[jj], i - jj); + ctx->tmp_len = i - jj; + } + ctx->buf_len = 0; + if (z > 0) { + ctx->buf_len = z; + } + i = z; + } else { + i = EVP_DecodeUpdate(&(ctx->base64), (uint8_t *)ctx->buf, + &ctx->buf_len, (uint8_t *)ctx->tmp, i); + ctx->tmp_len = 0; + } + ctx->buf_off = 0; + if (i < 0) { + ret_code = 0; + ctx->buf_len = 0; + break; + } + + if (ctx->buf_len <= outl) { + i = ctx->buf_len; + } else { + i = outl; + } + + memcpy(out, ctx->buf, i); + ret += i; + ctx->buf_off = i; + if (ctx->buf_off == ctx->buf_len) { + ctx->buf_len = 0; + ctx->buf_off = 0; + } + outl -= i; + out += i; + } + + BIO_copy_next_retry(b); + return ret == 0 ? ret_code : ret; +} + +static int b64_write(BIO *b, const char *in, int inl) { + int ret = 0, n, i; + BIO_B64_CTX *ctx; + + ctx = (BIO_B64_CTX *)b->ptr; + BIO_clear_retry_flags(b); + + if (ctx->encode != B64_ENCODE) { + ctx->encode = B64_ENCODE; + ctx->buf_len = 0; + ctx->buf_off = 0; + ctx->tmp_len = 0; + EVP_EncodeInit(&(ctx->base64)); + } + + assert(ctx->buf_off < (int)sizeof(ctx->buf)); + assert(ctx->buf_len <= (int)sizeof(ctx->buf)); + assert(ctx->buf_len >= ctx->buf_off); + + n = ctx->buf_len - ctx->buf_off; + while (n > 0) { + i = BIO_write(b->next_bio, &(ctx->buf[ctx->buf_off]), n); + if (i <= 0) { + BIO_copy_next_retry(b); + return i; + } + assert(i <= n); + ctx->buf_off += i; + assert(ctx->buf_off <= (int)sizeof(ctx->buf)); + assert(ctx->buf_len >= ctx->buf_off); + n -= i; + } + + /* at this point all pending data has been written. */ + ctx->buf_off = 0; + ctx->buf_len = 0; + + if (in == NULL || inl <= 0) { + return 0; + } + + while (inl > 0) { + n = (inl > B64_BLOCK_SIZE) ? B64_BLOCK_SIZE : inl; + + if (BIO_test_flags(b, BIO_FLAGS_BASE64_NO_NL)) { + if (ctx->tmp_len > 0) { + assert(ctx->tmp_len <= 3); + n = 3 - ctx->tmp_len; + /* There's a theoretical possibility of this. */ + if (n > inl) { + n = inl; + } + memcpy(&(ctx->tmp[ctx->tmp_len]), in, n); + ctx->tmp_len += n; + ret += n; + if (ctx->tmp_len < 3) { + break; + } + ctx->buf_len = EVP_EncodeBlock((uint8_t *)ctx->buf, (uint8_t *)ctx->tmp, + ctx->tmp_len); + assert(ctx->buf_len <= (int)sizeof(ctx->buf)); + assert(ctx->buf_len >= ctx->buf_off); + + /* Since we're now done using the temporary buffer, the length should + * be zeroed. */ + ctx->tmp_len = 0; + } else { + if (n < 3) { + memcpy(ctx->tmp, in, n); + ctx->tmp_len = n; + ret += n; + break; + } + n -= n % 3; + ctx->buf_len = + EVP_EncodeBlock((uint8_t *)ctx->buf, (const uint8_t *)in, n); + assert(ctx->buf_len <= (int)sizeof(ctx->buf)); + assert(ctx->buf_len >= ctx->buf_off); + ret += n; + } + } else { + EVP_EncodeUpdate(&(ctx->base64), (uint8_t *)ctx->buf, &ctx->buf_len, + (uint8_t *)in, n); + assert(ctx->buf_len <= (int)sizeof(ctx->buf)); + assert(ctx->buf_len >= ctx->buf_off); + ret += n; + } + inl -= n; + in += n; + + ctx->buf_off = 0; + n = ctx->buf_len; + + while (n > 0) { + i = BIO_write(b->next_bio, &(ctx->buf[ctx->buf_off]), n); + if (i <= 0) { + BIO_copy_next_retry(b); + return ret == 0 ? i : ret; + } + assert(i <= n); + n -= i; + ctx->buf_off += i; + assert(ctx->buf_off <= (int)sizeof(ctx->buf)); + assert(ctx->buf_len >= ctx->buf_off); + } + ctx->buf_len = 0; + ctx->buf_off = 0; + } + return ret; +} + +static long b64_ctrl(BIO *b, int cmd, long num, void *ptr) { + BIO_B64_CTX *ctx; + long ret = 1; + int i; + + ctx = (BIO_B64_CTX *)b->ptr; + + switch (cmd) { + case BIO_CTRL_RESET: + ctx->cont = 1; + ctx->start = 1; + ctx->encode = B64_NONE; + ret = BIO_ctrl(b->next_bio, cmd, num, ptr); + break; + + case BIO_CTRL_EOF: /* More to read */ + if (ctx->cont <= 0) { + ret = 1; + } else { + ret = BIO_ctrl(b->next_bio, cmd, num, ptr); + } + break; + + case BIO_CTRL_WPENDING: /* More to write in buffer */ + assert(ctx->buf_len >= ctx->buf_off); + ret = ctx->buf_len - ctx->buf_off; + if ((ret == 0) && (ctx->encode != B64_NONE) && (ctx->base64.data_used != 0)) { + ret = 1; + } else if (ret <= 0) { + ret = BIO_ctrl(b->next_bio, cmd, num, ptr); + } + break; + + case BIO_CTRL_PENDING: /* More to read in buffer */ + assert(ctx->buf_len >= ctx->buf_off); + ret = ctx->buf_len - ctx->buf_off; + if (ret <= 0) { + ret = BIO_ctrl(b->next_bio, cmd, num, ptr); + } + break; + + case BIO_CTRL_FLUSH: + /* do a final write */ + again: + while (ctx->buf_len != ctx->buf_off) { + i = b64_write(b, NULL, 0); + if (i < 0) { + return i; + } + } + if (BIO_test_flags(b, BIO_FLAGS_BASE64_NO_NL)) { + if (ctx->tmp_len != 0) { + ctx->buf_len = EVP_EncodeBlock((uint8_t *)ctx->buf, + (uint8_t *)ctx->tmp, ctx->tmp_len); + ctx->buf_off = 0; + ctx->tmp_len = 0; + goto again; + } + } else if (ctx->encode != B64_NONE && ctx->base64.data_used != 0) { + ctx->buf_off = 0; + EVP_EncodeFinal(&(ctx->base64), (uint8_t *)ctx->buf, &(ctx->buf_len)); + /* push out the bytes */ + goto again; + } + /* Finally flush the underlying BIO */ + ret = BIO_ctrl(b->next_bio, cmd, num, ptr); + break; + + case BIO_C_DO_STATE_MACHINE: + BIO_clear_retry_flags(b); + ret = BIO_ctrl(b->next_bio, cmd, num, ptr); + BIO_copy_next_retry(b); + break; + + case BIO_CTRL_INFO: + case BIO_CTRL_GET: + case BIO_CTRL_SET: + default: + ret = BIO_ctrl(b->next_bio, cmd, num, ptr); + break; + } + return ret; +} + +static long b64_callback_ctrl(BIO *b, int cmd, bio_info_cb fp) { + long ret = 1; + + if (b->next_bio == NULL) { + return 0; + } + switch (cmd) { + default: + ret = BIO_callback_ctrl(b->next_bio, cmd, fp); + break; + } + return ret; +} + +static int b64_puts(BIO *b, const char *str) { + return b64_write(b, str, strlen(str)); +} + +static const BIO_METHOD b64_method = { + BIO_TYPE_BASE64, "base64 encoding", b64_write, b64_read, b64_puts, + NULL /* gets */, b64_ctrl, b64_new, b64_free, b64_callback_ctrl, +}; + +const BIO_METHOD *BIO_f_base64(void) { return &b64_method; } diff --git a/external/boringssl/decrepit/blowfish/CMakeLists.txt b/external/boringssl/decrepit/blowfish/CMakeLists.txt new file mode 100644 index 0000000000..29729c4982 --- /dev/null +++ b/external/boringssl/decrepit/blowfish/CMakeLists.txt @@ -0,0 +1,9 @@ +include_directories(../../include) + +add_library( + blowfish + + OBJECT + + blowfish.c +) diff --git a/external/boringssl/decrepit/blowfish/blowfish.c b/external/boringssl/decrepit/blowfish/blowfish.c new file mode 100644 index 0000000000..e277f3446b --- /dev/null +++ b/external/boringssl/decrepit/blowfish/blowfish.c @@ -0,0 +1,493 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include "../macros.h" + + +#define BF_ENC(LL, R, S, P) \ + (LL ^= P, \ + LL ^= \ + (((S[((int)(R >> 24) & 0xff)] + S[0x0100 + ((int)(R >> 16) & 0xff)]) ^ \ + S[0x0200 + ((int)(R >> 8) & 0xff)]) + \ + S[0x0300 + ((int)(R)&0xff)]) & \ + 0xffffffffL) + +void BF_encrypt(uint32_t *data, const BF_KEY *key) { + uint32_t l, r; + const uint32_t *p, *s; + + p = key->P; + s = &(key->S[0]); + l = data[0]; + r = data[1]; + + l ^= p[0]; + BF_ENC(r, l, s, p[1]); + BF_ENC(l, r, s, p[2]); + BF_ENC(r, l, s, p[3]); + BF_ENC(l, r, s, p[4]); + BF_ENC(r, l, s, p[5]); + BF_ENC(l, r, s, p[6]); + BF_ENC(r, l, s, p[7]); + BF_ENC(l, r, s, p[8]); + BF_ENC(r, l, s, p[9]); + BF_ENC(l, r, s, p[10]); + BF_ENC(r, l, s, p[11]); + BF_ENC(l, r, s, p[12]); + BF_ENC(r, l, s, p[13]); + BF_ENC(l, r, s, p[14]); + BF_ENC(r, l, s, p[15]); + BF_ENC(l, r, s, p[16]); + r ^= p[BF_ROUNDS + 1]; + + data[1] = l & 0xffffffffL; + data[0] = r & 0xffffffffL; +} + +void BF_decrypt(uint32_t *data, const BF_KEY *key) { + uint32_t l, r; + const uint32_t *p, *s; + + p = key->P; + s = &(key->S[0]); + l = data[0]; + r = data[1]; + + l ^= p[BF_ROUNDS + 1]; + BF_ENC(r, l, s, p[16]); + BF_ENC(l, r, s, p[15]); + BF_ENC(r, l, s, p[14]); + BF_ENC(l, r, s, p[13]); + BF_ENC(r, l, s, p[12]); + BF_ENC(l, r, s, p[11]); + BF_ENC(r, l, s, p[10]); + BF_ENC(l, r, s, p[9]); + BF_ENC(r, l, s, p[8]); + BF_ENC(l, r, s, p[7]); + BF_ENC(r, l, s, p[6]); + BF_ENC(l, r, s, p[5]); + BF_ENC(r, l, s, p[4]); + BF_ENC(l, r, s, p[3]); + BF_ENC(r, l, s, p[2]); + BF_ENC(l, r, s, p[1]); + r ^= p[0]; + + data[1] = l & 0xffffffffL; + data[0] = r & 0xffffffffL; +} + +void BF_ecb_encrypt(const uint8_t *in, uint8_t *out, + const BF_KEY *key, int encrypt) { + uint32_t d[2]; + + n2l(in, d[0]); + n2l(in, d[1]); + if (encrypt) { + BF_encrypt(d, key); + } else { + BF_decrypt(d, key); + } + l2n(d[0], out); + l2n(d[1], out); +} + +void BF_cbc_encrypt(const uint8_t *in, uint8_t *out, long length, + const BF_KEY *schedule, uint8_t *ivec, int encrypt) { + uint32_t tin0, tin1; + uint32_t tout0, tout1, xor0, xor1; + long l = length; + uint32_t tin[2]; + + if (encrypt) { + n2l(ivec, tout0); + n2l(ivec, tout1); + ivec -= 8; + for (l -= 8; l >= 0; l -= 8) { + n2l(in, tin0); + n2l(in, tin1); + tin0 ^= tout0; + tin1 ^= tout1; + tin[0] = tin0; + tin[1] = tin1; + BF_encrypt(tin, schedule); + tout0 = tin[0]; + tout1 = tin[1]; + l2n(tout0, out); + l2n(tout1, out); + } + if (l != -8) { + n2ln(in, tin0, tin1, l + 8); + tin0 ^= tout0; + tin1 ^= tout1; + tin[0] = tin0; + tin[1] = tin1; + BF_encrypt(tin, schedule); + tout0 = tin[0]; + tout1 = tin[1]; + l2n(tout0, out); + l2n(tout1, out); + } + l2n(tout0, ivec); + l2n(tout1, ivec); + } else { + n2l(ivec, xor0); + n2l(ivec, xor1); + ivec -= 8; + for (l -= 8; l >= 0; l -= 8) { + n2l(in, tin0); + n2l(in, tin1); + tin[0] = tin0; + tin[1] = tin1; + BF_decrypt(tin, schedule); + tout0 = tin[0] ^ xor0; + tout1 = tin[1] ^ xor1; + l2n(tout0, out); + l2n(tout1, out); + xor0 = tin0; + xor1 = tin1; + } + if (l != -8) { + n2l(in, tin0); + n2l(in, tin1); + tin[0] = tin0; + tin[1] = tin1; + BF_decrypt(tin, schedule); + tout0 = tin[0] ^ xor0; + tout1 = tin[1] ^ xor1; + l2nn(tout0, tout1, out, l + 8); + xor0 = tin0; + xor1 = tin1; + } + l2n(xor0, ivec); + l2n(xor1, ivec); + } + tin0 = tin1 = tout0 = tout1 = xor0 = xor1 = 0; + tin[0] = tin[1] = 0; +} + +static const BF_KEY bf_init = { + {0x243f6a88L, 0x85a308d3L, 0x13198a2eL, 0x03707344L, 0xa4093822L, + 0x299f31d0L, 0x082efa98L, 0xec4e6c89L, 0x452821e6L, 0x38d01377L, + 0xbe5466cfL, 0x34e90c6cL, 0xc0ac29b7L, 0xc97c50ddL, 0x3f84d5b5L, + 0xb5470917L, 0x9216d5d9L, 0x8979fb1b}, + { + 0xd1310ba6L, 0x98dfb5acL, 0x2ffd72dbL, 0xd01adfb7L, 0xb8e1afedL, + 0x6a267e96L, 0xba7c9045L, 0xf12c7f99L, 0x24a19947L, 0xb3916cf7L, + 0x0801f2e2L, 0x858efc16L, 0x636920d8L, 0x71574e69L, 0xa458fea3L, + 0xf4933d7eL, 0x0d95748fL, 0x728eb658L, 0x718bcd58L, 0x82154aeeL, + 0x7b54a41dL, 0xc25a59b5L, 0x9c30d539L, 0x2af26013L, 0xc5d1b023L, + 0x286085f0L, 0xca417918L, 0xb8db38efL, 0x8e79dcb0L, 0x603a180eL, + 0x6c9e0e8bL, 0xb01e8a3eL, 0xd71577c1L, 0xbd314b27L, 0x78af2fdaL, + 0x55605c60L, 0xe65525f3L, 0xaa55ab94L, 0x57489862L, 0x63e81440L, + 0x55ca396aL, 0x2aab10b6L, 0xb4cc5c34L, 0x1141e8ceL, 0xa15486afL, + 0x7c72e993L, 0xb3ee1411L, 0x636fbc2aL, 0x2ba9c55dL, 0x741831f6L, + 0xce5c3e16L, 0x9b87931eL, 0xafd6ba33L, 0x6c24cf5cL, 0x7a325381L, + 0x28958677L, 0x3b8f4898L, 0x6b4bb9afL, 0xc4bfe81bL, 0x66282193L, + 0x61d809ccL, 0xfb21a991L, 0x487cac60L, 0x5dec8032L, 0xef845d5dL, + 0xe98575b1L, 0xdc262302L, 0xeb651b88L, 0x23893e81L, 0xd396acc5L, + 0x0f6d6ff3L, 0x83f44239L, 0x2e0b4482L, 0xa4842004L, 0x69c8f04aL, + 0x9e1f9b5eL, 0x21c66842L, 0xf6e96c9aL, 0x670c9c61L, 0xabd388f0L, + 0x6a51a0d2L, 0xd8542f68L, 0x960fa728L, 0xab5133a3L, 0x6eef0b6cL, + 0x137a3be4L, 0xba3bf050L, 0x7efb2a98L, 0xa1f1651dL, 0x39af0176L, + 0x66ca593eL, 0x82430e88L, 0x8cee8619L, 0x456f9fb4L, 0x7d84a5c3L, + 0x3b8b5ebeL, 0xe06f75d8L, 0x85c12073L, 0x401a449fL, 0x56c16aa6L, + 0x4ed3aa62L, 0x363f7706L, 0x1bfedf72L, 0x429b023dL, 0x37d0d724L, + 0xd00a1248L, 0xdb0fead3L, 0x49f1c09bL, 0x075372c9L, 0x80991b7bL, + 0x25d479d8L, 0xf6e8def7L, 0xe3fe501aL, 0xb6794c3bL, 0x976ce0bdL, + 0x04c006baL, 0xc1a94fb6L, 0x409f60c4L, 0x5e5c9ec2L, 0x196a2463L, + 0x68fb6fafL, 0x3e6c53b5L, 0x1339b2ebL, 0x3b52ec6fL, 0x6dfc511fL, + 0x9b30952cL, 0xcc814544L, 0xaf5ebd09L, 0xbee3d004L, 0xde334afdL, + 0x660f2807L, 0x192e4bb3L, 0xc0cba857L, 0x45c8740fL, 0xd20b5f39L, + 0xb9d3fbdbL, 0x5579c0bdL, 0x1a60320aL, 0xd6a100c6L, 0x402c7279L, + 0x679f25feL, 0xfb1fa3ccL, 0x8ea5e9f8L, 0xdb3222f8L, 0x3c7516dfL, + 0xfd616b15L, 0x2f501ec8L, 0xad0552abL, 0x323db5faL, 0xfd238760L, + 0x53317b48L, 0x3e00df82L, 0x9e5c57bbL, 0xca6f8ca0L, 0x1a87562eL, + 0xdf1769dbL, 0xd542a8f6L, 0x287effc3L, 0xac6732c6L, 0x8c4f5573L, + 0x695b27b0L, 0xbbca58c8L, 0xe1ffa35dL, 0xb8f011a0L, 0x10fa3d98L, + 0xfd2183b8L, 0x4afcb56cL, 0x2dd1d35bL, 0x9a53e479L, 0xb6f84565L, + 0xd28e49bcL, 0x4bfb9790L, 0xe1ddf2daL, 0xa4cb7e33L, 0x62fb1341L, + 0xcee4c6e8L, 0xef20cadaL, 0x36774c01L, 0xd07e9efeL, 0x2bf11fb4L, + 0x95dbda4dL, 0xae909198L, 0xeaad8e71L, 0x6b93d5a0L, 0xd08ed1d0L, + 0xafc725e0L, 0x8e3c5b2fL, 0x8e7594b7L, 0x8ff6e2fbL, 0xf2122b64L, + 0x8888b812L, 0x900df01cL, 0x4fad5ea0L, 0x688fc31cL, 0xd1cff191L, + 0xb3a8c1adL, 0x2f2f2218L, 0xbe0e1777L, 0xea752dfeL, 0x8b021fa1L, + 0xe5a0cc0fL, 0xb56f74e8L, 0x18acf3d6L, 0xce89e299L, 0xb4a84fe0L, + 0xfd13e0b7L, 0x7cc43b81L, 0xd2ada8d9L, 0x165fa266L, 0x80957705L, + 0x93cc7314L, 0x211a1477L, 0xe6ad2065L, 0x77b5fa86L, 0xc75442f5L, + 0xfb9d35cfL, 0xebcdaf0cL, 0x7b3e89a0L, 0xd6411bd3L, 0xae1e7e49L, + 0x00250e2dL, 0x2071b35eL, 0x226800bbL, 0x57b8e0afL, 0x2464369bL, + 0xf009b91eL, 0x5563911dL, 0x59dfa6aaL, 0x78c14389L, 0xd95a537fL, + 0x207d5ba2L, 0x02e5b9c5L, 0x83260376L, 0x6295cfa9L, 0x11c81968L, + 0x4e734a41L, 0xb3472dcaL, 0x7b14a94aL, 0x1b510052L, 0x9a532915L, + 0xd60f573fL, 0xbc9bc6e4L, 0x2b60a476L, 0x81e67400L, 0x08ba6fb5L, + 0x571be91fL, 0xf296ec6bL, 0x2a0dd915L, 0xb6636521L, 0xe7b9f9b6L, + 0xff34052eL, 0xc5855664L, 0x53b02d5dL, 0xa99f8fa1L, 0x08ba4799L, + 0x6e85076aL, 0x4b7a70e9L, 0xb5b32944L, 0xdb75092eL, 0xc4192623L, + 0xad6ea6b0L, 0x49a7df7dL, 0x9cee60b8L, 0x8fedb266L, 0xecaa8c71L, + 0x699a17ffL, 0x5664526cL, 0xc2b19ee1L, 0x193602a5L, 0x75094c29L, + 0xa0591340L, 0xe4183a3eL, 0x3f54989aL, 0x5b429d65L, 0x6b8fe4d6L, + 0x99f73fd6L, 0xa1d29c07L, 0xefe830f5L, 0x4d2d38e6L, 0xf0255dc1L, + 0x4cdd2086L, 0x8470eb26L, 0x6382e9c6L, 0x021ecc5eL, 0x09686b3fL, + 0x3ebaefc9L, 0x3c971814L, 0x6b6a70a1L, 0x687f3584L, 0x52a0e286L, + 0xb79c5305L, 0xaa500737L, 0x3e07841cL, 0x7fdeae5cL, 0x8e7d44ecL, + 0x5716f2b8L, 0xb03ada37L, 0xf0500c0dL, 0xf01c1f04L, 0x0200b3ffL, + 0xae0cf51aL, 0x3cb574b2L, 0x25837a58L, 0xdc0921bdL, 0xd19113f9L, + 0x7ca92ff6L, 0x94324773L, 0x22f54701L, 0x3ae5e581L, 0x37c2dadcL, + 0xc8b57634L, 0x9af3dda7L, 0xa9446146L, 0x0fd0030eL, 0xecc8c73eL, + 0xa4751e41L, 0xe238cd99L, 0x3bea0e2fL, 0x3280bba1L, 0x183eb331L, + 0x4e548b38L, 0x4f6db908L, 0x6f420d03L, 0xf60a04bfL, 0x2cb81290L, + 0x24977c79L, 0x5679b072L, 0xbcaf89afL, 0xde9a771fL, 0xd9930810L, + 0xb38bae12L, 0xdccf3f2eL, 0x5512721fL, 0x2e6b7124L, 0x501adde6L, + 0x9f84cd87L, 0x7a584718L, 0x7408da17L, 0xbc9f9abcL, 0xe94b7d8cL, + 0xec7aec3aL, 0xdb851dfaL, 0x63094366L, 0xc464c3d2L, 0xef1c1847L, + 0x3215d908L, 0xdd433b37L, 0x24c2ba16L, 0x12a14d43L, 0x2a65c451L, + 0x50940002L, 0x133ae4ddL, 0x71dff89eL, 0x10314e55L, 0x81ac77d6L, + 0x5f11199bL, 0x043556f1L, 0xd7a3c76bL, 0x3c11183bL, 0x5924a509L, + 0xf28fe6edL, 0x97f1fbfaL, 0x9ebabf2cL, 0x1e153c6eL, 0x86e34570L, + 0xeae96fb1L, 0x860e5e0aL, 0x5a3e2ab3L, 0x771fe71cL, 0x4e3d06faL, + 0x2965dcb9L, 0x99e71d0fL, 0x803e89d6L, 0x5266c825L, 0x2e4cc978L, + 0x9c10b36aL, 0xc6150ebaL, 0x94e2ea78L, 0xa5fc3c53L, 0x1e0a2df4L, + 0xf2f74ea7L, 0x361d2b3dL, 0x1939260fL, 0x19c27960L, 0x5223a708L, + 0xf71312b6L, 0xebadfe6eL, 0xeac31f66L, 0xe3bc4595L, 0xa67bc883L, + 0xb17f37d1L, 0x018cff28L, 0xc332ddefL, 0xbe6c5aa5L, 0x65582185L, + 0x68ab9802L, 0xeecea50fL, 0xdb2f953bL, 0x2aef7dadL, 0x5b6e2f84L, + 0x1521b628L, 0x29076170L, 0xecdd4775L, 0x619f1510L, 0x13cca830L, + 0xeb61bd96L, 0x0334fe1eL, 0xaa0363cfL, 0xb5735c90L, 0x4c70a239L, + 0xd59e9e0bL, 0xcbaade14L, 0xeecc86bcL, 0x60622ca7L, 0x9cab5cabL, + 0xb2f3846eL, 0x648b1eafL, 0x19bdf0caL, 0xa02369b9L, 0x655abb50L, + 0x40685a32L, 0x3c2ab4b3L, 0x319ee9d5L, 0xc021b8f7L, 0x9b540b19L, + 0x875fa099L, 0x95f7997eL, 0x623d7da8L, 0xf837889aL, 0x97e32d77L, + 0x11ed935fL, 0x16681281L, 0x0e358829L, 0xc7e61fd6L, 0x96dedfa1L, + 0x7858ba99L, 0x57f584a5L, 0x1b227263L, 0x9b83c3ffL, 0x1ac24696L, + 0xcdb30aebL, 0x532e3054L, 0x8fd948e4L, 0x6dbc3128L, 0x58ebf2efL, + 0x34c6ffeaL, 0xfe28ed61L, 0xee7c3c73L, 0x5d4a14d9L, 0xe864b7e3L, + 0x42105d14L, 0x203e13e0L, 0x45eee2b6L, 0xa3aaabeaL, 0xdb6c4f15L, + 0xfacb4fd0L, 0xc742f442L, 0xef6abbb5L, 0x654f3b1dL, 0x41cd2105L, + 0xd81e799eL, 0x86854dc7L, 0xe44b476aL, 0x3d816250L, 0xcf62a1f2L, + 0x5b8d2646L, 0xfc8883a0L, 0xc1c7b6a3L, 0x7f1524c3L, 0x69cb7492L, + 0x47848a0bL, 0x5692b285L, 0x095bbf00L, 0xad19489dL, 0x1462b174L, + 0x23820e00L, 0x58428d2aL, 0x0c55f5eaL, 0x1dadf43eL, 0x233f7061L, + 0x3372f092L, 0x8d937e41L, 0xd65fecf1L, 0x6c223bdbL, 0x7cde3759L, + 0xcbee7460L, 0x4085f2a7L, 0xce77326eL, 0xa6078084L, 0x19f8509eL, + 0xe8efd855L, 0x61d99735L, 0xa969a7aaL, 0xc50c06c2L, 0x5a04abfcL, + 0x800bcadcL, 0x9e447a2eL, 0xc3453484L, 0xfdd56705L, 0x0e1e9ec9L, + 0xdb73dbd3L, 0x105588cdL, 0x675fda79L, 0xe3674340L, 0xc5c43465L, + 0x713e38d8L, 0x3d28f89eL, 0xf16dff20L, 0x153e21e7L, 0x8fb03d4aL, + 0xe6e39f2bL, 0xdb83adf7L, 0xe93d5a68L, 0x948140f7L, 0xf64c261cL, + 0x94692934L, 0x411520f7L, 0x7602d4f7L, 0xbcf46b2eL, 0xd4a20068L, + 0xd4082471L, 0x3320f46aL, 0x43b7d4b7L, 0x500061afL, 0x1e39f62eL, + 0x97244546L, 0x14214f74L, 0xbf8b8840L, 0x4d95fc1dL, 0x96b591afL, + 0x70f4ddd3L, 0x66a02f45L, 0xbfbc09ecL, 0x03bd9785L, 0x7fac6dd0L, + 0x31cb8504L, 0x96eb27b3L, 0x55fd3941L, 0xda2547e6L, 0xabca0a9aL, + 0x28507825L, 0x530429f4L, 0x0a2c86daL, 0xe9b66dfbL, 0x68dc1462L, + 0xd7486900L, 0x680ec0a4L, 0x27a18deeL, 0x4f3ffea2L, 0xe887ad8cL, + 0xb58ce006L, 0x7af4d6b6L, 0xaace1e7cL, 0xd3375fecL, 0xce78a399L, + 0x406b2a42L, 0x20fe9e35L, 0xd9f385b9L, 0xee39d7abL, 0x3b124e8bL, + 0x1dc9faf7L, 0x4b6d1856L, 0x26a36631L, 0xeae397b2L, 0x3a6efa74L, + 0xdd5b4332L, 0x6841e7f7L, 0xca7820fbL, 0xfb0af54eL, 0xd8feb397L, + 0x454056acL, 0xba489527L, 0x55533a3aL, 0x20838d87L, 0xfe6ba9b7L, + 0xd096954bL, 0x55a867bcL, 0xa1159a58L, 0xcca92963L, 0x99e1db33L, + 0xa62a4a56L, 0x3f3125f9L, 0x5ef47e1cL, 0x9029317cL, 0xfdf8e802L, + 0x04272f70L, 0x80bb155cL, 0x05282ce3L, 0x95c11548L, 0xe4c66d22L, + 0x48c1133fL, 0xc70f86dcL, 0x07f9c9eeL, 0x41041f0fL, 0x404779a4L, + 0x5d886e17L, 0x325f51ebL, 0xd59bc0d1L, 0xf2bcc18fL, 0x41113564L, + 0x257b7834L, 0x602a9c60L, 0xdff8e8a3L, 0x1f636c1bL, 0x0e12b4c2L, + 0x02e1329eL, 0xaf664fd1L, 0xcad18115L, 0x6b2395e0L, 0x333e92e1L, + 0x3b240b62L, 0xeebeb922L, 0x85b2a20eL, 0xe6ba0d99L, 0xde720c8cL, + 0x2da2f728L, 0xd0127845L, 0x95b794fdL, 0x647d0862L, 0xe7ccf5f0L, + 0x5449a36fL, 0x877d48faL, 0xc39dfd27L, 0xf33e8d1eL, 0x0a476341L, + 0x992eff74L, 0x3a6f6eabL, 0xf4f8fd37L, 0xa812dc60L, 0xa1ebddf8L, + 0x991be14cL, 0xdb6e6b0dL, 0xc67b5510L, 0x6d672c37L, 0x2765d43bL, + 0xdcd0e804L, 0xf1290dc7L, 0xcc00ffa3L, 0xb5390f92L, 0x690fed0bL, + 0x667b9ffbL, 0xcedb7d9cL, 0xa091cf0bL, 0xd9155ea3L, 0xbb132f88L, + 0x515bad24L, 0x7b9479bfL, 0x763bd6ebL, 0x37392eb3L, 0xcc115979L, + 0x8026e297L, 0xf42e312dL, 0x6842ada7L, 0xc66a2b3bL, 0x12754cccL, + 0x782ef11cL, 0x6a124237L, 0xb79251e7L, 0x06a1bbe6L, 0x4bfb6350L, + 0x1a6b1018L, 0x11caedfaL, 0x3d25bdd8L, 0xe2e1c3c9L, 0x44421659L, + 0x0a121386L, 0xd90cec6eL, 0xd5abea2aL, 0x64af674eL, 0xda86a85fL, + 0xbebfe988L, 0x64e4c3feL, 0x9dbc8057L, 0xf0f7c086L, 0x60787bf8L, + 0x6003604dL, 0xd1fd8346L, 0xf6381fb0L, 0x7745ae04L, 0xd736fcccL, + 0x83426b33L, 0xf01eab71L, 0xb0804187L, 0x3c005e5fL, 0x77a057beL, + 0xbde8ae24L, 0x55464299L, 0xbf582e61L, 0x4e58f48fL, 0xf2ddfda2L, + 0xf474ef38L, 0x8789bdc2L, 0x5366f9c3L, 0xc8b38e74L, 0xb475f255L, + 0x46fcd9b9L, 0x7aeb2661L, 0x8b1ddf84L, 0x846a0e79L, 0x915f95e2L, + 0x466e598eL, 0x20b45770L, 0x8cd55591L, 0xc902de4cL, 0xb90bace1L, + 0xbb8205d0L, 0x11a86248L, 0x7574a99eL, 0xb77f19b6L, 0xe0a9dc09L, + 0x662d09a1L, 0xc4324633L, 0xe85a1f02L, 0x09f0be8cL, 0x4a99a025L, + 0x1d6efe10L, 0x1ab93d1dL, 0x0ba5a4dfL, 0xa186f20fL, 0x2868f169L, + 0xdcb7da83L, 0x573906feL, 0xa1e2ce9bL, 0x4fcd7f52L, 0x50115e01L, + 0xa70683faL, 0xa002b5c4L, 0x0de6d027L, 0x9af88c27L, 0x773f8641L, + 0xc3604c06L, 0x61a806b5L, 0xf0177a28L, 0xc0f586e0L, 0x006058aaL, + 0x30dc7d62L, 0x11e69ed7L, 0x2338ea63L, 0x53c2dd94L, 0xc2c21634L, + 0xbbcbee56L, 0x90bcb6deL, 0xebfc7da1L, 0xce591d76L, 0x6f05e409L, + 0x4b7c0188L, 0x39720a3dL, 0x7c927c24L, 0x86e3725fL, 0x724d9db9L, + 0x1ac15bb4L, 0xd39eb8fcL, 0xed545578L, 0x08fca5b5L, 0xd83d7cd3L, + 0x4dad0fc4L, 0x1e50ef5eL, 0xb161e6f8L, 0xa28514d9L, 0x6c51133cL, + 0x6fd5c7e7L, 0x56e14ec4L, 0x362abfceL, 0xddc6c837L, 0xd79a3234L, + 0x92638212L, 0x670efa8eL, 0x406000e0L, 0x3a39ce37L, 0xd3faf5cfL, + 0xabc27737L, 0x5ac52d1bL, 0x5cb0679eL, 0x4fa33742L, 0xd3822740L, + 0x99bc9bbeL, 0xd5118e9dL, 0xbf0f7315L, 0xd62d1c7eL, 0xc700c47bL, + 0xb78c1b6bL, 0x21a19045L, 0xb26eb1beL, 0x6a366eb4L, 0x5748ab2fL, + 0xbc946e79L, 0xc6a376d2L, 0x6549c2c8L, 0x530ff8eeL, 0x468dde7dL, + 0xd5730a1dL, 0x4cd04dc6L, 0x2939bbdbL, 0xa9ba4650L, 0xac9526e8L, + 0xbe5ee304L, 0xa1fad5f0L, 0x6a2d519aL, 0x63ef8ce2L, 0x9a86ee22L, + 0xc089c2b8L, 0x43242ef6L, 0xa51e03aaL, 0x9cf2d0a4L, 0x83c061baL, + 0x9be96a4dL, 0x8fe51550L, 0xba645bd6L, 0x2826a2f9L, 0xa73a3ae1L, + 0x4ba99586L, 0xef5562e9L, 0xc72fefd3L, 0xf752f7daL, 0x3f046f69L, + 0x77fa0a59L, 0x80e4a915L, 0x87b08601L, 0x9b09e6adL, 0x3b3ee593L, + 0xe990fd5aL, 0x9e34d797L, 0x2cf0b7d9L, 0x022b8b51L, 0x96d5ac3aL, + 0x017da67dL, 0xd1cf3ed6L, 0x7c7d2d28L, 0x1f9f25cfL, 0xadf2b89bL, + 0x5ad6b472L, 0x5a88f54cL, 0xe029ac71L, 0xe019a5e6L, 0x47b0acfdL, + 0xed93fa9bL, 0xe8d3c48dL, 0x283b57ccL, 0xf8d56629L, 0x79132e28L, + 0x785f0191L, 0xed756055L, 0xf7960e44L, 0xe3d35e8cL, 0x15056dd4L, + 0x88f46dbaL, 0x03a16125L, 0x0564f0bdL, 0xc3eb9e15L, 0x3c9057a2L, + 0x97271aecL, 0xa93a072aL, 0x1b3f6d9bL, 0x1e6321f5L, 0xf59c66fbL, + 0x26dcf319L, 0x7533d928L, 0xb155fdf5L, 0x03563482L, 0x8aba3cbbL, + 0x28517711L, 0xc20ad9f8L, 0xabcc5167L, 0xccad925fL, 0x4de81751L, + 0x3830dc8eL, 0x379d5862L, 0x9320f991L, 0xea7a90c2L, 0xfb3e7bceL, + 0x5121ce64L, 0x774fbe32L, 0xa8b6e37eL, 0xc3293d46L, 0x48de5369L, + 0x6413e680L, 0xa2ae0810L, 0xdd6db224L, 0x69852dfdL, 0x09072166L, + 0xb39a460aL, 0x6445c0ddL, 0x586cdecfL, 0x1c20c8aeL, 0x5bbef7ddL, + 0x1b588d40L, 0xccd2017fL, 0x6bb4e3bbL, 0xdda26a7eL, 0x3a59ff45L, + 0x3e350a44L, 0xbcb4cdd5L, 0x72eacea8L, 0xfa6484bbL, 0x8d6612aeL, + 0xbf3c6f47L, 0xd29be463L, 0x542f5d9eL, 0xaec2771bL, 0xf64e6370L, + 0x740e0d8dL, 0xe75b1357L, 0xf8721671L, 0xaf537d5dL, 0x4040cb08L, + 0x4eb4e2ccL, 0x34d2466aL, 0x0115af84L, 0xe1b00428L, 0x95983a1dL, + 0x06b89fb4L, 0xce6ea048L, 0x6f3f3b82L, 0x3520ab82L, 0x011a1d4bL, + 0x277227f8L, 0x611560b1L, 0xe7933fdcL, 0xbb3a792bL, 0x344525bdL, + 0xa08839e1L, 0x51ce794bL, 0x2f32c9b7L, 0xa01fbac9L, 0xe01cc87eL, + 0xbcc7d1f6L, 0xcf0111c3L, 0xa1e8aac7L, 0x1a908749L, 0xd44fbd9aL, + 0xd0dadecbL, 0xd50ada38L, 0x0339c32aL, 0xc6913667L, 0x8df9317cL, + 0xe0b12b4fL, 0xf79e59b7L, 0x43f5bb3aL, 0xf2d519ffL, 0x27d9459cL, + 0xbf97222cL, 0x15e6fc2aL, 0x0f91fc71L, 0x9b941525L, 0xfae59361L, + 0xceb69cebL, 0xc2a86459L, 0x12baa8d1L, 0xb6c1075eL, 0xe3056a0cL, + 0x10d25065L, 0xcb03a442L, 0xe0ec6e0eL, 0x1698db3bL, 0x4c98a0beL, + 0x3278e964L, 0x9f1f9532L, 0xe0d392dfL, 0xd3a0342bL, 0x8971f21eL, + 0x1b0a7441L, 0x4ba3348cL, 0xc5be7120L, 0xc37632d8L, 0xdf359f8dL, + 0x9b992f2eL, 0xe60b6f47L, 0x0fe3f11dL, 0xe54cda54L, 0x1edad891L, + 0xce6279cfL, 0xcd3e7e6fL, 0x1618b166L, 0xfd2c1d05L, 0x848fd2c5L, + 0xf6fb2299L, 0xf523f357L, 0xa6327623L, 0x93a83531L, 0x56cccd02L, + 0xacf08162L, 0x5a75ebb5L, 0x6e163697L, 0x88d273ccL, 0xde966292L, + 0x81b949d0L, 0x4c50901bL, 0x71c65614L, 0xe6c6c7bdL, 0x327a140aL, + 0x45e1d006L, 0xc3f27b9aL, 0xc9aa53fdL, 0x62a80f00L, 0xbb25bfe2L, + 0x35bdd2f6L, 0x71126905L, 0xb2040222L, 0xb6cbcf7cL, 0xcd769c2bL, + 0x53113ec0L, 0x1640e3d3L, 0x38abbd60L, 0x2547adf0L, 0xba38209cL, + 0xf746ce76L, 0x77afa1c5L, 0x20756060L, 0x85cbfe4eL, 0x8ae88dd8L, + 0x7aaaf9b0L, 0x4cf9aa7eL, 0x1948c25cL, 0x02fb8a8cL, 0x01c36ae4L, + 0xd6ebe1f9L, 0x90d4f869L, 0xa65cdea0L, 0x3f09252dL, 0xc208e69fL, + 0xb74e6132L, 0xce77e25bL, 0x578fdfe3L, 0x3ac372e6L, + }, +}; + +void BF_set_key(BF_KEY *key, size_t len, const uint8_t *data) { + int i; + uint32_t *p, ri, in[2]; + const uint8_t *d, *end; + + memcpy(key, &bf_init, sizeof(BF_KEY)); + p = key->P; + + if (len > ((BF_ROUNDS + 2) * 4)) + len = (BF_ROUNDS + 2) * 4; + + d = data; + end = &data[len]; + for (i = 0; i < BF_ROUNDS + 2; i++) { + ri = *(d++); + if (d >= end) { + d = data; + } + + ri <<= 8; + ri |= *(d++); + if (d >= end) { + d = data; + } + + ri <<= 8; + ri |= *(d++); + if (d >= end) { + d = data; + } + + ri <<= 8; + ri |= *(d++); + if (d >= end) { + d = data; + } + + p[i] ^= ri; + } + + in[0] = 0L; + in[1] = 0L; + for (i = 0; i < BF_ROUNDS + 2; i += 2) { + BF_encrypt(in, key); + p[i] = in[0]; + p[i + 1] = in[1]; + } + + p = key->S; + for (i = 0; i < 4 * 256; i += 2) { + BF_encrypt(in, key); + p[i] = in[0]; + p[i + 1] = in[1]; + } +} diff --git a/external/boringssl/decrepit/cast/CMakeLists.txt b/external/boringssl/decrepit/cast/CMakeLists.txt new file mode 100644 index 0000000000..2830381a6d --- /dev/null +++ b/external/boringssl/decrepit/cast/CMakeLists.txt @@ -0,0 +1,10 @@ +include_directories(../../include) + +add_library( + cast + + OBJECT + + cast.c + cast_tables.c +) diff --git a/external/boringssl/decrepit/cast/cast.c b/external/boringssl/decrepit/cast/cast.c new file mode 100644 index 0000000000..75ea656717 --- /dev/null +++ b/external/boringssl/decrepit/cast/cast.c @@ -0,0 +1,408 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.]. */ + +#include + +#if defined(OPENSSL_WINDOWS) +OPENSSL_MSVC_PRAGMA(warning(push, 3)) +#include +OPENSSL_MSVC_PRAGMA(warning(pop)) +#endif + +#include "internal.h" +#include "../macros.h" + + +void CAST_ecb_encrypt(const uint8_t *in, uint8_t *out, const CAST_KEY *ks, + int enc) { + uint32_t d[2]; + + n2l(in, d[0]); + n2l(in, d[1]); + if (enc) { + CAST_encrypt(d, ks); + } else { + CAST_decrypt(d, ks); + } + l2n(d[0], out); + l2n(d[1], out); +} + +#if defined(OPENSSL_WINDOWS) && defined(_MSC_VER) +#define ROTL(a, n) (_lrotl(a, n)) +#else +#define ROTL(a, n) ((((a) << (n)) | ((a) >> ((-(n))&31))) & 0xffffffffL) +#endif + +#define E_CAST(n, key, L, R, OP1, OP2, OP3) \ + { \ + uint32_t a, b, c, d; \ + t = (key[n * 2] OP1 R) & 0xffffffff; \ + t = ROTL(t, (key[n * 2 + 1])); \ + a = CAST_S_table0[(t >> 8) & 0xff]; \ + b = CAST_S_table1[(t)&0xff]; \ + c = CAST_S_table2[(t >> 24) & 0xff]; \ + d = CAST_S_table3[(t >> 16) & 0xff]; \ + L ^= (((((a OP2 b)&0xffffffffL)OP3 c) & 0xffffffffL)OP1 d) & 0xffffffffL; \ + } + +void CAST_encrypt(uint32_t *data, const CAST_KEY *key) { + uint32_t l, r, t; + const uint32_t *k; + + k = &key->data[0]; + l = data[0]; + r = data[1]; + + E_CAST(0, k, l, r, +, ^, -); + E_CAST(1, k, r, l, ^, -, +); + E_CAST(2, k, l, r, -, +, ^); + E_CAST(3, k, r, l, +, ^, -); + E_CAST(4, k, l, r, ^, -, +); + E_CAST(5, k, r, l, -, +, ^); + E_CAST(6, k, l, r, +, ^, -); + E_CAST(7, k, r, l, ^, -, +); + E_CAST(8, k, l, r, -, +, ^); + E_CAST(9, k, r, l, +, ^, -); + E_CAST(10, k, l, r, ^, -, +); + E_CAST(11, k, r, l, -, +, ^); + + if (!key->short_key) { + E_CAST(12, k, l, r, +, ^, -); + E_CAST(13, k, r, l, ^, -, +); + E_CAST(14, k, l, r, -, +, ^); + E_CAST(15, k, r, l, +, ^, -); + } + + data[1] = l & 0xffffffffL; + data[0] = r & 0xffffffffL; +} + +void CAST_decrypt(uint32_t *data, const CAST_KEY *key) { + uint32_t l, r, t; + const uint32_t *k; + + k = &key->data[0]; + l = data[0]; + r = data[1]; + + if (!key->short_key) { + E_CAST(15, k, l, r, +, ^, -); + E_CAST(14, k, r, l, -, +, ^); + E_CAST(13, k, l, r, ^, -, +); + E_CAST(12, k, r, l, +, ^, -); + } + + E_CAST(11, k, l, r, -, +, ^); + E_CAST(10, k, r, l, ^, -, +); + E_CAST(9, k, l, r, +, ^, -); + E_CAST(8, k, r, l, -, +, ^); + E_CAST(7, k, l, r, ^, -, +); + E_CAST(6, k, r, l, +, ^, -); + E_CAST(5, k, l, r, -, +, ^); + E_CAST(4, k, r, l, ^, -, +); + E_CAST(3, k, l, r, +, ^, -); + E_CAST(2, k, r, l, -, +, ^); + E_CAST(1, k, l, r, ^, -, +); + E_CAST(0, k, r, l, +, ^, -); + + data[1] = l & 0xffffffffL; + data[0] = r & 0xffffffffL; +} + +void CAST_cbc_encrypt(const uint8_t *in, uint8_t *out, long length, + const CAST_KEY *ks, uint8_t *iv, int enc) { + uint32_t tin0, tin1; + uint32_t tout0, tout1, xor0, xor1; + long l = length; + uint32_t tin[2]; + + if (enc) { + n2l(iv, tout0); + n2l(iv, tout1); + iv -= 8; + for (l -= 8; l >= 0; l -= 8) { + n2l(in, tin0); + n2l(in, tin1); + tin0 ^= tout0; + tin1 ^= tout1; + tin[0] = tin0; + tin[1] = tin1; + CAST_encrypt(tin, ks); + tout0 = tin[0]; + tout1 = tin[1]; + l2n(tout0, out); + l2n(tout1, out); + } + if (l != -8) { + n2ln(in, tin0, tin1, l + 8); + tin0 ^= tout0; + tin1 ^= tout1; + tin[0] = tin0; + tin[1] = tin1; + CAST_encrypt(tin, ks); + tout0 = tin[0]; + tout1 = tin[1]; + l2n(tout0, out); + l2n(tout1, out); + } + l2n(tout0, iv); + l2n(tout1, iv); + } else { + n2l(iv, xor0); + n2l(iv, xor1); + iv -= 8; + for (l -= 8; l >= 0; l -= 8) { + n2l(in, tin0); + n2l(in, tin1); + tin[0] = tin0; + tin[1] = tin1; + CAST_decrypt(tin, ks); + tout0 = tin[0] ^ xor0; + tout1 = tin[1] ^ xor1; + l2n(tout0, out); + l2n(tout1, out); + xor0 = tin0; + xor1 = tin1; + } + if (l != -8) { + n2l(in, tin0); + n2l(in, tin1); + tin[0] = tin0; + tin[1] = tin1; + CAST_decrypt(tin, ks); + tout0 = tin[0] ^ xor0; + tout1 = tin[1] ^ xor1; + l2nn(tout0, tout1, out, l + 8); + xor0 = tin0; + xor1 = tin1; + } + l2n(xor0, iv); + l2n(xor1, iv); + } + tin0 = tin1 = tout0 = tout1 = xor0 = xor1 = 0; + tin[0] = tin[1] = 0; +} + +#define CAST_exp(l, A, a, n) \ + A[n / 4] = l; \ + a[n + 3] = (l)&0xff; \ + a[n + 2] = (l >> 8) & 0xff; \ + a[n + 1] = (l >> 16) & 0xff; \ + a[n + 0] = (l >> 24) & 0xff; +#define S4 CAST_S_table4 +#define S5 CAST_S_table5 +#define S6 CAST_S_table6 +#define S7 CAST_S_table7 + +void CAST_set_key(CAST_KEY *key, size_t len, const uint8_t *data) { + uint32_t x[16]; + uint32_t z[16]; + uint32_t k[32]; + uint32_t X[4], Z[4]; + uint32_t l, *K; + size_t i; + + for (i = 0; i < 16; i++) { + x[i] = 0; + } + + if (len > 16) { + len = 16; + } + + for (i = 0; i < len; i++) { + x[i] = data[i]; + } + + if (len <= 10) { + key->short_key = 1; + } else { + key->short_key = 0; + } + + K = &k[0]; + X[0] = ((x[0] << 24) | (x[1] << 16) | (x[2] << 8) | x[3]) & 0xffffffffL; + X[1] = ((x[4] << 24) | (x[5] << 16) | (x[6] << 8) | x[7]) & 0xffffffffL; + X[2] = ((x[8] << 24) | (x[9] << 16) | (x[10] << 8) | x[11]) & 0xffffffffL; + X[3] = ((x[12] << 24) | (x[13] << 16) | (x[14] << 8) | x[15]) & 0xffffffffL; + + for (;;) { + l = X[0] ^ S4[x[13]] ^ S5[x[15]] ^ S6[x[12]] ^ S7[x[14]] ^ S6[x[8]]; + CAST_exp(l, Z, z, 0); + l = X[2] ^ S4[z[0]] ^ S5[z[2]] ^ S6[z[1]] ^ S7[z[3]] ^ S7[x[10]]; + CAST_exp(l, Z, z, 4); + l = X[3] ^ S4[z[7]] ^ S5[z[6]] ^ S6[z[5]] ^ S7[z[4]] ^ S4[x[9]]; + CAST_exp(l, Z, z, 8); + l = X[1] ^ S4[z[10]] ^ S5[z[9]] ^ S6[z[11]] ^ S7[z[8]] ^ S5[x[11]]; + CAST_exp(l, Z, z, 12); + + K[0] = S4[z[8]] ^ S5[z[9]] ^ S6[z[7]] ^ S7[z[6]] ^ S4[z[2]]; + K[1] = S4[z[10]] ^ S5[z[11]] ^ S6[z[5]] ^ S7[z[4]] ^ S5[z[6]]; + K[2] = S4[z[12]] ^ S5[z[13]] ^ S6[z[3]] ^ S7[z[2]] ^ S6[z[9]]; + K[3] = S4[z[14]] ^ S5[z[15]] ^ S6[z[1]] ^ S7[z[0]] ^ S7[z[12]]; + + l = Z[2] ^ S4[z[5]] ^ S5[z[7]] ^ S6[z[4]] ^ S7[z[6]] ^ S6[z[0]]; + CAST_exp(l, X, x, 0); + l = Z[0] ^ S4[x[0]] ^ S5[x[2]] ^ S6[x[1]] ^ S7[x[3]] ^ S7[z[2]]; + CAST_exp(l, X, x, 4); + l = Z[1] ^ S4[x[7]] ^ S5[x[6]] ^ S6[x[5]] ^ S7[x[4]] ^ S4[z[1]]; + CAST_exp(l, X, x, 8); + l = Z[3] ^ S4[x[10]] ^ S5[x[9]] ^ S6[x[11]] ^ S7[x[8]] ^ S5[z[3]]; + CAST_exp(l, X, x, 12); + + K[4] = S4[x[3]] ^ S5[x[2]] ^ S6[x[12]] ^ S7[x[13]] ^ S4[x[8]]; + K[5] = S4[x[1]] ^ S5[x[0]] ^ S6[x[14]] ^ S7[x[15]] ^ S5[x[13]]; + K[6] = S4[x[7]] ^ S5[x[6]] ^ S6[x[8]] ^ S7[x[9]] ^ S6[x[3]]; + K[7] = S4[x[5]] ^ S5[x[4]] ^ S6[x[10]] ^ S7[x[11]] ^ S7[x[7]]; + + l = X[0] ^ S4[x[13]] ^ S5[x[15]] ^ S6[x[12]] ^ S7[x[14]] ^ S6[x[8]]; + CAST_exp(l, Z, z, 0); + l = X[2] ^ S4[z[0]] ^ S5[z[2]] ^ S6[z[1]] ^ S7[z[3]] ^ S7[x[10]]; + CAST_exp(l, Z, z, 4); + l = X[3] ^ S4[z[7]] ^ S5[z[6]] ^ S6[z[5]] ^ S7[z[4]] ^ S4[x[9]]; + CAST_exp(l, Z, z, 8); + l = X[1] ^ S4[z[10]] ^ S5[z[9]] ^ S6[z[11]] ^ S7[z[8]] ^ S5[x[11]]; + CAST_exp(l, Z, z, 12); + + K[8] = S4[z[3]] ^ S5[z[2]] ^ S6[z[12]] ^ S7[z[13]] ^ S4[z[9]]; + K[9] = S4[z[1]] ^ S5[z[0]] ^ S6[z[14]] ^ S7[z[15]] ^ S5[z[12]]; + K[10] = S4[z[7]] ^ S5[z[6]] ^ S6[z[8]] ^ S7[z[9]] ^ S6[z[2]]; + K[11] = S4[z[5]] ^ S5[z[4]] ^ S6[z[10]] ^ S7[z[11]] ^ S7[z[6]]; + + l = Z[2] ^ S4[z[5]] ^ S5[z[7]] ^ S6[z[4]] ^ S7[z[6]] ^ S6[z[0]]; + CAST_exp(l, X, x, 0); + l = Z[0] ^ S4[x[0]] ^ S5[x[2]] ^ S6[x[1]] ^ S7[x[3]] ^ S7[z[2]]; + CAST_exp(l, X, x, 4); + l = Z[1] ^ S4[x[7]] ^ S5[x[6]] ^ S6[x[5]] ^ S7[x[4]] ^ S4[z[1]]; + CAST_exp(l, X, x, 8); + l = Z[3] ^ S4[x[10]] ^ S5[x[9]] ^ S6[x[11]] ^ S7[x[8]] ^ S5[z[3]]; + CAST_exp(l, X, x, 12); + + K[12] = S4[x[8]] ^ S5[x[9]] ^ S6[x[7]] ^ S7[x[6]] ^ S4[x[3]]; + K[13] = S4[x[10]] ^ S5[x[11]] ^ S6[x[5]] ^ S7[x[4]] ^ S5[x[7]]; + K[14] = S4[x[12]] ^ S5[x[13]] ^ S6[x[3]] ^ S7[x[2]] ^ S6[x[8]]; + K[15] = S4[x[14]] ^ S5[x[15]] ^ S6[x[1]] ^ S7[x[0]] ^ S7[x[13]]; + if (K != k) { + break; + } + K += 16; + } + + for (i = 0; i < 16; i++) { + key->data[i * 2] = k[i]; + key->data[i * 2 + 1] = ((k[i + 16]) + 16) & 0x1f; + } +} + +/* The input and output encrypted as though 64bit cfb mode is being used. The + * extra state information to record how much of the 64bit block we have used + * is contained in *num. */ +void CAST_cfb64_encrypt(const uint8_t *in, uint8_t *out, long length, + const CAST_KEY *schedule, uint8_t *ivec, int *num, + int enc) { + uint32_t v0, v1, t; + int n = *num; + long l = length; + uint32_t ti[2]; + uint8_t *iv, c, cc; + + iv = ivec; + if (enc) { + while (l--) { + if (n == 0) { + n2l(iv, v0); + ti[0] = v0; + n2l(iv, v1); + ti[1] = v1; + CAST_encrypt((uint32_t *)ti, schedule); + iv = ivec; + t = ti[0]; + l2n(t, iv); + t = ti[1]; + l2n(t, iv); + iv = ivec; + } + c = *(in++) ^ iv[n]; + *(out++) = c; + iv[n] = c; + n = (n + 1) & 0x07; + } + } else { + while (l--) { + if (n == 0) { + n2l(iv, v0); + ti[0] = v0; + n2l(iv, v1); + ti[1] = v1; + CAST_encrypt((uint32_t *)ti, schedule); + iv = ivec; + t = ti[0]; + l2n(t, iv); + t = ti[1]; + l2n(t, iv); + iv = ivec; + } + cc = *(in++); + c = iv[n]; + iv[n] = cc; + *(out++) = c ^ cc; + n = (n + 1) & 0x07; + } + } + v0 = v1 = ti[0] = ti[1] = t = c = cc = 0; + *num = n; +} diff --git a/external/boringssl/decrepit/cast/cast_tables.c b/external/boringssl/decrepit/cast/cast_tables.c new file mode 100644 index 0000000000..6808aa894b --- /dev/null +++ b/external/boringssl/decrepit/cast/cast_tables.c @@ -0,0 +1,428 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include "internal.h" + + +const uint32_t CAST_S_table0[256] = { + 0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, 0x9c004dd3, + 0x6003e540, 0xcf9fc949, 0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, + 0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e, 0x28683b6f, 0xc07fd059, + 0xff2379c8, 0x775f50e2, 0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d, + 0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1, 0xaa54166b, + 0x22568e3a, 0xa2d341d0, 0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, + 0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7, 0xb82cbaef, 0xd751d159, + 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935, + 0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290, 0xe93b159f, + 0xb48ee411, 0x4bff345d, 0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, + 0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50, 0x882240f2, 0x0c6e4f38, + 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe, + 0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5, 0x6a390493, + 0xe63d37e0, 0x2a54f6b3, 0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, + 0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167, 0x38901091, 0xc6b505eb, + 0x84c7cb8c, 0x2ad75a0f, 0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291, + 0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d, 0x73e2bb14, + 0xa0bebc3c, 0x54623779, 0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, + 0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2, 0x81383f05, 0x6963c5c8, + 0x76cb5ad6, 0xd49974c9, 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511, + 0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241, 0x051ef495, + 0xaa573b04, 0x4a805d8d, 0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, + 0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5, 0x6b54bfab, 0x2b0b1426, + 0xab4cc9d7, 0x449ccd82, 0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324, + 0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3, 0xd5bd9e98, + 0xe31231b2, 0x2ad5ad6c, 0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, + 0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc, 0x7b5a41f0, 0xd37cfbad, + 0x1b069505, 0x41ece491, 0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d, + 0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da, 0x4736f464, + 0x5ad328d8, 0xb347cc96, 0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, + 0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a, 0x3f04442f, 0x6188b153, + 0xe0397a2e, 0x5727cb79, 0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d, + 0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4, 0xb11c3274, + 0xdd24cb9e, 0x7e1c54bd, 0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, + 0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6, 0x580304f0, 0xca042cf1, + 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9, + 0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf, 0x700b45e1, + 0xd5ea50f1, 0x85a92872, 0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, + 0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c, 0x474d6ad7, 0x7c0c5e5c, + 0xd1231959, 0x381b7298, 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e, + 0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, 0xe1e696ff, + 0xb141ab08, 0x7cca89b9, 0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, + 0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf, +}; + +const uint32_t CAST_S_table1[256] = { + 0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, 0xeec5207a, + 0x55889c94, 0x72fc0651, 0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, + 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3, 0xa0b52f7b, 0x59e83605, + 0xee15b094, 0xe9ffd909, 0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb, + 0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb, 0xe4e7ef5b, + 0x25a1ff41, 0xe180f806, 0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, + 0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b, 0xe113c85b, 0xacc40083, + 0xd7503525, 0xf7ea615f, 0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359, + 0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181, 0x39f7627f, + 0x361e3084, 0xe4eb573b, 0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, + 0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c, 0x10843094, 0x2537a95e, + 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34, + 0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c, 0x1d804366, + 0x721d9bfd, 0xa58684bb, 0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, + 0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd, 0xc5d655dd, 0xeb667064, + 0x77840b4d, 0xa1b6a801, 0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860, + 0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf, 0x68561be6, + 0x83ca6b94, 0x2d6ed23b, 0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, + 0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304, 0x81ed6f61, 0x20e74364, + 0xb45e1378, 0xde18639b, 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b, + 0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402, 0x1ba4fe5b, + 0xa4b09f6b, 0x1ca815cf, 0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, + 0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c, 0xee41e729, 0x6e1d2d7c, + 0x50045286, 0x1e6685f3, 0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13, + 0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6, 0xa02b1741, + 0x7cbad9a2, 0x2180036f, 0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, + 0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6, 0xcdf0b680, 0x17844d3b, + 0x31eef84d, 0x7e0824e4, 0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6, + 0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54, 0x157fd7fa, + 0xef8579cc, 0xd152de58, 0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, + 0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906, 0xb8da230c, 0x80823028, + 0xdcdef3c8, 0xd35fb171, 0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d, + 0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc, 0x301e16e6, + 0x273be979, 0xb0ffeaa6, 0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, + 0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4, 0xdc8637a0, 0x16a7d3b1, + 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6, + 0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb, 0x5eea29cb, + 0x145892f5, 0x91584f7f, 0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, + 0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249, 0xb284600c, 0xd835731d, + 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa, + 0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, 0xa345415e, + 0x5c038323, 0x3e5d3bb9, 0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, + 0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1, +}; + +const uint32_t CAST_S_table2[256] = { + 0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, 0x369fe44b, + 0x8c1fc644, 0xaececa90, 0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, + 0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5, 0x11107d9f, 0x07647db9, + 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e, + 0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee, 0x825b1bfd, + 0x9255c5ed, 0x1257a240, 0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, + 0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5, 0xa8c01db7, 0x579fc264, + 0x67094f31, 0xf2bd3f5f, 0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b, + 0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c, 0x4a012d6e, + 0xc5884a28, 0xccc36f71, 0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, + 0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04, 0xa747d2d0, 0x1651192e, + 0xaf70bf3e, 0x58c31380, 0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82, + 0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0, 0x1eac5790, + 0x796fb449, 0x8252dc15, 0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, + 0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2, 0x23efe941, 0xa903f12e, + 0x60270df2, 0x0276e4b6, 0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176, + 0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83, 0x340ce5c8, + 0x96bbb682, 0x93b4b148, 0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, + 0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc, 0x8b907cee, 0xb51fd240, + 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341, + 0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9, 0xbda8229c, + 0x127dadaa, 0x438a074e, 0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, + 0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51, 0x68cc7bfb, 0xd90f2788, + 0x12490181, 0x5de5ffd4, 0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f, + 0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623, 0x193cbcfa, + 0x27627545, 0x825cf47a, 0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, + 0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b, 0x285ba1c8, 0x3c62f44f, + 0x35c0eaa5, 0xe805d231, 0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b, + 0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11, 0x236a5cae, + 0x12deca4d, 0x2c3f8cc5, 0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, + 0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45, 0x3a609437, 0xec00c9a9, + 0x44715253, 0x0a874b49, 0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536, + 0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1, 0x006e1888, + 0xa2e53f55, 0xb9e6d4bc, 0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, + 0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0, 0x947b0001, 0x570075d2, + 0xf9bb88f8, 0x8942019e, 0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69, + 0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2, 0x61efc8c2, + 0xf1ac2571, 0xcc8239c2, 0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, + 0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49, 0x5727c148, 0x2be98a1d, + 0x8ab41738, 0x20e1be24, 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d, + 0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, 0x9c305a00, + 0x52bce688, 0x1b03588a, 0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, + 0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783, +}; + +const uint32_t CAST_S_table3[256] = { + 0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, 0x64ad8c57, + 0x85510443, 0xfa020ed1, 0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, + 0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf, 0x28147f5f, 0x4fa2b8cd, + 0xc9430040, 0x0cc32220, 0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15, + 0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f, 0x0c13fefe, + 0x081b08ca, 0x05170121, 0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, + 0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25, 0xce84ffdf, 0xf5718801, + 0x3dd64b04, 0xa26f263b, 0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5, + 0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061, 0x11b638e1, + 0x72500e03, 0xf80eb2bb, 0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, + 0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5, 0x4d351805, 0x7f3d5ce3, + 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d, + 0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8, 0x3fb6180c, + 0x18f8931e, 0x281658e6, 0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, + 0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23, 0x69dead38, 0x1574ca16, + 0xdf871b62, 0x211c40b7, 0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003, + 0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de, 0x00eae4a7, + 0x0ce5c2ec, 0x4db4bba6, 0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, + 0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119, 0x6e85cb75, 0xbe07c002, + 0xc2325577, 0x893ff4ec, 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24, + 0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a, 0xeca1d7c7, + 0x041afa32, 0x1d16625a, 0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, + 0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79, 0x026a4ceb, 0x52437eff, + 0x2f8f76b4, 0x0df980a5, 0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df, + 0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254, 0xe5b6a035, + 0x213d42f6, 0x2c1c7c26, 0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, + 0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab, 0x63315c21, 0x5e0a72ec, + 0x49bafefd, 0x187908d9, 0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7, + 0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1, 0x1f9af36e, + 0xcfcbd12f, 0xc1de8417, 0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, + 0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2, 0x6f7de532, 0x58fd7eb6, + 0xd01ee900, 0x24adffc2, 0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2, + 0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415, 0x7fbb977f, + 0xaf9eb3db, 0x29c9ed2a, 0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, + 0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919, 0x77079103, 0xdea03af6, + 0x78a8565e, 0xdee356df, 0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef, + 0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb, 0xf470c4b2, + 0xf3e0eb5b, 0xd6cc9876, 0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, + 0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab, 0xb5676e69, 0x9bd3ddda, + 0xdf7e052f, 0xdb25701c, 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04, + 0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, 0x932bcdf6, + 0xb657c34d, 0x4edfd282, 0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, + 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2, +}; + +const uint32_t CAST_S_table4[256] = { + 0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff, 0x1dd358f5, + 0x44dd9d44, 0x1731167f, 0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, + 0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a, 0xe6a2e77f, 0xf0c720cd, + 0xc4494816, 0xccf5c180, 0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff, + 0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d, 0x248eb6fb, + 0x8dba1cfe, 0x41a99b02, 0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725, + 0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a, 0xf2f3f763, 0x68af8040, + 0xed0c9e56, 0x11b4958b, 0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7, + 0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, 0x0c05372a, 0x578535f2, + 0x2261be02, 0xd642a0c9, 0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, + 0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981, 0x5c1ff900, 0xfe38d399, + 0x0c4eff0b, 0x062407ea, 0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774, + 0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, 0xdf65001f, 0x0ec50966, + 0xdfdd55bc, 0x29de0655, 0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, + 0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2, 0xbcf3f0aa, 0x87ac36e9, + 0xe53a7426, 0x01b3d82b, 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910, + 0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, 0x636737b6, 0x50f5b616, + 0xf24766e3, 0x8eca36c1, 0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4, + 0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da, 0x26e46695, 0xb7566419, + 0xf654efc5, 0xd08d58b7, 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049, + 0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd, 0x9e0885f9, + 0x68cb3e47, 0x086c010f, 0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6, + 0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba, 0x0ab378d5, 0xd951fb0c, + 0xded7da56, 0x4124bbe4, 0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be, + 0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280, 0x05687715, + 0x646c6bd7, 0x44904db3, 0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6, + 0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840, 0x76f0ae02, 0x083be84d, + 0x28421c9a, 0x44489406, 0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4, + 0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, 0x3ca5d717, 0x7d161bba, + 0x9cad9010, 0xaf462ba2, 0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, + 0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7, 0x445f7382, 0x175683f4, + 0xcdc66a97, 0x70be0288, 0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5, + 0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, 0x1c5c1572, 0xf6721b2c, + 0x1ad2fff3, 0x8c25404e, 0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, + 0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e, 0x44094f85, 0x3f481d87, + 0xfcfeae7b, 0x77b5ff76, 0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801, + 0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, 0xdf3b0874, 0x95055110, + 0x1b5ad7a8, 0xf61ed5ad, 0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58, + 0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0, 0x5ce96c28, 0xe176eda3, + 0x6bac307f, 0x376829d2, 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20, + 0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a, 0xeeb9491d, + 0x34010718, 0xbb30cab8, 0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, + 0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4, +}; + +const uint32_t CAST_S_table5[256] = { + 0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7, 0x016843b4, + 0xeced5cbc, 0x325553ac, 0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, + 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138, 0x33f14961, 0xc01937bd, + 0xf506c6da, 0xe4625e7e, 0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367, + 0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d, 0x09a8486f, + 0xa888614a, 0x2900af98, 0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c, + 0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072, 0xfd41197e, 0x9305a6b0, + 0xe86be3da, 0x74bed3cd, 0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3, + 0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, 0x5c3d9c01, 0x64bdb941, + 0x2c0e636a, 0xba7dd9cd, 0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, + 0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8, 0x284caf89, 0xaa928223, + 0x9334be53, 0x3b3a21bf, 0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9, + 0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, 0x5b7c5ecc, 0x221db3a6, + 0x9a69a02f, 0x68818a54, 0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, + 0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387, 0x53bddb65, 0xe76ffbe7, + 0xe967fd78, 0x0ba93563, 0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc, + 0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, 0xe81f994f, 0x9528cd89, + 0xfd339fed, 0xb87834bf, 0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be, + 0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf, 0x4ec75b95, 0x24f2c3c0, + 0x42d15d99, 0xcd0d7fa0, 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f, + 0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af, 0x692573e4, + 0xe9a9d848, 0xf3160289, 0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853, + 0x20951063, 0x4576698d, 0xb6fad407, 0x592af950, 0x36f73523, 0x4cfb6e87, + 0x7da4cec0, 0x6c152daa, 0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f, + 0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d, 0x48b9d585, + 0xdc049441, 0xc8098f9b, 0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751, + 0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be, 0xbf32679d, 0xd45b5b75, + 0xb353fd00, 0xcbb0e358, 0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13, + 0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, 0x47cf8e7a, 0xb6c85283, + 0x3cc2acfb, 0x3fc06976, 0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, + 0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0, 0x3007cd3e, 0x74719eef, + 0xdc872681, 0x073340d4, 0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891, + 0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, 0x6fe4ac98, 0xb173ecc0, + 0xbc60b42a, 0x953498da, 0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, + 0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc, 0xe8816f4a, 0x3814f200, + 0xa3f94043, 0x9c7a54c2, 0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084, + 0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, 0xba5ac7b5, 0xb6f6deaf, + 0x3a479c3a, 0x5302da25, 0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b, + 0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121, 0xb81a928a, 0x60ed5869, + 0x97c55b96, 0xeaec991b, 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5, + 0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1, 0xf544edeb, + 0xb0e93524, 0xbebb8fbd, 0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, + 0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f, +}; + +const uint32_t CAST_S_table6[256] = { + 0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f, 0xab9bc912, + 0xde6008a1, 0x2028da1f, 0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, + 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de, 0xa05fbcf6, 0xcd4181e9, + 0xe150210c, 0xe24ef1bd, 0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43, + 0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be, 0xbaeeadf4, + 0x1286becf, 0xb6eacb19, 0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9, + 0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2, 0x107789be, 0xb3b2e9ce, + 0x0502aa8f, 0x0bc0351e, 0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516, + 0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, 0x334266ce, 0x8c9341b7, + 0xd0d854c0, 0xcb3a6c88, 0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, + 0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816, 0x0a961288, 0xe1a5c06e, + 0x13749e67, 0x72fc081a, 0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756, + 0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, 0xbc8ec511, 0x38bc46e9, + 0xc6e6fa14, 0xbae8584a, 0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, + 0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264, 0x92544a8b, 0x009b4fc3, + 0xaba68ced, 0x9ac96f78, 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688, + 0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, 0xf7debb85, 0x61fe033c, + 0x16746233, 0x3c034c28, 0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802, + 0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3, 0x0c4fb99a, 0xbb325778, + 0x3ec6d97b, 0x6e77a6a9, 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7, + 0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32, 0xebd4e7be, + 0xbe8b9d2d, 0x7979fb06, 0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858, + 0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033, 0xf28ebfb0, 0xf5b9c310, + 0xa0eac280, 0x08b9767a, 0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a, + 0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef, 0x4eeb8476, + 0x488dcf25, 0x36c9d566, 0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df, + 0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509, 0xf22b017d, 0xa4173f70, + 0xdd1e16c3, 0x15e0d7f9, 0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962, + 0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, 0x93d29a22, 0xe32dbf9a, + 0x058745b9, 0x3453dc1e, 0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, + 0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c, 0x66626c1c, 0x7154c24c, + 0xea082b2a, 0x93eb2939, 0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c, + 0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, 0xd3a0c108, 0xa1e7160e, + 0xe4f2dfa6, 0x693ed285, 0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, + 0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301, 0xc79f022f, 0x3c997e7e, + 0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be, + 0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, 0x5592a33d, 0xb5229301, + 0xcfd2a87f, 0x60aeb767, 0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2, + 0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647, 0x97fd61a9, 0xea7759f4, + 0x2d57539d, 0x569a58cf, 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914, + 0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc, 0x3d40f021, + 0xc3c0bdae, 0x4958c24c, 0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, + 0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3, +}; + +const uint32_t CAST_S_table7[256] = { + 0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7, 0xe6c1121b, + 0x0e241600, 0x052ce8b5, 0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, + 0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc, 0xde9adeb1, 0x0a0cc32c, + 0xbe197029, 0x84a00940, 0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd, + 0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831, 0x3f8f95e7, + 0x72df191b, 0x7580330d, 0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164, + 0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2, 0x12a8ddec, 0xfdaa335d, + 0x176f43e8, 0x71fb46d4, 0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862, + 0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, 0x4cfde06f, 0xc28ec4b8, + 0x57e8726e, 0x647a78fc, 0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, + 0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c, 0xbbd35049, 0x2998df04, + 0x980cf42a, 0x9b6df491, 0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e, + 0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, 0x3cf1d2e2, 0x19b47a38, + 0x424f7618, 0x35856039, 0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, + 0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8, 0x7170c608, 0x2d5e3354, + 0xd4de495a, 0x64c6d006, 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42, + 0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, 0xf8d7e54e, 0x3e378160, + 0x7895cda5, 0x859c15a5, 0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, + 0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472, 0x835ffcb8, 0x6df4c1f2, + 0x96f5b195, 0xfd0af0fc, 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225, + 0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187, 0xea7a6e98, + 0x7cd16efc, 0x1436876c, 0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441, + 0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb, 0xa842eedf, 0xfdba60b4, + 0xf1907b75, 0x20e3030f, 0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054, + 0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d, 0x844a1be5, + 0xbae7dfdc, 0x42cbda70, 0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c, + 0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc, 0x77853b53, 0x37effcb5, + 0xc5068778, 0xe580b3e6, 0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c, + 0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, 0xdd06caa2, 0x37df932b, + 0xc4248289, 0xacf3ebc3, 0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, + 0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4, 0xe87b40e4, 0xe98ea084, + 0x5889e9e1, 0xefd390fc, 0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101, + 0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, 0x646f1282, 0x7523d24a, + 0xe0779695, 0xf9c17a8f, 0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, + 0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e, 0x11403092, 0x00da6d77, + 0x4a0cdd61, 0xad1f4603, 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a, + 0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, 0x2de705ca, 0x8951570f, + 0xdf09822b, 0xbd691a6c, 0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819, + 0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384, 0x5938fa0f, 0x42399ef3, + 0x36997b07, 0x0e84093d, 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c, + 0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82, 0x0d2059d1, + 0xa466bb1e, 0xf8da0a82, 0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d, + 0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e, +}; diff --git a/external/boringssl/decrepit/cast/internal.h b/external/boringssl/decrepit/cast/internal.h new file mode 100644 index 0000000000..15e222264c --- /dev/null +++ b/external/boringssl/decrepit/cast/internal.h @@ -0,0 +1,81 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_CAST_INTERNAL_H +#define OPENSSL_HEADER_CAST_INTERNAL_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +extern const uint32_t CAST_S_table0[256]; +extern const uint32_t CAST_S_table1[256]; +extern const uint32_t CAST_S_table2[256]; +extern const uint32_t CAST_S_table3[256]; +extern const uint32_t CAST_S_table4[256]; +extern const uint32_t CAST_S_table5[256]; +extern const uint32_t CAST_S_table6[256]; +extern const uint32_t CAST_S_table7[256]; + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_CAST_INTERNAL_H */ diff --git a/external/boringssl/decrepit/des/CMakeLists.txt b/external/boringssl/decrepit/des/CMakeLists.txt new file mode 100644 index 0000000000..0ee5c2e3b5 --- /dev/null +++ b/external/boringssl/decrepit/des/CMakeLists.txt @@ -0,0 +1,9 @@ +include_directories(../../include) + +add_library( + des_decrepit + + OBJECT + + cfb64ede.c +) diff --git a/external/boringssl/decrepit/des/cfb64ede.c b/external/boringssl/decrepit/des/cfb64ede.c new file mode 100644 index 0000000000..f7e81d4557 --- /dev/null +++ b/external/boringssl/decrepit/des/cfb64ede.c @@ -0,0 +1,236 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include "../crypto/des/internal.h" + + +/* The input and output encrypted as though 64bit cfb mode is being used. The + * extra state information to record how much of the 64bit block we have used + * is contained in *num; */ +void DES_ede3_cfb64_encrypt(const uint8_t *in, uint8_t *out, + long length, DES_key_schedule *ks1, + DES_key_schedule *ks2, DES_key_schedule *ks3, + DES_cblock *ivec, int *num, int enc) { + uint32_t v0, v1; + long l = length; + int n = *num; + uint32_t ti[2]; + uint8_t *iv, c, cc; + + iv = ivec->bytes; + if (enc) { + while (l--) { + if (n == 0) { + c2l(iv, v0); + c2l(iv, v1); + + ti[0] = v0; + ti[1] = v1; + DES_encrypt3(ti, ks1, ks2, ks3); + v0 = ti[0]; + v1 = ti[1]; + + iv = ivec->bytes; + l2c(v0, iv); + l2c(v1, iv); + iv = ivec->bytes; + } + c = *(in++) ^ iv[n]; + *(out++) = c; + iv[n] = c; + n = (n + 1) & 0x07; + } + } else { + while (l--) { + if (n == 0) { + c2l(iv, v0); + c2l(iv, v1); + + ti[0] = v0; + ti[1] = v1; + DES_encrypt3(ti, ks1, ks2, ks3); + v0 = ti[0]; + v1 = ti[1]; + + iv = ivec->bytes; + l2c(v0, iv); + l2c(v1, iv); + iv = ivec->bytes; + } + cc = *(in++); + c = iv[n]; + iv[n] = cc; + *(out++) = c ^ cc; + n = (n + 1) & 0x07; + } + } + v0 = v1 = ti[0] = ti[1] = c = cc = 0; + *num = n; +} + +/* This is compatible with the single key CFB-r for DES, even thought that's + * not what EVP needs. */ + +void DES_ede3_cfb_encrypt(const uint8_t *in, uint8_t *out, int numbits, + long length, DES_key_schedule *ks1, + DES_key_schedule *ks2, DES_key_schedule *ks3, + DES_cblock *ivec, int enc) { + uint32_t d0, d1, v0, v1; + unsigned long l = length, n = ((unsigned int)numbits + 7) / 8; + int num = numbits, i; + uint32_t ti[2]; + uint8_t *iv; + uint8_t ovec[16]; + + if (num > 64) { + return; + }; + + iv = ivec->bytes; + c2l(iv, v0); + c2l(iv, v1); + + if (enc) { + while (l >= n) { + l -= n; + ti[0] = v0; + ti[1] = v1; + DES_encrypt3(ti, ks1, ks2, ks3); + c2ln(in, d0, d1, n); + in += n; + d0 ^= ti[0]; + d1 ^= ti[1]; + l2cn(d0, d1, out, n); + out += n; + /* 30-08-94 - eay - changed because l>>32 and l<<32 are bad under + * gcc :-( */ + if (num == 32) { + v0 = v1; + v1 = d0; + } else if (num == 64) { + v0 = d0; + v1 = d1; + } else { + iv = &ovec[0]; + l2c(v0, iv); + l2c(v1, iv); + l2c(d0, iv); + l2c(d1, iv); + /* shift ovec left most of the bits... */ + memmove(ovec, ovec + num / 8, 8 + (num % 8 ? 1 : 0)); + /* now the remaining bits */ + if (num % 8 != 0) { + for (i = 0; i < 8; ++i) { + ovec[i] <<= num % 8; + ovec[i] |= ovec[i + 1] >> (8 - num % 8); + } + } + iv = &ovec[0]; + c2l(iv, v0); + c2l(iv, v1); + } + } + } else { + while (l >= n) { + l -= n; + ti[0] = v0; + ti[1] = v1; + DES_encrypt3(ti, ks1, ks2, ks3); + c2ln(in, d0, d1, n); + in += n; + /* 30-08-94 - eay - changed because l>>32 and l<<32 are bad under + * gcc :-( */ + if (num == 32) { + v0 = v1; + v1 = d0; + } else if (num == 64) { + v0 = d0; + v1 = d1; + } else { + iv = &ovec[0]; + l2c(v0, iv); + l2c(v1, iv); + l2c(d0, iv); + l2c(d1, iv); + /* shift ovec left most of the bits... */ + memmove(ovec, ovec + num / 8, 8 + (num % 8 ? 1 : 0)); + /* now the remaining bits */ + if (num % 8 != 0) { + for (i = 0; i < 8; ++i) { + ovec[i] <<= num % 8; + ovec[i] |= ovec[i + 1] >> (8 - num % 8); + } + } + iv = &ovec[0]; + c2l(iv, v0); + c2l(iv, v1); + } + d0 ^= ti[0]; + d1 ^= ti[1]; + l2cn(d0, d1, out, n); + out += n; + } + } + + iv = ivec->bytes; + l2c(v0, iv); + l2c(v1, iv); + v0 = v1 = d0 = d1 = ti[0] = ti[1] = 0; +} diff --git a/external/boringssl/decrepit/dh/CMakeLists.txt b/external/boringssl/decrepit/dh/CMakeLists.txt new file mode 100644 index 0000000000..fb862b512b --- /dev/null +++ b/external/boringssl/decrepit/dh/CMakeLists.txt @@ -0,0 +1,9 @@ +include_directories(../../include) + +add_library( + dh_decrepit + + OBJECT + + dh_decrepit.c +) diff --git a/external/boringssl/decrepit/dh/dh_decrepit.c b/external/boringssl/decrepit/dh/dh_decrepit.c new file mode 100644 index 0000000000..1d38c12eb4 --- /dev/null +++ b/external/boringssl/decrepit/dh/dh_decrepit.c @@ -0,0 +1,103 @@ +/* ==================================================================== + * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include +#include + + +struct wrapped_callback { + void (*callback)(int, int, void *); + void *arg; +}; + +/* callback_wrapper converts an “old†style generation callback to the newer + * |BN_GENCB| form. */ +static int callback_wrapper(int event, int n, BN_GENCB *gencb) { + struct wrapped_callback *wrapped = (struct wrapped_callback *) gencb->arg; + wrapped->callback(event, n, wrapped->arg); + return 1; +} + +DH *DH_generate_parameters(int prime_len, int generator, + void (*callback)(int, int, void *), void *cb_arg) { + if (prime_len < 0 || generator < 0) { + return NULL; + } + + DH *ret = DH_new(); + if (ret == NULL) { + return NULL; + } + + BN_GENCB gencb_storage; + BN_GENCB *cb = NULL; + + struct wrapped_callback wrapped; + + if (callback != NULL) { + wrapped.callback = callback; + wrapped.arg = cb_arg; + + cb = &gencb_storage; + BN_GENCB_set(cb, callback_wrapper, &wrapped); + } + + if (!DH_generate_parameters_ex(ret, prime_len, generator, cb)) { + goto err; + } + + return ret; + +err: + DH_free(ret); + return NULL; +} diff --git a/external/boringssl/decrepit/dsa/CMakeLists.txt b/external/boringssl/decrepit/dsa/CMakeLists.txt new file mode 100644 index 0000000000..cc64b60483 --- /dev/null +++ b/external/boringssl/decrepit/dsa/CMakeLists.txt @@ -0,0 +1,9 @@ +include_directories(../../include) + +add_library( + dsa_decrepit + + OBJECT + + dsa_decrepit.c +) diff --git a/external/boringssl/decrepit/dsa/dsa_decrepit.c b/external/boringssl/decrepit/dsa/dsa_decrepit.c new file mode 100644 index 0000000000..aef8056bf1 --- /dev/null +++ b/external/boringssl/decrepit/dsa/dsa_decrepit.c @@ -0,0 +1,105 @@ +/* ==================================================================== + * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include +#include + + +struct wrapped_callback { + void (*callback)(int, int, void *); + void *arg; +}; + +/* callback_wrapper converts an “old†style generation callback to the newer + * |BN_GENCB| form. */ +static int callback_wrapper(int event, int n, BN_GENCB *gencb) { + struct wrapped_callback *wrapped = (struct wrapped_callback *) gencb->arg; + wrapped->callback(event, n, wrapped->arg); + return 1; +} + +DSA *DSA_generate_parameters(int bits, uint8_t *seed_in, int seed_len, + int *counter_ret, unsigned long *h_ret, + void (*callback)(int, int, void *), void *cb_arg) { + if (bits < 0 || seed_len < 0) { + return NULL; + } + + DSA *ret = DSA_new(); + if (ret == NULL) { + return NULL; + } + + BN_GENCB gencb_storage; + BN_GENCB *cb = NULL; + + struct wrapped_callback wrapped; + + if (callback != NULL) { + wrapped.callback = callback; + wrapped.arg = cb_arg; + + cb = &gencb_storage; + BN_GENCB_set(cb, callback_wrapper, &wrapped); + } + + if (!DSA_generate_parameters_ex(ret, bits, seed_in, seed_len, counter_ret, + h_ret, cb)) { + goto err; + } + + return ret; + +err: + DSA_free(ret); + return NULL; +} diff --git a/external/boringssl/decrepit/evp/CMakeLists.txt b/external/boringssl/decrepit/evp/CMakeLists.txt new file mode 100644 index 0000000000..e631a9a99f --- /dev/null +++ b/external/boringssl/decrepit/evp/CMakeLists.txt @@ -0,0 +1,10 @@ +include_directories(../../include) + +add_library( + evp_decrepit + + OBJECT + + dss1.c + evp_do_all.c +) diff --git a/external/boringssl/decrepit/evp/dss1.c b/external/boringssl/decrepit/evp/dss1.c new file mode 100644 index 0000000000..9c370acb77 --- /dev/null +++ b/external/boringssl/decrepit/evp/dss1.c @@ -0,0 +1,20 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + + +const EVP_MD *EVP_dss1(void) { + return EVP_sha1(); +} diff --git a/external/boringssl/decrepit/evp/evp_do_all.c b/external/boringssl/decrepit/evp/evp_do_all.c new file mode 100644 index 0000000000..621c0b1170 --- /dev/null +++ b/external/boringssl/decrepit/evp/evp_do_all.c @@ -0,0 +1,77 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + + +void EVP_CIPHER_do_all_sorted(void (*callback)(const EVP_CIPHER *cipher, + const char *name, + const char *unused, void *arg), + void *arg) { + callback(EVP_aes_128_cbc(), "AES-128-CBC", NULL, arg); + callback(EVP_aes_128_ctr(), "AES-128-CTR", NULL, arg); + callback(EVP_aes_128_ecb(), "AES-128-ECB", NULL, arg); + callback(EVP_aes_128_ofb(), "AES-128-OFB", NULL, arg); + callback(EVP_aes_256_cbc(), "AES-256-CBC", NULL, arg); + callback(EVP_aes_256_ctr(), "AES-256-CTR", NULL, arg); + callback(EVP_aes_256_ecb(), "AES-256-ECB", NULL, arg); + callback(EVP_aes_256_ofb(), "AES-256-OFB", NULL, arg); + callback(EVP_aes_256_xts(), "AES-256-XTS", NULL, arg); + callback(EVP_des_cbc(), "DES-CBC", NULL, arg); + callback(EVP_des_ecb(), "DES-ECB", NULL, arg); + callback(EVP_des_ede(), "DES-EDE", NULL, arg); + callback(EVP_des_ede_cbc(), "DES-EDE-CBC", NULL, arg); + callback(EVP_des_ede3_cbc(), "DES-EDE3-CBC", NULL, arg); + callback(EVP_rc2_cbc(), "RC2-CBC", NULL, arg); + callback(EVP_rc4(), "RC4", NULL, arg); + + /* OpenSSL returns everything twice, the second time in lower case. */ + callback(EVP_aes_128_cbc(), "aes-128-cbc", NULL, arg); + callback(EVP_aes_128_ctr(), "aes-128-ctr", NULL, arg); + callback(EVP_aes_128_ecb(), "aes-128-ecb", NULL, arg); + callback(EVP_aes_128_ofb(), "aes-128-ofb", NULL, arg); + callback(EVP_aes_256_cbc(), "aes-256-cbc", NULL, arg); + callback(EVP_aes_256_ctr(), "aes-256-ctr", NULL, arg); + callback(EVP_aes_256_ecb(), "aes-256-ecb", NULL, arg); + callback(EVP_aes_256_ofb(), "aes-256-ofb", NULL, arg); + callback(EVP_aes_256_xts(), "aes-256-xts", NULL, arg); + callback(EVP_des_cbc(), "des-cbc", NULL, arg); + callback(EVP_des_ecb(), "des-ecb", NULL, arg); + callback(EVP_des_ede(), "des-ede", NULL, arg); + callback(EVP_des_ede_cbc(), "des-ede-cbc", NULL, arg); + callback(EVP_des_ede3_cbc(), "des-ede3-cbc", NULL, arg); + callback(EVP_rc2_cbc(), "rc2-cbc", NULL, arg); + callback(EVP_rc4(), "rc4", NULL, arg); +} + +void EVP_MD_do_all_sorted(void (*callback)(const EVP_MD *cipher, + const char *name, const char *unused, + void *arg), + void *arg) { + callback(EVP_md4(), "MD4", NULL, arg); + callback(EVP_md5(), "MD5", NULL, arg); + callback(EVP_sha1(), "SHA1", NULL, arg); + callback(EVP_sha224(), "SHA224", NULL, arg); + callback(EVP_sha256(), "SHA256", NULL, arg); + callback(EVP_sha384(), "SHA384", NULL, arg); + callback(EVP_sha512(), "SHA512", NULL, arg); + + callback(EVP_md4(), "md4", NULL, arg); + callback(EVP_md5(), "md5", NULL, arg); + callback(EVP_sha1(), "sha1", NULL, arg); + callback(EVP_sha224(), "sha224", NULL, arg); + callback(EVP_sha256(), "sha256", NULL, arg); + callback(EVP_sha384(), "sha384", NULL, arg); + callback(EVP_sha512(), "sha512", NULL, arg); +} diff --git a/external/boringssl/decrepit/macros.h b/external/boringssl/decrepit/macros.h new file mode 100644 index 0000000000..228183a332 --- /dev/null +++ b/external/boringssl/decrepit/macros.h @@ -0,0 +1,123 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_DECREPIT_MACROS_H +#define OPENSSL_HEADER_DECREPIT_MACROS_H + + +/* NOTE - c is not incremented as per n2l */ +#define n2ln(c, l1, l2, n) \ + { \ + c += n; \ + l1 = l2 = 0; \ + switch (n) { \ + case 8: \ + l2 = ((unsigned long)(*(--(c)))); \ + case 7: \ + l2 |= ((unsigned long)(*(--(c)))) << 8; \ + case 6: \ + l2 |= ((unsigned long)(*(--(c)))) << 16; \ + case 5: \ + l2 |= ((unsigned long)(*(--(c)))) << 24; \ + case 4: \ + l1 = ((unsigned long)(*(--(c)))); \ + case 3: \ + l1 |= ((unsigned long)(*(--(c)))) << 8; \ + case 2: \ + l1 |= ((unsigned long)(*(--(c)))) << 16; \ + case 1: \ + l1 |= ((unsigned long)(*(--(c)))) << 24; \ + } \ + } + +/* NOTE - c is not incremented as per l2n */ +#define l2nn(l1, l2, c, n) \ + { \ + c += n; \ + switch (n) { \ + case 8: \ + *(--(c)) = (unsigned char)(((l2)) & 0xff); \ + case 7: \ + *(--(c)) = (unsigned char)(((l2) >> 8) & 0xff); \ + case 6: \ + *(--(c)) = (unsigned char)(((l2) >> 16) & 0xff); \ + case 5: \ + *(--(c)) = (unsigned char)(((l2) >> 24) & 0xff); \ + case 4: \ + *(--(c)) = (unsigned char)(((l1)) & 0xff); \ + case 3: \ + *(--(c)) = (unsigned char)(((l1) >> 8) & 0xff); \ + case 2: \ + *(--(c)) = (unsigned char)(((l1) >> 16) & 0xff); \ + case 1: \ + *(--(c)) = (unsigned char)(((l1) >> 24) & 0xff); \ + } \ + } + +#define l2n(l, c) \ + (*((c)++) = (unsigned char)(((l) >> 24L) & 0xff), \ + *((c)++) = (unsigned char)(((l) >> 16L) & 0xff), \ + *((c)++) = (unsigned char)(((l) >> 8L) & 0xff), \ + *((c)++) = (unsigned char)(((l)) & 0xff)) + +#define n2l(c, l) \ + (l = ((unsigned long)(*((c)++))) << 24L, \ + l |= ((unsigned long)(*((c)++))) << 16L, \ + l |= ((unsigned long)(*((c)++))) << 8L, \ + l |= ((unsigned long)(*((c)++)))) + + +#endif /* OPENSSL_HEADER_DECREPIT_MACROS_H */ diff --git a/external/boringssl/decrepit/obj/CMakeLists.txt b/external/boringssl/decrepit/obj/CMakeLists.txt new file mode 100644 index 0000000000..caaecd32c8 --- /dev/null +++ b/external/boringssl/decrepit/obj/CMakeLists.txt @@ -0,0 +1,9 @@ +include_directories(../../include) + +add_library( + obj_decrepit + + OBJECT + + obj_decrepit.c +) diff --git a/external/boringssl/decrepit/obj/obj_decrepit.c b/external/boringssl/decrepit/obj/obj_decrepit.c new file mode 100644 index 0000000000..06051f1124 --- /dev/null +++ b/external/boringssl/decrepit/obj/obj_decrepit.c @@ -0,0 +1,71 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include +#include + +#include + + +struct wrapped_callback { + void (*callback)(const OBJ_NAME *, void *arg); + void *arg; +}; + +static void cipher_callback(const EVP_CIPHER *cipher, const char *name, + const char *unused, void *arg) { + const struct wrapped_callback *wrapped = (struct wrapped_callback *)arg; + OBJ_NAME obj_name; + + memset(&obj_name, 0, sizeof(obj_name)); + obj_name.type = OBJ_NAME_TYPE_CIPHER_METH; + obj_name.name = name; + + wrapped->callback(&obj_name, wrapped->arg); +} + +static void md_callback(const EVP_MD *md, const char *name, const char *unused, + void *arg) { + const struct wrapped_callback *wrapped = (struct wrapped_callback*) arg; + OBJ_NAME obj_name; + + memset(&obj_name, 0, sizeof(obj_name)); + obj_name.type = OBJ_NAME_TYPE_MD_METH; + obj_name.name = name; + + wrapped->callback(&obj_name, wrapped->arg); +} + +void OBJ_NAME_do_all_sorted(int type, + void (*callback)(const OBJ_NAME *, void *arg), + void *arg) { + struct wrapped_callback wrapped; + wrapped.callback = callback; + wrapped.arg = arg; + + if (type == OBJ_NAME_TYPE_CIPHER_METH) { + EVP_CIPHER_do_all_sorted(cipher_callback, &wrapped); + } else if (type == OBJ_NAME_TYPE_MD_METH) { + EVP_MD_do_all_sorted(md_callback, &wrapped); + } else { + assert(0); + } +} + +void OBJ_NAME_do_all(int type, void (*callback)(const OBJ_NAME *, void *arg), + void *arg) { + OBJ_NAME_do_all_sorted(type, callback, arg); +} diff --git a/external/boringssl/decrepit/rc4/CMakeLists.txt b/external/boringssl/decrepit/rc4/CMakeLists.txt new file mode 100644 index 0000000000..459b24e2f7 --- /dev/null +++ b/external/boringssl/decrepit/rc4/CMakeLists.txt @@ -0,0 +1,9 @@ +include_directories(../../include) + +add_library( + rc4_decrepit + + OBJECT + + rc4_decrepit.c +) diff --git a/external/boringssl/decrepit/rc4/rc4_decrepit.c b/external/boringssl/decrepit/rc4/rc4_decrepit.c new file mode 100644 index 0000000000..140e15d612 --- /dev/null +++ b/external/boringssl/decrepit/rc4/rc4_decrepit.c @@ -0,0 +1,62 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + + +const char *RC4_options(void) { + return "rc4(ptr,int)"; +} diff --git a/external/boringssl/decrepit/ripemd/CMakeLists.txt b/external/boringssl/decrepit/ripemd/CMakeLists.txt new file mode 100644 index 0000000000..b913e5b848 --- /dev/null +++ b/external/boringssl/decrepit/ripemd/CMakeLists.txt @@ -0,0 +1,23 @@ +include_directories(../../include) + +add_library( + ripemd_decrepit + + OBJECT + + ripemd.c +) + +if(ENABLE_TESTS) +add_executable( + ripemd_test + + ripemd_test.cc + + $ +) + +target_link_libraries(ripemd_test crypto) +target_link_libraries(ripemd_test decrepit) +add_dependencies(all_tests ripemd_test) +endif() diff --git a/external/boringssl/decrepit/ripemd/internal.h b/external/boringssl/decrepit/ripemd/internal.h new file mode 100644 index 0000000000..c4db4b23dd --- /dev/null +++ b/external/boringssl/decrepit/ripemd/internal.h @@ -0,0 +1,493 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_BN_INTERNAL_H +#define OPENSSL_HEADER_BN_INTERNAL_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +static void ripemd160_block_data_order(uint32_t h[5], const uint8_t *data, + size_t num); + +#define DATA_ORDER_IS_LITTLE_ENDIAN + +#define HASH_LONG uint32_t +#define HASH_CTX RIPEMD160_CTX +#define HASH_CBLOCK RIPEMD160_CBLOCK +#define HASH_UPDATE RIPEMD160_Update +#define HASH_TRANSFORM RIPEMD160_Transform +#define HASH_FINAL RIPEMD160_Final +#define HASH_MAKE_STRING(c, s) \ + do { \ + unsigned long ll; \ + ll = (c)->h[0]; \ + (void)HOST_l2c(ll, (s)); \ + ll = (c)->h[1]; \ + (void)HOST_l2c(ll, (s)); \ + ll = (c)->h[2]; \ + (void)HOST_l2c(ll, (s)); \ + ll = (c)->h[3]; \ + (void)HOST_l2c(ll, (s)); \ + ll = (c)->h[4]; \ + (void)HOST_l2c(ll, (s)); \ + } while (0) +#define HASH_BLOCK_DATA_ORDER ripemd160_block_data_order + +#include "../../crypto/digest/md32_common.h" + +/* Transformed F2 and F4 are courtesy of Wei Dai */ +#define F1(x, y, z) ((x) ^ (y) ^ (z)) +#define F2(x, y, z) ((((y) ^ (z)) & (x)) ^ (z)) +#define F3(x, y, z) (((~(y)) | (x)) ^ (z)) +#define F4(x, y, z) ((((x) ^ (y)) & (z)) ^ (y)) +#define F5(x, y, z) (((~(z)) | (y)) ^ (x)) + +#define RIPEMD160_A 0x67452301L +#define RIPEMD160_B 0xEFCDAB89L +#define RIPEMD160_C 0x98BADCFEL +#define RIPEMD160_D 0x10325476L +#define RIPEMD160_E 0xC3D2E1F0L + +#define ROTATE(a, n) (((a) << (n)) | (((a)&0xffffffff) >> (32 - (n)))) + +#define RIP1(a, b, c, d, e, w, s) \ + { \ + a += F1(b, c, d) + X(w); \ + a = ROTATE(a, s) + e; \ + c = ROTATE(c, 10); \ + } + +#define RIP2(a, b, c, d, e, w, s, K) \ + { \ + a += F2(b, c, d) + X(w) + K; \ + a = ROTATE(a, s) + e; \ + c = ROTATE(c, 10); \ + } + +#define RIP3(a, b, c, d, e, w, s, K) \ + { \ + a += F3(b, c, d) + X(w) + K; \ + a = ROTATE(a, s) + e; \ + c = ROTATE(c, 10); \ + } + +#define RIP4(a, b, c, d, e, w, s, K) \ + { \ + a += F4(b, c, d) + X(w) + K; \ + a = ROTATE(a, s) + e; \ + c = ROTATE(c, 10); \ + } + +#define RIP5(a, b, c, d, e, w, s, K) \ + { \ + a += F5(b, c, d) + X(w) + K; \ + a = ROTATE(a, s) + e; \ + c = ROTATE(c, 10); \ + } + +#define KL0 0x00000000L +#define KL1 0x5A827999L +#define KL2 0x6ED9EBA1L +#define KL3 0x8F1BBCDCL +#define KL4 0xA953FD4EL + +#define KR0 0x50A28BE6L +#define KR1 0x5C4DD124L +#define KR2 0x6D703EF3L +#define KR3 0x7A6D76E9L +#define KR4 0x00000000L + +#define WL00 0 +#define SL00 11 +#define WL01 1 +#define SL01 14 +#define WL02 2 +#define SL02 15 +#define WL03 3 +#define SL03 12 +#define WL04 4 +#define SL04 5 +#define WL05 5 +#define SL05 8 +#define WL06 6 +#define SL06 7 +#define WL07 7 +#define SL07 9 +#define WL08 8 +#define SL08 11 +#define WL09 9 +#define SL09 13 +#define WL10 10 +#define SL10 14 +#define WL11 11 +#define SL11 15 +#define WL12 12 +#define SL12 6 +#define WL13 13 +#define SL13 7 +#define WL14 14 +#define SL14 9 +#define WL15 15 +#define SL15 8 + +#define WL16 7 +#define SL16 7 +#define WL17 4 +#define SL17 6 +#define WL18 13 +#define SL18 8 +#define WL19 1 +#define SL19 13 +#define WL20 10 +#define SL20 11 +#define WL21 6 +#define SL21 9 +#define WL22 15 +#define SL22 7 +#define WL23 3 +#define SL23 15 +#define WL24 12 +#define SL24 7 +#define WL25 0 +#define SL25 12 +#define WL26 9 +#define SL26 15 +#define WL27 5 +#define SL27 9 +#define WL28 2 +#define SL28 11 +#define WL29 14 +#define SL29 7 +#define WL30 11 +#define SL30 13 +#define WL31 8 +#define SL31 12 + +#define WL32 3 +#define SL32 11 +#define WL33 10 +#define SL33 13 +#define WL34 14 +#define SL34 6 +#define WL35 4 +#define SL35 7 +#define WL36 9 +#define SL36 14 +#define WL37 15 +#define SL37 9 +#define WL38 8 +#define SL38 13 +#define WL39 1 +#define SL39 15 +#define WL40 2 +#define SL40 14 +#define WL41 7 +#define SL41 8 +#define WL42 0 +#define SL42 13 +#define WL43 6 +#define SL43 6 +#define WL44 13 +#define SL44 5 +#define WL45 11 +#define SL45 12 +#define WL46 5 +#define SL46 7 +#define WL47 12 +#define SL47 5 + +#define WL48 1 +#define SL48 11 +#define WL49 9 +#define SL49 12 +#define WL50 11 +#define SL50 14 +#define WL51 10 +#define SL51 15 +#define WL52 0 +#define SL52 14 +#define WL53 8 +#define SL53 15 +#define WL54 12 +#define SL54 9 +#define WL55 4 +#define SL55 8 +#define WL56 13 +#define SL56 9 +#define WL57 3 +#define SL57 14 +#define WL58 7 +#define SL58 5 +#define WL59 15 +#define SL59 6 +#define WL60 14 +#define SL60 8 +#define WL61 5 +#define SL61 6 +#define WL62 6 +#define SL62 5 +#define WL63 2 +#define SL63 12 + +#define WL64 4 +#define SL64 9 +#define WL65 0 +#define SL65 15 +#define WL66 5 +#define SL66 5 +#define WL67 9 +#define SL67 11 +#define WL68 7 +#define SL68 6 +#define WL69 12 +#define SL69 8 +#define WL70 2 +#define SL70 13 +#define WL71 10 +#define SL71 12 +#define WL72 14 +#define SL72 5 +#define WL73 1 +#define SL73 12 +#define WL74 3 +#define SL74 13 +#define WL75 8 +#define SL75 14 +#define WL76 11 +#define SL76 11 +#define WL77 6 +#define SL77 8 +#define WL78 15 +#define SL78 5 +#define WL79 13 +#define SL79 6 + +#define WR00 5 +#define SR00 8 +#define WR01 14 +#define SR01 9 +#define WR02 7 +#define SR02 9 +#define WR03 0 +#define SR03 11 +#define WR04 9 +#define SR04 13 +#define WR05 2 +#define SR05 15 +#define WR06 11 +#define SR06 15 +#define WR07 4 +#define SR07 5 +#define WR08 13 +#define SR08 7 +#define WR09 6 +#define SR09 7 +#define WR10 15 +#define SR10 8 +#define WR11 8 +#define SR11 11 +#define WR12 1 +#define SR12 14 +#define WR13 10 +#define SR13 14 +#define WR14 3 +#define SR14 12 +#define WR15 12 +#define SR15 6 + +#define WR16 6 +#define SR16 9 +#define WR17 11 +#define SR17 13 +#define WR18 3 +#define SR18 15 +#define WR19 7 +#define SR19 7 +#define WR20 0 +#define SR20 12 +#define WR21 13 +#define SR21 8 +#define WR22 5 +#define SR22 9 +#define WR23 10 +#define SR23 11 +#define WR24 14 +#define SR24 7 +#define WR25 15 +#define SR25 7 +#define WR26 8 +#define SR26 12 +#define WR27 12 +#define SR27 7 +#define WR28 4 +#define SR28 6 +#define WR29 9 +#define SR29 15 +#define WR30 1 +#define SR30 13 +#define WR31 2 +#define SR31 11 + +#define WR32 15 +#define SR32 9 +#define WR33 5 +#define SR33 7 +#define WR34 1 +#define SR34 15 +#define WR35 3 +#define SR35 11 +#define WR36 7 +#define SR36 8 +#define WR37 14 +#define SR37 6 +#define WR38 6 +#define SR38 6 +#define WR39 9 +#define SR39 14 +#define WR40 11 +#define SR40 12 +#define WR41 8 +#define SR41 13 +#define WR42 12 +#define SR42 5 +#define WR43 2 +#define SR43 14 +#define WR44 10 +#define SR44 13 +#define WR45 0 +#define SR45 13 +#define WR46 4 +#define SR46 7 +#define WR47 13 +#define SR47 5 + +#define WR48 8 +#define SR48 15 +#define WR49 6 +#define SR49 5 +#define WR50 4 +#define SR50 8 +#define WR51 1 +#define SR51 11 +#define WR52 3 +#define SR52 14 +#define WR53 11 +#define SR53 14 +#define WR54 15 +#define SR54 6 +#define WR55 0 +#define SR55 14 +#define WR56 5 +#define SR56 6 +#define WR57 12 +#define SR57 9 +#define WR58 2 +#define SR58 12 +#define WR59 13 +#define SR59 9 +#define WR60 9 +#define SR60 12 +#define WR61 7 +#define SR61 5 +#define WR62 10 +#define SR62 15 +#define WR63 14 +#define SR63 8 + +#define WR64 12 +#define SR64 8 +#define WR65 15 +#define SR65 5 +#define WR66 10 +#define SR66 12 +#define WR67 4 +#define SR67 9 +#define WR68 1 +#define SR68 12 +#define WR69 5 +#define SR69 5 +#define WR70 8 +#define SR70 14 +#define WR71 7 +#define SR71 6 +#define WR72 6 +#define SR72 8 +#define WR73 2 +#define SR73 13 +#define WR74 13 +#define SR74 6 +#define WR75 14 +#define SR75 5 +#define WR76 0 +#define SR76 15 +#define WR77 3 +#define SR77 13 +#define WR78 9 +#define SR78 11 +#define WR79 11 +#define SR79 11 + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_BN_INTERNAL_H */ diff --git a/external/boringssl/decrepit/ripemd/ripemd.c b/external/boringssl/decrepit/ripemd/ripemd.c new file mode 100644 index 0000000000..6ed7816c3d --- /dev/null +++ b/external/boringssl/decrepit/ripemd/ripemd.c @@ -0,0 +1,324 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include "internal.h" + + +int RIPEMD160_Init(RIPEMD160_CTX *ctx) { + memset(ctx, 0, sizeof(*ctx)); + ctx->h[0] = RIPEMD160_A; + ctx->h[1] = RIPEMD160_B; + ctx->h[2] = RIPEMD160_C; + ctx->h[3] = RIPEMD160_D; + ctx->h[4] = RIPEMD160_E; + return 1; +} + +static void ripemd160_block_data_order(uint32_t h[5], const uint8_t *data, + size_t num) { + uint32_t A, B, C, D, E; + uint32_t a, b, c, d, e, l; + uint32_t XX0, XX1, XX2, XX3, XX4, XX5, XX6, XX7, XX8, XX9, XX10, XX11, XX12, + XX13, XX14, XX15; +#define X(i) XX##i + + for (; num--;) { + A = h[0]; + B = h[1]; + C = h[2]; + D = h[3]; + E = h[4]; + + (void)HOST_c2l(data, l); + X(0) = l; + (void)HOST_c2l(data, l); + X(1) = l; + RIP1(A, B, C, D, E, WL00, SL00); + (void)HOST_c2l(data, l); + X(2) = l; + RIP1(E, A, B, C, D, WL01, SL01); + (void)HOST_c2l(data, l); + X(3) = l; + RIP1(D, E, A, B, C, WL02, SL02); + (void)HOST_c2l(data, l); + X(4) = l; + RIP1(C, D, E, A, B, WL03, SL03); + (void)HOST_c2l(data, l); + X(5) = l; + RIP1(B, C, D, E, A, WL04, SL04); + (void)HOST_c2l(data, l); + X(6) = l; + RIP1(A, B, C, D, E, WL05, SL05); + (void)HOST_c2l(data, l); + X(7) = l; + RIP1(E, A, B, C, D, WL06, SL06); + (void)HOST_c2l(data, l); + X(8) = l; + RIP1(D, E, A, B, C, WL07, SL07); + (void)HOST_c2l(data, l); + X(9) = l; + RIP1(C, D, E, A, B, WL08, SL08); + (void)HOST_c2l(data, l); + X(10) = l; + RIP1(B, C, D, E, A, WL09, SL09); + (void)HOST_c2l(data, l); + X(11) = l; + RIP1(A, B, C, D, E, WL10, SL10); + (void)HOST_c2l(data, l); + X(12) = l; + RIP1(E, A, B, C, D, WL11, SL11); + (void)HOST_c2l(data, l); + X(13) = l; + RIP1(D, E, A, B, C, WL12, SL12); + (void)HOST_c2l(data, l); + X(14) = l; + RIP1(C, D, E, A, B, WL13, SL13); + (void)HOST_c2l(data, l); + X(15) = l; + RIP1(B, C, D, E, A, WL14, SL14); + RIP1(A, B, C, D, E, WL15, SL15); + + RIP2(E, A, B, C, D, WL16, SL16, KL1); + RIP2(D, E, A, B, C, WL17, SL17, KL1); + RIP2(C, D, E, A, B, WL18, SL18, KL1); + RIP2(B, C, D, E, A, WL19, SL19, KL1); + RIP2(A, B, C, D, E, WL20, SL20, KL1); + RIP2(E, A, B, C, D, WL21, SL21, KL1); + RIP2(D, E, A, B, C, WL22, SL22, KL1); + RIP2(C, D, E, A, B, WL23, SL23, KL1); + RIP2(B, C, D, E, A, WL24, SL24, KL1); + RIP2(A, B, C, D, E, WL25, SL25, KL1); + RIP2(E, A, B, C, D, WL26, SL26, KL1); + RIP2(D, E, A, B, C, WL27, SL27, KL1); + RIP2(C, D, E, A, B, WL28, SL28, KL1); + RIP2(B, C, D, E, A, WL29, SL29, KL1); + RIP2(A, B, C, D, E, WL30, SL30, KL1); + RIP2(E, A, B, C, D, WL31, SL31, KL1); + + RIP3(D, E, A, B, C, WL32, SL32, KL2); + RIP3(C, D, E, A, B, WL33, SL33, KL2); + RIP3(B, C, D, E, A, WL34, SL34, KL2); + RIP3(A, B, C, D, E, WL35, SL35, KL2); + RIP3(E, A, B, C, D, WL36, SL36, KL2); + RIP3(D, E, A, B, C, WL37, SL37, KL2); + RIP3(C, D, E, A, B, WL38, SL38, KL2); + RIP3(B, C, D, E, A, WL39, SL39, KL2); + RIP3(A, B, C, D, E, WL40, SL40, KL2); + RIP3(E, A, B, C, D, WL41, SL41, KL2); + RIP3(D, E, A, B, C, WL42, SL42, KL2); + RIP3(C, D, E, A, B, WL43, SL43, KL2); + RIP3(B, C, D, E, A, WL44, SL44, KL2); + RIP3(A, B, C, D, E, WL45, SL45, KL2); + RIP3(E, A, B, C, D, WL46, SL46, KL2); + RIP3(D, E, A, B, C, WL47, SL47, KL2); + + RIP4(C, D, E, A, B, WL48, SL48, KL3); + RIP4(B, C, D, E, A, WL49, SL49, KL3); + RIP4(A, B, C, D, E, WL50, SL50, KL3); + RIP4(E, A, B, C, D, WL51, SL51, KL3); + RIP4(D, E, A, B, C, WL52, SL52, KL3); + RIP4(C, D, E, A, B, WL53, SL53, KL3); + RIP4(B, C, D, E, A, WL54, SL54, KL3); + RIP4(A, B, C, D, E, WL55, SL55, KL3); + RIP4(E, A, B, C, D, WL56, SL56, KL3); + RIP4(D, E, A, B, C, WL57, SL57, KL3); + RIP4(C, D, E, A, B, WL58, SL58, KL3); + RIP4(B, C, D, E, A, WL59, SL59, KL3); + RIP4(A, B, C, D, E, WL60, SL60, KL3); + RIP4(E, A, B, C, D, WL61, SL61, KL3); + RIP4(D, E, A, B, C, WL62, SL62, KL3); + RIP4(C, D, E, A, B, WL63, SL63, KL3); + + RIP5(B, C, D, E, A, WL64, SL64, KL4); + RIP5(A, B, C, D, E, WL65, SL65, KL4); + RIP5(E, A, B, C, D, WL66, SL66, KL4); + RIP5(D, E, A, B, C, WL67, SL67, KL4); + RIP5(C, D, E, A, B, WL68, SL68, KL4); + RIP5(B, C, D, E, A, WL69, SL69, KL4); + RIP5(A, B, C, D, E, WL70, SL70, KL4); + RIP5(E, A, B, C, D, WL71, SL71, KL4); + RIP5(D, E, A, B, C, WL72, SL72, KL4); + RIP5(C, D, E, A, B, WL73, SL73, KL4); + RIP5(B, C, D, E, A, WL74, SL74, KL4); + RIP5(A, B, C, D, E, WL75, SL75, KL4); + RIP5(E, A, B, C, D, WL76, SL76, KL4); + RIP5(D, E, A, B, C, WL77, SL77, KL4); + RIP5(C, D, E, A, B, WL78, SL78, KL4); + RIP5(B, C, D, E, A, WL79, SL79, KL4); + + a = A; + b = B; + c = C; + d = D; + e = E; + /* Do other half */ + A = h[0]; + B = h[1]; + C = h[2]; + D = h[3]; + E = h[4]; + + RIP5(A, B, C, D, E, WR00, SR00, KR0); + RIP5(E, A, B, C, D, WR01, SR01, KR0); + RIP5(D, E, A, B, C, WR02, SR02, KR0); + RIP5(C, D, E, A, B, WR03, SR03, KR0); + RIP5(B, C, D, E, A, WR04, SR04, KR0); + RIP5(A, B, C, D, E, WR05, SR05, KR0); + RIP5(E, A, B, C, D, WR06, SR06, KR0); + RIP5(D, E, A, B, C, WR07, SR07, KR0); + RIP5(C, D, E, A, B, WR08, SR08, KR0); + RIP5(B, C, D, E, A, WR09, SR09, KR0); + RIP5(A, B, C, D, E, WR10, SR10, KR0); + RIP5(E, A, B, C, D, WR11, SR11, KR0); + RIP5(D, E, A, B, C, WR12, SR12, KR0); + RIP5(C, D, E, A, B, WR13, SR13, KR0); + RIP5(B, C, D, E, A, WR14, SR14, KR0); + RIP5(A, B, C, D, E, WR15, SR15, KR0); + + RIP4(E, A, B, C, D, WR16, SR16, KR1); + RIP4(D, E, A, B, C, WR17, SR17, KR1); + RIP4(C, D, E, A, B, WR18, SR18, KR1); + RIP4(B, C, D, E, A, WR19, SR19, KR1); + RIP4(A, B, C, D, E, WR20, SR20, KR1); + RIP4(E, A, B, C, D, WR21, SR21, KR1); + RIP4(D, E, A, B, C, WR22, SR22, KR1); + RIP4(C, D, E, A, B, WR23, SR23, KR1); + RIP4(B, C, D, E, A, WR24, SR24, KR1); + RIP4(A, B, C, D, E, WR25, SR25, KR1); + RIP4(E, A, B, C, D, WR26, SR26, KR1); + RIP4(D, E, A, B, C, WR27, SR27, KR1); + RIP4(C, D, E, A, B, WR28, SR28, KR1); + RIP4(B, C, D, E, A, WR29, SR29, KR1); + RIP4(A, B, C, D, E, WR30, SR30, KR1); + RIP4(E, A, B, C, D, WR31, SR31, KR1); + + RIP3(D, E, A, B, C, WR32, SR32, KR2); + RIP3(C, D, E, A, B, WR33, SR33, KR2); + RIP3(B, C, D, E, A, WR34, SR34, KR2); + RIP3(A, B, C, D, E, WR35, SR35, KR2); + RIP3(E, A, B, C, D, WR36, SR36, KR2); + RIP3(D, E, A, B, C, WR37, SR37, KR2); + RIP3(C, D, E, A, B, WR38, SR38, KR2); + RIP3(B, C, D, E, A, WR39, SR39, KR2); + RIP3(A, B, C, D, E, WR40, SR40, KR2); + RIP3(E, A, B, C, D, WR41, SR41, KR2); + RIP3(D, E, A, B, C, WR42, SR42, KR2); + RIP3(C, D, E, A, B, WR43, SR43, KR2); + RIP3(B, C, D, E, A, WR44, SR44, KR2); + RIP3(A, B, C, D, E, WR45, SR45, KR2); + RIP3(E, A, B, C, D, WR46, SR46, KR2); + RIP3(D, E, A, B, C, WR47, SR47, KR2); + + RIP2(C, D, E, A, B, WR48, SR48, KR3); + RIP2(B, C, D, E, A, WR49, SR49, KR3); + RIP2(A, B, C, D, E, WR50, SR50, KR3); + RIP2(E, A, B, C, D, WR51, SR51, KR3); + RIP2(D, E, A, B, C, WR52, SR52, KR3); + RIP2(C, D, E, A, B, WR53, SR53, KR3); + RIP2(B, C, D, E, A, WR54, SR54, KR3); + RIP2(A, B, C, D, E, WR55, SR55, KR3); + RIP2(E, A, B, C, D, WR56, SR56, KR3); + RIP2(D, E, A, B, C, WR57, SR57, KR3); + RIP2(C, D, E, A, B, WR58, SR58, KR3); + RIP2(B, C, D, E, A, WR59, SR59, KR3); + RIP2(A, B, C, D, E, WR60, SR60, KR3); + RIP2(E, A, B, C, D, WR61, SR61, KR3); + RIP2(D, E, A, B, C, WR62, SR62, KR3); + RIP2(C, D, E, A, B, WR63, SR63, KR3); + + RIP1(B, C, D, E, A, WR64, SR64); + RIP1(A, B, C, D, E, WR65, SR65); + RIP1(E, A, B, C, D, WR66, SR66); + RIP1(D, E, A, B, C, WR67, SR67); + RIP1(C, D, E, A, B, WR68, SR68); + RIP1(B, C, D, E, A, WR69, SR69); + RIP1(A, B, C, D, E, WR70, SR70); + RIP1(E, A, B, C, D, WR71, SR71); + RIP1(D, E, A, B, C, WR72, SR72); + RIP1(C, D, E, A, B, WR73, SR73); + RIP1(B, C, D, E, A, WR74, SR74); + RIP1(A, B, C, D, E, WR75, SR75); + RIP1(E, A, B, C, D, WR76, SR76); + RIP1(D, E, A, B, C, WR77, SR77); + RIP1(C, D, E, A, B, WR78, SR78); + RIP1(B, C, D, E, A, WR79, SR79); + + D = h[1] + c + D; + h[1] = h[2] + d + E; + h[2] = h[3] + e + A; + h[3] = h[4] + a + B; + h[4] = h[0] + b + C; + h[0] = D; + } + +#undef X +} + +uint8_t *RIPEMD160(const uint8_t *data, size_t len, unsigned char *out) { + RIPEMD160_CTX ctx; + + if (!RIPEMD160_Init(&ctx)) { + return NULL; + } + + RIPEMD160_Update(&ctx, data, len); + RIPEMD160_Final(out, &ctx); + return out; +} diff --git a/external/boringssl/decrepit/ripemd/ripemd_test.cc b/external/boringssl/decrepit/ripemd/ripemd_test.cc new file mode 100644 index 0000000000..ebcabdfb49 --- /dev/null +++ b/external/boringssl/decrepit/ripemd/ripemd_test.cc @@ -0,0 +1,119 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include + +#include +#include + +#include "../../crypto/test/test_util.h" + + +struct RIPEMDTestCase { + const char *input; + uint8_t expected[RIPEMD160_DIGEST_LENGTH]; +}; + +static const RIPEMDTestCase kRIPEMDTestCases[] = { + {"", {0x9c, 0x11, 0x85, 0xa5, 0xc5, 0xe9, 0xfc, 0x54, 0x61, 0x28, + 0x08, 0x97, 0x7e, 0xe8, 0xf5, 0x48, 0xb2, 0x25, 0x8d, 0x31}}, + {"a", {0x0b, 0xdc, 0x9d, 0x2d, 0x25, 0x6b, 0x3e, 0xe9, 0xda, 0xae, + 0x34, 0x7b, 0xe6, 0xf4, 0xdc, 0x83, 0x5a, 0x46, 0x7f, 0xfe}}, + {"abc", {0x8e, 0xb2, 0x08, 0xf7, 0xe0, 0x5d, 0x98, 0x7a, 0x9b, 0x04, + 0x4a, 0x8e, 0x98, 0xc6, 0xb0, 0x87, 0xf1, 0x5a, 0x0b, 0xfc}}, + {"message digest", + {0x5d, 0x06, 0x89, 0xef, 0x49, 0xd2, 0xfa, 0xe5, 0x72, 0xb8, + 0x81, 0xb1, 0x23, 0xa8, 0x5f, 0xfa, 0x21, 0x59, 0x5f, 0x36}}, + {"abcdefghijklmnopqrstuvwxyz", + {0xf7, 0x1c, 0x27, 0x10, 0x9c, 0x69, 0x2c, 0x1b, 0x56, 0xbb, + 0xdc, 0xeb, 0x5b, 0x9d, 0x28, 0x65, 0xb3, 0x70, 0x8d, 0xbc}}, + {"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + {0x12, 0xa0, 0x53, 0x38, 0x4a, 0x9c, 0x0c, 0x88, 0xe4, 0x05, + 0xa0, 0x6c, 0x27, 0xdc, 0xf4, 0x9a, 0xda, 0x62, 0xeb, 0x2b}}, + {"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + {0xb0, 0xe2, 0x0b, 0x6e, 0x31, 0x16, 0x64, 0x02, 0x86, 0xed, + 0x3a, 0x87, 0xa5, 0x71, 0x30, 0x79, 0xb2, 0x1f, 0x51, 0x89}}, + {"1234567890123456789012345678901234567890123456789012345678901234567890123" + "4567890", + {0x9b, 0x75, 0x2e, 0x45, 0x57, 0x3d, 0x4b, 0x39, 0xf4, 0xdb, + 0xd3, 0x32, 0x3c, 0xab, 0x82, 0xbf, 0x63, 0x32, 0x6b, 0xfb}}, +}; + +int main(void) { + unsigned test_num = 0; + int ok = 1; + + for (const auto &test : kRIPEMDTestCases) { + test_num++; + + const size_t input_len = strlen(test.input); + + for (size_t stride = 0; stride <= input_len; stride++) { + uint8_t digest[RIPEMD160_DIGEST_LENGTH]; + + if (stride == 0) { + RIPEMD160(reinterpret_cast(test.input), input_len, + digest); + } else { + RIPEMD160_CTX ctx; + RIPEMD160_Init(&ctx); + + for (size_t done = 0; done < input_len;) { + const size_t remaining = input_len - done; + size_t todo = stride; + if (todo > remaining) { + todo = remaining; + } + + RIPEMD160_Update(&ctx, &test.input[done], todo); + done += todo; + } + + RIPEMD160_Final(digest, &ctx); + } + + if (memcmp(digest, test.expected, sizeof(digest)) != 0) { + fprintf(stderr, "#%u: bad result with stride %u: ", test_num, + static_cast(stride)); + hexdump(stderr, "", digest, sizeof(digest)); + ok = 0; + } + } + } + + static const size_t kLargeBufSize = 1000000; + std::unique_ptr buf(new uint8_t[kLargeBufSize]); + memset(buf.get(), 'a', kLargeBufSize); + uint8_t digest[RIPEMD160_DIGEST_LENGTH]; + RIPEMD160(buf.get(), kLargeBufSize, digest); + + static const uint8_t kMillionADigest[RIPEMD160_DIGEST_LENGTH] = { + 0x52, 0x78, 0x32, 0x43, 0xc1, 0x69, 0x7b, 0xdb, 0xe1, 0x6d, + 0x37, 0xf9, 0x7f, 0x68, 0xf0, 0x83, 0x25, 0xdc, 0x15, 0x28}; + + if (memcmp(digest, kMillionADigest, sizeof(digest)) != 0) { + fprintf(stderr, "Digest incorrect for “million a's†test: "); + hexdump(stderr, "", digest, sizeof(digest)); + ok = 0; + } + + if (!ok) { + return 1; + } + + printf("PASS\n"); + return 0; +} diff --git a/external/boringssl/decrepit/rsa/CMakeLists.txt b/external/boringssl/decrepit/rsa/CMakeLists.txt new file mode 100644 index 0000000000..66d836b13f --- /dev/null +++ b/external/boringssl/decrepit/rsa/CMakeLists.txt @@ -0,0 +1,9 @@ +include_directories(../../include) + +add_library( + rsa_decrepit + + OBJECT + + rsa_decrepit.c +) diff --git a/external/boringssl/decrepit/rsa/rsa_decrepit.c b/external/boringssl/decrepit/rsa/rsa_decrepit.c new file mode 100644 index 0000000000..0d7c5f66b2 --- /dev/null +++ b/external/boringssl/decrepit/rsa/rsa_decrepit.c @@ -0,0 +1,103 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include + + +RSA *RSA_generate_key(int bits, unsigned long e_value, void *callback, + void *cb_arg) { + assert(callback == NULL); + assert(cb_arg == NULL); + + RSA *rsa = RSA_new(); + BIGNUM *e = BN_new(); + + if (rsa == NULL || + e == NULL || + !BN_set_word(e, e_value) || + !RSA_generate_key_ex(rsa, bits, e, NULL)) { + goto err; + } + + BN_free(e); + return rsa; + +err: + BN_free(e); + RSA_free(rsa); + return NULL; +} + +int RSA_padding_add_PKCS1_PSS(RSA *rsa, uint8_t *EM, const uint8_t *mHash, + const EVP_MD *Hash, int sLen) { + return RSA_padding_add_PKCS1_PSS_mgf1(rsa, EM, mHash, Hash, NULL, sLen); +} + +int RSA_verify_PKCS1_PSS(RSA *rsa, const uint8_t *mHash, const EVP_MD *Hash, + const uint8_t *EM, int sLen) { + return RSA_verify_PKCS1_PSS_mgf1(rsa, mHash, Hash, NULL, EM, sLen); +} + +int RSA_padding_add_PKCS1_OAEP(uint8_t *to, unsigned to_len, + const uint8_t *from, unsigned from_len, + const uint8_t *param, unsigned param_len) { + return RSA_padding_add_PKCS1_OAEP_mgf1(to, to_len, from, from_len, param, + param_len, NULL, NULL); +} diff --git a/external/boringssl/decrepit/ssl/CMakeLists.txt b/external/boringssl/decrepit/ssl/CMakeLists.txt new file mode 100644 index 0000000000..fba0234d3a --- /dev/null +++ b/external/boringssl/decrepit/ssl/CMakeLists.txt @@ -0,0 +1,9 @@ +include_directories(../../include) + +add_library( + ssl_decrepit + + OBJECT + + ssl_decrepit.c +) diff --git a/external/boringssl/decrepit/ssl/ssl_decrepit.c b/external/boringssl/decrepit/ssl/ssl_decrepit.c new file mode 100644 index 0000000000..e25cbf3119 --- /dev/null +++ b/external/boringssl/decrepit/ssl/ssl_decrepit.c @@ -0,0 +1,225 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include + +#if !defined(OPENSSL_WINDOWS) && !defined(OPENSSL_PNACL) + +#include +#include +#include +#include + +#include +#include + + +typedef struct { + DIR *dir; + struct dirent dirent; +} OPENSSL_DIR_CTX; + +static const char *OPENSSL_DIR_read(OPENSSL_DIR_CTX **ctx, + const char *directory) { + struct dirent *dirent; + + if (ctx == NULL || directory == NULL) { + errno = EINVAL; + return NULL; + } + + errno = 0; + if (*ctx == NULL) { + *ctx = malloc(sizeof(OPENSSL_DIR_CTX)); + if (*ctx == NULL) { + errno = ENOMEM; + return 0; + } + memset(*ctx, 0, sizeof(OPENSSL_DIR_CTX)); + + (*ctx)->dir = opendir(directory); + if ((*ctx)->dir == NULL) { + int save_errno = errno; /* Probably not needed, but I'm paranoid */ + free(*ctx); + *ctx = NULL; + errno = save_errno; + return 0; + } + } + + if (readdir_r((*ctx)->dir, &(*ctx)->dirent, &dirent) != 0 || + dirent == NULL) { + return 0; + } + + return (*ctx)->dirent.d_name; +} + +static int OPENSSL_DIR_end(OPENSSL_DIR_CTX **ctx) { + if (ctx != NULL && *ctx != NULL) { + int r = closedir((*ctx)->dir); + free(*ctx); + *ctx = NULL; + return r == 0; + } + + errno = EINVAL; + return 0; +} + + +/* Add a directory of certs to a stack. + * + * \param stack the stack to append to. + * \param dir the directory to append from. All files in this directory will be + * examined as potential certs. Any that are acceptable to + * SSL_add_dir_cert_subjects_to_stack() that are not already in the stack will + * be included. + * \return 1 for success, 0 for failure. Note that in the case of failure some + * certs may have been added to \c stack. */ +int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack, + const char *dir) { + OPENSSL_DIR_CTX *d = NULL; + const char *filename; + int ret = 0; + + /* Note that a side effect is that the CAs will be sorted by name */ + while ((filename = OPENSSL_DIR_read(&d, dir))) { + char buf[1024]; + int r; + + if (strlen(dir) + strlen(filename) + 2 > sizeof(buf)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_PATH_TOO_LONG); + goto err; + } + + r = BIO_snprintf(buf, sizeof buf, "%s/%s", dir, filename); + if (r <= 0 || r >= (int)sizeof(buf) || + !SSL_add_file_cert_subjects_to_stack(stack, buf)) { + goto err; + } + } + + if (errno) { + OPENSSL_PUT_ERROR(SSL, ERR_R_SYS_LIB); + ERR_add_error_data(3, "OPENSSL_DIR_read(&ctx, '", dir, "')"); + goto err; + } + + ret = 1; + +err: + if (d) { + OPENSSL_DIR_end(&d); + } + return ret; +} + +#endif /* !WINDOWS && !PNACL */ diff --git a/external/boringssl/decrepit/x509/CMakeLists.txt b/external/boringssl/decrepit/x509/CMakeLists.txt new file mode 100644 index 0000000000..930912d19a --- /dev/null +++ b/external/boringssl/decrepit/x509/CMakeLists.txt @@ -0,0 +1,9 @@ +include_directories(../../include) + +add_library( + x509_decrepit + + OBJECT + + x509_decrepit.c +) diff --git a/external/boringssl/decrepit/x509/x509_decrepit.c b/external/boringssl/decrepit/x509/x509_decrepit.c new file mode 100644 index 0000000000..5714b40a0a --- /dev/null +++ b/external/boringssl/decrepit/x509/x509_decrepit.c @@ -0,0 +1,42 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include + + +X509_EXTENSION *X509V3_EXT_conf_nid(LHASH_OF(CONF_VALUE) *conf, + X509V3_CTX *ctx, int ext_nid, char *value) { + CONF *nconf = NULL; + LHASH_OF(CONF_VALUE) *orig_data = NULL; + + if (conf != NULL) { + nconf = NCONF_new(NULL /* no method */); + if (nconf == NULL) { + return NULL; + } + + orig_data = nconf->data; + nconf->data = conf; + } + + X509_EXTENSION *ret = X509V3_EXT_nconf_nid(nconf, ctx, ext_nid, value); + + if (nconf != NULL) { + nconf->data = orig_data; + NCONF_free(nconf); + } + + return ret; +} diff --git a/external/boringssl/decrepit/xts/CMakeLists.txt b/external/boringssl/decrepit/xts/CMakeLists.txt new file mode 100644 index 0000000000..7dccde0377 --- /dev/null +++ b/external/boringssl/decrepit/xts/CMakeLists.txt @@ -0,0 +1,9 @@ +include_directories(../../include) + +add_library( + xts + + OBJECT + + xts.c +) diff --git a/external/boringssl/decrepit/xts/xts.c b/external/boringssl/decrepit/xts/xts.c new file mode 100644 index 0000000000..10a696de04 --- /dev/null +++ b/external/boringssl/decrepit/xts/xts.c @@ -0,0 +1,258 @@ +/* ==================================================================== + * Copyright (c) 2011 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== */ + +#include + +#include + +#include +#include + +#include "../crypto/modes/internal.h" + + +typedef struct xts128_context { + void *key1, *key2; + block128_f block1, block2; +} XTS128_CONTEXT; + +static size_t CRYPTO_xts128_encrypt(const XTS128_CONTEXT *ctx, + const uint8_t iv[16], const uint8_t *inp, + uint8_t *out, size_t len, int enc) { + union { + uint64_t u[2]; + uint32_t d[4]; + uint8_t c[16]; + } tweak, scratch; + unsigned int i; + + if (len < 16) return 0; + + memcpy(tweak.c, iv, 16); + + (*ctx->block2)(tweak.c, tweak.c, ctx->key2); + + if (!enc && (len % 16)) len -= 16; + + while (len >= 16) { +#if STRICT_ALIGNMENT + memcpy(scratch.c, inp, 16); + scratch.u[0] ^= tweak.u[0]; + scratch.u[1] ^= tweak.u[1]; +#else + scratch.u[0] = ((uint64_t *)inp)[0] ^ tweak.u[0]; + scratch.u[1] = ((uint64_t *)inp)[1] ^ tweak.u[1]; +#endif + (*ctx->block1)(scratch.c, scratch.c, ctx->key1); +#if STRICT_ALIGNMENT + scratch.u[0] ^= tweak.u[0]; + scratch.u[1] ^= tweak.u[1]; + memcpy(out, scratch.c, 16); +#else + ((uint64_t *)out)[0] = scratch.u[0] ^= tweak.u[0]; + ((uint64_t *)out)[1] = scratch.u[1] ^= tweak.u[1]; +#endif + inp += 16; + out += 16; + len -= 16; + + if (len == 0) return 1; + + unsigned int carry, res; + + res = 0x87 & (((int)tweak.d[3]) >> 31); + carry = (unsigned int)(tweak.u[0] >> 63); + tweak.u[0] = (tweak.u[0] << 1) ^ res; + tweak.u[1] = (tweak.u[1] << 1) | carry; + } + if (enc) { + for (i = 0; i < len; ++i) { + uint8_t c = inp[i]; + out[i] = scratch.c[i]; + scratch.c[i] = c; + } + scratch.u[0] ^= tweak.u[0]; + scratch.u[1] ^= tweak.u[1]; + (*ctx->block1)(scratch.c, scratch.c, ctx->key1); + scratch.u[0] ^= tweak.u[0]; + scratch.u[1] ^= tweak.u[1]; + memcpy(out - 16, scratch.c, 16); + } else { + union { + uint64_t u[2]; + uint8_t c[16]; + } tweak1; + + unsigned int carry, res; + + res = 0x87 & (((int)tweak.d[3]) >> 31); + carry = (unsigned int)(tweak.u[0] >> 63); + tweak1.u[0] = (tweak.u[0] << 1) ^ res; + tweak1.u[1] = (tweak.u[1] << 1) | carry; +#if STRICT_ALIGNMENT + memcpy(scratch.c, inp, 16); + scratch.u[0] ^= tweak1.u[0]; + scratch.u[1] ^= tweak1.u[1]; +#else + scratch.u[0] = ((uint64_t *)inp)[0] ^ tweak1.u[0]; + scratch.u[1] = ((uint64_t *)inp)[1] ^ tweak1.u[1]; +#endif + (*ctx->block1)(scratch.c, scratch.c, ctx->key1); + scratch.u[0] ^= tweak1.u[0]; + scratch.u[1] ^= tweak1.u[1]; + + for (i = 0; i < len; ++i) { + uint8_t c = inp[16 + i]; + out[16 + i] = scratch.c[i]; + scratch.c[i] = c; + } + scratch.u[0] ^= tweak.u[0]; + scratch.u[1] ^= tweak.u[1]; + (*ctx->block1)(scratch.c, scratch.c, ctx->key1); +#if STRICT_ALIGNMENT + scratch.u[0] ^= tweak.u[0]; + scratch.u[1] ^= tweak.u[1]; + memcpy(out, scratch.c, 16); +#else + ((uint64_t *)out)[0] = scratch.u[0] ^ tweak.u[0]; + ((uint64_t *)out)[1] = scratch.u[1] ^ tweak.u[1]; +#endif + } + + return 1; +} + +typedef struct { + union { + double align; + AES_KEY ks; + } ks1, ks2; /* AES key schedules to use */ + XTS128_CONTEXT xts; +} EVP_AES_XTS_CTX; + +static int aes_xts_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key, + const uint8_t *iv, int enc) { + EVP_AES_XTS_CTX *xctx = ctx->cipher_data; + if (!iv && !key) { + return 1; + } + + if (key) { + /* key_len is two AES keys */ + if (enc) { + AES_set_encrypt_key(key, ctx->key_len * 4, &xctx->ks1.ks); + xctx->xts.block1 = (block128_f) AES_encrypt; + } else { + AES_set_decrypt_key(key, ctx->key_len * 4, &xctx->ks1.ks); + xctx->xts.block1 = (block128_f) AES_decrypt; + } + + AES_set_encrypt_key(key + ctx->key_len / 2, + ctx->key_len * 4, &xctx->ks2.ks); + xctx->xts.block2 = (block128_f) AES_encrypt; + xctx->xts.key1 = &xctx->ks1; + } + + if (iv) { + xctx->xts.key2 = &xctx->ks2; + memcpy(ctx->iv, iv, 16); + } + + return 1; +} + +static int aes_xts_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, + const uint8_t *in, size_t len) { + EVP_AES_XTS_CTX *xctx = ctx->cipher_data; + if (!xctx->xts.key1 || + !xctx->xts.key2 || + !out || + !in || + len < AES_BLOCK_SIZE || + !CRYPTO_xts128_encrypt(&xctx->xts, ctx->iv, in, out, len, ctx->encrypt)) { + return 0; + } + return 1; +} + +static int aes_xts_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) { + EVP_AES_XTS_CTX *xctx = c->cipher_data; + if (type == EVP_CTRL_COPY) { + EVP_CIPHER_CTX *out = ptr; + EVP_AES_XTS_CTX *xctx_out = out->cipher_data; + if (xctx->xts.key1) { + if (xctx->xts.key1 != &xctx->ks1) { + return 0; + } + xctx_out->xts.key1 = &xctx_out->ks1; + } + if (xctx->xts.key2) { + if (xctx->xts.key2 != &xctx->ks2) { + return 0; + } + xctx_out->xts.key2 = &xctx_out->ks2; + } + return 1; + } else if (type != EVP_CTRL_INIT) { + return -1; + } + /* key1 and key2 are used as an indicator both key and IV are set */ + xctx->xts.key1 = NULL; + xctx->xts.key2 = NULL; + return 1; +} + +static const EVP_CIPHER aes_256_xts = { + NID_aes_256_xts, 1 /* block_size */, 64 /* key_size (2 AES keys) */, + 16 /* iv_len */, sizeof(EVP_AES_XTS_CTX), + EVP_CIPH_XTS_MODE | EVP_CIPH_CUSTOM_IV | EVP_CIPH_ALWAYS_CALL_INIT | + EVP_CIPH_CTRL_INIT | EVP_CIPH_CUSTOM_COPY, + NULL /* app_data */, aes_xts_init_key, aes_xts_cipher, + NULL /* cleanup */, aes_xts_ctrl}; + +const EVP_CIPHER *EVP_aes_256_xts(void) { return &aes_256_xts; } diff --git a/external/boringssl/fuzz/CMakeLists.txt b/external/boringssl/fuzz/CMakeLists.txt new file mode 100644 index 0000000000..5bef3ae97e --- /dev/null +++ b/external/boringssl/fuzz/CMakeLists.txt @@ -0,0 +1,66 @@ +include_directories(../include) + +add_executable( + privkey + + privkey.cc +) + +target_link_libraries(privkey Fuzzer) +target_link_libraries(privkey crypto) + +add_executable( + cert + + cert.cc +) + +target_link_libraries(cert Fuzzer) +target_link_libraries(cert crypto) + +add_executable( + spki + + spki.cc +) + +target_link_libraries(spki Fuzzer) +target_link_libraries(spki crypto) + +add_executable( + pkcs8 + + pkcs8.cc +) + +target_link_libraries(pkcs8 Fuzzer) +target_link_libraries(pkcs8 crypto) + +add_executable( + server + + server.cc +) + +target_link_libraries(server Fuzzer) +target_link_libraries(server crypto) +target_link_libraries(server ssl) + +add_executable( + client + + client.cc +) + +target_link_libraries(client Fuzzer) +target_link_libraries(client crypto) +target_link_libraries(client ssl) + +add_executable( + read_pem + + read_pem.cc +) + +target_link_libraries(read_pem Fuzzer) +target_link_libraries(read_pem crypto) diff --git a/external/boringssl/fuzz/cert.cc b/external/boringssl/fuzz/cert.cc new file mode 100644 index 0000000000..b8815a5a0b --- /dev/null +++ b/external/boringssl/fuzz/cert.cc @@ -0,0 +1,32 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include + +extern "C" int LLVMFuzzerTestOneInput(uint8_t *buf, size_t len) { + const uint8_t *bufp = buf; + X509 *x509 = d2i_X509(NULL, &bufp, len); + if (x509 != NULL) { + /* Extract the public key. */ + EVP_PKEY_free(X509_get_pubkey(x509)); + + /* Reserialize the structure. */ + uint8_t *der = NULL; + i2d_X509(x509, &der); + OPENSSL_free(der); + } + X509_free(x509); + return 0; +} diff --git a/external/boringssl/fuzz/cert_corpus/00c85e80891f1b88e11ee5a2502e0f682f0e60be b/external/boringssl/fuzz/cert_corpus/00c85e80891f1b88e11ee5a2502e0f682f0e60be new file mode 100644 index 0000000000..25e3980ac9 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/00c85e80891f1b88e11ee5a2502e0f682f0e60be differ diff --git a/external/boringssl/fuzz/cert_corpus/02e0dfed35539f2a8fe487237de3cf6ba4ebb54f b/external/boringssl/fuzz/cert_corpus/02e0dfed35539f2a8fe487237de3cf6ba4ebb54f new file mode 100644 index 0000000000..ed974654d1 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/02e0dfed35539f2a8fe487237de3cf6ba4ebb54f differ diff --git a/external/boringssl/fuzz/cert_corpus/031c5183d8c8c560e8e1818ff82aabf33973f770 b/external/boringssl/fuzz/cert_corpus/031c5183d8c8c560e8e1818ff82aabf33973f770 new file mode 100644 index 0000000000..f22c66f41c --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/031c5183d8c8c560e8e1818ff82aabf33973f770 @@ -0,0 +1 @@ +Ÿ­œ¹† \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/039d65de40da4745433e149f9fb5ae66f8c90408 b/external/boringssl/fuzz/cert_corpus/039d65de40da4745433e149f9fb5ae66f8c90408 new file mode 100644 index 0000000000..3073da2c06 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/039d65de40da4745433e149f9fb5ae66f8c90408 differ diff --git a/external/boringssl/fuzz/cert_corpus/03b547e325434d1454dfdd34d4819f5b1e234fde b/external/boringssl/fuzz/cert_corpus/03b547e325434d1454dfdd34d4819f5b1e234fde new file mode 100644 index 0000000000..132c924399 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/03b547e325434d1454dfdd34d4819f5b1e234fde differ diff --git a/external/boringssl/fuzz/cert_corpus/04ed1e2c50886acd723b3a78d4bafd49938bd14d b/external/boringssl/fuzz/cert_corpus/04ed1e2c50886acd723b3a78d4bafd49938bd14d new file mode 100644 index 0000000000..2765f008a7 --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/04ed1e2c50886acd723b3a78d4bafd49938bd14d @@ -0,0 +1 @@ +0†:;€0 \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/054cb963aaf9b554874b32275f44520641a11d41 b/external/boringssl/fuzz/cert_corpus/054cb963aaf9b554874b32275f44520641a11d41 new file mode 100644 index 0000000000..2e7495721b Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/054cb963aaf9b554874b32275f44520641a11d41 differ diff --git a/external/boringssl/fuzz/cert_corpus/0694a2168fe7699e2dcabe3386a80bd4209094fc b/external/boringssl/fuzz/cert_corpus/0694a2168fe7699e2dcabe3386a80bd4209094fc new file mode 100644 index 0000000000..2f9e77f7b9 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/0694a2168fe7699e2dcabe3386a80bd4209094fc differ diff --git a/external/boringssl/fuzz/cert_corpus/08464c9f40426e219bdd673525af22a89b62c4d3 b/external/boringssl/fuzz/cert_corpus/08464c9f40426e219bdd673525af22a89b62c4d3 new file mode 100644 index 0000000000..bce3ec1153 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/08464c9f40426e219bdd673525af22a89b62c4d3 differ diff --git a/external/boringssl/fuzz/cert_corpus/09406b74a5fd8ad9a82052a835c24dc3194d9704 b/external/boringssl/fuzz/cert_corpus/09406b74a5fd8ad9a82052a835c24dc3194d9704 new file mode 100644 index 0000000000..877a49b532 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/09406b74a5fd8ad9a82052a835c24dc3194d9704 differ diff --git a/external/boringssl/fuzz/cert_corpus/094d3581e71a4316a567e43e6ebfa63b95196b8e b/external/boringssl/fuzz/cert_corpus/094d3581e71a4316a567e43e6ebfa63b95196b8e new file mode 100644 index 0000000000..8d21c6f489 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/094d3581e71a4316a567e43e6ebfa63b95196b8e differ diff --git a/external/boringssl/fuzz/cert_corpus/095554da7da9b4234670b7f47cf9663c9c60c144 b/external/boringssl/fuzz/cert_corpus/095554da7da9b4234670b7f47cf9663c9c60c144 new file mode 100644 index 0000000000..44d087c055 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/095554da7da9b4234670b7f47cf9663c9c60c144 differ diff --git a/external/boringssl/fuzz/cert_corpus/0969cd6815249cf0c66b302b20e71ef677b1c3e5 b/external/boringssl/fuzz/cert_corpus/0969cd6815249cf0c66b302b20e71ef677b1c3e5 new file mode 100644 index 0000000000..902db25310 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/0969cd6815249cf0c66b302b20e71ef677b1c3e5 differ diff --git a/external/boringssl/fuzz/cert_corpus/0b2f2af22568510301982a60fba3763b6ca92409 b/external/boringssl/fuzz/cert_corpus/0b2f2af22568510301982a60fba3763b6ca92409 new file mode 100644 index 0000000000..d48401c68e Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/0b2f2af22568510301982a60fba3763b6ca92409 differ diff --git a/external/boringssl/fuzz/cert_corpus/0ba8e2a62b579b857e560bf1201fad463318c73e b/external/boringssl/fuzz/cert_corpus/0ba8e2a62b579b857e560bf1201fad463318c73e new file mode 100644 index 0000000000..220384f71b Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/0ba8e2a62b579b857e560bf1201fad463318c73e differ diff --git a/external/boringssl/fuzz/cert_corpus/0bacf5f9ce89ed83a29bf8b01109f1ebd5b1a627 b/external/boringssl/fuzz/cert_corpus/0bacf5f9ce89ed83a29bf8b01109f1ebd5b1a627 new file mode 100644 index 0000000000..c063caef98 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/0bacf5f9ce89ed83a29bf8b01109f1ebd5b1a627 differ diff --git a/external/boringssl/fuzz/cert_corpus/0be05d072f2f3828875fdfc55b04ff0f0ae9fc59 b/external/boringssl/fuzz/cert_corpus/0be05d072f2f3828875fdfc55b04ff0f0ae9fc59 new file mode 100644 index 0000000000..2fea51cca1 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/0be05d072f2f3828875fdfc55b04ff0f0ae9fc59 differ diff --git a/external/boringssl/fuzz/cert_corpus/0c30def9baf58c5be015cede0594b4bd73507f00 b/external/boringssl/fuzz/cert_corpus/0c30def9baf58c5be015cede0594b4bd73507f00 new file mode 100644 index 0000000000..67f9146b32 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/0c30def9baf58c5be015cede0594b4bd73507f00 differ diff --git a/external/boringssl/fuzz/cert_corpus/0d8ec36263c4e32e25e4ef1f01baed35b6227d3c b/external/boringssl/fuzz/cert_corpus/0d8ec36263c4e32e25e4ef1f01baed35b6227d3c new file mode 100644 index 0000000000..74a03643cd Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/0d8ec36263c4e32e25e4ef1f01baed35b6227d3c differ diff --git a/external/boringssl/fuzz/cert_corpus/0db3ab78e42c2aecbc7b898501c4f91ba91c200f b/external/boringssl/fuzz/cert_corpus/0db3ab78e42c2aecbc7b898501c4f91ba91c200f new file mode 100644 index 0000000000..24f68d985f Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/0db3ab78e42c2aecbc7b898501c4f91ba91c200f differ diff --git a/external/boringssl/fuzz/cert_corpus/0db7a0d1afb99cd01fafa18b2961c6623f5b1d8f b/external/boringssl/fuzz/cert_corpus/0db7a0d1afb99cd01fafa18b2961c6623f5b1d8f new file mode 100644 index 0000000000..d16502498a Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/0db7a0d1afb99cd01fafa18b2961c6623f5b1d8f differ diff --git a/external/boringssl/fuzz/cert_corpus/0e29ba7cbd357efa6d2619ea98ef275e0b13a1de b/external/boringssl/fuzz/cert_corpus/0e29ba7cbd357efa6d2619ea98ef275e0b13a1de new file mode 100644 index 0000000000..266f737eca Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/0e29ba7cbd357efa6d2619ea98ef275e0b13a1de differ diff --git a/external/boringssl/fuzz/cert_corpus/0eb5037935ba1c2791f3b7e9bc8470c3c60d2aff b/external/boringssl/fuzz/cert_corpus/0eb5037935ba1c2791f3b7e9bc8470c3c60d2aff new file mode 100644 index 0000000000..1c8ce6f6a0 --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/0eb5037935ba1c2791f3b7e9bc8470c3c60d2aff @@ -0,0 +1 @@ +0€ \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/0fa9626b934e330a7cc18c118e31aad5639f2dad b/external/boringssl/fuzz/cert_corpus/0fa9626b934e330a7cc18c118e31aad5639f2dad new file mode 100644 index 0000000000..3b2ca66c0a Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/0fa9626b934e330a7cc18c118e31aad5639f2dad differ diff --git a/external/boringssl/fuzz/cert_corpus/0ff9646573d3cbb8cfad86755ff52cad4788fcb1 b/external/boringssl/fuzz/cert_corpus/0ff9646573d3cbb8cfad86755ff52cad4788fcb1 new file mode 100644 index 0000000000..a342e7e48c Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/0ff9646573d3cbb8cfad86755ff52cad4788fcb1 differ diff --git a/external/boringssl/fuzz/cert_corpus/1108c80f8912d5d9492de40e48dbdb7e44ae4a8c b/external/boringssl/fuzz/cert_corpus/1108c80f8912d5d9492de40e48dbdb7e44ae4a8c new file mode 100644 index 0000000000..d30626c94e Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/1108c80f8912d5d9492de40e48dbdb7e44ae4a8c differ diff --git a/external/boringssl/fuzz/cert_corpus/1173445eb10e631879bf6b5cc168e2b8fb89dbdf b/external/boringssl/fuzz/cert_corpus/1173445eb10e631879bf6b5cc168e2b8fb89dbdf new file mode 100644 index 0000000000..660f0b00db Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/1173445eb10e631879bf6b5cc168e2b8fb89dbdf differ diff --git a/external/boringssl/fuzz/cert_corpus/1288e7bc9178d23aa6662dc5348b8010e6b4ec92 b/external/boringssl/fuzz/cert_corpus/1288e7bc9178d23aa6662dc5348b8010e6b4ec92 new file mode 100644 index 0000000000..dab7340385 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/1288e7bc9178d23aa6662dc5348b8010e6b4ec92 differ diff --git a/external/boringssl/fuzz/cert_corpus/1293428367413052338e0b8b9e2660fea076f900 b/external/boringssl/fuzz/cert_corpus/1293428367413052338e0b8b9e2660fea076f900 new file mode 100644 index 0000000000..63be22dca0 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/1293428367413052338e0b8b9e2660fea076f900 differ diff --git a/external/boringssl/fuzz/cert_corpus/1400c7baa454c64e5e1bc6454bfbef3700c881bc b/external/boringssl/fuzz/cert_corpus/1400c7baa454c64e5e1bc6454bfbef3700c881bc new file mode 100644 index 0000000000..64b57dfe2e Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/1400c7baa454c64e5e1bc6454bfbef3700c881bc differ diff --git a/external/boringssl/fuzz/cert_corpus/148fc92ab76dab6ffbb59a544e9174ecf32f187b b/external/boringssl/fuzz/cert_corpus/148fc92ab76dab6ffbb59a544e9174ecf32f187b new file mode 100644 index 0000000000..90f7ca414a Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/148fc92ab76dab6ffbb59a544e9174ecf32f187b differ diff --git a/external/boringssl/fuzz/cert_corpus/152bd97b8a6e893d704db2947e31f2e7dd7f9c63 b/external/boringssl/fuzz/cert_corpus/152bd97b8a6e893d704db2947e31f2e7dd7f9c63 new file mode 100644 index 0000000000..09c1daf363 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/152bd97b8a6e893d704db2947e31f2e7dd7f9c63 differ diff --git a/external/boringssl/fuzz/cert_corpus/159cc124352f0c0ac1cef2399c5c25614e29c6eb b/external/boringssl/fuzz/cert_corpus/159cc124352f0c0ac1cef2399c5c25614e29c6eb new file mode 100644 index 0000000000..d435368e13 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/159cc124352f0c0ac1cef2399c5c25614e29c6eb differ diff --git a/external/boringssl/fuzz/cert_corpus/15c89fc35e674fcd2fca3563669cc3c02db164ac b/external/boringssl/fuzz/cert_corpus/15c89fc35e674fcd2fca3563669cc3c02db164ac new file mode 100644 index 0000000000..4e5cc3b344 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/15c89fc35e674fcd2fca3563669cc3c02db164ac differ diff --git a/external/boringssl/fuzz/cert_corpus/162f227ef1629ac9a11a433bf124d297aedac5ef b/external/boringssl/fuzz/cert_corpus/162f227ef1629ac9a11a433bf124d297aedac5ef new file mode 100644 index 0000000000..e63653dd0a Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/162f227ef1629ac9a11a433bf124d297aedac5ef differ diff --git a/external/boringssl/fuzz/cert_corpus/163fd7d62de6042f6353f383cdc0b700e0980f8a b/external/boringssl/fuzz/cert_corpus/163fd7d62de6042f6353f383cdc0b700e0980f8a new file mode 100644 index 0000000000..df739fc013 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/163fd7d62de6042f6353f383cdc0b700e0980f8a differ diff --git a/external/boringssl/fuzz/cert_corpus/173db5dac0923eaaf0516593ec62ff48d07aa938 b/external/boringssl/fuzz/cert_corpus/173db5dac0923eaaf0516593ec62ff48d07aa938 new file mode 100644 index 0000000000..4595890a32 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/173db5dac0923eaaf0516593ec62ff48d07aa938 differ diff --git a/external/boringssl/fuzz/cert_corpus/183c776a51a73466cf9f32b5d22f05cf1348fa90 b/external/boringssl/fuzz/cert_corpus/183c776a51a73466cf9f32b5d22f05cf1348fa90 new file mode 100644 index 0000000000..216621484d Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/183c776a51a73466cf9f32b5d22f05cf1348fa90 differ diff --git a/external/boringssl/fuzz/cert_corpus/1894a7ef9741425a741189996181a7b85773a94e b/external/boringssl/fuzz/cert_corpus/1894a7ef9741425a741189996181a7b85773a94e new file mode 100644 index 0000000000..2005ec5424 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/1894a7ef9741425a741189996181a7b85773a94e differ diff --git a/external/boringssl/fuzz/cert_corpus/1950704c247d49ee53fde32fcdff958b44bdd2ea b/external/boringssl/fuzz/cert_corpus/1950704c247d49ee53fde32fcdff958b44bdd2ea new file mode 100644 index 0000000000..1c50fb0ddd Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/1950704c247d49ee53fde32fcdff958b44bdd2ea differ diff --git a/external/boringssl/fuzz/cert_corpus/19a0a17b14c3a849d626f6b61219959343a575d7 b/external/boringssl/fuzz/cert_corpus/19a0a17b14c3a849d626f6b61219959343a575d7 new file mode 100644 index 0000000000..fe6520c7b8 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/19a0a17b14c3a849d626f6b61219959343a575d7 differ diff --git a/external/boringssl/fuzz/cert_corpus/1a6654c8844f6eb41d34508e4330111cc14a4875 b/external/boringssl/fuzz/cert_corpus/1a6654c8844f6eb41d34508e4330111cc14a4875 new file mode 100644 index 0000000000..310216fbb6 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/1a6654c8844f6eb41d34508e4330111cc14a4875 differ diff --git a/external/boringssl/fuzz/cert_corpus/1a75d3e2d9ee4c34fb8d7506be6b2d762f6215d9 b/external/boringssl/fuzz/cert_corpus/1a75d3e2d9ee4c34fb8d7506be6b2d762f6215d9 new file mode 100644 index 0000000000..dbac0f398f Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/1a75d3e2d9ee4c34fb8d7506be6b2d762f6215d9 differ diff --git a/external/boringssl/fuzz/cert_corpus/1b4aac6123267d5f6258899bb6ccd01747a87ba8 b/external/boringssl/fuzz/cert_corpus/1b4aac6123267d5f6258899bb6ccd01747a87ba8 new file mode 100644 index 0000000000..b52e4ddf14 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/1b4aac6123267d5f6258899bb6ccd01747a87ba8 differ diff --git a/external/boringssl/fuzz/cert_corpus/1b9384af3bcfce2b1cb34dcc4541fc1177e18dae b/external/boringssl/fuzz/cert_corpus/1b9384af3bcfce2b1cb34dcc4541fc1177e18dae new file mode 100644 index 0000000000..b33f9ccdda Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/1b9384af3bcfce2b1cb34dcc4541fc1177e18dae differ diff --git a/external/boringssl/fuzz/cert_corpus/1ba101e147f4453f2c709c037ae506cd79b6d7c7 b/external/boringssl/fuzz/cert_corpus/1ba101e147f4453f2c709c037ae506cd79b6d7c7 new file mode 100644 index 0000000000..362abb3782 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/1ba101e147f4453f2c709c037ae506cd79b6d7c7 differ diff --git a/external/boringssl/fuzz/cert_corpus/1ced169e5e3c017b015637eeb88afcd7d48bafc2 b/external/boringssl/fuzz/cert_corpus/1ced169e5e3c017b015637eeb88afcd7d48bafc2 new file mode 100644 index 0000000000..8b0fbf38eb --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/1ced169e5e3c017b015637eeb88afcd7d48bafc2 @@ -0,0 +1 @@ +0€0€(í0‚€0‚h €1’h A!1hö|0‚%“¥0  *†€00¯€€0 \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/1d61ed4eb67ed64942174bea48a77523a805a3e0 b/external/boringssl/fuzz/cert_corpus/1d61ed4eb67ed64942174bea48a77523a805a3e0 new file mode 100644 index 0000000000..88e4e80f8b Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/1d61ed4eb67ed64942174bea48a77523a805a3e0 differ diff --git a/external/boringssl/fuzz/cert_corpus/1d6b1f58a8be854b7667c019b5c470f3d325d575 b/external/boringssl/fuzz/cert_corpus/1d6b1f58a8be854b7667c019b5c470f3d325d575 new file mode 100644 index 0000000000..27a2a39a76 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/1d6b1f58a8be854b7667c019b5c470f3d325d575 differ diff --git a/external/boringssl/fuzz/cert_corpus/1d752734c8ecb0ffb7d98801159f9cfbd97e0d01 b/external/boringssl/fuzz/cert_corpus/1d752734c8ecb0ffb7d98801159f9cfbd97e0d01 new file mode 100644 index 0000000000..79023b1110 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/1d752734c8ecb0ffb7d98801159f9cfbd97e0d01 differ diff --git a/external/boringssl/fuzz/cert_corpus/2172996f7233ccd5607b6414058e64ac7c9bcdca b/external/boringssl/fuzz/cert_corpus/2172996f7233ccd5607b6414058e64ac7c9bcdca new file mode 100644 index 0000000000..51396035dd Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/2172996f7233ccd5607b6414058e64ac7c9bcdca differ diff --git a/external/boringssl/fuzz/cert_corpus/2199b815cfe8b39732b8eb2847f6b5008a75d189 b/external/boringssl/fuzz/cert_corpus/2199b815cfe8b39732b8eb2847f6b5008a75d189 new file mode 100644 index 0000000000..731b90c4f5 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/2199b815cfe8b39732b8eb2847f6b5008a75d189 differ diff --git a/external/boringssl/fuzz/cert_corpus/21a4835c0fe0b0a69bab262724f6356f7c008132 b/external/boringssl/fuzz/cert_corpus/21a4835c0fe0b0a69bab262724f6356f7c008132 new file mode 100644 index 0000000000..532aae11e7 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/21a4835c0fe0b0a69bab262724f6356f7c008132 differ diff --git a/external/boringssl/fuzz/cert_corpus/22a7767a68debe1a1cfdb43355d2c9332ac88409 b/external/boringssl/fuzz/cert_corpus/22a7767a68debe1a1cfdb43355d2c9332ac88409 new file mode 100644 index 0000000000..e42a5d4ba3 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/22a7767a68debe1a1cfdb43355d2c9332ac88409 differ diff --git a/external/boringssl/fuzz/cert_corpus/2357c3ad0b6adfa54a5fe88b7f99b1c21416d304 b/external/boringssl/fuzz/cert_corpus/2357c3ad0b6adfa54a5fe88b7f99b1c21416d304 new file mode 100644 index 0000000000..61cdabad30 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/2357c3ad0b6adfa54a5fe88b7f99b1c21416d304 differ diff --git a/external/boringssl/fuzz/cert_corpus/23da98cdc1af6ef01ca8fad38ac021910832fe02 b/external/boringssl/fuzz/cert_corpus/23da98cdc1af6ef01ca8fad38ac021910832fe02 new file mode 100644 index 0000000000..39e6d6bec4 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/23da98cdc1af6ef01ca8fad38ac021910832fe02 differ diff --git a/external/boringssl/fuzz/cert_corpus/245c09cd01ac5a3a74dc5c2c2d11921978ebc4ed b/external/boringssl/fuzz/cert_corpus/245c09cd01ac5a3a74dc5c2c2d11921978ebc4ed new file mode 100644 index 0000000000..4b58072a50 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/245c09cd01ac5a3a74dc5c2c2d11921978ebc4ed differ diff --git a/external/boringssl/fuzz/cert_corpus/24fad8b85d8f1129e12f742472a4895aadef1872 b/external/boringssl/fuzz/cert_corpus/24fad8b85d8f1129e12f742472a4895aadef1872 new file mode 100644 index 0000000000..26db40278b Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/24fad8b85d8f1129e12f742472a4895aadef1872 differ diff --git a/external/boringssl/fuzz/cert_corpus/25e586f9292916959c71561431fecfc188dcf69e b/external/boringssl/fuzz/cert_corpus/25e586f9292916959c71561431fecfc188dcf69e new file mode 100644 index 0000000000..318611cc5a Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/25e586f9292916959c71561431fecfc188dcf69e differ diff --git a/external/boringssl/fuzz/cert_corpus/272ed7d95717a523c65e5cbf1849f89041cb58a4 b/external/boringssl/fuzz/cert_corpus/272ed7d95717a523c65e5cbf1849f89041cb58a4 new file mode 100644 index 0000000000..f3bdb763d5 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/272ed7d95717a523c65e5cbf1849f89041cb58a4 differ diff --git a/external/boringssl/fuzz/cert_corpus/277042c5f5018c9e4ead5db206baf143f0a1a9a1 b/external/boringssl/fuzz/cert_corpus/277042c5f5018c9e4ead5db206baf143f0a1a9a1 new file mode 100644 index 0000000000..750eb09d33 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/277042c5f5018c9e4ead5db206baf143f0a1a9a1 differ diff --git a/external/boringssl/fuzz/cert_corpus/29164dbd53e8108c324376573091e4c4213d5bf4 b/external/boringssl/fuzz/cert_corpus/29164dbd53e8108c324376573091e4c4213d5bf4 new file mode 100644 index 0000000000..24181ca62a Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/29164dbd53e8108c324376573091e4c4213d5bf4 differ diff --git a/external/boringssl/fuzz/cert_corpus/2957f98f3f77110b8a05a8d67a1ff574f090c2b3 b/external/boringssl/fuzz/cert_corpus/2957f98f3f77110b8a05a8d67a1ff574f090c2b3 new file mode 100644 index 0000000000..16db3b2edd Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/2957f98f3f77110b8a05a8d67a1ff574f090c2b3 differ diff --git a/external/boringssl/fuzz/cert_corpus/29e05bbfa0e8cb0a9b3bd679b0572bf5229c26c8 b/external/boringssl/fuzz/cert_corpus/29e05bbfa0e8cb0a9b3bd679b0572bf5229c26c8 new file mode 100644 index 0000000000..dcd4a2c4a5 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/29e05bbfa0e8cb0a9b3bd679b0572bf5229c26c8 differ diff --git a/external/boringssl/fuzz/cert_corpus/29f8bb7ef38d13bff66e3c52ba2f20376731c2c1 b/external/boringssl/fuzz/cert_corpus/29f8bb7ef38d13bff66e3c52ba2f20376731c2c1 new file mode 100644 index 0000000000..51a8f09041 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/29f8bb7ef38d13bff66e3c52ba2f20376731c2c1 differ diff --git a/external/boringssl/fuzz/cert_corpus/2a0d8199c1117a1cee556ce8e13fdce6c00529f8 b/external/boringssl/fuzz/cert_corpus/2a0d8199c1117a1cee556ce8e13fdce6c00529f8 new file mode 100644 index 0000000000..3553e97f3f Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/2a0d8199c1117a1cee556ce8e13fdce6c00529f8 differ diff --git a/external/boringssl/fuzz/cert_corpus/2ab7a88a553b5b82b4346b4ed2abb832bf9ac6c2 b/external/boringssl/fuzz/cert_corpus/2ab7a88a553b5b82b4346b4ed2abb832bf9ac6c2 new file mode 100644 index 0000000000..01423b80ab Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/2ab7a88a553b5b82b4346b4ed2abb832bf9ac6c2 differ diff --git a/external/boringssl/fuzz/cert_corpus/2adda7db83a6e20697612ee835c58415072899f0 b/external/boringssl/fuzz/cert_corpus/2adda7db83a6e20697612ee835c58415072899f0 new file mode 100644 index 0000000000..6a7b6527a9 --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/2adda7db83a6e20697612ee835c58415072899f0 @@ -0,0 +1 @@ +Ȇ!: \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/2c3735c25b884954b3daf5fe573d89f5d516df4a b/external/boringssl/fuzz/cert_corpus/2c3735c25b884954b3daf5fe573d89f5d516df4a new file mode 100644 index 0000000000..9c94c1d697 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/2c3735c25b884954b3daf5fe573d89f5d516df4a differ diff --git a/external/boringssl/fuzz/cert_corpus/2c3743ad90044cc189240b7874e6e4df3ce69571 b/external/boringssl/fuzz/cert_corpus/2c3743ad90044cc189240b7874e6e4df3ce69571 new file mode 100644 index 0000000000..02e3915380 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/2c3743ad90044cc189240b7874e6e4df3ce69571 differ diff --git a/external/boringssl/fuzz/cert_corpus/2cd91be7451b6016cee440fb86e06c7afd157e79 b/external/boringssl/fuzz/cert_corpus/2cd91be7451b6016cee440fb86e06c7afd157e79 new file mode 100644 index 0000000000..21d883a6ec Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/2cd91be7451b6016cee440fb86e06c7afd157e79 differ diff --git a/external/boringssl/fuzz/cert_corpus/2d0c5affedc4d6a45b59a45abd71cf4b59efb5f1 b/external/boringssl/fuzz/cert_corpus/2d0c5affedc4d6a45b59a45abd71cf4b59efb5f1 new file mode 100644 index 0000000000..b941ede880 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/2d0c5affedc4d6a45b59a45abd71cf4b59efb5f1 differ diff --git a/external/boringssl/fuzz/cert_corpus/2e1f157c8c157903e5e862dcb34fb3b7be376879 b/external/boringssl/fuzz/cert_corpus/2e1f157c8c157903e5e862dcb34fb3b7be376879 new file mode 100644 index 0000000000..63777aa220 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/2e1f157c8c157903e5e862dcb34fb3b7be376879 differ diff --git a/external/boringssl/fuzz/cert_corpus/2e375a900fedc57b49326e77554e6550fdc1e436 b/external/boringssl/fuzz/cert_corpus/2e375a900fedc57b49326e77554e6550fdc1e436 new file mode 100644 index 0000000000..229d9e1bf0 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/2e375a900fedc57b49326e77554e6550fdc1e436 differ diff --git a/external/boringssl/fuzz/cert_corpus/2e4777559846e771a689f12bdc77806853cf4d08 b/external/boringssl/fuzz/cert_corpus/2e4777559846e771a689f12bdc77806853cf4d08 new file mode 100644 index 0000000000..e2671461b1 --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/2e4777559846e771a689f12bdc77806853cf4d08 @@ -0,0 +1 @@ +€1’h A1hö|%“å000‚€0‚h  \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/2ef6c305d2b8478403c470bfc09807d3cfedcd42 b/external/boringssl/fuzz/cert_corpus/2ef6c305d2b8478403c470bfc09807d3cfedcd42 new file mode 100644 index 0000000000..15e70080c5 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/2ef6c305d2b8478403c470bfc09807d3cfedcd42 differ diff --git a/external/boringssl/fuzz/cert_corpus/301c5e78f8b0334ee078e8e89eba2d9ea545d572 b/external/boringssl/fuzz/cert_corpus/301c5e78f8b0334ee078e8e89eba2d9ea545d572 new file mode 100644 index 0000000000..caea8d8be6 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/301c5e78f8b0334ee078e8e89eba2d9ea545d572 differ diff --git a/external/boringssl/fuzz/cert_corpus/301f44ea637ab6dbc97d15ace5a3250215c999ad b/external/boringssl/fuzz/cert_corpus/301f44ea637ab6dbc97d15ace5a3250215c999ad new file mode 100644 index 0000000000..ccb2275825 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/301f44ea637ab6dbc97d15ace5a3250215c999ad differ diff --git a/external/boringssl/fuzz/cert_corpus/312cbcea0df790d023073e9dc5de165190f86b5b b/external/boringssl/fuzz/cert_corpus/312cbcea0df790d023073e9dc5de165190f86b5b new file mode 100644 index 0000000000..15d763e752 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/312cbcea0df790d023073e9dc5de165190f86b5b differ diff --git a/external/boringssl/fuzz/cert_corpus/31dad1d547e55649e2ca06f479081d5418d212b1 b/external/boringssl/fuzz/cert_corpus/31dad1d547e55649e2ca06f479081d5418d212b1 new file mode 100644 index 0000000000..6bcd137ce5 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/31dad1d547e55649e2ca06f479081d5418d212b1 differ diff --git a/external/boringssl/fuzz/cert_corpus/3256b480f1212007bcb0e53ef124ead78ec30b9b b/external/boringssl/fuzz/cert_corpus/3256b480f1212007bcb0e53ef124ead78ec30b9b new file mode 100644 index 0000000000..550f4c9074 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/3256b480f1212007bcb0e53ef124ead78ec30b9b differ diff --git a/external/boringssl/fuzz/cert_corpus/340cd6562eb74d264b8a8123b49fc3babb6033bd b/external/boringssl/fuzz/cert_corpus/340cd6562eb74d264b8a8123b49fc3babb6033bd new file mode 100644 index 0000000000..de773a6bc2 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/340cd6562eb74d264b8a8123b49fc3babb6033bd differ diff --git a/external/boringssl/fuzz/cert_corpus/3607fbd5d18f5f196e2ad467b39c31d80c136f06 b/external/boringssl/fuzz/cert_corpus/3607fbd5d18f5f196e2ad467b39c31d80c136f06 new file mode 100644 index 0000000000..0c30057b58 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/3607fbd5d18f5f196e2ad467b39c31d80c136f06 differ diff --git a/external/boringssl/fuzz/cert_corpus/360e330b02ff481851b528cdb2fdc952d21afa91 b/external/boringssl/fuzz/cert_corpus/360e330b02ff481851b528cdb2fdc952d21afa91 new file mode 100644 index 0000000000..16dbc90c00 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/360e330b02ff481851b528cdb2fdc952d21afa91 differ diff --git a/external/boringssl/fuzz/cert_corpus/3663d7a7c4840fccf48c134a13eed5156b44055e b/external/boringssl/fuzz/cert_corpus/3663d7a7c4840fccf48c134a13eed5156b44055e new file mode 100644 index 0000000000..9368c7b1fc Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/3663d7a7c4840fccf48c134a13eed5156b44055e differ diff --git a/external/boringssl/fuzz/cert_corpus/3666ba893cec5a069376d0b91532ab4317b720a9 b/external/boringssl/fuzz/cert_corpus/3666ba893cec5a069376d0b91532ab4317b720a9 new file mode 100644 index 0000000000..07673247f3 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/3666ba893cec5a069376d0b91532ab4317b720a9 differ diff --git a/external/boringssl/fuzz/cert_corpus/370522e931da2c14602da88ac1a9b781f0d7a17f b/external/boringssl/fuzz/cert_corpus/370522e931da2c14602da88ac1a9b781f0d7a17f new file mode 100644 index 0000000000..ac2a24f531 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/370522e931da2c14602da88ac1a9b781f0d7a17f differ diff --git a/external/boringssl/fuzz/cert_corpus/375a68f804031aaaf103a54625036bf419656cb0 b/external/boringssl/fuzz/cert_corpus/375a68f804031aaaf103a54625036bf419656cb0 new file mode 100644 index 0000000000..8fa5ff7fe3 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/375a68f804031aaaf103a54625036bf419656cb0 differ diff --git a/external/boringssl/fuzz/cert_corpus/37ea6223d496dd2bb8d317b752010198d1fc14c7 b/external/boringssl/fuzz/cert_corpus/37ea6223d496dd2bb8d317b752010198d1fc14c7 new file mode 100644 index 0000000000..03d905b85b Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/37ea6223d496dd2bb8d317b752010198d1fc14c7 differ diff --git a/external/boringssl/fuzz/cert_corpus/37ffecbaa9a8f5540d94963beb62d93e8f1c568d b/external/boringssl/fuzz/cert_corpus/37ffecbaa9a8f5540d94963beb62d93e8f1c568d new file mode 100644 index 0000000000..1195907bd3 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/37ffecbaa9a8f5540d94963beb62d93e8f1c568d differ diff --git a/external/boringssl/fuzz/cert_corpus/3834b376516fd4984fc5dc3b8f42a1fabd74664c b/external/boringssl/fuzz/cert_corpus/3834b376516fd4984fc5dc3b8f42a1fabd74664c new file mode 100644 index 0000000000..1cab213853 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/3834b376516fd4984fc5dc3b8f42a1fabd74664c differ diff --git a/external/boringssl/fuzz/cert_corpus/38d7a3a0edc77172b1663880ceda8d1ab373a0d6 b/external/boringssl/fuzz/cert_corpus/38d7a3a0edc77172b1663880ceda8d1ab373a0d6 new file mode 100644 index 0000000000..8cd3819b2b Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/38d7a3a0edc77172b1663880ceda8d1ab373a0d6 differ diff --git a/external/boringssl/fuzz/cert_corpus/3922605043f42c4868f47dd2463d2858fadfe0c4 b/external/boringssl/fuzz/cert_corpus/3922605043f42c4868f47dd2463d2858fadfe0c4 new file mode 100644 index 0000000000..5c0b792502 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/3922605043f42c4868f47dd2463d2858fadfe0c4 differ diff --git a/external/boringssl/fuzz/cert_corpus/39fe902954bf3c1e0a033d33528e090c8c7835ee b/external/boringssl/fuzz/cert_corpus/39fe902954bf3c1e0a033d33528e090c8c7835ee new file mode 100644 index 0000000000..d3bd31da65 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/39fe902954bf3c1e0a033d33528e090c8c7835ee differ diff --git a/external/boringssl/fuzz/cert_corpus/3b7f75154dca9e79b5662226dc6c939b8aa7ac33 b/external/boringssl/fuzz/cert_corpus/3b7f75154dca9e79b5662226dc6c939b8aa7ac33 new file mode 100644 index 0000000000..82ceb520c3 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/3b7f75154dca9e79b5662226dc6c939b8aa7ac33 differ diff --git a/external/boringssl/fuzz/cert_corpus/3bac41829e17f9dc2f349d90283030f97e9c6541 b/external/boringssl/fuzz/cert_corpus/3bac41829e17f9dc2f349d90283030f97e9c6541 new file mode 100644 index 0000000000..5534c4b5cf Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/3bac41829e17f9dc2f349d90283030f97e9c6541 differ diff --git a/external/boringssl/fuzz/cert_corpus/3c2763aa2e94dc845be54417f2ca9c1386720151 b/external/boringssl/fuzz/cert_corpus/3c2763aa2e94dc845be54417f2ca9c1386720151 new file mode 100644 index 0000000000..ef62d9ebff Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/3c2763aa2e94dc845be54417f2ca9c1386720151 differ diff --git a/external/boringssl/fuzz/cert_corpus/3d1dc5780b01d8d4e3381d534b36ac875d2e8537 b/external/boringssl/fuzz/cert_corpus/3d1dc5780b01d8d4e3381d534b36ac875d2e8537 new file mode 100644 index 0000000000..40ad5df160 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/3d1dc5780b01d8d4e3381d534b36ac875d2e8537 differ diff --git a/external/boringssl/fuzz/cert_corpus/3decf06ce7e54513145619feedb9ad5ba96e898d b/external/boringssl/fuzz/cert_corpus/3decf06ce7e54513145619feedb9ad5ba96e898d new file mode 100644 index 0000000000..f65e28b874 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/3decf06ce7e54513145619feedb9ad5ba96e898d differ diff --git a/external/boringssl/fuzz/cert_corpus/3e5d5a9ba52db7de52d2aa3a08f95c35ae9b9137 b/external/boringssl/fuzz/cert_corpus/3e5d5a9ba52db7de52d2aa3a08f95c35ae9b9137 new file mode 100644 index 0000000000..2ec21a4b9e Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/3e5d5a9ba52db7de52d2aa3a08f95c35ae9b9137 differ diff --git a/external/boringssl/fuzz/cert_corpus/3eace4afa12afe234d6ded7d08130217fc2c9645 b/external/boringssl/fuzz/cert_corpus/3eace4afa12afe234d6ded7d08130217fc2c9645 new file mode 100644 index 0000000000..8e6697387d Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/3eace4afa12afe234d6ded7d08130217fc2c9645 differ diff --git a/external/boringssl/fuzz/cert_corpus/3f1f7551d55ebb535cb54aa24037a83275b0c89a b/external/boringssl/fuzz/cert_corpus/3f1f7551d55ebb535cb54aa24037a83275b0c89a new file mode 100644 index 0000000000..c8dbfdbad6 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/3f1f7551d55ebb535cb54aa24037a83275b0c89a differ diff --git a/external/boringssl/fuzz/cert_corpus/3fa31bd76bae27f66b61c63a4abfc461bd371934 b/external/boringssl/fuzz/cert_corpus/3fa31bd76bae27f66b61c63a4abfc461bd371934 new file mode 100644 index 0000000000..83452a8133 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/3fa31bd76bae27f66b61c63a4abfc461bd371934 differ diff --git a/external/boringssl/fuzz/cert_corpus/40ac31d214a40326d74fdf7814ca312288360fab b/external/boringssl/fuzz/cert_corpus/40ac31d214a40326d74fdf7814ca312288360fab new file mode 100644 index 0000000000..bcd14d2877 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/40ac31d214a40326d74fdf7814ca312288360fab differ diff --git a/external/boringssl/fuzz/cert_corpus/4225f4d93f8b87431acc7167a7e6ca27fe7d119c b/external/boringssl/fuzz/cert_corpus/4225f4d93f8b87431acc7167a7e6ca27fe7d119c new file mode 100644 index 0000000000..e6153bae55 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/4225f4d93f8b87431acc7167a7e6ca27fe7d119c differ diff --git a/external/boringssl/fuzz/cert_corpus/4257efd87e9368cde94e8e321ebff4f3a623dd5c b/external/boringssl/fuzz/cert_corpus/4257efd87e9368cde94e8e321ebff4f3a623dd5c new file mode 100644 index 0000000000..14d6860eee Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/4257efd87e9368cde94e8e321ebff4f3a623dd5c differ diff --git a/external/boringssl/fuzz/cert_corpus/4298a95b560d773b41276414f4f7e991126fe619 b/external/boringssl/fuzz/cert_corpus/4298a95b560d773b41276414f4f7e991126fe619 new file mode 100644 index 0000000000..8c66eca184 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/4298a95b560d773b41276414f4f7e991126fe619 differ diff --git a/external/boringssl/fuzz/cert_corpus/4306c7e25b8389c7d3f402887a4077655ace41c6 b/external/boringssl/fuzz/cert_corpus/4306c7e25b8389c7d3f402887a4077655ace41c6 new file mode 100644 index 0000000000..b82296b17f Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/4306c7e25b8389c7d3f402887a4077655ace41c6 differ diff --git a/external/boringssl/fuzz/cert_corpus/4439d387e849de35ea6711c3819463345004b2e3 b/external/boringssl/fuzz/cert_corpus/4439d387e849de35ea6711c3819463345004b2e3 new file mode 100644 index 0000000000..fed229953b Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/4439d387e849de35ea6711c3819463345004b2e3 differ diff --git a/external/boringssl/fuzz/cert_corpus/44d2f5537df291966ab6205ee71a809a8a56e866 b/external/boringssl/fuzz/cert_corpus/44d2f5537df291966ab6205ee71a809a8a56e866 new file mode 100644 index 0000000000..999fdc0951 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/44d2f5537df291966ab6205ee71a809a8a56e866 differ diff --git a/external/boringssl/fuzz/cert_corpus/457c25ce787e34b315d3b161a8b478a5e793c3c4 b/external/boringssl/fuzz/cert_corpus/457c25ce787e34b315d3b161a8b478a5e793c3c4 new file mode 100644 index 0000000000..eab257ee1d Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/457c25ce787e34b315d3b161a8b478a5e793c3c4 differ diff --git a/external/boringssl/fuzz/cert_corpus/45bec5a0ca33be77b2363ab59fb821aa44c55cbb b/external/boringssl/fuzz/cert_corpus/45bec5a0ca33be77b2363ab59fb821aa44c55cbb new file mode 100644 index 0000000000..a15499a899 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/45bec5a0ca33be77b2363ab59fb821aa44c55cbb differ diff --git a/external/boringssl/fuzz/cert_corpus/4685dd4dae8033acdb72a6fb3a0ce71f1299a92c b/external/boringssl/fuzz/cert_corpus/4685dd4dae8033acdb72a6fb3a0ce71f1299a92c new file mode 100644 index 0000000000..2d0a3841ea Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/4685dd4dae8033acdb72a6fb3a0ce71f1299a92c differ diff --git a/external/boringssl/fuzz/cert_corpus/46904f9ce32352458c5e294c368797ae0e48991b b/external/boringssl/fuzz/cert_corpus/46904f9ce32352458c5e294c368797ae0e48991b new file mode 100644 index 0000000000..fbaa9603fe Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/46904f9ce32352458c5e294c368797ae0e48991b differ diff --git a/external/boringssl/fuzz/cert_corpus/471e13c4ef32ffa3867034fe360e142cd7699faf b/external/boringssl/fuzz/cert_corpus/471e13c4ef32ffa3867034fe360e142cd7699faf new file mode 100644 index 0000000000..a798b2edea Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/471e13c4ef32ffa3867034fe360e142cd7699faf differ diff --git a/external/boringssl/fuzz/cert_corpus/47c5db7df8938b05eb5344148af2ba4e6a6ebec2 b/external/boringssl/fuzz/cert_corpus/47c5db7df8938b05eb5344148af2ba4e6a6ebec2 new file mode 100644 index 0000000000..dd35e586eb Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/47c5db7df8938b05eb5344148af2ba4e6a6ebec2 differ diff --git a/external/boringssl/fuzz/cert_corpus/47f69c07723fe0f12f8f81d3a622f0ca09d693ad b/external/boringssl/fuzz/cert_corpus/47f69c07723fe0f12f8f81d3a622f0ca09d693ad new file mode 100644 index 0000000000..5c22df7510 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/47f69c07723fe0f12f8f81d3a622f0ca09d693ad differ diff --git a/external/boringssl/fuzz/cert_corpus/4843ed9fc33451381b6f97311b8c6e254937f2bc b/external/boringssl/fuzz/cert_corpus/4843ed9fc33451381b6f97311b8c6e254937f2bc new file mode 100644 index 0000000000..0164a8dca3 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/4843ed9fc33451381b6f97311b8c6e254937f2bc differ diff --git a/external/boringssl/fuzz/cert_corpus/484c387f1936612f6e742f10775fa81593cb0c47 b/external/boringssl/fuzz/cert_corpus/484c387f1936612f6e742f10775fa81593cb0c47 new file mode 100644 index 0000000000..fe509f6633 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/484c387f1936612f6e742f10775fa81593cb0c47 differ diff --git a/external/boringssl/fuzz/cert_corpus/4938a5264e0e29b97f1a10e1a51a0e7de8334a90 b/external/boringssl/fuzz/cert_corpus/4938a5264e0e29b97f1a10e1a51a0e7de8334a90 new file mode 100644 index 0000000000..9f71dd3e50 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/4938a5264e0e29b97f1a10e1a51a0e7de8334a90 differ diff --git a/external/boringssl/fuzz/cert_corpus/4a59656c14d04ce913197e47cde59133db0401c8 b/external/boringssl/fuzz/cert_corpus/4a59656c14d04ce913197e47cde59133db0401c8 new file mode 100644 index 0000000000..7e05e4638b --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/4a59656c14d04ce913197e47cde59133db0401c8 @@ -0,0 +1 @@ +0€0€(í0‚€0‚h €1’h A1hö|:‚%“;0 ¿÷œ¹æ†*+€¿0ÿ \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/4a7220ebd75b74c4b91bbde748ea273342e7d306 b/external/boringssl/fuzz/cert_corpus/4a7220ebd75b74c4b91bbde748ea273342e7d306 new file mode 100644 index 0000000000..8bd54f11e5 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/4a7220ebd75b74c4b91bbde748ea273342e7d306 differ diff --git a/external/boringssl/fuzz/cert_corpus/4b32eb728bdaa1e1ce8f75344c9113f01addd7dd b/external/boringssl/fuzz/cert_corpus/4b32eb728bdaa1e1ce8f75344c9113f01addd7dd new file mode 100644 index 0000000000..8ef0accb9e Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/4b32eb728bdaa1e1ce8f75344c9113f01addd7dd differ diff --git a/external/boringssl/fuzz/cert_corpus/4b5b5c5fafa6bd96ffc447488f2b283ef76287a5 b/external/boringssl/fuzz/cert_corpus/4b5b5c5fafa6bd96ffc447488f2b283ef76287a5 new file mode 100644 index 0000000000..ed6657374a Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/4b5b5c5fafa6bd96ffc447488f2b283ef76287a5 differ diff --git a/external/boringssl/fuzz/cert_corpus/4b67f91302b63e6de6ffa81a57b38e12f1ee88b0 b/external/boringssl/fuzz/cert_corpus/4b67f91302b63e6de6ffa81a57b38e12f1ee88b0 new file mode 100644 index 0000000000..b6595073fb Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/4b67f91302b63e6de6ffa81a57b38e12f1ee88b0 differ diff --git a/external/boringssl/fuzz/cert_corpus/4bb850171e9fc5a8a480876eb1f7331ffd2fc7b5 b/external/boringssl/fuzz/cert_corpus/4bb850171e9fc5a8a480876eb1f7331ffd2fc7b5 new file mode 100644 index 0000000000..242ece8247 --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/4bb850171e9fc5a8a480876eb1f7331ffd2fc7b5 @@ -0,0 +1 @@ +0€0€(í0‚€0‚h €1’h A1hö|0‚%“å0  *†€00¯€0€ \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/4bea495c65f278e4ec1b343819a713f062aaac99 b/external/boringssl/fuzz/cert_corpus/4bea495c65f278e4ec1b343819a713f062aaac99 new file mode 100644 index 0000000000..d84d981ace Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/4bea495c65f278e4ec1b343819a713f062aaac99 differ diff --git a/external/boringssl/fuzz/cert_corpus/4c1470de173adf77388fd8be8206e5f987d468e6 b/external/boringssl/fuzz/cert_corpus/4c1470de173adf77388fd8be8206e5f987d468e6 new file mode 100644 index 0000000000..24ab6ebbb7 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/4c1470de173adf77388fd8be8206e5f987d468e6 differ diff --git a/external/boringssl/fuzz/cert_corpus/4c1bb06706cb5a80f1c7ea2a738b129360823a84 b/external/boringssl/fuzz/cert_corpus/4c1bb06706cb5a80f1c7ea2a738b129360823a84 new file mode 100644 index 0000000000..cd94bb280f Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/4c1bb06706cb5a80f1c7ea2a738b129360823a84 differ diff --git a/external/boringssl/fuzz/cert_corpus/4c3c8a3a7e4d8ed30d8f37924503f1d643aab3c2 b/external/boringssl/fuzz/cert_corpus/4c3c8a3a7e4d8ed30d8f37924503f1d643aab3c2 new file mode 100644 index 0000000000..2111d2d44e Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/4c3c8a3a7e4d8ed30d8f37924503f1d643aab3c2 differ diff --git a/external/boringssl/fuzz/cert_corpus/4cef0705d69922b19e4f50c16446115d03691379 b/external/boringssl/fuzz/cert_corpus/4cef0705d69922b19e4f50c16446115d03691379 new file mode 100644 index 0000000000..febb23428d Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/4cef0705d69922b19e4f50c16446115d03691379 differ diff --git a/external/boringssl/fuzz/cert_corpus/4cf5cbf6eff378231f206e345fe96ce8b8ce5057 b/external/boringssl/fuzz/cert_corpus/4cf5cbf6eff378231f206e345fe96ce8b8ce5057 new file mode 100644 index 0000000000..83f616169e Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/4cf5cbf6eff378231f206e345fe96ce8b8ce5057 differ diff --git a/external/boringssl/fuzz/cert_corpus/4d19ff9e4518157c69e1a03d87d00f2eaa932a90 b/external/boringssl/fuzz/cert_corpus/4d19ff9e4518157c69e1a03d87d00f2eaa932a90 new file mode 100644 index 0000000000..d6d1eed819 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/4d19ff9e4518157c69e1a03d87d00f2eaa932a90 differ diff --git a/external/boringssl/fuzz/cert_corpus/4e433c8a70e56cfa46a1ae7be617a9609540e59c b/external/boringssl/fuzz/cert_corpus/4e433c8a70e56cfa46a1ae7be617a9609540e59c new file mode 100644 index 0000000000..2f28f2fc2c Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/4e433c8a70e56cfa46a1ae7be617a9609540e59c differ diff --git a/external/boringssl/fuzz/cert_corpus/4f131a48839d15feb0fb9fc92e3cafb76975632a b/external/boringssl/fuzz/cert_corpus/4f131a48839d15feb0fb9fc92e3cafb76975632a new file mode 100644 index 0000000000..202ee12c17 --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/4f131a48839d15feb0fb9fc92e3cafb76975632a @@ -0,0 +1 @@ +0€0€”€1’h A0‚ \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/51f89a8688c1b0fcdd806578ca485c7e4037f3c0 b/external/boringssl/fuzz/cert_corpus/51f89a8688c1b0fcdd806578ca485c7e4037f3c0 new file mode 100644 index 0000000000..47c240d4c3 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/51f89a8688c1b0fcdd806578ca485c7e4037f3c0 differ diff --git a/external/boringssl/fuzz/cert_corpus/5222e890a092812b05c20232eca33516d61e6854 b/external/boringssl/fuzz/cert_corpus/5222e890a092812b05c20232eca33516d61e6854 new file mode 100644 index 0000000000..abf6dbe30e Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/5222e890a092812b05c20232eca33516d61e6854 differ diff --git a/external/boringssl/fuzz/cert_corpus/5357bd89f226463ea66378f1872f2f3dcc45c833 b/external/boringssl/fuzz/cert_corpus/5357bd89f226463ea66378f1872f2f3dcc45c833 new file mode 100644 index 0000000000..cb767023a2 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/5357bd89f226463ea66378f1872f2f3dcc45c833 differ diff --git a/external/boringssl/fuzz/cert_corpus/536b9cd5f18e73b30687908443036be7a1b108b0 b/external/boringssl/fuzz/cert_corpus/536b9cd5f18e73b30687908443036be7a1b108b0 new file mode 100644 index 0000000000..6375dbf402 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/536b9cd5f18e73b30687908443036be7a1b108b0 differ diff --git a/external/boringssl/fuzz/cert_corpus/545e53e61cfc711f2faf4556040d09fc8d8aaf2f b/external/boringssl/fuzz/cert_corpus/545e53e61cfc711f2faf4556040d09fc8d8aaf2f new file mode 100644 index 0000000000..02bdd1d070 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/545e53e61cfc711f2faf4556040d09fc8d8aaf2f differ diff --git a/external/boringssl/fuzz/cert_corpus/54e8f165765c879ddb14f19d76b6e040a8269e23 b/external/boringssl/fuzz/cert_corpus/54e8f165765c879ddb14f19d76b6e040a8269e23 new file mode 100644 index 0000000000..6aabed0427 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/54e8f165765c879ddb14f19d76b6e040a8269e23 differ diff --git a/external/boringssl/fuzz/cert_corpus/54faf9d362f22ac220377a9d478731301876830d b/external/boringssl/fuzz/cert_corpus/54faf9d362f22ac220377a9d478731301876830d new file mode 100644 index 0000000000..b15aaee943 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/54faf9d362f22ac220377a9d478731301876830d differ diff --git a/external/boringssl/fuzz/cert_corpus/55a82b305fab4b2ab0bee8d3c70e8f41e8fedc92 b/external/boringssl/fuzz/cert_corpus/55a82b305fab4b2ab0bee8d3c70e8f41e8fedc92 new file mode 100644 index 0000000000..b5badb0c02 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/55a82b305fab4b2ab0bee8d3c70e8f41e8fedc92 differ diff --git a/external/boringssl/fuzz/cert_corpus/55ff515a21332c377e8682bb0f05d4a36595cb18 b/external/boringssl/fuzz/cert_corpus/55ff515a21332c377e8682bb0f05d4a36595cb18 new file mode 100644 index 0000000000..5e416abfd0 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/55ff515a21332c377e8682bb0f05d4a36595cb18 differ diff --git a/external/boringssl/fuzz/cert_corpus/5616542c0240af6572786b4088b07a3d6da77caf b/external/boringssl/fuzz/cert_corpus/5616542c0240af6572786b4088b07a3d6da77caf new file mode 100644 index 0000000000..e6b619f202 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/5616542c0240af6572786b4088b07a3d6da77caf differ diff --git a/external/boringssl/fuzz/cert_corpus/56e4a5c9a93b5a414e2d14ea6eabd787dd0ffe7b b/external/boringssl/fuzz/cert_corpus/56e4a5c9a93b5a414e2d14ea6eabd787dd0ffe7b new file mode 100644 index 0000000000..cfc78b45c8 --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/56e4a5c9a93b5a414e2d14ea6eabd787dd0ffe7b @@ -0,0 +1 @@ +ÿ÷Ñ \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/56ef359b39b367bc94f66501729907dfd8fb8425 b/external/boringssl/fuzz/cert_corpus/56ef359b39b367bc94f66501729907dfd8fb8425 new file mode 100644 index 0000000000..7e67019fbb Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/56ef359b39b367bc94f66501729907dfd8fb8425 differ diff --git a/external/boringssl/fuzz/cert_corpus/5873ef5ad329e0bb4d788f1e8ea965fe2da858b8 b/external/boringssl/fuzz/cert_corpus/5873ef5ad329e0bb4d788f1e8ea965fe2da858b8 new file mode 100644 index 0000000000..55d28feeb9 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/5873ef5ad329e0bb4d788f1e8ea965fe2da858b8 differ diff --git a/external/boringssl/fuzz/cert_corpus/5a7baa69f7c27ed50c560f427370910220cf4073 b/external/boringssl/fuzz/cert_corpus/5a7baa69f7c27ed50c560f427370910220cf4073 new file mode 100644 index 0000000000..38ef03a5ed Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/5a7baa69f7c27ed50c560f427370910220cf4073 differ diff --git a/external/boringssl/fuzz/cert_corpus/5aa3c8afa0c89038c509026d2a48d790521f92a5 b/external/boringssl/fuzz/cert_corpus/5aa3c8afa0c89038c509026d2a48d790521f92a5 new file mode 100644 index 0000000000..dd27b81f92 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/5aa3c8afa0c89038c509026d2a48d790521f92a5 differ diff --git a/external/boringssl/fuzz/cert_corpus/5b20a5b709ca2a262ba0e6a89c4a7f3bd9098422 b/external/boringssl/fuzz/cert_corpus/5b20a5b709ca2a262ba0e6a89c4a7f3bd9098422 new file mode 100644 index 0000000000..c7c90d2073 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/5b20a5b709ca2a262ba0e6a89c4a7f3bd9098422 differ diff --git a/external/boringssl/fuzz/cert_corpus/5c7389e097519d3d2c974b7d082344c6fdb9e74b b/external/boringssl/fuzz/cert_corpus/5c7389e097519d3d2c974b7d082344c6fdb9e74b new file mode 100644 index 0000000000..443034d206 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/5c7389e097519d3d2c974b7d082344c6fdb9e74b differ diff --git a/external/boringssl/fuzz/cert_corpus/5ccb2368d4f51967b4d79b062103604a0e73c6ab b/external/boringssl/fuzz/cert_corpus/5ccb2368d4f51967b4d79b062103604a0e73c6ab new file mode 100644 index 0000000000..39ac6cb471 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/5ccb2368d4f51967b4d79b062103604a0e73c6ab differ diff --git a/external/boringssl/fuzz/cert_corpus/5d00700f69a1db5a65201dc8d56aa917c6e6132b b/external/boringssl/fuzz/cert_corpus/5d00700f69a1db5a65201dc8d56aa917c6e6132b new file mode 100644 index 0000000000..d547333760 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/5d00700f69a1db5a65201dc8d56aa917c6e6132b differ diff --git a/external/boringssl/fuzz/cert_corpus/5d26b3013f6c3210b1e1b0e837bc577bb491e1b8 b/external/boringssl/fuzz/cert_corpus/5d26b3013f6c3210b1e1b0e837bc577bb491e1b8 new file mode 100644 index 0000000000..88bebfb591 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/5d26b3013f6c3210b1e1b0e837bc577bb491e1b8 differ diff --git a/external/boringssl/fuzz/cert_corpus/5d5680962803669e9a931bc79eb421002bb6abdf b/external/boringssl/fuzz/cert_corpus/5d5680962803669e9a931bc79eb421002bb6abdf new file mode 100644 index 0000000000..15f124b4cc Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/5d5680962803669e9a931bc79eb421002bb6abdf differ diff --git a/external/boringssl/fuzz/cert_corpus/5d64f19209be8be3ce3e914b475db34591d7a985 b/external/boringssl/fuzz/cert_corpus/5d64f19209be8be3ce3e914b475db34591d7a985 new file mode 100644 index 0000000000..86efae82de --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/5d64f19209be8be3ce3e914b475db34591d7a985 @@ -0,0 +1 @@ +ÿ( \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/5d6ffff8423a44c92868994adb23e851b6932224 b/external/boringssl/fuzz/cert_corpus/5d6ffff8423a44c92868994adb23e851b6932224 new file mode 100644 index 0000000000..1a757ff877 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/5d6ffff8423a44c92868994adb23e851b6932224 differ diff --git a/external/boringssl/fuzz/cert_corpus/5f6a0d4e63e434e50dbf1159514610e031afbbc9 b/external/boringssl/fuzz/cert_corpus/5f6a0d4e63e434e50dbf1159514610e031afbbc9 new file mode 100644 index 0000000000..918ca124b6 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/5f6a0d4e63e434e50dbf1159514610e031afbbc9 differ diff --git a/external/boringssl/fuzz/cert_corpus/5f7cc578c2516d3b9465841482354b609fee62fb b/external/boringssl/fuzz/cert_corpus/5f7cc578c2516d3b9465841482354b609fee62fb new file mode 100644 index 0000000000..cebe87c2c7 --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/5f7cc578c2516d3b9465841482354b609fee62fb @@ -0,0 +1 @@ +0€0€(í0‚€0‚h €1’h A1hö|0‚%“å0  *†€00¯€0€ \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/5fd4775f8a1b947387c3fbd5f8d5e794e21eaa31 b/external/boringssl/fuzz/cert_corpus/5fd4775f8a1b947387c3fbd5f8d5e794e21eaa31 new file mode 100644 index 0000000000..d69f231a2c Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/5fd4775f8a1b947387c3fbd5f8d5e794e21eaa31 differ diff --git a/external/boringssl/fuzz/cert_corpus/5fe171e9917a45ecee64fd75cdc3726a0dc65a5b b/external/boringssl/fuzz/cert_corpus/5fe171e9917a45ecee64fd75cdc3726a0dc65a5b new file mode 100644 index 0000000000..0322804b36 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/5fe171e9917a45ecee64fd75cdc3726a0dc65a5b differ diff --git a/external/boringssl/fuzz/cert_corpus/6030d8a8d1d58b4e2efa13c04a1da538bac6c2c4 b/external/boringssl/fuzz/cert_corpus/6030d8a8d1d58b4e2efa13c04a1da538bac6c2c4 new file mode 100644 index 0000000000..7d999fee77 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/6030d8a8d1d58b4e2efa13c04a1da538bac6c2c4 differ diff --git a/external/boringssl/fuzz/cert_corpus/60c070cf2975070c6def7c702abd7d7d941ae0e9 b/external/boringssl/fuzz/cert_corpus/60c070cf2975070c6def7c702abd7d7d941ae0e9 new file mode 100644 index 0000000000..227dc49222 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/60c070cf2975070c6def7c702abd7d7d941ae0e9 differ diff --git a/external/boringssl/fuzz/cert_corpus/6118a3fcc0337a2cae92be95b87dcdc47a2c53c9 b/external/boringssl/fuzz/cert_corpus/6118a3fcc0337a2cae92be95b87dcdc47a2c53c9 new file mode 100644 index 0000000000..bef3bcf4ae Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/6118a3fcc0337a2cae92be95b87dcdc47a2c53c9 differ diff --git a/external/boringssl/fuzz/cert_corpus/6461be4247a144f92150a896c56f9561f2169337 b/external/boringssl/fuzz/cert_corpus/6461be4247a144f92150a896c56f9561f2169337 new file mode 100644 index 0000000000..0464b03884 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/6461be4247a144f92150a896c56f9561f2169337 differ diff --git a/external/boringssl/fuzz/cert_corpus/64a9ce67fccd9c0a3b2ff3d02ea9afbe5619b41f b/external/boringssl/fuzz/cert_corpus/64a9ce67fccd9c0a3b2ff3d02ea9afbe5619b41f new file mode 100644 index 0000000000..661a4d001f --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/64a9ce67fccd9c0a3b2ff3d02ea9afbe5619b41f @@ -0,0 +1 @@ +0€0€(í0‚€0‚h €1’h A1hö|0‚%“å0 ¿÷œ¹æ†**€¿0ÿœ \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/64f00e208a2077bce3a031aa41a2dd696d012715 b/external/boringssl/fuzz/cert_corpus/64f00e208a2077bce3a031aa41a2dd696d012715 new file mode 100644 index 0000000000..f6d312a932 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/64f00e208a2077bce3a031aa41a2dd696d012715 differ diff --git a/external/boringssl/fuzz/cert_corpus/65459fb5f394db61715e19187239b7aa90b1719b b/external/boringssl/fuzz/cert_corpus/65459fb5f394db61715e19187239b7aa90b1719b new file mode 100644 index 0000000000..fa42c20af8 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/65459fb5f394db61715e19187239b7aa90b1719b differ diff --git a/external/boringssl/fuzz/cert_corpus/65769e24f85a4467ff67707ede0c56b5e7046687 b/external/boringssl/fuzz/cert_corpus/65769e24f85a4467ff67707ede0c56b5e7046687 new file mode 100644 index 0000000000..1c81200136 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/65769e24f85a4467ff67707ede0c56b5e7046687 differ diff --git a/external/boringssl/fuzz/cert_corpus/65b1bfb6b449b875079f932a6075771dba978141 b/external/boringssl/fuzz/cert_corpus/65b1bfb6b449b875079f932a6075771dba978141 new file mode 100644 index 0000000000..2d9f218a64 --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/65b1bfb6b449b875079f932a6075771dba978141 @@ -0,0 +1 @@ +0€0€(í0‚€0‚h €1’h A1hö|0‚%“å0  ¿÷œ¹æ†*†H†÷  \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/667d0776ef5074ba6525d5a56fbf3ff140108a33 b/external/boringssl/fuzz/cert_corpus/667d0776ef5074ba6525d5a56fbf3ff140108a33 new file mode 100644 index 0000000000..f7e437abf8 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/667d0776ef5074ba6525d5a56fbf3ff140108a33 differ diff --git a/external/boringssl/fuzz/cert_corpus/66cb9a69e7289f878d3f9bdb235bb4ad97e138b0 b/external/boringssl/fuzz/cert_corpus/66cb9a69e7289f878d3f9bdb235bb4ad97e138b0 new file mode 100644 index 0000000000..372d0cc2a0 --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/66cb9a69e7289f878d3f9bdb235bb4ad97e138b0 @@ -0,0 +1 @@ +0€0€(í0‚€0‚h €1’h A1hö|0‚%“å0  €*š†H†÷ 0€0 \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/67c6b2d857ae3edc271adac024751559bed7ae97 b/external/boringssl/fuzz/cert_corpus/67c6b2d857ae3edc271adac024751559bed7ae97 new file mode 100644 index 0000000000..5cec5d5e02 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/67c6b2d857ae3edc271adac024751559bed7ae97 differ diff --git a/external/boringssl/fuzz/cert_corpus/67f672ab618d2facc0092cd32837cc04e5d37216 b/external/boringssl/fuzz/cert_corpus/67f672ab618d2facc0092cd32837cc04e5d37216 new file mode 100644 index 0000000000..47443f7836 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/67f672ab618d2facc0092cd32837cc04e5d37216 differ diff --git a/external/boringssl/fuzz/cert_corpus/6869834d4b7c77e0bd7ce160876197a3c9be7040 b/external/boringssl/fuzz/cert_corpus/6869834d4b7c77e0bd7ce160876197a3c9be7040 new file mode 100644 index 0000000000..80d069dbf5 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/6869834d4b7c77e0bd7ce160876197a3c9be7040 differ diff --git a/external/boringssl/fuzz/cert_corpus/693913decd386589e4d4212fc498714506d667f0 b/external/boringssl/fuzz/cert_corpus/693913decd386589e4d4212fc498714506d667f0 new file mode 100644 index 0000000000..d6af9f7ea7 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/693913decd386589e4d4212fc498714506d667f0 differ diff --git a/external/boringssl/fuzz/cert_corpus/6b6697d8bf086fa6e9fc7d5dfb27a5fee7a3a148 b/external/boringssl/fuzz/cert_corpus/6b6697d8bf086fa6e9fc7d5dfb27a5fee7a3a148 new file mode 100644 index 0000000000..fc15793cfc Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/6b6697d8bf086fa6e9fc7d5dfb27a5fee7a3a148 differ diff --git a/external/boringssl/fuzz/cert_corpus/6e58bd8357c877fe7e3ca75af4b9959831ee44b1 b/external/boringssl/fuzz/cert_corpus/6e58bd8357c877fe7e3ca75af4b9959831ee44b1 new file mode 100644 index 0000000000..11f1f3fb6e Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/6e58bd8357c877fe7e3ca75af4b9959831ee44b1 differ diff --git a/external/boringssl/fuzz/cert_corpus/6f0d97a3ed2a4c3c330edb10959f005a553d08f4 b/external/boringssl/fuzz/cert_corpus/6f0d97a3ed2a4c3c330edb10959f005a553d08f4 new file mode 100644 index 0000000000..2ef1a051f2 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/6f0d97a3ed2a4c3c330edb10959f005a553d08f4 differ diff --git a/external/boringssl/fuzz/cert_corpus/6fe20105baf3a79f9c69ff4dde501c4542118d06 b/external/boringssl/fuzz/cert_corpus/6fe20105baf3a79f9c69ff4dde501c4542118d06 new file mode 100644 index 0000000000..781008a688 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/6fe20105baf3a79f9c69ff4dde501c4542118d06 differ diff --git a/external/boringssl/fuzz/cert_corpus/70be2630942a6f72e66f3f7189ad014acc45bb7d b/external/boringssl/fuzz/cert_corpus/70be2630942a6f72e66f3f7189ad014acc45bb7d new file mode 100644 index 0000000000..1eb8883311 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/70be2630942a6f72e66f3f7189ad014acc45bb7d differ diff --git a/external/boringssl/fuzz/cert_corpus/70f2004db5c4ddfa9bd91d0db596867b4403d9cd b/external/boringssl/fuzz/cert_corpus/70f2004db5c4ddfa9bd91d0db596867b4403d9cd new file mode 100644 index 0000000000..5d1a0fee6d Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/70f2004db5c4ddfa9bd91d0db596867b4403d9cd differ diff --git a/external/boringssl/fuzz/cert_corpus/71123779ed3db9713684829f9a2ed309c9d96f06 b/external/boringssl/fuzz/cert_corpus/71123779ed3db9713684829f9a2ed309c9d96f06 new file mode 100644 index 0000000000..31cd941075 --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/71123779ed3db9713684829f9a2ed309c9d96f06 @@ -0,0 +1 @@ +0€0€(í0‚€0‚h €1’h A!1hö|0‚%“¥0  *†€€0¯€€' \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/719702d86cd0fc94ad0b193398112815f3308744 b/external/boringssl/fuzz/cert_corpus/719702d86cd0fc94ad0b193398112815f3308744 new file mode 100644 index 0000000000..67bd84067e Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/719702d86cd0fc94ad0b193398112815f3308744 differ diff --git a/external/boringssl/fuzz/cert_corpus/71b0adb1b0c1fccff4150b015220e74e549d24d3 b/external/boringssl/fuzz/cert_corpus/71b0adb1b0c1fccff4150b015220e74e549d24d3 new file mode 100644 index 0000000000..f5f7646e3b Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/71b0adb1b0c1fccff4150b015220e74e549d24d3 differ diff --git a/external/boringssl/fuzz/cert_corpus/72273c2fa36dbb9b39a69e65f59b616c706f3330 b/external/boringssl/fuzz/cert_corpus/72273c2fa36dbb9b39a69e65f59b616c706f3330 new file mode 100644 index 0000000000..628d517da0 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/72273c2fa36dbb9b39a69e65f59b616c706f3330 differ diff --git a/external/boringssl/fuzz/cert_corpus/72b8b2c9ae429de1590b68fd125892a3832abc5d b/external/boringssl/fuzz/cert_corpus/72b8b2c9ae429de1590b68fd125892a3832abc5d new file mode 100644 index 0000000000..98502362a1 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/72b8b2c9ae429de1590b68fd125892a3832abc5d differ diff --git a/external/boringssl/fuzz/cert_corpus/72c6ba776c93cce6f82c1acaf9ccd95adfd22a18 b/external/boringssl/fuzz/cert_corpus/72c6ba776c93cce6f82c1acaf9ccd95adfd22a18 new file mode 100644 index 0000000000..5a91ba118b Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/72c6ba776c93cce6f82c1acaf9ccd95adfd22a18 differ diff --git a/external/boringssl/fuzz/cert_corpus/72d95d75d6a1c5e6f8c0e488f71d30bdd01b52d5 b/external/boringssl/fuzz/cert_corpus/72d95d75d6a1c5e6f8c0e488f71d30bdd01b52d5 new file mode 100644 index 0000000000..b88f394222 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/72d95d75d6a1c5e6f8c0e488f71d30bdd01b52d5 differ diff --git a/external/boringssl/fuzz/cert_corpus/7345d2f36ce35f7aaeb3f3c62a2b37f55dfd7af7 b/external/boringssl/fuzz/cert_corpus/7345d2f36ce35f7aaeb3f3c62a2b37f55dfd7af7 new file mode 100644 index 0000000000..1103cb5645 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/7345d2f36ce35f7aaeb3f3c62a2b37f55dfd7af7 differ diff --git a/external/boringssl/fuzz/cert_corpus/73c845434d7055e1cff670fe85edb1b7581ee224 b/external/boringssl/fuzz/cert_corpus/73c845434d7055e1cff670fe85edb1b7581ee224 new file mode 100644 index 0000000000..65c09fa575 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/73c845434d7055e1cff670fe85edb1b7581ee224 differ diff --git a/external/boringssl/fuzz/cert_corpus/73fa79cca934a2c5c13f7d41b0162e611d6e4f5c b/external/boringssl/fuzz/cert_corpus/73fa79cca934a2c5c13f7d41b0162e611d6e4f5c new file mode 100644 index 0000000000..8c6be702bb Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/73fa79cca934a2c5c13f7d41b0162e611d6e4f5c differ diff --git a/external/boringssl/fuzz/cert_corpus/74287c085825b190ed3cf50ad0f5beec7cc07edd b/external/boringssl/fuzz/cert_corpus/74287c085825b190ed3cf50ad0f5beec7cc07edd new file mode 100644 index 0000000000..b623eec4a0 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/74287c085825b190ed3cf50ad0f5beec7cc07edd differ diff --git a/external/boringssl/fuzz/cert_corpus/74a907e9d20fab94e34c3e46d73f7aa2d4f1dccd b/external/boringssl/fuzz/cert_corpus/74a907e9d20fab94e34c3e46d73f7aa2d4f1dccd new file mode 100644 index 0000000000..f69814f2e5 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/74a907e9d20fab94e34c3e46d73f7aa2d4f1dccd differ diff --git a/external/boringssl/fuzz/cert_corpus/7685b3e299f2cce95aab0d8559fd45d8198f5da2 b/external/boringssl/fuzz/cert_corpus/7685b3e299f2cce95aab0d8559fd45d8198f5da2 new file mode 100644 index 0000000000..7ca6b09447 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/7685b3e299f2cce95aab0d8559fd45d8198f5da2 differ diff --git a/external/boringssl/fuzz/cert_corpus/771688184c18822e2182b18bb1ec853a88262659 b/external/boringssl/fuzz/cert_corpus/771688184c18822e2182b18bb1ec853a88262659 new file mode 100644 index 0000000000..ac6e9ec758 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/771688184c18822e2182b18bb1ec853a88262659 differ diff --git a/external/boringssl/fuzz/cert_corpus/772739edb5a338fade2b33ed8c4c7e5c3856e7bd b/external/boringssl/fuzz/cert_corpus/772739edb5a338fade2b33ed8c4c7e5c3856e7bd new file mode 100644 index 0000000000..1ce94e494e Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/772739edb5a338fade2b33ed8c4c7e5c3856e7bd differ diff --git a/external/boringssl/fuzz/cert_corpus/77818abcde8b135fcc987e61388553e697d32d75 b/external/boringssl/fuzz/cert_corpus/77818abcde8b135fcc987e61388553e697d32d75 new file mode 100644 index 0000000000..32e7bc8401 --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/77818abcde8b135fcc987e61388553e697d32d75 @@ -0,0 +1 @@ +1ˆ0 \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/785389bce6d1f4c8f2cec6062ecacb1d49a784f9 b/external/boringssl/fuzz/cert_corpus/785389bce6d1f4c8f2cec6062ecacb1d49a784f9 new file mode 100644 index 0000000000..ec01b39f37 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/785389bce6d1f4c8f2cec6062ecacb1d49a784f9 differ diff --git a/external/boringssl/fuzz/cert_corpus/78fa5096155d1b72a074a486cf7ace40a4c92f1f b/external/boringssl/fuzz/cert_corpus/78fa5096155d1b72a074a486cf7ace40a4c92f1f new file mode 100644 index 0000000000..5a9acdae2b Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/78fa5096155d1b72a074a486cf7ace40a4c92f1f differ diff --git a/external/boringssl/fuzz/cert_corpus/795b50e9f9bc6f1a3be9b158a9fa287a5bba6876 b/external/boringssl/fuzz/cert_corpus/795b50e9f9bc6f1a3be9b158a9fa287a5bba6876 new file mode 100644 index 0000000000..31cf984926 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/795b50e9f9bc6f1a3be9b158a9fa287a5bba6876 differ diff --git a/external/boringssl/fuzz/cert_corpus/79fe694f60433debeb203f01dbacefcde6e9483f b/external/boringssl/fuzz/cert_corpus/79fe694f60433debeb203f01dbacefcde6e9483f new file mode 100644 index 0000000000..35b47e8ba5 --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/79fe694f60433debeb203f01dbacefcde6e9483f @@ -0,0 +1 @@ +0€0€(í0‚€0‚h €1’h A1hö|0‚%“å0 ¿÷œ¹æ†*0€0 \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/7a37f6614fd5c0dda82eceb3d171090c7581f0c1 b/external/boringssl/fuzz/cert_corpus/7a37f6614fd5c0dda82eceb3d171090c7581f0c1 new file mode 100644 index 0000000000..51b0e63fd2 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/7a37f6614fd5c0dda82eceb3d171090c7581f0c1 differ diff --git a/external/boringssl/fuzz/cert_corpus/7adda79c5f85db9577eac0cf60e0cad63c74e144 b/external/boringssl/fuzz/cert_corpus/7adda79c5f85db9577eac0cf60e0cad63c74e144 new file mode 100644 index 0000000000..598723ce56 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/7adda79c5f85db9577eac0cf60e0cad63c74e144 differ diff --git a/external/boringssl/fuzz/cert_corpus/7d8eed80cfd58de130245bea2880f3b042225847 b/external/boringssl/fuzz/cert_corpus/7d8eed80cfd58de130245bea2880f3b042225847 new file mode 100644 index 0000000000..90c6010154 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/7d8eed80cfd58de130245bea2880f3b042225847 differ diff --git a/external/boringssl/fuzz/cert_corpus/7e87ff06a8c83b1195fb15a9d599abfe28b94cbf b/external/boringssl/fuzz/cert_corpus/7e87ff06a8c83b1195fb15a9d599abfe28b94cbf new file mode 100644 index 0000000000..ca8d2ab8c6 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/7e87ff06a8c83b1195fb15a9d599abfe28b94cbf differ diff --git a/external/boringssl/fuzz/cert_corpus/7eb1f7349c812a0ed94fe21f9900600516164b17 b/external/boringssl/fuzz/cert_corpus/7eb1f7349c812a0ed94fe21f9900600516164b17 new file mode 100644 index 0000000000..e6776977b7 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/7eb1f7349c812a0ed94fe21f9900600516164b17 differ diff --git a/external/boringssl/fuzz/cert_corpus/7ecb46c93915184be12fa3cbaac3b65072116242 b/external/boringssl/fuzz/cert_corpus/7ecb46c93915184be12fa3cbaac3b65072116242 new file mode 100644 index 0000000000..2acc67937b Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/7ecb46c93915184be12fa3cbaac3b65072116242 differ diff --git a/external/boringssl/fuzz/cert_corpus/806fd814b69bc6511d7f6e1a3bc762d14a56364a b/external/boringssl/fuzz/cert_corpus/806fd814b69bc6511d7f6e1a3bc762d14a56364a new file mode 100644 index 0000000000..6cb60a8ddf Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/806fd814b69bc6511d7f6e1a3bc762d14a56364a differ diff --git a/external/boringssl/fuzz/cert_corpus/808871bc380bc3221c7ce683031bb6d85293ee5f b/external/boringssl/fuzz/cert_corpus/808871bc380bc3221c7ce683031bb6d85293ee5f new file mode 100644 index 0000000000..7f953764b1 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/808871bc380bc3221c7ce683031bb6d85293ee5f differ diff --git a/external/boringssl/fuzz/cert_corpus/808882216e9afcc5257f494435c2d9757dc785eb b/external/boringssl/fuzz/cert_corpus/808882216e9afcc5257f494435c2d9757dc785eb new file mode 100644 index 0000000000..a9b39dff50 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/808882216e9afcc5257f494435c2d9757dc785eb differ diff --git a/external/boringssl/fuzz/cert_corpus/808bf82ca615b1d70ef5b1c2d2afc19d25e3dbb6 b/external/boringssl/fuzz/cert_corpus/808bf82ca615b1d70ef5b1c2d2afc19d25e3dbb6 new file mode 100644 index 0000000000..621450063b Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/808bf82ca615b1d70ef5b1c2d2afc19d25e3dbb6 differ diff --git a/external/boringssl/fuzz/cert_corpus/8210a65e177303f8b801f73c663806236584988b b/external/boringssl/fuzz/cert_corpus/8210a65e177303f8b801f73c663806236584988b new file mode 100644 index 0000000000..9153901473 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/8210a65e177303f8b801f73c663806236584988b differ diff --git a/external/boringssl/fuzz/cert_corpus/8217aa968f0050b2fb1aac92ae6f377c41c3952b b/external/boringssl/fuzz/cert_corpus/8217aa968f0050b2fb1aac92ae6f377c41c3952b new file mode 100644 index 0000000000..fbc2294555 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/8217aa968f0050b2fb1aac92ae6f377c41c3952b differ diff --git a/external/boringssl/fuzz/cert_corpus/8369ebff6d1524579c2bcd10b5ab2df186cba6c1 b/external/boringssl/fuzz/cert_corpus/8369ebff6d1524579c2bcd10b5ab2df186cba6c1 new file mode 100644 index 0000000000..4463be1214 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/8369ebff6d1524579c2bcd10b5ab2df186cba6c1 differ diff --git a/external/boringssl/fuzz/cert_corpus/83a5535a9a577453d218f897017e59a996439c48 b/external/boringssl/fuzz/cert_corpus/83a5535a9a577453d218f897017e59a996439c48 new file mode 100644 index 0000000000..888308add0 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/83a5535a9a577453d218f897017e59a996439c48 differ diff --git a/external/boringssl/fuzz/cert_corpus/848426625248d49961481ba4616c501a808983ac b/external/boringssl/fuzz/cert_corpus/848426625248d49961481ba4616c501a808983ac new file mode 100644 index 0000000000..99dc6cc105 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/848426625248d49961481ba4616c501a808983ac differ diff --git a/external/boringssl/fuzz/cert_corpus/84882a41d7892f52a3145178b9ff8ad6947ddbf4 b/external/boringssl/fuzz/cert_corpus/84882a41d7892f52a3145178b9ff8ad6947ddbf4 new file mode 100644 index 0000000000..56e7733265 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/84882a41d7892f52a3145178b9ff8ad6947ddbf4 differ diff --git a/external/boringssl/fuzz/cert_corpus/848f69b34380f7554ab3074737d72ca8b0264def b/external/boringssl/fuzz/cert_corpus/848f69b34380f7554ab3074737d72ca8b0264def new file mode 100644 index 0000000000..530b4805a4 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/848f69b34380f7554ab3074737d72ca8b0264def differ diff --git a/external/boringssl/fuzz/cert_corpus/85e7763d7b35b96c1fd9f3462f02f4ddd9fb9e85 b/external/boringssl/fuzz/cert_corpus/85e7763d7b35b96c1fd9f3462f02f4ddd9fb9e85 new file mode 100644 index 0000000000..afae567cc5 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/85e7763d7b35b96c1fd9f3462f02f4ddd9fb9e85 differ diff --git a/external/boringssl/fuzz/cert_corpus/86c40f29670fbf2e1eed17d3a99aa2a6b90cecf6 b/external/boringssl/fuzz/cert_corpus/86c40f29670fbf2e1eed17d3a99aa2a6b90cecf6 new file mode 100644 index 0000000000..54e2620348 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/86c40f29670fbf2e1eed17d3a99aa2a6b90cecf6 differ diff --git a/external/boringssl/fuzz/cert_corpus/8786dd7aa2d0ea06461fc1d4751c9c00e234e57f b/external/boringssl/fuzz/cert_corpus/8786dd7aa2d0ea06461fc1d4751c9c00e234e57f new file mode 100644 index 0000000000..b7539dbb83 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/8786dd7aa2d0ea06461fc1d4751c9c00e234e57f differ diff --git a/external/boringssl/fuzz/cert_corpus/8816b6afa44700585efccf15d9b4b0ebdaa57668 b/external/boringssl/fuzz/cert_corpus/8816b6afa44700585efccf15d9b4b0ebdaa57668 new file mode 100644 index 0000000000..351ca6edd8 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/8816b6afa44700585efccf15d9b4b0ebdaa57668 differ diff --git a/external/boringssl/fuzz/cert_corpus/883b4622778cad8346c050139607cac3ff967b35 b/external/boringssl/fuzz/cert_corpus/883b4622778cad8346c050139607cac3ff967b35 new file mode 100644 index 0000000000..51c9b6da74 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/883b4622778cad8346c050139607cac3ff967b35 differ diff --git a/external/boringssl/fuzz/cert_corpus/8853ff143e14ef222a6c7044ea50992b53ed7387 b/external/boringssl/fuzz/cert_corpus/8853ff143e14ef222a6c7044ea50992b53ed7387 new file mode 100644 index 0000000000..4a32e415c6 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/8853ff143e14ef222a6c7044ea50992b53ed7387 differ diff --git a/external/boringssl/fuzz/cert_corpus/888fe58059dfa918cfa17edfeb3746c709050ead b/external/boringssl/fuzz/cert_corpus/888fe58059dfa918cfa17edfeb3746c709050ead new file mode 100644 index 0000000000..940f722f58 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/888fe58059dfa918cfa17edfeb3746c709050ead differ diff --git a/external/boringssl/fuzz/cert_corpus/88bc068b97b79216220812a038ebb2810b26886d b/external/boringssl/fuzz/cert_corpus/88bc068b97b79216220812a038ebb2810b26886d new file mode 100644 index 0000000000..677607b72b Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/88bc068b97b79216220812a038ebb2810b26886d differ diff --git a/external/boringssl/fuzz/cert_corpus/88e90e49acd2ab796a48eda68f66529dd4206671 b/external/boringssl/fuzz/cert_corpus/88e90e49acd2ab796a48eda68f66529dd4206671 new file mode 100644 index 0000000000..7a3dfe474a Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/88e90e49acd2ab796a48eda68f66529dd4206671 differ diff --git a/external/boringssl/fuzz/cert_corpus/88fd1e4a65f306244552395b6ca6534a20982b8f b/external/boringssl/fuzz/cert_corpus/88fd1e4a65f306244552395b6ca6534a20982b8f new file mode 100644 index 0000000000..056b81d080 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/88fd1e4a65f306244552395b6ca6534a20982b8f differ diff --git a/external/boringssl/fuzz/cert_corpus/8a27963ce5bb499fea5f1fc3a2876e4f5a21fade b/external/boringssl/fuzz/cert_corpus/8a27963ce5bb499fea5f1fc3a2876e4f5a21fade new file mode 100644 index 0000000000..e8810237d0 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/8a27963ce5bb499fea5f1fc3a2876e4f5a21fade differ diff --git a/external/boringssl/fuzz/cert_corpus/8a677dfa5510949833db9b79ae63bd4a5d882665 b/external/boringssl/fuzz/cert_corpus/8a677dfa5510949833db9b79ae63bd4a5d882665 new file mode 100644 index 0000000000..85039f892b Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/8a677dfa5510949833db9b79ae63bd4a5d882665 differ diff --git a/external/boringssl/fuzz/cert_corpus/8abde7f7cab98c1b02729fcd665090c8b0934431 b/external/boringssl/fuzz/cert_corpus/8abde7f7cab98c1b02729fcd665090c8b0934431 new file mode 100644 index 0000000000..4ce4a75c88 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/8abde7f7cab98c1b02729fcd665090c8b0934431 differ diff --git a/external/boringssl/fuzz/cert_corpus/8b188b379875299b1f6ca0501cf758b3a313a7d8 b/external/boringssl/fuzz/cert_corpus/8b188b379875299b1f6ca0501cf758b3a313a7d8 new file mode 100644 index 0000000000..fd6a3f4f58 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/8b188b379875299b1f6ca0501cf758b3a313a7d8 differ diff --git a/external/boringssl/fuzz/cert_corpus/8ce5aebbe8c9d1562a2ae1b996669f1843692c4d b/external/boringssl/fuzz/cert_corpus/8ce5aebbe8c9d1562a2ae1b996669f1843692c4d new file mode 100644 index 0000000000..e5759761d8 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/8ce5aebbe8c9d1562a2ae1b996669f1843692c4d differ diff --git a/external/boringssl/fuzz/cert_corpus/8d181c10f73a5574cbf445593200e71a16584ec3 b/external/boringssl/fuzz/cert_corpus/8d181c10f73a5574cbf445593200e71a16584ec3 new file mode 100644 index 0000000000..3e6a37d1fc Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/8d181c10f73a5574cbf445593200e71a16584ec3 differ diff --git a/external/boringssl/fuzz/cert_corpus/8dbbc76831fa9eaff21b8a04f5ce41c1a0468538 b/external/boringssl/fuzz/cert_corpus/8dbbc76831fa9eaff21b8a04f5ce41c1a0468538 new file mode 100644 index 0000000000..a0c7acc998 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/8dbbc76831fa9eaff21b8a04f5ce41c1a0468538 differ diff --git a/external/boringssl/fuzz/cert_corpus/8f5cdec4e18527ddbc930a7bfe710ac015527f00 b/external/boringssl/fuzz/cert_corpus/8f5cdec4e18527ddbc930a7bfe710ac015527f00 new file mode 100644 index 0000000000..4e1df5dae7 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/8f5cdec4e18527ddbc930a7bfe710ac015527f00 differ diff --git a/external/boringssl/fuzz/cert_corpus/9070df87024c0167e6a1bd9512f698d3a31ca0b1 b/external/boringssl/fuzz/cert_corpus/9070df87024c0167e6a1bd9512f698d3a31ca0b1 new file mode 100644 index 0000000000..7d7b792778 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/9070df87024c0167e6a1bd9512f698d3a31ca0b1 differ diff --git a/external/boringssl/fuzz/cert_corpus/90fbdf2d500b38c15e3364d041484cf065cba9df b/external/boringssl/fuzz/cert_corpus/90fbdf2d500b38c15e3364d041484cf065cba9df new file mode 100644 index 0000000000..90a4e76681 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/90fbdf2d500b38c15e3364d041484cf065cba9df differ diff --git a/external/boringssl/fuzz/cert_corpus/92e6a50ac9f8a75d43d93b85873adf8f0ffb9d0a b/external/boringssl/fuzz/cert_corpus/92e6a50ac9f8a75d43d93b85873adf8f0ffb9d0a new file mode 100644 index 0000000000..75117a5243 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/92e6a50ac9f8a75d43d93b85873adf8f0ffb9d0a differ diff --git a/external/boringssl/fuzz/cert_corpus/94b7796d627b110ff66c1bd9dc1a7c2f87a723ad b/external/boringssl/fuzz/cert_corpus/94b7796d627b110ff66c1bd9dc1a7c2f87a723ad new file mode 100644 index 0000000000..6070558381 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/94b7796d627b110ff66c1bd9dc1a7c2f87a723ad differ diff --git a/external/boringssl/fuzz/cert_corpus/94d777c0eae1377aa35069f15e75954792406394 b/external/boringssl/fuzz/cert_corpus/94d777c0eae1377aa35069f15e75954792406394 new file mode 100644 index 0000000000..1ed9eac08c Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/94d777c0eae1377aa35069f15e75954792406394 differ diff --git a/external/boringssl/fuzz/cert_corpus/953b46659c6224c0068a9ddb3fa7b0a74f89af3e b/external/boringssl/fuzz/cert_corpus/953b46659c6224c0068a9ddb3fa7b0a74f89af3e new file mode 100644 index 0000000000..d5443083f1 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/953b46659c6224c0068a9ddb3fa7b0a74f89af3e differ diff --git a/external/boringssl/fuzz/cert_corpus/96516b3b33c6faa0224d198d549b6a167416a4f6 b/external/boringssl/fuzz/cert_corpus/96516b3b33c6faa0224d198d549b6a167416a4f6 new file mode 100644 index 0000000000..11296bfcb8 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/96516b3b33c6faa0224d198d549b6a167416a4f6 differ diff --git a/external/boringssl/fuzz/cert_corpus/96aa3fabebccf825b9cc06ec34e605a450b49eae b/external/boringssl/fuzz/cert_corpus/96aa3fabebccf825b9cc06ec34e605a450b49eae new file mode 100644 index 0000000000..5d40be852b Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/96aa3fabebccf825b9cc06ec34e605a450b49eae differ diff --git a/external/boringssl/fuzz/cert_corpus/96ce1cb3ca0061f2865d1348f3e147000a3b1a93 b/external/boringssl/fuzz/cert_corpus/96ce1cb3ca0061f2865d1348f3e147000a3b1a93 new file mode 100644 index 0000000000..034fc2bbd5 --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/96ce1cb3ca0061f2865d1348f3e147000a3b1a93 @@ -0,0 +1 @@ +¿ÿœ)†(; \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/9716858fbfa71a1c8bc855f2a09dece8df15e5bd b/external/boringssl/fuzz/cert_corpus/9716858fbfa71a1c8bc855f2a09dece8df15e5bd new file mode 100644 index 0000000000..7cd7165dea Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/9716858fbfa71a1c8bc855f2a09dece8df15e5bd differ diff --git a/external/boringssl/fuzz/cert_corpus/97335aacabe616a3b92c25187ef3ccc58dc09fad b/external/boringssl/fuzz/cert_corpus/97335aacabe616a3b92c25187ef3ccc58dc09fad new file mode 100644 index 0000000000..d8d6fc10c9 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/97335aacabe616a3b92c25187ef3ccc58dc09fad differ diff --git a/external/boringssl/fuzz/cert_corpus/9827e8a5ab0f09782c75a948175d723ea6fc54db b/external/boringssl/fuzz/cert_corpus/9827e8a5ab0f09782c75a948175d723ea6fc54db new file mode 100644 index 0000000000..1552adb572 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/9827e8a5ab0f09782c75a948175d723ea6fc54db differ diff --git a/external/boringssl/fuzz/cert_corpus/990a8dcc9aadd0b161023f0d16e6556e30ddc631 b/external/boringssl/fuzz/cert_corpus/990a8dcc9aadd0b161023f0d16e6556e30ddc631 new file mode 100644 index 0000000000..b112929b93 --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/990a8dcc9aadd0b161023f0d16e6556e30ddc631 @@ -0,0 +1 @@ +0†:;€0 \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/9948b60fcf547feec8bdd433a1dde37e2cd34de9 b/external/boringssl/fuzz/cert_corpus/9948b60fcf547feec8bdd433a1dde37e2cd34de9 new file mode 100644 index 0000000000..fd85e93a7b Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/9948b60fcf547feec8bdd433a1dde37e2cd34de9 differ diff --git a/external/boringssl/fuzz/cert_corpus/999f2f88a8b6510ca0253005f3a6cc06840a8079 b/external/boringssl/fuzz/cert_corpus/999f2f88a8b6510ca0253005f3a6cc06840a8079 new file mode 100644 index 0000000000..901fe6ffa0 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/999f2f88a8b6510ca0253005f3a6cc06840a8079 differ diff --git a/external/boringssl/fuzz/cert_corpus/9afae58a2080ea211e3e5b25f4c35c0aa3c341a3 b/external/boringssl/fuzz/cert_corpus/9afae58a2080ea211e3e5b25f4c35c0aa3c341a3 new file mode 100644 index 0000000000..5c254e7ee6 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/9afae58a2080ea211e3e5b25f4c35c0aa3c341a3 differ diff --git a/external/boringssl/fuzz/cert_corpus/9baa5f344ecd37e2762cb8a7497709b78d69cae6 b/external/boringssl/fuzz/cert_corpus/9baa5f344ecd37e2762cb8a7497709b78d69cae6 new file mode 100644 index 0000000000..b1f09056ca Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/9baa5f344ecd37e2762cb8a7497709b78d69cae6 differ diff --git a/external/boringssl/fuzz/cert_corpus/9c719bffb73cc4fa6a3bba4acd487049eb781a7d b/external/boringssl/fuzz/cert_corpus/9c719bffb73cc4fa6a3bba4acd487049eb781a7d new file mode 100644 index 0000000000..8267cd157d Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/9c719bffb73cc4fa6a3bba4acd487049eb781a7d differ diff --git a/external/boringssl/fuzz/cert_corpus/9d20961e30091256f8211c2837a35db60411dffd b/external/boringssl/fuzz/cert_corpus/9d20961e30091256f8211c2837a35db60411dffd new file mode 100644 index 0000000000..41b10c203c Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/9d20961e30091256f8211c2837a35db60411dffd differ diff --git a/external/boringssl/fuzz/cert_corpus/9dc938dc1db7f1b8f8f21a3550f1f3de5729d155 b/external/boringssl/fuzz/cert_corpus/9dc938dc1db7f1b8f8f21a3550f1f3de5729d155 new file mode 100644 index 0000000000..5fbfacb11f --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/9dc938dc1db7f1b8f8f21a3550f1f3de5729d155 @@ -0,0 +1 @@ +¿†¹ÿœ(; \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/a0666bf912f161ed73664e328cdd57d59118e3a3 b/external/boringssl/fuzz/cert_corpus/a0666bf912f161ed73664e328cdd57d59118e3a3 new file mode 100644 index 0000000000..a2ab64c5a0 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/a0666bf912f161ed73664e328cdd57d59118e3a3 differ diff --git a/external/boringssl/fuzz/cert_corpus/a15fa9644e1be0193331158823bf88ff51593bff b/external/boringssl/fuzz/cert_corpus/a15fa9644e1be0193331158823bf88ff51593bff new file mode 100644 index 0000000000..4a375c3385 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/a15fa9644e1be0193331158823bf88ff51593bff differ diff --git a/external/boringssl/fuzz/cert_corpus/a19ed2ca60eddf4a56e318b33c4767194efdd420 b/external/boringssl/fuzz/cert_corpus/a19ed2ca60eddf4a56e318b33c4767194efdd420 new file mode 100644 index 0000000000..09c2b624a2 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/a19ed2ca60eddf4a56e318b33c4767194efdd420 differ diff --git a/external/boringssl/fuzz/cert_corpus/a29b87920a4c706f69a58c61e7d22aaa26a781a9 b/external/boringssl/fuzz/cert_corpus/a29b87920a4c706f69a58c61e7d22aaa26a781a9 new file mode 100644 index 0000000000..994fc86ef9 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/a29b87920a4c706f69a58c61e7d22aaa26a781a9 differ diff --git a/external/boringssl/fuzz/cert_corpus/a330339d9f71af3b1ef51f62aacf3e5a18233029 b/external/boringssl/fuzz/cert_corpus/a330339d9f71af3b1ef51f62aacf3e5a18233029 new file mode 100644 index 0000000000..b12aa104b6 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/a330339d9f71af3b1ef51f62aacf3e5a18233029 differ diff --git a/external/boringssl/fuzz/cert_corpus/a3332f9638dc9ec85e9c2166128bf7eb8ebb005f b/external/boringssl/fuzz/cert_corpus/a3332f9638dc9ec85e9c2166128bf7eb8ebb005f new file mode 100644 index 0000000000..a31a79b04c --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/a3332f9638dc9ec85e9c2166128bf7eb8ebb005f @@ -0,0 +1 @@ +„‡( \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/a36107992ae6b6dca220e831495ba60a4e817681 b/external/boringssl/fuzz/cert_corpus/a36107992ae6b6dca220e831495ba60a4e817681 new file mode 100644 index 0000000000..8b4d7f2f5b Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/a36107992ae6b6dca220e831495ba60a4e817681 differ diff --git a/external/boringssl/fuzz/cert_corpus/a37c3ee4668153e5ef9c272d43a2545a75b36854 b/external/boringssl/fuzz/cert_corpus/a37c3ee4668153e5ef9c272d43a2545a75b36854 new file mode 100644 index 0000000000..61ea85a364 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/a37c3ee4668153e5ef9c272d43a2545a75b36854 differ diff --git a/external/boringssl/fuzz/cert_corpus/a46eda9b97888af5263bc32293f940a8c2125ac3 b/external/boringssl/fuzz/cert_corpus/a46eda9b97888af5263bc32293f940a8c2125ac3 new file mode 100644 index 0000000000..b951711526 --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/a46eda9b97888af5263bc32293f940a8c2125ac3 @@ -0,0 +1 @@ +0€0€(í0‚€0Šh €1’h APhö|0‚%“å0 ¿÷œ¹æ(*)03€0€ \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/a5061c9bd9b94e35318ca968a7f933147ca56e83 b/external/boringssl/fuzz/cert_corpus/a5061c9bd9b94e35318ca968a7f933147ca56e83 new file mode 100644 index 0000000000..be16f72a1a --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/a5061c9bd9b94e35318ca968a7f933147ca56e83 @@ -0,0 +1 @@ +?ÿœ',; \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/a5dbab7e4f4c13f0ae62a3df935501484fecc8d4 b/external/boringssl/fuzz/cert_corpus/a5dbab7e4f4c13f0ae62a3df935501484fecc8d4 new file mode 100644 index 0000000000..ea357ce00a --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/a5dbab7e4f4c13f0ae62a3df935501484fecc8d4 @@ -0,0 +1 @@ +0€0€û€&0€ \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/a63ee3d25f38c1cca2b1498b548396d900e8741a b/external/boringssl/fuzz/cert_corpus/a63ee3d25f38c1cca2b1498b548396d900e8741a new file mode 100644 index 0000000000..523423a9ca Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/a63ee3d25f38c1cca2b1498b548396d900e8741a differ diff --git a/external/boringssl/fuzz/cert_corpus/a6447b7b3c50340aa14feb960245856ddeebc2cf b/external/boringssl/fuzz/cert_corpus/a6447b7b3c50340aa14feb960245856ddeebc2cf new file mode 100644 index 0000000000..61afa88159 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/a6447b7b3c50340aa14feb960245856ddeebc2cf differ diff --git a/external/boringssl/fuzz/cert_corpus/a6e50bf5f58ab1b4d2f034f924ef88ab3255e88d b/external/boringssl/fuzz/cert_corpus/a6e50bf5f58ab1b4d2f034f924ef88ab3255e88d new file mode 100644 index 0000000000..f150565058 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/a6e50bf5f58ab1b4d2f034f924ef88ab3255e88d differ diff --git a/external/boringssl/fuzz/cert_corpus/a758736dfeb57d7bb7f31793d81bab116942d31a b/external/boringssl/fuzz/cert_corpus/a758736dfeb57d7bb7f31793d81bab116942d31a new file mode 100644 index 0000000000..6b42801054 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/a758736dfeb57d7bb7f31793d81bab116942d31a differ diff --git a/external/boringssl/fuzz/cert_corpus/a83ca2374044aa6547ce0cd931cea82f34bcfbeb b/external/boringssl/fuzz/cert_corpus/a83ca2374044aa6547ce0cd931cea82f34bcfbeb new file mode 100644 index 0000000000..9529ae153f Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/a83ca2374044aa6547ce0cd931cea82f34bcfbeb differ diff --git a/external/boringssl/fuzz/cert_corpus/a897327b805c8b342ef8ad32adc92e904ee16bcd b/external/boringssl/fuzz/cert_corpus/a897327b805c8b342ef8ad32adc92e904ee16bcd new file mode 100644 index 0000000000..095fe4c7de Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/a897327b805c8b342ef8ad32adc92e904ee16bcd differ diff --git a/external/boringssl/fuzz/cert_corpus/a8be778f7892a8d914e7d742529143c57959e457 b/external/boringssl/fuzz/cert_corpus/a8be778f7892a8d914e7d742529143c57959e457 new file mode 100644 index 0000000000..8ec9696cc0 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/a8be778f7892a8d914e7d742529143c57959e457 differ diff --git a/external/boringssl/fuzz/cert_corpus/aa94b8c126db37057eba60ebf9ee8424c4dcd931 b/external/boringssl/fuzz/cert_corpus/aa94b8c126db37057eba60ebf9ee8424c4dcd931 new file mode 100644 index 0000000000..631376b890 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/aa94b8c126db37057eba60ebf9ee8424c4dcd931 differ diff --git a/external/boringssl/fuzz/cert_corpus/aa94e8277aa662cf0a17f930b9724e0c39699db7 b/external/boringssl/fuzz/cert_corpus/aa94e8277aa662cf0a17f930b9724e0c39699db7 new file mode 100644 index 0000000000..b7a3633177 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/aa94e8277aa662cf0a17f930b9724e0c39699db7 differ diff --git a/external/boringssl/fuzz/cert_corpus/ac7ce7801f5c13864f06b098b137bcca98c9dd4a b/external/boringssl/fuzz/cert_corpus/ac7ce7801f5c13864f06b098b137bcca98c9dd4a new file mode 100644 index 0000000000..40a633e6ed Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/ac7ce7801f5c13864f06b098b137bcca98c9dd4a differ diff --git a/external/boringssl/fuzz/cert_corpus/ad0875493831e5d809ec58af56dc27736d8da4cf b/external/boringssl/fuzz/cert_corpus/ad0875493831e5d809ec58af56dc27736d8da4cf new file mode 100644 index 0000000000..d90f248971 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/ad0875493831e5d809ec58af56dc27736d8da4cf differ diff --git a/external/boringssl/fuzz/cert_corpus/ad520c064da535365c2cf4262dc960cc03011a0a b/external/boringssl/fuzz/cert_corpus/ad520c064da535365c2cf4262dc960cc03011a0a new file mode 100644 index 0000000000..137e123d79 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/ad520c064da535365c2cf4262dc960cc03011a0a differ diff --git a/external/boringssl/fuzz/cert_corpus/ad6d7bb7923133cf1bd53c824cd8f400359430e2 b/external/boringssl/fuzz/cert_corpus/ad6d7bb7923133cf1bd53c824cd8f400359430e2 new file mode 100644 index 0000000000..701d60b2eb Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/ad6d7bb7923133cf1bd53c824cd8f400359430e2 differ diff --git a/external/boringssl/fuzz/cert_corpus/ad987767605d380e8465acbca66ea6b74158e4f9 b/external/boringssl/fuzz/cert_corpus/ad987767605d380e8465acbca66ea6b74158e4f9 new file mode 100644 index 0000000000..f6d620a653 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/ad987767605d380e8465acbca66ea6b74158e4f9 differ diff --git a/external/boringssl/fuzz/cert_corpus/ae096884e1100954f53c3e6c79845e94d4d9a746 b/external/boringssl/fuzz/cert_corpus/ae096884e1100954f53c3e6c79845e94d4d9a746 new file mode 100644 index 0000000000..2136ac82e8 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/ae096884e1100954f53c3e6c79845e94d4d9a746 differ diff --git a/external/boringssl/fuzz/cert_corpus/ae6c9f7732c5b28312dbfdd0d2708050e056f85b b/external/boringssl/fuzz/cert_corpus/ae6c9f7732c5b28312dbfdd0d2708050e056f85b new file mode 100644 index 0000000000..9aff0ede76 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/ae6c9f7732c5b28312dbfdd0d2708050e056f85b differ diff --git a/external/boringssl/fuzz/cert_corpus/af72aeeb36675d40d33838d25bad17ebe69e95eb b/external/boringssl/fuzz/cert_corpus/af72aeeb36675d40d33838d25bad17ebe69e95eb new file mode 100644 index 0000000000..fa9b883134 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/af72aeeb36675d40d33838d25bad17ebe69e95eb differ diff --git a/external/boringssl/fuzz/cert_corpus/afebf1b47d59c6c659856c5858596d646d42048a b/external/boringssl/fuzz/cert_corpus/afebf1b47d59c6c659856c5858596d646d42048a new file mode 100644 index 0000000000..92621d97db Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/afebf1b47d59c6c659856c5858596d646d42048a differ diff --git a/external/boringssl/fuzz/cert_corpus/b0bbe893c3557ffe322c9acbb268f58bd6f6ab9d b/external/boringssl/fuzz/cert_corpus/b0bbe893c3557ffe322c9acbb268f58bd6f6ab9d new file mode 100644 index 0000000000..7e5621d060 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/b0bbe893c3557ffe322c9acbb268f58bd6f6ab9d differ diff --git a/external/boringssl/fuzz/cert_corpus/b240ee6879847aa20ae97315c6062da51a223542 b/external/boringssl/fuzz/cert_corpus/b240ee6879847aa20ae97315c6062da51a223542 new file mode 100644 index 0000000000..cfb4fcef4b --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/b240ee6879847aa20ae97315c6062da51a223542 @@ -0,0 +1 @@ +¿÷œ¹ \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/b255b3d96ff0a405b5c782cd18fbc50034d09793 b/external/boringssl/fuzz/cert_corpus/b255b3d96ff0a405b5c782cd18fbc50034d09793 new file mode 100644 index 0000000000..62e59a0b4e --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/b255b3d96ff0a405b5c782cd18fbc50034d09793 @@ -0,0 +1 @@ +0€0€€1’h A0‚ \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/b2617f1a96f347b9d3d08f52e2459de63daaae63 b/external/boringssl/fuzz/cert_corpus/b2617f1a96f347b9d3d08f52e2459de63daaae63 new file mode 100644 index 0000000000..0e3021673d Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/b2617f1a96f347b9d3d08f52e2459de63daaae63 differ diff --git a/external/boringssl/fuzz/cert_corpus/b27f0261d700798b8499047d9d3e5a4330ff1b99 b/external/boringssl/fuzz/cert_corpus/b27f0261d700798b8499047d9d3e5a4330ff1b99 new file mode 100644 index 0000000000..456fba1d46 --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/b27f0261d700798b8499047d9d3e5a4330ff1b99 @@ -0,0 +1 @@ +¿¹)†ÿ¼; \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/b2bce56f2d1a5dcd77cc5373fcb6c6fd2bf0d810 b/external/boringssl/fuzz/cert_corpus/b2bce56f2d1a5dcd77cc5373fcb6c6fd2bf0d810 new file mode 100644 index 0000000000..a571c87c1d Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/b2bce56f2d1a5dcd77cc5373fcb6c6fd2bf0d810 differ diff --git a/external/boringssl/fuzz/cert_corpus/b33bee76673e45a532c82df4459d8f0efca9b024 b/external/boringssl/fuzz/cert_corpus/b33bee76673e45a532c82df4459d8f0efca9b024 new file mode 100644 index 0000000000..d434d19523 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/b33bee76673e45a532c82df4459d8f0efca9b024 differ diff --git a/external/boringssl/fuzz/cert_corpus/b496b414ddd42dd3d1633921131dab70ee93f9e8 b/external/boringssl/fuzz/cert_corpus/b496b414ddd42dd3d1633921131dab70ee93f9e8 new file mode 100644 index 0000000000..3bfb466217 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/b496b414ddd42dd3d1633921131dab70ee93f9e8 differ diff --git a/external/boringssl/fuzz/cert_corpus/b5442281d01a098f07aa150dc8c8ebc432922b74 b/external/boringssl/fuzz/cert_corpus/b5442281d01a098f07aa150dc8c8ebc432922b74 new file mode 100644 index 0000000000..257ea3fb24 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/b5442281d01a098f07aa150dc8c8ebc432922b74 differ diff --git a/external/boringssl/fuzz/cert_corpus/b569b141740c0b32d4f8f8d77fe603287cf4d902 b/external/boringssl/fuzz/cert_corpus/b569b141740c0b32d4f8f8d77fe603287cf4d902 new file mode 100644 index 0000000000..1ea877c5e9 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/b569b141740c0b32d4f8f8d77fe603287cf4d902 differ diff --git a/external/boringssl/fuzz/cert_corpus/b5f5a28954d2634baf685a1790ce013ca0f0f951 b/external/boringssl/fuzz/cert_corpus/b5f5a28954d2634baf685a1790ce013ca0f0f951 new file mode 100644 index 0000000000..72f9c5924d Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/b5f5a28954d2634baf685a1790ce013ca0f0f951 differ diff --git a/external/boringssl/fuzz/cert_corpus/b612998fc4201e2955aec046387e95254b25ba29 b/external/boringssl/fuzz/cert_corpus/b612998fc4201e2955aec046387e95254b25ba29 new file mode 100644 index 0000000000..c7d4fda706 --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/b612998fc4201e2955aec046387e95254b25ba29 @@ -0,0 +1 @@ +0}‚00 \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/b63a8d0e7c1848019b4e4e8e19d14adec00b7c19 b/external/boringssl/fuzz/cert_corpus/b63a8d0e7c1848019b4e4e8e19d14adec00b7c19 new file mode 100644 index 0000000000..540bf684db Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/b63a8d0e7c1848019b4e4e8e19d14adec00b7c19 differ diff --git a/external/boringssl/fuzz/cert_corpus/b6934c620f93440e12cf5861f588ab3574da9a84 b/external/boringssl/fuzz/cert_corpus/b6934c620f93440e12cf5861f588ab3574da9a84 new file mode 100644 index 0000000000..d849e7cd80 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/b6934c620f93440e12cf5861f588ab3574da9a84 differ diff --git a/external/boringssl/fuzz/cert_corpus/b6b89469619a6e0194005e993cf053cae6ff9fda b/external/boringssl/fuzz/cert_corpus/b6b89469619a6e0194005e993cf053cae6ff9fda new file mode 100644 index 0000000000..479ca26638 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/b6b89469619a6e0194005e993cf053cae6ff9fda differ diff --git a/external/boringssl/fuzz/cert_corpus/b732cd2e2227deff1529a431a16b3166bd66f0ac b/external/boringssl/fuzz/cert_corpus/b732cd2e2227deff1529a431a16b3166bd66f0ac new file mode 100644 index 0000000000..d01d05e83f Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/b732cd2e2227deff1529a431a16b3166bd66f0ac differ diff --git a/external/boringssl/fuzz/cert_corpus/b7a53770b23d0ac54b006ea0509bcc5bd27ce1d7 b/external/boringssl/fuzz/cert_corpus/b7a53770b23d0ac54b006ea0509bcc5bd27ce1d7 new file mode 100644 index 0000000000..2b91c14390 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/b7a53770b23d0ac54b006ea0509bcc5bd27ce1d7 differ diff --git a/external/boringssl/fuzz/cert_corpus/b88401cca46b7cc9cf588dbec641411101bbce68 b/external/boringssl/fuzz/cert_corpus/b88401cca46b7cc9cf588dbec641411101bbce68 new file mode 100644 index 0000000000..2347c46f95 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/b88401cca46b7cc9cf588dbec641411101bbce68 differ diff --git a/external/boringssl/fuzz/cert_corpus/b8c68e6426d5993b9c08d0384dce5d52014254a6 b/external/boringssl/fuzz/cert_corpus/b8c68e6426d5993b9c08d0384dce5d52014254a6 new file mode 100644 index 0000000000..8f76f42a5e --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/b8c68e6426d5993b9c08d0384dce5d52014254a6 @@ -0,0 +1 @@ +¿ÿœ¹†(; \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/b8f244f0d4a928ec6e532af4c7c633c99de03ee2 b/external/boringssl/fuzz/cert_corpus/b8f244f0d4a928ec6e532af4c7c633c99de03ee2 new file mode 100644 index 0000000000..a3332f249c Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/b8f244f0d4a928ec6e532af4c7c633c99de03ee2 differ diff --git a/external/boringssl/fuzz/cert_corpus/ba485873c6de244c1d036607fd57107bf3d54399 b/external/boringssl/fuzz/cert_corpus/ba485873c6de244c1d036607fd57107bf3d54399 new file mode 100644 index 0000000000..89f479aa15 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/ba485873c6de244c1d036607fd57107bf3d54399 differ diff --git a/external/boringssl/fuzz/cert_corpus/ba8ffb341293741fb442ad7817290bf57acc87f0 b/external/boringssl/fuzz/cert_corpus/ba8ffb341293741fb442ad7817290bf57acc87f0 new file mode 100644 index 0000000000..48242a3e00 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/ba8ffb341293741fb442ad7817290bf57acc87f0 differ diff --git a/external/boringssl/fuzz/cert_corpus/bae9b0825a33ac52cd413665dd38a17837174a7e b/external/boringssl/fuzz/cert_corpus/bae9b0825a33ac52cd413665dd38a17837174a7e new file mode 100644 index 0000000000..f4e18e0836 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/bae9b0825a33ac52cd413665dd38a17837174a7e differ diff --git a/external/boringssl/fuzz/cert_corpus/bb1fb206c56745bf992220e6c7de0e2fc94cf068 b/external/boringssl/fuzz/cert_corpus/bb1fb206c56745bf992220e6c7de0e2fc94cf068 new file mode 100644 index 0000000000..f0bbba61e9 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/bb1fb206c56745bf992220e6c7de0e2fc94cf068 differ diff --git a/external/boringssl/fuzz/cert_corpus/bc01d9510d91bcf2ba747842a572140801564b92 b/external/boringssl/fuzz/cert_corpus/bc01d9510d91bcf2ba747842a572140801564b92 new file mode 100644 index 0000000000..8a70845622 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/bc01d9510d91bcf2ba747842a572140801564b92 differ diff --git a/external/boringssl/fuzz/cert_corpus/bd32136e6ec853a56e70060a2c308187b8fccf65 b/external/boringssl/fuzz/cert_corpus/bd32136e6ec853a56e70060a2c308187b8fccf65 new file mode 100644 index 0000000000..3383d6e72b Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/bd32136e6ec853a56e70060a2c308187b8fccf65 differ diff --git a/external/boringssl/fuzz/cert_corpus/bd351dbed468c58280ee4735c6fe101813bb767c b/external/boringssl/fuzz/cert_corpus/bd351dbed468c58280ee4735c6fe101813bb767c new file mode 100644 index 0000000000..b41960e7be Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/bd351dbed468c58280ee4735c6fe101813bb767c differ diff --git a/external/boringssl/fuzz/cert_corpus/bd49114ebfcb9795f8231b482ad700f1dd092def b/external/boringssl/fuzz/cert_corpus/bd49114ebfcb9795f8231b482ad700f1dd092def new file mode 100644 index 0000000000..583b122948 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/bd49114ebfcb9795f8231b482ad700f1dd092def differ diff --git a/external/boringssl/fuzz/cert_corpus/bd72b9ca5d91970e5b77e97a67781e3e70810edf b/external/boringssl/fuzz/cert_corpus/bd72b9ca5d91970e5b77e97a67781e3e70810edf new file mode 100644 index 0000000000..f576286605 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/bd72b9ca5d91970e5b77e97a67781e3e70810edf differ diff --git a/external/boringssl/fuzz/cert_corpus/be96bcebf50e143552339a23071c9994bb7b5548 b/external/boringssl/fuzz/cert_corpus/be96bcebf50e143552339a23071c9994bb7b5548 new file mode 100644 index 0000000000..415c590339 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/be96bcebf50e143552339a23071c9994bb7b5548 differ diff --git a/external/boringssl/fuzz/cert_corpus/bf89b0f5278535c052386adea67874b12668fca2 b/external/boringssl/fuzz/cert_corpus/bf89b0f5278535c052386adea67874b12668fca2 new file mode 100644 index 0000000000..682eebf8a0 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/bf89b0f5278535c052386adea67874b12668fca2 differ diff --git a/external/boringssl/fuzz/cert_corpus/bfa6177702f7b3d35d431d805af1216b3ace3a28 b/external/boringssl/fuzz/cert_corpus/bfa6177702f7b3d35d431d805af1216b3ace3a28 new file mode 100644 index 0000000000..905033306b Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/bfa6177702f7b3d35d431d805af1216b3ace3a28 differ diff --git a/external/boringssl/fuzz/cert_corpus/c10def6097a072cd11a89161c49c76f4cd9b851b b/external/boringssl/fuzz/cert_corpus/c10def6097a072cd11a89161c49c76f4cd9b851b new file mode 100644 index 0000000000..60554075c6 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/c10def6097a072cd11a89161c49c76f4cd9b851b differ diff --git a/external/boringssl/fuzz/cert_corpus/c218be470382eb7b9cf45659c58d66bb000f4eea b/external/boringssl/fuzz/cert_corpus/c218be470382eb7b9cf45659c58d66bb000f4eea new file mode 100644 index 0000000000..cdce1db360 --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/c218be470382eb7b9cf45659c58d66bb000f4eea @@ -0,0 +1 @@ +¿óµ90† \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/c2b238783ccd5d9a8ab37f45e12001e2d32634b6 b/external/boringssl/fuzz/cert_corpus/c2b238783ccd5d9a8ab37f45e12001e2d32634b6 new file mode 100644 index 0000000000..473c58d51d Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/c2b238783ccd5d9a8ab37f45e12001e2d32634b6 differ diff --git a/external/boringssl/fuzz/cert_corpus/c3c6d8be363e9b8535dc6586a6b01122efefdea9 b/external/boringssl/fuzz/cert_corpus/c3c6d8be363e9b8535dc6586a6b01122efefdea9 new file mode 100644 index 0000000000..f2332b4973 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/c3c6d8be363e9b8535dc6586a6b01122efefdea9 differ diff --git a/external/boringssl/fuzz/cert_corpus/c4437538c745e35381b74aba56778cfa6379180b b/external/boringssl/fuzz/cert_corpus/c4437538c745e35381b74aba56778cfa6379180b new file mode 100644 index 0000000000..a4c5ee24ae Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/c4437538c745e35381b74aba56778cfa6379180b differ diff --git a/external/boringssl/fuzz/cert_corpus/c452d11f12a4eafb8d61aefd5354e5f5d51c18d4 b/external/boringssl/fuzz/cert_corpus/c452d11f12a4eafb8d61aefd5354e5f5d51c18d4 new file mode 100644 index 0000000000..620119d8d6 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/c452d11f12a4eafb8d61aefd5354e5f5d51c18d4 differ diff --git a/external/boringssl/fuzz/cert_corpus/c45c2dd1094d4b93f18f081c0b576bae60bb27d3 b/external/boringssl/fuzz/cert_corpus/c45c2dd1094d4b93f18f081c0b576bae60bb27d3 new file mode 100644 index 0000000000..fac8866af9 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/c45c2dd1094d4b93f18f081c0b576bae60bb27d3 differ diff --git a/external/boringssl/fuzz/cert_corpus/c47cc42321d347f0b8596e94c53ddfc0c5a90a88 b/external/boringssl/fuzz/cert_corpus/c47cc42321d347f0b8596e94c53ddfc0c5a90a88 new file mode 100644 index 0000000000..2eaa4b215f Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/c47cc42321d347f0b8596e94c53ddfc0c5a90a88 differ diff --git a/external/boringssl/fuzz/cert_corpus/c4f3c6cfbef081bf63b3b5972c9137635d445fdd b/external/boringssl/fuzz/cert_corpus/c4f3c6cfbef081bf63b3b5972c9137635d445fdd new file mode 100644 index 0000000000..8d81d37589 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/c4f3c6cfbef081bf63b3b5972c9137635d445fdd differ diff --git a/external/boringssl/fuzz/cert_corpus/c4f605ca070c95dc5d1fd59124a12d35e8c76008 b/external/boringssl/fuzz/cert_corpus/c4f605ca070c95dc5d1fd59124a12d35e8c76008 new file mode 100644 index 0000000000..42c6db63ea Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/c4f605ca070c95dc5d1fd59124a12d35e8c76008 differ diff --git a/external/boringssl/fuzz/cert_corpus/c549b74782b8ee587cea2d773c76f736774a1040 b/external/boringssl/fuzz/cert_corpus/c549b74782b8ee587cea2d773c76f736774a1040 new file mode 100644 index 0000000000..dcc743f4c4 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/c549b74782b8ee587cea2d773c76f736774a1040 differ diff --git a/external/boringssl/fuzz/cert_corpus/c613a74f7c25acd72e426aae6b6f8aca4230de92 b/external/boringssl/fuzz/cert_corpus/c613a74f7c25acd72e426aae6b6f8aca4230de92 new file mode 100644 index 0000000000..eea0415290 --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/c613a74f7c25acd72e426aae6b6f8aca4230de92 @@ -0,0 +1 @@ +Ÿ­œ:† \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/c6b5b66f8a56110cef76c49e0f128584ff9ae744 b/external/boringssl/fuzz/cert_corpus/c6b5b66f8a56110cef76c49e0f128584ff9ae744 new file mode 100644 index 0000000000..7f767fdec0 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/c6b5b66f8a56110cef76c49e0f128584ff9ae744 differ diff --git a/external/boringssl/fuzz/cert_corpus/c6bb980166717e341bc7628fdcf7e6857f42b78e b/external/boringssl/fuzz/cert_corpus/c6bb980166717e341bc7628fdcf7e6857f42b78e new file mode 100644 index 0000000000..9f4dec049f Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/c6bb980166717e341bc7628fdcf7e6857f42b78e differ diff --git a/external/boringssl/fuzz/cert_corpus/c885c076019c097c788823b5c242789315ce18fb b/external/boringssl/fuzz/cert_corpus/c885c076019c097c788823b5c242789315ce18fb new file mode 100644 index 0000000000..f760e5edc6 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/c885c076019c097c788823b5c242789315ce18fb differ diff --git a/external/boringssl/fuzz/cert_corpus/c8fe6b745e1bed025f2948444e1372cf89bf2f54 b/external/boringssl/fuzz/cert_corpus/c8fe6b745e1bed025f2948444e1372cf89bf2f54 new file mode 100644 index 0000000000..5091a2023e Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/c8fe6b745e1bed025f2948444e1372cf89bf2f54 differ diff --git a/external/boringssl/fuzz/cert_corpus/ca5f6f2655ef6d5737e61519eddd94cecbd9aec8 b/external/boringssl/fuzz/cert_corpus/ca5f6f2655ef6d5737e61519eddd94cecbd9aec8 new file mode 100644 index 0000000000..c50621aa48 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/ca5f6f2655ef6d5737e61519eddd94cecbd9aec8 differ diff --git a/external/boringssl/fuzz/cert_corpus/cc70087dae81f66673015fe1f97b13b0f1d7256d b/external/boringssl/fuzz/cert_corpus/cc70087dae81f66673015fe1f97b13b0f1d7256d new file mode 100644 index 0000000000..2c5ab046eb Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/cc70087dae81f66673015fe1f97b13b0f1d7256d differ diff --git a/external/boringssl/fuzz/cert_corpus/cca7bdb3e8b8c03d754aedbb5f781644305d3644 b/external/boringssl/fuzz/cert_corpus/cca7bdb3e8b8c03d754aedbb5f781644305d3644 new file mode 100644 index 0000000000..1ff4122baf Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/cca7bdb3e8b8c03d754aedbb5f781644305d3644 differ diff --git a/external/boringssl/fuzz/cert_corpus/ccea62417883c07b37d5f8120602b78e96cf18ca b/external/boringssl/fuzz/cert_corpus/ccea62417883c07b37d5f8120602b78e96cf18ca new file mode 100644 index 0000000000..8ecbb726b2 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/ccea62417883c07b37d5f8120602b78e96cf18ca differ diff --git a/external/boringssl/fuzz/cert_corpus/ccf05090692d99c4c28dc2e104896819ed3fdd9a b/external/boringssl/fuzz/cert_corpus/ccf05090692d99c4c28dc2e104896819ed3fdd9a new file mode 100644 index 0000000000..bc6940271b Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/ccf05090692d99c4c28dc2e104896819ed3fdd9a differ diff --git a/external/boringssl/fuzz/cert_corpus/ce1b40306ee7b3df129aa772c11103f7237aa1ca b/external/boringssl/fuzz/cert_corpus/ce1b40306ee7b3df129aa772c11103f7237aa1ca new file mode 100644 index 0000000000..636066d8b3 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/ce1b40306ee7b3df129aa772c11103f7237aa1ca differ diff --git a/external/boringssl/fuzz/cert_corpus/ce80fcf5a7c0dcfbdb2739c27c38a4d4a764d66f b/external/boringssl/fuzz/cert_corpus/ce80fcf5a7c0dcfbdb2739c27c38a4d4a764d66f new file mode 100644 index 0000000000..3873f4b70d Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/ce80fcf5a7c0dcfbdb2739c27c38a4d4a764d66f differ diff --git a/external/boringssl/fuzz/cert_corpus/d16735101a64c74e14692a65c2ca06abb8d9cb0d b/external/boringssl/fuzz/cert_corpus/d16735101a64c74e14692a65c2ca06abb8d9cb0d new file mode 100644 index 0000000000..e18ba5665c Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/d16735101a64c74e14692a65c2ca06abb8d9cb0d differ diff --git a/external/boringssl/fuzz/cert_corpus/d16b443aec52814ed1678cb3b02ee561b6f1889c b/external/boringssl/fuzz/cert_corpus/d16b443aec52814ed1678cb3b02ee561b6f1889c new file mode 100644 index 0000000000..bf18fc9cf8 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/d16b443aec52814ed1678cb3b02ee561b6f1889c differ diff --git a/external/boringssl/fuzz/cert_corpus/d3c601c2ca8db7dbeddb254cda2d91cadc036e61 b/external/boringssl/fuzz/cert_corpus/d3c601c2ca8db7dbeddb254cda2d91cadc036e61 new file mode 100644 index 0000000000..c439807e2f Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/d3c601c2ca8db7dbeddb254cda2d91cadc036e61 differ diff --git a/external/boringssl/fuzz/cert_corpus/d3fe83b8d87ccda2bbca5e81ce3ab1a1400bfbe8 b/external/boringssl/fuzz/cert_corpus/d3fe83b8d87ccda2bbca5e81ce3ab1a1400bfbe8 new file mode 100644 index 0000000000..08e5b85ed7 --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/d3fe83b8d87ccda2bbca5e81ce3ab1a1400bfbe8 @@ -0,0 +1 @@ +¿ \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/d51782b160d3dacee93a1dc34cfec9a7ca4a6c53 b/external/boringssl/fuzz/cert_corpus/d51782b160d3dacee93a1dc34cfec9a7ca4a6c53 new file mode 100644 index 0000000000..2231162370 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/d51782b160d3dacee93a1dc34cfec9a7ca4a6c53 differ diff --git a/external/boringssl/fuzz/cert_corpus/d5c2fed75bc049b570bd445b9461a1595f880dca b/external/boringssl/fuzz/cert_corpus/d5c2fed75bc049b570bd445b9461a1595f880dca new file mode 100644 index 0000000000..c7b76a37bb --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/d5c2fed75bc049b570bd445b9461a1595f880dca @@ -0,0 +1 @@ +0€0€"*€1’h A0:;€ \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/d5c3e609d1685e2a11e63622d71cba7cc8a73590 b/external/boringssl/fuzz/cert_corpus/d5c3e609d1685e2a11e63622d71cba7cc8a73590 new file mode 100644 index 0000000000..3ca6881b00 --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/d5c3e609d1685e2a11e63622d71cba7cc8a73590 @@ -0,0 +1 @@ +0€0€(í0‚€0‚h €1’h A1hö|0‚%“å0  *†0¯€0€0€ \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/d60f11bfbd2a0b5de6ca765d4059f994ec6e9c15 b/external/boringssl/fuzz/cert_corpus/d60f11bfbd2a0b5de6ca765d4059f994ec6e9c15 new file mode 100644 index 0000000000..0533d26d89 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/d60f11bfbd2a0b5de6ca765d4059f994ec6e9c15 differ diff --git a/external/boringssl/fuzz/cert_corpus/d665df68474dfd7f768ac8f202455cebf498724d b/external/boringssl/fuzz/cert_corpus/d665df68474dfd7f768ac8f202455cebf498724d new file mode 100644 index 0000000000..ed27ac7427 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/d665df68474dfd7f768ac8f202455cebf498724d differ diff --git a/external/boringssl/fuzz/cert_corpus/d6df7b56969b3f2bd6c323aca98179f1f3ef3396 b/external/boringssl/fuzz/cert_corpus/d6df7b56969b3f2bd6c323aca98179f1f3ef3396 new file mode 100644 index 0000000000..85d42a2bb1 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/d6df7b56969b3f2bd6c323aca98179f1f3ef3396 differ diff --git a/external/boringssl/fuzz/cert_corpus/d74eeb9a616344007edfa077561a95bd1874152d b/external/boringssl/fuzz/cert_corpus/d74eeb9a616344007edfa077561a95bd1874152d new file mode 100644 index 0000000000..7c91980aa2 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/d74eeb9a616344007edfa077561a95bd1874152d differ diff --git a/external/boringssl/fuzz/cert_corpus/d7ba4e58caa05b0c3bd0f5258adf1429d022632f b/external/boringssl/fuzz/cert_corpus/d7ba4e58caa05b0c3bd0f5258adf1429d022632f new file mode 100644 index 0000000000..4142ca23d5 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/d7ba4e58caa05b0c3bd0f5258adf1429d022632f differ diff --git a/external/boringssl/fuzz/cert_corpus/d805c1da8681e325ad44cf57dbac466ca77efca8 b/external/boringssl/fuzz/cert_corpus/d805c1da8681e325ad44cf57dbac466ca77efca8 new file mode 100644 index 0000000000..5397af44eb Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/d805c1da8681e325ad44cf57dbac466ca77efca8 differ diff --git a/external/boringssl/fuzz/cert_corpus/d88ae7db4ae813bab4769563be5290808a004796 b/external/boringssl/fuzz/cert_corpus/d88ae7db4ae813bab4769563be5290808a004796 new file mode 100644 index 0000000000..b945a254cd Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/d88ae7db4ae813bab4769563be5290808a004796 differ diff --git a/external/boringssl/fuzz/cert_corpus/d93f2f96d294071ed098a03d86ed46d71919e7a1 b/external/boringssl/fuzz/cert_corpus/d93f2f96d294071ed098a03d86ed46d71919e7a1 new file mode 100644 index 0000000000..8e3f12c8a6 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/d93f2f96d294071ed098a03d86ed46d71919e7a1 differ diff --git a/external/boringssl/fuzz/cert_corpus/dc999ae9538c03dc88825fb62c92d98a8d8e48ee b/external/boringssl/fuzz/cert_corpus/dc999ae9538c03dc88825fb62c92d98a8d8e48ee new file mode 100644 index 0000000000..513eabb402 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/dc999ae9538c03dc88825fb62c92d98a8d8e48ee differ diff --git a/external/boringssl/fuzz/cert_corpus/de05b31a05846f00be753f15be9242b01396a553 b/external/boringssl/fuzz/cert_corpus/de05b31a05846f00be753f15be9242b01396a553 new file mode 100644 index 0000000000..1c253ccf40 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/de05b31a05846f00be753f15be9242b01396a553 differ diff --git a/external/boringssl/fuzz/cert_corpus/de0df75a8e629a16586e75477510bb7f0093f674 b/external/boringssl/fuzz/cert_corpus/de0df75a8e629a16586e75477510bb7f0093f674 new file mode 100644 index 0000000000..2f9537c064 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/de0df75a8e629a16586e75477510bb7f0093f674 differ diff --git a/external/boringssl/fuzz/cert_corpus/dfab8ecb3664b5c7e32ef43d24f964fd2d7aad4e b/external/boringssl/fuzz/cert_corpus/dfab8ecb3664b5c7e32ef43d24f964fd2d7aad4e new file mode 100644 index 0000000000..8363e7d91c Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/dfab8ecb3664b5c7e32ef43d24f964fd2d7aad4e differ diff --git a/external/boringssl/fuzz/cert_corpus/e1749e1d3e67cc947379ece199ded471a5e55c79 b/external/boringssl/fuzz/cert_corpus/e1749e1d3e67cc947379ece199ded471a5e55c79 new file mode 100644 index 0000000000..af531320c3 --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/e1749e1d3e67cc947379ece199ded471a5e55c79 @@ -0,0 +1 @@ +1‚ \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/e180125371c88bbab75d9aac4d6b1144e0f0683e b/external/boringssl/fuzz/cert_corpus/e180125371c88bbab75d9aac4d6b1144e0f0683e new file mode 100644 index 0000000000..5d77a89acb Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/e180125371c88bbab75d9aac4d6b1144e0f0683e differ diff --git a/external/boringssl/fuzz/cert_corpus/e350aef7327491a094f8a8bc3ca01ce636e9b945 b/external/boringssl/fuzz/cert_corpus/e350aef7327491a094f8a8bc3ca01ce636e9b945 new file mode 100644 index 0000000000..1fe7694e84 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/e350aef7327491a094f8a8bc3ca01ce636e9b945 differ diff --git a/external/boringssl/fuzz/cert_corpus/e4c5cfd43a153699610e5456b0b58984bdc36b25 b/external/boringssl/fuzz/cert_corpus/e4c5cfd43a153699610e5456b0b58984bdc36b25 new file mode 100644 index 0000000000..46ac641d00 --- /dev/null +++ b/external/boringssl/fuzz/cert_corpus/e4c5cfd43a153699610e5456b0b58984bdc36b25 @@ -0,0 +1 @@ +0€0€(í0‚€0‚h €1’h A1hö|0‚%“å0  (€0†*0À0€ \ No newline at end of file diff --git a/external/boringssl/fuzz/cert_corpus/e662bc8b0f1bcea6081c65fc1195e6df53a51961 b/external/boringssl/fuzz/cert_corpus/e662bc8b0f1bcea6081c65fc1195e6df53a51961 new file mode 100644 index 0000000000..21a90781e7 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/e662bc8b0f1bcea6081c65fc1195e6df53a51961 differ diff --git a/external/boringssl/fuzz/cert_corpus/e67cc75ea22aec3e31ac08718a0e8ebb49d0378b b/external/boringssl/fuzz/cert_corpus/e67cc75ea22aec3e31ac08718a0e8ebb49d0378b new file mode 100644 index 0000000000..e704b2b930 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/e67cc75ea22aec3e31ac08718a0e8ebb49d0378b differ diff --git a/external/boringssl/fuzz/cert_corpus/e6d0bda14de5fabf61d6a77ed9de9dc32751c193 b/external/boringssl/fuzz/cert_corpus/e6d0bda14de5fabf61d6a77ed9de9dc32751c193 new file mode 100644 index 0000000000..ce4f10335e Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/e6d0bda14de5fabf61d6a77ed9de9dc32751c193 differ diff --git a/external/boringssl/fuzz/cert_corpus/e8d362075baf5e7ffa283a1f685ecfe270b756e3 b/external/boringssl/fuzz/cert_corpus/e8d362075baf5e7ffa283a1f685ecfe270b756e3 new file mode 100644 index 0000000000..93353a7a5d Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/e8d362075baf5e7ffa283a1f685ecfe270b756e3 differ diff --git a/external/boringssl/fuzz/cert_corpus/e9617db6d8b651b46ea1ef7b904887d3259d8721 b/external/boringssl/fuzz/cert_corpus/e9617db6d8b651b46ea1ef7b904887d3259d8721 new file mode 100644 index 0000000000..0cf5bc7313 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/e9617db6d8b651b46ea1ef7b904887d3259d8721 differ diff --git a/external/boringssl/fuzz/cert_corpus/ea796fb39b55459c01da8f1aa538c91b9a3e0419 b/external/boringssl/fuzz/cert_corpus/ea796fb39b55459c01da8f1aa538c91b9a3e0419 new file mode 100644 index 0000000000..51bfe73355 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/ea796fb39b55459c01da8f1aa538c91b9a3e0419 differ diff --git a/external/boringssl/fuzz/cert_corpus/eb0f13db27c5f72eef417ac98c8d5b326f40d229 b/external/boringssl/fuzz/cert_corpus/eb0f13db27c5f72eef417ac98c8d5b326f40d229 new file mode 100644 index 0000000000..a6b757b115 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/eb0f13db27c5f72eef417ac98c8d5b326f40d229 differ diff --git a/external/boringssl/fuzz/cert_corpus/ebb2f919adba543e9f61ba5ffd13e89c9422f70a b/external/boringssl/fuzz/cert_corpus/ebb2f919adba543e9f61ba5ffd13e89c9422f70a new file mode 100644 index 0000000000..e5497b5eef Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/ebb2f919adba543e9f61ba5ffd13e89c9422f70a differ diff --git a/external/boringssl/fuzz/cert_corpus/ebf19e8523e49eabc87277ada0e355d096d5cddf b/external/boringssl/fuzz/cert_corpus/ebf19e8523e49eabc87277ada0e355d096d5cddf new file mode 100644 index 0000000000..8ab90f423e Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/ebf19e8523e49eabc87277ada0e355d096d5cddf differ diff --git a/external/boringssl/fuzz/cert_corpus/ec19b8e77fa86a2aa5602a6a45a8a6df7b334794 b/external/boringssl/fuzz/cert_corpus/ec19b8e77fa86a2aa5602a6a45a8a6df7b334794 new file mode 100644 index 0000000000..33ce1592bc Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/ec19b8e77fa86a2aa5602a6a45a8a6df7b334794 differ diff --git a/external/boringssl/fuzz/cert_corpus/ec32acf8f685b186fcfe11250167c70174cbea22 b/external/boringssl/fuzz/cert_corpus/ec32acf8f685b186fcfe11250167c70174cbea22 new file mode 100644 index 0000000000..dbc33b6f93 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/ec32acf8f685b186fcfe11250167c70174cbea22 differ diff --git a/external/boringssl/fuzz/cert_corpus/ec32f05544e071fea1ec748e9a5692e85a490cc2 b/external/boringssl/fuzz/cert_corpus/ec32f05544e071fea1ec748e9a5692e85a490cc2 new file mode 100644 index 0000000000..ca67e3cc2a Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/ec32f05544e071fea1ec748e9a5692e85a490cc2 differ diff --git a/external/boringssl/fuzz/cert_corpus/ec755a11cd589bdd907bbb67b83f41e3b49f42cd b/external/boringssl/fuzz/cert_corpus/ec755a11cd589bdd907bbb67b83f41e3b49f42cd new file mode 100644 index 0000000000..71bfc737d9 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/ec755a11cd589bdd907bbb67b83f41e3b49f42cd differ diff --git a/external/boringssl/fuzz/cert_corpus/ecac00e857f10a143e5760a8d027498fdb46cbf4 b/external/boringssl/fuzz/cert_corpus/ecac00e857f10a143e5760a8d027498fdb46cbf4 new file mode 100644 index 0000000000..540320c896 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/ecac00e857f10a143e5760a8d027498fdb46cbf4 differ diff --git a/external/boringssl/fuzz/cert_corpus/ed5c5806eb26764f7aa87b897ab67a1df82dbf53 b/external/boringssl/fuzz/cert_corpus/ed5c5806eb26764f7aa87b897ab67a1df82dbf53 new file mode 100644 index 0000000000..cda1d18cd1 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/ed5c5806eb26764f7aa87b897ab67a1df82dbf53 differ diff --git a/external/boringssl/fuzz/cert_corpus/edf23858b6ac5eb22f6e573f9d6edae229b9c100 b/external/boringssl/fuzz/cert_corpus/edf23858b6ac5eb22f6e573f9d6edae229b9c100 new file mode 100644 index 0000000000..3e1f378330 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/edf23858b6ac5eb22f6e573f9d6edae229b9c100 differ diff --git a/external/boringssl/fuzz/cert_corpus/ee895bc6274dd27e4a6f18e26d598846f4b15e95 b/external/boringssl/fuzz/cert_corpus/ee895bc6274dd27e4a6f18e26d598846f4b15e95 new file mode 100644 index 0000000000..14f5dc7504 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/ee895bc6274dd27e4a6f18e26d598846f4b15e95 differ diff --git a/external/boringssl/fuzz/cert_corpus/efb28c035f9c8a62a312dfe83434cddbc51b4c8a b/external/boringssl/fuzz/cert_corpus/efb28c035f9c8a62a312dfe83434cddbc51b4c8a new file mode 100644 index 0000000000..3c835e0fc7 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/efb28c035f9c8a62a312dfe83434cddbc51b4c8a differ diff --git a/external/boringssl/fuzz/cert_corpus/efbda51a6d24e19451c4445f985b85fe04b87a93 b/external/boringssl/fuzz/cert_corpus/efbda51a6d24e19451c4445f985b85fe04b87a93 new file mode 100644 index 0000000000..b6dfdc410e Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/efbda51a6d24e19451c4445f985b85fe04b87a93 differ diff --git a/external/boringssl/fuzz/cert_corpus/f00aedcbd7394eb866d433f49f04f6d252d3fe44 b/external/boringssl/fuzz/cert_corpus/f00aedcbd7394eb866d433f49f04f6d252d3fe44 new file mode 100644 index 0000000000..0b71f42cf9 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/f00aedcbd7394eb866d433f49f04f6d252d3fe44 differ diff --git a/external/boringssl/fuzz/cert_corpus/f00bfbc36ddb3d9cf089414ff7dcfc973927987c b/external/boringssl/fuzz/cert_corpus/f00bfbc36ddb3d9cf089414ff7dcfc973927987c new file mode 100644 index 0000000000..97bd8c94f3 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/f00bfbc36ddb3d9cf089414ff7dcfc973927987c differ diff --git a/external/boringssl/fuzz/cert_corpus/f02539e797ce16b7842fe95cfba87c44fbf92119 b/external/boringssl/fuzz/cert_corpus/f02539e797ce16b7842fe95cfba87c44fbf92119 new file mode 100644 index 0000000000..5f7013c410 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/f02539e797ce16b7842fe95cfba87c44fbf92119 differ diff --git a/external/boringssl/fuzz/cert_corpus/f0cf1c8a091014b0ddd88edb3e9567370cb5d741 b/external/boringssl/fuzz/cert_corpus/f0cf1c8a091014b0ddd88edb3e9567370cb5d741 new file mode 100644 index 0000000000..c3a681d455 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/f0cf1c8a091014b0ddd88edb3e9567370cb5d741 differ diff --git a/external/boringssl/fuzz/cert_corpus/f167e20b679ab2689a5723e39c19c33fc3b4c9e8 b/external/boringssl/fuzz/cert_corpus/f167e20b679ab2689a5723e39c19c33fc3b4c9e8 new file mode 100644 index 0000000000..a84f9e2807 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/f167e20b679ab2689a5723e39c19c33fc3b4c9e8 differ diff --git a/external/boringssl/fuzz/cert_corpus/f34b279011e9a03e95b85f6a8d5e2a59089fe516 b/external/boringssl/fuzz/cert_corpus/f34b279011e9a03e95b85f6a8d5e2a59089fe516 new file mode 100644 index 0000000000..2641dad74b Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/f34b279011e9a03e95b85f6a8d5e2a59089fe516 differ diff --git a/external/boringssl/fuzz/cert_corpus/f44630078d74ae4e135a62d7477847b24b399bf1 b/external/boringssl/fuzz/cert_corpus/f44630078d74ae4e135a62d7477847b24b399bf1 new file mode 100644 index 0000000000..d8bd910a15 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/f44630078d74ae4e135a62d7477847b24b399bf1 differ diff --git a/external/boringssl/fuzz/cert_corpus/f588df591762aeb4f9cef3e2d63ab34cbab3567b b/external/boringssl/fuzz/cert_corpus/f588df591762aeb4f9cef3e2d63ab34cbab3567b new file mode 100644 index 0000000000..304f5b3ebd Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/f588df591762aeb4f9cef3e2d63ab34cbab3567b differ diff --git a/external/boringssl/fuzz/cert_corpus/f8e817dc5c2b1f27d31240841ade404d15606742 b/external/boringssl/fuzz/cert_corpus/f8e817dc5c2b1f27d31240841ade404d15606742 new file mode 100644 index 0000000000..be2675bea4 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/f8e817dc5c2b1f27d31240841ade404d15606742 differ diff --git a/external/boringssl/fuzz/cert_corpus/fbd5fda7debfed22a821cd1c796f2ecf459a14a0 b/external/boringssl/fuzz/cert_corpus/fbd5fda7debfed22a821cd1c796f2ecf459a14a0 new file mode 100644 index 0000000000..9ebce3541c Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/fbd5fda7debfed22a821cd1c796f2ecf459a14a0 differ diff --git a/external/boringssl/fuzz/cert_corpus/fca0bbdfab4ad790670f079ac242c12a5c7fa58a b/external/boringssl/fuzz/cert_corpus/fca0bbdfab4ad790670f079ac242c12a5c7fa58a new file mode 100644 index 0000000000..ff878240ce Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/fca0bbdfab4ad790670f079ac242c12a5c7fa58a differ diff --git a/external/boringssl/fuzz/cert_corpus/fd7e619a4b12bc64f5275b6afde1c2c1ccb8e4ac b/external/boringssl/fuzz/cert_corpus/fd7e619a4b12bc64f5275b6afde1c2c1ccb8e4ac new file mode 100644 index 0000000000..2d3b0ce0af Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/fd7e619a4b12bc64f5275b6afde1c2c1ccb8e4ac differ diff --git a/external/boringssl/fuzz/cert_corpus/feba41538668e8c9eb82132ca606c0fd7f812547 b/external/boringssl/fuzz/cert_corpus/feba41538668e8c9eb82132ca606c0fd7f812547 new file mode 100644 index 0000000000..4bc86a27b7 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/feba41538668e8c9eb82132ca606c0fd7f812547 differ diff --git a/external/boringssl/fuzz/cert_corpus/feefb266829c616c907a1d4accab0287ef47c2c2 b/external/boringssl/fuzz/cert_corpus/feefb266829c616c907a1d4accab0287ef47c2c2 new file mode 100644 index 0000000000..fb4165c69d Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/feefb266829c616c907a1d4accab0287ef47c2c2 differ diff --git a/external/boringssl/fuzz/cert_corpus/ff46d1b4923b92b30fa6fd9a7e429ad1cb1f9e7f b/external/boringssl/fuzz/cert_corpus/ff46d1b4923b92b30fa6fd9a7e429ad1cb1f9e7f new file mode 100644 index 0000000000..aff10442a0 Binary files /dev/null and b/external/boringssl/fuzz/cert_corpus/ff46d1b4923b92b30fa6fd9a7e429ad1cb1f9e7f differ diff --git a/external/boringssl/fuzz/client.cc b/external/boringssl/fuzz/client.cc new file mode 100644 index 0000000000..a90a896054 --- /dev/null +++ b/external/boringssl/fuzz/client.cc @@ -0,0 +1,55 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include +#include + +struct GlobalState { + GlobalState() : ctx(SSL_CTX_new(SSLv23_method())) {} + + ~GlobalState() { + SSL_CTX_free(ctx); + } + + SSL_CTX *const ctx; +}; + +static GlobalState g_state; + +extern "C" int LLVMFuzzerTestOneInput(uint8_t *buf, size_t len) { + RAND_reset_for_fuzzing(); + + SSL *client = SSL_new(g_state.ctx); + BIO *in = BIO_new(BIO_s_mem()); + BIO *out = BIO_new(BIO_s_mem()); + SSL_set_bio(client, in, out); + SSL_set_connect_state(client); + SSL_set_renegotiate_mode(client, ssl_renegotiate_freely); + + BIO_write(in, buf, len); + if (SSL_do_handshake(client) == 1) { + // Keep reading application data until error or EOF. + uint8_t tmp[1024]; + for (;;) { + if (SSL_read(client, tmp, sizeof(tmp)) <= 0) { + break; + } + } + } + SSL_free(client); + + return 0; +} diff --git a/external/boringssl/fuzz/client_corpus/00717d11ddde89f0895bf72de8de3bf99d1b5c46 b/external/boringssl/fuzz/client_corpus/00717d11ddde89f0895bf72de8de3bf99d1b5c46 new file mode 100644 index 0000000000..27985b43e1 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/00717d11ddde89f0895bf72de8de3bf99d1b5c46 differ diff --git a/external/boringssl/fuzz/client_corpus/008ffccde65bd0671279ec86741c59a52e0dd87c b/external/boringssl/fuzz/client_corpus/008ffccde65bd0671279ec86741c59a52e0dd87c new file mode 100644 index 0000000000..4a6fe54693 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/008ffccde65bd0671279ec86741c59a52e0dd87c differ diff --git a/external/boringssl/fuzz/client_corpus/00a71e9e98b44548faef02dc058b357edeaf6e88 b/external/boringssl/fuzz/client_corpus/00a71e9e98b44548faef02dc058b357edeaf6e88 new file mode 100644 index 0000000000..89a99f0a1d Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/00a71e9e98b44548faef02dc058b357edeaf6e88 differ diff --git a/external/boringssl/fuzz/client_corpus/00a98becb30742ad93ddeb7c851dd34f369d8e86 b/external/boringssl/fuzz/client_corpus/00a98becb30742ad93ddeb7c851dd34f369d8e86 new file mode 100644 index 0000000000..d5bf92f1aa Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/00a98becb30742ad93ddeb7c851dd34f369d8e86 differ diff --git a/external/boringssl/fuzz/client_corpus/01e050c8b311caa72bebb132b9fe98e22ac56682 b/external/boringssl/fuzz/client_corpus/01e050c8b311caa72bebb132b9fe98e22ac56682 new file mode 100644 index 0000000000..ef1c9d4454 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/01e050c8b311caa72bebb132b9fe98e22ac56682 differ diff --git a/external/boringssl/fuzz/client_corpus/02551a10425ba3ad2afdbefb411ff64aba801dee b/external/boringssl/fuzz/client_corpus/02551a10425ba3ad2afdbefb411ff64aba801dee new file mode 100644 index 0000000000..5400898ca3 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/02551a10425ba3ad2afdbefb411ff64aba801dee differ diff --git a/external/boringssl/fuzz/client_corpus/02c7b35834a45ac78a329ee5ed00bb55b2885678 b/external/boringssl/fuzz/client_corpus/02c7b35834a45ac78a329ee5ed00bb55b2885678 new file mode 100644 index 0000000000..55cafe358f Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/02c7b35834a45ac78a329ee5ed00bb55b2885678 differ diff --git a/external/boringssl/fuzz/client_corpus/030f1cffd7e368013256e33ac467b978fbb60d16 b/external/boringssl/fuzz/client_corpus/030f1cffd7e368013256e33ac467b978fbb60d16 new file mode 100644 index 0000000000..fe7e1a82d7 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/030f1cffd7e368013256e33ac467b978fbb60d16 differ diff --git a/external/boringssl/fuzz/client_corpus/031b3b89e72498be49f6cf81c83993686097fba2 b/external/boringssl/fuzz/client_corpus/031b3b89e72498be49f6cf81c83993686097fba2 new file mode 100644 index 0000000000..ed7b708f62 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/031b3b89e72498be49f6cf81c83993686097fba2 differ diff --git a/external/boringssl/fuzz/client_corpus/031f30a25eb84fc9585ffa6d9f8ad2a6910a450b b/external/boringssl/fuzz/client_corpus/031f30a25eb84fc9585ffa6d9f8ad2a6910a450b new file mode 100644 index 0000000000..52c692d9f5 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/031f30a25eb84fc9585ffa6d9f8ad2a6910a450b differ diff --git a/external/boringssl/fuzz/client_corpus/03b58ffa513cd4ada2eab899bf1399530dd1bf05 b/external/boringssl/fuzz/client_corpus/03b58ffa513cd4ada2eab899bf1399530dd1bf05 new file mode 100644 index 0000000000..c77b13d6d2 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/03b58ffa513cd4ada2eab899bf1399530dd1bf05 differ diff --git a/external/boringssl/fuzz/client_corpus/03e3208240d13bdbe7f9c85e49c2059c69b35c45 b/external/boringssl/fuzz/client_corpus/03e3208240d13bdbe7f9c85e49c2059c69b35c45 new file mode 100644 index 0000000000..521b73291f Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/03e3208240d13bdbe7f9c85e49c2059c69b35c45 differ diff --git a/external/boringssl/fuzz/client_corpus/03e6058b6fad092499130b6651f3cdf2a937eec5 b/external/boringssl/fuzz/client_corpus/03e6058b6fad092499130b6651f3cdf2a937eec5 new file mode 100644 index 0000000000..a8b3a5f7cd Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/03e6058b6fad092499130b6651f3cdf2a937eec5 differ diff --git a/external/boringssl/fuzz/client_corpus/03f8d3cd1b55f1b7ef8f9aa635a0890edbd7c263 b/external/boringssl/fuzz/client_corpus/03f8d3cd1b55f1b7ef8f9aa635a0890edbd7c263 new file mode 100644 index 0000000000..6135044c0e Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/03f8d3cd1b55f1b7ef8f9aa635a0890edbd7c263 differ diff --git a/external/boringssl/fuzz/client_corpus/046d8a2ca8e3e68dc1b555e46ac4d4a6d2491982 b/external/boringssl/fuzz/client_corpus/046d8a2ca8e3e68dc1b555e46ac4d4a6d2491982 new file mode 100644 index 0000000000..ea5e280274 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/046d8a2ca8e3e68dc1b555e46ac4d4a6d2491982 differ diff --git a/external/boringssl/fuzz/client_corpus/0513ed635daf437c5a28ca633f74646a61ca6865 b/external/boringssl/fuzz/client_corpus/0513ed635daf437c5a28ca633f74646a61ca6865 new file mode 100644 index 0000000000..edd1c0c1ba Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/0513ed635daf437c5a28ca633f74646a61ca6865 differ diff --git a/external/boringssl/fuzz/client_corpus/051cb5c1e3b99a50ff1a9b76944011402b738083 b/external/boringssl/fuzz/client_corpus/051cb5c1e3b99a50ff1a9b76944011402b738083 new file mode 100644 index 0000000000..f103d21a92 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/051cb5c1e3b99a50ff1a9b76944011402b738083 differ diff --git a/external/boringssl/fuzz/client_corpus/052085640421d4472a5597cc6b4f86104a8c9078 b/external/boringssl/fuzz/client_corpus/052085640421d4472a5597cc6b4f86104a8c9078 new file mode 100644 index 0000000000..be9f2495ed Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/052085640421d4472a5597cc6b4f86104a8c9078 differ diff --git a/external/boringssl/fuzz/client_corpus/0526966b0ebf7fe77e4dee7c39fe7f0741730520 b/external/boringssl/fuzz/client_corpus/0526966b0ebf7fe77e4dee7c39fe7f0741730520 new file mode 100644 index 0000000000..4951427b82 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/0526966b0ebf7fe77e4dee7c39fe7f0741730520 differ diff --git a/external/boringssl/fuzz/client_corpus/05580dbaccccb94d23cbfc8bab5a1d299ebe79ee b/external/boringssl/fuzz/client_corpus/05580dbaccccb94d23cbfc8bab5a1d299ebe79ee new file mode 100644 index 0000000000..2efe81c298 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/05580dbaccccb94d23cbfc8bab5a1d299ebe79ee differ diff --git a/external/boringssl/fuzz/client_corpus/05a05196a8e0958f1ba744d122208d337a8696fa b/external/boringssl/fuzz/client_corpus/05a05196a8e0958f1ba744d122208d337a8696fa new file mode 100644 index 0000000000..eadbb9c0dd Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/05a05196a8e0958f1ba744d122208d337a8696fa differ diff --git a/external/boringssl/fuzz/client_corpus/05eb6bb7db04c88f052471a36c9937431f2e51a8 b/external/boringssl/fuzz/client_corpus/05eb6bb7db04c88f052471a36c9937431f2e51a8 new file mode 100644 index 0000000000..c6971e1a1a Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/05eb6bb7db04c88f052471a36c9937431f2e51a8 differ diff --git a/external/boringssl/fuzz/client_corpus/063c1c4256bb77dcd3abaac0dbe28071bd749343 b/external/boringssl/fuzz/client_corpus/063c1c4256bb77dcd3abaac0dbe28071bd749343 new file mode 100644 index 0000000000..51d5338368 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/063c1c4256bb77dcd3abaac0dbe28071bd749343 differ diff --git a/external/boringssl/fuzz/client_corpus/06e7df8edebe9b55ffe0279cc19b46b88ae76aa6 b/external/boringssl/fuzz/client_corpus/06e7df8edebe9b55ffe0279cc19b46b88ae76aa6 new file mode 100644 index 0000000000..8a1f12b9c0 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/06e7df8edebe9b55ffe0279cc19b46b88ae76aa6 differ diff --git a/external/boringssl/fuzz/client_corpus/06fa70728c05d229e2dfa67ff3f0172feae65ff3 b/external/boringssl/fuzz/client_corpus/06fa70728c05d229e2dfa67ff3f0172feae65ff3 new file mode 100644 index 0000000000..647756f31c Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/06fa70728c05d229e2dfa67ff3f0172feae65ff3 differ diff --git a/external/boringssl/fuzz/client_corpus/07559907aedb2924c0084232c2a50ce815443f0d b/external/boringssl/fuzz/client_corpus/07559907aedb2924c0084232c2a50ce815443f0d new file mode 100644 index 0000000000..aa41f6618e Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/07559907aedb2924c0084232c2a50ce815443f0d differ diff --git a/external/boringssl/fuzz/client_corpus/075c12272d2e7c3b9dacac07ea89f69c76d8968f b/external/boringssl/fuzz/client_corpus/075c12272d2e7c3b9dacac07ea89f69c76d8968f new file mode 100644 index 0000000000..24be586dfa Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/075c12272d2e7c3b9dacac07ea89f69c76d8968f differ diff --git a/external/boringssl/fuzz/client_corpus/07e4a83c3949fcf90947bdcb7b9f97b0d09cfc85 b/external/boringssl/fuzz/client_corpus/07e4a83c3949fcf90947bdcb7b9f97b0d09cfc85 new file mode 100644 index 0000000000..f5fb6cc45e Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/07e4a83c3949fcf90947bdcb7b9f97b0d09cfc85 differ diff --git a/external/boringssl/fuzz/client_corpus/083018618734196e3979d96b571e627909d8be0a b/external/boringssl/fuzz/client_corpus/083018618734196e3979d96b571e627909d8be0a new file mode 100644 index 0000000000..864cb3e3ab Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/083018618734196e3979d96b571e627909d8be0a differ diff --git a/external/boringssl/fuzz/client_corpus/08310c6bd2fd887cf1f5933965c9321bc3a96b35 b/external/boringssl/fuzz/client_corpus/08310c6bd2fd887cf1f5933965c9321bc3a96b35 new file mode 100644 index 0000000000..6fe60e8fa5 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/08310c6bd2fd887cf1f5933965c9321bc3a96b35 differ diff --git a/external/boringssl/fuzz/client_corpus/08719b765365d265aae6a3ca7e5cc45e92e4c740 b/external/boringssl/fuzz/client_corpus/08719b765365d265aae6a3ca7e5cc45e92e4c740 new file mode 100644 index 0000000000..64f5a9c559 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/08719b765365d265aae6a3ca7e5cc45e92e4c740 differ diff --git a/external/boringssl/fuzz/client_corpus/089063763289688a92b523abe0b21dde1dcb5903 b/external/boringssl/fuzz/client_corpus/089063763289688a92b523abe0b21dde1dcb5903 new file mode 100644 index 0000000000..5e3ca1149a Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/089063763289688a92b523abe0b21dde1dcb5903 differ diff --git a/external/boringssl/fuzz/client_corpus/09225c1125fed526539a962ff46972676518fa34 b/external/boringssl/fuzz/client_corpus/09225c1125fed526539a962ff46972676518fa34 new file mode 100644 index 0000000000..2efb6c7763 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/09225c1125fed526539a962ff46972676518fa34 differ diff --git a/external/boringssl/fuzz/client_corpus/09a8967150d2ecb7b2adb5cfacf86e754274a145 b/external/boringssl/fuzz/client_corpus/09a8967150d2ecb7b2adb5cfacf86e754274a145 new file mode 100644 index 0000000000..50b56d3d90 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/09a8967150d2ecb7b2adb5cfacf86e754274a145 differ diff --git a/external/boringssl/fuzz/client_corpus/09ea428e385f7cedefdd33c6e46ded0c26eca099 b/external/boringssl/fuzz/client_corpus/09ea428e385f7cedefdd33c6e46ded0c26eca099 new file mode 100644 index 0000000000..53a2c26ff2 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/09ea428e385f7cedefdd33c6e46ded0c26eca099 differ diff --git a/external/boringssl/fuzz/client_corpus/0a3cb64ca50c3eddeb4f38d82bb300896ce258d5 b/external/boringssl/fuzz/client_corpus/0a3cb64ca50c3eddeb4f38d82bb300896ce258d5 new file mode 100644 index 0000000000..acf76c6607 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/0a3cb64ca50c3eddeb4f38d82bb300896ce258d5 differ diff --git a/external/boringssl/fuzz/client_corpus/0a44610c64874e172780e8e51b10031b0a2a4103 b/external/boringssl/fuzz/client_corpus/0a44610c64874e172780e8e51b10031b0a2a4103 new file mode 100644 index 0000000000..b0bc2c56b7 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/0a44610c64874e172780e8e51b10031b0a2a4103 differ diff --git a/external/boringssl/fuzz/client_corpus/0a7fc3b19f7aa0892008f89d2540cfd652d924a0 b/external/boringssl/fuzz/client_corpus/0a7fc3b19f7aa0892008f89d2540cfd652d924a0 new file mode 100644 index 0000000000..7eb67c19ef Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/0a7fc3b19f7aa0892008f89d2540cfd652d924a0 differ diff --git a/external/boringssl/fuzz/client_corpus/0b1614426dcada7c22eae8bde20c9ea1955af192 b/external/boringssl/fuzz/client_corpus/0b1614426dcada7c22eae8bde20c9ea1955af192 new file mode 100644 index 0000000000..970edff374 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/0b1614426dcada7c22eae8bde20c9ea1955af192 differ diff --git a/external/boringssl/fuzz/client_corpus/0b251113d82bdc624c418ca3e9a822af3f43f4bc b/external/boringssl/fuzz/client_corpus/0b251113d82bdc624c418ca3e9a822af3f43f4bc new file mode 100644 index 0000000000..57c31c337f Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/0b251113d82bdc624c418ca3e9a822af3f43f4bc differ diff --git a/external/boringssl/fuzz/client_corpus/0b393412092142d934bd3021e9ab95fa9c433de2 b/external/boringssl/fuzz/client_corpus/0b393412092142d934bd3021e9ab95fa9c433de2 new file mode 100644 index 0000000000..a290f8a1d4 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/0b393412092142d934bd3021e9ab95fa9c433de2 differ diff --git a/external/boringssl/fuzz/client_corpus/0ca74dfc9546ed626a103ffece16d214b0b4629d b/external/boringssl/fuzz/client_corpus/0ca74dfc9546ed626a103ffece16d214b0b4629d new file mode 100644 index 0000000000..d109fdd5f1 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/0ca74dfc9546ed626a103ffece16d214b0b4629d differ diff --git a/external/boringssl/fuzz/client_corpus/0d860a629f778931860041c502a048b562c5b929 b/external/boringssl/fuzz/client_corpus/0d860a629f778931860041c502a048b562c5b929 new file mode 100644 index 0000000000..0060faa806 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/0d860a629f778931860041c502a048b562c5b929 differ diff --git a/external/boringssl/fuzz/client_corpus/0d9891ca130cb689545acefd20ccc979e4b53f27 b/external/boringssl/fuzz/client_corpus/0d9891ca130cb689545acefd20ccc979e4b53f27 new file mode 100644 index 0000000000..72b85bc14b Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/0d9891ca130cb689545acefd20ccc979e4b53f27 differ diff --git a/external/boringssl/fuzz/client_corpus/0ee7921127cd9571a51441816b048a4f340ac51d b/external/boringssl/fuzz/client_corpus/0ee7921127cd9571a51441816b048a4f340ac51d new file mode 100644 index 0000000000..2de58f60cd Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/0ee7921127cd9571a51441816b048a4f340ac51d differ diff --git a/external/boringssl/fuzz/client_corpus/0f14ae60b90b40bee0fec50ab06886127a245c28 b/external/boringssl/fuzz/client_corpus/0f14ae60b90b40bee0fec50ab06886127a245c28 new file mode 100644 index 0000000000..c75297dbfc Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/0f14ae60b90b40bee0fec50ab06886127a245c28 differ diff --git a/external/boringssl/fuzz/client_corpus/0f7df9d0bc3a0978204d37dc4c74034e32438d9f b/external/boringssl/fuzz/client_corpus/0f7df9d0bc3a0978204d37dc4c74034e32438d9f new file mode 100644 index 0000000000..33907868cc Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/0f7df9d0bc3a0978204d37dc4c74034e32438d9f differ diff --git a/external/boringssl/fuzz/client_corpus/0fd8481bfc9ea37bbd7fc33dce344bca965b04ad b/external/boringssl/fuzz/client_corpus/0fd8481bfc9ea37bbd7fc33dce344bca965b04ad new file mode 100644 index 0000000000..ced45d0bed Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/0fd8481bfc9ea37bbd7fc33dce344bca965b04ad differ diff --git a/external/boringssl/fuzz/client_corpus/1018b39874ea33fd123605bffa8986270e6ba538 b/external/boringssl/fuzz/client_corpus/1018b39874ea33fd123605bffa8986270e6ba538 new file mode 100644 index 0000000000..0b10f6352a Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/1018b39874ea33fd123605bffa8986270e6ba538 differ diff --git a/external/boringssl/fuzz/client_corpus/10b4b91e0940fcfaa7a4f0959f2079ed70ae7370 b/external/boringssl/fuzz/client_corpus/10b4b91e0940fcfaa7a4f0959f2079ed70ae7370 new file mode 100644 index 0000000000..75defd2f45 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/10b4b91e0940fcfaa7a4f0959f2079ed70ae7370 differ diff --git a/external/boringssl/fuzz/client_corpus/10d8e6931cf75e896c8a6ec1081df869e30310e1 b/external/boringssl/fuzz/client_corpus/10d8e6931cf75e896c8a6ec1081df869e30310e1 new file mode 100644 index 0000000000..f74f09af0b Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/10d8e6931cf75e896c8a6ec1081df869e30310e1 differ diff --git a/external/boringssl/fuzz/client_corpus/111bb472fcf4fc134af5ec3c189f43ef9ef19b36 b/external/boringssl/fuzz/client_corpus/111bb472fcf4fc134af5ec3c189f43ef9ef19b36 new file mode 100644 index 0000000000..92f5146963 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/111bb472fcf4fc134af5ec3c189f43ef9ef19b36 differ diff --git a/external/boringssl/fuzz/client_corpus/1175419b73c59b028cb36d263fe31dddff6ed54d b/external/boringssl/fuzz/client_corpus/1175419b73c59b028cb36d263fe31dddff6ed54d new file mode 100644 index 0000000000..d025cfe86d Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/1175419b73c59b028cb36d263fe31dddff6ed54d differ diff --git a/external/boringssl/fuzz/client_corpus/117e20e32c26799a3228a2b1fa2cbe39c8440720 b/external/boringssl/fuzz/client_corpus/117e20e32c26799a3228a2b1fa2cbe39c8440720 new file mode 100644 index 0000000000..4be2e154d5 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/117e20e32c26799a3228a2b1fa2cbe39c8440720 differ diff --git a/external/boringssl/fuzz/client_corpus/119735b91048ae492dfb7459aaa01d7fe13c767d b/external/boringssl/fuzz/client_corpus/119735b91048ae492dfb7459aaa01d7fe13c767d new file mode 100644 index 0000000000..5fd89383a1 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/119735b91048ae492dfb7459aaa01d7fe13c767d differ diff --git a/external/boringssl/fuzz/client_corpus/11a132d5dd71f67c2386cd2f6a5a256572423c8f b/external/boringssl/fuzz/client_corpus/11a132d5dd71f67c2386cd2f6a5a256572423c8f new file mode 100644 index 0000000000..51b2dd8b8b Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/11a132d5dd71f67c2386cd2f6a5a256572423c8f differ diff --git a/external/boringssl/fuzz/client_corpus/11d92649d0dd312e6328dd34231e4bc56ee7cfb8 b/external/boringssl/fuzz/client_corpus/11d92649d0dd312e6328dd34231e4bc56ee7cfb8 new file mode 100644 index 0000000000..d9c9522ef8 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/11d92649d0dd312e6328dd34231e4bc56ee7cfb8 differ diff --git a/external/boringssl/fuzz/client_corpus/11da8204a79299f2855dbeddff540442ac33ed4a b/external/boringssl/fuzz/client_corpus/11da8204a79299f2855dbeddff540442ac33ed4a new file mode 100644 index 0000000000..6ae89b13b8 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/11da8204a79299f2855dbeddff540442ac33ed4a differ diff --git a/external/boringssl/fuzz/client_corpus/125a95886e4a7240566a17221a4453078a659d1b b/external/boringssl/fuzz/client_corpus/125a95886e4a7240566a17221a4453078a659d1b new file mode 100644 index 0000000000..f076b10825 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/125a95886e4a7240566a17221a4453078a659d1b differ diff --git a/external/boringssl/fuzz/client_corpus/12852dc6e23d0eb6dffa19470b4d44f0105d6a5e b/external/boringssl/fuzz/client_corpus/12852dc6e23d0eb6dffa19470b4d44f0105d6a5e new file mode 100644 index 0000000000..f1b28e0c8b Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/12852dc6e23d0eb6dffa19470b4d44f0105d6a5e differ diff --git a/external/boringssl/fuzz/client_corpus/129f293ffb471c54f0a65ebe68e8c03ae20edc63 b/external/boringssl/fuzz/client_corpus/129f293ffb471c54f0a65ebe68e8c03ae20edc63 new file mode 100644 index 0000000000..9edb0d7eb3 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/129f293ffb471c54f0a65ebe68e8c03ae20edc63 differ diff --git a/external/boringssl/fuzz/client_corpus/12a16512ec0e3937654b4d283d70c7506cbeffbb b/external/boringssl/fuzz/client_corpus/12a16512ec0e3937654b4d283d70c7506cbeffbb new file mode 100644 index 0000000000..47db6941a1 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/12a16512ec0e3937654b4d283d70c7506cbeffbb differ diff --git a/external/boringssl/fuzz/client_corpus/12b0df532889077124403153935a3d4902a6268d b/external/boringssl/fuzz/client_corpus/12b0df532889077124403153935a3d4902a6268d new file mode 100644 index 0000000000..3e33a968bf Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/12b0df532889077124403153935a3d4902a6268d differ diff --git a/external/boringssl/fuzz/client_corpus/1364b4aa04c2515df069617f9de27a1311e5b526 b/external/boringssl/fuzz/client_corpus/1364b4aa04c2515df069617f9de27a1311e5b526 new file mode 100644 index 0000000000..128abcce84 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/1364b4aa04c2515df069617f9de27a1311e5b526 differ diff --git a/external/boringssl/fuzz/client_corpus/13e9182cb5db0720afec91acafe85fe3bac18d49 b/external/boringssl/fuzz/client_corpus/13e9182cb5db0720afec91acafe85fe3bac18d49 new file mode 100644 index 0000000000..85c35f807e Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/13e9182cb5db0720afec91acafe85fe3bac18d49 differ diff --git a/external/boringssl/fuzz/client_corpus/1413c7537c6e54d1c9e36d5559eee4c6f4bebe36 b/external/boringssl/fuzz/client_corpus/1413c7537c6e54d1c9e36d5559eee4c6f4bebe36 new file mode 100644 index 0000000000..a0a999f797 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/1413c7537c6e54d1c9e36d5559eee4c6f4bebe36 differ diff --git a/external/boringssl/fuzz/client_corpus/143cce6709b4f9760b89dc6920b427e2628db95e b/external/boringssl/fuzz/client_corpus/143cce6709b4f9760b89dc6920b427e2628db95e new file mode 100644 index 0000000000..e72dd64e62 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/143cce6709b4f9760b89dc6920b427e2628db95e differ diff --git a/external/boringssl/fuzz/client_corpus/14c3e63325718a0374c028dcd127d952bd5e063b b/external/boringssl/fuzz/client_corpus/14c3e63325718a0374c028dcd127d952bd5e063b new file mode 100644 index 0000000000..2ccc8c2c0b Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/14c3e63325718a0374c028dcd127d952bd5e063b differ diff --git a/external/boringssl/fuzz/client_corpus/15a54d5f346c2fd9fa3da6f73cee5db2c7952f68 b/external/boringssl/fuzz/client_corpus/15a54d5f346c2fd9fa3da6f73cee5db2c7952f68 new file mode 100644 index 0000000000..ba8f4852db Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/15a54d5f346c2fd9fa3da6f73cee5db2c7952f68 differ diff --git a/external/boringssl/fuzz/client_corpus/15bbaf9e1cd7992a03fb9e365ef92f02c0d17bb6 b/external/boringssl/fuzz/client_corpus/15bbaf9e1cd7992a03fb9e365ef92f02c0d17bb6 new file mode 100644 index 0000000000..f7daa4e52f Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/15bbaf9e1cd7992a03fb9e365ef92f02c0d17bb6 differ diff --git a/external/boringssl/fuzz/client_corpus/1617afc9570c0c60a70fc6c93313203df55e35f9 b/external/boringssl/fuzz/client_corpus/1617afc9570c0c60a70fc6c93313203df55e35f9 new file mode 100644 index 0000000000..d39abf0559 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/1617afc9570c0c60a70fc6c93313203df55e35f9 differ diff --git a/external/boringssl/fuzz/client_corpus/1635f341671bca1a04ff2a13c8c3c54f914288bf b/external/boringssl/fuzz/client_corpus/1635f341671bca1a04ff2a13c8c3c54f914288bf new file mode 100644 index 0000000000..d868278252 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/1635f341671bca1a04ff2a13c8c3c54f914288bf differ diff --git a/external/boringssl/fuzz/client_corpus/16673ecbbfa4b6a7e0246386e0ee2785515ecf0d b/external/boringssl/fuzz/client_corpus/16673ecbbfa4b6a7e0246386e0ee2785515ecf0d new file mode 100644 index 0000000000..07dfc9cf16 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/16673ecbbfa4b6a7e0246386e0ee2785515ecf0d differ diff --git a/external/boringssl/fuzz/client_corpus/169f2b81de0de2a0d403d21ca7f9ed0da77eb644 b/external/boringssl/fuzz/client_corpus/169f2b81de0de2a0d403d21ca7f9ed0da77eb644 new file mode 100644 index 0000000000..9292a8c2da Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/169f2b81de0de2a0d403d21ca7f9ed0da77eb644 differ diff --git a/external/boringssl/fuzz/client_corpus/16dc8080d01278cfb39ee1c6836fe9d3b7e55436 b/external/boringssl/fuzz/client_corpus/16dc8080d01278cfb39ee1c6836fe9d3b7e55436 new file mode 100644 index 0000000000..58b828881e Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/16dc8080d01278cfb39ee1c6836fe9d3b7e55436 differ diff --git a/external/boringssl/fuzz/client_corpus/1701cb50412ff3dd90f63cc9380bdf9421a9b8c7 b/external/boringssl/fuzz/client_corpus/1701cb50412ff3dd90f63cc9380bdf9421a9b8c7 new file mode 100644 index 0000000000..2aa9ea7c89 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/1701cb50412ff3dd90f63cc9380bdf9421a9b8c7 differ diff --git a/external/boringssl/fuzz/client_corpus/1731d4b7ac9ea64d9e0f7852ca94e7a6382a7f5a b/external/boringssl/fuzz/client_corpus/1731d4b7ac9ea64d9e0f7852ca94e7a6382a7f5a new file mode 100644 index 0000000000..2690f7dc60 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/1731d4b7ac9ea64d9e0f7852ca94e7a6382a7f5a differ diff --git a/external/boringssl/fuzz/client_corpus/1737b38dda86f8045b2ec419664c9cba31d02801 b/external/boringssl/fuzz/client_corpus/1737b38dda86f8045b2ec419664c9cba31d02801 new file mode 100644 index 0000000000..f027ddcea4 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/1737b38dda86f8045b2ec419664c9cba31d02801 differ diff --git a/external/boringssl/fuzz/client_corpus/175b59e886da4e09ecac6c84b39a6f30b37c6dec b/external/boringssl/fuzz/client_corpus/175b59e886da4e09ecac6c84b39a6f30b37c6dec new file mode 100644 index 0000000000..cc798deac9 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/175b59e886da4e09ecac6c84b39a6f30b37c6dec differ diff --git a/external/boringssl/fuzz/client_corpus/1825f52717650a3fac3cd62f5250255a83b9f4ae b/external/boringssl/fuzz/client_corpus/1825f52717650a3fac3cd62f5250255a83b9f4ae new file mode 100644 index 0000000000..611f0d9777 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/1825f52717650a3fac3cd62f5250255a83b9f4ae differ diff --git a/external/boringssl/fuzz/client_corpus/1856b18ba40b75802c03e5216393950a32cdbc6d b/external/boringssl/fuzz/client_corpus/1856b18ba40b75802c03e5216393950a32cdbc6d new file mode 100644 index 0000000000..cf4af918f1 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/1856b18ba40b75802c03e5216393950a32cdbc6d differ diff --git a/external/boringssl/fuzz/client_corpus/185e35d9e0d325e70f58efa24fbee9f4edce6c1d b/external/boringssl/fuzz/client_corpus/185e35d9e0d325e70f58efa24fbee9f4edce6c1d new file mode 100644 index 0000000000..de83ccce75 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/185e35d9e0d325e70f58efa24fbee9f4edce6c1d differ diff --git a/external/boringssl/fuzz/client_corpus/189eec7d1e6d85b7cbc91c0320ea8643426e3ccd b/external/boringssl/fuzz/client_corpus/189eec7d1e6d85b7cbc91c0320ea8643426e3ccd new file mode 100644 index 0000000000..5e50ad6c7b Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/189eec7d1e6d85b7cbc91c0320ea8643426e3ccd differ diff --git a/external/boringssl/fuzz/client_corpus/193183a77f39a2ee7a54d2cd86191fcbde1c5924 b/external/boringssl/fuzz/client_corpus/193183a77f39a2ee7a54d2cd86191fcbde1c5924 new file mode 100644 index 0000000000..672f94908f Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/193183a77f39a2ee7a54d2cd86191fcbde1c5924 differ diff --git a/external/boringssl/fuzz/client_corpus/19d0710b2aeacf4904cebbc1b304cbf02bad0d7f b/external/boringssl/fuzz/client_corpus/19d0710b2aeacf4904cebbc1b304cbf02bad0d7f new file mode 100644 index 0000000000..6712ba92a1 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/19d0710b2aeacf4904cebbc1b304cbf02bad0d7f differ diff --git a/external/boringssl/fuzz/client_corpus/1a024dc9c5d74085b76f8cad6600f4edc350b956 b/external/boringssl/fuzz/client_corpus/1a024dc9c5d74085b76f8cad6600f4edc350b956 new file mode 100644 index 0000000000..0fc9d66f3d Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/1a024dc9c5d74085b76f8cad6600f4edc350b956 differ diff --git a/external/boringssl/fuzz/client_corpus/1b21a6e6a2f9b34a8ce85f0adea54578b58d48b2 b/external/boringssl/fuzz/client_corpus/1b21a6e6a2f9b34a8ce85f0adea54578b58d48b2 new file mode 100644 index 0000000000..d409c0397e Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/1b21a6e6a2f9b34a8ce85f0adea54578b58d48b2 differ diff --git a/external/boringssl/fuzz/client_corpus/1b2437add9137fd1392126d2535573a016628d38 b/external/boringssl/fuzz/client_corpus/1b2437add9137fd1392126d2535573a016628d38 new file mode 100644 index 0000000000..abe97d0b2f Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/1b2437add9137fd1392126d2535573a016628d38 differ diff --git a/external/boringssl/fuzz/client_corpus/1c7a97739e894d39ece462a80f4039f3c778a3ef b/external/boringssl/fuzz/client_corpus/1c7a97739e894d39ece462a80f4039f3c778a3ef new file mode 100644 index 0000000000..73807d10ed Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/1c7a97739e894d39ece462a80f4039f3c778a3ef differ diff --git a/external/boringssl/fuzz/client_corpus/1cac14fadaa7ae3640dd3916f3c78e3544afd00b b/external/boringssl/fuzz/client_corpus/1cac14fadaa7ae3640dd3916f3c78e3544afd00b new file mode 100644 index 0000000000..0da10a93ff Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/1cac14fadaa7ae3640dd3916f3c78e3544afd00b differ diff --git a/external/boringssl/fuzz/client_corpus/1ce3af082176f17eae5a3987ea9a131c74da45e6 b/external/boringssl/fuzz/client_corpus/1ce3af082176f17eae5a3987ea9a131c74da45e6 new file mode 100644 index 0000000000..c2e4bdee9f Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/1ce3af082176f17eae5a3987ea9a131c74da45e6 differ diff --git a/external/boringssl/fuzz/client_corpus/1d103883a36101f8f67fd0eda2273177bd979069 b/external/boringssl/fuzz/client_corpus/1d103883a36101f8f67fd0eda2273177bd979069 new file mode 100644 index 0000000000..6f5d62dc26 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/1d103883a36101f8f67fd0eda2273177bd979069 differ diff --git a/external/boringssl/fuzz/client_corpus/1dba9107853637cddf377a6a07ca87c1e4cd18f2 b/external/boringssl/fuzz/client_corpus/1dba9107853637cddf377a6a07ca87c1e4cd18f2 new file mode 100644 index 0000000000..991584eb5d Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/1dba9107853637cddf377a6a07ca87c1e4cd18f2 differ diff --git a/external/boringssl/fuzz/client_corpus/1e58390b95aa6e729013cd5ec6f67fd9410fe507 b/external/boringssl/fuzz/client_corpus/1e58390b95aa6e729013cd5ec6f67fd9410fe507 new file mode 100644 index 0000000000..640ac65dba Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/1e58390b95aa6e729013cd5ec6f67fd9410fe507 differ diff --git a/external/boringssl/fuzz/client_corpus/1eeae24b70a330001a18cb1d7b3e6358b34fddd7 b/external/boringssl/fuzz/client_corpus/1eeae24b70a330001a18cb1d7b3e6358b34fddd7 new file mode 100644 index 0000000000..2300c5f1ee Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/1eeae24b70a330001a18cb1d7b3e6358b34fddd7 differ diff --git a/external/boringssl/fuzz/client_corpus/1efe14c5799b31f2dc4c413643235c9ec5086e06 b/external/boringssl/fuzz/client_corpus/1efe14c5799b31f2dc4c413643235c9ec5086e06 new file mode 100644 index 0000000000..9c181bd9c4 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/1efe14c5799b31f2dc4c413643235c9ec5086e06 differ diff --git a/external/boringssl/fuzz/client_corpus/1f93a5e95e85c6a649ca7ed71d349ca6e04a6d92 b/external/boringssl/fuzz/client_corpus/1f93a5e95e85c6a649ca7ed71d349ca6e04a6d92 new file mode 100644 index 0000000000..f5b701c864 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/1f93a5e95e85c6a649ca7ed71d349ca6e04a6d92 differ diff --git a/external/boringssl/fuzz/client_corpus/207778a53046b0f733160d96fc0e0a5f9d9f55da b/external/boringssl/fuzz/client_corpus/207778a53046b0f733160d96fc0e0a5f9d9f55da new file mode 100644 index 0000000000..4bd5216b15 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/207778a53046b0f733160d96fc0e0a5f9d9f55da differ diff --git a/external/boringssl/fuzz/client_corpus/209164c30c53ba6c97e2bf6f767310e540f335ff b/external/boringssl/fuzz/client_corpus/209164c30c53ba6c97e2bf6f767310e540f335ff new file mode 100644 index 0000000000..4b37c8b46e Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/209164c30c53ba6c97e2bf6f767310e540f335ff differ diff --git a/external/boringssl/fuzz/client_corpus/20f99df931bffe2e70b4114d50250cfa8c32ff94 b/external/boringssl/fuzz/client_corpus/20f99df931bffe2e70b4114d50250cfa8c32ff94 new file mode 100644 index 0000000000..0abb5e715e Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/20f99df931bffe2e70b4114d50250cfa8c32ff94 differ diff --git a/external/boringssl/fuzz/client_corpus/212a56ac6a79d534cdf75292a9e9cd4b7c98ff9b b/external/boringssl/fuzz/client_corpus/212a56ac6a79d534cdf75292a9e9cd4b7c98ff9b new file mode 100644 index 0000000000..36cbefd875 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/212a56ac6a79d534cdf75292a9e9cd4b7c98ff9b differ diff --git a/external/boringssl/fuzz/client_corpus/212aefea1187a824be184640c2c673c5b85fb6e4 b/external/boringssl/fuzz/client_corpus/212aefea1187a824be184640c2c673c5b85fb6e4 new file mode 100644 index 0000000000..64043d3eee Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/212aefea1187a824be184640c2c673c5b85fb6e4 differ diff --git a/external/boringssl/fuzz/client_corpus/21928dcf456992eb55399cd77f741a332978d73a b/external/boringssl/fuzz/client_corpus/21928dcf456992eb55399cd77f741a332978d73a new file mode 100644 index 0000000000..37070b9253 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/21928dcf456992eb55399cd77f741a332978d73a differ diff --git a/external/boringssl/fuzz/client_corpus/22363c659b583272354f371c4d0107a0d2aff819 b/external/boringssl/fuzz/client_corpus/22363c659b583272354f371c4d0107a0d2aff819 new file mode 100644 index 0000000000..5c16ae2267 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/22363c659b583272354f371c4d0107a0d2aff819 differ diff --git a/external/boringssl/fuzz/client_corpus/223d182dd2661a4ce650c9cff7f0dea8582b647d b/external/boringssl/fuzz/client_corpus/223d182dd2661a4ce650c9cff7f0dea8582b647d new file mode 100644 index 0000000000..1975f77449 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/223d182dd2661a4ce650c9cff7f0dea8582b647d differ diff --git a/external/boringssl/fuzz/client_corpus/2254a23660bd2a0ff02c837c37a270e59a460de7 b/external/boringssl/fuzz/client_corpus/2254a23660bd2a0ff02c837c37a270e59a460de7 new file mode 100644 index 0000000000..c704d4d155 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/2254a23660bd2a0ff02c837c37a270e59a460de7 differ diff --git a/external/boringssl/fuzz/client_corpus/22721e338dad9836a391790ee54b4de0cbe00c89 b/external/boringssl/fuzz/client_corpus/22721e338dad9836a391790ee54b4de0cbe00c89 new file mode 100644 index 0000000000..55cd68d3a6 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/22721e338dad9836a391790ee54b4de0cbe00c89 differ diff --git a/external/boringssl/fuzz/client_corpus/227d4ae9ca9f113f16b84ab497ca26db8fc5ce92 b/external/boringssl/fuzz/client_corpus/227d4ae9ca9f113f16b84ab497ca26db8fc5ce92 new file mode 100644 index 0000000000..c90db251d1 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/227d4ae9ca9f113f16b84ab497ca26db8fc5ce92 differ diff --git a/external/boringssl/fuzz/client_corpus/234ff4cbcd44f84d9dc948795ee60452a0693625 b/external/boringssl/fuzz/client_corpus/234ff4cbcd44f84d9dc948795ee60452a0693625 new file mode 100644 index 0000000000..6ffed455d9 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/234ff4cbcd44f84d9dc948795ee60452a0693625 differ diff --git a/external/boringssl/fuzz/client_corpus/237565819ea32ff3cbad0947bbf63311e1b9a560 b/external/boringssl/fuzz/client_corpus/237565819ea32ff3cbad0947bbf63311e1b9a560 new file mode 100644 index 0000000000..2119201af3 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/237565819ea32ff3cbad0947bbf63311e1b9a560 differ diff --git a/external/boringssl/fuzz/client_corpus/23af7fe04a1105a294ba962383a1a90895f23e0b b/external/boringssl/fuzz/client_corpus/23af7fe04a1105a294ba962383a1a90895f23e0b new file mode 100644 index 0000000000..8fa6aa37e8 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/23af7fe04a1105a294ba962383a1a90895f23e0b differ diff --git a/external/boringssl/fuzz/client_corpus/2465ecbfe1070f98fd88ca6158eb3014a19e01dc b/external/boringssl/fuzz/client_corpus/2465ecbfe1070f98fd88ca6158eb3014a19e01dc new file mode 100644 index 0000000000..23c0f16f33 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/2465ecbfe1070f98fd88ca6158eb3014a19e01dc differ diff --git a/external/boringssl/fuzz/client_corpus/24f2ed7e40f94ef359aa05060ee1d13ca5a26740 b/external/boringssl/fuzz/client_corpus/24f2ed7e40f94ef359aa05060ee1d13ca5a26740 new file mode 100644 index 0000000000..6d4a24e8c5 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/24f2ed7e40f94ef359aa05060ee1d13ca5a26740 differ diff --git a/external/boringssl/fuzz/client_corpus/252954f3b81c2bf8a67fcfe0e3c1647f60993be4 b/external/boringssl/fuzz/client_corpus/252954f3b81c2bf8a67fcfe0e3c1647f60993be4 new file mode 100644 index 0000000000..d20ae105c9 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/252954f3b81c2bf8a67fcfe0e3c1647f60993be4 differ diff --git a/external/boringssl/fuzz/client_corpus/252a34182e0b4b0f44f41e82de867242bdccea79 b/external/boringssl/fuzz/client_corpus/252a34182e0b4b0f44f41e82de867242bdccea79 new file mode 100644 index 0000000000..65d93c030e Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/252a34182e0b4b0f44f41e82de867242bdccea79 differ diff --git a/external/boringssl/fuzz/client_corpus/259e1c5b762116d55e5369ac45c611ee06f873da b/external/boringssl/fuzz/client_corpus/259e1c5b762116d55e5369ac45c611ee06f873da new file mode 100644 index 0000000000..15f23cd6ce Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/259e1c5b762116d55e5369ac45c611ee06f873da differ diff --git a/external/boringssl/fuzz/client_corpus/262cc348aa328fa0e256c1ee38a13bf32be45080 b/external/boringssl/fuzz/client_corpus/262cc348aa328fa0e256c1ee38a13bf32be45080 new file mode 100644 index 0000000000..adb0146fa4 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/262cc348aa328fa0e256c1ee38a13bf32be45080 differ diff --git a/external/boringssl/fuzz/client_corpus/2640d5ce7a30e232909199583946b0d0e93639b9 b/external/boringssl/fuzz/client_corpus/2640d5ce7a30e232909199583946b0d0e93639b9 new file mode 100644 index 0000000000..e7bb434476 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/2640d5ce7a30e232909199583946b0d0e93639b9 differ diff --git a/external/boringssl/fuzz/client_corpus/265cf9b5e8b582233ee53de117a953ec586a129e b/external/boringssl/fuzz/client_corpus/265cf9b5e8b582233ee53de117a953ec586a129e new file mode 100644 index 0000000000..9d63d2f46f Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/265cf9b5e8b582233ee53de117a953ec586a129e differ diff --git a/external/boringssl/fuzz/client_corpus/2751bd28914df3bc80eabdf0a1722c01a9d9a0bb b/external/boringssl/fuzz/client_corpus/2751bd28914df3bc80eabdf0a1722c01a9d9a0bb new file mode 100644 index 0000000000..d1440b2733 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/2751bd28914df3bc80eabdf0a1722c01a9d9a0bb differ diff --git a/external/boringssl/fuzz/client_corpus/28459cfb1e5a27160fc0a2337bae96c1c7c0296d b/external/boringssl/fuzz/client_corpus/28459cfb1e5a27160fc0a2337bae96c1c7c0296d new file mode 100644 index 0000000000..8981ff1343 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/28459cfb1e5a27160fc0a2337bae96c1c7c0296d differ diff --git a/external/boringssl/fuzz/client_corpus/28a6cbd11ae657e98ef2536fbdd66a5ba44ecdc2 b/external/boringssl/fuzz/client_corpus/28a6cbd11ae657e98ef2536fbdd66a5ba44ecdc2 new file mode 100644 index 0000000000..7d95076e31 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/28a6cbd11ae657e98ef2536fbdd66a5ba44ecdc2 differ diff --git a/external/boringssl/fuzz/client_corpus/28bb46d65faf3a8d3e112d25e7937e15571277e1 b/external/boringssl/fuzz/client_corpus/28bb46d65faf3a8d3e112d25e7937e15571277e1 new file mode 100644 index 0000000000..4ecead8a9e Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/28bb46d65faf3a8d3e112d25e7937e15571277e1 differ diff --git a/external/boringssl/fuzz/client_corpus/294892eee3e322937e5c48a692c1a80f512f86a7 b/external/boringssl/fuzz/client_corpus/294892eee3e322937e5c48a692c1a80f512f86a7 new file mode 100644 index 0000000000..e90ae3272e Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/294892eee3e322937e5c48a692c1a80f512f86a7 differ diff --git a/external/boringssl/fuzz/client_corpus/295259cda114ddc75587c4237e42d2cb3bd58165 b/external/boringssl/fuzz/client_corpus/295259cda114ddc75587c4237e42d2cb3bd58165 new file mode 100644 index 0000000000..1ab19b9b99 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/295259cda114ddc75587c4237e42d2cb3bd58165 differ diff --git a/external/boringssl/fuzz/client_corpus/296b4a799ffd5949e625d993de20aaf47045b807 b/external/boringssl/fuzz/client_corpus/296b4a799ffd5949e625d993de20aaf47045b807 new file mode 100644 index 0000000000..a2aab8192d Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/296b4a799ffd5949e625d993de20aaf47045b807 differ diff --git a/external/boringssl/fuzz/client_corpus/2a74dc354366c2490747f436c3a9ece14330857f b/external/boringssl/fuzz/client_corpus/2a74dc354366c2490747f436c3a9ece14330857f new file mode 100644 index 0000000000..52888481f0 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/2a74dc354366c2490747f436c3a9ece14330857f differ diff --git a/external/boringssl/fuzz/client_corpus/2afe68d42826fa1cdad90848708c07a710658e9c b/external/boringssl/fuzz/client_corpus/2afe68d42826fa1cdad90848708c07a710658e9c new file mode 100644 index 0000000000..771e023d77 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/2afe68d42826fa1cdad90848708c07a710658e9c differ diff --git a/external/boringssl/fuzz/client_corpus/2b298d34dea054df52fbec818faef171c34e1c8a b/external/boringssl/fuzz/client_corpus/2b298d34dea054df52fbec818faef171c34e1c8a new file mode 100644 index 0000000000..4300d129a4 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/2b298d34dea054df52fbec818faef171c34e1c8a differ diff --git a/external/boringssl/fuzz/client_corpus/2b448ff1e24aa4da10783f03e86b58f5f8446205 b/external/boringssl/fuzz/client_corpus/2b448ff1e24aa4da10783f03e86b58f5f8446205 new file mode 100644 index 0000000000..a2bac37197 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/2b448ff1e24aa4da10783f03e86b58f5f8446205 differ diff --git a/external/boringssl/fuzz/client_corpus/2b86a76cf1318e021a59f231a72bc64b410dbea6 b/external/boringssl/fuzz/client_corpus/2b86a76cf1318e021a59f231a72bc64b410dbea6 new file mode 100644 index 0000000000..f86cdd26ee Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/2b86a76cf1318e021a59f231a72bc64b410dbea6 differ diff --git a/external/boringssl/fuzz/client_corpus/2c0ba9f07133ff5c9f25f2518a375ece8a4b2ab7 b/external/boringssl/fuzz/client_corpus/2c0ba9f07133ff5c9f25f2518a375ece8a4b2ab7 new file mode 100644 index 0000000000..e2ee8fb60f Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/2c0ba9f07133ff5c9f25f2518a375ece8a4b2ab7 differ diff --git a/external/boringssl/fuzz/client_corpus/2c25c12a76c3fa337df33fb8523855fef69a3552 b/external/boringssl/fuzz/client_corpus/2c25c12a76c3fa337df33fb8523855fef69a3552 new file mode 100644 index 0000000000..9a2e4075f4 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/2c25c12a76c3fa337df33fb8523855fef69a3552 differ diff --git a/external/boringssl/fuzz/client_corpus/2c29b94d94502d8f305aad65c532f0e4ef6400a8 b/external/boringssl/fuzz/client_corpus/2c29b94d94502d8f305aad65c532f0e4ef6400a8 new file mode 100644 index 0000000000..1c2f3754e1 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/2c29b94d94502d8f305aad65c532f0e4ef6400a8 differ diff --git a/external/boringssl/fuzz/client_corpus/2c673d0a67080d78b85738d7494270f4e9932020 b/external/boringssl/fuzz/client_corpus/2c673d0a67080d78b85738d7494270f4e9932020 new file mode 100644 index 0000000000..f148ed231b Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/2c673d0a67080d78b85738d7494270f4e9932020 differ diff --git a/external/boringssl/fuzz/client_corpus/2db4737507ab67ea548413e232fb8c5edfe907aa b/external/boringssl/fuzz/client_corpus/2db4737507ab67ea548413e232fb8c5edfe907aa new file mode 100644 index 0000000000..32b5940d92 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/2db4737507ab67ea548413e232fb8c5edfe907aa differ diff --git a/external/boringssl/fuzz/client_corpus/2dcef28430b5fefc918a951bf28bbf996dce68e9 b/external/boringssl/fuzz/client_corpus/2dcef28430b5fefc918a951bf28bbf996dce68e9 new file mode 100644 index 0000000000..5a3c2b360b Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/2dcef28430b5fefc918a951bf28bbf996dce68e9 differ diff --git a/external/boringssl/fuzz/client_corpus/2e271373d7ea8184987d5d9cb61e0dab7b8af8e5 b/external/boringssl/fuzz/client_corpus/2e271373d7ea8184987d5d9cb61e0dab7b8af8e5 new file mode 100644 index 0000000000..c9498f7e8a Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/2e271373d7ea8184987d5d9cb61e0dab7b8af8e5 differ diff --git a/external/boringssl/fuzz/client_corpus/2e3b6c6ae461d3aaad63e918019874edd57bd40e b/external/boringssl/fuzz/client_corpus/2e3b6c6ae461d3aaad63e918019874edd57bd40e new file mode 100644 index 0000000000..9c39e12f90 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/2e3b6c6ae461d3aaad63e918019874edd57bd40e differ diff --git a/external/boringssl/fuzz/client_corpus/2e7f99689d1ac0a28adf0785f28946561b3a9076 b/external/boringssl/fuzz/client_corpus/2e7f99689d1ac0a28adf0785f28946561b3a9076 new file mode 100644 index 0000000000..950c3e3ae0 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/2e7f99689d1ac0a28adf0785f28946561b3a9076 differ diff --git a/external/boringssl/fuzz/client_corpus/2ec2f6f5530b0daf769c3a5b608d95132283c248 b/external/boringssl/fuzz/client_corpus/2ec2f6f5530b0daf769c3a5b608d95132283c248 new file mode 100644 index 0000000000..b5f0b73f15 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/2ec2f6f5530b0daf769c3a5b608d95132283c248 differ diff --git a/external/boringssl/fuzz/client_corpus/2f0549f7d7779c00cd1aaf4a69f14f96b6b0a85a b/external/boringssl/fuzz/client_corpus/2f0549f7d7779c00cd1aaf4a69f14f96b6b0a85a new file mode 100644 index 0000000000..545c52d002 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/2f0549f7d7779c00cd1aaf4a69f14f96b6b0a85a differ diff --git a/external/boringssl/fuzz/client_corpus/2f0c291ff5daa13064c5c7ff4a95d6785e78f66e b/external/boringssl/fuzz/client_corpus/2f0c291ff5daa13064c5c7ff4a95d6785e78f66e new file mode 100644 index 0000000000..4abc84970d Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/2f0c291ff5daa13064c5c7ff4a95d6785e78f66e differ diff --git a/external/boringssl/fuzz/client_corpus/2feba4853e4f4d64baeba180780940cdf8ff1825 b/external/boringssl/fuzz/client_corpus/2feba4853e4f4d64baeba180780940cdf8ff1825 new file mode 100644 index 0000000000..deab891cc4 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/2feba4853e4f4d64baeba180780940cdf8ff1825 differ diff --git a/external/boringssl/fuzz/client_corpus/304eea2da2a6032172159e9f43ddb21397a08224 b/external/boringssl/fuzz/client_corpus/304eea2da2a6032172159e9f43ddb21397a08224 new file mode 100644 index 0000000000..a382da5c6b Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/304eea2da2a6032172159e9f43ddb21397a08224 differ diff --git a/external/boringssl/fuzz/client_corpus/30763ce17b7ec3d80954cf5a461743cf04238c6a b/external/boringssl/fuzz/client_corpus/30763ce17b7ec3d80954cf5a461743cf04238c6a new file mode 100644 index 0000000000..f3337e211e Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/30763ce17b7ec3d80954cf5a461743cf04238c6a differ diff --git a/external/boringssl/fuzz/client_corpus/318fb04e83191ad61d152cc68f6d84d0a24a66d3 b/external/boringssl/fuzz/client_corpus/318fb04e83191ad61d152cc68f6d84d0a24a66d3 new file mode 100644 index 0000000000..4b3568cf18 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/318fb04e83191ad61d152cc68f6d84d0a24a66d3 differ diff --git a/external/boringssl/fuzz/client_corpus/31bd0841f052c324db7b6bcde7e5517b289708d7 b/external/boringssl/fuzz/client_corpus/31bd0841f052c324db7b6bcde7e5517b289708d7 new file mode 100644 index 0000000000..3ecd780818 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/31bd0841f052c324db7b6bcde7e5517b289708d7 differ diff --git a/external/boringssl/fuzz/client_corpus/31f779223bc6f44ef7a9a464fe11b31ca5abd5e8 b/external/boringssl/fuzz/client_corpus/31f779223bc6f44ef7a9a464fe11b31ca5abd5e8 new file mode 100644 index 0000000000..6a0d64673c Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/31f779223bc6f44ef7a9a464fe11b31ca5abd5e8 differ diff --git a/external/boringssl/fuzz/client_corpus/3286a72e23cd5f583a25bb5c489f12c60427d501 b/external/boringssl/fuzz/client_corpus/3286a72e23cd5f583a25bb5c489f12c60427d501 new file mode 100644 index 0000000000..2ada790121 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/3286a72e23cd5f583a25bb5c489f12c60427d501 differ diff --git a/external/boringssl/fuzz/client_corpus/32e6b85afd36cbafcb3149b16da3783c5bbd8c39 b/external/boringssl/fuzz/client_corpus/32e6b85afd36cbafcb3149b16da3783c5bbd8c39 new file mode 100644 index 0000000000..25d31a9ce5 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/32e6b85afd36cbafcb3149b16da3783c5bbd8c39 differ diff --git a/external/boringssl/fuzz/client_corpus/32fcabb3daaba21acf21bad494ef03b3f81f7f7c b/external/boringssl/fuzz/client_corpus/32fcabb3daaba21acf21bad494ef03b3f81f7f7c new file mode 100644 index 0000000000..6ea294ec01 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/32fcabb3daaba21acf21bad494ef03b3f81f7f7c differ diff --git a/external/boringssl/fuzz/client_corpus/334532c6a6e2d134c489dfa4d80989fb06172d02 b/external/boringssl/fuzz/client_corpus/334532c6a6e2d134c489dfa4d80989fb06172d02 new file mode 100644 index 0000000000..9a6dda011b Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/334532c6a6e2d134c489dfa4d80989fb06172d02 differ diff --git a/external/boringssl/fuzz/client_corpus/34bd03730328037405744586b88c57c81992cd31 b/external/boringssl/fuzz/client_corpus/34bd03730328037405744586b88c57c81992cd31 new file mode 100644 index 0000000000..e1f29c760f Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/34bd03730328037405744586b88c57c81992cd31 differ diff --git a/external/boringssl/fuzz/client_corpus/34d566d2f53d0b428cd37a9a775992bc41763d9d b/external/boringssl/fuzz/client_corpus/34d566d2f53d0b428cd37a9a775992bc41763d9d new file mode 100644 index 0000000000..d1ec7b0a1e Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/34d566d2f53d0b428cd37a9a775992bc41763d9d differ diff --git a/external/boringssl/fuzz/client_corpus/34edfdaf9801227520aef18e911c0dd28cad2dde b/external/boringssl/fuzz/client_corpus/34edfdaf9801227520aef18e911c0dd28cad2dde new file mode 100644 index 0000000000..4399ca0132 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/34edfdaf9801227520aef18e911c0dd28cad2dde differ diff --git a/external/boringssl/fuzz/client_corpus/361bcd77ea202443741a8c6abe135f3d430c6203 b/external/boringssl/fuzz/client_corpus/361bcd77ea202443741a8c6abe135f3d430c6203 new file mode 100644 index 0000000000..6a8dd19c0f Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/361bcd77ea202443741a8c6abe135f3d430c6203 differ diff --git a/external/boringssl/fuzz/client_corpus/36cc750fd326bb566cd107ddd157a6e7e191fcbe b/external/boringssl/fuzz/client_corpus/36cc750fd326bb566cd107ddd157a6e7e191fcbe new file mode 100644 index 0000000000..0000ed5cd1 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/36cc750fd326bb566cd107ddd157a6e7e191fcbe differ diff --git a/external/boringssl/fuzz/client_corpus/36d0151313a6b5053cb75bae03d3860dd48c725b b/external/boringssl/fuzz/client_corpus/36d0151313a6b5053cb75bae03d3860dd48c725b new file mode 100644 index 0000000000..e603e14589 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/36d0151313a6b5053cb75bae03d3860dd48c725b differ diff --git a/external/boringssl/fuzz/client_corpus/36e6dd737b0f9e0c28acd58660006ea5ba3e08a3 b/external/boringssl/fuzz/client_corpus/36e6dd737b0f9e0c28acd58660006ea5ba3e08a3 new file mode 100644 index 0000000000..2591216049 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/36e6dd737b0f9e0c28acd58660006ea5ba3e08a3 differ diff --git a/external/boringssl/fuzz/client_corpus/37d11e4a9d0dc08dd725a6909f4b3ccc0d904e0f b/external/boringssl/fuzz/client_corpus/37d11e4a9d0dc08dd725a6909f4b3ccc0d904e0f new file mode 100644 index 0000000000..cb278f1159 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/37d11e4a9d0dc08dd725a6909f4b3ccc0d904e0f differ diff --git a/external/boringssl/fuzz/client_corpus/37ecd40aaea21c8d39d36ded147feb60af7a58c8 b/external/boringssl/fuzz/client_corpus/37ecd40aaea21c8d39d36ded147feb60af7a58c8 new file mode 100644 index 0000000000..70eb35b881 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/37ecd40aaea21c8d39d36ded147feb60af7a58c8 differ diff --git a/external/boringssl/fuzz/client_corpus/388e0215db4ce5142a628644b3cd431c515a1f14 b/external/boringssl/fuzz/client_corpus/388e0215db4ce5142a628644b3cd431c515a1f14 new file mode 100644 index 0000000000..9d0d3e4be1 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/388e0215db4ce5142a628644b3cd431c515a1f14 differ diff --git a/external/boringssl/fuzz/client_corpus/389938579b67a293b6b5176c16e7199edcd75a12 b/external/boringssl/fuzz/client_corpus/389938579b67a293b6b5176c16e7199edcd75a12 new file mode 100644 index 0000000000..1e5ee59c19 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/389938579b67a293b6b5176c16e7199edcd75a12 differ diff --git a/external/boringssl/fuzz/client_corpus/38c4742b3533fb5fe2aa75661055614683a90b42 b/external/boringssl/fuzz/client_corpus/38c4742b3533fb5fe2aa75661055614683a90b42 new file mode 100644 index 0000000000..86ec229221 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/38c4742b3533fb5fe2aa75661055614683a90b42 differ diff --git a/external/boringssl/fuzz/client_corpus/38d4760261ec36cb13967bed3bd2f1914082ade5 b/external/boringssl/fuzz/client_corpus/38d4760261ec36cb13967bed3bd2f1914082ade5 new file mode 100644 index 0000000000..878a30bbd3 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/38d4760261ec36cb13967bed3bd2f1914082ade5 differ diff --git a/external/boringssl/fuzz/client_corpus/38f482657361ba8058abba483509cec9b2ba7f6d b/external/boringssl/fuzz/client_corpus/38f482657361ba8058abba483509cec9b2ba7f6d new file mode 100644 index 0000000000..204f858839 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/38f482657361ba8058abba483509cec9b2ba7f6d differ diff --git a/external/boringssl/fuzz/client_corpus/38fedaee7cc66c4cec5cb9c0618b6f6bfaf04308 b/external/boringssl/fuzz/client_corpus/38fedaee7cc66c4cec5cb9c0618b6f6bfaf04308 new file mode 100644 index 0000000000..1f6da9c51b Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/38fedaee7cc66c4cec5cb9c0618b6f6bfaf04308 differ diff --git a/external/boringssl/fuzz/client_corpus/3965ca28906687da44123bbaf6a6c589021a80b4 b/external/boringssl/fuzz/client_corpus/3965ca28906687da44123bbaf6a6c589021a80b4 new file mode 100644 index 0000000000..e14a837519 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/3965ca28906687da44123bbaf6a6c589021a80b4 differ diff --git a/external/boringssl/fuzz/client_corpus/3981b84969aeaa457545577ff22b6fa973c21656 b/external/boringssl/fuzz/client_corpus/3981b84969aeaa457545577ff22b6fa973c21656 new file mode 100644 index 0000000000..cad8ed30f5 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/3981b84969aeaa457545577ff22b6fa973c21656 differ diff --git a/external/boringssl/fuzz/client_corpus/39a56836c3a816e0e4930846af629bdbd139e8a8 b/external/boringssl/fuzz/client_corpus/39a56836c3a816e0e4930846af629bdbd139e8a8 new file mode 100644 index 0000000000..6841412d36 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/39a56836c3a816e0e4930846af629bdbd139e8a8 differ diff --git a/external/boringssl/fuzz/client_corpus/39ab33714bd7e79f1905c2471643371bbd22b809 b/external/boringssl/fuzz/client_corpus/39ab33714bd7e79f1905c2471643371bbd22b809 new file mode 100644 index 0000000000..3c38351915 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/39ab33714bd7e79f1905c2471643371bbd22b809 differ diff --git a/external/boringssl/fuzz/client_corpus/3a077a02dab98581d00d2f679def27b8818b9afb b/external/boringssl/fuzz/client_corpus/3a077a02dab98581d00d2f679def27b8818b9afb new file mode 100644 index 0000000000..a8a32edf6e Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/3a077a02dab98581d00d2f679def27b8818b9afb differ diff --git a/external/boringssl/fuzz/client_corpus/3a7353d5a43ca223422a827a480d3c7faf69c491 b/external/boringssl/fuzz/client_corpus/3a7353d5a43ca223422a827a480d3c7faf69c491 new file mode 100644 index 0000000000..386bfe612d Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/3a7353d5a43ca223422a827a480d3c7faf69c491 differ diff --git a/external/boringssl/fuzz/client_corpus/3aa50d20cca6074a98c77480f27d62ef3675438c b/external/boringssl/fuzz/client_corpus/3aa50d20cca6074a98c77480f27d62ef3675438c new file mode 100644 index 0000000000..40fd0a0fbe Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/3aa50d20cca6074a98c77480f27d62ef3675438c differ diff --git a/external/boringssl/fuzz/client_corpus/3acf8c1831d6f97bdc31ff541fe1da11e558c37c b/external/boringssl/fuzz/client_corpus/3acf8c1831d6f97bdc31ff541fe1da11e558c37c new file mode 100644 index 0000000000..102e21b5ed Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/3acf8c1831d6f97bdc31ff541fe1da11e558c37c differ diff --git a/external/boringssl/fuzz/client_corpus/3ae3f333e3883de4de59431f0bde46aaae04dc32 b/external/boringssl/fuzz/client_corpus/3ae3f333e3883de4de59431f0bde46aaae04dc32 new file mode 100644 index 0000000000..b337102eaf Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/3ae3f333e3883de4de59431f0bde46aaae04dc32 differ diff --git a/external/boringssl/fuzz/client_corpus/3b085660a48ed6743ab50e4cf21ba181487e834c b/external/boringssl/fuzz/client_corpus/3b085660a48ed6743ab50e4cf21ba181487e834c new file mode 100644 index 0000000000..f866eac294 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/3b085660a48ed6743ab50e4cf21ba181487e834c differ diff --git a/external/boringssl/fuzz/client_corpus/3b240f61c01265600a3a37d2be9e1ba0d9e31990 b/external/boringssl/fuzz/client_corpus/3b240f61c01265600a3a37d2be9e1ba0d9e31990 new file mode 100644 index 0000000000..98ea5dda1e Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/3b240f61c01265600a3a37d2be9e1ba0d9e31990 differ diff --git a/external/boringssl/fuzz/client_corpus/3b7b4ca1d3fd9f71d35dfeef5df35d231c9cebba b/external/boringssl/fuzz/client_corpus/3b7b4ca1d3fd9f71d35dfeef5df35d231c9cebba new file mode 100644 index 0000000000..5fe2d11b2a Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/3b7b4ca1d3fd9f71d35dfeef5df35d231c9cebba differ diff --git a/external/boringssl/fuzz/client_corpus/3be80948934b8980f9f6a509062820245c51512a b/external/boringssl/fuzz/client_corpus/3be80948934b8980f9f6a509062820245c51512a new file mode 100644 index 0000000000..05f7c0174e Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/3be80948934b8980f9f6a509062820245c51512a differ diff --git a/external/boringssl/fuzz/client_corpus/3c185ac9221ffa389695a41ea1cd5d6edba6f5af b/external/boringssl/fuzz/client_corpus/3c185ac9221ffa389695a41ea1cd5d6edba6f5af new file mode 100644 index 0000000000..bae2b233f2 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/3c185ac9221ffa389695a41ea1cd5d6edba6f5af differ diff --git a/external/boringssl/fuzz/client_corpus/3c3226c37487c643f0c392730627c0aef3ba1495 b/external/boringssl/fuzz/client_corpus/3c3226c37487c643f0c392730627c0aef3ba1495 new file mode 100644 index 0000000000..464c532ded Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/3c3226c37487c643f0c392730627c0aef3ba1495 differ diff --git a/external/boringssl/fuzz/client_corpus/3c32698e2d5af52bd2011d3924058834f0a34ed5 b/external/boringssl/fuzz/client_corpus/3c32698e2d5af52bd2011d3924058834f0a34ed5 new file mode 100644 index 0000000000..daa63e1847 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/3c32698e2d5af52bd2011d3924058834f0a34ed5 differ diff --git a/external/boringssl/fuzz/client_corpus/3c6f5c00bc1086d604ae1a50eef96cf721c62353 b/external/boringssl/fuzz/client_corpus/3c6f5c00bc1086d604ae1a50eef96cf721c62353 new file mode 100644 index 0000000000..c597f22506 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/3c6f5c00bc1086d604ae1a50eef96cf721c62353 differ diff --git a/external/boringssl/fuzz/client_corpus/3c72b62ed35afc086b83c81e71053a0f4ef3988c b/external/boringssl/fuzz/client_corpus/3c72b62ed35afc086b83c81e71053a0f4ef3988c new file mode 100644 index 0000000000..71953a950f Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/3c72b62ed35afc086b83c81e71053a0f4ef3988c differ diff --git a/external/boringssl/fuzz/client_corpus/3cd1dd085b1ab7bea2586e5aaf0807d22dde5c13 b/external/boringssl/fuzz/client_corpus/3cd1dd085b1ab7bea2586e5aaf0807d22dde5c13 new file mode 100644 index 0000000000..50ad4defc1 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/3cd1dd085b1ab7bea2586e5aaf0807d22dde5c13 differ diff --git a/external/boringssl/fuzz/client_corpus/3cffa14e490c092657bbb33af7c14a33768b3beb b/external/boringssl/fuzz/client_corpus/3cffa14e490c092657bbb33af7c14a33768b3beb new file mode 100644 index 0000000000..b423fb98bf Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/3cffa14e490c092657bbb33af7c14a33768b3beb differ diff --git a/external/boringssl/fuzz/client_corpus/3d63cf90bd396f0824b290f576997daf16884f80 b/external/boringssl/fuzz/client_corpus/3d63cf90bd396f0824b290f576997daf16884f80 new file mode 100644 index 0000000000..93638feab0 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/3d63cf90bd396f0824b290f576997daf16884f80 differ diff --git a/external/boringssl/fuzz/client_corpus/3ed7d737427f45bd3f824c31aaa6c0b2d72c5df0 b/external/boringssl/fuzz/client_corpus/3ed7d737427f45bd3f824c31aaa6c0b2d72c5df0 new file mode 100644 index 0000000000..a1be5d8826 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/3ed7d737427f45bd3f824c31aaa6c0b2d72c5df0 differ diff --git a/external/boringssl/fuzz/client_corpus/3f67156ac8c46e96a0cf59c6b7f64af25316db6f b/external/boringssl/fuzz/client_corpus/3f67156ac8c46e96a0cf59c6b7f64af25316db6f new file mode 100644 index 0000000000..b96224eceb Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/3f67156ac8c46e96a0cf59c6b7f64af25316db6f differ diff --git a/external/boringssl/fuzz/client_corpus/40515498756f4fac616ddc3ac4c2669ea5a8771f b/external/boringssl/fuzz/client_corpus/40515498756f4fac616ddc3ac4c2669ea5a8771f new file mode 100644 index 0000000000..964fc15601 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/40515498756f4fac616ddc3ac4c2669ea5a8771f differ diff --git a/external/boringssl/fuzz/client_corpus/405b2eaa9f8a6ec9aebcaa7d9897c1be18bf9b57 b/external/boringssl/fuzz/client_corpus/405b2eaa9f8a6ec9aebcaa7d9897c1be18bf9b57 new file mode 100644 index 0000000000..85a520dc41 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/405b2eaa9f8a6ec9aebcaa7d9897c1be18bf9b57 differ diff --git a/external/boringssl/fuzz/client_corpus/4073b68ca8908512aa7a9f71fad9866321690c5b b/external/boringssl/fuzz/client_corpus/4073b68ca8908512aa7a9f71fad9866321690c5b new file mode 100644 index 0000000000..02703a20e8 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/4073b68ca8908512aa7a9f71fad9866321690c5b differ diff --git a/external/boringssl/fuzz/client_corpus/41b22775bbf5e9716b641b963830a1f35029b400 b/external/boringssl/fuzz/client_corpus/41b22775bbf5e9716b641b963830a1f35029b400 new file mode 100644 index 0000000000..7c31d6d50f Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/41b22775bbf5e9716b641b963830a1f35029b400 differ diff --git a/external/boringssl/fuzz/client_corpus/420326169b2a6c801a90fa1a414a17a461e81de5 b/external/boringssl/fuzz/client_corpus/420326169b2a6c801a90fa1a414a17a461e81de5 new file mode 100644 index 0000000000..86c55cc6f8 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/420326169b2a6c801a90fa1a414a17a461e81de5 differ diff --git a/external/boringssl/fuzz/client_corpus/4207635e571247e374c3bac2d5cfe6d279b3c182 b/external/boringssl/fuzz/client_corpus/4207635e571247e374c3bac2d5cfe6d279b3c182 new file mode 100644 index 0000000000..e55728b289 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/4207635e571247e374c3bac2d5cfe6d279b3c182 differ diff --git a/external/boringssl/fuzz/client_corpus/42ec8d96c8304cc2f4a98d1670752862ea967a5a b/external/boringssl/fuzz/client_corpus/42ec8d96c8304cc2f4a98d1670752862ea967a5a new file mode 100644 index 0000000000..2b058751c7 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/42ec8d96c8304cc2f4a98d1670752862ea967a5a differ diff --git a/external/boringssl/fuzz/client_corpus/433c4b6fa77655178d8d2782e9ac59fa527ec4fb b/external/boringssl/fuzz/client_corpus/433c4b6fa77655178d8d2782e9ac59fa527ec4fb new file mode 100644 index 0000000000..7c570377ca Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/433c4b6fa77655178d8d2782e9ac59fa527ec4fb differ diff --git a/external/boringssl/fuzz/client_corpus/43f38755fd9aeab3ac4f842c87379ea2e7c087bd b/external/boringssl/fuzz/client_corpus/43f38755fd9aeab3ac4f842c87379ea2e7c087bd new file mode 100644 index 0000000000..7249606421 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/43f38755fd9aeab3ac4f842c87379ea2e7c087bd differ diff --git a/external/boringssl/fuzz/client_corpus/4405b79401b4338ea26a7b0f2cc43f4cf4c5c4b8 b/external/boringssl/fuzz/client_corpus/4405b79401b4338ea26a7b0f2cc43f4cf4c5c4b8 new file mode 100644 index 0000000000..9633d8e155 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/4405b79401b4338ea26a7b0f2cc43f4cf4c5c4b8 differ diff --git a/external/boringssl/fuzz/client_corpus/44e7f1eae0a0e729bb6f990eceb544ba1cfde7d5 b/external/boringssl/fuzz/client_corpus/44e7f1eae0a0e729bb6f990eceb544ba1cfde7d5 new file mode 100644 index 0000000000..4e5634088d Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/44e7f1eae0a0e729bb6f990eceb544ba1cfde7d5 differ diff --git a/external/boringssl/fuzz/client_corpus/453340dfa05d4c218067a9c01d12d0c0dc05872b b/external/boringssl/fuzz/client_corpus/453340dfa05d4c218067a9c01d12d0c0dc05872b new file mode 100644 index 0000000000..52dea25ec1 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/453340dfa05d4c218067a9c01d12d0c0dc05872b differ diff --git a/external/boringssl/fuzz/client_corpus/4589942d410d038d7739511c3fc862bfaf6f5d55 b/external/boringssl/fuzz/client_corpus/4589942d410d038d7739511c3fc862bfaf6f5d55 new file mode 100644 index 0000000000..ec5085797e Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/4589942d410d038d7739511c3fc862bfaf6f5d55 differ diff --git a/external/boringssl/fuzz/client_corpus/458e6fe51ffd10f4f003507da3d34105ff4ba41d b/external/boringssl/fuzz/client_corpus/458e6fe51ffd10f4f003507da3d34105ff4ba41d new file mode 100644 index 0000000000..70d89967c0 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/458e6fe51ffd10f4f003507da3d34105ff4ba41d differ diff --git a/external/boringssl/fuzz/client_corpus/45add649d95c14b12c577e21ae2af7f9050aaf64 b/external/boringssl/fuzz/client_corpus/45add649d95c14b12c577e21ae2af7f9050aaf64 new file mode 100644 index 0000000000..3c1d7e5f78 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/45add649d95c14b12c577e21ae2af7f9050aaf64 differ diff --git a/external/boringssl/fuzz/client_corpus/45c53453a35ecd0c755c03936c68103b0dff17b8 b/external/boringssl/fuzz/client_corpus/45c53453a35ecd0c755c03936c68103b0dff17b8 new file mode 100644 index 0000000000..a10145507f Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/45c53453a35ecd0c755c03936c68103b0dff17b8 differ diff --git a/external/boringssl/fuzz/client_corpus/45e5a626f981cca5c160850cf0a7054d6dcb7252 b/external/boringssl/fuzz/client_corpus/45e5a626f981cca5c160850cf0a7054d6dcb7252 new file mode 100644 index 0000000000..1d3933f32a Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/45e5a626f981cca5c160850cf0a7054d6dcb7252 differ diff --git a/external/boringssl/fuzz/client_corpus/45f83321ca27fbb48c856bf051c5ac1b3293f5d4 b/external/boringssl/fuzz/client_corpus/45f83321ca27fbb48c856bf051c5ac1b3293f5d4 new file mode 100644 index 0000000000..82afe1b6a2 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/45f83321ca27fbb48c856bf051c5ac1b3293f5d4 differ diff --git a/external/boringssl/fuzz/client_corpus/461ec2d1f3724eba0fc12a620a1a3b441bde50f1 b/external/boringssl/fuzz/client_corpus/461ec2d1f3724eba0fc12a620a1a3b441bde50f1 new file mode 100644 index 0000000000..9dcc455475 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/461ec2d1f3724eba0fc12a620a1a3b441bde50f1 differ diff --git a/external/boringssl/fuzz/client_corpus/465d2a8214142a177aaacafc8e7da3642b7410cb b/external/boringssl/fuzz/client_corpus/465d2a8214142a177aaacafc8e7da3642b7410cb new file mode 100644 index 0000000000..6c5c29d419 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/465d2a8214142a177aaacafc8e7da3642b7410cb differ diff --git a/external/boringssl/fuzz/client_corpus/468dc35f968efd4dac4fa31bbe1f5e69bf1c7dd8 b/external/boringssl/fuzz/client_corpus/468dc35f968efd4dac4fa31bbe1f5e69bf1c7dd8 new file mode 100644 index 0000000000..5c2b04df59 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/468dc35f968efd4dac4fa31bbe1f5e69bf1c7dd8 differ diff --git a/external/boringssl/fuzz/client_corpus/470813fb2b87e90fd61f1a3e3a7046afe1ca552c b/external/boringssl/fuzz/client_corpus/470813fb2b87e90fd61f1a3e3a7046afe1ca552c new file mode 100644 index 0000000000..9beba51489 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/470813fb2b87e90fd61f1a3e3a7046afe1ca552c differ diff --git a/external/boringssl/fuzz/client_corpus/47a72fd0a7615521d4ced25c6df549288dc45418 b/external/boringssl/fuzz/client_corpus/47a72fd0a7615521d4ced25c6df549288dc45418 new file mode 100644 index 0000000000..1a1803c42f Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/47a72fd0a7615521d4ced25c6df549288dc45418 differ diff --git a/external/boringssl/fuzz/client_corpus/48396ed7c8f8d7cb48705c22d157a43841e3bf54 b/external/boringssl/fuzz/client_corpus/48396ed7c8f8d7cb48705c22d157a43841e3bf54 new file mode 100644 index 0000000000..47553be87e Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/48396ed7c8f8d7cb48705c22d157a43841e3bf54 differ diff --git a/external/boringssl/fuzz/client_corpus/48d0e70401c0f5124e8ee35ce51453c4648ea01d b/external/boringssl/fuzz/client_corpus/48d0e70401c0f5124e8ee35ce51453c4648ea01d new file mode 100644 index 0000000000..cfc8760637 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/48d0e70401c0f5124e8ee35ce51453c4648ea01d differ diff --git a/external/boringssl/fuzz/client_corpus/48dbfc59064af6b303eaa6c6b39b92047b6e9a77 b/external/boringssl/fuzz/client_corpus/48dbfc59064af6b303eaa6c6b39b92047b6e9a77 new file mode 100644 index 0000000000..b77aff7b58 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/48dbfc59064af6b303eaa6c6b39b92047b6e9a77 differ diff --git a/external/boringssl/fuzz/client_corpus/4976325a6b3d9d258b512743adf4dd7ef037ae4e b/external/boringssl/fuzz/client_corpus/4976325a6b3d9d258b512743adf4dd7ef037ae4e new file mode 100644 index 0000000000..27eae10034 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/4976325a6b3d9d258b512743adf4dd7ef037ae4e differ diff --git a/external/boringssl/fuzz/client_corpus/49a3fc41e9dc84a4e693056bdfc96139d9f25f80 b/external/boringssl/fuzz/client_corpus/49a3fc41e9dc84a4e693056bdfc96139d9f25f80 new file mode 100644 index 0000000000..560466b02c Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/49a3fc41e9dc84a4e693056bdfc96139d9f25f80 differ diff --git a/external/boringssl/fuzz/client_corpus/49c7e584495621defd79963151fb33ebf79bc35e b/external/boringssl/fuzz/client_corpus/49c7e584495621defd79963151fb33ebf79bc35e new file mode 100644 index 0000000000..d0d8b8898d Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/49c7e584495621defd79963151fb33ebf79bc35e differ diff --git a/external/boringssl/fuzz/client_corpus/4a0a0cb71589d083291ea86ebc858f8a49868cfd b/external/boringssl/fuzz/client_corpus/4a0a0cb71589d083291ea86ebc858f8a49868cfd new file mode 100644 index 0000000000..ede296fb19 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/4a0a0cb71589d083291ea86ebc858f8a49868cfd differ diff --git a/external/boringssl/fuzz/client_corpus/4a0b77fa110185719de6c967c6030acab1ba82b0 b/external/boringssl/fuzz/client_corpus/4a0b77fa110185719de6c967c6030acab1ba82b0 new file mode 100644 index 0000000000..060c4a020a Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/4a0b77fa110185719de6c967c6030acab1ba82b0 differ diff --git a/external/boringssl/fuzz/client_corpus/4aa9b19fc0c44229c97649e98566b23235876c8a b/external/boringssl/fuzz/client_corpus/4aa9b19fc0c44229c97649e98566b23235876c8a new file mode 100644 index 0000000000..4b0e6965c0 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/4aa9b19fc0c44229c97649e98566b23235876c8a differ diff --git a/external/boringssl/fuzz/client_corpus/4ab06c821f1a0b5d761ecf299708867e4ca99e9b b/external/boringssl/fuzz/client_corpus/4ab06c821f1a0b5d761ecf299708867e4ca99e9b new file mode 100644 index 0000000000..4f64cb0c8f Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/4ab06c821f1a0b5d761ecf299708867e4ca99e9b differ diff --git a/external/boringssl/fuzz/client_corpus/4ad50b5ec8b4abc82f90962f6d2a845720fc5b5e b/external/boringssl/fuzz/client_corpus/4ad50b5ec8b4abc82f90962f6d2a845720fc5b5e new file mode 100644 index 0000000000..67f0191a37 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/4ad50b5ec8b4abc82f90962f6d2a845720fc5b5e differ diff --git a/external/boringssl/fuzz/client_corpus/4afce9787aecf1f3bfccaf89fdf65cabb504b432 b/external/boringssl/fuzz/client_corpus/4afce9787aecf1f3bfccaf89fdf65cabb504b432 new file mode 100644 index 0000000000..db08354209 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/4afce9787aecf1f3bfccaf89fdf65cabb504b432 differ diff --git a/external/boringssl/fuzz/client_corpus/4b2b4eef9cb2f51ba3b06799c5dd384c7373f714 b/external/boringssl/fuzz/client_corpus/4b2b4eef9cb2f51ba3b06799c5dd384c7373f714 new file mode 100644 index 0000000000..857434b25c Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/4b2b4eef9cb2f51ba3b06799c5dd384c7373f714 differ diff --git a/external/boringssl/fuzz/client_corpus/4b9f7e74269a66abf0332cef8d0754617fdbbd35 b/external/boringssl/fuzz/client_corpus/4b9f7e74269a66abf0332cef8d0754617fdbbd35 new file mode 100644 index 0000000000..700779ad1f Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/4b9f7e74269a66abf0332cef8d0754617fdbbd35 differ diff --git a/external/boringssl/fuzz/client_corpus/4bd18d873361567417de32972a3672d54102d412 b/external/boringssl/fuzz/client_corpus/4bd18d873361567417de32972a3672d54102d412 new file mode 100644 index 0000000000..1f4d3ef737 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/4bd18d873361567417de32972a3672d54102d412 differ diff --git a/external/boringssl/fuzz/client_corpus/4bd886ceae40aefd8e370a126f0c9eb914fd5178 b/external/boringssl/fuzz/client_corpus/4bd886ceae40aefd8e370a126f0c9eb914fd5178 new file mode 100644 index 0000000000..f6583d4c23 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/4bd886ceae40aefd8e370a126f0c9eb914fd5178 differ diff --git a/external/boringssl/fuzz/client_corpus/4c2e48c4b70f93db36c76fde74b5a858f90eef42 b/external/boringssl/fuzz/client_corpus/4c2e48c4b70f93db36c76fde74b5a858f90eef42 new file mode 100644 index 0000000000..ca65fe8879 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/4c2e48c4b70f93db36c76fde74b5a858f90eef42 differ diff --git a/external/boringssl/fuzz/client_corpus/4c2f5c72d1c9b71d6673feec2f4b3fd7b02b89dc b/external/boringssl/fuzz/client_corpus/4c2f5c72d1c9b71d6673feec2f4b3fd7b02b89dc new file mode 100644 index 0000000000..f849263121 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/4c2f5c72d1c9b71d6673feec2f4b3fd7b02b89dc differ diff --git a/external/boringssl/fuzz/client_corpus/4c7f90f4d64c6ef5968dedca30385c5cf76f3972 b/external/boringssl/fuzz/client_corpus/4c7f90f4d64c6ef5968dedca30385c5cf76f3972 new file mode 100644 index 0000000000..0956e8444f Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/4c7f90f4d64c6ef5968dedca30385c5cf76f3972 differ diff --git a/external/boringssl/fuzz/client_corpus/4cb2db6b2178c7548d37ca9d2b6c1216ed0aa479 b/external/boringssl/fuzz/client_corpus/4cb2db6b2178c7548d37ca9d2b6c1216ed0aa479 new file mode 100644 index 0000000000..e3ca838afa Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/4cb2db6b2178c7548d37ca9d2b6c1216ed0aa479 differ diff --git a/external/boringssl/fuzz/client_corpus/4cdf29aab0710302590f972ae90c76ab98d4866e b/external/boringssl/fuzz/client_corpus/4cdf29aab0710302590f972ae90c76ab98d4866e new file mode 100644 index 0000000000..e69148ec0b Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/4cdf29aab0710302590f972ae90c76ab98d4866e differ diff --git a/external/boringssl/fuzz/client_corpus/4ce91349ad2d273a481bcc859277322cfe3ca2cf b/external/boringssl/fuzz/client_corpus/4ce91349ad2d273a481bcc859277322cfe3ca2cf new file mode 100644 index 0000000000..0ce3a262fb Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/4ce91349ad2d273a481bcc859277322cfe3ca2cf differ diff --git a/external/boringssl/fuzz/client_corpus/4d8c1b4c5e122c2b8255b65e0bdb80ef9fa1573c b/external/boringssl/fuzz/client_corpus/4d8c1b4c5e122c2b8255b65e0bdb80ef9fa1573c new file mode 100644 index 0000000000..cfb785aef9 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/4d8c1b4c5e122c2b8255b65e0bdb80ef9fa1573c differ diff --git a/external/boringssl/fuzz/client_corpus/4dc96e80aeb3cfb40d59716db7316357a787ddbe b/external/boringssl/fuzz/client_corpus/4dc96e80aeb3cfb40d59716db7316357a787ddbe new file mode 100644 index 0000000000..a71223152a Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/4dc96e80aeb3cfb40d59716db7316357a787ddbe differ diff --git a/external/boringssl/fuzz/client_corpus/4dedc9b74663d27cb122c6dc4d1f9de031bfba32 b/external/boringssl/fuzz/client_corpus/4dedc9b74663d27cb122c6dc4d1f9de031bfba32 new file mode 100644 index 0000000000..50249d5986 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/4dedc9b74663d27cb122c6dc4d1f9de031bfba32 differ diff --git a/external/boringssl/fuzz/client_corpus/4dfb9236bb2c945b7f38ca2ddf80ebeb206ef019 b/external/boringssl/fuzz/client_corpus/4dfb9236bb2c945b7f38ca2ddf80ebeb206ef019 new file mode 100644 index 0000000000..8ee5d90ed8 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/4dfb9236bb2c945b7f38ca2ddf80ebeb206ef019 differ diff --git a/external/boringssl/fuzz/client_corpus/4e5ca638af464b9c18f96cf68ef346a1c7f4249b b/external/boringssl/fuzz/client_corpus/4e5ca638af464b9c18f96cf68ef346a1c7f4249b new file mode 100644 index 0000000000..5607116cc7 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/4e5ca638af464b9c18f96cf68ef346a1c7f4249b differ diff --git a/external/boringssl/fuzz/client_corpus/4ea847253da2a1a1153634efa3d904a35c59f4a1 b/external/boringssl/fuzz/client_corpus/4ea847253da2a1a1153634efa3d904a35c59f4a1 new file mode 100644 index 0000000000..3b45977230 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/4ea847253da2a1a1153634efa3d904a35c59f4a1 differ diff --git a/external/boringssl/fuzz/client_corpus/4f041d38c50cd4d7f6a65b8a3c0386ed8e62b97f b/external/boringssl/fuzz/client_corpus/4f041d38c50cd4d7f6a65b8a3c0386ed8e62b97f new file mode 100644 index 0000000000..b25bce0d96 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/4f041d38c50cd4d7f6a65b8a3c0386ed8e62b97f differ diff --git a/external/boringssl/fuzz/client_corpus/4f04ca4460744c01566bd82d52cc7aad444d3e13 b/external/boringssl/fuzz/client_corpus/4f04ca4460744c01566bd82d52cc7aad444d3e13 new file mode 100644 index 0000000000..147c292df2 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/4f04ca4460744c01566bd82d52cc7aad444d3e13 differ diff --git a/external/boringssl/fuzz/client_corpus/4f4d94f986e0ef2a67b2dda1d93dfbfe95194c71 b/external/boringssl/fuzz/client_corpus/4f4d94f986e0ef2a67b2dda1d93dfbfe95194c71 new file mode 100644 index 0000000000..afa96cb6f8 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/4f4d94f986e0ef2a67b2dda1d93dfbfe95194c71 differ diff --git a/external/boringssl/fuzz/client_corpus/4f79b4289be8ebc7a2524bb2ac9f29098d4b73a9 b/external/boringssl/fuzz/client_corpus/4f79b4289be8ebc7a2524bb2ac9f29098d4b73a9 new file mode 100644 index 0000000000..4a750d4ab0 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/4f79b4289be8ebc7a2524bb2ac9f29098d4b73a9 differ diff --git a/external/boringssl/fuzz/client_corpus/4f9252d70faee72c6708fce7f5c744248fe3261d b/external/boringssl/fuzz/client_corpus/4f9252d70faee72c6708fce7f5c744248fe3261d new file mode 100644 index 0000000000..16a5a56585 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/4f9252d70faee72c6708fce7f5c744248fe3261d differ diff --git a/external/boringssl/fuzz/client_corpus/501d6d76ac062c912f5896543a7983bcf4253c55 b/external/boringssl/fuzz/client_corpus/501d6d76ac062c912f5896543a7983bcf4253c55 new file mode 100644 index 0000000000..e9f7aa24ee Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/501d6d76ac062c912f5896543a7983bcf4253c55 differ diff --git a/external/boringssl/fuzz/client_corpus/5093bef091d961c4db1461031506e734374120f1 b/external/boringssl/fuzz/client_corpus/5093bef091d961c4db1461031506e734374120f1 new file mode 100644 index 0000000000..df21df4740 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/5093bef091d961c4db1461031506e734374120f1 differ diff --git a/external/boringssl/fuzz/client_corpus/50ef30b0dff70dae8632b17cd493971d63a65ebc b/external/boringssl/fuzz/client_corpus/50ef30b0dff70dae8632b17cd493971d63a65ebc new file mode 100644 index 0000000000..f9a987ed3a Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/50ef30b0dff70dae8632b17cd493971d63a65ebc differ diff --git a/external/boringssl/fuzz/client_corpus/51a55b3718f12f1a65110f86eddf8f0c81ce148e b/external/boringssl/fuzz/client_corpus/51a55b3718f12f1a65110f86eddf8f0c81ce148e new file mode 100644 index 0000000000..3a1de20ab2 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/51a55b3718f12f1a65110f86eddf8f0c81ce148e differ diff --git a/external/boringssl/fuzz/client_corpus/51aa8cac7aa64345016927d1f2d694926244a183 b/external/boringssl/fuzz/client_corpus/51aa8cac7aa64345016927d1f2d694926244a183 new file mode 100644 index 0000000000..c326a29c70 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/51aa8cac7aa64345016927d1f2d694926244a183 differ diff --git a/external/boringssl/fuzz/client_corpus/51c860e1ee8f6b577aace2da887d1357df130b78 b/external/boringssl/fuzz/client_corpus/51c860e1ee8f6b577aace2da887d1357df130b78 new file mode 100644 index 0000000000..42a236e53b Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/51c860e1ee8f6b577aace2da887d1357df130b78 differ diff --git a/external/boringssl/fuzz/client_corpus/525b787309e65a8a02fd26b313f06598052a4ae3 b/external/boringssl/fuzz/client_corpus/525b787309e65a8a02fd26b313f06598052a4ae3 new file mode 100644 index 0000000000..fcc855f6f9 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/525b787309e65a8a02fd26b313f06598052a4ae3 differ diff --git a/external/boringssl/fuzz/client_corpus/52a4a908684553c648cecb1bc85476f72aec44e9 b/external/boringssl/fuzz/client_corpus/52a4a908684553c648cecb1bc85476f72aec44e9 new file mode 100644 index 0000000000..7bd322132a Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/52a4a908684553c648cecb1bc85476f72aec44e9 differ diff --git a/external/boringssl/fuzz/client_corpus/52d54569aef7040df77bb0d484e929b927968c14 b/external/boringssl/fuzz/client_corpus/52d54569aef7040df77bb0d484e929b927968c14 new file mode 100644 index 0000000000..c020bc6dfe Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/52d54569aef7040df77bb0d484e929b927968c14 differ diff --git a/external/boringssl/fuzz/client_corpus/53fdf746a1ff4ca6004a67122c6667292ee01350 b/external/boringssl/fuzz/client_corpus/53fdf746a1ff4ca6004a67122c6667292ee01350 new file mode 100644 index 0000000000..93ad1d116f Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/53fdf746a1ff4ca6004a67122c6667292ee01350 differ diff --git a/external/boringssl/fuzz/client_corpus/54097c70512fcb14a736ef5049279161b86b0a97 b/external/boringssl/fuzz/client_corpus/54097c70512fcb14a736ef5049279161b86b0a97 new file mode 100644 index 0000000000..eda584c1e1 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/54097c70512fcb14a736ef5049279161b86b0a97 differ diff --git a/external/boringssl/fuzz/client_corpus/54be5dc0bfab143c982bf41b88d21f0cbb4969e1 b/external/boringssl/fuzz/client_corpus/54be5dc0bfab143c982bf41b88d21f0cbb4969e1 new file mode 100644 index 0000000000..ab15ac218a Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/54be5dc0bfab143c982bf41b88d21f0cbb4969e1 differ diff --git a/external/boringssl/fuzz/client_corpus/5598d89f542fdc4bc2bae890b3cacc9f41373306 b/external/boringssl/fuzz/client_corpus/5598d89f542fdc4bc2bae890b3cacc9f41373306 new file mode 100644 index 0000000000..14cb1ad501 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/5598d89f542fdc4bc2bae890b3cacc9f41373306 differ diff --git a/external/boringssl/fuzz/client_corpus/55dc2b5c70c3456c6ec3806f94d960d92488608a b/external/boringssl/fuzz/client_corpus/55dc2b5c70c3456c6ec3806f94d960d92488608a new file mode 100644 index 0000000000..f8f6c70886 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/55dc2b5c70c3456c6ec3806f94d960d92488608a differ diff --git a/external/boringssl/fuzz/client_corpus/5607123e29f461b258f5ba9bc32772766d09365f b/external/boringssl/fuzz/client_corpus/5607123e29f461b258f5ba9bc32772766d09365f new file mode 100644 index 0000000000..1128c9e655 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/5607123e29f461b258f5ba9bc32772766d09365f differ diff --git a/external/boringssl/fuzz/client_corpus/56484d61a742afd778d2f6c3d515aeebe632cf44 b/external/boringssl/fuzz/client_corpus/56484d61a742afd778d2f6c3d515aeebe632cf44 new file mode 100644 index 0000000000..c61a88364a Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/56484d61a742afd778d2f6c3d515aeebe632cf44 differ diff --git a/external/boringssl/fuzz/client_corpus/572e7a6444bf5587b2162daa9a72f1c8f5d51e9c b/external/boringssl/fuzz/client_corpus/572e7a6444bf5587b2162daa9a72f1c8f5d51e9c new file mode 100644 index 0000000000..86c8a3f9cb Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/572e7a6444bf5587b2162daa9a72f1c8f5d51e9c differ diff --git a/external/boringssl/fuzz/client_corpus/57414bd14950858020832e058d5df0e476472075 b/external/boringssl/fuzz/client_corpus/57414bd14950858020832e058d5df0e476472075 new file mode 100644 index 0000000000..a5b60970f1 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/57414bd14950858020832e058d5df0e476472075 differ diff --git a/external/boringssl/fuzz/client_corpus/574b435b4ef7de4bcd68e660cb470bbdc66e374a b/external/boringssl/fuzz/client_corpus/574b435b4ef7de4bcd68e660cb470bbdc66e374a new file mode 100644 index 0000000000..9c51b7f8b4 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/574b435b4ef7de4bcd68e660cb470bbdc66e374a differ diff --git a/external/boringssl/fuzz/client_corpus/5754da205d9819c7ea49216be19802eee8e753a0 b/external/boringssl/fuzz/client_corpus/5754da205d9819c7ea49216be19802eee8e753a0 new file mode 100644 index 0000000000..e83502d179 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/5754da205d9819c7ea49216be19802eee8e753a0 differ diff --git a/external/boringssl/fuzz/client_corpus/57a964488d1e20c8533345f23beb1c5c9e01d449 b/external/boringssl/fuzz/client_corpus/57a964488d1e20c8533345f23beb1c5c9e01d449 new file mode 100644 index 0000000000..f4d35f2a40 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/57a964488d1e20c8533345f23beb1c5c9e01d449 differ diff --git a/external/boringssl/fuzz/client_corpus/57bb13e7806ca27917172cc30594672f9ba207b9 b/external/boringssl/fuzz/client_corpus/57bb13e7806ca27917172cc30594672f9ba207b9 new file mode 100644 index 0000000000..1d3d292caf Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/57bb13e7806ca27917172cc30594672f9ba207b9 differ diff --git a/external/boringssl/fuzz/client_corpus/57c5d916bf10fdd126c0e96c1069369905b58cf2 b/external/boringssl/fuzz/client_corpus/57c5d916bf10fdd126c0e96c1069369905b58cf2 new file mode 100644 index 0000000000..c8cfb3bc8f Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/57c5d916bf10fdd126c0e96c1069369905b58cf2 differ diff --git a/external/boringssl/fuzz/client_corpus/583bba681bfd0c4f7716a1ce2d20c32dfe564d4c b/external/boringssl/fuzz/client_corpus/583bba681bfd0c4f7716a1ce2d20c32dfe564d4c new file mode 100644 index 0000000000..23eac38ffd Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/583bba681bfd0c4f7716a1ce2d20c32dfe564d4c differ diff --git a/external/boringssl/fuzz/client_corpus/58cac50fb8d0c0a7fd30fea7c8f4b6eeb618604d b/external/boringssl/fuzz/client_corpus/58cac50fb8d0c0a7fd30fea7c8f4b6eeb618604d new file mode 100644 index 0000000000..a75e70fc2e Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/58cac50fb8d0c0a7fd30fea7c8f4b6eeb618604d differ diff --git a/external/boringssl/fuzz/client_corpus/596704f5b04744871e34207f99222293839ff87a b/external/boringssl/fuzz/client_corpus/596704f5b04744871e34207f99222293839ff87a new file mode 100644 index 0000000000..b3ea299d84 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/596704f5b04744871e34207f99222293839ff87a differ diff --git a/external/boringssl/fuzz/client_corpus/59ef60353ba39b1bc59b5a2b514d4a0ebce56a86 b/external/boringssl/fuzz/client_corpus/59ef60353ba39b1bc59b5a2b514d4a0ebce56a86 new file mode 100644 index 0000000000..ead2fcde95 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/59ef60353ba39b1bc59b5a2b514d4a0ebce56a86 differ diff --git a/external/boringssl/fuzz/client_corpus/5a20733c310f3909b5a809efb0f46a8b5feae47a b/external/boringssl/fuzz/client_corpus/5a20733c310f3909b5a809efb0f46a8b5feae47a new file mode 100644 index 0000000000..833ae210e1 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/5a20733c310f3909b5a809efb0f46a8b5feae47a differ diff --git a/external/boringssl/fuzz/client_corpus/5a48db5a7daaf524abc694cd705d254a67422dd5 b/external/boringssl/fuzz/client_corpus/5a48db5a7daaf524abc694cd705d254a67422dd5 new file mode 100644 index 0000000000..1f792c6d90 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/5a48db5a7daaf524abc694cd705d254a67422dd5 differ diff --git a/external/boringssl/fuzz/client_corpus/5a82000383e9b7b54a845b59252c45b3d5e033fa b/external/boringssl/fuzz/client_corpus/5a82000383e9b7b54a845b59252c45b3d5e033fa new file mode 100644 index 0000000000..25b740a1ca Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/5a82000383e9b7b54a845b59252c45b3d5e033fa differ diff --git a/external/boringssl/fuzz/client_corpus/5aeb1c91ca68e775203bad56f26fd8674dc99fd2 b/external/boringssl/fuzz/client_corpus/5aeb1c91ca68e775203bad56f26fd8674dc99fd2 new file mode 100644 index 0000000000..4dd8b7c6b7 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/5aeb1c91ca68e775203bad56f26fd8674dc99fd2 differ diff --git a/external/boringssl/fuzz/client_corpus/5b74d4da2178f677bcbd74fff58b81d340f92e6f b/external/boringssl/fuzz/client_corpus/5b74d4da2178f677bcbd74fff58b81d340f92e6f new file mode 100644 index 0000000000..b2f3d05490 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/5b74d4da2178f677bcbd74fff58b81d340f92e6f differ diff --git a/external/boringssl/fuzz/client_corpus/5b86351af3b24a2417c722402ebb541f59f737d0 b/external/boringssl/fuzz/client_corpus/5b86351af3b24a2417c722402ebb541f59f737d0 new file mode 100644 index 0000000000..d99c7d7f9f Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/5b86351af3b24a2417c722402ebb541f59f737d0 differ diff --git a/external/boringssl/fuzz/client_corpus/5c4163db4fc5f3a4ad2a9af3d2fb451c4e74c635 b/external/boringssl/fuzz/client_corpus/5c4163db4fc5f3a4ad2a9af3d2fb451c4e74c635 new file mode 100644 index 0000000000..2858a1a0b8 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/5c4163db4fc5f3a4ad2a9af3d2fb451c4e74c635 differ diff --git a/external/boringssl/fuzz/client_corpus/5c4fa075408244af7dd819c116c275fb3bfbb77b b/external/boringssl/fuzz/client_corpus/5c4fa075408244af7dd819c116c275fb3bfbb77b new file mode 100644 index 0000000000..6e606ca858 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/5c4fa075408244af7dd819c116c275fb3bfbb77b differ diff --git a/external/boringssl/fuzz/client_corpus/5c583e55833688cc4f7f6f425147ef3734ad269a b/external/boringssl/fuzz/client_corpus/5c583e55833688cc4f7f6f425147ef3734ad269a new file mode 100644 index 0000000000..8908dfe873 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/5c583e55833688cc4f7f6f425147ef3734ad269a differ diff --git a/external/boringssl/fuzz/client_corpus/5c843d345a3a7763930444707181aee5cd191438 b/external/boringssl/fuzz/client_corpus/5c843d345a3a7763930444707181aee5cd191438 new file mode 100644 index 0000000000..b5db104241 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/5c843d345a3a7763930444707181aee5cd191438 differ diff --git a/external/boringssl/fuzz/client_corpus/5c94616c033d0ffca7d4d5a9a21ee506af3aebae b/external/boringssl/fuzz/client_corpus/5c94616c033d0ffca7d4d5a9a21ee506af3aebae new file mode 100644 index 0000000000..8a6d25c2fa Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/5c94616c033d0ffca7d4d5a9a21ee506af3aebae differ diff --git a/external/boringssl/fuzz/client_corpus/5d7c621d353957c1f30ff0551bf103e0533ec5d7 b/external/boringssl/fuzz/client_corpus/5d7c621d353957c1f30ff0551bf103e0533ec5d7 new file mode 100644 index 0000000000..1a5d4474d1 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/5d7c621d353957c1f30ff0551bf103e0533ec5d7 differ diff --git a/external/boringssl/fuzz/client_corpus/5d88975282d86be1605186c9f9390f2a97856f5b b/external/boringssl/fuzz/client_corpus/5d88975282d86be1605186c9f9390f2a97856f5b new file mode 100644 index 0000000000..0f2a1a2a9e Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/5d88975282d86be1605186c9f9390f2a97856f5b differ diff --git a/external/boringssl/fuzz/client_corpus/5dcf69ec2d27aa65a270aa75b893bfa843379c3a b/external/boringssl/fuzz/client_corpus/5dcf69ec2d27aa65a270aa75b893bfa843379c3a new file mode 100644 index 0000000000..d618dcb6ff Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/5dcf69ec2d27aa65a270aa75b893bfa843379c3a differ diff --git a/external/boringssl/fuzz/client_corpus/5e196581924d733f8faa3d3619453aa01e3700f3 b/external/boringssl/fuzz/client_corpus/5e196581924d733f8faa3d3619453aa01e3700f3 new file mode 100644 index 0000000000..307cccadb6 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/5e196581924d733f8faa3d3619453aa01e3700f3 differ diff --git a/external/boringssl/fuzz/client_corpus/5e513e23df48329990ed63dc6310e820b21500fb b/external/boringssl/fuzz/client_corpus/5e513e23df48329990ed63dc6310e820b21500fb new file mode 100644 index 0000000000..f404255438 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/5e513e23df48329990ed63dc6310e820b21500fb differ diff --git a/external/boringssl/fuzz/client_corpus/5e541fdc01b0b57e4f642af19a8dcada95fc7af6 b/external/boringssl/fuzz/client_corpus/5e541fdc01b0b57e4f642af19a8dcada95fc7af6 new file mode 100644 index 0000000000..a3ce21522d Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/5e541fdc01b0b57e4f642af19a8dcada95fc7af6 differ diff --git a/external/boringssl/fuzz/client_corpus/5e84e44562a78a2ac27ff90e26bcc5a33835e331 b/external/boringssl/fuzz/client_corpus/5e84e44562a78a2ac27ff90e26bcc5a33835e331 new file mode 100644 index 0000000000..8bd49e6b76 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/5e84e44562a78a2ac27ff90e26bcc5a33835e331 differ diff --git a/external/boringssl/fuzz/client_corpus/5ecd7fa21205cd75112a2182955dc33dc1befd28 b/external/boringssl/fuzz/client_corpus/5ecd7fa21205cd75112a2182955dc33dc1befd28 new file mode 100644 index 0000000000..a720c7aa56 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/5ecd7fa21205cd75112a2182955dc33dc1befd28 differ diff --git a/external/boringssl/fuzz/client_corpus/5f2456ab7aa81a53b89e0af7455db660c54ac925 b/external/boringssl/fuzz/client_corpus/5f2456ab7aa81a53b89e0af7455db660c54ac925 new file mode 100644 index 0000000000..512e6e6618 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/5f2456ab7aa81a53b89e0af7455db660c54ac925 differ diff --git a/external/boringssl/fuzz/client_corpus/5f3f171c9d7370fc11a2d31925bfec08286dbaf5 b/external/boringssl/fuzz/client_corpus/5f3f171c9d7370fc11a2d31925bfec08286dbaf5 new file mode 100644 index 0000000000..95774804ed Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/5f3f171c9d7370fc11a2d31925bfec08286dbaf5 differ diff --git a/external/boringssl/fuzz/client_corpus/5fd69dd2daac7ec11fa9bc6789263ab658a5eabe b/external/boringssl/fuzz/client_corpus/5fd69dd2daac7ec11fa9bc6789263ab658a5eabe new file mode 100644 index 0000000000..aa3ca3961f Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/5fd69dd2daac7ec11fa9bc6789263ab658a5eabe differ diff --git a/external/boringssl/fuzz/client_corpus/6163978844f3de0ffe06c5da0d2ac19d93a1a34b b/external/boringssl/fuzz/client_corpus/6163978844f3de0ffe06c5da0d2ac19d93a1a34b new file mode 100644 index 0000000000..282fce40f4 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/6163978844f3de0ffe06c5da0d2ac19d93a1a34b differ diff --git a/external/boringssl/fuzz/client_corpus/6173cc33be71450af930872b0029d42f7f9a9e4b b/external/boringssl/fuzz/client_corpus/6173cc33be71450af930872b0029d42f7f9a9e4b new file mode 100644 index 0000000000..f74042448b Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/6173cc33be71450af930872b0029d42f7f9a9e4b differ diff --git a/external/boringssl/fuzz/client_corpus/61e69397b08eef12ef32859936989b57525f163e b/external/boringssl/fuzz/client_corpus/61e69397b08eef12ef32859936989b57525f163e new file mode 100644 index 0000000000..ca3065a95d Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/61e69397b08eef12ef32859936989b57525f163e differ diff --git a/external/boringssl/fuzz/client_corpus/624cdac358ae1bfd8fe7ee1c42c7ac79a549d78c b/external/boringssl/fuzz/client_corpus/624cdac358ae1bfd8fe7ee1c42c7ac79a549d78c new file mode 100644 index 0000000000..c392c86f93 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/624cdac358ae1bfd8fe7ee1c42c7ac79a549d78c differ diff --git a/external/boringssl/fuzz/client_corpus/624e7bf21953e5ad0f95669086842161f2f86e03 b/external/boringssl/fuzz/client_corpus/624e7bf21953e5ad0f95669086842161f2f86e03 new file mode 100644 index 0000000000..429ab1e4e0 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/624e7bf21953e5ad0f95669086842161f2f86e03 differ diff --git a/external/boringssl/fuzz/client_corpus/6264654e1126813ba22fb14a3be0752b488fd418 b/external/boringssl/fuzz/client_corpus/6264654e1126813ba22fb14a3be0752b488fd418 new file mode 100644 index 0000000000..9d367a8a69 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/6264654e1126813ba22fb14a3be0752b488fd418 differ diff --git a/external/boringssl/fuzz/client_corpus/6276b4e7495a620b384250f61dd5264698cc0a08 b/external/boringssl/fuzz/client_corpus/6276b4e7495a620b384250f61dd5264698cc0a08 new file mode 100644 index 0000000000..e02b353f73 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/6276b4e7495a620b384250f61dd5264698cc0a08 differ diff --git a/external/boringssl/fuzz/client_corpus/62a932027da8c0b8ab694b888aa2050de3883343 b/external/boringssl/fuzz/client_corpus/62a932027da8c0b8ab694b888aa2050de3883343 new file mode 100644 index 0000000000..1ee9c45941 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/62a932027da8c0b8ab694b888aa2050de3883343 differ diff --git a/external/boringssl/fuzz/client_corpus/62ac547e0a1d58293db58e3f3c23505b08029e56 b/external/boringssl/fuzz/client_corpus/62ac547e0a1d58293db58e3f3c23505b08029e56 new file mode 100644 index 0000000000..ea091552a5 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/62ac547e0a1d58293db58e3f3c23505b08029e56 differ diff --git a/external/boringssl/fuzz/client_corpus/62b7b6dde6cac1830d8d1b64c3ff146cc9ee909c b/external/boringssl/fuzz/client_corpus/62b7b6dde6cac1830d8d1b64c3ff146cc9ee909c new file mode 100644 index 0000000000..4d472fceb5 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/62b7b6dde6cac1830d8d1b64c3ff146cc9ee909c differ diff --git a/external/boringssl/fuzz/client_corpus/63d2f2cd51b3851f6e2f115a717b5da3bed6dc5a b/external/boringssl/fuzz/client_corpus/63d2f2cd51b3851f6e2f115a717b5da3bed6dc5a new file mode 100644 index 0000000000..396d0be2af Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/63d2f2cd51b3851f6e2f115a717b5da3bed6dc5a differ diff --git a/external/boringssl/fuzz/client_corpus/64382d709a4f6a87cb58fcccc0ad716207d409b6 b/external/boringssl/fuzz/client_corpus/64382d709a4f6a87cb58fcccc0ad716207d409b6 new file mode 100644 index 0000000000..d89447b28f Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/64382d709a4f6a87cb58fcccc0ad716207d409b6 differ diff --git a/external/boringssl/fuzz/client_corpus/64a109fad628c758f34cb85efb00dca77826b9f6 b/external/boringssl/fuzz/client_corpus/64a109fad628c758f34cb85efb00dca77826b9f6 new file mode 100644 index 0000000000..397a811f86 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/64a109fad628c758f34cb85efb00dca77826b9f6 differ diff --git a/external/boringssl/fuzz/client_corpus/64d2d203ec77b22c80b0587a19bd157f609408b9 b/external/boringssl/fuzz/client_corpus/64d2d203ec77b22c80b0587a19bd157f609408b9 new file mode 100644 index 0000000000..c72a093aab Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/64d2d203ec77b22c80b0587a19bd157f609408b9 differ diff --git a/external/boringssl/fuzz/client_corpus/650d6182ce2b79795477071a5edf71e5e4a2d9af b/external/boringssl/fuzz/client_corpus/650d6182ce2b79795477071a5edf71e5e4a2d9af new file mode 100644 index 0000000000..1a9e4db32b Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/650d6182ce2b79795477071a5edf71e5e4a2d9af differ diff --git a/external/boringssl/fuzz/client_corpus/65232590b25ceebb4287ca8108142578ff4e341a b/external/boringssl/fuzz/client_corpus/65232590b25ceebb4287ca8108142578ff4e341a new file mode 100644 index 0000000000..24d03e8229 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/65232590b25ceebb4287ca8108142578ff4e341a differ diff --git a/external/boringssl/fuzz/client_corpus/6539b554ad60eeffa97fa4024d2ee8dac1800a7d b/external/boringssl/fuzz/client_corpus/6539b554ad60eeffa97fa4024d2ee8dac1800a7d new file mode 100644 index 0000000000..565c28c573 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/6539b554ad60eeffa97fa4024d2ee8dac1800a7d differ diff --git a/external/boringssl/fuzz/client_corpus/65b1680687a0ba3ba4d53917b4a07a22f2b45caa b/external/boringssl/fuzz/client_corpus/65b1680687a0ba3ba4d53917b4a07a22f2b45caa new file mode 100644 index 0000000000..f337ba0693 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/65b1680687a0ba3ba4d53917b4a07a22f2b45caa differ diff --git a/external/boringssl/fuzz/client_corpus/65d29e0e9f26b5a95f68c3c8bb7d52b7baad2561 b/external/boringssl/fuzz/client_corpus/65d29e0e9f26b5a95f68c3c8bb7d52b7baad2561 new file mode 100644 index 0000000000..157cff566e Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/65d29e0e9f26b5a95f68c3c8bb7d52b7baad2561 differ diff --git a/external/boringssl/fuzz/client_corpus/665c6dc07ff4414425a77a786be26280af20851a b/external/boringssl/fuzz/client_corpus/665c6dc07ff4414425a77a786be26280af20851a new file mode 100644 index 0000000000..3fa3f28853 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/665c6dc07ff4414425a77a786be26280af20851a differ diff --git a/external/boringssl/fuzz/client_corpus/6682e09c97ef156e808ad63e3a5dd9030146153a b/external/boringssl/fuzz/client_corpus/6682e09c97ef156e808ad63e3a5dd9030146153a new file mode 100644 index 0000000000..57d4ee33b6 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/6682e09c97ef156e808ad63e3a5dd9030146153a differ diff --git a/external/boringssl/fuzz/client_corpus/669dfafe89414c0056ffa214d4ef4c1405d01c6b b/external/boringssl/fuzz/client_corpus/669dfafe89414c0056ffa214d4ef4c1405d01c6b new file mode 100644 index 0000000000..ed97090220 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/669dfafe89414c0056ffa214d4ef4c1405d01c6b differ diff --git a/external/boringssl/fuzz/client_corpus/66ea20db9af412114e60b20143b063643ac0209f b/external/boringssl/fuzz/client_corpus/66ea20db9af412114e60b20143b063643ac0209f new file mode 100644 index 0000000000..a041547678 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/66ea20db9af412114e60b20143b063643ac0209f differ diff --git a/external/boringssl/fuzz/client_corpus/67201a0dcd94ff51530eaf8d43982203d8cc3613 b/external/boringssl/fuzz/client_corpus/67201a0dcd94ff51530eaf8d43982203d8cc3613 new file mode 100644 index 0000000000..569ccf814e Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/67201a0dcd94ff51530eaf8d43982203d8cc3613 differ diff --git a/external/boringssl/fuzz/client_corpus/67740cc59121af29e2b57f491c6dfaf9e54a16f2 b/external/boringssl/fuzz/client_corpus/67740cc59121af29e2b57f491c6dfaf9e54a16f2 new file mode 100644 index 0000000000..92195afa47 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/67740cc59121af29e2b57f491c6dfaf9e54a16f2 differ diff --git a/external/boringssl/fuzz/client_corpus/67c56ee635a2f54a05120f7f741b6de3b8416545 b/external/boringssl/fuzz/client_corpus/67c56ee635a2f54a05120f7f741b6de3b8416545 new file mode 100644 index 0000000000..1f82642bd3 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/67c56ee635a2f54a05120f7f741b6de3b8416545 differ diff --git a/external/boringssl/fuzz/client_corpus/67ec3a092c013c1901c6056982c4b3c2d4345b12 b/external/boringssl/fuzz/client_corpus/67ec3a092c013c1901c6056982c4b3c2d4345b12 new file mode 100644 index 0000000000..03fb0d03e7 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/67ec3a092c013c1901c6056982c4b3c2d4345b12 differ diff --git a/external/boringssl/fuzz/client_corpus/681a06e9ae918b77088a6c41e2084a7065fb4a80 b/external/boringssl/fuzz/client_corpus/681a06e9ae918b77088a6c41e2084a7065fb4a80 new file mode 100644 index 0000000000..d17b0978ee Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/681a06e9ae918b77088a6c41e2084a7065fb4a80 differ diff --git a/external/boringssl/fuzz/client_corpus/68d08ed34adbab401519c4a6b457edf839a8e11b b/external/boringssl/fuzz/client_corpus/68d08ed34adbab401519c4a6b457edf839a8e11b new file mode 100644 index 0000000000..5b40dfce9c Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/68d08ed34adbab401519c4a6b457edf839a8e11b differ diff --git a/external/boringssl/fuzz/client_corpus/692e389e27b91478ee30ab6966720c8e42198b62 b/external/boringssl/fuzz/client_corpus/692e389e27b91478ee30ab6966720c8e42198b62 new file mode 100644 index 0000000000..a378c89bf9 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/692e389e27b91478ee30ab6966720c8e42198b62 differ diff --git a/external/boringssl/fuzz/client_corpus/69301c0fab85b8afd0c235a97125acb36f259277 b/external/boringssl/fuzz/client_corpus/69301c0fab85b8afd0c235a97125acb36f259277 new file mode 100644 index 0000000000..dc78ff9eaf Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/69301c0fab85b8afd0c235a97125acb36f259277 differ diff --git a/external/boringssl/fuzz/client_corpus/693212f1a1e378e4020ee13126b4ee8df4ce9262 b/external/boringssl/fuzz/client_corpus/693212f1a1e378e4020ee13126b4ee8df4ce9262 new file mode 100644 index 0000000000..c153fc46d4 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/693212f1a1e378e4020ee13126b4ee8df4ce9262 differ diff --git a/external/boringssl/fuzz/client_corpus/693a6ddbf67b0835d90ca231b9d68d9f2cccffbd b/external/boringssl/fuzz/client_corpus/693a6ddbf67b0835d90ca231b9d68d9f2cccffbd new file mode 100644 index 0000000000..86e8e6e6d4 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/693a6ddbf67b0835d90ca231b9d68d9f2cccffbd differ diff --git a/external/boringssl/fuzz/client_corpus/695cb65aafb76161e3a319c68d4430ee80985b81 b/external/boringssl/fuzz/client_corpus/695cb65aafb76161e3a319c68d4430ee80985b81 new file mode 100644 index 0000000000..2a4348d9d5 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/695cb65aafb76161e3a319c68d4430ee80985b81 differ diff --git a/external/boringssl/fuzz/client_corpus/69a10fd0965617fda08b1ff2bf80999a51b8960a b/external/boringssl/fuzz/client_corpus/69a10fd0965617fda08b1ff2bf80999a51b8960a new file mode 100644 index 0000000000..f843b13f6a Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/69a10fd0965617fda08b1ff2bf80999a51b8960a differ diff --git a/external/boringssl/fuzz/client_corpus/6a09a081020b1d5bdad5c981af10066d4ed4b045 b/external/boringssl/fuzz/client_corpus/6a09a081020b1d5bdad5c981af10066d4ed4b045 new file mode 100644 index 0000000000..10c3223992 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/6a09a081020b1d5bdad5c981af10066d4ed4b045 differ diff --git a/external/boringssl/fuzz/client_corpus/6a4404e833ba7eef96eec09b54978858661acecf b/external/boringssl/fuzz/client_corpus/6a4404e833ba7eef96eec09b54978858661acecf new file mode 100644 index 0000000000..88ddabdf4d Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/6a4404e833ba7eef96eec09b54978858661acecf differ diff --git a/external/boringssl/fuzz/client_corpus/6a5e936ffd7eba1efe6b7aa54b5beff373272822 b/external/boringssl/fuzz/client_corpus/6a5e936ffd7eba1efe6b7aa54b5beff373272822 new file mode 100644 index 0000000000..a3b3cbe631 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/6a5e936ffd7eba1efe6b7aa54b5beff373272822 differ diff --git a/external/boringssl/fuzz/client_corpus/6a75638c3215e638e82bbc28c3fc523bda75f312 b/external/boringssl/fuzz/client_corpus/6a75638c3215e638e82bbc28c3fc523bda75f312 new file mode 100644 index 0000000000..c8adab108d Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/6a75638c3215e638e82bbc28c3fc523bda75f312 differ diff --git a/external/boringssl/fuzz/client_corpus/6adf7477d929629afb4d07b4518a0e23b301b232 b/external/boringssl/fuzz/client_corpus/6adf7477d929629afb4d07b4518a0e23b301b232 new file mode 100644 index 0000000000..f5b84b9535 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/6adf7477d929629afb4d07b4518a0e23b301b232 differ diff --git a/external/boringssl/fuzz/client_corpus/6bbd392cd841bb74dbba1190cab5066d5ecd9b2e b/external/boringssl/fuzz/client_corpus/6bbd392cd841bb74dbba1190cab5066d5ecd9b2e new file mode 100644 index 0000000000..d8eae63633 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/6bbd392cd841bb74dbba1190cab5066d5ecd9b2e differ diff --git a/external/boringssl/fuzz/client_corpus/6bdc8def26589304a945125ceb8bcb15b55d463b b/external/boringssl/fuzz/client_corpus/6bdc8def26589304a945125ceb8bcb15b55d463b new file mode 100644 index 0000000000..fdb0dd9cfc Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/6bdc8def26589304a945125ceb8bcb15b55d463b differ diff --git a/external/boringssl/fuzz/client_corpus/6c55036b8922e6b076ca36b92afa11601625e5af b/external/boringssl/fuzz/client_corpus/6c55036b8922e6b076ca36b92afa11601625e5af new file mode 100644 index 0000000000..7908617e6c Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/6c55036b8922e6b076ca36b92afa11601625e5af differ diff --git a/external/boringssl/fuzz/client_corpus/6c630175c87c742ab0c8723f6a0a53aae43b974e b/external/boringssl/fuzz/client_corpus/6c630175c87c742ab0c8723f6a0a53aae43b974e new file mode 100644 index 0000000000..323e1dc110 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/6c630175c87c742ab0c8723f6a0a53aae43b974e differ diff --git a/external/boringssl/fuzz/client_corpus/6c651672e43ef4440abd90b3e6e1dd0a32e97437 b/external/boringssl/fuzz/client_corpus/6c651672e43ef4440abd90b3e6e1dd0a32e97437 new file mode 100644 index 0000000000..6914973371 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/6c651672e43ef4440abd90b3e6e1dd0a32e97437 differ diff --git a/external/boringssl/fuzz/client_corpus/6cb141671c7744c225aa3f7ce0e9813ae01f2a2b b/external/boringssl/fuzz/client_corpus/6cb141671c7744c225aa3f7ce0e9813ae01f2a2b new file mode 100644 index 0000000000..602f404b3e Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/6cb141671c7744c225aa3f7ce0e9813ae01f2a2b differ diff --git a/external/boringssl/fuzz/client_corpus/6cbd0fd179a77260e246c45f424a769b951363df b/external/boringssl/fuzz/client_corpus/6cbd0fd179a77260e246c45f424a769b951363df new file mode 100644 index 0000000000..30776e991f Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/6cbd0fd179a77260e246c45f424a769b951363df differ diff --git a/external/boringssl/fuzz/client_corpus/6cdbc5f074be9de313240590e337c7733f3bcb5a b/external/boringssl/fuzz/client_corpus/6cdbc5f074be9de313240590e337c7733f3bcb5a new file mode 100644 index 0000000000..b6dbf0fffb Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/6cdbc5f074be9de313240590e337c7733f3bcb5a differ diff --git a/external/boringssl/fuzz/client_corpus/6d6212a5e12e69903e45291526bc0ecd3ea0e6f5 b/external/boringssl/fuzz/client_corpus/6d6212a5e12e69903e45291526bc0ecd3ea0e6f5 new file mode 100644 index 0000000000..1ad4d80019 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/6d6212a5e12e69903e45291526bc0ecd3ea0e6f5 differ diff --git a/external/boringssl/fuzz/client_corpus/6d7de8f65158095884723fb0b1a4dd9bb1e4bcad b/external/boringssl/fuzz/client_corpus/6d7de8f65158095884723fb0b1a4dd9bb1e4bcad new file mode 100644 index 0000000000..d7fa9cfe09 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/6d7de8f65158095884723fb0b1a4dd9bb1e4bcad differ diff --git a/external/boringssl/fuzz/client_corpus/6ed3b3793181c3319bacd290bc05190cfd944eec b/external/boringssl/fuzz/client_corpus/6ed3b3793181c3319bacd290bc05190cfd944eec new file mode 100644 index 0000000000..431a77b894 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/6ed3b3793181c3319bacd290bc05190cfd944eec differ diff --git a/external/boringssl/fuzz/client_corpus/6efd3899822aa131578394f89fb5c8fd17d14771 b/external/boringssl/fuzz/client_corpus/6efd3899822aa131578394f89fb5c8fd17d14771 new file mode 100644 index 0000000000..013cadca92 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/6efd3899822aa131578394f89fb5c8fd17d14771 differ diff --git a/external/boringssl/fuzz/client_corpus/6f2c69f7cc2c99cb694c37710c7b46104906aff7 b/external/boringssl/fuzz/client_corpus/6f2c69f7cc2c99cb694c37710c7b46104906aff7 new file mode 100644 index 0000000000..41b11c3f27 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/6f2c69f7cc2c99cb694c37710c7b46104906aff7 differ diff --git a/external/boringssl/fuzz/client_corpus/709b1199449d8138c4936b95179ba12fbb9a68d5 b/external/boringssl/fuzz/client_corpus/709b1199449d8138c4936b95179ba12fbb9a68d5 new file mode 100644 index 0000000000..bf76455883 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/709b1199449d8138c4936b95179ba12fbb9a68d5 differ diff --git a/external/boringssl/fuzz/client_corpus/71050f1658866c73590296856c498f54087519cc b/external/boringssl/fuzz/client_corpus/71050f1658866c73590296856c498f54087519cc new file mode 100644 index 0000000000..227a07b230 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/71050f1658866c73590296856c498f54087519cc differ diff --git a/external/boringssl/fuzz/client_corpus/71432178fa30339f80d4fe0b95ca40886ea4b864 b/external/boringssl/fuzz/client_corpus/71432178fa30339f80d4fe0b95ca40886ea4b864 new file mode 100644 index 0000000000..a26d494f64 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/71432178fa30339f80d4fe0b95ca40886ea4b864 differ diff --git a/external/boringssl/fuzz/client_corpus/715f569f1599e0fec12773fec26c7cc3cddbec4a b/external/boringssl/fuzz/client_corpus/715f569f1599e0fec12773fec26c7cc3cddbec4a new file mode 100644 index 0000000000..8f10bcc283 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/715f569f1599e0fec12773fec26c7cc3cddbec4a differ diff --git a/external/boringssl/fuzz/client_corpus/7166e8b36a98dc10904f0a92bee9c729ef454388 b/external/boringssl/fuzz/client_corpus/7166e8b36a98dc10904f0a92bee9c729ef454388 new file mode 100644 index 0000000000..124420725d Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/7166e8b36a98dc10904f0a92bee9c729ef454388 differ diff --git a/external/boringssl/fuzz/client_corpus/716737b5ca18f7589bdc492806e84bafbf7822e1 b/external/boringssl/fuzz/client_corpus/716737b5ca18f7589bdc492806e84bafbf7822e1 new file mode 100644 index 0000000000..ca083559ec Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/716737b5ca18f7589bdc492806e84bafbf7822e1 differ diff --git a/external/boringssl/fuzz/client_corpus/71983e3b061a3211f83e36cccaf8be3d61e3ade7 b/external/boringssl/fuzz/client_corpus/71983e3b061a3211f83e36cccaf8be3d61e3ade7 new file mode 100644 index 0000000000..b942cd1403 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/71983e3b061a3211f83e36cccaf8be3d61e3ade7 differ diff --git a/external/boringssl/fuzz/client_corpus/725174c7260ca145c5513b1f8277581ad80d8066 b/external/boringssl/fuzz/client_corpus/725174c7260ca145c5513b1f8277581ad80d8066 new file mode 100644 index 0000000000..a62786d4a1 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/725174c7260ca145c5513b1f8277581ad80d8066 differ diff --git a/external/boringssl/fuzz/client_corpus/7268bdfc00cc1a2c768d4c9c13cca51538d3f6e2 b/external/boringssl/fuzz/client_corpus/7268bdfc00cc1a2c768d4c9c13cca51538d3f6e2 new file mode 100644 index 0000000000..723da2ba0a Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/7268bdfc00cc1a2c768d4c9c13cca51538d3f6e2 differ diff --git a/external/boringssl/fuzz/client_corpus/7312c2e60d9d48602429f06752f2c1856b2484a4 b/external/boringssl/fuzz/client_corpus/7312c2e60d9d48602429f06752f2c1856b2484a4 new file mode 100644 index 0000000000..301ae4bee3 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/7312c2e60d9d48602429f06752f2c1856b2484a4 differ diff --git a/external/boringssl/fuzz/client_corpus/73641c2c728554997a9a97544e207a235111d14b b/external/boringssl/fuzz/client_corpus/73641c2c728554997a9a97544e207a235111d14b new file mode 100644 index 0000000000..3af5fc4b7b Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/73641c2c728554997a9a97544e207a235111d14b differ diff --git a/external/boringssl/fuzz/client_corpus/73786b6e81d47e740623eb11e031c685c239d8e5 b/external/boringssl/fuzz/client_corpus/73786b6e81d47e740623eb11e031c685c239d8e5 new file mode 100644 index 0000000000..c140b5ef13 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/73786b6e81d47e740623eb11e031c685c239d8e5 differ diff --git a/external/boringssl/fuzz/client_corpus/73f63d7db6fb57a25e5f47a004e6f24eb66e685e b/external/boringssl/fuzz/client_corpus/73f63d7db6fb57a25e5f47a004e6f24eb66e685e new file mode 100644 index 0000000000..55f3a15b82 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/73f63d7db6fb57a25e5f47a004e6f24eb66e685e differ diff --git a/external/boringssl/fuzz/client_corpus/7454f672d5cea5dade5e712090b552ca39a3cbe0 b/external/boringssl/fuzz/client_corpus/7454f672d5cea5dade5e712090b552ca39a3cbe0 new file mode 100644 index 0000000000..5ee48c8a0d Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/7454f672d5cea5dade5e712090b552ca39a3cbe0 differ diff --git a/external/boringssl/fuzz/client_corpus/745e5941c0812aa48b525e64969d6960c3f86d6c b/external/boringssl/fuzz/client_corpus/745e5941c0812aa48b525e64969d6960c3f86d6c new file mode 100644 index 0000000000..40bc21192e Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/745e5941c0812aa48b525e64969d6960c3f86d6c differ diff --git a/external/boringssl/fuzz/client_corpus/7460a3a91f807e0c47725fe6d856219c9b1a3f43 b/external/boringssl/fuzz/client_corpus/7460a3a91f807e0c47725fe6d856219c9b1a3f43 new file mode 100644 index 0000000000..51bca855c3 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/7460a3a91f807e0c47725fe6d856219c9b1a3f43 differ diff --git a/external/boringssl/fuzz/client_corpus/7492e1899d22a15452e163881437a23ccc705d45 b/external/boringssl/fuzz/client_corpus/7492e1899d22a15452e163881437a23ccc705d45 new file mode 100644 index 0000000000..0dbbd88437 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/7492e1899d22a15452e163881437a23ccc705d45 differ diff --git a/external/boringssl/fuzz/client_corpus/74f4656ef6630ddae9353e0989f10d9c8f37edb4 b/external/boringssl/fuzz/client_corpus/74f4656ef6630ddae9353e0989f10d9c8f37edb4 new file mode 100644 index 0000000000..936f18e690 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/74f4656ef6630ddae9353e0989f10d9c8f37edb4 differ diff --git a/external/boringssl/fuzz/client_corpus/750e5dd452c8bc44976eae6b99463b951cf3ed20 b/external/boringssl/fuzz/client_corpus/750e5dd452c8bc44976eae6b99463b951cf3ed20 new file mode 100644 index 0000000000..5281f5a5f5 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/750e5dd452c8bc44976eae6b99463b951cf3ed20 differ diff --git a/external/boringssl/fuzz/client_corpus/75629895fd19a7ff9492e93a6d2aae0de33b6a24 b/external/boringssl/fuzz/client_corpus/75629895fd19a7ff9492e93a6d2aae0de33b6a24 new file mode 100644 index 0000000000..c90c9241aa Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/75629895fd19a7ff9492e93a6d2aae0de33b6a24 differ diff --git a/external/boringssl/fuzz/client_corpus/75a37a2cdee4ac71d0996720b3c9adf50da186cc b/external/boringssl/fuzz/client_corpus/75a37a2cdee4ac71d0996720b3c9adf50da186cc new file mode 100644 index 0000000000..5b85fe593d Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/75a37a2cdee4ac71d0996720b3c9adf50da186cc differ diff --git a/external/boringssl/fuzz/client_corpus/7643869fe4d74ef2e262015d55ea60dc08f072b7 b/external/boringssl/fuzz/client_corpus/7643869fe4d74ef2e262015d55ea60dc08f072b7 new file mode 100644 index 0000000000..ac6e7b2cd4 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/7643869fe4d74ef2e262015d55ea60dc08f072b7 differ diff --git a/external/boringssl/fuzz/client_corpus/76ad1888b6ab0433924386fc74ec9668f08d3769 b/external/boringssl/fuzz/client_corpus/76ad1888b6ab0433924386fc74ec9668f08d3769 new file mode 100644 index 0000000000..46e8685022 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/76ad1888b6ab0433924386fc74ec9668f08d3769 differ diff --git a/external/boringssl/fuzz/client_corpus/76b77a87e73f5fd403af0cb73ad2b8bbcd572254 b/external/boringssl/fuzz/client_corpus/76b77a87e73f5fd403af0cb73ad2b8bbcd572254 new file mode 100644 index 0000000000..b03996b43b Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/76b77a87e73f5fd403af0cb73ad2b8bbcd572254 differ diff --git a/external/boringssl/fuzz/client_corpus/76f0e061914c0fe572963f0cc404d49121ec57a4 b/external/boringssl/fuzz/client_corpus/76f0e061914c0fe572963f0cc404d49121ec57a4 new file mode 100644 index 0000000000..efc7bfd87b Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/76f0e061914c0fe572963f0cc404d49121ec57a4 differ diff --git a/external/boringssl/fuzz/client_corpus/7757a4fcd5642fb0ac1f0230ced865a8546a9c29 b/external/boringssl/fuzz/client_corpus/7757a4fcd5642fb0ac1f0230ced865a8546a9c29 new file mode 100644 index 0000000000..9974766df2 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/7757a4fcd5642fb0ac1f0230ced865a8546a9c29 differ diff --git a/external/boringssl/fuzz/client_corpus/77a1114a47681f3f3cf0f65aa2f4645214b5c7c9 b/external/boringssl/fuzz/client_corpus/77a1114a47681f3f3cf0f65aa2f4645214b5c7c9 new file mode 100644 index 0000000000..21c06f6c3c Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/77a1114a47681f3f3cf0f65aa2f4645214b5c7c9 differ diff --git a/external/boringssl/fuzz/client_corpus/77aa55183550820d02557f4a09c688cfe6c2b5f6 b/external/boringssl/fuzz/client_corpus/77aa55183550820d02557f4a09c688cfe6c2b5f6 new file mode 100644 index 0000000000..7a1a684ab6 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/77aa55183550820d02557f4a09c688cfe6c2b5f6 differ diff --git a/external/boringssl/fuzz/client_corpus/78623435559dd4f83050c3a5743c0652d2b47088 b/external/boringssl/fuzz/client_corpus/78623435559dd4f83050c3a5743c0652d2b47088 new file mode 100644 index 0000000000..785e71e93a Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/78623435559dd4f83050c3a5743c0652d2b47088 differ diff --git a/external/boringssl/fuzz/client_corpus/789d5b07e2685ea9b9dec86f6d4026ac3edaf4ef b/external/boringssl/fuzz/client_corpus/789d5b07e2685ea9b9dec86f6d4026ac3edaf4ef new file mode 100644 index 0000000000..8871626fa1 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/789d5b07e2685ea9b9dec86f6d4026ac3edaf4ef differ diff --git a/external/boringssl/fuzz/client_corpus/78d330c46e50c13cae9560065fa4cc7bcac8dcb3 b/external/boringssl/fuzz/client_corpus/78d330c46e50c13cae9560065fa4cc7bcac8dcb3 new file mode 100644 index 0000000000..81f1adc190 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/78d330c46e50c13cae9560065fa4cc7bcac8dcb3 differ diff --git a/external/boringssl/fuzz/client_corpus/790ffe47b5b84c76762f6b95eb51467844ef210b b/external/boringssl/fuzz/client_corpus/790ffe47b5b84c76762f6b95eb51467844ef210b new file mode 100644 index 0000000000..ff3a16aa44 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/790ffe47b5b84c76762f6b95eb51467844ef210b differ diff --git a/external/boringssl/fuzz/client_corpus/79153550be1dc1365a10a08792f49b02a9c56c40 b/external/boringssl/fuzz/client_corpus/79153550be1dc1365a10a08792f49b02a9c56c40 new file mode 100644 index 0000000000..870a7e9f7d Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/79153550be1dc1365a10a08792f49b02a9c56c40 differ diff --git a/external/boringssl/fuzz/client_corpus/79f2cafab7df9ff93fbd71edd2049f431f478a35 b/external/boringssl/fuzz/client_corpus/79f2cafab7df9ff93fbd71edd2049f431f478a35 new file mode 100644 index 0000000000..87b443e218 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/79f2cafab7df9ff93fbd71edd2049f431f478a35 differ diff --git a/external/boringssl/fuzz/client_corpus/7a13e0426d9dbdfeb38d83eb5a51d48e5de38913 b/external/boringssl/fuzz/client_corpus/7a13e0426d9dbdfeb38d83eb5a51d48e5de38913 new file mode 100644 index 0000000000..1215f8ed26 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/7a13e0426d9dbdfeb38d83eb5a51d48e5de38913 differ diff --git a/external/boringssl/fuzz/client_corpus/7a5e12eb4b25a0c9687e38e614f062a5e74ff7d0 b/external/boringssl/fuzz/client_corpus/7a5e12eb4b25a0c9687e38e614f062a5e74ff7d0 new file mode 100644 index 0000000000..43c1687052 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/7a5e12eb4b25a0c9687e38e614f062a5e74ff7d0 differ diff --git a/external/boringssl/fuzz/client_corpus/7a7c19fbe0835087aaa22bc29bc713d825a4853b b/external/boringssl/fuzz/client_corpus/7a7c19fbe0835087aaa22bc29bc713d825a4853b new file mode 100644 index 0000000000..49a6534db8 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/7a7c19fbe0835087aaa22bc29bc713d825a4853b differ diff --git a/external/boringssl/fuzz/client_corpus/7b1989a53e27b944b1f3a71ba37b95bf65502578 b/external/boringssl/fuzz/client_corpus/7b1989a53e27b944b1f3a71ba37b95bf65502578 new file mode 100644 index 0000000000..a6e06f421b Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/7b1989a53e27b944b1f3a71ba37b95bf65502578 differ diff --git a/external/boringssl/fuzz/client_corpus/7b1fb1cf0c4afa24743bc18c43d810383ff35b5d b/external/boringssl/fuzz/client_corpus/7b1fb1cf0c4afa24743bc18c43d810383ff35b5d new file mode 100644 index 0000000000..ddd0b6c894 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/7b1fb1cf0c4afa24743bc18c43d810383ff35b5d differ diff --git a/external/boringssl/fuzz/client_corpus/7ba00c13f3af17b2f767423f969827ed237674f0 b/external/boringssl/fuzz/client_corpus/7ba00c13f3af17b2f767423f969827ed237674f0 new file mode 100644 index 0000000000..33c6c3f397 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/7ba00c13f3af17b2f767423f969827ed237674f0 differ diff --git a/external/boringssl/fuzz/client_corpus/7baeee7bae72e0d0df2d314544e7476afffd9256 b/external/boringssl/fuzz/client_corpus/7baeee7bae72e0d0df2d314544e7476afffd9256 new file mode 100644 index 0000000000..452c868e08 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/7baeee7bae72e0d0df2d314544e7476afffd9256 differ diff --git a/external/boringssl/fuzz/client_corpus/7c833d2738d69dd0303fd774e425c0da8da5b01e b/external/boringssl/fuzz/client_corpus/7c833d2738d69dd0303fd774e425c0da8da5b01e new file mode 100644 index 0000000000..bbe73a0bca Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/7c833d2738d69dd0303fd774e425c0da8da5b01e differ diff --git a/external/boringssl/fuzz/client_corpus/7cc04676ba336d7e15e837b9c7648e804b1b320d b/external/boringssl/fuzz/client_corpus/7cc04676ba336d7e15e837b9c7648e804b1b320d new file mode 100644 index 0000000000..629a978b5e Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/7cc04676ba336d7e15e837b9c7648e804b1b320d differ diff --git a/external/boringssl/fuzz/client_corpus/7cd0efd7b6d2fb98673ad3cf4b663bcefda82053 b/external/boringssl/fuzz/client_corpus/7cd0efd7b6d2fb98673ad3cf4b663bcefda82053 new file mode 100644 index 0000000000..8e15f2e79c Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/7cd0efd7b6d2fb98673ad3cf4b663bcefda82053 differ diff --git a/external/boringssl/fuzz/client_corpus/7d13671b71b0f71496a2e17bdc503826bd4d0c26 b/external/boringssl/fuzz/client_corpus/7d13671b71b0f71496a2e17bdc503826bd4d0c26 new file mode 100644 index 0000000000..8d20715cf6 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/7d13671b71b0f71496a2e17bdc503826bd4d0c26 differ diff --git a/external/boringssl/fuzz/client_corpus/7d7637cadd57353b459108088ad62bd7746fca63 b/external/boringssl/fuzz/client_corpus/7d7637cadd57353b459108088ad62bd7746fca63 new file mode 100644 index 0000000000..02e8ff55ee Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/7d7637cadd57353b459108088ad62bd7746fca63 differ diff --git a/external/boringssl/fuzz/client_corpus/7d82bcecfa30a487dd52bd4dd8461304d7d499e0 b/external/boringssl/fuzz/client_corpus/7d82bcecfa30a487dd52bd4dd8461304d7d499e0 new file mode 100644 index 0000000000..584dec8507 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/7d82bcecfa30a487dd52bd4dd8461304d7d499e0 differ diff --git a/external/boringssl/fuzz/client_corpus/7d8bfe2499bea27ee16d1dbeb1707037b99a87ba b/external/boringssl/fuzz/client_corpus/7d8bfe2499bea27ee16d1dbeb1707037b99a87ba new file mode 100644 index 0000000000..f29cd2269e Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/7d8bfe2499bea27ee16d1dbeb1707037b99a87ba differ diff --git a/external/boringssl/fuzz/client_corpus/7db2e5e257d7891667d78cb272ca3ec3b6dc044d b/external/boringssl/fuzz/client_corpus/7db2e5e257d7891667d78cb272ca3ec3b6dc044d new file mode 100644 index 0000000000..4c37ee56da Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/7db2e5e257d7891667d78cb272ca3ec3b6dc044d differ diff --git a/external/boringssl/fuzz/client_corpus/7dbb31067130270f15c56b92f50d21818e4e817b b/external/boringssl/fuzz/client_corpus/7dbb31067130270f15c56b92f50d21818e4e817b new file mode 100644 index 0000000000..5449d26189 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/7dbb31067130270f15c56b92f50d21818e4e817b differ diff --git a/external/boringssl/fuzz/client_corpus/7e1e374599e9ff2d515754b718b3e959966ac1ea b/external/boringssl/fuzz/client_corpus/7e1e374599e9ff2d515754b718b3e959966ac1ea new file mode 100644 index 0000000000..b29adf3da5 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/7e1e374599e9ff2d515754b718b3e959966ac1ea differ diff --git a/external/boringssl/fuzz/client_corpus/7ea89e4a96e2deadf8b9ca3e81d0f886dabdebfa b/external/boringssl/fuzz/client_corpus/7ea89e4a96e2deadf8b9ca3e81d0f886dabdebfa new file mode 100644 index 0000000000..a2fc83a05a Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/7ea89e4a96e2deadf8b9ca3e81d0f886dabdebfa differ diff --git a/external/boringssl/fuzz/client_corpus/7f0f43b60dbb78b847fc67e352f7ce8d0eac57ca b/external/boringssl/fuzz/client_corpus/7f0f43b60dbb78b847fc67e352f7ce8d0eac57ca new file mode 100644 index 0000000000..b27f1fa1bf Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/7f0f43b60dbb78b847fc67e352f7ce8d0eac57ca differ diff --git a/external/boringssl/fuzz/client_corpus/7f6ab5401afb02d08c34b835ce95d4f886c50a86 b/external/boringssl/fuzz/client_corpus/7f6ab5401afb02d08c34b835ce95d4f886c50a86 new file mode 100644 index 0000000000..cf2d7971f2 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/7f6ab5401afb02d08c34b835ce95d4f886c50a86 differ diff --git a/external/boringssl/fuzz/client_corpus/7fd3e12d7776e72ea2a347d1a546f4e17275e205 b/external/boringssl/fuzz/client_corpus/7fd3e12d7776e72ea2a347d1a546f4e17275e205 new file mode 100644 index 0000000000..1578b0083b Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/7fd3e12d7776e72ea2a347d1a546f4e17275e205 differ diff --git a/external/boringssl/fuzz/client_corpus/80003831f114e372c44f168f26e192100b8bc4c6 b/external/boringssl/fuzz/client_corpus/80003831f114e372c44f168f26e192100b8bc4c6 new file mode 100644 index 0000000000..f4fc7c21ab Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/80003831f114e372c44f168f26e192100b8bc4c6 differ diff --git a/external/boringssl/fuzz/client_corpus/809b64143ccfb187a639440e8a49dc061733c571 b/external/boringssl/fuzz/client_corpus/809b64143ccfb187a639440e8a49dc061733c571 new file mode 100644 index 0000000000..9f1f43272b Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/809b64143ccfb187a639440e8a49dc061733c571 differ diff --git a/external/boringssl/fuzz/client_corpus/81860583db2f2f8e3492dbe683063e2bc7c6a727 b/external/boringssl/fuzz/client_corpus/81860583db2f2f8e3492dbe683063e2bc7c6a727 new file mode 100644 index 0000000000..39b05ac91a Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/81860583db2f2f8e3492dbe683063e2bc7c6a727 differ diff --git a/external/boringssl/fuzz/client_corpus/81b11d6d83e00df6595eed84463b910f30d77270 b/external/boringssl/fuzz/client_corpus/81b11d6d83e00df6595eed84463b910f30d77270 new file mode 100644 index 0000000000..6ddbde5e58 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/81b11d6d83e00df6595eed84463b910f30d77270 differ diff --git a/external/boringssl/fuzz/client_corpus/81d289fdfa9a0ae60dcbe3b67db2b33db6159a62 b/external/boringssl/fuzz/client_corpus/81d289fdfa9a0ae60dcbe3b67db2b33db6159a62 new file mode 100644 index 0000000000..4e4acbe82f Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/81d289fdfa9a0ae60dcbe3b67db2b33db6159a62 differ diff --git a/external/boringssl/fuzz/client_corpus/81df12ca53a2432e288b18c6c00af52b8769182d b/external/boringssl/fuzz/client_corpus/81df12ca53a2432e288b18c6c00af52b8769182d new file mode 100644 index 0000000000..3878eb4660 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/81df12ca53a2432e288b18c6c00af52b8769182d differ diff --git a/external/boringssl/fuzz/client_corpus/821820b20f0fbbe3a958e4b9ab2a13e958a7e3e8 b/external/boringssl/fuzz/client_corpus/821820b20f0fbbe3a958e4b9ab2a13e958a7e3e8 new file mode 100644 index 0000000000..037f23dbc3 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/821820b20f0fbbe3a958e4b9ab2a13e958a7e3e8 differ diff --git a/external/boringssl/fuzz/client_corpus/822f3b140b0934e8e0263f1dd2c6f1527c06df1f b/external/boringssl/fuzz/client_corpus/822f3b140b0934e8e0263f1dd2c6f1527c06df1f new file mode 100644 index 0000000000..2db2a5089c Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/822f3b140b0934e8e0263f1dd2c6f1527c06df1f differ diff --git a/external/boringssl/fuzz/client_corpus/8259b1524f55bc4cb4f365ab450cbe984e494116 b/external/boringssl/fuzz/client_corpus/8259b1524f55bc4cb4f365ab450cbe984e494116 new file mode 100644 index 0000000000..b668fe63a1 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/8259b1524f55bc4cb4f365ab450cbe984e494116 differ diff --git a/external/boringssl/fuzz/client_corpus/82a1464e8df650fa1f2e4943d31904f6c266741c b/external/boringssl/fuzz/client_corpus/82a1464e8df650fa1f2e4943d31904f6c266741c new file mode 100644 index 0000000000..1c10e57416 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/82a1464e8df650fa1f2e4943d31904f6c266741c differ diff --git a/external/boringssl/fuzz/client_corpus/8305e70211c7966e15cc56bd12625ecb5f156ce3 b/external/boringssl/fuzz/client_corpus/8305e70211c7966e15cc56bd12625ecb5f156ce3 new file mode 100644 index 0000000000..a87e7858ac Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/8305e70211c7966e15cc56bd12625ecb5f156ce3 differ diff --git a/external/boringssl/fuzz/client_corpus/8368d8b0cdaaba63b4183434b0a42567b4baca1a b/external/boringssl/fuzz/client_corpus/8368d8b0cdaaba63b4183434b0a42567b4baca1a new file mode 100644 index 0000000000..5c0c37aa03 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/8368d8b0cdaaba63b4183434b0a42567b4baca1a differ diff --git a/external/boringssl/fuzz/client_corpus/83cf3abf757469e3f081bf0714766a1d603dc2d0 b/external/boringssl/fuzz/client_corpus/83cf3abf757469e3f081bf0714766a1d603dc2d0 new file mode 100644 index 0000000000..f7142e181f Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/83cf3abf757469e3f081bf0714766a1d603dc2d0 differ diff --git a/external/boringssl/fuzz/client_corpus/83edd983c9817e0bd1a5613acab9ee0329bff86b b/external/boringssl/fuzz/client_corpus/83edd983c9817e0bd1a5613acab9ee0329bff86b new file mode 100644 index 0000000000..0f4e55dabe Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/83edd983c9817e0bd1a5613acab9ee0329bff86b differ diff --git a/external/boringssl/fuzz/client_corpus/84f9f1c8cf176949f562f077a36b81adbf8a2a1d b/external/boringssl/fuzz/client_corpus/84f9f1c8cf176949f562f077a36b81adbf8a2a1d new file mode 100644 index 0000000000..4f130bc2a0 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/84f9f1c8cf176949f562f077a36b81adbf8a2a1d differ diff --git a/external/boringssl/fuzz/client_corpus/8537957625c6fbe222a7aa318210d21a146ef206 b/external/boringssl/fuzz/client_corpus/8537957625c6fbe222a7aa318210d21a146ef206 new file mode 100644 index 0000000000..ea3401c5d3 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/8537957625c6fbe222a7aa318210d21a146ef206 differ diff --git a/external/boringssl/fuzz/client_corpus/860e128954a5d8933886313be553fb2bf872e6f5 b/external/boringssl/fuzz/client_corpus/860e128954a5d8933886313be553fb2bf872e6f5 new file mode 100644 index 0000000000..8cf9e3a9cb Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/860e128954a5d8933886313be553fb2bf872e6f5 differ diff --git a/external/boringssl/fuzz/client_corpus/86674fe6d9cef4e7dc6f810214161701fc266658 b/external/boringssl/fuzz/client_corpus/86674fe6d9cef4e7dc6f810214161701fc266658 new file mode 100644 index 0000000000..220cf804be Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/86674fe6d9cef4e7dc6f810214161701fc266658 differ diff --git a/external/boringssl/fuzz/client_corpus/8689c5a7abc8bab0ca468f15671d770331fa9a3f b/external/boringssl/fuzz/client_corpus/8689c5a7abc8bab0ca468f15671d770331fa9a3f new file mode 100644 index 0000000000..3737f855c2 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/8689c5a7abc8bab0ca468f15671d770331fa9a3f differ diff --git a/external/boringssl/fuzz/client_corpus/873fdc25def6c4c6fbed6a548d23f268c393be3e b/external/boringssl/fuzz/client_corpus/873fdc25def6c4c6fbed6a548d23f268c393be3e new file mode 100644 index 0000000000..ccea4c22a4 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/873fdc25def6c4c6fbed6a548d23f268c393be3e differ diff --git a/external/boringssl/fuzz/client_corpus/877637beb6b6884b7fdf7d01b07b5c950de56a3d b/external/boringssl/fuzz/client_corpus/877637beb6b6884b7fdf7d01b07b5c950de56a3d new file mode 100644 index 0000000000..721b5e5a04 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/877637beb6b6884b7fdf7d01b07b5c950de56a3d differ diff --git a/external/boringssl/fuzz/client_corpus/87af0b01920985b125c1a5482d6cc9039887f624 b/external/boringssl/fuzz/client_corpus/87af0b01920985b125c1a5482d6cc9039887f624 new file mode 100644 index 0000000000..852982912e Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/87af0b01920985b125c1a5482d6cc9039887f624 differ diff --git a/external/boringssl/fuzz/client_corpus/881a7c422abdfd0dc71278d126ac94f22ae61832 b/external/boringssl/fuzz/client_corpus/881a7c422abdfd0dc71278d126ac94f22ae61832 new file mode 100644 index 0000000000..b4fea7ddda Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/881a7c422abdfd0dc71278d126ac94f22ae61832 differ diff --git a/external/boringssl/fuzz/client_corpus/89355b9199fa689195eeca48631ac8effaaeabb5 b/external/boringssl/fuzz/client_corpus/89355b9199fa689195eeca48631ac8effaaeabb5 new file mode 100644 index 0000000000..e0e05ca0f8 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/89355b9199fa689195eeca48631ac8effaaeabb5 differ diff --git a/external/boringssl/fuzz/client_corpus/8958860f8aae77703cc14b0ca88fa902319d4f1e b/external/boringssl/fuzz/client_corpus/8958860f8aae77703cc14b0ca88fa902319d4f1e new file mode 100644 index 0000000000..a3f84ed4de Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/8958860f8aae77703cc14b0ca88fa902319d4f1e differ diff --git a/external/boringssl/fuzz/client_corpus/89cbaec2af2c891586062633c097e9c4e9762cf8 b/external/boringssl/fuzz/client_corpus/89cbaec2af2c891586062633c097e9c4e9762cf8 new file mode 100644 index 0000000000..e3dd7366b7 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/89cbaec2af2c891586062633c097e9c4e9762cf8 differ diff --git a/external/boringssl/fuzz/client_corpus/89ce5fb7b86ce8f2c0e62b8fe79b12f9d2def007 b/external/boringssl/fuzz/client_corpus/89ce5fb7b86ce8f2c0e62b8fe79b12f9d2def007 new file mode 100644 index 0000000000..33b0f56a4a Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/89ce5fb7b86ce8f2c0e62b8fe79b12f9d2def007 differ diff --git a/external/boringssl/fuzz/client_corpus/89defbb1150e0cb3520e7510f0e7e06bf8973078 b/external/boringssl/fuzz/client_corpus/89defbb1150e0cb3520e7510f0e7e06bf8973078 new file mode 100644 index 0000000000..3ced36bd85 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/89defbb1150e0cb3520e7510f0e7e06bf8973078 differ diff --git a/external/boringssl/fuzz/client_corpus/8a01471d4ddb4d5c1c71f89bb0018e9eb0aed463 b/external/boringssl/fuzz/client_corpus/8a01471d4ddb4d5c1c71f89bb0018e9eb0aed463 new file mode 100644 index 0000000000..71e188b5c3 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/8a01471d4ddb4d5c1c71f89bb0018e9eb0aed463 differ diff --git a/external/boringssl/fuzz/client_corpus/8a962b1da16fd4b7af2bd08d0a1421bdcc3306fe b/external/boringssl/fuzz/client_corpus/8a962b1da16fd4b7af2bd08d0a1421bdcc3306fe new file mode 100644 index 0000000000..ef181e7c34 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/8a962b1da16fd4b7af2bd08d0a1421bdcc3306fe differ diff --git a/external/boringssl/fuzz/client_corpus/8ae0eed9ec461f1b6cfa172573d0ff0c94d62f58 b/external/boringssl/fuzz/client_corpus/8ae0eed9ec461f1b6cfa172573d0ff0c94d62f58 new file mode 100644 index 0000000000..258ac77c3e Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/8ae0eed9ec461f1b6cfa172573d0ff0c94d62f58 differ diff --git a/external/boringssl/fuzz/client_corpus/8b055ee2fc887c0d42c013c861a790b199cccfa4 b/external/boringssl/fuzz/client_corpus/8b055ee2fc887c0d42c013c861a790b199cccfa4 new file mode 100644 index 0000000000..100699dd7b Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/8b055ee2fc887c0d42c013c861a790b199cccfa4 differ diff --git a/external/boringssl/fuzz/client_corpus/8b57c39fadcde2215b64ce3925654fba85c5ea22 b/external/boringssl/fuzz/client_corpus/8b57c39fadcde2215b64ce3925654fba85c5ea22 new file mode 100644 index 0000000000..7be01ae80e Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/8b57c39fadcde2215b64ce3925654fba85c5ea22 differ diff --git a/external/boringssl/fuzz/client_corpus/8b9f236c2d33624817a2e03bcc8a3c78c4e756c6 b/external/boringssl/fuzz/client_corpus/8b9f236c2d33624817a2e03bcc8a3c78c4e756c6 new file mode 100644 index 0000000000..c1f19b0927 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/8b9f236c2d33624817a2e03bcc8a3c78c4e756c6 differ diff --git a/external/boringssl/fuzz/client_corpus/8bb94ac9d58ce60fb4baab8403722f1a173497b3 b/external/boringssl/fuzz/client_corpus/8bb94ac9d58ce60fb4baab8403722f1a173497b3 new file mode 100644 index 0000000000..7e081d9e00 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/8bb94ac9d58ce60fb4baab8403722f1a173497b3 differ diff --git a/external/boringssl/fuzz/client_corpus/8bdf4c52b4671f30500f90e08445da26adf93beb b/external/boringssl/fuzz/client_corpus/8bdf4c52b4671f30500f90e08445da26adf93beb new file mode 100644 index 0000000000..012821c194 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/8bdf4c52b4671f30500f90e08445da26adf93beb differ diff --git a/external/boringssl/fuzz/client_corpus/8c71832b8b6a2cd633d1dab36191392e08af24b3 b/external/boringssl/fuzz/client_corpus/8c71832b8b6a2cd633d1dab36191392e08af24b3 new file mode 100644 index 0000000000..240dfc6d5c Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/8c71832b8b6a2cd633d1dab36191392e08af24b3 differ diff --git a/external/boringssl/fuzz/client_corpus/8ce6863d4a91451041f82fb30a6bb6bcfe04bd57 b/external/boringssl/fuzz/client_corpus/8ce6863d4a91451041f82fb30a6bb6bcfe04bd57 new file mode 100644 index 0000000000..315aeb6c97 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/8ce6863d4a91451041f82fb30a6bb6bcfe04bd57 differ diff --git a/external/boringssl/fuzz/client_corpus/8d3d73f19d7bdfdcf299934f0c865d14fd0a209b b/external/boringssl/fuzz/client_corpus/8d3d73f19d7bdfdcf299934f0c865d14fd0a209b new file mode 100644 index 0000000000..44bd8c8aa4 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/8d3d73f19d7bdfdcf299934f0c865d14fd0a209b differ diff --git a/external/boringssl/fuzz/client_corpus/8d5185ae5f4f9ec9753a995ca97c16f937508e20 b/external/boringssl/fuzz/client_corpus/8d5185ae5f4f9ec9753a995ca97c16f937508e20 new file mode 100644 index 0000000000..c065474bf2 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/8d5185ae5f4f9ec9753a995ca97c16f937508e20 differ diff --git a/external/boringssl/fuzz/client_corpus/8d5bca4e95a1b5f22533a680142064237957363d b/external/boringssl/fuzz/client_corpus/8d5bca4e95a1b5f22533a680142064237957363d new file mode 100644 index 0000000000..abf33ceec6 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/8d5bca4e95a1b5f22533a680142064237957363d differ diff --git a/external/boringssl/fuzz/client_corpus/8d66c97ec703bad66d714f8f76eaf3d80f4fec4d b/external/boringssl/fuzz/client_corpus/8d66c97ec703bad66d714f8f76eaf3d80f4fec4d new file mode 100644 index 0000000000..64f555644f Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/8d66c97ec703bad66d714f8f76eaf3d80f4fec4d differ diff --git a/external/boringssl/fuzz/client_corpus/8d7451a7ce24c4ff1a684228fede21c6a27090e3 b/external/boringssl/fuzz/client_corpus/8d7451a7ce24c4ff1a684228fede21c6a27090e3 new file mode 100644 index 0000000000..83b98691c9 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/8d7451a7ce24c4ff1a684228fede21c6a27090e3 differ diff --git a/external/boringssl/fuzz/client_corpus/8da2fcb023ba27413d3e034b552e576cb348e6b8 b/external/boringssl/fuzz/client_corpus/8da2fcb023ba27413d3e034b552e576cb348e6b8 new file mode 100644 index 0000000000..efa16f5df2 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/8da2fcb023ba27413d3e034b552e576cb348e6b8 differ diff --git a/external/boringssl/fuzz/client_corpus/8dc032fd415972bf4ff2c700e875f05bf4c6708f b/external/boringssl/fuzz/client_corpus/8dc032fd415972bf4ff2c700e875f05bf4c6708f new file mode 100644 index 0000000000..35075b5ef4 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/8dc032fd415972bf4ff2c700e875f05bf4c6708f differ diff --git a/external/boringssl/fuzz/client_corpus/8e3d1f50587b38d1b71c64cd1f047c4617ebea63 b/external/boringssl/fuzz/client_corpus/8e3d1f50587b38d1b71c64cd1f047c4617ebea63 new file mode 100644 index 0000000000..4670c17d5d Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/8e3d1f50587b38d1b71c64cd1f047c4617ebea63 differ diff --git a/external/boringssl/fuzz/client_corpus/8e7191d8482bccdf5b7b9ad2ae98bb56f976ea05 b/external/boringssl/fuzz/client_corpus/8e7191d8482bccdf5b7b9ad2ae98bb56f976ea05 new file mode 100644 index 0000000000..63ec2fcaab Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/8e7191d8482bccdf5b7b9ad2ae98bb56f976ea05 differ diff --git a/external/boringssl/fuzz/client_corpus/8ea73c00f324ec5a252b47857dd59f9828ccd400 b/external/boringssl/fuzz/client_corpus/8ea73c00f324ec5a252b47857dd59f9828ccd400 new file mode 100644 index 0000000000..aa7b59f106 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/8ea73c00f324ec5a252b47857dd59f9828ccd400 differ diff --git a/external/boringssl/fuzz/client_corpus/8ed53379924ea04ec7917a8625bd8d42153516e6 b/external/boringssl/fuzz/client_corpus/8ed53379924ea04ec7917a8625bd8d42153516e6 new file mode 100644 index 0000000000..77c5c3c5d4 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/8ed53379924ea04ec7917a8625bd8d42153516e6 differ diff --git a/external/boringssl/fuzz/client_corpus/8f555d98707e74734b2d9f175fecd508d9e73f59 b/external/boringssl/fuzz/client_corpus/8f555d98707e74734b2d9f175fecd508d9e73f59 new file mode 100644 index 0000000000..341b274d60 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/8f555d98707e74734b2d9f175fecd508d9e73f59 differ diff --git a/external/boringssl/fuzz/client_corpus/8f57cb63093021e5617344387a6ef9b472514e8b b/external/boringssl/fuzz/client_corpus/8f57cb63093021e5617344387a6ef9b472514e8b new file mode 100644 index 0000000000..236f52a340 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/8f57cb63093021e5617344387a6ef9b472514e8b differ diff --git a/external/boringssl/fuzz/client_corpus/90c6b18f6c5042404ad9bd8a44dc7f3d079d3f97 b/external/boringssl/fuzz/client_corpus/90c6b18f6c5042404ad9bd8a44dc7f3d079d3f97 new file mode 100644 index 0000000000..4db53cbdd6 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/90c6b18f6c5042404ad9bd8a44dc7f3d079d3f97 differ diff --git a/external/boringssl/fuzz/client_corpus/90d49e05c95e7e73df106cae3a0391439736a760 b/external/boringssl/fuzz/client_corpus/90d49e05c95e7e73df106cae3a0391439736a760 new file mode 100644 index 0000000000..f00f62c23d Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/90d49e05c95e7e73df106cae3a0391439736a760 differ diff --git a/external/boringssl/fuzz/client_corpus/912f1e539eefdc5b24e0d1ea4733314c4a45dd73 b/external/boringssl/fuzz/client_corpus/912f1e539eefdc5b24e0d1ea4733314c4a45dd73 new file mode 100644 index 0000000000..08c4de31cf Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/912f1e539eefdc5b24e0d1ea4733314c4a45dd73 differ diff --git a/external/boringssl/fuzz/client_corpus/919751352435a91c9e331722b0deb8b5a953eb17 b/external/boringssl/fuzz/client_corpus/919751352435a91c9e331722b0deb8b5a953eb17 new file mode 100644 index 0000000000..a9dab91f75 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/919751352435a91c9e331722b0deb8b5a953eb17 differ diff --git a/external/boringssl/fuzz/client_corpus/91c6bb92bd906e6bda8bbdc81e811f6374f0ecc3 b/external/boringssl/fuzz/client_corpus/91c6bb92bd906e6bda8bbdc81e811f6374f0ecc3 new file mode 100644 index 0000000000..f860aaf076 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/91c6bb92bd906e6bda8bbdc81e811f6374f0ecc3 differ diff --git a/external/boringssl/fuzz/client_corpus/9200f3939411cb47950bbc4578bbb8e061f17674 b/external/boringssl/fuzz/client_corpus/9200f3939411cb47950bbc4578bbb8e061f17674 new file mode 100644 index 0000000000..97d4bdda1b Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/9200f3939411cb47950bbc4578bbb8e061f17674 differ diff --git a/external/boringssl/fuzz/client_corpus/92f58505d1c1904cb7f5c0f38abf62432a380c92 b/external/boringssl/fuzz/client_corpus/92f58505d1c1904cb7f5c0f38abf62432a380c92 new file mode 100644 index 0000000000..aa6af6bd8e Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/92f58505d1c1904cb7f5c0f38abf62432a380c92 differ diff --git a/external/boringssl/fuzz/client_corpus/92fcc5e47daf5fc36a817aebef83191add2c783c b/external/boringssl/fuzz/client_corpus/92fcc5e47daf5fc36a817aebef83191add2c783c new file mode 100644 index 0000000000..5549e5bff9 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/92fcc5e47daf5fc36a817aebef83191add2c783c differ diff --git a/external/boringssl/fuzz/client_corpus/93416d9bae039bfbcd8a847cee630d6253b1c141 b/external/boringssl/fuzz/client_corpus/93416d9bae039bfbcd8a847cee630d6253b1c141 new file mode 100644 index 0000000000..89628552b4 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/93416d9bae039bfbcd8a847cee630d6253b1c141 differ diff --git a/external/boringssl/fuzz/client_corpus/9379b70637beee45fa31d3e016363eefb5834488 b/external/boringssl/fuzz/client_corpus/9379b70637beee45fa31d3e016363eefb5834488 new file mode 100644 index 0000000000..6b34c0c963 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/9379b70637beee45fa31d3e016363eefb5834488 differ diff --git a/external/boringssl/fuzz/client_corpus/938b5f50bb8bdf2e2ba3ff9f56e1a06f4a11cbcc b/external/boringssl/fuzz/client_corpus/938b5f50bb8bdf2e2ba3ff9f56e1a06f4a11cbcc new file mode 100644 index 0000000000..360422181d Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/938b5f50bb8bdf2e2ba3ff9f56e1a06f4a11cbcc differ diff --git a/external/boringssl/fuzz/client_corpus/93a0fefc5de9feda0a6e7130aea669a423920b9f b/external/boringssl/fuzz/client_corpus/93a0fefc5de9feda0a6e7130aea669a423920b9f new file mode 100644 index 0000000000..a861f95a61 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/93a0fefc5de9feda0a6e7130aea669a423920b9f differ diff --git a/external/boringssl/fuzz/client_corpus/93ff7a343798cbe2c42e02d8bc85b7a63d5ecc2d b/external/boringssl/fuzz/client_corpus/93ff7a343798cbe2c42e02d8bc85b7a63d5ecc2d new file mode 100644 index 0000000000..cfc8be4d5f Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/93ff7a343798cbe2c42e02d8bc85b7a63d5ecc2d differ diff --git a/external/boringssl/fuzz/client_corpus/9458125f964837130e97064c97abb83f9646aa3a b/external/boringssl/fuzz/client_corpus/9458125f964837130e97064c97abb83f9646aa3a new file mode 100644 index 0000000000..cb81c3dc8a Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/9458125f964837130e97064c97abb83f9646aa3a differ diff --git a/external/boringssl/fuzz/client_corpus/948632bab2c87e14a502f6515527b4ce924f7253 b/external/boringssl/fuzz/client_corpus/948632bab2c87e14a502f6515527b4ce924f7253 new file mode 100644 index 0000000000..45558cb1b9 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/948632bab2c87e14a502f6515527b4ce924f7253 differ diff --git a/external/boringssl/fuzz/client_corpus/94ea697bb35e030154ca5c901a1e3b3f39d36e2c b/external/boringssl/fuzz/client_corpus/94ea697bb35e030154ca5c901a1e3b3f39d36e2c new file mode 100644 index 0000000000..c046a4aa9b Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/94ea697bb35e030154ca5c901a1e3b3f39d36e2c differ diff --git a/external/boringssl/fuzz/client_corpus/952698e57a900fd6dfd60cac5161b4acdb16b90d b/external/boringssl/fuzz/client_corpus/952698e57a900fd6dfd60cac5161b4acdb16b90d new file mode 100644 index 0000000000..2639e1c060 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/952698e57a900fd6dfd60cac5161b4acdb16b90d differ diff --git a/external/boringssl/fuzz/client_corpus/9546e93d1ebee30df46b3946a6739ffb52624e4b b/external/boringssl/fuzz/client_corpus/9546e93d1ebee30df46b3946a6739ffb52624e4b new file mode 100644 index 0000000000..6bcf2a1b87 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/9546e93d1ebee30df46b3946a6739ffb52624e4b differ diff --git a/external/boringssl/fuzz/client_corpus/9626102a12051d367f2cbc10d134766302a2510b b/external/boringssl/fuzz/client_corpus/9626102a12051d367f2cbc10d134766302a2510b new file mode 100644 index 0000000000..269c6fec23 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/9626102a12051d367f2cbc10d134766302a2510b differ diff --git a/external/boringssl/fuzz/client_corpus/96528c570cfaaea1ed945bba352f194fc4e9dd76 b/external/boringssl/fuzz/client_corpus/96528c570cfaaea1ed945bba352f194fc4e9dd76 new file mode 100644 index 0000000000..deb5c7c60c Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/96528c570cfaaea1ed945bba352f194fc4e9dd76 differ diff --git a/external/boringssl/fuzz/client_corpus/9671b1c78f584a5de5029ae5d2cbd807c4b9ff71 b/external/boringssl/fuzz/client_corpus/9671b1c78f584a5de5029ae5d2cbd807c4b9ff71 new file mode 100644 index 0000000000..fc3456473a Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/9671b1c78f584a5de5029ae5d2cbd807c4b9ff71 differ diff --git a/external/boringssl/fuzz/client_corpus/96d52303f3d71a4b80cd05cbcfeb0de94cdff14e b/external/boringssl/fuzz/client_corpus/96d52303f3d71a4b80cd05cbcfeb0de94cdff14e new file mode 100644 index 0000000000..88cb902984 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/96d52303f3d71a4b80cd05cbcfeb0de94cdff14e differ diff --git a/external/boringssl/fuzz/client_corpus/96e04588af90d18412bed0fe821ee8609f1445f7 b/external/boringssl/fuzz/client_corpus/96e04588af90d18412bed0fe821ee8609f1445f7 new file mode 100644 index 0000000000..a76a8729b7 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/96e04588af90d18412bed0fe821ee8609f1445f7 differ diff --git a/external/boringssl/fuzz/client_corpus/98a585cedac8d4736c292421597537dba155e731 b/external/boringssl/fuzz/client_corpus/98a585cedac8d4736c292421597537dba155e731 new file mode 100644 index 0000000000..04c2bfe89f Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/98a585cedac8d4736c292421597537dba155e731 differ diff --git a/external/boringssl/fuzz/client_corpus/99582e8bb92c8a66cd106db899de002e38a3f25d b/external/boringssl/fuzz/client_corpus/99582e8bb92c8a66cd106db899de002e38a3f25d new file mode 100644 index 0000000000..2017c7f7d6 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/99582e8bb92c8a66cd106db899de002e38a3f25d differ diff --git a/external/boringssl/fuzz/client_corpus/997fc5a88d3784c7ca294afa083e0c803f801fb0 b/external/boringssl/fuzz/client_corpus/997fc5a88d3784c7ca294afa083e0c803f801fb0 new file mode 100644 index 0000000000..a717924a32 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/997fc5a88d3784c7ca294afa083e0c803f801fb0 differ diff --git a/external/boringssl/fuzz/client_corpus/99b8f9912e5eb8b7305ebe14d09c80f21faf05cf b/external/boringssl/fuzz/client_corpus/99b8f9912e5eb8b7305ebe14d09c80f21faf05cf new file mode 100644 index 0000000000..e2690d503c Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/99b8f9912e5eb8b7305ebe14d09c80f21faf05cf differ diff --git a/external/boringssl/fuzz/client_corpus/99e5f2d8823aff6c698ecd0a2e0bf2a23f6f9f7e b/external/boringssl/fuzz/client_corpus/99e5f2d8823aff6c698ecd0a2e0bf2a23f6f9f7e new file mode 100644 index 0000000000..3a1f5c3bb7 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/99e5f2d8823aff6c698ecd0a2e0bf2a23f6f9f7e differ diff --git a/external/boringssl/fuzz/client_corpus/9a2ecde2abf1b187b05d042840236f29c658f634 b/external/boringssl/fuzz/client_corpus/9a2ecde2abf1b187b05d042840236f29c658f634 new file mode 100644 index 0000000000..2c5f68c1ee Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/9a2ecde2abf1b187b05d042840236f29c658f634 differ diff --git a/external/boringssl/fuzz/client_corpus/9cea539fa3ed5e1cb0b22afd9b0ae7c2fc400fa3 b/external/boringssl/fuzz/client_corpus/9cea539fa3ed5e1cb0b22afd9b0ae7c2fc400fa3 new file mode 100644 index 0000000000..7e0d4fcd75 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/9cea539fa3ed5e1cb0b22afd9b0ae7c2fc400fa3 differ diff --git a/external/boringssl/fuzz/client_corpus/9d5097026b59a1f6608991d745c001707134c98d b/external/boringssl/fuzz/client_corpus/9d5097026b59a1f6608991d745c001707134c98d new file mode 100644 index 0000000000..dd35cdc12d Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/9d5097026b59a1f6608991d745c001707134c98d differ diff --git a/external/boringssl/fuzz/client_corpus/9d66badf189ceb88b4a45d225c63a54787b9916e b/external/boringssl/fuzz/client_corpus/9d66badf189ceb88b4a45d225c63a54787b9916e new file mode 100644 index 0000000000..d7522af6d3 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/9d66badf189ceb88b4a45d225c63a54787b9916e differ diff --git a/external/boringssl/fuzz/client_corpus/9d9923ec92568c981b160f715358aa70d8e079b2 b/external/boringssl/fuzz/client_corpus/9d9923ec92568c981b160f715358aa70d8e079b2 new file mode 100644 index 0000000000..b90787e226 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/9d9923ec92568c981b160f715358aa70d8e079b2 differ diff --git a/external/boringssl/fuzz/client_corpus/9de75429028831dca2fd372a81cdd9a3ec343f22 b/external/boringssl/fuzz/client_corpus/9de75429028831dca2fd372a81cdd9a3ec343f22 new file mode 100644 index 0000000000..42c9e76806 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/9de75429028831dca2fd372a81cdd9a3ec343f22 differ diff --git a/external/boringssl/fuzz/client_corpus/9f3c5c4568790eb1583d02d285d1a6bfc209e98d b/external/boringssl/fuzz/client_corpus/9f3c5c4568790eb1583d02d285d1a6bfc209e98d new file mode 100644 index 0000000000..d53e90fd9a Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/9f3c5c4568790eb1583d02d285d1a6bfc209e98d differ diff --git a/external/boringssl/fuzz/client_corpus/9f6f8fb110096b920fa6a3e65564ae0a0cca4834 b/external/boringssl/fuzz/client_corpus/9f6f8fb110096b920fa6a3e65564ae0a0cca4834 new file mode 100644 index 0000000000..a7958bd680 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/9f6f8fb110096b920fa6a3e65564ae0a0cca4834 differ diff --git a/external/boringssl/fuzz/client_corpus/9fc364fc3f2a6522f904ac7afa35f74853ff6cdc b/external/boringssl/fuzz/client_corpus/9fc364fc3f2a6522f904ac7afa35f74853ff6cdc new file mode 100644 index 0000000000..57c2ba3faa Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/9fc364fc3f2a6522f904ac7afa35f74853ff6cdc differ diff --git a/external/boringssl/fuzz/client_corpus/a0235e7a5ff466220a742084c5c254c1ddbe9229 b/external/boringssl/fuzz/client_corpus/a0235e7a5ff466220a742084c5c254c1ddbe9229 new file mode 100644 index 0000000000..442a197be0 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/a0235e7a5ff466220a742084c5c254c1ddbe9229 differ diff --git a/external/boringssl/fuzz/client_corpus/a0753eaf3cf2571e61efa16bbd8ff494d1d746f0 b/external/boringssl/fuzz/client_corpus/a0753eaf3cf2571e61efa16bbd8ff494d1d746f0 new file mode 100644 index 0000000000..2fce9076a0 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/a0753eaf3cf2571e61efa16bbd8ff494d1d746f0 differ diff --git a/external/boringssl/fuzz/client_corpus/a07942a046ea947ee7fa432c44f2dfe8369ad3b1 b/external/boringssl/fuzz/client_corpus/a07942a046ea947ee7fa432c44f2dfe8369ad3b1 new file mode 100644 index 0000000000..f32b434cba Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/a07942a046ea947ee7fa432c44f2dfe8369ad3b1 differ diff --git a/external/boringssl/fuzz/client_corpus/a0e018264482fdad568e31e3698ae48d09f5ede9 b/external/boringssl/fuzz/client_corpus/a0e018264482fdad568e31e3698ae48d09f5ede9 new file mode 100644 index 0000000000..79fd173d27 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/a0e018264482fdad568e31e3698ae48d09f5ede9 differ diff --git a/external/boringssl/fuzz/client_corpus/a0ed1be09750824c2f10f1e47249cea3210bf179 b/external/boringssl/fuzz/client_corpus/a0ed1be09750824c2f10f1e47249cea3210bf179 new file mode 100644 index 0000000000..dbbbb28e66 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/a0ed1be09750824c2f10f1e47249cea3210bf179 differ diff --git a/external/boringssl/fuzz/client_corpus/a130fb854ed6720458b564902ad8356882862daf b/external/boringssl/fuzz/client_corpus/a130fb854ed6720458b564902ad8356882862daf new file mode 100644 index 0000000000..92e3ed34ec Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/a130fb854ed6720458b564902ad8356882862daf differ diff --git a/external/boringssl/fuzz/client_corpus/a172350dffb276e420877c300b37260c243ef2d0 b/external/boringssl/fuzz/client_corpus/a172350dffb276e420877c300b37260c243ef2d0 new file mode 100644 index 0000000000..12e631b92e Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/a172350dffb276e420877c300b37260c243ef2d0 differ diff --git a/external/boringssl/fuzz/client_corpus/a19081ccc4eee7a72caf54666e34706bd6ccb486 b/external/boringssl/fuzz/client_corpus/a19081ccc4eee7a72caf54666e34706bd6ccb486 new file mode 100644 index 0000000000..c9da3a0d44 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/a19081ccc4eee7a72caf54666e34706bd6ccb486 differ diff --git a/external/boringssl/fuzz/client_corpus/a1ff1dc066ae44ba884fa5fba82543577a5261ad b/external/boringssl/fuzz/client_corpus/a1ff1dc066ae44ba884fa5fba82543577a5261ad new file mode 100644 index 0000000000..6a6eaddb8f Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/a1ff1dc066ae44ba884fa5fba82543577a5261ad differ diff --git a/external/boringssl/fuzz/client_corpus/a2158aa067898aba1b75e977192e03f13de20552 b/external/boringssl/fuzz/client_corpus/a2158aa067898aba1b75e977192e03f13de20552 new file mode 100644 index 0000000000..3286296be0 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/a2158aa067898aba1b75e977192e03f13de20552 differ diff --git a/external/boringssl/fuzz/client_corpus/a22efd143aa1cf004a7ace6ba056dffdf1bed8f3 b/external/boringssl/fuzz/client_corpus/a22efd143aa1cf004a7ace6ba056dffdf1bed8f3 new file mode 100644 index 0000000000..cdbda66626 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/a22efd143aa1cf004a7ace6ba056dffdf1bed8f3 differ diff --git a/external/boringssl/fuzz/client_corpus/a294bec7193e517c3d48201cd5ce2200a8c482bb b/external/boringssl/fuzz/client_corpus/a294bec7193e517c3d48201cd5ce2200a8c482bb new file mode 100644 index 0000000000..f7aa3af1a4 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/a294bec7193e517c3d48201cd5ce2200a8c482bb differ diff --git a/external/boringssl/fuzz/client_corpus/a2f974cccbf5442bf1a8c55477afccf39168605b b/external/boringssl/fuzz/client_corpus/a2f974cccbf5442bf1a8c55477afccf39168605b new file mode 100644 index 0000000000..f24fadc4d4 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/a2f974cccbf5442bf1a8c55477afccf39168605b differ diff --git a/external/boringssl/fuzz/client_corpus/a3bfeed2ef700425f8faf0c6b93295149f23ac2a b/external/boringssl/fuzz/client_corpus/a3bfeed2ef700425f8faf0c6b93295149f23ac2a new file mode 100644 index 0000000000..2aba93e1d8 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/a3bfeed2ef700425f8faf0c6b93295149f23ac2a differ diff --git a/external/boringssl/fuzz/client_corpus/a417315ebb027548f50a52b1e274fc5f8f6b0104 b/external/boringssl/fuzz/client_corpus/a417315ebb027548f50a52b1e274fc5f8f6b0104 new file mode 100644 index 0000000000..0c4f719b0a Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/a417315ebb027548f50a52b1e274fc5f8f6b0104 differ diff --git a/external/boringssl/fuzz/client_corpus/a51278e710ef32f80c76a25419ded9f378f73928 b/external/boringssl/fuzz/client_corpus/a51278e710ef32f80c76a25419ded9f378f73928 new file mode 100644 index 0000000000..7186fd4415 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/a51278e710ef32f80c76a25419ded9f378f73928 differ diff --git a/external/boringssl/fuzz/client_corpus/a52b559cb5576d2d78315121b141ab72adb7bf20 b/external/boringssl/fuzz/client_corpus/a52b559cb5576d2d78315121b141ab72adb7bf20 new file mode 100644 index 0000000000..71a50263be Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/a52b559cb5576d2d78315121b141ab72adb7bf20 differ diff --git a/external/boringssl/fuzz/client_corpus/a55b4c066a0ade77b7d681e47b7341c479d68c3b b/external/boringssl/fuzz/client_corpus/a55b4c066a0ade77b7d681e47b7341c479d68c3b new file mode 100644 index 0000000000..a919857f78 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/a55b4c066a0ade77b7d681e47b7341c479d68c3b differ diff --git a/external/boringssl/fuzz/client_corpus/a5b5d110779c03c88043f20cb31a443402cf401d b/external/boringssl/fuzz/client_corpus/a5b5d110779c03c88043f20cb31a443402cf401d new file mode 100644 index 0000000000..ec54ec3c59 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/a5b5d110779c03c88043f20cb31a443402cf401d differ diff --git a/external/boringssl/fuzz/client_corpus/a5c7daa6ba53a703f416d7f258ceb73a0697fbfb b/external/boringssl/fuzz/client_corpus/a5c7daa6ba53a703f416d7f258ceb73a0697fbfb new file mode 100644 index 0000000000..28602bc437 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/a5c7daa6ba53a703f416d7f258ceb73a0697fbfb differ diff --git a/external/boringssl/fuzz/client_corpus/a5ccd3683d69f1699f62d1b25bb72bfe804c821a b/external/boringssl/fuzz/client_corpus/a5ccd3683d69f1699f62d1b25bb72bfe804c821a new file mode 100644 index 0000000000..8b61e7f4a7 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/a5ccd3683d69f1699f62d1b25bb72bfe804c821a differ diff --git a/external/boringssl/fuzz/client_corpus/a647ad0e3689d42850d0dc5211b63ed3bbd51290 b/external/boringssl/fuzz/client_corpus/a647ad0e3689d42850d0dc5211b63ed3bbd51290 new file mode 100644 index 0000000000..5cc479c484 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/a647ad0e3689d42850d0dc5211b63ed3bbd51290 differ diff --git a/external/boringssl/fuzz/client_corpus/a6718d2e96c00ab472bab71e57b6ac3486b15921 b/external/boringssl/fuzz/client_corpus/a6718d2e96c00ab472bab71e57b6ac3486b15921 new file mode 100644 index 0000000000..50dae549c6 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/a6718d2e96c00ab472bab71e57b6ac3486b15921 differ diff --git a/external/boringssl/fuzz/client_corpus/a679b20b95835cea68864e84d9d5271dc148cdef b/external/boringssl/fuzz/client_corpus/a679b20b95835cea68864e84d9d5271dc148cdef new file mode 100644 index 0000000000..f95a7bd1a3 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/a679b20b95835cea68864e84d9d5271dc148cdef differ diff --git a/external/boringssl/fuzz/client_corpus/a6a0b7158098709725de5a40691cf476af9fa826 b/external/boringssl/fuzz/client_corpus/a6a0b7158098709725de5a40691cf476af9fa826 new file mode 100644 index 0000000000..5f8cf8adf2 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/a6a0b7158098709725de5a40691cf476af9fa826 differ diff --git a/external/boringssl/fuzz/client_corpus/a6c3e91a3a28655fce34b777ffc83112591a5305 b/external/boringssl/fuzz/client_corpus/a6c3e91a3a28655fce34b777ffc83112591a5305 new file mode 100644 index 0000000000..10c900d011 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/a6c3e91a3a28655fce34b777ffc83112591a5305 differ diff --git a/external/boringssl/fuzz/client_corpus/a72e9c8f8a5898128d15f8db799805fb0af08769 b/external/boringssl/fuzz/client_corpus/a72e9c8f8a5898128d15f8db799805fb0af08769 new file mode 100644 index 0000000000..532023b454 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/a72e9c8f8a5898128d15f8db799805fb0af08769 differ diff --git a/external/boringssl/fuzz/client_corpus/a778a560be38a3bd5a3ea923c350f804d1dece94 b/external/boringssl/fuzz/client_corpus/a778a560be38a3bd5a3ea923c350f804d1dece94 new file mode 100644 index 0000000000..fc1e4c30e3 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/a778a560be38a3bd5a3ea923c350f804d1dece94 differ diff --git a/external/boringssl/fuzz/client_corpus/a7816bfa7527e483e56adb8c69bab7b1e8e9bd28 b/external/boringssl/fuzz/client_corpus/a7816bfa7527e483e56adb8c69bab7b1e8e9bd28 new file mode 100644 index 0000000000..73b3137422 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/a7816bfa7527e483e56adb8c69bab7b1e8e9bd28 differ diff --git a/external/boringssl/fuzz/client_corpus/a7960ebdd7568141959f4174078a227b67b6a42e b/external/boringssl/fuzz/client_corpus/a7960ebdd7568141959f4174078a227b67b6a42e new file mode 100644 index 0000000000..62235a862d Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/a7960ebdd7568141959f4174078a227b67b6a42e differ diff --git a/external/boringssl/fuzz/client_corpus/a7f7698acb1a785bc16f01a9996a0b552feb9641 b/external/boringssl/fuzz/client_corpus/a7f7698acb1a785bc16f01a9996a0b552feb9641 new file mode 100644 index 0000000000..d2ed50b7e0 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/a7f7698acb1a785bc16f01a9996a0b552feb9641 differ diff --git a/external/boringssl/fuzz/client_corpus/a867840096cb79e3ce2a5d9484ce84f9477e3201 b/external/boringssl/fuzz/client_corpus/a867840096cb79e3ce2a5d9484ce84f9477e3201 new file mode 100644 index 0000000000..8174c0ec96 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/a867840096cb79e3ce2a5d9484ce84f9477e3201 differ diff --git a/external/boringssl/fuzz/client_corpus/a8f7d1273ef6222a7d75652c9692146d1285fe98 b/external/boringssl/fuzz/client_corpus/a8f7d1273ef6222a7d75652c9692146d1285fe98 new file mode 100644 index 0000000000..1e780ad46e Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/a8f7d1273ef6222a7d75652c9692146d1285fe98 differ diff --git a/external/boringssl/fuzz/client_corpus/a93092c6332f5da16c6445e9901c751967377973 b/external/boringssl/fuzz/client_corpus/a93092c6332f5da16c6445e9901c751967377973 new file mode 100644 index 0000000000..19b26c1c09 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/a93092c6332f5da16c6445e9901c751967377973 differ diff --git a/external/boringssl/fuzz/client_corpus/a948c8df25bd48a0c09ec5a4c9414d75b92f9f53 b/external/boringssl/fuzz/client_corpus/a948c8df25bd48a0c09ec5a4c9414d75b92f9f53 new file mode 100644 index 0000000000..ac8bf19102 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/a948c8df25bd48a0c09ec5a4c9414d75b92f9f53 differ diff --git a/external/boringssl/fuzz/client_corpus/a95561be75e63a4cbc50dc98ce9522df464cb9f7 b/external/boringssl/fuzz/client_corpus/a95561be75e63a4cbc50dc98ce9522df464cb9f7 new file mode 100644 index 0000000000..fd0d570304 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/a95561be75e63a4cbc50dc98ce9522df464cb9f7 differ diff --git a/external/boringssl/fuzz/client_corpus/a9c923edd522f91856371fb45fa87d4e432286c6 b/external/boringssl/fuzz/client_corpus/a9c923edd522f91856371fb45fa87d4e432286c6 new file mode 100644 index 0000000000..5ea2fe6b5a Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/a9c923edd522f91856371fb45fa87d4e432286c6 differ diff --git a/external/boringssl/fuzz/client_corpus/a9ffba3c720e1215a0e65c0952ddfda9664b2585 b/external/boringssl/fuzz/client_corpus/a9ffba3c720e1215a0e65c0952ddfda9664b2585 new file mode 100644 index 0000000000..dcc072085f Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/a9ffba3c720e1215a0e65c0952ddfda9664b2585 differ diff --git a/external/boringssl/fuzz/client_corpus/aa45f50d4ad0419c89f03c11032fefb7f27f09c6 b/external/boringssl/fuzz/client_corpus/aa45f50d4ad0419c89f03c11032fefb7f27f09c6 new file mode 100644 index 0000000000..962b81b053 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/aa45f50d4ad0419c89f03c11032fefb7f27f09c6 differ diff --git a/external/boringssl/fuzz/client_corpus/aac5de1115c0934b3e4a4fa1bff4e10fa1e61d71 b/external/boringssl/fuzz/client_corpus/aac5de1115c0934b3e4a4fa1bff4e10fa1e61d71 new file mode 100644 index 0000000000..f26c474cc8 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/aac5de1115c0934b3e4a4fa1bff4e10fa1e61d71 differ diff --git a/external/boringssl/fuzz/client_corpus/ac7d3c35fcfcfb6a3d02c4fc08f60981cb121664 b/external/boringssl/fuzz/client_corpus/ac7d3c35fcfcfb6a3d02c4fc08f60981cb121664 new file mode 100644 index 0000000000..9b3b96e9f0 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/ac7d3c35fcfcfb6a3d02c4fc08f60981cb121664 differ diff --git a/external/boringssl/fuzz/client_corpus/ac7e3ccc463eb9334528b256bb2fa05b58274508 b/external/boringssl/fuzz/client_corpus/ac7e3ccc463eb9334528b256bb2fa05b58274508 new file mode 100644 index 0000000000..9b1a094612 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/ac7e3ccc463eb9334528b256bb2fa05b58274508 differ diff --git a/external/boringssl/fuzz/client_corpus/ac9900e115b00f2e3955371c512a5048cb9126e5 b/external/boringssl/fuzz/client_corpus/ac9900e115b00f2e3955371c512a5048cb9126e5 new file mode 100644 index 0000000000..df778e2ae9 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/ac9900e115b00f2e3955371c512a5048cb9126e5 differ diff --git a/external/boringssl/fuzz/client_corpus/ac9c3021b430c86c30300143099b6f313a25ef60 b/external/boringssl/fuzz/client_corpus/ac9c3021b430c86c30300143099b6f313a25ef60 new file mode 100644 index 0000000000..5b2f9ec97a Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/ac9c3021b430c86c30300143099b6f313a25ef60 differ diff --git a/external/boringssl/fuzz/client_corpus/acc7c0d52ef2f9477aa67e3aefc8c05d89c8e872 b/external/boringssl/fuzz/client_corpus/acc7c0d52ef2f9477aa67e3aefc8c05d89c8e872 new file mode 100644 index 0000000000..498e7a78fd Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/acc7c0d52ef2f9477aa67e3aefc8c05d89c8e872 differ diff --git a/external/boringssl/fuzz/client_corpus/acd6f322d20bdd2325a0927aa307fdd4a57b1ce5 b/external/boringssl/fuzz/client_corpus/acd6f322d20bdd2325a0927aa307fdd4a57b1ce5 new file mode 100644 index 0000000000..5485f0bbed Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/acd6f322d20bdd2325a0927aa307fdd4a57b1ce5 differ diff --git a/external/boringssl/fuzz/client_corpus/ace9bdbbb130491029271f8a781605b940eb807f b/external/boringssl/fuzz/client_corpus/ace9bdbbb130491029271f8a781605b940eb807f new file mode 100644 index 0000000000..e7bf5d30e5 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/ace9bdbbb130491029271f8a781605b940eb807f differ diff --git a/external/boringssl/fuzz/client_corpus/ad8e168bbba36c52740aa3bbb41d8f503715683a b/external/boringssl/fuzz/client_corpus/ad8e168bbba36c52740aa3bbb41d8f503715683a new file mode 100644 index 0000000000..7db1bef3a5 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/ad8e168bbba36c52740aa3bbb41d8f503715683a differ diff --git a/external/boringssl/fuzz/client_corpus/adc8f85e6d26d1d01ec10aa01b8733ec7622c7fd b/external/boringssl/fuzz/client_corpus/adc8f85e6d26d1d01ec10aa01b8733ec7622c7fd new file mode 100644 index 0000000000..8860f360db Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/adc8f85e6d26d1d01ec10aa01b8733ec7622c7fd differ diff --git a/external/boringssl/fuzz/client_corpus/ae2a77d41b7fac3e56af9e15139c2fb667387445 b/external/boringssl/fuzz/client_corpus/ae2a77d41b7fac3e56af9e15139c2fb667387445 new file mode 100644 index 0000000000..24f20c135d Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/ae2a77d41b7fac3e56af9e15139c2fb667387445 differ diff --git a/external/boringssl/fuzz/client_corpus/ae9abebb13aafcead7dbd2a3b309be9bbc2ee055 b/external/boringssl/fuzz/client_corpus/ae9abebb13aafcead7dbd2a3b309be9bbc2ee055 new file mode 100644 index 0000000000..db9f830b9f Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/ae9abebb13aafcead7dbd2a3b309be9bbc2ee055 differ diff --git a/external/boringssl/fuzz/client_corpus/af5ad09d790177794ac60e2e8cd54be03c7df970 b/external/boringssl/fuzz/client_corpus/af5ad09d790177794ac60e2e8cd54be03c7df970 new file mode 100644 index 0000000000..2a4f624962 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/af5ad09d790177794ac60e2e8cd54be03c7df970 differ diff --git a/external/boringssl/fuzz/client_corpus/b02387538c10d919e45118d91ebb52d3fdfb74e6 b/external/boringssl/fuzz/client_corpus/b02387538c10d919e45118d91ebb52d3fdfb74e6 new file mode 100644 index 0000000000..a1db8f4746 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/b02387538c10d919e45118d91ebb52d3fdfb74e6 differ diff --git a/external/boringssl/fuzz/client_corpus/b0b2cece76492218026f90503c4394daaa0d95d9 b/external/boringssl/fuzz/client_corpus/b0b2cece76492218026f90503c4394daaa0d95d9 new file mode 100644 index 0000000000..3d97490771 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/b0b2cece76492218026f90503c4394daaa0d95d9 differ diff --git a/external/boringssl/fuzz/client_corpus/b1511eff332f93d93d5990f9d49014fbb8fc1a84 b/external/boringssl/fuzz/client_corpus/b1511eff332f93d93d5990f9d49014fbb8fc1a84 new file mode 100644 index 0000000000..5bae12b7cb Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/b1511eff332f93d93d5990f9d49014fbb8fc1a84 differ diff --git a/external/boringssl/fuzz/client_corpus/b174c062d7b5df9f7e88d3f2b4b107e8f582e6e6 b/external/boringssl/fuzz/client_corpus/b174c062d7b5df9f7e88d3f2b4b107e8f582e6e6 new file mode 100644 index 0000000000..1f3ff03d6f Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/b174c062d7b5df9f7e88d3f2b4b107e8f582e6e6 differ diff --git a/external/boringssl/fuzz/client_corpus/b1850b14ae80f8be2fd166838e994eb536d9a817 b/external/boringssl/fuzz/client_corpus/b1850b14ae80f8be2fd166838e994eb536d9a817 new file mode 100644 index 0000000000..8df81c52e4 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/b1850b14ae80f8be2fd166838e994eb536d9a817 differ diff --git a/external/boringssl/fuzz/client_corpus/b1bc8ccbf4ca18d4fc67cc4298bdfbf2f8a48a52 b/external/boringssl/fuzz/client_corpus/b1bc8ccbf4ca18d4fc67cc4298bdfbf2f8a48a52 new file mode 100644 index 0000000000..708c1f1478 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/b1bc8ccbf4ca18d4fc67cc4298bdfbf2f8a48a52 differ diff --git a/external/boringssl/fuzz/client_corpus/b215c683e8544dc16c0285029b72f8ef8e4bdf8a b/external/boringssl/fuzz/client_corpus/b215c683e8544dc16c0285029b72f8ef8e4bdf8a new file mode 100644 index 0000000000..f2f882222e Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/b215c683e8544dc16c0285029b72f8ef8e4bdf8a differ diff --git a/external/boringssl/fuzz/client_corpus/b25fcfa7688e490ff503af7a1fe277c4ccae0e79 b/external/boringssl/fuzz/client_corpus/b25fcfa7688e490ff503af7a1fe277c4ccae0e79 new file mode 100644 index 0000000000..aaa85d41ca Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/b25fcfa7688e490ff503af7a1fe277c4ccae0e79 differ diff --git a/external/boringssl/fuzz/client_corpus/b27898123afcd9087d724486b032b67f38f3b564 b/external/boringssl/fuzz/client_corpus/b27898123afcd9087d724486b032b67f38f3b564 new file mode 100644 index 0000000000..f984bb45f6 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/b27898123afcd9087d724486b032b67f38f3b564 differ diff --git a/external/boringssl/fuzz/client_corpus/b3450111f5d3ccdbcf6e08ffda25a7e0e5c53811 b/external/boringssl/fuzz/client_corpus/b3450111f5d3ccdbcf6e08ffda25a7e0e5c53811 new file mode 100644 index 0000000000..dcfb17a937 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/b3450111f5d3ccdbcf6e08ffda25a7e0e5c53811 differ diff --git a/external/boringssl/fuzz/client_corpus/b34dcdb2702d8fc829ddcc8908c227db8ab39f18 b/external/boringssl/fuzz/client_corpus/b34dcdb2702d8fc829ddcc8908c227db8ab39f18 new file mode 100644 index 0000000000..c0858d60b2 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/b34dcdb2702d8fc829ddcc8908c227db8ab39f18 differ diff --git a/external/boringssl/fuzz/client_corpus/b38d66292459ad2fae16464f561aa199812b7ec6 b/external/boringssl/fuzz/client_corpus/b38d66292459ad2fae16464f561aa199812b7ec6 new file mode 100644 index 0000000000..457af3daa0 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/b38d66292459ad2fae16464f561aa199812b7ec6 differ diff --git a/external/boringssl/fuzz/client_corpus/b3a58509fdd22e3f6a77d4718b3933c2144e8be8 b/external/boringssl/fuzz/client_corpus/b3a58509fdd22e3f6a77d4718b3933c2144e8be8 new file mode 100644 index 0000000000..32b699d7a7 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/b3a58509fdd22e3f6a77d4718b3933c2144e8be8 differ diff --git a/external/boringssl/fuzz/client_corpus/b4768e27463348cdc83824f609bcc0bc4c064648 b/external/boringssl/fuzz/client_corpus/b4768e27463348cdc83824f609bcc0bc4c064648 new file mode 100644 index 0000000000..3d47a95c6f Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/b4768e27463348cdc83824f609bcc0bc4c064648 differ diff --git a/external/boringssl/fuzz/client_corpus/b47b7e03177dc00879c0c5eaa1046e289e8cc74f b/external/boringssl/fuzz/client_corpus/b47b7e03177dc00879c0c5eaa1046e289e8cc74f new file mode 100644 index 0000000000..d400327749 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/b47b7e03177dc00879c0c5eaa1046e289e8cc74f differ diff --git a/external/boringssl/fuzz/client_corpus/b4b6b38c2edab3fd1396696ab437c144603713be b/external/boringssl/fuzz/client_corpus/b4b6b38c2edab3fd1396696ab437c144603713be new file mode 100644 index 0000000000..b923b55f91 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/b4b6b38c2edab3fd1396696ab437c144603713be differ diff --git a/external/boringssl/fuzz/client_corpus/b4d11620cbd84d8f68d387969c7e1b6db5b437f9 b/external/boringssl/fuzz/client_corpus/b4d11620cbd84d8f68d387969c7e1b6db5b437f9 new file mode 100644 index 0000000000..165be2f3ed --- /dev/null +++ b/external/boringssl/fuzz/client_corpus/b4d11620cbd84d8f68d387969c7e1b6db5b437f9 @@ -0,0 +1 @@ +6 \ No newline at end of file diff --git a/external/boringssl/fuzz/client_corpus/b50f8d1d0d99c5d7c8b8b185aef00d3fb082c567 b/external/boringssl/fuzz/client_corpus/b50f8d1d0d99c5d7c8b8b185aef00d3fb082c567 new file mode 100644 index 0000000000..0fc9c7a98d Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/b50f8d1d0d99c5d7c8b8b185aef00d3fb082c567 differ diff --git a/external/boringssl/fuzz/client_corpus/b51cc11a839138e0a972e1c13b2da0d86e67a27d b/external/boringssl/fuzz/client_corpus/b51cc11a839138e0a972e1c13b2da0d86e67a27d new file mode 100644 index 0000000000..9187998e4c Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/b51cc11a839138e0a972e1c13b2da0d86e67a27d differ diff --git a/external/boringssl/fuzz/client_corpus/b524627a5d86fca25217970da5f8cb4c6119d226 b/external/boringssl/fuzz/client_corpus/b524627a5d86fca25217970da5f8cb4c6119d226 new file mode 100644 index 0000000000..2640f7a989 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/b524627a5d86fca25217970da5f8cb4c6119d226 differ diff --git a/external/boringssl/fuzz/client_corpus/b5709d7b4b2591636f8d80695dbf7b6a03ce488a b/external/boringssl/fuzz/client_corpus/b5709d7b4b2591636f8d80695dbf7b6a03ce488a new file mode 100644 index 0000000000..4aab285da9 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/b5709d7b4b2591636f8d80695dbf7b6a03ce488a differ diff --git a/external/boringssl/fuzz/client_corpus/b5ceea502c4b27e709a4baa0e2992cc942b57621 b/external/boringssl/fuzz/client_corpus/b5ceea502c4b27e709a4baa0e2992cc942b57621 new file mode 100644 index 0000000000..b7d48efd9c Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/b5ceea502c4b27e709a4baa0e2992cc942b57621 differ diff --git a/external/boringssl/fuzz/client_corpus/b5e84dfe2ad6dec21fe39b8a158022db050b7f18 b/external/boringssl/fuzz/client_corpus/b5e84dfe2ad6dec21fe39b8a158022db050b7f18 new file mode 100644 index 0000000000..b970ef71ec Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/b5e84dfe2ad6dec21fe39b8a158022db050b7f18 differ diff --git a/external/boringssl/fuzz/client_corpus/b5f0a0ed4afb8db0be1385bbb58df0e39637941a b/external/boringssl/fuzz/client_corpus/b5f0a0ed4afb8db0be1385bbb58df0e39637941a new file mode 100644 index 0000000000..2beb7922e8 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/b5f0a0ed4afb8db0be1385bbb58df0e39637941a differ diff --git a/external/boringssl/fuzz/client_corpus/b601dcb412a63b13ef14d9ae6c041acf7a7716a1 b/external/boringssl/fuzz/client_corpus/b601dcb412a63b13ef14d9ae6c041acf7a7716a1 new file mode 100644 index 0000000000..f3a5df370e Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/b601dcb412a63b13ef14d9ae6c041acf7a7716a1 differ diff --git a/external/boringssl/fuzz/client_corpus/b672eb91f36cce66d8e000551c6bef6d0215bfde b/external/boringssl/fuzz/client_corpus/b672eb91f36cce66d8e000551c6bef6d0215bfde new file mode 100644 index 0000000000..611a07a969 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/b672eb91f36cce66d8e000551c6bef6d0215bfde differ diff --git a/external/boringssl/fuzz/client_corpus/b6b132f06663996cf8c976cb44be9cfafbef83d9 b/external/boringssl/fuzz/client_corpus/b6b132f06663996cf8c976cb44be9cfafbef83d9 new file mode 100644 index 0000000000..b9cc663e63 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/b6b132f06663996cf8c976cb44be9cfafbef83d9 differ diff --git a/external/boringssl/fuzz/client_corpus/b70773f3b09ea80a6adf9641ed753f364a1cb43b b/external/boringssl/fuzz/client_corpus/b70773f3b09ea80a6adf9641ed753f364a1cb43b new file mode 100644 index 0000000000..f0a876ed3c Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/b70773f3b09ea80a6adf9641ed753f364a1cb43b differ diff --git a/external/boringssl/fuzz/client_corpus/b711730ee7cf094e22dfed3d9bbdafe6537945fc b/external/boringssl/fuzz/client_corpus/b711730ee7cf094e22dfed3d9bbdafe6537945fc new file mode 100644 index 0000000000..1653e72624 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/b711730ee7cf094e22dfed3d9bbdafe6537945fc differ diff --git a/external/boringssl/fuzz/client_corpus/b72f792402e28cf94c28bc8e33e785989e5683ae b/external/boringssl/fuzz/client_corpus/b72f792402e28cf94c28bc8e33e785989e5683ae new file mode 100644 index 0000000000..8a98e95bd8 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/b72f792402e28cf94c28bc8e33e785989e5683ae differ diff --git a/external/boringssl/fuzz/client_corpus/b748db1e3357fde15527e79c66dd5dcc3b96a07a b/external/boringssl/fuzz/client_corpus/b748db1e3357fde15527e79c66dd5dcc3b96a07a new file mode 100644 index 0000000000..a4626b3bb3 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/b748db1e3357fde15527e79c66dd5dcc3b96a07a differ diff --git a/external/boringssl/fuzz/client_corpus/b80c7961e196c01be618d2b46c9c3497f7f32c9b b/external/boringssl/fuzz/client_corpus/b80c7961e196c01be618d2b46c9c3497f7f32c9b new file mode 100644 index 0000000000..50468fc348 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/b80c7961e196c01be618d2b46c9c3497f7f32c9b differ diff --git a/external/boringssl/fuzz/client_corpus/b85c172c80e31de442f8af7d1c182e0a88d4cef2 b/external/boringssl/fuzz/client_corpus/b85c172c80e31de442f8af7d1c182e0a88d4cef2 new file mode 100644 index 0000000000..4d9949c79f Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/b85c172c80e31de442f8af7d1c182e0a88d4cef2 differ diff --git a/external/boringssl/fuzz/client_corpus/b8ab490b280bfa2e0514a86776e7c2d069e26fc1 b/external/boringssl/fuzz/client_corpus/b8ab490b280bfa2e0514a86776e7c2d069e26fc1 new file mode 100644 index 0000000000..427709a378 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/b8ab490b280bfa2e0514a86776e7c2d069e26fc1 differ diff --git a/external/boringssl/fuzz/client_corpus/b93163f45f4e7d49ee5721e5865aa2e7a394251b b/external/boringssl/fuzz/client_corpus/b93163f45f4e7d49ee5721e5865aa2e7a394251b new file mode 100644 index 0000000000..ee3030b4fe Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/b93163f45f4e7d49ee5721e5865aa2e7a394251b differ diff --git a/external/boringssl/fuzz/client_corpus/b9abeb89a255b98c7dcf1c740f6a352dfd6ef0a5 b/external/boringssl/fuzz/client_corpus/b9abeb89a255b98c7dcf1c740f6a352dfd6ef0a5 new file mode 100644 index 0000000000..121007783d Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/b9abeb89a255b98c7dcf1c740f6a352dfd6ef0a5 differ diff --git a/external/boringssl/fuzz/client_corpus/baadac1b80a15dbf1db8ba42c4f439cbcd911828 b/external/boringssl/fuzz/client_corpus/baadac1b80a15dbf1db8ba42c4f439cbcd911828 new file mode 100644 index 0000000000..97494ba6da Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/baadac1b80a15dbf1db8ba42c4f439cbcd911828 differ diff --git a/external/boringssl/fuzz/client_corpus/baf11ce608a902568d00f98bca4ff7a819bb60b6 b/external/boringssl/fuzz/client_corpus/baf11ce608a902568d00f98bca4ff7a819bb60b6 new file mode 100644 index 0000000000..01b8f4f266 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/baf11ce608a902568d00f98bca4ff7a819bb60b6 differ diff --git a/external/boringssl/fuzz/client_corpus/bb0a8f58a539f9ad9ae76ca78dee870fe4fe63f7 b/external/boringssl/fuzz/client_corpus/bb0a8f58a539f9ad9ae76ca78dee870fe4fe63f7 new file mode 100644 index 0000000000..5d99a7c849 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/bb0a8f58a539f9ad9ae76ca78dee870fe4fe63f7 differ diff --git a/external/boringssl/fuzz/client_corpus/bb4436d1ef9495c9e28cca2f036cb9542d6e9a5c b/external/boringssl/fuzz/client_corpus/bb4436d1ef9495c9e28cca2f036cb9542d6e9a5c new file mode 100644 index 0000000000..944e1763d4 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/bb4436d1ef9495c9e28cca2f036cb9542d6e9a5c differ diff --git a/external/boringssl/fuzz/client_corpus/bb6db7d33c7d284a648fa1ec3b063027b85e4246 b/external/boringssl/fuzz/client_corpus/bb6db7d33c7d284a648fa1ec3b063027b85e4246 new file mode 100644 index 0000000000..a08cc69111 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/bb6db7d33c7d284a648fa1ec3b063027b85e4246 differ diff --git a/external/boringssl/fuzz/client_corpus/bb9c2f7c0e7e527e32ee0f76f7115c1a69894c55 b/external/boringssl/fuzz/client_corpus/bb9c2f7c0e7e527e32ee0f76f7115c1a69894c55 new file mode 100644 index 0000000000..60aecbecd2 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/bb9c2f7c0e7e527e32ee0f76f7115c1a69894c55 differ diff --git a/external/boringssl/fuzz/client_corpus/bc6b78c3b0976d705b9e1ac3e72f5a9f0d5fc4f4 b/external/boringssl/fuzz/client_corpus/bc6b78c3b0976d705b9e1ac3e72f5a9f0d5fc4f4 new file mode 100644 index 0000000000..db54f255d9 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/bc6b78c3b0976d705b9e1ac3e72f5a9f0d5fc4f4 differ diff --git a/external/boringssl/fuzz/client_corpus/bc72c2884450288e4b04aa3a04e632259ba7bb29 b/external/boringssl/fuzz/client_corpus/bc72c2884450288e4b04aa3a04e632259ba7bb29 new file mode 100644 index 0000000000..7211dbac79 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/bc72c2884450288e4b04aa3a04e632259ba7bb29 differ diff --git a/external/boringssl/fuzz/client_corpus/bc82b67ead0462d088b02bc7bd2fc9916f522730 b/external/boringssl/fuzz/client_corpus/bc82b67ead0462d088b02bc7bd2fc9916f522730 new file mode 100644 index 0000000000..f2e650612d Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/bc82b67ead0462d088b02bc7bd2fc9916f522730 differ diff --git a/external/boringssl/fuzz/client_corpus/bcc2c2490f36613db8fd45ff4bdd3bc4b52cb2e4 b/external/boringssl/fuzz/client_corpus/bcc2c2490f36613db8fd45ff4bdd3bc4b52cb2e4 new file mode 100644 index 0000000000..a0a003bd5f Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/bcc2c2490f36613db8fd45ff4bdd3bc4b52cb2e4 differ diff --git a/external/boringssl/fuzz/client_corpus/bd011a83422f5d64081ea5c6c9caf1224292ad42 b/external/boringssl/fuzz/client_corpus/bd011a83422f5d64081ea5c6c9caf1224292ad42 new file mode 100644 index 0000000000..c90a8e6487 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/bd011a83422f5d64081ea5c6c9caf1224292ad42 differ diff --git a/external/boringssl/fuzz/client_corpus/bd466cc2cf72548409171797d3825e499c74a8d0 b/external/boringssl/fuzz/client_corpus/bd466cc2cf72548409171797d3825e499c74a8d0 new file mode 100644 index 0000000000..72aadda8fb Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/bd466cc2cf72548409171797d3825e499c74a8d0 differ diff --git a/external/boringssl/fuzz/client_corpus/bd5f333b42d9e02433074109af2ed85120648125 b/external/boringssl/fuzz/client_corpus/bd5f333b42d9e02433074109af2ed85120648125 new file mode 100644 index 0000000000..648643994a Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/bd5f333b42d9e02433074109af2ed85120648125 differ diff --git a/external/boringssl/fuzz/client_corpus/bdb1831c86d75d7dbfc9350ca5cc1aaf81ef0c7c b/external/boringssl/fuzz/client_corpus/bdb1831c86d75d7dbfc9350ca5cc1aaf81ef0c7c new file mode 100644 index 0000000000..0d8683e8c9 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/bdb1831c86d75d7dbfc9350ca5cc1aaf81ef0c7c differ diff --git a/external/boringssl/fuzz/client_corpus/be295faf55c0b0d81ae1ad6725c19e8910e3a0ed b/external/boringssl/fuzz/client_corpus/be295faf55c0b0d81ae1ad6725c19e8910e3a0ed new file mode 100644 index 0000000000..3c505f629c Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/be295faf55c0b0d81ae1ad6725c19e8910e3a0ed differ diff --git a/external/boringssl/fuzz/client_corpus/bf329543f2b0cd6f4ed335035294caef4853baf0 b/external/boringssl/fuzz/client_corpus/bf329543f2b0cd6f4ed335035294caef4853baf0 new file mode 100644 index 0000000000..9ccb37f5cc Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/bf329543f2b0cd6f4ed335035294caef4853baf0 differ diff --git a/external/boringssl/fuzz/client_corpus/bf3afcd912f6bb94259c0892591fa1c90fab98ea b/external/boringssl/fuzz/client_corpus/bf3afcd912f6bb94259c0892591fa1c90fab98ea new file mode 100644 index 0000000000..ad6e1c251b Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/bf3afcd912f6bb94259c0892591fa1c90fab98ea differ diff --git a/external/boringssl/fuzz/client_corpus/c01dc2df8abf8fa0da256c42671eb3ccef2c7583 b/external/boringssl/fuzz/client_corpus/c01dc2df8abf8fa0da256c42671eb3ccef2c7583 new file mode 100644 index 0000000000..edd886642f Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/c01dc2df8abf8fa0da256c42671eb3ccef2c7583 differ diff --git a/external/boringssl/fuzz/client_corpus/c03fbdfcb8e959099df158b38e16e6e98fa0a8f1 b/external/boringssl/fuzz/client_corpus/c03fbdfcb8e959099df158b38e16e6e98fa0a8f1 new file mode 100644 index 0000000000..3a46250ce3 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/c03fbdfcb8e959099df158b38e16e6e98fa0a8f1 differ diff --git a/external/boringssl/fuzz/client_corpus/c12fd34002a04bef3844ea9baaa3afafc0b68f8c b/external/boringssl/fuzz/client_corpus/c12fd34002a04bef3844ea9baaa3afafc0b68f8c new file mode 100644 index 0000000000..7e36aea190 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/c12fd34002a04bef3844ea9baaa3afafc0b68f8c differ diff --git a/external/boringssl/fuzz/client_corpus/c1ec31d151af62da3c866eb4399bae3ea8fc9d4d b/external/boringssl/fuzz/client_corpus/c1ec31d151af62da3c866eb4399bae3ea8fc9d4d new file mode 100644 index 0000000000..ac533ee719 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/c1ec31d151af62da3c866eb4399bae3ea8fc9d4d differ diff --git a/external/boringssl/fuzz/client_corpus/c1f877b95dfe5d06ebfb3e7a7d7b16e24985b8e8 b/external/boringssl/fuzz/client_corpus/c1f877b95dfe5d06ebfb3e7a7d7b16e24985b8e8 new file mode 100644 index 0000000000..2a8c3f7ab8 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/c1f877b95dfe5d06ebfb3e7a7d7b16e24985b8e8 differ diff --git a/external/boringssl/fuzz/client_corpus/c262943ec79d2929acb8beab22686d0687c4427e b/external/boringssl/fuzz/client_corpus/c262943ec79d2929acb8beab22686d0687c4427e new file mode 100644 index 0000000000..8086922fbb Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/c262943ec79d2929acb8beab22686d0687c4427e differ diff --git a/external/boringssl/fuzz/client_corpus/c2707301c99a3b7447cbc72f5bf9f2d133c66e86 b/external/boringssl/fuzz/client_corpus/c2707301c99a3b7447cbc72f5bf9f2d133c66e86 new file mode 100644 index 0000000000..f9aeeaa0d1 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/c2707301c99a3b7447cbc72f5bf9f2d133c66e86 differ diff --git a/external/boringssl/fuzz/client_corpus/c27785bdba6f5e27bf38a51a58058998fe3edf8d b/external/boringssl/fuzz/client_corpus/c27785bdba6f5e27bf38a51a58058998fe3edf8d new file mode 100644 index 0000000000..5097207823 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/c27785bdba6f5e27bf38a51a58058998fe3edf8d differ diff --git a/external/boringssl/fuzz/client_corpus/c3324216917872b674aff6cdcb6f4aef27045523 b/external/boringssl/fuzz/client_corpus/c3324216917872b674aff6cdcb6f4aef27045523 new file mode 100644 index 0000000000..24a3c7bf00 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/c3324216917872b674aff6cdcb6f4aef27045523 differ diff --git a/external/boringssl/fuzz/client_corpus/c4146e5fc9388f70a690f71722d86e7a38caa419 b/external/boringssl/fuzz/client_corpus/c4146e5fc9388f70a690f71722d86e7a38caa419 new file mode 100644 index 0000000000..9dbc3ebb0f Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/c4146e5fc9388f70a690f71722d86e7a38caa419 differ diff --git a/external/boringssl/fuzz/client_corpus/c49fb6353471694f0c78891efa2faf9f093c98d9 b/external/boringssl/fuzz/client_corpus/c49fb6353471694f0c78891efa2faf9f093c98d9 new file mode 100644 index 0000000000..f0e8454e14 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/c49fb6353471694f0c78891efa2faf9f093c98d9 differ diff --git a/external/boringssl/fuzz/client_corpus/c504bcfb34d2cb10820c049d5437e9a9744b9224 b/external/boringssl/fuzz/client_corpus/c504bcfb34d2cb10820c049d5437e9a9744b9224 new file mode 100644 index 0000000000..81d8a4b6b6 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/c504bcfb34d2cb10820c049d5437e9a9744b9224 differ diff --git a/external/boringssl/fuzz/client_corpus/c55fd6f979e9fe13ce89b4e236f40c4bd1bed862 b/external/boringssl/fuzz/client_corpus/c55fd6f979e9fe13ce89b4e236f40c4bd1bed862 new file mode 100644 index 0000000000..ff34cd820d Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/c55fd6f979e9fe13ce89b4e236f40c4bd1bed862 differ diff --git a/external/boringssl/fuzz/client_corpus/c588d48045128b1d22de91bb640411cfaa4bc9ad b/external/boringssl/fuzz/client_corpus/c588d48045128b1d22de91bb640411cfaa4bc9ad new file mode 100644 index 0000000000..5e9c47b0b4 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/c588d48045128b1d22de91bb640411cfaa4bc9ad differ diff --git a/external/boringssl/fuzz/client_corpus/c58f346547bdcb658ad1cb70fff078b8701dd117 b/external/boringssl/fuzz/client_corpus/c58f346547bdcb658ad1cb70fff078b8701dd117 new file mode 100644 index 0000000000..86aae327ba Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/c58f346547bdcb658ad1cb70fff078b8701dd117 differ diff --git a/external/boringssl/fuzz/client_corpus/c676b7ee163f0a21bb6577d2649aa5d5cab305d8 b/external/boringssl/fuzz/client_corpus/c676b7ee163f0a21bb6577d2649aa5d5cab305d8 new file mode 100644 index 0000000000..1100e024a7 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/c676b7ee163f0a21bb6577d2649aa5d5cab305d8 differ diff --git a/external/boringssl/fuzz/client_corpus/c705dcc86039ee3a05d5cd15ab00cc2356d9aab7 b/external/boringssl/fuzz/client_corpus/c705dcc86039ee3a05d5cd15ab00cc2356d9aab7 new file mode 100644 index 0000000000..a1dc9e76d2 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/c705dcc86039ee3a05d5cd15ab00cc2356d9aab7 differ diff --git a/external/boringssl/fuzz/client_corpus/c788bb2baf4eaccebbdbbd865fd36688103057cb b/external/boringssl/fuzz/client_corpus/c788bb2baf4eaccebbdbbd865fd36688103057cb new file mode 100644 index 0000000000..2b9a6326e0 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/c788bb2baf4eaccebbdbbd865fd36688103057cb differ diff --git a/external/boringssl/fuzz/client_corpus/c78af7af9a7f67ab59e314cfe67ca7825d697705 b/external/boringssl/fuzz/client_corpus/c78af7af9a7f67ab59e314cfe67ca7825d697705 new file mode 100644 index 0000000000..467e489964 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/c78af7af9a7f67ab59e314cfe67ca7825d697705 differ diff --git a/external/boringssl/fuzz/client_corpus/c78e5014d7ea4b8fcd106de5d889cec13d3d68e7 b/external/boringssl/fuzz/client_corpus/c78e5014d7ea4b8fcd106de5d889cec13d3d68e7 new file mode 100644 index 0000000000..dfba4e97fd Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/c78e5014d7ea4b8fcd106de5d889cec13d3d68e7 differ diff --git a/external/boringssl/fuzz/client_corpus/c78ece72bae26caf43d6739f97a17ed5dda5490b b/external/boringssl/fuzz/client_corpus/c78ece72bae26caf43d6739f97a17ed5dda5490b new file mode 100644 index 0000000000..c460cd2a00 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/c78ece72bae26caf43d6739f97a17ed5dda5490b differ diff --git a/external/boringssl/fuzz/client_corpus/c8664ec4a19b06e1d468cb8ba5d87447f1e4aa89 b/external/boringssl/fuzz/client_corpus/c8664ec4a19b06e1d468cb8ba5d87447f1e4aa89 new file mode 100644 index 0000000000..dfc62bcc47 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/c8664ec4a19b06e1d468cb8ba5d87447f1e4aa89 differ diff --git a/external/boringssl/fuzz/client_corpus/c915f6eb5bf85d6f906722e77e4ec28493ed54d2 b/external/boringssl/fuzz/client_corpus/c915f6eb5bf85d6f906722e77e4ec28493ed54d2 new file mode 100644 index 0000000000..15509e7d6d Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/c915f6eb5bf85d6f906722e77e4ec28493ed54d2 differ diff --git a/external/boringssl/fuzz/client_corpus/c992a79f1c3f1f793885df808cb830ea934099a0 b/external/boringssl/fuzz/client_corpus/c992a79f1c3f1f793885df808cb830ea934099a0 new file mode 100644 index 0000000000..58259ec0a1 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/c992a79f1c3f1f793885df808cb830ea934099a0 differ diff --git a/external/boringssl/fuzz/client_corpus/c9ff9d69ff63ca545ec8ac2585c3c5202c2e552e b/external/boringssl/fuzz/client_corpus/c9ff9d69ff63ca545ec8ac2585c3c5202c2e552e new file mode 100644 index 0000000000..c1257daeda Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/c9ff9d69ff63ca545ec8ac2585c3c5202c2e552e differ diff --git a/external/boringssl/fuzz/client_corpus/c9ffc718c34d14f22de37b5b4f23747ea9c1c1c7 b/external/boringssl/fuzz/client_corpus/c9ffc718c34d14f22de37b5b4f23747ea9c1c1c7 new file mode 100644 index 0000000000..de136f1e32 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/c9ffc718c34d14f22de37b5b4f23747ea9c1c1c7 differ diff --git a/external/boringssl/fuzz/client_corpus/cac2b2aad6911e529198d2255be8f5fd47192152 b/external/boringssl/fuzz/client_corpus/cac2b2aad6911e529198d2255be8f5fd47192152 new file mode 100644 index 0000000000..df7c99c775 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/cac2b2aad6911e529198d2255be8f5fd47192152 differ diff --git a/external/boringssl/fuzz/client_corpus/cad08942d1b38a26085b2550c66de32fef4faa5c b/external/boringssl/fuzz/client_corpus/cad08942d1b38a26085b2550c66de32fef4faa5c new file mode 100644 index 0000000000..fb280cb8e1 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/cad08942d1b38a26085b2550c66de32fef4faa5c differ diff --git a/external/boringssl/fuzz/client_corpus/cbab437e9479b87d3cc898a5db555d5cca59db3b b/external/boringssl/fuzz/client_corpus/cbab437e9479b87d3cc898a5db555d5cca59db3b new file mode 100644 index 0000000000..75eabcaec3 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/cbab437e9479b87d3cc898a5db555d5cca59db3b differ diff --git a/external/boringssl/fuzz/client_corpus/cbc503f6dd40fdc5f03e8a90044cf183a595600a b/external/boringssl/fuzz/client_corpus/cbc503f6dd40fdc5f03e8a90044cf183a595600a new file mode 100644 index 0000000000..4ce7560498 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/cbc503f6dd40fdc5f03e8a90044cf183a595600a differ diff --git a/external/boringssl/fuzz/client_corpus/cc3c09cc41156962a002569cc7467bf10ef77721 b/external/boringssl/fuzz/client_corpus/cc3c09cc41156962a002569cc7467bf10ef77721 new file mode 100644 index 0000000000..cf02099c00 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/cc3c09cc41156962a002569cc7467bf10ef77721 differ diff --git a/external/boringssl/fuzz/client_corpus/ccd0c03acdc4430cbc759f3d672ff530c1d3ad48 b/external/boringssl/fuzz/client_corpus/ccd0c03acdc4430cbc759f3d672ff530c1d3ad48 new file mode 100644 index 0000000000..fa64070065 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/ccd0c03acdc4430cbc759f3d672ff530c1d3ad48 differ diff --git a/external/boringssl/fuzz/client_corpus/cd89f3d76d270f94df4e98676711f9afddcd0a81 b/external/boringssl/fuzz/client_corpus/cd89f3d76d270f94df4e98676711f9afddcd0a81 new file mode 100644 index 0000000000..86571246e3 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/cd89f3d76d270f94df4e98676711f9afddcd0a81 differ diff --git a/external/boringssl/fuzz/client_corpus/cddf422981522324fdb5b0b1a7cfe9ac0305e5b2 b/external/boringssl/fuzz/client_corpus/cddf422981522324fdb5b0b1a7cfe9ac0305e5b2 new file mode 100644 index 0000000000..50331c1790 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/cddf422981522324fdb5b0b1a7cfe9ac0305e5b2 differ diff --git a/external/boringssl/fuzz/client_corpus/cde1c623e7095e180c3a485bc8333cf8bee2e984 b/external/boringssl/fuzz/client_corpus/cde1c623e7095e180c3a485bc8333cf8bee2e984 new file mode 100644 index 0000000000..ef0769f957 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/cde1c623e7095e180c3a485bc8333cf8bee2e984 differ diff --git a/external/boringssl/fuzz/client_corpus/ce6c351af3d3912d66db41de4a2c71fa812e8d41 b/external/boringssl/fuzz/client_corpus/ce6c351af3d3912d66db41de4a2c71fa812e8d41 new file mode 100644 index 0000000000..9108f179b3 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/ce6c351af3d3912d66db41de4a2c71fa812e8d41 differ diff --git a/external/boringssl/fuzz/client_corpus/ce93d2a149cdc6695256b062cfd1225092ba565d b/external/boringssl/fuzz/client_corpus/ce93d2a149cdc6695256b062cfd1225092ba565d new file mode 100644 index 0000000000..4547363a73 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/ce93d2a149cdc6695256b062cfd1225092ba565d differ diff --git a/external/boringssl/fuzz/client_corpus/cea198948bc4ad0e2eeaf2ccf116d53c0c577881 b/external/boringssl/fuzz/client_corpus/cea198948bc4ad0e2eeaf2ccf116d53c0c577881 new file mode 100644 index 0000000000..270483ccfb Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/cea198948bc4ad0e2eeaf2ccf116d53c0c577881 differ diff --git a/external/boringssl/fuzz/client_corpus/cea7fd28eef6a02a13ea90d784c1207dded60b92 b/external/boringssl/fuzz/client_corpus/cea7fd28eef6a02a13ea90d784c1207dded60b92 new file mode 100644 index 0000000000..658631664c Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/cea7fd28eef6a02a13ea90d784c1207dded60b92 differ diff --git a/external/boringssl/fuzz/client_corpus/ced8a723d0468a850f5aa93642f934e547928f41 b/external/boringssl/fuzz/client_corpus/ced8a723d0468a850f5aa93642f934e547928f41 new file mode 100644 index 0000000000..864361fa13 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/ced8a723d0468a850f5aa93642f934e547928f41 differ diff --git a/external/boringssl/fuzz/client_corpus/cf6f67c363efa2d77cdc6b81f6e74c9fc3e17143 b/external/boringssl/fuzz/client_corpus/cf6f67c363efa2d77cdc6b81f6e74c9fc3e17143 new file mode 100644 index 0000000000..401fab1ca3 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/cf6f67c363efa2d77cdc6b81f6e74c9fc3e17143 differ diff --git a/external/boringssl/fuzz/client_corpus/d0288bf062576db0058deb80e6a475d6b1fdbc60 b/external/boringssl/fuzz/client_corpus/d0288bf062576db0058deb80e6a475d6b1fdbc60 new file mode 100644 index 0000000000..d9ddb7b878 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/d0288bf062576db0058deb80e6a475d6b1fdbc60 differ diff --git a/external/boringssl/fuzz/client_corpus/d032befc9c75ee26197c43f1d189c231d9aa824b b/external/boringssl/fuzz/client_corpus/d032befc9c75ee26197c43f1d189c231d9aa824b new file mode 100644 index 0000000000..d6f34ede5c Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/d032befc9c75ee26197c43f1d189c231d9aa824b differ diff --git a/external/boringssl/fuzz/client_corpus/d03537cd5fde0747d593075d6a6f595f6a425a84 b/external/boringssl/fuzz/client_corpus/d03537cd5fde0747d593075d6a6f595f6a425a84 new file mode 100644 index 0000000000..2bf136e924 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/d03537cd5fde0747d593075d6a6f595f6a425a84 differ diff --git a/external/boringssl/fuzz/client_corpus/d03a3bf8b4d1976030d1584960ac3dea63e06290 b/external/boringssl/fuzz/client_corpus/d03a3bf8b4d1976030d1584960ac3dea63e06290 new file mode 100644 index 0000000000..5d23763c81 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/d03a3bf8b4d1976030d1584960ac3dea63e06290 differ diff --git a/external/boringssl/fuzz/client_corpus/d058010606ec0a6c48817aa0d93a48e455e8c00f b/external/boringssl/fuzz/client_corpus/d058010606ec0a6c48817aa0d93a48e455e8c00f new file mode 100644 index 0000000000..a2ed9df3d3 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/d058010606ec0a6c48817aa0d93a48e455e8c00f differ diff --git a/external/boringssl/fuzz/client_corpus/d12a59b71ab1c96bada47b4a2ec2a6376699e344 b/external/boringssl/fuzz/client_corpus/d12a59b71ab1c96bada47b4a2ec2a6376699e344 new file mode 100644 index 0000000000..eee8294698 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/d12a59b71ab1c96bada47b4a2ec2a6376699e344 differ diff --git a/external/boringssl/fuzz/client_corpus/d1788576205c4adf09461c7961a29a2b41fa9f04 b/external/boringssl/fuzz/client_corpus/d1788576205c4adf09461c7961a29a2b41fa9f04 new file mode 100644 index 0000000000..47834725a4 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/d1788576205c4adf09461c7961a29a2b41fa9f04 differ diff --git a/external/boringssl/fuzz/client_corpus/d17b3b5c53b857d35787caf5a547e58e5a326f90 b/external/boringssl/fuzz/client_corpus/d17b3b5c53b857d35787caf5a547e58e5a326f90 new file mode 100644 index 0000000000..abd2edbc22 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/d17b3b5c53b857d35787caf5a547e58e5a326f90 differ diff --git a/external/boringssl/fuzz/client_corpus/d1b04032c449ccfdb320500ce922e905a9b746f6 b/external/boringssl/fuzz/client_corpus/d1b04032c449ccfdb320500ce922e905a9b746f6 new file mode 100644 index 0000000000..e4ae2cd095 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/d1b04032c449ccfdb320500ce922e905a9b746f6 differ diff --git a/external/boringssl/fuzz/client_corpus/d2c608fc637a44b7ab58dfbd2adfc919857c9a6d b/external/boringssl/fuzz/client_corpus/d2c608fc637a44b7ab58dfbd2adfc919857c9a6d new file mode 100644 index 0000000000..689d3b013f Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/d2c608fc637a44b7ab58dfbd2adfc919857c9a6d differ diff --git a/external/boringssl/fuzz/client_corpus/d2dc18b5d34852e1a4e1c9956d729259af11c024 b/external/boringssl/fuzz/client_corpus/d2dc18b5d34852e1a4e1c9956d729259af11c024 new file mode 100644 index 0000000000..38d69d752e Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/d2dc18b5d34852e1a4e1c9956d729259af11c024 differ diff --git a/external/boringssl/fuzz/client_corpus/d35b83a8f3a1503d9d8682d2e123127c42852032 b/external/boringssl/fuzz/client_corpus/d35b83a8f3a1503d9d8682d2e123127c42852032 new file mode 100644 index 0000000000..13c311a66e Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/d35b83a8f3a1503d9d8682d2e123127c42852032 differ diff --git a/external/boringssl/fuzz/client_corpus/d44d74d1e715b1eff600cf9025ccf7980cdbeb19 b/external/boringssl/fuzz/client_corpus/d44d74d1e715b1eff600cf9025ccf7980cdbeb19 new file mode 100644 index 0000000000..77c13c41b4 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/d44d74d1e715b1eff600cf9025ccf7980cdbeb19 differ diff --git a/external/boringssl/fuzz/client_corpus/d4826144f817a4419086d0c3e6eaf326843ab005 b/external/boringssl/fuzz/client_corpus/d4826144f817a4419086d0c3e6eaf326843ab005 new file mode 100644 index 0000000000..958846402c Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/d4826144f817a4419086d0c3e6eaf326843ab005 differ diff --git a/external/boringssl/fuzz/client_corpus/d49261c056a68e3789b2aa041c9a8372f9342603 b/external/boringssl/fuzz/client_corpus/d49261c056a68e3789b2aa041c9a8372f9342603 new file mode 100644 index 0000000000..1bdedc18ee Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/d49261c056a68e3789b2aa041c9a8372f9342603 differ diff --git a/external/boringssl/fuzz/client_corpus/d4ddfce77cf7f1e9b50618c636f9a811dbc64e69 b/external/boringssl/fuzz/client_corpus/d4ddfce77cf7f1e9b50618c636f9a811dbc64e69 new file mode 100644 index 0000000000..003a7458a8 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/d4ddfce77cf7f1e9b50618c636f9a811dbc64e69 differ diff --git a/external/boringssl/fuzz/client_corpus/d4e7f76de93312778f03a167ef99b93e8a277694 b/external/boringssl/fuzz/client_corpus/d4e7f76de93312778f03a167ef99b93e8a277694 new file mode 100644 index 0000000000..e5efee8634 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/d4e7f76de93312778f03a167ef99b93e8a277694 differ diff --git a/external/boringssl/fuzz/client_corpus/d50e0da5bd72f68d49bbe8b080dfe16587f9317a b/external/boringssl/fuzz/client_corpus/d50e0da5bd72f68d49bbe8b080dfe16587f9317a new file mode 100644 index 0000000000..147853c8fe Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/d50e0da5bd72f68d49bbe8b080dfe16587f9317a differ diff --git a/external/boringssl/fuzz/client_corpus/d5149852f264e96d3a7bfb87aeacf88e21d7cd81 b/external/boringssl/fuzz/client_corpus/d5149852f264e96d3a7bfb87aeacf88e21d7cd81 new file mode 100644 index 0000000000..179b470a97 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/d5149852f264e96d3a7bfb87aeacf88e21d7cd81 differ diff --git a/external/boringssl/fuzz/client_corpus/d5278057d56703a1526dae2e78a40392f9d1a0d7 b/external/boringssl/fuzz/client_corpus/d5278057d56703a1526dae2e78a40392f9d1a0d7 new file mode 100644 index 0000000000..8deb82aff8 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/d5278057d56703a1526dae2e78a40392f9d1a0d7 differ diff --git a/external/boringssl/fuzz/client_corpus/d531f5874372bc6af0e744859bca3eeb101e0d52 b/external/boringssl/fuzz/client_corpus/d531f5874372bc6af0e744859bca3eeb101e0d52 new file mode 100644 index 0000000000..9410f6b3b3 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/d531f5874372bc6af0e744859bca3eeb101e0d52 differ diff --git a/external/boringssl/fuzz/client_corpus/d54b651c80434d4c87f0ffc1a94a8934bfcbe57c b/external/boringssl/fuzz/client_corpus/d54b651c80434d4c87f0ffc1a94a8934bfcbe57c new file mode 100644 index 0000000000..4f9459f93f Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/d54b651c80434d4c87f0ffc1a94a8934bfcbe57c differ diff --git a/external/boringssl/fuzz/client_corpus/d5a14089cae100bd2a22abd28263798e146743e7 b/external/boringssl/fuzz/client_corpus/d5a14089cae100bd2a22abd28263798e146743e7 new file mode 100644 index 0000000000..45e4dd2276 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/d5a14089cae100bd2a22abd28263798e146743e7 differ diff --git a/external/boringssl/fuzz/client_corpus/d5c17cf9f504aa2b8013d4a70e9f197c5ec1ee01 b/external/boringssl/fuzz/client_corpus/d5c17cf9f504aa2b8013d4a70e9f197c5ec1ee01 new file mode 100644 index 0000000000..93c24c24c7 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/d5c17cf9f504aa2b8013d4a70e9f197c5ec1ee01 differ diff --git a/external/boringssl/fuzz/client_corpus/d5ed598cfe5995c9f93d9141181d629b5122efd0 b/external/boringssl/fuzz/client_corpus/d5ed598cfe5995c9f93d9141181d629b5122efd0 new file mode 100644 index 0000000000..606094c671 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/d5ed598cfe5995c9f93d9141181d629b5122efd0 differ diff --git a/external/boringssl/fuzz/client_corpus/d60a9a78b49e24cffcf407fe5fd50bb9365b4278 b/external/boringssl/fuzz/client_corpus/d60a9a78b49e24cffcf407fe5fd50bb9365b4278 new file mode 100644 index 0000000000..f8786fd23b Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/d60a9a78b49e24cffcf407fe5fd50bb9365b4278 differ diff --git a/external/boringssl/fuzz/client_corpus/d60b4797ac2c7cc376e670dd97ded488a75d7a02 b/external/boringssl/fuzz/client_corpus/d60b4797ac2c7cc376e670dd97ded488a75d7a02 new file mode 100644 index 0000000000..bbc61cd650 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/d60b4797ac2c7cc376e670dd97ded488a75d7a02 differ diff --git a/external/boringssl/fuzz/client_corpus/d61f9163c366f3cb907570af9263cfe139523275 b/external/boringssl/fuzz/client_corpus/d61f9163c366f3cb907570af9263cfe139523275 new file mode 100644 index 0000000000..4c166a0277 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/d61f9163c366f3cb907570af9263cfe139523275 differ diff --git a/external/boringssl/fuzz/client_corpus/d62572b25b3b2f5d91a46757a7b98b5823d601a4 b/external/boringssl/fuzz/client_corpus/d62572b25b3b2f5d91a46757a7b98b5823d601a4 new file mode 100644 index 0000000000..d7a6442aff Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/d62572b25b3b2f5d91a46757a7b98b5823d601a4 differ diff --git a/external/boringssl/fuzz/client_corpus/d62c0e1927c0518813dc457bf4b9798096758399 b/external/boringssl/fuzz/client_corpus/d62c0e1927c0518813dc457bf4b9798096758399 new file mode 100644 index 0000000000..ab0d67ce73 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/d62c0e1927c0518813dc457bf4b9798096758399 differ diff --git a/external/boringssl/fuzz/client_corpus/d799d28eea5dc9ec1b00e18d9bb650a069304d10 b/external/boringssl/fuzz/client_corpus/d799d28eea5dc9ec1b00e18d9bb650a069304d10 new file mode 100644 index 0000000000..4cab30e522 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/d799d28eea5dc9ec1b00e18d9bb650a069304d10 differ diff --git a/external/boringssl/fuzz/client_corpus/d7b49428ad8ba32ff3ed0de60bb2454517ad4318 b/external/boringssl/fuzz/client_corpus/d7b49428ad8ba32ff3ed0de60bb2454517ad4318 new file mode 100644 index 0000000000..1017355663 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/d7b49428ad8ba32ff3ed0de60bb2454517ad4318 differ diff --git a/external/boringssl/fuzz/client_corpus/d80d720514be9459653d2eb637ea5b76c6982d3b b/external/boringssl/fuzz/client_corpus/d80d720514be9459653d2eb637ea5b76c6982d3b new file mode 100644 index 0000000000..07c1ebecc5 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/d80d720514be9459653d2eb637ea5b76c6982d3b differ diff --git a/external/boringssl/fuzz/client_corpus/d94dc3e2729f9aba19d5ac15ee1cdd14edc4f58b b/external/boringssl/fuzz/client_corpus/d94dc3e2729f9aba19d5ac15ee1cdd14edc4f58b new file mode 100644 index 0000000000..5285739716 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/d94dc3e2729f9aba19d5ac15ee1cdd14edc4f58b differ diff --git a/external/boringssl/fuzz/client_corpus/d9533ed23666d92676c97620061e21a33d6d1bc5 b/external/boringssl/fuzz/client_corpus/d9533ed23666d92676c97620061e21a33d6d1bc5 new file mode 100644 index 0000000000..bd9c75d5ac Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/d9533ed23666d92676c97620061e21a33d6d1bc5 differ diff --git a/external/boringssl/fuzz/client_corpus/d9d1d1a511c5a753ad80a380f28a4e405e73ca4e b/external/boringssl/fuzz/client_corpus/d9d1d1a511c5a753ad80a380f28a4e405e73ca4e new file mode 100644 index 0000000000..ab390ad12c Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/d9d1d1a511c5a753ad80a380f28a4e405e73ca4e differ diff --git a/external/boringssl/fuzz/client_corpus/da8789ba323501ec7ca492232eb9a0ab1fff559d b/external/boringssl/fuzz/client_corpus/da8789ba323501ec7ca492232eb9a0ab1fff559d new file mode 100644 index 0000000000..a25e83f3ca Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/da8789ba323501ec7ca492232eb9a0ab1fff559d differ diff --git a/external/boringssl/fuzz/client_corpus/db1a0fcfb08514ca415b2009b06d4d03fa85d93d b/external/boringssl/fuzz/client_corpus/db1a0fcfb08514ca415b2009b06d4d03fa85d93d new file mode 100644 index 0000000000..f58beb3724 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/db1a0fcfb08514ca415b2009b06d4d03fa85d93d differ diff --git a/external/boringssl/fuzz/client_corpus/dbe1c29786bcb974e23eeeb948a094b8b60ed6bd b/external/boringssl/fuzz/client_corpus/dbe1c29786bcb974e23eeeb948a094b8b60ed6bd new file mode 100644 index 0000000000..fd5c11763d Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/dbe1c29786bcb974e23eeeb948a094b8b60ed6bd differ diff --git a/external/boringssl/fuzz/client_corpus/dc9fd88d1bef7f495ea968bc451988098eff8ee9 b/external/boringssl/fuzz/client_corpus/dc9fd88d1bef7f495ea968bc451988098eff8ee9 new file mode 100644 index 0000000000..ec9378a012 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/dc9fd88d1bef7f495ea968bc451988098eff8ee9 differ diff --git a/external/boringssl/fuzz/client_corpus/dd0b7faae253e3f2d0251266ce65752648ecf3e0 b/external/boringssl/fuzz/client_corpus/dd0b7faae253e3f2d0251266ce65752648ecf3e0 new file mode 100644 index 0000000000..38d3203a7f Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/dd0b7faae253e3f2d0251266ce65752648ecf3e0 differ diff --git a/external/boringssl/fuzz/client_corpus/dd0d01989ca202ed57067269b166148bc2c5575f b/external/boringssl/fuzz/client_corpus/dd0d01989ca202ed57067269b166148bc2c5575f new file mode 100644 index 0000000000..e2f8f46579 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/dd0d01989ca202ed57067269b166148bc2c5575f differ diff --git a/external/boringssl/fuzz/client_corpus/dd7ce1ad6b11303be4937c29f4724c24e6b5ea2d b/external/boringssl/fuzz/client_corpus/dd7ce1ad6b11303be4937c29f4724c24e6b5ea2d new file mode 100644 index 0000000000..78eec5aa34 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/dd7ce1ad6b11303be4937c29f4724c24e6b5ea2d differ diff --git a/external/boringssl/fuzz/client_corpus/dd8287ebeb79534ebe090d6085806f3b44fdfe30 b/external/boringssl/fuzz/client_corpus/dd8287ebeb79534ebe090d6085806f3b44fdfe30 new file mode 100644 index 0000000000..fbf79852fa Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/dd8287ebeb79534ebe090d6085806f3b44fdfe30 differ diff --git a/external/boringssl/fuzz/client_corpus/dd8cf6b21f54ae0083050f5458e54b1dbc3180c9 b/external/boringssl/fuzz/client_corpus/dd8cf6b21f54ae0083050f5458e54b1dbc3180c9 new file mode 100644 index 0000000000..2cb8af315a Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/dd8cf6b21f54ae0083050f5458e54b1dbc3180c9 differ diff --git a/external/boringssl/fuzz/client_corpus/de0335436dd87366e3be8c7d728943a7c6177aba b/external/boringssl/fuzz/client_corpus/de0335436dd87366e3be8c7d728943a7c6177aba new file mode 100644 index 0000000000..46f629b161 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/de0335436dd87366e3be8c7d728943a7c6177aba differ diff --git a/external/boringssl/fuzz/client_corpus/de66c31a968bf35553dff76e45831ecf1000856a b/external/boringssl/fuzz/client_corpus/de66c31a968bf35553dff76e45831ecf1000856a new file mode 100644 index 0000000000..fe5590baab Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/de66c31a968bf35553dff76e45831ecf1000856a differ diff --git a/external/boringssl/fuzz/client_corpus/de98b3137af7eab1edef6958a79ff8d731056f01 b/external/boringssl/fuzz/client_corpus/de98b3137af7eab1edef6958a79ff8d731056f01 new file mode 100644 index 0000000000..21ee366403 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/de98b3137af7eab1edef6958a79ff8d731056f01 differ diff --git a/external/boringssl/fuzz/client_corpus/dedfa96557b62d4a8df63694dad15e0b0f491303 b/external/boringssl/fuzz/client_corpus/dedfa96557b62d4a8df63694dad15e0b0f491303 new file mode 100644 index 0000000000..36c6a2edba Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/dedfa96557b62d4a8df63694dad15e0b0f491303 differ diff --git a/external/boringssl/fuzz/client_corpus/df2d4210d382ad94c550c3d560c607c8febd8294 b/external/boringssl/fuzz/client_corpus/df2d4210d382ad94c550c3d560c607c8febd8294 new file mode 100644 index 0000000000..e0b56c4fcb Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/df2d4210d382ad94c550c3d560c607c8febd8294 differ diff --git a/external/boringssl/fuzz/client_corpus/df314bab00b12c1a31e29132d5eb9771ba14edc8 b/external/boringssl/fuzz/client_corpus/df314bab00b12c1a31e29132d5eb9771ba14edc8 new file mode 100644 index 0000000000..0063b9211b Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/df314bab00b12c1a31e29132d5eb9771ba14edc8 differ diff --git a/external/boringssl/fuzz/client_corpus/df58f2b01e1583f71599e1e98f5c8cb50fee4cf0 b/external/boringssl/fuzz/client_corpus/df58f2b01e1583f71599e1e98f5c8cb50fee4cf0 new file mode 100644 index 0000000000..652cf27bd5 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/df58f2b01e1583f71599e1e98f5c8cb50fee4cf0 differ diff --git a/external/boringssl/fuzz/client_corpus/df8361ab66b111e870d66da944074034a8b9aff0 b/external/boringssl/fuzz/client_corpus/df8361ab66b111e870d66da944074034a8b9aff0 new file mode 100644 index 0000000000..29850a77f6 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/df8361ab66b111e870d66da944074034a8b9aff0 differ diff --git a/external/boringssl/fuzz/client_corpus/dfa5eae13138c3035d5be8ee38d14437664b8099 b/external/boringssl/fuzz/client_corpus/dfa5eae13138c3035d5be8ee38d14437664b8099 new file mode 100644 index 0000000000..afc902a993 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/dfa5eae13138c3035d5be8ee38d14437664b8099 differ diff --git a/external/boringssl/fuzz/client_corpus/dfa62f0edaf6b90d9fa8d58b3792abf1937db679 b/external/boringssl/fuzz/client_corpus/dfa62f0edaf6b90d9fa8d58b3792abf1937db679 new file mode 100644 index 0000000000..32c1d1d1a5 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/dfa62f0edaf6b90d9fa8d58b3792abf1937db679 differ diff --git a/external/boringssl/fuzz/client_corpus/dfcb7073dea2e606dc7b1877577bbaac9c020998 b/external/boringssl/fuzz/client_corpus/dfcb7073dea2e606dc7b1877577bbaac9c020998 new file mode 100644 index 0000000000..b12fae6e10 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/dfcb7073dea2e606dc7b1877577bbaac9c020998 differ diff --git a/external/boringssl/fuzz/client_corpus/dfcf39ec02f1f05132f8cb28c9ad62fc2b6fe074 b/external/boringssl/fuzz/client_corpus/dfcf39ec02f1f05132f8cb28c9ad62fc2b6fe074 new file mode 100644 index 0000000000..75239b30bd Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/dfcf39ec02f1f05132f8cb28c9ad62fc2b6fe074 differ diff --git a/external/boringssl/fuzz/client_corpus/dfe4cc06c05e43dbedb195bd5b3e5d2cc889ab1e b/external/boringssl/fuzz/client_corpus/dfe4cc06c05e43dbedb195bd5b3e5d2cc889ab1e new file mode 100644 index 0000000000..e3b6a5f13b Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/dfe4cc06c05e43dbedb195bd5b3e5d2cc889ab1e differ diff --git a/external/boringssl/fuzz/client_corpus/dff8677490e8b612a3fa1aafea7db76a57531a7d b/external/boringssl/fuzz/client_corpus/dff8677490e8b612a3fa1aafea7db76a57531a7d new file mode 100644 index 0000000000..3e153ec8bd Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/dff8677490e8b612a3fa1aafea7db76a57531a7d differ diff --git a/external/boringssl/fuzz/client_corpus/e00c632f0217269fce83f0baac055b2e9dc522d6 b/external/boringssl/fuzz/client_corpus/e00c632f0217269fce83f0baac055b2e9dc522d6 new file mode 100644 index 0000000000..457e25ab4d Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/e00c632f0217269fce83f0baac055b2e9dc522d6 differ diff --git a/external/boringssl/fuzz/client_corpus/e04df2a864a3be5065d25603a6f79090c8f70ef8 b/external/boringssl/fuzz/client_corpus/e04df2a864a3be5065d25603a6f79090c8f70ef8 new file mode 100644 index 0000000000..c377d01d69 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/e04df2a864a3be5065d25603a6f79090c8f70ef8 differ diff --git a/external/boringssl/fuzz/client_corpus/e1fc2e3105fc3a2a7be7d48d8edce0632572a88b b/external/boringssl/fuzz/client_corpus/e1fc2e3105fc3a2a7be7d48d8edce0632572a88b new file mode 100644 index 0000000000..c036498e51 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/e1fc2e3105fc3a2a7be7d48d8edce0632572a88b differ diff --git a/external/boringssl/fuzz/client_corpus/e25a7b9befe26a89d379fecf190f4b9aad7c2305 b/external/boringssl/fuzz/client_corpus/e25a7b9befe26a89d379fecf190f4b9aad7c2305 new file mode 100644 index 0000000000..e329c770f9 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/e25a7b9befe26a89d379fecf190f4b9aad7c2305 differ diff --git a/external/boringssl/fuzz/client_corpus/e2d7108a4559fe36b7ff8854d7cf96549deb8897 b/external/boringssl/fuzz/client_corpus/e2d7108a4559fe36b7ff8854d7cf96549deb8897 new file mode 100644 index 0000000000..ddc86fe8b9 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/e2d7108a4559fe36b7ff8854d7cf96549deb8897 differ diff --git a/external/boringssl/fuzz/client_corpus/e31c99618df1f322012029dcc2e0f1d4fd4c3977 b/external/boringssl/fuzz/client_corpus/e31c99618df1f322012029dcc2e0f1d4fd4c3977 new file mode 100644 index 0000000000..64ea1ba87f Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/e31c99618df1f322012029dcc2e0f1d4fd4c3977 differ diff --git a/external/boringssl/fuzz/client_corpus/e33830dba87718ca367a275cf4c7a59ccd4927ec b/external/boringssl/fuzz/client_corpus/e33830dba87718ca367a275cf4c7a59ccd4927ec new file mode 100644 index 0000000000..9ba32c48dc Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/e33830dba87718ca367a275cf4c7a59ccd4927ec differ diff --git a/external/boringssl/fuzz/client_corpus/e3f7aeef652e35f920ed3fb6081884f12c9f9bcd b/external/boringssl/fuzz/client_corpus/e3f7aeef652e35f920ed3fb6081884f12c9f9bcd new file mode 100644 index 0000000000..a4b132c515 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/e3f7aeef652e35f920ed3fb6081884f12c9f9bcd differ diff --git a/external/boringssl/fuzz/client_corpus/e41056775fb1db9c520347187e5f33b529db14cb b/external/boringssl/fuzz/client_corpus/e41056775fb1db9c520347187e5f33b529db14cb new file mode 100644 index 0000000000..2b48328100 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/e41056775fb1db9c520347187e5f33b529db14cb differ diff --git a/external/boringssl/fuzz/client_corpus/e46cf6de573e5e07b5e2429ddca6277e5dad9b4e b/external/boringssl/fuzz/client_corpus/e46cf6de573e5e07b5e2429ddca6277e5dad9b4e new file mode 100644 index 0000000000..a768f31413 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/e46cf6de573e5e07b5e2429ddca6277e5dad9b4e differ diff --git a/external/boringssl/fuzz/client_corpus/e478fba23e6bec21363045d0d1de05237a0dcfe0 b/external/boringssl/fuzz/client_corpus/e478fba23e6bec21363045d0d1de05237a0dcfe0 new file mode 100644 index 0000000000..ccf58d07d8 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/e478fba23e6bec21363045d0d1de05237a0dcfe0 differ diff --git a/external/boringssl/fuzz/client_corpus/e48eb2509e260ee8d19ebc618b895a457491c583 b/external/boringssl/fuzz/client_corpus/e48eb2509e260ee8d19ebc618b895a457491c583 new file mode 100644 index 0000000000..c6cf70d9f6 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/e48eb2509e260ee8d19ebc618b895a457491c583 differ diff --git a/external/boringssl/fuzz/client_corpus/e4d71e3a91460379358500d9b998a911e04f0bd8 b/external/boringssl/fuzz/client_corpus/e4d71e3a91460379358500d9b998a911e04f0bd8 new file mode 100644 index 0000000000..7e401f26bd Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/e4d71e3a91460379358500d9b998a911e04f0bd8 differ diff --git a/external/boringssl/fuzz/client_corpus/e4eec0bbadced0366353f387512000ec8504f501 b/external/boringssl/fuzz/client_corpus/e4eec0bbadced0366353f387512000ec8504f501 new file mode 100644 index 0000000000..285989a334 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/e4eec0bbadced0366353f387512000ec8504f501 differ diff --git a/external/boringssl/fuzz/client_corpus/e51409d12b954c9e7478e79b1393b76c3dea5eeb b/external/boringssl/fuzz/client_corpus/e51409d12b954c9e7478e79b1393b76c3dea5eeb new file mode 100644 index 0000000000..2b8015be57 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/e51409d12b954c9e7478e79b1393b76c3dea5eeb differ diff --git a/external/boringssl/fuzz/client_corpus/e567be3c710068e4b985312b5c342e78ac177111 b/external/boringssl/fuzz/client_corpus/e567be3c710068e4b985312b5c342e78ac177111 new file mode 100644 index 0000000000..afd971f44f Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/e567be3c710068e4b985312b5c342e78ac177111 differ diff --git a/external/boringssl/fuzz/client_corpus/e5a85219718efd390ce1cffbe60cbb8fbe7bd07d b/external/boringssl/fuzz/client_corpus/e5a85219718efd390ce1cffbe60cbb8fbe7bd07d new file mode 100644 index 0000000000..68b3ebfa89 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/e5a85219718efd390ce1cffbe60cbb8fbe7bd07d differ diff --git a/external/boringssl/fuzz/client_corpus/e734d584122a869a16a10dd58fd90b82e8c9f444 b/external/boringssl/fuzz/client_corpus/e734d584122a869a16a10dd58fd90b82e8c9f444 new file mode 100644 index 0000000000..790ca6e19c Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/e734d584122a869a16a10dd58fd90b82e8c9f444 differ diff --git a/external/boringssl/fuzz/client_corpus/e74c6de58f2b27059af669fadc1c6e65fc5c2c6a b/external/boringssl/fuzz/client_corpus/e74c6de58f2b27059af669fadc1c6e65fc5c2c6a new file mode 100644 index 0000000000..2e37e07698 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/e74c6de58f2b27059af669fadc1c6e65fc5c2c6a differ diff --git a/external/boringssl/fuzz/client_corpus/e764ee13b2cbee6650ac9a43e30059748be94875 b/external/boringssl/fuzz/client_corpus/e764ee13b2cbee6650ac9a43e30059748be94875 new file mode 100644 index 0000000000..4c42849f22 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/e764ee13b2cbee6650ac9a43e30059748be94875 differ diff --git a/external/boringssl/fuzz/client_corpus/e78589cd285cd5f51be25c22e99ee6d5b3dd0fea b/external/boringssl/fuzz/client_corpus/e78589cd285cd5f51be25c22e99ee6d5b3dd0fea new file mode 100644 index 0000000000..2752fc13be Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/e78589cd285cd5f51be25c22e99ee6d5b3dd0fea differ diff --git a/external/boringssl/fuzz/client_corpus/e793e02598daa45d72386d500fadc7b8847966ac b/external/boringssl/fuzz/client_corpus/e793e02598daa45d72386d500fadc7b8847966ac new file mode 100644 index 0000000000..4bef09b57a Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/e793e02598daa45d72386d500fadc7b8847966ac differ diff --git a/external/boringssl/fuzz/client_corpus/e7b94d5f17cb2bda3a289528baa04e66b5ef5478 b/external/boringssl/fuzz/client_corpus/e7b94d5f17cb2bda3a289528baa04e66b5ef5478 new file mode 100644 index 0000000000..f782f873de Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/e7b94d5f17cb2bda3a289528baa04e66b5ef5478 differ diff --git a/external/boringssl/fuzz/client_corpus/e88137978a989ffac6c11e5565b1678e3a2f2a07 b/external/boringssl/fuzz/client_corpus/e88137978a989ffac6c11e5565b1678e3a2f2a07 new file mode 100644 index 0000000000..e5a6583058 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/e88137978a989ffac6c11e5565b1678e3a2f2a07 differ diff --git a/external/boringssl/fuzz/client_corpus/e8baf78fba26327aeea9353f4160469133c9e26b b/external/boringssl/fuzz/client_corpus/e8baf78fba26327aeea9353f4160469133c9e26b new file mode 100644 index 0000000000..23f88637b0 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/e8baf78fba26327aeea9353f4160469133c9e26b differ diff --git a/external/boringssl/fuzz/client_corpus/ea76c818a4ae9c92d431de82f50c194727e99d9c b/external/boringssl/fuzz/client_corpus/ea76c818a4ae9c92d431de82f50c194727e99d9c new file mode 100644 index 0000000000..68d3bec8d0 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/ea76c818a4ae9c92d431de82f50c194727e99d9c differ diff --git a/external/boringssl/fuzz/client_corpus/eac3471325184b407218efb4fbf9ed18502b90ad b/external/boringssl/fuzz/client_corpus/eac3471325184b407218efb4fbf9ed18502b90ad new file mode 100644 index 0000000000..3d6c6ebec8 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/eac3471325184b407218efb4fbf9ed18502b90ad differ diff --git a/external/boringssl/fuzz/client_corpus/eb0614a6bcbfbf345c2760bc22ca0061c5d6e670 b/external/boringssl/fuzz/client_corpus/eb0614a6bcbfbf345c2760bc22ca0061c5d6e670 new file mode 100644 index 0000000000..8f22276f6c Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/eb0614a6bcbfbf345c2760bc22ca0061c5d6e670 differ diff --git a/external/boringssl/fuzz/client_corpus/ebd0214511a49a39219400618c3d355021157884 b/external/boringssl/fuzz/client_corpus/ebd0214511a49a39219400618c3d355021157884 new file mode 100644 index 0000000000..93e7edff73 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/ebd0214511a49a39219400618c3d355021157884 differ diff --git a/external/boringssl/fuzz/client_corpus/ec6ed05526c37da3cb8f5f13c4af297999ac86b1 b/external/boringssl/fuzz/client_corpus/ec6ed05526c37da3cb8f5f13c4af297999ac86b1 new file mode 100644 index 0000000000..ff1a0e0a90 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/ec6ed05526c37da3cb8f5f13c4af297999ac86b1 differ diff --git a/external/boringssl/fuzz/client_corpus/ed12741b6e328f435f5859366b7307de25191d84 b/external/boringssl/fuzz/client_corpus/ed12741b6e328f435f5859366b7307de25191d84 new file mode 100644 index 0000000000..6bd2c49c07 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/ed12741b6e328f435f5859366b7307de25191d84 differ diff --git a/external/boringssl/fuzz/client_corpus/ed762b2b7148ee7ed1759bc6dc3d898238f3c4a2 b/external/boringssl/fuzz/client_corpus/ed762b2b7148ee7ed1759bc6dc3d898238f3c4a2 new file mode 100644 index 0000000000..50fd4c48e1 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/ed762b2b7148ee7ed1759bc6dc3d898238f3c4a2 differ diff --git a/external/boringssl/fuzz/client_corpus/eda54f7e9fa02af74383bb89950adf6dc3d55401 b/external/boringssl/fuzz/client_corpus/eda54f7e9fa02af74383bb89950adf6dc3d55401 new file mode 100644 index 0000000000..b28f61eca7 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/eda54f7e9fa02af74383bb89950adf6dc3d55401 differ diff --git a/external/boringssl/fuzz/client_corpus/edb8eb2806f70ced44e984d5b6ba736e2bfc87a6 b/external/boringssl/fuzz/client_corpus/edb8eb2806f70ced44e984d5b6ba736e2bfc87a6 new file mode 100644 index 0000000000..753949c5bf Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/edb8eb2806f70ced44e984d5b6ba736e2bfc87a6 differ diff --git a/external/boringssl/fuzz/client_corpus/ee4553a19b0f86ef2b74c1d2821b9be12bf19190 b/external/boringssl/fuzz/client_corpus/ee4553a19b0f86ef2b74c1d2821b9be12bf19190 new file mode 100644 index 0000000000..5b3183cc54 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/ee4553a19b0f86ef2b74c1d2821b9be12bf19190 differ diff --git a/external/boringssl/fuzz/client_corpus/ee9397fa6666c21dcfde633a790ae8c928e34f59 b/external/boringssl/fuzz/client_corpus/ee9397fa6666c21dcfde633a790ae8c928e34f59 new file mode 100644 index 0000000000..d16d3f515f Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/ee9397fa6666c21dcfde633a790ae8c928e34f59 differ diff --git a/external/boringssl/fuzz/client_corpus/eef3168490e70c8b410a8595d440d05ebb3265ca b/external/boringssl/fuzz/client_corpus/eef3168490e70c8b410a8595d440d05ebb3265ca new file mode 100644 index 0000000000..ef3ee60608 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/eef3168490e70c8b410a8595d440d05ebb3265ca differ diff --git a/external/boringssl/fuzz/client_corpus/ef08605ec2c45ae9d761fc90ea46e73328c81b2f b/external/boringssl/fuzz/client_corpus/ef08605ec2c45ae9d761fc90ea46e73328c81b2f new file mode 100644 index 0000000000..38eb62b442 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/ef08605ec2c45ae9d761fc90ea46e73328c81b2f differ diff --git a/external/boringssl/fuzz/client_corpus/ef10ddcdd49df604183649b612ffe27ea1473786 b/external/boringssl/fuzz/client_corpus/ef10ddcdd49df604183649b612ffe27ea1473786 new file mode 100644 index 0000000000..f94739301f Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/ef10ddcdd49df604183649b612ffe27ea1473786 differ diff --git a/external/boringssl/fuzz/client_corpus/f030612c62ffda07dfd3f71da34a355f810351c1 b/external/boringssl/fuzz/client_corpus/f030612c62ffda07dfd3f71da34a355f810351c1 new file mode 100644 index 0000000000..4fbd9f2092 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/f030612c62ffda07dfd3f71da34a355f810351c1 differ diff --git a/external/boringssl/fuzz/client_corpus/f044a49ce9380a26ab8ab4b92999c9d045fde573 b/external/boringssl/fuzz/client_corpus/f044a49ce9380a26ab8ab4b92999c9d045fde573 new file mode 100644 index 0000000000..ba8fd7e94e Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/f044a49ce9380a26ab8ab4b92999c9d045fde573 differ diff --git a/external/boringssl/fuzz/client_corpus/f16469af68d82405182616d57cb88e79a8f84fa5 b/external/boringssl/fuzz/client_corpus/f16469af68d82405182616d57cb88e79a8f84fa5 new file mode 100644 index 0000000000..9c20c2a1c8 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/f16469af68d82405182616d57cb88e79a8f84fa5 differ diff --git a/external/boringssl/fuzz/client_corpus/f20d61a351628b54d7acc53df3fa9a8b89d23a35 b/external/boringssl/fuzz/client_corpus/f20d61a351628b54d7acc53df3fa9a8b89d23a35 new file mode 100644 index 0000000000..5ff2dfd10f Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/f20d61a351628b54d7acc53df3fa9a8b89d23a35 differ diff --git a/external/boringssl/fuzz/client_corpus/f279591cee3d393edab74b64f5bff2783f7896e1 b/external/boringssl/fuzz/client_corpus/f279591cee3d393edab74b64f5bff2783f7896e1 new file mode 100644 index 0000000000..5babb58174 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/f279591cee3d393edab74b64f5bff2783f7896e1 differ diff --git a/external/boringssl/fuzz/client_corpus/f2be10d2e0ede8e502a5ad6d7327c0c57b7510e3 b/external/boringssl/fuzz/client_corpus/f2be10d2e0ede8e502a5ad6d7327c0c57b7510e3 new file mode 100644 index 0000000000..3234a33eda Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/f2be10d2e0ede8e502a5ad6d7327c0c57b7510e3 differ diff --git a/external/boringssl/fuzz/client_corpus/f2fcc44bdba89769aef1a58d9067e5e43918e9c0 b/external/boringssl/fuzz/client_corpus/f2fcc44bdba89769aef1a58d9067e5e43918e9c0 new file mode 100644 index 0000000000..be999faf20 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/f2fcc44bdba89769aef1a58d9067e5e43918e9c0 differ diff --git a/external/boringssl/fuzz/client_corpus/f32305c1d36de1b0fb6d285af73faf95c35dbd16 b/external/boringssl/fuzz/client_corpus/f32305c1d36de1b0fb6d285af73faf95c35dbd16 new file mode 100644 index 0000000000..a54e8b6db2 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/f32305c1d36de1b0fb6d285af73faf95c35dbd16 differ diff --git a/external/boringssl/fuzz/client_corpus/f35d6f2a1afc32377a077202b533490fa53ef4e2 b/external/boringssl/fuzz/client_corpus/f35d6f2a1afc32377a077202b533490fa53ef4e2 new file mode 100644 index 0000000000..834d321de7 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/f35d6f2a1afc32377a077202b533490fa53ef4e2 differ diff --git a/external/boringssl/fuzz/client_corpus/f45c5268333bc7bb0b7cca415d591d825e42ceb0 b/external/boringssl/fuzz/client_corpus/f45c5268333bc7bb0b7cca415d591d825e42ceb0 new file mode 100644 index 0000000000..819e6d8ff0 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/f45c5268333bc7bb0b7cca415d591d825e42ceb0 differ diff --git a/external/boringssl/fuzz/client_corpus/f46c909f402c6c9388a03588a3259caa870ab286 b/external/boringssl/fuzz/client_corpus/f46c909f402c6c9388a03588a3259caa870ab286 new file mode 100644 index 0000000000..ef2d230263 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/f46c909f402c6c9388a03588a3259caa870ab286 differ diff --git a/external/boringssl/fuzz/client_corpus/f490ddb2112392be3524baf6a9232090865665e2 b/external/boringssl/fuzz/client_corpus/f490ddb2112392be3524baf6a9232090865665e2 new file mode 100644 index 0000000000..1a8e4e6469 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/f490ddb2112392be3524baf6a9232090865665e2 differ diff --git a/external/boringssl/fuzz/client_corpus/f4bad3d51cdf7d01881e91f8a490cea8d1e54ea9 b/external/boringssl/fuzz/client_corpus/f4bad3d51cdf7d01881e91f8a490cea8d1e54ea9 new file mode 100644 index 0000000000..b1815b7c7d Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/f4bad3d51cdf7d01881e91f8a490cea8d1e54ea9 differ diff --git a/external/boringssl/fuzz/client_corpus/f4f2510033775e469a30abcfbc0a32fe6d515f8e b/external/boringssl/fuzz/client_corpus/f4f2510033775e469a30abcfbc0a32fe6d515f8e new file mode 100644 index 0000000000..705272b5b4 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/f4f2510033775e469a30abcfbc0a32fe6d515f8e differ diff --git a/external/boringssl/fuzz/client_corpus/f4fd47fe28b86db86a6924d755b21e4de999097a b/external/boringssl/fuzz/client_corpus/f4fd47fe28b86db86a6924d755b21e4de999097a new file mode 100644 index 0000000000..d9cd5a7eca Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/f4fd47fe28b86db86a6924d755b21e4de999097a differ diff --git a/external/boringssl/fuzz/client_corpus/f56b7a7c163e45f1bcb7f770f1dedae14f6118d8 b/external/boringssl/fuzz/client_corpus/f56b7a7c163e45f1bcb7f770f1dedae14f6118d8 new file mode 100644 index 0000000000..db25df9502 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/f56b7a7c163e45f1bcb7f770f1dedae14f6118d8 differ diff --git a/external/boringssl/fuzz/client_corpus/f5dfbb265362ba53aba22dba5f1ea72fd6e5944a b/external/boringssl/fuzz/client_corpus/f5dfbb265362ba53aba22dba5f1ea72fd6e5944a new file mode 100644 index 0000000000..964a4cd93d Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/f5dfbb265362ba53aba22dba5f1ea72fd6e5944a differ diff --git a/external/boringssl/fuzz/client_corpus/f68b9f23a79a62e1d6175d0c88e9c1f68d27cbae b/external/boringssl/fuzz/client_corpus/f68b9f23a79a62e1d6175d0c88e9c1f68d27cbae new file mode 100644 index 0000000000..f7a4640372 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/f68b9f23a79a62e1d6175d0c88e9c1f68d27cbae differ diff --git a/external/boringssl/fuzz/client_corpus/f6913522dd421f05632968344bd38c06d1954d4b b/external/boringssl/fuzz/client_corpus/f6913522dd421f05632968344bd38c06d1954d4b new file mode 100644 index 0000000000..e560f9518a Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/f6913522dd421f05632968344bd38c06d1954d4b differ diff --git a/external/boringssl/fuzz/client_corpus/f6c8c28942664fd860f1105fc6a734f94a6f84fe b/external/boringssl/fuzz/client_corpus/f6c8c28942664fd860f1105fc6a734f94a6f84fe new file mode 100644 index 0000000000..cbac193f3e Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/f6c8c28942664fd860f1105fc6a734f94a6f84fe differ diff --git a/external/boringssl/fuzz/client_corpus/f7048f702c3ca6c9586dbb81db5bf4858dcda2f6 b/external/boringssl/fuzz/client_corpus/f7048f702c3ca6c9586dbb81db5bf4858dcda2f6 new file mode 100644 index 0000000000..e8c8a77e69 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/f7048f702c3ca6c9586dbb81db5bf4858dcda2f6 differ diff --git a/external/boringssl/fuzz/client_corpus/f734fc3f014d55431bcdd133b58da2b1a96380d3 b/external/boringssl/fuzz/client_corpus/f734fc3f014d55431bcdd133b58da2b1a96380d3 new file mode 100644 index 0000000000..e4a2d3d4ca Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/f734fc3f014d55431bcdd133b58da2b1a96380d3 differ diff --git a/external/boringssl/fuzz/client_corpus/f7993bc9d744a6cd696b1a3c3ddcfcf783670dd9 b/external/boringssl/fuzz/client_corpus/f7993bc9d744a6cd696b1a3c3ddcfcf783670dd9 new file mode 100644 index 0000000000..e1a07e5de0 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/f7993bc9d744a6cd696b1a3c3ddcfcf783670dd9 differ diff --git a/external/boringssl/fuzz/client_corpus/f81cb544d394ef24caab41b1d9fc7108a95ceb1a b/external/boringssl/fuzz/client_corpus/f81cb544d394ef24caab41b1d9fc7108a95ceb1a new file mode 100644 index 0000000000..098fb59ed1 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/f81cb544d394ef24caab41b1d9fc7108a95ceb1a differ diff --git a/external/boringssl/fuzz/client_corpus/f855d4851bf113baf924a3694e3256fa084b060a b/external/boringssl/fuzz/client_corpus/f855d4851bf113baf924a3694e3256fa084b060a new file mode 100644 index 0000000000..9232d4906b Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/f855d4851bf113baf924a3694e3256fa084b060a differ diff --git a/external/boringssl/fuzz/client_corpus/f99f314fc629fdbb8ef0abbfa2b1315f081c66aa b/external/boringssl/fuzz/client_corpus/f99f314fc629fdbb8ef0abbfa2b1315f081c66aa new file mode 100644 index 0000000000..bc947368f8 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/f99f314fc629fdbb8ef0abbfa2b1315f081c66aa differ diff --git a/external/boringssl/fuzz/client_corpus/fa3a1b5f04942ab0eccd31075514dc93e542e090 b/external/boringssl/fuzz/client_corpus/fa3a1b5f04942ab0eccd31075514dc93e542e090 new file mode 100644 index 0000000000..1f6077cf1a Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/fa3a1b5f04942ab0eccd31075514dc93e542e090 differ diff --git a/external/boringssl/fuzz/client_corpus/fab4991ad6fa8f169113266acab7a163ad17fe21 b/external/boringssl/fuzz/client_corpus/fab4991ad6fa8f169113266acab7a163ad17fe21 new file mode 100644 index 0000000000..384becd2df Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/fab4991ad6fa8f169113266acab7a163ad17fe21 differ diff --git a/external/boringssl/fuzz/client_corpus/fab7c6b18d19dd33b24adc9cf45d53e385ae502a b/external/boringssl/fuzz/client_corpus/fab7c6b18d19dd33b24adc9cf45d53e385ae502a new file mode 100644 index 0000000000..c7abe5e85a Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/fab7c6b18d19dd33b24adc9cf45d53e385ae502a differ diff --git a/external/boringssl/fuzz/client_corpus/fb0317a7ce975c9dfa03675f67ca79aa488e3c31 b/external/boringssl/fuzz/client_corpus/fb0317a7ce975c9dfa03675f67ca79aa488e3c31 new file mode 100644 index 0000000000..211e50c99e Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/fb0317a7ce975c9dfa03675f67ca79aa488e3c31 differ diff --git a/external/boringssl/fuzz/client_corpus/fb9480b786a21506a1ec7934c939acf52c7bbe08 b/external/boringssl/fuzz/client_corpus/fb9480b786a21506a1ec7934c939acf52c7bbe08 new file mode 100644 index 0000000000..853de8a88f Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/fb9480b786a21506a1ec7934c939acf52c7bbe08 differ diff --git a/external/boringssl/fuzz/client_corpus/fb99ad4d6f7a231d56480050b364e0e37e91f80b b/external/boringssl/fuzz/client_corpus/fb99ad4d6f7a231d56480050b364e0e37e91f80b new file mode 100644 index 0000000000..bd74d9bb82 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/fb99ad4d6f7a231d56480050b364e0e37e91f80b differ diff --git a/external/boringssl/fuzz/client_corpus/fd86260d8b505b81449a6c72f4c86ae869366afb b/external/boringssl/fuzz/client_corpus/fd86260d8b505b81449a6c72f4c86ae869366afb new file mode 100644 index 0000000000..668c6fa951 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/fd86260d8b505b81449a6c72f4c86ae869366afb differ diff --git a/external/boringssl/fuzz/client_corpus/fdad067c8148822fffbbf2e8ec8b0021ea597b5a b/external/boringssl/fuzz/client_corpus/fdad067c8148822fffbbf2e8ec8b0021ea597b5a new file mode 100644 index 0000000000..3a01319b00 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/fdad067c8148822fffbbf2e8ec8b0021ea597b5a differ diff --git a/external/boringssl/fuzz/client_corpus/fe9abe3ee8ab25893f43f213496ba1c01f9d8579 b/external/boringssl/fuzz/client_corpus/fe9abe3ee8ab25893f43f213496ba1c01f9d8579 new file mode 100644 index 0000000000..73dee12c01 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/fe9abe3ee8ab25893f43f213496ba1c01f9d8579 differ diff --git a/external/boringssl/fuzz/client_corpus/feb7e9ac7b76f28911465a514c2c8ec273e2ba60 b/external/boringssl/fuzz/client_corpus/feb7e9ac7b76f28911465a514c2c8ec273e2ba60 new file mode 100644 index 0000000000..d23f09e43e Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/feb7e9ac7b76f28911465a514c2c8ec273e2ba60 differ diff --git a/external/boringssl/fuzz/client_corpus/ff7ba21b79ba75d821d722933b5d03a1437c38f3 b/external/boringssl/fuzz/client_corpus/ff7ba21b79ba75d821d722933b5d03a1437c38f3 new file mode 100644 index 0000000000..5d6a206b73 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/ff7ba21b79ba75d821d722933b5d03a1437c38f3 differ diff --git a/external/boringssl/fuzz/client_corpus/ff7f5fcbaf508db2e56ff22d5f38446f03837749 b/external/boringssl/fuzz/client_corpus/ff7f5fcbaf508db2e56ff22d5f38446f03837749 new file mode 100644 index 0000000000..7b6062b407 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/ff7f5fcbaf508db2e56ff22d5f38446f03837749 differ diff --git a/external/boringssl/fuzz/client_corpus/ffc9310b8efa4d9644324dc9c79b0024aa28c561 b/external/boringssl/fuzz/client_corpus/ffc9310b8efa4d9644324dc9c79b0024aa28c561 new file mode 100644 index 0000000000..68136af0c8 Binary files /dev/null and b/external/boringssl/fuzz/client_corpus/ffc9310b8efa4d9644324dc9c79b0024aa28c561 differ diff --git a/external/boringssl/fuzz/minimise_corpuses.sh b/external/boringssl/fuzz/minimise_corpuses.sh new file mode 100644 index 0000000000..7c45ef66ad --- /dev/null +++ b/external/boringssl/fuzz/minimise_corpuses.sh @@ -0,0 +1,44 @@ +# Copyright (c) 2016, Google Inc. +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +set -e + +buildDir=../build +if [ $# -gt 0 ]; then + buildDir=$1 +fi + +for testSource in $(ls -1 *.cc); do + test=$(echo $testSource | sed -e 's/\.cc$//') + if [ ! -x $buildDir/fuzz/$test ] ; then + echo "Failed to find binary for $test" + exit 1 + fi + if [ ! -d ${test}_corpus ]; then + echo "Failed to find corpus directory for $test" + exit 1 + fi + if [ -d ${test}_corpus_old ]; then + echo "Old corpus directory for $test already exists" + exit 1 + fi +done + +for testSource in $(ls -1 *.cc); do + test=$(echo $testSource | sed -e 's/\.cc$//') + mv ${test}_corpus ${test}_corpus_old + mkdir ${test}_corpus + $buildDir/fuzz/$test -max_len=50000 -merge=1 ${test}_corpus ${test}_corpus_old + rm -Rf ${test}_corpus_old +done diff --git a/external/boringssl/fuzz/pkcs8.cc b/external/boringssl/fuzz/pkcs8.cc new file mode 100644 index 0000000000..55d38930ef --- /dev/null +++ b/external/boringssl/fuzz/pkcs8.cc @@ -0,0 +1,38 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include +#include + +extern "C" int LLVMFuzzerTestOneInput(uint8_t *buf, size_t len) { + CBS cbs; + CBS_init(&cbs, buf, len); + EVP_PKEY *pkey = EVP_parse_private_key(&cbs); + if (pkey == NULL) { + return 0; + } + + uint8_t *der; + size_t der_len; + CBB cbb; + if (CBB_init(&cbb, 0) && + EVP_marshal_private_key(&cbb, pkey) && + CBB_finish(&cbb, &der, &der_len)) { + OPENSSL_free(der); + } + CBB_cleanup(&cbb); + EVP_PKEY_free(pkey); + return 0; +} diff --git a/external/boringssl/fuzz/pkcs8_corpus/129ebe4bf8b167a37741c9c470fd7c4a0359ad63 b/external/boringssl/fuzz/pkcs8_corpus/129ebe4bf8b167a37741c9c470fd7c4a0359ad63 new file mode 100644 index 0000000000..3221600e3f Binary files /dev/null and b/external/boringssl/fuzz/pkcs8_corpus/129ebe4bf8b167a37741c9c470fd7c4a0359ad63 differ diff --git a/external/boringssl/fuzz/pkcs8_corpus/1bf03b5d9f129cd80513b820a55c9568eb1d350b b/external/boringssl/fuzz/pkcs8_corpus/1bf03b5d9f129cd80513b820a55c9568eb1d350b new file mode 100644 index 0000000000..05800eefcc Binary files /dev/null and b/external/boringssl/fuzz/pkcs8_corpus/1bf03b5d9f129cd80513b820a55c9568eb1d350b differ diff --git a/external/boringssl/fuzz/pkcs8_corpus/225df81ad5fc9783575b57e20207645e55a8fa3f b/external/boringssl/fuzz/pkcs8_corpus/225df81ad5fc9783575b57e20207645e55a8fa3f new file mode 100644 index 0000000000..df3b06bfad Binary files /dev/null and b/external/boringssl/fuzz/pkcs8_corpus/225df81ad5fc9783575b57e20207645e55a8fa3f differ diff --git a/external/boringssl/fuzz/pkcs8_corpus/3033b336d833baef80981f40394c281c20677f53 b/external/boringssl/fuzz/pkcs8_corpus/3033b336d833baef80981f40394c281c20677f53 new file mode 100644 index 0000000000..a13699c4f9 Binary files /dev/null and b/external/boringssl/fuzz/pkcs8_corpus/3033b336d833baef80981f40394c281c20677f53 differ diff --git a/external/boringssl/fuzz/pkcs8_corpus/31aa87887801ac3f6eaab0bade714e56fcb5fab7 b/external/boringssl/fuzz/pkcs8_corpus/31aa87887801ac3f6eaab0bade714e56fcb5fab7 new file mode 100644 index 0000000000..96f304e73f Binary files /dev/null and b/external/boringssl/fuzz/pkcs8_corpus/31aa87887801ac3f6eaab0bade714e56fcb5fab7 differ diff --git a/external/boringssl/fuzz/pkcs8_corpus/3f7e0b4378403f44de34874789bce582790a1348 b/external/boringssl/fuzz/pkcs8_corpus/3f7e0b4378403f44de34874789bce582790a1348 new file mode 100644 index 0000000000..ab5dc9e0be Binary files /dev/null and b/external/boringssl/fuzz/pkcs8_corpus/3f7e0b4378403f44de34874789bce582790a1348 differ diff --git a/external/boringssl/fuzz/pkcs8_corpus/40d5a9f71cacb2389b58a8a24cfa52d6b51bf046 b/external/boringssl/fuzz/pkcs8_corpus/40d5a9f71cacb2389b58a8a24cfa52d6b51bf046 new file mode 100644 index 0000000000..05020c93b1 Binary files /dev/null and b/external/boringssl/fuzz/pkcs8_corpus/40d5a9f71cacb2389b58a8a24cfa52d6b51bf046 differ diff --git a/external/boringssl/fuzz/pkcs8_corpus/57e8e625f2f2313f2ec174a3209972e9bc5125ab b/external/boringssl/fuzz/pkcs8_corpus/57e8e625f2f2313f2ec174a3209972e9bc5125ab new file mode 100644 index 0000000000..4d4de1c81f Binary files /dev/null and b/external/boringssl/fuzz/pkcs8_corpus/57e8e625f2f2313f2ec174a3209972e9bc5125ab differ diff --git a/external/boringssl/fuzz/pkcs8_corpus/89db3807a0d30e36007b74c8ee4aac912fe3fd75 b/external/boringssl/fuzz/pkcs8_corpus/89db3807a0d30e36007b74c8ee4aac912fe3fd75 new file mode 100644 index 0000000000..7e8322c0bc Binary files /dev/null and b/external/boringssl/fuzz/pkcs8_corpus/89db3807a0d30e36007b74c8ee4aac912fe3fd75 differ diff --git a/external/boringssl/fuzz/pkcs8_corpus/d38e79992de4ffaf585a6450ba2e6f21188fdd08 b/external/boringssl/fuzz/pkcs8_corpus/d38e79992de4ffaf585a6450ba2e6f21188fdd08 new file mode 100644 index 0000000000..fe360394f9 Binary files /dev/null and b/external/boringssl/fuzz/pkcs8_corpus/d38e79992de4ffaf585a6450ba2e6f21188fdd08 differ diff --git a/external/boringssl/fuzz/pkcs8_corpus/d9206dbdd26c06ee8de4e587553e72b3bb22d36b b/external/boringssl/fuzz/pkcs8_corpus/d9206dbdd26c06ee8de4e587553e72b3bb22d36b new file mode 100644 index 0000000000..f45bac55d4 Binary files /dev/null and b/external/boringssl/fuzz/pkcs8_corpus/d9206dbdd26c06ee8de4e587553e72b3bb22d36b differ diff --git a/external/boringssl/fuzz/pkcs8_corpus/e0a0b34deb64510a36919a13258bd2c8725e41fe b/external/boringssl/fuzz/pkcs8_corpus/e0a0b34deb64510a36919a13258bd2c8725e41fe new file mode 100644 index 0000000000..4047d7e4fb Binary files /dev/null and b/external/boringssl/fuzz/pkcs8_corpus/e0a0b34deb64510a36919a13258bd2c8725e41fe differ diff --git a/external/boringssl/fuzz/pkcs8_corpus/e5cfb9f3e23eda47731b1cf3414df1bd408179b7 b/external/boringssl/fuzz/pkcs8_corpus/e5cfb9f3e23eda47731b1cf3414df1bd408179b7 new file mode 100644 index 0000000000..477a3da17a Binary files /dev/null and b/external/boringssl/fuzz/pkcs8_corpus/e5cfb9f3e23eda47731b1cf3414df1bd408179b7 differ diff --git a/external/boringssl/fuzz/pkcs8_corpus/efb2c016e9375355e04a5d99e2a17415c9d4f648 b/external/boringssl/fuzz/pkcs8_corpus/efb2c016e9375355e04a5d99e2a17415c9d4f648 new file mode 100644 index 0000000000..d9a28d422c Binary files /dev/null and b/external/boringssl/fuzz/pkcs8_corpus/efb2c016e9375355e04a5d99e2a17415c9d4f648 differ diff --git a/external/boringssl/fuzz/pkcs8_corpus/fc0fad9f9fb142dee99a03a50a64d10767f9f18e b/external/boringssl/fuzz/pkcs8_corpus/fc0fad9f9fb142dee99a03a50a64d10767f9f18e new file mode 100644 index 0000000000..cac230a572 Binary files /dev/null and b/external/boringssl/fuzz/pkcs8_corpus/fc0fad9f9fb142dee99a03a50a64d10767f9f18e differ diff --git a/external/boringssl/fuzz/privkey.cc b/external/boringssl/fuzz/privkey.cc new file mode 100644 index 0000000000..a7cd1b7bc5 --- /dev/null +++ b/external/boringssl/fuzz/privkey.cc @@ -0,0 +1,21 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +extern "C" int LLVMFuzzerTestOneInput(uint8_t *buf, size_t len) { + const uint8_t *bufp = buf; + EVP_PKEY_free(d2i_AutoPrivateKey(NULL, &bufp, len)); + return 0; +} diff --git a/external/boringssl/fuzz/privkey_corpus/00c42569d947a510cf9797c6f57e072aa0ca5bb3 b/external/boringssl/fuzz/privkey_corpus/00c42569d947a510cf9797c6f57e072aa0ca5bb3 new file mode 100644 index 0000000000..2b0fd294ad Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/00c42569d947a510cf9797c6f57e072aa0ca5bb3 differ diff --git a/external/boringssl/fuzz/privkey_corpus/015681c081de9b2950dcfe212a3ce6a12cae5104 b/external/boringssl/fuzz/privkey_corpus/015681c081de9b2950dcfe212a3ce6a12cae5104 new file mode 100644 index 0000000000..f56d6bbc16 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/015681c081de9b2950dcfe212a3ce6a12cae5104 differ diff --git a/external/boringssl/fuzz/privkey_corpus/019773b072a48b8cf7e0aa11b1d9a37898dc70f9 b/external/boringssl/fuzz/privkey_corpus/019773b072a48b8cf7e0aa11b1d9a37898dc70f9 new file mode 100644 index 0000000000..38c74b9080 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/019773b072a48b8cf7e0aa11b1d9a37898dc70f9 differ diff --git a/external/boringssl/fuzz/privkey_corpus/040e09a6e89086dfd9260699f1dd27f1ac8fc608 b/external/boringssl/fuzz/privkey_corpus/040e09a6e89086dfd9260699f1dd27f1ac8fc608 new file mode 100644 index 0000000000..83e378e07c Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/040e09a6e89086dfd9260699f1dd27f1ac8fc608 differ diff --git a/external/boringssl/fuzz/privkey_corpus/05025c1927ae0e2827a85a34c295f2aa08e58b67 b/external/boringssl/fuzz/privkey_corpus/05025c1927ae0e2827a85a34c295f2aa08e58b67 new file mode 100644 index 0000000000..02928978e0 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/05025c1927ae0e2827a85a34c295f2aa08e58b67 differ diff --git a/external/boringssl/fuzz/privkey_corpus/05a573fb3bb39c31923a303fc2792e72eff61cc4 b/external/boringssl/fuzz/privkey_corpus/05a573fb3bb39c31923a303fc2792e72eff61cc4 new file mode 100644 index 0000000000..b3e6ac0482 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/05a573fb3bb39c31923a303fc2792e72eff61cc4 differ diff --git a/external/boringssl/fuzz/privkey_corpus/061a18d5264822fc83ec032231ebaf117ffb6b35 b/external/boringssl/fuzz/privkey_corpus/061a18d5264822fc83ec032231ebaf117ffb6b35 new file mode 100644 index 0000000000..d16e08b650 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/061a18d5264822fc83ec032231ebaf117ffb6b35 differ diff --git a/external/boringssl/fuzz/privkey_corpus/0769477785fe09940b3003c2d57ae2510be249d2 b/external/boringssl/fuzz/privkey_corpus/0769477785fe09940b3003c2d57ae2510be249d2 new file mode 100644 index 0000000000..aa55da67a4 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/0769477785fe09940b3003c2d57ae2510be249d2 differ diff --git a/external/boringssl/fuzz/privkey_corpus/077658aca2047636d0a66aff776af558a960e60b b/external/boringssl/fuzz/privkey_corpus/077658aca2047636d0a66aff776af558a960e60b new file mode 100644 index 0000000000..09641d1faa Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/077658aca2047636d0a66aff776af558a960e60b differ diff --git a/external/boringssl/fuzz/privkey_corpus/09a98dfe76a481a565719e05e80fd48d780144bf b/external/boringssl/fuzz/privkey_corpus/09a98dfe76a481a565719e05e80fd48d780144bf new file mode 100644 index 0000000000..65b9af9c35 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/09a98dfe76a481a565719e05e80fd48d780144bf differ diff --git a/external/boringssl/fuzz/privkey_corpus/09db9192b630c602121231a0de852de7888af92f b/external/boringssl/fuzz/privkey_corpus/09db9192b630c602121231a0de852de7888af92f new file mode 100644 index 0000000000..4bb2e46f26 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/09db9192b630c602121231a0de852de7888af92f differ diff --git a/external/boringssl/fuzz/privkey_corpus/0a6ff602ee335dd5e91e1ce4e4807f9830108e4f b/external/boringssl/fuzz/privkey_corpus/0a6ff602ee335dd5e91e1ce4e4807f9830108e4f new file mode 100644 index 0000000000..3b2e952299 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/0a6ff602ee335dd5e91e1ce4e4807f9830108e4f differ diff --git a/external/boringssl/fuzz/privkey_corpus/0b274245377b1f87f39f76dbc876d43192ec7346 b/external/boringssl/fuzz/privkey_corpus/0b274245377b1f87f39f76dbc876d43192ec7346 new file mode 100644 index 0000000000..6f95548122 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/0b274245377b1f87f39f76dbc876d43192ec7346 differ diff --git a/external/boringssl/fuzz/privkey_corpus/0b85f3e44876a3d970e21d829336e33faa9d36d5 b/external/boringssl/fuzz/privkey_corpus/0b85f3e44876a3d970e21d829336e33faa9d36d5 new file mode 100644 index 0000000000..b6efb3d5f8 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/0b85f3e44876a3d970e21d829336e33faa9d36d5 differ diff --git a/external/boringssl/fuzz/privkey_corpus/0c49b71767b49200648c3672ba14308d8a525961 b/external/boringssl/fuzz/privkey_corpus/0c49b71767b49200648c3672ba14308d8a525961 new file mode 100644 index 0000000000..bcc6e0ee6d Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/0c49b71767b49200648c3672ba14308d8a525961 differ diff --git a/external/boringssl/fuzz/privkey_corpus/0ce90fa3fde09714028bbed4b835b9889868f05b b/external/boringssl/fuzz/privkey_corpus/0ce90fa3fde09714028bbed4b835b9889868f05b new file mode 100644 index 0000000000..9f4d770dc8 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/0ce90fa3fde09714028bbed4b835b9889868f05b differ diff --git a/external/boringssl/fuzz/privkey_corpus/0da750195873f5330d846c55736fa9c952daba74 b/external/boringssl/fuzz/privkey_corpus/0da750195873f5330d846c55736fa9c952daba74 new file mode 100644 index 0000000000..3f77e05913 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/0da750195873f5330d846c55736fa9c952daba74 differ diff --git a/external/boringssl/fuzz/privkey_corpus/0e33f8a77a50c72a6a6d72a539badee3bb8cf95e b/external/boringssl/fuzz/privkey_corpus/0e33f8a77a50c72a6a6d72a539badee3bb8cf95e new file mode 100644 index 0000000000..8b9d315e3d Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/0e33f8a77a50c72a6a6d72a539badee3bb8cf95e differ diff --git a/external/boringssl/fuzz/privkey_corpus/0e371858c1ec53ce2327b9067fb0f663b3951f2f b/external/boringssl/fuzz/privkey_corpus/0e371858c1ec53ce2327b9067fb0f663b3951f2f new file mode 100644 index 0000000000..530056a6c8 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/0e371858c1ec53ce2327b9067fb0f663b3951f2f differ diff --git a/external/boringssl/fuzz/privkey_corpus/0eb5037935ba1c2791f3b7e9bc8470c3c60d2aff b/external/boringssl/fuzz/privkey_corpus/0eb5037935ba1c2791f3b7e9bc8470c3c60d2aff new file mode 100644 index 0000000000..1c8ce6f6a0 --- /dev/null +++ b/external/boringssl/fuzz/privkey_corpus/0eb5037935ba1c2791f3b7e9bc8470c3c60d2aff @@ -0,0 +1 @@ +0€ \ No newline at end of file diff --git a/external/boringssl/fuzz/privkey_corpus/0fe7d2c6759892ccb8117dee4427b01230c32ac0 b/external/boringssl/fuzz/privkey_corpus/0fe7d2c6759892ccb8117dee4427b01230c32ac0 new file mode 100644 index 0000000000..01982fbd16 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/0fe7d2c6759892ccb8117dee4427b01230c32ac0 differ diff --git a/external/boringssl/fuzz/privkey_corpus/111513715bade1f0f1a1bcd76defc32853664673 b/external/boringssl/fuzz/privkey_corpus/111513715bade1f0f1a1bcd76defc32853664673 new file mode 100644 index 0000000000..98b0eb3077 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/111513715bade1f0f1a1bcd76defc32853664673 differ diff --git a/external/boringssl/fuzz/privkey_corpus/1116b7d25a60b231dcb7f6b244cfae6ebc272bc4 b/external/boringssl/fuzz/privkey_corpus/1116b7d25a60b231dcb7f6b244cfae6ebc272bc4 new file mode 100644 index 0000000000..d06ba8b2cd Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/1116b7d25a60b231dcb7f6b244cfae6ebc272bc4 differ diff --git a/external/boringssl/fuzz/privkey_corpus/144955d4b56923a5003f4778a724aaae45e133a7 b/external/boringssl/fuzz/privkey_corpus/144955d4b56923a5003f4778a724aaae45e133a7 new file mode 100644 index 0000000000..bf9ea3aa81 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/144955d4b56923a5003f4778a724aaae45e133a7 differ diff --git a/external/boringssl/fuzz/privkey_corpus/159042d0b44248e2218fde21764132a20b29f794 b/external/boringssl/fuzz/privkey_corpus/159042d0b44248e2218fde21764132a20b29f794 new file mode 100644 index 0000000000..6bd564656d Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/159042d0b44248e2218fde21764132a20b29f794 differ diff --git a/external/boringssl/fuzz/privkey_corpus/1716744626b9a81aafcd612d6802ba6d968533b1 b/external/boringssl/fuzz/privkey_corpus/1716744626b9a81aafcd612d6802ba6d968533b1 new file mode 100644 index 0000000000..38874749b3 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/1716744626b9a81aafcd612d6802ba6d968533b1 differ diff --git a/external/boringssl/fuzz/privkey_corpus/171735592c8f147c39aa928c10b3a2fb101eadb1 b/external/boringssl/fuzz/privkey_corpus/171735592c8f147c39aa928c10b3a2fb101eadb1 new file mode 100644 index 0000000000..648100e853 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/171735592c8f147c39aa928c10b3a2fb101eadb1 differ diff --git a/external/boringssl/fuzz/privkey_corpus/1786f7578e40c0526ef27e9d14276f2e30cf1fa4 b/external/boringssl/fuzz/privkey_corpus/1786f7578e40c0526ef27e9d14276f2e30cf1fa4 new file mode 100644 index 0000000000..2e03c8808b Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/1786f7578e40c0526ef27e9d14276f2e30cf1fa4 differ diff --git a/external/boringssl/fuzz/privkey_corpus/17960a325cbc94a0d43d005a00f7243b44403574 b/external/boringssl/fuzz/privkey_corpus/17960a325cbc94a0d43d005a00f7243b44403574 new file mode 100644 index 0000000000..26c288afa0 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/17960a325cbc94a0d43d005a00f7243b44403574 differ diff --git a/external/boringssl/fuzz/privkey_corpus/19793a06cf885b10b04e38a23649bd7f1e31301b b/external/boringssl/fuzz/privkey_corpus/19793a06cf885b10b04e38a23649bd7f1e31301b new file mode 100644 index 0000000000..bd998c5681 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/19793a06cf885b10b04e38a23649bd7f1e31301b differ diff --git a/external/boringssl/fuzz/privkey_corpus/1a23c272e3bef73eb0bbd4f74122a1c99d86489d b/external/boringssl/fuzz/privkey_corpus/1a23c272e3bef73eb0bbd4f74122a1c99d86489d new file mode 100644 index 0000000000..09e29bc1f4 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/1a23c272e3bef73eb0bbd4f74122a1c99d86489d differ diff --git a/external/boringssl/fuzz/privkey_corpus/1b2547c6637c3b54fe2c243a56ebc2b778e574fd b/external/boringssl/fuzz/privkey_corpus/1b2547c6637c3b54fe2c243a56ebc2b778e574fd new file mode 100644 index 0000000000..c12613f70f Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/1b2547c6637c3b54fe2c243a56ebc2b778e574fd differ diff --git a/external/boringssl/fuzz/privkey_corpus/1e5f0ef4e8fedbd7d8712b9b65accaa4257c6e1b b/external/boringssl/fuzz/privkey_corpus/1e5f0ef4e8fedbd7d8712b9b65accaa4257c6e1b new file mode 100644 index 0000000000..127ef66b66 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/1e5f0ef4e8fedbd7d8712b9b65accaa4257c6e1b differ diff --git a/external/boringssl/fuzz/privkey_corpus/1fbe5e5f1e017d5624f50ce4fe90f4e2aef10018 b/external/boringssl/fuzz/privkey_corpus/1fbe5e5f1e017d5624f50ce4fe90f4e2aef10018 new file mode 100644 index 0000000000..9d1ee6b7ae Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/1fbe5e5f1e017d5624f50ce4fe90f4e2aef10018 differ diff --git a/external/boringssl/fuzz/privkey_corpus/21390a583c6914c6217e3e7a6f0f500565c3db01 b/external/boringssl/fuzz/privkey_corpus/21390a583c6914c6217e3e7a6f0f500565c3db01 new file mode 100644 index 0000000000..d1a75470b3 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/21390a583c6914c6217e3e7a6f0f500565c3db01 differ diff --git a/external/boringssl/fuzz/privkey_corpus/25c8eb80d13e90627aeaeb6041ec5c9c80db73ef b/external/boringssl/fuzz/privkey_corpus/25c8eb80d13e90627aeaeb6041ec5c9c80db73ef new file mode 100644 index 0000000000..dc8f4e4354 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/25c8eb80d13e90627aeaeb6041ec5c9c80db73ef differ diff --git a/external/boringssl/fuzz/privkey_corpus/2658121eaf30eacfa090bbfb248068dde890a904 b/external/boringssl/fuzz/privkey_corpus/2658121eaf30eacfa090bbfb248068dde890a904 new file mode 100644 index 0000000000..3eb536e4d7 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/2658121eaf30eacfa090bbfb248068dde890a904 differ diff --git a/external/boringssl/fuzz/privkey_corpus/290126ecf71a6a446667ef8d55e533330409423b b/external/boringssl/fuzz/privkey_corpus/290126ecf71a6a446667ef8d55e533330409423b new file mode 100644 index 0000000000..9f05553c64 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/290126ecf71a6a446667ef8d55e533330409423b differ diff --git a/external/boringssl/fuzz/privkey_corpus/2909caee653dbeefc20c7071a91eae9f4cfa35b8 b/external/boringssl/fuzz/privkey_corpus/2909caee653dbeefc20c7071a91eae9f4cfa35b8 new file mode 100644 index 0000000000..a6f9ba1e9e Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/2909caee653dbeefc20c7071a91eae9f4cfa35b8 differ diff --git a/external/boringssl/fuzz/privkey_corpus/290a2847a0a316567c9c292d1655934b092196b4 b/external/boringssl/fuzz/privkey_corpus/290a2847a0a316567c9c292d1655934b092196b4 new file mode 100644 index 0000000000..3e4f31bc9f Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/290a2847a0a316567c9c292d1655934b092196b4 differ diff --git a/external/boringssl/fuzz/privkey_corpus/29c333dee5bb24eebdd3a69e2f384115b62f5da9 b/external/boringssl/fuzz/privkey_corpus/29c333dee5bb24eebdd3a69e2f384115b62f5da9 new file mode 100644 index 0000000000..278f2da55c Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/29c333dee5bb24eebdd3a69e2f384115b62f5da9 differ diff --git a/external/boringssl/fuzz/privkey_corpus/2acf5bdf834aaad09ced02a2f9b17c6b84ee183e b/external/boringssl/fuzz/privkey_corpus/2acf5bdf834aaad09ced02a2f9b17c6b84ee183e new file mode 100644 index 0000000000..83d136537d Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/2acf5bdf834aaad09ced02a2f9b17c6b84ee183e differ diff --git a/external/boringssl/fuzz/privkey_corpus/2b3a1c22ead8fc7d963fc8b09d733529970a1ed0 b/external/boringssl/fuzz/privkey_corpus/2b3a1c22ead8fc7d963fc8b09d733529970a1ed0 new file mode 100644 index 0000000000..4eb5cb0061 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/2b3a1c22ead8fc7d963fc8b09d733529970a1ed0 differ diff --git a/external/boringssl/fuzz/privkey_corpus/2d4091ae2ed10fe2008a9345042316e0d9e12f78 b/external/boringssl/fuzz/privkey_corpus/2d4091ae2ed10fe2008a9345042316e0d9e12f78 new file mode 100644 index 0000000000..b5185c990e Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/2d4091ae2ed10fe2008a9345042316e0d9e12f78 differ diff --git a/external/boringssl/fuzz/privkey_corpus/2d91275a1b8cfa0d6d96bf496b71f39ee061f696 b/external/boringssl/fuzz/privkey_corpus/2d91275a1b8cfa0d6d96bf496b71f39ee061f696 new file mode 100644 index 0000000000..00ab22d84c Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/2d91275a1b8cfa0d6d96bf496b71f39ee061f696 differ diff --git a/external/boringssl/fuzz/privkey_corpus/2eb06460c0ce9f89df1b7b71d59ffe29007b24b9 b/external/boringssl/fuzz/privkey_corpus/2eb06460c0ce9f89df1b7b71d59ffe29007b24b9 new file mode 100644 index 0000000000..b9b5d97545 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/2eb06460c0ce9f89df1b7b71d59ffe29007b24b9 differ diff --git a/external/boringssl/fuzz/privkey_corpus/2f180fb11e42c282af2cce12419433c3edc37274 b/external/boringssl/fuzz/privkey_corpus/2f180fb11e42c282af2cce12419433c3edc37274 new file mode 100644 index 0000000000..51cc7f758f Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/2f180fb11e42c282af2cce12419433c3edc37274 differ diff --git a/external/boringssl/fuzz/privkey_corpus/2f8e198fa3cd2d59a1bbe2ac182de095368689f9 b/external/boringssl/fuzz/privkey_corpus/2f8e198fa3cd2d59a1bbe2ac182de095368689f9 new file mode 100644 index 0000000000..353c75485e Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/2f8e198fa3cd2d59a1bbe2ac182de095368689f9 differ diff --git a/external/boringssl/fuzz/privkey_corpus/30cdd0dffab35c6e1fa833a06956f29de0540164 b/external/boringssl/fuzz/privkey_corpus/30cdd0dffab35c6e1fa833a06956f29de0540164 new file mode 100644 index 0000000000..8196de3944 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/30cdd0dffab35c6e1fa833a06956f29de0540164 differ diff --git a/external/boringssl/fuzz/privkey_corpus/30d35fe2026932f96aa4254f12fba48d42ddabe4 b/external/boringssl/fuzz/privkey_corpus/30d35fe2026932f96aa4254f12fba48d42ddabe4 new file mode 100644 index 0000000000..3a82476db1 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/30d35fe2026932f96aa4254f12fba48d42ddabe4 differ diff --git a/external/boringssl/fuzz/privkey_corpus/312b84ddde85711337fe7e38f9e66c67d53af068 b/external/boringssl/fuzz/privkey_corpus/312b84ddde85711337fe7e38f9e66c67d53af068 new file mode 100644 index 0000000000..10971e67a2 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/312b84ddde85711337fe7e38f9e66c67d53af068 differ diff --git a/external/boringssl/fuzz/privkey_corpus/32d0205dcae956ac26c7faa7a5696daaf288ac83 b/external/boringssl/fuzz/privkey_corpus/32d0205dcae956ac26c7faa7a5696daaf288ac83 new file mode 100644 index 0000000000..5deb0688f9 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/32d0205dcae956ac26c7faa7a5696daaf288ac83 differ diff --git a/external/boringssl/fuzz/privkey_corpus/32e6213837aac65804f3b3c57a9a58b3dd751e29 b/external/boringssl/fuzz/privkey_corpus/32e6213837aac65804f3b3c57a9a58b3dd751e29 new file mode 100644 index 0000000000..dc4a15959f Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/32e6213837aac65804f3b3c57a9a58b3dd751e29 differ diff --git a/external/boringssl/fuzz/privkey_corpus/339e070bfd090281e546cefa960412b76bcaafb0 b/external/boringssl/fuzz/privkey_corpus/339e070bfd090281e546cefa960412b76bcaafb0 new file mode 100644 index 0000000000..360bc456e2 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/339e070bfd090281e546cefa960412b76bcaafb0 differ diff --git a/external/boringssl/fuzz/privkey_corpus/346b0e49695097dec5bc9f39616b744e825c32af b/external/boringssl/fuzz/privkey_corpus/346b0e49695097dec5bc9f39616b744e825c32af new file mode 100644 index 0000000000..e701803e87 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/346b0e49695097dec5bc9f39616b744e825c32af differ diff --git a/external/boringssl/fuzz/privkey_corpus/3485d5bced3fb725b0d5db9a9a5ededd07b84b39 b/external/boringssl/fuzz/privkey_corpus/3485d5bced3fb725b0d5db9a9a5ededd07b84b39 new file mode 100644 index 0000000000..548f7750b4 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/3485d5bced3fb725b0d5db9a9a5ededd07b84b39 differ diff --git a/external/boringssl/fuzz/privkey_corpus/3499daeee13c1a1f32021dd6666834b3f57eaf75 b/external/boringssl/fuzz/privkey_corpus/3499daeee13c1a1f32021dd6666834b3f57eaf75 new file mode 100644 index 0000000000..35cb9a6ffa Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/3499daeee13c1a1f32021dd6666834b3f57eaf75 differ diff --git a/external/boringssl/fuzz/privkey_corpus/35191613835734a77f62636d0e5ca55656df19ef b/external/boringssl/fuzz/privkey_corpus/35191613835734a77f62636d0e5ca55656df19ef new file mode 100644 index 0000000000..176b6833fd Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/35191613835734a77f62636d0e5ca55656df19ef differ diff --git a/external/boringssl/fuzz/privkey_corpus/35d56dec4d0b9eee7bc3f7116694b78bd3e14adf b/external/boringssl/fuzz/privkey_corpus/35d56dec4d0b9eee7bc3f7116694b78bd3e14adf new file mode 100644 index 0000000000..ee5af3587f Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/35d56dec4d0b9eee7bc3f7116694b78bd3e14adf differ diff --git a/external/boringssl/fuzz/privkey_corpus/35ec32a0302aff2dd46b92744dd0e0aad643a735 b/external/boringssl/fuzz/privkey_corpus/35ec32a0302aff2dd46b92744dd0e0aad643a735 new file mode 100644 index 0000000000..1d89360f75 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/35ec32a0302aff2dd46b92744dd0e0aad643a735 differ diff --git a/external/boringssl/fuzz/privkey_corpus/390356980b48356de3bb28ddbc5cf107ec4f7a85 b/external/boringssl/fuzz/privkey_corpus/390356980b48356de3bb28ddbc5cf107ec4f7a85 new file mode 100644 index 0000000000..3a386e5549 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/390356980b48356de3bb28ddbc5cf107ec4f7a85 differ diff --git a/external/boringssl/fuzz/privkey_corpus/3a37605591ee36af41d000670302ff871c78a9e4 b/external/boringssl/fuzz/privkey_corpus/3a37605591ee36af41d000670302ff871c78a9e4 new file mode 100644 index 0000000000..25c92d18d9 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/3a37605591ee36af41d000670302ff871c78a9e4 differ diff --git a/external/boringssl/fuzz/privkey_corpus/3b99bd1bf571734f599661c6e3032034c1c397a7 b/external/boringssl/fuzz/privkey_corpus/3b99bd1bf571734f599661c6e3032034c1c397a7 new file mode 100644 index 0000000000..d44126ade4 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/3b99bd1bf571734f599661c6e3032034c1c397a7 differ diff --git a/external/boringssl/fuzz/privkey_corpus/3c0fd6b8973aecbc8515b7659c611b1f43fc9512 b/external/boringssl/fuzz/privkey_corpus/3c0fd6b8973aecbc8515b7659c611b1f43fc9512 new file mode 100644 index 0000000000..ba908232fa Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/3c0fd6b8973aecbc8515b7659c611b1f43fc9512 differ diff --git a/external/boringssl/fuzz/privkey_corpus/3d70c8546bd266eb21f3ad3410ce40ce0f11c754 b/external/boringssl/fuzz/privkey_corpus/3d70c8546bd266eb21f3ad3410ce40ce0f11c754 new file mode 100644 index 0000000000..50b260a935 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/3d70c8546bd266eb21f3ad3410ce40ce0f11c754 differ diff --git a/external/boringssl/fuzz/privkey_corpus/3da8eb8c3fad53453fe6be874706f011290cc193 b/external/boringssl/fuzz/privkey_corpus/3da8eb8c3fad53453fe6be874706f011290cc193 new file mode 100644 index 0000000000..e81eaf03be Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/3da8eb8c3fad53453fe6be874706f011290cc193 differ diff --git a/external/boringssl/fuzz/privkey_corpus/3fa9a81502da9188dc226556ca3ebedf247b2a31 b/external/boringssl/fuzz/privkey_corpus/3fa9a81502da9188dc226556ca3ebedf247b2a31 new file mode 100644 index 0000000000..a4d6d0ef47 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/3fa9a81502da9188dc226556ca3ebedf247b2a31 differ diff --git a/external/boringssl/fuzz/privkey_corpus/401ae4a9be451bec291b1ea4d2a3326b9b40574b b/external/boringssl/fuzz/privkey_corpus/401ae4a9be451bec291b1ea4d2a3326b9b40574b new file mode 100644 index 0000000000..50847fa721 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/401ae4a9be451bec291b1ea4d2a3326b9b40574b differ diff --git a/external/boringssl/fuzz/privkey_corpus/4084d7b10c7f3c7e5312e49c478ba7f01545fc10 b/external/boringssl/fuzz/privkey_corpus/4084d7b10c7f3c7e5312e49c478ba7f01545fc10 new file mode 100644 index 0000000000..da2802b20c Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/4084d7b10c7f3c7e5312e49c478ba7f01545fc10 differ diff --git a/external/boringssl/fuzz/privkey_corpus/408eb93771f2db1955f2d3b886aa1288955e9595 b/external/boringssl/fuzz/privkey_corpus/408eb93771f2db1955f2d3b886aa1288955e9595 new file mode 100644 index 0000000000..3a8018fadc Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/408eb93771f2db1955f2d3b886aa1288955e9595 differ diff --git a/external/boringssl/fuzz/privkey_corpus/41180009eff3da207f5fab3a1e03764aaabff217 b/external/boringssl/fuzz/privkey_corpus/41180009eff3da207f5fab3a1e03764aaabff217 new file mode 100644 index 0000000000..dc9de300ed Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/41180009eff3da207f5fab3a1e03764aaabff217 differ diff --git a/external/boringssl/fuzz/privkey_corpus/4225b400b9e45f5b3a9bea9b4b1ded8c400a1be5 b/external/boringssl/fuzz/privkey_corpus/4225b400b9e45f5b3a9bea9b4b1ded8c400a1be5 new file mode 100644 index 0000000000..dc2e774e1a Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/4225b400b9e45f5b3a9bea9b4b1ded8c400a1be5 differ diff --git a/external/boringssl/fuzz/privkey_corpus/435a4c85a2ac1876353838fa2a6ed505b0513fb6 b/external/boringssl/fuzz/privkey_corpus/435a4c85a2ac1876353838fa2a6ed505b0513fb6 new file mode 100644 index 0000000000..189c3316e4 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/435a4c85a2ac1876353838fa2a6ed505b0513fb6 differ diff --git a/external/boringssl/fuzz/privkey_corpus/48832cec638db3098a957580a1da162535ae25a0 b/external/boringssl/fuzz/privkey_corpus/48832cec638db3098a957580a1da162535ae25a0 new file mode 100644 index 0000000000..0e7ae5f027 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/48832cec638db3098a957580a1da162535ae25a0 differ diff --git a/external/boringssl/fuzz/privkey_corpus/4af1489b0c9ee9d122721c257dbcc71076950412 b/external/boringssl/fuzz/privkey_corpus/4af1489b0c9ee9d122721c257dbcc71076950412 new file mode 100644 index 0000000000..c80a11acaf Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/4af1489b0c9ee9d122721c257dbcc71076950412 differ diff --git a/external/boringssl/fuzz/privkey_corpus/4fe79bebd0cc1d75bc6c6f3f35f9792f1dbfe1db b/external/boringssl/fuzz/privkey_corpus/4fe79bebd0cc1d75bc6c6f3f35f9792f1dbfe1db new file mode 100644 index 0000000000..98ab1e7a0e Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/4fe79bebd0cc1d75bc6c6f3f35f9792f1dbfe1db differ diff --git a/external/boringssl/fuzz/privkey_corpus/502f53c70c4a0cdc28ec7d4e5e663d71628eba04 b/external/boringssl/fuzz/privkey_corpus/502f53c70c4a0cdc28ec7d4e5e663d71628eba04 new file mode 100644 index 0000000000..893471f7a2 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/502f53c70c4a0cdc28ec7d4e5e663d71628eba04 differ diff --git a/external/boringssl/fuzz/privkey_corpus/50bc50a6a7b81c4f8056973b0c54bdae838c2e28 b/external/boringssl/fuzz/privkey_corpus/50bc50a6a7b81c4f8056973b0c54bdae838c2e28 new file mode 100644 index 0000000000..f5fc512121 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/50bc50a6a7b81c4f8056973b0c54bdae838c2e28 differ diff --git a/external/boringssl/fuzz/privkey_corpus/516282abddff3db5f7806bb9540c4ffb3da5a647 b/external/boringssl/fuzz/privkey_corpus/516282abddff3db5f7806bb9540c4ffb3da5a647 new file mode 100644 index 0000000000..b2c494a696 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/516282abddff3db5f7806bb9540c4ffb3da5a647 differ diff --git a/external/boringssl/fuzz/privkey_corpus/51911d8d5529737e78a8c07f7835add996096e4e b/external/boringssl/fuzz/privkey_corpus/51911d8d5529737e78a8c07f7835add996096e4e new file mode 100644 index 0000000000..54cb5b8efe Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/51911d8d5529737e78a8c07f7835add996096e4e differ diff --git a/external/boringssl/fuzz/privkey_corpus/528fc66881a989e0be226cb9681f25fe8f8639e8 b/external/boringssl/fuzz/privkey_corpus/528fc66881a989e0be226cb9681f25fe8f8639e8 new file mode 100644 index 0000000000..3b236f1c99 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/528fc66881a989e0be226cb9681f25fe8f8639e8 differ diff --git a/external/boringssl/fuzz/privkey_corpus/5519002b1f0f5920ced3f7db347bb2a9a803f13e b/external/boringssl/fuzz/privkey_corpus/5519002b1f0f5920ced3f7db347bb2a9a803f13e new file mode 100644 index 0000000000..8cd6fdc067 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/5519002b1f0f5920ced3f7db347bb2a9a803f13e differ diff --git a/external/boringssl/fuzz/privkey_corpus/552b2592e9e09483334a9e43fb11cf4c60c9a040 b/external/boringssl/fuzz/privkey_corpus/552b2592e9e09483334a9e43fb11cf4c60c9a040 new file mode 100644 index 0000000000..8e0d23c8d0 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/552b2592e9e09483334a9e43fb11cf4c60c9a040 differ diff --git a/external/boringssl/fuzz/privkey_corpus/57e60fab45178a0597b816ff92a5f72d6c789da0 b/external/boringssl/fuzz/privkey_corpus/57e60fab45178a0597b816ff92a5f72d6c789da0 new file mode 100644 index 0000000000..9f20287e03 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/57e60fab45178a0597b816ff92a5f72d6c789da0 differ diff --git a/external/boringssl/fuzz/privkey_corpus/586d7d93d8c2a3f43248c6b437e743de6dc0ac6c b/external/boringssl/fuzz/privkey_corpus/586d7d93d8c2a3f43248c6b437e743de6dc0ac6c new file mode 100644 index 0000000000..e00b220784 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/586d7d93d8c2a3f43248c6b437e743de6dc0ac6c differ diff --git a/external/boringssl/fuzz/privkey_corpus/59685ccee38382c2b951f3f147a930aca6157cc9 b/external/boringssl/fuzz/privkey_corpus/59685ccee38382c2b951f3f147a930aca6157cc9 new file mode 100644 index 0000000000..34f2f8adee Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/59685ccee38382c2b951f3f147a930aca6157cc9 differ diff --git a/external/boringssl/fuzz/privkey_corpus/596f5f7d381c904a2f4bd12ec6e061b8e9656287 b/external/boringssl/fuzz/privkey_corpus/596f5f7d381c904a2f4bd12ec6e061b8e9656287 new file mode 100644 index 0000000000..f633bcba12 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/596f5f7d381c904a2f4bd12ec6e061b8e9656287 differ diff --git a/external/boringssl/fuzz/privkey_corpus/59f333ce69d71f603fe0864944d9b5da92b4cf87 b/external/boringssl/fuzz/privkey_corpus/59f333ce69d71f603fe0864944d9b5da92b4cf87 new file mode 100644 index 0000000000..c5906ae743 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/59f333ce69d71f603fe0864944d9b5da92b4cf87 differ diff --git a/external/boringssl/fuzz/privkey_corpus/5aec6cb701b322ad16c4cd6b35e2ba07b09f0f36 b/external/boringssl/fuzz/privkey_corpus/5aec6cb701b322ad16c4cd6b35e2ba07b09f0f36 new file mode 100644 index 0000000000..2cfe629c9a Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/5aec6cb701b322ad16c4cd6b35e2ba07b09f0f36 differ diff --git a/external/boringssl/fuzz/privkey_corpus/5b1101cb6a5041a87b29734f0a9e5db654781ad9 b/external/boringssl/fuzz/privkey_corpus/5b1101cb6a5041a87b29734f0a9e5db654781ad9 new file mode 100644 index 0000000000..c06289de22 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/5b1101cb6a5041a87b29734f0a9e5db654781ad9 differ diff --git a/external/boringssl/fuzz/privkey_corpus/5b31b569e17276924adb39d7c501f8146eb40217 b/external/boringssl/fuzz/privkey_corpus/5b31b569e17276924adb39d7c501f8146eb40217 new file mode 100644 index 0000000000..6578bc99f5 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/5b31b569e17276924adb39d7c501f8146eb40217 differ diff --git a/external/boringssl/fuzz/privkey_corpus/5bacad39834b363e5a1c70862881bf1bd6cd692d b/external/boringssl/fuzz/privkey_corpus/5bacad39834b363e5a1c70862881bf1bd6cd692d new file mode 100644 index 0000000000..ee8319395a Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/5bacad39834b363e5a1c70862881bf1bd6cd692d differ diff --git a/external/boringssl/fuzz/privkey_corpus/5c6c100ff72c9e74d3dbf16d7fc29752cf983f0e b/external/boringssl/fuzz/privkey_corpus/5c6c100ff72c9e74d3dbf16d7fc29752cf983f0e new file mode 100644 index 0000000000..0f1c7cb9a4 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/5c6c100ff72c9e74d3dbf16d7fc29752cf983f0e differ diff --git a/external/boringssl/fuzz/privkey_corpus/5c755df2a1f4c2672ff31c9d7d58d6e003a5f42e b/external/boringssl/fuzz/privkey_corpus/5c755df2a1f4c2672ff31c9d7d58d6e003a5f42e new file mode 100644 index 0000000000..05282a1dd6 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/5c755df2a1f4c2672ff31c9d7d58d6e003a5f42e differ diff --git a/external/boringssl/fuzz/privkey_corpus/5d50b7105a65869ceb68ad2a8d6dbadc184d0841 b/external/boringssl/fuzz/privkey_corpus/5d50b7105a65869ceb68ad2a8d6dbadc184d0841 new file mode 100644 index 0000000000..e724e6d9be Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/5d50b7105a65869ceb68ad2a8d6dbadc184d0841 differ diff --git a/external/boringssl/fuzz/privkey_corpus/5e89654d60cffb7a5a715535a4aaf4828269cfaa b/external/boringssl/fuzz/privkey_corpus/5e89654d60cffb7a5a715535a4aaf4828269cfaa new file mode 100644 index 0000000000..a4d6266789 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/5e89654d60cffb7a5a715535a4aaf4828269cfaa differ diff --git a/external/boringssl/fuzz/privkey_corpus/5ecdfa9f5c5f4052646bc85523a3d66f606f050b b/external/boringssl/fuzz/privkey_corpus/5ecdfa9f5c5f4052646bc85523a3d66f606f050b new file mode 100644 index 0000000000..6c8d07c811 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/5ecdfa9f5c5f4052646bc85523a3d66f606f050b differ diff --git a/external/boringssl/fuzz/privkey_corpus/600e8914f660c5e8d5d403313e6d50c022e60bec b/external/boringssl/fuzz/privkey_corpus/600e8914f660c5e8d5d403313e6d50c022e60bec new file mode 100644 index 0000000000..f5b51e12bc Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/600e8914f660c5e8d5d403313e6d50c022e60bec differ diff --git a/external/boringssl/fuzz/privkey_corpus/6099440734ee930046e454c92ff576aafe33023c b/external/boringssl/fuzz/privkey_corpus/6099440734ee930046e454c92ff576aafe33023c new file mode 100644 index 0000000000..43653a75b6 --- /dev/null +++ b/external/boringssl/fuzz/privkey_corpus/6099440734ee930046e454c92ff576aafe33023c @@ -0,0 +1 @@ +0))00€€00)0€0)0€0„0à \ No newline at end of file diff --git a/external/boringssl/fuzz/privkey_corpus/61db53da0168c52fbe159f9490f899d40babe9b8 b/external/boringssl/fuzz/privkey_corpus/61db53da0168c52fbe159f9490f899d40babe9b8 new file mode 100644 index 0000000000..460566f741 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/61db53da0168c52fbe159f9490f899d40babe9b8 differ diff --git a/external/boringssl/fuzz/privkey_corpus/63a1c254ef76396040a8a11c9715f0d7435ca3cb b/external/boringssl/fuzz/privkey_corpus/63a1c254ef76396040a8a11c9715f0d7435ca3cb new file mode 100644 index 0000000000..8e1c6c8f9c Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/63a1c254ef76396040a8a11c9715f0d7435ca3cb differ diff --git a/external/boringssl/fuzz/privkey_corpus/63c16bcb66f7e1bf859ddb2652033d08322e1ef9 b/external/boringssl/fuzz/privkey_corpus/63c16bcb66f7e1bf859ddb2652033d08322e1ef9 new file mode 100644 index 0000000000..538b5f60b1 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/63c16bcb66f7e1bf859ddb2652033d08322e1ef9 differ diff --git a/external/boringssl/fuzz/privkey_corpus/63d06cb1068c254e3dd462b434e985ae8fb10e9b b/external/boringssl/fuzz/privkey_corpus/63d06cb1068c254e3dd462b434e985ae8fb10e9b new file mode 100644 index 0000000000..b4a2c65071 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/63d06cb1068c254e3dd462b434e985ae8fb10e9b differ diff --git a/external/boringssl/fuzz/privkey_corpus/63fcd39ff8f3d87e84282915540cbf08e2df0d7d b/external/boringssl/fuzz/privkey_corpus/63fcd39ff8f3d87e84282915540cbf08e2df0d7d new file mode 100644 index 0000000000..a968bad46c --- /dev/null +++ b/external/boringssl/fuzz/privkey_corpus/63fcd39ff8f3d87e84282915540cbf08e2df0d7d @@ -0,0 +1 @@ +°é0[ *†H†÷ 00‚é¾é000 *†H†÷ \ No newline at end of file diff --git a/external/boringssl/fuzz/privkey_corpus/6457f1ad199e3535c56189326f5785071ca45658 b/external/boringssl/fuzz/privkey_corpus/6457f1ad199e3535c56189326f5785071ca45658 new file mode 100644 index 0000000000..b83b3ebff5 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/6457f1ad199e3535c56189326f5785071ca45658 differ diff --git a/external/boringssl/fuzz/privkey_corpus/64d5fbd143dd252a45201c7ca8a9d5df6503fca3 b/external/boringssl/fuzz/privkey_corpus/64d5fbd143dd252a45201c7ca8a9d5df6503fca3 new file mode 100644 index 0000000000..a8e098642d Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/64d5fbd143dd252a45201c7ca8a9d5df6503fca3 differ diff --git a/external/boringssl/fuzz/privkey_corpus/6564b23ca877f7b46600c0628d9ecc503888cc67 b/external/boringssl/fuzz/privkey_corpus/6564b23ca877f7b46600c0628d9ecc503888cc67 new file mode 100644 index 0000000000..973b0ad784 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/6564b23ca877f7b46600c0628d9ecc503888cc67 differ diff --git a/external/boringssl/fuzz/privkey_corpus/69568bdb90b3dfaa1537da561b1fd3da443c4965 b/external/boringssl/fuzz/privkey_corpus/69568bdb90b3dfaa1537da561b1fd3da443c4965 new file mode 100644 index 0000000000..419f9c27ce Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/69568bdb90b3dfaa1537da561b1fd3da443c4965 differ diff --git a/external/boringssl/fuzz/privkey_corpus/6a291a3d2db8f217bbf4778ff04b7f09c8fb5308 b/external/boringssl/fuzz/privkey_corpus/6a291a3d2db8f217bbf4778ff04b7f09c8fb5308 new file mode 100644 index 0000000000..5904dcc53a Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/6a291a3d2db8f217bbf4778ff04b7f09c8fb5308 differ diff --git a/external/boringssl/fuzz/privkey_corpus/6a3f0dff7e9cb30114ba47d280dc228074a3884b b/external/boringssl/fuzz/privkey_corpus/6a3f0dff7e9cb30114ba47d280dc228074a3884b new file mode 100644 index 0000000000..123df83b93 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/6a3f0dff7e9cb30114ba47d280dc228074a3884b differ diff --git a/external/boringssl/fuzz/privkey_corpus/6b470afcebd759c96b6c15f6936f8d3068eb79f1 b/external/boringssl/fuzz/privkey_corpus/6b470afcebd759c96b6c15f6936f8d3068eb79f1 new file mode 100644 index 0000000000..7f7337cbd5 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/6b470afcebd759c96b6c15f6936f8d3068eb79f1 differ diff --git a/external/boringssl/fuzz/privkey_corpus/6fd9b893b202e88165bd8b4b0e55b2879667606d b/external/boringssl/fuzz/privkey_corpus/6fd9b893b202e88165bd8b4b0e55b2879667606d new file mode 100644 index 0000000000..aad3b41477 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/6fd9b893b202e88165bd8b4b0e55b2879667606d differ diff --git a/external/boringssl/fuzz/privkey_corpus/6fdabfc555764f5a61263c6c213e57f93fb12a0b b/external/boringssl/fuzz/privkey_corpus/6fdabfc555764f5a61263c6c213e57f93fb12a0b new file mode 100644 index 0000000000..cfee2217d9 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/6fdabfc555764f5a61263c6c213e57f93fb12a0b differ diff --git a/external/boringssl/fuzz/privkey_corpus/7019dcba7ca33cc061327b124fb24709299a3e9b b/external/boringssl/fuzz/privkey_corpus/7019dcba7ca33cc061327b124fb24709299a3e9b new file mode 100644 index 0000000000..afe6753e2c Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/7019dcba7ca33cc061327b124fb24709299a3e9b differ diff --git a/external/boringssl/fuzz/privkey_corpus/704cc64f5ba905eeb3f4cb8049231ee97c34e4ec b/external/boringssl/fuzz/privkey_corpus/704cc64f5ba905eeb3f4cb8049231ee97c34e4ec new file mode 100644 index 0000000000..942655028d Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/704cc64f5ba905eeb3f4cb8049231ee97c34e4ec differ diff --git a/external/boringssl/fuzz/privkey_corpus/7115008ca4af946a5e2cec6166c8cf2bfacf6f0b b/external/boringssl/fuzz/privkey_corpus/7115008ca4af946a5e2cec6166c8cf2bfacf6f0b new file mode 100644 index 0000000000..076f00cebd Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/7115008ca4af946a5e2cec6166c8cf2bfacf6f0b differ diff --git a/external/boringssl/fuzz/privkey_corpus/715d34e2a6215569029969826e0bf2b78534fc14 b/external/boringssl/fuzz/privkey_corpus/715d34e2a6215569029969826e0bf2b78534fc14 new file mode 100644 index 0000000000..653b3b7824 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/715d34e2a6215569029969826e0bf2b78534fc14 differ diff --git a/external/boringssl/fuzz/privkey_corpus/723b16d087e14eab86b59cdd487a264f91cfc4e3 b/external/boringssl/fuzz/privkey_corpus/723b16d087e14eab86b59cdd487a264f91cfc4e3 new file mode 100644 index 0000000000..aea9b499e3 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/723b16d087e14eab86b59cdd487a264f91cfc4e3 differ diff --git a/external/boringssl/fuzz/privkey_corpus/7469a2e7bd870f04ad21e12c6547f4c5e3c2ee10 b/external/boringssl/fuzz/privkey_corpus/7469a2e7bd870f04ad21e12c6547f4c5e3c2ee10 new file mode 100644 index 0000000000..7bb6836e8e Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/7469a2e7bd870f04ad21e12c6547f4c5e3c2ee10 differ diff --git a/external/boringssl/fuzz/privkey_corpus/74de715f42ee6e07b7b86bbe56d488227e0e30a7 b/external/boringssl/fuzz/privkey_corpus/74de715f42ee6e07b7b86bbe56d488227e0e30a7 new file mode 100644 index 0000000000..85d81e72c1 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/74de715f42ee6e07b7b86bbe56d488227e0e30a7 differ diff --git a/external/boringssl/fuzz/privkey_corpus/7508d58d4f00dc14a072ef68c79d5db942195bac b/external/boringssl/fuzz/privkey_corpus/7508d58d4f00dc14a072ef68c79d5db942195bac new file mode 100644 index 0000000000..c0cf5ff4bd Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/7508d58d4f00dc14a072ef68c79d5db942195bac differ diff --git a/external/boringssl/fuzz/privkey_corpus/767184473ade3f29a1a06a6498f9acf4aead72ea b/external/boringssl/fuzz/privkey_corpus/767184473ade3f29a1a06a6498f9acf4aead72ea new file mode 100644 index 0000000000..bedfdfa373 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/767184473ade3f29a1a06a6498f9acf4aead72ea differ diff --git a/external/boringssl/fuzz/privkey_corpus/775f54fa88dc085283d4363426a4c408771545ec b/external/boringssl/fuzz/privkey_corpus/775f54fa88dc085283d4363426a4c408771545ec new file mode 100644 index 0000000000..68c3c31bc0 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/775f54fa88dc085283d4363426a4c408771545ec differ diff --git a/external/boringssl/fuzz/privkey_corpus/7898b0d86f7cc71b934347a20e134169ef076d2f b/external/boringssl/fuzz/privkey_corpus/7898b0d86f7cc71b934347a20e134169ef076d2f new file mode 100644 index 0000000000..4a03969e49 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/7898b0d86f7cc71b934347a20e134169ef076d2f differ diff --git a/external/boringssl/fuzz/privkey_corpus/79959ffbd0c540e1769f94f6381bbd2c28736a86 b/external/boringssl/fuzz/privkey_corpus/79959ffbd0c540e1769f94f6381bbd2c28736a86 new file mode 100644 index 0000000000..92c7c57c17 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/79959ffbd0c540e1769f94f6381bbd2c28736a86 differ diff --git a/external/boringssl/fuzz/privkey_corpus/7997306479d844e94a2b8cd0c33bd928bfaaf26b b/external/boringssl/fuzz/privkey_corpus/7997306479d844e94a2b8cd0c33bd928bfaaf26b new file mode 100644 index 0000000000..1b2f880aea Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/7997306479d844e94a2b8cd0c33bd928bfaaf26b differ diff --git a/external/boringssl/fuzz/privkey_corpus/7ad800c3d44252093ad9ad6030f08a48fcd72f70 b/external/boringssl/fuzz/privkey_corpus/7ad800c3d44252093ad9ad6030f08a48fcd72f70 new file mode 100644 index 0000000000..011f0dc5e9 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/7ad800c3d44252093ad9ad6030f08a48fcd72f70 differ diff --git a/external/boringssl/fuzz/privkey_corpus/7b1d3464ee005c28e177b4f65f7f71a1cd50462e b/external/boringssl/fuzz/privkey_corpus/7b1d3464ee005c28e177b4f65f7f71a1cd50462e new file mode 100644 index 0000000000..e5e9ffbdec Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/7b1d3464ee005c28e177b4f65f7f71a1cd50462e differ diff --git a/external/boringssl/fuzz/privkey_corpus/7b4202b35800a1c6fbfde9de8dd7c06704353bdd b/external/boringssl/fuzz/privkey_corpus/7b4202b35800a1c6fbfde9de8dd7c06704353bdd new file mode 100644 index 0000000000..f75a9bb2ba Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/7b4202b35800a1c6fbfde9de8dd7c06704353bdd differ diff --git a/external/boringssl/fuzz/privkey_corpus/7baa95845eeabd342bfec6eacfa14a623c59e158 b/external/boringssl/fuzz/privkey_corpus/7baa95845eeabd342bfec6eacfa14a623c59e158 new file mode 100644 index 0000000000..14ce22db00 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/7baa95845eeabd342bfec6eacfa14a623c59e158 differ diff --git a/external/boringssl/fuzz/privkey_corpus/7c418f677717e6525bc27159e3af3a5858b15018 b/external/boringssl/fuzz/privkey_corpus/7c418f677717e6525bc27159e3af3a5858b15018 new file mode 100644 index 0000000000..b17041b986 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/7c418f677717e6525bc27159e3af3a5858b15018 differ diff --git a/external/boringssl/fuzz/privkey_corpus/7dfd158e7e1d8c6737ece7d1ea5d67820c671c90 b/external/boringssl/fuzz/privkey_corpus/7dfd158e7e1d8c6737ece7d1ea5d67820c671c90 new file mode 100644 index 0000000000..b83b1dc719 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/7dfd158e7e1d8c6737ece7d1ea5d67820c671c90 differ diff --git a/external/boringssl/fuzz/privkey_corpus/7f52cc7f25c0899099277f4057fdac6351907856 b/external/boringssl/fuzz/privkey_corpus/7f52cc7f25c0899099277f4057fdac6351907856 new file mode 100644 index 0000000000..246e0e8dd1 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/7f52cc7f25c0899099277f4057fdac6351907856 differ diff --git a/external/boringssl/fuzz/privkey_corpus/7ff996c54474adad856bc3db017ddc9959784270 b/external/boringssl/fuzz/privkey_corpus/7ff996c54474adad856bc3db017ddc9959784270 new file mode 100644 index 0000000000..a1ae80869f Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/7ff996c54474adad856bc3db017ddc9959784270 differ diff --git a/external/boringssl/fuzz/privkey_corpus/81107eec8b4507243f1c673f820a72ea80c18892 b/external/boringssl/fuzz/privkey_corpus/81107eec8b4507243f1c673f820a72ea80c18892 new file mode 100644 index 0000000000..30e7b5e516 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/81107eec8b4507243f1c673f820a72ea80c18892 differ diff --git a/external/boringssl/fuzz/privkey_corpus/8134651d726deed781cdf0d3283af116cea8491b b/external/boringssl/fuzz/privkey_corpus/8134651d726deed781cdf0d3283af116cea8491b new file mode 100644 index 0000000000..3d838ed52d Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/8134651d726deed781cdf0d3283af116cea8491b differ diff --git a/external/boringssl/fuzz/privkey_corpus/815c2fb64bab0f77580b953f7c2d7fd0621996fc b/external/boringssl/fuzz/privkey_corpus/815c2fb64bab0f77580b953f7c2d7fd0621996fc new file mode 100644 index 0000000000..eb5dbc7c42 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/815c2fb64bab0f77580b953f7c2d7fd0621996fc differ diff --git a/external/boringssl/fuzz/privkey_corpus/81bbb1193d24b3cf1e462f898f47a2e819e293bb b/external/boringssl/fuzz/privkey_corpus/81bbb1193d24b3cf1e462f898f47a2e819e293bb new file mode 100644 index 0000000000..5bcfd75051 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/81bbb1193d24b3cf1e462f898f47a2e819e293bb differ diff --git a/external/boringssl/fuzz/privkey_corpus/820362d206b0835f12b35ff4aa7a813799be8eef b/external/boringssl/fuzz/privkey_corpus/820362d206b0835f12b35ff4aa7a813799be8eef new file mode 100644 index 0000000000..bf06ec217d Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/820362d206b0835f12b35ff4aa7a813799be8eef differ diff --git a/external/boringssl/fuzz/privkey_corpus/825915611b3cd3ba1ae6a9c178fe27bbc7dd3688 b/external/boringssl/fuzz/privkey_corpus/825915611b3cd3ba1ae6a9c178fe27bbc7dd3688 new file mode 100644 index 0000000000..b0920263db Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/825915611b3cd3ba1ae6a9c178fe27bbc7dd3688 differ diff --git a/external/boringssl/fuzz/privkey_corpus/827761890aafb4a26f4da0eb6232a59420c1ecb0 b/external/boringssl/fuzz/privkey_corpus/827761890aafb4a26f4da0eb6232a59420c1ecb0 new file mode 100644 index 0000000000..054414023c Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/827761890aafb4a26f4da0eb6232a59420c1ecb0 differ diff --git a/external/boringssl/fuzz/privkey_corpus/82e9c1cb3f406331f68205bcf9a96691dd463009 b/external/boringssl/fuzz/privkey_corpus/82e9c1cb3f406331f68205bcf9a96691dd463009 new file mode 100644 index 0000000000..10dacc6eeb Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/82e9c1cb3f406331f68205bcf9a96691dd463009 differ diff --git a/external/boringssl/fuzz/privkey_corpus/83a952b25c76484e160a04f5f2c0263cc07cc99d b/external/boringssl/fuzz/privkey_corpus/83a952b25c76484e160a04f5f2c0263cc07cc99d new file mode 100644 index 0000000000..6a74b9c8c2 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/83a952b25c76484e160a04f5f2c0263cc07cc99d differ diff --git a/external/boringssl/fuzz/privkey_corpus/8526e62eff355f6b808a1f8682ffbbb99efc876c b/external/boringssl/fuzz/privkey_corpus/8526e62eff355f6b808a1f8682ffbbb99efc876c new file mode 100644 index 0000000000..54688dfa1e Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/8526e62eff355f6b808a1f8682ffbbb99efc876c differ diff --git a/external/boringssl/fuzz/privkey_corpus/85b4691cf62b04e12af3d914153b2f92bda218f5 b/external/boringssl/fuzz/privkey_corpus/85b4691cf62b04e12af3d914153b2f92bda218f5 new file mode 100644 index 0000000000..fb719df082 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/85b4691cf62b04e12af3d914153b2f92bda218f5 differ diff --git a/external/boringssl/fuzz/privkey_corpus/864e3b9ea0ec966bcf1d1dc827c5b5d32dfe5bd9 b/external/boringssl/fuzz/privkey_corpus/864e3b9ea0ec966bcf1d1dc827c5b5d32dfe5bd9 new file mode 100644 index 0000000000..7a9fcbe345 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/864e3b9ea0ec966bcf1d1dc827c5b5d32dfe5bd9 differ diff --git a/external/boringssl/fuzz/privkey_corpus/8718dc82bbda78b01bef7fa736f36fdd7db61a2c b/external/boringssl/fuzz/privkey_corpus/8718dc82bbda78b01bef7fa736f36fdd7db61a2c new file mode 100644 index 0000000000..abb7a0972e Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/8718dc82bbda78b01bef7fa736f36fdd7db61a2c differ diff --git a/external/boringssl/fuzz/privkey_corpus/879102898920f7b123cb3bf2d3bce4eab71c38e0 b/external/boringssl/fuzz/privkey_corpus/879102898920f7b123cb3bf2d3bce4eab71c38e0 new file mode 100644 index 0000000000..3ce04de84d Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/879102898920f7b123cb3bf2d3bce4eab71c38e0 differ diff --git a/external/boringssl/fuzz/privkey_corpus/87b0269cf7ebd7a44757d8f9a45ef60484904365 b/external/boringssl/fuzz/privkey_corpus/87b0269cf7ebd7a44757d8f9a45ef60484904365 new file mode 100644 index 0000000000..8575eb1df8 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/87b0269cf7ebd7a44757d8f9a45ef60484904365 differ diff --git a/external/boringssl/fuzz/privkey_corpus/88053e0d269f3cb40b00c68ef2ee4e51aab1b669 b/external/boringssl/fuzz/privkey_corpus/88053e0d269f3cb40b00c68ef2ee4e51aab1b669 new file mode 100644 index 0000000000..31e6008fd5 --- /dev/null +++ b/external/boringssl/fuzz/privkey_corpus/88053e0d269f3cb40b00c68ef2ee4e51aab1b669 @@ -0,0 +1 @@ +0ì0€0*m0€0Ã)è;‚¾é000•)B*Ÿ0€0 \ No newline at end of file diff --git a/external/boringssl/fuzz/privkey_corpus/8930a6e954f28a8c0e4e70c9f41df099a931a088 b/external/boringssl/fuzz/privkey_corpus/8930a6e954f28a8c0e4e70c9f41df099a931a088 new file mode 100644 index 0000000000..c74a127d03 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/8930a6e954f28a8c0e4e70c9f41df099a931a088 differ diff --git a/external/boringssl/fuzz/privkey_corpus/89333d13b767e6b4af04246afb58e77b5e2d7be3 b/external/boringssl/fuzz/privkey_corpus/89333d13b767e6b4af04246afb58e77b5e2d7be3 new file mode 100644 index 0000000000..bacf4a8984 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/89333d13b767e6b4af04246afb58e77b5e2d7be3 differ diff --git a/external/boringssl/fuzz/privkey_corpus/8af7ff3e32e33166427356e04d98401ded9a347d b/external/boringssl/fuzz/privkey_corpus/8af7ff3e32e33166427356e04d98401ded9a347d new file mode 100644 index 0000000000..1935c27b7d Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/8af7ff3e32e33166427356e04d98401ded9a347d differ diff --git a/external/boringssl/fuzz/privkey_corpus/8b6fd2ab1d0d7fefe124696065e074b2d161c14c b/external/boringssl/fuzz/privkey_corpus/8b6fd2ab1d0d7fefe124696065e074b2d161c14c new file mode 100644 index 0000000000..34502ecbfe Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/8b6fd2ab1d0d7fefe124696065e074b2d161c14c differ diff --git a/external/boringssl/fuzz/privkey_corpus/8f108bc5c869083074bfe9d08f9f9e905e56a206 b/external/boringssl/fuzz/privkey_corpus/8f108bc5c869083074bfe9d08f9f9e905e56a206 new file mode 100644 index 0000000000..13a1bd6caa Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/8f108bc5c869083074bfe9d08f9f9e905e56a206 differ diff --git a/external/boringssl/fuzz/privkey_corpus/906e954acb728d2e7ed6fb8630672667f09b1f1e b/external/boringssl/fuzz/privkey_corpus/906e954acb728d2e7ed6fb8630672667f09b1f1e new file mode 100644 index 0000000000..201d6fddb6 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/906e954acb728d2e7ed6fb8630672667f09b1f1e differ diff --git a/external/boringssl/fuzz/privkey_corpus/91583ca2b096602157ea1e68c7d6b2adff9378e4 b/external/boringssl/fuzz/privkey_corpus/91583ca2b096602157ea1e68c7d6b2adff9378e4 new file mode 100644 index 0000000000..e923075568 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/91583ca2b096602157ea1e68c7d6b2adff9378e4 differ diff --git a/external/boringssl/fuzz/privkey_corpus/91946201829018208daad41691f4aaa7e2c3eb15 b/external/boringssl/fuzz/privkey_corpus/91946201829018208daad41691f4aaa7e2c3eb15 new file mode 100644 index 0000000000..03cc373311 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/91946201829018208daad41691f4aaa7e2c3eb15 differ diff --git a/external/boringssl/fuzz/privkey_corpus/92ba02b6268e6c21133447c6518a896157d68afa b/external/boringssl/fuzz/privkey_corpus/92ba02b6268e6c21133447c6518a896157d68afa new file mode 100644 index 0000000000..40a111bcfa Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/92ba02b6268e6c21133447c6518a896157d68afa differ diff --git a/external/boringssl/fuzz/privkey_corpus/946bfe147670f490b65da4929129a05ba4fe3eb3 b/external/boringssl/fuzz/privkey_corpus/946bfe147670f490b65da4929129a05ba4fe3eb3 new file mode 100644 index 0000000000..fd29f40b6e Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/946bfe147670f490b65da4929129a05ba4fe3eb3 differ diff --git a/external/boringssl/fuzz/privkey_corpus/94a53c59e935429397267a33a6d19fb5bd90c594 b/external/boringssl/fuzz/privkey_corpus/94a53c59e935429397267a33a6d19fb5bd90c594 new file mode 100644 index 0000000000..13014bad14 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/94a53c59e935429397267a33a6d19fb5bd90c594 differ diff --git a/external/boringssl/fuzz/privkey_corpus/94af57e79c33b555ed3d577d7d7278776e2e3354 b/external/boringssl/fuzz/privkey_corpus/94af57e79c33b555ed3d577d7d7278776e2e3354 new file mode 100644 index 0000000000..8f8ec04d82 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/94af57e79c33b555ed3d577d7d7278776e2e3354 differ diff --git a/external/boringssl/fuzz/privkey_corpus/94d32ba71497e04e729fed8a7b0eb4bbdd44be23 b/external/boringssl/fuzz/privkey_corpus/94d32ba71497e04e729fed8a7b0eb4bbdd44be23 new file mode 100644 index 0000000000..b683ebd338 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/94d32ba71497e04e729fed8a7b0eb4bbdd44be23 differ diff --git a/external/boringssl/fuzz/privkey_corpus/96ca3c3159a62867cd0f67e00cdc29592777fa88 b/external/boringssl/fuzz/privkey_corpus/96ca3c3159a62867cd0f67e00cdc29592777fa88 new file mode 100644 index 0000000000..9f5a5ffe03 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/96ca3c3159a62867cd0f67e00cdc29592777fa88 differ diff --git a/external/boringssl/fuzz/privkey_corpus/97d88e10db105ca8aff02affa4df9105fcf6c0c9 b/external/boringssl/fuzz/privkey_corpus/97d88e10db105ca8aff02affa4df9105fcf6c0c9 new file mode 100644 index 0000000000..8899be37af Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/97d88e10db105ca8aff02affa4df9105fcf6c0c9 differ diff --git a/external/boringssl/fuzz/privkey_corpus/97dccd2f5301d606ef218ead83374e2dbf23931f b/external/boringssl/fuzz/privkey_corpus/97dccd2f5301d606ef218ead83374e2dbf23931f new file mode 100644 index 0000000000..b529b0b405 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/97dccd2f5301d606ef218ead83374e2dbf23931f differ diff --git a/external/boringssl/fuzz/privkey_corpus/987113dad3aecd5a8bc478cc94e11708f3e23b49 b/external/boringssl/fuzz/privkey_corpus/987113dad3aecd5a8bc478cc94e11708f3e23b49 new file mode 100644 index 0000000000..35c51bdf21 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/987113dad3aecd5a8bc478cc94e11708f3e23b49 differ diff --git a/external/boringssl/fuzz/privkey_corpus/98ac3859a7ffb3851d4269b8fbc1b408eb36da02 b/external/boringssl/fuzz/privkey_corpus/98ac3859a7ffb3851d4269b8fbc1b408eb36da02 new file mode 100644 index 0000000000..416b6777b5 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/98ac3859a7ffb3851d4269b8fbc1b408eb36da02 differ diff --git a/external/boringssl/fuzz/privkey_corpus/98d8745802ae439a6bd8b6cb20b35ba6c942f6ca b/external/boringssl/fuzz/privkey_corpus/98d8745802ae439a6bd8b6cb20b35ba6c942f6ca new file mode 100644 index 0000000000..f71a19d700 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/98d8745802ae439a6bd8b6cb20b35ba6c942f6ca differ diff --git a/external/boringssl/fuzz/privkey_corpus/996a0120ca7d868a8a8da7141ed352e18ada4631 b/external/boringssl/fuzz/privkey_corpus/996a0120ca7d868a8a8da7141ed352e18ada4631 new file mode 100644 index 0000000000..a164e0072f Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/996a0120ca7d868a8a8da7141ed352e18ada4631 differ diff --git a/external/boringssl/fuzz/privkey_corpus/99925faf1244b710b84a12cb1b602dae69f795cf b/external/boringssl/fuzz/privkey_corpus/99925faf1244b710b84a12cb1b602dae69f795cf new file mode 100644 index 0000000000..b8d7e5bc92 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/99925faf1244b710b84a12cb1b602dae69f795cf differ diff --git a/external/boringssl/fuzz/privkey_corpus/99af875391c1e7c13743893fdd8c3d354e034dac b/external/boringssl/fuzz/privkey_corpus/99af875391c1e7c13743893fdd8c3d354e034dac new file mode 100644 index 0000000000..c02e8e8020 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/99af875391c1e7c13743893fdd8c3d354e034dac differ diff --git a/external/boringssl/fuzz/privkey_corpus/9b1bb094b817690bf3f92ed11eaa10371ad3cb0c b/external/boringssl/fuzz/privkey_corpus/9b1bb094b817690bf3f92ed11eaa10371ad3cb0c new file mode 100644 index 0000000000..964d820917 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/9b1bb094b817690bf3f92ed11eaa10371ad3cb0c differ diff --git a/external/boringssl/fuzz/privkey_corpus/9d23cb41145d5d0643f52b7376b75f5628f95546 b/external/boringssl/fuzz/privkey_corpus/9d23cb41145d5d0643f52b7376b75f5628f95546 new file mode 100644 index 0000000000..187ad6e534 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/9d23cb41145d5d0643f52b7376b75f5628f95546 differ diff --git a/external/boringssl/fuzz/privkey_corpus/9d93a1a13ef025beb36b2d0c3fda83177c0dd1b4 b/external/boringssl/fuzz/privkey_corpus/9d93a1a13ef025beb36b2d0c3fda83177c0dd1b4 new file mode 100644 index 0000000000..7776a83217 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/9d93a1a13ef025beb36b2d0c3fda83177c0dd1b4 differ diff --git a/external/boringssl/fuzz/privkey_corpus/9daaa6a59373116fdafd6a88ae78a66f82d3b12c b/external/boringssl/fuzz/privkey_corpus/9daaa6a59373116fdafd6a88ae78a66f82d3b12c new file mode 100644 index 0000000000..7fc8b6e1bb Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/9daaa6a59373116fdafd6a88ae78a66f82d3b12c differ diff --git a/external/boringssl/fuzz/privkey_corpus/9e68ef050c944e5ad80ecb7b4e5023520e190425 b/external/boringssl/fuzz/privkey_corpus/9e68ef050c944e5ad80ecb7b4e5023520e190425 new file mode 100644 index 0000000000..f5697194c5 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/9e68ef050c944e5ad80ecb7b4e5023520e190425 differ diff --git a/external/boringssl/fuzz/privkey_corpus/9f1eabfff336e298505550b3f369c61431289713 b/external/boringssl/fuzz/privkey_corpus/9f1eabfff336e298505550b3f369c61431289713 new file mode 100644 index 0000000000..21ec4f6cd3 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/9f1eabfff336e298505550b3f369c61431289713 differ diff --git a/external/boringssl/fuzz/privkey_corpus/9f24c5b2bf1b8306de8f5f708476773bfdf8d141 b/external/boringssl/fuzz/privkey_corpus/9f24c5b2bf1b8306de8f5f708476773bfdf8d141 new file mode 100644 index 0000000000..a4e75b345d --- /dev/null +++ b/external/boringssl/fuzz/privkey_corpus/9f24c5b2bf1b8306de8f5f708476773bfdf8d141 @@ -0,0 +1 @@ +¤‚ \ No newline at end of file diff --git a/external/boringssl/fuzz/privkey_corpus/9f3c56915a0a55918fb711cddc3c72039d2766ed b/external/boringssl/fuzz/privkey_corpus/9f3c56915a0a55918fb711cddc3c72039d2766ed new file mode 100644 index 0000000000..e2ac5c628c Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/9f3c56915a0a55918fb711cddc3c72039d2766ed differ diff --git a/external/boringssl/fuzz/privkey_corpus/a148911d708b9ce5e436a45f9ade17782afc86b7 b/external/boringssl/fuzz/privkey_corpus/a148911d708b9ce5e436a45f9ade17782afc86b7 new file mode 100644 index 0000000000..42d2dbb0c8 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/a148911d708b9ce5e436a45f9ade17782afc86b7 differ diff --git a/external/boringssl/fuzz/privkey_corpus/a4d958b6af098740bdd7bdbc670d9d5ff33af0df b/external/boringssl/fuzz/privkey_corpus/a4d958b6af098740bdd7bdbc670d9d5ff33af0df new file mode 100644 index 0000000000..1cd09f4535 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/a4d958b6af098740bdd7bdbc670d9d5ff33af0df differ diff --git a/external/boringssl/fuzz/privkey_corpus/a5481eb2b17062606e626ae7cb9156851f314cfb b/external/boringssl/fuzz/privkey_corpus/a5481eb2b17062606e626ae7cb9156851f314cfb new file mode 100644 index 0000000000..8557eb81ad Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/a5481eb2b17062606e626ae7cb9156851f314cfb differ diff --git a/external/boringssl/fuzz/privkey_corpus/a57da87205e925a5088c9136d5013928ea966bee b/external/boringssl/fuzz/privkey_corpus/a57da87205e925a5088c9136d5013928ea966bee new file mode 100644 index 0000000000..e0c424a7a0 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/a57da87205e925a5088c9136d5013928ea966bee differ diff --git a/external/boringssl/fuzz/privkey_corpus/a5bbdddaabff03f981ac4812c9f78744fb59d555 b/external/boringssl/fuzz/privkey_corpus/a5bbdddaabff03f981ac4812c9f78744fb59d555 new file mode 100644 index 0000000000..edc9a33d03 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/a5bbdddaabff03f981ac4812c9f78744fb59d555 differ diff --git a/external/boringssl/fuzz/privkey_corpus/a786d0dd572029971ee468ceea31c153df41bd2d b/external/boringssl/fuzz/privkey_corpus/a786d0dd572029971ee468ceea31c153df41bd2d new file mode 100644 index 0000000000..29c9a4aea1 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/a786d0dd572029971ee468ceea31c153df41bd2d differ diff --git a/external/boringssl/fuzz/privkey_corpus/a7d0b5428d0fee536cad87e3243a8668061164c5 b/external/boringssl/fuzz/privkey_corpus/a7d0b5428d0fee536cad87e3243a8668061164c5 new file mode 100644 index 0000000000..d35f31ad10 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/a7d0b5428d0fee536cad87e3243a8668061164c5 differ diff --git a/external/boringssl/fuzz/privkey_corpus/a876f0286bdaf5715d37f5446196924288318078 b/external/boringssl/fuzz/privkey_corpus/a876f0286bdaf5715d37f5446196924288318078 new file mode 100644 index 0000000000..c4f9c9fde9 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/a876f0286bdaf5715d37f5446196924288318078 differ diff --git a/external/boringssl/fuzz/privkey_corpus/a89172016f91c2d90eae0ec282965f2b980cd43a b/external/boringssl/fuzz/privkey_corpus/a89172016f91c2d90eae0ec282965f2b980cd43a new file mode 100644 index 0000000000..84eb4c73a2 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/a89172016f91c2d90eae0ec282965f2b980cd43a differ diff --git a/external/boringssl/fuzz/privkey_corpus/a8bdd4f4f781cc89e87621188db36b8490046042 b/external/boringssl/fuzz/privkey_corpus/a8bdd4f4f781cc89e87621188db36b8490046042 new file mode 100644 index 0000000000..b51d35c4f0 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/a8bdd4f4f781cc89e87621188db36b8490046042 differ diff --git a/external/boringssl/fuzz/privkey_corpus/a9d62074bf9e1200cd0a3dea12c106925b58e6e6 b/external/boringssl/fuzz/privkey_corpus/a9d62074bf9e1200cd0a3dea12c106925b58e6e6 new file mode 100644 index 0000000000..3c4d88a363 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/a9d62074bf9e1200cd0a3dea12c106925b58e6e6 differ diff --git a/external/boringssl/fuzz/privkey_corpus/aa0505ea0b3d4c360a5200a50a010b4a55849fad b/external/boringssl/fuzz/privkey_corpus/aa0505ea0b3d4c360a5200a50a010b4a55849fad new file mode 100644 index 0000000000..8d6852f378 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/aa0505ea0b3d4c360a5200a50a010b4a55849fad differ diff --git a/external/boringssl/fuzz/privkey_corpus/aa3a41b9a808b2028bb83d5279ba42371c8dca4d b/external/boringssl/fuzz/privkey_corpus/aa3a41b9a808b2028bb83d5279ba42371c8dca4d new file mode 100644 index 0000000000..265ef556aa Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/aa3a41b9a808b2028bb83d5279ba42371c8dca4d differ diff --git a/external/boringssl/fuzz/privkey_corpus/aabc600f07af79ddb976e2c101f0625f991f2c82 b/external/boringssl/fuzz/privkey_corpus/aabc600f07af79ddb976e2c101f0625f991f2c82 new file mode 100644 index 0000000000..74007711f4 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/aabc600f07af79ddb976e2c101f0625f991f2c82 differ diff --git a/external/boringssl/fuzz/privkey_corpus/aafac2d9b5d50385e892a1c9792bbf9f31530544 b/external/boringssl/fuzz/privkey_corpus/aafac2d9b5d50385e892a1c9792bbf9f31530544 new file mode 100644 index 0000000000..82a5caeaa6 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/aafac2d9b5d50385e892a1c9792bbf9f31530544 differ diff --git a/external/boringssl/fuzz/privkey_corpus/ab5f3c4a4181cfaec1fbd6949a96cde343cfa908 b/external/boringssl/fuzz/privkey_corpus/ab5f3c4a4181cfaec1fbd6949a96cde343cfa908 new file mode 100644 index 0000000000..684d61c943 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/ab5f3c4a4181cfaec1fbd6949a96cde343cfa908 differ diff --git a/external/boringssl/fuzz/privkey_corpus/adc6e9d3be69a83a22a8e9579d721139fdef534e b/external/boringssl/fuzz/privkey_corpus/adc6e9d3be69a83a22a8e9579d721139fdef534e new file mode 100644 index 0000000000..b9384e91a5 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/adc6e9d3be69a83a22a8e9579d721139fdef534e differ diff --git a/external/boringssl/fuzz/privkey_corpus/ae4960ecdce376a9bbd26afbc481619ba303f4e4 b/external/boringssl/fuzz/privkey_corpus/ae4960ecdce376a9bbd26afbc481619ba303f4e4 new file mode 100644 index 0000000000..d37482fad9 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/ae4960ecdce376a9bbd26afbc481619ba303f4e4 differ diff --git a/external/boringssl/fuzz/privkey_corpus/ae97c55d39f8c51a81fe559e278110d90a8095bf b/external/boringssl/fuzz/privkey_corpus/ae97c55d39f8c51a81fe559e278110d90a8095bf new file mode 100644 index 0000000000..e3dc371ca1 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/ae97c55d39f8c51a81fe559e278110d90a8095bf differ diff --git a/external/boringssl/fuzz/privkey_corpus/aecd29853dcf0d6429665efa95349bca6672d451 b/external/boringssl/fuzz/privkey_corpus/aecd29853dcf0d6429665efa95349bca6672d451 new file mode 100644 index 0000000000..705931c470 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/aecd29853dcf0d6429665efa95349bca6672d451 differ diff --git a/external/boringssl/fuzz/privkey_corpus/b199b6e6200bcbc9b8972d8e5fd5bae8a379f57d b/external/boringssl/fuzz/privkey_corpus/b199b6e6200bcbc9b8972d8e5fd5bae8a379f57d new file mode 100644 index 0000000000..74f1528e84 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/b199b6e6200bcbc9b8972d8e5fd5bae8a379f57d differ diff --git a/external/boringssl/fuzz/privkey_corpus/b3f8287d91c8ae6d29b8db61b5d4b757a9c4c238 b/external/boringssl/fuzz/privkey_corpus/b3f8287d91c8ae6d29b8db61b5d4b757a9c4c238 new file mode 100644 index 0000000000..fac39b43a7 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/b3f8287d91c8ae6d29b8db61b5d4b757a9c4c238 differ diff --git a/external/boringssl/fuzz/privkey_corpus/b56d41d9a951ef3ed52a55a640c9741d7d171321 b/external/boringssl/fuzz/privkey_corpus/b56d41d9a951ef3ed52a55a640c9741d7d171321 new file mode 100644 index 0000000000..59c38276c2 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/b56d41d9a951ef3ed52a55a640c9741d7d171321 differ diff --git a/external/boringssl/fuzz/privkey_corpus/b626fd67fd56e710f1ab83f25cd9355de125898c b/external/boringssl/fuzz/privkey_corpus/b626fd67fd56e710f1ab83f25cd9355de125898c new file mode 100644 index 0000000000..cf9528801e Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/b626fd67fd56e710f1ab83f25cd9355de125898c differ diff --git a/external/boringssl/fuzz/privkey_corpus/b6b36ce62527c806633c581bd83928ca658c5636 b/external/boringssl/fuzz/privkey_corpus/b6b36ce62527c806633c581bd83928ca658c5636 new file mode 100644 index 0000000000..ed9bf8d2c1 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/b6b36ce62527c806633c581bd83928ca658c5636 differ diff --git a/external/boringssl/fuzz/privkey_corpus/b73ec5775410255daf79b77df66d8bc3844ac185 b/external/boringssl/fuzz/privkey_corpus/b73ec5775410255daf79b77df66d8bc3844ac185 new file mode 100644 index 0000000000..1b95c6b6dd Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/b73ec5775410255daf79b77df66d8bc3844ac185 differ diff --git a/external/boringssl/fuzz/privkey_corpus/b82de94562e200e03ce3082d5618fb95d1f61ab6 b/external/boringssl/fuzz/privkey_corpus/b82de94562e200e03ce3082d5618fb95d1f61ab6 new file mode 100644 index 0000000000..33efbfb0dc Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/b82de94562e200e03ce3082d5618fb95d1f61ab6 differ diff --git a/external/boringssl/fuzz/privkey_corpus/b83ad977325da3e287251f214e5f076700df66c4 b/external/boringssl/fuzz/privkey_corpus/b83ad977325da3e287251f214e5f076700df66c4 new file mode 100644 index 0000000000..05d0017d67 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/b83ad977325da3e287251f214e5f076700df66c4 differ diff --git a/external/boringssl/fuzz/privkey_corpus/b8e3f3d19adcbb244d85b968264adf4bc34bbba4 b/external/boringssl/fuzz/privkey_corpus/b8e3f3d19adcbb244d85b968264adf4bc34bbba4 new file mode 100644 index 0000000000..313bba8661 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/b8e3f3d19adcbb244d85b968264adf4bc34bbba4 differ diff --git a/external/boringssl/fuzz/privkey_corpus/b9260c758df1d058735482a8b9b540612b9d2ae3 b/external/boringssl/fuzz/privkey_corpus/b9260c758df1d058735482a8b9b540612b9d2ae3 new file mode 100644 index 0000000000..c136bf93f2 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/b9260c758df1d058735482a8b9b540612b9d2ae3 differ diff --git a/external/boringssl/fuzz/privkey_corpus/b9924406c46a4a954895fdb416f6ef4f9fbecfca b/external/boringssl/fuzz/privkey_corpus/b9924406c46a4a954895fdb416f6ef4f9fbecfca new file mode 100644 index 0000000000..c1d2aa69d8 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/b9924406c46a4a954895fdb416f6ef4f9fbecfca differ diff --git a/external/boringssl/fuzz/privkey_corpus/ba0e5fccc5b9b1a3c009ef5ab6b616be07aea369 b/external/boringssl/fuzz/privkey_corpus/ba0e5fccc5b9b1a3c009ef5ab6b616be07aea369 new file mode 100644 index 0000000000..6b3745f5f7 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/ba0e5fccc5b9b1a3c009ef5ab6b616be07aea369 differ diff --git a/external/boringssl/fuzz/privkey_corpus/baa2017f3f816ea489150c2753fcf2acceed711e b/external/boringssl/fuzz/privkey_corpus/baa2017f3f816ea489150c2753fcf2acceed711e new file mode 100644 index 0000000000..32576ed0fc Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/baa2017f3f816ea489150c2753fcf2acceed711e differ diff --git a/external/boringssl/fuzz/privkey_corpus/be34aad9e27b0e5fbeea5acbdefe813dff55c273 b/external/boringssl/fuzz/privkey_corpus/be34aad9e27b0e5fbeea5acbdefe813dff55c273 new file mode 100644 index 0000000000..89f12f2d21 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/be34aad9e27b0e5fbeea5acbdefe813dff55c273 differ diff --git a/external/boringssl/fuzz/privkey_corpus/be998be251e63a0d855a269dec3abd974edf064f b/external/boringssl/fuzz/privkey_corpus/be998be251e63a0d855a269dec3abd974edf064f new file mode 100644 index 0000000000..ad4d5c14da Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/be998be251e63a0d855a269dec3abd974edf064f differ diff --git a/external/boringssl/fuzz/privkey_corpus/beca0cd7b91a6b0af4fc012cf1385952287660af b/external/boringssl/fuzz/privkey_corpus/beca0cd7b91a6b0af4fc012cf1385952287660af new file mode 100644 index 0000000000..e1c74979a3 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/beca0cd7b91a6b0af4fc012cf1385952287660af differ diff --git a/external/boringssl/fuzz/privkey_corpus/bf44fcd5fb4037ca361643ead75091cd7d7591ee b/external/boringssl/fuzz/privkey_corpus/bf44fcd5fb4037ca361643ead75091cd7d7591ee new file mode 100644 index 0000000000..040c66a8fd Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/bf44fcd5fb4037ca361643ead75091cd7d7591ee differ diff --git a/external/boringssl/fuzz/privkey_corpus/c09c79dd6953ac6766586c288673bbf07717188f b/external/boringssl/fuzz/privkey_corpus/c09c79dd6953ac6766586c288673bbf07717188f new file mode 100644 index 0000000000..ee8636f736 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/c09c79dd6953ac6766586c288673bbf07717188f differ diff --git a/external/boringssl/fuzz/privkey_corpus/c0fb9c7ea154ea9bd8d69b07054aef25a7c7122b b/external/boringssl/fuzz/privkey_corpus/c0fb9c7ea154ea9bd8d69b07054aef25a7c7122b new file mode 100644 index 0000000000..371cbb6b26 --- /dev/null +++ b/external/boringssl/fuzz/privkey_corpus/c0fb9c7ea154ea9bd8d69b07054aef25a7c7122b @@ -0,0 +1 @@ +0)0€0)€00)0€0)0€0„0à \ No newline at end of file diff --git a/external/boringssl/fuzz/privkey_corpus/c1a97da39a236c416de37437ac41ab4ff86caee8 b/external/boringssl/fuzz/privkey_corpus/c1a97da39a236c416de37437ac41ab4ff86caee8 new file mode 100644 index 0000000000..b00080566d Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/c1a97da39a236c416de37437ac41ab4ff86caee8 differ diff --git a/external/boringssl/fuzz/privkey_corpus/c24ffe679d844cc26ac590f2657bd36de7876703 b/external/boringssl/fuzz/privkey_corpus/c24ffe679d844cc26ac590f2657bd36de7876703 new file mode 100644 index 0000000000..23cce40e33 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/c24ffe679d844cc26ac590f2657bd36de7876703 differ diff --git a/external/boringssl/fuzz/privkey_corpus/c3658e11896a6c7a16d3f40160d91c6e281caece b/external/boringssl/fuzz/privkey_corpus/c3658e11896a6c7a16d3f40160d91c6e281caece new file mode 100644 index 0000000000..2ccd946e9b Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/c3658e11896a6c7a16d3f40160d91c6e281caece differ diff --git a/external/boringssl/fuzz/privkey_corpus/c540b77632fe86d68bd3caa3c3ffb92473e38216 b/external/boringssl/fuzz/privkey_corpus/c540b77632fe86d68bd3caa3c3ffb92473e38216 new file mode 100644 index 0000000000..a81026f68c Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/c540b77632fe86d68bd3caa3c3ffb92473e38216 differ diff --git a/external/boringssl/fuzz/privkey_corpus/c5964a09ff096f10007be24c483697813e641050 b/external/boringssl/fuzz/privkey_corpus/c5964a09ff096f10007be24c483697813e641050 new file mode 100644 index 0000000000..1ed257aaf7 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/c5964a09ff096f10007be24c483697813e641050 differ diff --git a/external/boringssl/fuzz/privkey_corpus/c5be586cbc10f9982b132505e84eed971e375fd3 b/external/boringssl/fuzz/privkey_corpus/c5be586cbc10f9982b132505e84eed971e375fd3 new file mode 100644 index 0000000000..d21cb87e57 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/c5be586cbc10f9982b132505e84eed971e375fd3 differ diff --git a/external/boringssl/fuzz/privkey_corpus/c63c2f2c72fa6788f4e229f4021c3f9001d9ae71 b/external/boringssl/fuzz/privkey_corpus/c63c2f2c72fa6788f4e229f4021c3f9001d9ae71 new file mode 100644 index 0000000000..bfb517346b Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/c63c2f2c72fa6788f4e229f4021c3f9001d9ae71 differ diff --git a/external/boringssl/fuzz/privkey_corpus/c7639de8641dc12f675107b0ce6aee03e1f4ca46 b/external/boringssl/fuzz/privkey_corpus/c7639de8641dc12f675107b0ce6aee03e1f4ca46 new file mode 100644 index 0000000000..c76f07c229 --- /dev/null +++ b/external/boringssl/fuzz/privkey_corpus/c7639de8641dc12f675107b0ce6aee03e1f4ca46 @@ -0,0 +1 @@ +ŸŸ \ No newline at end of file diff --git a/external/boringssl/fuzz/privkey_corpus/c7add8dd1a26be2f8429baad24c10726c5e62a75 b/external/boringssl/fuzz/privkey_corpus/c7add8dd1a26be2f8429baad24c10726c5e62a75 new file mode 100644 index 0000000000..7dc22bc14f Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/c7add8dd1a26be2f8429baad24c10726c5e62a75 differ diff --git a/external/boringssl/fuzz/privkey_corpus/c8f478aa35ec77a762c0289f59baeb61fc4bbb7b b/external/boringssl/fuzz/privkey_corpus/c8f478aa35ec77a762c0289f59baeb61fc4bbb7b new file mode 100644 index 0000000000..a3e7397e93 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/c8f478aa35ec77a762c0289f59baeb61fc4bbb7b differ diff --git a/external/boringssl/fuzz/privkey_corpus/ca3805fce726847a1fcd57e100bde2c4058afa6e b/external/boringssl/fuzz/privkey_corpus/ca3805fce726847a1fcd57e100bde2c4058afa6e new file mode 100644 index 0000000000..8539d665c1 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/ca3805fce726847a1fcd57e100bde2c4058afa6e differ diff --git a/external/boringssl/fuzz/privkey_corpus/cb0a918db754c106d0ba72f50c03eb4b2a434e2b b/external/boringssl/fuzz/privkey_corpus/cb0a918db754c106d0ba72f50c03eb4b2a434e2b new file mode 100644 index 0000000000..bd126a9873 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/cb0a918db754c106d0ba72f50c03eb4b2a434e2b differ diff --git a/external/boringssl/fuzz/privkey_corpus/cbebcaa181e9397a660ad6e6f48e91c1c92c4c19 b/external/boringssl/fuzz/privkey_corpus/cbebcaa181e9397a660ad6e6f48e91c1c92c4c19 new file mode 100644 index 0000000000..cd1fa9d25c Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/cbebcaa181e9397a660ad6e6f48e91c1c92c4c19 differ diff --git a/external/boringssl/fuzz/privkey_corpus/cc28f7a74f73a3429ef1268030fff5ee64e09acf b/external/boringssl/fuzz/privkey_corpus/cc28f7a74f73a3429ef1268030fff5ee64e09acf new file mode 100644 index 0000000000..a2ef00ef66 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/cc28f7a74f73a3429ef1268030fff5ee64e09acf differ diff --git a/external/boringssl/fuzz/privkey_corpus/cd54bf63ab01d994be8c966cb92ef919530afc21 b/external/boringssl/fuzz/privkey_corpus/cd54bf63ab01d994be8c966cb92ef919530afc21 new file mode 100644 index 0000000000..857af6d19c Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/cd54bf63ab01d994be8c966cb92ef919530afc21 differ diff --git a/external/boringssl/fuzz/privkey_corpus/ce25fe172d2513459fb070d62778e3b7aa865016 b/external/boringssl/fuzz/privkey_corpus/ce25fe172d2513459fb070d62778e3b7aa865016 new file mode 100644 index 0000000000..66cc449b40 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/ce25fe172d2513459fb070d62778e3b7aa865016 differ diff --git a/external/boringssl/fuzz/privkey_corpus/ce3d342f48dc9d4602f9ec0b63d665fc54a06f62 b/external/boringssl/fuzz/privkey_corpus/ce3d342f48dc9d4602f9ec0b63d665fc54a06f62 new file mode 100644 index 0000000000..3ec8f23356 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/ce3d342f48dc9d4602f9ec0b63d665fc54a06f62 differ diff --git a/external/boringssl/fuzz/privkey_corpus/ce8427301dda48d954972a123a2d93a501761643 b/external/boringssl/fuzz/privkey_corpus/ce8427301dda48d954972a123a2d93a501761643 new file mode 100644 index 0000000000..d1428ae1df Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/ce8427301dda48d954972a123a2d93a501761643 differ diff --git a/external/boringssl/fuzz/privkey_corpus/d0b3bfe45b283df4ba481c7e64ec2400dc16ae99 b/external/boringssl/fuzz/privkey_corpus/d0b3bfe45b283df4ba481c7e64ec2400dc16ae99 new file mode 100644 index 0000000000..3013814e04 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/d0b3bfe45b283df4ba481c7e64ec2400dc16ae99 differ diff --git a/external/boringssl/fuzz/privkey_corpus/d1187b0b6682c51b58021364a766c43108691cc5 b/external/boringssl/fuzz/privkey_corpus/d1187b0b6682c51b58021364a766c43108691cc5 new file mode 100644 index 0000000000..6441dd8750 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/d1187b0b6682c51b58021364a766c43108691cc5 differ diff --git a/external/boringssl/fuzz/privkey_corpus/d124af93bea4a34e7faf20d4c2d81b93c2d8e7c1 b/external/boringssl/fuzz/privkey_corpus/d124af93bea4a34e7faf20d4c2d81b93c2d8e7c1 new file mode 100644 index 0000000000..f372111dc8 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/d124af93bea4a34e7faf20d4c2d81b93c2d8e7c1 differ diff --git a/external/boringssl/fuzz/privkey_corpus/d23dd357f27569aa18f9ca99bedc31267977eedb b/external/boringssl/fuzz/privkey_corpus/d23dd357f27569aa18f9ca99bedc31267977eedb new file mode 100644 index 0000000000..62f8bfcd21 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/d23dd357f27569aa18f9ca99bedc31267977eedb differ diff --git a/external/boringssl/fuzz/privkey_corpus/d36420fc5040deaf0c097779c63ad45c5dc40a2b b/external/boringssl/fuzz/privkey_corpus/d36420fc5040deaf0c097779c63ad45c5dc40a2b new file mode 100644 index 0000000000..9730d54863 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/d36420fc5040deaf0c097779c63ad45c5dc40a2b differ diff --git a/external/boringssl/fuzz/privkey_corpus/d3c7a122c93a36b2e2ddd3576ea446e0cb39fc32 b/external/boringssl/fuzz/privkey_corpus/d3c7a122c93a36b2e2ddd3576ea446e0cb39fc32 new file mode 100644 index 0000000000..68c6bdf9eb Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/d3c7a122c93a36b2e2ddd3576ea446e0cb39fc32 differ diff --git a/external/boringssl/fuzz/privkey_corpus/d70ddef2d9af1c0b3bca27e5e1fd28508151c3ec b/external/boringssl/fuzz/privkey_corpus/d70ddef2d9af1c0b3bca27e5e1fd28508151c3ec new file mode 100644 index 0000000000..f2ee4e4193 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/d70ddef2d9af1c0b3bca27e5e1fd28508151c3ec differ diff --git a/external/boringssl/fuzz/privkey_corpus/d87db84d6d07adc1eaf599cd5c648b12dd27ac35 b/external/boringssl/fuzz/privkey_corpus/d87db84d6d07adc1eaf599cd5c648b12dd27ac35 new file mode 100644 index 0000000000..750df24a15 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/d87db84d6d07adc1eaf599cd5c648b12dd27ac35 differ diff --git a/external/boringssl/fuzz/privkey_corpus/d91f6aa49d402a9e5af29198f642f5362e768ff0 b/external/boringssl/fuzz/privkey_corpus/d91f6aa49d402a9e5af29198f642f5362e768ff0 new file mode 100644 index 0000000000..404213d42f Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/d91f6aa49d402a9e5af29198f642f5362e768ff0 differ diff --git a/external/boringssl/fuzz/privkey_corpus/d9438c6b463eb1d6ad4b3927379bab36bbc83a28 b/external/boringssl/fuzz/privkey_corpus/d9438c6b463eb1d6ad4b3927379bab36bbc83a28 new file mode 100644 index 0000000000..1ae825ba2c Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/d9438c6b463eb1d6ad4b3927379bab36bbc83a28 differ diff --git a/external/boringssl/fuzz/privkey_corpus/d95b5a0a0e5f4899ec2810205fa188eaec863375 b/external/boringssl/fuzz/privkey_corpus/d95b5a0a0e5f4899ec2810205fa188eaec863375 new file mode 100644 index 0000000000..3078732923 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/d95b5a0a0e5f4899ec2810205fa188eaec863375 differ diff --git a/external/boringssl/fuzz/privkey_corpus/da5cb65f5a4b18e5667b7fa2e9dd0217f738da44 b/external/boringssl/fuzz/privkey_corpus/da5cb65f5a4b18e5667b7fa2e9dd0217f738da44 new file mode 100644 index 0000000000..2f694f0e5f Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/da5cb65f5a4b18e5667b7fa2e9dd0217f738da44 differ diff --git a/external/boringssl/fuzz/privkey_corpus/daa4d5092473a26fa51d907baf58b62001574112 b/external/boringssl/fuzz/privkey_corpus/daa4d5092473a26fa51d907baf58b62001574112 new file mode 100644 index 0000000000..9b533c2664 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/daa4d5092473a26fa51d907baf58b62001574112 differ diff --git a/external/boringssl/fuzz/privkey_corpus/db0897cfd10616880044b4ecd103a9b342bebdb7 b/external/boringssl/fuzz/privkey_corpus/db0897cfd10616880044b4ecd103a9b342bebdb7 new file mode 100644 index 0000000000..dba943b134 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/db0897cfd10616880044b4ecd103a9b342bebdb7 differ diff --git a/external/boringssl/fuzz/privkey_corpus/db168d324c7afabbd41281dea38fb921b26127a2 b/external/boringssl/fuzz/privkey_corpus/db168d324c7afabbd41281dea38fb921b26127a2 new file mode 100644 index 0000000000..c6de154b12 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/db168d324c7afabbd41281dea38fb921b26127a2 differ diff --git a/external/boringssl/fuzz/privkey_corpus/dcd1e294bde4644814fcce9efae0302f7eb0238a b/external/boringssl/fuzz/privkey_corpus/dcd1e294bde4644814fcce9efae0302f7eb0238a new file mode 100644 index 0000000000..f1e29a0da0 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/dcd1e294bde4644814fcce9efae0302f7eb0238a differ diff --git a/external/boringssl/fuzz/privkey_corpus/ddbc813e2d2bd98f212f672d957c4435ec2d44fd b/external/boringssl/fuzz/privkey_corpus/ddbc813e2d2bd98f212f672d957c4435ec2d44fd new file mode 100644 index 0000000000..38c7903a0e Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/ddbc813e2d2bd98f212f672d957c4435ec2d44fd differ diff --git a/external/boringssl/fuzz/privkey_corpus/de5041627e235f218681ba95d19f2e9173e63151 b/external/boringssl/fuzz/privkey_corpus/de5041627e235f218681ba95d19f2e9173e63151 new file mode 100644 index 0000000000..41689c31e4 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/de5041627e235f218681ba95d19f2e9173e63151 differ diff --git a/external/boringssl/fuzz/privkey_corpus/dec155c4b108bd455f1b4ef2aa7c126d99c8d041 b/external/boringssl/fuzz/privkey_corpus/dec155c4b108bd455f1b4ef2aa7c126d99c8d041 new file mode 100644 index 0000000000..29c82cc93e Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/dec155c4b108bd455f1b4ef2aa7c126d99c8d041 differ diff --git a/external/boringssl/fuzz/privkey_corpus/dedafeddf2d532a8e4c2659d81e774539df6d1e7 b/external/boringssl/fuzz/privkey_corpus/dedafeddf2d532a8e4c2659d81e774539df6d1e7 new file mode 100644 index 0000000000..82fab30c62 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/dedafeddf2d532a8e4c2659d81e774539df6d1e7 differ diff --git a/external/boringssl/fuzz/privkey_corpus/dfabe7f053a84772adcd20f73f28c4b7d4360091 b/external/boringssl/fuzz/privkey_corpus/dfabe7f053a84772adcd20f73f28c4b7d4360091 new file mode 100644 index 0000000000..ab88371c47 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/dfabe7f053a84772adcd20f73f28c4b7d4360091 differ diff --git a/external/boringssl/fuzz/privkey_corpus/e0c41dfc764c3a0343dbb9bc55109dc45f88798d b/external/boringssl/fuzz/privkey_corpus/e0c41dfc764c3a0343dbb9bc55109dc45f88798d new file mode 100644 index 0000000000..b2dc58aafe Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/e0c41dfc764c3a0343dbb9bc55109dc45f88798d differ diff --git a/external/boringssl/fuzz/privkey_corpus/e2e3d56e07f5c7c4a496c232fad04406eefedf54 b/external/boringssl/fuzz/privkey_corpus/e2e3d56e07f5c7c4a496c232fad04406eefedf54 new file mode 100644 index 0000000000..a671525d13 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/e2e3d56e07f5c7c4a496c232fad04406eefedf54 differ diff --git a/external/boringssl/fuzz/privkey_corpus/e37e78da0ab0693a777912980c4db4e9a8faa975 b/external/boringssl/fuzz/privkey_corpus/e37e78da0ab0693a777912980c4db4e9a8faa975 new file mode 100644 index 0000000000..307518d34c --- /dev/null +++ b/external/boringssl/fuzz/privkey_corpus/e37e78da0ab0693a777912980c4db4e9a8faa975 @@ -0,0 +1 @@ +v'0ÂR \ No newline at end of file diff --git a/external/boringssl/fuzz/privkey_corpus/e59134a28131083c665bb210e95ec94903f65b10 b/external/boringssl/fuzz/privkey_corpus/e59134a28131083c665bb210e95ec94903f65b10 new file mode 100644 index 0000000000..dba55f6e39 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/e59134a28131083c665bb210e95ec94903f65b10 differ diff --git a/external/boringssl/fuzz/privkey_corpus/e5b4fb31f24d7177673bd17da10fcc23bc5fc36d b/external/boringssl/fuzz/privkey_corpus/e5b4fb31f24d7177673bd17da10fcc23bc5fc36d new file mode 100644 index 0000000000..b4611b053e Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/e5b4fb31f24d7177673bd17da10fcc23bc5fc36d differ diff --git a/external/boringssl/fuzz/privkey_corpus/e5c82c5fcbe0067ffda8defedc3ce3a7fc1e0ce9 b/external/boringssl/fuzz/privkey_corpus/e5c82c5fcbe0067ffda8defedc3ce3a7fc1e0ce9 new file mode 100644 index 0000000000..d9361177d0 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/e5c82c5fcbe0067ffda8defedc3ce3a7fc1e0ce9 differ diff --git a/external/boringssl/fuzz/privkey_corpus/e5e988ac8dd0269554bc8c0d636c6c5f1ab306c5 b/external/boringssl/fuzz/privkey_corpus/e5e988ac8dd0269554bc8c0d636c6c5f1ab306c5 new file mode 100644 index 0000000000..2963c6a738 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/e5e988ac8dd0269554bc8c0d636c6c5f1ab306c5 differ diff --git a/external/boringssl/fuzz/privkey_corpus/e8570727b0bdb9794368ce4e52702cc6fa91660c b/external/boringssl/fuzz/privkey_corpus/e8570727b0bdb9794368ce4e52702cc6fa91660c new file mode 100644 index 0000000000..76d8ccd0e9 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/e8570727b0bdb9794368ce4e52702cc6fa91660c differ diff --git a/external/boringssl/fuzz/privkey_corpus/e877fa4f35693b4629b43b5e0a464f9239a8a0ad b/external/boringssl/fuzz/privkey_corpus/e877fa4f35693b4629b43b5e0a464f9239a8a0ad new file mode 100644 index 0000000000..bf71f0af0d Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/e877fa4f35693b4629b43b5e0a464f9239a8a0ad differ diff --git a/external/boringssl/fuzz/privkey_corpus/e8c30442040d5df46c96fcf09e200565851fd464 b/external/boringssl/fuzz/privkey_corpus/e8c30442040d5df46c96fcf09e200565851fd464 new file mode 100644 index 0000000000..b0b9279826 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/e8c30442040d5df46c96fcf09e200565851fd464 differ diff --git a/external/boringssl/fuzz/privkey_corpus/e9734e0052649aab1e22f6638d4e4070fd7675dc b/external/boringssl/fuzz/privkey_corpus/e9734e0052649aab1e22f6638d4e4070fd7675dc new file mode 100644 index 0000000000..ddd36e7b30 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/e9734e0052649aab1e22f6638d4e4070fd7675dc differ diff --git a/external/boringssl/fuzz/privkey_corpus/e97a189be7a813919db5a4b277d0978d762e6db7 b/external/boringssl/fuzz/privkey_corpus/e97a189be7a813919db5a4b277d0978d762e6db7 new file mode 100644 index 0000000000..15fcbfb1aa Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/e97a189be7a813919db5a4b277d0978d762e6db7 differ diff --git a/external/boringssl/fuzz/privkey_corpus/ea1fb604e956587f84c7af5ab9b2d0c39549be41 b/external/boringssl/fuzz/privkey_corpus/ea1fb604e956587f84c7af5ab9b2d0c39549be41 new file mode 100644 index 0000000000..ec04dac5c4 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/ea1fb604e956587f84c7af5ab9b2d0c39549be41 differ diff --git a/external/boringssl/fuzz/privkey_corpus/ebc358fc77925b5da9feec9b06a12724f7416477 b/external/boringssl/fuzz/privkey_corpus/ebc358fc77925b5da9feec9b06a12724f7416477 new file mode 100644 index 0000000000..084c5593e4 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/ebc358fc77925b5da9feec9b06a12724f7416477 differ diff --git a/external/boringssl/fuzz/privkey_corpus/ec8c496dd5407c982d19a0814c282bed0bc8ba94 b/external/boringssl/fuzz/privkey_corpus/ec8c496dd5407c982d19a0814c282bed0bc8ba94 new file mode 100644 index 0000000000..7bf2aaefe2 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/ec8c496dd5407c982d19a0814c282bed0bc8ba94 differ diff --git a/external/boringssl/fuzz/privkey_corpus/ec91f82481fda2b90261e991ea8a9bc210ca8424 b/external/boringssl/fuzz/privkey_corpus/ec91f82481fda2b90261e991ea8a9bc210ca8424 new file mode 100644 index 0000000000..07ec62fc66 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/ec91f82481fda2b90261e991ea8a9bc210ca8424 differ diff --git a/external/boringssl/fuzz/privkey_corpus/ecb6d9c45861c603a32054d8543fa740598751e7 b/external/boringssl/fuzz/privkey_corpus/ecb6d9c45861c603a32054d8543fa740598751e7 new file mode 100644 index 0000000000..00997d3e4f Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/ecb6d9c45861c603a32054d8543fa740598751e7 differ diff --git a/external/boringssl/fuzz/privkey_corpus/ee988717ae3fbaecc5463e174a397c35afcb400d b/external/boringssl/fuzz/privkey_corpus/ee988717ae3fbaecc5463e174a397c35afcb400d new file mode 100644 index 0000000000..bf86cb0add Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/ee988717ae3fbaecc5463e174a397c35afcb400d differ diff --git a/external/boringssl/fuzz/privkey_corpus/ef7b58b485fa43fe4db625066556e21c53d74c96 b/external/boringssl/fuzz/privkey_corpus/ef7b58b485fa43fe4db625066556e21c53d74c96 new file mode 100644 index 0000000000..3a67b04b07 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/ef7b58b485fa43fe4db625066556e21c53d74c96 differ diff --git a/external/boringssl/fuzz/privkey_corpus/f02080cd564a6b1a46ceff085f2a44ac015af1b8 b/external/boringssl/fuzz/privkey_corpus/f02080cd564a6b1a46ceff085f2a44ac015af1b8 new file mode 100644 index 0000000000..377e3b31c6 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/f02080cd564a6b1a46ceff085f2a44ac015af1b8 differ diff --git a/external/boringssl/fuzz/privkey_corpus/f0c2ec4a959d10612cd67742f319075d172da9ed b/external/boringssl/fuzz/privkey_corpus/f0c2ec4a959d10612cd67742f319075d172da9ed new file mode 100644 index 0000000000..fc452d7b87 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/f0c2ec4a959d10612cd67742f319075d172da9ed differ diff --git a/external/boringssl/fuzz/privkey_corpus/f195c020a28dfc5f2fb6af256b524ddcd93756ed b/external/boringssl/fuzz/privkey_corpus/f195c020a28dfc5f2fb6af256b524ddcd93756ed new file mode 100644 index 0000000000..b1d81e7935 --- /dev/null +++ b/external/boringssl/fuzz/privkey_corpus/f195c020a28dfc5f2fb6af256b524ddcd93756ed @@ -0,0 +1 @@ +Ÿ \ No newline at end of file diff --git a/external/boringssl/fuzz/privkey_corpus/f2672bb54f6a49d0c5b14c4da7ca3f790955c61d b/external/boringssl/fuzz/privkey_corpus/f2672bb54f6a49d0c5b14c4da7ca3f790955c61d new file mode 100644 index 0000000000..bc8d86844e Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/f2672bb54f6a49d0c5b14c4da7ca3f790955c61d differ diff --git a/external/boringssl/fuzz/privkey_corpus/f2b919fbae73d9d89c6afbd7352a6d6271db076b b/external/boringssl/fuzz/privkey_corpus/f2b919fbae73d9d89c6afbd7352a6d6271db076b new file mode 100644 index 0000000000..9deb868861 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/f2b919fbae73d9d89c6afbd7352a6d6271db076b differ diff --git a/external/boringssl/fuzz/privkey_corpus/f3494677a550ceb7644ca41d74f5358389eb162d b/external/boringssl/fuzz/privkey_corpus/f3494677a550ceb7644ca41d74f5358389eb162d new file mode 100644 index 0000000000..ef400c08a5 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/f3494677a550ceb7644ca41d74f5358389eb162d differ diff --git a/external/boringssl/fuzz/privkey_corpus/f3b6ac34b1e0de8b6a8bc0092af2546f17db985e b/external/boringssl/fuzz/privkey_corpus/f3b6ac34b1e0de8b6a8bc0092af2546f17db985e new file mode 100644 index 0000000000..fb96ad0ee1 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/f3b6ac34b1e0de8b6a8bc0092af2546f17db985e differ diff --git a/external/boringssl/fuzz/privkey_corpus/f510a4e3243a5214e171c388d4de68dbb074e34b b/external/boringssl/fuzz/privkey_corpus/f510a4e3243a5214e171c388d4de68dbb074e34b new file mode 100644 index 0000000000..d23b05afe0 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/f510a4e3243a5214e171c388d4de68dbb074e34b differ diff --git a/external/boringssl/fuzz/privkey_corpus/f63885f363b05455c24d547a378d98578529e6bd b/external/boringssl/fuzz/privkey_corpus/f63885f363b05455c24d547a378d98578529e6bd new file mode 100644 index 0000000000..31cdac4031 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/f63885f363b05455c24d547a378d98578529e6bd differ diff --git a/external/boringssl/fuzz/privkey_corpus/f67021300689c16cff95fac4d33565f788e820bd b/external/boringssl/fuzz/privkey_corpus/f67021300689c16cff95fac4d33565f788e820bd new file mode 100644 index 0000000000..854c083f11 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/f67021300689c16cff95fac4d33565f788e820bd differ diff --git a/external/boringssl/fuzz/privkey_corpus/f686aef722cf896abde5defa3dfc6d6533189eb7 b/external/boringssl/fuzz/privkey_corpus/f686aef722cf896abde5defa3dfc6d6533189eb7 new file mode 100644 index 0000000000..b1fa88cc00 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/f686aef722cf896abde5defa3dfc6d6533189eb7 differ diff --git a/external/boringssl/fuzz/privkey_corpus/f69f0bcbf3c1afcd32f0506afca7b37db449634e b/external/boringssl/fuzz/privkey_corpus/f69f0bcbf3c1afcd32f0506afca7b37db449634e new file mode 100644 index 0000000000..31a64ed340 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/f69f0bcbf3c1afcd32f0506afca7b37db449634e differ diff --git a/external/boringssl/fuzz/privkey_corpus/f6bf878f2c1a1f523e8b1cff0a2a3cfadb492c1e b/external/boringssl/fuzz/privkey_corpus/f6bf878f2c1a1f523e8b1cff0a2a3cfadb492c1e new file mode 100644 index 0000000000..6cf47b4b72 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/f6bf878f2c1a1f523e8b1cff0a2a3cfadb492c1e differ diff --git a/external/boringssl/fuzz/privkey_corpus/f84e4fd02339fdc0d688342523e803b1a786848a b/external/boringssl/fuzz/privkey_corpus/f84e4fd02339fdc0d688342523e803b1a786848a new file mode 100644 index 0000000000..ac6083674b Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/f84e4fd02339fdc0d688342523e803b1a786848a differ diff --git a/external/boringssl/fuzz/privkey_corpus/f99bca591409d3bab5f99232c5af1d7bf871e7ce b/external/boringssl/fuzz/privkey_corpus/f99bca591409d3bab5f99232c5af1d7bf871e7ce new file mode 100644 index 0000000000..f5092aa2aa Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/f99bca591409d3bab5f99232c5af1d7bf871e7ce differ diff --git a/external/boringssl/fuzz/privkey_corpus/fa21edf3b4aac56ad7c2e224d31b269b099f420d b/external/boringssl/fuzz/privkey_corpus/fa21edf3b4aac56ad7c2e224d31b269b099f420d new file mode 100644 index 0000000000..506ad56603 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/fa21edf3b4aac56ad7c2e224d31b269b099f420d differ diff --git a/external/boringssl/fuzz/privkey_corpus/fd0faf38df5b04f9a26ecd3084af7e669eb23a5e b/external/boringssl/fuzz/privkey_corpus/fd0faf38df5b04f9a26ecd3084af7e669eb23a5e new file mode 100644 index 0000000000..295d55aa3a Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/fd0faf38df5b04f9a26ecd3084af7e669eb23a5e differ diff --git a/external/boringssl/fuzz/privkey_corpus/fd3d7ba8e7ced0692c56beb9150b0bbbb546f208 b/external/boringssl/fuzz/privkey_corpus/fd3d7ba8e7ced0692c56beb9150b0bbbb546f208 new file mode 100644 index 0000000000..a33319c4ed Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/fd3d7ba8e7ced0692c56beb9150b0bbbb546f208 differ diff --git a/external/boringssl/fuzz/privkey_corpus/fe4c7ca0cd95cef2dca804ce88c3ee1e076197d4 b/external/boringssl/fuzz/privkey_corpus/fe4c7ca0cd95cef2dca804ce88c3ee1e076197d4 new file mode 100644 index 0000000000..8941f7f579 Binary files /dev/null and b/external/boringssl/fuzz/privkey_corpus/fe4c7ca0cd95cef2dca804ce88c3ee1e076197d4 differ diff --git a/external/boringssl/fuzz/read_pem.cc b/external/boringssl/fuzz/read_pem.cc new file mode 100644 index 0000000000..511c4ee060 --- /dev/null +++ b/external/boringssl/fuzz/read_pem.cc @@ -0,0 +1,36 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include +#include + + +extern "C" int LLVMFuzzerTestOneInput(uint8_t *buf, size_t len) { + char *name, *header; + uint8_t *pem_data; + long pem_len; + + BIO *bio = BIO_new_mem_buf(buf, len); + + if (PEM_read_bio(bio, &name, &header, &pem_data, &pem_len) == 1) { + OPENSSL_free(name); + OPENSSL_free(header); + OPENSSL_free(pem_data); + } + + BIO_free(bio); + + return 0; +} diff --git a/external/boringssl/fuzz/read_pem_corpus/01270d57eecae64f59b9b27cc06e3f9eaf2304e2 b/external/boringssl/fuzz/read_pem_corpus/01270d57eecae64f59b9b27cc06e3f9eaf2304e2 new file mode 100644 index 0000000000..7709f4a36a --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/01270d57eecae64f59b9b27cc06e3f9eaf2304e2 @@ -0,0 +1 @@ +-----BEGIN O-------- \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/0ab8318acaf6e678dd02e2b5c343ed41111b393d b/external/boringssl/fuzz/read_pem_corpus/0ab8318acaf6e678dd02e2b5c343ed41111b393d new file mode 100644 index 0000000000..74e0f12e32 --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/0ab8318acaf6e678dd02e2b5c343ed41111b393d @@ -0,0 +1 @@ +! \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/0b08765ad46bb11ac55348755ad5c8e4386bd2f3 b/external/boringssl/fuzz/read_pem_corpus/0b08765ad46bb11ac55348755ad5c8e4386bd2f3 new file mode 100644 index 0000000000..80ece3cf04 Binary files /dev/null and b/external/boringssl/fuzz/read_pem_corpus/0b08765ad46bb11ac55348755ad5c8e4386bd2f3 differ diff --git a/external/boringssl/fuzz/read_pem_corpus/0bdb9660f74f82a5471210026fdee0b674f1114e b/external/boringssl/fuzz/read_pem_corpus/0bdb9660f74f82a5471210026fdee0b674f1114e new file mode 100644 index 0000000000..6f429701ad --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/0bdb9660f74f82a5471210026fdee0b674f1114e @@ -0,0 +1,33 @@ +-G +----BEGIN O----- +----(END /!----‘G +( + 7-- +--BEGIN :°4'----- +G +UU -----BEGIN :°4'/---- +-----BEIN :°4'----- +G +UU-- +--BEGIN :°4'----- +G +UU -----BEGIN 2°4'/---- +----BEGIN :°4'----- +G +UU qG +wFUG + fbwFUU QG +wFU QG +wFUG + fbwFUU QG +wFU fbwFUUU G +bwFU f +bwFU U fbwFUU f +bwFU U fbU fbwF fUG + fbwFU f fTwFTU fbwFUf( +FUU f +bwFU U fbwFUUí‘;!(;)š-----EN ç/O!:š--- +---BE- NI-GO--- +---* + f +bwFU U fbU fbw-----BEG-F fU \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/0c4287915a432e6b50e1c2eb0f4ca037b1730aa0 b/external/boringssl/fuzz/read_pem_corpus/0c4287915a432e6b50e1c2eb0f4ca037b1730aa0 new file mode 100644 index 0000000000..0bcf00c1f5 Binary files /dev/null and b/external/boringssl/fuzz/read_pem_corpus/0c4287915a432e6b50e1c2eb0f4ca037b1730aa0 differ diff --git a/external/boringssl/fuzz/read_pem_corpus/0d583f2aee2e15a7dc7eb93af1ecf44203b537f4 b/external/boringssl/fuzz/read_pem_corpus/0d583f2aee2e15a7dc7eb93af1ecf44203b537f4 new file mode 100644 index 0000000000..8782df57c0 --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/0d583f2aee2e15a7dc7eb93af1ecf44203b537f4 @@ -0,0 +1,3 @@ +------BEG-* +----BEGIN N è)(!Ìùa!*ì)(ça'‡:':--!;'---BEGIN è)a'‡:'!;'R):u ;qrR)M +* \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/0e3deb2e809b535f39efded20697314a29c8335a b/external/boringssl/fuzz/read_pem_corpus/0e3deb2e809b535f39efded20697314a29c8335a new file mode 100644 index 0000000000..77d030eba4 --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/0e3deb2e809b535f39efded20697314a29c8335a @@ -0,0 +1,7 @@ +- +---BEGIN O----- +----(END--=--END /!-----BE-----END GI 5í‘;!(;)š-----END ç/!--- + +- +‘6ôí(- + \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/0f29362dfb076a14a103e8bc2c9681fac93c237d b/external/boringssl/fuzz/read_pem_corpus/0f29362dfb076a14a103e8bc2c9681fac93c237d new file mode 100644 index 0000000000..c8e019d145 Binary files /dev/null and b/external/boringssl/fuzz/read_pem_corpus/0f29362dfb076a14a103e8bc2c9681fac93c237d differ diff --git a/external/boringssl/fuzz/read_pem_corpus/1078e6b183abbe50aa19cffd741db1cb30e5cf4f b/external/boringssl/fuzz/read_pem_corpus/1078e6b183abbe50aa19cffd741db1cb30e5cf4f new file mode 100644 index 0000000000..61da76b971 --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/1078e6b183abbe50aa19cffd741db1cb30e5cf4f @@ -0,0 +1,8 @@ +-----BEGIN O!:š'U('ß((ç/!;!;‘O!:š'U('ß((ç/!;!;‘6í();':(´'H('G)M˜G¿ëÑ'yO )O(*---ç-- +-----BEGIN :(*ª:!:ŒO!:š'U('ß(:(ç/!;!;‘6í();-----BEGIN (ç/!;!;‘6í();':(´ò'H('G)':(´'H('G)M˜G¿ëÑ-----BEGIN O!:š'U('ß((ç/!;!;‘O!:š'U('ß((ç/!;!;‘3í();':(´'H('G)M˜G¿ëÑ'yO )O(*---ç-- +-----BEGIN :(*ª:!:ŒO!OÇ*Ä;ò¹:) +-----BEGIN :(ç/!;!;‘6í();':[´'H('G)MG¿Ñ'ë˜yO )o(*(Ç*;ò¹:) + +¬Ù*ª:!------ +----BEIN Ç*Ä;ò¹:) +N O!:š'U('ß((ç!;!;‘6í();''yO )o(*(Ç*Ä;ò¹:)·¬Ù*ª:!:Œ:(';±×'Ú(;—é)Ð(!:™)¢í:”"P•Z ˆw;:P:(´'H(%G; ) \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/149b4073e8ee2d37455c0d7867c7cffdecf0f8e1 b/external/boringssl/fuzz/read_pem_corpus/149b4073e8ee2d37455c0d7867c7cffdecf0f8e1 new file mode 100644 index 0000000000..71c2bae54d --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/149b4073e8ee2d37455c0d7867c7cffdecf0f8e1 @@ -0,0 +1,17 @@ +OÇ*Ä;ò¹:) +OÇ*Ä;ò¹:) + :(ç/!;!;‘7í();':[´'H 'G)MG¿Ñ'ëyO )o(*(Ç*Ä--------- +;ò¹:) +-----BEGIN¬OÇ*Ä;ò¹:) + + + :(ç/!;!;‘OÇ*Ä;ò¹:) +-----BEGIN :(ç/!;!;‘6í();':[´'H('G)MG¿Ñ'ë˜yO )o(*(Ç*Ä----- +¬ÙOÇ*Ä;ò¹:) + +----BEGIN O!:š'U('ß((ç/!;!;‘6í();'8(´'H('G)M˜G¿ëÑ'OÇ!*Ä;ò¹:) +:(ç-/!;!;‘6í();':(´'H('G)M˜G¿ëÑ'yO-----BEGIN----:Œ:(OÇ*Ä;ò¹:) +;(j-7í();';[´'H('Gç/!;!;‘6í();':(';±)MG¿Ñ'ë˜yO )o(*(Ç*Ä----- +ÙOÇ*Ä;ò¹:×) + +----B--E-6-BG \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/15dd914fbdc4335ebc69caa9afe37681dd75cc32 b/external/boringssl/fuzz/read_pem_corpus/15dd914fbdc4335ebc69caa9afe37681dd75cc32 new file mode 100644 index 0000000000..592aee1a70 --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/15dd914fbdc4335ebc69caa9afe37681dd75cc32 @@ -0,0 +1,17 @@ +------ +----- +----BEGIN ‘6í( + +----N!(ED /-----BEGI 6í‘;!(;)š--'-8-END ç- +---BEGIN O----- +----(END--=--END -----BEGIN O----- +----(END /!-----BEGIN 6í‘;!(;)š-----END ç//!-----!;BE-----END GI 5í‘;!(;)š-----END ç----- +/!--- + +- +‘6í/!--!----- +‘6í(- + +- +‘6ôí((- + \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/18810634408061267ccb64d68fb85b4ed93515e8 b/external/boringssl/fuzz/read_pem_corpus/18810634408061267ccb64d68fb85b4ed93515e8 new file mode 100644 index 0000000000..8cb5a8c8e3 --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/18810634408061267ccb64d68fb85b4ed93515e8 @@ -0,0 +1,45 @@ +-----BEGIN O-*--- +-( +-(END /!----‘G +( + (-- +( +BEGIN :°4'----- +G +UU -----BEGIN :°4'/---- +-----BEIN :°4'----- +G +UU-- +--BEGIN :°4'G +----- +G +UU -----BEGIN 2°4'/---- +-----BEGIN :°4'---=- +G +UU-----BEGIN O----- +-( +-(END /!----‘G +( + (-- +( +BEGIN :°4'----- +G +UU -----BEGIN :°4'/---- +-----BEIN QG +wF:°4'----- +G +UU-- +--BEGIN :°4'G +----- +G +UU -----BEGIN 2°4'/---- +-----BGIN :°4'----- +G +UU QG +wFUG + fbwFUU QG +wFU UQG +wFUG + fbwFUU QG +wFU fG + b \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/1f68f0ee67566b2954a4e2d2c31f6abb60cdaed5 b/external/boringssl/fuzz/read_pem_corpus/1f68f0ee67566b2954a4e2d2c31f6abb60cdaed5 new file mode 100644 index 0000000000..089c789248 --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/1f68f0ee67566b2954a4e2d2c31f6abb60cdaed5 @@ -0,0 +1,4 @@ +-* +-----BEG--)--BEGIN N è)a'‡:':--!;'* +---BEGIN è)a'‡:':!;'R):u::rR)M' +* \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/20a000f3932e041a634b759b7cef8138b5b40f67 b/external/boringssl/fuzz/read_pem_corpus/20a000f3932e041a634b759b7cef8138b5b40f67 new file mode 100644 index 0000000000..d3be1807c2 Binary files /dev/null and b/external/boringssl/fuzz/read_pem_corpus/20a000f3932e041a634b759b7cef8138b5b40f67 differ diff --git a/external/boringssl/fuzz/read_pem_corpus/20d3859cd71d9b215f55983a5ac9cce7c0a36cc4 b/external/boringssl/fuzz/read_pem_corpus/20d3859cd71d9b215f55983a5ac9cce7c0a36cc4 new file mode 100644 index 0000000000..e2d9d4c5cd Binary files /dev/null and b/external/boringssl/fuzz/read_pem_corpus/20d3859cd71d9b215f55983a5ac9cce7c0a36cc4 differ diff --git a/external/boringssl/fuzz/read_pem_corpus/217d0e120e43e1899a8ab51009de55038fe52789 b/external/boringssl/fuzz/read_pem_corpus/217d0e120e43e1899a8ab51009de55038fe52789 new file mode 100644 index 0000000000..b66cf6b857 --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/217d0e120e43e1899a8ab51009de55038fe52789 @@ -0,0 +1,15 @@ +-----BEGIN :T!(!*!*z:'*ô:èÍ°:!m®*ÍÕOÇ*Ä;ò¹:) +OÇ*Ä;ò¹:) + :(ç/!;!;‘7í();':[´'H 'G)MG¿Ñ'ëyO )o(*(Ç*Ä-------END ò¹:) +OÇ*Ä;ò¹:) +-----BEGIN¬OÇ*Ä;ò¹:) + + + :(ç/!;!;‘OÇ*Ä;ò¹:) +-----BEGIN :(ç/!;!;‘6í();':[´'H('G)MG¿Ñ'ë˜yO )(*(*ÇÄ----- +¬ÙOÇ*Ä;ò¹:) + +----BEGIN O!:š'U('ß((ç/!;!;‘6í();'8(´'H('1)M˜G¿ëÑ'OÇ!*Ä;ò¹:) +:(ç-/!;!;‘6í();':(´'H('G)M˜G¿ëÑ'yO-----BEGIN----:Œ:(OÇ*Ä;ò¹:) +;(j-7í();';[´'H('Gç/!;!;‘6í();':(';±)MG¿Ñ'ë˜yO )o(*(Ç*Ä----- +Ù-----END OÇ*;;)''D;Û…:f(;w:;Å;V*ÆH \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/2493849afd1697d00f4c2f36af4522e6a9ba46b8 b/external/boringssl/fuzz/read_pem_corpus/2493849afd1697d00f4c2f36af4522e6a9ba46b8 new file mode 100644 index 0000000000..08dee539a8 Binary files /dev/null and b/external/boringssl/fuzz/read_pem_corpus/2493849afd1697d00f4c2f36af4522e6a9ba46b8 differ diff --git a/external/boringssl/fuzz/read_pem_corpus/27c891aa76f51487ada28b1fc69ac13c7315c933 b/external/boringssl/fuzz/read_pem_corpus/27c891aa76f51487ada28b1fc69ac13c7315c933 new file mode 100644 index 0000000000..ffa0411365 Binary files /dev/null and b/external/boringssl/fuzz/read_pem_corpus/27c891aa76f51487ada28b1fc69ac13c7315c933 differ diff --git a/external/boringssl/fuzz/read_pem_corpus/27ec8c0bf073ec4ea4f5ee15fbaca4fb32f728b3 b/external/boringssl/fuzz/read_pem_corpus/27ec8c0bf073ec4ea4f5ee15fbaca4fb32f728b3 new file mode 100644 index 0000000000..db3ca3cc93 --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/27ec8c0bf073ec4ea4f5ee15fbaca4fb32f728b3 @@ -0,0 +1 @@ +O!:š'U('ß((ç/!;!;‘6í();'8(´'H('G)M˜G¿ëÑ'yO )o(*(Ç*Ä;ò¹:)·¬ÙO!:š'U(*ª:!:Œ:(';±×'Ú(;'ß(:(ç/)é)Ð(-----BEGIN (ç/!;!;‘6í();':(´'!;!;H('G)M˜G¿ëÑ'yO*o( )(Ç*Ä;ò¹:)·¬Ù*ª:!:Œ:(';±×'Ú(‘6;—é)Ð(!:™)¢í:”"P•Z ˆw;:P; :':Â:7!)÷ö)vôǾ:kqU;|:ØŽ8*:;sá(f!‘;;)j*:: \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/2904f9b6f6cb0ddf9248537b4fb4b2170174b74f b/external/boringssl/fuzz/read_pem_corpus/2904f9b6f6cb0ddf9248537b4fb4b2170174b74f new file mode 100644 index 0000000000..0e95e43bff --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/2904f9b6f6cb0ddf9248537b4fb4b2170174b74f @@ -0,0 +1,3 @@ +-----BEGIN x:€**”Á*Ñ**f(À~'!5 ) );á'*EÆþ-----þ---------- + +-----Eâ::Tð*Ñ**f(À~'!5); Cá'*EÆ;Ÿ:;h0G;G´('!Í*'l*)!:!:;'4¿®ÆC*ˆ3Ÿ:)((#('²:¡('î'uÂ*!!³!;›!;) \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/2a7b8759f3267d3ddca22e936df0b21eabb1aeed b/external/boringssl/fuzz/read_pem_corpus/2a7b8759f3267d3ddca22e936df0b21eabb1aeed new file mode 100644 index 0000000000..e07812af50 Binary files /dev/null and b/external/boringssl/fuzz/read_pem_corpus/2a7b8759f3267d3ddca22e936df0b21eabb1aeed differ diff --git a/external/boringssl/fuzz/read_pem_corpus/2aaf881c96d0758e5ac244a74deccb7e6363c111 b/external/boringssl/fuzz/read_pem_corpus/2aaf881c96d0758e5ac244a74deccb7e6363c111 new file mode 100644 index 0000000000..08e697b65a --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/2aaf881c96d0758e5ac244a74deccb7e6363c111 @@ -0,0 +1,14 @@ +-----BEGIN O----- +----(END /!-----BEGI 7í‘;!(;)š-----END ç/O!:š--- +-----END O----- +----(END /!---'U('ß(:(ç!/;!;‘6í();':(´'H('G)M˜G¿ëÑ'yO- + )o(*(Ç*Ä;ò¹:)·¬Ù*ª:!- +:(';±×'Ú(;—é)- +Ð(!:™)¢í:”"P•Z ˆg;:; :':Â:7!)÷ö)v*Ǿ:--BEGIN 6í‘;!(;)š-- +----END ç/!----- +- +kqU;!:Oš'U|:ØŽ9*:;sá(f!‘;;)------ +----BEGIN ‘O----- +----(END /!-----BEGIN 6í +j- +‘;!(;)š-----END 6çí( \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/2ef2666e807e55481eb81bd2bd8369a4422dfc6f b/external/boringssl/fuzz/read_pem_corpus/2ef2666e807e55481eb81bd2bd8369a4422dfc6f new file mode 100644 index 0000000000..5ed63dd8dc --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/2ef2666e807e55481eb81bd2bd8369a4422dfc6f @@ -0,0 +1,5 @@ +-----BEGIN --‡+ô---'---+ô------- + +èè-----BEGIN :T!(!*!*z:HŒ_t);ˆú~*Nñ?!:m®*ÍÕ;ì*Æ'---+ô-------- +GIN '----- +:T!(!-Èc:>:ó;}!í;*Ú:!;å¼'y 'x»'ž`ô)¾*¬a;:!E!Ù*Ë)(*)()''*:·E*:1***!*z:HŒ:*'*$'F'¬;ø'*ìTÝ!):- \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/318bcf81a2b6fa0ce680ec82cf11e8a6e4bd93f0 b/external/boringssl/fuzz/read_pem_corpus/318bcf81a2b6fa0ce680ec82cf11e8a6e4bd93f0 new file mode 100644 index 0000000000..36b112609e --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/318bcf81a2b6fa0ce680ec82cf11e8a6e4bd93f0 @@ -0,0 +1,4 @@ +-----BEGIN O----- +----(END /!-----BEGI 2í‘;!(;)š-----EçDÎ/ !--- + +-‘6í( \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/358ff4aeb6903affa5d080c317c3270ac4f13121 b/external/boringssl/fuzz/read_pem_corpus/358ff4aeb6903affa5d080c317c3270ac4f13121 new file mode 100644 index 0000000000..be1427a10e --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/358ff4aeb6903affa5d080c317c3270ac4f13121 @@ -0,0 +1 @@ +Ç- \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/35bae979e092abdc6b31f8b3c52ddcafa4722a9a b/external/boringssl/fuzz/read_pem_corpus/35bae979e092abdc6b31f8b3c52ddcafa4722a9a new file mode 100644 index 0000000000..654203b5d6 --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/35bae979e092abdc6b31f8b3c52ddcafa4722a9a @@ -0,0 +1,11 @@ +-----BEGIN O---- +----N!(ED /-----BEGI 6í‘;!(;)š----8-END ç- +---BEGIN O----- +----(END--=--END /!-----BE-----END GI 5í‘;!(;)š-----END ç/!--- + +- +‘6í/!--- + +- +‘6ôí((- + \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/38fccbaee723a06ca137a952843b58d32d35ef25 b/external/boringssl/fuzz/read_pem_corpus/38fccbaee723a06ca137a952843b58d32d35ef25 new file mode 100644 index 0000000000..1ddb5fd95e --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/38fccbaee723a06ca137a952843b58d32d35ef25 @@ -0,0 +1,2 @@ +-----BEGIN --+ô----- +è \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/3aaa3cdd4444fad7e59ba1ac2c0cbe6b60ea1181 b/external/boringssl/fuzz/read_pem_corpus/3aaa3cdd4444fad7e59ba1ac2c0cbe6b60ea1181 new file mode 100644 index 0000000000..de6ff53b59 --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/3aaa3cdd4444fad7e59ba1ac2c0cbe6b60ea1181 @@ -0,0 +1 @@ +-----BEGIN \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/3b981c1e4697103278b32ee4e29e3a7b5225d798 b/external/boringssl/fuzz/read_pem_corpus/3b981c1e4697103278b32ee4e29e3a7b5225d798 new file mode 100644 index 0000000000..9f35df061d --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/3b981c1e4697103278b32ee4e29e3a7b5225d798 @@ -0,0 +1,14 @@ +OÇ*Ä;ò¹:) +OÇ*Ä;ò¹:) + :(ç/!;!;‘7í();':[´'H 'G)MG¿Ñ'ëyO )o(*(Ç*Ä-------END ò¹:) +-----BEGIN¬OÇ*Ä;ò¹:) + + + :(ç/!;!;‘OÇ*Ä;ò¹:) +-----BEGIN :(ç/!;!;‘6í();':[´'H('G)MG¿Ñ'ë˜yO )(*(Ç*Ä----- +¬ÙOÇ*Ä;ò¹:) + +----BEGIN O!:š'U('ß((ç/!;!;‘6í();'8(´'H('1)M˜G¿ëÑ'OÇ!*Ä;ò¹:) +:(ç-/!;!;‘6í();':(´'H('G)M˜G¿ëÑ'yO-----BEGIN----:Œ:(OÇ*Ä;ò¹:) +;(j-7í();';[´'H('Gç/!;!;‘6í();':(';±)MG¿Ñ'ë˜yO )o(*(Ç*Ä----- +Ù-----END OÇ*;;)''D;Û…:f(;w:;Å ,Ÿ=*'í4>;9:°ç(ñð;'5Ø*iØ)T×;:)Ä \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/3bff6c9ef0381ea1080fdfb5b4f9c02e95f549b2 b/external/boringssl/fuzz/read_pem_corpus/3bff6c9ef0381ea1080fdfb5b4f9c02e95f549b2 new file mode 100644 index 0000000000..c998e40ad3 Binary files /dev/null and b/external/boringssl/fuzz/read_pem_corpus/3bff6c9ef0381ea1080fdfb5b4f9c02e95f549b2 differ diff --git a/external/boringssl/fuzz/read_pem_corpus/3cdb51f7ffc8ef0bd03265c3a414069815821d18 b/external/boringssl/fuzz/read_pem_corpus/3cdb51f7ffc8ef0bd03265c3a414069815821d18 new file mode 100644 index 0000000000..60180841a2 Binary files /dev/null and b/external/boringssl/fuzz/read_pem_corpus/3cdb51f7ffc8ef0bd03265c3a414069815821d18 differ diff --git a/external/boringssl/fuzz/read_pem_corpus/3f46a93da1448c00d2a9f3a62117bd522ce8de64 b/external/boringssl/fuzz/read_pem_corpus/3f46a93da1448c00d2a9f3a62117bd522ce8de64 new file mode 100644 index 0000000000..a082d7ca87 Binary files /dev/null and b/external/boringssl/fuzz/read_pem_corpus/3f46a93da1448c00d2a9f3a62117bd522ce8de64 differ diff --git a/external/boringssl/fuzz/read_pem_corpus/411752e433e18c27f83b9728256082c2ffb77ebb b/external/boringssl/fuzz/read_pem_corpus/411752e433e18c27f83b9728256082c2ffb77ebb new file mode 100644 index 0000000000..cc8856077b --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/411752e433e18c27f83b9728256082c2ffb77ebb @@ -0,0 +1,15 @@ +OÇ*Ä;ò¹:) +OÇ*Ä;ò¹:) + :(ç/!;!;‘7í();':[´'H 'G)MG¿Ñ'ëyO )o(*(Ç*Ä-------END ò¹:) +-----BEGIN¬OÇ*Ä;ò¹:) + + + :(ç/!;!;‘OÇ*Ä;ò¹:) +-----BEGIN :(ç/!;!;‘6í();':[´'H('G)MG¿Ñ'ë˜yO )(*(Ç*Ä----- +¬ÙOÇ*Ä;ò¹:) + +----BEGIN O!:š'U('ß((ç/!;!;‘6í();'8(´'H('1)M˜G¿ëÑ'OÇ!*Ä;ò¹:) +:(ç-/!;!;‘6í();':(´'H('G)M˜G¿ëÑ'yO-----BEGIN----:Œ:(OÇ*Ä;ò¹:) +;(j-7í();';[´'H('Gç/!;!;‘6í();':(';±)MG¿Ñ'ë˜yO )o(*(Ç*Ä----- +Ù-----END OÇ*;;)''D;Û…:f(;w:;Å ,Ÿ=*'í4>;9:°ç(ñð;'5Ø*iØ)T×;:G +)Ä \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/42650de48dbf62d86a91ede484061f834214915d b/external/boringssl/fuzz/read_pem_corpus/42650de48dbf62d86a91ede484061f834214915d new file mode 100644 index 0000000000..bc4db0e67b --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/42650de48dbf62d86a91ede484061f834214915d @@ -0,0 +1,2 @@ +-----BEGIN O----- +----(END------B /!----BEGIN 6í‘;!(;)š-----END çEGIN ---/!;!‘6í(-BEGIN Oô \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/488ae502baabc6506f8722dcdc5294940fa5d588 b/external/boringssl/fuzz/read_pem_corpus/488ae502baabc6506f8722dcdc5294940fa5d588 new file mode 100644 index 0000000000..ec5064dcd3 Binary files /dev/null and b/external/boringssl/fuzz/read_pem_corpus/488ae502baabc6506f8722dcdc5294940fa5d588 differ diff --git a/external/boringssl/fuzz/read_pem_corpus/4aa25eda7560bbd746d9a69b63965c0de21bb53e b/external/boringssl/fuzz/read_pem_corpus/4aa25eda7560bbd746d9a69b63965c0de21bb53e new file mode 100644 index 0000000000..8935731f9b --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/4aa25eda7560bbd746d9a69b63965c0de21bb53e @@ -0,0 +1,34 @@ +-----BEGIN O----- +-( +-(END /!----‘G +( + (-- +( +BEGIN :°4'----- +G +UU -----BEGIN :°4'/---- +-----BEIN :°4'----- +G +UU-- +--BEGIN :°4'G +----- +G +UU -----BEGIN 2°4'/---- +-----BEGIN :°4'----- +G +UU QG +wFUG + fbwFUU QG +wFU QG +wFUG + fbwFUU QG +wFU fbwFUUU G +bwFU f +bwFU U f fbwFUU f +bwFU U fbU fbwF fUG + fbwFU f fTwFTU fbwFUfbwFUU f +bwFU U fbwFUUí‘;!(;)š-----EN ç/O!:š--- +---BE- NI-GO--- +---* + f +bwFU U fbU fbw-----BEG-F fU \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/4b32aa9edbd17b2d63390a41cc98739be7d45596 b/external/boringssl/fuzz/read_pem_corpus/4b32aa9edbd17b2d63390a41cc98739be7d45596 new file mode 100644 index 0000000000..0240c224ea --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/4b32aa9edbd17b2d63390a41cc98739be7d45596 @@ -0,0 +1,7 @@ +-----BEGIN :°4'----- + f uf f - +;3;w: ,Ÿ=*'í3>;9:5ð;(°'çñØ*iØ)T'fµi'(;n*;;Ñ*?;¯Â----- +-----END :°4'----- +:$;(:!@;L)J‘))':ýZ:!ã:.6'y:*'*aíYXX;À‡:Ø()*!;Sß------BEGIN Û…:f(;w:;Å ,Ÿ=*'í3>;9:°ç(ñð;µi'(; +E=BEGI(N-----)GIÔ‚'Ð)*–::!!;!²>:r*>!oT#!>;):))†ä¸ :pÑ*òÄ;e÷' *(%ùy¬*'£;*'Ÿ(“d'!¥;Õï;æN 'µi'(; +%i;;)''D;Û…:;;)j':'È;þ;ki!£ûš'!''D;Ûm!!Æ(£'4!$­!0*‘… \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/4d43fa4e63042871afdb387b75a8845d47b46d18 b/external/boringssl/fuzz/read_pem_corpus/4d43fa4e63042871afdb387b75a8845d47b46d18 new file mode 100644 index 0000000000..23ab556b4c Binary files /dev/null and b/external/boringssl/fuzz/read_pem_corpus/4d43fa4e63042871afdb387b75a8845d47b46d18 differ diff --git a/external/boringssl/fuzz/read_pem_corpus/548649f5502df5e77b9d332d3f1e29dedd7afdb2 b/external/boringssl/fuzz/read_pem_corpus/548649f5502df5e77b9d332d3f1e29dedd7afdb2 new file mode 100644 index 0000000000..a6b3eb0c1b Binary files /dev/null and b/external/boringssl/fuzz/read_pem_corpus/548649f5502df5e77b9d332d3f1e29dedd7afdb2 differ diff --git a/external/boringssl/fuzz/read_pem_corpus/55885a3f94688b36e34fac8ce1fd7fcc7bb7208c b/external/boringssl/fuzz/read_pem_corpus/55885a3f94688b36e34fac8ce1fd7fcc7bb7208c new file mode 100644 index 0000000000..dbf27e96c5 Binary files /dev/null and b/external/boringssl/fuzz/read_pem_corpus/55885a3f94688b36e34fac8ce1fd7fcc7bb7208c differ diff --git a/external/boringssl/fuzz/read_pem_corpus/5891dd7c6715eca7f427ed9267de9da72b8e82e8 b/external/boringssl/fuzz/read_pem_corpus/5891dd7c6715eca7f427ed9267de9da72b8e82e8 new file mode 100644 index 0000000000..fe31431959 --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/5891dd7c6715eca7f427ed9267de9da72b8e82e8 @@ -0,0 +1,15 @@ +-----BEGIN :T!(!*!*z:'*ô:èÍ°:!m®*ÍÕOÇ*Ä;ò¹:) +OÇ*Ä;ò¹:) + :(ç/!;!;‘7í();':[´'H 'G)MG¿Ñ'ëyO )o(*(Ç*Ä-------END ò¹:) +-----BEGIN¬OÇ*Ä;ò¹:) + + + :(ç/!;!;‘OÇ*Ä;ò¹:) +-----BEGIN :(ç/!;!;‘6í();':[´'H('G)MG¿Ñ'ë˜yO )(*(Ç*Ä----- +¬ÙOÇ*Ä;ò¹:) + +----BEGIN O!:š'U('ß((ç/!;!;‘6í();'8(´'H('1)M˜G¿ëÑ'OÇ!*Ä;ò¹:) +:(ç-/!;!;‘6í();':(´'H('G)M˜G¿ëÑ'yO-----BEGIN----:Œ:(OÇ*Ä;ò¹:) +;(j-7í();';[´'H('Gç/!;!;‘6í();':(';±)MG¿Ñ'ë˜yO )o(*(Ç*Ä----- +Ù-----END OÇ*;;)''D;Û…:f(;w:;Å;ì*ÆHŒ----- + \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/58bdb0aea139a2790c2e1a3b25e302892a6c4b55 b/external/boringssl/fuzz/read_pem_corpus/58bdb0aea139a2790c2e1a3b25e302892a6c4b55 new file mode 100644 index 0000000000..2a9c6c51db Binary files /dev/null and b/external/boringssl/fuzz/read_pem_corpus/58bdb0aea139a2790c2e1a3b25e302892a6c4b55 differ diff --git a/external/boringssl/fuzz/read_pem_corpus/5c720dc0326e4ffa322f706337df9bc87f42fd96 b/external/boringssl/fuzz/read_pem_corpus/5c720dc0326e4ffa322f706337df9bc87f42fd96 new file mode 100644 index 0000000000..32ddacab9a Binary files /dev/null and b/external/boringssl/fuzz/read_pem_corpus/5c720dc0326e4ffa322f706337df9bc87f42fd96 differ diff --git a/external/boringssl/fuzz/read_pem_corpus/667da9df1cde33d635bbde1986827573ed686a7e b/external/boringssl/fuzz/read_pem_corpus/667da9df1cde33d635bbde1986827573ed686a7e new file mode 100644 index 0000000000..e0f7f03577 --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/667da9df1cde33d635bbde1986827573ed686a7e @@ -0,0 +1,6 @@ +OÇ*Ä;ò¹:) +-----BEGIN :(ç/!;!;‘6í();':[´'H('G)MG¿Ñ'ë˜yO )o(*(Ç*Ä----- +¬ÙOÇ*Ä;ò¹:) + +----BEGIN O!:š'U('OÇ*Ä;ò¹:) +-----BEGIN :(ç/!ß((ç \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/66f8b696c46c10a6db20b690e4431b72745f4760 b/external/boringssl/fuzz/read_pem_corpus/66f8b696c46c10a6db20b690e4431b72745f4760 new file mode 100644 index 0000000000..1a3eaae40e --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/66f8b696c46c10a6db20b690e4431b72745f4760 @@ -0,0 +1,7 @@ +-----BEGIN !:T(!*!*z:HŒ----- +F'*ìT!:m®*ÍÕ;ì*ÆÈc:>:ó;}!í;*Z:!;å¼'y 'x»'ž`ô)¾*¬a;:!E!Ù*Ë)('---+ô----­ +è*)()''*:·E*:1**'¬;øÝ)*(¬;Ë*-----vBEGIN --+ô---'---+ô------/ + +ìè-----BEGIN --+ô---'---+ô-----è-- + +èè \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/699044ddfe4887d6081ce2a36c1302814294eb68 b/external/boringssl/fuzz/read_pem_corpus/699044ddfe4887d6081ce2a36c1302814294eb68 new file mode 100644 index 0000000000..3e36ec287b --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/699044ddfe4887d6081ce2a36c1302814294eb68 @@ -0,0 +1,15 @@ +--* +--* +BEGIN -* +Ìùa!*ì)(ç-----BE-* + +----BEGIN N è--* +--* +BEGIN -* +Ìùa!*ì)(ç-----BE-* + +----BEGIN N è)(!Ìùa!*ì)(ça'‡:':--!9'---BEGIN è†)a'-* +Ìùa!*ì)(ç--‰:'!;'R):w (;Rrq)---B)(!Ìùa!*ì)(ça'‡:'E-* + +----BEGIN N è:--!9'---BEGIN è†)a')(!-* +ÌùÌ \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/6d1d12ef00c585b4c859479bfa2522f4a447d907 b/external/boringssl/fuzz/read_pem_corpus/6d1d12ef00c585b4c859479bfa2522f4a447d907 new file mode 100644 index 0000000000..3c91ae4434 --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/6d1d12ef00c585b4c859479bfa2522f4a447d907 @@ -0,0 +1,5 @@ +-----BEGIN --+ô---'------BEGIN --‡+ô---'---+ô------- + +èè-----BEGIN :T!(ñ!**z:HŒ_t);ˆú~*Nñ?!:m®*ÍÕ;ì*Æ'----+ô------/ + +-è \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/6d67bafd83bed7aadd641417671e6864dc87073c b/external/boringssl/fuzz/read_pem_corpus/6d67bafd83bed7aadd641417671e6864dc87073c new file mode 100644 index 0000000000..50119ec34e --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/6d67bafd83bed7aadd641417671e6864dc87073c @@ -0,0 +1,16 @@ +OÇ*Ä;ò¹:) +OÇ*Ä;ò¹:) + :(ç/!;!;‘7í();':[´'H 'G)MG¿Ñ'ëyO )o(*(Ç*Ä-------END ò¹:) +-----BEGIN¬OÇ*Ä;ò¹:) + + + :(ç/!;!;‘OÇ*Ä;ò¹:) +-----BEGIN :(ç/!;!;‘6í();':[´'H('G)MG¿Ñ'ë˜yO )o(*(Ç*Ä----- +¬ÙOÇ*Ä;ò¹:) + +----BEGIN O!:š'U('ß((ç/!;!;‘6í();'8(´'H('G)M˜G¿ëÑ'OÇ!*Ä;ò¹:) +:(ç-/!;!;‘6í();':(´'H('G)M˜G¿ëÑ'yO-----BEGIN----:Œ:(OÇ*Ä;ò¹:) +;(j-7í();';[´'H('Gç/!;!;‘6í();':(';±)MG¿Ñ'ë˜yO )o(*(Ç*Ä----- +Ù-----END OÇ*×;:)Ĺò + +----B--E-6-BG \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/6dcb7976d9af4a72b3667926f1fe7642c75685b2 b/external/boringssl/fuzz/read_pem_corpus/6dcb7976d9af4a72b3667926f1fe7642c75685b2 new file mode 100644 index 0000000000..2090fe2068 Binary files /dev/null and b/external/boringssl/fuzz/read_pem_corpus/6dcb7976d9af4a72b3667926f1fe7642c75685b2 differ diff --git a/external/boringssl/fuzz/read_pem_corpus/6e6aa5ec1653a57a37c043255ab834f6b2228b80 b/external/boringssl/fuzz/read_pem_corpus/6e6aa5ec1653a57a37c043255ab834f6b2228b80 new file mode 100644 index 0000000000..7ad3f5c39b --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/6e6aa5ec1653a57a37c043255ab834f6b2228b80 @@ -0,0 +1,2 @@ +-----BEGIN O!:š'U('ß((ç/!;!;‘O!:š'U('ß((ç/!;!;‘3í();':(´'H('GOÇ*Ä;ò¹:) +-----BEGIN :(ç/!;!;‘6í();':[´'H('G)MG¿Ñ'ë˜yO )o(*(Ç*)M˜G¿ëÑ'Ä----- \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/729be2837328d9f25597b1d605188bc724c632e6 b/external/boringssl/fuzz/read_pem_corpus/729be2837328d9f25597b1d605188bc724c632e6 new file mode 100644 index 0000000000..6f38622941 --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/729be2837328d9f25597b1d605188bc724c632e6 @@ -0,0 +1,6 @@ +OÇ*Ä;ò¹:) +-----BEGIN :(ç/!;!;‘6í();':[´'H('G)MG¿Ñ'ë˜yO )o(*(Ç*Ä----- +¬ÙOÇ*Ä;ò¹:) + +----BEGIN O!:š'U('ß((ç/!;!;‘6í();'8(´'H('G)M˜G¿ëÑ'OÇ*Ä;ò¹:) +:(ç-/!;!;‘6í();':(´'H('G)M˜G¿ëÑ'yO-----BEGIN----:Œ:(----BEGIN ;(j-ç/!;!;‘6í();':(';±× \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/74a4f38726a49f3a8c06763d58d8fc229b2aa915 b/external/boringssl/fuzz/read_pem_corpus/74a4f38726a49f3a8c06763d58d8fc229b2aa915 new file mode 100644 index 0000000000..a88821da31 --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/74a4f38726a49f3a8c06763d58d8fc229b2aa915 @@ -0,0 +1,3 @@ +-----BEGIN --+ô---'---+ô------- + +èè \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/74b9536c60def2f9cb8e83512b80ff8406d12567 b/external/boringssl/fuzz/read_pem_corpus/74b9536c60def2f9cb8e83512b80ff8406d12567 new file mode 100644 index 0000000000..fc048fe483 Binary files /dev/null and b/external/boringssl/fuzz/read_pem_corpus/74b9536c60def2f9cb8e83512b80ff8406d12567 differ diff --git a/external/boringssl/fuzz/read_pem_corpus/74b97735df0ee03d5a912734de93772093826bda b/external/boringssl/fuzz/read_pem_corpus/74b97735df0ee03d5a912734de93772093826bda new file mode 100644 index 0000000000..16ea15dd6d --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/74b97735df0ee03d5a912734de93772093826bda @@ -0,0 +1,33 @@ +-‘6í( + +----- +----BEGIN ‘6í( + +----N!(ED /-----BEGI 5í‘;!(»)š--'-8-END ç- +---BEGIN O----- +----(END--=--E------ +----- +----ND -----BEGIN O----- +----(END /!-----BEGIN 6í‘;!(;)š-----END ç//!-----!;BE-----END GI 5í‘;!(;)š-----END ç/!--- + +- +‘6íBEGIN ‘6í( + +----N!(ED /-----BEGI 6í‘;!(;)š--'-8-END ç- +---BEGIN O----- +---;(END--=--END -----BEGIN O- +--- +----(END /!-----BEGIN 6í‘;!(;)š-----END ç//!-----!;BE-----END GI 5í/!--!----- +‘6í(-‘;!(;)š-----END ç/!--- + +- +Ñ6í/!-- + +- +‘6ôí((- +!----- +‘6í(- + +- +‘6ôí((- + \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/7539289d67a0974d16f0ed01ded0a58a02b21126 b/external/boringssl/fuzz/read_pem_corpus/7539289d67a0974d16f0ed01ded0a58a02b21126 new file mode 100644 index 0000000000..59ae4f4716 --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/7539289d67a0974d16f0ed01ded0a58a02b21126 @@ -0,0 +1 @@ +ô \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/78c435e1927ec196afab938edced0b9ee267e70b b/external/boringssl/fuzz/read_pem_corpus/78c435e1927ec196afab938edced0b9ee267e70b new file mode 100644 index 0000000000..7eeef2a9c2 Binary files /dev/null and b/external/boringssl/fuzz/read_pem_corpus/78c435e1927ec196afab938edced0b9ee267e70b differ diff --git a/external/boringssl/fuzz/read_pem_corpus/78e4c8a5d73cf074f243ef12a3669fef1e848121 b/external/boringssl/fuzz/read_pem_corpus/78e4c8a5d73cf074f243ef12a3669fef1e848121 new file mode 100644 index 0000000000..890697e640 --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/78e4c8a5d73cf074f243ef12a3669fef1e848121 @@ -0,0 +1,10 @@ +-----BEGIN O----- +----(END /!-----BEGI 7í‘;!(;)š-----END ç/O!:š-----BEGIN O----- +----(END /!---'U('ß(:(ç/!;!;‘6í();':(´'H('G)M˜G¿ëÑ'yO- + )o(*(Ç*Ä;ò¹:)·¬Ù*ª:!:Œ:(';±×'Ú(;—é)Ð(!:™)¢í:”"P•Z ˆg;:; :':Â:7!)÷ö)vôǾ:--BEGIN 6í‘;!(;)š-- +----END ç/!----- +- +kqU;O!:š'U|:ØŽ8*:;sá(f!‘;;)--*---- +----BEGIN ‘O----- +----(END /!-----BEGIN 6í- +j*:‘;!(;)š-----END 6çí( \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/7a582440bd4712ab88a3e745f928202707585e6f b/external/boringssl/fuzz/read_pem_corpus/7a582440bd4712ab88a3e745f928202707585e6f new file mode 100644 index 0000000000..84f5797cd6 --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/7a582440bd4712ab88a3e745f928202707585e6f @@ -0,0 +1,33 @@ +-----BEGIN O----- +-( +-(END /!----‘G +( + 7-- +( +BEGIN :°4'----- +G +UU -----BEGIN :°4'/---- +-----BEIN :°4'----- +G +UU-- +--BEGIN :°4'----- +G +UU -----BEGIN 2°4'/---- +-----BEGIN :°4'----- +G +UU QG +wFUG + fbwFUU QG +wFU QG +wFUG + fbwFUU QG +wFU fbwFUUU G +bwFU f +bwFU U f fbwFUU f +bwFU U fbU fbwF fUG + fbwFU f fTwFTU fbwFUfbwFUU f +bwFU U fbwFUUí‘;!(;)š-----EN ç/O!:š--- +---BE- NI-GO--- +---* + f +bwFU U fbU fbw-----BEG-F fU \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/7b8e2a5dfa03cc13b70eb5f77d61222c108ab6bd b/external/boringssl/fuzz/read_pem_corpus/7b8e2a5dfa03cc13b70eb5f77d61222c108ab6bd new file mode 100644 index 0000000000..7e27d28435 Binary files /dev/null and b/external/boringssl/fuzz/read_pem_corpus/7b8e2a5dfa03cc13b70eb5f77d61222c108ab6bd differ diff --git a/external/boringssl/fuzz/read_pem_corpus/824b6dd27deb9ed157fdc80485f104268f7232fe b/external/boringssl/fuzz/read_pem_corpus/824b6dd27deb9ed157fdc80485f104268f7232fe new file mode 100644 index 0000000000..7a8b3f8816 Binary files /dev/null and b/external/boringssl/fuzz/read_pem_corpus/824b6dd27deb9ed157fdc80485f104268f7232fe differ diff --git a/external/boringssl/fuzz/read_pem_corpus/825edbf21bc40ec23225772635ea6390e6d9fb4c b/external/boringssl/fuzz/read_pem_corpus/825edbf21bc40ec23225772635ea6390e6d9fb4c new file mode 100644 index 0000000000..a92ec4f430 --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/825edbf21bc40ec23225772635ea6390e6d9fb4c @@ -0,0 +1,3 @@ +-----BEGIN --+ô---'---+ô------/ + +èè \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/8347c4366b5d668b467fb589c3090f201eacb5db b/external/boringssl/fuzz/read_pem_corpus/8347c4366b5d668b467fb589c3090f201eacb5db new file mode 100644 index 0000000000..a0629275d4 Binary files /dev/null and b/external/boringssl/fuzz/read_pem_corpus/8347c4366b5d668b467fb589c3090f201eacb5db differ diff --git a/external/boringssl/fuzz/read_pem_corpus/874ed5d633d245b10fdda52c49627b43b3f2e25b b/external/boringssl/fuzz/read_pem_corpus/874ed5d633d245b10fdda52c49627b43b3f2e25b new file mode 100644 index 0000000000..a11db388ac --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/874ed5d633d245b10fdda52c49627b43b3f2e25b @@ -0,0 +1,14 @@ +-----BEGIN :T!(!*!*z:'*ô:èÍ°:!m®*ÍÕOÇ*Ä;ò¹:) +OÇ*Ä;ò¹:) + :(ç/!;!;‘7í();':[´'H 'G)MG¿Ñ'ëyO )o(*(Ç*Ä-------END ò¹:) +-----BEGIN¬OÇ*Ä;ò¹:) + + + :(ç/!;!;‘OÇ*Ä;ò¹:) +-----BEGIN :(ç/!;!;‘6í();':[´'H('G)MG¿Ñ'ë˜yO )(*(Ç*Ä----- +¬ÙOÇ*Ä;ò¹:) + +----BEGIN O!:š'U('ß((ç/!;!;‘6í();'8(´'H('1)M˜G¿ëÑ'OÇ!*Ä;ò¹:) +:(ç-/!;!;‘6í();':(´'H('G)M˜G¿ëÑ'yO-----BEGIN----:Œ:(OÇ*Ä;ò¹:) +;(j-7í();';[´'H('Gç/!;!;‘6í();':(';±)MG¿Ñ'ë˜yO )o(*(Ç*Ä----- +Ù-----END OÇ*;;)''D;Û…:f(;w:;Å;ì*ÆHŒ--- \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/88581ebac8ffbea71bb83f704e14d789dbc33f37 b/external/boringssl/fuzz/read_pem_corpus/88581ebac8ffbea71bb83f704e14d789dbc33f37 new file mode 100644 index 0000000000..66f9ba8255 --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/88581ebac8ffbea71bb83f704e14d789dbc33f37 @@ -0,0 +1,17 @@ +-----BEGIN O----- +----(END /!----‘6í( + 7í‘;!(;)š-----END ç/O!:š--- +---BEGIN O----- +----(END /!---'U('ß(:(ç!/;!;‘6í();':(´'H('G)M˜G¿ëÑ'yO- + )o(*(Ç*Ä;ò¹:)·¬Ù*ª:!- +:(';±×'Ú(;—é)- +Ð(!:™)¢í:”"P•Z ˆg:; :':Â:0!)÷ö)v*Ǿ:--BEGIN 6í‘;!(;)š-- +----END ç/!----- +- +kqU;!:Oš'U|:ØŽ8*:;sá(f!‘;;)--*---- +----BEGIN ‘O----- +----(END /!-----BEGIN 6í +j- +‘;!(;)š-- +----EN- +6çí( \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/892155ce92d4c3293f48e6fc2097336ba882a0ad b/external/boringssl/fuzz/read_pem_corpus/892155ce92d4c3293f48e6fc2097336ba882a0ad new file mode 100644 index 0000000000..fa326656de --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/892155ce92d4c3293f48e6fc2097336ba882a0ad @@ -0,0 +1,8 @@ +-:($X: +m---BEGIN è)a'‡:':!;'R):u ;:rM'**;)¡=*ë;Ì:)O(hõ!;Ãú:;'Âþ*0'!:;:Ë((:;*()'(!E(:*t;;::;:!:('à'`'O:!*Ú:‰(&((')V`;'m\:!(@!(*:']A …*:Ìùa!*ì)(ç(;!2')þ:ã::)**g*!rŠßÜ;S()ï(;(±¤*(;)*ã:(;c(!)!'òÊ:Ñè)a'‡:':!;'R):u ;:rM'**;)¡=*ë;ÄÍ:¦“:5;ˆ*j•(¯Å'Š;*»(X) -x +-----BEGIN )'*;´'þƒÛ))¼€!':----- + 8x +x + = +-----END )'*;´'þƒÛ))¼€!':----- +---BEGIN è)a'‡:':!;'R):u ;:rM'**;)¡=*ë;Ì:)O(hõ!;Ãú:;'Âþ*0'!:Ë(:;:;(*()'(!E(:*t;;::;:!:('à'`'O:!*Ú:‰(&((')V`;'m\:!(@!(*:']A …*:Ìùa!*ì)(ç(;!0')þ:ã*::)*g*!rŠßÜ;S()ï( \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/894e092b7fd9f4e0a5911ca106e097d3833d3491 b/external/boringssl/fuzz/read_pem_corpus/894e092b7fd9f4e0a5911ca106e097d3833d3491 new file mode 100644 index 0000000000..3c9e422ec7 --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/894e092b7fd9f4e0a5911ca106e097d3833d3491 @@ -0,0 +1,3 @@ +Nh'ñÍ):!X;‚*:¹):–;üµû!¨)l;'O2)+'*:†):($X: +-----BEGIN !•*!ø²((4!èΰô)Ï«(œ(«D­:¼(!(ºW;:w:¯*S;((':â*:((`²:(6 !; *(:'3@¶;2!ü(J¹×`!Ÿ:¸õ¶(() )­'9:(Bþ)J ñm!åY(!;)T!);*P)Nh'ñÍ):!X;‚*:¹):–;üµû!¨)l;'O2Nh'ñÍ):!X;‚*:¹)k*!Œ*DÕ'žaÐ[!ʬ*#'&:–;üµû!¨)l;)+*Å;öNh'ñ'*:†):($X: +-----BEGIN !•*!'O2)+'*:†)ø² \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/8c07d6299f33fee89ab0c82e92e06cd558ade60f b/external/boringssl/fuzz/read_pem_corpus/8c07d6299f33fee89ab0c82e92e06cd558ade60f new file mode 100644 index 0000000000..1322c288dd --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/8c07d6299f33fee89ab0c82e92e06cd558ade60f @@ -0,0 +1,14 @@ +-----BEGIN :T!(!*!*z:'*ô:èÍ°:!m®*ÍÕOÇ*Ä;ò¹:) +OÇ*Ä;ò¹:) + :(ç/!;!;‘7í();':[´'H 'G)MG¿Ñ'ëyO )o(*(Ç*Ä-------END ò¹:) +-----BEGIN¬OÇ*Ä;ò¹:) + + + :(ç/!;!;‘OÇ*Ä;ò¹:) +-----BEGIN :(ç/!;!;‘6í();':[´'H('G)MG¿Ñ'ë˜yO )(*(Ç*Ä----- +¬ÙOÇ*Ä;ò¹:) + +----BEGIN O!:š'U('ß((ç/!;!;‘6í();'8(´'H('1)M˜G¿ëÑ'OÇ!*Ä;ò¹:) +:(ç-/!;!;‘6í();':(´'H('G)M˜G¿ëÑ'yO-----BEGIN----:Œ:(OÇ*Ä;ò¹:) +;(j-7í();';[´'H('Gç/!;!;‘6í();':(;±)MG¿Ñ'ë˜yO )o(*(Ç*Ä----- +Ù-----END OÇ*;;)''D;Û…:f(;w:;Å \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/8e07fb01e0cfa23caddb6b0280c03d0ae2bac57e b/external/boringssl/fuzz/read_pem_corpus/8e07fb01e0cfa23caddb6b0280c03d0ae2bac57e new file mode 100644 index 0000000000..715ec1ccbf Binary files /dev/null and b/external/boringssl/fuzz/read_pem_corpus/8e07fb01e0cfa23caddb6b0280c03d0ae2bac57e differ diff --git a/external/boringssl/fuzz/read_pem_corpus/92207925db84106af0167e887696d936aa41e785 b/external/boringssl/fuzz/read_pem_corpus/92207925db84106af0167e887696d936aa41e785 new file mode 100644 index 0000000000..e5afad418d --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/92207925db84106af0167e887696d936aa41e785 @@ -0,0 +1,5 @@ +-----BEGIN O----- +----(END /!-----BEGI 6í‘;!(;)š-----END ç/!--- + + +‘6í( \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/94514c5c092afe2f8295dc193d506f16c6ea82c1 b/external/boringssl/fuzz/read_pem_corpus/94514c5c092afe2f8295dc193d506f16c6ea82c1 new file mode 100644 index 0000000000..66aec936f4 Binary files /dev/null and b/external/boringssl/fuzz/read_pem_corpus/94514c5c092afe2f8295dc193d506f16c6ea82c1 differ diff --git a/external/boringssl/fuzz/read_pem_corpus/956c8cf1db9220ac8004eb9a75e3ebc1df33a33f b/external/boringssl/fuzz/read_pem_corpus/956c8cf1db9220ac8004eb9a75e3ebc1df33a33f new file mode 100644 index 0000000000..eb4f595171 Binary files /dev/null and b/external/boringssl/fuzz/read_pem_corpus/956c8cf1db9220ac8004eb9a75e3ebc1df33a33f differ diff --git a/external/boringssl/fuzz/read_pem_corpus/97c5565f723c0e49787fdec9ed15354760fcb1e6 b/external/boringssl/fuzz/read_pem_corpus/97c5565f723c0e49787fdec9ed15354760fcb1e6 new file mode 100644 index 0000000000..eabac816f9 Binary files /dev/null and b/external/boringssl/fuzz/read_pem_corpus/97c5565f723c0e49787fdec9ed15354760fcb1e6 differ diff --git a/external/boringssl/fuzz/read_pem_corpus/9832fea1fe1c8b575790f59f98404fb61672a3f3 b/external/boringssl/fuzz/read_pem_corpus/9832fea1fe1c8b575790f59f98404fb61672a3f3 new file mode 100644 index 0000000000..033a272388 --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/9832fea1fe1c8b575790f59f98404fb61672a3f3 @@ -0,0 +1,5 @@ +-----BEGIN O----- +----(END /!-----BE-----END GI 6í‘;!(;)š-----END ç/!--- + +- +‘6ôí( \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/9940bd2f440a8c1e07dba6476c219349afeae711 b/external/boringssl/fuzz/read_pem_corpus/9940bd2f440a8c1e07dba6476c219349afeae711 new file mode 100644 index 0000000000..009adb9feb --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/9940bd2f440a8c1e07dba6476c219349afeae711 @@ -0,0 +1,12 @@ +-----BEGIN O----- +----(END /!-----BEGI 7í‘;!(;)š-----END ç/O!:š--- +---BEGIN O----- +----(END /!---'U('ß(:(ç!/;!;‘6í();':(´'H('G)M˜G¿ëÑ'yO- + )o(*(Ç*Ä;ò¹:)·¬Ù*ª:!:Œ:(';±×'Ú(;—é)Ð(!:™)¢í:”"P•Z ˆg;:; :':Â:7!)÷ö)vôǾ:--BEGIN 6í‘;!(;)š-- +----END ç/!----- +- +kqU;O!:š'U|:ØŽ8*:;sá(f!‘;;)--*---- +----BEGIN ‘O----- +----(END /!-----BEGIN 6í +j- +‘;!(;)š-----END 6çí( \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/9d1e6ed2fc4b095a2ccb4e695241c91d4b194be5 b/external/boringssl/fuzz/read_pem_corpus/9d1e6ed2fc4b095a2ccb4e695241c91d4b194be5 new file mode 100644 index 0000000000..44917bba48 Binary files /dev/null and b/external/boringssl/fuzz/read_pem_corpus/9d1e6ed2fc4b095a2ccb4e695241c91d4b194be5 differ diff --git a/external/boringssl/fuzz/read_pem_corpus/a2bc14d4be3bb4f4deb93ddaa77224db305158af b/external/boringssl/fuzz/read_pem_corpus/a2bc14d4be3bb4f4deb93ddaa77224db305158af new file mode 100644 index 0000000000..e0e223d069 Binary files /dev/null and b/external/boringssl/fuzz/read_pem_corpus/a2bc14d4be3bb4f4deb93ddaa77224db305158af differ diff --git a/external/boringssl/fuzz/read_pem_corpus/a75abe0b4dd03dc232f9192666d6adb369beffca b/external/boringssl/fuzz/read_pem_corpus/a75abe0b4dd03dc232f9192666d6adb369beffca new file mode 100644 index 0000000000..d10f2f60f2 --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/a75abe0b4dd03dc232f9192666d6adb369beffca @@ -0,0 +1,5 @@ +-----vBEGIN --+ô---'---+ô------/ + +è-----BEGIN --+ô---'---+ô-----è-- + +èè \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/a92c58dfadb8195fbd90c70b4dc576986dbb7c46 b/external/boringssl/fuzz/read_pem_corpus/a92c58dfadb8195fbd90c70b4dc576986dbb7c46 new file mode 100644 index 0000000000..23a5038790 Binary files /dev/null and b/external/boringssl/fuzz/read_pem_corpus/a92c58dfadb8195fbd90c70b4dc576986dbb7c46 differ diff --git a/external/boringssl/fuzz/read_pem_corpus/aa82ef4cf1c3c2d7dd7811803227cc87d2429b3c b/external/boringssl/fuzz/read_pem_corpus/aa82ef4cf1c3c2d7dd7811803227cc87d2429b3c new file mode 100644 index 0000000000..d84db471e7 Binary files /dev/null and b/external/boringssl/fuzz/read_pem_corpus/aa82ef4cf1c3c2d7dd7811803227cc87d2429b3c differ diff --git a/external/boringssl/fuzz/read_pem_corpus/ad49ff8fb9ff95a8f110b15702f8209df64f8fad b/external/boringssl/fuzz/read_pem_corpus/ad49ff8fb9ff95a8f110b15702f8209df64f8fad new file mode 100644 index 0000000000..99dd9ff640 --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/ad49ff8fb9ff95a8f110b15702f8209df64f8fad @@ -0,0 +1,14 @@ +-----BEGIN O----- +----(END /!-----BEGI 7í‘;!(;)š-----END ç/O!:š--- +-----END O-=--- +----(END /!---'U('ß(:(ç!/;!;‘6í();':(´'H('G)M˜G¿ëÑ'yO- + )o(*(Ç*Ä;ò¹:)·¬Ù*ª:!- +:(';±×'Ú(;—é)- +Ð(!:™)¢í:”"P•Z ˆg;:; :':Â:7!)÷ö)v*Ǿ:--BEGIN 6í‘;!(;)š-- +----END ç/!----- +- +kqU;!:Oš'U|:ØŽ9*:;sá(f!‘;;)------ +----BEGIN ‘O----- +----(END /!-----BEGIN 6í +j- +‘;!(;)š-----END 6çí( \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/af9207c320f7400ba18dea62fd4af98330ba260b b/external/boringssl/fuzz/read_pem_corpus/af9207c320f7400ba18dea62fd4af98330ba260b new file mode 100644 index 0000000000..45332baf9e --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/af9207c320f7400ba18dea62fd4af98330ba260b @@ -0,0 +1,3 @@ +-----BEGIN x:€**”Á*Ñ**f(À~'!5 ) );á'*EÆþ-----B----- +-----END f(À~'!5 ) C;á'*EÆ;Ÿ:;h0G;G´('!Í*l*)!:!:;'4¿®ÆC*Öˆ3Ÿ:)((#('²:¡('î'uÂ*!!x +;›!;) \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/b034864020154378b78a11122c8f61f81e8009ce b/external/boringssl/fuzz/read_pem_corpus/b034864020154378b78a11122c8f61f81e8009ce new file mode 100644 index 0000000000..eb2588976d Binary files /dev/null and b/external/boringssl/fuzz/read_pem_corpus/b034864020154378b78a11122c8f61f81e8009ce differ diff --git a/external/boringssl/fuzz/read_pem_corpus/b178eadb35af688d045ba6bc400396ae0fc7c9b9 b/external/boringssl/fuzz/read_pem_corpus/b178eadb35af688d045ba6bc400396ae0fc7c9b9 new file mode 100644 index 0000000000..b66e0af33a --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/b178eadb35af688d045ba6bc400396ae0fc7c9b9 @@ -0,0 +1,6 @@ +-----BEGIN O!:š'U('ß((ç/!;!;‘O!:š'U('ß((ç/!;!;‘3í();':(´'H('G)M˜G¿ëÑ'yO )O(*---ç-- +-----BEGIN :(*ª:!:ŒO!OÇ*Ä;ò¹:) +-----BEGIN :(ç/!;!;‘6í();':[´'H('G)MG¿Ñ'ë˜yO )o(*(Ç*Ä----- +¬Ù*ª:!------ +----BEIN Ç*Ä;ò¹:) +N O!:š'U('ß((ç!;!;‘6í();':(´'H(%G)M˜G¿ëÑ'yO :)o(*(Ç*Ä;ò¹:)·:š'U('¬ÙO!:š'U(*ª:!:Œ:(';±×'Ú(;'ß(:(ç/—é)Ð(!;!;ß(:(ç/!;!;‘6í‘();-6í();O!-: \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/b709f3412c5fb9a0b38a69eee59620a5c3990385 b/external/boringssl/fuzz/read_pem_corpus/b709f3412c5fb9a0b38a69eee59620a5c3990385 new file mode 100644 index 0000000000..6c2f8068b8 --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/b709f3412c5fb9a0b38a69eee59620a5c3990385 @@ -0,0 +1,8 @@ +-:($X: +----BEGIN è)a'‡:':!;'R):u ;:rM'**;)¡=*ë;Ì:)O(hõ!;Ãú:;'Âþ*0'!:;:Ë((:;*()'(!E(:*t;;::;:!:('à'`'O:!*Ú:‰(&((')V`;'m\:!(@!(*:']A …*:Ìùa!*ì)(ç(;!2')þ:ã::)**g*!rŠßÜ;S()ï(;(±¤*(;)*ã:(;c(!)!'òÊ:Ñè)a'‡:':!;'R):u ;:rM'**;)¡=*ë;ÄÌ:¦“:5;€*j•(¯Å'Š;*»(X) -x +-----BEGIN )'*;´'þƒÛ))¼€!':----- + x +x + x +-----END )'*;´'þƒÛ))¼€!':----- +---BEGIN è)a'‡:':!;'R):u ;:rM'**;)¡=*ë;Ì:)O(hõ!;Ãú:;'Âþ*0'!:Ë(:;(:;*()'(!E(:*t;;::;:!:('à'`'O:!*Ú:‰(&((')V`;'m\:!(@!(*:']A …*:Ìùa!*ì)(ç(;!0')þ:ã*::)*g*!rŠßÜ;S()ï( \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/b92f0f72b6839f6c7ac10f4c663765b89e1fa513 b/external/boringssl/fuzz/read_pem_corpus/b92f0f72b6839f6c7ac10f4c663765b89e1fa513 new file mode 100644 index 0000000000..5393ba082b --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/b92f0f72b6839f6c7ac10f4c663765b89e1fa513 @@ -0,0 +1,2 @@ +-----BEGIN O----- +'U('ß(:(ç/!-----BEGIN 6í‘;!(;)š'U('ß(:(ç/!;!;;':(´‘6í( \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/bc205ed015bb01de66b5a6b5a631d167c8077a5c b/external/boringssl/fuzz/read_pem_corpus/bc205ed015bb01de66b5a6b5a631d167c8077a5c new file mode 100644 index 0000000000..0fa1d3d735 Binary files /dev/null and b/external/boringssl/fuzz/read_pem_corpus/bc205ed015bb01de66b5a6b5a631d167c8077a5c differ diff --git a/external/boringssl/fuzz/read_pem_corpus/c0348b5dd7aaf73888372a5a6abef82bd0df97b9 b/external/boringssl/fuzz/read_pem_corpus/c0348b5dd7aaf73888372a5a6abef82bd0df97b9 new file mode 100644 index 0000000000..4471d0e6fb --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/c0348b5dd7aaf73888372a5a6abef82bd0df97b9 @@ -0,0 +1,18 @@ +-----BEGIN O----- +----(END /!-- +---‘6í( + 7í‘;!(;)š-----END ç/O!:š--- +---BEGIN O----- +----(END /!---'U('ß(:(ç!/;!;‘6í();':(´'H('G)M˜G¿ëÑ'yO- + )o(*(Ç*Ä;ò¹:)·¬Ù*ª:!- +:(';±×'Ú(;—é)- +Ð(!:™)¢í:”"P•Z ˆg:; :':Â:0!)÷ö)v*Ǿ:--BEGIN 6í‘;!(;)š-- +----END ç/!----- +- +kqU;!:Oš'U|:ØŽ8*:;sá(f!‘;;)--*---- +----BEGIN ‘O----- +----(END /!-----BEGIN 6í +j- +‘;!(;)š-- +----EN- +6çí( \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/c0596e573f43d2bd5a5d038bf4bd7d073141ddf0 b/external/boringssl/fuzz/read_pem_corpus/c0596e573f43d2bd5a5d038bf4bd7d073141ddf0 new file mode 100644 index 0000000000..1588358370 --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/c0596e573f43d2bd5a5d038bf4bd7d073141ddf0 @@ -0,0 +1,16 @@ +------ +----- +----BEGIN ‘6í( + +----N!(ED /-----BEGI 6í‘;!(;)š--'-8-END ç- +---BEGIN O----- +----(END--=--END -----BEGIN O----- +----(END /!-----BEGIN 6í‘;!(;)š-----END ç//!-----!;BE-----END GI 5í‘;!(;)š-----END ç/!--- + +- +‘6í/!--!----- +‘6í(- + +- +‘6ôí((- + \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/c45f49452fcdf531f2bcfd100645c535e5b71205 b/external/boringssl/fuzz/read_pem_corpus/c45f49452fcdf531f2bcfd100645c535e5b71205 new file mode 100644 index 0000000000..887d05d15c --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/c45f49452fcdf531f2bcfd100645c535e5b71205 @@ -0,0 +1 @@ +Oô \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/c504659b0454be5eef0594da6a952f8daf347929 b/external/boringssl/fuzz/read_pem_corpus/c504659b0454be5eef0594da6a952f8daf347929 new file mode 100644 index 0000000000..e5a9f0514e --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/c504659b0454be5eef0594da6a952f8daf347929 @@ -0,0 +1 @@ +-----B-EGIN f( \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/c7e4b7f4c3bbc7c6ed4e3366d1d4c16ed44952f1 b/external/boringssl/fuzz/read_pem_corpus/c7e4b7f4c3bbc7c6ed4e3366d1d4c16ed44952f1 new file mode 100644 index 0000000000..4b26afa737 Binary files /dev/null and b/external/boringssl/fuzz/read_pem_corpus/c7e4b7f4c3bbc7c6ed4e3366d1d4c16ed44952f1 differ diff --git a/external/boringssl/fuzz/read_pem_corpus/caf489bb8f6f48e35b95032b2824ca0ffc77d26a b/external/boringssl/fuzz/read_pem_corpus/caf489bb8f6f48e35b95032b2824ca0ffc77d26a new file mode 100644 index 0000000000..b30a845eb6 Binary files /dev/null and b/external/boringssl/fuzz/read_pem_corpus/caf489bb8f6f48e35b95032b2824ca0ffc77d26a differ diff --git a/external/boringssl/fuzz/read_pem_corpus/cc8ceeebb230ca237479e0c3dacafbb5524222e1 b/external/boringssl/fuzz/read_pem_corpus/cc8ceeebb230ca237479e0c3dacafbb5524222e1 new file mode 100644 index 0000000000..fe47159b6a --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/cc8ceeebb230ca237479e0c3dacafbb5524222e1 @@ -0,0 +1,20 @@ +-‘6í( + +----- +----BEGI) ‘6í( + +----N!(ED /-----BEGI 6í‘;!(;)š--'-8-END ç-‰ +---BEGIN O----- +----(END--=--END -----BEGIN O----- +----(END /!---GB-E-IN 3í‘;!(;)š-----END ç//!-----!;BE-----END GI 5í‘;!(;)š-----END ç----------BEGIN O---------BEGIN O----- +---- +'U('ß(:(ç +/!--- + +- +‘7í/!--!----- +‘6/!---O!:š'U('í(- + +ß(:(ç/!;!;‘6í();':(´- +‘6ôí((- +'H'G)M˜G¿ëÑ'yO )o(*(Ç*Ä;ò¹:)·¬Ù*ª;!:Œ:(';±×'Ú(; —é)Ð(!:™)¢í:”"P•Z ˆw;:P; :':Â:7!)÷ö)vôǾ:kqU;|:Ø8*a;sá(f! \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/cf1b3d1ed204deed6c62f41d0e706ee47bc802e0 b/external/boringssl/fuzz/read_pem_corpus/cf1b3d1ed204deed6c62f41d0e706ee47bc802e0 new file mode 100644 index 0000000000..b7c794bef2 --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/cf1b3d1ed204deed6c62f41d0e706ee47bc802e0 @@ -0,0 +1,7 @@ +OÇ*Ä;ò¹:) +-----BEGIN :(ç/!;!;‘6í();':[´'H('G)MG¿Ñ'ë˜yO )o(*(Ç*Ä----- +¬ÙOÇ*Ä;ò¹:) + +----BEGIN O!:š'U('ß((ç/!;!;‘6í();'8(´'H('G)M˜G¿ëÑ'OÇ!*Ä;ò¹:) +:(ç-/!;!;‘6í();':(´'H('G)M˜G¿ëÑ'yO-----BEGIN----:Œ:(OÇ*Ä;ò¹:) +;(j-ç/!;!;‘6í();':(';±× \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/cfc3b1348ca73b8c02d9aed715d1e0681326888c b/external/boringssl/fuzz/read_pem_corpus/cfc3b1348ca73b8c02d9aed715d1e0681326888c new file mode 100644 index 0000000000..f994166032 --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/cfc3b1348ca73b8c02d9aed715d1e0681326888c @@ -0,0 +1 @@ +O!:š'U('ß((ç/!;!;‘6í();'8(´'H('G)M˜G¿ëÑ'yO )o(*(Ç*Ä;òO!:š'U('ß((ç/!;!;‘6í();'8(´'H('G)M˜G¿ëÑ'yO )o¹:)·¬ÙO!:š'U(*ª:!:Œ:(';±×'Ú(;'ß(:(ç/)é)Ð(-----BEGIN (ç/!;!;‘6í();':(´'!;!;H('G)M˜G¿ëÑ'yO*o( )(Ç*Ä;ò¹:()·¬Ù*ª*(Ç*Ä;ò¹:)·¬ÙO!:š'U(*ª:!:Œ:(';±×'Ú(;'ß(:(ç:!:Œ:(';±×'Ú/)é)Ð(-----BEGIN (ç/!;!;‘6í();':(´'!;!;H('G)M˜G(‘6;—é)Ð(!:™)¢í:”¿ëÑ'yO*o( )(Ç*Ä;ò¹:)·¬Ù*ª:!:Œ:(';±×'Ú(‘6;—é)Ð(!:™)¢í:”"P•Z ˆw;:P; :':Â:7!)÷ö)vôǾ:kqU;|:ØŽ8"P•Z ˆw;:P; :'*:;sá(f!‘;;)j:Â*:::7!)÷ö)vôǾ:kqU;|:ØŽ8*:;sá(f!‘; \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/d4f0a19ece82b78c82c81eae5b49dc662c6f4a89 b/external/boringssl/fuzz/read_pem_corpus/d4f0a19ece82b78c82c81eae5b49dc662c6f4a89 new file mode 100644 index 0000000000..cc15e7f405 Binary files /dev/null and b/external/boringssl/fuzz/read_pem_corpus/d4f0a19ece82b78c82c81eae5b49dc662c6f4a89 differ diff --git a/external/boringssl/fuzz/read_pem_corpus/d959c647c6a5ea641fec147b0de36187a9d2f8c5 b/external/boringssl/fuzz/read_pem_corpus/d959c647c6a5ea641fec147b0de36187a9d2f8c5 new file mode 100644 index 0000000000..cae86a1d87 Binary files /dev/null and b/external/boringssl/fuzz/read_pem_corpus/d959c647c6a5ea641fec147b0de36187a9d2f8c5 differ diff --git a/external/boringssl/fuzz/read_pem_corpus/de2fb44503aca3f82d5466a9489c0735324b214d b/external/boringssl/fuzz/read_pem_corpus/de2fb44503aca3f82d5466a9489c0735324b214d new file mode 100644 index 0000000000..10df3f6206 Binary files /dev/null and b/external/boringssl/fuzz/read_pem_corpus/de2fb44503aca3f82d5466a9489c0735324b214d differ diff --git a/external/boringssl/fuzz/read_pem_corpus/df9fe7d51a89ee267034a2834025f71505d4a421 b/external/boringssl/fuzz/read_pem_corpus/df9fe7d51a89ee267034a2834025f71505d4a421 new file mode 100644 index 0000000000..f5951adb1d --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/df9fe7d51a89ee267034a2834025f71505d4a421 @@ -0,0 +1,7 @@ +-----BEGIN è)a':‡':!;'R):u ;:rM----- +--* +(!Ìùa!*ì)(ç-)--BEGIN N è)a'‡:':--* +* +(!Ìùa!*ì)(ç-)--BEGIN N è)!;'* +---BEGIN è)a'‡:':!;'R):u::rR)M'è)a'‡:':!a'‡:':--!;'* +---BEGIN è)a'‡:':!;'R):u::rR)M'è)a'‡:':!;'R):u ;;'R):u:rM' *;:rM'* \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/e1a6c4096b145ced5362ede6ffedbc49d16ba57e b/external/boringssl/fuzz/read_pem_corpus/e1a6c4096b145ced5362ede6ffedbc49d16ba57e new file mode 100644 index 0000000000..2afaa7cef3 --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/e1a6c4096b145ced5362ede6ffedbc49d16ba57e @@ -0,0 +1,4 @@ +-----BEGIN O----- +----(END /!-----BEGIN 6í‘;!(;)š-----END ç/!----- +- +‘6í( \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/e207960b1761ba95e7544b9d924459c56e2c4695 b/external/boringssl/fuzz/read_pem_corpus/e207960b1761ba95e7544b9d924459c56e2c4695 new file mode 100644 index 0000000000..f45de5f651 Binary files /dev/null and b/external/boringssl/fuzz/read_pem_corpus/e207960b1761ba95e7544b9d924459c56e2c4695 differ diff --git a/external/boringssl/fuzz/read_pem_corpus/e3344ef8d734471ef90b16c719cb0f11af2ce743 b/external/boringssl/fuzz/read_pem_corpus/e3344ef8d734471ef90b16c719cb0f11af2ce743 new file mode 100644 index 0000000000..4e5586e5cf --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/e3344ef8d734471ef90b16c719cb0f11af2ce743 @@ -0,0 +1,3 @@ +-----BEGIN è)a':‡':!;'R):u ;:rM----- +--* +(!Ìùa!*ì)(ç-)--BEGIN N è)--a \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/e45a6df435a1cecae6547f6dcde626a7e706434c b/external/boringssl/fuzz/read_pem_corpus/e45a6df435a1cecae6547f6dcde626a7e706434c new file mode 100644 index 0000000000..349cbf1933 --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/e45a6df435a1cecae6547f6dcde626a7e706434c @@ -0,0 +1,8 @@ +-:($X: +----BEGIN è)a'‡:':!;'R):u ;:rM'**;)¡=*ë;Ì:)O(hõ!;Ãú:;'Âþ*0'!:;:Ë((:;*()'(!E(:*t;;::;:!:('à'`'O:!*Ú:‰(&((')V`;'m\:!(@!(*:']A …*:Ìùa!*ì)(ç(;!2')þ:ã::)**g*!rŠßÜ;S()ï(;(±¤*(;)*ã:(;c(!)!'òÊ:Ñè)a'‡:':!;'R):u ;:rM'**;)¡=*ë;ÄÍ:¦“:5;ˆ*j•(¯Å'Š;*»(X) -x +-----BEGIN )'*;´'þƒÛ))¼€!':----- + 8x +x + x +-----END )'*;´'þƒÛ))¼€!':----- +---BEGIN è)a'‡:':!;'R):u ;:rM'**;)¡=*ë;Ì:)O(hõ!;Ãú:;'Âþ*0'!:Ë(:;(:;*()'(!E(:*t;;::;:!:('à'`'O:!*Ú:‰(&((')V`;'m\:!(@!(*:']A …*:Ìùa!*ì)(ç(;!0')þ:ã*::)*g*!rŠßÜ;S()ï( \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/e7ef91e03a3aa8bd53b2466a2207a5028185678f b/external/boringssl/fuzz/read_pem_corpus/e7ef91e03a3aa8bd53b2466a2207a5028185678f new file mode 100644 index 0000000000..7885083307 Binary files /dev/null and b/external/boringssl/fuzz/read_pem_corpus/e7ef91e03a3aa8bd53b2466a2207a5028185678f differ diff --git a/external/boringssl/fuzz/read_pem_corpus/ebcae74985ccc7905a3800c0db2723392cfd2f2c b/external/boringssl/fuzz/read_pem_corpus/ebcae74985ccc7905a3800c0db2723392cfd2f2c new file mode 100644 index 0000000000..dc16e558f8 Binary files /dev/null and b/external/boringssl/fuzz/read_pem_corpus/ebcae74985ccc7905a3800c0db2723392cfd2f2c differ diff --git a/external/boringssl/fuzz/read_pem_corpus/ed31baee70d3b705762e808e494b4debf604c5fb b/external/boringssl/fuzz/read_pem_corpus/ed31baee70d3b705762e808e494b4debf604c5fb new file mode 100644 index 0000000000..0a71a8eac9 --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/ed31baee70d3b705762e808e494b4debf604c5fb @@ -0,0 +1,31 @@ +-----BEGIN O----- +----(END /!----‘G +( + 7-- +--BEGIN :°4'----- +G +UU -----BEGIN :°4'/---- +-----BEIN :°4'----- +G +UU-- +--BEGIN :°4'----- +G +UU -----BEGIN 2°4'/---- +-----BEGIN :°4'----- +G +UU QG +wFUG + fbwFUU QG +wFU QG +wFUG + fbwFUU QG +wFU fbwFUUU G +bwFU f +bwFU U fbwFUU f +bwFU U fbU fbwF fUG + fbwFU f fTwFTU fbwFUfbwFUU f +bwFU U fbwFUUí‘;!(;)š-----EN ç/O!:š--- +---BE- NI-GO--- +---* + f +bwFU U fbU fbw-----BEG-F fU \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/ee06965764fdf6769657e744a61efe7d60d085fb b/external/boringssl/fuzz/read_pem_corpus/ee06965764fdf6769657e744a61efe7d60d085fb new file mode 100644 index 0000000000..cc7aeba88b --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/ee06965764fdf6769657e744a61efe7d60d085fb @@ -0,0 +1 @@ +Oô! \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/f123c08d0a46b72fa8989296e82e7aa25ebf16f8 b/external/boringssl/fuzz/read_pem_corpus/f123c08d0a46b72fa8989296e82e7aa25ebf16f8 new file mode 100644 index 0000000000..e530a1278e --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/f123c08d0a46b72fa8989296e82e7aa25ebf16f8 @@ -0,0 +1,7 @@ +-----BEGIN --+ô---'-----vBEGIN --+ô---'---+ô------/ + +è-----+ô---------BEGIN --+ô---'---- + +è+ô-----è-è- + +èè \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/f18ebc593b87baa03b5e003b7540577001ba6aca b/external/boringssl/fuzz/read_pem_corpus/f18ebc593b87baa03b5e003b7540577001ba6aca new file mode 100644 index 0000000000..fe29dff66c Binary files /dev/null and b/external/boringssl/fuzz/read_pem_corpus/f18ebc593b87baa03b5e003b7540577001ba6aca differ diff --git a/external/boringssl/fuzz/read_pem_corpus/f1903c6e205ba7b902e53b07e08890ec8179cbd5 b/external/boringssl/fuzz/read_pem_corpus/f1903c6e205ba7b902e53b07e08890ec8179cbd5 new file mode 100644 index 0000000000..628e26765e --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/f1903c6e205ba7b902e53b07e08890ec8179cbd5 @@ -0,0 +1 @@ +'*:èÍ'*ô:è-'----BEGIN*ô:èÍ'*ô: è \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/f3f2959361766dbfafbb2f99a4f60c920001386e b/external/boringssl/fuzz/read_pem_corpus/f3f2959361766dbfafbb2f99a4f60c920001386e new file mode 100644 index 0000000000..47ebb5b436 --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/f3f2959361766dbfafbb2f99a4f60c920001386e @@ -0,0 +1,6 @@ +------ +----BEGIN O--------- +----BEGIN O----- +----(END /!-----BEGIN 6í‘;!(;)š------- +--END --(END /!-----BEGIN 6í‘;!(;)š--ç/!----- +-- \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/f72115838630c70a067e89b98615357fcf19d058 b/external/boringssl/fuzz/read_pem_corpus/f72115838630c70a067e89b98615357fcf19d058 new file mode 100644 index 0000000000..ce9b7f8e67 --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/f72115838630c70a067e89b98615357fcf19d058 @@ -0,0 +1,45 @@ +-----BEGIN O----- +-( +-(END /!----‘G +( + (-- +( +BEGIN :°4'----- +G +UU -----BEGIN :°4'/---- +-----BEIN :°4'----- +G +UU-- +--BEGIN :°4'G +----- +G +UU -----BEGIN 2°4'/---- +-----BEGIN :°4'----- +G +UU-----BEGIN O----- +-( +-(END /!----‘G +( + (-- +( +BEGIN :°4'----- +G +UU -----BEGIN :°4'/---- +-----BEIN QG +wF:°4'----- +G +UU-- +--BEGIN :°4'G +----- +G +UU -----BEGIN 2°4'/---- +-----BEGIN :°4'----- +G +UU QG +wFUG + fbwFUU QG +wFU UQG +wFUG + fbwFUU QG +wFU fG + b \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/f9f61f03681250b015a00df3010b89d2d776d8fc b/external/boringssl/fuzz/read_pem_corpus/f9f61f03681250b015a00df3010b89d2d776d8fc new file mode 100644 index 0000000000..7643d8eb58 Binary files /dev/null and b/external/boringssl/fuzz/read_pem_corpus/f9f61f03681250b015a00df3010b89d2d776d8fc differ diff --git a/external/boringssl/fuzz/read_pem_corpus/fad7e4071afc1e4f441e2cb65cf9b0da37dcd74e b/external/boringssl/fuzz/read_pem_corpus/fad7e4071afc1e4f441e2cb65cf9b0da37dcd74e new file mode 100644 index 0000000000..a6b2ddb603 --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/fad7e4071afc1e4f441e2cb65cf9b0da37dcd74e @@ -0,0 +1,2 @@ +'---+ô----- +è \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/fb36b0ce1600b9399d552eab916600c239be5ad5 b/external/boringssl/fuzz/read_pem_corpus/fb36b0ce1600b9399d552eab916600c239be5ad5 new file mode 100644 index 0000000000..56195cbdd5 Binary files /dev/null and b/external/boringssl/fuzz/read_pem_corpus/fb36b0ce1600b9399d552eab916600c239be5ad5 differ diff --git a/external/boringssl/fuzz/read_pem_corpus/fb64fef6ea2f835804b69ae3d21fb2cac7e4973f b/external/boringssl/fuzz/read_pem_corpus/fb64fef6ea2f835804b69ae3d21fb2cac7e4973f new file mode 100644 index 0000000000..00294ef9f0 --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/fb64fef6ea2f835804b69ae3d21fb2cac7e4973f @@ -0,0 +1,9 @@ +-----BEGIN O----- +----(END /!-----BEGI 7í‘;!(;)š-----END ç/O!:š-----BEGIN O----- +----(END /!---'U('ß(:(ç/!;!;‘6í();':(´'H('G)M˜G¿ëÑ'yO- + )o(*(Ç*Ä;ò¹:)·¬Ù*ª:!:Œ:(';±×'Ú(;—é)Ð(!:™)¢í:”"P•Z ˆg;:P; :':Â:7!)÷ö)vôǾ:--BEGIN 6í‘;!(;)š-----END ç/!----- +- +kqU;O!:š'U|:ØŽ8*:;sá(f!‘;;)------ +----BEGIN ‘O----- +----(END /!-----BEGIN 6í- +j*:‘;!(;)š-----END 6çí( \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/fb6d4702bcb98df173527a5f08d5ac829adb2f9f b/external/boringssl/fuzz/read_pem_corpus/fb6d4702bcb98df173527a5f08d5ac829adb2f9f new file mode 100644 index 0000000000..cc3cbef272 --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/fb6d4702bcb98df173527a5f08d5ac829adb2f9f @@ -0,0 +1,15 @@ +-----BEGIN O----- +----(END /!----‘6í( + 7í‘;!(;)š-----END ç/O!:š--- +---BEGIN O----- +----(END /!---'U('ß(:(ç!/;!;‘6í();':(´'H('G)M˜G¿ëÑ'yO- + )o(*(Ç*Ä;ò¹:)·¬Ù*ª:!- +:(';±×'Ú(;—é)- +Ð(!:™)¢í:”"P•Z ˆg;:; :':Â:7!)÷ö)v*Ǿ:--BEGIN 6í‘;!(;)š-- +----END ç/!----- +- +kqU;!:Oš'U|:ØŽ8*:;sá(f!‘;;)--*---- +----BEGIN ‘O----- +----(END /!-----BEGIN 6í +j- +‘;!(;)š-----END 6çí( \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/fd1cc706033976b86a93d2b0c74b15bb2f31fccf b/external/boringssl/fuzz/read_pem_corpus/fd1cc706033976b86a93d2b0c74b15bb2f31fccf new file mode 100644 index 0000000000..06f32836da --- /dev/null +++ b/external/boringssl/fuzz/read_pem_corpus/fd1cc706033976b86a93d2b0c74b15bb2f31fccf @@ -0,0 +1,18 @@ +-‘6í( + +----- +----BEGIN ‘6í( + +----N!(ED /-----BEGI 6í‘;!(;)š--'-8-END ç-‰ +---BEGIN O----- +----(END--=--END -----BEGIN O----- +----(END /!-----BEGIN 7í‘;!(;)š-----END ç//!-----!;BE-----END GI 5í‘;!(;)š-----END ç----- +/!--- + +- +‘7í/!--!----- +‘6í(- + +- +‘6ôí((- + \ No newline at end of file diff --git a/external/boringssl/fuzz/read_pem_corpus/ff7dcdb0fc13ddea6e82cac7bf3a0414cb772ded b/external/boringssl/fuzz/read_pem_corpus/ff7dcdb0fc13ddea6e82cac7bf3a0414cb772ded new file mode 100644 index 0000000000..88fd2b0315 Binary files /dev/null and b/external/boringssl/fuzz/read_pem_corpus/ff7dcdb0fc13ddea6e82cac7bf3a0414cb772ded differ diff --git a/external/boringssl/fuzz/server.cc b/external/boringssl/fuzz/server.cc new file mode 100644 index 0000000000..75522bacc6 --- /dev/null +++ b/external/boringssl/fuzz/server.cc @@ -0,0 +1,243 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include +#include + +static const uint8_t kCertificateDER[] = { + 0x30, 0x82, 0x02, 0xff, 0x30, 0x82, 0x01, 0xe7, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x11, 0x00, 0xb1, 0x84, 0xee, 0x34, 0x99, 0x98, 0x76, 0xfb, + 0x6f, 0xb2, 0x15, 0xc8, 0x47, 0x79, 0x05, 0x9b, 0x30, 0x0d, 0x06, 0x09, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, + 0x12, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x07, + 0x41, 0x63, 0x6d, 0x65, 0x20, 0x43, 0x6f, 0x30, 0x1e, 0x17, 0x0d, 0x31, + 0x35, 0x31, 0x31, 0x30, 0x37, 0x30, 0x30, 0x32, 0x34, 0x35, 0x36, 0x5a, + 0x17, 0x0d, 0x31, 0x36, 0x31, 0x31, 0x30, 0x36, 0x30, 0x30, 0x32, 0x34, + 0x35, 0x36, 0x5a, 0x30, 0x12, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, + 0x04, 0x0a, 0x13, 0x07, 0x41, 0x63, 0x6d, 0x65, 0x20, 0x43, 0x6f, 0x30, + 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, + 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xce, 0x47, 0xcb, 0x11, + 0xbb, 0xd2, 0x9d, 0x8e, 0x9e, 0xd2, 0x1e, 0x14, 0xaf, 0xc7, 0xea, 0xb6, + 0xc9, 0x38, 0x2a, 0x6f, 0xb3, 0x7e, 0xfb, 0xbc, 0xfc, 0x59, 0x42, 0xb9, + 0x56, 0xf0, 0x4c, 0x3f, 0xf7, 0x31, 0x84, 0xbe, 0xac, 0x03, 0x9e, 0x71, + 0x91, 0x85, 0xd8, 0x32, 0xbd, 0x00, 0xea, 0xac, 0x65, 0xf6, 0x03, 0xc8, + 0x0f, 0x8b, 0xfd, 0x6e, 0x58, 0x88, 0x04, 0x41, 0x92, 0x74, 0xa6, 0x57, + 0x2e, 0x8e, 0x88, 0xd5, 0x3d, 0xda, 0x14, 0x3e, 0x63, 0x88, 0x22, 0xe3, + 0x53, 0xe9, 0xba, 0x39, 0x09, 0xac, 0xfb, 0xd0, 0x4c, 0xf2, 0x3c, 0x20, + 0xd6, 0x97, 0xe6, 0xed, 0xf1, 0x62, 0x1e, 0xe5, 0xc9, 0x48, 0xa0, 0xca, + 0x2e, 0x3c, 0x14, 0x5a, 0x82, 0xd4, 0xed, 0xb1, 0xe3, 0x43, 0xc1, 0x2a, + 0x59, 0xa5, 0xb9, 0xc8, 0x48, 0xa7, 0x39, 0x23, 0x74, 0xa7, 0x37, 0xb0, + 0x6f, 0xc3, 0x64, 0x99, 0x6c, 0xa2, 0x82, 0xc8, 0xf6, 0xdb, 0x86, 0x40, + 0xce, 0xd1, 0x85, 0x9f, 0xce, 0x69, 0xf4, 0x15, 0x2a, 0x23, 0xca, 0xea, + 0xb7, 0x7b, 0xdf, 0xfb, 0x43, 0x5f, 0xff, 0x7a, 0x49, 0x49, 0x0e, 0xe7, + 0x02, 0x51, 0x45, 0x13, 0xe8, 0x90, 0x64, 0x21, 0x0c, 0x26, 0x2b, 0x5d, + 0xfc, 0xe4, 0xb5, 0x86, 0x89, 0x43, 0x22, 0x4c, 0xf3, 0x3b, 0xf3, 0x09, + 0xc4, 0xa4, 0x10, 0x80, 0xf2, 0x46, 0xe2, 0x46, 0x8f, 0x76, 0x50, 0xbf, + 0xaf, 0x2b, 0x90, 0x1b, 0x78, 0xc7, 0xcf, 0xc1, 0x77, 0xd0, 0xfb, 0xa9, + 0xfb, 0xc9, 0x66, 0x5a, 0xc5, 0x9b, 0x31, 0x41, 0x67, 0x01, 0xbe, 0x33, + 0x10, 0xba, 0x05, 0x58, 0xed, 0x76, 0x53, 0xde, 0x5d, 0xc1, 0xe8, 0xbb, + 0x9f, 0xf1, 0xcd, 0xfb, 0xdf, 0x64, 0x7f, 0xd7, 0x18, 0xab, 0x0f, 0x94, + 0x28, 0x95, 0x4a, 0xcc, 0x6a, 0xa9, 0x50, 0xc7, 0x05, 0x47, 0x10, 0x41, + 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x50, 0x30, 0x4e, 0x30, 0x0e, 0x06, + 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x05, + 0xa0, 0x30, 0x13, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x0c, 0x30, 0x0a, + 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0x30, 0x0c, + 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, 0x00, + 0x30, 0x19, 0x06, 0x03, 0x55, 0x1d, 0x11, 0x04, 0x12, 0x30, 0x10, 0x82, + 0x0e, 0x66, 0x75, 0x7a, 0x7a, 0x2e, 0x62, 0x6f, 0x72, 0x69, 0x6e, 0x67, + 0x73, 0x73, 0x6c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x92, + 0xde, 0xef, 0x96, 0x06, 0x7b, 0xff, 0x71, 0x7d, 0x4e, 0xa0, 0x7d, 0xae, + 0xb8, 0x22, 0xb4, 0x2c, 0xf7, 0x96, 0x9c, 0x37, 0x1d, 0x8f, 0xe7, 0xd9, + 0x47, 0xff, 0x3f, 0xe9, 0x35, 0x95, 0x0e, 0xdd, 0xdc, 0x7f, 0xc8, 0x8a, + 0x1e, 0x36, 0x1d, 0x38, 0x47, 0xfc, 0x76, 0xd2, 0x1f, 0x98, 0xa1, 0x36, + 0xac, 0xc8, 0x70, 0x38, 0x0a, 0x3d, 0x51, 0x8d, 0x0f, 0x03, 0x1b, 0xef, + 0x62, 0xa1, 0xcb, 0x2b, 0x4a, 0x8c, 0x12, 0x2b, 0x54, 0x50, 0x9a, 0x6b, + 0xfe, 0xaf, 0xd9, 0xf6, 0xbf, 0x58, 0x11, 0x58, 0x5e, 0xe5, 0x86, 0x1e, + 0x3b, 0x6b, 0x30, 0x7e, 0x72, 0x89, 0xe8, 0x6b, 0x7b, 0xb7, 0xaf, 0xef, + 0x8b, 0xa9, 0x3e, 0xb0, 0xcd, 0x0b, 0xef, 0xb0, 0x0c, 0x96, 0x2b, 0xc5, + 0x3b, 0xd5, 0xf1, 0xc2, 0xae, 0x3a, 0x60, 0xd9, 0x0f, 0x75, 0x37, 0x55, + 0x4d, 0x62, 0xd2, 0xed, 0x96, 0xac, 0x30, 0x6b, 0xda, 0xa1, 0x48, 0x17, + 0x96, 0x23, 0x85, 0x9a, 0x57, 0x77, 0xe9, 0x22, 0xa2, 0x37, 0x03, 0xba, + 0x49, 0x77, 0x40, 0x3b, 0x76, 0x4b, 0xda, 0xc1, 0x04, 0x57, 0x55, 0x34, + 0x22, 0x83, 0x45, 0x29, 0xab, 0x2e, 0x11, 0xff, 0x0d, 0xab, 0x55, 0xb1, + 0xa7, 0x58, 0x59, 0x05, 0x25, 0xf9, 0x1e, 0x3d, 0xb7, 0xac, 0x04, 0x39, + 0x2c, 0xf9, 0xaf, 0xb8, 0x68, 0xfb, 0x8e, 0x35, 0x71, 0x32, 0xff, 0x70, + 0xe9, 0x46, 0x6d, 0x5c, 0x06, 0x90, 0x88, 0x23, 0x48, 0x0c, 0x50, 0xeb, + 0x0a, 0xa9, 0xae, 0xe8, 0xfc, 0xbe, 0xa5, 0x76, 0x94, 0xd7, 0x64, 0x22, + 0x38, 0x98, 0x17, 0xa4, 0x3a, 0xa7, 0x59, 0x9f, 0x1d, 0x3b, 0x75, 0x90, + 0x1a, 0x81, 0xef, 0x19, 0xfb, 0x2b, 0xb7, 0xa7, 0x64, 0x61, 0x22, 0xa4, + 0x6f, 0x7b, 0xfa, 0x58, 0xbb, 0x8c, 0x4e, 0x77, 0x67, 0xd0, 0x5d, 0x58, + 0x76, 0x8a, 0xbb, +}; + +static const uint8_t kRSAPrivateKeyDER[] = { + 0x30, 0x82, 0x04, 0xa5, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, + 0xce, 0x47, 0xcb, 0x11, 0xbb, 0xd2, 0x9d, 0x8e, 0x9e, 0xd2, 0x1e, 0x14, + 0xaf, 0xc7, 0xea, 0xb6, 0xc9, 0x38, 0x2a, 0x6f, 0xb3, 0x7e, 0xfb, 0xbc, + 0xfc, 0x59, 0x42, 0xb9, 0x56, 0xf0, 0x4c, 0x3f, 0xf7, 0x31, 0x84, 0xbe, + 0xac, 0x03, 0x9e, 0x71, 0x91, 0x85, 0xd8, 0x32, 0xbd, 0x00, 0xea, 0xac, + 0x65, 0xf6, 0x03, 0xc8, 0x0f, 0x8b, 0xfd, 0x6e, 0x58, 0x88, 0x04, 0x41, + 0x92, 0x74, 0xa6, 0x57, 0x2e, 0x8e, 0x88, 0xd5, 0x3d, 0xda, 0x14, 0x3e, + 0x63, 0x88, 0x22, 0xe3, 0x53, 0xe9, 0xba, 0x39, 0x09, 0xac, 0xfb, 0xd0, + 0x4c, 0xf2, 0x3c, 0x20, 0xd6, 0x97, 0xe6, 0xed, 0xf1, 0x62, 0x1e, 0xe5, + 0xc9, 0x48, 0xa0, 0xca, 0x2e, 0x3c, 0x14, 0x5a, 0x82, 0xd4, 0xed, 0xb1, + 0xe3, 0x43, 0xc1, 0x2a, 0x59, 0xa5, 0xb9, 0xc8, 0x48, 0xa7, 0x39, 0x23, + 0x74, 0xa7, 0x37, 0xb0, 0x6f, 0xc3, 0x64, 0x99, 0x6c, 0xa2, 0x82, 0xc8, + 0xf6, 0xdb, 0x86, 0x40, 0xce, 0xd1, 0x85, 0x9f, 0xce, 0x69, 0xf4, 0x15, + 0x2a, 0x23, 0xca, 0xea, 0xb7, 0x7b, 0xdf, 0xfb, 0x43, 0x5f, 0xff, 0x7a, + 0x49, 0x49, 0x0e, 0xe7, 0x02, 0x51, 0x45, 0x13, 0xe8, 0x90, 0x64, 0x21, + 0x0c, 0x26, 0x2b, 0x5d, 0xfc, 0xe4, 0xb5, 0x86, 0x89, 0x43, 0x22, 0x4c, + 0xf3, 0x3b, 0xf3, 0x09, 0xc4, 0xa4, 0x10, 0x80, 0xf2, 0x46, 0xe2, 0x46, + 0x8f, 0x76, 0x50, 0xbf, 0xaf, 0x2b, 0x90, 0x1b, 0x78, 0xc7, 0xcf, 0xc1, + 0x77, 0xd0, 0xfb, 0xa9, 0xfb, 0xc9, 0x66, 0x5a, 0xc5, 0x9b, 0x31, 0x41, + 0x67, 0x01, 0xbe, 0x33, 0x10, 0xba, 0x05, 0x58, 0xed, 0x76, 0x53, 0xde, + 0x5d, 0xc1, 0xe8, 0xbb, 0x9f, 0xf1, 0xcd, 0xfb, 0xdf, 0x64, 0x7f, 0xd7, + 0x18, 0xab, 0x0f, 0x94, 0x28, 0x95, 0x4a, 0xcc, 0x6a, 0xa9, 0x50, 0xc7, + 0x05, 0x47, 0x10, 0x41, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, + 0x01, 0x00, 0xa8, 0x47, 0xb9, 0x4a, 0x06, 0x47, 0x93, 0x71, 0x3d, 0xef, + 0x7b, 0xca, 0xb4, 0x7c, 0x0a, 0xe6, 0x82, 0xd0, 0xe7, 0x0d, 0xa9, 0x08, + 0xf6, 0xa4, 0xfd, 0xd8, 0x73, 0xae, 0x6f, 0x56, 0x29, 0x5e, 0x25, 0x72, + 0xa8, 0x30, 0x44, 0x73, 0xcf, 0x56, 0x26, 0xb9, 0x61, 0xde, 0x42, 0x81, + 0xf4, 0xf0, 0x1f, 0x5d, 0xcb, 0x47, 0xf2, 0x26, 0xe9, 0xe0, 0x93, 0x28, + 0xa3, 0x10, 0x3b, 0x42, 0x1e, 0x51, 0x11, 0x12, 0x06, 0x5e, 0xaf, 0xce, + 0xb0, 0xa5, 0x14, 0xdd, 0x82, 0x58, 0xa1, 0xa4, 0x12, 0xdf, 0x65, 0x1d, + 0x51, 0x70, 0x64, 0xd5, 0x58, 0x68, 0x11, 0xa8, 0x6a, 0x23, 0xc2, 0xbf, + 0xa1, 0x25, 0x24, 0x47, 0xb3, 0xa4, 0x3c, 0x83, 0x96, 0xb7, 0x1f, 0xf4, + 0x44, 0xd4, 0xd1, 0xe9, 0xfc, 0x33, 0x68, 0x5e, 0xe2, 0x68, 0x99, 0x9c, + 0x91, 0xe8, 0x72, 0xc9, 0xd7, 0x8c, 0x80, 0x20, 0x8e, 0x77, 0x83, 0x4d, + 0xe4, 0xab, 0xf9, 0x74, 0xa1, 0xdf, 0xd3, 0xc0, 0x0d, 0x5b, 0x05, 0x51, + 0xc2, 0x6f, 0xb2, 0x91, 0x02, 0xec, 0xc0, 0x02, 0x1a, 0x5c, 0x91, 0x05, + 0xf1, 0xe3, 0xfa, 0x65, 0xc2, 0xad, 0x24, 0xe6, 0xe5, 0x3c, 0xb6, 0x16, + 0xf1, 0xa1, 0x67, 0x1a, 0x9d, 0x37, 0x56, 0xbf, 0x01, 0xd7, 0x3b, 0x35, + 0x30, 0x57, 0x73, 0xf4, 0xf0, 0x5e, 0xa7, 0xe8, 0x0a, 0xc1, 0x94, 0x17, + 0xcf, 0x0a, 0xbd, 0xf5, 0x31, 0xa7, 0x2d, 0xf7, 0xf5, 0xd9, 0x8c, 0xc2, + 0x01, 0xbd, 0xda, 0x16, 0x8e, 0xb9, 0x30, 0x40, 0xa6, 0x6e, 0xbd, 0xcd, + 0x4d, 0x84, 0x67, 0x4e, 0x0b, 0xce, 0xd5, 0xef, 0xf8, 0x08, 0x63, 0x02, + 0xc6, 0xc7, 0xf7, 0x67, 0x92, 0xe2, 0x23, 0x9d, 0x27, 0x22, 0x1d, 0xc6, + 0x67, 0x5e, 0x66, 0xbf, 0x03, 0xb8, 0xa9, 0x67, 0xd4, 0x39, 0xd8, 0x75, + 0xfa, 0xe8, 0xed, 0x56, 0xb8, 0x81, 0x02, 0x81, 0x81, 0x00, 0xf7, 0x46, + 0x68, 0xc6, 0x13, 0xf8, 0xba, 0x0f, 0x83, 0xdb, 0x05, 0xa8, 0x25, 0x00, + 0x70, 0x9c, 0x9e, 0x8b, 0x12, 0x34, 0x0d, 0x96, 0xcf, 0x0d, 0x98, 0x9b, + 0x8d, 0x9c, 0x96, 0x78, 0xd1, 0x3c, 0x01, 0x8c, 0xb9, 0x35, 0x5c, 0x20, + 0x42, 0xb4, 0x38, 0xe3, 0xd6, 0x54, 0xe7, 0x55, 0xd6, 0x26, 0x8a, 0x0c, + 0xf6, 0x1f, 0xe0, 0x04, 0xc1, 0x22, 0x42, 0x19, 0x61, 0xc4, 0x94, 0x7c, + 0x07, 0x2e, 0x80, 0x52, 0xfe, 0x8d, 0xe6, 0x92, 0x3a, 0x91, 0xfe, 0x72, + 0x99, 0xe1, 0x2a, 0x73, 0x76, 0xb1, 0x24, 0x20, 0x67, 0xde, 0x28, 0xcb, + 0x0e, 0xe6, 0x52, 0xb5, 0xfa, 0xfb, 0x8b, 0x1e, 0x6a, 0x1d, 0x09, 0x26, + 0xb9, 0xa7, 0x61, 0xba, 0xf8, 0x79, 0xd2, 0x66, 0x57, 0x28, 0xd7, 0x31, + 0xb5, 0x0b, 0x27, 0x19, 0x1e, 0x6f, 0x46, 0xfc, 0x54, 0x95, 0xeb, 0x78, + 0x01, 0xb6, 0xd9, 0x79, 0x5a, 0x4d, 0x02, 0x81, 0x81, 0x00, 0xd5, 0x8f, + 0x16, 0x53, 0x2f, 0x57, 0x93, 0xbf, 0x09, 0x75, 0xbf, 0x63, 0x40, 0x3d, + 0x27, 0xfd, 0x23, 0x21, 0xde, 0x9b, 0xe9, 0x73, 0x3f, 0x49, 0x02, 0xd2, + 0x38, 0x96, 0xcf, 0xc3, 0xba, 0x92, 0x07, 0x87, 0x52, 0xa9, 0x35, 0xe3, + 0x0c, 0xe4, 0x2f, 0x05, 0x7b, 0x37, 0xa5, 0x40, 0x9c, 0x3b, 0x94, 0xf7, + 0xad, 0xa0, 0xee, 0x3a, 0xa8, 0xfb, 0x1f, 0x11, 0x1f, 0xd8, 0x9a, 0x80, + 0x42, 0x3d, 0x7f, 0xa4, 0xb8, 0x9a, 0xaa, 0xea, 0x72, 0xc1, 0xe3, 0xed, + 0x06, 0x60, 0x92, 0x37, 0xf9, 0xba, 0xfb, 0x9e, 0xed, 0x05, 0xa6, 0xd4, + 0x72, 0x68, 0x4f, 0x63, 0xfe, 0xd6, 0x10, 0x0d, 0x4f, 0x0a, 0x93, 0xc6, + 0xb9, 0xd7, 0xaf, 0xfd, 0xd9, 0x57, 0x7d, 0xcb, 0x75, 0xe8, 0x93, 0x2b, + 0xae, 0x4f, 0xea, 0xd7, 0x30, 0x0b, 0x58, 0x44, 0x82, 0x0f, 0x84, 0x5d, + 0x62, 0x11, 0x78, 0xea, 0x5f, 0xc5, 0x02, 0x81, 0x81, 0x00, 0x82, 0x0c, + 0xc1, 0xe6, 0x0b, 0x72, 0xf1, 0x48, 0x5f, 0xac, 0xbd, 0x98, 0xe5, 0x7d, + 0x09, 0xbd, 0x15, 0x95, 0x47, 0x09, 0xa1, 0x6c, 0x03, 0x91, 0xbf, 0x05, + 0x70, 0xc1, 0x3e, 0x52, 0x64, 0x99, 0x0e, 0xa7, 0x98, 0x70, 0xfb, 0xf6, + 0xeb, 0x9e, 0x25, 0x9d, 0x8e, 0x88, 0x30, 0xf2, 0xf0, 0x22, 0x6c, 0xd0, + 0xcc, 0x51, 0x8f, 0x5c, 0x70, 0xc7, 0x37, 0xc4, 0x69, 0xab, 0x1d, 0xfc, + 0xed, 0x3a, 0x03, 0xbb, 0xa2, 0xad, 0xb6, 0xea, 0x89, 0x6b, 0x67, 0x4b, + 0x96, 0xaa, 0xd9, 0xcc, 0xc8, 0x4b, 0xfa, 0x18, 0x21, 0x08, 0xb2, 0xa3, + 0xb9, 0x3e, 0x61, 0x99, 0xdc, 0x5a, 0x97, 0x9c, 0x73, 0x6a, 0xb9, 0xf9, + 0x68, 0x03, 0x24, 0x5f, 0x55, 0x77, 0x9c, 0xb4, 0xbe, 0x7a, 0x78, 0x53, + 0x68, 0x48, 0x69, 0x53, 0xc8, 0xb1, 0xf5, 0xbf, 0x98, 0x2d, 0x11, 0x1e, + 0x98, 0xa8, 0x36, 0x50, 0xa0, 0xb1, 0x02, 0x81, 0x81, 0x00, 0x90, 0x88, + 0x30, 0x71, 0xc7, 0xfe, 0x9b, 0x6d, 0x95, 0x37, 0x6d, 0x79, 0xfc, 0x85, + 0xe7, 0x44, 0x78, 0xbc, 0x79, 0x6e, 0x47, 0x86, 0xc9, 0xf3, 0xdd, 0xc6, + 0xec, 0xa9, 0x94, 0x9f, 0x40, 0xeb, 0x87, 0xd0, 0xdb, 0xee, 0xcd, 0x1b, + 0x87, 0x23, 0xff, 0x76, 0xd4, 0x37, 0x8a, 0xcd, 0xb9, 0x6e, 0xd1, 0x98, + 0xf6, 0x97, 0x8d, 0xe3, 0x81, 0x6d, 0xc3, 0x4e, 0xd1, 0xa0, 0xc4, 0x9f, + 0xbd, 0x34, 0xe5, 0xe8, 0x53, 0x4f, 0xca, 0x10, 0xb5, 0xed, 0xe7, 0x16, + 0x09, 0x54, 0xde, 0x60, 0xa7, 0xd1, 0x16, 0x6e, 0x2e, 0xb7, 0xbe, 0x7a, + 0xd5, 0x9b, 0x26, 0xef, 0xe4, 0x0e, 0x77, 0xfa, 0xa9, 0xdd, 0xdc, 0xb9, + 0x88, 0x19, 0x23, 0x70, 0xc7, 0xe1, 0x60, 0xaf, 0x8c, 0x73, 0x04, 0xf7, + 0x71, 0x17, 0x81, 0x36, 0x75, 0xbb, 0x97, 0xd7, 0x75, 0xb6, 0x8e, 0xbc, + 0xac, 0x9c, 0x6a, 0x9b, 0x24, 0x89, 0x02, 0x81, 0x80, 0x5a, 0x2b, 0xc7, + 0x6b, 0x8c, 0x65, 0xdb, 0x04, 0x73, 0xab, 0x25, 0xe1, 0x5b, 0xbc, 0x3c, + 0xcf, 0x5a, 0x3c, 0x04, 0xae, 0x97, 0x2e, 0xfd, 0xa4, 0x97, 0x1f, 0x05, + 0x17, 0x27, 0xac, 0x7c, 0x30, 0x85, 0xb4, 0x82, 0x3f, 0x5b, 0xb7, 0x94, + 0x3b, 0x7f, 0x6c, 0x0c, 0xc7, 0x16, 0xc6, 0xa0, 0xbd, 0x80, 0xb0, 0x81, + 0xde, 0xa0, 0x23, 0xa6, 0xf6, 0x75, 0x33, 0x51, 0x35, 0xa2, 0x75, 0x55, + 0x70, 0x4d, 0x42, 0xbb, 0xcf, 0x54, 0xe4, 0xdb, 0x2d, 0x88, 0xa0, 0x7a, + 0xf2, 0x17, 0xa7, 0xdd, 0x13, 0x44, 0x9f, 0x5f, 0x6b, 0x2c, 0x42, 0x42, + 0x8b, 0x13, 0x4d, 0xf9, 0x5b, 0xf8, 0x33, 0x42, 0xd9, 0x9e, 0x50, 0x1c, + 0x7c, 0xbc, 0xfa, 0x62, 0x85, 0x0b, 0xcf, 0x99, 0xda, 0x9e, 0x04, 0x90, + 0xb2, 0xc6, 0xb2, 0x0a, 0x2a, 0x7c, 0x6d, 0x6a, 0x40, 0xfc, 0xf5, 0x50, + 0x98, 0x46, 0x89, 0x82, 0x40, +}; + +struct GlobalState { + GlobalState() + : ctx(SSL_CTX_new(SSLv23_method())) { + const uint8_t *bufp = kRSAPrivateKeyDER; + RSA *privkey = d2i_RSAPrivateKey(NULL, &bufp, sizeof(kRSAPrivateKeyDER)); + assert(privkey != nullptr); + + EVP_PKEY *pkey = EVP_PKEY_new(); + EVP_PKEY_assign_RSA(pkey, privkey); + + SSL_CTX_use_PrivateKey(ctx, pkey); + EVP_PKEY_free(pkey); + + bufp = kCertificateDER; + X509 *cert = d2i_X509(NULL, &bufp, sizeof(kCertificateDER)); + assert(cert != nullptr); + + SSL_CTX_use_certificate(ctx, cert); + X509_free(cert); + } + + ~GlobalState() { + SSL_CTX_free(ctx); + } + + SSL_CTX *const ctx; +}; + +static GlobalState g_state; + +extern "C" int LLVMFuzzerTestOneInput(uint8_t *buf, size_t len) { + RAND_reset_for_fuzzing(); + + SSL *server = SSL_new(g_state.ctx); + BIO *in = BIO_new(BIO_s_mem()); + BIO *out = BIO_new(BIO_s_mem()); + SSL_set_bio(server, in, out); + SSL_set_accept_state(server); + + BIO_write(in, buf, len); + if (SSL_do_handshake(server) == 1) { + // Keep reading application data until error or EOF. + uint8_t tmp[1024]; + for (;;) { + if (SSL_read(server, tmp, sizeof(tmp)) <= 0) { + break; + } + } + } + SSL_free(server); + + return 0; +} diff --git a/external/boringssl/fuzz/server_corpus/009baa11e6cfa1713bc175dbf069d3bdf0c5b49c b/external/boringssl/fuzz/server_corpus/009baa11e6cfa1713bc175dbf069d3bdf0c5b49c new file mode 100644 index 0000000000..1a881d4b30 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/009baa11e6cfa1713bc175dbf069d3bdf0c5b49c differ diff --git a/external/boringssl/fuzz/server_corpus/02601bb35ae3de52d87fc0b48188195b7c07e9ab b/external/boringssl/fuzz/server_corpus/02601bb35ae3de52d87fc0b48188195b7c07e9ab new file mode 100644 index 0000000000..34c02a03e4 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/02601bb35ae3de52d87fc0b48188195b7c07e9ab differ diff --git a/external/boringssl/fuzz/server_corpus/0293d811efcdbb311aa55d23fa9fe9566a64bd2b b/external/boringssl/fuzz/server_corpus/0293d811efcdbb311aa55d23fa9fe9566a64bd2b new file mode 100644 index 0000000000..fc4c50566c Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/0293d811efcdbb311aa55d23fa9fe9566a64bd2b differ diff --git a/external/boringssl/fuzz/server_corpus/0339d4398642097dd08378d2de67f45825d623b9 b/external/boringssl/fuzz/server_corpus/0339d4398642097dd08378d2de67f45825d623b9 new file mode 100644 index 0000000000..a05a6e5be3 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/0339d4398642097dd08378d2de67f45825d623b9 differ diff --git a/external/boringssl/fuzz/server_corpus/0353776fd79d387026cfe5366f46f5a7417e58e2 b/external/boringssl/fuzz/server_corpus/0353776fd79d387026cfe5366f46f5a7417e58e2 new file mode 100644 index 0000000000..7461015710 --- /dev/null +++ b/external/boringssl/fuzz/server_corpus/0353776fd79d387026cfe5366f46f5a7417e58e2 @@ -0,0 +1 @@ +€);Õ›ãºR#)_ \ No newline at end of file diff --git a/external/boringssl/fuzz/server_corpus/0356ffe0a247cb950a3c2fc4b125c2ec1d19e480 b/external/boringssl/fuzz/server_corpus/0356ffe0a247cb950a3c2fc4b125c2ec1d19e480 new file mode 100644 index 0000000000..2851119a30 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/0356ffe0a247cb950a3c2fc4b125c2ec1d19e480 differ diff --git a/external/boringssl/fuzz/server_corpus/03c9f2cc53c803b0cfa115e252ed40f2546cde27 b/external/boringssl/fuzz/server_corpus/03c9f2cc53c803b0cfa115e252ed40f2546cde27 new file mode 100644 index 0000000000..56c728bbf0 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/03c9f2cc53c803b0cfa115e252ed40f2546cde27 differ diff --git a/external/boringssl/fuzz/server_corpus/03ed4f1ff81afbad5eedbb5a80b56b23298ec078 b/external/boringssl/fuzz/server_corpus/03ed4f1ff81afbad5eedbb5a80b56b23298ec078 new file mode 100644 index 0000000000..621f52fbb0 --- /dev/null +++ b/external/boringssl/fuzz/server_corpus/03ed4f1ff81afbad5eedbb5a80b56b23298ec078 @@ -0,0 +1 @@ +€)(:*Î*);›ã)ã×(*¹; \ No newline at end of file diff --git a/external/boringssl/fuzz/server_corpus/03fc9321fb45199b8fbbdefabc651e84b73f0ff8 b/external/boringssl/fuzz/server_corpus/03fc9321fb45199b8fbbdefabc651e84b73f0ff8 new file mode 100644 index 0000000000..d5a543465d Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/03fc9321fb45199b8fbbdefabc651e84b73f0ff8 differ diff --git a/external/boringssl/fuzz/server_corpus/0475246ec9d1587d2e0a6bf08ea99bfa2e37f78d b/external/boringssl/fuzz/server_corpus/0475246ec9d1587d2e0a6bf08ea99bfa2e37f78d new file mode 100644 index 0000000000..1ef5ad7399 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/0475246ec9d1587d2e0a6bf08ea99bfa2e37f78d differ diff --git a/external/boringssl/fuzz/server_corpus/04a3dd601cad12e190ceeddb450e6314c602719c b/external/boringssl/fuzz/server_corpus/04a3dd601cad12e190ceeddb450e6314c602719c new file mode 100644 index 0000000000..772f7cb043 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/04a3dd601cad12e190ceeddb450e6314c602719c differ diff --git a/external/boringssl/fuzz/server_corpus/05f1de3d83b0d836b0e504f127f6e7445e61400e b/external/boringssl/fuzz/server_corpus/05f1de3d83b0d836b0e504f127f6e7445e61400e new file mode 100644 index 0000000000..42150a6afc Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/05f1de3d83b0d836b0e504f127f6e7445e61400e differ diff --git a/external/boringssl/fuzz/server_corpus/06c1bbafe734f1bce369c330411e508dda42f8fe b/external/boringssl/fuzz/server_corpus/06c1bbafe734f1bce369c330411e508dda42f8fe new file mode 100644 index 0000000000..e8baa3999f Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/06c1bbafe734f1bce369c330411e508dda42f8fe differ diff --git a/external/boringssl/fuzz/server_corpus/06f786810efbda4369f4d6ae5613eec10c64b2a6 b/external/boringssl/fuzz/server_corpus/06f786810efbda4369f4d6ae5613eec10c64b2a6 new file mode 100644 index 0000000000..a24811b4e6 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/06f786810efbda4369f4d6ae5613eec10c64b2a6 differ diff --git a/external/boringssl/fuzz/server_corpus/0729cde85be33f7f78ed90db14fc05924f755fc0 b/external/boringssl/fuzz/server_corpus/0729cde85be33f7f78ed90db14fc05924f755fc0 new file mode 100644 index 0000000000..a0f6576bc2 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/0729cde85be33f7f78ed90db14fc05924f755fc0 differ diff --git a/external/boringssl/fuzz/server_corpus/078734f3f4e18e155dd4252624103b2d890f1e44 b/external/boringssl/fuzz/server_corpus/078734f3f4e18e155dd4252624103b2d890f1e44 new file mode 100644 index 0000000000..b4d0f61c27 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/078734f3f4e18e155dd4252624103b2d890f1e44 differ diff --git a/external/boringssl/fuzz/server_corpus/086d77d2f6efbdf4be783a888a44611cf9b14baa b/external/boringssl/fuzz/server_corpus/086d77d2f6efbdf4be783a888a44611cf9b14baa new file mode 100644 index 0000000000..db157b48c9 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/086d77d2f6efbdf4be783a888a44611cf9b14baa differ diff --git a/external/boringssl/fuzz/server_corpus/08bff079591413942c31a9d927f12d39bb9e4efe b/external/boringssl/fuzz/server_corpus/08bff079591413942c31a9d927f12d39bb9e4efe new file mode 100644 index 0000000000..ac80ae43da Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/08bff079591413942c31a9d927f12d39bb9e4efe differ diff --git a/external/boringssl/fuzz/server_corpus/0a331b0b018d33b9eb78982b333415dfc24b578f b/external/boringssl/fuzz/server_corpus/0a331b0b018d33b9eb78982b333415dfc24b578f new file mode 100644 index 0000000000..96324aa79e Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/0a331b0b018d33b9eb78982b333415dfc24b578f differ diff --git a/external/boringssl/fuzz/server_corpus/0ad3635fc2fb35c1250f4abddbc4bf40553f87ad b/external/boringssl/fuzz/server_corpus/0ad3635fc2fb35c1250f4abddbc4bf40553f87ad new file mode 100644 index 0000000000..76eb151b3f Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/0ad3635fc2fb35c1250f4abddbc4bf40553f87ad differ diff --git a/external/boringssl/fuzz/server_corpus/0b313e12e6182402ed9e6c968cfc82f305db785f b/external/boringssl/fuzz/server_corpus/0b313e12e6182402ed9e6c968cfc82f305db785f new file mode 100644 index 0000000000..f816d1f6e6 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/0b313e12e6182402ed9e6c968cfc82f305db785f differ diff --git a/external/boringssl/fuzz/server_corpus/0b9ceba9ca962d9e6aa94dffa9fce3004a587c4c b/external/boringssl/fuzz/server_corpus/0b9ceba9ca962d9e6aa94dffa9fce3004a587c4c new file mode 100644 index 0000000000..a57a49da1c Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/0b9ceba9ca962d9e6aa94dffa9fce3004a587c4c differ diff --git a/external/boringssl/fuzz/server_corpus/0c3dce9c0c0498f100445c9bfe487aefa63d16cf b/external/boringssl/fuzz/server_corpus/0c3dce9c0c0498f100445c9bfe487aefa63d16cf new file mode 100644 index 0000000000..417188c793 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/0c3dce9c0c0498f100445c9bfe487aefa63d16cf differ diff --git a/external/boringssl/fuzz/server_corpus/0cecf043638810fa52a2491cfbcd348613753822 b/external/boringssl/fuzz/server_corpus/0cecf043638810fa52a2491cfbcd348613753822 new file mode 100644 index 0000000000..3ce76341fa Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/0cecf043638810fa52a2491cfbcd348613753822 differ diff --git a/external/boringssl/fuzz/server_corpus/0d05d41086700c7ebba2cc83461cfacd83a4c93a b/external/boringssl/fuzz/server_corpus/0d05d41086700c7ebba2cc83461cfacd83a4c93a new file mode 100644 index 0000000000..237169f6d2 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/0d05d41086700c7ebba2cc83461cfacd83a4c93a differ diff --git a/external/boringssl/fuzz/server_corpus/0ecf26dbd7d24b25a474acc633d53f524ba118a8 b/external/boringssl/fuzz/server_corpus/0ecf26dbd7d24b25a474acc633d53f524ba118a8 new file mode 100644 index 0000000000..4a7e4e6721 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/0ecf26dbd7d24b25a474acc633d53f524ba118a8 differ diff --git a/external/boringssl/fuzz/server_corpus/10aab907c39d9f80fe8e8641e1931ee2ad270e16 b/external/boringssl/fuzz/server_corpus/10aab907c39d9f80fe8e8641e1931ee2ad270e16 new file mode 100644 index 0000000000..a8f2e1ef98 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/10aab907c39d9f80fe8e8641e1931ee2ad270e16 differ diff --git a/external/boringssl/fuzz/server_corpus/10e8fb6fd26d9721bb6131d91281755ebf94ef21 b/external/boringssl/fuzz/server_corpus/10e8fb6fd26d9721bb6131d91281755ebf94ef21 new file mode 100644 index 0000000000..c9bf9140be Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/10e8fb6fd26d9721bb6131d91281755ebf94ef21 differ diff --git a/external/boringssl/fuzz/server_corpus/12a98036ff99402f5be27c4e64456059b440c248 b/external/boringssl/fuzz/server_corpus/12a98036ff99402f5be27c4e64456059b440c248 new file mode 100644 index 0000000000..31a03e92ce Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/12a98036ff99402f5be27c4e64456059b440c248 differ diff --git a/external/boringssl/fuzz/server_corpus/136480311a2064a853c568d8d41b0d9c62b3d906 b/external/boringssl/fuzz/server_corpus/136480311a2064a853c568d8d41b0d9c62b3d906 new file mode 100644 index 0000000000..764778bd5d Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/136480311a2064a853c568d8d41b0d9c62b3d906 differ diff --git a/external/boringssl/fuzz/server_corpus/1378a7c740e1608a0075be8dc362445b691eaca1 b/external/boringssl/fuzz/server_corpus/1378a7c740e1608a0075be8dc362445b691eaca1 new file mode 100644 index 0000000000..c90b5a0661 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/1378a7c740e1608a0075be8dc362445b691eaca1 differ diff --git a/external/boringssl/fuzz/server_corpus/13ef34ae06ef674c04808db2c0a8adb1de856546 b/external/boringssl/fuzz/server_corpus/13ef34ae06ef674c04808db2c0a8adb1de856546 new file mode 100644 index 0000000000..2b5a64679a Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/13ef34ae06ef674c04808db2c0a8adb1de856546 differ diff --git a/external/boringssl/fuzz/server_corpus/14ce51872fcd9e415b14936b6692472f445f4489 b/external/boringssl/fuzz/server_corpus/14ce51872fcd9e415b14936b6692472f445f4489 new file mode 100644 index 0000000000..95ff827f08 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/14ce51872fcd9e415b14936b6692472f445f4489 differ diff --git a/external/boringssl/fuzz/server_corpus/1584b2eb5bc2f0e9351f5630ba9f513ffe9c1089 b/external/boringssl/fuzz/server_corpus/1584b2eb5bc2f0e9351f5630ba9f513ffe9c1089 new file mode 100644 index 0000000000..7dad299691 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/1584b2eb5bc2f0e9351f5630ba9f513ffe9c1089 differ diff --git a/external/boringssl/fuzz/server_corpus/1628ba4f9bbb8c96aecc47305f93e028040bbdac b/external/boringssl/fuzz/server_corpus/1628ba4f9bbb8c96aecc47305f93e028040bbdac new file mode 100644 index 0000000000..f8d6ce7293 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/1628ba4f9bbb8c96aecc47305f93e028040bbdac differ diff --git a/external/boringssl/fuzz/server_corpus/167171e86e3539873f2f6d19146c797774a6bcb4 b/external/boringssl/fuzz/server_corpus/167171e86e3539873f2f6d19146c797774a6bcb4 new file mode 100644 index 0000000000..82ccfb62a0 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/167171e86e3539873f2f6d19146c797774a6bcb4 differ diff --git a/external/boringssl/fuzz/server_corpus/169029c8da9497dd15c0f8ae2f2ce585568e0659 b/external/boringssl/fuzz/server_corpus/169029c8da9497dd15c0f8ae2f2ce585568e0659 new file mode 100644 index 0000000000..81f37cba32 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/169029c8da9497dd15c0f8ae2f2ce585568e0659 differ diff --git a/external/boringssl/fuzz/server_corpus/1754c50fb526624f67c4c286a29b47da5caea506 b/external/boringssl/fuzz/server_corpus/1754c50fb526624f67c4c286a29b47da5caea506 new file mode 100644 index 0000000000..84fd562291 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/1754c50fb526624f67c4c286a29b47da5caea506 differ diff --git a/external/boringssl/fuzz/server_corpus/1776797c43f6caab7f17dcd0ba1ea74e7a94b39c b/external/boringssl/fuzz/server_corpus/1776797c43f6caab7f17dcd0ba1ea74e7a94b39c new file mode 100644 index 0000000000..69f0a264d2 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/1776797c43f6caab7f17dcd0ba1ea74e7a94b39c differ diff --git a/external/boringssl/fuzz/server_corpus/19a2a537172038059839e797eaf487cc317e9ffd b/external/boringssl/fuzz/server_corpus/19a2a537172038059839e797eaf487cc317e9ffd new file mode 100644 index 0000000000..716e36a0c8 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/19a2a537172038059839e797eaf487cc317e9ffd differ diff --git a/external/boringssl/fuzz/server_corpus/1b163f7dc072468d689581829dcb93b9560e4e97 b/external/boringssl/fuzz/server_corpus/1b163f7dc072468d689581829dcb93b9560e4e97 new file mode 100644 index 0000000000..12d0b42d20 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/1b163f7dc072468d689581829dcb93b9560e4e97 differ diff --git a/external/boringssl/fuzz/server_corpus/1d9b4cbce0998360304d17a5273b57d1bb6fb33c b/external/boringssl/fuzz/server_corpus/1d9b4cbce0998360304d17a5273b57d1bb6fb33c new file mode 100644 index 0000000000..a1aa7bb255 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/1d9b4cbce0998360304d17a5273b57d1bb6fb33c differ diff --git a/external/boringssl/fuzz/server_corpus/1de612cf9b75c023cf183e85997a0797657266a3 b/external/boringssl/fuzz/server_corpus/1de612cf9b75c023cf183e85997a0797657266a3 new file mode 100644 index 0000000000..dbb2e23631 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/1de612cf9b75c023cf183e85997a0797657266a3 differ diff --git a/external/boringssl/fuzz/server_corpus/1de66d7e26f3df137ad2868570263e7fa14c0aff b/external/boringssl/fuzz/server_corpus/1de66d7e26f3df137ad2868570263e7fa14c0aff new file mode 100644 index 0000000000..08901d61ab Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/1de66d7e26f3df137ad2868570263e7fa14c0aff differ diff --git a/external/boringssl/fuzz/server_corpus/201a57ee9fff7cb160f28aea6084c520d59d5537 b/external/boringssl/fuzz/server_corpus/201a57ee9fff7cb160f28aea6084c520d59d5537 new file mode 100644 index 0000000000..0bf1d72303 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/201a57ee9fff7cb160f28aea6084c520d59d5537 differ diff --git a/external/boringssl/fuzz/server_corpus/205c2b1f4683eef4f65ca1dce4e39ee5a0423bd4 b/external/boringssl/fuzz/server_corpus/205c2b1f4683eef4f65ca1dce4e39ee5a0423bd4 new file mode 100644 index 0000000000..dd15230abc Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/205c2b1f4683eef4f65ca1dce4e39ee5a0423bd4 differ diff --git a/external/boringssl/fuzz/server_corpus/20d3cfe62b986e9fc74c2bd4f8d793928df88f4d b/external/boringssl/fuzz/server_corpus/20d3cfe62b986e9fc74c2bd4f8d793928df88f4d new file mode 100644 index 0000000000..dac432be03 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/20d3cfe62b986e9fc74c2bd4f8d793928df88f4d differ diff --git a/external/boringssl/fuzz/server_corpus/217f128931d1db8e7a12784e793d3613f7a584b1 b/external/boringssl/fuzz/server_corpus/217f128931d1db8e7a12784e793d3613f7a584b1 new file mode 100644 index 0000000000..42c85798f7 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/217f128931d1db8e7a12784e793d3613f7a584b1 differ diff --git a/external/boringssl/fuzz/server_corpus/22eda57a5819d876bbe9e0d938d4ceec5ef7bde0 b/external/boringssl/fuzz/server_corpus/22eda57a5819d876bbe9e0d938d4ceec5ef7bde0 new file mode 100644 index 0000000000..efeb24e1de Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/22eda57a5819d876bbe9e0d938d4ceec5ef7bde0 differ diff --git a/external/boringssl/fuzz/server_corpus/238118230b83a2beac4fc04e8ace080c96427e29 b/external/boringssl/fuzz/server_corpus/238118230b83a2beac4fc04e8ace080c96427e29 new file mode 100644 index 0000000000..e34a6c976b Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/238118230b83a2beac4fc04e8ace080c96427e29 differ diff --git a/external/boringssl/fuzz/server_corpus/260ef2d666d03e5451109135b50cbd9657fc6964 b/external/boringssl/fuzz/server_corpus/260ef2d666d03e5451109135b50cbd9657fc6964 new file mode 100644 index 0000000000..aabacf0042 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/260ef2d666d03e5451109135b50cbd9657fc6964 differ diff --git a/external/boringssl/fuzz/server_corpus/2694758ce91a4233066ec157880fec851c16c59b b/external/boringssl/fuzz/server_corpus/2694758ce91a4233066ec157880fec851c16c59b new file mode 100644 index 0000000000..4231b08e99 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/2694758ce91a4233066ec157880fec851c16c59b differ diff --git a/external/boringssl/fuzz/server_corpus/26962d40bfb0f49cdded97cc981d789e4699b08c b/external/boringssl/fuzz/server_corpus/26962d40bfb0f49cdded97cc981d789e4699b08c new file mode 100644 index 0000000000..40eb60116c Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/26962d40bfb0f49cdded97cc981d789e4699b08c differ diff --git a/external/boringssl/fuzz/server_corpus/27e55ccf7c64899aeb1011629cd1edc492730dff b/external/boringssl/fuzz/server_corpus/27e55ccf7c64899aeb1011629cd1edc492730dff new file mode 100644 index 0000000000..684e987806 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/27e55ccf7c64899aeb1011629cd1edc492730dff differ diff --git a/external/boringssl/fuzz/server_corpus/280376c0907c566a201a131ab01e567aca85513a b/external/boringssl/fuzz/server_corpus/280376c0907c566a201a131ab01e567aca85513a new file mode 100644 index 0000000000..2530dc261f Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/280376c0907c566a201a131ab01e567aca85513a differ diff --git a/external/boringssl/fuzz/server_corpus/286456dce363ae8bf19ce6ebbf027889cdd351f3 b/external/boringssl/fuzz/server_corpus/286456dce363ae8bf19ce6ebbf027889cdd351f3 new file mode 100644 index 0000000000..d211553d9f Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/286456dce363ae8bf19ce6ebbf027889cdd351f3 differ diff --git a/external/boringssl/fuzz/server_corpus/28bd4185ae535c2d6bc9d848db4b4039e60dcfa7 b/external/boringssl/fuzz/server_corpus/28bd4185ae535c2d6bc9d848db4b4039e60dcfa7 new file mode 100644 index 0000000000..7224206539 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/28bd4185ae535c2d6bc9d848db4b4039e60dcfa7 differ diff --git a/external/boringssl/fuzz/server_corpus/29000511dd6707b7e8c7f10ed70340e1391dd3c3 b/external/boringssl/fuzz/server_corpus/29000511dd6707b7e8c7f10ed70340e1391dd3c3 new file mode 100644 index 0000000000..371ebbffb0 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/29000511dd6707b7e8c7f10ed70340e1391dd3c3 differ diff --git a/external/boringssl/fuzz/server_corpus/298752b8d5f8cae623a95764289da5f0d94afb24 b/external/boringssl/fuzz/server_corpus/298752b8d5f8cae623a95764289da5f0d94afb24 new file mode 100644 index 0000000000..5c717a8956 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/298752b8d5f8cae623a95764289da5f0d94afb24 differ diff --git a/external/boringssl/fuzz/server_corpus/298ee587ceb3e7685ab165fee56780031113c766 b/external/boringssl/fuzz/server_corpus/298ee587ceb3e7685ab165fee56780031113c766 new file mode 100644 index 0000000000..551f542a74 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/298ee587ceb3e7685ab165fee56780031113c766 differ diff --git a/external/boringssl/fuzz/server_corpus/2badd38a1ebbaccd61bfdc3d79e1f79f585ed390 b/external/boringssl/fuzz/server_corpus/2badd38a1ebbaccd61bfdc3d79e1f79f585ed390 new file mode 100644 index 0000000000..014e4bd551 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/2badd38a1ebbaccd61bfdc3d79e1f79f585ed390 differ diff --git a/external/boringssl/fuzz/server_corpus/2c79975ee52b16aa14b8faaaf43eccfac72f4651 b/external/boringssl/fuzz/server_corpus/2c79975ee52b16aa14b8faaaf43eccfac72f4651 new file mode 100644 index 0000000000..c9a38a67a8 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/2c79975ee52b16aa14b8faaaf43eccfac72f4651 differ diff --git a/external/boringssl/fuzz/server_corpus/2d85badb9e3e4c1639e2a895d5cf9a864ba5ce17 b/external/boringssl/fuzz/server_corpus/2d85badb9e3e4c1639e2a895d5cf9a864ba5ce17 new file mode 100644 index 0000000000..13a210fe21 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/2d85badb9e3e4c1639e2a895d5cf9a864ba5ce17 differ diff --git a/external/boringssl/fuzz/server_corpus/2de59b00466c89d774e8dbf353761c4611d65e2a b/external/boringssl/fuzz/server_corpus/2de59b00466c89d774e8dbf353761c4611d65e2a new file mode 100644 index 0000000000..0d7869c56e Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/2de59b00466c89d774e8dbf353761c4611d65e2a differ diff --git a/external/boringssl/fuzz/server_corpus/2e830d13eff02a0da6b6ae20ca271cb8cdbdb64a b/external/boringssl/fuzz/server_corpus/2e830d13eff02a0da6b6ae20ca271cb8cdbdb64a new file mode 100644 index 0000000000..329c0c9d25 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/2e830d13eff02a0da6b6ae20ca271cb8cdbdb64a differ diff --git a/external/boringssl/fuzz/server_corpus/30215b01f68c655988e2be5d071767adb918ab41 b/external/boringssl/fuzz/server_corpus/30215b01f68c655988e2be5d071767adb918ab41 new file mode 100644 index 0000000000..894d17bb21 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/30215b01f68c655988e2be5d071767adb918ab41 differ diff --git a/external/boringssl/fuzz/server_corpus/302f9b349fc7d906fd38893a85431925e319508e b/external/boringssl/fuzz/server_corpus/302f9b349fc7d906fd38893a85431925e319508e new file mode 100644 index 0000000000..cd93906b07 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/302f9b349fc7d906fd38893a85431925e319508e differ diff --git a/external/boringssl/fuzz/server_corpus/317bc318af6286bf0ac2d679d3518b12b75c49e7 b/external/boringssl/fuzz/server_corpus/317bc318af6286bf0ac2d679d3518b12b75c49e7 new file mode 100644 index 0000000000..629c966d34 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/317bc318af6286bf0ac2d679d3518b12b75c49e7 differ diff --git a/external/boringssl/fuzz/server_corpus/31f6f995d8cbf4291e5197d421e78de61bcf53dc b/external/boringssl/fuzz/server_corpus/31f6f995d8cbf4291e5197d421e78de61bcf53dc new file mode 100644 index 0000000000..8465bcd3e0 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/31f6f995d8cbf4291e5197d421e78de61bcf53dc differ diff --git a/external/boringssl/fuzz/server_corpus/31fce22e8c242afcd1c122dd1623c77e0b1b4a0d b/external/boringssl/fuzz/server_corpus/31fce22e8c242afcd1c122dd1623c77e0b1b4a0d new file mode 100644 index 0000000000..5b20fb65a4 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/31fce22e8c242afcd1c122dd1623c77e0b1b4a0d differ diff --git a/external/boringssl/fuzz/server_corpus/32302b428fdb884e4de50171bf7897354ee35ee3 b/external/boringssl/fuzz/server_corpus/32302b428fdb884e4de50171bf7897354ee35ee3 new file mode 100644 index 0000000000..4c92569df2 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/32302b428fdb884e4de50171bf7897354ee35ee3 differ diff --git a/external/boringssl/fuzz/server_corpus/324bf110726da4cf6de7bb28a0b2a99dac045768 b/external/boringssl/fuzz/server_corpus/324bf110726da4cf6de7bb28a0b2a99dac045768 new file mode 100644 index 0000000000..56f81e75a0 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/324bf110726da4cf6de7bb28a0b2a99dac045768 differ diff --git a/external/boringssl/fuzz/server_corpus/32cf502f739bb71624940b06ce964422a175b6da b/external/boringssl/fuzz/server_corpus/32cf502f739bb71624940b06ce964422a175b6da new file mode 100644 index 0000000000..6610efcaa5 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/32cf502f739bb71624940b06ce964422a175b6da differ diff --git a/external/boringssl/fuzz/server_corpus/32d38a0276c734a25c88823b79710dafce4721f9 b/external/boringssl/fuzz/server_corpus/32d38a0276c734a25c88823b79710dafce4721f9 new file mode 100644 index 0000000000..a7d29e8941 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/32d38a0276c734a25c88823b79710dafce4721f9 differ diff --git a/external/boringssl/fuzz/server_corpus/337d50236ca01f8e660527e1c7f1190188cc5af9 b/external/boringssl/fuzz/server_corpus/337d50236ca01f8e660527e1c7f1190188cc5af9 new file mode 100644 index 0000000000..62a538a7ab Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/337d50236ca01f8e660527e1c7f1190188cc5af9 differ diff --git a/external/boringssl/fuzz/server_corpus/34b4eb249c57036a82496931b7823a8abffbfe43 b/external/boringssl/fuzz/server_corpus/34b4eb249c57036a82496931b7823a8abffbfe43 new file mode 100644 index 0000000000..07b0690ebd Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/34b4eb249c57036a82496931b7823a8abffbfe43 differ diff --git a/external/boringssl/fuzz/server_corpus/34f2704805423aee640b1ad1fefb54ff5c49bf7c b/external/boringssl/fuzz/server_corpus/34f2704805423aee640b1ad1fefb54ff5c49bf7c new file mode 100644 index 0000000000..a16ba3d1ec Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/34f2704805423aee640b1ad1fefb54ff5c49bf7c differ diff --git a/external/boringssl/fuzz/server_corpus/3593bd1cfd62ca2f53432dd7444b452e1d7c7206 b/external/boringssl/fuzz/server_corpus/3593bd1cfd62ca2f53432dd7444b452e1d7c7206 new file mode 100644 index 0000000000..f9b79dc493 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/3593bd1cfd62ca2f53432dd7444b452e1d7c7206 differ diff --git a/external/boringssl/fuzz/server_corpus/35fe7fd7c3ee1858cec80fef8f18bb5c5da5dcd3 b/external/boringssl/fuzz/server_corpus/35fe7fd7c3ee1858cec80fef8f18bb5c5da5dcd3 new file mode 100644 index 0000000000..35e2d47e21 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/35fe7fd7c3ee1858cec80fef8f18bb5c5da5dcd3 differ diff --git a/external/boringssl/fuzz/server_corpus/360b997587a9c6f4773e1ccc2f56a3e60d7d6b1c b/external/boringssl/fuzz/server_corpus/360b997587a9c6f4773e1ccc2f56a3e60d7d6b1c new file mode 100644 index 0000000000..dbf1bbc8c5 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/360b997587a9c6f4773e1ccc2f56a3e60d7d6b1c differ diff --git a/external/boringssl/fuzz/server_corpus/364ff4d7992806bf179b156ab465400e46fa515d b/external/boringssl/fuzz/server_corpus/364ff4d7992806bf179b156ab465400e46fa515d new file mode 100644 index 0000000000..8b24b7dcb7 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/364ff4d7992806bf179b156ab465400e46fa515d differ diff --git a/external/boringssl/fuzz/server_corpus/3697165cd5d8c192e32be9f6f62fb514910fd1e3 b/external/boringssl/fuzz/server_corpus/3697165cd5d8c192e32be9f6f62fb514910fd1e3 new file mode 100644 index 0000000000..c0ec1c1375 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/3697165cd5d8c192e32be9f6f62fb514910fd1e3 differ diff --git a/external/boringssl/fuzz/server_corpus/37826e5324f024632f3fe4d6aeb6c5e0cd33b770 b/external/boringssl/fuzz/server_corpus/37826e5324f024632f3fe4d6aeb6c5e0cd33b770 new file mode 100644 index 0000000000..f598c540fe Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/37826e5324f024632f3fe4d6aeb6c5e0cd33b770 differ diff --git a/external/boringssl/fuzz/server_corpus/3791653050209ed3d11f6749e0d8e874fdc68b89 b/external/boringssl/fuzz/server_corpus/3791653050209ed3d11f6749e0d8e874fdc68b89 new file mode 100644 index 0000000000..058393a7fb Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/3791653050209ed3d11f6749e0d8e874fdc68b89 differ diff --git a/external/boringssl/fuzz/server_corpus/37a863dd9c47ee54937c65c6e43ee95667808661 b/external/boringssl/fuzz/server_corpus/37a863dd9c47ee54937c65c6e43ee95667808661 new file mode 100644 index 0000000000..963a68609f Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/37a863dd9c47ee54937c65c6e43ee95667808661 differ diff --git a/external/boringssl/fuzz/server_corpus/38fb26179fe6db37a43708ebc02df87cfe01fd14 b/external/boringssl/fuzz/server_corpus/38fb26179fe6db37a43708ebc02df87cfe01fd14 new file mode 100644 index 0000000000..0ea0d46ed1 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/38fb26179fe6db37a43708ebc02df87cfe01fd14 differ diff --git a/external/boringssl/fuzz/server_corpus/3928f49b93a191a465e788af538a969278c14823 b/external/boringssl/fuzz/server_corpus/3928f49b93a191a465e788af538a969278c14823 new file mode 100644 index 0000000000..883a91ba9f Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/3928f49b93a191a465e788af538a969278c14823 differ diff --git a/external/boringssl/fuzz/server_corpus/397b7e5b1afb2f886fa46fe47e3340e9e25db74b b/external/boringssl/fuzz/server_corpus/397b7e5b1afb2f886fa46fe47e3340e9e25db74b new file mode 100644 index 0000000000..1937185d8a Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/397b7e5b1afb2f886fa46fe47e3340e9e25db74b differ diff --git a/external/boringssl/fuzz/server_corpus/399976c7723f20941ac86dfbc66090453e496528 b/external/boringssl/fuzz/server_corpus/399976c7723f20941ac86dfbc66090453e496528 new file mode 100644 index 0000000000..577cc6d9d9 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/399976c7723f20941ac86dfbc66090453e496528 differ diff --git a/external/boringssl/fuzz/server_corpus/39d8e38c9f3e5c310068ca78d532c61c4dbb7f5e b/external/boringssl/fuzz/server_corpus/39d8e38c9f3e5c310068ca78d532c61c4dbb7f5e new file mode 100644 index 0000000000..f4ebdd5152 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/39d8e38c9f3e5c310068ca78d532c61c4dbb7f5e differ diff --git a/external/boringssl/fuzz/server_corpus/3aaf48199b093ba93f0e1ddf972782cc99e613d2 b/external/boringssl/fuzz/server_corpus/3aaf48199b093ba93f0e1ddf972782cc99e613d2 new file mode 100644 index 0000000000..8aa09bb90d Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/3aaf48199b093ba93f0e1ddf972782cc99e613d2 differ diff --git a/external/boringssl/fuzz/server_corpus/3aec20067842293ca181d1c98b1caad6b10153c1 b/external/boringssl/fuzz/server_corpus/3aec20067842293ca181d1c98b1caad6b10153c1 new file mode 100644 index 0000000000..67d5849a2c Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/3aec20067842293ca181d1c98b1caad6b10153c1 differ diff --git a/external/boringssl/fuzz/server_corpus/3c4f860903933d2305eb9ce4eaf53144d79c5843 b/external/boringssl/fuzz/server_corpus/3c4f860903933d2305eb9ce4eaf53144d79c5843 new file mode 100644 index 0000000000..209a0ff3e6 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/3c4f860903933d2305eb9ce4eaf53144d79c5843 differ diff --git a/external/boringssl/fuzz/server_corpus/3cbf37bfdfe9dd100367e512ba6298dfba7bf294 b/external/boringssl/fuzz/server_corpus/3cbf37bfdfe9dd100367e512ba6298dfba7bf294 new file mode 100644 index 0000000000..9a7cc9a157 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/3cbf37bfdfe9dd100367e512ba6298dfba7bf294 differ diff --git a/external/boringssl/fuzz/server_corpus/3d1a07692bc1687bfe9d4ee6f54811578fc54884 b/external/boringssl/fuzz/server_corpus/3d1a07692bc1687bfe9d4ee6f54811578fc54884 new file mode 100644 index 0000000000..cb28091e94 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/3d1a07692bc1687bfe9d4ee6f54811578fc54884 differ diff --git a/external/boringssl/fuzz/server_corpus/3e71382d2831304e50054a0175baf664fae49608 b/external/boringssl/fuzz/server_corpus/3e71382d2831304e50054a0175baf664fae49608 new file mode 100644 index 0000000000..f9658818fa Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/3e71382d2831304e50054a0175baf664fae49608 differ diff --git a/external/boringssl/fuzz/server_corpus/3f66254e9c33487a194952aef2b4b38cae181ff7 b/external/boringssl/fuzz/server_corpus/3f66254e9c33487a194952aef2b4b38cae181ff7 new file mode 100644 index 0000000000..68be63be2b Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/3f66254e9c33487a194952aef2b4b38cae181ff7 differ diff --git a/external/boringssl/fuzz/server_corpus/40ce675771c2d778f8c746a5d0adc41d6236ecf9 b/external/boringssl/fuzz/server_corpus/40ce675771c2d778f8c746a5d0adc41d6236ecf9 new file mode 100644 index 0000000000..6d133f20d0 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/40ce675771c2d778f8c746a5d0adc41d6236ecf9 differ diff --git a/external/boringssl/fuzz/server_corpus/4108e3cf35e8e7bffe615ed6c1f898df52ac5fb9 b/external/boringssl/fuzz/server_corpus/4108e3cf35e8e7bffe615ed6c1f898df52ac5fb9 new file mode 100644 index 0000000000..a39b6bde38 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/4108e3cf35e8e7bffe615ed6c1f898df52ac5fb9 differ diff --git a/external/boringssl/fuzz/server_corpus/41aa254eb9cf327e23976ad968de5f6c6fd41929 b/external/boringssl/fuzz/server_corpus/41aa254eb9cf327e23976ad968de5f6c6fd41929 new file mode 100644 index 0000000000..fcd824205a Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/41aa254eb9cf327e23976ad968de5f6c6fd41929 differ diff --git a/external/boringssl/fuzz/server_corpus/41b3e56ab8d7752ea12fb170efdc8318f822a384 b/external/boringssl/fuzz/server_corpus/41b3e56ab8d7752ea12fb170efdc8318f822a384 new file mode 100644 index 0000000000..4a55d1497f Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/41b3e56ab8d7752ea12fb170efdc8318f822a384 differ diff --git a/external/boringssl/fuzz/server_corpus/41fddbda3d28306beb8045d74be6c048c8d95a44 b/external/boringssl/fuzz/server_corpus/41fddbda3d28306beb8045d74be6c048c8d95a44 new file mode 100644 index 0000000000..65de38efe5 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/41fddbda3d28306beb8045d74be6c048c8d95a44 differ diff --git a/external/boringssl/fuzz/server_corpus/435e84066c2a010e52c2452852816bf2ac8ab348 b/external/boringssl/fuzz/server_corpus/435e84066c2a010e52c2452852816bf2ac8ab348 new file mode 100644 index 0000000000..8cd9757d07 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/435e84066c2a010e52c2452852816bf2ac8ab348 differ diff --git a/external/boringssl/fuzz/server_corpus/448cdd2ee6d4f30585785ee406d7a5be76783814 b/external/boringssl/fuzz/server_corpus/448cdd2ee6d4f30585785ee406d7a5be76783814 new file mode 100644 index 0000000000..53cdafedea Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/448cdd2ee6d4f30585785ee406d7a5be76783814 differ diff --git a/external/boringssl/fuzz/server_corpus/45331d2e2c0f21e6f070d26e381bd0fa0c82ab81 b/external/boringssl/fuzz/server_corpus/45331d2e2c0f21e6f070d26e381bd0fa0c82ab81 new file mode 100644 index 0000000000..04ae71e27e Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/45331d2e2c0f21e6f070d26e381bd0fa0c82ab81 differ diff --git a/external/boringssl/fuzz/server_corpus/458469682e541e27218f68140b3ec5e08a160907 b/external/boringssl/fuzz/server_corpus/458469682e541e27218f68140b3ec5e08a160907 new file mode 100644 index 0000000000..c15ad9fd98 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/458469682e541e27218f68140b3ec5e08a160907 differ diff --git a/external/boringssl/fuzz/server_corpus/45c8ed787ce862a29bbef404b84fd672d4e44c02 b/external/boringssl/fuzz/server_corpus/45c8ed787ce862a29bbef404b84fd672d4e44c02 new file mode 100644 index 0000000000..8b3f1a1b49 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/45c8ed787ce862a29bbef404b84fd672d4e44c02 differ diff --git a/external/boringssl/fuzz/server_corpus/463538114921dd033e2b968874a8d0103d8a0550 b/external/boringssl/fuzz/server_corpus/463538114921dd033e2b968874a8d0103d8a0550 new file mode 100644 index 0000000000..9e9060f871 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/463538114921dd033e2b968874a8d0103d8a0550 differ diff --git a/external/boringssl/fuzz/server_corpus/463b9a9c1edafa2d42b1b0dbd9390186002eb775 b/external/boringssl/fuzz/server_corpus/463b9a9c1edafa2d42b1b0dbd9390186002eb775 new file mode 100644 index 0000000000..213c0be4e3 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/463b9a9c1edafa2d42b1b0dbd9390186002eb775 differ diff --git a/external/boringssl/fuzz/server_corpus/480fdad19f48ccb66c79e4daad4bf4c189334d76 b/external/boringssl/fuzz/server_corpus/480fdad19f48ccb66c79e4daad4bf4c189334d76 new file mode 100644 index 0000000000..49318771db Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/480fdad19f48ccb66c79e4daad4bf4c189334d76 differ diff --git a/external/boringssl/fuzz/server_corpus/492a81af49a5a0f6e88192f8d8a6212bb15671f6 b/external/boringssl/fuzz/server_corpus/492a81af49a5a0f6e88192f8d8a6212bb15671f6 new file mode 100644 index 0000000000..001de81ab0 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/492a81af49a5a0f6e88192f8d8a6212bb15671f6 differ diff --git a/external/boringssl/fuzz/server_corpus/499f80ae1a49f344f6ea00678211e0bc08339451 b/external/boringssl/fuzz/server_corpus/499f80ae1a49f344f6ea00678211e0bc08339451 new file mode 100644 index 0000000000..0b9e52fcb0 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/499f80ae1a49f344f6ea00678211e0bc08339451 differ diff --git a/external/boringssl/fuzz/server_corpus/49c09c1aa90fb1879802f348f2564c7a67f07f61 b/external/boringssl/fuzz/server_corpus/49c09c1aa90fb1879802f348f2564c7a67f07f61 new file mode 100644 index 0000000000..0e65d7b86a Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/49c09c1aa90fb1879802f348f2564c7a67f07f61 differ diff --git a/external/boringssl/fuzz/server_corpus/49d88822047d201e1ffc6759e61a917886c899c5 b/external/boringssl/fuzz/server_corpus/49d88822047d201e1ffc6759e61a917886c899c5 new file mode 100644 index 0000000000..e73f0a22b8 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/49d88822047d201e1ffc6759e61a917886c899c5 differ diff --git a/external/boringssl/fuzz/server_corpus/4a33f80e3245dbac94867a309485514038284345 b/external/boringssl/fuzz/server_corpus/4a33f80e3245dbac94867a309485514038284345 new file mode 100644 index 0000000000..4251d551fc Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/4a33f80e3245dbac94867a309485514038284345 differ diff --git a/external/boringssl/fuzz/server_corpus/4b2338c4375e3dc2e6a1aa3684de4a163f7c83c1 b/external/boringssl/fuzz/server_corpus/4b2338c4375e3dc2e6a1aa3684de4a163f7c83c1 new file mode 100644 index 0000000000..4f46103df8 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/4b2338c4375e3dc2e6a1aa3684de4a163f7c83c1 differ diff --git a/external/boringssl/fuzz/server_corpus/4b8a432fa4bf47f45d9c2ed257f0a958fcc94f9c b/external/boringssl/fuzz/server_corpus/4b8a432fa4bf47f45d9c2ed257f0a958fcc94f9c new file mode 100644 index 0000000000..c510272e01 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/4b8a432fa4bf47f45d9c2ed257f0a958fcc94f9c differ diff --git a/external/boringssl/fuzz/server_corpus/4c19babb1cd203839c0849f977058b7eaddf39be b/external/boringssl/fuzz/server_corpus/4c19babb1cd203839c0849f977058b7eaddf39be new file mode 100644 index 0000000000..5b1f7bdab8 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/4c19babb1cd203839c0849f977058b7eaddf39be differ diff --git a/external/boringssl/fuzz/server_corpus/4c948e8277af54d8f79adf1fc5f748f51f2f99dd b/external/boringssl/fuzz/server_corpus/4c948e8277af54d8f79adf1fc5f748f51f2f99dd new file mode 100644 index 0000000000..e9e7ef25c0 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/4c948e8277af54d8f79adf1fc5f748f51f2f99dd differ diff --git a/external/boringssl/fuzz/server_corpus/50a4c64c532174353794ca054ad60e30ef25110d b/external/boringssl/fuzz/server_corpus/50a4c64c532174353794ca054ad60e30ef25110d new file mode 100644 index 0000000000..b22804bcda Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/50a4c64c532174353794ca054ad60e30ef25110d differ diff --git a/external/boringssl/fuzz/server_corpus/50bb213c61033f9305b0bd3828c72505ec6a1caa b/external/boringssl/fuzz/server_corpus/50bb213c61033f9305b0bd3828c72505ec6a1caa new file mode 100644 index 0000000000..43326c51aa Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/50bb213c61033f9305b0bd3828c72505ec6a1caa differ diff --git a/external/boringssl/fuzz/server_corpus/50edce6beb7be88fd0fec26d84bc2706432adccd b/external/boringssl/fuzz/server_corpus/50edce6beb7be88fd0fec26d84bc2706432adccd new file mode 100644 index 0000000000..6cb9faefa8 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/50edce6beb7be88fd0fec26d84bc2706432adccd differ diff --git a/external/boringssl/fuzz/server_corpus/522d6829d952b1611ed141de5d2b500e95f46133 b/external/boringssl/fuzz/server_corpus/522d6829d952b1611ed141de5d2b500e95f46133 new file mode 100644 index 0000000000..2942b3a02a Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/522d6829d952b1611ed141de5d2b500e95f46133 differ diff --git a/external/boringssl/fuzz/server_corpus/52a47ded2085baa31ad7c7ef5b8f5fd7d124bf72 b/external/boringssl/fuzz/server_corpus/52a47ded2085baa31ad7c7ef5b8f5fd7d124bf72 new file mode 100644 index 0000000000..359fd8fc99 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/52a47ded2085baa31ad7c7ef5b8f5fd7d124bf72 differ diff --git a/external/boringssl/fuzz/server_corpus/52bd453551c468e4fa1503fb4b113d6b143dc553 b/external/boringssl/fuzz/server_corpus/52bd453551c468e4fa1503fb4b113d6b143dc553 new file mode 100644 index 0000000000..b07a9cd698 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/52bd453551c468e4fa1503fb4b113d6b143dc553 differ diff --git a/external/boringssl/fuzz/server_corpus/530aeb352e1f3e82138f4a3325463ab8738ee045 b/external/boringssl/fuzz/server_corpus/530aeb352e1f3e82138f4a3325463ab8738ee045 new file mode 100644 index 0000000000..e268ecc967 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/530aeb352e1f3e82138f4a3325463ab8738ee045 differ diff --git a/external/boringssl/fuzz/server_corpus/545801d21d7321adfc5e2fec30ad21125c612bbf b/external/boringssl/fuzz/server_corpus/545801d21d7321adfc5e2fec30ad21125c612bbf new file mode 100644 index 0000000000..699da8e2d3 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/545801d21d7321adfc5e2fec30ad21125c612bbf differ diff --git a/external/boringssl/fuzz/server_corpus/557f33e444c12f4ae11cbed2463509e2b76c4838 b/external/boringssl/fuzz/server_corpus/557f33e444c12f4ae11cbed2463509e2b76c4838 new file mode 100644 index 0000000000..52130fa881 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/557f33e444c12f4ae11cbed2463509e2b76c4838 differ diff --git a/external/boringssl/fuzz/server_corpus/5686ea1bd2b626e81ca079482a81c4133a589e0d b/external/boringssl/fuzz/server_corpus/5686ea1bd2b626e81ca079482a81c4133a589e0d new file mode 100644 index 0000000000..d743fc3f92 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/5686ea1bd2b626e81ca079482a81c4133a589e0d differ diff --git a/external/boringssl/fuzz/server_corpus/57779cd03374bd1ffb254ee0749d437108879a28 b/external/boringssl/fuzz/server_corpus/57779cd03374bd1ffb254ee0749d437108879a28 new file mode 100644 index 0000000000..0667ef2b19 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/57779cd03374bd1ffb254ee0749d437108879a28 differ diff --git a/external/boringssl/fuzz/server_corpus/57bed14657b0ba761b67f5663af6dbcf891e06cd b/external/boringssl/fuzz/server_corpus/57bed14657b0ba761b67f5663af6dbcf891e06cd new file mode 100644 index 0000000000..d345376f5d Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/57bed14657b0ba761b67f5663af6dbcf891e06cd differ diff --git a/external/boringssl/fuzz/server_corpus/58080a322d37e7d8cb9fa7585be92689a971ffd6 b/external/boringssl/fuzz/server_corpus/58080a322d37e7d8cb9fa7585be92689a971ffd6 new file mode 100644 index 0000000000..a4005344d8 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/58080a322d37e7d8cb9fa7585be92689a971ffd6 differ diff --git a/external/boringssl/fuzz/server_corpus/59849e9352267bb6c79fe78960a8369797da6281 b/external/boringssl/fuzz/server_corpus/59849e9352267bb6c79fe78960a8369797da6281 new file mode 100644 index 0000000000..e6f1b1cab5 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/59849e9352267bb6c79fe78960a8369797da6281 differ diff --git a/external/boringssl/fuzz/server_corpus/5a09520c67133379b720d9b4aa549e6a4f76b604 b/external/boringssl/fuzz/server_corpus/5a09520c67133379b720d9b4aa549e6a4f76b604 new file mode 100644 index 0000000000..317480978d Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/5a09520c67133379b720d9b4aa549e6a4f76b604 differ diff --git a/external/boringssl/fuzz/server_corpus/5b492ed27785260ed00654e71e9b272071618fc8 b/external/boringssl/fuzz/server_corpus/5b492ed27785260ed00654e71e9b272071618fc8 new file mode 100644 index 0000000000..3a9a0ba677 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/5b492ed27785260ed00654e71e9b272071618fc8 differ diff --git a/external/boringssl/fuzz/server_corpus/5b598ddf2bc6d1b376c733a935306e45cb247879 b/external/boringssl/fuzz/server_corpus/5b598ddf2bc6d1b376c733a935306e45cb247879 new file mode 100644 index 0000000000..d1a5ae5eec Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/5b598ddf2bc6d1b376c733a935306e45cb247879 differ diff --git a/external/boringssl/fuzz/server_corpus/5bef1a165880066972ce67fc28c01f46bc306e6b b/external/boringssl/fuzz/server_corpus/5bef1a165880066972ce67fc28c01f46bc306e6b new file mode 100644 index 0000000000..ebc94a551c --- /dev/null +++ b/external/boringssl/fuzz/server_corpus/5bef1a165880066972ce67fc28c01f46bc306e6b @@ -0,0 +1 @@ +€)(:q* \ No newline at end of file diff --git a/external/boringssl/fuzz/server_corpus/5ed11035d4c1eb0685d4b4aa9e153e0b394b8f7a b/external/boringssl/fuzz/server_corpus/5ed11035d4c1eb0685d4b4aa9e153e0b394b8f7a new file mode 100644 index 0000000000..218ac16a55 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/5ed11035d4c1eb0685d4b4aa9e153e0b394b8f7a differ diff --git a/external/boringssl/fuzz/server_corpus/5edf5a17f9862feb006b9400cafed2843ff80adf b/external/boringssl/fuzz/server_corpus/5edf5a17f9862feb006b9400cafed2843ff80adf new file mode 100644 index 0000000000..eb5fa11299 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/5edf5a17f9862feb006b9400cafed2843ff80adf differ diff --git a/external/boringssl/fuzz/server_corpus/5f05a5fac8c767208fcfc64dd55ac78c24bf4ea0 b/external/boringssl/fuzz/server_corpus/5f05a5fac8c767208fcfc64dd55ac78c24bf4ea0 new file mode 100644 index 0000000000..fcc90d98aa Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/5f05a5fac8c767208fcfc64dd55ac78c24bf4ea0 differ diff --git a/external/boringssl/fuzz/server_corpus/5f25cbe4c0e5b376a9b8c1b820c448fe5915c8a8 b/external/boringssl/fuzz/server_corpus/5f25cbe4c0e5b376a9b8c1b820c448fe5915c8a8 new file mode 100644 index 0000000000..8baefef1ba Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/5f25cbe4c0e5b376a9b8c1b820c448fe5915c8a8 differ diff --git a/external/boringssl/fuzz/server_corpus/5f70e0ee2f616a7b4bbb743a9b1b91517bc3f057 b/external/boringssl/fuzz/server_corpus/5f70e0ee2f616a7b4bbb743a9b1b91517bc3f057 new file mode 100644 index 0000000000..88a3d6914b Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/5f70e0ee2f616a7b4bbb743a9b1b91517bc3f057 differ diff --git a/external/boringssl/fuzz/server_corpus/6040b1427656967d16ff771db3d32ecc5ec579f9 b/external/boringssl/fuzz/server_corpus/6040b1427656967d16ff771db3d32ecc5ec579f9 new file mode 100644 index 0000000000..5147a5e518 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/6040b1427656967d16ff771db3d32ecc5ec579f9 differ diff --git a/external/boringssl/fuzz/server_corpus/60b3caaf413cf16a1bbb4741cdbbe66259540902 b/external/boringssl/fuzz/server_corpus/60b3caaf413cf16a1bbb4741cdbbe66259540902 new file mode 100644 index 0000000000..ca4283ae2a Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/60b3caaf413cf16a1bbb4741cdbbe66259540902 differ diff --git a/external/boringssl/fuzz/server_corpus/610e3905ae7cbfb26c383c894489c45fddcc644e b/external/boringssl/fuzz/server_corpus/610e3905ae7cbfb26c383c894489c45fddcc644e new file mode 100644 index 0000000000..9311b157be Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/610e3905ae7cbfb26c383c894489c45fddcc644e differ diff --git a/external/boringssl/fuzz/server_corpus/61d0f602fbb64038787d3c79591a4673f84d591f b/external/boringssl/fuzz/server_corpus/61d0f602fbb64038787d3c79591a4673f84d591f new file mode 100644 index 0000000000..b649ff11f7 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/61d0f602fbb64038787d3c79591a4673f84d591f differ diff --git a/external/boringssl/fuzz/server_corpus/6288b112228f24ecbe24c87d06698e244e15a7ee b/external/boringssl/fuzz/server_corpus/6288b112228f24ecbe24c87d06698e244e15a7ee new file mode 100644 index 0000000000..d4d6b86cab Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/6288b112228f24ecbe24c87d06698e244e15a7ee differ diff --git a/external/boringssl/fuzz/server_corpus/630800205061e44da8f2a98f73192b6c02ac2cda b/external/boringssl/fuzz/server_corpus/630800205061e44da8f2a98f73192b6c02ac2cda new file mode 100644 index 0000000000..6279ce2f9f Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/630800205061e44da8f2a98f73192b6c02ac2cda differ diff --git a/external/boringssl/fuzz/server_corpus/63103eb0da3c238ad20edd649bc2e0ff1d65d485 b/external/boringssl/fuzz/server_corpus/63103eb0da3c238ad20edd649bc2e0ff1d65d485 new file mode 100644 index 0000000000..9f7446b290 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/63103eb0da3c238ad20edd649bc2e0ff1d65d485 differ diff --git a/external/boringssl/fuzz/server_corpus/63ed349b02542d6a86a6dc2cbbfad610f9c3e8ea b/external/boringssl/fuzz/server_corpus/63ed349b02542d6a86a6dc2cbbfad610f9c3e8ea new file mode 100644 index 0000000000..a472e6666d Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/63ed349b02542d6a86a6dc2cbbfad610f9c3e8ea differ diff --git a/external/boringssl/fuzz/server_corpus/6427c33410538cfa3263291caefc5fef483baee3 b/external/boringssl/fuzz/server_corpus/6427c33410538cfa3263291caefc5fef483baee3 new file mode 100644 index 0000000000..cc47908a0d Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/6427c33410538cfa3263291caefc5fef483baee3 differ diff --git a/external/boringssl/fuzz/server_corpus/64b9b46b076ce2b5c3f9d4958cf292e0e55b5be7 b/external/boringssl/fuzz/server_corpus/64b9b46b076ce2b5c3f9d4958cf292e0e55b5be7 new file mode 100644 index 0000000000..fa3fd11591 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/64b9b46b076ce2b5c3f9d4958cf292e0e55b5be7 differ diff --git a/external/boringssl/fuzz/server_corpus/65ee094875fb0e661e0a83872c5ef2a2b96456d3 b/external/boringssl/fuzz/server_corpus/65ee094875fb0e661e0a83872c5ef2a2b96456d3 new file mode 100644 index 0000000000..f109c693b4 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/65ee094875fb0e661e0a83872c5ef2a2b96456d3 differ diff --git a/external/boringssl/fuzz/server_corpus/663aac853a26b5b7d366b1084fa0b89e8c1042c7 b/external/boringssl/fuzz/server_corpus/663aac853a26b5b7d366b1084fa0b89e8c1042c7 new file mode 100644 index 0000000000..1a04dee5af Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/663aac853a26b5b7d366b1084fa0b89e8c1042c7 differ diff --git a/external/boringssl/fuzz/server_corpus/6804200e6128651336b64a491deff4c045edea10 b/external/boringssl/fuzz/server_corpus/6804200e6128651336b64a491deff4c045edea10 new file mode 100644 index 0000000000..5c2a80d72e Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/6804200e6128651336b64a491deff4c045edea10 differ diff --git a/external/boringssl/fuzz/server_corpus/68ed9e990a43456def6c94ea616668f5d17d739f b/external/boringssl/fuzz/server_corpus/68ed9e990a43456def6c94ea616668f5d17d739f new file mode 100644 index 0000000000..b08dd29cc8 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/68ed9e990a43456def6c94ea616668f5d17d739f differ diff --git a/external/boringssl/fuzz/server_corpus/6a28ed0197ddb6f8ceb4ca87ab463fa80152db78 b/external/boringssl/fuzz/server_corpus/6a28ed0197ddb6f8ceb4ca87ab463fa80152db78 new file mode 100644 index 0000000000..45f034377d Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/6a28ed0197ddb6f8ceb4ca87ab463fa80152db78 differ diff --git a/external/boringssl/fuzz/server_corpus/6ad9e29108e9b826b4ae5ef1b6748dcaee3647bb b/external/boringssl/fuzz/server_corpus/6ad9e29108e9b826b4ae5ef1b6748dcaee3647bb new file mode 100644 index 0000000000..6401242257 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/6ad9e29108e9b826b4ae5ef1b6748dcaee3647bb differ diff --git a/external/boringssl/fuzz/server_corpus/6adff19a28e5d20cbf9cb4cc576b86718d7b02ce b/external/boringssl/fuzz/server_corpus/6adff19a28e5d20cbf9cb4cc576b86718d7b02ce new file mode 100644 index 0000000000..a929eb9214 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/6adff19a28e5d20cbf9cb4cc576b86718d7b02ce differ diff --git a/external/boringssl/fuzz/server_corpus/6afb292e0d86866ead887381e4bb95c6abbd00a7 b/external/boringssl/fuzz/server_corpus/6afb292e0d86866ead887381e4bb95c6abbd00a7 new file mode 100644 index 0000000000..7de3f898c2 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/6afb292e0d86866ead887381e4bb95c6abbd00a7 differ diff --git a/external/boringssl/fuzz/server_corpus/6ce759d9375ef41abf26be9e5f79447f9cd10753 b/external/boringssl/fuzz/server_corpus/6ce759d9375ef41abf26be9e5f79447f9cd10753 new file mode 100644 index 0000000000..873195c9b0 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/6ce759d9375ef41abf26be9e5f79447f9cd10753 differ diff --git a/external/boringssl/fuzz/server_corpus/6d77b6fa38172e6716a8faa9672364199025be5c b/external/boringssl/fuzz/server_corpus/6d77b6fa38172e6716a8faa9672364199025be5c new file mode 100644 index 0000000000..5f9a8cbe8e Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/6d77b6fa38172e6716a8faa9672364199025be5c differ diff --git a/external/boringssl/fuzz/server_corpus/6dca0b5a9175bcc8bf0da3b0efbe48fcc67aca06 b/external/boringssl/fuzz/server_corpus/6dca0b5a9175bcc8bf0da3b0efbe48fcc67aca06 new file mode 100644 index 0000000000..0bb854dccb Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/6dca0b5a9175bcc8bf0da3b0efbe48fcc67aca06 differ diff --git a/external/boringssl/fuzz/server_corpus/6de87dc2626b2b0068ba2d981665d6b366c3532c b/external/boringssl/fuzz/server_corpus/6de87dc2626b2b0068ba2d981665d6b366c3532c new file mode 100644 index 0000000000..f065dcc807 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/6de87dc2626b2b0068ba2d981665d6b366c3532c differ diff --git a/external/boringssl/fuzz/server_corpus/6eb8ee617c043084a08fd19105f897bf9a5ce7f0 b/external/boringssl/fuzz/server_corpus/6eb8ee617c043084a08fd19105f897bf9a5ce7f0 new file mode 100644 index 0000000000..708bed8da5 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/6eb8ee617c043084a08fd19105f897bf9a5ce7f0 differ diff --git a/external/boringssl/fuzz/server_corpus/6ede1a48fb0da7644f9bc8f91c9b8d717710a359 b/external/boringssl/fuzz/server_corpus/6ede1a48fb0da7644f9bc8f91c9b8d717710a359 new file mode 100644 index 0000000000..9ab40cb460 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/6ede1a48fb0da7644f9bc8f91c9b8d717710a359 differ diff --git a/external/boringssl/fuzz/server_corpus/6f65f68defc58c4e70ac774728d73df16b035890 b/external/boringssl/fuzz/server_corpus/6f65f68defc58c4e70ac774728d73df16b035890 new file mode 100644 index 0000000000..9725564311 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/6f65f68defc58c4e70ac774728d73df16b035890 differ diff --git a/external/boringssl/fuzz/server_corpus/6f89a51d7c8c7f4f467d4deda8b8d3d74711bd7a b/external/boringssl/fuzz/server_corpus/6f89a51d7c8c7f4f467d4deda8b8d3d74711bd7a new file mode 100644 index 0000000000..f7c0496827 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/6f89a51d7c8c7f4f467d4deda8b8d3d74711bd7a differ diff --git a/external/boringssl/fuzz/server_corpus/7033506106b6f14d4b73713d409503581d6d83be b/external/boringssl/fuzz/server_corpus/7033506106b6f14d4b73713d409503581d6d83be new file mode 100644 index 0000000000..d0b0a4f686 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/7033506106b6f14d4b73713d409503581d6d83be differ diff --git a/external/boringssl/fuzz/server_corpus/703da7bc1a86d25c4a719ffd8dd758eb593d151c b/external/boringssl/fuzz/server_corpus/703da7bc1a86d25c4a719ffd8dd758eb593d151c new file mode 100644 index 0000000000..916407849e Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/703da7bc1a86d25c4a719ffd8dd758eb593d151c differ diff --git a/external/boringssl/fuzz/server_corpus/706f54bf24538976566b61e852b1c4d9ae1119f4 b/external/boringssl/fuzz/server_corpus/706f54bf24538976566b61e852b1c4d9ae1119f4 new file mode 100644 index 0000000000..c0ad820cbe Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/706f54bf24538976566b61e852b1c4d9ae1119f4 differ diff --git a/external/boringssl/fuzz/server_corpus/7073f6010cff349f012670f14da7428b53755634 b/external/boringssl/fuzz/server_corpus/7073f6010cff349f012670f14da7428b53755634 new file mode 100644 index 0000000000..aab475924d Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/7073f6010cff349f012670f14da7428b53755634 differ diff --git a/external/boringssl/fuzz/server_corpus/70c37f8fac66c1b1246354d4c7236ee2dc283e5c b/external/boringssl/fuzz/server_corpus/70c37f8fac66c1b1246354d4c7236ee2dc283e5c new file mode 100644 index 0000000000..030998e2a6 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/70c37f8fac66c1b1246354d4c7236ee2dc283e5c differ diff --git a/external/boringssl/fuzz/server_corpus/743fd36937f52741a4cc0a8657203cfd02c46aad b/external/boringssl/fuzz/server_corpus/743fd36937f52741a4cc0a8657203cfd02c46aad new file mode 100644 index 0000000000..73bafa6603 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/743fd36937f52741a4cc0a8657203cfd02c46aad differ diff --git a/external/boringssl/fuzz/server_corpus/75cc89a6fd3156770999a138f3d2a050344364ad b/external/boringssl/fuzz/server_corpus/75cc89a6fd3156770999a138f3d2a050344364ad new file mode 100644 index 0000000000..12cebf4e28 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/75cc89a6fd3156770999a138f3d2a050344364ad differ diff --git a/external/boringssl/fuzz/server_corpus/75f7f0ca59f5ed0bbdb782a7e37f8fb79c7a69af b/external/boringssl/fuzz/server_corpus/75f7f0ca59f5ed0bbdb782a7e37f8fb79c7a69af new file mode 100644 index 0000000000..413b6ec3b4 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/75f7f0ca59f5ed0bbdb782a7e37f8fb79c7a69af differ diff --git a/external/boringssl/fuzz/server_corpus/77b55b3457cd7ea618c65886edf5661322f94232 b/external/boringssl/fuzz/server_corpus/77b55b3457cd7ea618c65886edf5661322f94232 new file mode 100644 index 0000000000..55de2e0f57 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/77b55b3457cd7ea618c65886edf5661322f94232 differ diff --git a/external/boringssl/fuzz/server_corpus/7a4ac7e949d3a80da8e02b5cf09aa586d5fc2c58 b/external/boringssl/fuzz/server_corpus/7a4ac7e949d3a80da8e02b5cf09aa586d5fc2c58 new file mode 100644 index 0000000000..5c4d46708b Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/7a4ac7e949d3a80da8e02b5cf09aa586d5fc2c58 differ diff --git a/external/boringssl/fuzz/server_corpus/7ad83ae355cd42307de44effef5fa238db8de93e b/external/boringssl/fuzz/server_corpus/7ad83ae355cd42307de44effef5fa238db8de93e new file mode 100644 index 0000000000..4fe9104e71 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/7ad83ae355cd42307de44effef5fa238db8de93e differ diff --git a/external/boringssl/fuzz/server_corpus/7c13a00efcf05848cca0015ec99705939bd7762d b/external/boringssl/fuzz/server_corpus/7c13a00efcf05848cca0015ec99705939bd7762d new file mode 100644 index 0000000000..052f23885a Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/7c13a00efcf05848cca0015ec99705939bd7762d differ diff --git a/external/boringssl/fuzz/server_corpus/7c1cb7d73425b8f58dc83ed2a058b28d6c8910e2 b/external/boringssl/fuzz/server_corpus/7c1cb7d73425b8f58dc83ed2a058b28d6c8910e2 new file mode 100644 index 0000000000..774c1e4859 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/7c1cb7d73425b8f58dc83ed2a058b28d6c8910e2 differ diff --git a/external/boringssl/fuzz/server_corpus/7c7edef35a80358b098ede960f7a254c2920b945 b/external/boringssl/fuzz/server_corpus/7c7edef35a80358b098ede960f7a254c2920b945 new file mode 100644 index 0000000000..a22bb13820 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/7c7edef35a80358b098ede960f7a254c2920b945 differ diff --git a/external/boringssl/fuzz/server_corpus/7c8d8a6475c235eee93a9132e3efcc2d8cf2457f b/external/boringssl/fuzz/server_corpus/7c8d8a6475c235eee93a9132e3efcc2d8cf2457f new file mode 100644 index 0000000000..69d8b6178f Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/7c8d8a6475c235eee93a9132e3efcc2d8cf2457f differ diff --git a/external/boringssl/fuzz/server_corpus/7cd231570a9a7ba088cc00447c836839564bdc71 b/external/boringssl/fuzz/server_corpus/7cd231570a9a7ba088cc00447c836839564bdc71 new file mode 100644 index 0000000000..bf68036c8c Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/7cd231570a9a7ba088cc00447c836839564bdc71 differ diff --git a/external/boringssl/fuzz/server_corpus/7d70d47487b1c99d7a154307e976905551bff147 b/external/boringssl/fuzz/server_corpus/7d70d47487b1c99d7a154307e976905551bff147 new file mode 100644 index 0000000000..eef03154bc Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/7d70d47487b1c99d7a154307e976905551bff147 differ diff --git a/external/boringssl/fuzz/server_corpus/7d7bf92eb0b77728910683eb97d356df3bcafd01 b/external/boringssl/fuzz/server_corpus/7d7bf92eb0b77728910683eb97d356df3bcafd01 new file mode 100644 index 0000000000..b88d26aad5 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/7d7bf92eb0b77728910683eb97d356df3bcafd01 differ diff --git a/external/boringssl/fuzz/server_corpus/7e1dd1d1d2f30337a345ee16662089530e19ba10 b/external/boringssl/fuzz/server_corpus/7e1dd1d1d2f30337a345ee16662089530e19ba10 new file mode 100644 index 0000000000..f4f843b346 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/7e1dd1d1d2f30337a345ee16662089530e19ba10 differ diff --git a/external/boringssl/fuzz/server_corpus/7eb254ed656a33e05bdc3def3565b7ef45d30cee b/external/boringssl/fuzz/server_corpus/7eb254ed656a33e05bdc3def3565b7ef45d30cee new file mode 100644 index 0000000000..0a4385b885 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/7eb254ed656a33e05bdc3def3565b7ef45d30cee differ diff --git a/external/boringssl/fuzz/server_corpus/7ecae41dba4999017c7282a2e17c5be94d13bb35 b/external/boringssl/fuzz/server_corpus/7ecae41dba4999017c7282a2e17c5be94d13bb35 new file mode 100644 index 0000000000..f588f54f6f Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/7ecae41dba4999017c7282a2e17c5be94d13bb35 differ diff --git a/external/boringssl/fuzz/server_corpus/7eda66afbb955d4d0c1fb9c3236aaf01bcbfcd02 b/external/boringssl/fuzz/server_corpus/7eda66afbb955d4d0c1fb9c3236aaf01bcbfcd02 new file mode 100644 index 0000000000..10abd484aa Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/7eda66afbb955d4d0c1fb9c3236aaf01bcbfcd02 differ diff --git a/external/boringssl/fuzz/server_corpus/7f762ef581bf5b21dc2b9e5d0a6f01556d02827d b/external/boringssl/fuzz/server_corpus/7f762ef581bf5b21dc2b9e5d0a6f01556d02827d new file mode 100644 index 0000000000..47534566af --- /dev/null +++ b/external/boringssl/fuzz/server_corpus/7f762ef581bf5b21dc2b9e5d0a6f01556d02827d @@ -0,0 +1 @@ +€)(:* \ No newline at end of file diff --git a/external/boringssl/fuzz/server_corpus/7fd784bcc4b1e7cca034bd5e90d013cdd5ed37fc b/external/boringssl/fuzz/server_corpus/7fd784bcc4b1e7cca034bd5e90d013cdd5ed37fc new file mode 100644 index 0000000000..0afcf0538b Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/7fd784bcc4b1e7cca034bd5e90d013cdd5ed37fc differ diff --git a/external/boringssl/fuzz/server_corpus/7ff26dd574e66a7f3425f1aa68717beb16a6943a b/external/boringssl/fuzz/server_corpus/7ff26dd574e66a7f3425f1aa68717beb16a6943a new file mode 100644 index 0000000000..d8277a1e46 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/7ff26dd574e66a7f3425f1aa68717beb16a6943a differ diff --git a/external/boringssl/fuzz/server_corpus/7ff47a645111533c4c4a5680485aebec1fc71ba2 b/external/boringssl/fuzz/server_corpus/7ff47a645111533c4c4a5680485aebec1fc71ba2 new file mode 100644 index 0000000000..592f779e7e Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/7ff47a645111533c4c4a5680485aebec1fc71ba2 differ diff --git a/external/boringssl/fuzz/server_corpus/805673ac41123503f5ec4d5a5b26d0c49751d219 b/external/boringssl/fuzz/server_corpus/805673ac41123503f5ec4d5a5b26d0c49751d219 new file mode 100644 index 0000000000..3c5ba90646 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/805673ac41123503f5ec4d5a5b26d0c49751d219 differ diff --git a/external/boringssl/fuzz/server_corpus/807e902da37bf045992967c88bdd7ef5e3311079 b/external/boringssl/fuzz/server_corpus/807e902da37bf045992967c88bdd7ef5e3311079 new file mode 100644 index 0000000000..f019d591bf Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/807e902da37bf045992967c88bdd7ef5e3311079 differ diff --git a/external/boringssl/fuzz/server_corpus/81002fc62e533b6df9bac981650d9379efa1538e b/external/boringssl/fuzz/server_corpus/81002fc62e533b6df9bac981650d9379efa1538e new file mode 100644 index 0000000000..17b689bf1f Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/81002fc62e533b6df9bac981650d9379efa1538e differ diff --git a/external/boringssl/fuzz/server_corpus/8130aa1cfff870363a58b1aed00aeddbd08e3439 b/external/boringssl/fuzz/server_corpus/8130aa1cfff870363a58b1aed00aeddbd08e3439 new file mode 100644 index 0000000000..454040c1ac Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/8130aa1cfff870363a58b1aed00aeddbd08e3439 differ diff --git a/external/boringssl/fuzz/server_corpus/815efc8337a4dafb7acac5e27f188729e794ec1a b/external/boringssl/fuzz/server_corpus/815efc8337a4dafb7acac5e27f188729e794ec1a new file mode 100644 index 0000000000..d5c676f183 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/815efc8337a4dafb7acac5e27f188729e794ec1a differ diff --git a/external/boringssl/fuzz/server_corpus/81908c24376fd3bb3e3678298583972f3bc21629 b/external/boringssl/fuzz/server_corpus/81908c24376fd3bb3e3678298583972f3bc21629 new file mode 100644 index 0000000000..c2769f71fd Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/81908c24376fd3bb3e3678298583972f3bc21629 differ diff --git a/external/boringssl/fuzz/server_corpus/81a73f364c5a7966e7fc06aa0208e16836324ff9 b/external/boringssl/fuzz/server_corpus/81a73f364c5a7966e7fc06aa0208e16836324ff9 new file mode 100644 index 0000000000..6599cd0ef6 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/81a73f364c5a7966e7fc06aa0208e16836324ff9 differ diff --git a/external/boringssl/fuzz/server_corpus/81aed319be7488358f8fbf252561c12c68f88a96 b/external/boringssl/fuzz/server_corpus/81aed319be7488358f8fbf252561c12c68f88a96 new file mode 100644 index 0000000000..edfe1e4a5e Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/81aed319be7488358f8fbf252561c12c68f88a96 differ diff --git a/external/boringssl/fuzz/server_corpus/832fd1d40a6a34cb526a2a0d51d7f98c01216e27 b/external/boringssl/fuzz/server_corpus/832fd1d40a6a34cb526a2a0d51d7f98c01216e27 new file mode 100644 index 0000000000..e337f1263c Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/832fd1d40a6a34cb526a2a0d51d7f98c01216e27 differ diff --git a/external/boringssl/fuzz/server_corpus/83a1fe57841a03e9f62e5c4c98121779d027d7f4 b/external/boringssl/fuzz/server_corpus/83a1fe57841a03e9f62e5c4c98121779d027d7f4 new file mode 100644 index 0000000000..19d848a451 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/83a1fe57841a03e9f62e5c4c98121779d027d7f4 differ diff --git a/external/boringssl/fuzz/server_corpus/83a7146b87bdb59b9d181983c0b15934fa141095 b/external/boringssl/fuzz/server_corpus/83a7146b87bdb59b9d181983c0b15934fa141095 new file mode 100644 index 0000000000..8b115c8973 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/83a7146b87bdb59b9d181983c0b15934fa141095 differ diff --git a/external/boringssl/fuzz/server_corpus/84128b248dde02f39d9038b0d9a92be858064b93 b/external/boringssl/fuzz/server_corpus/84128b248dde02f39d9038b0d9a92be858064b93 new file mode 100644 index 0000000000..8f160c3799 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/84128b248dde02f39d9038b0d9a92be858064b93 differ diff --git a/external/boringssl/fuzz/server_corpus/846f489beaa418c54a7558e3dda22fa18a613344 b/external/boringssl/fuzz/server_corpus/846f489beaa418c54a7558e3dda22fa18a613344 new file mode 100644 index 0000000000..d831a9dfda Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/846f489beaa418c54a7558e3dda22fa18a613344 differ diff --git a/external/boringssl/fuzz/server_corpus/84cd4487cc10e218fac4e005a2f36e6cda07f2f1 b/external/boringssl/fuzz/server_corpus/84cd4487cc10e218fac4e005a2f36e6cda07f2f1 new file mode 100644 index 0000000000..cbe945fbc7 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/84cd4487cc10e218fac4e005a2f36e6cda07f2f1 differ diff --git a/external/boringssl/fuzz/server_corpus/8538cd3259ad3d8f06f9ae921b6a365b33548097 b/external/boringssl/fuzz/server_corpus/8538cd3259ad3d8f06f9ae921b6a365b33548097 new file mode 100644 index 0000000000..93d88c2c20 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/8538cd3259ad3d8f06f9ae921b6a365b33548097 differ diff --git a/external/boringssl/fuzz/server_corpus/8550e0986e06c2c732bf5707cf1679d18d4018a7 b/external/boringssl/fuzz/server_corpus/8550e0986e06c2c732bf5707cf1679d18d4018a7 new file mode 100644 index 0000000000..9d8af35086 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/8550e0986e06c2c732bf5707cf1679d18d4018a7 differ diff --git a/external/boringssl/fuzz/server_corpus/865424250f3372fd80022ecbd3030371eb7484bb b/external/boringssl/fuzz/server_corpus/865424250f3372fd80022ecbd3030371eb7484bb new file mode 100644 index 0000000000..5490d4b990 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/865424250f3372fd80022ecbd3030371eb7484bb differ diff --git a/external/boringssl/fuzz/server_corpus/87312b033ed008fdeb949278f51403dd15ca3f77 b/external/boringssl/fuzz/server_corpus/87312b033ed008fdeb949278f51403dd15ca3f77 new file mode 100644 index 0000000000..97552b025f Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/87312b033ed008fdeb949278f51403dd15ca3f77 differ diff --git a/external/boringssl/fuzz/server_corpus/87bb4f11ea55340864b41f92cfd96699e34dcb01 b/external/boringssl/fuzz/server_corpus/87bb4f11ea55340864b41f92cfd96699e34dcb01 new file mode 100644 index 0000000000..f33611bf4e Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/87bb4f11ea55340864b41f92cfd96699e34dcb01 differ diff --git a/external/boringssl/fuzz/server_corpus/87d63b2cf65c4a56d5c6c7354e122472c1c86985 b/external/boringssl/fuzz/server_corpus/87d63b2cf65c4a56d5c6c7354e122472c1c86985 new file mode 100644 index 0000000000..4645d67491 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/87d63b2cf65c4a56d5c6c7354e122472c1c86985 differ diff --git a/external/boringssl/fuzz/server_corpus/8ae391773c823fc455913bb5ec33047dd840e9f9 b/external/boringssl/fuzz/server_corpus/8ae391773c823fc455913bb5ec33047dd840e9f9 new file mode 100644 index 0000000000..075884c8b8 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/8ae391773c823fc455913bb5ec33047dd840e9f9 differ diff --git a/external/boringssl/fuzz/server_corpus/8b4aeaa1d3ce97c435b07445e55b778db0f8fda6 b/external/boringssl/fuzz/server_corpus/8b4aeaa1d3ce97c435b07445e55b778db0f8fda6 new file mode 100644 index 0000000000..a826a36c9c Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/8b4aeaa1d3ce97c435b07445e55b778db0f8fda6 differ diff --git a/external/boringssl/fuzz/server_corpus/8b7fab7b5c33fbb29a8cc5d48040f30b06c16f4c b/external/boringssl/fuzz/server_corpus/8b7fab7b5c33fbb29a8cc5d48040f30b06c16f4c new file mode 100644 index 0000000000..4adecc399d Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/8b7fab7b5c33fbb29a8cc5d48040f30b06c16f4c differ diff --git a/external/boringssl/fuzz/server_corpus/8bb068ede7bfaba9627d9820634c0eb4289db338 b/external/boringssl/fuzz/server_corpus/8bb068ede7bfaba9627d9820634c0eb4289db338 new file mode 100644 index 0000000000..ead297a6a5 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/8bb068ede7bfaba9627d9820634c0eb4289db338 differ diff --git a/external/boringssl/fuzz/server_corpus/8d8899a4a0aca676e6e4df78003f237073f850e4 b/external/boringssl/fuzz/server_corpus/8d8899a4a0aca676e6e4df78003f237073f850e4 new file mode 100644 index 0000000000..9322726d8d Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/8d8899a4a0aca676e6e4df78003f237073f850e4 differ diff --git a/external/boringssl/fuzz/server_corpus/8dc9927297dc363f7858864279aba3d2e7f1abea b/external/boringssl/fuzz/server_corpus/8dc9927297dc363f7858864279aba3d2e7f1abea new file mode 100644 index 0000000000..16d2735680 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/8dc9927297dc363f7858864279aba3d2e7f1abea differ diff --git a/external/boringssl/fuzz/server_corpus/909f5acb8de0079ff4c8b107d272574085c8f779 b/external/boringssl/fuzz/server_corpus/909f5acb8de0079ff4c8b107d272574085c8f779 new file mode 100644 index 0000000000..d18b36cf33 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/909f5acb8de0079ff4c8b107d272574085c8f779 differ diff --git a/external/boringssl/fuzz/server_corpus/90d7f98a4df715ea087a5ac5f96c20d968cdfa11 b/external/boringssl/fuzz/server_corpus/90d7f98a4df715ea087a5ac5f96c20d968cdfa11 new file mode 100644 index 0000000000..80da881193 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/90d7f98a4df715ea087a5ac5f96c20d968cdfa11 differ diff --git a/external/boringssl/fuzz/server_corpus/92d1725e6cd758eeb1139f214d4431b8c8cc8006 b/external/boringssl/fuzz/server_corpus/92d1725e6cd758eeb1139f214d4431b8c8cc8006 new file mode 100644 index 0000000000..da859b9e00 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/92d1725e6cd758eeb1139f214d4431b8c8cc8006 differ diff --git a/external/boringssl/fuzz/server_corpus/93fd04136be09b9ff4986bb17fee653ba10c3f86 b/external/boringssl/fuzz/server_corpus/93fd04136be09b9ff4986bb17fee653ba10c3f86 new file mode 100644 index 0000000000..18ae783d22 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/93fd04136be09b9ff4986bb17fee653ba10c3f86 differ diff --git a/external/boringssl/fuzz/server_corpus/94581aeb5d99c7ec11279264a94e4d3fa845c41d b/external/boringssl/fuzz/server_corpus/94581aeb5d99c7ec11279264a94e4d3fa845c41d new file mode 100644 index 0000000000..c11faaf6ee Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/94581aeb5d99c7ec11279264a94e4d3fa845c41d differ diff --git a/external/boringssl/fuzz/server_corpus/968d9f7d5bf7e11e205dedf844a771f185c777a0 b/external/boringssl/fuzz/server_corpus/968d9f7d5bf7e11e205dedf844a771f185c777a0 new file mode 100644 index 0000000000..f9bc4f61dc --- /dev/null +++ b/external/boringssl/fuzz/server_corpus/968d9f7d5bf7e11e205dedf844a771f185c777a0 @@ -0,0 +1 @@ +‡*Ì ;›ãÂ)×(D \ No newline at end of file diff --git a/external/boringssl/fuzz/server_corpus/96e88c6539e937f868152998ba46a8decab25bf6 b/external/boringssl/fuzz/server_corpus/96e88c6539e937f868152998ba46a8decab25bf6 new file mode 100644 index 0000000000..68d0d1cd64 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/96e88c6539e937f868152998ba46a8decab25bf6 differ diff --git a/external/boringssl/fuzz/server_corpus/971714820d6742e5e6d84e95a26c1e526898c726 b/external/boringssl/fuzz/server_corpus/971714820d6742e5e6d84e95a26c1e526898c726 new file mode 100644 index 0000000000..8cea4be05e Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/971714820d6742e5e6d84e95a26c1e526898c726 differ diff --git a/external/boringssl/fuzz/server_corpus/97835515e9845c8094b017636f42e40db853e358 b/external/boringssl/fuzz/server_corpus/97835515e9845c8094b017636f42e40db853e358 new file mode 100644 index 0000000000..fe3e5811c2 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/97835515e9845c8094b017636f42e40db853e358 differ diff --git a/external/boringssl/fuzz/server_corpus/9841a3665b7d75fd247655a673018735e69e13ca b/external/boringssl/fuzz/server_corpus/9841a3665b7d75fd247655a673018735e69e13ca new file mode 100644 index 0000000000..33b41b61c1 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/9841a3665b7d75fd247655a673018735e69e13ca differ diff --git a/external/boringssl/fuzz/server_corpus/98c12c0d2c35bc2141a8c5fd2438bc6e237df335 b/external/boringssl/fuzz/server_corpus/98c12c0d2c35bc2141a8c5fd2438bc6e237df335 new file mode 100644 index 0000000000..ea94415f69 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/98c12c0d2c35bc2141a8c5fd2438bc6e237df335 differ diff --git a/external/boringssl/fuzz/server_corpus/990b7bec61d2e85dc617b456db532b738791dfcb b/external/boringssl/fuzz/server_corpus/990b7bec61d2e85dc617b456db532b738791dfcb new file mode 100644 index 0000000000..3538d11b63 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/990b7bec61d2e85dc617b456db532b738791dfcb differ diff --git a/external/boringssl/fuzz/server_corpus/999678f54ffad44b964188ff7b839fe323e5d8a0 b/external/boringssl/fuzz/server_corpus/999678f54ffad44b964188ff7b839fe323e5d8a0 new file mode 100644 index 0000000000..7ce0c54ee8 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/999678f54ffad44b964188ff7b839fe323e5d8a0 differ diff --git a/external/boringssl/fuzz/server_corpus/99f84ab3877198979a5644873f3078e56d9bce74 b/external/boringssl/fuzz/server_corpus/99f84ab3877198979a5644873f3078e56d9bce74 new file mode 100644 index 0000000000..947ac61a3e Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/99f84ab3877198979a5644873f3078e56d9bce74 differ diff --git a/external/boringssl/fuzz/server_corpus/9a0a22651c45daadb5e28c2fb5a722050242e3ad b/external/boringssl/fuzz/server_corpus/9a0a22651c45daadb5e28c2fb5a722050242e3ad new file mode 100644 index 0000000000..5c5a517145 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/9a0a22651c45daadb5e28c2fb5a722050242e3ad differ diff --git a/external/boringssl/fuzz/server_corpus/9d6670b22713ef933f7023a1de30f1bf0f153b7c b/external/boringssl/fuzz/server_corpus/9d6670b22713ef933f7023a1de30f1bf0f153b7c new file mode 100644 index 0000000000..f5b83099ef Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/9d6670b22713ef933f7023a1de30f1bf0f153b7c differ diff --git a/external/boringssl/fuzz/server_corpus/9f47049690a48658cf855cada2ba67ca467f6b4c b/external/boringssl/fuzz/server_corpus/9f47049690a48658cf855cada2ba67ca467f6b4c new file mode 100644 index 0000000000..796363f366 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/9f47049690a48658cf855cada2ba67ca467f6b4c differ diff --git a/external/boringssl/fuzz/server_corpus/a17c22b54007188166fa0ddc4afc05dce426bd06 b/external/boringssl/fuzz/server_corpus/a17c22b54007188166fa0ddc4afc05dce426bd06 new file mode 100644 index 0000000000..4e65694807 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/a17c22b54007188166fa0ddc4afc05dce426bd06 differ diff --git a/external/boringssl/fuzz/server_corpus/a2119075a436f488b9caddcd0d2e78f08eb9a5ff b/external/boringssl/fuzz/server_corpus/a2119075a436f488b9caddcd0d2e78f08eb9a5ff new file mode 100644 index 0000000000..9dac082697 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/a2119075a436f488b9caddcd0d2e78f08eb9a5ff differ diff --git a/external/boringssl/fuzz/server_corpus/a38a19f50fd1cda8c1fecbe27ac83324ca211b84 b/external/boringssl/fuzz/server_corpus/a38a19f50fd1cda8c1fecbe27ac83324ca211b84 new file mode 100644 index 0000000000..445b39a209 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/a38a19f50fd1cda8c1fecbe27ac83324ca211b84 differ diff --git a/external/boringssl/fuzz/server_corpus/a38b5e4d0ec3ea571a38c35c2ed3c72772c4732b b/external/boringssl/fuzz/server_corpus/a38b5e4d0ec3ea571a38c35c2ed3c72772c4732b new file mode 100644 index 0000000000..f8bcb04e3a Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/a38b5e4d0ec3ea571a38c35c2ed3c72772c4732b differ diff --git a/external/boringssl/fuzz/server_corpus/a499e6063ea86dada60bc06951f13039e9c1f3ac b/external/boringssl/fuzz/server_corpus/a499e6063ea86dada60bc06951f13039e9c1f3ac new file mode 100644 index 0000000000..5c9c674f0a Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/a499e6063ea86dada60bc06951f13039e9c1f3ac differ diff --git a/external/boringssl/fuzz/server_corpus/a501e54923687ec3b05c49c06457d145342f47f5 b/external/boringssl/fuzz/server_corpus/a501e54923687ec3b05c49c06457d145342f47f5 new file mode 100644 index 0000000000..96e5a92548 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/a501e54923687ec3b05c49c06457d145342f47f5 differ diff --git a/external/boringssl/fuzz/server_corpus/a522a19032823024bb19fd0df2d4f26ea54a896d b/external/boringssl/fuzz/server_corpus/a522a19032823024bb19fd0df2d4f26ea54a896d new file mode 100644 index 0000000000..e73d4c7eda Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/a522a19032823024bb19fd0df2d4f26ea54a896d differ diff --git a/external/boringssl/fuzz/server_corpus/a6d011ffcc98cf16234a7d20ccd4db30809b39ac b/external/boringssl/fuzz/server_corpus/a6d011ffcc98cf16234a7d20ccd4db30809b39ac new file mode 100644 index 0000000000..8621d3ef1d Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/a6d011ffcc98cf16234a7d20ccd4db30809b39ac differ diff --git a/external/boringssl/fuzz/server_corpus/a7b732b28fef3a7d2797d793c1d972f3460e50c9 b/external/boringssl/fuzz/server_corpus/a7b732b28fef3a7d2797d793c1d972f3460e50c9 new file mode 100644 index 0000000000..1d2f6cc57a Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/a7b732b28fef3a7d2797d793c1d972f3460e50c9 differ diff --git a/external/boringssl/fuzz/server_corpus/a805ac78ea5ac34b9f16d1db6a2586bebb804d1a b/external/boringssl/fuzz/server_corpus/a805ac78ea5ac34b9f16d1db6a2586bebb804d1a new file mode 100644 index 0000000000..14d1547776 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/a805ac78ea5ac34b9f16d1db6a2586bebb804d1a differ diff --git a/external/boringssl/fuzz/server_corpus/a8461484408a8b22ac775b72a0fae9362e1bbf46 b/external/boringssl/fuzz/server_corpus/a8461484408a8b22ac775b72a0fae9362e1bbf46 new file mode 100644 index 0000000000..c96f6b622a --- /dev/null +++ b/external/boringssl/fuzz/server_corpus/a8461484408a8b22ac775b72a0fae9362e1bbf46 @@ -0,0 +1 @@ +‡*;›ã \ No newline at end of file diff --git a/external/boringssl/fuzz/server_corpus/a851fcf09f23a5980550492a7b6a9af5e55c786b b/external/boringssl/fuzz/server_corpus/a851fcf09f23a5980550492a7b6a9af5e55c786b new file mode 100644 index 0000000000..329cbf8fdd Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/a851fcf09f23a5980550492a7b6a9af5e55c786b differ diff --git a/external/boringssl/fuzz/server_corpus/a94773a424fb3dd39e61ef294cce3a226002085f b/external/boringssl/fuzz/server_corpus/a94773a424fb3dd39e61ef294cce3a226002085f new file mode 100644 index 0000000000..778f1222f9 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/a94773a424fb3dd39e61ef294cce3a226002085f differ diff --git a/external/boringssl/fuzz/server_corpus/a9aaf8b0c4396ca9a8905c257cadad38b015f715 b/external/boringssl/fuzz/server_corpus/a9aaf8b0c4396ca9a8905c257cadad38b015f715 new file mode 100644 index 0000000000..a13ec20a42 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/a9aaf8b0c4396ca9a8905c257cadad38b015f715 differ diff --git a/external/boringssl/fuzz/server_corpus/abbc509bc116d4cb303b4efc226110e3d2b1f9cb b/external/boringssl/fuzz/server_corpus/abbc509bc116d4cb303b4efc226110e3d2b1f9cb new file mode 100644 index 0000000000..18e012b1dd Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/abbc509bc116d4cb303b4efc226110e3d2b1f9cb differ diff --git a/external/boringssl/fuzz/server_corpus/ad657af7ec670f63bf7b699bfc2d7784d9679c75 b/external/boringssl/fuzz/server_corpus/ad657af7ec670f63bf7b699bfc2d7784d9679c75 new file mode 100644 index 0000000000..5f91127dea Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/ad657af7ec670f63bf7b699bfc2d7784d9679c75 differ diff --git a/external/boringssl/fuzz/server_corpus/adbf34bf3b6c339e3aedeb5bda369026f1041498 b/external/boringssl/fuzz/server_corpus/adbf34bf3b6c339e3aedeb5bda369026f1041498 new file mode 100644 index 0000000000..981d72ca0f Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/adbf34bf3b6c339e3aedeb5bda369026f1041498 differ diff --git a/external/boringssl/fuzz/server_corpus/ae1addcfe82e6e924c3d5186aebc7f4595a34f79 b/external/boringssl/fuzz/server_corpus/ae1addcfe82e6e924c3d5186aebc7f4595a34f79 new file mode 100644 index 0000000000..7a2da9f418 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/ae1addcfe82e6e924c3d5186aebc7f4595a34f79 differ diff --git a/external/boringssl/fuzz/server_corpus/afb52e07276941f1176601b4855bf5d96773221b b/external/boringssl/fuzz/server_corpus/afb52e07276941f1176601b4855bf5d96773221b new file mode 100644 index 0000000000..5f40826c27 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/afb52e07276941f1176601b4855bf5d96773221b differ diff --git a/external/boringssl/fuzz/server_corpus/b0d31fd682c73610a7879d9f4932388b95d0bc27 b/external/boringssl/fuzz/server_corpus/b0d31fd682c73610a7879d9f4932388b95d0bc27 new file mode 100644 index 0000000000..b21b6022cd Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/b0d31fd682c73610a7879d9f4932388b95d0bc27 differ diff --git a/external/boringssl/fuzz/server_corpus/b110009f633e2daf74b775a2f29521e49cb50021 b/external/boringssl/fuzz/server_corpus/b110009f633e2daf74b775a2f29521e49cb50021 new file mode 100644 index 0000000000..3fb45ebf46 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/b110009f633e2daf74b775a2f29521e49cb50021 differ diff --git a/external/boringssl/fuzz/server_corpus/b161a1165fdcc35082d791714fa697f88f673f32 b/external/boringssl/fuzz/server_corpus/b161a1165fdcc35082d791714fa697f88f673f32 new file mode 100644 index 0000000000..f0edfaa39e Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/b161a1165fdcc35082d791714fa697f88f673f32 differ diff --git a/external/boringssl/fuzz/server_corpus/b19d4db2ac81eca8ec7270e840ade3c0d0f9c961 b/external/boringssl/fuzz/server_corpus/b19d4db2ac81eca8ec7270e840ade3c0d0f9c961 new file mode 100644 index 0000000000..11295cdbbc Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/b19d4db2ac81eca8ec7270e840ade3c0d0f9c961 differ diff --git a/external/boringssl/fuzz/server_corpus/b34fe229d5704686c2f583c49081e780f9eee0f0 b/external/boringssl/fuzz/server_corpus/b34fe229d5704686c2f583c49081e780f9eee0f0 new file mode 100644 index 0000000000..ad7547c6e7 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/b34fe229d5704686c2f583c49081e780f9eee0f0 differ diff --git a/external/boringssl/fuzz/server_corpus/b3c32ca3d0de7706ec31c174e56d3f3a02a29e74 b/external/boringssl/fuzz/server_corpus/b3c32ca3d0de7706ec31c174e56d3f3a02a29e74 new file mode 100644 index 0000000000..e42d3e90a5 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/b3c32ca3d0de7706ec31c174e56d3f3a02a29e74 differ diff --git a/external/boringssl/fuzz/server_corpus/b5a0df0a67120a113aaa8e66d2a89e92eb83518c b/external/boringssl/fuzz/server_corpus/b5a0df0a67120a113aaa8e66d2a89e92eb83518c new file mode 100644 index 0000000000..248229a199 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/b5a0df0a67120a113aaa8e66d2a89e92eb83518c differ diff --git a/external/boringssl/fuzz/server_corpus/b5e350594b8a451635004e4adbac220855746f95 b/external/boringssl/fuzz/server_corpus/b5e350594b8a451635004e4adbac220855746f95 new file mode 100644 index 0000000000..b86f57f006 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/b5e350594b8a451635004e4adbac220855746f95 differ diff --git a/external/boringssl/fuzz/server_corpus/b635afc6b7eb4837e06e295a0b7be1dd4304c938 b/external/boringssl/fuzz/server_corpus/b635afc6b7eb4837e06e295a0b7be1dd4304c938 new file mode 100644 index 0000000000..9fca7cf426 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/b635afc6b7eb4837e06e295a0b7be1dd4304c938 differ diff --git a/external/boringssl/fuzz/server_corpus/b68c52bcc48b4828c3b9c0a1e549333b33fc3571 b/external/boringssl/fuzz/server_corpus/b68c52bcc48b4828c3b9c0a1e549333b33fc3571 new file mode 100644 index 0000000000..b5baa8bebe Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/b68c52bcc48b4828c3b9c0a1e549333b33fc3571 differ diff --git a/external/boringssl/fuzz/server_corpus/b6a51620f85e0bf69b534402b0d0397ceb834e9b b/external/boringssl/fuzz/server_corpus/b6a51620f85e0bf69b534402b0d0397ceb834e9b new file mode 100644 index 0000000000..e95a34a1a8 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/b6a51620f85e0bf69b534402b0d0397ceb834e9b differ diff --git a/external/boringssl/fuzz/server_corpus/b6b9e9149d9da8a20823ddd794b17f3e07c5902f b/external/boringssl/fuzz/server_corpus/b6b9e9149d9da8a20823ddd794b17f3e07c5902f new file mode 100644 index 0000000000..79fa028916 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/b6b9e9149d9da8a20823ddd794b17f3e07c5902f differ diff --git a/external/boringssl/fuzz/server_corpus/b6cc929d3a3e0c526463b451e5a9e3b00d105368 b/external/boringssl/fuzz/server_corpus/b6cc929d3a3e0c526463b451e5a9e3b00d105368 new file mode 100644 index 0000000000..f4b7f477f4 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/b6cc929d3a3e0c526463b451e5a9e3b00d105368 differ diff --git a/external/boringssl/fuzz/server_corpus/b6e477f0159ebe9a37e048602f357a148ddb3b32 b/external/boringssl/fuzz/server_corpus/b6e477f0159ebe9a37e048602f357a148ddb3b32 new file mode 100644 index 0000000000..676819019f Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/b6e477f0159ebe9a37e048602f357a148ddb3b32 differ diff --git a/external/boringssl/fuzz/server_corpus/b7801a9236dd2281a0acc933019224d6c1dbf257 b/external/boringssl/fuzz/server_corpus/b7801a9236dd2281a0acc933019224d6c1dbf257 new file mode 100644 index 0000000000..63ba0b0b7d Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/b7801a9236dd2281a0acc933019224d6c1dbf257 differ diff --git a/external/boringssl/fuzz/server_corpus/b7dcbba77174c4a08c659a593ec3f5ebe5094343 b/external/boringssl/fuzz/server_corpus/b7dcbba77174c4a08c659a593ec3f5ebe5094343 new file mode 100644 index 0000000000..81f58bf104 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/b7dcbba77174c4a08c659a593ec3f5ebe5094343 differ diff --git a/external/boringssl/fuzz/server_corpus/b832a18069022b70323d9a0ccdf38a6bd3d9aa5e b/external/boringssl/fuzz/server_corpus/b832a18069022b70323d9a0ccdf38a6bd3d9aa5e new file mode 100644 index 0000000000..6b937d840b Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/b832a18069022b70323d9a0ccdf38a6bd3d9aa5e differ diff --git a/external/boringssl/fuzz/server_corpus/b8a03d1b641ed88f0951d04943b8a07050370f7e b/external/boringssl/fuzz/server_corpus/b8a03d1b641ed88f0951d04943b8a07050370f7e new file mode 100644 index 0000000000..c6e45f6274 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/b8a03d1b641ed88f0951d04943b8a07050370f7e differ diff --git a/external/boringssl/fuzz/server_corpus/b8dbc8daf864513bd67dfd27651067ec8cee20bf b/external/boringssl/fuzz/server_corpus/b8dbc8daf864513bd67dfd27651067ec8cee20bf new file mode 100644 index 0000000000..e5457d8bb4 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/b8dbc8daf864513bd67dfd27651067ec8cee20bf differ diff --git a/external/boringssl/fuzz/server_corpus/b9331377e2a9f03a15649ff1ed311d9c70057b9c b/external/boringssl/fuzz/server_corpus/b9331377e2a9f03a15649ff1ed311d9c70057b9c new file mode 100644 index 0000000000..83c409b90e Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/b9331377e2a9f03a15649ff1ed311d9c70057b9c differ diff --git a/external/boringssl/fuzz/server_corpus/bb589d0621e5472f470fa3425a234c74b1e202e8 b/external/boringssl/fuzz/server_corpus/bb589d0621e5472f470fa3425a234c74b1e202e8 new file mode 100644 index 0000000000..ad2823b48f --- /dev/null +++ b/external/boringssl/fuzz/server_corpus/bb589d0621e5472f470fa3425a234c74b1e202e8 @@ -0,0 +1 @@ +' \ No newline at end of file diff --git a/external/boringssl/fuzz/server_corpus/bcbe93c3346d8dc6de9b6db6963d7787440498a8 b/external/boringssl/fuzz/server_corpus/bcbe93c3346d8dc6de9b6db6963d7787440498a8 new file mode 100644 index 0000000000..96dd7ba85d Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/bcbe93c3346d8dc6de9b6db6963d7787440498a8 differ diff --git a/external/boringssl/fuzz/server_corpus/bd2f13c2ea9251c8f5984e4801964d2c535e979a b/external/boringssl/fuzz/server_corpus/bd2f13c2ea9251c8f5984e4801964d2c535e979a new file mode 100644 index 0000000000..fd6a5cfb4d --- /dev/null +++ b/external/boringssl/fuzz/server_corpus/bd2f13c2ea9251c8f5984e4801964d2c535e979a @@ -0,0 +1 @@ +Î*);›ã)ã×(*¹; \ No newline at end of file diff --git a/external/boringssl/fuzz/server_corpus/bd6b8551ceeb4f504ef7428a1fe188ad343c9e70 b/external/boringssl/fuzz/server_corpus/bd6b8551ceeb4f504ef7428a1fe188ad343c9e70 new file mode 100644 index 0000000000..cb4d1e3e6c Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/bd6b8551ceeb4f504ef7428a1fe188ad343c9e70 differ diff --git a/external/boringssl/fuzz/server_corpus/be6b4b2ec34f17afc2630bd13ceda59817a86bf0 b/external/boringssl/fuzz/server_corpus/be6b4b2ec34f17afc2630bd13ceda59817a86bf0 new file mode 100644 index 0000000000..625f2c6d01 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/be6b4b2ec34f17afc2630bd13ceda59817a86bf0 differ diff --git a/external/boringssl/fuzz/server_corpus/bf85c5738caa0751b6192e3f2210153e16190e7f b/external/boringssl/fuzz/server_corpus/bf85c5738caa0751b6192e3f2210153e16190e7f new file mode 100644 index 0000000000..19bc5c99e6 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/bf85c5738caa0751b6192e3f2210153e16190e7f differ diff --git a/external/boringssl/fuzz/server_corpus/c095ac0fc0793343959fb8ce7b9f0a448a679a72 b/external/boringssl/fuzz/server_corpus/c095ac0fc0793343959fb8ce7b9f0a448a679a72 new file mode 100644 index 0000000000..026b10137c Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/c095ac0fc0793343959fb8ce7b9f0a448a679a72 differ diff --git a/external/boringssl/fuzz/server_corpus/c0b121e41d0a429854a5967bd6d1367414333246 b/external/boringssl/fuzz/server_corpus/c0b121e41d0a429854a5967bd6d1367414333246 new file mode 100644 index 0000000000..11e51f594c Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/c0b121e41d0a429854a5967bd6d1367414333246 differ diff --git a/external/boringssl/fuzz/server_corpus/c1324667e62ed6cc878ebab4c7e8a8ce4cb7dbe0 b/external/boringssl/fuzz/server_corpus/c1324667e62ed6cc878ebab4c7e8a8ce4cb7dbe0 new file mode 100644 index 0000000000..d0802689f5 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/c1324667e62ed6cc878ebab4c7e8a8ce4cb7dbe0 differ diff --git a/external/boringssl/fuzz/server_corpus/c1774d0621d44733a05eb58edf38f7f994ada191 b/external/boringssl/fuzz/server_corpus/c1774d0621d44733a05eb58edf38f7f994ada191 new file mode 100644 index 0000000000..d5cb7ca67f Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/c1774d0621d44733a05eb58edf38f7f994ada191 differ diff --git a/external/boringssl/fuzz/server_corpus/c2316b3de8f79e6021ba25dc3522c440cce56abb b/external/boringssl/fuzz/server_corpus/c2316b3de8f79e6021ba25dc3522c440cce56abb new file mode 100644 index 0000000000..79e8819c8e Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/c2316b3de8f79e6021ba25dc3522c440cce56abb differ diff --git a/external/boringssl/fuzz/server_corpus/c25117880ac0e46d72797ac80e67ea5c8d8d0e8d b/external/boringssl/fuzz/server_corpus/c25117880ac0e46d72797ac80e67ea5c8d8d0e8d new file mode 100644 index 0000000000..e37f867c9c Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/c25117880ac0e46d72797ac80e67ea5c8d8d0e8d differ diff --git a/external/boringssl/fuzz/server_corpus/c367c8c9fb925f801d2b3a21bf1738ee5cfe57a8 b/external/boringssl/fuzz/server_corpus/c367c8c9fb925f801d2b3a21bf1738ee5cfe57a8 new file mode 100644 index 0000000000..aa63ecf0bd Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/c367c8c9fb925f801d2b3a21bf1738ee5cfe57a8 differ diff --git a/external/boringssl/fuzz/server_corpus/c39ffbdda14f7196ff35c67a2589bcd873e07e84 b/external/boringssl/fuzz/server_corpus/c39ffbdda14f7196ff35c67a2589bcd873e07e84 new file mode 100644 index 0000000000..dec01c1fa8 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/c39ffbdda14f7196ff35c67a2589bcd873e07e84 differ diff --git a/external/boringssl/fuzz/server_corpus/c3b18d830d2afda016d1c6d2cf8656707936d9aa b/external/boringssl/fuzz/server_corpus/c3b18d830d2afda016d1c6d2cf8656707936d9aa new file mode 100644 index 0000000000..f4fbeeda20 --- /dev/null +++ b/external/boringssl/fuzz/server_corpus/c3b18d830d2afda016d1c6d2cf8656707936d9aa @@ -0,0 +1 @@ +€ );Õ›ã)ã×( \ No newline at end of file diff --git a/external/boringssl/fuzz/server_corpus/c4530fd98a3f55c874638e7703b4755dcbf03d25 b/external/boringssl/fuzz/server_corpus/c4530fd98a3f55c874638e7703b4755dcbf03d25 new file mode 100644 index 0000000000..5bd24ee04f Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/c4530fd98a3f55c874638e7703b4755dcbf03d25 differ diff --git a/external/boringssl/fuzz/server_corpus/c488daaa980c5b4637c14a7a9dba41f905ad40ee b/external/boringssl/fuzz/server_corpus/c488daaa980c5b4637c14a7a9dba41f905ad40ee new file mode 100644 index 0000000000..1d59155cf6 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/c488daaa980c5b4637c14a7a9dba41f905ad40ee differ diff --git a/external/boringssl/fuzz/server_corpus/c4dd3c8cdd8d7c95603dd67f1cd873d5f9148b29 b/external/boringssl/fuzz/server_corpus/c4dd3c8cdd8d7c95603dd67f1cd873d5f9148b29 new file mode 100644 index 0000000000..c5fa78456d --- /dev/null +++ b/external/boringssl/fuzz/server_corpus/c4dd3c8cdd8d7c95603dd67f1cd873d5f9148b29 @@ -0,0 +1 @@ +< \ No newline at end of file diff --git a/external/boringssl/fuzz/server_corpus/c4e90f27e3780d2596c565dbc6b23e8a62a32671 b/external/boringssl/fuzz/server_corpus/c4e90f27e3780d2596c565dbc6b23e8a62a32671 new file mode 100644 index 0000000000..6e17df0158 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/c4e90f27e3780d2596c565dbc6b23e8a62a32671 differ diff --git a/external/boringssl/fuzz/server_corpus/c5d128e9ef95c5ea1941b1583bf5d67433efa122 b/external/boringssl/fuzz/server_corpus/c5d128e9ef95c5ea1941b1583bf5d67433efa122 new file mode 100644 index 0000000000..112e8ce63f Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/c5d128e9ef95c5ea1941b1583bf5d67433efa122 differ diff --git a/external/boringssl/fuzz/server_corpus/c6f9e5c4cc9a6f8af4df7e633ba7267244810910 b/external/boringssl/fuzz/server_corpus/c6f9e5c4cc9a6f8af4df7e633ba7267244810910 new file mode 100644 index 0000000000..782e94e467 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/c6f9e5c4cc9a6f8af4df7e633ba7267244810910 differ diff --git a/external/boringssl/fuzz/server_corpus/c783f8c9cfb382374aa8359a3ecdd689140aa3ac b/external/boringssl/fuzz/server_corpus/c783f8c9cfb382374aa8359a3ecdd689140aa3ac new file mode 100644 index 0000000000..bc2aab6127 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/c783f8c9cfb382374aa8359a3ecdd689140aa3ac differ diff --git a/external/boringssl/fuzz/server_corpus/c7ca9b384fb874d12f54ba800b7db3fc35d47d1a b/external/boringssl/fuzz/server_corpus/c7ca9b384fb874d12f54ba800b7db3fc35d47d1a new file mode 100644 index 0000000000..4a11ba8e22 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/c7ca9b384fb874d12f54ba800b7db3fc35d47d1a differ diff --git a/external/boringssl/fuzz/server_corpus/c83f7080ddbe04198dd715887ca44666a1fb29b7 b/external/boringssl/fuzz/server_corpus/c83f7080ddbe04198dd715887ca44666a1fb29b7 new file mode 100644 index 0000000000..9898ee46fd Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/c83f7080ddbe04198dd715887ca44666a1fb29b7 differ diff --git a/external/boringssl/fuzz/server_corpus/c877371f7bb5a27b25fd354f7643c95481f7c970 b/external/boringssl/fuzz/server_corpus/c877371f7bb5a27b25fd354f7643c95481f7c970 new file mode 100644 index 0000000000..13a0f6d1a7 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/c877371f7bb5a27b25fd354f7643c95481f7c970 differ diff --git a/external/boringssl/fuzz/server_corpus/c92efc4a4757c37f8373d5da954b114eb780dc52 b/external/boringssl/fuzz/server_corpus/c92efc4a4757c37f8373d5da954b114eb780dc52 new file mode 100644 index 0000000000..156c1d3eeb Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/c92efc4a4757c37f8373d5da954b114eb780dc52 differ diff --git a/external/boringssl/fuzz/server_corpus/cab79dd0612ba0a5213ad42c88619860f9e9485b b/external/boringssl/fuzz/server_corpus/cab79dd0612ba0a5213ad42c88619860f9e9485b new file mode 100644 index 0000000000..2c064c4665 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/cab79dd0612ba0a5213ad42c88619860f9e9485b differ diff --git a/external/boringssl/fuzz/server_corpus/cb0bbbd9c59f0dc9dd030885b65afb8524a4fd45 b/external/boringssl/fuzz/server_corpus/cb0bbbd9c59f0dc9dd030885b65afb8524a4fd45 new file mode 100644 index 0000000000..b19cc15d32 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/cb0bbbd9c59f0dc9dd030885b65afb8524a4fd45 differ diff --git a/external/boringssl/fuzz/server_corpus/cb3f92a2f51c86bd52c598116e73e393d003590d b/external/boringssl/fuzz/server_corpus/cb3f92a2f51c86bd52c598116e73e393d003590d new file mode 100644 index 0000000000..6682687190 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/cb3f92a2f51c86bd52c598116e73e393d003590d differ diff --git a/external/boringssl/fuzz/server_corpus/cc060d9eb0217741ce6e78b428aad5e49f26d6a2 b/external/boringssl/fuzz/server_corpus/cc060d9eb0217741ce6e78b428aad5e49f26d6a2 new file mode 100644 index 0000000000..f46c0a38e9 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/cc060d9eb0217741ce6e78b428aad5e49f26d6a2 differ diff --git a/external/boringssl/fuzz/server_corpus/cc646165768ece9d7b3a53295139c652758719eb b/external/boringssl/fuzz/server_corpus/cc646165768ece9d7b3a53295139c652758719eb new file mode 100644 index 0000000000..87318c7536 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/cc646165768ece9d7b3a53295139c652758719eb differ diff --git a/external/boringssl/fuzz/server_corpus/ccaa1ac7731c409ffde2f89e8cbf71bc7b1a3800 b/external/boringssl/fuzz/server_corpus/ccaa1ac7731c409ffde2f89e8cbf71bc7b1a3800 new file mode 100644 index 0000000000..36bc114f2f Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/ccaa1ac7731c409ffde2f89e8cbf71bc7b1a3800 differ diff --git a/external/boringssl/fuzz/server_corpus/ccf7f63d6c7c9cb39f7ab1e160f2f6a98bce67dc b/external/boringssl/fuzz/server_corpus/ccf7f63d6c7c9cb39f7ab1e160f2f6a98bce67dc new file mode 100644 index 0000000000..50de2c0a49 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/ccf7f63d6c7c9cb39f7ab1e160f2f6a98bce67dc differ diff --git a/external/boringssl/fuzz/server_corpus/cea030f4e5beef22bd9892408a0708bdaf3c3743 b/external/boringssl/fuzz/server_corpus/cea030f4e5beef22bd9892408a0708bdaf3c3743 new file mode 100644 index 0000000000..7e748ccc07 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/cea030f4e5beef22bd9892408a0708bdaf3c3743 differ diff --git a/external/boringssl/fuzz/server_corpus/cef9da3480218f4a353a1d4b10d5095b2273be49 b/external/boringssl/fuzz/server_corpus/cef9da3480218f4a353a1d4b10d5095b2273be49 new file mode 100644 index 0000000000..68372e9473 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/cef9da3480218f4a353a1d4b10d5095b2273be49 differ diff --git a/external/boringssl/fuzz/server_corpus/cf4553b998285a8ef7bcfbb845288955302344b0 b/external/boringssl/fuzz/server_corpus/cf4553b998285a8ef7bcfbb845288955302344b0 new file mode 100644 index 0000000000..c3a3de60c9 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/cf4553b998285a8ef7bcfbb845288955302344b0 differ diff --git a/external/boringssl/fuzz/server_corpus/cfeda2740e1750c2a71175a21457eb3359d36e75 b/external/boringssl/fuzz/server_corpus/cfeda2740e1750c2a71175a21457eb3359d36e75 new file mode 100644 index 0000000000..f4517e6307 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/cfeda2740e1750c2a71175a21457eb3359d36e75 differ diff --git a/external/boringssl/fuzz/server_corpus/cff5833dd4809d38118c760600d7a4a06fb63912 b/external/boringssl/fuzz/server_corpus/cff5833dd4809d38118c760600d7a4a06fb63912 new file mode 100644 index 0000000000..b8f7fdd44c Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/cff5833dd4809d38118c760600d7a4a06fb63912 differ diff --git a/external/boringssl/fuzz/server_corpus/d044e375a03f40f24ca4fa054419d5425912d8f9 b/external/boringssl/fuzz/server_corpus/d044e375a03f40f24ca4fa054419d5425912d8f9 new file mode 100644 index 0000000000..d74dbd89b0 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/d044e375a03f40f24ca4fa054419d5425912d8f9 differ diff --git a/external/boringssl/fuzz/server_corpus/d0846c7f54810ba3483ecaaa84e73b5c87fb72fb b/external/boringssl/fuzz/server_corpus/d0846c7f54810ba3483ecaaa84e73b5c87fb72fb new file mode 100644 index 0000000000..597c059cb7 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/d0846c7f54810ba3483ecaaa84e73b5c87fb72fb differ diff --git a/external/boringssl/fuzz/server_corpus/d0d6d66d04f08f11ad9fb417b8482b62a1c488ce b/external/boringssl/fuzz/server_corpus/d0d6d66d04f08f11ad9fb417b8482b62a1c488ce new file mode 100644 index 0000000000..a80c920c56 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/d0d6d66d04f08f11ad9fb417b8482b62a1c488ce differ diff --git a/external/boringssl/fuzz/server_corpus/d129f7b49f19f3ff63cc8b8c8b27757c3ba968e6 b/external/boringssl/fuzz/server_corpus/d129f7b49f19f3ff63cc8b8c8b27757c3ba968e6 new file mode 100644 index 0000000000..335aacd25d Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/d129f7b49f19f3ff63cc8b8c8b27757c3ba968e6 differ diff --git a/external/boringssl/fuzz/server_corpus/d1730107611b33be2922586c05825454c3bb9cc9 b/external/boringssl/fuzz/server_corpus/d1730107611b33be2922586c05825454c3bb9cc9 new file mode 100644 index 0000000000..53e21e5c16 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/d1730107611b33be2922586c05825454c3bb9cc9 differ diff --git a/external/boringssl/fuzz/server_corpus/d19c0da91a0bb15ee5b7b480ab2304557ba9c079 b/external/boringssl/fuzz/server_corpus/d19c0da91a0bb15ee5b7b480ab2304557ba9c079 new file mode 100644 index 0000000000..2e9fc98bdb Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/d19c0da91a0bb15ee5b7b480ab2304557ba9c079 differ diff --git a/external/boringssl/fuzz/server_corpus/d2c6c9be5638d2a45f14c15f4f73c14f3ef59799 b/external/boringssl/fuzz/server_corpus/d2c6c9be5638d2a45f14c15f4f73c14f3ef59799 new file mode 100644 index 0000000000..84352df8d1 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/d2c6c9be5638d2a45f14c15f4f73c14f3ef59799 differ diff --git a/external/boringssl/fuzz/server_corpus/d2ea7356790b71e17270aa885b1440228810767e b/external/boringssl/fuzz/server_corpus/d2ea7356790b71e17270aa885b1440228810767e new file mode 100644 index 0000000000..274d55d3ce Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/d2ea7356790b71e17270aa885b1440228810767e differ diff --git a/external/boringssl/fuzz/server_corpus/d34d64db9a73ba104b383f991f4ed92a60987cf5 b/external/boringssl/fuzz/server_corpus/d34d64db9a73ba104b383f991f4ed92a60987cf5 new file mode 100644 index 0000000000..c23c74990a Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/d34d64db9a73ba104b383f991f4ed92a60987cf5 differ diff --git a/external/boringssl/fuzz/server_corpus/d374b7d09d4196c596a2586a88256fcb1e9fcb2e b/external/boringssl/fuzz/server_corpus/d374b7d09d4196c596a2586a88256fcb1e9fcb2e new file mode 100644 index 0000000000..53fdb725dd Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/d374b7d09d4196c596a2586a88256fcb1e9fcb2e differ diff --git a/external/boringssl/fuzz/server_corpus/d37f0db1910aa2e906b546fc035f2831addcde43 b/external/boringssl/fuzz/server_corpus/d37f0db1910aa2e906b546fc035f2831addcde43 new file mode 100644 index 0000000000..57732b81c1 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/d37f0db1910aa2e906b546fc035f2831addcde43 differ diff --git a/external/boringssl/fuzz/server_corpus/d3a86e7b61070b78611766d587f5c1bae1786b32 b/external/boringssl/fuzz/server_corpus/d3a86e7b61070b78611766d587f5c1bae1786b32 new file mode 100644 index 0000000000..67533ca610 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/d3a86e7b61070b78611766d587f5c1bae1786b32 differ diff --git a/external/boringssl/fuzz/server_corpus/d3cf42aee90dedb4148eba308eaa0087219d8773 b/external/boringssl/fuzz/server_corpus/d3cf42aee90dedb4148eba308eaa0087219d8773 new file mode 100644 index 0000000000..53b3eca034 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/d3cf42aee90dedb4148eba308eaa0087219d8773 differ diff --git a/external/boringssl/fuzz/server_corpus/d47d2dc334230da3acf3f34b782e2fbb79dcce72 b/external/boringssl/fuzz/server_corpus/d47d2dc334230da3acf3f34b782e2fbb79dcce72 new file mode 100644 index 0000000000..af49b1cac2 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/d47d2dc334230da3acf3f34b782e2fbb79dcce72 differ diff --git a/external/boringssl/fuzz/server_corpus/d4f46b0706389e9680ae047f98bdf38bc31eabd2 b/external/boringssl/fuzz/server_corpus/d4f46b0706389e9680ae047f98bdf38bc31eabd2 new file mode 100644 index 0000000000..e19119087b Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/d4f46b0706389e9680ae047f98bdf38bc31eabd2 differ diff --git a/external/boringssl/fuzz/server_corpus/d503f0f105b563087338bf3517a269ba8b130f1c b/external/boringssl/fuzz/server_corpus/d503f0f105b563087338bf3517a269ba8b130f1c new file mode 100644 index 0000000000..2f3c1eeb48 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/d503f0f105b563087338bf3517a269ba8b130f1c differ diff --git a/external/boringssl/fuzz/server_corpus/d6a617adce65f5e26d0b216b04cf5faf774ae5df b/external/boringssl/fuzz/server_corpus/d6a617adce65f5e26d0b216b04cf5faf774ae5df new file mode 100644 index 0000000000..d7045a444b Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/d6a617adce65f5e26d0b216b04cf5faf774ae5df differ diff --git a/external/boringssl/fuzz/server_corpus/d7247e3132134e04b695907afdce71681fe30f60 b/external/boringssl/fuzz/server_corpus/d7247e3132134e04b695907afdce71681fe30f60 new file mode 100644 index 0000000000..c9d409fcc0 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/d7247e3132134e04b695907afdce71681fe30f60 differ diff --git a/external/boringssl/fuzz/server_corpus/d741dcf9b121e34a0141845b9329ea92f15ff447 b/external/boringssl/fuzz/server_corpus/d741dcf9b121e34a0141845b9329ea92f15ff447 new file mode 100644 index 0000000000..76012ddd6f Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/d741dcf9b121e34a0141845b9329ea92f15ff447 differ diff --git a/external/boringssl/fuzz/server_corpus/d757fd2f32ef978a9d45f8dc90c1c310d6cdfc27 b/external/boringssl/fuzz/server_corpus/d757fd2f32ef978a9d45f8dc90c1c310d6cdfc27 new file mode 100644 index 0000000000..9f2f3ec060 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/d757fd2f32ef978a9d45f8dc90c1c310d6cdfc27 differ diff --git a/external/boringssl/fuzz/server_corpus/d8425676bd4a9091fee7680cc80ec7003a8230c8 b/external/boringssl/fuzz/server_corpus/d8425676bd4a9091fee7680cc80ec7003a8230c8 new file mode 100644 index 0000000000..00cd2d2024 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/d8425676bd4a9091fee7680cc80ec7003a8230c8 differ diff --git a/external/boringssl/fuzz/server_corpus/d8f891994e13e538a9ad177d687423c92cc9a6c1 b/external/boringssl/fuzz/server_corpus/d8f891994e13e538a9ad177d687423c92cc9a6c1 new file mode 100644 index 0000000000..8eeb76f244 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/d8f891994e13e538a9ad177d687423c92cc9a6c1 differ diff --git a/external/boringssl/fuzz/server_corpus/d94aefab9d08d20cd1703e87f92501579ddb9fe0 b/external/boringssl/fuzz/server_corpus/d94aefab9d08d20cd1703e87f92501579ddb9fe0 new file mode 100644 index 0000000000..24bbcf3ead Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/d94aefab9d08d20cd1703e87f92501579ddb9fe0 differ diff --git a/external/boringssl/fuzz/server_corpus/d95337213aefb62a5cac46bca1b4bc2c61538677 b/external/boringssl/fuzz/server_corpus/d95337213aefb62a5cac46bca1b4bc2c61538677 new file mode 100644 index 0000000000..17a6280044 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/d95337213aefb62a5cac46bca1b4bc2c61538677 differ diff --git a/external/boringssl/fuzz/server_corpus/d9d4ac3b729317fced3cd857d1c6b1896b798434 b/external/boringssl/fuzz/server_corpus/d9d4ac3b729317fced3cd857d1c6b1896b798434 new file mode 100644 index 0000000000..57ea4bd61b Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/d9d4ac3b729317fced3cd857d1c6b1896b798434 differ diff --git a/external/boringssl/fuzz/server_corpus/daf8423d0e1956a5daa501ed104e5b6d08cf4e9a b/external/boringssl/fuzz/server_corpus/daf8423d0e1956a5daa501ed104e5b6d08cf4e9a new file mode 100644 index 0000000000..ad663344a1 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/daf8423d0e1956a5daa501ed104e5b6d08cf4e9a differ diff --git a/external/boringssl/fuzz/server_corpus/db8c5c0ef970ec9116de7b29a6af3f15d3a6df3e b/external/boringssl/fuzz/server_corpus/db8c5c0ef970ec9116de7b29a6af3f15d3a6df3e new file mode 100644 index 0000000000..d228ed57f0 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/db8c5c0ef970ec9116de7b29a6af3f15d3a6df3e differ diff --git a/external/boringssl/fuzz/server_corpus/dcd0ac87b1cae69418b6f6f95154186f6f039dd5 b/external/boringssl/fuzz/server_corpus/dcd0ac87b1cae69418b6f6f95154186f6f039dd5 new file mode 100644 index 0000000000..7ccbdb4ebd Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/dcd0ac87b1cae69418b6f6f95154186f6f039dd5 differ diff --git a/external/boringssl/fuzz/server_corpus/dcf711a0bfa12e4616d3b644d381cb75d3113a5f b/external/boringssl/fuzz/server_corpus/dcf711a0bfa12e4616d3b644d381cb75d3113a5f new file mode 100644 index 0000000000..757515997b Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/dcf711a0bfa12e4616d3b644d381cb75d3113a5f differ diff --git a/external/boringssl/fuzz/server_corpus/ddca9eec2e1401c8c1f7dc2fe7c2a6e2a187b155 b/external/boringssl/fuzz/server_corpus/ddca9eec2e1401c8c1f7dc2fe7c2a6e2a187b155 new file mode 100644 index 0000000000..36d06275ed Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/ddca9eec2e1401c8c1f7dc2fe7c2a6e2a187b155 differ diff --git a/external/boringssl/fuzz/server_corpus/df0c69339b2d0625f2114cc0665bf85726fd7737 b/external/boringssl/fuzz/server_corpus/df0c69339b2d0625f2114cc0665bf85726fd7737 new file mode 100644 index 0000000000..45947e520d Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/df0c69339b2d0625f2114cc0665bf85726fd7737 differ diff --git a/external/boringssl/fuzz/server_corpus/df38c584e0a47097ffb84eeeb233378bbe4adb27 b/external/boringssl/fuzz/server_corpus/df38c584e0a47097ffb84eeeb233378bbe4adb27 new file mode 100644 index 0000000000..a208ab7919 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/df38c584e0a47097ffb84eeeb233378bbe4adb27 differ diff --git a/external/boringssl/fuzz/server_corpus/dfc889e877441114c78c93a2c27862d90b8ceb0e b/external/boringssl/fuzz/server_corpus/dfc889e877441114c78c93a2c27862d90b8ceb0e new file mode 100644 index 0000000000..f10b53b5ef Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/dfc889e877441114c78c93a2c27862d90b8ceb0e differ diff --git a/external/boringssl/fuzz/server_corpus/e0c910a95189f32b6f53ae4738352abd5a02bae1 b/external/boringssl/fuzz/server_corpus/e0c910a95189f32b6f53ae4738352abd5a02bae1 new file mode 100644 index 0000000000..f7359ff872 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/e0c910a95189f32b6f53ae4738352abd5a02bae1 differ diff --git a/external/boringssl/fuzz/server_corpus/e2c8667b857090a2a76111235b1dda0410d0531b b/external/boringssl/fuzz/server_corpus/e2c8667b857090a2a76111235b1dda0410d0531b new file mode 100644 index 0000000000..ac3b55d5af Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/e2c8667b857090a2a76111235b1dda0410d0531b differ diff --git a/external/boringssl/fuzz/server_corpus/e4cd6455558a3a56b6cc322044eb2e76bb204c11 b/external/boringssl/fuzz/server_corpus/e4cd6455558a3a56b6cc322044eb2e76bb204c11 new file mode 100644 index 0000000000..7db1b160a9 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/e4cd6455558a3a56b6cc322044eb2e76bb204c11 differ diff --git a/external/boringssl/fuzz/server_corpus/e4f601c4530865ed5c238194692199b65cf6846e b/external/boringssl/fuzz/server_corpus/e4f601c4530865ed5c238194692199b65cf6846e new file mode 100644 index 0000000000..3235a01be4 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/e4f601c4530865ed5c238194692199b65cf6846e differ diff --git a/external/boringssl/fuzz/server_corpus/e58ab0cf342c2e3f7d71b68e7a18e219f86b9a60 b/external/boringssl/fuzz/server_corpus/e58ab0cf342c2e3f7d71b68e7a18e219f86b9a60 new file mode 100644 index 0000000000..4dde4ce391 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/e58ab0cf342c2e3f7d71b68e7a18e219f86b9a60 differ diff --git a/external/boringssl/fuzz/server_corpus/e5adcc3d74b69a26f7dd56c70d37ffd8e472a1bf b/external/boringssl/fuzz/server_corpus/e5adcc3d74b69a26f7dd56c70d37ffd8e472a1bf new file mode 100644 index 0000000000..e7a5d3adae Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/e5adcc3d74b69a26f7dd56c70d37ffd8e472a1bf differ diff --git a/external/boringssl/fuzz/server_corpus/e76d51463070189be289c46db1fef08f8c44ce3c b/external/boringssl/fuzz/server_corpus/e76d51463070189be289c46db1fef08f8c44ce3c new file mode 100644 index 0000000000..2eb68a2d3c Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/e76d51463070189be289c46db1fef08f8c44ce3c differ diff --git a/external/boringssl/fuzz/server_corpus/e7ef72fdab634ae7658cd862feaf944d0ea3ce2b b/external/boringssl/fuzz/server_corpus/e7ef72fdab634ae7658cd862feaf944d0ea3ce2b new file mode 100644 index 0000000000..18ade57a49 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/e7ef72fdab634ae7658cd862feaf944d0ea3ce2b differ diff --git a/external/boringssl/fuzz/server_corpus/e82273fd2b509ffeaa0a06138fd48878b708c557 b/external/boringssl/fuzz/server_corpus/e82273fd2b509ffeaa0a06138fd48878b708c557 new file mode 100644 index 0000000000..28a5b87cd6 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/e82273fd2b509ffeaa0a06138fd48878b708c557 differ diff --git a/external/boringssl/fuzz/server_corpus/e82e55fa1dc031602bd9db99ef3bfba52828a7e7 b/external/boringssl/fuzz/server_corpus/e82e55fa1dc031602bd9db99ef3bfba52828a7e7 new file mode 100644 index 0000000000..014869bb60 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/e82e55fa1dc031602bd9db99ef3bfba52828a7e7 differ diff --git a/external/boringssl/fuzz/server_corpus/e94b2714af564e9e3ee8b464514a55c2ed46d8ba b/external/boringssl/fuzz/server_corpus/e94b2714af564e9e3ee8b464514a55c2ed46d8ba new file mode 100644 index 0000000000..96422f5e43 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/e94b2714af564e9e3ee8b464514a55c2ed46d8ba differ diff --git a/external/boringssl/fuzz/server_corpus/ebe605930e73da69d25b156cff9dbd13f0861484 b/external/boringssl/fuzz/server_corpus/ebe605930e73da69d25b156cff9dbd13f0861484 new file mode 100644 index 0000000000..85e4c6768b --- /dev/null +++ b/external/boringssl/fuzz/server_corpus/ebe605930e73da69d25b156cff9dbd13f0861484 @@ -0,0 +1 @@ +‡*);›ãÂ)ã×(D \ No newline at end of file diff --git a/external/boringssl/fuzz/server_corpus/ebe60c3b30c6c5bd1ce23e3a033ddfeb4515b303 b/external/boringssl/fuzz/server_corpus/ebe60c3b30c6c5bd1ce23e3a033ddfeb4515b303 new file mode 100644 index 0000000000..5bc0a38285 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/ebe60c3b30c6c5bd1ce23e3a033ddfeb4515b303 differ diff --git a/external/boringssl/fuzz/server_corpus/ec1a7fa84fb643ff5d8c52e225edfd1605218874 b/external/boringssl/fuzz/server_corpus/ec1a7fa84fb643ff5d8c52e225edfd1605218874 new file mode 100644 index 0000000000..0cd4506295 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/ec1a7fa84fb643ff5d8c52e225edfd1605218874 differ diff --git a/external/boringssl/fuzz/server_corpus/ec744f66e6351373f00a36829029d73d597cb976 b/external/boringssl/fuzz/server_corpus/ec744f66e6351373f00a36829029d73d597cb976 new file mode 100644 index 0000000000..341bafa7c8 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/ec744f66e6351373f00a36829029d73d597cb976 differ diff --git a/external/boringssl/fuzz/server_corpus/edd61df88481ddefc20a02e326ada5a6eaa41dec b/external/boringssl/fuzz/server_corpus/edd61df88481ddefc20a02e326ada5a6eaa41dec new file mode 100644 index 0000000000..a4c6030d58 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/edd61df88481ddefc20a02e326ada5a6eaa41dec differ diff --git a/external/boringssl/fuzz/server_corpus/eeb0f79e9507ef27c237ddaac2fc859a1fee8bc9 b/external/boringssl/fuzz/server_corpus/eeb0f79e9507ef27c237ddaac2fc859a1fee8bc9 new file mode 100644 index 0000000000..057d26cae1 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/eeb0f79e9507ef27c237ddaac2fc859a1fee8bc9 differ diff --git a/external/boringssl/fuzz/server_corpus/eee65b9d72dd80d44e3d9f7fb7115503131bdad4 b/external/boringssl/fuzz/server_corpus/eee65b9d72dd80d44e3d9f7fb7115503131bdad4 new file mode 100644 index 0000000000..27e891156a Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/eee65b9d72dd80d44e3d9f7fb7115503131bdad4 differ diff --git a/external/boringssl/fuzz/server_corpus/eef1516de918dcc086d39edc23206bcc7715679d b/external/boringssl/fuzz/server_corpus/eef1516de918dcc086d39edc23206bcc7715679d new file mode 100644 index 0000000000..d891fe2f75 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/eef1516de918dcc086d39edc23206bcc7715679d differ diff --git a/external/boringssl/fuzz/server_corpus/f00bdfcb2a5a22ef03bbdcc3e661335eb4d11c84 b/external/boringssl/fuzz/server_corpus/f00bdfcb2a5a22ef03bbdcc3e661335eb4d11c84 new file mode 100644 index 0000000000..b3015834b5 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/f00bdfcb2a5a22ef03bbdcc3e661335eb4d11c84 differ diff --git a/external/boringssl/fuzz/server_corpus/f06014fa4a9681f2e1e977e4bca8d86a575a8c18 b/external/boringssl/fuzz/server_corpus/f06014fa4a9681f2e1e977e4bca8d86a575a8c18 new file mode 100644 index 0000000000..e13614bf8b Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/f06014fa4a9681f2e1e977e4bca8d86a575a8c18 differ diff --git a/external/boringssl/fuzz/server_corpus/f102f1e3eb74b2b872523c5bcfe1fa0de9d9da30 b/external/boringssl/fuzz/server_corpus/f102f1e3eb74b2b872523c5bcfe1fa0de9d9da30 new file mode 100644 index 0000000000..4b416c84a5 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/f102f1e3eb74b2b872523c5bcfe1fa0de9d9da30 differ diff --git a/external/boringssl/fuzz/server_corpus/f1d972ed5d10bcd4741c0f5eeee723ad245a6a86 b/external/boringssl/fuzz/server_corpus/f1d972ed5d10bcd4741c0f5eeee723ad245a6a86 new file mode 100644 index 0000000000..45ea20449f Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/f1d972ed5d10bcd4741c0f5eeee723ad245a6a86 differ diff --git a/external/boringssl/fuzz/server_corpus/f1ee7dd7ebf5b68a385e5dc1f289116c67aa5fd5 b/external/boringssl/fuzz/server_corpus/f1ee7dd7ebf5b68a385e5dc1f289116c67aa5fd5 new file mode 100644 index 0000000000..00c548197d Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/f1ee7dd7ebf5b68a385e5dc1f289116c67aa5fd5 differ diff --git a/external/boringssl/fuzz/server_corpus/f219ee1ce52714fbdbd6e33c012ec4082efc691b b/external/boringssl/fuzz/server_corpus/f219ee1ce52714fbdbd6e33c012ec4082efc691b new file mode 100644 index 0000000000..c0b8495c29 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/f219ee1ce52714fbdbd6e33c012ec4082efc691b differ diff --git a/external/boringssl/fuzz/server_corpus/f34cbb130fef3f89599402ea6d721b7eb3e5615d b/external/boringssl/fuzz/server_corpus/f34cbb130fef3f89599402ea6d721b7eb3e5615d new file mode 100644 index 0000000000..a58a97213e Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/f34cbb130fef3f89599402ea6d721b7eb3e5615d differ diff --git a/external/boringssl/fuzz/server_corpus/f38adbdf7df8def4641eeb1a28ce0ecf8d9b2fe1 b/external/boringssl/fuzz/server_corpus/f38adbdf7df8def4641eeb1a28ce0ecf8d9b2fe1 new file mode 100644 index 0000000000..ce51689ac0 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/f38adbdf7df8def4641eeb1a28ce0ecf8d9b2fe1 differ diff --git a/external/boringssl/fuzz/server_corpus/f3c3c4eb731e6cfafa5b13667bf2928646d8134a b/external/boringssl/fuzz/server_corpus/f3c3c4eb731e6cfafa5b13667bf2928646d8134a new file mode 100644 index 0000000000..34d168b81b Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/f3c3c4eb731e6cfafa5b13667bf2928646d8134a differ diff --git a/external/boringssl/fuzz/server_corpus/f4425d6adf697df0f85be8758c0cd21d6a5df57a b/external/boringssl/fuzz/server_corpus/f4425d6adf697df0f85be8758c0cd21d6a5df57a new file mode 100644 index 0000000000..b677caa68b Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/f4425d6adf697df0f85be8758c0cd21d6a5df57a differ diff --git a/external/boringssl/fuzz/server_corpus/f465f74ff5a9e4248a332bf306f45cecd8314322 b/external/boringssl/fuzz/server_corpus/f465f74ff5a9e4248a332bf306f45cecd8314322 new file mode 100644 index 0000000000..1d2f857da1 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/f465f74ff5a9e4248a332bf306f45cecd8314322 differ diff --git a/external/boringssl/fuzz/server_corpus/f7bf8c5ec7a71cf8a7f713279901817705eb6ab9 b/external/boringssl/fuzz/server_corpus/f7bf8c5ec7a71cf8a7f713279901817705eb6ab9 new file mode 100644 index 0000000000..32b3d38498 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/f7bf8c5ec7a71cf8a7f713279901817705eb6ab9 differ diff --git a/external/boringssl/fuzz/server_corpus/f80cb481d2d6d253dd4fe0140055a69699ae8fe6 b/external/boringssl/fuzz/server_corpus/f80cb481d2d6d253dd4fe0140055a69699ae8fe6 new file mode 100644 index 0000000000..ee717486a3 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/f80cb481d2d6d253dd4fe0140055a69699ae8fe6 differ diff --git a/external/boringssl/fuzz/server_corpus/f8c000e8f3090950de2c5c1844a45c9148fb9a0b b/external/boringssl/fuzz/server_corpus/f8c000e8f3090950de2c5c1844a45c9148fb9a0b new file mode 100644 index 0000000000..a6c5c44f91 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/f8c000e8f3090950de2c5c1844a45c9148fb9a0b differ diff --git a/external/boringssl/fuzz/server_corpus/f93d7c03d0cdf7ca4313c80a2912ffb1c512149e b/external/boringssl/fuzz/server_corpus/f93d7c03d0cdf7ca4313c80a2912ffb1c512149e new file mode 100644 index 0000000000..972ff639cd Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/f93d7c03d0cdf7ca4313c80a2912ffb1c512149e differ diff --git a/external/boringssl/fuzz/server_corpus/f968e146e317dbb5281aca4634de84461fd1ff82 b/external/boringssl/fuzz/server_corpus/f968e146e317dbb5281aca4634de84461fd1ff82 new file mode 100644 index 0000000000..cfbf8d11e7 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/f968e146e317dbb5281aca4634de84461fd1ff82 differ diff --git a/external/boringssl/fuzz/server_corpus/fa1a1093d1da4f71b18d30481f09eeb7d61e6de1 b/external/boringssl/fuzz/server_corpus/fa1a1093d1da4f71b18d30481f09eeb7d61e6de1 new file mode 100644 index 0000000000..3e346fd23c Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/fa1a1093d1da4f71b18d30481f09eeb7d61e6de1 differ diff --git a/external/boringssl/fuzz/server_corpus/fa929c8218dd1b0676db695576a8f1a66067c685 b/external/boringssl/fuzz/server_corpus/fa929c8218dd1b0676db695576a8f1a66067c685 new file mode 100644 index 0000000000..e16b31f87b Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/fa929c8218dd1b0676db695576a8f1a66067c685 differ diff --git a/external/boringssl/fuzz/server_corpus/fba6554348b195a4752225342ded315662a11a99 b/external/boringssl/fuzz/server_corpus/fba6554348b195a4752225342ded315662a11a99 new file mode 100644 index 0000000000..c0d36960a9 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/fba6554348b195a4752225342ded315662a11a99 differ diff --git a/external/boringssl/fuzz/server_corpus/fc0f2acceb87b5396e0a10054b7ca35a2a124f38 b/external/boringssl/fuzz/server_corpus/fc0f2acceb87b5396e0a10054b7ca35a2a124f38 new file mode 100644 index 0000000000..345895c4c0 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/fc0f2acceb87b5396e0a10054b7ca35a2a124f38 differ diff --git a/external/boringssl/fuzz/server_corpus/fcf1e81b7005c8aea37b5d8f0949a5d3048caf61 b/external/boringssl/fuzz/server_corpus/fcf1e81b7005c8aea37b5d8f0949a5d3048caf61 new file mode 100644 index 0000000000..539f0a147c Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/fcf1e81b7005c8aea37b5d8f0949a5d3048caf61 differ diff --git a/external/boringssl/fuzz/server_corpus/fe9517d5de1d6e4b9d9fa9cc67e809b697e61886 b/external/boringssl/fuzz/server_corpus/fe9517d5de1d6e4b9d9fa9cc67e809b697e61886 new file mode 100644 index 0000000000..349e1dd5af Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/fe9517d5de1d6e4b9d9fa9cc67e809b697e61886 differ diff --git a/external/boringssl/fuzz/server_corpus/feb2a10cc688251772b52cbdf910f45130ed07db b/external/boringssl/fuzz/server_corpus/feb2a10cc688251772b52cbdf910f45130ed07db new file mode 100644 index 0000000000..a0b073dccd Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/feb2a10cc688251772b52cbdf910f45130ed07db differ diff --git a/external/boringssl/fuzz/server_corpus/fed06ee7931bb35a7cfdc9699f928df530bc2602 b/external/boringssl/fuzz/server_corpus/fed06ee7931bb35a7cfdc9699f928df530bc2602 new file mode 100644 index 0000000000..515f40f02a Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/fed06ee7931bb35a7cfdc9699f928df530bc2602 differ diff --git a/external/boringssl/fuzz/server_corpus/ff01b583eddbccbe7c7ea08e7f83873310d91f0f b/external/boringssl/fuzz/server_corpus/ff01b583eddbccbe7c7ea08e7f83873310d91f0f new file mode 100644 index 0000000000..583d85bf26 Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/ff01b583eddbccbe7c7ea08e7f83873310d91f0f differ diff --git a/external/boringssl/fuzz/server_corpus/ff164d41110cbdcf7b035bd2eeb1c0fdabeaf439 b/external/boringssl/fuzz/server_corpus/ff164d41110cbdcf7b035bd2eeb1c0fdabeaf439 new file mode 100644 index 0000000000..87d99998ca Binary files /dev/null and b/external/boringssl/fuzz/server_corpus/ff164d41110cbdcf7b035bd2eeb1c0fdabeaf439 differ diff --git a/external/boringssl/fuzz/spki.cc b/external/boringssl/fuzz/spki.cc new file mode 100644 index 0000000000..939d7196a6 --- /dev/null +++ b/external/boringssl/fuzz/spki.cc @@ -0,0 +1,38 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include +#include + +extern "C" int LLVMFuzzerTestOneInput(uint8_t *buf, size_t len) { + CBS cbs; + CBS_init(&cbs, buf, len); + EVP_PKEY *pkey = EVP_parse_public_key(&cbs); + if (pkey == NULL) { + return 0; + } + + uint8_t *der; + size_t der_len; + CBB cbb; + if (CBB_init(&cbb, 0) && + EVP_marshal_public_key(&cbb, pkey) && + CBB_finish(&cbb, &der, &der_len)) { + OPENSSL_free(der); + } + CBB_cleanup(&cbb); + EVP_PKEY_free(pkey); + return 0; +} diff --git a/external/boringssl/fuzz/spki_corpus/04f58baf6e4bba0bb3094e2e26d3a531a7c263ee b/external/boringssl/fuzz/spki_corpus/04f58baf6e4bba0bb3094e2e26d3a531a7c263ee new file mode 100644 index 0000000000..d1eac6d588 Binary files /dev/null and b/external/boringssl/fuzz/spki_corpus/04f58baf6e4bba0bb3094e2e26d3a531a7c263ee differ diff --git a/external/boringssl/fuzz/spki_corpus/079bdf85c086ad0a92bd01f1f70c645d81053f3a b/external/boringssl/fuzz/spki_corpus/079bdf85c086ad0a92bd01f1f70c645d81053f3a new file mode 100644 index 0000000000..a6eb9d4c42 Binary files /dev/null and b/external/boringssl/fuzz/spki_corpus/079bdf85c086ad0a92bd01f1f70c645d81053f3a differ diff --git a/external/boringssl/fuzz/spki_corpus/0f5bd094b20a4632f14903bf62db8d467d2c548f b/external/boringssl/fuzz/spki_corpus/0f5bd094b20a4632f14903bf62db8d467d2c548f new file mode 100644 index 0000000000..2bd95c3b2a Binary files /dev/null and b/external/boringssl/fuzz/spki_corpus/0f5bd094b20a4632f14903bf62db8d467d2c548f differ diff --git a/external/boringssl/fuzz/spki_corpus/183c579d75863c1e10100f76e3ffb757b44a9587 b/external/boringssl/fuzz/spki_corpus/183c579d75863c1e10100f76e3ffb757b44a9587 new file mode 100644 index 0000000000..e3a1ed7b32 Binary files /dev/null and b/external/boringssl/fuzz/spki_corpus/183c579d75863c1e10100f76e3ffb757b44a9587 differ diff --git a/external/boringssl/fuzz/spki_corpus/4ee178363e1d8411f30e540cb97d550d4ce62f0c b/external/boringssl/fuzz/spki_corpus/4ee178363e1d8411f30e540cb97d550d4ce62f0c new file mode 100644 index 0000000000..471dddf617 Binary files /dev/null and b/external/boringssl/fuzz/spki_corpus/4ee178363e1d8411f30e540cb97d550d4ce62f0c differ diff --git a/external/boringssl/fuzz/spki_corpus/70da87d1d374ade329433dde31805abc8d80d915 b/external/boringssl/fuzz/spki_corpus/70da87d1d374ade329433dde31805abc8d80d915 new file mode 100644 index 0000000000..e6deda1081 Binary files /dev/null and b/external/boringssl/fuzz/spki_corpus/70da87d1d374ade329433dde31805abc8d80d915 differ diff --git a/external/boringssl/fuzz/spki_corpus/de0338b0c809548dc79d5a34e28b0010852a8f00 b/external/boringssl/fuzz/spki_corpus/de0338b0c809548dc79d5a34e28b0010852a8f00 new file mode 100644 index 0000000000..81cbe26f1a Binary files /dev/null and b/external/boringssl/fuzz/spki_corpus/de0338b0c809548dc79d5a34e28b0010852a8f00 differ diff --git a/external/boringssl/fuzz/spki_corpus/fc941f77c710354d3c3c1426432a5ee935d51dd6 b/external/boringssl/fuzz/spki_corpus/fc941f77c710354d3c3c1426432a5ee935d51dd6 new file mode 100644 index 0000000000..10e16744c0 Binary files /dev/null and b/external/boringssl/fuzz/spki_corpus/fc941f77c710354d3c3c1426432a5ee935d51dd6 differ diff --git a/external/boringssl/include/openssl/aead.h b/external/boringssl/include/openssl/aead.h new file mode 100644 index 0000000000..7895825c01 --- /dev/null +++ b/external/boringssl/include/openssl/aead.h @@ -0,0 +1,338 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_AEAD_H +#define OPENSSL_HEADER_AEAD_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* Authenticated Encryption with Additional Data. + * + * AEAD couples confidentiality and integrity in a single primitive. AEAD + * algorithms take a key and then can seal and open individual messages. Each + * message has a unique, per-message nonce and, optionally, additional data + * which is authenticated but not included in the ciphertext. + * + * The |EVP_AEAD_CTX_init| function initialises an |EVP_AEAD_CTX| structure and + * performs any precomputation needed to use |aead| with |key|. The length of + * the key, |key_len|, is given in bytes. + * + * The |tag_len| argument contains the length of the tags, in bytes, and allows + * for the processing of truncated authenticators. A zero value indicates that + * the default tag length should be used and this is defined as + * |EVP_AEAD_DEFAULT_TAG_LENGTH| in order to make the code clear. Using + * truncated tags increases an attacker's chance of creating a valid forgery. + * Be aware that the attacker's chance may increase more than exponentially as + * would naively be expected. + * + * When no longer needed, the initialised |EVP_AEAD_CTX| structure must be + * passed to |EVP_AEAD_CTX_cleanup|, which will deallocate any memory used. + * + * With an |EVP_AEAD_CTX| in hand, one can seal and open messages. These + * operations are intended to meet the standard notions of privacy and + * authenticity for authenticated encryption. For formal definitions see + * Bellare and Namprempre, "Authenticated encryption: relations among notions + * and analysis of the generic composition paradigm," Lecture Notes in Computer + * Science B<1976> (2000), 531–545, + * http://www-cse.ucsd.edu/~mihir/papers/oem.html. + * + * When sealing messages, a nonce must be given. The length of the nonce is + * fixed by the AEAD in use and is returned by |EVP_AEAD_nonce_length|. *The + * nonce must be unique for all messages with the same key*. This is critically + * important - nonce reuse may completely undermine the security of the AEAD. + * Nonces may be predictable and public, so long as they are unique. Uniqueness + * may be achieved with a simple counter or, if large enough, may be generated + * randomly. The nonce must be passed into the "open" operation by the receiver + * so must either be implicit (e.g. a counter), or must be transmitted along + * with the sealed message. + * + * The "seal" and "open" operations are atomic - an entire message must be + * encrypted or decrypted in a single call. Large messages may have to be split + * up in order to accomodate this. When doing so, be mindful of the need not to + * repeat nonces and the possibility that an attacker could duplicate, reorder + * or drop message chunks. For example, using a single key for a given (large) + * message and sealing chunks with nonces counting from zero would be secure as + * long as the number of chunks was securely transmitted. (Otherwise an + * attacker could truncate the message by dropping chunks from the end.) + * + * The number of chunks could be transmitted by prefixing it to the plaintext, + * for example. This also assumes that no other message would ever use the same + * key otherwise the rule that nonces must be unique for a given key would be + * violated. + * + * The "seal" and "open" operations also permit additional data to be + * authenticated via the |ad| parameter. This data is not included in the + * ciphertext and must be identical for both the "seal" and "open" call. This + * permits implicit context to be authenticated but may be empty if not needed. + * + * The "seal" and "open" operations may work in-place if the |out| and |in| + * arguments are equal. They may also be used to shift the data left inside the + * same buffer if |out| is less than |in|. However, |out| may not point inside + * the input data otherwise the input may be overwritten before it has been + * read. This situation will cause an error. + * + * The "seal" and "open" operations return one on success and zero on error. */ + + +/* AEAD algorithms. */ + +/* EVP_aead_aes_128_gcm is AES-128 in Galois Counter Mode. */ +OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_gcm(void); + +/* EVP_aead_aes_256_gcm is AES-256 in Galois Counter Mode. */ +OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_gcm(void); + +/* EVP_aead_chacha20_poly1305 is the AEAD built from ChaCha20 and + * Poly1305 as described in RFC 7539. */ +OPENSSL_EXPORT const EVP_AEAD *EVP_aead_chacha20_poly1305(void); + +/* EVP_aead_chacha20_poly1305_old is an AEAD built from ChaCha20 and + * Poly1305 that is used in the experimental ChaCha20-Poly1305 TLS cipher + * suites. */ +OPENSSL_EXPORT const EVP_AEAD *EVP_aead_chacha20_poly1305_old(void); + +/* EVP_aead_aes_128_key_wrap is AES-128 Key Wrap mode. This should never be + * used except to interoperate with existing systems that use this mode. + * + * If the nonce is empty then the default nonce will be used, otherwise it must + * be eight bytes long. The input must be a multiple of eight bytes long. No + * additional data can be given to this mode. */ +OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_key_wrap(void); + +/* EVP_aead_aes_256_key_wrap is AES-256 in Key Wrap mode. This should never be + * used except to interoperate with existing systems that use this mode. + * + * See |EVP_aead_aes_128_key_wrap| for details. */ +OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_key_wrap(void); + +/* EVP_aead_aes_128_ctr_hmac_sha256 is AES-128 in CTR mode with HMAC-SHA256 for + * authentication. The nonce is 12 bytes; the bottom 32-bits are used as the + * block counter, thus the maximum plaintext size is 64GB. */ +OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_ctr_hmac_sha256(void); + +/* EVP_aead_aes_256_ctr_hmac_sha256 is AES-256 in CTR mode with HMAC-SHA256 for + * authentication. See |EVP_aead_aes_128_ctr_hmac_sha256| for details. */ +OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_ctr_hmac_sha256(void); + +/* EVP_has_aes_hardware returns one if we enable hardware support for fast and + * constant-time AES-GCM. */ +OPENSSL_EXPORT int EVP_has_aes_hardware(void); + + +/* Utility functions. */ + +/* EVP_AEAD_key_length returns the length, in bytes, of the keys used by + * |aead|. */ +OPENSSL_EXPORT size_t EVP_AEAD_key_length(const EVP_AEAD *aead); + +/* EVP_AEAD_nonce_length returns the length, in bytes, of the per-message nonce + * for |aead|. */ +OPENSSL_EXPORT size_t EVP_AEAD_nonce_length(const EVP_AEAD *aead); + +/* EVP_AEAD_max_overhead returns the maximum number of additional bytes added + * by the act of sealing data with |aead|. */ +OPENSSL_EXPORT size_t EVP_AEAD_max_overhead(const EVP_AEAD *aead); + +/* EVP_AEAD_max_tag_len returns the maximum tag length when using |aead|. This + * is the largest value that can be passed as |tag_len| to + * |EVP_AEAD_CTX_init|. */ +OPENSSL_EXPORT size_t EVP_AEAD_max_tag_len(const EVP_AEAD *aead); + + +/* AEAD operations. */ + +/* An EVP_AEAD_CTX represents an AEAD algorithm configured with a specific key + * and message-independent IV. */ +typedef struct evp_aead_ctx_st { + const EVP_AEAD *aead; + /* aead_state is an opaque pointer to whatever state the AEAD needs to + * maintain. */ + void *aead_state; +} EVP_AEAD_CTX; + +/* EVP_AEAD_MAX_KEY_LENGTH contains the maximum key length used by + * any AEAD defined in this header. */ +#define EVP_AEAD_MAX_KEY_LENGTH 80 + +/* EVP_AEAD_MAX_NONCE_LENGTH contains the maximum nonce length used by + * any AEAD defined in this header. */ +#define EVP_AEAD_MAX_NONCE_LENGTH 16 + +/* EVP_AEAD_MAX_OVERHEAD contains the maximum overhead used by any AEAD + * defined in this header. */ +#define EVP_AEAD_MAX_OVERHEAD 64 + +/* EVP_AEAD_DEFAULT_TAG_LENGTH is a magic value that can be passed to + * EVP_AEAD_CTX_init to indicate that the default tag length for an AEAD should + * be used. */ +#define EVP_AEAD_DEFAULT_TAG_LENGTH 0 + +/* EVP_AEAD_CTX_zero sets an uninitialized |ctx| to the zero state. It must be + * initialized with |EVP_AEAD_CTX_init| before use. It is safe, but not + * necessary, to call |EVP_AEAD_CTX_cleanup| in this state. This may be used for + * more uniform cleanup of |EVP_AEAD_CTX|. */ +OPENSSL_EXPORT void EVP_AEAD_CTX_zero(EVP_AEAD_CTX *ctx); + +/* EVP_AEAD_CTX_init initializes |ctx| for the given AEAD algorithm. The |impl| + * argument is ignored and should be NULL. Authentication tags may be truncated + * by passing a size as |tag_len|. A |tag_len| of zero indicates the default + * tag length and this is defined as EVP_AEAD_DEFAULT_TAG_LENGTH for + * readability. + * + * Returns 1 on success. Otherwise returns 0 and pushes to the error stack. In + * the error case, you do not need to call |EVP_AEAD_CTX_cleanup|, but it's + * harmless to do so. */ +OPENSSL_EXPORT int EVP_AEAD_CTX_init(EVP_AEAD_CTX *ctx, const EVP_AEAD *aead, + const uint8_t *key, size_t key_len, + size_t tag_len, ENGINE *impl); + +/* EVP_AEAD_CTX_cleanup frees any data allocated by |ctx|. It is a no-op to + * call |EVP_AEAD_CTX_cleanup| on a |EVP_AEAD_CTX| that has been |memset| to + * all zeros. */ +OPENSSL_EXPORT void EVP_AEAD_CTX_cleanup(EVP_AEAD_CTX *ctx); + +/* EVP_AEAD_CTX_seal encrypts and authenticates |in_len| bytes from |in| and + * authenticates |ad_len| bytes from |ad| and writes the result to |out|. It + * returns one on success and zero otherwise. + * + * This function may be called (with the same |EVP_AEAD_CTX|) concurrently with + * itself or |EVP_AEAD_CTX_open|. + * + * At most |max_out_len| bytes are written to |out| and, in order to ensure + * success, |max_out_len| should be |in_len| plus the result of + * |EVP_AEAD_max_overhead|. On successful return, |*out_len| is set to the + * actual number of bytes written. + * + * The length of |nonce|, |nonce_len|, must be equal to the result of + * |EVP_AEAD_nonce_length| for this AEAD. + * + * |EVP_AEAD_CTX_seal| never results in a partial output. If |max_out_len| is + * insufficient, zero will be returned. (In this case, |*out_len| is set to + * zero.) + * + * If |in| and |out| alias then |out| must be == |in|. */ +OPENSSL_EXPORT int EVP_AEAD_CTX_seal(const EVP_AEAD_CTX *ctx, uint8_t *out, + size_t *out_len, size_t max_out_len, + const uint8_t *nonce, size_t nonce_len, + const uint8_t *in, size_t in_len, + const uint8_t *ad, size_t ad_len); + +/* EVP_AEAD_CTX_open authenticates |in_len| bytes from |in| and |ad_len| bytes + * from |ad| and decrypts at most |in_len| bytes into |out|. It returns one on + * success and zero otherwise. + * + * This function may be called (with the same |EVP_AEAD_CTX|) concurrently with + * itself or |EVP_AEAD_CTX_seal|. + * + * At most |in_len| bytes are written to |out|. In order to ensure success, + * |max_out_len| should be at least |in_len|. On successful return, |*out_len| + * is set to the the actual number of bytes written. + * + * The length of |nonce|, |nonce_len|, must be equal to the result of + * |EVP_AEAD_nonce_length| for this AEAD. + * + * |EVP_AEAD_CTX_open| never results in a partial output. If |max_out_len| is + * insufficient, zero will be returned. (In this case, |*out_len| is set to + * zero.) + * + * If |in| and |out| alias then |out| must be == |in|. */ +OPENSSL_EXPORT int EVP_AEAD_CTX_open(const EVP_AEAD_CTX *ctx, uint8_t *out, + size_t *out_len, size_t max_out_len, + const uint8_t *nonce, size_t nonce_len, + const uint8_t *in, size_t in_len, + const uint8_t *ad, size_t ad_len); + + +/* TLS-specific AEAD algorithms. + * + * These AEAD primitives do not meet the definition of generic AEADs. They are + * all specific to TLS and should not be used outside of that context. They must + * be initialized with |EVP_AEAD_CTX_init_with_direction|, are stateful, and may + * not be used concurrently. Any nonces are used as IVs, so they must be + * unpredictable. They only accept an |ad| parameter of length 11 (the standard + * TLS one with length omitted). */ + +OPENSSL_EXPORT const EVP_AEAD *EVP_aead_rc4_md5_tls(void); +OPENSSL_EXPORT const EVP_AEAD *EVP_aead_rc4_sha1_tls(void); + +OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_cbc_sha1_tls(void); +OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_cbc_sha1_tls_implicit_iv(void); +OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_cbc_sha256_tls(void); + +OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_cbc_sha1_tls(void); +OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_cbc_sha1_tls_implicit_iv(void); +OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_cbc_sha256_tls(void); +OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_cbc_sha384_tls(void); + +OPENSSL_EXPORT const EVP_AEAD *EVP_aead_des_ede3_cbc_sha1_tls(void); +OPENSSL_EXPORT const EVP_AEAD *EVP_aead_des_ede3_cbc_sha1_tls_implicit_iv(void); + +OPENSSL_EXPORT const EVP_AEAD *EVP_aead_null_sha1_tls(void); + + +/* SSLv3-specific AEAD algorithms. + * + * These AEAD primitives do not meet the definition of generic AEADs. They are + * all specific to SSLv3 and should not be used outside of that context. They + * must be initialized with |EVP_AEAD_CTX_init_with_direction|, are stateful, + * and may not be used concurrently. They only accept an |ad| parameter of + * length 9 (the standard TLS one with length and version omitted). */ + +OPENSSL_EXPORT const EVP_AEAD *EVP_aead_rc4_md5_ssl3(void); +OPENSSL_EXPORT const EVP_AEAD *EVP_aead_rc4_sha1_ssl3(void); +OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_cbc_sha1_ssl3(void); +OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_cbc_sha1_ssl3(void); +OPENSSL_EXPORT const EVP_AEAD *EVP_aead_des_ede3_cbc_sha1_ssl3(void); +OPENSSL_EXPORT const EVP_AEAD *EVP_aead_null_sha1_ssl3(void); + + +/* Obscure functions. */ + +/* evp_aead_direction_t denotes the direction of an AEAD operation. */ +enum evp_aead_direction_t { + evp_aead_open, + evp_aead_seal, +}; + +/* EVP_AEAD_CTX_init_with_direction calls |EVP_AEAD_CTX_init| for normal + * AEADs. For TLS-specific and SSL3-specific AEADs, it initializes |ctx| for a + * given direction. */ +OPENSSL_EXPORT int EVP_AEAD_CTX_init_with_direction( + EVP_AEAD_CTX *ctx, const EVP_AEAD *aead, const uint8_t *key, size_t key_len, + size_t tag_len, enum evp_aead_direction_t dir); + +/* EVP_AEAD_CTX_get_rc4_state sets |*out_key| to point to an RC4 key structure. + * It returns one on success or zero if |ctx| doesn't have an RC4 key. */ +OPENSSL_EXPORT int EVP_AEAD_CTX_get_rc4_state(const EVP_AEAD_CTX *ctx, + const RC4_KEY **out_key); + +/* EVP_AEAD_CTX_get_iv sets |*out_len| to the length of the IV for |ctx| and + * sets |*out_iv| to point to that many bytes of the current IV. This is only + * meaningful for AEADs with implicit IVs (i.e. CBC mode in SSLv3 and TLS 1.0). + * + * It returns one on success or zero on error. */ +OPENSSL_EXPORT int EVP_AEAD_CTX_get_iv(const EVP_AEAD_CTX *ctx, + const uint8_t **out_iv, size_t *out_len); + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_AEAD_H */ diff --git a/external/boringssl/include/openssl/aes.h b/external/boringssl/include/openssl/aes.h new file mode 100644 index 0000000000..ed060ff669 --- /dev/null +++ b/external/boringssl/include/openssl/aes.h @@ -0,0 +1,158 @@ +/* ==================================================================== + * Copyright (c) 2002-2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== */ + +#ifndef OPENSSL_HEADER_AES_H +#define OPENSSL_HEADER_AES_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* Raw AES functions. */ + + +#define AES_ENCRYPT 1 +#define AES_DECRYPT 0 + +/* AES_MAXNR is the maximum number of AES rounds. */ +#define AES_MAXNR 14 + +#define AES_BLOCK_SIZE 16 + +/* aes_key_st should be an opaque type, but EVP requires that the size be + * known. */ +struct aes_key_st { + uint32_t rd_key[4 * (AES_MAXNR + 1)]; + unsigned rounds; +}; +typedef struct aes_key_st AES_KEY; + +/* AES_set_encrypt_key configures |aeskey| to encrypt with the |bits|-bit key, + * |key|. + * + * WARNING: unlike other OpenSSL functions, this returns zero on success and a + * negative number on error. */ +OPENSSL_EXPORT int AES_set_encrypt_key(const uint8_t *key, unsigned bits, + AES_KEY *aeskey); + +/* AES_set_decrypt_key configures |aeskey| to decrypt with the |bits|-bit key, + * |key|. + * + * WARNING: unlike other OpenSSL functions, this returns zero on success and a + * negative number on error. */ +OPENSSL_EXPORT int AES_set_decrypt_key(const uint8_t *key, unsigned bits, + AES_KEY *aeskey); + +/* AES_encrypt encrypts a single block from |in| to |out| with |key|. The |in| + * and |out| pointers may overlap. */ +OPENSSL_EXPORT void AES_encrypt(const uint8_t *in, uint8_t *out, + const AES_KEY *key); + +/* AES_decrypt decrypts a single block from |in| to |out| with |key|. The |in| + * and |out| pointers may overlap. */ +OPENSSL_EXPORT void AES_decrypt(const uint8_t *in, uint8_t *out, + const AES_KEY *key); + + +/* Block cipher modes. */ + +/* AES_ctr128_encrypt encrypts (or decrypts, it's the same in CTR mode) |len| + * bytes from |in| to |out|. The |num| parameter must be set to zero on the + * first call and |ivec| will be incremented. */ +OPENSSL_EXPORT void AES_ctr128_encrypt(const uint8_t *in, uint8_t *out, + size_t len, const AES_KEY *key, + uint8_t ivec[AES_BLOCK_SIZE], + uint8_t ecount_buf[AES_BLOCK_SIZE], + unsigned int *num); + +/* AES_ecb_encrypt encrypts (or decrypts, if |enc| == |AES_DECRYPT|) a single, + * 16 byte block from |in| to |out|. */ +OPENSSL_EXPORT void AES_ecb_encrypt(const uint8_t *in, uint8_t *out, + const AES_KEY *key, const int enc); + +/* AES_cbc_encrypt encrypts (or decrypts, if |enc| == |AES_DECRYPT|) |len| + * bytes from |in| to |out|. The length must be a multiple of the block size. */ +OPENSSL_EXPORT void AES_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t len, + const AES_KEY *key, uint8_t *ivec, + const int enc); + +/* AES_ofb128_encrypt encrypts (or decrypts, it's the same in OFB mode) |len| + * bytes from |in| to |out|. The |num| parameter must be set to zero on the + * first call. */ +OPENSSL_EXPORT void AES_ofb128_encrypt(const uint8_t *in, uint8_t *out, + size_t len, const AES_KEY *key, + uint8_t *ivec, int *num); + +/* AES_cfb128_encrypt encrypts (or decrypts, if |enc| == |AES_DECRYPT|) |len| + * bytes from |in| to |out|. The |num| parameter must be set to zero on the + * first call. */ +OPENSSL_EXPORT void AES_cfb128_encrypt(const uint8_t *in, uint8_t *out, + size_t len, const AES_KEY *key, + uint8_t *ivec, int *num, int enc); + + +/* Android compatibility section. + * + * These functions are declared, temporarily, for Android because + * wpa_supplicant will take a little time to sync with upstream. Outside of + * Android they'll have no definition. */ + +OPENSSL_EXPORT int AES_wrap_key(AES_KEY *key, const uint8_t *iv, uint8_t *out, + const uint8_t *in, unsigned in_len); +OPENSSL_EXPORT int AES_unwrap_key(AES_KEY *key, const uint8_t *iv, uint8_t *out, + const uint8_t *in, unsigned in_len); + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_AES_H */ diff --git a/external/boringssl/include/openssl/arm_arch.h b/external/boringssl/include/openssl/arm_arch.h new file mode 100644 index 0000000000..e7010f4029 --- /dev/null +++ b/external/boringssl/include/openssl/arm_arch.h @@ -0,0 +1,121 @@ +/* ==================================================================== + * Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#ifndef OPENSSL_HEADER_ARM_ARCH_H +#define OPENSSL_HEADER_ARM_ARCH_H + +#if !defined(__ARM_ARCH__) +# if defined(__CC_ARM) +# define __ARM_ARCH__ __TARGET_ARCH_ARM +# if defined(__BIG_ENDIAN) +# define __ARMEB__ +# else +# define __ARMEL__ +# endif +# elif defined(__GNUC__) +# if defined(__aarch64__) +# define __ARM_ARCH__ 8 +# if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +# define __ARMEB__ +# else +# define __ARMEL__ +# endif + /* Why doesn't gcc define __ARM_ARCH__? Instead it defines + * bunch of below macros. See all_architectires[] table in + * gcc/config/arm/arm.c. On a side note it defines + * __ARMEL__/__ARMEB__ for little-/big-endian. */ +# elif defined(__ARM_ARCH) +# define __ARM_ARCH__ __ARM_ARCH +# elif defined(__ARM_ARCH_8A__) +# define __ARM_ARCH__ 8 +# elif defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || \ + defined(__ARM_ARCH_7R__)|| defined(__ARM_ARCH_7M__) || \ + defined(__ARM_ARCH_7EM__) +# define __ARM_ARCH__ 7 +# elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || \ + defined(__ARM_ARCH_6K__)|| defined(__ARM_ARCH_6M__) || \ + defined(__ARM_ARCH_6Z__)|| defined(__ARM_ARCH_6ZK__) || \ + defined(__ARM_ARCH_6T2__) +# define __ARM_ARCH__ 6 +# elif defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) || \ + defined(__ARM_ARCH_5E__)|| defined(__ARM_ARCH_5TE__) || \ + defined(__ARM_ARCH_5TEJ__) +# define __ARM_ARCH__ 5 +# elif defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__) +# define __ARM_ARCH__ 4 +# else +# error "unsupported ARM architecture" +# endif +# endif +#endif + +/* Even when building for 32-bit ARM, support for aarch64 crypto instructions + * will be included. */ +#define __ARM_MAX_ARCH__ 8 + +/* ARMV7_NEON is true when a NEON unit is present in the current CPU. */ +#define ARMV7_NEON (1 << 0) + +/* ARMV8_AES indicates support for hardware AES instructions. */ +#define ARMV8_AES (1 << 2) + +/* ARMV8_SHA1 indicates support for hardware SHA-1 instructions. */ +#define ARMV8_SHA1 (1 << 3) + +/* ARMV8_SHA256 indicates support for hardware SHA-256 instructions. */ +#define ARMV8_SHA256 (1 << 4) + +/* ARMV8_PMULL indicates support for carryless multiplication. */ +#define ARMV8_PMULL (1 << 5) + + +#endif /* OPENSSL_HEADER_ARM_ARCH_H */ diff --git a/external/boringssl/include/openssl/asn1.h b/external/boringssl/include/openssl/asn1.h new file mode 100644 index 0000000000..42c953510d --- /dev/null +++ b/external/boringssl/include/openssl/asn1.h @@ -0,0 +1,1114 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_ASN1_H +#define HEADER_ASN1_H + +#include + +#include + +#include +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define V_ASN1_UNIVERSAL 0x00 +#define V_ASN1_APPLICATION 0x40 +#define V_ASN1_CONTEXT_SPECIFIC 0x80 +#define V_ASN1_PRIVATE 0xc0 + +#define V_ASN1_CONSTRUCTED 0x20 +#define V_ASN1_PRIMITIVE_TAG 0x1f +#define V_ASN1_PRIMATIVE_TAG 0x1f + +#define V_ASN1_APP_CHOOSE -2 /* let the recipient choose */ +#define V_ASN1_OTHER -3 /* used in ASN1_TYPE */ +#define V_ASN1_ANY -4 /* used in ASN1 template code */ + +#define V_ASN1_NEG 0x100 /* negative flag */ +/* No supported universal tags may exceed this value, to avoid ambiguity with + * V_ASN1_NEG. */ +#define V_ASN1_MAX_UNIVERSAL 0xff + +#define V_ASN1_UNDEF -1 +#define V_ASN1_EOC 0 +#define V_ASN1_BOOLEAN 1 /**/ +#define V_ASN1_INTEGER 2 +#define V_ASN1_NEG_INTEGER (2 | V_ASN1_NEG) +#define V_ASN1_BIT_STRING 3 +#define V_ASN1_OCTET_STRING 4 +#define V_ASN1_NULL 5 +#define V_ASN1_OBJECT 6 +#define V_ASN1_OBJECT_DESCRIPTOR 7 +#define V_ASN1_EXTERNAL 8 +#define V_ASN1_REAL 9 +#define V_ASN1_ENUMERATED 10 +#define V_ASN1_NEG_ENUMERATED (10 | V_ASN1_NEG) +#define V_ASN1_UTF8STRING 12 +#define V_ASN1_SEQUENCE 16 +#define V_ASN1_SET 17 +#define V_ASN1_NUMERICSTRING 18 /**/ +#define V_ASN1_PRINTABLESTRING 19 +#define V_ASN1_T61STRING 20 +#define V_ASN1_TELETEXSTRING 20 /* alias */ +#define V_ASN1_VIDEOTEXSTRING 21 /**/ +#define V_ASN1_IA5STRING 22 +#define V_ASN1_UTCTIME 23 +#define V_ASN1_GENERALIZEDTIME 24 /**/ +#define V_ASN1_GRAPHICSTRING 25 /**/ +#define V_ASN1_ISO64STRING 26 /**/ +#define V_ASN1_VISIBLESTRING 26 /* alias */ +#define V_ASN1_GENERALSTRING 27 /**/ +#define V_ASN1_UNIVERSALSTRING 28 /**/ +#define V_ASN1_BMPSTRING 30 + +/* For use with d2i_ASN1_type_bytes() */ +#define B_ASN1_NUMERICSTRING 0x0001 +#define B_ASN1_PRINTABLESTRING 0x0002 +#define B_ASN1_T61STRING 0x0004 +#define B_ASN1_TELETEXSTRING 0x0004 +#define B_ASN1_VIDEOTEXSTRING 0x0008 +#define B_ASN1_IA5STRING 0x0010 +#define B_ASN1_GRAPHICSTRING 0x0020 +#define B_ASN1_ISO64STRING 0x0040 +#define B_ASN1_VISIBLESTRING 0x0040 +#define B_ASN1_GENERALSTRING 0x0080 +#define B_ASN1_UNIVERSALSTRING 0x0100 +#define B_ASN1_OCTET_STRING 0x0200 +#define B_ASN1_BIT_STRING 0x0400 +#define B_ASN1_BMPSTRING 0x0800 +#define B_ASN1_UNKNOWN 0x1000 +#define B_ASN1_UTF8STRING 0x2000 +#define B_ASN1_UTCTIME 0x4000 +#define B_ASN1_GENERALIZEDTIME 0x8000 +#define B_ASN1_SEQUENCE 0x10000 + +/* For use with ASN1_mbstring_copy() */ +#define MBSTRING_FLAG 0x1000 +#define MBSTRING_UTF8 (MBSTRING_FLAG) +#define MBSTRING_ASC (MBSTRING_FLAG|1) +#define MBSTRING_BMP (MBSTRING_FLAG|2) +#define MBSTRING_UNIV (MBSTRING_FLAG|4) + +#define SMIME_OLDMIME 0x400 +#define SMIME_CRLFEOL 0x800 +#define SMIME_STREAM 0x1000 + +#define DECLARE_ASN1_SET_OF(type) /* filled in by mkstack.pl */ +#define IMPLEMENT_ASN1_SET_OF(type) /* nothing, no longer needed */ + +/* We MUST make sure that, except for constness, asn1_ctx_st and + asn1_const_ctx are exactly the same. Fortunately, as soon as + the old ASN1 parsing macros are gone, we can throw this away + as well... */ +typedef struct asn1_ctx_st + { + unsigned char *p;/* work char pointer */ + int eos; /* end of sequence read for indefinite encoding */ + int error; /* error code to use when returning an error */ + int inf; /* constructed if 0x20, indefinite is 0x21 */ + int tag; /* tag from last 'get object' */ + int xclass; /* class from last 'get object' */ + long slen; /* length of last 'get object' */ + unsigned char *max; /* largest value of p allowed */ + unsigned char *q;/* temporary variable */ + unsigned char **pp;/* variable */ + int line; /* used in error processing */ + } ASN1_CTX; + +typedef struct asn1_const_ctx_st + { + const unsigned char *p;/* work char pointer */ + int eos; /* end of sequence read for indefinite encoding */ + int error; /* error code to use when returning an error */ + int inf; /* constructed if 0x20, indefinite is 0x21 */ + int tag; /* tag from last 'get object' */ + int xclass; /* class from last 'get object' */ + long slen; /* length of last 'get object' */ + const unsigned char *max; /* largest value of p allowed */ + const unsigned char *q;/* temporary variable */ + const unsigned char **pp;/* variable */ + int line; /* used in error processing */ + } ASN1_const_CTX; + +/* These are used internally in the ASN1_OBJECT to keep track of + * whether the names and data need to be free()ed */ +#define ASN1_OBJECT_FLAG_DYNAMIC 0x01 /* internal use */ +#define ASN1_OBJECT_FLAG_CRITICAL 0x02 /* critical x509v3 object id */ +#define ASN1_OBJECT_FLAG_DYNAMIC_STRINGS 0x04 /* internal use */ +#define ASN1_OBJECT_FLAG_DYNAMIC_DATA 0x08 /* internal use */ +struct asn1_object_st + { + const char *sn,*ln; + int nid; + int length; + const unsigned char *data; /* data remains const after init */ + int flags; /* Should we free this one */ + }; + +#define ASN1_STRING_FLAG_BITS_LEFT 0x08 /* Set if 0x07 has bits left value */ +/* This indicates that the ASN1_STRING is not a real value but just a place + * holder for the location where indefinite length constructed data should + * be inserted in the memory buffer + */ +#define ASN1_STRING_FLAG_NDEF 0x010 + +/* This flag is used by the CMS code to indicate that a string is not + * complete and is a place holder for content when it had all been + * accessed. The flag will be reset when content has been written to it. + */ + +#define ASN1_STRING_FLAG_CONT 0x020 +/* This flag is used by ASN1 code to indicate an ASN1_STRING is an MSTRING + * type. + */ +#define ASN1_STRING_FLAG_MSTRING 0x040 +/* This is the base type that holds just about everything :-) */ +struct asn1_string_st + { + int length; + int type; + unsigned char *data; + /* The value of the following field depends on the type being + * held. It is mostly being used for BIT_STRING so if the + * input data has a non-zero 'unused bits' value, it will be + * handled correctly */ + long flags; + }; + +/* ASN1_ENCODING structure: this is used to save the received + * encoding of an ASN1 type. This is useful to get round + * problems with invalid encodings which can break signatures. + */ + +typedef struct ASN1_ENCODING_st + { + unsigned char *enc; /* DER encoding */ + long len; /* Length of encoding */ + int modified; /* set to 1 if 'enc' is invalid */ + } ASN1_ENCODING; + +/* Used with ASN1 LONG type: if a long is set to this it is omitted */ +#define ASN1_LONG_UNDEF 0x7fffffffL + +#define STABLE_FLAGS_MALLOC 0x01 +#define STABLE_NO_MASK 0x02 +#define DIRSTRING_TYPE \ + (B_ASN1_PRINTABLESTRING|B_ASN1_T61STRING|B_ASN1_BMPSTRING|B_ASN1_UTF8STRING) +#define PKCS9STRING_TYPE (DIRSTRING_TYPE|B_ASN1_IA5STRING) + +typedef struct asn1_string_table_st { + int nid; + long minsize; + long maxsize; + unsigned long mask; + unsigned long flags; +} ASN1_STRING_TABLE; + +/* size limits: this stuff is taken straight from RFC2459 */ + +#define ub_name 32768 +#define ub_common_name 64 +#define ub_locality_name 128 +#define ub_state_name 128 +#define ub_organization_name 64 +#define ub_organization_unit_name 64 +#define ub_title 64 +#define ub_email_address 128 + +/* Declarations for template structures: for full definitions + * see asn1t.h + */ +typedef struct ASN1_TEMPLATE_st ASN1_TEMPLATE; +typedef struct ASN1_TLC_st ASN1_TLC; +/* This is just an opaque pointer */ +typedef struct ASN1_VALUE_st ASN1_VALUE; + +/* Declare ASN1 functions: the implement macro in in asn1t.h */ + +#define DECLARE_ASN1_FUNCTIONS(type) DECLARE_ASN1_FUNCTIONS_name(type, type) + +#define DECLARE_ASN1_ALLOC_FUNCTIONS(type) \ + DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, type) + +#define DECLARE_ASN1_FUNCTIONS_name(type, name) \ + DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, name) \ + DECLARE_ASN1_ENCODE_FUNCTIONS(type, name, name) + +#define DECLARE_ASN1_FUNCTIONS_fname(type, itname, name) \ + DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, name) \ + DECLARE_ASN1_ENCODE_FUNCTIONS(type, itname, name) + +#define DECLARE_ASN1_ENCODE_FUNCTIONS(type, itname, name) \ + OPENSSL_EXPORT type *d2i_##name(type **a, const unsigned char **in, long len); \ + OPENSSL_EXPORT int i2d_##name(type *a, unsigned char **out); \ + DECLARE_ASN1_ITEM(itname) + +#define DECLARE_ASN1_ENCODE_FUNCTIONS_const(type, name) \ + OPENSSL_EXPORT type *d2i_##name(type **a, const unsigned char **in, long len); \ + OPENSSL_EXPORT int i2d_##name(const type *a, unsigned char **out); \ + DECLARE_ASN1_ITEM(name) + +#define DECLARE_ASN1_NDEF_FUNCTION(name) \ + OPENSSL_EXPORT int i2d_##name##_NDEF(name *a, unsigned char **out); + +#define DECLARE_ASN1_FUNCTIONS_const(name) \ + DECLARE_ASN1_ALLOC_FUNCTIONS(name) \ + DECLARE_ASN1_ENCODE_FUNCTIONS_const(name, name) + +#define DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, name) \ + OPENSSL_EXPORT type *name##_new(void); \ + OPENSSL_EXPORT void name##_free(type *a); + +#define DECLARE_ASN1_PRINT_FUNCTION(stname) \ + DECLARE_ASN1_PRINT_FUNCTION_fname(stname, stname) + +#define DECLARE_ASN1_PRINT_FUNCTION_fname(stname, fname) \ + OPENSSL_EXPORT int fname##_print_ctx(BIO *out, stname *x, int indent, \ + const ASN1_PCTX *pctx); + +#define D2I_OF(type) type *(*)(type **,const unsigned char **,long) +#define I2D_OF(type) int (*)(type *,unsigned char **) +#define I2D_OF_const(type) int (*)(const type *,unsigned char **) + +#define CHECKED_D2I_OF(type, d2i) \ + ((d2i_of_void*) (1 ? d2i : ((D2I_OF(type))0))) +#define CHECKED_I2D_OF(type, i2d) \ + ((i2d_of_void*) (1 ? i2d : ((I2D_OF(type))0))) +#define CHECKED_NEW_OF(type, xnew) \ + ((void *(*)(void)) (1 ? xnew : ((type *(*)(void))0))) +#define CHECKED_PPTR_OF(type, p) \ + ((void**) (1 ? p : (type**)0)) + +#define TYPEDEF_D2I_OF(type) typedef type *d2i_of_##type(type **,const unsigned char **,long) +#define TYPEDEF_I2D_OF(type) typedef int i2d_of_##type(const type *,unsigned char **) +#define TYPEDEF_D2I2D_OF(type) TYPEDEF_D2I_OF(type); TYPEDEF_I2D_OF(type) + +TYPEDEF_D2I2D_OF(void); + +/* The following macros and typedefs allow an ASN1_ITEM + * to be embedded in a structure and referenced. Since + * the ASN1_ITEM pointers need to be globally accessible + * (possibly from shared libraries) they may exist in + * different forms. On platforms that support it the + * ASN1_ITEM structure itself will be globally exported. + * Other platforms will export a function that returns + * an ASN1_ITEM pointer. + * + * To handle both cases transparently the macros below + * should be used instead of hard coding an ASN1_ITEM + * pointer in a structure. + * + * The structure will look like this: + * + * typedef struct SOMETHING_st { + * ... + * ASN1_ITEM_EXP *iptr; + * ... + * } SOMETHING; + * + * It would be initialised as e.g.: + * + * SOMETHING somevar = {...,ASN1_ITEM_ref(X509),...}; + * + * and the actual pointer extracted with: + * + * const ASN1_ITEM *it = ASN1_ITEM_ptr(somevar.iptr); + * + * Finally an ASN1_ITEM pointer can be extracted from an + * appropriate reference with: ASN1_ITEM_rptr(X509). This + * would be used when a function takes an ASN1_ITEM * argument. + * + */ + +/* ASN1_ITEM pointer exported type */ +typedef const ASN1_ITEM ASN1_ITEM_EXP; + +/* Macro to obtain ASN1_ITEM pointer from exported type */ +#define ASN1_ITEM_ptr(iptr) (iptr) + +/* Macro to include ASN1_ITEM pointer from base type */ +#define ASN1_ITEM_ref(iptr) (&(iptr##_it)) + +#define ASN1_ITEM_rptr(ref) (&(ref##_it)) + +#define DECLARE_ASN1_ITEM(name) \ + extern OPENSSL_EXPORT const ASN1_ITEM name##_it; + +/* Parameters used by ASN1_STRING_print_ex() */ + +/* These determine which characters to escape: + * RFC2253 special characters, control characters and + * MSB set characters + */ + +#define ASN1_STRFLGS_ESC_2253 1 +#define ASN1_STRFLGS_ESC_CTRL 2 +#define ASN1_STRFLGS_ESC_MSB 4 + + +/* This flag determines how we do escaping: normally + * RC2253 backslash only, set this to use backslash and + * quote. + */ + +#define ASN1_STRFLGS_ESC_QUOTE 8 + + +/* These three flags are internal use only. */ + +/* Character is a valid PrintableString character */ +#define CHARTYPE_PRINTABLESTRING 0x10 +/* Character needs escaping if it is the first character */ +#define CHARTYPE_FIRST_ESC_2253 0x20 +/* Character needs escaping if it is the last character */ +#define CHARTYPE_LAST_ESC_2253 0x40 + +/* NB the internal flags are safely reused below by flags + * handled at the top level. + */ + +/* If this is set we convert all character strings + * to UTF8 first + */ + +#define ASN1_STRFLGS_UTF8_CONVERT 0x10 + +/* If this is set we don't attempt to interpret content: + * just assume all strings are 1 byte per character. This + * will produce some pretty odd looking output! + */ + +#define ASN1_STRFLGS_IGNORE_TYPE 0x20 + +/* If this is set we include the string type in the output */ +#define ASN1_STRFLGS_SHOW_TYPE 0x40 + +/* This determines which strings to display and which to + * 'dump' (hex dump of content octets or DER encoding). We can + * only dump non character strings or everything. If we + * don't dump 'unknown' they are interpreted as character + * strings with 1 octet per character and are subject to + * the usual escaping options. + */ + +#define ASN1_STRFLGS_DUMP_ALL 0x80 +#define ASN1_STRFLGS_DUMP_UNKNOWN 0x100 + +/* These determine what 'dumping' does, we can dump the + * content octets or the DER encoding: both use the + * RFC2253 #XXXXX notation. + */ + +#define ASN1_STRFLGS_DUMP_DER 0x200 + +/* All the string flags consistent with RFC2253, + * escaping control characters isn't essential in + * RFC2253 but it is advisable anyway. + */ + +#define ASN1_STRFLGS_RFC2253 (ASN1_STRFLGS_ESC_2253 | \ + ASN1_STRFLGS_ESC_CTRL | \ + ASN1_STRFLGS_ESC_MSB | \ + ASN1_STRFLGS_UTF8_CONVERT | \ + ASN1_STRFLGS_DUMP_UNKNOWN | \ + ASN1_STRFLGS_DUMP_DER) + +DECLARE_ASN1_SET_OF(ASN1_INTEGER) + +typedef struct asn1_type_st + { + int type; + union { + char *ptr; + ASN1_BOOLEAN boolean; + ASN1_STRING * asn1_string; + ASN1_OBJECT * object; + ASN1_INTEGER * integer; + ASN1_ENUMERATED * enumerated; + ASN1_BIT_STRING * bit_string; + ASN1_OCTET_STRING * octet_string; + ASN1_PRINTABLESTRING * printablestring; + ASN1_T61STRING * t61string; + ASN1_IA5STRING * ia5string; + ASN1_GENERALSTRING * generalstring; + ASN1_BMPSTRING * bmpstring; + ASN1_UNIVERSALSTRING * universalstring; + ASN1_UTCTIME * utctime; + ASN1_GENERALIZEDTIME * generalizedtime; + ASN1_VISIBLESTRING * visiblestring; + ASN1_UTF8STRING * utf8string; + /* set and sequence are left complete and still + * contain the set or sequence bytes */ + ASN1_STRING * set; + ASN1_STRING * sequence; + ASN1_VALUE * asn1_value; + } value; + } ASN1_TYPE; + +DECLARE_ASN1_SET_OF(ASN1_TYPE) + +typedef STACK_OF(ASN1_TYPE) ASN1_SEQUENCE_ANY; + +DECLARE_ASN1_ENCODE_FUNCTIONS_const(ASN1_SEQUENCE_ANY, ASN1_SEQUENCE_ANY) +DECLARE_ASN1_ENCODE_FUNCTIONS_const(ASN1_SEQUENCE_ANY, ASN1_SET_ANY) + +struct X509_algor_st + { + ASN1_OBJECT *algorithm; + ASN1_TYPE *parameter; + } /* X509_ALGOR */; + +DECLARE_ASN1_FUNCTIONS(X509_ALGOR) + +typedef struct NETSCAPE_X509_st + { + ASN1_OCTET_STRING *header; + X509 *cert; + } NETSCAPE_X509; + +/* This is used to contain a list of bit names */ +typedef struct BIT_STRING_BITNAME_st { + int bitnum; + const char *lname; + const char *sname; +} BIT_STRING_BITNAME; + + +#define M_ASN1_STRING_length(x) ((x)->length) +#define M_ASN1_STRING_length_set(x, n) ((x)->length = (n)) +#define M_ASN1_STRING_type(x) ((x)->type) +#define M_ASN1_STRING_data(x) ((x)->data) + +/* Macros for string operations */ +#define M_ASN1_BIT_STRING_new() (ASN1_BIT_STRING *)\ + ASN1_STRING_type_new(V_ASN1_BIT_STRING) +#define M_ASN1_BIT_STRING_free(a) ASN1_STRING_free((ASN1_STRING *)a) +#define M_ASN1_BIT_STRING_dup(a) (ASN1_BIT_STRING *)\ + ASN1_STRING_dup((const ASN1_STRING *)a) +#define M_ASN1_BIT_STRING_cmp(a,b) ASN1_STRING_cmp(\ + (const ASN1_STRING *)a,(const ASN1_STRING *)b) +#define M_ASN1_BIT_STRING_set(a,b,c) ASN1_STRING_set((ASN1_STRING *)a,b,c) + +#define M_ASN1_INTEGER_new() (ASN1_INTEGER *)\ + ASN1_STRING_type_new(V_ASN1_INTEGER) +#define M_ASN1_INTEGER_free(a) ASN1_STRING_free((ASN1_STRING *)a) +#define M_ASN1_INTEGER_dup(a) (ASN1_INTEGER *)\ + ASN1_STRING_dup((const ASN1_STRING *)a) +#define M_ASN1_INTEGER_cmp(a,b) ASN1_STRING_cmp(\ + (const ASN1_STRING *)a,(const ASN1_STRING *)b) + +#define M_ASN1_ENUMERATED_new() (ASN1_ENUMERATED *)\ + ASN1_STRING_type_new(V_ASN1_ENUMERATED) +#define M_ASN1_ENUMERATED_free(a) ASN1_STRING_free((ASN1_STRING *)a) +#define M_ASN1_ENUMERATED_dup(a) (ASN1_ENUMERATED *)\ + ASN1_STRING_dup((const ASN1_STRING *)a) +#define M_ASN1_ENUMERATED_cmp(a,b) ASN1_STRING_cmp(\ + (const ASN1_STRING *)a,(const ASN1_STRING *)b) + +#define M_ASN1_OCTET_STRING_new() (ASN1_OCTET_STRING *)\ + ASN1_STRING_type_new(V_ASN1_OCTET_STRING) +#define M_ASN1_OCTET_STRING_free(a) ASN1_STRING_free((ASN1_STRING *)a) +#define M_ASN1_OCTET_STRING_dup(a) (ASN1_OCTET_STRING *)\ + ASN1_STRING_dup((const ASN1_STRING *)a) +#define M_ASN1_OCTET_STRING_cmp(a,b) ASN1_STRING_cmp(\ + (const ASN1_STRING *)a,(const ASN1_STRING *)b) +#define M_ASN1_OCTET_STRING_set(a,b,c) ASN1_STRING_set((ASN1_STRING *)a,b,c) +#define M_ASN1_OCTET_STRING_print(a,b) ASN1_STRING_print(a,(ASN1_STRING *)b) +#define M_i2d_ASN1_OCTET_STRING(a,pp) \ + i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_OCTET_STRING,\ + V_ASN1_UNIVERSAL) + +#define B_ASN1_TIME \ + B_ASN1_UTCTIME | \ + B_ASN1_GENERALIZEDTIME + +#define B_ASN1_PRINTABLE \ + B_ASN1_NUMERICSTRING| \ + B_ASN1_PRINTABLESTRING| \ + B_ASN1_T61STRING| \ + B_ASN1_IA5STRING| \ + B_ASN1_BIT_STRING| \ + B_ASN1_UNIVERSALSTRING|\ + B_ASN1_BMPSTRING|\ + B_ASN1_UTF8STRING|\ + B_ASN1_SEQUENCE|\ + B_ASN1_UNKNOWN + +#define B_ASN1_DIRECTORYSTRING \ + B_ASN1_PRINTABLESTRING| \ + B_ASN1_TELETEXSTRING|\ + B_ASN1_BMPSTRING|\ + B_ASN1_UNIVERSALSTRING|\ + B_ASN1_UTF8STRING + +#define B_ASN1_DISPLAYTEXT \ + B_ASN1_IA5STRING| \ + B_ASN1_VISIBLESTRING| \ + B_ASN1_BMPSTRING|\ + B_ASN1_UTF8STRING + +#define M_ASN1_PRINTABLE_new() ASN1_STRING_type_new(V_ASN1_T61STRING) +#define M_ASN1_PRINTABLE_free(a) ASN1_STRING_free((ASN1_STRING *)a) +#define M_i2d_ASN1_PRINTABLE(a,pp) i2d_ASN1_bytes((ASN1_STRING *)a,\ + pp,a->type,V_ASN1_UNIVERSAL) +#define M_d2i_ASN1_PRINTABLE(a,pp,l) \ + d2i_ASN1_type_bytes((ASN1_STRING **)a,pp,l, \ + B_ASN1_PRINTABLE) + +#define M_DIRECTORYSTRING_new() ASN1_STRING_type_new(V_ASN1_PRINTABLESTRING) +#define M_DIRECTORYSTRING_free(a) ASN1_STRING_free((ASN1_STRING *)a) +#define M_i2d_DIRECTORYSTRING(a,pp) i2d_ASN1_bytes((ASN1_STRING *)a,\ + pp,a->type,V_ASN1_UNIVERSAL) +#define M_d2i_DIRECTORYSTRING(a,pp,l) \ + d2i_ASN1_type_bytes((ASN1_STRING **)a,pp,l, \ + B_ASN1_DIRECTORYSTRING) + +#define M_DISPLAYTEXT_new() ASN1_STRING_type_new(V_ASN1_VISIBLESTRING) +#define M_DISPLAYTEXT_free(a) ASN1_STRING_free((ASN1_STRING *)a) +#define M_i2d_DISPLAYTEXT(a,pp) i2d_ASN1_bytes((ASN1_STRING *)a,\ + pp,a->type,V_ASN1_UNIVERSAL) +#define M_d2i_DISPLAYTEXT(a,pp,l) \ + d2i_ASN1_type_bytes((ASN1_STRING **)a,pp,l, \ + B_ASN1_DISPLAYTEXT) + +#define M_ASN1_PRINTABLESTRING_new() (ASN1_PRINTABLESTRING *)\ + ASN1_STRING_type_new(V_ASN1_PRINTABLESTRING) +#define M_ASN1_PRINTABLESTRING_free(a) ASN1_STRING_free((ASN1_STRING *)a) +#define M_i2d_ASN1_PRINTABLESTRING(a,pp) \ + i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_PRINTABLESTRING,\ + V_ASN1_UNIVERSAL) +#define M_d2i_ASN1_PRINTABLESTRING(a,pp,l) \ + (ASN1_PRINTABLESTRING *)d2i_ASN1_type_bytes\ + ((ASN1_STRING **)a,pp,l,B_ASN1_PRINTABLESTRING) + +#define M_ASN1_T61STRING_new() (ASN1_T61STRING *)\ + ASN1_STRING_type_new(V_ASN1_T61STRING) +#define M_ASN1_T61STRING_free(a) ASN1_STRING_free((ASN1_STRING *)a) +#define M_i2d_ASN1_T61STRING(a,pp) \ + i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_T61STRING,\ + V_ASN1_UNIVERSAL) +#define M_d2i_ASN1_T61STRING(a,pp,l) \ + (ASN1_T61STRING *)d2i_ASN1_type_bytes\ + ((ASN1_STRING **)a,pp,l,B_ASN1_T61STRING) + +#define M_ASN1_IA5STRING_new() (ASN1_IA5STRING *)\ + ASN1_STRING_type_new(V_ASN1_IA5STRING) +#define M_ASN1_IA5STRING_free(a) ASN1_STRING_free((ASN1_STRING *)a) +#define M_ASN1_IA5STRING_dup(a) \ + (ASN1_IA5STRING *)ASN1_STRING_dup((const ASN1_STRING *)a) +#define M_i2d_ASN1_IA5STRING(a,pp) \ + i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_IA5STRING,\ + V_ASN1_UNIVERSAL) +#define M_d2i_ASN1_IA5STRING(a,pp,l) \ + (ASN1_IA5STRING *)d2i_ASN1_type_bytes((ASN1_STRING **)a,pp,l,\ + B_ASN1_IA5STRING) + +#define M_ASN1_UTCTIME_new() (ASN1_UTCTIME *)\ + ASN1_STRING_type_new(V_ASN1_UTCTIME) +#define M_ASN1_UTCTIME_free(a) ASN1_STRING_free((ASN1_STRING *)a) +#define M_ASN1_UTCTIME_dup(a) (ASN1_UTCTIME *)\ + ASN1_STRING_dup((const ASN1_STRING *)a) + +#define M_ASN1_GENERALIZEDTIME_new() (ASN1_GENERALIZEDTIME *)\ + ASN1_STRING_type_new(V_ASN1_GENERALIZEDTIME) +#define M_ASN1_GENERALIZEDTIME_free(a) ASN1_STRING_free((ASN1_STRING *)a) +#define M_ASN1_GENERALIZEDTIME_dup(a) (ASN1_GENERALIZEDTIME *)ASN1_STRING_dup(\ + (const ASN1_STRING *)a) + +#define M_ASN1_TIME_new() (ASN1_TIME *)\ + ASN1_STRING_type_new(V_ASN1_UTCTIME) +#define M_ASN1_TIME_free(a) ASN1_STRING_free((ASN1_STRING *)a) +#define M_ASN1_TIME_dup(a) (ASN1_TIME *)\ + ASN1_STRING_dup((const ASN1_STRING *)a) + +#define M_ASN1_GENERALSTRING_new() (ASN1_GENERALSTRING *)\ + ASN1_STRING_type_new(V_ASN1_GENERALSTRING) +#define M_ASN1_GENERALSTRING_free(a) ASN1_STRING_free((ASN1_STRING *)a) +#define M_i2d_ASN1_GENERALSTRING(a,pp) \ + i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_GENERALSTRING,\ + V_ASN1_UNIVERSAL) +#define M_d2i_ASN1_GENERALSTRING(a,pp,l) \ + (ASN1_GENERALSTRING *)d2i_ASN1_type_bytes\ + ((ASN1_STRING **)a,pp,l,B_ASN1_GENERALSTRING) + +#define M_ASN1_UNIVERSALSTRING_new() (ASN1_UNIVERSALSTRING *)\ + ASN1_STRING_type_new(V_ASN1_UNIVERSALSTRING) +#define M_ASN1_UNIVERSALSTRING_free(a) ASN1_STRING_free((ASN1_STRING *)a) +#define M_i2d_ASN1_UNIVERSALSTRING(a,pp) \ + i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_UNIVERSALSTRING,\ + V_ASN1_UNIVERSAL) +#define M_d2i_ASN1_UNIVERSALSTRING(a,pp,l) \ + (ASN1_UNIVERSALSTRING *)d2i_ASN1_type_bytes\ + ((ASN1_STRING **)a,pp,l,B_ASN1_UNIVERSALSTRING) + +#define M_ASN1_BMPSTRING_new() (ASN1_BMPSTRING *)\ + ASN1_STRING_type_new(V_ASN1_BMPSTRING) +#define M_ASN1_BMPSTRING_free(a) ASN1_STRING_free((ASN1_STRING *)a) +#define M_i2d_ASN1_BMPSTRING(a,pp) \ + i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_BMPSTRING,\ + V_ASN1_UNIVERSAL) +#define M_d2i_ASN1_BMPSTRING(a,pp,l) \ + (ASN1_BMPSTRING *)d2i_ASN1_type_bytes\ + ((ASN1_STRING **)a,pp,l,B_ASN1_BMPSTRING) + +#define M_ASN1_VISIBLESTRING_new() (ASN1_VISIBLESTRING *)\ + ASN1_STRING_type_new(V_ASN1_VISIBLESTRING) +#define M_ASN1_VISIBLESTRING_free(a) ASN1_STRING_free((ASN1_STRING *)a) +#define M_i2d_ASN1_VISIBLESTRING(a,pp) \ + i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_VISIBLESTRING,\ + V_ASN1_UNIVERSAL) +#define M_d2i_ASN1_VISIBLESTRING(a,pp,l) \ + (ASN1_VISIBLESTRING *)d2i_ASN1_type_bytes\ + ((ASN1_STRING **)a,pp,l,B_ASN1_VISIBLESTRING) + +#define M_ASN1_UTF8STRING_new() (ASN1_UTF8STRING *)\ + ASN1_STRING_type_new(V_ASN1_UTF8STRING) +#define M_ASN1_UTF8STRING_free(a) ASN1_STRING_free((ASN1_STRING *)a) +#define M_i2d_ASN1_UTF8STRING(a,pp) \ + i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_UTF8STRING,\ + V_ASN1_UNIVERSAL) +#define M_d2i_ASN1_UTF8STRING(a,pp,l) \ + (ASN1_UTF8STRING *)d2i_ASN1_type_bytes\ + ((ASN1_STRING **)a,pp,l,B_ASN1_UTF8STRING) + + /* for the is_set parameter to i2d_ASN1_SET */ +#define IS_SEQUENCE 0 +#define IS_SET 1 + +DECLARE_ASN1_FUNCTIONS_fname(ASN1_TYPE, ASN1_ANY, ASN1_TYPE) + +OPENSSL_EXPORT int ASN1_TYPE_get(ASN1_TYPE *a); +OPENSSL_EXPORT void ASN1_TYPE_set(ASN1_TYPE *a, int type, void *value); +OPENSSL_EXPORT int ASN1_TYPE_set1(ASN1_TYPE *a, int type, const void *value); +OPENSSL_EXPORT int ASN1_TYPE_cmp(const ASN1_TYPE *a, const ASN1_TYPE *b); + +OPENSSL_EXPORT ASN1_OBJECT * ASN1_OBJECT_new(void ); +OPENSSL_EXPORT void ASN1_OBJECT_free(ASN1_OBJECT *a); +OPENSSL_EXPORT int i2d_ASN1_OBJECT(ASN1_OBJECT *a,unsigned char **pp); +OPENSSL_EXPORT ASN1_OBJECT * c2i_ASN1_OBJECT(ASN1_OBJECT **a,const unsigned char **pp, + long length); +OPENSSL_EXPORT ASN1_OBJECT * d2i_ASN1_OBJECT(ASN1_OBJECT **a,const unsigned char **pp, + long length); + +DECLARE_ASN1_ITEM(ASN1_OBJECT) + +DECLARE_ASN1_SET_OF(ASN1_OBJECT) + +OPENSSL_EXPORT ASN1_STRING * ASN1_STRING_new(void); +OPENSSL_EXPORT void ASN1_STRING_free(ASN1_STRING *a); +OPENSSL_EXPORT int ASN1_STRING_copy(ASN1_STRING *dst, const ASN1_STRING *str); +OPENSSL_EXPORT ASN1_STRING * ASN1_STRING_dup(const ASN1_STRING *a); +OPENSSL_EXPORT ASN1_STRING * ASN1_STRING_type_new(int type ); +OPENSSL_EXPORT int ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b); + /* Since this is used to store all sorts of things, via macros, for now, make + its data void * */ +OPENSSL_EXPORT int ASN1_STRING_set(ASN1_STRING *str, const void *data, int len); +OPENSSL_EXPORT void ASN1_STRING_set0(ASN1_STRING *str, void *data, int len); +OPENSSL_EXPORT int ASN1_STRING_length(const ASN1_STRING *x); +OPENSSL_EXPORT void ASN1_STRING_length_set(ASN1_STRING *x, int n); +OPENSSL_EXPORT int ASN1_STRING_type(ASN1_STRING *x); +OPENSSL_EXPORT unsigned char * ASN1_STRING_data(ASN1_STRING *x); + +DECLARE_ASN1_FUNCTIONS(ASN1_BIT_STRING) +OPENSSL_EXPORT int i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a,unsigned char **pp); +OPENSSL_EXPORT ASN1_BIT_STRING *c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a,const unsigned char **pp, long length); +OPENSSL_EXPORT int ASN1_BIT_STRING_set(ASN1_BIT_STRING *a, unsigned char *d, int length ); +OPENSSL_EXPORT int ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int value); +OPENSSL_EXPORT int ASN1_BIT_STRING_get_bit(ASN1_BIT_STRING *a, int n); +OPENSSL_EXPORT int ASN1_BIT_STRING_check(ASN1_BIT_STRING *a, unsigned char *flags, int flags_len); + +OPENSSL_EXPORT int ASN1_BIT_STRING_name_print(BIO *out, ASN1_BIT_STRING *bs, BIT_STRING_BITNAME *tbl, int indent); +OPENSSL_EXPORT int ASN1_BIT_STRING_num_asc(char *name, BIT_STRING_BITNAME *tbl); +OPENSSL_EXPORT int ASN1_BIT_STRING_set_asc(ASN1_BIT_STRING *bs, char *name, int value, BIT_STRING_BITNAME *tbl); + +OPENSSL_EXPORT int i2d_ASN1_BOOLEAN(int a,unsigned char **pp); +OPENSSL_EXPORT int d2i_ASN1_BOOLEAN(int *a,const unsigned char **pp,long length); + +DECLARE_ASN1_FUNCTIONS(ASN1_INTEGER) +OPENSSL_EXPORT int i2c_ASN1_INTEGER(ASN1_INTEGER *a,unsigned char **pp); +OPENSSL_EXPORT ASN1_INTEGER *c2i_ASN1_INTEGER(ASN1_INTEGER **a,const unsigned char **pp, long length); +OPENSSL_EXPORT ASN1_INTEGER *d2i_ASN1_UINTEGER(ASN1_INTEGER **a,const unsigned char **pp, long length); +OPENSSL_EXPORT ASN1_INTEGER * ASN1_INTEGER_dup(const ASN1_INTEGER *x); +OPENSSL_EXPORT int ASN1_INTEGER_cmp(const ASN1_INTEGER *x, const ASN1_INTEGER *y); + +DECLARE_ASN1_FUNCTIONS(ASN1_ENUMERATED) + +OPENSSL_EXPORT int ASN1_UTCTIME_check(const ASN1_UTCTIME *a); +OPENSSL_EXPORT ASN1_UTCTIME *ASN1_UTCTIME_set(ASN1_UTCTIME *s,time_t t); +OPENSSL_EXPORT ASN1_UTCTIME *ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t, int offset_day, long offset_sec); +OPENSSL_EXPORT int ASN1_UTCTIME_set_string(ASN1_UTCTIME *s, const char *str); +OPENSSL_EXPORT int ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t); +#if 0 +time_t ASN1_UTCTIME_get(const ASN1_UTCTIME *s); +#endif + +OPENSSL_EXPORT int ASN1_GENERALIZEDTIME_check(const ASN1_GENERALIZEDTIME *a); +OPENSSL_EXPORT ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_set(ASN1_GENERALIZEDTIME *s,time_t t); +OPENSSL_EXPORT ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_adj(ASN1_GENERALIZEDTIME *s, time_t t, int offset_day, long offset_sec); +OPENSSL_EXPORT int ASN1_GENERALIZEDTIME_set_string(ASN1_GENERALIZEDTIME *s, const char *str); +OPENSSL_EXPORT int ASN1_TIME_diff(int *pday, int *psec, const ASN1_TIME *from, const ASN1_TIME *to); + +DECLARE_ASN1_FUNCTIONS(ASN1_OCTET_STRING) +OPENSSL_EXPORT ASN1_OCTET_STRING * ASN1_OCTET_STRING_dup(const ASN1_OCTET_STRING *a); +OPENSSL_EXPORT int ASN1_OCTET_STRING_cmp(const ASN1_OCTET_STRING *a, const ASN1_OCTET_STRING *b); +OPENSSL_EXPORT int ASN1_OCTET_STRING_set(ASN1_OCTET_STRING *str, const unsigned char *data, int len); + +DECLARE_ASN1_FUNCTIONS(ASN1_VISIBLESTRING) +DECLARE_ASN1_FUNCTIONS(ASN1_UNIVERSALSTRING) +DECLARE_ASN1_FUNCTIONS(ASN1_UTF8STRING) +DECLARE_ASN1_FUNCTIONS(ASN1_NULL) +DECLARE_ASN1_FUNCTIONS(ASN1_BMPSTRING) + +OPENSSL_EXPORT int UTF8_getc(const unsigned char *str, int len, unsigned long *val); +OPENSSL_EXPORT int UTF8_putc(unsigned char *str, int len, unsigned long value); + +DECLARE_ASN1_FUNCTIONS_name(ASN1_STRING, ASN1_PRINTABLE) + +DECLARE_ASN1_FUNCTIONS_name(ASN1_STRING, DIRECTORYSTRING) +DECLARE_ASN1_FUNCTIONS_name(ASN1_STRING, DISPLAYTEXT) +DECLARE_ASN1_FUNCTIONS(ASN1_PRINTABLESTRING) +DECLARE_ASN1_FUNCTIONS(ASN1_T61STRING) +DECLARE_ASN1_FUNCTIONS(ASN1_IA5STRING) +DECLARE_ASN1_FUNCTIONS(ASN1_GENERALSTRING) +DECLARE_ASN1_FUNCTIONS(ASN1_UTCTIME) +DECLARE_ASN1_FUNCTIONS(ASN1_GENERALIZEDTIME) +DECLARE_ASN1_FUNCTIONS(ASN1_TIME) + +DECLARE_ASN1_ITEM(ASN1_OCTET_STRING_NDEF) + +OPENSSL_EXPORT ASN1_TIME *ASN1_TIME_set(ASN1_TIME *s,time_t t); +OPENSSL_EXPORT ASN1_TIME *ASN1_TIME_adj(ASN1_TIME *s,time_t t, int offset_day, long offset_sec); +OPENSSL_EXPORT int ASN1_TIME_check(ASN1_TIME *t); +OPENSSL_EXPORT ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *t, ASN1_GENERALIZEDTIME **out); +OPENSSL_EXPORT int ASN1_TIME_set_string(ASN1_TIME *s, const char *str); + +OPENSSL_EXPORT int i2d_ASN1_SET(STACK_OF(OPENSSL_BLOCK) *a, unsigned char **pp, i2d_of_void *i2d, int ex_tag, int ex_class, int is_set); +OPENSSL_EXPORT STACK_OF(OPENSSL_BLOCK) *d2i_ASN1_SET(STACK_OF(OPENSSL_BLOCK) **a, + const unsigned char **pp, + long length, d2i_of_void *d2i, + void (*free_func)(OPENSSL_BLOCK), int ex_tag, + int ex_class); + +OPENSSL_EXPORT int i2a_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *a); +OPENSSL_EXPORT int a2i_ASN1_INTEGER(BIO *bp,ASN1_INTEGER *bs,char *buf,int size); +OPENSSL_EXPORT int i2a_ASN1_ENUMERATED(BIO *bp, ASN1_ENUMERATED *a); +OPENSSL_EXPORT int a2i_ASN1_ENUMERATED(BIO *bp,ASN1_ENUMERATED *bs,char *buf,int size); +OPENSSL_EXPORT int i2a_ASN1_OBJECT(BIO *bp,ASN1_OBJECT *a); +OPENSSL_EXPORT int a2i_ASN1_STRING(BIO *bp,ASN1_STRING *bs,char *buf,int size); +OPENSSL_EXPORT int i2a_ASN1_STRING(BIO *bp, ASN1_STRING *a, int type); +OPENSSL_EXPORT int i2t_ASN1_OBJECT(char *buf,int buf_len,ASN1_OBJECT *a); + +OPENSSL_EXPORT int a2d_ASN1_OBJECT(unsigned char *out,int olen, const char *buf, int num); +OPENSSL_EXPORT ASN1_OBJECT *ASN1_OBJECT_create(int nid, unsigned char *data,int len, const char *sn, const char *ln); + +OPENSSL_EXPORT int ASN1_INTEGER_set(ASN1_INTEGER *a, long v); +OPENSSL_EXPORT long ASN1_INTEGER_get(const ASN1_INTEGER *a); +OPENSSL_EXPORT ASN1_INTEGER *BN_to_ASN1_INTEGER(const BIGNUM *bn, ASN1_INTEGER *ai); +OPENSSL_EXPORT BIGNUM *ASN1_INTEGER_to_BN(const ASN1_INTEGER *ai,BIGNUM *bn); + +OPENSSL_EXPORT int ASN1_ENUMERATED_set(ASN1_ENUMERATED *a, long v); +OPENSSL_EXPORT long ASN1_ENUMERATED_get(ASN1_ENUMERATED *a); +OPENSSL_EXPORT ASN1_ENUMERATED *BN_to_ASN1_ENUMERATED(BIGNUM *bn, ASN1_ENUMERATED *ai); +OPENSSL_EXPORT BIGNUM *ASN1_ENUMERATED_to_BN(ASN1_ENUMERATED *ai,BIGNUM *bn); + +/* General */ +/* given a string, return the correct type, max is the maximum length */ +OPENSSL_EXPORT int ASN1_PRINTABLE_type(const unsigned char *s, int max); + +OPENSSL_EXPORT int i2d_ASN1_bytes(ASN1_STRING *a, unsigned char **pp, int tag, int xclass); +OPENSSL_EXPORT ASN1_STRING *d2i_ASN1_bytes(ASN1_STRING **a, const unsigned char **pp, long length, int Ptag, int Pclass); +OPENSSL_EXPORT unsigned long ASN1_tag2bit(int tag); +/* type is one or more of the B_ASN1_ values. */ +OPENSSL_EXPORT ASN1_STRING *d2i_ASN1_type_bytes(ASN1_STRING **a,const unsigned char **pp, long length,int type); + +/* PARSING */ +OPENSSL_EXPORT int asn1_Finish(ASN1_CTX *c); +OPENSSL_EXPORT int asn1_const_Finish(ASN1_const_CTX *c); + +/* SPECIALS */ +OPENSSL_EXPORT int ASN1_get_object(const unsigned char **pp, long *plength, int *ptag, int *pclass, long omax); +OPENSSL_EXPORT int ASN1_check_infinite_end(unsigned char **p,long len); +OPENSSL_EXPORT int ASN1_const_check_infinite_end(const unsigned char **p,long len); +OPENSSL_EXPORT void ASN1_put_object(unsigned char **pp, int constructed, int length, int tag, int xclass); +OPENSSL_EXPORT int ASN1_put_eoc(unsigned char **pp); +OPENSSL_EXPORT int ASN1_object_size(int constructed, int length, int tag); + +/* Used to implement other functions */ +OPENSSL_EXPORT void *ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, void *x); + +#define ASN1_dup_of(type,i2d,d2i,x) \ + ((type*)ASN1_dup(CHECKED_I2D_OF(type, i2d), \ + CHECKED_D2I_OF(type, d2i), \ + CHECKED_PTR_OF(type, x))) + +#define ASN1_dup_of_const(type,i2d,d2i,x) \ + ((type*)ASN1_dup(CHECKED_I2D_OF(const type, i2d), \ + CHECKED_D2I_OF(type, d2i), \ + CHECKED_PTR_OF(const type, x))) + +OPENSSL_EXPORT void *ASN1_item_dup(const ASN1_ITEM *it, void *x); + +/* ASN1 alloc/free macros for when a type is only used internally */ + +#define M_ASN1_new_of(type) (type *)ASN1_item_new(ASN1_ITEM_rptr(type)) +#define M_ASN1_free_of(x, type) \ + ASN1_item_free(CHECKED_PTR_OF(type, x), ASN1_ITEM_rptr(type)) + +#ifndef OPENSSL_NO_FP_API +OPENSSL_EXPORT void *ASN1_d2i_fp(void *(*xnew)(void), d2i_of_void *d2i, FILE *in, void **x); + +#define ASN1_d2i_fp_of(type,xnew,d2i,in,x) \ + ((type*)ASN1_d2i_fp(CHECKED_NEW_OF(type, xnew), \ + CHECKED_D2I_OF(type, d2i), \ + in, \ + CHECKED_PPTR_OF(type, x))) + +OPENSSL_EXPORT void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x); +OPENSSL_EXPORT int ASN1_i2d_fp(i2d_of_void *i2d,FILE *out,void *x); + +#define ASN1_i2d_fp_of(type,i2d,out,x) \ + (ASN1_i2d_fp(CHECKED_I2D_OF(type, i2d), \ + out, \ + CHECKED_PTR_OF(type, x))) + +#define ASN1_i2d_fp_of_const(type,i2d,out,x) \ + (ASN1_i2d_fp(CHECKED_I2D_OF(const type, i2d), \ + out, \ + CHECKED_PTR_OF(const type, x))) + +OPENSSL_EXPORT int ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out, void *x); +OPENSSL_EXPORT int ASN1_STRING_print_ex_fp(FILE *fp, ASN1_STRING *str, unsigned long flags); +#endif + +OPENSSL_EXPORT int ASN1_STRING_to_UTF8(unsigned char **out, ASN1_STRING *in); + +OPENSSL_EXPORT void *ASN1_d2i_bio(void *(*xnew)(void), d2i_of_void *d2i, BIO *in, void **x); + +#define ASN1_d2i_bio_of(type,xnew,d2i,in,x) \ + ((type*)ASN1_d2i_bio( CHECKED_NEW_OF(type, xnew), \ + CHECKED_D2I_OF(type, d2i), \ + in, \ + CHECKED_PPTR_OF(type, x))) + +OPENSSL_EXPORT void *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x); +OPENSSL_EXPORT int ASN1_i2d_bio(i2d_of_void *i2d,BIO *out, void *x); + +#define ASN1_i2d_bio_of(type,i2d,out,x) \ + (ASN1_i2d_bio(CHECKED_I2D_OF(type, i2d), \ + out, \ + CHECKED_PTR_OF(type, x))) + +#define ASN1_i2d_bio_of_const(type,i2d,out,x) \ + (ASN1_i2d_bio(CHECKED_I2D_OF(const type, i2d), \ + out, \ + CHECKED_PTR_OF(const type, x))) + +OPENSSL_EXPORT int ASN1_item_i2d_bio(const ASN1_ITEM *it, BIO *out, void *x); +OPENSSL_EXPORT int ASN1_UTCTIME_print(BIO *fp, const ASN1_UTCTIME *a); +OPENSSL_EXPORT int ASN1_GENERALIZEDTIME_print(BIO *fp, const ASN1_GENERALIZEDTIME *a); +OPENSSL_EXPORT int ASN1_TIME_print(BIO *fp, const ASN1_TIME *a); +OPENSSL_EXPORT int ASN1_STRING_print(BIO *bp, const ASN1_STRING *v); +OPENSSL_EXPORT int ASN1_STRING_print_ex(BIO *out, ASN1_STRING *str, unsigned long flags); +OPENSSL_EXPORT const char *ASN1_tag2str(int tag); + +/* Used to load and write netscape format cert */ + +DECLARE_ASN1_FUNCTIONS(NETSCAPE_X509) + +int ASN1_UNIVERSALSTRING_to_string(ASN1_UNIVERSALSTRING *s); + +OPENSSL_EXPORT STACK_OF(OPENSSL_BLOCK) *ASN1_seq_unpack(const unsigned char *buf, int len, d2i_of_void *d2i, void (*free_func)(OPENSSL_BLOCK)); +OPENSSL_EXPORT unsigned char *ASN1_seq_pack(STACK_OF(OPENSSL_BLOCK) *safes, i2d_of_void *i2d, unsigned char **buf, int *len ); +OPENSSL_EXPORT void *ASN1_unpack_string(ASN1_STRING *oct, d2i_of_void *d2i); +OPENSSL_EXPORT void *ASN1_item_unpack(ASN1_STRING *oct, const ASN1_ITEM *it); +OPENSSL_EXPORT ASN1_STRING *ASN1_pack_string(void *obj, i2d_of_void *i2d, ASN1_OCTET_STRING **oct); + +#define ASN1_pack_string_of(type,obj,i2d,oct) \ + (ASN1_pack_string(CHECKED_PTR_OF(type, obj), \ + CHECKED_I2D_OF(type, i2d), \ + oct)) + +OPENSSL_EXPORT ASN1_STRING *ASN1_item_pack(void *obj, const ASN1_ITEM *it, ASN1_OCTET_STRING **oct); + +OPENSSL_EXPORT void ASN1_STRING_set_default_mask(unsigned long mask); +OPENSSL_EXPORT int ASN1_STRING_set_default_mask_asc(const char *p); +OPENSSL_EXPORT unsigned long ASN1_STRING_get_default_mask(void); +OPENSSL_EXPORT int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len, int inform, unsigned long mask); +OPENSSL_EXPORT int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len, int inform, unsigned long mask, long minsize, long maxsize); + +OPENSSL_EXPORT ASN1_STRING *ASN1_STRING_set_by_NID(ASN1_STRING **out, const unsigned char *in, int inlen, int inform, int nid); +OPENSSL_EXPORT ASN1_STRING_TABLE *ASN1_STRING_TABLE_get(int nid); +OPENSSL_EXPORT int ASN1_STRING_TABLE_add(int, long, long, unsigned long, unsigned long); +OPENSSL_EXPORT void ASN1_STRING_TABLE_cleanup(void); + +/* ASN1 template functions */ + +/* Old API compatible functions */ +OPENSSL_EXPORT ASN1_VALUE *ASN1_item_new(const ASN1_ITEM *it); +OPENSSL_EXPORT void ASN1_item_free(ASN1_VALUE *val, const ASN1_ITEM *it); +OPENSSL_EXPORT ASN1_VALUE * ASN1_item_d2i(ASN1_VALUE **val, const unsigned char **in, long len, const ASN1_ITEM *it); +OPENSSL_EXPORT int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it); +OPENSSL_EXPORT int ASN1_item_ndef_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it); + +OPENSSL_EXPORT ASN1_TYPE *ASN1_generate_nconf(char *str, CONF *nconf); +OPENSSL_EXPORT ASN1_TYPE *ASN1_generate_v3(char *str, X509V3_CTX *cnf); + + +#ifdef __cplusplus +} +#endif + +#define ASN1_R_ASN1_LENGTH_MISMATCH 100 +#define ASN1_R_AUX_ERROR 101 +#define ASN1_R_BAD_GET_ASN1_OBJECT_CALL 102 +#define ASN1_R_BAD_OBJECT_HEADER 103 +#define ASN1_R_BMPSTRING_IS_WRONG_LENGTH 104 +#define ASN1_R_BN_LIB 105 +#define ASN1_R_BOOLEAN_IS_WRONG_LENGTH 106 +#define ASN1_R_BUFFER_TOO_SMALL 107 +#define ASN1_R_CONTEXT_NOT_INITIALISED 108 +#define ASN1_R_DECODE_ERROR 109 +#define ASN1_R_DEPTH_EXCEEDED 110 +#define ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED 111 +#define ASN1_R_ENCODE_ERROR 112 +#define ASN1_R_ERROR_GETTING_TIME 113 +#define ASN1_R_EXPECTING_AN_ASN1_SEQUENCE 114 +#define ASN1_R_EXPECTING_AN_INTEGER 115 +#define ASN1_R_EXPECTING_AN_OBJECT 116 +#define ASN1_R_EXPECTING_A_BOOLEAN 117 +#define ASN1_R_EXPECTING_A_TIME 118 +#define ASN1_R_EXPLICIT_LENGTH_MISMATCH 119 +#define ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED 120 +#define ASN1_R_FIELD_MISSING 121 +#define ASN1_R_FIRST_NUM_TOO_LARGE 122 +#define ASN1_R_HEADER_TOO_LONG 123 +#define ASN1_R_ILLEGAL_BITSTRING_FORMAT 124 +#define ASN1_R_ILLEGAL_BOOLEAN 125 +#define ASN1_R_ILLEGAL_CHARACTERS 126 +#define ASN1_R_ILLEGAL_FORMAT 127 +#define ASN1_R_ILLEGAL_HEX 128 +#define ASN1_R_ILLEGAL_IMPLICIT_TAG 129 +#define ASN1_R_ILLEGAL_INTEGER 130 +#define ASN1_R_ILLEGAL_NESTED_TAGGING 131 +#define ASN1_R_ILLEGAL_NULL 132 +#define ASN1_R_ILLEGAL_NULL_VALUE 133 +#define ASN1_R_ILLEGAL_OBJECT 134 +#define ASN1_R_ILLEGAL_OPTIONAL_ANY 135 +#define ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE 136 +#define ASN1_R_ILLEGAL_TAGGED_ANY 137 +#define ASN1_R_ILLEGAL_TIME_VALUE 138 +#define ASN1_R_INTEGER_NOT_ASCII_FORMAT 139 +#define ASN1_R_INTEGER_TOO_LARGE_FOR_LONG 140 +#define ASN1_R_INVALID_BIT_STRING_BITS_LEFT 141 +#define ASN1_R_INVALID_BMPSTRING_LENGTH 142 +#define ASN1_R_INVALID_DIGIT 143 +#define ASN1_R_INVALID_MODIFIER 144 +#define ASN1_R_INVALID_NUMBER 145 +#define ASN1_R_INVALID_OBJECT_ENCODING 146 +#define ASN1_R_INVALID_SEPARATOR 147 +#define ASN1_R_INVALID_TIME_FORMAT 148 +#define ASN1_R_INVALID_UNIVERSALSTRING_LENGTH 149 +#define ASN1_R_INVALID_UTF8STRING 150 +#define ASN1_R_LIST_ERROR 151 +#define ASN1_R_MISSING_ASN1_EOS 152 +#define ASN1_R_MISSING_EOC 153 +#define ASN1_R_MISSING_SECOND_NUMBER 154 +#define ASN1_R_MISSING_VALUE 155 +#define ASN1_R_MSTRING_NOT_UNIVERSAL 156 +#define ASN1_R_MSTRING_WRONG_TAG 157 +#define ASN1_R_NESTED_ASN1_ERROR 158 +#define ASN1_R_NESTED_ASN1_STRING 159 +#define ASN1_R_NON_HEX_CHARACTERS 160 +#define ASN1_R_NOT_ASCII_FORMAT 161 +#define ASN1_R_NOT_ENOUGH_DATA 162 +#define ASN1_R_NO_MATCHING_CHOICE_TYPE 163 +#define ASN1_R_NULL_IS_WRONG_LENGTH 164 +#define ASN1_R_OBJECT_NOT_ASCII_FORMAT 165 +#define ASN1_R_ODD_NUMBER_OF_CHARS 166 +#define ASN1_R_SECOND_NUMBER_TOO_LARGE 167 +#define ASN1_R_SEQUENCE_LENGTH_MISMATCH 168 +#define ASN1_R_SEQUENCE_NOT_CONSTRUCTED 169 +#define ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG 170 +#define ASN1_R_SHORT_LINE 171 +#define ASN1_R_STREAMING_NOT_SUPPORTED 172 +#define ASN1_R_STRING_TOO_LONG 173 +#define ASN1_R_STRING_TOO_SHORT 174 +#define ASN1_R_TAG_VALUE_TOO_HIGH 175 +#define ASN1_R_TIME_NOT_ASCII_FORMAT 176 +#define ASN1_R_TOO_LONG 177 +#define ASN1_R_TYPE_NOT_CONSTRUCTED 178 +#define ASN1_R_TYPE_NOT_PRIMITIVE 179 +#define ASN1_R_UNEXPECTED_EOC 180 +#define ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH 181 +#define ASN1_R_UNKNOWN_FORMAT 182 +#define ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM 183 +#define ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM 184 +#define ASN1_R_UNKNOWN_TAG 185 +#define ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE 186 +#define ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE 187 +#define ASN1_R_UNSUPPORTED_TYPE 188 +#define ASN1_R_WRONG_PUBLIC_KEY_TYPE 189 +#define ASN1_R_WRONG_TAG 190 +#define ASN1_R_WRONG_TYPE 191 + +#endif diff --git a/external/boringssl/include/openssl/asn1_mac.h b/external/boringssl/include/openssl/asn1_mac.h new file mode 100644 index 0000000000..f319beec05 --- /dev/null +++ b/external/boringssl/include/openssl/asn1_mac.h @@ -0,0 +1,75 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_ASN1_MAC_H +#define HEADER_ASN1_MAC_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +OPENSSL_EXPORT int asn1_GetSequence(ASN1_const_CTX *c, long *length); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/external/boringssl/include/openssl/asn1t.h b/external/boringssl/include/openssl/asn1t.h new file mode 100644 index 0000000000..10d32c4364 --- /dev/null +++ b/external/boringssl/include/openssl/asn1t.h @@ -0,0 +1,896 @@ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 2000-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +#ifndef HEADER_ASN1T_H +#define HEADER_ASN1T_H + +#include +#include + +#ifdef OPENSSL_BUILD_SHLIBCRYPTO +# undef OPENSSL_EXTERN +# define OPENSSL_EXTERN OPENSSL_EXPORT +#endif + +/* ASN1 template defines, structures and functions */ + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Macro to obtain ASN1_ADB pointer from a type (only used internally) */ +#define ASN1_ADB_ptr(iptr) ((const ASN1_ADB *)(iptr)) + + +/* Macros for start and end of ASN1_ITEM definition */ + +#define ASN1_ITEM_start(itname) \ + const ASN1_ITEM itname##_it = { + +#define ASN1_ITEM_end(itname) \ + }; + +/* Macros to aid ASN1 template writing */ + +#define ASN1_ITEM_TEMPLATE(tname) \ + static const ASN1_TEMPLATE tname##_item_tt + +#define ASN1_ITEM_TEMPLATE_END(tname) \ + ;\ + ASN1_ITEM_start(tname) \ + ASN1_ITYPE_PRIMITIVE,\ + -1,\ + &tname##_item_tt,\ + 0,\ + NULL,\ + 0,\ + #tname \ + ASN1_ITEM_end(tname) + + +/* This is a ASN1 type which just embeds a template */ + +/* This pair helps declare a SEQUENCE. We can do: + * + * ASN1_SEQUENCE(stname) = { + * ... SEQUENCE components ... + * } ASN1_SEQUENCE_END(stname) + * + * This will produce an ASN1_ITEM called stname_it + * for a structure called stname. + * + * If you want the same structure but a different + * name then use: + * + * ASN1_SEQUENCE(itname) = { + * ... SEQUENCE components ... + * } ASN1_SEQUENCE_END_name(stname, itname) + * + * This will create an item called itname_it using + * a structure called stname. + */ + +#define ASN1_SEQUENCE(tname) \ + static const ASN1_TEMPLATE tname##_seq_tt[] + +#define ASN1_SEQUENCE_END(stname) ASN1_SEQUENCE_END_name(stname, stname) + +#define ASN1_SEQUENCE_END_name(stname, tname) \ + ;\ + ASN1_ITEM_start(tname) \ + ASN1_ITYPE_SEQUENCE,\ + V_ASN1_SEQUENCE,\ + tname##_seq_tt,\ + sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\ + NULL,\ + sizeof(stname),\ + #stname \ + ASN1_ITEM_end(tname) + +#define ASN1_NDEF_SEQUENCE(tname) \ + ASN1_SEQUENCE(tname) + +#define ASN1_NDEF_SEQUENCE_cb(tname, cb) \ + ASN1_SEQUENCE_cb(tname, cb) + +#define ASN1_SEQUENCE_cb(tname, cb) \ + static const ASN1_AUX tname##_aux = {NULL, 0, 0, cb, 0}; \ + ASN1_SEQUENCE(tname) + +#define ASN1_BROKEN_SEQUENCE(tname) \ + static const ASN1_AUX tname##_aux = {NULL, ASN1_AFLG_BROKEN, 0, 0, 0}; \ + ASN1_SEQUENCE(tname) + +#define ASN1_SEQUENCE_ref(tname, cb) \ + static const ASN1_AUX tname##_aux = {NULL, ASN1_AFLG_REFCOUNT, offsetof(tname, references), cb, 0}; \ + ASN1_SEQUENCE(tname) + +#define ASN1_SEQUENCE_enc(tname, enc, cb) \ + static const ASN1_AUX tname##_aux = {NULL, ASN1_AFLG_ENCODING, 0, cb, offsetof(tname, enc)}; \ + ASN1_SEQUENCE(tname) + +#define ASN1_NDEF_SEQUENCE_END(tname) \ + ;\ + ASN1_ITEM_start(tname) \ + ASN1_ITYPE_NDEF_SEQUENCE,\ + V_ASN1_SEQUENCE,\ + tname##_seq_tt,\ + sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\ + NULL,\ + sizeof(tname),\ + #tname \ + ASN1_ITEM_end(tname) + +#define ASN1_BROKEN_SEQUENCE_END(stname) ASN1_SEQUENCE_END_ref(stname, stname) + +#define ASN1_SEQUENCE_END_enc(stname, tname) ASN1_SEQUENCE_END_ref(stname, tname) + +#define ASN1_SEQUENCE_END_cb(stname, tname) ASN1_SEQUENCE_END_ref(stname, tname) + +#define ASN1_SEQUENCE_END_ref(stname, tname) \ + ;\ + ASN1_ITEM_start(tname) \ + ASN1_ITYPE_SEQUENCE,\ + V_ASN1_SEQUENCE,\ + tname##_seq_tt,\ + sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\ + &tname##_aux,\ + sizeof(stname),\ + #stname \ + ASN1_ITEM_end(tname) + +#define ASN1_NDEF_SEQUENCE_END_cb(stname, tname) \ + ;\ + ASN1_ITEM_start(tname) \ + ASN1_ITYPE_NDEF_SEQUENCE,\ + V_ASN1_SEQUENCE,\ + tname##_seq_tt,\ + sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\ + &tname##_aux,\ + sizeof(stname),\ + #stname \ + ASN1_ITEM_end(tname) + + +/* This pair helps declare a CHOICE type. We can do: + * + * ASN1_CHOICE(chname) = { + * ... CHOICE options ... + * ASN1_CHOICE_END(chname) + * + * This will produce an ASN1_ITEM called chname_it + * for a structure called chname. The structure + * definition must look like this: + * typedef struct { + * int type; + * union { + * ASN1_SOMETHING *opt1; + * ASN1_SOMEOTHER *opt2; + * } value; + * } chname; + * + * the name of the selector must be 'type'. + * to use an alternative selector name use the + * ASN1_CHOICE_END_selector() version. + */ + +#define ASN1_CHOICE(tname) \ + static const ASN1_TEMPLATE tname##_ch_tt[] + +#define ASN1_CHOICE_cb(tname, cb) \ + static const ASN1_AUX tname##_aux = {NULL, 0, 0, cb, 0}; \ + ASN1_CHOICE(tname) + +#define ASN1_CHOICE_END(stname) ASN1_CHOICE_END_name(stname, stname) + +#define ASN1_CHOICE_END_name(stname, tname) ASN1_CHOICE_END_selector(stname, tname, type) + +#define ASN1_CHOICE_END_selector(stname, tname, selname) \ + ;\ + ASN1_ITEM_start(tname) \ + ASN1_ITYPE_CHOICE,\ + offsetof(stname,selname) ,\ + tname##_ch_tt,\ + sizeof(tname##_ch_tt) / sizeof(ASN1_TEMPLATE),\ + NULL,\ + sizeof(stname),\ + #stname \ + ASN1_ITEM_end(tname) + +#define ASN1_CHOICE_END_cb(stname, tname, selname) \ + ;\ + ASN1_ITEM_start(tname) \ + ASN1_ITYPE_CHOICE,\ + offsetof(stname,selname) ,\ + tname##_ch_tt,\ + sizeof(tname##_ch_tt) / sizeof(ASN1_TEMPLATE),\ + &tname##_aux,\ + sizeof(stname),\ + #stname \ + ASN1_ITEM_end(tname) + +/* This helps with the template wrapper form of ASN1_ITEM */ + +#define ASN1_EX_TEMPLATE_TYPE(flags, tag, name, type) { \ + (flags), (tag), 0,\ + #name, ASN1_ITEM_ref(type) } + +/* These help with SEQUENCE or CHOICE components */ + +/* used to declare other types */ + +#define ASN1_EX_TYPE(flags, tag, stname, field, type) { \ + (flags), (tag), offsetof(stname, field),\ + #field, ASN1_ITEM_ref(type) } + +/* used when the structure is combined with the parent */ + +#define ASN1_EX_COMBINE(flags, tag, type) { \ + (flags)|ASN1_TFLG_COMBINE, (tag), 0, NULL, ASN1_ITEM_ref(type) } + +/* implicit and explicit helper macros */ + +#define ASN1_IMP_EX(stname, field, type, tag, ex) \ + ASN1_EX_TYPE(ASN1_TFLG_IMPLICIT | ex, tag, stname, field, type) + +#define ASN1_EXP_EX(stname, field, type, tag, ex) \ + ASN1_EX_TYPE(ASN1_TFLG_EXPLICIT | ex, tag, stname, field, type) + +/* Any defined by macros: the field used is in the table itself */ + +#define ASN1_ADB_OBJECT(tblname) { ASN1_TFLG_ADB_OID, -1, 0, #tblname, (const ASN1_ITEM *)&(tblname##_adb) } +#define ASN1_ADB_INTEGER(tblname) { ASN1_TFLG_ADB_INT, -1, 0, #tblname, (const ASN1_ITEM *)&(tblname##_adb) } +/* Plain simple type */ +#define ASN1_SIMPLE(stname, field, type) ASN1_EX_TYPE(0,0, stname, field, type) + +/* OPTIONAL simple type */ +#define ASN1_OPT(stname, field, type) ASN1_EX_TYPE(ASN1_TFLG_OPTIONAL, 0, stname, field, type) + +/* IMPLICIT tagged simple type */ +#define ASN1_IMP(stname, field, type, tag) ASN1_IMP_EX(stname, field, type, tag, 0) + +/* IMPLICIT tagged OPTIONAL simple type */ +#define ASN1_IMP_OPT(stname, field, type, tag) ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_OPTIONAL) + +/* Same as above but EXPLICIT */ + +#define ASN1_EXP(stname, field, type, tag) ASN1_EXP_EX(stname, field, type, tag, 0) +#define ASN1_EXP_OPT(stname, field, type, tag) ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_OPTIONAL) + +/* SEQUENCE OF type */ +#define ASN1_SEQUENCE_OF(stname, field, type) \ + ASN1_EX_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, stname, field, type) + +/* OPTIONAL SEQUENCE OF */ +#define ASN1_SEQUENCE_OF_OPT(stname, field, type) \ + ASN1_EX_TYPE(ASN1_TFLG_SEQUENCE_OF|ASN1_TFLG_OPTIONAL, 0, stname, field, type) + +/* Same as above but for SET OF */ + +#define ASN1_SET_OF(stname, field, type) \ + ASN1_EX_TYPE(ASN1_TFLG_SET_OF, 0, stname, field, type) + +#define ASN1_SET_OF_OPT(stname, field, type) \ + ASN1_EX_TYPE(ASN1_TFLG_SET_OF|ASN1_TFLG_OPTIONAL, 0, stname, field, type) + +/* Finally compound types of SEQUENCE, SET, IMPLICIT, EXPLICIT and OPTIONAL */ + +#define ASN1_IMP_SET_OF(stname, field, type, tag) \ + ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF) + +#define ASN1_EXP_SET_OF(stname, field, type, tag) \ + ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF) + +#define ASN1_IMP_SET_OF_OPT(stname, field, type, tag) \ + ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF|ASN1_TFLG_OPTIONAL) + +#define ASN1_EXP_SET_OF_OPT(stname, field, type, tag) \ + ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF|ASN1_TFLG_OPTIONAL) + +#define ASN1_IMP_SEQUENCE_OF(stname, field, type, tag) \ + ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF) + +#define ASN1_IMP_SEQUENCE_OF_OPT(stname, field, type, tag) \ + ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF|ASN1_TFLG_OPTIONAL) + +#define ASN1_EXP_SEQUENCE_OF(stname, field, type, tag) \ + ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF) + +#define ASN1_EXP_SEQUENCE_OF_OPT(stname, field, type, tag) \ + ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF|ASN1_TFLG_OPTIONAL) + +/* EXPLICIT using indefinite length constructed form */ +#define ASN1_NDEF_EXP(stname, field, type, tag) \ + ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_NDEF) + +/* EXPLICIT OPTIONAL using indefinite length constructed form */ +#define ASN1_NDEF_EXP_OPT(stname, field, type, tag) \ + ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_OPTIONAL|ASN1_TFLG_NDEF) + +/* Macros for the ASN1_ADB structure */ + +#define ASN1_ADB(name) \ + static const ASN1_ADB_TABLE name##_adbtbl[] + +#define ASN1_ADB_END(name, flags, field, app_table, def, none) \ + ;\ + static const ASN1_ADB name##_adb = {\ + flags,\ + offsetof(name, field),\ + app_table,\ + name##_adbtbl,\ + sizeof(name##_adbtbl) / sizeof(ASN1_ADB_TABLE),\ + def,\ + none\ + } + +#define ADB_ENTRY(val, template) {val, template} + +#define ASN1_ADB_TEMPLATE(name) \ + static const ASN1_TEMPLATE name##_tt + +/* This is the ASN1 template structure that defines + * a wrapper round the actual type. It determines the + * actual position of the field in the value structure, + * various flags such as OPTIONAL and the field name. + */ + +struct ASN1_TEMPLATE_st { +unsigned long flags; /* Various flags */ +long tag; /* tag, not used if no tagging */ +unsigned long offset; /* Offset of this field in structure */ +#ifndef NO_ASN1_FIELD_NAMES +const char *field_name; /* Field name */ +#endif +ASN1_ITEM_EXP *item; /* Relevant ASN1_ITEM or ASN1_ADB */ +}; + +/* Macro to extract ASN1_ITEM and ASN1_ADB pointer from ASN1_TEMPLATE */ + +#define ASN1_TEMPLATE_item(t) (t->item_ptr) +#define ASN1_TEMPLATE_adb(t) (t->item_ptr) + +typedef struct ASN1_ADB_TABLE_st ASN1_ADB_TABLE; +typedef struct ASN1_ADB_st ASN1_ADB; + +struct ASN1_ADB_st { + unsigned long flags; /* Various flags */ + unsigned long offset; /* Offset of selector field */ + STACK_OF(ASN1_ADB_TABLE) **app_items; /* Application defined items */ + const ASN1_ADB_TABLE *tbl; /* Table of possible types */ + long tblcount; /* Number of entries in tbl */ + const ASN1_TEMPLATE *default_tt; /* Type to use if no match */ + const ASN1_TEMPLATE *null_tt; /* Type to use if selector is NULL */ +}; + +struct ASN1_ADB_TABLE_st { + long value; /* NID for an object or value for an int */ + const ASN1_TEMPLATE tt; /* item for this value */ +}; + +/* template flags */ + +/* Field is optional */ +#define ASN1_TFLG_OPTIONAL (0x1) + +/* Field is a SET OF */ +#define ASN1_TFLG_SET_OF (0x1 << 1) + +/* Field is a SEQUENCE OF */ +#define ASN1_TFLG_SEQUENCE_OF (0x2 << 1) + +/* Special case: this refers to a SET OF that + * will be sorted into DER order when encoded *and* + * the corresponding STACK will be modified to match + * the new order. + */ +#define ASN1_TFLG_SET_ORDER (0x3 << 1) + +/* Mask for SET OF or SEQUENCE OF */ +#define ASN1_TFLG_SK_MASK (0x3 << 1) + +/* These flags mean the tag should be taken from the + * tag field. If EXPLICIT then the underlying type + * is used for the inner tag. + */ + +/* IMPLICIT tagging */ +#define ASN1_TFLG_IMPTAG (0x1 << 3) + + +/* EXPLICIT tagging, inner tag from underlying type */ +#define ASN1_TFLG_EXPTAG (0x2 << 3) + +#define ASN1_TFLG_TAG_MASK (0x3 << 3) + +/* context specific IMPLICIT */ +#define ASN1_TFLG_IMPLICIT ASN1_TFLG_IMPTAG|ASN1_TFLG_CONTEXT + +/* context specific EXPLICIT */ +#define ASN1_TFLG_EXPLICIT ASN1_TFLG_EXPTAG|ASN1_TFLG_CONTEXT + +/* If tagging is in force these determine the + * type of tag to use. Otherwise the tag is + * determined by the underlying type. These + * values reflect the actual octet format. + */ + +/* Universal tag */ +#define ASN1_TFLG_UNIVERSAL (0x0<<6) +/* Application tag */ +#define ASN1_TFLG_APPLICATION (0x1<<6) +/* Context specific tag */ +#define ASN1_TFLG_CONTEXT (0x2<<6) +/* Private tag */ +#define ASN1_TFLG_PRIVATE (0x3<<6) + +#define ASN1_TFLG_TAG_CLASS (0x3<<6) + +/* These are for ANY DEFINED BY type. In this case + * the 'item' field points to an ASN1_ADB structure + * which contains a table of values to decode the + * relevant type + */ + +#define ASN1_TFLG_ADB_MASK (0x3<<8) + +#define ASN1_TFLG_ADB_OID (0x1<<8) + +#define ASN1_TFLG_ADB_INT (0x1<<9) + +/* This flag means a parent structure is passed + * instead of the field: this is useful is a + * SEQUENCE is being combined with a CHOICE for + * example. Since this means the structure and + * item name will differ we need to use the + * ASN1_CHOICE_END_name() macro for example. + */ + +#define ASN1_TFLG_COMBINE (0x1<<10) + +/* This flag when present in a SEQUENCE OF, SET OF + * or EXPLICIT causes indefinite length constructed + * encoding to be used if required. + */ + +#define ASN1_TFLG_NDEF (0x1<<11) + +/* This is the actual ASN1 item itself */ + +struct ASN1_ITEM_st { +char itype; /* The item type, primitive, SEQUENCE, CHOICE or extern */ +long utype; /* underlying type */ +const ASN1_TEMPLATE *templates; /* If SEQUENCE or CHOICE this contains the contents */ +long tcount; /* Number of templates if SEQUENCE or CHOICE */ +const void *funcs; /* functions that handle this type */ +long size; /* Structure size (usually)*/ +#ifndef NO_ASN1_FIELD_NAMES +const char *sname; /* Structure name */ +#endif +}; + +/* These are values for the itype field and + * determine how the type is interpreted. + * + * For PRIMITIVE types the underlying type + * determines the behaviour if items is NULL. + * + * Otherwise templates must contain a single + * template and the type is treated in the + * same way as the type specified in the template. + * + * For SEQUENCE types the templates field points + * to the members, the size field is the + * structure size. + * + * For CHOICE types the templates field points + * to each possible member (typically a union) + * and the 'size' field is the offset of the + * selector. + * + * The 'funcs' field is used for application + * specific functions. + * + * For COMPAT types the funcs field gives a + * set of functions that handle this type, this + * supports the old d2i, i2d convention. + * + * The EXTERN type uses a new style d2i/i2d. + * The new style should be used where possible + * because it avoids things like the d2i IMPLICIT + * hack. + * + * MSTRING is a multiple string type, it is used + * for a CHOICE of character strings where the + * actual strings all occupy an ASN1_STRING + * structure. In this case the 'utype' field + * has a special meaning, it is used as a mask + * of acceptable types using the B_ASN1 constants. + * + * NDEF_SEQUENCE is the same as SEQUENCE except + * that it will use indefinite length constructed + * encoding if requested. + * + */ + +#define ASN1_ITYPE_PRIMITIVE 0x0 + +#define ASN1_ITYPE_SEQUENCE 0x1 + +#define ASN1_ITYPE_CHOICE 0x2 + +#define ASN1_ITYPE_COMPAT 0x3 + +#define ASN1_ITYPE_EXTERN 0x4 + +#define ASN1_ITYPE_MSTRING 0x5 + +#define ASN1_ITYPE_NDEF_SEQUENCE 0x6 + +/* Cache for ASN1 tag and length, so we + * don't keep re-reading it for things + * like CHOICE + */ + +struct ASN1_TLC_st{ + char valid; /* Values below are valid */ + int ret; /* return value */ + long plen; /* length */ + int ptag; /* class value */ + int pclass; /* class value */ + int hdrlen; /* header length */ +}; + +/* Typedefs for ASN1 function pointers */ + +typedef ASN1_VALUE * ASN1_new_func(void); +typedef void ASN1_free_func(ASN1_VALUE *a); +typedef ASN1_VALUE * ASN1_d2i_func(ASN1_VALUE **a, const unsigned char ** in, long length); +typedef int ASN1_i2d_func(ASN1_VALUE * a, unsigned char **in); + +typedef int ASN1_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, const ASN1_ITEM *it, + int tag, int aclass, char opt, ASN1_TLC *ctx); + +typedef int ASN1_ex_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM *it, int tag, int aclass); +typedef int ASN1_ex_new_func(ASN1_VALUE **pval, const ASN1_ITEM *it); +typedef void ASN1_ex_free_func(ASN1_VALUE **pval, const ASN1_ITEM *it); + +typedef int ASN1_ex_print_func(BIO *out, ASN1_VALUE **pval, + int indent, const char *fname, + const ASN1_PCTX *pctx); + +typedef int ASN1_primitive_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, const ASN1_ITEM *it); +typedef int ASN1_primitive_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, int utype, char *free_cont, const ASN1_ITEM *it); +typedef int ASN1_primitive_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it, int indent, const ASN1_PCTX *pctx); + +typedef struct ASN1_COMPAT_FUNCS_st { + ASN1_new_func *asn1_new; + ASN1_free_func *asn1_free; + ASN1_d2i_func *asn1_d2i; + ASN1_i2d_func *asn1_i2d; +} ASN1_COMPAT_FUNCS; + +typedef struct ASN1_EXTERN_FUNCS_st { + void *app_data; + ASN1_ex_new_func *asn1_ex_new; + ASN1_ex_free_func *asn1_ex_free; + ASN1_ex_free_func *asn1_ex_clear; + ASN1_ex_d2i *asn1_ex_d2i; + ASN1_ex_i2d *asn1_ex_i2d; + /* asn1_ex_print is unused. */ + ASN1_ex_print_func *asn1_ex_print; +} ASN1_EXTERN_FUNCS; + +typedef struct ASN1_PRIMITIVE_FUNCS_st { + void *app_data; + unsigned long flags; + ASN1_ex_new_func *prim_new; + ASN1_ex_free_func *prim_free; + ASN1_ex_free_func *prim_clear; + ASN1_primitive_c2i *prim_c2i; + ASN1_primitive_i2c *prim_i2c; + ASN1_primitive_print *prim_print; +} ASN1_PRIMITIVE_FUNCS; + +/* This is the ASN1_AUX structure: it handles various + * miscellaneous requirements. For example the use of + * reference counts and an informational callback. + * + * The "informational callback" is called at various + * points during the ASN1 encoding and decoding. It can + * be used to provide minor customisation of the structures + * used. This is most useful where the supplied routines + * *almost* do the right thing but need some extra help + * at a few points. If the callback returns zero then + * it is assumed a fatal error has occurred and the + * main operation should be abandoned. + * + * If major changes in the default behaviour are required + * then an external type is more appropriate. + */ + +typedef int ASN1_aux_cb(int operation, ASN1_VALUE **in, const ASN1_ITEM *it, + void *exarg); + +typedef struct ASN1_AUX_st { + void *app_data; + int flags; + int ref_offset; /* Offset of reference value */ + ASN1_aux_cb *asn1_cb; + int enc_offset; /* Offset of ASN1_ENCODING structure */ +} ASN1_AUX; + +/* For print related callbacks exarg points to this structure */ +typedef struct ASN1_PRINT_ARG_st { + BIO *out; + int indent; + const ASN1_PCTX *pctx; +} ASN1_PRINT_ARG; + +/* For streaming related callbacks exarg points to this structure */ +typedef struct ASN1_STREAM_ARG_st { + /* BIO to stream through */ + BIO *out; + /* BIO with filters appended */ + BIO *ndef_bio; + /* Streaming I/O boundary */ + unsigned char **boundary; +} ASN1_STREAM_ARG; + +/* Flags in ASN1_AUX */ + +/* Use a reference count */ +#define ASN1_AFLG_REFCOUNT 1 +/* Save the encoding of structure (useful for signatures) */ +#define ASN1_AFLG_ENCODING 2 +/* The Sequence length is invalid */ +#define ASN1_AFLG_BROKEN 4 + +/* operation values for asn1_cb */ + +#define ASN1_OP_NEW_PRE 0 +#define ASN1_OP_NEW_POST 1 +#define ASN1_OP_FREE_PRE 2 +#define ASN1_OP_FREE_POST 3 +#define ASN1_OP_D2I_PRE 4 +#define ASN1_OP_D2I_POST 5 +#define ASN1_OP_I2D_PRE 6 +#define ASN1_OP_I2D_POST 7 +#define ASN1_OP_PRINT_PRE 8 +#define ASN1_OP_PRINT_POST 9 +#define ASN1_OP_STREAM_PRE 10 +#define ASN1_OP_STREAM_POST 11 +#define ASN1_OP_DETACHED_PRE 12 +#define ASN1_OP_DETACHED_POST 13 + +/* Macro to implement a primitive type */ +#define IMPLEMENT_ASN1_TYPE(stname) IMPLEMENT_ASN1_TYPE_ex(stname, stname, 0) +#define IMPLEMENT_ASN1_TYPE_ex(itname, vname, ex) \ + ASN1_ITEM_start(itname) \ + ASN1_ITYPE_PRIMITIVE, V_##vname, NULL, 0, NULL, ex, #itname \ + ASN1_ITEM_end(itname) + +/* Macro to implement a multi string type */ +#define IMPLEMENT_ASN1_MSTRING(itname, mask) \ + ASN1_ITEM_start(itname) \ + ASN1_ITYPE_MSTRING, mask, NULL, 0, NULL, sizeof(ASN1_STRING), #itname \ + ASN1_ITEM_end(itname) + +/* Macro to implement an ASN1_ITEM in terms of old style funcs */ + +#define IMPLEMENT_COMPAT_ASN1(sname) IMPLEMENT_COMPAT_ASN1_type(sname, V_ASN1_SEQUENCE) + +#define IMPLEMENT_COMPAT_ASN1_type(sname, tag) \ + static const ASN1_COMPAT_FUNCS sname##_ff = { \ + (ASN1_new_func *)sname##_new, \ + (ASN1_free_func *)sname##_free, \ + (ASN1_d2i_func *)d2i_##sname, \ + (ASN1_i2d_func *)i2d_##sname, \ + }; \ + ASN1_ITEM_start(sname) \ + ASN1_ITYPE_COMPAT, \ + tag, \ + NULL, \ + 0, \ + &sname##_ff, \ + 0, \ + #sname \ + ASN1_ITEM_end(sname) + +#define IMPLEMENT_EXTERN_ASN1(sname, tag, fptrs) \ + ASN1_ITEM_start(sname) \ + ASN1_ITYPE_EXTERN, \ + tag, \ + NULL, \ + 0, \ + &fptrs, \ + 0, \ + #sname \ + ASN1_ITEM_end(sname) + +/* Macro to implement standard functions in terms of ASN1_ITEM structures */ + +#define IMPLEMENT_ASN1_FUNCTIONS(stname) IMPLEMENT_ASN1_FUNCTIONS_fname(stname, stname, stname) + +#define IMPLEMENT_ASN1_FUNCTIONS_name(stname, itname) IMPLEMENT_ASN1_FUNCTIONS_fname(stname, itname, itname) + +#define IMPLEMENT_ASN1_FUNCTIONS_ENCODE_name(stname, itname) \ + IMPLEMENT_ASN1_FUNCTIONS_ENCODE_fname(stname, itname, itname) + +#define IMPLEMENT_STATIC_ASN1_ALLOC_FUNCTIONS(stname) \ + IMPLEMENT_ASN1_ALLOC_FUNCTIONS_pfname(static, stname, stname, stname) + +#define IMPLEMENT_ASN1_ALLOC_FUNCTIONS(stname) \ + IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, stname, stname) + +#define IMPLEMENT_ASN1_ALLOC_FUNCTIONS_pfname(pre, stname, itname, fname) \ + pre stname *fname##_new(void) \ + { \ + return (stname *)ASN1_item_new(ASN1_ITEM_rptr(itname)); \ + } \ + pre void fname##_free(stname *a) \ + { \ + ASN1_item_free((ASN1_VALUE *)a, ASN1_ITEM_rptr(itname)); \ + } + +#define IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, itname, fname) \ + stname *fname##_new(void) \ + { \ + return (stname *)ASN1_item_new(ASN1_ITEM_rptr(itname)); \ + } \ + void fname##_free(stname *a) \ + { \ + ASN1_item_free((ASN1_VALUE *)a, ASN1_ITEM_rptr(itname)); \ + } + +#define IMPLEMENT_ASN1_FUNCTIONS_fname(stname, itname, fname) \ + IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(stname, itname, fname) \ + IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, itname, fname) + +#define IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(stname, itname, fname) \ + stname *d2i_##fname(stname **a, const unsigned char **in, long len) \ + { \ + return (stname *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, ASN1_ITEM_rptr(itname));\ + } \ + int i2d_##fname(stname *a, unsigned char **out) \ + { \ + return ASN1_item_i2d((ASN1_VALUE *)a, out, ASN1_ITEM_rptr(itname));\ + } + +#define IMPLEMENT_ASN1_NDEF_FUNCTION(stname) \ + int i2d_##stname##_NDEF(stname *a, unsigned char **out) \ + { \ + return ASN1_item_ndef_i2d((ASN1_VALUE *)a, out, ASN1_ITEM_rptr(stname));\ + } + +/* This includes evil casts to remove const: they will go away when full + * ASN1 constification is done. + */ +#define IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(stname, itname, fname) \ + stname *d2i_##fname(stname **a, const unsigned char **in, long len) \ + { \ + return (stname *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, ASN1_ITEM_rptr(itname));\ + } \ + int i2d_##fname(const stname *a, unsigned char **out) \ + { \ + return ASN1_item_i2d((ASN1_VALUE *)a, out, ASN1_ITEM_rptr(itname));\ + } + +#define IMPLEMENT_ASN1_DUP_FUNCTION(stname) \ + stname * stname##_dup(stname *x) \ + { \ + return ASN1_item_dup(ASN1_ITEM_rptr(stname), x); \ + } + +#define IMPLEMENT_ASN1_FUNCTIONS_const(name) \ + IMPLEMENT_ASN1_FUNCTIONS_const_fname(name, name, name) + +#define IMPLEMENT_ASN1_FUNCTIONS_const_fname(stname, itname, fname) \ + IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(stname, itname, fname) \ + IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, itname, fname) + +/* external definitions for primitive types */ + +DECLARE_ASN1_ITEM(ASN1_BOOLEAN) +DECLARE_ASN1_ITEM(ASN1_TBOOLEAN) +DECLARE_ASN1_ITEM(ASN1_FBOOLEAN) +DECLARE_ASN1_ITEM(ASN1_SEQUENCE) +DECLARE_ASN1_ITEM(CBIGNUM) +DECLARE_ASN1_ITEM(BIGNUM) +DECLARE_ASN1_ITEM(LONG) +DECLARE_ASN1_ITEM(ZLONG) + +DECLARE_STACK_OF(ASN1_VALUE) + +/* Functions used internally by the ASN1 code */ + +int ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it); +void ASN1_item_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it); +int ASN1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt); +int ASN1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it); + +void ASN1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt); +int ASN1_template_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, const ASN1_TEMPLATE *tt); +int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, const ASN1_ITEM *it, + int tag, int aclass, char opt, ASN1_TLC *ctx); + +int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM *it, int tag, int aclass); +int ASN1_template_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_TEMPLATE *tt); +void ASN1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it); + +int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, const ASN1_ITEM *it); +int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, int utype, char *free_cont, const ASN1_ITEM *it); + +int asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it); +int asn1_set_choice_selector(ASN1_VALUE **pval, int value, const ASN1_ITEM *it); + +ASN1_VALUE ** asn1_get_field_ptr(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt); + +const ASN1_TEMPLATE *asn1_do_adb(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt, int nullerr); + +void asn1_refcount_set_one(ASN1_VALUE **pval, const ASN1_ITEM *it); +int asn1_refcount_dec_and_test_zero(ASN1_VALUE **pval, const ASN1_ITEM *it); + +void asn1_enc_init(ASN1_VALUE **pval, const ASN1_ITEM *it); +void asn1_enc_free(ASN1_VALUE **pval, const ASN1_ITEM *it); +int asn1_enc_restore(int *len, unsigned char **out, ASN1_VALUE **pval, const ASN1_ITEM *it); +int asn1_enc_save(ASN1_VALUE **pval, const unsigned char *in, int inlen, const ASN1_ITEM *it); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/external/boringssl/include/openssl/base.h b/external/boringssl/include/openssl/base.h new file mode 100644 index 0000000000..96eb6936eb --- /dev/null +++ b/external/boringssl/include/openssl/base.h @@ -0,0 +1,298 @@ +/* ==================================================================== + * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#ifndef OPENSSL_HEADER_BASE_H +#define OPENSSL_HEADER_BASE_H + + +/* This file should be the first included by all BoringSSL headers. */ + +#include +#include +#include + +#include + +#if defined(BORINGSSL_PREFIX) +#include +#endif + +#if defined(__cplusplus) +extern "C" { +#endif + + +#if defined(__x86_64) || defined(_M_AMD64) || defined(_M_X64) +#define OPENSSL_64_BIT +#define OPENSSL_X86_64 +#elif defined(__x86) || defined(__i386) || defined(__i386__) || defined(_M_IX86) +#define OPENSSL_32_BIT +#define OPENSSL_X86 +#elif defined(__aarch64__) +#define OPENSSL_64_BIT +#define OPENSSL_AARCH64 +#elif defined(__arm) || defined(__arm__) || defined(_M_ARM) +#define OPENSSL_32_BIT +#define OPENSSL_ARM +#elif defined(__PPC64__) || defined(__powerpc64__) +#define OPENSSL_64_BIT +#elif defined(__mips__) && !defined(__LP64__) +#define OPENSSL_32_BIT +#define OPENSSL_MIPS +#elif defined(__mips__) && defined(__LP64__) +#define OPENSSL_64_BIT +#define OPENSSL_MIPS64 +#elif defined(__pnacl__) +#define OPENSSL_32_BIT +#define OPENSSL_PNACL +#elif defined(__s390x__) +#define OPENSSL_64_BIT +#define OPENSSL_S390X +#else +#error "Unknown target CPU" +#endif + +#if defined(__APPLE__) +#define OPENSSL_APPLE +#endif + +#if defined(_WIN32) +#define OPENSSL_WINDOWS +#endif + +#if defined(TRUSTY) +#define OPENSSL_TRUSTY +#define OPENSSL_NO_THREADS +#endif + +#define OPENSSL_IS_BORINGSSL +#define BORINGSSL_201512 +#define BORINGSSL_201603 +#define OPENSSL_VERSION_NUMBER 0x10002000 +#define SSLEAY_VERSION_NUMBER OPENSSL_VERSION_NUMBER + +/* BORINGSSL_API_VERSION is a positive integer that increments as BoringSSL + * changes over time. The value itself is not meaningful. It will be incremented + * whenever is convenient to coordinate an API change with consumers. This will + * not denote any special point in development. + * + * A consumer may use this symbol in the preprocessor to temporarily build + * against multiple revisions of BoringSSL at the same time. It is not + * recommended to do so for longer than is necessary. */ +#define BORINGSSL_API_VERSION 1 + +#if defined(BORINGSSL_SHARED_LIBRARY) + +#if defined(OPENSSL_WINDOWS) + +#if defined(BORINGSSL_IMPLEMENTATION) +#define OPENSSL_EXPORT __declspec(dllexport) +#else +#define OPENSSL_EXPORT __declspec(dllimport) +#endif + +#else /* defined(OPENSSL_WINDOWS) */ + +#if defined(BORINGSSL_IMPLEMENTATION) +#define OPENSSL_EXPORT __attribute__((visibility("default"))) +#else +#define OPENSSL_EXPORT +#endif + +#endif /* defined(OPENSSL_WINDOWS) */ + +#else /* defined(BORINGSSL_SHARED_LIBRARY) */ + +#define OPENSSL_EXPORT + +#endif /* defined(BORINGSSL_SHARED_LIBRARY) */ + + +#if defined(__GNUC__) +#define OPENSSL_PRINTF_FORMAT_FUNC(string_index, first_to_check) \ + __attribute__((__format__(__printf__, string_index, first_to_check))) +#else +#define OPENSSL_PRINTF_FORMAT_FUNC(string_index, first_to_check) +#endif + +/* OPENSSL_MSVC_PRAGMA emits a pragma on MSVC and nothing on other compilers. */ +#if defined(_MSC_VER) +#define OPENSSL_MSVC_PRAGMA(arg) __pragma(arg) +#else +#define OPENSSL_MSVC_PRAGMA(arg) +#endif + + +/* CRYPTO_THREADID is a dummy value. */ +typedef int CRYPTO_THREADID; + +typedef int ASN1_BOOLEAN; +typedef int ASN1_NULL; +typedef struct ASN1_ITEM_st ASN1_ITEM; +typedef struct asn1_object_st ASN1_OBJECT; +typedef struct asn1_pctx_st ASN1_PCTX; +typedef struct asn1_string_st ASN1_BIT_STRING; +typedef struct asn1_string_st ASN1_BMPSTRING; +typedef struct asn1_string_st ASN1_ENUMERATED; +typedef struct asn1_string_st ASN1_GENERALIZEDTIME; +typedef struct asn1_string_st ASN1_GENERALSTRING; +typedef struct asn1_string_st ASN1_IA5STRING; +typedef struct asn1_string_st ASN1_INTEGER; +typedef struct asn1_string_st ASN1_OCTET_STRING; +typedef struct asn1_string_st ASN1_PRINTABLESTRING; +typedef struct asn1_string_st ASN1_STRING; +typedef struct asn1_string_st ASN1_T61STRING; +typedef struct asn1_string_st ASN1_TIME; +typedef struct asn1_string_st ASN1_UNIVERSALSTRING; +typedef struct asn1_string_st ASN1_UTCTIME; +typedef struct asn1_string_st ASN1_UTF8STRING; +typedef struct asn1_string_st ASN1_VISIBLESTRING; + +typedef struct AUTHORITY_KEYID_st AUTHORITY_KEYID; +typedef struct DIST_POINT_st DIST_POINT; +typedef struct ISSUING_DIST_POINT_st ISSUING_DIST_POINT; +typedef struct NAME_CONSTRAINTS_st NAME_CONSTRAINTS; +typedef struct Netscape_certificate_sequence NETSCAPE_CERT_SEQUENCE; +typedef struct Netscape_spkac_st NETSCAPE_SPKAC; +typedef struct Netscape_spki_st NETSCAPE_SPKI; +typedef struct PBE2PARAM_st PBE2PARAM; +typedef struct PBEPARAM_st PBEPARAM; +typedef struct PBKDF2PARAM_st PBKDF2PARAM; +typedef struct RIPEMD160state_st RIPEMD160_CTX; +typedef struct X509_POLICY_CACHE_st X509_POLICY_CACHE; +typedef struct X509_POLICY_LEVEL_st X509_POLICY_LEVEL; +typedef struct X509_POLICY_NODE_st X509_POLICY_NODE; +typedef struct X509_POLICY_TREE_st X509_POLICY_TREE; +typedef struct X509_algor_st X509_ALGOR; +typedef struct X509_crl_info_st X509_CRL_INFO; +typedef struct X509_crl_st X509_CRL; +typedef struct X509_extension_st X509_EXTENSION; +typedef struct X509_info_st X509_INFO; +typedef struct X509_name_entry_st X509_NAME_ENTRY; +typedef struct X509_name_st X509_NAME; +typedef struct X509_objects_st X509_OBJECTS; +typedef struct X509_pubkey_st X509_PUBKEY; +typedef struct X509_req_info_st X509_REQ_INFO; +typedef struct X509_req_st X509_REQ; +typedef struct X509_sig_st X509_SIG; +typedef struct X509_val_st X509_VAL; +typedef struct bignum_ctx BN_CTX; +typedef struct bignum_st BIGNUM; +typedef struct bio_method_st BIO_METHOD; +typedef struct bio_st BIO; +typedef struct bn_gencb_st BN_GENCB; +typedef struct bn_mont_ctx_st BN_MONT_CTX; +typedef struct buf_mem_st BUF_MEM; +typedef struct cbb_st CBB; +typedef struct cbs_st CBS; +typedef struct cmac_ctx_st CMAC_CTX; +typedef struct conf_st CONF; +typedef struct conf_value_st CONF_VALUE; +typedef struct dh_st DH; +typedef struct dsa_st DSA; +typedef struct ec_key_st EC_KEY; +typedef struct ecdsa_method_st ECDSA_METHOD; +typedef struct ecdsa_sig_st ECDSA_SIG; +typedef struct engine_st ENGINE; +typedef struct env_md_ctx_st EVP_MD_CTX; +typedef struct env_md_st EVP_MD; +typedef struct evp_aead_st EVP_AEAD; +typedef struct evp_cipher_ctx_st EVP_CIPHER_CTX; +typedef struct evp_cipher_st EVP_CIPHER; +typedef struct evp_encode_ctx_st EVP_ENCODE_CTX; +typedef struct evp_pkey_asn1_method_st EVP_PKEY_ASN1_METHOD; +typedef struct evp_pkey_ctx_st EVP_PKEY_CTX; +typedef struct evp_pkey_method_st EVP_PKEY_METHOD; +typedef struct evp_pkey_st EVP_PKEY; +typedef struct hmac_ctx_st HMAC_CTX; +typedef struct md4_state_st MD4_CTX; +typedef struct md5_state_st MD5_CTX; +typedef struct newhope_poly_st NEWHOPE_POLY; +typedef struct pkcs12_st PKCS12; +typedef struct pkcs8_priv_key_info_st PKCS8_PRIV_KEY_INFO; +typedef struct private_key_st X509_PKEY; +typedef struct rand_meth_st RAND_METHOD; +typedef struct rc4_key_st RC4_KEY; +typedef struct rsa_meth_st RSA_METHOD; +typedef struct rsa_st RSA; +typedef struct sha256_state_st SHA256_CTX; +typedef struct sha512_state_st SHA512_CTX; +typedef struct sha_state_st SHA_CTX; +typedef struct spake2_ctx_st SPAKE2_CTX; +typedef struct srtp_protection_profile_st SRTP_PROTECTION_PROFILE; +typedef struct ssl_cipher_st SSL_CIPHER; +typedef struct ssl_ctx_st SSL_CTX; +typedef struct ssl_custom_extension SSL_CUSTOM_EXTENSION; +typedef struct ssl_method_st SSL_METHOD; +typedef struct ssl_session_st SSL_SESSION; +typedef struct ssl_st SSL; +typedef struct st_ERR_FNS ERR_FNS; +typedef struct v3_ext_ctx X509V3_CTX; +typedef struct x509_attributes_st X509_ATTRIBUTE; +typedef struct x509_cert_aux_st X509_CERT_AUX; +typedef struct x509_cert_pair_st X509_CERT_PAIR; +typedef struct x509_cinf_st X509_CINF; +typedef struct x509_crl_method_st X509_CRL_METHOD; +typedef struct x509_revoked_st X509_REVOKED; +typedef struct x509_st X509; +typedef struct x509_store_ctx_st X509_STORE_CTX; +typedef struct x509_store_st X509_STORE; +typedef struct x509_trust_st X509_TRUST; + +typedef void *OPENSSL_BLOCK; + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_BASE_H */ diff --git a/external/boringssl/include/openssl/base64.h b/external/boringssl/include/openssl/base64.h new file mode 100644 index 0000000000..4bf3888c01 --- /dev/null +++ b/external/boringssl/include/openssl/base64.h @@ -0,0 +1,187 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_BASE64_H +#define OPENSSL_HEADER_BASE64_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* base64 functions. + * + * For historical reasons, these functions have the EVP_ prefix but just do + * base64 encoding and decoding. */ + + +/* Encoding */ + +/* EVP_EncodeBlock encodes |src_len| bytes from |src| and writes the + * result to |dst| with a trailing NUL. It returns the number of bytes + * written, not including this trailing NUL. */ +OPENSSL_EXPORT size_t EVP_EncodeBlock(uint8_t *dst, const uint8_t *src, + size_t src_len); + +/* EVP_EncodedLength sets |*out_len| to the number of bytes that will be needed + * to call |EVP_EncodeBlock| on an input of length |len|. This includes the + * final NUL that |EVP_EncodeBlock| writes. It returns one on success or zero + * on error. */ +OPENSSL_EXPORT int EVP_EncodedLength(size_t *out_len, size_t len); + + +/* Decoding */ + +/* EVP_DecodedLength sets |*out_len| to the maximum number of bytes that will + * be needed to call |EVP_DecodeBase64| on an input of length |len|. It returns + * one on success or zero if |len| is not a valid length for a base64-encoded + * string. */ +OPENSSL_EXPORT int EVP_DecodedLength(size_t *out_len, size_t len); + +/* EVP_DecodeBase64 decodes |in_len| bytes from base64 and writes + * |*out_len| bytes to |out|. |max_out| is the size of the output + * buffer. If it is not enough for the maximum output size, the + * operation fails. It returns one on success or zero on error. */ +OPENSSL_EXPORT int EVP_DecodeBase64(uint8_t *out, size_t *out_len, + size_t max_out, const uint8_t *in, + size_t in_len); + + +/* Deprecated functions. + * + * OpenSSL provides a streaming base64 implementation, however its behavior is + * very specific to PEM. It is also very lenient of invalid input. Use of any of + * these functions is thus deprecated. */ + +/* EVP_EncodeInit initialises |*ctx|, which is typically stack + * allocated, for an encoding operation. + * + * NOTE: The encoding operation breaks its output with newlines every + * 64 characters of output (48 characters of input). Use + * EVP_EncodeBlock to encode raw base64. */ +OPENSSL_EXPORT void EVP_EncodeInit(EVP_ENCODE_CTX *ctx); + +/* EVP_EncodeUpdate encodes |in_len| bytes from |in| and writes an encoded + * version of them to |out| and sets |*out_len| to the number of bytes written. + * Some state may be contained in |ctx| so |EVP_EncodeFinal| must be used to + * flush it before using the encoded data. */ +OPENSSL_EXPORT void EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, uint8_t *out, + int *out_len, const uint8_t *in, + size_t in_len); + +/* EVP_EncodeFinal flushes any remaining output bytes from |ctx| to |out| and + * sets |*out_len| to the number of bytes written. */ +OPENSSL_EXPORT void EVP_EncodeFinal(EVP_ENCODE_CTX *ctx, uint8_t *out, + int *out_len); + +/* EVP_DecodeInit initialises |*ctx|, which is typically stack allocated, for + * a decoding operation. + * + * TODO(davidben): This isn't a straight-up base64 decode either. Document + * and/or fix exactly what's going on here; maximum line length and such. */ +OPENSSL_EXPORT void EVP_DecodeInit(EVP_ENCODE_CTX *ctx); + +/* EVP_DecodeUpdate decodes |in_len| bytes from |in| and writes the decoded + * data to |out| and sets |*out_len| to the number of bytes written. Some state + * may be contained in |ctx| so |EVP_DecodeFinal| must be used to flush it + * before using the encoded data. + * + * It returns -1 on error, one if a full line of input was processed and zero + * if the line was short (i.e. it was the last line). */ +OPENSSL_EXPORT int EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, uint8_t *out, + int *out_len, const uint8_t *in, + size_t in_len); + +/* EVP_DecodeFinal flushes any remaining output bytes from |ctx| to |out| and + * sets |*out_len| to the number of bytes written. It returns one on success + * and minus one on error. */ +OPENSSL_EXPORT int EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, uint8_t *out, + int *out_len); + +/* EVP_DecodeBlock encodes |src_len| bytes from |src| and writes the result to + * |dst|. It returns the number of bytes written or -1 on error. + * + * WARNING: EVP_DecodeBlock's return value does not take padding into + * account. It also strips leading whitespace and trailing + * whitespace and minuses. */ +OPENSSL_EXPORT int EVP_DecodeBlock(uint8_t *dst, const uint8_t *src, + size_t src_len); + + +struct evp_encode_ctx_st { + /* data_used indicates the number of bytes of |data| that are valid. When + * encoding, |data| will be filled and encoded as a lump. When decoding, only + * the first four bytes of |data| will be used. */ + unsigned data_used; + uint8_t data[48]; + + /* eof_seen indicates that the end of the base64 data has been seen when + * decoding. Only whitespace can follow. */ + char eof_seen; + + /* error_encountered indicates that invalid base64 data was found. This will + * cause all future calls to fail. */ + char error_encountered; +}; + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_BASE64_H */ diff --git a/external/boringssl/include/openssl/bio.h b/external/boringssl/include/openssl/bio.h new file mode 100644 index 0000000000..5416c6579f --- /dev/null +++ b/external/boringssl/include/openssl/bio.h @@ -0,0 +1,918 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_BIO_H +#define OPENSSL_HEADER_BIO_H + +#include + +#include /* For FILE */ + +#include +#include /* for ERR_print_errors_fp */ +#include +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* BIO abstracts over a file-descriptor like interface. */ + + +/* Allocation and freeing. */ + +/* BIO_new creates a new BIO with the given type and a reference count of one. + * It returns the fresh |BIO|, or NULL on error. */ +OPENSSL_EXPORT BIO *BIO_new(const BIO_METHOD *type); + +/* BIO_free decrements the reference count of |bio|. If the reference count + * drops to zero, it (optionally) calls the BIO's callback with |BIO_CB_FREE|, + * frees the ex_data and then, if the BIO has a destroy callback for the + * method, calls it. Finally it frees |bio| itself. It then repeats that for + * the next BIO in the chain, if any. + * + * It returns one on success or zero otherwise. */ +OPENSSL_EXPORT int BIO_free(BIO *bio); + +/* BIO_vfree performs the same actions as |BIO_free|, but has a void return + * value. This is provided for API-compat. + * + * TODO(fork): remove. */ +OPENSSL_EXPORT void BIO_vfree(BIO *bio); + +/* BIO_up_ref increments the reference count of |bio| and returns it. */ +OPENSSL_EXPORT BIO *BIO_up_ref(BIO *bio); + + +/* Basic I/O. */ + +/* BIO_read attempts to read |len| bytes into |data|. It returns the number of + * bytes read, zero on EOF, or a negative number on error. */ +OPENSSL_EXPORT int BIO_read(BIO *bio, void *data, int len); + +/* BIO_gets "reads a line" from |bio| and puts at most |size| bytes into |buf|. + * It returns the number of bytes read or a negative number on error. The + * phrase "reads a line" is in quotes in the previous sentence because the + * exact operation depends on the BIO's method. For example, a digest BIO will + * return the digest in response to a |BIO_gets| call. + * + * TODO(fork): audit the set of BIOs that we end up needing. If all actually + * return a line for this call, remove the warning above. */ +OPENSSL_EXPORT int BIO_gets(BIO *bio, char *buf, int size); + +/* BIO_write writes |len| bytes from |data| to BIO. It returns the number of + * bytes written or a negative number on error. */ +OPENSSL_EXPORT int BIO_write(BIO *bio, const void *data, int len); + +/* BIO_puts writes a NUL terminated string from |buf| to |bio|. It returns the + * number of bytes written or a negative number on error. */ +OPENSSL_EXPORT int BIO_puts(BIO *bio, const char *buf); + +/* BIO_flush flushes any buffered output. It returns one on success and zero + * otherwise. */ +OPENSSL_EXPORT int BIO_flush(BIO *bio); + + +/* Low-level control functions. + * + * These are generic functions for sending control requests to a BIO. In + * general one should use the wrapper functions like |BIO_get_close|. */ + +/* BIO_ctrl sends the control request |cmd| to |bio|. The |cmd| argument should + * be one of the |BIO_C_*| values. */ +OPENSSL_EXPORT long BIO_ctrl(BIO *bio, int cmd, long larg, void *parg); + +/* BIO_ptr_ctrl acts like |BIO_ctrl| but passes the address of a |void*| + * pointer as |parg| and returns the value that is written to it, or NULL if + * the control request returns <= 0. */ +OPENSSL_EXPORT char *BIO_ptr_ctrl(BIO *bp, int cmd, long larg); + +/* BIO_int_ctrl acts like |BIO_ctrl| but passes the address of a copy of |iarg| + * as |parg|. */ +OPENSSL_EXPORT long BIO_int_ctrl(BIO *bp, int cmd, long larg, int iarg); + +/* BIO_reset resets |bio| to its initial state, the precise meaning of which + * depends on the concrete type of |bio|. It returns one on success and zero + * otherwise. */ +OPENSSL_EXPORT int BIO_reset(BIO *bio); + +/* BIO_set_flags ORs |flags| with |bio->flags|. */ +OPENSSL_EXPORT void BIO_set_flags(BIO *bio, int flags); + +/* BIO_test_flags returns |bio->flags| AND |flags|. */ +OPENSSL_EXPORT int BIO_test_flags(const BIO *bio, int flags); + +/* BIO_should_read returns non-zero if |bio| encountered a temporary error + * while reading (i.e. EAGAIN), indicating that the caller should retry the + * read. */ +OPENSSL_EXPORT int BIO_should_read(const BIO *bio); + +/* BIO_should_write returns non-zero if |bio| encountered a temporary error + * while writing (i.e. EAGAIN), indicating that the caller should retry the + * write. */ +OPENSSL_EXPORT int BIO_should_write(const BIO *bio); + +/* BIO_should_retry returns non-zero if the reason that caused a failed I/O + * operation is temporary and thus the operation should be retried. Otherwise, + * it was a permanent error and it returns zero. */ +OPENSSL_EXPORT int BIO_should_retry(const BIO *bio); + +/* BIO_should_io_special returns non-zero if |bio| encountered a temporary + * error while performing a special I/O operation, indicating that the caller + * should retry. The operation that caused the error is returned by + * |BIO_get_retry_reason|. */ +OPENSSL_EXPORT int BIO_should_io_special(const BIO *bio); + +/* BIO_RR_SSL_X509_LOOKUP indicates that an SSL BIO blocked because the SSL + * library returned with SSL_ERROR_WANT_X509_LOOKUP. + * + * TODO(fork): remove. */ +#define BIO_RR_SSL_X509_LOOKUP 0x01 + +/* BIO_RR_CONNECT indicates that a connect would have blocked */ +#define BIO_RR_CONNECT 0x02 + +/* BIO_RR_ACCEPT indicates that an accept would have blocked */ +#define BIO_RR_ACCEPT 0x03 + +/* BIO_RR_SSL_CHANNEL_ID_LOOKUP indicates that the ChannelID code cannot find + * a private key for a TLS connection. */ +#define BIO_RR_SSL_CHANNEL_ID_LOOKUP 0x04 + +/* BIO_get_retry_reason returns the special I/O operation that needs to be + * retried. The return value is one of the |BIO_RR_*| values. */ +OPENSSL_EXPORT int BIO_get_retry_reason(const BIO *bio); + +/* BIO_clear_flags ANDs |bio->flags| with the bitwise-complement of |flags|. */ +OPENSSL_EXPORT void BIO_clear_flags(BIO *bio, int flags); + +/* BIO_set_retry_read sets the |BIO_FLAGS_READ| and |BIO_FLAGS_SHOULD_RETRY| + * flags on |bio|. */ +OPENSSL_EXPORT void BIO_set_retry_read(BIO *bio); + +/* BIO_set_retry_write sets the |BIO_FLAGS_WRITE| and |BIO_FLAGS_SHOULD_RETRY| + * flags on |bio|. */ +OPENSSL_EXPORT void BIO_set_retry_write(BIO *bio); + +/* BIO_get_retry_flags gets the |BIO_FLAGS_READ|, |BIO_FLAGS_WRITE|, + * |BIO_FLAGS_IO_SPECIAL| and |BIO_FLAGS_SHOULD_RETRY| flags from |bio|. */ +OPENSSL_EXPORT int BIO_get_retry_flags(BIO *bio); + +/* BIO_clear_retry_flags clears the |BIO_FLAGS_READ|, |BIO_FLAGS_WRITE|, + * |BIO_FLAGS_IO_SPECIAL| and |BIO_FLAGS_SHOULD_RETRY| flags from |bio|. */ +OPENSSL_EXPORT void BIO_clear_retry_flags(BIO *bio); + +/* BIO_method_type returns the type of |bio|, which is one of the |BIO_TYPE_*| + * values. */ +OPENSSL_EXPORT int BIO_method_type(const BIO *bio); + +/* bio_info_cb is the type of a callback function that can be called for most + * BIO operations. The |event| argument is one of |BIO_CB_*| and can be ORed + * with |BIO_CB_RETURN| if the callback is being made after the operation in + * question. In that case, |return_value| will contain the return value from + * the operation. */ +typedef long (*bio_info_cb)(BIO *bio, int event, const char *parg, int cmd, + long larg, long return_value); + +/* BIO_callback_ctrl allows the callback function to be manipulated. The |cmd| + * arg will generally be |BIO_CTRL_SET_CALLBACK| but arbitary command values + * can be interpreted by the |BIO|. */ +OPENSSL_EXPORT long BIO_callback_ctrl(BIO *bio, int cmd, bio_info_cb fp); + +/* BIO_pending returns the number of bytes pending to be read. */ +OPENSSL_EXPORT size_t BIO_pending(const BIO *bio); + +/* BIO_ctrl_pending calls |BIO_pending| and exists only for compatibility with + * OpenSSL. */ +OPENSSL_EXPORT size_t BIO_ctrl_pending(const BIO *bio); + +/* BIO_wpending returns the number of bytes pending to be written. */ +OPENSSL_EXPORT size_t BIO_wpending(const BIO *bio); + +/* BIO_set_close sets the close flag for |bio|. The meaning of which depends on + * the type of |bio| but, for example, a memory BIO interprets the close flag + * as meaning that it owns its buffer. It returns one on success and zero + * otherwise. */ +OPENSSL_EXPORT int BIO_set_close(BIO *bio, int close_flag); + +/* BIO_set_callback sets a callback function that will be called before and + * after most operations. See the comment above |bio_info_cb|. */ +OPENSSL_EXPORT void BIO_set_callback(BIO *bio, bio_info_cb callback_func); + +/* BIO_set_callback_arg sets the opaque pointer value that can be read within a + * callback with |BIO_get_callback_arg|. */ +OPENSSL_EXPORT void BIO_set_callback_arg(BIO *bio, char *arg); + +/* BIO_get_callback_arg returns the last value of the opaque callback pointer + * set by |BIO_set_callback_arg|. */ +OPENSSL_EXPORT char *BIO_get_callback_arg(const BIO *bio); + +/* BIO_number_read returns the number of bytes that have been read from + * |bio|. */ +OPENSSL_EXPORT size_t BIO_number_read(const BIO *bio); + +/* BIO_number_written returns the number of bytes that have been written to + * |bio|. */ +OPENSSL_EXPORT size_t BIO_number_written(const BIO *bio); + + +/* Managing chains of BIOs. + * + * BIOs can be put into chains where the output of one is used as the input of + * the next etc. The most common case is a buffering BIO, which accepts and + * buffers writes until flushed into the next BIO in the chain. */ + +/* BIO_push adds |appended_bio| to the end of the chain with |bio| at the head. + * It returns |bio|. Note that |appended_bio| may be the head of a chain itself + * and thus this function can be used to join two chains. + * + * BIO_push takes ownership of the caller's reference to |appended_bio|. */ +OPENSSL_EXPORT BIO *BIO_push(BIO *bio, BIO *appended_bio); + +/* BIO_pop removes |bio| from the head of a chain and returns the next BIO in + * the chain, or NULL if there is no next BIO. + * + * The caller takes ownership of the chain's reference to |bio|. */ +OPENSSL_EXPORT BIO *BIO_pop(BIO *bio); + +/* BIO_next returns the next BIO in the chain after |bio|, or NULL if there is + * no such BIO. */ +OPENSSL_EXPORT BIO *BIO_next(BIO *bio); + +/* BIO_free_all calls |BIO_free|. + * + * TODO(fork): update callers and remove. */ +OPENSSL_EXPORT void BIO_free_all(BIO *bio); + +/* BIO_find_type walks a chain of BIOs and returns the first that matches + * |type|, which is one of the |BIO_TYPE_*| values. */ +OPENSSL_EXPORT BIO *BIO_find_type(BIO *bio, int type); + +/* BIO_copy_next_retry sets the retry flags and |retry_reason| of |bio| from + * the next BIO in the chain. */ +OPENSSL_EXPORT void BIO_copy_next_retry(BIO *bio); + + +/* Printf functions. */ + +/* BIO_printf behaves like |printf| but outputs to |bio| rather than a |FILE|. + * It returns the number of bytes written or a negative number on error. */ +OPENSSL_EXPORT int BIO_printf(BIO *bio, const char *format, ...) + OPENSSL_PRINTF_FORMAT_FUNC(2, 3); + + +/* Utility functions. */ + +/* BIO_indent prints min(|indent|, |max_indent|) spaces. It returns one on + * success and zero otherwise. */ +OPENSSL_EXPORT int BIO_indent(BIO *bio, unsigned indent, unsigned max_indent); + +/* BIO_hexdump writes a hex dump of |data| to |bio|. Each line will be indented + * by |indent| spaces. */ +OPENSSL_EXPORT int BIO_hexdump(BIO *bio, const uint8_t *data, size_t len, + unsigned indent); + +/* BIO_print_errors prints the current contents of the error stack to |bio| + * using human readable strings where possible. */ +OPENSSL_EXPORT void BIO_print_errors(BIO *bio); + +/* BIO_read_asn1 reads a single ASN.1 object from |bio|. If successful it sets + * |*out| to be an allocated buffer (that should be freed with |OPENSSL_free|), + * |*out_size| to the length, in bytes, of that buffer and returns one. + * Otherwise it returns zero. + * + * If the length of the object is greater than |max_len| or 2^32 then the + * function will fail. Long-form tags are not supported. If the length of the + * object is indefinite the full contents of |bio| are read, unless it would be + * greater than |max_len|, in which case the function fails. + * + * If the function fails then some unknown amount of data may have been read + * from |bio|. */ +OPENSSL_EXPORT int BIO_read_asn1(BIO *bio, uint8_t **out, size_t *out_len, + size_t max_len); + + +/* Memory BIOs. + * + * Memory BIOs can be used as a read-only source (with |BIO_new_mem_buf|) or a + * writable sink (with |BIO_new|, |BIO_s_mem| and |BIO_get_mem_buf|). Data + * written to a writable, memory BIO can be recalled by reading from it. + * + * Calling |BIO_reset| on a read-only BIO resets it to the original contents. + * On a writable BIO, it clears any data. + * + * If the close flag is set to |BIO_NOCLOSE| (not the default) then the + * underlying |BUF_MEM| will not be freed when the |BIO| is freed. + * + * Memory BIOs support |BIO_gets| and |BIO_puts|. + * + * |BIO_ctrl_pending| returns the number of bytes currently stored. */ + +/* BIO_s_mem returns a |BIO_METHOD| that uses a in-memory buffer. */ +OPENSSL_EXPORT const BIO_METHOD *BIO_s_mem(void); + +/* BIO_new_mem_buf creates read-only BIO that reads from |len| bytes at |buf|. + * It does not take ownership of |buf|. It returns the BIO or NULL on error. + * + * If |len| is negative, then |buf| is treated as a NUL-terminated string, but + * don't depend on this in new code. */ +OPENSSL_EXPORT BIO *BIO_new_mem_buf(const void *buf, int len); + +/* BIO_mem_contents sets |*out_contents| to point to the current contents of + * |bio| and |*out_len| to contain the length of that data. It returns one on + * success and zero otherwise. */ +OPENSSL_EXPORT int BIO_mem_contents(const BIO *bio, + const uint8_t **out_contents, + size_t *out_len); + +/* BIO_get_mem_data sets |*contents| to point to the current contents of |bio| + * and returns the length of the data. + * + * WARNING: don't use this, use |BIO_mem_contents|. A return value of zero from + * this function can mean either that it failed or that the memory buffer is + * empty. */ +OPENSSL_EXPORT long BIO_get_mem_data(BIO *bio, char **contents); + +/* BIO_get_mem_ptr sets |*out| to a BUF_MEM containing the current contents of + * |bio|. It returns one on success or zero on error. */ +OPENSSL_EXPORT int BIO_get_mem_ptr(BIO *bio, BUF_MEM **out); + +/* BIO_set_mem_buf sets |b| as the contents of |bio|. If |take_ownership| is + * non-zero, then |b| will be freed when |bio| is closed. Returns one on + * success or zero otherwise. */ +OPENSSL_EXPORT int BIO_set_mem_buf(BIO *bio, BUF_MEM *b, int take_ownership); + +/* BIO_set_mem_eof_return sets the value that will be returned from reading + * |bio| when empty. If |eof_value| is zero then an empty memory BIO will + * return EOF (that is it will return zero and |BIO_should_retry| will be + * false). If |eof_value| is non zero then it will return |eof_value| when it + * is empty and it will set the read retry flag (that is |BIO_read_retry| is + * true). To avoid ambiguity with a normal positive return value, |eof_value| + * should be set to a negative value, typically -1. + * + * For a read-only BIO, the default is zero (EOF). For a writable BIO, the + * default is -1 so that additional data can be written once exhausted. */ +OPENSSL_EXPORT int BIO_set_mem_eof_return(BIO *bio, int eof_value); + + +/* File descriptor BIOs. + * + * File descriptor BIOs are wrappers around the system's |read| and |write| + * functions. If the close flag is set then then |close| is called on the + * underlying file descriptor when the BIO is freed. + * + * |BIO_reset| attempts to seek the file pointer to the start of file using + * |lseek|. */ + +/* BIO_s_fd returns a |BIO_METHOD| for file descriptor fds. */ +OPENSSL_EXPORT const BIO_METHOD *BIO_s_fd(void); + +/* BIO_new_fd creates a new file descriptor BIO wrapping |fd|. If |close_flag| + * is non-zero, then |fd| will be closed when the BIO is. */ +OPENSSL_EXPORT BIO *BIO_new_fd(int fd, int close_flag); + +/* BIO_set_fd sets the file descriptor of |bio| to |fd|. If |close_flag| is + * non-zero then |fd| will be closed when |bio| is. It returns one on success + * or zero on error. + * + * This function may also be used with socket BIOs (see |BIO_s_socket| and + * |BIO_new_socket|). */ +OPENSSL_EXPORT int BIO_set_fd(BIO *bio, int fd, int close_flag); + +/* BIO_get_fd returns the file descriptor currently in use by |bio| or -1 if + * |bio| does not wrap a file descriptor. If there is a file descriptor and + * |out_fd| is not NULL, it also sets |*out_fd| to the file descriptor. + * + * This function may also be used with socket BIOs (see |BIO_s_socket| and + * |BIO_new_socket|). */ +OPENSSL_EXPORT int BIO_get_fd(BIO *bio, int *out_fd); + + +/* File BIOs. + * + * File BIOs are wrappers around a C |FILE| object. + * + * |BIO_flush| on a file BIO calls |fflush| on the wrapped stream. + * + * |BIO_reset| attempts to seek the file pointer to the start of file using + * |fseek|. + * + * Setting the close flag causes |fclose| to be called on the stream when the + * BIO is freed. */ + +/* BIO_s_file returns a BIO_METHOD that wraps a |FILE|. */ +OPENSSL_EXPORT const BIO_METHOD *BIO_s_file(void); + +/* BIO_new_file creates a file BIO by opening |filename| with the given mode. + * See the |fopen| manual page for details of the mode argument. */ +OPENSSL_EXPORT BIO *BIO_new_file(const char *filename, const char *mode); + +/* BIO_new_fp creates a new file BIO that wraps the given |FILE|. If + * |close_flag| is |BIO_CLOSE|, then |fclose| will be called on |stream| when + * the BIO is closed. */ +OPENSSL_EXPORT BIO *BIO_new_fp(FILE *stream, int close_flag); + +/* BIO_get_fp sets |*out_file| to the current |FILE| for |bio|. It returns one + * on success and zero otherwise. */ +OPENSSL_EXPORT int BIO_get_fp(BIO *bio, FILE **out_file); + +/* BIO_set_fp sets the |FILE| for |bio|. If |close_flag| is |BIO_CLOSE| then + * |fclose| will be called on |file| when |bio| is closed. It returns one on + * sucess and zero otherwise. */ +OPENSSL_EXPORT int BIO_set_fp(BIO *bio, FILE *file, int close_flag); + +/* BIO_read_filename opens |filename| for reading and sets the result as the + * |FILE| for |bio|. It returns one on success and zero otherwise. The |FILE| + * will be closed when |bio| is freed. */ +OPENSSL_EXPORT int BIO_read_filename(BIO *bio, const char *filename); + +/* BIO_write_filename opens |filename| for writing and sets the result as the + * |FILE| for |bio|. It returns one on success and zero otherwise. The |FILE| + * will be closed when |bio| is freed. */ +OPENSSL_EXPORT int BIO_write_filename(BIO *bio, const char *filename); + +/* BIO_append_filename opens |filename| for appending and sets the result as + * the |FILE| for |bio|. It returns one on success and zero otherwise. The + * |FILE| will be closed when |bio| is freed. */ +OPENSSL_EXPORT int BIO_append_filename(BIO *bio, const char *filename); + +/* BIO_rw_filename opens |filename| for reading and writing and sets the result + * as the |FILE| for |bio|. It returns one on success and zero otherwise. The + * |FILE| will be closed when |bio| is freed. */ +OPENSSL_EXPORT int BIO_rw_filename(BIO *bio, const char *filename); + + +/* Buffer BIOs. + * + * Buffer BIOs are a filter-type BIO, i.e. they are designed to be used in a + * chain of BIOs. They provide buffering to reduce the number of operations on + * the underlying BIOs. */ + +OPENSSL_EXPORT const BIO_METHOD *BIO_f_buffer(void); + +/* BIO_set_read_buffer_size sets the size, in bytes, of the read buffer and + * clears it. It returns one on success and zero on failure. */ +OPENSSL_EXPORT int BIO_set_read_buffer_size(BIO *bio, int buffer_size); + +/* BIO_set_write_buffer_size sets the size, in bytes, of the write buffer and + * clears it. It returns one on success and zero on failure. */ +OPENSSL_EXPORT int BIO_set_write_buffer_size(BIO *bio, int buffer_size); + + +/* Socket BIOs. + * + * Socket BIOs behave like file descriptor BIOs but, on Windows systems, wrap + * the system's |recv| and |send| functions instead of |read| and |write|. On + * Windows, file descriptors are provided by C runtime and are not + * interchangeable with sockets. + * + * Socket BIOs may be used with |BIO_set_fd| and |BIO_get_fd|. + * + * TODO(davidben): Add separate APIs and fix the internals to use |SOCKET|s + * around rather than rely on int casts. */ + +OPENSSL_EXPORT const BIO_METHOD *BIO_s_socket(void); + +/* BIO_new_socket allocates and initialises a fresh BIO which will read and + * write to the socket |fd|. If |close_flag| is |BIO_CLOSE| then closing the + * BIO will close |fd|. It returns the fresh |BIO| or NULL on error. */ +OPENSSL_EXPORT BIO *BIO_new_socket(int fd, int close_flag); + + +/* Connect BIOs. + * + * A connection BIO creates a network connection and transfers data over the + * resulting socket. */ + +OPENSSL_EXPORT const BIO_METHOD *BIO_s_connect(void); + +/* BIO_new_connect returns a BIO that connects to the given hostname and port. + * The |host_and_optional_port| argument should be of the form + * "www.example.com" or "www.example.com:443". If the port is omitted, it must + * be provided with |BIO_set_conn_port|. + * + * It returns the new BIO on success, or NULL on error. */ +OPENSSL_EXPORT BIO *BIO_new_connect(const char *host_and_optional_port); + +/* BIO_set_conn_hostname sets |host_and_optional_port| as the hostname and + * optional port that |bio| will connect to. If the port is omitted, it must be + * provided with |BIO_set_conn_port|. + * + * It returns one on success and zero otherwise. */ +OPENSSL_EXPORT int BIO_set_conn_hostname(BIO *bio, + const char *host_and_optional_port); + +/* BIO_set_conn_port sets |port_str| as the port or service name that |bio| + * will connect to. It returns one on success and zero otherwise. */ +OPENSSL_EXPORT int BIO_set_conn_port(BIO *bio, const char *port_str); + +/* BIO_set_conn_int_port sets |*port| as the port that |bio| will connect to. + * It returns one on success and zero otherwise. */ +OPENSSL_EXPORT int BIO_set_conn_int_port(BIO *bio, const int *port); + +/* BIO_set_nbio sets whether |bio| will use non-blocking I/O operations. It + * returns one on success and zero otherwise. */ +OPENSSL_EXPORT int BIO_set_nbio(BIO *bio, int on); + +/* BIO_do_connect connects |bio| if it has not been connected yet. It returns + * one on success and <= 0 otherwise. */ +OPENSSL_EXPORT int BIO_do_connect(BIO *bio); + + +/* Datagram BIOs. + * + * TODO(fork): not implemented. */ + +#define BIO_CTRL_DGRAM_QUERY_MTU 40 /* as kernel for current MTU */ + +#define BIO_CTRL_DGRAM_SET_MTU 42 /* set cached value for MTU. want to use + this if asking the kernel fails */ + +#define BIO_CTRL_DGRAM_MTU_EXCEEDED 43 /* check whether the MTU was exceed in + the previous write operation. */ + +/* BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT sets a read deadline to drive + * retransmits. The |parg| argument to |BIO_ctrl| will be a pointer to a + * |timeval| struct. If the structure is all zeros, it clears the read + * deadline. Otherwise, |BIO_read| must fail with a temporary error + * (e.g. |EAGAIN|) after the deadline. */ +#define BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT 45 + +#define BIO_CTRL_DGRAM_GET_PEER 46 + +#define BIO_CTRL_DGRAM_GET_FALLBACK_MTU 47 + + +/* BIO Pairs. + * + * BIO pairs provide a "loopback" like system: a pair of BIOs where data + * written to one can be read from the other and vice versa. */ + +/* BIO_new_bio_pair sets |*out1| and |*out2| to two freshly created BIOs where + * data written to one can be read from the other and vice versa. The + * |writebuf1| argument gives the size of the buffer used in |*out1| and + * |writebuf2| for |*out2|. It returns one on success and zero on error. */ +OPENSSL_EXPORT int BIO_new_bio_pair(BIO **out1, size_t writebuf1, BIO **out2, + size_t writebuf2); + +/* BIO_new_bio_pair_external_buf is the same as |BIO_new_bio_pair| with the + * difference that the caller keeps ownership of the write buffers + * |ext_writebuf1_len| and |ext_writebuf2_len|. This is useful when using zero + * copy API for read and write operations, in cases where the buffers need to + * outlive the BIO pairs. It returns one on success and zero on error. */ +OPENSSL_EXPORT int BIO_new_bio_pair_external_buf(BIO** bio1_p, + size_t writebuf1_len, + uint8_t* ext_writebuf1, + BIO** bio2_p, + size_t writebuf2_len, + uint8_t* ext_writebuf2); + +/* BIO_ctrl_get_read_request returns the number of bytes that the other side of + * |bio| tried (unsuccessfully) to read. */ +OPENSSL_EXPORT size_t BIO_ctrl_get_read_request(BIO *bio); + +/* BIO_ctrl_get_write_guarantee returns the number of bytes that |bio| (which + * must have been returned by |BIO_new_bio_pair|) will accept on the next + * |BIO_write| call. */ +OPENSSL_EXPORT size_t BIO_ctrl_get_write_guarantee(BIO *bio); + +/* BIO_shutdown_wr marks |bio| as closed, from the point of view of the other + * side of the pair. Future |BIO_write| calls on |bio| will fail. It returns + * one on success and zero otherwise. */ +OPENSSL_EXPORT int BIO_shutdown_wr(BIO *bio); + + +/* Zero copy versions of BIO_read and BIO_write for BIO pairs. */ + +/* BIO_zero_copy_get_read_buf initiates a zero copy read operation. + * |out_read_buf| is set to the internal read buffer, and |out_buf_offset| is + * set to the current read position of |out_read_buf|. The number of bytes + * available for read from |out_read_buf| + |out_buf_offset| is returned in + * |out_available_bytes|. Note that this function might report fewer bytes + * available than |BIO_pending|, if the internal ring buffer is wrapped. It + * returns one on success. In case of error it returns zero and pushes to the + * error stack. + * + * The zero copy read operation is completed by calling + * |BIO_zero_copy_get_read_buf_done|. Neither |BIO_zero_copy_get_read_buf| nor + * any other I/O read operation may be called while a zero copy read operation + * is active. */ +OPENSSL_EXPORT int BIO_zero_copy_get_read_buf(BIO* bio, + uint8_t** out_read_buf, + size_t* out_buf_offset, + size_t* out_available_bytes); + +/* BIO_zero_copy_get_read_buf_done must be called after reading from a BIO using + * |BIO_zero_copy_get_read_buf| to finish the read operation. The |bytes_read| + * argument is the number of bytes read. + * + * It returns one on success. In case of error it returns zero and pushes to the + * error stack. */ +OPENSSL_EXPORT int BIO_zero_copy_get_read_buf_done(BIO* bio, size_t bytes_read); + +/* BIO_zero_copy_get_write_buf initiates a zero copy write operation. + * |out_write_buf| is set to to the internal write buffer, and |out_buf_offset| + * is set to the current write position of |out_write_buf|. + * The number of bytes available for write from |out_write_buf| + + * |out_buf_offset| is returned in |out_available_bytes|. Note that this + * function might report fewer bytes available than + * |BIO_ctrl_get_write_guarantee|, if the internal buffer is wrapped. It returns + * one on success. In case of error it returns zero and pushes to the error + * stack. + * + * The zero copy write operation is completed by calling + * |BIO_zero_copy_get_write_buf_done|. Neither |BIO_zero_copy_get_write_buf| + * nor any other I/O write operation may be called while a zero copy write + * operation is active. */ +OPENSSL_EXPORT int BIO_zero_copy_get_write_buf(BIO* bio, + uint8_t** out_write_buf, + size_t* out_buf_offset, + size_t* out_available_bytes); + +/* BIO_zero_copy_get_write_buf_done must be called after writing to a BIO using + * |BIO_zero_copy_get_write_buf| to finish the write operation. The + * |bytes_written| argument gives the number of bytes written. + * + * It returns one on success. In case of error it returns zero and pushes to the + * error stack. */ +OPENSSL_EXPORT int BIO_zero_copy_get_write_buf_done(BIO* bio, + size_t bytes_written); + + +/* BIO_NOCLOSE and |BIO_CLOSE| can be used as symbolic arguments when a "close + * flag" is passed to a BIO function. */ +#define BIO_NOCLOSE 0 +#define BIO_CLOSE 1 + +/* These are passed to the BIO callback */ +#define BIO_CB_FREE 0x01 +#define BIO_CB_READ 0x02 +#define BIO_CB_WRITE 0x03 +#define BIO_CB_PUTS 0x04 +#define BIO_CB_GETS 0x05 +#define BIO_CB_CTRL 0x06 + +/* The callback is called before and after the underling operation, + * The BIO_CB_RETURN flag indicates if it is after the call */ +#define BIO_CB_RETURN 0x80 + +/* These are values of the |cmd| argument to |BIO_ctrl|. */ +#define BIO_CTRL_RESET 1 /* opt - rewind/zero etc */ +#define BIO_CTRL_EOF 2 /* opt - are we at the eof */ +#define BIO_CTRL_INFO 3 /* opt - extra tit-bits */ +#define BIO_CTRL_SET 4 /* man - set the 'IO' type */ +#define BIO_CTRL_GET 5 /* man - get the 'IO' type */ +#define BIO_CTRL_PUSH 6 +#define BIO_CTRL_POP 7 +#define BIO_CTRL_GET_CLOSE 8 /* man - set the 'close' on free */ +#define BIO_CTRL_SET_CLOSE 9 /* man - set the 'close' on free */ +#define BIO_CTRL_PENDING 10 /* opt - is their more data buffered */ +#define BIO_CTRL_FLUSH 11 /* opt - 'flush' buffered output */ +#define BIO_CTRL_WPENDING 13 /* opt - number of bytes still to write */ +/* callback is int cb(BIO *bio,state,ret); */ +#define BIO_CTRL_SET_CALLBACK 14 /* opt - set callback function */ +#define BIO_CTRL_GET_CALLBACK 15 /* opt - set callback function */ +#define BIO_CTRL_SET_FILENAME 30 /* BIO_s_file special */ + +/* BIO_CTRL_DUP is never used, but exists to allow code to compile more easily. */ +#define BIO_CTRL_DUP 12 + + +/* Android compatibility section. + * + * A previous version of BoringSSL used in Android renamed ERR_print_errors_fp + * to BIO_print_errors_fp. It has subsequently been renamed back to + * ERR_print_errors_fp. */ +#define BIO_print_errors_fp ERR_print_errors_fp + + +/* Deprecated functions. */ + +/* BIO_f_base64 returns a filter |BIO| that base64-encodes data written into + * it, and decodes data read from it. |BIO_gets| is not supported. Call + * |BIO_flush| when done writing, to signal that no more data are to be + * encoded. The flag |BIO_FLAGS_BASE64_NO_NL| may be set to encode all the data + * on one line. */ +OPENSSL_EXPORT const BIO_METHOD *BIO_f_base64(void); + +/* ERR_print_errors is an alias for |BIO_print_errors|. */ +OPENSSL_EXPORT void ERR_print_errors(BIO *bio); + + +/* Private functions */ + +#define BIO_FLAGS_READ 0x01 +#define BIO_FLAGS_WRITE 0x02 +#define BIO_FLAGS_IO_SPECIAL 0x04 +#define BIO_FLAGS_RWS (BIO_FLAGS_READ | BIO_FLAGS_WRITE | BIO_FLAGS_IO_SPECIAL) +#define BIO_FLAGS_SHOULD_RETRY 0x08 +#define BIO_FLAGS_BASE64_NO_NL 0x100 +/* This is used with memory BIOs: it means we shouldn't free up or change the + * data in any way. */ +#define BIO_FLAGS_MEM_RDONLY 0x200 + +/* These are the 'types' of BIOs */ +#define BIO_TYPE_NONE 0 +#define BIO_TYPE_MEM (1 | 0x0400) +#define BIO_TYPE_FILE (2 | 0x0400) +#define BIO_TYPE_FD (4 | 0x0400 | 0x0100) +#define BIO_TYPE_SOCKET (5 | 0x0400 | 0x0100) +#define BIO_TYPE_NULL (6 | 0x0400) +#define BIO_TYPE_SSL (7 | 0x0200) +#define BIO_TYPE_MD (8 | 0x0200) /* passive filter */ +#define BIO_TYPE_BUFFER (9 | 0x0200) /* filter */ +#define BIO_TYPE_CIPHER (10 | 0x0200) /* filter */ +#define BIO_TYPE_BASE64 (11 | 0x0200) /* filter */ +#define BIO_TYPE_CONNECT (12 | 0x0400 | 0x0100) /* socket - connect */ +#define BIO_TYPE_ACCEPT (13 | 0x0400 | 0x0100) /* socket for accept */ +#define BIO_TYPE_PROXY_CLIENT (14 | 0x0200) /* client proxy BIO */ +#define BIO_TYPE_PROXY_SERVER (15 | 0x0200) /* server proxy BIO */ +#define BIO_TYPE_NBIO_TEST (16 | 0x0200) /* server proxy BIO */ +#define BIO_TYPE_NULL_FILTER (17 | 0x0200) +#define BIO_TYPE_BER (18 | 0x0200) /* BER -> bin filter */ +#define BIO_TYPE_BIO (19 | 0x0400) /* (half a) BIO pair */ +#define BIO_TYPE_LINEBUFFER (20 | 0x0200) /* filter */ +#define BIO_TYPE_DGRAM (21 | 0x0400 | 0x0100) +#define BIO_TYPE_ASN1 (22 | 0x0200) /* filter */ +#define BIO_TYPE_COMP (23 | 0x0200) /* filter */ + +#define BIO_TYPE_DESCRIPTOR 0x0100 /* socket, fd, connect or accept */ +#define BIO_TYPE_FILTER 0x0200 +#define BIO_TYPE_SOURCE_SINK 0x0400 + +struct bio_method_st { + int type; + const char *name; + int (*bwrite)(BIO *, const char *, int); + int (*bread)(BIO *, char *, int); + /* TODO(fork): remove bputs. */ + int (*bputs)(BIO *, const char *); + int (*bgets)(BIO *, char *, int); + long (*ctrl)(BIO *, int, long, void *); + int (*create)(BIO *); + int (*destroy)(BIO *); + long (*callback_ctrl)(BIO *, int, bio_info_cb); +}; + +struct bio_st { + const BIO_METHOD *method; + /* bio, mode, argp, argi, argl, ret */ + long (*callback)(BIO *, int, const char *, int, long, long); + char *cb_arg; /* first argument for the callback */ + + /* init is non-zero if this |BIO| has been initialised. */ + int init; + /* shutdown is often used by specific |BIO_METHOD|s to determine whether + * they own some underlying resource. This flag can often by controlled by + * |BIO_set_close|. For example, whether an fd BIO closes the underlying fd + * when it, itself, is closed. */ + int shutdown; + int flags; + int retry_reason; + /* num is a BIO-specific value. For example, in fd BIOs it's used to store a + * file descriptor. */ + int num; + CRYPTO_refcount_t references; + void *ptr; + /* next_bio points to the next |BIO| in a chain. This |BIO| owns a reference + * to |next_bio|. */ + BIO *next_bio; /* used by filter BIOs */ + size_t num_read, num_write; +}; + +#define BIO_C_SET_CONNECT 100 +#define BIO_C_DO_STATE_MACHINE 101 +#define BIO_C_SET_NBIO 102 +#define BIO_C_SET_PROXY_PARAM 103 +#define BIO_C_SET_FD 104 +#define BIO_C_GET_FD 105 +#define BIO_C_SET_FILE_PTR 106 +#define BIO_C_GET_FILE_PTR 107 +#define BIO_C_SET_FILENAME 108 +#define BIO_C_SET_SSL 109 +#define BIO_C_GET_SSL 110 +#define BIO_C_SET_MD 111 +#define BIO_C_GET_MD 112 +#define BIO_C_GET_CIPHER_STATUS 113 +#define BIO_C_SET_BUF_MEM 114 +#define BIO_C_GET_BUF_MEM_PTR 115 +#define BIO_C_GET_BUFF_NUM_LINES 116 +#define BIO_C_SET_BUFF_SIZE 117 +#define BIO_C_SET_ACCEPT 118 +#define BIO_C_SSL_MODE 119 +#define BIO_C_GET_MD_CTX 120 +#define BIO_C_GET_PROXY_PARAM 121 +#define BIO_C_SET_BUFF_READ_DATA 122 /* data to read first */ +#define BIO_C_GET_ACCEPT 124 +#define BIO_C_SET_SSL_RENEGOTIATE_BYTES 125 +#define BIO_C_GET_SSL_NUM_RENEGOTIATES 126 +#define BIO_C_SET_SSL_RENEGOTIATE_TIMEOUT 127 +#define BIO_C_FILE_SEEK 128 +#define BIO_C_GET_CIPHER_CTX 129 +#define BIO_C_SET_BUF_MEM_EOF_RETURN 130/*return end of input value*/ +#define BIO_C_SET_BIND_MODE 131 +#define BIO_C_GET_BIND_MODE 132 +#define BIO_C_FILE_TELL 133 +#define BIO_C_GET_SOCKS 134 +#define BIO_C_SET_SOCKS 135 + +#define BIO_C_SET_WRITE_BUF_SIZE 136/* for BIO_s_bio */ +#define BIO_C_GET_WRITE_BUF_SIZE 137 +#define BIO_C_GET_WRITE_GUARANTEE 140 +#define BIO_C_GET_READ_REQUEST 141 +#define BIO_C_SHUTDOWN_WR 142 +#define BIO_C_NREAD0 143 +#define BIO_C_NREAD 144 +#define BIO_C_NWRITE0 145 +#define BIO_C_NWRITE 146 +#define BIO_C_RESET_READ_REQUEST 147 +#define BIO_C_SET_MD_CTX 148 + +#define BIO_C_SET_PREFIX 149 +#define BIO_C_GET_PREFIX 150 +#define BIO_C_SET_SUFFIX 151 +#define BIO_C_GET_SUFFIX 152 + +#define BIO_C_SET_EX_ARG 153 +#define BIO_C_GET_EX_ARG 154 + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#define BIO_R_BAD_FOPEN_MODE 100 +#define BIO_R_BROKEN_PIPE 101 +#define BIO_R_CONNECT_ERROR 102 +#define BIO_R_ERROR_SETTING_NBIO 103 +#define BIO_R_INVALID_ARGUMENT 104 +#define BIO_R_IN_USE 105 +#define BIO_R_KEEPALIVE 106 +#define BIO_R_NBIO_CONNECT_ERROR 107 +#define BIO_R_NO_HOSTNAME_SPECIFIED 108 +#define BIO_R_NO_PORT_SPECIFIED 109 +#define BIO_R_NO_SUCH_FILE 110 +#define BIO_R_NULL_PARAMETER 111 +#define BIO_R_SYS_LIB 112 +#define BIO_R_UNABLE_TO_CREATE_SOCKET 113 +#define BIO_R_UNINITIALIZED 114 +#define BIO_R_UNSUPPORTED_METHOD 115 +#define BIO_R_WRITE_TO_READ_ONLY_BIO 116 + +#endif /* OPENSSL_HEADER_BIO_H */ diff --git a/external/boringssl/include/openssl/blowfish.h b/external/boringssl/include/openssl/blowfish.h new file mode 100644 index 0000000000..fa60d5336f --- /dev/null +++ b/external/boringssl/include/openssl/blowfish.h @@ -0,0 +1,93 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_BLOWFISH_H +#define OPENSSL_HEADER_BLOWFISH_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +#define BF_ENCRYPT 1 +#define BF_DECRYPT 0 + +#define BF_ROUNDS 16 +#define BF_BLOCK 8 + +typedef struct bf_key_st { + uint32_t P[BF_ROUNDS + 2]; + uint32_t S[4 * 256]; +} BF_KEY; + +OPENSSL_EXPORT void BF_set_key(BF_KEY *key, size_t len, const uint8_t *data); +OPENSSL_EXPORT void BF_encrypt(uint32_t *data, const BF_KEY *key); +OPENSSL_EXPORT void BF_decrypt(uint32_t *data, const BF_KEY *key); + +OPENSSL_EXPORT void BF_ecb_encrypt(const uint8_t *in, uint8_t *out, + const BF_KEY *key, int enc); +OPENSSL_EXPORT void BF_cbc_encrypt(const uint8_t *in, uint8_t *out, long length, + const BF_KEY *schedule, uint8_t *ivec, + int enc); + + +#ifdef __cplusplus +} +#endif + +#endif /* OPENSSL_HEADER_BLOWFISH_H */ diff --git a/external/boringssl/include/openssl/bn.h b/external/boringssl/include/openssl/bn.h new file mode 100644 index 0000000000..e9be0f5b21 --- /dev/null +++ b/external/boringssl/include/openssl/bn.h @@ -0,0 +1,890 @@ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * + * Portions of the attached software ("Contribution") are developed by + * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. + * + * The Contribution is licensed pursuant to the Eric Young open source + * license provided above. + * + * The binary polynomial arithmetic software is originally written by + * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems + * Laboratories. */ + +#ifndef OPENSSL_HEADER_BN_H +#define OPENSSL_HEADER_BN_H + +#include +#include + +#include /* for PRIu64 and friends */ +#include /* for FILE* */ + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* BN provides support for working with arbitary sized integers. For example, + * although the largest integer supported by the compiler might be 64 bits, BN + * will allow you to work with numbers until you run out of memory. */ + + +/* BN_ULONG is the native word size when working with big integers. + * + * Note: on some platforms, inttypes.h does not define print format macros in + * C++ unless |__STDC_FORMAT_MACROS| defined. As this is a public header, bn.h + * does not define |__STDC_FORMAT_MACROS| itself. C++ source files which use the + * FMT macros must define it externally. */ +#if defined(OPENSSL_64_BIT) +#define BN_ULONG uint64_t +#define BN_BITS2 64 +#define BN_DEC_FMT1 "%" PRIu64 +#define BN_DEC_FMT2 "%019" PRIu64 +#define BN_HEX_FMT1 "%" PRIx64 +#elif defined(OPENSSL_32_BIT) +#define BN_ULONG uint32_t +#define BN_BITS2 32 +#define BN_DEC_FMT1 "%" PRIu32 +#define BN_DEC_FMT2 "%09" PRIu32 +#define BN_HEX_FMT1 "%" PRIx32 +#else +#error "Must define either OPENSSL_32_BIT or OPENSSL_64_BIT" +#endif + + +/* Allocation and freeing. */ + +/* BN_new creates a new, allocated BIGNUM and initialises it. */ +OPENSSL_EXPORT BIGNUM *BN_new(void); + +/* BN_init initialises a stack allocated |BIGNUM|. */ +OPENSSL_EXPORT void BN_init(BIGNUM *bn); + +/* BN_free frees the data referenced by |bn| and, if |bn| was originally + * allocated on the heap, frees |bn| also. */ +OPENSSL_EXPORT void BN_free(BIGNUM *bn); + +/* BN_clear_free erases and frees the data referenced by |bn| and, if |bn| was + * originally allocated on the heap, frees |bn| also. */ +OPENSSL_EXPORT void BN_clear_free(BIGNUM *bn); + +/* BN_dup allocates a new BIGNUM and sets it equal to |src|. It returns the + * allocated BIGNUM on success or NULL otherwise. */ +OPENSSL_EXPORT BIGNUM *BN_dup(const BIGNUM *src); + +/* BN_copy sets |dest| equal to |src| and returns |dest| or NULL on allocation + * failure. */ +OPENSSL_EXPORT BIGNUM *BN_copy(BIGNUM *dest, const BIGNUM *src); + +/* BN_clear sets |bn| to zero and erases the old data. */ +OPENSSL_EXPORT void BN_clear(BIGNUM *bn); + +/* BN_value_one returns a static BIGNUM with value 1. */ +OPENSSL_EXPORT const BIGNUM *BN_value_one(void); + +/* BN_with_flags initialises a stack allocated |BIGNUM| with pointers to the + * contents of |in| but with |flags| ORed into the flags field. + * + * Note: the two BIGNUMs share state and so |out| should /not/ be passed to + * |BN_free|. */ +OPENSSL_EXPORT void BN_with_flags(BIGNUM *out, const BIGNUM *in, int flags); + + +/* Basic functions. */ + +/* BN_num_bits returns the minimum number of bits needed to represent the + * absolute value of |bn|. */ +OPENSSL_EXPORT unsigned BN_num_bits(const BIGNUM *bn); + +/* BN_num_bytes returns the minimum number of bytes needed to represent the + * absolute value of |bn|. */ +OPENSSL_EXPORT unsigned BN_num_bytes(const BIGNUM *bn); + +/* BN_zero sets |bn| to zero. */ +OPENSSL_EXPORT void BN_zero(BIGNUM *bn); + +/* BN_one sets |bn| to one. It returns one on success or zero on allocation + * failure. */ +OPENSSL_EXPORT int BN_one(BIGNUM *bn); + +/* BN_set_word sets |bn| to |value|. It returns one on success or zero on + * allocation failure. */ +OPENSSL_EXPORT int BN_set_word(BIGNUM *bn, BN_ULONG value); + +/* BN_set_negative sets the sign of |bn|. */ +OPENSSL_EXPORT void BN_set_negative(BIGNUM *bn, int sign); + +/* BN_is_negative returns one if |bn| is negative and zero otherwise. */ +OPENSSL_EXPORT int BN_is_negative(const BIGNUM *bn); + +/* BN_get_flags returns |bn->flags| & |flags|. */ +OPENSSL_EXPORT int BN_get_flags(const BIGNUM *bn, int flags); + +/* BN_set_flags sets |flags| on |bn|. */ +OPENSSL_EXPORT void BN_set_flags(BIGNUM *bn, int flags); + + +/* Conversion functions. */ + +/* BN_bin2bn sets |*ret| to the value of |len| bytes from |in|, interpreted as + * a big-endian number, and returns |ret|. If |ret| is NULL then a fresh + * |BIGNUM| is allocated and returned. It returns NULL on allocation + * failure. */ +OPENSSL_EXPORT BIGNUM *BN_bin2bn(const uint8_t *in, size_t len, BIGNUM *ret); + +/* BN_bn2bin serialises the absolute value of |in| to |out| as a big-endian + * integer, which must have |BN_num_bytes| of space available. It returns the + * number of bytes written. */ +OPENSSL_EXPORT size_t BN_bn2bin(const BIGNUM *in, uint8_t *out); + +/* BN_bn2bin_padded serialises the absolute value of |in| to |out| as a + * big-endian integer. The integer is padded with leading zeros up to size + * |len|. If |len| is smaller than |BN_num_bytes|, the function fails and + * returns 0. Otherwise, it returns 1. */ +OPENSSL_EXPORT int BN_bn2bin_padded(uint8_t *out, size_t len, const BIGNUM *in); + +/* BN_bn2cbb_padded behaves like |BN_bn2bin_padded| but writes to a |CBB|. */ +OPENSSL_EXPORT int BN_bn2cbb_padded(CBB *out, size_t len, const BIGNUM *in); + +/* BN_bn2hex returns an allocated string that contains a NUL-terminated, hex + * representation of |bn|. If |bn| is negative, the first char in the resulting + * string will be '-'. Returns NULL on allocation failure. */ +OPENSSL_EXPORT char *BN_bn2hex(const BIGNUM *bn); + +/* BN_hex2bn parses the leading hex number from |in|, which may be proceeded by + * a '-' to indicate a negative number and may contain trailing, non-hex data. + * If |outp| is not NULL, it constructs a BIGNUM equal to the hex number and + * stores it in |*outp|. If |*outp| is NULL then it allocates a new BIGNUM and + * updates |*outp|. It returns the number of bytes of |in| processed or zero on + * error. */ +OPENSSL_EXPORT int BN_hex2bn(BIGNUM **outp, const char *in); + +/* BN_bn2dec returns an allocated string that contains a NUL-terminated, + * decimal representation of |bn|. If |bn| is negative, the first char in the + * resulting string will be '-'. Returns NULL on allocation failure. */ +OPENSSL_EXPORT char *BN_bn2dec(const BIGNUM *a); + +/* BN_dec2bn parses the leading decimal number from |in|, which may be + * proceeded by a '-' to indicate a negative number and may contain trailing, + * non-decimal data. If |outp| is not NULL, it constructs a BIGNUM equal to the + * decimal number and stores it in |*outp|. If |*outp| is NULL then it + * allocates a new BIGNUM and updates |*outp|. It returns the number of bytes + * of |in| processed or zero on error. */ +OPENSSL_EXPORT int BN_dec2bn(BIGNUM **outp, const char *in); + +/* BN_asc2bn acts like |BN_dec2bn| or |BN_hex2bn| depending on whether |in| + * begins with "0X" or "0x" (indicating hex) or not (indicating decimal). A + * leading '-' is still permitted and comes before the optional 0X/0x. It + * returns one on success or zero on error. */ +OPENSSL_EXPORT int BN_asc2bn(BIGNUM **outp, const char *in); + +/* BN_print writes a hex encoding of |a| to |bio|. It returns one on success + * and zero on error. */ +OPENSSL_EXPORT int BN_print(BIO *bio, const BIGNUM *a); + +/* BN_print_fp acts like |BIO_print|, but wraps |fp| in a |BIO| first. */ +OPENSSL_EXPORT int BN_print_fp(FILE *fp, const BIGNUM *a); + +/* BN_get_word returns the absolute value of |bn| as a single word. If |bn| is + * too large to be represented as a single word, the maximum possible value + * will be returned. */ +OPENSSL_EXPORT BN_ULONG BN_get_word(const BIGNUM *bn); + + +/* ASN.1 functions. */ + +/* BN_parse_asn1_unsigned parses a non-negative DER INTEGER from |cbs| writes + * the result to |ret|. It returns one on success and zero on failure. */ +OPENSSL_EXPORT int BN_parse_asn1_unsigned(CBS *cbs, BIGNUM *ret); + +/* BN_parse_asn1_unsigned_buggy acts like |BN_parse_asn1_unsigned| but tolerates + * some invalid encodings. Do not use this function. */ +OPENSSL_EXPORT int BN_parse_asn1_unsigned_buggy(CBS *cbs, BIGNUM *ret); + +/* BN_marshal_asn1 marshals |bn| as a non-negative DER INTEGER and appends the + * result to |cbb|. It returns one on success and zero on failure. */ +OPENSSL_EXPORT int BN_marshal_asn1(CBB *cbb, const BIGNUM *bn); + + +/* Internal functions. + * + * These functions are useful for code that is doing low-level manipulations of + * BIGNUM values. However, be sure that no other function in this file does + * what you want before turning to these. */ + +/* bn_correct_top decrements |bn->top| until |bn->d[top-1]| is non-zero or + * until |top| is zero. */ +OPENSSL_EXPORT void bn_correct_top(BIGNUM *bn); + +/* bn_wexpand ensures that |bn| has at least |words| works of space without + * altering its value. It returns one on success or zero on allocation + * failure. */ +OPENSSL_EXPORT BIGNUM *bn_wexpand(BIGNUM *bn, size_t words); + + +/* BIGNUM pools. + * + * Certain BIGNUM operations need to use many temporary variables and + * allocating and freeing them can be quite slow. Thus such opertions typically + * take a |BN_CTX| parameter, which contains a pool of |BIGNUMs|. The |ctx| + * argument to a public function may be NULL, in which case a local |BN_CTX| + * will be created just for the lifetime of that call. + * + * A function must call |BN_CTX_start| first. Then, |BN_CTX_get| may be called + * repeatedly to obtain temporary |BIGNUM|s. All |BN_CTX_get| calls must be made + * before calling any other functions that use the |ctx| as an argument. + * + * Finally, |BN_CTX_end| must be called before returning from the function. + * When |BN_CTX_end| is called, the |BIGNUM| pointers obtained from + * |BN_CTX_get| become invalid. */ + +/* BN_CTX_new returns a new, empty BN_CTX or NULL on allocation failure. */ +OPENSSL_EXPORT BN_CTX *BN_CTX_new(void); + +/* BN_CTX_free frees all BIGNUMs contained in |ctx| and then frees |ctx| + * itself. */ +OPENSSL_EXPORT void BN_CTX_free(BN_CTX *ctx); + +/* BN_CTX_start "pushes" a new entry onto the |ctx| stack and allows future + * calls to |BN_CTX_get|. */ +OPENSSL_EXPORT void BN_CTX_start(BN_CTX *ctx); + +/* BN_CTX_get returns a new |BIGNUM|, or NULL on allocation failure. Once + * |BN_CTX_get| has returned NULL, all future calls will also return NULL until + * |BN_CTX_end| is called. */ +OPENSSL_EXPORT BIGNUM *BN_CTX_get(BN_CTX *ctx); + +/* BN_CTX_end invalidates all |BIGNUM|s returned from |BN_CTX_get| since the + * matching |BN_CTX_start| call. */ +OPENSSL_EXPORT void BN_CTX_end(BN_CTX *ctx); + + +/* Simple arithmetic */ + +/* BN_add sets |r| = |a| + |b|, where |r| may be the same pointer as either |a| + * or |b|. It returns one on success and zero on allocation failure. */ +OPENSSL_EXPORT int BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b); + +/* BN_uadd sets |r| = |a| + |b|, where |a| and |b| are non-negative and |r| may + * be the same pointer as either |a| or |b|. It returns one on success and zero + * on allocation failure. */ +OPENSSL_EXPORT int BN_uadd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b); + +/* BN_add_word adds |w| to |a|. It returns one on success and zero otherwise. */ +OPENSSL_EXPORT int BN_add_word(BIGNUM *a, BN_ULONG w); + +/* BN_sub sets |r| = |a| - |b|, where |r| must be a distinct pointer from |a| + * and |b|. It returns one on success and zero on allocation failure. */ +OPENSSL_EXPORT int BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b); + +/* BN_usub sets |r| = |a| - |b|, where |a| and |b| are non-negative integers, + * |b| < |a| and |r| must be a distinct pointer from |a| and |b|. It returns + * one on success and zero on allocation failure. */ +OPENSSL_EXPORT int BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b); + +/* BN_sub_word subtracts |w| from |a|. It returns one on success and zero on + * allocation failure. */ +OPENSSL_EXPORT int BN_sub_word(BIGNUM *a, BN_ULONG w); + +/* BN_mul sets |r| = |a| * |b|, where |r| may be the same pointer as |a| or + * |b|. Returns one on success and zero otherwise. */ +OPENSSL_EXPORT int BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + BN_CTX *ctx); + +/* BN_mul_word sets |bn| = |bn| * |w|. It returns one on success or zero on + * allocation failure. */ +OPENSSL_EXPORT int BN_mul_word(BIGNUM *bn, BN_ULONG w); + +/* BN_sqr sets |r| = |a|^2 (i.e. squares), where |r| may be the same pointer as + * |a|. Returns one on success and zero otherwise. This is more efficient than + * BN_mul(r, a, a, ctx). */ +OPENSSL_EXPORT int BN_sqr(BIGNUM *r, const BIGNUM *a, BN_CTX *ctx); + +/* BN_div divides |numerator| by |divisor| and places the result in |quotient| + * and the remainder in |rem|. Either of |quotient| or |rem| may be NULL, in + * which case the respective value is not returned. The result is rounded + * towards zero; thus if |numerator| is negative, the remainder will be zero or + * negative. It returns one on success or zero on error. */ +OPENSSL_EXPORT int BN_div(BIGNUM *quotient, BIGNUM *rem, + const BIGNUM *numerator, const BIGNUM *divisor, + BN_CTX *ctx); + +/* BN_div_word sets |numerator| = |numerator|/|divisor| and returns the + * remainder or (BN_ULONG)-1 on error. */ +OPENSSL_EXPORT BN_ULONG BN_div_word(BIGNUM *numerator, BN_ULONG divisor); + +/* BN_sqrt sets |*out_sqrt| (which may be the same |BIGNUM| as |in|) to the + * square root of |in|, using |ctx|. It returns one on success or zero on + * error. Negative numbers and non-square numbers will result in an error with + * appropriate errors on the error queue. */ +OPENSSL_EXPORT int BN_sqrt(BIGNUM *out_sqrt, const BIGNUM *in, BN_CTX *ctx); + + +/* Comparison functions */ + +/* BN_cmp returns a value less than, equal to or greater than zero if |a| is + * less than, equal to or greater than |b|, respectively. */ +OPENSSL_EXPORT int BN_cmp(const BIGNUM *a, const BIGNUM *b); + +/* BN_ucmp returns a value less than, equal to or greater than zero if the + * absolute value of |a| is less than, equal to or greater than the absolute + * value of |b|, respectively. */ +OPENSSL_EXPORT int BN_ucmp(const BIGNUM *a, const BIGNUM *b); + +/* BN_equal_consttime returns one if |a| is equal to |b|, and zero otherwise. + * It takes an amount of time dependent on the sizes of |a| and |b|, but + * independent of the contents (including the signs) of |a| and |b|. */ +OPENSSL_EXPORT int BN_equal_consttime(const BIGNUM *a, const BIGNUM *b); + +/* BN_abs_is_word returns one if the absolute value of |bn| equals |w| and zero + * otherwise. */ +OPENSSL_EXPORT int BN_abs_is_word(const BIGNUM *bn, BN_ULONG w); + +/* BN_is_zero returns one if |bn| is zero and zero otherwise. */ +OPENSSL_EXPORT int BN_is_zero(const BIGNUM *bn); + +/* BN_is_one returns one if |bn| equals one and zero otherwise. */ +OPENSSL_EXPORT int BN_is_one(const BIGNUM *bn); + +/* BN_is_word returns one if |bn| is exactly |w| and zero otherwise. */ +OPENSSL_EXPORT int BN_is_word(const BIGNUM *bn, BN_ULONG w); + +/* BN_is_odd returns one if |bn| is odd and zero otherwise. */ +OPENSSL_EXPORT int BN_is_odd(const BIGNUM *bn); + + +/* Bitwise operations. */ + +/* BN_lshift sets |r| equal to |a| << n. The |a| and |r| arguments may be the + * same |BIGNUM|. It returns one on success and zero on allocation failure. */ +OPENSSL_EXPORT int BN_lshift(BIGNUM *r, const BIGNUM *a, int n); + +/* BN_lshift1 sets |r| equal to |a| << 1, where |r| and |a| may be the same + * pointer. It returns one on success and zero on allocation failure. */ +OPENSSL_EXPORT int BN_lshift1(BIGNUM *r, const BIGNUM *a); + +/* BN_rshift sets |r| equal to |a| >> n, where |r| and |a| may be the same + * pointer. It returns one on success and zero on allocation failure. */ +OPENSSL_EXPORT int BN_rshift(BIGNUM *r, const BIGNUM *a, int n); + +/* BN_rshift1 sets |r| equal to |a| >> 1, where |r| and |a| may be the same + * pointer. It returns one on success and zero on allocation failure. */ +OPENSSL_EXPORT int BN_rshift1(BIGNUM *r, const BIGNUM *a); + +/* BN_set_bit sets the |n|th, least-significant bit in |a|. For example, if |a| + * is 2 then setting bit zero will make it 3. It returns one on success or zero + * on allocation failure. */ +OPENSSL_EXPORT int BN_set_bit(BIGNUM *a, int n); + +/* BN_clear_bit clears the |n|th, least-significant bit in |a|. For example, if + * |a| is 3, clearing bit zero will make it two. It returns one on success or + * zero on allocation failure. */ +OPENSSL_EXPORT int BN_clear_bit(BIGNUM *a, int n); + +/* BN_is_bit_set returns the value of the |n|th, least-significant bit in |a|, + * or zero if the bit doesn't exist. */ +OPENSSL_EXPORT int BN_is_bit_set(const BIGNUM *a, int n); + +/* BN_mask_bits truncates |a| so that it is only |n| bits long. It returns one + * on success or zero if |n| is greater than the length of |a| already. */ +OPENSSL_EXPORT int BN_mask_bits(BIGNUM *a, int n); + + +/* Modulo arithmetic. */ + +/* BN_mod_word returns |a| mod |w|. */ +OPENSSL_EXPORT BN_ULONG BN_mod_word(const BIGNUM *a, BN_ULONG w); + +/* BN_mod is a helper macro that calls |BN_div| and discards the quotient. */ +#define BN_mod(rem, numerator, divisor, ctx) \ + BN_div(NULL, (rem), (numerator), (divisor), (ctx)) + +/* BN_nnmod is a non-negative modulo function. It acts like |BN_mod|, but 0 <= + * |rem| < |divisor| is always true. It returns one on success and zero on + * error. */ +OPENSSL_EXPORT int BN_nnmod(BIGNUM *rem, const BIGNUM *numerator, + const BIGNUM *divisor, BN_CTX *ctx); + +/* BN_mod_add sets |r| = |a| + |b| mod |m|. It returns one on success and zero + * on error. */ +OPENSSL_EXPORT int BN_mod_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const BIGNUM *m, BN_CTX *ctx); + +/* BN_mod_add_quick acts like |BN_mod_add| but requires that |a| and |b| be + * non-negative and less than |m|. */ +OPENSSL_EXPORT int BN_mod_add_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const BIGNUM *m); + +/* BN_mod_sub sets |r| = |a| - |b| mod |m|. It returns one on success and zero + * on error. */ +OPENSSL_EXPORT int BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const BIGNUM *m, BN_CTX *ctx); + +/* BN_mod_sub_quick acts like |BN_mod_sub| but requires that |a| and |b| be + * non-negative and less than |m|. */ +OPENSSL_EXPORT int BN_mod_sub_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const BIGNUM *m); + +/* BN_mod_mul sets |r| = |a|*|b| mod |m|. It returns one on success and zero + * on error. */ +OPENSSL_EXPORT int BN_mod_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const BIGNUM *m, BN_CTX *ctx); + +/* BN_mod_sqr sets |r| = |a|^2 mod |m|. It returns one on success and zero + * on error. */ +OPENSSL_EXPORT int BN_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, + BN_CTX *ctx); + +/* BN_mod_lshift sets |r| = (|a| << n) mod |m|, where |r| and |a| may be the + * same pointer. It returns one on success and zero on error. */ +OPENSSL_EXPORT int BN_mod_lshift(BIGNUM *r, const BIGNUM *a, int n, + const BIGNUM *m, BN_CTX *ctx); + +/* BN_mod_lshift_quick acts like |BN_mod_lshift| but requires that |a| be + * non-negative and less than |m|. */ +OPENSSL_EXPORT int BN_mod_lshift_quick(BIGNUM *r, const BIGNUM *a, int n, + const BIGNUM *m); + +/* BN_mod_lshift1 sets |r| = (|a| << 1) mod |m|, where |r| and |a| may be the + * same pointer. It returns one on success and zero on error. */ +OPENSSL_EXPORT int BN_mod_lshift1(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, + BN_CTX *ctx); + +/* BN_mod_lshift1_quick acts like |BN_mod_lshift1| but requires that |a| be + * non-negative and less than |m|. */ +OPENSSL_EXPORT int BN_mod_lshift1_quick(BIGNUM *r, const BIGNUM *a, + const BIGNUM *m); + +/* BN_mod_sqrt returns a |BIGNUM|, r, such that r^2 == a (mod p). */ +OPENSSL_EXPORT BIGNUM *BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p, + BN_CTX *ctx); + + +/* Random and prime number generation. */ + +/* BN_rand sets |rnd| to a random number of length |bits|. If |top| is zero, the + * most-significant bit, if any, will be set. If |top| is one, the two most + * significant bits, if any, will be set. + * + * If |top| is -1 then no extra action will be taken and |BN_num_bits(rnd)| may + * not equal |bits| if the most significant bits randomly ended up as zeros. + * + * If |bottom| is non-zero, the least-significant bit, if any, will be set. The + * function returns one on success or zero otherwise. */ +OPENSSL_EXPORT int BN_rand(BIGNUM *rnd, int bits, int top, int bottom); + +/* BN_pseudo_rand is an alias for |BN_rand|. */ +OPENSSL_EXPORT int BN_pseudo_rand(BIGNUM *rnd, int bits, int top, int bottom); + +/* BN_rand_range sets |rnd| to a random value [0..range). It returns one on + * success and zero otherwise. */ +OPENSSL_EXPORT int BN_rand_range(BIGNUM *rnd, const BIGNUM *range); + +/* BN_pseudo_rand_range is an alias for BN_rand_range. */ +OPENSSL_EXPORT int BN_pseudo_rand_range(BIGNUM *rnd, const BIGNUM *range); + +/* BN_generate_dsa_nonce generates a random number 0 <= out < range. Unlike + * BN_rand_range, it also includes the contents of |priv| and |message| in the + * generation so that an RNG failure isn't fatal as long as |priv| remains + * secret. This is intended for use in DSA and ECDSA where an RNG weakness + * leads directly to private key exposure unless this function is used. + * It returns one on success and zero on error. */ +OPENSSL_EXPORT int BN_generate_dsa_nonce(BIGNUM *out, const BIGNUM *range, + const BIGNUM *priv, + const uint8_t *message, + size_t message_len, BN_CTX *ctx); + +/* BN_GENCB holds a callback function that is used by generation functions that + * can take a very long time to complete. Use |BN_GENCB_set| to initialise a + * |BN_GENCB| structure. + * + * The callback receives the address of that |BN_GENCB| structure as its last + * argument and the user is free to put an arbitary pointer in |arg|. The other + * arguments are set as follows: + * event=BN_GENCB_GENERATED, n=i: after generating the i'th possible prime + * number. + * event=BN_GENCB_PRIME_TEST, n=-1: when finished trial division primality + * checks. + * event=BN_GENCB_PRIME_TEST, n=i: when the i'th primality test has finished. + * + * The callback can return zero to abort the generation progress or one to + * allow it to continue. + * + * When other code needs to call a BN generation function it will often take a + * BN_GENCB argument and may call the function with other argument values. */ +#define BN_GENCB_GENERATED 0 +#define BN_GENCB_PRIME_TEST 1 + +struct bn_gencb_st { + void *arg; /* callback-specific data */ + int (*callback)(int event, int n, struct bn_gencb_st *); +}; + +/* BN_GENCB_set configures |callback| to call |f| and sets |callout->arg| to + * |arg|. */ +OPENSSL_EXPORT void BN_GENCB_set(BN_GENCB *callback, + int (*f)(int event, int n, + struct bn_gencb_st *), + void *arg); + +/* BN_GENCB_call calls |callback|, if not NULL, and returns the return value of + * the callback, or 1 if |callback| is NULL. */ +OPENSSL_EXPORT int BN_GENCB_call(BN_GENCB *callback, int event, int n); + +/* BN_generate_prime_ex sets |ret| to a prime number of |bits| length. If safe + * is non-zero then the prime will be such that (ret-1)/2 is also a prime. + * (This is needed for Diffie-Hellman groups to ensure that the only subgroups + * are of size 2 and (p-1)/2.). + * + * If |add| is not NULL, the prime will fulfill the condition |ret| % |add| == + * |rem| in order to suit a given generator. (If |rem| is NULL then |ret| % + * |add| == 1.) + * + * If |cb| is not NULL, it will be called during processing to give an + * indication of progress. See the comments for |BN_GENCB|. It returns one on + * success and zero otherwise. */ +OPENSSL_EXPORT int BN_generate_prime_ex(BIGNUM *ret, int bits, int safe, + const BIGNUM *add, const BIGNUM *rem, + BN_GENCB *cb); + +/* BN_prime_checks is magic value that can be used as the |checks| argument to + * the primality testing functions in order to automatically select a number of + * Miller-Rabin checks that gives a false positive rate of ~2^{-80}. */ +#define BN_prime_checks 0 + +/* BN_primality_test sets |*is_probably_prime| to one if |candidate| is + * probably a prime number by the Miller-Rabin test or zero if it's certainly + * not. + * + * If |do_trial_division| is non-zero then |candidate| will be tested against a + * list of small primes before Miller-Rabin tests. The probability of this + * function returning a false positive is 2^{2*checks}. If |checks| is + * |BN_prime_checks| then a value that results in approximately 2^{-80} false + * positive probability is used. If |cb| is not NULL then it is called during + * the checking process. See the comment above |BN_GENCB|. + * + * The function returns one on success and zero on error. + * + * (If you are unsure whether you want |do_trial_division|, don't set it.) */ +OPENSSL_EXPORT int BN_primality_test(int *is_probably_prime, + const BIGNUM *candidate, int checks, + BN_CTX *ctx, int do_trial_division, + BN_GENCB *cb); + +/* BN_is_prime_fasttest_ex returns one if |candidate| is probably a prime + * number by the Miller-Rabin test, zero if it's certainly not and -1 on error. + * + * If |do_trial_division| is non-zero then |candidate| will be tested against a + * list of small primes before Miller-Rabin tests. The probability of this + * function returning one when |candidate| is composite is 2^{2*checks}. If + * |checks| is |BN_prime_checks| then a value that results in approximately + * 2^{-80} false positive probability is used. If |cb| is not NULL then it is + * called during the checking process. See the comment above |BN_GENCB|. + * + * WARNING: deprecated. Use |BN_primality_test|. */ +OPENSSL_EXPORT int BN_is_prime_fasttest_ex(const BIGNUM *candidate, int checks, + BN_CTX *ctx, int do_trial_division, + BN_GENCB *cb); + +/* BN_is_prime_ex acts the same as |BN_is_prime_fasttest_ex| with + * |do_trial_division| set to zero. + * + * WARNING: deprecated: Use |BN_primality_test|. */ +OPENSSL_EXPORT int BN_is_prime_ex(const BIGNUM *candidate, int checks, + BN_CTX *ctx, BN_GENCB *cb); + + +/* Number theory functions */ + +/* BN_gcd sets |r| = gcd(|a|, |b|). It returns one on success and zero + * otherwise. */ +OPENSSL_EXPORT int BN_gcd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + BN_CTX *ctx); + +/* BN_mod_inverse sets |out| equal to |a|^-1, mod |n|. If either of |a| or |n| + * have |BN_FLG_CONSTTIME| set then the operation is performed in constant + * time. If |out| is NULL, a fresh BIGNUM is allocated. It returns the result + * or NULL on error. */ +OPENSSL_EXPORT BIGNUM *BN_mod_inverse(BIGNUM *out, const BIGNUM *a, + const BIGNUM *n, BN_CTX *ctx); + +/* BN_mod_inverse_ex acts like |BN_mod_inverse| except that, when it returns + * zero, it will set |*out_no_inverse| to one if the failure was caused because + * |a| has no inverse mod |n|. Otherwise it will set |*out_no_inverse| to + * zero. */ +OPENSSL_EXPORT BIGNUM *BN_mod_inverse_ex(BIGNUM *out, int *out_no_inverse, + const BIGNUM *a, const BIGNUM *n, + BN_CTX *ctx); + +/* BN_kronecker returns the Kronecker symbol of |a| and |b| (which is -1, 0 or + * 1), or -2 on error. */ +OPENSSL_EXPORT int BN_kronecker(const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx); + + +/* Montgomery arithmetic. */ + +/* BN_MONT_CTX contains the precomputed values needed to work in a specific + * Montgomery domain. */ + +/* BN_MONT_CTX_new returns a fresh BN_MONT_CTX or NULL on allocation failure. */ +OPENSSL_EXPORT BN_MONT_CTX *BN_MONT_CTX_new(void); + +/* BN_MONT_CTX_free frees memory associated with |mont|. */ +OPENSSL_EXPORT void BN_MONT_CTX_free(BN_MONT_CTX *mont); + +/* BN_MONT_CTX_copy sets |to| equal to |from|. It returns |to| on success or + * NULL on error. */ +OPENSSL_EXPORT BN_MONT_CTX *BN_MONT_CTX_copy(BN_MONT_CTX *to, + const BN_MONT_CTX *from); + +/* BN_MONT_CTX_set sets up a Montgomery context given the modulus, |mod|. It + * returns one on success and zero on error. */ +OPENSSL_EXPORT int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, + BN_CTX *ctx); + +/* BN_MONT_CTX_set_locked takes |lock| and checks whether |*pmont| is NULL. If + * so, it creates a new |BN_MONT_CTX| and sets the modulus for it to |mod|. It + * then stores it as |*pmont|. It returns one on success and zero on error. + * + * If |*pmont| is already non-NULL then it does nothing and returns one. */ +int BN_MONT_CTX_set_locked(BN_MONT_CTX **pmont, CRYPTO_MUTEX *lock, + const BIGNUM *mod, BN_CTX *bn_ctx); + +/* BN_to_montgomery sets |ret| equal to |a| in the Montgomery domain. It + * returns one on success and zero on error. */ +OPENSSL_EXPORT int BN_to_montgomery(BIGNUM *ret, const BIGNUM *a, + const BN_MONT_CTX *mont, BN_CTX *ctx); + +/* BN_from_montgomery sets |ret| equal to |a| * R^-1, i.e. translates values + * out of the Montgomery domain. It returns one on success or zero on error. */ +OPENSSL_EXPORT int BN_from_montgomery(BIGNUM *ret, const BIGNUM *a, + const BN_MONT_CTX *mont, BN_CTX *ctx); + +/* BN_mod_mul_montgomery set |r| equal to |a| * |b|, in the Montgomery domain. + * Both |a| and |b| must already be in the Montgomery domain (by + * |BN_to_montgomery|). It returns one on success or zero on error. */ +OPENSSL_EXPORT int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, + const BIGNUM *b, + const BN_MONT_CTX *mont, BN_CTX *ctx); + + +/* Exponentiation. */ + +/* BN_exp sets |r| equal to |a|^{|p|}. It does so with a square-and-multiply + * algorithm that leaks side-channel information. It returns one on success or + * zero otherwise. */ +OPENSSL_EXPORT int BN_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + BN_CTX *ctx); + +/* BN_mod_exp sets |r| equal to |a|^{|p|} mod |m|. It does so with the best + * algorithm for the values provided and can run in constant time if + * |BN_FLG_CONSTTIME| is set for |p|. It returns one on success or zero + * otherwise. */ +OPENSSL_EXPORT int BN_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx); + +OPENSSL_EXPORT int BN_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, + const BN_MONT_CTX *mont); + +OPENSSL_EXPORT int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, + const BIGNUM *p, const BIGNUM *m, + BN_CTX *ctx, + const BN_MONT_CTX *mont); + + +/* Deprecated functions */ + +/* BN_bn2mpi serialises the value of |in| to |out|, using a format that consists + * of the number's length in bytes represented as a 4-byte big-endian number, + * and the number itself in big-endian format, where the most significant bit + * signals a negative number. (The representation of numbers with the MSB set is + * prefixed with null byte). |out| must have sufficient space available; to + * find the needed amount of space, call the function with |out| set to NULL. */ +OPENSSL_EXPORT size_t BN_bn2mpi(const BIGNUM *in, uint8_t *out); + +/* BN_mpi2bn parses |len| bytes from |in| and returns the resulting value. The + * bytes at |in| are expected to be in the format emitted by |BN_bn2mpi|. + * + * If |out| is NULL then a fresh |BIGNUM| is allocated and returned, otherwise + * |out| is reused and returned. On error, NULL is returned and the error queue + * is updated. */ +OPENSSL_EXPORT BIGNUM *BN_mpi2bn(const uint8_t *in, size_t len, BIGNUM *out); + +/* BN_mod_exp_mont_word is like |BN_mod_exp_mont| except that the base |a| is + * given as a |BN_ULONG| instead of a |BIGNUM *|. It returns one on success + * or zero otherwise. */ +OPENSSL_EXPORT int BN_mod_exp_mont_word(BIGNUM *r, BN_ULONG a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, + const BN_MONT_CTX *mont); + +/* BN_mod_exp2_mont calculates (a1^p1) * (a2^p2) mod m. It returns 1 on success + * or zero otherwise. */ +OPENSSL_EXPORT int BN_mod_exp2_mont(BIGNUM *r, const BIGNUM *a1, + const BIGNUM *p1, const BIGNUM *a2, + const BIGNUM *p2, const BIGNUM *m, + BN_CTX *ctx, const BN_MONT_CTX *mont); + + +/* Private functions */ + +struct bignum_st { + BN_ULONG *d; /* Pointer to an array of 'BN_BITS2' bit chunks in little-endian + order. */ + int top; /* Index of last used element in |d|, plus one. */ + int dmax; /* Size of |d|, in words. */ + int neg; /* one if the number is negative */ + int flags; /* bitmask of BN_FLG_* values */ +}; + +struct bn_mont_ctx_st { + BIGNUM RR; /* used to convert to montgomery form */ + BIGNUM N; /* The modulus */ + BN_ULONG n0[2]; /* least significant words of (R*Ri-1)/N */ +}; + +OPENSSL_EXPORT unsigned BN_num_bits_word(BN_ULONG l); + +#define BN_FLG_MALLOCED 0x01 +#define BN_FLG_STATIC_DATA 0x02 +/* avoid leaking exponent information through timing, BN_mod_exp_mont() will + * call BN_mod_exp_mont_consttime, BN_div() will call BN_div_no_branch, + * BN_mod_inverse() will call BN_mod_inverse_no_branch. */ +#define BN_FLG_CONSTTIME 0x04 + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#define BN_R_ARG2_LT_ARG3 100 +#define BN_R_BAD_RECIPROCAL 101 +#define BN_R_BIGNUM_TOO_LONG 102 +#define BN_R_BITS_TOO_SMALL 103 +#define BN_R_CALLED_WITH_EVEN_MODULUS 104 +#define BN_R_DIV_BY_ZERO 105 +#define BN_R_EXPAND_ON_STATIC_BIGNUM_DATA 106 +#define BN_R_INPUT_NOT_REDUCED 107 +#define BN_R_INVALID_RANGE 108 +#define BN_R_NEGATIVE_NUMBER 109 +#define BN_R_NOT_A_SQUARE 110 +#define BN_R_NOT_INITIALIZED 111 +#define BN_R_NO_INVERSE 112 +#define BN_R_PRIVATE_KEY_TOO_LARGE 113 +#define BN_R_P_IS_NOT_PRIME 114 +#define BN_R_TOO_MANY_ITERATIONS 115 +#define BN_R_TOO_MANY_TEMPORARY_VARIABLES 116 +#define BN_R_BAD_ENCODING 117 +#define BN_R_ENCODE_ERROR 118 + +#endif /* OPENSSL_HEADER_BN_H */ diff --git a/external/boringssl/include/openssl/buf.h b/external/boringssl/include/openssl/buf.h new file mode 100644 index 0000000000..8ae856b671 --- /dev/null +++ b/external/boringssl/include/openssl/buf.h @@ -0,0 +1,122 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_BUFFER_H +#define OPENSSL_HEADER_BUFFER_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* Memory and string functions, see also mem.h. */ + + +/* buf_mem_st (aka |BUF_MEM|) is a generic buffer object used by OpenSSL. */ +struct buf_mem_st { + size_t length; /* current number of bytes */ + char *data; + size_t max; /* size of buffer */ +}; + +/* BUF_MEM_new creates a new BUF_MEM which has no allocated data buffer. */ +OPENSSL_EXPORT BUF_MEM *BUF_MEM_new(void); + +/* BUF_MEM_free frees |buf->data| if needed and then frees |buf| itself. */ +OPENSSL_EXPORT void BUF_MEM_free(BUF_MEM *buf); + +/* BUF_MEM_reserve ensures |buf| has capacity |cap| and allocates memory if + * needed. It returns one on success and zero on error. */ +OPENSSL_EXPORT int BUF_MEM_reserve(BUF_MEM *buf, size_t cap); + +/* BUF_MEM_grow ensures that |buf| has length |len| and allocates memory if + * needed. If the length of |buf| increased, the new bytes are filled with + * zeros. It returns the length of |buf|, or zero if there's an error. */ +OPENSSL_EXPORT size_t BUF_MEM_grow(BUF_MEM *buf, size_t len); + +/* BUF_MEM_grow_clean acts the same as |BUF_MEM_grow|, but clears the previous + * contents of memory if reallocing. */ +OPENSSL_EXPORT size_t BUF_MEM_grow_clean(BUF_MEM *str, size_t len); + +/* BUF_strdup returns an allocated, duplicate of |str|. */ +OPENSSL_EXPORT char *BUF_strdup(const char *str); + +/* BUF_strnlen returns the number of characters in |str|, excluding the NUL + * byte, but at most |max_len|. This function never reads more than |max_len| + * bytes from |str|. */ +OPENSSL_EXPORT size_t BUF_strnlen(const char *str, size_t max_len); + +/* BUF_strndup returns an allocated, duplicate of |str|, which is, at most, + * |size| bytes. The result is always NUL terminated. */ +OPENSSL_EXPORT char *BUF_strndup(const char *str, size_t size); + +/* BUF_memdup returns an allocated, duplicate of |size| bytes from |data|. */ +OPENSSL_EXPORT void *BUF_memdup(const void *data, size_t size); + +/* BUF_strlcpy acts like strlcpy(3). */ +OPENSSL_EXPORT size_t BUF_strlcpy(char *dst, const char *src, size_t dst_size); + +/* BUF_strlcat acts like strlcat(3). */ +OPENSSL_EXPORT size_t BUF_strlcat(char *dst, const char *src, size_t size); + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_BUFFER_H */ diff --git a/external/boringssl/include/openssl/buffer.h b/external/boringssl/include/openssl/buffer.h new file mode 100644 index 0000000000..c6b721c277 --- /dev/null +++ b/external/boringssl/include/openssl/buffer.h @@ -0,0 +1,18 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +/* This header is provided in order to make compiling against code that expects + OpenSSL easier. */ + +#include "buf.h" diff --git a/external/boringssl/include/openssl/bytestring.h b/external/boringssl/include/openssl/bytestring.h new file mode 100644 index 0000000000..3a8d4e535f --- /dev/null +++ b/external/boringssl/include/openssl/bytestring.h @@ -0,0 +1,394 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_BYTESTRING_H +#define OPENSSL_HEADER_BYTESTRING_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* Bytestrings are used for parsing and building TLS and ASN.1 messages. + * + * A "CBS" (CRYPTO ByteString) represents a string of bytes in memory and + * provides utility functions for safely parsing length-prefixed structures + * like TLS and ASN.1 from it. + * + * A "CBB" (CRYPTO ByteBuilder) is a memory buffer that grows as needed and + * provides utility functions for building length-prefixed messages. */ + + +/* CRYPTO ByteString */ + +struct cbs_st { + const uint8_t *data; + size_t len; +}; + +/* CBS_init sets |cbs| to point to |data|. It does not take ownership of + * |data|. */ +OPENSSL_EXPORT void CBS_init(CBS *cbs, const uint8_t *data, size_t len); + +/* CBS_skip advances |cbs| by |len| bytes. It returns one on success and zero + * otherwise. */ +OPENSSL_EXPORT int CBS_skip(CBS *cbs, size_t len); + +/* CBS_data returns a pointer to the contents of |cbs|. */ +OPENSSL_EXPORT const uint8_t *CBS_data(const CBS *cbs); + +/* CBS_len returns the number of bytes remaining in |cbs|. */ +OPENSSL_EXPORT size_t CBS_len(const CBS *cbs); + +/* CBS_stow copies the current contents of |cbs| into |*out_ptr| and + * |*out_len|. If |*out_ptr| is not NULL, the contents are freed with + * OPENSSL_free. It returns one on success and zero on allocation failure. On + * success, |*out_ptr| should be freed with OPENSSL_free. If |cbs| is empty, + * |*out_ptr| will be NULL. */ +OPENSSL_EXPORT int CBS_stow(const CBS *cbs, uint8_t **out_ptr, size_t *out_len); + +/* CBS_strdup copies the current contents of |cbs| into |*out_ptr| as a + * NUL-terminated C string. If |*out_ptr| is not NULL, the contents are freed + * with OPENSSL_free. It returns one on success and zero on allocation + * failure. On success, |*out_ptr| should be freed with OPENSSL_free. + * + * NOTE: If |cbs| contains NUL bytes, the string will be truncated. Call + * |CBS_contains_zero_byte(cbs)| to check for NUL bytes. */ +OPENSSL_EXPORT int CBS_strdup(const CBS *cbs, char **out_ptr); + +/* CBS_contains_zero_byte returns one if the current contents of |cbs| contains + * a NUL byte and zero otherwise. */ +OPENSSL_EXPORT int CBS_contains_zero_byte(const CBS *cbs); + +/* CBS_mem_equal compares the current contents of |cbs| with the |len| bytes + * starting at |data|. If they're equal, it returns one, otherwise zero. If the + * lengths match, it uses a constant-time comparison. */ +OPENSSL_EXPORT int CBS_mem_equal(const CBS *cbs, const uint8_t *data, + size_t len); + +/* CBS_get_u8 sets |*out| to the next uint8_t from |cbs| and advances |cbs|. It + * returns one on success and zero on error. */ +OPENSSL_EXPORT int CBS_get_u8(CBS *cbs, uint8_t *out); + +/* CBS_get_u16 sets |*out| to the next, big-endian uint16_t from |cbs| and + * advances |cbs|. It returns one on success and zero on error. */ +OPENSSL_EXPORT int CBS_get_u16(CBS *cbs, uint16_t *out); + +/* CBS_get_u24 sets |*out| to the next, big-endian 24-bit value from |cbs| and + * advances |cbs|. It returns one on success and zero on error. */ +OPENSSL_EXPORT int CBS_get_u24(CBS *cbs, uint32_t *out); + +/* CBS_get_u32 sets |*out| to the next, big-endian uint32_t value from |cbs| + * and advances |cbs|. It returns one on success and zero on error. */ +OPENSSL_EXPORT int CBS_get_u32(CBS *cbs, uint32_t *out); + +/* CBS_get_last_u8 sets |*out| to the last uint8_t from |cbs| and shortens + * |cbs|. It returns one on success and zero on error. */ +OPENSSL_EXPORT int CBS_get_last_u8(CBS *cbs, uint8_t *out); + +/* CBS_get_bytes sets |*out| to the next |len| bytes from |cbs| and advances + * |cbs|. It returns one on success and zero on error. */ +OPENSSL_EXPORT int CBS_get_bytes(CBS *cbs, CBS *out, size_t len); + +/* CBS_copy_bytes copies the next |len| bytes from |cbs| to |out| and advances + * |cbs|. It returns one on success and zero on error. */ +OPENSSL_EXPORT int CBS_copy_bytes(CBS *cbs, uint8_t *out, size_t len); + +/* CBS_get_u8_length_prefixed sets |*out| to the contents of an 8-bit, + * length-prefixed value from |cbs| and advances |cbs| over it. It returns one + * on success and zero on error. */ +OPENSSL_EXPORT int CBS_get_u8_length_prefixed(CBS *cbs, CBS *out); + +/* CBS_get_u16_length_prefixed sets |*out| to the contents of a 16-bit, + * big-endian, length-prefixed value from |cbs| and advances |cbs| over it. It + * returns one on success and zero on error. */ +OPENSSL_EXPORT int CBS_get_u16_length_prefixed(CBS *cbs, CBS *out); + +/* CBS_get_u24_length_prefixed sets |*out| to the contents of a 24-bit, + * big-endian, length-prefixed value from |cbs| and advances |cbs| over it. It + * returns one on success and zero on error. */ +OPENSSL_EXPORT int CBS_get_u24_length_prefixed(CBS *cbs, CBS *out); + + +/* Parsing ASN.1 */ + +#define CBS_ASN1_BOOLEAN 0x1 +#define CBS_ASN1_INTEGER 0x2 +#define CBS_ASN1_BITSTRING 0x3 +#define CBS_ASN1_OCTETSTRING 0x4 +#define CBS_ASN1_NULL 0x5 +#define CBS_ASN1_OBJECT 0x6 +#define CBS_ASN1_ENUMERATED 0xa +#define CBS_ASN1_UTF8STRING 0xc +#define CBS_ASN1_SEQUENCE (0x10 | CBS_ASN1_CONSTRUCTED) +#define CBS_ASN1_SET (0x11 | CBS_ASN1_CONSTRUCTED) +#define CBS_ASN1_NUMERICSTRING 0x12 +#define CBS_ASN1_PRINTABLESTRING 0x13 +#define CBS_ASN1_T16STRING 0x14 +#define CBS_ASN1_VIDEOTEXSTRING 0x15 +#define CBS_ASN1_IA5STRING 0x16 +#define CBS_ASN1_UTCTIME 0x17 +#define CBS_ASN1_GENERALIZEDTIME 0x18 +#define CBS_ASN1_GRAPHICSTRING 0x19 +#define CBS_ASN1_VISIBLESTRING 0x1a +#define CBS_ASN1_GENERALSTRING 0x1b +#define CBS_ASN1_UNIVERSALSTRING 0x1c +#define CBS_ASN1_BMPSTRING 0x1e + +#define CBS_ASN1_CONSTRUCTED 0x20 +#define CBS_ASN1_CONTEXT_SPECIFIC 0x80 + +/* CBS_get_asn1 sets |*out| to the contents of DER-encoded, ASN.1 element (not + * including tag and length bytes) and advances |cbs| over it. The ASN.1 + * element must match |tag_value|. It returns one on success and zero + * on error. + * + * Tag numbers greater than 30 are not supported (i.e. short form only). */ +OPENSSL_EXPORT int CBS_get_asn1(CBS *cbs, CBS *out, unsigned tag_value); + +/* CBS_get_asn1_element acts like |CBS_get_asn1| but |out| will include the + * ASN.1 header bytes too. */ +OPENSSL_EXPORT int CBS_get_asn1_element(CBS *cbs, CBS *out, unsigned tag_value); + +/* CBS_peek_asn1_tag looks ahead at the next ASN.1 tag and returns one + * if the next ASN.1 element on |cbs| would have tag |tag_value|. If + * |cbs| is empty or the tag does not match, it returns zero. Note: if + * it returns one, CBS_get_asn1 may still fail if the rest of the + * element is malformed. */ +OPENSSL_EXPORT int CBS_peek_asn1_tag(const CBS *cbs, unsigned tag_value); + +/* CBS_get_any_asn1_element sets |*out| to contain the next ASN.1 element from + * |*cbs| (including header bytes) and advances |*cbs|. It sets |*out_tag| to + * the tag number and |*out_header_len| to the length of the ASN.1 header. Each + * of |out|, |out_tag|, and |out_header_len| may be NULL to ignore the value. + * + * Tag numbers greater than 30 are not supported (i.e. short form only). */ +OPENSSL_EXPORT int CBS_get_any_asn1_element(CBS *cbs, CBS *out, + unsigned *out_tag, + size_t *out_header_len); + +/* CBS_get_any_ber_asn1_element acts the same as |CBS_get_any_asn1_element| but + * also allows indefinite-length elements to be returned. In that case, + * |*out_header_len| and |CBS_len(out)| will both be two as only the header is + * returned, otherwise it behaves the same as the previous function. */ +OPENSSL_EXPORT int CBS_get_any_ber_asn1_element(CBS *cbs, CBS *out, + unsigned *out_tag, + size_t *out_header_len); + +/* CBS_get_asn1_uint64 gets an ASN.1 INTEGER from |cbs| using |CBS_get_asn1| + * and sets |*out| to its value. It returns one on success and zero on error, + * where error includes the integer being negative, or too large to represent + * in 64 bits. */ +OPENSSL_EXPORT int CBS_get_asn1_uint64(CBS *cbs, uint64_t *out); + +/* CBS_get_optional_asn1 gets an optional explicitly-tagged element from |cbs| + * tagged with |tag| and sets |*out| to its contents. If present and if + * |out_present| is not NULL, it sets |*out_present| to one, otherwise zero. It + * returns one on success, whether or not the element was present, and zero on + * decode failure. */ +OPENSSL_EXPORT int CBS_get_optional_asn1(CBS *cbs, CBS *out, int *out_present, + unsigned tag); + +/* CBS_get_optional_asn1_octet_string gets an optional + * explicitly-tagged OCTET STRING from |cbs|. If present, it sets + * |*out| to the string and |*out_present| to one. Otherwise, it sets + * |*out| to empty and |*out_present| to zero. |out_present| may be + * NULL. It returns one on success, whether or not the element was + * present, and zero on decode failure. */ +OPENSSL_EXPORT int CBS_get_optional_asn1_octet_string(CBS *cbs, CBS *out, + int *out_present, + unsigned tag); + +/* CBS_get_optional_asn1_uint64 gets an optional explicitly-tagged + * INTEGER from |cbs|. If present, it sets |*out| to the + * value. Otherwise, it sets |*out| to |default_value|. It returns one + * on success, whether or not the element was present, and zero on + * decode failure. */ +OPENSSL_EXPORT int CBS_get_optional_asn1_uint64(CBS *cbs, uint64_t *out, + unsigned tag, + uint64_t default_value); + +/* CBS_get_optional_asn1_bool gets an optional, explicitly-tagged BOOLEAN from + * |cbs|. If present, it sets |*out| to either zero or one, based on the + * boolean. Otherwise, it sets |*out| to |default_value|. It returns one on + * success, whether or not the element was present, and zero on decode + * failure. */ +OPENSSL_EXPORT int CBS_get_optional_asn1_bool(CBS *cbs, int *out, unsigned tag, + int default_value); + + +/* CRYPTO ByteBuilder. + * + * |CBB| objects allow one to build length-prefixed serialisations. A |CBB| + * object is associated with a buffer and new buffers are created with + * |CBB_init|. Several |CBB| objects can point at the same buffer when a + * length-prefix is pending, however only a single |CBB| can be 'current' at + * any one time. For example, if one calls |CBB_add_u8_length_prefixed| then + * the new |CBB| points at the same buffer as the original. But if the original + * |CBB| is used then the length prefix is written out and the new |CBB| must + * not be used again. + * + * If one needs to force a length prefix to be written out because a |CBB| is + * going out of scope, use |CBB_flush|. */ + +struct cbb_buffer_st { + uint8_t *buf; + size_t len; /* The number of valid bytes. */ + size_t cap; /* The size of buf. */ + char can_resize; /* One iff |buf| is owned by this object. If not then |buf| + cannot be resized. */ +}; + +struct cbb_st { + struct cbb_buffer_st *base; + /* child points to a child CBB if a length-prefix is pending. */ + CBB *child; + /* offset is the number of bytes from the start of |base->buf| to this |CBB|'s + * pending length prefix. */ + size_t offset; + /* pending_len_len contains the number of bytes in this |CBB|'s pending + * length-prefix, or zero if no length-prefix is pending. */ + uint8_t pending_len_len; + char pending_is_asn1; + /* is_top_level is true iff this is a top-level |CBB| (as opposed to a child + * |CBB|). Top-level objects are valid arguments for |CBB_finish|. */ + char is_top_level; +}; + +/* CBB_zero sets an uninitialised |cbb| to the zero state. It must be + * initialised with |CBB_init| or |CBB_init_fixed| before use, but it is safe to + * call |CBB_cleanup| without a successful |CBB_init|. This may be used for more + * uniform cleanup of a |CBB|. */ +OPENSSL_EXPORT void CBB_zero(CBB *cbb); + +/* CBB_init initialises |cbb| with |initial_capacity|. Since a |CBB| grows as + * needed, the |initial_capacity| is just a hint. It returns one on success or + * zero on error. */ +OPENSSL_EXPORT int CBB_init(CBB *cbb, size_t initial_capacity); + +/* CBB_init_fixed initialises |cbb| to write to |len| bytes at |buf|. Since + * |buf| cannot grow, trying to write more than |len| bytes will cause CBB + * functions to fail. It returns one on success or zero on error. */ +OPENSSL_EXPORT int CBB_init_fixed(CBB *cbb, uint8_t *buf, size_t len); + +/* CBB_cleanup frees all resources owned by |cbb| and other |CBB| objects + * writing to the same buffer. This should be used in an error case where a + * serialisation is abandoned. + * + * This function can only be called on a "top level" |CBB|, i.e. one initialised + * with |CBB_init| or |CBB_init_fixed|, or a |CBB| set to the zero state with + * |CBB_zero|. */ +OPENSSL_EXPORT void CBB_cleanup(CBB *cbb); + +/* CBB_finish completes any pending length prefix and sets |*out_data| to a + * malloced buffer and |*out_len| to the length of that buffer. The caller + * takes ownership of the buffer and, unless the buffer was fixed with + * |CBB_init_fixed|, must call |OPENSSL_free| when done. + * + * It can only be called on a "top level" |CBB|, i.e. one initialised with + * |CBB_init| or |CBB_init_fixed|. It returns one on success and zero on + * error. */ +OPENSSL_EXPORT int CBB_finish(CBB *cbb, uint8_t **out_data, size_t *out_len); + +/* CBB_flush causes any pending length prefixes to be written out and any child + * |CBB| objects of |cbb| to be invalidated. It returns one on success or zero + * on error. */ +OPENSSL_EXPORT int CBB_flush(CBB *cbb); + +/* CBB_data returns a pointer to the bytes written to |cbb|. It does not flush + * |cbb|. The pointer is valid until the next operation to |cbb|. + * + * To avoid unfinalized length prefixes, it is a fatal error to call this on a + * CBB with any active children. */ +OPENSSL_EXPORT const uint8_t *CBB_data(const CBB *cbb); + +/* CBB_len returns the number of bytes written to |cbb|. It does not flush + * |cbb|. + * + * To avoid unfinalized length prefixes, it is a fatal error to call this on a + * CBB with any active children. */ +OPENSSL_EXPORT size_t CBB_len(const CBB *cbb); + +/* CBB_add_u8_length_prefixed sets |*out_contents| to a new child of |cbb|. The + * data written to |*out_contents| will be prefixed in |cbb| with an 8-bit + * length. It returns one on success or zero on error. */ +OPENSSL_EXPORT int CBB_add_u8_length_prefixed(CBB *cbb, CBB *out_contents); + +/* CBB_add_u16_length_prefixed sets |*out_contents| to a new child of |cbb|. + * The data written to |*out_contents| will be prefixed in |cbb| with a 16-bit, + * big-endian length. It returns one on success or zero on error. */ +OPENSSL_EXPORT int CBB_add_u16_length_prefixed(CBB *cbb, CBB *out_contents); + +/* CBB_add_u24_length_prefixed sets |*out_contents| to a new child of |cbb|. + * The data written to |*out_contents| will be prefixed in |cbb| with a 24-bit, + * big-endian length. It returns one on success or zero on error. */ +OPENSSL_EXPORT int CBB_add_u24_length_prefixed(CBB *cbb, CBB *out_contents); + +/* CBB_add_asn1 sets |*out_contents| to a |CBB| into which the contents of an + * ASN.1 object can be written. The |tag| argument will be used as the tag for + * the object. Passing in |tag| number 31 will return in an error since only + * single octet identifiers are supported. It returns one on success or zero + * on error. */ +OPENSSL_EXPORT int CBB_add_asn1(CBB *cbb, CBB *out_contents, uint8_t tag); + +/* CBB_add_bytes appends |len| bytes from |data| to |cbb|. It returns one on + * success and zero otherwise. */ +OPENSSL_EXPORT int CBB_add_bytes(CBB *cbb, const uint8_t *data, size_t len); + +/* CBB_add_space appends |len| bytes to |cbb| and sets |*out_data| to point to + * the beginning of that space. The caller must then write |len| bytes of + * actual contents to |*out_data|. It returns one on success and zero + * otherwise. */ +OPENSSL_EXPORT int CBB_add_space(CBB *cbb, uint8_t **out_data, size_t len); + +/* CBB_reserve ensures |cbb| has room for |len| additional bytes and sets + * |*out_data| to point to the beginning of that space. It returns one on + * success and zero otherwise. The caller may write up to |len| bytes to + * |*out_data| and call |CBB_did_write| to complete the write. |*out_data| is + * valid until the next operation on |cbb| or an ancestor |CBB|. */ +OPENSSL_EXPORT int CBB_reserve(CBB *cbb, uint8_t **out_data, size_t len); + +/* CBB_did_write advances |cbb| by |len| bytes, assuming the space has been + * written to by the caller. It returns one on success and zero on error. */ +OPENSSL_EXPORT int CBB_did_write(CBB *cbb, size_t len); + +/* CBB_add_u8 appends an 8-bit number from |value| to |cbb|. It returns one on + * success and zero otherwise. */ +OPENSSL_EXPORT int CBB_add_u8(CBB *cbb, uint8_t value); + +/* CBB_add_u16 appends a 16-bit, big-endian number from |value| to |cbb|. It + * returns one on success and zero otherwise. */ +OPENSSL_EXPORT int CBB_add_u16(CBB *cbb, uint16_t value); + +/* CBB_add_u24 appends a 24-bit, big-endian number from |value| to |cbb|. It + * returns one on success and zero otherwise. */ +OPENSSL_EXPORT int CBB_add_u24(CBB *cbb, uint32_t value); + +/* CBB_discard_child discards the current unflushed child of |cbb|. Neither the + * child's contents nor the length prefix will be included in the output. */ +OPENSSL_EXPORT void CBB_discard_child(CBB *cbb); + +/* CBB_add_asn1_uint64 writes an ASN.1 INTEGER into |cbb| using |CBB_add_asn1| + * and writes |value| in its contents. It returns one on success and zero on + * error. */ +OPENSSL_EXPORT int CBB_add_asn1_uint64(CBB *cbb, uint64_t value); + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_BYTESTRING_H */ diff --git a/external/boringssl/include/openssl/cast.h b/external/boringssl/include/openssl/cast.h new file mode 100644 index 0000000000..802172394e --- /dev/null +++ b/external/boringssl/include/openssl/cast.h @@ -0,0 +1,96 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_CAST_H +#define OPENSSL_HEADER_CAST_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +#define CAST_ENCRYPT 1 +#define CAST_DECRYPT 0 + +#define CAST_BLOCK 8 +#define CAST_KEY_LENGTH 16 + +typedef struct cast_key_st { + uint32_t data[32]; + int short_key; /* Use reduced rounds for short key */ +} CAST_KEY; + +OPENSSL_EXPORT void CAST_set_key(CAST_KEY *key, size_t len, + const uint8_t *data); +OPENSSL_EXPORT void CAST_ecb_encrypt(const uint8_t *in, uint8_t *out, + const CAST_KEY *key, int enc); +OPENSSL_EXPORT void CAST_encrypt(uint32_t *data, const CAST_KEY *key); +OPENSSL_EXPORT void CAST_decrypt(uint32_t *data, const CAST_KEY *key); +OPENSSL_EXPORT void CAST_cbc_encrypt(const uint8_t *in, uint8_t *out, + long length, const CAST_KEY *ks, + uint8_t *iv, int enc); + +OPENSSL_EXPORT void CAST_cfb64_encrypt(const uint8_t *in, uint8_t *out, + long length, const CAST_KEY *schedule, + uint8_t *ivec, int *num, int enc); + +#ifdef __cplusplus +} +#endif + +#endif /* OPENSSL_HEADER_CAST_H */ diff --git a/external/boringssl/include/openssl/chacha.h b/external/boringssl/include/openssl/chacha.h new file mode 100644 index 0000000000..3d035e69a8 --- /dev/null +++ b/external/boringssl/include/openssl/chacha.h @@ -0,0 +1,37 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_CHACHA_H +#define OPENSSL_HEADER_CHACHA_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +/* CRYPTO_chacha_20 encrypts |in_len| bytes from |in| with the given key and + * nonce and writes the result to |out|. If |in| and |out| alias, they must be + * equal. The initial block counter is specified by |counter|. */ +OPENSSL_EXPORT void CRYPTO_chacha_20(uint8_t *out, const uint8_t *in, + size_t in_len, const uint8_t key[32], + const uint8_t nonce[12], uint32_t counter); + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_CHACHA_H */ diff --git a/external/boringssl/include/openssl/cipher.h b/external/boringssl/include/openssl/cipher.h new file mode 100644 index 0000000000..53123086f6 --- /dev/null +++ b/external/boringssl/include/openssl/cipher.h @@ -0,0 +1,571 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_CIPHER_H +#define OPENSSL_HEADER_CIPHER_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* Ciphers. */ + + +/* Cipher primitives. + * + * The following functions return |EVP_CIPHER| objects that implement the named + * cipher algorithm. */ + +OPENSSL_EXPORT const EVP_CIPHER *EVP_rc4(void); + +OPENSSL_EXPORT const EVP_CIPHER *EVP_des_cbc(void); +OPENSSL_EXPORT const EVP_CIPHER *EVP_des_ecb(void); +OPENSSL_EXPORT const EVP_CIPHER *EVP_des_ede(void); +OPENSSL_EXPORT const EVP_CIPHER *EVP_des_ede_cbc(void); +OPENSSL_EXPORT const EVP_CIPHER *EVP_des_ede3_cbc(void); + +OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_128_ecb(void); +OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_128_cbc(void); +OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_128_ctr(void); +OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_128_ofb(void); + +OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_256_ecb(void); +OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_256_cbc(void); +OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_256_ctr(void); +OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_256_ofb(void); +OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_256_xts(void); + +/* EVP_enc_null returns a 'cipher' that passes plaintext through as + * ciphertext. */ +OPENSSL_EXPORT const EVP_CIPHER *EVP_enc_null(void); + +/* EVP_rc2_cbc returns a cipher that implements 128-bit RC2 in CBC mode. */ +OPENSSL_EXPORT const EVP_CIPHER *EVP_rc2_cbc(void); + +/* EVP_rc2_40_cbc returns a cipher that implements 40-bit RC2 in CBC mode. This + * is obviously very, very weak and is included only in order to read PKCS#12 + * files, which often encrypt the certificate chain using this cipher. It is + * deliberately not exported. */ +const EVP_CIPHER *EVP_rc2_40_cbc(void); + +/* EVP_get_cipherbynid returns the cipher corresponding to the given NID, or + * NULL if no such cipher is known. */ +OPENSSL_EXPORT const EVP_CIPHER *EVP_get_cipherbynid(int nid); + + +/* Cipher context allocation. + * + * An |EVP_CIPHER_CTX| represents the state of an encryption or decryption in + * progress. */ + +/* EVP_CIPHER_CTX_init initialises an, already allocated, |EVP_CIPHER_CTX|. */ +OPENSSL_EXPORT void EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *ctx); + +/* EVP_CIPHER_CTX_new allocates a fresh |EVP_CIPHER_CTX|, calls + * |EVP_CIPHER_CTX_init| and returns it, or NULL on allocation failure. */ +OPENSSL_EXPORT EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void); + +/* EVP_CIPHER_CTX_cleanup frees any memory referenced by |ctx|. It returns + * one. */ +OPENSSL_EXPORT int EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *ctx); + +/* EVP_CIPHER_CTX_free calls |EVP_CIPHER_CTX_cleanup| on |ctx| and then frees + * |ctx| itself. */ +OPENSSL_EXPORT void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx); + +/* EVP_CIPHER_CTX_copy sets |out| to be a duplicate of the current state of + * |in|. The |out| argument must have been previously initialised. */ +OPENSSL_EXPORT int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, + const EVP_CIPHER_CTX *in); + + +/* Cipher context configuration. */ + +/* EVP_CipherInit_ex configures |ctx| for a fresh encryption (or decryption, if + * |enc| is zero) operation using |cipher|. If |ctx| has been previously + * configured with a cipher then |cipher|, |key| and |iv| may be |NULL| and + * |enc| may be -1 to reuse the previous values. The operation will use |key| + * as the key and |iv| as the IV (if any). These should have the correct + * lengths given by |EVP_CIPHER_key_length| and |EVP_CIPHER_iv_length|. It + * returns one on success and zero on error. */ +OPENSSL_EXPORT int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, + const EVP_CIPHER *cipher, ENGINE *engine, + const uint8_t *key, const uint8_t *iv, + int enc); + +/* EVP_EncryptInit_ex calls |EVP_CipherInit_ex| with |enc| equal to one. */ +OPENSSL_EXPORT int EVP_EncryptInit_ex(EVP_CIPHER_CTX *ctx, + const EVP_CIPHER *cipher, ENGINE *impl, + const uint8_t *key, const uint8_t *iv); + +/* EVP_DecryptInit_ex calls |EVP_CipherInit_ex| with |enc| equal to zero. */ +OPENSSL_EXPORT int EVP_DecryptInit_ex(EVP_CIPHER_CTX *ctx, + const EVP_CIPHER *cipher, ENGINE *impl, + const uint8_t *key, const uint8_t *iv); + + +/* Cipher operations. */ + +/* EVP_EncryptUpdate encrypts |in_len| bytes from |in| to |out|. The number + * of output bytes may be up to |in_len| plus the block length minus one and + * |out| must have sufficient space. The number of bytes actually output is + * written to |*out_len|. It returns one on success and zero otherwise. */ +OPENSSL_EXPORT int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, uint8_t *out, + int *out_len, const uint8_t *in, + int in_len); + +/* EVP_EncryptFinal_ex writes at most a block of ciphertext to |out| and sets + * |*out_len| to the number of bytes written. If padding is enabled (the + * default) then standard padding is applied to create the final block. If + * padding is disabled (with |EVP_CIPHER_CTX_set_padding|) then any partial + * block remaining will cause an error. The function returns one on success and + * zero otherwise. */ +OPENSSL_EXPORT int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, uint8_t *out, + int *out_len); + +/* EVP_DecryptUpdate decrypts |in_len| bytes from |in| to |out|. The number of + * output bytes may be up to |in_len| plus the block length minus one and |out| + * must have sufficient space. The number of bytes actually output is written + * to |*out_len|. It returns one on success and zero otherwise. */ +OPENSSL_EXPORT int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, uint8_t *out, + int *out_len, const uint8_t *in, + int in_len); + +/* EVP_DecryptFinal_ex writes at most a block of ciphertext to |out| and sets + * |*out_len| to the number of bytes written. If padding is enabled (the + * default) then padding is removed from the final block. + * + * WARNING: it is unsafe to call this function with unauthenticted + * ciphertext if padding is enabled. */ +OPENSSL_EXPORT int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, + int *out_len); + +/* EVP_Cipher performs a one-shot encryption/decryption operation. No partial + * blocks are maintained between calls. However, any internal cipher state is + * still updated. For CBC-mode ciphers, the IV is updated to the final + * ciphertext block. For stream ciphers, the stream is advanced past the bytes + * used. It returns one on success and zero otherwise, unless |EVP_CIPHER_flags| + * has |EVP_CIPH_FLAG_CUSTOM_CIPHER| set. Then it returns the number of bytes + * written or -1 on error. + * + * WARNING: this differs from the usual return value convention when using + * |EVP_CIPH_FLAG_CUSTOM_CIPHER|. + * + * TODO(davidben): The normal ciphers currently never fail, even if, e.g., + * |in_len| is not a multiple of the block size for CBC-mode decryption. The + * input just gets rounded up while the output gets truncated. This should + * either be officially documented or fail. */ +OPENSSL_EXPORT int EVP_Cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, + const uint8_t *in, size_t in_len); + +/* EVP_CipherUpdate calls either |EVP_EncryptUpdate| or |EVP_DecryptUpdate| + * depending on how |ctx| has been setup. */ +OPENSSL_EXPORT int EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, uint8_t *out, + int *out_len, const uint8_t *in, + int in_len); + +/* EVP_CipherFinal_ex calls either |EVP_EncryptFinal_ex| or + * |EVP_DecryptFinal_ex| depending on how |ctx| has been setup. */ +OPENSSL_EXPORT int EVP_CipherFinal_ex(EVP_CIPHER_CTX *ctx, uint8_t *out, + int *out_len); + + +/* Cipher context accessors. */ + +/* EVP_CIPHER_CTX_cipher returns the |EVP_CIPHER| underlying |ctx|, or NULL if + * none has been set. */ +OPENSSL_EXPORT const EVP_CIPHER *EVP_CIPHER_CTX_cipher( + const EVP_CIPHER_CTX *ctx); + +/* EVP_CIPHER_CTX_nid returns a NID identifying the |EVP_CIPHER| underlying + * |ctx| (e.g. |NID_aes_128_gcm|). It will crash if no cipher has been + * configured. */ +OPENSSL_EXPORT int EVP_CIPHER_CTX_nid(const EVP_CIPHER_CTX *ctx); + +/* EVP_CIPHER_CTX_block_size returns the block size, in bytes, of the cipher + * underlying |ctx|, or one if the cipher is a stream cipher. It will crash if + * no cipher has been configured. */ +OPENSSL_EXPORT unsigned EVP_CIPHER_CTX_block_size(const EVP_CIPHER_CTX *ctx); + +/* EVP_CIPHER_CTX_key_length returns the key size, in bytes, of the cipher + * underlying |ctx| or zero if no cipher has been configured. */ +OPENSSL_EXPORT unsigned EVP_CIPHER_CTX_key_length(const EVP_CIPHER_CTX *ctx); + +/* EVP_CIPHER_CTX_iv_length returns the IV size, in bytes, of the cipher + * underlying |ctx|. It will crash if no cipher has been configured. */ +OPENSSL_EXPORT unsigned EVP_CIPHER_CTX_iv_length(const EVP_CIPHER_CTX *ctx); + +/* EVP_CIPHER_CTX_get_app_data returns the opaque, application data pointer for + * |ctx|, or NULL if none has been set. */ +OPENSSL_EXPORT void *EVP_CIPHER_CTX_get_app_data(const EVP_CIPHER_CTX *ctx); + +/* EVP_CIPHER_CTX_set_app_data sets the opaque, application data pointer for + * |ctx| to |data|. */ +OPENSSL_EXPORT void EVP_CIPHER_CTX_set_app_data(EVP_CIPHER_CTX *ctx, + void *data); + +/* EVP_CIPHER_CTX_flags returns a value which is the OR of zero or more + * |EVP_CIPH_*| flags. It will crash if no cipher has been configured. */ +OPENSSL_EXPORT uint32_t EVP_CIPHER_CTX_flags(const EVP_CIPHER_CTX *ctx); + +/* EVP_CIPHER_CTX_mode returns one of the |EVP_CIPH_*| cipher mode values + * enumerated below. It will crash if no cipher has been configured. */ +OPENSSL_EXPORT uint32_t EVP_CIPHER_CTX_mode(const EVP_CIPHER_CTX *ctx); + +/* EVP_CIPHER_CTX_ctrl is an |ioctl| like function. The |command| argument + * should be one of the |EVP_CTRL_*| values. The |arg| and |ptr| arguments are + * specific to the command in question. */ +OPENSSL_EXPORT int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int command, + int arg, void *ptr); + +/* EVP_CIPHER_CTX_set_padding sets whether padding is enabled for |ctx| and + * returns one. Pass a non-zero |pad| to enable padding (the default) or zero + * to disable. */ +OPENSSL_EXPORT int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *ctx, int pad); + +/* EVP_CIPHER_CTX_set_key_length sets the key length for |ctx|. This is only + * valid for ciphers that can take a variable length key. It returns one on + * success and zero on error. */ +OPENSSL_EXPORT int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *ctx, unsigned key_len); + + +/* Cipher accessors. */ + +/* EVP_CIPHER_nid returns a NID identifing |cipher|. (For example, + * |NID_aes_128_gcm|.) */ +OPENSSL_EXPORT int EVP_CIPHER_nid(const EVP_CIPHER *cipher); + +/* EVP_CIPHER_block_size returns the block size, in bytes, for |cipher|, or one + * if |cipher| is a stream cipher. */ +OPENSSL_EXPORT unsigned EVP_CIPHER_block_size(const EVP_CIPHER *cipher); + +/* EVP_CIPHER_key_length returns the key size, in bytes, for |cipher|. If + * |cipher| can take a variable key length then this function returns the + * default key length and |EVP_CIPHER_flags| will return a value with + * |EVP_CIPH_VARIABLE_LENGTH| set. */ +OPENSSL_EXPORT unsigned EVP_CIPHER_key_length(const EVP_CIPHER *cipher); + +/* EVP_CIPHER_iv_length returns the IV size, in bytes, of |cipher|, or zero if + * |cipher| doesn't take an IV. */ +OPENSSL_EXPORT unsigned EVP_CIPHER_iv_length(const EVP_CIPHER *cipher); + +/* EVP_CIPHER_flags returns a value which is the OR of zero or more + * |EVP_CIPH_*| flags. */ +OPENSSL_EXPORT uint32_t EVP_CIPHER_flags(const EVP_CIPHER *cipher); + +/* EVP_CIPHER_mode returns one of the cipher mode values enumerated below. */ +OPENSSL_EXPORT uint32_t EVP_CIPHER_mode(const EVP_CIPHER *cipher); + + +/* Key derivation. */ + +/* EVP_BytesToKey generates a key and IV for the cipher |type| by iterating + * |md| |count| times using |data| and |salt|. On entry, the |key| and |iv| + * buffers must have enough space to hold a key and IV for |type|. It returns + * the length of the key on success or zero on error. */ +OPENSSL_EXPORT int EVP_BytesToKey(const EVP_CIPHER *type, const EVP_MD *md, + const uint8_t *salt, const uint8_t *data, + size_t data_len, unsigned count, uint8_t *key, + uint8_t *iv); + + +/* Cipher modes (for |EVP_CIPHER_mode|). */ + +#define EVP_CIPH_STREAM_CIPHER 0x0 +#define EVP_CIPH_ECB_MODE 0x1 +#define EVP_CIPH_CBC_MODE 0x2 +#define EVP_CIPH_CFB_MODE 0x3 +#define EVP_CIPH_OFB_MODE 0x4 +#define EVP_CIPH_CTR_MODE 0x5 +#define EVP_CIPH_GCM_MODE 0x6 +#define EVP_CIPH_XTS_MODE 0x7 + + +/* Cipher flags (for |EVP_CIPHER_flags|). */ + +/* EVP_CIPH_VARIABLE_LENGTH indicates that the cipher takes a variable length + * key. */ +#define EVP_CIPH_VARIABLE_LENGTH 0x40 + +/* EVP_CIPH_ALWAYS_CALL_INIT indicates that the |init| function for the cipher + * should always be called when initialising a new operation, even if the key + * is NULL to indicate that the same key is being used. */ +#define EVP_CIPH_ALWAYS_CALL_INIT 0x80 + +/* EVP_CIPH_CUSTOM_IV indicates that the cipher manages the IV itself rather + * than keeping it in the |iv| member of |EVP_CIPHER_CTX|. */ +#define EVP_CIPH_CUSTOM_IV 0x100 + +/* EVP_CIPH_CTRL_INIT indicates that EVP_CTRL_INIT should be used when + * initialising an |EVP_CIPHER_CTX|. */ +#define EVP_CIPH_CTRL_INIT 0x200 + +/* EVP_CIPH_FLAG_CUSTOM_CIPHER indicates that the cipher manages blocking + * itself. This causes EVP_(En|De)crypt_ex to be simple wrapper functions. */ +#define EVP_CIPH_FLAG_CUSTOM_CIPHER 0x400 + +/* EVP_CIPH_FLAG_AEAD_CIPHER specifies that the cipher is an AEAD. This is an + * older version of the proper AEAD interface. See aead.h for the current + * one. */ +#define EVP_CIPH_FLAG_AEAD_CIPHER 0x800 + +/* EVP_CIPH_CUSTOM_COPY indicates that the |ctrl| callback should be called + * with |EVP_CTRL_COPY| at the end of normal |EVP_CIPHER_CTX_copy| + * processing. */ +#define EVP_CIPH_CUSTOM_COPY 0x1000 + + +/* Deprecated functions */ + +/* EVP_CipherInit acts like EVP_CipherInit_ex except that |EVP_CIPHER_CTX_init| + * is called on |cipher| first, if |cipher| is not NULL. */ +OPENSSL_EXPORT int EVP_CipherInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, + const uint8_t *key, const uint8_t *iv, + int enc); + +/* EVP_EncryptInit calls |EVP_CipherInit| with |enc| equal to one. */ +OPENSSL_EXPORT int EVP_EncryptInit(EVP_CIPHER_CTX *ctx, + const EVP_CIPHER *cipher, const uint8_t *key, + const uint8_t *iv); + +/* EVP_DecryptInit calls |EVP_CipherInit| with |enc| equal to zero. */ +OPENSSL_EXPORT int EVP_DecryptInit(EVP_CIPHER_CTX *ctx, + const EVP_CIPHER *cipher, const uint8_t *key, + const uint8_t *iv); + +/* EVP_add_cipher_alias does nothing and returns one. */ +OPENSSL_EXPORT int EVP_add_cipher_alias(const char *a, const char *b); + +/* EVP_get_cipherbyname returns an |EVP_CIPHER| given a human readable name in + * |name|, or NULL if the name is unknown. */ +OPENSSL_EXPORT const EVP_CIPHER *EVP_get_cipherbyname(const char *name); + +/* These AEADs are deprecated AES-GCM implementations that set + * |EVP_CIPH_FLAG_CUSTOM_CIPHER|. Use |EVP_aead_aes_128_gcm| and + * |EVP_aead_aes_256_gcm| instead. */ +OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_128_gcm(void); +OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_256_gcm(void); + +/* These are deprecated, 192-bit version of AES. */ +OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_192_ecb(void); +OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_192_cbc(void); +OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_192_ctr(void); +OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_192_gcm(void); + + +/* Private functions. */ + +/* EVP_CIPH_NO_PADDING disables padding in block ciphers. */ +#define EVP_CIPH_NO_PADDING 0x800 + +/* EVP_CIPHER_CTX_ctrl commands. */ +#define EVP_CTRL_INIT 0x0 +#define EVP_CTRL_SET_KEY_LENGTH 0x1 +#define EVP_CTRL_GET_RC2_KEY_BITS 0x2 +#define EVP_CTRL_SET_RC2_KEY_BITS 0x3 +#define EVP_CTRL_GET_RC5_ROUNDS 0x4 +#define EVP_CTRL_SET_RC5_ROUNDS 0x5 +#define EVP_CTRL_RAND_KEY 0x6 +#define EVP_CTRL_PBE_PRF_NID 0x7 +#define EVP_CTRL_COPY 0x8 +#define EVP_CTRL_GCM_SET_IVLEN 0x9 +#define EVP_CTRL_GCM_GET_TAG 0x10 +#define EVP_CTRL_GCM_SET_TAG 0x11 +#define EVP_CTRL_GCM_SET_IV_FIXED 0x12 +#define EVP_CTRL_GCM_IV_GEN 0x13 +#define EVP_CTRL_AEAD_SET_MAC_KEY 0x17 +/* Set the GCM invocation field, decrypt only */ +#define EVP_CTRL_GCM_SET_IV_INV 0x18 + +/* GCM TLS constants */ +/* Length of fixed part of IV derived from PRF */ +#define EVP_GCM_TLS_FIXED_IV_LEN 4 +/* Length of explicit part of IV part of TLS records */ +#define EVP_GCM_TLS_EXPLICIT_IV_LEN 8 +/* Length of tag for TLS */ +#define EVP_GCM_TLS_TAG_LEN 16 + +#define EVP_MAX_KEY_LENGTH 64 +#define EVP_MAX_IV_LENGTH 16 +#define EVP_MAX_BLOCK_LENGTH 32 + +struct evp_cipher_ctx_st { + /* cipher contains the underlying cipher for this context. */ + const EVP_CIPHER *cipher; + + /* app_data is a pointer to opaque, user data. */ + void *app_data; /* application stuff */ + + /* cipher_data points to the |cipher| specific state. */ + void *cipher_data; + + /* key_len contains the length of the key, which may differ from + * |cipher->key_len| if the cipher can take a variable key length. */ + unsigned key_len; + + /* encrypt is one if encrypting and zero if decrypting. */ + int encrypt; + + /* flags contains the OR of zero or more |EVP_CIPH_*| flags, above. */ + uint32_t flags; + + /* oiv contains the original IV value. */ + uint8_t oiv[EVP_MAX_IV_LENGTH]; + + /* iv contains the current IV value, which may have been updated. */ + uint8_t iv[EVP_MAX_IV_LENGTH]; + + /* buf contains a partial block which is used by, for example, CTR mode to + * store unused keystream bytes. */ + uint8_t buf[EVP_MAX_BLOCK_LENGTH]; + + /* buf_len contains the number of bytes of a partial block contained in + * |buf|. */ + int buf_len; + + /* num contains the number of bytes of |iv| which are valid for modes that + * manage partial blocks themselves. */ + unsigned num; + + /* final_used is non-zero if the |final| buffer contains plaintext. */ + int final_used; + + /* block_mask contains |cipher->block_size| minus one. (The block size + * assumed to be a power of two.) */ + int block_mask; + + uint8_t final[EVP_MAX_BLOCK_LENGTH]; /* possible final block */ +} /* EVP_CIPHER_CTX */; + +typedef struct evp_cipher_info_st { + const EVP_CIPHER *cipher; + unsigned char iv[EVP_MAX_IV_LENGTH]; +} EVP_CIPHER_INFO; + +struct evp_cipher_st { + /* type contains a NID identifing the cipher. (e.g. NID_aes_128_gcm.) */ + int nid; + + /* block_size contains the block size, in bytes, of the cipher, or 1 for a + * stream cipher. */ + unsigned block_size; + + /* key_len contains the key size, in bytes, for the cipher. If the cipher + * takes a variable key size then this contains the default size. */ + unsigned key_len; + + /* iv_len contains the IV size, in bytes, or zero if inapplicable. */ + unsigned iv_len; + + /* ctx_size contains the size, in bytes, of the per-key context for this + * cipher. */ + unsigned ctx_size; + + /* flags contains the OR of a number of flags. See |EVP_CIPH_*|. */ + uint32_t flags; + + /* app_data is a pointer to opaque, user data. */ + void *app_data; + + int (*init)(EVP_CIPHER_CTX *ctx, const uint8_t *key, const uint8_t *iv, + int enc); + + int (*cipher)(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in, + size_t inl); + + /* cleanup, if non-NULL, releases memory associated with the context. It is + * called if |EVP_CTRL_INIT| succeeds. Note that |init| may not have been + * called at this point. */ + void (*cleanup)(EVP_CIPHER_CTX *); + + int (*ctrl)(EVP_CIPHER_CTX *, int type, int arg, void *ptr); +}; + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#define CIPHER_R_AES_KEY_SETUP_FAILED 100 +#define CIPHER_R_BAD_DECRYPT 101 +#define CIPHER_R_BAD_KEY_LENGTH 102 +#define CIPHER_R_BUFFER_TOO_SMALL 103 +#define CIPHER_R_CTRL_NOT_IMPLEMENTED 104 +#define CIPHER_R_CTRL_OPERATION_NOT_IMPLEMENTED 105 +#define CIPHER_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH 106 +#define CIPHER_R_INITIALIZATION_ERROR 107 +#define CIPHER_R_INPUT_NOT_INITIALIZED 108 +#define CIPHER_R_INVALID_AD_SIZE 109 +#define CIPHER_R_INVALID_KEY_LENGTH 110 +#define CIPHER_R_INVALID_NONCE_SIZE 111 +#define CIPHER_R_INVALID_OPERATION 112 +#define CIPHER_R_IV_TOO_LARGE 113 +#define CIPHER_R_NO_CIPHER_SET 114 +#define CIPHER_R_OUTPUT_ALIASES_INPUT 115 +#define CIPHER_R_TAG_TOO_LARGE 116 +#define CIPHER_R_TOO_LARGE 117 +#define CIPHER_R_UNSUPPORTED_AD_SIZE 118 +#define CIPHER_R_UNSUPPORTED_INPUT_SIZE 119 +#define CIPHER_R_UNSUPPORTED_KEY_SIZE 120 +#define CIPHER_R_UNSUPPORTED_NONCE_SIZE 121 +#define CIPHER_R_UNSUPPORTED_TAG_SIZE 122 +#define CIPHER_R_WRONG_FINAL_BLOCK_LENGTH 123 +#define CIPHER_R_NO_DIRECTION_SET 124 + +#endif /* OPENSSL_HEADER_CIPHER_H */ diff --git a/external/boringssl/include/openssl/cmac.h b/external/boringssl/include/openssl/cmac.h new file mode 100644 index 0000000000..0bb44b9526 --- /dev/null +++ b/external/boringssl/include/openssl/cmac.h @@ -0,0 +1,76 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_CMAC_H +#define OPENSSL_HEADER_CMAC_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* CMAC. + * + * CMAC is a MAC based on AES-CBC and defined in + * https://tools.ietf.org/html/rfc4493#section-2.3. */ + + +/* One-shot functions. */ + +/* AES_CMAC calculates the 16-byte, CMAC authenticator of |in_len| bytes of + * |in| and writes it to |out|. The |key_len| may be 16 or 32 bytes to select + * between AES-128 and AES-256. It returns one on success or zero on error. */ +OPENSSL_EXPORT int AES_CMAC(uint8_t out[16], const uint8_t *key, size_t key_len, + const uint8_t *in, size_t in_len); + + +/* Incremental interface. */ + +/* CMAC_CTX_new allocates a fresh |CMAC_CTX| and returns it, or NULL on + * error. */ +OPENSSL_EXPORT CMAC_CTX *CMAC_CTX_new(void); + +/* CMAC_CTX_free frees a |CMAC_CTX|. */ +OPENSSL_EXPORT void CMAC_CTX_free(CMAC_CTX *ctx); + +/* CMAC_Init configures |ctx| to use the given |key| and |cipher|. The CMAC RFC + * only specifies the use of AES-128 thus |key_len| should be 16 and |cipher| + * should be |EVP_aes_128_cbc()|. However, this implementation also supports + * AES-256 by setting |key_len| to 32 and |cipher| to |EVP_aes_256_cbc()|. The + * |engine| argument is ignored. + * + * It returns one on success or zero on error. */ +OPENSSL_EXPORT int CMAC_Init(CMAC_CTX *ctx, const void *key, size_t key_len, + const EVP_CIPHER *cipher, ENGINE *engine); + + +/* CMAC_Reset resets |ctx| so that a fresh message can be authenticated. */ +OPENSSL_EXPORT int CMAC_Reset(CMAC_CTX *ctx); + +/* CMAC_Update processes |in_len| bytes of message from |in|. It returns one on + * success or zero on error. */ +OPENSSL_EXPORT int CMAC_Update(CMAC_CTX *ctx, const uint8_t *in, size_t in_len); + +/* CMAC_Final sets |*out_len| to 16 and, if |out| is not NULL, writes 16 bytes + * of authenticator to it. It returns one on success or zero on error. */ +OPENSSL_EXPORT int CMAC_Final(CMAC_CTX *ctx, uint8_t *out, size_t *out_len); + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_CMAC_H */ diff --git a/external/boringssl/include/openssl/conf.h b/external/boringssl/include/openssl/conf.h new file mode 100644 index 0000000000..2aa3b79e3a --- /dev/null +++ b/external/boringssl/include/openssl/conf.h @@ -0,0 +1,170 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_CONF_H +#define OPENSSL_HEADER_CONF_H + +#include + +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* Config files look like: + * + * # Comment + * + * # This key is in the default section. + * key=value + * + * [section_name] + * key2=value2 + * + * Config files are representated by a |CONF|. */ + +struct conf_value_st { + char *section; + char *name; + char *value; +}; + +struct conf_st { + LHASH_OF(CONF_VALUE) *data; +}; + + +/* NCONF_new returns a fresh, empty |CONF|, or NULL on error. The |method| + * argument must be NULL. */ +OPENSSL_EXPORT CONF *NCONF_new(void *method); + +/* NCONF_free frees all the data owned by |conf| and then |conf| itself. */ +OPENSSL_EXPORT void NCONF_free(CONF *conf); + +/* NCONF_load parses the file named |filename| and adds the values found to + * |conf|. It returns one on success and zero on error. In the event of an + * error, if |out_error_line| is not NULL, |*out_error_line| is set to the + * number of the line that contained the error. */ +int NCONF_load(CONF *conf, const char *filename, long *out_error_line); + +/* NCONF_load_bio acts like |NCONF_load| but reads from |bio| rather than from + * a named file. */ +int NCONF_load_bio(CONF *conf, BIO *bio, long *out_error_line); + +/* NCONF_get_section returns a stack of values for a given section in |conf|. + * If |section| is NULL, the default section is returned. It returns NULL on + * error. */ +STACK_OF(CONF_VALUE) *NCONF_get_section(const CONF *conf, const char *section); + +/* NCONF_get_string returns the value of the key |name|, in section |section|. + * The |section| argument may be NULL to indicate the default section. It + * returns the value or NULL on error. */ +const char *NCONF_get_string(const CONF *conf, const char *section, + const char *name); + + +/* Utility functions */ + +/* CONF_parse_list takes a list separated by 'sep' and calls |list_cb| giving + * the start and length of each member, optionally stripping leading and + * trailing whitespace. This can be used to parse comma separated lists for + * example. If |list_cb| returns <= 0, then the iteration is halted and that + * value is returned immediately. Otherwise it returns one. Note that |list_cb| + * may be called on an empty member. */ +int CONF_parse_list(const char *list, char sep, int remove_whitespace, + int (*list_cb)(const char *elem, int len, void *usr), + void *arg); + + +/* Deprecated functions */ + +/* These defines do nothing but are provided to make old code easier to + * compile. */ +#define CONF_MFLAGS_DEFAULT_SECTION 0 +#define CONF_MFLAGS_IGNORE_MISSING_FILE 0 + +typedef struct conf_must_be_null_st CONF_MUST_BE_NULL; + +/* CONF_modules_load_file returns one. |filename| was originally a string, with + * NULL indicating the default. BoringSSL does not support configuration files, + * so this stub emulates the "default" no-op file but intentionally breaks + * compilation of consumers actively attempting to use this subsystem. */ +OPENSSL_EXPORT int CONF_modules_load_file(CONF_MUST_BE_NULL *filename, + const char *appname, + unsigned long flags); + +/* CONF_modules_free does nothing. */ +OPENSSL_EXPORT void CONF_modules_free(void); + +/* OPENSSL_config does nothing. */ +OPENSSL_EXPORT void OPENSSL_config(CONF_MUST_BE_NULL *config_name); + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#define CONF_R_LIST_CANNOT_BE_NULL 100 +#define CONF_R_MISSING_CLOSE_SQUARE_BRACKET 101 +#define CONF_R_MISSING_EQUAL_SIGN 102 +#define CONF_R_NO_CLOSE_BRACE 103 +#define CONF_R_UNABLE_TO_CREATE_NEW_SECTION 104 +#define CONF_R_VARIABLE_HAS_NO_VALUE 105 + +#endif /* OPENSSL_HEADER_THREAD_H */ diff --git a/external/boringssl/include/openssl/cpu.h b/external/boringssl/include/openssl/cpu.h new file mode 100644 index 0000000000..55be4c1faf --- /dev/null +++ b/external/boringssl/include/openssl/cpu.h @@ -0,0 +1,173 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#ifndef OPENSSL_HEADER_CPU_H +#define OPENSSL_HEADER_CPU_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* Runtime CPU feature support */ + + +#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64) +/* OPENSSL_ia32cap_P contains the Intel CPUID bits when running on an x86 or + * x86-64 system. + * + * Index 0: + * EDX for CPUID where EAX = 1 + * Bit 20 is always zero + * Bit 28 is adjusted to reflect whether the data cache is shared between + * multiple logical cores + * Bit 30 is used to indicate an Intel CPU + * Index 1: + * ECX for CPUID where EAX = 1 + * Bit 11 is used to indicate AMD XOP support, not SDBG + * Index 2: + * EBX for CPUID where EAX = 7 + * Index 3 is set to zero. + * + * Note: the CPUID bits are pre-adjusted for the OSXSAVE bit and the YMM and XMM + * bits in XCR0, so it is not necessary to check those. */ +extern uint32_t OPENSSL_ia32cap_P[4]; +#endif + +#if defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64) + +#if defined(OPENSSL_APPLE) +/* iOS builds use the static ARM configuration. */ +#define OPENSSL_STATIC_ARMCAP +#endif + +#if !defined(OPENSSL_STATIC_ARMCAP) + +/* CRYPTO_is_NEON_capable_at_runtime returns true if the current CPU has a NEON + * unit. Note that |OPENSSL_armcap_P| also exists and contains the same + * information in a form that's easier for assembly to use. */ +OPENSSL_EXPORT char CRYPTO_is_NEON_capable_at_runtime(void); + +/* CRYPTO_is_NEON_capable returns true if the current CPU has a NEON unit. If + * this is known statically then it returns one immediately. */ +static inline int CRYPTO_is_NEON_capable(void) { + /* Only statically skip the runtime lookup on aarch64. On arm, one CPU is + * known to have a broken NEON unit which is known to fail with on some + * hand-written NEON assembly. For now, continue to apply the workaround even + * when the compiler is instructed to freely emit NEON code. See + * https://crbug.com/341598 and https://crbug.com/606629. */ +#if defined(__ARM_NEON__) && !defined(OPENSSL_ARM) + return 1; +#else + return CRYPTO_is_NEON_capable_at_runtime(); +#endif +} + +#if defined(OPENSSL_ARM) +/* CRYPTO_has_broken_NEON returns one if the current CPU is known to have a + * broken NEON unit. See https://crbug.com/341598. */ +OPENSSL_EXPORT int CRYPTO_has_broken_NEON(void); +#endif + +/* CRYPTO_is_ARMv8_AES_capable returns true if the current CPU supports the + * ARMv8 AES instruction. */ +int CRYPTO_is_ARMv8_AES_capable(void); + +/* CRYPTO_is_ARMv8_PMULL_capable returns true if the current CPU supports the + * ARMv8 PMULL instruction. */ +int CRYPTO_is_ARMv8_PMULL_capable(void); + +#else + +static inline int CRYPTO_is_NEON_capable(void) { +#if defined(OPENSSL_STATIC_ARMCAP_NEON) || defined(__ARM_NEON__) + return 1; +#else + return 0; +#endif +} + +static inline int CRYPTO_is_ARMv8_AES_capable(void) { +#if defined(OPENSSL_STATIC_ARMCAP_AES) + return 1; +#else + return 0; +#endif +} + +static inline int CRYPTO_is_ARMv8_PMULL_capable(void) { +#if defined(OPENSSL_STATIC_ARMCAP_PMULL) + return 1; +#else + return 0; +#endif +} + +#endif /* OPENSSL_STATIC_ARMCAP */ +#endif /* OPENSSL_ARM || OPENSSL_AARCH64 */ + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_CPU_H */ diff --git a/external/boringssl/include/openssl/crypto.h b/external/boringssl/include/openssl/crypto.h new file mode 100644 index 0000000000..80d7196956 --- /dev/null +++ b/external/boringssl/include/openssl/crypto.h @@ -0,0 +1,91 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_CRYPTO_H +#define OPENSSL_HEADER_CRYPTO_H + +#include + +/* Upstream OpenSSL defines |OPENSSL_malloc|, etc., in crypto.h rather than + * mem.h. */ +#include + +/* Upstream OpenSSL defines |CRYPTO_LOCK|, etc., in crypto.h rather than + * thread.h. */ +#include + + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* crypto.h contains functions for initializing the crypto library. */ + + +/* CRYPTO_library_init initializes the crypto library. It must be called if the + * library is built with BORINGSSL_NO_STATIC_INITIALIZER. Otherwise, it does + * nothing and a static initializer is used instead. It is safe to call this + * function multiple times and concurrently from multiple threads. + * + * On some ARM configurations, this function may require filesystem access and + * should be called before entering a sandbox. */ +OPENSSL_EXPORT void CRYPTO_library_init(void); + +/* CRYPTO_is_confidential_build returns one if the linked version of BoringSSL + * has been built with the BORINGSSL_CONFIDENTIAL define and zero otherwise. + * + * This is used by some consumers to identify whether they are using an + * internal version of BoringSSL. */ +OPENSSL_EXPORT int CRYPTO_is_confidential_build(void); + +/* CRYPTO_has_asm returns one unless BoringSSL was built with OPENSSL_NO_ASM, + * in which case it returns zero. */ +OPENSSL_EXPORT int CRYPTO_has_asm(void); + + +/* Deprecated functions. */ + +/* OPENSSL_VERSION_TEXT contains a string the identifies the version of + * “OpenSSLâ€. node.js requires a version number in this text. */ +#define OPENSSL_VERSION_TEXT "OpenSSL 1.0.2 (compatible; BoringSSL)" + +#define SSLEAY_VERSION 0 + +/* SSLeay_version is a compatibility function that returns the string + * "BoringSSL". */ +OPENSSL_EXPORT const char *SSLeay_version(int unused); + +/* SSLeay is a compatibility function that returns OPENSSL_VERSION_NUMBER from + * base.h. */ +OPENSSL_EXPORT unsigned long SSLeay(void); + +/* CRYPTO_malloc_init returns one. */ +OPENSSL_EXPORT int CRYPTO_malloc_init(void); + +/* ENGINE_load_builtin_engines does nothing. */ +OPENSSL_EXPORT void ENGINE_load_builtin_engines(void); + +/* OPENSSL_load_builtin_modules does nothing. */ +OPENSSL_EXPORT void OPENSSL_load_builtin_modules(void); + +/* FIPS_mode returns zero. */ +OPENSSL_EXPORT int FIPS_mode(void); + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_CRYPTO_H */ diff --git a/external/boringssl/include/openssl/curve25519.h b/external/boringssl/include/openssl/curve25519.h new file mode 100644 index 0000000000..a9441cd498 --- /dev/null +++ b/external/boringssl/include/openssl/curve25519.h @@ -0,0 +1,172 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_CURVE25519_H +#define OPENSSL_HEADER_CURVE25519_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* Curve25519. + * + * Curve25519 is an elliptic curve. See https://tools.ietf.org/html/rfc7748. */ + + +/* X25519. + * + * X25519 is the Diffie-Hellman primitive built from curve25519. It is + * sometimes referred to as “curve25519â€, but “X25519†is a more precise name. + * See http://cr.yp.to/ecdh.html and https://tools.ietf.org/html/rfc7748. */ + +/* X25519_keypair sets |out_public_value| and |out_private_key| to a freshly + * generated, public–private key pair. */ +OPENSSL_EXPORT void X25519_keypair(uint8_t out_public_value[32], + uint8_t out_private_key[32]); + +/* X25519 writes a shared key to |out_shared_key| that is calculated from the + * given private key and the peer's public value. It returns one on success and + * zero on error. + * + * Don't use the shared key directly, rather use a KDF and also include the two + * public values as inputs. */ +OPENSSL_EXPORT int X25519(uint8_t out_shared_key[32], + const uint8_t private_key[32], + const uint8_t peers_public_value[32]); + +/* X25519_public_from_private calculates a Diffie-Hellman public value from the + * given private key and writes it to |out_public_value|. */ +OPENSSL_EXPORT void X25519_public_from_private(uint8_t out_public_value[32], + const uint8_t private_key[32]); + + +/* Ed25519. + * + * Ed25519 is a signature scheme using a twisted-Edwards curve that is + * birationally equivalent to curve25519. */ + +#define ED25519_PRIVATE_KEY_LEN 64 +#define ED25519_PUBLIC_KEY_LEN 32 +#define ED25519_SIGNATURE_LEN 64 + +/* ED25519_keypair sets |out_public_key| and |out_private_key| to a freshly + * generated, public–private key pair. */ +OPENSSL_EXPORT void ED25519_keypair(uint8_t out_public_key[32], + uint8_t out_private_key[64]); + +/* ED25519_sign sets |out_sig| to be a signature of |message_len| bytes from + * |message| using |private_key|. It returns one on success or zero on + * error. */ +OPENSSL_EXPORT int ED25519_sign(uint8_t out_sig[64], const uint8_t *message, + size_t message_len, + const uint8_t private_key[64]); + +/* ED25519_verify returns one iff |signature| is a valid signature, by + * |public_key| of |message_len| bytes from |message|. It returns zero + * otherwise. */ +OPENSSL_EXPORT int ED25519_verify(const uint8_t *message, size_t message_len, + const uint8_t signature[64], + const uint8_t public_key[32]); + + +/* SPAKE2. + * + * SPAKE2 is a password-authenticated key-exchange. It allows two parties, + * who share a low-entropy secret (i.e. password), to agree on a shared key. + * An attacker can only make one guess of the password per execution of the + * protocol. + * + * See https://tools.ietf.org/html/draft-irtf-cfrg-spake2-02. */ + +/* spake2_role_t enumerates the different “roles†in SPAKE2. The protocol + * requires that the symmetry of the two parties be broken so one participant + * must be “Alice†and the other be “Bobâ€. */ +enum spake2_role_t { + spake2_role_alice, + spake2_role_bob, +}; + +/* SPAKE2_CTX_new creates a new |SPAKE2_CTX| (which can only be used for a + * single execution of the protocol). SPAKE2 requires the symmetry of the two + * parties to be broken which is indicated via |my_role| – each party must pass + * a different value for this argument. + * + * The |my_name| and |their_name| arguments allow optional, opaque names to be + * bound into the protocol. For example MAC addresses, hostnames, usernames + * etc. These values are not exposed and can avoid context-confusion attacks + * when a password is shared between several devices. */ +OPENSSL_EXPORT SPAKE2_CTX *SPAKE2_CTX_new( + enum spake2_role_t my_role, + const uint8_t *my_name, size_t my_name_len, + const uint8_t *their_name, size_t their_name_len); + +/* SPAKE2_CTX_free frees |ctx| and all the resources that it has allocated. */ +OPENSSL_EXPORT void SPAKE2_CTX_free(SPAKE2_CTX *ctx); + +/* SPAKE2_MAX_MSG_SIZE is the maximum size of a SPAKE2 message. */ +#define SPAKE2_MAX_MSG_SIZE 32 + +/* SPAKE2_generate_msg generates a SPAKE2 message given |password|, writes + * it to |out| and sets |*out_len| to the number of bytes written. + * + * At most |max_out_len| bytes are written to |out| and, in order to ensure + * success, |max_out_len| should be at least |SPAKE2_MAX_MSG_SIZE| bytes. + * + * This function can only be called once for a given |SPAKE2_CTX|. + * + * It returns one on success and zero on error. */ +OPENSSL_EXPORT int SPAKE2_generate_msg(SPAKE2_CTX *ctx, uint8_t *out, + size_t *out_len, size_t max_out_len, + const uint8_t *password, + size_t password_len); + +/* SPAKE2_MAX_KEY_SIZE is the maximum amount of key material that SPAKE2 will + * produce. */ +#define SPAKE2_MAX_KEY_SIZE 64 + +/* SPAKE2_process_msg completes the SPAKE2 exchange given the peer's message in + * |their_msg|, writes at most |max_out_key_len| bytes to |out_key| and sets + * |*out_key_len| to the number of bytes written. + * + * The resulting keying material is suitable for: + * a) Using directly in a key-confirmation step: i.e. each side could + * transmit a hash of their role, a channel-binding value and the key + * material to prove to the other side that they know the shared key. + * b) Using as input keying material to HKDF to generate a variety of subkeys + * for encryption etc. + * + * If |max_out_key_key| is smaller than the amount of key material generated + * then the key is silently truncated. If you want to ensure that no truncation + * occurs then |max_out_key| should be at least |SPAKE2_MAX_KEY_SIZE|. + * + * You must call |SPAKE2_generate_msg| on a given |SPAKE2_CTX| before calling + * this function. On successful return, |ctx| is complete and calling + * |SPAKE2_CTX_free| is the only acceptable operation on it. + * + * Returns one on success or zero on error. */ +OPENSSL_EXPORT int SPAKE2_process_msg(SPAKE2_CTX *ctx, uint8_t *out_key, + size_t *out_key_len, + size_t max_out_key_len, + const uint8_t *their_msg, + size_t their_msg_len); + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_CURVE25519_H */ diff --git a/external/boringssl/include/openssl/des.h b/external/boringssl/include/openssl/des.h new file mode 100644 index 0000000000..2b8dd0f625 --- /dev/null +++ b/external/boringssl/include/openssl/des.h @@ -0,0 +1,177 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_DES_H +#define OPENSSL_HEADER_DES_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* DES. */ + + +typedef struct DES_cblock_st { + uint8_t bytes[8]; +} DES_cblock; + +typedef struct DES_ks { + uint32_t subkeys[16][2]; +} DES_key_schedule; + + +#define DES_KEY_SZ (sizeof(DES_cblock)) +#define DES_SCHEDULE_SZ (sizeof(DES_key_schedule)) + +#define DES_ENCRYPT 1 +#define DES_DECRYPT 0 + +#define DES_CBC_MODE 0 +#define DES_PCBC_MODE 1 + +/* DES_set_key performs a key schedule and initialises |schedule| with |key|. */ +OPENSSL_EXPORT void DES_set_key(const DES_cblock *key, + DES_key_schedule *schedule); + +/* DES_set_odd_parity sets the parity bits (the least-significant bits in each + * byte) of |key| given the other bits in each byte. */ +OPENSSL_EXPORT void DES_set_odd_parity(DES_cblock *key); + +/* DES_ecb_encrypt encrypts (or decrypts, if |is_encrypt| is |DES_DECRYPT|) a + * single DES block (8 bytes) from in to out, using the key configured in + * |schedule|. */ +OPENSSL_EXPORT void DES_ecb_encrypt(const DES_cblock *in, DES_cblock *out, + const DES_key_schedule *schedule, + int is_encrypt); + +/* DES_ncbc_encrypt encrypts (or decrypts, if |enc| is |DES_DECRYPT|) |len| + * bytes from |in| to |out| with DES in CBC mode. */ +OPENSSL_EXPORT void DES_ncbc_encrypt(const uint8_t *in, uint8_t *out, + size_t len, + const DES_key_schedule *schedule, + DES_cblock *ivec, int enc); + +/* DES_ecb3_encrypt encrypts (or decrypts, if |enc| is |DES_DECRYPT|) a single + * block (8 bytes) of data from |input| to |output| using 3DES. */ +OPENSSL_EXPORT void DES_ecb3_encrypt(const DES_cblock *input, + DES_cblock *output, + const DES_key_schedule *ks1, + const DES_key_schedule *ks2, + const DES_key_schedule *ks3, + int enc); + +/* DES_ede3_cbc_encrypt encrypts (or decrypts, if |enc| is |DES_DECRYPT|) |len| + * bytes from |in| to |out| with 3DES in CBC mode. 3DES uses three keys, thus + * the function takes three different |DES_key_schedule|s. */ +OPENSSL_EXPORT void DES_ede3_cbc_encrypt(const uint8_t *in, uint8_t *out, + size_t len, + const DES_key_schedule *ks1, + const DES_key_schedule *ks2, + const DES_key_schedule *ks3, + DES_cblock *ivec, int enc); + +/* DES_ede2_cbc_encrypt encrypts (or decrypts, if |enc| is |DES_DECRYPT|) |len| + * bytes from |in| to |out| with 3DES in CBC mode. With this keying option, the + * first and third 3DES keys are identical. Thus, this function takes only two + * different |DES_key_schedule|s. */ +OPENSSL_EXPORT void DES_ede2_cbc_encrypt(const uint8_t *in, uint8_t *out, + size_t len, + const DES_key_schedule *ks1, + const DES_key_schedule *ks2, + DES_cblock *ivec, int enc); + + +/* Deprecated functions. */ + +/* DES_set_key_unchecked calls |DES_set_key|. */ +OPENSSL_EXPORT void DES_set_key_unchecked(const DES_cblock *key, + DES_key_schedule *schedule); + +OPENSSL_EXPORT void DES_ede3_cfb64_encrypt(const uint8_t *in, uint8_t *out, + long length, DES_key_schedule *ks1, + DES_key_schedule *ks2, + DES_key_schedule *ks3, + DES_cblock *ivec, int *num, int enc); + +OPENSSL_EXPORT void DES_ede3_cfb_encrypt(const uint8_t *in, uint8_t *out, + int numbits, long length, + DES_key_schedule *ks1, + DES_key_schedule *ks2, + DES_key_schedule *ks3, + DES_cblock *ivec, int enc); + + +/* Private functions. + * + * These functions are only exported for use in |decrepit|. */ + +OPENSSL_EXPORT void DES_decrypt3(uint32_t *data, const DES_key_schedule *ks1, + const DES_key_schedule *ks2, + const DES_key_schedule *ks3); + +OPENSSL_EXPORT void DES_encrypt3(uint32_t *data, const DES_key_schedule *ks1, + const DES_key_schedule *ks2, + const DES_key_schedule *ks3); + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_DES_H */ diff --git a/external/boringssl/include/openssl/dh.h b/external/boringssl/include/openssl/dh.h new file mode 100644 index 0000000000..a08765183a --- /dev/null +++ b/external/boringssl/include/openssl/dh.h @@ -0,0 +1,267 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_DH_H +#define OPENSSL_HEADER_DH_H + +#include + +#include +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* DH contains functions for performing Diffie-Hellman key agreement in + * multiplicative groups. */ + + +/* Allocation and destruction. */ + +/* DH_new returns a new, empty DH object or NULL on error. */ +OPENSSL_EXPORT DH *DH_new(void); + +/* DH_free decrements the reference count of |dh| and frees it if the reference + * count drops to zero. */ +OPENSSL_EXPORT void DH_free(DH *dh); + +/* DH_up_ref increments the reference count of |dh|. */ +OPENSSL_EXPORT int DH_up_ref(DH *dh); + + +/* Standard parameters. + * + * These functions return new DH objects with standard parameters. They return + * NULL on allocation failure. The |engine| parameter is ignored. */ + +/* These parameters are taken from RFC 5114. */ + +OPENSSL_EXPORT DH *DH_get_1024_160(const ENGINE *engine); +OPENSSL_EXPORT DH *DH_get_2048_224(const ENGINE *engine); +OPENSSL_EXPORT DH *DH_get_2048_256(const ENGINE *engine); + + +/* Parameter generation. */ + +#define DH_GENERATOR_2 2 +#define DH_GENERATOR_5 5 + +/* DH_generate_parameters_ex generates a suitable Diffie-Hellman group with a + * prime that is |prime_bits| long and stores it in |dh|. The generator of the + * group will be |generator|, which should be |DH_GENERATOR_2| unless there's a + * good reason to use a different value. The |cb| argument contains a callback + * function that will be called during the generation. See the documentation in + * |bn.h| about this. In addition to the callback invocations from |BN|, |cb| + * will also be called with |event| equal to three when the generation is + * complete. */ +OPENSSL_EXPORT int DH_generate_parameters_ex(DH *dh, int prime_bits, + int generator, BN_GENCB *cb); + + +/* Diffie-Hellman operations. */ + +/* DH_generate_key generates a new, random, private key and stores it in + * |dh|. It returns one on success and zero on error. */ +OPENSSL_EXPORT int DH_generate_key(DH *dh); + +/* DH_compute_key calculates the shared key between |dh| and |peers_key| and + * writes it as a big-endian integer into |out|, which must have |DH_size| + * bytes of space. It returns the number of bytes written, or a negative number + * on error. */ +OPENSSL_EXPORT int DH_compute_key(uint8_t *out, const BIGNUM *peers_key, + DH *dh); + + +/* Utility functions. */ + +/* DH_size returns the number of bytes in the DH group's prime. */ +OPENSSL_EXPORT int DH_size(const DH *dh); + +/* DH_num_bits returns the minimum number of bits needed to represent the + * absolute value of the DH group's prime. */ +OPENSSL_EXPORT unsigned DH_num_bits(const DH *dh); + +#define DH_CHECK_P_NOT_PRIME 0x01 +#define DH_CHECK_P_NOT_SAFE_PRIME 0x02 +#define DH_CHECK_UNABLE_TO_CHECK_GENERATOR 0x04 +#define DH_CHECK_NOT_SUITABLE_GENERATOR 0x08 +#define DH_CHECK_Q_NOT_PRIME 0x10 +#define DH_CHECK_INVALID_Q_VALUE 0x20 +#define DH_CHECK_INVALID_J_VALUE 0x40 + +/* These are compatibility defines. */ +#define DH_NOT_SUITABLE_GENERATOR DH_CHECK_NOT_SUITABLE_GENERATOR +#define DH_UNABLE_TO_CHECK_GENERATOR DH_CHECK_UNABLE_TO_CHECK_GENERATOR + +/* DH_check checks the suitability of |dh| as a Diffie-Hellman group. and sets + * |DH_CHECK_*| flags in |*out_flags| if it finds any errors. It returns one if + * |*out_flags| was successfully set and zero on error. + * + * Note: these checks may be quite computationally expensive. */ +OPENSSL_EXPORT int DH_check(const DH *dh, int *out_flags); + +#define DH_CHECK_PUBKEY_TOO_SMALL 0x1 +#define DH_CHECK_PUBKEY_TOO_LARGE 0x2 +#define DH_CHECK_PUBKEY_INVALID 0x4 + +/* DH_check_pub_key checks the suitability of |pub_key| as a public key for the + * DH group in |dh| and sets |DH_CHECK_PUBKEY_*| flags in |*out_flags| if it + * finds any errors. It returns one if |*out_flags| was successfully set and + * zero on error. */ +OPENSSL_EXPORT int DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, + int *out_flags); + +/* DHparams_dup allocates a fresh |DH| and copies the parameters from |dh| into + * it. It returns the new |DH| or NULL on error. */ +OPENSSL_EXPORT DH *DHparams_dup(const DH *dh); + + +/* ASN.1 functions. */ + +/* DH_parse_parameters decodes a DER-encoded DHParameter structure (PKCS #3) + * from |cbs| and advances |cbs|. It returns a newly-allocated |DH| or NULL on + * error. */ +OPENSSL_EXPORT DH *DH_parse_parameters(CBS *cbs); + +/* DH_marshal_parameters marshals |dh| as a DER-encoded DHParameter structure + * (PKCS #3) and appends the result to |cbb|. It returns one on success and zero + * on error. */ +OPENSSL_EXPORT int DH_marshal_parameters(CBB *cbb, const DH *dh); + + +/* ex_data functions. + * + * See |ex_data.h| for details. */ + +OPENSSL_EXPORT int DH_get_ex_new_index(long argl, void *argp, + CRYPTO_EX_unused *unused, + CRYPTO_EX_dup *dup_func, + CRYPTO_EX_free *free_func); +OPENSSL_EXPORT int DH_set_ex_data(DH *d, int idx, void *arg); +OPENSSL_EXPORT void *DH_get_ex_data(DH *d, int idx); + + +/* Deprecated functions. */ + +/* DH_generate_parameters behaves like |DH_generate_parameters_ex|, which is + * what you should use instead. It returns NULL on error, or a newly-allocated + * |DH| on success. This function is provided for compatibility only. */ +OPENSSL_EXPORT DH *DH_generate_parameters(int prime_len, int generator, + void (*callback)(int, int, void *), + void *cb_arg); + +/* d2i_DHparams parses an ASN.1, DER encoded Diffie-Hellman parameters structure + * from |len| bytes at |*inp|. If |ret| is not NULL then, on exit, a pointer to + * the result is in |*ret|. Note that, even if |*ret| is already non-NULL on + * entry, it will not be written to. Rather, a fresh |DH| is allocated and the + * previous one is freed. + * + * On successful exit, |*inp| is advanced past the DER structure. It + * returns the result or NULL on error. + * + * Use |DH_parse_parameters| instead. */ +OPENSSL_EXPORT DH *d2i_DHparams(DH **ret, const unsigned char **inp, long len); + +/* i2d_DHparams marshals |in| to an ASN.1, DER structure. If |outp| is not NULL + * then the result is written to |*outp| and |*outp| is advanced just past the + * output. It returns the number of bytes in the result, whether written or + * not, or a negative value on error. + * + * Use |DH_marshal_parameters| instead. */ +OPENSSL_EXPORT int i2d_DHparams(const DH *in, unsigned char **outp); + + +struct dh_st { + BIGNUM *p; + BIGNUM *g; + BIGNUM *pub_key; /* g^x mod p */ + BIGNUM *priv_key; /* x */ + + /* priv_length contains the length, in bits, of the private value. If zero, + * the private value will be the same length as |p|. */ + unsigned priv_length; + + CRYPTO_MUTEX method_mont_p_lock; + BN_MONT_CTX *method_mont_p; + + /* Place holders if we want to do X9.42 DH */ + BIGNUM *q; + BIGNUM *j; + unsigned char *seed; + int seedlen; + BIGNUM *counter; + + int flags; + CRYPTO_refcount_t references; + CRYPTO_EX_DATA ex_data; +}; + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#define DH_R_BAD_GENERATOR 100 +#define DH_R_INVALID_PUBKEY 101 +#define DH_R_MODULUS_TOO_LARGE 102 +#define DH_R_NO_PRIVATE_VALUE 103 +#define DH_R_DECODE_ERROR 104 +#define DH_R_ENCODE_ERROR 105 + +#endif /* OPENSSL_HEADER_DH_H */ diff --git a/external/boringssl/include/openssl/digest.h b/external/boringssl/include/openssl/digest.h new file mode 100644 index 0000000000..07ea07a64f --- /dev/null +++ b/external/boringssl/include/openssl/digest.h @@ -0,0 +1,267 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_DIGEST_H +#define OPENSSL_HEADER_DIGEST_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* Digest functions. + * + * An EVP_MD abstracts the details of a specific hash function allowing code to + * deal with the concept of a "hash function" without needing to know exactly + * which hash function it is. */ + + +/* Hash algorithms. + * + * The following functions return |EVP_MD| objects that implement the named hash + * function. */ + +OPENSSL_EXPORT const EVP_MD *EVP_md4(void); +OPENSSL_EXPORT const EVP_MD *EVP_md5(void); +OPENSSL_EXPORT const EVP_MD *EVP_sha1(void); +OPENSSL_EXPORT const EVP_MD *EVP_sha224(void); +OPENSSL_EXPORT const EVP_MD *EVP_sha256(void); +OPENSSL_EXPORT const EVP_MD *EVP_sha384(void); +OPENSSL_EXPORT const EVP_MD *EVP_sha512(void); + +/* EVP_md5_sha1 is a TLS-specific |EVP_MD| which computes the concatenation of + * MD5 and SHA-1, as used in TLS 1.1 and below. */ +OPENSSL_EXPORT const EVP_MD *EVP_md5_sha1(void); + +/* EVP_get_digestbynid returns an |EVP_MD| for the given NID, or NULL if no + * such digest is known. */ +OPENSSL_EXPORT const EVP_MD *EVP_get_digestbynid(int nid); + +/* EVP_get_digestbyobj returns an |EVP_MD| for the given |ASN1_OBJECT|, or NULL + * if no such digest is known. */ +OPENSSL_EXPORT const EVP_MD *EVP_get_digestbyobj(const ASN1_OBJECT *obj); + + +/* Digest contexts. + * + * An EVP_MD_CTX represents the state of a specific digest operation in + * progress. */ + +/* EVP_MD_CTX_init initialises an, already allocated, |EVP_MD_CTX|. */ +OPENSSL_EXPORT void EVP_MD_CTX_init(EVP_MD_CTX *ctx); + +/* EVP_MD_CTX_create allocates and initialises a fresh |EVP_MD_CTX| and returns + * it, or NULL on allocation failure. */ +OPENSSL_EXPORT EVP_MD_CTX *EVP_MD_CTX_create(void); + +/* EVP_MD_CTX_cleanup frees any resources owned by |ctx| and resets it to a + * freshly initialised state. It does not free |ctx| itself. It returns one. */ +OPENSSL_EXPORT int EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx); + +/* EVP_MD_CTX_destroy calls |EVP_MD_CTX_cleanup| and then frees |ctx| itself. */ +OPENSSL_EXPORT void EVP_MD_CTX_destroy(EVP_MD_CTX *ctx); + +/* EVP_MD_CTX_copy_ex sets |out|, which must already be initialised, to be a + * copy of |in|. It returns one on success and zero on error. */ +OPENSSL_EXPORT int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in); + + +/* Digest operations. */ + +/* EVP_DigestInit_ex configures |ctx|, which must already have been + * initialised, for a fresh hashing operation using |type|. It returns one on + * success and zero otherwise. */ +OPENSSL_EXPORT int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, + ENGINE *engine); + +/* EVP_DigestInit acts like |EVP_DigestInit_ex| except that |ctx| is + * initialised before use. */ +OPENSSL_EXPORT int EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type); + +/* EVP_DigestUpdate hashes |len| bytes from |data| into the hashing operation + * in |ctx|. It returns one. */ +OPENSSL_EXPORT int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *data, + size_t len); + +/* EVP_MAX_MD_SIZE is the largest digest size supported, in bytes. + * Functions that output a digest generally require the buffer have + * at least this much space. */ +#define EVP_MAX_MD_SIZE 64 /* SHA-512 is the longest so far. */ + +/* EVP_MAX_MD_BLOCK_SIZE is the largest digest block size supported, in bytes. */ +#define EVP_MAX_MD_BLOCK_SIZE 128 /* SHA-512 is the longest so far. */ + +/* EVP_DigestFinal_ex finishes the digest in |ctx| and writes the output to + * |md_out|. At most |EVP_MAX_MD_SIZE| bytes are written. If |out_size| is not + * NULL then |*out_size| is set to the number of bytes written. It returns one. + * After this call, the hash cannot be updated or finished again until + * |EVP_DigestInit_ex| is called to start another hashing operation. */ +OPENSSL_EXPORT int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, uint8_t *md_out, + unsigned int *out_size); + +/* EVP_DigestFinal acts like |EVP_DigestFinal_ex| except that + * |EVP_MD_CTX_cleanup| is called on |ctx| before returning. */ +OPENSSL_EXPORT int EVP_DigestFinal(EVP_MD_CTX *ctx, uint8_t *md_out, + unsigned int *out_size); + +/* EVP_Digest performs a complete hashing operation in one call. It hashes + * |len| bytes from |data| and writes the digest to |md_out|. At most + * |EVP_MAX_MD_SIZE| bytes are written. If |out_size| is not NULL then + * |*out_size| is set to the number of bytes written. It returns one on success + * and zero otherwise. */ +OPENSSL_EXPORT int EVP_Digest(const void *data, size_t len, uint8_t *md_out, + unsigned int *md_out_size, const EVP_MD *type, + ENGINE *impl); + + +/* Digest function accessors. + * + * These functions allow code to learn details about an abstract hash + * function. */ + +/* EVP_MD_type returns a NID identifing |md|. (For example, |NID_sha256|.) */ +OPENSSL_EXPORT int EVP_MD_type(const EVP_MD *md); + +/* EVP_MD_flags returns the flags for |md|, which is a set of |EVP_MD_FLAG_*| + * values, ORed together. */ +OPENSSL_EXPORT uint32_t EVP_MD_flags(const EVP_MD *md); + +/* EVP_MD_size returns the digest size of |md|, in bytes. */ +OPENSSL_EXPORT size_t EVP_MD_size(const EVP_MD *md); + +/* EVP_MD_block_size returns the native block-size of |md|, in bytes. */ +OPENSSL_EXPORT size_t EVP_MD_block_size(const EVP_MD *md); + +/* EVP_MD_FLAG_PKEY_DIGEST indicates the the digest function is used with a + * specific public key in order to verify signatures. (For example, + * EVP_dss1.) */ +#define EVP_MD_FLAG_PKEY_DIGEST 1 + +/* EVP_MD_FLAG_DIGALGID_ABSENT indicates that the parameter type in an X.509 + * DigestAlgorithmIdentifier representing this digest function should be + * undefined rather than NULL. */ +#define EVP_MD_FLAG_DIGALGID_ABSENT 2 + + +/* Deprecated functions. */ + +/* EVP_MD_CTX_copy sets |out|, which must /not/ be initialised, to be a copy of + * |in|. It returns one on success and zero on error. */ +OPENSSL_EXPORT int EVP_MD_CTX_copy(EVP_MD_CTX *out, const EVP_MD_CTX *in); + +/* EVP_add_digest does nothing and returns one. It exists only for + * compatibility with OpenSSL. */ +OPENSSL_EXPORT int EVP_add_digest(const EVP_MD *digest); + +/* EVP_get_digestbyname returns an |EVP_MD| given a human readable name in + * |name|, or NULL if the name is unknown. */ +OPENSSL_EXPORT const EVP_MD *EVP_get_digestbyname(const char *); + +/* EVP_dss1 returns the value of EVP_sha1(). This was provided by OpenSSL to + * specifiy the original DSA signatures, which were fixed to use SHA-1. Note, + * however, that attempting to sign or verify DSA signatures with the EVP + * interface will always fail. */ +OPENSSL_EXPORT const EVP_MD *EVP_dss1(void); + + +/* Digest operation accessors. */ + +/* EVP_MD_CTX_md returns the underlying digest function, or NULL if one has not + * been set. */ +OPENSSL_EXPORT const EVP_MD *EVP_MD_CTX_md(const EVP_MD_CTX *ctx); + +/* EVP_MD_CTX_size returns the digest size of |ctx|, in bytes. It + * will crash if a digest hasn't been set on |ctx|. */ +OPENSSL_EXPORT size_t EVP_MD_CTX_size(const EVP_MD_CTX *ctx); + +/* EVP_MD_CTX_block_size returns the block size of the digest function used by + * |ctx|, in bytes. It will crash if a digest hasn't been set on |ctx|. */ +OPENSSL_EXPORT size_t EVP_MD_CTX_block_size(const EVP_MD_CTX *ctx); + +/* EVP_MD_CTX_type returns a NID describing the digest function used by |ctx|. + * (For example, |NID_sha256|.) It will crash if a digest hasn't been set on + * |ctx|. */ +OPENSSL_EXPORT int EVP_MD_CTX_type(const EVP_MD_CTX *ctx); + + +struct evp_md_pctx_ops; + +struct env_md_ctx_st { + /* digest is the underlying digest function, or NULL if not set. */ + const EVP_MD *digest; + /* md_data points to a block of memory that contains the hash-specific + * context. */ + void *md_data; + + /* pctx is an opaque (at this layer) pointer to additional context that + * EVP_PKEY functions may store in this object. */ + EVP_PKEY_CTX *pctx; + + /* pctx_ops, if not NULL, points to a vtable that contains functions to + * manipulate |pctx|. */ + const struct evp_md_pctx_ops *pctx_ops; +} /* EVP_MD_CTX */; + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#define DIGEST_R_INPUT_NOT_INITIALIZED 100 + +#endif /* OPENSSL_HEADER_DIGEST_H */ diff --git a/external/boringssl/include/openssl/dsa.h b/external/boringssl/include/openssl/dsa.h new file mode 100644 index 0000000000..0077a722d2 --- /dev/null +++ b/external/boringssl/include/openssl/dsa.h @@ -0,0 +1,409 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + * + * The DSS routines are based on patches supplied by + * Steven Schoch . */ + +#ifndef OPENSSL_HEADER_DSA_H +#define OPENSSL_HEADER_DSA_H + +#include + +#include +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* DSA contains functions for signing and verifing with the Digital Signature + * Algorithm. */ + + +/* Allocation and destruction. */ + +/* DSA_new returns a new, empty DSA object or NULL on error. */ +OPENSSL_EXPORT DSA *DSA_new(void); + +/* DSA_free decrements the reference count of |dsa| and frees it if the + * reference count drops to zero. */ +OPENSSL_EXPORT void DSA_free(DSA *dsa); + +/* DSA_up_ref increments the reference count of |dsa|. */ +OPENSSL_EXPORT int DSA_up_ref(DSA *dsa); + + +/* Parameter generation. */ + +/* DSA_generate_parameters_ex generates a set of DSA parameters by following + * the procedure given in FIPS 186-4, appendix A. + * (http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf) + * + * The larger prime will have a length of |bits| (e.g. 2048). The |seed| value + * allows others to generate and verify the same parameters and should be + * random input which is kept for reference. If |out_counter| or |out_h| are + * not NULL then the counter and h value used in the generation are written to + * them. + * + * The |cb| argument is passed to |BN_generate_prime_ex| and is thus called + * during the generation process in order to indicate progress. See the + * comments for that function for details. In addition to the calls made by + * |BN_generate_prime_ex|, |DSA_generate_parameters_ex| will call it with + * |event| equal to 2 and 3 at different stages of the process. + * + * It returns one on success and zero otherwise. */ +OPENSSL_EXPORT int DSA_generate_parameters_ex(DSA *dsa, unsigned bits, + const uint8_t *seed, + size_t seed_len, int *out_counter, + unsigned long *out_h, + BN_GENCB *cb); + +/* DSAparams_dup returns a freshly allocated |DSA| that contains a copy of the + * parameters from |dsa|. It returns NULL on error. */ +OPENSSL_EXPORT DSA *DSAparams_dup(const DSA *dsa); + + +/* Key generation. */ + +/* DSA_generate_key generates a public/private key pair in |dsa|, which must + * already have parameters setup. It returns one on success and zero on + * error. */ +OPENSSL_EXPORT int DSA_generate_key(DSA *dsa); + + +/* Signatures. */ + +/* DSA_SIG_st (aka |DSA_SIG|) contains a DSA signature as a pair of integers. */ +typedef struct DSA_SIG_st { + BIGNUM *r, *s; +} DSA_SIG; + +/* DSA_SIG_new returns a freshly allocated, DIG_SIG structure or NULL on error. + * Both |r| and |s| in the signature will be NULL. */ +OPENSSL_EXPORT DSA_SIG *DSA_SIG_new(void); + +/* DSA_SIG_free frees the contents of |sig| and then frees |sig| itself. */ +OPENSSL_EXPORT void DSA_SIG_free(DSA_SIG *sig); + +/* DSA_do_sign returns a signature of the hash in |digest| by the key in |dsa| + * and returns an allocated, DSA_SIG structure, or NULL on error. */ +OPENSSL_EXPORT DSA_SIG *DSA_do_sign(const uint8_t *digest, size_t digest_len, + DSA *dsa); + +/* DSA_do_verify verifies that |sig| is a valid signature, by the public key in + * |dsa|, of the hash in |digest|. It returns one if so, zero if invalid and -1 + * on error. + * + * WARNING: do not use. This function returns -1 for error, 0 for invalid and 1 + * for valid. However, this is dangerously different to the usual OpenSSL + * convention and could be a disaster if a user did |if (DSA_do_verify(...))|. + * Because of this, |DSA_check_signature| is a safer version of this. + * + * TODO(fork): deprecate. */ +OPENSSL_EXPORT int DSA_do_verify(const uint8_t *digest, size_t digest_len, + DSA_SIG *sig, const DSA *dsa); + +/* DSA_do_check_signature sets |*out_valid| to zero. Then it verifies that |sig| + * is a valid signature, by the public key in |dsa| of the hash in |digest| + * and, if so, it sets |*out_valid| to one. + * + * It returns one if it was able to verify the signature as valid or invalid, + * and zero on error. */ +OPENSSL_EXPORT int DSA_do_check_signature(int *out_valid, const uint8_t *digest, + size_t digest_len, DSA_SIG *sig, + const DSA *dsa); + + +/* ASN.1 signatures. + * + * These functions also perform DSA signature operations, but deal with ASN.1 + * encoded signatures as opposed to raw |BIGNUM|s. If you don't know what + * encoding a DSA signature is in, it's probably ASN.1. */ + +/* DSA_sign signs |digest| with the key in |dsa| and writes the resulting + * signature, in ASN.1 form, to |out_sig| and the length of the signature to + * |*out_siglen|. There must be, at least, |DSA_size(dsa)| bytes of space in + * |out_sig|. It returns one on success and zero otherwise. + * + * (The |type| argument is ignored.) */ +OPENSSL_EXPORT int DSA_sign(int type, const uint8_t *digest, size_t digest_len, + uint8_t *out_sig, unsigned int *out_siglen, + DSA *dsa); + +/* DSA_verify verifies that |sig| is a valid, ASN.1 signature, by the public + * key in |dsa|, of the hash in |digest|. It returns one if so, zero if invalid + * and -1 on error. + * + * (The |type| argument is ignored.) + * + * WARNING: do not use. This function returns -1 for error, 0 for invalid and 1 + * for valid. However, this is dangerously different to the usual OpenSSL + * convention and could be a disaster if a user did |if (DSA_do_verify(...))|. + * Because of this, |DSA_check_signature| is a safer version of this. + * + * TODO(fork): deprecate. */ +OPENSSL_EXPORT int DSA_verify(int type, const uint8_t *digest, + size_t digest_len, const uint8_t *sig, + size_t sig_len, const DSA *dsa); + +/* DSA_check_signature sets |*out_valid| to zero. Then it verifies that |sig| + * is a valid, ASN.1 signature, by the public key in |dsa|, of the hash in + * |digest|. If so, it sets |*out_valid| to one. + * + * It returns one if it was able to verify the signature as valid or invalid, + * and zero on error. */ +OPENSSL_EXPORT int DSA_check_signature(int *out_valid, const uint8_t *digest, + size_t digest_len, const uint8_t *sig, + size_t sig_len, const DSA *dsa); + +/* DSA_size returns the size, in bytes, of an ASN.1 encoded, DSA signature + * generated by |dsa|. Parameters must already have been setup in |dsa|. */ +OPENSSL_EXPORT int DSA_size(const DSA *dsa); + + +/* ASN.1 encoding. */ + +/* DSA_SIG_parse parses a DER-encoded DSA-Sig-Value structure from |cbs| and + * advances |cbs|. It returns a newly-allocated |DSA_SIG| or NULL on error. */ +OPENSSL_EXPORT DSA_SIG *DSA_SIG_parse(CBS *cbs); + +/* DSA_SIG_marshal marshals |sig| as a DER-encoded DSA-Sig-Value and appends the + * result to |cbb|. It returns one on success and zero on error. */ +OPENSSL_EXPORT int DSA_SIG_marshal(CBB *cbb, const DSA_SIG *sig); + +/* DSA_parse_public_key parses a DER-encoded DSA public key from |cbs| and + * advances |cbs|. It returns a newly-allocated |DSA| or NULL on error. */ +OPENSSL_EXPORT DSA *DSA_parse_public_key(CBS *cbs); + +/* DSA_marshal_public_key marshals |dsa| as a DER-encoded DSA public key and + * appends the result to |cbb|. It returns one on success and zero on + * failure. */ +OPENSSL_EXPORT int DSA_marshal_public_key(CBB *cbb, const DSA *dsa); + +/* DSA_parse_private_key parses a DER-encoded DSA private key from |cbs| and + * advances |cbs|. It returns a newly-allocated |DSA| or NULL on error. */ +OPENSSL_EXPORT DSA *DSA_parse_private_key(CBS *cbs); + +/* DSA_marshal_private_key marshals |dsa| as a DER-encoded DSA private key and + * appends the result to |cbb|. It returns one on success and zero on + * failure. */ +OPENSSL_EXPORT int DSA_marshal_private_key(CBB *cbb, const DSA *dsa); + +/* DSA_parse_parameters parses a DER-encoded Dss-Parms structure (RFC 3279) + * from |cbs| and advances |cbs|. It returns a newly-allocated |DSA| or NULL on + * error. */ +OPENSSL_EXPORT DSA *DSA_parse_parameters(CBS *cbs); + +/* DSA_marshal_parameters marshals |dsa| as a DER-encoded Dss-Parms structure + * (RFC 3447) and appends the result to |cbb|. It returns one on success and + * zero on failure. */ +OPENSSL_EXPORT int DSA_marshal_parameters(CBB *cbb, const DSA *dsa); + + +/* Precomputation. */ + +/* DSA_sign_setup precomputes the message independent part of the DSA signature + * and writes them to |*out_kinv| and |*out_r|. Returns one on success, zero on + * error. + * + * TODO(fork): decide what to do with this. Since making DSA* opaque there's no + * way for the user to install them. Also, it forces the DSA* not to be const + * when passing to the signing function. */ +OPENSSL_EXPORT int DSA_sign_setup(const DSA *dsa, BN_CTX *ctx, + BIGNUM **out_kinv, BIGNUM **out_r); + + +/* Conversion. */ + +/* DSA_dup_DH returns a |DH| constructed from the parameters of |dsa|. This is + * sometimes needed when Diffie-Hellman parameters are stored in the form of + * DSA parameters. It returns an allocated |DH| on success or NULL on error. */ +OPENSSL_EXPORT DH *DSA_dup_DH(const DSA *dsa); + + +/* ex_data functions. + * + * See |ex_data.h| for details. */ + +OPENSSL_EXPORT int DSA_get_ex_new_index(long argl, void *argp, + CRYPTO_EX_unused *unused, + CRYPTO_EX_dup *dup_func, + CRYPTO_EX_free *free_func); +OPENSSL_EXPORT int DSA_set_ex_data(DSA *d, int idx, void *arg); +OPENSSL_EXPORT void *DSA_get_ex_data(const DSA *d, int idx); + + +/* Deprecated functions. */ + +/* d2i_DSA_SIG parses an ASN.1, DER-encoded, DSA signature from |len| bytes at + * |*inp|. If |out_sig| is not NULL then, on exit, a pointer to the result is + * in |*out_sig|. Note that, even if |*out_sig| is already non-NULL on entry, it + * will not be written to. Rather, a fresh |DSA_SIG| is allocated and the + * previous one is freed. On successful exit, |*inp| is advanced past the DER + * structure. It returns the result or NULL on error. + * + * Use |DSA_SIG_parse| instead. */ +OPENSSL_EXPORT DSA_SIG *d2i_DSA_SIG(DSA_SIG **out_sig, const uint8_t **inp, + long len); + +/* i2d_DSA_SIG marshals |in| to an ASN.1, DER structure. If |outp| is not NULL + * then the result is written to |*outp| and |*outp| is advanced just past the + * output. It returns the number of bytes in the result, whether written or not, + * or a negative value on error. + * + * Use |DSA_SIG_marshal| instead. */ +OPENSSL_EXPORT int i2d_DSA_SIG(const DSA_SIG *in, uint8_t **outp); + +/* d2i_DSAPublicKey parses an ASN.1, DER-encoded, DSA public key from |len| + * bytes at |*inp|. If |out| is not NULL then, on exit, a pointer to the result + * is in |*out|. Note that, even if |*ou| is already non-NULL on entry, it will + * not be written to. Rather, a fresh |DSA| is allocated and the previous one is + * freed. On successful exit, |*inp| is advanced past the DER structure. It + * returns the result or NULL on error. + * + * Use |DSA_parse_public_key| instead. */ +OPENSSL_EXPORT DSA *d2i_DSAPublicKey(DSA **out, const uint8_t **inp, long len); + +/* i2d_DSAPublicKey marshals a public key from |in| to an ASN.1, DER structure. + * If |outp| is not NULL then the result is written to |*outp| and |*outp| is + * advanced just past the output. It returns the number of bytes in the result, + * whether written or not, or a negative value on error. + * + * Use |DSA_marshal_public_key| instead. */ +OPENSSL_EXPORT int i2d_DSAPublicKey(const DSA *in, uint8_t **outp); + +/* d2i_DSAPrivateKey parses an ASN.1, DER-encoded, DSA private key from |len| + * bytes at |*inp|. If |out| is not NULL then, on exit, a pointer to the result + * is in |*out|. Note that, even if |*out| is already non-NULL on entry, it will + * not be written to. Rather, a fresh |DSA| is allocated and the previous one is + * freed. On successful exit, |*inp| is advanced past the DER structure. It + * returns the result or NULL on error. + * + * Use |DSA_parse_private_key| instead. */ +OPENSSL_EXPORT DSA *d2i_DSAPrivateKey(DSA **out, const uint8_t **inp, long len); + +/* i2d_DSAPrivateKey marshals a private key from |in| to an ASN.1, DER structure. + * If |outp| is not NULL then the result is written to |*outp| and |*outp| is + * advanced just past the output. It returns the number of bytes in the result, + * whether written or not, or a negative value on error. + * + * Use |DSA_marshal_private_key| instead. */ +OPENSSL_EXPORT int i2d_DSAPrivateKey(const DSA *in, uint8_t **outp); + +/* d2i_DSAparams parses ASN.1, DER-encoded, DSA parameters from |len| bytes at + * |*inp|. If |out| is not NULL then, on exit, a pointer to the result is in + * |*out|. Note that, even if |*out| is already non-NULL on entry, it will not + * be written to. Rather, a fresh |DSA| is allocated and the previous one is + * freed. On successful exit, |*inp| is advanced past the DER structure. It + * returns the result or NULL on error. + * + * Use |DSA_parse_parameters| instead. */ +OPENSSL_EXPORT DSA *d2i_DSAparams(DSA **out, const uint8_t **inp, long len); + +/* i2d_DSAparams marshals DSA parameters from |in| to an ASN.1, DER structure. + * If |outp| is not NULL then the result is written to |*outp| and |*outp| is + * advanced just past the output. It returns the number of bytes in the result, + * whether written or not, or a negative value on error. + * + * Use |DSA_marshal_parameters| instead. */ +OPENSSL_EXPORT int i2d_DSAparams(const DSA *in, uint8_t **outp); + +/* DSA_generate_parameters is a deprecated version of + * |DSA_generate_parameters_ex| that creates and returns a |DSA*|. Don't use + * it. */ +OPENSSL_EXPORT DSA *DSA_generate_parameters(int bits, unsigned char *seed, + int seed_len, int *counter_ret, + unsigned long *h_ret, + void (*callback)(int, int, void *), + void *cb_arg); + + +struct dsa_st { + long version; + BIGNUM *p; + BIGNUM *q; /* == 20 */ + BIGNUM *g; + + BIGNUM *pub_key; /* y public key */ + BIGNUM *priv_key; /* x private key */ + + BIGNUM *kinv; /* Signing pre-calc */ + BIGNUM *r; /* Signing pre-calc */ + + int flags; + /* Normally used to cache montgomery values */ + CRYPTO_MUTEX method_mont_p_lock; + BN_MONT_CTX *method_mont_p; + CRYPTO_refcount_t references; + CRYPTO_EX_DATA ex_data; +}; + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#define DSA_R_BAD_Q_VALUE 100 +#define DSA_R_MISSING_PARAMETERS 101 +#define DSA_R_MODULUS_TOO_LARGE 102 +#define DSA_R_NEED_NEW_SETUP_VALUES 103 +#define DSA_R_BAD_VERSION 104 +#define DSA_R_DECODE_ERROR 105 +#define DSA_R_ENCODE_ERROR 106 + +#endif /* OPENSSL_HEADER_DSA_H */ diff --git a/external/boringssl/include/openssl/dtls1.h b/external/boringssl/include/openssl/dtls1.h new file mode 100644 index 0000000000..38ca801cb1 --- /dev/null +++ b/external/boringssl/include/openssl/dtls1.h @@ -0,0 +1,16 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +/* This header is provided in order to make compiling against code that expects + OpenSSL easier. */ diff --git a/external/boringssl/include/openssl/ec.h b/external/boringssl/include/openssl/ec.h new file mode 100644 index 0000000000..143aa96cce --- /dev/null +++ b/external/boringssl/include/openssl/ec.h @@ -0,0 +1,405 @@ +/* Originally written by Bodo Moeller for the OpenSSL project. + * ==================================================================== + * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * + * Portions of the attached software ("Contribution") are developed by + * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. + * + * The Contribution is licensed pursuant to the OpenSSL open source + * license provided above. + * + * The elliptic curve binary polynomial software is originally written by + * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems + * Laboratories. */ + +#ifndef OPENSSL_HEADER_EC_H +#define OPENSSL_HEADER_EC_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* Low-level operations on elliptic curves. */ + + +typedef struct ec_group_st EC_GROUP; +typedef struct ec_point_st EC_POINT; + +/* point_conversion_form_t enumerates forms, as defined in X9.62 (ECDSA), for + * the encoding of a elliptic curve point (x,y) */ +typedef enum { + /* POINT_CONVERSION_COMPRESSED indicates that the point is encoded as z||x, + * where the octet z specifies which solution of the quadratic equation y + * is. */ + POINT_CONVERSION_COMPRESSED = 2, + + /* POINT_CONVERSION_COMPRESSED indicates that the point is encoded as + * z||x||y, where z is the octet 0x04. */ + POINT_CONVERSION_UNCOMPRESSED = 4, + + /* POINT_CONVERSION_HYBRID indicates that the point is encoded as z||x||y, + * where z specifies which solution of the quadratic equation y is. This is + * not supported by the code and has never been observed in use. + * + * TODO(agl): remove once node.js no longer references this. */ + POINT_CONVERSION_HYBRID = 6, +} point_conversion_form_t; + + +/* Elliptic curve groups. */ + +/* EC_GROUP_new_by_curve_name returns a fresh EC_GROUP object for the elliptic + * curve specified by |nid|, or NULL on error. + * + * The supported NIDs are: + * NID_secp224r1, + * NID_X9_62_prime256v1, + * NID_secp384r1, + * NID_secp521r1 */ +OPENSSL_EXPORT EC_GROUP *EC_GROUP_new_by_curve_name(int nid); + +/* EC_GROUP_free frees |group| and the data that it points to. */ +OPENSSL_EXPORT void EC_GROUP_free(EC_GROUP *group); + +/* EC_GROUP_dup returns a fresh |EC_GROUP| which is equal to |a| or NULL on + * error. */ +OPENSSL_EXPORT EC_GROUP *EC_GROUP_dup(const EC_GROUP *a); + +/* EC_GROUP_cmp returns zero if |a| and |b| are the same group and non-zero + * otherwise. */ +OPENSSL_EXPORT int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, + BN_CTX *ignored); + +/* EC_GROUP_get0_generator returns a pointer to the internal |EC_POINT| object + * in |group| that specifies the generator for the group. */ +OPENSSL_EXPORT const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group); + +/* EC_GROUP_get0_order returns a pointer to the internal |BIGNUM| object in + * |group| that specifies the order of the group. */ +OPENSSL_EXPORT const BIGNUM *EC_GROUP_get0_order(const EC_GROUP *group); + +/* EC_GROUP_get_cofactor sets |*cofactor| to the cofactor of |group| using + * |ctx|, if it's not NULL. It returns one on success and zero otherwise. */ +OPENSSL_EXPORT int EC_GROUP_get_cofactor(const EC_GROUP *group, + BIGNUM *cofactor, BN_CTX *ctx); + +/* EC_GROUP_get_curve_GFp gets various parameters about a group. It sets + * |*out_p| to the order of the coordinate field and |*out_a| and |*out_b| to + * the parameters of the curve when expressed as y² = x³ + ax + b. Any of the + * output parameters can be NULL. It returns one on success and zero on + * error. */ +OPENSSL_EXPORT int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *out_p, + BIGNUM *out_a, BIGNUM *out_b, + BN_CTX *ctx); + +/* EC_GROUP_get_curve_name returns a NID that identifies |group|. */ +OPENSSL_EXPORT int EC_GROUP_get_curve_name(const EC_GROUP *group); + +/* EC_GROUP_get_degree returns the number of bits needed to represent an + * element of the field underlying |group|. */ +OPENSSL_EXPORT unsigned EC_GROUP_get_degree(const EC_GROUP *group); + + +/* Points on elliptic curves. */ + +/* EC_POINT_new returns a fresh |EC_POINT| object in the given group, or NULL + * on error. */ +OPENSSL_EXPORT EC_POINT *EC_POINT_new(const EC_GROUP *group); + +/* EC_POINT_free frees |point| and the data that it points to. */ +OPENSSL_EXPORT void EC_POINT_free(EC_POINT *point); + +/* EC_POINT_clear_free clears the data that |point| points to, frees it and + * then frees |point| itself. */ +OPENSSL_EXPORT void EC_POINT_clear_free(EC_POINT *point); + +/* EC_POINT_copy sets |*dest| equal to |*src|. It returns one on success and + * zero otherwise. */ +OPENSSL_EXPORT int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src); + +/* EC_POINT_dup returns a fresh |EC_POINT| that contains the same values as + * |src|, or NULL on error. */ +OPENSSL_EXPORT EC_POINT *EC_POINT_dup(const EC_POINT *src, + const EC_GROUP *group); + +/* EC_POINT_set_to_infinity sets |point| to be the "point at infinity" for the + * given group. */ +OPENSSL_EXPORT int EC_POINT_set_to_infinity(const EC_GROUP *group, + EC_POINT *point); + +/* EC_POINT_is_at_infinity returns one iff |point| is the point at infinity and + * zero otherwise. */ +OPENSSL_EXPORT int EC_POINT_is_at_infinity(const EC_GROUP *group, + const EC_POINT *point); + +/* EC_POINT_is_on_curve returns one if |point| is an element of |group| and + * and zero otherwise or when an error occurs. This is different from OpenSSL, + * which returns -1 on error. If |ctx| is non-NULL, it may be used. */ +OPENSSL_EXPORT int EC_POINT_is_on_curve(const EC_GROUP *group, + const EC_POINT *point, BN_CTX *ctx); + +/* EC_POINT_cmp returns zero if |a| is equal to |b|, greater than zero if + * not equal and -1 on error. If |ctx| is not NULL, it may be used. */ +OPENSSL_EXPORT int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, + const EC_POINT *b, BN_CTX *ctx); + +/* EC_POINT_make_affine converts |point| to affine form, internally. It returns + * one on success and zero otherwise. If |ctx| is not NULL, it may be used. */ +OPENSSL_EXPORT int EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, + BN_CTX *ctx); + +/* EC_POINTs_make_affine converts |num| points from |points| to affine form, + * internally. It returns one on success and zero otherwise. If |ctx| is not + * NULL, it may be used. */ +OPENSSL_EXPORT int EC_POINTs_make_affine(const EC_GROUP *group, size_t num, + EC_POINT *points[], BN_CTX *ctx); + + +/* Point conversion. */ + +/* EC_POINT_get_affine_coordinates_GFp sets |x| and |y| to the affine value of + * |point| using |ctx|, if it's not NULL. It returns one on success and zero + * otherwise. */ +OPENSSL_EXPORT int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group, + const EC_POINT *point, + BIGNUM *x, BIGNUM *y, + BN_CTX *ctx); + +/* EC_POINT_set_affine_coordinates_GFp sets the value of |point| to be + * (|x|, |y|). The |ctx| argument may be used if not NULL. It returns one + * on success or zero on error. Note that, unlike with OpenSSL, it's + * considered an error if the point is not on the curve. */ +OPENSSL_EXPORT int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, + EC_POINT *point, + const BIGNUM *x, + const BIGNUM *y, + BN_CTX *ctx); + +/* EC_POINT_point2oct serialises |point| into the X9.62 form given by |form| + * into, at most, |len| bytes at |buf|. It returns the number of bytes written + * or zero on error if |buf| is non-NULL, else the number of bytes needed. The + * |ctx| argument may be used if not NULL. */ +OPENSSL_EXPORT size_t EC_POINT_point2oct(const EC_GROUP *group, + const EC_POINT *point, + point_conversion_form_t form, + uint8_t *buf, size_t len, BN_CTX *ctx); + +/* EC_POINT_point2cbb behaves like |EC_POINT_point2oct| but appends the + * serialised point to |cbb|. It returns one on success and zero on error. */ +OPENSSL_EXPORT int EC_POINT_point2cbb(CBB *out, const EC_GROUP *group, + const EC_POINT *point, + point_conversion_form_t form, + BN_CTX *ctx); + +/* EC_POINT_oct2point sets |point| from |len| bytes of X9.62 format + * serialisation in |buf|. It returns one on success and zero otherwise. The + * |ctx| argument may be used if not NULL. */ +OPENSSL_EXPORT int EC_POINT_oct2point(const EC_GROUP *group, EC_POINT *point, + const uint8_t *buf, size_t len, + BN_CTX *ctx); + +/* EC_POINT_set_compressed_coordinates_GFp sets |point| to equal the point with + * the given |x| coordinate and the y coordinate specified by |y_bit| (see + * X9.62). It returns one on success and zero otherwise. */ +OPENSSL_EXPORT int EC_POINT_set_compressed_coordinates_GFp( + const EC_GROUP *group, EC_POINT *point, const BIGNUM *x, int y_bit, + BN_CTX *ctx); + + +/* Group operations. */ + +/* EC_POINT_add sets |r| equal to |a| plus |b|. It returns one on success and + * zero otherwise. If |ctx| is not NULL, it may be used. */ +OPENSSL_EXPORT int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, + const EC_POINT *a, const EC_POINT *b, + BN_CTX *ctx); + +/* EC_POINT_dbl sets |r| equal to |a| plus |a|. It returns one on success and + * zero otherwise. If |ctx| is not NULL, it may be used. */ +OPENSSL_EXPORT int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, + const EC_POINT *a, BN_CTX *ctx); + +/* EC_POINT_invert sets |a| equal to minus |a|. It returns one on success and zero + * otherwise. If |ctx| is not NULL, it may be used. */ +OPENSSL_EXPORT int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, + BN_CTX *ctx); + +/* EC_POINT_mul sets r = generator*n + q*m. It returns one on success and zero + * otherwise. If |ctx| is not NULL, it may be used. */ +OPENSSL_EXPORT int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, + const BIGNUM *n, const EC_POINT *q, + const BIGNUM *m, BN_CTX *ctx); + + +/* Deprecated functions. */ + +/* EC_GROUP_new_curve_GFp creates a new, arbitrary elliptic curve group based + * on the equation y² = x³ + a·x + b. It returns the new group or NULL on + * error. + * + * This new group has no generator. It is an error to use a generator-less group + * with any functions except for |EC_GROUP_free|, |EC_POINT_new|, + * |EC_POINT_set_affine_coordinates_GFp|, and |EC_GROUP_set_generator|. + * + * |EC_GROUP|s returned by this function will always compare as unequal via + * |EC_GROUP_cmp| (even to themselves). |EC_GROUP_get_curve_name| will always + * return |NID_undef|. + * + * Avoid using arbitrary curves and use |EC_GROUP_new_by_curve_name| instead. */ +OPENSSL_EXPORT EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, + const BIGNUM *a, + const BIGNUM *b, BN_CTX *ctx); + +/* EC_GROUP_set_generator sets the generator for |group| to |generator|, which + * must have the given order and cofactor. It may only be used with |EC_GROUP| + * objects returned by |EC_GROUP_new_curve_GFp| and may only be used once on + * each group. */ +OPENSSL_EXPORT int EC_GROUP_set_generator(EC_GROUP *group, + const EC_POINT *generator, + const BIGNUM *order, + const BIGNUM *cofactor); + +/* EC_GROUP_new_arbitrary calls |EC_GROUP_new_curve_GFp| and + * |EC_GROUP_set_generator|. + * + * TODO(davidben): Remove this once + * https://android-review.googlesource.com/#/c/207990/ has cycled in. */ +OPENSSL_EXPORT EC_GROUP *EC_GROUP_new_arbitrary( + const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, const BIGNUM *gx, + const BIGNUM *gy, const BIGNUM *order, const BIGNUM *cofactor); + +/* EC_GROUP_get_order sets |*order| to the order of |group|, if it's not + * NULL. It returns one on success and zero otherwise. |ctx| is ignored. Use + * |EC_GROUP_get0_order| instead. */ +OPENSSL_EXPORT int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, + BN_CTX *ctx); + +/* EC_GROUP_set_asn1_flag does nothing. */ +OPENSSL_EXPORT void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag); + +#define OPENSSL_EC_NAMED_CURVE 0 + +typedef struct ec_method_st EC_METHOD; + +/* EC_GROUP_method_of returns NULL. */ +OPENSSL_EXPORT const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group); + +/* EC_METHOD_get_field_type returns NID_X9_62_prime_field. */ +OPENSSL_EXPORT int EC_METHOD_get_field_type(const EC_METHOD *meth); + +/* EC_GROUP_set_point_conversion_form aborts the process if |form| is not + * |POINT_CONVERSION_UNCOMPRESSED| and otherwise does nothing. */ +OPENSSL_EXPORT void EC_GROUP_set_point_conversion_form( + EC_GROUP *group, point_conversion_form_t form); + +/* EC_builtin_curve describes a supported elliptic curve. */ +typedef struct { + int nid; + const char *comment; +} EC_builtin_curve; + +/* EC_get_builtin_curves writes at most |max_num_curves| elements to + * |out_curves| and returns the total number that it would have written, had + * |max_num_curves| been large enough. + * + * The |EC_builtin_curve| items describe the supported elliptic curves. */ +OPENSSL_EXPORT size_t EC_get_builtin_curves(EC_builtin_curve *out_curves, + size_t max_num_curves); + +/* Old code expects to get EC_KEY from ec.h. */ +#include + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#define EC_R_BUFFER_TOO_SMALL 100 +#define EC_R_COORDINATES_OUT_OF_RANGE 101 +#define EC_R_D2I_ECPKPARAMETERS_FAILURE 102 +#define EC_R_EC_GROUP_NEW_BY_NAME_FAILURE 103 +#define EC_R_GROUP2PKPARAMETERS_FAILURE 104 +#define EC_R_I2D_ECPKPARAMETERS_FAILURE 105 +#define EC_R_INCOMPATIBLE_OBJECTS 106 +#define EC_R_INVALID_COMPRESSED_POINT 107 +#define EC_R_INVALID_COMPRESSION_BIT 108 +#define EC_R_INVALID_ENCODING 109 +#define EC_R_INVALID_FIELD 110 +#define EC_R_INVALID_FORM 111 +#define EC_R_INVALID_GROUP_ORDER 112 +#define EC_R_INVALID_PRIVATE_KEY 113 +#define EC_R_MISSING_PARAMETERS 114 +#define EC_R_MISSING_PRIVATE_KEY 115 +#define EC_R_NON_NAMED_CURVE 116 +#define EC_R_NOT_INITIALIZED 117 +#define EC_R_PKPARAMETERS2GROUP_FAILURE 118 +#define EC_R_POINT_AT_INFINITY 119 +#define EC_R_POINT_IS_NOT_ON_CURVE 120 +#define EC_R_SLOT_FULL 121 +#define EC_R_UNDEFINED_GENERATOR 122 +#define EC_R_UNKNOWN_GROUP 123 +#define EC_R_UNKNOWN_ORDER 124 +#define EC_R_WRONG_ORDER 125 +#define EC_R_BIGNUM_OUT_OF_RANGE 126 +#define EC_R_WRONG_CURVE_PARAMETERS 127 +#define EC_R_DECODE_ERROR 128 +#define EC_R_ENCODE_ERROR 129 +#define EC_R_GROUP_MISMATCH 130 + +#endif /* OPENSSL_HEADER_EC_H */ diff --git a/external/boringssl/include/openssl/ec_key.h b/external/boringssl/include/openssl/ec_key.h new file mode 100644 index 0000000000..63554a7818 --- /dev/null +++ b/external/boringssl/include/openssl/ec_key.h @@ -0,0 +1,327 @@ +/* Originally written by Bodo Moeller for the OpenSSL project. + * ==================================================================== + * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * + * Portions of the attached software ("Contribution") are developed by + * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. + * + * The Contribution is licensed pursuant to the OpenSSL open source + * license provided above. + * + * The elliptic curve binary polynomial software is originally written by + * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems + * Laboratories. */ + +#ifndef OPENSSL_HEADER_EC_KEY_H +#define OPENSSL_HEADER_EC_KEY_H + +#include + +#include +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* ec_key.h contains functions that handle elliptic-curve points that are + * public/private keys. */ + + +/* EC key objects. */ + +/* EC_KEY_new returns a fresh |EC_KEY| object or NULL on error. */ +OPENSSL_EXPORT EC_KEY *EC_KEY_new(void); + +/* EC_KEY_new_method acts the same as |EC_KEY_new|, but takes an explicit + * |ENGINE|. */ +OPENSSL_EXPORT EC_KEY *EC_KEY_new_method(const ENGINE *engine); + +/* EC_KEY_new_by_curve_name returns a fresh EC_KEY for group specified by |nid| + * or NULL on error. */ +OPENSSL_EXPORT EC_KEY *EC_KEY_new_by_curve_name(int nid); + +/* EC_KEY_free frees all the data owned by |key| and |key| itself. */ +OPENSSL_EXPORT void EC_KEY_free(EC_KEY *key); + +/* EC_KEY_copy sets |dst| equal to |src| and returns |dst| or NULL on error. */ +OPENSSL_EXPORT EC_KEY *EC_KEY_copy(EC_KEY *dst, const EC_KEY *src); + +/* EC_KEY_dup returns a fresh copy of |src| or NULL on error. */ +OPENSSL_EXPORT EC_KEY *EC_KEY_dup(const EC_KEY *src); + +/* EC_KEY_up_ref increases the reference count of |key|. It returns one on + * success and zero otherwise. */ +OPENSSL_EXPORT int EC_KEY_up_ref(EC_KEY *key); + +/* EC_KEY_is_opaque returns one if |key| is opaque and doesn't expose its key + * material. Otherwise it return zero. */ +OPENSSL_EXPORT int EC_KEY_is_opaque(const EC_KEY *key); + +/* EC_KEY_get0_group returns a pointer to the |EC_GROUP| object inside |key|. */ +OPENSSL_EXPORT const EC_GROUP *EC_KEY_get0_group(const EC_KEY *key); + +/* EC_KEY_set_group sets the |EC_GROUP| object that |key| will use to |group|. + * It returns one on success and zero otherwise. */ +OPENSSL_EXPORT int EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group); + +/* EC_KEY_get0_private_key returns a pointer to the private key inside |key|. */ +OPENSSL_EXPORT const BIGNUM *EC_KEY_get0_private_key(const EC_KEY *key); + +/* EC_KEY_set_private_key sets the private key of |key| to |priv|. It returns + * one on success and zero otherwise. */ +OPENSSL_EXPORT int EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *prv); + +/* EC_KEY_get0_public_key returns a pointer to the public key point inside + * |key|. */ +OPENSSL_EXPORT const EC_POINT *EC_KEY_get0_public_key(const EC_KEY *key); + +/* EC_KEY_set_public_key sets the public key of |key| to |pub|, by copying it. + * It returns one on success and zero otherwise. */ +OPENSSL_EXPORT int EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub); + +#define EC_PKEY_NO_PARAMETERS 0x001 +#define EC_PKEY_NO_PUBKEY 0x002 + +/* EC_KEY_get_enc_flags returns the encoding flags for |key|, which is a + * bitwise-OR of |EC_PKEY_*| values. */ +OPENSSL_EXPORT unsigned EC_KEY_get_enc_flags(const EC_KEY *key); + +/* EC_KEY_set_enc_flags sets the encoding flags for |key|, which is a + * bitwise-OR of |EC_PKEY_*| values. */ +OPENSSL_EXPORT void EC_KEY_set_enc_flags(EC_KEY *key, unsigned flags); + +/* EC_KEY_get_conv_form returns the conversation form that will be used by + * |key|. */ +OPENSSL_EXPORT point_conversion_form_t EC_KEY_get_conv_form(const EC_KEY *key); + +/* EC_KEY_set_conv_form sets the conversion form to be used by |key|. */ +OPENSSL_EXPORT void EC_KEY_set_conv_form(EC_KEY *key, + point_conversion_form_t cform); + +/* EC_KEY_check_key performs several checks on |key| (possibly including an + * expensive check that the public key is in the primary subgroup). It returns + * one if all checks pass and zero otherwise. If it returns zero then detail + * about the problem can be found on the error stack. */ +OPENSSL_EXPORT int EC_KEY_check_key(const EC_KEY *key); + +/* EC_KEY_set_public_key_affine_coordinates sets the public key in |key| to + * (|x|, |y|). It returns one on success and zero otherwise. */ +OPENSSL_EXPORT int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, + BIGNUM *x, + BIGNUM *y); + + +/* Key generation. */ + +/* EC_KEY_generate_key generates a random, private key, calculates the + * corresponding public key and stores both in |key|. It returns one on success + * or zero otherwise. */ +OPENSSL_EXPORT int EC_KEY_generate_key(EC_KEY *key); + + +/* Serialisation. */ + +/* EC_KEY_parse_private_key parses a DER-encoded ECPrivateKey structure (RFC + * 5915) from |cbs| and advances |cbs|. It returns a newly-allocated |EC_KEY| or + * NULL on error. If |group| is non-null, the parameters field of the + * ECPrivateKey may be omitted (but must match |group| if present). Otherwise, + * the parameters field is required. */ +OPENSSL_EXPORT EC_KEY *EC_KEY_parse_private_key(CBS *cbs, + const EC_GROUP *group); + +/* EC_KEY_marshal_private_key marshals |key| as a DER-encoded ECPrivateKey + * structure (RFC 5915) and appends the result to |cbb|. It returns one on + * success and zero on failure. |enc_flags| is a combination of |EC_PKEY_*| + * values and controls whether corresponding fields are omitted. */ +OPENSSL_EXPORT int EC_KEY_marshal_private_key(CBB *cbb, const EC_KEY *key, + unsigned enc_flags); + +/* EC_KEY_parse_curve_name parses a DER-encoded OBJECT IDENTIFIER as a curve + * name from |cbs| and advances |cbs|. It returns a newly-allocated |EC_GROUP| + * or NULL on error. */ +OPENSSL_EXPORT EC_GROUP *EC_KEY_parse_curve_name(CBS *cbs); + +/* EC_KEY_marshal_curve_name marshals |group| as a DER-encoded OBJECT IDENTIFIER + * and appends the result to |cbb|. It returns one on success and zero on + * failure. */ +OPENSSL_EXPORT int EC_KEY_marshal_curve_name(CBB *cbb, const EC_GROUP *group); + +/* EC_KEY_parse_parameters parses a DER-encoded ECParameters structure (RFC + * 5480) from |cbs| and advances |cbs|. It returns a newly-allocated |EC_GROUP| + * or NULL on error. It supports the namedCurve and specifiedCurve options, but + * use of specifiedCurve is deprecated. Use |EC_KEY_parse_curve_name| + * instead. */ +OPENSSL_EXPORT EC_GROUP *EC_KEY_parse_parameters(CBS *cbs); + + +/* ex_data functions. + * + * These functions are wrappers. See |ex_data.h| for details. */ + +OPENSSL_EXPORT int EC_KEY_get_ex_new_index(long argl, void *argp, + CRYPTO_EX_unused *unused, + CRYPTO_EX_dup *dup_func, + CRYPTO_EX_free *free_func); +OPENSSL_EXPORT int EC_KEY_set_ex_data(EC_KEY *r, int idx, void *arg); +OPENSSL_EXPORT void *EC_KEY_get_ex_data(const EC_KEY *r, int idx); + + +/* ECDSA method. */ + +/* ECDSA_FLAG_OPAQUE specifies that this ECDSA_METHOD does not expose its key + * material. This may be set if, for instance, it is wrapping some other crypto + * API, like a platform key store. */ +#define ECDSA_FLAG_OPAQUE 1 + +/* ecdsa_method_st is a structure of function pointers for implementing ECDSA. + * See engine.h. */ +struct ecdsa_method_st { + struct openssl_method_common_st common; + + void *app_data; + + int (*init)(EC_KEY *key); + int (*finish)(EC_KEY *key); + + /* group_order_size returns the number of bytes needed to represent the order + * of the group. This is used to calculate the maximum size of an ECDSA + * signature in |ECDSA_size|. */ + size_t (*group_order_size)(const EC_KEY *key); + + /* sign matches the arguments and behaviour of |ECDSA_sign|. */ + int (*sign)(const uint8_t *digest, size_t digest_len, uint8_t *sig, + unsigned int *sig_len, EC_KEY *eckey); + + /* Ignored. Set this to NULL. */ + int (*verify)(const uint8_t *digest, size_t digest_len, const uint8_t *sig, + size_t sig_len, EC_KEY *eckey); + + int flags; +}; + + +/* Deprecated functions. */ + +/* EC_KEY_set_asn1_flag does nothing. */ +OPENSSL_EXPORT void EC_KEY_set_asn1_flag(EC_KEY *key, int flag); + +/* d2i_ECPrivateKey parses an ASN.1, DER-encoded, private key from |len| bytes + * at |*inp|. If |out_key| is not NULL then, on exit, a pointer to the result + * is in |*out_key|. Note that, even if |*out_key| is already non-NULL on entry, + * it * will not be written to. Rather, a fresh |EC_KEY| is allocated and the + * previous * one is freed. On successful exit, |*inp| is advanced past the DER + * structure. It returns the result or NULL on error. + * + * On input, if |*out_key| is non-NULL and has a group configured, the + * parameters field may be omitted but must match that group if present. + * + * Use |EC_KEY_parse_private_key| instead. */ +OPENSSL_EXPORT EC_KEY *d2i_ECPrivateKey(EC_KEY **out_key, const uint8_t **inp, + long len); + +/* i2d_ECPrivateKey marshals an EC private key from |key| to an ASN.1, DER + * structure. If |outp| is not NULL then the result is written to |*outp| and + * |*outp| is advanced just past the output. It returns the number of bytes in + * the result, whether written or not, or a negative value on error. + * + * Use |EC_KEY_marshal_private_key| instead. */ +OPENSSL_EXPORT int i2d_ECPrivateKey(const EC_KEY *key, uint8_t **outp); + +/* d2i_ECParameters parses an ASN.1, DER-encoded, set of EC parameters from + * |len| bytes at |*inp|. If |out_key| is not NULL then, on exit, a pointer to + * the result is in |*out_key|. Note that, even if |*out_key| is already + * non-NULL on entry, it will not be written to. Rather, a fresh |EC_KEY| is + * allocated and the previous one is freed. On successful exit, |*inp| is + * advanced past the DER structure. It returns the result or NULL on error. + * + * Use |EC_KEY_parse_parameters| or |EC_KEY_parse_curve_name| instead. */ +OPENSSL_EXPORT EC_KEY *d2i_ECParameters(EC_KEY **out_key, const uint8_t **inp, + long len); + +/* i2d_ECParameters marshals EC parameters from |key| to an ASN.1, DER + * structure. If |outp| is not NULL then the result is written to |*outp| and + * |*outp| is advanced just past the output. It returns the number of bytes in + * the result, whether written or not, or a negative value on error. + * + * Use |EC_KEY_marshal_curve_name| instead. */ +OPENSSL_EXPORT int i2d_ECParameters(const EC_KEY *key, uint8_t **outp); + +/* o2i_ECPublicKey parses an EC point from |len| bytes at |*inp| into + * |*out_key|. Note that this differs from the d2i format in that |*out_key| + * must be non-NULL with a group set. On successful exit, |*inp| is advanced by + * |len| bytes. It returns |*out_key| or NULL on error. + * + * Use |EC_POINT_oct2point| instead. */ +OPENSSL_EXPORT EC_KEY *o2i_ECPublicKey(EC_KEY **out_key, const uint8_t **inp, + long len); + +/* i2o_ECPublicKey marshals an EC point from |key|. If |outp| is not NULL then + * the result is written to |*outp| and |*outp| is advanced just past the + * output. It returns the number of bytes in the result, whether written or + * not, or a negative value on error. + * + * Use |EC_POINT_point2cbb| instead. */ +OPENSSL_EXPORT int i2o_ECPublicKey(const EC_KEY *key, unsigned char **outp); + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_EC_KEY_H */ diff --git a/external/boringssl/include/openssl/ecdh.h b/external/boringssl/include/openssl/ecdh.h new file mode 100644 index 0000000000..5fe3ae9925 --- /dev/null +++ b/external/boringssl/include/openssl/ecdh.h @@ -0,0 +1,102 @@ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * + * The Elliptic Curve Public-Key Crypto Library (ECC Code) included + * herein is developed by SUN MICROSYSTEMS, INC., and is contributed + * to the OpenSSL project. + * + * The ECC Code is licensed pursuant to the OpenSSL open source + * license provided below. + * + * The ECDH software is originally written by Douglas Stebila of + * Sun Microsystems Laboratories. + * + */ +/* ==================================================================== + * Copyright (c) 2000-2002 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#ifndef OPENSSL_HEADER_ECDH_H +#define OPENSSL_HEADER_ECDH_H + +#include + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* Elliptic curve Diffie-Hellman. */ + + +/* ECDH_compute_key calculates the shared key between |pub_key| and |priv_key|. + * If |kdf| is not NULL, then it is called with the bytes of the shared key and + * the parameter |out|. When |kdf| returns, the value of |*outlen| becomes the + * return value. Otherwise, as many bytes of the shared key as will fit are + * copied directly to, at most, |outlen| bytes at |out|. It returns the number + * of bytes written to |out|, or -1 on error. */ +OPENSSL_EXPORT int ECDH_compute_key(void *out, size_t outlen, + const EC_POINT *pub_key, EC_KEY *priv_key, + void *(*kdf)(const void *in, size_t inlen, + void *out, size_t *outlen)); + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#define ECDH_R_KDF_FAILED 100 +#define ECDH_R_NO_PRIVATE_VALUE 101 +#define ECDH_R_POINT_ARITHMETIC_FAILURE 102 + +#endif /* OPENSSL_HEADER_ECDH_H */ diff --git a/external/boringssl/include/openssl/ecdsa.h b/external/boringssl/include/openssl/ecdsa.h new file mode 100644 index 0000000000..a060eab349 --- /dev/null +++ b/external/boringssl/include/openssl/ecdsa.h @@ -0,0 +1,206 @@ +/* ==================================================================== + * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#ifndef OPENSSL_HEADER_ECDSA_H +#define OPENSSL_HEADER_ECDSA_H + +#include + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* ECDSA contains functions for signing and verifying with the Digital Signature + * Algorithm over elliptic curves. */ + + +/* Signing and verifing. */ + +/* ECDSA_sign signs |digest_len| bytes from |digest| with |key| and writes the + * resulting signature to |sig|, which must have |ECDSA_size(key)| bytes of + * space. On successful exit, |*sig_len| is set to the actual number of bytes + * written. The |type| argument should be zero. It returns one on success and + * zero otherwise. */ +OPENSSL_EXPORT int ECDSA_sign(int type, const uint8_t *digest, + size_t digest_len, uint8_t *sig, + unsigned int *sig_len, EC_KEY *key); + +/* ECDSA_verify verifies that |sig_len| bytes from |sig| constitute a valid + * signature by |key| of |digest|. (The |type| argument should be zero.) It + * returns one on success or zero if the signature is invalid or an error + * occured. */ +OPENSSL_EXPORT int ECDSA_verify(int type, const uint8_t *digest, + size_t digest_len, const uint8_t *sig, + size_t sig_len, EC_KEY *key); + +/* ECDSA_size returns the maximum size of an ECDSA signature using |key|. It + * returns zero on error. */ +OPENSSL_EXPORT size_t ECDSA_size(const EC_KEY *key); + + +/* Low-level signing and verification. + * + * Low-level functions handle signatures as |ECDSA_SIG| structures which allow + * the two values in an ECDSA signature to be handled separately. */ + +struct ecdsa_sig_st { + BIGNUM *r; + BIGNUM *s; +}; + +/* ECDSA_SIG_new returns a fresh |ECDSA_SIG| structure or NULL on error. */ +OPENSSL_EXPORT ECDSA_SIG *ECDSA_SIG_new(void); + +/* ECDSA_SIG_free frees |sig| its member |BIGNUM|s. */ +OPENSSL_EXPORT void ECDSA_SIG_free(ECDSA_SIG *sig); + +/* ECDSA_do_sign signs |digest_len| bytes from |digest| with |key| and returns + * the resulting signature structure, or NULL on error. */ +OPENSSL_EXPORT ECDSA_SIG *ECDSA_do_sign(const uint8_t *digest, + size_t digest_len, EC_KEY *key); + +/* ECDSA_do_verify verifies that |sig| constitutes a valid signature by |key| + * of |digest|. It returns one on success or zero if the signature is invalid + * or on error. */ +OPENSSL_EXPORT int ECDSA_do_verify(const uint8_t *digest, size_t digest_len, + const ECDSA_SIG *sig, EC_KEY *key); + + +/* Signing with precomputation. + * + * Parts of the ECDSA signature can be independent of the message to be signed + * thus it's possible to precompute them and reduce the signing latency. + * + * TODO(fork): remove support for this as it cannot support safe-randomness. */ + +/* ECDSA_sign_setup precomputes parts of an ECDSA signing operation. It sets + * |*kinv| and |*rp| to the precomputed values and uses the |ctx| argument, if + * not NULL. It returns one on success and zero otherwise. */ +OPENSSL_EXPORT int ECDSA_sign_setup(EC_KEY *eckey, BN_CTX *ctx, BIGNUM **kinv, + BIGNUM **rp); + +/* ECDSA_do_sign_ex is the same as |ECDSA_do_sign| but takes precomputed values + * as generated by |ECDSA_sign_setup|. */ +OPENSSL_EXPORT ECDSA_SIG *ECDSA_do_sign_ex(const uint8_t *digest, + size_t digest_len, + const BIGNUM *kinv, const BIGNUM *rp, + EC_KEY *eckey); + +/* ECDSA_sign_ex is the same as |ECDSA_sign| but takes precomputed values as + * generated by |ECDSA_sign_setup|. */ +OPENSSL_EXPORT int ECDSA_sign_ex(int type, const uint8_t *digest, + size_t digest_len, uint8_t *sig, + unsigned int *sig_len, const BIGNUM *kinv, + const BIGNUM *rp, EC_KEY *eckey); + + +/* ASN.1 functions. */ + +/* ECDSA_SIG_parse parses a DER-encoded ECDSA-Sig-Value structure from |cbs| and + * advances |cbs|. It returns a newly-allocated |ECDSA_SIG| or NULL on error. */ +OPENSSL_EXPORT ECDSA_SIG *ECDSA_SIG_parse(CBS *cbs); + +/* ECDSA_SIG_from_bytes parses |in| as a DER-encoded ECDSA-Sig-Value structure. + * It returns a newly-allocated |ECDSA_SIG| structure or NULL on error. */ +OPENSSL_EXPORT ECDSA_SIG *ECDSA_SIG_from_bytes(const uint8_t *in, + size_t in_len); + +/* ECDSA_SIG_marshal marshals |sig| as a DER-encoded ECDSA-Sig-Value and appends + * the result to |cbb|. It returns one on success and zero on error. */ +OPENSSL_EXPORT int ECDSA_SIG_marshal(CBB *cbb, const ECDSA_SIG *sig); + +/* ECDSA_SIG_to_bytes marshals |sig| as a DER-encoded ECDSA-Sig-Value and, on + * success, sets |*out_bytes| to a newly allocated buffer containing the result + * and returns one. Otherwise, it returns zero. The result should be freed with + * |OPENSSL_free|. */ +OPENSSL_EXPORT int ECDSA_SIG_to_bytes(uint8_t **out_bytes, size_t *out_len, + const ECDSA_SIG *sig); + +/* ECDSA_SIG_max_len returns the maximum length of a DER-encoded ECDSA-Sig-Value + * structure for a group whose order is represented in |order_len| bytes, or + * zero on overflow. */ +OPENSSL_EXPORT size_t ECDSA_SIG_max_len(size_t order_len); + + +/* Deprecated functions. */ + +/* d2i_ECDSA_SIG parses an ASN.1, DER-encoded, signature from |len| bytes at + * |*inp|. If |out| is not NULL then, on exit, a pointer to the result is in + * |*out|. Note that, even if |*out| is already non-NULL on entry, it will not + * be written to. Rather, a fresh |ECDSA_SIG| is allocated and the previous one + * is freed. On successful exit, |*inp| is advanced past the DER structure. It + * returns the result or NULL on error. */ +OPENSSL_EXPORT ECDSA_SIG *d2i_ECDSA_SIG(ECDSA_SIG **out, const uint8_t **inp, + long len); + +/* i2d_ECDSA_SIG marshals a signature from |sig| to an ASN.1, DER + * structure. If |outp| is not NULL then the result is written to |*outp| and + * |*outp| is advanced just past the output. It returns the number of bytes in + * the result, whether written or not, or a negative value on error. */ +OPENSSL_EXPORT int i2d_ECDSA_SIG(const ECDSA_SIG *sig, uint8_t **outp); + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#define ECDSA_R_BAD_SIGNATURE 100 +#define ECDSA_R_MISSING_PARAMETERS 101 +#define ECDSA_R_NEED_NEW_SETUP_VALUES 102 +#define ECDSA_R_NOT_IMPLEMENTED 103 +#define ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED 104 +#define ECDSA_R_ENCODE_ERROR 105 + +#endif /* OPENSSL_HEADER_ECDSA_H */ diff --git a/external/boringssl/include/openssl/engine.h b/external/boringssl/include/openssl/engine.h new file mode 100644 index 0000000000..128a2ae12c --- /dev/null +++ b/external/boringssl/include/openssl/engine.h @@ -0,0 +1,98 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_ENGINE_H +#define OPENSSL_HEADER_ENGINE_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* Engines are collections of methods. Methods are tables of function pointers, + * defined for certain algorithms, that allow operations on those algorithms to + * be overridden via a callback. This can be used, for example, to implement an + * RSA* that forwards operations to a hardware module. + * + * Methods are reference counted but |ENGINE|s are not. When creating a method, + * you should zero the whole structure and fill in the function pointers that + * you wish before setting it on an |ENGINE|. Any functions pointers that + * are NULL indicate that the default behaviour should be used. */ + + +/* Allocation and destruction. */ + +/* ENGINE_new returns an empty ENGINE that uses the default method for all + * algorithms. */ +OPENSSL_EXPORT ENGINE *ENGINE_new(void); + +/* ENGINE_free decrements the reference counts for all methods linked from + * |engine| and frees |engine| itself. */ +OPENSSL_EXPORT void ENGINE_free(ENGINE *engine); + + +/* Method accessors. + * + * Method accessors take a method pointer and the size of the structure. The + * size allows for ABI compatibility in the case that the method structure is + * extended with extra elements at the end. Methods are always copied by the + * set functions. + * + * Set functions return one on success and zero on allocation failure. */ + +OPENSSL_EXPORT int ENGINE_set_RSA_method(ENGINE *engine, + const RSA_METHOD *method, + size_t method_size); +OPENSSL_EXPORT RSA_METHOD *ENGINE_get_RSA_method(const ENGINE *engine); + +OPENSSL_EXPORT int ENGINE_set_ECDSA_method(ENGINE *engine, + const ECDSA_METHOD *method, + size_t method_size); +OPENSSL_EXPORT ECDSA_METHOD *ENGINE_get_ECDSA_method(const ENGINE *engine); + + +/* Generic method functions. + * + * These functions take a void* type but actually operate on all method + * structures. */ + +/* METHOD_ref increments the reference count of |method|. This is a no-op for + * now because all methods are currently static. */ +void METHOD_ref(void *method); + +/* METHOD_unref decrements the reference count of |method| and frees it if the + * reference count drops to zero. This is a no-op for now because all methods + * are currently static. */ +void METHOD_unref(void *method); + + +/* Private functions. */ + +/* openssl_method_common_st contains the common part of all method structures. + * This must be the first member of all method structures. */ +struct openssl_method_common_st { + int references; /* dummy – not used. */ + char is_static; +}; + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#define ENGINE_R_OPERATION_NOT_SUPPORTED 100 + +#endif /* OPENSSL_HEADER_ENGINE_H */ diff --git a/external/boringssl/include/openssl/err.h b/external/boringssl/include/openssl/err.h new file mode 100644 index 0000000000..cac50e0fb3 --- /dev/null +++ b/external/boringssl/include/openssl/err.h @@ -0,0 +1,488 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#ifndef OPENSSL_HEADER_ERR_H +#define OPENSSL_HEADER_ERR_H + +#include + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* Error queue handling functions. + * + * Errors in OpenSSL are generally signalled by the return value of a function. + * When a function fails it may add an entry to a per-thread error queue, + * which is managed by the functions in this header. + * + * Each error contains: + * 1) The library (i.e. ec, pem, rsa) which created it. + * 2) The file and line number of the call that added the error. + * 3) A pointer to some error specific data, which may be NULL. + * + * The library identifier and reason code are packed in a uint32_t and there + * exist various functions for unpacking it. + * + * The typical behaviour is that an error will occur deep in a call queue and + * that code will push an error onto the error queue. As the error queue + * unwinds, other functions will push their own errors. Thus, the "least + * recent" error is the most specific and the other errors will provide a + * backtrace of sorts. */ + + +/* Startup and shutdown. */ + +/* ERR_load_BIO_strings does nothing. + * + * TODO(fork): remove. libjingle calls this. */ +OPENSSL_EXPORT void ERR_load_BIO_strings(void); + +/* ERR_load_ERR_strings does nothing. */ +OPENSSL_EXPORT void ERR_load_ERR_strings(void); + +/* ERR_load_crypto_strings does nothing. */ +OPENSSL_EXPORT void ERR_load_crypto_strings(void); + +/* ERR_free_strings does nothing. */ +OPENSSL_EXPORT void ERR_free_strings(void); + + +/* Reading and formatting errors. */ + +/* ERR_get_error gets the packed error code for the least recent error and + * removes that error from the queue. If there are no errors in the queue then + * it returns zero. */ +OPENSSL_EXPORT uint32_t ERR_get_error(void); + +/* ERR_get_error_line acts like |ERR_get_error|, except that the file and line + * number of the call that added the error are also returned. */ +OPENSSL_EXPORT uint32_t ERR_get_error_line(const char **file, int *line); + +/* ERR_get_error_line_data acts like |ERR_get_error_line|, but also returns the + * error-specific data pointer and flags. The flags are a bitwise-OR of + * |ERR_FLAG_*| values. The error-specific data is owned by the error queue + * and the pointer becomes invalid after the next call that affects the same + * thread's error queue. If |*flags| contains |ERR_FLAG_STRING| then |*data| is + * human-readable. */ +OPENSSL_EXPORT uint32_t ERR_get_error_line_data(const char **file, int *line, + const char **data, int *flags); + +/* The "peek" functions act like the |ERR_get_error| functions, above, but they + * do not remove the error from the queue. */ +OPENSSL_EXPORT uint32_t ERR_peek_error(void); +OPENSSL_EXPORT uint32_t ERR_peek_error_line(const char **file, int *line); +OPENSSL_EXPORT uint32_t ERR_peek_error_line_data(const char **file, int *line, + const char **data, int *flags); + +/* The "peek last" functions act like the "peek" functions, above, except that + * they return the most recent error. */ +OPENSSL_EXPORT uint32_t ERR_peek_last_error(void); +OPENSSL_EXPORT uint32_t ERR_peek_last_error_line(const char **file, int *line); +OPENSSL_EXPORT uint32_t ERR_peek_last_error_line_data(const char **file, + int *line, + const char **data, + int *flags); + +/* ERR_error_string generates a human-readable string representing + * |packed_error|, places it at |buf| (which must be at least + * ERR_ERROR_STRING_BUF_LEN bytes long) and returns |buf|. If |buf| is NULL, + * the error string is placed in a static buffer which is returned. (The static + * buffer may be overridden by concurrent calls in other threads so this form + * is deprecated.) + * + * The string will have the following format: + * + * error:[error code]:[library name]:OPENSSL_internal:[reason string] + * + * error code is an 8 digit hexadecimal number; library name and reason string + * are ASCII text. + * + * TODO(fork): remove in favour of |ERR_error_string_n|. */ +OPENSSL_EXPORT char *ERR_error_string(uint32_t packed_error, char *buf); +#define ERR_ERROR_STRING_BUF_LEN 256 + +/* ERR_error_string_n is a variant of |ERR_error_string| that writes at most + * len characters (including the terminating NUL) and truncates the string if + * necessary. If |len| is greater than zero then |buf| is always NUL + * terminated. */ +OPENSSL_EXPORT void ERR_error_string_n(uint32_t packed_error, char *buf, + size_t len); + +/* ERR_lib_error_string returns a string representation of the library that + * generated |packed_error|. */ +OPENSSL_EXPORT const char *ERR_lib_error_string(uint32_t packed_error); + +/* ERR_reason_error_string returns a string representation of the reason for + * |packed_error|. */ +OPENSSL_EXPORT const char *ERR_reason_error_string(uint32_t packed_error); + +/* ERR_print_errors_callback_t is the type of a function used by + * |ERR_print_errors_cb|. It takes a pointer to a human readable string (and + * its length) that describes an entry in the error queue. The |ctx| argument + * is an opaque pointer given to |ERR_print_errors_cb|. + * + * It should return one on success or zero on error, which will stop the + * iteration over the error queue. */ +typedef int (*ERR_print_errors_callback_t)(const char *str, size_t len, + void *ctx); + +/* ERR_print_errors_cb calls |callback| with a string representation of each + * error in the current thread's error queue, from the least recent to the most + * recent error. + * + * The string will have the following format (which differs from + * |ERR_error_string|): + * + * [thread id]:error:[error code]:[library name]:OPENSSL_internal: + * [reason string]:[file]:[line number]:[optional string data] + * + * (All in one line.) + * + * The callback can return one to continue the iteration or zero to stop it. + * The |ctx| argument is an opaque value that is passed through to the + * callback. */ +OPENSSL_EXPORT void ERR_print_errors_cb(ERR_print_errors_callback_t callback, + void *ctx); + +/* ERR_print_errors_fp prints the current contents of the error stack to |file| + * using human readable strings where possible. */ +OPENSSL_EXPORT void ERR_print_errors_fp(FILE *file); + + +/* Clearing errors. */ + +/* ERR_clear_error clears the error queue for the current thread. */ +OPENSSL_EXPORT void ERR_clear_error(void); + +/* ERR_remove_thread_state clears the error queue for the current thread if + * |tid| is NULL. Otherwise it calls |assert(0)|, because it's no longer + * possible to delete the error queue for other threads. + * + * Error queues are thread-local data and are deleted automatically. You do not + * need to call this function. Use |ERR_clear_error|. */ +OPENSSL_EXPORT void ERR_remove_thread_state(const CRYPTO_THREADID *tid); + + +/* Custom errors. */ + +/* ERR_get_next_error_library returns a value suitable for passing as the + * |library| argument to |ERR_put_error|. This is intended for code that wishes + * to push its own, non-standard errors to the error queue. */ +OPENSSL_EXPORT int ERR_get_next_error_library(void); + + +/* Deprecated functions. */ + +/* ERR_remove_state calls |ERR_clear_error|. */ +OPENSSL_EXPORT void ERR_remove_state(unsigned long pid); + +/* ERR_func_error_string returns the string "OPENSSL_internal". */ +OPENSSL_EXPORT const char *ERR_func_error_string(uint32_t packed_error); + + +/* Private functions. */ + +/* ERR_clear_system_error clears the system's error value (i.e. errno). */ +OPENSSL_EXPORT void ERR_clear_system_error(void); + +/* OPENSSL_PUT_ERROR is used by OpenSSL code to add an error to the error + * queue. */ +#define OPENSSL_PUT_ERROR(library, reason) \ + ERR_put_error(ERR_LIB_##library, 0, reason, __FILE__, __LINE__) + +/* OPENSSL_PUT_SYSTEM_ERROR is used by OpenSSL code to add an error from the + * operating system to the error queue. + * TODO(fork): include errno. */ +#define OPENSSL_PUT_SYSTEM_ERROR() \ + ERR_put_error(ERR_LIB_SYS, 0, 0, __FILE__, __LINE__); + +/* ERR_put_error adds an error to the error queue, dropping the least recent + * error if neccessary for space reasons. */ +OPENSSL_EXPORT void ERR_put_error(int library, int unused, int reason, + const char *file, unsigned line); + +/* ERR_add_error_data takes a variable number (|count|) of const char* + * pointers, concatenates them and sets the result as the data on the most + * recent error. */ +OPENSSL_EXPORT void ERR_add_error_data(unsigned count, ...); + +/* ERR_add_error_dataf takes a printf-style format and arguments, and sets the + * result as the data on the most recent error. */ +OPENSSL_EXPORT void ERR_add_error_dataf(const char *format, ...) + OPENSSL_PRINTF_FORMAT_FUNC(1, 2); + +/* ERR_set_mark "marks" the most recent error for use with |ERR_pop_to_mark|. + * It returns one if an error was marked and zero if there are no errors. */ +OPENSSL_EXPORT int ERR_set_mark(void); + +/* ERR_pop_to_mark removes errors from the most recent to the least recent + * until (and not including) a "marked" error. It returns zero if no marked + * error was found (and thus all errors were removed) and one otherwise. Errors + * are marked using |ERR_set_mark|. */ +OPENSSL_EXPORT int ERR_pop_to_mark(void); + +struct err_error_st { + /* file contains the filename where the error occured. */ + const char *file; + /* data contains optional data. It must be freed with |OPENSSL_free| if + * |flags&ERR_FLAG_MALLOCED|. */ + char *data; + /* packed contains the error library and reason, as packed by ERR_PACK. */ + uint32_t packed; + /* line contains the line number where the error occured. */ + uint16_t line; + /* flags contains a bitwise-OR of ERR_FLAG_* values. */ + uint8_t flags; +}; + +/* ERR_FLAG_STRING means that the |data| member is a NUL-terminated string that + * can be printed. */ +#define ERR_FLAG_STRING 1 +/* ERR_TXT_STRING is provided for compatibility with code that assumes that + * it's using OpenSSL. */ +#define ERR_TXT_STRING ERR_FLAG_STRING + +/* ERR_FLAG_PUBLIC_MASK is applied to the flags field before it is returned + * from functions like |ERR_get_error_line_data|. */ +#define ERR_FLAG_PUBLIC_MASK 0xf + +/* The following flag values are internal and are masked when flags are + * returned from functions like |ERR_get_error_line_data|. */ + +/* ERR_FLAG_MALLOCED means the the |data| member must be freed when no longer + * needed. */ +#define ERR_FLAG_MALLOCED 16 +/* ERR_FLAG_MARK is used to indicate a reversion point in the queue. See + * |ERR_pop_to_mark|. */ +#define ERR_FLAG_MARK 32 + +/* ERR_NUM_ERRORS is the limit of the number of errors in the queue. */ +#define ERR_NUM_ERRORS 16 + +/* err_state_st (aka |ERR_STATE|) contains the per-thread, error queue. */ +typedef struct err_state_st { + /* errors contains the ERR_NUM_ERRORS most recent errors, organised as a ring + * buffer. */ + struct err_error_st errors[ERR_NUM_ERRORS]; + /* top contains the index one past the most recent error. If |top| equals + * |bottom| then the queue is empty. */ + unsigned top; + /* bottom contains the index of the last error in the queue. */ + unsigned bottom; + + /* to_free, if not NULL, contains a pointer owned by this structure that was + * previously a |data| pointer of one of the elements of |errors|. */ + void *to_free; +} ERR_STATE; + +enum { + ERR_LIB_NONE = 1, + ERR_LIB_SYS, + ERR_LIB_BN, + ERR_LIB_RSA, + ERR_LIB_DH, + ERR_LIB_EVP, + ERR_LIB_BUF, + ERR_LIB_OBJ, + ERR_LIB_PEM, + ERR_LIB_DSA, + ERR_LIB_X509, + ERR_LIB_ASN1, + ERR_LIB_CONF, + ERR_LIB_CRYPTO, + ERR_LIB_EC, + ERR_LIB_SSL, + ERR_LIB_BIO, + ERR_LIB_PKCS7, + ERR_LIB_PKCS8, + ERR_LIB_X509V3, + ERR_LIB_RAND, + ERR_LIB_ENGINE, + ERR_LIB_OCSP, + ERR_LIB_UI, + ERR_LIB_COMP, + ERR_LIB_ECDSA, + ERR_LIB_ECDH, + ERR_LIB_HMAC, + ERR_LIB_DIGEST, + ERR_LIB_CIPHER, + ERR_LIB_HKDF, + ERR_LIB_USER, + ERR_NUM_LIBS +}; + +#define ERR_R_SYS_LIB ERR_LIB_SYS +#define ERR_R_BN_LIB ERR_LIB_BN +#define ERR_R_RSA_LIB ERR_LIB_RSA +#define ERR_R_DH_LIB ERR_LIB_DH +#define ERR_R_EVP_LIB ERR_LIB_EVP +#define ERR_R_BUF_LIB ERR_LIB_BUF +#define ERR_R_OBJ_LIB ERR_LIB_OBJ +#define ERR_R_PEM_LIB ERR_LIB_PEM +#define ERR_R_DSA_LIB ERR_LIB_DSA +#define ERR_R_X509_LIB ERR_LIB_X509 +#define ERR_R_ASN1_LIB ERR_LIB_ASN1 +#define ERR_R_CONF_LIB ERR_LIB_CONF +#define ERR_R_CRYPTO_LIB ERR_LIB_CRYPTO +#define ERR_R_EC_LIB ERR_LIB_EC +#define ERR_R_SSL_LIB ERR_LIB_SSL +#define ERR_R_BIO_LIB ERR_LIB_BIO +#define ERR_R_PKCS7_LIB ERR_LIB_PKCS7 +#define ERR_R_PKCS8_LIB ERR_LIB_PKCS8 +#define ERR_R_X509V3_LIB ERR_LIB_X509V3 +#define ERR_R_RAND_LIB ERR_LIB_RAND +#define ERR_R_DSO_LIB ERR_LIB_DSO +#define ERR_R_ENGINE_LIB ERR_LIB_ENGINE +#define ERR_R_OCSP_LIB ERR_LIB_OCSP +#define ERR_R_UI_LIB ERR_LIB_UI +#define ERR_R_COMP_LIB ERR_LIB_COMP +#define ERR_R_ECDSA_LIB ERR_LIB_ECDSA +#define ERR_R_ECDH_LIB ERR_LIB_ECDH +#define ERR_R_STORE_LIB ERR_LIB_STORE +#define ERR_R_FIPS_LIB ERR_LIB_FIPS +#define ERR_R_CMS_LIB ERR_LIB_CMS +#define ERR_R_TS_LIB ERR_LIB_TS +#define ERR_R_HMAC_LIB ERR_LIB_HMAC +#define ERR_R_JPAKE_LIB ERR_LIB_JPAKE +#define ERR_R_USER_LIB ERR_LIB_USER +#define ERR_R_DIGEST_LIB ERR_LIB_DIGEST +#define ERR_R_CIPHER_LIB ERR_LIB_CIPHER +#define ERR_R_HKDF_LIB ERR_LIB_HKDF + +/* Global reasons. */ +#define ERR_R_FATAL 64 +#define ERR_R_MALLOC_FAILURE (1 | ERR_R_FATAL) +#define ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED (2 | ERR_R_FATAL) +#define ERR_R_PASSED_NULL_PARAMETER (3 | ERR_R_FATAL) +#define ERR_R_INTERNAL_ERROR (4 | ERR_R_FATAL) +#define ERR_R_OVERFLOW (5 | ERR_R_FATAL) + +#define ERR_PACK(lib, reason) \ + (((((uint32_t)lib) & 0xff) << 24) | ((((uint32_t)reason) & 0xfff))) + +#define ERR_GET_LIB(packed_error) ((int)(((packed_error) >> 24) & 0xff)) +#define ERR_GET_FUNC(packed_error) 0 +#define ERR_GET_REASON(packed_error) ((int)((packed_error) & 0xfff)) + +/* OPENSSL_DECLARE_ERROR_REASON is used by util/make_errors.h (which generates + * the error defines) to recognise that an additional reason value is needed. + * This is needed when the reason value is used outside of an + * |OPENSSL_PUT_ERROR| macro. The resulting define will be + * ${lib}_R_${reason}. */ +#define OPENSSL_DECLARE_ERROR_REASON(lib, reason) + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_ERR_H */ diff --git a/external/boringssl/include/openssl/evp.h b/external/boringssl/include/openssl/evp.h new file mode 100644 index 0000000000..54074073d8 --- /dev/null +++ b/external/boringssl/include/openssl/evp.h @@ -0,0 +1,783 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_EVP_H +#define OPENSSL_HEADER_EVP_H + +#include + +#include + +/* OpenSSL included digest and cipher functions in this header so we include + * them for users that still expect that. + * + * TODO(fork): clean up callers so that they include what they use. */ +#include +#include +#include +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* EVP abstracts over public/private key algorithms. */ + + +/* Public key objects. */ + +/* EVP_PKEY_new creates a new, empty public-key object and returns it or NULL + * on allocation failure. */ +OPENSSL_EXPORT EVP_PKEY *EVP_PKEY_new(void); + +/* EVP_PKEY_free frees all data referenced by |pkey| and then frees |pkey| + * itself. */ +OPENSSL_EXPORT void EVP_PKEY_free(EVP_PKEY *pkey); + +/* EVP_PKEY_up_ref increments the reference count of |pkey| and returns it. */ +OPENSSL_EXPORT EVP_PKEY *EVP_PKEY_up_ref(EVP_PKEY *pkey); + +/* EVP_PKEY_is_opaque returns one if |pkey| is opaque. Opaque keys are backed by + * custom implementations which do not expose key material and parameters. It is + * an error to attempt to duplicate, export, or compare an opaque key. */ +OPENSSL_EXPORT int EVP_PKEY_is_opaque(const EVP_PKEY *pkey); + +/* EVP_PKEY_supports_digest returns one if |pkey| supports digests of + * type |md|. This is intended for use with EVP_PKEYs backing custom + * implementations which can't sign all digests. */ +OPENSSL_EXPORT int EVP_PKEY_supports_digest(const EVP_PKEY *pkey, + const EVP_MD *md); + +/* EVP_PKEY_cmp compares |a| and |b| and returns one if they are equal, zero if + * not and a negative number on error. + * + * WARNING: this differs from the traditional return value of a "cmp" + * function. */ +OPENSSL_EXPORT int EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b); + +/* EVP_PKEY_copy_parameters sets the parameters of |to| to equal the parameters + * of |from|. It returns one on success and zero on error. */ +OPENSSL_EXPORT int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from); + +/* EVP_PKEY_missing_parameters returns one if |pkey| is missing needed + * parameters or zero if not, or if the algorithm doesn't take parameters. */ +OPENSSL_EXPORT int EVP_PKEY_missing_parameters(const EVP_PKEY *pkey); + +/* EVP_PKEY_size returns the maximum size, in bytes, of a signature signed by + * |pkey|. For an RSA key, this returns the number of bytes needed to represent + * the modulus. For an EC key, this returns the maximum size of a DER-encoded + * ECDSA signature. */ +OPENSSL_EXPORT int EVP_PKEY_size(const EVP_PKEY *pkey); + +/* EVP_PKEY_bits returns the "size", in bits, of |pkey|. For an RSA key, this + * returns the bit length of the modulus. For an EC key, this returns the bit + * length of the group order. */ +OPENSSL_EXPORT int EVP_PKEY_bits(EVP_PKEY *pkey); + +/* EVP_PKEY_id returns the type of |pkey|, which is one of the |EVP_PKEY_*| + * values. */ +OPENSSL_EXPORT int EVP_PKEY_id(const EVP_PKEY *pkey); + +/* EVP_PKEY_type returns |nid| if |nid| is a known key type and |NID_undef| + * otherwise. */ +OPENSSL_EXPORT int EVP_PKEY_type(int nid); + + +/* Getting and setting concrete public key types. + * + * The following functions get and set the underlying public key in an + * |EVP_PKEY| object. The |set1| functions take an additional reference to the + * underlying key and return one on success or zero on error. The |assign| + * functions adopt the caller's reference. The |get1| functions return a fresh + * reference to the underlying object or NULL if |pkey| is not of the correct + * type. The |get0| functions behave the same but return a non-owning + * pointer. */ + +OPENSSL_EXPORT int EVP_PKEY_set1_RSA(EVP_PKEY *pkey, RSA *key); +OPENSSL_EXPORT int EVP_PKEY_assign_RSA(EVP_PKEY *pkey, RSA *key); +OPENSSL_EXPORT RSA *EVP_PKEY_get0_RSA(EVP_PKEY *pkey); +OPENSSL_EXPORT RSA *EVP_PKEY_get1_RSA(EVP_PKEY *pkey); + +OPENSSL_EXPORT int EVP_PKEY_set1_DSA(EVP_PKEY *pkey, DSA *key); +OPENSSL_EXPORT int EVP_PKEY_assign_DSA(EVP_PKEY *pkey, DSA *key); +OPENSSL_EXPORT DSA *EVP_PKEY_get0_DSA(EVP_PKEY *pkey); +OPENSSL_EXPORT DSA *EVP_PKEY_get1_DSA(EVP_PKEY *pkey); + +OPENSSL_EXPORT int EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey, EC_KEY *key); +OPENSSL_EXPORT int EVP_PKEY_assign_EC_KEY(EVP_PKEY *pkey, EC_KEY *key); +OPENSSL_EXPORT EC_KEY *EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey); +OPENSSL_EXPORT EC_KEY *EVP_PKEY_get1_EC_KEY(EVP_PKEY *pkey); + +#define EVP_PKEY_NONE NID_undef +#define EVP_PKEY_RSA NID_rsaEncryption +#define EVP_PKEY_DSA NID_dsa +#define EVP_PKEY_EC NID_X9_62_id_ecPublicKey + +/* EVP_PKEY_assign sets the underlying key of |pkey| to |key|, which must be of + * the given type. The |type| argument should be one of the |EVP_PKEY_*| + * values. */ +OPENSSL_EXPORT int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key); + +/* EVP_PKEY_set_type sets the type of |pkey| to |type|, which should be one of + * the |EVP_PKEY_*| values. It returns one if sucessful or zero otherwise. If + * |pkey| is NULL, it simply reports whether the type is known. */ +OPENSSL_EXPORT int EVP_PKEY_set_type(EVP_PKEY *pkey, int type); + +/* EVP_PKEY_cmp_parameters compares the parameters of |a| and |b|. It returns + * one if they match, zero if not, or a negative number of on error. + * + * WARNING: the return value differs from the usual return value convention. */ +OPENSSL_EXPORT int EVP_PKEY_cmp_parameters(const EVP_PKEY *a, + const EVP_PKEY *b); + + +/* ASN.1 functions */ + +/* EVP_parse_public_key decodes a DER-encoded SubjectPublicKeyInfo structure + * (RFC 5280) from |cbs| and advances |cbs|. It returns a newly-allocated + * |EVP_PKEY| or NULL on error. + * + * The caller must check the type of the parsed public key to ensure it is + * suitable and validate other desired key properties such as RSA modulus size + * or EC curve. */ +OPENSSL_EXPORT EVP_PKEY *EVP_parse_public_key(CBS *cbs); + +/* EVP_marshal_public_key marshals |key| as a DER-encoded SubjectPublicKeyInfo + * structure (RFC 5280) and appends the result to |cbb|. It returns one on + * success and zero on error. */ +OPENSSL_EXPORT int EVP_marshal_public_key(CBB *cbb, const EVP_PKEY *key); + +/* EVP_parse_private_key decodes a DER-encoded PrivateKeyInfo structure (RFC + * 5208) from |cbs| and advances |cbs|. It returns a newly-allocated |EVP_PKEY| + * or NULL on error. + * + * The caller must check the type of the parsed private key to ensure it is + * suitable and validate other desired key properties such as RSA modulus size + * or EC curve. + * + * A PrivateKeyInfo ends with an optional set of attributes. These are not + * processed and so this function will silently ignore any trailing data in the + * structure. */ +OPENSSL_EXPORT EVP_PKEY *EVP_parse_private_key(CBS *cbs); + +/* EVP_marshal_private_key marshals |key| as a DER-encoded PrivateKeyInfo + * structure (RFC 5208) and appends the result to |cbb|. It returns one on + * success and zero on error. */ +OPENSSL_EXPORT int EVP_marshal_private_key(CBB *cbb, const EVP_PKEY *key); + + +/* Signing */ + +/* EVP_DigestSignInit sets up |ctx| for a signing operation with |type| and + * |pkey|. The |ctx| argument must have been initialised with + * |EVP_MD_CTX_init|. If |pctx| is not NULL, the |EVP_PKEY_CTX| of the signing + * operation will be written to |*pctx|; this can be used to set alternative + * signing options. + * + * It returns one on success, or zero on error. */ +OPENSSL_EXPORT int EVP_DigestSignInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, + const EVP_MD *type, ENGINE *e, + EVP_PKEY *pkey); + +/* EVP_DigestSignUpdate appends |len| bytes from |data| to the data which will + * be signed in |EVP_DigestSignFinal|. It returns one. */ +OPENSSL_EXPORT int EVP_DigestSignUpdate(EVP_MD_CTX *ctx, const void *data, + size_t len); + +/* EVP_DigestSignFinal signs the data that has been included by one or more + * calls to |EVP_DigestSignUpdate|. If |out_sig| is NULL then |*out_sig_len| is + * set to the maximum number of output bytes. Otherwise, on entry, + * |*out_sig_len| must contain the length of the |out_sig| buffer. If the call + * is successful, the signature is written to |out_sig| and |*out_sig_len| is + * set to its length. + * + * It returns one on success, or zero on error. */ +OPENSSL_EXPORT int EVP_DigestSignFinal(EVP_MD_CTX *ctx, uint8_t *out_sig, + size_t *out_sig_len); + + +/* Verifying */ + +/* EVP_DigestVerifyInit sets up |ctx| for a signature verification operation + * with |type| and |pkey|. The |ctx| argument must have been initialised with + * |EVP_MD_CTX_init|. If |pctx| is not NULL, the |EVP_PKEY_CTX| of the signing + * operation will be written to |*pctx|; this can be used to set alternative + * signing options. + * + * It returns one on success, or zero on error. */ +OPENSSL_EXPORT int EVP_DigestVerifyInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, + const EVP_MD *type, ENGINE *e, + EVP_PKEY *pkey); + +/* EVP_DigestVerifyUpdate appends |len| bytes from |data| to the data which + * will be verified by |EVP_DigestVerifyFinal|. It returns one. */ +OPENSSL_EXPORT int EVP_DigestVerifyUpdate(EVP_MD_CTX *ctx, const void *data, + size_t len); + +/* EVP_DigestVerifyFinal verifies that |sig_len| bytes of |sig| are a valid + * signature for the data that has been included by one or more calls to + * |EVP_DigestVerifyUpdate|. It returns one on success and zero otherwise. */ +OPENSSL_EXPORT int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const uint8_t *sig, + size_t sig_len); + + +/* Signing (old functions) */ + +/* EVP_SignInit_ex configures |ctx|, which must already have been initialised, + * for a fresh signing operation using the hash function |type|. It returns one + * on success and zero otherwise. + * + * (In order to initialise |ctx|, either obtain it initialised with + * |EVP_MD_CTX_create|, or use |EVP_MD_CTX_init|.) */ +OPENSSL_EXPORT int EVP_SignInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, + ENGINE *impl); + +/* EVP_SignInit is a deprecated version of |EVP_SignInit_ex|. + * + * TODO(fork): remove. */ +OPENSSL_EXPORT int EVP_SignInit(EVP_MD_CTX *ctx, const EVP_MD *type); + +/* EVP_SignUpdate appends |len| bytes from |data| to the data which will be + * signed in |EVP_SignFinal|. */ +OPENSSL_EXPORT int EVP_SignUpdate(EVP_MD_CTX *ctx, const void *data, + size_t len); + +/* EVP_SignFinal signs the data that has been included by one or more calls to + * |EVP_SignUpdate|, using the key |pkey|, and writes it to |sig|. On entry, + * |sig| must point to at least |EVP_PKEY_size(pkey)| bytes of space. The + * actual size of the signature is written to |*out_sig_len|. + * + * It returns one on success and zero otherwise. + * + * It does not modify |ctx|, thus it's possible to continue to use |ctx| in + * order to sign a longer message. */ +OPENSSL_EXPORT int EVP_SignFinal(const EVP_MD_CTX *ctx, uint8_t *sig, + unsigned int *out_sig_len, EVP_PKEY *pkey); + + +/* Verifying (old functions) */ + +/* EVP_VerifyInit_ex configures |ctx|, which must already have been + * initialised, for a fresh signature verification operation using the hash + * function |type|. It returns one on success and zero otherwise. + * + * (In order to initialise |ctx|, either obtain it initialised with + * |EVP_MD_CTX_create|, or use |EVP_MD_CTX_init|.) */ +OPENSSL_EXPORT int EVP_VerifyInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, + ENGINE *impl); + +/* EVP_VerifyInit is a deprecated version of |EVP_VerifyInit_ex|. + * + * TODO(fork): remove. */ +OPENSSL_EXPORT int EVP_VerifyInit(EVP_MD_CTX *ctx, const EVP_MD *type); + +/* EVP_VerifyUpdate appends |len| bytes from |data| to the data which will be + * signed in |EVP_VerifyFinal|. */ +OPENSSL_EXPORT int EVP_VerifyUpdate(EVP_MD_CTX *ctx, const void *data, + size_t len); + +/* EVP_VerifyFinal verifies that |sig_len| bytes of |sig| are a valid + * signature, by |pkey|, for the data that has been included by one or more + * calls to |EVP_VerifyUpdate|. + * + * It returns one on success and zero otherwise. + * + * It does not modify |ctx|, thus it's possible to continue to use |ctx| in + * order to sign a longer message. */ +OPENSSL_EXPORT int EVP_VerifyFinal(EVP_MD_CTX *ctx, const uint8_t *sig, + size_t sig_len, EVP_PKEY *pkey); + + +/* Printing */ + +/* EVP_PKEY_print_public prints a textual representation of the public key in + * |pkey| to |out|. Returns one on success or zero otherwise. */ +OPENSSL_EXPORT int EVP_PKEY_print_public(BIO *out, const EVP_PKEY *pkey, + int indent, ASN1_PCTX *pctx); + +/* EVP_PKEY_print_private prints a textual representation of the private key in + * |pkey| to |out|. Returns one on success or zero otherwise. */ +OPENSSL_EXPORT int EVP_PKEY_print_private(BIO *out, const EVP_PKEY *pkey, + int indent, ASN1_PCTX *pctx); + +/* EVP_PKEY_print_params prints a textual representation of the parameters in + * |pkey| to |out|. Returns one on success or zero otherwise. */ +OPENSSL_EXPORT int EVP_PKEY_print_params(BIO *out, const EVP_PKEY *pkey, + int indent, ASN1_PCTX *pctx); + + +/* Password stretching. + * + * Password stretching functions take a low-entropy password and apply a slow + * function that results in a key suitable for use in symmetric + * cryptography. */ + +/* PKCS5_PBKDF2_HMAC computes |iterations| iterations of PBKDF2 of |password| + * and |salt|, using |digest|, and outputs |key_len| bytes to |out_key|. It + * returns one on success and zero on error. */ +OPENSSL_EXPORT int PKCS5_PBKDF2_HMAC(const char *password, size_t password_len, + const uint8_t *salt, size_t salt_len, + unsigned iterations, const EVP_MD *digest, + size_t key_len, uint8_t *out_key); + +/* PKCS5_PBKDF2_HMAC_SHA1 is the same as PKCS5_PBKDF2_HMAC, but with |digest| + * fixed to |EVP_sha1|. */ +OPENSSL_EXPORT int PKCS5_PBKDF2_HMAC_SHA1(const char *password, + size_t password_len, const uint8_t *salt, + size_t salt_len, unsigned iterations, + size_t key_len, uint8_t *out_key); + + +/* Public key contexts. + * + * |EVP_PKEY_CTX| objects hold the context of an operation (e.g. signing or + * encrypting) that uses a public key. */ + +/* EVP_PKEY_CTX_new allocates a fresh |EVP_PKEY_CTX| for use with |pkey|. It + * returns the context or NULL on error. */ +OPENSSL_EXPORT EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *e); + +/* EVP_PKEY_CTX_new_id allocates a fresh |EVP_PKEY_CTX| for a key of type |id| + * (e.g. |EVP_PKEY_HMAC|). This can be used for key generation where + * |EVP_PKEY_CTX_new| can't be used because there isn't an |EVP_PKEY| to pass + * it. It returns the context or NULL on error. */ +OPENSSL_EXPORT EVP_PKEY_CTX *EVP_PKEY_CTX_new_id(int id, ENGINE *e); + +/* EVP_PKEY_CTX_free frees |ctx| and the data it owns. */ +OPENSSL_EXPORT void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx); + +/* EVP_PKEY_CTX_dup allocates a fresh |EVP_PKEY_CTX| and sets it equal to the + * state of |ctx|. It returns the fresh |EVP_PKEY_CTX| or NULL on error. */ +OPENSSL_EXPORT EVP_PKEY_CTX *EVP_PKEY_CTX_dup(EVP_PKEY_CTX *ctx); + +/* EVP_PKEY_CTX_get0_pkey returns the |EVP_PKEY| associated with |ctx|. */ +OPENSSL_EXPORT EVP_PKEY *EVP_PKEY_CTX_get0_pkey(EVP_PKEY_CTX *ctx); + +/* EVP_PKEY_sign_init initialises an |EVP_PKEY_CTX| for a signing operation. It + * should be called before |EVP_PKEY_sign|. + * + * It returns one on success or zero on error. */ +OPENSSL_EXPORT int EVP_PKEY_sign_init(EVP_PKEY_CTX *ctx); + +/* EVP_PKEY_sign signs |data_len| bytes from |data| using |ctx|. If |sig| is + * NULL, the maximum size of the signature is written to + * |out_sig_len|. Otherwise, |*sig_len| must contain the number of bytes of + * space available at |sig|. If sufficient, the signature will be written to + * |sig| and |*sig_len| updated with the true length. + * + * WARNING: Setting |sig| to NULL only gives the maximum size of the + * signature. The actual signature may be smaller. + * + * It returns one on success or zero on error. (Note: this differs from + * OpenSSL, which can also return negative values to indicate an error. ) */ +OPENSSL_EXPORT int EVP_PKEY_sign(EVP_PKEY_CTX *ctx, uint8_t *sig, + size_t *sig_len, const uint8_t *data, + size_t data_len); + +/* EVP_PKEY_verify_init initialises an |EVP_PKEY_CTX| for a signature + * verification operation. It should be called before |EVP_PKEY_verify|. + * + * It returns one on success or zero on error. */ +OPENSSL_EXPORT int EVP_PKEY_verify_init(EVP_PKEY_CTX *ctx); + +/* EVP_PKEY_verify verifies that |sig_len| bytes from |sig| are a valid signature + * for |data|. + * + * It returns one on success or zero on error. */ +OPENSSL_EXPORT int EVP_PKEY_verify(EVP_PKEY_CTX *ctx, const uint8_t *sig, + size_t sig_len, const uint8_t *data, + size_t data_len); + +/* EVP_PKEY_encrypt_init initialises an |EVP_PKEY_CTX| for an encryption + * operation. It should be called before |EVP_PKEY_encrypt|. + * + * It returns one on success or zero on error. */ +OPENSSL_EXPORT int EVP_PKEY_encrypt_init(EVP_PKEY_CTX *ctx); + +/* EVP_PKEY_encrypt encrypts |in_len| bytes from |in|. If |out| is NULL, the + * maximum size of the ciphertext is written to |out_len|. Otherwise, |*out_len| + * must contain the number of bytes of space available at |out|. If sufficient, + * the ciphertext will be written to |out| and |*out_len| updated with the true + * length. + * + * WARNING: Setting |out| to NULL only gives the maximum size of the + * ciphertext. The actual ciphertext may be smaller. + * + * It returns one on success or zero on error. */ +OPENSSL_EXPORT int EVP_PKEY_encrypt(EVP_PKEY_CTX *ctx, uint8_t *out, + size_t *out_len, const uint8_t *in, + size_t in_len); + +/* EVP_PKEY_decrypt_init initialises an |EVP_PKEY_CTX| for a decryption + * operation. It should be called before |EVP_PKEY_decrypt|. + * + * It returns one on success or zero on error. */ +OPENSSL_EXPORT int EVP_PKEY_decrypt_init(EVP_PKEY_CTX *ctx); + +/* EVP_PKEY_decrypt decrypts |in_len| bytes from |in|. If |out| is NULL, the + * maximum size of the plaintext is written to |out_len|. Otherwise, |*out_len| + * must contain the number of bytes of space available at |out|. If sufficient, + * the ciphertext will be written to |out| and |*out_len| updated with the true + * length. + * + * WARNING: Setting |out| to NULL only gives the maximum size of the + * plaintext. The actual plaintext may be smaller. + * + * It returns one on success or zero on error. */ +OPENSSL_EXPORT int EVP_PKEY_decrypt(EVP_PKEY_CTX *ctx, uint8_t *out, + size_t *out_len, const uint8_t *in, + size_t in_len); + +/* EVP_PKEY_verify_recover_init initialises an |EVP_PKEY_CTX| for a public-key + * decryption operation. It should be called before |EVP_PKEY_verify_recover|. + * + * Public-key decryption is a very obscure operation that is only implemented + * by RSA keys. It is effectively a signature verification operation that + * returns the signed message directly. It is almost certainly not what you + * want. + * + * It returns one on success or zero on error. */ +OPENSSL_EXPORT int EVP_PKEY_verify_recover_init(EVP_PKEY_CTX *ctx); + +/* EVP_PKEY_verify_recover decrypts |sig_len| bytes from |sig|. If |out| is + * NULL, the maximum size of the plaintext is written to |out_len|. Otherwise, + * |*out_len| must contain the number of bytes of space available at |out|. If + * sufficient, the ciphertext will be written to |out| and |*out_len| updated + * with the true length. + * + * WARNING: Setting |out| to NULL only gives the maximum size of the + * plaintext. The actual plaintext may be smaller. + * + * See the warning about this operation in |EVP_PKEY_verify_recover_init|. It + * is probably not what you want. + * + * It returns one on success or zero on error. */ +OPENSSL_EXPORT int EVP_PKEY_verify_recover(EVP_PKEY_CTX *ctx, uint8_t *out, + size_t *out_len, const uint8_t *sig, + size_t siglen); + +/* EVP_PKEY_derive_init initialises an |EVP_PKEY_CTX| for a key derivation + * operation. It should be called before |EVP_PKEY_derive_set_peer| and + * |EVP_PKEY_derive|. + * + * It returns one on success or zero on error. */ +OPENSSL_EXPORT int EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx); + +/* EVP_PKEY_derive_set_peer sets the peer's key to be used for key derivation + * by |ctx| to |peer|. It should be called after |EVP_PKEY_derive_init|. (For + * example, this is used to set the peer's key in (EC)DH.) It returns one on + * success and zero on error. */ +OPENSSL_EXPORT int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer); + +/* EVP_PKEY_derive derives a shared key between the two keys configured in + * |ctx|. If |key| is non-NULL then, on entry, |out_key_len| must contain the + * amount of space at |key|. If sufficient then the shared key will be written + * to |key| and |*out_key_len| will be set to the length. If |key| is NULL then + * |out_key_len| will be set to the maximum length. + * + * WARNING: Setting |out| to NULL only gives the maximum size of the key. The + * actual key may be smaller. + * + * It returns one on success and zero on error. */ +OPENSSL_EXPORT int EVP_PKEY_derive(EVP_PKEY_CTX *ctx, uint8_t *key, + size_t *out_key_len); + +/* EVP_PKEY_keygen_init initialises an |EVP_PKEY_CTX| for a key generation + * operation. It should be called before |EVP_PKEY_keygen|. + * + * It returns one on success or zero on error. */ +OPENSSL_EXPORT int EVP_PKEY_keygen_init(EVP_PKEY_CTX *ctx); + +/* EVP_PKEY_keygen performs a key generation operation using the values from + * |ctx| and sets |*ppkey| to a fresh |EVP_PKEY| containing the resulting key. + * It returns one on success or zero on error. */ +OPENSSL_EXPORT int EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey); + + +/* Generic control functions. */ + +/* EVP_PKEY_CTX_set_signature_md sets |md| as the digest to be used in a + * signature operation. It returns one on success or zero on error. */ +OPENSSL_EXPORT int EVP_PKEY_CTX_set_signature_md(EVP_PKEY_CTX *ctx, + const EVP_MD *md); + +/* EVP_PKEY_CTX_get_signature_md sets |*out_md| to the digest to be used in a + * signature operation. It returns one on success or zero on error. */ +OPENSSL_EXPORT int EVP_PKEY_CTX_get_signature_md(EVP_PKEY_CTX *ctx, + const EVP_MD **out_md); + + +/* RSA specific control functions. */ + +/* EVP_PKEY_CTX_set_rsa_padding sets the padding type to use. It should be one + * of the |RSA_*_PADDING| values. Returns one on success or zero on error. */ +OPENSSL_EXPORT int EVP_PKEY_CTX_set_rsa_padding(EVP_PKEY_CTX *ctx, int padding); + +/* EVP_PKEY_CTX_get_rsa_padding sets |*out_padding| to the current padding + * value, which is one of the |RSA_*_PADDING| values. Returns one on success or + * zero on error. */ +OPENSSL_EXPORT int EVP_PKEY_CTX_get_rsa_padding(EVP_PKEY_CTX *ctx, + int *out_padding); + +/* EVP_PKEY_CTX_set_rsa_pss_saltlen sets the length of the salt in a PSS-padded + * signature. A value of -1 cause the salt to be the same length as the digest + * in the signature. A value of -2 causes the salt to be the maximum length + * that will fit. Otherwise the value gives the size of the salt in bytes. + * + * Returns one on success or zero on error. */ +OPENSSL_EXPORT int EVP_PKEY_CTX_set_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, + int salt_len); + +/* EVP_PKEY_CTX_get_rsa_pss_saltlen sets |*out_salt_len| to the salt length of + * a PSS-padded signature. See the documentation for + * |EVP_PKEY_CTX_set_rsa_pss_saltlen| for details of the special values that it + * can take. + * + * Returns one on success or zero on error. */ +OPENSSL_EXPORT int EVP_PKEY_CTX_get_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, + int *out_salt_len); + +/* EVP_PKEY_CTX_set_rsa_keygen_bits sets the size of the desired RSA modulus, + * in bits, for key generation. Returns one on success or zero on + * error. */ +OPENSSL_EXPORT int EVP_PKEY_CTX_set_rsa_keygen_bits(EVP_PKEY_CTX *ctx, + int bits); + +/* EVP_PKEY_CTX_set_rsa_keygen_pubexp sets |e| as the public exponent for key + * generation. Returns one on success or zero on error. */ +OPENSSL_EXPORT int EVP_PKEY_CTX_set_rsa_keygen_pubexp(EVP_PKEY_CTX *ctx, + BIGNUM *e); + +/* EVP_PKEY_CTX_set_rsa_oaep_md sets |md| as the digest used in OAEP padding. + * Returns one on success or zero on error. */ +OPENSSL_EXPORT int EVP_PKEY_CTX_set_rsa_oaep_md(EVP_PKEY_CTX *ctx, + const EVP_MD *md); + +/* EVP_PKEY_CTX_get_rsa_oaep_md sets |*out_md| to the digest function used in + * OAEP padding. Returns one on success or zero on error. */ +OPENSSL_EXPORT int EVP_PKEY_CTX_get_rsa_oaep_md(EVP_PKEY_CTX *ctx, + const EVP_MD **out_md); + +/* EVP_PKEY_CTX_set_rsa_mgf1_md sets |md| as the digest used in MGF1. Returns + * one on success or zero on error. */ +OPENSSL_EXPORT int EVP_PKEY_CTX_set_rsa_mgf1_md(EVP_PKEY_CTX *ctx, + const EVP_MD *md); + +/* EVP_PKEY_CTX_get_rsa_mgf1_md sets |*out_md| to the digest function used in + * MGF1. Returns one on success or zero on error. */ +OPENSSL_EXPORT int EVP_PKEY_CTX_get_rsa_mgf1_md(EVP_PKEY_CTX *ctx, + const EVP_MD **out_md); + +/* EVP_PKEY_CTX_set0_rsa_oaep_label sets |label_len| bytes from |label| as the + * label used in OAEP. DANGER: On success, this call takes ownership of |label| + * and will call |OPENSSL_free| on it when |ctx| is destroyed. + * + * Returns one on success or zero on error. */ +OPENSSL_EXPORT int EVP_PKEY_CTX_set0_rsa_oaep_label(EVP_PKEY_CTX *ctx, + uint8_t *label, + size_t label_len); + +/* EVP_PKEY_CTX_get0_rsa_oaep_label sets |*out_label| to point to the internal + * buffer containing the OAEP label (which may be NULL) and returns the length + * of the label or a negative value on error. + * + * WARNING: the return value differs from the usual return value convention. */ +OPENSSL_EXPORT int EVP_PKEY_CTX_get0_rsa_oaep_label(EVP_PKEY_CTX *ctx, + const uint8_t **out_label); + + +/* Deprecated functions. */ + +/* EVP_PKEY_DH is defined for compatibility, but it is impossible to create an + * |EVP_PKEY| of that type. */ +#define EVP_PKEY_DH NID_dhKeyAgreement + +/* EVP_PKEY_RSA2 was historically an alternate form for RSA public keys (OID + * 2.5.8.1.1), but is no longer accepted. */ +#define EVP_PKEY_RSA2 NID_rsa + +/* OpenSSL_add_all_algorithms does nothing. */ +OPENSSL_EXPORT void OpenSSL_add_all_algorithms(void); + +/* OPENSSL_add_all_algorithms_conf does nothing. */ +OPENSSL_EXPORT void OPENSSL_add_all_algorithms_conf(void); + +/* OpenSSL_add_all_ciphers does nothing. */ +OPENSSL_EXPORT void OpenSSL_add_all_ciphers(void); + +/* OpenSSL_add_all_digests does nothing. */ +OPENSSL_EXPORT void OpenSSL_add_all_digests(void); + +/* EVP_cleanup does nothing. */ +OPENSSL_EXPORT void EVP_cleanup(void); + +OPENSSL_EXPORT void EVP_CIPHER_do_all_sorted( + void (*callback)(const EVP_CIPHER *cipher, const char *name, + const char *unused, void *arg), + void *arg); + +OPENSSL_EXPORT void EVP_MD_do_all_sorted(void (*callback)(const EVP_MD *cipher, + const char *name, + const char *unused, + void *arg), + void *arg); + +/* i2d_PrivateKey marshals a private key from |key| to an ASN.1, DER + * structure. If |outp| is not NULL then the result is written to |*outp| and + * |*outp| is advanced just past the output. It returns the number of bytes in + * the result, whether written or not, or a negative value on error. + * + * RSA keys are serialized as a DER-encoded RSAPublicKey (RFC 3447) structure. + * EC keys are serialized as a DER-encoded ECPrivateKey (RFC 5915) structure. + * + * Use |RSA_marshal_private_key| or |EC_marshal_private_key| instead. */ +OPENSSL_EXPORT int i2d_PrivateKey(const EVP_PKEY *key, uint8_t **outp); + +/* i2d_PublicKey marshals a public key from |key| to a type-specific format. + * If |outp| is not NULL then the result is written to |*outp| and + * |*outp| is advanced just past the output. It returns the number of bytes in + * the result, whether written or not, or a negative value on error. + * + * RSA keys are serialized as a DER-encoded RSAPublicKey (RFC 3447) structure. + * EC keys are serialized as an EC point per SEC 1. + * + * Use |RSA_marshal_public_key| or |EC_POINT_point2cbb| instead. */ +OPENSSL_EXPORT int i2d_PublicKey(EVP_PKEY *key, uint8_t **outp); + +/* d2i_PrivateKey parses an ASN.1, DER-encoded, private key from |len| bytes at + * |*inp|. If |out| is not NULL then, on exit, a pointer to the result is in + * |*out|. Note that, even if |*out| is already non-NULL on entry, it will not + * be written to. Rather, a fresh |EVP_PKEY| is allocated and the previous one + * is freed. On successful exit, |*inp| is advanced past the DER structure. It + * returns the result or NULL on error. + * + * This function tries to detect one of several formats. Instead, use + * |EVP_parse_private_key| for a PrivateKeyInfo, |RSA_parse_private_key| for an + * RSAPrivateKey, and |EC_parse_private_key| for an ECPrivateKey. */ +OPENSSL_EXPORT EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **out, + const uint8_t **inp, long len); + +/* d2i_AutoPrivateKey acts the same as |d2i_PrivateKey|, but detects the type + * of the private key. + * + * This function tries to detect one of several formats. Instead, use + * |EVP_parse_private_key| for a PrivateKeyInfo, |RSA_parse_private_key| for an + * RSAPrivateKey, and |EC_parse_private_key| for an ECPrivateKey. */ +OPENSSL_EXPORT EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **out, const uint8_t **inp, + long len); + + +/* Private structures. */ + +struct evp_pkey_st { + CRYPTO_refcount_t references; + + /* type contains one of the EVP_PKEY_* values or NID_undef and determines + * which element (if any) of the |pkey| union is valid. */ + int type; + + union { + char *ptr; + RSA *rsa; + DSA *dsa; + DH *dh; + EC_KEY *ec; + } pkey; + + /* ameth contains a pointer to a method table that contains many ASN.1 + * methods for the key type. */ + const EVP_PKEY_ASN1_METHOD *ameth; +} /* EVP_PKEY */; + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#define EVP_R_BUFFER_TOO_SMALL 100 +#define EVP_R_COMMAND_NOT_SUPPORTED 101 +#define EVP_R_DECODE_ERROR 102 +#define EVP_R_DIFFERENT_KEY_TYPES 103 +#define EVP_R_DIFFERENT_PARAMETERS 104 +#define EVP_R_ENCODE_ERROR 105 +#define EVP_R_EXPECTING_AN_EC_KEY_KEY 106 +#define EVP_R_EXPECTING_AN_RSA_KEY 107 +#define EVP_R_EXPECTING_A_DSA_KEY 108 +#define EVP_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE 109 +#define EVP_R_INVALID_DIGEST_LENGTH 110 +#define EVP_R_INVALID_DIGEST_TYPE 111 +#define EVP_R_INVALID_KEYBITS 112 +#define EVP_R_INVALID_MGF1_MD 113 +#define EVP_R_INVALID_OPERATION 114 +#define EVP_R_INVALID_PADDING_MODE 115 +#define EVP_R_INVALID_PSS_SALTLEN 116 +#define EVP_R_KEYS_NOT_SET 117 +#define EVP_R_MISSING_PARAMETERS 118 +#define EVP_R_NO_DEFAULT_DIGEST 119 +#define EVP_R_NO_KEY_SET 120 +#define EVP_R_NO_MDC2_SUPPORT 121 +#define EVP_R_NO_NID_FOR_CURVE 122 +#define EVP_R_NO_OPERATION_SET 123 +#define EVP_R_NO_PARAMETERS_SET 124 +#define EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE 125 +#define EVP_R_OPERATON_NOT_INITIALIZED 126 +#define EVP_R_UNKNOWN_PUBLIC_KEY_TYPE 127 +#define EVP_R_UNSUPPORTED_ALGORITHM 128 +#define EVP_R_UNSUPPORTED_PUBLIC_KEY_TYPE 129 + +#endif /* OPENSSL_HEADER_EVP_H */ diff --git a/external/boringssl/include/openssl/ex_data.h b/external/boringssl/include/openssl/ex_data.h new file mode 100644 index 0000000000..e78e0703ad --- /dev/null +++ b/external/boringssl/include/openssl/ex_data.h @@ -0,0 +1,213 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#ifndef OPENSSL_HEADER_EX_DATA_H +#define OPENSSL_HEADER_EX_DATA_H + +#include + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* ex_data is a mechanism for associating arbitrary extra data with objects. + * For each type of object that supports ex_data, different users can be + * assigned indexes in which to store their data. Each index has callback + * functions that are called when an object of that type is freed or + * duplicated. */ + + +typedef struct crypto_ex_data_st CRYPTO_EX_DATA; + + +/* Type-specific functions. + * + * Each type that supports ex_data provides three functions: */ + +#if 0 /* Sample */ + +/* TYPE_get_ex_new_index allocates a new index for |TYPE|. See the + * descriptions of the callback typedefs for details of when they are + * called. Any of the callback arguments may be NULL. The |argl| and |argp| + * arguments are opaque values that are passed to the callbacks. It returns the + * new index or a negative number on error. + * + * TODO(fork): this should follow the standard calling convention. */ +OPENSSL_EXPORT int TYPE_get_ex_new_index(long argl, void *argp, + CRYPTO_EX_unused *unused, + CRYPTO_EX_dup *dup_func, + CRYPTO_EX_free *free_func); + +/* TYPE_set_ex_data sets an extra data pointer on |t|. The |index| argument + * should have been returned from a previous call to |TYPE_get_ex_new_index|. */ +OPENSSL_EXPORT int TYPE_set_ex_data(TYPE *t, int index, void *arg); + +/* TYPE_get_ex_data returns an extra data pointer for |t|, or NULL if no such + * pointer exists. The |index| argument should have been returned from a + * previous call to |TYPE_get_ex_new_index|. */ +OPENSSL_EXPORT void *TYPE_get_ex_data(const TYPE *t, int index); + +#endif /* Sample */ + + +/* Callback types. */ + +/* CRYPTO_EX_free is a callback function that is called when an object of the + * class with extra data pointers is being destroyed. For example, if this + * callback has been passed to |SSL_get_ex_new_index| then it may be called each + * time an |SSL*| is destroyed. + * + * The callback is passed the new object (i.e. the |SSL*|) in |parent|. The + * arguments |argl| and |argp| contain opaque values that were given to + * |CRYPTO_get_ex_new_index|. The callback should return one on success, but + * the value is ignored. + * + * This callback may be called with a NULL value for |ptr| if |parent| has no + * value set for this index. However, the callbacks may also be skipped entirely + * if no extra data pointers are set on |parent| at all. */ +typedef void CRYPTO_EX_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad, + int index, long argl, void *argp); + +/* CRYPTO_EX_dup is a callback function that is called when an object of the + * class is being copied and thus the ex_data linked to it also needs to be + * copied. On entry, |*from_d| points to the data for this index from the + * original object. When the callback returns, |*from_d| will be set as the + * data for this index in |to|. + * + * This callback may be called with a NULL value for |*from_d| if |from| has no + * value set for this index. However, the callbacks may also be skipped entirely + * if no extra data pointers are set on |from| at all. */ +typedef int CRYPTO_EX_dup(CRYPTO_EX_DATA *to, const CRYPTO_EX_DATA *from, + void **from_d, int index, long argl, void *argp); + + +/* Deprecated functions. */ + +/* CRYPTO_cleanup_all_ex_data does nothing. */ +OPENSSL_EXPORT void CRYPTO_cleanup_all_ex_data(void); + + +/* Private structures. */ + +/* CRYPTO_EX_unused is a placeholder for an unused callback. It is aliased to + * int to ensure non-NULL callers fail to compile rather than fail silently. */ +typedef int CRYPTO_EX_unused; + +struct crypto_ex_data_st { + STACK_OF(void) *sk; +}; + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_EX_DATA_H */ diff --git a/external/boringssl/include/openssl/hkdf.h b/external/boringssl/include/openssl/hkdf.h new file mode 100644 index 0000000000..a484a309c4 --- /dev/null +++ b/external/boringssl/include/openssl/hkdf.h @@ -0,0 +1,64 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_HKDF_H +#define OPENSSL_HEADER_HKDF_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* HKDF. */ + + +/* HKDF computes HKDF (as specified by RFC 5869) of initial keying material + * |secret| with |salt| and |info| using |digest|, and outputs |out_len| bytes + * to |out_key|. It returns one on success and zero on error. + * + * HKDF is an Extract-and-Expand algorithm. It does not do any key stretching, + * and as such, is not suited to be used alone to generate a key from a + * password. */ +OPENSSL_EXPORT int HKDF(uint8_t *out_key, size_t out_len, const EVP_MD *digest, + const uint8_t *secret, size_t secret_len, + const uint8_t *salt, size_t salt_len, + const uint8_t *info, size_t info_len); + +/* HKDF_extract computes a HKDF PRK (as specified by RFC 5869) from initial + * keying material |secret| and salt |salt| using |digest|, and outputs + * |out_len| bytes to |out_key|. The maximum output size is |EVP_MAX_MD_SIZE|. + * It returns one on success and zero on error. */ +OPENSSL_EXPORT int HKDF_extract(uint8_t *out_key, size_t *out_len, + const EVP_MD *digest, const uint8_t *secret, + size_t secret_len, const uint8_t *salt, + size_t salt_len); + +/* HKDF_expand computes a HKDF OKM (as specified by RFC 5869) of length + * |out_len| from the PRK |prk| and info |info| using |digest|, and outputs + * the result to |out_key|. It returns one on success and zero on error. */ +OPENSSL_EXPORT int HKDF_expand(uint8_t *out_key, size_t out_len, + const EVP_MD *digest, uint8_t *prk, + size_t prk_len, const uint8_t *info, + size_t info_len); + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#define HKDF_R_OUTPUT_TOO_LARGE 100 + +#endif /* OPENSSL_HEADER_HKDF_H */ diff --git a/external/boringssl/include/openssl/hmac.h b/external/boringssl/include/openssl/hmac.h new file mode 100644 index 0000000000..5a4e9c7fdb --- /dev/null +++ b/external/boringssl/include/openssl/hmac.h @@ -0,0 +1,158 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_HMAC_H +#define OPENSSL_HEADER_HMAC_H + +#include + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* HMAC contains functions for constructing PRFs from Merkle–DamgÃ¥rd hash + * functions using HMAC. */ + + +/* One-shot operation. */ + +/* HMAC calculates the HMAC of |data_len| bytes of |data|, using the given key + * and hash function, and writes the result to |out|. On entry, |out| must + * contain |EVP_MAX_MD_SIZE| bytes of space. The actual length of the result is + * written to |*out_len|. It returns |out| or NULL on error. */ +OPENSSL_EXPORT uint8_t *HMAC(const EVP_MD *evp_md, const void *key, + size_t key_len, const uint8_t *data, + size_t data_len, uint8_t *out, + unsigned int *out_len); + + +/* Incremental operation. */ + +/* HMAC_CTX_init initialises |ctx| for use in an HMAC operation. It's assumed + * that HMAC_CTX objects will be allocated on the stack thus no allocation + * function is provided. If needed, allocate |sizeof(HMAC_CTX)| and call + * |HMAC_CTX_init| on it. */ +OPENSSL_EXPORT void HMAC_CTX_init(HMAC_CTX *ctx); + +/* HMAC_CTX_cleanup frees data owned by |ctx|. */ +OPENSSL_EXPORT void HMAC_CTX_cleanup(HMAC_CTX *ctx); + +/* HMAC_Init_ex sets up an initialised |HMAC_CTX| to use |md| as the hash + * function and |key| as the key. For a non-initial call, |md| may be NULL, in + * which case the previous hash function will be used. If the hash function has + * not changed and |key| is NULL, |ctx| reuses the previous key. It returns one + * on success or zero otherwise. + * + * WARNING: NULL and empty keys are ambiguous on non-initial calls. Passing NULL + * |key| but repeating the previous |md| reuses the previous key rather than the + * empty key. */ +OPENSSL_EXPORT int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, size_t key_len, + const EVP_MD *md, ENGINE *impl); + +/* HMAC_Update hashes |data_len| bytes from |data| into the current HMAC + * operation in |ctx|. It returns one. */ +OPENSSL_EXPORT int HMAC_Update(HMAC_CTX *ctx, const uint8_t *data, + size_t data_len); + +/* HMAC_Final completes the HMAC operation in |ctx| and writes the result to + * |out| and the sets |*out_len| to the length of the result. On entry, |out| + * must contain at least |EVP_MAX_MD_SIZE| bytes of space. It returns one on + * success or zero on error. */ +OPENSSL_EXPORT int HMAC_Final(HMAC_CTX *ctx, uint8_t *out, + unsigned int *out_len); + + +/* Utility functions. */ + +/* HMAC_size returns the size, in bytes, of the HMAC that will be produced by + * |ctx|. On entry, |ctx| must have been setup with |HMAC_Init_ex|. */ +OPENSSL_EXPORT size_t HMAC_size(const HMAC_CTX *ctx); + +/* HMAC_CTX_copy_ex sets |dest| equal to |src|. On entry, |dest| must have been + * initialised by calling |HMAC_CTX_init|. It returns one on success and zero + * on error. */ +OPENSSL_EXPORT int HMAC_CTX_copy_ex(HMAC_CTX *dest, const HMAC_CTX *src); + + +/* Deprecated functions. */ + +OPENSSL_EXPORT int HMAC_Init(HMAC_CTX *ctx, const void *key, int key_len, + const EVP_MD *md); + +/* HMAC_CTX_copy calls |HMAC_CTX_init| on |dest| and then sets it equal to + * |src|. On entry, |dest| must /not/ be initialised for an operation with + * |HMAC_Init_ex|. It returns one on success and zero on error. */ +OPENSSL_EXPORT int HMAC_CTX_copy(HMAC_CTX *dest, const HMAC_CTX *src); + + +/* Private functions */ + +struct hmac_ctx_st { + const EVP_MD *md; + EVP_MD_CTX md_ctx; + EVP_MD_CTX i_ctx; + EVP_MD_CTX o_ctx; +} /* HMAC_CTX */; + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_HMAC_H */ diff --git a/external/boringssl/include/openssl/lhash.h b/external/boringssl/include/openssl/lhash.h new file mode 100644 index 0000000000..0d6d3aef14 --- /dev/null +++ b/external/boringssl/include/openssl/lhash.h @@ -0,0 +1,192 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_LHASH_H +#define OPENSSL_HEADER_LHASH_H + +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* lhash is a traditional, chaining hash table that automatically expands and + * contracts as needed. One should not use the lh_* functions directly, rather + * use the type-safe macro wrappers: + * + * A hash table of a specific type of object has type |LHASH_OF(type)|. This + * can be defined (once) with |DEFINE_LHASH_OF(type)| and declared where needed + * with |DECLARE_LHASH_OF(type)|. For example: + * + * struct foo { + * int bar; + * }; + * + * DEFINE_LHASH_OF(struct foo); + * + * Although note that the hash table will contain /pointers/ to |foo|. + * + * A macro will be defined for each of the lh_* functions below. For + * LHASH_OF(foo), the macros would be lh_foo_new, lh_foo_num_items etc. */ + + +#define LHASH_OF(type) struct lhash_st_##type + +#define DEFINE_LHASH_OF(type) LHASH_OF(type) { int dummy; } + +#define DECLARE_LHASH_OF(type) LHASH_OF(type); + +/* The make_macros.sh script in this directory parses the following lines and + * generates the lhash_macros.h file that contains macros for the following + * types of stacks: + * + * LHASH_OF:ASN1_OBJECT + * LHASH_OF:CONF_VALUE + * LHASH_OF:SSL_SESSION */ + +#define IN_LHASH_H +#include +#undef IN_LHASH_H + + +/* lhash_item_st is an element of a hash chain. It points to the opaque data + * for this element and to the next item in the chain. The linked-list is NULL + * terminated. */ +typedef struct lhash_item_st { + void *data; + struct lhash_item_st *next; + /* hash contains the cached, hash value of |data|. */ + uint32_t hash; +} LHASH_ITEM; + +/* lhash_cmp_func is a comparison function that returns a value equal, or not + * equal, to zero depending on whether |*a| is equal, or not equal to |*b|, + * respectively. Note the difference between this and |stack_cmp_func| in that + * this takes pointers to the objects directly. */ +typedef int (*lhash_cmp_func)(const void *a, const void *b); + +/* lhash_hash_func is a function that maps an object to a uniformly distributed + * uint32_t. */ +typedef uint32_t (*lhash_hash_func)(const void *a); + +typedef struct lhash_st { + /* num_items contains the total number of items in the hash table. */ + size_t num_items; + /* buckets is an array of |num_buckets| pointers. Each points to the head of + * a chain of LHASH_ITEM objects that have the same hash value, mod + * |num_buckets|. */ + LHASH_ITEM **buckets; + /* num_buckets contains the length of |buckets|. This value is always >= + * kMinNumBuckets. */ + size_t num_buckets; + /* callback_depth contains the current depth of |lh_doall| or |lh_doall_arg| + * calls. If non-zero then this suppresses resizing of the |buckets| array, + * which would otherwise disrupt the iteration. */ + unsigned callback_depth; + + lhash_cmp_func comp; + lhash_hash_func hash; +} _LHASH; + +/* lh_new returns a new, empty hash table or NULL on error. If |comp| is NULL, + * |strcmp| will be used. If |hash| is NULL, a generic hash function will be + * used. */ +OPENSSL_EXPORT _LHASH *lh_new(lhash_hash_func hash, lhash_cmp_func comp); + +/* lh_free frees the hash table itself but none of the elements. See + * |lh_doall|. */ +OPENSSL_EXPORT void lh_free(_LHASH *lh); + +/* lh_num_items returns the number of items in |lh|. */ +OPENSSL_EXPORT size_t lh_num_items(const _LHASH *lh); + +/* lh_retrieve finds an element equal to |data| in the hash table and returns + * it. If no such element exists, it returns NULL. */ +OPENSSL_EXPORT void *lh_retrieve(const _LHASH *lh, const void *data); + +/* lh_insert inserts |data| into the hash table. If an existing element is + * equal to |data| (with respect to the comparison function) then |*old_data| + * will be set to that value and it will be replaced. Otherwise, or in the + * event of an error, |*old_data| will be set to NULL. It returns one on + * success or zero in the case of an allocation error. */ +OPENSSL_EXPORT int lh_insert(_LHASH *lh, void **old_data, void *data); + +/* lh_delete removes an element equal to |data| from the hash table and returns + * it. If no such element is found, it returns NULL. */ +OPENSSL_EXPORT void *lh_delete(_LHASH *lh, const void *data); + +/* lh_doall calls |func| on each element of the hash table. + * TODO(fork): rename this */ +OPENSSL_EXPORT void lh_doall(_LHASH *lh, void (*func)(void *)); + +/* lh_doall_arg calls |func| on each element of the hash table and also passes + * |arg| as the second argument. + * TODO(fork): rename this */ +OPENSSL_EXPORT void lh_doall_arg(_LHASH *lh, void (*func)(void *, void *), + void *arg); + +/* lh_strhash is the default hash function which processes NUL-terminated + * strings. */ +OPENSSL_EXPORT uint32_t lh_strhash(const char *c); + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_LHASH_H */ diff --git a/external/boringssl/include/openssl/lhash_macros.h b/external/boringssl/include/openssl/lhash_macros.h new file mode 100644 index 0000000000..1d981073ea --- /dev/null +++ b/external/boringssl/include/openssl/lhash_macros.h @@ -0,0 +1,132 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#if !defined(IN_LHASH_H) +#error "Don't include this file directly. Include lhash.h" +#endif + +/* ASN1_OBJECT */ +#define lh_ASN1_OBJECT_new(hash, comp) \ + ((LHASH_OF(ASN1_OBJECT) *)lh_new( \ + CHECKED_CAST(lhash_hash_func, uint32_t (*)(const ASN1_OBJECT *), hash), \ + CHECKED_CAST(lhash_cmp_func, \ + int (*)(const ASN1_OBJECT *a, const ASN1_OBJECT *b), \ + comp))) + +#define lh_ASN1_OBJECT_free(lh) \ + lh_free(CHECKED_CAST(_LHASH *, LHASH_OF(ASN1_OBJECT) *, lh)); + +#define lh_ASN1_OBJECT_num_items(lh) \ + lh_num_items(CHECKED_CAST(_LHASH *, LHASH_OF(ASN1_OBJECT) *, lh)) + +#define lh_ASN1_OBJECT_retrieve(lh, data) \ + ((ASN1_OBJECT *)lh_retrieve( \ + CHECKED_CAST(_LHASH *, LHASH_OF(ASN1_OBJECT) *, lh), \ + CHECKED_CAST(void *, ASN1_OBJECT *, data))) + +#define lh_ASN1_OBJECT_insert(lh, old_data, data) \ + lh_insert(CHECKED_CAST(_LHASH *, LHASH_OF(ASN1_OBJECT) *, lh), \ + CHECKED_CAST(void **, ASN1_OBJECT **, old_data), \ + CHECKED_CAST(void *, ASN1_OBJECT *, data)) + +#define lh_ASN1_OBJECT_delete(lh, data) \ + ((ASN1_OBJECT *)lh_delete( \ + CHECKED_CAST(_LHASH *, LHASH_OF(ASN1_OBJECT) *, lh), \ + CHECKED_CAST(void *, ASN1_OBJECT *, data))) + +#define lh_ASN1_OBJECT_doall(lh, func) \ + lh_doall(CHECKED_CAST(_LHASH *, LHASH_OF(ASN1_OBJECT) *, lh), \ + CHECKED_CAST(void (*)(void *), void (*)(ASN1_OBJECT *), func)); + +#define lh_ASN1_OBJECT_doall_arg(lh, func, arg) \ + lh_doall_arg(CHECKED_CAST(_LHASH *, LHASH_OF(ASN1_OBJECT) *, lh), \ + CHECKED_CAST(void (*)(void *, void *), \ + void (*)(ASN1_OBJECT *, void *), func), \ + arg); + +/* CONF_VALUE */ +#define lh_CONF_VALUE_new(hash, comp) \ + ((LHASH_OF(CONF_VALUE) *)lh_new( \ + CHECKED_CAST(lhash_hash_func, uint32_t (*)(const CONF_VALUE *), hash), \ + CHECKED_CAST(lhash_cmp_func, \ + int (*)(const CONF_VALUE *a, const CONF_VALUE *b), comp))) + +#define lh_CONF_VALUE_free(lh) \ + lh_free(CHECKED_CAST(_LHASH *, LHASH_OF(CONF_VALUE) *, lh)); + +#define lh_CONF_VALUE_num_items(lh) \ + lh_num_items(CHECKED_CAST(_LHASH *, LHASH_OF(CONF_VALUE) *, lh)) + +#define lh_CONF_VALUE_retrieve(lh, data) \ + ((CONF_VALUE *)lh_retrieve( \ + CHECKED_CAST(_LHASH *, LHASH_OF(CONF_VALUE) *, lh), \ + CHECKED_CAST(void *, CONF_VALUE *, data))) + +#define lh_CONF_VALUE_insert(lh, old_data, data) \ + lh_insert(CHECKED_CAST(_LHASH *, LHASH_OF(CONF_VALUE) *, lh), \ + CHECKED_CAST(void **, CONF_VALUE **, old_data), \ + CHECKED_CAST(void *, CONF_VALUE *, data)) + +#define lh_CONF_VALUE_delete(lh, data) \ + ((CONF_VALUE *)lh_delete(CHECKED_CAST(_LHASH *, LHASH_OF(CONF_VALUE) *, lh), \ + CHECKED_CAST(void *, CONF_VALUE *, data))) + +#define lh_CONF_VALUE_doall(lh, func) \ + lh_doall(CHECKED_CAST(_LHASH *, LHASH_OF(CONF_VALUE) *, lh), \ + CHECKED_CAST(void (*)(void *), void (*)(CONF_VALUE *), func)); + +#define lh_CONF_VALUE_doall_arg(lh, func, arg) \ + lh_doall_arg(CHECKED_CAST(_LHASH *, LHASH_OF(CONF_VALUE) *, lh), \ + CHECKED_CAST(void (*)(void *, void *), \ + void (*)(CONF_VALUE *, void *), func), \ + arg); + +/* SSL_SESSION */ +#define lh_SSL_SESSION_new(hash, comp) \ + ((LHASH_OF(SSL_SESSION) *)lh_new( \ + CHECKED_CAST(lhash_hash_func, uint32_t (*)(const SSL_SESSION *), hash), \ + CHECKED_CAST(lhash_cmp_func, \ + int (*)(const SSL_SESSION *a, const SSL_SESSION *b), \ + comp))) + +#define lh_SSL_SESSION_free(lh) \ + lh_free(CHECKED_CAST(_LHASH *, LHASH_OF(SSL_SESSION) *, lh)); + +#define lh_SSL_SESSION_num_items(lh) \ + lh_num_items(CHECKED_CAST(_LHASH *, LHASH_OF(SSL_SESSION) *, lh)) + +#define lh_SSL_SESSION_retrieve(lh, data) \ + ((SSL_SESSION *)lh_retrieve( \ + CHECKED_CAST(_LHASH *, LHASH_OF(SSL_SESSION) *, lh), \ + CHECKED_CAST(void *, SSL_SESSION *, data))) + +#define lh_SSL_SESSION_insert(lh, old_data, data) \ + lh_insert(CHECKED_CAST(_LHASH *, LHASH_OF(SSL_SESSION) *, lh), \ + CHECKED_CAST(void **, SSL_SESSION **, old_data), \ + CHECKED_CAST(void *, SSL_SESSION *, data)) + +#define lh_SSL_SESSION_delete(lh, data) \ + ((SSL_SESSION *)lh_delete( \ + CHECKED_CAST(_LHASH *, LHASH_OF(SSL_SESSION) *, lh), \ + CHECKED_CAST(void *, SSL_SESSION *, data))) + +#define lh_SSL_SESSION_doall(lh, func) \ + lh_doall(CHECKED_CAST(_LHASH *, LHASH_OF(SSL_SESSION) *, lh), \ + CHECKED_CAST(void (*)(void *), void (*)(SSL_SESSION *), func)); + +#define lh_SSL_SESSION_doall_arg(lh, func, arg) \ + lh_doall_arg(CHECKED_CAST(_LHASH *, LHASH_OF(SSL_SESSION) *, lh), \ + CHECKED_CAST(void (*)(void *, void *), \ + void (*)(SSL_SESSION *, void *), func), \ + arg); diff --git a/external/boringssl/include/openssl/md4.h b/external/boringssl/include/openssl/md4.h new file mode 100644 index 0000000000..b66fcb0f3d --- /dev/null +++ b/external/boringssl/include/openssl/md4.h @@ -0,0 +1,106 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_MD4_H +#define OPENSSL_HEADER_MD4_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* MD4. */ + +/* MD4_CBLOCK is the block size of MD4. */ +#define MD4_CBLOCK 64 + +/* MD4_DIGEST_LENGTH is the length of an MD4 digest. */ +#define MD4_DIGEST_LENGTH 16 + +/* MD4_Init initialises |md4| and returns one. */ +OPENSSL_EXPORT int MD4_Init(MD4_CTX *md4); + +/* MD4_Update adds |len| bytes from |data| to |md4| and returns one. */ +OPENSSL_EXPORT int MD4_Update(MD4_CTX *md4, const void *data, size_t len); + +/* MD4_Final adds the final padding to |md4| and writes the resulting digest to + * |md|, which must have at least |MD4_DIGEST_LENGTH| bytes of space. It + * returns one. */ +OPENSSL_EXPORT int MD4_Final(uint8_t *md, MD4_CTX *md4); + +/* MD4 writes the digest of |len| bytes from |data| to |out| and returns |out|. + * There must be at least |MD4_DIGEST_LENGTH| bytes of space in |out|. */ +OPENSSL_EXPORT uint8_t *MD4(const uint8_t *data, size_t len, uint8_t *out); + +/* MD4_Transform is a low-level function that performs a single, MD4 block + * transformation using the state from |md4| and 64 bytes from |block|. */ +OPENSSL_EXPORT void MD4_Transform(MD4_CTX *md4, const uint8_t *block); + +struct md4_state_st { + uint32_t h[4]; + uint32_t Nl, Nh; + uint8_t data[MD4_CBLOCK]; + unsigned num; +}; + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_MD4_H */ diff --git a/external/boringssl/include/openssl/md5.h b/external/boringssl/include/openssl/md5.h new file mode 100644 index 0000000000..55162f0236 --- /dev/null +++ b/external/boringssl/include/openssl/md5.h @@ -0,0 +1,107 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_MD5_H +#define OPENSSL_HEADER_MD5_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* MD5. */ + + +/* MD5_CBLOCK is the block size of MD5. */ +#define MD5_CBLOCK 64 + +/* MD5_DIGEST_LENGTH is the length of an MD5 digest. */ +#define MD5_DIGEST_LENGTH 16 + +/* MD5_Init initialises |md5| and returns one. */ +OPENSSL_EXPORT int MD5_Init(MD5_CTX *md5); + +/* MD5_Update adds |len| bytes from |data| to |md5| and returns one. */ +OPENSSL_EXPORT int MD5_Update(MD5_CTX *md5, const void *data, size_t len); + +/* MD5_Final adds the final padding to |md5| and writes the resulting digest to + * |md|, which must have at least |MD5_DIGEST_LENGTH| bytes of space. It + * returns one. */ +OPENSSL_EXPORT int MD5_Final(uint8_t *md, MD5_CTX *md5); + +/* MD5 writes the digest of |len| bytes from |data| to |out| and returns |out|. + * There must be at least |MD5_DIGEST_LENGTH| bytes of space in |out|. */ +OPENSSL_EXPORT uint8_t *MD5(const uint8_t *data, size_t len, uint8_t *out); + +/* MD5_Transform is a low-level function that performs a single, MD5 block + * transformation using the state from |md5| and 64 bytes from |block|. */ +OPENSSL_EXPORT void MD5_Transform(MD5_CTX *md5, const uint8_t *block); + +struct md5_state_st { + uint32_t h[4]; + uint32_t Nl, Nh; + uint8_t data[MD5_CBLOCK]; + unsigned num; +}; + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_MD5_H */ diff --git a/external/boringssl/include/openssl/mem.h b/external/boringssl/include/openssl/mem.h new file mode 100644 index 0000000000..31756f03aa --- /dev/null +++ b/external/boringssl/include/openssl/mem.h @@ -0,0 +1,138 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_MEM_H +#define OPENSSL_HEADER_MEM_H + +#include + +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* Memory and string functions, see also buf.h. + * + * OpenSSL has, historically, had a complex set of malloc debugging options. + * However, that was written in a time before Valgrind and ASAN. Since we now + * have those tools, the OpenSSL allocation functions are simply macros around + * the standard memory functions. */ + + +#define OPENSSL_malloc malloc +#define OPENSSL_realloc realloc +#define OPENSSL_free free + +/* OPENSSL_realloc_clean acts like |realloc|, but clears the previous memory + * buffer. Because this is implemented as a wrapper around |malloc|, it needs + * to be given the size of the buffer pointed to by |ptr|. */ +void *OPENSSL_realloc_clean(void *ptr, size_t old_size, size_t new_size); + +/* OPENSSL_cleanse zeros out |len| bytes of memory at |ptr|. This is similar to + * |memset_s| from C11. */ +OPENSSL_EXPORT void OPENSSL_cleanse(void *ptr, size_t len); + +/* CRYPTO_memcmp returns zero iff the |len| bytes at |a| and |b| are equal. It + * takes an amount of time dependent on |len|, but independent of the contents + * of |a| and |b|. Unlike memcmp, it cannot be used to put elements into a + * defined order as the return value when a != b is undefined, other than to be + * non-zero. */ +OPENSSL_EXPORT int CRYPTO_memcmp(const void *a, const void *b, size_t len); + +/* OPENSSL_hash32 implements the 32 bit, FNV-1a hash. */ +OPENSSL_EXPORT uint32_t OPENSSL_hash32(const void *ptr, size_t len); + +/* OPENSSL_strdup has the same behaviour as strdup(3). */ +OPENSSL_EXPORT char *OPENSSL_strdup(const char *s); + +/* OPENSSL_strnlen has the same behaviour as strnlen(3). */ +OPENSSL_EXPORT size_t OPENSSL_strnlen(const char *s, size_t len); + +/* OPENSSL_strcasecmp has the same behaviour as strcasecmp(3). */ +OPENSSL_EXPORT int OPENSSL_strcasecmp(const char *a, const char *b); + +/* OPENSSL_strncasecmp has the same behaviour as strncasecmp(3). */ +OPENSSL_EXPORT int OPENSSL_strncasecmp(const char *a, const char *b, size_t n); + +/* DECIMAL_SIZE returns an upper bound for the length of the decimal + * representation of the given type. */ +#define DECIMAL_SIZE(type) ((sizeof(type)*8+2)/3+1) + +/* BIO_snprintf has the same behavior as snprintf(3). */ +OPENSSL_EXPORT int BIO_snprintf(char *buf, size_t n, const char *format, ...) + OPENSSL_PRINTF_FORMAT_FUNC(3, 4); + +/* BIO_vsnprintf has the same behavior as vsnprintf(3). */ +OPENSSL_EXPORT int BIO_vsnprintf(char *buf, size_t n, const char *format, + va_list args) + OPENSSL_PRINTF_FORMAT_FUNC(3, 0); + + +/* Deprecated functions. */ + +#define CRYPTO_malloc OPENSSL_malloc +#define CRYPTO_realloc OPENSSL_realloc +#define CRYPTO_free OPENSSL_free + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_MEM_H */ diff --git a/external/boringssl/include/openssl/newhope.h b/external/boringssl/include/openssl/newhope.h new file mode 100644 index 0000000000..487e03f692 --- /dev/null +++ b/external/boringssl/include/openssl/newhope.h @@ -0,0 +1,147 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_NEWHOPE_H +#define OPENSSL_HEADER_NEWHOPE_H + +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* Post-quantum key agreement, based upon the reference + * implementation. Note: this implementation does not interoperate + * with the reference implementation! + * + * Source: https://github.com/tpoeppelmann/newhope + * + * The authors' permission to use their code is gratefully acknowledged. */ + + +/* NEWHOPE_POLY_new returns a new |NEWHOPE_POLY| object, or NULL on error. */ +OPENSSL_EXPORT NEWHOPE_POLY *NEWHOPE_POLY_new(void); + +/* NEWHOPE_POLY_free frees |p|. */ +OPENSSL_EXPORT void NEWHOPE_POLY_free(NEWHOPE_POLY *p); + +/* NEWHOPE_POLY_LENGTH is the size in bytes of the packed representation of a + * polynomial, encoded with 14 bits per coefficient. */ +#define NEWHOPE_POLY_LENGTH ((1024 * 14) / 8) + +/* NEWHOPE_RECONCILIATION_LENGTH is the size in bytes of the packed + * representation of the reconciliation data, encoded as 2 bits per + * coefficient. */ +#define NEWHOPE_RECONCILIATION_LENGTH ((1024 * 2) / 8) + +/* NEWHOPE_OFFERMSG_LENGTH is the length of the offering party's message to the + * accepting party. */ +#define NEWHOPE_OFFERMSG_LENGTH (NEWHOPE_POLY_LENGTH + 32) + +/* NEWHOPE_ACCEPTMSG_LENGTH is the length of the accepting party's message to + * the offering party. */ +#define NEWHOPE_ACCEPTMSG_LENGTH \ + (NEWHOPE_POLY_LENGTH + NEWHOPE_RECONCILIATION_LENGTH) + +/* NEWHOPE_KEY_LENGTH is the size of the result of the key agreement. This + * result is not exposed to callers: instead, it is whitened with SHA-256, whose + * output happens to be the same size. */ +#define NEWHOPE_KEY_LENGTH 32 + +/* NEWHOPE_offer initializes |out_msg| and |out_sk| for a new key + * exchange. |msg| must have room for |NEWHOPE_OFFERMSG_LENGTH| bytes. Neither + * output may be cached. */ +OPENSSL_EXPORT void NEWHOPE_offer(uint8_t out_msg[NEWHOPE_OFFERMSG_LENGTH], + NEWHOPE_POLY *out_sk); + +/* NEWHOPE_accept completes a key exchange given an offer message |msg|. The + * result of the key exchange is written to |out_key|, which must have space for + * |SHA256_DIGEST_LENGTH| bytes. The message to be send to the offering party is + * written to |out_msg|, which must have room for |NEWHOPE_ACCEPTMSG_LENGTH| + * bytes. Returns 1 on success and 0 on error. */ +OPENSSL_EXPORT int NEWHOPE_accept(uint8_t out_key[SHA256_DIGEST_LENGTH], + uint8_t out_msg[NEWHOPE_ACCEPTMSG_LENGTH], + const uint8_t msg[NEWHOPE_OFFERMSG_LENGTH], + size_t msg_len); + +/* NEWHOPE_finish completes a key exchange for the offering party, given an + * accept message |msg| and the previously generated secret |sk|. The result of + * the key exchange is written to |out_key|, which must have space for + * |SHA256_DIGEST_LENGTH| bytes. Returns 1 on success and 0 on error. */ +OPENSSL_EXPORT int NEWHOPE_finish(uint8_t out_key[SHA256_DIGEST_LENGTH], + const NEWHOPE_POLY *sk, + const uint8_t msg[NEWHOPE_ACCEPTMSG_LENGTH], + size_t msg_len); + + +/* Lower-level functions. */ + +/* NEWHOPE_POLY_noise sets |r| to a random polynomial where the coefficients are + * sampled from the noise distribution. */ +OPENSSL_EXPORT void NEWHOPE_POLY_noise(NEWHOPE_POLY* r); + +/* NEWHOPE_POLY_noise_ntt sets |r| to an output of NEWHOPE_POLY_noise, and then + * applies NTT(r) in-place. */ +OPENSSL_EXPORT void NEWHOPE_POLY_noise_ntt(NEWHOPE_POLY* r); + +/* NEWHOPE_offer_computation is the work of |NEWHOPE_offer|, less the encoding + * parts. The inputs are the noise polynomials |s| and |e|, and random + * polynomial |a|. The output is the polynomial |pk|. */ +OPENSSL_EXPORT void NEWHOPE_offer_computation( + NEWHOPE_POLY *out_pk, + const NEWHOPE_POLY *s, const NEWHOPE_POLY *e, const NEWHOPE_POLY *a); + +/* NEWHOPE_accept_computation is the work of |NEWHOPE_accept|, less the encoding + * parts. The inputs from the peer are |pk| and |a|. The locally-generated + * inputs are the noise polynomials |sp|, |ep|, and |epp|, and the random bytes + * |rand|. The outputs are |out_bp| and |out_reconciliation|, and the result of + * key agreement |key|. Returns 1 on success and 0 on failure. */ +OPENSSL_EXPORT void NEWHOPE_accept_computation( + uint8_t out_key[NEWHOPE_KEY_LENGTH], NEWHOPE_POLY *out_bp, + NEWHOPE_POLY *out_reconciliation, + const NEWHOPE_POLY *sp, const NEWHOPE_POLY *ep, const NEWHOPE_POLY *epp, + const uint8_t rand[32], + const NEWHOPE_POLY *pk, const NEWHOPE_POLY *a); + +/* NEWHOPE_finish_computation is the work of |NEWHOPE_finish|, less the encoding + * parts. Given the peer's |bp| and |reconciliation|, and locally-generated + * noise |noise|, the result of the key agreement is written to out_key. + * Returns 1 on success and 0 on failure. */ +OPENSSL_EXPORT void NEWHOPE_finish_computation( + uint8_t out_key[NEWHOPE_KEY_LENGTH], const NEWHOPE_POLY *noise, + const NEWHOPE_POLY *bp, const NEWHOPE_POLY *reconciliation); + +/* NEWHOPE_POLY_frombytes decodes |a| into |r|. */ +OPENSSL_EXPORT void NEWHOPE_POLY_frombytes( + NEWHOPE_POLY *r, const uint8_t a[NEWHOPE_POLY_LENGTH]); + +/* NEWHOPE_POLY_tobytes packs the polynomial |p| into the compact representation + * |r|. */ +OPENSSL_EXPORT void NEWHOPE_POLY_tobytes(uint8_t r[NEWHOPE_POLY_LENGTH], + const NEWHOPE_POLY* p); + +/* NEWHOPE_offer_frommsg decodes an offer message |msg| into its constituent + * polynomials |out_pk| and |a|. */ +OPENSSL_EXPORT void NEWHOPE_offer_frommsg( + NEWHOPE_POLY *out_pk, NEWHOPE_POLY *out_a, + const uint8_t msg[NEWHOPE_OFFERMSG_LENGTH]); + + +#if defined(__cplusplus) +} /* extern "C" */ +#endif + +#endif /* OPENSSL_HEADER_NEWHOPE_H */ diff --git a/external/boringssl/include/openssl/nid.h.REMOVED.git-id b/external/boringssl/include/openssl/nid.h.REMOVED.git-id new file mode 100644 index 0000000000..bad686b841 --- /dev/null +++ b/external/boringssl/include/openssl/nid.h.REMOVED.git-id @@ -0,0 +1 @@ +5ed44ee35de651c6444cdd62da92f2cf328a6eff \ No newline at end of file diff --git a/external/boringssl/include/openssl/obj.h b/external/boringssl/include/openssl/obj.h new file mode 100644 index 0000000000..7e24820c8e --- /dev/null +++ b/external/boringssl/include/openssl/obj.h @@ -0,0 +1,224 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_OBJ_H +#define OPENSSL_HEADER_OBJ_H + +#include + +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* The objects library deals with the registration and indexing of ASN.1 object + * identifiers. These values are often written as a dotted sequence of numbers, + * e.g. 1.2.840.113549.1.9.16.3.9. + * + * Internally, OpenSSL likes to deal with these values by numbering them with + * numbers called "nids". OpenSSL has a large, built-in database of common + * object identifiers and also has both short and long names for them. + * + * This library provides functions for translating between object identifiers, + * nids, short names and long names. + * + * The nid values should not be used outside of a single process: they are not + * stable identifiers. */ + + +/* Basic operations. */ + +/* OBJ_dup returns a duplicate copy of |obj| or NULL on allocation failure. */ +OPENSSL_EXPORT ASN1_OBJECT *OBJ_dup(const ASN1_OBJECT *obj); + +/* OBJ_cmp returns a value less than, equal to or greater than zero if |a| is + * less than, equal to or greater than |b|, respectively. */ +OPENSSL_EXPORT int OBJ_cmp(const ASN1_OBJECT *a, const ASN1_OBJECT *b); + + +/* Looking up nids. */ + +/* OBJ_obj2nid returns the nid corresponding to |obj|, or |NID_undef| if no + * such object is known. */ +OPENSSL_EXPORT int OBJ_obj2nid(const ASN1_OBJECT *obj); + +/* OBJ_cbs2nid returns the nid corresponding to the DER data in |cbs|, or + * |NID_undef| if no such object is known. */ +OPENSSL_EXPORT int OBJ_cbs2nid(const CBS *cbs); + +/* OBJ_sn2nid returns the nid corresponding to |short_name|, or |NID_undef| if + * no such short name is known. */ +OPENSSL_EXPORT int OBJ_sn2nid(const char *short_name); + +/* OBJ_ln2nid returns the nid corresponding to |long_name|, or |NID_undef| if + * no such long name is known. */ +OPENSSL_EXPORT int OBJ_ln2nid(const char *long_name); + +/* OBJ_txt2nid returns the nid corresponding to |s|, which may be a short name, + * long name, or an ASCII string containing a dotted sequence of numbers. It + * returns the nid or NID_undef if unknown. */ +OPENSSL_EXPORT int OBJ_txt2nid(const char *s); + + +/* Getting information about nids. */ + +/* OBJ_nid2obj returns the ASN1_OBJECT corresponding to |nid|, or NULL if |nid| + * is unknown. */ +OPENSSL_EXPORT const ASN1_OBJECT *OBJ_nid2obj(int nid); + +/* OBJ_nid2sn returns the short name for |nid|, or NULL if |nid| is unknown. */ +OPENSSL_EXPORT const char *OBJ_nid2sn(int nid); + +/* OBJ_nid2ln returns the long name for |nid|, or NULL if |nid| is unknown. */ +OPENSSL_EXPORT const char *OBJ_nid2ln(int nid); + +/* OBJ_nid2cbb writes |nid| as an ASN.1 OBJECT IDENTIFIER to |out|. It returns + * one on success or zero otherwise. */ +OPENSSL_EXPORT int OBJ_nid2cbb(CBB *out, int nid); + + +/* Dealing with textual representations of object identifiers. */ + +/* OBJ_txt2obj returns an ASN1_OBJECT for the textual respresentation in |s|. + * If |dont_search_names| is zero, then |s| will be matched against the long + * and short names of a known objects to find a match. Otherwise |s| must + * contain an ASCII string with a dotted sequence of numbers. The resulting + * object need not be previously known. It returns a freshly allocated + * |ASN1_OBJECT| or NULL on error. */ +OPENSSL_EXPORT ASN1_OBJECT *OBJ_txt2obj(const char *s, int dont_search_names); + +/* OBJ_obj2txt converts |obj| to a textual representation. If + * |dont_return_name| is zero then |obj| will be matched against known objects + * and the long (preferably) or short name will be used if found. Otherwise + * |obj| will be converted into a dotted sequence of integers. If |out| is not + * NULL, then at most |out_len| bytes of the textual form will be written + * there. If |out_len| is at least one, then string written to |out| will + * always be NUL terminated. It returns the number of characters that could + * have been written, not including the final NUL, or -1 on error. */ +OPENSSL_EXPORT int OBJ_obj2txt(char *out, int out_len, const ASN1_OBJECT *obj, + int dont_return_name); + + +/* Adding objects at runtime. */ + +/* OBJ_create adds a known object and returns the nid of the new object, or + * NID_undef on error. */ +OPENSSL_EXPORT int OBJ_create(const char *oid, const char *short_name, + const char *long_name); + + +/* Handling signature algorithm identifiers. + * + * Some NIDs (e.g. sha256WithRSAEncryption) specify both a digest algorithm and + * a public key algorithm. The following functions map between pairs of digest + * and public-key algorithms and the NIDs that specify their combination. + * + * Sometimes the combination NID leaves the digest unspecified (e.g. + * rsassaPss). In these cases, the digest NID is |NID_undef|. */ + +/* OBJ_find_sigid_algs finds the digest and public-key NIDs that correspond to + * the signing algorithm |sign_nid|. If successful, it sets |*out_digest_nid| + * and |*out_pkey_nid| and returns one. Otherwise it returns zero. Any of + * |out_digest_nid| or |out_pkey_nid| can be NULL if the caller doesn't need + * that output value. */ +OPENSSL_EXPORT int OBJ_find_sigid_algs(int sign_nid, int *out_digest_nid, + int *out_pkey_nid); + +/* OBJ_find_sigid_by_algs finds the signature NID that corresponds to the + * combination of |digest_nid| and |pkey_nid|. If success, it sets + * |*out_sign_nid| and returns one. Otherwise it returns zero. The + * |out_sign_nid| argument can be NULL if the caller only wishes to learn + * whether the combination is valid. */ +OPENSSL_EXPORT int OBJ_find_sigid_by_algs(int *out_sign_nid, int digest_nid, + int pkey_nid); + + +/* Deprecated functions. */ + +typedef struct obj_name_st { + int type; + const char *name; +} OBJ_NAME; + +#define OBJ_NAME_TYPE_MD_METH 1 +#define OBJ_NAME_TYPE_CIPHER_METH 2 + +/* OBJ_NAME_do_all_sorted calls |callback| zero or more times, each time with + * the name of a different primitive. If |type| is |OBJ_NAME_TYPE_MD_METH| then + * the primitives will be hash functions, alternatively if |type| is + * |OBJ_NAME_TYPE_CIPHER_METH| then the primitives will be ciphers or cipher + * modes. + * + * This function is ill-specified and should never be used. */ +OPENSSL_EXPORT void OBJ_NAME_do_all_sorted( + int type, void (*callback)(const OBJ_NAME *, void *arg), void *arg); + +/* OBJ_NAME_do_all calls |OBJ_NAME_do_all_sorted|. */ +OPENSSL_EXPORT void OBJ_NAME_do_all(int type, void (*callback)(const OBJ_NAME *, + void *arg), + void *arg); + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#define OBJ_R_UNKNOWN_NID 100 + +#endif /* OPENSSL_HEADER_OBJ_H */ diff --git a/external/boringssl/include/openssl/obj_mac.h b/external/boringssl/include/openssl/obj_mac.h new file mode 100644 index 0000000000..e7ccadc193 --- /dev/null +++ b/external/boringssl/include/openssl/obj_mac.h @@ -0,0 +1,18 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +/* This header is provided in order to make compiling against code that expects + OpenSSL easier. */ + +#include "nid.h" diff --git a/external/boringssl/include/openssl/objects.h b/external/boringssl/include/openssl/objects.h new file mode 100644 index 0000000000..dd6556f264 --- /dev/null +++ b/external/boringssl/include/openssl/objects.h @@ -0,0 +1,18 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +/* This header is provided in order to make compiling against code that expects + OpenSSL easier. */ + +#include "obj.h" diff --git a/external/boringssl/include/openssl/opensslconf.h b/external/boringssl/include/openssl/opensslconf.h new file mode 100644 index 0000000000..bf65fc3b2d --- /dev/null +++ b/external/boringssl/include/openssl/opensslconf.h @@ -0,0 +1,60 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +/* This header is provided in order to make compiling against code that expects + OpenSSL easier. */ + +#ifndef OPENSSL_HEADER_OPENSSLCONF_H +#define OPENSSL_HEADER_OPENSSLCONF_H + + +#define OPENSSL_NO_BF +#define OPENSSL_NO_BUF_FREELISTS +#define OPENSSL_NO_CAMELLIA +#define OPENSSL_NO_CAPIENG +#define OPENSSL_NO_CAST +#define OPENSSL_NO_CMS +#define OPENSSL_NO_COMP +#define OPENSSL_NO_DANE +#define OPENSSL_NO_DEPRECATED +#define OPENSSL_NO_DYNAMIC_ENGINE +#define OPENSSL_NO_EC_NISTP_64_GCC_128 +#define OPENSSL_NO_EC2M +#define OPENSSL_NO_ENGINE +#define OPENSSL_NO_GMP +#define OPENSSL_NO_GOST +#define OPENSSL_NO_HEARTBEATS +#define OPENSSL_NO_HW +#define OPENSSL_NO_IDEA +#define OPENSSL_NO_JPAKE +#define OPENSSL_NO_KRB5 +#define OPENSSL_NO_MD2 +#define OPENSSL_NO_MDC2 +#define OPENSSL_NO_OCB +#define OPENSSL_NO_OCSP +#define OPENSSL_NO_RC2 +#define OPENSSL_NO_RC5 +#define OPENSSL_NO_RFC3779 +#define OPENSSL_NO_RIPEMD +#define OPENSSL_NO_RMD160 +#define OPENSSL_NO_SCTP +#define OPENSSL_NO_SEED +#define OPENSSL_NO_SRP +#define OPENSSL_NO_SSL2 +#define OPENSSL_NO_STATIC_ENGINE +#define OPENSSL_NO_STORE +#define OPENSSL_NO_WHIRLPOOL + + +#endif /* OPENSSL_HEADER_OPENSSLCONF_H */ diff --git a/external/boringssl/include/openssl/opensslv.h b/external/boringssl/include/openssl/opensslv.h new file mode 100644 index 0000000000..a3555d4f8b --- /dev/null +++ b/external/boringssl/include/openssl/opensslv.h @@ -0,0 +1,18 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +/* This header is provided in order to make compiling against code that expects + OpenSSL easier. */ + +#include "crypto.h" diff --git a/external/boringssl/include/openssl/ossl_typ.h b/external/boringssl/include/openssl/ossl_typ.h new file mode 100644 index 0000000000..c2b3fe7c50 --- /dev/null +++ b/external/boringssl/include/openssl/ossl_typ.h @@ -0,0 +1,18 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +/* This header is provided in order to make compiling against code that expects + OpenSSL easier. */ + +#include "base.h" diff --git a/external/boringssl/include/openssl/pem.h b/external/boringssl/include/openssl/pem.h new file mode 100644 index 0000000000..58aecaf50d --- /dev/null +++ b/external/boringssl/include/openssl/pem.h @@ -0,0 +1,517 @@ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_PEM_H +#define OPENSSL_HEADER_PEM_H + +#include +#include +#include +#include +#include +#include +#include + +/* For compatibility with open-iscsi, which assumes that it can get + * |OPENSSL_malloc| from pem.h or err.h */ +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +#define PEM_BUFSIZE 1024 + +#define PEM_OBJ_UNDEF 0 +#define PEM_OBJ_X509 1 +#define PEM_OBJ_X509_REQ 2 +#define PEM_OBJ_CRL 3 +#define PEM_OBJ_SSL_SESSION 4 +#define PEM_OBJ_PRIV_KEY 10 +#define PEM_OBJ_PRIV_RSA 11 +#define PEM_OBJ_PRIV_DSA 12 +#define PEM_OBJ_PRIV_DH 13 +#define PEM_OBJ_PUB_RSA 14 +#define PEM_OBJ_PUB_DSA 15 +#define PEM_OBJ_PUB_DH 16 +#define PEM_OBJ_DHPARAMS 17 +#define PEM_OBJ_DSAPARAMS 18 +#define PEM_OBJ_PRIV_RSA_PUBLIC 19 +#define PEM_OBJ_PRIV_ECDSA 20 +#define PEM_OBJ_PUB_ECDSA 21 +#define PEM_OBJ_ECPARAMETERS 22 + +#define PEM_ERROR 30 +#define PEM_DEK_DES_CBC 40 +#define PEM_DEK_IDEA_CBC 45 +#define PEM_DEK_DES_EDE 50 +#define PEM_DEK_DES_ECB 60 +#define PEM_DEK_RSA 70 +#define PEM_DEK_RSA_MD2 80 +#define PEM_DEK_RSA_MD5 90 + +#define PEM_MD_MD2 NID_md2 +#define PEM_MD_MD5 NID_md5 +#define PEM_MD_SHA NID_sha +#define PEM_MD_MD2_RSA NID_md2WithRSAEncryption +#define PEM_MD_MD5_RSA NID_md5WithRSAEncryption +#define PEM_MD_SHA_RSA NID_sha1WithRSAEncryption + +#define PEM_STRING_X509_OLD "X509 CERTIFICATE" +#define PEM_STRING_X509 "CERTIFICATE" +#define PEM_STRING_X509_PAIR "CERTIFICATE PAIR" +#define PEM_STRING_X509_TRUSTED "TRUSTED CERTIFICATE" +#define PEM_STRING_X509_REQ_OLD "NEW CERTIFICATE REQUEST" +#define PEM_STRING_X509_REQ "CERTIFICATE REQUEST" +#define PEM_STRING_X509_CRL "X509 CRL" +#define PEM_STRING_EVP_PKEY "ANY PRIVATE KEY" +#define PEM_STRING_PUBLIC "PUBLIC KEY" +#define PEM_STRING_RSA "RSA PRIVATE KEY" +#define PEM_STRING_RSA_PUBLIC "RSA PUBLIC KEY" +#define PEM_STRING_DSA "DSA PRIVATE KEY" +#define PEM_STRING_DSA_PUBLIC "DSA PUBLIC KEY" +#define PEM_STRING_EC "EC PRIVATE KEY" +#define PEM_STRING_PKCS7 "PKCS7" +#define PEM_STRING_PKCS7_SIGNED "PKCS #7 SIGNED DATA" +#define PEM_STRING_PKCS8 "ENCRYPTED PRIVATE KEY" +#define PEM_STRING_PKCS8INF "PRIVATE KEY" +#define PEM_STRING_DHPARAMS "DH PARAMETERS" +#define PEM_STRING_SSL_SESSION "SSL SESSION PARAMETERS" +#define PEM_STRING_DSAPARAMS "DSA PARAMETERS" +#define PEM_STRING_ECDSA_PUBLIC "ECDSA PUBLIC KEY" +#define PEM_STRING_ECPRIVATEKEY "EC PRIVATE KEY" +#define PEM_STRING_CMS "CMS" + + /* Note that this structure is initialised by PEM_SealInit and cleaned up + by PEM_SealFinal (at least for now) */ +typedef struct PEM_Encode_Seal_st + { + EVP_ENCODE_CTX encode; + EVP_MD_CTX md; + EVP_CIPHER_CTX cipher; + } PEM_ENCODE_SEAL_CTX; + +/* enc_type is one off */ +#define PEM_TYPE_ENCRYPTED 10 +#define PEM_TYPE_MIC_ONLY 20 +#define PEM_TYPE_MIC_CLEAR 30 +#define PEM_TYPE_CLEAR 40 + +typedef struct pem_recip_st + { + char *name; + X509_NAME *dn; + + int cipher; + int key_enc; + /* char iv[8]; unused and wrong size */ + } PEM_USER; + +typedef struct pem_ctx_st + { + int type; /* what type of object */ + + struct { + int version; + int mode; + } proc_type; + + char *domain; + + struct { + int cipher; + /* unused, and wrong size + unsigned char iv[8]; */ + } DEK_info; + + PEM_USER *originator; + + int num_recipient; + PEM_USER **recipient; + + EVP_MD *md; /* signature type */ + + int md_enc; /* is the md encrypted or not? */ + int md_len; /* length of md_data */ + char *md_data; /* message digest, could be pkey encrypted */ + + EVP_CIPHER *dec; /* date encryption cipher */ + int key_len; /* key length */ + unsigned char *key; /* key */ + /* unused, and wrong size + unsigned char iv[8]; */ + + + int data_enc; /* is the data encrypted */ + int data_len; + unsigned char *data; + } PEM_CTX; + +/* These macros make the PEM_read/PEM_write functions easier to maintain and + * write. Now they are all implemented with either: + * IMPLEMENT_PEM_rw(...) or IMPLEMENT_PEM_rw_cb(...) + */ + +#ifdef OPENSSL_NO_FP_API + +#define IMPLEMENT_PEM_read_fp(name, type, str, asn1) /**/ +#define IMPLEMENT_PEM_write_fp(name, type, str, asn1) /**/ +#define IMPLEMENT_PEM_write_fp_const(name, type, str, asn1) /**/ +#define IMPLEMENT_PEM_write_cb_fp(name, type, str, asn1) /**/ +#define IMPLEMENT_PEM_write_cb_fp_const(name, type, str, asn1) /**/ + +#else + +#define IMPLEMENT_PEM_read_fp(name, type, str, asn1) \ +OPENSSL_EXPORT type *PEM_read_##name(FILE *fp, type **x, pem_password_cb *cb, void *u)\ +{ \ +return PEM_ASN1_read((d2i_of_void *)d2i_##asn1, str,fp,(void **)x,cb,u); \ +} + +#define IMPLEMENT_PEM_write_fp(name, type, str, asn1) \ +OPENSSL_EXPORT int PEM_write_##name(FILE *fp, type *x) \ +{ \ +return PEM_ASN1_write((i2d_of_void *)i2d_##asn1,str,fp,x,NULL,NULL,0,NULL,NULL); \ +} + +#define IMPLEMENT_PEM_write_fp_const(name, type, str, asn1) \ +OPENSSL_EXPORT int PEM_write_##name(FILE *fp, const type *x) \ +{ \ +return PEM_ASN1_write((i2d_of_void *)i2d_##asn1,str,fp,(void *)x,NULL,NULL,0,NULL,NULL); \ +} + +#define IMPLEMENT_PEM_write_cb_fp(name, type, str, asn1) \ +OPENSSL_EXPORT int PEM_write_##name(FILE *fp, type *x, const EVP_CIPHER *enc, \ + unsigned char *kstr, int klen, pem_password_cb *cb, \ + void *u) \ + { \ + return PEM_ASN1_write((i2d_of_void *)i2d_##asn1,str,fp,x,enc,kstr,klen,cb,u); \ + } + +#define IMPLEMENT_PEM_write_cb_fp_const(name, type, str, asn1) \ +OPENSSL_EXPORT int PEM_write_##name(FILE *fp, type *x, const EVP_CIPHER *enc, \ + unsigned char *kstr, int klen, pem_password_cb *cb, \ + void *u) \ + { \ + return PEM_ASN1_write((i2d_of_void *)i2d_##asn1,str,fp,x,enc,kstr,klen,cb,u); \ + } + +#endif + +#define IMPLEMENT_PEM_read_bio(name, type, str, asn1) \ +OPENSSL_EXPORT type *PEM_read_bio_##name(BIO *bp, type **x, pem_password_cb *cb, void *u)\ +{ \ +return PEM_ASN1_read_bio((d2i_of_void *)d2i_##asn1, str,bp,(void **)x,cb,u); \ +} + +#define IMPLEMENT_PEM_write_bio(name, type, str, asn1) \ +OPENSSL_EXPORT int PEM_write_bio_##name(BIO *bp, type *x) \ +{ \ +return PEM_ASN1_write_bio((i2d_of_void *)i2d_##asn1,str,bp,x,NULL,NULL,0,NULL,NULL); \ +} + +#define IMPLEMENT_PEM_write_bio_const(name, type, str, asn1) \ +OPENSSL_EXPORT int PEM_write_bio_##name(BIO *bp, const type *x) \ +{ \ +return PEM_ASN1_write_bio((i2d_of_void *)i2d_##asn1,str,bp,(void *)x,NULL,NULL,0,NULL,NULL); \ +} + +#define IMPLEMENT_PEM_write_cb_bio(name, type, str, asn1) \ +OPENSSL_EXPORT int PEM_write_bio_##name(BIO *bp, type *x, const EVP_CIPHER *enc, \ + unsigned char *kstr, int klen, pem_password_cb *cb, void *u) \ + { \ + return PEM_ASN1_write_bio((i2d_of_void *)i2d_##asn1,str,bp,x,enc,kstr,klen,cb,u); \ + } + +#define IMPLEMENT_PEM_write_cb_bio_const(name, type, str, asn1) \ +OPENSSL_EXPORT int PEM_write_bio_##name(BIO *bp, type *x, const EVP_CIPHER *enc, \ + unsigned char *kstr, int klen, pem_password_cb *cb, void *u) \ + { \ + return PEM_ASN1_write_bio((i2d_of_void *)i2d_##asn1,str,bp,(void *)x,enc,kstr,klen,cb,u); \ + } + +#define IMPLEMENT_PEM_write(name, type, str, asn1) \ + IMPLEMENT_PEM_write_bio(name, type, str, asn1) \ + IMPLEMENT_PEM_write_fp(name, type, str, asn1) + +#define IMPLEMENT_PEM_write_const(name, type, str, asn1) \ + IMPLEMENT_PEM_write_bio_const(name, type, str, asn1) \ + IMPLEMENT_PEM_write_fp_const(name, type, str, asn1) + +#define IMPLEMENT_PEM_write_cb(name, type, str, asn1) \ + IMPLEMENT_PEM_write_cb_bio(name, type, str, asn1) \ + IMPLEMENT_PEM_write_cb_fp(name, type, str, asn1) + +#define IMPLEMENT_PEM_write_cb_const(name, type, str, asn1) \ + IMPLEMENT_PEM_write_cb_bio_const(name, type, str, asn1) \ + IMPLEMENT_PEM_write_cb_fp_const(name, type, str, asn1) + +#define IMPLEMENT_PEM_read(name, type, str, asn1) \ + IMPLEMENT_PEM_read_bio(name, type, str, asn1) \ + IMPLEMENT_PEM_read_fp(name, type, str, asn1) + +#define IMPLEMENT_PEM_rw(name, type, str, asn1) \ + IMPLEMENT_PEM_read(name, type, str, asn1) \ + IMPLEMENT_PEM_write(name, type, str, asn1) + +#define IMPLEMENT_PEM_rw_const(name, type, str, asn1) \ + IMPLEMENT_PEM_read(name, type, str, asn1) \ + IMPLEMENT_PEM_write_const(name, type, str, asn1) + +#define IMPLEMENT_PEM_rw_cb(name, type, str, asn1) \ + IMPLEMENT_PEM_read(name, type, str, asn1) \ + IMPLEMENT_PEM_write_cb(name, type, str, asn1) + +/* These are the same except they are for the declarations */ + +#if defined(OPENSSL_NO_FP_API) + +#define DECLARE_PEM_read_fp(name, type) /**/ +#define DECLARE_PEM_write_fp(name, type) /**/ +#define DECLARE_PEM_write_cb_fp(name, type) /**/ + +#else + +#define DECLARE_PEM_read_fp(name, type) \ + OPENSSL_EXPORT type *PEM_read_##name(FILE *fp, type **x, pem_password_cb *cb, void *u); + +#define DECLARE_PEM_write_fp(name, type) \ + OPENSSL_EXPORT int PEM_write_##name(FILE *fp, type *x); + +#define DECLARE_PEM_write_fp_const(name, type) \ + OPENSSL_EXPORT int PEM_write_##name(FILE *fp, const type *x); + +#define DECLARE_PEM_write_cb_fp(name, type) \ + OPENSSL_EXPORT int PEM_write_##name(FILE *fp, type *x, const EVP_CIPHER *enc, \ + unsigned char *kstr, int klen, pem_password_cb *cb, void *u); + +#endif + +#define DECLARE_PEM_read_bio(name, type) \ + OPENSSL_EXPORT type *PEM_read_bio_##name(BIO *bp, type **x, pem_password_cb *cb, void *u); + +#define DECLARE_PEM_write_bio(name, type) \ + OPENSSL_EXPORT int PEM_write_bio_##name(BIO *bp, type *x); + +#define DECLARE_PEM_write_bio_const(name, type) \ + OPENSSL_EXPORT int PEM_write_bio_##name(BIO *bp, const type *x); + +#define DECLARE_PEM_write_cb_bio(name, type) \ + OPENSSL_EXPORT int PEM_write_bio_##name(BIO *bp, type *x, const EVP_CIPHER *enc, \ + unsigned char *kstr, int klen, pem_password_cb *cb, void *u); + + +#define DECLARE_PEM_write(name, type) \ + DECLARE_PEM_write_bio(name, type) \ + DECLARE_PEM_write_fp(name, type) + +#define DECLARE_PEM_write_const(name, type) \ + DECLARE_PEM_write_bio_const(name, type) \ + DECLARE_PEM_write_fp_const(name, type) + +#define DECLARE_PEM_write_cb(name, type) \ + DECLARE_PEM_write_cb_bio(name, type) \ + DECLARE_PEM_write_cb_fp(name, type) + +#define DECLARE_PEM_read(name, type) \ + DECLARE_PEM_read_bio(name, type) \ + DECLARE_PEM_read_fp(name, type) + +#define DECLARE_PEM_rw(name, type) \ + DECLARE_PEM_read(name, type) \ + DECLARE_PEM_write(name, type) + +#define DECLARE_PEM_rw_const(name, type) \ + DECLARE_PEM_read(name, type) \ + DECLARE_PEM_write_const(name, type) + +#define DECLARE_PEM_rw_cb(name, type) \ + DECLARE_PEM_read(name, type) \ + DECLARE_PEM_write_cb(name, type) + +/* "userdata": new with OpenSSL 0.9.4 */ +typedef int pem_password_cb(char *buf, int size, int rwflag, void *userdata); + +OPENSSL_EXPORT int PEM_get_EVP_CIPHER_INFO(char *header, EVP_CIPHER_INFO *cipher); +OPENSSL_EXPORT int PEM_do_header (EVP_CIPHER_INFO *cipher, unsigned char *data,long *len, pem_password_cb *callback,void *u); + +OPENSSL_EXPORT int PEM_read_bio(BIO *bp, char **name, char **header, unsigned char **data,long *len); +OPENSSL_EXPORT int PEM_write_bio(BIO *bp,const char *name, const char *hdr, const unsigned char *data, long len); +OPENSSL_EXPORT int PEM_bytes_read_bio(unsigned char **pdata, long *plen, char **pnm, const char *name, BIO *bp, pem_password_cb *cb, void *u); +OPENSSL_EXPORT void * PEM_ASN1_read_bio(d2i_of_void *d2i, const char *name, BIO *bp, void **x, pem_password_cb *cb, void *u); +OPENSSL_EXPORT int PEM_ASN1_write_bio(i2d_of_void *i2d,const char *name,BIO *bp, void *x, const EVP_CIPHER *enc,unsigned char *kstr,int klen, pem_password_cb *cb, void *u); + +OPENSSL_EXPORT STACK_OF(X509_INFO) * PEM_X509_INFO_read_bio(BIO *bp, STACK_OF(X509_INFO) *sk, pem_password_cb *cb, void *u); +OPENSSL_EXPORT int PEM_X509_INFO_write_bio(BIO *bp,X509_INFO *xi, EVP_CIPHER *enc, unsigned char *kstr, int klen, pem_password_cb *cd, void *u); + +OPENSSL_EXPORT int PEM_read(FILE *fp, char **name, char **header, unsigned char **data,long *len); +OPENSSL_EXPORT int PEM_write(FILE *fp, const char *name, const char *hdr, const unsigned char *data, long len); +OPENSSL_EXPORT void * PEM_ASN1_read(d2i_of_void *d2i, const char *name, FILE *fp, void **x, pem_password_cb *cb, void *u); +OPENSSL_EXPORT int PEM_ASN1_write(i2d_of_void *i2d,const char *name,FILE *fp, void *x,const EVP_CIPHER *enc,unsigned char *kstr, int klen,pem_password_cb *callback, void *u); +OPENSSL_EXPORT STACK_OF(X509_INFO) * PEM_X509_INFO_read(FILE *fp, STACK_OF(X509_INFO) *sk, pem_password_cb *cb, void *u); + +OPENSSL_EXPORT int PEM_SealInit(PEM_ENCODE_SEAL_CTX *ctx, EVP_CIPHER *type, EVP_MD *md_type, unsigned char **ek, int *ekl, unsigned char *iv, EVP_PKEY **pubk, int npubk); +OPENSSL_EXPORT void PEM_SealUpdate(PEM_ENCODE_SEAL_CTX *ctx, unsigned char *out, int *outl, unsigned char *in, int inl); +OPENSSL_EXPORT int PEM_SealFinal(PEM_ENCODE_SEAL_CTX *ctx, unsigned char *sig,int *sigl, unsigned char *out, int *outl, EVP_PKEY *priv); + +OPENSSL_EXPORT void PEM_SignInit(EVP_MD_CTX *ctx, EVP_MD *type); +OPENSSL_EXPORT void PEM_SignUpdate(EVP_MD_CTX *ctx,unsigned char *d,unsigned int cnt); +OPENSSL_EXPORT int PEM_SignFinal(EVP_MD_CTX *ctx, unsigned char *sigret, unsigned int *siglen, EVP_PKEY *pkey); + +/* PEM_def_callback treats |userdata| as a string and copies it into |buf|, + * assuming its |size| is sufficient. Returns the length of the string, or 0 + * if there is not enough room. If either |buf| or |userdata| is NULL, 0 is + * returned. Note that this is different from OpenSSL, which prompts for a + * password. */ +OPENSSL_EXPORT int PEM_def_callback(char *buf, int size, int rwflag, void *userdata); +OPENSSL_EXPORT void PEM_proc_type(char *buf, int type); +OPENSSL_EXPORT void PEM_dek_info(char *buf, const char *type, int len, char *str); + + +DECLARE_PEM_rw(X509, X509) + +DECLARE_PEM_rw(X509_AUX, X509) + +DECLARE_PEM_rw(X509_CERT_PAIR, X509_CERT_PAIR) + +DECLARE_PEM_rw(X509_REQ, X509_REQ) +DECLARE_PEM_write(X509_REQ_NEW, X509_REQ) + +DECLARE_PEM_rw(X509_CRL, X509_CRL) + +/* DECLARE_PEM_rw(PKCS7, PKCS7) */ + +DECLARE_PEM_rw(NETSCAPE_CERT_SEQUENCE, NETSCAPE_CERT_SEQUENCE) + +DECLARE_PEM_rw(PKCS8, X509_SIG) + +DECLARE_PEM_rw(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO) + +DECLARE_PEM_rw_cb(RSAPrivateKey, RSA) + +DECLARE_PEM_rw_const(RSAPublicKey, RSA) +DECLARE_PEM_rw(RSA_PUBKEY, RSA) + +#ifndef OPENSSL_NO_DSA + +DECLARE_PEM_rw_cb(DSAPrivateKey, DSA) + +DECLARE_PEM_rw(DSA_PUBKEY, DSA) + +DECLARE_PEM_rw_const(DSAparams, DSA) + +#endif + +DECLARE_PEM_rw_cb(ECPrivateKey, EC_KEY) +DECLARE_PEM_rw(EC_PUBKEY, EC_KEY) + + +DECLARE_PEM_rw_const(DHparams, DH) + + +DECLARE_PEM_rw_cb(PrivateKey, EVP_PKEY) + +DECLARE_PEM_rw(PUBKEY, EVP_PKEY) + +OPENSSL_EXPORT int PEM_write_bio_PKCS8PrivateKey_nid(BIO *bp, EVP_PKEY *x, int nid, char *kstr, int klen, pem_password_cb *cb, void *u); +OPENSSL_EXPORT int PEM_write_bio_PKCS8PrivateKey(BIO *, EVP_PKEY *, const EVP_CIPHER *, char *, int, pem_password_cb *, void *); +OPENSSL_EXPORT int i2d_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc, char *kstr, int klen, pem_password_cb *cb, void *u); +OPENSSL_EXPORT int i2d_PKCS8PrivateKey_nid_bio(BIO *bp, EVP_PKEY *x, int nid, char *kstr, int klen, pem_password_cb *cb, void *u); +OPENSSL_EXPORT EVP_PKEY *d2i_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY **x, pem_password_cb *cb, void *u); + +OPENSSL_EXPORT int i2d_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc, char *kstr, int klen, pem_password_cb *cb, void *u); +OPENSSL_EXPORT int i2d_PKCS8PrivateKey_nid_fp(FILE *fp, EVP_PKEY *x, int nid, char *kstr, int klen, pem_password_cb *cb, void *u); +OPENSSL_EXPORT int PEM_write_PKCS8PrivateKey_nid(FILE *fp, EVP_PKEY *x, int nid, char *kstr, int klen, pem_password_cb *cb, void *u); + +OPENSSL_EXPORT EVP_PKEY *d2i_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY **x, pem_password_cb *cb, void *u); + +OPENSSL_EXPORT int PEM_write_PKCS8PrivateKey(FILE *fp,EVP_PKEY *x,const EVP_CIPHER *enc, char *kstr,int klen, pem_password_cb *cd, void *u); + +OPENSSL_EXPORT EVP_PKEY *b2i_PrivateKey(const unsigned char **in, long length); +OPENSSL_EXPORT EVP_PKEY *b2i_PublicKey(const unsigned char **in, long length); +OPENSSL_EXPORT EVP_PKEY *b2i_PrivateKey_bio(BIO *in); +OPENSSL_EXPORT EVP_PKEY *b2i_PublicKey_bio(BIO *in); +OPENSSL_EXPORT int i2b_PrivateKey_bio(BIO *out, EVP_PKEY *pk); +OPENSSL_EXPORT int i2b_PublicKey_bio(BIO *out, EVP_PKEY *pk); +OPENSSL_EXPORT EVP_PKEY *b2i_PVK_bio(BIO *in, pem_password_cb *cb, void *u); +OPENSSL_EXPORT int i2b_PVK_bio(BIO *out, EVP_PKEY *pk, int enclevel, pem_password_cb *cb, void *u); + + +void ERR_load_PEM_strings(void); + + +#ifdef __cplusplus +} +#endif + +#define PEM_R_BAD_BASE64_DECODE 100 +#define PEM_R_BAD_DECRYPT 101 +#define PEM_R_BAD_END_LINE 102 +#define PEM_R_BAD_IV_CHARS 103 +#define PEM_R_BAD_PASSWORD_READ 104 +#define PEM_R_CIPHER_IS_NULL 105 +#define PEM_R_ERROR_CONVERTING_PRIVATE_KEY 106 +#define PEM_R_NOT_DEK_INFO 107 +#define PEM_R_NOT_ENCRYPTED 108 +#define PEM_R_NOT_PROC_TYPE 109 +#define PEM_R_NO_START_LINE 110 +#define PEM_R_READ_KEY 111 +#define PEM_R_SHORT_HEADER 112 +#define PEM_R_UNSUPPORTED_CIPHER 113 +#define PEM_R_UNSUPPORTED_ENCRYPTION 114 + +#endif /* OPENSSL_HEADER_PEM_H */ diff --git a/external/boringssl/include/openssl/pkcs12.h b/external/boringssl/include/openssl/pkcs12.h new file mode 100644 index 0000000000..b5e9516382 --- /dev/null +++ b/external/boringssl/include/openssl/pkcs12.h @@ -0,0 +1,18 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +/* This header is provided in order to make compiling against code that expects + OpenSSL easier. */ + +#include "pkcs8.h" diff --git a/external/boringssl/include/openssl/pkcs7.h b/external/boringssl/include/openssl/pkcs7.h new file mode 100644 index 0000000000..6e5e433074 --- /dev/null +++ b/external/boringssl/include/openssl/pkcs7.h @@ -0,0 +1,16 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +/* This header is provided in order to make compiling against code that expects + OpenSSL easier. */ diff --git a/external/boringssl/include/openssl/pkcs8.h b/external/boringssl/include/openssl/pkcs8.h new file mode 100644 index 0000000000..28cf6ac1f6 --- /dev/null +++ b/external/boringssl/include/openssl/pkcs8.h @@ -0,0 +1,224 @@ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 1999. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + + +#ifndef OPENSSL_HEADER_PKCS8_H +#define OPENSSL_HEADER_PKCS8_H + +#include +#include + + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* PKCS8_encrypt_pbe serializes and encrypts a PKCS8_PRIV_KEY_INFO with PBES1 or + * PBES2 as defined in PKCS #5. Only pbeWithSHAAnd128BitRC4, + * pbeWithSHAAnd3-KeyTripleDES-CBC and pbeWithSHA1And40BitRC2, defined in PKCS + * #12, and PBES2, are supported. PBES2 is selected by setting |cipher| and + * passing -1 for |pbe_nid|. Otherwise, PBES1 is used and |cipher| is ignored. + * + * The |pass_raw_len| bytes pointed to by |pass_raw| are used as the password. + * Note that any conversions from the password as supplied in a text string + * (such as those specified in B.1 of PKCS #12) must be performed by the caller. + * + * If |salt| is NULL, a random salt of |salt_len| bytes is generated. If + * |salt_len| is zero, a default salt length is used instead. + * + * The resulting structure is stored in an X509_SIG which must be freed by the + * caller. + * + * TODO(davidben): Really? An X509_SIG? OpenSSL probably did that because it has + * the same structure as EncryptedPrivateKeyInfo. */ +OPENSSL_EXPORT X509_SIG *PKCS8_encrypt_pbe(int pbe_nid, + const EVP_CIPHER *cipher, + const uint8_t *pass_raw, + size_t pass_raw_len, + uint8_t *salt, size_t salt_len, + int iterations, + PKCS8_PRIV_KEY_INFO *p8inf); + +/* PKCS8_decrypt_pbe decrypts and decodes a PKCS8_PRIV_KEY_INFO with PBES1 or + * PBES2 as defined in PKCS #5. Only pbeWithSHAAnd128BitRC4, + * pbeWithSHAAnd3-KeyTripleDES-CBC and pbeWithSHA1And40BitRC2, and PBES2, + * defined in PKCS #12, are supported. + * + * The |pass_raw_len| bytes pointed to by |pass_raw| are used as the password. + * Note that any conversions from the password as supplied in a text string + * (such as those specified in B.1 of PKCS #12) must be performed by the caller. + * + * The resulting structure must be freed by the caller. */ +OPENSSL_EXPORT PKCS8_PRIV_KEY_INFO *PKCS8_decrypt_pbe(X509_SIG *pkcs8, + const uint8_t *pass_raw, + size_t pass_raw_len); + +/* PKCS12_get_key_and_certs parses a PKCS#12 structure from |in|, authenticates + * and decrypts it using |password|, sets |*out_key| to the included private + * key and appends the included certificates to |out_certs|. It returns one on + * success and zero on error. The caller takes ownership of the outputs. */ +OPENSSL_EXPORT int PKCS12_get_key_and_certs(EVP_PKEY **out_key, + STACK_OF(X509) *out_certs, + CBS *in, const char *password); + + +/* Deprecated functions. */ + +/* PKCS8_encrypt calls |PKCS8_encrypt_pbe| after (in the PKCS#12 case) treating + * |pass| as an ASCII string, appending U+0000, and converting to UCS-2. (So the + * empty password encodes as two NUL bytes.) In the PBES2 case, the password is + * unchanged. */ +OPENSSL_EXPORT X509_SIG *PKCS8_encrypt(int pbe_nid, const EVP_CIPHER *cipher, + const char *pass, int pass_len, + uint8_t *salt, size_t salt_len, + int iterations, + PKCS8_PRIV_KEY_INFO *p8inf); + +/* PKCS8_decrypt calls PKCS8_decrypt_pbe after (in the PKCS#12 case) treating + * |pass| as an ASCII string, appending U+0000, and converting to UCS-2. (So the + * empty password encodes as two NUL bytes.) In the PBES2 case, the password is + * unchanged. */ +OPENSSL_EXPORT PKCS8_PRIV_KEY_INFO *PKCS8_decrypt(X509_SIG *pkcs8, + const char *pass, + int pass_len); + +/* PKCS12_PBE_add does nothing. It exists for compatibility with OpenSSL. */ +OPENSSL_EXPORT void PKCS12_PBE_add(void); + +/* d2i_PKCS12 is a dummy function that copies |*ber_bytes| into a + * |PKCS12| structure. The |out_p12| argument should be NULL(âœ). On exit, + * |*ber_bytes| will be advanced by |ber_len|. It returns a fresh |PKCS12| + * structure or NULL on error. + * + * Note: unlike other d2i functions, |d2i_PKCS12| will always consume |ber_len| + * bytes. + * + * (âœ) If |out_p12| is not NULL and the function is successful, |*out_p12| will + * be freed if not NULL itself and the result will be written to |*out_p12|. + * New code should not depend on this. */ +OPENSSL_EXPORT PKCS12 *d2i_PKCS12(PKCS12 **out_p12, const uint8_t **ber_bytes, + size_t ber_len); + +/* d2i_PKCS12_bio acts like |d2i_PKCS12| but reads from a |BIO|. */ +OPENSSL_EXPORT PKCS12* d2i_PKCS12_bio(BIO *bio, PKCS12 **out_p12); + +/* d2i_PKCS12_fp acts like |d2i_PKCS12| but reads from a |FILE|. */ +OPENSSL_EXPORT PKCS12* d2i_PKCS12_fp(FILE *fp, PKCS12 **out_p12); + +/* PKCS12_parse calls |PKCS12_get_key_and_certs| on the ASN.1 data stored in + * |p12|. The |out_pkey| and |out_cert| arguments must not be NULL and, on + * successful exit, the private key and first certificate will be stored in + * them. The |out_ca_certs| argument may be NULL but, if not, then any extra + * certificates will be appended to |*out_ca_certs|. If |*out_ca_certs| is NULL + * then it will be set to a freshly allocated stack containing the extra certs. + * + * It returns one on success and zero on error. */ +OPENSSL_EXPORT int PKCS12_parse(const PKCS12 *p12, const char *password, + EVP_PKEY **out_pkey, X509 **out_cert, + STACK_OF(X509) **out_ca_certs); + +/* PKCS12_verify_mac returns one if |password| is a valid password for |p12| + * and zero otherwise. Since |PKCS12_parse| doesn't take a length parameter, + * it's not actually possible to use a non-NUL-terminated password to actually + * get anything from a |PKCS12|. Thus |password| and |password_len| may be + * |NULL| and zero, respectively, or else |password_len| may be -1, or else + * |password[password_len]| must be zero and no other NUL bytes may appear in + * |password|. If the |password_len| checks fail, zero is returned + * immediately. */ +OPENSSL_EXPORT int PKCS12_verify_mac(const PKCS12 *p12, const char *password, + int password_len); + +/* PKCS12_free frees |p12| and its contents. */ +OPENSSL_EXPORT void PKCS12_free(PKCS12 *p12); + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#define PKCS8_R_BAD_PKCS12_DATA 100 +#define PKCS8_R_BAD_PKCS12_VERSION 101 +#define PKCS8_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER 102 +#define PKCS8_R_CRYPT_ERROR 103 +#define PKCS8_R_DECODE_ERROR 104 +#define PKCS8_R_ENCODE_ERROR 105 +#define PKCS8_R_ENCRYPT_ERROR 106 +#define PKCS8_R_ERROR_SETTING_CIPHER_PARAMS 107 +#define PKCS8_R_INCORRECT_PASSWORD 108 +#define PKCS8_R_KEYGEN_FAILURE 109 +#define PKCS8_R_KEY_GEN_ERROR 110 +#define PKCS8_R_METHOD_NOT_SUPPORTED 111 +#define PKCS8_R_MISSING_MAC 112 +#define PKCS8_R_MULTIPLE_PRIVATE_KEYS_IN_PKCS12 113 +#define PKCS8_R_PKCS12_PUBLIC_KEY_INTEGRITY_NOT_SUPPORTED 114 +#define PKCS8_R_PKCS12_TOO_DEEPLY_NESTED 115 +#define PKCS8_R_PRIVATE_KEY_DECODE_ERROR 116 +#define PKCS8_R_PRIVATE_KEY_ENCODE_ERROR 117 +#define PKCS8_R_TOO_LONG 118 +#define PKCS8_R_UNKNOWN_ALGORITHM 119 +#define PKCS8_R_UNKNOWN_CIPHER 120 +#define PKCS8_R_UNKNOWN_CIPHER_ALGORITHM 121 +#define PKCS8_R_UNKNOWN_DIGEST 122 +#define PKCS8_R_UNKNOWN_HASH 123 +#define PKCS8_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM 124 +#define PKCS8_R_UNSUPPORTED_KEYLENGTH 125 +#define PKCS8_R_UNSUPPORTED_SALT_TYPE 126 +#define PKCS8_R_UNSUPPORTED_CIPHER 127 +#define PKCS8_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION 128 +#define PKCS8_R_BAD_ITERATION_COUNT 129 +#define PKCS8_R_UNSUPPORTED_PRF 130 + +#endif /* OPENSSL_HEADER_PKCS8_H */ diff --git a/external/boringssl/include/openssl/poly1305.h b/external/boringssl/include/openssl/poly1305.h new file mode 100644 index 0000000000..b4e23e298e --- /dev/null +++ b/external/boringssl/include/openssl/poly1305.h @@ -0,0 +1,51 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_POLY1305_H +#define OPENSSL_HEADER_POLY1305_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef uint8_t poly1305_state[512]; + +/* CRYPTO_poly1305_init sets up |state| so that it can be used to calculate an + * authentication tag with the one-time key |key|. Note that |key| is a + * one-time key and therefore there is no `reset' method because that would + * enable several messages to be authenticated with the same key. */ +OPENSSL_EXPORT void CRYPTO_poly1305_init(poly1305_state* state, + const uint8_t key[32]); + +/* CRYPTO_poly1305_update processes |in_len| bytes from |in|. It can be called + * zero or more times after poly1305_init. */ +OPENSSL_EXPORT void CRYPTO_poly1305_update(poly1305_state* state, + const uint8_t* in, + size_t in_len); + +/* CRYPTO_poly1305_finish completes the poly1305 calculation and writes a 16 + * byte authentication tag to |mac|. The |mac| address must be 16-byte + * aligned. */ +OPENSSL_EXPORT void CRYPTO_poly1305_finish(poly1305_state* state, + uint8_t mac[16]); + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_POLY1305_H */ diff --git a/external/boringssl/include/openssl/pqueue.h b/external/boringssl/include/openssl/pqueue.h new file mode 100644 index 0000000000..ceb1fa2a74 --- /dev/null +++ b/external/boringssl/include/openssl/pqueue.h @@ -0,0 +1,146 @@ +/* + * DTLS implementation written by Nagendra Modadugu + * (nagendra@cs.stanford.edu) for the OpenSSL project 2005. + */ +/* ==================================================================== + * Copyright (c) 1999-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#ifndef OPENSSL_HEADER_PQUEUE_H +#define OPENSSL_HEADER_PQUEUE_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* Priority queue. + * + * The priority queue maintains a linked-list of nodes, each with a unique, + * 64-bit priority, in ascending priority order. */ + +typedef struct _pqueue *pqueue; + +typedef struct _pitem { + uint8_t priority[8]; /* 64-bit value in big-endian encoding */ + void *data; + struct _pitem *next; +} pitem; + +typedef struct _pitem *piterator; + + +/* Creating and freeing queues. */ + +/* pqueue_new allocates a fresh, empty priority queue object and returns it, or + * NULL on error. */ +OPENSSL_EXPORT pqueue pqueue_new(void); + +/* pqueue_free frees |pq| but not any of the items it points to. Thus |pq| must + * be empty or a memory leak will occur. */ +OPENSSL_EXPORT void pqueue_free(pqueue pq); + + +/* Creating and freeing items. */ + +/* pitem_new allocates a fresh priority queue item that points at |data| and + * has a priority given by |prio64be|, which is a 64-bit, unsigned number + * expressed in big-endian form. It returns the fresh item, or NULL on + * error. */ +OPENSSL_EXPORT pitem *pitem_new(uint8_t prio64be[8], void *data); + +/* pitem_free frees |item|, but not any data that it points to. */ +OPENSSL_EXPORT void pitem_free(pitem *item); + + +/* Queue accessor functions */ + +/* pqueue_peek returns the item with the smallest priority from |pq|, or NULL + * if empty. */ +OPENSSL_EXPORT pitem *pqueue_peek(pqueue pq); + +/* pqueue_find returns the item whose priority matches |prio64be| or NULL if no + * such item exists. */ +OPENSSL_EXPORT pitem *pqueue_find(pqueue pq, uint8_t *prio64be); + + +/* Queue mutation functions */ + +/* pqueue_insert inserts |item| into |pq| and returns item. */ +OPENSSL_EXPORT pitem *pqueue_insert(pqueue pq, pitem *item); + +/* pqueue_pop takes the item with the least priority from |pq| and returns it, + * or NULL if |pq| is empty. */ +OPENSSL_EXPORT pitem *pqueue_pop(pqueue pq); + +/* pqueue_size returns the number of items in |pq|. */ +OPENSSL_EXPORT size_t pqueue_size(pqueue pq); + + +/* Iterating */ + +/* pqueue_iterator returns an iterator that can be used to iterate over the + * contents of the queue. */ +OPENSSL_EXPORT piterator pqueue_iterator(pqueue pq); + +/* pqueue_next returns the current value of |iter| and advances it to the next + * position. If the iterator has advanced over all the elements, it returns + * NULL. */ +OPENSSL_EXPORT pitem *pqueue_next(piterator *iter); + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_PQUEUE_H */ diff --git a/external/boringssl/include/openssl/rand.h b/external/boringssl/include/openssl/rand.h new file mode 100644 index 0000000000..322249c9f9 --- /dev/null +++ b/external/boringssl/include/openssl/rand.h @@ -0,0 +1,122 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_RAND_H +#define OPENSSL_HEADER_RAND_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* Random number generation. */ + + +/* RAND_bytes writes |len| bytes of random data to |buf| and returns one. */ +OPENSSL_EXPORT int RAND_bytes(uint8_t *buf, size_t len); + +/* RAND_cleanup frees any resources used by the RNG. This is not safe if other + * threads might still be calling |RAND_bytes|. */ +OPENSSL_EXPORT void RAND_cleanup(void); + + +/* Obscure functions. */ + +#if !defined(OPENSSL_WINDOWS) +/* RAND_set_urandom_fd causes the module to use a copy of |fd| for system + * randomness rather opening /dev/urandom internally. The caller retains + * ownership of |fd| and is at liberty to close it at any time. This is useful + * if, due to a sandbox, /dev/urandom isn't available. If used, it must be + * called before the first call to |RAND_bytes|, and it is mutually exclusive + * with |RAND_enable_fork_unsafe_buffering|. + * + * |RAND_set_urandom_fd| does not buffer any entropy, so it is safe to call + * |fork| at any time after calling |RAND_set_urandom_fd|. */ +OPENSSL_EXPORT void RAND_set_urandom_fd(int fd); + +/* RAND_enable_fork_unsafe_buffering enables efficient buffered reading of + * /dev/urandom. It adds an overhead of a few KB of memory per thread. It must + * be called before the first call to |RAND_bytes| and it is mutually exclusive + * with calls to |RAND_set_urandom_fd|. + * + * If |fd| is non-negative then a copy of |fd| will be used rather than opening + * /dev/urandom internally. Like |RAND_set_urandom_fd|, the caller retains + * ownership of |fd|. If |fd| is negative then /dev/urandom will be opened and + * any error from open(2) crashes the address space. + * + * It has an unusual name because the buffer is unsafe across calls to |fork|. + * Hence, this function should never be called by libraries. */ +OPENSSL_EXPORT void RAND_enable_fork_unsafe_buffering(int fd); +#endif + +#if defined(BORINGSSL_UNSAFE_FUZZER_MODE) +/* RAND_reset_for_fuzzing resets the fuzzer-only deterministic RNG. This + * function is only defined in the fuzzer-only build configuration. */ +OPENSSL_EXPORT void RAND_reset_for_fuzzing(void); +#endif + + +/* Deprecated functions */ + +/* RAND_pseudo_bytes is a wrapper around |RAND_bytes|. */ +OPENSSL_EXPORT int RAND_pseudo_bytes(uint8_t *buf, size_t len); + +/* RAND_seed reads a single byte of random data to ensure that any file + * descriptors etc are opened. */ +OPENSSL_EXPORT void RAND_seed(const void *buf, int num); + +/* RAND_load_file returns a nonnegative number. */ +OPENSSL_EXPORT int RAND_load_file(const char *path, long num); + +/* RAND_file_name returns NULL. */ +OPENSSL_EXPORT const char *RAND_file_name(char *buf, size_t num); + +/* RAND_add does nothing. */ +OPENSSL_EXPORT void RAND_add(const void *buf, int num, double entropy); + +/* RAND_egd returns 255. */ +OPENSSL_EXPORT int RAND_egd(const char *); + +/* RAND_poll returns one. */ +OPENSSL_EXPORT int RAND_poll(void); + +/* RAND_status returns one. */ +OPENSSL_EXPORT int RAND_status(void); + +/* rand_meth_st is typedefed to |RAND_METHOD| in base.h. It isn't used; it + * exists only to be the return type of |RAND_SSLeay|. It's + * external so that variables of this type can be initialized. */ +struct rand_meth_st { + void (*seed) (const void *buf, int num); + int (*bytes) (uint8_t *buf, size_t num); + void (*cleanup) (void); + void (*add) (const void *buf, int num, double entropy); + int (*pseudorand) (uint8_t *buf, size_t num); + int (*status) (void); +}; + +/* RAND_SSLeay returns a pointer to a dummy |RAND_METHOD|. */ +OPENSSL_EXPORT RAND_METHOD *RAND_SSLeay(void); + +/* RAND_set_rand_method does nothing. */ +OPENSSL_EXPORT void RAND_set_rand_method(const RAND_METHOD *); + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_RAND_H */ diff --git a/external/boringssl/include/openssl/rc4.h b/external/boringssl/include/openssl/rc4.h new file mode 100644 index 0000000000..68af8782ed --- /dev/null +++ b/external/boringssl/include/openssl/rc4.h @@ -0,0 +1,96 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_RC4_H +#define OPENSSL_HEADER_RC4_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* RC4. */ + + +struct rc4_key_st { + uint32_t x, y; + uint32_t data[256]; +} /* RC4_KEY */; + +/* RC4_set_key performs an RC4 key schedule and initialises |rc4key| with |len| + * bytes of key material from |key|. */ +OPENSSL_EXPORT void RC4_set_key(RC4_KEY *rc4key, unsigned len, + const uint8_t *key); + +/* RC4 encrypts (or decrypts, it's the same with RC4) |len| bytes from |in| to + * |out|. */ +OPENSSL_EXPORT void RC4(RC4_KEY *key, size_t len, const uint8_t *in, + uint8_t *out); + + +/* Deprecated functions. */ + +/* RC4_options returns the string "rc4(ptr,int)". */ +OPENSSL_EXPORT const char *RC4_options(void); + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_RC4_H */ diff --git a/external/boringssl/include/openssl/ripemd.h b/external/boringssl/include/openssl/ripemd.h new file mode 100644 index 0000000000..cf1e49e2a4 --- /dev/null +++ b/external/boringssl/include/openssl/ripemd.h @@ -0,0 +1,107 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_RIPEMD_H +#define OPENSSL_HEADER_RIPEMD_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +# define RIPEMD160_CBLOCK 64 +# define RIPEMD160_LBLOCK (RIPEMD160_CBLOCK/4) +# define RIPEMD160_DIGEST_LENGTH 20 + +struct RIPEMD160state_st { + uint32_t h[5]; + uint32_t Nl, Nh; + uint8_t data[RIPEMD160_CBLOCK]; + unsigned num; +}; + +/* RIPEMD160_Init initialises |ctx| and returns one. */ +OPENSSL_EXPORT int RIPEMD160_Init(RIPEMD160_CTX *ctx); + +/* RIPEMD160_Update adds |len| bytes from |data| to |ctx| and returns one. */ +OPENSSL_EXPORT int RIPEMD160_Update(RIPEMD160_CTX *ctx, const void *data, + size_t len); + +/* RIPEMD160_Final adds the final padding to |ctx| and writes the resulting + * digest to |md|, which must have at least |RIPEMD160_DIGEST_LENGTH| bytes of + * space. It returns one. */ +OPENSSL_EXPORT int RIPEMD160_Final(uint8_t *md, RIPEMD160_CTX *ctx); + +/* RIPEMD160 writes the digest of |len| bytes from |data| to |out| and returns + * |out|. There must be at least |RIPEMD160_DIGEST_LENGTH| bytes of space in + * |out|. */ +OPENSSL_EXPORT uint8_t *RIPEMD160(const uint8_t *data, size_t len, + uint8_t *out); + +/* RIPEMD160_Transform is a low-level function that performs a single, + * RIPEMD160 block transformation using the state from |ctx| and 64 bytes from + * |block|. */ +OPENSSL_EXPORT void RIPEMD160_Transform(RIPEMD160_CTX *ctx, + const uint8_t *block); + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_RIPEMD_H */ diff --git a/external/boringssl/include/openssl/rsa.h b/external/boringssl/include/openssl/rsa.h new file mode 100644 index 0000000000..063d2e8bfd --- /dev/null +++ b/external/boringssl/include/openssl/rsa.h @@ -0,0 +1,664 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_RSA_H +#define OPENSSL_HEADER_RSA_H + +#include + +#include +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* rsa.h contains functions for handling encryption and signature using RSA. */ + + +/* Allocation and destruction. */ + +/* RSA_new returns a new, empty RSA object or NULL on error. */ +OPENSSL_EXPORT RSA *RSA_new(void); + +/* RSA_new_method acts the same as |RSA_new| but takes an explicit |ENGINE|. */ +OPENSSL_EXPORT RSA *RSA_new_method(const ENGINE *engine); + +/* RSA_free decrements the reference count of |rsa| and frees it if the + * reference count drops to zero. */ +OPENSSL_EXPORT void RSA_free(RSA *rsa); + +/* RSA_up_ref increments the reference count of |rsa|. */ +OPENSSL_EXPORT int RSA_up_ref(RSA *rsa); + + +/* Key generation. */ + +/* RSA_generate_key_ex generates a new RSA key where the modulus has size + * |bits| and the public exponent is |e|. If unsure, |RSA_F4| is a good value + * for |e|. If |cb| is not NULL then it is called during the key generation + * process. In addition to the calls documented for |BN_generate_prime_ex|, it + * is called with event=2 when the n'th prime is rejected as unsuitable and + * with event=3 when a suitable value for |p| is found. + * + * It returns one on success or zero on error. */ +OPENSSL_EXPORT int RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e, + BN_GENCB *cb); + +/* RSA_generate_multi_prime_key acts like |RSA_generate_key_ex| but can + * generate an RSA private key with more than two primes. */ +OPENSSL_EXPORT int RSA_generate_multi_prime_key(RSA *rsa, int bits, + int num_primes, BIGNUM *e, + BN_GENCB *cb); + + +/* Encryption / Decryption */ + +/* Padding types for encryption. */ +#define RSA_PKCS1_PADDING 1 +#define RSA_NO_PADDING 3 +#define RSA_PKCS1_OAEP_PADDING 4 +/* RSA_PKCS1_PSS_PADDING can only be used via the EVP interface. */ +#define RSA_PKCS1_PSS_PADDING 6 + +/* RSA_encrypt encrypts |in_len| bytes from |in| to the public key from |rsa| + * and writes, at most, |max_out| bytes of encrypted data to |out|. The + * |max_out| argument must be, at least, |RSA_size| in order to ensure success. + * + * It returns 1 on success or zero on error. + * + * The |padding| argument must be one of the |RSA_*_PADDING| values. If in + * doubt, use |RSA_PKCS1_OAEP_PADDING| for new protocols but + * |RSA_PKCS1_PADDING| is most common. */ +OPENSSL_EXPORT int RSA_encrypt(RSA *rsa, size_t *out_len, uint8_t *out, + size_t max_out, const uint8_t *in, size_t in_len, + int padding); + +/* RSA_decrypt decrypts |in_len| bytes from |in| with the private key from + * |rsa| and writes, at most, |max_out| bytes of plaintext to |out|. The + * |max_out| argument must be, at least, |RSA_size| in order to ensure success. + * + * It returns 1 on success or zero on error. + * + * The |padding| argument must be one of the |RSA_*_PADDING| values. If in + * doubt, use |RSA_PKCS1_OAEP_PADDING| for new protocols. + * + * Passing |RSA_PKCS1_PADDING| into this function is deprecated and insecure. If + * implementing a protocol using RSAES-PKCS1-V1_5, use |RSA_NO_PADDING| and then + * check padding in constant-time combined with a swap to a random session key + * or other mitigation. See "Chosen Ciphertext Attacks Against Protocols Based + * on the RSA Encryption Standard PKCS #1", Daniel Bleichenbacher, Advances in + * Cryptology (Crypto '98). */ +OPENSSL_EXPORT int RSA_decrypt(RSA *rsa, size_t *out_len, uint8_t *out, + size_t max_out, const uint8_t *in, size_t in_len, + int padding); + +/* RSA_public_encrypt encrypts |flen| bytes from |from| to the public key in + * |rsa| and writes the encrypted data to |to|. The |to| buffer must have at + * least |RSA_size| bytes of space. It returns the number of bytes written, or + * -1 on error. The |padding| argument must be one of the |RSA_*_PADDING| + * values. If in doubt, use |RSA_PKCS1_OAEP_PADDING| for new protocols but + * |RSA_PKCS1_PADDING| is most common. + * + * WARNING: this function is dangerous because it breaks the usual return value + * convention. Use |RSA_encrypt| instead. */ +OPENSSL_EXPORT int RSA_public_encrypt(size_t flen, const uint8_t *from, + uint8_t *to, RSA *rsa, int padding); + +/* RSA_private_decrypt decrypts |flen| bytes from |from| with the public key in + * |rsa| and writes the plaintext to |to|. The |to| buffer must have at least + * |RSA_size| bytes of space. It returns the number of bytes written, or -1 on + * error. The |padding| argument must be one of the |RSA_*_PADDING| values. If + * in doubt, use |RSA_PKCS1_OAEP_PADDING| for new protocols. Passing + * |RSA_PKCS1_PADDING| into this function is deprecated and insecure. See + * |RSA_decrypt|. + * + * WARNING: this function is dangerous because it breaks the usual return value + * convention. Use |RSA_decrypt| instead. */ +OPENSSL_EXPORT int RSA_private_decrypt(size_t flen, const uint8_t *from, + uint8_t *to, RSA *rsa, int padding); + + +/* Signing / Verification */ + +/* RSA_sign signs |in_len| bytes of digest from |in| with |rsa| using + * RSASSA-PKCS1-v1_5. It writes, at most, |RSA_size(rsa)| bytes to |out|. On + * successful return, the actual number of bytes written is written to + * |*out_len|. + * + * The |hash_nid| argument identifies the hash function used to calculate |in| + * and is embedded in the resulting signature. For example, it might be + * |NID_sha256|. + * + * It returns 1 on success and zero on error. */ +OPENSSL_EXPORT int RSA_sign(int hash_nid, const uint8_t *in, + unsigned int in_len, uint8_t *out, + unsigned int *out_len, RSA *rsa); + +/* RSA_sign_raw signs |in_len| bytes from |in| with the public key from |rsa| + * and writes, at most, |max_out| bytes of signature data to |out|. The + * |max_out| argument must be, at least, |RSA_size| in order to ensure success. + * + * It returns 1 on success or zero on error. + * + * The |padding| argument must be one of the |RSA_*_PADDING| values. If in + * doubt, |RSA_PKCS1_PADDING| is the most common but |RSA_PKCS1_PSS_PADDING| + * (via the |EVP_PKEY| interface) is preferred for new protocols. */ +OPENSSL_EXPORT int RSA_sign_raw(RSA *rsa, size_t *out_len, uint8_t *out, + size_t max_out, const uint8_t *in, + size_t in_len, int padding); + +/* RSA_verify verifies that |sig_len| bytes from |sig| are a valid, + * RSASSA-PKCS1-v1_5 signature of |msg_len| bytes at |msg| by |rsa|. + * + * The |hash_nid| argument identifies the hash function used to calculate |in| + * and is embedded in the resulting signature in order to prevent hash + * confusion attacks. For example, it might be |NID_sha256|. + * + * It returns one if the signature is valid and zero otherwise. + * + * WARNING: this differs from the original, OpenSSL function which additionally + * returned -1 on error. */ +OPENSSL_EXPORT int RSA_verify(int hash_nid, const uint8_t *msg, size_t msg_len, + const uint8_t *sig, size_t sig_len, RSA *rsa); + +/* RSA_verify_raw verifies |in_len| bytes of signature from |in| using the + * public key from |rsa| and writes, at most, |max_out| bytes of plaintext to + * |out|. The |max_out| argument must be, at least, |RSA_size| in order to + * ensure success. + * + * It returns 1 on success or zero on error. + * + * The |padding| argument must be one of the |RSA_*_PADDING| values. If in + * doubt, |RSA_PKCS1_PADDING| is the most common but |RSA_PKCS1_PSS_PADDING| + * (via the |EVP_PKEY| interface) is preferred for new protocols. */ +OPENSSL_EXPORT int RSA_verify_raw(RSA *rsa, size_t *out_len, uint8_t *out, + size_t max_out, const uint8_t *in, + size_t in_len, int padding); + +/* RSA_private_encrypt encrypts |flen| bytes from |from| with the private key in + * |rsa| and writes the encrypted data to |to|. The |to| buffer must have at + * least |RSA_size| bytes of space. It returns the number of bytes written, or + * -1 on error. The |padding| argument must be one of the |RSA_*_PADDING| + * values. If in doubt, |RSA_PKCS1_PADDING| is the most common but + * |RSA_PKCS1_PSS_PADDING| (via the |EVP_PKEY| interface) is preferred for new + * protocols. + * + * WARNING: this function is dangerous because it breaks the usual return value + * convention. Use |RSA_sign_raw| instead. */ +OPENSSL_EXPORT int RSA_private_encrypt(size_t flen, const uint8_t *from, + uint8_t *to, RSA *rsa, int padding); + +/* RSA_public_decrypt verifies |flen| bytes of signature from |from| using the + * public key in |rsa| and writes the plaintext to |to|. The |to| buffer must + * have at least |RSA_size| bytes of space. It returns the number of bytes + * written, or -1 on error. The |padding| argument must be one of the + * |RSA_*_PADDING| values. If in doubt, |RSA_PKCS1_PADDING| is the most common + * but |RSA_PKCS1_PSS_PADDING| (via the |EVP_PKEY| interface) is preferred for + * new protocols. + * + * WARNING: this function is dangerous because it breaks the usual return value + * convention. Use |RSA_verify_raw| instead. */ +OPENSSL_EXPORT int RSA_public_decrypt(size_t flen, const uint8_t *from, + uint8_t *to, RSA *rsa, int padding); + + +/* Utility functions. */ + +/* RSA_size returns the number of bytes in the modulus, which is also the size + * of a signature or encrypted value using |rsa|. */ +OPENSSL_EXPORT unsigned RSA_size(const RSA *rsa); + +/* RSA_is_opaque returns one if |rsa| is opaque and doesn't expose its key + * material. Otherwise it returns zero. */ +OPENSSL_EXPORT int RSA_is_opaque(const RSA *rsa); + +/* RSA_supports_digest returns one if |rsa| supports signing digests + * of type |md|. Otherwise it returns zero. */ +OPENSSL_EXPORT int RSA_supports_digest(const RSA *rsa, const EVP_MD *md); + +/* RSAPublicKey_dup allocates a fresh |RSA| and copies the public key from + * |rsa| into it. It returns the fresh |RSA| object, or NULL on error. */ +OPENSSL_EXPORT RSA *RSAPublicKey_dup(const RSA *rsa); + +/* RSAPrivateKey_dup allocates a fresh |RSA| and copies the private key from + * |rsa| into it. It returns the fresh |RSA| object, or NULL on error. */ +OPENSSL_EXPORT RSA *RSAPrivateKey_dup(const RSA *rsa); + +/* RSA_check_key performs basic validatity tests on |rsa|. It returns one if + * they pass and zero otherwise. Opaque keys and public keys always pass. If it + * returns zero then a more detailed error is available on the error queue. */ +OPENSSL_EXPORT int RSA_check_key(const RSA *rsa); + +/* RSA_recover_crt_params uses |rsa->n|, |rsa->d| and |rsa->e| in order to + * calculate the two primes used and thus the precomputed, CRT values. These + * values are set in the |p|, |q|, |dmp1|, |dmq1| and |iqmp| members of |rsa|, + * which must be |NULL| on entry. It returns one on success and zero + * otherwise. */ +OPENSSL_EXPORT int RSA_recover_crt_params(RSA *rsa); + +/* RSA_verify_PKCS1_PSS_mgf1 verifies that |EM| is a correct PSS padding of + * |mHash|, where |mHash| is a digest produced by |Hash|. |EM| must point to + * exactly |RSA_size(rsa)| bytes of data. The |mgf1Hash| argument specifies the + * hash function for generating the mask. If NULL, |Hash| is used. The |sLen| + * argument specifies the expected salt length in bytes. If |sLen| is -1 then + * the salt length is the same as the hash length. If -2, then the salt length + * is maximal and is taken from the size of |EM|. + * + * It returns one on success or zero on error. */ +OPENSSL_EXPORT int RSA_verify_PKCS1_PSS_mgf1(RSA *rsa, const uint8_t *mHash, + const EVP_MD *Hash, + const EVP_MD *mgf1Hash, + const uint8_t *EM, int sLen); + +/* RSA_padding_add_PKCS1_PSS_mgf1 writes a PSS padding of |mHash| to |EM|, + * where |mHash| is a digest produced by |Hash|. |RSA_size(rsa)| bytes of + * output will be written to |EM|. The |mgf1Hash| argument specifies the hash + * function for generating the mask. If NULL, |Hash| is used. The |sLen| + * argument specifies the expected salt length in bytes. If |sLen| is -1 then + * the salt length is the same as the hash length. If -2, then the salt length + * is maximal given the space in |EM|. + * + * It returns one on success or zero on error. */ +OPENSSL_EXPORT int RSA_padding_add_PKCS1_PSS_mgf1(RSA *rsa, uint8_t *EM, + const uint8_t *mHash, + const EVP_MD *Hash, + const EVP_MD *mgf1Hash, + int sLen); + +/* RSA_padding_add_PKCS1_OAEP_mgf1 writes an OAEP padding of |from| to |to| + * with the given parameters and hash functions. If |md| is NULL then SHA-1 is + * used. If |mgf1md| is NULL then the value of |md| is used (which means SHA-1 + * if that, in turn, is NULL). + * + * It returns one on success or zero on error. */ +OPENSSL_EXPORT int RSA_padding_add_PKCS1_OAEP_mgf1( + uint8_t *to, unsigned to_len, const uint8_t *from, unsigned from_len, + const uint8_t *param, unsigned param_len, const EVP_MD *md, + const EVP_MD *mgf1md); + +/* RSA_add_pkcs1_prefix builds a version of |msg| prefixed with the DigestInfo + * header for the given hash function and sets |out_msg| to point to it. On + * successful return, |*out_msg| may be allocated memory and, if so, + * |*is_alloced| will be 1. */ +OPENSSL_EXPORT int RSA_add_pkcs1_prefix(uint8_t **out_msg, size_t *out_msg_len, + int *is_alloced, int hash_nid, + const uint8_t *msg, size_t msg_len); + + +/* ASN.1 functions. */ + +/* RSA_parse_public_key parses a DER-encoded RSAPublicKey structure (RFC 3447) + * from |cbs| and advances |cbs|. It returns a newly-allocated |RSA| or NULL on + * error. */ +OPENSSL_EXPORT RSA *RSA_parse_public_key(CBS *cbs); + +/* RSA_parse_public_key_buggy behaves like |RSA_parse_public_key|, but it + * tolerates some invalid encodings. Do not use this function. */ +OPENSSL_EXPORT RSA *RSA_parse_public_key_buggy(CBS *cbs); + +/* RSA_public_key_from_bytes parses |in| as a DER-encoded RSAPublicKey structure + * (RFC 3447). It returns a newly-allocated |RSA| or NULL on error. */ +OPENSSL_EXPORT RSA *RSA_public_key_from_bytes(const uint8_t *in, size_t in_len); + +/* RSA_marshal_public_key marshals |rsa| as a DER-encoded RSAPublicKey structure + * (RFC 3447) and appends the result to |cbb|. It returns one on success and + * zero on failure. */ +OPENSSL_EXPORT int RSA_marshal_public_key(CBB *cbb, const RSA *rsa); + +/* RSA_public_key_to_bytes marshals |rsa| as a DER-encoded RSAPublicKey + * structure (RFC 3447) and, on success, sets |*out_bytes| to a newly allocated + * buffer containing the result and returns one. Otherwise, it returns zero. The + * result should be freed with |OPENSSL_free|. */ +OPENSSL_EXPORT int RSA_public_key_to_bytes(uint8_t **out_bytes, size_t *out_len, + const RSA *rsa); + +/* RSA_parse_private_key parses a DER-encoded RSAPrivateKey structure (RFC 3447) + * from |cbs| and advances |cbs|. It returns a newly-allocated |RSA| or NULL on + * error. */ +OPENSSL_EXPORT RSA *RSA_parse_private_key(CBS *cbs); + +/* RSA_private_key_from_bytes parses |in| as a DER-encoded RSAPrivateKey + * structure (RFC 3447). It returns a newly-allocated |RSA| or NULL on error. */ +OPENSSL_EXPORT RSA *RSA_private_key_from_bytes(const uint8_t *in, + size_t in_len); + +/* RSA_marshal_private_key marshals |rsa| as a DER-encoded RSAPrivateKey + * structure (RFC 3447) and appends the result to |cbb|. It returns one on + * success and zero on failure. */ +OPENSSL_EXPORT int RSA_marshal_private_key(CBB *cbb, const RSA *rsa); + +/* RSA_private_key_to_bytes marshals |rsa| as a DER-encoded RSAPrivateKey + * structure (RFC 3447) and, on success, sets |*out_bytes| to a newly allocated + * buffer containing the result and returns one. Otherwise, it returns zero. The + * result should be freed with |OPENSSL_free|. */ +OPENSSL_EXPORT int RSA_private_key_to_bytes(uint8_t **out_bytes, + size_t *out_len, const RSA *rsa); + + +/* ex_data functions. + * + * See |ex_data.h| for details. */ + +OPENSSL_EXPORT int RSA_get_ex_new_index(long argl, void *argp, + CRYPTO_EX_unused *unused, + CRYPTO_EX_dup *dup_func, + CRYPTO_EX_free *free_func); +OPENSSL_EXPORT int RSA_set_ex_data(RSA *r, int idx, void *arg); +OPENSSL_EXPORT void *RSA_get_ex_data(const RSA *r, int idx); + + +/* Flags. */ + +/* RSA_FLAG_OPAQUE specifies that this RSA_METHOD does not expose its key + * material. This may be set if, for instance, it is wrapping some other crypto + * API, like a platform key store. */ +#define RSA_FLAG_OPAQUE 1 + +/* Deprecated and ignored. */ +#define RSA_FLAG_CACHE_PUBLIC 2 + +/* Deprecated and ignored. */ +#define RSA_FLAG_CACHE_PRIVATE 4 + +/* RSA_FLAG_NO_BLINDING disables blinding of private operations, which is a + * dangerous thing to do. It is deprecated and should not be used. It will + * be ignored whenever possible. + * + * This flag must be used if a key without the public exponent |e| is used for + * private key operations; avoid using such keys whenever possible. */ +#define RSA_FLAG_NO_BLINDING 8 + +/* RSA_FLAG_EXT_PKEY is deprecated and ignored. */ +#define RSA_FLAG_EXT_PKEY 0x20 + +/* RSA_FLAG_SIGN_VER causes the |sign| and |verify| functions of |rsa_meth_st| + * to be called when set. */ +#define RSA_FLAG_SIGN_VER 0x40 + + +/* RSA public exponent values. */ + +#define RSA_3 0x3 +#define RSA_F4 0x10001 + + +/* Deprecated functions. */ + +/* RSA_blinding_on returns one. */ +OPENSSL_EXPORT int RSA_blinding_on(RSA *rsa, BN_CTX *ctx); + +/* RSA_generate_key behaves like |RSA_generate_key_ex|, which is what you + * should use instead. It returns NULL on error, or a newly-allocated |RSA| on + * success. This function is provided for compatibility only. The |callback| + * and |cb_arg| parameters must be NULL. */ +OPENSSL_EXPORT RSA *RSA_generate_key(int bits, unsigned long e, void *callback, + void *cb_arg); + +/* d2i_RSAPublicKey parses an ASN.1, DER-encoded, RSA public key from |len| + * bytes at |*inp|. If |out| is not NULL then, on exit, a pointer to the result + * is in |*out|. Note that, even if |*out| is already non-NULL on entry, it + * will not be written to. Rather, a fresh |RSA| is allocated and the previous + * one is freed. On successful exit, |*inp| is advanced past the DER structure. + * It returns the result or NULL on error. */ +OPENSSL_EXPORT RSA *d2i_RSAPublicKey(RSA **out, const uint8_t **inp, long len); + +/* i2d_RSAPublicKey marshals |in| to an ASN.1, DER structure. If |outp| is not + * NULL then the result is written to |*outp| and |*outp| is advanced just past + * the output. It returns the number of bytes in the result, whether written or + * not, or a negative value on error. */ +OPENSSL_EXPORT int i2d_RSAPublicKey(const RSA *in, uint8_t **outp); + +/* d2i_RSAPrivateKey parses an ASN.1, DER-encoded, RSA private key from |len| + * bytes at |*inp|. If |out| is not NULL then, on exit, a pointer to the result + * is in |*out|. Note that, even if |*out| is already non-NULL on entry, it + * will not be written to. Rather, a fresh |RSA| is allocated and the previous + * one is freed. On successful exit, |*inp| is advanced past the DER structure. + * It returns the result or NULL on error. */ +OPENSSL_EXPORT RSA *d2i_RSAPrivateKey(RSA **out, const uint8_t **inp, long len); + +/* i2d_RSAPrivateKey marshals |in| to an ASN.1, DER structure. If |outp| is not + * NULL then the result is written to |*outp| and |*outp| is advanced just past + * the output. It returns the number of bytes in the result, whether written or + * not, or a negative value on error. */ +OPENSSL_EXPORT int i2d_RSAPrivateKey(const RSA *in, uint8_t **outp); + +/* RSA_padding_add_PKCS1_PSS acts like |RSA_padding_add_PKCS1_PSS_mgf1| but the + * |mgf1Hash| parameter of the latter is implicitly set to |Hash|. */ +OPENSSL_EXPORT int RSA_padding_add_PKCS1_PSS(RSA *rsa, uint8_t *EM, + const uint8_t *mHash, + const EVP_MD *Hash, int sLen); + +/* RSA_verify_PKCS1_PSS acts like |RSA_verify_PKCS1_PSS_mgf1| but the + * |mgf1Hash| parameter of the latter is implicitly set to |Hash|. */ +OPENSSL_EXPORT int RSA_verify_PKCS1_PSS(RSA *rsa, const uint8_t *mHash, + const EVP_MD *Hash, const uint8_t *EM, + int sLen); + +/* RSA_padding_add_PKCS1_OAEP acts like |RSA_padding_add_PKCS1_OAEP_mgf1| but + * the |md| and |mgf1md| paramaters of the latter are implicitly set to NULL, + * which means SHA-1. */ +OPENSSL_EXPORT int RSA_padding_add_PKCS1_OAEP(uint8_t *to, unsigned to_len, + const uint8_t *from, + unsigned from_len, + const uint8_t *param, + unsigned param_len); + + +struct rsa_meth_st { + struct openssl_method_common_st common; + + void *app_data; + + int (*init)(RSA *rsa); + int (*finish)(RSA *rsa); + + /* size returns the size of the RSA modulus in bytes. */ + size_t (*size)(const RSA *rsa); + + int (*sign)(int type, const uint8_t *m, unsigned int m_length, + uint8_t *sigret, unsigned int *siglen, const RSA *rsa); + + /* Ignored. Set this to NULL. */ + int (*verify)(int dtype, const uint8_t *m, unsigned int m_length, + const uint8_t *sigbuf, unsigned int siglen, const RSA *rsa); + + + /* These functions mirror the |RSA_*| functions of the same name. */ + int (*encrypt)(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out, + const uint8_t *in, size_t in_len, int padding); + int (*sign_raw)(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out, + const uint8_t *in, size_t in_len, int padding); + + int (*decrypt)(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out, + const uint8_t *in, size_t in_len, int padding); + /* Ignored. Set this to NULL. */ + int (*verify_raw)(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out, + const uint8_t *in, size_t in_len, int padding); + + /* private_transform takes a big-endian integer from |in|, calculates the + * d'th power of it, modulo the RSA modulus and writes the result as a + * big-endian integer to |out|. Both |in| and |out| are |len| bytes long and + * |len| is always equal to |RSA_size(rsa)|. If the result of the transform + * can be represented in fewer than |len| bytes, then |out| must be zero + * padded on the left. + * + * It returns one on success and zero otherwise. + * + * RSA decrypt and sign operations will call this, thus an ENGINE might wish + * to override it in order to avoid having to implement the padding + * functionality demanded by those, higher level, operations. */ + int (*private_transform)(RSA *rsa, uint8_t *out, const uint8_t *in, + size_t len); + + /* mod_exp is deprecated and ignored. Set it to NULL. */ + int (*mod_exp)(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx); + + /* bn_mod_exp is deprecated and ignored. Set it to NULL. */ + int (*bn_mod_exp)(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, + const BN_MONT_CTX *mont); + + int flags; + + int (*keygen)(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb); + + int (*multi_prime_keygen)(RSA *rsa, int bits, int num_primes, BIGNUM *e, + BN_GENCB *cb); + + /* supports_digest returns one if |rsa| supports digests of type + * |md|. If null, it is assumed that all digests are supported. */ + int (*supports_digest)(const RSA *rsa, const EVP_MD *md); +}; + + +/* Private functions. */ + +typedef struct bn_blinding_st BN_BLINDING; + +struct rsa_st { + RSA_METHOD *meth; + + BIGNUM *n; + BIGNUM *e; + BIGNUM *d; + BIGNUM *p; + BIGNUM *q; + BIGNUM *dmp1; + BIGNUM *dmq1; + BIGNUM *iqmp; + + STACK_OF(RSA_additional_prime) *additional_primes; + + /* be careful using this if the RSA structure is shared */ + CRYPTO_EX_DATA ex_data; + CRYPTO_refcount_t references; + int flags; + + CRYPTO_MUTEX lock; + + /* Used to cache montgomery values. The creation of these values is protected + * by |lock|. */ + BN_MONT_CTX *mont_n; + BN_MONT_CTX *mont_p; + BN_MONT_CTX *mont_q; + + /* num_blindings contains the size of the |blindings| and |blindings_inuse| + * arrays. This member and the |blindings_inuse| array are protected by + * |lock|. */ + unsigned num_blindings; + /* blindings is an array of BN_BLINDING structures that can be reserved by a + * thread by locking |lock| and changing the corresponding element in + * |blindings_inuse| from 0 to 1. */ + BN_BLINDING **blindings; + unsigned char *blindings_inuse; +}; + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#define RSA_R_BAD_ENCODING 100 +#define RSA_R_BAD_E_VALUE 101 +#define RSA_R_BAD_FIXED_HEADER_DECRYPT 102 +#define RSA_R_BAD_PAD_BYTE_COUNT 103 +#define RSA_R_BAD_RSA_PARAMETERS 104 +#define RSA_R_BAD_SIGNATURE 105 +#define RSA_R_BAD_VERSION 106 +#define RSA_R_BLOCK_TYPE_IS_NOT_01 107 +#define RSA_R_BN_NOT_INITIALIZED 108 +#define RSA_R_CANNOT_RECOVER_MULTI_PRIME_KEY 109 +#define RSA_R_CRT_PARAMS_ALREADY_GIVEN 110 +#define RSA_R_CRT_VALUES_INCORRECT 111 +#define RSA_R_DATA_LEN_NOT_EQUAL_TO_MOD_LEN 112 +#define RSA_R_DATA_TOO_LARGE 113 +#define RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE 114 +#define RSA_R_DATA_TOO_LARGE_FOR_MODULUS 115 +#define RSA_R_DATA_TOO_SMALL 116 +#define RSA_R_DATA_TOO_SMALL_FOR_KEY_SIZE 117 +#define RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY 118 +#define RSA_R_D_E_NOT_CONGRUENT_TO_1 119 +#define RSA_R_EMPTY_PUBLIC_KEY 120 +#define RSA_R_ENCODE_ERROR 121 +#define RSA_R_FIRST_OCTET_INVALID 122 +#define RSA_R_INCONSISTENT_SET_OF_CRT_VALUES 123 +#define RSA_R_INTERNAL_ERROR 124 +#define RSA_R_INVALID_MESSAGE_LENGTH 125 +#define RSA_R_KEY_SIZE_TOO_SMALL 126 +#define RSA_R_LAST_OCTET_INVALID 127 +#define RSA_R_MODULUS_TOO_LARGE 128 +#define RSA_R_MUST_HAVE_AT_LEAST_TWO_PRIMES 129 +#define RSA_R_NO_PUBLIC_EXPONENT 130 +#define RSA_R_NULL_BEFORE_BLOCK_MISSING 131 +#define RSA_R_N_NOT_EQUAL_P_Q 132 +#define RSA_R_OAEP_DECODING_ERROR 133 +#define RSA_R_ONLY_ONE_OF_P_Q_GIVEN 134 +#define RSA_R_OUTPUT_BUFFER_TOO_SMALL 135 +#define RSA_R_PADDING_CHECK_FAILED 136 +#define RSA_R_PKCS_DECODING_ERROR 137 +#define RSA_R_SLEN_CHECK_FAILED 138 +#define RSA_R_SLEN_RECOVERY_FAILED 139 +#define RSA_R_TOO_LONG 140 +#define RSA_R_TOO_MANY_ITERATIONS 141 +#define RSA_R_UNKNOWN_ALGORITHM_TYPE 142 +#define RSA_R_UNKNOWN_PADDING_TYPE 143 +#define RSA_R_VALUE_MISSING 144 +#define RSA_R_WRONG_SIGNATURE_LENGTH 145 + +#endif /* OPENSSL_HEADER_RSA_H */ diff --git a/external/boringssl/include/openssl/safestack.h b/external/boringssl/include/openssl/safestack.h new file mode 100644 index 0000000000..6e5e433074 --- /dev/null +++ b/external/boringssl/include/openssl/safestack.h @@ -0,0 +1,16 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +/* This header is provided in order to make compiling against code that expects + OpenSSL easier. */ diff --git a/external/boringssl/include/openssl/sha.h b/external/boringssl/include/openssl/sha.h new file mode 100644 index 0000000000..48a52e8f0e --- /dev/null +++ b/external/boringssl/include/openssl/sha.h @@ -0,0 +1,256 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_SHA_H +#define OPENSSL_HEADER_SHA_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* The SHA family of hash functions (SHA-1 and SHA-2). */ + + +/* SHA_CBLOCK is the block size of SHA-1. */ +#define SHA_CBLOCK 64 + +/* SHA_DIGEST_LENGTH is the length of a SHA-1 digest. */ +#define SHA_DIGEST_LENGTH 20 + +/* TODO(fork): remove */ +#define SHA_LBLOCK 16 +#define SHA_LONG uint32_t + +/* SHA1_Init initialises |sha| and returns one. */ +OPENSSL_EXPORT int SHA1_Init(SHA_CTX *sha); + +/* SHA1_Update adds |len| bytes from |data| to |sha| and returns one. */ +OPENSSL_EXPORT int SHA1_Update(SHA_CTX *sha, const void *data, size_t len); + +/* SHA1_Final adds the final padding to |sha| and writes the resulting digest + * to |md|, which must have at least |SHA_DIGEST_LENGTH| bytes of space. It + * returns one. */ +OPENSSL_EXPORT int SHA1_Final(uint8_t *md, SHA_CTX *sha); + +/* SHA1 writes the digest of |len| bytes from |data| to |out| and returns + * |out|. There must be at least |SHA_DIGEST_LENGTH| bytes of space in + * |out|. */ +OPENSSL_EXPORT uint8_t *SHA1(const uint8_t *data, size_t len, uint8_t *out); + +/* SHA1_Transform is a low-level function that performs a single, SHA-1 block + * transformation using the state from |sha| and 64 bytes from |block|. */ +OPENSSL_EXPORT void SHA1_Transform(SHA_CTX *sha, const uint8_t *block); + +struct sha_state_st { +#if defined(OPENSSL_WINDOWS) + uint32_t h[5]; +#else + /* wpa_supplicant accesses |h0|..|h4| so we must support those names + * for compatibility with it until it can be updated. */ + union { + uint32_t h[5]; + struct { + uint32_t h0; + uint32_t h1; + uint32_t h2; + uint32_t h3; + uint32_t h4; + }; + }; +#endif + uint32_t Nl, Nh; + uint8_t data[SHA_CBLOCK]; + unsigned num; +}; + + +/* SHA-224. */ + +/* SHA224_CBLOCK is the block size of SHA-224. */ +#define SHA224_CBLOCK 64 + +/* SHA224_DIGEST_LENGTH is the length of a SHA-224 digest. */ +#define SHA224_DIGEST_LENGTH 28 + +/* SHA224_Init initialises |sha| and returns 1. */ +OPENSSL_EXPORT int SHA224_Init(SHA256_CTX *sha); + +/* SHA224_Update adds |len| bytes from |data| to |sha| and returns 1. */ +OPENSSL_EXPORT int SHA224_Update(SHA256_CTX *sha, const void *data, size_t len); + +/* SHA224_Final adds the final padding to |sha| and writes the resulting digest + * to |md|, which must have at least |SHA224_DIGEST_LENGTH| bytes of space. It + * returns one on success and zero on programmer error. */ +OPENSSL_EXPORT int SHA224_Final(uint8_t *md, SHA256_CTX *sha); + +/* SHA224 writes the digest of |len| bytes from |data| to |out| and returns + * |out|. There must be at least |SHA224_DIGEST_LENGTH| bytes of space in + * |out|. */ +OPENSSL_EXPORT uint8_t *SHA224(const uint8_t *data, size_t len, uint8_t *out); + + +/* SHA-256. */ + +/* SHA256_CBLOCK is the block size of SHA-256. */ +#define SHA256_CBLOCK 64 + +/* SHA256_DIGEST_LENGTH is the length of a SHA-256 digest. */ +#define SHA256_DIGEST_LENGTH 32 + +/* SHA256_Init initialises |sha| and returns 1. */ +OPENSSL_EXPORT int SHA256_Init(SHA256_CTX *sha); + +/* SHA256_Update adds |len| bytes from |data| to |sha| and returns 1. */ +OPENSSL_EXPORT int SHA256_Update(SHA256_CTX *sha, const void *data, size_t len); + +/* SHA256_Final adds the final padding to |sha| and writes the resulting digest + * to |md|, which must have at least |SHA256_DIGEST_LENGTH| bytes of space. It + * returns one on success and zero on programmer error. */ +OPENSSL_EXPORT int SHA256_Final(uint8_t *md, SHA256_CTX *sha); + +/* SHA256 writes the digest of |len| bytes from |data| to |out| and returns + * |out|. There must be at least |SHA256_DIGEST_LENGTH| bytes of space in + * |out|. */ +OPENSSL_EXPORT uint8_t *SHA256(const uint8_t *data, size_t len, uint8_t *out); + +/* SHA256_Transform is a low-level function that performs a single, SHA-1 block + * transformation using the state from |sha| and 64 bytes from |block|. */ +OPENSSL_EXPORT void SHA256_Transform(SHA256_CTX *sha, const uint8_t *data); + +struct sha256_state_st { + uint32_t h[8]; + uint32_t Nl, Nh; + uint8_t data[SHA256_CBLOCK]; + unsigned num, md_len; +}; + + +/* SHA-384. */ + +/* SHA384_CBLOCK is the block size of SHA-384. */ +#define SHA384_CBLOCK 128 + +/* SHA384_DIGEST_LENGTH is the length of a SHA-384 digest. */ +#define SHA384_DIGEST_LENGTH 48 + +/* SHA384_Init initialises |sha| and returns 1. */ +OPENSSL_EXPORT int SHA384_Init(SHA512_CTX *sha); + +/* SHA384_Update adds |len| bytes from |data| to |sha| and returns 1. */ +OPENSSL_EXPORT int SHA384_Update(SHA512_CTX *sha, const void *data, size_t len); + +/* SHA384_Final adds the final padding to |sha| and writes the resulting digest + * to |md|, which must have at least |SHA384_DIGEST_LENGTH| bytes of space. It + * returns one on success and zero on programmer error. */ +OPENSSL_EXPORT int SHA384_Final(uint8_t *md, SHA512_CTX *sha); + +/* SHA384 writes the digest of |len| bytes from |data| to |out| and returns + * |out|. There must be at least |SHA384_DIGEST_LENGTH| bytes of space in + * |out|. */ +OPENSSL_EXPORT uint8_t *SHA384(const uint8_t *data, size_t len, uint8_t *out); + +/* SHA384_Transform is a low-level function that performs a single, SHA-1 block + * transformation using the state from |sha| and 64 bytes from |block|. */ +OPENSSL_EXPORT void SHA384_Transform(SHA512_CTX *sha, const uint8_t *data); + + +/* SHA-512. */ + +/* SHA512_CBLOCK is the block size of SHA-512. */ +#define SHA512_CBLOCK 128 + +/* SHA512_DIGEST_LENGTH is the length of a SHA-512 digest. */ +#define SHA512_DIGEST_LENGTH 64 + +/* SHA512_Init initialises |sha| and returns 1. */ +OPENSSL_EXPORT int SHA512_Init(SHA512_CTX *sha); + +/* SHA512_Update adds |len| bytes from |data| to |sha| and returns 1. */ +OPENSSL_EXPORT int SHA512_Update(SHA512_CTX *sha, const void *data, size_t len); + +/* SHA512_Final adds the final padding to |sha| and writes the resulting digest + * to |md|, which must have at least |SHA512_DIGEST_LENGTH| bytes of space. It + * returns one on success and zero on programmer error. */ +OPENSSL_EXPORT int SHA512_Final(uint8_t *md, SHA512_CTX *sha); + +/* SHA512 writes the digest of |len| bytes from |data| to |out| and returns + * |out|. There must be at least |SHA512_DIGEST_LENGTH| bytes of space in + * |out|. */ +OPENSSL_EXPORT uint8_t *SHA512(const uint8_t *data, size_t len, uint8_t *out); + +/* SHA512_Transform is a low-level function that performs a single, SHA-1 block + * transformation using the state from |sha| and 64 bytes from |block|. */ +OPENSSL_EXPORT void SHA512_Transform(SHA512_CTX *sha, const uint8_t *data); + +struct sha512_state_st { + uint64_t h[8]; + uint64_t Nl, Nh; + union { + uint64_t d[16]; + uint8_t p[128]; + } u; + unsigned num, md_len; +}; + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_SHA_H */ diff --git a/external/boringssl/include/openssl/srtp.h b/external/boringssl/include/openssl/srtp.h new file mode 100644 index 0000000000..39f6a85521 --- /dev/null +++ b/external/boringssl/include/openssl/srtp.h @@ -0,0 +1,18 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +/* This header is provided in order to make compiling against code that expects + OpenSSL easier. */ + +#include "ssl.h" diff --git a/external/boringssl/include/openssl/ssl.h.REMOVED.git-id b/external/boringssl/include/openssl/ssl.h.REMOVED.git-id new file mode 100644 index 0000000000..d33f818a5d --- /dev/null +++ b/external/boringssl/include/openssl/ssl.h.REMOVED.git-id @@ -0,0 +1 @@ +b8d1f7b5eb6f7ed875eff1a0ffbb98ce11d2bff3 \ No newline at end of file diff --git a/external/boringssl/include/openssl/ssl3.h b/external/boringssl/include/openssl/ssl3.h new file mode 100644 index 0000000000..1da5de72c7 --- /dev/null +++ b/external/boringssl/include/openssl/ssl3.h @@ -0,0 +1,435 @@ +/* ssl/ssl3.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * ECC cipher suite support in OpenSSL originally developed by + * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. + */ + +#ifndef OPENSSL_HEADER_SSL3_H +#define OPENSSL_HEADER_SSL3_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +/* These are kept to support clients that negotiates higher protocol versions + * using SSLv2 client hello records. */ +#define SSL2_MT_CLIENT_HELLO 1 +#define SSL2_VERSION 0x0002 + +/* Signalling cipher suite value from RFC 5746. */ +#define SSL3_CK_SCSV 0x030000FF +/* Fallback signalling cipher suite value from RFC 7507. */ +#define SSL3_CK_FALLBACK_SCSV 0x03005600 + +#define SSL3_CK_RSA_NULL_MD5 0x03000001 +#define SSL3_CK_RSA_NULL_SHA 0x03000002 +#define SSL3_CK_RSA_RC4_40_MD5 0x03000003 +#define SSL3_CK_RSA_RC4_128_MD5 0x03000004 +#define SSL3_CK_RSA_RC4_128_SHA 0x03000005 +#define SSL3_CK_RSA_RC2_40_MD5 0x03000006 +#define SSL3_CK_RSA_IDEA_128_SHA 0x03000007 +#define SSL3_CK_RSA_DES_40_CBC_SHA 0x03000008 +#define SSL3_CK_RSA_DES_64_CBC_SHA 0x03000009 +#define SSL3_CK_RSA_DES_192_CBC3_SHA 0x0300000A + +#define SSL3_CK_DH_DSS_DES_40_CBC_SHA 0x0300000B +#define SSL3_CK_DH_DSS_DES_64_CBC_SHA 0x0300000C +#define SSL3_CK_DH_DSS_DES_192_CBC3_SHA 0x0300000D +#define SSL3_CK_DH_RSA_DES_40_CBC_SHA 0x0300000E +#define SSL3_CK_DH_RSA_DES_64_CBC_SHA 0x0300000F +#define SSL3_CK_DH_RSA_DES_192_CBC3_SHA 0x03000010 + +#define SSL3_CK_EDH_DSS_DES_40_CBC_SHA 0x03000011 +#define SSL3_CK_EDH_DSS_DES_64_CBC_SHA 0x03000012 +#define SSL3_CK_EDH_DSS_DES_192_CBC3_SHA 0x03000013 +#define SSL3_CK_EDH_RSA_DES_40_CBC_SHA 0x03000014 +#define SSL3_CK_EDH_RSA_DES_64_CBC_SHA 0x03000015 +#define SSL3_CK_EDH_RSA_DES_192_CBC3_SHA 0x03000016 + +#define SSL3_CK_ADH_RC4_40_MD5 0x03000017 +#define SSL3_CK_ADH_RC4_128_MD5 0x03000018 +#define SSL3_CK_ADH_DES_40_CBC_SHA 0x03000019 +#define SSL3_CK_ADH_DES_64_CBC_SHA 0x0300001A +#define SSL3_CK_ADH_DES_192_CBC_SHA 0x0300001B + +#define SSL3_TXT_RSA_NULL_MD5 "NULL-MD5" +#define SSL3_TXT_RSA_NULL_SHA "NULL-SHA" +#define SSL3_TXT_RSA_RC4_40_MD5 "EXP-RC4-MD5" +#define SSL3_TXT_RSA_RC4_128_MD5 "RC4-MD5" +#define SSL3_TXT_RSA_RC4_128_SHA "RC4-SHA" +#define SSL3_TXT_RSA_RC2_40_MD5 "EXP-RC2-CBC-MD5" +#define SSL3_TXT_RSA_IDEA_128_SHA "IDEA-CBC-SHA" +#define SSL3_TXT_RSA_DES_40_CBC_SHA "EXP-DES-CBC-SHA" +#define SSL3_TXT_RSA_DES_64_CBC_SHA "DES-CBC-SHA" +#define SSL3_TXT_RSA_DES_192_CBC3_SHA "DES-CBC3-SHA" + +#define SSL3_TXT_DH_DSS_DES_40_CBC_SHA "EXP-DH-DSS-DES-CBC-SHA" +#define SSL3_TXT_DH_DSS_DES_64_CBC_SHA "DH-DSS-DES-CBC-SHA" +#define SSL3_TXT_DH_DSS_DES_192_CBC3_SHA "DH-DSS-DES-CBC3-SHA" +#define SSL3_TXT_DH_RSA_DES_40_CBC_SHA "EXP-DH-RSA-DES-CBC-SHA" +#define SSL3_TXT_DH_RSA_DES_64_CBC_SHA "DH-RSA-DES-CBC-SHA" +#define SSL3_TXT_DH_RSA_DES_192_CBC3_SHA "DH-RSA-DES-CBC3-SHA" + +#define SSL3_TXT_EDH_DSS_DES_40_CBC_SHA "EXP-EDH-DSS-DES-CBC-SHA" +#define SSL3_TXT_EDH_DSS_DES_64_CBC_SHA "EDH-DSS-DES-CBC-SHA" +#define SSL3_TXT_EDH_DSS_DES_192_CBC3_SHA "EDH-DSS-DES-CBC3-SHA" +#define SSL3_TXT_EDH_RSA_DES_40_CBC_SHA "EXP-EDH-RSA-DES-CBC-SHA" +#define SSL3_TXT_EDH_RSA_DES_64_CBC_SHA "EDH-RSA-DES-CBC-SHA" +#define SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA "EDH-RSA-DES-CBC3-SHA" + +#define SSL3_TXT_ADH_RC4_40_MD5 "EXP-ADH-RC4-MD5" +#define SSL3_TXT_ADH_RC4_128_MD5 "ADH-RC4-MD5" +#define SSL3_TXT_ADH_DES_40_CBC_SHA "EXP-ADH-DES-CBC-SHA" +#define SSL3_TXT_ADH_DES_64_CBC_SHA "ADH-DES-CBC-SHA" +#define SSL3_TXT_ADH_DES_192_CBC_SHA "ADH-DES-CBC3-SHA" + +#define SSL3_SSL_SESSION_ID_LENGTH 32 +#define SSL3_MAX_SSL_SESSION_ID_LENGTH 32 + +#define SSL3_MASTER_SECRET_SIZE 48 +#define SSL3_RANDOM_SIZE 32 +#define SSL3_SESSION_ID_SIZE 32 +#define SSL3_RT_HEADER_LENGTH 5 + +#define SSL3_HM_HEADER_LENGTH 4 + +#ifndef SSL3_ALIGN_PAYLOAD +/* Some will argue that this increases memory footprint, but it's not actually + * true. Point is that malloc has to return at least 64-bit aligned pointers, + * meaning that allocating 5 bytes wastes 3 bytes in either case. Suggested + * pre-gaping simply moves these wasted bytes from the end of allocated region + * to its front, but makes data payload aligned, which improves performance. */ +#define SSL3_ALIGN_PAYLOAD 8 +#else +#if (SSL3_ALIGN_PAYLOAD & (SSL3_ALIGN_PAYLOAD - 1)) != 0 +#error "insane SSL3_ALIGN_PAYLOAD" +#undef SSL3_ALIGN_PAYLOAD +#endif +#endif + +/* This is the maximum MAC (digest) size used by the SSL library. Currently + * maximum of 20 is used by SHA1, but we reserve for future extension for + * 512-bit hashes. */ + +#define SSL3_RT_MAX_MD_SIZE 64 + +/* Maximum block size used in all ciphersuites. Currently 16 for AES. */ + +#define SSL_RT_MAX_CIPHER_BLOCK_SIZE 16 + +/* Maximum plaintext length: defined by SSL/TLS standards */ +#define SSL3_RT_MAX_PLAIN_LENGTH 16384 +/* Maximum compression overhead: defined by SSL/TLS standards */ +#define SSL3_RT_MAX_COMPRESSED_OVERHEAD 1024 + +/* The standards give a maximum encryption overhead of 1024 bytes. In practice + * the value is lower than this. The overhead is the maximum number of padding + * bytes (256) plus the mac size. + * + * TODO(davidben): This derivation doesn't take AEADs into account, or TLS 1.1 + * explicit nonces. It happens to work because |SSL3_RT_MAX_MD_SIZE| is larger + * than necessary and no true AEAD has variable overhead in TLS 1.2. */ +#define SSL3_RT_MAX_ENCRYPTED_OVERHEAD (256 + SSL3_RT_MAX_MD_SIZE) + +/* SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD is the maximum overhead in encrypting a + * record. This does not include the record header. Some ciphers use explicit + * nonces, so it includes both the AEAD overhead as well as the nonce. */ +#define SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD \ + (EVP_AEAD_MAX_OVERHEAD + EVP_AEAD_MAX_NONCE_LENGTH) + +OPENSSL_COMPILE_ASSERT( + SSL3_RT_MAX_ENCRYPTED_OVERHEAD >= SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD, + max_overheads_are_consistent); + +/* SSL3_RT_MAX_COMPRESSED_LENGTH is an alias for + * |SSL3_RT_MAX_PLAIN_LENGTH|. Compression is gone, so don't include the + * compression overhead. */ +#define SSL3_RT_MAX_COMPRESSED_LENGTH SSL3_RT_MAX_PLAIN_LENGTH + +#define SSL3_RT_MAX_ENCRYPTED_LENGTH \ + (SSL3_RT_MAX_ENCRYPTED_OVERHEAD + SSL3_RT_MAX_COMPRESSED_LENGTH) +#define SSL3_RT_MAX_PACKET_SIZE \ + (SSL3_RT_MAX_ENCRYPTED_LENGTH + SSL3_RT_HEADER_LENGTH) + +#define SSL3_MD_CLIENT_FINISHED_CONST "\x43\x4C\x4E\x54" +#define SSL3_MD_SERVER_FINISHED_CONST "\x53\x52\x56\x52" + +#define SSL3_RT_CHANGE_CIPHER_SPEC 20 +#define SSL3_RT_ALERT 21 +#define SSL3_RT_HANDSHAKE 22 +#define SSL3_RT_APPLICATION_DATA 23 + +/* Pseudo content type for SSL/TLS header info */ +#define SSL3_RT_HEADER 0x100 + +#define SSL3_AL_WARNING 1 +#define SSL3_AL_FATAL 2 + +#define SSL3_AD_CLOSE_NOTIFY 0 +#define SSL3_AD_UNEXPECTED_MESSAGE 10 /* fatal */ +#define SSL3_AD_BAD_RECORD_MAC 20 /* fatal */ +#define SSL3_AD_DECOMPRESSION_FAILURE 30 /* fatal */ +#define SSL3_AD_HANDSHAKE_FAILURE 40 /* fatal */ +#define SSL3_AD_NO_CERTIFICATE 41 +#define SSL3_AD_BAD_CERTIFICATE 42 +#define SSL3_AD_UNSUPPORTED_CERTIFICATE 43 +#define SSL3_AD_CERTIFICATE_REVOKED 44 +#define SSL3_AD_CERTIFICATE_EXPIRED 45 +#define SSL3_AD_CERTIFICATE_UNKNOWN 46 +#define SSL3_AD_ILLEGAL_PARAMETER 47 /* fatal */ +#define SSL3_AD_INAPPROPRIATE_FALLBACK 86 /* fatal */ + +#define SSL3_CT_RSA_SIGN 1 +#define SSL3_CT_DSS_SIGN 2 +#define SSL3_CT_RSA_FIXED_DH 3 +#define SSL3_CT_DSS_FIXED_DH 4 +#define SSL3_CT_RSA_EPHEMERAL_DH 5 +#define SSL3_CT_DSS_EPHEMERAL_DH 6 +#define SSL3_CT_FORTEZZA_DMS 20 + +/* SSLv3 */ +/* client */ +/* extra state */ +#define SSL3_ST_CW_FLUSH (0x100 | SSL_ST_CONNECT) +#define SSL3_ST_FALSE_START (0x101 | SSL_ST_CONNECT) +#define SSL3_ST_VERIFY_SERVER_CERT (0x102 | SSL_ST_CONNECT) +/* write to server */ +#define SSL3_ST_CW_CLNT_HELLO_A (0x110 | SSL_ST_CONNECT) +#define SSL3_ST_CW_CLNT_HELLO_B (0x111 | SSL_ST_CONNECT) +/* read from server */ +#define SSL3_ST_CR_SRVR_HELLO_A (0x120 | SSL_ST_CONNECT) +#define DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A (0x126 | SSL_ST_CONNECT) +#define SSL3_ST_CR_CERT_A (0x130 | SSL_ST_CONNECT) +#define SSL3_ST_CR_KEY_EXCH_A (0x140 | SSL_ST_CONNECT) +#define SSL3_ST_CR_KEY_EXCH_B (0x141 | SSL_ST_CONNECT) +#define SSL3_ST_CR_CERT_REQ_A (0x150 | SSL_ST_CONNECT) +#define SSL3_ST_CR_SRVR_DONE_A (0x160 | SSL_ST_CONNECT) +/* write to server */ +#define SSL3_ST_CW_CERT_A (0x170 | SSL_ST_CONNECT) +#define SSL3_ST_CW_CERT_B (0x171 | SSL_ST_CONNECT) +#define SSL3_ST_CW_CERT_C (0x172 | SSL_ST_CONNECT) +#define SSL3_ST_CW_CERT_D (0x173 | SSL_ST_CONNECT) +#define SSL3_ST_CW_KEY_EXCH_A (0x180 | SSL_ST_CONNECT) +#define SSL3_ST_CW_KEY_EXCH_B (0x181 | SSL_ST_CONNECT) +#define SSL3_ST_CW_CERT_VRFY_A (0x190 | SSL_ST_CONNECT) +#define SSL3_ST_CW_CERT_VRFY_B (0x191 | SSL_ST_CONNECT) +#define SSL3_ST_CW_CERT_VRFY_C (0x192 | SSL_ST_CONNECT) +#define SSL3_ST_CW_CHANGE_A (0x1A0 | SSL_ST_CONNECT) +#define SSL3_ST_CW_CHANGE_B (0x1A1 | SSL_ST_CONNECT) +#define SSL3_ST_CW_NEXT_PROTO_A (0x200 | SSL_ST_CONNECT) +#define SSL3_ST_CW_NEXT_PROTO_B (0x201 | SSL_ST_CONNECT) +#define SSL3_ST_CW_CHANNEL_ID_A (0x220 | SSL_ST_CONNECT) +#define SSL3_ST_CW_CHANNEL_ID_B (0x221 | SSL_ST_CONNECT) +#define SSL3_ST_CW_FINISHED_A (0x1B0 | SSL_ST_CONNECT) +#define SSL3_ST_CW_FINISHED_B (0x1B1 | SSL_ST_CONNECT) +/* read from server */ +#define SSL3_ST_CR_CHANGE (0x1C0 | SSL_ST_CONNECT) +#define SSL3_ST_CR_FINISHED_A (0x1D0 | SSL_ST_CONNECT) +#define SSL3_ST_CR_SESSION_TICKET_A (0x1E0 | SSL_ST_CONNECT) +#define SSL3_ST_CR_CERT_STATUS_A (0x1F0 | SSL_ST_CONNECT) + +/* SSL3_ST_CR_SRVR_HELLO_B is a legacy alias for |SSL3_ST_CR_SRVR_HELLO_A| used + * by some consumers which check |SSL_state|. */ +#define SSL3_ST_CR_SRVR_HELLO_B SSL3_ST_CR_SRVR_HELLO_A + +/* server */ +/* extra state */ +#define SSL3_ST_SW_FLUSH (0x100 | SSL_ST_ACCEPT) +/* read from client */ +#define SSL3_ST_SR_INITIAL_BYTES (0x240 | SSL_ST_ACCEPT) +#define SSL3_ST_SR_V2_CLIENT_HELLO (0x241 | SSL_ST_ACCEPT) +#define SSL3_ST_SR_CLNT_HELLO_A (0x110 | SSL_ST_ACCEPT) +#define SSL3_ST_SR_CLNT_HELLO_B (0x111 | SSL_ST_ACCEPT) +#define SSL3_ST_SR_CLNT_HELLO_C (0x112 | SSL_ST_ACCEPT) +/* write to client */ +#define SSL3_ST_SW_HELLO_REQ_A (0x120 | SSL_ST_ACCEPT) +#define SSL3_ST_SW_HELLO_REQ_B (0x121 | SSL_ST_ACCEPT) +#define SSL3_ST_SW_HELLO_REQ_C (0x122 | SSL_ST_ACCEPT) +#define SSL3_ST_SW_SRVR_HELLO_A (0x130 | SSL_ST_ACCEPT) +#define SSL3_ST_SW_SRVR_HELLO_B (0x131 | SSL_ST_ACCEPT) +#define SSL3_ST_SW_CERT_A (0x140 | SSL_ST_ACCEPT) +#define SSL3_ST_SW_CERT_B (0x141 | SSL_ST_ACCEPT) +#define SSL3_ST_SW_KEY_EXCH_A (0x150 | SSL_ST_ACCEPT) +#define SSL3_ST_SW_KEY_EXCH_B (0x151 | SSL_ST_ACCEPT) +#define SSL3_ST_SW_KEY_EXCH_C (0x152 | SSL_ST_ACCEPT) +#define SSL3_ST_SW_CERT_REQ_A (0x160 | SSL_ST_ACCEPT) +#define SSL3_ST_SW_CERT_REQ_B (0x161 | SSL_ST_ACCEPT) +#define SSL3_ST_SW_SRVR_DONE_A (0x170 | SSL_ST_ACCEPT) +#define SSL3_ST_SW_SRVR_DONE_B (0x171 | SSL_ST_ACCEPT) +/* read from client */ +#define SSL3_ST_SR_CERT_A (0x180 | SSL_ST_ACCEPT) +#define SSL3_ST_SR_KEY_EXCH_A (0x190 | SSL_ST_ACCEPT) +#define SSL3_ST_SR_KEY_EXCH_B (0x191 | SSL_ST_ACCEPT) +#define SSL3_ST_SR_CERT_VRFY_A (0x1A0 | SSL_ST_ACCEPT) +#define SSL3_ST_SR_CHANGE (0x1B0 | SSL_ST_ACCEPT) +#define SSL3_ST_SR_NEXT_PROTO_A (0x210 | SSL_ST_ACCEPT) +#define SSL3_ST_SR_CHANNEL_ID_A (0x230 | SSL_ST_ACCEPT) +#define SSL3_ST_SR_FINISHED_A (0x1C0 | SSL_ST_ACCEPT) + +/* write to client */ +#define SSL3_ST_SW_CHANGE_A (0x1D0 | SSL_ST_ACCEPT) +#define SSL3_ST_SW_CHANGE_B (0x1D1 | SSL_ST_ACCEPT) +#define SSL3_ST_SW_FINISHED_A (0x1E0 | SSL_ST_ACCEPT) +#define SSL3_ST_SW_FINISHED_B (0x1E1 | SSL_ST_ACCEPT) +#define SSL3_ST_SW_SESSION_TICKET_A (0x1F0 | SSL_ST_ACCEPT) +#define SSL3_ST_SW_SESSION_TICKET_B (0x1F1 | SSL_ST_ACCEPT) +#define SSL3_ST_SW_CERT_STATUS_A (0x200 | SSL_ST_ACCEPT) +#define SSL3_ST_SW_CERT_STATUS_B (0x201 | SSL_ST_ACCEPT) +#define SSL3_ST_SW_SUPPLEMENTAL_DATA_A (0x220 | SSL_ST_ACCEPT) +#define SSL3_ST_SW_SUPPLEMENTAL_DATA_B (0x221 | SSL_ST_ACCEPT) + +#define SSL3_MT_HELLO_REQUEST 0 +#define SSL3_MT_CLIENT_HELLO 1 +#define SSL3_MT_SERVER_HELLO 2 +#define SSL3_MT_NEW_SESSION_TICKET 4 +#define SSL3_MT_CERTIFICATE 11 +#define SSL3_MT_SERVER_KEY_EXCHANGE 12 +#define SSL3_MT_CERTIFICATE_REQUEST 13 +#define SSL3_MT_SERVER_HELLO_DONE 14 +#define SSL3_MT_CERTIFICATE_VERIFY 15 +#define SSL3_MT_CLIENT_KEY_EXCHANGE 16 +#define SSL3_MT_FINISHED 20 +#define SSL3_MT_CERTIFICATE_STATUS 22 +#define SSL3_MT_SUPPLEMENTAL_DATA 23 +#define SSL3_MT_NEXT_PROTO 67 +#define SSL3_MT_CHANNEL_ID_ENCRYPTED_EXTENSIONS 203 +#define DTLS1_MT_HELLO_VERIFY_REQUEST 3 + +/* The following are legacy aliases for consumers which use + * |SSL_CTX_set_msg_callback|. */ +#define SSL3_MT_SERVER_DONE SSL3_MT_SERVER_HELLO_DONE +#define SSL3_MT_NEWSESSION_TICKET SSL3_MT_NEW_SESSION_TICKET + + +#define SSL3_MT_CCS 1 + +/* These are used when changing over to a new cipher */ +#define SSL3_CC_READ 0x01 +#define SSL3_CC_WRITE 0x02 +#define SSL3_CC_CLIENT 0x10 +#define SSL3_CC_SERVER 0x20 +#define SSL3_CHANGE_CIPHER_CLIENT_WRITE (SSL3_CC_CLIENT | SSL3_CC_WRITE) +#define SSL3_CHANGE_CIPHER_SERVER_READ (SSL3_CC_SERVER | SSL3_CC_READ) +#define SSL3_CHANGE_CIPHER_CLIENT_READ (SSL3_CC_CLIENT | SSL3_CC_READ) +#define SSL3_CHANGE_CIPHER_SERVER_WRITE (SSL3_CC_SERVER | SSL3_CC_WRITE) + + +#ifdef __cplusplus +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_SSL3_H */ diff --git a/external/boringssl/include/openssl/stack.h b/external/boringssl/include/openssl/stack.h new file mode 100644 index 0000000000..16b9f4f66b --- /dev/null +++ b/external/boringssl/include/openssl/stack.h @@ -0,0 +1,295 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_STACK_H +#define OPENSSL_HEADER_STACK_H + +#include + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* A stack, in OpenSSL, is an array of pointers. They are the most commonly + * used collection object. + * + * This file defines macros for type safe use of the stack functions. A stack + * of a specific type of object has type |STACK_OF(type)|. This can be defined + * (once) with |DEFINE_STACK_OF(type)| and declared where needed with + * |DECLARE_STACK_OF(type)|. For example: + * + * struct foo { + * int bar; + * }; + * + * DEFINE_STACK_OF(struct foo); + * + * Although note that the stack will contain /pointers/ to |foo|. + * + * A macro will be defined for each of the sk_* functions below. For + * STACK_OF(foo), the macros would be sk_foo_new, sk_foo_pop etc. */ + + +/* stack_cmp_func is a comparison function that returns a value < 0, 0 or > 0 + * if |*a| is less than, equal to or greater than |*b|, respectively. Note the + * extra indirection - the function is given a pointer to a pointer to the + * element. This differs from the usual qsort/bsearch comparison function. */ +typedef int (*stack_cmp_func)(const void **a, const void **b); + +/* stack_st contains an array of pointers. It is not designed to be used + * directly, rather the wrapper macros should be used. */ +typedef struct stack_st { + /* num contains the number of valid pointers in |data|. */ + size_t num; + void **data; + /* sorted is non-zero if the values pointed to by |data| are in ascending + * order, based on |comp|. */ + size_t sorted; + /* num_alloc contains the number of pointers allocated in the buffer pointed + * to by |data|, which may be larger than |num|. */ + size_t num_alloc; + /* comp is an optional comparison function. */ + stack_cmp_func comp; +} _STACK; + + +#define STACK_OF(type) struct stack_st_##type + +#define DECLARE_STACK_OF(type) STACK_OF(type); + +/* The make_macros.sh script in this directory parses the following lines and + * generates the stack_macros.h file that contains macros for the following + * types of stacks: + * + * STACK_OF:ACCESS_DESCRIPTION + * STACK_OF:ASN1_ADB_TABLE + * STACK_OF:ASN1_GENERALSTRING + * STACK_OF:ASN1_INTEGER + * STACK_OF:ASN1_OBJECT + * STACK_OF:ASN1_STRING_TABLE + * STACK_OF:ASN1_TYPE + * STACK_OF:ASN1_VALUE + * STACK_OF:BIO + * STACK_OF:BY_DIR_ENTRY + * STACK_OF:BY_DIR_HASH + * STACK_OF:CONF_VALUE + * STACK_OF:CRYPTO_EX_DATA_FUNCS + * STACK_OF:DIST_POINT + * STACK_OF:GENERAL_NAME + * STACK_OF:GENERAL_NAMES + * STACK_OF:GENERAL_SUBTREE + * STACK_OF:POLICYINFO + * STACK_OF:POLICYQUALINFO + * STACK_OF:POLICY_MAPPING + * STACK_OF:RSA_additional_prime + * STACK_OF:SSL_COMP + * STACK_OF:SSL_CUSTOM_EXTENSION + * STACK_OF:STACK_OF_X509_NAME_ENTRY + * STACK_OF:SXNETID + * STACK_OF:X509 + * STACK_OF:X509V3_EXT_METHOD + * STACK_OF:X509_ALGOR + * STACK_OF:X509_ATTRIBUTE + * STACK_OF:X509_CRL + * STACK_OF:X509_EXTENSION + * STACK_OF:X509_INFO + * STACK_OF:X509_LOOKUP + * STACK_OF:X509_NAME + * STACK_OF:X509_NAME_ENTRY + * STACK_OF:X509_OBJECT + * STACK_OF:X509_POLICY_DATA + * STACK_OF:X509_POLICY_NODE + * STACK_OF:X509_PURPOSE + * STACK_OF:X509_REVOKED + * STACK_OF:X509_TRUST + * STACK_OF:X509_VERIFY_PARAM + * STACK_OF:void + * + * Some stacks contain only const structures, so the stack should return const + * pointers to retain type-checking. + * + * CONST_STACK_OF:SRTP_PROTECTION_PROFILE + * CONST_STACK_OF:SSL_CIPHER */ + + +/* Some stacks are special because, although we would like STACK_OF(char *), + * that would actually be a stack of pointers to char*, but we just want to + * point to the string directly. In this case we call them "special" and use + * |DEFINE_SPECIAL_STACK_OF(type)| */ +#define DEFINE_SPECIAL_STACK_OF(type, inner) \ + STACK_OF(type) { _STACK special_stack; }; \ + OPENSSL_COMPILE_ASSERT(sizeof(type) == sizeof(void *), \ + special_stack_of_non_pointer_##type); + +typedef char *OPENSSL_STRING; + +DEFINE_SPECIAL_STACK_OF(OPENSSL_STRING, char) +DEFINE_SPECIAL_STACK_OF(OPENSSL_BLOCK, uint8_t) + +/* The make_macros.sh script in this directory parses the following lines and + * generates the stack_macros.h file that contains macros for the following + * types of stacks: + * + * SPECIAL_STACK_OF:OPENSSL_STRING + * SPECIAL_STACK_OF:OPENSSL_BLOCK */ + +#define IN_STACK_H +#include +#undef IN_STACK_H + + +/* These are the raw stack functions, you shouldn't be using them. Rather you + * should be using the type stack macros implemented above. */ + +/* sk_new creates a new, empty stack with the given comparison function, which + * may be zero. It returns the new stack or NULL on allocation failure. */ +OPENSSL_EXPORT _STACK *sk_new(stack_cmp_func comp); + +/* sk_new_null creates a new, empty stack. It returns the new stack or NULL on + * allocation failure. */ +OPENSSL_EXPORT _STACK *sk_new_null(void); + +/* sk_num returns the number of elements in |s|. */ +OPENSSL_EXPORT size_t sk_num(const _STACK *sk); + +/* sk_zero resets |sk| to the empty state but does nothing to free the + * individual elements themselves. */ +OPENSSL_EXPORT void sk_zero(_STACK *sk); + +/* sk_value returns the |i|th pointer in |sk|, or NULL if |i| is out of + * range. */ +OPENSSL_EXPORT void *sk_value(const _STACK *sk, size_t i); + +/* sk_set sets the |i|th pointer in |sk| to |p| and returns |p|. If |i| is out + * of range, it returns NULL. */ +OPENSSL_EXPORT void *sk_set(_STACK *sk, size_t i, void *p); + +/* sk_free frees the given stack and array of pointers, but does nothing to + * free the individual elements. Also see |sk_pop_free|. */ +OPENSSL_EXPORT void sk_free(_STACK *sk); + +/* sk_pop_free calls |free_func| on each element in the stack and then frees + * the stack itself. */ +OPENSSL_EXPORT void sk_pop_free(_STACK *sk, void (*free_func)(void *)); + +/* sk_insert inserts |p| into the stack at index |where|, moving existing + * elements if needed. It returns the length of the new stack, or zero on + * error. */ +OPENSSL_EXPORT size_t sk_insert(_STACK *sk, void *p, size_t where); + +/* sk_delete removes the pointer at index |where|, moving other elements down + * if needed. It returns the removed pointer, or NULL if |where| is out of + * range. */ +OPENSSL_EXPORT void *sk_delete(_STACK *sk, size_t where); + +/* sk_delete_ptr removes, at most, one instance of |p| from the stack based on + * pointer equality. If an instance of |p| is found then |p| is returned, + * otherwise it returns NULL. */ +OPENSSL_EXPORT void *sk_delete_ptr(_STACK *sk, void *p); + +/* sk_find returns the first value in the stack equal to |p|. If a comparison + * function has been set on the stack, then equality is defined by it and the + * stack will be sorted if need be so that a binary search can be used. + * Otherwise pointer equality is used. If a matching element is found, its + * index is written to |*out_index| (if |out_index| is not NULL) and one is + * returned. Otherwise zero is returned. */ +OPENSSL_EXPORT int sk_find(_STACK *sk, size_t *out_index, void *p); + +/* sk_shift removes and returns the first element in the stack, or returns NULL + * if the stack is empty. */ +OPENSSL_EXPORT void *sk_shift(_STACK *sk); + +/* sk_push appends |p| to the stack and returns the length of the new stack, or + * 0 on allocation failure. */ +OPENSSL_EXPORT size_t sk_push(_STACK *sk, void *p); + +/* sk_pop returns and removes the last element on the stack, or NULL if the + * stack is empty. */ +OPENSSL_EXPORT void *sk_pop(_STACK *sk); + +/* sk_dup performs a shallow copy of a stack and returns the new stack, or NULL + * on error. */ +OPENSSL_EXPORT _STACK *sk_dup(const _STACK *sk); + +/* sk_sort sorts the elements of |sk| into ascending order based on the + * comparison function. The stack maintains a |sorted| flag and sorting an + * already sorted stack is a no-op. */ +OPENSSL_EXPORT void sk_sort(_STACK *sk); + +/* sk_is_sorted returns one if |sk| is known to be sorted and zero + * otherwise. */ +OPENSSL_EXPORT int sk_is_sorted(const _STACK *sk); + +/* sk_set_cmp_func sets the comparison function to be used by |sk| and returns + * the previous one. */ +OPENSSL_EXPORT stack_cmp_func sk_set_cmp_func(_STACK *sk, stack_cmp_func comp); + +/* sk_deep_copy performs a copy of |sk| and of each of the non-NULL elements in + * |sk| by using |copy_func|. If an error occurs, |free_func| is used to free + * any copies already made and NULL is returned. */ +OPENSSL_EXPORT _STACK *sk_deep_copy(const _STACK *sk, + void *(*copy_func)(void *), + void (*free_func)(void *)); + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_STACK_H */ diff --git a/external/boringssl/include/openssl/stack_macros.h.REMOVED.git-id b/external/boringssl/include/openssl/stack_macros.h.REMOVED.git-id new file mode 100644 index 0000000000..8439744267 --- /dev/null +++ b/external/boringssl/include/openssl/stack_macros.h.REMOVED.git-id @@ -0,0 +1 @@ +2a60b8f9656307e62e74cdeed8e685f4a48069f2 \ No newline at end of file diff --git a/external/boringssl/include/openssl/thread.h b/external/boringssl/include/openssl/thread.h new file mode 100644 index 0000000000..9a96fb43da --- /dev/null +++ b/external/boringssl/include/openssl/thread.h @@ -0,0 +1,184 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_THREAD_H +#define OPENSSL_HEADER_THREAD_H + +#include + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +#if defined(OPENSSL_NO_THREADS) +typedef struct crypto_mutex_st { + char padding; /* Empty structs have different sizes in C and C++. */ +} CRYPTO_MUTEX; +#elif defined(OPENSSL_WINDOWS) +/* CRYPTO_MUTEX can appear in public header files so we really don't want to + * pull in windows.h. It's statically asserted that this structure is large + * enough to contain a Windows SRWLOCK by thread_win.c. */ +typedef union crypto_mutex_st { + void *handle; +} CRYPTO_MUTEX; +#elif defined(__MACH__) && defined(__APPLE__) +typedef pthread_rwlock_t CRYPTO_MUTEX; +#else +/* It is reasonable to include pthread.h on non-Windows systems, however the + * |pthread_rwlock_t| that we need is hidden under feature flags, and we can't + * ensure that we'll be able to get it. It's statically asserted that this + * structure is large enough to contain a |pthread_rwlock_t| by + * thread_pthread.c. */ +typedef union crypto_mutex_st { + double alignment; + uint8_t padding[3*sizeof(int) + 5*sizeof(unsigned) + 16 + 8]; +} CRYPTO_MUTEX; +#endif + +/* CRYPTO_refcount_t is the type of a reference count. + * + * Since some platforms use C11 atomics to access this, it should have the + * _Atomic qualifier. However, this header is included by C++ programs as well + * as C code that might not set -std=c11. So, in practice, it's not possible to + * do that. Instead we statically assert that the size and native alignment of + * a plain uint32_t and an _Atomic uint32_t are equal in refcount_c11.c. */ +typedef uint32_t CRYPTO_refcount_t; + + +/* Deprecated functions. + * + * Historically, OpenSSL required callers to provide locking callbacks. + * BoringSSL is thread-safe by default, but some old code calls these functions + * and so no-op implementations are provided. */ + +/* These defines do nothing but are provided to make old code easier to + * compile. */ +#define CRYPTO_LOCK 1 +#define CRYPTO_UNLOCK 2 +#define CRYPTO_READ 4 +#define CRYPTO_WRITE 8 + +/* CRYPTO_num_locks returns one. (This is non-zero that callers who allocate + * sizeof(lock) times this value don't get zero and then fail because malloc(0) + * returned NULL.) */ +OPENSSL_EXPORT int CRYPTO_num_locks(void); + +/* CRYPTO_set_locking_callback does nothing. */ +OPENSSL_EXPORT void CRYPTO_set_locking_callback( + void (*func)(int mode, int lock_num, const char *file, int line)); + +/* CRYPTO_set_add_lock_callback does nothing. */ +OPENSSL_EXPORT void CRYPTO_set_add_lock_callback(int (*func)( + int *num, int amount, int lock_num, const char *file, int line)); + +/* CRYPTO_get_locking_callback returns NULL. */ +OPENSSL_EXPORT void (*CRYPTO_get_locking_callback(void))(int mode, int lock_num, + const char *file, + int line); + +/* CRYPTO_get_lock_name returns a fixed, dummy string. */ +OPENSSL_EXPORT const char *CRYPTO_get_lock_name(int lock_num); + +/* CRYPTO_THREADID_set_callback returns one. */ +OPENSSL_EXPORT int CRYPTO_THREADID_set_callback( + void (*threadid_func)(CRYPTO_THREADID *threadid)); + +/* CRYPTO_THREADID_set_numeric does nothing. */ +OPENSSL_EXPORT void CRYPTO_THREADID_set_numeric(CRYPTO_THREADID *id, + unsigned long val); + +/* CRYPTO_THREADID_set_pointer does nothing. */ +OPENSSL_EXPORT void CRYPTO_THREADID_set_pointer(CRYPTO_THREADID *id, void *ptr); + +/* CRYPTO_THREADID_current does nothing. */ +OPENSSL_EXPORT void CRYPTO_THREADID_current(CRYPTO_THREADID *id); + +OPENSSL_EXPORT void CRYPTO_set_id_callback(unsigned long (*func)(void)); + +typedef struct { + int references; + struct CRYPTO_dynlock_value *data; +} CRYPTO_dynlock; + +OPENSSL_EXPORT void CRYPTO_set_dynlock_create_callback( + struct CRYPTO_dynlock_value *(*dyn_create_function)(const char *file, + int line)); + +OPENSSL_EXPORT void CRYPTO_set_dynlock_lock_callback(void (*dyn_lock_function)( + int mode, struct CRYPTO_dynlock_value *l, const char *file, int line)); + +OPENSSL_EXPORT void CRYPTO_set_dynlock_destroy_callback( + void (*dyn_destroy_function)(struct CRYPTO_dynlock_value *l, + const char *file, int line)); + +OPENSSL_EXPORT struct CRYPTO_dynlock_value *( + *CRYPTO_get_dynlock_create_callback(void))(const char *file, int line); + +OPENSSL_EXPORT void (*CRYPTO_get_dynlock_lock_callback(void))( + int mode, struct CRYPTO_dynlock_value *l, const char *file, int line); + +OPENSSL_EXPORT void (*CRYPTO_get_dynlock_destroy_callback(void))( + struct CRYPTO_dynlock_value *l, const char *file, int line); + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_THREAD_H */ diff --git a/external/boringssl/include/openssl/time_support.h b/external/boringssl/include/openssl/time_support.h new file mode 100644 index 0000000000..274b17d1d3 --- /dev/null +++ b/external/boringssl/include/openssl/time_support.h @@ -0,0 +1,91 @@ +/* Written by Richard Levitte (richard@levitte.org) for the OpenSSL + * project 2001. + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 2008. + */ +/* ==================================================================== + * Copyright (c) 2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#ifndef OPENSSL_HEADER_TIME_SUPPORT_H +#define OPENSSL_HEADER_TIME_SUPPORT_H + +#include + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* Wrapper functions for time functions. */ + + +/* OPENSSL_gmtime wraps |gmtime_r|. See the manual page for that function. */ +struct tm *OPENSSL_gmtime(const time_t *timer, struct tm *result); + +/* OPENSSL_gmtime_adj updates |tm| by adding |offset_day| days and |offset_sec| + * seconds. */ +int OPENSSL_gmtime_adj(struct tm *tm, int offset_day, long offset_sec); + +/* OPENSSL_gmtime_diff calculates the difference between |from| and |to| and + * outputs the difference as a number of days and seconds in |*out_days| and + * |*out_secs|. */ +int OPENSSL_gmtime_diff(int *out_days, int *out_secs, const struct tm *from, + const struct tm *to); + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_TIME_SUPPORT_H */ diff --git a/external/boringssl/include/openssl/tls1.h b/external/boringssl/include/openssl/tls1.h new file mode 100644 index 0000000000..d195940bd4 --- /dev/null +++ b/external/boringssl/include/openssl/tls1.h @@ -0,0 +1,680 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * + * Portions of the attached software ("Contribution") are developed by + * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. + * + * The Contribution is licensed pursuant to the OpenSSL open source + * license provided above. + * + * ECC cipher suite support in OpenSSL originally written by + * Vipul Gupta and Sumit Gupta of Sun Microsystems Laboratories. + * + */ +/* ==================================================================== + * Copyright 2005 Nokia. All rights reserved. + * + * The portions of the attached software ("Contribution") is developed by + * Nokia Corporation and is licensed pursuant to the OpenSSL open source + * license. + * + * The Contribution, originally written by Mika Kousa and Pasi Eronen of + * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites + * support (see RFC 4279) to OpenSSL. + * + * No patent licenses or other rights except those expressly stated in + * the OpenSSL open source license shall be deemed granted or received + * expressly, by implication, estoppel, or otherwise. + * + * No assurances are provided by Nokia that the Contribution does not + * infringe the patent or other intellectual property rights of any third + * party or that the license provides you with all the necessary rights + * to make use of the Contribution. + * + * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN + * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA + * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY + * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR + * OTHERWISE. + */ + +#ifndef OPENSSL_HEADER_TLS1_H +#define OPENSSL_HEADER_TLS1_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +#define TLS1_ALLOW_EXPERIMENTAL_CIPHERSUITES 0 + +#define TLS1_AD_DECRYPTION_FAILED 21 +#define TLS1_AD_RECORD_OVERFLOW 22 +#define TLS1_AD_UNKNOWN_CA 48 /* fatal */ +#define TLS1_AD_ACCESS_DENIED 49 /* fatal */ +#define TLS1_AD_DECODE_ERROR 50 /* fatal */ +#define TLS1_AD_DECRYPT_ERROR 51 +#define TLS1_AD_EXPORT_RESTRICTION 60 /* fatal */ +#define TLS1_AD_PROTOCOL_VERSION 70 /* fatal */ +#define TLS1_AD_INSUFFICIENT_SECURITY 71 /* fatal */ +#define TLS1_AD_INTERNAL_ERROR 80 /* fatal */ +#define TLS1_AD_USER_CANCELLED 90 +#define TLS1_AD_NO_RENEGOTIATION 100 +/* codes 110-114 are from RFC3546 */ +#define TLS1_AD_UNSUPPORTED_EXTENSION 110 +#define TLS1_AD_CERTIFICATE_UNOBTAINABLE 111 +#define TLS1_AD_UNRECOGNIZED_NAME 112 +#define TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE 113 +#define TLS1_AD_BAD_CERTIFICATE_HASH_VALUE 114 +#define TLS1_AD_UNKNOWN_PSK_IDENTITY 115 /* fatal */ + +/* ExtensionType values from RFC3546 / RFC4366 / RFC6066 */ +#define TLSEXT_TYPE_server_name 0 +#define TLSEXT_TYPE_max_fragment_length 1 +#define TLSEXT_TYPE_client_certificate_url 2 +#define TLSEXT_TYPE_trusted_ca_keys 3 +#define TLSEXT_TYPE_truncated_hmac 4 +#define TLSEXT_TYPE_status_request 5 +/* ExtensionType values from RFC4681 */ +#define TLSEXT_TYPE_user_mapping 6 + +/* ExtensionType values from RFC5878 */ +#define TLSEXT_TYPE_client_authz 7 +#define TLSEXT_TYPE_server_authz 8 + +/* ExtensionType values from RFC6091 */ +#define TLSEXT_TYPE_cert_type 9 + +/* ExtensionType values from draft-ietf-tls-tls13-latest */ +#define TLSEXT_TYPE_supported_groups 10 + +/* ExtensionType values from RFC4492 */ +#define TLSEXT_TYPE_ec_point_formats 11 + +/* ExtensionType value from RFC5054 */ +#define TLSEXT_TYPE_srp 12 + +/* ExtensionType values from RFC5246 */ +#define TLSEXT_TYPE_signature_algorithms 13 + +/* ExtensionType value from RFC5764 */ +#define TLSEXT_TYPE_srtp 14 + +/* ExtensionType value from RFC5620 */ +#define TLSEXT_TYPE_heartbeat 15 + +/* ExtensionType value from RFC7301 */ +#define TLSEXT_TYPE_application_layer_protocol_negotiation 16 + +/* ExtensionType value from RFC7685 */ +#define TLSEXT_TYPE_padding 21 + +/* ExtensionType value from RFC7627 */ +#define TLSEXT_TYPE_extended_master_secret 23 + +/* ExtensionType value from RFC4507 */ +#define TLSEXT_TYPE_session_ticket 35 + +/* ExtensionType value from RFC5746 */ +#define TLSEXT_TYPE_renegotiate 0xff01 + +/* ExtensionType value from RFC6962 */ +#define TLSEXT_TYPE_certificate_timestamp 18 + +/* This is not an IANA defined extension number */ +#define TLSEXT_TYPE_next_proto_neg 13172 + +/* This is not an IANA defined extension number */ +#define TLSEXT_TYPE_channel_id 30032 + +/* status request value from RFC 3546 */ +#define TLSEXT_STATUSTYPE_ocsp 1 + +/* ECPointFormat values from RFC 4492 */ +#define TLSEXT_ECPOINTFORMAT_uncompressed 0 +#define TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime 1 +#define TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2 2 + +/* Signature and hash algorithms from RFC 5246 */ + +#define TLSEXT_signature_anonymous 0 +#define TLSEXT_signature_rsa 1 +#define TLSEXT_signature_dsa 2 +#define TLSEXT_signature_ecdsa 3 + +#define TLSEXT_hash_none 0 +#define TLSEXT_hash_md5 1 +#define TLSEXT_hash_sha1 2 +#define TLSEXT_hash_sha224 3 +#define TLSEXT_hash_sha256 4 +#define TLSEXT_hash_sha384 5 +#define TLSEXT_hash_sha512 6 + +/* Flag set for unrecognised algorithms */ +#define TLSEXT_nid_unknown 0x1000000 + +/* ECC curves */ + +#define TLSEXT_curve_P_256 23 +#define TLSEXT_curve_P_384 24 + + +#define TLSEXT_MAXLEN_host_name 255 + +/* PSK ciphersuites from 4279 */ +#define TLS1_CK_PSK_WITH_RC4_128_SHA 0x0300008A +#define TLS1_CK_PSK_WITH_3DES_EDE_CBC_SHA 0x0300008B +#define TLS1_CK_PSK_WITH_AES_128_CBC_SHA 0x0300008C +#define TLS1_CK_PSK_WITH_AES_256_CBC_SHA 0x0300008D + +/* PSK ciphersuites from RFC 5489 */ +#define TLS1_CK_ECDHE_PSK_WITH_AES_128_CBC_SHA 0x0300C035 +#define TLS1_CK_ECDHE_PSK_WITH_AES_256_CBC_SHA 0x0300C036 + +/* Additional TLS ciphersuites from expired Internet Draft + * draft-ietf-tls-56-bit-ciphersuites-01.txt + * (available if TLS1_ALLOW_EXPERIMENTAL_CIPHERSUITES is defined, see + * s3_lib.c). We actually treat them like SSL 3.0 ciphers, which we probably + * shouldn't. Note that the first two are actually not in the IDs. */ +#define TLS1_CK_RSA_EXPORT1024_WITH_RC4_56_MD5 0x03000060 /* not in ID */ +#define TLS1_CK_RSA_EXPORT1024_WITH_RC2_CBC_56_MD5 0x03000061 /* not in ID */ +#define TLS1_CK_RSA_EXPORT1024_WITH_DES_CBC_SHA 0x03000062 +#define TLS1_CK_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA 0x03000063 +#define TLS1_CK_RSA_EXPORT1024_WITH_RC4_56_SHA 0x03000064 +#define TLS1_CK_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA 0x03000065 +#define TLS1_CK_DHE_DSS_WITH_RC4_128_SHA 0x03000066 + +/* AES ciphersuites from RFC3268 */ + +#define TLS1_CK_RSA_WITH_AES_128_SHA 0x0300002F +#define TLS1_CK_DH_DSS_WITH_AES_128_SHA 0x03000030 +#define TLS1_CK_DH_RSA_WITH_AES_128_SHA 0x03000031 +#define TLS1_CK_DHE_DSS_WITH_AES_128_SHA 0x03000032 +#define TLS1_CK_DHE_RSA_WITH_AES_128_SHA 0x03000033 +#define TLS1_CK_ADH_WITH_AES_128_SHA 0x03000034 + +#define TLS1_CK_RSA_WITH_AES_256_SHA 0x03000035 +#define TLS1_CK_DH_DSS_WITH_AES_256_SHA 0x03000036 +#define TLS1_CK_DH_RSA_WITH_AES_256_SHA 0x03000037 +#define TLS1_CK_DHE_DSS_WITH_AES_256_SHA 0x03000038 +#define TLS1_CK_DHE_RSA_WITH_AES_256_SHA 0x03000039 +#define TLS1_CK_ADH_WITH_AES_256_SHA 0x0300003A + +/* TLS v1.2 ciphersuites */ +#define TLS1_CK_RSA_WITH_NULL_SHA256 0x0300003B +#define TLS1_CK_RSA_WITH_AES_128_SHA256 0x0300003C +#define TLS1_CK_RSA_WITH_AES_256_SHA256 0x0300003D +#define TLS1_CK_DH_DSS_WITH_AES_128_SHA256 0x0300003E +#define TLS1_CK_DH_RSA_WITH_AES_128_SHA256 0x0300003F +#define TLS1_CK_DHE_DSS_WITH_AES_128_SHA256 0x03000040 + +/* Camellia ciphersuites from RFC4132 */ +#define TLS1_CK_RSA_WITH_CAMELLIA_128_CBC_SHA 0x03000041 +#define TLS1_CK_DH_DSS_WITH_CAMELLIA_128_CBC_SHA 0x03000042 +#define TLS1_CK_DH_RSA_WITH_CAMELLIA_128_CBC_SHA 0x03000043 +#define TLS1_CK_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA 0x03000044 +#define TLS1_CK_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA 0x03000045 +#define TLS1_CK_ADH_WITH_CAMELLIA_128_CBC_SHA 0x03000046 + +/* TLS v1.2 ciphersuites */ +#define TLS1_CK_DHE_RSA_WITH_AES_128_SHA256 0x03000067 +#define TLS1_CK_DH_DSS_WITH_AES_256_SHA256 0x03000068 +#define TLS1_CK_DH_RSA_WITH_AES_256_SHA256 0x03000069 +#define TLS1_CK_DHE_DSS_WITH_AES_256_SHA256 0x0300006A +#define TLS1_CK_DHE_RSA_WITH_AES_256_SHA256 0x0300006B +#define TLS1_CK_ADH_WITH_AES_128_SHA256 0x0300006C +#define TLS1_CK_ADH_WITH_AES_256_SHA256 0x0300006D + +/* Camellia ciphersuites from RFC4132 */ +#define TLS1_CK_RSA_WITH_CAMELLIA_256_CBC_SHA 0x03000084 +#define TLS1_CK_DH_DSS_WITH_CAMELLIA_256_CBC_SHA 0x03000085 +#define TLS1_CK_DH_RSA_WITH_CAMELLIA_256_CBC_SHA 0x03000086 +#define TLS1_CK_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA 0x03000087 +#define TLS1_CK_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA 0x03000088 +#define TLS1_CK_ADH_WITH_CAMELLIA_256_CBC_SHA 0x03000089 + +/* SEED ciphersuites from RFC4162 */ +#define TLS1_CK_RSA_WITH_SEED_SHA 0x03000096 +#define TLS1_CK_DH_DSS_WITH_SEED_SHA 0x03000097 +#define TLS1_CK_DH_RSA_WITH_SEED_SHA 0x03000098 +#define TLS1_CK_DHE_DSS_WITH_SEED_SHA 0x03000099 +#define TLS1_CK_DHE_RSA_WITH_SEED_SHA 0x0300009A +#define TLS1_CK_ADH_WITH_SEED_SHA 0x0300009B + +/* TLS v1.2 GCM ciphersuites from RFC5288 */ +#define TLS1_CK_RSA_WITH_AES_128_GCM_SHA256 0x0300009C +#define TLS1_CK_RSA_WITH_AES_256_GCM_SHA384 0x0300009D +#define TLS1_CK_DHE_RSA_WITH_AES_128_GCM_SHA256 0x0300009E +#define TLS1_CK_DHE_RSA_WITH_AES_256_GCM_SHA384 0x0300009F +#define TLS1_CK_DH_RSA_WITH_AES_128_GCM_SHA256 0x030000A0 +#define TLS1_CK_DH_RSA_WITH_AES_256_GCM_SHA384 0x030000A1 +#define TLS1_CK_DHE_DSS_WITH_AES_128_GCM_SHA256 0x030000A2 +#define TLS1_CK_DHE_DSS_WITH_AES_256_GCM_SHA384 0x030000A3 +#define TLS1_CK_DH_DSS_WITH_AES_128_GCM_SHA256 0x030000A4 +#define TLS1_CK_DH_DSS_WITH_AES_256_GCM_SHA384 0x030000A5 +#define TLS1_CK_ADH_WITH_AES_128_GCM_SHA256 0x030000A6 +#define TLS1_CK_ADH_WITH_AES_256_GCM_SHA384 0x030000A7 + +/* ECC ciphersuites from RFC4492 */ +#define TLS1_CK_ECDH_ECDSA_WITH_NULL_SHA 0x0300C001 +#define TLS1_CK_ECDH_ECDSA_WITH_RC4_128_SHA 0x0300C002 +#define TLS1_CK_ECDH_ECDSA_WITH_DES_192_CBC3_SHA 0x0300C003 +#define TLS1_CK_ECDH_ECDSA_WITH_AES_128_CBC_SHA 0x0300C004 +#define TLS1_CK_ECDH_ECDSA_WITH_AES_256_CBC_SHA 0x0300C005 + +#define TLS1_CK_ECDHE_ECDSA_WITH_NULL_SHA 0x0300C006 +#define TLS1_CK_ECDHE_ECDSA_WITH_RC4_128_SHA 0x0300C007 +#define TLS1_CK_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA 0x0300C008 +#define TLS1_CK_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 0x0300C009 +#define TLS1_CK_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 0x0300C00A + +#define TLS1_CK_ECDH_RSA_WITH_NULL_SHA 0x0300C00B +#define TLS1_CK_ECDH_RSA_WITH_RC4_128_SHA 0x0300C00C +#define TLS1_CK_ECDH_RSA_WITH_DES_192_CBC3_SHA 0x0300C00D +#define TLS1_CK_ECDH_RSA_WITH_AES_128_CBC_SHA 0x0300C00E +#define TLS1_CK_ECDH_RSA_WITH_AES_256_CBC_SHA 0x0300C00F + +#define TLS1_CK_ECDHE_RSA_WITH_NULL_SHA 0x0300C010 +#define TLS1_CK_ECDHE_RSA_WITH_RC4_128_SHA 0x0300C011 +#define TLS1_CK_ECDHE_RSA_WITH_DES_192_CBC3_SHA 0x0300C012 +#define TLS1_CK_ECDHE_RSA_WITH_AES_128_CBC_SHA 0x0300C013 +#define TLS1_CK_ECDHE_RSA_WITH_AES_256_CBC_SHA 0x0300C014 + +#define TLS1_CK_ECDH_anon_WITH_NULL_SHA 0x0300C015 +#define TLS1_CK_ECDH_anon_WITH_RC4_128_SHA 0x0300C016 +#define TLS1_CK_ECDH_anon_WITH_DES_192_CBC3_SHA 0x0300C017 +#define TLS1_CK_ECDH_anon_WITH_AES_128_CBC_SHA 0x0300C018 +#define TLS1_CK_ECDH_anon_WITH_AES_256_CBC_SHA 0x0300C019 + +/* SRP ciphersuites from RFC 5054 */ +#define TLS1_CK_SRP_SHA_WITH_3DES_EDE_CBC_SHA 0x0300C01A +#define TLS1_CK_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA 0x0300C01B +#define TLS1_CK_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA 0x0300C01C +#define TLS1_CK_SRP_SHA_WITH_AES_128_CBC_SHA 0x0300C01D +#define TLS1_CK_SRP_SHA_RSA_WITH_AES_128_CBC_SHA 0x0300C01E +#define TLS1_CK_SRP_SHA_DSS_WITH_AES_128_CBC_SHA 0x0300C01F +#define TLS1_CK_SRP_SHA_WITH_AES_256_CBC_SHA 0x0300C020 +#define TLS1_CK_SRP_SHA_RSA_WITH_AES_256_CBC_SHA 0x0300C021 +#define TLS1_CK_SRP_SHA_DSS_WITH_AES_256_CBC_SHA 0x0300C022 + +/* ECDH HMAC based ciphersuites from RFC5289 */ + +#define TLS1_CK_ECDHE_ECDSA_WITH_AES_128_SHA256 0x0300C023 +#define TLS1_CK_ECDHE_ECDSA_WITH_AES_256_SHA384 0x0300C024 +#define TLS1_CK_ECDH_ECDSA_WITH_AES_128_SHA256 0x0300C025 +#define TLS1_CK_ECDH_ECDSA_WITH_AES_256_SHA384 0x0300C026 +#define TLS1_CK_ECDHE_RSA_WITH_AES_128_SHA256 0x0300C027 +#define TLS1_CK_ECDHE_RSA_WITH_AES_256_SHA384 0x0300C028 +#define TLS1_CK_ECDH_RSA_WITH_AES_128_SHA256 0x0300C029 +#define TLS1_CK_ECDH_RSA_WITH_AES_256_SHA384 0x0300C02A + +/* ECDH GCM based ciphersuites from RFC5289 */ +#define TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0x0300C02B +#define TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 0x0300C02C +#define TLS1_CK_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 0x0300C02D +#define TLS1_CK_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 0x0300C02E +#define TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256 0x0300C02F +#define TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384 0x0300C030 +#define TLS1_CK_ECDH_RSA_WITH_AES_128_GCM_SHA256 0x0300C031 +#define TLS1_CK_ECDH_RSA_WITH_AES_256_GCM_SHA384 0x0300C032 + +#define TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD 0x0300CC13 +#define TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD 0x0300CC14 + +#define TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0x0300CCA8 +#define TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 0x0300CCA9 +#define TLS1_CK_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 0x0300CCAC + +/* PSK ciphersuites from mattsson-tls-ecdhe-psk-aead */ +#define TLS1_CK_ECDHE_PSK_WITH_AES_128_GCM_SHA256 0x0300D001 +#define TLS1_CK_ECDHE_PSK_WITH_AES_256_GCM_SHA384 0x0300D002 + +/* TODO(davidben): Remove this. Historically, the CK names for CHACHA20_POLY1305 + * were missing 'WITH' and 'SHA256'. */ +#define TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305 \ + TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 + +/* CECPQ1 ciphersuites. These are specific to BoringSSL and not standard. */ +#define TLS1_CK_CECPQ1_RSA_WITH_CHACHA20_POLY1305_SHA256 0x030016B7 +#define TLS1_CK_CECPQ1_ECDSA_WITH_CHACHA20_POLY1305_SHA256 0x030016B8 +#define TLS1_CK_CECPQ1_RSA_WITH_AES_256_GCM_SHA384 0x030016B9 +#define TLS1_CK_CECPQ1_ECDSA_WITH_AES_256_GCM_SHA384 0x030016BA + +/* XXX + * Inconsistency alert: + * The OpenSSL names of ciphers with ephemeral DH here include the string + * "DHE", while elsewhere it has always been "EDH". + * (The alias for the list of all such ciphers also is "EDH".) + * The specifications speak of "EDH"; maybe we should allow both forms + * for everything. */ +#define TLS1_TXT_RSA_EXPORT1024_WITH_RC4_56_MD5 "EXP1024-RC4-MD5" +#define TLS1_TXT_RSA_EXPORT1024_WITH_RC2_CBC_56_MD5 "EXP1024-RC2-CBC-MD5" +#define TLS1_TXT_RSA_EXPORT1024_WITH_DES_CBC_SHA "EXP1024-DES-CBC-SHA" +#define TLS1_TXT_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA \ + "EXP1024-DHE-DSS-DES-CBC-SHA" +#define TLS1_TXT_RSA_EXPORT1024_WITH_RC4_56_SHA "EXP1024-RC4-SHA" +#define TLS1_TXT_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA "EXP1024-DHE-DSS-RC4-SHA" +#define TLS1_TXT_DHE_DSS_WITH_RC4_128_SHA "DHE-DSS-RC4-SHA" + +/* AES ciphersuites from RFC3268 */ +#define TLS1_TXT_RSA_WITH_AES_128_SHA "AES128-SHA" +#define TLS1_TXT_DH_DSS_WITH_AES_128_SHA "DH-DSS-AES128-SHA" +#define TLS1_TXT_DH_RSA_WITH_AES_128_SHA "DH-RSA-AES128-SHA" +#define TLS1_TXT_DHE_DSS_WITH_AES_128_SHA "DHE-DSS-AES128-SHA" +#define TLS1_TXT_DHE_RSA_WITH_AES_128_SHA "DHE-RSA-AES128-SHA" +#define TLS1_TXT_ADH_WITH_AES_128_SHA "ADH-AES128-SHA" + +#define TLS1_TXT_RSA_WITH_AES_256_SHA "AES256-SHA" +#define TLS1_TXT_DH_DSS_WITH_AES_256_SHA "DH-DSS-AES256-SHA" +#define TLS1_TXT_DH_RSA_WITH_AES_256_SHA "DH-RSA-AES256-SHA" +#define TLS1_TXT_DHE_DSS_WITH_AES_256_SHA "DHE-DSS-AES256-SHA" +#define TLS1_TXT_DHE_RSA_WITH_AES_256_SHA "DHE-RSA-AES256-SHA" +#define TLS1_TXT_ADH_WITH_AES_256_SHA "ADH-AES256-SHA" + +/* ECC ciphersuites from RFC4492 */ +#define TLS1_TXT_ECDH_ECDSA_WITH_NULL_SHA "ECDH-ECDSA-NULL-SHA" +#define TLS1_TXT_ECDH_ECDSA_WITH_RC4_128_SHA "ECDH-ECDSA-RC4-SHA" +#define TLS1_TXT_ECDH_ECDSA_WITH_DES_192_CBC3_SHA "ECDH-ECDSA-DES-CBC3-SHA" +#define TLS1_TXT_ECDH_ECDSA_WITH_AES_128_CBC_SHA "ECDH-ECDSA-AES128-SHA" +#define TLS1_TXT_ECDH_ECDSA_WITH_AES_256_CBC_SHA "ECDH-ECDSA-AES256-SHA" + +#define TLS1_TXT_ECDHE_ECDSA_WITH_NULL_SHA "ECDHE-ECDSA-NULL-SHA" +#define TLS1_TXT_ECDHE_ECDSA_WITH_RC4_128_SHA "ECDHE-ECDSA-RC4-SHA" +#define TLS1_TXT_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA "ECDHE-ECDSA-DES-CBC3-SHA" +#define TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_CBC_SHA "ECDHE-ECDSA-AES128-SHA" +#define TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_CBC_SHA "ECDHE-ECDSA-AES256-SHA" + +#define TLS1_TXT_ECDH_RSA_WITH_NULL_SHA "ECDH-RSA-NULL-SHA" +#define TLS1_TXT_ECDH_RSA_WITH_RC4_128_SHA "ECDH-RSA-RC4-SHA" +#define TLS1_TXT_ECDH_RSA_WITH_DES_192_CBC3_SHA "ECDH-RSA-DES-CBC3-SHA" +#define TLS1_TXT_ECDH_RSA_WITH_AES_128_CBC_SHA "ECDH-RSA-AES128-SHA" +#define TLS1_TXT_ECDH_RSA_WITH_AES_256_CBC_SHA "ECDH-RSA-AES256-SHA" + +#define TLS1_TXT_ECDHE_RSA_WITH_NULL_SHA "ECDHE-RSA-NULL-SHA" +#define TLS1_TXT_ECDHE_RSA_WITH_RC4_128_SHA "ECDHE-RSA-RC4-SHA" +#define TLS1_TXT_ECDHE_RSA_WITH_DES_192_CBC3_SHA "ECDHE-RSA-DES-CBC3-SHA" +#define TLS1_TXT_ECDHE_RSA_WITH_AES_128_CBC_SHA "ECDHE-RSA-AES128-SHA" +#define TLS1_TXT_ECDHE_RSA_WITH_AES_256_CBC_SHA "ECDHE-RSA-AES256-SHA" + +#define TLS1_TXT_ECDH_anon_WITH_NULL_SHA "AECDH-NULL-SHA" +#define TLS1_TXT_ECDH_anon_WITH_RC4_128_SHA "AECDH-RC4-SHA" +#define TLS1_TXT_ECDH_anon_WITH_DES_192_CBC3_SHA "AECDH-DES-CBC3-SHA" +#define TLS1_TXT_ECDH_anon_WITH_AES_128_CBC_SHA "AECDH-AES128-SHA" +#define TLS1_TXT_ECDH_anon_WITH_AES_256_CBC_SHA "AECDH-AES256-SHA" + +/* PSK ciphersuites from RFC 4279 */ +#define TLS1_TXT_PSK_WITH_RC4_128_SHA "PSK-RC4-SHA" +#define TLS1_TXT_PSK_WITH_3DES_EDE_CBC_SHA "PSK-3DES-EDE-CBC-SHA" +#define TLS1_TXT_PSK_WITH_AES_128_CBC_SHA "PSK-AES128-CBC-SHA" +#define TLS1_TXT_PSK_WITH_AES_256_CBC_SHA "PSK-AES256-CBC-SHA" + +/* PSK ciphersuites from RFC 5489 */ +#define TLS1_TXT_ECDHE_PSK_WITH_AES_128_CBC_SHA "ECDHE-PSK-AES128-CBC-SHA" +#define TLS1_TXT_ECDHE_PSK_WITH_AES_256_CBC_SHA "ECDHE-PSK-AES256-CBC-SHA" + +/* SRP ciphersuite from RFC 5054 */ +#define TLS1_TXT_SRP_SHA_WITH_3DES_EDE_CBC_SHA "SRP-3DES-EDE-CBC-SHA" +#define TLS1_TXT_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA "SRP-RSA-3DES-EDE-CBC-SHA" +#define TLS1_TXT_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA "SRP-DSS-3DES-EDE-CBC-SHA" +#define TLS1_TXT_SRP_SHA_WITH_AES_128_CBC_SHA "SRP-AES-128-CBC-SHA" +#define TLS1_TXT_SRP_SHA_RSA_WITH_AES_128_CBC_SHA "SRP-RSA-AES-128-CBC-SHA" +#define TLS1_TXT_SRP_SHA_DSS_WITH_AES_128_CBC_SHA "SRP-DSS-AES-128-CBC-SHA" +#define TLS1_TXT_SRP_SHA_WITH_AES_256_CBC_SHA "SRP-AES-256-CBC-SHA" +#define TLS1_TXT_SRP_SHA_RSA_WITH_AES_256_CBC_SHA "SRP-RSA-AES-256-CBC-SHA" +#define TLS1_TXT_SRP_SHA_DSS_WITH_AES_256_CBC_SHA "SRP-DSS-AES-256-CBC-SHA" + +/* Camellia ciphersuites from RFC4132 */ +#define TLS1_TXT_RSA_WITH_CAMELLIA_128_CBC_SHA "CAMELLIA128-SHA" +#define TLS1_TXT_DH_DSS_WITH_CAMELLIA_128_CBC_SHA "DH-DSS-CAMELLIA128-SHA" +#define TLS1_TXT_DH_RSA_WITH_CAMELLIA_128_CBC_SHA "DH-RSA-CAMELLIA128-SHA" +#define TLS1_TXT_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA "DHE-DSS-CAMELLIA128-SHA" +#define TLS1_TXT_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA "DHE-RSA-CAMELLIA128-SHA" +#define TLS1_TXT_ADH_WITH_CAMELLIA_128_CBC_SHA "ADH-CAMELLIA128-SHA" + +#define TLS1_TXT_RSA_WITH_CAMELLIA_256_CBC_SHA "CAMELLIA256-SHA" +#define TLS1_TXT_DH_DSS_WITH_CAMELLIA_256_CBC_SHA "DH-DSS-CAMELLIA256-SHA" +#define TLS1_TXT_DH_RSA_WITH_CAMELLIA_256_CBC_SHA "DH-RSA-CAMELLIA256-SHA" +#define TLS1_TXT_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA "DHE-DSS-CAMELLIA256-SHA" +#define TLS1_TXT_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA "DHE-RSA-CAMELLIA256-SHA" +#define TLS1_TXT_ADH_WITH_CAMELLIA_256_CBC_SHA "ADH-CAMELLIA256-SHA" + +/* SEED ciphersuites from RFC4162 */ +#define TLS1_TXT_RSA_WITH_SEED_SHA "SEED-SHA" +#define TLS1_TXT_DH_DSS_WITH_SEED_SHA "DH-DSS-SEED-SHA" +#define TLS1_TXT_DH_RSA_WITH_SEED_SHA "DH-RSA-SEED-SHA" +#define TLS1_TXT_DHE_DSS_WITH_SEED_SHA "DHE-DSS-SEED-SHA" +#define TLS1_TXT_DHE_RSA_WITH_SEED_SHA "DHE-RSA-SEED-SHA" +#define TLS1_TXT_ADH_WITH_SEED_SHA "ADH-SEED-SHA" + +/* TLS v1.2 ciphersuites */ +#define TLS1_TXT_RSA_WITH_NULL_SHA256 "NULL-SHA256" +#define TLS1_TXT_RSA_WITH_AES_128_SHA256 "AES128-SHA256" +#define TLS1_TXT_RSA_WITH_AES_256_SHA256 "AES256-SHA256" +#define TLS1_TXT_DH_DSS_WITH_AES_128_SHA256 "DH-DSS-AES128-SHA256" +#define TLS1_TXT_DH_RSA_WITH_AES_128_SHA256 "DH-RSA-AES128-SHA256" +#define TLS1_TXT_DHE_DSS_WITH_AES_128_SHA256 "DHE-DSS-AES128-SHA256" +#define TLS1_TXT_DHE_RSA_WITH_AES_128_SHA256 "DHE-RSA-AES128-SHA256" +#define TLS1_TXT_DH_DSS_WITH_AES_256_SHA256 "DH-DSS-AES256-SHA256" +#define TLS1_TXT_DH_RSA_WITH_AES_256_SHA256 "DH-RSA-AES256-SHA256" +#define TLS1_TXT_DHE_DSS_WITH_AES_256_SHA256 "DHE-DSS-AES256-SHA256" +#define TLS1_TXT_DHE_RSA_WITH_AES_256_SHA256 "DHE-RSA-AES256-SHA256" +#define TLS1_TXT_ADH_WITH_AES_128_SHA256 "ADH-AES128-SHA256" +#define TLS1_TXT_ADH_WITH_AES_256_SHA256 "ADH-AES256-SHA256" + +/* TLS v1.2 GCM ciphersuites from RFC5288 */ +#define TLS1_TXT_RSA_WITH_AES_128_GCM_SHA256 "AES128-GCM-SHA256" +#define TLS1_TXT_RSA_WITH_AES_256_GCM_SHA384 "AES256-GCM-SHA384" +#define TLS1_TXT_DHE_RSA_WITH_AES_128_GCM_SHA256 "DHE-RSA-AES128-GCM-SHA256" +#define TLS1_TXT_DHE_RSA_WITH_AES_256_GCM_SHA384 "DHE-RSA-AES256-GCM-SHA384" +#define TLS1_TXT_DH_RSA_WITH_AES_128_GCM_SHA256 "DH-RSA-AES128-GCM-SHA256" +#define TLS1_TXT_DH_RSA_WITH_AES_256_GCM_SHA384 "DH-RSA-AES256-GCM-SHA384" +#define TLS1_TXT_DHE_DSS_WITH_AES_128_GCM_SHA256 "DHE-DSS-AES128-GCM-SHA256" +#define TLS1_TXT_DHE_DSS_WITH_AES_256_GCM_SHA384 "DHE-DSS-AES256-GCM-SHA384" +#define TLS1_TXT_DH_DSS_WITH_AES_128_GCM_SHA256 "DH-DSS-AES128-GCM-SHA256" +#define TLS1_TXT_DH_DSS_WITH_AES_256_GCM_SHA384 "DH-DSS-AES256-GCM-SHA384" +#define TLS1_TXT_ADH_WITH_AES_128_GCM_SHA256 "ADH-AES128-GCM-SHA256" +#define TLS1_TXT_ADH_WITH_AES_256_GCM_SHA384 "ADH-AES256-GCM-SHA384" + +/* ECDH HMAC based ciphersuites from RFC5289 */ + +#define TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_SHA256 "ECDHE-ECDSA-AES128-SHA256" +#define TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_SHA384 "ECDHE-ECDSA-AES256-SHA384" +#define TLS1_TXT_ECDH_ECDSA_WITH_AES_128_SHA256 "ECDH-ECDSA-AES128-SHA256" +#define TLS1_TXT_ECDH_ECDSA_WITH_AES_256_SHA384 "ECDH-ECDSA-AES256-SHA384" +#define TLS1_TXT_ECDHE_RSA_WITH_AES_128_SHA256 "ECDHE-RSA-AES128-SHA256" +#define TLS1_TXT_ECDHE_RSA_WITH_AES_256_SHA384 "ECDHE-RSA-AES256-SHA384" +#define TLS1_TXT_ECDH_RSA_WITH_AES_128_SHA256 "ECDH-RSA-AES128-SHA256" +#define TLS1_TXT_ECDH_RSA_WITH_AES_256_SHA384 "ECDH-RSA-AES256-SHA384" + +/* ECDH GCM based ciphersuites from RFC5289 */ +#define TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 \ + "ECDHE-ECDSA-AES128-GCM-SHA256" +#define TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 \ + "ECDHE-ECDSA-AES256-GCM-SHA384" +#define TLS1_TXT_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 \ + "ECDH-ECDSA-AES128-GCM-SHA256" +#define TLS1_TXT_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 \ + "ECDH-ECDSA-AES256-GCM-SHA384" +#define TLS1_TXT_ECDHE_RSA_WITH_AES_128_GCM_SHA256 "ECDHE-RSA-AES128-GCM-SHA256" +#define TLS1_TXT_ECDHE_RSA_WITH_AES_256_GCM_SHA384 "ECDHE-RSA-AES256-GCM-SHA384" +#define TLS1_TXT_ECDH_RSA_WITH_AES_128_GCM_SHA256 "ECDH-RSA-AES128-GCM-SHA256" +#define TLS1_TXT_ECDH_RSA_WITH_AES_256_GCM_SHA384 "ECDH-RSA-AES256-GCM-SHA384" + +/* For convenience, the old and new CHACHA20_POLY1305 ciphers have the same + * name. In cipher strings, both will be selected. This is temporary and will be + * removed when the pre-standard construction is removed. */ +#define TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305_OLD \ + "ECDHE-RSA-CHACHA20-POLY1305" +#define TLS1_TXT_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_OLD \ + "ECDHE-ECDSA-CHACHA20-POLY1305" + +#define TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 \ + "ECDHE-RSA-CHACHA20-POLY1305" +#define TLS1_TXT_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 \ + "ECDHE-ECDSA-CHACHA20-POLY1305" +#define TLS1_TXT_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 \ + "ECDHE-PSK-CHACHA20-POLY1305" + +/* TODO(davidben): Remove this. Historically, the TXT names for CHACHA20_POLY1305 + * were missing 'SHA256'. */ +#define TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305 \ + TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 + +/* PSK ciphersuites from mattsson-tls-ecdhe-psk-aead */ +#define TLS1_TXT_ECDHE_PSK_WITH_AES_128_GCM_SHA256 "ECDHE-PSK-AES128-GCM-SHA256" +#define TLS1_TXT_ECDHE_PSK_WITH_AES_256_GCM_SHA384 "ECDHE-PSK-AES256-GCM-SHA384" + +/* CECPQ1 ciphersuites. These are specific to BoringSSL and not standard. */ +#define TLS1_TXT_CECPQ1_RSA_WITH_CHACHA20_POLY1305_SHA256 \ + "CECPQ1-RSA-CHACHA20-POLY1305-SHA256" +#define TLS1_TXT_CECPQ1_ECDSA_WITH_CHACHA20_POLY1305_SHA256 \ + "CECPQ1-ECDSA-CHACHA20-POLY1305-SHA256" +#define TLS1_TXT_CECPQ1_RSA_WITH_AES_256_GCM_SHA384 \ + "CECPQ1-RSA-AES256-GCM-SHA384" +#define TLS1_TXT_CECPQ1_ECDSA_WITH_AES_256_GCM_SHA384 \ + "CECPQ1-ECDSA-AES256-GCM-SHA384" + + +#define TLS_CT_RSA_SIGN 1 +#define TLS_CT_DSS_SIGN 2 +#define TLS_CT_RSA_FIXED_DH 3 +#define TLS_CT_DSS_FIXED_DH 4 +#define TLS_CT_ECDSA_SIGN 64 +#define TLS_CT_RSA_FIXED_ECDH 65 +#define TLS_CT_ECDSA_FIXED_ECDH 66 + +#define TLS_MD_MAX_CONST_SIZE 20 +#define TLS_MD_CLIENT_FINISH_CONST "client finished" +#define TLS_MD_CLIENT_FINISH_CONST_SIZE 15 +#define TLS_MD_SERVER_FINISH_CONST "server finished" +#define TLS_MD_SERVER_FINISH_CONST_SIZE 15 +#define TLS_MD_KEY_EXPANSION_CONST "key expansion" +#define TLS_MD_KEY_EXPANSION_CONST_SIZE 13 +#define TLS_MD_CLIENT_WRITE_KEY_CONST "client write key" +#define TLS_MD_CLIENT_WRITE_KEY_CONST_SIZE 16 +#define TLS_MD_SERVER_WRITE_KEY_CONST "server write key" +#define TLS_MD_SERVER_WRITE_KEY_CONST_SIZE 16 +#define TLS_MD_IV_BLOCK_CONST "IV block" +#define TLS_MD_IV_BLOCK_CONST_SIZE 8 +#define TLS_MD_MASTER_SECRET_CONST "master secret" +#define TLS_MD_MASTER_SECRET_CONST_SIZE 13 +#define TLS_MD_EXTENDED_MASTER_SECRET_CONST "extended master secret" +#define TLS_MD_EXTENDED_MASTER_SECRET_CONST_SIZE 22 + + +#ifdef __cplusplus +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_TLS1_H */ diff --git a/external/boringssl/include/openssl/type_check.h b/external/boringssl/include/openssl/type_check.h new file mode 100644 index 0000000000..674913a354 --- /dev/null +++ b/external/boringssl/include/openssl/type_check.h @@ -0,0 +1,91 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_TYPE_CHECK_H +#define OPENSSL_HEADER_TYPE_CHECK_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* This header file contains some common macros for enforcing type checking. + * Several, common OpenSSL structures (i.e. stack and lhash) operate on void + * pointers, but we wish to have type checking when they are used with a + * specific type. */ + +/* CHECKED_CAST casts |p| from type |from| to type |to|. */ +#define CHECKED_CAST(to, from, p) ((to) (1 ? (p) : (from)0)) + +/* CHECKED_PTR_OF casts a given pointer to void* and statically checks that it + * was a pointer to |type|. */ +#define CHECKED_PTR_OF(type, p) CHECKED_CAST(void*, type*, (p)) + +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L +#define OPENSSL_COMPILE_ASSERT(cond, msg) _Static_assert(cond, #msg) +#else +#define OPENSSL_COMPILE_ASSERT(cond, msg) \ + typedef char OPENSSL_COMPILE_ASSERT_##msg[((cond) ? 1 : -1)] +#endif + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_TYPE_CHECK_H */ diff --git a/external/boringssl/include/openssl/x509.h b/external/boringssl/include/openssl/x509.h new file mode 100644 index 0000000000..bbc263e090 --- /dev/null +++ b/external/boringssl/include/openssl/x509.h @@ -0,0 +1,1267 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * ECDH support in OpenSSL originally developed by + * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. + */ + +#ifndef HEADER_X509_H +#define HEADER_X509_H + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +#define X509_FILETYPE_PEM 1 +#define X509_FILETYPE_ASN1 2 +#define X509_FILETYPE_DEFAULT 3 + +#define X509v3_KU_DIGITAL_SIGNATURE 0x0080 +#define X509v3_KU_NON_REPUDIATION 0x0040 +#define X509v3_KU_KEY_ENCIPHERMENT 0x0020 +#define X509v3_KU_DATA_ENCIPHERMENT 0x0010 +#define X509v3_KU_KEY_AGREEMENT 0x0008 +#define X509v3_KU_KEY_CERT_SIGN 0x0004 +#define X509v3_KU_CRL_SIGN 0x0002 +#define X509v3_KU_ENCIPHER_ONLY 0x0001 +#define X509v3_KU_DECIPHER_ONLY 0x8000 +#define X509v3_KU_UNDEF 0xffff + +struct X509_objects_st + { + int nid; + int (*a2i)(void); + int (*i2a)(void); + } /* X509_OBJECTS */; + +DECLARE_ASN1_SET_OF(X509_ALGOR) + +typedef STACK_OF(X509_ALGOR) X509_ALGORS; + +struct X509_val_st + { + ASN1_TIME *notBefore; + ASN1_TIME *notAfter; + } /* X509_VAL */; + +struct X509_pubkey_st + { + X509_ALGOR *algor; + ASN1_BIT_STRING *public_key; + EVP_PKEY *pkey; + }; + +struct X509_sig_st + { + X509_ALGOR *algor; + ASN1_OCTET_STRING *digest; + } /* X509_SIG */; + +struct X509_name_entry_st + { + ASN1_OBJECT *object; + ASN1_STRING *value; + int set; + int size; /* temp variable */ + } /* X509_NAME_ENTRY */; + +DECLARE_STACK_OF(X509_NAME_ENTRY) +DECLARE_ASN1_SET_OF(X509_NAME_ENTRY) + +/* we always keep X509_NAMEs in 2 forms. */ +struct X509_name_st + { + STACK_OF(X509_NAME_ENTRY) *entries; + int modified; /* true if 'bytes' needs to be built */ +#ifndef OPENSSL_NO_BUFFER + BUF_MEM *bytes; +#else + char *bytes; +#endif +/* unsigned long hash; Keep the hash around for lookups */ + unsigned char *canon_enc; + int canon_enclen; + } /* X509_NAME */; + +DECLARE_STACK_OF(X509_NAME) + +#define X509_EX_V_NETSCAPE_HACK 0x8000 +#define X509_EX_V_INIT 0x0001 +struct X509_extension_st + { + ASN1_OBJECT *object; + ASN1_BOOLEAN critical; + ASN1_OCTET_STRING *value; + } /* X509_EXTENSION */; + +typedef STACK_OF(X509_EXTENSION) X509_EXTENSIONS; + +DECLARE_STACK_OF(X509_EXTENSION) +DECLARE_ASN1_SET_OF(X509_EXTENSION) + +/* a sequence of these are used */ +struct x509_attributes_st + { + ASN1_OBJECT *object; + int single; /* 0 for a set, 1 for a single item (which is wrong) */ + union { + char *ptr; +/* 0 */ STACK_OF(ASN1_TYPE) *set; +/* 1 */ ASN1_TYPE *single; + } value; + } /* X509_ATTRIBUTE */; + +DECLARE_STACK_OF(X509_ATTRIBUTE) +DECLARE_ASN1_SET_OF(X509_ATTRIBUTE) + + +struct X509_req_info_st + { + ASN1_ENCODING enc; + ASN1_INTEGER *version; + X509_NAME *subject; + X509_PUBKEY *pubkey; + /* d=2 hl=2 l= 0 cons: cont: 00 */ + STACK_OF(X509_ATTRIBUTE) *attributes; /* [ 0 ] */ + } /* X509_REQ_INFO */; + +struct X509_req_st + { + X509_REQ_INFO *req_info; + X509_ALGOR *sig_alg; + ASN1_BIT_STRING *signature; + CRYPTO_refcount_t references; + } /* X509_REQ */; + +struct x509_cinf_st + { + ASN1_INTEGER *version; /* [ 0 ] default of v1 */ + ASN1_INTEGER *serialNumber; + X509_ALGOR *signature; + X509_NAME *issuer; + X509_VAL *validity; + X509_NAME *subject; + X509_PUBKEY *key; + ASN1_BIT_STRING *issuerUID; /* [ 1 ] optional in v2 */ + ASN1_BIT_STRING *subjectUID; /* [ 2 ] optional in v2 */ + STACK_OF(X509_EXTENSION) *extensions; /* [ 3 ] optional in v3 */ + ASN1_ENCODING enc; + } /* X509_CINF */; + +/* This stuff is certificate "auxiliary info" + * it contains details which are useful in certificate + * stores and databases. When used this is tagged onto + * the end of the certificate itself + */ + +struct x509_cert_aux_st + { + STACK_OF(ASN1_OBJECT) *trust; /* trusted uses */ + STACK_OF(ASN1_OBJECT) *reject; /* rejected uses */ + ASN1_UTF8STRING *alias; /* "friendly name" */ + ASN1_OCTET_STRING *keyid; /* key id of private key */ + STACK_OF(X509_ALGOR) *other; /* other unspecified info */ + } /* X509_CERT_AUX */; + +struct x509_st + { + X509_CINF *cert_info; + X509_ALGOR *sig_alg; + ASN1_BIT_STRING *signature; + int valid; + CRYPTO_refcount_t references; + char *name; + CRYPTO_EX_DATA ex_data; + /* These contain copies of various extension values */ + long ex_pathlen; + long ex_pcpathlen; + unsigned long ex_flags; + unsigned long ex_kusage; + unsigned long ex_xkusage; + unsigned long ex_nscert; + ASN1_OCTET_STRING *skid; + AUTHORITY_KEYID *akid; + X509_POLICY_CACHE *policy_cache; + STACK_OF(DIST_POINT) *crldp; + STACK_OF(GENERAL_NAME) *altname; + NAME_CONSTRAINTS *nc; + unsigned char sha1_hash[SHA_DIGEST_LENGTH]; + X509_CERT_AUX *aux; + } /* X509 */; + +DECLARE_STACK_OF(X509) +DECLARE_ASN1_SET_OF(X509) + +/* This is used for a table of trust checking functions */ + +struct x509_trust_st { + int trust; + int flags; + int (*check_trust)(struct x509_trust_st *, X509 *, int); + char *name; + int arg1; + void *arg2; +} /* X509_TRUST */; + +DECLARE_STACK_OF(X509_TRUST) + +struct x509_cert_pair_st { + X509 *forward; + X509 *reverse; +} /* X509_CERT_PAIR */; + +/* standard trust ids */ + +#define X509_TRUST_DEFAULT -1 /* Only valid in purpose settings */ + +#define X509_TRUST_COMPAT 1 +#define X509_TRUST_SSL_CLIENT 2 +#define X509_TRUST_SSL_SERVER 3 +#define X509_TRUST_EMAIL 4 +#define X509_TRUST_OBJECT_SIGN 5 +#define X509_TRUST_OCSP_SIGN 6 +#define X509_TRUST_OCSP_REQUEST 7 +#define X509_TRUST_TSA 8 + +/* Keep these up to date! */ +#define X509_TRUST_MIN 1 +#define X509_TRUST_MAX 8 + + +/* trust_flags values */ +#define X509_TRUST_DYNAMIC 1 +#define X509_TRUST_DYNAMIC_NAME 2 + +/* check_trust return codes */ + +#define X509_TRUST_TRUSTED 1 +#define X509_TRUST_REJECTED 2 +#define X509_TRUST_UNTRUSTED 3 + +/* Flags for X509_print_ex() */ + +#define X509_FLAG_COMPAT 0 +#define X509_FLAG_NO_HEADER 1L +#define X509_FLAG_NO_VERSION (1L << 1) +#define X509_FLAG_NO_SERIAL (1L << 2) +#define X509_FLAG_NO_SIGNAME (1L << 3) +#define X509_FLAG_NO_ISSUER (1L << 4) +#define X509_FLAG_NO_VALIDITY (1L << 5) +#define X509_FLAG_NO_SUBJECT (1L << 6) +#define X509_FLAG_NO_PUBKEY (1L << 7) +#define X509_FLAG_NO_EXTENSIONS (1L << 8) +#define X509_FLAG_NO_SIGDUMP (1L << 9) +#define X509_FLAG_NO_AUX (1L << 10) +#define X509_FLAG_NO_ATTRIBUTES (1L << 11) +#define X509_FLAG_NO_IDS (1L << 12) + +/* Flags specific to X509_NAME_print_ex() */ + +/* The field separator information */ + +#define XN_FLAG_SEP_MASK (0xf << 16) + +#define XN_FLAG_COMPAT 0 /* Traditional SSLeay: use old X509_NAME_print */ +#define XN_FLAG_SEP_COMMA_PLUS (1 << 16) /* RFC2253 ,+ */ +#define XN_FLAG_SEP_CPLUS_SPC (2 << 16) /* ,+ spaced: more readable */ +#define XN_FLAG_SEP_SPLUS_SPC (3 << 16) /* ;+ spaced */ +#define XN_FLAG_SEP_MULTILINE (4 << 16) /* One line per field */ + +#define XN_FLAG_DN_REV (1 << 20) /* Reverse DN order */ + +/* How the field name is shown */ + +#define XN_FLAG_FN_MASK (0x3 << 21) + +#define XN_FLAG_FN_SN 0 /* Object short name */ +#define XN_FLAG_FN_LN (1 << 21) /* Object long name */ +#define XN_FLAG_FN_OID (2 << 21) /* Always use OIDs */ +#define XN_FLAG_FN_NONE (3 << 21) /* No field names */ + +#define XN_FLAG_SPC_EQ (1 << 23) /* Put spaces round '=' */ + +/* This determines if we dump fields we don't recognise: + * RFC2253 requires this. + */ + +#define XN_FLAG_DUMP_UNKNOWN_FIELDS (1 << 24) + +#define XN_FLAG_FN_ALIGN (1 << 25) /* Align field names to 20 characters */ + +/* Complete set of RFC2253 flags */ + +#define XN_FLAG_RFC2253 (ASN1_STRFLGS_RFC2253 | \ + XN_FLAG_SEP_COMMA_PLUS | \ + XN_FLAG_DN_REV | \ + XN_FLAG_FN_SN | \ + XN_FLAG_DUMP_UNKNOWN_FIELDS) + +/* readable oneline form */ + +#define XN_FLAG_ONELINE (ASN1_STRFLGS_RFC2253 | \ + ASN1_STRFLGS_ESC_QUOTE | \ + XN_FLAG_SEP_CPLUS_SPC | \ + XN_FLAG_SPC_EQ | \ + XN_FLAG_FN_SN) + +/* readable multiline form */ + +#define XN_FLAG_MULTILINE (ASN1_STRFLGS_ESC_CTRL | \ + ASN1_STRFLGS_ESC_MSB | \ + XN_FLAG_SEP_MULTILINE | \ + XN_FLAG_SPC_EQ | \ + XN_FLAG_FN_LN | \ + XN_FLAG_FN_ALIGN) + +struct x509_revoked_st + { + ASN1_INTEGER *serialNumber; + ASN1_TIME *revocationDate; + STACK_OF(X509_EXTENSION) /* optional */ *extensions; + /* Set up if indirect CRL */ + STACK_OF(GENERAL_NAME) *issuer; + /* Revocation reason */ + int reason; + int sequence; /* load sequence */ + }; + +DECLARE_STACK_OF(X509_REVOKED) +DECLARE_ASN1_SET_OF(X509_REVOKED) + +struct X509_crl_info_st + { + ASN1_INTEGER *version; + X509_ALGOR *sig_alg; + X509_NAME *issuer; + ASN1_TIME *lastUpdate; + ASN1_TIME *nextUpdate; + STACK_OF(X509_REVOKED) *revoked; + STACK_OF(X509_EXTENSION) /* [0] */ *extensions; + ASN1_ENCODING enc; + } /* X509_CRL_INFO */; + +struct X509_crl_st + { + /* actual signature */ + X509_CRL_INFO *crl; + X509_ALGOR *sig_alg; + ASN1_BIT_STRING *signature; + CRYPTO_refcount_t references; + int flags; + /* Copies of various extensions */ + AUTHORITY_KEYID *akid; + ISSUING_DIST_POINT *idp; + /* Convenient breakdown of IDP */ + int idp_flags; + int idp_reasons; + /* CRL and base CRL numbers for delta processing */ + ASN1_INTEGER *crl_number; + ASN1_INTEGER *base_crl_number; + unsigned char sha1_hash[SHA_DIGEST_LENGTH]; + STACK_OF(GENERAL_NAMES) *issuers; + const X509_CRL_METHOD *meth; + void *meth_data; + } /* X509_CRL */; + +DECLARE_STACK_OF(X509_CRL) +DECLARE_ASN1_SET_OF(X509_CRL) + +struct private_key_st + { + int version; + /* The PKCS#8 data types */ + X509_ALGOR *enc_algor; + ASN1_OCTET_STRING *enc_pkey; /* encrypted pub key */ + + /* When decrypted, the following will not be NULL */ + EVP_PKEY *dec_pkey; + + /* used to encrypt and decrypt */ + int key_length; + char *key_data; + int key_free; /* true if we should auto free key_data */ + + /* expanded version of 'enc_algor' */ + EVP_CIPHER_INFO cipher; + } /* X509_PKEY */; + +#ifndef OPENSSL_NO_EVP +struct X509_info_st + { + X509 *x509; + X509_CRL *crl; + X509_PKEY *x_pkey; + + EVP_CIPHER_INFO enc_cipher; + int enc_len; + char *enc_data; + + } /* X509_INFO */; + +DECLARE_STACK_OF(X509_INFO) +#endif + +/* The next 2 structures and their 8 routines were sent to me by + * Pat Richard and are used to manipulate + * Netscapes spki structures - useful if you are writing a CA web page + */ +struct Netscape_spkac_st + { + X509_PUBKEY *pubkey; + ASN1_IA5STRING *challenge; /* challenge sent in atlas >= PR2 */ + } /* NETSCAPE_SPKAC */; + +struct Netscape_spki_st + { + NETSCAPE_SPKAC *spkac; /* signed public key and challenge */ + X509_ALGOR *sig_algor; + ASN1_BIT_STRING *signature; + } /* NETSCAPE_SPKI */; + +/* Netscape certificate sequence structure */ +struct Netscape_certificate_sequence + { + ASN1_OBJECT *type; + STACK_OF(X509) *certs; + } /* NETSCAPE_CERT_SEQUENCE */; + +/* Unused (and iv length is wrong) +typedef struct CBCParameter_st + { + unsigned char iv[8]; + } CBC_PARAM; +*/ + +/* Password based encryption structure */ + +struct PBEPARAM_st { +ASN1_OCTET_STRING *salt; +ASN1_INTEGER *iter; +} /* PBEPARAM */; + +/* Password based encryption V2 structures */ + +struct PBE2PARAM_st { +X509_ALGOR *keyfunc; +X509_ALGOR *encryption; +} /* PBE2PARAM */; + +struct PBKDF2PARAM_st { +ASN1_TYPE *salt; /* Usually OCTET STRING but could be anything */ +ASN1_INTEGER *iter; +ASN1_INTEGER *keylength; +X509_ALGOR *prf; +} /* PBKDF2PARAM */; + + +/* PKCS#8 private key info structure */ + +struct pkcs8_priv_key_info_st + { + int broken; /* Flag for various broken formats */ +#define PKCS8_OK 0 +#define PKCS8_NO_OCTET 1 +#define PKCS8_EMBEDDED_PARAM 2 +#define PKCS8_NS_DB 3 +#define PKCS8_NEG_PRIVKEY 4 + ASN1_INTEGER *version; + X509_ALGOR *pkeyalg; + ASN1_TYPE *pkey; /* Should be OCTET STRING but some are broken */ + STACK_OF(X509_ATTRIBUTE) *attributes; + }; + +#ifdef __cplusplus +} +#endif + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define X509_EXT_PACK_UNKNOWN 1 +#define X509_EXT_PACK_STRING 2 + +#define X509_get_version(x) ASN1_INTEGER_get((x)->cert_info->version) +/* #define X509_get_serialNumber(x) ((x)->cert_info->serialNumber) */ +#define X509_get_notBefore(x) ((x)->cert_info->validity->notBefore) +#define X509_get_notAfter(x) ((x)->cert_info->validity->notAfter) +#define X509_get_cert_info(x) ((x)->cert_info) +#define X509_extract_key(x) X509_get_pubkey(x) /*****/ +#define X509_REQ_get_version(x) ASN1_INTEGER_get((x)->req_info->version) +#define X509_REQ_get_subject_name(x) ((x)->req_info->subject) +#define X509_REQ_extract_key(a) X509_REQ_get_pubkey(a) +#define X509_name_cmp(a,b) X509_NAME_cmp((a),(b)) +#define X509_get_signature_type(x) EVP_PKEY_type(OBJ_obj2nid((x)->sig_alg->algorithm)) + +#define X509_CRL_get_version(x) ASN1_INTEGER_get((x)->crl->version) +#define X509_CRL_get_lastUpdate(x) ((x)->crl->lastUpdate) +#define X509_CRL_get_nextUpdate(x) ((x)->crl->nextUpdate) +#define X509_CRL_get_issuer(x) ((x)->crl->issuer) +#define X509_CRL_get_REVOKED(x) ((x)->crl->revoked) + +#define X509_CINF_set_modified(c) ((c)->enc.modified = 1) +#define X509_CINF_get_issuer(c) (&(c)->issuer) +#define X509_CINF_get_extensions(c) ((c)->extensions) +#define X509_CINF_get_signature(c) ((c)->signature) + +OPENSSL_EXPORT void X509_CRL_set_default_method(const X509_CRL_METHOD *meth); +OPENSSL_EXPORT X509_CRL_METHOD *X509_CRL_METHOD_new( + int (*crl_init)(X509_CRL *crl), + int (*crl_free)(X509_CRL *crl), + int (*crl_lookup)(X509_CRL *crl, X509_REVOKED **ret, + ASN1_INTEGER *ser, X509_NAME *issuer), + int (*crl_verify)(X509_CRL *crl, EVP_PKEY *pk)); +OPENSSL_EXPORT void X509_CRL_METHOD_free(X509_CRL_METHOD *m); + +OPENSSL_EXPORT void X509_CRL_set_meth_data(X509_CRL *crl, void *dat); +OPENSSL_EXPORT void *X509_CRL_get_meth_data(X509_CRL *crl); + +/* This one is only used so that a binary form can output, as in + * i2d_X509_NAME(X509_get_X509_PUBKEY(x),&buf) */ +#define X509_get_X509_PUBKEY(x) ((x)->cert_info->key) + + +OPENSSL_EXPORT const char *X509_verify_cert_error_string(long n); + +#ifndef OPENSSL_NO_EVP +OPENSSL_EXPORT int X509_verify(X509 *a, EVP_PKEY *r); + +OPENSSL_EXPORT int X509_REQ_verify(X509_REQ *a, EVP_PKEY *r); +OPENSSL_EXPORT int X509_CRL_verify(X509_CRL *a, EVP_PKEY *r); +OPENSSL_EXPORT int NETSCAPE_SPKI_verify(NETSCAPE_SPKI *a, EVP_PKEY *r); + +OPENSSL_EXPORT NETSCAPE_SPKI * NETSCAPE_SPKI_b64_decode(const char *str, int len); +OPENSSL_EXPORT char * NETSCAPE_SPKI_b64_encode(NETSCAPE_SPKI *x); +OPENSSL_EXPORT EVP_PKEY *NETSCAPE_SPKI_get_pubkey(NETSCAPE_SPKI *x); +OPENSSL_EXPORT int NETSCAPE_SPKI_set_pubkey(NETSCAPE_SPKI *x, EVP_PKEY *pkey); + +OPENSSL_EXPORT int NETSCAPE_SPKI_print(BIO *out, NETSCAPE_SPKI *spki); + +OPENSSL_EXPORT int X509_signature_dump(BIO *bp,const ASN1_STRING *sig, int indent); +OPENSSL_EXPORT int X509_signature_print(BIO *bp,X509_ALGOR *alg, ASN1_STRING *sig); + +OPENSSL_EXPORT int X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md); +OPENSSL_EXPORT int X509_sign_ctx(X509 *x, EVP_MD_CTX *ctx); +OPENSSL_EXPORT int X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md); +OPENSSL_EXPORT int X509_REQ_sign_ctx(X509_REQ *x, EVP_MD_CTX *ctx); +OPENSSL_EXPORT int X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md); +OPENSSL_EXPORT int X509_CRL_sign_ctx(X509_CRL *x, EVP_MD_CTX *ctx); +OPENSSL_EXPORT int NETSCAPE_SPKI_sign(NETSCAPE_SPKI *x, EVP_PKEY *pkey, const EVP_MD *md); + +OPENSSL_EXPORT int X509_pubkey_digest(const X509 *data,const EVP_MD *type, + unsigned char *md, unsigned int *len); +OPENSSL_EXPORT int X509_digest(const X509 *data,const EVP_MD *type, + unsigned char *md, unsigned int *len); +OPENSSL_EXPORT int X509_CRL_digest(const X509_CRL *data,const EVP_MD *type, + unsigned char *md, unsigned int *len); +OPENSSL_EXPORT int X509_REQ_digest(const X509_REQ *data,const EVP_MD *type, + unsigned char *md, unsigned int *len); +OPENSSL_EXPORT int X509_NAME_digest(const X509_NAME *data,const EVP_MD *type, + unsigned char *md, unsigned int *len); +#endif + +#ifndef OPENSSL_NO_FP_API +OPENSSL_EXPORT X509 *d2i_X509_fp(FILE *fp, X509 **x509); +OPENSSL_EXPORT int i2d_X509_fp(FILE *fp,X509 *x509); +OPENSSL_EXPORT X509_CRL *d2i_X509_CRL_fp(FILE *fp,X509_CRL **crl); +OPENSSL_EXPORT int i2d_X509_CRL_fp(FILE *fp,X509_CRL *crl); +OPENSSL_EXPORT X509_REQ *d2i_X509_REQ_fp(FILE *fp,X509_REQ **req); +OPENSSL_EXPORT int i2d_X509_REQ_fp(FILE *fp,X509_REQ *req); +OPENSSL_EXPORT RSA *d2i_RSAPrivateKey_fp(FILE *fp,RSA **rsa); +OPENSSL_EXPORT int i2d_RSAPrivateKey_fp(FILE *fp,RSA *rsa); +OPENSSL_EXPORT RSA *d2i_RSAPublicKey_fp(FILE *fp,RSA **rsa); +OPENSSL_EXPORT int i2d_RSAPublicKey_fp(FILE *fp,RSA *rsa); +OPENSSL_EXPORT RSA *d2i_RSA_PUBKEY_fp(FILE *fp,RSA **rsa); +OPENSSL_EXPORT int i2d_RSA_PUBKEY_fp(FILE *fp,RSA *rsa); +#ifndef OPENSSL_NO_DSA +OPENSSL_EXPORT DSA *d2i_DSA_PUBKEY_fp(FILE *fp, DSA **dsa); +OPENSSL_EXPORT int i2d_DSA_PUBKEY_fp(FILE *fp, DSA *dsa); +OPENSSL_EXPORT DSA *d2i_DSAPrivateKey_fp(FILE *fp, DSA **dsa); +OPENSSL_EXPORT int i2d_DSAPrivateKey_fp(FILE *fp, DSA *dsa); +#endif +OPENSSL_EXPORT EC_KEY *d2i_EC_PUBKEY_fp(FILE *fp, EC_KEY **eckey); +OPENSSL_EXPORT int i2d_EC_PUBKEY_fp(FILE *fp, EC_KEY *eckey); +OPENSSL_EXPORT EC_KEY *d2i_ECPrivateKey_fp(FILE *fp, EC_KEY **eckey); +OPENSSL_EXPORT int i2d_ECPrivateKey_fp(FILE *fp, EC_KEY *eckey); +OPENSSL_EXPORT X509_SIG *d2i_PKCS8_fp(FILE *fp,X509_SIG **p8); +OPENSSL_EXPORT int i2d_PKCS8_fp(FILE *fp,X509_SIG *p8); +OPENSSL_EXPORT PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_fp(FILE *fp, + PKCS8_PRIV_KEY_INFO **p8inf); +OPENSSL_EXPORT int i2d_PKCS8_PRIV_KEY_INFO_fp(FILE *fp,PKCS8_PRIV_KEY_INFO *p8inf); +OPENSSL_EXPORT int i2d_PKCS8PrivateKeyInfo_fp(FILE *fp, EVP_PKEY *key); +OPENSSL_EXPORT int i2d_PrivateKey_fp(FILE *fp, EVP_PKEY *pkey); +OPENSSL_EXPORT EVP_PKEY *d2i_PrivateKey_fp(FILE *fp, EVP_PKEY **a); +OPENSSL_EXPORT int i2d_PUBKEY_fp(FILE *fp, EVP_PKEY *pkey); +OPENSSL_EXPORT EVP_PKEY *d2i_PUBKEY_fp(FILE *fp, EVP_PKEY **a); +#endif + +OPENSSL_EXPORT X509 *d2i_X509_bio(BIO *bp,X509 **x509); +OPENSSL_EXPORT int i2d_X509_bio(BIO *bp,X509 *x509); +OPENSSL_EXPORT X509_CRL *d2i_X509_CRL_bio(BIO *bp,X509_CRL **crl); +OPENSSL_EXPORT int i2d_X509_CRL_bio(BIO *bp,X509_CRL *crl); +OPENSSL_EXPORT X509_REQ *d2i_X509_REQ_bio(BIO *bp,X509_REQ **req); +OPENSSL_EXPORT int i2d_X509_REQ_bio(BIO *bp,X509_REQ *req); +OPENSSL_EXPORT RSA *d2i_RSAPrivateKey_bio(BIO *bp,RSA **rsa); +OPENSSL_EXPORT int i2d_RSAPrivateKey_bio(BIO *bp,RSA *rsa); +OPENSSL_EXPORT RSA *d2i_RSAPublicKey_bio(BIO *bp,RSA **rsa); +OPENSSL_EXPORT int i2d_RSAPublicKey_bio(BIO *bp,RSA *rsa); +OPENSSL_EXPORT RSA *d2i_RSA_PUBKEY_bio(BIO *bp,RSA **rsa); +OPENSSL_EXPORT int i2d_RSA_PUBKEY_bio(BIO *bp,RSA *rsa); +#ifndef OPENSSL_NO_DSA +OPENSSL_EXPORT DSA *d2i_DSA_PUBKEY_bio(BIO *bp, DSA **dsa); +OPENSSL_EXPORT int i2d_DSA_PUBKEY_bio(BIO *bp, DSA *dsa); +OPENSSL_EXPORT DSA *d2i_DSAPrivateKey_bio(BIO *bp, DSA **dsa); +OPENSSL_EXPORT int i2d_DSAPrivateKey_bio(BIO *bp, DSA *dsa); +#endif +OPENSSL_EXPORT EC_KEY *d2i_EC_PUBKEY_bio(BIO *bp, EC_KEY **eckey); +OPENSSL_EXPORT int i2d_EC_PUBKEY_bio(BIO *bp, EC_KEY *eckey); +OPENSSL_EXPORT EC_KEY *d2i_ECPrivateKey_bio(BIO *bp, EC_KEY **eckey); +OPENSSL_EXPORT int i2d_ECPrivateKey_bio(BIO *bp, EC_KEY *eckey); +OPENSSL_EXPORT X509_SIG *d2i_PKCS8_bio(BIO *bp,X509_SIG **p8); +OPENSSL_EXPORT int i2d_PKCS8_bio(BIO *bp,X509_SIG *p8); +OPENSSL_EXPORT PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_bio(BIO *bp, + PKCS8_PRIV_KEY_INFO **p8inf); +OPENSSL_EXPORT int i2d_PKCS8_PRIV_KEY_INFO_bio(BIO *bp,PKCS8_PRIV_KEY_INFO *p8inf); +OPENSSL_EXPORT int i2d_PKCS8PrivateKeyInfo_bio(BIO *bp, EVP_PKEY *key); +OPENSSL_EXPORT int i2d_PrivateKey_bio(BIO *bp, EVP_PKEY *pkey); +OPENSSL_EXPORT EVP_PKEY *d2i_PrivateKey_bio(BIO *bp, EVP_PKEY **a); +OPENSSL_EXPORT int i2d_PUBKEY_bio(BIO *bp, EVP_PKEY *pkey); +OPENSSL_EXPORT EVP_PKEY *d2i_PUBKEY_bio(BIO *bp, EVP_PKEY **a); + +OPENSSL_EXPORT X509 *X509_dup(X509 *x509); +OPENSSL_EXPORT X509_ATTRIBUTE *X509_ATTRIBUTE_dup(X509_ATTRIBUTE *xa); +OPENSSL_EXPORT X509_EXTENSION *X509_EXTENSION_dup(X509_EXTENSION *ex); +OPENSSL_EXPORT X509_CRL *X509_CRL_dup(X509_CRL *crl); +OPENSSL_EXPORT X509_REVOKED *X509_REVOKED_dup(X509_REVOKED *rev); +OPENSSL_EXPORT X509_REQ *X509_REQ_dup(X509_REQ *req); +OPENSSL_EXPORT X509_ALGOR *X509_ALGOR_dup(X509_ALGOR *xn); +OPENSSL_EXPORT int X509_ALGOR_set0(X509_ALGOR *alg, const ASN1_OBJECT *aobj, int ptype, void *pval); +OPENSSL_EXPORT void X509_ALGOR_get0(ASN1_OBJECT **paobj, int *pptype, void **ppval, + X509_ALGOR *algor); +OPENSSL_EXPORT void X509_ALGOR_set_md(X509_ALGOR *alg, const EVP_MD *md); +OPENSSL_EXPORT int X509_ALGOR_cmp(const X509_ALGOR *a, const X509_ALGOR *b); + +OPENSSL_EXPORT X509_NAME *X509_NAME_dup(X509_NAME *xn); +OPENSSL_EXPORT X509_NAME_ENTRY *X509_NAME_ENTRY_dup(X509_NAME_ENTRY *ne); + +OPENSSL_EXPORT int X509_cmp_time(const ASN1_TIME *s, time_t *t); +OPENSSL_EXPORT int X509_cmp_current_time(const ASN1_TIME *s); +OPENSSL_EXPORT ASN1_TIME * X509_time_adj(ASN1_TIME *s, long adj, time_t *t); +OPENSSL_EXPORT ASN1_TIME * X509_time_adj_ex(ASN1_TIME *s, int offset_day, long offset_sec, time_t *t); +OPENSSL_EXPORT ASN1_TIME * X509_gmtime_adj(ASN1_TIME *s, long adj); + +OPENSSL_EXPORT const char * X509_get_default_cert_area(void ); +OPENSSL_EXPORT const char * X509_get_default_cert_dir(void ); +OPENSSL_EXPORT const char * X509_get_default_cert_file(void ); +OPENSSL_EXPORT const char * X509_get_default_cert_dir_env(void ); +OPENSSL_EXPORT const char * X509_get_default_cert_file_env(void ); +OPENSSL_EXPORT const char * X509_get_default_private_dir(void ); + +OPENSSL_EXPORT X509_REQ * X509_to_X509_REQ(X509 *x, EVP_PKEY *pkey, const EVP_MD *md); +OPENSSL_EXPORT X509 * X509_REQ_to_X509(X509_REQ *r, int days,EVP_PKEY *pkey); + +DECLARE_ASN1_ENCODE_FUNCTIONS(X509_ALGORS, X509_ALGORS, X509_ALGORS) +DECLARE_ASN1_FUNCTIONS(X509_VAL) + +DECLARE_ASN1_FUNCTIONS(X509_PUBKEY) + +OPENSSL_EXPORT int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey); +OPENSSL_EXPORT EVP_PKEY * X509_PUBKEY_get(X509_PUBKEY *key); +OPENSSL_EXPORT int i2d_PUBKEY(const EVP_PKEY *a,unsigned char **pp); +OPENSSL_EXPORT EVP_PKEY * d2i_PUBKEY(EVP_PKEY **a,const unsigned char **pp, + long length); +OPENSSL_EXPORT int i2d_RSA_PUBKEY(const RSA *a,unsigned char **pp); +OPENSSL_EXPORT RSA * d2i_RSA_PUBKEY(RSA **a,const unsigned char **pp, + long length); +#ifndef OPENSSL_NO_DSA +OPENSSL_EXPORT int i2d_DSA_PUBKEY(const DSA *a,unsigned char **pp); +OPENSSL_EXPORT DSA * d2i_DSA_PUBKEY(DSA **a,const unsigned char **pp, + long length); +#endif +OPENSSL_EXPORT int i2d_EC_PUBKEY(const EC_KEY *a, unsigned char **pp); +OPENSSL_EXPORT EC_KEY *d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp, + long length); + +DECLARE_ASN1_FUNCTIONS(X509_SIG) +DECLARE_ASN1_FUNCTIONS(X509_REQ_INFO) +DECLARE_ASN1_FUNCTIONS(X509_REQ) + +DECLARE_ASN1_FUNCTIONS(X509_ATTRIBUTE) +OPENSSL_EXPORT X509_ATTRIBUTE *X509_ATTRIBUTE_create(int nid, int atrtype, void *value); + +DECLARE_ASN1_FUNCTIONS(X509_EXTENSION) +DECLARE_ASN1_ENCODE_FUNCTIONS(X509_EXTENSIONS, X509_EXTENSIONS, X509_EXTENSIONS) + +DECLARE_ASN1_FUNCTIONS(X509_NAME_ENTRY) + +DECLARE_ASN1_FUNCTIONS(X509_NAME) + +OPENSSL_EXPORT int X509_NAME_set(X509_NAME **xn, X509_NAME *name); + +DECLARE_ASN1_FUNCTIONS(X509_CINF) + +DECLARE_ASN1_FUNCTIONS(X509) +DECLARE_ASN1_FUNCTIONS(X509_CERT_AUX) + +DECLARE_ASN1_FUNCTIONS(X509_CERT_PAIR) + +/* X509_up_ref adds one to the reference count of |x| and returns + * |x|. */ +OPENSSL_EXPORT X509 *X509_up_ref(X509 *x); + +OPENSSL_EXPORT int X509_get_ex_new_index(long argl, void *argp, CRYPTO_EX_unused *unused, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func); +OPENSSL_EXPORT int X509_set_ex_data(X509 *r, int idx, void *arg); +OPENSSL_EXPORT void *X509_get_ex_data(X509 *r, int idx); +OPENSSL_EXPORT int i2d_X509_AUX(X509 *a,unsigned char **pp); +OPENSSL_EXPORT X509 * d2i_X509_AUX(X509 **a,const unsigned char **pp,long length); + +OPENSSL_EXPORT void X509_get0_signature(ASN1_BIT_STRING **psig, X509_ALGOR **palg, + const X509 *x); +OPENSSL_EXPORT int X509_get_signature_nid(const X509 *x); + +OPENSSL_EXPORT int X509_alias_set1(X509 *x, unsigned char *name, int len); +OPENSSL_EXPORT int X509_keyid_set1(X509 *x, unsigned char *id, int len); +OPENSSL_EXPORT unsigned char * X509_alias_get0(X509 *x, int *len); +OPENSSL_EXPORT unsigned char * X509_keyid_get0(X509 *x, int *len); +OPENSSL_EXPORT int (*X509_TRUST_set_default(int (*trust)(int , X509 *, int)))(int, X509 *, int); +OPENSSL_EXPORT int X509_TRUST_set(int *t, int trust); +OPENSSL_EXPORT int X509_add1_trust_object(X509 *x, ASN1_OBJECT *obj); +OPENSSL_EXPORT int X509_add1_reject_object(X509 *x, ASN1_OBJECT *obj); +OPENSSL_EXPORT void X509_trust_clear(X509 *x); +OPENSSL_EXPORT void X509_reject_clear(X509 *x); + +DECLARE_ASN1_FUNCTIONS(X509_REVOKED) +DECLARE_ASN1_FUNCTIONS(X509_CRL_INFO) +DECLARE_ASN1_FUNCTIONS(X509_CRL) + +OPENSSL_EXPORT int X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev); +OPENSSL_EXPORT int X509_CRL_get0_by_serial(X509_CRL *crl, + X509_REVOKED **ret, ASN1_INTEGER *serial); +OPENSSL_EXPORT int X509_CRL_get0_by_cert(X509_CRL *crl, X509_REVOKED **ret, X509 *x); + +OPENSSL_EXPORT X509_PKEY * X509_PKEY_new(void ); +OPENSSL_EXPORT void X509_PKEY_free(X509_PKEY *a); + +DECLARE_ASN1_FUNCTIONS(NETSCAPE_SPKI) +DECLARE_ASN1_FUNCTIONS(NETSCAPE_SPKAC) +DECLARE_ASN1_FUNCTIONS(NETSCAPE_CERT_SEQUENCE) + +#ifndef OPENSSL_NO_EVP +OPENSSL_EXPORT X509_INFO * X509_INFO_new(void); +OPENSSL_EXPORT void X509_INFO_free(X509_INFO *a); +OPENSSL_EXPORT char * X509_NAME_oneline(X509_NAME *a,char *buf,int size); + +OPENSSL_EXPORT int ASN1_digest(i2d_of_void *i2d,const EVP_MD *type,char *data, + unsigned char *md,unsigned int *len); + +OPENSSL_EXPORT int ASN1_item_digest(const ASN1_ITEM *it,const EVP_MD *type,void *data, + unsigned char *md,unsigned int *len); + +OPENSSL_EXPORT int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *algor1, + ASN1_BIT_STRING *signature,void *data,EVP_PKEY *pkey); + +OPENSSL_EXPORT int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1, X509_ALGOR *algor2, + ASN1_BIT_STRING *signature, + void *data, EVP_PKEY *pkey, const EVP_MD *type); +OPENSSL_EXPORT int ASN1_item_sign_ctx(const ASN1_ITEM *it, + X509_ALGOR *algor1, X509_ALGOR *algor2, + ASN1_BIT_STRING *signature, void *asn, EVP_MD_CTX *ctx); +#endif + +OPENSSL_EXPORT int X509_set_version(X509 *x,long version); +OPENSSL_EXPORT int X509_set_serialNumber(X509 *x, ASN1_INTEGER *serial); +OPENSSL_EXPORT ASN1_INTEGER * X509_get_serialNumber(X509 *x); +OPENSSL_EXPORT int X509_set_issuer_name(X509 *x, X509_NAME *name); +OPENSSL_EXPORT X509_NAME * X509_get_issuer_name(X509 *a); +OPENSSL_EXPORT int X509_set_subject_name(X509 *x, X509_NAME *name); +OPENSSL_EXPORT X509_NAME * X509_get_subject_name(X509 *a); +OPENSSL_EXPORT int X509_set_notBefore(X509 *x, const ASN1_TIME *tm); +OPENSSL_EXPORT int X509_set_notAfter(X509 *x, const ASN1_TIME *tm); +OPENSSL_EXPORT int X509_set_pubkey(X509 *x, EVP_PKEY *pkey); +OPENSSL_EXPORT EVP_PKEY * X509_get_pubkey(X509 *x); +OPENSSL_EXPORT ASN1_BIT_STRING * X509_get0_pubkey_bitstr(const X509 *x); +OPENSSL_EXPORT int X509_certificate_type(X509 *x,EVP_PKEY *pubkey /* optional */); + +OPENSSL_EXPORT int X509_REQ_set_version(X509_REQ *x,long version); +OPENSSL_EXPORT int X509_REQ_set_subject_name(X509_REQ *req,X509_NAME *name); +OPENSSL_EXPORT int X509_REQ_set_pubkey(X509_REQ *x, EVP_PKEY *pkey); +OPENSSL_EXPORT EVP_PKEY * X509_REQ_get_pubkey(X509_REQ *req); +OPENSSL_EXPORT int X509_REQ_extension_nid(int nid); +OPENSSL_EXPORT const int * X509_REQ_get_extension_nids(void); +OPENSSL_EXPORT void X509_REQ_set_extension_nids(const int *nids); +OPENSSL_EXPORT STACK_OF(X509_EXTENSION) *X509_REQ_get_extensions(X509_REQ *req); +OPENSSL_EXPORT int X509_REQ_add_extensions_nid(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts, + int nid); +OPENSSL_EXPORT int X509_REQ_add_extensions(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts); +OPENSSL_EXPORT int X509_REQ_get_attr_count(const X509_REQ *req); +OPENSSL_EXPORT int X509_REQ_get_attr_by_NID(const X509_REQ *req, int nid, + int lastpos); +OPENSSL_EXPORT int X509_REQ_get_attr_by_OBJ(const X509_REQ *req, ASN1_OBJECT *obj, + int lastpos); +OPENSSL_EXPORT X509_ATTRIBUTE *X509_REQ_get_attr(const X509_REQ *req, int loc); +OPENSSL_EXPORT X509_ATTRIBUTE *X509_REQ_delete_attr(X509_REQ *req, int loc); +OPENSSL_EXPORT int X509_REQ_add1_attr(X509_REQ *req, X509_ATTRIBUTE *attr); +OPENSSL_EXPORT int X509_REQ_add1_attr_by_OBJ(X509_REQ *req, + const ASN1_OBJECT *obj, int type, + const unsigned char *bytes, int len); +OPENSSL_EXPORT int X509_REQ_add1_attr_by_NID(X509_REQ *req, + int nid, int type, + const unsigned char *bytes, int len); +OPENSSL_EXPORT int X509_REQ_add1_attr_by_txt(X509_REQ *req, + const char *attrname, int type, + const unsigned char *bytes, int len); + +OPENSSL_EXPORT int X509_CRL_set_version(X509_CRL *x, long version); +OPENSSL_EXPORT int X509_CRL_set_issuer_name(X509_CRL *x, X509_NAME *name); +OPENSSL_EXPORT int X509_CRL_set_lastUpdate(X509_CRL *x, const ASN1_TIME *tm); +OPENSSL_EXPORT int X509_CRL_set_nextUpdate(X509_CRL *x, const ASN1_TIME *tm); +OPENSSL_EXPORT int X509_CRL_sort(X509_CRL *crl); +OPENSSL_EXPORT void X509_CRL_up_ref(X509_CRL *crl); + +OPENSSL_EXPORT int X509_REVOKED_set_serialNumber(X509_REVOKED *x, ASN1_INTEGER *serial); +OPENSSL_EXPORT int X509_REVOKED_set_revocationDate(X509_REVOKED *r, ASN1_TIME *tm); + +OPENSSL_EXPORT X509_CRL *X509_CRL_diff(X509_CRL *base, X509_CRL *newer, + EVP_PKEY *skey, const EVP_MD *md, unsigned int flags); + +OPENSSL_EXPORT int X509_REQ_check_private_key(X509_REQ *x509,EVP_PKEY *pkey); + +OPENSSL_EXPORT int X509_check_private_key(X509 *x509,EVP_PKEY *pkey); +OPENSSL_EXPORT int X509_chain_check_suiteb(int *perror_depth, + X509 *x, STACK_OF(X509) *chain, + unsigned long flags); +OPENSSL_EXPORT int X509_CRL_check_suiteb(X509_CRL *crl, EVP_PKEY *pk, + unsigned long flags); +OPENSSL_EXPORT STACK_OF(X509) *X509_chain_up_ref(STACK_OF(X509) *chain); + +OPENSSL_EXPORT int X509_issuer_and_serial_cmp(const X509 *a, const X509 *b); +OPENSSL_EXPORT unsigned long X509_issuer_and_serial_hash(X509 *a); + +OPENSSL_EXPORT int X509_issuer_name_cmp(const X509 *a, const X509 *b); +OPENSSL_EXPORT unsigned long X509_issuer_name_hash(X509 *a); + +OPENSSL_EXPORT int X509_subject_name_cmp(const X509 *a, const X509 *b); +OPENSSL_EXPORT unsigned long X509_subject_name_hash(X509 *x); + +OPENSSL_EXPORT unsigned long X509_issuer_name_hash_old(X509 *a); +OPENSSL_EXPORT unsigned long X509_subject_name_hash_old(X509 *x); + +OPENSSL_EXPORT int X509_cmp(const X509 *a, const X509 *b); +OPENSSL_EXPORT int X509_NAME_cmp(const X509_NAME *a, const X509_NAME *b); +OPENSSL_EXPORT unsigned long X509_NAME_hash(X509_NAME *x); +OPENSSL_EXPORT unsigned long X509_NAME_hash_old(X509_NAME *x); + +OPENSSL_EXPORT int X509_CRL_cmp(const X509_CRL *a, const X509_CRL *b); +OPENSSL_EXPORT int X509_CRL_match(const X509_CRL *a, const X509_CRL *b); +#ifndef OPENSSL_NO_FP_API +OPENSSL_EXPORT int X509_print_ex_fp(FILE *bp,X509 *x, unsigned long nmflag, unsigned long cflag); +OPENSSL_EXPORT int X509_print_fp(FILE *bp,X509 *x); +OPENSSL_EXPORT int X509_CRL_print_fp(FILE *bp,X509_CRL *x); +OPENSSL_EXPORT int X509_REQ_print_fp(FILE *bp,X509_REQ *req); +OPENSSL_EXPORT int X509_NAME_print_ex_fp(FILE *fp, X509_NAME *nm, int indent, unsigned long flags); +#endif + +OPENSSL_EXPORT int X509_NAME_print(BIO *bp, X509_NAME *name, int obase); +OPENSSL_EXPORT int X509_NAME_print_ex(BIO *out, X509_NAME *nm, int indent, unsigned long flags); +OPENSSL_EXPORT int X509_print_ex(BIO *bp,X509 *x, unsigned long nmflag, unsigned long cflag); +OPENSSL_EXPORT int X509_print(BIO *bp,X509 *x); +OPENSSL_EXPORT int X509_ocspid_print(BIO *bp,X509 *x); +OPENSSL_EXPORT int X509_CERT_AUX_print(BIO *bp,X509_CERT_AUX *x, int indent); +OPENSSL_EXPORT int X509_CRL_print(BIO *bp,X509_CRL *x); +OPENSSL_EXPORT int X509_REQ_print_ex(BIO *bp, X509_REQ *x, unsigned long nmflag, unsigned long cflag); +OPENSSL_EXPORT int X509_REQ_print(BIO *bp,X509_REQ *req); + +OPENSSL_EXPORT int X509_NAME_entry_count(X509_NAME *name); +OPENSSL_EXPORT int X509_NAME_get_text_by_NID(X509_NAME *name, int nid, + char *buf,int len); +OPENSSL_EXPORT int X509_NAME_get_text_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj, + char *buf,int len); + +/* NOTE: you should be passsing -1, not 0 as lastpos. The functions that use + * lastpos, search after that position on. */ +OPENSSL_EXPORT int X509_NAME_get_index_by_NID(X509_NAME *name,int nid,int lastpos); +OPENSSL_EXPORT int X509_NAME_get_index_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj, + int lastpos); +OPENSSL_EXPORT X509_NAME_ENTRY *X509_NAME_get_entry(X509_NAME *name, int loc); +OPENSSL_EXPORT X509_NAME_ENTRY *X509_NAME_delete_entry(X509_NAME *name, int loc); +OPENSSL_EXPORT int X509_NAME_add_entry(X509_NAME *name,X509_NAME_ENTRY *ne, + int loc, int set); +OPENSSL_EXPORT int X509_NAME_add_entry_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj, int type, + unsigned char *bytes, int len, int loc, int set); +OPENSSL_EXPORT int X509_NAME_add_entry_by_NID(X509_NAME *name, int nid, int type, + unsigned char *bytes, int len, int loc, int set); +OPENSSL_EXPORT X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_txt(X509_NAME_ENTRY **ne, + const char *field, int type, const unsigned char *bytes, int len); +OPENSSL_EXPORT X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_NID(X509_NAME_ENTRY **ne, int nid, + int type,unsigned char *bytes, int len); +OPENSSL_EXPORT int X509_NAME_add_entry_by_txt(X509_NAME *name, const char *field, int type, + const unsigned char *bytes, int len, int loc, int set); +OPENSSL_EXPORT X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_OBJ(X509_NAME_ENTRY **ne, + const ASN1_OBJECT *obj, int type,const unsigned char *bytes, + int len); +OPENSSL_EXPORT int X509_NAME_ENTRY_set_object(X509_NAME_ENTRY *ne, + const ASN1_OBJECT *obj); +OPENSSL_EXPORT int X509_NAME_ENTRY_set_data(X509_NAME_ENTRY *ne, int type, + const unsigned char *bytes, int len); +OPENSSL_EXPORT ASN1_OBJECT * X509_NAME_ENTRY_get_object(X509_NAME_ENTRY *ne); +OPENSSL_EXPORT ASN1_STRING * X509_NAME_ENTRY_get_data(X509_NAME_ENTRY *ne); + +OPENSSL_EXPORT int X509v3_get_ext_count(const STACK_OF(X509_EXTENSION) *x); +OPENSSL_EXPORT int X509v3_get_ext_by_NID(const STACK_OF(X509_EXTENSION) *x, + int nid, int lastpos); +OPENSSL_EXPORT int X509v3_get_ext_by_OBJ(const STACK_OF(X509_EXTENSION) *x, + const ASN1_OBJECT *obj,int lastpos); +OPENSSL_EXPORT int X509v3_get_ext_by_critical(const STACK_OF(X509_EXTENSION) *x, + int crit, int lastpos); +OPENSSL_EXPORT X509_EXTENSION *X509v3_get_ext(const STACK_OF(X509_EXTENSION) *x, int loc); +OPENSSL_EXPORT X509_EXTENSION *X509v3_delete_ext(STACK_OF(X509_EXTENSION) *x, int loc); +OPENSSL_EXPORT STACK_OF(X509_EXTENSION) *X509v3_add_ext(STACK_OF(X509_EXTENSION) **x, + X509_EXTENSION *ex, int loc); + +OPENSSL_EXPORT int X509_get_ext_count(X509 *x); +OPENSSL_EXPORT int X509_get_ext_by_NID(X509 *x, int nid, int lastpos); +OPENSSL_EXPORT int X509_get_ext_by_OBJ(X509 *x,ASN1_OBJECT *obj,int lastpos); +OPENSSL_EXPORT int X509_get_ext_by_critical(X509 *x, int crit, int lastpos); +OPENSSL_EXPORT X509_EXTENSION *X509_get_ext(X509 *x, int loc); +OPENSSL_EXPORT X509_EXTENSION *X509_delete_ext(X509 *x, int loc); +OPENSSL_EXPORT int X509_add_ext(X509 *x, X509_EXTENSION *ex, int loc); +OPENSSL_EXPORT void * X509_get_ext_d2i(X509 *x, int nid, int *crit, int *idx); +OPENSSL_EXPORT int X509_add1_ext_i2d(X509 *x, int nid, void *value, int crit, + unsigned long flags); + +OPENSSL_EXPORT int X509_CRL_get_ext_count(X509_CRL *x); +OPENSSL_EXPORT int X509_CRL_get_ext_by_NID(X509_CRL *x, int nid, int lastpos); +OPENSSL_EXPORT int X509_CRL_get_ext_by_OBJ(X509_CRL *x,ASN1_OBJECT *obj,int lastpos); +OPENSSL_EXPORT int X509_CRL_get_ext_by_critical(X509_CRL *x, int crit, int lastpos); +OPENSSL_EXPORT X509_EXTENSION *X509_CRL_get_ext(X509_CRL *x, int loc); +OPENSSL_EXPORT X509_EXTENSION *X509_CRL_delete_ext(X509_CRL *x, int loc); +OPENSSL_EXPORT int X509_CRL_add_ext(X509_CRL *x, X509_EXTENSION *ex, int loc); +OPENSSL_EXPORT void * X509_CRL_get_ext_d2i(X509_CRL *x, int nid, int *crit, int *idx); +OPENSSL_EXPORT int X509_CRL_add1_ext_i2d(X509_CRL *x, int nid, void *value, int crit, + unsigned long flags); + +OPENSSL_EXPORT int X509_REVOKED_get_ext_count(X509_REVOKED *x); +OPENSSL_EXPORT int X509_REVOKED_get_ext_by_NID(X509_REVOKED *x, int nid, int lastpos); +OPENSSL_EXPORT int X509_REVOKED_get_ext_by_OBJ(X509_REVOKED *x,ASN1_OBJECT *obj,int lastpos); +OPENSSL_EXPORT int X509_REVOKED_get_ext_by_critical(X509_REVOKED *x, int crit, int lastpos); +OPENSSL_EXPORT X509_EXTENSION *X509_REVOKED_get_ext(X509_REVOKED *x, int loc); +OPENSSL_EXPORT X509_EXTENSION *X509_REVOKED_delete_ext(X509_REVOKED *x, int loc); +OPENSSL_EXPORT int X509_REVOKED_add_ext(X509_REVOKED *x, X509_EXTENSION *ex, int loc); +OPENSSL_EXPORT void * X509_REVOKED_get_ext_d2i(X509_REVOKED *x, int nid, int *crit, int *idx); +OPENSSL_EXPORT int X509_REVOKED_add1_ext_i2d(X509_REVOKED *x, int nid, void *value, int crit, + unsigned long flags); + +OPENSSL_EXPORT X509_EXTENSION *X509_EXTENSION_create_by_NID(X509_EXTENSION **ex, + int nid, int crit, ASN1_OCTET_STRING *data); +OPENSSL_EXPORT X509_EXTENSION *X509_EXTENSION_create_by_OBJ(X509_EXTENSION **ex, + const ASN1_OBJECT *obj,int crit,ASN1_OCTET_STRING *data); +OPENSSL_EXPORT int X509_EXTENSION_set_object(X509_EXTENSION *ex,const ASN1_OBJECT *obj); +OPENSSL_EXPORT int X509_EXTENSION_set_critical(X509_EXTENSION *ex, int crit); +OPENSSL_EXPORT int X509_EXTENSION_set_data(X509_EXTENSION *ex, + ASN1_OCTET_STRING *data); +OPENSSL_EXPORT ASN1_OBJECT * X509_EXTENSION_get_object(X509_EXTENSION *ex); +OPENSSL_EXPORT ASN1_OCTET_STRING *X509_EXTENSION_get_data(X509_EXTENSION *ne); +OPENSSL_EXPORT int X509_EXTENSION_get_critical(X509_EXTENSION *ex); + +OPENSSL_EXPORT int X509at_get_attr_count(const STACK_OF(X509_ATTRIBUTE) *x); +OPENSSL_EXPORT int X509at_get_attr_by_NID(const STACK_OF(X509_ATTRIBUTE) *x, int nid, + int lastpos); +OPENSSL_EXPORT int X509at_get_attr_by_OBJ(const STACK_OF(X509_ATTRIBUTE) *sk, const ASN1_OBJECT *obj, + int lastpos); +OPENSSL_EXPORT X509_ATTRIBUTE *X509at_get_attr(const STACK_OF(X509_ATTRIBUTE) *x, int loc); +OPENSSL_EXPORT X509_ATTRIBUTE *X509at_delete_attr(STACK_OF(X509_ATTRIBUTE) *x, int loc); +OPENSSL_EXPORT STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr(STACK_OF(X509_ATTRIBUTE) **x, + X509_ATTRIBUTE *attr); +OPENSSL_EXPORT STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_OBJ(STACK_OF(X509_ATTRIBUTE) **x, + const ASN1_OBJECT *obj, int type, + const unsigned char *bytes, int len); +OPENSSL_EXPORT STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_NID(STACK_OF(X509_ATTRIBUTE) **x, + int nid, int type, + const unsigned char *bytes, int len); +OPENSSL_EXPORT STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_txt(STACK_OF(X509_ATTRIBUTE) **x, + const char *attrname, int type, + const unsigned char *bytes, int len); +OPENSSL_EXPORT void *X509at_get0_data_by_OBJ(STACK_OF(X509_ATTRIBUTE) *x, + ASN1_OBJECT *obj, int lastpos, int type); +OPENSSL_EXPORT X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_NID(X509_ATTRIBUTE **attr, int nid, + int atrtype, const void *data, int len); +OPENSSL_EXPORT X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_OBJ(X509_ATTRIBUTE **attr, + const ASN1_OBJECT *obj, int atrtype, const void *data, int len); +OPENSSL_EXPORT X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_txt(X509_ATTRIBUTE **attr, + const char *atrname, int type, const unsigned char *bytes, int len); +OPENSSL_EXPORT int X509_ATTRIBUTE_set1_object(X509_ATTRIBUTE *attr, const ASN1_OBJECT *obj); +OPENSSL_EXPORT int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype, const void *data, int len); +OPENSSL_EXPORT void *X509_ATTRIBUTE_get0_data(X509_ATTRIBUTE *attr, int idx, + int atrtype, void *data); +OPENSSL_EXPORT int X509_ATTRIBUTE_count(X509_ATTRIBUTE *attr); +OPENSSL_EXPORT ASN1_OBJECT *X509_ATTRIBUTE_get0_object(X509_ATTRIBUTE *attr); +OPENSSL_EXPORT ASN1_TYPE *X509_ATTRIBUTE_get0_type(X509_ATTRIBUTE *attr, int idx); + +OPENSSL_EXPORT int EVP_PKEY_get_attr_count(const EVP_PKEY *key); +OPENSSL_EXPORT int EVP_PKEY_get_attr_by_NID(const EVP_PKEY *key, int nid, + int lastpos); +OPENSSL_EXPORT int EVP_PKEY_get_attr_by_OBJ(const EVP_PKEY *key, ASN1_OBJECT *obj, + int lastpos); +OPENSSL_EXPORT X509_ATTRIBUTE *EVP_PKEY_get_attr(const EVP_PKEY *key, int loc); +OPENSSL_EXPORT X509_ATTRIBUTE *EVP_PKEY_delete_attr(EVP_PKEY *key, int loc); +OPENSSL_EXPORT int EVP_PKEY_add1_attr(EVP_PKEY *key, X509_ATTRIBUTE *attr); +OPENSSL_EXPORT int EVP_PKEY_add1_attr_by_OBJ(EVP_PKEY *key, + const ASN1_OBJECT *obj, int type, + const unsigned char *bytes, int len); +OPENSSL_EXPORT int EVP_PKEY_add1_attr_by_NID(EVP_PKEY *key, + int nid, int type, + const unsigned char *bytes, int len); +OPENSSL_EXPORT int EVP_PKEY_add1_attr_by_txt(EVP_PKEY *key, + const char *attrname, int type, + const unsigned char *bytes, int len); + +OPENSSL_EXPORT int X509_verify_cert(X509_STORE_CTX *ctx); + +/* lookup a cert from a X509 STACK */ +OPENSSL_EXPORT X509 *X509_find_by_issuer_and_serial(STACK_OF(X509) *sk,X509_NAME *name, + ASN1_INTEGER *serial); +OPENSSL_EXPORT X509 *X509_find_by_subject(STACK_OF(X509) *sk,X509_NAME *name); + +DECLARE_ASN1_FUNCTIONS(PBEPARAM) +DECLARE_ASN1_FUNCTIONS(PBE2PARAM) +DECLARE_ASN1_FUNCTIONS(PBKDF2PARAM) + +OPENSSL_EXPORT int PKCS5_pbe_set0_algor(X509_ALGOR *algor, int alg, int iter, + const unsigned char *salt, int saltlen); + +OPENSSL_EXPORT X509_ALGOR *PKCS5_pbe_set(int alg, int iter, + const unsigned char *salt, int saltlen); +OPENSSL_EXPORT X509_ALGOR *PKCS5_pbe2_set(const EVP_CIPHER *cipher, int iter, + unsigned char *salt, int saltlen); +OPENSSL_EXPORT X509_ALGOR *PKCS5_pbe2_set_iv(const EVP_CIPHER *cipher, int iter, + unsigned char *salt, int saltlen, + unsigned char *aiv, int prf_nid); + +OPENSSL_EXPORT X509_ALGOR *PKCS5_pbkdf2_set(int iter, unsigned char *salt, int saltlen, + int prf_nid, int keylen); + +/* PKCS#8 utilities */ + +DECLARE_ASN1_FUNCTIONS(PKCS8_PRIV_KEY_INFO) + +OPENSSL_EXPORT EVP_PKEY *EVP_PKCS82PKEY(PKCS8_PRIV_KEY_INFO *p8); +OPENSSL_EXPORT PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(EVP_PKEY *pkey); +OPENSSL_EXPORT PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8_broken(EVP_PKEY *pkey, int broken); +OPENSSL_EXPORT PKCS8_PRIV_KEY_INFO *PKCS8_set_broken(PKCS8_PRIV_KEY_INFO *p8, int broken); + +OPENSSL_EXPORT int PKCS8_pkey_set0(PKCS8_PRIV_KEY_INFO *priv, ASN1_OBJECT *aobj, + int version, int ptype, void *pval, + unsigned char *penc, int penclen); +OPENSSL_EXPORT int PKCS8_pkey_get0(ASN1_OBJECT **ppkalg, + const unsigned char **pk, int *ppklen, + X509_ALGOR **pa, + PKCS8_PRIV_KEY_INFO *p8); + +OPENSSL_EXPORT int X509_PUBKEY_set0_param(X509_PUBKEY *pub, const ASN1_OBJECT *aobj, + int ptype, void *pval, + unsigned char *penc, int penclen); +OPENSSL_EXPORT int X509_PUBKEY_get0_param(ASN1_OBJECT **ppkalg, + const unsigned char **pk, int *ppklen, + X509_ALGOR **pa, + X509_PUBKEY *pub); + +OPENSSL_EXPORT int X509_check_trust(X509 *x, int id, int flags); +OPENSSL_EXPORT int X509_TRUST_get_count(void); +OPENSSL_EXPORT X509_TRUST * X509_TRUST_get0(int idx); +OPENSSL_EXPORT int X509_TRUST_get_by_id(int id); +OPENSSL_EXPORT int X509_TRUST_add(int id, int flags, int (*ck)(X509_TRUST *, X509 *, int), + char *name, int arg1, void *arg2); +OPENSSL_EXPORT void X509_TRUST_cleanup(void); +OPENSSL_EXPORT int X509_TRUST_get_flags(X509_TRUST *xp); +OPENSSL_EXPORT char *X509_TRUST_get0_name(X509_TRUST *xp); +OPENSSL_EXPORT int X509_TRUST_get_trust(X509_TRUST *xp); + + +typedef struct rsa_pss_params_st { + X509_ALGOR *hashAlgorithm; + X509_ALGOR *maskGenAlgorithm; + ASN1_INTEGER *saltLength; + ASN1_INTEGER *trailerField; +} RSA_PSS_PARAMS; + +DECLARE_ASN1_FUNCTIONS(RSA_PSS_PARAMS) + + +/* PKCS7_get_certificates parses a PKCS#7, SignedData structure from |cbs| and + * appends the included certificates to |out_certs|. It returns one on success + * and zero on error. */ +OPENSSL_EXPORT int PKCS7_get_certificates(STACK_OF(X509) *out_certs, CBS *cbs); + +/* PKCS7_bundle_certificates appends a PKCS#7, SignedData structure containing + * |certs| to |out|. It returns one on success and zero on error. */ +OPENSSL_EXPORT int PKCS7_bundle_certificates( + CBB *out, const STACK_OF(X509) *certs); + +/* PKCS7_get_CRLs parses a PKCS#7, SignedData structure from |cbs| and appends + * the included CRLs to |out_crls|. It returns one on success and zero on + * error. */ +OPENSSL_EXPORT int PKCS7_get_CRLs(STACK_OF(X509_CRL) *out_crls, CBS *cbs); + +/* PKCS7_bundle_CRLs appends a PKCS#7, SignedData structure containing + * |crls| to |out|. It returns one on success and zero on error. */ +OPENSSL_EXPORT int PKCS7_bundle_CRLs(CBB *out, const STACK_OF(X509_CRL) *crls); + +/* PKCS7_get_PEM_certificates reads a PEM-encoded, PKCS#7, SignedData structure + * from |pem_bio| and appends the included certificates to |out_certs|. It + * returns one on success and zero on error. */ +OPENSSL_EXPORT int PKCS7_get_PEM_certificates(STACK_OF(X509) *out_certs, + BIO *pem_bio); + +/* PKCS7_get_PEM_CRLs reads a PEM-encoded, PKCS#7, SignedData structure from + * |pem_bio| and appends the included CRLs to |out_crls|. It returns one on + * success and zero on error. */ +OPENSSL_EXPORT int PKCS7_get_PEM_CRLs(STACK_OF(X509_CRL) *out_crls, + BIO *pem_bio); + +/* EVP_PK values indicate the algorithm of the public key in a certificate. */ + +#define EVP_PK_RSA 0x0001 +#define EVP_PK_DSA 0x0002 +#define EVP_PK_DH 0x0004 +#define EVP_PK_EC 0x0008 + +/* EVP_PKS values indicate the algorithm used to sign a certificate. */ + +#define EVP_PKS_RSA 0x0100 +#define EVP_PKS_DSA 0x0200 +#define EVP_PKS_EC 0x0400 + +/* EVP_PKT values are flags that define what public-key operations can be + * performed with the public key from a certificate. */ + +/* EVP_PKT_SIGN indicates that the public key can be used for signing. */ +#define EVP_PKT_SIGN 0x0010 +/* EVP_PKT_ENC indicates that a session key can be encrypted to the public + * key. */ +#define EVP_PKT_ENC 0x0020 +/* EVP_PKT_EXCH indicates that key-agreement can be performed. */ +#define EVP_PKT_EXCH 0x0040 +/* EVP_PKT_EXP indicates that key is weak (i.e. "export"). */ +#define EVP_PKT_EXP 0x1000 + + +#ifdef __cplusplus +} +#endif + +#define X509_R_AKID_MISMATCH 100 +#define X509_R_BAD_PKCS7_VERSION 101 +#define X509_R_BAD_X509_FILETYPE 102 +#define X509_R_BASE64_DECODE_ERROR 103 +#define X509_R_CANT_CHECK_DH_KEY 104 +#define X509_R_CERT_ALREADY_IN_HASH_TABLE 105 +#define X509_R_CRL_ALREADY_DELTA 106 +#define X509_R_CRL_VERIFY_FAILURE 107 +#define X509_R_IDP_MISMATCH 108 +#define X509_R_INVALID_BIT_STRING_BITS_LEFT 109 +#define X509_R_INVALID_DIRECTORY 110 +#define X509_R_INVALID_FIELD_NAME 111 +#define X509_R_INVALID_PSS_PARAMETERS 112 +#define X509_R_INVALID_TRUST 113 +#define X509_R_ISSUER_MISMATCH 114 +#define X509_R_KEY_TYPE_MISMATCH 115 +#define X509_R_KEY_VALUES_MISMATCH 116 +#define X509_R_LOADING_CERT_DIR 117 +#define X509_R_LOADING_DEFAULTS 118 +#define X509_R_NEWER_CRL_NOT_NEWER 119 +#define X509_R_NOT_PKCS7_SIGNED_DATA 120 +#define X509_R_NO_CERTIFICATES_INCLUDED 121 +#define X509_R_NO_CERT_SET_FOR_US_TO_VERIFY 122 +#define X509_R_NO_CRLS_INCLUDED 123 +#define X509_R_NO_CRL_NUMBER 124 +#define X509_R_PUBLIC_KEY_DECODE_ERROR 125 +#define X509_R_PUBLIC_KEY_ENCODE_ERROR 126 +#define X509_R_SHOULD_RETRY 127 +#define X509_R_UNKNOWN_KEY_TYPE 128 +#define X509_R_UNKNOWN_NID 129 +#define X509_R_UNKNOWN_PURPOSE_ID 130 +#define X509_R_UNKNOWN_TRUST_ID 131 +#define X509_R_UNSUPPORTED_ALGORITHM 132 +#define X509_R_WRONG_LOOKUP_TYPE 133 +#define X509_R_WRONG_TYPE 134 +#define X509_R_NAME_TOO_LONG 135 + +#endif diff --git a/external/boringssl/include/openssl/x509_vfy.h b/external/boringssl/include/openssl/x509_vfy.h new file mode 100644 index 0000000000..5343dbd757 --- /dev/null +++ b/external/boringssl/include/openssl/x509_vfy.h @@ -0,0 +1,620 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_X509_H +#include +/* openssl/x509.h ends up #include-ing this file at about the only + * appropriate moment. */ +#endif + +#ifndef HEADER_X509_VFY_H +#define HEADER_X509_VFY_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#if 0 +/* Outer object */ +typedef struct x509_hash_dir_st + { + int num_dirs; + char **dirs; + int *dirs_type; + int num_dirs_alloced; + } X509_HASH_DIR_CTX; +#endif + +typedef struct x509_file_st + { + int num_paths; /* number of paths to files or directories */ + int num_alloced; + char **paths; /* the list of paths or directories */ + int *path_type; + } X509_CERT_FILE_CTX; + +/*******************************/ +/* +SSL_CTX -> X509_STORE + -> X509_LOOKUP + ->X509_LOOKUP_METHOD + -> X509_LOOKUP + ->X509_LOOKUP_METHOD + +SSL -> X509_STORE_CTX + ->X509_STORE + +The X509_STORE holds the tables etc for verification stuff. +A X509_STORE_CTX is used while validating a single certificate. +The X509_STORE has X509_LOOKUPs for looking up certs. +The X509_STORE then calls a function to actually verify the +certificate chain. +*/ + +/* The following are legacy constants that should not be used. */ +#define X509_LU_RETRY -1 +#define X509_LU_FAIL 0 + +#define X509_LU_X509 1 +#define X509_LU_CRL 2 +#define X509_LU_PKEY 3 + +typedef struct x509_object_st + { + /* one of the above types */ + int type; + union { + char *ptr; + X509 *x509; + X509_CRL *crl; + EVP_PKEY *pkey; + } data; + } X509_OBJECT; + +typedef struct x509_lookup_st X509_LOOKUP; + +DECLARE_STACK_OF(X509_LOOKUP) +DECLARE_STACK_OF(X509_OBJECT) + +/* This is a static that defines the function interface */ +typedef struct x509_lookup_method_st + { + const char *name; + int (*new_item)(X509_LOOKUP *ctx); + void (*free)(X509_LOOKUP *ctx); + int (*init)(X509_LOOKUP *ctx); + int (*shutdown)(X509_LOOKUP *ctx); + int (*ctrl)(X509_LOOKUP *ctx,int cmd,const char *argc,long argl, + char **ret); + int (*get_by_subject)(X509_LOOKUP *ctx,int type,X509_NAME *name, + X509_OBJECT *ret); + int (*get_by_issuer_serial)(X509_LOOKUP *ctx,int type,X509_NAME *name, + ASN1_INTEGER *serial,X509_OBJECT *ret); + int (*get_by_fingerprint)(X509_LOOKUP *ctx,int type, + unsigned char *bytes,int len, + X509_OBJECT *ret); + int (*get_by_alias)(X509_LOOKUP *ctx,int type,char *str,int len, + X509_OBJECT *ret); + } X509_LOOKUP_METHOD; + +typedef struct X509_VERIFY_PARAM_ID_st X509_VERIFY_PARAM_ID; + +/* This structure hold all parameters associated with a verify operation + * by including an X509_VERIFY_PARAM structure in related structures the + * parameters used can be customized + */ + +typedef struct X509_VERIFY_PARAM_st + { + char *name; + time_t check_time; /* Time to use */ + unsigned long inh_flags; /* Inheritance flags */ + unsigned long flags; /* Various verify flags */ + int purpose; /* purpose to check untrusted certificates */ + int trust; /* trust setting to check */ + int depth; /* Verify depth */ + STACK_OF(ASN1_OBJECT) *policies; /* Permissible policies */ + X509_VERIFY_PARAM_ID *id; /* opaque ID data */ + } X509_VERIFY_PARAM; + +DECLARE_STACK_OF(X509_VERIFY_PARAM) + +/* This is used to hold everything. It is used for all certificate + * validation. Once we have a certificate chain, the 'verify' + * function is then called to actually check the cert chain. */ +struct x509_store_st + { + /* The following is a cache of trusted certs */ + int cache; /* if true, stash any hits */ + STACK_OF(X509_OBJECT) *objs; /* Cache of all objects */ + CRYPTO_MUTEX objs_lock; + + /* These are external lookup methods */ + STACK_OF(X509_LOOKUP) *get_cert_methods; + + X509_VERIFY_PARAM *param; + + /* Callbacks for various operations */ + int (*verify)(X509_STORE_CTX *ctx); /* called to verify a certificate */ + int (*verify_cb)(int ok,X509_STORE_CTX *ctx); /* error callback */ + int (*get_issuer)(X509 **issuer, X509_STORE_CTX *ctx, X509 *x); /* get issuers cert from ctx */ + int (*check_issued)(X509_STORE_CTX *ctx, X509 *x, X509 *issuer); /* check issued */ + int (*check_revocation)(X509_STORE_CTX *ctx); /* Check revocation status of chain */ + int (*get_crl)(X509_STORE_CTX *ctx, X509_CRL **crl, X509 *x); /* retrieve CRL */ + int (*check_crl)(X509_STORE_CTX *ctx, X509_CRL *crl); /* Check CRL validity */ + int (*cert_crl)(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x); /* Check certificate against CRL */ + STACK_OF(X509) * (*lookup_certs)(X509_STORE_CTX *ctx, X509_NAME *nm); + STACK_OF(X509_CRL) * (*lookup_crls)(X509_STORE_CTX *ctx, X509_NAME *nm); + int (*cleanup)(X509_STORE_CTX *ctx); + + CRYPTO_refcount_t references; + } /* X509_STORE */; + +OPENSSL_EXPORT int X509_STORE_set_depth(X509_STORE *store, int depth); + +#define X509_STORE_set_verify_cb_func(ctx,func) ((ctx)->verify_cb=(func)) +#define X509_STORE_set_verify_func(ctx,func) ((ctx)->verify=(func)) + +/* This is the functions plus an instance of the local variables. */ +struct x509_lookup_st + { + int init; /* have we been started */ + int skip; /* don't use us. */ + X509_LOOKUP_METHOD *method; /* the functions */ + char *method_data; /* method data */ + + X509_STORE *store_ctx; /* who owns us */ + } /* X509_LOOKUP */; + +/* This is a used when verifying cert chains. Since the + * gathering of the cert chain can take some time (and have to be + * 'retried', this needs to be kept and passed around. */ +struct x509_store_ctx_st /* X509_STORE_CTX */ + { + X509_STORE *ctx; + + /* The following are set by the caller */ + X509 *cert; /* The cert to check */ + STACK_OF(X509) *untrusted; /* chain of X509s - untrusted - passed in */ + STACK_OF(X509_CRL) *crls; /* set of CRLs passed in */ + + X509_VERIFY_PARAM *param; + void *other_ctx; /* Other info for use with get_issuer() */ + + /* Callbacks for various operations */ + int (*verify)(X509_STORE_CTX *ctx); /* called to verify a certificate */ + int (*verify_cb)(int ok,X509_STORE_CTX *ctx); /* error callback */ + int (*get_issuer)(X509 **issuer, X509_STORE_CTX *ctx, X509 *x); /* get issuers cert from ctx */ + int (*check_issued)(X509_STORE_CTX *ctx, X509 *x, X509 *issuer); /* check issued */ + int (*check_revocation)(X509_STORE_CTX *ctx); /* Check revocation status of chain */ + int (*get_crl)(X509_STORE_CTX *ctx, X509_CRL **crl, X509 *x); /* retrieve CRL */ + int (*check_crl)(X509_STORE_CTX *ctx, X509_CRL *crl); /* Check CRL validity */ + int (*cert_crl)(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x); /* Check certificate against CRL */ + int (*check_policy)(X509_STORE_CTX *ctx); + STACK_OF(X509) * (*lookup_certs)(X509_STORE_CTX *ctx, X509_NAME *nm); + STACK_OF(X509_CRL) * (*lookup_crls)(X509_STORE_CTX *ctx, X509_NAME *nm); + int (*cleanup)(X509_STORE_CTX *ctx); + + /* The following is built up */ + int valid; /* if 0, rebuild chain */ + int last_untrusted; /* index of last untrusted cert */ + STACK_OF(X509) *chain; /* chain of X509s - built up and trusted */ + X509_POLICY_TREE *tree; /* Valid policy tree */ + + int explicit_policy; /* Require explicit policy value */ + + /* When something goes wrong, this is why */ + int error_depth; + int error; + X509 *current_cert; + X509 *current_issuer; /* cert currently being tested as valid issuer */ + X509_CRL *current_crl; /* current CRL */ + + int current_crl_score; /* score of current CRL */ + unsigned int current_reasons; /* Reason mask */ + + X509_STORE_CTX *parent; /* For CRL path validation: parent context */ + + CRYPTO_EX_DATA ex_data; + } /* X509_STORE_CTX */; + +OPENSSL_EXPORT void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth); + +#define X509_STORE_CTX_set_app_data(ctx,data) \ + X509_STORE_CTX_set_ex_data(ctx,0,data) +#define X509_STORE_CTX_get_app_data(ctx) \ + X509_STORE_CTX_get_ex_data(ctx,0) + +#define X509_L_FILE_LOAD 1 +#define X509_L_ADD_DIR 2 + +#define X509_LOOKUP_load_file(x,name,type) \ + X509_LOOKUP_ctrl((x),X509_L_FILE_LOAD,(name),(long)(type),NULL) + +#define X509_LOOKUP_add_dir(x,name,type) \ + X509_LOOKUP_ctrl((x),X509_L_ADD_DIR,(name),(long)(type),NULL) + +#define X509_V_OK 0 +#define X509_V_ERR_UNSPECIFIED 1 + +#define X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT 2 +#define X509_V_ERR_UNABLE_TO_GET_CRL 3 +#define X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE 4 +#define X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE 5 +#define X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY 6 +#define X509_V_ERR_CERT_SIGNATURE_FAILURE 7 +#define X509_V_ERR_CRL_SIGNATURE_FAILURE 8 +#define X509_V_ERR_CERT_NOT_YET_VALID 9 +#define X509_V_ERR_CERT_HAS_EXPIRED 10 +#define X509_V_ERR_CRL_NOT_YET_VALID 11 +#define X509_V_ERR_CRL_HAS_EXPIRED 12 +#define X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD 13 +#define X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD 14 +#define X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD 15 +#define X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD 16 +#define X509_V_ERR_OUT_OF_MEM 17 +#define X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT 18 +#define X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN 19 +#define X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY 20 +#define X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE 21 +#define X509_V_ERR_CERT_CHAIN_TOO_LONG 22 +#define X509_V_ERR_CERT_REVOKED 23 +#define X509_V_ERR_INVALID_CA 24 +#define X509_V_ERR_PATH_LENGTH_EXCEEDED 25 +#define X509_V_ERR_INVALID_PURPOSE 26 +#define X509_V_ERR_CERT_UNTRUSTED 27 +#define X509_V_ERR_CERT_REJECTED 28 +/* These are 'informational' when looking for issuer cert */ +#define X509_V_ERR_SUBJECT_ISSUER_MISMATCH 29 +#define X509_V_ERR_AKID_SKID_MISMATCH 30 +#define X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH 31 +#define X509_V_ERR_KEYUSAGE_NO_CERTSIGN 32 + +#define X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER 33 +#define X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION 34 +#define X509_V_ERR_KEYUSAGE_NO_CRL_SIGN 35 +#define X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION 36 +#define X509_V_ERR_INVALID_NON_CA 37 +#define X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED 38 +#define X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE 39 +#define X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED 40 + +#define X509_V_ERR_INVALID_EXTENSION 41 +#define X509_V_ERR_INVALID_POLICY_EXTENSION 42 +#define X509_V_ERR_NO_EXPLICIT_POLICY 43 +#define X509_V_ERR_DIFFERENT_CRL_SCOPE 44 +#define X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE 45 + +#define X509_V_ERR_UNNESTED_RESOURCE 46 + +#define X509_V_ERR_PERMITTED_VIOLATION 47 +#define X509_V_ERR_EXCLUDED_VIOLATION 48 +#define X509_V_ERR_SUBTREE_MINMAX 49 +#define X509_V_ERR_APPLICATION_VERIFICATION 50 +#define X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE 51 +#define X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX 52 +#define X509_V_ERR_UNSUPPORTED_NAME_SYNTAX 53 +#define X509_V_ERR_CRL_PATH_VALIDATION_ERROR 54 + +/* Suite B mode algorithm violation */ +#define X509_V_ERR_SUITE_B_INVALID_VERSION 56 +#define X509_V_ERR_SUITE_B_INVALID_ALGORITHM 57 +#define X509_V_ERR_SUITE_B_INVALID_CURVE 58 +#define X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM 59 +#define X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED 60 +#define X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256 61 + +/* Host, email and IP check errors */ +#define X509_V_ERR_HOSTNAME_MISMATCH 62 +#define X509_V_ERR_EMAIL_MISMATCH 63 +#define X509_V_ERR_IP_ADDRESS_MISMATCH 64 + +/* Caller error */ +#define X509_V_ERR_INVALID_CALL 65 +/* Issuer lookup error */ +#define X509_V_ERR_STORE_LOOKUP 66 + +/* Certificate verify flags */ + +/* Send issuer+subject checks to verify_cb */ +#define X509_V_FLAG_CB_ISSUER_CHECK 0x1 +/* Use check time instead of current time */ +#define X509_V_FLAG_USE_CHECK_TIME 0x2 +/* Lookup CRLs */ +#define X509_V_FLAG_CRL_CHECK 0x4 +/* Lookup CRLs for whole chain */ +#define X509_V_FLAG_CRL_CHECK_ALL 0x8 +/* Ignore unhandled critical extensions */ +#define X509_V_FLAG_IGNORE_CRITICAL 0x10 +/* Disable workarounds for broken certificates */ +#define X509_V_FLAG_X509_STRICT 0x20 +/* Enable proxy certificate validation */ +#define X509_V_FLAG_ALLOW_PROXY_CERTS 0x40 +/* Enable policy checking */ +#define X509_V_FLAG_POLICY_CHECK 0x80 +/* Policy variable require-explicit-policy */ +#define X509_V_FLAG_EXPLICIT_POLICY 0x100 +/* Policy variable inhibit-any-policy */ +#define X509_V_FLAG_INHIBIT_ANY 0x200 +/* Policy variable inhibit-policy-mapping */ +#define X509_V_FLAG_INHIBIT_MAP 0x400 +/* Notify callback that policy is OK */ +#define X509_V_FLAG_NOTIFY_POLICY 0x800 +/* Extended CRL features such as indirect CRLs, alternate CRL signing keys */ +#define X509_V_FLAG_EXTENDED_CRL_SUPPORT 0x1000 +/* Delta CRL support */ +#define X509_V_FLAG_USE_DELTAS 0x2000 +/* Check selfsigned CA signature */ +#define X509_V_FLAG_CHECK_SS_SIGNATURE 0x4000 +/* Use trusted store first */ +#define X509_V_FLAG_TRUSTED_FIRST 0x8000 +/* Suite B 128 bit only mode: not normally used */ +#define X509_V_FLAG_SUITEB_128_LOS_ONLY 0x10000 +/* Suite B 192 bit only mode */ +#define X509_V_FLAG_SUITEB_192_LOS 0x20000 +/* Suite B 128 bit mode allowing 192 bit algorithms */ +#define X509_V_FLAG_SUITEB_128_LOS 0x30000 + +/* Allow partial chains if at least one certificate is in trusted store */ +#define X509_V_FLAG_PARTIAL_CHAIN 0x80000 + +/* If the initial chain is not trusted, do not attempt to build an alternative + * chain. Alternate chain checking was introduced in 1.0.2b. Setting this flag + * will force the behaviour to match that of previous versions. */ +#define X509_V_FLAG_NO_ALT_CHAINS 0x100000 + +#define X509_VP_FLAG_DEFAULT 0x1 +#define X509_VP_FLAG_OVERWRITE 0x2 +#define X509_VP_FLAG_RESET_FLAGS 0x4 +#define X509_VP_FLAG_LOCKED 0x8 +#define X509_VP_FLAG_ONCE 0x10 + +/* Internal use: mask of policy related options */ +#define X509_V_FLAG_POLICY_MASK (X509_V_FLAG_POLICY_CHECK \ + | X509_V_FLAG_EXPLICIT_POLICY \ + | X509_V_FLAG_INHIBIT_ANY \ + | X509_V_FLAG_INHIBIT_MAP) + +OPENSSL_EXPORT int X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, int type, + X509_NAME *name); +OPENSSL_EXPORT X509_OBJECT *X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h,int type,X509_NAME *name); +OPENSSL_EXPORT X509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h, X509_OBJECT *x); +OPENSSL_EXPORT void X509_OBJECT_up_ref_count(X509_OBJECT *a); +OPENSSL_EXPORT void X509_OBJECT_free_contents(X509_OBJECT *a); +OPENSSL_EXPORT X509_STORE *X509_STORE_new(void ); +OPENSSL_EXPORT void X509_STORE_up_ref(X509_STORE *store); +OPENSSL_EXPORT void X509_STORE_free(X509_STORE *v); + +OPENSSL_EXPORT STACK_OF(X509)* X509_STORE_get1_certs(X509_STORE_CTX *st, X509_NAME *nm); +OPENSSL_EXPORT STACK_OF(X509_CRL)* X509_STORE_get1_crls(X509_STORE_CTX *st, X509_NAME *nm); +OPENSSL_EXPORT int X509_STORE_set_flags(X509_STORE *ctx, unsigned long flags); +OPENSSL_EXPORT int X509_STORE_set_purpose(X509_STORE *ctx, int purpose); +OPENSSL_EXPORT int X509_STORE_set_trust(X509_STORE *ctx, int trust); +OPENSSL_EXPORT int X509_STORE_set1_param(X509_STORE *ctx, X509_VERIFY_PARAM *pm); + +OPENSSL_EXPORT void X509_STORE_set_verify_cb(X509_STORE *ctx, + int (*verify_cb)(int, X509_STORE_CTX *)); + +OPENSSL_EXPORT void X509_STORE_set_lookup_crls_cb(X509_STORE *ctx, + STACK_OF(X509_CRL)* (*cb)(X509_STORE_CTX *ctx, X509_NAME *nm)); + +OPENSSL_EXPORT X509_STORE_CTX *X509_STORE_CTX_new(void); + +OPENSSL_EXPORT int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x); + +OPENSSL_EXPORT void X509_STORE_CTX_free(X509_STORE_CTX *ctx); +OPENSSL_EXPORT int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, + X509 *x509, STACK_OF(X509) *chain); +OPENSSL_EXPORT void X509_STORE_CTX_trusted_stack(X509_STORE_CTX *ctx, STACK_OF(X509) *sk); +OPENSSL_EXPORT void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx); + +OPENSSL_EXPORT X509_STORE *X509_STORE_CTX_get0_store(X509_STORE_CTX *ctx); + +OPENSSL_EXPORT X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m); + +OPENSSL_EXPORT X509_LOOKUP_METHOD *X509_LOOKUP_hash_dir(void); +OPENSSL_EXPORT X509_LOOKUP_METHOD *X509_LOOKUP_file(void); + +OPENSSL_EXPORT int X509_STORE_add_cert(X509_STORE *ctx, X509 *x); +OPENSSL_EXPORT int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x); + +OPENSSL_EXPORT int X509_STORE_get_by_subject(X509_STORE_CTX *vs,int type,X509_NAME *name, + X509_OBJECT *ret); + +OPENSSL_EXPORT int X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, + long argl, char **ret); + +#ifndef OPENSSL_NO_STDIO +OPENSSL_EXPORT int X509_load_cert_file(X509_LOOKUP *ctx, const char *file, int type); +OPENSSL_EXPORT int X509_load_crl_file(X509_LOOKUP *ctx, const char *file, int type); +OPENSSL_EXPORT int X509_load_cert_crl_file(X509_LOOKUP *ctx, const char *file, int type); +#endif + + +OPENSSL_EXPORT X509_LOOKUP *X509_LOOKUP_new(X509_LOOKUP_METHOD *method); +OPENSSL_EXPORT void X509_LOOKUP_free(X509_LOOKUP *ctx); +OPENSSL_EXPORT int X509_LOOKUP_init(X509_LOOKUP *ctx); +OPENSSL_EXPORT int X509_LOOKUP_by_subject(X509_LOOKUP *ctx, int type, X509_NAME *name, + X509_OBJECT *ret); +OPENSSL_EXPORT int X509_LOOKUP_by_issuer_serial(X509_LOOKUP *ctx, int type, X509_NAME *name, + ASN1_INTEGER *serial, X509_OBJECT *ret); +OPENSSL_EXPORT int X509_LOOKUP_by_fingerprint(X509_LOOKUP *ctx, int type, + unsigned char *bytes, int len, X509_OBJECT *ret); +OPENSSL_EXPORT int X509_LOOKUP_by_alias(X509_LOOKUP *ctx, int type, char *str, + int len, X509_OBJECT *ret); +OPENSSL_EXPORT int X509_LOOKUP_shutdown(X509_LOOKUP *ctx); + +#ifndef OPENSSL_NO_STDIO +OPENSSL_EXPORT int X509_STORE_load_locations (X509_STORE *ctx, + const char *file, const char *dir); +OPENSSL_EXPORT int X509_STORE_set_default_paths(X509_STORE *ctx); +#endif + +OPENSSL_EXPORT int X509_STORE_CTX_get_ex_new_index(long argl, void *argp, CRYPTO_EX_unused *unused, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func); +OPENSSL_EXPORT int X509_STORE_CTX_set_ex_data(X509_STORE_CTX *ctx,int idx,void *data); +OPENSSL_EXPORT void * X509_STORE_CTX_get_ex_data(X509_STORE_CTX *ctx,int idx); +OPENSSL_EXPORT int X509_STORE_CTX_get_error(X509_STORE_CTX *ctx); +OPENSSL_EXPORT void X509_STORE_CTX_set_error(X509_STORE_CTX *ctx,int s); +OPENSSL_EXPORT int X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx); +OPENSSL_EXPORT X509 * X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx); +OPENSSL_EXPORT X509 *X509_STORE_CTX_get0_current_issuer(X509_STORE_CTX *ctx); +OPENSSL_EXPORT X509_CRL *X509_STORE_CTX_get0_current_crl(X509_STORE_CTX *ctx); +OPENSSL_EXPORT X509_STORE_CTX *X509_STORE_CTX_get0_parent_ctx(X509_STORE_CTX *ctx); +OPENSSL_EXPORT STACK_OF(X509) *X509_STORE_CTX_get_chain(X509_STORE_CTX *ctx); +OPENSSL_EXPORT STACK_OF(X509) *X509_STORE_CTX_get1_chain(X509_STORE_CTX *ctx); +OPENSSL_EXPORT void X509_STORE_CTX_set_cert(X509_STORE_CTX *c,X509 *x); +OPENSSL_EXPORT void X509_STORE_CTX_set_chain(X509_STORE_CTX *c,STACK_OF(X509) *sk); +OPENSSL_EXPORT void X509_STORE_CTX_set0_crls(X509_STORE_CTX *c,STACK_OF(X509_CRL) *sk); +OPENSSL_EXPORT int X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose); +OPENSSL_EXPORT int X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust); +OPENSSL_EXPORT int X509_STORE_CTX_purpose_inherit(X509_STORE_CTX *ctx, int def_purpose, + int purpose, int trust); +OPENSSL_EXPORT void X509_STORE_CTX_set_flags(X509_STORE_CTX *ctx, unsigned long flags); +OPENSSL_EXPORT void X509_STORE_CTX_set_time(X509_STORE_CTX *ctx, unsigned long flags, + time_t t); +OPENSSL_EXPORT void X509_STORE_CTX_set_verify_cb(X509_STORE_CTX *ctx, + int (*verify_cb)(int, X509_STORE_CTX *)); + +OPENSSL_EXPORT X509_POLICY_TREE *X509_STORE_CTX_get0_policy_tree(X509_STORE_CTX *ctx); +OPENSSL_EXPORT int X509_STORE_CTX_get_explicit_policy(X509_STORE_CTX *ctx); + +OPENSSL_EXPORT X509_VERIFY_PARAM *X509_STORE_CTX_get0_param(X509_STORE_CTX *ctx); +OPENSSL_EXPORT void X509_STORE_CTX_set0_param(X509_STORE_CTX *ctx, X509_VERIFY_PARAM *param); +OPENSSL_EXPORT int X509_STORE_CTX_set_default(X509_STORE_CTX *ctx, const char *name); + +/* X509_VERIFY_PARAM functions */ + +OPENSSL_EXPORT X509_VERIFY_PARAM *X509_VERIFY_PARAM_new(void); +OPENSSL_EXPORT void X509_VERIFY_PARAM_free(X509_VERIFY_PARAM *param); +OPENSSL_EXPORT int X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *to, + const X509_VERIFY_PARAM *from); +OPENSSL_EXPORT int X509_VERIFY_PARAM_set1(X509_VERIFY_PARAM *to, + const X509_VERIFY_PARAM *from); +OPENSSL_EXPORT int X509_VERIFY_PARAM_set1_name(X509_VERIFY_PARAM *param, const char *name); +OPENSSL_EXPORT int X509_VERIFY_PARAM_set_flags(X509_VERIFY_PARAM *param, unsigned long flags); +OPENSSL_EXPORT int X509_VERIFY_PARAM_clear_flags(X509_VERIFY_PARAM *param, + unsigned long flags); +OPENSSL_EXPORT unsigned long X509_VERIFY_PARAM_get_flags(X509_VERIFY_PARAM *param); +OPENSSL_EXPORT int X509_VERIFY_PARAM_set_purpose(X509_VERIFY_PARAM *param, int purpose); +OPENSSL_EXPORT int X509_VERIFY_PARAM_set_trust(X509_VERIFY_PARAM *param, int trust); +OPENSSL_EXPORT void X509_VERIFY_PARAM_set_depth(X509_VERIFY_PARAM *param, int depth); +OPENSSL_EXPORT void X509_VERIFY_PARAM_set_time(X509_VERIFY_PARAM *param, time_t t); +OPENSSL_EXPORT int X509_VERIFY_PARAM_add0_policy(X509_VERIFY_PARAM *param, + ASN1_OBJECT *policy); +OPENSSL_EXPORT int X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param, + STACK_OF(ASN1_OBJECT) *policies); + +OPENSSL_EXPORT int X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param, + const char *name, size_t namelen); +OPENSSL_EXPORT int X509_VERIFY_PARAM_add1_host(X509_VERIFY_PARAM *param, + const char *name, + size_t namelen); +OPENSSL_EXPORT void X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *param, + unsigned int flags); +OPENSSL_EXPORT char *X509_VERIFY_PARAM_get0_peername(X509_VERIFY_PARAM *); +OPENSSL_EXPORT int X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param, + const char *email, size_t emaillen); +OPENSSL_EXPORT int X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param, + const unsigned char *ip, size_t iplen); +OPENSSL_EXPORT int X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM *param, const char *ipasc); + +OPENSSL_EXPORT int X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM *param); +OPENSSL_EXPORT const char *X509_VERIFY_PARAM_get0_name(const X509_VERIFY_PARAM *param); + +OPENSSL_EXPORT int X509_VERIFY_PARAM_add0_table(X509_VERIFY_PARAM *param); +OPENSSL_EXPORT int X509_VERIFY_PARAM_get_count(void); +OPENSSL_EXPORT const X509_VERIFY_PARAM *X509_VERIFY_PARAM_get0(int id); +OPENSSL_EXPORT const X509_VERIFY_PARAM *X509_VERIFY_PARAM_lookup(const char *name); +OPENSSL_EXPORT void X509_VERIFY_PARAM_table_cleanup(void); + +OPENSSL_EXPORT int X509_policy_check(X509_POLICY_TREE **ptree, int *pexplicit_policy, + STACK_OF(X509) *certs, + STACK_OF(ASN1_OBJECT) *policy_oids, + unsigned int flags); + +OPENSSL_EXPORT void X509_policy_tree_free(X509_POLICY_TREE *tree); + +OPENSSL_EXPORT int X509_policy_tree_level_count(const X509_POLICY_TREE *tree); +OPENSSL_EXPORT X509_POLICY_LEVEL * + X509_policy_tree_get0_level(const X509_POLICY_TREE *tree, int i); + +OPENSSL_EXPORT STACK_OF(X509_POLICY_NODE) * + X509_policy_tree_get0_policies(const X509_POLICY_TREE *tree); + +OPENSSL_EXPORT STACK_OF(X509_POLICY_NODE) * + X509_policy_tree_get0_user_policies(const X509_POLICY_TREE *tree); + +OPENSSL_EXPORT int X509_policy_level_node_count(X509_POLICY_LEVEL *level); + +OPENSSL_EXPORT X509_POLICY_NODE *X509_policy_level_get0_node(X509_POLICY_LEVEL *level, int i); + +OPENSSL_EXPORT const ASN1_OBJECT *X509_policy_node_get0_policy(const X509_POLICY_NODE *node); + +OPENSSL_EXPORT STACK_OF(POLICYQUALINFO) * + X509_policy_node_get0_qualifiers(const X509_POLICY_NODE *node); +OPENSSL_EXPORT const X509_POLICY_NODE * + X509_policy_node_get0_parent(const X509_POLICY_NODE *node); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/external/boringssl/include/openssl/x509v3.h b/external/boringssl/include/openssl/x509v3.h new file mode 100644 index 0000000000..fa78f33a21 --- /dev/null +++ b/external/boringssl/include/openssl/x509v3.h @@ -0,0 +1,800 @@ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 1999. */ +/* ==================================================================== + * Copyright (c) 1999-2004 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#ifndef HEADER_X509V3_H +#define HEADER_X509V3_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Forward reference */ +struct v3_ext_method; +struct v3_ext_ctx; + +/* Useful typedefs */ + +typedef void * (*X509V3_EXT_NEW)(void); +typedef void (*X509V3_EXT_FREE)(void *); +typedef void * (*X509V3_EXT_D2I)(void *, const unsigned char ** , long); +typedef int (*X509V3_EXT_I2D)(void *, unsigned char **); +typedef STACK_OF(CONF_VALUE) * + (*X509V3_EXT_I2V)(const struct v3_ext_method *method, void *ext, + STACK_OF(CONF_VALUE) *extlist); +typedef void * (*X509V3_EXT_V2I)(const struct v3_ext_method *method, + struct v3_ext_ctx *ctx, + STACK_OF(CONF_VALUE) *values); +typedef char * (*X509V3_EXT_I2S)(const struct v3_ext_method *method, void *ext); +typedef void * (*X509V3_EXT_S2I)(const struct v3_ext_method *method, + struct v3_ext_ctx *ctx, const char *str); +typedef int (*X509V3_EXT_I2R)(const struct v3_ext_method *method, void *ext, + BIO *out, int indent); +typedef void * (*X509V3_EXT_R2I)(const struct v3_ext_method *method, + struct v3_ext_ctx *ctx, const char *str); + +/* V3 extension structure */ + +struct v3_ext_method { +int ext_nid; +int ext_flags; +/* If this is set the following four fields are ignored */ +ASN1_ITEM_EXP *it; +/* Old style ASN1 calls */ +X509V3_EXT_NEW ext_new; +X509V3_EXT_FREE ext_free; +X509V3_EXT_D2I d2i; +X509V3_EXT_I2D i2d; + +/* The following pair is used for string extensions */ +X509V3_EXT_I2S i2s; +X509V3_EXT_S2I s2i; + +/* The following pair is used for multi-valued extensions */ +X509V3_EXT_I2V i2v; +X509V3_EXT_V2I v2i; + +/* The following are used for raw extensions */ +X509V3_EXT_I2R i2r; +X509V3_EXT_R2I r2i; + +void *usr_data; /* Any extension specific data */ +}; + +typedef struct X509V3_CONF_METHOD_st { +char * (*get_string)(void *db, char *section, char *value); +STACK_OF(CONF_VALUE) * (*get_section)(void *db, char *section); +void (*free_string)(void *db, char * string); +void (*free_section)(void *db, STACK_OF(CONF_VALUE) *section); +} X509V3_CONF_METHOD; + +/* Context specific info */ +struct v3_ext_ctx { +#define CTX_TEST 0x1 +int flags; +X509 *issuer_cert; +X509 *subject_cert; +X509_REQ *subject_req; +X509_CRL *crl; +const X509V3_CONF_METHOD *db_meth; +void *db; +/* Maybe more here */ +}; + +typedef struct v3_ext_method X509V3_EXT_METHOD; + +DECLARE_STACK_OF(X509V3_EXT_METHOD) + +/* ext_flags values */ +#define X509V3_EXT_DYNAMIC 0x1 +#define X509V3_EXT_CTX_DEP 0x2 +#define X509V3_EXT_MULTILINE 0x4 + +typedef BIT_STRING_BITNAME ENUMERATED_NAMES; + +typedef struct BASIC_CONSTRAINTS_st { +int ca; +ASN1_INTEGER *pathlen; +} BASIC_CONSTRAINTS; + + +typedef struct PKEY_USAGE_PERIOD_st { +ASN1_GENERALIZEDTIME *notBefore; +ASN1_GENERALIZEDTIME *notAfter; +} PKEY_USAGE_PERIOD; + +typedef struct otherName_st { +ASN1_OBJECT *type_id; +ASN1_TYPE *value; +} OTHERNAME; + +typedef struct EDIPartyName_st { + ASN1_STRING *nameAssigner; + ASN1_STRING *partyName; +} EDIPARTYNAME; + +typedef struct GENERAL_NAME_st { + +#define GEN_OTHERNAME 0 +#define GEN_EMAIL 1 +#define GEN_DNS 2 +#define GEN_X400 3 +#define GEN_DIRNAME 4 +#define GEN_EDIPARTY 5 +#define GEN_URI 6 +#define GEN_IPADD 7 +#define GEN_RID 8 + +int type; +union { + char *ptr; + OTHERNAME *otherName; /* otherName */ + ASN1_IA5STRING *rfc822Name; + ASN1_IA5STRING *dNSName; + ASN1_TYPE *x400Address; + X509_NAME *directoryName; + EDIPARTYNAME *ediPartyName; + ASN1_IA5STRING *uniformResourceIdentifier; + ASN1_OCTET_STRING *iPAddress; + ASN1_OBJECT *registeredID; + + /* Old names */ + ASN1_OCTET_STRING *ip; /* iPAddress */ + X509_NAME *dirn; /* dirn */ + ASN1_IA5STRING *ia5;/* rfc822Name, dNSName, uniformResourceIdentifier */ + ASN1_OBJECT *rid; /* registeredID */ + ASN1_TYPE *other; /* x400Address */ +} d; +} GENERAL_NAME; + +typedef STACK_OF(GENERAL_NAME) GENERAL_NAMES; + +typedef struct ACCESS_DESCRIPTION_st { + ASN1_OBJECT *method; + GENERAL_NAME *location; +} ACCESS_DESCRIPTION; + +typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS; + +typedef STACK_OF(ASN1_OBJECT) EXTENDED_KEY_USAGE; + +DECLARE_STACK_OF(GENERAL_NAME) +DECLARE_ASN1_SET_OF(GENERAL_NAME) + +DECLARE_STACK_OF(ACCESS_DESCRIPTION) +DECLARE_ASN1_SET_OF(ACCESS_DESCRIPTION) + +typedef struct DIST_POINT_NAME_st { +int type; +union { + GENERAL_NAMES *fullname; + STACK_OF(X509_NAME_ENTRY) *relativename; +} name; +/* If relativename then this contains the full distribution point name */ +X509_NAME *dpname; +} DIST_POINT_NAME; +/* All existing reasons */ +#define CRLDP_ALL_REASONS 0x807f + +#define CRL_REASON_NONE -1 +#define CRL_REASON_UNSPECIFIED 0 +#define CRL_REASON_KEY_COMPROMISE 1 +#define CRL_REASON_CA_COMPROMISE 2 +#define CRL_REASON_AFFILIATION_CHANGED 3 +#define CRL_REASON_SUPERSEDED 4 +#define CRL_REASON_CESSATION_OF_OPERATION 5 +#define CRL_REASON_CERTIFICATE_HOLD 6 +#define CRL_REASON_REMOVE_FROM_CRL 8 +#define CRL_REASON_PRIVILEGE_WITHDRAWN 9 +#define CRL_REASON_AA_COMPROMISE 10 + +struct DIST_POINT_st { +DIST_POINT_NAME *distpoint; +ASN1_BIT_STRING *reasons; +GENERAL_NAMES *CRLissuer; +int dp_reasons; +}; + +typedef STACK_OF(DIST_POINT) CRL_DIST_POINTS; + +DECLARE_STACK_OF(DIST_POINT) +DECLARE_ASN1_SET_OF(DIST_POINT) + +struct AUTHORITY_KEYID_st { +ASN1_OCTET_STRING *keyid; +GENERAL_NAMES *issuer; +ASN1_INTEGER *serial; +}; + +/* Strong extranet structures */ + +typedef struct SXNET_ID_st { + ASN1_INTEGER *zone; + ASN1_OCTET_STRING *user; +} SXNETID; + +DECLARE_STACK_OF(SXNETID) +DECLARE_ASN1_SET_OF(SXNETID) + +typedef struct SXNET_st { + ASN1_INTEGER *version; + STACK_OF(SXNETID) *ids; +} SXNET; + +typedef struct NOTICEREF_st { + ASN1_STRING *organization; + STACK_OF(ASN1_INTEGER) *noticenos; +} NOTICEREF; + +typedef struct USERNOTICE_st { + NOTICEREF *noticeref; + ASN1_STRING *exptext; +} USERNOTICE; + +typedef struct POLICYQUALINFO_st { + ASN1_OBJECT *pqualid; + union { + ASN1_IA5STRING *cpsuri; + USERNOTICE *usernotice; + ASN1_TYPE *other; + } d; +} POLICYQUALINFO; + +DECLARE_STACK_OF(POLICYQUALINFO) +DECLARE_ASN1_SET_OF(POLICYQUALINFO) + +typedef struct POLICYINFO_st { + ASN1_OBJECT *policyid; + STACK_OF(POLICYQUALINFO) *qualifiers; +} POLICYINFO; + +typedef STACK_OF(POLICYINFO) CERTIFICATEPOLICIES; + +DECLARE_STACK_OF(POLICYINFO) +DECLARE_ASN1_SET_OF(POLICYINFO) + +typedef struct POLICY_MAPPING_st { + ASN1_OBJECT *issuerDomainPolicy; + ASN1_OBJECT *subjectDomainPolicy; +} POLICY_MAPPING; + +DECLARE_STACK_OF(POLICY_MAPPING) + +typedef STACK_OF(POLICY_MAPPING) POLICY_MAPPINGS; + +typedef struct GENERAL_SUBTREE_st { + GENERAL_NAME *base; + ASN1_INTEGER *minimum; + ASN1_INTEGER *maximum; +} GENERAL_SUBTREE; + +DECLARE_STACK_OF(GENERAL_SUBTREE) + +struct NAME_CONSTRAINTS_st { + STACK_OF(GENERAL_SUBTREE) *permittedSubtrees; + STACK_OF(GENERAL_SUBTREE) *excludedSubtrees; +}; + +typedef struct POLICY_CONSTRAINTS_st { + ASN1_INTEGER *requireExplicitPolicy; + ASN1_INTEGER *inhibitPolicyMapping; +} POLICY_CONSTRAINTS; + +/* Proxy certificate structures, see RFC 3820 */ +typedef struct PROXY_POLICY_st + { + ASN1_OBJECT *policyLanguage; + ASN1_OCTET_STRING *policy; + } PROXY_POLICY; + +typedef struct PROXY_CERT_INFO_EXTENSION_st + { + ASN1_INTEGER *pcPathLengthConstraint; + PROXY_POLICY *proxyPolicy; + } PROXY_CERT_INFO_EXTENSION; + +DECLARE_ASN1_FUNCTIONS(PROXY_POLICY) +DECLARE_ASN1_FUNCTIONS(PROXY_CERT_INFO_EXTENSION) + +struct ISSUING_DIST_POINT_st + { + DIST_POINT_NAME *distpoint; + int onlyuser; + int onlyCA; + ASN1_BIT_STRING *onlysomereasons; + int indirectCRL; + int onlyattr; + }; + +/* Values in idp_flags field */ +/* IDP present */ +#define IDP_PRESENT 0x1 +/* IDP values inconsistent */ +#define IDP_INVALID 0x2 +/* onlyuser true */ +#define IDP_ONLYUSER 0x4 +/* onlyCA true */ +#define IDP_ONLYCA 0x8 +/* onlyattr true */ +#define IDP_ONLYATTR 0x10 +/* indirectCRL true */ +#define IDP_INDIRECT 0x20 +/* onlysomereasons present */ +#define IDP_REASONS 0x40 + +#define X509V3_conf_err(val) ERR_add_error_data(6, "section:", val->section, \ +",name:", val->name, ",value:", val->value); + +#define X509V3_set_ctx_test(ctx) \ + X509V3_set_ctx(ctx, NULL, NULL, NULL, NULL, CTX_TEST) +#define X509V3_set_ctx_nodb(ctx) (ctx)->db = NULL; + +#define EXT_BITSTRING(nid, table) { nid, 0, ASN1_ITEM_ref(ASN1_BIT_STRING), \ + 0,0,0,0, \ + 0,0, \ + (X509V3_EXT_I2V)i2v_ASN1_BIT_STRING, \ + (X509V3_EXT_V2I)v2i_ASN1_BIT_STRING, \ + NULL, NULL, \ + (void *)table} + +#define EXT_IA5STRING(nid) { nid, 0, ASN1_ITEM_ref(ASN1_IA5STRING), \ + 0,0,0,0, \ + (X509V3_EXT_I2S)i2s_ASN1_IA5STRING, \ + (X509V3_EXT_S2I)s2i_ASN1_IA5STRING, \ + 0,0,0,0, \ + NULL} + +#define EXT_END { -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + + +/* X509_PURPOSE stuff */ + +#define EXFLAG_BCONS 0x1 +#define EXFLAG_KUSAGE 0x2 +#define EXFLAG_XKUSAGE 0x4 +#define EXFLAG_NSCERT 0x8 + +#define EXFLAG_CA 0x10 +/* Really self issued not necessarily self signed */ +#define EXFLAG_SI 0x20 +#define EXFLAG_V1 0x40 +#define EXFLAG_INVALID 0x80 +#define EXFLAG_SET 0x100 +#define EXFLAG_CRITICAL 0x200 +#define EXFLAG_PROXY 0x400 + +#define EXFLAG_INVALID_POLICY 0x800 +#define EXFLAG_FRESHEST 0x1000 +/* Self signed */ +#define EXFLAG_SS 0x2000 + +#define KU_DIGITAL_SIGNATURE 0x0080 +#define KU_NON_REPUDIATION 0x0040 +#define KU_KEY_ENCIPHERMENT 0x0020 +#define KU_DATA_ENCIPHERMENT 0x0010 +#define KU_KEY_AGREEMENT 0x0008 +#define KU_KEY_CERT_SIGN 0x0004 +#define KU_CRL_SIGN 0x0002 +#define KU_ENCIPHER_ONLY 0x0001 +#define KU_DECIPHER_ONLY 0x8000 + +#define NS_SSL_CLIENT 0x80 +#define NS_SSL_SERVER 0x40 +#define NS_SMIME 0x20 +#define NS_OBJSIGN 0x10 +#define NS_SSL_CA 0x04 +#define NS_SMIME_CA 0x02 +#define NS_OBJSIGN_CA 0x01 +#define NS_ANY_CA (NS_SSL_CA|NS_SMIME_CA|NS_OBJSIGN_CA) + +#define XKU_SSL_SERVER 0x1 +#define XKU_SSL_CLIENT 0x2 +#define XKU_SMIME 0x4 +#define XKU_CODE_SIGN 0x8 +#define XKU_SGC 0x10 +#define XKU_OCSP_SIGN 0x20 +#define XKU_TIMESTAMP 0x40 +#define XKU_DVCS 0x80 +#define XKU_ANYEKU 0x100 + +#define X509_PURPOSE_DYNAMIC 0x1 +#define X509_PURPOSE_DYNAMIC_NAME 0x2 + +typedef struct x509_purpose_st { + int purpose; + int trust; /* Default trust ID */ + int flags; + int (*check_purpose)(const struct x509_purpose_st *, + const X509 *, int); + char *name; + char *sname; + void *usr_data; +} X509_PURPOSE; + +#define X509_PURPOSE_SSL_CLIENT 1 +#define X509_PURPOSE_SSL_SERVER 2 +#define X509_PURPOSE_NS_SSL_SERVER 3 +#define X509_PURPOSE_SMIME_SIGN 4 +#define X509_PURPOSE_SMIME_ENCRYPT 5 +#define X509_PURPOSE_CRL_SIGN 6 +#define X509_PURPOSE_ANY 7 +#define X509_PURPOSE_OCSP_HELPER 8 +#define X509_PURPOSE_TIMESTAMP_SIGN 9 + +#define X509_PURPOSE_MIN 1 +#define X509_PURPOSE_MAX 9 + +/* Flags for X509V3_EXT_print() */ + +#define X509V3_EXT_UNKNOWN_MASK (0xfL << 16) +/* Return error for unknown extensions */ +#define X509V3_EXT_DEFAULT 0 +/* Print error for unknown extensions */ +#define X509V3_EXT_ERROR_UNKNOWN (1L << 16) +/* ASN1 parse unknown extensions */ +#define X509V3_EXT_PARSE_UNKNOWN (2L << 16) +/* BIO_dump unknown extensions */ +#define X509V3_EXT_DUMP_UNKNOWN (3L << 16) + +/* Flags for X509V3_add1_i2d */ + +#define X509V3_ADD_OP_MASK 0xfL +#define X509V3_ADD_DEFAULT 0L +#define X509V3_ADD_APPEND 1L +#define X509V3_ADD_REPLACE 2L +#define X509V3_ADD_REPLACE_EXISTING 3L +#define X509V3_ADD_KEEP_EXISTING 4L +#define X509V3_ADD_DELETE 5L +#define X509V3_ADD_SILENT 0x10 + +DECLARE_STACK_OF(X509_PURPOSE) + +DECLARE_ASN1_FUNCTIONS(BASIC_CONSTRAINTS) + +DECLARE_ASN1_FUNCTIONS(SXNET) +DECLARE_ASN1_FUNCTIONS(SXNETID) + +int SXNET_add_id_asc(SXNET **psx, char *zone, char *user, int userlen); +int SXNET_add_id_ulong(SXNET **psx, unsigned long lzone, char *user, int userlen); +int SXNET_add_id_INTEGER(SXNET **psx, ASN1_INTEGER *izone, char *user, int userlen); + +ASN1_OCTET_STRING *SXNET_get_id_asc(SXNET *sx, char *zone); +ASN1_OCTET_STRING *SXNET_get_id_ulong(SXNET *sx, unsigned long lzone); +ASN1_OCTET_STRING *SXNET_get_id_INTEGER(SXNET *sx, ASN1_INTEGER *zone); + +DECLARE_ASN1_FUNCTIONS(AUTHORITY_KEYID) + +DECLARE_ASN1_FUNCTIONS(PKEY_USAGE_PERIOD) + +DECLARE_ASN1_FUNCTIONS(GENERAL_NAME) +OPENSSL_EXPORT GENERAL_NAME *GENERAL_NAME_dup(GENERAL_NAME *a); +OPENSSL_EXPORT int GENERAL_NAME_cmp(GENERAL_NAME *a, GENERAL_NAME *b); + + + +OPENSSL_EXPORT ASN1_BIT_STRING *v2i_ASN1_BIT_STRING(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval); +OPENSSL_EXPORT STACK_OF(CONF_VALUE) *i2v_ASN1_BIT_STRING(X509V3_EXT_METHOD *method, + ASN1_BIT_STRING *bits, + STACK_OF(CONF_VALUE) *extlist); + +OPENSSL_EXPORT STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method, GENERAL_NAME *gen, STACK_OF(CONF_VALUE) *ret); +OPENSSL_EXPORT int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen); + +DECLARE_ASN1_FUNCTIONS(GENERAL_NAMES) + +OPENSSL_EXPORT STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES(X509V3_EXT_METHOD *method, + GENERAL_NAMES *gen, STACK_OF(CONF_VALUE) *extlist); +OPENSSL_EXPORT GENERAL_NAMES *v2i_GENERAL_NAMES(const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval); + +DECLARE_ASN1_FUNCTIONS(OTHERNAME) +DECLARE_ASN1_FUNCTIONS(EDIPARTYNAME) +OPENSSL_EXPORT int OTHERNAME_cmp(OTHERNAME *a, OTHERNAME *b); +OPENSSL_EXPORT void GENERAL_NAME_set0_value(GENERAL_NAME *a, int type, void *value); +OPENSSL_EXPORT void *GENERAL_NAME_get0_value(GENERAL_NAME *a, int *ptype); +OPENSSL_EXPORT int GENERAL_NAME_set0_othername(GENERAL_NAME *gen, + ASN1_OBJECT *oid, ASN1_TYPE *value); +OPENSSL_EXPORT int GENERAL_NAME_get0_otherName(GENERAL_NAME *gen, + ASN1_OBJECT **poid, ASN1_TYPE **pvalue); + +OPENSSL_EXPORT char *i2s_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method, ASN1_OCTET_STRING *ia5); +OPENSSL_EXPORT ASN1_OCTET_STRING *s2i_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, char *str); + +DECLARE_ASN1_FUNCTIONS(EXTENDED_KEY_USAGE) +OPENSSL_EXPORT int i2a_ACCESS_DESCRIPTION(BIO *bp, ACCESS_DESCRIPTION* a); + +DECLARE_ASN1_FUNCTIONS(CERTIFICATEPOLICIES) +DECLARE_ASN1_FUNCTIONS(POLICYINFO) +DECLARE_ASN1_FUNCTIONS(POLICYQUALINFO) +DECLARE_ASN1_FUNCTIONS(USERNOTICE) +DECLARE_ASN1_FUNCTIONS(NOTICEREF) + +DECLARE_ASN1_FUNCTIONS(CRL_DIST_POINTS) +DECLARE_ASN1_FUNCTIONS(DIST_POINT) +DECLARE_ASN1_FUNCTIONS(DIST_POINT_NAME) +DECLARE_ASN1_FUNCTIONS(ISSUING_DIST_POINT) + +OPENSSL_EXPORT int DIST_POINT_set_dpname(DIST_POINT_NAME *dpn, X509_NAME *iname); + +OPENSSL_EXPORT int NAME_CONSTRAINTS_check(X509 *x, NAME_CONSTRAINTS *nc); + +DECLARE_ASN1_FUNCTIONS(ACCESS_DESCRIPTION) +DECLARE_ASN1_FUNCTIONS(AUTHORITY_INFO_ACCESS) + +DECLARE_ASN1_ITEM(POLICY_MAPPING) +DECLARE_ASN1_ALLOC_FUNCTIONS(POLICY_MAPPING) +DECLARE_ASN1_ITEM(POLICY_MAPPINGS) + +DECLARE_ASN1_ITEM(GENERAL_SUBTREE) +DECLARE_ASN1_ALLOC_FUNCTIONS(GENERAL_SUBTREE) + +DECLARE_ASN1_ITEM(NAME_CONSTRAINTS) +DECLARE_ASN1_ALLOC_FUNCTIONS(NAME_CONSTRAINTS) + +DECLARE_ASN1_ALLOC_FUNCTIONS(POLICY_CONSTRAINTS) +DECLARE_ASN1_ITEM(POLICY_CONSTRAINTS) + +OPENSSL_EXPORT GENERAL_NAME *a2i_GENERAL_NAME(GENERAL_NAME *out, + const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, + int gen_type, char *value, int is_nc); + +OPENSSL_EXPORT GENERAL_NAME *v2i_GENERAL_NAME(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, + CONF_VALUE *cnf); +OPENSSL_EXPORT GENERAL_NAME *v2i_GENERAL_NAME_ex(GENERAL_NAME *out, + const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, CONF_VALUE *cnf, int is_nc); +OPENSSL_EXPORT void X509V3_conf_free(CONF_VALUE *val); + +OPENSSL_EXPORT X509_EXTENSION *X509V3_EXT_conf_nid(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx, int ext_nid, char *value); +OPENSSL_EXPORT X509_EXTENSION *X509V3_EXT_nconf_nid(CONF *conf, X509V3_CTX *ctx, int ext_nid, char *value); +OPENSSL_EXPORT X509_EXTENSION *X509V3_EXT_nconf(CONF *conf, X509V3_CTX *ctx, char *name, char *value); +OPENSSL_EXPORT int X509V3_EXT_add_nconf_sk(CONF *conf, X509V3_CTX *ctx, char *section, STACK_OF(X509_EXTENSION) **sk); +OPENSSL_EXPORT int X509V3_EXT_add_nconf(CONF *conf, X509V3_CTX *ctx, char *section, X509 *cert); +OPENSSL_EXPORT int X509V3_EXT_REQ_add_nconf(CONF *conf, X509V3_CTX *ctx, char *section, X509_REQ *req); +OPENSSL_EXPORT int X509V3_EXT_CRL_add_nconf(CONF *conf, X509V3_CTX *ctx, char *section, X509_CRL *crl); + +OPENSSL_EXPORT int X509V3_EXT_CRL_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx, + char *section, X509_CRL *crl); + +OPENSSL_EXPORT int X509V3_add_value_bool_nf(char *name, int asn1_bool, + STACK_OF(CONF_VALUE) **extlist); +OPENSSL_EXPORT int X509V3_get_value_bool(CONF_VALUE *value, int *asn1_bool); +OPENSSL_EXPORT int X509V3_get_value_int(CONF_VALUE *value, ASN1_INTEGER **aint); +OPENSSL_EXPORT void X509V3_set_nconf(X509V3_CTX *ctx, CONF *conf); + +OPENSSL_EXPORT char * X509V3_get_string(X509V3_CTX *ctx, char *name, char *section); +OPENSSL_EXPORT STACK_OF(CONF_VALUE) * X509V3_get_section(X509V3_CTX *ctx, char *section); +OPENSSL_EXPORT void X509V3_string_free(X509V3_CTX *ctx, char *str); +OPENSSL_EXPORT void X509V3_section_free( X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *section); +OPENSSL_EXPORT void X509V3_set_ctx(X509V3_CTX *ctx, X509 *issuer, X509 *subject, + X509_REQ *req, X509_CRL *crl, int flags); + +OPENSSL_EXPORT int X509V3_add_value(const char *name, const char *value, + STACK_OF(CONF_VALUE) **extlist); +OPENSSL_EXPORT int X509V3_add_value_uchar(const char *name, const unsigned char *value, + STACK_OF(CONF_VALUE) **extlist); +OPENSSL_EXPORT int X509V3_add_value_bool(const char *name, int asn1_bool, + STACK_OF(CONF_VALUE) **extlist); +OPENSSL_EXPORT int X509V3_add_value_int(const char *name, ASN1_INTEGER *aint, + STACK_OF(CONF_VALUE) **extlist); +OPENSSL_EXPORT char * i2s_ASN1_INTEGER(X509V3_EXT_METHOD *meth, ASN1_INTEGER *aint); +OPENSSL_EXPORT ASN1_INTEGER * s2i_ASN1_INTEGER(X509V3_EXT_METHOD *meth, char *value); +OPENSSL_EXPORT char * i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *meth, ASN1_ENUMERATED *aint); +OPENSSL_EXPORT char * i2s_ASN1_ENUMERATED_TABLE(X509V3_EXT_METHOD *meth, ASN1_ENUMERATED *aint); +OPENSSL_EXPORT int X509V3_EXT_add(X509V3_EXT_METHOD *ext); +OPENSSL_EXPORT int X509V3_EXT_add_list(X509V3_EXT_METHOD *extlist); +OPENSSL_EXPORT int X509V3_EXT_add_alias(int nid_to, int nid_from); +OPENSSL_EXPORT void X509V3_EXT_cleanup(void); + +OPENSSL_EXPORT const X509V3_EXT_METHOD *X509V3_EXT_get(X509_EXTENSION *ext); +OPENSSL_EXPORT const X509V3_EXT_METHOD *X509V3_EXT_get_nid(int nid); +OPENSSL_EXPORT int X509V3_add_standard_extensions(void); +OPENSSL_EXPORT STACK_OF(CONF_VALUE) *X509V3_parse_list(const char *line); +OPENSSL_EXPORT void *X509V3_EXT_d2i(X509_EXTENSION *ext); +OPENSSL_EXPORT void *X509V3_get_d2i(STACK_OF(X509_EXTENSION) *x, int nid, int *crit, int *idx); +OPENSSL_EXPORT int X509V3_EXT_free(int nid, void *ext_data); + + +OPENSSL_EXPORT X509_EXTENSION *X509V3_EXT_i2d(int ext_nid, int crit, void *ext_struc); +OPENSSL_EXPORT int X509V3_add1_i2d(STACK_OF(X509_EXTENSION) **x, int nid, void *value, int crit, unsigned long flags); + +char *hex_to_string(const unsigned char *buffer, long len); +unsigned char *string_to_hex(const char *str, long *len); +int name_cmp(const char *name, const char *cmp); + +OPENSSL_EXPORT void X509V3_EXT_val_prn(BIO *out, STACK_OF(CONF_VALUE) *val, int indent, + int ml); +OPENSSL_EXPORT int X509V3_EXT_print(BIO *out, X509_EXTENSION *ext, unsigned long flag, int indent); +OPENSSL_EXPORT int X509V3_EXT_print_fp(FILE *out, X509_EXTENSION *ext, int flag, int indent); + +OPENSSL_EXPORT int X509V3_extensions_print(BIO *out, const char *title, STACK_OF(X509_EXTENSION) *exts, unsigned long flag, int indent); + +OPENSSL_EXPORT int X509_check_ca(X509 *x); +OPENSSL_EXPORT int X509_check_purpose(X509 *x, int id, int ca); +OPENSSL_EXPORT int X509_supported_extension(X509_EXTENSION *ex); +OPENSSL_EXPORT int X509_PURPOSE_set(int *p, int purpose); +OPENSSL_EXPORT int X509_check_issued(X509 *issuer, X509 *subject); +OPENSSL_EXPORT int X509_check_akid(X509 *issuer, AUTHORITY_KEYID *akid); +OPENSSL_EXPORT int X509_PURPOSE_get_count(void); +OPENSSL_EXPORT X509_PURPOSE * X509_PURPOSE_get0(int idx); +OPENSSL_EXPORT int X509_PURPOSE_get_by_sname(char *sname); +OPENSSL_EXPORT int X509_PURPOSE_get_by_id(int id); +OPENSSL_EXPORT int X509_PURPOSE_add(int id, int trust, int flags, + int (*ck)(const X509_PURPOSE *, const X509 *, int), + char *name, char *sname, void *arg); +OPENSSL_EXPORT char *X509_PURPOSE_get0_name(X509_PURPOSE *xp); +OPENSSL_EXPORT char *X509_PURPOSE_get0_sname(X509_PURPOSE *xp); +OPENSSL_EXPORT int X509_PURPOSE_get_trust(X509_PURPOSE *xp); +OPENSSL_EXPORT void X509_PURPOSE_cleanup(void); +OPENSSL_EXPORT int X509_PURPOSE_get_id(X509_PURPOSE *); + +OPENSSL_EXPORT STACK_OF(OPENSSL_STRING) *X509_get1_email(X509 *x); +OPENSSL_EXPORT STACK_OF(OPENSSL_STRING) *X509_REQ_get1_email(X509_REQ *x); +OPENSSL_EXPORT void X509_email_free(STACK_OF(OPENSSL_STRING) *sk); +OPENSSL_EXPORT STACK_OF(OPENSSL_STRING) *X509_get1_ocsp(X509 *x); +/* Flags for X509_check_* functions */ + +/* Always check subject name for host match even if subject alt names present */ +#define X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT 0x1 +/* Disable wildcard matching for dnsName fields and common name. */ +#define X509_CHECK_FLAG_NO_WILDCARDS 0x2 +/* Wildcards must not match a partial label. */ +#define X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS 0x4 +/* Allow (non-partial) wildcards to match multiple labels. */ +#define X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS 0x8 +/* Constraint verifier subdomain patterns to match a single labels. */ +#define X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS 0x10 +/* + * Match reference identifiers starting with "." to any sub-domain. + * This is a non-public flag, turned on implicitly when the subject + * reference identity is a DNS name. + */ +#define _X509_CHECK_FLAG_DOT_SUBDOMAINS 0x8000 + +OPENSSL_EXPORT int X509_check_host(X509 *x, const char *chk, size_t chklen, + unsigned int flags, char **peername); +OPENSSL_EXPORT int X509_check_email(X509 *x, const char *chk, size_t chklen, + unsigned int flags); +OPENSSL_EXPORT int X509_check_ip(X509 *x, const unsigned char *chk, size_t chklen, + unsigned int flags); +OPENSSL_EXPORT int X509_check_ip_asc(X509 *x, const char *ipasc, unsigned int flags); + +OPENSSL_EXPORT ASN1_OCTET_STRING *a2i_IPADDRESS(const char *ipasc); +OPENSSL_EXPORT ASN1_OCTET_STRING *a2i_IPADDRESS_NC(const char *ipasc); +OPENSSL_EXPORT int a2i_ipadd(unsigned char *ipout, const char *ipasc); +OPENSSL_EXPORT int X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE)*dn_sk, + unsigned long chtype); + +OPENSSL_EXPORT void X509_POLICY_NODE_print(BIO *out, X509_POLICY_NODE *node, int indent); +DECLARE_STACK_OF(X509_POLICY_NODE) + +/* BEGIN ERROR CODES */ +/* The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. + */ +void ERR_load_X509V3_strings(void); + + +#ifdef __cplusplus +} +#endif +#define X509V3_R_BAD_IP_ADDRESS 100 +#define X509V3_R_BAD_OBJECT 101 +#define X509V3_R_BN_DEC2BN_ERROR 102 +#define X509V3_R_BN_TO_ASN1_INTEGER_ERROR 103 +#define X509V3_R_CANNOT_FIND_FREE_FUNCTION 104 +#define X509V3_R_DIRNAME_ERROR 105 +#define X509V3_R_DISTPOINT_ALREADY_SET 106 +#define X509V3_R_DUPLICATE_ZONE_ID 107 +#define X509V3_R_ERROR_CONVERTING_ZONE 108 +#define X509V3_R_ERROR_CREATING_EXTENSION 109 +#define X509V3_R_ERROR_IN_EXTENSION 110 +#define X509V3_R_EXPECTED_A_SECTION_NAME 111 +#define X509V3_R_EXTENSION_EXISTS 112 +#define X509V3_R_EXTENSION_NAME_ERROR 113 +#define X509V3_R_EXTENSION_NOT_FOUND 114 +#define X509V3_R_EXTENSION_SETTING_NOT_SUPPORTED 115 +#define X509V3_R_EXTENSION_VALUE_ERROR 116 +#define X509V3_R_ILLEGAL_EMPTY_EXTENSION 117 +#define X509V3_R_ILLEGAL_HEX_DIGIT 118 +#define X509V3_R_INCORRECT_POLICY_SYNTAX_TAG 119 +#define X509V3_R_INVALID_BOOLEAN_STRING 120 +#define X509V3_R_INVALID_EXTENSION_STRING 121 +#define X509V3_R_INVALID_MULTIPLE_RDNS 122 +#define X509V3_R_INVALID_NAME 123 +#define X509V3_R_INVALID_NULL_ARGUMENT 124 +#define X509V3_R_INVALID_NULL_NAME 125 +#define X509V3_R_INVALID_NULL_VALUE 126 +#define X509V3_R_INVALID_NUMBER 127 +#define X509V3_R_INVALID_NUMBERS 128 +#define X509V3_R_INVALID_OBJECT_IDENTIFIER 129 +#define X509V3_R_INVALID_OPTION 130 +#define X509V3_R_INVALID_POLICY_IDENTIFIER 131 +#define X509V3_R_INVALID_PROXY_POLICY_SETTING 132 +#define X509V3_R_INVALID_PURPOSE 133 +#define X509V3_R_INVALID_SECTION 134 +#define X509V3_R_INVALID_SYNTAX 135 +#define X509V3_R_ISSUER_DECODE_ERROR 136 +#define X509V3_R_MISSING_VALUE 137 +#define X509V3_R_NEED_ORGANIZATION_AND_NUMBERS 138 +#define X509V3_R_NO_CONFIG_DATABASE 139 +#define X509V3_R_NO_ISSUER_CERTIFICATE 140 +#define X509V3_R_NO_ISSUER_DETAILS 141 +#define X509V3_R_NO_POLICY_IDENTIFIER 142 +#define X509V3_R_NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED 143 +#define X509V3_R_NO_PUBLIC_KEY 144 +#define X509V3_R_NO_SUBJECT_DETAILS 145 +#define X509V3_R_ODD_NUMBER_OF_DIGITS 146 +#define X509V3_R_OPERATION_NOT_DEFINED 147 +#define X509V3_R_OTHERNAME_ERROR 148 +#define X509V3_R_POLICY_LANGUAGE_ALREADY_DEFINED 149 +#define X509V3_R_POLICY_PATH_LENGTH 150 +#define X509V3_R_POLICY_PATH_LENGTH_ALREADY_DEFINED 151 +#define X509V3_R_POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY 152 +#define X509V3_R_SECTION_NOT_FOUND 153 +#define X509V3_R_UNABLE_TO_GET_ISSUER_DETAILS 154 +#define X509V3_R_UNABLE_TO_GET_ISSUER_KEYID 155 +#define X509V3_R_UNKNOWN_BIT_STRING_ARGUMENT 156 +#define X509V3_R_UNKNOWN_EXTENSION 157 +#define X509V3_R_UNKNOWN_EXTENSION_NAME 158 +#define X509V3_R_UNKNOWN_OPTION 159 +#define X509V3_R_UNSUPPORTED_OPTION 160 +#define X509V3_R_UNSUPPORTED_TYPE 161 +#define X509V3_R_USER_TOO_LONG 162 + +#endif diff --git a/external/boringssl/ssl/CMakeLists.txt b/external/boringssl/ssl/CMakeLists.txt new file mode 100644 index 0000000000..2eddc50dfa --- /dev/null +++ b/external/boringssl/ssl/CMakeLists.txt @@ -0,0 +1,92 @@ +include_directories(../include) + +add_subdirectory(pqueue) + +set( + ssl_objects_dependencies + $ + PARENT_SCOPE +) + +add_library( + ssl-objects OBJECT + + custom_extensions.c + handshake_server.c + handshake_client.c + d1_both.c + d1_lib.c + d1_meth.c + d1_pkt.c + d1_srtp.c + dtls_record.c + s3_both.c + s3_enc.c + s3_lib.c + s3_meth.c + s3_pkt.c + ssl_aead_ctx.c + ssl_asn1.c + ssl_buffer.c + ssl_cert.c + ssl_cipher.c + ssl_ecdh.c + ssl_file.c + ssl_lib.c + ssl_rsa.c + ssl_session.c + ssl_stat.c + t1_enc.c + t1_lib.c + tls_record.c +) + +add_library( + ssl + + custom_extensions.c + handshake_server.c + handshake_client.c + d1_both.c + d1_lib.c + d1_meth.c + d1_pkt.c + d1_srtp.c + dtls_record.c + s3_both.c + s3_enc.c + s3_lib.c + s3_meth.c + s3_pkt.c + ssl_aead_ctx.c + ssl_asn1.c + ssl_buffer.c + ssl_cert.c + ssl_cipher.c + ssl_ecdh.c + ssl_file.c + ssl_lib.c + ssl_rsa.c + ssl_session.c + ssl_stat.c + t1_enc.c + t1_lib.c + tls_record.c + + $ +) + +target_link_libraries(ssl crypto) + +if(ENABLE_TESTS) +add_executable( + ssl_test + + ssl_test.cc + + $ +) + +target_link_libraries(ssl_test ssl crypto) +add_dependencies(all_tests ssl_test) +endif() diff --git a/external/boringssl/ssl/custom_extensions.c b/external/boringssl/ssl/custom_extensions.c new file mode 100644 index 0000000000..c94543d880 --- /dev/null +++ b/external/boringssl/ssl/custom_extensions.c @@ -0,0 +1,257 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include +#include + +#include +#include +#include +#include + +#include "internal.h" + + +void SSL_CUSTOM_EXTENSION_free(SSL_CUSTOM_EXTENSION *custom_extension) { + OPENSSL_free(custom_extension); +} + +static const SSL_CUSTOM_EXTENSION *custom_ext_find( + STACK_OF(SSL_CUSTOM_EXTENSION) *stack, + unsigned *out_index, uint16_t value) { + size_t i; + for (i = 0; i < sk_SSL_CUSTOM_EXTENSION_num(stack); i++) { + const SSL_CUSTOM_EXTENSION *ext = sk_SSL_CUSTOM_EXTENSION_value(stack, i); + if (ext->value == value) { + if (out_index != NULL) { + *out_index = i; + } + return ext; + } + } + + return NULL; +} + +/* default_add_callback is used as the |add_callback| when the user doesn't + * provide one. For servers, it does nothing while, for clients, it causes an + * empty extension to be included. */ +static int default_add_callback(SSL *ssl, unsigned extension_value, + const uint8_t **out, size_t *out_len, + int *out_alert_value, void *add_arg) { + if (ssl->server) { + return 0; + } + *out_len = 0; + return 1; +} + +static int custom_ext_add_hello(SSL *ssl, CBB *extensions) { + STACK_OF(SSL_CUSTOM_EXTENSION) *stack = ssl->ctx->client_custom_extensions; + if (ssl->server) { + stack = ssl->ctx->server_custom_extensions; + } + + if (stack == NULL) { + return 1; + } + + size_t i; + for (i = 0; i < sk_SSL_CUSTOM_EXTENSION_num(stack); i++) { + const SSL_CUSTOM_EXTENSION *ext = sk_SSL_CUSTOM_EXTENSION_value(stack, i); + + if (ssl->server && + !(ssl->s3->tmp.custom_extensions.received & (1u << i))) { + /* Servers cannot echo extensions that the client didn't send. */ + continue; + } + + const uint8_t *contents; + size_t contents_len; + int alert = SSL_AD_DECODE_ERROR; + CBB contents_cbb; + + switch (ext->add_callback(ssl, ext->value, &contents, &contents_len, &alert, + ext->add_arg)) { + case 1: + if (!CBB_add_u16(extensions, ext->value) || + !CBB_add_u16_length_prefixed(extensions, &contents_cbb) || + !CBB_add_bytes(&contents_cbb, contents, contents_len) || + !CBB_flush(extensions)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + ERR_add_error_dataf("extension: %u", (unsigned) ext->value); + if (ext->free_callback && 0 < contents_len) { + ext->free_callback(ssl, ext->value, contents, ext->add_arg); + } + return 0; + } + + if (ext->free_callback && 0 < contents_len) { + ext->free_callback(ssl, ext->value, contents, ext->add_arg); + } + + if (!ssl->server) { + assert((ssl->s3->tmp.custom_extensions.sent & (1u << i)) == 0); + ssl->s3->tmp.custom_extensions.sent |= (1u << i); + } + break; + + case 0: + break; + + default: + ssl3_send_alert(ssl, SSL3_AL_FATAL, alert); + OPENSSL_PUT_ERROR(SSL, SSL_R_CUSTOM_EXTENSION_ERROR); + ERR_add_error_dataf("extension: %u", (unsigned) ext->value); + return 0; + } + } + + return 1; +} + +int custom_ext_add_clienthello(SSL *ssl, CBB *extensions) { + return custom_ext_add_hello(ssl, extensions); +} + +int custom_ext_parse_serverhello(SSL *ssl, int *out_alert, uint16_t value, + const CBS *extension) { + unsigned index; + const SSL_CUSTOM_EXTENSION *ext = + custom_ext_find(ssl->ctx->client_custom_extensions, &index, value); + + if (/* Unknown extensions are not allowed in a ServerHello. */ + ext == NULL || + /* Also, if we didn't send the extension, that's also unacceptable. */ + !(ssl->s3->tmp.custom_extensions.sent & (1u << index))) { + OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION); + ERR_add_error_dataf("extension: %u", (unsigned)value); + *out_alert = SSL_AD_DECODE_ERROR; + return 0; + } + + if (ext->parse_callback != NULL && + !ext->parse_callback(ssl, value, CBS_data(extension), CBS_len(extension), + out_alert, ext->parse_arg)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_CUSTOM_EXTENSION_ERROR); + ERR_add_error_dataf("extension: %u", (unsigned)ext->value); + return 0; + } + + return 1; +} + +int custom_ext_parse_clienthello(SSL *ssl, int *out_alert, uint16_t value, + const CBS *extension) { + unsigned index; + const SSL_CUSTOM_EXTENSION *ext = + custom_ext_find(ssl->ctx->server_custom_extensions, &index, value); + + if (ext == NULL) { + return 1; + } + + assert((ssl->s3->tmp.custom_extensions.received & (1u << index)) == 0); + ssl->s3->tmp.custom_extensions.received |= (1u << index); + + if (ext->parse_callback && + !ext->parse_callback(ssl, value, CBS_data(extension), CBS_len(extension), + out_alert, ext->parse_arg)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_CUSTOM_EXTENSION_ERROR); + ERR_add_error_dataf("extension: %u", (unsigned)ext->value); + return 0; + } + + return 1; +} + +int custom_ext_add_serverhello(SSL *ssl, CBB *extensions) { + return custom_ext_add_hello(ssl, extensions); +} + +/* MAX_NUM_CUSTOM_EXTENSIONS is the maximum number of custom extensions that + * can be set on an |SSL_CTX|. It's determined by the size of the bitset used + * to track when an extension has been sent. */ +#define MAX_NUM_CUSTOM_EXTENSIONS \ + (sizeof(((struct ssl3_state_st *)NULL)->tmp.custom_extensions.sent) * 8) + +static int custom_ext_append(STACK_OF(SSL_CUSTOM_EXTENSION) **stack, + unsigned extension_value, + SSL_custom_ext_add_cb add_cb, + SSL_custom_ext_free_cb free_cb, void *add_arg, + SSL_custom_ext_parse_cb parse_cb, + void *parse_arg) { + if (add_cb == NULL || + 0xffff < extension_value || + SSL_extension_supported(extension_value) || + /* Specifying a free callback without an add callback is nonsensical + * and an error. */ + (*stack != NULL && + (MAX_NUM_CUSTOM_EXTENSIONS <= sk_SSL_CUSTOM_EXTENSION_num(*stack) || + custom_ext_find(*stack, NULL, extension_value) != NULL))) { + return 0; + } + + SSL_CUSTOM_EXTENSION *ext = OPENSSL_malloc(sizeof(SSL_CUSTOM_EXTENSION)); + if (ext == NULL) { + return 0; + } + ext->add_callback = add_cb; + ext->add_arg = add_arg; + ext->free_callback = free_cb; + ext->parse_callback = parse_cb; + ext->parse_arg = parse_arg; + ext->value = extension_value; + + if (*stack == NULL) { + *stack = sk_SSL_CUSTOM_EXTENSION_new_null(); + if (*stack == NULL) { + SSL_CUSTOM_EXTENSION_free(ext); + return 0; + } + } + + if (!sk_SSL_CUSTOM_EXTENSION_push(*stack, ext)) { + SSL_CUSTOM_EXTENSION_free(ext); + if (sk_SSL_CUSTOM_EXTENSION_num(*stack) == 0) { + sk_SSL_CUSTOM_EXTENSION_free(*stack); + *stack = NULL; + } + return 0; + } + + return 1; +} + +int SSL_CTX_add_client_custom_ext(SSL_CTX *ctx, unsigned extension_value, + SSL_custom_ext_add_cb add_cb, + SSL_custom_ext_free_cb free_cb, void *add_arg, + SSL_custom_ext_parse_cb parse_cb, + void *parse_arg) { + return custom_ext_append(&ctx->client_custom_extensions, extension_value, + add_cb ? add_cb : default_add_callback, free_cb, + add_arg, parse_cb, parse_arg); +} + +int SSL_CTX_add_server_custom_ext(SSL_CTX *ctx, unsigned extension_value, + SSL_custom_ext_add_cb add_cb, + SSL_custom_ext_free_cb free_cb, void *add_arg, + SSL_custom_ext_parse_cb parse_cb, + void *parse_arg) { + return custom_ext_append(&ctx->server_custom_extensions, extension_value, + add_cb ? add_cb : default_add_callback, free_cb, + add_arg, parse_cb, parse_arg); +} diff --git a/external/boringssl/ssl/d1_both.c b/external/boringssl/ssl/d1_both.c new file mode 100644 index 0000000000..78f566e5ba --- /dev/null +++ b/external/boringssl/ssl/d1_both.c @@ -0,0 +1,851 @@ +/* + * DTLS implementation written by Nagendra Modadugu + * (nagendra@cs.stanford.edu) for the OpenSSL project 2005. + */ +/* ==================================================================== + * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "internal.h" + + +/* TODO(davidben): 28 comes from the size of IP + UDP header. Is this reasonable + * for these values? Notably, why is kMinMTU a function of the transport + * protocol's overhead rather than, say, what's needed to hold a minimally-sized + * handshake fragment plus protocol overhead. */ + +/* kMinMTU is the minimum acceptable MTU value. */ +static const unsigned int kMinMTU = 256 - 28; + +/* kDefaultMTU is the default MTU value to use if neither the user nor + * the underlying BIO supplies one. */ +static const unsigned int kDefaultMTU = 1500 - 28; + +/* kMaxHandshakeBuffer is the maximum number of handshake messages ahead of the + * current one to buffer. */ +static const unsigned int kHandshakeBufferSize = 10; + +static hm_fragment *dtls1_hm_fragment_new(size_t frag_len, int reassembly) { + hm_fragment *frag = OPENSSL_malloc(sizeof(hm_fragment)); + if (frag == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + return NULL; + } + memset(frag, 0, sizeof(hm_fragment)); + + /* If the handshake message is empty, |frag->fragment| and |frag->reassembly| + * are NULL. */ + if (frag_len > 0) { + frag->fragment = OPENSSL_malloc(frag_len); + if (frag->fragment == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (reassembly) { + /* Initialize reassembly bitmask. */ + if (frag_len + 7 < frag_len) { + OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW); + goto err; + } + size_t bitmask_len = (frag_len + 7) / 8; + frag->reassembly = OPENSSL_malloc(bitmask_len); + if (frag->reassembly == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + goto err; + } + memset(frag->reassembly, 0, bitmask_len); + } + } + + return frag; + +err: + dtls1_hm_fragment_free(frag); + return NULL; +} + +void dtls1_hm_fragment_free(hm_fragment *frag) { + if (frag == NULL) { + return; + } + OPENSSL_free(frag->fragment); + OPENSSL_free(frag->reassembly); + OPENSSL_free(frag); +} + +#if !defined(inline) +#define inline __inline +#endif + +/* bit_range returns a |uint8_t| with bits |start|, inclusive, to |end|, + * exclusive, set. */ +static inline uint8_t bit_range(size_t start, size_t end) { + return (uint8_t)(~((1u << start) - 1) & ((1u << end) - 1)); +} + +/* dtls1_hm_fragment_mark marks bytes |start|, inclusive, to |end|, exclusive, + * as received in |frag|. If |frag| becomes complete, it clears + * |frag->reassembly|. The range must be within the bounds of |frag|'s message + * and |frag->reassembly| must not be NULL. */ +static void dtls1_hm_fragment_mark(hm_fragment *frag, size_t start, + size_t end) { + size_t i; + size_t msg_len = frag->msg_header.msg_len; + + if (frag->reassembly == NULL || start > end || end > msg_len) { + assert(0); + return; + } + /* A zero-length message will never have a pending reassembly. */ + assert(msg_len > 0); + + if ((start >> 3) == (end >> 3)) { + frag->reassembly[start >> 3] |= bit_range(start & 7, end & 7); + } else { + frag->reassembly[start >> 3] |= bit_range(start & 7, 8); + for (i = (start >> 3) + 1; i < (end >> 3); i++) { + frag->reassembly[i] = 0xff; + } + if ((end & 7) != 0) { + frag->reassembly[end >> 3] |= bit_range(0, end & 7); + } + } + + /* Check if the fragment is complete. */ + for (i = 0; i < (msg_len >> 3); i++) { + if (frag->reassembly[i] != 0xff) { + return; + } + } + if ((msg_len & 7) != 0 && + frag->reassembly[msg_len >> 3] != bit_range(0, msg_len & 7)) { + return; + } + + OPENSSL_free(frag->reassembly); + frag->reassembly = NULL; +} + +static void dtls1_update_mtu(SSL *ssl) { + /* TODO(davidben): What is this code doing and do we need it? */ + if (ssl->d1->mtu < dtls1_min_mtu() && + !(SSL_get_options(ssl) & SSL_OP_NO_QUERY_MTU)) { + long mtu = BIO_ctrl(ssl->wbio, BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL); + if (mtu >= 0 && mtu <= (1 << 30) && (unsigned)mtu >= dtls1_min_mtu()) { + ssl->d1->mtu = (unsigned)mtu; + } else { + ssl->d1->mtu = kDefaultMTU; + BIO_ctrl(ssl->wbio, BIO_CTRL_DGRAM_SET_MTU, ssl->d1->mtu, NULL); + } + } + + /* The MTU should be above the minimum now. */ + assert(ssl->d1->mtu >= dtls1_min_mtu()); +} + +/* dtls1_max_record_size returns the maximum record body length that may be + * written without exceeding the MTU. It accounts for any buffering installed on + * the write BIO. If no record may be written, it returns zero. */ +static size_t dtls1_max_record_size(SSL *ssl) { + size_t ret = ssl->d1->mtu; + + size_t overhead = ssl_max_seal_overhead(ssl); + if (ret <= overhead) { + return 0; + } + ret -= overhead; + + size_t pending = BIO_wpending(ssl->wbio); + if (ret <= pending) { + return 0; + } + ret -= pending; + + return ret; +} + +static int dtls1_write_change_cipher_spec(SSL *ssl, + enum dtls1_use_epoch_t use_epoch) { + dtls1_update_mtu(ssl); + + /* During the handshake, wbio is buffered to pack messages together. Flush the + * buffer if the ChangeCipherSpec would not fit in a packet. */ + if (dtls1_max_record_size(ssl) == 0) { + int ret = BIO_flush(ssl->wbio); + if (ret <= 0) { + ssl->rwstate = SSL_WRITING; + return ret; + } + } + + static const uint8_t kChangeCipherSpec[1] = {SSL3_MT_CCS}; + int ret = + dtls1_write_record(ssl, SSL3_RT_CHANGE_CIPHER_SPEC, kChangeCipherSpec, + sizeof(kChangeCipherSpec), use_epoch); + if (ret <= 0) { + return ret; + } + + ssl_do_msg_callback(ssl, 1 /* write */, ssl->version, + SSL3_RT_CHANGE_CIPHER_SPEC, kChangeCipherSpec, + sizeof(kChangeCipherSpec)); + return 1; +} + +int dtls1_do_handshake_write(SSL *ssl, enum dtls1_use_epoch_t use_epoch) { + dtls1_update_mtu(ssl); + + int ret = -1; + CBB cbb; + CBB_zero(&cbb); + /* Allocate a temporary buffer to hold the message fragments to avoid + * clobbering the message. */ + uint8_t *buf = OPENSSL_malloc(ssl->d1->mtu); + if (buf == NULL) { + goto err; + } + + /* Consume the message header. Fragments will have different headers + * prepended. */ + if (ssl->init_off == 0) { + ssl->init_off += DTLS1_HM_HEADER_LENGTH; + ssl->init_num -= DTLS1_HM_HEADER_LENGTH; + } + assert(ssl->init_off >= DTLS1_HM_HEADER_LENGTH); + + do { + /* During the handshake, wbio is buffered to pack messages together. Flush + * the buffer if there isn't enough room to make progress. */ + if (dtls1_max_record_size(ssl) < DTLS1_HM_HEADER_LENGTH + 1) { + int flush_ret = BIO_flush(ssl->wbio); + if (flush_ret <= 0) { + ssl->rwstate = SSL_WRITING; + ret = flush_ret; + goto err; + } + assert(BIO_wpending(ssl->wbio) == 0); + } + + size_t todo = dtls1_max_record_size(ssl); + if (todo < DTLS1_HM_HEADER_LENGTH + 1) { + /* To make forward progress, the MTU must, at minimum, fit the handshake + * header and one byte of handshake body. */ + OPENSSL_PUT_ERROR(SSL, SSL_R_MTU_TOO_SMALL); + goto err; + } + todo -= DTLS1_HM_HEADER_LENGTH; + + if (todo > (size_t)ssl->init_num) { + todo = ssl->init_num; + } + if (todo >= (1u << 24)) { + todo = (1u << 24) - 1; + } + + size_t len; + if (!CBB_init_fixed(&cbb, buf, ssl->d1->mtu) || + !CBB_add_u8(&cbb, ssl->d1->w_msg_hdr.type) || + !CBB_add_u24(&cbb, ssl->d1->w_msg_hdr.msg_len) || + !CBB_add_u16(&cbb, ssl->d1->w_msg_hdr.seq) || + !CBB_add_u24(&cbb, ssl->init_off - DTLS1_HM_HEADER_LENGTH) || + !CBB_add_u24(&cbb, todo) || + !CBB_add_bytes( + &cbb, (const uint8_t *)ssl->init_buf->data + ssl->init_off, todo) || + !CBB_finish(&cbb, NULL, &len)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + goto err; + } + + int write_ret = + dtls1_write_record(ssl, SSL3_RT_HANDSHAKE, buf, len, use_epoch); + if (write_ret <= 0) { + ret = write_ret; + goto err; + } + ssl->init_off += todo; + ssl->init_num -= todo; + } while (ssl->init_num > 0); + + ssl_do_msg_callback(ssl, 1 /* write */, ssl->version, SSL3_RT_HANDSHAKE, + ssl->init_buf->data, + (size_t)(ssl->init_off + ssl->init_num)); + + ssl->init_off = 0; + ssl->init_num = 0; + + ret = 1; + +err: + CBB_cleanup(&cbb); + OPENSSL_free(buf); + return ret; +} + +/* dtls1_is_next_message_complete returns one if the next handshake message is + * complete and zero otherwise. */ +static int dtls1_is_next_message_complete(SSL *ssl) { + pitem *item = pqueue_peek(ssl->d1->buffered_messages); + if (item == NULL) { + return 0; + } + + hm_fragment *frag = (hm_fragment *)item->data; + assert(ssl->d1->handshake_read_seq <= frag->msg_header.seq); + + return ssl->d1->handshake_read_seq == frag->msg_header.seq && + frag->reassembly == NULL; +} + +/* dtls1_get_buffered_message returns the buffered message corresponding to + * |msg_hdr|. If none exists, it creates a new one and inserts it in the + * queue. Otherwise, it checks |msg_hdr| is consistent with the existing one. It + * returns NULL on failure. The caller does not take ownership of the result. */ +static hm_fragment *dtls1_get_buffered_message( + SSL *ssl, const struct hm_header_st *msg_hdr) { + uint8_t seq64be[8]; + memset(seq64be, 0, sizeof(seq64be)); + seq64be[6] = (uint8_t)(msg_hdr->seq >> 8); + seq64be[7] = (uint8_t)msg_hdr->seq; + pitem *item = pqueue_find(ssl->d1->buffered_messages, seq64be); + + hm_fragment *frag; + if (item == NULL) { + /* This is the first fragment from this message. */ + frag = dtls1_hm_fragment_new(msg_hdr->msg_len, + 1 /* reassembly buffer needed */); + if (frag == NULL) { + return NULL; + } + memcpy(&frag->msg_header, msg_hdr, sizeof(*msg_hdr)); + item = pitem_new(seq64be, frag); + if (item == NULL) { + dtls1_hm_fragment_free(frag); + return NULL; + } + item = pqueue_insert(ssl->d1->buffered_messages, item); + /* |pqueue_insert| fails iff a duplicate item is inserted, but |item| cannot + * be a duplicate. */ + assert(item != NULL); + } else { + frag = item->data; + assert(frag->msg_header.seq == msg_hdr->seq); + if (frag->msg_header.type != msg_hdr->type || + frag->msg_header.msg_len != msg_hdr->msg_len) { + /* The new fragment must be compatible with the previous fragments from + * this message. */ + OPENSSL_PUT_ERROR(SSL, SSL_R_FRAGMENT_MISMATCH); + ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER); + return NULL; + } + } + return frag; +} + +/* dtls1_process_handshake_record reads a handshake record and processes it. It + * returns one if the record was successfully processed and 0 or -1 on error. */ +static int dtls1_process_handshake_record(SSL *ssl) { + SSL3_RECORD *rr = &ssl->s3->rrec; + +start: + if (rr->length == 0) { + int ret = dtls1_get_record(ssl); + if (ret <= 0) { + return ret; + } + } + + /* Cross-epoch records are discarded, but we may receive out-of-order + * application data between ChangeCipherSpec and Finished or a ChangeCipherSpec + * before the appropriate point in the handshake. Those must be silently + * discarded. + * + * However, only allow the out-of-order records in the correct epoch. + * Application data must come in the encrypted epoch, and ChangeCipherSpec in + * the unencrypted epoch (we never renegotiate). Other cases fall through and + * fail with a fatal error. */ + if ((rr->type == SSL3_RT_APPLICATION_DATA && + ssl->s3->aead_read_ctx != NULL) || + (rr->type == SSL3_RT_CHANGE_CIPHER_SPEC && + ssl->s3->aead_read_ctx == NULL)) { + rr->length = 0; + goto start; + } + + if (rr->type != SSL3_RT_HANDSHAKE) { + ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE); + OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD); + return -1; + } + + CBS cbs; + CBS_init(&cbs, rr->data, rr->length); + + while (CBS_len(&cbs) > 0) { + /* Read a handshake fragment. */ + struct hm_header_st msg_hdr; + CBS body; + if (!dtls1_parse_fragment(&cbs, &msg_hdr, &body)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_HANDSHAKE_RECORD); + ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + return -1; + } + + const size_t frag_off = msg_hdr.frag_off; + const size_t frag_len = msg_hdr.frag_len; + const size_t msg_len = msg_hdr.msg_len; + if (frag_off > msg_len || frag_off + frag_len < frag_off || + frag_off + frag_len > msg_len || + msg_len > ssl_max_handshake_message_len(ssl)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_EXCESSIVE_MESSAGE_SIZE); + ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER); + return -1; + } + + if (msg_hdr.seq < ssl->d1->handshake_read_seq || + msg_hdr.seq > + (unsigned)ssl->d1->handshake_read_seq + kHandshakeBufferSize) { + /* Ignore fragments from the past, or ones too far in the future. */ + continue; + } + + hm_fragment *frag = dtls1_get_buffered_message(ssl, &msg_hdr); + if (frag == NULL) { + return -1; + } + assert(frag->msg_header.msg_len == msg_len); + + if (frag->reassembly == NULL) { + /* The message is already assembled. */ + continue; + } + assert(msg_len > 0); + + /* Copy the body into the fragment. */ + memcpy(frag->fragment + frag_off, CBS_data(&body), CBS_len(&body)); + dtls1_hm_fragment_mark(frag, frag_off, frag_off + frag_len); + } + + rr->length = 0; + ssl_read_buffer_discard(ssl); + return 1; +} + +/* dtls1_get_message reads a handshake message of message type |msg_type| (any + * if |msg_type| == -1). Read an entire handshake message. Handshake messages + * arrive in fragments. */ +long dtls1_get_message(SSL *ssl, int msg_type, + enum ssl_hash_message_t hash_message, int *ok) { + pitem *item = NULL; + hm_fragment *frag = NULL; + int al; + + /* s3->tmp is used to store messages that are unexpected, caused + * by the absence of an optional handshake message */ + if (ssl->s3->tmp.reuse_message) { + /* A ssl_dont_hash_message call cannot be combined with reuse_message; the + * ssl_dont_hash_message would have to have been applied to the previous + * call. */ + assert(hash_message == ssl_hash_message); + ssl->s3->tmp.reuse_message = 0; + if (msg_type >= 0 && ssl->s3->tmp.message_type != msg_type) { + al = SSL_AD_UNEXPECTED_MESSAGE; + OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE); + goto f_err; + } + *ok = 1; + assert(ssl->init_buf->length >= DTLS1_HM_HEADER_LENGTH); + ssl->init_msg = (uint8_t *)ssl->init_buf->data + DTLS1_HM_HEADER_LENGTH; + ssl->init_num = (int)ssl->init_buf->length - DTLS1_HM_HEADER_LENGTH; + return ssl->init_num; + } + + /* Process handshake records until the next message is ready. */ + while (!dtls1_is_next_message_complete(ssl)) { + int ret = dtls1_process_handshake_record(ssl); + if (ret <= 0) { + *ok = 0; + return ret; + } + } + + /* Read out the next complete handshake message. */ + item = pqueue_pop(ssl->d1->buffered_messages); + assert(item != NULL); + frag = (hm_fragment *)item->data; + assert(ssl->d1->handshake_read_seq == frag->msg_header.seq); + assert(frag->reassembly == NULL); + + /* Reconstruct the assembled message. */ + CBB cbb; + CBB_zero(&cbb); + if (!BUF_MEM_reserve(ssl->init_buf, (size_t)frag->msg_header.msg_len + + DTLS1_HM_HEADER_LENGTH) || + !CBB_init_fixed(&cbb, (uint8_t *)ssl->init_buf->data, + ssl->init_buf->max) || + !CBB_add_u8(&cbb, frag->msg_header.type) || + !CBB_add_u24(&cbb, frag->msg_header.msg_len) || + !CBB_add_u16(&cbb, frag->msg_header.seq) || + !CBB_add_u24(&cbb, 0 /* frag_off */) || + !CBB_add_u24(&cbb, frag->msg_header.msg_len) || + !CBB_add_bytes(&cbb, frag->fragment, frag->msg_header.msg_len) || + !CBB_finish(&cbb, NULL, &ssl->init_buf->length)) { + CBB_cleanup(&cbb); + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + goto err; + } + assert(ssl->init_buf->length == + (size_t)frag->msg_header.msg_len + DTLS1_HM_HEADER_LENGTH); + + ssl->d1->handshake_read_seq++; + + /* TODO(davidben): This function has a lot of implicit outputs. Simplify the + * |ssl_get_message| API. */ + ssl->s3->tmp.message_type = frag->msg_header.type; + ssl->init_msg = (uint8_t *)ssl->init_buf->data + DTLS1_HM_HEADER_LENGTH; + ssl->init_num = frag->msg_header.msg_len; + + if (msg_type >= 0 && ssl->s3->tmp.message_type != msg_type) { + al = SSL_AD_UNEXPECTED_MESSAGE; + OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE); + goto f_err; + } + if (hash_message == ssl_hash_message && !ssl3_hash_current_message(ssl)) { + goto err; + } + + ssl_do_msg_callback(ssl, 0 /* read */, ssl->version, SSL3_RT_HANDSHAKE, + ssl->init_buf->data, + ssl->init_num + DTLS1_HM_HEADER_LENGTH); + + pitem_free(item); + dtls1_hm_fragment_free(frag); + + *ok = 1; + return ssl->init_num; + +f_err: + ssl3_send_alert(ssl, SSL3_AL_FATAL, al); +err: + pitem_free(item); + dtls1_hm_fragment_free(frag); + *ok = 0; + return -1; +} + +static uint16_t dtls1_get_queue_priority(uint16_t seq, int is_ccs) { + assert(seq * 2 >= seq); + + /* The index of the retransmission queue actually is the message sequence + * number, since the queue only contains messages of a single handshake. + * However, the ChangeCipherSpec has no message sequence number and so using + * only the sequence will result in the CCS and Finished having the same + * index. To prevent this, the sequence number is multiplied by 2. In case of + * a CCS 1 is subtracted. This does not only differ CSS and Finished, it also + * maintains the order of the index (important for priority queues) and fits + * in the unsigned short variable. */ + return seq * 2 - is_ccs; +} + +static int dtls1_retransmit_message(SSL *ssl, hm_fragment *frag) { + /* DTLS renegotiation is unsupported, so only epochs 0 (NULL cipher) and 1 + * (negotiated cipher) exist. */ + assert(ssl->d1->w_epoch == 0 || ssl->d1->w_epoch == 1); + assert(frag->msg_header.epoch <= ssl->d1->w_epoch); + enum dtls1_use_epoch_t use_epoch = dtls1_use_current_epoch; + if (ssl->d1->w_epoch == 1 && frag->msg_header.epoch == 0) { + use_epoch = dtls1_use_previous_epoch; + } + + /* TODO(davidben): This cannot handle non-blocking writes. */ + int ret; + if (frag->msg_header.is_ccs) { + ret = dtls1_write_change_cipher_spec(ssl, use_epoch); + } else { + /* Restore the message body. + * TODO(davidben): Make this less stateful. */ + memcpy(ssl->init_buf->data, frag->fragment, + frag->msg_header.msg_len + DTLS1_HM_HEADER_LENGTH); + ssl->init_num = frag->msg_header.msg_len + DTLS1_HM_HEADER_LENGTH; + + dtls1_set_message_header(ssl, frag->msg_header.type, + frag->msg_header.msg_len, frag->msg_header.seq, + 0, frag->msg_header.frag_len); + ret = dtls1_do_handshake_write(ssl, use_epoch); + } + + return ret; +} + +int dtls1_retransmit_buffered_messages(SSL *ssl) { + /* Ensure we are packing handshake messages. */ + const int was_buffered = ssl_is_wbio_buffered(ssl); + assert(was_buffered == SSL_in_init(ssl)); + if (!was_buffered && !ssl_init_wbio_buffer(ssl)) { + return -1; + } + assert(ssl_is_wbio_buffered(ssl)); + + int ret = -1; + piterator iter = pqueue_iterator(ssl->d1->sent_messages); + pitem *item; + for (item = pqueue_next(&iter); item != NULL; item = pqueue_next(&iter)) { + hm_fragment *frag = (hm_fragment *)item->data; + if (dtls1_retransmit_message(ssl, frag) <= 0) { + goto err; + } + } + + ret = BIO_flush(ssl->wbio); + if (ret <= 0) { + ssl->rwstate = SSL_WRITING; + goto err; + } + +err: + if (!was_buffered) { + ssl_free_wbio_buffer(ssl); + } + return ret; +} + +/* dtls1_buffer_change_cipher_spec adds a ChangeCipherSpec to the current + * handshake flight, ordered just before the handshake message numbered + * |seq|. */ +static int dtls1_buffer_change_cipher_spec(SSL *ssl, uint16_t seq) { + hm_fragment *frag = dtls1_hm_fragment_new(0 /* frag_len */, + 0 /* no reassembly */); + if (frag == NULL) { + return 0; + } + frag->msg_header.is_ccs = 1; + frag->msg_header.epoch = ssl->d1->w_epoch; + + uint16_t priority = dtls1_get_queue_priority(seq, 1 /* is_ccs */); + uint8_t seq64be[8]; + memset(seq64be, 0, sizeof(seq64be)); + seq64be[6] = (uint8_t)(priority >> 8); + seq64be[7] = (uint8_t)priority; + + pitem *item = pitem_new(seq64be, frag); + if (item == NULL) { + dtls1_hm_fragment_free(frag); + return 0; + } + + pqueue_insert(ssl->d1->sent_messages, item); + return 1; +} + +int dtls1_buffer_message(SSL *ssl) { + /* this function is called immediately after a message has + * been serialized */ + assert(ssl->init_off == 0); + + hm_fragment *frag = dtls1_hm_fragment_new(ssl->init_num, 0); + if (!frag) { + return 0; + } + + memcpy(frag->fragment, ssl->init_buf->data, ssl->init_num); + + assert(ssl->d1->w_msg_hdr.msg_len + DTLS1_HM_HEADER_LENGTH == + (unsigned int)ssl->init_num); + + frag->msg_header.msg_len = ssl->d1->w_msg_hdr.msg_len; + frag->msg_header.seq = ssl->d1->w_msg_hdr.seq; + frag->msg_header.type = ssl->d1->w_msg_hdr.type; + frag->msg_header.frag_off = 0; + frag->msg_header.frag_len = ssl->d1->w_msg_hdr.msg_len; + frag->msg_header.is_ccs = 0; + frag->msg_header.epoch = ssl->d1->w_epoch; + + uint16_t priority = dtls1_get_queue_priority(frag->msg_header.seq, + 0 /* handshake */); + uint8_t seq64be[8]; + memset(seq64be, 0, sizeof(seq64be)); + seq64be[6] = (uint8_t)(priority >> 8); + seq64be[7] = (uint8_t)priority; + + pitem *item = pitem_new(seq64be, frag); + if (item == NULL) { + dtls1_hm_fragment_free(frag); + return 0; + } + + pqueue_insert(ssl->d1->sent_messages, item); + return 1; +} + +int dtls1_send_change_cipher_spec(SSL *ssl, int a, int b) { + if (ssl->state == a) { + /* Buffer the message to handle retransmits. */ + ssl->d1->handshake_write_seq = ssl->d1->next_handshake_write_seq; + dtls1_buffer_change_cipher_spec(ssl, ssl->d1->handshake_write_seq); + ssl->state = b; + } + + return dtls1_write_change_cipher_spec(ssl, dtls1_use_current_epoch); +} + +/* call this function when the buffered messages are no longer needed */ +void dtls1_clear_record_buffer(SSL *ssl) { + pitem *item; + + for (item = pqueue_pop(ssl->d1->sent_messages); item != NULL; + item = pqueue_pop(ssl->d1->sent_messages)) { + dtls1_hm_fragment_free((hm_fragment *)item->data); + pitem_free(item); + } +} + +/* don't actually do the writing, wait till the MTU has been retrieved */ +void dtls1_set_message_header(SSL *ssl, uint8_t mt, unsigned long len, + unsigned short seq_num, unsigned long frag_off, + unsigned long frag_len) { + struct hm_header_st *msg_hdr = &ssl->d1->w_msg_hdr; + + msg_hdr->type = mt; + msg_hdr->msg_len = len; + msg_hdr->seq = seq_num; + msg_hdr->frag_off = frag_off; + msg_hdr->frag_len = frag_len; +} + +unsigned int dtls1_min_mtu(void) { + return kMinMTU; +} + +int dtls1_parse_fragment(CBS *cbs, struct hm_header_st *out_hdr, + CBS *out_body) { + memset(out_hdr, 0x00, sizeof(struct hm_header_st)); + + if (!CBS_get_u8(cbs, &out_hdr->type) || + !CBS_get_u24(cbs, &out_hdr->msg_len) || + !CBS_get_u16(cbs, &out_hdr->seq) || + !CBS_get_u24(cbs, &out_hdr->frag_off) || + !CBS_get_u24(cbs, &out_hdr->frag_len) || + !CBS_get_bytes(cbs, out_body, out_hdr->frag_len)) { + return 0; + } + + return 1; +} diff --git a/external/boringssl/ssl/d1_lib.c b/external/boringssl/ssl/d1_lib.c new file mode 100644 index 0000000000..73ae4cfd0b --- /dev/null +++ b/external/boringssl/ssl/d1_lib.c @@ -0,0 +1,360 @@ +/* + * DTLS implementation written by Nagendra Modadugu + * (nagendra@cs.stanford.edu) for the OpenSSL project 2005. + */ +/* ==================================================================== + * Copyright (c) 1999-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include + +#include +#include +#include + +#include "internal.h" + +#if defined(OPENSSL_WINDOWS) +#include +#else +#include +#include +#endif + + +/* DTLS1_MTU_TIMEOUTS is the maximum number of timeouts to expire + * before starting to decrease the MTU. */ +#define DTLS1_MTU_TIMEOUTS 2 + +/* DTLS1_MAX_TIMEOUTS is the maximum number of timeouts to expire + * before failing the DTLS handshake. */ +#define DTLS1_MAX_TIMEOUTS 12 + +static void get_current_time(const SSL *ssl, struct timeval *out_clock); + +int dtls1_new(SSL *ssl) { + DTLS1_STATE *d1; + + if (!ssl3_new(ssl)) { + return 0; + } + d1 = OPENSSL_malloc(sizeof *d1); + if (d1 == NULL) { + ssl3_free(ssl); + return 0; + } + memset(d1, 0, sizeof *d1); + + d1->buffered_messages = pqueue_new(); + d1->sent_messages = pqueue_new(); + + if (!d1->buffered_messages || !d1->sent_messages) { + pqueue_free(d1->buffered_messages); + pqueue_free(d1->sent_messages); + OPENSSL_free(d1); + ssl3_free(ssl); + return 0; + } + + ssl->d1 = d1; + + /* Set the version to the highest supported version. + * + * TODO(davidben): Move this field into |s3|, have it store the normalized + * protocol version, and implement this pre-negotiation quirk in |SSL_version| + * at the API boundary rather than in internal state. */ + ssl->version = DTLS1_2_VERSION; + return 1; +} + +static void dtls1_clear_queues(SSL *ssl) { + pitem *item = NULL; + hm_fragment *frag = NULL; + + while ((item = pqueue_pop(ssl->d1->buffered_messages)) != NULL) { + frag = (hm_fragment *)item->data; + dtls1_hm_fragment_free(frag); + pitem_free(item); + } + + while ((item = pqueue_pop(ssl->d1->sent_messages)) != NULL) { + frag = (hm_fragment *)item->data; + dtls1_hm_fragment_free(frag); + pitem_free(item); + } +} + +void dtls1_free(SSL *ssl) { + ssl3_free(ssl); + + if (ssl == NULL || ssl->d1 == NULL) { + return; + } + + dtls1_clear_queues(ssl); + + pqueue_free(ssl->d1->buffered_messages); + pqueue_free(ssl->d1->sent_messages); + + OPENSSL_free(ssl->d1); + ssl->d1 = NULL; +} + +int dtls1_supports_cipher(const SSL_CIPHER *cipher) { + /* DTLS does not support stream ciphers. The NULL cipher is rejected because + * it's not needed. */ + return cipher->algorithm_enc != SSL_RC4 && cipher->algorithm_enc != SSL_eNULL; +} + +void DTLSv1_set_initial_timeout_duration(SSL *ssl, unsigned int duration_ms) { + ssl->initial_timeout_duration_ms = duration_ms; +} + +void dtls1_start_timer(SSL *ssl) { + /* If timer is not set, initialize duration (by default, 1 second) */ + if (ssl->d1->next_timeout.tv_sec == 0 && ssl->d1->next_timeout.tv_usec == 0) { + ssl->d1->timeout_duration_ms = ssl->initial_timeout_duration_ms; + } + + /* Set timeout to current time */ + get_current_time(ssl, &ssl->d1->next_timeout); + + /* Add duration to current time */ + ssl->d1->next_timeout.tv_sec += ssl->d1->timeout_duration_ms / 1000; + ssl->d1->next_timeout.tv_usec += (ssl->d1->timeout_duration_ms % 1000) * 1000; + if (ssl->d1->next_timeout.tv_usec >= 1000000) { + ssl->d1->next_timeout.tv_sec++; + ssl->d1->next_timeout.tv_usec -= 1000000; + } + BIO_ctrl(ssl->rbio, BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0, + &ssl->d1->next_timeout); +} + +int DTLSv1_get_timeout(const SSL *ssl, struct timeval *out) { + if (!SSL_IS_DTLS(ssl)) { + return 0; + } + + /* If no timeout is set, just return NULL */ + if (ssl->d1->next_timeout.tv_sec == 0 && ssl->d1->next_timeout.tv_usec == 0) { + return 0; + } + + /* Get current time */ + struct timeval timenow; + get_current_time(ssl, &timenow); + + /* If timer already expired, set remaining time to 0 */ + if (ssl->d1->next_timeout.tv_sec < timenow.tv_sec || + (ssl->d1->next_timeout.tv_sec == timenow.tv_sec && + ssl->d1->next_timeout.tv_usec <= timenow.tv_usec)) { + memset(out, 0, sizeof(struct timeval)); + return 1; + } + + /* Calculate time left until timer expires */ + memcpy(out, &ssl->d1->next_timeout, sizeof(struct timeval)); + out->tv_sec -= timenow.tv_sec; + out->tv_usec -= timenow.tv_usec; + if (out->tv_usec < 0) { + out->tv_sec--; + out->tv_usec += 1000000; + } + + /* If remaining time is less than 15 ms, set it to 0 to prevent issues + * because of small devergences with socket timeouts. */ + if (out->tv_sec == 0 && out->tv_usec < 15000) { + memset(out, 0, sizeof(struct timeval)); + } + + return 1; +} + +int dtls1_is_timer_expired(SSL *ssl) { + struct timeval timeleft; + + /* Get time left until timeout, return false if no timer running */ + if (!DTLSv1_get_timeout(ssl, &timeleft)) { + return 0; + } + + /* Return false if timer is not expired yet */ + if (timeleft.tv_sec > 0 || timeleft.tv_usec > 0) { + return 0; + } + + /* Timer expired, so return true */ + return 1; +} + +void dtls1_double_timeout(SSL *ssl) { + ssl->d1->timeout_duration_ms *= 2; + if (ssl->d1->timeout_duration_ms > 60000) { + ssl->d1->timeout_duration_ms = 60000; + } + dtls1_start_timer(ssl); +} + +void dtls1_stop_timer(SSL *ssl) { + /* Reset everything */ + ssl->d1->num_timeouts = 0; + memset(&ssl->d1->next_timeout, 0, sizeof(struct timeval)); + ssl->d1->timeout_duration_ms = ssl->initial_timeout_duration_ms; + BIO_ctrl(ssl->rbio, BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0, + &ssl->d1->next_timeout); + /* Clear retransmission buffer */ + dtls1_clear_record_buffer(ssl); +} + +int dtls1_check_timeout_num(SSL *ssl) { + ssl->d1->num_timeouts++; + + /* Reduce MTU after 2 unsuccessful retransmissions */ + if (ssl->d1->num_timeouts > DTLS1_MTU_TIMEOUTS && + !(SSL_get_options(ssl) & SSL_OP_NO_QUERY_MTU)) { + long mtu = BIO_ctrl(ssl->wbio, BIO_CTRL_DGRAM_GET_FALLBACK_MTU, 0, NULL); + if (mtu >= 0 && mtu <= (1 << 30) && (unsigned)mtu >= dtls1_min_mtu()) { + ssl->d1->mtu = (unsigned)mtu; + } + } + + if (ssl->d1->num_timeouts > DTLS1_MAX_TIMEOUTS) { + /* fail the connection, enough alerts have been sent */ + OPENSSL_PUT_ERROR(SSL, SSL_R_READ_TIMEOUT_EXPIRED); + return -1; + } + + return 0; +} + +int DTLSv1_handle_timeout(SSL *ssl) { + ssl->rwstate = SSL_NOTHING; + /* Functions which use SSL_get_error must clear the error queue on entry. */ + ERR_clear_error(); + + if (!SSL_IS_DTLS(ssl)) { + return -1; + } + + /* if no timer is expired, don't do anything */ + if (!dtls1_is_timer_expired(ssl)) { + return 0; + } + + dtls1_double_timeout(ssl); + + if (dtls1_check_timeout_num(ssl) < 0) { + return -1; + } + + dtls1_start_timer(ssl); + return dtls1_retransmit_buffered_messages(ssl); +} + +static void get_current_time(const SSL *ssl, struct timeval *out_clock) { + if (ssl->ctx->current_time_cb != NULL) { + ssl->ctx->current_time_cb(ssl, out_clock); + return; + } + +#if defined(OPENSSL_WINDOWS) + struct _timeb time; + _ftime(&time); + out_clock->tv_sec = time.time; + out_clock->tv_usec = time.millitm * 1000; +#else + gettimeofday(out_clock, NULL); +#endif +} + +int dtls1_set_handshake_header(SSL *ssl, int htype, unsigned long len) { + uint8_t *message = (uint8_t *)ssl->init_buf->data; + const struct hm_header_st *msg_hdr = &ssl->d1->w_msg_hdr; + uint8_t serialised_header[DTLS1_HM_HEADER_LENGTH]; + uint8_t *p = serialised_header; + + ssl->d1->handshake_write_seq = ssl->d1->next_handshake_write_seq; + ssl->d1->next_handshake_write_seq++; + + dtls1_set_message_header(ssl, htype, len, ssl->d1->handshake_write_seq, 0, + len); + ssl->init_num = (int)len + DTLS1_HM_HEADER_LENGTH; + ssl->init_off = 0; + + /* Buffer the message to handle re-xmits */ + dtls1_buffer_message(ssl); + + /* Add the new message to the handshake hash. Serialize the message + * header as if it were a single fragment. */ + *p++ = msg_hdr->type; + l2n3(msg_hdr->msg_len, p); + s2n(msg_hdr->seq, p); + l2n3(0, p); + l2n3(msg_hdr->msg_len, p); + return ssl3_update_handshake_hash(ssl, serialised_header, + sizeof(serialised_header)) && + ssl3_update_handshake_hash(ssl, message + DTLS1_HM_HEADER_LENGTH, len); +} + +int dtls1_handshake_write(SSL *ssl) { + return dtls1_do_handshake_write(ssl, dtls1_use_current_epoch); +} + +void dtls1_expect_flight(SSL *ssl) { + dtls1_start_timer(ssl); +} + +void dtls1_received_flight(SSL *ssl) { + dtls1_stop_timer(ssl); +} diff --git a/external/boringssl/ssl/d1_meth.c b/external/boringssl/ssl/d1_meth.c new file mode 100644 index 0000000000..32a4651acf --- /dev/null +++ b/external/boringssl/ssl/d1_meth.c @@ -0,0 +1,131 @@ +/* + * DTLS implementation written by Nagendra Modadugu + * (nagendra@cs.stanford.edu) for the OpenSSL project 2005. + */ +/* ==================================================================== + * Copyright (c) 1999-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include "internal.h" + + +static const SSL_PROTOCOL_METHOD DTLS_protocol_method = { + 1 /* is_dtls */, + dtls1_new, + dtls1_free, + dtls1_get_message, + dtls1_read_app_data, + dtls1_read_change_cipher_spec, + dtls1_read_close_notify, + dtls1_write_app_data, + dtls1_dispatch_alert, + dtls1_supports_cipher, + DTLS1_HM_HEADER_LENGTH, + dtls1_set_handshake_header, + dtls1_handshake_write, + dtls1_send_change_cipher_spec, + dtls1_expect_flight, + dtls1_received_flight, +}; + +const SSL_METHOD *DTLS_method(void) { + static const SSL_METHOD method = { + 0, + &DTLS_protocol_method, + }; + return &method; +} + +/* Legacy version-locked methods. */ + +const SSL_METHOD *DTLSv1_2_method(void) { + static const SSL_METHOD method = { + DTLS1_2_VERSION, + &DTLS_protocol_method, + }; + return &method; +} + +const SSL_METHOD *DTLSv1_method(void) { + static const SSL_METHOD method = { + DTLS1_VERSION, + &DTLS_protocol_method, + }; + return &method; +} + +/* Legacy side-specific methods. */ + +const SSL_METHOD *DTLSv1_2_server_method(void) { + return DTLSv1_2_method(); +} + +const SSL_METHOD *DTLSv1_server_method(void) { + return DTLSv1_method(); +} + +const SSL_METHOD *DTLSv1_2_client_method(void) { + return DTLSv1_2_method(); +} + +const SSL_METHOD *DTLSv1_client_method(void) { + return DTLSv1_method(); +} + +const SSL_METHOD *DTLS_server_method(void) { + return DTLS_method(); +} + +const SSL_METHOD *DTLS_client_method(void) { + return DTLS_method(); +} diff --git a/external/boringssl/ssl/d1_pkt.c b/external/boringssl/ssl/d1_pkt.c new file mode 100644 index 0000000000..b821ab3171 --- /dev/null +++ b/external/boringssl/ssl/d1_pkt.c @@ -0,0 +1,416 @@ +/* DTLS implementation written by Nagendra Modadugu + * (nagendra@cs.stanford.edu) for the OpenSSL project 2005. */ +/* ==================================================================== + * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "internal.h" + + +int dtls1_get_record(SSL *ssl) { +again: + switch (ssl->s3->recv_shutdown) { + case ssl_shutdown_none: + break; + case ssl_shutdown_fatal_alert: + OPENSSL_PUT_ERROR(SSL, SSL_R_PROTOCOL_IS_SHUTDOWN); + return -1; + case ssl_shutdown_close_notify: + return 0; + } + + /* Read a new packet if there is no unconsumed one. */ + if (ssl_read_buffer_len(ssl) == 0) { + int read_ret = ssl_read_buffer_extend_to(ssl, 0 /* unused */); + if (read_ret < 0 && dtls1_is_timer_expired(ssl)) { + /* For blocking BIOs, retransmits must be handled internally. */ + int timeout_ret = DTLSv1_handle_timeout(ssl); + if (timeout_ret <= 0) { + return timeout_ret; + } + goto again; + } + if (read_ret <= 0) { + return read_ret; + } + } + assert(ssl_read_buffer_len(ssl) > 0); + + CBS body; + uint8_t type, alert; + size_t consumed; + enum ssl_open_record_t open_ret = + dtls_open_record(ssl, &type, &body, &consumed, &alert, + ssl_read_buffer(ssl), ssl_read_buffer_len(ssl)); + ssl_read_buffer_consume(ssl, consumed); + switch (open_ret) { + case ssl_open_record_partial: + /* Impossible in DTLS. */ + break; + + case ssl_open_record_success: + if (CBS_len(&body) > 0xffff) { + OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW); + return -1; + } + + SSL3_RECORD *rr = &ssl->s3->rrec; + rr->type = type; + rr->length = (uint16_t)CBS_len(&body); + rr->data = (uint8_t *)CBS_data(&body); + return 1; + + case ssl_open_record_discard: + goto again; + + case ssl_open_record_close_notify: + return 0; + + case ssl_open_record_fatal_alert: + return -1; + + case ssl_open_record_error: + ssl3_send_alert(ssl, SSL3_AL_FATAL, alert); + return -1; + } + + assert(0); + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + return -1; +} + +int dtls1_read_app_data(SSL *ssl, uint8_t *buf, int len, int peek) { + assert(!SSL_in_init(ssl)); + + SSL3_RECORD *rr = &ssl->s3->rrec; + +again: + if (rr->length == 0) { + int ret = dtls1_get_record(ssl); + if (ret <= 0) { + return ret; + } + } + + if (rr->type == SSL3_RT_HANDSHAKE) { + /* Parse the first fragment header to determine if this is a pre-CCS or + * post-CCS handshake record. DTLS resets handshake message numbers on each + * handshake, so renegotiations and retransmissions are ambiguous. */ + CBS cbs, body; + struct hm_header_st msg_hdr; + CBS_init(&cbs, rr->data, rr->length); + if (!dtls1_parse_fragment(&cbs, &msg_hdr, &body)) { + ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_HANDSHAKE_RECORD); + return -1; + } + + if (msg_hdr.type == SSL3_MT_FINISHED) { + if (msg_hdr.frag_off == 0) { + /* Retransmit our last flight of messages. If the peer sends the second + * Finished, they may not have received ours. Only do this for the + * first fragment, in case the Finished was fragmented. */ + if (dtls1_check_timeout_num(ssl) < 0) { + return -1; + } + + dtls1_retransmit_buffered_messages(ssl); + } + + rr->length = 0; + goto again; + } + + /* Otherwise, this is a pre-CCS handshake message from an unsupported + * renegotiation attempt. Fall through to the error path. */ + } + + if (rr->type != SSL3_RT_APPLICATION_DATA) { + ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE); + OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD); + return -1; + } + + /* Discard empty records. */ + if (rr->length == 0) { + goto again; + } + + if (len <= 0) { + return len; + } + + if ((unsigned)len > rr->length) { + len = rr->length; + } + + memcpy(buf, rr->data, len); + if (!peek) { + /* TODO(davidben): Should the record be truncated instead? This is a + * datagram transport. See https://crbug.com/boringssl/65. */ + rr->length -= len; + rr->data += len; + if (rr->length == 0) { + /* The record has been consumed, so we may now clear the buffer. */ + ssl_read_buffer_discard(ssl); + } + } + + return len; +} + +int dtls1_read_change_cipher_spec(SSL *ssl) { + SSL3_RECORD *rr = &ssl->s3->rrec; + +again: + if (rr->length == 0) { + int ret = dtls1_get_record(ssl); + if (ret <= 0) { + return ret; + } + } + + /* Drop handshake records silently. The epochs match, so this must be a + * retransmit of a message we already received. */ + if (rr->type == SSL3_RT_HANDSHAKE) { + rr->length = 0; + goto again; + } + + /* Other record types are illegal in this epoch. Note all application data + * records come in the encrypted epoch. */ + if (rr->type != SSL3_RT_CHANGE_CIPHER_SPEC) { + ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE); + OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD); + return -1; + } + + if (rr->length != 1 || rr->data[0] != SSL3_MT_CCS) { + OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_CHANGE_CIPHER_SPEC); + ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER); + return -1; + } + + ssl_do_msg_callback(ssl, 0 /* read */, ssl->version, + SSL3_RT_CHANGE_CIPHER_SPEC, rr->data, rr->length); + + rr->length = 0; + ssl_read_buffer_discard(ssl); + return 1; +} + +void dtls1_read_close_notify(SSL *ssl) { + /* Bidirectional shutdown doesn't make sense for an unordered transport. DTLS + * alerts also aren't delivered reliably, so we may even time out because the + * peer never received our close_notify. Report to the caller that the channel + * has fully shut down. */ + if (ssl->s3->recv_shutdown == ssl_shutdown_none) { + ssl->s3->recv_shutdown = ssl_shutdown_close_notify; + } +} + +int dtls1_write_app_data(SSL *ssl, const void *buf_, int len) { + assert(!SSL_in_init(ssl)); + + if (len > SSL3_RT_MAX_PLAIN_LENGTH) { + OPENSSL_PUT_ERROR(SSL, SSL_R_DTLS_MESSAGE_TOO_BIG); + return -1; + } + + if (len < 0) { + OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_LENGTH); + return -1; + } + + if (len == 0) { + return 0; + } + + int ret = dtls1_write_record(ssl, SSL3_RT_APPLICATION_DATA, buf_, (size_t)len, + dtls1_use_current_epoch); + if (ret <= 0) { + return ret; + } + return len; +} + +int dtls1_write_record(SSL *ssl, int type, const uint8_t *buf, size_t len, + enum dtls1_use_epoch_t use_epoch) { + assert(len <= SSL3_RT_MAX_PLAIN_LENGTH); + /* There should never be a pending write buffer in DTLS. One can't write half + * a datagram, so the write buffer is always dropped in + * |ssl_write_buffer_flush|. */ + assert(!ssl_write_buffer_is_pending(ssl)); + + /* If we have an alert to send, lets send it */ + if (ssl->s3->alert_dispatch) { + int ret = ssl->method->ssl_dispatch_alert(ssl); + if (ret <= 0) { + return ret; + } + /* if it went, fall through and send more stuff */ + } + + if (len > SSL3_RT_MAX_PLAIN_LENGTH) { + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + return -1; + } + + size_t max_out = len + ssl_max_seal_overhead(ssl); + uint8_t *out; + size_t ciphertext_len; + if (!ssl_write_buffer_init(ssl, &out, max_out) || + !dtls_seal_record(ssl, out, &ciphertext_len, max_out, type, buf, len, + use_epoch)) { + ssl_write_buffer_clear(ssl); + return -1; + } + ssl_write_buffer_set_len(ssl, ciphertext_len); + + int ret = ssl_write_buffer_flush(ssl); + if (ret <= 0) { + return ret; + } + return 1; +} + +int dtls1_dispatch_alert(SSL *ssl) { + ssl->s3->alert_dispatch = 0; + int ret = dtls1_write_record(ssl, SSL3_RT_ALERT, &ssl->s3->send_alert[0], 2, + dtls1_use_current_epoch); + if (ret <= 0) { + ssl->s3->alert_dispatch = 1; + return ret; + } + + /* If the alert is fatal, flush the BIO now. */ + if (ssl->s3->send_alert[0] == SSL3_AL_FATAL) { + BIO_flush(ssl->wbio); + } + + ssl_do_msg_callback(ssl, 1 /* write */, ssl->version, SSL3_RT_ALERT, + ssl->s3->send_alert, 2); + + int alert = (ssl->s3->send_alert[0] << 8) | ssl->s3->send_alert[1]; + ssl_do_info_callback(ssl, SSL_CB_WRITE_ALERT, alert); + + return 1; +} diff --git a/external/boringssl/ssl/d1_srtp.c b/external/boringssl/ssl/d1_srtp.c new file mode 100644 index 0000000000..324bff7713 --- /dev/null +++ b/external/boringssl/ssl/d1_srtp.c @@ -0,0 +1,233 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* + DTLS code by Eric Rescorla + + Copyright (C) 2006, Network Resonance, Inc. + Copyright (C) 2011, RTFM, Inc. +*/ + +#include + +#include + +#include +#include + +#include "internal.h" + + +static const SRTP_PROTECTION_PROFILE kSRTPProfiles[] = { + { + "SRTP_AES128_CM_SHA1_80", SRTP_AES128_CM_SHA1_80, + }, + { + "SRTP_AES128_CM_SHA1_32", SRTP_AES128_CM_SHA1_32, + }, + { + "SRTP_AEAD_AES_128_GCM", SRTP_AEAD_AES_128_GCM, + }, + { + "SRTP_AEAD_AES_256_GCM", SRTP_AEAD_AES_256_GCM, + }, + {0, 0}, +}; + +static int find_profile_by_name(const char *profile_name, + const SRTP_PROTECTION_PROFILE **pptr, + size_t len) { + const SRTP_PROTECTION_PROFILE *p; + + p = kSRTPProfiles; + while (p->name) { + if (len == strlen(p->name) && !strncmp(p->name, profile_name, len)) { + *pptr = p; + return 1; + } + + p++; + } + + return 0; +} + +static int ssl_ctx_make_profiles(const char *profiles_string, + STACK_OF(SRTP_PROTECTION_PROFILE) **out) { + STACK_OF(SRTP_PROTECTION_PROFILE) *profiles; + + const char *col; + const char *ptr = profiles_string; + + profiles = sk_SRTP_PROTECTION_PROFILE_new_null(); + if (profiles == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_R_SRTP_COULD_NOT_ALLOCATE_PROFILES); + return 0; + } + + do { + const SRTP_PROTECTION_PROFILE *p; + + col = strchr(ptr, ':'); + if (find_profile_by_name(ptr, &p, + col ? (size_t)(col - ptr) : strlen(ptr))) { + sk_SRTP_PROTECTION_PROFILE_push(profiles, p); + } else { + OPENSSL_PUT_ERROR(SSL, SSL_R_SRTP_UNKNOWN_PROTECTION_PROFILE); + return 0; + } + + if (col) { + ptr = col + 1; + } + } while (col); + + sk_SRTP_PROTECTION_PROFILE_free(*out); + *out = profiles; + + return 1; +} + +int SSL_CTX_set_srtp_profiles(SSL_CTX *ctx, const char *profiles) { + return ssl_ctx_make_profiles(profiles, &ctx->srtp_profiles); +} + +int SSL_set_srtp_profiles(SSL *ssl, const char *profiles) { + return ssl_ctx_make_profiles(profiles, &ssl->srtp_profiles); +} + +STACK_OF(SRTP_PROTECTION_PROFILE) *SSL_get_srtp_profiles(SSL *ssl) { + if (ssl == NULL) { + return NULL; + } + + if (ssl->srtp_profiles != NULL) { + return ssl->srtp_profiles; + } + + if (ssl->ctx->srtp_profiles != NULL) { + return ssl->ctx->srtp_profiles; + } + + return NULL; +} + +const SRTP_PROTECTION_PROFILE *SSL_get_selected_srtp_profile(SSL *ssl) { + return ssl->srtp_profile; +} + +int SSL_CTX_set_tlsext_use_srtp(SSL_CTX *ctx, const char *profiles) { + /* This API inverts its return value. */ + return !SSL_CTX_set_srtp_profiles(ctx, profiles); +} + +int SSL_set_tlsext_use_srtp(SSL *ssl, const char *profiles) { + /* This API inverts its return value. */ + return !SSL_set_srtp_profiles(ssl, profiles); +} diff --git a/external/boringssl/ssl/dtls_record.c b/external/boringssl/ssl/dtls_record.c new file mode 100644 index 0000000000..e784e556dd --- /dev/null +++ b/external/boringssl/ssl/dtls_record.c @@ -0,0 +1,309 @@ +/* DTLS implementation written by Nagendra Modadugu + * (nagendra@cs.stanford.edu) for the OpenSSL project 2005. */ +/* ==================================================================== + * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include +#include + +#include +#include + +#include "internal.h" +#include "../crypto/internal.h" + + +/* to_u64_be treats |in| as a 8-byte big-endian integer and returns the value as + * a |uint64_t|. */ +static uint64_t to_u64_be(const uint8_t in[8]) { + uint64_t ret = 0; + unsigned i; + for (i = 0; i < 8; i++) { + ret <<= 8; + ret |= in[i]; + } + return ret; +} + +/* dtls1_bitmap_should_discard returns one if |seq_num| has been seen in |bitmap| + * or is stale. Otherwise it returns zero. */ +static int dtls1_bitmap_should_discard(DTLS1_BITMAP *bitmap, + const uint8_t seq_num[8]) { + const unsigned kWindowSize = sizeof(bitmap->map) * 8; + + uint64_t seq_num_u = to_u64_be(seq_num); + if (seq_num_u > bitmap->max_seq_num) { + return 0; + } + uint64_t idx = bitmap->max_seq_num - seq_num_u; + return idx >= kWindowSize || (bitmap->map & (((uint64_t)1) << idx)); +} + +/* dtls1_bitmap_record updates |bitmap| to record receipt of sequence number + * |seq_num|. It slides the window forward if needed. It is an error to call + * this function on a stale sequence number. */ +static void dtls1_bitmap_record(DTLS1_BITMAP *bitmap, + const uint8_t seq_num[8]) { + const unsigned kWindowSize = sizeof(bitmap->map) * 8; + + uint64_t seq_num_u = to_u64_be(seq_num); + /* Shift the window if necessary. */ + if (seq_num_u > bitmap->max_seq_num) { + uint64_t shift = seq_num_u - bitmap->max_seq_num; + if (shift >= kWindowSize) { + bitmap->map = 0; + } else { + bitmap->map <<= shift; + } + bitmap->max_seq_num = seq_num_u; + } + + uint64_t idx = bitmap->max_seq_num - seq_num_u; + if (idx < kWindowSize) { + bitmap->map |= ((uint64_t)1) << idx; + } +} + +enum ssl_open_record_t dtls_open_record(SSL *ssl, uint8_t *out_type, CBS *out, + size_t *out_consumed, + uint8_t *out_alert, uint8_t *in, + size_t in_len) { + *out_consumed = 0; + + CBS cbs; + CBS_init(&cbs, in, in_len); + + /* Decode the record. */ + uint8_t type; + uint16_t version; + uint8_t sequence[8]; + CBS body; + if (!CBS_get_u8(&cbs, &type) || + !CBS_get_u16(&cbs, &version) || + !CBS_copy_bytes(&cbs, sequence, 8) || + !CBS_get_u16_length_prefixed(&cbs, &body) || + (ssl->s3->have_version && version != ssl->version) || + (version >> 8) != DTLS1_VERSION_MAJOR || + CBS_len(&body) > SSL3_RT_MAX_ENCRYPTED_LENGTH) { + /* The record header was incomplete or malformed. Drop the entire packet. */ + *out_consumed = in_len; + return ssl_open_record_discard; + } + + ssl_do_msg_callback(ssl, 0 /* read */, 0, SSL3_RT_HEADER, in, + DTLS1_RT_HEADER_LENGTH); + + uint16_t epoch = (((uint16_t)sequence[0]) << 8) | sequence[1]; + if (epoch != ssl->d1->r_epoch || + dtls1_bitmap_should_discard(&ssl->d1->bitmap, sequence)) { + /* Drop this record. It's from the wrong epoch or is a replay. Note that if + * |epoch| is the next epoch, the record could be buffered for later. For + * simplicity, drop it and expect retransmit to handle it later; DTLS must + * handle packet loss anyway. */ + *out_consumed = in_len - CBS_len(&cbs); + return ssl_open_record_discard; + } + + /* Decrypt the body in-place. */ + if (!SSL_AEAD_CTX_open(ssl->s3->aead_read_ctx, out, type, version, sequence, + (uint8_t *)CBS_data(&body), CBS_len(&body))) { + /* Bad packets are silently dropped in DTLS. See section 4.2.1 of RFC 6347. + * Clear the error queue of any errors decryption may have added. Drop the + * entire packet as it must not have come from the peer. + * + * TODO(davidben): This doesn't distinguish malloc failures from encryption + * failures. */ + ERR_clear_error(); + *out_consumed = in_len - CBS_len(&cbs); + return ssl_open_record_discard; + } + *out_consumed = in_len - CBS_len(&cbs); + + /* Check the plaintext length. */ + if (CBS_len(out) > SSL3_RT_MAX_PLAIN_LENGTH) { + OPENSSL_PUT_ERROR(SSL, SSL_R_DATA_LENGTH_TOO_LONG); + *out_alert = SSL_AD_RECORD_OVERFLOW; + return ssl_open_record_error; + } + + dtls1_bitmap_record(&ssl->d1->bitmap, sequence); + + /* TODO(davidben): Limit the number of empty records as in TLS? This is only + * useful if we also limit discarded packets. */ + + if (type == SSL3_RT_ALERT) { + return ssl_process_alert(ssl, out_alert, CBS_data(out), CBS_len(out)); + } + + ssl->s3->warning_alert_count = 0; + + *out_type = type; + return ssl_open_record_success; +} + +int dtls_seal_record(SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out, + uint8_t type, const uint8_t *in, size_t in_len, + enum dtls1_use_epoch_t use_epoch) { + if (buffers_alias(in, in_len, out, max_out)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_OUTPUT_ALIASES_INPUT); + return 0; + } + + /* Determine the parameters for the current epoch. */ + uint16_t epoch = ssl->d1->w_epoch; + SSL_AEAD_CTX *aead = ssl->s3->aead_write_ctx; + uint8_t *seq = ssl->s3->write_sequence; + if (use_epoch == dtls1_use_previous_epoch) { + /* DTLS renegotiation is unsupported, so only epochs 0 (NULL cipher) and 1 + * (negotiated cipher) exist. */ + assert(ssl->d1->w_epoch == 1); + epoch = ssl->d1->w_epoch - 1; + aead = NULL; + seq = ssl->d1->last_write_sequence; + } + + if (max_out < DTLS1_RT_HEADER_LENGTH) { + OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFER_TOO_SMALL); + return 0; + } + + out[0] = type; + + uint16_t wire_version = ssl->s3->have_version ? ssl->version : DTLS1_VERSION; + out[1] = wire_version >> 8; + out[2] = wire_version & 0xff; + + out[3] = epoch >> 8; + out[4] = epoch & 0xff; + memcpy(&out[5], &seq[2], 6); + + size_t ciphertext_len; + if (!SSL_AEAD_CTX_seal(aead, out + DTLS1_RT_HEADER_LENGTH, &ciphertext_len, + max_out - DTLS1_RT_HEADER_LENGTH, type, wire_version, + &out[3] /* seq */, in, in_len) || + !ssl_record_sequence_update(&seq[2], 6)) { + return 0; + } + + if (ciphertext_len >= 1 << 16) { + OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW); + return 0; + } + out[11] = ciphertext_len >> 8; + out[12] = ciphertext_len & 0xff; + + *out_len = DTLS1_RT_HEADER_LENGTH + ciphertext_len; + + ssl_do_msg_callback(ssl, 1 /* write */, 0, SSL3_RT_HEADER, out, + DTLS1_RT_HEADER_LENGTH); + + return 1; +} diff --git a/external/boringssl/ssl/handshake_client.c b/external/boringssl/ssl/handshake_client.c new file mode 100644 index 0000000000..9b96bcd19e --- /dev/null +++ b/external/boringssl/ssl/handshake_client.c @@ -0,0 +1,2107 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * + * Portions of the attached software ("Contribution") are developed by + * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. + * + * The Contribution is licensed pursuant to the OpenSSL open source + * license provided above. + * + * ECC cipher suite support in OpenSSL originally written by + * Vipul Gupta and Sumit Gupta of Sun Microsystems Laboratories. + * + */ +/* ==================================================================== + * Copyright 2005 Nokia. All rights reserved. + * + * The portions of the attached software ("Contribution") is developed by + * Nokia Corporation and is licensed pursuant to the OpenSSL open source + * license. + * + * The Contribution, originally written by Mika Kousa and Pasi Eronen of + * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites + * support (see RFC 4279) to OpenSSL. + * + * No patent licenses or other rights except those expressly stated in + * the OpenSSL open source license shall be deemed granted or received + * expressly, by implication, estoppel, or otherwise. + * + * No assurances are provided by Nokia that the Contribution does not + * infringe the patent or other intellectual property rights of any third + * party or that the license provides you with all the necessary rights + * to make use of the Contribution. + * + * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN + * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA + * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY + * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR + * OTHERWISE. + */ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "internal.h" +#include "../crypto/dh/internal.h" + + +static int ssl3_send_client_hello(SSL *ssl); +static int dtls1_get_hello_verify(SSL *ssl); +static int ssl3_get_server_hello(SSL *ssl); +static int ssl3_get_server_certificate(SSL *ssl); +static int ssl3_get_cert_status(SSL *ssl); +static int ssl3_verify_server_cert(SSL *ssl); +static int ssl3_get_server_key_exchange(SSL *ssl); +static int ssl3_get_certificate_request(SSL *ssl); +static int ssl3_get_server_hello_done(SSL *ssl); +static int ssl3_send_client_certificate(SSL *ssl); +static int ssl3_send_client_key_exchange(SSL *ssl); +static int ssl3_send_cert_verify(SSL *ssl); +static int ssl3_send_next_proto(SSL *ssl); +static int ssl3_send_channel_id(SSL *ssl); +static int ssl3_get_new_session_ticket(SSL *ssl); + +int ssl3_connect(SSL *ssl) { + BUF_MEM *buf = NULL; + int ret = -1; + int state, skip = 0; + + assert(ssl->handshake_func == ssl3_connect); + assert(!ssl->server); + + for (;;) { + state = ssl->state; + + switch (ssl->state) { + case SSL_ST_CONNECT: + ssl_do_info_callback(ssl, SSL_CB_HANDSHAKE_START, 1); + + if (ssl->init_buf == NULL) { + buf = BUF_MEM_new(); + if (buf == NULL || + !BUF_MEM_reserve(buf, SSL3_RT_MAX_PLAIN_LENGTH)) { + ret = -1; + goto end; + } + + ssl->init_buf = buf; + buf = NULL; + } + ssl->init_num = 0; + + if (!ssl_init_wbio_buffer(ssl)) { + ret = -1; + goto end; + } + + ssl->state = SSL3_ST_CW_CLNT_HELLO_A; + break; + + case SSL3_ST_CW_CLNT_HELLO_A: + case SSL3_ST_CW_CLNT_HELLO_B: + ret = ssl3_send_client_hello(ssl); + if (ret <= 0) { + goto end; + } + + if (!SSL_IS_DTLS(ssl) || ssl->d1->send_cookie) { + ssl->s3->tmp.next_state = SSL3_ST_CR_SRVR_HELLO_A; + } else { + ssl->s3->tmp.next_state = DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A; + } + ssl->state = SSL3_ST_CW_FLUSH; + break; + + case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A: + assert(SSL_IS_DTLS(ssl)); + ret = dtls1_get_hello_verify(ssl); + if (ret <= 0) { + goto end; + } + if (ssl->d1->send_cookie) { + ssl->method->received_flight(ssl); + ssl->state = SSL3_ST_CW_CLNT_HELLO_A; + } else { + ssl->state = SSL3_ST_CR_SRVR_HELLO_A; + } + break; + + case SSL3_ST_CR_SRVR_HELLO_A: + ret = ssl3_get_server_hello(ssl); + if (ret <= 0) { + goto end; + } + + if (ssl->hit) { + ssl->state = SSL3_ST_CR_CHANGE; + if (ssl->tlsext_ticket_expected) { + /* receive renewed session ticket */ + ssl->state = SSL3_ST_CR_SESSION_TICKET_A; + } + } else { + ssl->state = SSL3_ST_CR_CERT_A; + } + break; + + case SSL3_ST_CR_CERT_A: + if (ssl_cipher_uses_certificate_auth(ssl->s3->tmp.new_cipher)) { + ret = ssl3_get_server_certificate(ssl); + if (ret <= 0) { + goto end; + } + if (ssl->s3->tmp.certificate_status_expected) { + ssl->state = SSL3_ST_CR_CERT_STATUS_A; + } else { + ssl->state = SSL3_ST_VERIFY_SERVER_CERT; + } + } else { + skip = 1; + ssl->state = SSL3_ST_CR_KEY_EXCH_A; + } + break; + + case SSL3_ST_CR_CERT_STATUS_A: + ret = ssl3_get_cert_status(ssl); + if (ret <= 0) { + goto end; + } + ssl->state = SSL3_ST_VERIFY_SERVER_CERT; + break; + + case SSL3_ST_VERIFY_SERVER_CERT: + ret = ssl3_verify_server_cert(ssl); + if (ret <= 0) { + goto end; + } + + ssl->state = SSL3_ST_CR_KEY_EXCH_A; + break; + + case SSL3_ST_CR_KEY_EXCH_A: + ret = ssl3_get_server_key_exchange(ssl); + if (ret <= 0) { + goto end; + } + if (ssl_cipher_uses_certificate_auth(ssl->s3->tmp.new_cipher)) { + ssl->state = SSL3_ST_CR_CERT_REQ_A; + } else { + ssl->state = SSL3_ST_CR_SRVR_DONE_A; + } + break; + + case SSL3_ST_CR_CERT_REQ_A: + ret = ssl3_get_certificate_request(ssl); + if (ret <= 0) { + goto end; + } + ssl->state = SSL3_ST_CR_SRVR_DONE_A; + break; + + case SSL3_ST_CR_SRVR_DONE_A: + ret = ssl3_get_server_hello_done(ssl); + if (ret <= 0) { + goto end; + } + ssl->method->received_flight(ssl); + if (ssl->s3->tmp.cert_req) { + ssl->state = SSL3_ST_CW_CERT_A; + } else { + ssl->state = SSL3_ST_CW_KEY_EXCH_A; + } + break; + + case SSL3_ST_CW_CERT_A: + case SSL3_ST_CW_CERT_B: + case SSL3_ST_CW_CERT_C: + case SSL3_ST_CW_CERT_D: + ret = ssl3_send_client_certificate(ssl); + if (ret <= 0) { + goto end; + } + ssl->state = SSL3_ST_CW_KEY_EXCH_A; + break; + + case SSL3_ST_CW_KEY_EXCH_A: + case SSL3_ST_CW_KEY_EXCH_B: + ret = ssl3_send_client_key_exchange(ssl); + if (ret <= 0) { + goto end; + } + /* For TLS, cert_req is set to 2, so a cert chain + * of nothing is sent, but no verify packet is sent */ + if (ssl->s3->tmp.cert_req == 1) { + ssl->state = SSL3_ST_CW_CERT_VRFY_A; + } else { + ssl->state = SSL3_ST_CW_CHANGE_A; + } + break; + + case SSL3_ST_CW_CERT_VRFY_A: + case SSL3_ST_CW_CERT_VRFY_B: + case SSL3_ST_CW_CERT_VRFY_C: + ret = ssl3_send_cert_verify(ssl); + if (ret <= 0) { + goto end; + } + ssl->state = SSL3_ST_CW_CHANGE_A; + break; + + case SSL3_ST_CW_CHANGE_A: + case SSL3_ST_CW_CHANGE_B: + ret = ssl->method->send_change_cipher_spec(ssl, SSL3_ST_CW_CHANGE_A, + SSL3_ST_CW_CHANGE_B); + if (ret <= 0) { + goto end; + } + + ssl->state = SSL3_ST_CW_FINISHED_A; + if (ssl->s3->tlsext_channel_id_valid) { + ssl->state = SSL3_ST_CW_CHANNEL_ID_A; + } + if (ssl->s3->next_proto_neg_seen) { + ssl->state = SSL3_ST_CW_NEXT_PROTO_A; + } + + if (!tls1_change_cipher_state(ssl, SSL3_CHANGE_CIPHER_CLIENT_WRITE)) { + ret = -1; + goto end; + } + + break; + + case SSL3_ST_CW_NEXT_PROTO_A: + case SSL3_ST_CW_NEXT_PROTO_B: + ret = ssl3_send_next_proto(ssl); + if (ret <= 0) { + goto end; + } + + if (ssl->s3->tlsext_channel_id_valid) { + ssl->state = SSL3_ST_CW_CHANNEL_ID_A; + } else { + ssl->state = SSL3_ST_CW_FINISHED_A; + } + break; + + case SSL3_ST_CW_CHANNEL_ID_A: + case SSL3_ST_CW_CHANNEL_ID_B: + ret = ssl3_send_channel_id(ssl); + if (ret <= 0) { + goto end; + } + ssl->state = SSL3_ST_CW_FINISHED_A; + break; + + case SSL3_ST_CW_FINISHED_A: + case SSL3_ST_CW_FINISHED_B: + ret = ssl3_send_finished(ssl, SSL3_ST_CW_FINISHED_A, + SSL3_ST_CW_FINISHED_B); + if (ret <= 0) { + goto end; + } + ssl->state = SSL3_ST_CW_FLUSH; + + if (ssl->hit) { + ssl->s3->tmp.next_state = SSL_ST_OK; + } else { + /* This is a non-resumption handshake. If it involves ChannelID, then + * record the handshake hashes at this point in the session so that + * any resumption of this session with ChannelID can sign those + * hashes. */ + ret = tls1_record_handshake_hashes_for_channel_id(ssl); + if (ret <= 0) { + goto end; + } + if ((SSL_get_mode(ssl) & SSL_MODE_ENABLE_FALSE_START) && + ssl3_can_false_start(ssl) && + /* No False Start on renegotiation (would complicate the state + * machine). */ + !ssl->s3->initial_handshake_complete) { + ssl->s3->tmp.next_state = SSL3_ST_FALSE_START; + } else { + /* Allow NewSessionTicket if ticket expected */ + if (ssl->tlsext_ticket_expected) { + ssl->s3->tmp.next_state = SSL3_ST_CR_SESSION_TICKET_A; + } else { + ssl->s3->tmp.next_state = SSL3_ST_CR_CHANGE; + } + } + } + break; + + case SSL3_ST_FALSE_START: + /* Allow NewSessionTicket if ticket expected */ + if (ssl->tlsext_ticket_expected) { + ssl->state = SSL3_ST_CR_SESSION_TICKET_A; + } else { + ssl->state = SSL3_ST_CR_CHANGE; + } + ssl->s3->tmp.in_false_start = 1; + + ssl_free_wbio_buffer(ssl); + ret = 1; + goto end; + + case SSL3_ST_CR_SESSION_TICKET_A: + ret = ssl3_get_new_session_ticket(ssl); + if (ret <= 0) { + goto end; + } + ssl->state = SSL3_ST_CR_CHANGE; + break; + + case SSL3_ST_CR_CHANGE: + ret = ssl->method->ssl_read_change_cipher_spec(ssl); + if (ret <= 0) { + goto end; + } + + if (!tls1_change_cipher_state(ssl, SSL3_CHANGE_CIPHER_CLIENT_READ)) { + ret = -1; + goto end; + } + ssl->state = SSL3_ST_CR_FINISHED_A; + break; + + case SSL3_ST_CR_FINISHED_A: + ret = ssl3_get_finished(ssl); + if (ret <= 0) { + goto end; + } + ssl->method->received_flight(ssl); + + if (ssl->hit) { + ssl->state = SSL3_ST_CW_CHANGE_A; + } else { + ssl->state = SSL_ST_OK; + } + break; + + case SSL3_ST_CW_FLUSH: + if (BIO_flush(ssl->wbio) <= 0) { + ssl->rwstate = SSL_WRITING; + ret = -1; + goto end; + } + ssl->state = ssl->s3->tmp.next_state; + if (ssl->state != SSL_ST_OK) { + ssl->method->expect_flight(ssl); + } + break; + + case SSL_ST_OK: + /* clean a few things up */ + ssl3_cleanup_key_block(ssl); + + /* |init_buf| cannot be released in DTLS because post-handshake + * retransmit relies on that buffer being available as scratch space. + * + * TODO(davidben): Fix this. */ + if (!SSL_IS_DTLS(ssl)) { + BUF_MEM_free(ssl->init_buf); + ssl->init_buf = NULL; + ssl->init_num = 0; + } + + /* Remove write buffering now. */ + ssl_free_wbio_buffer(ssl); + + const int is_initial_handshake = !ssl->s3->initial_handshake_complete; + + ssl->s3->tmp.in_false_start = 0; + ssl->s3->initial_handshake_complete = 1; + + if (is_initial_handshake) { + /* Renegotiations do not participate in session resumption. */ + ssl_update_cache(ssl, SSL_SESS_CACHE_CLIENT); + } + + if (SSL_IS_DTLS(ssl)) { + ssl->d1->handshake_read_seq = 0; + ssl->d1->next_handshake_write_seq = 0; + } + + ret = 1; + ssl_do_info_callback(ssl, SSL_CB_HANDSHAKE_DONE, 1); + goto end; + + default: + OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_STATE); + ret = -1; + goto end; + } + + if (!ssl->s3->tmp.reuse_message && !skip && ssl->state != state) { + int new_state = ssl->state; + ssl->state = state; + ssl_do_info_callback(ssl, SSL_CB_CONNECT_LOOP, 1); + ssl->state = new_state; + } + skip = 0; + } + +end: + BUF_MEM_free(buf); + ssl_do_info_callback(ssl, SSL_CB_CONNECT_EXIT, ret); + return ret; +} + +static int ssl3_write_client_cipher_list(SSL *ssl, CBB *out) { + /* Prepare disabled cipher masks. */ + ssl_set_client_disabled(ssl); + + CBB child; + if (!CBB_add_u16_length_prefixed(out, &child)) { + return 0; + } + + STACK_OF(SSL_CIPHER) *ciphers = SSL_get_ciphers(ssl); + + int any_enabled = 0; + size_t i; + for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) { + const SSL_CIPHER *cipher = sk_SSL_CIPHER_value(ciphers, i); + /* Skip disabled ciphers */ + if ((cipher->algorithm_mkey & ssl->cert->mask_k) || + (cipher->algorithm_auth & ssl->cert->mask_a)) { + continue; + } + if (SSL_CIPHER_get_min_version(cipher) > + ssl3_version_from_wire(ssl, ssl->client_version)) { + continue; + } + any_enabled = 1; + if (!CBB_add_u16(&child, ssl_cipher_get_value(cipher))) { + return 0; + } + } + + /* If all ciphers were disabled, return the error to the caller. */ + if (!any_enabled) { + OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CIPHERS_AVAILABLE); + return 0; + } + + /* For SSLv3, the SCSV is added. Otherwise the renegotiation extension is + * added. */ + if (ssl->client_version == SSL3_VERSION && + !ssl->s3->initial_handshake_complete) { + if (!CBB_add_u16(&child, SSL3_CK_SCSV & 0xffff)) { + return 0; + } + /* The renegotiation extension is required to be at index zero. */ + ssl->s3->tmp.extensions.sent |= (1u << 0); + } + + if ((ssl->mode & SSL_MODE_SEND_FALLBACK_SCSV) && + !CBB_add_u16(&child, SSL3_CK_FALLBACK_SCSV & 0xffff)) { + return 0; + } + + return CBB_flush(out); +} + +static int ssl3_send_client_hello(SSL *ssl) { + if (ssl->state == SSL3_ST_CW_CLNT_HELLO_B) { + return ssl_do_write(ssl); + } + + /* The handshake buffer is reset on every ClientHello. Notably, in DTLS, we + * may send multiple ClientHellos if we receive HelloVerifyRequest. */ + if (!ssl3_init_handshake_buffer(ssl)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + return -1; + } + + CBB cbb; + CBB_zero(&cbb); + + assert(ssl->state == SSL3_ST_CW_CLNT_HELLO_A); + if (!ssl->s3->have_version) { + uint16_t max_version = ssl3_get_max_client_version(ssl); + /* Disabling all versions is silly: return an error. */ + if (max_version == 0) { + OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SSL_VERSION); + goto err; + } + + ssl->version = max_version; + /* Only set |ssl->client_version| on the initial handshake. Renegotiations, + * although locked to a version, reuse the value. When using the plain RSA + * key exchange, the ClientHello version is checked in the premaster secret. + * Some servers fail when this value changes. */ + ssl->client_version = max_version; + } + + /* If the configured session has expired or was created at a disabled + * version, drop it. */ + if (ssl->session != NULL && + (ssl->session->session_id_length == 0 || ssl->session->not_resumable || + ssl->session->timeout < (long)(time(NULL) - ssl->session->time) || + !ssl3_is_version_enabled(ssl, ssl->session->ssl_version))) { + SSL_set_session(ssl, NULL); + } + + /* If resending the ClientHello in DTLS after a HelloVerifyRequest, don't + * renegerate the client_random. The random must be reused. */ + if ((!SSL_IS_DTLS(ssl) || !ssl->d1->send_cookie) && + !ssl_fill_hello_random(ssl->s3->client_random, + sizeof(ssl->s3->client_random), 0 /* client */)) { + goto err; + } + + /* Renegotiations do not participate in session resumption. */ + int has_session = ssl->session != NULL && + !ssl->s3->initial_handshake_complete; + + CBB child; + if (!CBB_init_fixed(&cbb, ssl_handshake_start(ssl), + ssl->init_buf->max - SSL_HM_HEADER_LENGTH(ssl)) || + !CBB_add_u16(&cbb, ssl->client_version) || + !CBB_add_bytes(&cbb, ssl->s3->client_random, SSL3_RANDOM_SIZE) || + !CBB_add_u8_length_prefixed(&cbb, &child) || + (has_session && + !CBB_add_bytes(&child, ssl->session->session_id, + ssl->session->session_id_length))) { + goto err; + } + + if (SSL_IS_DTLS(ssl)) { + if (!CBB_add_u8_length_prefixed(&cbb, &child) || + !CBB_add_bytes(&child, ssl->d1->cookie, ssl->d1->cookie_len)) { + goto err; + } + } + + size_t length; + if (!ssl3_write_client_cipher_list(ssl, &cbb) || + !CBB_add_u8(&cbb, 1 /* one compression method */) || + !CBB_add_u8(&cbb, 0 /* null compression */) || + !ssl_add_clienthello_tlsext(ssl, &cbb, + CBB_len(&cbb) + SSL_HM_HEADER_LENGTH(ssl)) || + !CBB_finish(&cbb, NULL, &length) || + !ssl_set_handshake_header(ssl, SSL3_MT_CLIENT_HELLO, length)) { + goto err; + } + + ssl->state = SSL3_ST_CW_CLNT_HELLO_B; + return ssl_do_write(ssl); + +err: + CBB_cleanup(&cbb); + return -1; +} + +static int dtls1_get_hello_verify(SSL *ssl) { + long n; + int al, ok = 0; + CBS hello_verify_request, cookie; + uint16_t server_version; + + n = ssl->method->ssl_get_message(ssl, -1, ssl_hash_message, &ok); + + if (!ok) { + return n; + } + + if (ssl->s3->tmp.message_type != DTLS1_MT_HELLO_VERIFY_REQUEST) { + ssl->d1->send_cookie = 0; + ssl->s3->tmp.reuse_message = 1; + return 1; + } + + CBS_init(&hello_verify_request, ssl->init_msg, n); + + if (!CBS_get_u16(&hello_verify_request, &server_version) || + !CBS_get_u8_length_prefixed(&hello_verify_request, &cookie) || + CBS_len(&hello_verify_request) != 0) { + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + goto f_err; + } + + if (CBS_len(&cookie) > sizeof(ssl->d1->cookie)) { + al = SSL_AD_ILLEGAL_PARAMETER; + goto f_err; + } + + memcpy(ssl->d1->cookie, CBS_data(&cookie), CBS_len(&cookie)); + ssl->d1->cookie_len = CBS_len(&cookie); + + ssl->d1->send_cookie = 1; + return 1; + +f_err: + ssl3_send_alert(ssl, SSL3_AL_FATAL, al); + return -1; +} + +static int ssl3_get_server_hello(SSL *ssl) { + STACK_OF(SSL_CIPHER) *sk; + const SSL_CIPHER *c; + CERT *ct = ssl->cert; + int al = SSL_AD_INTERNAL_ERROR, ok; + long n; + CBS server_hello, server_random, session_id; + uint16_t server_version, cipher_suite; + uint8_t compression_method; + + n = ssl->method->ssl_get_message(ssl, SSL3_MT_SERVER_HELLO, ssl_hash_message, + &ok); + + if (!ok) { + uint32_t err = ERR_peek_error(); + if (ERR_GET_LIB(err) == ERR_LIB_SSL && + ERR_GET_REASON(err) == SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE) { + /* Add a dedicated error code to the queue for a handshake_failure alert + * in response to ClientHello. This matches NSS's client behavior and + * gives a better error on a (probable) failure to negotiate initial + * parameters. Note: this error code comes after the original one. + * + * See https://crbug.com/446505. */ + OPENSSL_PUT_ERROR(SSL, SSL_R_HANDSHAKE_FAILURE_ON_CLIENT_HELLO); + } + return n; + } + + CBS_init(&server_hello, ssl->init_msg, n); + + if (!CBS_get_u16(&server_hello, &server_version) || + !CBS_get_bytes(&server_hello, &server_random, SSL3_RANDOM_SIZE) || + !CBS_get_u8_length_prefixed(&server_hello, &session_id) || + CBS_len(&session_id) > SSL3_SESSION_ID_SIZE || + !CBS_get_u16(&server_hello, &cipher_suite) || + !CBS_get_u8(&server_hello, &compression_method)) { + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + goto f_err; + } + + assert(ssl->s3->have_version == ssl->s3->initial_handshake_complete); + if (!ssl->s3->have_version) { + if (!ssl3_is_version_enabled(ssl, server_version)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_PROTOCOL); + ssl->version = server_version; + /* Mark the version as fixed so the record-layer version is not clamped + * to TLS 1.0. */ + ssl->s3->have_version = 1; + al = SSL_AD_PROTOCOL_VERSION; + goto f_err; + } + ssl->version = server_version; + ssl->s3->enc_method = ssl3_get_enc_method(server_version); + assert(ssl->s3->enc_method != NULL); + /* At this point, the connection's version is known and ssl->version is + * fixed. Begin enforcing the record-layer version. */ + ssl->s3->have_version = 1; + } else if (server_version != ssl->version) { + OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SSL_VERSION); + al = SSL_AD_PROTOCOL_VERSION; + goto f_err; + } + + /* Copy over the server random. */ + memcpy(ssl->s3->server_random, CBS_data(&server_random), SSL3_RANDOM_SIZE); + + assert(ssl->session == NULL || ssl->session->session_id_length > 0); + if (!ssl->s3->initial_handshake_complete && ssl->session != NULL && + CBS_mem_equal(&session_id, ssl->session->session_id, + ssl->session->session_id_length)) { + if (ssl->sid_ctx_length != ssl->session->sid_ctx_length || + memcmp(ssl->session->sid_ctx, ssl->sid_ctx, ssl->sid_ctx_length)) { + /* actually a client application bug */ + al = SSL_AD_ILLEGAL_PARAMETER; + OPENSSL_PUT_ERROR(SSL, + SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT); + goto f_err; + } + ssl->hit = 1; + } else { + /* The session wasn't resumed. Create a fresh SSL_SESSION to + * fill out. */ + ssl->hit = 0; + if (!ssl_get_new_session(ssl, 0 /* client */)) { + goto f_err; + } + /* Note: session_id could be empty. */ + ssl->session->session_id_length = CBS_len(&session_id); + memcpy(ssl->session->session_id, CBS_data(&session_id), + CBS_len(&session_id)); + } + + c = SSL_get_cipher_by_value(cipher_suite); + if (c == NULL) { + /* unknown cipher */ + al = SSL_AD_ILLEGAL_PARAMETER; + OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CIPHER_RETURNED); + goto f_err; + } + /* If the cipher is disabled then we didn't sent it in the ClientHello, so if + * the server selected it, it's an error. */ + if ((c->algorithm_mkey & ct->mask_k) || (c->algorithm_auth & ct->mask_a) || + SSL_CIPHER_get_min_version(c) > ssl3_protocol_version(ssl)) { + al = SSL_AD_ILLEGAL_PARAMETER; + OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CIPHER_RETURNED); + goto f_err; + } + + sk = ssl_get_ciphers_by_id(ssl); + if (!sk_SSL_CIPHER_find(sk, NULL, c)) { + /* we did not say we would use this cipher */ + al = SSL_AD_ILLEGAL_PARAMETER; + OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CIPHER_RETURNED); + goto f_err; + } + + if (ssl->hit) { + if (ssl->session->cipher != c) { + al = SSL_AD_ILLEGAL_PARAMETER; + OPENSSL_PUT_ERROR(SSL, SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED); + goto f_err; + } + if (ssl->session->ssl_version != ssl->version) { + al = SSL_AD_ILLEGAL_PARAMETER; + OPENSSL_PUT_ERROR(SSL, SSL_R_OLD_SESSION_VERSION_NOT_RETURNED); + goto f_err; + } + } else { + ssl->session->cipher = c; + } + ssl->s3->tmp.new_cipher = c; + + /* Now that the cipher is known, initialize the handshake hash. */ + if (!ssl3_init_handshake_hash(ssl)) { + goto f_err; + } + + /* If doing a full handshake with TLS 1.2, the server may request a client + * certificate which requires hashing the handshake transcript under a + * different hash. Otherwise, the handshake buffer may be released. */ + if (ssl->hit || ssl3_protocol_version(ssl) < TLS1_2_VERSION || + !ssl_cipher_uses_certificate_auth(ssl->s3->tmp.new_cipher)) { + ssl3_free_handshake_buffer(ssl); + } + + /* Only the NULL compression algorithm is supported. */ + if (compression_method != 0) { + al = SSL_AD_ILLEGAL_PARAMETER; + OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM); + goto f_err; + } + + /* TLS extensions */ + if (!ssl_parse_serverhello_tlsext(ssl, &server_hello)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_PARSE_TLSEXT); + goto err; + } + + /* There should be nothing left over in the record. */ + if (CBS_len(&server_hello) != 0) { + /* wrong packet length */ + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_PACKET_LENGTH); + goto f_err; + } + + if (ssl->hit && + ssl->s3->tmp.extended_master_secret != + ssl->session->extended_master_secret) { + al = SSL_AD_HANDSHAKE_FAILURE; + if (ssl->session->extended_master_secret) { + OPENSSL_PUT_ERROR(SSL, SSL_R_RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION); + } else { + OPENSSL_PUT_ERROR(SSL, SSL_R_RESUMED_NON_EMS_SESSION_WITH_EMS_EXTENSION); + } + goto f_err; + } + + return 1; + +f_err: + ssl3_send_alert(ssl, SSL3_AL_FATAL, al); +err: + return -1; +} + +/* ssl3_check_leaf_certificate returns one if |leaf| is a suitable leaf server + * certificate for |ssl|. Otherwise, it returns zero and pushes an error on the + * error queue. */ +static int ssl3_check_leaf_certificate(SSL *ssl, X509 *leaf) { + int ret = 0; + EVP_PKEY *pkey = X509_get_pubkey(leaf); + if (pkey == NULL) { + goto err; + } + + /* Check the certificate's type matches the cipher. */ + const SSL_CIPHER *cipher = ssl->s3->tmp.new_cipher; + int expected_type = ssl_cipher_get_key_type(cipher); + assert(expected_type != EVP_PKEY_NONE); + if (pkey->type != expected_type) { + OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CERTIFICATE_TYPE); + goto err; + } + + if (cipher->algorithm_auth & SSL_aECDSA) { + /* TODO(davidben): This behavior is preserved from upstream. Should key + * usages be checked in other cases as well? */ + /* This call populates the ex_flags field correctly */ + X509_check_purpose(leaf, -1, 0); + if ((leaf->ex_flags & EXFLAG_KUSAGE) && + !(leaf->ex_kusage & X509v3_KU_DIGITAL_SIGNATURE)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_ECC_CERT_NOT_FOR_SIGNING); + goto err; + } + + if (!tls1_check_ec_cert(ssl, leaf)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECC_CERT); + goto err; + } + } + + ret = 1; + +err: + EVP_PKEY_free(pkey); + return ret; +} + +static int ssl3_get_server_certificate(SSL *ssl) { + int al, ok, ret = -1; + unsigned long n; + X509 *x = NULL; + STACK_OF(X509) *sk = NULL; + EVP_PKEY *pkey = NULL; + CBS cbs, certificate_list; + const uint8_t *data; + + n = ssl->method->ssl_get_message(ssl, SSL3_MT_CERTIFICATE, ssl_hash_message, + &ok); + + if (!ok) { + return n; + } + + CBS_init(&cbs, ssl->init_msg, n); + + sk = sk_X509_new_null(); + if (sk == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (!CBS_get_u24_length_prefixed(&cbs, &certificate_list) || + CBS_len(&certificate_list) == 0 || + CBS_len(&cbs) != 0) { + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + goto f_err; + } + + while (CBS_len(&certificate_list) > 0) { + CBS certificate; + if (!CBS_get_u24_length_prefixed(&certificate_list, &certificate)) { + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, SSL_R_CERT_LENGTH_MISMATCH); + goto f_err; + } + /* A u24 length cannot overflow a long. */ + data = CBS_data(&certificate); + x = d2i_X509(NULL, &data, (long)CBS_len(&certificate)); + if (x == NULL) { + al = SSL_AD_BAD_CERTIFICATE; + OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB); + goto f_err; + } + if (data != CBS_data(&certificate) + CBS_len(&certificate)) { + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, SSL_R_CERT_LENGTH_MISMATCH); + goto f_err; + } + if (!sk_X509_push(sk, x)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + goto err; + } + x = NULL; + } + + X509 *leaf = sk_X509_value(sk, 0); + if (!ssl3_check_leaf_certificate(ssl, leaf)) { + al = SSL_AD_ILLEGAL_PARAMETER; + goto f_err; + } + + /* NOTE: Unlike the server half, the client's copy of |cert_chain| includes + * the leaf. */ + sk_X509_pop_free(ssl->session->cert_chain, X509_free); + ssl->session->cert_chain = sk; + sk = NULL; + + X509_free(ssl->session->peer); + ssl->session->peer = X509_up_ref(leaf); + + ssl->session->verify_result = ssl->verify_result; + + ret = 1; + + if (0) { + f_err: + ssl3_send_alert(ssl, SSL3_AL_FATAL, al); + } + +err: + EVP_PKEY_free(pkey); + X509_free(x); + sk_X509_pop_free(sk, X509_free); + return ret; +} + +static int ssl3_get_cert_status(SSL *ssl) { + int ok, al; + long n; + CBS certificate_status, ocsp_response; + uint8_t status_type; + + n = ssl->method->ssl_get_message(ssl, -1, ssl_hash_message, &ok); + + if (!ok) { + return n; + } + + if (ssl->s3->tmp.message_type != SSL3_MT_CERTIFICATE_STATUS) { + /* A server may send status_request in ServerHello and then change + * its mind about sending CertificateStatus. */ + ssl->s3->tmp.reuse_message = 1; + return 1; + } + + CBS_init(&certificate_status, ssl->init_msg, n); + if (!CBS_get_u8(&certificate_status, &status_type) || + status_type != TLSEXT_STATUSTYPE_ocsp || + !CBS_get_u24_length_prefixed(&certificate_status, &ocsp_response) || + CBS_len(&ocsp_response) == 0 || + CBS_len(&certificate_status) != 0) { + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + goto f_err; + } + + if (!CBS_stow(&ocsp_response, &ssl->session->ocsp_response, + &ssl->session->ocsp_response_length)) { + al = SSL_AD_INTERNAL_ERROR; + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + goto f_err; + } + return 1; + +f_err: + ssl3_send_alert(ssl, SSL3_AL_FATAL, al); + return -1; +} + +static int ssl3_verify_server_cert(SSL *ssl) { + int ret = ssl_verify_cert_chain(ssl, ssl->session->cert_chain); + if (ssl->verify_mode != SSL_VERIFY_NONE && ret <= 0) { + int al = ssl_verify_alarm_type(ssl->verify_result); + ssl3_send_alert(ssl, SSL3_AL_FATAL, al); + OPENSSL_PUT_ERROR(SSL, SSL_R_CERTIFICATE_VERIFY_FAILED); + } else { + ret = 1; + ERR_clear_error(); /* but we keep ssl->verify_result */ + } + + return ret; +} + +static int ssl3_get_server_key_exchange(SSL *ssl) { + EVP_MD_CTX md_ctx; + int al, ok; + EVP_PKEY *pkey = NULL; + DH *dh = NULL; + EC_KEY *ecdh = NULL; + EC_POINT *srvr_ecpoint = NULL; + + long n = ssl->method->ssl_get_message(ssl, -1, ssl_hash_message, &ok); + if (!ok) { + return n; + } + + if (ssl->s3->tmp.message_type != SSL3_MT_SERVER_KEY_EXCHANGE) { + if (ssl_cipher_requires_server_key_exchange(ssl->s3->tmp.new_cipher)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE); + ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE); + return -1; + } + + /* In plain PSK ciphersuite, ServerKeyExchange may be omitted to send no + * identity hint. */ + if (ssl->s3->tmp.new_cipher->algorithm_auth & SSL_aPSK) { + /* TODO(davidben): This should be reset in one place with the rest of the + * handshake state. */ + OPENSSL_free(ssl->s3->tmp.peer_psk_identity_hint); + ssl->s3->tmp.peer_psk_identity_hint = NULL; + } + ssl->s3->tmp.reuse_message = 1; + return 1; + } + + /* Retain a copy of the original CBS to compute the signature over. */ + CBS server_key_exchange; + CBS_init(&server_key_exchange, ssl->init_msg, n); + CBS server_key_exchange_orig = server_key_exchange; + + uint32_t alg_k = ssl->s3->tmp.new_cipher->algorithm_mkey; + uint32_t alg_a = ssl->s3->tmp.new_cipher->algorithm_auth; + EVP_MD_CTX_init(&md_ctx); + + if (alg_a & SSL_aPSK) { + CBS psk_identity_hint; + + /* Each of the PSK key exchanges begins with a psk_identity_hint. */ + if (!CBS_get_u16_length_prefixed(&server_key_exchange, + &psk_identity_hint)) { + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + goto f_err; + } + + /* Store PSK identity hint for later use, hint is used in + * ssl3_send_client_key_exchange. Assume that the maximum length of a PSK + * identity hint can be as long as the maximum length of a PSK identity. + * Also do not allow NULL characters; identities are saved as C strings. + * + * TODO(davidben): Should invalid hints be ignored? It's a hint rather than + * a specific identity. */ + if (CBS_len(&psk_identity_hint) > PSK_MAX_IDENTITY_LEN || + CBS_contains_zero_byte(&psk_identity_hint)) { + al = SSL_AD_HANDSHAKE_FAILURE; + OPENSSL_PUT_ERROR(SSL, SSL_R_DATA_LENGTH_TOO_LONG); + goto f_err; + } + + /* Save the identity hint as a C string. */ + if (!CBS_strdup(&psk_identity_hint, &ssl->s3->tmp.peer_psk_identity_hint)) { + al = SSL_AD_INTERNAL_ERROR; + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + goto f_err; + } + } + + if (alg_k & SSL_kDHE) { + CBS dh_p, dh_g, dh_Ys; + if (!CBS_get_u16_length_prefixed(&server_key_exchange, &dh_p) || + CBS_len(&dh_p) == 0 || + !CBS_get_u16_length_prefixed(&server_key_exchange, &dh_g) || + CBS_len(&dh_g) == 0 || + !CBS_get_u16_length_prefixed(&server_key_exchange, &dh_Ys) || + CBS_len(&dh_Ys) == 0) { + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + goto f_err; + } + + dh = DH_new(); + if (dh == NULL) { + goto err; + } + + dh->p = BN_bin2bn(CBS_data(&dh_p), CBS_len(&dh_p), NULL); + dh->g = BN_bin2bn(CBS_data(&dh_g), CBS_len(&dh_g), NULL); + if (dh->p == NULL || dh->g == NULL) { + goto err; + } + + ssl->session->key_exchange_info = DH_num_bits(dh); + if (ssl->session->key_exchange_info < 1024) { + OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_DH_P_LENGTH); + goto err; + } else if (ssl->session->key_exchange_info > 4096) { + /* Overly large DHE groups are prohibitively expensive, so enforce a limit + * to prevent a server from causing us to perform too expensive of a + * computation. */ + OPENSSL_PUT_ERROR(SSL, SSL_R_DH_P_TOO_LONG); + goto err; + } + + SSL_ECDH_CTX_init_for_dhe(&ssl->s3->tmp.ecdh_ctx, dh); + dh = NULL; + + /* Save the peer public key for later. */ + size_t peer_key_len; + if (!CBS_stow(&dh_Ys, &ssl->s3->tmp.peer_key, &peer_key_len)) { + goto err; + } + /* |dh_Ys| was initialized with CBS_get_u16_length_prefixed, so peer_key_len + * fits in a uint16_t. */ + assert(sizeof(ssl->s3->tmp.peer_key_len) == 2 && peer_key_len <= 0xffff); + ssl->s3->tmp.peer_key_len = (uint16_t)peer_key_len; + } else if (alg_k & SSL_kECDHE) { + /* Parse the server parameters. */ + uint8_t group_type; + uint16_t group_id; + CBS point; + if (!CBS_get_u8(&server_key_exchange, &group_type) || + group_type != NAMED_CURVE_TYPE || + !CBS_get_u16(&server_key_exchange, &group_id) || + !CBS_get_u8_length_prefixed(&server_key_exchange, &point)) { + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + goto f_err; + } + ssl->session->key_exchange_info = group_id; + + /* Ensure the group is consistent with preferences. */ + if (!tls1_check_group_id(ssl, group_id)) { + al = SSL_AD_ILLEGAL_PARAMETER; + OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CURVE); + goto f_err; + } + + /* Initialize ECDH and save the peer public key for later. */ + size_t peer_key_len; + if (!SSL_ECDH_CTX_init(&ssl->s3->tmp.ecdh_ctx, group_id) || + !CBS_stow(&point, &ssl->s3->tmp.peer_key, &peer_key_len)) { + goto err; + } + /* |point| was initialized with CBS_get_u8_length_prefixed, so peer_key_len + * fits in a uint16_t. */ + assert(sizeof(ssl->s3->tmp.peer_key_len) == 2 && peer_key_len <= 0xffff); + ssl->s3->tmp.peer_key_len = (uint16_t)peer_key_len; + } else if (alg_k & SSL_kCECPQ1) { + if (!SSL_ECDH_CTX_init(&ssl->s3->tmp.ecdh_ctx, SSL_GROUP_CECPQ1)) { + goto err; + } + CBS key; + if (!CBS_get_u16_length_prefixed(&server_key_exchange, &key)) { + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + goto f_err; + } + + size_t peer_key_len; + if (!CBS_stow(&key, &ssl->s3->tmp.peer_key, &peer_key_len)) { + goto err; + } + /* |key| was initialized with CBS_get_u16_length_prefixed, so peer_key_len + * fits in a uint16_t. */ + assert(sizeof(ssl->s3->tmp.peer_key_len) == 2 && peer_key_len <= 0xffff); + ssl->s3->tmp.peer_key_len = (uint16_t)peer_key_len; + } else if (!(alg_k & SSL_kPSK)) { + al = SSL_AD_UNEXPECTED_MESSAGE; + OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE); + goto f_err; + } + + /* At this point, |server_key_exchange| contains the signature, if any, while + * |server_key_exchange_orig| contains the entire message. From that, derive + * a CBS containing just the parameter. */ + CBS parameter; + CBS_init(¶meter, CBS_data(&server_key_exchange_orig), + CBS_len(&server_key_exchange_orig) - CBS_len(&server_key_exchange)); + + /* ServerKeyExchange should be signed by the server's public key. */ + if (ssl_cipher_uses_certificate_auth(ssl->s3->tmp.new_cipher)) { + pkey = X509_get_pubkey(ssl->session->peer); + if (pkey == NULL) { + goto err; + } + + const EVP_MD *md = NULL; + if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) { + uint8_t hash, signature; + if (!CBS_get_u8(&server_key_exchange, &hash) || + !CBS_get_u8(&server_key_exchange, &signature)) { + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + goto f_err; + } + if (!tls12_check_peer_sigalg(ssl, &md, &al, hash, signature, pkey)) { + goto f_err; + } + ssl->s3->tmp.server_key_exchange_hash = hash; + } else if (pkey->type == EVP_PKEY_RSA) { + md = EVP_md5_sha1(); + } else { + md = EVP_sha1(); + } + + /* The last field in |server_key_exchange| is the signature. */ + CBS signature; + if (!CBS_get_u16_length_prefixed(&server_key_exchange, &signature) || + CBS_len(&server_key_exchange) != 0) { + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + goto f_err; + } + + int sig_ok = EVP_DigestVerifyInit(&md_ctx, NULL, md, NULL, pkey) && + EVP_DigestVerifyUpdate(&md_ctx, ssl->s3->client_random, + SSL3_RANDOM_SIZE) && + EVP_DigestVerifyUpdate(&md_ctx, ssl->s3->server_random, + SSL3_RANDOM_SIZE) && + EVP_DigestVerifyUpdate(&md_ctx, CBS_data(¶meter), + CBS_len(¶meter)) && + EVP_DigestVerifyFinal(&md_ctx, CBS_data(&signature), + CBS_len(&signature)); +#if defined(BORINGSSL_UNSAFE_FUZZER_MODE) + sig_ok = 1; + ERR_clear_error(); +#endif + if (!sig_ok) { + /* bad signature */ + al = SSL_AD_DECRYPT_ERROR; + OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SIGNATURE); + goto f_err; + } + } else { + /* PSK ciphers are the only supported certificate-less ciphers. */ + assert(alg_a == SSL_aPSK); + + if (CBS_len(&server_key_exchange) > 0) { + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, SSL_R_EXTRA_DATA_IN_MESSAGE); + goto f_err; + } + } + EVP_PKEY_free(pkey); + EVP_MD_CTX_cleanup(&md_ctx); + return 1; + +f_err: + ssl3_send_alert(ssl, SSL3_AL_FATAL, al); +err: + EVP_PKEY_free(pkey); + DH_free(dh); + EC_POINT_free(srvr_ecpoint); + EC_KEY_free(ecdh); + EVP_MD_CTX_cleanup(&md_ctx); + return -1; +} + +static int ca_dn_cmp(const X509_NAME **a, const X509_NAME **b) { + return X509_NAME_cmp(*a, *b); +} + +static int ssl3_get_certificate_request(SSL *ssl) { + int ok, ret = 0; + X509_NAME *xn = NULL; + STACK_OF(X509_NAME) *ca_sk = NULL; + + long n = ssl->method->ssl_get_message(ssl, -1, ssl_hash_message, &ok); + + if (!ok) { + return n; + } + + ssl->s3->tmp.cert_req = 0; + + if (ssl->s3->tmp.message_type == SSL3_MT_SERVER_HELLO_DONE) { + ssl->s3->tmp.reuse_message = 1; + /* If we get here we don't need the handshake buffer as we won't be doing + * client auth. */ + ssl3_free_handshake_buffer(ssl); + return 1; + } + + if (ssl->s3->tmp.message_type != SSL3_MT_CERTIFICATE_REQUEST) { + ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE); + OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE); + goto err; + } + + CBS cbs; + CBS_init(&cbs, ssl->init_msg, n); + + ca_sk = sk_X509_NAME_new(ca_dn_cmp); + if (ca_sk == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + goto err; + } + + /* get the certificate types */ + CBS certificate_types; + if (!CBS_get_u8_length_prefixed(&cbs, &certificate_types)) { + ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + goto err; + } + + if (!CBS_stow(&certificate_types, &ssl->s3->tmp.certificate_types, + &ssl->s3->tmp.num_certificate_types)) { + ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); + goto err; + } + + if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) { + CBS supported_signature_algorithms; + if (!CBS_get_u16_length_prefixed(&cbs, &supported_signature_algorithms) || + !tls1_parse_peer_sigalgs(ssl, &supported_signature_algorithms)) { + ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + goto err; + } + } + + /* get the CA RDNs */ + CBS certificate_authorities; + if (!CBS_get_u16_length_prefixed(&cbs, &certificate_authorities)) { + ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + OPENSSL_PUT_ERROR(SSL, SSL_R_LENGTH_MISMATCH); + goto err; + } + + while (CBS_len(&certificate_authorities) > 0) { + CBS distinguished_name; + if (!CBS_get_u16_length_prefixed(&certificate_authorities, + &distinguished_name)) { + ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + OPENSSL_PUT_ERROR(SSL, SSL_R_CA_DN_TOO_LONG); + goto err; + } + + const uint8_t *data = CBS_data(&distinguished_name); + /* A u16 length cannot overflow a long. */ + xn = d2i_X509_NAME(NULL, &data, (long)CBS_len(&distinguished_name)); + if (xn == NULL || + data != CBS_data(&distinguished_name) + CBS_len(&distinguished_name)) { + ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + goto err; + } + + if (!sk_X509_NAME_push(ca_sk, xn)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + goto err; + } + xn = NULL; + } + + /* we should setup a certificate to return.... */ + ssl->s3->tmp.cert_req = 1; + sk_X509_NAME_pop_free(ssl->s3->tmp.ca_names, X509_NAME_free); + ssl->s3->tmp.ca_names = ca_sk; + ca_sk = NULL; + + ret = 1; + +err: + X509_NAME_free(xn); + sk_X509_NAME_pop_free(ca_sk, X509_NAME_free); + return ret; +} + +static int ssl3_get_server_hello_done(SSL *ssl) { + int ok; + long n; + + n = ssl->method->ssl_get_message(ssl, SSL3_MT_SERVER_HELLO_DONE, + ssl_hash_message, &ok); + + if (!ok) { + return n; + } + + if (n > 0) { + /* should contain no data */ + ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + OPENSSL_PUT_ERROR(SSL, SSL_R_LENGTH_MISMATCH); + return -1; + } + + return 1; +} + +/* ssl3_has_client_certificate returns true if a client certificate is + * configured. */ +static int ssl3_has_client_certificate(SSL *ssl) { + return ssl->cert && ssl->cert->x509 && ssl_has_private_key(ssl); +} + +static int ssl_do_client_cert_cb(SSL *ssl, X509 **out_x509, + EVP_PKEY **out_pkey) { + if (ssl->ctx->client_cert_cb == NULL) { + return 0; + } + + int ret = ssl->ctx->client_cert_cb(ssl, out_x509, out_pkey); + if (ret <= 0) { + return ret; + } + + assert(*out_x509 != NULL); + assert(*out_pkey != NULL); + return 1; +} + +static int ssl3_send_client_certificate(SSL *ssl) { + if (ssl->state == SSL3_ST_CW_CERT_A) { + /* Call cert_cb to update the certificate. */ + if (ssl->cert->cert_cb) { + int ret = ssl->cert->cert_cb(ssl, ssl->cert->cert_cb_arg); + if (ret < 0) { + ssl->rwstate = SSL_X509_LOOKUP; + return -1; + } + if (ret == 0) { + ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); + return -1; + } + } + + if (ssl3_has_client_certificate(ssl)) { + ssl->state = SSL3_ST_CW_CERT_C; + } else { + ssl->state = SSL3_ST_CW_CERT_B; + } + } + + if (ssl->state == SSL3_ST_CW_CERT_B) { + /* Call client_cert_cb to update the certificate. */ + X509 *x509 = NULL; + EVP_PKEY *pkey = NULL; + int ret = ssl_do_client_cert_cb(ssl, &x509, &pkey); + if (ret < 0) { + ssl->rwstate = SSL_X509_LOOKUP; + return -1; + } + + int setup_error = ret == 1 && (!SSL_use_certificate(ssl, x509) || + !SSL_use_PrivateKey(ssl, pkey)); + X509_free(x509); + EVP_PKEY_free(pkey); + if (setup_error) { + ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); + return -1; + } + + ssl->state = SSL3_ST_CW_CERT_C; + } + + if (ssl->state == SSL3_ST_CW_CERT_C) { + if (!ssl3_has_client_certificate(ssl)) { + /* Without a client certificate, the handshake buffer may be released. */ + ssl3_free_handshake_buffer(ssl); + + if (ssl->version == SSL3_VERSION) { + /* In SSL 3.0, send no certificate by skipping both messages. */ + ssl->s3->tmp.cert_req = 0; + ssl3_send_alert(ssl, SSL3_AL_WARNING, SSL_AD_NO_CERTIFICATE); + return 1; + } + + /* In TLS, send an empty Certificate message. */ + ssl->s3->tmp.cert_req = 2; + uint8_t *p = ssl_handshake_start(ssl); + l2n3(0, p); + if (!ssl_set_handshake_header(ssl, SSL3_MT_CERTIFICATE, 3)) { + return -1; + } + } else if (!ssl3_output_cert_chain(ssl)) { + return -1; + } + ssl->state = SSL3_ST_CW_CERT_D; + } + + assert(ssl->state == SSL3_ST_CW_CERT_D); + return ssl_do_write(ssl); +} + +OPENSSL_COMPILE_ASSERT(sizeof(size_t) >= sizeof(unsigned), + SIZE_T_IS_SMALLER_THAN_UNSIGNED); + +static int ssl3_send_client_key_exchange(SSL *ssl) { + if (ssl->state == SSL3_ST_CW_KEY_EXCH_B) { + return ssl_do_write(ssl); + } + assert(ssl->state == SSL3_ST_CW_KEY_EXCH_A); + + uint8_t *pms = NULL; + size_t pms_len = 0; + CBB cbb; + if (!CBB_init_fixed(&cbb, ssl_handshake_start(ssl), + ssl->init_buf->max - SSL_HM_HEADER_LENGTH(ssl))) { + goto err; + } + + uint32_t alg_k = ssl->s3->tmp.new_cipher->algorithm_mkey; + uint32_t alg_a = ssl->s3->tmp.new_cipher->algorithm_auth; + + /* If using a PSK key exchange, prepare the pre-shared key. */ + unsigned psk_len = 0; + uint8_t psk[PSK_MAX_PSK_LEN]; + if (alg_a & SSL_aPSK) { + if (ssl->psk_client_callback == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_NO_CLIENT_CB); + goto err; + } + + char identity[PSK_MAX_IDENTITY_LEN + 1]; + memset(identity, 0, sizeof(identity)); + psk_len = ssl->psk_client_callback( + ssl, ssl->s3->tmp.peer_psk_identity_hint, identity, sizeof(identity), + psk, sizeof(psk)); + if (psk_len == 0) { + OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_IDENTITY_NOT_FOUND); + ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); + goto err; + } + assert(psk_len <= PSK_MAX_PSK_LEN); + + OPENSSL_free(ssl->session->psk_identity); + ssl->session->psk_identity = BUF_strdup(identity); + if (ssl->session->psk_identity == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + goto err; + } + + /* Write out psk_identity. */ + CBB child; + if (!CBB_add_u16_length_prefixed(&cbb, &child) || + !CBB_add_bytes(&child, (const uint8_t *)identity, + OPENSSL_strnlen(identity, sizeof(identity))) || + !CBB_flush(&cbb)) { + goto err; + } + } + + /* Depending on the key exchange method, compute |pms| and |pms_len|. */ + if (alg_k & SSL_kRSA) { + pms_len = SSL_MAX_MASTER_KEY_LENGTH; + pms = OPENSSL_malloc(pms_len); + if (pms == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + goto err; + } + + EVP_PKEY *pkey = X509_get_pubkey(ssl->session->peer); + if (pkey == NULL) { + goto err; + } + + RSA *rsa = EVP_PKEY_get0_RSA(pkey); + if (rsa == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + EVP_PKEY_free(pkey); + goto err; + } + + ssl->session->key_exchange_info = EVP_PKEY_bits(pkey); + EVP_PKEY_free(pkey); + + pms[0] = ssl->client_version >> 8; + pms[1] = ssl->client_version & 0xff; + if (!RAND_bytes(&pms[2], SSL_MAX_MASTER_KEY_LENGTH - 2)) { + goto err; + } + + CBB child, *enc_pms = &cbb; + size_t enc_pms_len; + /* In TLS, there is a length prefix. */ + if (ssl->version > SSL3_VERSION) { + if (!CBB_add_u16_length_prefixed(&cbb, &child)) { + goto err; + } + enc_pms = &child; + } + + uint8_t *ptr; + if (!CBB_reserve(enc_pms, &ptr, RSA_size(rsa)) || + !RSA_encrypt(rsa, &enc_pms_len, ptr, RSA_size(rsa), pms, pms_len, + RSA_PKCS1_PADDING) || + /* Log the premaster secret, if logging is enabled. */ + !ssl_log_rsa_client_key_exchange(ssl, ptr, enc_pms_len, pms, pms_len) || + !CBB_did_write(enc_pms, enc_pms_len) || + !CBB_flush(&cbb)) { + goto err; + } + } else if (alg_k & (SSL_kECDHE|SSL_kDHE|SSL_kCECPQ1)) { + /* Generate a keypair and serialize the public half. */ + CBB child; + if (!SSL_ECDH_CTX_add_key(&ssl->s3->tmp.ecdh_ctx, &cbb, &child)) { + goto err; + } + + /* Compute the premaster. */ + uint8_t alert; + if (!SSL_ECDH_CTX_accept(&ssl->s3->tmp.ecdh_ctx, &child, &pms, &pms_len, + &alert, ssl->s3->tmp.peer_key, + ssl->s3->tmp.peer_key_len)) { + ssl3_send_alert(ssl, SSL3_AL_FATAL, alert); + goto err; + } + if (!CBB_flush(&cbb)) { + goto err; + } + + /* The key exchange state may now be discarded. */ + SSL_ECDH_CTX_cleanup(&ssl->s3->tmp.ecdh_ctx); + OPENSSL_free(ssl->s3->tmp.peer_key); + ssl->s3->tmp.peer_key = NULL; + } else if (alg_k & SSL_kPSK) { + /* For plain PSK, other_secret is a block of 0s with the same length as + * the pre-shared key. */ + pms_len = psk_len; + pms = OPENSSL_malloc(pms_len); + if (pms == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + goto err; + } + memset(pms, 0, pms_len); + } else { + ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + goto err; + } + + /* For a PSK cipher suite, other_secret is combined with the pre-shared + * key. */ + if (alg_a & SSL_aPSK) { + CBB pms_cbb, child; + uint8_t *new_pms; + size_t new_pms_len; + + CBB_zero(&pms_cbb); + if (!CBB_init(&pms_cbb, 2 + psk_len + 2 + pms_len) || + !CBB_add_u16_length_prefixed(&pms_cbb, &child) || + !CBB_add_bytes(&child, pms, pms_len) || + !CBB_add_u16_length_prefixed(&pms_cbb, &child) || + !CBB_add_bytes(&child, psk, psk_len) || + !CBB_finish(&pms_cbb, &new_pms, &new_pms_len)) { + CBB_cleanup(&pms_cbb); + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + goto err; + } + OPENSSL_cleanse(pms, pms_len); + OPENSSL_free(pms); + pms = new_pms; + pms_len = new_pms_len; + } + + /* The message must be added to the finished hash before calculating the + * master secret. */ + size_t length; + if (!CBB_finish(&cbb, NULL, &length) || + !ssl_set_handshake_header(ssl, SSL3_MT_CLIENT_KEY_EXCHANGE, length)) { + goto err; + } + ssl->state = SSL3_ST_CW_KEY_EXCH_B; + + ssl->session->master_key_length = + tls1_generate_master_secret(ssl, ssl->session->master_key, pms, pms_len); + if (ssl->session->master_key_length == 0) { + goto err; + } + ssl->session->extended_master_secret = ssl->s3->tmp.extended_master_secret; + OPENSSL_cleanse(pms, pms_len); + OPENSSL_free(pms); + + /* SSL3_ST_CW_KEY_EXCH_B */ + return ssl_do_write(ssl); + +err: + CBB_cleanup(&cbb); + if (pms != NULL) { + OPENSSL_cleanse(pms, pms_len); + OPENSSL_free(pms); + } + return -1; +} + +static int ssl3_send_cert_verify(SSL *ssl) { + if (ssl->state == SSL3_ST_CW_CERT_VRFY_C) { + return ssl_do_write(ssl); + } + + CBB cbb, child; + if (!CBB_init_fixed(&cbb, ssl_handshake_start(ssl), + ssl->init_buf->max - SSL_HM_HEADER_LENGTH(ssl))) { + goto err; + } + + assert(ssl_has_private_key(ssl)); + + const size_t max_sig_len = ssl_private_key_max_signature_len(ssl); + size_t sig_len; + enum ssl_private_key_result_t sign_result; + if (ssl->state == SSL3_ST_CW_CERT_VRFY_A) { + /* Select and write out the digest type in TLS 1.2. */ + const EVP_MD *md = NULL; + if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) { + md = tls1_choose_signing_digest(ssl); + if (!tls12_add_sigandhash(ssl, &cbb, md)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + goto err; + } + } + + /* Compute the digest. In TLS 1.1 and below, the digest type is also + * selected here. */ + uint8_t digest[EVP_MAX_MD_SIZE]; + size_t digest_len; + if (!ssl3_cert_verify_hash(ssl, digest, &digest_len, &md, + ssl_private_key_type(ssl))) { + goto err; + } + + /* The handshake buffer is no longer necessary. */ + ssl3_free_handshake_buffer(ssl); + + /* Sign the digest. */ + uint8_t *ptr; + if (!CBB_add_u16_length_prefixed(&cbb, &child) || + !CBB_reserve(&child, &ptr, max_sig_len)) { + goto err; + } + sign_result = ssl_private_key_sign(ssl, ptr, &sig_len, max_sig_len, md, + digest, digest_len); + } else { + assert(ssl->state == SSL3_ST_CW_CERT_VRFY_B); + + /* Skip over the already written signature algorithm and retry the + * signature. */ + uint8_t *ptr; + if ((ssl3_protocol_version(ssl) >= TLS1_2_VERSION && + !CBB_did_write(&cbb, 2)) || + !CBB_add_u16_length_prefixed(&cbb, &child) || + !CBB_reserve(&child, &ptr, max_sig_len)) { + goto err; + } + sign_result = + ssl_private_key_sign_complete(ssl, ptr, &sig_len, max_sig_len); + } + + switch (sign_result) { + case ssl_private_key_success: + break; + case ssl_private_key_failure: + goto err; + case ssl_private_key_retry: + ssl->rwstate = SSL_PRIVATE_KEY_OPERATION; + ssl->state = SSL3_ST_CW_CERT_VRFY_B; + goto err; + } + + size_t length; + if (!CBB_did_write(&child, sig_len) || + !CBB_finish(&cbb, NULL, &length) || + !ssl_set_handshake_header(ssl, SSL3_MT_CERTIFICATE_VERIFY, length)) { + goto err; + } + + ssl->state = SSL3_ST_CW_CERT_VRFY_C; + return ssl_do_write(ssl); + +err: + CBB_cleanup(&cbb); + return -1; +} + +static int ssl3_send_next_proto(SSL *ssl) { + if (ssl->state == SSL3_ST_CW_NEXT_PROTO_B) { + return ssl_do_write(ssl); + } + + assert(ssl->state == SSL3_ST_CW_NEXT_PROTO_A); + + static const uint8_t kZero[32] = {0}; + size_t padding_len = 32 - ((ssl->s3->next_proto_negotiated_len + 2) % 32); + + CBB cbb, child; + size_t length; + CBB_zero(&cbb); + if (!CBB_init_fixed(&cbb, ssl_handshake_start(ssl), + ssl->init_buf->max - SSL_HM_HEADER_LENGTH(ssl)) || + !CBB_add_u8_length_prefixed(&cbb, &child) || + !CBB_add_bytes(&child, ssl->s3->next_proto_negotiated, + ssl->s3->next_proto_negotiated_len) || + !CBB_add_u8_length_prefixed(&cbb, &child) || + !CBB_add_bytes(&child, kZero, padding_len) || + !CBB_finish(&cbb, NULL, &length) || + !ssl_set_handshake_header(ssl, SSL3_MT_NEXT_PROTO, length)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + CBB_cleanup(&cbb); + return -1; + } + + ssl->state = SSL3_ST_CW_NEXT_PROTO_B; + return ssl_do_write(ssl); +} + +static int ssl3_send_channel_id(SSL *ssl) { + if (ssl->state == SSL3_ST_CW_CHANNEL_ID_B) { + return ssl_do_write(ssl); + } + + assert(ssl->state == SSL3_ST_CW_CHANNEL_ID_A); + + if (ssl->tlsext_channel_id_private == NULL && + ssl->ctx->channel_id_cb != NULL) { + EVP_PKEY *key = NULL; + ssl->ctx->channel_id_cb(ssl, &key); + if (key != NULL && + !SSL_set1_tls_channel_id(ssl, key)) { + EVP_PKEY_free(key); + return -1; + } + EVP_PKEY_free(key); + } + + if (ssl->tlsext_channel_id_private == NULL) { + ssl->rwstate = SSL_CHANNEL_ID_LOOKUP; + return -1; + } + + EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(ssl->tlsext_channel_id_private); + if (ec_key == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + return -1; + } + + int ret = -1; + BIGNUM *x = BN_new(); + BIGNUM *y = BN_new(); + ECDSA_SIG *sig = NULL; + if (x == NULL || y == NULL || + !EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(ec_key), + EC_KEY_get0_public_key(ec_key), + x, y, NULL)) { + goto err; + } + + uint8_t digest[EVP_MAX_MD_SIZE]; + size_t digest_len; + if (!tls1_channel_id_hash(ssl, digest, &digest_len)) { + goto err; + } + + sig = ECDSA_do_sign(digest, digest_len, ec_key); + if (sig == NULL) { + goto err; + } + + CBB cbb, child; + size_t length; + CBB_zero(&cbb); + if (!CBB_init_fixed(&cbb, ssl_handshake_start(ssl), + ssl->init_buf->max - SSL_HM_HEADER_LENGTH(ssl)) || + !CBB_add_u16(&cbb, TLSEXT_TYPE_channel_id) || + !CBB_add_u16_length_prefixed(&cbb, &child) || + !BN_bn2cbb_padded(&child, 32, x) || + !BN_bn2cbb_padded(&child, 32, y) || + !BN_bn2cbb_padded(&child, 32, sig->r) || + !BN_bn2cbb_padded(&child, 32, sig->s) || + !CBB_finish(&cbb, NULL, &length) || + !ssl_set_handshake_header(ssl, SSL3_MT_CHANNEL_ID_ENCRYPTED_EXTENSIONS, + length)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + CBB_cleanup(&cbb); + goto err; + } + + ssl->state = SSL3_ST_CW_CHANNEL_ID_B; + ret = ssl_do_write(ssl); + +err: + BN_free(x); + BN_free(y); + ECDSA_SIG_free(sig); + return ret; +} + +static int ssl3_get_new_session_ticket(SSL *ssl) { + int ok, al; + long n = ssl->method->ssl_get_message(ssl, SSL3_MT_NEW_SESSION_TICKET, + ssl_hash_message, &ok); + + if (!ok) { + return n; + } + + CBS new_session_ticket, ticket; + uint32_t ticket_lifetime_hint; + CBS_init(&new_session_ticket, ssl->init_msg, n); + if (!CBS_get_u32(&new_session_ticket, &ticket_lifetime_hint) || + !CBS_get_u16_length_prefixed(&new_session_ticket, &ticket) || + CBS_len(&new_session_ticket) != 0) { + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + goto f_err; + } + + if (CBS_len(&ticket) == 0) { + /* RFC 5077 allows a server to change its mind and send no ticket after + * negotiating the extension. The value of |tlsext_ticket_expected| is + * checked in |ssl_update_cache| so is cleared here to avoid an unnecessary + * update. */ + ssl->tlsext_ticket_expected = 0; + return 1; + } + + if (ssl->hit) { + /* The server is sending a new ticket for an existing session. Sessions are + * immutable once established, so duplicate all but the ticket of the + * existing session. */ + uint8_t *bytes; + size_t bytes_len; + if (!SSL_SESSION_to_bytes_for_ticket(ssl->session, &bytes, &bytes_len)) { + goto err; + } + SSL_SESSION *new_session = SSL_SESSION_from_bytes(bytes, bytes_len); + OPENSSL_free(bytes); + if (new_session == NULL) { + /* This should never happen. */ + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + goto err; + } + + SSL_SESSION_free(ssl->session); + ssl->session = new_session; + } + + if (!CBS_stow(&ticket, &ssl->session->tlsext_tick, + &ssl->session->tlsext_ticklen)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + goto err; + } + ssl->session->tlsext_tick_lifetime_hint = ticket_lifetime_hint; + + /* Generate a session ID for this session based on the session ticket. We use + * the session ID mechanism for detecting ticket resumption. This also fits in + * with assumptions elsewhere in OpenSSL.*/ + if (!EVP_Digest(CBS_data(&ticket), CBS_len(&ticket), ssl->session->session_id, + &ssl->session->session_id_length, EVP_sha256(), NULL)) { + goto err; + } + + return 1; + +f_err: + ssl3_send_alert(ssl, SSL3_AL_FATAL, al); +err: + return -1; +} diff --git a/external/boringssl/ssl/handshake_server.c b/external/boringssl/ssl/handshake_server.c new file mode 100644 index 0000000000..68a013eba5 --- /dev/null +++ b/external/boringssl/ssl/handshake_server.c @@ -0,0 +1,2225 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * + * Portions of the attached software ("Contribution") are developed by + * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. + * + * The Contribution is licensed pursuant to the OpenSSL open source + * license provided above. + * + * ECC cipher suite support in OpenSSL originally written by + * Vipul Gupta and Sumit Gupta of Sun Microsystems Laboratories. + * + */ +/* ==================================================================== + * Copyright 2005 Nokia. All rights reserved. + * + * The portions of the attached software ("Contribution") is developed by + * Nokia Corporation and is licensed pursuant to the OpenSSL open source + * license. + * + * The Contribution, originally written by Mika Kousa and Pasi Eronen of + * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites + * support (see RFC 4279) to OpenSSL. + * + * No patent licenses or other rights except those expressly stated in + * the OpenSSL open source license shall be deemed granted or received + * expressly, by implication, estoppel, or otherwise. + * + * No assurances are provided by Nokia that the Contribution does not + * infringe the patent or other intellectual property rights of any third + * party or that the license provides you with all the necessary rights + * to make use of the Contribution. + * + * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN + * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA + * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY + * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR + * OTHERWISE. */ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "internal.h" +#include "../crypto/internal.h" +#include "../crypto/dh/internal.h" + + +static int ssl3_get_initial_bytes(SSL *ssl); +static int ssl3_get_v2_client_hello(SSL *ssl); +static int ssl3_get_client_hello(SSL *ssl); +static int ssl3_send_server_hello(SSL *ssl); +static int ssl3_send_server_certificate(SSL *ssl); +static int ssl3_send_certificate_status(SSL *ssl); +static int ssl3_send_server_key_exchange(SSL *ssl); +static int ssl3_send_certificate_request(SSL *ssl); +static int ssl3_send_server_hello_done(SSL *ssl); +static int ssl3_get_client_certificate(SSL *ssl); +static int ssl3_get_client_key_exchange(SSL *ssl); +static int ssl3_get_cert_verify(SSL *ssl); +static int ssl3_get_next_proto(SSL *ssl); +static int ssl3_get_channel_id(SSL *ssl); +static int ssl3_send_new_session_ticket(SSL *ssl); + +int ssl3_accept(SSL *ssl) { + BUF_MEM *buf = NULL; + uint32_t alg_a; + int ret = -1; + int state, skip = 0; + + assert(ssl->handshake_func == ssl3_accept); + assert(ssl->server); + + for (;;) { + state = ssl->state; + + switch (ssl->state) { + case SSL_ST_ACCEPT: + ssl_do_info_callback(ssl, SSL_CB_HANDSHAKE_START, 1); + + if (ssl->init_buf == NULL) { + buf = BUF_MEM_new(); + if (!buf || !BUF_MEM_reserve(buf, SSL3_RT_MAX_PLAIN_LENGTH)) { + ret = -1; + goto end; + } + ssl->init_buf = buf; + buf = NULL; + } + ssl->init_num = 0; + + /* Enable a write buffer. This groups handshake messages within a flight + * into a single write. */ + if (!ssl_init_wbio_buffer(ssl)) { + ret = -1; + goto end; + } + + if (!ssl3_init_handshake_buffer(ssl)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + ret = -1; + goto end; + } + + if (!ssl->s3->have_version && !SSL_IS_DTLS(ssl)) { + ssl->state = SSL3_ST_SR_INITIAL_BYTES; + } else { + ssl->state = SSL3_ST_SR_CLNT_HELLO_A; + } + break; + + case SSL3_ST_SR_INITIAL_BYTES: + assert(!SSL_IS_DTLS(ssl)); + ret = ssl3_get_initial_bytes(ssl); + if (ret <= 0) { + goto end; + } + /* ssl3_get_initial_bytes sets ssl->state to one of + * SSL3_ST_SR_V2_CLIENT_HELLO or SSL3_ST_SR_CLNT_HELLO_A on success. */ + break; + + case SSL3_ST_SR_V2_CLIENT_HELLO: + assert(!SSL_IS_DTLS(ssl)); + ret = ssl3_get_v2_client_hello(ssl); + if (ret <= 0) { + goto end; + } + ssl->state = SSL3_ST_SR_CLNT_HELLO_A; + break; + + case SSL3_ST_SR_CLNT_HELLO_A: + case SSL3_ST_SR_CLNT_HELLO_B: + case SSL3_ST_SR_CLNT_HELLO_C: + ret = ssl3_get_client_hello(ssl); + if (ret <= 0) { + goto end; + } + ssl->method->received_flight(ssl); + ssl->state = SSL3_ST_SW_SRVR_HELLO_A; + break; + + case SSL3_ST_SW_SRVR_HELLO_A: + case SSL3_ST_SW_SRVR_HELLO_B: + ret = ssl3_send_server_hello(ssl); + if (ret <= 0) { + goto end; + } + if (ssl->hit) { + if (ssl->tlsext_ticket_expected) { + ssl->state = SSL3_ST_SW_SESSION_TICKET_A; + } else { + ssl->state = SSL3_ST_SW_CHANGE_A; + } + } else { + ssl->state = SSL3_ST_SW_CERT_A; + } + break; + + case SSL3_ST_SW_CERT_A: + case SSL3_ST_SW_CERT_B: + if (ssl_cipher_uses_certificate_auth(ssl->s3->tmp.new_cipher)) { + ret = ssl3_send_server_certificate(ssl); + if (ret <= 0) { + goto end; + } + if (ssl->s3->tmp.certificate_status_expected) { + ssl->state = SSL3_ST_SW_CERT_STATUS_A; + } else { + ssl->state = SSL3_ST_SW_KEY_EXCH_A; + } + } else { + skip = 1; + ssl->state = SSL3_ST_SW_KEY_EXCH_A; + } + break; + + case SSL3_ST_SW_CERT_STATUS_A: + case SSL3_ST_SW_CERT_STATUS_B: + ret = ssl3_send_certificate_status(ssl); + if (ret <= 0) { + goto end; + } + ssl->state = SSL3_ST_SW_KEY_EXCH_A; + break; + + case SSL3_ST_SW_KEY_EXCH_A: + case SSL3_ST_SW_KEY_EXCH_B: + case SSL3_ST_SW_KEY_EXCH_C: + alg_a = ssl->s3->tmp.new_cipher->algorithm_auth; + + /* PSK ciphers send ServerKeyExchange if there is an identity hint. */ + if (ssl_cipher_requires_server_key_exchange(ssl->s3->tmp.new_cipher) || + ((alg_a & SSL_aPSK) && ssl->psk_identity_hint)) { + ret = ssl3_send_server_key_exchange(ssl); + if (ret <= 0) { + goto end; + } + } else { + skip = 1; + } + + ssl->state = SSL3_ST_SW_CERT_REQ_A; + break; + + case SSL3_ST_SW_CERT_REQ_A: + case SSL3_ST_SW_CERT_REQ_B: + if (ssl->s3->tmp.cert_request) { + ret = ssl3_send_certificate_request(ssl); + if (ret <= 0) { + goto end; + } + } else { + skip = 1; + } + ssl->state = SSL3_ST_SW_SRVR_DONE_A; + break; + + case SSL3_ST_SW_SRVR_DONE_A: + case SSL3_ST_SW_SRVR_DONE_B: + ret = ssl3_send_server_hello_done(ssl); + if (ret <= 0) { + goto end; + } + ssl->s3->tmp.next_state = SSL3_ST_SR_CERT_A; + ssl->state = SSL3_ST_SW_FLUSH; + break; + + case SSL3_ST_SR_CERT_A: + if (ssl->s3->tmp.cert_request) { + ret = ssl3_get_client_certificate(ssl); + if (ret <= 0) { + goto end; + } + } + ssl->state = SSL3_ST_SR_KEY_EXCH_A; + break; + + case SSL3_ST_SR_KEY_EXCH_A: + case SSL3_ST_SR_KEY_EXCH_B: + ret = ssl3_get_client_key_exchange(ssl); + if (ret <= 0) { + goto end; + } + ssl->state = SSL3_ST_SR_CERT_VRFY_A; + break; + + case SSL3_ST_SR_CERT_VRFY_A: + ret = ssl3_get_cert_verify(ssl); + if (ret <= 0) { + goto end; + } + + ssl->state = SSL3_ST_SR_CHANGE; + break; + + case SSL3_ST_SR_CHANGE: + ret = ssl->method->ssl_read_change_cipher_spec(ssl); + if (ret <= 0) { + goto end; + } + + if (!tls1_change_cipher_state(ssl, SSL3_CHANGE_CIPHER_SERVER_READ)) { + ret = -1; + goto end; + } + + if (ssl->s3->next_proto_neg_seen) { + ssl->state = SSL3_ST_SR_NEXT_PROTO_A; + } else if (ssl->s3->tlsext_channel_id_valid) { + ssl->state = SSL3_ST_SR_CHANNEL_ID_A; + } else { + ssl->state = SSL3_ST_SR_FINISHED_A; + } + break; + + case SSL3_ST_SR_NEXT_PROTO_A: + ret = ssl3_get_next_proto(ssl); + if (ret <= 0) { + goto end; + } + if (ssl->s3->tlsext_channel_id_valid) { + ssl->state = SSL3_ST_SR_CHANNEL_ID_A; + } else { + ssl->state = SSL3_ST_SR_FINISHED_A; + } + break; + + case SSL3_ST_SR_CHANNEL_ID_A: + ret = ssl3_get_channel_id(ssl); + if (ret <= 0) { + goto end; + } + ssl->state = SSL3_ST_SR_FINISHED_A; + break; + + case SSL3_ST_SR_FINISHED_A: + ret = ssl3_get_finished(ssl); + if (ret <= 0) { + goto end; + } + + ssl->method->received_flight(ssl); + if (ssl->hit) { + ssl->state = SSL_ST_OK; + } else if (ssl->tlsext_ticket_expected) { + ssl->state = SSL3_ST_SW_SESSION_TICKET_A; + } else { + ssl->state = SSL3_ST_SW_CHANGE_A; + } + + /* If this is a full handshake with ChannelID then record the hashshake + * hashes in |ssl->session| in case we need them to verify a ChannelID + * signature on a resumption of this session in the future. */ + if (!ssl->hit && ssl->s3->tlsext_channel_id_valid) { + ret = tls1_record_handshake_hashes_for_channel_id(ssl); + if (ret <= 0) { + goto end; + } + } + break; + + case SSL3_ST_SW_SESSION_TICKET_A: + case SSL3_ST_SW_SESSION_TICKET_B: + ret = ssl3_send_new_session_ticket(ssl); + if (ret <= 0) { + goto end; + } + ssl->state = SSL3_ST_SW_CHANGE_A; + break; + + case SSL3_ST_SW_CHANGE_A: + case SSL3_ST_SW_CHANGE_B: + ret = ssl->method->send_change_cipher_spec(ssl, SSL3_ST_SW_CHANGE_A, + SSL3_ST_SW_CHANGE_B); + if (ret <= 0) { + goto end; + } + ssl->state = SSL3_ST_SW_FINISHED_A; + + if (!tls1_change_cipher_state(ssl, SSL3_CHANGE_CIPHER_SERVER_WRITE)) { + ret = -1; + goto end; + } + break; + + case SSL3_ST_SW_FINISHED_A: + case SSL3_ST_SW_FINISHED_B: + ret = ssl3_send_finished(ssl, SSL3_ST_SW_FINISHED_A, + SSL3_ST_SW_FINISHED_B); + if (ret <= 0) { + goto end; + } + ssl->state = SSL3_ST_SW_FLUSH; + if (ssl->hit) { + ssl->s3->tmp.next_state = SSL3_ST_SR_CHANGE; + } else { + ssl->s3->tmp.next_state = SSL_ST_OK; + } + break; + + case SSL3_ST_SW_FLUSH: + if (BIO_flush(ssl->wbio) <= 0) { + ssl->rwstate = SSL_WRITING; + ret = -1; + goto end; + } + + ssl->state = ssl->s3->tmp.next_state; + if (ssl->state != SSL_ST_OK) { + ssl->method->expect_flight(ssl); + } + break; + + case SSL_ST_OK: + /* clean a few things up */ + ssl3_cleanup_key_block(ssl); + + /* In DTLS, |init_buf| cannot be released because post-handshake + * retransmit relies on that buffer being available as scratch space. + * + * TODO(davidben): Fix this. */ + if (!SSL_IS_DTLS(ssl)) { + BUF_MEM_free(ssl->init_buf); + ssl->init_buf = NULL; + ssl->init_num = 0; + } + + /* remove buffering on output */ + ssl_free_wbio_buffer(ssl); + + /* If we aren't retaining peer certificates then we can discard it + * now. */ + if (ssl->ctx->retain_only_sha256_of_client_certs) { + X509_free(ssl->session->peer); + ssl->session->peer = NULL; + sk_X509_pop_free(ssl->session->cert_chain, X509_free); + ssl->session->cert_chain = NULL; + } + + if (SSL_IS_DTLS(ssl)) { + ssl->d1->handshake_read_seq = 0; + ssl->d1->handshake_write_seq = 0; + ssl->d1->next_handshake_write_seq = 0; + } + + ssl->s3->initial_handshake_complete = 1; + + ssl_update_cache(ssl, SSL_SESS_CACHE_SERVER); + + ssl_do_info_callback(ssl, SSL_CB_HANDSHAKE_DONE, 1); + + ret = 1; + goto end; + + default: + OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_STATE); + ret = -1; + goto end; + } + + if (!ssl->s3->tmp.reuse_message && !skip && ssl->state != state) { + int new_state = ssl->state; + ssl->state = state; + ssl_do_info_callback(ssl, SSL_CB_ACCEPT_LOOP, 1); + ssl->state = new_state; + } + skip = 0; + } + +end: + BUF_MEM_free(buf); + ssl_do_info_callback(ssl, SSL_CB_ACCEPT_EXIT, ret); + return ret; +} + +static int ssl3_get_initial_bytes(SSL *ssl) { + /* Read the first 5 bytes, the size of the TLS record header. This is + * sufficient to detect a V2ClientHello and ensures that we never read beyond + * the first record. */ + int ret = ssl_read_buffer_extend_to(ssl, SSL3_RT_HEADER_LENGTH); + if (ret <= 0) { + return ret; + } + assert(ssl_read_buffer_len(ssl) == SSL3_RT_HEADER_LENGTH); + const uint8_t *p = ssl_read_buffer(ssl); + + /* Some dedicated error codes for protocol mixups should the application wish + * to interpret them differently. (These do not overlap with ClientHello or + * V2ClientHello.) */ + if (strncmp("GET ", (const char *)p, 4) == 0 || + strncmp("POST ", (const char *)p, 5) == 0 || + strncmp("HEAD ", (const char *)p, 5) == 0 || + strncmp("PUT ", (const char *)p, 4) == 0) { + OPENSSL_PUT_ERROR(SSL, SSL_R_HTTP_REQUEST); + return -1; + } + if (strncmp("CONNE", (const char *)p, 5) == 0) { + OPENSSL_PUT_ERROR(SSL, SSL_R_HTTPS_PROXY_REQUEST); + return -1; + } + + /* Determine if this is a V2ClientHello. */ + if ((p[0] & 0x80) && p[2] == SSL2_MT_CLIENT_HELLO && + p[3] >= SSL3_VERSION_MAJOR) { + /* This is a V2ClientHello. */ + ssl->state = SSL3_ST_SR_V2_CLIENT_HELLO; + return 1; + } + + /* Fall through to the standard logic. */ + ssl->state = SSL3_ST_SR_CLNT_HELLO_A; + return 1; +} + +static int ssl3_get_v2_client_hello(SSL *ssl) { + const uint8_t *p; + int ret; + CBS v2_client_hello, cipher_specs, session_id, challenge; + size_t msg_length, rand_len; + uint8_t msg_type; + uint16_t version, cipher_spec_length, session_id_length, challenge_length; + CBB client_hello, hello_body, cipher_suites; + uint8_t random[SSL3_RANDOM_SIZE]; + + /* Determine the length of the V2ClientHello. */ + assert(ssl_read_buffer_len(ssl) >= SSL3_RT_HEADER_LENGTH); + p = ssl_read_buffer(ssl); + msg_length = ((p[0] & 0x7f) << 8) | p[1]; + if (msg_length > (1024 * 4)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_RECORD_TOO_LARGE); + return -1; + } + if (msg_length < SSL3_RT_HEADER_LENGTH - 2) { + /* Reject lengths that are too short early. We have already read + * |SSL3_RT_HEADER_LENGTH| bytes, so we should not attempt to process an + * (invalid) V2ClientHello which would be shorter than that. */ + OPENSSL_PUT_ERROR(SSL, SSL_R_RECORD_LENGTH_MISMATCH); + return -1; + } + + /* Read the remainder of the V2ClientHello. */ + ret = ssl_read_buffer_extend_to(ssl, 2 + msg_length); + if (ret <= 0) { + return ret; + } + assert(ssl_read_buffer_len(ssl) == msg_length + 2); + CBS_init(&v2_client_hello, ssl_read_buffer(ssl) + 2, msg_length); + + /* The V2ClientHello without the length is incorporated into the handshake + * hash. */ + if (!ssl3_update_handshake_hash(ssl, CBS_data(&v2_client_hello), + CBS_len(&v2_client_hello))) { + return -1; + } + + ssl_do_msg_callback(ssl, 0 /* read */, SSL2_VERSION, 0, + CBS_data(&v2_client_hello), CBS_len(&v2_client_hello)); + + if (!CBS_get_u8(&v2_client_hello, &msg_type) || + !CBS_get_u16(&v2_client_hello, &version) || + !CBS_get_u16(&v2_client_hello, &cipher_spec_length) || + !CBS_get_u16(&v2_client_hello, &session_id_length) || + !CBS_get_u16(&v2_client_hello, &challenge_length) || + !CBS_get_bytes(&v2_client_hello, &cipher_specs, cipher_spec_length) || + !CBS_get_bytes(&v2_client_hello, &session_id, session_id_length) || + !CBS_get_bytes(&v2_client_hello, &challenge, challenge_length) || + CBS_len(&v2_client_hello) != 0) { + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + return -1; + } + + /* msg_type has already been checked. */ + assert(msg_type == SSL2_MT_CLIENT_HELLO); + + /* The client_random is the V2ClientHello challenge. Truncate or + * left-pad with zeros as needed. */ + memset(random, 0, SSL3_RANDOM_SIZE); + rand_len = CBS_len(&challenge); + if (rand_len > SSL3_RANDOM_SIZE) { + rand_len = SSL3_RANDOM_SIZE; + } + memcpy(random + (SSL3_RANDOM_SIZE - rand_len), CBS_data(&challenge), + rand_len); + + /* Write out an equivalent SSLv3 ClientHello. */ + CBB_zero(&client_hello); + if (!CBB_init_fixed(&client_hello, (uint8_t *)ssl->init_buf->data, + ssl->init_buf->max) || + !CBB_add_u8(&client_hello, SSL3_MT_CLIENT_HELLO) || + !CBB_add_u24_length_prefixed(&client_hello, &hello_body) || + !CBB_add_u16(&hello_body, version) || + !CBB_add_bytes(&hello_body, random, SSL3_RANDOM_SIZE) || + /* No session id. */ + !CBB_add_u8(&hello_body, 0) || + !CBB_add_u16_length_prefixed(&hello_body, &cipher_suites)) { + CBB_cleanup(&client_hello); + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + return -1; + } + + /* Copy the cipher suites. */ + while (CBS_len(&cipher_specs) > 0) { + uint32_t cipher_spec; + if (!CBS_get_u24(&cipher_specs, &cipher_spec)) { + CBB_cleanup(&client_hello); + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + return -1; + } + + /* Skip SSLv2 ciphers. */ + if ((cipher_spec & 0xff0000) != 0) { + continue; + } + if (!CBB_add_u16(&cipher_suites, cipher_spec)) { + CBB_cleanup(&client_hello); + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + return -1; + } + } + + /* Add the null compression scheme and finish. */ + if (!CBB_add_u8(&hello_body, 1) || !CBB_add_u8(&hello_body, 0) || + !CBB_finish(&client_hello, NULL, &ssl->init_buf->length)) { + CBB_cleanup(&client_hello); + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + return -1; + } + + /* Mark the message for "re"-use by the version-specific method. */ + ssl->s3->tmp.reuse_message = 1; + ssl->s3->tmp.message_type = SSL3_MT_CLIENT_HELLO; + ssl->s3->tmp.message_complete = 1; + + /* Consume and discard the V2ClientHello. */ + ssl_read_buffer_consume(ssl, 2 + msg_length); + ssl_read_buffer_discard(ssl); + + return 1; +} + +static int ssl3_get_client_hello(SSL *ssl) { + int ok, al = SSL_AD_INTERNAL_ERROR, ret = -1; + long n; + const SSL_CIPHER *c; + STACK_OF(SSL_CIPHER) *ciphers = NULL; + struct ssl_early_callback_ctx early_ctx; + CBS client_hello; + uint16_t client_version; + CBS client_random, session_id, cipher_suites, compression_methods; + SSL_SESSION *session = NULL; + + /* We do this so that we will respond with our native type. If we are TLSv1 + * and we get SSLv3, we will respond with TLSv1, This down switching should + * be handled by a different method. If we are SSLv3, we will respond with + * SSLv3, even if prompted with TLSv1. */ + switch (ssl->state) { + case SSL3_ST_SR_CLNT_HELLO_A: + n = ssl->method->ssl_get_message(ssl, SSL3_MT_CLIENT_HELLO, + ssl_hash_message, &ok); + + if (!ok) { + return n; + } + + ssl->state = SSL3_ST_SR_CLNT_HELLO_B; + /* fallthrough */ + case SSL3_ST_SR_CLNT_HELLO_B: + case SSL3_ST_SR_CLNT_HELLO_C: + /* We have previously parsed the ClientHello message, and can't call + * ssl_get_message again without hashing the message into the Finished + * digest again. */ + n = ssl->init_num; + + memset(&early_ctx, 0, sizeof(early_ctx)); + early_ctx.ssl = ssl; + early_ctx.client_hello = ssl->init_msg; + early_ctx.client_hello_len = n; + if (!ssl_early_callback_init(&early_ctx)) { + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, SSL_R_CLIENTHELLO_PARSE_FAILED); + goto f_err; + } + + if (ssl->state == SSL3_ST_SR_CLNT_HELLO_B && + ssl->ctx->select_certificate_cb != NULL) { + ssl->state = SSL3_ST_SR_CLNT_HELLO_C; + switch (ssl->ctx->select_certificate_cb(&early_ctx)) { + case 0: + ssl->rwstate = SSL_CERTIFICATE_SELECTION_PENDING; + goto err; + + case -1: + /* Connection rejected. */ + al = SSL_AD_ACCESS_DENIED; + OPENSSL_PUT_ERROR(SSL, SSL_R_CONNECTION_REJECTED); + goto f_err; + + default: + /* fallthrough */; + } + } + ssl->state = SSL3_ST_SR_CLNT_HELLO_C; + break; + + default: + OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_STATE); + return -1; + } + + CBS_init(&client_hello, ssl->init_msg, n); + if (!CBS_get_u16(&client_hello, &client_version) || + !CBS_get_bytes(&client_hello, &client_random, SSL3_RANDOM_SIZE) || + !CBS_get_u8_length_prefixed(&client_hello, &session_id) || + CBS_len(&session_id) > SSL_MAX_SSL_SESSION_ID_LENGTH) { + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + goto f_err; + } + + /* use version from inside client hello, not from record header (may differ: + * see RFC 2246, Appendix E, second paragraph) */ + ssl->client_version = client_version; + + /* Load the client random. */ + memcpy(ssl->s3->client_random, CBS_data(&client_random), SSL3_RANDOM_SIZE); + + if (SSL_IS_DTLS(ssl)) { + CBS cookie; + + if (!CBS_get_u8_length_prefixed(&client_hello, &cookie) || + CBS_len(&cookie) > DTLS1_COOKIE_LENGTH) { + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + goto f_err; + } + } + + /* Note: This codepath may run twice if |ssl_get_prev_session| completes + * asynchronously. + * + * TODO(davidben): Clean up the order of events around ClientHello + * processing. */ + if (!ssl->s3->have_version) { + /* Select version to use */ + uint16_t version = ssl3_get_mutual_version(ssl, client_version); + if (version == 0) { + OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_PROTOCOL); + ssl->version = ssl->client_version; + al = SSL_AD_PROTOCOL_VERSION; + goto f_err; + } + ssl->version = version; + ssl->s3->enc_method = ssl3_get_enc_method(version); + assert(ssl->s3->enc_method != NULL); + /* At this point, the connection's version is known and |ssl->version| is + * fixed. Begin enforcing the record-layer version. */ + ssl->s3->have_version = 1; + } else if (SSL_IS_DTLS(ssl) ? (ssl->client_version > ssl->version) + : (ssl->client_version < ssl->version)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_VERSION_NUMBER); + al = SSL_AD_PROTOCOL_VERSION; + goto f_err; + } + + ssl->hit = 0; + int send_new_ticket = 0; + switch (ssl_get_prev_session(ssl, &session, &send_new_ticket, &early_ctx)) { + case ssl_session_success: + break; + case ssl_session_error: + goto err; + case ssl_session_retry: + ssl->rwstate = SSL_PENDING_SESSION; + goto err; + } + ssl->tlsext_ticket_expected = send_new_ticket; + + /* The EMS state is needed when making the resumption decision, but + * extensions are not normally parsed until later. This detects the EMS + * extension for the resumption decision and it's checked against the result + * of the normal parse later in this function. */ + const uint8_t *ems_data; + size_t ems_len; + int have_extended_master_secret = + ssl->version != SSL3_VERSION && + SSL_early_callback_ctx_extension_get(&early_ctx, + TLSEXT_TYPE_extended_master_secret, + &ems_data, &ems_len) && + ems_len == 0; + + if (session != NULL) { + if (session->extended_master_secret && + !have_extended_master_secret) { + /* A ClientHello without EMS that attempts to resume a session with EMS + * is fatal to the connection. */ + al = SSL_AD_HANDSHAKE_FAILURE; + OPENSSL_PUT_ERROR(SSL, SSL_R_RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION); + goto f_err; + } + + ssl->hit = + /* Only resume if the session's version matches the negotiated version: + * most clients do not accept a mismatch. */ + ssl->version == session->ssl_version && + /* If the client offers the EMS extension, but the previous session + * didn't use it, then negotiate a new session. */ + have_extended_master_secret == session->extended_master_secret; + } + + if (ssl->hit) { + /* Use the new session. */ + SSL_SESSION_free(ssl->session); + ssl->session = session; + session = NULL; + + ssl->verify_result = ssl->session->verify_result; + } else { + if (!ssl_get_new_session(ssl, 1 /* server */)) { + goto err; + } + + /* Clear the session ID if we want the session to be single-use. */ + if (!(ssl->ctx->session_cache_mode & SSL_SESS_CACHE_SERVER)) { + ssl->session->session_id_length = 0; + } + } + + if (ssl->ctx->dos_protection_cb != NULL && + ssl->ctx->dos_protection_cb(&early_ctx) == 0) { + /* Connection rejected for DOS reasons. */ + al = SSL_AD_ACCESS_DENIED; + OPENSSL_PUT_ERROR(SSL, SSL_R_CONNECTION_REJECTED); + goto f_err; + } + + if (!CBS_get_u16_length_prefixed(&client_hello, &cipher_suites) || + CBS_len(&cipher_suites) == 0 || + CBS_len(&cipher_suites) % 2 != 0 || + !CBS_get_u8_length_prefixed(&client_hello, &compression_methods) || + CBS_len(&compression_methods) == 0) { + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + goto f_err; + } + + ciphers = ssl_bytes_to_cipher_list(ssl, &cipher_suites); + if (ciphers == NULL) { + goto err; + } + + /* If it is a hit, check that the cipher is in the list. */ + if (ssl->hit) { + size_t j; + int found_cipher = 0; + uint32_t id = ssl->session->cipher->id; + + for (j = 0; j < sk_SSL_CIPHER_num(ciphers); j++) { + c = sk_SSL_CIPHER_value(ciphers, j); + if (c->id == id) { + found_cipher = 1; + break; + } + } + + if (!found_cipher) { + /* we need to have the cipher in the cipher list if we are asked to reuse + * it */ + al = SSL_AD_ILLEGAL_PARAMETER; + OPENSSL_PUT_ERROR(SSL, SSL_R_REQUIRED_CIPHER_MISSING); + goto f_err; + } + } + + /* Only null compression is supported. */ + if (memchr(CBS_data(&compression_methods), 0, + CBS_len(&compression_methods)) == NULL) { + al = SSL_AD_ILLEGAL_PARAMETER; + OPENSSL_PUT_ERROR(SSL, SSL_R_NO_COMPRESSION_SPECIFIED); + goto f_err; + } + + /* TLS extensions. */ + if (ssl->version >= SSL3_VERSION && + !ssl_parse_clienthello_tlsext(ssl, &client_hello)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_PARSE_TLSEXT); + goto err; + } + + /* There should be nothing left over in the record. */ + if (CBS_len(&client_hello) != 0) { + /* wrong packet length */ + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_PACKET_LENGTH); + goto f_err; + } + + if (have_extended_master_secret != ssl->s3->tmp.extended_master_secret) { + al = SSL_AD_INTERNAL_ERROR; + OPENSSL_PUT_ERROR(SSL, SSL_R_EMS_STATE_INCONSISTENT); + goto f_err; + } + + /* Given ciphers and SSL_get_ciphers, we must pick a cipher */ + if (!ssl->hit) { + if (ciphers == NULL) { + al = SSL_AD_ILLEGAL_PARAMETER; + OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CIPHERS_PASSED); + goto f_err; + } + + /* Let cert callback update server certificates if required */ + if (ssl->cert->cert_cb) { + int rv = ssl->cert->cert_cb(ssl, ssl->cert->cert_cb_arg); + if (rv == 0) { + al = SSL_AD_INTERNAL_ERROR; + OPENSSL_PUT_ERROR(SSL, SSL_R_CERT_CB_ERROR); + goto f_err; + } + if (rv < 0) { + ssl->rwstate = SSL_X509_LOOKUP; + goto err; + } + } + c = ssl3_choose_cipher(ssl, ciphers, ssl_get_cipher_preferences(ssl)); + + if (c == NULL) { + al = SSL_AD_HANDSHAKE_FAILURE; + OPENSSL_PUT_ERROR(SSL, SSL_R_NO_SHARED_CIPHER); + goto f_err; + } + ssl->session->cipher = c; + ssl->s3->tmp.new_cipher = c; + + /* Determine whether to request a client certificate. */ + ssl->s3->tmp.cert_request = !!(ssl->verify_mode & SSL_VERIFY_PEER); + /* Only request a certificate if Channel ID isn't negotiated. */ + if ((ssl->verify_mode & SSL_VERIFY_PEER_IF_NO_OBC) && + ssl->s3->tlsext_channel_id_valid) { + ssl->s3->tmp.cert_request = 0; + } + /* CertificateRequest may only be sent in certificate-based ciphers. */ + if (!ssl_cipher_uses_certificate_auth(ssl->s3->tmp.new_cipher)) { + ssl->s3->tmp.cert_request = 0; + } + } else { + /* Session-id reuse */ + ssl->s3->tmp.new_cipher = ssl->session->cipher; + ssl->s3->tmp.cert_request = 0; + } + + /* Now that the cipher is known, initialize the handshake hash. */ + if (!ssl3_init_handshake_hash(ssl)) { + goto f_err; + } + + /* In TLS 1.2, client authentication requires hashing the handshake transcript + * under a different hash. Otherwise, release the handshake buffer. */ + if (!ssl->s3->tmp.cert_request || + ssl3_protocol_version(ssl) < TLS1_2_VERSION) { + ssl3_free_handshake_buffer(ssl); + } + + /* we now have the following setup; + * client_random + * cipher_list - our prefered list of ciphers + * ciphers - the clients prefered list of ciphers + * compression - basically ignored right now + * ssl version is set - sslv3 + * ssl->session - The ssl session has been setup. + * ssl->hit - session reuse flag + * ssl->tmp.new_cipher - the new cipher to use. */ + + ret = 1; + + if (0) { + f_err: + ssl3_send_alert(ssl, SSL3_AL_FATAL, al); + } + +err: + sk_SSL_CIPHER_free(ciphers); + SSL_SESSION_free(session); + return ret; +} + +static int ssl3_send_server_hello(SSL *ssl) { + if (ssl->state == SSL3_ST_SW_SRVR_HELLO_B) { + return ssl_do_write(ssl); + } + + assert(ssl->state == SSL3_ST_SW_SRVR_HELLO_A); + + /* We only accept ChannelIDs on connections with ECDHE in order to avoid a + * known attack while we fix ChannelID itself. */ + if (ssl->s3->tlsext_channel_id_valid && + (ssl->s3->tmp.new_cipher->algorithm_mkey & SSL_kECDHE) == 0) { + ssl->s3->tlsext_channel_id_valid = 0; + } + + /* If this is a resumption and the original handshake didn't support + * ChannelID then we didn't record the original handshake hashes in the + * session and so cannot resume with ChannelIDs. */ + if (ssl->hit && ssl->session->original_handshake_hash_len == 0) { + ssl->s3->tlsext_channel_id_valid = 0; + } + + if (!ssl_fill_hello_random(ssl->s3->server_random, SSL3_RANDOM_SIZE, + 1 /* server */)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + return -1; + } + + CBB cbb, session_id; + size_t length; + CBB_zero(&cbb); + if (!CBB_init_fixed(&cbb, ssl_handshake_start(ssl), + ssl->init_buf->max - SSL_HM_HEADER_LENGTH(ssl)) || + !CBB_add_u16(&cbb, ssl->version) || + !CBB_add_bytes(&cbb, ssl->s3->server_random, SSL3_RANDOM_SIZE) || + !CBB_add_u8_length_prefixed(&cbb, &session_id) || + !CBB_add_bytes(&session_id, ssl->session->session_id, + ssl->session->session_id_length) || + !CBB_add_u16(&cbb, ssl_cipher_get_value(ssl->s3->tmp.new_cipher)) || + !CBB_add_u8(&cbb, 0 /* no compression */) || + !ssl_add_serverhello_tlsext(ssl, &cbb) || + !CBB_finish(&cbb, NULL, &length) || + !ssl_set_handshake_header(ssl, SSL3_MT_SERVER_HELLO, length)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + CBB_cleanup(&cbb); + return -1; + } + + ssl->state = SSL3_ST_SW_SRVR_HELLO_B; + return ssl_do_write(ssl); +} + +static int ssl3_send_server_certificate(SSL *ssl) { + if (ssl->state == SSL3_ST_SW_CERT_A) { + if (!ssl3_output_cert_chain(ssl)) { + return 0; + } + ssl->state = SSL3_ST_SW_CERT_B; + } + + /* SSL3_ST_SW_CERT_B */ + return ssl_do_write(ssl); +} + +static int ssl3_send_certificate_status(SSL *ssl) { + if (ssl->state == SSL3_ST_SW_CERT_STATUS_A) { + CBB out, ocsp_response; + size_t length; + + CBB_zero(&out); + if (!CBB_init_fixed(&out, ssl_handshake_start(ssl), + ssl->init_buf->max - SSL_HM_HEADER_LENGTH(ssl)) || + !CBB_add_u8(&out, TLSEXT_STATUSTYPE_ocsp) || + !CBB_add_u24_length_prefixed(&out, &ocsp_response) || + !CBB_add_bytes(&ocsp_response, ssl->ctx->ocsp_response, + ssl->ctx->ocsp_response_length) || + !CBB_finish(&out, NULL, &length) || + !ssl_set_handshake_header(ssl, SSL3_MT_CERTIFICATE_STATUS, length)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + CBB_cleanup(&out); + return -1; + } + + ssl->state = SSL3_ST_SW_CERT_STATUS_B; + } + + /* SSL3_ST_SW_CERT_STATUS_B */ + return ssl_do_write(ssl); +} + +static int ssl3_send_server_key_exchange(SSL *ssl) { + if (ssl->state == SSL3_ST_SW_KEY_EXCH_C) { + return ssl_do_write(ssl); + } + + CBB cbb, child; + if (!CBB_init_fixed(&cbb, ssl_handshake_start(ssl), + ssl->init_buf->max - SSL_HM_HEADER_LENGTH(ssl))) { + goto err; + } + + if (ssl->state == SSL3_ST_SW_KEY_EXCH_A) { + /* This is the first iteration, so write parameters. */ + uint32_t alg_k = ssl->s3->tmp.new_cipher->algorithm_mkey; + uint32_t alg_a = ssl->s3->tmp.new_cipher->algorithm_auth; + + /* PSK ciphers begin with an identity hint. */ + if (alg_a & SSL_aPSK) { + size_t len = + (ssl->psk_identity_hint == NULL) ? 0 : strlen(ssl->psk_identity_hint); + if (!CBB_add_u16_length_prefixed(&cbb, &child) || + !CBB_add_bytes(&child, (const uint8_t *)ssl->psk_identity_hint, + len)) { + goto err; + } + } + + if (alg_k & SSL_kDHE) { + /* Determine the group to use. */ + DH *params = ssl->cert->dh_tmp; + if (params == NULL && ssl->cert->dh_tmp_cb != NULL) { + params = ssl->cert->dh_tmp_cb(ssl, 0, 1024); + } + if (params == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_TMP_DH_KEY); + ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); + goto err; + } + ssl->session->key_exchange_info = DH_num_bits(params); + + /* Set up DH, generate a key, and emit the public half. */ + DH *dh = DHparams_dup(params); + if (dh == NULL) { + goto err; + } + + SSL_ECDH_CTX_init_for_dhe(&ssl->s3->tmp.ecdh_ctx, dh); + if (!CBB_add_u16_length_prefixed(&cbb, &child) || + !BN_bn2cbb_padded(&child, BN_num_bytes(params->p), params->p) || + !CBB_add_u16_length_prefixed(&cbb, &child) || + !BN_bn2cbb_padded(&child, BN_num_bytes(params->g), params->g) || + !CBB_add_u16_length_prefixed(&cbb, &child) || + !SSL_ECDH_CTX_offer(&ssl->s3->tmp.ecdh_ctx, &child)) { + goto err; + } + } else if (alg_k & SSL_kECDHE) { + /* Determine the group to use. */ + uint16_t group_id; + if (!tls1_get_shared_group(ssl, &group_id)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_TMP_ECDH_KEY); + ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); + goto err; + } + ssl->session->key_exchange_info = group_id; + + /* Set up ECDH, generate a key, and emit the public half. */ + if (!SSL_ECDH_CTX_init(&ssl->s3->tmp.ecdh_ctx, group_id) || + !CBB_add_u8(&cbb, NAMED_CURVE_TYPE) || + !CBB_add_u16(&cbb, group_id) || + !CBB_add_u8_length_prefixed(&cbb, &child) || + !SSL_ECDH_CTX_offer(&ssl->s3->tmp.ecdh_ctx, &child)) { + goto err; + } + } else if (alg_k & SSL_kCECPQ1) { + if (!SSL_ECDH_CTX_init(&ssl->s3->tmp.ecdh_ctx, SSL_GROUP_CECPQ1) || + !CBB_add_u16_length_prefixed(&cbb, &child) || + !SSL_ECDH_CTX_offer(&ssl->s3->tmp.ecdh_ctx, &child)) { + goto err; + } + } else { + assert(alg_k & SSL_kPSK); + } + + /* Otherwise, restore |cbb| from the previous iteration. + * TODO(davidben): When |ssl->init_buf| is gone, come up with a simpler + * pattern. Probably keep the |CBB| around in the handshake state. */ + } else if (!CBB_did_write(&cbb, ssl->init_num - SSL_HM_HEADER_LENGTH(ssl))) { + goto err; + } + + /* Add a signature. */ + if (ssl_cipher_uses_certificate_auth(ssl->s3->tmp.new_cipher)) { + if (!ssl_has_private_key(ssl)) { + ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); + goto err; + } + + const size_t max_sig_len = ssl_private_key_max_signature_len(ssl); + size_t sig_len; + enum ssl_private_key_result_t sign_result; + if (ssl->state == SSL3_ST_SW_KEY_EXCH_A) { + /* This is the first iteration, so set up the signature. Sample the + * parameter length before adding a signature algorithm. */ + if (!CBB_flush(&cbb)) { + goto err; + } + size_t params_len = CBB_len(&cbb); + + /* Determine signature algorithm. */ + const EVP_MD *md; + if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) { + md = tls1_choose_signing_digest(ssl); + if (!tls12_add_sigandhash(ssl, &cbb, md)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); + goto err; + } + } else if (ssl_private_key_type(ssl) == EVP_PKEY_RSA) { + md = EVP_md5_sha1(); + } else { + md = EVP_sha1(); + } + + /* Compute the digest and sign it. */ + uint8_t digest[EVP_MAX_MD_SIZE]; + unsigned digest_len = 0; + EVP_MD_CTX md_ctx; + EVP_MD_CTX_init(&md_ctx); + int digest_ret = + EVP_DigestInit_ex(&md_ctx, md, NULL) && + EVP_DigestUpdate(&md_ctx, ssl->s3->client_random, SSL3_RANDOM_SIZE) && + EVP_DigestUpdate(&md_ctx, ssl->s3->server_random, SSL3_RANDOM_SIZE) && + EVP_DigestUpdate(&md_ctx, CBB_data(&cbb), params_len) && + EVP_DigestFinal_ex(&md_ctx, digest, &digest_len); + EVP_MD_CTX_cleanup(&md_ctx); + uint8_t *ptr; + if (!digest_ret || + !CBB_add_u16_length_prefixed(&cbb, &child) || + !CBB_reserve(&child, &ptr, max_sig_len)) { + goto err; + } + sign_result = ssl_private_key_sign(ssl, ptr, &sig_len, max_sig_len, md, + digest, digest_len); + } else { + assert(ssl->state == SSL3_ST_SW_KEY_EXCH_B); + + /* Retry the signature. */ + uint8_t *ptr; + if (!CBB_add_u16_length_prefixed(&cbb, &child) || + !CBB_reserve(&child, &ptr, max_sig_len)) { + goto err; + } + sign_result = + ssl_private_key_sign_complete(ssl, ptr, &sig_len, max_sig_len); + } + + switch (sign_result) { + case ssl_private_key_success: + if (!CBB_did_write(&child, sig_len)) { + goto err; + } + break; + case ssl_private_key_failure: + goto err; + case ssl_private_key_retry: + /* Discard the unfinished signature and save the state of |cbb| for the + * next iteration. */ + CBB_discard_child(&cbb); + ssl->init_num = SSL_HM_HEADER_LENGTH(ssl) + CBB_len(&cbb); + ssl->rwstate = SSL_PRIVATE_KEY_OPERATION; + ssl->state = SSL3_ST_SW_KEY_EXCH_B; + goto err; + } + } + + size_t length; + if (!CBB_finish(&cbb, NULL, &length) || + !ssl_set_handshake_header(ssl, SSL3_MT_SERVER_KEY_EXCHANGE, length)) { + goto err; + } + ssl->state = SSL3_ST_SW_KEY_EXCH_C; + return ssl_do_write(ssl); + +err: + CBB_cleanup(&cbb); + return -1; +} + +static int ssl3_send_certificate_request(SSL *ssl) { + uint8_t *p, *d; + size_t i; + int j, nl, off, n; + STACK_OF(X509_NAME) *sk = NULL; + X509_NAME *name; + BUF_MEM *buf; + + if (ssl->state == SSL3_ST_SW_CERT_REQ_A) { + buf = ssl->init_buf; + + d = p = ssl_handshake_start(ssl); + + /* get the list of acceptable cert types */ + p++; + n = ssl3_get_req_cert_type(ssl, p); + d[0] = n; + p += n; + n++; + + if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) { + const uint8_t *psigs; + nl = tls12_get_psigalgs(ssl, &psigs); + s2n(nl, p); + memcpy(p, psigs, nl); + p += nl; + n += nl + 2; + } + + off = n; + p += 2; + n += 2; + + sk = SSL_get_client_CA_list(ssl); + nl = 0; + if (sk != NULL) { + for (i = 0; i < sk_X509_NAME_num(sk); i++) { + name = sk_X509_NAME_value(sk, i); + j = i2d_X509_NAME(name, NULL); + if (!BUF_MEM_grow_clean(buf, SSL_HM_HEADER_LENGTH(ssl) + n + j + 2)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB); + goto err; + } + p = ssl_handshake_start(ssl) + n; + s2n(j, p); + i2d_X509_NAME(name, &p); + n += 2 + j; + nl += 2 + j; + } + } + + /* else no CA names */ + p = ssl_handshake_start(ssl) + off; + s2n(nl, p); + + if (!ssl_set_handshake_header(ssl, SSL3_MT_CERTIFICATE_REQUEST, n)) { + goto err; + } + ssl->state = SSL3_ST_SW_CERT_REQ_B; + } + + /* SSL3_ST_SW_CERT_REQ_B */ + return ssl_do_write(ssl); + +err: + return -1; +} + +static int ssl3_send_server_hello_done(SSL *ssl) { + if (ssl->state == SSL3_ST_SW_SRVR_DONE_A) { + if (!ssl_set_handshake_header(ssl, SSL3_MT_SERVER_HELLO_DONE, 0)) { + return -1; + } + ssl->state = SSL3_ST_SW_SRVR_DONE_B; + } + + /* SSL3_ST_SW_SRVR_DONE_B */ + return ssl_do_write(ssl); +} + +static int ssl3_get_client_certificate(SSL *ssl) { + int ok, al, ret = -1; + X509 *x = NULL; + unsigned long n; + STACK_OF(X509) *sk = NULL; + SHA256_CTX sha256; + CBS certificate_msg, certificate_list; + int is_first_certificate = 1; + + assert(ssl->s3->tmp.cert_request); + n = ssl->method->ssl_get_message(ssl, -1, ssl_hash_message, &ok); + + if (!ok) { + return n; + } + + if (ssl->s3->tmp.message_type != SSL3_MT_CERTIFICATE) { + if (ssl->version == SSL3_VERSION && + ssl->s3->tmp.message_type == SSL3_MT_CLIENT_KEY_EXCHANGE) { + /* In SSL 3.0, the Certificate message is omitted to signal no certificate. */ + if ((ssl->verify_mode & SSL_VERIFY_PEER) && + (ssl->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE); + al = SSL_AD_HANDSHAKE_FAILURE; + goto f_err; + } + + ssl->s3->tmp.reuse_message = 1; + return 1; + } + + al = SSL_AD_UNEXPECTED_MESSAGE; + OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE); + goto f_err; + } + + CBS_init(&certificate_msg, ssl->init_msg, n); + + sk = sk_X509_new_null(); + if (sk == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (!CBS_get_u24_length_prefixed(&certificate_msg, &certificate_list) || + CBS_len(&certificate_msg) != 0) { + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + goto f_err; + } + + while (CBS_len(&certificate_list) > 0) { + CBS certificate; + const uint8_t *data; + + if (!CBS_get_u24_length_prefixed(&certificate_list, &certificate)) { + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + goto f_err; + } + + if (is_first_certificate && ssl->ctx->retain_only_sha256_of_client_certs) { + /* If this is the first certificate, and we don't want to keep peer + * certificates in memory, then we hash it right away. */ + SHA256_Init(&sha256); + SHA256_Update(&sha256, CBS_data(&certificate), CBS_len(&certificate)); + SHA256_Final(ssl->session->peer_sha256, &sha256); + ssl->session->peer_sha256_valid = 1; + } + is_first_certificate = 0; + + /* A u24 length cannot overflow a long. */ + data = CBS_data(&certificate); + x = d2i_X509(NULL, &data, (long)CBS_len(&certificate)); + if (x == NULL) { + al = SSL_AD_BAD_CERTIFICATE; + OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB); + goto f_err; + } + if (data != CBS_data(&certificate) + CBS_len(&certificate)) { + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, SSL_R_CERT_LENGTH_MISMATCH); + goto f_err; + } + if (!sk_X509_push(sk, x)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + goto err; + } + x = NULL; + } + + if (sk_X509_num(sk) <= 0) { + /* No client certificate so the handshake buffer may be discarded. */ + ssl3_free_handshake_buffer(ssl); + + /* TLS does not mind 0 certs returned */ + if (ssl->version == SSL3_VERSION) { + al = SSL_AD_HANDSHAKE_FAILURE; + OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CERTIFICATES_RETURNED); + goto f_err; + } else if ((ssl->verify_mode & SSL_VERIFY_PEER) && + (ssl->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) { + /* Fail for TLS only if we required a certificate */ + OPENSSL_PUT_ERROR(SSL, SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE); + al = SSL_AD_HANDSHAKE_FAILURE; + goto f_err; + } + } else { + if (ssl_verify_cert_chain(ssl, sk) <= 0) { + al = ssl_verify_alarm_type(ssl->verify_result); + OPENSSL_PUT_ERROR(SSL, SSL_R_CERTIFICATE_VERIFY_FAILED); + goto f_err; + } + } + + X509_free(ssl->session->peer); + ssl->session->peer = sk_X509_shift(sk); + ssl->session->verify_result = ssl->verify_result; + + sk_X509_pop_free(ssl->session->cert_chain, X509_free); + ssl->session->cert_chain = sk; + /* Inconsistency alert: cert_chain does *not* include the peer's own + * certificate, while we do include it in s3_clnt.c */ + + sk = NULL; + + ret = 1; + + if (0) { + f_err: + ssl3_send_alert(ssl, SSL3_AL_FATAL, al); + } + +err: + X509_free(x); + sk_X509_pop_free(sk, X509_free); + return ret; +} + +static int ssl3_get_client_key_exchange(SSL *ssl) { + int al; + CBS client_key_exchange; + uint32_t alg_k; + uint32_t alg_a; + uint8_t *premaster_secret = NULL; + size_t premaster_secret_len = 0; + uint8_t *decrypt_buf = NULL; + + unsigned psk_len = 0; + uint8_t psk[PSK_MAX_PSK_LEN]; + + if (ssl->state == SSL3_ST_SR_KEY_EXCH_A) { + int ok; + const long n = ssl->method->ssl_get_message( + ssl, SSL3_MT_CLIENT_KEY_EXCHANGE, ssl_hash_message, &ok); + if (!ok) { + return n; + } + } + + CBS_init(&client_key_exchange, ssl->init_msg, ssl->init_num); + alg_k = ssl->s3->tmp.new_cipher->algorithm_mkey; + alg_a = ssl->s3->tmp.new_cipher->algorithm_auth; + + /* If using a PSK key exchange, prepare the pre-shared key. */ + if (alg_a & SSL_aPSK) { + CBS psk_identity; + + /* If using PSK, the ClientKeyExchange contains a psk_identity. If PSK, + * then this is the only field in the message. */ + if (!CBS_get_u16_length_prefixed(&client_key_exchange, &psk_identity) || + ((alg_k & SSL_kPSK) && CBS_len(&client_key_exchange) != 0)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + al = SSL_AD_DECODE_ERROR; + goto f_err; + } + + if (ssl->psk_server_callback == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_NO_SERVER_CB); + al = SSL_AD_INTERNAL_ERROR; + goto f_err; + } + + if (CBS_len(&psk_identity) > PSK_MAX_IDENTITY_LEN || + CBS_contains_zero_byte(&psk_identity)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_DATA_LENGTH_TOO_LONG); + al = SSL_AD_ILLEGAL_PARAMETER; + goto f_err; + } + + if (!CBS_strdup(&psk_identity, &ssl->session->psk_identity)) { + al = SSL_AD_INTERNAL_ERROR; + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + goto f_err; + } + + /* Look up the key for the identity. */ + psk_len = ssl->psk_server_callback(ssl, ssl->session->psk_identity, psk, + sizeof(psk)); + if (psk_len > PSK_MAX_PSK_LEN) { + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + al = SSL_AD_INTERNAL_ERROR; + goto f_err; + } else if (psk_len == 0) { + /* PSK related to the given identity not found */ + OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_IDENTITY_NOT_FOUND); + al = SSL_AD_UNKNOWN_PSK_IDENTITY; + goto f_err; + } + } + + /* Depending on the key exchange method, compute |premaster_secret| and + * |premaster_secret_len|. */ + if (alg_k & SSL_kRSA) { + /* Allocate a buffer large enough for an RSA decryption. */ + const size_t rsa_size = ssl_private_key_max_signature_len(ssl); + decrypt_buf = OPENSSL_malloc(rsa_size); + if (decrypt_buf == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + goto err; + } + + enum ssl_private_key_result_t decrypt_result; + size_t decrypt_len; + if (ssl->state == SSL3_ST_SR_KEY_EXCH_A) { + if (!ssl_has_private_key(ssl) || + ssl_private_key_type(ssl) != EVP_PKEY_RSA) { + al = SSL_AD_HANDSHAKE_FAILURE; + OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_RSA_CERTIFICATE); + goto f_err; + } + CBS encrypted_premaster_secret; + if (ssl->version > SSL3_VERSION) { + if (!CBS_get_u16_length_prefixed(&client_key_exchange, + &encrypted_premaster_secret) || + CBS_len(&client_key_exchange) != 0) { + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, + SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG); + goto f_err; + } + } else { + encrypted_premaster_secret = client_key_exchange; + } + + /* Decrypt with no padding. PKCS#1 padding will be removed as part of the + * timing-sensitive code below. */ + decrypt_result = ssl_private_key_decrypt( + ssl, decrypt_buf, &decrypt_len, rsa_size, + CBS_data(&encrypted_premaster_secret), + CBS_len(&encrypted_premaster_secret)); + } else { + assert(ssl->state == SSL3_ST_SR_KEY_EXCH_B); + /* Complete async decrypt. */ + decrypt_result = ssl_private_key_decrypt_complete( + ssl, decrypt_buf, &decrypt_len, rsa_size); + } + + switch (decrypt_result) { + case ssl_private_key_success: + break; + case ssl_private_key_failure: + goto err; + case ssl_private_key_retry: + ssl->rwstate = SSL_PRIVATE_KEY_OPERATION; + ssl->state = SSL3_ST_SR_KEY_EXCH_B; + goto err; + } + + if (decrypt_len != rsa_size) { + al = SSL_AD_DECRYPT_ERROR; + OPENSSL_PUT_ERROR(SSL, SSL_R_DECRYPTION_FAILED); + goto f_err; + } + + /* Prepare a random premaster, to be used on invalid padding. See RFC 5246, + * section 7.4.7.1. */ + premaster_secret_len = SSL_MAX_MASTER_KEY_LENGTH; + premaster_secret = OPENSSL_malloc(premaster_secret_len); + if (premaster_secret == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + goto err; + } + if (!RAND_bytes(premaster_secret, premaster_secret_len)) { + goto err; + } + + /* The smallest padded premaster is 11 bytes of overhead. Small keys are + * publicly invalid. */ + if (decrypt_len < 11 + premaster_secret_len) { + al = SSL_AD_DECRYPT_ERROR; + OPENSSL_PUT_ERROR(SSL, SSL_R_DECRYPTION_FAILED); + goto f_err; + } + + /* Check the padding. See RFC 3447, section 7.2.2. */ + size_t padding_len = decrypt_len - premaster_secret_len; + uint8_t good = constant_time_eq_int_8(decrypt_buf[0], 0) & + constant_time_eq_int_8(decrypt_buf[1], 2); + size_t i; + for (i = 2; i < padding_len - 1; i++) { + good &= ~constant_time_is_zero_8(decrypt_buf[i]); + } + good &= constant_time_is_zero_8(decrypt_buf[padding_len - 1]); + + /* The premaster secret must begin with |client_version|. This too must be + * checked in constant time (http://eprint.iacr.org/2003/052/). */ + good &= constant_time_eq_8(decrypt_buf[padding_len], + (unsigned)(ssl->client_version >> 8)); + good &= constant_time_eq_8(decrypt_buf[padding_len + 1], + (unsigned)(ssl->client_version & 0xff)); + + /* Select, in constant time, either the decrypted premaster or the random + * premaster based on |good|. */ + for (i = 0; i < premaster_secret_len; i++) { + premaster_secret[i] = constant_time_select_8( + good, decrypt_buf[padding_len + i], premaster_secret[i]); + } + + OPENSSL_free(decrypt_buf); + decrypt_buf = NULL; + } else if (alg_k & (SSL_kECDHE|SSL_kDHE|SSL_kCECPQ1)) { + /* Parse the ClientKeyExchange. */ + CBS peer_key; + if (!SSL_ECDH_CTX_get_key(&ssl->s3->tmp.ecdh_ctx, &client_key_exchange, + &peer_key) || + CBS_len(&client_key_exchange) != 0) { + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + goto f_err; + } + + /* Compute the premaster. */ + uint8_t alert; + if (!SSL_ECDH_CTX_finish(&ssl->s3->tmp.ecdh_ctx, &premaster_secret, + &premaster_secret_len, &alert, CBS_data(&peer_key), + CBS_len(&peer_key))) { + al = alert; + goto f_err; + } + + /* The key exchange state may now be discarded. */ + SSL_ECDH_CTX_cleanup(&ssl->s3->tmp.ecdh_ctx); + } else if (alg_k & SSL_kPSK) { + /* For plain PSK, other_secret is a block of 0s with the same length as the + * pre-shared key. */ + premaster_secret_len = psk_len; + premaster_secret = OPENSSL_malloc(premaster_secret_len); + if (premaster_secret == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + goto err; + } + memset(premaster_secret, 0, premaster_secret_len); + } else { + al = SSL_AD_HANDSHAKE_FAILURE; + OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CIPHER_TYPE); + goto f_err; + } + + /* For a PSK cipher suite, the actual pre-master secret is combined with the + * pre-shared key. */ + if (alg_a & SSL_aPSK) { + CBB new_premaster, child; + uint8_t *new_data; + size_t new_len; + + CBB_zero(&new_premaster); + if (!CBB_init(&new_premaster, 2 + psk_len + 2 + premaster_secret_len) || + !CBB_add_u16_length_prefixed(&new_premaster, &child) || + !CBB_add_bytes(&child, premaster_secret, premaster_secret_len) || + !CBB_add_u16_length_prefixed(&new_premaster, &child) || + !CBB_add_bytes(&child, psk, psk_len) || + !CBB_finish(&new_premaster, &new_data, &new_len)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + CBB_cleanup(&new_premaster); + goto err; + } + + OPENSSL_cleanse(premaster_secret, premaster_secret_len); + OPENSSL_free(premaster_secret); + premaster_secret = new_data; + premaster_secret_len = new_len; + } + + /* Compute the master secret */ + ssl->session->master_key_length = tls1_generate_master_secret( + ssl, ssl->session->master_key, premaster_secret, premaster_secret_len); + if (ssl->session->master_key_length == 0) { + goto err; + } + ssl->session->extended_master_secret = ssl->s3->tmp.extended_master_secret; + + OPENSSL_cleanse(premaster_secret, premaster_secret_len); + OPENSSL_free(premaster_secret); + return 1; + +f_err: + ssl3_send_alert(ssl, SSL3_AL_FATAL, al); +err: + if (premaster_secret != NULL) { + OPENSSL_cleanse(premaster_secret, premaster_secret_len); + OPENSSL_free(premaster_secret); + } + OPENSSL_free(decrypt_buf); + + return -1; +} + +static int ssl3_get_cert_verify(SSL *ssl) { + int al, ok, ret = 0; + long n; + CBS certificate_verify, signature; + X509 *peer = ssl->session->peer; + EVP_PKEY *pkey = NULL; + const EVP_MD *md = NULL; + uint8_t digest[EVP_MAX_MD_SIZE]; + size_t digest_length; + EVP_PKEY_CTX *pctx = NULL; + + /* Only RSA and ECDSA client certificates are supported, so a + * CertificateVerify is required if and only if there's a client certificate. + * */ + if (peer == NULL) { + ssl3_free_handshake_buffer(ssl); + return 1; + } + + n = ssl->method->ssl_get_message(ssl, SSL3_MT_CERTIFICATE_VERIFY, + ssl_dont_hash_message, &ok); + + if (!ok) { + return n; + } + + /* Filter out unsupported certificate types. */ + pkey = X509_get_pubkey(peer); + if (pkey == NULL) { + goto err; + } + if (!(X509_certificate_type(peer, pkey) & EVP_PKT_SIGN) || + (pkey->type != EVP_PKEY_RSA && pkey->type != EVP_PKEY_EC)) { + al = SSL_AD_UNSUPPORTED_CERTIFICATE; + OPENSSL_PUT_ERROR(SSL, SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE); + goto f_err; + } + + CBS_init(&certificate_verify, ssl->init_msg, n); + + /* Determine the digest type if needbe. */ + if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) { + uint8_t hash, signature_type; + if (!CBS_get_u8(&certificate_verify, &hash) || + !CBS_get_u8(&certificate_verify, &signature_type)) { + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + goto f_err; + } + if (!tls12_check_peer_sigalg(ssl, &md, &al, hash, signature_type, pkey)) { + goto f_err; + } + } + + /* Compute the digest. */ + if (!ssl3_cert_verify_hash(ssl, digest, &digest_length, &md, pkey->type)) { + goto err; + } + + /* The handshake buffer is no longer necessary, and we may hash the current + * message.*/ + ssl3_free_handshake_buffer(ssl); + if (!ssl3_hash_current_message(ssl)) { + goto err; + } + + /* Parse and verify the signature. */ + if (!CBS_get_u16_length_prefixed(&certificate_verify, &signature) || + CBS_len(&certificate_verify) != 0) { + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + goto f_err; + } + + pctx = EVP_PKEY_CTX_new(pkey, NULL); + if (pctx == NULL) { + goto err; + } + int sig_ok = EVP_PKEY_verify_init(pctx) && + EVP_PKEY_CTX_set_signature_md(pctx, md) && + EVP_PKEY_verify(pctx, CBS_data(&signature), CBS_len(&signature), + digest, digest_length); +#if defined(BORINGSSL_UNSAFE_FUZZER_MODE) + sig_ok = 1; + ERR_clear_error(); +#endif + if (!sig_ok) { + al = SSL_AD_DECRYPT_ERROR; + OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SIGNATURE); + goto f_err; + } + + ret = 1; + + if (0) { + f_err: + ssl3_send_alert(ssl, SSL3_AL_FATAL, al); + } + +err: + EVP_PKEY_CTX_free(pctx); + EVP_PKEY_free(pkey); + + return ret; +} + +/* ssl3_get_next_proto reads a Next Protocol Negotiation handshake message. It + * sets the next_proto member in s if found */ +static int ssl3_get_next_proto(SSL *ssl) { + int ok; + long n; + CBS next_protocol, selected_protocol, padding; + + /* Clients cannot send a NextProtocol message if we didn't see the extension + * in their ClientHello */ + if (!ssl->s3->next_proto_neg_seen) { + OPENSSL_PUT_ERROR(SSL, SSL_R_GOT_NEXT_PROTO_WITHOUT_EXTENSION); + return -1; + } + + n = ssl->method->ssl_get_message(ssl, SSL3_MT_NEXT_PROTO, ssl_hash_message, + &ok); + + if (!ok) { + return n; + } + + CBS_init(&next_protocol, ssl->init_msg, n); + + /* The payload looks like: + * uint8 proto_len; + * uint8 proto[proto_len]; + * uint8 padding_len; + * uint8 padding[padding_len]; */ + if (!CBS_get_u8_length_prefixed(&next_protocol, &selected_protocol) || + !CBS_get_u8_length_prefixed(&next_protocol, &padding) || + CBS_len(&next_protocol) != 0 || + !CBS_stow(&selected_protocol, &ssl->s3->next_proto_negotiated, + &ssl->s3->next_proto_negotiated_len)) { + return 0; + } + + return 1; +} + +/* ssl3_get_channel_id reads and verifies a ClientID handshake message. */ +static int ssl3_get_channel_id(SSL *ssl) { + int ret = -1, ok; + long n; + uint8_t channel_id_hash[EVP_MAX_MD_SIZE]; + size_t channel_id_hash_len; + const uint8_t *p; + uint16_t extension_type; + EC_GROUP *p256 = NULL; + EC_KEY *key = NULL; + EC_POINT *point = NULL; + ECDSA_SIG sig; + BIGNUM x, y; + CBS encrypted_extensions, extension; + + n = ssl->method->ssl_get_message(ssl, SSL3_MT_CHANNEL_ID_ENCRYPTED_EXTENSIONS, + ssl_dont_hash_message, &ok); + + if (!ok) { + return n; + } + + /* Before incorporating the EncryptedExtensions message to the handshake + * hash, compute the hash that should have been signed. */ + if (!tls1_channel_id_hash(ssl, channel_id_hash, &channel_id_hash_len)) { + return -1; + } + assert(channel_id_hash_len == SHA256_DIGEST_LENGTH); + + if (!ssl3_hash_current_message(ssl)) { + return -1; + } + + CBS_init(&encrypted_extensions, ssl->init_msg, n); + + /* EncryptedExtensions could include multiple extensions, but the only + * extension that could be negotiated is ChannelID, so there can only be one + * entry. + * + * The payload looks like: + * uint16 extension_type + * uint16 extension_len; + * uint8 x[32]; + * uint8 y[32]; + * uint8 r[32]; + * uint8 s[32]; */ + + if (!CBS_get_u16(&encrypted_extensions, &extension_type) || + !CBS_get_u16_length_prefixed(&encrypted_extensions, &extension) || + CBS_len(&encrypted_extensions) != 0 || + extension_type != TLSEXT_TYPE_channel_id || + CBS_len(&extension) != TLSEXT_CHANNEL_ID_SIZE) { + OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_MESSAGE); + return -1; + } + + p256 = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1); + if (!p256) { + OPENSSL_PUT_ERROR(SSL, SSL_R_NO_P256_SUPPORT); + return -1; + } + + BN_init(&x); + BN_init(&y); + sig.r = BN_new(); + sig.s = BN_new(); + if (sig.r == NULL || sig.s == NULL) { + goto err; + } + + p = CBS_data(&extension); + if (BN_bin2bn(p + 0, 32, &x) == NULL || + BN_bin2bn(p + 32, 32, &y) == NULL || + BN_bin2bn(p + 64, 32, sig.r) == NULL || + BN_bin2bn(p + 96, 32, sig.s) == NULL) { + goto err; + } + + point = EC_POINT_new(p256); + if (!point || + !EC_POINT_set_affine_coordinates_GFp(p256, point, &x, &y, NULL)) { + goto err; + } + + key = EC_KEY_new(); + if (!key || !EC_KEY_set_group(key, p256) || + !EC_KEY_set_public_key(key, point)) { + goto err; + } + + /* We stored the handshake hash in |tlsext_channel_id| the first time that we + * were called. */ + if (!ECDSA_do_verify(channel_id_hash, channel_id_hash_len, &sig, key)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_CHANNEL_ID_SIGNATURE_INVALID); + ssl->s3->tlsext_channel_id_valid = 0; + goto err; + } + + memcpy(ssl->s3->tlsext_channel_id, p, 64); + ret = 1; + +err: + BN_free(&x); + BN_free(&y); + BN_free(sig.r); + BN_free(sig.s); + EC_KEY_free(key); + EC_POINT_free(point); + EC_GROUP_free(p256); + return ret; +} + +/* send a new session ticket (not necessarily for a new session) */ +static int ssl3_send_new_session_ticket(SSL *ssl) { + int ret = -1; + uint8_t *session = NULL; + size_t session_len; + EVP_CIPHER_CTX ctx; + HMAC_CTX hctx; + + EVP_CIPHER_CTX_init(&ctx); + HMAC_CTX_init(&hctx); + + if (ssl->state == SSL3_ST_SW_SESSION_TICKET_A) { + uint8_t *p, *macstart; + int len; + unsigned int hlen; + SSL_CTX *tctx = ssl->initial_ctx; + uint8_t iv[EVP_MAX_IV_LENGTH]; + uint8_t key_name[16]; + /* The maximum overhead of encrypting the session is 16 (key name) + IV + + * one block of encryption overhead + HMAC. */ + const size_t max_ticket_overhead = + 16 + EVP_MAX_IV_LENGTH + EVP_MAX_BLOCK_LENGTH + EVP_MAX_MD_SIZE; + + /* Serialize the SSL_SESSION to be encoded into the ticket. */ + if (!SSL_SESSION_to_bytes_for_ticket(ssl->session, &session, + &session_len)) { + goto err; + } + + /* If the session is too long, emit a dummy value rather than abort the + * connection. */ + if (session_len > 0xFFFF - max_ticket_overhead) { + static const char kTicketPlaceholder[] = "TICKET TOO LARGE"; + const size_t placeholder_len = strlen(kTicketPlaceholder); + + OPENSSL_free(session); + session = NULL; + + p = ssl_handshake_start(ssl); + /* Emit ticket_lifetime_hint. */ + l2n(0, p); + /* Emit ticket. */ + s2n(placeholder_len, p); + memcpy(p, kTicketPlaceholder, placeholder_len); + p += placeholder_len; + + len = p - ssl_handshake_start(ssl); + if (!ssl_set_handshake_header(ssl, SSL3_MT_NEW_SESSION_TICKET, len)) { + goto err; + } + ssl->state = SSL3_ST_SW_SESSION_TICKET_B; + return ssl_do_write(ssl); + } + + /* Grow buffer if need be: the length calculation is as follows: + * handshake_header_length + 4 (ticket lifetime hint) + 2 (ticket length) + + * max_ticket_overhead + * session_length */ + if (!BUF_MEM_grow(ssl->init_buf, SSL_HM_HEADER_LENGTH(ssl) + 6 + + max_ticket_overhead + session_len)) { + goto err; + } + p = ssl_handshake_start(ssl); + /* Initialize HMAC and cipher contexts. If callback present it does all the + * work otherwise use generated values from parent ctx. */ + if (tctx->tlsext_ticket_key_cb) { + if (tctx->tlsext_ticket_key_cb(ssl, key_name, iv, &ctx, &hctx, + 1 /* encrypt */) < 0) { + goto err; + } + } else { + if (!RAND_bytes(iv, 16) || + !EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, + tctx->tlsext_tick_aes_key, iv) || + !HMAC_Init_ex(&hctx, tctx->tlsext_tick_hmac_key, 16, tlsext_tick_md(), + NULL)) { + goto err; + } + memcpy(key_name, tctx->tlsext_tick_key_name, 16); + } + + /* Ticket lifetime hint (advisory only): We leave this unspecified for + * resumed session (for simplicity), and guess that tickets for new + * sessions will live as long as their sessions. */ + l2n(ssl->hit ? 0 : ssl->session->timeout, p); + + /* Skip ticket length for now */ + p += 2; + /* Output key name */ + macstart = p; + memcpy(p, key_name, 16); + p += 16; + /* output IV */ + memcpy(p, iv, EVP_CIPHER_CTX_iv_length(&ctx)); + p += EVP_CIPHER_CTX_iv_length(&ctx); + /* Encrypt session data */ + if (!EVP_EncryptUpdate(&ctx, p, &len, session, session_len)) { + goto err; + } + p += len; + if (!EVP_EncryptFinal_ex(&ctx, p, &len)) { + goto err; + } + p += len; + + if (!HMAC_Update(&hctx, macstart, p - macstart) || + !HMAC_Final(&hctx, p, &hlen)) { + goto err; + } + + p += hlen; + /* Now write out lengths: p points to end of data written */ + /* Total length */ + len = p - ssl_handshake_start(ssl); + /* Skip ticket lifetime hint */ + p = ssl_handshake_start(ssl) + 4; + s2n(len - 6, p); + if (!ssl_set_handshake_header(ssl, SSL3_MT_NEW_SESSION_TICKET, len)) { + goto err; + } + ssl->state = SSL3_ST_SW_SESSION_TICKET_B; + } + + /* SSL3_ST_SW_SESSION_TICKET_B */ + ret = ssl_do_write(ssl); + +err: + OPENSSL_free(session); + EVP_CIPHER_CTX_cleanup(&ctx); + HMAC_CTX_cleanup(&hctx); + return ret; +} diff --git a/external/boringssl/ssl/internal.h b/external/boringssl/ssl/internal.h new file mode 100644 index 0000000000..457a8b4290 --- /dev/null +++ b/external/boringssl/ssl/internal.h @@ -0,0 +1,1253 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * ECC cipher suite support in OpenSSL originally developed by + * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. + */ +/* ==================================================================== + * Copyright 2005 Nokia. All rights reserved. + * + * The portions of the attached software ("Contribution") is developed by + * Nokia Corporation and is licensed pursuant to the OpenSSL open source + * license. + * + * The Contribution, originally written by Mika Kousa and Pasi Eronen of + * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites + * support (see RFC 4279) to OpenSSL. + * + * No patent licenses or other rights except those expressly stated in + * the OpenSSL open source license shall be deemed granted or received + * expressly, by implication, estoppel, or otherwise. + * + * No assurances are provided by Nokia that the Contribution does not + * infringe the patent or other intellectual property rights of any third + * party or that the license provides you with all the necessary rights + * to make use of the Contribution. + * + * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN + * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA + * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY + * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR + * OTHERWISE. + */ + +#ifndef OPENSSL_HEADER_SSL_INTERNAL_H +#define OPENSSL_HEADER_SSL_INTERNAL_H + +#include + +#include +#include +#include +#include + +#if defined(OPENSSL_WINDOWS) +/* Windows defines struct timeval in winsock2.h. */ +OPENSSL_MSVC_PRAGMA(warning(push, 3)) +#include +OPENSSL_MSVC_PRAGMA(warning(pop)) +#else +#include +#endif + + +/* Cipher suites. */ + +/* Bits for |algorithm_mkey| (key exchange algorithm). */ +#define SSL_kRSA 0x00000001L +#define SSL_kDHE 0x00000002L +#define SSL_kECDHE 0x00000004L +/* SSL_kPSK is only set for plain PSK, not ECDHE_PSK. */ +#define SSL_kPSK 0x00000008L +#define SSL_kCECPQ1 0x00000010L + +/* Bits for |algorithm_auth| (server authentication). */ +#define SSL_aRSA 0x00000001L +#define SSL_aECDSA 0x00000002L +/* SSL_aPSK is set for both PSK and ECDHE_PSK. */ +#define SSL_aPSK 0x00000004L + +#define SSL_aCERT (SSL_aRSA | SSL_aECDSA) + +/* Bits for |algorithm_enc| (symmetric encryption). */ +#define SSL_3DES 0x00000001L +#define SSL_RC4 0x00000002L +#define SSL_AES128 0x00000004L +#define SSL_AES256 0x00000008L +#define SSL_AES128GCM 0x00000010L +#define SSL_AES256GCM 0x00000020L +#define SSL_CHACHA20POLY1305_OLD 0x00000040L +#define SSL_eNULL 0x00000080L +#define SSL_CHACHA20POLY1305 0x00000100L + +#define SSL_AES (SSL_AES128 | SSL_AES256 | SSL_AES128GCM | SSL_AES256GCM) + +/* Bits for |algorithm_mac| (symmetric authentication). */ +#define SSL_MD5 0x00000001L +#define SSL_SHA1 0x00000002L +#define SSL_SHA256 0x00000004L +#define SSL_SHA384 0x00000008L +/* SSL_AEAD is set for all AEADs. */ +#define SSL_AEAD 0x00000010L + +/* Bits for |algorithm_prf| (handshake digest). */ +#define SSL_HANDSHAKE_MAC_DEFAULT 0x1 +#define SSL_HANDSHAKE_MAC_SHA256 0x2 +#define SSL_HANDSHAKE_MAC_SHA384 0x4 + +/* SSL_MAX_DIGEST is the number of digest types which exist. When adding a new + * one, update the table in ssl_cipher.c. */ +#define SSL_MAX_DIGEST 4 + +/* ssl_cipher_get_evp_aead sets |*out_aead| to point to the correct EVP_AEAD + * object for |cipher| protocol version |version|. It sets |*out_mac_secret_len| + * and |*out_fixed_iv_len| to the MAC key length and fixed IV length, + * respectively. The MAC key length is zero except for legacy block and stream + * ciphers. It returns 1 on success and 0 on error. */ +int ssl_cipher_get_evp_aead(const EVP_AEAD **out_aead, + size_t *out_mac_secret_len, + size_t *out_fixed_iv_len, + const SSL_CIPHER *cipher, uint16_t version); + +/* ssl_get_handshake_digest returns the |EVP_MD| corresponding to + * |algorithm_prf|. It returns SHA-1 for |SSL_HANDSHAKE_DEFAULT|. The caller is + * responsible for maintaining the additional MD5 digest and switching to + * SHA-256 in TLS 1.2. */ +const EVP_MD *ssl_get_handshake_digest(uint32_t algorithm_prf); + +/* ssl_create_cipher_list evaluates |rule_str| according to the ciphers in + * |ssl_method|. It sets |*out_cipher_list| to a newly-allocated + * |ssl_cipher_preference_list_st| containing the result. + * |*out_cipher_list_by_id| is set to a list of selected ciphers sorted by + * id. It returns |(*out_cipher_list)->ciphers| on success and NULL on + * failure. */ +STACK_OF(SSL_CIPHER) * +ssl_create_cipher_list(const SSL_PROTOCOL_METHOD *ssl_method, + struct ssl_cipher_preference_list_st **out_cipher_list, + STACK_OF(SSL_CIPHER) **out_cipher_list_by_id, + const char *rule_str); + +/* ssl_cipher_get_value returns the cipher suite id of |cipher|. */ +uint16_t ssl_cipher_get_value(const SSL_CIPHER *cipher); + +/* ssl_cipher_get_key_type returns the |EVP_PKEY_*| value corresponding to the + * server key used in |cipher| or |EVP_PKEY_NONE| if there is none. */ +int ssl_cipher_get_key_type(const SSL_CIPHER *cipher); + +/* ssl_cipher_uses_certificate_auth returns one if |cipher| authenticates the + * server and, optionally, the client with a certificate. Otherwise it returns + * zero. */ +int ssl_cipher_uses_certificate_auth(const SSL_CIPHER *cipher); + +/* ssl_cipher_requires_server_key_exchange returns 1 if |cipher| requires a + * ServerKeyExchange message. Otherwise it returns 0. + * + * This function may return zero while still allowing |cipher| an optional + * ServerKeyExchange. This is the case for plain PSK ciphers. */ +int ssl_cipher_requires_server_key_exchange(const SSL_CIPHER *cipher); + +/* ssl_cipher_get_record_split_len, for TLS 1.0 CBC mode ciphers, returns the + * length of an encrypted 1-byte record, for use in record-splitting. Otherwise + * it returns zero. */ +size_t ssl_cipher_get_record_split_len(const SSL_CIPHER *cipher); + + +/* Encryption layer. */ + +/* SSL_AEAD_CTX contains information about an AEAD that is being used to encrypt + * an SSL connection. */ +struct ssl_aead_ctx_st { + const SSL_CIPHER *cipher; + EVP_AEAD_CTX ctx; + /* fixed_nonce contains any bytes of the nonce that are fixed for all + * records. */ + uint8_t fixed_nonce[12]; + uint8_t fixed_nonce_len, variable_nonce_len; + /* variable_nonce_included_in_record is non-zero if the variable nonce + * for a record is included as a prefix before the ciphertext. */ + char variable_nonce_included_in_record; + /* random_variable_nonce is non-zero if the variable nonce is + * randomly generated, rather than derived from the sequence + * number. */ + char random_variable_nonce; + /* omit_length_in_ad is non-zero if the length should be omitted in the + * AEAD's ad parameter. */ + char omit_length_in_ad; + /* omit_version_in_ad is non-zero if the version should be omitted + * in the AEAD's ad parameter. */ + char omit_version_in_ad; + /* omit_ad is non-zero if the AEAD's ad parameter should be omitted. */ + char omit_ad; + /* xor_fixed_nonce is non-zero if the fixed nonce should be XOR'd into the + * variable nonce rather than prepended. */ + char xor_fixed_nonce; +} /* SSL_AEAD_CTX */; + +/* SSL_AEAD_CTX_new creates a newly-allocated |SSL_AEAD_CTX| using the supplied + * key material. It returns NULL on error. Only one of |SSL_AEAD_CTX_open| or + * |SSL_AEAD_CTX_seal| may be used with the resulting object, depending on + * |direction|. |version| is the normalized protocol version, so DTLS 1.0 is + * represented as 0x0301, not 0xffef. */ +SSL_AEAD_CTX *SSL_AEAD_CTX_new(enum evp_aead_direction_t direction, + uint16_t version, const SSL_CIPHER *cipher, + const uint8_t *enc_key, size_t enc_key_len, + const uint8_t *mac_key, size_t mac_key_len, + const uint8_t *fixed_iv, size_t fixed_iv_len); + +/* SSL_AEAD_CTX_free frees |ctx|. */ +void SSL_AEAD_CTX_free(SSL_AEAD_CTX *ctx); + +/* SSL_AEAD_CTX_explicit_nonce_len returns the length of the explicit nonce for + * |ctx|, if any. |ctx| may be NULL to denote the null cipher. */ +size_t SSL_AEAD_CTX_explicit_nonce_len(SSL_AEAD_CTX *ctx); + +/* SSL_AEAD_CTX_max_overhead returns the maximum overhead of calling + * |SSL_AEAD_CTX_seal|. |ctx| may be NULL to denote the null cipher. */ +size_t SSL_AEAD_CTX_max_overhead(SSL_AEAD_CTX *ctx); + +/* SSL_AEAD_CTX_open authenticates and decrypts |in_len| bytes from |in| + * in-place. On success, it sets |*out| to the plaintext in |in| and returns + * one. Otherwise, it returns zero. |ctx| may be NULL to denote the null cipher. + * The output will always be |explicit_nonce_len| bytes ahead of |in|. */ +int SSL_AEAD_CTX_open(SSL_AEAD_CTX *ctx, CBS *out, uint8_t type, + uint16_t wire_version, const uint8_t seqnum[8], + uint8_t *in, size_t in_len); + +/* SSL_AEAD_CTX_seal encrypts and authenticates |in_len| bytes from |in| and + * writes the result to |out|. It returns one on success and zero on + * error. |ctx| may be NULL to denote the null cipher. + * + * If |in| and |out| alias then |out| + |explicit_nonce_len| must be == |in|. */ +int SSL_AEAD_CTX_seal(SSL_AEAD_CTX *ctx, uint8_t *out, size_t *out_len, + size_t max_out, uint8_t type, uint16_t wire_version, + const uint8_t seqnum[8], const uint8_t *in, + size_t in_len); + + +/* DTLS replay bitmap. */ + +/* DTLS1_BITMAP maintains a sliding window of 64 sequence numbers to detect + * replayed packets. It should be initialized by zeroing every field. */ +typedef struct dtls1_bitmap_st { + /* map is a bit mask of the last 64 sequence numbers. Bit + * |1<> 24) & 0xff), \ + *((c)++) = (uint8_t)(((l) >> 16) & 0xff), \ + *((c)++) = (uint8_t)(((l) >> 8) & 0xff), \ + *((c)++) = (uint8_t)(((l)) & 0xff)) + +#define s2n(s, c) \ + ((c[0] = (uint8_t)(((s) >> 8) & 0xff), \ + c[1] = (uint8_t)(((s)) & 0xff)), \ + c += 2) + +#define l2n3(l, c) \ + ((c[0] = (uint8_t)(((l) >> 16) & 0xff), \ + c[1] = (uint8_t)(((l) >> 8) & 0xff), \ + c[2] = (uint8_t)(((l)) & 0xff)), \ + c += 3) + +/* LOCAL STUFF */ + +#define TLSEXT_CHANNEL_ID_SIZE 128 + +/* Check if an SSL structure is using DTLS */ +#define SSL_IS_DTLS(ssl) (ssl->method->is_dtls) + +/* From RFC4492, used in encoding the curve type in ECParameters */ +#define NAMED_CURVE_TYPE 3 + +enum ssl_hash_message_t { + ssl_dont_hash_message, + ssl_hash_message, +}; + +/* Structure containing decoded values of signature algorithms extension */ +typedef struct tls_sigalgs_st { + uint8_t rsign; + uint8_t rhash; +} TLS_SIGALGS; + +typedef struct cert_st { + X509 *x509; + EVP_PKEY *privatekey; + /* Chain for this certificate */ + STACK_OF(X509) *chain; + + /* key_method, if non-NULL, is a set of callbacks to call for private key + * operations. */ + const SSL_PRIVATE_KEY_METHOD *key_method; + + /* For clients the following masks are of *disabled* key and auth algorithms + * based on the current configuration. + * + * TODO(davidben): Remove these. They get checked twice: when sending the + * ClientHello and when processing the ServerHello. */ + uint32_t mask_k; + uint32_t mask_a; + + DH *dh_tmp; + DH *(*dh_tmp_cb)(SSL *ssl, int is_export, int keysize); + + /* peer_sigalgs are the algorithm/hash pairs that the peer supports. These + * are taken from the contents of signature algorithms extension for a server + * or from the CertificateRequest for a client. */ + TLS_SIGALGS *peer_sigalgs; + /* peer_sigalgslen is the number of entries in |peer_sigalgs|. */ + size_t peer_sigalgslen; + + /* digest_nids, if non-NULL, is the set of digests supported by |privatekey| + * in decreasing order of preference. */ + int *digest_nids; + size_t num_digest_nids; + + /* Certificate setup callback: if set is called whenever a + * certificate may be required (client or server). the callback + * can then examine any appropriate parameters and setup any + * certificates required. This allows advanced applications + * to select certificates on the fly: for example based on + * supported signature algorithms or curves. */ + int (*cert_cb)(SSL *ssl, void *arg); + void *cert_cb_arg; + + /* Optional X509_STORE for certificate validation. If NULL the parent SSL_CTX + * store is used instead. */ + X509_STORE *verify_store; +} CERT; + +/* SSL_METHOD is a compatibility structure to support the legacy version-locked + * methods. */ +struct ssl_method_st { + /* version, if non-zero, is the only protocol version acceptable to an + * SSL_CTX initialized from this method. */ + uint16_t version; + /* method is the underlying SSL_PROTOCOL_METHOD that initializes the + * SSL_CTX. */ + const SSL_PROTOCOL_METHOD *method; +}; + +/* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */ +struct ssl_protocol_method_st { + /* is_dtls is one if the protocol is DTLS and zero otherwise. */ + char is_dtls; + int (*ssl_new)(SSL *ssl); + void (*ssl_free)(SSL *ssl); + long (*ssl_get_message)(SSL *ssl, int msg_type, + enum ssl_hash_message_t hash_message, int *ok); + int (*ssl_read_app_data)(SSL *ssl, uint8_t *buf, int len, int peek); + int (*ssl_read_change_cipher_spec)(SSL *ssl); + void (*ssl_read_close_notify)(SSL *ssl); + int (*ssl_write_app_data)(SSL *ssl, const void *buf_, int len); + int (*ssl_dispatch_alert)(SSL *ssl); + /* supports_cipher returns one if |cipher| is supported by this protocol and + * zero otherwise. */ + int (*supports_cipher)(const SSL_CIPHER *cipher); + /* Handshake header length */ + unsigned int hhlen; + /* Set the handshake header */ + int (*set_handshake_header)(SSL *ssl, int type, unsigned long len); + /* Write out handshake message */ + int (*do_write)(SSL *ssl); + /* send_change_cipher_spec sends a ChangeCipherSpec message. */ + int (*send_change_cipher_spec)(SSL *ssl, int a, int b); + /* expect_flight is called when the handshake expects a flight of messages from + * the peer. */ + void (*expect_flight)(SSL *ssl); + /* received_flight is called when the handshake has received a flight of + * messages from the peer. */ + void (*received_flight)(SSL *ssl); +}; + +/* This is for the SSLv3/TLSv1.0 differences in crypto/hash stuff It is a bit + * of a mess of functions, but hell, think of it as an opaque structure. */ +struct ssl3_enc_method { + /* prf computes the PRF function for |ssl|. It writes |out_len| bytes to + * |out|, using |secret| as the secret and |label| as the label. |seed1| and + * |seed2| are concatenated to form the seed parameter. It returns one on + * success and zero on failure. */ + int (*prf)(const SSL *ssl, uint8_t *out, size_t out_len, + const uint8_t *secret, size_t secret_len, const char *label, + size_t label_len, const uint8_t *seed1, size_t seed1_len, + const uint8_t *seed2, size_t seed2_len); + int (*final_finish_mac)(SSL *ssl, int from_server, uint8_t *out); + int (*cert_verify_mac)(SSL *, int, uint8_t *); +}; + +#define SSL_HM_HEADER_LENGTH(ssl) ssl->method->hhlen +#define ssl_handshake_start(ssl) \ + (((uint8_t *)ssl->init_buf->data) + ssl->method->hhlen) +#define ssl_set_handshake_header(ssl, htype, len) \ + ssl->method->set_handshake_header(ssl, htype, len) +#define ssl_do_write(ssl) ssl->method->do_write(ssl) + +/* lengths of messages */ +#define DTLS1_COOKIE_LENGTH 256 + +#define DTLS1_RT_HEADER_LENGTH 13 + +#define DTLS1_HM_HEADER_LENGTH 12 + +#define DTLS1_CCS_HEADER_LENGTH 1 + +#define DTLS1_AL_HEADER_LENGTH 2 + +/* TODO(davidben): This structure is used for both incoming messages and + * outgoing messages. |is_ccs| and |epoch| are only used in the latter and + * should be moved elsewhere. */ +struct hm_header_st { + uint8_t type; + uint32_t msg_len; + uint16_t seq; + uint32_t frag_off; + uint32_t frag_len; + int is_ccs; + /* epoch, for buffered outgoing messages, is the epoch the message was + * originally sent in. */ + uint16_t epoch; +}; + +/* TODO(davidben): This structure is used for both incoming messages and + * outgoing messages. |fragment| and |reassembly| are only used in the former + * and should be moved elsewhere. */ +typedef struct hm_fragment_st { + struct hm_header_st msg_header; + uint8_t *fragment; + uint8_t *reassembly; +} hm_fragment; + +typedef struct dtls1_state_st { + /* send_cookie is true if we are resending the ClientHello + * with a cookie from a HelloVerifyRequest. */ + unsigned int send_cookie; + + uint8_t cookie[DTLS1_COOKIE_LENGTH]; + size_t cookie_len; + + /* The current data and handshake epoch. This is initially undefined, and + * starts at zero once the initial handshake is completed. */ + uint16_t r_epoch; + uint16_t w_epoch; + + /* records being received in the current epoch */ + DTLS1_BITMAP bitmap; + + /* handshake message numbers. + * TODO(davidben): It doesn't make much sense to store both of these. Only + * store one. */ + uint16_t handshake_write_seq; + uint16_t next_handshake_write_seq; + + uint16_t handshake_read_seq; + + /* save last sequence number for retransmissions */ + uint8_t last_write_sequence[8]; + + /* buffered_messages is a priority queue of incoming handshake messages that + * have yet to be processed. + * + * TODO(davidben): This data structure may as well be a ring buffer of fixed + * size. */ + pqueue buffered_messages; + + /* send_messages is a priority queue of outgoing handshake messages sent in + * the most recent handshake flight. + * + * TODO(davidben): This data structure may as well be a STACK_OF(T). */ + pqueue sent_messages; + + unsigned int mtu; /* max DTLS packet size */ + + struct hm_header_st w_msg_hdr; + + /* num_timeouts is the number of times the retransmit timer has fired since + * the last time it was reset. */ + unsigned int num_timeouts; + + /* Indicates when the last handshake msg or heartbeat sent will + * timeout. */ + struct timeval next_timeout; + + /* timeout_duration_ms is the timeout duration in milliseconds. */ + unsigned timeout_duration_ms; +} DTLS1_STATE; + +extern const SSL3_ENC_METHOD TLSv1_enc_data; +extern const SSL3_ENC_METHOD SSLv3_enc_data; + +int ssl_clear_bad_session(SSL *ssl); +CERT *ssl_cert_new(void); +CERT *ssl_cert_dup(CERT *cert); +void ssl_cert_clear_certs(CERT *c); +void ssl_cert_free(CERT *c); +int ssl_get_new_session(SSL *ssl, int is_server); + +enum ssl_session_result_t { + ssl_session_success, + ssl_session_error, + ssl_session_retry, +}; + +/* ssl_get_prev_session looks up the previous session based on |ctx|. On + * success, it sets |*out_session| to the session or NULL if none was found. It + * sets |*out_send_ticket| to whether a ticket should be sent at the end of the + * handshake. If the session could not be looked up synchronously, it returns + * |ssl_session_retry| and should be called again. Otherwise, it returns + * |ssl_session_error|. */ +enum ssl_session_result_t ssl_get_prev_session( + SSL *ssl, SSL_SESSION **out_session, int *out_send_ticket, + const struct ssl_early_callback_ctx *ctx); + +STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *ssl, const CBS *cbs); +void ssl_cipher_preference_list_free( + struct ssl_cipher_preference_list_st *cipher_list); +struct ssl_cipher_preference_list_st *ssl_get_cipher_preferences(SSL *ssl); + +int ssl_cert_set0_chain(CERT *cert, STACK_OF(X509) *chain); +int ssl_cert_set1_chain(CERT *cert, STACK_OF(X509) *chain); +int ssl_cert_add0_chain_cert(CERT *cert, X509 *x509); +int ssl_cert_add1_chain_cert(CERT *cert, X509 *x509); +void ssl_cert_set_cert_cb(CERT *cert, + int (*cb)(SSL *ssl, void *arg), void *arg); + +int ssl_verify_cert_chain(SSL *ssl, STACK_OF(X509) *cert_chain); +int ssl_add_cert_chain(SSL *ssl, unsigned long *l); +void ssl_update_cache(SSL *ssl, int mode); + +/* ssl_get_compatible_server_ciphers determines the key exchange and + * authentication cipher suite masks compatible with the server configuration + * and current ClientHello parameters of |ssl|. It sets |*out_mask_k| to the key + * exchange mask and |*out_mask_a| to the authentication mask. */ +void ssl_get_compatible_server_ciphers(SSL *ssl, uint32_t *out_mask_k, + uint32_t *out_mask_a); + +STACK_OF(SSL_CIPHER) *ssl_get_ciphers_by_id(SSL *ssl); +int ssl_verify_alarm_type(long type); + +/* ssl_fill_hello_random fills a client_random or server_random field of length + * |len|. It returns one on success and zero on failure. */ +int ssl_fill_hello_random(uint8_t *out, size_t len, int is_server); + +int ssl3_get_finished(SSL *ssl); +int ssl3_send_change_cipher_spec(SSL *ssl, int state_a, int state_b); +void ssl3_cleanup_key_block(SSL *ssl); +int ssl3_do_write(SSL *ssl, int type); +int ssl3_send_alert(SSL *ssl, int level, int desc); +int ssl3_get_req_cert_type(SSL *ssl, uint8_t *p); +long ssl3_get_message(SSL *ssl, int msg_type, + enum ssl_hash_message_t hash_message, int *ok); + +/* ssl3_hash_current_message incorporates the current handshake message into the + * handshake hash. It returns one on success and zero on allocation failure. */ +int ssl3_hash_current_message(SSL *ssl); + +/* ssl3_cert_verify_hash writes the CertificateVerify hash into the bytes + * pointed to by |out| and writes the number of bytes to |*out_len|. |out| must + * have room for EVP_MAX_MD_SIZE bytes. For TLS 1.2 and up, |*out_md| is used + * for the hash function, otherwise the hash function depends on |pkey_type| + * and is written to |*out_md|. It returns one on success and zero on + * failure. */ +int ssl3_cert_verify_hash(SSL *ssl, uint8_t *out, size_t *out_len, + const EVP_MD **out_md, int pkey_type); + +int ssl3_send_finished(SSL *ssl, int a, int b); +int ssl3_supports_cipher(const SSL_CIPHER *cipher); +int ssl3_dispatch_alert(SSL *ssl); +int ssl3_read_app_data(SSL *ssl, uint8_t *buf, int len, int peek); +int ssl3_read_change_cipher_spec(SSL *ssl); +void ssl3_read_close_notify(SSL *ssl); +int ssl3_read_bytes(SSL *ssl, int type, uint8_t *buf, int len, int peek); +int ssl3_write_app_data(SSL *ssl, const void *buf, int len); +int ssl3_write_bytes(SSL *ssl, int type, const void *buf, int len); +int ssl3_output_cert_chain(SSL *ssl); +const SSL_CIPHER *ssl3_choose_cipher( + SSL *ssl, STACK_OF(SSL_CIPHER) *clnt, + struct ssl_cipher_preference_list_st *srvr); + +int ssl3_new(SSL *ssl); +void ssl3_free(SSL *ssl); +int ssl3_accept(SSL *ssl); +int ssl3_connect(SSL *ssl); + +int ssl3_set_handshake_header(SSL *ssl, int htype, unsigned long len); +int ssl3_handshake_write(SSL *ssl); +void ssl3_expect_flight(SSL *ssl); +void ssl3_received_flight(SSL *ssl); + +int dtls1_do_handshake_write(SSL *ssl, enum dtls1_use_epoch_t use_epoch); + +/* dtls1_get_record reads a new input record. On success, it places it in + * |ssl->s3->rrec| and returns one. Otherwise it returns <= 0 on error or if + * more data is needed. */ +int dtls1_get_record(SSL *ssl); + +int dtls1_read_app_data(SSL *ssl, uint8_t *buf, int len, int peek); +int dtls1_read_change_cipher_spec(SSL *ssl); +void dtls1_read_close_notify(SSL *ssl); +void dtls1_set_message_header(SSL *ssl, uint8_t mt, unsigned long len, + unsigned short seq_num, unsigned long frag_off, + unsigned long frag_len); + +int dtls1_write_app_data(SSL *ssl, const void *buf, int len); + +/* dtls1_write_record sends a record. It returns one on success and <= 0 on + * error. */ +int dtls1_write_record(SSL *ssl, int type, const uint8_t *buf, size_t len, + enum dtls1_use_epoch_t use_epoch); + +int dtls1_send_change_cipher_spec(SSL *ssl, int a, int b); +int dtls1_send_finished(SSL *ssl, int a, int b, const char *sender, int slen); +int dtls1_buffer_message(SSL *ssl); +int dtls1_retransmit_buffered_messages(SSL *ssl); +void dtls1_clear_record_buffer(SSL *ssl); +int dtls1_parse_fragment(CBS *cbs, struct hm_header_st *out_hdr, + CBS *out_body); +int dtls1_check_timeout_num(SSL *ssl); +int dtls1_set_handshake_header(SSL *ssl, int type, unsigned long len); +int dtls1_handshake_write(SSL *ssl); +void dtls1_expect_flight(SSL *ssl); +void dtls1_received_flight(SSL *ssl); + +int dtls1_supports_cipher(const SSL_CIPHER *cipher); +void dtls1_start_timer(SSL *ssl); +void dtls1_stop_timer(SSL *ssl); +int dtls1_is_timer_expired(SSL *ssl); +void dtls1_double_timeout(SSL *ssl); +unsigned int dtls1_min_mtu(void); +void dtls1_hm_fragment_free(hm_fragment *frag); + +int dtls1_new(SSL *ssl); +int dtls1_accept(SSL *ssl); +int dtls1_connect(SSL *ssl); +void dtls1_free(SSL *ssl); + +long dtls1_get_message(SSL *ssl, int mt, enum ssl_hash_message_t hash_message, + int *ok); +int dtls1_dispatch_alert(SSL *ssl); + +/* ssl_is_wbio_buffered returns one if |ssl|'s write BIO is buffered and zero + * otherwise. */ +int ssl_is_wbio_buffered(const SSL *ssl); + +int ssl_init_wbio_buffer(SSL *ssl); +void ssl_free_wbio_buffer(SSL *ssl); + +int tls1_change_cipher_state(SSL *ssl, int which); +int tls1_setup_key_block(SSL *ssl); +int tls1_handshake_digest(SSL *ssl, uint8_t *out, size_t out_len); +int tls1_generate_master_secret(SSL *ssl, uint8_t *out, const uint8_t *premaster, + size_t premaster_len); + +char ssl_early_callback_init(struct ssl_early_callback_ctx *ctx); + +/* tls1_check_group_id returns one if |group_id| is consistent with both our + * and the peer's group preferences. Note: if called as the client, only our + * preferences are checked; the peer (the server) does not send preferences. */ +int tls1_check_group_id(SSL *ssl, uint16_t group_id); + +/* tls1_get_shared_group sets |*out_group_id| to the first preferred shared + * group between client and server preferences and returns one. If none may be + * found, it returns zero. */ +int tls1_get_shared_group(SSL *ssl, uint16_t *out_group_id); + +/* tls1_set_curves converts the array of |ncurves| NIDs pointed to by |curves| + * into a newly allocated array of TLS group IDs. On success, the function + * returns one and writes the array to |*out_group_ids| and its size to + * |*out_group_ids_len|. Otherwise, it returns zero. */ +int tls1_set_curves(uint16_t **out_group_ids, size_t *out_group_ids_len, + const int *curves, size_t ncurves); + +/* tls1_check_ec_cert returns one if |x| is an ECC certificate with curve and + * point format compatible with the client's preferences. Otherwise it returns + * zero. */ +int tls1_check_ec_cert(SSL *ssl, X509 *x); + +/* ssl_add_clienthello_tlsext writes ClientHello extensions to |out|. It + * returns one on success and zero on failure. The |header_len| argument is the + * length of the ClientHello written so far and is used to compute the padding + * length. (It does not include the record header.) */ +int ssl_add_clienthello_tlsext(SSL *ssl, CBB *out, size_t header_len); + +int ssl_add_serverhello_tlsext(SSL *ssl, CBB *out); +int ssl_parse_clienthello_tlsext(SSL *ssl, CBS *cbs); +int ssl_parse_serverhello_tlsext(SSL *ssl, CBS *cbs); + +#define tlsext_tick_md EVP_sha256 + +/* tls_process_ticket processes a session ticket from the client. On success, + * it sets |*out_session| to the decrypted session or NULL if the ticket was + * rejected. If the ticket was valid, it sets |*out_renew_ticket| to whether + * the ticket should be renewed. It returns one on success and zero on fatal + * error. */ +int tls_process_ticket(SSL *ssl, SSL_SESSION **out_session, + int *out_renew_ticket, const uint8_t *ticket, + size_t ticket_len, const uint8_t *session_id, + size_t session_id_len); + +/* tls12_add_sigandhash assembles the SignatureAndHashAlgorithm corresponding to + * |ssl|'s private key and |md|. The two-byte value is written to |out|. It + * returns one on success and zero on failure. */ +int tls12_add_sigandhash(SSL *ssl, CBB *out, const EVP_MD *md); + +int tls12_get_sigid(int pkey_type); +const EVP_MD *tls12_get_hash(uint8_t hash_alg); + +/* tls1_channel_id_hash computes the hash to be signed by Channel ID and writes + * it to |out|, which must contain at least |EVP_MAX_MD_SIZE| bytes. It returns + * one on success and zero on failure. */ +int tls1_channel_id_hash(SSL *ssl, uint8_t *out, size_t *out_len); + +int tls1_record_handshake_hashes_for_channel_id(SSL *ssl); + +/* ssl_log_rsa_client_key_exchange logs |premaster|, if logging is enabled for + * |ssl|. It returns one on success and zero on failure. The entry is identified + * by the first 8 bytes of |encrypted_premaster|. */ +int ssl_log_rsa_client_key_exchange(const SSL *ssl, + const uint8_t *encrypted_premaster, + size_t encrypted_premaster_len, + const uint8_t *premaster, + size_t premaster_len); + +/* ssl_log_master_secret logs |master|, if logging is enabled for |ssl|. It + * returns one on success and zero on failure. The entry is identified by + * |client_random|. */ +int ssl_log_master_secret(const SSL *ssl, const uint8_t *client_random, + size_t client_random_len, const uint8_t *master, + size_t master_len); + +/* ssl3_can_false_start returns one if |ssl| is allowed to False Start and zero + * otherwise. */ +int ssl3_can_false_start(const SSL *ssl); + +/* ssl3_get_enc_method returns the SSL3_ENC_METHOD corresponding to + * |version|. */ +const SSL3_ENC_METHOD *ssl3_get_enc_method(uint16_t version); + +/* ssl3_get_max_server_version returns the maximum SSL/TLS version number + * supported by |ssl| as a server, or zero if all versions are disabled. */ +uint16_t ssl3_get_max_server_version(const SSL *ssl); + +/* ssl3_get_mutual_version selects the protocol version on |ssl| for a client + * which advertises |client_version|. If no suitable version exists, it returns + * zero. */ +uint16_t ssl3_get_mutual_version(SSL *ssl, uint16_t client_version); + +/* ssl3_get_max_client_version returns the maximum protocol version configured + * for the client. It is guaranteed that the set of allowed versions at or below + * this maximum version is contiguous. If all versions are disabled, it returns + * zero. */ +uint16_t ssl3_get_max_client_version(SSL *ssl); + +/* ssl3_is_version_enabled returns one if |version| is an enabled protocol + * version for |ssl| and zero otherwise. */ +int ssl3_is_version_enabled(SSL *ssl, uint16_t version); + +/* ssl3_version_from_wire maps |wire_version| to a protocol version. For + * SSLv3/TLS, the version is returned as-is. For DTLS, the corresponding TLS + * version is used. Note that this mapping is not injective but preserves + * comparisons. + * + * TODO(davidben): To normalize some DTLS-specific code, move away from using + * the wire version except at API boundaries. */ +uint16_t ssl3_version_from_wire(const SSL *ssl, uint16_t wire_version); + +/* ssl3_protocol_version returns |ssl|'s protocol version. It is an error to + * call this function before the version is determined. */ +uint16_t ssl3_protocol_version(const SSL *ssl); + +uint32_t ssl_get_algorithm_prf(const SSL *ssl); +int tls1_parse_peer_sigalgs(SSL *ssl, const CBS *sigalgs); + +/* tls1_choose_signing_digest returns a digest for use with |ssl|'s private key + * based on the peer's preferences the digests supported. */ +const EVP_MD *tls1_choose_signing_digest(SSL *ssl); + +size_t tls12_get_psigalgs(SSL *ssl, const uint8_t **psigs); + +/* tls12_check_peer_sigalg checks that |hash| and |signature| are consistent + * with |pkey| and |ssl|'s sent, supported signature algorithms and, if so, + * writes the relevant digest into |*out_md| and returns 1. Otherwise it + * returns 0 and writes an alert into |*out_alert|. */ +int tls12_check_peer_sigalg(SSL *ssl, const EVP_MD **out_md, int *out_alert, + uint8_t hash, uint8_t signature, EVP_PKEY *pkey); +void ssl_set_client_disabled(SSL *ssl); + +#endif /* OPENSSL_HEADER_SSL_INTERNAL_H */ diff --git a/external/boringssl/ssl/pqueue/CMakeLists.txt b/external/boringssl/ssl/pqueue/CMakeLists.txt new file mode 100644 index 0000000000..294c0d13e0 --- /dev/null +++ b/external/boringssl/ssl/pqueue/CMakeLists.txt @@ -0,0 +1,22 @@ +include_directories(../../include) + +add_library( + pqueue + + OBJECT + + pqueue.c +) + +if(ENABLE_TESTS) +add_executable( + pqueue_test + + pqueue_test.c + + $ +) + +target_link_libraries(pqueue_test ssl crypto) +add_dependencies(all_tests pqueue_test) +endif() diff --git a/external/boringssl/ssl/pqueue/pqueue.c b/external/boringssl/ssl/pqueue/pqueue.c new file mode 100644 index 0000000000..e689761187 --- /dev/null +++ b/external/boringssl/ssl/pqueue/pqueue.c @@ -0,0 +1,197 @@ +/* + * DTLS implementation written by Nagendra Modadugu + * (nagendra@cs.stanford.edu) for the OpenSSL project 2005. + */ +/* ==================================================================== + * Copyright (c) 1999-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include + +#include + + +typedef struct _pqueue { + pitem *items; + unsigned count; +} pqueue_s; + + +pitem *pitem_new(uint8_t prio64be[8], void *data) { + pitem *item = OPENSSL_malloc(sizeof(pitem)); + if (item == NULL) { + return NULL; + } + + memcpy(item->priority, prio64be, sizeof(item->priority)); + + item->data = data; + item->next = NULL; + + return item; +} + +void pitem_free(pitem *item) { + if (item == NULL) { + return; + } + + OPENSSL_free(item); +} + +pqueue pqueue_new(void) { + pqueue_s *pq = OPENSSL_malloc(sizeof(pqueue_s)); + if (pq == NULL) { + return NULL; + } + + memset(pq, 0, sizeof(pqueue_s)); + return pq; +} + +void pqueue_free(pqueue_s *pq) { + if (pq == NULL) { + return; + } + + /* The queue must be empty. */ + assert(pq->items == NULL); + OPENSSL_free(pq); +} + +pitem *pqueue_peek(pqueue_s *pq) { return pq->items; } + +pitem *pqueue_find(pqueue_s *pq, uint8_t *prio64be) { + pitem *curr; + + for (curr = pq->items; curr; curr = curr->next) { + if (memcmp(curr->priority, prio64be, sizeof(curr->priority)) == 0) { + return curr; + } + } + + return NULL; +} + +size_t pqueue_size(pqueue_s *pq) { + pitem *item = pq->items; + size_t count = 0; + + while (item != NULL) { + count++; + item = item->next; + } + return count; +} + +piterator pqueue_iterator(pqueue_s *pq) { return pq->items; } + +pitem *pqueue_next(piterator *item) { + pitem *ret; + + if (item == NULL || *item == NULL) { + return NULL; + } + + ret = *item; + *item = (*item)->next; + + return ret; +} + +pitem *pqueue_insert(pqueue_s *pq, pitem *item) { + pitem *curr, *next; + + if (pq->items == NULL) { + pq->items = item; + return item; + } + + for (curr = NULL, next = pq->items; next != NULL; + curr = next, next = next->next) { + /* we can compare 64-bit value in big-endian encoding with memcmp. */ + int cmp = memcmp(next->priority, item->priority, sizeof(item->priority)); + if (cmp > 0) { + /* next > item */ + item->next = next; + + if (curr == NULL) { + pq->items = item; + } else { + curr->next = item; + } + + return item; + } else if (cmp == 0) { + /* duplicates not allowed */ + return NULL; + } + } + + item->next = NULL; + curr->next = item; + + return item; +} + + +pitem *pqueue_pop(pqueue_s *pq) { + pitem *item = pq->items; + + if (pq->items != NULL) { + pq->items = pq->items->next; + } + + return item; +} diff --git a/external/boringssl/ssl/pqueue/pqueue_test.c b/external/boringssl/ssl/pqueue/pqueue_test.c new file mode 100644 index 0000000000..f76e4a3cb7 --- /dev/null +++ b/external/boringssl/ssl/pqueue/pqueue_test.c @@ -0,0 +1,129 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include + +#include +#include +#include + + +static void clear_and_free_queue(pqueue q) { + for (;;) { + pitem *item = pqueue_pop(q); + if (item == NULL) { + break; + } + pitem_free(item); + } + pqueue_free(q); +} + +static int trivial(void) { + pqueue q = pqueue_new(); + if (q == NULL) { + return 0; + } + int32_t data = 0xdeadbeef; + uint8_t priority[8] = {0}; + pitem *item = pitem_new(priority, &data); + if (item == NULL || + pqueue_insert(q, item) != item || + pqueue_size(q) != 1 || + pqueue_peek(q) != item || + pqueue_pop(q) != item || + pqueue_size(q) != 0 || + pqueue_pop(q) != NULL) { + return 0; + } + pitem_free(item); + clear_and_free_queue(q); + return 1; +} + +#define NUM_ITEMS 10 + +static int fixed_random(void) { + /* Random order of 10 elements, chosen by + * random.choice(list(itertools.permutations(range(10)))) */ + int ordering[NUM_ITEMS] = {9, 6, 3, 4, 0, 2, 7, 1, 8, 5}; + int i; + pqueue q = pqueue_new(); + uint8_t priority[8] = {0}; + piterator iter; + pitem *curr, *item; + + if (q == NULL) { + return 0; + } + + /* Insert the elements */ + for (i = 0; i < NUM_ITEMS; i++) { + priority[7] = ordering[i]; + item = pitem_new(priority, &ordering[i]); + if (item == NULL || pqueue_insert(q, item) != item) { + return 0; + } + } + + /* Insert the elements again. This inserts duplicates and should + * fail. */ + for (i = 0; i < NUM_ITEMS; i++) { + priority[7] = ordering[i]; + item = pitem_new(priority, &ordering[i]); + if (item == NULL || pqueue_insert(q, item) != NULL) { + return 0; + } + pitem_free(item); + } + + if (pqueue_size(q) != NUM_ITEMS) { + return 0; + } + + /* Iterate over the elements. */ + iter = pqueue_iterator(q); + curr = pqueue_next(&iter); + if (curr == NULL) { + return 0; + } + while (1) { + pitem *next = pqueue_next(&iter); + int *curr_data, *next_data; + + if (next == NULL) { + break; + } + curr_data = (int*)curr->data; + next_data = (int*)next->data; + if (*curr_data >= *next_data) { + return 0; + } + curr = next; + } + clear_and_free_queue(q); + return 1; +} + +int main(void) { + CRYPTO_library_init(); + + if (!trivial() || !fixed_random()) { + return 1; + } + + printf("PASS\n"); + return 0; +} diff --git a/external/boringssl/ssl/s3_both.c b/external/boringssl/ssl/s3_both.c new file mode 100644 index 0000000000..f081066b26 --- /dev/null +++ b/external/boringssl/ssl/s3_both.c @@ -0,0 +1,551 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * ECC cipher suite support in OpenSSL originally developed by + * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. */ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "internal.h" + + +/* ssl3_do_write sends |ssl->init_buf| in records of type 'type' + * (SSL3_RT_HANDSHAKE or SSL3_RT_CHANGE_CIPHER_SPEC). It returns 1 on success + * and <= 0 on error. */ +int ssl3_do_write(SSL *ssl, int type) { + int ret = ssl3_write_bytes(ssl, type, ssl->init_buf->data, ssl->init_num); + if (ret <= 0) { + return ret; + } + + /* ssl3_write_bytes writes the data in its entirety. */ + assert(ret == ssl->init_num); + ssl_do_msg_callback(ssl, 1 /* write */, ssl->version, type, + ssl->init_buf->data, (size_t)ssl->init_num); + ssl->init_num = 0; + return 1; +} + +int ssl3_send_finished(SSL *ssl, int a, int b) { + uint8_t *p; + int n; + + if (ssl->state == a) { + p = ssl_handshake_start(ssl); + + n = ssl->s3->enc_method->final_finish_mac(ssl, ssl->server, + ssl->s3->tmp.finish_md); + if (n == 0) { + return 0; + } + ssl->s3->tmp.finish_md_len = n; + memcpy(p, ssl->s3->tmp.finish_md, n); + + /* Log the master secret, if logging is enabled. */ + if (!ssl_log_master_secret(ssl, ssl->s3->client_random, SSL3_RANDOM_SIZE, + ssl->session->master_key, + ssl->session->master_key_length)) { + return 0; + } + + /* Copy the finished so we can use it for renegotiation checks */ + if (ssl->server) { + assert(n <= EVP_MAX_MD_SIZE); + memcpy(ssl->s3->previous_server_finished, ssl->s3->tmp.finish_md, n); + ssl->s3->previous_server_finished_len = n; + } else { + assert(n <= EVP_MAX_MD_SIZE); + memcpy(ssl->s3->previous_client_finished, ssl->s3->tmp.finish_md, n); + ssl->s3->previous_client_finished_len = n; + } + + if (!ssl_set_handshake_header(ssl, SSL3_MT_FINISHED, n)) { + return 0; + } + ssl->state = b; + } + + /* SSL3_ST_SEND_xxxxxx_HELLO_B */ + return ssl_do_write(ssl); +} + +/* ssl3_take_mac calculates the Finished MAC for the handshakes messages seen + * so far. */ +static void ssl3_take_mac(SSL *ssl) { + /* If no new cipher setup then return immediately: other functions will set + * the appropriate error. */ + if (ssl->s3->tmp.new_cipher == NULL) { + return; + } + + ssl->s3->tmp.peer_finish_md_len = ssl->s3->enc_method->final_finish_mac( + ssl, !ssl->server, ssl->s3->tmp.peer_finish_md); +} + +int ssl3_get_finished(SSL *ssl) { + int al, finished_len, ok; + long message_len; + uint8_t *p; + + message_len = ssl->method->ssl_get_message(ssl, SSL3_MT_FINISHED, + ssl_dont_hash_message, &ok); + + if (!ok) { + return message_len; + } + + /* Snapshot the finished hash before incorporating the new message. */ + ssl3_take_mac(ssl); + if (!ssl3_hash_current_message(ssl)) { + goto err; + } + + p = ssl->init_msg; + finished_len = ssl->s3->tmp.peer_finish_md_len; + + if (finished_len != message_len) { + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_DIGEST_LENGTH); + goto f_err; + } + + int finished_ret = + CRYPTO_memcmp(p, ssl->s3->tmp.peer_finish_md, finished_len); +#if defined(BORINGSSL_UNSAFE_FUZZER_MODE) + finished_ret = 0; +#endif + if (finished_ret != 0) { + al = SSL_AD_DECRYPT_ERROR; + OPENSSL_PUT_ERROR(SSL, SSL_R_DIGEST_CHECK_FAILED); + goto f_err; + } + + /* Copy the finished so we can use it for renegotiation checks */ + if (ssl->server) { + assert(finished_len <= EVP_MAX_MD_SIZE); + memcpy(ssl->s3->previous_client_finished, ssl->s3->tmp.peer_finish_md, + finished_len); + ssl->s3->previous_client_finished_len = finished_len; + } else { + assert(finished_len <= EVP_MAX_MD_SIZE); + memcpy(ssl->s3->previous_server_finished, ssl->s3->tmp.peer_finish_md, + finished_len); + ssl->s3->previous_server_finished_len = finished_len; + } + + return 1; + +f_err: + ssl3_send_alert(ssl, SSL3_AL_FATAL, al); +err: + return 0; +} + +int ssl3_send_change_cipher_spec(SSL *ssl, int a, int b) { + if (ssl->state == a) { + *((uint8_t *)ssl->init_buf->data) = SSL3_MT_CCS; + ssl->init_num = 1; + + ssl->state = b; + } + + /* SSL3_ST_CW_CHANGE_B */ + return ssl3_do_write(ssl, SSL3_RT_CHANGE_CIPHER_SPEC); +} + +int ssl3_output_cert_chain(SSL *ssl) { + uint8_t *p; + unsigned long l = 3 + SSL_HM_HEADER_LENGTH(ssl); + + if (!ssl_add_cert_chain(ssl, &l)) { + return 0; + } + + l -= 3 + SSL_HM_HEADER_LENGTH(ssl); + p = ssl_handshake_start(ssl); + l2n3(l, p); + l += 3; + return ssl_set_handshake_header(ssl, SSL3_MT_CERTIFICATE, l); +} + +size_t ssl_max_handshake_message_len(const SSL *ssl) { + /* kMaxMessageLen is the default maximum message size for handshakes which do + * not accept peer certificate chains. */ + static const size_t kMaxMessageLen = 16384; + + if ((!ssl->server || (ssl->verify_mode & SSL_VERIFY_PEER)) && + kMaxMessageLen < ssl->max_cert_list) { + return ssl->max_cert_list; + } + return kMaxMessageLen; +} + +static int extend_handshake_buffer(SSL *ssl, size_t length) { + if (!BUF_MEM_reserve(ssl->init_buf, length)) { + return -1; + } + while (ssl->init_buf->length < length) { + int ret = + ssl3_read_bytes(ssl, SSL3_RT_HANDSHAKE, + (uint8_t *)ssl->init_buf->data + ssl->init_buf->length, + length - ssl->init_buf->length, 0); + if (ret <= 0) { + return ret; + } + ssl->init_buf->length += (size_t)ret; + } + return 1; +} + +/* Obtain handshake message of message type |msg_type| (any if |msg_type| == + * -1). */ +long ssl3_get_message(SSL *ssl, int msg_type, + enum ssl_hash_message_t hash_message, int *ok) { + *ok = 0; + + if (ssl->s3->tmp.reuse_message) { + /* A ssl_dont_hash_message call cannot be combined with reuse_message; the + * ssl_dont_hash_message would have to have been applied to the previous + * call. */ + assert(hash_message == ssl_hash_message); + assert(ssl->s3->tmp.message_complete); + ssl->s3->tmp.reuse_message = 0; + if (msg_type >= 0 && ssl->s3->tmp.message_type != msg_type) { + ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE); + OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE); + return -1; + } + *ok = 1; + assert(ssl->init_buf->length >= 4); + ssl->init_msg = (uint8_t *)ssl->init_buf->data + 4; + ssl->init_num = (int)ssl->init_buf->length - 4; + return ssl->init_num; + } + +again: + if (ssl->s3->tmp.message_complete) { + ssl->s3->tmp.message_complete = 0; + ssl->init_buf->length = 0; + } + + /* Read the message header, if we haven't yet. */ + int ret = extend_handshake_buffer(ssl, 4); + if (ret <= 0) { + return ret; + } + + /* Parse out the length. Cap it so the peer cannot force us to buffer up to + * 2^24 bytes. */ + const uint8_t *p = (uint8_t *)ssl->init_buf->data; + size_t msg_len = (((uint32_t)p[1]) << 16) | (((uint32_t)p[2]) << 8) | p[3]; + if (msg_len > ssl_max_handshake_message_len(ssl)) { + ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER); + OPENSSL_PUT_ERROR(SSL, SSL_R_EXCESSIVE_MESSAGE_SIZE); + return -1; + } + + /* Read the message body, if we haven't yet. */ + ret = extend_handshake_buffer(ssl, 4 + msg_len); + if (ret <= 0) { + return ret; + } + + /* We have now received a complete message. */ + ssl->s3->tmp.message_complete = 1; + ssl_do_msg_callback(ssl, 0 /* read */, ssl->version, SSL3_RT_HANDSHAKE, + ssl->init_buf->data, ssl->init_buf->length); + + static const uint8_t kHelloRequest[4] = {SSL3_MT_HELLO_REQUEST, 0, 0, 0}; + if (!ssl->server && ssl->init_buf->length == sizeof(kHelloRequest) && + memcmp(kHelloRequest, ssl->init_buf->data, sizeof(kHelloRequest)) == 0) { + /* The server may always send 'Hello Request' messages -- we are doing a + * handshake anyway now, so ignore them if their format is correct. Does + * not count for 'Finished' MAC. */ + goto again; + } + + uint8_t actual_type = ((const uint8_t *)ssl->init_buf->data)[0]; + if (msg_type >= 0 && actual_type != msg_type) { + ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE); + OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE); + return -1; + } + ssl->s3->tmp.message_type = actual_type; + + ssl->init_msg = (uint8_t*)ssl->init_buf->data + 4; + ssl->init_num = ssl->init_buf->length - 4; + + /* Feed this message into MAC computation. */ + if (hash_message == ssl_hash_message && !ssl3_hash_current_message(ssl)) { + return -1; + } + + *ok = 1; + return ssl->init_num; +} + +int ssl3_hash_current_message(SSL *ssl) { + /* The handshake header (different size between DTLS and TLS) is included in + * the hash. */ + size_t header_len = ssl->init_msg - (uint8_t *)ssl->init_buf->data; + return ssl3_update_handshake_hash(ssl, (uint8_t *)ssl->init_buf->data, + ssl->init_num + header_len); +} + +/* ssl3_cert_verify_hash is documented as needing EVP_MAX_MD_SIZE because that + * is sufficient pre-TLS1.2 as well. */ +OPENSSL_COMPILE_ASSERT(EVP_MAX_MD_SIZE > MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH, + combined_tls_hash_fits_in_max); + +int ssl3_cert_verify_hash(SSL *ssl, uint8_t *out, size_t *out_len, + const EVP_MD **out_md, int pkey_type) { + /* For TLS v1.2 send signature algorithm and signature using + * agreed digest and cached handshake records. Otherwise, use + * SHA1 or MD5 + SHA1 depending on key type. */ + if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) { + EVP_MD_CTX mctx; + unsigned len; + + EVP_MD_CTX_init(&mctx); + if (!EVP_DigestInit_ex(&mctx, *out_md, NULL) || + !EVP_DigestUpdate(&mctx, ssl->s3->handshake_buffer->data, + ssl->s3->handshake_buffer->length) || + !EVP_DigestFinal(&mctx, out, &len)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_EVP_LIB); + EVP_MD_CTX_cleanup(&mctx); + return 0; + } + *out_len = len; + } else if (pkey_type == EVP_PKEY_RSA) { + if (ssl->s3->enc_method->cert_verify_mac(ssl, NID_md5, out) == 0 || + ssl->s3->enc_method->cert_verify_mac(ssl, NID_sha1, + out + MD5_DIGEST_LENGTH) == 0) { + return 0; + } + *out_len = MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH; + *out_md = EVP_md5_sha1(); + } else if (pkey_type == EVP_PKEY_EC) { + if (ssl->s3->enc_method->cert_verify_mac(ssl, NID_sha1, out) == 0) { + return 0; + } + *out_len = SHA_DIGEST_LENGTH; + *out_md = EVP_sha1(); + } else { + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + return 0; + } + + return 1; +} + +int ssl_verify_alarm_type(long type) { + int al; + + switch (type) { + case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: + case X509_V_ERR_UNABLE_TO_GET_CRL: + case X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER: + al = SSL_AD_UNKNOWN_CA; + break; + + case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE: + case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE: + case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: + case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: + case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: + case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD: + case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD: + case X509_V_ERR_CERT_NOT_YET_VALID: + case X509_V_ERR_CRL_NOT_YET_VALID: + case X509_V_ERR_CERT_UNTRUSTED: + case X509_V_ERR_CERT_REJECTED: + case X509_V_ERR_HOSTNAME_MISMATCH: + case X509_V_ERR_EMAIL_MISMATCH: + case X509_V_ERR_IP_ADDRESS_MISMATCH: + al = SSL_AD_BAD_CERTIFICATE; + break; + + case X509_V_ERR_CERT_SIGNATURE_FAILURE: + case X509_V_ERR_CRL_SIGNATURE_FAILURE: + al = SSL_AD_DECRYPT_ERROR; + break; + + case X509_V_ERR_CERT_HAS_EXPIRED: + case X509_V_ERR_CRL_HAS_EXPIRED: + al = SSL_AD_CERTIFICATE_EXPIRED; + break; + + case X509_V_ERR_CERT_REVOKED: + al = SSL_AD_CERTIFICATE_REVOKED; + break; + + case X509_V_ERR_UNSPECIFIED: + case X509_V_ERR_OUT_OF_MEM: + case X509_V_ERR_INVALID_CALL: + case X509_V_ERR_STORE_LOOKUP: + al = SSL_AD_INTERNAL_ERROR; + break; + + case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: + case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: + case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: + case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: + case X509_V_ERR_CERT_CHAIN_TOO_LONG: + case X509_V_ERR_PATH_LENGTH_EXCEEDED: + case X509_V_ERR_INVALID_CA: + al = SSL_AD_UNKNOWN_CA; + break; + + case X509_V_ERR_APPLICATION_VERIFICATION: + al = SSL_AD_HANDSHAKE_FAILURE; + break; + + case X509_V_ERR_INVALID_PURPOSE: + al = SSL_AD_UNSUPPORTED_CERTIFICATE; + break; + + default: + al = SSL_AD_CERTIFICATE_UNKNOWN; + break; + } + + return al; +} + +int ssl_fill_hello_random(uint8_t *out, size_t len, int is_server) { + if (is_server) { + const uint32_t current_time = time(NULL); + uint8_t *p = out; + + if (len < 4) { + return 0; + } + p[0] = current_time >> 24; + p[1] = current_time >> 16; + p[2] = current_time >> 8; + p[3] = current_time; + return RAND_bytes(p + 4, len - 4); + } else { + return RAND_bytes(out, len); + } +} diff --git a/external/boringssl/ssl/s3_enc.c b/external/boringssl/ssl/s3_enc.c new file mode 100644 index 0000000000..04aa08c9f9 --- /dev/null +++ b/external/boringssl/ssl/s3_enc.c @@ -0,0 +1,394 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2005 Nokia. All rights reserved. + * + * The portions of the attached software ("Contribution") is developed by + * Nokia Corporation and is licensed pursuant to the OpenSSL open source + * license. + * + * The Contribution, originally written by Mika Kousa and Pasi Eronen of + * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites + * support (see RFC 4279) to OpenSSL. + * + * No patent licenses or other rights except those expressly stated in + * the OpenSSL open source license shall be deemed granted or received + * expressly, by implication, estoppel, or otherwise. + * + * No assurances are provided by Nokia that the Contribution does not + * infringe the patent or other intellectual property rights of any third + * party or that the license provides you with all the necessary rights + * to make use of the Contribution. + * + * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN + * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA + * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY + * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR + * OTHERWISE. */ + +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include "internal.h" + + +static int ssl3_handshake_mac(SSL *ssl, int md_nid, const char *sender, + size_t sender_len, uint8_t *p); + +static int ssl3_prf(const SSL *ssl, uint8_t *out, size_t out_len, + const uint8_t *secret, size_t secret_len, const char *label, + size_t label_len, const uint8_t *seed1, size_t seed1_len, + const uint8_t *seed2, size_t seed2_len) { + EVP_MD_CTX md5; + EVP_MD_CTX sha1; + uint8_t buf[16], smd[SHA_DIGEST_LENGTH]; + uint8_t c = 'A'; + size_t i, j, k; + + k = 0; + EVP_MD_CTX_init(&md5); + EVP_MD_CTX_init(&sha1); + for (i = 0; i < out_len; i += MD5_DIGEST_LENGTH) { + k++; + if (k > sizeof(buf)) { + /* bug: 'buf' is too small for this ciphersuite */ + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + return 0; + } + + for (j = 0; j < k; j++) { + buf[j] = c; + } + c++; + if (!EVP_DigestInit_ex(&sha1, EVP_sha1(), NULL)) { + OPENSSL_PUT_ERROR(SSL, ERR_LIB_EVP); + return 0; + } + EVP_DigestUpdate(&sha1, buf, k); + EVP_DigestUpdate(&sha1, secret, secret_len); + /* |label| is ignored for SSLv3. */ + if (seed1_len) { + EVP_DigestUpdate(&sha1, seed1, seed1_len); + } + if (seed2_len) { + EVP_DigestUpdate(&sha1, seed2, seed2_len); + } + EVP_DigestFinal_ex(&sha1, smd, NULL); + + if (!EVP_DigestInit_ex(&md5, EVP_md5(), NULL)) { + OPENSSL_PUT_ERROR(SSL, ERR_LIB_EVP); + return 0; + } + EVP_DigestUpdate(&md5, secret, secret_len); + EVP_DigestUpdate(&md5, smd, SHA_DIGEST_LENGTH); + if (i + MD5_DIGEST_LENGTH > out_len) { + EVP_DigestFinal_ex(&md5, smd, NULL); + memcpy(out, smd, out_len - i); + } else { + EVP_DigestFinal_ex(&md5, out, NULL); + } + + out += MD5_DIGEST_LENGTH; + } + + OPENSSL_cleanse(smd, SHA_DIGEST_LENGTH); + EVP_MD_CTX_cleanup(&md5); + EVP_MD_CTX_cleanup(&sha1); + + return 1; +} + +void ssl3_cleanup_key_block(SSL *ssl) { + if (ssl->s3->tmp.key_block != NULL) { + OPENSSL_cleanse(ssl->s3->tmp.key_block, ssl->s3->tmp.key_block_length); + OPENSSL_free(ssl->s3->tmp.key_block); + ssl->s3->tmp.key_block = NULL; + } + ssl->s3->tmp.key_block_length = 0; +} + +int ssl3_init_handshake_buffer(SSL *ssl) { + ssl3_free_handshake_buffer(ssl); + ssl3_free_handshake_hash(ssl); + ssl->s3->handshake_buffer = BUF_MEM_new(); + return ssl->s3->handshake_buffer != NULL; +} + +/* init_digest_with_data calls |EVP_DigestInit_ex| on |ctx| with |md| and then + * writes the data in |buf| to it. */ +static int init_digest_with_data(EVP_MD_CTX *ctx, const EVP_MD *md, + const BUF_MEM *buf) { + if (!EVP_DigestInit_ex(ctx, md, NULL)) { + return 0; + } + EVP_DigestUpdate(ctx, buf->data, buf->length); + return 1; +} + +int ssl3_init_handshake_hash(SSL *ssl) { + ssl3_free_handshake_hash(ssl); + + uint32_t algorithm_prf = ssl_get_algorithm_prf(ssl); + if (!init_digest_with_data(&ssl->s3->handshake_hash, + ssl_get_handshake_digest(algorithm_prf), + ssl->s3->handshake_buffer)) { + return 0; + } + + if (algorithm_prf == SSL_HANDSHAKE_MAC_DEFAULT && + !init_digest_with_data(&ssl->s3->handshake_md5, EVP_md5(), + ssl->s3->handshake_buffer)) { + return 0; + } + + return 1; +} + +void ssl3_free_handshake_hash(SSL *ssl) { + EVP_MD_CTX_cleanup(&ssl->s3->handshake_hash); + EVP_MD_CTX_cleanup(&ssl->s3->handshake_md5); +} + +void ssl3_free_handshake_buffer(SSL *ssl) { + BUF_MEM_free(ssl->s3->handshake_buffer); + ssl->s3->handshake_buffer = NULL; +} + +int ssl3_update_handshake_hash(SSL *ssl, const uint8_t *in, size_t in_len) { + /* Depending on the state of the handshake, either the handshake buffer may be + * active, the rolling hash, or both. */ + + if (ssl->s3->handshake_buffer != NULL) { + size_t new_len = ssl->s3->handshake_buffer->length + in_len; + if (new_len < in_len) { + OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW); + return 0; + } + if (!BUF_MEM_grow(ssl->s3->handshake_buffer, new_len)) { + return 0; + } + memcpy(ssl->s3->handshake_buffer->data + new_len - in_len, in, in_len); + } + + if (EVP_MD_CTX_md(&ssl->s3->handshake_hash) != NULL) { + EVP_DigestUpdate(&ssl->s3->handshake_hash, in, in_len); + } + if (EVP_MD_CTX_md(&ssl->s3->handshake_md5) != NULL) { + EVP_DigestUpdate(&ssl->s3->handshake_md5, in, in_len); + } + return 1; +} + +static int ssl3_cert_verify_mac(SSL *ssl, int md_nid, uint8_t *p) { + return ssl3_handshake_mac(ssl, md_nid, NULL, 0, p); +} + +static int ssl3_final_finish_mac(SSL *ssl, int from_server, uint8_t *out) { + const char *sender = from_server ? SSL3_MD_SERVER_FINISHED_CONST + : SSL3_MD_CLIENT_FINISHED_CONST; + const size_t sender_len = 4; + int ret, sha1len; + ret = ssl3_handshake_mac(ssl, NID_md5, sender, sender_len, out); + if (ret == 0) { + return 0; + } + + out += ret; + + sha1len = ssl3_handshake_mac(ssl, NID_sha1, sender, sender_len, out); + if (sha1len == 0) { + return 0; + } + + ret += sha1len; + return ret; +} + +static int ssl3_handshake_mac(SSL *ssl, int md_nid, const char *sender, + size_t sender_len, uint8_t *p) { + unsigned int ret; + size_t npad, n; + unsigned int i; + uint8_t md_buf[EVP_MAX_MD_SIZE]; + EVP_MD_CTX ctx; + const EVP_MD_CTX *ctx_template; + + if (md_nid == NID_md5) { + ctx_template = &ssl->s3->handshake_md5; + } else if (md_nid == EVP_MD_CTX_type(&ssl->s3->handshake_hash)) { + ctx_template = &ssl->s3->handshake_hash; + } else { + OPENSSL_PUT_ERROR(SSL, SSL_R_NO_REQUIRED_DIGEST); + return 0; + } + + EVP_MD_CTX_init(&ctx); + if (!EVP_MD_CTX_copy_ex(&ctx, ctx_template)) { + EVP_MD_CTX_cleanup(&ctx); + OPENSSL_PUT_ERROR(SSL, ERR_LIB_EVP); + return 0; + } + + static const uint8_t kPad1[48] = { + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + }; + + static const uint8_t kPad2[48] = { + 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, + 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, + 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, + 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, + }; + + n = EVP_MD_CTX_size(&ctx); + + npad = (48 / n) * n; + if (sender != NULL) { + EVP_DigestUpdate(&ctx, sender, sender_len); + } + EVP_DigestUpdate(&ctx, ssl->session->master_key, + ssl->session->master_key_length); + EVP_DigestUpdate(&ctx, kPad1, npad); + EVP_DigestFinal_ex(&ctx, md_buf, &i); + + if (!EVP_DigestInit_ex(&ctx, EVP_MD_CTX_md(&ctx), NULL)) { + EVP_MD_CTX_cleanup(&ctx); + OPENSSL_PUT_ERROR(SSL, ERR_LIB_EVP); + return 0; + } + EVP_DigestUpdate(&ctx, ssl->session->master_key, + ssl->session->master_key_length); + EVP_DigestUpdate(&ctx, kPad2, npad); + EVP_DigestUpdate(&ctx, md_buf, i); + EVP_DigestFinal_ex(&ctx, p, &ret); + + EVP_MD_CTX_cleanup(&ctx); + + return ret; +} + + + +const SSL3_ENC_METHOD SSLv3_enc_data = { + ssl3_prf, + ssl3_final_finish_mac, + ssl3_cert_verify_mac, +}; diff --git a/external/boringssl/ssl/s3_lib.c b/external/boringssl/ssl/s3_lib.c new file mode 100644 index 0000000000..43dcb020c9 --- /dev/null +++ b/external/boringssl/ssl/s3_lib.c @@ -0,0 +1,375 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * + * Portions of the attached software ("Contribution") are developed by + * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. + * + * The Contribution is licensed pursuant to the OpenSSL open source + * license provided above. + * + * ECC cipher suite support in OpenSSL originally written by + * Vipul Gupta and Sumit Gupta of Sun Microsystems Laboratories. + * + */ +/* ==================================================================== + * Copyright 2005 Nokia. All rights reserved. + * + * The portions of the attached software ("Contribution") is developed by + * Nokia Corporation and is licensed pursuant to the OpenSSL open source + * license. + * + * The Contribution, originally written by Mika Kousa and Pasi Eronen of + * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites + * support (see RFC 4279) to OpenSSL. + * + * No patent licenses or other rights except those expressly stated in + * the OpenSSL open source license shall be deemed granted or received + * expressly, by implication, estoppel, or otherwise. + * + * No assurances are provided by Nokia that the Contribution does not + * infringe the patent or other intellectual property rights of any third + * party or that the license provides you with all the necessary rights + * to make use of the Contribution. + * + * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN + * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA + * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY + * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR + * OTHERWISE. */ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "internal.h" + + +int ssl3_supports_cipher(const SSL_CIPHER *cipher) { + return 1; +} + +int ssl3_set_handshake_header(SSL *ssl, int htype, unsigned long len) { + uint8_t *p = (uint8_t *)ssl->init_buf->data; + *(p++) = htype; + l2n3(len, p); + ssl->init_num = (int)len + SSL3_HM_HEADER_LENGTH; + + /* Add the message to the handshake hash. */ + return ssl3_update_handshake_hash(ssl, (uint8_t *)ssl->init_buf->data, + ssl->init_num); +} + +int ssl3_handshake_write(SSL *ssl) { + return ssl3_do_write(ssl, SSL3_RT_HANDSHAKE); +} + +void ssl3_expect_flight(SSL *ssl) {} + +void ssl3_received_flight(SSL *ssl) {} + +int ssl3_new(SSL *ssl) { + SSL3_STATE *s3; + + s3 = OPENSSL_malloc(sizeof *s3); + if (s3 == NULL) { + goto err; + } + memset(s3, 0, sizeof *s3); + + EVP_MD_CTX_init(&s3->handshake_hash); + EVP_MD_CTX_init(&s3->handshake_md5); + + ssl->s3 = s3; + + /* Set the version to the highest supported version. + * + * TODO(davidben): Move this field into |s3|, have it store the normalized + * protocol version, and implement this pre-negotiation quirk in |SSL_version| + * at the API boundary rather than in internal state. */ + ssl->version = TLS1_2_VERSION; + return 1; +err: + return 0; +} + +void ssl3_free(SSL *ssl) { + if (ssl == NULL || ssl->s3 == NULL) { + return; + } + + ssl3_cleanup_key_block(ssl); + ssl_read_buffer_clear(ssl); + ssl_write_buffer_clear(ssl); + SSL_ECDH_CTX_cleanup(&ssl->s3->tmp.ecdh_ctx); + OPENSSL_free(ssl->s3->tmp.peer_key); + + sk_X509_NAME_pop_free(ssl->s3->tmp.ca_names, X509_NAME_free); + OPENSSL_free(ssl->s3->tmp.certificate_types); + OPENSSL_free(ssl->s3->tmp.peer_supported_group_list); + OPENSSL_free(ssl->s3->tmp.peer_psk_identity_hint); + ssl3_free_handshake_buffer(ssl); + ssl3_free_handshake_hash(ssl); + OPENSSL_free(ssl->s3->next_proto_negotiated); + OPENSSL_free(ssl->s3->alpn_selected); + SSL_AEAD_CTX_free(ssl->s3->aead_read_ctx); + SSL_AEAD_CTX_free(ssl->s3->aead_write_ctx); + + OPENSSL_cleanse(ssl->s3, sizeof *ssl->s3); + OPENSSL_free(ssl->s3); + ssl->s3 = NULL; +} + +struct ssl_cipher_preference_list_st *ssl_get_cipher_preferences(SSL *ssl) { + if (ssl->cipher_list != NULL) { + return ssl->cipher_list; + } + + if (ssl->version >= TLS1_1_VERSION && ssl->ctx->cipher_list_tls11 != NULL) { + return ssl->ctx->cipher_list_tls11; + } + + if (ssl->version >= TLS1_VERSION && ssl->ctx->cipher_list_tls10 != NULL) { + return ssl->ctx->cipher_list_tls10; + } + + if (ssl->ctx->cipher_list != NULL) { + return ssl->ctx->cipher_list; + } + + return NULL; +} + +const SSL_CIPHER *ssl3_choose_cipher( + SSL *ssl, STACK_OF(SSL_CIPHER) *clnt, + struct ssl_cipher_preference_list_st *server_pref) { + const SSL_CIPHER *c, *ret = NULL; + STACK_OF(SSL_CIPHER) *srvr = server_pref->ciphers, *prio, *allow; + size_t i; + int ok; + size_t cipher_index; + uint32_t alg_k, alg_a, mask_k, mask_a; + /* in_group_flags will either be NULL, or will point to an array of bytes + * which indicate equal-preference groups in the |prio| stack. See the + * comment about |in_group_flags| in the |ssl_cipher_preference_list_st| + * struct. */ + const uint8_t *in_group_flags; + /* group_min contains the minimal index so far found in a group, or -1 if no + * such value exists yet. */ + int group_min = -1; + + if (ssl->options & SSL_OP_CIPHER_SERVER_PREFERENCE) { + prio = srvr; + in_group_flags = server_pref->in_group_flags; + allow = clnt; + } else { + prio = clnt; + in_group_flags = NULL; + allow = srvr; + } + + ssl_get_compatible_server_ciphers(ssl, &mask_k, &mask_a); + + for (i = 0; i < sk_SSL_CIPHER_num(prio); i++) { + c = sk_SSL_CIPHER_value(prio, i); + + ok = 1; + + /* Check the TLS version. */ + if (SSL_CIPHER_get_min_version(c) > ssl3_protocol_version(ssl)) { + ok = 0; + } + + alg_k = c->algorithm_mkey; + alg_a = c->algorithm_auth; + + ok = ok && (alg_k & mask_k) && (alg_a & mask_a); + + if (ok && sk_SSL_CIPHER_find(allow, &cipher_index, c)) { + if (in_group_flags != NULL && in_group_flags[i] == 1) { + /* This element of |prio| is in a group. Update the minimum index found + * so far and continue looking. */ + if (group_min == -1 || (size_t)group_min > cipher_index) { + group_min = cipher_index; + } + } else { + if (group_min != -1 && (size_t)group_min < cipher_index) { + cipher_index = group_min; + } + ret = sk_SSL_CIPHER_value(allow, cipher_index); + break; + } + } + + if (in_group_flags != NULL && in_group_flags[i] == 0 && group_min != -1) { + /* We are about to leave a group, but we found a match in it, so that's + * our answer. */ + ret = sk_SSL_CIPHER_value(allow, group_min); + break; + } + } + + return ret; +} + +int ssl3_get_req_cert_type(SSL *ssl, uint8_t *p) { + int ret = 0; + const uint8_t *sig; + size_t i, siglen; + int have_rsa_sign = 0; + int have_ecdsa_sign = 0; + + /* get configured sigalgs */ + siglen = tls12_get_psigalgs(ssl, &sig); + for (i = 0; i < siglen; i += 2, sig += 2) { + switch (sig[1]) { + case TLSEXT_signature_rsa: + have_rsa_sign = 1; + break; + + case TLSEXT_signature_ecdsa: + have_ecdsa_sign = 1; + break; + } + } + + if (have_rsa_sign) { + p[ret++] = SSL3_CT_RSA_SIGN; + } + + /* ECDSA certs can be used with RSA cipher suites as well so we don't need to + * check for SSL_kECDH or SSL_kECDHE. */ + if (ssl->version >= TLS1_VERSION && have_ecdsa_sign) { + p[ret++] = TLS_CT_ECDSA_SIGN; + } + + return ret; +} + +/* If we are using default SHA1+MD5 algorithms switch to new SHA256 PRF and + * handshake macs if required. */ +uint32_t ssl_get_algorithm_prf(const SSL *ssl) { + uint32_t algorithm_prf = ssl->s3->tmp.new_cipher->algorithm_prf; + if (algorithm_prf == SSL_HANDSHAKE_MAC_DEFAULT && + ssl3_protocol_version(ssl) >= TLS1_2_VERSION) { + return SSL_HANDSHAKE_MAC_SHA256; + } + return algorithm_prf; +} diff --git a/external/boringssl/ssl/s3_meth.c b/external/boringssl/ssl/s3_meth.c new file mode 100644 index 0000000000..8370f23f22 --- /dev/null +++ b/external/boringssl/ssl/s3_meth.c @@ -0,0 +1,167 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include "internal.h" + + +static const SSL_PROTOCOL_METHOD TLS_protocol_method = { + 0 /* is_dtls */, + ssl3_new, + ssl3_free, + ssl3_get_message, + ssl3_read_app_data, + ssl3_read_change_cipher_spec, + ssl3_read_close_notify, + ssl3_write_app_data, + ssl3_dispatch_alert, + ssl3_supports_cipher, + SSL3_HM_HEADER_LENGTH, + ssl3_set_handshake_header, + ssl3_handshake_write, + ssl3_send_change_cipher_spec, + ssl3_expect_flight, + ssl3_received_flight, +}; + +const SSL_METHOD *TLS_method(void) { + static const SSL_METHOD method = { + 0, + &TLS_protocol_method, + }; + return &method; +} + +const SSL_METHOD *SSLv23_method(void) { + return TLS_method(); +} + +/* Legacy version-locked methods. */ + +const SSL_METHOD *TLSv1_2_method(void) { + static const SSL_METHOD method = { + TLS1_2_VERSION, + &TLS_protocol_method, + }; + return &method; +} + +const SSL_METHOD *TLSv1_1_method(void) { + static const SSL_METHOD method = { + TLS1_1_VERSION, + &TLS_protocol_method, + }; + return &method; +} + +const SSL_METHOD *TLSv1_method(void) { + static const SSL_METHOD method = { + TLS1_VERSION, + &TLS_protocol_method, + }; + return &method; +} + +const SSL_METHOD *SSLv3_method(void) { + static const SSL_METHOD method = { + SSL3_VERSION, + &TLS_protocol_method, + }; + return &method; +} + +/* Legacy side-specific methods. */ + +const SSL_METHOD *TLSv1_2_server_method(void) { + return TLSv1_2_method(); +} + +const SSL_METHOD *TLSv1_1_server_method(void) { + return TLSv1_1_method(); +} + +const SSL_METHOD *TLSv1_server_method(void) { + return TLSv1_method(); +} + +const SSL_METHOD *SSLv3_server_method(void) { + return SSLv3_method(); +} + +const SSL_METHOD *TLSv1_2_client_method(void) { + return TLSv1_2_method(); +} + +const SSL_METHOD *TLSv1_1_client_method(void) { + return TLSv1_1_method(); +} + +const SSL_METHOD *TLSv1_client_method(void) { + return TLSv1_method(); +} + +const SSL_METHOD *SSLv3_client_method(void) { + return SSLv3_method(); +} + +const SSL_METHOD *SSLv23_server_method(void) { + return SSLv23_method(); +} + +const SSL_METHOD *SSLv23_client_method(void) { + return SSLv23_method(); +} diff --git a/external/boringssl/ssl/s3_pkt.c b/external/boringssl/ssl/s3_pkt.c new file mode 100644 index 0000000000..2396a7fd41 --- /dev/null +++ b/external/boringssl/ssl/s3_pkt.c @@ -0,0 +1,559 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "internal.h" + + +static int do_ssl3_write(SSL *ssl, int type, const uint8_t *buf, unsigned len); + +/* ssl3_get_record reads a new input record. On success, it places it in + * |ssl->s3->rrec| and returns one. Otherwise it returns <= 0 on error or if + * more data is needed. */ +static int ssl3_get_record(SSL *ssl) { +again: + switch (ssl->s3->recv_shutdown) { + case ssl_shutdown_none: + break; + case ssl_shutdown_fatal_alert: + OPENSSL_PUT_ERROR(SSL, SSL_R_PROTOCOL_IS_SHUTDOWN); + return -1; + case ssl_shutdown_close_notify: + return 0; + } + + CBS body; + uint8_t type, alert; + size_t consumed; + enum ssl_open_record_t open_ret = + tls_open_record(ssl, &type, &body, &consumed, &alert, + ssl_read_buffer(ssl), ssl_read_buffer_len(ssl)); + if (open_ret != ssl_open_record_partial) { + ssl_read_buffer_consume(ssl, consumed); + } + switch (open_ret) { + case ssl_open_record_partial: { + int read_ret = ssl_read_buffer_extend_to(ssl, consumed); + if (read_ret <= 0) { + return read_ret; + } + goto again; + } + + case ssl_open_record_success: + if (CBS_len(&body) > 0xffff) { + OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW); + return -1; + } + + SSL3_RECORD *rr = &ssl->s3->rrec; + rr->type = type; + rr->length = (uint16_t)CBS_len(&body); + rr->data = (uint8_t *)CBS_data(&body); + return 1; + + case ssl_open_record_discard: + goto again; + + case ssl_open_record_close_notify: + return 0; + + case ssl_open_record_fatal_alert: + return -1; + + case ssl_open_record_error: + ssl3_send_alert(ssl, SSL3_AL_FATAL, alert); + return -1; + } + + assert(0); + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + return -1; +} + +int ssl3_write_app_data(SSL *ssl, const void *buf, int len) { + assert(!SSL_in_init(ssl) || SSL_in_false_start(ssl)); + + return ssl3_write_bytes(ssl, SSL3_RT_APPLICATION_DATA, buf, len); +} + +/* Call this to write data in records of type |type|. It will return <= 0 if + * not all data has been sent or non-blocking IO. */ +int ssl3_write_bytes(SSL *ssl, int type, const void *buf_, int len) { + const uint8_t *buf = buf_; + unsigned tot, n, nw; + + assert(ssl->s3->wnum <= INT_MAX); + tot = ssl->s3->wnum; + ssl->s3->wnum = 0; + + /* Ensure that if we end up with a smaller value of data to write out than + * the the original len from a write which didn't complete for non-blocking + * I/O and also somehow ended up avoiding the check for this in + * ssl3_write_pending/SSL_R_BAD_WRITE_RETRY as it must never be possible to + * end up with (len-tot) as a large number that will then promptly send + * beyond the end of the users buffer ... so we trap and report the error in + * a way the user will notice. */ + if (len < 0 || (size_t)len < tot) { + OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_LENGTH); + return -1; + } + + n = (len - tot); + for (;;) { + /* max contains the maximum number of bytes that we can put into a + * record. */ + unsigned max = ssl->max_send_fragment; + if (n > max) { + nw = max; + } else { + nw = n; + } + + int ret = do_ssl3_write(ssl, type, &buf[tot], nw); + if (ret <= 0) { + ssl->s3->wnum = tot; + return ret; + } + + if (ret == (int)n || (type == SSL3_RT_APPLICATION_DATA && + (ssl->mode & SSL_MODE_ENABLE_PARTIAL_WRITE))) { + return tot + ret; + } + + n -= ret; + tot += ret; + } +} + +static int ssl3_write_pending(SSL *ssl, int type, const uint8_t *buf, + unsigned int len) { + if (ssl->s3->wpend_tot > (int)len || + (ssl->s3->wpend_buf != buf && + !(ssl->mode & SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER)) || + ssl->s3->wpend_type != type) { + OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_WRITE_RETRY); + return -1; + } + + int ret = ssl_write_buffer_flush(ssl); + if (ret <= 0) { + return ret; + } + return ssl->s3->wpend_ret; +} + +/* do_ssl3_write writes an SSL record of the given type. */ +static int do_ssl3_write(SSL *ssl, int type, const uint8_t *buf, unsigned len) { + /* If there is still data from the previous record, flush it. */ + if (ssl_write_buffer_is_pending(ssl)) { + return ssl3_write_pending(ssl, type, buf, len); + } + + /* If we have an alert to send, lets send it */ + if (ssl->s3->alert_dispatch) { + int ret = ssl->method->ssl_dispatch_alert(ssl); + if (ret <= 0) { + return ret; + } + /* if it went, fall through and send more stuff */ + } + + if (len > SSL3_RT_MAX_PLAIN_LENGTH) { + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + return -1; + } + + if (len == 0) { + return 0; + } + + size_t max_out = len + ssl_max_seal_overhead(ssl); + if (max_out < len) { + OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW); + return -1; + } + uint8_t *out; + size_t ciphertext_len; + if (!ssl_write_buffer_init(ssl, &out, max_out) || + !tls_seal_record(ssl, out, &ciphertext_len, max_out, type, buf, len)) { + return -1; + } + ssl_write_buffer_set_len(ssl, ciphertext_len); + + /* memorize arguments so that ssl3_write_pending can detect bad write retries + * later */ + ssl->s3->wpend_tot = len; + ssl->s3->wpend_buf = buf; + ssl->s3->wpend_type = type; + ssl->s3->wpend_ret = len; + + /* we now just need to write the buffer */ + return ssl3_write_pending(ssl, type, buf, len); +} + +int ssl3_read_app_data(SSL *ssl, uint8_t *buf, int len, int peek) { + assert(!SSL_in_init(ssl)); + assert(ssl->s3->initial_handshake_complete); + + return ssl3_read_bytes(ssl, SSL3_RT_APPLICATION_DATA, buf, len, peek); +} + +int ssl3_read_change_cipher_spec(SSL *ssl) { + SSL3_RECORD *rr = &ssl->s3->rrec; + + if (rr->length == 0) { + int ret = ssl3_get_record(ssl); + if (ret <= 0) { + return ret; + } + } + + if (rr->type != SSL3_RT_CHANGE_CIPHER_SPEC) { + ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE); + OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD); + return -1; + } + + if (rr->length != 1 || rr->data[0] != SSL3_MT_CCS) { + OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_CHANGE_CIPHER_SPEC); + ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER); + return -1; + } + + ssl_do_msg_callback(ssl, 0 /* read */, ssl->version, + SSL3_RT_CHANGE_CIPHER_SPEC, rr->data, rr->length); + + rr->length = 0; + ssl_read_buffer_discard(ssl); + return 1; +} + +void ssl3_read_close_notify(SSL *ssl) { + /* Read records until an error or close_notify. */ + while (ssl3_get_record(ssl) > 0) { + ; + } +} + +static int ssl3_can_renegotiate(SSL *ssl) { + switch (ssl->renegotiate_mode) { + case ssl_renegotiate_never: + return 0; + case ssl_renegotiate_once: + return ssl->s3->total_renegotiations == 0; + case ssl_renegotiate_freely: + return 1; + case ssl_renegotiate_ignore: + return 1; + } + + assert(0); + return 0; +} + +/* Return up to 'len' payload bytes received in 'type' records. + * 'type' is one of the following: + * + * - SSL3_RT_HANDSHAKE (when ssl3_get_message calls us) + * - SSL3_RT_APPLICATION_DATA (when ssl3_read_app_data calls us) + * + * If we don't have stored data to work from, read a SSL/TLS record first + * (possibly multiple records if we still don't have anything to return). + * + * This function must handle any surprises the peer may have for us, such as + * Alert records (e.g. close_notify) or renegotiation requests. */ +int ssl3_read_bytes(SSL *ssl, int type, uint8_t *buf, int len, int peek) { + int al, i, ret; + unsigned int n; + SSL3_RECORD *rr; + + if ((type != SSL3_RT_APPLICATION_DATA && type != SSL3_RT_HANDSHAKE) || + (peek && type != SSL3_RT_APPLICATION_DATA)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + return -1; + } + +start: + /* ssl->s3->rrec.type - is the type of record + * ssl->s3->rrec.data - data + * ssl->s3->rrec.off - offset into 'data' for next read + * ssl->s3->rrec.length - number of bytes. */ + rr = &ssl->s3->rrec; + + /* get new packet if necessary */ + if (rr->length == 0) { + ret = ssl3_get_record(ssl); + if (ret <= 0) { + return ret; + } + } + + /* we now have a packet which can be read and processed */ + + if (type == rr->type) { + /* Discard empty records. */ + if (rr->length == 0) { + goto start; + } + + if (len <= 0) { + return len; + } + + if ((unsigned int)len > rr->length) { + n = rr->length; + } else { + n = (unsigned int)len; + } + + memcpy(buf, rr->data, n); + if (!peek) { + rr->length -= n; + rr->data += n; + if (rr->length == 0) { + /* The record has been consumed, so we may now clear the buffer. */ + ssl_read_buffer_discard(ssl); + } + } + + return n; + } + + /* Process unexpected records. */ + + if (type == SSL3_RT_APPLICATION_DATA && rr->type == SSL3_RT_HANDSHAKE) { + /* If peer renegotiations are disabled, all out-of-order handshake records + * are fatal. Renegotiations as a server are never supported. */ + if (ssl->server || !ssl3_can_renegotiate(ssl)) { + al = SSL_AD_NO_RENEGOTIATION; + OPENSSL_PUT_ERROR(SSL, SSL_R_NO_RENEGOTIATION); + goto f_err; + } + + /* This must be a HelloRequest, possibly fragmented over multiple records. + * Consume data from the handshake protocol until it is complete. */ + static const uint8_t kHelloRequest[] = {SSL3_MT_HELLO_REQUEST, 0, 0, 0}; + while (ssl->s3->hello_request_len < sizeof(kHelloRequest)) { + if (rr->length == 0) { + /* Get a new record. */ + goto start; + } + if (rr->data[0] != kHelloRequest[ssl->s3->hello_request_len]) { + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_HELLO_REQUEST); + goto f_err; + } + rr->data++; + rr->length--; + ssl->s3->hello_request_len++; + } + ssl->s3->hello_request_len = 0; + + ssl_do_msg_callback(ssl, 0 /* read */, ssl->version, SSL3_RT_HANDSHAKE, + kHelloRequest, sizeof(kHelloRequest)); + + if (ssl->renegotiate_mode == ssl_renegotiate_ignore) { + goto start; + } + + /* Renegotiation is only supported at quiescent points in the application + * protocol, namely in HTTPS, just before reading the HTTP response. Require + * the record-layer be idle and avoid complexities of sending a handshake + * record while an application_data record is being written. */ + if (ssl_write_buffer_is_pending(ssl)) { + al = SSL_AD_NO_RENEGOTIATION; + OPENSSL_PUT_ERROR(SSL, SSL_R_NO_RENEGOTIATION); + goto f_err; + } + + /* Begin a new handshake. */ + ssl->s3->total_renegotiations++; + ssl->state = SSL_ST_CONNECT; + i = ssl->handshake_func(ssl); + if (i < 0) { + return i; + } + if (i == 0) { + OPENSSL_PUT_ERROR(SSL, SSL_R_SSL_HANDSHAKE_FAILURE); + return -1; + } + + /* The handshake completed synchronously. Continue reading records. */ + goto start; + } + + al = SSL_AD_UNEXPECTED_MESSAGE; + OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD); + +f_err: + ssl3_send_alert(ssl, SSL3_AL_FATAL, al); + return -1; +} + +int ssl3_send_alert(SSL *ssl, int level, int desc) { + /* It is illegal to send an alert when we've already sent a closing one. */ + if (ssl->s3->send_shutdown != ssl_shutdown_none) { + OPENSSL_PUT_ERROR(SSL, SSL_R_PROTOCOL_IS_SHUTDOWN); + return -1; + } + + if (level == SSL3_AL_FATAL) { + if (ssl->session != NULL) { + SSL_CTX_remove_session(ssl->ctx, ssl->session); + } + ssl->s3->send_shutdown = ssl_shutdown_fatal_alert; + } else if (level == SSL3_AL_WARNING && desc == SSL_AD_CLOSE_NOTIFY) { + ssl->s3->send_shutdown = ssl_shutdown_close_notify; + } + + ssl->s3->alert_dispatch = 1; + ssl->s3->send_alert[0] = level; + ssl->s3->send_alert[1] = desc; + if (!ssl_write_buffer_is_pending(ssl)) { + /* Nothing is being written out, so the alert may be dispatched + * immediately. */ + return ssl->method->ssl_dispatch_alert(ssl); + } + + /* The alert will be dispatched later. */ + return -1; +} + +int ssl3_dispatch_alert(SSL *ssl) { + ssl->s3->alert_dispatch = 0; + int ret = do_ssl3_write(ssl, SSL3_RT_ALERT, &ssl->s3->send_alert[0], 2); + if (ret <= 0) { + ssl->s3->alert_dispatch = 1; + return ret; + } + + /* If the alert is fatal, flush the BIO now. */ + if (ssl->s3->send_alert[0] == SSL3_AL_FATAL) { + BIO_flush(ssl->wbio); + } + + ssl_do_msg_callback(ssl, 1 /* write */, ssl->version, SSL3_RT_ALERT, + ssl->s3->send_alert, 2); + + int alert = (ssl->s3->send_alert[0] << 8) | ssl->s3->send_alert[1]; + ssl_do_info_callback(ssl, SSL_CB_WRITE_ALERT, alert); + + return 1; +} diff --git a/external/boringssl/ssl/ssl_aead_ctx.c b/external/boringssl/ssl/ssl_aead_ctx.c new file mode 100644 index 0000000000..e5bfe86ab9 --- /dev/null +++ b/external/boringssl/ssl/ssl_aead_ctx.c @@ -0,0 +1,331 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include +#include + +#include +#include +#include +#include + +#include "internal.h" + + +OPENSSL_COMPILE_ASSERT(EVP_AEAD_MAX_NONCE_LENGTH < 256, + variable_nonce_len_doesnt_fit_in_uint8_t); + +SSL_AEAD_CTX *SSL_AEAD_CTX_new(enum evp_aead_direction_t direction, + uint16_t version, const SSL_CIPHER *cipher, + const uint8_t *enc_key, size_t enc_key_len, + const uint8_t *mac_key, size_t mac_key_len, + const uint8_t *fixed_iv, size_t fixed_iv_len) { + const EVP_AEAD *aead; + size_t discard; + if (!ssl_cipher_get_evp_aead(&aead, &discard, &discard, cipher, version)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + return 0; + } + + uint8_t merged_key[EVP_AEAD_MAX_KEY_LENGTH]; + if (mac_key_len > 0) { + /* This is a "stateful" AEAD (for compatibility with pre-AEAD cipher + * suites). */ + if (mac_key_len + enc_key_len + fixed_iv_len > sizeof(merged_key)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + return 0; + } + memcpy(merged_key, mac_key, mac_key_len); + memcpy(merged_key + mac_key_len, enc_key, enc_key_len); + memcpy(merged_key + mac_key_len + enc_key_len, fixed_iv, fixed_iv_len); + enc_key = merged_key; + enc_key_len += mac_key_len; + enc_key_len += fixed_iv_len; + } + + SSL_AEAD_CTX *aead_ctx = OPENSSL_malloc(sizeof(SSL_AEAD_CTX)); + if (aead_ctx == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + return NULL; + } + memset(aead_ctx, 0, sizeof(SSL_AEAD_CTX)); + aead_ctx->cipher = cipher; + + if (!EVP_AEAD_CTX_init_with_direction( + &aead_ctx->ctx, aead, enc_key, enc_key_len, + EVP_AEAD_DEFAULT_TAG_LENGTH, direction)) { + OPENSSL_free(aead_ctx); + return NULL; + } + + assert(EVP_AEAD_nonce_length(aead) <= EVP_AEAD_MAX_NONCE_LENGTH); + aead_ctx->variable_nonce_len = (uint8_t)EVP_AEAD_nonce_length(aead); + if (mac_key_len == 0) { + assert(fixed_iv_len <= sizeof(aead_ctx->fixed_nonce)); + memcpy(aead_ctx->fixed_nonce, fixed_iv, fixed_iv_len); + aead_ctx->fixed_nonce_len = fixed_iv_len; + + if (cipher->algorithm_enc & SSL_CHACHA20POLY1305) { + /* The fixed nonce into the actual nonce (the sequence number). */ + aead_ctx->xor_fixed_nonce = 1; + aead_ctx->variable_nonce_len = 8; + } else { + /* The fixed IV is prepended to the nonce. */ + assert(fixed_iv_len <= aead_ctx->variable_nonce_len); + aead_ctx->variable_nonce_len -= fixed_iv_len; + } + + /* AES-GCM uses an explicit nonce. */ + if (cipher->algorithm_enc & (SSL_AES128GCM | SSL_AES256GCM)) { + aead_ctx->variable_nonce_included_in_record = 1; + } + + /* The TLS 1.3 construction XORs the fixed nonce into the sequence number + * and omits the additional data. */ + if (version >= TLS1_3_VERSION) { + aead_ctx->xor_fixed_nonce = 1; + aead_ctx->variable_nonce_len = 8; + aead_ctx->variable_nonce_included_in_record = 0; + aead_ctx->omit_ad = 1; + assert(fixed_iv_len >= aead_ctx->variable_nonce_len); + } + } else { + assert(version < TLS1_3_VERSION); + aead_ctx->variable_nonce_included_in_record = 1; + aead_ctx->random_variable_nonce = 1; + aead_ctx->omit_length_in_ad = 1; + aead_ctx->omit_version_in_ad = (version == SSL3_VERSION); + } + + return aead_ctx; +} + +void SSL_AEAD_CTX_free(SSL_AEAD_CTX *aead) { + if (aead == NULL) { + return; + } + EVP_AEAD_CTX_cleanup(&aead->ctx); + OPENSSL_free(aead); +} + +size_t SSL_AEAD_CTX_explicit_nonce_len(SSL_AEAD_CTX *aead) { +#if defined(BORINGSSL_UNSAFE_FUZZER_MODE) + aead = NULL; +#endif + + if (aead != NULL && aead->variable_nonce_included_in_record) { + return aead->variable_nonce_len; + } + return 0; +} + +size_t SSL_AEAD_CTX_max_overhead(SSL_AEAD_CTX *aead) { +#if defined(BORINGSSL_UNSAFE_FUZZER_MODE) + aead = NULL; +#endif + + if (aead == NULL) { + return 0; + } + return EVP_AEAD_max_overhead(aead->ctx.aead) + + SSL_AEAD_CTX_explicit_nonce_len(aead); +} + +/* ssl_aead_ctx_get_ad writes the additional data for |aead| into |out| and + * returns the number of bytes written. */ +static size_t ssl_aead_ctx_get_ad(SSL_AEAD_CTX *aead, uint8_t out[13], + uint8_t type, uint16_t wire_version, + const uint8_t seqnum[8], + size_t plaintext_len) { + if (aead->omit_ad) { + return 0; + } + + memcpy(out, seqnum, 8); + size_t len = 8; + out[len++] = type; + if (!aead->omit_version_in_ad) { + out[len++] = (uint8_t)(wire_version >> 8); + out[len++] = (uint8_t)wire_version; + } + if (!aead->omit_length_in_ad) { + out[len++] = (uint8_t)(plaintext_len >> 8); + out[len++] = (uint8_t)plaintext_len; + } + return len; +} + +int SSL_AEAD_CTX_open(SSL_AEAD_CTX *aead, CBS *out, uint8_t type, + uint16_t wire_version, const uint8_t seqnum[8], + uint8_t *in, size_t in_len) { +#if defined(BORINGSSL_UNSAFE_FUZZER_MODE) + aead = NULL; +#endif + + if (aead == NULL) { + /* Handle the initial NULL cipher. */ + CBS_init(out, in, in_len); + return 1; + } + + /* TLS 1.2 AEADs include the length in the AD and are assumed to have fixed + * overhead. Otherwise the parameter is unused. */ + size_t plaintext_len = 0; + if (!aead->omit_length_in_ad) { + size_t overhead = SSL_AEAD_CTX_max_overhead(aead); + if (in_len < overhead) { + /* Publicly invalid. */ + OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_PACKET_LENGTH); + return 0; + } + plaintext_len = in_len - overhead; + } + uint8_t ad[13]; + size_t ad_len = ssl_aead_ctx_get_ad(aead, ad, type, wire_version, seqnum, + plaintext_len); + + /* Assemble the nonce. */ + uint8_t nonce[EVP_AEAD_MAX_NONCE_LENGTH]; + size_t nonce_len = 0; + + /* Prepend the fixed nonce, or left-pad with zeros if XORing. */ + if (aead->xor_fixed_nonce) { + nonce_len = aead->fixed_nonce_len - aead->variable_nonce_len; + memset(nonce, 0, nonce_len); + } else { + memcpy(nonce, aead->fixed_nonce, aead->fixed_nonce_len); + nonce_len += aead->fixed_nonce_len; + } + + /* Add the variable nonce. */ + if (aead->variable_nonce_included_in_record) { + if (in_len < aead->variable_nonce_len) { + /* Publicly invalid. */ + OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_PACKET_LENGTH); + return 0; + } + memcpy(nonce + nonce_len, in, aead->variable_nonce_len); + in += aead->variable_nonce_len; + in_len -= aead->variable_nonce_len; + } else { + assert(aead->variable_nonce_len == 8); + memcpy(nonce + nonce_len, seqnum, aead->variable_nonce_len); + } + nonce_len += aead->variable_nonce_len; + + /* XOR the fixed nonce, if necessary. */ + if (aead->xor_fixed_nonce) { + assert(nonce_len == aead->fixed_nonce_len); + size_t i; + for (i = 0; i < aead->fixed_nonce_len; i++) { + nonce[i] ^= aead->fixed_nonce[i]; + } + } + + /* Decrypt in-place. */ + size_t len; + if (!EVP_AEAD_CTX_open(&aead->ctx, in, &len, in_len, nonce, nonce_len, + in, in_len, ad, ad_len)) { + return 0; + } + CBS_init(out, in, len); + return 1; +} + +int SSL_AEAD_CTX_seal(SSL_AEAD_CTX *aead, uint8_t *out, size_t *out_len, + size_t max_out, uint8_t type, uint16_t wire_version, + const uint8_t seqnum[8], const uint8_t *in, + size_t in_len) { +#if defined(BORINGSSL_UNSAFE_FUZZER_MODE) + aead = NULL; +#endif + + if (aead == NULL) { + /* Handle the initial NULL cipher. */ + if (in_len > max_out) { + OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFER_TOO_SMALL); + return 0; + } + memmove(out, in, in_len); + *out_len = in_len; + return 1; + } + + uint8_t ad[13]; + size_t ad_len = ssl_aead_ctx_get_ad(aead, ad, type, wire_version, seqnum, + in_len); + + /* Assemble the nonce. */ + uint8_t nonce[EVP_AEAD_MAX_NONCE_LENGTH]; + size_t nonce_len = 0; + + /* Prepend the fixed nonce, or left-pad with zeros if XORing. */ + if (aead->xor_fixed_nonce) { + nonce_len = aead->fixed_nonce_len - aead->variable_nonce_len; + memset(nonce, 0, nonce_len); + } else { + memcpy(nonce, aead->fixed_nonce, aead->fixed_nonce_len); + nonce_len += aead->fixed_nonce_len; + } + + /* Select the variable nonce. */ + if (aead->random_variable_nonce) { + assert(aead->variable_nonce_included_in_record); + if (!RAND_bytes(nonce + nonce_len, aead->variable_nonce_len)) { + return 0; + } + } else { + /* When sending we use the sequence number as the variable part of the + * nonce. */ + assert(aead->variable_nonce_len == 8); + memcpy(nonce + nonce_len, seqnum, aead->variable_nonce_len); + } + nonce_len += aead->variable_nonce_len; + + /* Emit the variable nonce if included in the record. */ + size_t extra_len = 0; + if (aead->variable_nonce_included_in_record) { + assert(!aead->xor_fixed_nonce); + if (max_out < aead->variable_nonce_len) { + OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFER_TOO_SMALL); + return 0; + } + if (out < in + in_len && in < out + aead->variable_nonce_len) { + OPENSSL_PUT_ERROR(SSL, SSL_R_OUTPUT_ALIASES_INPUT); + return 0; + } + memcpy(out, nonce + aead->fixed_nonce_len, aead->variable_nonce_len); + extra_len = aead->variable_nonce_len; + out += aead->variable_nonce_len; + max_out -= aead->variable_nonce_len; + } + + /* XOR the fixed nonce, if necessary. */ + if (aead->xor_fixed_nonce) { + assert(nonce_len == aead->fixed_nonce_len); + size_t i; + for (i = 0; i < aead->fixed_nonce_len; i++) { + nonce[i] ^= aead->fixed_nonce[i]; + } + } + + if (!EVP_AEAD_CTX_seal(&aead->ctx, out, out_len, max_out, nonce, nonce_len, + in, in_len, ad, ad_len)) { + return 0; + } + *out_len += extra_len; + return 1; +} diff --git a/external/boringssl/ssl/ssl_asn1.c b/external/boringssl/ssl/ssl_asn1.c new file mode 100644 index 0000000000..5ec33eb40c --- /dev/null +++ b/external/boringssl/ssl/ssl_asn1.c @@ -0,0 +1,718 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright 2005 Nokia. All rights reserved. + * + * The portions of the attached software ("Contribution") is developed by + * Nokia Corporation and is licensed pursuant to the OpenSSL open source + * license. + * + * The Contribution, originally written by Mika Kousa and Pasi Eronen of + * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites + * support (see RFC 4279) to OpenSSL. + * + * No patent licenses or other rights except those expressly stated in + * the OpenSSL open source license shall be deemed granted or received + * expressly, by implication, estoppel, or otherwise. + * + * No assurances are provided by Nokia that the Contribution does not + * infringe the patent or other intellectual property rights of any third + * party or that the license provides you with all the necessary rights + * to make use of the Contribution. + * + * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN + * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA + * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY + * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR + * OTHERWISE. */ + +#include + +#include +#include + +#include +#include +#include +#include + +#include "internal.h" + + +/* An SSL_SESSION is serialized as the following ASN.1 structure: + * + * SSLSession ::= SEQUENCE { + * version INTEGER (1), -- ignored + * sslVersion INTEGER, -- protocol version number + * cipher OCTET STRING, -- two bytes long + * sessionID OCTET STRING, + * masterKey OCTET STRING, + * time [1] INTEGER OPTIONAL, -- seconds since UNIX epoch + * timeout [2] INTEGER OPTIONAL, -- in seconds + * peer [3] Certificate OPTIONAL, + * sessionIDContext [4] OCTET STRING OPTIONAL, + * verifyResult [5] INTEGER OPTIONAL, -- one of X509_V_* codes + * hostName [6] OCTET STRING OPTIONAL, + * -- from server_name extension + * pskIdentity [8] OCTET STRING OPTIONAL, + * ticketLifetimeHint [9] INTEGER OPTIONAL, -- client-only + * ticket [10] OCTET STRING OPTIONAL, -- client-only + * peerSHA256 [13] OCTET STRING OPTIONAL, + * originalHandshakeHash [14] OCTET STRING OPTIONAL, + * signedCertTimestampList [15] OCTET STRING OPTIONAL, + * -- contents of SCT extension + * ocspResponse [16] OCTET STRING OPTIONAL, + * -- stapled OCSP response from the server + * extendedMasterSecret [17] BOOLEAN OPTIONAL, + * keyExchangeInfo [18] INTEGER OPTIONAL, + * certChain [19] SEQUENCE OF Certificate OPTIONAL, + * } + * + * Note: historically this serialization has included other optional + * fields. Their presense is currently treated as a parse error: + * + * keyArg [0] IMPLICIT OCTET STRING OPTIONAL, + * pskIdentityHint [7] OCTET STRING OPTIONAL, + * compressionMethod [11] OCTET STRING OPTIONAL, + * srpUsername [12] OCTET STRING OPTIONAL, */ + +static const unsigned kVersion = 1; + +static const int kTimeTag = + CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 1; +static const int kTimeoutTag = + CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 2; +static const int kPeerTag = + CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 3; +static const int kSessionIDContextTag = + CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 4; +static const int kVerifyResultTag = + CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 5; +static const int kHostNameTag = + CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 6; +static const int kPSKIdentityTag = + CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 8; +static const int kTicketLifetimeHintTag = + CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 9; +static const int kTicketTag = + CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 10; +static const int kPeerSHA256Tag = + CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 13; +static const int kOriginalHandshakeHashTag = + CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 14; +static const int kSignedCertTimestampListTag = + CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 15; +static const int kOCSPResponseTag = + CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 16; +static const int kExtendedMasterSecretTag = + CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 17; +static const int kKeyExchangeInfoTag = + CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 18; +static const int kCertChainTag = + CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 19; + +static int add_X509(CBB *cbb, X509 *x509) { + int len = i2d_X509(x509, NULL); + if (len < 0) { + return 0; + } + uint8_t *buf; + if (!CBB_add_space(cbb, &buf, len)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + return 0; + } + if (buf != NULL && i2d_X509(x509, &buf) < 0) { + return 0; + } + return 1; +} + +static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, uint8_t **out_data, + size_t *out_len, int for_ticket) { + CBB cbb, session, child, child2; + + if (in == NULL || in->cipher == NULL) { + return 0; + } + + CBB_zero(&cbb); + if (!CBB_init(&cbb, 0) || + !CBB_add_asn1(&cbb, &session, CBS_ASN1_SEQUENCE) || + !CBB_add_asn1_uint64(&session, kVersion) || + !CBB_add_asn1_uint64(&session, in->ssl_version) || + !CBB_add_asn1(&session, &child, CBS_ASN1_OCTETSTRING) || + !CBB_add_u16(&child, (uint16_t)(in->cipher->id & 0xffff)) || + !CBB_add_asn1(&session, &child, CBS_ASN1_OCTETSTRING) || + /* The session ID is irrelevant for a session ticket. */ + !CBB_add_bytes(&child, in->session_id, + for_ticket ? 0 : in->session_id_length) || + !CBB_add_asn1(&session, &child, CBS_ASN1_OCTETSTRING) || + !CBB_add_bytes(&child, in->master_key, in->master_key_length)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (in->time != 0) { + if (!CBB_add_asn1(&session, &child, kTimeTag) || + !CBB_add_asn1_uint64(&child, in->time)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + goto err; + } + } + + if (in->timeout != 0) { + if (!CBB_add_asn1(&session, &child, kTimeoutTag) || + !CBB_add_asn1_uint64(&child, in->timeout)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + goto err; + } + } + + /* The peer certificate is only serialized if the SHA-256 isn't + * serialized instead. */ + if (in->peer && !in->peer_sha256_valid) { + if (!CBB_add_asn1(&session, &child, kPeerTag)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + goto err; + } + if (!add_X509(&child, in->peer)) { + goto err; + } + } + + /* Although it is OPTIONAL and usually empty, OpenSSL has + * historically always encoded the sid_ctx. */ + if (!CBB_add_asn1(&session, &child, kSessionIDContextTag) || + !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) || + !CBB_add_bytes(&child2, in->sid_ctx, in->sid_ctx_length)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (in->verify_result != X509_V_OK) { + if (!CBB_add_asn1(&session, &child, kVerifyResultTag) || + !CBB_add_asn1_uint64(&child, in->verify_result)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + goto err; + } + } + + if (in->tlsext_hostname) { + if (!CBB_add_asn1(&session, &child, kHostNameTag) || + !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) || + !CBB_add_bytes(&child2, (const uint8_t *)in->tlsext_hostname, + strlen(in->tlsext_hostname))) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + goto err; + } + } + + if (in->psk_identity) { + if (!CBB_add_asn1(&session, &child, kPSKIdentityTag) || + !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) || + !CBB_add_bytes(&child2, (const uint8_t *)in->psk_identity, + strlen(in->psk_identity))) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + goto err; + } + } + + if (in->tlsext_tick_lifetime_hint > 0) { + if (!CBB_add_asn1(&session, &child, kTicketLifetimeHintTag) || + !CBB_add_asn1_uint64(&child, in->tlsext_tick_lifetime_hint)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + goto err; + } + } + + if (in->tlsext_tick && !for_ticket) { + if (!CBB_add_asn1(&session, &child, kTicketTag) || + !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) || + !CBB_add_bytes(&child2, in->tlsext_tick, in->tlsext_ticklen)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + goto err; + } + } + + if (in->peer_sha256_valid) { + if (!CBB_add_asn1(&session, &child, kPeerSHA256Tag) || + !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) || + !CBB_add_bytes(&child2, in->peer_sha256, sizeof(in->peer_sha256))) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + goto err; + } + } + + if (in->original_handshake_hash_len > 0) { + if (!CBB_add_asn1(&session, &child, kOriginalHandshakeHashTag) || + !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) || + !CBB_add_bytes(&child2, in->original_handshake_hash, + in->original_handshake_hash_len)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + goto err; + } + } + + if (in->tlsext_signed_cert_timestamp_list_length > 0) { + if (!CBB_add_asn1(&session, &child, kSignedCertTimestampListTag) || + !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) || + !CBB_add_bytes(&child2, in->tlsext_signed_cert_timestamp_list, + in->tlsext_signed_cert_timestamp_list_length)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + goto err; + } + } + + if (in->ocsp_response_length > 0) { + if (!CBB_add_asn1(&session, &child, kOCSPResponseTag) || + !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) || + !CBB_add_bytes(&child2, in->ocsp_response, in->ocsp_response_length)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + goto err; + } + } + + if (in->extended_master_secret) { + if (!CBB_add_asn1(&session, &child, kExtendedMasterSecretTag) || + !CBB_add_asn1(&child, &child2, CBS_ASN1_BOOLEAN) || + !CBB_add_u8(&child2, 0xff)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + goto err; + } + } + + if (in->key_exchange_info > 0 && + (!CBB_add_asn1(&session, &child, kKeyExchangeInfoTag) || + !CBB_add_asn1_uint64(&child, in->key_exchange_info))) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + goto err; + } + + /* The certificate chain is only serialized if the leaf's SHA-256 isn't + * serialized instead. */ + if (in->cert_chain != NULL && !in->peer_sha256_valid) { + if (!CBB_add_asn1(&session, &child, kCertChainTag)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + goto err; + } + size_t i; + for (i = 0; i < sk_X509_num(in->cert_chain); i++) { + if (!add_X509(&child, sk_X509_value(in->cert_chain, i))) { + goto err; + } + } + } + + if (!CBB_finish(&cbb, out_data, out_len)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + goto err; + } + return 1; + + err: + CBB_cleanup(&cbb); + return 0; +} + +int SSL_SESSION_to_bytes(const SSL_SESSION *in, uint8_t **out_data, + size_t *out_len) { + return SSL_SESSION_to_bytes_full(in, out_data, out_len, 0); +} + +int SSL_SESSION_to_bytes_for_ticket(const SSL_SESSION *in, uint8_t **out_data, + size_t *out_len) { + return SSL_SESSION_to_bytes_full(in, out_data, out_len, 1); +} + +int i2d_SSL_SESSION(SSL_SESSION *in, uint8_t **pp) { + uint8_t *out; + size_t len; + + if (!SSL_SESSION_to_bytes(in, &out, &len)) { + return -1; + } + + if (len > INT_MAX) { + OPENSSL_free(out); + OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW); + return -1; + } + + if (pp) { + memcpy(*pp, out, len); + *pp += len; + } + OPENSSL_free(out); + + return len; +} + +/* SSL_SESSION_parse_string gets an optional ASN.1 OCTET STRING + * explicitly tagged with |tag| from |cbs| and saves it in |*out|. On + * entry, if |*out| is not NULL, it frees the existing contents. If + * the element was not found, it sets |*out| to NULL. It returns one + * on success, whether or not the element was found, and zero on + * decode error. */ +static int SSL_SESSION_parse_string(CBS *cbs, char **out, unsigned tag) { + CBS value; + int present; + if (!CBS_get_optional_asn1_octet_string(cbs, &value, &present, tag)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); + return 0; + } + if (present) { + if (CBS_contains_zero_byte(&value)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); + return 0; + } + if (!CBS_strdup(&value, out)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + return 0; + } + } else { + OPENSSL_free(*out); + *out = NULL; + } + return 1; +} + +/* SSL_SESSION_parse_string gets an optional ASN.1 OCTET STRING + * explicitly tagged with |tag| from |cbs| and stows it in |*out_ptr| + * and |*out_len|. If |*out_ptr| is not NULL, it frees the existing + * contents. On entry, if the element was not found, it sets + * |*out_ptr| to NULL. It returns one on success, whether or not the + * element was found, and zero on decode error. */ +static int SSL_SESSION_parse_octet_string(CBS *cbs, uint8_t **out_ptr, + size_t *out_len, unsigned tag) { + CBS value; + if (!CBS_get_optional_asn1_octet_string(cbs, &value, NULL, tag)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); + return 0; + } + if (!CBS_stow(&value, out_ptr, out_len)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + return 0; + } + return 1; +} + +/* SSL_SESSION_parse_bounded_octet_string parses an optional ASN.1 OCTET STRING + * explicitly tagged with |tag| of size at most |max_out|. */ +static int SSL_SESSION_parse_bounded_octet_string( + CBS *cbs, uint8_t *out, unsigned *out_len, unsigned max_out, unsigned tag) { + CBS value; + if (!CBS_get_optional_asn1_octet_string(cbs, &value, NULL, tag) || + CBS_len(&value) > max_out) { + OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); + return 0; + } + memcpy(out, CBS_data(&value), CBS_len(&value)); + *out_len = (unsigned)CBS_len(&value); + return 1; +} + +static int SSL_SESSION_parse_long(CBS *cbs, long *out, unsigned tag, + long default_value) { + uint64_t value; + if (!CBS_get_optional_asn1_uint64(cbs, &value, tag, + (uint64_t)default_value) || + value > LONG_MAX) { + OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); + return 0; + } + *out = (long)value; + return 1; +} + +static int SSL_SESSION_parse_u32(CBS *cbs, uint32_t *out, unsigned tag, + uint32_t default_value) { + uint64_t value; + if (!CBS_get_optional_asn1_uint64(cbs, &value, tag, + (uint64_t)default_value) || + value > 0xffffffff) { + OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); + return 0; + } + *out = (uint32_t)value; + return 1; +} + +static X509 *parse_x509(CBS *cbs) { + if (CBS_len(cbs) > LONG_MAX) { + OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); + return NULL; + } + const uint8_t *ptr = CBS_data(cbs); + X509 *ret = d2i_X509(NULL, &ptr, (long)CBS_len(cbs)); + if (ret == NULL) { + return NULL; + } + CBS_skip(cbs, ptr - CBS_data(cbs)); + return ret; +} + +static SSL_SESSION *SSL_SESSION_parse(CBS *cbs) { + SSL_SESSION *ret = SSL_SESSION_new(); + if (ret == NULL) { + goto err; + } + + CBS session; + uint64_t version, ssl_version; + if (!CBS_get_asn1(cbs, &session, CBS_ASN1_SEQUENCE) || + !CBS_get_asn1_uint64(&session, &version) || + version != kVersion || + !CBS_get_asn1_uint64(&session, &ssl_version)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); + goto err; + } + /* Only support SSLv3/TLS and DTLS. */ + if ((ssl_version >> 8) != SSL3_VERSION_MAJOR && + (ssl_version >> 8) != (DTLS1_VERSION >> 8)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_SSL_VERSION); + goto err; + } + ret->ssl_version = ssl_version; + + CBS cipher; + uint16_t cipher_value; + if (!CBS_get_asn1(&session, &cipher, CBS_ASN1_OCTETSTRING) || + !CBS_get_u16(&cipher, &cipher_value) || + CBS_len(&cipher) != 0) { + OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); + goto err; + } + ret->cipher = SSL_get_cipher_by_value(cipher_value); + if (ret->cipher == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_CIPHER); + goto err; + } + + CBS session_id, master_key; + if (!CBS_get_asn1(&session, &session_id, CBS_ASN1_OCTETSTRING) || + CBS_len(&session_id) > SSL3_MAX_SSL_SESSION_ID_LENGTH || + !CBS_get_asn1(&session, &master_key, CBS_ASN1_OCTETSTRING) || + CBS_len(&master_key) > SSL_MAX_MASTER_KEY_LENGTH) { + OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); + goto err; + } + memcpy(ret->session_id, CBS_data(&session_id), CBS_len(&session_id)); + ret->session_id_length = CBS_len(&session_id); + memcpy(ret->master_key, CBS_data(&master_key), CBS_len(&master_key)); + ret->master_key_length = CBS_len(&master_key); + + if (!SSL_SESSION_parse_long(&session, &ret->time, kTimeTag, time(NULL)) || + !SSL_SESSION_parse_long(&session, &ret->timeout, kTimeoutTag, 3)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); + goto err; + } + + CBS peer; + int has_peer; + if (!CBS_get_optional_asn1(&session, &peer, &has_peer, kPeerTag)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); + goto err; + } + X509_free(ret->peer); + ret->peer = NULL; + if (has_peer) { + ret->peer = parse_x509(&peer); + if (ret->peer == NULL) { + goto err; + } + if (CBS_len(&peer) != 0) { + OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); + goto err; + } + } + + if (!SSL_SESSION_parse_bounded_octet_string( + &session, ret->sid_ctx, &ret->sid_ctx_length, sizeof(ret->sid_ctx), + kSessionIDContextTag) || + !SSL_SESSION_parse_long(&session, &ret->verify_result, kVerifyResultTag, + X509_V_OK) || + !SSL_SESSION_parse_string(&session, &ret->tlsext_hostname, + kHostNameTag) || + !SSL_SESSION_parse_string(&session, &ret->psk_identity, + kPSKIdentityTag) || + !SSL_SESSION_parse_u32(&session, &ret->tlsext_tick_lifetime_hint, + kTicketLifetimeHintTag, 0) || + !SSL_SESSION_parse_octet_string(&session, &ret->tlsext_tick, + &ret->tlsext_ticklen, kTicketTag)) { + goto err; + } + + if (CBS_peek_asn1_tag(&session, kPeerSHA256Tag)) { + CBS child, peer_sha256; + if (!CBS_get_asn1(&session, &child, kPeerSHA256Tag) || + !CBS_get_asn1(&child, &peer_sha256, CBS_ASN1_OCTETSTRING) || + CBS_len(&peer_sha256) != sizeof(ret->peer_sha256) || + CBS_len(&child) != 0) { + OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); + goto err; + } + memcpy(ret->peer_sha256, CBS_data(&peer_sha256), sizeof(ret->peer_sha256)); + ret->peer_sha256_valid = 1; + } else { + ret->peer_sha256_valid = 0; + } + + if (!SSL_SESSION_parse_bounded_octet_string( + &session, ret->original_handshake_hash, + &ret->original_handshake_hash_len, + sizeof(ret->original_handshake_hash), kOriginalHandshakeHashTag) || + !SSL_SESSION_parse_octet_string( + &session, &ret->tlsext_signed_cert_timestamp_list, + &ret->tlsext_signed_cert_timestamp_list_length, + kSignedCertTimestampListTag) || + !SSL_SESSION_parse_octet_string( + &session, &ret->ocsp_response, &ret->ocsp_response_length, + kOCSPResponseTag)) { + goto err; + } + + int extended_master_secret; + if (!CBS_get_optional_asn1_bool(&session, &extended_master_secret, + kExtendedMasterSecretTag, + 0 /* default to false */)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); + goto err; + } + ret->extended_master_secret = !!extended_master_secret; + + if (!SSL_SESSION_parse_u32(&session, &ret->key_exchange_info, + kKeyExchangeInfoTag, 0)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); + goto err; + } + + CBS cert_chain; + int has_cert_chain; + if (!CBS_get_optional_asn1(&session, &cert_chain, &has_cert_chain, + kCertChainTag)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); + goto err; + } + sk_X509_pop_free(ret->cert_chain, X509_free); + ret->cert_chain = NULL; + if (has_cert_chain) { + ret->cert_chain = sk_X509_new_null(); + if (ret->cert_chain == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + goto err; + } + while (CBS_len(&cert_chain) > 0) { + X509 *x509 = parse_x509(&cert_chain); + if (x509 == NULL) { + goto err; + } + if (!sk_X509_push(ret->cert_chain, x509)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + X509_free(x509); + goto err; + } + } + } + + if (CBS_len(&session) != 0) { + OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); + goto err; + } + + return ret; + +err: + SSL_SESSION_free(ret); + return NULL; +} + +SSL_SESSION *SSL_SESSION_from_bytes(const uint8_t *in, size_t in_len) { + CBS cbs; + CBS_init(&cbs, in, in_len); + SSL_SESSION *ret = SSL_SESSION_parse(&cbs); + if (ret == NULL) { + return NULL; + } + if (CBS_len(&cbs) != 0) { + OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); + SSL_SESSION_free(ret); + return NULL; + } + return ret; +} + +SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const uint8_t **pp, long length) { + if (length < 0) { + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + return NULL; + } + + CBS cbs; + CBS_init(&cbs, *pp, length); + + SSL_SESSION *ret = SSL_SESSION_parse(&cbs); + if (ret == NULL) { + return NULL; + } + + if (a) { + SSL_SESSION_free(*a); + *a = ret; + } + *pp = CBS_data(&cbs); + return ret; +} diff --git a/external/boringssl/ssl/ssl_buffer.c b/external/boringssl/ssl/ssl_buffer.c new file mode 100644 index 0000000000..a3cf360bd7 --- /dev/null +++ b/external/boringssl/ssl/ssl_buffer.c @@ -0,0 +1,311 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "internal.h" + + +OPENSSL_COMPILE_ASSERT(0xffff <= INT_MAX, uint16_fits_in_int); + +OPENSSL_COMPILE_ASSERT((SSL3_ALIGN_PAYLOAD & (SSL3_ALIGN_PAYLOAD - 1)) == 0, + align_to_a_power_of_two); + +/* setup_buffer initializes |buf| with capacity |cap|, aligned such that data + * written after |header_len| is aligned to a |SSL3_ALIGN_PAYLOAD|-byte + * boundary. It returns one on success and zero on error. */ +static int setup_buffer(SSL3_BUFFER *buf, size_t header_len, size_t cap) { + if (buf->buf != NULL || cap > 0xffff) { + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + return 0; + } + + /* Add up to |SSL3_ALIGN_PAYLOAD| - 1 bytes of slack for alignment. */ + buf->buf = OPENSSL_malloc(cap + SSL3_ALIGN_PAYLOAD - 1); + if (buf->buf == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + return 0; + } + + /* Arrange the buffer such that the record body is aligned. */ + buf->offset = (0 - header_len - (uintptr_t)buf->buf) & + (SSL3_ALIGN_PAYLOAD - 1); + buf->len = 0; + buf->cap = cap; + return 1; +} + +static void consume_buffer(SSL3_BUFFER *buf, size_t len) { + if (len > buf->len) { + abort(); + } + buf->offset += (uint16_t)len; + buf->len -= (uint16_t)len; + buf->cap -= (uint16_t)len; +} + +static void clear_buffer(SSL3_BUFFER *buf) { + OPENSSL_free(buf->buf); + memset(buf, 0, sizeof(SSL3_BUFFER)); +} + +OPENSSL_COMPILE_ASSERT(DTLS1_RT_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH <= + 0xffff, + maximum_read_buffer_too_large); + +/* setup_read_buffer initializes the read buffer if not already initialized. It + * returns one on success and zero on failure. */ +static int setup_read_buffer(SSL *ssl) { + SSL3_BUFFER *buf = &ssl->s3->read_buffer; + + if (buf->buf != NULL) { + return 1; + } + + size_t header_len = ssl_record_prefix_len(ssl); + size_t cap = SSL3_RT_MAX_ENCRYPTED_LENGTH; + if (SSL_IS_DTLS(ssl)) { + cap += DTLS1_RT_HEADER_LENGTH; + } else { + cap += SSL3_RT_HEADER_LENGTH; + } + + return setup_buffer(buf, header_len, cap); +} + +uint8_t *ssl_read_buffer(SSL *ssl) { + return ssl->s3->read_buffer.buf + ssl->s3->read_buffer.offset; +} + +size_t ssl_read_buffer_len(const SSL *ssl) { + return ssl->s3->read_buffer.len; +} + +static int dtls_read_buffer_next_packet(SSL *ssl) { + SSL3_BUFFER *buf = &ssl->s3->read_buffer; + + if (buf->len > 0) { + /* It is an error to call |dtls_read_buffer_extend| when the read buffer is + * not empty. */ + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + return -1; + } + + /* Read a single packet from |ssl->rbio|. |buf->cap| must fit in an int. */ + int ret = BIO_read(ssl->rbio, buf->buf + buf->offset, (int)buf->cap); + if (ret <= 0) { + ssl->rwstate = SSL_READING; + return ret; + } + /* |BIO_read| was bound by |buf->cap|, so this cannot overflow. */ + buf->len = (uint16_t)ret; + return 1; +} + +static int tls_read_buffer_extend_to(SSL *ssl, size_t len) { + SSL3_BUFFER *buf = &ssl->s3->read_buffer; + + if (len > buf->cap) { + OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFER_TOO_SMALL); + return -1; + } + + /* Read until the target length is reached. */ + while (buf->len < len) { + /* The amount of data to read is bounded by |buf->cap|, which must fit in an + * int. */ + int ret = BIO_read(ssl->rbio, buf->buf + buf->offset + buf->len, + (int)(len - buf->len)); + if (ret <= 0) { + ssl->rwstate = SSL_READING; + return ret; + } + /* |BIO_read| was bound by |buf->cap - buf->len|, so this cannot + * overflow. */ + buf->len += (uint16_t)ret; + } + + return 1; +} + +int ssl_read_buffer_extend_to(SSL *ssl, size_t len) { + /* |ssl_read_buffer_extend_to| implicitly discards any consumed data. */ + ssl_read_buffer_discard(ssl); + + if (!setup_read_buffer(ssl)) { + return -1; + } + + if (ssl->rbio == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_R_BIO_NOT_SET); + return -1; + } + + int ret; + if (SSL_IS_DTLS(ssl)) { + /* |len| is ignored for a datagram transport. */ + ret = dtls_read_buffer_next_packet(ssl); + } else { + ret = tls_read_buffer_extend_to(ssl, len); + } + + if (ret <= 0) { + /* If the buffer was empty originally and remained empty after attempting to + * extend it, release the buffer until the next attempt. */ + ssl_read_buffer_discard(ssl); + } + return ret; +} + +void ssl_read_buffer_consume(SSL *ssl, size_t len) { + SSL3_BUFFER *buf = &ssl->s3->read_buffer; + + consume_buffer(buf, len); + + /* The TLS stack never reads beyond the current record, so there will never be + * unconsumed data. If read-ahead is ever reimplemented, + * |ssl_read_buffer_discard| will require a |memcpy| to shift the excess back + * to the front of the buffer, to ensure there is enough space for the next + * record. */ + assert(SSL_IS_DTLS(ssl) || len == 0 || buf->len == 0); +} + +void ssl_read_buffer_discard(SSL *ssl) { + if (ssl->s3->read_buffer.len == 0) { + ssl_read_buffer_clear(ssl); + } +} + +void ssl_read_buffer_clear(SSL *ssl) { + clear_buffer(&ssl->s3->read_buffer); +} + + +int ssl_write_buffer_is_pending(const SSL *ssl) { + return ssl->s3->write_buffer.len > 0; +} + +OPENSSL_COMPILE_ASSERT(SSL3_RT_HEADER_LENGTH * 2 + + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD * 2 + + SSL3_RT_MAX_PLAIN_LENGTH <= 0xffff, + maximum_tls_write_buffer_too_large); + +OPENSSL_COMPILE_ASSERT(DTLS1_RT_HEADER_LENGTH + + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD + + SSL3_RT_MAX_PLAIN_LENGTH <= 0xffff, + maximum_dtls_write_buffer_too_large); + +int ssl_write_buffer_init(SSL *ssl, uint8_t **out_ptr, size_t max_len) { + SSL3_BUFFER *buf = &ssl->s3->write_buffer; + + if (buf->buf != NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + return 0; + } + + size_t header_len = ssl_seal_align_prefix_len(ssl); + + /* TODO(davidben): This matches the original behavior in keeping the malloc + * size consistent. Does this matter? |cap| could just be |max_len|. */ + size_t cap = SSL3_RT_MAX_PLAIN_LENGTH + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD; + if (SSL_IS_DTLS(ssl)) { + cap += DTLS1_RT_HEADER_LENGTH; + } else { + cap += SSL3_RT_HEADER_LENGTH; + if (ssl->mode & SSL_MODE_CBC_RECORD_SPLITTING) { + cap += SSL3_RT_HEADER_LENGTH + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD; + } + } + + if (max_len > cap) { + OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFER_TOO_SMALL); + return 0; + } + + if (!setup_buffer(buf, header_len, cap)) { + return 0; + } + *out_ptr = buf->buf + buf->offset; + return 1; +} + +void ssl_write_buffer_set_len(SSL *ssl, size_t len) { + SSL3_BUFFER *buf = &ssl->s3->write_buffer; + + if (len > buf->cap) { + abort(); + } + buf->len = len; +} + +static int tls_write_buffer_flush(SSL *ssl) { + SSL3_BUFFER *buf = &ssl->s3->write_buffer; + + while (buf->len > 0) { + int ret = BIO_write(ssl->wbio, buf->buf + buf->offset, buf->len); + if (ret <= 0) { + ssl->rwstate = SSL_WRITING; + return ret; + } + consume_buffer(buf, (size_t)ret); + } + ssl_write_buffer_clear(ssl); + return 1; +} + +static int dtls_write_buffer_flush(SSL *ssl) { + SSL3_BUFFER *buf = &ssl->s3->write_buffer; + if (buf->len == 0) { + return 1; + } + + int ret = BIO_write(ssl->wbio, buf->buf + buf->offset, buf->len); + if (ret <= 0) { + ssl->rwstate = SSL_WRITING; + /* If the write failed, drop the write buffer anyway. Datagram transports + * can't write half a packet, so the caller is expected to retry from the + * top. */ + ssl_write_buffer_clear(ssl); + return ret; + } + ssl_write_buffer_clear(ssl); + return 1; +} + +int ssl_write_buffer_flush(SSL *ssl) { + if (ssl->wbio == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_R_BIO_NOT_SET); + return -1; + } + + if (SSL_IS_DTLS(ssl)) { + return dtls_write_buffer_flush(ssl); + } else { + return tls_write_buffer_flush(ssl); + } +} + +void ssl_write_buffer_clear(SSL *ssl) { + clear_buffer(&ssl->s3->write_buffer); +} diff --git a/external/boringssl/ssl/ssl_cert.c b/external/boringssl/ssl/ssl_cert.c new file mode 100644 index 0000000000..0eb0d8bfec --- /dev/null +++ b/external/boringssl/ssl/ssl_cert.c @@ -0,0 +1,584 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * ECC cipher suite support in OpenSSL originally developed by + * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../crypto/dh/internal.h" +#include "../crypto/internal.h" +#include "internal.h" + + +int SSL_get_ex_data_X509_STORE_CTX_idx(void) { + /* The ex_data index to go from |X509_STORE_CTX| to |SSL| always uses the + * reserved app_data slot. Before ex_data was introduced, app_data was used. + * Avoid breaking any software which assumes |X509_STORE_CTX_get_app_data| + * works. */ + return 0; +} + +CERT *ssl_cert_new(void) { + CERT *ret = OPENSSL_malloc(sizeof(CERT)); + if (ret == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + return NULL; + } + memset(ret, 0, sizeof(CERT)); + + return ret; +} + +CERT *ssl_cert_dup(CERT *cert) { + CERT *ret = OPENSSL_malloc(sizeof(CERT)); + if (ret == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + return NULL; + } + memset(ret, 0, sizeof(CERT)); + + ret->mask_k = cert->mask_k; + ret->mask_a = cert->mask_a; + + if (cert->dh_tmp != NULL) { + ret->dh_tmp = DHparams_dup(cert->dh_tmp); + if (ret->dh_tmp == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_DH_LIB); + goto err; + } + } + ret->dh_tmp_cb = cert->dh_tmp_cb; + + if (cert->x509 != NULL) { + ret->x509 = X509_up_ref(cert->x509); + } + + if (cert->privatekey != NULL) { + ret->privatekey = EVP_PKEY_up_ref(cert->privatekey); + } + + if (cert->chain) { + ret->chain = X509_chain_up_ref(cert->chain); + if (!ret->chain) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + goto err; + } + } + + ret->key_method = cert->key_method; + + ret->cert_cb = cert->cert_cb; + ret->cert_cb_arg = cert->cert_cb_arg; + + if (cert->verify_store != NULL) { + X509_STORE_up_ref(cert->verify_store); + ret->verify_store = cert->verify_store; + } + + return ret; + +err: + ssl_cert_free(ret); + return NULL; +} + +/* Free up and clear all certificates and chains */ +void ssl_cert_clear_certs(CERT *cert) { + if (cert == NULL) { + return; + } + + X509_free(cert->x509); + cert->x509 = NULL; + EVP_PKEY_free(cert->privatekey); + cert->privatekey = NULL; + sk_X509_pop_free(cert->chain, X509_free); + cert->chain = NULL; + cert->key_method = NULL; +} + +void ssl_cert_free(CERT *c) { + if (c == NULL) { + return; + } + + DH_free(c->dh_tmp); + + ssl_cert_clear_certs(c); + OPENSSL_free(c->peer_sigalgs); + OPENSSL_free(c->digest_nids); + X509_STORE_free(c->verify_store); + + OPENSSL_free(c); +} + +int ssl_cert_set0_chain(CERT *cert, STACK_OF(X509) *chain) { + sk_X509_pop_free(cert->chain, X509_free); + cert->chain = chain; + return 1; +} + +int ssl_cert_set1_chain(CERT *cert, STACK_OF(X509) *chain) { + STACK_OF(X509) *dchain; + if (chain == NULL) { + return ssl_cert_set0_chain(cert, NULL); + } + + dchain = X509_chain_up_ref(chain); + if (dchain == NULL) { + return 0; + } + + if (!ssl_cert_set0_chain(cert, dchain)) { + sk_X509_pop_free(dchain, X509_free); + return 0; + } + + return 1; +} + +int ssl_cert_add0_chain_cert(CERT *cert, X509 *x509) { + if (cert->chain == NULL) { + cert->chain = sk_X509_new_null(); + } + if (cert->chain == NULL || !sk_X509_push(cert->chain, x509)) { + return 0; + } + + return 1; +} + +int ssl_cert_add1_chain_cert(CERT *cert, X509 *x509) { + if (!ssl_cert_add0_chain_cert(cert, x509)) { + return 0; + } + + X509_up_ref(x509); + return 1; +} + +void ssl_cert_set_cert_cb(CERT *c, int (*cb)(SSL *ssl, void *arg), void *arg) { + c->cert_cb = cb; + c->cert_cb_arg = arg; +} + +int ssl_verify_cert_chain(SSL *ssl, STACK_OF(X509) *cert_chain) { + if (cert_chain == NULL || sk_X509_num(cert_chain) == 0) { + return 0; + } + + X509_STORE *verify_store = ssl->ctx->cert_store; + if (ssl->cert->verify_store != NULL) { + verify_store = ssl->cert->verify_store; + } + + X509 *leaf = sk_X509_value(cert_chain, 0); + int ret = 0; + X509_STORE_CTX ctx; + if (!X509_STORE_CTX_init(&ctx, verify_store, leaf, cert_chain)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_X509_LIB); + return 0; + } + if (!X509_STORE_CTX_set_ex_data(&ctx, SSL_get_ex_data_X509_STORE_CTX_idx(), + ssl)) { + goto err; + } + + /* We need to inherit the verify parameters. These can be determined by the + * context: if its a server it will verify SSL client certificates or vice + * versa. */ + X509_STORE_CTX_set_default(&ctx, ssl->server ? "ssl_client" : "ssl_server"); + + /* Anything non-default in "param" should overwrite anything in the ctx. */ + X509_VERIFY_PARAM_set1(X509_STORE_CTX_get0_param(&ctx), ssl->param); + + if (ssl->verify_callback) { + X509_STORE_CTX_set_verify_cb(&ctx, ssl->verify_callback); + } + + if (ssl->ctx->app_verify_callback != NULL) { + ret = ssl->ctx->app_verify_callback(&ctx, ssl->ctx->app_verify_arg); + } else { + ret = X509_verify_cert(&ctx); + } + + ssl->verify_result = ctx.error; + +err: + X509_STORE_CTX_cleanup(&ctx); + return ret; +} + +static void set_client_CA_list(STACK_OF(X509_NAME) **ca_list, + STACK_OF(X509_NAME) *name_list) { + sk_X509_NAME_pop_free(*ca_list, X509_NAME_free); + *ca_list = name_list; +} + +STACK_OF(X509_NAME) *SSL_dup_CA_list(STACK_OF(X509_NAME) *list) { + STACK_OF(X509_NAME) *ret = sk_X509_NAME_new_null(); + if (ret == NULL) { + return NULL; + } + + size_t i; + for (i = 0; i < sk_X509_NAME_num(list); i++) { + X509_NAME *name = X509_NAME_dup(sk_X509_NAME_value(list, i)); + if (name == NULL || !sk_X509_NAME_push(ret, name)) { + X509_NAME_free(name); + sk_X509_NAME_pop_free(ret, X509_NAME_free); + return NULL; + } + } + + return ret; +} + +void SSL_set_client_CA_list(SSL *ssl, STACK_OF(X509_NAME) *name_list) { + set_client_CA_list(&ssl->client_CA, name_list); +} + +void SSL_CTX_set_client_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list) { + set_client_CA_list(&ctx->client_CA, name_list); +} + +STACK_OF(X509_NAME) *SSL_CTX_get_client_CA_list(const SSL_CTX *ctx) { + return ctx->client_CA; +} + +STACK_OF(X509_NAME) *SSL_get_client_CA_list(const SSL *ssl) { + /* For historical reasons, this function is used both to query configuration + * state on a server as well as handshake state on a client. However, whether + * |ssl| is a client or server is not known until explicitly configured with + * |SSL_set_connect_state|. If |handshake_func| is NULL, |ssl| is in an + * indeterminate mode and |ssl->server| is unset. */ + if (ssl->handshake_func != NULL && !ssl->server) { + return ssl->s3->tmp.ca_names; + } + + if (ssl->client_CA != NULL) { + return ssl->client_CA; + } + return ssl->ctx->client_CA; +} + +static int add_client_CA(STACK_OF(X509_NAME) **sk, X509 *x509) { + X509_NAME *name; + + if (x509 == NULL) { + return 0; + } + if (*sk == NULL) { + *sk = sk_X509_NAME_new_null(); + if (*sk == NULL) { + return 0; + } + } + + name = X509_NAME_dup(X509_get_subject_name(x509)); + if (name == NULL) { + return 0; + } + + if (!sk_X509_NAME_push(*sk, name)) { + X509_NAME_free(name); + return 0; + } + + return 1; +} + +int SSL_add_client_CA(SSL *ssl, X509 *x509) { + return add_client_CA(&ssl->client_CA, x509); +} + +int SSL_CTX_add_client_CA(SSL_CTX *ctx, X509 *x509) { + return add_client_CA(&ctx->client_CA, x509); +} + +/* Add a certificate to a BUF_MEM structure */ +static int ssl_add_cert_to_buf(BUF_MEM *buf, unsigned long *l, X509 *x) { + int n; + uint8_t *p; + + n = i2d_X509(x, NULL); + if (n < 0 || !BUF_MEM_grow_clean(buf, (int)(n + (*l) + 3))) { + OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB); + return 0; + } + p = (uint8_t *)&(buf->data[*l]); + l2n3(n, p); + n = i2d_X509(x, &p); + if (n < 0) { + /* This shouldn't happen. */ + OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB); + return 0; + } + *l += n + 3; + + return 1; +} + +/* Add certificate chain to internal SSL BUF_MEM structure. */ +int ssl_add_cert_chain(SSL *ssl, unsigned long *l) { + CERT *cert = ssl->cert; + BUF_MEM *buf = ssl->init_buf; + int no_chain = 0; + size_t i; + + X509 *x = cert->x509; + STACK_OF(X509) *chain = cert->chain; + + if (x == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CERTIFICATE_SET); + return 0; + } + + if ((ssl->mode & SSL_MODE_NO_AUTO_CHAIN) || chain != NULL) { + no_chain = 1; + } + + if (no_chain) { + if (!ssl_add_cert_to_buf(buf, l, x)) { + return 0; + } + + for (i = 0; i < sk_X509_num(chain); i++) { + x = sk_X509_value(chain, i); + if (!ssl_add_cert_to_buf(buf, l, x)) { + return 0; + } + } + } else { + X509_STORE_CTX xs_ctx; + + if (!X509_STORE_CTX_init(&xs_ctx, ssl->ctx->cert_store, x, NULL)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_X509_LIB); + return 0; + } + X509_verify_cert(&xs_ctx); + /* Don't leave errors in the queue */ + ERR_clear_error(); + for (i = 0; i < sk_X509_num(xs_ctx.chain); i++) { + x = sk_X509_value(xs_ctx.chain, i); + + if (!ssl_add_cert_to_buf(buf, l, x)) { + X509_STORE_CTX_cleanup(&xs_ctx); + return 0; + } + } + X509_STORE_CTX_cleanup(&xs_ctx); + } + + return 1; +} + +static int set_cert_store(X509_STORE **store_ptr, X509_STORE *new_store, int take_ref) { + X509_STORE_free(*store_ptr); + *store_ptr = new_store; + + if (new_store != NULL && take_ref) { + X509_STORE_up_ref(new_store); + } + + return 1; +} + +int SSL_CTX_set0_verify_cert_store(SSL_CTX *ctx, X509_STORE *store) { + return set_cert_store(&ctx->cert->verify_store, store, 0); +} + +int SSL_CTX_set1_verify_cert_store(SSL_CTX *ctx, X509_STORE *store) { + return set_cert_store(&ctx->cert->verify_store, store, 1); +} + +int SSL_set0_verify_cert_store(SSL *ssl, X509_STORE *store) { + return set_cert_store(&ssl->cert->verify_store, store, 0); +} + +int SSL_set1_verify_cert_store(SSL *ssl, X509_STORE *store) { + return set_cert_store(&ssl->cert->verify_store, store, 1); +} + +int SSL_CTX_set0_chain(SSL_CTX *ctx, STACK_OF(X509) *chain) { + return ssl_cert_set0_chain(ctx->cert, chain); +} + +int SSL_CTX_set1_chain(SSL_CTX *ctx, STACK_OF(X509) *chain) { + return ssl_cert_set1_chain(ctx->cert, chain); +} + +int SSL_set0_chain(SSL *ssl, STACK_OF(X509) *chain) { + return ssl_cert_set0_chain(ssl->cert, chain); +} + +int SSL_set1_chain(SSL *ssl, STACK_OF(X509) *chain) { + return ssl_cert_set1_chain(ssl->cert, chain); +} + +int SSL_CTX_add0_chain_cert(SSL_CTX *ctx, X509 *x509) { + return ssl_cert_add0_chain_cert(ctx->cert, x509); +} + +int SSL_CTX_add1_chain_cert(SSL_CTX *ctx, X509 *x509) { + return ssl_cert_add1_chain_cert(ctx->cert, x509); +} + +int SSL_CTX_add_extra_chain_cert(SSL_CTX *ctx, X509 *x509) { + return SSL_CTX_add0_chain_cert(ctx, x509); +} + +int SSL_add0_chain_cert(SSL *ssl, X509 *x509) { + return ssl_cert_add0_chain_cert(ssl->cert, x509); +} + +int SSL_add1_chain_cert(SSL *ssl, X509 *x509) { + return ssl_cert_add1_chain_cert(ssl->cert, x509); +} + +int SSL_CTX_clear_chain_certs(SSL_CTX *ctx) { + return SSL_CTX_set0_chain(ctx, NULL); +} + +int SSL_CTX_clear_extra_chain_certs(SSL_CTX *ctx) { + return SSL_CTX_clear_chain_certs(ctx); +} + +int SSL_clear_chain_certs(SSL *ssl) { + return SSL_set0_chain(ssl, NULL); +} + +int SSL_CTX_get0_chain_certs(const SSL_CTX *ctx, STACK_OF(X509) **out_chain) { + *out_chain = ctx->cert->chain; + return 1; +} + +int SSL_CTX_get_extra_chain_certs(const SSL_CTX *ctx, + STACK_OF(X509) **out_chain) { + return SSL_CTX_get0_chain_certs(ctx, out_chain); +} + +int SSL_get0_chain_certs(const SSL *ssl, STACK_OF(X509) **out_chain) { + *out_chain = ssl->cert->chain; + return 1; +} diff --git a/external/boringssl/ssl/ssl_cipher.c b/external/boringssl/ssl/ssl_cipher.c new file mode 100644 index 0000000000..1aad8c485f --- /dev/null +++ b/external/boringssl/ssl/ssl_cipher.c @@ -0,0 +1,2115 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * ECC cipher suite support in OpenSSL originally developed by + * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. + */ +/* ==================================================================== + * Copyright 2005 Nokia. All rights reserved. + * + * The portions of the attached software ("Contribution") is developed by + * Nokia Corporation and is licensed pursuant to the OpenSSL open source + * license. + * + * The Contribution, originally written by Mika Kousa and Pasi Eronen of + * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites + * support (see RFC 4279) to OpenSSL. + * + * No patent licenses or other rights except those expressly stated in + * the OpenSSL open source license shall be deemed granted or received + * expressly, by implication, estoppel, or otherwise. + * + * No assurances are provided by Nokia that the Contribution does not + * infringe the patent or other intellectual property rights of any third + * party or that the license provides you with all the necessary rights + * to make use of the Contribution. + * + * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN + * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA + * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY + * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR + * OTHERWISE. */ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "internal.h" + + +/* kCiphers is an array of all supported ciphers, sorted by id. */ +static const SSL_CIPHER kCiphers[] = { + /* The RSA ciphers */ + /* Cipher 02 */ + { + SSL3_TXT_RSA_NULL_SHA, + SSL3_CK_RSA_NULL_SHA, + SSL_kRSA, + SSL_aRSA, + SSL_eNULL, + SSL_SHA1, + SSL_HANDSHAKE_MAC_DEFAULT, + }, + + /* Cipher 04 */ + { + SSL3_TXT_RSA_RC4_128_MD5, + SSL3_CK_RSA_RC4_128_MD5, + SSL_kRSA, + SSL_aRSA, + SSL_RC4, + SSL_MD5, + SSL_HANDSHAKE_MAC_DEFAULT, + }, + + /* Cipher 05 */ + { + SSL3_TXT_RSA_RC4_128_SHA, + SSL3_CK_RSA_RC4_128_SHA, + SSL_kRSA, + SSL_aRSA, + SSL_RC4, + SSL_SHA1, + SSL_HANDSHAKE_MAC_DEFAULT, + }, + + /* Cipher 0A */ + { + SSL3_TXT_RSA_DES_192_CBC3_SHA, + SSL3_CK_RSA_DES_192_CBC3_SHA, + SSL_kRSA, + SSL_aRSA, + SSL_3DES, + SSL_SHA1, + SSL_HANDSHAKE_MAC_DEFAULT, + }, + + + /* New AES ciphersuites */ + + /* Cipher 2F */ + { + TLS1_TXT_RSA_WITH_AES_128_SHA, + TLS1_CK_RSA_WITH_AES_128_SHA, + SSL_kRSA, + SSL_aRSA, + SSL_AES128, + SSL_SHA1, + SSL_HANDSHAKE_MAC_DEFAULT, + }, + + /* Cipher 33 */ + { + TLS1_TXT_DHE_RSA_WITH_AES_128_SHA, + TLS1_CK_DHE_RSA_WITH_AES_128_SHA, + SSL_kDHE, + SSL_aRSA, + SSL_AES128, + SSL_SHA1, + SSL_HANDSHAKE_MAC_DEFAULT, + }, + + /* Cipher 35 */ + { + TLS1_TXT_RSA_WITH_AES_256_SHA, + TLS1_CK_RSA_WITH_AES_256_SHA, + SSL_kRSA, + SSL_aRSA, + SSL_AES256, + SSL_SHA1, + SSL_HANDSHAKE_MAC_DEFAULT, + }, + + /* Cipher 39 */ + { + TLS1_TXT_DHE_RSA_WITH_AES_256_SHA, + TLS1_CK_DHE_RSA_WITH_AES_256_SHA, + SSL_kDHE, + SSL_aRSA, + SSL_AES256, + SSL_SHA1, + SSL_HANDSHAKE_MAC_DEFAULT, + }, + + + /* TLS v1.2 ciphersuites */ + + /* Cipher 3C */ + { + TLS1_TXT_RSA_WITH_AES_128_SHA256, + TLS1_CK_RSA_WITH_AES_128_SHA256, + SSL_kRSA, + SSL_aRSA, + SSL_AES128, + SSL_SHA256, + SSL_HANDSHAKE_MAC_SHA256, + }, + + /* Cipher 3D */ + { + TLS1_TXT_RSA_WITH_AES_256_SHA256, + TLS1_CK_RSA_WITH_AES_256_SHA256, + SSL_kRSA, + SSL_aRSA, + SSL_AES256, + SSL_SHA256, + SSL_HANDSHAKE_MAC_SHA256, + }, + + /* Cipher 67 */ + { + TLS1_TXT_DHE_RSA_WITH_AES_128_SHA256, + TLS1_CK_DHE_RSA_WITH_AES_128_SHA256, + SSL_kDHE, + SSL_aRSA, + SSL_AES128, + SSL_SHA256, + SSL_HANDSHAKE_MAC_SHA256, + }, + + /* Cipher 6B */ + { + TLS1_TXT_DHE_RSA_WITH_AES_256_SHA256, + TLS1_CK_DHE_RSA_WITH_AES_256_SHA256, + SSL_kDHE, + SSL_aRSA, + SSL_AES256, + SSL_SHA256, + SSL_HANDSHAKE_MAC_SHA256, + }, + + /* PSK cipher suites. */ + + /* Cipher 8A */ + { + TLS1_TXT_PSK_WITH_RC4_128_SHA, + TLS1_CK_PSK_WITH_RC4_128_SHA, + SSL_kPSK, + SSL_aPSK, + SSL_RC4, + SSL_SHA1, + SSL_HANDSHAKE_MAC_DEFAULT, + }, + + /* Cipher 8C */ + { + TLS1_TXT_PSK_WITH_AES_128_CBC_SHA, + TLS1_CK_PSK_WITH_AES_128_CBC_SHA, + SSL_kPSK, + SSL_aPSK, + SSL_AES128, + SSL_SHA1, + SSL_HANDSHAKE_MAC_DEFAULT, + }, + + /* Cipher 8D */ + { + TLS1_TXT_PSK_WITH_AES_256_CBC_SHA, + TLS1_CK_PSK_WITH_AES_256_CBC_SHA, + SSL_kPSK, + SSL_aPSK, + SSL_AES256, + SSL_SHA1, + SSL_HANDSHAKE_MAC_DEFAULT, + }, + + /* GCM ciphersuites from RFC5288 */ + + /* Cipher 9C */ + { + TLS1_TXT_RSA_WITH_AES_128_GCM_SHA256, + TLS1_CK_RSA_WITH_AES_128_GCM_SHA256, + SSL_kRSA, + SSL_aRSA, + SSL_AES128GCM, + SSL_AEAD, + SSL_HANDSHAKE_MAC_SHA256, + }, + + /* Cipher 9D */ + { + TLS1_TXT_RSA_WITH_AES_256_GCM_SHA384, + TLS1_CK_RSA_WITH_AES_256_GCM_SHA384, + SSL_kRSA, + SSL_aRSA, + SSL_AES256GCM, + SSL_AEAD, + SSL_HANDSHAKE_MAC_SHA384, + }, + + /* Cipher 9E */ + { + TLS1_TXT_DHE_RSA_WITH_AES_128_GCM_SHA256, + TLS1_CK_DHE_RSA_WITH_AES_128_GCM_SHA256, + SSL_kDHE, + SSL_aRSA, + SSL_AES128GCM, + SSL_AEAD, + SSL_HANDSHAKE_MAC_SHA256, + }, + + /* Cipher 9F */ + { + TLS1_TXT_DHE_RSA_WITH_AES_256_GCM_SHA384, + TLS1_CK_DHE_RSA_WITH_AES_256_GCM_SHA384, + SSL_kDHE, + SSL_aRSA, + SSL_AES256GCM, + SSL_AEAD, + SSL_HANDSHAKE_MAC_SHA384, + }, + + /* CECPQ1 (combined elliptic curve + post-quantum) suites. */ + + /* Cipher 16B7 */ + { + TLS1_TXT_CECPQ1_RSA_WITH_CHACHA20_POLY1305_SHA256, + TLS1_CK_CECPQ1_RSA_WITH_CHACHA20_POLY1305_SHA256, + SSL_kCECPQ1, + SSL_aRSA, + SSL_CHACHA20POLY1305, + SSL_AEAD, + SSL_HANDSHAKE_MAC_SHA256, + }, + + /* Cipher 16B8 */ + { + TLS1_TXT_CECPQ1_ECDSA_WITH_CHACHA20_POLY1305_SHA256, + TLS1_CK_CECPQ1_ECDSA_WITH_CHACHA20_POLY1305_SHA256, + SSL_kCECPQ1, + SSL_aECDSA, + SSL_CHACHA20POLY1305, + SSL_AEAD, + SSL_HANDSHAKE_MAC_SHA256, + }, + + /* Cipher 16B9 */ + { + TLS1_TXT_CECPQ1_RSA_WITH_AES_256_GCM_SHA384, + TLS1_CK_CECPQ1_RSA_WITH_AES_256_GCM_SHA384, + SSL_kCECPQ1, + SSL_aRSA, + SSL_AES256GCM, + SSL_AEAD, + SSL_HANDSHAKE_MAC_SHA384, + }, + + /* Cipher 16BA */ + { + TLS1_TXT_CECPQ1_ECDSA_WITH_AES_256_GCM_SHA384, + TLS1_CK_CECPQ1_ECDSA_WITH_AES_256_GCM_SHA384, + SSL_kCECPQ1, + SSL_aECDSA, + SSL_AES256GCM, + SSL_AEAD, + SSL_HANDSHAKE_MAC_SHA384, + }, + + /* Cipher C007 */ + { + TLS1_TXT_ECDHE_ECDSA_WITH_RC4_128_SHA, + TLS1_CK_ECDHE_ECDSA_WITH_RC4_128_SHA, + SSL_kECDHE, + SSL_aECDSA, + SSL_RC4, + SSL_SHA1, + SSL_HANDSHAKE_MAC_DEFAULT, + }, + + /* Cipher C009 */ + { + TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, + TLS1_CK_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, + SSL_kECDHE, + SSL_aECDSA, + SSL_AES128, + SSL_SHA1, + SSL_HANDSHAKE_MAC_DEFAULT, + }, + + /* Cipher C00A */ + { + TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, + TLS1_CK_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, + SSL_kECDHE, + SSL_aECDSA, + SSL_AES256, + SSL_SHA1, + SSL_HANDSHAKE_MAC_DEFAULT, + }, + + /* Cipher C011 */ + { + TLS1_TXT_ECDHE_RSA_WITH_RC4_128_SHA, + TLS1_CK_ECDHE_RSA_WITH_RC4_128_SHA, + SSL_kECDHE, + SSL_aRSA, + SSL_RC4, + SSL_SHA1, + SSL_HANDSHAKE_MAC_DEFAULT, + }, + + /* Cipher C013 */ + { + TLS1_TXT_ECDHE_RSA_WITH_AES_128_CBC_SHA, + TLS1_CK_ECDHE_RSA_WITH_AES_128_CBC_SHA, + SSL_kECDHE, + SSL_aRSA, + SSL_AES128, + SSL_SHA1, + SSL_HANDSHAKE_MAC_DEFAULT, + }, + + /* Cipher C014 */ + { + TLS1_TXT_ECDHE_RSA_WITH_AES_256_CBC_SHA, + TLS1_CK_ECDHE_RSA_WITH_AES_256_CBC_SHA, + SSL_kECDHE, + SSL_aRSA, + SSL_AES256, + SSL_SHA1, + SSL_HANDSHAKE_MAC_DEFAULT, + }, + + + /* HMAC based TLS v1.2 ciphersuites from RFC5289 */ + + /* Cipher C023 */ + { + TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_SHA256, + TLS1_CK_ECDHE_ECDSA_WITH_AES_128_SHA256, + SSL_kECDHE, + SSL_aECDSA, + SSL_AES128, + SSL_SHA256, + SSL_HANDSHAKE_MAC_SHA256, + }, + + /* Cipher C024 */ + { + TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_SHA384, + TLS1_CK_ECDHE_ECDSA_WITH_AES_256_SHA384, + SSL_kECDHE, + SSL_aECDSA, + SSL_AES256, + SSL_SHA384, + SSL_HANDSHAKE_MAC_SHA384, + }, + + /* Cipher C027 */ + { + TLS1_TXT_ECDHE_RSA_WITH_AES_128_SHA256, + TLS1_CK_ECDHE_RSA_WITH_AES_128_SHA256, + SSL_kECDHE, + SSL_aRSA, + SSL_AES128, + SSL_SHA256, + SSL_HANDSHAKE_MAC_SHA256, + }, + + /* Cipher C028 */ + { + TLS1_TXT_ECDHE_RSA_WITH_AES_256_SHA384, + TLS1_CK_ECDHE_RSA_WITH_AES_256_SHA384, + SSL_kECDHE, + SSL_aRSA, + SSL_AES256, + SSL_SHA384, + SSL_HANDSHAKE_MAC_SHA384, + }, + + + /* GCM based TLS v1.2 ciphersuites from RFC5289 */ + + /* Cipher C02B */ + { + TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + SSL_kECDHE, + SSL_aECDSA, + SSL_AES128GCM, + SSL_AEAD, + SSL_HANDSHAKE_MAC_SHA256, + }, + + /* Cipher C02C */ + { + TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + SSL_kECDHE, + SSL_aECDSA, + SSL_AES256GCM, + SSL_AEAD, + SSL_HANDSHAKE_MAC_SHA384, + }, + + /* Cipher C02F */ + { + TLS1_TXT_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + SSL_kECDHE, + SSL_aRSA, + SSL_AES128GCM, + SSL_AEAD, + SSL_HANDSHAKE_MAC_SHA256, + }, + + /* Cipher C030 */ + { + TLS1_TXT_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + SSL_kECDHE, + SSL_aRSA, + SSL_AES256GCM, + SSL_AEAD, + SSL_HANDSHAKE_MAC_SHA384, + }, + + /* ECDHE-PSK cipher suites. */ + + /* Cipher C035 */ + { + TLS1_TXT_ECDHE_PSK_WITH_AES_128_CBC_SHA, + TLS1_CK_ECDHE_PSK_WITH_AES_128_CBC_SHA, + SSL_kECDHE, + SSL_aPSK, + SSL_AES128, + SSL_SHA1, + SSL_HANDSHAKE_MAC_DEFAULT, + }, + + /* Cipher C036 */ + { + TLS1_TXT_ECDHE_PSK_WITH_AES_256_CBC_SHA, + TLS1_CK_ECDHE_PSK_WITH_AES_256_CBC_SHA, + SSL_kECDHE, + SSL_aPSK, + SSL_AES256, + SSL_SHA1, + SSL_HANDSHAKE_MAC_DEFAULT, + }, + + /* ChaCha20-Poly1305 cipher suites. */ + +#if !defined(BORINGSSL_ANDROID_SYSTEM) + { + TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305_OLD, + TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD, + SSL_kECDHE, + SSL_aRSA, + SSL_CHACHA20POLY1305_OLD, + SSL_AEAD, + SSL_HANDSHAKE_MAC_SHA256, + }, + + { + TLS1_TXT_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_OLD, + TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD, + SSL_kECDHE, + SSL_aECDSA, + SSL_CHACHA20POLY1305_OLD, + SSL_AEAD, + SSL_HANDSHAKE_MAC_SHA256, + }, +#endif + + /* Cipher CCA8 */ + { + TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + SSL_kECDHE, + SSL_aRSA, + SSL_CHACHA20POLY1305, + SSL_AEAD, + SSL_HANDSHAKE_MAC_SHA256, + }, + + /* Cipher CCA9 */ + { + TLS1_TXT_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, + TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, + SSL_kECDHE, + SSL_aECDSA, + SSL_CHACHA20POLY1305, + SSL_AEAD, + SSL_HANDSHAKE_MAC_SHA256, + }, + + /* Cipher CCAB */ + { + TLS1_TXT_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256, + TLS1_CK_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256, + SSL_kECDHE, + SSL_aPSK, + SSL_CHACHA20POLY1305, + SSL_AEAD, + SSL_HANDSHAKE_MAC_SHA256, + }, + + /* Cipher D001 */ + { + TLS1_TXT_ECDHE_PSK_WITH_AES_128_GCM_SHA256, + TLS1_CK_ECDHE_PSK_WITH_AES_128_GCM_SHA256, + SSL_kECDHE, + SSL_aPSK, + SSL_AES128GCM, + SSL_SHA256, + SSL_HANDSHAKE_MAC_SHA256, + }, + + /* Cipher D002 */ + { + TLS1_TXT_ECDHE_PSK_WITH_AES_256_GCM_SHA384, + TLS1_CK_ECDHE_PSK_WITH_AES_256_GCM_SHA384, + SSL_kECDHE, + SSL_aPSK, + SSL_AES256GCM, + SSL_SHA384, + SSL_HANDSHAKE_MAC_SHA384, + }, + +}; + +static const size_t kCiphersLen = sizeof(kCiphers) / sizeof(kCiphers[0]); + +#define CIPHER_ADD 1 +#define CIPHER_KILL 2 +#define CIPHER_DEL 3 +#define CIPHER_ORD 4 +#define CIPHER_SPECIAL 5 + +typedef struct cipher_order_st { + const SSL_CIPHER *cipher; + int active; + int in_group; + struct cipher_order_st *next, *prev; +} CIPHER_ORDER; + +typedef struct cipher_alias_st { + /* name is the name of the cipher alias. */ + const char *name; + + /* The following fields are bitmasks for the corresponding fields on + * |SSL_CIPHER|. A cipher matches a cipher alias iff, for each bitmask, the + * bit corresponding to the cipher's value is set to 1. If any bitmask is + * all zeroes, the alias matches nothing. Use |~0u| for the default value. */ + uint32_t algorithm_mkey; + uint32_t algorithm_auth; + uint32_t algorithm_enc; + uint32_t algorithm_mac; + + /* min_version, if non-zero, matches all ciphers which were added in that + * particular protocol version. */ + uint16_t min_version; +} CIPHER_ALIAS; + +static const CIPHER_ALIAS kCipherAliases[] = { + /* "ALL" doesn't include eNULL nor kCECPQ1. These must be explicitly + * enabled. */ + {"ALL", ~SSL_kCECPQ1, ~0u, ~SSL_eNULL, ~0u, 0}, + + /* The "COMPLEMENTOFDEFAULT" rule is omitted. It matches nothing. */ + + /* key exchange aliases + * (some of those using only a single bit here combine + * multiple key exchange algs according to the RFCs, + * e.g. kEDH combines DHE_DSS and DHE_RSA) */ + {"kRSA", SSL_kRSA, ~0u, ~0u, ~0u, 0}, + + {"kDHE", SSL_kDHE, ~0u, ~0u, ~0u, 0}, + {"kEDH", SSL_kDHE, ~0u, ~0u, ~0u, 0}, + {"DH", SSL_kDHE, ~0u, ~0u, ~0u, 0}, + + {"kECDHE", SSL_kECDHE, ~0u, ~0u, ~0u, 0}, + {"kCECPQ1", SSL_kCECPQ1, ~0u, ~0u, ~0u, 0}, + {"kEECDH", SSL_kECDHE, ~0u, ~0u, ~0u, 0}, + {"ECDH", SSL_kECDHE, ~0u, ~0u, ~0u, 0}, + + {"kPSK", SSL_kPSK, ~0u, ~0u, ~0u, 0}, + + /* server authentication aliases */ + {"aRSA", ~SSL_kCECPQ1, SSL_aRSA, ~SSL_eNULL, ~0u, 0}, + {"aECDSA", ~SSL_kCECPQ1, SSL_aECDSA, ~0u, ~0u, 0}, + {"ECDSA", ~SSL_kCECPQ1, SSL_aECDSA, ~0u, ~0u, 0}, + {"aPSK", ~0u, SSL_aPSK, ~0u, ~0u, 0}, + + /* aliases combining key exchange and server authentication */ + {"DHE", SSL_kDHE, ~0u, ~0u, ~0u, 0}, + {"EDH", SSL_kDHE, ~0u, ~0u, ~0u, 0}, + {"ECDHE", SSL_kECDHE, ~0u, ~0u, ~0u, 0}, + {"EECDH", SSL_kECDHE, ~0u, ~0u, ~0u, 0}, + {"RSA", SSL_kRSA, SSL_aRSA, ~SSL_eNULL, ~0u, 0}, + {"PSK", SSL_kPSK, SSL_aPSK, ~0u, ~0u, 0}, + + /* symmetric encryption aliases */ + {"3DES", ~0u, ~0u, SSL_3DES, ~0u, 0}, + {"RC4", ~0u, ~0u, SSL_RC4, ~0u, 0}, + {"AES128", ~0u, ~0u, SSL_AES128 | SSL_AES128GCM, ~0u, 0}, + {"AES256", ~SSL_kCECPQ1, ~0u, SSL_AES256 | SSL_AES256GCM, ~0u, 0}, + {"AES", ~SSL_kCECPQ1, ~0u, SSL_AES, ~0u, 0}, + {"AESGCM", ~SSL_kCECPQ1, ~0u, SSL_AES128GCM | SSL_AES256GCM, ~0u, 0}, + {"CHACHA20", ~SSL_kCECPQ1, ~0u, SSL_CHACHA20POLY1305 | SSL_CHACHA20POLY1305_OLD, ~0u, + 0}, + + /* MAC aliases */ + {"MD5", ~0u, ~0u, ~0u, SSL_MD5, 0}, + {"SHA1", ~0u, ~0u, ~SSL_eNULL, SSL_SHA1, 0}, + {"SHA", ~0u, ~0u, ~SSL_eNULL, SSL_SHA1, 0}, + {"SHA256", ~SSL_kCECPQ1, ~0u, ~0u, SSL_SHA256, 0}, + {"SHA384", ~SSL_kCECPQ1, ~0u, ~0u, SSL_SHA384, 0}, + + /* Legacy protocol minimum version aliases. "TLSv1" is intentionally the + * same as "SSLv3". */ + {"SSLv3", ~SSL_kCECPQ1, ~0u, ~SSL_eNULL, ~0u, SSL3_VERSION}, + {"TLSv1", ~SSL_kCECPQ1, ~0u, ~SSL_eNULL, ~0u, SSL3_VERSION}, + {"TLSv1.2", ~SSL_kCECPQ1, ~0u, ~SSL_eNULL, ~0u, TLS1_2_VERSION}, + + /* Legacy strength classes. */ + {"MEDIUM", ~0u, ~0u, SSL_RC4, ~0u, 0}, + {"HIGH", ~SSL_kCECPQ1, ~0u, ~(SSL_eNULL|SSL_RC4), ~0u, 0}, + {"FIPS", ~SSL_kCECPQ1, ~0u, ~(SSL_eNULL|SSL_RC4), ~0u, 0}, +}; + +static const size_t kCipherAliasesLen = + sizeof(kCipherAliases) / sizeof(kCipherAliases[0]); + +static int ssl_cipher_id_cmp(const void *in_a, const void *in_b) { + const SSL_CIPHER *a = in_a; + const SSL_CIPHER *b = in_b; + + if (a->id > b->id) { + return 1; + } else if (a->id < b->id) { + return -1; + } else { + return 0; + } +} + +static int ssl_cipher_ptr_id_cmp(const SSL_CIPHER **a, const SSL_CIPHER **b) { + return ssl_cipher_id_cmp(*a, *b); +} + +const SSL_CIPHER *SSL_get_cipher_by_value(uint16_t value) { + SSL_CIPHER c; + + c.id = 0x03000000L | value; + return bsearch(&c, kCiphers, kCiphersLen, sizeof(SSL_CIPHER), + ssl_cipher_id_cmp); +} + +int ssl_cipher_get_evp_aead(const EVP_AEAD **out_aead, + size_t *out_mac_secret_len, + size_t *out_fixed_iv_len, + const SSL_CIPHER *cipher, uint16_t version) { + *out_aead = NULL; + *out_mac_secret_len = 0; + *out_fixed_iv_len = 0; + + switch (cipher->algorithm_enc) { + case SSL_AES128GCM: + *out_aead = EVP_aead_aes_128_gcm(); + *out_fixed_iv_len = 4; + break; + + case SSL_AES256GCM: + *out_aead = EVP_aead_aes_256_gcm(); + *out_fixed_iv_len = 4; + break; + +#if !defined(BORINGSSL_ANDROID_SYSTEM) + case SSL_CHACHA20POLY1305_OLD: + *out_aead = EVP_aead_chacha20_poly1305_old(); + *out_fixed_iv_len = 0; + break; +#endif + + case SSL_CHACHA20POLY1305: + *out_aead = EVP_aead_chacha20_poly1305(); + *out_fixed_iv_len = 12; + break; + + case SSL_RC4: + switch (cipher->algorithm_mac) { + case SSL_MD5: + if (version == SSL3_VERSION) { + *out_aead = EVP_aead_rc4_md5_ssl3(); + } else { + *out_aead = EVP_aead_rc4_md5_tls(); + } + *out_mac_secret_len = MD5_DIGEST_LENGTH; + break; + case SSL_SHA1: + if (version == SSL3_VERSION) { + *out_aead = EVP_aead_rc4_sha1_ssl3(); + } else { + *out_aead = EVP_aead_rc4_sha1_tls(); + } + *out_mac_secret_len = SHA_DIGEST_LENGTH; + break; + default: + return 0; + } + break; + + case SSL_AES128: + switch (cipher->algorithm_mac) { + case SSL_SHA1: + if (version == SSL3_VERSION) { + *out_aead = EVP_aead_aes_128_cbc_sha1_ssl3(); + *out_fixed_iv_len = 16; + } else if (version == TLS1_VERSION) { + *out_aead = EVP_aead_aes_128_cbc_sha1_tls_implicit_iv(); + *out_fixed_iv_len = 16; + } else { + *out_aead = EVP_aead_aes_128_cbc_sha1_tls(); + } + *out_mac_secret_len = SHA_DIGEST_LENGTH; + break; + case SSL_SHA256: + *out_aead = EVP_aead_aes_128_cbc_sha256_tls(); + *out_mac_secret_len = SHA256_DIGEST_LENGTH; + break; + default: + return 0; + } + break; + + case SSL_AES256: + switch (cipher->algorithm_mac) { + case SSL_SHA1: + if (version == SSL3_VERSION) { + *out_aead = EVP_aead_aes_256_cbc_sha1_ssl3(); + *out_fixed_iv_len = 16; + } else if (version == TLS1_VERSION) { + *out_aead = EVP_aead_aes_256_cbc_sha1_tls_implicit_iv(); + *out_fixed_iv_len = 16; + } else { + *out_aead = EVP_aead_aes_256_cbc_sha1_tls(); + } + *out_mac_secret_len = SHA_DIGEST_LENGTH; + break; + case SSL_SHA256: + *out_aead = EVP_aead_aes_256_cbc_sha256_tls(); + *out_mac_secret_len = SHA256_DIGEST_LENGTH; + break; + case SSL_SHA384: + *out_aead = EVP_aead_aes_256_cbc_sha384_tls(); + *out_mac_secret_len = SHA384_DIGEST_LENGTH; + break; + default: + return 0; + } + break; + + case SSL_3DES: + switch (cipher->algorithm_mac) { + case SSL_SHA1: + if (version == SSL3_VERSION) { + *out_aead = EVP_aead_des_ede3_cbc_sha1_ssl3(); + *out_fixed_iv_len = 8; + } else if (version == TLS1_VERSION) { + *out_aead = EVP_aead_des_ede3_cbc_sha1_tls_implicit_iv(); + *out_fixed_iv_len = 8; + } else { + *out_aead = EVP_aead_des_ede3_cbc_sha1_tls(); + } + *out_mac_secret_len = SHA_DIGEST_LENGTH; + break; + default: + return 0; + } + break; + + case SSL_eNULL: + switch (cipher->algorithm_mac) { + case SSL_SHA1: + if (version == SSL3_VERSION) { + *out_aead = EVP_aead_null_sha1_ssl3(); + } else { + *out_aead = EVP_aead_null_sha1_tls(); + } + *out_mac_secret_len = SHA_DIGEST_LENGTH; + break; + default: + return 0; + } + break; + + default: + return 0; + } + + /* In TLS 1.3, the iv_len is equal to the AEAD nonce length whereas the code + * above computes the TLS 1.2 construction. + * + * TODO(davidben,svaldez): Avoid computing the wrong value and fixing it. */ + if (version >= TLS1_3_VERSION) { + *out_fixed_iv_len = EVP_AEAD_nonce_length(*out_aead); + assert(*out_fixed_iv_len >= 8); + } + return 1; +} + +const EVP_MD *ssl_get_handshake_digest(uint32_t algorithm_prf) { + switch (algorithm_prf) { + case SSL_HANDSHAKE_MAC_DEFAULT: + return EVP_sha1(); + case SSL_HANDSHAKE_MAC_SHA256: + return EVP_sha256(); + case SSL_HANDSHAKE_MAC_SHA384: + return EVP_sha384(); + default: + return NULL; + } +} + +#define ITEM_SEP(a) \ + (((a) == ':') || ((a) == ' ') || ((a) == ';') || ((a) == ',')) + +/* rule_equals returns one iff the NUL-terminated string |rule| is equal to the + * |buf_len| bytes at |buf|. */ +static int rule_equals(const char *rule, const char *buf, size_t buf_len) { + /* |strncmp| alone only checks that |buf| is a prefix of |rule|. */ + return strncmp(rule, buf, buf_len) == 0 && rule[buf_len] == '\0'; +} + +static void ll_append_tail(CIPHER_ORDER **head, CIPHER_ORDER *curr, + CIPHER_ORDER **tail) { + if (curr == *tail) { + return; + } + if (curr == *head) { + *head = curr->next; + } + if (curr->prev != NULL) { + curr->prev->next = curr->next; + } + if (curr->next != NULL) { + curr->next->prev = curr->prev; + } + (*tail)->next = curr; + curr->prev = *tail; + curr->next = NULL; + *tail = curr; +} + +static void ll_append_head(CIPHER_ORDER **head, CIPHER_ORDER *curr, + CIPHER_ORDER **tail) { + if (curr == *head) { + return; + } + if (curr == *tail) { + *tail = curr->prev; + } + if (curr->next != NULL) { + curr->next->prev = curr->prev; + } + if (curr->prev != NULL) { + curr->prev->next = curr->next; + } + (*head)->prev = curr; + curr->next = *head; + curr->prev = NULL; + *head = curr; +} + +static void ssl_cipher_collect_ciphers(const SSL_PROTOCOL_METHOD *ssl_method, + CIPHER_ORDER *co_list, + CIPHER_ORDER **head_p, + CIPHER_ORDER **tail_p) { + /* The set of ciphers is static, but some subset may be unsupported by + * |ssl_method|, so the list may be smaller. */ + size_t co_list_num = 0; + size_t i; + for (i = 0; i < kCiphersLen; i++) { + const SSL_CIPHER *cipher = &kCiphers[i]; + if (ssl_method->supports_cipher(cipher)) { + co_list[co_list_num].cipher = cipher; + co_list[co_list_num].next = NULL; + co_list[co_list_num].prev = NULL; + co_list[co_list_num].active = 0; + co_list[co_list_num].in_group = 0; + co_list_num++; + } + } + + /* Prepare linked list from list entries. */ + if (co_list_num > 0) { + co_list[0].prev = NULL; + + if (co_list_num > 1) { + co_list[0].next = &co_list[1]; + + for (i = 1; i < co_list_num - 1; i++) { + co_list[i].prev = &co_list[i - 1]; + co_list[i].next = &co_list[i + 1]; + } + + co_list[co_list_num - 1].prev = &co_list[co_list_num - 2]; + } + + co_list[co_list_num - 1].next = NULL; + + *head_p = &co_list[0]; + *tail_p = &co_list[co_list_num - 1]; + } +} + +/* ssl_cipher_apply_rule applies the rule type |rule| to ciphers matching its + * parameters in the linked list from |*head_p| to |*tail_p|. It writes the new + * head and tail of the list to |*head_p| and |*tail_p|, respectively. + * + * - If |cipher_id| is non-zero, only that cipher is selected. + * - Otherwise, if |strength_bits| is non-negative, it selects ciphers + * of that strength. + * - Otherwise, it selects ciphers that match each bitmasks in |alg_*| and + * |min_version|. */ +static void ssl_cipher_apply_rule( + uint32_t cipher_id, uint32_t alg_mkey, uint32_t alg_auth, + uint32_t alg_enc, uint32_t alg_mac, uint16_t min_version, int rule, + int strength_bits, int in_group, CIPHER_ORDER **head_p, + CIPHER_ORDER **tail_p) { + CIPHER_ORDER *head, *tail, *curr, *next, *last; + const SSL_CIPHER *cp; + int reverse = 0; + + if (cipher_id == 0 && strength_bits == -1 && min_version == 0 && + (alg_mkey == 0 || alg_auth == 0 || alg_enc == 0 || alg_mac == 0)) { + /* The rule matches nothing, so bail early. */ + return; + } + + if (rule == CIPHER_DEL) { + /* needed to maintain sorting between currently deleted ciphers */ + reverse = 1; + } + + head = *head_p; + tail = *tail_p; + + if (reverse) { + next = tail; + last = head; + } else { + next = head; + last = tail; + } + + curr = NULL; + for (;;) { + if (curr == last) { + break; + } + + curr = next; + if (curr == NULL) { + break; + } + + next = reverse ? curr->prev : curr->next; + cp = curr->cipher; + + /* Selection criteria is either a specific cipher, the value of + * |strength_bits|, or the algorithms used. */ + if (cipher_id != 0) { + if (cipher_id != cp->id) { + continue; + } + } else if (strength_bits >= 0) { + if (strength_bits != SSL_CIPHER_get_bits(cp, NULL)) { + continue; + } + } else if (!(alg_mkey & cp->algorithm_mkey) || + !(alg_auth & cp->algorithm_auth) || + !(alg_enc & cp->algorithm_enc) || + !(alg_mac & cp->algorithm_mac) || + (min_version != 0 && + SSL_CIPHER_get_min_version(cp) != min_version)) { + continue; + } + + /* add the cipher if it has not been added yet. */ + if (rule == CIPHER_ADD) { + /* reverse == 0 */ + if (!curr->active) { + ll_append_tail(&head, curr, &tail); + curr->active = 1; + curr->in_group = in_group; + } + } + + /* Move the added cipher to this location */ + else if (rule == CIPHER_ORD) { + /* reverse == 0 */ + if (curr->active) { + ll_append_tail(&head, curr, &tail); + curr->in_group = 0; + } + } else if (rule == CIPHER_DEL) { + /* reverse == 1 */ + if (curr->active) { + /* most recently deleted ciphersuites get best positions + * for any future CIPHER_ADD (note that the CIPHER_DEL loop + * works in reverse to maintain the order) */ + ll_append_head(&head, curr, &tail); + curr->active = 0; + curr->in_group = 0; + } + } else if (rule == CIPHER_KILL) { + /* reverse == 0 */ + if (head == curr) { + head = curr->next; + } else { + curr->prev->next = curr->next; + } + + if (tail == curr) { + tail = curr->prev; + } + curr->active = 0; + if (curr->next != NULL) { + curr->next->prev = curr->prev; + } + if (curr->prev != NULL) { + curr->prev->next = curr->next; + } + curr->next = NULL; + curr->prev = NULL; + } + } + + *head_p = head; + *tail_p = tail; +} + +static int ssl_cipher_strength_sort(CIPHER_ORDER **head_p, + CIPHER_ORDER **tail_p) { + int max_strength_bits, i, *number_uses; + CIPHER_ORDER *curr; + + /* This routine sorts the ciphers with descending strength. The sorting must + * keep the pre-sorted sequence, so we apply the normal sorting routine as + * '+' movement to the end of the list. */ + max_strength_bits = 0; + curr = *head_p; + while (curr != NULL) { + if (curr->active && + SSL_CIPHER_get_bits(curr->cipher, NULL) > max_strength_bits) { + max_strength_bits = SSL_CIPHER_get_bits(curr->cipher, NULL); + } + curr = curr->next; + } + + number_uses = OPENSSL_malloc((max_strength_bits + 1) * sizeof(int)); + if (!number_uses) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + return 0; + } + memset(number_uses, 0, (max_strength_bits + 1) * sizeof(int)); + + /* Now find the strength_bits values actually used. */ + curr = *head_p; + while (curr != NULL) { + if (curr->active) { + number_uses[SSL_CIPHER_get_bits(curr->cipher, NULL)]++; + } + curr = curr->next; + } + + /* Go through the list of used strength_bits values in descending order. */ + for (i = max_strength_bits; i >= 0; i--) { + if (number_uses[i] > 0) { + ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, CIPHER_ORD, i, 0, head_p, tail_p); + } + } + + OPENSSL_free(number_uses); + return 1; +} + +static int ssl_cipher_process_rulestr(const SSL_PROTOCOL_METHOD *ssl_method, + const char *rule_str, + CIPHER_ORDER **head_p, + CIPHER_ORDER **tail_p) { + uint32_t alg_mkey, alg_auth, alg_enc, alg_mac; + uint16_t min_version; + const char *l, *buf; + int multi, skip_rule, rule, retval, ok, in_group = 0, has_group = 0; + size_t j, buf_len; + uint32_t cipher_id; + char ch; + + retval = 1; + l = rule_str; + for (;;) { + ch = *l; + + if (ch == '\0') { + break; /* done */ + } + + if (in_group) { + if (ch == ']') { + if (*tail_p) { + (*tail_p)->in_group = 0; + } + in_group = 0; + l++; + continue; + } + + if (ch == '|') { + rule = CIPHER_ADD; + l++; + continue; + } else if (!(ch >= 'a' && ch <= 'z') && !(ch >= 'A' && ch <= 'Z') && + !(ch >= '0' && ch <= '9')) { + OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_OPERATOR_IN_GROUP); + retval = in_group = 0; + break; + } else { + rule = CIPHER_ADD; + } + } else if (ch == '-') { + rule = CIPHER_DEL; + l++; + } else if (ch == '+') { + rule = CIPHER_ORD; + l++; + } else if (ch == '!') { + rule = CIPHER_KILL; + l++; + } else if (ch == '@') { + rule = CIPHER_SPECIAL; + l++; + } else if (ch == '[') { + if (in_group) { + OPENSSL_PUT_ERROR(SSL, SSL_R_NESTED_GROUP); + retval = in_group = 0; + break; + } + in_group = 1; + has_group = 1; + l++; + continue; + } else { + rule = CIPHER_ADD; + } + + /* If preference groups are enabled, the only legal operator is +. + * Otherwise the in_group bits will get mixed up. */ + if (has_group && rule != CIPHER_ADD) { + OPENSSL_PUT_ERROR(SSL, SSL_R_MIXED_SPECIAL_OPERATOR_WITH_GROUPS); + retval = in_group = 0; + break; + } + + if (ITEM_SEP(ch)) { + l++; + continue; + } + + multi = 0; + cipher_id = 0; + alg_mkey = ~0u; + alg_auth = ~0u; + alg_enc = ~0u; + alg_mac = ~0u; + min_version = 0; + skip_rule = 0; + + for (;;) { + ch = *l; + buf = l; + buf_len = 0; + while (((ch >= 'A') && (ch <= 'Z')) || ((ch >= '0') && (ch <= '9')) || + ((ch >= 'a') && (ch <= 'z')) || (ch == '-') || (ch == '.')) { + ch = *(++l); + buf_len++; + } + + if (buf_len == 0) { + /* We hit something we cannot deal with, it is no command or separator + * nor alphanumeric, so we call this an error. */ + OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_COMMAND); + retval = in_group = 0; + l++; + break; + } + + if (rule == CIPHER_SPECIAL) { + break; + } + + /* Look for a matching exact cipher. These aren't allowed in multipart + * rules. */ + if (!multi && ch != '+') { + for (j = 0; j < kCiphersLen; j++) { + const SSL_CIPHER *cipher = &kCiphers[j]; + if (rule_equals(cipher->name, buf, buf_len)) { + cipher_id = cipher->id; + break; + } + } + } + if (cipher_id == 0) { + /* If not an exact cipher, look for a matching cipher alias. */ + for (j = 0; j < kCipherAliasesLen; j++) { + if (rule_equals(kCipherAliases[j].name, buf, buf_len)) { + alg_mkey &= kCipherAliases[j].algorithm_mkey; + alg_auth &= kCipherAliases[j].algorithm_auth; + alg_enc &= kCipherAliases[j].algorithm_enc; + alg_mac &= kCipherAliases[j].algorithm_mac; + + if (min_version != 0 && + min_version != kCipherAliases[j].min_version) { + skip_rule = 1; + } else { + min_version = kCipherAliases[j].min_version; + } + break; + } + } + if (j == kCipherAliasesLen) { + skip_rule = 1; + } + } + + /* Check for a multipart rule. */ + if (ch != '+') { + break; + } + l++; + multi = 1; + } + + /* If one of the CHACHA20_POLY1305 variants is selected, include the other + * as well. They have the same name to avoid requiring changes in + * configuration. Apply this transformation late so that the cipher name + * still behaves as an exact name and not an alias in multipart rules. + * + * This is temporary and will be removed when the pre-standard construction + * is removed. */ + if (cipher_id == TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD || + cipher_id == TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256) { + cipher_id = 0; + alg_mkey = SSL_kECDHE; + alg_auth = SSL_aRSA; + alg_enc = SSL_CHACHA20POLY1305|SSL_CHACHA20POLY1305_OLD; + alg_mac = SSL_AEAD; + } else if (cipher_id == TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD || + cipher_id == TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256) { + cipher_id = 0; + alg_mkey = SSL_kECDHE; + alg_auth = SSL_aECDSA; + alg_enc = SSL_CHACHA20POLY1305|SSL_CHACHA20POLY1305_OLD; + alg_mac = SSL_AEAD; + } + + /* Ok, we have the rule, now apply it. */ + if (rule == CIPHER_SPECIAL) { + /* special command */ + ok = 0; + if (buf_len == 8 && !strncmp(buf, "STRENGTH", 8)) { + ok = ssl_cipher_strength_sort(head_p, tail_p); + } else { + OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_COMMAND); + } + + if (ok == 0) { + retval = 0; + } + + /* We do not support any "multi" options together with "@", so throw away + * the rest of the command, if any left, until end or ':' is found. */ + while (*l != '\0' && !ITEM_SEP(*l)) { + l++; + } + } else if (!skip_rule) { + ssl_cipher_apply_rule(cipher_id, alg_mkey, alg_auth, alg_enc, alg_mac, + min_version, rule, -1, in_group, head_p, tail_p); + } + } + + if (in_group) { + OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_COMMAND); + retval = 0; + } + + return retval; +} + +STACK_OF(SSL_CIPHER) * +ssl_create_cipher_list(const SSL_PROTOCOL_METHOD *ssl_method, + struct ssl_cipher_preference_list_st **out_cipher_list, + STACK_OF(SSL_CIPHER) **out_cipher_list_by_id, + const char *rule_str) { + int ok; + STACK_OF(SSL_CIPHER) *cipherstack = NULL, *tmp_cipher_list = NULL; + const char *rule_p; + CIPHER_ORDER *co_list = NULL, *head = NULL, *tail = NULL, *curr; + uint8_t *in_group_flags = NULL; + unsigned int num_in_group_flags = 0; + struct ssl_cipher_preference_list_st *pref_list = NULL; + + /* Return with error if nothing to do. */ + if (rule_str == NULL || out_cipher_list == NULL) { + return NULL; + } + + /* Now we have to collect the available ciphers from the compiled in ciphers. + * We cannot get more than the number compiled in, so it is used for + * allocation. */ + co_list = OPENSSL_malloc(sizeof(CIPHER_ORDER) * kCiphersLen); + if (co_list == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + return NULL; + } + + ssl_cipher_collect_ciphers(ssl_method, co_list, &head, &tail); + + /* Now arrange all ciphers by preference: + * TODO(davidben): Compute this order once and copy it. */ + + /* Everything else being equal, prefer ECDHE_ECDSA then ECDHE_RSA over other + * key exchange mechanisms */ + + ssl_cipher_apply_rule(0, SSL_kECDHE, SSL_aECDSA, ~0u, ~0u, 0, CIPHER_ADD, -1, + 0, &head, &tail); + ssl_cipher_apply_rule(0, SSL_kECDHE, ~0u, ~0u, ~0u, 0, CIPHER_ADD, -1, 0, + &head, &tail); + ssl_cipher_apply_rule(0, SSL_kECDHE, ~0u, ~0u, ~0u, 0, CIPHER_DEL, -1, 0, + &head, &tail); + + /* Order the bulk ciphers. First the preferred AEAD ciphers. We prefer + * CHACHA20 unless there is hardware support for fast and constant-time + * AES_GCM. Of the two CHACHA20 variants, the new one is preferred over the + * old one. */ + if (EVP_has_aes_hardware()) { + ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_AES128GCM, ~0u, 0, CIPHER_ADD, -1, 0, + &head, &tail); + ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_AES256GCM, ~0u, 0, CIPHER_ADD, -1, 0, + &head, &tail); + ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_CHACHA20POLY1305, ~0u, 0, CIPHER_ADD, + -1, 0, &head, &tail); + ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_CHACHA20POLY1305_OLD, ~0u, 0, + CIPHER_ADD, -1, 0, &head, &tail); + } else { + ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_CHACHA20POLY1305, ~0u, 0, CIPHER_ADD, + -1, 0, &head, &tail); + ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_CHACHA20POLY1305_OLD, ~0u, 0, + CIPHER_ADD, -1, 0, &head, &tail); + ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_AES128GCM, ~0u, 0, CIPHER_ADD, -1, 0, + &head, &tail); + ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_AES256GCM, ~0u, 0, CIPHER_ADD, -1, 0, + &head, &tail); + } + + /* Then the legacy non-AEAD ciphers: AES_128_CBC, AES_256_CBC, + * 3DES_EDE_CBC_SHA, RC4_128_SHA, RC4_128_MD5. */ + ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_AES128, ~0u, 0, CIPHER_ADD, -1, 0, + &head, &tail); + ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_AES256, ~0u, 0, CIPHER_ADD, -1, 0, + &head, &tail); + ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_3DES, ~0u, 0, CIPHER_ADD, -1, 0, &head, + &tail); + ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_RC4, ~SSL_MD5, 0, CIPHER_ADD, -1, 0, + &head, &tail); + ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_RC4, SSL_MD5, 0, CIPHER_ADD, -1, 0, + &head, &tail); + + /* Temporarily enable everything else for sorting */ + ssl_cipher_apply_rule(0, ~0u, ~0u, ~0u, ~0u, 0, CIPHER_ADD, -1, 0, &head, + &tail); + + /* Move ciphers without forward secrecy to the end. */ + ssl_cipher_apply_rule(0, ~(SSL_kDHE | SSL_kECDHE), ~0u, ~0u, ~0u, 0, + CIPHER_ORD, -1, 0, &head, &tail); + + /* Now disable everything (maintaining the ordering!) */ + ssl_cipher_apply_rule(0, ~0u, ~0u, ~0u, ~0u, 0, CIPHER_DEL, -1, 0, &head, + &tail); + + /* If the rule_string begins with DEFAULT, apply the default rule before + * using the (possibly available) additional rules. */ + ok = 1; + rule_p = rule_str; + if (strncmp(rule_str, "DEFAULT", 7) == 0) { + ok = ssl_cipher_process_rulestr(ssl_method, SSL_DEFAULT_CIPHER_LIST, &head, + &tail); + rule_p += 7; + if (*rule_p == ':') { + rule_p++; + } + } + + if (ok && strlen(rule_p) > 0) { + ok = ssl_cipher_process_rulestr(ssl_method, rule_p, &head, &tail); + } + + if (!ok) { + goto err; + } + + /* Allocate new "cipherstack" for the result, return with error + * if we cannot get one. */ + cipherstack = sk_SSL_CIPHER_new_null(); + if (cipherstack == NULL) { + goto err; + } + + in_group_flags = OPENSSL_malloc(kCiphersLen); + if (!in_group_flags) { + goto err; + } + + /* The cipher selection for the list is done. The ciphers are added + * to the resulting precedence to the STACK_OF(SSL_CIPHER). */ + for (curr = head; curr != NULL; curr = curr->next) { + if (curr->active) { + if (!sk_SSL_CIPHER_push(cipherstack, curr->cipher)) { + goto err; + } + in_group_flags[num_in_group_flags++] = curr->in_group; + } + } + OPENSSL_free(co_list); /* Not needed any longer */ + co_list = NULL; + + tmp_cipher_list = sk_SSL_CIPHER_dup(cipherstack); + if (tmp_cipher_list == NULL) { + goto err; + } + pref_list = OPENSSL_malloc(sizeof(struct ssl_cipher_preference_list_st)); + if (!pref_list) { + goto err; + } + pref_list->ciphers = cipherstack; + pref_list->in_group_flags = OPENSSL_malloc(num_in_group_flags); + if (!pref_list->in_group_flags) { + goto err; + } + memcpy(pref_list->in_group_flags, in_group_flags, num_in_group_flags); + OPENSSL_free(in_group_flags); + in_group_flags = NULL; + if (*out_cipher_list != NULL) { + ssl_cipher_preference_list_free(*out_cipher_list); + } + *out_cipher_list = pref_list; + pref_list = NULL; + + if (out_cipher_list_by_id != NULL) { + sk_SSL_CIPHER_free(*out_cipher_list_by_id); + *out_cipher_list_by_id = tmp_cipher_list; + tmp_cipher_list = NULL; + (void) sk_SSL_CIPHER_set_cmp_func(*out_cipher_list_by_id, + ssl_cipher_ptr_id_cmp); + + sk_SSL_CIPHER_sort(*out_cipher_list_by_id); + } else { + sk_SSL_CIPHER_free(tmp_cipher_list); + tmp_cipher_list = NULL; + } + + return cipherstack; + +err: + OPENSSL_free(co_list); + OPENSSL_free(in_group_flags); + sk_SSL_CIPHER_free(cipherstack); + sk_SSL_CIPHER_free(tmp_cipher_list); + if (pref_list) { + OPENSSL_free(pref_list->in_group_flags); + } + OPENSSL_free(pref_list); + return NULL; +} + +uint32_t SSL_CIPHER_get_id(const SSL_CIPHER *cipher) { return cipher->id; } + +uint16_t ssl_cipher_get_value(const SSL_CIPHER *cipher) { + uint32_t id = cipher->id; + /* All ciphers are SSLv3. */ + assert((id & 0xff000000) == 0x03000000); + return id & 0xffff; +} + +int SSL_CIPHER_is_AES(const SSL_CIPHER *cipher) { + return (cipher->algorithm_enc & SSL_AES) != 0; +} + +int SSL_CIPHER_has_MD5_HMAC(const SSL_CIPHER *cipher) { + return (cipher->algorithm_mac & SSL_MD5) != 0; +} + +int SSL_CIPHER_has_SHA1_HMAC(const SSL_CIPHER *cipher) { + return (cipher->algorithm_mac & SSL_SHA1) != 0; +} + +int SSL_CIPHER_has_SHA256_HMAC(const SSL_CIPHER *cipher) { + return (cipher->algorithm_mac & SSL_SHA256) != 0; +} + +int SSL_CIPHER_is_AESGCM(const SSL_CIPHER *cipher) { + return (cipher->algorithm_enc & (SSL_AES128GCM | SSL_AES256GCM)) != 0; +} + +int SSL_CIPHER_is_AES128GCM(const SSL_CIPHER *cipher) { + return (cipher->algorithm_enc & SSL_AES128GCM) != 0; +} + +int SSL_CIPHER_is_AES128CBC(const SSL_CIPHER *cipher) { + return (cipher->algorithm_enc & SSL_AES128) != 0; +} + +int SSL_CIPHER_is_AES256CBC(const SSL_CIPHER *cipher) { + return (cipher->algorithm_enc & SSL_AES256) != 0; +} + +int SSL_CIPHER_is_CHACHA20POLY1305(const SSL_CIPHER *cipher) { + return (cipher->algorithm_enc & + (SSL_CHACHA20POLY1305 | SSL_CHACHA20POLY1305_OLD)) != 0; +} + +int SSL_CIPHER_is_NULL(const SSL_CIPHER *cipher) { + return (cipher->algorithm_enc & SSL_eNULL) != 0; +} + +int SSL_CIPHER_is_RC4(const SSL_CIPHER *cipher) { + return (cipher->algorithm_enc & SSL_RC4) != 0; +} + +int SSL_CIPHER_is_block_cipher(const SSL_CIPHER *cipher) { + /* Neither stream cipher nor AEAD. */ + return (cipher->algorithm_enc & (SSL_RC4 | SSL_eNULL)) == 0 && + cipher->algorithm_mac != SSL_AEAD; +} + +int SSL_CIPHER_is_ECDSA(const SSL_CIPHER *cipher) { + return (cipher->algorithm_auth & SSL_aECDSA) != 0; +} + +int SSL_CIPHER_is_DHE(const SSL_CIPHER *cipher) { + return (cipher->algorithm_mkey & SSL_kDHE) != 0; +} + +int SSL_CIPHER_is_ECDHE(const SSL_CIPHER *cipher) { + return (cipher->algorithm_mkey & SSL_kECDHE) != 0; +} + +int SSL_CIPHER_is_CECPQ1(const SSL_CIPHER *cipher) { + return (cipher->algorithm_mkey & SSL_kCECPQ1) != 0; +} + +uint16_t SSL_CIPHER_get_min_version(const SSL_CIPHER *cipher) { + if (cipher->algorithm_prf != SSL_HANDSHAKE_MAC_DEFAULT) { + /* Cipher suites before TLS 1.2 use the default PRF, while all those added + * afterwards specify a particular hash. */ + return TLS1_2_VERSION; + } + return SSL3_VERSION; +} + +/* return the actual cipher being used */ +const char *SSL_CIPHER_get_name(const SSL_CIPHER *cipher) { + if (cipher != NULL) { + return cipher->name; + } + + return "(NONE)"; +} + +const char *SSL_CIPHER_get_kx_name(const SSL_CIPHER *cipher) { + if (cipher == NULL) { + return ""; + } + + switch (cipher->algorithm_mkey) { + case SSL_kRSA: + return "RSA"; + + case SSL_kDHE: + switch (cipher->algorithm_auth) { + case SSL_aRSA: + return "DHE_RSA"; + default: + assert(0); + return "UNKNOWN"; + } + + case SSL_kECDHE: + switch (cipher->algorithm_auth) { + case SSL_aECDSA: + return "ECDHE_ECDSA"; + case SSL_aRSA: + return "ECDHE_RSA"; + case SSL_aPSK: + return "ECDHE_PSK"; + default: + assert(0); + return "UNKNOWN"; + } + + case SSL_kCECPQ1: + switch (cipher->algorithm_auth) { + case SSL_aECDSA: + return "CECPQ1_ECDSA"; + case SSL_aRSA: + return "CECPQ1_RSA"; + default: + assert(0); + return "UNKNOWN"; + } + + case SSL_kPSK: + assert(cipher->algorithm_auth == SSL_aPSK); + return "PSK"; + + default: + assert(0); + return "UNKNOWN"; + } +} + +static const char *ssl_cipher_get_enc_name(const SSL_CIPHER *cipher) { + switch (cipher->algorithm_enc) { + case SSL_3DES: + return "3DES_EDE_CBC"; + case SSL_RC4: + return "RC4"; + case SSL_AES128: + return "AES_128_CBC"; + case SSL_AES256: + return "AES_256_CBC"; + case SSL_AES128GCM: + return "AES_128_GCM"; + case SSL_AES256GCM: + return "AES_256_GCM"; + case SSL_CHACHA20POLY1305: + case SSL_CHACHA20POLY1305_OLD: + return "CHACHA20_POLY1305"; + break; + default: + assert(0); + return "UNKNOWN"; + } +} + +static const char *ssl_cipher_get_prf_name(const SSL_CIPHER *cipher) { + switch (cipher->algorithm_prf) { + case SSL_HANDSHAKE_MAC_DEFAULT: + /* Before TLS 1.2, the PRF component is the hash used in the HMAC, which is + * only ever MD5 or SHA-1. */ + switch (cipher->algorithm_mac) { + case SSL_MD5: + return "MD5"; + case SSL_SHA1: + return "SHA"; + } + break; + case SSL_HANDSHAKE_MAC_SHA256: + return "SHA256"; + case SSL_HANDSHAKE_MAC_SHA384: + return "SHA384"; + } + assert(0); + return "UNKNOWN"; +} + +char *SSL_CIPHER_get_rfc_name(const SSL_CIPHER *cipher) { + if (cipher == NULL) { + return NULL; + } + + const char *kx_name = SSL_CIPHER_get_kx_name(cipher); + const char *enc_name = ssl_cipher_get_enc_name(cipher); + const char *prf_name = ssl_cipher_get_prf_name(cipher); + + /* The final name is TLS_{kx_name}_WITH_{enc_name}_{prf_name}. */ + size_t len = 4 + strlen(kx_name) + 6 + strlen(enc_name) + 1 + + strlen(prf_name) + 1; + char *ret = OPENSSL_malloc(len); + if (ret == NULL) { + return NULL; + } + if (BUF_strlcpy(ret, "TLS_", len) >= len || + BUF_strlcat(ret, kx_name, len) >= len || + BUF_strlcat(ret, "_WITH_", len) >= len || + BUF_strlcat(ret, enc_name, len) >= len || + BUF_strlcat(ret, "_", len) >= len || + BUF_strlcat(ret, prf_name, len) >= len) { + assert(0); + OPENSSL_free(ret); + return NULL; + } + assert(strlen(ret) + 1 == len); + return ret; +} + +int SSL_CIPHER_get_bits(const SSL_CIPHER *cipher, int *out_alg_bits) { + if (cipher == NULL) { + return 0; + } + + int alg_bits, strength_bits; + switch (cipher->algorithm_enc) { + case SSL_AES128: + case SSL_AES128GCM: + case SSL_RC4: + alg_bits = 128; + strength_bits = 128; + break; + + case SSL_AES256: + case SSL_AES256GCM: +#if !defined(BORINGSSL_ANDROID_SYSTEM) + case SSL_CHACHA20POLY1305_OLD: +#endif + case SSL_CHACHA20POLY1305: + alg_bits = 256; + strength_bits = 256; + break; + + case SSL_3DES: + alg_bits = 168; + strength_bits = 112; + break; + + case SSL_eNULL: + alg_bits = 0; + strength_bits = 0; + break; + + default: + assert(0); + alg_bits = 0; + strength_bits = 0; + } + + if (out_alg_bits != NULL) { + *out_alg_bits = alg_bits; + } + return strength_bits; +} + +const char *SSL_CIPHER_description(const SSL_CIPHER *cipher, char *buf, + int len) { + const char *kx, *au, *enc, *mac; + uint32_t alg_mkey, alg_auth, alg_enc, alg_mac; + + alg_mkey = cipher->algorithm_mkey; + alg_auth = cipher->algorithm_auth; + alg_enc = cipher->algorithm_enc; + alg_mac = cipher->algorithm_mac; + + switch (alg_mkey) { + case SSL_kRSA: + kx = "RSA"; + break; + + case SSL_kDHE: + kx = "DH"; + break; + + case SSL_kECDHE: + kx = "ECDH"; + break; + + case SSL_kCECPQ1: + kx = "CECPQ1"; + break; + + case SSL_kPSK: + kx = "PSK"; + break; + + default: + kx = "unknown"; + } + + switch (alg_auth) { + case SSL_aRSA: + au = "RSA"; + break; + + case SSL_aECDSA: + au = "ECDSA"; + break; + + case SSL_aPSK: + au = "PSK"; + break; + + default: + au = "unknown"; + break; + } + + switch (alg_enc) { + case SSL_3DES: + enc = "3DES(168)"; + break; + + case SSL_RC4: + enc = "RC4(128)"; + break; + + case SSL_AES128: + enc = "AES(128)"; + break; + + case SSL_AES256: + enc = "AES(256)"; + break; + + case SSL_AES128GCM: + enc = "AESGCM(128)"; + break; + + case SSL_AES256GCM: + enc = "AESGCM(256)"; + break; + + case SSL_CHACHA20POLY1305_OLD: + enc = "ChaCha20-Poly1305-Old"; + break; + + case SSL_CHACHA20POLY1305: + enc = "ChaCha20-Poly1305"; + break; + + case SSL_eNULL: + enc="None"; + break; + + default: + enc = "unknown"; + break; + } + + switch (alg_mac) { + case SSL_MD5: + mac = "MD5"; + break; + + case SSL_SHA1: + mac = "SHA1"; + break; + + case SSL_SHA256: + mac = "SHA256"; + break; + + case SSL_SHA384: + mac = "SHA384"; + break; + + case SSL_AEAD: + mac = "AEAD"; + break; + + default: + mac = "unknown"; + break; + } + + if (buf == NULL) { + len = 128; + buf = OPENSSL_malloc(len); + if (buf == NULL) { + return NULL; + } + } else if (len < 128) { + return "Buffer too small"; + } + + BIO_snprintf(buf, len, "%-23s Kx=%-8s Au=%-4s Enc=%-9s Mac=%-4s\n", + cipher->name, kx, au, enc, mac); + return buf; +} + +const char *SSL_CIPHER_get_version(const SSL_CIPHER *cipher) { + return "TLSv1/SSLv3"; +} + +COMP_METHOD *SSL_COMP_get_compression_methods(void) { return NULL; } + +int SSL_COMP_add_compression_method(int id, COMP_METHOD *cm) { return 1; } + +const char *SSL_COMP_get_name(const COMP_METHOD *comp) { return NULL; } + +int ssl_cipher_get_key_type(const SSL_CIPHER *cipher) { + uint32_t alg_a = cipher->algorithm_auth; + + if (alg_a & SSL_aECDSA) { + return EVP_PKEY_EC; + } else if (alg_a & SSL_aRSA) { + return EVP_PKEY_RSA; + } + + return EVP_PKEY_NONE; +} + +int ssl_cipher_uses_certificate_auth(const SSL_CIPHER *cipher) { + return (cipher->algorithm_auth & SSL_aCERT) != 0; +} + +int ssl_cipher_requires_server_key_exchange(const SSL_CIPHER *cipher) { + /* Ephemeral Diffie-Hellman key exchanges require a ServerKeyExchange. */ + if (cipher->algorithm_mkey & SSL_kDHE || + cipher->algorithm_mkey & SSL_kECDHE || + cipher->algorithm_mkey & SSL_kCECPQ1) { + return 1; + } + + /* It is optional in all others. */ + return 0; +} + +size_t ssl_cipher_get_record_split_len(const SSL_CIPHER *cipher) { + size_t block_size; + switch (cipher->algorithm_enc) { + case SSL_3DES: + block_size = 8; + break; + case SSL_AES128: + case SSL_AES256: + block_size = 16; + break; + default: + return 0; + } + + size_t mac_len; + switch (cipher->algorithm_mac) { + case SSL_MD5: + mac_len = MD5_DIGEST_LENGTH; + break; + case SSL_SHA1: + mac_len = SHA_DIGEST_LENGTH; + break; + default: + return 0; + } + + size_t ret = 1 + mac_len; + ret += block_size - (ret % block_size); + return ret; +} diff --git a/external/boringssl/ssl/ssl_ecdh.c b/external/boringssl/ssl/ssl_ecdh.c new file mode 100644 index 0000000000..1236cd398b --- /dev/null +++ b/external/boringssl/ssl/ssl_ecdh.c @@ -0,0 +1,605 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "internal.h" + + +/* |EC_POINT| implementation. */ + +static void ssl_ec_point_cleanup(SSL_ECDH_CTX *ctx) { + BIGNUM *private_key = (BIGNUM *)ctx->data; + BN_clear_free(private_key); +} + +static int ssl_ec_point_offer(SSL_ECDH_CTX *ctx, CBB *out) { + assert(ctx->data == NULL); + BIGNUM *private_key = BN_new(); + if (private_key == NULL) { + return 0; + } + ctx->data = private_key; + + /* Set up a shared |BN_CTX| for all operations. */ + BN_CTX *bn_ctx = BN_CTX_new(); + if (bn_ctx == NULL) { + return 0; + } + BN_CTX_start(bn_ctx); + + int ret = 0; + EC_POINT *public_key = NULL; + EC_GROUP *group = EC_GROUP_new_by_curve_name(ctx->method->nid); + if (group == NULL) { + goto err; + } + + /* Generate a private key. */ + const BIGNUM *order = EC_GROUP_get0_order(group); + do { + if (!BN_rand_range(private_key, order)) { + goto err; + } + } while (BN_is_zero(private_key)); + + /* Compute the corresponding public key and serialize it. */ + public_key = EC_POINT_new(group); + if (public_key == NULL || + !EC_POINT_mul(group, public_key, private_key, NULL, NULL, bn_ctx) || + !EC_POINT_point2cbb(out, group, public_key, POINT_CONVERSION_UNCOMPRESSED, + bn_ctx)) { + goto err; + } + + ret = 1; + +err: + EC_GROUP_free(group); + EC_POINT_free(public_key); + BN_CTX_end(bn_ctx); + BN_CTX_free(bn_ctx); + return ret; +} + +static int ssl_ec_point_finish(SSL_ECDH_CTX *ctx, uint8_t **out_secret, + size_t *out_secret_len, uint8_t *out_alert, + const uint8_t *peer_key, size_t peer_key_len) { + BIGNUM *private_key = (BIGNUM *)ctx->data; + assert(private_key != NULL); + *out_alert = SSL_AD_INTERNAL_ERROR; + + /* Set up a shared |BN_CTX| for all operations. */ + BN_CTX *bn_ctx = BN_CTX_new(); + if (bn_ctx == NULL) { + return 0; + } + BN_CTX_start(bn_ctx); + + int ret = 0; + EC_GROUP *group = EC_GROUP_new_by_curve_name(ctx->method->nid); + EC_POINT *peer_point = NULL, *result = NULL; + uint8_t *secret = NULL; + if (group == NULL) { + goto err; + } + + /* Compute the x-coordinate of |peer_key| * |private_key|. */ + peer_point = EC_POINT_new(group); + result = EC_POINT_new(group); + if (peer_point == NULL || result == NULL) { + goto err; + } + BIGNUM *x = BN_CTX_get(bn_ctx); + if (x == NULL) { + goto err; + } + if (!EC_POINT_oct2point(group, peer_point, peer_key, peer_key_len, bn_ctx)) { + *out_alert = SSL_AD_DECODE_ERROR; + goto err; + } + if (!EC_POINT_mul(group, result, NULL, peer_point, private_key, bn_ctx) || + !EC_POINT_get_affine_coordinates_GFp(group, result, x, NULL, bn_ctx)) { + goto err; + } + + /* Encode the x-coordinate left-padded with zeros. */ + size_t secret_len = (EC_GROUP_get_degree(group) + 7) / 8; + secret = OPENSSL_malloc(secret_len); + if (secret == NULL || !BN_bn2bin_padded(secret, secret_len, x)) { + goto err; + } + + *out_secret = secret; + *out_secret_len = secret_len; + secret = NULL; + ret = 1; + +err: + EC_GROUP_free(group); + EC_POINT_free(peer_point); + EC_POINT_free(result); + BN_CTX_end(bn_ctx); + BN_CTX_free(bn_ctx); + OPENSSL_free(secret); + return ret; +} + +static int ssl_ec_point_accept(SSL_ECDH_CTX *ctx, CBB *out_public_key, + uint8_t **out_secret, size_t *out_secret_len, + uint8_t *out_alert, const uint8_t *peer_key, + size_t peer_key_len) { + *out_alert = SSL_AD_INTERNAL_ERROR; + if (!ssl_ec_point_offer(ctx, out_public_key) || + !ssl_ec_point_finish(ctx, out_secret, out_secret_len, out_alert, peer_key, + peer_key_len)) { + return 0; + } + return 1; +} + +/* X25119 implementation. */ + +static void ssl_x25519_cleanup(SSL_ECDH_CTX *ctx) { + if (ctx->data == NULL) { + return; + } + OPENSSL_cleanse(ctx->data, 32); + OPENSSL_free(ctx->data); +} + +static int ssl_x25519_offer(SSL_ECDH_CTX *ctx, CBB *out) { + assert(ctx->data == NULL); + + ctx->data = OPENSSL_malloc(32); + if (ctx->data == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + return 0; + } + uint8_t public_key[32]; + X25519_keypair(public_key, (uint8_t *)ctx->data); + return CBB_add_bytes(out, public_key, sizeof(public_key)); +} + +static int ssl_x25519_finish(SSL_ECDH_CTX *ctx, uint8_t **out_secret, + size_t *out_secret_len, uint8_t *out_alert, + const uint8_t *peer_key, size_t peer_key_len) { + assert(ctx->data != NULL); + *out_alert = SSL_AD_INTERNAL_ERROR; + + uint8_t *secret = OPENSSL_malloc(32); + if (secret == NULL) { + return 0; + } + + if (peer_key_len != 32 || + !X25519(secret, (uint8_t *)ctx->data, peer_key)) { + OPENSSL_free(secret); + *out_alert = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECPOINT); + return 0; + } + + *out_secret = secret; + *out_secret_len = 32; + return 1; +} + +static int ssl_x25519_accept(SSL_ECDH_CTX *ctx, CBB *out_public_key, + uint8_t **out_secret, size_t *out_secret_len, + uint8_t *out_alert, const uint8_t *peer_key, + size_t peer_key_len) { + *out_alert = SSL_AD_INTERNAL_ERROR; + if (!ssl_x25519_offer(ctx, out_public_key) || + !ssl_x25519_finish(ctx, out_secret, out_secret_len, out_alert, peer_key, + peer_key_len)) { + return 0; + } + return 1; +} + + +/* Combined X25119 + New Hope (post-quantum) implementation. */ + +typedef struct { + uint8_t x25519_key[32]; + NEWHOPE_POLY *newhope_sk; +} cecpq1_data; + +#define CECPQ1_OFFERMSG_LENGTH (32 + NEWHOPE_OFFERMSG_LENGTH) +#define CECPQ1_ACCEPTMSG_LENGTH (32 + NEWHOPE_ACCEPTMSG_LENGTH) +#define CECPQ1_SECRET_LENGTH (32 + SHA256_DIGEST_LENGTH) + +static void ssl_cecpq1_cleanup(SSL_ECDH_CTX *ctx) { + if (ctx->data == NULL) { + return; + } + cecpq1_data *data = ctx->data; + NEWHOPE_POLY_free(data->newhope_sk); + OPENSSL_cleanse(data, sizeof(cecpq1_data)); + OPENSSL_free(data); +} + +static int ssl_cecpq1_offer(SSL_ECDH_CTX *ctx, CBB *out) { + assert(ctx->data == NULL); + cecpq1_data *data = OPENSSL_malloc(sizeof(cecpq1_data)); + if (data == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + return 0; + } + ctx->data = data; + data->newhope_sk = NEWHOPE_POLY_new(); + if (data->newhope_sk == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + return 0; + } + + uint8_t x25519_public_key[32]; + X25519_keypair(x25519_public_key, data->x25519_key); + + uint8_t newhope_offermsg[NEWHOPE_OFFERMSG_LENGTH]; + NEWHOPE_offer(newhope_offermsg, data->newhope_sk); + + if (!CBB_add_bytes(out, x25519_public_key, sizeof(x25519_public_key)) || + !CBB_add_bytes(out, newhope_offermsg, sizeof(newhope_offermsg))) { + return 0; + } + return 1; +} + +static int ssl_cecpq1_accept(SSL_ECDH_CTX *ctx, CBB *cbb, uint8_t **out_secret, + size_t *out_secret_len, uint8_t *out_alert, + const uint8_t *peer_key, size_t peer_key_len) { + if (peer_key_len != CECPQ1_OFFERMSG_LENGTH) { + *out_alert = SSL_AD_DECODE_ERROR; + return 0; + } + + *out_alert = SSL_AD_INTERNAL_ERROR; + + assert(ctx->data == NULL); + cecpq1_data *data = OPENSSL_malloc(sizeof(cecpq1_data)); + if (data == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + return 0; + } + data->newhope_sk = NULL; + ctx->data = data; + + uint8_t *secret = OPENSSL_malloc(CECPQ1_SECRET_LENGTH); + if (secret == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + return 0; + } + + /* Generate message to server, and secret key, at once. */ + + uint8_t x25519_public_key[32]; + X25519_keypair(x25519_public_key, data->x25519_key); + if (!X25519(secret, data->x25519_key, peer_key)) { + *out_alert = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECPOINT); + goto err; + } + + uint8_t newhope_acceptmsg[NEWHOPE_ACCEPTMSG_LENGTH]; + if (!NEWHOPE_accept(secret + 32, newhope_acceptmsg, peer_key + 32, + NEWHOPE_OFFERMSG_LENGTH)) { + *out_alert = SSL_AD_DECODE_ERROR; + goto err; + } + + if (!CBB_add_bytes(cbb, x25519_public_key, sizeof(x25519_public_key)) || + !CBB_add_bytes(cbb, newhope_acceptmsg, sizeof(newhope_acceptmsg))) { + goto err; + } + + *out_secret = secret; + *out_secret_len = CECPQ1_SECRET_LENGTH; + return 1; + + err: + OPENSSL_cleanse(secret, CECPQ1_SECRET_LENGTH); + OPENSSL_free(secret); + return 0; +} + +static int ssl_cecpq1_finish(SSL_ECDH_CTX *ctx, uint8_t **out_secret, + size_t *out_secret_len, uint8_t *out_alert, + const uint8_t *peer_key, size_t peer_key_len) { + if (peer_key_len != CECPQ1_ACCEPTMSG_LENGTH) { + *out_alert = SSL_AD_DECODE_ERROR; + return 0; + } + + *out_alert = SSL_AD_INTERNAL_ERROR; + + assert(ctx->data != NULL); + cecpq1_data *data = ctx->data; + + uint8_t *secret = OPENSSL_malloc(CECPQ1_SECRET_LENGTH); + if (secret == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + return 0; + } + + if (!X25519(secret, data->x25519_key, peer_key)) { + *out_alert = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECPOINT); + goto err; + } + + if (!NEWHOPE_finish(secret + 32, data->newhope_sk, peer_key + 32, + NEWHOPE_ACCEPTMSG_LENGTH)) { + *out_alert = SSL_AD_DECODE_ERROR; + goto err; + } + + *out_secret = secret; + *out_secret_len = CECPQ1_SECRET_LENGTH; + return 1; + + err: + OPENSSL_cleanse(secret, CECPQ1_SECRET_LENGTH); + OPENSSL_free(secret); + return 0; +} + + +/* Legacy DHE-based implementation. */ + +static void ssl_dhe_cleanup(SSL_ECDH_CTX *ctx) { + DH_free((DH *)ctx->data); +} + +static int ssl_dhe_offer(SSL_ECDH_CTX *ctx, CBB *out) { + DH *dh = (DH *)ctx->data; + /* The group must have been initialized already, but not the key. */ + assert(dh != NULL); + assert(dh->priv_key == NULL); + + /* Due to a bug in yaSSL, the public key must be zero padded to the size of + * the prime. */ + return DH_generate_key(dh) && + BN_bn2cbb_padded(out, BN_num_bytes(dh->p), dh->pub_key); +} + +static int ssl_dhe_finish(SSL_ECDH_CTX *ctx, uint8_t **out_secret, + size_t *out_secret_len, uint8_t *out_alert, + const uint8_t *peer_key, size_t peer_key_len) { + DH *dh = (DH *)ctx->data; + assert(dh != NULL); + assert(dh->priv_key != NULL); + *out_alert = SSL_AD_INTERNAL_ERROR; + + int secret_len = 0; + uint8_t *secret = NULL; + BIGNUM *peer_point = BN_bin2bn(peer_key, peer_key_len, NULL); + if (peer_point == NULL) { + goto err; + } + + secret = OPENSSL_malloc(DH_size(dh)); + if (secret == NULL) { + goto err; + } + secret_len = DH_compute_key(secret, peer_point, dh); + if (secret_len <= 0) { + goto err; + } + + *out_secret = secret; + *out_secret_len = (size_t)secret_len; + BN_free(peer_point); + return 1; + +err: + if (secret_len > 0) { + OPENSSL_cleanse(secret, (size_t)secret_len); + } + OPENSSL_free(secret); + BN_free(peer_point); + return 0; +} + +static int ssl_dhe_accept(SSL_ECDH_CTX *ctx, CBB *out_public_key, + uint8_t **out_secret, size_t *out_secret_len, + uint8_t *out_alert, const uint8_t *peer_key, + size_t peer_key_len) { + *out_alert = SSL_AD_INTERNAL_ERROR; + if (!ssl_dhe_offer(ctx, out_public_key) || + !ssl_dhe_finish(ctx, out_secret, out_secret_len, out_alert, peer_key, + peer_key_len)) { + return 0; + } + return 1; +} + +static const SSL_ECDH_METHOD kDHEMethod = { + NID_undef, 0, "", + ssl_dhe_cleanup, + ssl_dhe_offer, + ssl_dhe_accept, + ssl_dhe_finish, + CBS_get_u16_length_prefixed, + CBB_add_u16_length_prefixed, +}; + +static const SSL_ECDH_METHOD kMethods[] = { + { + NID_X9_62_prime256v1, + SSL_GROUP_SECP256R1, + "P-256", + ssl_ec_point_cleanup, + ssl_ec_point_offer, + ssl_ec_point_accept, + ssl_ec_point_finish, + CBS_get_u8_length_prefixed, + CBB_add_u8_length_prefixed, + }, + { + NID_secp384r1, + SSL_GROUP_SECP384R1, + "P-384", + ssl_ec_point_cleanup, + ssl_ec_point_offer, + ssl_ec_point_accept, + ssl_ec_point_finish, + CBS_get_u8_length_prefixed, + CBB_add_u8_length_prefixed, + }, + { + NID_secp521r1, + SSL_GROUP_SECP521R1, + "P-521", + ssl_ec_point_cleanup, + ssl_ec_point_offer, + ssl_ec_point_accept, + ssl_ec_point_finish, + CBS_get_u8_length_prefixed, + CBB_add_u8_length_prefixed, + }, + { + NID_X25519, + SSL_GROUP_X25519, + "X25519", + ssl_x25519_cleanup, + ssl_x25519_offer, + ssl_x25519_accept, + ssl_x25519_finish, + CBS_get_u8_length_prefixed, + CBB_add_u8_length_prefixed, + }, + { + NID_cecpq1, + SSL_GROUP_CECPQ1, + "CECPQ1", + ssl_cecpq1_cleanup, + ssl_cecpq1_offer, + ssl_cecpq1_accept, + ssl_cecpq1_finish, + CBS_get_u16_length_prefixed, + CBB_add_u16_length_prefixed, + }, +}; + +static const SSL_ECDH_METHOD *method_from_group_id(uint16_t group_id) { + size_t i; + for (i = 0; i < sizeof(kMethods) / sizeof(kMethods[0]); i++) { + if (kMethods[i].group_id == group_id) { + return &kMethods[i]; + } + } + return NULL; +} + +static const SSL_ECDH_METHOD *method_from_nid(int nid) { + size_t i; + for (i = 0; i < sizeof(kMethods) / sizeof(kMethods[0]); i++) { + if (kMethods[i].nid == nid) { + return &kMethods[i]; + } + } + return NULL; +} + +const char* SSL_get_curve_name(uint16_t group_id) { + const SSL_ECDH_METHOD *method = method_from_group_id(group_id); + if (method == NULL) { + return NULL; + } + return method->name; +} + +int ssl_nid_to_group_id(uint16_t *out_group_id, int nid) { + const SSL_ECDH_METHOD *method = method_from_nid(nid); + if (method == NULL) { + return 0; + } + *out_group_id = method->group_id; + return 1; +} + +int SSL_ECDH_CTX_init(SSL_ECDH_CTX *ctx, uint16_t group_id) { + SSL_ECDH_CTX_cleanup(ctx); + + const SSL_ECDH_METHOD *method = method_from_group_id(group_id); + if (method == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_ELLIPTIC_CURVE); + return 0; + } + ctx->method = method; + return 1; +} + +void SSL_ECDH_CTX_init_for_dhe(SSL_ECDH_CTX *ctx, DH *params) { + SSL_ECDH_CTX_cleanup(ctx); + + ctx->method = &kDHEMethod; + ctx->data = params; +} + +int SSL_ECDH_CTX_get_key(SSL_ECDH_CTX *ctx, CBS *cbs, CBS *out) { + if (ctx->method == NULL) { + return 0; + } + return ctx->method->get_key(cbs, out); +} + +int SSL_ECDH_CTX_add_key(SSL_ECDH_CTX *ctx, CBB *cbb, CBB *out_contents) { + if (ctx->method == NULL) { + return 0; + } + return ctx->method->add_key(cbb, out_contents); +} + +void SSL_ECDH_CTX_cleanup(SSL_ECDH_CTX *ctx) { + if (ctx->method == NULL) { + return; + } + ctx->method->cleanup(ctx); + ctx->method = NULL; + ctx->data = NULL; +} + +int SSL_ECDH_CTX_offer(SSL_ECDH_CTX *ctx, CBB *out_public_key) { + return ctx->method->offer(ctx, out_public_key); +} + +int SSL_ECDH_CTX_accept(SSL_ECDH_CTX *ctx, CBB *out_public_key, + uint8_t **out_secret, size_t *out_secret_len, + uint8_t *out_alert, const uint8_t *peer_key, + size_t peer_key_len) { + return ctx->method->accept(ctx, out_public_key, out_secret, out_secret_len, + out_alert, peer_key, peer_key_len); +} + +int SSL_ECDH_CTX_finish(SSL_ECDH_CTX *ctx, uint8_t **out_secret, + size_t *out_secret_len, uint8_t *out_alert, + const uint8_t *peer_key, size_t peer_key_len) { + return ctx->method->finish(ctx, out_secret, out_secret_len, out_alert, + peer_key, peer_key_len); +} diff --git a/external/boringssl/ssl/ssl_file.c b/external/boringssl/ssl/ssl_file.c new file mode 100644 index 0000000000..748d50cac9 --- /dev/null +++ b/external/boringssl/ssl/ssl_file.c @@ -0,0 +1,585 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "internal.h" + + +static int xname_cmp(const X509_NAME **a, const X509_NAME **b) { + return X509_NAME_cmp(*a, *b); +} + +/* TODO(davidben): Is there any reason this doesn't call + * |SSL_add_file_cert_subjects_to_stack|? */ +STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file) { + BIO *in; + X509 *x = NULL; + X509_NAME *xn = NULL; + STACK_OF(X509_NAME) *ret = NULL, *sk; + + sk = sk_X509_NAME_new(xname_cmp); + in = BIO_new(BIO_s_file()); + + if (sk == NULL || in == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (!BIO_read_filename(in, file)) { + goto err; + } + + for (;;) { + if (PEM_read_bio_X509(in, &x, NULL, NULL) == NULL) { + break; + } + if (ret == NULL) { + ret = sk_X509_NAME_new_null(); + if (ret == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + goto err; + } + } + xn = X509_get_subject_name(x); + if (xn == NULL) { + goto err; + } + + /* check for duplicates */ + xn = X509_NAME_dup(xn); + if (xn == NULL) { + goto err; + } + if (sk_X509_NAME_find(sk, NULL, xn)) { + X509_NAME_free(xn); + } else { + sk_X509_NAME_push(sk, xn); + sk_X509_NAME_push(ret, xn); + } + } + + if (0) { + err: + sk_X509_NAME_pop_free(ret, X509_NAME_free); + ret = NULL; + } + + sk_X509_NAME_free(sk); + BIO_free(in); + X509_free(x); + if (ret != NULL) { + ERR_clear_error(); + } + return ret; +} + +int SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack, + const char *file) { + BIO *in; + X509 *x = NULL; + X509_NAME *xn = NULL; + int ret = 1; + int (*oldcmp)(const X509_NAME **a, const X509_NAME **b); + + oldcmp = sk_X509_NAME_set_cmp_func(stack, xname_cmp); + in = BIO_new(BIO_s_file()); + + if (in == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (!BIO_read_filename(in, file)) { + goto err; + } + + for (;;) { + if (PEM_read_bio_X509(in, &x, NULL, NULL) == NULL) { + break; + } + xn = X509_get_subject_name(x); + if (xn == NULL) { + goto err; + } + xn = X509_NAME_dup(xn); + if (xn == NULL) { + goto err; + } + if (sk_X509_NAME_find(stack, NULL, xn)) { + X509_NAME_free(xn); + } else { + sk_X509_NAME_push(stack, xn); + } + } + + ERR_clear_error(); + + if (0) { + err: + ret = 0; + } + + BIO_free(in); + X509_free(x); + + (void) sk_X509_NAME_set_cmp_func(stack, oldcmp); + + return ret; +} + +int SSL_use_certificate_file(SSL *ssl, const char *file, int type) { + int reason_code; + BIO *in; + int ret = 0; + X509 *x = NULL; + + in = BIO_new(BIO_s_file()); + if (in == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB); + goto end; + } + + if (BIO_read_filename(in, file) <= 0) { + OPENSSL_PUT_ERROR(SSL, ERR_R_SYS_LIB); + goto end; + } + + if (type == SSL_FILETYPE_ASN1) { + reason_code = ERR_R_ASN1_LIB; + x = d2i_X509_bio(in, NULL); + } else if (type == SSL_FILETYPE_PEM) { + reason_code = ERR_R_PEM_LIB; + x = PEM_read_bio_X509(in, NULL, ssl->ctx->default_passwd_callback, + ssl->ctx->default_passwd_callback_userdata); + } else { + OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SSL_FILETYPE); + goto end; + } + + if (x == NULL) { + OPENSSL_PUT_ERROR(SSL, reason_code); + goto end; + } + + ret = SSL_use_certificate(ssl, x); + +end: + X509_free(x); + BIO_free(in); + + return ret; +} + +int SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type) { + int reason_code, ret = 0; + BIO *in; + RSA *rsa = NULL; + + in = BIO_new(BIO_s_file()); + if (in == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB); + goto end; + } + + if (BIO_read_filename(in, file) <= 0) { + OPENSSL_PUT_ERROR(SSL, ERR_R_SYS_LIB); + goto end; + } + + if (type == SSL_FILETYPE_ASN1) { + reason_code = ERR_R_ASN1_LIB; + rsa = d2i_RSAPrivateKey_bio(in, NULL); + } else if (type == SSL_FILETYPE_PEM) { + reason_code = ERR_R_PEM_LIB; + rsa = + PEM_read_bio_RSAPrivateKey(in, NULL, ssl->ctx->default_passwd_callback, + ssl->ctx->default_passwd_callback_userdata); + } else { + OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SSL_FILETYPE); + goto end; + } + + if (rsa == NULL) { + OPENSSL_PUT_ERROR(SSL, reason_code); + goto end; + } + ret = SSL_use_RSAPrivateKey(ssl, rsa); + RSA_free(rsa); + +end: + BIO_free(in); + return ret; +} + +int SSL_use_PrivateKey_file(SSL *ssl, const char *file, int type) { + int reason_code, ret = 0; + BIO *in; + EVP_PKEY *pkey = NULL; + + in = BIO_new(BIO_s_file()); + if (in == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB); + goto end; + } + + if (BIO_read_filename(in, file) <= 0) { + OPENSSL_PUT_ERROR(SSL, ERR_R_SYS_LIB); + goto end; + } + + if (type == SSL_FILETYPE_PEM) { + reason_code = ERR_R_PEM_LIB; + pkey = PEM_read_bio_PrivateKey(in, NULL, ssl->ctx->default_passwd_callback, + ssl->ctx->default_passwd_callback_userdata); + } else if (type == SSL_FILETYPE_ASN1) { + reason_code = ERR_R_ASN1_LIB; + pkey = d2i_PrivateKey_bio(in, NULL); + } else { + OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SSL_FILETYPE); + goto end; + } + + if (pkey == NULL) { + OPENSSL_PUT_ERROR(SSL, reason_code); + goto end; + } + ret = SSL_use_PrivateKey(ssl, pkey); + EVP_PKEY_free(pkey); + +end: + BIO_free(in); + return ret; +} + +int SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type) { + int reason_code; + BIO *in; + int ret = 0; + X509 *x = NULL; + + in = BIO_new(BIO_s_file()); + if (in == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB); + goto end; + } + + if (BIO_read_filename(in, file) <= 0) { + OPENSSL_PUT_ERROR(SSL, ERR_R_SYS_LIB); + goto end; + } + + if (type == SSL_FILETYPE_ASN1) { + reason_code = ERR_R_ASN1_LIB; + x = d2i_X509_bio(in, NULL); + } else if (type == SSL_FILETYPE_PEM) { + reason_code = ERR_R_PEM_LIB; + x = PEM_read_bio_X509(in, NULL, ctx->default_passwd_callback, + ctx->default_passwd_callback_userdata); + } else { + OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SSL_FILETYPE); + goto end; + } + + if (x == NULL) { + OPENSSL_PUT_ERROR(SSL, reason_code); + goto end; + } + + ret = SSL_CTX_use_certificate(ctx, x); + +end: + X509_free(x); + BIO_free(in); + return ret; +} + +int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file, int type) { + int reason_code, ret = 0; + BIO *in; + RSA *rsa = NULL; + + in = BIO_new(BIO_s_file()); + if (in == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB); + goto end; + } + + if (BIO_read_filename(in, file) <= 0) { + OPENSSL_PUT_ERROR(SSL, ERR_R_SYS_LIB); + goto end; + } + + if (type == SSL_FILETYPE_ASN1) { + reason_code = ERR_R_ASN1_LIB; + rsa = d2i_RSAPrivateKey_bio(in, NULL); + } else if (type == SSL_FILETYPE_PEM) { + reason_code = ERR_R_PEM_LIB; + rsa = PEM_read_bio_RSAPrivateKey(in, NULL, ctx->default_passwd_callback, + ctx->default_passwd_callback_userdata); + } else { + OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SSL_FILETYPE); + goto end; + } + + if (rsa == NULL) { + OPENSSL_PUT_ERROR(SSL, reason_code); + goto end; + } + ret = SSL_CTX_use_RSAPrivateKey(ctx, rsa); + RSA_free(rsa); + +end: + BIO_free(in); + return ret; +} + +int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type) { + int reason_code, ret = 0; + BIO *in; + EVP_PKEY *pkey = NULL; + + in = BIO_new(BIO_s_file()); + if (in == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB); + goto end; + } + + if (BIO_read_filename(in, file) <= 0) { + OPENSSL_PUT_ERROR(SSL, ERR_R_SYS_LIB); + goto end; + } + + if (type == SSL_FILETYPE_PEM) { + reason_code = ERR_R_PEM_LIB; + pkey = PEM_read_bio_PrivateKey(in, NULL, ctx->default_passwd_callback, + ctx->default_passwd_callback_userdata); + } else if (type == SSL_FILETYPE_ASN1) { + reason_code = ERR_R_ASN1_LIB; + pkey = d2i_PrivateKey_bio(in, NULL); + } else { + OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SSL_FILETYPE); + goto end; + } + + if (pkey == NULL) { + OPENSSL_PUT_ERROR(SSL, reason_code); + goto end; + } + ret = SSL_CTX_use_PrivateKey(ctx, pkey); + EVP_PKEY_free(pkey); + +end: + BIO_free(in); + return ret; +} + +/* Read a file that contains our certificate in "PEM" format, possibly followed + * by a sequence of CA certificates that should be sent to the peer in the + * Certificate message. */ +int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file) { + BIO *in; + int ret = 0; + X509 *x = NULL; + + ERR_clear_error(); /* clear error stack for SSL_CTX_use_certificate() */ + + in = BIO_new(BIO_s_file()); + if (in == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB); + goto end; + } + + if (BIO_read_filename(in, file) <= 0) { + OPENSSL_PUT_ERROR(SSL, ERR_R_SYS_LIB); + goto end; + } + + x = PEM_read_bio_X509_AUX(in, NULL, ctx->default_passwd_callback, + ctx->default_passwd_callback_userdata); + if (x == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_PEM_LIB); + goto end; + } + + ret = SSL_CTX_use_certificate(ctx, x); + + if (ERR_peek_error() != 0) { + ret = 0; /* Key/certificate mismatch doesn't imply ret==0 ... */ + } + + if (ret) { + /* If we could set up our certificate, now proceed to the CA + * certificates. */ + X509 *ca; + int r; + uint32_t err; + + SSL_CTX_clear_chain_certs(ctx); + + while ((ca = PEM_read_bio_X509(in, NULL, ctx->default_passwd_callback, + ctx->default_passwd_callback_userdata)) != + NULL) { + r = SSL_CTX_add0_chain_cert(ctx, ca); + if (!r) { + X509_free(ca); + ret = 0; + goto end; + } + /* Note that we must not free r if it was successfully added to the chain + * (while we must free the main certificate, since its reference count is + * increased by SSL_CTX_use_certificate). */ + } + + /* When the while loop ends, it's usually just EOF. */ + err = ERR_peek_last_error(); + if (ERR_GET_LIB(err) == ERR_LIB_PEM && + ERR_GET_REASON(err) == PEM_R_NO_START_LINE) { + ERR_clear_error(); + } else { + ret = 0; /* some real error */ + } + } + +end: + X509_free(x); + BIO_free(in); + return ret; +} + +void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, pem_password_cb *cb) { + ctx->default_passwd_callback = cb; +} + +void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx, void *data) { + ctx->default_passwd_callback_userdata = data; +} + +SSL_SESSION *d2i_SSL_SESSION_bio(BIO *bio, SSL_SESSION **out) { + return ASN1_d2i_bio_of(SSL_SESSION, SSL_SESSION_new, d2i_SSL_SESSION, bio, + out); +} + +int i2d_SSL_SESSION_bio(BIO *bio, const SSL_SESSION *session) { + return ASN1_i2d_bio_of(SSL_SESSION, i2d_SSL_SESSION, bio, session); +} + +IMPLEMENT_PEM_rw(SSL_SESSION, SSL_SESSION, PEM_STRING_SSL_SESSION, SSL_SESSION) diff --git a/external/boringssl/ssl/ssl_lib.c b/external/boringssl/ssl/ssl_lib.c new file mode 100644 index 0000000000..0d9569507b --- /dev/null +++ b/external/boringssl/ssl/ssl_lib.c @@ -0,0 +1,2968 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * ECC cipher suite support in OpenSSL originally developed by + * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. + */ +/* ==================================================================== + * Copyright 2005 Nokia. All rights reserved. + * + * The portions of the attached software ("Contribution") is developed by + * Nokia Corporation and is licensed pursuant to the OpenSSL open source + * license. + * + * The Contribution, originally written by Mika Kousa and Pasi Eronen of + * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites + * support (see RFC 4279) to OpenSSL. + * + * No patent licenses or other rights except those expressly stated in + * the OpenSSL open source license shall be deemed granted or received + * expressly, by implication, estoppel, or otherwise. + * + * No assurances are provided by Nokia that the Contribution does not + * infringe the patent or other intellectual property rights of any third + * party or that the license provides you with all the necessary rights + * to make use of the Contribution. + * + * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN + * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA + * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY + * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR + * OTHERWISE. */ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "internal.h" +#include "../crypto/internal.h" + + +/* |SSL_R_UNKNOWN_PROTOCOL| is no longer emitted, but continue to define it + * to avoid downstream churn. */ +OPENSSL_DECLARE_ERROR_REASON(SSL, UNKNOWN_PROTOCOL) + +/* Some error codes are special. Ensure the make_errors.go script never + * regresses this. */ +OPENSSL_COMPILE_ASSERT(SSL_R_TLSV1_ALERT_NO_RENEGOTIATION == + SSL_AD_NO_RENEGOTIATION + SSL_AD_REASON_OFFSET, + ssl_alert_reason_code_mismatch); + +/* kMaxHandshakeSize is the maximum size, in bytes, of a handshake message. */ +static const size_t kMaxHandshakeSize = (1u << 24) - 1; + +static CRYPTO_EX_DATA_CLASS g_ex_data_class_ssl = + CRYPTO_EX_DATA_CLASS_INIT_WITH_APP_DATA; +static CRYPTO_EX_DATA_CLASS g_ex_data_class_ssl_ctx = + CRYPTO_EX_DATA_CLASS_INIT_WITH_APP_DATA; + +int SSL_library_init(void) { + CRYPTO_library_init(); + return 1; +} + +static uint32_t ssl_session_hash(const SSL_SESSION *sess) { + const uint8_t *session_id = sess->session_id; + + uint8_t tmp_storage[sizeof(uint32_t)]; + if (sess->session_id_length < sizeof(tmp_storage)) { + memset(tmp_storage, 0, sizeof(tmp_storage)); + memcpy(tmp_storage, sess->session_id, sess->session_id_length); + session_id = tmp_storage; + } + + uint32_t hash = + ((uint32_t)session_id[0]) | + ((uint32_t)session_id[1] << 8) | + ((uint32_t)session_id[2] << 16) | + ((uint32_t)session_id[3] << 24); + + return hash; +} + +/* NB: If this function (or indeed the hash function which uses a sort of + * coarser function than this one) is changed, ensure + * SSL_CTX_has_matching_session_id() is checked accordingly. It relies on being + * able to construct an SSL_SESSION that will collide with any existing session + * with a matching session ID. */ +static int ssl_session_cmp(const SSL_SESSION *a, const SSL_SESSION *b) { + if (a->ssl_version != b->ssl_version) { + return 1; + } + + if (a->session_id_length != b->session_id_length) { + return 1; + } + + return memcmp(a->session_id, b->session_id, a->session_id_length); +} + +SSL_CTX *SSL_CTX_new(const SSL_METHOD *method) { + SSL_CTX *ret = NULL; + + if (method == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_R_NULL_SSL_METHOD_PASSED); + return NULL; + } + + if (SSL_get_ex_data_X509_STORE_CTX_idx() < 0) { + OPENSSL_PUT_ERROR(SSL, SSL_R_X509_VERIFICATION_SETUP_PROBLEMS); + goto err; + } + + ret = OPENSSL_malloc(sizeof(SSL_CTX)); + if (ret == NULL) { + goto err; + } + + memset(ret, 0, sizeof(SSL_CTX)); + + ret->method = method->method; + + CRYPTO_MUTEX_init(&ret->lock); + + ret->session_cache_mode = SSL_SESS_CACHE_SERVER; + ret->session_cache_size = SSL_SESSION_CACHE_MAX_SIZE_DEFAULT; + + /* We take the system default */ + ret->session_timeout = SSL_DEFAULT_SESSION_TIMEOUT; + + ret->references = 1; + + ret->max_cert_list = SSL_MAX_CERT_LIST_DEFAULT; + ret->verify_mode = SSL_VERIFY_NONE; + ret->cert = ssl_cert_new(); + if (ret->cert == NULL) { + goto err; + } + + ret->sessions = lh_SSL_SESSION_new(ssl_session_hash, ssl_session_cmp); + if (ret->sessions == NULL) { + goto err; + } + ret->cert_store = X509_STORE_new(); + if (ret->cert_store == NULL) { + goto err; + } + + ssl_create_cipher_list(ret->method, &ret->cipher_list, + &ret->cipher_list_by_id, SSL_DEFAULT_CIPHER_LIST); + if (ret->cipher_list == NULL || + sk_SSL_CIPHER_num(ret->cipher_list->ciphers) <= 0) { + OPENSSL_PUT_ERROR(SSL, SSL_R_LIBRARY_HAS_NO_CIPHERS); + goto err2; + } + + ret->param = X509_VERIFY_PARAM_new(); + if (!ret->param) { + goto err; + } + + ret->client_CA = sk_X509_NAME_new_null(); + if (ret->client_CA == NULL) { + goto err; + } + + CRYPTO_new_ex_data(&ret->ex_data); + + ret->max_send_fragment = SSL3_RT_MAX_PLAIN_LENGTH; + + /* Setup RFC4507 ticket keys */ + if (!RAND_bytes(ret->tlsext_tick_key_name, 16) || + !RAND_bytes(ret->tlsext_tick_hmac_key, 16) || + !RAND_bytes(ret->tlsext_tick_aes_key, 16)) { + ret->options |= SSL_OP_NO_TICKET; + } + + /* Lock the SSL_CTX to the specified version, for compatibility with legacy + * uses of SSL_METHOD. */ + if (method->version != 0) { + SSL_CTX_set_max_version(ret, method->version); + SSL_CTX_set_min_version(ret, method->version); + } else if (!method->method->is_dtls) { + /* TODO(svaldez): Enable TLS 1.3 once implemented. */ + SSL_CTX_set_max_version(ret, TLS1_2_VERSION); + } + + return ret; + +err: + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); +err2: + SSL_CTX_free(ret); + return NULL; +} + +void SSL_CTX_free(SSL_CTX *ctx) { + if (ctx == NULL || + !CRYPTO_refcount_dec_and_test_zero(&ctx->references)) { + return; + } + + X509_VERIFY_PARAM_free(ctx->param); + + /* Free internal session cache. However: the remove_cb() may reference the + * ex_data of SSL_CTX, thus the ex_data store can only be removed after the + * sessions were flushed. As the ex_data handling routines might also touch + * the session cache, the most secure solution seems to be: empty (flush) the + * cache, then free ex_data, then finally free the cache. (See ticket + * [openssl.org #212].) */ + SSL_CTX_flush_sessions(ctx, 0); + + CRYPTO_free_ex_data(&g_ex_data_class_ssl_ctx, ctx, &ctx->ex_data); + + CRYPTO_MUTEX_cleanup(&ctx->lock); + lh_SSL_SESSION_free(ctx->sessions); + X509_STORE_free(ctx->cert_store); + ssl_cipher_preference_list_free(ctx->cipher_list); + sk_SSL_CIPHER_free(ctx->cipher_list_by_id); + ssl_cipher_preference_list_free(ctx->cipher_list_tls10); + ssl_cipher_preference_list_free(ctx->cipher_list_tls11); + ssl_cert_free(ctx->cert); + sk_SSL_CUSTOM_EXTENSION_pop_free(ctx->client_custom_extensions, + SSL_CUSTOM_EXTENSION_free); + sk_SSL_CUSTOM_EXTENSION_pop_free(ctx->server_custom_extensions, + SSL_CUSTOM_EXTENSION_free); + sk_X509_NAME_pop_free(ctx->client_CA, X509_NAME_free); + sk_SRTP_PROTECTION_PROFILE_free(ctx->srtp_profiles); + OPENSSL_free(ctx->psk_identity_hint); + OPENSSL_free(ctx->supported_group_list); + OPENSSL_free(ctx->alpn_client_proto_list); + OPENSSL_free(ctx->ocsp_response); + OPENSSL_free(ctx->signed_cert_timestamp_list); + EVP_PKEY_free(ctx->tlsext_channel_id_private); + + OPENSSL_free(ctx); +} + +SSL *SSL_new(SSL_CTX *ctx) { + if (ctx == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_R_NULL_SSL_CTX); + return NULL; + } + if (ctx->method == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION); + return NULL; + } + + SSL *ssl = OPENSSL_malloc(sizeof(SSL)); + if (ssl == NULL) { + goto err; + } + memset(ssl, 0, sizeof(SSL)); + + ssl->min_version = ctx->min_version; + ssl->max_version = ctx->max_version; + + /* RFC 6347 states that implementations SHOULD use an initial timer value of + * 1 second. */ + ssl->initial_timeout_duration_ms = 1000; + + ssl->options = ctx->options; + ssl->mode = ctx->mode; + ssl->max_cert_list = ctx->max_cert_list; + + ssl->cert = ssl_cert_dup(ctx->cert); + if (ssl->cert == NULL) { + goto err; + } + + ssl->msg_callback = ctx->msg_callback; + ssl->msg_callback_arg = ctx->msg_callback_arg; + ssl->verify_mode = ctx->verify_mode; + ssl->sid_ctx_length = ctx->sid_ctx_length; + assert(ssl->sid_ctx_length <= sizeof ssl->sid_ctx); + memcpy(&ssl->sid_ctx, &ctx->sid_ctx, sizeof(ssl->sid_ctx)); + ssl->verify_callback = ctx->default_verify_callback; + + ssl->param = X509_VERIFY_PARAM_new(); + if (!ssl->param) { + goto err; + } + X509_VERIFY_PARAM_inherit(ssl->param, ctx->param); + ssl->quiet_shutdown = ctx->quiet_shutdown; + ssl->max_send_fragment = ctx->max_send_fragment; + + CRYPTO_refcount_inc(&ctx->references); + ssl->ctx = ctx; + CRYPTO_refcount_inc(&ctx->references); + ssl->initial_ctx = ctx; + + if (ctx->supported_group_list) { + ssl->supported_group_list = + BUF_memdup(ctx->supported_group_list, + ctx->supported_group_list_len * 2); + if (!ssl->supported_group_list) { + goto err; + } + ssl->supported_group_list_len = ctx->supported_group_list_len; + } + + if (ssl->ctx->alpn_client_proto_list) { + ssl->alpn_client_proto_list = BUF_memdup( + ssl->ctx->alpn_client_proto_list, ssl->ctx->alpn_client_proto_list_len); + if (ssl->alpn_client_proto_list == NULL) { + goto err; + } + ssl->alpn_client_proto_list_len = ssl->ctx->alpn_client_proto_list_len; + } + + ssl->verify_result = X509_V_OK; + ssl->method = ctx->method; + + if (!ssl->method->ssl_new(ssl)) { + goto err; + } + + ssl->rwstate = SSL_NOTHING; + + CRYPTO_new_ex_data(&ssl->ex_data); + + ssl->psk_identity_hint = NULL; + if (ctx->psk_identity_hint) { + ssl->psk_identity_hint = BUF_strdup(ctx->psk_identity_hint); + if (ssl->psk_identity_hint == NULL) { + goto err; + } + } + ssl->psk_client_callback = ctx->psk_client_callback; + ssl->psk_server_callback = ctx->psk_server_callback; + + ssl->tlsext_channel_id_enabled = ctx->tlsext_channel_id_enabled; + if (ctx->tlsext_channel_id_private) { + ssl->tlsext_channel_id_private = + EVP_PKEY_up_ref(ctx->tlsext_channel_id_private); + } + + ssl->signed_cert_timestamps_enabled = + ssl->ctx->signed_cert_timestamps_enabled; + ssl->ocsp_stapling_enabled = ssl->ctx->ocsp_stapling_enabled; + + return ssl; + +err: + SSL_free(ssl); + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + + return NULL; +} + +void SSL_free(SSL *ssl) { + if (ssl == NULL) { + return; + } + + X509_VERIFY_PARAM_free(ssl->param); + + CRYPTO_free_ex_data(&g_ex_data_class_ssl, ssl, &ssl->ex_data); + + ssl_free_wbio_buffer(ssl); + assert(ssl->bbio == NULL); + + BIO_free_all(ssl->rbio); + BIO_free_all(ssl->wbio); + + BUF_MEM_free(ssl->init_buf); + + /* add extra stuff */ + ssl_cipher_preference_list_free(ssl->cipher_list); + sk_SSL_CIPHER_free(ssl->cipher_list_by_id); + + ssl_clear_bad_session(ssl); + SSL_SESSION_free(ssl->session); + + ssl_cert_free(ssl->cert); + + OPENSSL_free(ssl->tlsext_hostname); + SSL_CTX_free(ssl->initial_ctx); + OPENSSL_free(ssl->supported_group_list); + OPENSSL_free(ssl->alpn_client_proto_list); + EVP_PKEY_free(ssl->tlsext_channel_id_private); + OPENSSL_free(ssl->psk_identity_hint); + sk_X509_NAME_pop_free(ssl->client_CA, X509_NAME_free); + sk_SRTP_PROTECTION_PROFILE_free(ssl->srtp_profiles); + + if (ssl->method != NULL) { + ssl->method->ssl_free(ssl); + } + SSL_CTX_free(ssl->ctx); + + OPENSSL_free(ssl); +} + +void SSL_set_connect_state(SSL *ssl) { + ssl->server = 0; + ssl->state = SSL_ST_CONNECT; + ssl->handshake_func = ssl3_connect; +} + +void SSL_set_accept_state(SSL *ssl) { + ssl->server = 1; + ssl->state = SSL_ST_ACCEPT; + ssl->handshake_func = ssl3_accept; +} + +static void ssl_set_rbio(SSL *ssl, BIO *rbio) { + BIO_free_all(ssl->rbio); + ssl->rbio = rbio; +} + +static void ssl_set_wbio(SSL *ssl, BIO *wbio) { + /* If the output buffering BIO is still in place, remove it. */ + if (ssl->bbio != NULL) { + ssl->wbio = BIO_pop(ssl->wbio); + } + + BIO_free_all(ssl->wbio); + ssl->wbio = wbio; + + /* Re-attach |bbio| to the new |wbio|. */ + if (ssl->bbio != NULL) { + ssl->wbio = BIO_push(ssl->bbio, ssl->wbio); + } +} + +void SSL_set_bio(SSL *ssl, BIO *rbio, BIO *wbio) { + /* For historical reasons, this function has many different cases in ownership + * handling. */ + + /* If the two arguments are equal, one fewer reference is granted than + * taken. */ + if (rbio != NULL && rbio == wbio) { + BIO_up_ref(rbio); + } + + /* If at most one of rbio or wbio is changed, only adopt one reference. */ + if (rbio == SSL_get_rbio(ssl)) { + ssl_set_wbio(ssl, wbio); + return; + } + if (wbio == SSL_get_wbio(ssl)) { + ssl_set_rbio(ssl, rbio); + return; + } + + /* Otherwise, adopt both references. */ + ssl_set_rbio(ssl, rbio); + ssl_set_wbio(ssl, wbio); +} + +BIO *SSL_get_rbio(const SSL *ssl) { return ssl->rbio; } + +BIO *SSL_get_wbio(const SSL *ssl) { + if (ssl->bbio != NULL) { + /* If |bbio| is active, the true caller-configured BIO is its |next_bio|. */ + assert(ssl->bbio == ssl->wbio); + return ssl->bbio->next_bio; + } + return ssl->wbio; +} + +int SSL_do_handshake(SSL *ssl) { + ssl->rwstate = SSL_NOTHING; + /* Functions which use SSL_get_error must clear the error queue on entry. */ + ERR_clear_error(); + ERR_clear_system_error(); + + if (ssl->handshake_func == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_R_CONNECTION_TYPE_NOT_SET); + return -1; + } + + if (!SSL_in_init(ssl)) { + return 1; + } + + return ssl->handshake_func(ssl); +} + +int SSL_connect(SSL *ssl) { + if (ssl->handshake_func == NULL) { + /* Not properly initialized yet */ + SSL_set_connect_state(ssl); + } + + return SSL_do_handshake(ssl); +} + +int SSL_accept(SSL *ssl) { + if (ssl->handshake_func == NULL) { + /* Not properly initialized yet */ + SSL_set_accept_state(ssl); + } + + return SSL_do_handshake(ssl); +} + +static int ssl_read_impl(SSL *ssl, void *buf, int num, int peek) { + ssl->rwstate = SSL_NOTHING; + /* Functions which use SSL_get_error must clear the error queue on entry. */ + ERR_clear_error(); + ERR_clear_system_error(); + + if (ssl->handshake_func == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_R_UNINITIALIZED); + return -1; + } + + /* This may require multiple iterations. False Start will cause + * |ssl->handshake_func| to signal success one step early, but the handshake + * must be completely finished before other modes are accepted. */ + while (SSL_in_init(ssl)) { + int ret = SSL_do_handshake(ssl); + if (ret < 0) { + return ret; + } + if (ret == 0) { + OPENSSL_PUT_ERROR(SSL, SSL_R_SSL_HANDSHAKE_FAILURE); + return -1; + } + } + + return ssl->method->ssl_read_app_data(ssl, buf, num, peek); +} + +int SSL_read(SSL *ssl, void *buf, int num) { + return ssl_read_impl(ssl, buf, num, 0 /* consume bytes */); +} + +int SSL_peek(SSL *ssl, void *buf, int num) { + return ssl_read_impl(ssl, buf, num, 1 /* peek */); +} + +int SSL_write(SSL *ssl, const void *buf, int num) { + ssl->rwstate = SSL_NOTHING; + /* Functions which use SSL_get_error must clear the error queue on entry. */ + ERR_clear_error(); + ERR_clear_system_error(); + + if (ssl->handshake_func == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_R_UNINITIALIZED); + return -1; + } + + if (ssl->s3->send_shutdown != ssl_shutdown_none) { + OPENSSL_PUT_ERROR(SSL, SSL_R_PROTOCOL_IS_SHUTDOWN); + return -1; + } + + /* If necessary, complete the handshake implicitly. */ + if (SSL_in_init(ssl) && !SSL_in_false_start(ssl)) { + int ret = SSL_do_handshake(ssl); + if (ret < 0) { + return ret; + } + if (ret == 0) { + OPENSSL_PUT_ERROR(SSL, SSL_R_SSL_HANDSHAKE_FAILURE); + return -1; + } + } + + return ssl->method->ssl_write_app_data(ssl, buf, num); +} + +int SSL_shutdown(SSL *ssl) { + ssl->rwstate = SSL_NOTHING; + /* Functions which use SSL_get_error must clear the error queue on entry. */ + ERR_clear_error(); + ERR_clear_system_error(); + + if (ssl->handshake_func == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_R_UNINITIALIZED); + return -1; + } + + /* We can't shutdown properly if we are in the middle of a handshake. */ + if (SSL_in_init(ssl)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_SHUTDOWN_WHILE_IN_INIT); + return -1; + } + + if (ssl->quiet_shutdown) { + /* Do nothing if configured not to send a close_notify. */ + ssl->s3->send_shutdown = ssl_shutdown_close_notify; + ssl->s3->recv_shutdown = ssl_shutdown_close_notify; + return 1; + } + + /* This function completes in two stages. It sends a close_notify and then it + * waits for a close_notify to come in. Perform exactly one action and return + * whether or not it succeeds. */ + + if (ssl->s3->send_shutdown != ssl_shutdown_close_notify) { + /* Send a close_notify. */ + if (ssl3_send_alert(ssl, SSL3_AL_WARNING, SSL_AD_CLOSE_NOTIFY) <= 0) { + return -1; + } + } else if (ssl->s3->alert_dispatch) { + /* Finish sending the close_notify. */ + if (ssl->method->ssl_dispatch_alert(ssl) <= 0) { + return -1; + } + } else if (ssl->s3->recv_shutdown != ssl_shutdown_close_notify) { + /* Wait for the peer's close_notify. */ + ssl->method->ssl_read_close_notify(ssl); + if (ssl->s3->recv_shutdown != ssl_shutdown_close_notify) { + return -1; + } + } + + /* Return 0 for unidirectional shutdown and 1 for bidirectional shutdown. */ + return ssl->s3->recv_shutdown == ssl_shutdown_close_notify; +} + +int SSL_get_error(const SSL *ssl, int ret_code) { + int reason; + uint32_t err; + BIO *bio; + + if (ret_code > 0) { + return SSL_ERROR_NONE; + } + + /* Make things return SSL_ERROR_SYSCALL when doing SSL_do_handshake etc, + * where we do encode the error */ + err = ERR_peek_error(); + if (err != 0) { + if (ERR_GET_LIB(err) == ERR_LIB_SYS) { + return SSL_ERROR_SYSCALL; + } + return SSL_ERROR_SSL; + } + + if (ret_code == 0) { + if (ssl->s3->recv_shutdown == ssl_shutdown_close_notify) { + return SSL_ERROR_ZERO_RETURN; + } + /* An EOF was observed which violates the protocol, and the underlying + * transport does not participate in the error queue. Bubble up to the + * caller. */ + return SSL_ERROR_SYSCALL; + } + + if (SSL_want_session(ssl)) { + return SSL_ERROR_PENDING_SESSION; + } + + if (SSL_want_certificate(ssl)) { + return SSL_ERROR_PENDING_CERTIFICATE; + } + + if (SSL_want_read(ssl)) { + bio = SSL_get_rbio(ssl); + if (BIO_should_read(bio)) { + return SSL_ERROR_WANT_READ; + } + + if (BIO_should_write(bio)) { + /* This one doesn't make too much sense ... We never try to write to the + * rbio, and an application program where rbio and wbio are separate + * couldn't even know what it should wait for. However if we ever set + * ssl->rwstate incorrectly (so that we have SSL_want_read(ssl) instead of + * SSL_want_write(ssl)) and rbio and wbio *are* the same, this test works + * around that bug; so it might be safer to keep it. */ + return SSL_ERROR_WANT_WRITE; + } + + if (BIO_should_io_special(bio)) { + reason = BIO_get_retry_reason(bio); + if (reason == BIO_RR_CONNECT) { + return SSL_ERROR_WANT_CONNECT; + } + + if (reason == BIO_RR_ACCEPT) { + return SSL_ERROR_WANT_ACCEPT; + } + + return SSL_ERROR_SYSCALL; /* unknown */ + } + } + + if (SSL_want_write(ssl)) { + bio = SSL_get_wbio(ssl); + if (BIO_should_write(bio)) { + return SSL_ERROR_WANT_WRITE; + } + + if (BIO_should_read(bio)) { + /* See above (SSL_want_read(ssl) with BIO_should_write(bio)) */ + return SSL_ERROR_WANT_READ; + } + + if (BIO_should_io_special(bio)) { + reason = BIO_get_retry_reason(bio); + if (reason == BIO_RR_CONNECT) { + return SSL_ERROR_WANT_CONNECT; + } + + if (reason == BIO_RR_ACCEPT) { + return SSL_ERROR_WANT_ACCEPT; + } + + return SSL_ERROR_SYSCALL; + } + } + + if (SSL_want_x509_lookup(ssl)) { + return SSL_ERROR_WANT_X509_LOOKUP; + } + + if (SSL_want_channel_id_lookup(ssl)) { + return SSL_ERROR_WANT_CHANNEL_ID_LOOKUP; + } + + if (SSL_want_private_key_operation(ssl)) { + return SSL_ERROR_WANT_PRIVATE_KEY_OPERATION; + } + + return SSL_ERROR_SYSCALL; +} + +void SSL_CTX_set_min_version(SSL_CTX *ctx, uint16_t version) { + ctx->min_version = version; +} + +void SSL_CTX_set_max_version(SSL_CTX *ctx, uint16_t version) { + ctx->max_version = version; +} + +void SSL_set_min_version(SSL *ssl, uint16_t version) { + ssl->min_version = version; +} + +void SSL_set_max_version(SSL *ssl, uint16_t version) { + ssl->max_version = version; +} + +uint32_t SSL_CTX_set_options(SSL_CTX *ctx, uint32_t options) { + ctx->options |= options; + return ctx->options; +} + +uint32_t SSL_CTX_clear_options(SSL_CTX *ctx, uint32_t options) { + ctx->options &= ~options; + return ctx->options; +} + +uint32_t SSL_CTX_get_options(const SSL_CTX *ctx) { return ctx->options; } + +uint32_t SSL_set_options(SSL *ssl, uint32_t options) { + ssl->options |= options; + return ssl->options; +} + +uint32_t SSL_clear_options(SSL *ssl, uint32_t options) { + ssl->options &= ~options; + return ssl->options; +} + +uint32_t SSL_get_options(const SSL *ssl) { return ssl->options; } + +uint32_t SSL_CTX_set_mode(SSL_CTX *ctx, uint32_t mode) { + ctx->mode |= mode; + return ctx->mode; +} + +uint32_t SSL_CTX_clear_mode(SSL_CTX *ctx, uint32_t mode) { + ctx->mode &= ~mode; + return ctx->mode; +} + +uint32_t SSL_CTX_get_mode(const SSL_CTX *ctx) { return ctx->mode; } + +uint32_t SSL_set_mode(SSL *ssl, uint32_t mode) { + ssl->mode |= mode; + return ssl->mode; +} + +uint32_t SSL_clear_mode(SSL *ssl, uint32_t mode) { + ssl->mode &= ~mode; + return ssl->mode; +} + +uint32_t SSL_get_mode(const SSL *ssl) { return ssl->mode; } + +X509 *SSL_get_peer_certificate(const SSL *ssl) { + if (ssl == NULL || ssl->session == NULL || ssl->session->peer == NULL) { + return NULL; + } + return X509_up_ref(ssl->session->peer); +} + +STACK_OF(X509) *SSL_get_peer_cert_chain(const SSL *ssl) { + if (ssl == NULL || ssl->session == NULL) { + return NULL; + } + return ssl->session->cert_chain; +} + +int SSL_get_tls_unique(const SSL *ssl, uint8_t *out, size_t *out_len, + size_t max_out) { + /* The tls-unique value is the first Finished message in the handshake, which + * is the client's in a full handshake and the server's for a resumption. See + * https://tools.ietf.org/html/rfc5929#section-3.1. */ + const uint8_t *finished = ssl->s3->previous_client_finished; + size_t finished_len = ssl->s3->previous_client_finished_len; + if (ssl->hit) { + /* tls-unique is broken for resumed sessions unless EMS is used. */ + if (!ssl->session->extended_master_secret) { + goto err; + } + finished = ssl->s3->previous_server_finished; + finished_len = ssl->s3->previous_server_finished_len; + } + + if (!ssl->s3->initial_handshake_complete || + ssl->version < TLS1_VERSION) { + goto err; + } + + *out_len = finished_len; + if (finished_len > max_out) { + *out_len = max_out; + } + + memcpy(out, finished, *out_len); + return 1; + +err: + *out_len = 0; + memset(out, 0, max_out); + return 0; +} + +int SSL_CTX_set_session_id_context(SSL_CTX *ctx, const uint8_t *sid_ctx, + unsigned sid_ctx_len) { + if (sid_ctx_len > sizeof(ctx->sid_ctx)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG); + return 0; + } + ctx->sid_ctx_length = sid_ctx_len; + memcpy(ctx->sid_ctx, sid_ctx, sid_ctx_len); + + return 1; +} + +int SSL_set_session_id_context(SSL *ssl, const uint8_t *sid_ctx, + unsigned sid_ctx_len) { + if (sid_ctx_len > SSL_MAX_SID_CTX_LENGTH) { + OPENSSL_PUT_ERROR(SSL, SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG); + return 0; + } + ssl->sid_ctx_length = sid_ctx_len; + memcpy(ssl->sid_ctx, sid_ctx, sid_ctx_len); + + return 1; +} + +int SSL_CTX_set_purpose(SSL_CTX *ctx, int purpose) { + return X509_VERIFY_PARAM_set_purpose(ctx->param, purpose); +} + +int SSL_set_purpose(SSL *ssl, int purpose) { + return X509_VERIFY_PARAM_set_purpose(ssl->param, purpose); +} + +int SSL_CTX_set_trust(SSL_CTX *ctx, int trust) { + return X509_VERIFY_PARAM_set_trust(ctx->param, trust); +} + +int SSL_set_trust(SSL *ssl, int trust) { + return X509_VERIFY_PARAM_set_trust(ssl->param, trust); +} + +int SSL_CTX_set1_param(SSL_CTX *ctx, const X509_VERIFY_PARAM *param) { + return X509_VERIFY_PARAM_set1(ctx->param, param); +} + +int SSL_set1_param(SSL *ssl, const X509_VERIFY_PARAM *param) { + return X509_VERIFY_PARAM_set1(ssl->param, param); +} + +void ssl_cipher_preference_list_free( + struct ssl_cipher_preference_list_st *cipher_list) { + if (cipher_list == NULL) { + return; + } + sk_SSL_CIPHER_free(cipher_list->ciphers); + OPENSSL_free(cipher_list->in_group_flags); + OPENSSL_free(cipher_list); +} + +X509_VERIFY_PARAM *SSL_CTX_get0_param(SSL_CTX *ctx) { return ctx->param; } + +X509_VERIFY_PARAM *SSL_get0_param(SSL *ssl) { return ssl->param; } + +void SSL_certs_clear(SSL *ssl) { ssl_cert_clear_certs(ssl->cert); } + +int SSL_get_fd(const SSL *ssl) { return SSL_get_rfd(ssl); } + +int SSL_get_rfd(const SSL *ssl) { + int ret = -1; + BIO *b = BIO_find_type(SSL_get_rbio(ssl), BIO_TYPE_DESCRIPTOR); + if (b != NULL) { + BIO_get_fd(b, &ret); + } + return ret; +} + +int SSL_get_wfd(const SSL *ssl) { + int ret = -1; + BIO *b = BIO_find_type(SSL_get_wbio(ssl), BIO_TYPE_DESCRIPTOR); + if (b != NULL) { + BIO_get_fd(b, &ret); + } + return ret; +} + +int SSL_set_fd(SSL *ssl, int fd) { + BIO *bio = BIO_new(BIO_s_socket()); + if (bio == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB); + return 0; + } + BIO_set_fd(bio, fd, BIO_NOCLOSE); + SSL_set_bio(ssl, bio, bio); + return 1; +} + +int SSL_set_wfd(SSL *ssl, int fd) { + BIO *rbio = SSL_get_rbio(ssl); + if (rbio == NULL || BIO_method_type(rbio) != BIO_TYPE_SOCKET || + BIO_get_fd(rbio, NULL) != fd) { + BIO *bio = BIO_new(BIO_s_socket()); + if (bio == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB); + return 0; + } + BIO_set_fd(bio, fd, BIO_NOCLOSE); + SSL_set_bio(ssl, rbio, bio); + } else { + SSL_set_bio(ssl, rbio, rbio); + } + + return 1; +} + +int SSL_set_rfd(SSL *ssl, int fd) { + BIO *wbio = SSL_get_wbio(ssl); + if (wbio == NULL || BIO_method_type(wbio) != BIO_TYPE_SOCKET || + BIO_get_fd(wbio, NULL) != fd) { + BIO *bio = BIO_new(BIO_s_socket()); + if (bio == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB); + return 0; + } + BIO_set_fd(bio, fd, BIO_NOCLOSE); + SSL_set_bio(ssl, bio, wbio); + } else { + SSL_set_bio(ssl, wbio, wbio); + } + return 1; +} + +size_t SSL_get_finished(const SSL *ssl, void *buf, size_t count) { + size_t ret = 0; + + if (ssl->s3 != NULL) { + ret = ssl->s3->tmp.finish_md_len; + if (count > ret) { + count = ret; + } + memcpy(buf, ssl->s3->tmp.finish_md, count); + } + + return ret; +} + +size_t SSL_get_peer_finished(const SSL *ssl, void *buf, size_t count) { + size_t ret = 0; + + if (ssl->s3 != NULL) { + ret = ssl->s3->tmp.peer_finish_md_len; + if (count > ret) { + count = ret; + } + memcpy(buf, ssl->s3->tmp.peer_finish_md, count); + } + + return ret; +} + +int SSL_get_verify_mode(const SSL *ssl) { return ssl->verify_mode; } + +int SSL_get_verify_depth(const SSL *ssl) { + return X509_VERIFY_PARAM_get_depth(ssl->param); +} + +int SSL_get_extms_support(const SSL *ssl) { + return ssl->s3->tmp.extended_master_secret == 1; +} + +int (*SSL_get_verify_callback(const SSL *ssl))(int, X509_STORE_CTX *) { + return ssl->verify_callback; +} + +int SSL_CTX_get_verify_mode(const SSL_CTX *ctx) { return ctx->verify_mode; } + +int SSL_CTX_get_verify_depth(const SSL_CTX *ctx) { + return X509_VERIFY_PARAM_get_depth(ctx->param); +} + +int (*SSL_CTX_get_verify_callback(const SSL_CTX *ctx))( + int ok, X509_STORE_CTX *store_ctx) { + return ctx->default_verify_callback; +} + +void SSL_set_verify(SSL *ssl, int mode, + int (*callback)(int ok, X509_STORE_CTX *store_ctx)) { + ssl->verify_mode = mode; + if (callback != NULL) { + ssl->verify_callback = callback; + } +} + +void SSL_set_verify_depth(SSL *ssl, int depth) { + X509_VERIFY_PARAM_set_depth(ssl->param, depth); +} + +int SSL_CTX_get_read_ahead(const SSL_CTX *ctx) { return 0; } + +int SSL_get_read_ahead(const SSL *ssl) { return 0; } + +void SSL_CTX_set_read_ahead(SSL_CTX *ctx, int yes) { } + +void SSL_set_read_ahead(SSL *ssl, int yes) { } + +int SSL_pending(const SSL *ssl) { + if (ssl->s3->rrec.type != SSL3_RT_APPLICATION_DATA) { + return 0; + } + return ssl->s3->rrec.length; +} + +/* Fix this so it checks all the valid key/cert options */ +int SSL_CTX_check_private_key(const SSL_CTX *ctx) { + if (ctx->cert->x509 == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CERTIFICATE_ASSIGNED); + return 0; + } + + if (ctx->cert->privatekey == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_R_NO_PRIVATE_KEY_ASSIGNED); + return 0; + } + + return X509_check_private_key(ctx->cert->x509, ctx->cert->privatekey); +} + +/* Fix this function so that it takes an optional type parameter */ +int SSL_check_private_key(const SSL *ssl) { + if (ssl->cert->x509 == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CERTIFICATE_ASSIGNED); + return 0; + } + + if (ssl->cert->privatekey == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_R_NO_PRIVATE_KEY_ASSIGNED); + return 0; + } + + return X509_check_private_key(ssl->cert->x509, ssl->cert->privatekey); +} + +long SSL_get_default_timeout(const SSL *ssl) { + return SSL_DEFAULT_SESSION_TIMEOUT; +} + +int SSL_renegotiate(SSL *ssl) { + /* Caller-initiated renegotiation is not supported. */ + OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; +} + +int SSL_renegotiate_pending(SSL *ssl) { + return SSL_in_init(ssl) && ssl->s3->initial_handshake_complete; +} + +int SSL_total_renegotiations(const SSL *ssl) { + return ssl->s3->total_renegotiations; +} + +size_t SSL_CTX_get_max_cert_list(const SSL_CTX *ctx) { + return ctx->max_cert_list; +} + +void SSL_CTX_set_max_cert_list(SSL_CTX *ctx, size_t max_cert_list) { + if (max_cert_list > kMaxHandshakeSize) { + max_cert_list = kMaxHandshakeSize; + } + ctx->max_cert_list = (uint32_t)max_cert_list; +} + +size_t SSL_get_max_cert_list(const SSL *ssl) { + return ssl->max_cert_list; +} + +void SSL_set_max_cert_list(SSL *ssl, size_t max_cert_list) { + if (max_cert_list > kMaxHandshakeSize) { + max_cert_list = kMaxHandshakeSize; + } + ssl->max_cert_list = (uint32_t)max_cert_list; +} + +int SSL_CTX_set_max_send_fragment(SSL_CTX *ctx, size_t max_send_fragment) { + if (max_send_fragment < 512) { + max_send_fragment = 512; + } + if (max_send_fragment > SSL3_RT_MAX_PLAIN_LENGTH) { + max_send_fragment = SSL3_RT_MAX_PLAIN_LENGTH; + } + ctx->max_send_fragment = (uint16_t)max_send_fragment; + + return 1; +} + +int SSL_set_max_send_fragment(SSL *ssl, size_t max_send_fragment) { + if (max_send_fragment < 512) { + max_send_fragment = 512; + } + if (max_send_fragment > SSL3_RT_MAX_PLAIN_LENGTH) { + max_send_fragment = SSL3_RT_MAX_PLAIN_LENGTH; + } + ssl->max_send_fragment = (uint16_t)max_send_fragment; + + return 1; +} + +int SSL_set_mtu(SSL *ssl, unsigned mtu) { + if (!SSL_IS_DTLS(ssl) || mtu < dtls1_min_mtu()) { + return 0; + } + ssl->d1->mtu = mtu; + return 1; +} + +int SSL_get_secure_renegotiation_support(const SSL *ssl) { + return ssl->s3->send_connection_binding; +} + +LHASH_OF(SSL_SESSION) *SSL_CTX_sessions(SSL_CTX *ctx) { return ctx->sessions; } + +size_t SSL_CTX_sess_number(const SSL_CTX *ctx) { + return lh_SSL_SESSION_num_items(ctx->sessions); +} + +unsigned long SSL_CTX_sess_set_cache_size(SSL_CTX *ctx, unsigned long size) { + unsigned long ret = ctx->session_cache_size; + ctx->session_cache_size = size; + return ret; +} + +unsigned long SSL_CTX_sess_get_cache_size(const SSL_CTX *ctx) { + return ctx->session_cache_size; +} + +int SSL_CTX_set_session_cache_mode(SSL_CTX *ctx, int mode) { + int ret = ctx->session_cache_mode; + ctx->session_cache_mode = mode; + return ret; +} + +int SSL_CTX_get_session_cache_mode(const SSL_CTX *ctx) { + return ctx->session_cache_mode; +} + + +int SSL_CTX_get_tlsext_ticket_keys(SSL_CTX *ctx, void *out, size_t len) { + if (out == NULL) { + return 48; + } + if (len != 48) { + OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_TICKET_KEYS_LENGTH); + return 0; + } + uint8_t *out_bytes = out; + memcpy(out_bytes, ctx->tlsext_tick_key_name, 16); + memcpy(out_bytes + 16, ctx->tlsext_tick_hmac_key, 16); + memcpy(out_bytes + 32, ctx->tlsext_tick_aes_key, 16); + return 1; +} + +int SSL_CTX_set_tlsext_ticket_keys(SSL_CTX *ctx, const void *in, size_t len) { + if (in == NULL) { + return 48; + } + if (len != 48) { + OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_TICKET_KEYS_LENGTH); + return 0; + } + const uint8_t *in_bytes = in; + memcpy(ctx->tlsext_tick_key_name, in_bytes, 16); + memcpy(ctx->tlsext_tick_hmac_key, in_bytes + 16, 16); + memcpy(ctx->tlsext_tick_aes_key, in_bytes + 32, 16); + return 1; +} + +int SSL_CTX_set_tlsext_ticket_key_cb( + SSL_CTX *ctx, int (*callback)(SSL *ssl, uint8_t *key_name, uint8_t *iv, + EVP_CIPHER_CTX *ctx, HMAC_CTX *hmac_ctx, + int encrypt)) { + ctx->tlsext_ticket_key_cb = callback; + return 1; +} + +int SSL_CTX_set1_curves(SSL_CTX *ctx, const int *curves, size_t curves_len) { + return tls1_set_curves(&ctx->supported_group_list, + &ctx->supported_group_list_len, curves, + curves_len); +} + +int SSL_set1_curves(SSL *ssl, const int *curves, size_t curves_len) { + return tls1_set_curves(&ssl->supported_group_list, + &ssl->supported_group_list_len, curves, + curves_len); +} + +int SSL_CTX_set_tmp_dh(SSL_CTX *ctx, const DH *dh) { + DH_free(ctx->cert->dh_tmp); + ctx->cert->dh_tmp = DHparams_dup(dh); + if (ctx->cert->dh_tmp == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_DH_LIB); + return 0; + } + return 1; +} + +int SSL_set_tmp_dh(SSL *ssl, const DH *dh) { + DH_free(ssl->cert->dh_tmp); + ssl->cert->dh_tmp = DHparams_dup(dh); + if (ssl->cert->dh_tmp == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_DH_LIB); + return 0; + } + return 1; +} + +STACK_OF(SSL_CIPHER) *SSL_get_ciphers(const SSL *ssl) { + if (ssl == NULL) { + return NULL; + } + + if (ssl->cipher_list != NULL) { + return ssl->cipher_list->ciphers; + } + + if (ssl->version >= TLS1_1_VERSION && ssl->ctx->cipher_list_tls11 != NULL) { + return ssl->ctx->cipher_list_tls11->ciphers; + } + + if (ssl->version >= TLS1_VERSION && ssl->ctx->cipher_list_tls10 != NULL) { + return ssl->ctx->cipher_list_tls10->ciphers; + } + + if (ssl->ctx->cipher_list != NULL) { + return ssl->ctx->cipher_list->ciphers; + } + + return NULL; +} + +/* return a STACK of the ciphers available for the SSL and in order of + * algorithm id */ +STACK_OF(SSL_CIPHER) *ssl_get_ciphers_by_id(SSL *ssl) { + if (ssl == NULL) { + return NULL; + } + + if (ssl->cipher_list_by_id != NULL) { + return ssl->cipher_list_by_id; + } + + if (ssl->ctx->cipher_list_by_id != NULL) { + return ssl->ctx->cipher_list_by_id; + } + + return NULL; +} + +const char *SSL_get_cipher_list(const SSL *ssl, int n) { + const SSL_CIPHER *c; + STACK_OF(SSL_CIPHER) *sk; + + if (ssl == NULL) { + return NULL; + } + + sk = SSL_get_ciphers(ssl); + if (sk == NULL || n < 0 || (size_t)n >= sk_SSL_CIPHER_num(sk)) { + return NULL; + } + + c = sk_SSL_CIPHER_value(sk, n); + if (c == NULL) { + return NULL; + } + + return c->name; +} + +int SSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str) { + STACK_OF(SSL_CIPHER) *cipher_list = ssl_create_cipher_list( + ctx->method, &ctx->cipher_list, &ctx->cipher_list_by_id, str); + if (cipher_list == NULL) { + return 0; + } + + /* |ssl_create_cipher_list| may succeed but return an empty cipher list. */ + if (sk_SSL_CIPHER_num(cipher_list) == 0) { + OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CIPHER_MATCH); + return 0; + } + + return 1; +} + +int SSL_CTX_set_cipher_list_tls10(SSL_CTX *ctx, const char *str) { + STACK_OF(SSL_CIPHER) *cipher_list = ssl_create_cipher_list( + ctx->method, &ctx->cipher_list_tls10, NULL, str); + if (cipher_list == NULL) { + return 0; + } + + /* |ssl_create_cipher_list| may succeed but return an empty cipher list. */ + if (sk_SSL_CIPHER_num(cipher_list) == 0) { + OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CIPHER_MATCH); + return 0; + } + + return 1; +} + +int SSL_CTX_set_cipher_list_tls11(SSL_CTX *ctx, const char *str) { + STACK_OF(SSL_CIPHER) *cipher_list = ssl_create_cipher_list( + ctx->method, &ctx->cipher_list_tls11, NULL, str); + if (cipher_list == NULL) { + return 0; + } + + /* |ssl_create_cipher_list| may succeed but return an empty cipher list. */ + if (sk_SSL_CIPHER_num(cipher_list) == 0) { + OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CIPHER_MATCH); + return 0; + } + + return 1; +} + +int SSL_set_cipher_list(SSL *ssl, const char *str) { + STACK_OF(SSL_CIPHER) *cipher_list = ssl_create_cipher_list( + ssl->ctx->method, &ssl->cipher_list, &ssl->cipher_list_by_id, str); + if (cipher_list == NULL) { + return 0; + } + + /* |ssl_create_cipher_list| may succeed but return an empty cipher list. */ + if (sk_SSL_CIPHER_num(cipher_list) == 0) { + OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CIPHER_MATCH); + return 0; + } + + return 1; +} + +STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *ssl, const CBS *cbs) { + CBS cipher_suites = *cbs; + const SSL_CIPHER *c; + STACK_OF(SSL_CIPHER) *sk; + + if (ssl->s3) { + ssl->s3->send_connection_binding = 0; + } + + if (CBS_len(&cipher_suites) % 2 != 0) { + OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST); + return NULL; + } + + sk = sk_SSL_CIPHER_new_null(); + if (sk == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + goto err; + } + + while (CBS_len(&cipher_suites) > 0) { + uint16_t cipher_suite; + + if (!CBS_get_u16(&cipher_suites, &cipher_suite)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + goto err; + } + + /* Check for SCSV. */ + if (ssl->s3 && cipher_suite == (SSL3_CK_SCSV & 0xffff)) { + /* SCSV is fatal if renegotiating. */ + if (ssl->s3->initial_handshake_complete) { + OPENSSL_PUT_ERROR(SSL, SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING); + ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); + goto err; + } + ssl->s3->send_connection_binding = 1; + continue; + } + + /* Check for FALLBACK_SCSV. */ + if (ssl->s3 && cipher_suite == (SSL3_CK_FALLBACK_SCSV & 0xffff)) { + uint16_t max_version = ssl3_get_max_server_version(ssl); + if (SSL_IS_DTLS(ssl) ? (uint16_t)ssl->version > max_version + : (uint16_t)ssl->version < max_version) { + OPENSSL_PUT_ERROR(SSL, SSL_R_INAPPROPRIATE_FALLBACK); + ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL3_AD_INAPPROPRIATE_FALLBACK); + goto err; + } + continue; + } + + c = SSL_get_cipher_by_value(cipher_suite); + if (c != NULL && !sk_SSL_CIPHER_push(sk, c)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + goto err; + } + } + + return sk; + +err: + sk_SSL_CIPHER_free(sk); + return NULL; +} + +const char *SSL_get_servername(const SSL *ssl, const int type) { + if (type != TLSEXT_NAMETYPE_host_name) { + return NULL; + } + + /* Historically, |SSL_get_servername| was also the configuration getter + * corresponding to |SSL_set_tlsext_host_name|. */ + if (ssl->tlsext_hostname != NULL) { + return ssl->tlsext_hostname; + } + + if (ssl->session == NULL) { + return NULL; + } + return ssl->session->tlsext_hostname; +} + +int SSL_get_servername_type(const SSL *ssl) { + if (ssl->session != NULL && ssl->session->tlsext_hostname != NULL) { + return TLSEXT_NAMETYPE_host_name; + } + + return -1; +} + +void SSL_CTX_enable_signed_cert_timestamps(SSL_CTX *ctx) { + ctx->signed_cert_timestamps_enabled = 1; +} + +int SSL_enable_signed_cert_timestamps(SSL *ssl) { + ssl->signed_cert_timestamps_enabled = 1; + return 1; +} + +void SSL_CTX_enable_ocsp_stapling(SSL_CTX *ctx) { + ctx->ocsp_stapling_enabled = 1; +} + +int SSL_enable_ocsp_stapling(SSL *ssl) { + ssl->ocsp_stapling_enabled = 1; + return 1; +} + +void SSL_get0_signed_cert_timestamp_list(const SSL *ssl, const uint8_t **out, + size_t *out_len) { + SSL_SESSION *session = ssl->session; + + *out_len = 0; + *out = NULL; + if (ssl->server || !session || !session->tlsext_signed_cert_timestamp_list) { + return; + } + + *out = session->tlsext_signed_cert_timestamp_list; + *out_len = session->tlsext_signed_cert_timestamp_list_length; +} + +void SSL_get0_ocsp_response(const SSL *ssl, const uint8_t **out, + size_t *out_len) { + SSL_SESSION *session = ssl->session; + + *out_len = 0; + *out = NULL; + if (ssl->server || !session || !session->ocsp_response) { + return; + } + *out = session->ocsp_response; + *out_len = session->ocsp_response_length; +} + +int SSL_CTX_set_signed_cert_timestamp_list(SSL_CTX *ctx, const uint8_t *list, + size_t list_len) { + OPENSSL_free(ctx->signed_cert_timestamp_list); + ctx->signed_cert_timestamp_list_length = 0; + + ctx->signed_cert_timestamp_list = BUF_memdup(list, list_len); + if (ctx->signed_cert_timestamp_list == NULL) { + return 0; + } + ctx->signed_cert_timestamp_list_length = list_len; + + return 1; +} + +int SSL_CTX_set_ocsp_response(SSL_CTX *ctx, const uint8_t *response, + size_t response_len) { + OPENSSL_free(ctx->ocsp_response); + ctx->ocsp_response_length = 0; + + ctx->ocsp_response = BUF_memdup(response, response_len); + if (ctx->ocsp_response == NULL) { + return 0; + } + ctx->ocsp_response_length = response_len; + + return 1; +} + +int SSL_set_tlsext_host_name(SSL *ssl, const char *name) { + OPENSSL_free(ssl->tlsext_hostname); + ssl->tlsext_hostname = NULL; + + if (name == NULL) { + return 1; + } + + size_t len = strlen(name); + if (len == 0 || len > TLSEXT_MAXLEN_host_name) { + OPENSSL_PUT_ERROR(SSL, SSL_R_SSL3_EXT_INVALID_SERVERNAME); + return 0; + } + ssl->tlsext_hostname = BUF_strdup(name); + if (ssl->tlsext_hostname == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + return 0; + } + return 1; +} + +int SSL_CTX_set_tlsext_servername_callback( + SSL_CTX *ctx, int (*callback)(SSL *ssl, int *out_alert, void *arg)) { + ctx->tlsext_servername_callback = callback; + return 1; +} + +int SSL_CTX_set_tlsext_servername_arg(SSL_CTX *ctx, void *arg) { + ctx->tlsext_servername_arg = arg; + return 1; +} + +int SSL_select_next_proto(uint8_t **out, uint8_t *out_len, + const uint8_t *server, unsigned server_len, + const uint8_t *client, unsigned client_len) { + unsigned int i, j; + const uint8_t *result; + int status = OPENSSL_NPN_UNSUPPORTED; + + /* For each protocol in server preference order, see if we support it. */ + for (i = 0; i < server_len;) { + for (j = 0; j < client_len;) { + if (server[i] == client[j] && + memcmp(&server[i + 1], &client[j + 1], server[i]) == 0) { + /* We found a match */ + result = &server[i]; + status = OPENSSL_NPN_NEGOTIATED; + goto found; + } + j += client[j]; + j++; + } + i += server[i]; + i++; + } + + /* There's no overlap between our protocols and the server's list. */ + result = client; + status = OPENSSL_NPN_NO_OVERLAP; + +found: + *out = (uint8_t *)result + 1; + *out_len = result[0]; + return status; +} + +void SSL_get0_next_proto_negotiated(const SSL *ssl, const uint8_t **out_data, + unsigned *out_len) { + *out_data = ssl->s3->next_proto_negotiated; + if (*out_data == NULL) { + *out_len = 0; + } else { + *out_len = ssl->s3->next_proto_negotiated_len; + } +} + +void SSL_CTX_set_next_protos_advertised_cb( + SSL_CTX *ctx, + int (*cb)(SSL *ssl, const uint8_t **out, unsigned *out_len, void *arg), + void *arg) { + ctx->next_protos_advertised_cb = cb; + ctx->next_protos_advertised_cb_arg = arg; +} + +void SSL_CTX_set_next_proto_select_cb( + SSL_CTX *ctx, int (*cb)(SSL *ssl, uint8_t **out, uint8_t *out_len, + const uint8_t *in, unsigned in_len, void *arg), + void *arg) { + ctx->next_proto_select_cb = cb; + ctx->next_proto_select_cb_arg = arg; +} + +int SSL_CTX_set_alpn_protos(SSL_CTX *ctx, const uint8_t *protos, + unsigned protos_len) { + OPENSSL_free(ctx->alpn_client_proto_list); + ctx->alpn_client_proto_list = BUF_memdup(protos, protos_len); + if (!ctx->alpn_client_proto_list) { + return 1; + } + ctx->alpn_client_proto_list_len = protos_len; + + return 0; +} + +int SSL_set_alpn_protos(SSL *ssl, const uint8_t *protos, unsigned protos_len) { + OPENSSL_free(ssl->alpn_client_proto_list); + ssl->alpn_client_proto_list = BUF_memdup(protos, protos_len); + if (!ssl->alpn_client_proto_list) { + return 1; + } + ssl->alpn_client_proto_list_len = protos_len; + + return 0; +} + +void SSL_CTX_set_alpn_select_cb(SSL_CTX *ctx, + int (*cb)(SSL *ssl, const uint8_t **out, + uint8_t *out_len, const uint8_t *in, + unsigned in_len, void *arg), + void *arg) { + ctx->alpn_select_cb = cb; + ctx->alpn_select_cb_arg = arg; +} + +void SSL_get0_alpn_selected(const SSL *ssl, const uint8_t **out_data, + unsigned *out_len) { + *out_data = NULL; + if (ssl->s3) { + *out_data = ssl->s3->alpn_selected; + } + if (*out_data == NULL) { + *out_len = 0; + } else { + *out_len = ssl->s3->alpn_selected_len; + } +} + + +int SSL_CTX_enable_tls_channel_id(SSL_CTX *ctx) { + ctx->tlsext_channel_id_enabled = 1; + return 1; +} + +int SSL_enable_tls_channel_id(SSL *ssl) { + ssl->tlsext_channel_id_enabled = 1; + return 1; +} + +static int is_p256_key(EVP_PKEY *private_key) { + const EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(private_key); + return ec_key != NULL && + EC_GROUP_get_curve_name(EC_KEY_get0_group(ec_key)) == + NID_X9_62_prime256v1; +} + +int SSL_CTX_set1_tls_channel_id(SSL_CTX *ctx, EVP_PKEY *private_key) { + if (!is_p256_key(private_key)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_CHANNEL_ID_NOT_P256); + return 0; + } + + EVP_PKEY_free(ctx->tlsext_channel_id_private); + ctx->tlsext_channel_id_private = EVP_PKEY_up_ref(private_key); + ctx->tlsext_channel_id_enabled = 1; + + return 1; +} + +int SSL_set1_tls_channel_id(SSL *ssl, EVP_PKEY *private_key) { + if (!is_p256_key(private_key)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_CHANNEL_ID_NOT_P256); + return 0; + } + + EVP_PKEY_free(ssl->tlsext_channel_id_private); + ssl->tlsext_channel_id_private = EVP_PKEY_up_ref(private_key); + ssl->tlsext_channel_id_enabled = 1; + + return 1; +} + +size_t SSL_get_tls_channel_id(SSL *ssl, uint8_t *out, size_t max_out) { + if (!ssl->s3->tlsext_channel_id_valid) { + return 0; + } + memcpy(out, ssl->s3->tlsext_channel_id, (max_out < 64) ? max_out : 64); + return 64; +} + +void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx, + int (*cb)(X509_STORE_CTX *store_ctx, + void *arg), + void *arg) { + ctx->app_verify_callback = cb; + ctx->app_verify_arg = arg; +} + +void SSL_CTX_set_verify(SSL_CTX *ctx, int mode, + int (*cb)(int, X509_STORE_CTX *)) { + ctx->verify_mode = mode; + ctx->default_verify_callback = cb; +} + +void SSL_CTX_set_verify_depth(SSL_CTX *ctx, int depth) { + X509_VERIFY_PARAM_set_depth(ctx->param, depth); +} + +void SSL_CTX_set_cert_cb(SSL_CTX *ctx, int (*cb)(SSL *ssl, void *arg), + void *arg) { + ssl_cert_set_cert_cb(ctx->cert, cb, arg); +} + +void SSL_set_cert_cb(SSL *ssl, int (*cb)(SSL *ssl, void *arg), void *arg) { + ssl_cert_set_cert_cb(ssl->cert, cb, arg); +} + +size_t SSL_get0_certificate_types(SSL *ssl, const uint8_t **out_types) { + if (ssl->server || !ssl->s3->tmp.cert_req) { + *out_types = NULL; + return 0; + } + *out_types = ssl->s3->tmp.certificate_types; + return ssl->s3->tmp.num_certificate_types; +} + +void ssl_get_compatible_server_ciphers(SSL *ssl, uint32_t *out_mask_k, + uint32_t *out_mask_a) { + uint32_t mask_k = 0; + uint32_t mask_a = 0; + + if (ssl->cert->x509 != NULL && ssl_has_private_key(ssl)) { + if (ssl_private_key_type(ssl) == EVP_PKEY_RSA) { + mask_k |= SSL_kRSA; + mask_a |= SSL_aRSA; + } else if (ssl_private_key_type(ssl) == EVP_PKEY_EC) { + /* An ECC certificate may be usable for ECDSA cipher suites depending on + * the key usage extension and on the client's group preferences. */ + X509 *x = ssl->cert->x509; + /* This call populates extension flags (ex_flags). */ + X509_check_purpose(x, -1, 0); + int ecdsa_ok = (x->ex_flags & EXFLAG_KUSAGE) + ? (x->ex_kusage & X509v3_KU_DIGITAL_SIGNATURE) + : 1; + if (ecdsa_ok && tls1_check_ec_cert(ssl, x)) { + mask_a |= SSL_aECDSA; + } + } + } + + if (ssl->cert->dh_tmp != NULL || ssl->cert->dh_tmp_cb != NULL) { + mask_k |= SSL_kDHE; + } + + /* Check for a shared group to consider ECDHE ciphers. */ + uint16_t unused; + if (tls1_get_shared_group(ssl, &unused)) { + mask_k |= SSL_kECDHE; + } + + /* CECPQ1 ciphers are always acceptable if supported by both sides. */ + mask_k |= SSL_kCECPQ1; + + /* PSK requires a server callback. */ + if (ssl->psk_server_callback != NULL) { + mask_k |= SSL_kPSK; + mask_a |= SSL_aPSK; + } + + *out_mask_k = mask_k; + *out_mask_a = mask_a; +} + +void ssl_update_cache(SSL *ssl, int mode) { + SSL_CTX *ctx = ssl->initial_ctx; + /* Never cache sessions with empty session IDs. */ + if (ssl->session->session_id_length == 0 || + (ctx->session_cache_mode & mode) != mode) { + return; + } + + /* Clients never use the internal session cache. */ + int use_internal_cache = ssl->server && !(ctx->session_cache_mode & + SSL_SESS_CACHE_NO_INTERNAL_STORE); + + /* A client may see new sessions on abbreviated handshakes if the server + * decides to renew the ticket. Once the handshake is completed, it should be + * inserted into the cache. */ + if (!ssl->hit || (!ssl->server && ssl->tlsext_ticket_expected)) { + if (use_internal_cache) { + SSL_CTX_add_session(ctx, ssl->session); + } + if (ctx->new_session_cb != NULL && + !ctx->new_session_cb(ssl, SSL_SESSION_up_ref(ssl->session))) { + /* |new_session_cb|'s return value signals whether it took ownership. */ + SSL_SESSION_free(ssl->session); + } + } + + if (use_internal_cache && + !(ctx->session_cache_mode & SSL_SESS_CACHE_NO_AUTO_CLEAR)) { + /* Automatically flush the internal session cache every 255 connections. */ + int flush_cache = 0; + CRYPTO_MUTEX_lock_write(&ctx->lock); + ctx->handshakes_since_cache_flush++; + if (ctx->handshakes_since_cache_flush >= 255) { + flush_cache = 1; + ctx->handshakes_since_cache_flush = 0; + } + CRYPTO_MUTEX_unlock_write(&ctx->lock); + + if (flush_cache) { + SSL_CTX_flush_sessions(ctx, (unsigned long)time(NULL)); + } + } +} + +static const char *ssl_get_version(int version) { + switch (version) { + case TLS1_3_VERSION: + return "TLSv1.3"; + + case TLS1_2_VERSION: + return "TLSv1.2"; + + case TLS1_1_VERSION: + return "TLSv1.1"; + + case TLS1_VERSION: + return "TLSv1"; + + case SSL3_VERSION: + return "SSLv3"; + + case DTLS1_VERSION: + return "DTLSv1"; + + case DTLS1_2_VERSION: + return "DTLSv1.2"; + + default: + return "unknown"; + } +} + +const char *SSL_get_version(const SSL *ssl) { + return ssl_get_version(ssl->version); +} + +const char *SSL_SESSION_get_version(const SSL_SESSION *session) { + return ssl_get_version(session->ssl_version); +} + +X509 *SSL_get_certificate(const SSL *ssl) { + if (ssl->cert != NULL) { + return ssl->cert->x509; + } + + return NULL; +} + +EVP_PKEY *SSL_get_privatekey(const SSL *ssl) { + if (ssl->cert != NULL) { + return ssl->cert->privatekey; + } + + return NULL; +} + +X509 *SSL_CTX_get0_certificate(const SSL_CTX *ctx) { + if (ctx->cert != NULL) { + return ctx->cert->x509; + } + + return NULL; +} + +EVP_PKEY *SSL_CTX_get0_privatekey(const SSL_CTX *ctx) { + if (ctx->cert != NULL) { + return ctx->cert->privatekey; + } + + return NULL; +} + +const SSL_CIPHER *SSL_get_current_cipher(const SSL *ssl) { + if (ssl->s3->aead_write_ctx == NULL) { + return NULL; + } + return ssl->s3->aead_write_ctx->cipher; +} + +int SSL_session_reused(const SSL *ssl) { + return ssl->hit; +} + +const COMP_METHOD *SSL_get_current_compression(SSL *ssl) { return NULL; } + +const COMP_METHOD *SSL_get_current_expansion(SSL *ssl) { return NULL; } + +int *SSL_get_server_tmp_key(SSL *ssl, EVP_PKEY **out_key) { return 0; } + +int ssl_is_wbio_buffered(const SSL *ssl) { + return ssl->bbio != NULL; +} + +int ssl_init_wbio_buffer(SSL *ssl) { + if (ssl->bbio != NULL) { + /* Already buffered. */ + assert(ssl->bbio == ssl->wbio); + return 1; + } + + BIO *bbio = BIO_new(BIO_f_buffer()); + if (bbio == NULL || + !BIO_set_read_buffer_size(bbio, 1)) { + BIO_free(bbio); + return 0; + } + + ssl->bbio = bbio; + ssl->wbio = BIO_push(bbio, ssl->wbio); + return 1; +} + +void ssl_free_wbio_buffer(SSL *ssl) { + if (ssl->bbio == NULL) { + return; + } + + assert(ssl->bbio == ssl->wbio); + + ssl->wbio = BIO_pop(ssl->wbio); + BIO_free(ssl->bbio); + ssl->bbio = NULL; +} + +void SSL_CTX_set_quiet_shutdown(SSL_CTX *ctx, int mode) { + ctx->quiet_shutdown = (mode != 0); +} + +int SSL_CTX_get_quiet_shutdown(const SSL_CTX *ctx) { + return ctx->quiet_shutdown; +} + +void SSL_set_quiet_shutdown(SSL *ssl, int mode) { + ssl->quiet_shutdown = (mode != 0); +} + +int SSL_get_quiet_shutdown(const SSL *ssl) { return ssl->quiet_shutdown; } + +void SSL_set_shutdown(SSL *ssl, int mode) { + /* It is an error to clear any bits that have already been set. (We can't try + * to get a second close_notify or send two.) */ + assert((SSL_get_shutdown(ssl) & mode) == SSL_get_shutdown(ssl)); + + if (mode & SSL_RECEIVED_SHUTDOWN && + ssl->s3->recv_shutdown == ssl_shutdown_none) { + ssl->s3->recv_shutdown = ssl_shutdown_close_notify; + } + + if (mode & SSL_SENT_SHUTDOWN && + ssl->s3->send_shutdown == ssl_shutdown_none) { + ssl->s3->send_shutdown = ssl_shutdown_close_notify; + } +} + +int SSL_get_shutdown(const SSL *ssl) { + int ret = 0; + if (ssl->s3->recv_shutdown != ssl_shutdown_none) { + /* Historically, OpenSSL set |SSL_RECEIVED_SHUTDOWN| on both close_notify + * and fatal alert. */ + ret |= SSL_RECEIVED_SHUTDOWN; + } + if (ssl->s3->send_shutdown == ssl_shutdown_close_notify) { + /* Historically, OpenSSL set |SSL_SENT_SHUTDOWN| on only close_notify. */ + ret |= SSL_SENT_SHUTDOWN; + } + return ret; +} + +int SSL_version(const SSL *ssl) { return ssl->version; } + +SSL_CTX *SSL_get_SSL_CTX(const SSL *ssl) { return ssl->ctx; } + +SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX *ctx) { + if (ssl->ctx == ctx) { + return ssl->ctx; + } + + if (ctx == NULL) { + ctx = ssl->initial_ctx; + } + + ssl_cert_free(ssl->cert); + ssl->cert = ssl_cert_dup(ctx->cert); + + CRYPTO_refcount_inc(&ctx->references); + SSL_CTX_free(ssl->ctx); /* decrement reference count */ + ssl->ctx = ctx; + + ssl->sid_ctx_length = ctx->sid_ctx_length; + assert(ssl->sid_ctx_length <= sizeof(ssl->sid_ctx)); + memcpy(ssl->sid_ctx, ctx->sid_ctx, sizeof(ssl->sid_ctx)); + + return ssl->ctx; +} + +int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx) { + return X509_STORE_set_default_paths(ctx->cert_store); +} + +int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *ca_file, + const char *ca_dir) { + return X509_STORE_load_locations(ctx->cert_store, ca_file, ca_dir); +} + +void SSL_set_info_callback(SSL *ssl, + void (*cb)(const SSL *ssl, int type, int value)) { + ssl->info_callback = cb; +} + +void (*SSL_get_info_callback(const SSL *ssl))(const SSL *ssl, int type, + int value) { + return ssl->info_callback; +} + +int SSL_state(const SSL *ssl) { return ssl->state; } + +void SSL_set_state(SSL *ssl, int state) { } + +char *SSL_get_shared_ciphers(const SSL *ssl, char *buf, int len) { + if (len <= 0) { + return NULL; + } + buf[0] = '\0'; + return buf; +} + +void SSL_set_verify_result(SSL *ssl, long result) { + ssl->verify_result = result; +} + +long SSL_get_verify_result(const SSL *ssl) { return ssl->verify_result; } + +int SSL_get_ex_new_index(long argl, void *argp, CRYPTO_EX_unused *unused, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) { + int index; + if (!CRYPTO_get_ex_new_index(&g_ex_data_class_ssl, &index, argl, argp, + dup_func, free_func)) { + return -1; + } + return index; +} + +int SSL_set_ex_data(SSL *ssl, int idx, void *arg) { + return CRYPTO_set_ex_data(&ssl->ex_data, idx, arg); +} + +void *SSL_get_ex_data(const SSL *ssl, int idx) { + return CRYPTO_get_ex_data(&ssl->ex_data, idx); +} + +int SSL_CTX_get_ex_new_index(long argl, void *argp, CRYPTO_EX_unused *unused, + CRYPTO_EX_dup *dup_func, + CRYPTO_EX_free *free_func) { + int index; + if (!CRYPTO_get_ex_new_index(&g_ex_data_class_ssl_ctx, &index, argl, argp, + dup_func, free_func)) { + return -1; + } + return index; +} + +int SSL_CTX_set_ex_data(SSL_CTX *ctx, int idx, void *arg) { + return CRYPTO_set_ex_data(&ctx->ex_data, idx, arg); +} + +void *SSL_CTX_get_ex_data(const SSL_CTX *ctx, int idx) { + return CRYPTO_get_ex_data(&ctx->ex_data, idx); +} + +X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *ctx) { + return ctx->cert_store; +} + +void SSL_CTX_set_cert_store(SSL_CTX *ctx, X509_STORE *store) { + X509_STORE_free(ctx->cert_store); + ctx->cert_store = store; +} + +int SSL_want(const SSL *ssl) { return ssl->rwstate; } + +void SSL_CTX_set_tmp_rsa_callback(SSL_CTX *ctx, + RSA *(*cb)(SSL *ssl, int is_export, + int keylength)) { +} + +void SSL_set_tmp_rsa_callback(SSL *ssl, RSA *(*cb)(SSL *ssl, int is_export, + int keylength)) { +} + +void SSL_CTX_set_tmp_dh_callback(SSL_CTX *ctx, + DH *(*callback)(SSL *ssl, int is_export, + int keylength)) { + ctx->cert->dh_tmp_cb = callback; +} + +void SSL_set_tmp_dh_callback(SSL *ssl, DH *(*callback)(SSL *ssl, int is_export, + int keylength)) { + ssl->cert->dh_tmp_cb = callback; +} + +int SSL_CTX_use_psk_identity_hint(SSL_CTX *ctx, const char *identity_hint) { + if (identity_hint != NULL && strlen(identity_hint) > PSK_MAX_IDENTITY_LEN) { + OPENSSL_PUT_ERROR(SSL, SSL_R_DATA_LENGTH_TOO_LONG); + return 0; + } + + OPENSSL_free(ctx->psk_identity_hint); + + if (identity_hint != NULL) { + ctx->psk_identity_hint = BUF_strdup(identity_hint); + if (ctx->psk_identity_hint == NULL) { + return 0; + } + } else { + ctx->psk_identity_hint = NULL; + } + + return 1; +} + +int SSL_use_psk_identity_hint(SSL *ssl, const char *identity_hint) { + if (ssl == NULL) { + return 0; + } + + if (identity_hint != NULL && strlen(identity_hint) > PSK_MAX_IDENTITY_LEN) { + OPENSSL_PUT_ERROR(SSL, SSL_R_DATA_LENGTH_TOO_LONG); + return 0; + } + + /* Clear currently configured hint, if any. */ + OPENSSL_free(ssl->psk_identity_hint); + ssl->psk_identity_hint = NULL; + + if (identity_hint != NULL) { + ssl->psk_identity_hint = BUF_strdup(identity_hint); + if (ssl->psk_identity_hint == NULL) { + return 0; + } + } + + return 1; +} + +const char *SSL_get_psk_identity_hint(const SSL *ssl) { + if (ssl == NULL) { + return NULL; + } + return ssl->psk_identity_hint; +} + +const char *SSL_get_psk_identity(const SSL *ssl) { + if (ssl == NULL || ssl->session == NULL) { + return NULL; + } + + return ssl->session->psk_identity; +} + +void SSL_set_psk_client_callback( + SSL *ssl, unsigned (*cb)(SSL *ssl, const char *hint, char *identity, + unsigned max_identity_len, uint8_t *psk, + unsigned max_psk_len)) { + ssl->psk_client_callback = cb; +} + +void SSL_CTX_set_psk_client_callback( + SSL_CTX *ctx, unsigned (*cb)(SSL *ssl, const char *hint, char *identity, + unsigned max_identity_len, uint8_t *psk, + unsigned max_psk_len)) { + ctx->psk_client_callback = cb; +} + +void SSL_set_psk_server_callback( + SSL *ssl, unsigned (*cb)(SSL *ssl, const char *identity, uint8_t *psk, + unsigned max_psk_len)) { + ssl->psk_server_callback = cb; +} + +void SSL_CTX_set_psk_server_callback( + SSL_CTX *ctx, unsigned (*cb)(SSL *ssl, const char *identity, + uint8_t *psk, unsigned max_psk_len)) { + ctx->psk_server_callback = cb; +} + +void SSL_CTX_set_msg_callback(SSL_CTX *ctx, + void (*cb)(int write_p, int version, + int content_type, const void *buf, + size_t len, SSL *ssl, void *arg)) { + ctx->msg_callback = cb; +} + +void SSL_CTX_set_msg_callback_arg(SSL_CTX *ctx, void *arg) { + ctx->msg_callback_arg = arg; +} + +void SSL_set_msg_callback(SSL *ssl, + void (*cb)(int write_p, int version, int content_type, + const void *buf, size_t len, SSL *ssl, + void *arg)) { + ssl->msg_callback = cb; +} + +void SSL_set_msg_callback_arg(SSL *ssl, void *arg) { + ssl->msg_callback_arg = arg; +} + +void SSL_CTX_set_keylog_callback(SSL_CTX *ctx, + void (*cb)(const SSL *ssl, const char *line)) { + ctx->keylog_callback = cb; +} + +void SSL_CTX_set_current_time_cb(SSL_CTX *ctx, + void (*cb)(const SSL *ssl, + struct timeval *out_clock)) { + ctx->current_time_cb = cb; +} + +static int cbb_add_hex(CBB *cbb, const uint8_t *in, size_t in_len) { + static const char hextable[] = "0123456789abcdef"; + uint8_t *out; + size_t i; + + if (!CBB_add_space(cbb, &out, in_len * 2)) { + return 0; + } + + for (i = 0; i < in_len; i++) { + *(out++) = (uint8_t)hextable[in[i] >> 4]; + *(out++) = (uint8_t)hextable[in[i] & 0xf]; + } + + return 1; +} + +int ssl_log_rsa_client_key_exchange(const SSL *ssl, + const uint8_t *encrypted_premaster, + size_t encrypted_premaster_len, + const uint8_t *premaster, + size_t premaster_len) { + if (ssl->ctx->keylog_callback == NULL) { + return 1; + } + + if (encrypted_premaster_len < 8) { + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + return 0; + } + + CBB cbb; + uint8_t *out; + size_t out_len; + if (!CBB_init(&cbb, 4 + 16 + 1 + premaster_len * 2 + 1) || + !CBB_add_bytes(&cbb, (const uint8_t *)"RSA ", 4) || + /* Only the first 8 bytes of the encrypted premaster secret are + * logged. */ + !cbb_add_hex(&cbb, encrypted_premaster, 8) || + !CBB_add_bytes(&cbb, (const uint8_t *)" ", 1) || + !cbb_add_hex(&cbb, premaster, premaster_len) || + !CBB_add_u8(&cbb, 0 /* NUL */) || + !CBB_finish(&cbb, &out, &out_len)) { + CBB_cleanup(&cbb); + return 0; + } + + ssl->ctx->keylog_callback(ssl, (const char *)out); + OPENSSL_free(out); + return 1; +} + +int ssl_log_master_secret(const SSL *ssl, const uint8_t *client_random, + size_t client_random_len, const uint8_t *master, + size_t master_len) { + if (ssl->ctx->keylog_callback == NULL) { + return 1; + } + + if (client_random_len != 32) { + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + return 0; + } + + CBB cbb; + uint8_t *out; + size_t out_len; + if (!CBB_init(&cbb, 14 + 64 + 1 + master_len * 2 + 1) || + !CBB_add_bytes(&cbb, (const uint8_t *)"CLIENT_RANDOM ", 14) || + !cbb_add_hex(&cbb, client_random, 32) || + !CBB_add_bytes(&cbb, (const uint8_t *)" ", 1) || + !cbb_add_hex(&cbb, master, master_len) || + !CBB_add_u8(&cbb, 0 /* NUL */) || + !CBB_finish(&cbb, &out, &out_len)) { + CBB_cleanup(&cbb); + return 0; + } + + ssl->ctx->keylog_callback(ssl, (const char *)out); + OPENSSL_free(out); + return 1; +} + +int SSL_is_init_finished(const SSL *ssl) { + return ssl->state == SSL_ST_OK; +} + +int SSL_in_init(const SSL *ssl) { + return (ssl->state & SSL_ST_INIT) != 0; +} + +int SSL_in_false_start(const SSL *ssl) { + return ssl->s3->tmp.in_false_start; +} + +int SSL_cutthrough_complete(const SSL *ssl) { + return SSL_in_false_start(ssl); +} + +void SSL_get_structure_sizes(size_t *ssl_size, size_t *ssl_ctx_size, + size_t *ssl_session_size) { + *ssl_size = sizeof(SSL); + *ssl_ctx_size = sizeof(SSL_CTX); + *ssl_session_size = sizeof(SSL_SESSION); +} + +int ssl3_can_false_start(const SSL *ssl) { + const SSL_CIPHER *const cipher = SSL_get_current_cipher(ssl); + + /* False Start only for TLS 1.2 with an ECDHE+AEAD cipher and ALPN or NPN. */ + return !SSL_IS_DTLS(ssl) && + SSL_version(ssl) == TLS1_2_VERSION && + (ssl->s3->alpn_selected || ssl->s3->next_proto_neg_seen) && + cipher != NULL && + cipher->algorithm_mkey == SSL_kECDHE && + cipher->algorithm_mac == SSL_AEAD; +} + +const SSL3_ENC_METHOD *ssl3_get_enc_method(uint16_t version) { + switch (version) { + case SSL3_VERSION: + return &SSLv3_enc_data; + + case TLS1_VERSION: + case TLS1_1_VERSION: + case TLS1_2_VERSION: + case TLS1_3_VERSION: + case DTLS1_VERSION: + case DTLS1_2_VERSION: + return &TLSv1_enc_data; + + default: + return NULL; + } +} + +uint16_t ssl3_get_max_server_version(const SSL *ssl) { + uint16_t max_version; + + if (SSL_IS_DTLS(ssl)) { + max_version = (ssl->max_version != 0) ? ssl->max_version : DTLS1_2_VERSION; + if (!(ssl->options & SSL_OP_NO_DTLSv1_2) && + DTLS1_2_VERSION >= max_version) { + return DTLS1_2_VERSION; + } + if (!(ssl->options & SSL_OP_NO_DTLSv1) && DTLS1_VERSION >= max_version) { + return DTLS1_VERSION; + } + return 0; + } + + max_version = (ssl->max_version != 0) ? ssl->max_version : TLS1_3_VERSION; + if (!(ssl->options & SSL_OP_NO_TLSv1_3) && TLS1_3_VERSION <= max_version) { + return TLS1_3_VERSION; + } + if (!(ssl->options & SSL_OP_NO_TLSv1_2) && TLS1_2_VERSION <= max_version) { + return TLS1_2_VERSION; + } + if (!(ssl->options & SSL_OP_NO_TLSv1_1) && TLS1_1_VERSION <= max_version) { + return TLS1_1_VERSION; + } + if (!(ssl->options & SSL_OP_NO_TLSv1) && TLS1_VERSION <= max_version) { + return TLS1_VERSION; + } + if (!(ssl->options & SSL_OP_NO_SSLv3) && SSL3_VERSION <= max_version) { + return SSL3_VERSION; + } + return 0; +} + +uint16_t ssl3_get_mutual_version(SSL *ssl, uint16_t client_version) { + uint16_t version = 0; + + if (SSL_IS_DTLS(ssl)) { + /* Clamp client_version to max_version. */ + if (ssl->max_version != 0 && client_version < ssl->max_version) { + client_version = ssl->max_version; + } + + if (client_version <= DTLS1_2_VERSION && + !(ssl->options & SSL_OP_NO_DTLSv1_2)) { + version = DTLS1_2_VERSION; + } else if (client_version <= DTLS1_VERSION && + !(ssl->options & SSL_OP_NO_DTLSv1)) { + version = DTLS1_VERSION; + } + + /* Check against min_version. */ + if (version != 0 && ssl->min_version != 0 && version > ssl->min_version) { + return 0; + } + return version; + } else { + /* Clamp client_version to max_version. */ + if (ssl->max_version != 0 && client_version > ssl->max_version) { + client_version = ssl->max_version; + } + + if (client_version >= TLS1_3_VERSION && + !(ssl->options & SSL_OP_NO_TLSv1_3)) { + version = TLS1_3_VERSION; + } else if (client_version >= TLS1_2_VERSION && + !(ssl->options & SSL_OP_NO_TLSv1_2)) { + version = TLS1_2_VERSION; + } else if (client_version >= TLS1_1_VERSION && + !(ssl->options & SSL_OP_NO_TLSv1_1)) { + version = TLS1_1_VERSION; + } else if (client_version >= TLS1_VERSION && + !(ssl->options & SSL_OP_NO_TLSv1)) { + version = TLS1_VERSION; + } else if (client_version >= SSL3_VERSION && + !(ssl->options & SSL_OP_NO_SSLv3)) { + version = SSL3_VERSION; + } + + /* Check against min_version. */ + if (version != 0 && ssl->min_version != 0 && version < ssl->min_version) { + return 0; + } + return version; + } +} + +uint16_t ssl3_get_max_client_version(SSL *ssl) { + uint32_t options = ssl->options; + uint16_t version = 0; + + /* OpenSSL's API for controlling versions entails blacklisting individual + * protocols. This has two problems. First, on the client, the protocol can + * only express a contiguous range of versions. Second, a library consumer + * trying to set a maximum version cannot disable protocol versions that get + * added in a future version of the library. + * + * To account for both of these, OpenSSL interprets the client-side bitmask + * as a min/max range by picking the lowest contiguous non-empty range of + * enabled protocols. Note that this means it is impossible to set a maximum + * version of TLS 1.2 in a future-proof way. + * + * By this scheme, the maximum version is the lowest version V such that V is + * enabled and V+1 is disabled or unimplemented. */ + if (SSL_IS_DTLS(ssl)) { + if (!(options & SSL_OP_NO_DTLSv1_2)) { + version = DTLS1_2_VERSION; + } + if (!(options & SSL_OP_NO_DTLSv1) && (options & SSL_OP_NO_DTLSv1_2)) { + version = DTLS1_VERSION; + } + if (ssl->max_version != 0 && version < ssl->max_version) { + version = ssl->max_version; + } + } else { + if (!(options & SSL_OP_NO_TLSv1_3)) { + version = TLS1_3_VERSION; + } + if (!(options & SSL_OP_NO_TLSv1_2) && (options & SSL_OP_NO_TLSv1_3)) { + version = TLS1_2_VERSION; + } + if (!(options & SSL_OP_NO_TLSv1_1) && (options & SSL_OP_NO_TLSv1_2)) { + version = TLS1_1_VERSION; + } + if (!(options & SSL_OP_NO_TLSv1) && (options & SSL_OP_NO_TLSv1_1)) { + version = TLS1_VERSION; + } + if (!(options & SSL_OP_NO_SSLv3) && (options & SSL_OP_NO_TLSv1)) { + version = SSL3_VERSION; + } + if (ssl->max_version != 0 && version > ssl->max_version) { + version = ssl->max_version; + } + } + + return version; +} + +int ssl3_is_version_enabled(SSL *ssl, uint16_t version) { + if (SSL_IS_DTLS(ssl)) { + if (ssl->max_version != 0 && version < ssl->max_version) { + return 0; + } + if (ssl->min_version != 0 && version > ssl->min_version) { + return 0; + } + + switch (version) { + case DTLS1_VERSION: + return !(ssl->options & SSL_OP_NO_DTLSv1); + + case DTLS1_2_VERSION: + return !(ssl->options & SSL_OP_NO_DTLSv1_2); + + default: + return 0; + } + } else { + if (ssl->max_version != 0 && version > ssl->max_version) { + return 0; + } + if (ssl->min_version != 0 && version < ssl->min_version) { + return 0; + } + + switch (version) { + case SSL3_VERSION: + return !(ssl->options & SSL_OP_NO_SSLv3); + + case TLS1_VERSION: + return !(ssl->options & SSL_OP_NO_TLSv1); + + case TLS1_1_VERSION: + return !(ssl->options & SSL_OP_NO_TLSv1_1); + + case TLS1_2_VERSION: + return !(ssl->options & SSL_OP_NO_TLSv1_2); + + case TLS1_3_VERSION: + return !(ssl->options & SSL_OP_NO_TLSv1_3); + + default: + return 0; + } + } +} + +uint16_t ssl3_version_from_wire(const SSL *ssl, uint16_t wire_version) { + if (!SSL_IS_DTLS(ssl)) { + return wire_version; + } + + uint16_t tls_version = ~wire_version; + uint16_t version = tls_version + 0x0201; + /* If either component overflowed, clamp it so comparisons still work. */ + if ((version >> 8) < (tls_version >> 8)) { + version = 0xff00 | (version & 0xff); + } + if ((version & 0xff) < (tls_version & 0xff)) { + version = (version & 0xff00) | 0xff; + } + /* DTLS 1.0 maps to TLS 1.1, not TLS 1.0. */ + if (version == TLS1_VERSION) { + version = TLS1_1_VERSION; + } + return version; +} + +uint16_t ssl3_protocol_version(const SSL *ssl) { + assert(ssl->s3->have_version); + return ssl3_version_from_wire(ssl, ssl->version); +} + +int SSL_is_server(SSL *ssl) { return ssl->server; } + +void SSL_CTX_set_select_certificate_cb( + SSL_CTX *ctx, int (*cb)(const struct ssl_early_callback_ctx *)) { + ctx->select_certificate_cb = cb; +} + +void SSL_CTX_set_dos_protection_cb( + SSL_CTX *ctx, int (*cb)(const struct ssl_early_callback_ctx *)) { + ctx->dos_protection_cb = cb; +} + +void SSL_set_renegotiate_mode(SSL *ssl, enum ssl_renegotiate_mode_t mode) { + ssl->renegotiate_mode = mode; +} + +void SSL_set_reject_peer_renegotiations(SSL *ssl, int reject) { + SSL_set_renegotiate_mode( + ssl, reject ? ssl_renegotiate_never : ssl_renegotiate_freely); +} + +int SSL_get_rc4_state(const SSL *ssl, const RC4_KEY **read_key, + const RC4_KEY **write_key) { + if (ssl->s3->aead_read_ctx == NULL || ssl->s3->aead_write_ctx == NULL) { + return 0; + } + + return EVP_AEAD_CTX_get_rc4_state(&ssl->s3->aead_read_ctx->ctx, read_key) && + EVP_AEAD_CTX_get_rc4_state(&ssl->s3->aead_write_ctx->ctx, write_key); +} + +int SSL_get_ivs(const SSL *ssl, const uint8_t **out_read_iv, + const uint8_t **out_write_iv, size_t *out_iv_len) { + if (ssl->s3->aead_read_ctx == NULL || ssl->s3->aead_write_ctx == NULL) { + return 0; + } + + size_t write_iv_len; + if (!EVP_AEAD_CTX_get_iv(&ssl->s3->aead_read_ctx->ctx, out_read_iv, + out_iv_len) || + !EVP_AEAD_CTX_get_iv(&ssl->s3->aead_write_ctx->ctx, out_write_iv, + &write_iv_len) || + *out_iv_len != write_iv_len) { + return 0; + } + + return 1; +} + +static uint64_t be_to_u64(const uint8_t in[8]) { + return (((uint64_t)in[0]) << 56) | (((uint64_t)in[1]) << 48) | + (((uint64_t)in[2]) << 40) | (((uint64_t)in[3]) << 32) | + (((uint64_t)in[4]) << 24) | (((uint64_t)in[5]) << 16) | + (((uint64_t)in[6]) << 8) | ((uint64_t)in[7]); +} + +uint64_t SSL_get_read_sequence(const SSL *ssl) { + /* TODO(davidben): Internally represent sequence numbers as uint64_t. */ + if (SSL_IS_DTLS(ssl)) { + /* max_seq_num already includes the epoch. */ + assert(ssl->d1->r_epoch == (ssl->d1->bitmap.max_seq_num >> 48)); + return ssl->d1->bitmap.max_seq_num; + } + return be_to_u64(ssl->s3->read_sequence); +} + +uint64_t SSL_get_write_sequence(const SSL *ssl) { + uint64_t ret = be_to_u64(ssl->s3->write_sequence); + if (SSL_IS_DTLS(ssl)) { + assert((ret >> 48) == 0); + ret |= ((uint64_t)ssl->d1->w_epoch) << 48; + } + return ret; +} + +uint8_t SSL_get_server_key_exchange_hash(const SSL *ssl) { + return ssl->s3->tmp.server_key_exchange_hash; +} + +size_t SSL_get_client_random(const SSL *ssl, uint8_t *out, size_t max_out) { + if (max_out == 0) { + return sizeof(ssl->s3->client_random); + } + if (max_out > sizeof(ssl->s3->client_random)) { + max_out = sizeof(ssl->s3->client_random); + } + memcpy(out, ssl->s3->client_random, max_out); + return max_out; +} + +size_t SSL_get_server_random(const SSL *ssl, uint8_t *out, size_t max_out) { + if (max_out == 0) { + return sizeof(ssl->s3->server_random); + } + if (max_out > sizeof(ssl->s3->server_random)) { + max_out = sizeof(ssl->s3->server_random); + } + memcpy(out, ssl->s3->server_random, max_out); + return max_out; +} + +const SSL_CIPHER *SSL_get_pending_cipher(const SSL *ssl) { + if (!SSL_in_init(ssl)) { + return NULL; + } + return ssl->s3->tmp.new_cipher; +} + +void SSL_CTX_set_retain_only_sha256_of_client_certs(SSL_CTX *ctx, int enabled) { + ctx->retain_only_sha256_of_client_certs = !!enabled; +} + +int SSL_clear(SSL *ssl) { + if (ssl->method == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_R_NO_METHOD_SPECIFIED); + return 0; + } + + if (ssl_clear_bad_session(ssl)) { + SSL_SESSION_free(ssl->session); + ssl->session = NULL; + } + + ssl->hit = 0; + + /* SSL_clear may be called before or after the |ssl| is initialized in either + * accept or connect state. In the latter case, SSL_clear should preserve the + * half and reset |ssl->state| accordingly. */ + if (ssl->handshake_func != NULL) { + if (ssl->server) { + SSL_set_accept_state(ssl); + } else { + SSL_set_connect_state(ssl); + } + } else { + assert(ssl->state == 0); + } + + /* TODO(davidben): Some state on |ssl| is reset both in |SSL_new| and + * |SSL_clear| because it is per-connection state rather than configuration + * state. Per-connection state should be on |ssl->s3| and |ssl->d1| so it is + * naturally reset at the right points between |SSL_new|, |SSL_clear|, and + * |ssl3_new|. */ + + ssl->rwstate = SSL_NOTHING; + + BUF_MEM_free(ssl->init_buf); + ssl->init_buf = NULL; + + /* The ssl->d1->mtu is simultaneously configuration (preserved across + * clear) and connection-specific state (gets reset). + * + * TODO(davidben): Avoid this. */ + unsigned mtu = 0; + if (ssl->d1 != NULL) { + mtu = ssl->d1->mtu; + } + + ssl->method->ssl_free(ssl); + if (!ssl->method->ssl_new(ssl)) { + return 0; + } + + if (SSL_IS_DTLS(ssl) && (SSL_get_options(ssl) & SSL_OP_NO_QUERY_MTU)) { + ssl->d1->mtu = mtu; + } + + ssl->client_version = ssl->version; + + return 1; +} + +void ssl_do_info_callback(const SSL *ssl, int type, int value) { + void (*cb)(const SSL *ssl, int type, int value) = NULL; + if (ssl->info_callback != NULL) { + cb = ssl->info_callback; + } else if (ssl->ctx->info_callback != NULL) { + cb = ssl->ctx->info_callback; + } + + if (cb != NULL) { + cb(ssl, type, value); + } +} + +void ssl_do_msg_callback(SSL *ssl, int is_write, int version, int content_type, + const void *buf, size_t len) { + if (ssl->msg_callback != NULL) { + ssl->msg_callback(is_write, version, content_type, buf, len, ssl, + ssl->msg_callback_arg); + } +} + +int SSL_CTX_sess_connect(const SSL_CTX *ctx) { return 0; } +int SSL_CTX_sess_connect_good(const SSL_CTX *ctx) { return 0; } +int SSL_CTX_sess_connect_renegotiate(const SSL_CTX *ctx) { return 0; } +int SSL_CTX_sess_accept(const SSL_CTX *ctx) { return 0; } +int SSL_CTX_sess_accept_renegotiate(const SSL_CTX *ctx) { return 0; } +int SSL_CTX_sess_accept_good(const SSL_CTX *ctx) { return 0; } +int SSL_CTX_sess_hits(const SSL_CTX *ctx) { return 0; } +int SSL_CTX_sess_cb_hits(const SSL_CTX *ctx) { return 0; } +int SSL_CTX_sess_misses(const SSL_CTX *ctx) { return 0; } +int SSL_CTX_sess_timeouts(const SSL_CTX *ctx) { return 0; } +int SSL_CTX_sess_cache_full(const SSL_CTX *ctx) { return 0; } + +int SSL_num_renegotiations(const SSL *ssl) { + return SSL_total_renegotiations(ssl); +} + +int SSL_CTX_need_tmp_RSA(const SSL_CTX *ctx) { return 0; } +int SSL_need_tmp_RSA(const SSL *ssl) { return 0; } +int SSL_CTX_set_tmp_rsa(SSL_CTX *ctx, const RSA *rsa) { return 1; } +int SSL_set_tmp_rsa(SSL *ssl, const RSA *rsa) { return 1; } +void ERR_load_SSL_strings(void) {} +void SSL_load_error_strings(void) {} +int SSL_cache_hit(SSL *ssl) { return SSL_session_reused(ssl); } + +int SSL_CTX_set_tmp_ecdh(SSL_CTX *ctx, const EC_KEY *ec_key) { + if (ec_key == NULL || EC_KEY_get0_group(ec_key) == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + int nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec_key)); + return SSL_CTX_set1_curves(ctx, &nid, 1); +} + +int SSL_set_tmp_ecdh(SSL *ssl, const EC_KEY *ec_key) { + if (ec_key == NULL || EC_KEY_get0_group(ec_key) == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + int nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec_key)); + return SSL_set1_curves(ssl, &nid, 1); +} diff --git a/external/boringssl/ssl/ssl_rsa.c b/external/boringssl/ssl/ssl_rsa.c new file mode 100644 index 0000000000..c17d2da4bc --- /dev/null +++ b/external/boringssl/ssl/ssl_rsa.c @@ -0,0 +1,428 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include + +#include + +#include +#include +#include +#include + +#include "internal.h" + + +static int ssl_set_cert(CERT *c, X509 *x509); +static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey); + +static int is_key_type_supported(int key_type) { + return key_type == EVP_PKEY_RSA || key_type == EVP_PKEY_EC; +} + +int SSL_use_certificate(SSL *ssl, X509 *x) { + if (x == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + return ssl_set_cert(ssl->cert, x); +} + +int SSL_use_certificate_ASN1(SSL *ssl, const uint8_t *der, size_t der_len) { + if (der_len > LONG_MAX) { + OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW); + return 0; + } + + const uint8_t *p = der; + X509 *x509 = d2i_X509(NULL, &p, (long)der_len); + if (x509 == NULL || p != der + der_len) { + OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB); + X509_free(x509); + return 0; + } + + int ret = SSL_use_certificate(ssl, x509); + X509_free(x509); + return ret; +} + +int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa) { + EVP_PKEY *pkey; + int ret; + + if (rsa == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + pkey = EVP_PKEY_new(); + if (pkey == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_EVP_LIB); + return 0; + } + + RSA_up_ref(rsa); + EVP_PKEY_assign_RSA(pkey, rsa); + + ret = ssl_set_pkey(ssl->cert, pkey); + EVP_PKEY_free(pkey); + + return ret; +} + +static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey) { + if (!is_key_type_supported(pkey->type)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE); + return 0; + } + + if (c->x509 != NULL) { + /* Sanity-check that the private key and the certificate match, unless the + * key is opaque (in case of, say, a smartcard). */ + if (!EVP_PKEY_is_opaque(pkey) && + !X509_check_private_key(c->x509, pkey)) { + X509_free(c->x509); + c->x509 = NULL; + return 0; + } + } + + EVP_PKEY_free(c->privatekey); + c->privatekey = EVP_PKEY_up_ref(pkey); + + return 1; +} + +int SSL_use_RSAPrivateKey_ASN1(SSL *ssl, const uint8_t *der, size_t der_len) { + RSA *rsa = RSA_private_key_from_bytes(der, der_len); + if (rsa == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB); + return 0; + } + + int ret = SSL_use_RSAPrivateKey(ssl, rsa); + RSA_free(rsa); + return ret; +} + +int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey) { + int ret; + + if (pkey == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + ret = ssl_set_pkey(ssl->cert, pkey); + return ret; +} + +int SSL_use_PrivateKey_ASN1(int type, SSL *ssl, const uint8_t *der, + size_t der_len) { + if (der_len > LONG_MAX) { + OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW); + return 0; + } + + const uint8_t *p = der; + EVP_PKEY *pkey = d2i_PrivateKey(type, NULL, &p, (long)der_len); + if (pkey == NULL || p != der + der_len) { + OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB); + EVP_PKEY_free(pkey); + return 0; + } + + int ret = SSL_use_PrivateKey(ssl, pkey); + EVP_PKEY_free(pkey); + return ret; +} + +int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x) { + if (x == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + return ssl_set_cert(ctx->cert, x); +} + +static int ssl_set_cert(CERT *c, X509 *x) { + EVP_PKEY *pkey = X509_get_pubkey(x); + if (pkey == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_R_X509_LIB); + return 0; + } + + if (!is_key_type_supported(pkey->type)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE); + EVP_PKEY_free(pkey); + return 0; + } + + if (c->privatekey != NULL) { + /* Sanity-check that the private key and the certificate match, unless the + * key is opaque (in case of, say, a smartcard). */ + if (!EVP_PKEY_is_opaque(c->privatekey) && + !X509_check_private_key(x, c->privatekey)) { + /* don't fail for a cert/key mismatch, just free current private key + * (when switching to a different cert & key, first this function should + * be used, then ssl_set_pkey */ + EVP_PKEY_free(c->privatekey); + c->privatekey = NULL; + /* clear error queue */ + ERR_clear_error(); + } + } + + EVP_PKEY_free(pkey); + + X509_free(c->x509); + c->x509 = X509_up_ref(x); + + return 1; +} + +int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, size_t der_len, + const uint8_t *der) { + if (der_len > LONG_MAX) { + OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW); + return 0; + } + + const uint8_t *p = der; + X509 *x509 = d2i_X509(NULL, &p, (long)der_len); + if (x509 == NULL || p != der + der_len) { + OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB); + X509_free(x509); + return 0; + } + + int ret = SSL_CTX_use_certificate(ctx, x509); + X509_free(x509); + return ret; +} + +int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa) { + int ret; + EVP_PKEY *pkey; + + if (rsa == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + pkey = EVP_PKEY_new(); + if (pkey == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_EVP_LIB); + return 0; + } + + RSA_up_ref(rsa); + EVP_PKEY_assign_RSA(pkey, rsa); + + ret = ssl_set_pkey(ctx->cert, pkey); + EVP_PKEY_free(pkey); + return ret; +} + +int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const uint8_t *der, + size_t der_len) { + RSA *rsa = RSA_private_key_from_bytes(der, der_len); + if (rsa == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB); + return 0; + } + + int ret = SSL_CTX_use_RSAPrivateKey(ctx, rsa); + RSA_free(rsa); + return ret; +} + +int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey) { + if (pkey == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + return ssl_set_pkey(ctx->cert, pkey); +} + +int SSL_CTX_use_PrivateKey_ASN1(int type, SSL_CTX *ctx, const uint8_t *der, + size_t der_len) { + if (der_len > LONG_MAX) { + OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW); + return 0; + } + + const uint8_t *p = der; + EVP_PKEY *pkey = d2i_PrivateKey(type, NULL, &p, (long)der_len); + if (pkey == NULL || p != der + der_len) { + OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB); + EVP_PKEY_free(pkey); + return 0; + } + + int ret = SSL_CTX_use_PrivateKey(ctx, pkey); + EVP_PKEY_free(pkey); + return ret; +} + +void SSL_set_private_key_method(SSL *ssl, + const SSL_PRIVATE_KEY_METHOD *key_method) { + ssl->cert->key_method = key_method; +} + +void SSL_CTX_set_private_key_method(SSL_CTX *ctx, + const SSL_PRIVATE_KEY_METHOD *key_method) { + ctx->cert->key_method = key_method; +} + +int SSL_set_private_key_digest_prefs(SSL *ssl, const int *digest_nids, + size_t num_digests) { + OPENSSL_free(ssl->cert->digest_nids); + + ssl->cert->num_digest_nids = 0; + ssl->cert->digest_nids = BUF_memdup(digest_nids, num_digests*sizeof(int)); + if (ssl->cert->digest_nids == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + return 0; + } + + ssl->cert->num_digest_nids = num_digests; + return 1; +} + +int ssl_has_private_key(SSL *ssl) { + return ssl->cert->privatekey != NULL || ssl->cert->key_method != NULL; +} + +int ssl_private_key_type(SSL *ssl) { + if (ssl->cert->key_method != NULL) { + return ssl->cert->key_method->type(ssl); + } + return EVP_PKEY_id(ssl->cert->privatekey); +} + +size_t ssl_private_key_max_signature_len(SSL *ssl) { + if (ssl->cert->key_method != NULL) { + return ssl->cert->key_method->max_signature_len(ssl); + } + return EVP_PKEY_size(ssl->cert->privatekey); +} + +enum ssl_private_key_result_t ssl_private_key_sign( + SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out, const EVP_MD *md, + const uint8_t *in, size_t in_len) { + if (ssl->cert->key_method != NULL) { + return ssl->cert->key_method->sign(ssl, out, out_len, max_out, md, in, + in_len); + } + + enum ssl_private_key_result_t ret = ssl_private_key_failure; + EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(ssl->cert->privatekey, NULL); + if (ctx == NULL) { + goto end; + } + + size_t len = max_out; + if (!EVP_PKEY_sign_init(ctx) || + !EVP_PKEY_CTX_set_signature_md(ctx, md) || + !EVP_PKEY_sign(ctx, out, &len, in, in_len)) { + goto end; + } + *out_len = len; + ret = ssl_private_key_success; + +end: + EVP_PKEY_CTX_free(ctx); + return ret; +} + +enum ssl_private_key_result_t ssl_private_key_sign_complete( + SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out) { + /* Only custom keys may be asynchronous. */ + return ssl->cert->key_method->sign_complete(ssl, out, out_len, max_out); +} + +enum ssl_private_key_result_t ssl_private_key_decrypt( + SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out, + const uint8_t *in, size_t in_len) { + if (ssl->cert->key_method != NULL) { + return ssl->cert->key_method->decrypt(ssl, out, out_len, max_out, in, + in_len); + } + + RSA *rsa = EVP_PKEY_get0_RSA(ssl->cert->privatekey); + if (rsa == NULL) { + /* Decrypt operations are only supported for RSA keys. */ + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + return ssl_private_key_failure; + } + + /* Decrypt with no padding. PKCS#1 padding will be removed as part + * of the timing-sensitive code by the caller. */ + if (!RSA_decrypt(rsa, out_len, out, max_out, in, in_len, RSA_NO_PADDING)) { + return ssl_private_key_failure; + } + return ssl_private_key_success; +} + +enum ssl_private_key_result_t ssl_private_key_decrypt_complete( + SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out) { + /* Only custom keys may be asynchronous. */ + return ssl->cert->key_method->decrypt_complete(ssl, out, out_len, max_out); +} diff --git a/external/boringssl/ssl/ssl_session.c b/external/boringssl/ssl/ssl_session.c new file mode 100644 index 0000000000..8e51a6a2bc --- /dev/null +++ b/external/boringssl/ssl/ssl_session.c @@ -0,0 +1,777 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2005 Nokia. All rights reserved. + * + * The portions of the attached software ("Contribution") is developed by + * Nokia Corporation and is licensed pursuant to the OpenSSL open source + * license. + * + * The Contribution, originally written by Mika Kousa and Pasi Eronen of + * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites + * support (see RFC 4279) to OpenSSL. + * + * No patent licenses or other rights except those expressly stated in + * the OpenSSL open source license shall be deemed granted or received + * expressly, by implication, estoppel, or otherwise. + * + * No assurances are provided by Nokia that the Contribution does not + * infringe the patent or other intellectual property rights of any third + * party or that the license provides you with all the necessary rights + * to make use of the Contribution. + * + * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN + * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA + * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY + * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR + * OTHERWISE. */ + +#include + +#include +#include + +#include +#include +#include +#include + +#include "internal.h" +#include "../crypto/internal.h" + + +/* The address of this is a magic value, a pointer to which is returned by + * SSL_magic_pending_session_ptr(). It allows a session callback to indicate + * that it needs to asynchronously fetch session information. */ +static const char g_pending_session_magic = 0; + +static CRYPTO_EX_DATA_CLASS g_ex_data_class = + CRYPTO_EX_DATA_CLASS_INIT_WITH_APP_DATA; + +static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *session); +static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *session); +static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *session, int lock); + +SSL_SESSION *SSL_SESSION_new(void) { + SSL_SESSION *session = OPENSSL_malloc(sizeof(SSL_SESSION)); + if (session == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + return 0; + } + memset(session, 0, sizeof(SSL_SESSION)); + + session->verify_result = 1; /* avoid 0 (= X509_V_OK) just in case */ + session->references = 1; + session->timeout = SSL_DEFAULT_SESSION_TIMEOUT; + session->time = (unsigned long)time(NULL); + CRYPTO_new_ex_data(&session->ex_data); + return session; +} + +SSL_SESSION *SSL_SESSION_up_ref(SSL_SESSION *session) { + if (session != NULL) { + CRYPTO_refcount_inc(&session->references); + } + return session; +} + +void SSL_SESSION_free(SSL_SESSION *session) { + if (session == NULL || + !CRYPTO_refcount_dec_and_test_zero(&session->references)) { + return; + } + + CRYPTO_free_ex_data(&g_ex_data_class, session, &session->ex_data); + + OPENSSL_cleanse(session->master_key, sizeof(session->master_key)); + OPENSSL_cleanse(session->session_id, sizeof(session->session_id)); + X509_free(session->peer); + sk_X509_pop_free(session->cert_chain, X509_free); + OPENSSL_free(session->tlsext_hostname); + OPENSSL_free(session->tlsext_tick); + OPENSSL_free(session->tlsext_signed_cert_timestamp_list); + OPENSSL_free(session->ocsp_response); + OPENSSL_free(session->psk_identity); + OPENSSL_cleanse(session, sizeof(*session)); + OPENSSL_free(session); +} + +const uint8_t *SSL_SESSION_get_id(const SSL_SESSION *session, + unsigned *out_len) { + if (out_len != NULL) { + *out_len = session->session_id_length; + } + return session->session_id; +} + +long SSL_SESSION_get_timeout(const SSL_SESSION *session) { + return session->timeout; +} + +long SSL_SESSION_get_time(const SSL_SESSION *session) { + if (session == NULL) { + /* NULL should crash, but silently accept it here for compatibility. */ + return 0; + } + return session->time; +} + +uint32_t SSL_SESSION_get_key_exchange_info(const SSL_SESSION *session) { + return session->key_exchange_info; +} + +X509 *SSL_SESSION_get0_peer(const SSL_SESSION *session) { + return session->peer; +} + +size_t SSL_SESSION_get_master_key(const SSL_SESSION *session, uint8_t *out, + size_t max_out) { + /* TODO(davidben): Fix master_key_length's type and remove these casts. */ + if (max_out == 0) { + return (size_t)session->master_key_length; + } + if (max_out > (size_t)session->master_key_length) { + max_out = (size_t)session->master_key_length; + } + memcpy(out, session->master_key, max_out); + return max_out; +} + +long SSL_SESSION_set_time(SSL_SESSION *session, long time) { + if (session == NULL) { + return 0; + } + + session->time = time; + return time; +} + +long SSL_SESSION_set_timeout(SSL_SESSION *session, long timeout) { + if (session == NULL) { + return 0; + } + + session->timeout = timeout; + return 1; +} + +int SSL_SESSION_set1_id_context(SSL_SESSION *session, const uint8_t *sid_ctx, + unsigned sid_ctx_len) { + if (sid_ctx_len > SSL_MAX_SID_CTX_LENGTH) { + OPENSSL_PUT_ERROR(SSL, SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG); + return 0; + } + + session->sid_ctx_length = sid_ctx_len; + memcpy(session->sid_ctx, sid_ctx, sid_ctx_len); + + return 1; +} + +SSL_SESSION *SSL_magic_pending_session_ptr(void) { + return (SSL_SESSION *)&g_pending_session_magic; +} + +SSL_SESSION *SSL_get_session(const SSL *ssl) +{ + /* aka SSL_get0_session; gets 0 objects, just returns a copy of the pointer */ + return ssl->session; +} + +SSL_SESSION *SSL_get1_session(SSL *ssl) { + /* variant of SSL_get_session: caller really gets something */ + return SSL_SESSION_up_ref(ssl->session); +} + +int SSL_SESSION_get_ex_new_index(long argl, void *argp, + CRYPTO_EX_unused *unused, + CRYPTO_EX_dup *dup_func, + CRYPTO_EX_free *free_func) { + int index; + if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp, dup_func, + free_func)) { + return -1; + } + return index; +} + +int SSL_SESSION_set_ex_data(SSL_SESSION *session, int idx, void *arg) { + return CRYPTO_set_ex_data(&session->ex_data, idx, arg); +} + +void *SSL_SESSION_get_ex_data(const SSL_SESSION *session, int idx) { + return CRYPTO_get_ex_data(&session->ex_data, idx); +} + +int ssl_get_new_session(SSL *ssl, int is_server) { + if (ssl->mode & SSL_MODE_NO_SESSION_CREATION) { + OPENSSL_PUT_ERROR(SSL, SSL_R_SESSION_MAY_NOT_BE_CREATED); + return 0; + } + + SSL_SESSION *session = SSL_SESSION_new(); + if (session == NULL) { + return 0; + } + + /* If the context has a default timeout, use it over the default. */ + if (ssl->initial_ctx->session_timeout != 0) { + session->timeout = ssl->initial_ctx->session_timeout; + } + + session->ssl_version = ssl->version; + + if (is_server) { + if (ssl->tlsext_ticket_expected) { + /* Don't set session IDs for sessions resumed with tickets. This will keep + * them out of the session cache. */ + session->session_id_length = 0; + } else { + session->session_id_length = SSL3_SSL_SESSION_ID_LENGTH; + if (!RAND_bytes(session->session_id, session->session_id_length)) { + goto err; + } + } + + if (ssl->tlsext_hostname != NULL) { + session->tlsext_hostname = BUF_strdup(ssl->tlsext_hostname); + if (session->tlsext_hostname == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + goto err; + } + } + } else { + session->session_id_length = 0; + } + + if (ssl->sid_ctx_length > sizeof(session->sid_ctx)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + goto err; + } + memcpy(session->sid_ctx, ssl->sid_ctx, ssl->sid_ctx_length); + session->sid_ctx_length = ssl->sid_ctx_length; + + session->verify_result = X509_V_OK; + + SSL_SESSION_free(ssl->session); + ssl->session = session; + return 1; + +err: + SSL_SESSION_free(session); + return 0; +} + +/* ssl_lookup_session looks up |session_id| in the session cache and sets + * |*out_session| to an |SSL_SESSION| object if found. The caller takes + * ownership of the result. */ +static enum ssl_session_result_t ssl_lookup_session( + SSL *ssl, SSL_SESSION **out_session, const uint8_t *session_id, + size_t session_id_len) { + *out_session = NULL; + + if (session_id_len == 0 || session_id_len > SSL_MAX_SSL_SESSION_ID_LENGTH) { + return ssl_session_success; + } + + SSL_SESSION *session; + /* Try the internal cache, if it exists. */ + if (!(ssl->initial_ctx->session_cache_mode & + SSL_SESS_CACHE_NO_INTERNAL_LOOKUP)) { + SSL_SESSION data; + data.ssl_version = ssl->version; + data.session_id_length = session_id_len; + memcpy(data.session_id, session_id, session_id_len); + + CRYPTO_MUTEX_lock_read(&ssl->initial_ctx->lock); + session = lh_SSL_SESSION_retrieve(ssl->initial_ctx->sessions, &data); + if (session != NULL) { + SSL_SESSION_up_ref(session); + } + /* TODO(davidben): This should probably move it to the front of the list. */ + CRYPTO_MUTEX_unlock_read(&ssl->initial_ctx->lock); + + if (session != NULL) { + *out_session = session; + return ssl_session_success; + } + } + + /* Fall back to the external cache, if it exists. */ + if (ssl->initial_ctx->get_session_cb == NULL) { + return ssl_session_success; + } + int copy = 1; + session = ssl->initial_ctx->get_session_cb(ssl, (uint8_t *)session_id, + session_id_len, ©); + if (session == NULL) { + return ssl_session_success; + } + if (session == SSL_magic_pending_session_ptr()) { + return ssl_session_retry; + } + + /* Increment reference count now if the session callback asks us to do so + * (note that if the session structures returned by the callback are shared + * between threads, it must handle the reference count itself [i.e. copy == + * 0], or things won't be thread-safe). */ + if (copy) { + SSL_SESSION_up_ref(session); + } + + /* Add the externally cached session to the internal cache if necessary. */ + if (!(ssl->initial_ctx->session_cache_mode & + SSL_SESS_CACHE_NO_INTERNAL_STORE)) { + SSL_CTX_add_session(ssl->initial_ctx, session); + } + + *out_session = session; + return ssl_session_success; +} + +enum ssl_session_result_t ssl_get_prev_session( + SSL *ssl, SSL_SESSION **out_session, int *out_send_ticket, + const struct ssl_early_callback_ctx *ctx) { + /* This is used only by servers. */ + assert(ssl->server); + SSL_SESSION *session = NULL; + int renew_ticket = 0; + + /* If tickets are disabled, always behave as if no tickets are present. */ + const uint8_t *ticket = NULL; + size_t ticket_len = 0; + const int tickets_supported = + !(SSL_get_options(ssl) & SSL_OP_NO_TICKET) && + ssl->version > SSL3_VERSION && + SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_session_ticket, + &ticket, &ticket_len); + int from_cache = 0; + if (tickets_supported && ticket_len > 0) { + if (!tls_process_ticket(ssl, &session, &renew_ticket, ticket, ticket_len, + ctx->session_id, ctx->session_id_len)) { + return ssl_session_error; + } + } else { + /* The client didn't send a ticket, so the session ID is a real ID. */ + enum ssl_session_result_t lookup_ret = ssl_lookup_session( + ssl, &session, ctx->session_id, ctx->session_id_len); + if (lookup_ret != ssl_session_success) { + return lookup_ret; + } + from_cache = 1; + } + + if (session == NULL || + session->sid_ctx_length != ssl->sid_ctx_length || + memcmp(session->sid_ctx, ssl->sid_ctx, ssl->sid_ctx_length) != 0) { + /* The client did not offer a suitable ticket or session ID. If supported, + * the new session should use a ticket. */ + goto no_session; + } + + if ((ssl->verify_mode & SSL_VERIFY_PEER) && ssl->sid_ctx_length == 0) { + /* We can't be sure if this session is being used out of context, which is + * especially important for SSL_VERIFY_PEER. The application should have + * used SSL[_CTX]_set_session_id_context. + * + * For this error case, we generate an error instead of treating the event + * like a cache miss (otherwise it would be easy for applications to + * effectively disable the session cache by accident without anyone + * noticing). */ + OPENSSL_PUT_ERROR(SSL, SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED); + SSL_SESSION_free(session); + return ssl_session_error; + } + + if (session->timeout < (long)(time(NULL) - session->time)) { + if (from_cache) { + /* The session was from the cache, so remove it. */ + SSL_CTX_remove_session(ssl->initial_ctx, session); + } + goto no_session; + } + + *out_session = session; + *out_send_ticket = renew_ticket; + return ssl_session_success; + +no_session: + *out_session = NULL; + *out_send_ticket = tickets_supported; + SSL_SESSION_free(session); + return ssl_session_success; +} + +int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *session) { + /* Although |session| is inserted into two structures (a doubly-linked list + * and the hash table), |ctx| only takes one reference. */ + SSL_SESSION_up_ref(session); + + SSL_SESSION *old_session; + CRYPTO_MUTEX_lock_write(&ctx->lock); + if (!lh_SSL_SESSION_insert(ctx->sessions, &old_session, session)) { + CRYPTO_MUTEX_unlock_write(&ctx->lock); + SSL_SESSION_free(session); + return 0; + } + + if (old_session != NULL) { + if (old_session == session) { + /* |session| was already in the cache. */ + CRYPTO_MUTEX_unlock_write(&ctx->lock); + SSL_SESSION_free(old_session); + return 0; + } + + /* There was a session ID collision. |old_session| must be removed from + * the linked list and released. */ + SSL_SESSION_list_remove(ctx, old_session); + SSL_SESSION_free(old_session); + } + + SSL_SESSION_list_add(ctx, session); + + /* Enforce any cache size limits. */ + if (SSL_CTX_sess_get_cache_size(ctx) > 0) { + while (SSL_CTX_sess_number(ctx) > SSL_CTX_sess_get_cache_size(ctx)) { + if (!remove_session_lock(ctx, ctx->session_cache_tail, 0)) { + break; + } + } + } + + CRYPTO_MUTEX_unlock_write(&ctx->lock); + return 1; +} + +int SSL_CTX_remove_session(SSL_CTX *ctx, SSL_SESSION *session) { + return remove_session_lock(ctx, session, 1); +} + +static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *session, int lock) { + int ret = 0; + + if (session != NULL && session->session_id_length != 0) { + if (lock) { + CRYPTO_MUTEX_lock_write(&ctx->lock); + } + SSL_SESSION *found_session = lh_SSL_SESSION_retrieve(ctx->sessions, + session); + if (found_session == session) { + ret = 1; + found_session = lh_SSL_SESSION_delete(ctx->sessions, session); + SSL_SESSION_list_remove(ctx, session); + } + + if (lock) { + CRYPTO_MUTEX_unlock_write(&ctx->lock); + } + + if (ret) { + found_session->not_resumable = 1; + if (ctx->remove_session_cb != NULL) { + ctx->remove_session_cb(ctx, found_session); + } + SSL_SESSION_free(found_session); + } + } + + return ret; +} + +int SSL_set_session(SSL *ssl, SSL_SESSION *session) { + if (ssl->session == session) { + return 1; + } + + SSL_SESSION_free(ssl->session); + ssl->session = session; + if (session != NULL) { + SSL_SESSION_up_ref(session); + ssl->verify_result = session->verify_result; + } + + return 1; +} + +long SSL_CTX_set_timeout(SSL_CTX *ctx, long timeout) { + if (ctx == NULL) { + return 0; + } + + long old_timeout = ctx->session_timeout; + ctx->session_timeout = timeout; + return old_timeout; +} + +long SSL_CTX_get_timeout(const SSL_CTX *ctx) { + if (ctx == NULL) { + return 0; + } + + return ctx->session_timeout; +} + +typedef struct timeout_param_st { + SSL_CTX *ctx; + long time; + LHASH_OF(SSL_SESSION) *cache; +} TIMEOUT_PARAM; + +static void timeout_doall_arg(SSL_SESSION *session, void *void_param) { + TIMEOUT_PARAM *param = void_param; + + if (param->time == 0 || + param->time > (session->time + session->timeout)) { + /* timeout */ + /* The reason we don't call SSL_CTX_remove_session() is to + * save on locking overhead */ + (void) lh_SSL_SESSION_delete(param->cache, session); + SSL_SESSION_list_remove(param->ctx, session); + session->not_resumable = 1; + if (param->ctx->remove_session_cb != NULL) { + param->ctx->remove_session_cb(param->ctx, session); + } + SSL_SESSION_free(session); + } +} + +void SSL_CTX_flush_sessions(SSL_CTX *ctx, long time) { + TIMEOUT_PARAM tp; + + tp.ctx = ctx; + tp.cache = ctx->sessions; + if (tp.cache == NULL) { + return; + } + tp.time = time; + CRYPTO_MUTEX_lock_write(&ctx->lock); + lh_SSL_SESSION_doall_arg(tp.cache, timeout_doall_arg, &tp); + CRYPTO_MUTEX_unlock_write(&ctx->lock); +} + +int ssl_clear_bad_session(SSL *ssl) { + if (ssl->session != NULL && + ssl->s3->send_shutdown != ssl_shutdown_close_notify && + !SSL_in_init(ssl)) { + SSL_CTX_remove_session(ssl->ctx, ssl->session); + return 1; + } + + return 0; +} + +/* locked by SSL_CTX in the calling function */ +static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *session) { + if (session->next == NULL || session->prev == NULL) { + return; + } + + if (session->next == (SSL_SESSION *)&ctx->session_cache_tail) { + /* last element in list */ + if (session->prev == (SSL_SESSION *)&ctx->session_cache_head) { + /* only one element in list */ + ctx->session_cache_head = NULL; + ctx->session_cache_tail = NULL; + } else { + ctx->session_cache_tail = session->prev; + session->prev->next = (SSL_SESSION *)&(ctx->session_cache_tail); + } + } else { + if (session->prev == (SSL_SESSION *)&ctx->session_cache_head) { + /* first element in list */ + ctx->session_cache_head = session->next; + session->next->prev = (SSL_SESSION *)&(ctx->session_cache_head); + } else { /* middle of list */ + session->next->prev = session->prev; + session->prev->next = session->next; + } + } + session->prev = session->next = NULL; +} + +static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *session) { + if (session->next != NULL && session->prev != NULL) { + SSL_SESSION_list_remove(ctx, session); + } + + if (ctx->session_cache_head == NULL) { + ctx->session_cache_head = session; + ctx->session_cache_tail = session; + session->prev = (SSL_SESSION *)&(ctx->session_cache_head); + session->next = (SSL_SESSION *)&(ctx->session_cache_tail); + } else { + session->next = ctx->session_cache_head; + session->next->prev = session; + session->prev = (SSL_SESSION *)&(ctx->session_cache_head); + ctx->session_cache_head = session; + } +} + +void SSL_CTX_sess_set_new_cb(SSL_CTX *ctx, + int (*cb)(SSL *ssl, SSL_SESSION *session)) { + ctx->new_session_cb = cb; +} + +int (*SSL_CTX_sess_get_new_cb(SSL_CTX *ctx))(SSL *ssl, SSL_SESSION *session) { + return ctx->new_session_cb; +} + +void SSL_CTX_sess_set_remove_cb( + SSL_CTX *ctx, void (*cb)(SSL_CTX *ctx, SSL_SESSION *session)) { + ctx->remove_session_cb = cb; +} + +void (*SSL_CTX_sess_get_remove_cb(SSL_CTX *ctx))(SSL_CTX *ctx, + SSL_SESSION *session) { + return ctx->remove_session_cb; +} + +void SSL_CTX_sess_set_get_cb(SSL_CTX *ctx, + SSL_SESSION *(*cb)(SSL *ssl, + uint8_t *id, int id_len, + int *out_copy)) { + ctx->get_session_cb = cb; +} + +SSL_SESSION *(*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx))( + SSL *ssl, uint8_t *id, int id_len, int *out_copy) { + return ctx->get_session_cb; +} + +void SSL_CTX_set_info_callback( + SSL_CTX *ctx, void (*cb)(const SSL *ssl, int type, int value)) { + ctx->info_callback = cb; +} + +void (*SSL_CTX_get_info_callback(SSL_CTX *ctx))(const SSL *ssl, int type, + int value) { + return ctx->info_callback; +} + +void SSL_CTX_set_client_cert_cb(SSL_CTX *ctx, int (*cb)(SSL *ssl, + X509 **out_x509, + EVP_PKEY **out_pkey)) { + ctx->client_cert_cb = cb; +} + +int (*SSL_CTX_get_client_cert_cb(SSL_CTX *ctx))(SSL *ssl, X509 **out_x509, + EVP_PKEY **out_pkey) { + return ctx->client_cert_cb; +} + +void SSL_CTX_set_channel_id_cb(SSL_CTX *ctx, + void (*cb)(SSL *ssl, EVP_PKEY **pkey)) { + ctx->channel_id_cb = cb; +} + +void (*SSL_CTX_get_channel_id_cb(SSL_CTX *ctx))(SSL *ssl, EVP_PKEY **pkey) { + return ctx->channel_id_cb; +} diff --git a/external/boringssl/ssl/ssl_stat.c b/external/boringssl/ssl/ssl_stat.c new file mode 100644 index 0000000000..15d1270b08 --- /dev/null +++ b/external/boringssl/ssl/ssl_stat.c @@ -0,0 +1,523 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright 2005 Nokia. All rights reserved. + * + * The portions of the attached software ("Contribution") is developed by + * Nokia Corporation and is licensed pursuant to the OpenSSL open source + * license. + * + * The Contribution, originally written by Mika Kousa and Pasi Eronen of + * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites + * support (see RFC 4279) to OpenSSL. + * + * No patent licenses or other rights except those expressly stated in + * the OpenSSL open source license shall be deemed granted or received + * expressly, by implication, estoppel, or otherwise. + * + * No assurances are provided by Nokia that the Contribution does not + * infringe the patent or other intellectual property rights of any third + * party or that the license provides you with all the necessary rights + * to make use of the Contribution. + * + * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN + * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA + * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY + * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR + * OTHERWISE. + */ + +#include + +#include "internal.h" + + +const char *SSL_state_string_long(const SSL *ssl) { + switch (ssl->state) { + case SSL_ST_ACCEPT: + return "before accept initialization"; + + case SSL_ST_CONNECT: + return "before connect initialization"; + + case SSL_ST_OK: + return "SSL negotiation finished successfully"; + + case SSL_ST_RENEGOTIATE: + return "SSL renegotiate ciphers"; + + /* SSLv3 additions */ + case SSL3_ST_CW_CLNT_HELLO_A: + return "SSLv3 write client hello A"; + + case SSL3_ST_CW_CLNT_HELLO_B: + return "SSLv3 write client hello B"; + + case SSL3_ST_CR_SRVR_HELLO_A: + return "SSLv3 read server hello A"; + + case SSL3_ST_CR_CERT_A: + return "SSLv3 read server certificate A"; + + case SSL3_ST_CR_KEY_EXCH_A: + return "SSLv3 read server key exchange A"; + + case SSL3_ST_CR_CERT_REQ_A: + return "SSLv3 read server certificate request A"; + + case SSL3_ST_CR_SESSION_TICKET_A: + return "SSLv3 read server session ticket A"; + + case SSL3_ST_CR_SRVR_DONE_A: + return "SSLv3 read server done A"; + + case SSL3_ST_CW_CERT_A: + return "SSLv3 write client certificate A"; + + case SSL3_ST_CW_CERT_B: + return "SSLv3 write client certificate B"; + + case SSL3_ST_CW_CERT_C: + return "SSLv3 write client certificate C"; + + case SSL3_ST_CW_CERT_D: + return "SSLv3 write client certificate D"; + + case SSL3_ST_CW_KEY_EXCH_A: + return "SSLv3 write client key exchange A"; + + case SSL3_ST_CW_KEY_EXCH_B: + return "SSLv3 write client key exchange B"; + + case SSL3_ST_CW_CERT_VRFY_A: + return "SSLv3 write certificate verify A"; + + case SSL3_ST_CW_CERT_VRFY_B: + return "SSLv3 write certificate verify B"; + + case SSL3_ST_CW_CHANGE_A: + case SSL3_ST_SW_CHANGE_A: + return "SSLv3 write change cipher spec A"; + + case SSL3_ST_CW_CHANGE_B: + case SSL3_ST_SW_CHANGE_B: + return "SSLv3 write change cipher spec B"; + + case SSL3_ST_CW_FINISHED_A: + case SSL3_ST_SW_FINISHED_A: + return "SSLv3 write finished A"; + + case SSL3_ST_CW_FINISHED_B: + case SSL3_ST_SW_FINISHED_B: + return "SSLv3 write finished B"; + + case SSL3_ST_CR_CHANGE: + case SSL3_ST_SR_CHANGE: + return "SSLv3 read change cipher spec"; + + case SSL3_ST_CR_FINISHED_A: + case SSL3_ST_SR_FINISHED_A: + return "SSLv3 read finished A"; + + case SSL3_ST_CW_FLUSH: + case SSL3_ST_SW_FLUSH: + return "SSLv3 flush data"; + + case SSL3_ST_SR_CLNT_HELLO_A: + return "SSLv3 read client hello A"; + + case SSL3_ST_SR_CLNT_HELLO_B: + return "SSLv3 read client hello B"; + + case SSL3_ST_SR_CLNT_HELLO_C: + return "SSLv3 read client hello C"; + + case SSL3_ST_SW_HELLO_REQ_A: + return "SSLv3 write hello request A"; + + case SSL3_ST_SW_HELLO_REQ_B: + return "SSLv3 write hello request B"; + + case SSL3_ST_SW_HELLO_REQ_C: + return "SSLv3 write hello request C"; + + case SSL3_ST_SW_SRVR_HELLO_A: + return "SSLv3 write server hello A"; + + case SSL3_ST_SW_SRVR_HELLO_B: + return "SSLv3 write server hello B"; + + case SSL3_ST_SW_CERT_A: + return "SSLv3 write certificate A"; + + case SSL3_ST_SW_CERT_B: + return "SSLv3 write certificate B"; + + case SSL3_ST_SW_KEY_EXCH_A: + return "SSLv3 write key exchange A"; + + case SSL3_ST_SW_KEY_EXCH_B: + return "SSLv3 write key exchange B"; + + case SSL3_ST_SW_CERT_REQ_A: + return "SSLv3 write certificate request A"; + + case SSL3_ST_SW_CERT_REQ_B: + return "SSLv3 write certificate request B"; + + case SSL3_ST_SW_SESSION_TICKET_A: + return "SSLv3 write session ticket A"; + + case SSL3_ST_SW_SESSION_TICKET_B: + return "SSLv3 write session ticket B"; + + case SSL3_ST_SW_SRVR_DONE_A: + return "SSLv3 write server done A"; + + case SSL3_ST_SW_SRVR_DONE_B: + return "SSLv3 write server done B"; + + case SSL3_ST_SR_CERT_A: + return "SSLv3 read client certificate A"; + + case SSL3_ST_SR_KEY_EXCH_A: + return "SSLv3 read client key exchange A"; + + case SSL3_ST_SR_KEY_EXCH_B: + return "SSLv3 read client key exchange B"; + + case SSL3_ST_SR_CERT_VRFY_A: + return "SSLv3 read certificate verify A"; + + /* DTLS */ + case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A: + return "DTLS1 read hello verify request A"; + + default: + return "unknown state"; + } +} + +const char *SSL_state_string(const SSL *ssl) { + switch (ssl->state) { + case SSL_ST_ACCEPT: + return "AINIT "; + + case SSL_ST_CONNECT: + return "CINIT "; + + case SSL_ST_OK: + return "SSLOK "; + + /* SSLv3 additions */ + case SSL3_ST_SW_FLUSH: + case SSL3_ST_CW_FLUSH: + return "3FLUSH"; + + case SSL3_ST_CW_CLNT_HELLO_A: + return "3WCH_A"; + + case SSL3_ST_CW_CLNT_HELLO_B: + return "3WCH_B"; + + case SSL3_ST_CR_SRVR_HELLO_A: + return "3RSH_A"; + + case SSL3_ST_CR_CERT_A: + return "3RSC_A"; + + case SSL3_ST_CR_KEY_EXCH_A: + return "3RSKEA"; + + case SSL3_ST_CR_CERT_REQ_A: + return "3RCR_A"; + + case SSL3_ST_CR_SRVR_DONE_A: + return "3RSD_A"; + + case SSL3_ST_CW_CERT_A: + return "3WCC_A"; + + case SSL3_ST_CW_CERT_B: + return "3WCC_B"; + + case SSL3_ST_CW_CERT_C: + return "3WCC_C"; + + case SSL3_ST_CW_CERT_D: + return "3WCC_D"; + + case SSL3_ST_CW_KEY_EXCH_A: + return "3WCKEA"; + + case SSL3_ST_CW_KEY_EXCH_B: + return "3WCKEB"; + + case SSL3_ST_CW_CERT_VRFY_A: + return "3WCV_A"; + + case SSL3_ST_CW_CERT_VRFY_B: + return "3WCV_B"; + + case SSL3_ST_SW_CHANGE_A: + case SSL3_ST_CW_CHANGE_A: + return "3WCCSA"; + + case SSL3_ST_SW_CHANGE_B: + case SSL3_ST_CW_CHANGE_B: + return "3WCCSB"; + + case SSL3_ST_SW_FINISHED_A: + case SSL3_ST_CW_FINISHED_A: + return "3WFINA"; + + case SSL3_ST_SW_FINISHED_B: + case SSL3_ST_CW_FINISHED_B: + return "3WFINB"; + + case SSL3_ST_CR_CHANGE: + case SSL3_ST_SR_CHANGE: + return "3RCCS_"; + + case SSL3_ST_SR_FINISHED_A: + case SSL3_ST_CR_FINISHED_A: + return "3RFINA"; + + case SSL3_ST_SW_HELLO_REQ_A: + return "3WHR_A"; + + case SSL3_ST_SW_HELLO_REQ_B: + return "3WHR_B"; + + case SSL3_ST_SW_HELLO_REQ_C: + return "3WHR_C"; + + case SSL3_ST_SR_CLNT_HELLO_A: + return "3RCH_A"; + + case SSL3_ST_SR_CLNT_HELLO_B: + return "3RCH_B"; + + case SSL3_ST_SR_CLNT_HELLO_C: + return "3RCH_C"; + + case SSL3_ST_SW_SRVR_HELLO_A: + return "3WSH_A"; + + case SSL3_ST_SW_SRVR_HELLO_B: + return "3WSH_B"; + + case SSL3_ST_SW_CERT_A: + return "3WSC_A"; + + case SSL3_ST_SW_CERT_B: + return "3WSC_B"; + + case SSL3_ST_SW_KEY_EXCH_A: + return "3WSKEA"; + + case SSL3_ST_SW_KEY_EXCH_B: + return "3WSKEB"; + + case SSL3_ST_SW_CERT_REQ_A: + return "3WCR_A"; + + case SSL3_ST_SW_CERT_REQ_B: + return "3WCR_B"; + + case SSL3_ST_SW_SRVR_DONE_A: + return "3WSD_A"; + + case SSL3_ST_SW_SRVR_DONE_B: + return "3WSD_B"; + + case SSL3_ST_SR_CERT_A: + return "3RCC_A"; + + case SSL3_ST_SR_KEY_EXCH_A: + return "3RCKEA"; + + case SSL3_ST_SR_CERT_VRFY_A: + return "3RCV_A"; + + /* DTLS */ + case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A: + return "DRCHVA"; + + default: + return "UNKWN "; + } +} + +const char *SSL_alert_type_string_long(int value) { + value >>= 8; + if (value == SSL3_AL_WARNING) { + return "warning"; + } else if (value == SSL3_AL_FATAL) { + return "fatal"; + } + + return "unknown"; +} + +const char *SSL_alert_type_string(int value) { + return "!"; +} + +const char *SSL_alert_desc_string(int value) { + return "!!"; +} + +const char *SSL_alert_desc_string_long(int value) { + switch (value & 0xff) { + case SSL3_AD_CLOSE_NOTIFY: + return "close notify"; + + case SSL3_AD_UNEXPECTED_MESSAGE: + return "unexpected_message"; + + case SSL3_AD_BAD_RECORD_MAC: + return "bad record mac"; + + case SSL3_AD_DECOMPRESSION_FAILURE: + return "decompression failure"; + + case SSL3_AD_HANDSHAKE_FAILURE: + return "handshake failure"; + + case SSL3_AD_NO_CERTIFICATE: + return "no certificate"; + + case SSL3_AD_BAD_CERTIFICATE: + return "bad certificate"; + + case SSL3_AD_UNSUPPORTED_CERTIFICATE: + return "unsupported certificate"; + + case SSL3_AD_CERTIFICATE_REVOKED: + return "certificate revoked"; + + case SSL3_AD_CERTIFICATE_EXPIRED: + return "certificate expired"; + + case SSL3_AD_CERTIFICATE_UNKNOWN: + return "certificate unknown"; + + case SSL3_AD_ILLEGAL_PARAMETER: + return "illegal parameter"; + + case TLS1_AD_DECRYPTION_FAILED: + return "decryption failed"; + + case TLS1_AD_RECORD_OVERFLOW: + return "record overflow"; + + case TLS1_AD_UNKNOWN_CA: + return "unknown CA"; + + case TLS1_AD_ACCESS_DENIED: + return "access denied"; + + case TLS1_AD_DECODE_ERROR: + return "decode error"; + + case TLS1_AD_DECRYPT_ERROR: + return "decrypt error"; + + case TLS1_AD_EXPORT_RESTRICTION: + return "export restriction"; + + case TLS1_AD_PROTOCOL_VERSION: + return "protocol version"; + + case TLS1_AD_INSUFFICIENT_SECURITY: + return "insufficient security"; + + case TLS1_AD_INTERNAL_ERROR: + return "internal error"; + + case TLS1_AD_USER_CANCELLED: + return "user canceled"; + + case TLS1_AD_NO_RENEGOTIATION: + return "no renegotiation"; + + case TLS1_AD_UNSUPPORTED_EXTENSION: + return "unsupported extension"; + + case TLS1_AD_CERTIFICATE_UNOBTAINABLE: + return "certificate unobtainable"; + + case TLS1_AD_UNRECOGNIZED_NAME: + return "unrecognized name"; + + case TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE: + return "bad certificate status response"; + + case TLS1_AD_BAD_CERTIFICATE_HASH_VALUE: + return "bad certificate hash value"; + + case TLS1_AD_UNKNOWN_PSK_IDENTITY: + return "unknown PSK identity"; + + case SSL3_AD_INAPPROPRIATE_FALLBACK: + return "inappropriate fallback"; + + default: + return "unknown"; + } +} diff --git a/external/boringssl/ssl/ssl_test.cc b/external/boringssl/ssl/ssl_test.cc new file mode 100644 index 0000000000..3e9cd1ed67 --- /dev/null +++ b/external/boringssl/ssl/ssl_test.cc @@ -0,0 +1,1386 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "test/scoped_types.h" +#include "../crypto/test/test_util.h" + + +struct ExpectedCipher { + unsigned long id; + int in_group_flag; +}; + +struct CipherTest { + // The rule string to apply. + const char *rule; + // The list of expected ciphers, in order. + std::vector expected; +}; + +static const CipherTest kCipherTests[] = { + // Selecting individual ciphers should work. + { + "ECDHE-ECDSA-CHACHA20-POLY1305:" + "ECDHE-RSA-CHACHA20-POLY1305:" + "ECDHE-ECDSA-AES128-GCM-SHA256:" + "ECDHE-RSA-AES128-GCM-SHA256", + { + {TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 0}, + {TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD, 0}, + {TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0}, + {TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD, 0}, + {TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0}, + {TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0}, + }, + }, + // + reorders selected ciphers to the end, keeping their relative order. + { + "ECDHE-ECDSA-CHACHA20-POLY1305:" + "ECDHE-RSA-CHACHA20-POLY1305:" + "ECDHE-ECDSA-AES128-GCM-SHA256:" + "ECDHE-RSA-AES128-GCM-SHA256:" + "+aRSA", + { + {TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 0}, + {TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD, 0}, + {TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0}, + {TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0}, + {TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD, 0}, + {TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0}, + }, + }, + // ! banishes ciphers from future selections. + { + "!aRSA:" + "ECDHE-ECDSA-CHACHA20-POLY1305:" + "ECDHE-RSA-CHACHA20-POLY1305:" + "ECDHE-ECDSA-AES128-GCM-SHA256:" + "ECDHE-RSA-AES128-GCM-SHA256", + { + {TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 0}, + {TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD, 0}, + {TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0}, + }, + }, + // Multiple masks can be ANDed in a single rule. + { + "kRSA+AESGCM+AES128", + { + {TLS1_CK_RSA_WITH_AES_128_GCM_SHA256, 0}, + }, + }, + // - removes selected ciphers, but preserves their order for future + // selections. Select AES_128_GCM, but order the key exchanges RSA, DHE_RSA, + // ECDHE_RSA. + { + "ALL:-kECDHE:-kDHE:-kRSA:-ALL:" + "AESGCM+AES128+aRSA", + { + {TLS1_CK_RSA_WITH_AES_128_GCM_SHA256, 0}, + {TLS1_CK_DHE_RSA_WITH_AES_128_GCM_SHA256, 0}, + {TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0}, + }, + }, + // Unknown selectors are no-ops. + { + "ECDHE-ECDSA-CHACHA20-POLY1305:" + "ECDHE-RSA-CHACHA20-POLY1305:" + "ECDHE-ECDSA-AES128-GCM-SHA256:" + "ECDHE-RSA-AES128-GCM-SHA256:" + "BOGUS1:-BOGUS2:+BOGUS3:!BOGUS4", + { + {TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 0}, + {TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD, 0}, + {TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0}, + {TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD, 0}, + {TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0}, + {TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0}, + }, + }, + // Square brackets specify equi-preference groups. + { + "[ECDHE-ECDSA-CHACHA20-POLY1305|ECDHE-ECDSA-AES128-GCM-SHA256]:" + "[ECDHE-RSA-CHACHA20-POLY1305]:" + "ECDHE-RSA-AES128-GCM-SHA256", + { + {TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 1}, + {TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD, 1}, + {TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0}, + {TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 1}, + {TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD, 0}, + {TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0}, + }, + }, + // @STRENGTH performs a stable strength-sort of the selected ciphers and + // only the selected ciphers. + { + // To simplify things, banish all but {ECDHE_RSA,RSA} x + // {CHACHA20,AES_256_CBC,AES_128_CBC,RC4} x SHA1. + "!kEDH:!AESGCM:!3DES:!SHA256:!MD5:!SHA384:" + // Order some ciphers backwards by strength. + "ALL:-CHACHA20:-AES256:-AES128:-RC4:-ALL:" + // Select ECDHE ones and sort them by strength. Ties should resolve + // based on the order above. + "kECDHE:@STRENGTH:-ALL:" + // Now bring back everything uses RSA. ECDHE_RSA should be first, sorted + // by strength. Then RSA, backwards by strength. + "aRSA", + { + {TLS1_CK_ECDHE_RSA_WITH_AES_256_CBC_SHA, 0}, + {TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0}, + {TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD, 0}, + {TLS1_CK_ECDHE_RSA_WITH_RC4_128_SHA, 0}, + {TLS1_CK_ECDHE_RSA_WITH_AES_128_CBC_SHA, 0}, + {SSL3_CK_RSA_RC4_128_SHA, 0}, + {TLS1_CK_RSA_WITH_AES_128_SHA, 0}, + {TLS1_CK_RSA_WITH_AES_256_SHA, 0}, + }, + }, + // Exact ciphers may not be used in multi-part rules; they are treated + // as unknown aliases. + { + "ECDHE-ECDSA-AES128-GCM-SHA256:" + "ECDHE-RSA-AES128-GCM-SHA256:" + "!ECDHE-RSA-AES128-GCM-SHA256+RSA:" + "!ECDSA+ECDHE-ECDSA-AES128-GCM-SHA256", + { + {TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0}, + {TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0}, + }, + }, + // SSLv3 matches everything that existed before TLS 1.2. + { + "AES128-SHA:AES128-SHA256:!SSLv3", + { + {TLS1_CK_RSA_WITH_AES_128_SHA256, 0}, + }, + }, + // TLSv1.2 matches everything added in TLS 1.2. + { + "AES128-SHA:AES128-SHA256:!TLSv1.2", + { + {TLS1_CK_RSA_WITH_AES_128_SHA, 0}, + }, + }, + // The two directives have no intersection. + { + "AES128-SHA:AES128-SHA256:!TLSv1.2+SSLv3", + { + {TLS1_CK_RSA_WITH_AES_128_SHA, 0}, + {TLS1_CK_RSA_WITH_AES_128_SHA256, 0}, + }, + }, + // The shared name of the CHACHA20_POLY1305 variants behaves like a cipher + // name and not an alias. It may not be used in a multipart rule. (That the + // shared name works is covered by the standard tests.) + { + "ECDHE-ECDSA-CHACHA20-POLY1305:" + "ECDHE-RSA-CHACHA20-POLY1305:" + "!ECDHE-RSA-CHACHA20-POLY1305+RSA:" + "!ECDSA+ECDHE-ECDSA-CHACHA20-POLY1305", + { + {TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 0}, + {TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD, 0}, + {TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0}, + {TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD, 0}, + }, + }, +}; + +static const char *kBadRules[] = { + // Invalid brackets. + "[ECDHE-RSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256", + "RSA]", + "[[RSA]]", + // Operators inside brackets. + "[+RSA]", + // Unknown directive. + "@BOGUS", + // Empty cipher lists error at SSL_CTX_set_cipher_list. + "", + "BOGUS", + // COMPLEMENTOFDEFAULT is empty. + "COMPLEMENTOFDEFAULT", + // Invalid command. + "?BAR", + // Special operators are not allowed if groups are used. + "[ECDHE-RSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256]:+FOO", + "[ECDHE-RSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256]:!FOO", + "[ECDHE-RSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256]:-FOO", + "[ECDHE-RSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256]:@STRENGTH", +}; + +static const char *kMustNotIncludeNull[] = { + "ALL", + "DEFAULT", + "ALL:!eNULL", + "ALL:!NULL", + "MEDIUM", + "HIGH", + "FIPS", + "SHA", + "SHA1", + "RSA", + "SSLv3", + "TLSv1", + "TLSv1.2", +}; + +static const char *kMustNotIncludeCECPQ1[] = { + "ALL", + "DEFAULT", + "MEDIUM", + "HIGH", + "FIPS", + "SHA", + "SHA1", + "SHA256", + "SHA384", + "RSA", + "SSLv3", + "TLSv1", + "TLSv1.2", + "aRSA", + "RSA", + "aECDSA", + "ECDSA", + "AES", + "AES128", + "AES256", + "AESGCM", + "CHACHA20", +}; + +static void PrintCipherPreferenceList(ssl_cipher_preference_list_st *list) { + bool in_group = false; + for (size_t i = 0; i < sk_SSL_CIPHER_num(list->ciphers); i++) { + const SSL_CIPHER *cipher = sk_SSL_CIPHER_value(list->ciphers, i); + if (!in_group && list->in_group_flags[i]) { + fprintf(stderr, "\t[\n"); + in_group = true; + } + fprintf(stderr, "\t"); + if (in_group) { + fprintf(stderr, " "); + } + fprintf(stderr, "%s\n", SSL_CIPHER_get_name(cipher)); + if (in_group && !list->in_group_flags[i]) { + fprintf(stderr, "\t]\n"); + in_group = false; + } + } +} + +static bool TestCipherRule(const CipherTest &t) { + ScopedSSL_CTX ctx(SSL_CTX_new(TLS_method())); + if (!ctx) { + return false; + } + + if (!SSL_CTX_set_cipher_list(ctx.get(), t.rule)) { + fprintf(stderr, "Error testing cipher rule '%s'\n", t.rule); + return false; + } + + // Compare the two lists. + if (sk_SSL_CIPHER_num(ctx->cipher_list->ciphers) != t.expected.size()) { + fprintf(stderr, "Error: cipher rule '%s' evaluated to:\n", t.rule); + PrintCipherPreferenceList(ctx->cipher_list); + return false; + } + + for (size_t i = 0; i < t.expected.size(); i++) { + const SSL_CIPHER *cipher = + sk_SSL_CIPHER_value(ctx->cipher_list->ciphers, i); + if (t.expected[i].id != SSL_CIPHER_get_id(cipher) || + t.expected[i].in_group_flag != ctx->cipher_list->in_group_flags[i]) { + fprintf(stderr, "Error: cipher rule '%s' evaluated to:\n", t.rule); + PrintCipherPreferenceList(ctx->cipher_list); + return false; + } + } + + return true; +} + +static bool TestRuleDoesNotIncludeNull(const char *rule) { + ScopedSSL_CTX ctx(SSL_CTX_new(SSLv23_server_method())); + if (!ctx) { + return false; + } + if (!SSL_CTX_set_cipher_list(ctx.get(), rule)) { + fprintf(stderr, "Error: cipher rule '%s' failed\n", rule); + return false; + } + for (size_t i = 0; i < sk_SSL_CIPHER_num(ctx->cipher_list->ciphers); i++) { + if (SSL_CIPHER_is_NULL(sk_SSL_CIPHER_value(ctx->cipher_list->ciphers, i))) { + fprintf(stderr, "Error: cipher rule '%s' includes NULL\n",rule); + return false; + } + } + return true; +} + +static bool TestRuleDoesNotIncludeCECPQ1(const char *rule) { + ScopedSSL_CTX ctx(SSL_CTX_new(TLS_method())); + if (!ctx) { + return false; + } + if (!SSL_CTX_set_cipher_list(ctx.get(), rule)) { + fprintf(stderr, "Error: cipher rule '%s' failed\n", rule); + return false; + } + for (size_t i = 0; i < sk_SSL_CIPHER_num(ctx->cipher_list->ciphers); i++) { + if (SSL_CIPHER_is_CECPQ1(sk_SSL_CIPHER_value(ctx->cipher_list->ciphers, i))) { + fprintf(stderr, "Error: cipher rule '%s' includes CECPQ1\n",rule); + return false; + } + } + return true; +} + +static bool TestCipherRules() { + for (const CipherTest &test : kCipherTests) { + if (!TestCipherRule(test)) { + return false; + } + } + + for (const char *rule : kBadRules) { + ScopedSSL_CTX ctx(SSL_CTX_new(SSLv23_server_method())); + if (!ctx) { + return false; + } + if (SSL_CTX_set_cipher_list(ctx.get(), rule)) { + fprintf(stderr, "Cipher rule '%s' unexpectedly succeeded\n", rule); + return false; + } + ERR_clear_error(); + } + + for (const char *rule : kMustNotIncludeNull) { + if (!TestRuleDoesNotIncludeNull(rule)) { + return false; + } + } + + for (const char *rule : kMustNotIncludeCECPQ1) { + if (!TestRuleDoesNotIncludeCECPQ1(rule)) { + return false; + } + } + + return true; +} + +// kOpenSSLSession is a serialized SSL_SESSION generated from openssl +// s_client -sess_out. +static const char kOpenSSLSession[] = + "MIIFpQIBAQICAwMEAsAvBCAG5Q1ndq4Yfmbeo1zwLkNRKmCXGdNgWvGT3cskV0yQ" + "kAQwJlrlzkAWBOWiLj/jJ76D7l+UXoizP2KI2C7I2FccqMmIfFmmkUy32nIJ0mZH" + "IWoJoQYCBFRDO46iBAICASyjggR6MIIEdjCCA16gAwIBAgIIK9dUvsPWSlUwDQYJ" + "KoZIhvcNAQEFBQAwSTELMAkGA1UEBhMCVVMxEzARBgNVBAoTCkdvb2dsZSBJbmMx" + "JTAjBgNVBAMTHEdvb2dsZSBJbnRlcm5ldCBBdXRob3JpdHkgRzIwHhcNMTQxMDA4" + "MTIwNzU3WhcNMTUwMTA2MDAwMDAwWjBoMQswCQYDVQQGEwJVUzETMBEGA1UECAwK" + "Q2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzETMBEGA1UECgwKR29v" + "Z2xlIEluYzEXMBUGA1UEAwwOd3d3Lmdvb2dsZS5jb20wggEiMA0GCSqGSIb3DQEB" + "AQUAA4IBDwAwggEKAoIBAQCcKeLrplAC+Lofy8t/wDwtB6eu72CVp0cJ4V3lknN6" + "huH9ct6FFk70oRIh/VBNBBz900jYy+7111Jm1b8iqOTQ9aT5C7SEhNcQFJvqzH3e" + "MPkb6ZSWGm1yGF7MCQTGQXF20Sk/O16FSjAynU/b3oJmOctcycWYkY0ytS/k3LBu" + "Id45PJaoMqjB0WypqvNeJHC3q5JjCB4RP7Nfx5jjHSrCMhw8lUMW4EaDxjaR9KDh" + "PLgjsk+LDIySRSRDaCQGhEOWLJZVLzLo4N6/UlctCHEllpBUSvEOyFga52qroGjg" + "rf3WOQ925MFwzd6AK+Ich0gDRg8sQfdLH5OuP1cfLfU1AgMBAAGjggFBMIIBPTAd" + "BgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwGQYDVR0RBBIwEIIOd3d3Lmdv" + "b2dsZS5jb20waAYIKwYBBQUHAQEEXDBaMCsGCCsGAQUFBzAChh9odHRwOi8vcGtp" + "Lmdvb2dsZS5jb20vR0lBRzIuY3J0MCsGCCsGAQUFBzABhh9odHRwOi8vY2xpZW50" + "czEuZ29vZ2xlLmNvbS9vY3NwMB0GA1UdDgQWBBQ7a+CcxsZByOpc+xpYFcIbnUMZ" + "hTAMBgNVHRMBAf8EAjAAMB8GA1UdIwQYMBaAFErdBhYbvPZotXb1gba7Yhq6WoEv" + "MBcGA1UdIAQQMA4wDAYKKwYBBAHWeQIFATAwBgNVHR8EKTAnMCWgI6Ahhh9odHRw" + "Oi8vcGtpLmdvb2dsZS5jb20vR0lBRzIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQCa" + "OXCBdoqUy5bxyq+Wrh1zsyyCFim1PH5VU2+yvDSWrgDY8ibRGJmfff3r4Lud5kal" + "dKs9k8YlKD3ITG7P0YT/Rk8hLgfEuLcq5cc0xqmE42xJ+Eo2uzq9rYorc5emMCxf" + "5L0TJOXZqHQpOEcuptZQ4OjdYMfSxk5UzueUhA3ogZKRcRkdB3WeWRp+nYRhx4St" + "o2rt2A0MKmY9165GHUqMK9YaaXHDXqBu7Sefr1uSoAP9gyIJKeihMivsGqJ1TD6Z" + "cc6LMe+dN2P8cZEQHtD1y296ul4Mivqk3jatUVL8/hCwgch9A8O4PGZq9WqBfEWm" + "IyHh1dPtbg1lOXdYCWtjpAIEAKUDAgEUqQUCAwGJwKqBpwSBpBwUQvoeOk0Kg36S" + "YTcLEkXqKwOBfF9vE4KX0NxeLwjcDTpsuh3qXEaZ992r1N38VDcyS6P7I6HBYN9B" + "sNHM362zZnY27GpTw+Kwd751CLoXFPoaMOe57dbBpXoro6Pd3BTbf/Tzr88K06yE" + "OTDKPNj3+inbMaVigtK4PLyPq+Topyzvx9USFgRvyuoxn0Hgb+R0A3j6SLRuyOdA" + "i4gv7Y5oliyn"; + +// kCustomSession is a custom serialized SSL_SESSION generated by +// filling in missing fields from |kOpenSSLSession|. This includes +// providing |peer_sha256|, so |peer| is not serialized. +static const char kCustomSession[] = + "MIIBdgIBAQICAwMEAsAvBCAG5Q1ndq4Yfmbeo1zwLkNRKmCXGdNgWvGT3cskV0yQ" + "kAQwJlrlzkAWBOWiLj/jJ76D7l+UXoizP2KI2C7I2FccqMmIfFmmkUy32nIJ0mZH" + "IWoJoQYCBFRDO46iBAICASykAwQBAqUDAgEUphAEDnd3dy5nb29nbGUuY29tqAcE" + "BXdvcmxkqQUCAwGJwKqBpwSBpBwUQvoeOk0Kg36SYTcLEkXqKwOBfF9vE4KX0Nxe" + "LwjcDTpsuh3qXEaZ992r1N38VDcyS6P7I6HBYN9BsNHM362zZnY27GpTw+Kwd751" + "CLoXFPoaMOe57dbBpXoro6Pd3BTbf/Tzr88K06yEOTDKPNj3+inbMaVigtK4PLyP" + "q+Topyzvx9USFgRvyuoxn0Hgb+R0A3j6SLRuyOdAi4gv7Y5oliynrSIEIAYGBgYG" + "BgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGrgMEAQevAwQBBLADBAEF"; + +// kBoringSSLSession is a serialized SSL_SESSION generated from bssl client. +static const char kBoringSSLSession[] = + "MIIRwQIBAQICAwMEAsAvBCDdoGxGK26mR+8lM0uq6+k9xYuxPnwAjpcF9n0Yli9R" + "kQQwbyshfWhdi5XQ1++7n2L1qqrcVlmHBPpr6yknT/u4pUrpQB5FZ7vqvNn8MdHf" + "9rWgoQYCBFXgs7uiBAICHCCjggR6MIIEdjCCA16gAwIBAgIIf+yfD7Y6UicwDQYJ" + "KoZIhvcNAQELBQAwSTELMAkGA1UEBhMCVVMxEzARBgNVBAoTCkdvb2dsZSBJbmMx" + "JTAjBgNVBAMTHEdvb2dsZSBJbnRlcm5ldCBBdXRob3JpdHkgRzIwHhcNMTUwODEy" + "MTQ1MzE1WhcNMTUxMTEwMDAwMDAwWjBoMQswCQYDVQQGEwJVUzETMBEGA1UECAwK" + "Q2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzETMBEGA1UECgwKR29v" + "Z2xlIEluYzEXMBUGA1UEAwwOd3d3Lmdvb2dsZS5jb20wggEiMA0GCSqGSIb3DQEB" + "AQUAA4IBDwAwggEKAoIBAQC0MeG5YGQ0t+IeJeoneP/PrhEaieibeKYkbKVLNZpo" + "PLuBinvhkXZo3DC133NpCBpy6ZktBwamqyixAyuk/NU6OjgXqwwxfQ7di1AInLIU" + "792c7hFyNXSUCG7At8Ifi3YwBX9Ba6u/1d6rWTGZJrdCq3QU11RkKYyTq2KT5mce" + "Tv9iGKqSkSTlp8puy/9SZ/3DbU3U+BuqCFqeSlz7zjwFmk35acdCilpJlVDDN5C/" + "RCh8/UKc8PaL+cxlt531qoTENvYrflBno14YEZlCBZsPiFeUSILpKEj3Ccwhy0eL" + "EucWQ72YZU8mUzXBoXGn0zA0crFl5ci/2sTBBGZsylNBAgMBAAGjggFBMIIBPTAd" + "BgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwGQYDVR0RBBIwEIIOd3d3Lmdv" + "b2dsZS5jb20waAYIKwYBBQUHAQEEXDBaMCsGCCsGAQUFBzAChh9odHRwOi8vcGtp" + "Lmdvb2dsZS5jb20vR0lBRzIuY3J0MCsGCCsGAQUFBzABhh9odHRwOi8vY2xpZW50" + "czEuZ29vZ2xlLmNvbS9vY3NwMB0GA1UdDgQWBBS/bzHxcE73Q4j3slC4BLbMtLjG" + "GjAMBgNVHRMBAf8EAjAAMB8GA1UdIwQYMBaAFErdBhYbvPZotXb1gba7Yhq6WoEv" + "MBcGA1UdIAQQMA4wDAYKKwYBBAHWeQIFATAwBgNVHR8EKTAnMCWgI6Ahhh9odHRw" + "Oi8vcGtpLmdvb2dsZS5jb20vR0lBRzIuY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQAb" + "qdWPZEHk0X7iKPCTHL6S3w6q1eR67goxZGFSM1lk1hjwyu7XcLJuvALVV9uY3ovE" + "kQZSHwT+pyOPWQhsSjO+1GyjvCvK/CAwiUmBX+bQRGaqHsRcio7xSbdVcajQ3bXd" + "X+s0WdbOpn6MStKAiBVloPlSxEI8pxY6x/BBCnTIk/+DMB17uZlOjG3vbAnkDkP+" + "n0OTucD9sHV7EVj9XUxi51nOfNBCN/s7lpUjDS/NJ4k3iwOtbCPswiot8vLO779a" + "f07vR03r349Iz/KTzk95rlFtX0IU+KYNxFNsanIXZ+C9FYGRXkwhHcvFb4qMUB1y" + "TTlM80jBMOwyjZXmjRAhpAIEAKUDAgEUqQUCAwGJwKqBpwSBpOgebbmn9NRUtMWH" + "+eJpqA5JLMFSMCChOsvKey3toBaCNGU7HfAEiiXNuuAdCBoK262BjQc2YYfqFzqH" + "zuppopXCvhohx7j/tnCNZIMgLYt/O9SXK2RYI5z8FhCCHvB4CbD5G0LGl5EFP27s" + "Jb6S3aTTYPkQe8yZSlxevg6NDwmTogLO9F7UUkaYmVcMQhzssEE2ZRYNwSOU6KjE" + "0Yj+8fAiBtbQriIEIN2L8ZlpaVrdN5KFNdvcmOxJu81P8q53X55xQyGTnGWwsgMC" + "ARezggvvMIIEdjCCA16gAwIBAgIIf+yfD7Y6UicwDQYJKoZIhvcNAQELBQAwSTEL" + "MAkGA1UEBhMCVVMxEzARBgNVBAoTCkdvb2dsZSBJbmMxJTAjBgNVBAMTHEdvb2ds" + "ZSBJbnRlcm5ldCBBdXRob3JpdHkgRzIwHhcNMTUwODEyMTQ1MzE1WhcNMTUxMTEw" + "MDAwMDAwWjBoMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQG" + "A1UEBwwNTW91bnRhaW4gVmlldzETMBEGA1UECgwKR29vZ2xlIEluYzEXMBUGA1UE" + "AwwOd3d3Lmdvb2dsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB" + "AQC0MeG5YGQ0t+IeJeoneP/PrhEaieibeKYkbKVLNZpoPLuBinvhkXZo3DC133Np" + "CBpy6ZktBwamqyixAyuk/NU6OjgXqwwxfQ7di1AInLIU792c7hFyNXSUCG7At8If" + "i3YwBX9Ba6u/1d6rWTGZJrdCq3QU11RkKYyTq2KT5mceTv9iGKqSkSTlp8puy/9S" + "Z/3DbU3U+BuqCFqeSlz7zjwFmk35acdCilpJlVDDN5C/RCh8/UKc8PaL+cxlt531" + "qoTENvYrflBno14YEZlCBZsPiFeUSILpKEj3Ccwhy0eLEucWQ72YZU8mUzXBoXGn" + "0zA0crFl5ci/2sTBBGZsylNBAgMBAAGjggFBMIIBPTAdBgNVHSUEFjAUBggrBgEF" + "BQcDAQYIKwYBBQUHAwIwGQYDVR0RBBIwEIIOd3d3Lmdvb2dsZS5jb20waAYIKwYB" + "BQUHAQEEXDBaMCsGCCsGAQUFBzAChh9odHRwOi8vcGtpLmdvb2dsZS5jb20vR0lB" + "RzIuY3J0MCsGCCsGAQUFBzABhh9odHRwOi8vY2xpZW50czEuZ29vZ2xlLmNvbS9v" + "Y3NwMB0GA1UdDgQWBBS/bzHxcE73Q4j3slC4BLbMtLjGGjAMBgNVHRMBAf8EAjAA" + "MB8GA1UdIwQYMBaAFErdBhYbvPZotXb1gba7Yhq6WoEvMBcGA1UdIAQQMA4wDAYK" + "KwYBBAHWeQIFATAwBgNVHR8EKTAnMCWgI6Ahhh9odHRwOi8vcGtpLmdvb2dsZS5j" + "b20vR0lBRzIuY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQAbqdWPZEHk0X7iKPCTHL6S" + "3w6q1eR67goxZGFSM1lk1hjwyu7XcLJuvALVV9uY3ovEkQZSHwT+pyOPWQhsSjO+" + "1GyjvCvK/CAwiUmBX+bQRGaqHsRcio7xSbdVcajQ3bXdX+s0WdbOpn6MStKAiBVl" + "oPlSxEI8pxY6x/BBCnTIk/+DMB17uZlOjG3vbAnkDkP+n0OTucD9sHV7EVj9XUxi" + "51nOfNBCN/s7lpUjDS/NJ4k3iwOtbCPswiot8vLO779af07vR03r349Iz/KTzk95" + "rlFtX0IU+KYNxFNsanIXZ+C9FYGRXkwhHcvFb4qMUB1yTTlM80jBMOwyjZXmjRAh" + "MIID8DCCAtigAwIBAgIDAjqDMA0GCSqGSIb3DQEBCwUAMEIxCzAJBgNVBAYTAlVT" + "MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i" + "YWwgQ0EwHhcNMTMwNDA1MTUxNTU2WhcNMTYxMjMxMjM1OTU5WjBJMQswCQYDVQQG" + "EwJVUzETMBEGA1UEChMKR29vZ2xlIEluYzElMCMGA1UEAxMcR29vZ2xlIEludGVy" + "bmV0IEF1dGhvcml0eSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB" + "AJwqBHdc2FCROgajguDYUEi8iT/xGXAaiEZ+4I/F8YnOIe5a/mENtzJEiaB0C1NP" + "VaTOgmKV7utZX8bhBYASxF6UP7xbSDj0U/ck5vuR6RXEz/RTDfRK/J9U3n2+oGtv" + "h8DQUB8oMANA2ghzUWx//zo8pzcGjr1LEQTrfSTe5vn8MXH7lNVg8y5Kr0LSy+rE" + "ahqyzFPdFUuLH8gZYR/Nnag+YyuENWllhMgZxUYi+FOVvuOAShDGKuy6lyARxzmZ" + "EASg8GF6lSWMTlJ14rbtCMoU/M4iarNOz0YDl5cDfsCx3nuvRTPPuj5xt970JSXC" + "DTWJnZ37DhF5iR43xa+OcmkCAwEAAaOB5zCB5DAfBgNVHSMEGDAWgBTAephojYn7" + "qwVkDBF9qn1luMrMTjAdBgNVHQ4EFgQUSt0GFhu89mi1dvWBtrtiGrpagS8wDgYD" + "VR0PAQH/BAQDAgEGMC4GCCsGAQUFBwEBBCIwIDAeBggrBgEFBQcwAYYSaHR0cDov" + "L2cuc3ltY2QuY29tMBIGA1UdEwEB/wQIMAYBAf8CAQAwNQYDVR0fBC4wLDAqoCig" + "JoYkaHR0cDovL2cuc3ltY2IuY29tL2NybHMvZ3RnbG9iYWwuY3JsMBcGA1UdIAQQ" + "MA4wDAYKKwYBBAHWeQIFATANBgkqhkiG9w0BAQsFAAOCAQEAqvqpIM1qZ4PtXtR+" + "3h3Ef+AlBgDFJPupyC1tft6dgmUsgWM0Zj7pUsIItMsv91+ZOmqcUHqFBYx90SpI" + "hNMJbHzCzTWf84LuUt5oX+QAihcglvcpjZpNy6jehsgNb1aHA30DP9z6eX0hGfnI" + "Oi9RdozHQZJxjyXON/hKTAAj78Q1EK7gI4BzfE00LshukNYQHpmEcxpw8u1VDu4X" + "Bupn7jLrLN1nBz/2i8Jw3lsA5rsb0zYaImxssDVCbJAJPZPpZAkiDoUGn8JzIdPm" + "X4DkjYUiOnMDsWCOrmji9D6X52ASCWg23jrW4kOVWzeBkoEfu43XrVJkFleW2V40" + "fsg12DCCA30wggLmoAMCAQICAxK75jANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQG" + "EwJVUzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUg" + "Q2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTAyMDUyMTA0MDAwMFoXDTE4MDgyMTA0" + "MDAwMFowQjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xGzAZ" + "BgNVBAMTEkdlb1RydXN0IEdsb2JhbCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP" + "ADCCAQoCggEBANrMGGMw/fQXIxpWflvfPGw45HG3eJHUvKHYTPioQ7YD6U0hBwiI" + "2lgvZjkpvQV4i5046AW3an5xpObEYKaw74DkiSgPniXW7YPzraaRx5jJQhg1FJ2t" + "mEaSLk/K8YdDwRaVVy1Q74ktgHpXrfLuX2vSAI25FPgUFTXZwEaje3LIkb/JVSvN" + "0Jc+nCZkzN/Ogxlxyk7m1NV7qRnNVd7I7NJeOFPlXE+MLf5QIzb8ZubLjqQ5GQC3" + "lQI5kQsO/jgu0R0FmvZNPm8PBx2vLB6PYDni+jZTEznUXiYr2z2oFL0y6xgDKFIE" + "ceWrMz3hOLsHNoRinHnqFjD0X8Ar6HFr5PkCAwEAAaOB8DCB7TAfBgNVHSMEGDAW" + "gBRI5mj5K9KylddH2CMgEE8zmJCf1DAdBgNVHQ4EFgQUwHqYaI2J+6sFZAwRfap9" + "ZbjKzE4wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwOgYDVR0fBDMw" + "MTAvoC2gK4YpaHR0cDovL2NybC5nZW90cnVzdC5jb20vY3Jscy9zZWN1cmVjYS5j" + "cmwwTgYDVR0gBEcwRTBDBgRVHSAAMDswOQYIKwYBBQUHAgEWLWh0dHBzOi8vd3d3" + "Lmdlb3RydXN0LmNvbS9yZXNvdXJjZXMvcmVwb3NpdG9yeTANBgkqhkiG9w0BAQUF" + "AAOBgQB24RJuTksWEoYwBrKBCM/wCMfHcX5m7sLt1Dsf//DwyE7WQziwuTB9GNBV" + "g6JqyzYRnOhIZqNtf7gT1Ef+i1pcc/yu2RsyGTirlzQUqpbS66McFAhJtrvlke+D" + "NusdVm/K2rxzY5Dkf3s+Iss9B+1fOHSc4wNQTqGvmO5h8oQ/Eg=="; + +// kBadSessionExtraField is a custom serialized SSL_SESSION generated by replacing +// the final (optional) element of |kCustomSession| with tag number 30. +static const char kBadSessionExtraField[] = + "MIIBdgIBAQICAwMEAsAvBCAG5Q1ndq4Yfmbeo1zwLkNRKmCXGdNgWvGT3cskV0yQ" + "kAQwJlrlzkAWBOWiLj/jJ76D7l+UXoizP2KI2C7I2FccqMmIfFmmkUy32nIJ0mZH" + "IWoJoQYCBFRDO46iBAICASykAwQBAqUDAgEUphAEDnd3dy5nb29nbGUuY29tqAcE" + "BXdvcmxkqQUCAwGJwKqBpwSBpBwUQvoeOk0Kg36SYTcLEkXqKwOBfF9vE4KX0Nxe" + "LwjcDTpsuh3qXEaZ992r1N38VDcyS6P7I6HBYN9BsNHM362zZnY27GpTw+Kwd751" + "CLoXFPoaMOe57dbBpXoro6Pd3BTbf/Tzr88K06yEOTDKPNj3+inbMaVigtK4PLyP" + "q+Topyzvx9USFgRvyuoxn0Hgb+R0A3j6SLRuyOdAi4gv7Y5oliynrSIEIAYGBgYG" + "BgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGrgMEAQevAwQBBL4DBAEF"; + +// kBadSessionVersion is a custom serialized SSL_SESSION generated by replacing +// the version of |kCustomSession| with 2. +static const char kBadSessionVersion[] = + "MIIBdgIBAgICAwMEAsAvBCAG5Q1ndq4Yfmbeo1zwLkNRKmCXGdNgWvGT3cskV0yQ" + "kAQwJlrlzkAWBOWiLj/jJ76D7l+UXoizP2KI2C7I2FccqMmIfFmmkUy32nIJ0mZH" + "IWoJoQYCBFRDO46iBAICASykAwQBAqUDAgEUphAEDnd3dy5nb29nbGUuY29tqAcE" + "BXdvcmxkqQUCAwGJwKqBpwSBpBwUQvoeOk0Kg36SYTcLEkXqKwOBfF9vE4KX0Nxe" + "LwjcDTpsuh3qXEaZ992r1N38VDcyS6P7I6HBYN9BsNHM362zZnY27GpTw+Kwd751" + "CLoXFPoaMOe57dbBpXoro6Pd3BTbf/Tzr88K06yEOTDKPNj3+inbMaVigtK4PLyP" + "q+Topyzvx9USFgRvyuoxn0Hgb+R0A3j6SLRuyOdAi4gv7Y5oliynrSIEIAYGBgYG" + "BgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGrgMEAQevAwQBBLADBAEF"; + +// kBadSessionTrailingData is a custom serialized SSL_SESSION with trailing data +// appended. +static const char kBadSessionTrailingData[] = + "MIIBdgIBAQICAwMEAsAvBCAG5Q1ndq4Yfmbeo1zwLkNRKmCXGdNgWvGT3cskV0yQ" + "kAQwJlrlzkAWBOWiLj/jJ76D7l+UXoizP2KI2C7I2FccqMmIfFmmkUy32nIJ0mZH" + "IWoJoQYCBFRDO46iBAICASykAwQBAqUDAgEUphAEDnd3dy5nb29nbGUuY29tqAcE" + "BXdvcmxkqQUCAwGJwKqBpwSBpBwUQvoeOk0Kg36SYTcLEkXqKwOBfF9vE4KX0Nxe" + "LwjcDTpsuh3qXEaZ992r1N38VDcyS6P7I6HBYN9BsNHM362zZnY27GpTw+Kwd751" + "CLoXFPoaMOe57dbBpXoro6Pd3BTbf/Tzr88K06yEOTDKPNj3+inbMaVigtK4PLyP" + "q+Topyzvx9USFgRvyuoxn0Hgb+R0A3j6SLRuyOdAi4gv7Y5oliynrSIEIAYGBgYG" + "BgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGrgMEAQevAwQBBLADBAEFAAAA"; + +static bool DecodeBase64(std::vector *out, const char *in) { + size_t len; + if (!EVP_DecodedLength(&len, strlen(in))) { + fprintf(stderr, "EVP_DecodedLength failed\n"); + return false; + } + + out->resize(len); + if (!EVP_DecodeBase64(out->data(), &len, len, (const uint8_t *)in, + strlen(in))) { + fprintf(stderr, "EVP_DecodeBase64 failed\n"); + return false; + } + out->resize(len); + return true; +} + +static bool TestSSL_SESSIONEncoding(const char *input_b64) { + const uint8_t *cptr; + uint8_t *ptr; + + // Decode the input. + std::vector input; + if (!DecodeBase64(&input, input_b64)) { + return false; + } + + // Verify the SSL_SESSION decodes. + ScopedSSL_SESSION session(SSL_SESSION_from_bytes(input.data(), input.size())); + if (!session) { + fprintf(stderr, "SSL_SESSION_from_bytes failed\n"); + return false; + } + + // Verify the SSL_SESSION encoding round-trips. + size_t encoded_len; + ScopedOpenSSLBytes encoded; + uint8_t *encoded_raw; + if (!SSL_SESSION_to_bytes(session.get(), &encoded_raw, &encoded_len)) { + fprintf(stderr, "SSL_SESSION_to_bytes failed\n"); + return false; + } + encoded.reset(encoded_raw); + if (encoded_len != input.size() || + memcmp(input.data(), encoded.get(), input.size()) != 0) { + fprintf(stderr, "SSL_SESSION_to_bytes did not round-trip\n"); + hexdump(stderr, "Before: ", input.data(), input.size()); + hexdump(stderr, "After: ", encoded_raw, encoded_len); + return false; + } + + // Verify the SSL_SESSION also decodes with the legacy API. + cptr = input.data(); + session.reset(d2i_SSL_SESSION(NULL, &cptr, input.size())); + if (!session || cptr != input.data() + input.size()) { + fprintf(stderr, "d2i_SSL_SESSION failed\n"); + return false; + } + + // Verify the SSL_SESSION encoding round-trips via the legacy API. + int len = i2d_SSL_SESSION(session.get(), NULL); + if (len < 0 || (size_t)len != input.size()) { + fprintf(stderr, "i2d_SSL_SESSION(NULL) returned invalid length\n"); + return false; + } + + encoded.reset((uint8_t *)OPENSSL_malloc(input.size())); + if (!encoded) { + fprintf(stderr, "malloc failed\n"); + return false; + } + + ptr = encoded.get(); + len = i2d_SSL_SESSION(session.get(), &ptr); + if (len < 0 || (size_t)len != input.size()) { + fprintf(stderr, "i2d_SSL_SESSION returned invalid length\n"); + return false; + } + if (ptr != encoded.get() + input.size()) { + fprintf(stderr, "i2d_SSL_SESSION did not advance ptr correctly\n"); + return false; + } + if (memcmp(input.data(), encoded.get(), input.size()) != 0) { + fprintf(stderr, "i2d_SSL_SESSION did not round-trip\n"); + return false; + } + + return true; +} + +static bool TestBadSSL_SESSIONEncoding(const char *input_b64) { + std::vector input; + if (!DecodeBase64(&input, input_b64)) { + return false; + } + + // Verify that the SSL_SESSION fails to decode. + ScopedSSL_SESSION session(SSL_SESSION_from_bytes(input.data(), input.size())); + if (session) { + fprintf(stderr, "SSL_SESSION_from_bytes unexpectedly succeeded\n"); + return false; + } + ERR_clear_error(); + return true; +} + +static bool TestDefaultVersion(uint16_t version, + const SSL_METHOD *(*method)(void)) { + ScopedSSL_CTX ctx(SSL_CTX_new(method())); + if (!ctx) { + return false; + } + // TODO(svaldez): Remove TLS1_2_VERSION fallback upon implementing TLS 1.3. + return ctx->min_version == version && + (ctx->max_version == version || + (version == 0 && ctx->max_version == TLS1_2_VERSION)); +} + +static bool CipherGetRFCName(std::string *out, uint16_t value) { + const SSL_CIPHER *cipher = SSL_get_cipher_by_value(value); + if (cipher == NULL) { + return false; + } + ScopedOpenSSLString rfc_name(SSL_CIPHER_get_rfc_name(cipher)); + if (!rfc_name) { + return false; + } + out->assign(rfc_name.get()); + return true; +} + +typedef struct { + int id; + const char *rfc_name; +} CIPHER_RFC_NAME_TEST; + +static const CIPHER_RFC_NAME_TEST kCipherRFCNameTests[] = { + { SSL3_CK_RSA_DES_192_CBC3_SHA, "TLS_RSA_WITH_3DES_EDE_CBC_SHA" }, + { SSL3_CK_RSA_RC4_128_MD5, "TLS_RSA_WITH_RC4_MD5" }, + { TLS1_CK_RSA_WITH_AES_128_SHA, "TLS_RSA_WITH_AES_128_CBC_SHA" }, + { TLS1_CK_DHE_RSA_WITH_AES_256_SHA, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA" }, + { TLS1_CK_DHE_RSA_WITH_AES_256_SHA256, + "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256" }, + { TLS1_CK_ECDHE_RSA_WITH_AES_128_SHA256, + "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256" }, + { TLS1_CK_ECDHE_RSA_WITH_AES_256_SHA384, + "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384" }, + { TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" }, + { TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" }, + { TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384" }, + { TLS1_CK_PSK_WITH_RC4_128_SHA, "TLS_PSK_WITH_RC4_SHA" }, + { TLS1_CK_ECDHE_PSK_WITH_AES_128_CBC_SHA, + "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA" }, + { TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256" }, + // These names are non-standard: + { TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD, + "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256" }, + { TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD, + "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256" }, +}; + +static bool TestCipherGetRFCName(void) { + for (size_t i = 0; + i < sizeof(kCipherRFCNameTests) / sizeof(kCipherRFCNameTests[0]); i++) { + const CIPHER_RFC_NAME_TEST *test = &kCipherRFCNameTests[i]; + std::string rfc_name; + if (!CipherGetRFCName(&rfc_name, test->id & 0xffff)) { + fprintf(stderr, "SSL_CIPHER_get_rfc_name failed\n"); + return false; + } + if (rfc_name != test->rfc_name) { + fprintf(stderr, "SSL_CIPHER_get_rfc_name: got '%s', wanted '%s'\n", + rfc_name.c_str(), test->rfc_name); + return false; + } + } + return true; +} + +// CreateSessionWithTicket returns a sample |SSL_SESSION| with the ticket +// replaced for one of length |ticket_len| or nullptr on failure. +static ScopedSSL_SESSION CreateSessionWithTicket(size_t ticket_len) { + std::vector der; + if (!DecodeBase64(&der, kOpenSSLSession)) { + return nullptr; + } + ScopedSSL_SESSION session(SSL_SESSION_from_bytes(der.data(), der.size())); + if (!session) { + return nullptr; + } + + // Swap out the ticket for a garbage one. + OPENSSL_free(session->tlsext_tick); + session->tlsext_tick = reinterpret_cast(OPENSSL_malloc(ticket_len)); + if (session->tlsext_tick == nullptr) { + return nullptr; + } + memset(session->tlsext_tick, 'a', ticket_len); + session->tlsext_ticklen = ticket_len; + + // Fix up the timeout. + session->time = time(NULL); + return session; +} + +// GetClientHelloLen creates a client SSL connection with a ticket of length +// |ticket_len| and records the ClientHello. It returns the length of the +// ClientHello, not including the record header, on success and zero on error. +static size_t GetClientHelloLen(size_t ticket_len) { + ScopedSSL_CTX ctx(SSL_CTX_new(TLS_method())); + ScopedSSL_SESSION session = CreateSessionWithTicket(ticket_len); + if (!ctx || !session) { + return 0; + } + ScopedSSL ssl(SSL_new(ctx.get())); + ScopedBIO bio(BIO_new(BIO_s_mem())); + if (!ssl || !bio || !SSL_set_session(ssl.get(), session.get())) { + return 0; + } + // Do not configure a reading BIO, but record what's written to a memory BIO. + SSL_set_bio(ssl.get(), nullptr /* rbio */, BIO_up_ref(bio.get())); + int ret = SSL_connect(ssl.get()); + if (ret > 0) { + // SSL_connect should fail without a BIO to write to. + return 0; + } + ERR_clear_error(); + + const uint8_t *unused; + size_t client_hello_len; + if (!BIO_mem_contents(bio.get(), &unused, &client_hello_len) || + client_hello_len <= SSL3_RT_HEADER_LENGTH) { + return 0; + } + return client_hello_len - SSL3_RT_HEADER_LENGTH; +} + +struct PaddingTest { + size_t input_len, padded_len; +}; + +static const PaddingTest kPaddingTests[] = { + // ClientHellos of length below 0x100 do not require padding. + {0xfe, 0xfe}, + {0xff, 0xff}, + // ClientHellos of length 0x100 through 0x1fb are padded up to 0x200. + {0x100, 0x200}, + {0x123, 0x200}, + {0x1fb, 0x200}, + // ClientHellos of length 0x1fc through 0x1ff get padded beyond 0x200. The + // padding extension takes a minimum of four bytes plus one required content + // byte. (To work around yet more server bugs, we avoid empty final + // extensions.) + {0x1fc, 0x201}, + {0x1fd, 0x202}, + {0x1fe, 0x203}, + {0x1ff, 0x204}, + // Finally, larger ClientHellos need no padding. + {0x200, 0x200}, + {0x201, 0x201}, +}; + +static bool TestPaddingExtension() { + // Sample a baseline length. + size_t base_len = GetClientHelloLen(1); + if (base_len == 0) { + return false; + } + + for (const PaddingTest &test : kPaddingTests) { + if (base_len > test.input_len) { + fprintf(stderr, "Baseline ClientHello too long.\n"); + return false; + } + + size_t padded_len = GetClientHelloLen(1 + test.input_len - base_len); + if (padded_len != test.padded_len) { + fprintf(stderr, "%u-byte ClientHello padded to %u bytes, not %u.\n", + static_cast(test.input_len), + static_cast(padded_len), + static_cast(test.padded_len)); + return false; + } + } + return true; +} + +// Test that |SSL_get_client_CA_list| echoes back the configured parameter even +// before configuring as a server. +static bool TestClientCAList() { + ScopedSSL_CTX ctx(SSL_CTX_new(TLS_method())); + if (!ctx) { + return false; + } + ScopedSSL ssl(SSL_new(ctx.get())); + if (!ssl) { + return false; + } + + STACK_OF(X509_NAME) *stack = sk_X509_NAME_new_null(); + if (stack == nullptr) { + return false; + } + // |SSL_set_client_CA_list| takes ownership. + SSL_set_client_CA_list(ssl.get(), stack); + + return SSL_get_client_CA_list(ssl.get()) == stack; +} + +static void AppendSession(SSL_SESSION *session, void *arg) { + std::vector *out = + reinterpret_cast*>(arg); + out->push_back(session); +} + +// ExpectCache returns true if |ctx|'s session cache consists of |expected|, in +// order. +static bool ExpectCache(SSL_CTX *ctx, + const std::vector &expected) { + // Check the linked list. + SSL_SESSION *ptr = ctx->session_cache_head; + for (SSL_SESSION *session : expected) { + if (ptr != session) { + return false; + } + // TODO(davidben): This is an absurd way to denote the end of the list. + if (ptr->next == + reinterpret_cast(&ctx->session_cache_tail)) { + ptr = nullptr; + } else { + ptr = ptr->next; + } + } + if (ptr != nullptr) { + return false; + } + + // Check the hash table. + std::vector actual, expected_copy; + lh_SSL_SESSION_doall_arg(SSL_CTX_sessions(ctx), AppendSession, &actual); + expected_copy = expected; + + std::sort(actual.begin(), actual.end()); + std::sort(expected_copy.begin(), expected_copy.end()); + + return actual == expected_copy; +} + +static ScopedSSL_SESSION CreateTestSession(uint32_t number) { + ScopedSSL_SESSION ret(SSL_SESSION_new()); + if (!ret) { + return nullptr; + } + + ret->session_id_length = SSL3_SSL_SESSION_ID_LENGTH; + memset(ret->session_id, 0, ret->session_id_length); + memcpy(ret->session_id, &number, sizeof(number)); + return ret; +} + +// Test that the internal session cache behaves as expected. +static bool TestInternalSessionCache() { + ScopedSSL_CTX ctx(SSL_CTX_new(TLS_method())); + if (!ctx) { + return false; + } + + // Prepare 10 test sessions. + std::vector sessions; + for (int i = 0; i < 10; i++) { + ScopedSSL_SESSION session = CreateTestSession(i); + if (!session) { + return false; + } + sessions.push_back(std::move(session)); + } + + SSL_CTX_sess_set_cache_size(ctx.get(), 5); + + // Insert all the test sessions. + for (const auto &session : sessions) { + if (!SSL_CTX_add_session(ctx.get(), session.get())) { + return false; + } + } + + // Only the last five should be in the list. + std::vector expected = { + sessions[9].get(), + sessions[8].get(), + sessions[7].get(), + sessions[6].get(), + sessions[5].get(), + }; + if (!ExpectCache(ctx.get(), expected)) { + return false; + } + + // Inserting an element already in the cache should fail. + if (SSL_CTX_add_session(ctx.get(), sessions[7].get()) || + !ExpectCache(ctx.get(), expected)) { + return false; + } + + // Although collisions should be impossible (256-bit session IDs), the cache + // must handle them gracefully. + ScopedSSL_SESSION collision(CreateTestSession(7)); + if (!collision || !SSL_CTX_add_session(ctx.get(), collision.get())) { + return false; + } + expected = { + collision.get(), + sessions[9].get(), + sessions[8].get(), + sessions[6].get(), + sessions[5].get(), + }; + if (!ExpectCache(ctx.get(), expected)) { + return false; + } + + // Removing sessions behaves correctly. + if (!SSL_CTX_remove_session(ctx.get(), sessions[6].get())) { + return false; + } + expected = { + collision.get(), + sessions[9].get(), + sessions[8].get(), + sessions[5].get(), + }; + if (!ExpectCache(ctx.get(), expected)) { + return false; + } + + // Removing sessions requires an exact match. + if (SSL_CTX_remove_session(ctx.get(), sessions[0].get()) || + SSL_CTX_remove_session(ctx.get(), sessions[7].get()) || + !ExpectCache(ctx.get(), expected)) { + return false; + } + + return true; +} + +static uint16_t EpochFromSequence(uint64_t seq) { + return static_cast(seq >> 48); +} + +static ScopedX509 GetTestCertificate() { + static const char kCertPEM[] = + "-----BEGIN CERTIFICATE-----\n" + "MIICWDCCAcGgAwIBAgIJAPuwTC6rEJsMMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV\n" + "BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX\n" + "aWRnaXRzIFB0eSBMdGQwHhcNMTQwNDIzMjA1MDQwWhcNMTcwNDIyMjA1MDQwWjBF\n" + "MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50\n" + "ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB\n" + "gQDYK8imMuRi/03z0K1Zi0WnvfFHvwlYeyK9Na6XJYaUoIDAtB92kWdGMdAQhLci\n" + "HnAjkXLI6W15OoV3gA/ElRZ1xUpxTMhjP6PyY5wqT5r6y8FxbiiFKKAnHmUcrgfV\n" + "W28tQ+0rkLGMryRtrukXOgXBv7gcrmU7G1jC2a7WqmeI8QIDAQABo1AwTjAdBgNV\n" + "HQ4EFgQUi3XVrMsIvg4fZbf6Vr5sp3Xaha8wHwYDVR0jBBgwFoAUi3XVrMsIvg4f\n" + "Zbf6Vr5sp3Xaha8wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQA76Hht\n" + "ldY9avcTGSwbwoiuIqv0jTL1fHFnzy3RHMLDh+Lpvolc5DSrSJHCP5WuK0eeJXhr\n" + "T5oQpHL9z/cCDLAKCKRa4uV0fhEdOWBqyR9p8y5jJtye72t6CuFUV5iqcpF4BH4f\n" + "j2VNHwsSrJwkD4QUGlUtH7vwnQmyCFxZMmWAJg==\n" + "-----END CERTIFICATE-----\n"; + ScopedBIO bio(BIO_new_mem_buf(kCertPEM, strlen(kCertPEM))); + return ScopedX509(PEM_read_bio_X509(bio.get(), nullptr, nullptr, nullptr)); +} + +static ScopedEVP_PKEY GetTestKey() { + static const char kKeyPEM[] = + "-----BEGIN RSA PRIVATE KEY-----\n" + "MIICXgIBAAKBgQDYK8imMuRi/03z0K1Zi0WnvfFHvwlYeyK9Na6XJYaUoIDAtB92\n" + "kWdGMdAQhLciHnAjkXLI6W15OoV3gA/ElRZ1xUpxTMhjP6PyY5wqT5r6y8FxbiiF\n" + "KKAnHmUcrgfVW28tQ+0rkLGMryRtrukXOgXBv7gcrmU7G1jC2a7WqmeI8QIDAQAB\n" + "AoGBAIBy09Fd4DOq/Ijp8HeKuCMKTHqTW1xGHshLQ6jwVV2vWZIn9aIgmDsvkjCe\n" + "i6ssZvnbjVcwzSoByhjN8ZCf/i15HECWDFFh6gt0P5z0MnChwzZmvatV/FXCT0j+\n" + "WmGNB/gkehKjGXLLcjTb6dRYVJSCZhVuOLLcbWIV10gggJQBAkEA8S8sGe4ezyyZ\n" + "m4e9r95g6s43kPqtj5rewTsUxt+2n4eVodD+ZUlCULWVNAFLkYRTBCASlSrm9Xhj\n" + "QpmWAHJUkQJBAOVzQdFUaewLtdOJoPCtpYoY1zd22eae8TQEmpGOR11L6kbxLQsk\n" + "aMly/DOnOaa82tqAGTdqDEZgSNmCeKKknmECQAvpnY8GUOVAubGR6c+W90iBuQLj\n" + "LtFp/9ihd2w/PoDwrHZaoUYVcT4VSfJQog/k7kjE4MYXYWL8eEKg3WTWQNECQQDk\n" + "104Wi91Umd1PzF0ijd2jXOERJU1wEKe6XLkYYNHWQAe5l4J4MWj9OdxFXAxIuuR/\n" + "tfDwbqkta4xcux67//khAkEAvvRXLHTaa6VFzTaiiO8SaFsHV3lQyXOtMrBpB5jd\n" + "moZWgjHvB2W9Ckn7sDqsPB+U2tyX0joDdQEyuiMECDY8oQ==\n" + "-----END RSA PRIVATE KEY-----\n"; + ScopedBIO bio(BIO_new_mem_buf(kKeyPEM, strlen(kKeyPEM))); + return ScopedEVP_PKEY( + PEM_read_bio_PrivateKey(bio.get(), nullptr, nullptr, nullptr)); +} + +static bool ConnectClientAndServer(ScopedSSL *out_client, ScopedSSL *out_server, + SSL_CTX *client_ctx, SSL_CTX *server_ctx) { + ScopedSSL client(SSL_new(client_ctx)), server(SSL_new(server_ctx)); + if (!client || !server) { + return false; + } + SSL_set_connect_state(client.get()); + SSL_set_accept_state(server.get()); + + BIO *bio1, *bio2; + if (!BIO_new_bio_pair(&bio1, 0, &bio2, 0)) { + return false; + } + // SSL_set_bio takes ownership. + SSL_set_bio(client.get(), bio1, bio1); + SSL_set_bio(server.get(), bio2, bio2); + + // Drive both their handshakes to completion. + for (;;) { + int client_ret = SSL_do_handshake(client.get()); + int client_err = SSL_get_error(client.get(), client_ret); + if (client_err != SSL_ERROR_NONE && + client_err != SSL_ERROR_WANT_READ && + client_err != SSL_ERROR_WANT_WRITE) { + fprintf(stderr, "Client error: %d\n", client_err); + return false; + } + + int server_ret = SSL_do_handshake(server.get()); + int server_err = SSL_get_error(server.get(), server_ret); + if (server_err != SSL_ERROR_NONE && + server_err != SSL_ERROR_WANT_READ && + server_err != SSL_ERROR_WANT_WRITE) { + fprintf(stderr, "Server error: %d\n", server_err); + return false; + } + + if (client_ret == 1 && server_ret == 1) { + break; + } + } + + *out_client = std::move(client); + *out_server = std::move(server); + return true; +} + +static bool TestSequenceNumber(bool dtls) { + ScopedSSL_CTX client_ctx(SSL_CTX_new(dtls ? DTLS_method() : TLS_method())); + ScopedSSL_CTX server_ctx(SSL_CTX_new(dtls ? DTLS_method() : TLS_method())); + if (!client_ctx || !server_ctx) { + return false; + } + + ScopedX509 cert = GetTestCertificate(); + ScopedEVP_PKEY key = GetTestKey(); + if (!cert || !key || + !SSL_CTX_use_certificate(server_ctx.get(), cert.get()) || + !SSL_CTX_use_PrivateKey(server_ctx.get(), key.get())) { + return false; + } + + ScopedSSL client, server; + if (!ConnectClientAndServer(&client, &server, client_ctx.get(), + server_ctx.get())) { + return false; + } + + uint64_t client_read_seq = SSL_get_read_sequence(client.get()); + uint64_t client_write_seq = SSL_get_write_sequence(client.get()); + uint64_t server_read_seq = SSL_get_read_sequence(server.get()); + uint64_t server_write_seq = SSL_get_write_sequence(server.get()); + + if (dtls) { + // Both client and server must be at epoch 1. + if (EpochFromSequence(client_read_seq) != 1 || + EpochFromSequence(client_write_seq) != 1 || + EpochFromSequence(server_read_seq) != 1 || + EpochFromSequence(server_write_seq) != 1) { + fprintf(stderr, "Bad epochs.\n"); + return false; + } + + // The next record to be written should exceed the largest received. + if (client_write_seq <= server_read_seq || + server_write_seq <= client_read_seq) { + fprintf(stderr, "Inconsistent sequence numbers.\n"); + return false; + } + } else { + // The next record to be written should equal the next to be received. + if (client_write_seq != server_read_seq || + server_write_seq != client_write_seq) { + fprintf(stderr, "Inconsistent sequence numbers.\n"); + return false; + } + } + + // Send a record from client to server. + uint8_t byte = 0; + if (SSL_write(client.get(), &byte, 1) != 1 || + SSL_read(server.get(), &byte, 1) != 1) { + fprintf(stderr, "Could not send byte.\n"); + return false; + } + + // The client write and server read sequence numbers should have incremented. + if (client_write_seq + 1 != SSL_get_write_sequence(client.get()) || + server_read_seq + 1 != SSL_get_read_sequence(server.get())) { + fprintf(stderr, "Sequence numbers did not increment.\n");\ + return false; + } + + return true; +} + +static bool TestOneSidedShutdown() { + ScopedSSL_CTX client_ctx(SSL_CTX_new(TLS_method())); + ScopedSSL_CTX server_ctx(SSL_CTX_new(TLS_method())); + if (!client_ctx || !server_ctx) { + return false; + } + + ScopedX509 cert = GetTestCertificate(); + ScopedEVP_PKEY key = GetTestKey(); + if (!cert || !key || + !SSL_CTX_use_certificate(server_ctx.get(), cert.get()) || + !SSL_CTX_use_PrivateKey(server_ctx.get(), key.get())) { + return false; + } + + ScopedSSL client, server; + if (!ConnectClientAndServer(&client, &server, client_ctx.get(), + server_ctx.get())) { + return false; + } + + // Shut down half the connection. SSL_shutdown will return 0 to signal only + // one side has shut down. + if (SSL_shutdown(client.get()) != 0) { + fprintf(stderr, "Could not shutdown.\n"); + return false; + } + + // Reading from the server should consume the EOF. + uint8_t byte; + if (SSL_read(server.get(), &byte, 1) != 0 || + SSL_get_error(server.get(), 0) != SSL_ERROR_ZERO_RETURN) { + fprintf(stderr, "Connection was not shut down cleanly.\n"); + return false; + } + + // However, the server may continue to write data and then shut down the + // connection. + byte = 42; + if (SSL_write(server.get(), &byte, 1) != 1 || + SSL_read(client.get(), &byte, 1) != 1 || + byte != 42) { + fprintf(stderr, "Could not send byte.\n"); + return false; + } + + // The server may then shutdown the connection. + if (SSL_shutdown(server.get()) != 1 || + SSL_shutdown(client.get()) != 1) { + fprintf(stderr, "Could not complete shutdown.\n"); + return false; + } + + return true; +} + +static bool ExpectFDs(const SSL *ssl, int rfd, int wfd) { + if (SSL_get_rfd(ssl) != rfd || SSL_get_wfd(ssl) != wfd) { + fprintf(stderr, "Got fds %d and %d, wanted %d and %d.\n", SSL_get_rfd(ssl), + SSL_get_wfd(ssl), rfd, wfd); + return false; + } + + // The wrapper BIOs are always equal when fds are equal, even if set + // individually. + if (rfd == wfd && SSL_get_rbio(ssl) != SSL_get_wbio(ssl)) { + fprintf(stderr, "rbio and wbio did not match.\n"); + return false; + } + + return true; +} + +static bool TestSetFD() { + ScopedSSL_CTX ctx(SSL_CTX_new(TLS_method())); + if (!ctx) { + return false; + } + + // Test setting different read and write FDs. + ScopedSSL ssl(SSL_new(ctx.get())); + if (!ssl || + !SSL_set_rfd(ssl.get(), 1) || + !SSL_set_wfd(ssl.get(), 2) || + !ExpectFDs(ssl.get(), 1, 2)) { + return false; + } + + // Test setting the same FD. + ssl.reset(SSL_new(ctx.get())); + if (!ssl || + !SSL_set_fd(ssl.get(), 1) || + !ExpectFDs(ssl.get(), 1, 1)) { + return false; + } + + // Test setting the same FD one side at a time. + ssl.reset(SSL_new(ctx.get())); + if (!ssl || + !SSL_set_rfd(ssl.get(), 1) || + !SSL_set_wfd(ssl.get(), 1) || + !ExpectFDs(ssl.get(), 1, 1)) { + return false; + } + + // Test setting the same FD in the other order. + ssl.reset(SSL_new(ctx.get())); + if (!ssl || + !SSL_set_wfd(ssl.get(), 1) || + !SSL_set_rfd(ssl.get(), 1) || + !ExpectFDs(ssl.get(), 1, 1)) { + return false; + } + + // Test changing the read FD partway through. + ssl.reset(SSL_new(ctx.get())); + if (!ssl || + !SSL_set_fd(ssl.get(), 1) || + !SSL_set_rfd(ssl.get(), 2) || + !ExpectFDs(ssl.get(), 2, 1)) { + return false; + } + + // Test changing the write FD partway through. + ssl.reset(SSL_new(ctx.get())); + if (!ssl || + !SSL_set_fd(ssl.get(), 1) || + !SSL_set_wfd(ssl.get(), 2) || + !ExpectFDs(ssl.get(), 1, 2)) { + return false; + } + + // Test a no-op change to the read FD partway through. + ssl.reset(SSL_new(ctx.get())); + if (!ssl || + !SSL_set_fd(ssl.get(), 1) || + !SSL_set_rfd(ssl.get(), 1) || + !ExpectFDs(ssl.get(), 1, 1)) { + return false; + } + + // Test a no-op change to the write FD partway through. + ssl.reset(SSL_new(ctx.get())); + if (!ssl || + !SSL_set_fd(ssl.get(), 1) || + !SSL_set_wfd(ssl.get(), 1) || + !ExpectFDs(ssl.get(), 1, 1)) { + return false; + } + + // ASan builds will implicitly test that the internal |BIO| reference-counting + // is correct. + + return true; +} + +int main() { + CRYPTO_library_init(); + + if (!TestCipherRules() || + !TestSSL_SESSIONEncoding(kOpenSSLSession) || + !TestSSL_SESSIONEncoding(kCustomSession) || + !TestSSL_SESSIONEncoding(kBoringSSLSession) || + !TestBadSSL_SESSIONEncoding(kBadSessionExtraField) || + !TestBadSSL_SESSIONEncoding(kBadSessionVersion) || + !TestBadSSL_SESSIONEncoding(kBadSessionTrailingData) || + !TestDefaultVersion(0, &TLS_method) || + !TestDefaultVersion(SSL3_VERSION, &SSLv3_method) || + !TestDefaultVersion(TLS1_VERSION, &TLSv1_method) || + !TestDefaultVersion(TLS1_1_VERSION, &TLSv1_1_method) || + !TestDefaultVersion(TLS1_2_VERSION, &TLSv1_2_method) || + !TestDefaultVersion(0, &DTLS_method) || + !TestDefaultVersion(DTLS1_VERSION, &DTLSv1_method) || + !TestDefaultVersion(DTLS1_2_VERSION, &DTLSv1_2_method) || + !TestCipherGetRFCName() || + !TestPaddingExtension() || + !TestClientCAList() || + !TestInternalSessionCache() || + !TestSequenceNumber(false /* TLS */) || + !TestSequenceNumber(true /* DTLS */) || + !TestOneSidedShutdown() || + !TestSetFD()) { + ERR_print_errors_fp(stderr); + return 1; + } + + printf("PASS\n"); + return 0; +} diff --git a/external/boringssl/ssl/t1_enc.c b/external/boringssl/ssl/t1_enc.c new file mode 100644 index 0000000000..b59920772c --- /dev/null +++ b/external/boringssl/ssl/t1_enc.c @@ -0,0 +1,562 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2005 Nokia. All rights reserved. + * + * The portions of the attached software ("Contribution") is developed by + * Nokia Corporation and is licensed pursuant to the OpenSSL open source + * license. + * + * The Contribution, originally written by Mika Kousa and Pasi Eronen of + * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites + * support (see RFC 4279) to OpenSSL. + * + * No patent licenses or other rights except those expressly stated in + * the OpenSSL open source license shall be deemed granted or received + * expressly, by implication, estoppel, or otherwise. + * + * No assurances are provided by Nokia that the Contribution does not + * infringe the patent or other intellectual property rights of any third + * party or that the license provides you with all the necessary rights + * to make use of the Contribution. + * + * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN + * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA + * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY + * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR + * OTHERWISE. */ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "internal.h" + + +/* tls1_P_hash computes the TLS P_ function as described in RFC 5246, + * section 5. It XORs |out_len| bytes to |out|, using |md| as the hash and + * |secret| as the secret. |seed1| through |seed3| are concatenated to form the + * seed parameter. It returns one on success and zero on failure. */ +static int tls1_P_hash(uint8_t *out, size_t out_len, const EVP_MD *md, + const uint8_t *secret, size_t secret_len, + const uint8_t *seed1, size_t seed1_len, + const uint8_t *seed2, size_t seed2_len, + const uint8_t *seed3, size_t seed3_len) { + HMAC_CTX ctx, ctx_tmp, ctx_init; + uint8_t A1[EVP_MAX_MD_SIZE]; + unsigned A1_len; + int ret = 0; + + size_t chunk = EVP_MD_size(md); + + HMAC_CTX_init(&ctx); + HMAC_CTX_init(&ctx_tmp); + HMAC_CTX_init(&ctx_init); + if (!HMAC_Init_ex(&ctx_init, secret, secret_len, md, NULL) || + !HMAC_CTX_copy_ex(&ctx, &ctx_init) || + !HMAC_Update(&ctx, seed1, seed1_len) || + !HMAC_Update(&ctx, seed2, seed2_len) || + !HMAC_Update(&ctx, seed3, seed3_len) || + !HMAC_Final(&ctx, A1, &A1_len)) { + goto err; + } + + for (;;) { + unsigned len; + uint8_t hmac[EVP_MAX_MD_SIZE]; + if (!HMAC_CTX_copy_ex(&ctx, &ctx_init) || + !HMAC_Update(&ctx, A1, A1_len) || + /* Save a copy of |ctx| to compute the next A1 value below. */ + (out_len > chunk && !HMAC_CTX_copy_ex(&ctx_tmp, &ctx)) || + !HMAC_Update(&ctx, seed1, seed1_len) || + !HMAC_Update(&ctx, seed2, seed2_len) || + !HMAC_Update(&ctx, seed3, seed3_len) || + !HMAC_Final(&ctx, hmac, &len)) { + goto err; + } + assert(len == chunk); + + /* XOR the result into |out|. */ + if (len > out_len) { + len = out_len; + } + unsigned i; + for (i = 0; i < len; i++) { + out[i] ^= hmac[i]; + } + out += len; + out_len -= len; + + if (out_len == 0) { + break; + } + + /* Calculate the next A1 value. */ + if (!HMAC_Final(&ctx_tmp, A1, &A1_len)) { + goto err; + } + } + + ret = 1; + +err: + HMAC_CTX_cleanup(&ctx); + HMAC_CTX_cleanup(&ctx_tmp); + HMAC_CTX_cleanup(&ctx_init); + OPENSSL_cleanse(A1, sizeof(A1)); + return ret; +} + +static int tls1_prf(const SSL *ssl, uint8_t *out, size_t out_len, + const uint8_t *secret, size_t secret_len, const char *label, + size_t label_len, const uint8_t *seed1, size_t seed1_len, + const uint8_t *seed2, size_t seed2_len) { + if (out_len == 0) { + return 1; + } + + memset(out, 0, out_len); + + uint32_t algorithm_prf = ssl_get_algorithm_prf(ssl); + if (algorithm_prf == SSL_HANDSHAKE_MAC_DEFAULT) { + /* If using the MD5/SHA1 PRF, |secret| is partitioned between SHA-1 and + * MD5, MD5 first. */ + size_t secret_half = secret_len - (secret_len / 2); + if (!tls1_P_hash(out, out_len, EVP_md5(), secret, secret_half, + (const uint8_t *)label, label_len, seed1, seed1_len, seed2, + seed2_len)) { + return 0; + } + + /* Note that, if |secret_len| is odd, the two halves share a byte. */ + secret = secret + (secret_len - secret_half); + secret_len = secret_half; + } + + if (!tls1_P_hash(out, out_len, ssl_get_handshake_digest(algorithm_prf), + secret, secret_len, (const uint8_t *)label, label_len, + seed1, seed1_len, seed2, seed2_len)) { + return 0; + } + + return 1; +} + +int tls1_change_cipher_state(SSL *ssl, int which) { + /* Ensure the key block is set up. */ + if (!tls1_setup_key_block(ssl)) { + return 0; + } + + /* is_read is true if we have just read a ChangeCipherSpec message - i.e. we + * need to update the read cipherspec. Otherwise we have just written one. */ + const char is_read = (which & SSL3_CC_READ) != 0; + /* use_client_keys is true if we wish to use the keys for the "client write" + * direction. This is the case if we're a client sending a ChangeCipherSpec, + * or a server reading a client's ChangeCipherSpec. */ + const char use_client_keys = which == SSL3_CHANGE_CIPHER_CLIENT_WRITE || + which == SSL3_CHANGE_CIPHER_SERVER_READ; + + size_t mac_secret_len = ssl->s3->tmp.new_mac_secret_len; + size_t key_len = ssl->s3->tmp.new_key_len; + size_t iv_len = ssl->s3->tmp.new_fixed_iv_len; + assert((mac_secret_len + key_len + iv_len) * 2 == + ssl->s3->tmp.key_block_length); + + const uint8_t *key_data = ssl->s3->tmp.key_block; + const uint8_t *client_write_mac_secret = key_data; + key_data += mac_secret_len; + const uint8_t *server_write_mac_secret = key_data; + key_data += mac_secret_len; + const uint8_t *client_write_key = key_data; + key_data += key_len; + const uint8_t *server_write_key = key_data; + key_data += key_len; + const uint8_t *client_write_iv = key_data; + key_data += iv_len; + const uint8_t *server_write_iv = key_data; + key_data += iv_len; + + const uint8_t *mac_secret, *key, *iv; + if (use_client_keys) { + mac_secret = client_write_mac_secret; + key = client_write_key; + iv = client_write_iv; + } else { + mac_secret = server_write_mac_secret; + key = server_write_key; + iv = server_write_iv; + } + + SSL_AEAD_CTX *aead_ctx = + SSL_AEAD_CTX_new(is_read ? evp_aead_open : evp_aead_seal, + ssl3_protocol_version(ssl), ssl->s3->tmp.new_cipher, key, + key_len, mac_secret, mac_secret_len, iv, iv_len); + if (aead_ctx == NULL) { + return 0; + } + + if (is_read) { + ssl_set_read_state(ssl, aead_ctx); + } else { + ssl_set_write_state(ssl, aead_ctx); + } + return 1; +} + +size_t SSL_get_key_block_len(const SSL *ssl) { + return 2 * ((size_t)ssl->s3->tmp.new_mac_secret_len + + (size_t)ssl->s3->tmp.new_key_len + + (size_t)ssl->s3->tmp.new_fixed_iv_len); +} + +int SSL_generate_key_block(const SSL *ssl, uint8_t *out, size_t out_len) { + return ssl->s3->enc_method->prf( + ssl, out, out_len, ssl->session->master_key, + ssl->session->master_key_length, TLS_MD_KEY_EXPANSION_CONST, + TLS_MD_KEY_EXPANSION_CONST_SIZE, ssl->s3->server_random, SSL3_RANDOM_SIZE, + ssl->s3->client_random, SSL3_RANDOM_SIZE); +} + +int tls1_setup_key_block(SSL *ssl) { + if (ssl->s3->tmp.key_block_length != 0) { + return 1; + } + + const EVP_AEAD *aead = NULL; + size_t mac_secret_len, fixed_iv_len; + if (ssl->session->cipher == NULL || + !ssl_cipher_get_evp_aead(&aead, &mac_secret_len, &fixed_iv_len, + ssl->session->cipher, + ssl3_protocol_version(ssl))) { + OPENSSL_PUT_ERROR(SSL, SSL_R_CIPHER_OR_HASH_UNAVAILABLE); + return 0; + } + size_t key_len = EVP_AEAD_key_length(aead); + if (mac_secret_len > 0) { + /* For "stateful" AEADs (i.e. compatibility with pre-AEAD cipher suites) the + * key length reported by |EVP_AEAD_key_length| will include the MAC key + * bytes and initial implicit IV. */ + if (key_len < mac_secret_len + fixed_iv_len) { + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + return 0; + } + key_len -= mac_secret_len + fixed_iv_len; + } + + assert(mac_secret_len < 256); + assert(key_len < 256); + assert(fixed_iv_len < 256); + + ssl->s3->tmp.new_mac_secret_len = (uint8_t)mac_secret_len; + ssl->s3->tmp.new_key_len = (uint8_t)key_len; + ssl->s3->tmp.new_fixed_iv_len = (uint8_t)fixed_iv_len; + + size_t key_block_len = SSL_get_key_block_len(ssl); + + ssl3_cleanup_key_block(ssl); + + uint8_t *keyblock = OPENSSL_malloc(key_block_len); + if (keyblock == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + return 0; + } + + if (!SSL_generate_key_block(ssl, keyblock, key_block_len)) { + OPENSSL_free(keyblock); + return 0; + } + + assert(key_block_len < 256); + ssl->s3->tmp.key_block_length = (uint8_t)key_block_len; + ssl->s3->tmp.key_block = keyblock; + return 1; +} + +static int tls1_cert_verify_mac(SSL *ssl, int md_nid, uint8_t *out) { + const EVP_MD_CTX *ctx_template; + if (md_nid == NID_md5) { + ctx_template = &ssl->s3->handshake_md5; + } else if (md_nid == EVP_MD_CTX_type(&ssl->s3->handshake_hash)) { + ctx_template = &ssl->s3->handshake_hash; + } else { + OPENSSL_PUT_ERROR(SSL, SSL_R_NO_REQUIRED_DIGEST); + return 0; + } + + EVP_MD_CTX ctx; + EVP_MD_CTX_init(&ctx); + if (!EVP_MD_CTX_copy_ex(&ctx, ctx_template)) { + EVP_MD_CTX_cleanup(&ctx); + return 0; + } + unsigned ret; + EVP_DigestFinal_ex(&ctx, out, &ret); + EVP_MD_CTX_cleanup(&ctx); + return ret; +} + +static int append_digest(const EVP_MD_CTX *ctx, uint8_t *out, size_t *out_len, + size_t max_out) { + int ret = 0; + EVP_MD_CTX ctx_copy; + EVP_MD_CTX_init(&ctx_copy); + + if (EVP_MD_CTX_size(ctx) > max_out) { + OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFER_TOO_SMALL); + goto err; + } + unsigned len; + if (!EVP_MD_CTX_copy_ex(&ctx_copy, ctx) || + !EVP_DigestFinal_ex(&ctx_copy, out, &len)) { + goto err; + } + assert(len == EVP_MD_CTX_size(ctx)); + + *out_len = len; + ret = 1; + +err: + EVP_MD_CTX_cleanup(&ctx_copy); + return ret; +} + +/* tls1_handshake_digest calculates the current handshake hash and writes it to + * |out|, which has space for |out_len| bytes. It returns the number of bytes + * written or -1 in the event of an error. This function works on a copy of the + * underlying digests so can be called multiple times and prior to the final + * update etc. */ +int tls1_handshake_digest(SSL *ssl, uint8_t *out, size_t out_len) { + size_t md5_len = 0; + if (EVP_MD_CTX_md(&ssl->s3->handshake_md5) != NULL && + !append_digest(&ssl->s3->handshake_md5, out, &md5_len, out_len)) { + return -1; + } + + size_t len; + if (!append_digest(&ssl->s3->handshake_hash, out + md5_len, &len, + out_len - md5_len)) { + return -1; + } + + return (int)(md5_len + len); +} + +static int tls1_final_finish_mac(SSL *ssl, int from_server, uint8_t *out) { + /* At this point, the handshake should have released the handshake buffer on + * its own. */ + assert(ssl->s3->handshake_buffer == NULL); + + const char *label = TLS_MD_CLIENT_FINISH_CONST; + size_t label_len = TLS_MD_SERVER_FINISH_CONST_SIZE; + if (from_server) { + label = TLS_MD_SERVER_FINISH_CONST; + label_len = TLS_MD_SERVER_FINISH_CONST_SIZE; + } + + uint8_t buf[EVP_MAX_MD_SIZE]; + int digests_len = tls1_handshake_digest(ssl, buf, sizeof(buf)); + if (digests_len < 0) { + return 0; + } + + static const size_t kFinishedLen = 12; + if (!ssl->s3->enc_method->prf(ssl, out, kFinishedLen, + ssl->session->master_key, + ssl->session->master_key_length, label, + label_len, buf, digests_len, NULL, 0)) { + return 0; + } + + return (int)kFinishedLen; +} + +int tls1_generate_master_secret(SSL *ssl, uint8_t *out, + const uint8_t *premaster, + size_t premaster_len) { + if (ssl->s3->tmp.extended_master_secret) { + uint8_t digests[EVP_MAX_MD_SIZE]; + int digests_len = tls1_handshake_digest(ssl, digests, sizeof(digests)); + if (digests_len == -1) { + return 0; + } + + if (!ssl->s3->enc_method->prf(ssl, out, SSL3_MASTER_SECRET_SIZE, premaster, + premaster_len, + TLS_MD_EXTENDED_MASTER_SECRET_CONST, + TLS_MD_EXTENDED_MASTER_SECRET_CONST_SIZE, + digests, digests_len, NULL, 0)) { + return 0; + } + } else { + if (!ssl->s3->enc_method->prf(ssl, out, SSL3_MASTER_SECRET_SIZE, premaster, + premaster_len, TLS_MD_MASTER_SECRET_CONST, + TLS_MD_MASTER_SECRET_CONST_SIZE, + ssl->s3->client_random, SSL3_RANDOM_SIZE, + ssl->s3->server_random, SSL3_RANDOM_SIZE)) { + return 0; + } + } + + return SSL3_MASTER_SECRET_SIZE; +} + +int SSL_export_keying_material(SSL *ssl, uint8_t *out, size_t out_len, + const char *label, size_t label_len, + const uint8_t *context, size_t context_len, + int use_context) { + if (!ssl->s3->have_version || ssl->version == SSL3_VERSION) { + return 0; + } + + size_t seed_len = 2 * SSL3_RANDOM_SIZE; + if (use_context) { + if (context_len >= 1u << 16) { + OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW); + return 0; + } + seed_len += 2 + context_len; + } + uint8_t *seed = OPENSSL_malloc(seed_len); + if (seed == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + return 0; + } + + memcpy(seed, ssl->s3->client_random, SSL3_RANDOM_SIZE); + memcpy(seed + SSL3_RANDOM_SIZE, ssl->s3->server_random, SSL3_RANDOM_SIZE); + if (use_context) { + seed[2 * SSL3_RANDOM_SIZE] = (uint8_t)(context_len >> 8); + seed[2 * SSL3_RANDOM_SIZE + 1] = (uint8_t)context_len; + memcpy(seed + 2 * SSL3_RANDOM_SIZE + 2, context, context_len); + } + + int ret = + ssl->s3->enc_method->prf(ssl, out, out_len, ssl->session->master_key, + ssl->session->master_key_length, label, + label_len, seed, seed_len, NULL, 0); + OPENSSL_free(seed); + return ret; +} + +const SSL3_ENC_METHOD TLSv1_enc_data = { + tls1_prf, + tls1_final_finish_mac, + tls1_cert_verify_mac, +}; diff --git a/external/boringssl/ssl/t1_lib.c b/external/boringssl/ssl/t1_lib.c new file mode 100644 index 0000000000..16cac15efa --- /dev/null +++ b/external/boringssl/ssl/t1_lib.c @@ -0,0 +1,2743 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "internal.h" + + +static int ssl_check_clienthello_tlsext(SSL *ssl); +static int ssl_check_serverhello_tlsext(SSL *ssl); + +static int compare_uint16_t(const void *p1, const void *p2) { + uint16_t u1 = *((const uint16_t *)p1); + uint16_t u2 = *((const uint16_t *)p2); + if (u1 < u2) { + return -1; + } else if (u1 > u2) { + return 1; + } else { + return 0; + } +} + +/* Per http://tools.ietf.org/html/rfc5246#section-7.4.1.4, there may not be + * more than one extension of the same type in a ClientHello or ServerHello. + * This function does an initial scan over the extensions block to filter those + * out. */ +static int tls1_check_duplicate_extensions(const CBS *cbs) { + CBS extensions = *cbs; + size_t num_extensions = 0, i = 0; + uint16_t *extension_types = NULL; + int ret = 0; + + /* First pass: count the extensions. */ + while (CBS_len(&extensions) > 0) { + uint16_t type; + CBS extension; + + if (!CBS_get_u16(&extensions, &type) || + !CBS_get_u16_length_prefixed(&extensions, &extension)) { + goto done; + } + + num_extensions++; + } + + if (num_extensions == 0) { + return 1; + } + + extension_types = OPENSSL_malloc(sizeof(uint16_t) * num_extensions); + if (extension_types == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + goto done; + } + + /* Second pass: gather the extension types. */ + extensions = *cbs; + for (i = 0; i < num_extensions; i++) { + CBS extension; + + if (!CBS_get_u16(&extensions, &extension_types[i]) || + !CBS_get_u16_length_prefixed(&extensions, &extension)) { + /* This should not happen. */ + goto done; + } + } + assert(CBS_len(&extensions) == 0); + + /* Sort the extensions and make sure there are no duplicates. */ + qsort(extension_types, num_extensions, sizeof(uint16_t), compare_uint16_t); + for (i = 1; i < num_extensions; i++) { + if (extension_types[i - 1] == extension_types[i]) { + goto done; + } + } + + ret = 1; + +done: + OPENSSL_free(extension_types); + return ret; +} + +char ssl_early_callback_init(struct ssl_early_callback_ctx *ctx) { + CBS client_hello, session_id, cipher_suites, compression_methods, extensions; + + CBS_init(&client_hello, ctx->client_hello, ctx->client_hello_len); + + if (/* Skip client version. */ + !CBS_skip(&client_hello, 2) || + /* Skip client nonce. */ + !CBS_skip(&client_hello, 32) || + /* Extract session_id. */ + !CBS_get_u8_length_prefixed(&client_hello, &session_id)) { + return 0; + } + + ctx->session_id = CBS_data(&session_id); + ctx->session_id_len = CBS_len(&session_id); + + /* Skip past DTLS cookie */ + if (SSL_IS_DTLS(ctx->ssl)) { + CBS cookie; + + if (!CBS_get_u8_length_prefixed(&client_hello, &cookie)) { + return 0; + } + } + + /* Extract cipher_suites. */ + if (!CBS_get_u16_length_prefixed(&client_hello, &cipher_suites) || + CBS_len(&cipher_suites) < 2 || (CBS_len(&cipher_suites) & 1) != 0) { + return 0; + } + ctx->cipher_suites = CBS_data(&cipher_suites); + ctx->cipher_suites_len = CBS_len(&cipher_suites); + + /* Extract compression_methods. */ + if (!CBS_get_u8_length_prefixed(&client_hello, &compression_methods) || + CBS_len(&compression_methods) < 1) { + return 0; + } + ctx->compression_methods = CBS_data(&compression_methods); + ctx->compression_methods_len = CBS_len(&compression_methods); + + /* If the ClientHello ends here then it's valid, but doesn't have any + * extensions. (E.g. SSLv3.) */ + if (CBS_len(&client_hello) == 0) { + ctx->extensions = NULL; + ctx->extensions_len = 0; + return 1; + } + + /* Extract extensions and check it is valid. */ + if (!CBS_get_u16_length_prefixed(&client_hello, &extensions) || + !tls1_check_duplicate_extensions(&extensions) || + CBS_len(&client_hello) != 0) { + return 0; + } + ctx->extensions = CBS_data(&extensions); + ctx->extensions_len = CBS_len(&extensions); + + return 1; +} + +int SSL_early_callback_ctx_extension_get( + const struct ssl_early_callback_ctx *ctx, uint16_t extension_type, + const uint8_t **out_data, size_t *out_len) { + CBS extensions; + + CBS_init(&extensions, ctx->extensions, ctx->extensions_len); + + while (CBS_len(&extensions) != 0) { + uint16_t type; + CBS extension; + + /* Decode the next extension. */ + if (!CBS_get_u16(&extensions, &type) || + !CBS_get_u16_length_prefixed(&extensions, &extension)) { + return 0; + } + + if (type == extension_type) { + *out_data = CBS_data(&extension); + *out_len = CBS_len(&extension); + return 1; + } + } + + return 0; +} + +static const uint16_t kDefaultGroups[] = { + SSL_GROUP_X25519, + SSL_GROUP_SECP256R1, + SSL_GROUP_SECP384R1, +#if defined(BORINGSSL_ANDROID_SYSTEM) + SSL_GROUP_SECP521R1, +#endif +}; + +/* tls1_get_grouplist sets |*out_group_ids| and |*out_group_ids_len| to the + * list of allowed group IDs. If |get_peer_groups| is non-zero, return the + * peer's group list. Otherwise, return the preferred list. */ +static void tls1_get_grouplist(SSL *ssl, int get_peer_groups, + const uint16_t **out_group_ids, + size_t *out_group_ids_len) { + if (get_peer_groups) { + /* Only clients send a supported group list, so this function is only + * called on the server. */ + assert(ssl->server); + *out_group_ids = ssl->s3->tmp.peer_supported_group_list; + *out_group_ids_len = ssl->s3->tmp.peer_supported_group_list_len; + return; + } + + *out_group_ids = ssl->supported_group_list; + *out_group_ids_len = ssl->supported_group_list_len; + if (!*out_group_ids) { + *out_group_ids = kDefaultGroups; + *out_group_ids_len = sizeof(kDefaultGroups) / sizeof(kDefaultGroups[0]); + } +} + +int tls1_get_shared_group(SSL *ssl, uint16_t *out_group_id) { + const uint16_t *groups, *peer_groups, *pref, *supp; + size_t groups_len, peer_groups_len, pref_len, supp_len, i, j; + + /* Can't do anything on client side */ + if (ssl->server == 0) { + return 0; + } + + tls1_get_grouplist(ssl, 0 /* local groups */, &groups, &groups_len); + tls1_get_grouplist(ssl, 1 /* peer groups */, &peer_groups, &peer_groups_len); + + if (peer_groups_len == 0) { + /* Clients are not required to send a supported_groups extension. In this + * case, the server is free to pick any group it likes. See RFC 4492, + * section 4, paragraph 3. + * + * However, in the interests of compatibility, we will skip ECDH if the + * client didn't send an extension because we can't be sure that they'll + * support our favoured group. */ + return 0; + } + + if (ssl->options & SSL_OP_CIPHER_SERVER_PREFERENCE) { + pref = groups; + pref_len = groups_len; + supp = peer_groups; + supp_len = peer_groups_len; + } else { + pref = peer_groups; + pref_len = peer_groups_len; + supp = groups; + supp_len = groups_len; + } + + for (i = 0; i < pref_len; i++) { + for (j = 0; j < supp_len; j++) { + if (pref[i] == supp[j]) { + *out_group_id = pref[i]; + return 1; + } + } + } + + return 0; +} + +int tls1_set_curves(uint16_t **out_group_ids, size_t *out_group_ids_len, + const int *curves, size_t ncurves) { + uint16_t *group_ids; + size_t i; + + group_ids = OPENSSL_malloc(ncurves * sizeof(uint16_t)); + if (group_ids == NULL) { + return 0; + } + + for (i = 0; i < ncurves; i++) { + if (!ssl_nid_to_group_id(&group_ids[i], curves[i])) { + OPENSSL_free(group_ids); + return 0; + } + } + + OPENSSL_free(*out_group_ids); + *out_group_ids = group_ids; + *out_group_ids_len = ncurves; + + return 1; +} + +/* tls1_curve_params_from_ec_key sets |*out_group_id| and |*out_comp_id| to the + * TLS group ID and point format, respectively, for |ec|. It returns one on + * success and zero on failure. */ +static int tls1_curve_params_from_ec_key(uint16_t *out_group_id, + uint8_t *out_comp_id, EC_KEY *ec) { + int nid; + uint16_t id; + const EC_GROUP *grp; + + if (ec == NULL) { + return 0; + } + + grp = EC_KEY_get0_group(ec); + if (grp == NULL) { + return 0; + } + + /* Determine group ID */ + nid = EC_GROUP_get_curve_name(grp); + if (!ssl_nid_to_group_id(&id, nid)) { + return 0; + } + + /* Set the named group ID. Arbitrary explicit groups are not supported. */ + *out_group_id = id; + + if (out_comp_id) { + if (EC_KEY_get0_public_key(ec) == NULL) { + return 0; + } + if (EC_KEY_get_conv_form(ec) == POINT_CONVERSION_COMPRESSED) { + *out_comp_id = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime; + } else { + *out_comp_id = TLSEXT_ECPOINTFORMAT_uncompressed; + } + } + + return 1; +} + +/* tls1_check_group_id returns one if |group_id| is consistent with both our + * and the peer's group preferences. Note: if called as the client, only our + * preferences are checked; the peer (the server) does not send preferences. */ +int tls1_check_group_id(SSL *ssl, uint16_t group_id) { + const uint16_t *groups; + size_t groups_len, i, get_peer_groups; + + /* Check against our list, then the peer's list. */ + for (get_peer_groups = 0; get_peer_groups <= 1; get_peer_groups++) { + if (get_peer_groups && !ssl->server) { + /* Servers do not present a preference list so, if we are a client, only + * check our list. */ + continue; + } + + tls1_get_grouplist(ssl, get_peer_groups, &groups, &groups_len); + if (get_peer_groups && groups_len == 0) { + /* Clients are not required to send a supported_groups extension. In this + * case, the server is free to pick any group it likes. See RFC 4492, + * section 4, paragraph 3. */ + continue; + } + for (i = 0; i < groups_len; i++) { + if (groups[i] == group_id) { + break; + } + } + + if (i == groups_len) { + return 0; + } + } + + return 1; +} + +int tls1_check_ec_cert(SSL *ssl, X509 *x) { + int ret = 0; + EVP_PKEY *pkey = X509_get_pubkey(x); + uint16_t group_id; + uint8_t comp_id; + + if (!pkey) { + goto done; + } + EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(pkey); + if (ec_key == NULL || + !tls1_curve_params_from_ec_key(&group_id, &comp_id, ec_key) || + !tls1_check_group_id(ssl, group_id) || + comp_id != TLSEXT_ECPOINTFORMAT_uncompressed) { + goto done; + } + + ret = 1; + +done: + EVP_PKEY_free(pkey); + return ret; +} + +/* List of supported signature algorithms and hashes. Should make this + * customisable at some point, for now include everything we support. */ + +#define tlsext_sigalg_rsa(md) md, TLSEXT_signature_rsa, + +#define tlsext_sigalg_ecdsa(md) md, TLSEXT_signature_ecdsa, + +#define tlsext_sigalg(md) tlsext_sigalg_rsa(md) tlsext_sigalg_ecdsa(md) + +static const uint8_t tls12_sigalgs[] = { + tlsext_sigalg(TLSEXT_hash_sha512) + tlsext_sigalg(TLSEXT_hash_sha384) + tlsext_sigalg(TLSEXT_hash_sha256) + tlsext_sigalg(TLSEXT_hash_sha1) +}; + +size_t tls12_get_psigalgs(SSL *ssl, const uint8_t **psigs) { + *psigs = tls12_sigalgs; + return sizeof(tls12_sigalgs); +} + +int tls12_check_peer_sigalg(SSL *ssl, const EVP_MD **out_md, int *out_alert, + uint8_t hash, uint8_t signature, EVP_PKEY *pkey) { + const uint8_t *sent_sigs; + size_t sent_sigslen, i; + int sigalg = tls12_get_sigid(pkey->type); + + /* Should never happen */ + if (sigalg == -1) { + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + *out_alert = SSL_AD_INTERNAL_ERROR; + return 0; + } + + /* Check key type is consistent with signature */ + if (sigalg != signature) { + OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE); + *out_alert = SSL_AD_ILLEGAL_PARAMETER; + return 0; + } + + /* Check signature matches a type we sent */ + sent_sigslen = tls12_get_psigalgs(ssl, &sent_sigs); + for (i = 0; i < sent_sigslen; i += 2, sent_sigs += 2) { + if (hash == sent_sigs[0] && signature == sent_sigs[1]) { + break; + } + } + + if (i == sent_sigslen) { + OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE); + *out_alert = SSL_AD_ILLEGAL_PARAMETER; + return 0; + } + + *out_md = tls12_get_hash(hash); + if (*out_md == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_DIGEST); + *out_alert = SSL_AD_ILLEGAL_PARAMETER; + return 0; + } + + return 1; +} + +/* Get a mask of disabled algorithms: an algorithm is disabled if it isn't + * supported or doesn't appear in supported signature algorithms. Unlike + * ssl_cipher_get_disabled this applies to a specific session and not global + * settings. */ +void ssl_set_client_disabled(SSL *ssl) { + CERT *c = ssl->cert; + const uint8_t *sigalgs; + size_t i, sigalgslen; + int have_rsa = 0, have_ecdsa = 0; + c->mask_a = 0; + c->mask_k = 0; + + /* Now go through all signature algorithms seeing if we support any for RSA, + * DSA, ECDSA. Do this for all versions not just TLS 1.2. */ + sigalgslen = tls12_get_psigalgs(ssl, &sigalgs); + for (i = 0; i < sigalgslen; i += 2, sigalgs += 2) { + switch (sigalgs[1]) { + case TLSEXT_signature_rsa: + have_rsa = 1; + break; + + case TLSEXT_signature_ecdsa: + have_ecdsa = 1; + break; + } + } + + /* Disable auth if we don't include any appropriate signature algorithms. */ + if (!have_rsa) { + c->mask_a |= SSL_aRSA; + } + if (!have_ecdsa) { + c->mask_a |= SSL_aECDSA; + } + + /* with PSK there must be client callback set */ + if (!ssl->psk_client_callback) { + c->mask_a |= SSL_aPSK; + c->mask_k |= SSL_kPSK; + } +} + +/* tls_extension represents a TLS extension that is handled internally. The + * |init| function is called for each handshake, before any other functions of + * the extension. Then the add and parse callbacks are called as needed. + * + * The parse callbacks receive a |CBS| that contains the contents of the + * extension (i.e. not including the type and length bytes). If an extension is + * not received then the parse callbacks will be called with a NULL CBS so that + * they can do any processing needed to handle the absence of an extension. + * + * The add callbacks receive a |CBB| to which the extension can be appended but + * the function is responsible for appending the type and length bytes too. + * + * All callbacks return one for success and zero for error. If a parse function + * returns zero then a fatal alert with value |*out_alert| will be sent. If + * |*out_alert| isn't set, then a |decode_error| alert will be sent. */ +struct tls_extension { + uint16_t value; + void (*init)(SSL *ssl); + + int (*add_clienthello)(SSL *ssl, CBB *out); + int (*parse_serverhello)(SSL *ssl, uint8_t *out_alert, CBS *contents); + + int (*parse_clienthello)(SSL *ssl, uint8_t *out_alert, CBS *contents); + int (*add_serverhello)(SSL *ssl, CBB *out); +}; + + +/* Server name indication (SNI). + * + * https://tools.ietf.org/html/rfc6066#section-3. */ + +static void ext_sni_init(SSL *ssl) { + ssl->s3->tmp.should_ack_sni = 0; +} + +static int ext_sni_add_clienthello(SSL *ssl, CBB *out) { + if (ssl->tlsext_hostname == NULL) { + return 1; + } + + CBB contents, server_name_list, name; + if (!CBB_add_u16(out, TLSEXT_TYPE_server_name) || + !CBB_add_u16_length_prefixed(out, &contents) || + !CBB_add_u16_length_prefixed(&contents, &server_name_list) || + !CBB_add_u8(&server_name_list, TLSEXT_NAMETYPE_host_name) || + !CBB_add_u16_length_prefixed(&server_name_list, &name) || + !CBB_add_bytes(&name, (const uint8_t *)ssl->tlsext_hostname, + strlen(ssl->tlsext_hostname)) || + !CBB_flush(out)) { + return 0; + } + + return 1; +} + +static int ext_sni_parse_serverhello(SSL *ssl, uint8_t *out_alert, + CBS *contents) { + if (contents == NULL) { + return 1; + } + + if (CBS_len(contents) != 0) { + return 0; + } + + assert(ssl->tlsext_hostname != NULL); + + if (!ssl->hit) { + assert(ssl->session->tlsext_hostname == NULL); + ssl->session->tlsext_hostname = BUF_strdup(ssl->tlsext_hostname); + if (!ssl->session->tlsext_hostname) { + *out_alert = SSL_AD_INTERNAL_ERROR; + return 0; + } + } + + return 1; +} + +static int ext_sni_parse_clienthello(SSL *ssl, uint8_t *out_alert, + CBS *contents) { + if (contents == NULL) { + return 1; + } + + CBS server_name_list, host_name; + uint8_t name_type; + if (!CBS_get_u16_length_prefixed(contents, &server_name_list) || + !CBS_get_u8(&server_name_list, &name_type) || + /* Although the server_name extension was intended to be extensible to + * new name types and multiple names, OpenSSL 1.0.x had a bug which meant + * different name types will cause an error. Further, RFC 4366 originally + * defined syntax inextensibly. RFC 6066 corrected this mistake, but + * adding new name types is no longer feasible. + * + * Act as if the extensibility does not exist to simplify parsing. */ + !CBS_get_u16_length_prefixed(&server_name_list, &host_name) || + CBS_len(&server_name_list) != 0 || + CBS_len(contents) != 0) { + return 0; + } + + if (name_type != TLSEXT_NAMETYPE_host_name || + CBS_len(&host_name) == 0 || + CBS_len(&host_name) > TLSEXT_MAXLEN_host_name || + CBS_contains_zero_byte(&host_name)) { + *out_alert = SSL_AD_UNRECOGNIZED_NAME; + return 0; + } + + /* TODO(davidben): SNI should be resolved before resumption. We have the + * early callback as a replacement, but we should fix the current callback + * and avoid the need for |SSL_CTX_set_session_id_context|. */ + if (!ssl->hit) { + assert(ssl->session->tlsext_hostname == NULL); + + /* Copy the hostname as a string. */ + if (!CBS_strdup(&host_name, &ssl->session->tlsext_hostname)) { + *out_alert = SSL_AD_INTERNAL_ERROR; + return 0; + } + + ssl->s3->tmp.should_ack_sni = 1; + } + + return 1; +} + +static int ext_sni_add_serverhello(SSL *ssl, CBB *out) { + if (ssl->hit || + !ssl->s3->tmp.should_ack_sni || + ssl->session->tlsext_hostname == NULL) { + return 1; + } + + if (!CBB_add_u16(out, TLSEXT_TYPE_server_name) || + !CBB_add_u16(out, 0 /* length */)) { + return 0; + } + + return 1; +} + + +/* Renegotiation indication. + * + * https://tools.ietf.org/html/rfc5746 */ + +static int ext_ri_add_clienthello(SSL *ssl, CBB *out) { + CBB contents, prev_finished; + if (!CBB_add_u16(out, TLSEXT_TYPE_renegotiate) || + !CBB_add_u16_length_prefixed(out, &contents) || + !CBB_add_u8_length_prefixed(&contents, &prev_finished) || + !CBB_add_bytes(&prev_finished, ssl->s3->previous_client_finished, + ssl->s3->previous_client_finished_len) || + !CBB_flush(out)) { + return 0; + } + + return 1; +} + +static int ext_ri_parse_serverhello(SSL *ssl, uint8_t *out_alert, + CBS *contents) { + /* Servers may not switch between omitting the extension and supporting it. + * See RFC 5746, sections 3.5 and 4.2. */ + if (ssl->s3->initial_handshake_complete && + (contents != NULL) != ssl->s3->send_connection_binding) { + *out_alert = SSL_AD_HANDSHAKE_FAILURE; + OPENSSL_PUT_ERROR(SSL, SSL_R_RENEGOTIATION_MISMATCH); + return 0; + } + + if (contents == NULL) { + /* Strictly speaking, if we want to avoid an attack we should *always* see + * RI even on initial ServerHello because the client doesn't see any + * renegotiation during an attack. However this would mean we could not + * connect to any server which doesn't support RI. + * + * OpenSSL has |SSL_OP_LEGACY_SERVER_CONNECT| to control this, but in + * practical terms every client sets it so it's just assumed here. */ + return 1; + } + + const size_t expected_len = ssl->s3->previous_client_finished_len + + ssl->s3->previous_server_finished_len; + + /* Check for logic errors */ + assert(!expected_len || ssl->s3->previous_client_finished_len); + assert(!expected_len || ssl->s3->previous_server_finished_len); + + /* Parse out the extension contents. */ + CBS renegotiated_connection; + if (!CBS_get_u8_length_prefixed(contents, &renegotiated_connection) || + CBS_len(contents) != 0) { + OPENSSL_PUT_ERROR(SSL, SSL_R_RENEGOTIATION_ENCODING_ERR); + *out_alert = SSL_AD_ILLEGAL_PARAMETER; + return 0; + } + + /* Check that the extension matches. */ + if (CBS_len(&renegotiated_connection) != expected_len) { + OPENSSL_PUT_ERROR(SSL, SSL_R_RENEGOTIATION_MISMATCH); + *out_alert = SSL_AD_HANDSHAKE_FAILURE; + return 0; + } + + const uint8_t *d = CBS_data(&renegotiated_connection); + if (CRYPTO_memcmp(d, ssl->s3->previous_client_finished, + ssl->s3->previous_client_finished_len)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_RENEGOTIATION_MISMATCH); + *out_alert = SSL_AD_HANDSHAKE_FAILURE; + return 0; + } + d += ssl->s3->previous_client_finished_len; + + if (CRYPTO_memcmp(d, ssl->s3->previous_server_finished, + ssl->s3->previous_server_finished_len)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_RENEGOTIATION_MISMATCH); + *out_alert = SSL_AD_ILLEGAL_PARAMETER; + return 0; + } + ssl->s3->send_connection_binding = 1; + + return 1; +} + +static int ext_ri_parse_clienthello(SSL *ssl, uint8_t *out_alert, + CBS *contents) { + /* Renegotiation isn't supported as a server so this function should never be + * called after the initial handshake. */ + assert(!ssl->s3->initial_handshake_complete); + + CBS fake_contents; + static const uint8_t kFakeExtension[] = {0}; + + if (contents == NULL) { + if (ssl->s3->send_connection_binding) { + /* The renegotiation SCSV was received so pretend that we received a + * renegotiation extension. */ + CBS_init(&fake_contents, kFakeExtension, sizeof(kFakeExtension)); + contents = &fake_contents; + /* We require that the renegotiation extension is at index zero of + * kExtensions. */ + ssl->s3->tmp.extensions.received |= (1u << 0); + } else { + return 1; + } + } + + CBS renegotiated_connection; + + if (!CBS_get_u8_length_prefixed(contents, &renegotiated_connection) || + CBS_len(contents) != 0) { + OPENSSL_PUT_ERROR(SSL, SSL_R_RENEGOTIATION_ENCODING_ERR); + return 0; + } + + /* Check that the extension matches */ + if (!CBS_mem_equal(&renegotiated_connection, + ssl->s3->previous_client_finished, + ssl->s3->previous_client_finished_len)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_RENEGOTIATION_MISMATCH); + *out_alert = SSL_AD_HANDSHAKE_FAILURE; + return 0; + } + + ssl->s3->send_connection_binding = 1; + + return 1; +} + +static int ext_ri_add_serverhello(SSL *ssl, CBB *out) { + CBB contents, prev_finished; + if (!CBB_add_u16(out, TLSEXT_TYPE_renegotiate) || + !CBB_add_u16_length_prefixed(out, &contents) || + !CBB_add_u8_length_prefixed(&contents, &prev_finished) || + !CBB_add_bytes(&prev_finished, ssl->s3->previous_client_finished, + ssl->s3->previous_client_finished_len) || + !CBB_add_bytes(&prev_finished, ssl->s3->previous_server_finished, + ssl->s3->previous_server_finished_len) || + !CBB_flush(out)) { + return 0; + } + + return 1; +} + + +/* Extended Master Secret. + * + * https://tools.ietf.org/html/rfc7627 */ + +static void ext_ems_init(SSL *ssl) { + ssl->s3->tmp.extended_master_secret = 0; +} + +static int ext_ems_add_clienthello(SSL *ssl, CBB *out) { + if (ssl->version == SSL3_VERSION) { + return 1; + } + + if (!CBB_add_u16(out, TLSEXT_TYPE_extended_master_secret) || + !CBB_add_u16(out, 0 /* length */)) { + return 0; + } + + return 1; +} + +static int ext_ems_parse_serverhello(SSL *ssl, uint8_t *out_alert, + CBS *contents) { + if (contents == NULL) { + return 1; + } + + if (ssl->version == SSL3_VERSION || CBS_len(contents) != 0) { + return 0; + } + + ssl->s3->tmp.extended_master_secret = 1; + return 1; +} + +static int ext_ems_parse_clienthello(SSL *ssl, uint8_t *out_alert, + CBS *contents) { + if (ssl->version == SSL3_VERSION || contents == NULL) { + return 1; + } + + if (CBS_len(contents) != 0) { + return 0; + } + + ssl->s3->tmp.extended_master_secret = 1; + return 1; +} + +static int ext_ems_add_serverhello(SSL *ssl, CBB *out) { + if (!ssl->s3->tmp.extended_master_secret) { + return 1; + } + + if (!CBB_add_u16(out, TLSEXT_TYPE_extended_master_secret) || + !CBB_add_u16(out, 0 /* length */)) { + return 0; + } + + return 1; +} + + +/* Session tickets. + * + * https://tools.ietf.org/html/rfc5077 */ + +static int ext_ticket_add_clienthello(SSL *ssl, CBB *out) { + if (SSL_get_options(ssl) & SSL_OP_NO_TICKET) { + return 1; + } + + const uint8_t *ticket_data = NULL; + int ticket_len = 0; + + /* Renegotiation does not participate in session resumption. However, still + * advertise the extension to avoid potentially breaking servers which carry + * over the state from the previous handshake, such as OpenSSL servers + * without upstream's 3c3f0259238594d77264a78944d409f2127642c4. */ + if (!ssl->s3->initial_handshake_complete && + ssl->session != NULL && + ssl->session->tlsext_tick != NULL) { + ticket_data = ssl->session->tlsext_tick; + ticket_len = ssl->session->tlsext_ticklen; + } + + CBB ticket; + if (!CBB_add_u16(out, TLSEXT_TYPE_session_ticket) || + !CBB_add_u16_length_prefixed(out, &ticket) || + !CBB_add_bytes(&ticket, ticket_data, ticket_len) || + !CBB_flush(out)) { + return 0; + } + + return 1; +} + +static int ext_ticket_parse_serverhello(SSL *ssl, uint8_t *out_alert, + CBS *contents) { + ssl->tlsext_ticket_expected = 0; + + if (contents == NULL) { + return 1; + } + + /* If |SSL_OP_NO_TICKET| is set then no extension will have been sent and + * this function should never be called, even if the server tries to send the + * extension. */ + assert((SSL_get_options(ssl) & SSL_OP_NO_TICKET) == 0); + + if (CBS_len(contents) != 0) { + return 0; + } + + ssl->tlsext_ticket_expected = 1; + return 1; +} + +static int ext_ticket_parse_clienthello(SSL *ssl, uint8_t *out_alert, + CBS *contents) { + /* This function isn't used because the ticket extension from the client is + * handled in ssl_session.c. */ + return 1; +} + +static int ext_ticket_add_serverhello(SSL *ssl, CBB *out) { + if (!ssl->tlsext_ticket_expected) { + return 1; + } + + /* If |SSL_OP_NO_TICKET| is set, |tlsext_ticket_expected| should never be + * true. */ + assert((SSL_get_options(ssl) & SSL_OP_NO_TICKET) == 0); + + if (!CBB_add_u16(out, TLSEXT_TYPE_session_ticket) || + !CBB_add_u16(out, 0 /* length */)) { + return 0; + } + + return 1; +} + + +/* Signature Algorithms. + * + * https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 */ + +static int ext_sigalgs_add_clienthello(SSL *ssl, CBB *out) { + if (ssl3_version_from_wire(ssl, ssl->client_version) < TLS1_2_VERSION) { + return 1; + } + + const uint8_t *sigalgs_data; + const size_t sigalgs_len = tls12_get_psigalgs(ssl, &sigalgs_data); + + CBB contents, sigalgs; + if (!CBB_add_u16(out, TLSEXT_TYPE_signature_algorithms) || + !CBB_add_u16_length_prefixed(out, &contents) || + !CBB_add_u16_length_prefixed(&contents, &sigalgs) || + !CBB_add_bytes(&sigalgs, sigalgs_data, sigalgs_len) || + !CBB_flush(out)) { + return 0; + } + + return 1; +} + +static int ext_sigalgs_parse_serverhello(SSL *ssl, uint8_t *out_alert, + CBS *contents) { + if (contents != NULL) { + /* Servers MUST NOT send this extension. */ + *out_alert = SSL_AD_UNSUPPORTED_EXTENSION; + OPENSSL_PUT_ERROR(SSL, SSL_R_SIGNATURE_ALGORITHMS_EXTENSION_SENT_BY_SERVER); + return 0; + } + + return 1; +} + +static int ext_sigalgs_parse_clienthello(SSL *ssl, uint8_t *out_alert, + CBS *contents) { + OPENSSL_free(ssl->cert->peer_sigalgs); + ssl->cert->peer_sigalgs = NULL; + ssl->cert->peer_sigalgslen = 0; + + if (contents == NULL) { + return 1; + } + + CBS supported_signature_algorithms; + if (!CBS_get_u16_length_prefixed(contents, &supported_signature_algorithms) || + CBS_len(contents) != 0 || + CBS_len(&supported_signature_algorithms) == 0 || + !tls1_parse_peer_sigalgs(ssl, &supported_signature_algorithms)) { + return 0; + } + + return 1; +} + +static int ext_sigalgs_add_serverhello(SSL *ssl, CBB *out) { + /* Servers MUST NOT send this extension. */ + return 1; +} + + +/* OCSP Stapling. + * + * https://tools.ietf.org/html/rfc6066#section-8 */ + +static void ext_ocsp_init(SSL *ssl) { + ssl->s3->tmp.certificate_status_expected = 0; + ssl->tlsext_status_type = -1; +} + +static int ext_ocsp_add_clienthello(SSL *ssl, CBB *out) { + if (!ssl->ocsp_stapling_enabled) { + return 1; + } + + CBB contents; + if (!CBB_add_u16(out, TLSEXT_TYPE_status_request) || + !CBB_add_u16_length_prefixed(out, &contents) || + !CBB_add_u8(&contents, TLSEXT_STATUSTYPE_ocsp) || + !CBB_add_u16(&contents, 0 /* empty responder ID list */) || + !CBB_add_u16(&contents, 0 /* empty request extensions */) || + !CBB_flush(out)) { + return 0; + } + + ssl->tlsext_status_type = TLSEXT_STATUSTYPE_ocsp; + return 1; +} + +static int ext_ocsp_parse_serverhello(SSL *ssl, uint8_t *out_alert, + CBS *contents) { + if (contents == NULL) { + return 1; + } + + if (CBS_len(contents) != 0) { + return 0; + } + + ssl->s3->tmp.certificate_status_expected = 1; + return 1; +} + +static int ext_ocsp_parse_clienthello(SSL *ssl, uint8_t *out_alert, + CBS *contents) { + if (contents == NULL) { + return 1; + } + + uint8_t status_type; + if (!CBS_get_u8(contents, &status_type)) { + return 0; + } + + /* We cannot decide whether OCSP stapling will occur yet because the correct + * SSL_CTX might not have been selected. */ + ssl->s3->tmp.ocsp_stapling_requested = status_type == TLSEXT_STATUSTYPE_ocsp; + + return 1; +} + +static int ext_ocsp_add_serverhello(SSL *ssl, CBB *out) { + /* The extension shouldn't be sent when resuming sessions. */ + if (ssl->hit || + !ssl->s3->tmp.ocsp_stapling_requested || + ssl->ctx->ocsp_response_length == 0) { + return 1; + } + + ssl->s3->tmp.certificate_status_expected = 1; + + return CBB_add_u16(out, TLSEXT_TYPE_status_request) && + CBB_add_u16(out, 0 /* length */); +} + + +/* Next protocol negotiation. + * + * https://htmlpreview.github.io/?https://github.com/agl/technotes/blob/master/nextprotoneg.html */ + +static void ext_npn_init(SSL *ssl) { + ssl->s3->next_proto_neg_seen = 0; +} + +static int ext_npn_add_clienthello(SSL *ssl, CBB *out) { + if (ssl->s3->initial_handshake_complete || + ssl->ctx->next_proto_select_cb == NULL || + (ssl->options & SSL_OP_DISABLE_NPN) || + SSL_IS_DTLS(ssl)) { + return 1; + } + + if (!CBB_add_u16(out, TLSEXT_TYPE_next_proto_neg) || + !CBB_add_u16(out, 0 /* length */)) { + return 0; + } + + return 1; +} + +static int ext_npn_parse_serverhello(SSL *ssl, uint8_t *out_alert, + CBS *contents) { + if (contents == NULL) { + return 1; + } + + /* If any of these are false then we should never have sent the NPN + * extension in the ClientHello and thus this function should never have been + * called. */ + assert(!ssl->s3->initial_handshake_complete); + assert(!SSL_IS_DTLS(ssl)); + assert(ssl->ctx->next_proto_select_cb != NULL); + assert(!(ssl->options & SSL_OP_DISABLE_NPN)); + + if (ssl->s3->alpn_selected != NULL) { + /* NPN and ALPN may not be negotiated in the same connection. */ + *out_alert = SSL_AD_ILLEGAL_PARAMETER; + OPENSSL_PUT_ERROR(SSL, SSL_R_NEGOTIATED_BOTH_NPN_AND_ALPN); + return 0; + } + + const uint8_t *const orig_contents = CBS_data(contents); + const size_t orig_len = CBS_len(contents); + + while (CBS_len(contents) != 0) { + CBS proto; + if (!CBS_get_u8_length_prefixed(contents, &proto) || + CBS_len(&proto) == 0) { + return 0; + } + } + + uint8_t *selected; + uint8_t selected_len; + if (ssl->ctx->next_proto_select_cb( + ssl, &selected, &selected_len, orig_contents, orig_len, + ssl->ctx->next_proto_select_cb_arg) != SSL_TLSEXT_ERR_OK) { + *out_alert = SSL_AD_INTERNAL_ERROR; + return 0; + } + + OPENSSL_free(ssl->s3->next_proto_negotiated); + ssl->s3->next_proto_negotiated = BUF_memdup(selected, selected_len); + if (ssl->s3->next_proto_negotiated == NULL) { + *out_alert = SSL_AD_INTERNAL_ERROR; + return 0; + } + + ssl->s3->next_proto_negotiated_len = selected_len; + ssl->s3->next_proto_neg_seen = 1; + + return 1; +} + +static int ext_npn_parse_clienthello(SSL *ssl, uint8_t *out_alert, + CBS *contents) { + if (contents != NULL && CBS_len(contents) != 0) { + return 0; + } + + if (contents == NULL || + ssl->s3->initial_handshake_complete || + /* If the ALPN extension is seen before NPN, ignore it. (If ALPN is seen + * afterwards, parsing the ALPN extension will clear + * |next_proto_neg_seen|. */ + ssl->s3->alpn_selected != NULL || + ssl->ctx->next_protos_advertised_cb == NULL || + SSL_IS_DTLS(ssl)) { + return 1; + } + + ssl->s3->next_proto_neg_seen = 1; + return 1; +} + +static int ext_npn_add_serverhello(SSL *ssl, CBB *out) { + /* |next_proto_neg_seen| might have been cleared when an ALPN extension was + * parsed. */ + if (!ssl->s3->next_proto_neg_seen) { + return 1; + } + + const uint8_t *npa; + unsigned npa_len; + + if (ssl->ctx->next_protos_advertised_cb( + ssl, &npa, &npa_len, ssl->ctx->next_protos_advertised_cb_arg) != + SSL_TLSEXT_ERR_OK) { + ssl->s3->next_proto_neg_seen = 0; + return 1; + } + + CBB contents; + if (!CBB_add_u16(out, TLSEXT_TYPE_next_proto_neg) || + !CBB_add_u16_length_prefixed(out, &contents) || + !CBB_add_bytes(&contents, npa, npa_len) || + !CBB_flush(out)) { + return 0; + } + + return 1; +} + + +/* Signed certificate timestamps. + * + * https://tools.ietf.org/html/rfc6962#section-3.3.1 */ + +static int ext_sct_add_clienthello(SSL *ssl, CBB *out) { + if (!ssl->signed_cert_timestamps_enabled) { + return 1; + } + + if (!CBB_add_u16(out, TLSEXT_TYPE_certificate_timestamp) || + !CBB_add_u16(out, 0 /* length */)) { + return 0; + } + + return 1; +} + +static int ext_sct_parse_serverhello(SSL *ssl, uint8_t *out_alert, + CBS *contents) { + if (contents == NULL) { + return 1; + } + + /* If this is false then we should never have sent the SCT extension in the + * ClientHello and thus this function should never have been called. */ + assert(ssl->signed_cert_timestamps_enabled); + + if (CBS_len(contents) == 0) { + *out_alert = SSL_AD_DECODE_ERROR; + return 0; + } + + /* Session resumption uses the original session information. */ + if (!ssl->hit && + !CBS_stow(contents, &ssl->session->tlsext_signed_cert_timestamp_list, + &ssl->session->tlsext_signed_cert_timestamp_list_length)) { + *out_alert = SSL_AD_INTERNAL_ERROR; + return 0; + } + + return 1; +} + +static int ext_sct_parse_clienthello(SSL *ssl, uint8_t *out_alert, + CBS *contents) { + return contents == NULL || CBS_len(contents) == 0; +} + +static int ext_sct_add_serverhello(SSL *ssl, CBB *out) { + /* The extension shouldn't be sent when resuming sessions. */ + if (ssl->hit || + ssl->ctx->signed_cert_timestamp_list_length == 0) { + return 1; + } + + CBB contents; + return CBB_add_u16(out, TLSEXT_TYPE_certificate_timestamp) && + CBB_add_u16_length_prefixed(out, &contents) && + CBB_add_bytes(&contents, ssl->ctx->signed_cert_timestamp_list, + ssl->ctx->signed_cert_timestamp_list_length) && + CBB_flush(out); +} + + +/* Application-level Protocol Negotiation. + * + * https://tools.ietf.org/html/rfc7301 */ + +static void ext_alpn_init(SSL *ssl) { + OPENSSL_free(ssl->s3->alpn_selected); + ssl->s3->alpn_selected = NULL; +} + +static int ext_alpn_add_clienthello(SSL *ssl, CBB *out) { + if (ssl->alpn_client_proto_list == NULL || + ssl->s3->initial_handshake_complete) { + return 1; + } + + CBB contents, proto_list; + if (!CBB_add_u16(out, TLSEXT_TYPE_application_layer_protocol_negotiation) || + !CBB_add_u16_length_prefixed(out, &contents) || + !CBB_add_u16_length_prefixed(&contents, &proto_list) || + !CBB_add_bytes(&proto_list, ssl->alpn_client_proto_list, + ssl->alpn_client_proto_list_len) || + !CBB_flush(out)) { + return 0; + } + + return 1; +} + +static int ext_alpn_parse_serverhello(SSL *ssl, uint8_t *out_alert, + CBS *contents) { + if (contents == NULL) { + return 1; + } + + assert(!ssl->s3->initial_handshake_complete); + assert(ssl->alpn_client_proto_list != NULL); + + if (ssl->s3->next_proto_neg_seen) { + /* NPN and ALPN may not be negotiated in the same connection. */ + *out_alert = SSL_AD_ILLEGAL_PARAMETER; + OPENSSL_PUT_ERROR(SSL, SSL_R_NEGOTIATED_BOTH_NPN_AND_ALPN); + return 0; + } + + /* The extension data consists of a ProtocolNameList which must have + * exactly one ProtocolName. Each of these is length-prefixed. */ + CBS protocol_name_list, protocol_name; + if (!CBS_get_u16_length_prefixed(contents, &protocol_name_list) || + CBS_len(contents) != 0 || + !CBS_get_u8_length_prefixed(&protocol_name_list, &protocol_name) || + /* Empty protocol names are forbidden. */ + CBS_len(&protocol_name) == 0 || + CBS_len(&protocol_name_list) != 0) { + return 0; + } + + if (!CBS_stow(&protocol_name, &ssl->s3->alpn_selected, + &ssl->s3->alpn_selected_len)) { + *out_alert = SSL_AD_INTERNAL_ERROR; + return 0; + } + + return 1; +} + +static int ext_alpn_parse_clienthello(SSL *ssl, uint8_t *out_alert, + CBS *contents) { + if (contents == NULL) { + return 1; + } + + if (ssl->ctx->alpn_select_cb == NULL || + ssl->s3->initial_handshake_complete) { + return 1; + } + + /* ALPN takes precedence over NPN. */ + ssl->s3->next_proto_neg_seen = 0; + + CBS protocol_name_list; + if (!CBS_get_u16_length_prefixed(contents, &protocol_name_list) || + CBS_len(contents) != 0 || + CBS_len(&protocol_name_list) < 2) { + return 0; + } + + /* Validate the protocol list. */ + CBS protocol_name_list_copy = protocol_name_list; + while (CBS_len(&protocol_name_list_copy) > 0) { + CBS protocol_name; + + if (!CBS_get_u8_length_prefixed(&protocol_name_list_copy, &protocol_name) || + /* Empty protocol names are forbidden. */ + CBS_len(&protocol_name) == 0) { + return 0; + } + } + + const uint8_t *selected; + uint8_t selected_len; + if (ssl->ctx->alpn_select_cb( + ssl, &selected, &selected_len, CBS_data(&protocol_name_list), + CBS_len(&protocol_name_list), + ssl->ctx->alpn_select_cb_arg) == SSL_TLSEXT_ERR_OK) { + OPENSSL_free(ssl->s3->alpn_selected); + ssl->s3->alpn_selected = BUF_memdup(selected, selected_len); + if (ssl->s3->alpn_selected == NULL) { + *out_alert = SSL_AD_INTERNAL_ERROR; + return 0; + } + ssl->s3->alpn_selected_len = selected_len; + } + + return 1; +} + +static int ext_alpn_add_serverhello(SSL *ssl, CBB *out) { + if (ssl->s3->alpn_selected == NULL) { + return 1; + } + + CBB contents, proto_list, proto; + if (!CBB_add_u16(out, TLSEXT_TYPE_application_layer_protocol_negotiation) || + !CBB_add_u16_length_prefixed(out, &contents) || + !CBB_add_u16_length_prefixed(&contents, &proto_list) || + !CBB_add_u8_length_prefixed(&proto_list, &proto) || + !CBB_add_bytes(&proto, ssl->s3->alpn_selected, + ssl->s3->alpn_selected_len) || + !CBB_flush(out)) { + return 0; + } + + return 1; +} + + +/* Channel ID. + * + * https://tools.ietf.org/html/draft-balfanz-tls-channelid-01 */ + +static void ext_channel_id_init(SSL *ssl) { + ssl->s3->tlsext_channel_id_valid = 0; +} + +static int ext_channel_id_add_clienthello(SSL *ssl, CBB *out) { + if (!ssl->tlsext_channel_id_enabled || + SSL_IS_DTLS(ssl)) { + return 1; + } + + if (!CBB_add_u16(out, TLSEXT_TYPE_channel_id) || + !CBB_add_u16(out, 0 /* length */)) { + return 0; + } + + return 1; +} + +static int ext_channel_id_parse_serverhello(SSL *ssl, uint8_t *out_alert, + CBS *contents) { + if (contents == NULL) { + return 1; + } + + assert(!SSL_IS_DTLS(ssl)); + assert(ssl->tlsext_channel_id_enabled); + + if (CBS_len(contents) != 0) { + return 0; + } + + ssl->s3->tlsext_channel_id_valid = 1; + return 1; +} + +static int ext_channel_id_parse_clienthello(SSL *ssl, uint8_t *out_alert, + CBS *contents) { + if (contents == NULL || + !ssl->tlsext_channel_id_enabled || + SSL_IS_DTLS(ssl)) { + return 1; + } + + if (CBS_len(contents) != 0) { + return 0; + } + + ssl->s3->tlsext_channel_id_valid = 1; + return 1; +} + +static int ext_channel_id_add_serverhello(SSL *ssl, CBB *out) { + if (!ssl->s3->tlsext_channel_id_valid) { + return 1; + } + + if (!CBB_add_u16(out, TLSEXT_TYPE_channel_id) || + !CBB_add_u16(out, 0 /* length */)) { + return 0; + } + + return 1; +} + + +/* Secure Real-time Transport Protocol (SRTP) extension. + * + * https://tools.ietf.org/html/rfc5764 */ + + +static void ext_srtp_init(SSL *ssl) { + ssl->srtp_profile = NULL; +} + +static int ext_srtp_add_clienthello(SSL *ssl, CBB *out) { + STACK_OF(SRTP_PROTECTION_PROFILE) *profiles = SSL_get_srtp_profiles(ssl); + if (profiles == NULL) { + return 1; + } + const size_t num_profiles = sk_SRTP_PROTECTION_PROFILE_num(profiles); + if (num_profiles == 0) { + return 1; + } + + CBB contents, profile_ids; + if (!CBB_add_u16(out, TLSEXT_TYPE_srtp) || + !CBB_add_u16_length_prefixed(out, &contents) || + !CBB_add_u16_length_prefixed(&contents, &profile_ids)) { + return 0; + } + + size_t i; + for (i = 0; i < num_profiles; i++) { + if (!CBB_add_u16(&profile_ids, + sk_SRTP_PROTECTION_PROFILE_value(profiles, i)->id)) { + return 0; + } + } + + if (!CBB_add_u8(&contents, 0 /* empty use_mki value */) || + !CBB_flush(out)) { + return 0; + } + + return 1; +} + +static int ext_srtp_parse_serverhello(SSL *ssl, uint8_t *out_alert, + CBS *contents) { + if (contents == NULL) { + return 1; + } + + /* The extension consists of a u16-prefixed profile ID list containing a + * single uint16_t profile ID, then followed by a u8-prefixed srtp_mki field. + * + * See https://tools.ietf.org/html/rfc5764#section-4.1.1 */ + CBS profile_ids, srtp_mki; + uint16_t profile_id; + if (!CBS_get_u16_length_prefixed(contents, &profile_ids) || + !CBS_get_u16(&profile_ids, &profile_id) || + CBS_len(&profile_ids) != 0 || + !CBS_get_u8_length_prefixed(contents, &srtp_mki) || + CBS_len(contents) != 0) { + OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST); + return 0; + } + + if (CBS_len(&srtp_mki) != 0) { + /* Must be no MKI, since we never offer one. */ + OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SRTP_MKI_VALUE); + *out_alert = SSL_AD_ILLEGAL_PARAMETER; + return 0; + } + + STACK_OF(SRTP_PROTECTION_PROFILE) *profiles = SSL_get_srtp_profiles(ssl); + + /* Check to see if the server gave us something we support (and presumably + * offered). */ + size_t i; + for (i = 0; i < sk_SRTP_PROTECTION_PROFILE_num(profiles); i++) { + const SRTP_PROTECTION_PROFILE *profile = + sk_SRTP_PROTECTION_PROFILE_value(profiles, i); + + if (profile->id == profile_id) { + ssl->srtp_profile = profile; + return 1; + } + } + + OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST); + *out_alert = SSL_AD_ILLEGAL_PARAMETER; + return 0; +} + +static int ext_srtp_parse_clienthello(SSL *ssl, uint8_t *out_alert, + CBS *contents) { + if (contents == NULL) { + return 1; + } + + CBS profile_ids, srtp_mki; + if (!CBS_get_u16_length_prefixed(contents, &profile_ids) || + CBS_len(&profile_ids) < 2 || + !CBS_get_u8_length_prefixed(contents, &srtp_mki) || + CBS_len(contents) != 0) { + OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST); + return 0; + } + /* Discard the MKI value for now. */ + + const STACK_OF(SRTP_PROTECTION_PROFILE) *server_profiles = + SSL_get_srtp_profiles(ssl); + + /* Pick the server's most preferred profile. */ + size_t i; + for (i = 0; i < sk_SRTP_PROTECTION_PROFILE_num(server_profiles); i++) { + const SRTP_PROTECTION_PROFILE *server_profile = + sk_SRTP_PROTECTION_PROFILE_value(server_profiles, i); + + CBS profile_ids_tmp; + CBS_init(&profile_ids_tmp, CBS_data(&profile_ids), CBS_len(&profile_ids)); + + while (CBS_len(&profile_ids_tmp) > 0) { + uint16_t profile_id; + if (!CBS_get_u16(&profile_ids_tmp, &profile_id)) { + return 0; + } + + if (server_profile->id == profile_id) { + ssl->srtp_profile = server_profile; + return 1; + } + } + } + + return 1; +} + +static int ext_srtp_add_serverhello(SSL *ssl, CBB *out) { + if (ssl->srtp_profile == NULL) { + return 1; + } + + CBB contents, profile_ids; + if (!CBB_add_u16(out, TLSEXT_TYPE_srtp) || + !CBB_add_u16_length_prefixed(out, &contents) || + !CBB_add_u16_length_prefixed(&contents, &profile_ids) || + !CBB_add_u16(&profile_ids, ssl->srtp_profile->id) || + !CBB_add_u8(&contents, 0 /* empty MKI */) || + !CBB_flush(out)) { + return 0; + } + + return 1; +} + + +/* EC point formats. + * + * https://tools.ietf.org/html/rfc4492#section-5.1.2 */ + +static int ssl_any_ec_cipher_suites_enabled(const SSL *ssl) { + if (ssl->version < TLS1_VERSION && !SSL_IS_DTLS(ssl)) { + return 0; + } + + const STACK_OF(SSL_CIPHER) *cipher_stack = SSL_get_ciphers(ssl); + + size_t i; + for (i = 0; i < sk_SSL_CIPHER_num(cipher_stack); i++) { + const SSL_CIPHER *cipher = sk_SSL_CIPHER_value(cipher_stack, i); + + const uint32_t alg_k = cipher->algorithm_mkey; + const uint32_t alg_a = cipher->algorithm_auth; + if ((alg_k & SSL_kECDHE) || (alg_a & SSL_aECDSA)) { + return 1; + } + } + + return 0; +} + +static int ext_ec_point_add_extension(SSL *ssl, CBB *out) { + CBB contents, formats; + if (!CBB_add_u16(out, TLSEXT_TYPE_ec_point_formats) || + !CBB_add_u16_length_prefixed(out, &contents) || + !CBB_add_u8_length_prefixed(&contents, &formats) || + !CBB_add_u8(&formats, TLSEXT_ECPOINTFORMAT_uncompressed) || + !CBB_flush(out)) { + return 0; + } + + return 1; +} + +static int ext_ec_point_add_clienthello(SSL *ssl, CBB *out) { + if (!ssl_any_ec_cipher_suites_enabled(ssl)) { + return 1; + } + + return ext_ec_point_add_extension(ssl, out); +} + +static int ext_ec_point_parse_serverhello(SSL *ssl, uint8_t *out_alert, + CBS *contents) { + if (contents == NULL) { + return 1; + } + + CBS ec_point_format_list; + if (!CBS_get_u8_length_prefixed(contents, &ec_point_format_list) || + CBS_len(contents) != 0) { + return 0; + } + + /* Per RFC 4492, section 5.1.2, implementations MUST support the uncompressed + * point format. */ + if (memchr(CBS_data(&ec_point_format_list), TLSEXT_ECPOINTFORMAT_uncompressed, + CBS_len(&ec_point_format_list)) == NULL) { + *out_alert = SSL_AD_ILLEGAL_PARAMETER; + return 0; + } + + return 1; +} + +static int ext_ec_point_parse_clienthello(SSL *ssl, uint8_t *out_alert, + CBS *contents) { + return ext_ec_point_parse_serverhello(ssl, out_alert, contents); +} + +static int ext_ec_point_add_serverhello(SSL *ssl, CBB *out) { + const uint32_t alg_k = ssl->s3->tmp.new_cipher->algorithm_mkey; + const uint32_t alg_a = ssl->s3->tmp.new_cipher->algorithm_auth; + const int using_ecc = (alg_k & SSL_kECDHE) || (alg_a & SSL_aECDSA); + + if (!using_ecc) { + return 1; + } + + return ext_ec_point_add_extension(ssl, out); +} + + +/* Negotiated Groups + * + * https://tools.ietf.org/html/rfc4492#section-5.1.2 + * https://tools.ietf.org/html/draft-ietf-tls-tls13-12#section-6.3.2.2 */ + +static void ext_supported_groups_init(SSL *ssl) { + OPENSSL_free(ssl->s3->tmp.peer_supported_group_list); + ssl->s3->tmp.peer_supported_group_list = NULL; + ssl->s3->tmp.peer_supported_group_list_len = 0; +} + +static int ext_supported_groups_add_clienthello(SSL *ssl, CBB *out) { + if (!ssl_any_ec_cipher_suites_enabled(ssl)) { + return 1; + } + + CBB contents, groups_bytes; + if (!CBB_add_u16(out, TLSEXT_TYPE_supported_groups) || + !CBB_add_u16_length_prefixed(out, &contents) || + !CBB_add_u16_length_prefixed(&contents, &groups_bytes)) { + return 0; + } + + const uint16_t *groups; + size_t groups_len; + tls1_get_grouplist(ssl, 0, &groups, &groups_len); + + size_t i; + for (i = 0; i < groups_len; i++) { + if (!CBB_add_u16(&groups_bytes, groups[i])) { + return 0; + } + } + + return CBB_flush(out); +} + +static int ext_supported_groups_parse_serverhello(SSL *ssl, uint8_t *out_alert, + CBS *contents) { + /* This extension is not expected to be echoed by servers and is ignored. */ + return 1; +} + +static int ext_supported_groups_parse_clienthello(SSL *ssl, uint8_t *out_alert, + CBS *contents) { + if (contents == NULL) { + return 1; + } + + CBS supported_group_list; + if (!CBS_get_u16_length_prefixed(contents, &supported_group_list) || + CBS_len(&supported_group_list) == 0 || + (CBS_len(&supported_group_list) & 1) != 0 || + CBS_len(contents) != 0) { + return 0; + } + + ssl->s3->tmp.peer_supported_group_list = OPENSSL_malloc( + CBS_len(&supported_group_list)); + if (ssl->s3->tmp.peer_supported_group_list == NULL) { + *out_alert = SSL_AD_INTERNAL_ERROR; + return 0; + } + + const size_t num_groups = CBS_len(&supported_group_list) / 2; + size_t i; + for (i = 0; i < num_groups; i++) { + if (!CBS_get_u16(&supported_group_list, + &ssl->s3->tmp.peer_supported_group_list[i])) { + goto err; + } + } + + assert(CBS_len(&supported_group_list) == 0); + ssl->s3->tmp.peer_supported_group_list_len = num_groups; + + return 1; + +err: + OPENSSL_free(ssl->s3->tmp.peer_supported_group_list); + ssl->s3->tmp.peer_supported_group_list = NULL; + *out_alert = SSL_AD_INTERNAL_ERROR; + return 0; +} + +static int ext_supported_groups_add_serverhello(SSL *ssl, CBB *out) { + /* Servers don't echo this extension. */ + return 1; +} + + +/* kExtensions contains all the supported extensions. */ +static const struct tls_extension kExtensions[] = { + { + /* The renegotiation extension must always be at index zero because the + * |received| and |sent| bitsets need to be tweaked when the "extension" is + * sent as an SCSV. */ + TLSEXT_TYPE_renegotiate, + NULL, + ext_ri_add_clienthello, + ext_ri_parse_serverhello, + ext_ri_parse_clienthello, + ext_ri_add_serverhello, + }, + { + TLSEXT_TYPE_server_name, + ext_sni_init, + ext_sni_add_clienthello, + ext_sni_parse_serverhello, + ext_sni_parse_clienthello, + ext_sni_add_serverhello, + }, + { + TLSEXT_TYPE_extended_master_secret, + ext_ems_init, + ext_ems_add_clienthello, + ext_ems_parse_serverhello, + ext_ems_parse_clienthello, + ext_ems_add_serverhello, + }, + { + TLSEXT_TYPE_session_ticket, + NULL, + ext_ticket_add_clienthello, + ext_ticket_parse_serverhello, + ext_ticket_parse_clienthello, + ext_ticket_add_serverhello, + }, + { + TLSEXT_TYPE_signature_algorithms, + NULL, + ext_sigalgs_add_clienthello, + ext_sigalgs_parse_serverhello, + ext_sigalgs_parse_clienthello, + ext_sigalgs_add_serverhello, + }, + { + TLSEXT_TYPE_status_request, + ext_ocsp_init, + ext_ocsp_add_clienthello, + ext_ocsp_parse_serverhello, + ext_ocsp_parse_clienthello, + ext_ocsp_add_serverhello, + }, + { + TLSEXT_TYPE_next_proto_neg, + ext_npn_init, + ext_npn_add_clienthello, + ext_npn_parse_serverhello, + ext_npn_parse_clienthello, + ext_npn_add_serverhello, + }, + { + TLSEXT_TYPE_certificate_timestamp, + NULL, + ext_sct_add_clienthello, + ext_sct_parse_serverhello, + ext_sct_parse_clienthello, + ext_sct_add_serverhello, + }, + { + TLSEXT_TYPE_application_layer_protocol_negotiation, + ext_alpn_init, + ext_alpn_add_clienthello, + ext_alpn_parse_serverhello, + ext_alpn_parse_clienthello, + ext_alpn_add_serverhello, + }, + { + TLSEXT_TYPE_channel_id, + ext_channel_id_init, + ext_channel_id_add_clienthello, + ext_channel_id_parse_serverhello, + ext_channel_id_parse_clienthello, + ext_channel_id_add_serverhello, + }, + { + TLSEXT_TYPE_srtp, + ext_srtp_init, + ext_srtp_add_clienthello, + ext_srtp_parse_serverhello, + ext_srtp_parse_clienthello, + ext_srtp_add_serverhello, + }, + { + TLSEXT_TYPE_ec_point_formats, + NULL, + ext_ec_point_add_clienthello, + ext_ec_point_parse_serverhello, + ext_ec_point_parse_clienthello, + ext_ec_point_add_serverhello, + }, + /* The final extension must be non-empty. WebSphere Application Server 7.0 is + * intolerant to the last extension being zero-length. See + * https://crbug.com/363583. */ + { + TLSEXT_TYPE_supported_groups, + ext_supported_groups_init, + ext_supported_groups_add_clienthello, + ext_supported_groups_parse_serverhello, + ext_supported_groups_parse_clienthello, + ext_supported_groups_add_serverhello, + }, +}; + +#define kNumExtensions (sizeof(kExtensions) / sizeof(struct tls_extension)) + +OPENSSL_COMPILE_ASSERT(kNumExtensions <= + sizeof(((SSL *)NULL)->s3->tmp.extensions.sent) * 8, + too_many_extensions_for_sent_bitset); +OPENSSL_COMPILE_ASSERT(kNumExtensions <= + sizeof(((SSL *)NULL)->s3->tmp.extensions.received) * + 8, + too_many_extensions_for_received_bitset); + +static const struct tls_extension *tls_extension_find(uint32_t *out_index, + uint16_t value) { + unsigned i; + for (i = 0; i < kNumExtensions; i++) { + if (kExtensions[i].value == value) { + *out_index = i; + return &kExtensions[i]; + } + } + + return NULL; +} + +int SSL_extension_supported(unsigned extension_value) { + uint32_t index; + return extension_value == TLSEXT_TYPE_padding || + tls_extension_find(&index, extension_value) != NULL; +} + +int ssl_add_clienthello_tlsext(SSL *ssl, CBB *out, size_t header_len) { + /* don't add extensions for SSLv3 unless doing secure renegotiation */ + if (ssl->client_version == SSL3_VERSION && + !ssl->s3->send_connection_binding) { + return 1; + } + + CBB extensions; + if (!CBB_add_u16_length_prefixed(out, &extensions)) { + goto err; + } + + ssl->s3->tmp.extensions.sent = 0; + ssl->s3->tmp.custom_extensions.sent = 0; + + size_t i; + for (i = 0; i < kNumExtensions; i++) { + if (kExtensions[i].init != NULL) { + kExtensions[i].init(ssl); + } + } + + for (i = 0; i < kNumExtensions; i++) { + const size_t len_before = CBB_len(&extensions); + if (!kExtensions[i].add_clienthello(ssl, &extensions)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_ADDING_EXTENSION); + ERR_add_error_dataf("extension: %u", (unsigned)kExtensions[i].value); + goto err; + } + + if (CBB_len(&extensions) != len_before) { + ssl->s3->tmp.extensions.sent |= (1u << i); + } + } + + if (!custom_ext_add_clienthello(ssl, &extensions)) { + goto err; + } + + if (!SSL_IS_DTLS(ssl)) { + header_len += 2 + CBB_len(&extensions); + if (header_len > 0xff && header_len < 0x200) { + /* Add padding to workaround bugs in F5 terminators. See RFC 7685. + * + * NB: because this code works out the length of all existing extensions + * it MUST always appear last. */ + size_t padding_len = 0x200 - header_len; + /* Extensions take at least four bytes to encode. Always include at least + * one byte of data if including the extension. WebSphere Application + * Server 7.0 is intolerant to the last extension being zero-length. See + * https://crbug.com/363583. */ + if (padding_len >= 4 + 1) { + padding_len -= 4; + } else { + padding_len = 1; + } + + uint8_t *padding_bytes; + if (!CBB_add_u16(&extensions, TLSEXT_TYPE_padding) || + !CBB_add_u16(&extensions, padding_len) || + !CBB_add_space(&extensions, &padding_bytes, padding_len)) { + goto err; + } + + memset(padding_bytes, 0, padding_len); + } + } + + /* Discard empty extensions blocks. */ + if (CBB_len(&extensions) == 0) { + CBB_discard_child(out); + } + + return CBB_flush(out); + +err: + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + return 0; +} + +int ssl_add_serverhello_tlsext(SSL *ssl, CBB *out) { + CBB extensions; + if (!CBB_add_u16_length_prefixed(out, &extensions)) { + goto err; + } + + unsigned i; + for (i = 0; i < kNumExtensions; i++) { + if (!(ssl->s3->tmp.extensions.received & (1u << i))) { + /* Don't send extensions that were not received. */ + continue; + } + + if (!kExtensions[i].add_serverhello(ssl, &extensions)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_ADDING_EXTENSION); + ERR_add_error_dataf("extension: %u", (unsigned)kExtensions[i].value); + goto err; + } + } + + if (!custom_ext_add_serverhello(ssl, &extensions)) { + goto err; + } + + /* Discard empty extensions blocks. */ + if (CBB_len(&extensions) == 0) { + CBB_discard_child(out); + } + + return CBB_flush(out); + +err: + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + return 0; +} + +static int ssl_scan_clienthello_tlsext(SSL *ssl, CBS *cbs, int *out_alert) { + size_t i; + for (i = 0; i < kNumExtensions; i++) { + if (kExtensions[i].init != NULL) { + kExtensions[i].init(ssl); + } + } + + ssl->s3->tmp.extensions.received = 0; + ssl->s3->tmp.custom_extensions.received = 0; + /* The renegotiation extension must always be at index zero because the + * |received| and |sent| bitsets need to be tweaked when the "extension" is + * sent as an SCSV. */ + assert(kExtensions[0].value == TLSEXT_TYPE_renegotiate); + + /* There may be no extensions. */ + if (CBS_len(cbs) != 0) { + /* Decode the extensions block and check it is valid. */ + CBS extensions; + if (!CBS_get_u16_length_prefixed(cbs, &extensions) || + !tls1_check_duplicate_extensions(&extensions)) { + *out_alert = SSL_AD_DECODE_ERROR; + return 0; + } + + while (CBS_len(&extensions) != 0) { + uint16_t type; + CBS extension; + + /* Decode the next extension. */ + if (!CBS_get_u16(&extensions, &type) || + !CBS_get_u16_length_prefixed(&extensions, &extension)) { + *out_alert = SSL_AD_DECODE_ERROR; + return 0; + } + + /* RFC 5746 made the existence of extensions in SSL 3.0 somewhat + * ambiguous. Ignore all but the renegotiation_info extension. */ + if (ssl->version == SSL3_VERSION && type != TLSEXT_TYPE_renegotiate) { + continue; + } + + unsigned ext_index; + const struct tls_extension *const ext = + tls_extension_find(&ext_index, type); + + if (ext == NULL) { + if (!custom_ext_parse_clienthello(ssl, out_alert, type, &extension)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_PARSING_EXTENSION); + return 0; + } + continue; + } + + ssl->s3->tmp.extensions.received |= (1u << ext_index); + uint8_t alert = SSL_AD_DECODE_ERROR; + if (!ext->parse_clienthello(ssl, &alert, &extension)) { + *out_alert = alert; + OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_PARSING_EXTENSION); + ERR_add_error_dataf("extension: %u", (unsigned)type); + return 0; + } + } + } + + for (i = 0; i < kNumExtensions; i++) { + if (!(ssl->s3->tmp.extensions.received & (1u << i))) { + /* Extension wasn't observed so call the callback with a NULL + * parameter. */ + uint8_t alert = SSL_AD_DECODE_ERROR; + if (!kExtensions[i].parse_clienthello(ssl, &alert, NULL)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_EXTENSION); + ERR_add_error_dataf("extension: %u", (unsigned)kExtensions[i].value); + *out_alert = alert; + return 0; + } + } + } + + return 1; +} + +int ssl_parse_clienthello_tlsext(SSL *ssl, CBS *cbs) { + int alert = -1; + if (ssl_scan_clienthello_tlsext(ssl, cbs, &alert) <= 0) { + ssl3_send_alert(ssl, SSL3_AL_FATAL, alert); + return 0; + } + + if (ssl_check_clienthello_tlsext(ssl) <= 0) { + OPENSSL_PUT_ERROR(SSL, SSL_R_CLIENTHELLO_TLSEXT); + return 0; + } + + return 1; +} + +OPENSSL_COMPILE_ASSERT(kNumExtensions <= sizeof(uint32_t) * 8, too_many_bits); + +static int ssl_scan_serverhello_tlsext(SSL *ssl, CBS *cbs, int *out_alert) { + uint32_t received = 0; + + if (CBS_len(cbs) != 0) { + /* Decode the extensions block and check it is valid. */ + CBS extensions; + if (!CBS_get_u16_length_prefixed(cbs, &extensions) || + !tls1_check_duplicate_extensions(&extensions)) { + *out_alert = SSL_AD_DECODE_ERROR; + return 0; + } + + + while (CBS_len(&extensions) != 0) { + uint16_t type; + CBS extension; + + /* Decode the next extension. */ + if (!CBS_get_u16(&extensions, &type) || + !CBS_get_u16_length_prefixed(&extensions, &extension)) { + *out_alert = SSL_AD_DECODE_ERROR; + return 0; + } + + unsigned ext_index; + const struct tls_extension *const ext = + tls_extension_find(&ext_index, type); + + if (ext == NULL) { + if (!custom_ext_parse_serverhello(ssl, out_alert, type, &extension)) { + return 0; + } + continue; + } + + if (!(ssl->s3->tmp.extensions.sent & (1u << ext_index))) { + /* If the extension was never sent then it is illegal. */ + OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION); + ERR_add_error_dataf("extension :%u", (unsigned)type); + *out_alert = SSL_AD_DECODE_ERROR; + return 0; + } + + received |= (1u << ext_index); + + uint8_t alert = SSL_AD_DECODE_ERROR; + if (!ext->parse_serverhello(ssl, &alert, &extension)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_PARSING_EXTENSION); + ERR_add_error_dataf("extension: %u", (unsigned)type); + *out_alert = alert; + return 0; + } + } + } + + size_t i; + for (i = 0; i < kNumExtensions; i++) { + if (!(received & (1u << i))) { + /* Extension wasn't observed so call the callback with a NULL + * parameter. */ + uint8_t alert = SSL_AD_DECODE_ERROR; + if (!kExtensions[i].parse_serverhello(ssl, &alert, NULL)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_EXTENSION); + ERR_add_error_dataf("extension: %u", (unsigned)kExtensions[i].value); + *out_alert = alert; + return 0; + } + } + } + + return 1; +} + +static int ssl_check_clienthello_tlsext(SSL *ssl) { + int ret = SSL_TLSEXT_ERR_NOACK; + int al = SSL_AD_UNRECOGNIZED_NAME; + + if (ssl->ctx->tlsext_servername_callback != 0) { + ret = ssl->ctx->tlsext_servername_callback(ssl, &al, + ssl->ctx->tlsext_servername_arg); + } else if (ssl->initial_ctx->tlsext_servername_callback != 0) { + ret = ssl->initial_ctx->tlsext_servername_callback( + ssl, &al, ssl->initial_ctx->tlsext_servername_arg); + } + + switch (ret) { + case SSL_TLSEXT_ERR_ALERT_FATAL: + ssl3_send_alert(ssl, SSL3_AL_FATAL, al); + return -1; + + case SSL_TLSEXT_ERR_ALERT_WARNING: + ssl3_send_alert(ssl, SSL3_AL_WARNING, al); + return 1; + + case SSL_TLSEXT_ERR_NOACK: + ssl->s3->tmp.should_ack_sni = 0; + return 1; + + default: + return 1; + } +} + +static int ssl_check_serverhello_tlsext(SSL *ssl) { + int ret = SSL_TLSEXT_ERR_OK; + int al = SSL_AD_UNRECOGNIZED_NAME; + + if (ssl->ctx->tlsext_servername_callback != 0) { + ret = ssl->ctx->tlsext_servername_callback(ssl, &al, + ssl->ctx->tlsext_servername_arg); + } else if (ssl->initial_ctx->tlsext_servername_callback != 0) { + ret = ssl->initial_ctx->tlsext_servername_callback( + ssl, &al, ssl->initial_ctx->tlsext_servername_arg); + } + + switch (ret) { + case SSL_TLSEXT_ERR_ALERT_FATAL: + ssl3_send_alert(ssl, SSL3_AL_FATAL, al); + return -1; + + case SSL_TLSEXT_ERR_ALERT_WARNING: + ssl3_send_alert(ssl, SSL3_AL_WARNING, al); + return 1; + + default: + return 1; + } +} + +int ssl_parse_serverhello_tlsext(SSL *ssl, CBS *cbs) { + int alert = -1; + if (ssl_scan_serverhello_tlsext(ssl, cbs, &alert) <= 0) { + ssl3_send_alert(ssl, SSL3_AL_FATAL, alert); + return 0; + } + + if (ssl_check_serverhello_tlsext(ssl) <= 0) { + OPENSSL_PUT_ERROR(SSL, SSL_R_SERVERHELLO_TLSEXT); + return 0; + } + + return 1; +} + +int tls_process_ticket(SSL *ssl, SSL_SESSION **out_session, + int *out_renew_ticket, const uint8_t *ticket, + size_t ticket_len, const uint8_t *session_id, + size_t session_id_len) { + int ret = 1; /* Most errors are non-fatal. */ + SSL_CTX *ssl_ctx = ssl->initial_ctx; + uint8_t *plaintext = NULL; + + HMAC_CTX hmac_ctx; + HMAC_CTX_init(&hmac_ctx); + EVP_CIPHER_CTX cipher_ctx; + EVP_CIPHER_CTX_init(&cipher_ctx); + + *out_renew_ticket = 0; + *out_session = NULL; + + if (session_id_len > SSL_MAX_SSL_SESSION_ID_LENGTH) { + goto done; + } + + /* Ensure there is room for the key name and the largest IV + * |tlsext_ticket_key_cb| may try to consume. The real limit may be lower, but + * the maximum IV length should be well under the minimum size for the + * session material and HMAC. */ + if (ticket_len < SSL_TICKET_KEY_NAME_LEN + EVP_MAX_IV_LENGTH) { + goto done; + } + const uint8_t *iv = ticket + SSL_TICKET_KEY_NAME_LEN; + + if (ssl_ctx->tlsext_ticket_key_cb != NULL) { + int cb_ret = ssl_ctx->tlsext_ticket_key_cb( + ssl, (uint8_t *)ticket /* name */, (uint8_t *)iv, &cipher_ctx, + &hmac_ctx, 0 /* decrypt */); + if (cb_ret < 0) { + ret = 0; + goto done; + } + if (cb_ret == 0) { + goto done; + } + if (cb_ret == 2) { + *out_renew_ticket = 1; + } + } else { + /* Check the key name matches. */ + if (memcmp(ticket, ssl_ctx->tlsext_tick_key_name, + SSL_TICKET_KEY_NAME_LEN) != 0) { + goto done; + } + if (!HMAC_Init_ex(&hmac_ctx, ssl_ctx->tlsext_tick_hmac_key, + sizeof(ssl_ctx->tlsext_tick_hmac_key), tlsext_tick_md(), + NULL) || + !EVP_DecryptInit_ex(&cipher_ctx, EVP_aes_128_cbc(), NULL, + ssl_ctx->tlsext_tick_aes_key, iv)) { + ret = 0; + goto done; + } + } + size_t iv_len = EVP_CIPHER_CTX_iv_length(&cipher_ctx); + + /* Check the MAC at the end of the ticket. */ + uint8_t mac[EVP_MAX_MD_SIZE]; + size_t mac_len = HMAC_size(&hmac_ctx); + if (ticket_len < SSL_TICKET_KEY_NAME_LEN + iv_len + 1 + mac_len) { + /* The ticket must be large enough for key name, IV, data, and MAC. */ + goto done; + } + HMAC_Update(&hmac_ctx, ticket, ticket_len - mac_len); + HMAC_Final(&hmac_ctx, mac, NULL); + if (CRYPTO_memcmp(mac, ticket + (ticket_len - mac_len), mac_len) != 0) { + goto done; + } + + /* Decrypt the session data. */ + const uint8_t *ciphertext = ticket + SSL_TICKET_KEY_NAME_LEN + iv_len; + size_t ciphertext_len = ticket_len - SSL_TICKET_KEY_NAME_LEN - iv_len - + mac_len; + plaintext = OPENSSL_malloc(ciphertext_len); + if (plaintext == NULL) { + ret = 0; + goto done; + } + if (ciphertext_len >= INT_MAX) { + goto done; + } + int len1, len2; + if (!EVP_DecryptUpdate(&cipher_ctx, plaintext, &len1, ciphertext, + (int)ciphertext_len) || + !EVP_DecryptFinal_ex(&cipher_ctx, plaintext + len1, &len2)) { + ERR_clear_error(); /* Don't leave an error on the queue. */ + goto done; + } + + /* Decode the session. */ + SSL_SESSION *session = SSL_SESSION_from_bytes(plaintext, len1 + len2); + if (session == NULL) { + ERR_clear_error(); /* Don't leave an error on the queue. */ + goto done; + } + + /* Copy the client's session ID into the new session, to denote the ticket has + * been accepted. */ + memcpy(session->session_id, session_id, session_id_len); + session->session_id_length = session_id_len; + + *out_session = session; + +done: + OPENSSL_free(plaintext); + HMAC_CTX_cleanup(&hmac_ctx); + EVP_CIPHER_CTX_cleanup(&cipher_ctx); + return ret; +} + +/* Tables to translate from NIDs to TLS v1.2 ids */ +typedef struct { + int nid; + int id; +} tls12_lookup; + +static const tls12_lookup tls12_md[] = { + {NID_sha1, TLSEXT_hash_sha1}, + {NID_sha256, TLSEXT_hash_sha256}, + {NID_sha384, TLSEXT_hash_sha384}, + {NID_sha512, TLSEXT_hash_sha512}, +}; + +static const tls12_lookup tls12_sig[] = {{EVP_PKEY_RSA, TLSEXT_signature_rsa}, + {EVP_PKEY_EC, TLSEXT_signature_ecdsa}}; + +static int tls12_find_id(int nid, const tls12_lookup *table, size_t tlen) { + size_t i; + for (i = 0; i < tlen; i++) { + if (table[i].nid == nid) { + return table[i].id; + } + } + + return -1; +} + +int tls12_get_sigid(int pkey_type) { + return tls12_find_id(pkey_type, tls12_sig, + sizeof(tls12_sig) / sizeof(tls12_lookup)); +} + +int tls12_add_sigandhash(SSL *ssl, CBB *out, const EVP_MD *md) { + int md_id = tls12_find_id(EVP_MD_type(md), tls12_md, + sizeof(tls12_md) / sizeof(tls12_lookup)); + int sig_id = tls12_get_sigid(ssl_private_key_type(ssl)); + + return md_id != -1 && + sig_id != -1 && + CBB_add_u8(out, (uint8_t)md_id) && + CBB_add_u8(out, (uint8_t)sig_id); +} + +const EVP_MD *tls12_get_hash(uint8_t hash_alg) { + switch (hash_alg) { + case TLSEXT_hash_sha1: + return EVP_sha1(); + + case TLSEXT_hash_sha256: + return EVP_sha256(); + + case TLSEXT_hash_sha384: + return EVP_sha384(); + + case TLSEXT_hash_sha512: + return EVP_sha512(); + + default: + return NULL; + } +} + +/* tls12_get_pkey_type returns the EVP_PKEY type corresponding to TLS signature + * algorithm |sig_alg|. It returns -1 if the type is unknown. */ +static int tls12_get_pkey_type(uint8_t sig_alg) { + switch (sig_alg) { + case TLSEXT_signature_rsa: + return EVP_PKEY_RSA; + + case TLSEXT_signature_ecdsa: + return EVP_PKEY_EC; + + default: + return -1; + } +} + +OPENSSL_COMPILE_ASSERT(sizeof(TLS_SIGALGS) == 2, + sizeof_tls_sigalgs_is_not_two); + +int tls1_parse_peer_sigalgs(SSL *ssl, const CBS *in_sigalgs) { + /* Extension ignored for inappropriate versions */ + if (ssl3_protocol_version(ssl) < TLS1_2_VERSION) { + return 1; + } + + CERT *const cert = ssl->cert; + OPENSSL_free(cert->peer_sigalgs); + cert->peer_sigalgs = NULL; + cert->peer_sigalgslen = 0; + + size_t num_sigalgs = CBS_len(in_sigalgs); + + if (num_sigalgs % 2 != 0) { + return 0; + } + num_sigalgs /= 2; + + /* supported_signature_algorithms in the certificate request is + * allowed to be empty. */ + if (num_sigalgs == 0) { + return 1; + } + + /* This multiplication doesn't overflow because sizeof(TLS_SIGALGS) is two + * (statically asserted above) and we just divided |num_sigalgs| by two. */ + cert->peer_sigalgs = OPENSSL_malloc(num_sigalgs * sizeof(TLS_SIGALGS)); + if (cert->peer_sigalgs == NULL) { + return 0; + } + cert->peer_sigalgslen = num_sigalgs; + + CBS sigalgs; + CBS_init(&sigalgs, CBS_data(in_sigalgs), CBS_len(in_sigalgs)); + + size_t i; + for (i = 0; i < num_sigalgs; i++) { + TLS_SIGALGS *const sigalg = &cert->peer_sigalgs[i]; + if (!CBS_get_u8(&sigalgs, &sigalg->rhash) || + !CBS_get_u8(&sigalgs, &sigalg->rsign)) { + return 0; + } + } + + return 1; +} + +const EVP_MD *tls1_choose_signing_digest(SSL *ssl) { + CERT *cert = ssl->cert; + int type = ssl_private_key_type(ssl); + size_t i, j; + + static const int kDefaultDigestList[] = {NID_sha256, NID_sha384, NID_sha512, + NID_sha1}; + + const int *digest_nids = kDefaultDigestList; + size_t num_digest_nids = + sizeof(kDefaultDigestList) / sizeof(kDefaultDigestList[0]); + if (cert->digest_nids != NULL) { + digest_nids = cert->digest_nids; + num_digest_nids = cert->num_digest_nids; + } + + for (i = 0; i < num_digest_nids; i++) { + const int digest_nid = digest_nids[i]; + for (j = 0; j < cert->peer_sigalgslen; j++) { + const EVP_MD *md = tls12_get_hash(cert->peer_sigalgs[j].rhash); + if (md == NULL || + digest_nid != EVP_MD_type(md) || + tls12_get_pkey_type(cert->peer_sigalgs[j].rsign) != type) { + continue; + } + + return md; + } + } + + /* If no suitable digest may be found, default to SHA-1. */ + return EVP_sha1(); +} + +int tls1_channel_id_hash(SSL *ssl, uint8_t *out, size_t *out_len) { + int ret = 0; + EVP_MD_CTX ctx; + + EVP_MD_CTX_init(&ctx); + if (!EVP_DigestInit_ex(&ctx, EVP_sha256(), NULL)) { + goto err; + } + + static const char kClientIDMagic[] = "TLS Channel ID signature"; + EVP_DigestUpdate(&ctx, kClientIDMagic, sizeof(kClientIDMagic)); + + if (ssl->hit) { + static const char kResumptionMagic[] = "Resumption"; + EVP_DigestUpdate(&ctx, kResumptionMagic, sizeof(kResumptionMagic)); + if (ssl->session->original_handshake_hash_len == 0) { + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + goto err; + } + EVP_DigestUpdate(&ctx, ssl->session->original_handshake_hash, + ssl->session->original_handshake_hash_len); + } + + uint8_t handshake_hash[EVP_MAX_MD_SIZE]; + int handshake_hash_len = tls1_handshake_digest(ssl, handshake_hash, + sizeof(handshake_hash)); + if (handshake_hash_len < 0) { + goto err; + } + EVP_DigestUpdate(&ctx, handshake_hash, (size_t)handshake_hash_len); + unsigned len_u; + EVP_DigestFinal_ex(&ctx, out, &len_u); + *out_len = len_u; + + ret = 1; + +err: + EVP_MD_CTX_cleanup(&ctx); + return ret; +} + +/* tls1_record_handshake_hashes_for_channel_id records the current handshake + * hashes in |ssl->session| so that Channel ID resumptions can sign that + * data. */ +int tls1_record_handshake_hashes_for_channel_id(SSL *ssl) { + int digest_len; + /* This function should never be called for a resumed session because the + * handshake hashes that we wish to record are for the original, full + * handshake. */ + if (ssl->hit) { + return -1; + } + + digest_len = + tls1_handshake_digest(ssl, ssl->session->original_handshake_hash, + sizeof(ssl->session->original_handshake_hash)); + if (digest_len < 0) { + return -1; + } + + ssl->session->original_handshake_hash_len = digest_len; + + return 1; +} diff --git a/external/boringssl/ssl/test/CMakeLists.txt b/external/boringssl/ssl/test/CMakeLists.txt new file mode 100644 index 0000000000..3b07903084 --- /dev/null +++ b/external/boringssl/ssl/test/CMakeLists.txt @@ -0,0 +1,14 @@ +include_directories(../../include) + +add_executable( + bssl_shim + + async_bio.cc + bssl_shim.cc + packeted_bio.cc + test_config.cc + + $ +) + +target_link_libraries(bssl_shim ssl crypto) diff --git a/external/boringssl/ssl/test/README.md b/external/boringssl/ssl/test/README.md new file mode 100644 index 0000000000..7a46c323e3 --- /dev/null +++ b/external/boringssl/ssl/test/README.md @@ -0,0 +1,35 @@ +# BoringSSL SSL Tests + +This directory contains BoringSSL's protocol-level test suite. + +Testing a TLS implementation can be difficult. We need to produce invalid but +sufficiently correct handshakes to get our implementation close to its edge +cases. TLS's cryptographic steps mean we cannot use a transcript and effectively +need a TLS implementation on the other end. But we do not wish to litter +BoringSSL with options for bugs to test against. + +Instead, we use a fork of the Go `crypto/tls` package, heavily patched with +configurable bugs. This code, along with a test suite and harness written in Go, +lives in the `runner` directory. The harness runs BoringSSL via a C/C++ shim +binary which lives in this directory. All communication with the shim binary +occurs with command-line flags, sockets, and standard I/O. + +This strategy also ensures we always test against a second implementation. All +features should be implemented twice, once in C for BoringSSL and once in Go for +testing. If possible, the Go code should be suitable for potentially +upstreaming. However, sometimes test code has different needs. For example, our +test DTLS code enforces strict ordering on sequence numbers and has controlled +packet drop simulation. + +To run the tests manually, run `go test` from the `runner` directory. It takes +command-line flags found at the top of `runner/runner.go`. The `-help` option +also works after using `go test -c` to make a `runner.test` binary first. + +If adding a new test, these files may be a good starting point: + + * `runner/runner.go`: the test harness and all the individual tests. + * `runner/common.go`: contains the `Config` and `ProtocolBugs` struct which + control the Go TLS implementation's behavior. + * `test_config.h`, `test_config.cc`: the command-line flags which control the + shim's behavior. + * `bssl_shim.cc`: the shim binary itself. diff --git a/external/boringssl/ssl/test/async_bio.cc b/external/boringssl/ssl/test/async_bio.cc new file mode 100644 index 0000000000..7a5737bbea --- /dev/null +++ b/external/boringssl/ssl/test/async_bio.cc @@ -0,0 +1,188 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include "async_bio.h" + +#include +#include + +#include + + +namespace { + +extern const BIO_METHOD g_async_bio_method; + +struct AsyncBio { + bool datagram; + bool enforce_write_quota; + size_t read_quota; + size_t write_quota; +}; + +AsyncBio *GetData(BIO *bio) { + if (bio->method != &g_async_bio_method) { + return NULL; + } + return (AsyncBio *)bio->ptr; +} + +static int AsyncWrite(BIO *bio, const char *in, int inl) { + AsyncBio *a = GetData(bio); + if (a == NULL || bio->next_bio == NULL) { + return 0; + } + + if (!a->enforce_write_quota) { + return BIO_write(bio->next_bio, in, inl); + } + + BIO_clear_retry_flags(bio); + + if (a->write_quota == 0) { + BIO_set_retry_write(bio); + errno = EAGAIN; + return -1; + } + + if (!a->datagram && (size_t)inl > a->write_quota) { + inl = a->write_quota; + } + int ret = BIO_write(bio->next_bio, in, inl); + if (ret <= 0) { + BIO_copy_next_retry(bio); + } else { + a->write_quota -= (a->datagram ? 1 : ret); + } + return ret; +} + +static int AsyncRead(BIO *bio, char *out, int outl) { + AsyncBio *a = GetData(bio); + if (a == NULL || bio->next_bio == NULL) { + return 0; + } + + BIO_clear_retry_flags(bio); + + if (a->read_quota == 0) { + BIO_set_retry_read(bio); + errno = EAGAIN; + return -1; + } + + if (!a->datagram && (size_t)outl > a->read_quota) { + outl = a->read_quota; + } + int ret = BIO_read(bio->next_bio, out, outl); + if (ret <= 0) { + BIO_copy_next_retry(bio); + } else { + a->read_quota -= (a->datagram ? 1 : ret); + } + return ret; +} + +static long AsyncCtrl(BIO *bio, int cmd, long num, void *ptr) { + if (bio->next_bio == NULL) { + return 0; + } + BIO_clear_retry_flags(bio); + int ret = BIO_ctrl(bio->next_bio, cmd, num, ptr); + BIO_copy_next_retry(bio); + return ret; +} + +static int AsyncNew(BIO *bio) { + AsyncBio *a = (AsyncBio *)OPENSSL_malloc(sizeof(*a)); + if (a == NULL) { + return 0; + } + memset(a, 0, sizeof(*a)); + a->enforce_write_quota = true; + bio->init = 1; + bio->ptr = (char *)a; + return 1; +} + +static int AsyncFree(BIO *bio) { + if (bio == NULL) { + return 0; + } + + OPENSSL_free(bio->ptr); + bio->ptr = NULL; + bio->init = 0; + bio->flags = 0; + return 1; +} + +static long AsyncCallbackCtrl(BIO *bio, int cmd, bio_info_cb fp) { + if (bio->next_bio == NULL) { + return 0; + } + return BIO_callback_ctrl(bio->next_bio, cmd, fp); +} + +const BIO_METHOD g_async_bio_method = { + BIO_TYPE_FILTER, + "async bio", + AsyncWrite, + AsyncRead, + NULL /* puts */, + NULL /* gets */, + AsyncCtrl, + AsyncNew, + AsyncFree, + AsyncCallbackCtrl, +}; + +} // namespace + +ScopedBIO AsyncBioCreate() { + return ScopedBIO(BIO_new(&g_async_bio_method)); +} + +ScopedBIO AsyncBioCreateDatagram() { + ScopedBIO ret(BIO_new(&g_async_bio_method)); + if (!ret) { + return nullptr; + } + GetData(ret.get())->datagram = true; + return ret; +} + +void AsyncBioAllowRead(BIO *bio, size_t count) { + AsyncBio *a = GetData(bio); + if (a == NULL) { + return; + } + a->read_quota += count; +} + +void AsyncBioAllowWrite(BIO *bio, size_t count) { + AsyncBio *a = GetData(bio); + if (a == NULL) { + return; + } + a->write_quota += count; +} + +void AsyncBioEnforceWriteQuota(BIO *bio, bool enforce) { + AsyncBio *a = GetData(bio); + if (a == NULL) { + return; + } + a->enforce_write_quota = enforce; +} diff --git a/external/boringssl/ssl/test/async_bio.h b/external/boringssl/ssl/test/async_bio.h new file mode 100644 index 0000000000..fbc40163ee --- /dev/null +++ b/external/boringssl/ssl/test/async_bio.h @@ -0,0 +1,45 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef HEADER_ASYNC_BIO +#define HEADER_ASYNC_BIO + +#include + +#include "../../crypto/test/scoped_types.h" + + +// AsyncBioCreate creates a filter BIO for testing asynchronous state +// machines which consume a stream socket. Reads and writes will fail +// and return EAGAIN unless explicitly allowed. Each async BIO has a +// read quota and a write quota. Initially both are zero. As each is +// incremented, bytes are allowed to flow through the BIO. +ScopedBIO AsyncBioCreate(); + +// AsyncBioCreateDatagram creates a filter BIO for testing for +// asynchronous state machines which consume datagram sockets. The read +// and write quota count in packets rather than bytes. +ScopedBIO AsyncBioCreateDatagram(); + +// AsyncBioAllowRead increments |bio|'s read quota by |count|. +void AsyncBioAllowRead(BIO *bio, size_t count); + +// AsyncBioAllowWrite increments |bio|'s write quota by |count|. +void AsyncBioAllowWrite(BIO *bio, size_t count); + +// AsyncBioEnforceWriteQuota configures where |bio| enforces its write quota. +void AsyncBioEnforceWriteQuota(BIO *bio, bool enforce); + + +#endif // HEADER_ASYNC_BIO diff --git a/external/boringssl/ssl/test/bssl_shim.cc b/external/boringssl/ssl/test/bssl_shim.cc new file mode 100644 index 0000000000..ef759d9f5a --- /dev/null +++ b/external/boringssl/ssl/test/bssl_shim.cc @@ -0,0 +1,1598 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#if !defined(__STDC_FORMAT_MACROS) +#define __STDC_FORMAT_MACROS +#endif + +#include + +#if !defined(OPENSSL_WINDOWS) +#include +#include +#include +#include +#include +#include +#include +#else +#include +OPENSSL_MSVC_PRAGMA(warning(push, 3)) +#include +#include +OPENSSL_MSVC_PRAGMA(warning(pop)) + +#pragma comment(lib, "Ws2_32.lib") +#endif + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "../../crypto/test/scoped_types.h" +#include "async_bio.h" +#include "packeted_bio.h" +#include "scoped_types.h" +#include "test_config.h" + + +#if !defined(OPENSSL_WINDOWS) +static int closesocket(int sock) { + return close(sock); +} + +static void PrintSocketError(const char *func) { + perror(func); +} +#else +static void PrintSocketError(const char *func) { + fprintf(stderr, "%s: %d\n", func, WSAGetLastError()); +} +#endif + +static int Usage(const char *program) { + fprintf(stderr, "Usage: %s [flags...]\n", program); + return 1; +} + +struct TestState { + // async_bio is async BIO which pauses reads and writes. + BIO *async_bio = nullptr; + // packeted_bio is the packeted BIO which simulates read timeouts. + BIO *packeted_bio = nullptr; + ScopedEVP_PKEY channel_id; + bool cert_ready = false; + ScopedSSL_SESSION session; + ScopedSSL_SESSION pending_session; + bool early_callback_called = false; + bool handshake_done = false; + // private_key is the underlying private key used when testing custom keys. + ScopedEVP_PKEY private_key; + std::vector private_key_result; + // private_key_retries is the number of times an asynchronous private key + // operation has been retried. + unsigned private_key_retries = 0; + bool got_new_session = false; +}; + +static void TestStateExFree(void *parent, void *ptr, CRYPTO_EX_DATA *ad, + int index, long argl, void *argp) { + delete ((TestState *)ptr); +} + +static int g_config_index = 0; +static int g_state_index = 0; + +static bool SetTestConfig(SSL *ssl, const TestConfig *config) { + return SSL_set_ex_data(ssl, g_config_index, (void *)config) == 1; +} + +static const TestConfig *GetTestConfig(const SSL *ssl) { + return (const TestConfig *)SSL_get_ex_data(ssl, g_config_index); +} + +static bool SetTestState(SSL *ssl, std::unique_ptr state) { + // |SSL_set_ex_data| takes ownership of |state| only on success. + if (SSL_set_ex_data(ssl, g_state_index, state.get()) == 1) { + state.release(); + return true; + } + return false; +} + +static TestState *GetTestState(const SSL *ssl) { + return (TestState *)SSL_get_ex_data(ssl, g_state_index); +} + +static ScopedX509 LoadCertificate(const std::string &file) { + ScopedBIO bio(BIO_new(BIO_s_file())); + if (!bio || !BIO_read_filename(bio.get(), file.c_str())) { + return nullptr; + } + return ScopedX509(PEM_read_bio_X509(bio.get(), NULL, NULL, NULL)); +} + +static ScopedEVP_PKEY LoadPrivateKey(const std::string &file) { + ScopedBIO bio(BIO_new(BIO_s_file())); + if (!bio || !BIO_read_filename(bio.get(), file.c_str())) { + return nullptr; + } + return ScopedEVP_PKEY(PEM_read_bio_PrivateKey(bio.get(), NULL, NULL, NULL)); +} + +static int AsyncPrivateKeyType(SSL *ssl) { + return EVP_PKEY_id(GetTestState(ssl)->private_key.get()); +} + +static size_t AsyncPrivateKeyMaxSignatureLen(SSL *ssl) { + return EVP_PKEY_size(GetTestState(ssl)->private_key.get()); +} + +static ssl_private_key_result_t AsyncPrivateKeySign( + SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out, + const EVP_MD *md, const uint8_t *in, size_t in_len) { + TestState *test_state = GetTestState(ssl); + if (!test_state->private_key_result.empty()) { + fprintf(stderr, "AsyncPrivateKeySign called with operation pending.\n"); + abort(); + } + + ScopedEVP_PKEY_CTX ctx(EVP_PKEY_CTX_new(test_state->private_key.get(), + nullptr)); + if (!ctx) { + return ssl_private_key_failure; + } + + // Write the signature into |test_state|. + size_t len = 0; + if (!EVP_PKEY_sign_init(ctx.get()) || + !EVP_PKEY_CTX_set_signature_md(ctx.get(), md) || + !EVP_PKEY_sign(ctx.get(), nullptr, &len, in, in_len)) { + return ssl_private_key_failure; + } + test_state->private_key_result.resize(len); + if (!EVP_PKEY_sign(ctx.get(), test_state->private_key_result.data(), &len, in, + in_len)) { + return ssl_private_key_failure; + } + test_state->private_key_result.resize(len); + + // The signature will be released asynchronously in + // |AsyncPrivateKeySignComplete|. + return ssl_private_key_retry; +} + +static ssl_private_key_result_t AsyncPrivateKeySignComplete( + SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out) { + TestState *test_state = GetTestState(ssl); + if (test_state->private_key_result.empty()) { + fprintf(stderr, + "AsyncPrivateKeySignComplete called without operation pending.\n"); + abort(); + } + + if (test_state->private_key_retries < 2) { + // Only return the signature on the second attempt, to test both incomplete + // |sign| and |sign_complete|. + return ssl_private_key_retry; + } + + if (max_out < test_state->private_key_result.size()) { + fprintf(stderr, "Output buffer too small.\n"); + return ssl_private_key_failure; + } + memcpy(out, test_state->private_key_result.data(), + test_state->private_key_result.size()); + *out_len = test_state->private_key_result.size(); + + test_state->private_key_result.clear(); + test_state->private_key_retries = 0; + return ssl_private_key_success; +} + +static ssl_private_key_result_t AsyncPrivateKeyDecrypt( + SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out, + const uint8_t *in, size_t in_len) { + TestState *test_state = GetTestState(ssl); + if (!test_state->private_key_result.empty()) { + fprintf(stderr, + "AsyncPrivateKeyDecrypt called with operation pending.\n"); + abort(); + } + + RSA *rsa = EVP_PKEY_get0_RSA(test_state->private_key.get()); + if (rsa == NULL) { + fprintf(stderr, + "AsyncPrivateKeyDecrypt called with incorrect key type.\n"); + abort(); + } + test_state->private_key_result.resize(RSA_size(rsa)); + if (!RSA_decrypt(rsa, out_len, test_state->private_key_result.data(), + RSA_size(rsa), in, in_len, RSA_NO_PADDING)) { + return ssl_private_key_failure; + } + + test_state->private_key_result.resize(*out_len); + + // The decryption will be released asynchronously in + // |AsyncPrivateKeyDecryptComplete|. + return ssl_private_key_retry; +} + +static ssl_private_key_result_t AsyncPrivateKeyDecryptComplete( + SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out) { + TestState *test_state = GetTestState(ssl); + if (test_state->private_key_result.empty()) { + fprintf(stderr, + "AsyncPrivateKeyDecryptComplete called without operation " + "pending.\n"); + abort(); + } + + if (test_state->private_key_retries < 2) { + // Only return the decryption on the second attempt, to test both incomplete + // |decrypt| and |decrypt_complete|. + return ssl_private_key_retry; + } + + if (max_out < test_state->private_key_result.size()) { + fprintf(stderr, "Output buffer too small.\n"); + return ssl_private_key_failure; + } + memcpy(out, test_state->private_key_result.data(), + test_state->private_key_result.size()); + *out_len = test_state->private_key_result.size(); + + test_state->private_key_result.clear(); + test_state->private_key_retries = 0; + return ssl_private_key_success; +} + +static const SSL_PRIVATE_KEY_METHOD g_async_private_key_method = { + AsyncPrivateKeyType, + AsyncPrivateKeyMaxSignatureLen, + AsyncPrivateKeySign, + AsyncPrivateKeySignComplete, + AsyncPrivateKeyDecrypt, + AsyncPrivateKeyDecryptComplete +}; + +template +struct Free { + void operator()(T *buf) { + free(buf); + } +}; + +static bool GetCertificate(SSL *ssl, ScopedX509 *out_x509, + ScopedEVP_PKEY *out_pkey) { + const TestConfig *config = GetTestConfig(ssl); + + if (!config->digest_prefs.empty()) { + std::unique_ptr> digest_prefs( + strdup(config->digest_prefs.c_str())); + std::vector digest_list; + + for (;;) { + char *token = + strtok(digest_list.empty() ? digest_prefs.get() : nullptr, ","); + if (token == nullptr) { + break; + } + + digest_list.push_back(EVP_MD_type(EVP_get_digestbyname(token))); + } + + if (!SSL_set_private_key_digest_prefs(ssl, digest_list.data(), + digest_list.size())) { + return false; + } + } + + if (!config->key_file.empty()) { + *out_pkey = LoadPrivateKey(config->key_file.c_str()); + if (!*out_pkey) { + return false; + } + } + if (!config->cert_file.empty()) { + *out_x509 = LoadCertificate(config->cert_file.c_str()); + if (!*out_x509) { + return false; + } + } + if (!config->ocsp_response.empty() && + !SSL_CTX_set_ocsp_response(ssl->ctx, + (const uint8_t *)config->ocsp_response.data(), + config->ocsp_response.size())) { + return false; + } + return true; +} + +static bool InstallCertificate(SSL *ssl) { + ScopedX509 x509; + ScopedEVP_PKEY pkey; + if (!GetCertificate(ssl, &x509, &pkey)) { + return false; + } + + if (pkey) { + TestState *test_state = GetTestState(ssl); + const TestConfig *config = GetTestConfig(ssl); + if (config->async) { + test_state->private_key = std::move(pkey); + SSL_set_private_key_method(ssl, &g_async_private_key_method); + } else if (!SSL_use_PrivateKey(ssl, pkey.get())) { + return false; + } + } + + if (x509 && !SSL_use_certificate(ssl, x509.get())) { + return false; + } + + return true; +} + +static int SelectCertificateCallback(const struct ssl_early_callback_ctx *ctx) { + const TestConfig *config = GetTestConfig(ctx->ssl); + GetTestState(ctx->ssl)->early_callback_called = true; + + if (!config->expected_server_name.empty()) { + const uint8_t *extension_data; + size_t extension_len; + CBS extension, server_name_list, host_name; + uint8_t name_type; + + if (!SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_server_name, + &extension_data, + &extension_len)) { + fprintf(stderr, "Could not find server_name extension.\n"); + return -1; + } + + CBS_init(&extension, extension_data, extension_len); + if (!CBS_get_u16_length_prefixed(&extension, &server_name_list) || + CBS_len(&extension) != 0 || + !CBS_get_u8(&server_name_list, &name_type) || + name_type != TLSEXT_NAMETYPE_host_name || + !CBS_get_u16_length_prefixed(&server_name_list, &host_name) || + CBS_len(&server_name_list) != 0) { + fprintf(stderr, "Could not decode server_name extension.\n"); + return -1; + } + + if (!CBS_mem_equal(&host_name, + (const uint8_t*)config->expected_server_name.data(), + config->expected_server_name.size())) { + fprintf(stderr, "Server name mismatch.\n"); + } + } + + if (config->fail_early_callback) { + return -1; + } + + // Install the certificate in the early callback. + if (config->use_early_callback) { + if (config->async) { + // Install the certificate asynchronously. + return 0; + } + if (!InstallCertificate(ctx->ssl)) { + return -1; + } + } + return 1; +} + +static int ClientCertCallback(SSL *ssl, X509 **out_x509, EVP_PKEY **out_pkey) { + if (GetTestConfig(ssl)->async && !GetTestState(ssl)->cert_ready) { + return -1; + } + + ScopedX509 x509; + ScopedEVP_PKEY pkey; + if (!GetCertificate(ssl, &x509, &pkey)) { + return -1; + } + + // Return zero for no certificate. + if (!x509) { + return 0; + } + + // Asynchronous private keys are not supported with client_cert_cb. + *out_x509 = x509.release(); + *out_pkey = pkey.release(); + return 1; +} + +static int VerifySucceed(X509_STORE_CTX *store_ctx, void *arg) { + SSL* ssl = (SSL*)X509_STORE_CTX_get_ex_data(store_ctx, + SSL_get_ex_data_X509_STORE_CTX_idx()); + const TestConfig *config = GetTestConfig(ssl); + + if (!config->expected_ocsp_response.empty()) { + const uint8_t *data; + size_t len; + SSL_get0_ocsp_response(ssl, &data, &len); + if (len == 0) { + fprintf(stderr, "OCSP response not available in verify callback\n"); + return 0; + } + } + + return 1; +} + +static int VerifyFail(X509_STORE_CTX *store_ctx, void *arg) { + store_ctx->error = X509_V_ERR_APPLICATION_VERIFICATION; + return 0; +} + +static int NextProtosAdvertisedCallback(SSL *ssl, const uint8_t **out, + unsigned int *out_len, void *arg) { + const TestConfig *config = GetTestConfig(ssl); + if (config->advertise_npn.empty()) { + return SSL_TLSEXT_ERR_NOACK; + } + + *out = (const uint8_t*)config->advertise_npn.data(); + *out_len = config->advertise_npn.size(); + return SSL_TLSEXT_ERR_OK; +} + +static int NextProtoSelectCallback(SSL* ssl, uint8_t** out, uint8_t* outlen, + const uint8_t* in, unsigned inlen, void* arg) { + const TestConfig *config = GetTestConfig(ssl); + if (config->select_next_proto.empty()) { + return SSL_TLSEXT_ERR_NOACK; + } + + *out = (uint8_t*)config->select_next_proto.data(); + *outlen = config->select_next_proto.size(); + return SSL_TLSEXT_ERR_OK; +} + +static int AlpnSelectCallback(SSL* ssl, const uint8_t** out, uint8_t* outlen, + const uint8_t* in, unsigned inlen, void* arg) { + const TestConfig *config = GetTestConfig(ssl); + if (config->decline_alpn) { + return SSL_TLSEXT_ERR_NOACK; + } + + if (!config->expected_advertised_alpn.empty() && + (config->expected_advertised_alpn.size() != inlen || + memcmp(config->expected_advertised_alpn.data(), + in, inlen) != 0)) { + fprintf(stderr, "bad ALPN select callback inputs\n"); + exit(1); + } + + *out = (const uint8_t*)config->select_alpn.data(); + *outlen = config->select_alpn.size(); + return SSL_TLSEXT_ERR_OK; +} + +static unsigned PskClientCallback(SSL *ssl, const char *hint, + char *out_identity, + unsigned max_identity_len, + uint8_t *out_psk, unsigned max_psk_len) { + const TestConfig *config = GetTestConfig(ssl); + + if (strcmp(hint ? hint : "", config->psk_identity.c_str()) != 0) { + fprintf(stderr, "Server PSK hint did not match.\n"); + return 0; + } + + // Account for the trailing '\0' for the identity. + if (config->psk_identity.size() >= max_identity_len || + config->psk.size() > max_psk_len) { + fprintf(stderr, "PSK buffers too small\n"); + return 0; + } + + BUF_strlcpy(out_identity, config->psk_identity.c_str(), + max_identity_len); + memcpy(out_psk, config->psk.data(), config->psk.size()); + return config->psk.size(); +} + +static unsigned PskServerCallback(SSL *ssl, const char *identity, + uint8_t *out_psk, unsigned max_psk_len) { + const TestConfig *config = GetTestConfig(ssl); + + if (strcmp(identity, config->psk_identity.c_str()) != 0) { + fprintf(stderr, "Client PSK identity did not match.\n"); + return 0; + } + + if (config->psk.size() > max_psk_len) { + fprintf(stderr, "PSK buffers too small\n"); + return 0; + } + + memcpy(out_psk, config->psk.data(), config->psk.size()); + return config->psk.size(); +} + +static void CurrentTimeCallback(const SSL *ssl, timeval *out_clock) { + *out_clock = PacketedBioGetClock(GetTestState(ssl)->packeted_bio); +} + +static void ChannelIdCallback(SSL *ssl, EVP_PKEY **out_pkey) { + *out_pkey = GetTestState(ssl)->channel_id.release(); +} + +static int CertCallback(SSL *ssl, void *arg) { + if (!GetTestState(ssl)->cert_ready) { + return -1; + } + if (!InstallCertificate(ssl)) { + return 0; + } + return 1; +} + +static SSL_SESSION *GetSessionCallback(SSL *ssl, uint8_t *data, int len, + int *copy) { + TestState *async_state = GetTestState(ssl); + if (async_state->session) { + *copy = 0; + return async_state->session.release(); + } else if (async_state->pending_session) { + return SSL_magic_pending_session_ptr(); + } else { + return NULL; + } +} + +static int DDoSCallback(const struct ssl_early_callback_ctx *early_context) { + const TestConfig *config = GetTestConfig(early_context->ssl); + static int callback_num = 0; + + callback_num++; + if (config->fail_ddos_callback || + (config->fail_second_ddos_callback && callback_num == 2)) { + return 0; + } + return 1; +} + +static void InfoCallback(const SSL *ssl, int type, int val) { + if (type == SSL_CB_HANDSHAKE_DONE) { + if (GetTestConfig(ssl)->handshake_never_done) { + fprintf(stderr, "handshake completed\n"); + // Abort before any expected error code is printed, to ensure the overall + // test fails. + abort(); + } + GetTestState(ssl)->handshake_done = true; + } +} + +static int NewSessionCallback(SSL *ssl, SSL_SESSION *session) { + GetTestState(ssl)->got_new_session = true; + // BoringSSL passes a reference to |session|. + SSL_SESSION_free(session); + return 1; +} + +static int TicketKeyCallback(SSL *ssl, uint8_t *key_name, uint8_t *iv, + EVP_CIPHER_CTX *ctx, HMAC_CTX *hmac_ctx, + int encrypt) { + // This is just test code, so use the all-zeros key. + static const uint8_t kZeros[16] = {0}; + + if (encrypt) { + memcpy(key_name, kZeros, sizeof(kZeros)); + RAND_bytes(iv, 16); + } else if (memcmp(key_name, kZeros, 16) != 0) { + return 0; + } + + if (!HMAC_Init_ex(hmac_ctx, kZeros, sizeof(kZeros), EVP_sha256(), NULL) || + !EVP_CipherInit_ex(ctx, EVP_aes_128_cbc(), NULL, kZeros, iv, encrypt)) { + return -1; + } + + if (!encrypt) { + return GetTestConfig(ssl)->renew_ticket ? 2 : 1; + } + return 1; +} + +// kCustomExtensionValue is the extension value that the custom extension +// callbacks will add. +static const uint16_t kCustomExtensionValue = 1234; +static void *const kCustomExtensionAddArg = + reinterpret_cast(kCustomExtensionValue); +static void *const kCustomExtensionParseArg = + reinterpret_cast(kCustomExtensionValue + 1); +static const char kCustomExtensionContents[] = "custom extension"; + +static int CustomExtensionAddCallback(SSL *ssl, unsigned extension_value, + const uint8_t **out, size_t *out_len, + int *out_alert_value, void *add_arg) { + if (extension_value != kCustomExtensionValue || + add_arg != kCustomExtensionAddArg) { + abort(); + } + + if (GetTestConfig(ssl)->custom_extension_skip) { + return 0; + } + if (GetTestConfig(ssl)->custom_extension_fail_add) { + return -1; + } + + *out = reinterpret_cast(kCustomExtensionContents); + *out_len = sizeof(kCustomExtensionContents) - 1; + + return 1; +} + +static void CustomExtensionFreeCallback(SSL *ssl, unsigned extension_value, + const uint8_t *out, void *add_arg) { + if (extension_value != kCustomExtensionValue || + add_arg != kCustomExtensionAddArg || + out != reinterpret_cast(kCustomExtensionContents)) { + abort(); + } +} + +static int CustomExtensionParseCallback(SSL *ssl, unsigned extension_value, + const uint8_t *contents, + size_t contents_len, + int *out_alert_value, void *parse_arg) { + if (extension_value != kCustomExtensionValue || + parse_arg != kCustomExtensionParseArg) { + abort(); + } + + if (contents_len != sizeof(kCustomExtensionContents) - 1 || + memcmp(contents, kCustomExtensionContents, contents_len) != 0) { + *out_alert_value = SSL_AD_DECODE_ERROR; + return 0; + } + + return 1; +} + +// Connect returns a new socket connected to localhost on |port| or -1 on +// error. +static int Connect(uint16_t port) { + int sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock == -1) { + PrintSocketError("socket"); + return -1; + } + int nodelay = 1; + if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, + reinterpret_cast(&nodelay), sizeof(nodelay)) != 0) { + PrintSocketError("setsockopt"); + closesocket(sock); + return -1; + } + sockaddr_in sin; + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_port = htons(port); + if (!inet_pton(AF_INET, "127.0.0.1", &sin.sin_addr)) { + PrintSocketError("inet_pton"); + closesocket(sock); + return -1; + } + if (connect(sock, reinterpret_cast(&sin), + sizeof(sin)) != 0) { + PrintSocketError("connect"); + closesocket(sock); + return -1; + } + return sock; +} + +class SocketCloser { + public: + explicit SocketCloser(int sock) : sock_(sock) {} + ~SocketCloser() { + // Half-close and drain the socket before releasing it. This seems to be + // necessary for graceful shutdown on Windows. It will also avoid write + // failures in the test runner. +#if defined(OPENSSL_WINDOWS) + shutdown(sock_, SD_SEND); +#else + shutdown(sock_, SHUT_WR); +#endif + while (true) { + char buf[1024]; + if (recv(sock_, buf, sizeof(buf), 0) <= 0) { + break; + } + } + closesocket(sock_); + } + + private: + const int sock_; +}; + +static ScopedSSL_CTX SetupCtx(const TestConfig *config) { + ScopedSSL_CTX ssl_ctx(SSL_CTX_new( + config->is_dtls ? DTLS_method() : TLS_method())); + if (!ssl_ctx) { + return nullptr; + } + + std::string cipher_list = "ALL"; + if (!config->cipher.empty()) { + cipher_list = config->cipher; + SSL_CTX_set_options(ssl_ctx.get(), SSL_OP_CIPHER_SERVER_PREFERENCE); + } + if (!SSL_CTX_set_cipher_list(ssl_ctx.get(), cipher_list.c_str())) { + return nullptr; + } + + if (!config->cipher_tls10.empty() && + !SSL_CTX_set_cipher_list_tls10(ssl_ctx.get(), + config->cipher_tls10.c_str())) { + return nullptr; + } + if (!config->cipher_tls11.empty() && + !SSL_CTX_set_cipher_list_tls11(ssl_ctx.get(), + config->cipher_tls11.c_str())) { + return nullptr; + } + + ScopedDH dh(DH_get_2048_256(NULL)); + if (!dh) { + return nullptr; + } + + if (config->use_sparse_dh_prime) { + // This prime number is 2^1024 + 643 – a value just above a power of two. + // Because of its form, values modulo it are essentially certain to be one + // byte shorter. This is used to test padding of these values. + if (BN_hex2bn( + &dh->p, + "1000000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000028" + "3") == 0 || + !BN_set_word(dh->g, 2)) { + return nullptr; + } + BN_free(dh->q); + dh->q = NULL; + dh->priv_length = 0; + } + + if (!SSL_CTX_set_tmp_dh(ssl_ctx.get(), dh.get())) { + return nullptr; + } + + if (config->async && config->is_server) { + // Disable the internal session cache. To test asynchronous session lookup, + // we use an external session cache. + SSL_CTX_set_session_cache_mode( + ssl_ctx.get(), SSL_SESS_CACHE_BOTH | SSL_SESS_CACHE_NO_INTERNAL); + SSL_CTX_sess_set_get_cb(ssl_ctx.get(), GetSessionCallback); + } else { + SSL_CTX_set_session_cache_mode(ssl_ctx.get(), SSL_SESS_CACHE_BOTH); + } + + SSL_CTX_set_select_certificate_cb(ssl_ctx.get(), SelectCertificateCallback); + + if (config->use_old_client_cert_callback) { + SSL_CTX_set_client_cert_cb(ssl_ctx.get(), ClientCertCallback); + } + + SSL_CTX_set_next_protos_advertised_cb( + ssl_ctx.get(), NextProtosAdvertisedCallback, NULL); + if (!config->select_next_proto.empty()) { + SSL_CTX_set_next_proto_select_cb(ssl_ctx.get(), NextProtoSelectCallback, + NULL); + } + + if (!config->select_alpn.empty() || config->decline_alpn) { + SSL_CTX_set_alpn_select_cb(ssl_ctx.get(), AlpnSelectCallback, NULL); + } + + SSL_CTX_enable_tls_channel_id(ssl_ctx.get()); + SSL_CTX_set_channel_id_cb(ssl_ctx.get(), ChannelIdCallback); + + SSL_CTX_set_current_time_cb(ssl_ctx.get(), CurrentTimeCallback); + + SSL_CTX_set_info_callback(ssl_ctx.get(), InfoCallback); + SSL_CTX_sess_set_new_cb(ssl_ctx.get(), NewSessionCallback); + + if (config->use_ticket_callback) { + SSL_CTX_set_tlsext_ticket_key_cb(ssl_ctx.get(), TicketKeyCallback); + } + + if (config->enable_client_custom_extension && + !SSL_CTX_add_client_custom_ext( + ssl_ctx.get(), kCustomExtensionValue, CustomExtensionAddCallback, + CustomExtensionFreeCallback, kCustomExtensionAddArg, + CustomExtensionParseCallback, kCustomExtensionParseArg)) { + return nullptr; + } + + if (config->enable_server_custom_extension && + !SSL_CTX_add_server_custom_ext( + ssl_ctx.get(), kCustomExtensionValue, CustomExtensionAddCallback, + CustomExtensionFreeCallback, kCustomExtensionAddArg, + CustomExtensionParseCallback, kCustomExtensionParseArg)) { + return nullptr; + } + + if (config->verify_fail) { + SSL_CTX_set_cert_verify_callback(ssl_ctx.get(), VerifyFail, NULL); + } else { + SSL_CTX_set_cert_verify_callback(ssl_ctx.get(), VerifySucceed, NULL); + } + + if (!config->signed_cert_timestamps.empty() && + !SSL_CTX_set_signed_cert_timestamp_list( + ssl_ctx.get(), (const uint8_t *)config->signed_cert_timestamps.data(), + config->signed_cert_timestamps.size())) { + return nullptr; + } + + return ssl_ctx; +} + +// RetryAsync is called after a failed operation on |ssl| with return code +// |ret|. If the operation should be retried, it simulates one asynchronous +// event and returns true. Otherwise it returns false. +static bool RetryAsync(SSL *ssl, int ret) { + // No error; don't retry. + if (ret >= 0) { + return false; + } + + TestState *test_state = GetTestState(ssl); + assert(GetTestConfig(ssl)->async); + + if (test_state->packeted_bio != nullptr && + PacketedBioAdvanceClock(test_state->packeted_bio)) { + // The DTLS retransmit logic silently ignores write failures. So the test + // may progress, allow writes through synchronously. + AsyncBioEnforceWriteQuota(test_state->async_bio, false); + int timeout_ret = DTLSv1_handle_timeout(ssl); + AsyncBioEnforceWriteQuota(test_state->async_bio, true); + + if (timeout_ret < 0) { + fprintf(stderr, "Error retransmitting.\n"); + return false; + } + return true; + } + + // See if we needed to read or write more. If so, allow one byte through on + // the appropriate end to maximally stress the state machine. + switch (SSL_get_error(ssl, ret)) { + case SSL_ERROR_WANT_READ: + AsyncBioAllowRead(test_state->async_bio, 1); + return true; + case SSL_ERROR_WANT_WRITE: + AsyncBioAllowWrite(test_state->async_bio, 1); + return true; + case SSL_ERROR_WANT_CHANNEL_ID_LOOKUP: { + ScopedEVP_PKEY pkey = LoadPrivateKey(GetTestConfig(ssl)->send_channel_id); + if (!pkey) { + return false; + } + test_state->channel_id = std::move(pkey); + return true; + } + case SSL_ERROR_WANT_X509_LOOKUP: + test_state->cert_ready = true; + return true; + case SSL_ERROR_PENDING_SESSION: + test_state->session = std::move(test_state->pending_session); + return true; + case SSL_ERROR_PENDING_CERTIFICATE: + // The handshake will resume without a second call to the early callback. + return InstallCertificate(ssl); + case SSL_ERROR_WANT_PRIVATE_KEY_OPERATION: + test_state->private_key_retries++; + return true; + default: + return false; + } +} + +// DoRead reads from |ssl|, resolving any asynchronous operations. It returns +// the result value of the final |SSL_read| call. +static int DoRead(SSL *ssl, uint8_t *out, size_t max_out) { + const TestConfig *config = GetTestConfig(ssl); + TestState *test_state = GetTestState(ssl); + int ret; + do { + if (config->async) { + // The DTLS retransmit logic silently ignores write failures. So the test + // may progress, allow writes through synchronously. |SSL_read| may + // trigger a retransmit, so disconnect the write quota. + AsyncBioEnforceWriteQuota(test_state->async_bio, false); + } + ret = SSL_read(ssl, out, max_out); + if (config->async) { + AsyncBioEnforceWriteQuota(test_state->async_bio, true); + } + } while (config->async && RetryAsync(ssl, ret)); + return ret; +} + +// WriteAll writes |in_len| bytes from |in| to |ssl|, resolving any asynchronous +// operations. It returns the result of the final |SSL_write| call. +static int WriteAll(SSL *ssl, const uint8_t *in, size_t in_len) { + const TestConfig *config = GetTestConfig(ssl); + int ret; + do { + ret = SSL_write(ssl, in, in_len); + if (ret > 0) { + in += ret; + in_len -= ret; + } + } while ((config->async && RetryAsync(ssl, ret)) || (ret > 0 && in_len > 0)); + return ret; +} + +// DoShutdown calls |SSL_shutdown|, resolving any asynchronous operations. It +// returns the result of the final |SSL_shutdown| call. +static int DoShutdown(SSL *ssl) { + const TestConfig *config = GetTestConfig(ssl); + int ret; + do { + ret = SSL_shutdown(ssl); + } while (config->async && RetryAsync(ssl, ret)); + return ret; +} + +// CheckHandshakeProperties checks, immediately after |ssl| completes its +// initial handshake (or False Starts), whether all the properties are +// consistent with the test configuration and invariants. +static bool CheckHandshakeProperties(SSL *ssl, bool is_resume) { + const TestConfig *config = GetTestConfig(ssl); + + if (SSL_get_current_cipher(ssl) == nullptr) { + fprintf(stderr, "null cipher after handshake\n"); + return false; + } + + if (is_resume && + (!!SSL_session_reused(ssl) == config->expect_session_miss)) { + fprintf(stderr, "session was%s reused\n", + SSL_session_reused(ssl) ? "" : " not"); + return false; + } + + bool expect_handshake_done = is_resume || !config->false_start; + if (expect_handshake_done != GetTestState(ssl)->handshake_done) { + fprintf(stderr, "handshake was%s completed\n", + GetTestState(ssl)->handshake_done ? "" : " not"); + return false; + } + + if (expect_handshake_done && !config->is_server) { + bool expect_new_session = + !config->expect_no_session && + (!SSL_session_reused(ssl) || config->expect_ticket_renewal); + if (expect_new_session != GetTestState(ssl)->got_new_session) { + fprintf(stderr, + "new session was%s cached, but we expected the opposite\n", + GetTestState(ssl)->got_new_session ? "" : " not"); + return false; + } + } + + if (config->is_server && !GetTestState(ssl)->early_callback_called) { + fprintf(stderr, "early callback not called\n"); + return false; + } + + if (!config->expected_server_name.empty()) { + const char *server_name = + SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); + if (server_name != config->expected_server_name) { + fprintf(stderr, "servername mismatch (got %s; want %s)\n", + server_name, config->expected_server_name.c_str()); + return false; + } + } + + if (!config->expected_certificate_types.empty()) { + const uint8_t *certificate_types; + size_t certificate_types_len = + SSL_get0_certificate_types(ssl, &certificate_types); + if (certificate_types_len != config->expected_certificate_types.size() || + memcmp(certificate_types, + config->expected_certificate_types.data(), + certificate_types_len) != 0) { + fprintf(stderr, "certificate types mismatch\n"); + return false; + } + } + + if (!config->expected_next_proto.empty()) { + const uint8_t *next_proto; + unsigned next_proto_len; + SSL_get0_next_proto_negotiated(ssl, &next_proto, &next_proto_len); + if (next_proto_len != config->expected_next_proto.size() || + memcmp(next_proto, config->expected_next_proto.data(), + next_proto_len) != 0) { + fprintf(stderr, "negotiated next proto mismatch\n"); + return false; + } + } + + if (!config->expected_alpn.empty()) { + const uint8_t *alpn_proto; + unsigned alpn_proto_len; + SSL_get0_alpn_selected(ssl, &alpn_proto, &alpn_proto_len); + if (alpn_proto_len != config->expected_alpn.size() || + memcmp(alpn_proto, config->expected_alpn.data(), + alpn_proto_len) != 0) { + fprintf(stderr, "negotiated alpn proto mismatch\n"); + return false; + } + } + + if (!config->expected_channel_id.empty()) { + uint8_t channel_id[64]; + if (!SSL_get_tls_channel_id(ssl, channel_id, sizeof(channel_id))) { + fprintf(stderr, "no channel id negotiated\n"); + return false; + } + if (config->expected_channel_id.size() != 64 || + memcmp(config->expected_channel_id.data(), + channel_id, 64) != 0) { + fprintf(stderr, "channel id mismatch\n"); + return false; + } + } + + if (config->expect_extended_master_secret) { + if (!ssl->session->extended_master_secret) { + fprintf(stderr, "No EMS for session when expected"); + return false; + } + } + + if (!config->expected_ocsp_response.empty()) { + const uint8_t *data; + size_t len; + SSL_get0_ocsp_response(ssl, &data, &len); + if (config->expected_ocsp_response.size() != len || + memcmp(config->expected_ocsp_response.data(), data, len) != 0) { + fprintf(stderr, "OCSP response mismatch\n"); + return false; + } + } + + if (!config->expected_signed_cert_timestamps.empty()) { + const uint8_t *data; + size_t len; + SSL_get0_signed_cert_timestamp_list(ssl, &data, &len); + if (config->expected_signed_cert_timestamps.size() != len || + memcmp(config->expected_signed_cert_timestamps.data(), + data, len) != 0) { + fprintf(stderr, "SCT list mismatch\n"); + return false; + } + } + + if (config->expect_verify_result) { + int expected_verify_result = config->verify_fail ? + X509_V_ERR_APPLICATION_VERIFICATION : + X509_V_OK; + + if (SSL_get_verify_result(ssl) != expected_verify_result) { + fprintf(stderr, "Wrong certificate verification result\n"); + return false; + } + } + + if (config->expect_server_key_exchange_hash != 0 && + config->expect_server_key_exchange_hash != + SSL_get_server_key_exchange_hash(ssl)) { + fprintf(stderr, "ServerKeyExchange hash was %d, wanted %d.\n", + SSL_get_server_key_exchange_hash(ssl), + config->expect_server_key_exchange_hash); + return false; + } + + if (config->expect_key_exchange_info != 0) { + uint32_t info = SSL_SESSION_get_key_exchange_info(SSL_get_session(ssl)); + if (static_cast(config->expect_key_exchange_info) != info) { + fprintf(stderr, "key_exchange_info was %" PRIu32 ", wanted %" PRIu32 "\n", + info, static_cast(config->expect_key_exchange_info)); + return false; + } + } + + if (!config->is_server) { + /* Clients should expect a peer certificate chain iff this was not a PSK + * cipher suite. */ + if (config->psk.empty()) { + if (SSL_get_peer_cert_chain(ssl) == nullptr) { + fprintf(stderr, "Missing peer certificate chain!\n"); + return false; + } + } else if (SSL_get_peer_cert_chain(ssl) != nullptr) { + fprintf(stderr, "Unexpected peer certificate chain!\n"); + return false; + } + } + return true; +} + +// DoExchange runs a test SSL exchange against the peer. On success, it returns +// true and sets |*out_session| to the negotiated SSL session. If the test is a +// resumption attempt, |is_resume| is true and |session| is the session from the +// previous exchange. +static bool DoExchange(ScopedSSL_SESSION *out_session, SSL_CTX *ssl_ctx, + const TestConfig *config, bool is_resume, + SSL_SESSION *session) { + ScopedSSL ssl(SSL_new(ssl_ctx)); + if (!ssl) { + return false; + } + + if (!SetTestConfig(ssl.get(), config) || + !SetTestState(ssl.get(), std::unique_ptr(new TestState))) { + return false; + } + + if (config->fallback_scsv && + !SSL_set_mode(ssl.get(), SSL_MODE_SEND_FALLBACK_SCSV)) { + return false; + } + if (!config->use_early_callback && !config->use_old_client_cert_callback) { + if (config->async) { + SSL_set_cert_cb(ssl.get(), CertCallback, NULL); + } else if (!InstallCertificate(ssl.get())) { + return false; + } + } + if (config->require_any_client_certificate) { + SSL_set_verify(ssl.get(), SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, + NULL); + } + if (config->verify_peer) { + SSL_set_verify(ssl.get(), SSL_VERIFY_PEER, NULL); + } + if (config->false_start) { + SSL_set_mode(ssl.get(), SSL_MODE_ENABLE_FALSE_START); + } + if (config->cbc_record_splitting) { + SSL_set_mode(ssl.get(), SSL_MODE_CBC_RECORD_SPLITTING); + } + if (config->partial_write) { + SSL_set_mode(ssl.get(), SSL_MODE_ENABLE_PARTIAL_WRITE); + } + if (config->no_tls13) { + SSL_set_options(ssl.get(), SSL_OP_NO_TLSv1_3); + } + if (config->no_tls12) { + SSL_set_options(ssl.get(), SSL_OP_NO_TLSv1_2); + } + if (config->no_tls11) { + SSL_set_options(ssl.get(), SSL_OP_NO_TLSv1_1); + } + if (config->no_tls1) { + SSL_set_options(ssl.get(), SSL_OP_NO_TLSv1); + } + if (config->no_ssl3) { + SSL_set_options(ssl.get(), SSL_OP_NO_SSLv3); + } + if (!config->expected_channel_id.empty()) { + SSL_enable_tls_channel_id(ssl.get()); + } + if (!config->send_channel_id.empty()) { + SSL_enable_tls_channel_id(ssl.get()); + if (!config->async) { + // The async case will be supplied by |ChannelIdCallback|. + ScopedEVP_PKEY pkey = LoadPrivateKey(config->send_channel_id); + if (!pkey || !SSL_set1_tls_channel_id(ssl.get(), pkey.get())) { + return false; + } + } + } + if (!config->host_name.empty() && + !SSL_set_tlsext_host_name(ssl.get(), config->host_name.c_str())) { + return false; + } + if (!config->advertise_alpn.empty() && + SSL_set_alpn_protos(ssl.get(), + (const uint8_t *)config->advertise_alpn.data(), + config->advertise_alpn.size()) != 0) { + return false; + } + if (!config->psk.empty()) { + SSL_set_psk_client_callback(ssl.get(), PskClientCallback); + SSL_set_psk_server_callback(ssl.get(), PskServerCallback); + } + if (!config->psk_identity.empty() && + !SSL_use_psk_identity_hint(ssl.get(), config->psk_identity.c_str())) { + return false; + } + if (!config->srtp_profiles.empty() && + !SSL_set_srtp_profiles(ssl.get(), config->srtp_profiles.c_str())) { + return false; + } + if (config->enable_ocsp_stapling && + !SSL_enable_ocsp_stapling(ssl.get())) { + return false; + } + if (config->enable_signed_cert_timestamps && + !SSL_enable_signed_cert_timestamps(ssl.get())) { + return false; + } + if (config->min_version != 0) { + SSL_set_min_version(ssl.get(), (uint16_t)config->min_version); + } + if (config->max_version != 0) { + SSL_set_max_version(ssl.get(), (uint16_t)config->max_version); + } + if (config->mtu != 0) { + SSL_set_options(ssl.get(), SSL_OP_NO_QUERY_MTU); + SSL_set_mtu(ssl.get(), config->mtu); + } + if (config->install_ddos_callback) { + SSL_CTX_set_dos_protection_cb(ssl_ctx, DDoSCallback); + } + if (config->renegotiate_once) { + SSL_set_renegotiate_mode(ssl.get(), ssl_renegotiate_once); + } + if (config->renegotiate_freely) { + SSL_set_renegotiate_mode(ssl.get(), ssl_renegotiate_freely); + } + if (config->renegotiate_ignore) { + SSL_set_renegotiate_mode(ssl.get(), ssl_renegotiate_ignore); + } + if (!config->check_close_notify) { + SSL_set_quiet_shutdown(ssl.get(), 1); + } + if (config->disable_npn) { + SSL_set_options(ssl.get(), SSL_OP_DISABLE_NPN); + } + if (config->p384_only) { + int nid = NID_secp384r1; + if (!SSL_set1_curves(ssl.get(), &nid, 1)) { + return false; + } + } + if (config->enable_all_curves) { + static const int kAllCurves[] = { + NID_X9_62_prime256v1, NID_secp384r1, NID_secp521r1, NID_X25519, + }; + if (!SSL_set1_curves(ssl.get(), kAllCurves, + sizeof(kAllCurves) / sizeof(kAllCurves[0]))) { + return false; + } + } + if (config->initial_timeout_duration_ms > 0) { + DTLSv1_set_initial_timeout_duration(ssl.get(), + config->initial_timeout_duration_ms); + } + + int sock = Connect(config->port); + if (sock == -1) { + return false; + } + SocketCloser closer(sock); + + ScopedBIO bio(BIO_new_socket(sock, BIO_NOCLOSE)); + if (!bio) { + return false; + } + if (config->is_dtls) { + ScopedBIO packeted = PacketedBioCreate(!config->async); + if (!packeted) { + return false; + } + GetTestState(ssl.get())->packeted_bio = packeted.get(); + BIO_push(packeted.get(), bio.release()); + bio = std::move(packeted); + } + if (config->async) { + ScopedBIO async_scoped = + config->is_dtls ? AsyncBioCreateDatagram() : AsyncBioCreate(); + if (!async_scoped) { + return false; + } + BIO_push(async_scoped.get(), bio.release()); + GetTestState(ssl.get())->async_bio = async_scoped.get(); + bio = std::move(async_scoped); + } + SSL_set_bio(ssl.get(), bio.get(), bio.get()); + bio.release(); // SSL_set_bio takes ownership. + + if (session != NULL) { + if (!config->is_server) { + if (SSL_set_session(ssl.get(), session) != 1) { + return false; + } + } else if (config->async) { + // The internal session cache is disabled, so install the session + // manually. + GetTestState(ssl.get())->pending_session.reset( + SSL_SESSION_up_ref(session)); + } + } + + if (SSL_get_current_cipher(ssl.get()) != nullptr) { + fprintf(stderr, "non-null cipher before handshake\n"); + return false; + } + + int ret; + if (config->implicit_handshake) { + if (config->is_server) { + SSL_set_accept_state(ssl.get()); + } else { + SSL_set_connect_state(ssl.get()); + } + } else { + do { + if (config->is_server) { + ret = SSL_accept(ssl.get()); + } else { + ret = SSL_connect(ssl.get()); + } + } while (config->async && RetryAsync(ssl.get(), ret)); + if (ret != 1 || + !CheckHandshakeProperties(ssl.get(), is_resume)) { + return false; + } + + // Reset the state to assert later that the callback isn't called in + // renegotations. + GetTestState(ssl.get())->got_new_session = false; + } + + if (config->export_keying_material > 0) { + std::vector result( + static_cast(config->export_keying_material)); + if (!SSL_export_keying_material( + ssl.get(), result.data(), result.size(), + config->export_label.data(), config->export_label.size(), + reinterpret_cast(config->export_context.data()), + config->export_context.size(), config->use_export_context)) { + fprintf(stderr, "failed to export keying material\n"); + return false; + } + if (WriteAll(ssl.get(), result.data(), result.size()) < 0) { + return false; + } + } + + if (config->tls_unique) { + uint8_t tls_unique[16]; + size_t tls_unique_len; + if (!SSL_get_tls_unique(ssl.get(), tls_unique, &tls_unique_len, + sizeof(tls_unique))) { + fprintf(stderr, "failed to get tls-unique\n"); + return false; + } + + if (tls_unique_len != 12) { + fprintf(stderr, "expected 12 bytes of tls-unique but got %u", + static_cast(tls_unique_len)); + return false; + } + + if (WriteAll(ssl.get(), tls_unique, tls_unique_len) < 0) { + return false; + } + } + + if (config->write_different_record_sizes) { + if (config->is_dtls) { + fprintf(stderr, "write_different_record_sizes not supported for DTLS\n"); + return false; + } + // This mode writes a number of different record sizes in an attempt to + // trip up the CBC record splitting code. + static const size_t kBufLen = 32769; + std::unique_ptr buf(new uint8_t[kBufLen]); + memset(buf.get(), 0x42, kBufLen); + static const size_t kRecordSizes[] = { + 0, 1, 255, 256, 257, 16383, 16384, 16385, 32767, 32768, 32769}; + for (size_t i = 0; i < sizeof(kRecordSizes) / sizeof(kRecordSizes[0]); + i++) { + const size_t len = kRecordSizes[i]; + if (len > kBufLen) { + fprintf(stderr, "Bad kRecordSizes value.\n"); + return false; + } + if (WriteAll(ssl.get(), buf.get(), len) < 0) { + return false; + } + } + } else { + if (config->shim_writes_first) { + if (WriteAll(ssl.get(), reinterpret_cast("hello"), + 5) < 0) { + return false; + } + } + if (!config->shim_shuts_down) { + for (;;) { + static const size_t kBufLen = 16384; + std::unique_ptr buf(new uint8_t[kBufLen]); + + // Read only 512 bytes at a time in TLS to ensure records may be + // returned in multiple reads. + int n = DoRead(ssl.get(), buf.get(), config->is_dtls ? kBufLen : 512); + int err = SSL_get_error(ssl.get(), n); + if (err == SSL_ERROR_ZERO_RETURN || + (n == 0 && err == SSL_ERROR_SYSCALL)) { + if (n != 0) { + fprintf(stderr, "Invalid SSL_get_error output\n"); + return false; + } + // Stop on either clean or unclean shutdown. + break; + } else if (err != SSL_ERROR_NONE) { + if (n > 0) { + fprintf(stderr, "Invalid SSL_get_error output\n"); + return false; + } + return false; + } + // Successfully read data. + if (n <= 0) { + fprintf(stderr, "Invalid SSL_get_error output\n"); + return false; + } + + // After a successful read, with or without False Start, the handshake + // must be complete. + if (!GetTestState(ssl.get())->handshake_done) { + fprintf(stderr, "handshake was not completed after SSL_read\n"); + return false; + } + + for (int i = 0; i < n; i++) { + buf[i] ^= 0xff; + } + if (WriteAll(ssl.get(), buf.get(), n) < 0) { + return false; + } + } + } + } + + if (!config->is_server && !config->false_start && + !config->implicit_handshake && + GetTestState(ssl.get())->got_new_session) { + fprintf(stderr, "new session was established after the handshake\n"); + return false; + } + + if (out_session) { + out_session->reset(SSL_get1_session(ssl.get())); + } + + ret = DoShutdown(ssl.get()); + + if (config->shim_shuts_down && config->check_close_notify) { + // We initiate shutdown, so |SSL_shutdown| will return in two stages. First + // it returns zero when our close_notify is sent, then one when the peer's + // is received. + if (ret != 0) { + fprintf(stderr, "Unexpected SSL_shutdown result: %d != 0\n", ret); + return false; + } + ret = DoShutdown(ssl.get()); + } + + if (ret != 1) { + fprintf(stderr, "Unexpected SSL_shutdown result: %d != 1\n", ret); + return false; + } + + if (SSL_total_renegotiations(ssl.get()) != + config->expect_total_renegotiations) { + fprintf(stderr, "Expected %d renegotiations, got %d\n", + config->expect_total_renegotiations, + SSL_total_renegotiations(ssl.get())); + return false; + } + + return true; +} + +class StderrDelimiter { + public: + ~StderrDelimiter() { fprintf(stderr, "--- DONE ---\n"); } +}; + +int main(int argc, char **argv) { + // To distinguish ASan's output from ours, add a trailing message to stderr. + // Anything following this line will be considered an error. + StderrDelimiter delimiter; + +#if defined(OPENSSL_WINDOWS) + /* Initialize Winsock. */ + WORD wsa_version = MAKEWORD(2, 2); + WSADATA wsa_data; + int wsa_err = WSAStartup(wsa_version, &wsa_data); + if (wsa_err != 0) { + fprintf(stderr, "WSAStartup failed: %d\n", wsa_err); + return 1; + } + if (wsa_data.wVersion != wsa_version) { + fprintf(stderr, "Didn't get expected version: %x\n", wsa_data.wVersion); + return 1; + } +#else + signal(SIGPIPE, SIG_IGN); +#endif + + CRYPTO_library_init(); + g_config_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL); + g_state_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, TestStateExFree); + if (g_config_index < 0 || g_state_index < 0) { + return 1; + } + + TestConfig config; + if (!ParseConfig(argc - 1, argv + 1, &config)) { + return Usage(argv[0]); + } + + ScopedSSL_CTX ssl_ctx = SetupCtx(&config); + if (!ssl_ctx) { + ERR_print_errors_fp(stderr); + return 1; + } + + ScopedSSL_SESSION session; + if (!DoExchange(&session, ssl_ctx.get(), &config, false /* is_resume */, + NULL /* session */)) { + ERR_print_errors_fp(stderr); + return 1; + } + + if (config.resume && + !DoExchange(NULL, ssl_ctx.get(), &config, true /* is_resume */, + session.get())) { + ERR_print_errors_fp(stderr); + return 1; + } + + return 0; +} diff --git a/external/boringssl/ssl/test/packeted_bio.cc b/external/boringssl/ssl/test/packeted_bio.cc new file mode 100644 index 0000000000..b0982b0742 --- /dev/null +++ b/external/boringssl/ssl/test/packeted_bio.cc @@ -0,0 +1,304 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include "packeted_bio.h" + +#include +#include +#include +#include + +#include + + +namespace { + +extern const BIO_METHOD g_packeted_bio_method; + +const uint8_t kOpcodePacket = 'P'; +const uint8_t kOpcodeTimeout = 'T'; +const uint8_t kOpcodeTimeoutAck = 't'; + +struct PacketedBio { + explicit PacketedBio(bool advance_clock_arg) + : advance_clock(advance_clock_arg) { + memset(&timeout, 0, sizeof(timeout)); + memset(&clock, 0, sizeof(clock)); + memset(&read_deadline, 0, sizeof(read_deadline)); + } + + bool HasTimeout() const { + return timeout.tv_sec != 0 || timeout.tv_usec != 0; + } + + bool CanRead() const { + if (read_deadline.tv_sec == 0 && read_deadline.tv_usec == 0) { + return true; + } + + if (clock.tv_sec == read_deadline.tv_sec) { + return clock.tv_usec < read_deadline.tv_usec; + } + return clock.tv_sec < read_deadline.tv_sec; + } + + timeval timeout; + timeval clock; + timeval read_deadline; + bool advance_clock; +}; + +PacketedBio *GetData(BIO *bio) { + if (bio->method != &g_packeted_bio_method) { + return NULL; + } + return (PacketedBio *)bio->ptr; +} + +const PacketedBio *GetData(const BIO *bio) { + return GetData(const_cast(bio)); +} + +// ReadAll reads |len| bytes from |bio| into |out|. It returns 1 on success and +// 0 or -1 on error. +static int ReadAll(BIO *bio, uint8_t *out, size_t len) { + while (len > 0) { + int chunk_len = INT_MAX; + if (len <= INT_MAX) { + chunk_len = (int)len; + } + int ret = BIO_read(bio, out, chunk_len); + if (ret <= 0) { + return ret; + } + out += ret; + len -= ret; + } + return 1; +} + +static int PacketedWrite(BIO *bio, const char *in, int inl) { + if (bio->next_bio == NULL) { + return 0; + } + + BIO_clear_retry_flags(bio); + + // Write the header. + uint8_t header[5]; + header[0] = kOpcodePacket; + header[1] = (inl >> 24) & 0xff; + header[2] = (inl >> 16) & 0xff; + header[3] = (inl >> 8) & 0xff; + header[4] = inl & 0xff; + int ret = BIO_write(bio->next_bio, header, sizeof(header)); + if (ret <= 0) { + BIO_copy_next_retry(bio); + return ret; + } + + // Write the buffer. + ret = BIO_write(bio->next_bio, in, inl); + if (ret < 0 || (inl > 0 && ret == 0)) { + BIO_copy_next_retry(bio); + return ret; + } + assert(ret == inl); + return ret; +} + +static int PacketedRead(BIO *bio, char *out, int outl) { + PacketedBio *data = GetData(bio); + if (bio->next_bio == NULL) { + return 0; + } + + BIO_clear_retry_flags(bio); + + for (;;) { + // Check if the read deadline has passed. + if (!data->CanRead()) { + BIO_set_retry_read(bio); + return -1; + } + + // Read the opcode. + uint8_t opcode; + int ret = ReadAll(bio->next_bio, &opcode, sizeof(opcode)); + if (ret <= 0) { + BIO_copy_next_retry(bio); + return ret; + } + + if (opcode == kOpcodeTimeout) { + // The caller is required to advance any pending timeouts before + // continuing. + if (data->HasTimeout()) { + fprintf(stderr, "Unprocessed timeout!\n"); + return -1; + } + + // Process the timeout. + uint8_t buf[8]; + ret = ReadAll(bio->next_bio, buf, sizeof(buf)); + if (ret <= 0) { + BIO_copy_next_retry(bio); + return ret; + } + uint64_t timeout = (static_cast(buf[0]) << 56) | + (static_cast(buf[1]) << 48) | + (static_cast(buf[2]) << 40) | + (static_cast(buf[3]) << 32) | + (static_cast(buf[4]) << 24) | + (static_cast(buf[5]) << 16) | + (static_cast(buf[6]) << 8) | + static_cast(buf[7]); + timeout /= 1000; // Convert nanoseconds to microseconds. + + data->timeout.tv_usec = timeout % 1000000; + data->timeout.tv_sec = timeout / 1000000; + + // Send an ACK to the peer. + ret = BIO_write(bio->next_bio, &kOpcodeTimeoutAck, 1); + if (ret <= 0) { + return ret; + } + assert(ret == 1); + + if (!data->advance_clock) { + // Signal to the caller to retry the read, after advancing the clock. + BIO_set_retry_read(bio); + return -1; + } + + PacketedBioAdvanceClock(bio); + continue; + } + + if (opcode != kOpcodePacket) { + fprintf(stderr, "Unknown opcode, %u\n", opcode); + return -1; + } + + // Read the length prefix. + uint8_t len_bytes[4]; + ret = ReadAll(bio->next_bio, len_bytes, sizeof(len_bytes)); + if (ret <= 0) { + BIO_copy_next_retry(bio); + return ret; + } + + uint32_t len = (len_bytes[0] << 24) | (len_bytes[1] << 16) | + (len_bytes[2] << 8) | len_bytes[3]; + uint8_t *buf = (uint8_t *)OPENSSL_malloc(len); + if (buf == NULL) { + return -1; + } + ret = ReadAll(bio->next_bio, buf, len); + if (ret <= 0) { + fprintf(stderr, "Packeted BIO was truncated\n"); + return -1; + } + + if (outl > (int)len) { + outl = len; + } + memcpy(out, buf, outl); + OPENSSL_free(buf); + return outl; + } +} + +static long PacketedCtrl(BIO *bio, int cmd, long num, void *ptr) { + if (cmd == BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT) { + memcpy(&GetData(bio)->read_deadline, ptr, sizeof(timeval)); + return 1; + } + + if (bio->next_bio == NULL) { + return 0; + } + BIO_clear_retry_flags(bio); + int ret = BIO_ctrl(bio->next_bio, cmd, num, ptr); + BIO_copy_next_retry(bio); + return ret; +} + +static int PacketedNew(BIO *bio) { + bio->init = 1; + return 1; +} + +static int PacketedFree(BIO *bio) { + if (bio == NULL) { + return 0; + } + + delete GetData(bio); + bio->init = 0; + return 1; +} + +static long PacketedCallbackCtrl(BIO *bio, int cmd, bio_info_cb fp) { + if (bio->next_bio == NULL) { + return 0; + } + return BIO_callback_ctrl(bio->next_bio, cmd, fp); +} + +const BIO_METHOD g_packeted_bio_method = { + BIO_TYPE_FILTER, + "packeted bio", + PacketedWrite, + PacketedRead, + NULL /* puts */, + NULL /* gets */, + PacketedCtrl, + PacketedNew, + PacketedFree, + PacketedCallbackCtrl, +}; + +} // namespace + +ScopedBIO PacketedBioCreate(bool advance_clock) { + ScopedBIO bio(BIO_new(&g_packeted_bio_method)); + if (!bio) { + return nullptr; + } + bio->ptr = new PacketedBio(advance_clock); + return bio; +} + +timeval PacketedBioGetClock(const BIO *bio) { + return GetData(bio)->clock; +} + +bool PacketedBioAdvanceClock(BIO *bio) { + PacketedBio *data = GetData(bio); + if (data == nullptr) { + return false; + } + + if (!data->HasTimeout()) { + return false; + } + + data->clock.tv_usec += data->timeout.tv_usec; + data->clock.tv_sec += data->clock.tv_usec / 1000000; + data->clock.tv_usec %= 1000000; + data->clock.tv_sec += data->timeout.tv_sec; + memset(&data->timeout, 0, sizeof(data->timeout)); + return true; +} diff --git a/external/boringssl/ssl/test/packeted_bio.h b/external/boringssl/ssl/test/packeted_bio.h new file mode 100644 index 0000000000..9bab635a07 --- /dev/null +++ b/external/boringssl/ssl/test/packeted_bio.h @@ -0,0 +1,51 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef HEADER_PACKETED_BIO +#define HEADER_PACKETED_BIO + +#include +#include + +#include "../../crypto/test/scoped_types.h" + +#if defined(OPENSSL_WINDOWS) +OPENSSL_MSVC_PRAGMA(warning(push, 3)) +#include +OPENSSL_MSVC_PRAGMA(warning(pop)) +#else +#include +#endif + + +// PacketedBioCreate creates a filter BIO which implements a reliable in-order +// blocking datagram socket. It internally maintains a clock and honors +// |BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT| based on it. +// +// During a |BIO_read|, the peer may signal the filter BIO to simulate a +// timeout. If |advance_clock| is true, it automatically advances the clock and +// continues reading, subject to the read deadline. Otherwise, it fails +// immediately. The caller must then call |PacketedBioAdvanceClock| before +// retrying |BIO_read|. +ScopedBIO PacketedBioCreate(bool advance_clock); + +// PacketedBioGetClock returns the current time for |bio|. +timeval PacketedBioGetClock(const BIO *bio); + +// PacketedBioAdvanceClock advances |bio|'s internal clock and returns true if +// there is a pending timeout. Otherwise, it returns false. +bool PacketedBioAdvanceClock(BIO *bio); + + +#endif // HEADER_PACKETED_BIO diff --git a/external/boringssl/ssl/test/runner/alert.go b/external/boringssl/ssl/test/runner/alert.go new file mode 100644 index 0000000000..7db682672b --- /dev/null +++ b/external/boringssl/ssl/test/runner/alert.go @@ -0,0 +1,78 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package runner + +import "strconv" + +type alert uint8 + +const ( + // alert level + alertLevelWarning = 1 + alertLevelError = 2 +) + +const ( + alertCloseNotify alert = 0 + alertUnexpectedMessage alert = 10 + alertBadRecordMAC alert = 20 + alertDecryptionFailed alert = 21 + alertRecordOverflow alert = 22 + alertDecompressionFailure alert = 30 + alertHandshakeFailure alert = 40 + alertNoCertficate alert = 41 + alertBadCertificate alert = 42 + alertUnsupportedCertificate alert = 43 + alertCertificateRevoked alert = 44 + alertCertificateExpired alert = 45 + alertCertificateUnknown alert = 46 + alertIllegalParameter alert = 47 + alertUnknownCA alert = 48 + alertAccessDenied alert = 49 + alertDecodeError alert = 50 + alertDecryptError alert = 51 + alertProtocolVersion alert = 70 + alertInsufficientSecurity alert = 71 + alertInternalError alert = 80 + alertUserCanceled alert = 90 + alertNoRenegotiation alert = 100 +) + +var alertText = map[alert]string{ + alertCloseNotify: "close notify", + alertUnexpectedMessage: "unexpected message", + alertBadRecordMAC: "bad record MAC", + alertDecryptionFailed: "decryption failed", + alertRecordOverflow: "record overflow", + alertDecompressionFailure: "decompression failure", + alertHandshakeFailure: "handshake failure", + alertBadCertificate: "bad certificate", + alertUnsupportedCertificate: "unsupported certificate", + alertCertificateRevoked: "revoked certificate", + alertCertificateExpired: "expired certificate", + alertCertificateUnknown: "unknown certificate", + alertIllegalParameter: "illegal parameter", + alertUnknownCA: "unknown certificate authority", + alertAccessDenied: "access denied", + alertDecodeError: "error decoding message", + alertDecryptError: "error decrypting message", + alertProtocolVersion: "protocol version not supported", + alertInsufficientSecurity: "insufficient security level", + alertInternalError: "internal error", + alertUserCanceled: "user canceled", + alertNoRenegotiation: "no renegotiation", +} + +func (e alert) String() string { + s, ok := alertText[e] + if ok { + return s + } + return "alert(" + strconv.Itoa(int(e)) + ")" +} + +func (e alert) Error() string { + return e.String() +} diff --git a/external/boringssl/ssl/test/runner/cert.pem b/external/boringssl/ssl/test/runner/cert.pem new file mode 100644 index 0000000000..4de4f49a34 --- /dev/null +++ b/external/boringssl/ssl/test/runner/cert.pem @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICWDCCAcGgAwIBAgIJAPuwTC6rEJsMMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV +BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX +aWRnaXRzIFB0eSBMdGQwHhcNMTQwNDIzMjA1MDQwWhcNMTcwNDIyMjA1MDQwWjBF +MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50 +ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB +gQDYK8imMuRi/03z0K1Zi0WnvfFHvwlYeyK9Na6XJYaUoIDAtB92kWdGMdAQhLci +HnAjkXLI6W15OoV3gA/ElRZ1xUpxTMhjP6PyY5wqT5r6y8FxbiiFKKAnHmUcrgfV +W28tQ+0rkLGMryRtrukXOgXBv7gcrmU7G1jC2a7WqmeI8QIDAQABo1AwTjAdBgNV +HQ4EFgQUi3XVrMsIvg4fZbf6Vr5sp3Xaha8wHwYDVR0jBBgwFoAUi3XVrMsIvg4f +Zbf6Vr5sp3Xaha8wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQA76Hht +ldY9avcTGSwbwoiuIqv0jTL1fHFnzy3RHMLDh+Lpvolc5DSrSJHCP5WuK0eeJXhr +T5oQpHL9z/cCDLAKCKRa4uV0fhEdOWBqyR9p8y5jJtye72t6CuFUV5iqcpF4BH4f +j2VNHwsSrJwkD4QUGlUtH7vwnQmyCFxZMmWAJg== +-----END CERTIFICATE----- diff --git a/external/boringssl/ssl/test/runner/chacha20_poly1305.go b/external/boringssl/ssl/test/runner/chacha20_poly1305.go new file mode 100644 index 0000000000..8b97545920 --- /dev/null +++ b/external/boringssl/ssl/test/runner/chacha20_poly1305.go @@ -0,0 +1,235 @@ +// Copyright (c) 2016, Google Inc. +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +package runner + +import ( + "crypto/cipher" + "crypto/subtle" + "encoding/binary" + "errors" + + "./poly1305" +) + +// See RFC 7539. + +func leftRotate(a uint32, n uint) uint32 { + return (a << n) | (a >> (32 - n)) +} + +func chaChaQuarterRound(state *[16]uint32, a, b, c, d int) { + state[a] += state[b] + state[d] = leftRotate(state[d]^state[a], 16) + + state[c] += state[d] + state[b] = leftRotate(state[b]^state[c], 12) + + state[a] += state[b] + state[d] = leftRotate(state[d]^state[a], 8) + + state[c] += state[d] + state[b] = leftRotate(state[b]^state[c], 7) +} + +func chaCha20Block(state *[16]uint32, out []byte) { + var workingState [16]uint32 + copy(workingState[:], state[:]) + for i := 0; i < 10; i++ { + chaChaQuarterRound(&workingState, 0, 4, 8, 12) + chaChaQuarterRound(&workingState, 1, 5, 9, 13) + chaChaQuarterRound(&workingState, 2, 6, 10, 14) + chaChaQuarterRound(&workingState, 3, 7, 11, 15) + chaChaQuarterRound(&workingState, 0, 5, 10, 15) + chaChaQuarterRound(&workingState, 1, 6, 11, 12) + chaChaQuarterRound(&workingState, 2, 7, 8, 13) + chaChaQuarterRound(&workingState, 3, 4, 9, 14) + } + for i := 0; i < 16; i++ { + binary.LittleEndian.PutUint32(out[i*4:i*4+4], workingState[i]+state[i]) + } +} + +// sliceForAppend takes a slice and a requested number of bytes. It returns a +// slice with the contents of the given slice followed by that many bytes and a +// second slice that aliases into it and contains only the extra bytes. If the +// original slice has sufficient capacity then no allocation is performed. +func sliceForAppend(in []byte, n int) (head, tail []byte) { + if total := len(in) + n; cap(in) >= total { + head = in[:total] + } else { + head = make([]byte, total) + copy(head, in) + } + tail = head[len(in):] + return +} + +func chaCha20(out, in, key, nonce []byte, counter uint64) { + var state [16]uint32 + state[0] = 0x61707865 + state[1] = 0x3320646e + state[2] = 0x79622d32 + state[3] = 0x6b206574 + for i := 0; i < 8; i++ { + state[4+i] = binary.LittleEndian.Uint32(key[i*4 : i*4+4]) + } + + switch len(nonce) { + case 8: + state[14] = binary.LittleEndian.Uint32(nonce[0:4]) + state[15] = binary.LittleEndian.Uint32(nonce[4:8]) + case 12: + state[13] = binary.LittleEndian.Uint32(nonce[0:4]) + state[14] = binary.LittleEndian.Uint32(nonce[4:8]) + state[15] = binary.LittleEndian.Uint32(nonce[8:12]) + default: + panic("bad nonce length") + } + + for i := 0; i < len(in); i += 64 { + state[12] = uint32(counter) + + var tmp [64]byte + chaCha20Block(&state, tmp[:]) + count := 64 + if len(in)-i < count { + count = len(in) - i + } + for j := 0; j < count; j++ { + out[i+j] = in[i+j] ^ tmp[j] + } + + counter++ + } +} + +// chaCha20Poly1305 implements the AEAD from +// RFC 7539 and draft-agl-tls-chacha20poly1305-04. +type chaCha20Poly1305 struct { + key [32]byte + // oldMode, if true, indicates that the draft spec should be + // implemented rather than the final, RFC version. + oldMode bool +} + +func newChaCha20Poly1305(key []byte) (cipher.AEAD, error) { + if len(key) != 32 { + return nil, errors.New("bad key length") + } + aead := new(chaCha20Poly1305) + copy(aead.key[:], key) + return aead, nil +} + +func newChaCha20Poly1305Old(key []byte) (cipher.AEAD, error) { + if len(key) != 32 { + return nil, errors.New("bad key length") + } + aead := &chaCha20Poly1305{ + oldMode: true, + } + copy(aead.key[:], key) + return aead, nil +} + +func (c *chaCha20Poly1305) NonceSize() int { + if c.oldMode { + return 8 + } else { + return 12 + } +} + +func (c *chaCha20Poly1305) Overhead() int { return 16 } + +func (c *chaCha20Poly1305) poly1305(tag *[16]byte, nonce, ciphertext, additionalData []byte) { + input := make([]byte, 0, len(additionalData)+15+len(ciphertext)+15+8+8) + input = append(input, additionalData...) + var zeros [15]byte + if pad := len(input) % 16; pad != 0 { + input = append(input, zeros[:16-pad]...) + } + input = append(input, ciphertext...) + if pad := len(input) % 16; pad != 0 { + input = append(input, zeros[:16-pad]...) + } + input, out := sliceForAppend(input, 8) + binary.LittleEndian.PutUint64(out, uint64(len(additionalData))) + input, out = sliceForAppend(input, 8) + binary.LittleEndian.PutUint64(out, uint64(len(ciphertext))) + + var poly1305Key [32]byte + chaCha20(poly1305Key[:], poly1305Key[:], c.key[:], nonce, 0) + + poly1305.Sum(tag, input, &poly1305Key) +} + +func (c *chaCha20Poly1305) poly1305Old(tag *[16]byte, nonce, ciphertext, additionalData []byte) { + input := make([]byte, 0, len(additionalData)+8+len(ciphertext)+8) + input = append(input, additionalData...) + input, out := sliceForAppend(input, 8) + binary.LittleEndian.PutUint64(out, uint64(len(additionalData))) + input = append(input, ciphertext...) + input, out = sliceForAppend(input, 8) + binary.LittleEndian.PutUint64(out, uint64(len(ciphertext))) + + var poly1305Key [32]byte + chaCha20(poly1305Key[:], poly1305Key[:], c.key[:], nonce, 0) + + poly1305.Sum(tag, input, &poly1305Key) +} + +func (c *chaCha20Poly1305) Seal(dst, nonce, plaintext, additionalData []byte) []byte { + if len(nonce) != c.NonceSize() { + panic("Bad nonce length") + } + + ret, out := sliceForAppend(dst, len(plaintext)+16) + chaCha20(out[:len(plaintext)], plaintext, c.key[:], nonce, 1) + + var tag [16]byte + if c.oldMode { + c.poly1305Old(&tag, nonce, out[:len(plaintext)], additionalData) + } else { + c.poly1305(&tag, nonce, out[:len(plaintext)], additionalData) + } + copy(out[len(plaintext):], tag[:]) + + return ret +} + +func (c *chaCha20Poly1305) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) { + if len(nonce) != c.NonceSize() { + panic("Bad nonce length") + } + if len(ciphertext) < 16 { + return nil, errors.New("chacha20: message authentication failed") + } + plaintextLen := len(ciphertext) - 16 + + var tag [16]byte + if c.oldMode { + c.poly1305Old(&tag, nonce, ciphertext[:plaintextLen], additionalData) + } else { + c.poly1305(&tag, nonce, ciphertext[:plaintextLen], additionalData) + } + if subtle.ConstantTimeCompare(tag[:], ciphertext[plaintextLen:]) != 1 { + return nil, errors.New("chacha20: message authentication failed") + } + + ret, out := sliceForAppend(dst, plaintextLen) + chaCha20(out, ciphertext[:plaintextLen], c.key[:], nonce, 1) + return ret, nil +} diff --git a/external/boringssl/ssl/test/runner/chacha20_poly1305_test.go b/external/boringssl/ssl/test/runner/chacha20_poly1305_test.go new file mode 100644 index 0000000000..8cecb5c84e --- /dev/null +++ b/external/boringssl/ssl/test/runner/chacha20_poly1305_test.go @@ -0,0 +1,176 @@ +// Copyright (c) 2016, Google Inc. +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +package runner + +import ( + "bytes" + "encoding/hex" + "testing" +) + +// See RFC 7539, section 2.1.1. +func TestChaChaQuarterRound(t *testing.T) { + state := [16]uint32{0x11111111, 0x01020304, 0x9b8d6f43, 0x01234567} + chaChaQuarterRound(&state, 0, 1, 2, 3) + + a, b, c, d := state[0], state[1], state[2], state[3] + if a != 0xea2a92f4 || b != 0xcb1cf8ce || c != 0x4581472e || d != 0x5881c4bb { + t.Errorf("Incorrect results: %x", state) + } +} + +// See RFC 7539, section 2.2.1. +func TestChaChaQuarterRoundState(t *testing.T) { + state := [16]uint32{ + 0x879531e0, 0xc5ecf37d, 0x516461b1, 0xc9a62f8a, + 0x44c20ef3, 0x3390af7f, 0xd9fc690b, 0x2a5f714c, + 0x53372767, 0xb00a5631, 0x974c541a, 0x359e9963, + 0x5c971061, 0x3d631689, 0x2098d9d6, 0x91dbd320, + } + chaChaQuarterRound(&state, 2, 7, 8, 13) + + expected := [16]uint32{ + 0x879531e0, 0xc5ecf37d, 0xbdb886dc, 0xc9a62f8a, + 0x44c20ef3, 0x3390af7f, 0xd9fc690b, 0xcfacafd2, + 0xe46bea80, 0xb00a5631, 0x974c541a, 0x359e9963, + 0x5c971061, 0xccc07c79, 0x2098d9d6, 0x91dbd320, + } + for i := range state { + if state[i] != expected[i] { + t.Errorf("Mismatch at %d: %x vs %x", i, state, expected) + } + } +} + +// See RFC 7539, section 2.3.2. +func TestChaCha20Block(t *testing.T) { + state := [16]uint32{ + 0x61707865, 0x3320646e, 0x79622d32, 0x6b206574, + 0x03020100, 0x07060504, 0x0b0a0908, 0x0f0e0d0c, + 0x13121110, 0x17161514, 0x1b1a1918, 0x1f1e1d1c, + 0x00000001, 0x09000000, 0x4a000000, 0x00000000, + } + out := make([]byte, 64) + chaCha20Block(&state, out) + + expected := []byte{ + 0x10, 0xf1, 0xe7, 0xe4, 0xd1, 0x3b, 0x59, 0x15, + 0x50, 0x0f, 0xdd, 0x1f, 0xa3, 0x20, 0x71, 0xc4, + 0xc7, 0xd1, 0xf4, 0xc7, 0x33, 0xc0, 0x68, 0x03, + 0x04, 0x22, 0xaa, 0x9a, 0xc3, 0xd4, 0x6c, 0x4e, + 0xd2, 0x82, 0x64, 0x46, 0x07, 0x9f, 0xaa, 0x09, + 0x14, 0xc2, 0xd7, 0x05, 0xd9, 0x8b, 0x02, 0xa2, + 0xb5, 0x12, 0x9c, 0xd1, 0xde, 0x16, 0x4e, 0xb9, + 0xcb, 0xd0, 0x83, 0xe8, 0xa2, 0x50, 0x3c, 0x4e, + } + if !bytes.Equal(out, expected) { + t.Errorf("Got %x, wanted %x", out, expected) + } +} + +func decodeHexOrPanic(in string) []byte { + out, err := hex.DecodeString(in) + if err != nil { + panic(err) + } + return out +} + +// See draft-agl-tls-chacha20poly1305-04, section 7. +func TestChaCha20Poly1305Old(t *testing.T) { + key := decodeHexOrPanic("4290bcb154173531f314af57f3be3b5006da371ece272afa1b5dbdd1100a1007") + input := decodeHexOrPanic("86d09974840bded2a5ca") + nonce := decodeHexOrPanic("cd7cf67be39c794a") + ad := decodeHexOrPanic("87e229d4500845a079c0") + output := decodeHexOrPanic("e3e446f7ede9a19b62a4677dabf4e3d24b876bb284753896e1d6") + + aead, err := newChaCha20Poly1305Old(key) + if err != nil { + t.Fatal(err) + } + + out, err := aead.Open(nil, nonce, output, ad) + if err != nil { + t.Errorf("Open failed: %s", err) + } else if !bytes.Equal(out, input) { + t.Errorf("Open gave %x, wanted %x", out, input) + } + + out = aead.Seal(nil, nonce, input, ad) + if !bytes.Equal(out, output) { + t.Errorf("Open gave %x, wanted %x", out, output) + } + + out[0]++ + _, err = aead.Open(nil, nonce, out, ad) + if err == nil { + t.Errorf("Open on malformed data unexpectedly succeeded") + } +} + +var chaCha20Poly1305TestVectors = []struct { + key, input, nonce, ad, output string +}{ + { + // See RFC 7539, section 2.8.2. + key: "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", + input: "4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393a204966204920636f756c64206f6666657220796f75206f6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73637265656e20776f756c642062652069742e", + nonce: "070000004041424344454647", + ad: "50515253c0c1c2c3c4c5c6c7", + output: "d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d63dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b3692ddbd7f2d778b8c9803aee328091b58fab324e4fad675945585808b4831d7bc3ff4def08e4b7a9de576d26586cec64b61161ae10b594f09e26a7e902ecbd0600691", + }, + { + // See RFC 7539, section A.5. + key: "1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0", + input: "496e7465726e65742d4472616674732061726520647261667420646f63756d656e74732076616c696420666f722061206d6178696d756d206f6620736978206d6f6e74687320616e64206d617920626520757064617465642c207265706c616365642c206f72206f62736f6c65746564206279206f7468657220646f63756d656e747320617420616e792074696d652e20497420697320696e617070726f70726961746520746f2075736520496e7465726e65742d447261667473206173207265666572656e6365206d6174657269616c206f7220746f2063697465207468656d206f74686572207468616e206173202fe2809c776f726b20696e2070726f67726573732e2fe2809d", + nonce: "000000000102030405060708", + ad: "f33388860000000000004e91", + output: "64a0861575861af460f062c79be643bd5e805cfd345cf389f108670ac76c8cb24c6cfc18755d43eea09ee94e382d26b0bdb7b73c321b0100d4f03b7f355894cf332f830e710b97ce98c8a84abd0b948114ad176e008d33bd60f982b1ff37c8559797a06ef4f0ef61c186324e2b3506383606907b6a7c02b0f9f6157b53c867e4b9166c767b804d46a59b5216cde7a4e99040c5a40433225ee282a1b0a06c523eaf4534d7f83fa1155b0047718cbc546a0d072b04b3564eea1b422273f548271a0bb2316053fa76991955ebd63159434ecebb4e466dae5a1073a6727627097a1049e617d91d361094fa68f0ff77987130305beaba2eda04df997b714d6c6f2c29a6ad5cb4022b02709beead9d67890cbb22392336fea1851f38", + }, +} + +// See draft-agl-tls-chacha20poly1305-04, section 7. +func TestChaCha20Poly1305(t *testing.T) { + for i, tt := range chaCha20Poly1305TestVectors { + key := decodeHexOrPanic(tt.key) + input := decodeHexOrPanic(tt.input) + nonce := decodeHexOrPanic(tt.nonce) + ad := decodeHexOrPanic(tt.ad) + output := decodeHexOrPanic(tt.output) + + aead, err := newChaCha20Poly1305(key) + if err != nil { + t.Fatal(err) + } + + out, err := aead.Open(nil, nonce, output, ad) + if err != nil { + t.Errorf("%d. Open failed: %s", i, err) + } else if !bytes.Equal(out, input) { + t.Errorf("%d. Open gave %x, wanted %x", i, out, input) + } + + out = aead.Seal(nil, nonce, input, ad) + if !bytes.Equal(out, output) { + t.Errorf("%d. Open gave %x, wanted %x", i, out, output) + } + + out[0]++ + _, err = aead.Open(nil, nonce, out, ad) + if err == nil { + t.Errorf("%d. Open on malformed data unexpectedly succeeded", i) + } + } +} diff --git a/external/boringssl/ssl/test/runner/channel_id_key.pem b/external/boringssl/ssl/test/runner/channel_id_key.pem new file mode 100644 index 0000000000..604752bcda --- /dev/null +++ b/external/boringssl/ssl/test/runner/channel_id_key.pem @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIPwxu50c7LEhVNRYJFRWBUnoaz7JSos96T5hBp4rjyptoAoGCCqGSM49 +AwEHoUQDQgAEzFSVTE5guxJRQ0VbZ8dicPs5e/DT7xpW7Yc9hq0VOchv7cbXuI/T +CwadDjGWX/oaz0ftFqrVmfkwZu+C58ioWg== +-----END EC PRIVATE KEY----- diff --git a/external/boringssl/ssl/test/runner/cipher_suites.go b/external/boringssl/ssl/test/runner/cipher_suites.go new file mode 100644 index 0000000000..26f51b0626 --- /dev/null +++ b/external/boringssl/ssl/test/runner/cipher_suites.go @@ -0,0 +1,508 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package runner + +import ( + "crypto/aes" + "crypto/cipher" + "crypto/des" + "crypto/hmac" + "crypto/md5" + "crypto/rc4" + "crypto/sha1" + "crypto/sha256" + "crypto/sha512" + "crypto/x509" + "hash" +) + +// a keyAgreement implements the client and server side of a TLS key agreement +// protocol by generating and processing key exchange messages. +type keyAgreement interface { + // On the server side, the first two methods are called in order. + + // In the case that the key agreement protocol doesn't use a + // ServerKeyExchange message, generateServerKeyExchange can return nil, + // nil. + generateServerKeyExchange(*Config, *Certificate, *clientHelloMsg, *serverHelloMsg) (*serverKeyExchangeMsg, error) + processClientKeyExchange(*Config, *Certificate, *clientKeyExchangeMsg, uint16) ([]byte, error) + + // On the client side, the next two methods are called in order. + + // This method may not be called if the server doesn't send a + // ServerKeyExchange message. + processServerKeyExchange(*Config, *clientHelloMsg, *serverHelloMsg, *x509.Certificate, *serverKeyExchangeMsg) error + generateClientKeyExchange(*Config, *clientHelloMsg, *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) +} + +const ( + // suiteECDH indicates that the cipher suite involves elliptic curve + // Diffie-Hellman. This means that it should only be selected when the + // client indicates that it supports ECC with a curve and point format + // that we're happy with. + suiteECDHE = 1 << iota + // suiteCECPQ1 indicates that the cipher suite uses the + // experimental, temporary, and non-standard CECPQ1 key agreement. + suiteCECPQ1 + // suiteECDSA indicates that the cipher suite involves an ECDSA + // signature and therefore may only be selected when the server's + // certificate is ECDSA. If this is not set then the cipher suite is + // RSA based. + suiteECDSA + // suiteTLS12 indicates that the cipher suite should only be advertised + // and accepted when using TLS 1.2. + suiteTLS12 + // suiteSHA384 indicates that the cipher suite uses SHA384 as the + // handshake hash. + suiteSHA384 + // suiteNoDTLS indicates that the cipher suite cannot be used + // in DTLS. + suiteNoDTLS + // suitePSK indicates that the cipher suite authenticates with + // a pre-shared key rather than a server private key. + suitePSK +) + +type tlsAead struct { + cipher.AEAD + explicitNonce bool +} + +// A cipherSuite is a specific combination of key agreement, cipher and MAC +// function. All cipher suites currently assume RSA key agreement. +type cipherSuite struct { + id uint16 + // the lengths, in bytes, of the key material needed for each component. + keyLen int + macLen int + ivLen int + ka func(version uint16) keyAgreement + // flags is a bitmask of the suite* values, above. + flags int + cipher func(key, iv []byte, isRead bool) interface{} + mac func(version uint16, macKey []byte) macFunction + aead func(key, fixedNonce []byte) *tlsAead +} + +var cipherSuites = []*cipherSuite{ + // Ciphersuite order is chosen so that ECDHE comes before plain RSA + // and RC4 comes before AES (because of the Lucky13 attack). + {TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 32, 0, 12, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12, nil, nil, aeadCHACHA20POLY1305}, + {TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 32, 0, 12, ecdheRSAKA, suiteECDHE | suiteTLS12, nil, nil, aeadCHACHA20POLY1305}, + {TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256_OLD, 32, 0, 0, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12, nil, nil, aeadCHACHA20POLY1305Old}, + {TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256_OLD, 32, 0, 0, ecdheRSAKA, suiteECDHE | suiteTLS12, nil, nil, aeadCHACHA20POLY1305Old}, + {TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, ecdheRSAKA, suiteECDHE | suiteTLS12, nil, nil, aeadAESGCM}, + {TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12, nil, nil, aeadAESGCM}, + {TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, ecdheRSAKA, suiteECDHE | suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM}, + {TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM}, + {TLS_ECDHE_RSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheRSAKA, suiteECDHE | suiteNoDTLS, cipherRC4, macSHA1, nil}, + {TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteNoDTLS, cipherRC4, macSHA1, nil}, + {TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, ecdheRSAKA, suiteECDHE | suiteTLS12, cipherAES, macSHA256, nil}, + {TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12, cipherAES, macSHA256, nil}, + {TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheRSAKA, suiteECDHE, cipherAES, macSHA1, nil}, + {TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA, cipherAES, macSHA1, nil}, + {TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, 32, 48, 16, ecdheRSAKA, suiteECDHE | suiteTLS12 | suiteSHA384, cipherAES, macSHA384, nil}, + {TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, 32, 48, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12 | suiteSHA384, cipherAES, macSHA384, nil}, + {TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheRSAKA, suiteECDHE, cipherAES, macSHA1, nil}, + {TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA, cipherAES, macSHA1, nil}, + {TLS_CECPQ1_RSA_WITH_CHACHA20_POLY1305_SHA256, 32, 0, 12, cecpq1RSAKA, suiteCECPQ1 | suiteTLS12, nil, nil, aeadCHACHA20POLY1305}, + {TLS_CECPQ1_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 32, 0, 12, cecpq1ECDSAKA, suiteCECPQ1 | suiteECDSA | suiteTLS12, nil, nil, aeadCHACHA20POLY1305}, + {TLS_CECPQ1_RSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, cecpq1RSAKA, suiteCECPQ1 | suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM}, + {TLS_CECPQ1_ECDSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, cecpq1ECDSAKA, suiteCECPQ1 | suiteECDSA | suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM}, + {TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, dheRSAKA, suiteTLS12, nil, nil, aeadAESGCM}, + {TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, dheRSAKA, suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM}, + {TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, dheRSAKA, suiteTLS12, cipherAES, macSHA256, nil}, + {TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, 32, 32, 16, dheRSAKA, suiteTLS12, cipherAES, macSHA256, nil}, + {TLS_DHE_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, dheRSAKA, 0, cipherAES, macSHA1, nil}, + {TLS_DHE_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, dheRSAKA, 0, cipherAES, macSHA1, nil}, + {TLS_RSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, rsaKA, suiteTLS12, nil, nil, aeadAESGCM}, + {TLS_RSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, rsaKA, suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM}, + {TLS_RSA_WITH_RC4_128_SHA, 16, 20, 0, rsaKA, suiteNoDTLS, cipherRC4, macSHA1, nil}, + {TLS_RSA_WITH_RC4_128_MD5, 16, 16, 0, rsaKA, suiteNoDTLS, cipherRC4, macMD5, nil}, + {TLS_RSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, rsaKA, suiteTLS12, cipherAES, macSHA256, nil}, + {TLS_RSA_WITH_AES_256_CBC_SHA256, 32, 32, 16, rsaKA, suiteTLS12, cipherAES, macSHA256, nil}, + {TLS_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, rsaKA, 0, cipherAES, macSHA1, nil}, + {TLS_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, rsaKA, 0, cipherAES, macSHA1, nil}, + {TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, ecdheRSAKA, suiteECDHE, cipher3DES, macSHA1, nil}, + {TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, dheRSAKA, 0, cipher3DES, macSHA1, nil}, + {TLS_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, rsaKA, 0, cipher3DES, macSHA1, nil}, + {TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256, 32, 0, 12, ecdhePSKKA, suiteECDHE | suitePSK | suiteTLS12, nil, nil, aeadCHACHA20POLY1305}, + {TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256, 16, 0, 4, ecdhePSKKA, suiteECDHE | suitePSK | suiteTLS12, nil, nil, aeadAESGCM}, + {TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384, 32, 0, 4, ecdhePSKKA, suiteECDHE | suitePSK | suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM}, + {TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdhePSKKA, suiteECDHE | suitePSK, cipherAES, macSHA1, nil}, + {TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdhePSKKA, suiteECDHE | suitePSK, cipherAES, macSHA1, nil}, + {TLS_PSK_WITH_RC4_128_SHA, 16, 20, 0, pskKA, suiteNoDTLS | suitePSK, cipherRC4, macSHA1, nil}, + {TLS_PSK_WITH_AES_128_CBC_SHA, 16, 20, 16, pskKA, suitePSK, cipherAES, macSHA1, nil}, + {TLS_PSK_WITH_AES_256_CBC_SHA, 32, 20, 16, pskKA, suitePSK, cipherAES, macSHA1, nil}, + {TLS_RSA_WITH_NULL_SHA, 0, 20, 0, rsaKA, suiteNoDTLS, cipherNull, macSHA1, nil}, +} + +type nullCipher struct{} + +func cipherNull(key, iv []byte, isRead bool) interface{} { + return nullCipher{} +} + +func cipherRC4(key, iv []byte, isRead bool) interface{} { + cipher, _ := rc4.NewCipher(key) + return cipher +} + +func cipher3DES(key, iv []byte, isRead bool) interface{} { + block, _ := des.NewTripleDESCipher(key) + if isRead { + return cipher.NewCBCDecrypter(block, iv) + } + return cipher.NewCBCEncrypter(block, iv) +} + +func cipherAES(key, iv []byte, isRead bool) interface{} { + block, _ := aes.NewCipher(key) + if isRead { + return cipher.NewCBCDecrypter(block, iv) + } + return cipher.NewCBCEncrypter(block, iv) +} + +// macSHA1 returns a macFunction for the given protocol version. +func macSHA1(version uint16, key []byte) macFunction { + if version == VersionSSL30 { + mac := ssl30MAC{ + h: sha1.New(), + key: make([]byte, len(key)), + } + copy(mac.key, key) + return mac + } + return tls10MAC{hmac.New(sha1.New, key)} +} + +func macMD5(version uint16, key []byte) macFunction { + if version == VersionSSL30 { + mac := ssl30MAC{ + h: md5.New(), + key: make([]byte, len(key)), + } + copy(mac.key, key) + return mac + } + return tls10MAC{hmac.New(md5.New, key)} +} + +func macSHA256(version uint16, key []byte) macFunction { + if version == VersionSSL30 { + mac := ssl30MAC{ + h: sha256.New(), + key: make([]byte, len(key)), + } + copy(mac.key, key) + return mac + } + return tls10MAC{hmac.New(sha256.New, key)} +} + +func macSHA384(version uint16, key []byte) macFunction { + if version == VersionSSL30 { + mac := ssl30MAC{ + h: sha512.New384(), + key: make([]byte, len(key)), + } + copy(mac.key, key) + return mac + } + return tls10MAC{hmac.New(sha512.New384, key)} +} + +type macFunction interface { + Size() int + MAC(digestBuf, seq, header, length, data []byte) []byte +} + +// fixedNonceAEAD wraps an AEAD and prefixes a fixed portion of the nonce to +// each call. +type fixedNonceAEAD struct { + // sealNonce and openNonce are buffers where the larger nonce will be + // constructed. Since a seal and open operation may be running + // concurrently, there is a separate buffer for each. + sealNonce, openNonce []byte + aead cipher.AEAD +} + +func (f *fixedNonceAEAD) NonceSize() int { return 8 } +func (f *fixedNonceAEAD) Overhead() int { return f.aead.Overhead() } + +func (f *fixedNonceAEAD) Seal(out, nonce, plaintext, additionalData []byte) []byte { + copy(f.sealNonce[len(f.sealNonce)-8:], nonce) + return f.aead.Seal(out, f.sealNonce, plaintext, additionalData) +} + +func (f *fixedNonceAEAD) Open(out, nonce, plaintext, additionalData []byte) ([]byte, error) { + copy(f.openNonce[len(f.openNonce)-8:], nonce) + return f.aead.Open(out, f.openNonce, plaintext, additionalData) +} + +func aeadAESGCM(key, fixedNonce []byte) *tlsAead { + aes, err := aes.NewCipher(key) + if err != nil { + panic(err) + } + aead, err := cipher.NewGCM(aes) + if err != nil { + panic(err) + } + + nonce1, nonce2 := make([]byte, 12), make([]byte, 12) + copy(nonce1, fixedNonce) + copy(nonce2, fixedNonce) + + return &tlsAead{&fixedNonceAEAD{nonce1, nonce2, aead}, true} +} + +func aeadCHACHA20POLY1305Old(key, fixedNonce []byte) *tlsAead { + aead, err := newChaCha20Poly1305Old(key) + if err != nil { + panic(err) + } + return &tlsAead{aead, false} +} + +func xorSlice(out, in []byte) { + for i := range out { + out[i] ^= in[i] + } +} + +// xorNonceAEAD wraps an AEAD and XORs a fixed portion of the nonce, left-padded +// if necessary, each call. +type xorNonceAEAD struct { + // sealNonce and openNonce are buffers where the larger nonce will be + // constructed. Since a seal and open operation may be running + // concurrently, there is a separate buffer for each. + sealNonce, openNonce []byte + aead cipher.AEAD +} + +func (x *xorNonceAEAD) NonceSize() int { return 8 } +func (x *xorNonceAEAD) Overhead() int { return x.aead.Overhead() } + +func (x *xorNonceAEAD) Seal(out, nonce, plaintext, additionalData []byte) []byte { + xorSlice(x.sealNonce[len(x.sealNonce)-len(nonce):], nonce) + ret := x.aead.Seal(out, x.sealNonce, plaintext, additionalData) + xorSlice(x.sealNonce[len(x.sealNonce)-len(nonce):], nonce) + return ret +} + +func (x *xorNonceAEAD) Open(out, nonce, plaintext, additionalData []byte) ([]byte, error) { + xorSlice(x.openNonce[len(x.openNonce)-len(nonce):], nonce) + ret, err := x.aead.Open(out, x.openNonce, plaintext, additionalData) + xorSlice(x.openNonce[len(x.openNonce)-len(nonce):], nonce) + return ret, err +} + +func aeadCHACHA20POLY1305(key, fixedNonce []byte) *tlsAead { + aead, err := newChaCha20Poly1305(key) + if err != nil { + panic(err) + } + + nonce1, nonce2 := make([]byte, len(fixedNonce)), make([]byte, len(fixedNonce)) + copy(nonce1, fixedNonce) + copy(nonce2, fixedNonce) + + return &tlsAead{&xorNonceAEAD{nonce1, nonce2, aead}, false} +} + +// ssl30MAC implements the SSLv3 MAC function, as defined in +// www.mozilla.org/projects/security/pki/nss/ssl/draft302.txt section 5.2.3.1 +type ssl30MAC struct { + h hash.Hash + key []byte +} + +func (s ssl30MAC) Size() int { + return s.h.Size() +} + +var ssl30Pad1 = [48]byte{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36} + +var ssl30Pad2 = [48]byte{0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c} + +func (s ssl30MAC) MAC(digestBuf, seq, header, length, data []byte) []byte { + padLength := 48 + if s.h.Size() == 20 { + padLength = 40 + } + + s.h.Reset() + s.h.Write(s.key) + s.h.Write(ssl30Pad1[:padLength]) + s.h.Write(seq) + s.h.Write(header[:1]) + s.h.Write(length) + s.h.Write(data) + digestBuf = s.h.Sum(digestBuf[:0]) + + s.h.Reset() + s.h.Write(s.key) + s.h.Write(ssl30Pad2[:padLength]) + s.h.Write(digestBuf) + return s.h.Sum(digestBuf[:0]) +} + +// tls10MAC implements the TLS 1.0 MAC function. RFC 2246, section 6.2.3. +type tls10MAC struct { + h hash.Hash +} + +func (s tls10MAC) Size() int { + return s.h.Size() +} + +func (s tls10MAC) MAC(digestBuf, seq, header, length, data []byte) []byte { + s.h.Reset() + s.h.Write(seq) + s.h.Write(header) + s.h.Write(length) + s.h.Write(data) + return s.h.Sum(digestBuf[:0]) +} + +func rsaKA(version uint16) keyAgreement { + return &rsaKeyAgreement{version: version} +} + +func ecdheECDSAKA(version uint16) keyAgreement { + return &ecdheKeyAgreement{ + auth: &signedKeyAgreement{ + sigType: signatureECDSA, + version: version, + }, + } +} + +func cecpq1ECDSAKA(version uint16) keyAgreement { + return &cecpq1KeyAgreement{ + auth: &signedKeyAgreement{ + sigType: signatureECDSA, + version: version, + }, + } +} + +func ecdheRSAKA(version uint16) keyAgreement { + return &ecdheKeyAgreement{ + auth: &signedKeyAgreement{ + sigType: signatureRSA, + version: version, + }, + } +} + +func cecpq1RSAKA(version uint16) keyAgreement { + return &cecpq1KeyAgreement{ + auth: &signedKeyAgreement{ + sigType: signatureRSA, + version: version, + }, + } +} + +func dheRSAKA(version uint16) keyAgreement { + return &dheKeyAgreement{ + auth: &signedKeyAgreement{ + sigType: signatureRSA, + version: version, + }, + } +} + +func pskKA(version uint16) keyAgreement { + return &pskKeyAgreement{ + base: &nilKeyAgreement{}, + } +} + +func ecdhePSKKA(version uint16) keyAgreement { + return &pskKeyAgreement{ + base: &ecdheKeyAgreement{ + auth: &nilKeyAgreementAuthentication{}, + }, + } +} + +// mutualCipherSuite returns a cipherSuite given a list of supported +// ciphersuites and the id requested by the peer. +func mutualCipherSuite(have []uint16, want uint16) *cipherSuite { + for _, id := range have { + if id == want { + for _, suite := range cipherSuites { + if suite.id == want { + return suite + } + } + return nil + } + } + return nil +} + +// A list of the possible cipher suite ids. Taken from +// http://www.iana.org/assignments/tls-parameters/tls-parameters.xml +const ( + TLS_RSA_WITH_NULL_SHA uint16 = 0x0002 + TLS_RSA_WITH_RC4_128_MD5 uint16 = 0x0004 + TLS_RSA_WITH_RC4_128_SHA uint16 = 0x0005 + TLS_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0x000a + TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0x0016 + TLS_RSA_WITH_AES_128_CBC_SHA uint16 = 0x002f + TLS_DHE_RSA_WITH_AES_128_CBC_SHA uint16 = 0x0033 + TLS_RSA_WITH_AES_256_CBC_SHA uint16 = 0x0035 + TLS_DHE_RSA_WITH_AES_256_CBC_SHA uint16 = 0x0039 + TLS_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0x003c + TLS_RSA_WITH_AES_256_CBC_SHA256 uint16 = 0x003d + TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0x0067 + TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 uint16 = 0x006b + TLS_PSK_WITH_RC4_128_SHA uint16 = 0x008a + TLS_PSK_WITH_AES_128_CBC_SHA uint16 = 0x008c + TLS_PSK_WITH_AES_256_CBC_SHA uint16 = 0x008d + TLS_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0x009c + TLS_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0x009d + TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0x009e + TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0x009f + TLS_ECDHE_ECDSA_WITH_RC4_128_SHA uint16 = 0xc007 + TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA uint16 = 0xc009 + TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA uint16 = 0xc00a + TLS_ECDHE_RSA_WITH_RC4_128_SHA uint16 = 0xc011 + TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xc012 + TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA uint16 = 0xc013 + TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA uint16 = 0xc014 + TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 uint16 = 0xc023 + TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 uint16 = 0xc024 + TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0xc027 + TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 uint16 = 0xc028 + TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 uint16 = 0xc02b + TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 uint16 = 0xc02c + TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0xc02f + TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0xc030 + TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA uint16 = 0xc035 + TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA uint16 = 0xc036 + TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xcca8 + TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xcca9 + TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xccac + renegotiationSCSV uint16 = 0x00ff + fallbackSCSV uint16 = 0x5600 +) + +// Additional cipher suite IDs, not IANA-assigned. +const ( + TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256_OLD uint16 = 0xcc13 + TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256_OLD uint16 = 0xcc14 + TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256 uint16 = 0xd001 + TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384 uint16 = 0xd002 + TLS_CECPQ1_RSA_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0x16b7 + TLS_CECPQ1_ECDSA_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0x16b8 + TLS_CECPQ1_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0x16b9 + TLS_CECPQ1_ECDSA_WITH_AES_256_GCM_SHA384 uint16 = 0x16ba +) diff --git a/external/boringssl/ssl/test/runner/common.go b/external/boringssl/ssl/test/runner/common.go new file mode 100644 index 0000000000..648807fcc7 --- /dev/null +++ b/external/boringssl/ssl/test/runner/common.go @@ -0,0 +1,1200 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package runner + +import ( + "container/list" + "crypto" + "crypto/ecdsa" + "crypto/rand" + "crypto/x509" + "fmt" + "io" + "math/big" + "strings" + "sync" + "time" +) + +const ( + VersionSSL30 = 0x0300 + VersionTLS10 = 0x0301 + VersionTLS11 = 0x0302 + VersionTLS12 = 0x0303 +) + +const ( + maxPlaintext = 16384 // maximum plaintext payload length + maxCiphertext = 16384 + 2048 // maximum ciphertext payload length + tlsRecordHeaderLen = 5 // record header length + dtlsRecordHeaderLen = 13 + maxHandshake = 65536 // maximum handshake we support (protocol max is 16 MB) + + minVersion = VersionSSL30 + maxVersion = VersionTLS12 +) + +// TLS record types. +type recordType uint8 + +const ( + recordTypeChangeCipherSpec recordType = 20 + recordTypeAlert recordType = 21 + recordTypeHandshake recordType = 22 + recordTypeApplicationData recordType = 23 +) + +// TLS handshake message types. +const ( + typeHelloRequest uint8 = 0 + typeClientHello uint8 = 1 + typeServerHello uint8 = 2 + typeHelloVerifyRequest uint8 = 3 + typeNewSessionTicket uint8 = 4 + typeCertificate uint8 = 11 + typeServerKeyExchange uint8 = 12 + typeCertificateRequest uint8 = 13 + typeServerHelloDone uint8 = 14 + typeCertificateVerify uint8 = 15 + typeClientKeyExchange uint8 = 16 + typeFinished uint8 = 20 + typeCertificateStatus uint8 = 22 + typeNextProtocol uint8 = 67 // Not IANA assigned + typeEncryptedExtensions uint8 = 203 // Not IANA assigned +) + +// TLS compression types. +const ( + compressionNone uint8 = 0 +) + +// TLS extension numbers +const ( + extensionServerName uint16 = 0 + extensionStatusRequest uint16 = 5 + extensionSupportedCurves uint16 = 10 + extensionSupportedPoints uint16 = 11 + extensionSignatureAlgorithms uint16 = 13 + extensionUseSRTP uint16 = 14 + extensionALPN uint16 = 16 + extensionSignedCertificateTimestamp uint16 = 18 + extensionExtendedMasterSecret uint16 = 23 + extensionSessionTicket uint16 = 35 + extensionCustom uint16 = 1234 // not IANA assigned + extensionNextProtoNeg uint16 = 13172 // not IANA assigned + extensionRenegotiationInfo uint16 = 0xff01 + extensionChannelID uint16 = 30032 // not IANA assigned +) + +// TLS signaling cipher suite values +const ( + scsvRenegotiation uint16 = 0x00ff +) + +// CurveID is the type of a TLS identifier for an elliptic curve. See +// http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-8 +type CurveID uint16 + +const ( + CurveP224 CurveID = 21 + CurveP256 CurveID = 23 + CurveP384 CurveID = 24 + CurveP521 CurveID = 25 + CurveX25519 CurveID = 29 +) + +// TLS Elliptic Curve Point Formats +// http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-9 +const ( + pointFormatUncompressed uint8 = 0 +) + +// TLS CertificateStatusType (RFC 3546) +const ( + statusTypeOCSP uint8 = 1 +) + +// Certificate types (for certificateRequestMsg) +const ( + CertTypeRSASign = 1 // A certificate containing an RSA key + CertTypeDSSSign = 2 // A certificate containing a DSA key + CertTypeRSAFixedDH = 3 // A certificate containing a static DH key + CertTypeDSSFixedDH = 4 // A certificate containing a static DH key + + // See RFC4492 sections 3 and 5.5. + CertTypeECDSASign = 64 // A certificate containing an ECDSA-capable public key, signed with ECDSA. + CertTypeRSAFixedECDH = 65 // A certificate containing an ECDH-capable public key, signed with RSA. + CertTypeECDSAFixedECDH = 66 // A certificate containing an ECDH-capable public key, signed with ECDSA. + + // Rest of these are reserved by the TLS spec +) + +// Hash functions for TLS 1.2 (See RFC 5246, section A.4.1) +const ( + hashMD5 uint8 = 1 + hashSHA1 uint8 = 2 + hashSHA224 uint8 = 3 + hashSHA256 uint8 = 4 + hashSHA384 uint8 = 5 + hashSHA512 uint8 = 6 +) + +// Signature algorithms for TLS 1.2 (See RFC 5246, section A.4.1) +const ( + signatureRSA uint8 = 1 + signatureECDSA uint8 = 3 +) + +// signatureAndHash mirrors the TLS 1.2, SignatureAndHashAlgorithm struct. See +// RFC 5246, section A.4.1. +type signatureAndHash struct { + signature, hash uint8 +} + +// supportedSKXSignatureAlgorithms contains the signature and hash algorithms +// that the code advertises as supported in a TLS 1.2 ClientHello. +var supportedSKXSignatureAlgorithms = []signatureAndHash{ + {signatureRSA, hashSHA256}, + {signatureECDSA, hashSHA256}, + {signatureRSA, hashSHA1}, + {signatureECDSA, hashSHA1}, +} + +// supportedClientCertSignatureAlgorithms contains the signature and hash +// algorithms that the code advertises as supported in a TLS 1.2 +// CertificateRequest. +var supportedClientCertSignatureAlgorithms = []signatureAndHash{ + {signatureRSA, hashSHA256}, + {signatureECDSA, hashSHA256}, +} + +// SRTP protection profiles (See RFC 5764, section 4.1.2) +const ( + SRTP_AES128_CM_HMAC_SHA1_80 uint16 = 0x0001 + SRTP_AES128_CM_HMAC_SHA1_32 = 0x0002 +) + +// ConnectionState records basic TLS details about the connection. +type ConnectionState struct { + Version uint16 // TLS version used by the connection (e.g. VersionTLS12) + HandshakeComplete bool // TLS handshake is complete + DidResume bool // connection resumes a previous TLS connection + CipherSuite uint16 // cipher suite in use (TLS_RSA_WITH_RC4_128_SHA, ...) + NegotiatedProtocol string // negotiated next protocol (from Config.NextProtos) + NegotiatedProtocolIsMutual bool // negotiated protocol was advertised by server + NegotiatedProtocolFromALPN bool // protocol negotiated with ALPN + ServerName string // server name requested by client, if any (server side only) + PeerCertificates []*x509.Certificate // certificate chain presented by remote peer + VerifiedChains [][]*x509.Certificate // verified chains built from PeerCertificates + ChannelID *ecdsa.PublicKey // the channel ID for this connection + SRTPProtectionProfile uint16 // the negotiated DTLS-SRTP protection profile + TLSUnique []byte // the tls-unique channel binding + SCTList []byte // signed certificate timestamp list + ClientCertSignatureHash uint8 // TLS id of the hash used by the client to sign the handshake +} + +// ClientAuthType declares the policy the server will follow for +// TLS Client Authentication. +type ClientAuthType int + +const ( + NoClientCert ClientAuthType = iota + RequestClientCert + RequireAnyClientCert + VerifyClientCertIfGiven + RequireAndVerifyClientCert +) + +// ClientSessionState contains the state needed by clients to resume TLS +// sessions. +type ClientSessionState struct { + sessionId []uint8 // Session ID supplied by the server. nil if the session has a ticket. + sessionTicket []uint8 // Encrypted ticket used for session resumption with server + vers uint16 // SSL/TLS version negotiated for the session + cipherSuite uint16 // Ciphersuite negotiated for the session + masterSecret []byte // MasterSecret generated by client on a full handshake + handshakeHash []byte // Handshake hash for Channel ID purposes. + serverCertificates []*x509.Certificate // Certificate chain presented by the server + extendedMasterSecret bool // Whether an extended master secret was used to generate the session + sctList []byte + ocspResponse []byte +} + +// ClientSessionCache is a cache of ClientSessionState objects that can be used +// by a client to resume a TLS session with a given server. ClientSessionCache +// implementations should expect to be called concurrently from different +// goroutines. +type ClientSessionCache interface { + // Get searches for a ClientSessionState associated with the given key. + // On return, ok is true if one was found. + Get(sessionKey string) (session *ClientSessionState, ok bool) + + // Put adds the ClientSessionState to the cache with the given key. + Put(sessionKey string, cs *ClientSessionState) +} + +// ServerSessionCache is a cache of sessionState objects that can be used by a +// client to resume a TLS session with a given server. ServerSessionCache +// implementations should expect to be called concurrently from different +// goroutines. +type ServerSessionCache interface { + // Get searches for a sessionState associated with the given session + // ID. On return, ok is true if one was found. + Get(sessionId string) (session *sessionState, ok bool) + + // Put adds the sessionState to the cache with the given session ID. + Put(sessionId string, session *sessionState) +} + +// A Config structure is used to configure a TLS client or server. +// After one has been passed to a TLS function it must not be +// modified. A Config may be reused; the tls package will also not +// modify it. +type Config struct { + // Rand provides the source of entropy for nonces and RSA blinding. + // If Rand is nil, TLS uses the cryptographic random reader in package + // crypto/rand. + // The Reader must be safe for use by multiple goroutines. + Rand io.Reader + + // Time returns the current time as the number of seconds since the epoch. + // If Time is nil, TLS uses time.Now. + Time func() time.Time + + // Certificates contains one or more certificate chains + // to present to the other side of the connection. + // Server configurations must include at least one certificate. + Certificates []Certificate + + // NameToCertificate maps from a certificate name to an element of + // Certificates. Note that a certificate name can be of the form + // '*.example.com' and so doesn't have to be a domain name as such. + // See Config.BuildNameToCertificate + // The nil value causes the first element of Certificates to be used + // for all connections. + NameToCertificate map[string]*Certificate + + // RootCAs defines the set of root certificate authorities + // that clients use when verifying server certificates. + // If RootCAs is nil, TLS uses the host's root CA set. + RootCAs *x509.CertPool + + // NextProtos is a list of supported, application level protocols. + NextProtos []string + + // ServerName is used to verify the hostname on the returned + // certificates unless InsecureSkipVerify is given. It is also included + // in the client's handshake to support virtual hosting. + ServerName string + + // ClientAuth determines the server's policy for + // TLS Client Authentication. The default is NoClientCert. + ClientAuth ClientAuthType + + // ClientCAs defines the set of root certificate authorities + // that servers use if required to verify a client certificate + // by the policy in ClientAuth. + ClientCAs *x509.CertPool + + // ClientCertificateTypes defines the set of allowed client certificate + // types. The default is CertTypeRSASign and CertTypeECDSASign. + ClientCertificateTypes []byte + + // InsecureSkipVerify controls whether a client verifies the + // server's certificate chain and host name. + // If InsecureSkipVerify is true, TLS accepts any certificate + // presented by the server and any host name in that certificate. + // In this mode, TLS is susceptible to man-in-the-middle attacks. + // This should be used only for testing. + InsecureSkipVerify bool + + // CipherSuites is a list of supported cipher suites. If CipherSuites + // is nil, TLS uses a list of suites supported by the implementation. + CipherSuites []uint16 + + // PreferServerCipherSuites controls whether the server selects the + // client's most preferred ciphersuite, or the server's most preferred + // ciphersuite. If true then the server's preference, as expressed in + // the order of elements in CipherSuites, is used. + PreferServerCipherSuites bool + + // SessionTicketsDisabled may be set to true to disable session ticket + // (resumption) support. + SessionTicketsDisabled bool + + // SessionTicketKey is used by TLS servers to provide session + // resumption. See RFC 5077. If zero, it will be filled with + // random data before the first server handshake. + // + // If multiple servers are terminating connections for the same host + // they should all have the same SessionTicketKey. If the + // SessionTicketKey leaks, previously recorded and future TLS + // connections using that key are compromised. + SessionTicketKey [32]byte + + // ClientSessionCache is a cache of ClientSessionState entries + // for TLS session resumption. + ClientSessionCache ClientSessionCache + + // ServerSessionCache is a cache of sessionState entries for TLS session + // resumption. + ServerSessionCache ServerSessionCache + + // MinVersion contains the minimum SSL/TLS version that is acceptable. + // If zero, then SSLv3 is taken as the minimum. + MinVersion uint16 + + // MaxVersion contains the maximum SSL/TLS version that is acceptable. + // If zero, then the maximum version supported by this package is used, + // which is currently TLS 1.2. + MaxVersion uint16 + + // CurvePreferences contains the elliptic curves that will be used in + // an ECDHE handshake, in preference order. If empty, the default will + // be used. + CurvePreferences []CurveID + + // ChannelID contains the ECDSA key for the client to use as + // its TLS Channel ID. + ChannelID *ecdsa.PrivateKey + + // RequestChannelID controls whether the server requests a TLS + // Channel ID. If negotiated, the client's public key is + // returned in the ConnectionState. + RequestChannelID bool + + // PreSharedKey, if not nil, is the pre-shared key to use with + // the PSK cipher suites. + PreSharedKey []byte + + // PreSharedKeyIdentity, if not empty, is the identity to use + // with the PSK cipher suites. + PreSharedKeyIdentity string + + // SRTPProtectionProfiles, if not nil, is the list of SRTP + // protection profiles to offer in DTLS-SRTP. + SRTPProtectionProfiles []uint16 + + // SignatureAndHashes, if not nil, overrides the default set of + // supported signature and hash algorithms to advertise in + // CertificateRequest. + SignatureAndHashes []signatureAndHash + + // Bugs specifies optional misbehaviour to be used for testing other + // implementations. + Bugs ProtocolBugs + + serverInitOnce sync.Once // guards calling (*Config).serverInit +} + +type BadValue int + +const ( + BadValueNone BadValue = iota + BadValueNegative + BadValueZero + BadValueLimit + BadValueLarge + NumBadValues +) + +type RSABadValue int + +const ( + RSABadValueNone RSABadValue = iota + RSABadValueCorrupt + RSABadValueTooLong + RSABadValueTooShort + RSABadValueWrongVersion + NumRSABadValues +) + +type ProtocolBugs struct { + // InvalidSKXSignature specifies that the signature in a + // ServerKeyExchange message should be invalid. + InvalidSKXSignature bool + + // InvalidCertVerifySignature specifies that the signature in a + // CertificateVerify message should be invalid. + InvalidCertVerifySignature bool + + // InvalidSKXCurve causes the curve ID in the ServerKeyExchange message + // to be wrong. + InvalidSKXCurve bool + + // InvalidECDHPoint, if true, causes the ECC points in + // ServerKeyExchange or ClientKeyExchange messages to be invalid. + InvalidECDHPoint bool + + // BadECDSAR controls ways in which the 'r' value of an ECDSA signature + // can be invalid. + BadECDSAR BadValue + BadECDSAS BadValue + + // MaxPadding causes CBC records to have the maximum possible padding. + MaxPadding bool + // PaddingFirstByteBad causes the first byte of the padding to be + // incorrect. + PaddingFirstByteBad bool + // PaddingFirstByteBadIf255 causes the first byte of padding to be + // incorrect if there's a maximum amount of padding (i.e. 255 bytes). + PaddingFirstByteBadIf255 bool + + // FailIfNotFallbackSCSV causes a server handshake to fail if the + // client doesn't send the fallback SCSV value. + FailIfNotFallbackSCSV bool + + // DuplicateExtension causes an extra empty extension of bogus type to + // be emitted in either the ClientHello or the ServerHello. + DuplicateExtension bool + + // UnauthenticatedECDH causes the server to pretend ECDHE_RSA + // and ECDHE_ECDSA cipher suites are actually ECDH_anon. No + // Certificate message is sent and no signature is added to + // ServerKeyExchange. + UnauthenticatedECDH bool + + // SkipHelloVerifyRequest causes a DTLS server to skip the + // HelloVerifyRequest message. + SkipHelloVerifyRequest bool + + // SkipCertificateStatus, if true, causes the server to skip the + // CertificateStatus message. This is legal because CertificateStatus is + // optional, even with a status_request in ServerHello. + SkipCertificateStatus bool + + // SkipServerKeyExchange causes the server to skip sending + // ServerKeyExchange messages. + SkipServerKeyExchange bool + + // SkipNewSessionTicket causes the server to skip sending the + // NewSessionTicket message despite promising to in ServerHello. + SkipNewSessionTicket bool + + // SkipClientCertificate causes the client to skip the Certificate + // message. + SkipClientCertificate bool + + // SkipChangeCipherSpec causes the implementation to skip + // sending the ChangeCipherSpec message (and adjusting cipher + // state accordingly for the Finished message). + SkipChangeCipherSpec bool + + // SkipFinished causes the implementation to skip sending the Finished + // message. + SkipFinished bool + + // EarlyChangeCipherSpec causes the client to send an early + // ChangeCipherSpec message before the ClientKeyExchange. A value of + // zero disables this behavior. One and two configure variants for 0.9.8 + // and 1.0.1 modes, respectively. + EarlyChangeCipherSpec int + + // FragmentAcrossChangeCipherSpec causes the implementation to fragment + // the Finished (or NextProto) message around the ChangeCipherSpec + // messages. + FragmentAcrossChangeCipherSpec bool + + // SendV2ClientHello causes the client to send a V2ClientHello + // instead of a normal ClientHello. + SendV2ClientHello bool + + // SendFallbackSCSV causes the client to include + // TLS_FALLBACK_SCSV in the ClientHello. + SendFallbackSCSV bool + + // SendRenegotiationSCSV causes the client to include the renegotiation + // SCSV in the ClientHello. + SendRenegotiationSCSV bool + + // MaxHandshakeRecordLength, if non-zero, is the maximum size of a + // handshake record. Handshake messages will be split into multiple + // records at the specified size, except that the client_version will + // never be fragmented. For DTLS, it is the maximum handshake fragment + // size, not record size; DTLS allows multiple handshake fragments in a + // single handshake record. See |PackHandshakeFragments|. + MaxHandshakeRecordLength int + + // FragmentClientVersion will allow MaxHandshakeRecordLength to apply to + // the first 6 bytes of the ClientHello. + FragmentClientVersion bool + + // FragmentAlert will cause all alerts to be fragmented across + // two records. + FragmentAlert bool + + // DoubleAlert will cause all alerts to be sent as two copies packed + // within one record. + DoubleAlert bool + + // SendSpuriousAlert, if non-zero, will cause an spurious, unwanted + // alert to be sent. + SendSpuriousAlert alert + + // BadRSAClientKeyExchange causes the client to send a corrupted RSA + // ClientKeyExchange which would not pass padding checks. + BadRSAClientKeyExchange RSABadValue + + // RenewTicketOnResume causes the server to renew the session ticket and + // send a NewSessionTicket message during an abbreviated handshake. + RenewTicketOnResume bool + + // SendClientVersion, if non-zero, causes the client to send a different + // TLS version in the ClientHello than the maximum supported version. + SendClientVersion uint16 + + // ExpectFalseStart causes the server to, on full handshakes, + // expect the peer to False Start; the server Finished message + // isn't sent until we receive an application data record + // from the peer. + ExpectFalseStart bool + + // AlertBeforeFalseStartTest, if non-zero, causes the server to, on full + // handshakes, send an alert just before reading the application data + // record to test False Start. This can be used in a negative False + // Start test to determine whether the peer processed the alert (and + // closed the connection) before or after sending app data. + AlertBeforeFalseStartTest alert + + // SkipCipherVersionCheck causes the server to negotiate + // TLS 1.2 ciphers in earlier versions of TLS. + SkipCipherVersionCheck bool + + // ExpectServerName, if not empty, is the hostname the client + // must specify in the server_name extension. + ExpectServerName string + + // SwapNPNAndALPN switches the relative order between NPN and ALPN in + // both ClientHello and ServerHello. + SwapNPNAndALPN bool + + // ALPNProtocol, if not nil, sets the ALPN protocol that a server will + // return. + ALPNProtocol *string + + // AllowSessionVersionMismatch causes the server to resume sessions + // regardless of the version associated with the session. + AllowSessionVersionMismatch bool + + // CorruptTicket causes a client to corrupt a session ticket before + // sending it in a resume handshake. + CorruptTicket bool + + // OversizedSessionId causes the session id that is sent with a ticket + // resumption attempt to be too large (33 bytes). + OversizedSessionId bool + + // RequireExtendedMasterSecret, if true, requires that the peer support + // the extended master secret option. + RequireExtendedMasterSecret bool + + // NoExtendedMasterSecret causes the client and server to behave as if + // they didn't support an extended master secret. + NoExtendedMasterSecret bool + + // EmptyRenegotiationInfo causes the renegotiation extension to be + // empty in a renegotiation handshake. + EmptyRenegotiationInfo bool + + // BadRenegotiationInfo causes the renegotiation extension value in a + // renegotiation handshake to be incorrect. + BadRenegotiationInfo bool + + // NoRenegotiationInfo disables renegotiation info support in all + // handshakes. + NoRenegotiationInfo bool + + // NoRenegotiationInfoInInitial disables renegotiation info support in + // the initial handshake. + NoRenegotiationInfoInInitial bool + + // NoRenegotiationInfoAfterInitial disables renegotiation info support + // in renegotiation handshakes. + NoRenegotiationInfoAfterInitial bool + + // RequireRenegotiationInfo, if true, causes the client to return an + // error if the server doesn't reply with the renegotiation extension. + RequireRenegotiationInfo bool + + // SequenceNumberMapping, if non-nil, is the mapping function to apply + // to the sequence number of outgoing packets. For both TLS and DTLS, + // the two most-significant bytes in the resulting sequence number are + // ignored so that the DTLS epoch cannot be changed. + SequenceNumberMapping func(uint64) uint64 + + // RSAEphemeralKey, if true, causes the server to send a + // ServerKeyExchange message containing an ephemeral key (as in + // RSA_EXPORT) in the plain RSA key exchange. + RSAEphemeralKey bool + + // SRTPMasterKeyIdentifer, if not empty, is the SRTP MKI value that the + // client offers when negotiating SRTP. MKI support is still missing so + // the peer must still send none. + SRTPMasterKeyIdentifer string + + // SendSRTPProtectionProfile, if non-zero, is the SRTP profile that the + // server sends in the ServerHello instead of the negotiated one. + SendSRTPProtectionProfile uint16 + + // NoSignatureAndHashes, if true, causes the client to omit the + // signature and hashes extension. + // + // For a server, it will cause an empty list to be sent in the + // CertificateRequest message. None the less, the configured set will + // still be enforced. + NoSignatureAndHashes bool + + // NoSupportedCurves, if true, causes the client to omit the + // supported_curves extension. + NoSupportedCurves bool + + // RequireSameRenegoClientVersion, if true, causes the server + // to require that all ClientHellos match in offered version + // across a renego. + RequireSameRenegoClientVersion bool + + // ExpectInitialRecordVersion, if non-zero, is the expected + // version of the records before the version is determined. + ExpectInitialRecordVersion uint16 + + // MaxPacketLength, if non-zero, is the maximum acceptable size for a + // packet. + MaxPacketLength int + + // SendCipherSuite, if non-zero, is the cipher suite value that the + // server will send in the ServerHello. This does not affect the cipher + // the server believes it has actually negotiated. + SendCipherSuite uint16 + + // AppDataBeforeHandshake, if not nil, causes application data to be + // sent immediately before the first handshake message. + AppDataBeforeHandshake []byte + + // AppDataAfterChangeCipherSpec, if not nil, causes application data to + // be sent immediately after ChangeCipherSpec. + AppDataAfterChangeCipherSpec []byte + + // AlertAfterChangeCipherSpec, if non-zero, causes an alert to be sent + // immediately after ChangeCipherSpec. + AlertAfterChangeCipherSpec alert + + // TimeoutSchedule is the schedule of packet drops and simulated + // timeouts for before each handshake leg from the peer. + TimeoutSchedule []time.Duration + + // PacketAdaptor is the packetAdaptor to use to simulate timeouts. + PacketAdaptor *packetAdaptor + + // ReorderHandshakeFragments, if true, causes handshake fragments in + // DTLS to overlap and be sent in the wrong order. It also causes + // pre-CCS flights to be sent twice. (Post-CCS flights consist of + // Finished and will trigger a spurious retransmit.) + ReorderHandshakeFragments bool + + // MixCompleteMessageWithFragments, if true, causes handshake + // messages in DTLS to redundantly both fragment the message + // and include a copy of the full one. + MixCompleteMessageWithFragments bool + + // SendInvalidRecordType, if true, causes a record with an invalid + // content type to be sent immediately following the handshake. + SendInvalidRecordType bool + + // WrongCertificateMessageType, if true, causes Certificate message to + // be sent with the wrong message type. + WrongCertificateMessageType bool + + // FragmentMessageTypeMismatch, if true, causes all non-initial + // handshake fragments in DTLS to have the wrong message type. + FragmentMessageTypeMismatch bool + + // FragmentMessageLengthMismatch, if true, causes all non-initial + // handshake fragments in DTLS to have the wrong message length. + FragmentMessageLengthMismatch bool + + // SplitFragments, if non-zero, causes the handshake fragments in DTLS + // to be split across two records. The value of |SplitFragments| is the + // number of bytes in the first fragment. + SplitFragments int + + // SendEmptyFragments, if true, causes handshakes to include empty + // fragments in DTLS. + SendEmptyFragments bool + + // SendSplitAlert, if true, causes an alert to be sent with the header + // and record body split across multiple packets. The peer should + // discard these packets rather than process it. + SendSplitAlert bool + + // FailIfResumeOnRenego, if true, causes renegotiations to fail if the + // client offers a resumption or the server accepts one. + FailIfResumeOnRenego bool + + // IgnorePeerCipherPreferences, if true, causes the peer's cipher + // preferences to be ignored. + IgnorePeerCipherPreferences bool + + // IgnorePeerSignatureAlgorithmPreferences, if true, causes the peer's + // signature algorithm preferences to be ignored. + IgnorePeerSignatureAlgorithmPreferences bool + + // IgnorePeerCurvePreferences, if true, causes the peer's curve + // preferences to be ignored. + IgnorePeerCurvePreferences bool + + // BadFinished, if true, causes the Finished hash to be broken. + BadFinished bool + + // DHGroupPrime, if not nil, is used to define the (finite field) + // Diffie-Hellman group. The generator used is always two. + DHGroupPrime *big.Int + + // PackHandshakeFragments, if true, causes handshake fragments to be + // packed into individual handshake records, up to the specified record + // size. + PackHandshakeFragments int + + // PackHandshakeRecords, if true, causes handshake records to be packed + // into individual packets, up to the specified packet size. + PackHandshakeRecords int + + // EnableAllCiphersInDTLS, if true, causes RC4 to be enabled in DTLS. + EnableAllCiphersInDTLS bool + + // EmptyCertificateList, if true, causes the server to send an empty + // certificate list in the Certificate message. + EmptyCertificateList bool + + // ExpectNewTicket, if true, causes the client to abort if it does not + // receive a new ticket. + ExpectNewTicket bool + + // RequireClientHelloSize, if not zero, is the required length in bytes + // of the ClientHello /record/. This is checked by the server. + RequireClientHelloSize int + + // CustomExtension, if not empty, contains the contents of an extension + // that will be added to client/server hellos. + CustomExtension string + + // ExpectedCustomExtension, if not nil, contains the expected contents + // of a custom extension. + ExpectedCustomExtension *string + + // NoCloseNotify, if true, causes the close_notify alert to be skipped + // on connection shutdown. + NoCloseNotify bool + + // SendAlertOnShutdown, if non-zero, is the alert to send instead of + // close_notify on shutdown. + SendAlertOnShutdown alert + + // ExpectCloseNotify, if true, requires a close_notify from the peer on + // shutdown. Records from the peer received after close_notify is sent + // are not discard. + ExpectCloseNotify bool + + // SendLargeRecords, if true, allows outgoing records to be sent + // arbitrarily large. + SendLargeRecords bool + + // NegotiateALPNAndNPN, if true, causes the server to negotiate both + // ALPN and NPN in the same connetion. + NegotiateALPNAndNPN bool + + // SendEmptySessionTicket, if true, causes the server to send an empty + // session ticket. + SendEmptySessionTicket bool + + // FailIfSessionOffered, if true, causes the server to fail any + // connections where the client offers a non-empty session ID or session + // ticket. + FailIfSessionOffered bool + + // SendHelloRequestBeforeEveryAppDataRecord, if true, causes a + // HelloRequest handshake message to be sent before each application + // data record. This only makes sense for a server. + SendHelloRequestBeforeEveryAppDataRecord bool + + // RequireDHPublicValueLen causes a fatal error if the length (in + // bytes) of the server's Diffie-Hellman public value is not equal to + // this. + RequireDHPublicValueLen int + + // BadChangeCipherSpec, if not nil, is the body to be sent in + // ChangeCipherSpec records instead of {1}. + BadChangeCipherSpec []byte + + // BadHelloRequest, if not nil, is what to send instead of a + // HelloRequest. + BadHelloRequest []byte + + // RequireSessionTickets, if true, causes the client to require new + // sessions use session tickets instead of session IDs. + RequireSessionTickets bool + + // NullAllCiphers, if true, causes every cipher to behave like the null + // cipher. + NullAllCiphers bool + + // SendSCTListOnResume, if not nil, causes the server to send the + // supplied SCT list in resumption handshakes. + SendSCTListOnResume []byte + + // CECPQ1BadX25519Part corrupts the X25519 part of a CECPQ1 key exchange, as + // a trivial proof that it is actually used. + CECPQ1BadX25519Part bool + + // CECPQ1BadNewhopePart corrupts the Newhope part of a CECPQ1 key exchange, + // as a trivial proof that it is actually used. + CECPQ1BadNewhopePart bool +} + +func (c *Config) serverInit() { + if c.SessionTicketsDisabled { + return + } + + // If the key has already been set then we have nothing to do. + for _, b := range c.SessionTicketKey { + if b != 0 { + return + } + } + + if _, err := io.ReadFull(c.rand(), c.SessionTicketKey[:]); err != nil { + c.SessionTicketsDisabled = true + } +} + +func (c *Config) rand() io.Reader { + r := c.Rand + if r == nil { + return rand.Reader + } + return r +} + +func (c *Config) time() time.Time { + t := c.Time + if t == nil { + t = time.Now + } + return t() +} + +func (c *Config) cipherSuites() []uint16 { + s := c.CipherSuites + if s == nil { + s = defaultCipherSuites() + } + return s +} + +func (c *Config) minVersion() uint16 { + if c == nil || c.MinVersion == 0 { + return minVersion + } + return c.MinVersion +} + +func (c *Config) maxVersion() uint16 { + if c == nil || c.MaxVersion == 0 { + return maxVersion + } + return c.MaxVersion +} + +var defaultCurvePreferences = []CurveID{CurveX25519, CurveP256, CurveP384, CurveP521} + +func (c *Config) curvePreferences() []CurveID { + if c == nil || len(c.CurvePreferences) == 0 { + return defaultCurvePreferences + } + return c.CurvePreferences +} + +// mutualVersion returns the protocol version to use given the advertised +// version of the peer. +func (c *Config) mutualVersion(vers uint16) (uint16, bool) { + minVersion := c.minVersion() + maxVersion := c.maxVersion() + + if vers < minVersion { + return 0, false + } + if vers > maxVersion { + vers = maxVersion + } + return vers, true +} + +// getCertificateForName returns the best certificate for the given name, +// defaulting to the first element of c.Certificates if there are no good +// options. +func (c *Config) getCertificateForName(name string) *Certificate { + if len(c.Certificates) == 1 || c.NameToCertificate == nil { + // There's only one choice, so no point doing any work. + return &c.Certificates[0] + } + + name = strings.ToLower(name) + for len(name) > 0 && name[len(name)-1] == '.' { + name = name[:len(name)-1] + } + + if cert, ok := c.NameToCertificate[name]; ok { + return cert + } + + // try replacing labels in the name with wildcards until we get a + // match. + labels := strings.Split(name, ".") + for i := range labels { + labels[i] = "*" + candidate := strings.Join(labels, ".") + if cert, ok := c.NameToCertificate[candidate]; ok { + return cert + } + } + + // If nothing matches, return the first certificate. + return &c.Certificates[0] +} + +func (c *Config) signatureAndHashesForServer() []signatureAndHash { + if c != nil && c.SignatureAndHashes != nil { + return c.SignatureAndHashes + } + return supportedClientCertSignatureAlgorithms +} + +func (c *Config) signatureAndHashesForClient() []signatureAndHash { + if c != nil && c.SignatureAndHashes != nil { + return c.SignatureAndHashes + } + return supportedSKXSignatureAlgorithms +} + +// BuildNameToCertificate parses c.Certificates and builds c.NameToCertificate +// from the CommonName and SubjectAlternateName fields of each of the leaf +// certificates. +func (c *Config) BuildNameToCertificate() { + c.NameToCertificate = make(map[string]*Certificate) + for i := range c.Certificates { + cert := &c.Certificates[i] + x509Cert, err := x509.ParseCertificate(cert.Certificate[0]) + if err != nil { + continue + } + if len(x509Cert.Subject.CommonName) > 0 { + c.NameToCertificate[x509Cert.Subject.CommonName] = cert + } + for _, san := range x509Cert.DNSNames { + c.NameToCertificate[san] = cert + } + } +} + +// A Certificate is a chain of one or more certificates, leaf first. +type Certificate struct { + Certificate [][]byte + PrivateKey crypto.PrivateKey // supported types: *rsa.PrivateKey, *ecdsa.PrivateKey + // OCSPStaple contains an optional OCSP response which will be served + // to clients that request it. + OCSPStaple []byte + // SignedCertificateTimestampList contains an optional encoded + // SignedCertificateTimestampList structure which will be + // served to clients that request it. + SignedCertificateTimestampList []byte + // Leaf is the parsed form of the leaf certificate, which may be + // initialized using x509.ParseCertificate to reduce per-handshake + // processing for TLS clients doing client authentication. If nil, the + // leaf certificate will be parsed as needed. + Leaf *x509.Certificate +} + +// A TLS record. +type record struct { + contentType recordType + major, minor uint8 + payload []byte +} + +type handshakeMessage interface { + marshal() []byte + unmarshal([]byte) bool +} + +// lruSessionCache is a client or server session cache implementation +// that uses an LRU caching strategy. +type lruSessionCache struct { + sync.Mutex + + m map[string]*list.Element + q *list.List + capacity int +} + +type lruSessionCacheEntry struct { + sessionKey string + state interface{} +} + +// Put adds the provided (sessionKey, cs) pair to the cache. +func (c *lruSessionCache) Put(sessionKey string, cs interface{}) { + c.Lock() + defer c.Unlock() + + if elem, ok := c.m[sessionKey]; ok { + entry := elem.Value.(*lruSessionCacheEntry) + entry.state = cs + c.q.MoveToFront(elem) + return + } + + if c.q.Len() < c.capacity { + entry := &lruSessionCacheEntry{sessionKey, cs} + c.m[sessionKey] = c.q.PushFront(entry) + return + } + + elem := c.q.Back() + entry := elem.Value.(*lruSessionCacheEntry) + delete(c.m, entry.sessionKey) + entry.sessionKey = sessionKey + entry.state = cs + c.q.MoveToFront(elem) + c.m[sessionKey] = elem +} + +// Get returns the value associated with a given key. It returns (nil, +// false) if no value is found. +func (c *lruSessionCache) Get(sessionKey string) (interface{}, bool) { + c.Lock() + defer c.Unlock() + + if elem, ok := c.m[sessionKey]; ok { + c.q.MoveToFront(elem) + return elem.Value.(*lruSessionCacheEntry).state, true + } + return nil, false +} + +// lruClientSessionCache is a ClientSessionCache implementation that +// uses an LRU caching strategy. +type lruClientSessionCache struct { + lruSessionCache +} + +func (c *lruClientSessionCache) Put(sessionKey string, cs *ClientSessionState) { + c.lruSessionCache.Put(sessionKey, cs) +} + +func (c *lruClientSessionCache) Get(sessionKey string) (*ClientSessionState, bool) { + cs, ok := c.lruSessionCache.Get(sessionKey) + if !ok { + return nil, false + } + return cs.(*ClientSessionState), true +} + +// lruServerSessionCache is a ServerSessionCache implementation that +// uses an LRU caching strategy. +type lruServerSessionCache struct { + lruSessionCache +} + +func (c *lruServerSessionCache) Put(sessionId string, session *sessionState) { + c.lruSessionCache.Put(sessionId, session) +} + +func (c *lruServerSessionCache) Get(sessionId string) (*sessionState, bool) { + cs, ok := c.lruSessionCache.Get(sessionId) + if !ok { + return nil, false + } + return cs.(*sessionState), true +} + +// NewLRUClientSessionCache returns a ClientSessionCache with the given +// capacity that uses an LRU strategy. If capacity is < 1, a default capacity +// is used instead. +func NewLRUClientSessionCache(capacity int) ClientSessionCache { + const defaultSessionCacheCapacity = 64 + + if capacity < 1 { + capacity = defaultSessionCacheCapacity + } + return &lruClientSessionCache{ + lruSessionCache{ + m: make(map[string]*list.Element), + q: list.New(), + capacity: capacity, + }, + } +} + +// NewLRUServerSessionCache returns a ServerSessionCache with the given +// capacity that uses an LRU strategy. If capacity is < 1, a default capacity +// is used instead. +func NewLRUServerSessionCache(capacity int) ServerSessionCache { + const defaultSessionCacheCapacity = 64 + + if capacity < 1 { + capacity = defaultSessionCacheCapacity + } + return &lruServerSessionCache{ + lruSessionCache{ + m: make(map[string]*list.Element), + q: list.New(), + capacity: capacity, + }, + } +} + +// TODO(jsing): Make these available to both crypto/x509 and crypto/tls. +type dsaSignature struct { + R, S *big.Int +} + +type ecdsaSignature dsaSignature + +var emptyConfig Config + +func defaultConfig() *Config { + return &emptyConfig +} + +var ( + once sync.Once + varDefaultCipherSuites []uint16 +) + +func defaultCipherSuites() []uint16 { + once.Do(initDefaultCipherSuites) + return varDefaultCipherSuites +} + +func initDefaultCipherSuites() { + for _, suite := range cipherSuites { + if suite.flags&suitePSK == 0 { + varDefaultCipherSuites = append(varDefaultCipherSuites, suite.id) + } + } +} + +func unexpectedMessageError(wanted, got interface{}) error { + return fmt.Errorf("tls: received unexpected handshake message of type %T when waiting for %T", got, wanted) +} + +func isSupportedSignatureAndHash(sigHash signatureAndHash, sigHashes []signatureAndHash) bool { + for _, s := range sigHashes { + if s == sigHash { + return true + } + } + return false +} diff --git a/external/boringssl/ssl/test/runner/conn.go b/external/boringssl/ssl/test/runner/conn.go new file mode 100644 index 0000000000..3913995b8e --- /dev/null +++ b/external/boringssl/ssl/test/runner/conn.go @@ -0,0 +1,1451 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// TLS low level connection and record layer + +package runner + +import ( + "bytes" + "crypto/cipher" + "crypto/ecdsa" + "crypto/subtle" + "crypto/x509" + "encoding/binary" + "errors" + "fmt" + "io" + "net" + "sync" + "time" +) + +// A Conn represents a secured connection. +// It implements the net.Conn interface. +type Conn struct { + // constant + conn net.Conn + isDTLS bool + isClient bool + + // constant after handshake; protected by handshakeMutex + handshakeMutex sync.Mutex // handshakeMutex < in.Mutex, out.Mutex, errMutex + handshakeErr error // error resulting from handshake + vers uint16 // TLS version + haveVers bool // version has been negotiated + config *Config // configuration passed to constructor + handshakeComplete bool + didResume bool // whether this connection was a session resumption + extendedMasterSecret bool // whether this session used an extended master secret + cipherSuite *cipherSuite + ocspResponse []byte // stapled OCSP response + sctList []byte // signed certificate timestamp list + peerCertificates []*x509.Certificate + // verifiedChains contains the certificate chains that we built, as + // opposed to the ones presented by the server. + verifiedChains [][]*x509.Certificate + // serverName contains the server name indicated by the client, if any. + serverName string + // firstFinished contains the first Finished hash sent during the + // handshake. This is the "tls-unique" channel binding value. + firstFinished [12]byte + // clientCertSignatureHash contains the TLS hash id for the hash that + // was used by the client to sign the handshake with a client + // certificate. This is only set by a server and is zero if no client + // certificates were used. + clientCertSignatureHash uint8 + + clientRandom, serverRandom [32]byte + masterSecret [48]byte + + clientProtocol string + clientProtocolFallback bool + usedALPN bool + + // verify_data values for the renegotiation extension. + clientVerify []byte + serverVerify []byte + + channelID *ecdsa.PublicKey + + srtpProtectionProfile uint16 + + clientVersion uint16 + + // input/output + in, out halfConn // in.Mutex < out.Mutex + rawInput *block // raw input, right off the wire + input *block // application record waiting to be read + hand bytes.Buffer // handshake record waiting to be read + + // DTLS state + sendHandshakeSeq uint16 + recvHandshakeSeq uint16 + handMsg []byte // pending assembled handshake message + handMsgLen int // handshake message length, not including the header + pendingFragments [][]byte // pending outgoing handshake fragments. + + tmp [16]byte +} + +func (c *Conn) init() { + c.in.isDTLS = c.isDTLS + c.out.isDTLS = c.isDTLS + c.in.config = c.config + c.out.config = c.config + + c.out.updateOutSeq() +} + +// Access to net.Conn methods. +// Cannot just embed net.Conn because that would +// export the struct field too. + +// LocalAddr returns the local network address. +func (c *Conn) LocalAddr() net.Addr { + return c.conn.LocalAddr() +} + +// RemoteAddr returns the remote network address. +func (c *Conn) RemoteAddr() net.Addr { + return c.conn.RemoteAddr() +} + +// SetDeadline sets the read and write deadlines associated with the connection. +// A zero value for t means Read and Write will not time out. +// After a Write has timed out, the TLS state is corrupt and all future writes will return the same error. +func (c *Conn) SetDeadline(t time.Time) error { + return c.conn.SetDeadline(t) +} + +// SetReadDeadline sets the read deadline on the underlying connection. +// A zero value for t means Read will not time out. +func (c *Conn) SetReadDeadline(t time.Time) error { + return c.conn.SetReadDeadline(t) +} + +// SetWriteDeadline sets the write deadline on the underlying conneciton. +// A zero value for t means Write will not time out. +// After a Write has timed out, the TLS state is corrupt and all future writes will return the same error. +func (c *Conn) SetWriteDeadline(t time.Time) error { + return c.conn.SetWriteDeadline(t) +} + +// A halfConn represents one direction of the record layer +// connection, either sending or receiving. +type halfConn struct { + sync.Mutex + + err error // first permanent error + version uint16 // protocol version + isDTLS bool + cipher interface{} // cipher algorithm + mac macFunction + seq [8]byte // 64-bit sequence number + outSeq [8]byte // Mapped sequence number + bfree *block // list of free blocks + + nextCipher interface{} // next encryption state + nextMac macFunction // next MAC algorithm + nextSeq [6]byte // next epoch's starting sequence number in DTLS + + // used to save allocating a new buffer for each MAC. + inDigestBuf, outDigestBuf []byte + + config *Config +} + +func (hc *halfConn) setErrorLocked(err error) error { + hc.err = err + return err +} + +func (hc *halfConn) error() error { + // This should be locked, but I've removed it for the renegotiation + // tests since we don't concurrently read and write the same tls.Conn + // in any case during testing. + err := hc.err + return err +} + +// prepareCipherSpec sets the encryption and MAC states +// that a subsequent changeCipherSpec will use. +func (hc *halfConn) prepareCipherSpec(version uint16, cipher interface{}, mac macFunction) { + hc.version = version + hc.nextCipher = cipher + hc.nextMac = mac +} + +// changeCipherSpec changes the encryption and MAC states +// to the ones previously passed to prepareCipherSpec. +func (hc *halfConn) changeCipherSpec(config *Config) error { + if hc.nextCipher == nil { + return alertInternalError + } + hc.cipher = hc.nextCipher + hc.mac = hc.nextMac + hc.nextCipher = nil + hc.nextMac = nil + hc.config = config + hc.incEpoch() + + if config.Bugs.NullAllCiphers { + hc.cipher = nil + hc.mac = nil + } + return nil +} + +// incSeq increments the sequence number. +func (hc *halfConn) incSeq(isOutgoing bool) { + limit := 0 + increment := uint64(1) + if hc.isDTLS { + // Increment up to the epoch in DTLS. + limit = 2 + } + for i := 7; i >= limit; i-- { + increment += uint64(hc.seq[i]) + hc.seq[i] = byte(increment) + increment >>= 8 + } + + // Not allowed to let sequence number wrap. + // Instead, must renegotiate before it does. + // Not likely enough to bother. + if increment != 0 { + panic("TLS: sequence number wraparound") + } + + hc.updateOutSeq() +} + +// incNextSeq increments the starting sequence number for the next epoch. +func (hc *halfConn) incNextSeq() { + for i := len(hc.nextSeq) - 1; i >= 0; i-- { + hc.nextSeq[i]++ + if hc.nextSeq[i] != 0 { + return + } + } + panic("TLS: sequence number wraparound") +} + +// incEpoch resets the sequence number. In DTLS, it also increments the epoch +// half of the sequence number. +func (hc *halfConn) incEpoch() { + if hc.isDTLS { + for i := 1; i >= 0; i-- { + hc.seq[i]++ + if hc.seq[i] != 0 { + break + } + if i == 0 { + panic("TLS: epoch number wraparound") + } + } + copy(hc.seq[2:], hc.nextSeq[:]) + for i := range hc.nextSeq { + hc.nextSeq[i] = 0 + } + } else { + for i := range hc.seq { + hc.seq[i] = 0 + } + } + + hc.updateOutSeq() +} + +func (hc *halfConn) updateOutSeq() { + if hc.config.Bugs.SequenceNumberMapping != nil { + seqU64 := binary.BigEndian.Uint64(hc.seq[:]) + seqU64 = hc.config.Bugs.SequenceNumberMapping(seqU64) + binary.BigEndian.PutUint64(hc.outSeq[:], seqU64) + + // The DTLS epoch cannot be changed. + copy(hc.outSeq[:2], hc.seq[:2]) + return + } + + copy(hc.outSeq[:], hc.seq[:]) +} + +func (hc *halfConn) recordHeaderLen() int { + if hc.isDTLS { + return dtlsRecordHeaderLen + } + return tlsRecordHeaderLen +} + +// removePadding returns an unpadded slice, in constant time, which is a prefix +// of the input. It also returns a byte which is equal to 255 if the padding +// was valid and 0 otherwise. See RFC 2246, section 6.2.3.2 +func removePadding(payload []byte) ([]byte, byte) { + if len(payload) < 1 { + return payload, 0 + } + + paddingLen := payload[len(payload)-1] + t := uint(len(payload)-1) - uint(paddingLen) + // if len(payload) >= (paddingLen - 1) then the MSB of t is zero + good := byte(int32(^t) >> 31) + + toCheck := 255 // the maximum possible padding length + // The length of the padded data is public, so we can use an if here + if toCheck+1 > len(payload) { + toCheck = len(payload) - 1 + } + + for i := 0; i < toCheck; i++ { + t := uint(paddingLen) - uint(i) + // if i <= paddingLen then the MSB of t is zero + mask := byte(int32(^t) >> 31) + b := payload[len(payload)-1-i] + good &^= mask&paddingLen ^ mask&b + } + + // We AND together the bits of good and replicate the result across + // all the bits. + good &= good << 4 + good &= good << 2 + good &= good << 1 + good = uint8(int8(good) >> 7) + + toRemove := good&paddingLen + 1 + return payload[:len(payload)-int(toRemove)], good +} + +// removePaddingSSL30 is a replacement for removePadding in the case that the +// protocol version is SSLv3. In this version, the contents of the padding +// are random and cannot be checked. +func removePaddingSSL30(payload []byte) ([]byte, byte) { + if len(payload) < 1 { + return payload, 0 + } + + paddingLen := int(payload[len(payload)-1]) + 1 + if paddingLen > len(payload) { + return payload, 0 + } + + return payload[:len(payload)-paddingLen], 255 +} + +func roundUp(a, b int) int { + return a + (b-a%b)%b +} + +// cbcMode is an interface for block ciphers using cipher block chaining. +type cbcMode interface { + cipher.BlockMode + SetIV([]byte) +} + +// decrypt checks and strips the mac and decrypts the data in b. Returns a +// success boolean, the number of bytes to skip from the start of the record in +// order to get the application payload, and an optional alert value. +func (hc *halfConn) decrypt(b *block) (ok bool, prefixLen int, alertValue alert) { + recordHeaderLen := hc.recordHeaderLen() + + // pull out payload + payload := b.data[recordHeaderLen:] + + macSize := 0 + if hc.mac != nil { + macSize = hc.mac.Size() + } + + paddingGood := byte(255) + explicitIVLen := 0 + + seq := hc.seq[:] + if hc.isDTLS { + // DTLS sequence numbers are explicit. + seq = b.data[3:11] + } + + // decrypt + if hc.cipher != nil { + switch c := hc.cipher.(type) { + case cipher.Stream: + c.XORKeyStream(payload, payload) + case *tlsAead: + nonce := seq + if c.explicitNonce { + explicitIVLen = 8 + if len(payload) < explicitIVLen { + return false, 0, alertBadRecordMAC + } + nonce = payload[:8] + payload = payload[8:] + } + + var additionalData [13]byte + copy(additionalData[:], seq) + copy(additionalData[8:], b.data[:3]) + n := len(payload) - c.Overhead() + additionalData[11] = byte(n >> 8) + additionalData[12] = byte(n) + var err error + payload, err = c.Open(payload[:0], nonce, payload, additionalData[:]) + if err != nil { + return false, 0, alertBadRecordMAC + } + b.resize(recordHeaderLen + explicitIVLen + len(payload)) + case cbcMode: + blockSize := c.BlockSize() + if hc.version >= VersionTLS11 || hc.isDTLS { + explicitIVLen = blockSize + } + + if len(payload)%blockSize != 0 || len(payload) < roundUp(explicitIVLen+macSize+1, blockSize) { + return false, 0, alertBadRecordMAC + } + + if explicitIVLen > 0 { + c.SetIV(payload[:explicitIVLen]) + payload = payload[explicitIVLen:] + } + c.CryptBlocks(payload, payload) + if hc.version == VersionSSL30 { + payload, paddingGood = removePaddingSSL30(payload) + } else { + payload, paddingGood = removePadding(payload) + } + b.resize(recordHeaderLen + explicitIVLen + len(payload)) + + // note that we still have a timing side-channel in the + // MAC check, below. An attacker can align the record + // so that a correct padding will cause one less hash + // block to be calculated. Then they can iteratively + // decrypt a record by breaking each byte. See + // "Password Interception in a SSL/TLS Channel", Brice + // Canvel et al. + // + // However, our behavior matches OpenSSL, so we leak + // only as much as they do. + case nullCipher: + break + default: + panic("unknown cipher type") + } + } + + // check, strip mac + if hc.mac != nil { + if len(payload) < macSize { + return false, 0, alertBadRecordMAC + } + + // strip mac off payload, b.data + n := len(payload) - macSize + b.data[recordHeaderLen-2] = byte(n >> 8) + b.data[recordHeaderLen-1] = byte(n) + b.resize(recordHeaderLen + explicitIVLen + n) + remoteMAC := payload[n:] + localMAC := hc.mac.MAC(hc.inDigestBuf, seq, b.data[:3], b.data[recordHeaderLen-2:recordHeaderLen], payload[:n]) + + if subtle.ConstantTimeCompare(localMAC, remoteMAC) != 1 || paddingGood != 255 { + return false, 0, alertBadRecordMAC + } + hc.inDigestBuf = localMAC + } + hc.incSeq(false) + + return true, recordHeaderLen + explicitIVLen, 0 +} + +// padToBlockSize calculates the needed padding block, if any, for a payload. +// On exit, prefix aliases payload and extends to the end of the last full +// block of payload. finalBlock is a fresh slice which contains the contents of +// any suffix of payload as well as the needed padding to make finalBlock a +// full block. +func padToBlockSize(payload []byte, blockSize int, config *Config) (prefix, finalBlock []byte) { + overrun := len(payload) % blockSize + prefix = payload[:len(payload)-overrun] + + paddingLen := blockSize - overrun + finalSize := blockSize + if config.Bugs.MaxPadding { + for paddingLen+blockSize <= 256 { + paddingLen += blockSize + } + finalSize = 256 + } + finalBlock = make([]byte, finalSize) + for i := range finalBlock { + finalBlock[i] = byte(paddingLen - 1) + } + if config.Bugs.PaddingFirstByteBad || config.Bugs.PaddingFirstByteBadIf255 && paddingLen == 256 { + finalBlock[overrun] ^= 0xff + } + copy(finalBlock, payload[len(payload)-overrun:]) + return +} + +// encrypt encrypts and macs the data in b. +func (hc *halfConn) encrypt(b *block, explicitIVLen int) (bool, alert) { + recordHeaderLen := hc.recordHeaderLen() + + // mac + if hc.mac != nil { + mac := hc.mac.MAC(hc.outDigestBuf, hc.outSeq[0:], b.data[:3], b.data[recordHeaderLen-2:recordHeaderLen], b.data[recordHeaderLen+explicitIVLen:]) + + n := len(b.data) + b.resize(n + len(mac)) + copy(b.data[n:], mac) + hc.outDigestBuf = mac + } + + payload := b.data[recordHeaderLen:] + + // encrypt + if hc.cipher != nil { + switch c := hc.cipher.(type) { + case cipher.Stream: + c.XORKeyStream(payload, payload) + case *tlsAead: + payloadLen := len(b.data) - recordHeaderLen - explicitIVLen + b.resize(len(b.data) + c.Overhead()) + nonce := hc.outSeq[:] + if c.explicitNonce { + nonce = b.data[recordHeaderLen : recordHeaderLen+explicitIVLen] + } + payload := b.data[recordHeaderLen+explicitIVLen:] + payload = payload[:payloadLen] + + var additionalData [13]byte + copy(additionalData[:], hc.outSeq[:]) + copy(additionalData[8:], b.data[:3]) + additionalData[11] = byte(payloadLen >> 8) + additionalData[12] = byte(payloadLen) + + c.Seal(payload[:0], nonce, payload, additionalData[:]) + case cbcMode: + blockSize := c.BlockSize() + if explicitIVLen > 0 { + c.SetIV(payload[:explicitIVLen]) + payload = payload[explicitIVLen:] + } + prefix, finalBlock := padToBlockSize(payload, blockSize, hc.config) + b.resize(recordHeaderLen + explicitIVLen + len(prefix) + len(finalBlock)) + c.CryptBlocks(b.data[recordHeaderLen+explicitIVLen:], prefix) + c.CryptBlocks(b.data[recordHeaderLen+explicitIVLen+len(prefix):], finalBlock) + case nullCipher: + break + default: + panic("unknown cipher type") + } + } + + // update length to include MAC and any block padding needed. + n := len(b.data) - recordHeaderLen + b.data[recordHeaderLen-2] = byte(n >> 8) + b.data[recordHeaderLen-1] = byte(n) + hc.incSeq(true) + + return true, 0 +} + +// A block is a simple data buffer. +type block struct { + data []byte + off int // index for Read + link *block +} + +// resize resizes block to be n bytes, growing if necessary. +func (b *block) resize(n int) { + if n > cap(b.data) { + b.reserve(n) + } + b.data = b.data[0:n] +} + +// reserve makes sure that block contains a capacity of at least n bytes. +func (b *block) reserve(n int) { + if cap(b.data) >= n { + return + } + m := cap(b.data) + if m == 0 { + m = 1024 + } + for m < n { + m *= 2 + } + data := make([]byte, len(b.data), m) + copy(data, b.data) + b.data = data +} + +// readFromUntil reads from r into b until b contains at least n bytes +// or else returns an error. +func (b *block) readFromUntil(r io.Reader, n int) error { + // quick case + if len(b.data) >= n { + return nil + } + + // read until have enough. + b.reserve(n) + for { + m, err := r.Read(b.data[len(b.data):cap(b.data)]) + b.data = b.data[0 : len(b.data)+m] + if len(b.data) >= n { + // TODO(bradfitz,agl): slightly suspicious + // that we're throwing away r.Read's err here. + break + } + if err != nil { + return err + } + } + return nil +} + +func (b *block) Read(p []byte) (n int, err error) { + n = copy(p, b.data[b.off:]) + b.off += n + return +} + +// newBlock allocates a new block, from hc's free list if possible. +func (hc *halfConn) newBlock() *block { + b := hc.bfree + if b == nil { + return new(block) + } + hc.bfree = b.link + b.link = nil + b.resize(0) + return b +} + +// freeBlock returns a block to hc's free list. +// The protocol is such that each side only has a block or two on +// its free list at a time, so there's no need to worry about +// trimming the list, etc. +func (hc *halfConn) freeBlock(b *block) { + b.link = hc.bfree + hc.bfree = b +} + +// splitBlock splits a block after the first n bytes, +// returning a block with those n bytes and a +// block with the remainder. the latter may be nil. +func (hc *halfConn) splitBlock(b *block, n int) (*block, *block) { + if len(b.data) <= n { + return b, nil + } + bb := hc.newBlock() + bb.resize(len(b.data) - n) + copy(bb.data, b.data[n:]) + b.data = b.data[0:n] + return b, bb +} + +func (c *Conn) doReadRecord(want recordType) (recordType, *block, error) { + if c.isDTLS { + return c.dtlsDoReadRecord(want) + } + + recordHeaderLen := tlsRecordHeaderLen + + if c.rawInput == nil { + c.rawInput = c.in.newBlock() + } + b := c.rawInput + + // Read header, payload. + if err := b.readFromUntil(c.conn, recordHeaderLen); err != nil { + // RFC suggests that EOF without an alertCloseNotify is + // an error, but popular web sites seem to do this, + // so we can't make it an error, outside of tests. + if err == io.EOF && c.config.Bugs.ExpectCloseNotify { + err = io.ErrUnexpectedEOF + } + if e, ok := err.(net.Error); !ok || !e.Temporary() { + c.in.setErrorLocked(err) + } + return 0, nil, err + } + typ := recordType(b.data[0]) + + // No valid TLS record has a type of 0x80, however SSLv2 handshakes + // start with a uint16 length where the MSB is set and the first record + // is always < 256 bytes long. Therefore typ == 0x80 strongly suggests + // an SSLv2 client. + if want == recordTypeHandshake && typ == 0x80 { + c.sendAlert(alertProtocolVersion) + return 0, nil, c.in.setErrorLocked(errors.New("tls: unsupported SSLv2 handshake received")) + } + + vers := uint16(b.data[1])<<8 | uint16(b.data[2]) + n := int(b.data[3])<<8 | int(b.data[4]) + if c.haveVers { + if vers != c.vers { + c.sendAlert(alertProtocolVersion) + return 0, nil, c.in.setErrorLocked(fmt.Errorf("tls: received record with version %x when expecting version %x", vers, c.vers)) + } + } else { + if expect := c.config.Bugs.ExpectInitialRecordVersion; expect != 0 && vers != expect { + c.sendAlert(alertProtocolVersion) + return 0, nil, c.in.setErrorLocked(fmt.Errorf("tls: received record with version %x when expecting version %x", vers, expect)) + } + } + if n > maxCiphertext { + c.sendAlert(alertRecordOverflow) + return 0, nil, c.in.setErrorLocked(fmt.Errorf("tls: oversized record received with length %d", n)) + } + if !c.haveVers { + // First message, be extra suspicious: + // this might not be a TLS client. + // Bail out before reading a full 'body', if possible. + // The current max version is 3.1. + // If the version is >= 16.0, it's probably not real. + // Similarly, a clientHello message encodes in + // well under a kilobyte. If the length is >= 12 kB, + // it's probably not real. + if (typ != recordTypeAlert && typ != want) || vers >= 0x1000 || n >= 0x3000 { + c.sendAlert(alertUnexpectedMessage) + return 0, nil, c.in.setErrorLocked(fmt.Errorf("tls: first record does not look like a TLS handshake")) + } + } + if err := b.readFromUntil(c.conn, recordHeaderLen+n); err != nil { + if err == io.EOF { + err = io.ErrUnexpectedEOF + } + if e, ok := err.(net.Error); !ok || !e.Temporary() { + c.in.setErrorLocked(err) + } + return 0, nil, err + } + + // Process message. + b, c.rawInput = c.in.splitBlock(b, recordHeaderLen+n) + ok, off, err := c.in.decrypt(b) + if !ok { + c.in.setErrorLocked(c.sendAlert(err)) + } + b.off = off + return typ, b, nil +} + +// readRecord reads the next TLS record from the connection +// and updates the record layer state. +// c.in.Mutex <= L; c.input == nil. +func (c *Conn) readRecord(want recordType) error { + // Caller must be in sync with connection: + // handshake data if handshake not yet completed, + // else application data. + switch want { + default: + c.sendAlert(alertInternalError) + return c.in.setErrorLocked(errors.New("tls: unknown record type requested")) + case recordTypeHandshake, recordTypeChangeCipherSpec: + if c.handshakeComplete { + c.sendAlert(alertInternalError) + return c.in.setErrorLocked(errors.New("tls: handshake or ChangeCipherSpec requested after handshake complete")) + } + case recordTypeApplicationData: + if !c.handshakeComplete && !c.config.Bugs.ExpectFalseStart { + c.sendAlert(alertInternalError) + return c.in.setErrorLocked(errors.New("tls: application data record requested before handshake complete")) + } + case recordTypeAlert: + // Looking for a close_notify. Note: unlike a real + // implementation, this is not tolerant of additional records. + // See the documentation for ExpectCloseNotify. + } + +Again: + typ, b, err := c.doReadRecord(want) + if err != nil { + return err + } + data := b.data[b.off:] + if len(data) > maxPlaintext { + err := c.sendAlert(alertRecordOverflow) + c.in.freeBlock(b) + return c.in.setErrorLocked(err) + } + + switch typ { + default: + c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage)) + + case recordTypeAlert: + if len(data) != 2 { + c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage)) + break + } + if alert(data[1]) == alertCloseNotify { + c.in.setErrorLocked(io.EOF) + break + } + switch data[0] { + case alertLevelWarning: + // drop on the floor + c.in.freeBlock(b) + goto Again + case alertLevelError: + c.in.setErrorLocked(&net.OpError{Op: "remote error", Err: alert(data[1])}) + default: + c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage)) + } + + case recordTypeChangeCipherSpec: + if typ != want || len(data) != 1 || data[0] != 1 { + c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage)) + break + } + err := c.in.changeCipherSpec(c.config) + if err != nil { + c.in.setErrorLocked(c.sendAlert(err.(alert))) + } + + case recordTypeApplicationData: + if typ != want { + c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage)) + break + } + c.input = b + b = nil + + case recordTypeHandshake: + // TODO(rsc): Should at least pick off connection close. + if typ != want { + // A client might need to process a HelloRequest from + // the server, thus receiving a handshake message when + // application data is expected is ok. + if !c.isClient || want != recordTypeApplicationData { + return c.in.setErrorLocked(c.sendAlert(alertNoRenegotiation)) + } + } + c.hand.Write(data) + } + + if b != nil { + c.in.freeBlock(b) + } + return c.in.err +} + +// sendAlert sends a TLS alert message. +// c.out.Mutex <= L. +func (c *Conn) sendAlertLocked(level byte, err alert) error { + c.tmp[0] = level + c.tmp[1] = byte(err) + if c.config.Bugs.FragmentAlert { + c.writeRecord(recordTypeAlert, c.tmp[0:1]) + c.writeRecord(recordTypeAlert, c.tmp[1:2]) + } else if c.config.Bugs.DoubleAlert { + copy(c.tmp[2:4], c.tmp[0:2]) + c.writeRecord(recordTypeAlert, c.tmp[0:4]) + } else { + c.writeRecord(recordTypeAlert, c.tmp[0:2]) + } + // Error alerts are fatal to the connection. + if level == alertLevelError { + return c.out.setErrorLocked(&net.OpError{Op: "local error", Err: err}) + } + return nil +} + +// sendAlert sends a TLS alert message. +// L < c.out.Mutex. +func (c *Conn) sendAlert(err alert) error { + level := byte(alertLevelError) + if err == alertNoRenegotiation || err == alertCloseNotify || err == alertNoCertficate { + level = alertLevelWarning + } + return c.SendAlert(level, err) +} + +func (c *Conn) SendAlert(level byte, err alert) error { + c.out.Lock() + defer c.out.Unlock() + return c.sendAlertLocked(level, err) +} + +// writeV2Record writes a record for a V2ClientHello. +func (c *Conn) writeV2Record(data []byte) (n int, err error) { + record := make([]byte, 2+len(data)) + record[0] = uint8(len(data)>>8) | 0x80 + record[1] = uint8(len(data)) + copy(record[2:], data) + return c.conn.Write(record) +} + +// writeRecord writes a TLS record with the given type and payload +// to the connection and updates the record layer state. +// c.out.Mutex <= L. +func (c *Conn) writeRecord(typ recordType, data []byte) (n int, err error) { + if c.isDTLS { + return c.dtlsWriteRecord(typ, data) + } + + recordHeaderLen := tlsRecordHeaderLen + b := c.out.newBlock() + first := true + isClientHello := typ == recordTypeHandshake && len(data) > 0 && data[0] == typeClientHello + for len(data) > 0 || first { + m := len(data) + if m > maxPlaintext && !c.config.Bugs.SendLargeRecords { + m = maxPlaintext + } + if typ == recordTypeHandshake && c.config.Bugs.MaxHandshakeRecordLength > 0 && m > c.config.Bugs.MaxHandshakeRecordLength { + m = c.config.Bugs.MaxHandshakeRecordLength + // By default, do not fragment the client_version or + // server_version, which are located in the first 6 + // bytes. + if first && isClientHello && !c.config.Bugs.FragmentClientVersion && m < 6 { + m = 6 + } + } + explicitIVLen := 0 + explicitIVIsSeq := false + first = false + + var cbc cbcMode + if c.out.version >= VersionTLS11 { + var ok bool + if cbc, ok = c.out.cipher.(cbcMode); ok { + explicitIVLen = cbc.BlockSize() + } + } + if explicitIVLen == 0 { + if aead, ok := c.out.cipher.(*tlsAead); ok && aead.explicitNonce { + explicitIVLen = 8 + // The AES-GCM construction in TLS has an + // explicit nonce so that the nonce can be + // random. However, the nonce is only 8 bytes + // which is too small for a secure, random + // nonce. Therefore we use the sequence number + // as the nonce. + explicitIVIsSeq = true + } + } + b.resize(recordHeaderLen + explicitIVLen + m) + b.data[0] = byte(typ) + vers := c.vers + if vers == 0 { + // Some TLS servers fail if the record version is + // greater than TLS 1.0 for the initial ClientHello. + vers = VersionTLS10 + } + b.data[1] = byte(vers >> 8) + b.data[2] = byte(vers) + b.data[3] = byte(m >> 8) + b.data[4] = byte(m) + if explicitIVLen > 0 { + explicitIV := b.data[recordHeaderLen : recordHeaderLen+explicitIVLen] + if explicitIVIsSeq { + copy(explicitIV, c.out.seq[:]) + } else { + if _, err = io.ReadFull(c.config.rand(), explicitIV); err != nil { + break + } + } + } + copy(b.data[recordHeaderLen+explicitIVLen:], data) + c.out.encrypt(b, explicitIVLen) + _, err = c.conn.Write(b.data) + if err != nil { + break + } + n += m + data = data[m:] + } + c.out.freeBlock(b) + + if typ == recordTypeChangeCipherSpec { + err = c.out.changeCipherSpec(c.config) + if err != nil { + // Cannot call sendAlert directly, + // because we already hold c.out.Mutex. + c.tmp[0] = alertLevelError + c.tmp[1] = byte(err.(alert)) + c.writeRecord(recordTypeAlert, c.tmp[0:2]) + return n, c.out.setErrorLocked(&net.OpError{Op: "local error", Err: err}) + } + } + return +} + +func (c *Conn) doReadHandshake() ([]byte, error) { + if c.isDTLS { + return c.dtlsDoReadHandshake() + } + + for c.hand.Len() < 4 { + if err := c.in.err; err != nil { + return nil, err + } + if err := c.readRecord(recordTypeHandshake); err != nil { + return nil, err + } + } + + data := c.hand.Bytes() + n := int(data[1])<<16 | int(data[2])<<8 | int(data[3]) + if n > maxHandshake { + return nil, c.in.setErrorLocked(c.sendAlert(alertInternalError)) + } + for c.hand.Len() < 4+n { + if err := c.in.err; err != nil { + return nil, err + } + if err := c.readRecord(recordTypeHandshake); err != nil { + return nil, err + } + } + return c.hand.Next(4 + n), nil +} + +// readHandshake reads the next handshake message from +// the record layer. +// c.in.Mutex < L; c.out.Mutex < L. +func (c *Conn) readHandshake() (interface{}, error) { + data, err := c.doReadHandshake() + if err != nil { + return nil, err + } + + var m handshakeMessage + switch data[0] { + case typeHelloRequest: + m = new(helloRequestMsg) + case typeClientHello: + m = &clientHelloMsg{ + isDTLS: c.isDTLS, + } + case typeServerHello: + m = &serverHelloMsg{ + isDTLS: c.isDTLS, + } + case typeNewSessionTicket: + m = new(newSessionTicketMsg) + case typeCertificate: + m = new(certificateMsg) + case typeCertificateRequest: + m = &certificateRequestMsg{ + hasSignatureAndHash: c.vers >= VersionTLS12, + } + case typeCertificateStatus: + m = new(certificateStatusMsg) + case typeServerKeyExchange: + m = new(serverKeyExchangeMsg) + case typeServerHelloDone: + m = new(serverHelloDoneMsg) + case typeClientKeyExchange: + m = new(clientKeyExchangeMsg) + case typeCertificateVerify: + m = &certificateVerifyMsg{ + hasSignatureAndHash: c.vers >= VersionTLS12, + } + case typeNextProtocol: + m = new(nextProtoMsg) + case typeFinished: + m = new(finishedMsg) + case typeHelloVerifyRequest: + m = new(helloVerifyRequestMsg) + case typeEncryptedExtensions: + m = new(encryptedExtensionsMsg) + default: + return nil, c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage)) + } + + // The handshake message unmarshallers + // expect to be able to keep references to data, + // so pass in a fresh copy that won't be overwritten. + data = append([]byte(nil), data...) + + if !m.unmarshal(data) { + return nil, c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage)) + } + return m, nil +} + +// skipPacket processes all the DTLS records in packet. It updates +// sequence number expectations but otherwise ignores them. +func (c *Conn) skipPacket(packet []byte) error { + for len(packet) > 0 { + if len(packet) < 13 { + return errors.New("tls: bad packet") + } + // Dropped packets are completely ignored save to update + // expected sequence numbers for this and the next epoch. (We + // don't assert on the contents of the packets both for + // simplicity and because a previous test with one shorter + // timeout schedule would have done so.) + epoch := packet[3:5] + seq := packet[5:11] + length := uint16(packet[11])<<8 | uint16(packet[12]) + if bytes.Equal(c.in.seq[:2], epoch) { + if bytes.Compare(seq, c.in.seq[2:]) < 0 { + return errors.New("tls: sequence mismatch") + } + copy(c.in.seq[2:], seq) + c.in.incSeq(false) + } else { + if bytes.Compare(seq, c.in.nextSeq[:]) < 0 { + return errors.New("tls: sequence mismatch") + } + copy(c.in.nextSeq[:], seq) + c.in.incNextSeq() + } + if len(packet) < 13+int(length) { + return errors.New("tls: bad packet") + } + packet = packet[13+length:] + } + return nil +} + +// simulatePacketLoss simulates the loss of a handshake leg from the +// peer based on the schedule in c.config.Bugs. If resendFunc is +// non-nil, it is called after each simulated timeout to retransmit +// handshake messages from the local end. This is used in cases where +// the peer retransmits on a stale Finished rather than a timeout. +func (c *Conn) simulatePacketLoss(resendFunc func()) error { + if len(c.config.Bugs.TimeoutSchedule) == 0 { + return nil + } + if !c.isDTLS { + return errors.New("tls: TimeoutSchedule may only be set in DTLS") + } + if c.config.Bugs.PacketAdaptor == nil { + return errors.New("tls: TimeoutSchedule set without PacketAdapter") + } + for _, timeout := range c.config.Bugs.TimeoutSchedule { + // Simulate a timeout. + packets, err := c.config.Bugs.PacketAdaptor.SendReadTimeout(timeout) + if err != nil { + return err + } + for _, packet := range packets { + if err := c.skipPacket(packet); err != nil { + return err + } + } + if resendFunc != nil { + resendFunc() + } + } + return nil +} + +// Write writes data to the connection. +func (c *Conn) Write(b []byte) (int, error) { + if err := c.Handshake(); err != nil { + return 0, err + } + + c.out.Lock() + defer c.out.Unlock() + + if err := c.out.err; err != nil { + return 0, err + } + + if !c.handshakeComplete { + return 0, alertInternalError + } + + if c.config.Bugs.SendSpuriousAlert != 0 { + c.sendAlertLocked(alertLevelError, c.config.Bugs.SendSpuriousAlert) + } + + if c.config.Bugs.SendHelloRequestBeforeEveryAppDataRecord { + c.writeRecord(recordTypeHandshake, []byte{typeHelloRequest, 0, 0, 0}) + } + + // SSL 3.0 and TLS 1.0 are susceptible to a chosen-plaintext + // attack when using block mode ciphers due to predictable IVs. + // This can be prevented by splitting each Application Data + // record into two records, effectively randomizing the IV. + // + // http://www.openssl.org/~bodo/tls-cbc.txt + // https://bugzilla.mozilla.org/show_bug.cgi?id=665814 + // http://www.imperialviolet.org/2012/01/15/beastfollowup.html + + var m int + if len(b) > 1 && c.vers <= VersionTLS10 && !c.isDTLS { + if _, ok := c.out.cipher.(cipher.BlockMode); ok { + n, err := c.writeRecord(recordTypeApplicationData, b[:1]) + if err != nil { + return n, c.out.setErrorLocked(err) + } + m, b = 1, b[1:] + } + } + + n, err := c.writeRecord(recordTypeApplicationData, b) + return n + m, c.out.setErrorLocked(err) +} + +func (c *Conn) handleRenegotiation() error { + c.handshakeComplete = false + if !c.isClient { + panic("renegotiation should only happen for a client") + } + + msg, err := c.readHandshake() + if err != nil { + return err + } + _, ok := msg.(*helloRequestMsg) + if !ok { + c.sendAlert(alertUnexpectedMessage) + return alertUnexpectedMessage + } + + return c.Handshake() +} + +func (c *Conn) Renegotiate() error { + if !c.isClient { + helloReq := new(helloRequestMsg).marshal() + if c.config.Bugs.BadHelloRequest != nil { + helloReq = c.config.Bugs.BadHelloRequest + } + c.writeRecord(recordTypeHandshake, helloReq) + } + + c.handshakeComplete = false + return c.Handshake() +} + +// Read can be made to time out and return a net.Error with Timeout() == true +// after a fixed time limit; see SetDeadline and SetReadDeadline. +func (c *Conn) Read(b []byte) (n int, err error) { + if err = c.Handshake(); err != nil { + return + } + + c.in.Lock() + defer c.in.Unlock() + + // Some OpenSSL servers send empty records in order to randomize the + // CBC IV. So this loop ignores a limited number of empty records. + const maxConsecutiveEmptyRecords = 100 + for emptyRecordCount := 0; emptyRecordCount <= maxConsecutiveEmptyRecords; emptyRecordCount++ { + for c.input == nil && c.in.err == nil { + if err := c.readRecord(recordTypeApplicationData); err != nil { + // Soft error, like EAGAIN + return 0, err + } + if c.hand.Len() > 0 { + // We received handshake bytes, indicating the + // start of a renegotiation. + if err := c.handleRenegotiation(); err != nil { + return 0, err + } + continue + } + } + if err := c.in.err; err != nil { + return 0, err + } + + n, err = c.input.Read(b) + if c.input.off >= len(c.input.data) || c.isDTLS { + c.in.freeBlock(c.input) + c.input = nil + } + + // If a close-notify alert is waiting, read it so that + // we can return (n, EOF) instead of (n, nil), to signal + // to the HTTP response reading goroutine that the + // connection is now closed. This eliminates a race + // where the HTTP response reading goroutine would + // otherwise not observe the EOF until its next read, + // by which time a client goroutine might have already + // tried to reuse the HTTP connection for a new + // request. + // See https://codereview.appspot.com/76400046 + // and http://golang.org/issue/3514 + if ri := c.rawInput; ri != nil && + n != 0 && err == nil && + c.input == nil && len(ri.data) > 0 && recordType(ri.data[0]) == recordTypeAlert { + if recErr := c.readRecord(recordTypeApplicationData); recErr != nil { + err = recErr // will be io.EOF on closeNotify + } + } + + if n != 0 || err != nil { + return n, err + } + } + + return 0, io.ErrNoProgress +} + +// Close closes the connection. +func (c *Conn) Close() error { + var alertErr error + + c.handshakeMutex.Lock() + defer c.handshakeMutex.Unlock() + if c.handshakeComplete && !c.config.Bugs.NoCloseNotify { + alert := alertCloseNotify + if c.config.Bugs.SendAlertOnShutdown != 0 { + alert = c.config.Bugs.SendAlertOnShutdown + } + alertErr = c.sendAlert(alert) + // Clear local alerts when sending alerts so we continue to wait + // for the peer rather than closing the socket early. + if opErr, ok := alertErr.(*net.OpError); ok && opErr.Op == "local error" { + alertErr = nil + } + } + + // Consume a close_notify from the peer if one hasn't been received + // already. This avoids the peer from failing |SSL_shutdown| due to a + // write failing. + if c.handshakeComplete && alertErr == nil && c.config.Bugs.ExpectCloseNotify { + for c.in.error() == nil { + c.readRecord(recordTypeAlert) + } + if c.in.error() != io.EOF { + alertErr = c.in.error() + } + } + + if err := c.conn.Close(); err != nil { + return err + } + return alertErr +} + +// Handshake runs the client or server handshake +// protocol if it has not yet been run. +// Most uses of this package need not call Handshake +// explicitly: the first Read or Write will call it automatically. +func (c *Conn) Handshake() error { + c.handshakeMutex.Lock() + defer c.handshakeMutex.Unlock() + if err := c.handshakeErr; err != nil { + return err + } + if c.handshakeComplete { + return nil + } + + if c.isDTLS && c.config.Bugs.SendSplitAlert { + c.conn.Write([]byte{ + byte(recordTypeAlert), // type + 0xfe, 0xff, // version + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // sequence + 0x0, 0x2, // length + }) + c.conn.Write([]byte{alertLevelError, byte(alertInternalError)}) + } + if data := c.config.Bugs.AppDataBeforeHandshake; data != nil { + c.writeRecord(recordTypeApplicationData, data) + } + if c.isClient { + c.handshakeErr = c.clientHandshake() + } else { + c.handshakeErr = c.serverHandshake() + } + if c.handshakeErr == nil && c.config.Bugs.SendInvalidRecordType { + c.writeRecord(recordType(42), []byte("invalid record")) + } + return c.handshakeErr +} + +// ConnectionState returns basic TLS details about the connection. +func (c *Conn) ConnectionState() ConnectionState { + c.handshakeMutex.Lock() + defer c.handshakeMutex.Unlock() + + var state ConnectionState + state.HandshakeComplete = c.handshakeComplete + if c.handshakeComplete { + state.Version = c.vers + state.NegotiatedProtocol = c.clientProtocol + state.DidResume = c.didResume + state.NegotiatedProtocolIsMutual = !c.clientProtocolFallback + state.NegotiatedProtocolFromALPN = c.usedALPN + state.CipherSuite = c.cipherSuite.id + state.PeerCertificates = c.peerCertificates + state.VerifiedChains = c.verifiedChains + state.ServerName = c.serverName + state.ChannelID = c.channelID + state.SRTPProtectionProfile = c.srtpProtectionProfile + state.TLSUnique = c.firstFinished[:] + state.SCTList = c.sctList + state.ClientCertSignatureHash = c.clientCertSignatureHash + } + + return state +} + +// OCSPResponse returns the stapled OCSP response from the TLS server, if +// any. (Only valid for client connections.) +func (c *Conn) OCSPResponse() []byte { + c.handshakeMutex.Lock() + defer c.handshakeMutex.Unlock() + + return c.ocspResponse +} + +// VerifyHostname checks that the peer certificate chain is valid for +// connecting to host. If so, it returns nil; if not, it returns an error +// describing the problem. +func (c *Conn) VerifyHostname(host string) error { + c.handshakeMutex.Lock() + defer c.handshakeMutex.Unlock() + if !c.isClient { + return errors.New("tls: VerifyHostname called on TLS server connection") + } + if !c.handshakeComplete { + return errors.New("tls: handshake has not yet been performed") + } + return c.peerCertificates[0].VerifyHostname(host) +} + +// ExportKeyingMaterial exports keying material from the current connection +// state, as per RFC 5705. +func (c *Conn) ExportKeyingMaterial(length int, label, context []byte, useContext bool) ([]byte, error) { + c.handshakeMutex.Lock() + defer c.handshakeMutex.Unlock() + if !c.handshakeComplete { + return nil, errors.New("tls: handshake has not yet been performed") + } + + seedLen := len(c.clientRandom) + len(c.serverRandom) + if useContext { + seedLen += 2 + len(context) + } + seed := make([]byte, 0, seedLen) + seed = append(seed, c.clientRandom[:]...) + seed = append(seed, c.serverRandom[:]...) + if useContext { + seed = append(seed, byte(len(context)>>8), byte(len(context))) + seed = append(seed, context...) + } + result := make([]byte, length) + prfForVersion(c.vers, c.cipherSuite)(result, c.masterSecret[:], label, seed) + return result, nil +} + +// noRenegotiationInfo returns true if the renegotiation info extension +// should be supported in the current handshake. +func (c *Conn) noRenegotiationInfo() bool { + if c.config.Bugs.NoRenegotiationInfo { + return true + } + if c.cipherSuite == nil && c.config.Bugs.NoRenegotiationInfoInInitial { + return true + } + if c.cipherSuite != nil && c.config.Bugs.NoRenegotiationInfoAfterInitial { + return true + } + return false +} diff --git a/external/boringssl/ssl/test/runner/curve25519/const_amd64.s b/external/boringssl/ssl/test/runner/curve25519/const_amd64.s new file mode 100644 index 0000000000..797f9b051d --- /dev/null +++ b/external/boringssl/ssl/test/runner/curve25519/const_amd64.s @@ -0,0 +1,20 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This code was translated into a form compatible with 6a from the public +// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html + +// +build amd64,!gccgo,!appengine + +DATA ·REDMASK51(SB)/8, $0x0007FFFFFFFFFFFF +GLOBL ·REDMASK51(SB), 8, $8 + +DATA ·_121666_213(SB)/8, $996687872 +GLOBL ·_121666_213(SB), 8, $8 + +DATA ·_2P0(SB)/8, $0xFFFFFFFFFFFDA +GLOBL ·_2P0(SB), 8, $8 + +DATA ·_2P1234(SB)/8, $0xFFFFFFFFFFFFE +GLOBL ·_2P1234(SB), 8, $8 diff --git a/external/boringssl/ssl/test/runner/curve25519/cswap_amd64.s b/external/boringssl/ssl/test/runner/curve25519/cswap_amd64.s new file mode 100644 index 0000000000..45484d1b59 --- /dev/null +++ b/external/boringssl/ssl/test/runner/curve25519/cswap_amd64.s @@ -0,0 +1,88 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This code was translated into a form compatible with 6a from the public +// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html + +// +build amd64,!gccgo,!appengine + +// func cswap(inout *[5]uint64, v uint64) +TEXT ·cswap(SB),7,$0 + MOVQ inout+0(FP),DI + MOVQ v+8(FP),SI + + CMPQ SI,$1 + MOVQ 0(DI),SI + MOVQ 80(DI),DX + MOVQ 8(DI),CX + MOVQ 88(DI),R8 + MOVQ SI,R9 + CMOVQEQ DX,SI + CMOVQEQ R9,DX + MOVQ CX,R9 + CMOVQEQ R8,CX + CMOVQEQ R9,R8 + MOVQ SI,0(DI) + MOVQ DX,80(DI) + MOVQ CX,8(DI) + MOVQ R8,88(DI) + MOVQ 16(DI),SI + MOVQ 96(DI),DX + MOVQ 24(DI),CX + MOVQ 104(DI),R8 + MOVQ SI,R9 + CMOVQEQ DX,SI + CMOVQEQ R9,DX + MOVQ CX,R9 + CMOVQEQ R8,CX + CMOVQEQ R9,R8 + MOVQ SI,16(DI) + MOVQ DX,96(DI) + MOVQ CX,24(DI) + MOVQ R8,104(DI) + MOVQ 32(DI),SI + MOVQ 112(DI),DX + MOVQ 40(DI),CX + MOVQ 120(DI),R8 + MOVQ SI,R9 + CMOVQEQ DX,SI + CMOVQEQ R9,DX + MOVQ CX,R9 + CMOVQEQ R8,CX + CMOVQEQ R9,R8 + MOVQ SI,32(DI) + MOVQ DX,112(DI) + MOVQ CX,40(DI) + MOVQ R8,120(DI) + MOVQ 48(DI),SI + MOVQ 128(DI),DX + MOVQ 56(DI),CX + MOVQ 136(DI),R8 + MOVQ SI,R9 + CMOVQEQ DX,SI + CMOVQEQ R9,DX + MOVQ CX,R9 + CMOVQEQ R8,CX + CMOVQEQ R9,R8 + MOVQ SI,48(DI) + MOVQ DX,128(DI) + MOVQ CX,56(DI) + MOVQ R8,136(DI) + MOVQ 64(DI),SI + MOVQ 144(DI),DX + MOVQ 72(DI),CX + MOVQ 152(DI),R8 + MOVQ SI,R9 + CMOVQEQ DX,SI + CMOVQEQ R9,DX + MOVQ CX,R9 + CMOVQEQ R8,CX + CMOVQEQ R9,R8 + MOVQ SI,64(DI) + MOVQ DX,144(DI) + MOVQ CX,72(DI) + MOVQ R8,152(DI) + MOVQ DI,AX + MOVQ SI,DX + RET diff --git a/external/boringssl/ssl/test/runner/curve25519/curve25519.go b/external/boringssl/ssl/test/runner/curve25519/curve25519.go new file mode 100644 index 0000000000..6918c47fc2 --- /dev/null +++ b/external/boringssl/ssl/test/runner/curve25519/curve25519.go @@ -0,0 +1,841 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// We have a implementation in amd64 assembly so this code is only run on +// non-amd64 platforms. The amd64 assembly does not support gccgo. +// +build !amd64 gccgo appengine + +package curve25519 + +// This code is a port of the public domain, "ref10" implementation of +// curve25519 from SUPERCOP 20130419 by D. J. Bernstein. + +// fieldElement represents an element of the field GF(2^255 - 19). An element +// t, entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77 +// t[3]+2^102 t[4]+...+2^230 t[9]. Bounds on each t[i] vary depending on +// context. +type fieldElement [10]int32 + +func feZero(fe *fieldElement) { + for i := range fe { + fe[i] = 0 + } +} + +func feOne(fe *fieldElement) { + feZero(fe) + fe[0] = 1 +} + +func feAdd(dst, a, b *fieldElement) { + for i := range dst { + dst[i] = a[i] + b[i] + } +} + +func feSub(dst, a, b *fieldElement) { + for i := range dst { + dst[i] = a[i] - b[i] + } +} + +func feCopy(dst, src *fieldElement) { + for i := range dst { + dst[i] = src[i] + } +} + +// feCSwap replaces (f,g) with (g,f) if b == 1; replaces (f,g) with (f,g) if b == 0. +// +// Preconditions: b in {0,1}. +func feCSwap(f, g *fieldElement, b int32) { + var x fieldElement + b = -b + for i := range x { + x[i] = b & (f[i] ^ g[i]) + } + + for i := range f { + f[i] ^= x[i] + } + for i := range g { + g[i] ^= x[i] + } +} + +// load3 reads a 24-bit, little-endian value from in. +func load3(in []byte) int64 { + var r int64 + r = int64(in[0]) + r |= int64(in[1]) << 8 + r |= int64(in[2]) << 16 + return r +} + +// load4 reads a 32-bit, little-endian value from in. +func load4(in []byte) int64 { + var r int64 + r = int64(in[0]) + r |= int64(in[1]) << 8 + r |= int64(in[2]) << 16 + r |= int64(in[3]) << 24 + return r +} + +func feFromBytes(dst *fieldElement, src *[32]byte) { + h0 := load4(src[:]) + h1 := load3(src[4:]) << 6 + h2 := load3(src[7:]) << 5 + h3 := load3(src[10:]) << 3 + h4 := load3(src[13:]) << 2 + h5 := load4(src[16:]) + h6 := load3(src[20:]) << 7 + h7 := load3(src[23:]) << 5 + h8 := load3(src[26:]) << 4 + h9 := load3(src[29:]) << 2 + + var carry [10]int64 + carry[9] = (h9 + 1<<24) >> 25 + h0 += carry[9] * 19 + h9 -= carry[9] << 25 + carry[1] = (h1 + 1<<24) >> 25 + h2 += carry[1] + h1 -= carry[1] << 25 + carry[3] = (h3 + 1<<24) >> 25 + h4 += carry[3] + h3 -= carry[3] << 25 + carry[5] = (h5 + 1<<24) >> 25 + h6 += carry[5] + h5 -= carry[5] << 25 + carry[7] = (h7 + 1<<24) >> 25 + h8 += carry[7] + h7 -= carry[7] << 25 + + carry[0] = (h0 + 1<<25) >> 26 + h1 += carry[0] + h0 -= carry[0] << 26 + carry[2] = (h2 + 1<<25) >> 26 + h3 += carry[2] + h2 -= carry[2] << 26 + carry[4] = (h4 + 1<<25) >> 26 + h5 += carry[4] + h4 -= carry[4] << 26 + carry[6] = (h6 + 1<<25) >> 26 + h7 += carry[6] + h6 -= carry[6] << 26 + carry[8] = (h8 + 1<<25) >> 26 + h9 += carry[8] + h8 -= carry[8] << 26 + + dst[0] = int32(h0) + dst[1] = int32(h1) + dst[2] = int32(h2) + dst[3] = int32(h3) + dst[4] = int32(h4) + dst[5] = int32(h5) + dst[6] = int32(h6) + dst[7] = int32(h7) + dst[8] = int32(h8) + dst[9] = int32(h9) +} + +// feToBytes marshals h to s. +// Preconditions: +// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. +// +// Write p=2^255-19; q=floor(h/p). +// Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))). +// +// Proof: +// Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4. +// Also have |h-2^230 h9|<2^230 so |19 2^(-255)(h-2^230 h9)|<1/4. +// +// Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9). +// Then 0> 25 + q = (h[0] + q) >> 26 + q = (h[1] + q) >> 25 + q = (h[2] + q) >> 26 + q = (h[3] + q) >> 25 + q = (h[4] + q) >> 26 + q = (h[5] + q) >> 25 + q = (h[6] + q) >> 26 + q = (h[7] + q) >> 25 + q = (h[8] + q) >> 26 + q = (h[9] + q) >> 25 + + // Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20. + h[0] += 19 * q + // Goal: Output h-2^255 q, which is between 0 and 2^255-20. + + carry[0] = h[0] >> 26 + h[1] += carry[0] + h[0] -= carry[0] << 26 + carry[1] = h[1] >> 25 + h[2] += carry[1] + h[1] -= carry[1] << 25 + carry[2] = h[2] >> 26 + h[3] += carry[2] + h[2] -= carry[2] << 26 + carry[3] = h[3] >> 25 + h[4] += carry[3] + h[3] -= carry[3] << 25 + carry[4] = h[4] >> 26 + h[5] += carry[4] + h[4] -= carry[4] << 26 + carry[5] = h[5] >> 25 + h[6] += carry[5] + h[5] -= carry[5] << 25 + carry[6] = h[6] >> 26 + h[7] += carry[6] + h[6] -= carry[6] << 26 + carry[7] = h[7] >> 25 + h[8] += carry[7] + h[7] -= carry[7] << 25 + carry[8] = h[8] >> 26 + h[9] += carry[8] + h[8] -= carry[8] << 26 + carry[9] = h[9] >> 25 + h[9] -= carry[9] << 25 + // h10 = carry9 + + // Goal: Output h[0]+...+2^255 h10-2^255 q, which is between 0 and 2^255-20. + // Have h[0]+...+2^230 h[9] between 0 and 2^255-1; + // evidently 2^255 h10-2^255 q = 0. + // Goal: Output h[0]+...+2^230 h[9]. + + s[0] = byte(h[0] >> 0) + s[1] = byte(h[0] >> 8) + s[2] = byte(h[0] >> 16) + s[3] = byte((h[0] >> 24) | (h[1] << 2)) + s[4] = byte(h[1] >> 6) + s[5] = byte(h[1] >> 14) + s[6] = byte((h[1] >> 22) | (h[2] << 3)) + s[7] = byte(h[2] >> 5) + s[8] = byte(h[2] >> 13) + s[9] = byte((h[2] >> 21) | (h[3] << 5)) + s[10] = byte(h[3] >> 3) + s[11] = byte(h[3] >> 11) + s[12] = byte((h[3] >> 19) | (h[4] << 6)) + s[13] = byte(h[4] >> 2) + s[14] = byte(h[4] >> 10) + s[15] = byte(h[4] >> 18) + s[16] = byte(h[5] >> 0) + s[17] = byte(h[5] >> 8) + s[18] = byte(h[5] >> 16) + s[19] = byte((h[5] >> 24) | (h[6] << 1)) + s[20] = byte(h[6] >> 7) + s[21] = byte(h[6] >> 15) + s[22] = byte((h[6] >> 23) | (h[7] << 3)) + s[23] = byte(h[7] >> 5) + s[24] = byte(h[7] >> 13) + s[25] = byte((h[7] >> 21) | (h[8] << 4)) + s[26] = byte(h[8] >> 4) + s[27] = byte(h[8] >> 12) + s[28] = byte((h[8] >> 20) | (h[9] << 6)) + s[29] = byte(h[9] >> 2) + s[30] = byte(h[9] >> 10) + s[31] = byte(h[9] >> 18) +} + +// feMul calculates h = f * g +// Can overlap h with f or g. +// +// Preconditions: +// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. +// |g| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. +// +// Postconditions: +// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. +// +// Notes on implementation strategy: +// +// Using schoolbook multiplication. +// Karatsuba would save a little in some cost models. +// +// Most multiplications by 2 and 19 are 32-bit precomputations; +// cheaper than 64-bit postcomputations. +// +// There is one remaining multiplication by 19 in the carry chain; +// one *19 precomputation can be merged into this, +// but the resulting data flow is considerably less clean. +// +// There are 12 carries below. +// 10 of them are 2-way parallelizable and vectorizable. +// Can get away with 11 carries, but then data flow is much deeper. +// +// With tighter constraints on inputs can squeeze carries into int32. +func feMul(h, f, g *fieldElement) { + f0 := f[0] + f1 := f[1] + f2 := f[2] + f3 := f[3] + f4 := f[4] + f5 := f[5] + f6 := f[6] + f7 := f[7] + f8 := f[8] + f9 := f[9] + g0 := g[0] + g1 := g[1] + g2 := g[2] + g3 := g[3] + g4 := g[4] + g5 := g[5] + g6 := g[6] + g7 := g[7] + g8 := g[8] + g9 := g[9] + g1_19 := 19 * g1 // 1.4*2^29 + g2_19 := 19 * g2 // 1.4*2^30; still ok + g3_19 := 19 * g3 + g4_19 := 19 * g4 + g5_19 := 19 * g5 + g6_19 := 19 * g6 + g7_19 := 19 * g7 + g8_19 := 19 * g8 + g9_19 := 19 * g9 + f1_2 := 2 * f1 + f3_2 := 2 * f3 + f5_2 := 2 * f5 + f7_2 := 2 * f7 + f9_2 := 2 * f9 + f0g0 := int64(f0) * int64(g0) + f0g1 := int64(f0) * int64(g1) + f0g2 := int64(f0) * int64(g2) + f0g3 := int64(f0) * int64(g3) + f0g4 := int64(f0) * int64(g4) + f0g5 := int64(f0) * int64(g5) + f0g6 := int64(f0) * int64(g6) + f0g7 := int64(f0) * int64(g7) + f0g8 := int64(f0) * int64(g8) + f0g9 := int64(f0) * int64(g9) + f1g0 := int64(f1) * int64(g0) + f1g1_2 := int64(f1_2) * int64(g1) + f1g2 := int64(f1) * int64(g2) + f1g3_2 := int64(f1_2) * int64(g3) + f1g4 := int64(f1) * int64(g4) + f1g5_2 := int64(f1_2) * int64(g5) + f1g6 := int64(f1) * int64(g6) + f1g7_2 := int64(f1_2) * int64(g7) + f1g8 := int64(f1) * int64(g8) + f1g9_38 := int64(f1_2) * int64(g9_19) + f2g0 := int64(f2) * int64(g0) + f2g1 := int64(f2) * int64(g1) + f2g2 := int64(f2) * int64(g2) + f2g3 := int64(f2) * int64(g3) + f2g4 := int64(f2) * int64(g4) + f2g5 := int64(f2) * int64(g5) + f2g6 := int64(f2) * int64(g6) + f2g7 := int64(f2) * int64(g7) + f2g8_19 := int64(f2) * int64(g8_19) + f2g9_19 := int64(f2) * int64(g9_19) + f3g0 := int64(f3) * int64(g0) + f3g1_2 := int64(f3_2) * int64(g1) + f3g2 := int64(f3) * int64(g2) + f3g3_2 := int64(f3_2) * int64(g3) + f3g4 := int64(f3) * int64(g4) + f3g5_2 := int64(f3_2) * int64(g5) + f3g6 := int64(f3) * int64(g6) + f3g7_38 := int64(f3_2) * int64(g7_19) + f3g8_19 := int64(f3) * int64(g8_19) + f3g9_38 := int64(f3_2) * int64(g9_19) + f4g0 := int64(f4) * int64(g0) + f4g1 := int64(f4) * int64(g1) + f4g2 := int64(f4) * int64(g2) + f4g3 := int64(f4) * int64(g3) + f4g4 := int64(f4) * int64(g4) + f4g5 := int64(f4) * int64(g5) + f4g6_19 := int64(f4) * int64(g6_19) + f4g7_19 := int64(f4) * int64(g7_19) + f4g8_19 := int64(f4) * int64(g8_19) + f4g9_19 := int64(f4) * int64(g9_19) + f5g0 := int64(f5) * int64(g0) + f5g1_2 := int64(f5_2) * int64(g1) + f5g2 := int64(f5) * int64(g2) + f5g3_2 := int64(f5_2) * int64(g3) + f5g4 := int64(f5) * int64(g4) + f5g5_38 := int64(f5_2) * int64(g5_19) + f5g6_19 := int64(f5) * int64(g6_19) + f5g7_38 := int64(f5_2) * int64(g7_19) + f5g8_19 := int64(f5) * int64(g8_19) + f5g9_38 := int64(f5_2) * int64(g9_19) + f6g0 := int64(f6) * int64(g0) + f6g1 := int64(f6) * int64(g1) + f6g2 := int64(f6) * int64(g2) + f6g3 := int64(f6) * int64(g3) + f6g4_19 := int64(f6) * int64(g4_19) + f6g5_19 := int64(f6) * int64(g5_19) + f6g6_19 := int64(f6) * int64(g6_19) + f6g7_19 := int64(f6) * int64(g7_19) + f6g8_19 := int64(f6) * int64(g8_19) + f6g9_19 := int64(f6) * int64(g9_19) + f7g0 := int64(f7) * int64(g0) + f7g1_2 := int64(f7_2) * int64(g1) + f7g2 := int64(f7) * int64(g2) + f7g3_38 := int64(f7_2) * int64(g3_19) + f7g4_19 := int64(f7) * int64(g4_19) + f7g5_38 := int64(f7_2) * int64(g5_19) + f7g6_19 := int64(f7) * int64(g6_19) + f7g7_38 := int64(f7_2) * int64(g7_19) + f7g8_19 := int64(f7) * int64(g8_19) + f7g9_38 := int64(f7_2) * int64(g9_19) + f8g0 := int64(f8) * int64(g0) + f8g1 := int64(f8) * int64(g1) + f8g2_19 := int64(f8) * int64(g2_19) + f8g3_19 := int64(f8) * int64(g3_19) + f8g4_19 := int64(f8) * int64(g4_19) + f8g5_19 := int64(f8) * int64(g5_19) + f8g6_19 := int64(f8) * int64(g6_19) + f8g7_19 := int64(f8) * int64(g7_19) + f8g8_19 := int64(f8) * int64(g8_19) + f8g9_19 := int64(f8) * int64(g9_19) + f9g0 := int64(f9) * int64(g0) + f9g1_38 := int64(f9_2) * int64(g1_19) + f9g2_19 := int64(f9) * int64(g2_19) + f9g3_38 := int64(f9_2) * int64(g3_19) + f9g4_19 := int64(f9) * int64(g4_19) + f9g5_38 := int64(f9_2) * int64(g5_19) + f9g6_19 := int64(f9) * int64(g6_19) + f9g7_38 := int64(f9_2) * int64(g7_19) + f9g8_19 := int64(f9) * int64(g8_19) + f9g9_38 := int64(f9_2) * int64(g9_19) + h0 := f0g0 + f1g9_38 + f2g8_19 + f3g7_38 + f4g6_19 + f5g5_38 + f6g4_19 + f7g3_38 + f8g2_19 + f9g1_38 + h1 := f0g1 + f1g0 + f2g9_19 + f3g8_19 + f4g7_19 + f5g6_19 + f6g5_19 + f7g4_19 + f8g3_19 + f9g2_19 + h2 := f0g2 + f1g1_2 + f2g0 + f3g9_38 + f4g8_19 + f5g7_38 + f6g6_19 + f7g5_38 + f8g4_19 + f9g3_38 + h3 := f0g3 + f1g2 + f2g1 + f3g0 + f4g9_19 + f5g8_19 + f6g7_19 + f7g6_19 + f8g5_19 + f9g4_19 + h4 := f0g4 + f1g3_2 + f2g2 + f3g1_2 + f4g0 + f5g9_38 + f6g8_19 + f7g7_38 + f8g6_19 + f9g5_38 + h5 := f0g5 + f1g4 + f2g3 + f3g2 + f4g1 + f5g0 + f6g9_19 + f7g8_19 + f8g7_19 + f9g6_19 + h6 := f0g6 + f1g5_2 + f2g4 + f3g3_2 + f4g2 + f5g1_2 + f6g0 + f7g9_38 + f8g8_19 + f9g7_38 + h7 := f0g7 + f1g6 + f2g5 + f3g4 + f4g3 + f5g2 + f6g1 + f7g0 + f8g9_19 + f9g8_19 + h8 := f0g8 + f1g7_2 + f2g6 + f3g5_2 + f4g4 + f5g3_2 + f6g2 + f7g1_2 + f8g0 + f9g9_38 + h9 := f0g9 + f1g8 + f2g7 + f3g6 + f4g5 + f5g4 + f6g3 + f7g2 + f8g1 + f9g0 + var carry [10]int64 + + // |h0| <= (1.1*1.1*2^52*(1+19+19+19+19)+1.1*1.1*2^50*(38+38+38+38+38)) + // i.e. |h0| <= 1.2*2^59; narrower ranges for h2, h4, h6, h8 + // |h1| <= (1.1*1.1*2^51*(1+1+19+19+19+19+19+19+19+19)) + // i.e. |h1| <= 1.5*2^58; narrower ranges for h3, h5, h7, h9 + + carry[0] = (h0 + (1 << 25)) >> 26 + h1 += carry[0] + h0 -= carry[0] << 26 + carry[4] = (h4 + (1 << 25)) >> 26 + h5 += carry[4] + h4 -= carry[4] << 26 + // |h0| <= 2^25 + // |h4| <= 2^25 + // |h1| <= 1.51*2^58 + // |h5| <= 1.51*2^58 + + carry[1] = (h1 + (1 << 24)) >> 25 + h2 += carry[1] + h1 -= carry[1] << 25 + carry[5] = (h5 + (1 << 24)) >> 25 + h6 += carry[5] + h5 -= carry[5] << 25 + // |h1| <= 2^24; from now on fits into int32 + // |h5| <= 2^24; from now on fits into int32 + // |h2| <= 1.21*2^59 + // |h6| <= 1.21*2^59 + + carry[2] = (h2 + (1 << 25)) >> 26 + h3 += carry[2] + h2 -= carry[2] << 26 + carry[6] = (h6 + (1 << 25)) >> 26 + h7 += carry[6] + h6 -= carry[6] << 26 + // |h2| <= 2^25; from now on fits into int32 unchanged + // |h6| <= 2^25; from now on fits into int32 unchanged + // |h3| <= 1.51*2^58 + // |h7| <= 1.51*2^58 + + carry[3] = (h3 + (1 << 24)) >> 25 + h4 += carry[3] + h3 -= carry[3] << 25 + carry[7] = (h7 + (1 << 24)) >> 25 + h8 += carry[7] + h7 -= carry[7] << 25 + // |h3| <= 2^24; from now on fits into int32 unchanged + // |h7| <= 2^24; from now on fits into int32 unchanged + // |h4| <= 1.52*2^33 + // |h8| <= 1.52*2^33 + + carry[4] = (h4 + (1 << 25)) >> 26 + h5 += carry[4] + h4 -= carry[4] << 26 + carry[8] = (h8 + (1 << 25)) >> 26 + h9 += carry[8] + h8 -= carry[8] << 26 + // |h4| <= 2^25; from now on fits into int32 unchanged + // |h8| <= 2^25; from now on fits into int32 unchanged + // |h5| <= 1.01*2^24 + // |h9| <= 1.51*2^58 + + carry[9] = (h9 + (1 << 24)) >> 25 + h0 += carry[9] * 19 + h9 -= carry[9] << 25 + // |h9| <= 2^24; from now on fits into int32 unchanged + // |h0| <= 1.8*2^37 + + carry[0] = (h0 + (1 << 25)) >> 26 + h1 += carry[0] + h0 -= carry[0] << 26 + // |h0| <= 2^25; from now on fits into int32 unchanged + // |h1| <= 1.01*2^24 + + h[0] = int32(h0) + h[1] = int32(h1) + h[2] = int32(h2) + h[3] = int32(h3) + h[4] = int32(h4) + h[5] = int32(h5) + h[6] = int32(h6) + h[7] = int32(h7) + h[8] = int32(h8) + h[9] = int32(h9) +} + +// feSquare calculates h = f*f. Can overlap h with f. +// +// Preconditions: +// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. +// +// Postconditions: +// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. +func feSquare(h, f *fieldElement) { + f0 := f[0] + f1 := f[1] + f2 := f[2] + f3 := f[3] + f4 := f[4] + f5 := f[5] + f6 := f[6] + f7 := f[7] + f8 := f[8] + f9 := f[9] + f0_2 := 2 * f0 + f1_2 := 2 * f1 + f2_2 := 2 * f2 + f3_2 := 2 * f3 + f4_2 := 2 * f4 + f5_2 := 2 * f5 + f6_2 := 2 * f6 + f7_2 := 2 * f7 + f5_38 := 38 * f5 // 1.31*2^30 + f6_19 := 19 * f6 // 1.31*2^30 + f7_38 := 38 * f7 // 1.31*2^30 + f8_19 := 19 * f8 // 1.31*2^30 + f9_38 := 38 * f9 // 1.31*2^30 + f0f0 := int64(f0) * int64(f0) + f0f1_2 := int64(f0_2) * int64(f1) + f0f2_2 := int64(f0_2) * int64(f2) + f0f3_2 := int64(f0_2) * int64(f3) + f0f4_2 := int64(f0_2) * int64(f4) + f0f5_2 := int64(f0_2) * int64(f5) + f0f6_2 := int64(f0_2) * int64(f6) + f0f7_2 := int64(f0_2) * int64(f7) + f0f8_2 := int64(f0_2) * int64(f8) + f0f9_2 := int64(f0_2) * int64(f9) + f1f1_2 := int64(f1_2) * int64(f1) + f1f2_2 := int64(f1_2) * int64(f2) + f1f3_4 := int64(f1_2) * int64(f3_2) + f1f4_2 := int64(f1_2) * int64(f4) + f1f5_4 := int64(f1_2) * int64(f5_2) + f1f6_2 := int64(f1_2) * int64(f6) + f1f7_4 := int64(f1_2) * int64(f7_2) + f1f8_2 := int64(f1_2) * int64(f8) + f1f9_76 := int64(f1_2) * int64(f9_38) + f2f2 := int64(f2) * int64(f2) + f2f3_2 := int64(f2_2) * int64(f3) + f2f4_2 := int64(f2_2) * int64(f4) + f2f5_2 := int64(f2_2) * int64(f5) + f2f6_2 := int64(f2_2) * int64(f6) + f2f7_2 := int64(f2_2) * int64(f7) + f2f8_38 := int64(f2_2) * int64(f8_19) + f2f9_38 := int64(f2) * int64(f9_38) + f3f3_2 := int64(f3_2) * int64(f3) + f3f4_2 := int64(f3_2) * int64(f4) + f3f5_4 := int64(f3_2) * int64(f5_2) + f3f6_2 := int64(f3_2) * int64(f6) + f3f7_76 := int64(f3_2) * int64(f7_38) + f3f8_38 := int64(f3_2) * int64(f8_19) + f3f9_76 := int64(f3_2) * int64(f9_38) + f4f4 := int64(f4) * int64(f4) + f4f5_2 := int64(f4_2) * int64(f5) + f4f6_38 := int64(f4_2) * int64(f6_19) + f4f7_38 := int64(f4) * int64(f7_38) + f4f8_38 := int64(f4_2) * int64(f8_19) + f4f9_38 := int64(f4) * int64(f9_38) + f5f5_38 := int64(f5) * int64(f5_38) + f5f6_38 := int64(f5_2) * int64(f6_19) + f5f7_76 := int64(f5_2) * int64(f7_38) + f5f8_38 := int64(f5_2) * int64(f8_19) + f5f9_76 := int64(f5_2) * int64(f9_38) + f6f6_19 := int64(f6) * int64(f6_19) + f6f7_38 := int64(f6) * int64(f7_38) + f6f8_38 := int64(f6_2) * int64(f8_19) + f6f9_38 := int64(f6) * int64(f9_38) + f7f7_38 := int64(f7) * int64(f7_38) + f7f8_38 := int64(f7_2) * int64(f8_19) + f7f9_76 := int64(f7_2) * int64(f9_38) + f8f8_19 := int64(f8) * int64(f8_19) + f8f9_38 := int64(f8) * int64(f9_38) + f9f9_38 := int64(f9) * int64(f9_38) + h0 := f0f0 + f1f9_76 + f2f8_38 + f3f7_76 + f4f6_38 + f5f5_38 + h1 := f0f1_2 + f2f9_38 + f3f8_38 + f4f7_38 + f5f6_38 + h2 := f0f2_2 + f1f1_2 + f3f9_76 + f4f8_38 + f5f7_76 + f6f6_19 + h3 := f0f3_2 + f1f2_2 + f4f9_38 + f5f8_38 + f6f7_38 + h4 := f0f4_2 + f1f3_4 + f2f2 + f5f9_76 + f6f8_38 + f7f7_38 + h5 := f0f5_2 + f1f4_2 + f2f3_2 + f6f9_38 + f7f8_38 + h6 := f0f6_2 + f1f5_4 + f2f4_2 + f3f3_2 + f7f9_76 + f8f8_19 + h7 := f0f7_2 + f1f6_2 + f2f5_2 + f3f4_2 + f8f9_38 + h8 := f0f8_2 + f1f7_4 + f2f6_2 + f3f5_4 + f4f4 + f9f9_38 + h9 := f0f9_2 + f1f8_2 + f2f7_2 + f3f6_2 + f4f5_2 + var carry [10]int64 + + carry[0] = (h0 + (1 << 25)) >> 26 + h1 += carry[0] + h0 -= carry[0] << 26 + carry[4] = (h4 + (1 << 25)) >> 26 + h5 += carry[4] + h4 -= carry[4] << 26 + + carry[1] = (h1 + (1 << 24)) >> 25 + h2 += carry[1] + h1 -= carry[1] << 25 + carry[5] = (h5 + (1 << 24)) >> 25 + h6 += carry[5] + h5 -= carry[5] << 25 + + carry[2] = (h2 + (1 << 25)) >> 26 + h3 += carry[2] + h2 -= carry[2] << 26 + carry[6] = (h6 + (1 << 25)) >> 26 + h7 += carry[6] + h6 -= carry[6] << 26 + + carry[3] = (h3 + (1 << 24)) >> 25 + h4 += carry[3] + h3 -= carry[3] << 25 + carry[7] = (h7 + (1 << 24)) >> 25 + h8 += carry[7] + h7 -= carry[7] << 25 + + carry[4] = (h4 + (1 << 25)) >> 26 + h5 += carry[4] + h4 -= carry[4] << 26 + carry[8] = (h8 + (1 << 25)) >> 26 + h9 += carry[8] + h8 -= carry[8] << 26 + + carry[9] = (h9 + (1 << 24)) >> 25 + h0 += carry[9] * 19 + h9 -= carry[9] << 25 + + carry[0] = (h0 + (1 << 25)) >> 26 + h1 += carry[0] + h0 -= carry[0] << 26 + + h[0] = int32(h0) + h[1] = int32(h1) + h[2] = int32(h2) + h[3] = int32(h3) + h[4] = int32(h4) + h[5] = int32(h5) + h[6] = int32(h6) + h[7] = int32(h7) + h[8] = int32(h8) + h[9] = int32(h9) +} + +// feMul121666 calculates h = f * 121666. Can overlap h with f. +// +// Preconditions: +// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. +// +// Postconditions: +// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. +func feMul121666(h, f *fieldElement) { + h0 := int64(f[0]) * 121666 + h1 := int64(f[1]) * 121666 + h2 := int64(f[2]) * 121666 + h3 := int64(f[3]) * 121666 + h4 := int64(f[4]) * 121666 + h5 := int64(f[5]) * 121666 + h6 := int64(f[6]) * 121666 + h7 := int64(f[7]) * 121666 + h8 := int64(f[8]) * 121666 + h9 := int64(f[9]) * 121666 + var carry [10]int64 + + carry[9] = (h9 + (1 << 24)) >> 25 + h0 += carry[9] * 19 + h9 -= carry[9] << 25 + carry[1] = (h1 + (1 << 24)) >> 25 + h2 += carry[1] + h1 -= carry[1] << 25 + carry[3] = (h3 + (1 << 24)) >> 25 + h4 += carry[3] + h3 -= carry[3] << 25 + carry[5] = (h5 + (1 << 24)) >> 25 + h6 += carry[5] + h5 -= carry[5] << 25 + carry[7] = (h7 + (1 << 24)) >> 25 + h8 += carry[7] + h7 -= carry[7] << 25 + + carry[0] = (h0 + (1 << 25)) >> 26 + h1 += carry[0] + h0 -= carry[0] << 26 + carry[2] = (h2 + (1 << 25)) >> 26 + h3 += carry[2] + h2 -= carry[2] << 26 + carry[4] = (h4 + (1 << 25)) >> 26 + h5 += carry[4] + h4 -= carry[4] << 26 + carry[6] = (h6 + (1 << 25)) >> 26 + h7 += carry[6] + h6 -= carry[6] << 26 + carry[8] = (h8 + (1 << 25)) >> 26 + h9 += carry[8] + h8 -= carry[8] << 26 + + h[0] = int32(h0) + h[1] = int32(h1) + h[2] = int32(h2) + h[3] = int32(h3) + h[4] = int32(h4) + h[5] = int32(h5) + h[6] = int32(h6) + h[7] = int32(h7) + h[8] = int32(h8) + h[9] = int32(h9) +} + +// feInvert sets out = z^-1. +func feInvert(out, z *fieldElement) { + var t0, t1, t2, t3 fieldElement + var i int + + feSquare(&t0, z) + for i = 1; i < 1; i++ { + feSquare(&t0, &t0) + } + feSquare(&t1, &t0) + for i = 1; i < 2; i++ { + feSquare(&t1, &t1) + } + feMul(&t1, z, &t1) + feMul(&t0, &t0, &t1) + feSquare(&t2, &t0) + for i = 1; i < 1; i++ { + feSquare(&t2, &t2) + } + feMul(&t1, &t1, &t2) + feSquare(&t2, &t1) + for i = 1; i < 5; i++ { + feSquare(&t2, &t2) + } + feMul(&t1, &t2, &t1) + feSquare(&t2, &t1) + for i = 1; i < 10; i++ { + feSquare(&t2, &t2) + } + feMul(&t2, &t2, &t1) + feSquare(&t3, &t2) + for i = 1; i < 20; i++ { + feSquare(&t3, &t3) + } + feMul(&t2, &t3, &t2) + feSquare(&t2, &t2) + for i = 1; i < 10; i++ { + feSquare(&t2, &t2) + } + feMul(&t1, &t2, &t1) + feSquare(&t2, &t1) + for i = 1; i < 50; i++ { + feSquare(&t2, &t2) + } + feMul(&t2, &t2, &t1) + feSquare(&t3, &t2) + for i = 1; i < 100; i++ { + feSquare(&t3, &t3) + } + feMul(&t2, &t3, &t2) + feSquare(&t2, &t2) + for i = 1; i < 50; i++ { + feSquare(&t2, &t2) + } + feMul(&t1, &t2, &t1) + feSquare(&t1, &t1) + for i = 1; i < 5; i++ { + feSquare(&t1, &t1) + } + feMul(out, &t1, &t0) +} + +func scalarMult(out, in, base *[32]byte) { + var e [32]byte + + copy(e[:], in[:]) + e[0] &= 248 + e[31] &= 127 + e[31] |= 64 + + var x1, x2, z2, x3, z3, tmp0, tmp1 fieldElement + feFromBytes(&x1, base) + feOne(&x2) + feCopy(&x3, &x1) + feOne(&z3) + + swap := int32(0) + for pos := 254; pos >= 0; pos-- { + b := e[pos/8] >> uint(pos&7) + b &= 1 + swap ^= int32(b) + feCSwap(&x2, &x3, swap) + feCSwap(&z2, &z3, swap) + swap = int32(b) + + feSub(&tmp0, &x3, &z3) + feSub(&tmp1, &x2, &z2) + feAdd(&x2, &x2, &z2) + feAdd(&z2, &x3, &z3) + feMul(&z3, &tmp0, &x2) + feMul(&z2, &z2, &tmp1) + feSquare(&tmp0, &tmp1) + feSquare(&tmp1, &x2) + feAdd(&x3, &z3, &z2) + feSub(&z2, &z3, &z2) + feMul(&x2, &tmp1, &tmp0) + feSub(&tmp1, &tmp1, &tmp0) + feSquare(&z2, &z2) + feMul121666(&z3, &tmp1) + feSquare(&x3, &x3) + feAdd(&tmp0, &tmp0, &z3) + feMul(&z3, &x1, &z2) + feMul(&z2, &tmp1, &tmp0) + } + + feCSwap(&x2, &x3, swap) + feCSwap(&z2, &z3, swap) + + feInvert(&z2, &z2) + feMul(&x2, &x2, &z2) + feToBytes(out, &x2) +} diff --git a/external/boringssl/ssl/test/runner/curve25519/curve25519_test.go b/external/boringssl/ssl/test/runner/curve25519/curve25519_test.go new file mode 100644 index 0000000000..14b0ee87cd --- /dev/null +++ b/external/boringssl/ssl/test/runner/curve25519/curve25519_test.go @@ -0,0 +1,29 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package curve25519 + +import ( + "fmt" + "testing" +) + +const expectedHex = "89161fde887b2b53de549af483940106ecc114d6982daa98256de23bdf77661a" + +func TestBaseScalarMult(t *testing.T) { + var a, b [32]byte + in := &a + out := &b + a[0] = 1 + + for i := 0; i < 200; i++ { + ScalarBaseMult(out, in) + in, out = out, in + } + + result := fmt.Sprintf("%x", in[:]) + if result != expectedHex { + t.Errorf("incorrect result: got %s, want %s", result, expectedHex) + } +} diff --git a/external/boringssl/ssl/test/runner/curve25519/doc.go b/external/boringssl/ssl/test/runner/curve25519/doc.go new file mode 100644 index 0000000000..ebeea3c2d6 --- /dev/null +++ b/external/boringssl/ssl/test/runner/curve25519/doc.go @@ -0,0 +1,23 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package curve25519 provides an implementation of scalar multiplication on +// the elliptic curve known as curve25519. See http://cr.yp.to/ecdh.html +package curve25519 // import "golang.org/x/crypto/curve25519" + +// basePoint is the x coordinate of the generator of the curve. +var basePoint = [32]byte{9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + +// ScalarMult sets dst to the product in*base where dst and base are the x +// coordinates of group points and all values are in little-endian form. +func ScalarMult(dst, in, base *[32]byte) { + scalarMult(dst, in, base) +} + +// ScalarBaseMult sets dst to the product in*base where dst and base are the x +// coordinates of group points, base is the standard generator and all values +// are in little-endian form. +func ScalarBaseMult(dst, in *[32]byte) { + ScalarMult(dst, in, &basePoint) +} diff --git a/external/boringssl/ssl/test/runner/curve25519/freeze_amd64.s b/external/boringssl/ssl/test/runner/curve25519/freeze_amd64.s new file mode 100644 index 0000000000..37599fac04 --- /dev/null +++ b/external/boringssl/ssl/test/runner/curve25519/freeze_amd64.s @@ -0,0 +1,94 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This code was translated into a form compatible with 6a from the public +// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html + +// +build amd64,!gccgo,!appengine + +// func freeze(inout *[5]uint64) +TEXT ·freeze(SB),7,$96-8 + MOVQ inout+0(FP), DI + + MOVQ SP,R11 + MOVQ $31,CX + NOTQ CX + ANDQ CX,SP + ADDQ $32,SP + + MOVQ R11,0(SP) + MOVQ R12,8(SP) + MOVQ R13,16(SP) + MOVQ R14,24(SP) + MOVQ R15,32(SP) + MOVQ BX,40(SP) + MOVQ BP,48(SP) + MOVQ 0(DI),SI + MOVQ 8(DI),DX + MOVQ 16(DI),CX + MOVQ 24(DI),R8 + MOVQ 32(DI),R9 + MOVQ ·REDMASK51(SB),AX + MOVQ AX,R10 + SUBQ $18,R10 + MOVQ $3,R11 +REDUCELOOP: + MOVQ SI,R12 + SHRQ $51,R12 + ANDQ AX,SI + ADDQ R12,DX + MOVQ DX,R12 + SHRQ $51,R12 + ANDQ AX,DX + ADDQ R12,CX + MOVQ CX,R12 + SHRQ $51,R12 + ANDQ AX,CX + ADDQ R12,R8 + MOVQ R8,R12 + SHRQ $51,R12 + ANDQ AX,R8 + ADDQ R12,R9 + MOVQ R9,R12 + SHRQ $51,R12 + ANDQ AX,R9 + IMUL3Q $19,R12,R12 + ADDQ R12,SI + SUBQ $1,R11 + JA REDUCELOOP + MOVQ $1,R12 + CMPQ R10,SI + CMOVQLT R11,R12 + CMPQ AX,DX + CMOVQNE R11,R12 + CMPQ AX,CX + CMOVQNE R11,R12 + CMPQ AX,R8 + CMOVQNE R11,R12 + CMPQ AX,R9 + CMOVQNE R11,R12 + NEGQ R12 + ANDQ R12,AX + ANDQ R12,R10 + SUBQ R10,SI + SUBQ AX,DX + SUBQ AX,CX + SUBQ AX,R8 + SUBQ AX,R9 + MOVQ SI,0(DI) + MOVQ DX,8(DI) + MOVQ CX,16(DI) + MOVQ R8,24(DI) + MOVQ R9,32(DI) + MOVQ 0(SP),R11 + MOVQ 8(SP),R12 + MOVQ 16(SP),R13 + MOVQ 24(SP),R14 + MOVQ 32(SP),R15 + MOVQ 40(SP),BX + MOVQ 48(SP),BP + MOVQ R11,SP + MOVQ DI,AX + MOVQ SI,DX + RET diff --git a/external/boringssl/ssl/test/runner/curve25519/ladderstep_amd64.s b/external/boringssl/ssl/test/runner/curve25519/ladderstep_amd64.s new file mode 100644 index 0000000000..3949f9cfaf --- /dev/null +++ b/external/boringssl/ssl/test/runner/curve25519/ladderstep_amd64.s @@ -0,0 +1,1398 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This code was translated into a form compatible with 6a from the public +// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html + +// +build amd64,!gccgo,!appengine + +// func ladderstep(inout *[5][5]uint64) +TEXT ·ladderstep(SB),0,$384-8 + MOVQ inout+0(FP),DI + + MOVQ SP,R11 + MOVQ $31,CX + NOTQ CX + ANDQ CX,SP + ADDQ $32,SP + + MOVQ R11,0(SP) + MOVQ R12,8(SP) + MOVQ R13,16(SP) + MOVQ R14,24(SP) + MOVQ R15,32(SP) + MOVQ BX,40(SP) + MOVQ BP,48(SP) + MOVQ 40(DI),SI + MOVQ 48(DI),DX + MOVQ 56(DI),CX + MOVQ 64(DI),R8 + MOVQ 72(DI),R9 + MOVQ SI,AX + MOVQ DX,R10 + MOVQ CX,R11 + MOVQ R8,R12 + MOVQ R9,R13 + ADDQ ·_2P0(SB),AX + ADDQ ·_2P1234(SB),R10 + ADDQ ·_2P1234(SB),R11 + ADDQ ·_2P1234(SB),R12 + ADDQ ·_2P1234(SB),R13 + ADDQ 80(DI),SI + ADDQ 88(DI),DX + ADDQ 96(DI),CX + ADDQ 104(DI),R8 + ADDQ 112(DI),R9 + SUBQ 80(DI),AX + SUBQ 88(DI),R10 + SUBQ 96(DI),R11 + SUBQ 104(DI),R12 + SUBQ 112(DI),R13 + MOVQ SI,56(SP) + MOVQ DX,64(SP) + MOVQ CX,72(SP) + MOVQ R8,80(SP) + MOVQ R9,88(SP) + MOVQ AX,96(SP) + MOVQ R10,104(SP) + MOVQ R11,112(SP) + MOVQ R12,120(SP) + MOVQ R13,128(SP) + MOVQ 96(SP),AX + MULQ 96(SP) + MOVQ AX,SI + MOVQ DX,CX + MOVQ 96(SP),AX + SHLQ $1,AX + MULQ 104(SP) + MOVQ AX,R8 + MOVQ DX,R9 + MOVQ 96(SP),AX + SHLQ $1,AX + MULQ 112(SP) + MOVQ AX,R10 + MOVQ DX,R11 + MOVQ 96(SP),AX + SHLQ $1,AX + MULQ 120(SP) + MOVQ AX,R12 + MOVQ DX,R13 + MOVQ 96(SP),AX + SHLQ $1,AX + MULQ 128(SP) + MOVQ AX,R14 + MOVQ DX,R15 + MOVQ 104(SP),AX + MULQ 104(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 104(SP),AX + SHLQ $1,AX + MULQ 112(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 104(SP),AX + SHLQ $1,AX + MULQ 120(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 104(SP),DX + IMUL3Q $38,DX,AX + MULQ 128(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 112(SP),AX + MULQ 112(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 112(SP),DX + IMUL3Q $38,DX,AX + MULQ 120(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 112(SP),DX + IMUL3Q $38,DX,AX + MULQ 128(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 120(SP),DX + IMUL3Q $19,DX,AX + MULQ 120(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 120(SP),DX + IMUL3Q $38,DX,AX + MULQ 128(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 128(SP),DX + IMUL3Q $19,DX,AX + MULQ 128(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ ·REDMASK51(SB),DX + SHLQ $13,CX:SI + ANDQ DX,SI + SHLQ $13,R9:R8 + ANDQ DX,R8 + ADDQ CX,R8 + SHLQ $13,R11:R10 + ANDQ DX,R10 + ADDQ R9,R10 + SHLQ $13,R13:R12 + ANDQ DX,R12 + ADDQ R11,R12 + SHLQ $13,R15:R14 + ANDQ DX,R14 + ADDQ R13,R14 + IMUL3Q $19,R15,CX + ADDQ CX,SI + MOVQ SI,CX + SHRQ $51,CX + ADDQ R8,CX + ANDQ DX,SI + MOVQ CX,R8 + SHRQ $51,CX + ADDQ R10,CX + ANDQ DX,R8 + MOVQ CX,R9 + SHRQ $51,CX + ADDQ R12,CX + ANDQ DX,R9 + MOVQ CX,AX + SHRQ $51,CX + ADDQ R14,CX + ANDQ DX,AX + MOVQ CX,R10 + SHRQ $51,CX + IMUL3Q $19,CX,CX + ADDQ CX,SI + ANDQ DX,R10 + MOVQ SI,136(SP) + MOVQ R8,144(SP) + MOVQ R9,152(SP) + MOVQ AX,160(SP) + MOVQ R10,168(SP) + MOVQ 56(SP),AX + MULQ 56(SP) + MOVQ AX,SI + MOVQ DX,CX + MOVQ 56(SP),AX + SHLQ $1,AX + MULQ 64(SP) + MOVQ AX,R8 + MOVQ DX,R9 + MOVQ 56(SP),AX + SHLQ $1,AX + MULQ 72(SP) + MOVQ AX,R10 + MOVQ DX,R11 + MOVQ 56(SP),AX + SHLQ $1,AX + MULQ 80(SP) + MOVQ AX,R12 + MOVQ DX,R13 + MOVQ 56(SP),AX + SHLQ $1,AX + MULQ 88(SP) + MOVQ AX,R14 + MOVQ DX,R15 + MOVQ 64(SP),AX + MULQ 64(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 64(SP),AX + SHLQ $1,AX + MULQ 72(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 64(SP),AX + SHLQ $1,AX + MULQ 80(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 64(SP),DX + IMUL3Q $38,DX,AX + MULQ 88(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 72(SP),AX + MULQ 72(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 72(SP),DX + IMUL3Q $38,DX,AX + MULQ 80(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 72(SP),DX + IMUL3Q $38,DX,AX + MULQ 88(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 80(SP),DX + IMUL3Q $19,DX,AX + MULQ 80(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 80(SP),DX + IMUL3Q $38,DX,AX + MULQ 88(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 88(SP),DX + IMUL3Q $19,DX,AX + MULQ 88(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ ·REDMASK51(SB),DX + SHLQ $13,CX:SI + ANDQ DX,SI + SHLQ $13,R9:R8 + ANDQ DX,R8 + ADDQ CX,R8 + SHLQ $13,R11:R10 + ANDQ DX,R10 + ADDQ R9,R10 + SHLQ $13,R13:R12 + ANDQ DX,R12 + ADDQ R11,R12 + SHLQ $13,R15:R14 + ANDQ DX,R14 + ADDQ R13,R14 + IMUL3Q $19,R15,CX + ADDQ CX,SI + MOVQ SI,CX + SHRQ $51,CX + ADDQ R8,CX + ANDQ DX,SI + MOVQ CX,R8 + SHRQ $51,CX + ADDQ R10,CX + ANDQ DX,R8 + MOVQ CX,R9 + SHRQ $51,CX + ADDQ R12,CX + ANDQ DX,R9 + MOVQ CX,AX + SHRQ $51,CX + ADDQ R14,CX + ANDQ DX,AX + MOVQ CX,R10 + SHRQ $51,CX + IMUL3Q $19,CX,CX + ADDQ CX,SI + ANDQ DX,R10 + MOVQ SI,176(SP) + MOVQ R8,184(SP) + MOVQ R9,192(SP) + MOVQ AX,200(SP) + MOVQ R10,208(SP) + MOVQ SI,SI + MOVQ R8,DX + MOVQ R9,CX + MOVQ AX,R8 + MOVQ R10,R9 + ADDQ ·_2P0(SB),SI + ADDQ ·_2P1234(SB),DX + ADDQ ·_2P1234(SB),CX + ADDQ ·_2P1234(SB),R8 + ADDQ ·_2P1234(SB),R9 + SUBQ 136(SP),SI + SUBQ 144(SP),DX + SUBQ 152(SP),CX + SUBQ 160(SP),R8 + SUBQ 168(SP),R9 + MOVQ SI,216(SP) + MOVQ DX,224(SP) + MOVQ CX,232(SP) + MOVQ R8,240(SP) + MOVQ R9,248(SP) + MOVQ 120(DI),SI + MOVQ 128(DI),DX + MOVQ 136(DI),CX + MOVQ 144(DI),R8 + MOVQ 152(DI),R9 + MOVQ SI,AX + MOVQ DX,R10 + MOVQ CX,R11 + MOVQ R8,R12 + MOVQ R9,R13 + ADDQ ·_2P0(SB),AX + ADDQ ·_2P1234(SB),R10 + ADDQ ·_2P1234(SB),R11 + ADDQ ·_2P1234(SB),R12 + ADDQ ·_2P1234(SB),R13 + ADDQ 160(DI),SI + ADDQ 168(DI),DX + ADDQ 176(DI),CX + ADDQ 184(DI),R8 + ADDQ 192(DI),R9 + SUBQ 160(DI),AX + SUBQ 168(DI),R10 + SUBQ 176(DI),R11 + SUBQ 184(DI),R12 + SUBQ 192(DI),R13 + MOVQ SI,256(SP) + MOVQ DX,264(SP) + MOVQ CX,272(SP) + MOVQ R8,280(SP) + MOVQ R9,288(SP) + MOVQ AX,296(SP) + MOVQ R10,304(SP) + MOVQ R11,312(SP) + MOVQ R12,320(SP) + MOVQ R13,328(SP) + MOVQ 280(SP),SI + IMUL3Q $19,SI,AX + MOVQ AX,336(SP) + MULQ 112(SP) + MOVQ AX,SI + MOVQ DX,CX + MOVQ 288(SP),DX + IMUL3Q $19,DX,AX + MOVQ AX,344(SP) + MULQ 104(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 256(SP),AX + MULQ 96(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 256(SP),AX + MULQ 104(SP) + MOVQ AX,R8 + MOVQ DX,R9 + MOVQ 256(SP),AX + MULQ 112(SP) + MOVQ AX,R10 + MOVQ DX,R11 + MOVQ 256(SP),AX + MULQ 120(SP) + MOVQ AX,R12 + MOVQ DX,R13 + MOVQ 256(SP),AX + MULQ 128(SP) + MOVQ AX,R14 + MOVQ DX,R15 + MOVQ 264(SP),AX + MULQ 96(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 264(SP),AX + MULQ 104(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 264(SP),AX + MULQ 112(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 264(SP),AX + MULQ 120(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 264(SP),DX + IMUL3Q $19,DX,AX + MULQ 128(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 272(SP),AX + MULQ 96(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 272(SP),AX + MULQ 104(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 272(SP),AX + MULQ 112(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 272(SP),DX + IMUL3Q $19,DX,AX + MULQ 120(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 272(SP),DX + IMUL3Q $19,DX,AX + MULQ 128(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 280(SP),AX + MULQ 96(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 280(SP),AX + MULQ 104(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 336(SP),AX + MULQ 120(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 336(SP),AX + MULQ 128(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 288(SP),AX + MULQ 96(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 344(SP),AX + MULQ 112(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 344(SP),AX + MULQ 120(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 344(SP),AX + MULQ 128(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ ·REDMASK51(SB),DX + SHLQ $13,CX:SI + ANDQ DX,SI + SHLQ $13,R9:R8 + ANDQ DX,R8 + ADDQ CX,R8 + SHLQ $13,R11:R10 + ANDQ DX,R10 + ADDQ R9,R10 + SHLQ $13,R13:R12 + ANDQ DX,R12 + ADDQ R11,R12 + SHLQ $13,R15:R14 + ANDQ DX,R14 + ADDQ R13,R14 + IMUL3Q $19,R15,CX + ADDQ CX,SI + MOVQ SI,CX + SHRQ $51,CX + ADDQ R8,CX + MOVQ CX,R8 + SHRQ $51,CX + ANDQ DX,SI + ADDQ R10,CX + MOVQ CX,R9 + SHRQ $51,CX + ANDQ DX,R8 + ADDQ R12,CX + MOVQ CX,AX + SHRQ $51,CX + ANDQ DX,R9 + ADDQ R14,CX + MOVQ CX,R10 + SHRQ $51,CX + ANDQ DX,AX + IMUL3Q $19,CX,CX + ADDQ CX,SI + ANDQ DX,R10 + MOVQ SI,96(SP) + MOVQ R8,104(SP) + MOVQ R9,112(SP) + MOVQ AX,120(SP) + MOVQ R10,128(SP) + MOVQ 320(SP),SI + IMUL3Q $19,SI,AX + MOVQ AX,256(SP) + MULQ 72(SP) + MOVQ AX,SI + MOVQ DX,CX + MOVQ 328(SP),DX + IMUL3Q $19,DX,AX + MOVQ AX,264(SP) + MULQ 64(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 296(SP),AX + MULQ 56(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 296(SP),AX + MULQ 64(SP) + MOVQ AX,R8 + MOVQ DX,R9 + MOVQ 296(SP),AX + MULQ 72(SP) + MOVQ AX,R10 + MOVQ DX,R11 + MOVQ 296(SP),AX + MULQ 80(SP) + MOVQ AX,R12 + MOVQ DX,R13 + MOVQ 296(SP),AX + MULQ 88(SP) + MOVQ AX,R14 + MOVQ DX,R15 + MOVQ 304(SP),AX + MULQ 56(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 304(SP),AX + MULQ 64(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 304(SP),AX + MULQ 72(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 304(SP),AX + MULQ 80(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 304(SP),DX + IMUL3Q $19,DX,AX + MULQ 88(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 312(SP),AX + MULQ 56(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 312(SP),AX + MULQ 64(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 312(SP),AX + MULQ 72(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 312(SP),DX + IMUL3Q $19,DX,AX + MULQ 80(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 312(SP),DX + IMUL3Q $19,DX,AX + MULQ 88(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 320(SP),AX + MULQ 56(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 320(SP),AX + MULQ 64(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 256(SP),AX + MULQ 80(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 256(SP),AX + MULQ 88(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 328(SP),AX + MULQ 56(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 264(SP),AX + MULQ 72(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 264(SP),AX + MULQ 80(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 264(SP),AX + MULQ 88(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ ·REDMASK51(SB),DX + SHLQ $13,CX:SI + ANDQ DX,SI + SHLQ $13,R9:R8 + ANDQ DX,R8 + ADDQ CX,R8 + SHLQ $13,R11:R10 + ANDQ DX,R10 + ADDQ R9,R10 + SHLQ $13,R13:R12 + ANDQ DX,R12 + ADDQ R11,R12 + SHLQ $13,R15:R14 + ANDQ DX,R14 + ADDQ R13,R14 + IMUL3Q $19,R15,CX + ADDQ CX,SI + MOVQ SI,CX + SHRQ $51,CX + ADDQ R8,CX + MOVQ CX,R8 + SHRQ $51,CX + ANDQ DX,SI + ADDQ R10,CX + MOVQ CX,R9 + SHRQ $51,CX + ANDQ DX,R8 + ADDQ R12,CX + MOVQ CX,AX + SHRQ $51,CX + ANDQ DX,R9 + ADDQ R14,CX + MOVQ CX,R10 + SHRQ $51,CX + ANDQ DX,AX + IMUL3Q $19,CX,CX + ADDQ CX,SI + ANDQ DX,R10 + MOVQ SI,DX + MOVQ R8,CX + MOVQ R9,R11 + MOVQ AX,R12 + MOVQ R10,R13 + ADDQ ·_2P0(SB),DX + ADDQ ·_2P1234(SB),CX + ADDQ ·_2P1234(SB),R11 + ADDQ ·_2P1234(SB),R12 + ADDQ ·_2P1234(SB),R13 + ADDQ 96(SP),SI + ADDQ 104(SP),R8 + ADDQ 112(SP),R9 + ADDQ 120(SP),AX + ADDQ 128(SP),R10 + SUBQ 96(SP),DX + SUBQ 104(SP),CX + SUBQ 112(SP),R11 + SUBQ 120(SP),R12 + SUBQ 128(SP),R13 + MOVQ SI,120(DI) + MOVQ R8,128(DI) + MOVQ R9,136(DI) + MOVQ AX,144(DI) + MOVQ R10,152(DI) + MOVQ DX,160(DI) + MOVQ CX,168(DI) + MOVQ R11,176(DI) + MOVQ R12,184(DI) + MOVQ R13,192(DI) + MOVQ 120(DI),AX + MULQ 120(DI) + MOVQ AX,SI + MOVQ DX,CX + MOVQ 120(DI),AX + SHLQ $1,AX + MULQ 128(DI) + MOVQ AX,R8 + MOVQ DX,R9 + MOVQ 120(DI),AX + SHLQ $1,AX + MULQ 136(DI) + MOVQ AX,R10 + MOVQ DX,R11 + MOVQ 120(DI),AX + SHLQ $1,AX + MULQ 144(DI) + MOVQ AX,R12 + MOVQ DX,R13 + MOVQ 120(DI),AX + SHLQ $1,AX + MULQ 152(DI) + MOVQ AX,R14 + MOVQ DX,R15 + MOVQ 128(DI),AX + MULQ 128(DI) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 128(DI),AX + SHLQ $1,AX + MULQ 136(DI) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 128(DI),AX + SHLQ $1,AX + MULQ 144(DI) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 128(DI),DX + IMUL3Q $38,DX,AX + MULQ 152(DI) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 136(DI),AX + MULQ 136(DI) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 136(DI),DX + IMUL3Q $38,DX,AX + MULQ 144(DI) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 136(DI),DX + IMUL3Q $38,DX,AX + MULQ 152(DI) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 144(DI),DX + IMUL3Q $19,DX,AX + MULQ 144(DI) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 144(DI),DX + IMUL3Q $38,DX,AX + MULQ 152(DI) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 152(DI),DX + IMUL3Q $19,DX,AX + MULQ 152(DI) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ ·REDMASK51(SB),DX + SHLQ $13,CX:SI + ANDQ DX,SI + SHLQ $13,R9:R8 + ANDQ DX,R8 + ADDQ CX,R8 + SHLQ $13,R11:R10 + ANDQ DX,R10 + ADDQ R9,R10 + SHLQ $13,R13:R12 + ANDQ DX,R12 + ADDQ R11,R12 + SHLQ $13,R15:R14 + ANDQ DX,R14 + ADDQ R13,R14 + IMUL3Q $19,R15,CX + ADDQ CX,SI + MOVQ SI,CX + SHRQ $51,CX + ADDQ R8,CX + ANDQ DX,SI + MOVQ CX,R8 + SHRQ $51,CX + ADDQ R10,CX + ANDQ DX,R8 + MOVQ CX,R9 + SHRQ $51,CX + ADDQ R12,CX + ANDQ DX,R9 + MOVQ CX,AX + SHRQ $51,CX + ADDQ R14,CX + ANDQ DX,AX + MOVQ CX,R10 + SHRQ $51,CX + IMUL3Q $19,CX,CX + ADDQ CX,SI + ANDQ DX,R10 + MOVQ SI,120(DI) + MOVQ R8,128(DI) + MOVQ R9,136(DI) + MOVQ AX,144(DI) + MOVQ R10,152(DI) + MOVQ 160(DI),AX + MULQ 160(DI) + MOVQ AX,SI + MOVQ DX,CX + MOVQ 160(DI),AX + SHLQ $1,AX + MULQ 168(DI) + MOVQ AX,R8 + MOVQ DX,R9 + MOVQ 160(DI),AX + SHLQ $1,AX + MULQ 176(DI) + MOVQ AX,R10 + MOVQ DX,R11 + MOVQ 160(DI),AX + SHLQ $1,AX + MULQ 184(DI) + MOVQ AX,R12 + MOVQ DX,R13 + MOVQ 160(DI),AX + SHLQ $1,AX + MULQ 192(DI) + MOVQ AX,R14 + MOVQ DX,R15 + MOVQ 168(DI),AX + MULQ 168(DI) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 168(DI),AX + SHLQ $1,AX + MULQ 176(DI) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 168(DI),AX + SHLQ $1,AX + MULQ 184(DI) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 168(DI),DX + IMUL3Q $38,DX,AX + MULQ 192(DI) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 176(DI),AX + MULQ 176(DI) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 176(DI),DX + IMUL3Q $38,DX,AX + MULQ 184(DI) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 176(DI),DX + IMUL3Q $38,DX,AX + MULQ 192(DI) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 184(DI),DX + IMUL3Q $19,DX,AX + MULQ 184(DI) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 184(DI),DX + IMUL3Q $38,DX,AX + MULQ 192(DI) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 192(DI),DX + IMUL3Q $19,DX,AX + MULQ 192(DI) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ ·REDMASK51(SB),DX + SHLQ $13,CX:SI + ANDQ DX,SI + SHLQ $13,R9:R8 + ANDQ DX,R8 + ADDQ CX,R8 + SHLQ $13,R11:R10 + ANDQ DX,R10 + ADDQ R9,R10 + SHLQ $13,R13:R12 + ANDQ DX,R12 + ADDQ R11,R12 + SHLQ $13,R15:R14 + ANDQ DX,R14 + ADDQ R13,R14 + IMUL3Q $19,R15,CX + ADDQ CX,SI + MOVQ SI,CX + SHRQ $51,CX + ADDQ R8,CX + ANDQ DX,SI + MOVQ CX,R8 + SHRQ $51,CX + ADDQ R10,CX + ANDQ DX,R8 + MOVQ CX,R9 + SHRQ $51,CX + ADDQ R12,CX + ANDQ DX,R9 + MOVQ CX,AX + SHRQ $51,CX + ADDQ R14,CX + ANDQ DX,AX + MOVQ CX,R10 + SHRQ $51,CX + IMUL3Q $19,CX,CX + ADDQ CX,SI + ANDQ DX,R10 + MOVQ SI,160(DI) + MOVQ R8,168(DI) + MOVQ R9,176(DI) + MOVQ AX,184(DI) + MOVQ R10,192(DI) + MOVQ 184(DI),SI + IMUL3Q $19,SI,AX + MOVQ AX,56(SP) + MULQ 16(DI) + MOVQ AX,SI + MOVQ DX,CX + MOVQ 192(DI),DX + IMUL3Q $19,DX,AX + MOVQ AX,64(SP) + MULQ 8(DI) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 160(DI),AX + MULQ 0(DI) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 160(DI),AX + MULQ 8(DI) + MOVQ AX,R8 + MOVQ DX,R9 + MOVQ 160(DI),AX + MULQ 16(DI) + MOVQ AX,R10 + MOVQ DX,R11 + MOVQ 160(DI),AX + MULQ 24(DI) + MOVQ AX,R12 + MOVQ DX,R13 + MOVQ 160(DI),AX + MULQ 32(DI) + MOVQ AX,R14 + MOVQ DX,R15 + MOVQ 168(DI),AX + MULQ 0(DI) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 168(DI),AX + MULQ 8(DI) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 168(DI),AX + MULQ 16(DI) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 168(DI),AX + MULQ 24(DI) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 168(DI),DX + IMUL3Q $19,DX,AX + MULQ 32(DI) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 176(DI),AX + MULQ 0(DI) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 176(DI),AX + MULQ 8(DI) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 176(DI),AX + MULQ 16(DI) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 176(DI),DX + IMUL3Q $19,DX,AX + MULQ 24(DI) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 176(DI),DX + IMUL3Q $19,DX,AX + MULQ 32(DI) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 184(DI),AX + MULQ 0(DI) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 184(DI),AX + MULQ 8(DI) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 56(SP),AX + MULQ 24(DI) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 56(SP),AX + MULQ 32(DI) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 192(DI),AX + MULQ 0(DI) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 64(SP),AX + MULQ 16(DI) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 64(SP),AX + MULQ 24(DI) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 64(SP),AX + MULQ 32(DI) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ ·REDMASK51(SB),DX + SHLQ $13,CX:SI + ANDQ DX,SI + SHLQ $13,R9:R8 + ANDQ DX,R8 + ADDQ CX,R8 + SHLQ $13,R11:R10 + ANDQ DX,R10 + ADDQ R9,R10 + SHLQ $13,R13:R12 + ANDQ DX,R12 + ADDQ R11,R12 + SHLQ $13,R15:R14 + ANDQ DX,R14 + ADDQ R13,R14 + IMUL3Q $19,R15,CX + ADDQ CX,SI + MOVQ SI,CX + SHRQ $51,CX + ADDQ R8,CX + MOVQ CX,R8 + SHRQ $51,CX + ANDQ DX,SI + ADDQ R10,CX + MOVQ CX,R9 + SHRQ $51,CX + ANDQ DX,R8 + ADDQ R12,CX + MOVQ CX,AX + SHRQ $51,CX + ANDQ DX,R9 + ADDQ R14,CX + MOVQ CX,R10 + SHRQ $51,CX + ANDQ DX,AX + IMUL3Q $19,CX,CX + ADDQ CX,SI + ANDQ DX,R10 + MOVQ SI,160(DI) + MOVQ R8,168(DI) + MOVQ R9,176(DI) + MOVQ AX,184(DI) + MOVQ R10,192(DI) + MOVQ 200(SP),SI + IMUL3Q $19,SI,AX + MOVQ AX,56(SP) + MULQ 152(SP) + MOVQ AX,SI + MOVQ DX,CX + MOVQ 208(SP),DX + IMUL3Q $19,DX,AX + MOVQ AX,64(SP) + MULQ 144(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 176(SP),AX + MULQ 136(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 176(SP),AX + MULQ 144(SP) + MOVQ AX,R8 + MOVQ DX,R9 + MOVQ 176(SP),AX + MULQ 152(SP) + MOVQ AX,R10 + MOVQ DX,R11 + MOVQ 176(SP),AX + MULQ 160(SP) + MOVQ AX,R12 + MOVQ DX,R13 + MOVQ 176(SP),AX + MULQ 168(SP) + MOVQ AX,R14 + MOVQ DX,R15 + MOVQ 184(SP),AX + MULQ 136(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 184(SP),AX + MULQ 144(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 184(SP),AX + MULQ 152(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 184(SP),AX + MULQ 160(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 184(SP),DX + IMUL3Q $19,DX,AX + MULQ 168(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 192(SP),AX + MULQ 136(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 192(SP),AX + MULQ 144(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 192(SP),AX + MULQ 152(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 192(SP),DX + IMUL3Q $19,DX,AX + MULQ 160(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 192(SP),DX + IMUL3Q $19,DX,AX + MULQ 168(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 200(SP),AX + MULQ 136(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 200(SP),AX + MULQ 144(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 56(SP),AX + MULQ 160(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 56(SP),AX + MULQ 168(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 208(SP),AX + MULQ 136(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 64(SP),AX + MULQ 152(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 64(SP),AX + MULQ 160(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 64(SP),AX + MULQ 168(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ ·REDMASK51(SB),DX + SHLQ $13,CX:SI + ANDQ DX,SI + SHLQ $13,R9:R8 + ANDQ DX,R8 + ADDQ CX,R8 + SHLQ $13,R11:R10 + ANDQ DX,R10 + ADDQ R9,R10 + SHLQ $13,R13:R12 + ANDQ DX,R12 + ADDQ R11,R12 + SHLQ $13,R15:R14 + ANDQ DX,R14 + ADDQ R13,R14 + IMUL3Q $19,R15,CX + ADDQ CX,SI + MOVQ SI,CX + SHRQ $51,CX + ADDQ R8,CX + MOVQ CX,R8 + SHRQ $51,CX + ANDQ DX,SI + ADDQ R10,CX + MOVQ CX,R9 + SHRQ $51,CX + ANDQ DX,R8 + ADDQ R12,CX + MOVQ CX,AX + SHRQ $51,CX + ANDQ DX,R9 + ADDQ R14,CX + MOVQ CX,R10 + SHRQ $51,CX + ANDQ DX,AX + IMUL3Q $19,CX,CX + ADDQ CX,SI + ANDQ DX,R10 + MOVQ SI,40(DI) + MOVQ R8,48(DI) + MOVQ R9,56(DI) + MOVQ AX,64(DI) + MOVQ R10,72(DI) + MOVQ 216(SP),AX + MULQ ·_121666_213(SB) + SHRQ $13,AX + MOVQ AX,SI + MOVQ DX,CX + MOVQ 224(SP),AX + MULQ ·_121666_213(SB) + SHRQ $13,AX + ADDQ AX,CX + MOVQ DX,R8 + MOVQ 232(SP),AX + MULQ ·_121666_213(SB) + SHRQ $13,AX + ADDQ AX,R8 + MOVQ DX,R9 + MOVQ 240(SP),AX + MULQ ·_121666_213(SB) + SHRQ $13,AX + ADDQ AX,R9 + MOVQ DX,R10 + MOVQ 248(SP),AX + MULQ ·_121666_213(SB) + SHRQ $13,AX + ADDQ AX,R10 + IMUL3Q $19,DX,DX + ADDQ DX,SI + ADDQ 136(SP),SI + ADDQ 144(SP),CX + ADDQ 152(SP),R8 + ADDQ 160(SP),R9 + ADDQ 168(SP),R10 + MOVQ SI,80(DI) + MOVQ CX,88(DI) + MOVQ R8,96(DI) + MOVQ R9,104(DI) + MOVQ R10,112(DI) + MOVQ 104(DI),SI + IMUL3Q $19,SI,AX + MOVQ AX,56(SP) + MULQ 232(SP) + MOVQ AX,SI + MOVQ DX,CX + MOVQ 112(DI),DX + IMUL3Q $19,DX,AX + MOVQ AX,64(SP) + MULQ 224(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 80(DI),AX + MULQ 216(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 80(DI),AX + MULQ 224(SP) + MOVQ AX,R8 + MOVQ DX,R9 + MOVQ 80(DI),AX + MULQ 232(SP) + MOVQ AX,R10 + MOVQ DX,R11 + MOVQ 80(DI),AX + MULQ 240(SP) + MOVQ AX,R12 + MOVQ DX,R13 + MOVQ 80(DI),AX + MULQ 248(SP) + MOVQ AX,R14 + MOVQ DX,R15 + MOVQ 88(DI),AX + MULQ 216(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 88(DI),AX + MULQ 224(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 88(DI),AX + MULQ 232(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 88(DI),AX + MULQ 240(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 88(DI),DX + IMUL3Q $19,DX,AX + MULQ 248(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 96(DI),AX + MULQ 216(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 96(DI),AX + MULQ 224(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 96(DI),AX + MULQ 232(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 96(DI),DX + IMUL3Q $19,DX,AX + MULQ 240(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 96(DI),DX + IMUL3Q $19,DX,AX + MULQ 248(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 104(DI),AX + MULQ 216(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 104(DI),AX + MULQ 224(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 56(SP),AX + MULQ 240(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 56(SP),AX + MULQ 248(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 112(DI),AX + MULQ 216(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 64(SP),AX + MULQ 232(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 64(SP),AX + MULQ 240(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 64(SP),AX + MULQ 248(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ ·REDMASK51(SB),DX + SHLQ $13,CX:SI + ANDQ DX,SI + SHLQ $13,R9:R8 + ANDQ DX,R8 + ADDQ CX,R8 + SHLQ $13,R11:R10 + ANDQ DX,R10 + ADDQ R9,R10 + SHLQ $13,R13:R12 + ANDQ DX,R12 + ADDQ R11,R12 + SHLQ $13,R15:R14 + ANDQ DX,R14 + ADDQ R13,R14 + IMUL3Q $19,R15,CX + ADDQ CX,SI + MOVQ SI,CX + SHRQ $51,CX + ADDQ R8,CX + MOVQ CX,R8 + SHRQ $51,CX + ANDQ DX,SI + ADDQ R10,CX + MOVQ CX,R9 + SHRQ $51,CX + ANDQ DX,R8 + ADDQ R12,CX + MOVQ CX,AX + SHRQ $51,CX + ANDQ DX,R9 + ADDQ R14,CX + MOVQ CX,R10 + SHRQ $51,CX + ANDQ DX,AX + IMUL3Q $19,CX,CX + ADDQ CX,SI + ANDQ DX,R10 + MOVQ SI,80(DI) + MOVQ R8,88(DI) + MOVQ R9,96(DI) + MOVQ AX,104(DI) + MOVQ R10,112(DI) + MOVQ 0(SP),R11 + MOVQ 8(SP),R12 + MOVQ 16(SP),R13 + MOVQ 24(SP),R14 + MOVQ 32(SP),R15 + MOVQ 40(SP),BX + MOVQ 48(SP),BP + MOVQ R11,SP + MOVQ DI,AX + MOVQ SI,DX + RET diff --git a/external/boringssl/ssl/test/runner/curve25519/mont25519_amd64.go b/external/boringssl/ssl/test/runner/curve25519/mont25519_amd64.go new file mode 100644 index 0000000000..5822bd5338 --- /dev/null +++ b/external/boringssl/ssl/test/runner/curve25519/mont25519_amd64.go @@ -0,0 +1,240 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build amd64,!gccgo,!appengine + +package curve25519 + +// These functions are implemented in the .s files. The names of the functions +// in the rest of the file are also taken from the SUPERCOP sources to help +// people following along. + +//go:noescape + +func cswap(inout *[5]uint64, v uint64) + +//go:noescape + +func ladderstep(inout *[5][5]uint64) + +//go:noescape + +func freeze(inout *[5]uint64) + +//go:noescape + +func mul(dest, a, b *[5]uint64) + +//go:noescape + +func square(out, in *[5]uint64) + +// mladder uses a Montgomery ladder to calculate (xr/zr) *= s. +func mladder(xr, zr *[5]uint64, s *[32]byte) { + var work [5][5]uint64 + + work[0] = *xr + setint(&work[1], 1) + setint(&work[2], 0) + work[3] = *xr + setint(&work[4], 1) + + j := uint(6) + var prevbit byte + + for i := 31; i >= 0; i-- { + for j < 8 { + bit := ((*s)[i] >> j) & 1 + swap := bit ^ prevbit + prevbit = bit + cswap(&work[1], uint64(swap)) + ladderstep(&work) + j-- + } + j = 7 + } + + *xr = work[1] + *zr = work[2] +} + +func scalarMult(out, in, base *[32]byte) { + var e [32]byte + copy(e[:], (*in)[:]) + e[0] &= 248 + e[31] &= 127 + e[31] |= 64 + + var t, z [5]uint64 + unpack(&t, base) + mladder(&t, &z, &e) + invert(&z, &z) + mul(&t, &t, &z) + pack(out, &t) +} + +func setint(r *[5]uint64, v uint64) { + r[0] = v + r[1] = 0 + r[2] = 0 + r[3] = 0 + r[4] = 0 +} + +// unpack sets r = x where r consists of 5, 51-bit limbs in little-endian +// order. +func unpack(r *[5]uint64, x *[32]byte) { + r[0] = uint64(x[0]) | + uint64(x[1])<<8 | + uint64(x[2])<<16 | + uint64(x[3])<<24 | + uint64(x[4])<<32 | + uint64(x[5])<<40 | + uint64(x[6]&7)<<48 + + r[1] = uint64(x[6])>>3 | + uint64(x[7])<<5 | + uint64(x[8])<<13 | + uint64(x[9])<<21 | + uint64(x[10])<<29 | + uint64(x[11])<<37 | + uint64(x[12]&63)<<45 + + r[2] = uint64(x[12])>>6 | + uint64(x[13])<<2 | + uint64(x[14])<<10 | + uint64(x[15])<<18 | + uint64(x[16])<<26 | + uint64(x[17])<<34 | + uint64(x[18])<<42 | + uint64(x[19]&1)<<50 + + r[3] = uint64(x[19])>>1 | + uint64(x[20])<<7 | + uint64(x[21])<<15 | + uint64(x[22])<<23 | + uint64(x[23])<<31 | + uint64(x[24])<<39 | + uint64(x[25]&15)<<47 + + r[4] = uint64(x[25])>>4 | + uint64(x[26])<<4 | + uint64(x[27])<<12 | + uint64(x[28])<<20 | + uint64(x[29])<<28 | + uint64(x[30])<<36 | + uint64(x[31]&127)<<44 +} + +// pack sets out = x where out is the usual, little-endian form of the 5, +// 51-bit limbs in x. +func pack(out *[32]byte, x *[5]uint64) { + t := *x + freeze(&t) + + out[0] = byte(t[0]) + out[1] = byte(t[0] >> 8) + out[2] = byte(t[0] >> 16) + out[3] = byte(t[0] >> 24) + out[4] = byte(t[0] >> 32) + out[5] = byte(t[0] >> 40) + out[6] = byte(t[0] >> 48) + + out[6] ^= byte(t[1]<<3) & 0xf8 + out[7] = byte(t[1] >> 5) + out[8] = byte(t[1] >> 13) + out[9] = byte(t[1] >> 21) + out[10] = byte(t[1] >> 29) + out[11] = byte(t[1] >> 37) + out[12] = byte(t[1] >> 45) + + out[12] ^= byte(t[2]<<6) & 0xc0 + out[13] = byte(t[2] >> 2) + out[14] = byte(t[2] >> 10) + out[15] = byte(t[2] >> 18) + out[16] = byte(t[2] >> 26) + out[17] = byte(t[2] >> 34) + out[18] = byte(t[2] >> 42) + out[19] = byte(t[2] >> 50) + + out[19] ^= byte(t[3]<<1) & 0xfe + out[20] = byte(t[3] >> 7) + out[21] = byte(t[3] >> 15) + out[22] = byte(t[3] >> 23) + out[23] = byte(t[3] >> 31) + out[24] = byte(t[3] >> 39) + out[25] = byte(t[3] >> 47) + + out[25] ^= byte(t[4]<<4) & 0xf0 + out[26] = byte(t[4] >> 4) + out[27] = byte(t[4] >> 12) + out[28] = byte(t[4] >> 20) + out[29] = byte(t[4] >> 28) + out[30] = byte(t[4] >> 36) + out[31] = byte(t[4] >> 44) +} + +// invert calculates r = x^-1 mod p using Fermat's little theorem. +func invert(r *[5]uint64, x *[5]uint64) { + var z2, z9, z11, z2_5_0, z2_10_0, z2_20_0, z2_50_0, z2_100_0, t [5]uint64 + + square(&z2, x) /* 2 */ + square(&t, &z2) /* 4 */ + square(&t, &t) /* 8 */ + mul(&z9, &t, x) /* 9 */ + mul(&z11, &z9, &z2) /* 11 */ + square(&t, &z11) /* 22 */ + mul(&z2_5_0, &t, &z9) /* 2^5 - 2^0 = 31 */ + + square(&t, &z2_5_0) /* 2^6 - 2^1 */ + for i := 1; i < 5; i++ { /* 2^20 - 2^10 */ + square(&t, &t) + } + mul(&z2_10_0, &t, &z2_5_0) /* 2^10 - 2^0 */ + + square(&t, &z2_10_0) /* 2^11 - 2^1 */ + for i := 1; i < 10; i++ { /* 2^20 - 2^10 */ + square(&t, &t) + } + mul(&z2_20_0, &t, &z2_10_0) /* 2^20 - 2^0 */ + + square(&t, &z2_20_0) /* 2^21 - 2^1 */ + for i := 1; i < 20; i++ { /* 2^40 - 2^20 */ + square(&t, &t) + } + mul(&t, &t, &z2_20_0) /* 2^40 - 2^0 */ + + square(&t, &t) /* 2^41 - 2^1 */ + for i := 1; i < 10; i++ { /* 2^50 - 2^10 */ + square(&t, &t) + } + mul(&z2_50_0, &t, &z2_10_0) /* 2^50 - 2^0 */ + + square(&t, &z2_50_0) /* 2^51 - 2^1 */ + for i := 1; i < 50; i++ { /* 2^100 - 2^50 */ + square(&t, &t) + } + mul(&z2_100_0, &t, &z2_50_0) /* 2^100 - 2^0 */ + + square(&t, &z2_100_0) /* 2^101 - 2^1 */ + for i := 1; i < 100; i++ { /* 2^200 - 2^100 */ + square(&t, &t) + } + mul(&t, &t, &z2_100_0) /* 2^200 - 2^0 */ + + square(&t, &t) /* 2^201 - 2^1 */ + for i := 1; i < 50; i++ { /* 2^250 - 2^50 */ + square(&t, &t) + } + mul(&t, &t, &z2_50_0) /* 2^250 - 2^0 */ + + square(&t, &t) /* 2^251 - 2^1 */ + square(&t, &t) /* 2^252 - 2^2 */ + square(&t, &t) /* 2^253 - 2^3 */ + + square(&t, &t) /* 2^254 - 2^4 */ + + square(&t, &t) /* 2^255 - 2^5 */ + mul(r, &t, &z11) /* 2^255 - 21 */ +} diff --git a/external/boringssl/ssl/test/runner/curve25519/mul_amd64.s b/external/boringssl/ssl/test/runner/curve25519/mul_amd64.s new file mode 100644 index 0000000000..e48d183ee5 --- /dev/null +++ b/external/boringssl/ssl/test/runner/curve25519/mul_amd64.s @@ -0,0 +1,191 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This code was translated into a form compatible with 6a from the public +// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html + +// +build amd64,!gccgo,!appengine + +// func mul(dest, a, b *[5]uint64) +TEXT ·mul(SB),0,$128-24 + MOVQ dest+0(FP), DI + MOVQ a+8(FP), SI + MOVQ b+16(FP), DX + + MOVQ SP,R11 + MOVQ $31,CX + NOTQ CX + ANDQ CX,SP + ADDQ $32,SP + + MOVQ R11,0(SP) + MOVQ R12,8(SP) + MOVQ R13,16(SP) + MOVQ R14,24(SP) + MOVQ R15,32(SP) + MOVQ BX,40(SP) + MOVQ BP,48(SP) + MOVQ DI,56(SP) + MOVQ DX,CX + MOVQ 24(SI),DX + IMUL3Q $19,DX,AX + MOVQ AX,64(SP) + MULQ 16(CX) + MOVQ AX,R8 + MOVQ DX,R9 + MOVQ 32(SI),DX + IMUL3Q $19,DX,AX + MOVQ AX,72(SP) + MULQ 8(CX) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 0(SI),AX + MULQ 0(CX) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 0(SI),AX + MULQ 8(CX) + MOVQ AX,R10 + MOVQ DX,R11 + MOVQ 0(SI),AX + MULQ 16(CX) + MOVQ AX,R12 + MOVQ DX,R13 + MOVQ 0(SI),AX + MULQ 24(CX) + MOVQ AX,R14 + MOVQ DX,R15 + MOVQ 0(SI),AX + MULQ 32(CX) + MOVQ AX,BX + MOVQ DX,BP + MOVQ 8(SI),AX + MULQ 0(CX) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 8(SI),AX + MULQ 8(CX) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 8(SI),AX + MULQ 16(CX) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 8(SI),AX + MULQ 24(CX) + ADDQ AX,BX + ADCQ DX,BP + MOVQ 8(SI),DX + IMUL3Q $19,DX,AX + MULQ 32(CX) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 16(SI),AX + MULQ 0(CX) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 16(SI),AX + MULQ 8(CX) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 16(SI),AX + MULQ 16(CX) + ADDQ AX,BX + ADCQ DX,BP + MOVQ 16(SI),DX + IMUL3Q $19,DX,AX + MULQ 24(CX) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 16(SI),DX + IMUL3Q $19,DX,AX + MULQ 32(CX) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 24(SI),AX + MULQ 0(CX) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 24(SI),AX + MULQ 8(CX) + ADDQ AX,BX + ADCQ DX,BP + MOVQ 64(SP),AX + MULQ 24(CX) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 64(SP),AX + MULQ 32(CX) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 32(SI),AX + MULQ 0(CX) + ADDQ AX,BX + ADCQ DX,BP + MOVQ 72(SP),AX + MULQ 16(CX) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 72(SP),AX + MULQ 24(CX) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 72(SP),AX + MULQ 32(CX) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ ·REDMASK51(SB),SI + SHLQ $13,R9:R8 + ANDQ SI,R8 + SHLQ $13,R11:R10 + ANDQ SI,R10 + ADDQ R9,R10 + SHLQ $13,R13:R12 + ANDQ SI,R12 + ADDQ R11,R12 + SHLQ $13,R15:R14 + ANDQ SI,R14 + ADDQ R13,R14 + SHLQ $13,BP:BX + ANDQ SI,BX + ADDQ R15,BX + IMUL3Q $19,BP,DX + ADDQ DX,R8 + MOVQ R8,DX + SHRQ $51,DX + ADDQ R10,DX + MOVQ DX,CX + SHRQ $51,DX + ANDQ SI,R8 + ADDQ R12,DX + MOVQ DX,R9 + SHRQ $51,DX + ANDQ SI,CX + ADDQ R14,DX + MOVQ DX,AX + SHRQ $51,DX + ANDQ SI,R9 + ADDQ BX,DX + MOVQ DX,R10 + SHRQ $51,DX + ANDQ SI,AX + IMUL3Q $19,DX,DX + ADDQ DX,R8 + ANDQ SI,R10 + MOVQ R8,0(DI) + MOVQ CX,8(DI) + MOVQ R9,16(DI) + MOVQ AX,24(DI) + MOVQ R10,32(DI) + MOVQ 0(SP),R11 + MOVQ 8(SP),R12 + MOVQ 16(SP),R13 + MOVQ 24(SP),R14 + MOVQ 32(SP),R15 + MOVQ 40(SP),BX + MOVQ 48(SP),BP + MOVQ R11,SP + MOVQ DI,AX + MOVQ SI,DX + RET diff --git a/external/boringssl/ssl/test/runner/curve25519/square_amd64.s b/external/boringssl/ssl/test/runner/curve25519/square_amd64.s new file mode 100644 index 0000000000..78d1a50ddc --- /dev/null +++ b/external/boringssl/ssl/test/runner/curve25519/square_amd64.s @@ -0,0 +1,153 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This code was translated into a form compatible with 6a from the public +// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html + +// +build amd64,!gccgo,!appengine + +// func square(out, in *[5]uint64) +TEXT ·square(SB),7,$96-16 + MOVQ out+0(FP), DI + MOVQ in+8(FP), SI + + MOVQ SP,R11 + MOVQ $31,CX + NOTQ CX + ANDQ CX,SP + ADDQ $32, SP + + MOVQ R11,0(SP) + MOVQ R12,8(SP) + MOVQ R13,16(SP) + MOVQ R14,24(SP) + MOVQ R15,32(SP) + MOVQ BX,40(SP) + MOVQ BP,48(SP) + MOVQ 0(SI),AX + MULQ 0(SI) + MOVQ AX,CX + MOVQ DX,R8 + MOVQ 0(SI),AX + SHLQ $1,AX + MULQ 8(SI) + MOVQ AX,R9 + MOVQ DX,R10 + MOVQ 0(SI),AX + SHLQ $1,AX + MULQ 16(SI) + MOVQ AX,R11 + MOVQ DX,R12 + MOVQ 0(SI),AX + SHLQ $1,AX + MULQ 24(SI) + MOVQ AX,R13 + MOVQ DX,R14 + MOVQ 0(SI),AX + SHLQ $1,AX + MULQ 32(SI) + MOVQ AX,R15 + MOVQ DX,BX + MOVQ 8(SI),AX + MULQ 8(SI) + ADDQ AX,R11 + ADCQ DX,R12 + MOVQ 8(SI),AX + SHLQ $1,AX + MULQ 16(SI) + ADDQ AX,R13 + ADCQ DX,R14 + MOVQ 8(SI),AX + SHLQ $1,AX + MULQ 24(SI) + ADDQ AX,R15 + ADCQ DX,BX + MOVQ 8(SI),DX + IMUL3Q $38,DX,AX + MULQ 32(SI) + ADDQ AX,CX + ADCQ DX,R8 + MOVQ 16(SI),AX + MULQ 16(SI) + ADDQ AX,R15 + ADCQ DX,BX + MOVQ 16(SI),DX + IMUL3Q $38,DX,AX + MULQ 24(SI) + ADDQ AX,CX + ADCQ DX,R8 + MOVQ 16(SI),DX + IMUL3Q $38,DX,AX + MULQ 32(SI) + ADDQ AX,R9 + ADCQ DX,R10 + MOVQ 24(SI),DX + IMUL3Q $19,DX,AX + MULQ 24(SI) + ADDQ AX,R9 + ADCQ DX,R10 + MOVQ 24(SI),DX + IMUL3Q $38,DX,AX + MULQ 32(SI) + ADDQ AX,R11 + ADCQ DX,R12 + MOVQ 32(SI),DX + IMUL3Q $19,DX,AX + MULQ 32(SI) + ADDQ AX,R13 + ADCQ DX,R14 + MOVQ ·REDMASK51(SB),SI + SHLQ $13,R8:CX + ANDQ SI,CX + SHLQ $13,R10:R9 + ANDQ SI,R9 + ADDQ R8,R9 + SHLQ $13,R12:R11 + ANDQ SI,R11 + ADDQ R10,R11 + SHLQ $13,R14:R13 + ANDQ SI,R13 + ADDQ R12,R13 + SHLQ $13,BX:R15 + ANDQ SI,R15 + ADDQ R14,R15 + IMUL3Q $19,BX,DX + ADDQ DX,CX + MOVQ CX,DX + SHRQ $51,DX + ADDQ R9,DX + ANDQ SI,CX + MOVQ DX,R8 + SHRQ $51,DX + ADDQ R11,DX + ANDQ SI,R8 + MOVQ DX,R9 + SHRQ $51,DX + ADDQ R13,DX + ANDQ SI,R9 + MOVQ DX,AX + SHRQ $51,DX + ADDQ R15,DX + ANDQ SI,AX + MOVQ DX,R10 + SHRQ $51,DX + IMUL3Q $19,DX,DX + ADDQ DX,CX + ANDQ SI,R10 + MOVQ CX,0(DI) + MOVQ R8,8(DI) + MOVQ R9,16(DI) + MOVQ AX,24(DI) + MOVQ R10,32(DI) + MOVQ 0(SP),R11 + MOVQ 8(SP),R12 + MOVQ 16(SP),R13 + MOVQ 24(SP),R14 + MOVQ 32(SP),R15 + MOVQ 40(SP),BX + MOVQ 48(SP),BP + MOVQ R11,SP + MOVQ DI,AX + MOVQ SI,DX + RET diff --git a/external/boringssl/ssl/test/runner/deterministic.go b/external/boringssl/ssl/test/runner/deterministic.go new file mode 100644 index 0000000000..4a61ee0a72 --- /dev/null +++ b/external/boringssl/ssl/test/runner/deterministic.go @@ -0,0 +1,37 @@ +// Copyright (c) 2016, Google Inc. +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +package runner + +import ( + "encoding/binary" +) + +// Use a different key from crypto/rand/deterministic.c. +var deterministicRandKey = []byte("runner deterministic key 0123456") + +type deterministicRand struct { + numCalls uint64 +} + +func (d *deterministicRand) Read(buf []byte) (int, error) { + for i := range buf { + buf[i] = 0 + } + var nonce [12]byte + binary.LittleEndian.PutUint64(nonce[:8], d.numCalls) + chaCha20(buf, buf, deterministicRandKey, nonce[:], 0) + d.numCalls++ + return len(buf), nil +} diff --git a/external/boringssl/ssl/test/runner/dtls.go b/external/boringssl/ssl/test/runner/dtls.go new file mode 100644 index 0000000000..a31dfc0088 --- /dev/null +++ b/external/boringssl/ssl/test/runner/dtls.go @@ -0,0 +1,446 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// DTLS implementation. +// +// NOTE: This is a not even a remotely production-quality DTLS +// implementation. It is the bare minimum necessary to be able to +// achieve coverage on BoringSSL's implementation. Of note is that +// this implementation assumes the underlying net.PacketConn is not +// only reliable but also ordered. BoringSSL will be expected to deal +// with simulated loss, but there is no point in forcing the test +// driver to. + +package runner + +import ( + "bytes" + "errors" + "fmt" + "io" + "math/rand" + "net" +) + +func versionToWire(vers uint16, isDTLS bool) uint16 { + if isDTLS { + return ^(vers - 0x0201) + } + return vers +} + +func wireToVersion(vers uint16, isDTLS bool) uint16 { + if isDTLS { + return ^vers + 0x0201 + } + return vers +} + +func (c *Conn) dtlsDoReadRecord(want recordType) (recordType, *block, error) { + recordHeaderLen := dtlsRecordHeaderLen + + if c.rawInput == nil { + c.rawInput = c.in.newBlock() + } + b := c.rawInput + + // Read a new packet only if the current one is empty. + var newPacket bool + if len(b.data) == 0 { + // Pick some absurdly large buffer size. + b.resize(maxCiphertext + recordHeaderLen) + n, err := c.conn.Read(c.rawInput.data) + if err != nil { + return 0, nil, err + } + if c.config.Bugs.MaxPacketLength != 0 && n > c.config.Bugs.MaxPacketLength { + return 0, nil, fmt.Errorf("dtls: exceeded maximum packet length") + } + c.rawInput.resize(n) + newPacket = true + } + + // Read out one record. + // + // A real DTLS implementation should be tolerant of errors, + // but this is test code. We should not be tolerant of our + // peer sending garbage. + if len(b.data) < recordHeaderLen { + return 0, nil, errors.New("dtls: failed to read record header") + } + typ := recordType(b.data[0]) + vers := wireToVersion(uint16(b.data[1])<<8|uint16(b.data[2]), c.isDTLS) + if c.haveVers { + if vers != c.vers { + c.sendAlert(alertProtocolVersion) + return 0, nil, c.in.setErrorLocked(fmt.Errorf("dtls: received record with version %x when expecting version %x", vers, c.vers)) + } + } else { + if expect := c.config.Bugs.ExpectInitialRecordVersion; expect != 0 && vers != expect { + c.sendAlert(alertProtocolVersion) + return 0, nil, c.in.setErrorLocked(fmt.Errorf("dtls: received record with version %x when expecting version %x", vers, expect)) + } + } + epoch := b.data[3:5] + seq := b.data[5:11] + // For test purposes, require the sequence number be monotonically + // increasing, so c.in includes the minimum next sequence number. Gaps + // may occur if packets failed to be sent out. A real implementation + // would maintain a replay window and such. + if !bytes.Equal(epoch, c.in.seq[:2]) { + c.sendAlert(alertIllegalParameter) + return 0, nil, c.in.setErrorLocked(fmt.Errorf("dtls: bad epoch")) + } + if bytes.Compare(seq, c.in.seq[2:]) < 0 { + c.sendAlert(alertIllegalParameter) + return 0, nil, c.in.setErrorLocked(fmt.Errorf("dtls: bad sequence number")) + } + copy(c.in.seq[2:], seq) + n := int(b.data[11])<<8 | int(b.data[12]) + if n > maxCiphertext || len(b.data) < recordHeaderLen+n { + c.sendAlert(alertRecordOverflow) + return 0, nil, c.in.setErrorLocked(fmt.Errorf("dtls: oversized record received with length %d", n)) + } + + // Process message. + b, c.rawInput = c.in.splitBlock(b, recordHeaderLen+n) + ok, off, err := c.in.decrypt(b) + if !ok { + c.in.setErrorLocked(c.sendAlert(err)) + } + b.off = off + + // Require that ChangeCipherSpec always share a packet with either the + // previous or next handshake message. + if newPacket && typ == recordTypeChangeCipherSpec && c.rawInput == nil { + return 0, nil, c.in.setErrorLocked(fmt.Errorf("dtls: ChangeCipherSpec not packed together with Finished")) + } + + return typ, b, nil +} + +func (c *Conn) makeFragment(header, data []byte, fragOffset, fragLen int) []byte { + fragment := make([]byte, 0, 12+fragLen) + fragment = append(fragment, header...) + fragment = append(fragment, byte(c.sendHandshakeSeq>>8), byte(c.sendHandshakeSeq)) + fragment = append(fragment, byte(fragOffset>>16), byte(fragOffset>>8), byte(fragOffset)) + fragment = append(fragment, byte(fragLen>>16), byte(fragLen>>8), byte(fragLen)) + fragment = append(fragment, data[fragOffset:fragOffset+fragLen]...) + return fragment +} + +func (c *Conn) dtlsWriteRecord(typ recordType, data []byte) (n int, err error) { + if typ != recordTypeHandshake { + // Only handshake messages are fragmented. + return c.dtlsWriteRawRecord(typ, data) + } + + maxLen := c.config.Bugs.MaxHandshakeRecordLength + if maxLen <= 0 { + maxLen = 1024 + } + + // Handshake messages have to be modified to include fragment + // offset and length and with the header replicated. Save the + // TLS header here. + // + // TODO(davidben): This assumes that data contains exactly one + // handshake message. This is incompatible with + // FragmentAcrossChangeCipherSpec. (Which is unfortunate + // because OpenSSL's DTLS implementation will probably accept + // such fragmentation and could do with a fix + tests.) + header := data[:4] + data = data[4:] + + isFinished := header[0] == typeFinished + + if c.config.Bugs.SendEmptyFragments { + fragment := c.makeFragment(header, data, 0, 0) + c.pendingFragments = append(c.pendingFragments, fragment) + } + + firstRun := true + fragOffset := 0 + for firstRun || fragOffset < len(data) { + firstRun = false + fragLen := len(data) - fragOffset + if fragLen > maxLen { + fragLen = maxLen + } + + fragment := c.makeFragment(header, data, fragOffset, fragLen) + if c.config.Bugs.FragmentMessageTypeMismatch && fragOffset > 0 { + fragment[0]++ + } + if c.config.Bugs.FragmentMessageLengthMismatch && fragOffset > 0 { + fragment[3]++ + } + + // Buffer the fragment for later. They will be sent (and + // reordered) on flush. + c.pendingFragments = append(c.pendingFragments, fragment) + if c.config.Bugs.ReorderHandshakeFragments { + // Don't duplicate Finished to avoid the peer + // interpreting it as a retransmit request. + if !isFinished { + c.pendingFragments = append(c.pendingFragments, fragment) + } + + if fragLen > (maxLen+1)/2 { + // Overlap each fragment by half. + fragLen = (maxLen + 1) / 2 + } + } + fragOffset += fragLen + n += fragLen + } + if !isFinished && c.config.Bugs.MixCompleteMessageWithFragments { + fragment := c.makeFragment(header, data, 0, len(data)) + c.pendingFragments = append(c.pendingFragments, fragment) + } + + // Increment the handshake sequence number for the next + // handshake message. + c.sendHandshakeSeq++ + return +} + +func (c *Conn) dtlsFlushHandshake() error { + if !c.isDTLS { + return nil + } + + // This is a test-only DTLS implementation, so there is no need to + // retain |c.pendingFragments| for a future retransmit. + var fragments [][]byte + fragments, c.pendingFragments = c.pendingFragments, fragments + + if c.config.Bugs.ReorderHandshakeFragments { + perm := rand.New(rand.NewSource(0)).Perm(len(fragments)) + tmp := make([][]byte, len(fragments)) + for i := range tmp { + tmp[i] = fragments[perm[i]] + } + fragments = tmp + } + + maxRecordLen := c.config.Bugs.PackHandshakeFragments + maxPacketLen := c.config.Bugs.PackHandshakeRecords + + // Pack handshake fragments into records. + var records [][]byte + for _, fragment := range fragments { + if n := c.config.Bugs.SplitFragments; n > 0 { + if len(fragment) > n { + records = append(records, fragment[:n]) + records = append(records, fragment[n:]) + } else { + records = append(records, fragment) + } + } else if i := len(records) - 1; len(records) > 0 && len(records[i])+len(fragment) <= maxRecordLen { + records[i] = append(records[i], fragment...) + } else { + // The fragment will be appended to, so copy it. + records = append(records, append([]byte{}, fragment...)) + } + } + + // Format them into packets. + var packets [][]byte + for _, record := range records { + b, err := c.dtlsSealRecord(recordTypeHandshake, record) + if err != nil { + return err + } + + if i := len(packets) - 1; len(packets) > 0 && len(packets[i])+len(b.data) <= maxPacketLen { + packets[i] = append(packets[i], b.data...) + } else { + // The sealed record will be appended to and reused by + // |c.out|, so copy it. + packets = append(packets, append([]byte{}, b.data...)) + } + c.out.freeBlock(b) + } + + // Send all the packets. + for _, packet := range packets { + if _, err := c.conn.Write(packet); err != nil { + return err + } + } + return nil +} + +// dtlsSealRecord seals a record into a block from |c.out|'s pool. +func (c *Conn) dtlsSealRecord(typ recordType, data []byte) (b *block, err error) { + recordHeaderLen := dtlsRecordHeaderLen + maxLen := c.config.Bugs.MaxHandshakeRecordLength + if maxLen <= 0 { + maxLen = 1024 + } + + b = c.out.newBlock() + + explicitIVLen := 0 + explicitIVIsSeq := false + + if cbc, ok := c.out.cipher.(cbcMode); ok { + // Block cipher modes have an explicit IV. + explicitIVLen = cbc.BlockSize() + } else if aead, ok := c.out.cipher.(*tlsAead); ok { + if aead.explicitNonce { + explicitIVLen = 8 + // The AES-GCM construction in TLS has an explicit nonce so that + // the nonce can be random. However, the nonce is only 8 bytes + // which is too small for a secure, random nonce. Therefore we + // use the sequence number as the nonce. + explicitIVIsSeq = true + } + } else if c.out.cipher != nil { + panic("Unknown cipher") + } + b.resize(recordHeaderLen + explicitIVLen + len(data)) + b.data[0] = byte(typ) + vers := c.vers + if vers == 0 { + // Some TLS servers fail if the record version is greater than + // TLS 1.0 for the initial ClientHello. + vers = VersionTLS10 + } + vers = versionToWire(vers, c.isDTLS) + b.data[1] = byte(vers >> 8) + b.data[2] = byte(vers) + // DTLS records include an explicit sequence number. + copy(b.data[3:11], c.out.outSeq[0:]) + b.data[11] = byte(len(data) >> 8) + b.data[12] = byte(len(data)) + if explicitIVLen > 0 { + explicitIV := b.data[recordHeaderLen : recordHeaderLen+explicitIVLen] + if explicitIVIsSeq { + copy(explicitIV, c.out.outSeq[:]) + } else { + if _, err = io.ReadFull(c.config.rand(), explicitIV); err != nil { + return + } + } + } + copy(b.data[recordHeaderLen+explicitIVLen:], data) + c.out.encrypt(b, explicitIVLen) + return +} + +func (c *Conn) dtlsWriteRawRecord(typ recordType, data []byte) (n int, err error) { + b, err := c.dtlsSealRecord(typ, data) + if err != nil { + return + } + + _, err = c.conn.Write(b.data) + if err != nil { + return + } + n = len(data) + + c.out.freeBlock(b) + + if typ == recordTypeChangeCipherSpec { + err = c.out.changeCipherSpec(c.config) + if err != nil { + // Cannot call sendAlert directly, + // because we already hold c.out.Mutex. + c.tmp[0] = alertLevelError + c.tmp[1] = byte(err.(alert)) + c.writeRecord(recordTypeAlert, c.tmp[0:2]) + return n, c.out.setErrorLocked(&net.OpError{Op: "local error", Err: err}) + } + } + return +} + +func (c *Conn) dtlsDoReadHandshake() ([]byte, error) { + // Assemble a full handshake message. For test purposes, this + // implementation assumes fragments arrive in order. It may + // need to be cleverer if we ever test BoringSSL's retransmit + // behavior. + for len(c.handMsg) < 4+c.handMsgLen { + // Get a new handshake record if the previous has been + // exhausted. + if c.hand.Len() == 0 { + if err := c.in.err; err != nil { + return nil, err + } + if err := c.readRecord(recordTypeHandshake); err != nil { + return nil, err + } + } + + // Read the next fragment. It must fit entirely within + // the record. + if c.hand.Len() < 12 { + return nil, errors.New("dtls: bad handshake record") + } + header := c.hand.Next(12) + fragN := int(header[1])<<16 | int(header[2])<<8 | int(header[3]) + fragSeq := uint16(header[4])<<8 | uint16(header[5]) + fragOff := int(header[6])<<16 | int(header[7])<<8 | int(header[8]) + fragLen := int(header[9])<<16 | int(header[10])<<8 | int(header[11]) + + if c.hand.Len() < fragLen { + return nil, errors.New("dtls: fragment length too long") + } + fragment := c.hand.Next(fragLen) + + // Check it's a fragment for the right message. + if fragSeq != c.recvHandshakeSeq { + return nil, errors.New("dtls: bad handshake sequence number") + } + + // Check that the length is consistent. + if c.handMsg == nil { + c.handMsgLen = fragN + if c.handMsgLen > maxHandshake { + return nil, c.in.setErrorLocked(c.sendAlert(alertInternalError)) + } + // Start with the TLS handshake header, + // without the DTLS bits. + c.handMsg = append([]byte{}, header[:4]...) + } else if fragN != c.handMsgLen { + return nil, errors.New("dtls: bad handshake length") + } + + // Add the fragment to the pending message. + if 4+fragOff != len(c.handMsg) { + return nil, errors.New("dtls: bad fragment offset") + } + if fragOff+fragLen > c.handMsgLen { + return nil, errors.New("dtls: bad fragment length") + } + c.handMsg = append(c.handMsg, fragment...) + } + c.recvHandshakeSeq++ + ret := c.handMsg + c.handMsg, c.handMsgLen = nil, 0 + return ret, nil +} + +// DTLSServer returns a new DTLS server side connection +// using conn as the underlying transport. +// The configuration config must be non-nil and must have +// at least one certificate. +func DTLSServer(conn net.Conn, config *Config) *Conn { + c := &Conn{config: config, isDTLS: true, conn: conn} + c.init() + return c +} + +// DTLSClient returns a new DTLS client side connection +// using conn as the underlying transport. +// The config cannot be nil: users must set either ServerHostname or +// InsecureSkipVerify in the config. +func DTLSClient(conn net.Conn, config *Config) *Conn { + c := &Conn{config: config, isClient: true, isDTLS: true, conn: conn} + c.init() + return c +} diff --git a/external/boringssl/ssl/test/runner/ecdsa_cert.pem b/external/boringssl/ssl/test/runner/ecdsa_cert.pem new file mode 100644 index 0000000000..50bcbf5bfd --- /dev/null +++ b/external/boringssl/ssl/test/runner/ecdsa_cert.pem @@ -0,0 +1,12 @@ +-----BEGIN CERTIFICATE----- +MIIBzzCCAXagAwIBAgIJANlMBNpJfb/rMAkGByqGSM49BAEwRTELMAkGA1UEBhMC +QVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdp +dHMgUHR5IEx0ZDAeFw0xNDA0MjMyMzIxNTdaFw0xNDA1MjMyMzIxNTdaMEUxCzAJ +BgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5l +dCBXaWRnaXRzIFB0eSBMdGQwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATmK2ni +v2Wfl74vHg2UikzVl2u3qR4NRvvdqakendy6WgHn1peoChj5w8SjHlbifINI2xYa +HPUdfvGULUvPciLBo1AwTjAdBgNVHQ4EFgQUq4TSrKuV8IJOFngHVVdf5CaNgtEw +HwYDVR0jBBgwFoAUq4TSrKuV8IJOFngHVVdf5CaNgtEwDAYDVR0TBAUwAwEB/zAJ +BgcqhkjOPQQBA0gAMEUCIQDyoDVeUTo2w4J5m+4nUIWOcAZ0lVfSKXQA9L4Vh13E +BwIgfB55FGohg/B6dGh5XxSZmmi08cueFV7mHzJSYV51yRQ= +-----END CERTIFICATE----- diff --git a/external/boringssl/ssl/test/runner/ecdsa_key.pem b/external/boringssl/ssl/test/runner/ecdsa_key.pem new file mode 100644 index 0000000000..b9116f0cac --- /dev/null +++ b/external/boringssl/ssl/test/runner/ecdsa_key.pem @@ -0,0 +1,8 @@ +-----BEGIN EC PARAMETERS----- +BggqhkjOPQMBBw== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIAcPCHJ61KBKnN1ZyU2JaHcItW/JXTB3DujRyc4Ki7RqoAoGCCqGSM49 +AwEHoUQDQgAE5itp4r9ln5e+Lx4NlIpM1Zdrt6keDUb73ampHp3culoB59aXqAoY ++cPEox5W4nyDSNsWGhz1HX7xlC1Lz3IiwQ== +-----END EC PRIVATE KEY----- diff --git a/external/boringssl/ssl/test/runner/handshake_client.go b/external/boringssl/ssl/test/runner/handshake_client.go new file mode 100644 index 0000000000..67609fcd6c --- /dev/null +++ b/external/boringssl/ssl/test/runner/handshake_client.go @@ -0,0 +1,1016 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package runner + +import ( + "bytes" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rsa" + "crypto/subtle" + "crypto/x509" + "encoding/asn1" + "errors" + "fmt" + "io" + "math/big" + "net" + "strconv" +) + +type clientHandshakeState struct { + c *Conn + serverHello *serverHelloMsg + hello *clientHelloMsg + suite *cipherSuite + finishedHash finishedHash + masterSecret []byte + session *ClientSessionState + finishedBytes []byte +} + +func (c *Conn) clientHandshake() error { + if c.config == nil { + c.config = defaultConfig() + } + + if len(c.config.ServerName) == 0 && !c.config.InsecureSkipVerify { + return errors.New("tls: either ServerName or InsecureSkipVerify must be specified in the tls.Config") + } + + c.sendHandshakeSeq = 0 + c.recvHandshakeSeq = 0 + + nextProtosLength := 0 + for _, proto := range c.config.NextProtos { + if l := len(proto); l > 255 { + return errors.New("tls: invalid NextProtos value") + } else { + nextProtosLength += 1 + l + } + } + if nextProtosLength > 0xffff { + return errors.New("tls: NextProtos values too large") + } + + hello := &clientHelloMsg{ + isDTLS: c.isDTLS, + vers: c.config.maxVersion(), + compressionMethods: []uint8{compressionNone}, + random: make([]byte, 32), + ocspStapling: true, + sctListSupported: true, + serverName: c.config.ServerName, + supportedCurves: c.config.curvePreferences(), + supportedPoints: []uint8{pointFormatUncompressed}, + nextProtoNeg: len(c.config.NextProtos) > 0, + secureRenegotiation: []byte{}, + alpnProtocols: c.config.NextProtos, + duplicateExtension: c.config.Bugs.DuplicateExtension, + channelIDSupported: c.config.ChannelID != nil, + npnLast: c.config.Bugs.SwapNPNAndALPN, + extendedMasterSecret: c.config.maxVersion() >= VersionTLS10, + srtpProtectionProfiles: c.config.SRTPProtectionProfiles, + srtpMasterKeyIdentifier: c.config.Bugs.SRTPMasterKeyIdentifer, + customExtension: c.config.Bugs.CustomExtension, + } + + if c.config.Bugs.SendClientVersion != 0 { + hello.vers = c.config.Bugs.SendClientVersion + } + + if c.config.Bugs.NoExtendedMasterSecret { + hello.extendedMasterSecret = false + } + + if c.config.Bugs.NoSupportedCurves { + hello.supportedCurves = nil + } + + if len(c.clientVerify) > 0 && !c.config.Bugs.EmptyRenegotiationInfo { + if c.config.Bugs.BadRenegotiationInfo { + hello.secureRenegotiation = append(hello.secureRenegotiation, c.clientVerify...) + hello.secureRenegotiation[0] ^= 0x80 + } else { + hello.secureRenegotiation = c.clientVerify + } + } + + if c.noRenegotiationInfo() { + hello.secureRenegotiation = nil + } + + possibleCipherSuites := c.config.cipherSuites() + hello.cipherSuites = make([]uint16, 0, len(possibleCipherSuites)) + +NextCipherSuite: + for _, suiteId := range possibleCipherSuites { + for _, suite := range cipherSuites { + if suite.id != suiteId { + continue + } + // Don't advertise TLS 1.2-only cipher suites unless + // we're attempting TLS 1.2. + if hello.vers < VersionTLS12 && suite.flags&suiteTLS12 != 0 { + continue + } + // Don't advertise non-DTLS cipher suites on DTLS. + if c.isDTLS && suite.flags&suiteNoDTLS != 0 && !c.config.Bugs.EnableAllCiphersInDTLS { + continue + } + hello.cipherSuites = append(hello.cipherSuites, suiteId) + continue NextCipherSuite + } + } + + if c.config.Bugs.SendRenegotiationSCSV { + hello.cipherSuites = append(hello.cipherSuites, renegotiationSCSV) + } + + if c.config.Bugs.SendFallbackSCSV { + hello.cipherSuites = append(hello.cipherSuites, fallbackSCSV) + } + + _, err := io.ReadFull(c.config.rand(), hello.random) + if err != nil { + c.sendAlert(alertInternalError) + return errors.New("tls: short read from Rand: " + err.Error()) + } + + if hello.vers >= VersionTLS12 && !c.config.Bugs.NoSignatureAndHashes { + hello.signatureAndHashes = c.config.signatureAndHashesForClient() + } + + var session *ClientSessionState + var cacheKey string + sessionCache := c.config.ClientSessionCache + + if sessionCache != nil { + hello.ticketSupported = !c.config.SessionTicketsDisabled + + // Try to resume a previously negotiated TLS session, if + // available. + cacheKey = clientSessionCacheKey(c.conn.RemoteAddr(), c.config) + candidateSession, ok := sessionCache.Get(cacheKey) + if ok { + ticketOk := !c.config.SessionTicketsDisabled || candidateSession.sessionTicket == nil + + // Check that the ciphersuite/version used for the + // previous session are still valid. + cipherSuiteOk := false + for _, id := range hello.cipherSuites { + if id == candidateSession.cipherSuite { + cipherSuiteOk = true + break + } + } + + versOk := candidateSession.vers >= c.config.minVersion() && + candidateSession.vers <= c.config.maxVersion() + if ticketOk && versOk && cipherSuiteOk { + session = candidateSession + } + } + } + + if session != nil { + if session.sessionTicket != nil { + hello.sessionTicket = session.sessionTicket + if c.config.Bugs.CorruptTicket { + hello.sessionTicket = make([]byte, len(session.sessionTicket)) + copy(hello.sessionTicket, session.sessionTicket) + if len(hello.sessionTicket) > 0 { + offset := 40 + if offset > len(hello.sessionTicket) { + offset = len(hello.sessionTicket) - 1 + } + hello.sessionTicket[offset] ^= 0x40 + } + } + // A random session ID is used to detect when the + // server accepted the ticket and is resuming a session + // (see RFC 5077). + sessionIdLen := 16 + if c.config.Bugs.OversizedSessionId { + sessionIdLen = 33 + } + hello.sessionId = make([]byte, sessionIdLen) + if _, err := io.ReadFull(c.config.rand(), hello.sessionId); err != nil { + c.sendAlert(alertInternalError) + return errors.New("tls: short read from Rand: " + err.Error()) + } + } else { + hello.sessionId = session.sessionId + } + } + + var helloBytes []byte + if c.config.Bugs.SendV2ClientHello { + // Test that the peer left-pads random. + hello.random[0] = 0 + v2Hello := &v2ClientHelloMsg{ + vers: hello.vers, + cipherSuites: hello.cipherSuites, + // No session resumption for V2ClientHello. + sessionId: nil, + challenge: hello.random[1:], + } + helloBytes = v2Hello.marshal() + c.writeV2Record(helloBytes) + } else { + helloBytes = hello.marshal() + c.writeRecord(recordTypeHandshake, helloBytes) + } + c.dtlsFlushHandshake() + + if err := c.simulatePacketLoss(nil); err != nil { + return err + } + msg, err := c.readHandshake() + if err != nil { + return err + } + + if c.isDTLS { + helloVerifyRequest, ok := msg.(*helloVerifyRequestMsg) + if ok { + if helloVerifyRequest.vers != VersionTLS10 { + // Per RFC 6347, the version field in + // HelloVerifyRequest SHOULD be always DTLS + // 1.0. Enforce this for testing purposes. + return errors.New("dtls: bad HelloVerifyRequest version") + } + + hello.raw = nil + hello.cookie = helloVerifyRequest.cookie + helloBytes = hello.marshal() + c.writeRecord(recordTypeHandshake, helloBytes) + c.dtlsFlushHandshake() + + if err := c.simulatePacketLoss(nil); err != nil { + return err + } + msg, err = c.readHandshake() + if err != nil { + return err + } + } + } + + serverHello, ok := msg.(*serverHelloMsg) + if !ok { + c.sendAlert(alertUnexpectedMessage) + return unexpectedMessageError(serverHello, msg) + } + + c.vers, ok = c.config.mutualVersion(serverHello.vers) + if !ok { + c.sendAlert(alertProtocolVersion) + return fmt.Errorf("tls: server selected unsupported protocol version %x", serverHello.vers) + } + c.haveVers = true + + suite := mutualCipherSuite(c.config.cipherSuites(), serverHello.cipherSuite) + if suite == nil { + c.sendAlert(alertHandshakeFailure) + return fmt.Errorf("tls: server selected an unsupported cipher suite") + } + + if c.config.Bugs.RequireRenegotiationInfo && serverHello.secureRenegotiation == nil { + return errors.New("tls: renegotiation extension missing") + } + + if len(c.clientVerify) > 0 && !c.noRenegotiationInfo() { + var expectedRenegInfo []byte + expectedRenegInfo = append(expectedRenegInfo, c.clientVerify...) + expectedRenegInfo = append(expectedRenegInfo, c.serverVerify...) + if !bytes.Equal(serverHello.secureRenegotiation, expectedRenegInfo) { + c.sendAlert(alertHandshakeFailure) + return fmt.Errorf("tls: renegotiation mismatch") + } + } + + if expected := c.config.Bugs.ExpectedCustomExtension; expected != nil { + if serverHello.customExtension != *expected { + return fmt.Errorf("tls: bad custom extension contents %q", serverHello.customExtension) + } + } + + hs := &clientHandshakeState{ + c: c, + serverHello: serverHello, + hello: hello, + suite: suite, + finishedHash: newFinishedHash(c.vers, suite), + session: session, + } + + hs.writeHash(helloBytes, hs.c.sendHandshakeSeq-1) + hs.writeServerHash(hs.serverHello.marshal()) + + if c.config.Bugs.EarlyChangeCipherSpec > 0 { + hs.establishKeys() + c.writeRecord(recordTypeChangeCipherSpec, []byte{1}) + } + + isResume, err := hs.processServerHello() + if err != nil { + return err + } + + if isResume { + if c.config.Bugs.EarlyChangeCipherSpec == 0 { + if err := hs.establishKeys(); err != nil { + return err + } + } + if err := hs.readSessionTicket(); err != nil { + return err + } + if err := hs.readFinished(c.firstFinished[:]); err != nil { + return err + } + if err := hs.sendFinished(nil, isResume); err != nil { + return err + } + } else { + if err := hs.doFullHandshake(); err != nil { + return err + } + if err := hs.establishKeys(); err != nil { + return err + } + if err := hs.sendFinished(c.firstFinished[:], isResume); err != nil { + return err + } + // Most retransmits are triggered by a timeout, but the final + // leg of the handshake is retransmited upon re-receiving a + // Finished. + if err := c.simulatePacketLoss(func() { + c.writeRecord(recordTypeHandshake, hs.finishedBytes) + c.dtlsFlushHandshake() + }); err != nil { + return err + } + if err := hs.readSessionTicket(); err != nil { + return err + } + if err := hs.readFinished(nil); err != nil { + return err + } + } + + if sessionCache != nil && hs.session != nil && session != hs.session { + if c.config.Bugs.RequireSessionTickets && len(hs.session.sessionTicket) == 0 { + return errors.New("tls: new session used session IDs instead of tickets") + } + sessionCache.Put(cacheKey, hs.session) + } + + c.didResume = isResume + c.handshakeComplete = true + c.cipherSuite = suite + copy(c.clientRandom[:], hs.hello.random) + copy(c.serverRandom[:], hs.serverHello.random) + copy(c.masterSecret[:], hs.masterSecret) + + return nil +} + +func (hs *clientHandshakeState) doFullHandshake() error { + c := hs.c + + var leaf *x509.Certificate + if hs.suite.flags&suitePSK == 0 { + msg, err := c.readHandshake() + if err != nil { + return err + } + + certMsg, ok := msg.(*certificateMsg) + if !ok || len(certMsg.certificates) == 0 { + c.sendAlert(alertUnexpectedMessage) + return unexpectedMessageError(certMsg, msg) + } + hs.writeServerHash(certMsg.marshal()) + + certs := make([]*x509.Certificate, len(certMsg.certificates)) + for i, asn1Data := range certMsg.certificates { + cert, err := x509.ParseCertificate(asn1Data) + if err != nil { + c.sendAlert(alertBadCertificate) + return errors.New("tls: failed to parse certificate from server: " + err.Error()) + } + certs[i] = cert + } + leaf = certs[0] + + if !c.config.InsecureSkipVerify { + opts := x509.VerifyOptions{ + Roots: c.config.RootCAs, + CurrentTime: c.config.time(), + DNSName: c.config.ServerName, + Intermediates: x509.NewCertPool(), + } + + for i, cert := range certs { + if i == 0 { + continue + } + opts.Intermediates.AddCert(cert) + } + c.verifiedChains, err = leaf.Verify(opts) + if err != nil { + c.sendAlert(alertBadCertificate) + return err + } + } + + switch leaf.PublicKey.(type) { + case *rsa.PublicKey, *ecdsa.PublicKey: + break + default: + c.sendAlert(alertUnsupportedCertificate) + return fmt.Errorf("tls: server's certificate contains an unsupported type of public key: %T", leaf.PublicKey) + } + + c.peerCertificates = certs + } + + if hs.serverHello.ocspStapling { + msg, err := c.readHandshake() + if err != nil { + return err + } + cs, ok := msg.(*certificateStatusMsg) + if !ok { + c.sendAlert(alertUnexpectedMessage) + return unexpectedMessageError(cs, msg) + } + hs.writeServerHash(cs.marshal()) + + if cs.statusType == statusTypeOCSP { + c.ocspResponse = cs.response + } + } + + msg, err := c.readHandshake() + if err != nil { + return err + } + + keyAgreement := hs.suite.ka(c.vers) + + skx, ok := msg.(*serverKeyExchangeMsg) + if ok { + hs.writeServerHash(skx.marshal()) + err = keyAgreement.processServerKeyExchange(c.config, hs.hello, hs.serverHello, leaf, skx) + if err != nil { + c.sendAlert(alertUnexpectedMessage) + return err + } + + msg, err = c.readHandshake() + if err != nil { + return err + } + } + + var chainToSend *Certificate + var certRequested bool + certReq, ok := msg.(*certificateRequestMsg) + if ok { + certRequested = true + + // RFC 4346 on the certificateAuthorities field: + // A list of the distinguished names of acceptable certificate + // authorities. These distinguished names may specify a desired + // distinguished name for a root CA or for a subordinate CA; + // thus, this message can be used to describe both known roots + // and a desired authorization space. If the + // certificate_authorities list is empty then the client MAY + // send any certificate of the appropriate + // ClientCertificateType, unless there is some external + // arrangement to the contrary. + + hs.writeServerHash(certReq.marshal()) + + var rsaAvail, ecdsaAvail bool + for _, certType := range certReq.certificateTypes { + switch certType { + case CertTypeRSASign: + rsaAvail = true + case CertTypeECDSASign: + ecdsaAvail = true + } + } + + // We need to search our list of client certs for one + // where SignatureAlgorithm is RSA and the Issuer is in + // certReq.certificateAuthorities + findCert: + for i, chain := range c.config.Certificates { + if !rsaAvail && !ecdsaAvail { + continue + } + + for j, cert := range chain.Certificate { + x509Cert := chain.Leaf + // parse the certificate if this isn't the leaf + // node, or if chain.Leaf was nil + if j != 0 || x509Cert == nil { + if x509Cert, err = x509.ParseCertificate(cert); err != nil { + c.sendAlert(alertInternalError) + return errors.New("tls: failed to parse client certificate #" + strconv.Itoa(i) + ": " + err.Error()) + } + } + + switch { + case rsaAvail && x509Cert.PublicKeyAlgorithm == x509.RSA: + case ecdsaAvail && x509Cert.PublicKeyAlgorithm == x509.ECDSA: + default: + continue findCert + } + + if len(certReq.certificateAuthorities) == 0 { + // they gave us an empty list, so just take the + // first RSA cert from c.config.Certificates + chainToSend = &chain + break findCert + } + + for _, ca := range certReq.certificateAuthorities { + if bytes.Equal(x509Cert.RawIssuer, ca) { + chainToSend = &chain + break findCert + } + } + } + } + + msg, err = c.readHandshake() + if err != nil { + return err + } + } + + shd, ok := msg.(*serverHelloDoneMsg) + if !ok { + c.sendAlert(alertUnexpectedMessage) + return unexpectedMessageError(shd, msg) + } + hs.writeServerHash(shd.marshal()) + + // If the server requested a certificate then we have to send a + // Certificate message in TLS, even if it's empty because we don't have + // a certificate to send. In SSL 3.0, skip the message and send a + // no_certificate warning alert. + if certRequested { + if c.vers == VersionSSL30 && chainToSend == nil { + c.sendAlert(alertNoCertficate) + } else if !c.config.Bugs.SkipClientCertificate { + certMsg := new(certificateMsg) + if chainToSend != nil { + certMsg.certificates = chainToSend.Certificate + } + hs.writeClientHash(certMsg.marshal()) + c.writeRecord(recordTypeHandshake, certMsg.marshal()) + } + } + + preMasterSecret, ckx, err := keyAgreement.generateClientKeyExchange(c.config, hs.hello, leaf) + if err != nil { + c.sendAlert(alertInternalError) + return err + } + if ckx != nil { + if c.config.Bugs.EarlyChangeCipherSpec < 2 { + hs.writeClientHash(ckx.marshal()) + } + c.writeRecord(recordTypeHandshake, ckx.marshal()) + } + + if hs.serverHello.extendedMasterSecret && c.vers >= VersionTLS10 { + hs.masterSecret = extendedMasterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.finishedHash) + c.extendedMasterSecret = true + } else { + if c.config.Bugs.RequireExtendedMasterSecret { + return errors.New("tls: extended master secret required but not supported by peer") + } + hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.hello.random, hs.serverHello.random) + } + + if chainToSend != nil { + var signed []byte + certVerify := &certificateVerifyMsg{ + hasSignatureAndHash: c.vers >= VersionTLS12, + } + + // Determine the hash to sign. + var signatureType uint8 + switch c.config.Certificates[0].PrivateKey.(type) { + case *ecdsa.PrivateKey: + signatureType = signatureECDSA + case *rsa.PrivateKey: + signatureType = signatureRSA + default: + c.sendAlert(alertInternalError) + return errors.New("unknown private key type") + } + if c.config.Bugs.IgnorePeerSignatureAlgorithmPreferences { + certReq.signatureAndHashes = c.config.signatureAndHashesForClient() + } + certVerify.signatureAndHash, err = hs.finishedHash.selectClientCertSignatureAlgorithm(certReq.signatureAndHashes, c.config.signatureAndHashesForClient(), signatureType) + if err != nil { + c.sendAlert(alertInternalError) + return err + } + digest, hashFunc, err := hs.finishedHash.hashForClientCertificate(certVerify.signatureAndHash, hs.masterSecret) + if err != nil { + c.sendAlert(alertInternalError) + return err + } + if c.config.Bugs.InvalidCertVerifySignature { + digest[0] ^= 0x80 + } + + switch key := c.config.Certificates[0].PrivateKey.(type) { + case *ecdsa.PrivateKey: + var r, s *big.Int + r, s, err = ecdsa.Sign(c.config.rand(), key, digest) + if err == nil { + signed, err = asn1.Marshal(ecdsaSignature{r, s}) + } + case *rsa.PrivateKey: + signed, err = rsa.SignPKCS1v15(c.config.rand(), key, hashFunc, digest) + default: + err = errors.New("unknown private key type") + } + if err != nil { + c.sendAlert(alertInternalError) + return errors.New("tls: failed to sign handshake with client certificate: " + err.Error()) + } + certVerify.signature = signed + + hs.writeClientHash(certVerify.marshal()) + c.writeRecord(recordTypeHandshake, certVerify.marshal()) + } + c.dtlsFlushHandshake() + + hs.finishedHash.discardHandshakeBuffer() + + return nil +} + +func (hs *clientHandshakeState) establishKeys() error { + c := hs.c + + clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV := + keysFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.hello.random, hs.serverHello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen) + var clientCipher, serverCipher interface{} + var clientHash, serverHash macFunction + if hs.suite.cipher != nil { + clientCipher = hs.suite.cipher(clientKey, clientIV, false /* not for reading */) + clientHash = hs.suite.mac(c.vers, clientMAC) + serverCipher = hs.suite.cipher(serverKey, serverIV, true /* for reading */) + serverHash = hs.suite.mac(c.vers, serverMAC) + } else { + clientCipher = hs.suite.aead(clientKey, clientIV) + serverCipher = hs.suite.aead(serverKey, serverIV) + } + + c.in.prepareCipherSpec(c.vers, serverCipher, serverHash) + c.out.prepareCipherSpec(c.vers, clientCipher, clientHash) + return nil +} + +func (hs *clientHandshakeState) serverResumedSession() bool { + // If the server responded with the same sessionId then it means the + // sessionTicket is being used to resume a TLS session. + return hs.session != nil && hs.hello.sessionId != nil && + bytes.Equal(hs.serverHello.sessionId, hs.hello.sessionId) +} + +func (hs *clientHandshakeState) processServerHello() (bool, error) { + c := hs.c + + if hs.serverHello.compressionMethod != compressionNone { + c.sendAlert(alertUnexpectedMessage) + return false, errors.New("tls: server selected unsupported compression format") + } + + clientDidNPN := hs.hello.nextProtoNeg + clientDidALPN := len(hs.hello.alpnProtocols) > 0 + serverHasNPN := hs.serverHello.nextProtoNeg + serverHasALPN := len(hs.serverHello.alpnProtocol) > 0 + + if !clientDidNPN && serverHasNPN { + c.sendAlert(alertHandshakeFailure) + return false, errors.New("server advertised unrequested NPN extension") + } + + if !clientDidALPN && serverHasALPN { + c.sendAlert(alertHandshakeFailure) + return false, errors.New("server advertised unrequested ALPN extension") + } + + if serverHasNPN && serverHasALPN { + c.sendAlert(alertHandshakeFailure) + return false, errors.New("server advertised both NPN and ALPN extensions") + } + + if serverHasALPN { + c.clientProtocol = hs.serverHello.alpnProtocol + c.clientProtocolFallback = false + c.usedALPN = true + } + + if !hs.hello.channelIDSupported && hs.serverHello.channelIDRequested { + c.sendAlert(alertHandshakeFailure) + return false, errors.New("server advertised unrequested Channel ID extension") + } + + if hs.serverHello.srtpProtectionProfile != 0 { + if hs.serverHello.srtpMasterKeyIdentifier != "" { + return false, errors.New("tls: server selected SRTP MKI value") + } + + found := false + for _, p := range c.config.SRTPProtectionProfiles { + if p == hs.serverHello.srtpProtectionProfile { + found = true + break + } + } + if !found { + return false, errors.New("tls: server advertised unsupported SRTP profile") + } + + c.srtpProtectionProfile = hs.serverHello.srtpProtectionProfile + } + + if hs.serverResumedSession() { + // For test purposes, assert that the server never accepts the + // resumption offer on renegotiation. + if c.cipherSuite != nil && c.config.Bugs.FailIfResumeOnRenego { + return false, errors.New("tls: server resumed session on renegotiation") + } + + if hs.serverHello.sctList != nil { + return false, errors.New("tls: server sent SCT extension on session resumption") + } + + if hs.serverHello.ocspStapling { + return false, errors.New("tls: server sent OCSP extension on session resumption") + } + + // Restore masterSecret and peerCerts from previous state + hs.masterSecret = hs.session.masterSecret + c.peerCertificates = hs.session.serverCertificates + c.extendedMasterSecret = hs.session.extendedMasterSecret + c.sctList = hs.session.sctList + c.ocspResponse = hs.session.ocspResponse + hs.finishedHash.discardHandshakeBuffer() + return true, nil + } + + if hs.serverHello.sctList != nil { + c.sctList = hs.serverHello.sctList + } + + return false, nil +} + +func (hs *clientHandshakeState) readFinished(out []byte) error { + c := hs.c + + c.readRecord(recordTypeChangeCipherSpec) + if err := c.in.error(); err != nil { + return err + } + + msg, err := c.readHandshake() + if err != nil { + return err + } + serverFinished, ok := msg.(*finishedMsg) + if !ok { + c.sendAlert(alertUnexpectedMessage) + return unexpectedMessageError(serverFinished, msg) + } + + if c.config.Bugs.EarlyChangeCipherSpec == 0 { + verify := hs.finishedHash.serverSum(hs.masterSecret) + if len(verify) != len(serverFinished.verifyData) || + subtle.ConstantTimeCompare(verify, serverFinished.verifyData) != 1 { + c.sendAlert(alertHandshakeFailure) + return errors.New("tls: server's Finished message was incorrect") + } + } + c.serverVerify = append(c.serverVerify[:0], serverFinished.verifyData...) + copy(out, serverFinished.verifyData) + hs.writeServerHash(serverFinished.marshal()) + return nil +} + +func (hs *clientHandshakeState) readSessionTicket() error { + c := hs.c + + // Create a session with no server identifier. Either a + // session ID or session ticket will be attached. + session := &ClientSessionState{ + vers: c.vers, + cipherSuite: hs.suite.id, + masterSecret: hs.masterSecret, + handshakeHash: hs.finishedHash.server.Sum(nil), + serverCertificates: c.peerCertificates, + sctList: c.sctList, + ocspResponse: c.ocspResponse, + } + + if !hs.serverHello.ticketSupported { + if c.config.Bugs.ExpectNewTicket { + return errors.New("tls: expected new ticket") + } + if hs.session == nil && len(hs.serverHello.sessionId) > 0 { + session.sessionId = hs.serverHello.sessionId + hs.session = session + } + return nil + } + + if c.vers == VersionSSL30 { + return errors.New("tls: negotiated session tickets in SSL 3.0") + } + + msg, err := c.readHandshake() + if err != nil { + return err + } + sessionTicketMsg, ok := msg.(*newSessionTicketMsg) + if !ok { + c.sendAlert(alertUnexpectedMessage) + return unexpectedMessageError(sessionTicketMsg, msg) + } + + session.sessionTicket = sessionTicketMsg.ticket + hs.session = session + + hs.writeServerHash(sessionTicketMsg.marshal()) + + return nil +} + +func (hs *clientHandshakeState) sendFinished(out []byte, isResume bool) error { + c := hs.c + + var postCCSBytes []byte + seqno := hs.c.sendHandshakeSeq + if hs.serverHello.nextProtoNeg { + nextProto := new(nextProtoMsg) + proto, fallback := mutualProtocol(c.config.NextProtos, hs.serverHello.nextProtos) + nextProto.proto = proto + c.clientProtocol = proto + c.clientProtocolFallback = fallback + + nextProtoBytes := nextProto.marshal() + hs.writeHash(nextProtoBytes, seqno) + seqno++ + postCCSBytes = append(postCCSBytes, nextProtoBytes...) + } + + if hs.serverHello.channelIDRequested { + encryptedExtensions := new(encryptedExtensionsMsg) + if c.config.ChannelID.Curve != elliptic.P256() { + return fmt.Errorf("tls: Channel ID is not on P-256.") + } + var resumeHash []byte + if isResume { + resumeHash = hs.session.handshakeHash + } + r, s, err := ecdsa.Sign(c.config.rand(), c.config.ChannelID, hs.finishedHash.hashForChannelID(resumeHash)) + if err != nil { + return err + } + channelID := make([]byte, 128) + writeIntPadded(channelID[0:32], c.config.ChannelID.X) + writeIntPadded(channelID[32:64], c.config.ChannelID.Y) + writeIntPadded(channelID[64:96], r) + writeIntPadded(channelID[96:128], s) + encryptedExtensions.channelID = channelID + + c.channelID = &c.config.ChannelID.PublicKey + + encryptedExtensionsBytes := encryptedExtensions.marshal() + hs.writeHash(encryptedExtensionsBytes, seqno) + seqno++ + postCCSBytes = append(postCCSBytes, encryptedExtensionsBytes...) + } + + finished := new(finishedMsg) + if c.config.Bugs.EarlyChangeCipherSpec == 2 { + finished.verifyData = hs.finishedHash.clientSum(nil) + } else { + finished.verifyData = hs.finishedHash.clientSum(hs.masterSecret) + } + copy(out, finished.verifyData) + if c.config.Bugs.BadFinished { + finished.verifyData[0]++ + } + c.clientVerify = append(c.clientVerify[:0], finished.verifyData...) + hs.finishedBytes = finished.marshal() + hs.writeHash(hs.finishedBytes, seqno) + postCCSBytes = append(postCCSBytes, hs.finishedBytes...) + + if c.config.Bugs.FragmentAcrossChangeCipherSpec { + c.writeRecord(recordTypeHandshake, postCCSBytes[:5]) + postCCSBytes = postCCSBytes[5:] + } + c.dtlsFlushHandshake() + + if !c.config.Bugs.SkipChangeCipherSpec && + c.config.Bugs.EarlyChangeCipherSpec == 0 { + ccs := []byte{1} + if c.config.Bugs.BadChangeCipherSpec != nil { + ccs = c.config.Bugs.BadChangeCipherSpec + } + c.writeRecord(recordTypeChangeCipherSpec, ccs) + } + + if c.config.Bugs.AppDataAfterChangeCipherSpec != nil { + c.writeRecord(recordTypeApplicationData, c.config.Bugs.AppDataAfterChangeCipherSpec) + } + if c.config.Bugs.AlertAfterChangeCipherSpec != 0 { + c.sendAlert(c.config.Bugs.AlertAfterChangeCipherSpec) + return errors.New("tls: simulating post-CCS alert") + } + + if !c.config.Bugs.SkipFinished { + c.writeRecord(recordTypeHandshake, postCCSBytes) + c.dtlsFlushHandshake() + } + return nil +} + +func (hs *clientHandshakeState) writeClientHash(msg []byte) { + // writeClientHash is called before writeRecord. + hs.writeHash(msg, hs.c.sendHandshakeSeq) +} + +func (hs *clientHandshakeState) writeServerHash(msg []byte) { + // writeServerHash is called after readHandshake. + hs.writeHash(msg, hs.c.recvHandshakeSeq-1) +} + +func (hs *clientHandshakeState) writeHash(msg []byte, seqno uint16) { + if hs.c.isDTLS { + // This is somewhat hacky. DTLS hashes a slightly different format. + // First, the TLS header. + hs.finishedHash.Write(msg[:4]) + // Then the sequence number and reassembled fragment offset (always 0). + hs.finishedHash.Write([]byte{byte(seqno >> 8), byte(seqno), 0, 0, 0}) + // Then the reassembled fragment (always equal to the message length). + hs.finishedHash.Write(msg[1:4]) + // And then the message body. + hs.finishedHash.Write(msg[4:]) + } else { + hs.finishedHash.Write(msg) + } +} + +// clientSessionCacheKey returns a key used to cache sessionTickets that could +// be used to resume previously negotiated TLS sessions with a server. +func clientSessionCacheKey(serverAddr net.Addr, config *Config) string { + if len(config.ServerName) > 0 { + return config.ServerName + } + return serverAddr.String() +} + +// mutualProtocol finds the mutual Next Protocol Negotiation or ALPN protocol +// given list of possible protocols and a list of the preference order. The +// first list must not be empty. It returns the resulting protocol and flag +// indicating if the fallback case was reached. +func mutualProtocol(protos, preferenceProtos []string) (string, bool) { + for _, s := range preferenceProtos { + for _, c := range protos { + if s == c { + return s, false + } + } + } + + return protos[0], true +} + +// writeIntPadded writes x into b, padded up with leading zeros as +// needed. +func writeIntPadded(b []byte, x *big.Int) { + for i := range b { + b[i] = 0 + } + xb := x.Bytes() + copy(b[len(b)-len(xb):], xb) +} diff --git a/external/boringssl/ssl/test/runner/handshake_messages.go b/external/boringssl/ssl/test/runner/handshake_messages.go new file mode 100644 index 0000000000..092f51ef49 --- /dev/null +++ b/external/boringssl/ssl/test/runner/handshake_messages.go @@ -0,0 +1,1759 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package runner + +import "bytes" + +type clientHelloMsg struct { + raw []byte + isDTLS bool + vers uint16 + random []byte + sessionId []byte + cookie []byte + cipherSuites []uint16 + compressionMethods []uint8 + nextProtoNeg bool + serverName string + ocspStapling bool + supportedCurves []CurveID + supportedPoints []uint8 + ticketSupported bool + sessionTicket []uint8 + signatureAndHashes []signatureAndHash + secureRenegotiation []byte + alpnProtocols []string + duplicateExtension bool + channelIDSupported bool + npnLast bool + extendedMasterSecret bool + srtpProtectionProfiles []uint16 + srtpMasterKeyIdentifier string + sctListSupported bool + customExtension string +} + +func (m *clientHelloMsg) equal(i interface{}) bool { + m1, ok := i.(*clientHelloMsg) + if !ok { + return false + } + + return bytes.Equal(m.raw, m1.raw) && + m.isDTLS == m1.isDTLS && + m.vers == m1.vers && + bytes.Equal(m.random, m1.random) && + bytes.Equal(m.sessionId, m1.sessionId) && + bytes.Equal(m.cookie, m1.cookie) && + eqUint16s(m.cipherSuites, m1.cipherSuites) && + bytes.Equal(m.compressionMethods, m1.compressionMethods) && + m.nextProtoNeg == m1.nextProtoNeg && + m.serverName == m1.serverName && + m.ocspStapling == m1.ocspStapling && + eqCurveIDs(m.supportedCurves, m1.supportedCurves) && + bytes.Equal(m.supportedPoints, m1.supportedPoints) && + m.ticketSupported == m1.ticketSupported && + bytes.Equal(m.sessionTicket, m1.sessionTicket) && + eqSignatureAndHashes(m.signatureAndHashes, m1.signatureAndHashes) && + bytes.Equal(m.secureRenegotiation, m1.secureRenegotiation) && + (m.secureRenegotiation == nil) == (m1.secureRenegotiation == nil) && + eqStrings(m.alpnProtocols, m1.alpnProtocols) && + m.duplicateExtension == m1.duplicateExtension && + m.channelIDSupported == m1.channelIDSupported && + m.npnLast == m1.npnLast && + m.extendedMasterSecret == m1.extendedMasterSecret && + eqUint16s(m.srtpProtectionProfiles, m1.srtpProtectionProfiles) && + m.srtpMasterKeyIdentifier == m1.srtpMasterKeyIdentifier && + m.sctListSupported == m1.sctListSupported && + m.customExtension == m1.customExtension +} + +func (m *clientHelloMsg) marshal() []byte { + if m.raw != nil { + return m.raw + } + + length := 2 + 32 + 1 + len(m.sessionId) + 2 + len(m.cipherSuites)*2 + 1 + len(m.compressionMethods) + if m.isDTLS { + length += 1 + len(m.cookie) + } + numExtensions := 0 + extensionsLength := 0 + if m.nextProtoNeg { + numExtensions++ + } + if m.ocspStapling { + extensionsLength += 1 + 2 + 2 + numExtensions++ + } + if len(m.serverName) > 0 { + extensionsLength += 5 + len(m.serverName) + numExtensions++ + } + if len(m.supportedCurves) > 0 { + extensionsLength += 2 + 2*len(m.supportedCurves) + numExtensions++ + } + if len(m.supportedPoints) > 0 { + extensionsLength += 1 + len(m.supportedPoints) + numExtensions++ + } + if m.ticketSupported { + extensionsLength += len(m.sessionTicket) + numExtensions++ + } + if len(m.signatureAndHashes) > 0 { + extensionsLength += 2 + 2*len(m.signatureAndHashes) + numExtensions++ + } + if m.secureRenegotiation != nil { + extensionsLength += 1 + len(m.secureRenegotiation) + numExtensions++ + } + if m.duplicateExtension { + numExtensions += 2 + } + if m.channelIDSupported { + numExtensions++ + } + if len(m.alpnProtocols) > 0 { + extensionsLength += 2 + for _, s := range m.alpnProtocols { + if l := len(s); l > 255 { + panic("invalid ALPN protocol") + } + extensionsLength++ + extensionsLength += len(s) + } + numExtensions++ + } + if m.extendedMasterSecret { + numExtensions++ + } + if len(m.srtpProtectionProfiles) > 0 { + extensionsLength += 2 + 2*len(m.srtpProtectionProfiles) + extensionsLength += 1 + len(m.srtpMasterKeyIdentifier) + numExtensions++ + } + if m.sctListSupported { + numExtensions++ + } + if l := len(m.customExtension); l > 0 { + extensionsLength += l + numExtensions++ + } + if numExtensions > 0 { + extensionsLength += 4 * numExtensions + length += 2 + extensionsLength + } + + x := make([]byte, 4+length) + x[0] = typeClientHello + x[1] = uint8(length >> 16) + x[2] = uint8(length >> 8) + x[3] = uint8(length) + vers := versionToWire(m.vers, m.isDTLS) + x[4] = uint8(vers >> 8) + x[5] = uint8(vers) + copy(x[6:38], m.random) + x[38] = uint8(len(m.sessionId)) + copy(x[39:39+len(m.sessionId)], m.sessionId) + y := x[39+len(m.sessionId):] + if m.isDTLS { + y[0] = uint8(len(m.cookie)) + copy(y[1:], m.cookie) + y = y[1+len(m.cookie):] + } + y[0] = uint8(len(m.cipherSuites) >> 7) + y[1] = uint8(len(m.cipherSuites) << 1) + for i, suite := range m.cipherSuites { + y[2+i*2] = uint8(suite >> 8) + y[3+i*2] = uint8(suite) + } + z := y[2+len(m.cipherSuites)*2:] + z[0] = uint8(len(m.compressionMethods)) + copy(z[1:], m.compressionMethods) + + z = z[1+len(m.compressionMethods):] + if numExtensions > 0 { + z[0] = byte(extensionsLength >> 8) + z[1] = byte(extensionsLength) + z = z[2:] + } + if m.duplicateExtension { + // Add a duplicate bogus extension at the beginning and end. + z[0] = 0xff + z[1] = 0xff + z = z[4:] + } + if m.nextProtoNeg && !m.npnLast { + z[0] = byte(extensionNextProtoNeg >> 8) + z[1] = byte(extensionNextProtoNeg & 0xff) + // The length is always 0 + z = z[4:] + } + if len(m.serverName) > 0 { + z[0] = byte(extensionServerName >> 8) + z[1] = byte(extensionServerName & 0xff) + l := len(m.serverName) + 5 + z[2] = byte(l >> 8) + z[3] = byte(l) + z = z[4:] + + // RFC 3546, section 3.1 + // + // struct { + // NameType name_type; + // select (name_type) { + // case host_name: HostName; + // } name; + // } ServerName; + // + // enum { + // host_name(0), (255) + // } NameType; + // + // opaque HostName<1..2^16-1>; + // + // struct { + // ServerName server_name_list<1..2^16-1> + // } ServerNameList; + + z[0] = byte((len(m.serverName) + 3) >> 8) + z[1] = byte(len(m.serverName) + 3) + z[3] = byte(len(m.serverName) >> 8) + z[4] = byte(len(m.serverName)) + copy(z[5:], []byte(m.serverName)) + z = z[l:] + } + if m.ocspStapling { + // RFC 4366, section 3.6 + z[0] = byte(extensionStatusRequest >> 8) + z[1] = byte(extensionStatusRequest) + z[2] = 0 + z[3] = 5 + z[4] = 1 // OCSP type + // Two zero valued uint16s for the two lengths. + z = z[9:] + } + if len(m.supportedCurves) > 0 { + // http://tools.ietf.org/html/rfc4492#section-5.5.1 + z[0] = byte(extensionSupportedCurves >> 8) + z[1] = byte(extensionSupportedCurves) + l := 2 + 2*len(m.supportedCurves) + z[2] = byte(l >> 8) + z[3] = byte(l) + l -= 2 + z[4] = byte(l >> 8) + z[5] = byte(l) + z = z[6:] + for _, curve := range m.supportedCurves { + z[0] = byte(curve >> 8) + z[1] = byte(curve) + z = z[2:] + } + } + if len(m.supportedPoints) > 0 { + // http://tools.ietf.org/html/rfc4492#section-5.5.2 + z[0] = byte(extensionSupportedPoints >> 8) + z[1] = byte(extensionSupportedPoints) + l := 1 + len(m.supportedPoints) + z[2] = byte(l >> 8) + z[3] = byte(l) + l-- + z[4] = byte(l) + z = z[5:] + for _, pointFormat := range m.supportedPoints { + z[0] = byte(pointFormat) + z = z[1:] + } + } + if m.ticketSupported { + // http://tools.ietf.org/html/rfc5077#section-3.2 + z[0] = byte(extensionSessionTicket >> 8) + z[1] = byte(extensionSessionTicket) + l := len(m.sessionTicket) + z[2] = byte(l >> 8) + z[3] = byte(l) + z = z[4:] + copy(z, m.sessionTicket) + z = z[len(m.sessionTicket):] + } + if len(m.signatureAndHashes) > 0 { + // https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 + z[0] = byte(extensionSignatureAlgorithms >> 8) + z[1] = byte(extensionSignatureAlgorithms) + l := 2 + 2*len(m.signatureAndHashes) + z[2] = byte(l >> 8) + z[3] = byte(l) + z = z[4:] + + l -= 2 + z[0] = byte(l >> 8) + z[1] = byte(l) + z = z[2:] + for _, sigAndHash := range m.signatureAndHashes { + z[0] = sigAndHash.hash + z[1] = sigAndHash.signature + z = z[2:] + } + } + if m.secureRenegotiation != nil { + z[0] = byte(extensionRenegotiationInfo >> 8) + z[1] = byte(extensionRenegotiationInfo & 0xff) + z[2] = 0 + z[3] = byte(1 + len(m.secureRenegotiation)) + z[4] = byte(len(m.secureRenegotiation)) + z = z[5:] + copy(z, m.secureRenegotiation) + z = z[len(m.secureRenegotiation):] + } + if len(m.alpnProtocols) > 0 { + z[0] = byte(extensionALPN >> 8) + z[1] = byte(extensionALPN & 0xff) + lengths := z[2:] + z = z[6:] + + stringsLength := 0 + for _, s := range m.alpnProtocols { + l := len(s) + z[0] = byte(l) + copy(z[1:], s) + z = z[1+l:] + stringsLength += 1 + l + } + + lengths[2] = byte(stringsLength >> 8) + lengths[3] = byte(stringsLength) + stringsLength += 2 + lengths[0] = byte(stringsLength >> 8) + lengths[1] = byte(stringsLength) + } + if m.channelIDSupported { + z[0] = byte(extensionChannelID >> 8) + z[1] = byte(extensionChannelID & 0xff) + z = z[4:] + } + if m.nextProtoNeg && m.npnLast { + z[0] = byte(extensionNextProtoNeg >> 8) + z[1] = byte(extensionNextProtoNeg & 0xff) + // The length is always 0 + z = z[4:] + } + if m.duplicateExtension { + // Add a duplicate bogus extension at the beginning and end. + z[0] = 0xff + z[1] = 0xff + z = z[4:] + } + if m.extendedMasterSecret { + // https://tools.ietf.org/html/rfc7627 + z[0] = byte(extensionExtendedMasterSecret >> 8) + z[1] = byte(extensionExtendedMasterSecret & 0xff) + z = z[4:] + } + if len(m.srtpProtectionProfiles) > 0 { + z[0] = byte(extensionUseSRTP >> 8) + z[1] = byte(extensionUseSRTP & 0xff) + + profilesLen := 2 * len(m.srtpProtectionProfiles) + mkiLen := len(m.srtpMasterKeyIdentifier) + l := 2 + profilesLen + 1 + mkiLen + z[2] = byte(l >> 8) + z[3] = byte(l & 0xff) + + z[4] = byte(profilesLen >> 8) + z[5] = byte(profilesLen & 0xff) + z = z[6:] + for _, p := range m.srtpProtectionProfiles { + z[0] = byte(p >> 8) + z[1] = byte(p & 0xff) + z = z[2:] + } + + z[0] = byte(mkiLen) + copy(z[1:], []byte(m.srtpMasterKeyIdentifier)) + z = z[1+mkiLen:] + } + if m.sctListSupported { + z[0] = byte(extensionSignedCertificateTimestamp >> 8) + z[1] = byte(extensionSignedCertificateTimestamp & 0xff) + z = z[4:] + } + if l := len(m.customExtension); l > 0 { + z[0] = byte(extensionCustom >> 8) + z[1] = byte(extensionCustom & 0xff) + z[2] = byte(l >> 8) + z[3] = byte(l & 0xff) + copy(z[4:], []byte(m.customExtension)) + z = z[4+l:] + } + + m.raw = x + + return x +} + +func (m *clientHelloMsg) unmarshal(data []byte) bool { + if len(data) < 42 { + return false + } + m.raw = data + m.vers = wireToVersion(uint16(data[4])<<8|uint16(data[5]), m.isDTLS) + m.random = data[6:38] + sessionIdLen := int(data[38]) + if sessionIdLen > 32 || len(data) < 39+sessionIdLen { + return false + } + m.sessionId = data[39 : 39+sessionIdLen] + data = data[39+sessionIdLen:] + if m.isDTLS { + if len(data) < 1 { + return false + } + cookieLen := int(data[0]) + if cookieLen > 32 || len(data) < 1+cookieLen { + return false + } + m.cookie = data[1 : 1+cookieLen] + data = data[1+cookieLen:] + } + if len(data) < 2 { + return false + } + // cipherSuiteLen is the number of bytes of cipher suite numbers. Since + // they are uint16s, the number must be even. + cipherSuiteLen := int(data[0])<<8 | int(data[1]) + if cipherSuiteLen%2 == 1 || len(data) < 2+cipherSuiteLen { + return false + } + numCipherSuites := cipherSuiteLen / 2 + m.cipherSuites = make([]uint16, numCipherSuites) + for i := 0; i < numCipherSuites; i++ { + m.cipherSuites[i] = uint16(data[2+2*i])<<8 | uint16(data[3+2*i]) + if m.cipherSuites[i] == scsvRenegotiation { + m.secureRenegotiation = []byte{} + } + } + data = data[2+cipherSuiteLen:] + if len(data) < 1 { + return false + } + compressionMethodsLen := int(data[0]) + if len(data) < 1+compressionMethodsLen { + return false + } + m.compressionMethods = data[1 : 1+compressionMethodsLen] + + data = data[1+compressionMethodsLen:] + + m.nextProtoNeg = false + m.serverName = "" + m.ocspStapling = false + m.ticketSupported = false + m.sessionTicket = nil + m.signatureAndHashes = nil + m.alpnProtocols = nil + m.extendedMasterSecret = false + m.customExtension = "" + + if len(data) == 0 { + // ClientHello is optionally followed by extension data + return true + } + if len(data) < 2 { + return false + } + + extensionsLength := int(data[0])<<8 | int(data[1]) + data = data[2:] + if extensionsLength != len(data) { + return false + } + + for len(data) != 0 { + if len(data) < 4 { + return false + } + extension := uint16(data[0])<<8 | uint16(data[1]) + length := int(data[2])<<8 | int(data[3]) + data = data[4:] + if len(data) < length { + return false + } + + switch extension { + case extensionServerName: + if length < 2 { + return false + } + numNames := int(data[0])<<8 | int(data[1]) + d := data[2:] + for i := 0; i < numNames; i++ { + if len(d) < 3 { + return false + } + nameType := d[0] + nameLen := int(d[1])<<8 | int(d[2]) + d = d[3:] + if len(d) < nameLen { + return false + } + if nameType == 0 { + m.serverName = string(d[0:nameLen]) + break + } + d = d[nameLen:] + } + case extensionNextProtoNeg: + if length > 0 { + return false + } + m.nextProtoNeg = true + case extensionStatusRequest: + m.ocspStapling = length > 0 && data[0] == statusTypeOCSP + case extensionSupportedCurves: + // http://tools.ietf.org/html/rfc4492#section-5.5.1 + if length < 2 { + return false + } + l := int(data[0])<<8 | int(data[1]) + if l%2 == 1 || length != l+2 { + return false + } + numCurves := l / 2 + m.supportedCurves = make([]CurveID, numCurves) + d := data[2:] + for i := 0; i < numCurves; i++ { + m.supportedCurves[i] = CurveID(d[0])<<8 | CurveID(d[1]) + d = d[2:] + } + case extensionSupportedPoints: + // http://tools.ietf.org/html/rfc4492#section-5.5.2 + if length < 1 { + return false + } + l := int(data[0]) + if length != l+1 { + return false + } + m.supportedPoints = make([]uint8, l) + copy(m.supportedPoints, data[1:]) + case extensionSessionTicket: + // http://tools.ietf.org/html/rfc5077#section-3.2 + m.ticketSupported = true + m.sessionTicket = data[:length] + case extensionSignatureAlgorithms: + // https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 + if length < 2 || length&1 != 0 { + return false + } + l := int(data[0])<<8 | int(data[1]) + if l != length-2 { + return false + } + n := l / 2 + d := data[2:] + m.signatureAndHashes = make([]signatureAndHash, n) + for i := range m.signatureAndHashes { + m.signatureAndHashes[i].hash = d[0] + m.signatureAndHashes[i].signature = d[1] + d = d[2:] + } + case extensionRenegotiationInfo: + if length < 1 || length != int(data[0])+1 { + return false + } + m.secureRenegotiation = data[1:length] + case extensionALPN: + if length < 2 { + return false + } + l := int(data[0])<<8 | int(data[1]) + if l != length-2 { + return false + } + d := data[2:length] + for len(d) != 0 { + stringLen := int(d[0]) + d = d[1:] + if stringLen == 0 || stringLen > len(d) { + return false + } + m.alpnProtocols = append(m.alpnProtocols, string(d[:stringLen])) + d = d[stringLen:] + } + case extensionChannelID: + if length > 0 { + return false + } + m.channelIDSupported = true + case extensionExtendedMasterSecret: + if length != 0 { + return false + } + m.extendedMasterSecret = true + case extensionUseSRTP: + if length < 2 { + return false + } + l := int(data[0])<<8 | int(data[1]) + if l > length-2 || l%2 != 0 { + return false + } + n := l / 2 + m.srtpProtectionProfiles = make([]uint16, n) + d := data[2:length] + for i := 0; i < n; i++ { + m.srtpProtectionProfiles[i] = uint16(d[0])<<8 | uint16(d[1]) + d = d[2:] + } + if len(d) < 1 || int(d[0]) != len(d)-1 { + return false + } + m.srtpMasterKeyIdentifier = string(d[1:]) + case extensionSignedCertificateTimestamp: + if length != 0 { + return false + } + m.sctListSupported = true + case extensionCustom: + m.customExtension = string(data[:length]) + } + data = data[length:] + } + + return true +} + +type serverHelloMsg struct { + raw []byte + isDTLS bool + vers uint16 + random []byte + sessionId []byte + cipherSuite uint16 + compressionMethod uint8 + nextProtoNeg bool + nextProtos []string + ocspStapling bool + ticketSupported bool + secureRenegotiation []byte + alpnProtocol string + alpnProtocolEmpty bool + duplicateExtension bool + channelIDRequested bool + extendedMasterSecret bool + srtpProtectionProfile uint16 + srtpMasterKeyIdentifier string + sctList []byte + customExtension string + npnLast bool +} + +func (m *serverHelloMsg) marshal() []byte { + if m.raw != nil { + return m.raw + } + + length := 38 + len(m.sessionId) + numExtensions := 0 + extensionsLength := 0 + + nextProtoLen := 0 + if m.nextProtoNeg { + numExtensions++ + for _, v := range m.nextProtos { + nextProtoLen += len(v) + } + nextProtoLen += len(m.nextProtos) + extensionsLength += nextProtoLen + } + if m.ocspStapling { + numExtensions++ + } + if m.ticketSupported { + numExtensions++ + } + if m.secureRenegotiation != nil { + extensionsLength += 1 + len(m.secureRenegotiation) + numExtensions++ + } + if m.duplicateExtension { + numExtensions += 2 + } + if m.channelIDRequested { + numExtensions++ + } + if alpnLen := len(m.alpnProtocol); alpnLen > 0 || m.alpnProtocolEmpty { + if alpnLen >= 256 { + panic("invalid ALPN protocol") + } + extensionsLength += 2 + 1 + alpnLen + numExtensions++ + } + if m.extendedMasterSecret { + numExtensions++ + } + if m.srtpProtectionProfile != 0 { + extensionsLength += 2 + 2 + 1 + len(m.srtpMasterKeyIdentifier) + numExtensions++ + } + if m.sctList != nil { + extensionsLength += len(m.sctList) + numExtensions++ + } + if l := len(m.customExtension); l > 0 { + extensionsLength += l + numExtensions++ + } + + if numExtensions > 0 { + extensionsLength += 4 * numExtensions + length += 2 + extensionsLength + } + + x := make([]byte, 4+length) + x[0] = typeServerHello + x[1] = uint8(length >> 16) + x[2] = uint8(length >> 8) + x[3] = uint8(length) + vers := versionToWire(m.vers, m.isDTLS) + x[4] = uint8(vers >> 8) + x[5] = uint8(vers) + copy(x[6:38], m.random) + x[38] = uint8(len(m.sessionId)) + copy(x[39:39+len(m.sessionId)], m.sessionId) + z := x[39+len(m.sessionId):] + z[0] = uint8(m.cipherSuite >> 8) + z[1] = uint8(m.cipherSuite) + z[2] = uint8(m.compressionMethod) + + z = z[3:] + if numExtensions > 0 { + z[0] = byte(extensionsLength >> 8) + z[1] = byte(extensionsLength) + z = z[2:] + } + if m.duplicateExtension { + // Add a duplicate bogus extension at the beginning and end. + z[0] = 0xff + z[1] = 0xff + z = z[4:] + } + if m.nextProtoNeg && !m.npnLast { + z[0] = byte(extensionNextProtoNeg >> 8) + z[1] = byte(extensionNextProtoNeg & 0xff) + z[2] = byte(nextProtoLen >> 8) + z[3] = byte(nextProtoLen) + z = z[4:] + + for _, v := range m.nextProtos { + l := len(v) + if l > 255 { + l = 255 + } + z[0] = byte(l) + copy(z[1:], []byte(v[0:l])) + z = z[1+l:] + } + } + if m.ocspStapling { + z[0] = byte(extensionStatusRequest >> 8) + z[1] = byte(extensionStatusRequest) + z = z[4:] + } + if m.ticketSupported { + z[0] = byte(extensionSessionTicket >> 8) + z[1] = byte(extensionSessionTicket) + z = z[4:] + } + if m.secureRenegotiation != nil { + z[0] = byte(extensionRenegotiationInfo >> 8) + z[1] = byte(extensionRenegotiationInfo & 0xff) + z[2] = 0 + z[3] = byte(1 + len(m.secureRenegotiation)) + z[4] = byte(len(m.secureRenegotiation)) + z = z[5:] + copy(z, m.secureRenegotiation) + z = z[len(m.secureRenegotiation):] + } + if alpnLen := len(m.alpnProtocol); alpnLen > 0 || m.alpnProtocolEmpty { + z[0] = byte(extensionALPN >> 8) + z[1] = byte(extensionALPN & 0xff) + l := 2 + 1 + alpnLen + z[2] = byte(l >> 8) + z[3] = byte(l) + l -= 2 + z[4] = byte(l >> 8) + z[5] = byte(l) + l -= 1 + z[6] = byte(l) + copy(z[7:], []byte(m.alpnProtocol)) + z = z[7+alpnLen:] + } + if m.channelIDRequested { + z[0] = byte(extensionChannelID >> 8) + z[1] = byte(extensionChannelID & 0xff) + z = z[4:] + } + if m.duplicateExtension { + // Add a duplicate bogus extension at the beginning and end. + z[0] = 0xff + z[1] = 0xff + z = z[4:] + } + if m.extendedMasterSecret { + z[0] = byte(extensionExtendedMasterSecret >> 8) + z[1] = byte(extensionExtendedMasterSecret & 0xff) + z = z[4:] + } + if m.srtpProtectionProfile != 0 { + z[0] = byte(extensionUseSRTP >> 8) + z[1] = byte(extensionUseSRTP & 0xff) + l := 2 + 2 + 1 + len(m.srtpMasterKeyIdentifier) + z[2] = byte(l >> 8) + z[3] = byte(l & 0xff) + z[4] = 0 + z[5] = 2 + z[6] = byte(m.srtpProtectionProfile >> 8) + z[7] = byte(m.srtpProtectionProfile & 0xff) + l = len(m.srtpMasterKeyIdentifier) + z[8] = byte(l) + copy(z[9:], []byte(m.srtpMasterKeyIdentifier)) + z = z[9+l:] + } + if m.sctList != nil { + z[0] = byte(extensionSignedCertificateTimestamp >> 8) + z[1] = byte(extensionSignedCertificateTimestamp & 0xff) + l := len(m.sctList) + z[2] = byte(l >> 8) + z[3] = byte(l & 0xff) + copy(z[4:], m.sctList) + z = z[4+l:] + } + if l := len(m.customExtension); l > 0 { + z[0] = byte(extensionCustom >> 8) + z[1] = byte(extensionCustom & 0xff) + z[2] = byte(l >> 8) + z[3] = byte(l & 0xff) + copy(z[4:], []byte(m.customExtension)) + z = z[4+l:] + } + if m.nextProtoNeg && m.npnLast { + z[0] = byte(extensionNextProtoNeg >> 8) + z[1] = byte(extensionNextProtoNeg & 0xff) + z[2] = byte(nextProtoLen >> 8) + z[3] = byte(nextProtoLen) + z = z[4:] + + for _, v := range m.nextProtos { + l := len(v) + if l > 255 { + l = 255 + } + z[0] = byte(l) + copy(z[1:], []byte(v[0:l])) + z = z[1+l:] + } + } + + m.raw = x + + return x +} + +func (m *serverHelloMsg) unmarshal(data []byte) bool { + if len(data) < 42 { + return false + } + m.raw = data + m.vers = wireToVersion(uint16(data[4])<<8|uint16(data[5]), m.isDTLS) + m.random = data[6:38] + sessionIdLen := int(data[38]) + if sessionIdLen > 32 || len(data) < 39+sessionIdLen { + return false + } + m.sessionId = data[39 : 39+sessionIdLen] + data = data[39+sessionIdLen:] + if len(data) < 3 { + return false + } + m.cipherSuite = uint16(data[0])<<8 | uint16(data[1]) + m.compressionMethod = data[2] + data = data[3:] + + m.nextProtoNeg = false + m.nextProtos = nil + m.ocspStapling = false + m.ticketSupported = false + m.alpnProtocol = "" + m.alpnProtocolEmpty = false + m.extendedMasterSecret = false + m.customExtension = "" + + if len(data) == 0 { + // ServerHello is optionally followed by extension data + return true + } + if len(data) < 2 { + return false + } + + extensionsLength := int(data[0])<<8 | int(data[1]) + data = data[2:] + if len(data) != extensionsLength { + return false + } + + for len(data) != 0 { + if len(data) < 4 { + return false + } + extension := uint16(data[0])<<8 | uint16(data[1]) + length := int(data[2])<<8 | int(data[3]) + data = data[4:] + if len(data) < length { + return false + } + + switch extension { + case extensionNextProtoNeg: + m.nextProtoNeg = true + d := data[:length] + for len(d) > 0 { + l := int(d[0]) + d = d[1:] + if l == 0 || l > len(d) { + return false + } + m.nextProtos = append(m.nextProtos, string(d[:l])) + d = d[l:] + } + case extensionStatusRequest: + if length > 0 { + return false + } + m.ocspStapling = true + case extensionSessionTicket: + if length > 0 { + return false + } + m.ticketSupported = true + case extensionRenegotiationInfo: + if length < 1 || length != int(data[0])+1 { + return false + } + m.secureRenegotiation = data[1:length] + case extensionALPN: + d := data[:length] + if len(d) < 3 { + return false + } + l := int(d[0])<<8 | int(d[1]) + if l != len(d)-2 { + return false + } + d = d[2:] + l = int(d[0]) + if l != len(d)-1 { + return false + } + d = d[1:] + m.alpnProtocol = string(d) + m.alpnProtocolEmpty = len(d) == 0 + case extensionChannelID: + if length > 0 { + return false + } + m.channelIDRequested = true + case extensionExtendedMasterSecret: + if length != 0 { + return false + } + m.extendedMasterSecret = true + case extensionUseSRTP: + if length < 2+2+1 { + return false + } + if data[0] != 0 || data[1] != 2 { + return false + } + m.srtpProtectionProfile = uint16(data[2])<<8 | uint16(data[3]) + d := data[4:length] + l := int(d[0]) + if l != len(d)-1 { + return false + } + m.srtpMasterKeyIdentifier = string(d[1:]) + case extensionSignedCertificateTimestamp: + m.sctList = data[:length] + case extensionCustom: + m.customExtension = string(data[:length]) + } + data = data[length:] + } + + return true +} + +type certificateMsg struct { + raw []byte + certificates [][]byte +} + +func (m *certificateMsg) marshal() (x []byte) { + if m.raw != nil { + return m.raw + } + + var i int + for _, slice := range m.certificates { + i += len(slice) + } + + length := 3 + 3*len(m.certificates) + i + x = make([]byte, 4+length) + x[0] = typeCertificate + x[1] = uint8(length >> 16) + x[2] = uint8(length >> 8) + x[3] = uint8(length) + + certificateOctets := length - 3 + x[4] = uint8(certificateOctets >> 16) + x[5] = uint8(certificateOctets >> 8) + x[6] = uint8(certificateOctets) + + y := x[7:] + for _, slice := range m.certificates { + y[0] = uint8(len(slice) >> 16) + y[1] = uint8(len(slice) >> 8) + y[2] = uint8(len(slice)) + copy(y[3:], slice) + y = y[3+len(slice):] + } + + m.raw = x + return +} + +func (m *certificateMsg) unmarshal(data []byte) bool { + if len(data) < 7 { + return false + } + + m.raw = data + certsLen := uint32(data[4])<<16 | uint32(data[5])<<8 | uint32(data[6]) + if uint32(len(data)) != certsLen+7 { + return false + } + + numCerts := 0 + d := data[7:] + for certsLen > 0 { + if len(d) < 4 { + return false + } + certLen := uint32(d[0])<<16 | uint32(d[1])<<8 | uint32(d[2]) + if uint32(len(d)) < 3+certLen { + return false + } + d = d[3+certLen:] + certsLen -= 3 + certLen + numCerts++ + } + + m.certificates = make([][]byte, numCerts) + d = data[7:] + for i := 0; i < numCerts; i++ { + certLen := uint32(d[0])<<16 | uint32(d[1])<<8 | uint32(d[2]) + m.certificates[i] = d[3 : 3+certLen] + d = d[3+certLen:] + } + + return true +} + +type serverKeyExchangeMsg struct { + raw []byte + key []byte +} + +func (m *serverKeyExchangeMsg) marshal() []byte { + if m.raw != nil { + return m.raw + } + length := len(m.key) + x := make([]byte, length+4) + x[0] = typeServerKeyExchange + x[1] = uint8(length >> 16) + x[2] = uint8(length >> 8) + x[3] = uint8(length) + copy(x[4:], m.key) + + m.raw = x + return x +} + +func (m *serverKeyExchangeMsg) unmarshal(data []byte) bool { + m.raw = data + if len(data) < 4 { + return false + } + m.key = data[4:] + return true +} + +type certificateStatusMsg struct { + raw []byte + statusType uint8 + response []byte +} + +func (m *certificateStatusMsg) marshal() []byte { + if m.raw != nil { + return m.raw + } + + var x []byte + if m.statusType == statusTypeOCSP { + x = make([]byte, 4+4+len(m.response)) + x[0] = typeCertificateStatus + l := len(m.response) + 4 + x[1] = byte(l >> 16) + x[2] = byte(l >> 8) + x[3] = byte(l) + x[4] = statusTypeOCSP + + l -= 4 + x[5] = byte(l >> 16) + x[6] = byte(l >> 8) + x[7] = byte(l) + copy(x[8:], m.response) + } else { + x = []byte{typeCertificateStatus, 0, 0, 1, m.statusType} + } + + m.raw = x + return x +} + +func (m *certificateStatusMsg) unmarshal(data []byte) bool { + m.raw = data + if len(data) < 5 { + return false + } + m.statusType = data[4] + + m.response = nil + if m.statusType == statusTypeOCSP { + if len(data) < 8 { + return false + } + respLen := uint32(data[5])<<16 | uint32(data[6])<<8 | uint32(data[7]) + if uint32(len(data)) != 4+4+respLen { + return false + } + m.response = data[8:] + } + return true +} + +type serverHelloDoneMsg struct{} + +func (m *serverHelloDoneMsg) marshal() []byte { + x := make([]byte, 4) + x[0] = typeServerHelloDone + return x +} + +func (m *serverHelloDoneMsg) unmarshal(data []byte) bool { + return len(data) == 4 +} + +type clientKeyExchangeMsg struct { + raw []byte + ciphertext []byte +} + +func (m *clientKeyExchangeMsg) marshal() []byte { + if m.raw != nil { + return m.raw + } + length := len(m.ciphertext) + x := make([]byte, length+4) + x[0] = typeClientKeyExchange + x[1] = uint8(length >> 16) + x[2] = uint8(length >> 8) + x[3] = uint8(length) + copy(x[4:], m.ciphertext) + + m.raw = x + return x +} + +func (m *clientKeyExchangeMsg) unmarshal(data []byte) bool { + m.raw = data + if len(data) < 4 { + return false + } + l := int(data[1])<<16 | int(data[2])<<8 | int(data[3]) + if l != len(data)-4 { + return false + } + m.ciphertext = data[4:] + return true +} + +type finishedMsg struct { + raw []byte + verifyData []byte +} + +func (m *finishedMsg) marshal() (x []byte) { + if m.raw != nil { + return m.raw + } + + x = make([]byte, 4+len(m.verifyData)) + x[0] = typeFinished + x[3] = byte(len(m.verifyData)) + copy(x[4:], m.verifyData) + m.raw = x + return +} + +func (m *finishedMsg) unmarshal(data []byte) bool { + m.raw = data + if len(data) < 4 { + return false + } + m.verifyData = data[4:] + return true +} + +type nextProtoMsg struct { + raw []byte + proto string +} + +func (m *nextProtoMsg) marshal() []byte { + if m.raw != nil { + return m.raw + } + l := len(m.proto) + if l > 255 { + l = 255 + } + + padding := 32 - (l+2)%32 + length := l + padding + 2 + x := make([]byte, length+4) + x[0] = typeNextProtocol + x[1] = uint8(length >> 16) + x[2] = uint8(length >> 8) + x[3] = uint8(length) + + y := x[4:] + y[0] = byte(l) + copy(y[1:], []byte(m.proto[0:l])) + y = y[1+l:] + y[0] = byte(padding) + + m.raw = x + + return x +} + +func (m *nextProtoMsg) unmarshal(data []byte) bool { + m.raw = data + + if len(data) < 5 { + return false + } + data = data[4:] + protoLen := int(data[0]) + data = data[1:] + if len(data) < protoLen { + return false + } + m.proto = string(data[0:protoLen]) + data = data[protoLen:] + + if len(data) < 1 { + return false + } + paddingLen := int(data[0]) + data = data[1:] + if len(data) != paddingLen { + return false + } + + return true +} + +type certificateRequestMsg struct { + raw []byte + // hasSignatureAndHash indicates whether this message includes a list + // of signature and hash functions. This change was introduced with TLS + // 1.2. + hasSignatureAndHash bool + + certificateTypes []byte + signatureAndHashes []signatureAndHash + certificateAuthorities [][]byte +} + +func (m *certificateRequestMsg) marshal() (x []byte) { + if m.raw != nil { + return m.raw + } + + // See http://tools.ietf.org/html/rfc4346#section-7.4.4 + length := 1 + len(m.certificateTypes) + 2 + casLength := 0 + for _, ca := range m.certificateAuthorities { + casLength += 2 + len(ca) + } + length += casLength + + if m.hasSignatureAndHash { + length += 2 + 2*len(m.signatureAndHashes) + } + + x = make([]byte, 4+length) + x[0] = typeCertificateRequest + x[1] = uint8(length >> 16) + x[2] = uint8(length >> 8) + x[3] = uint8(length) + + x[4] = uint8(len(m.certificateTypes)) + + copy(x[5:], m.certificateTypes) + y := x[5+len(m.certificateTypes):] + + if m.hasSignatureAndHash { + n := len(m.signatureAndHashes) * 2 + y[0] = uint8(n >> 8) + y[1] = uint8(n) + y = y[2:] + for _, sigAndHash := range m.signatureAndHashes { + y[0] = sigAndHash.hash + y[1] = sigAndHash.signature + y = y[2:] + } + } + + y[0] = uint8(casLength >> 8) + y[1] = uint8(casLength) + y = y[2:] + for _, ca := range m.certificateAuthorities { + y[0] = uint8(len(ca) >> 8) + y[1] = uint8(len(ca)) + y = y[2:] + copy(y, ca) + y = y[len(ca):] + } + + m.raw = x + return +} + +func (m *certificateRequestMsg) unmarshal(data []byte) bool { + m.raw = data + + if len(data) < 5 { + return false + } + + length := uint32(data[1])<<16 | uint32(data[2])<<8 | uint32(data[3]) + if uint32(len(data))-4 != length { + return false + } + + numCertTypes := int(data[4]) + data = data[5:] + if numCertTypes == 0 || len(data) <= numCertTypes { + return false + } + + m.certificateTypes = make([]byte, numCertTypes) + if copy(m.certificateTypes, data) != numCertTypes { + return false + } + + data = data[numCertTypes:] + + if m.hasSignatureAndHash { + if len(data) < 2 { + return false + } + sigAndHashLen := uint16(data[0])<<8 | uint16(data[1]) + data = data[2:] + if sigAndHashLen&1 != 0 { + return false + } + if len(data) < int(sigAndHashLen) { + return false + } + numSigAndHash := sigAndHashLen / 2 + m.signatureAndHashes = make([]signatureAndHash, numSigAndHash) + for i := range m.signatureAndHashes { + m.signatureAndHashes[i].hash = data[0] + m.signatureAndHashes[i].signature = data[1] + data = data[2:] + } + } + + if len(data) < 2 { + return false + } + casLength := uint16(data[0])<<8 | uint16(data[1]) + data = data[2:] + if len(data) < int(casLength) { + return false + } + cas := make([]byte, casLength) + copy(cas, data) + data = data[casLength:] + + m.certificateAuthorities = nil + for len(cas) > 0 { + if len(cas) < 2 { + return false + } + caLen := uint16(cas[0])<<8 | uint16(cas[1]) + cas = cas[2:] + + if len(cas) < int(caLen) { + return false + } + + m.certificateAuthorities = append(m.certificateAuthorities, cas[:caLen]) + cas = cas[caLen:] + } + if len(data) > 0 { + return false + } + + return true +} + +type certificateVerifyMsg struct { + raw []byte + hasSignatureAndHash bool + signatureAndHash signatureAndHash + signature []byte +} + +func (m *certificateVerifyMsg) marshal() (x []byte) { + if m.raw != nil { + return m.raw + } + + // See http://tools.ietf.org/html/rfc4346#section-7.4.8 + siglength := len(m.signature) + length := 2 + siglength + if m.hasSignatureAndHash { + length += 2 + } + x = make([]byte, 4+length) + x[0] = typeCertificateVerify + x[1] = uint8(length >> 16) + x[2] = uint8(length >> 8) + x[3] = uint8(length) + y := x[4:] + if m.hasSignatureAndHash { + y[0] = m.signatureAndHash.hash + y[1] = m.signatureAndHash.signature + y = y[2:] + } + y[0] = uint8(siglength >> 8) + y[1] = uint8(siglength) + copy(y[2:], m.signature) + + m.raw = x + + return +} + +func (m *certificateVerifyMsg) unmarshal(data []byte) bool { + m.raw = data + + if len(data) < 6 { + return false + } + + length := uint32(data[1])<<16 | uint32(data[2])<<8 | uint32(data[3]) + if uint32(len(data))-4 != length { + return false + } + + data = data[4:] + if m.hasSignatureAndHash { + m.signatureAndHash.hash = data[0] + m.signatureAndHash.signature = data[1] + data = data[2:] + } + + if len(data) < 2 { + return false + } + siglength := int(data[0])<<8 + int(data[1]) + data = data[2:] + if len(data) != siglength { + return false + } + + m.signature = data + + return true +} + +type newSessionTicketMsg struct { + raw []byte + ticket []byte +} + +func (m *newSessionTicketMsg) marshal() (x []byte) { + if m.raw != nil { + return m.raw + } + + // See http://tools.ietf.org/html/rfc5077#section-3.3 + ticketLen := len(m.ticket) + length := 2 + 4 + ticketLen + x = make([]byte, 4+length) + x[0] = typeNewSessionTicket + x[1] = uint8(length >> 16) + x[2] = uint8(length >> 8) + x[3] = uint8(length) + x[8] = uint8(ticketLen >> 8) + x[9] = uint8(ticketLen) + copy(x[10:], m.ticket) + + m.raw = x + + return +} + +func (m *newSessionTicketMsg) unmarshal(data []byte) bool { + m.raw = data + + if len(data) < 10 { + return false + } + + length := uint32(data[1])<<16 | uint32(data[2])<<8 | uint32(data[3]) + if uint32(len(data))-4 != length { + return false + } + + ticketLen := int(data[8])<<8 + int(data[9]) + if len(data)-10 != ticketLen { + return false + } + + m.ticket = data[10:] + + return true +} + +type v2ClientHelloMsg struct { + raw []byte + vers uint16 + cipherSuites []uint16 + sessionId []byte + challenge []byte +} + +func (m *v2ClientHelloMsg) marshal() []byte { + if m.raw != nil { + return m.raw + } + + length := 1 + 2 + 2 + 2 + 2 + len(m.cipherSuites)*3 + len(m.sessionId) + len(m.challenge) + + x := make([]byte, length) + x[0] = 1 + x[1] = uint8(m.vers >> 8) + x[2] = uint8(m.vers) + x[3] = uint8((len(m.cipherSuites) * 3) >> 8) + x[4] = uint8(len(m.cipherSuites) * 3) + x[5] = uint8(len(m.sessionId) >> 8) + x[6] = uint8(len(m.sessionId)) + x[7] = uint8(len(m.challenge) >> 8) + x[8] = uint8(len(m.challenge)) + y := x[9:] + for i, spec := range m.cipherSuites { + y[i*3] = 0 + y[i*3+1] = uint8(spec >> 8) + y[i*3+2] = uint8(spec) + } + y = y[len(m.cipherSuites)*3:] + copy(y, m.sessionId) + y = y[len(m.sessionId):] + copy(y, m.challenge) + + m.raw = x + + return x +} + +type helloVerifyRequestMsg struct { + raw []byte + vers uint16 + cookie []byte +} + +func (m *helloVerifyRequestMsg) marshal() []byte { + if m.raw != nil { + return m.raw + } + + length := 2 + 1 + len(m.cookie) + + x := make([]byte, 4+length) + x[0] = typeHelloVerifyRequest + x[1] = uint8(length >> 16) + x[2] = uint8(length >> 8) + x[3] = uint8(length) + vers := versionToWire(m.vers, true) + x[4] = uint8(vers >> 8) + x[5] = uint8(vers) + x[6] = uint8(len(m.cookie)) + copy(x[7:7+len(m.cookie)], m.cookie) + + return x +} + +func (m *helloVerifyRequestMsg) unmarshal(data []byte) bool { + if len(data) < 4+2+1 { + return false + } + m.raw = data + m.vers = wireToVersion(uint16(data[4])<<8|uint16(data[5]), true) + cookieLen := int(data[6]) + if cookieLen > 32 || len(data) != 7+cookieLen { + return false + } + m.cookie = data[7 : 7+cookieLen] + + return true +} + +type encryptedExtensionsMsg struct { + raw []byte + channelID []byte +} + +func (m *encryptedExtensionsMsg) marshal() []byte { + if m.raw != nil { + return m.raw + } + + length := 2 + 2 + len(m.channelID) + + x := make([]byte, 4+length) + x[0] = typeEncryptedExtensions + x[1] = uint8(length >> 16) + x[2] = uint8(length >> 8) + x[3] = uint8(length) + x[4] = uint8(extensionChannelID >> 8) + x[5] = uint8(extensionChannelID & 0xff) + x[6] = uint8(len(m.channelID) >> 8) + x[7] = uint8(len(m.channelID) & 0xff) + copy(x[8:], m.channelID) + + return x +} + +func (m *encryptedExtensionsMsg) unmarshal(data []byte) bool { + if len(data) != 4+2+2+128 { + return false + } + m.raw = data + if (uint16(data[4])<<8)|uint16(data[5]) != extensionChannelID { + return false + } + if int(data[6])<<8|int(data[7]) != 128 { + return false + } + m.channelID = data[4+2+2:] + + return true +} + +type helloRequestMsg struct { +} + +func (*helloRequestMsg) marshal() []byte { + return []byte{typeHelloRequest, 0, 0, 0} +} + +func (*helloRequestMsg) unmarshal(data []byte) bool { + return len(data) == 4 +} + +func eqUint16s(x, y []uint16) bool { + if len(x) != len(y) { + return false + } + for i, v := range x { + if y[i] != v { + return false + } + } + return true +} + +func eqCurveIDs(x, y []CurveID) bool { + if len(x) != len(y) { + return false + } + for i, v := range x { + if y[i] != v { + return false + } + } + return true +} + +func eqStrings(x, y []string) bool { + if len(x) != len(y) { + return false + } + for i, v := range x { + if y[i] != v { + return false + } + } + return true +} + +func eqByteSlices(x, y [][]byte) bool { + if len(x) != len(y) { + return false + } + for i, v := range x { + if !bytes.Equal(v, y[i]) { + return false + } + } + return true +} + +func eqSignatureAndHashes(x, y []signatureAndHash) bool { + if len(x) != len(y) { + return false + } + for i, v := range x { + v2 := y[i] + if v.hash != v2.hash || v.signature != v2.signature { + return false + } + } + return true +} diff --git a/external/boringssl/ssl/test/runner/handshake_server.go b/external/boringssl/ssl/test/runner/handshake_server.go new file mode 100644 index 0000000000..72d1eb9904 --- /dev/null +++ b/external/boringssl/ssl/test/runner/handshake_server.go @@ -0,0 +1,1094 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package runner + +import ( + "bytes" + "crypto" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rsa" + "crypto/subtle" + "crypto/x509" + "encoding/asn1" + "errors" + "fmt" + "io" + "math/big" +) + +// serverHandshakeState contains details of a server handshake in progress. +// It's discarded once the handshake has completed. +type serverHandshakeState struct { + c *Conn + clientHello *clientHelloMsg + hello *serverHelloMsg + suite *cipherSuite + ellipticOk bool + ecdsaOk bool + sessionState *sessionState + finishedHash finishedHash + masterSecret []byte + certsFromClient [][]byte + cert *Certificate + finishedBytes []byte +} + +// serverHandshake performs a TLS handshake as a server. +func (c *Conn) serverHandshake() error { + config := c.config + + // If this is the first server handshake, we generate a random key to + // encrypt the tickets with. + config.serverInitOnce.Do(config.serverInit) + + c.sendHandshakeSeq = 0 + c.recvHandshakeSeq = 0 + + hs := serverHandshakeState{ + c: c, + } + isResume, err := hs.readClientHello() + if err != nil { + return err + } + + // For an overview of TLS handshaking, see https://tools.ietf.org/html/rfc5246#section-7.3 + if isResume { + // The client has included a session ticket and so we do an abbreviated handshake. + if err := hs.doResumeHandshake(); err != nil { + return err + } + if err := hs.establishKeys(); err != nil { + return err + } + if c.config.Bugs.RenewTicketOnResume { + if err := hs.sendSessionTicket(); err != nil { + return err + } + } + if err := hs.sendFinished(c.firstFinished[:]); err != nil { + return err + } + // Most retransmits are triggered by a timeout, but the final + // leg of the handshake is retransmited upon re-receiving a + // Finished. + if err := c.simulatePacketLoss(func() { + c.writeRecord(recordTypeHandshake, hs.finishedBytes) + c.dtlsFlushHandshake() + }); err != nil { + return err + } + if err := hs.readFinished(nil, isResume); err != nil { + return err + } + c.didResume = true + } else { + // The client didn't include a session ticket, or it wasn't + // valid so we do a full handshake. + if err := hs.doFullHandshake(); err != nil { + return err + } + if err := hs.establishKeys(); err != nil { + return err + } + if err := hs.readFinished(c.firstFinished[:], isResume); err != nil { + return err + } + if c.config.Bugs.AlertBeforeFalseStartTest != 0 { + c.sendAlert(c.config.Bugs.AlertBeforeFalseStartTest) + } + if c.config.Bugs.ExpectFalseStart { + if err := c.readRecord(recordTypeApplicationData); err != nil { + return fmt.Errorf("tls: peer did not false start: %s", err) + } + } + if err := hs.sendSessionTicket(); err != nil { + return err + } + if err := hs.sendFinished(nil); err != nil { + return err + } + } + c.handshakeComplete = true + copy(c.clientRandom[:], hs.clientHello.random) + copy(c.serverRandom[:], hs.hello.random) + copy(c.masterSecret[:], hs.masterSecret) + + return nil +} + +// readClientHello reads a ClientHello message from the client and decides +// whether we will perform session resumption. +func (hs *serverHandshakeState) readClientHello() (isResume bool, err error) { + config := hs.c.config + c := hs.c + + if err := c.simulatePacketLoss(nil); err != nil { + return false, err + } + msg, err := c.readHandshake() + if err != nil { + return false, err + } + var ok bool + hs.clientHello, ok = msg.(*clientHelloMsg) + if !ok { + c.sendAlert(alertUnexpectedMessage) + return false, unexpectedMessageError(hs.clientHello, msg) + } + if size := config.Bugs.RequireClientHelloSize; size != 0 && len(hs.clientHello.raw) != size { + return false, fmt.Errorf("tls: ClientHello record size is %d, but expected %d", len(hs.clientHello.raw), size) + } + + if c.isDTLS && !config.Bugs.SkipHelloVerifyRequest { + // Per RFC 6347, the version field in HelloVerifyRequest SHOULD + // be always DTLS 1.0 + helloVerifyRequest := &helloVerifyRequestMsg{ + vers: VersionTLS10, + cookie: make([]byte, 32), + } + if _, err := io.ReadFull(c.config.rand(), helloVerifyRequest.cookie); err != nil { + c.sendAlert(alertInternalError) + return false, errors.New("dtls: short read from Rand: " + err.Error()) + } + c.writeRecord(recordTypeHandshake, helloVerifyRequest.marshal()) + c.dtlsFlushHandshake() + + if err := c.simulatePacketLoss(nil); err != nil { + return false, err + } + msg, err := c.readHandshake() + if err != nil { + return false, err + } + newClientHello, ok := msg.(*clientHelloMsg) + if !ok { + c.sendAlert(alertUnexpectedMessage) + return false, unexpectedMessageError(hs.clientHello, msg) + } + if !bytes.Equal(newClientHello.cookie, helloVerifyRequest.cookie) { + return false, errors.New("dtls: invalid cookie") + } + + // Apart from the cookie, the two ClientHellos must + // match. Note that clientHello.equal compares the + // serialization, so we make a copy. + oldClientHelloCopy := *hs.clientHello + oldClientHelloCopy.raw = nil + oldClientHelloCopy.cookie = nil + newClientHelloCopy := *newClientHello + newClientHelloCopy.raw = nil + newClientHelloCopy.cookie = nil + if !oldClientHelloCopy.equal(&newClientHelloCopy) { + return false, errors.New("dtls: retransmitted ClientHello does not match") + } + hs.clientHello = newClientHello + } + + if config.Bugs.RequireSameRenegoClientVersion && c.clientVersion != 0 { + if c.clientVersion != hs.clientHello.vers { + return false, fmt.Errorf("tls: client offered different version on renego") + } + } + c.clientVersion = hs.clientHello.vers + + // Reject < 1.2 ClientHellos with signature_algorithms. + if c.clientVersion < VersionTLS12 && len(hs.clientHello.signatureAndHashes) > 0 { + return false, fmt.Errorf("tls: client included signature_algorithms before TLS 1.2") + } + if config.Bugs.IgnorePeerSignatureAlgorithmPreferences { + hs.clientHello.signatureAndHashes = config.signatureAndHashesForServer() + } + + // Check the client cipher list is consistent with the version. + if hs.clientHello.vers < VersionTLS12 { + for _, id := range hs.clientHello.cipherSuites { + if isTLS12Cipher(id) { + return false, fmt.Errorf("tls: client offered TLS 1.2 cipher before TLS 1.2") + } + } + } + + c.vers, ok = config.mutualVersion(hs.clientHello.vers) + if !ok { + c.sendAlert(alertProtocolVersion) + return false, fmt.Errorf("tls: client offered an unsupported, maximum protocol version of %x", hs.clientHello.vers) + } + c.haveVers = true + + hs.hello = &serverHelloMsg{ + isDTLS: c.isDTLS, + customExtension: config.Bugs.CustomExtension, + npnLast: config.Bugs.SwapNPNAndALPN, + } + + supportedCurve := false + preferredCurves := config.curvePreferences() + if config.Bugs.IgnorePeerCurvePreferences { + hs.clientHello.supportedCurves = preferredCurves + } +Curves: + for _, curve := range hs.clientHello.supportedCurves { + for _, supported := range preferredCurves { + if supported == curve { + supportedCurve = true + break Curves + } + } + } + + supportedPointFormat := false + for _, pointFormat := range hs.clientHello.supportedPoints { + if pointFormat == pointFormatUncompressed { + supportedPointFormat = true + break + } + } + hs.ellipticOk = supportedCurve && supportedPointFormat + + foundCompression := false + // We only support null compression, so check that the client offered it. + for _, compression := range hs.clientHello.compressionMethods { + if compression == compressionNone { + foundCompression = true + break + } + } + + if !foundCompression { + c.sendAlert(alertHandshakeFailure) + return false, errors.New("tls: client does not support uncompressed connections") + } + + hs.hello.vers = c.vers + hs.hello.random = make([]byte, 32) + _, err = io.ReadFull(config.rand(), hs.hello.random) + if err != nil { + c.sendAlert(alertInternalError) + return false, err + } + + if !bytes.Equal(c.clientVerify, hs.clientHello.secureRenegotiation) { + c.sendAlert(alertHandshakeFailure) + return false, errors.New("tls: renegotiation mismatch") + } + + if len(c.clientVerify) > 0 && !c.config.Bugs.EmptyRenegotiationInfo { + hs.hello.secureRenegotiation = append(hs.hello.secureRenegotiation, c.clientVerify...) + hs.hello.secureRenegotiation = append(hs.hello.secureRenegotiation, c.serverVerify...) + if c.config.Bugs.BadRenegotiationInfo { + hs.hello.secureRenegotiation[0] ^= 0x80 + } + } else { + hs.hello.secureRenegotiation = hs.clientHello.secureRenegotiation + } + + if c.noRenegotiationInfo() { + hs.hello.secureRenegotiation = nil + } + + hs.hello.compressionMethod = compressionNone + hs.hello.duplicateExtension = c.config.Bugs.DuplicateExtension + if len(hs.clientHello.serverName) > 0 { + c.serverName = hs.clientHello.serverName + } + + if len(hs.clientHello.alpnProtocols) > 0 { + if proto := c.config.Bugs.ALPNProtocol; proto != nil { + hs.hello.alpnProtocol = *proto + hs.hello.alpnProtocolEmpty = len(*proto) == 0 + c.clientProtocol = *proto + c.usedALPN = true + } else if selectedProto, fallback := mutualProtocol(hs.clientHello.alpnProtocols, c.config.NextProtos); !fallback { + hs.hello.alpnProtocol = selectedProto + c.clientProtocol = selectedProto + c.usedALPN = true + } + } + if len(hs.clientHello.alpnProtocols) == 0 || c.config.Bugs.NegotiateALPNAndNPN { + // Although sending an empty NPN extension is reasonable, Firefox has + // had a bug around this. Best to send nothing at all if + // config.NextProtos is empty. See + // https://code.google.com/p/go/issues/detail?id=5445. + if hs.clientHello.nextProtoNeg && len(config.NextProtos) > 0 { + hs.hello.nextProtoNeg = true + hs.hello.nextProtos = config.NextProtos + } + } + hs.hello.extendedMasterSecret = c.vers >= VersionTLS10 && hs.clientHello.extendedMasterSecret && !c.config.Bugs.NoExtendedMasterSecret + + if len(config.Certificates) == 0 { + c.sendAlert(alertInternalError) + return false, errors.New("tls: no certificates configured") + } + hs.cert = &config.Certificates[0] + if len(hs.clientHello.serverName) > 0 { + hs.cert = config.getCertificateForName(hs.clientHello.serverName) + } + if expected := c.config.Bugs.ExpectServerName; expected != "" && expected != hs.clientHello.serverName { + return false, errors.New("tls: unexpected server name") + } + + if hs.clientHello.channelIDSupported && config.RequestChannelID { + hs.hello.channelIDRequested = true + } + + if hs.clientHello.srtpProtectionProfiles != nil { + SRTPLoop: + for _, p1 := range c.config.SRTPProtectionProfiles { + for _, p2 := range hs.clientHello.srtpProtectionProfiles { + if p1 == p2 { + hs.hello.srtpProtectionProfile = p1 + c.srtpProtectionProfile = p1 + break SRTPLoop + } + } + } + } + + if c.config.Bugs.SendSRTPProtectionProfile != 0 { + hs.hello.srtpProtectionProfile = c.config.Bugs.SendSRTPProtectionProfile + } + + if expected := c.config.Bugs.ExpectedCustomExtension; expected != nil { + if hs.clientHello.customExtension != *expected { + return false, fmt.Errorf("tls: bad custom extension contents %q", hs.clientHello.customExtension) + } + } + + _, hs.ecdsaOk = hs.cert.PrivateKey.(*ecdsa.PrivateKey) + + // For test purposes, check that the peer never offers a session when + // renegotiating. + if c.cipherSuite != nil && len(hs.clientHello.sessionId) > 0 && c.config.Bugs.FailIfResumeOnRenego { + return false, errors.New("tls: offered resumption on renegotiation") + } + + if c.config.Bugs.FailIfSessionOffered && (len(hs.clientHello.sessionTicket) > 0 || len(hs.clientHello.sessionId) > 0) { + return false, errors.New("tls: client offered a session ticket or ID") + } + + if hs.checkForResumption() { + return true, nil + } + + var scsvFound bool + + for _, cipherSuite := range hs.clientHello.cipherSuites { + if cipherSuite == fallbackSCSV { + scsvFound = true + break + } + } + + if !scsvFound && config.Bugs.FailIfNotFallbackSCSV { + return false, errors.New("tls: no fallback SCSV found when expected") + } else if scsvFound && !config.Bugs.FailIfNotFallbackSCSV { + return false, errors.New("tls: fallback SCSV found when not expected") + } + + if config.Bugs.IgnorePeerCipherPreferences { + hs.clientHello.cipherSuites = c.config.cipherSuites() + } + var preferenceList, supportedList []uint16 + if c.config.PreferServerCipherSuites { + preferenceList = c.config.cipherSuites() + supportedList = hs.clientHello.cipherSuites + } else { + preferenceList = hs.clientHello.cipherSuites + supportedList = c.config.cipherSuites() + } + + for _, id := range preferenceList { + if hs.suite = c.tryCipherSuite(id, supportedList, c.vers, hs.ellipticOk, hs.ecdsaOk); hs.suite != nil { + break + } + } + + if hs.suite == nil { + c.sendAlert(alertHandshakeFailure) + return false, errors.New("tls: no cipher suite supported by both client and server") + } + + return false, nil +} + +// checkForResumption returns true if we should perform resumption on this connection. +func (hs *serverHandshakeState) checkForResumption() bool { + c := hs.c + + if len(hs.clientHello.sessionTicket) > 0 { + if c.config.SessionTicketsDisabled { + return false + } + + var ok bool + if hs.sessionState, ok = c.decryptTicket(hs.clientHello.sessionTicket); !ok { + return false + } + } else { + if c.config.ServerSessionCache == nil { + return false + } + + var ok bool + sessionId := string(hs.clientHello.sessionId) + if hs.sessionState, ok = c.config.ServerSessionCache.Get(sessionId); !ok { + return false + } + } + + // Never resume a session for a different SSL version. + if !c.config.Bugs.AllowSessionVersionMismatch && c.vers != hs.sessionState.vers { + return false + } + + cipherSuiteOk := false + // Check that the client is still offering the ciphersuite in the session. + for _, id := range hs.clientHello.cipherSuites { + if id == hs.sessionState.cipherSuite { + cipherSuiteOk = true + break + } + } + if !cipherSuiteOk { + return false + } + + // Check that we also support the ciphersuite from the session. + hs.suite = c.tryCipherSuite(hs.sessionState.cipherSuite, c.config.cipherSuites(), hs.sessionState.vers, hs.ellipticOk, hs.ecdsaOk) + if hs.suite == nil { + return false + } + + sessionHasClientCerts := len(hs.sessionState.certificates) != 0 + needClientCerts := c.config.ClientAuth == RequireAnyClientCert || c.config.ClientAuth == RequireAndVerifyClientCert + if needClientCerts && !sessionHasClientCerts { + return false + } + if sessionHasClientCerts && c.config.ClientAuth == NoClientCert { + return false + } + + return true +} + +func (hs *serverHandshakeState) doResumeHandshake() error { + c := hs.c + + hs.hello.cipherSuite = hs.suite.id + if c.config.Bugs.SendCipherSuite != 0 { + hs.hello.cipherSuite = c.config.Bugs.SendCipherSuite + } + // We echo the client's session ID in the ServerHello to let it know + // that we're doing a resumption. + hs.hello.sessionId = hs.clientHello.sessionId + hs.hello.ticketSupported = c.config.Bugs.RenewTicketOnResume + + if c.config.Bugs.SendSCTListOnResume != nil { + hs.hello.sctList = c.config.Bugs.SendSCTListOnResume + } + + hs.finishedHash = newFinishedHash(c.vers, hs.suite) + hs.finishedHash.discardHandshakeBuffer() + hs.writeClientHash(hs.clientHello.marshal()) + hs.writeServerHash(hs.hello.marshal()) + + c.writeRecord(recordTypeHandshake, hs.hello.marshal()) + + if len(hs.sessionState.certificates) > 0 { + if _, err := hs.processCertsFromClient(hs.sessionState.certificates); err != nil { + return err + } + } + + hs.masterSecret = hs.sessionState.masterSecret + c.extendedMasterSecret = hs.sessionState.extendedMasterSecret + + return nil +} + +func (hs *serverHandshakeState) doFullHandshake() error { + config := hs.c.config + c := hs.c + + isPSK := hs.suite.flags&suitePSK != 0 + if !isPSK && hs.clientHello.ocspStapling && len(hs.cert.OCSPStaple) > 0 { + hs.hello.ocspStapling = true + } + + if hs.clientHello.sctListSupported && len(hs.cert.SignedCertificateTimestampList) > 0 { + hs.hello.sctList = hs.cert.SignedCertificateTimestampList + } + + hs.hello.ticketSupported = hs.clientHello.ticketSupported && !config.SessionTicketsDisabled && c.vers > VersionSSL30 + hs.hello.cipherSuite = hs.suite.id + if config.Bugs.SendCipherSuite != 0 { + hs.hello.cipherSuite = config.Bugs.SendCipherSuite + } + c.extendedMasterSecret = hs.hello.extendedMasterSecret + + // Generate a session ID if we're to save the session. + if !hs.hello.ticketSupported && config.ServerSessionCache != nil { + hs.hello.sessionId = make([]byte, 32) + if _, err := io.ReadFull(config.rand(), hs.hello.sessionId); err != nil { + c.sendAlert(alertInternalError) + return errors.New("tls: short read from Rand: " + err.Error()) + } + } + + hs.finishedHash = newFinishedHash(c.vers, hs.suite) + hs.writeClientHash(hs.clientHello.marshal()) + hs.writeServerHash(hs.hello.marshal()) + + c.writeRecord(recordTypeHandshake, hs.hello.marshal()) + + if !isPSK { + certMsg := new(certificateMsg) + if !config.Bugs.EmptyCertificateList { + certMsg.certificates = hs.cert.Certificate + } + if !config.Bugs.UnauthenticatedECDH { + certMsgBytes := certMsg.marshal() + if config.Bugs.WrongCertificateMessageType { + certMsgBytes[0] += 42 + } + hs.writeServerHash(certMsgBytes) + c.writeRecord(recordTypeHandshake, certMsgBytes) + } + } + + if hs.hello.ocspStapling && !c.config.Bugs.SkipCertificateStatus { + certStatus := new(certificateStatusMsg) + certStatus.statusType = statusTypeOCSP + certStatus.response = hs.cert.OCSPStaple + hs.writeServerHash(certStatus.marshal()) + c.writeRecord(recordTypeHandshake, certStatus.marshal()) + } + + keyAgreement := hs.suite.ka(c.vers) + skx, err := keyAgreement.generateServerKeyExchange(config, hs.cert, hs.clientHello, hs.hello) + if err != nil { + c.sendAlert(alertHandshakeFailure) + return err + } + if skx != nil && !config.Bugs.SkipServerKeyExchange { + hs.writeServerHash(skx.marshal()) + c.writeRecord(recordTypeHandshake, skx.marshal()) + } + + if config.ClientAuth >= RequestClientCert { + // Request a client certificate + certReq := &certificateRequestMsg{ + certificateTypes: config.ClientCertificateTypes, + } + if certReq.certificateTypes == nil { + certReq.certificateTypes = []byte{ + byte(CertTypeRSASign), + byte(CertTypeECDSASign), + } + } + if c.vers >= VersionTLS12 { + certReq.hasSignatureAndHash = true + if !config.Bugs.NoSignatureAndHashes { + certReq.signatureAndHashes = config.signatureAndHashesForServer() + } + } + + // An empty list of certificateAuthorities signals to + // the client that it may send any certificate in response + // to our request. When we know the CAs we trust, then + // we can send them down, so that the client can choose + // an appropriate certificate to give to us. + if config.ClientCAs != nil { + certReq.certificateAuthorities = config.ClientCAs.Subjects() + } + hs.writeServerHash(certReq.marshal()) + c.writeRecord(recordTypeHandshake, certReq.marshal()) + } + + helloDone := new(serverHelloDoneMsg) + hs.writeServerHash(helloDone.marshal()) + c.writeRecord(recordTypeHandshake, helloDone.marshal()) + c.dtlsFlushHandshake() + + var pub crypto.PublicKey // public key for client auth, if any + + if err := c.simulatePacketLoss(nil); err != nil { + return err + } + msg, err := c.readHandshake() + if err != nil { + return err + } + + var ok bool + // If we requested a client certificate, then the client must send a + // certificate message, even if it's empty. + if config.ClientAuth >= RequestClientCert { + var certMsg *certificateMsg + var certificates [][]byte + if certMsg, ok = msg.(*certificateMsg); ok { + if c.vers == VersionSSL30 && len(certMsg.certificates) == 0 { + return errors.New("tls: empty certificate message in SSL 3.0") + } + + hs.writeClientHash(certMsg.marshal()) + certificates = certMsg.certificates + } else if c.vers != VersionSSL30 { + // In TLS, the Certificate message is required. In SSL + // 3.0, the peer skips it when sending no certificates. + c.sendAlert(alertUnexpectedMessage) + return unexpectedMessageError(certMsg, msg) + } + + if len(certificates) == 0 { + // The client didn't actually send a certificate + switch config.ClientAuth { + case RequireAnyClientCert, RequireAndVerifyClientCert: + c.sendAlert(alertBadCertificate) + return errors.New("tls: client didn't provide a certificate") + } + } + + pub, err = hs.processCertsFromClient(certificates) + if err != nil { + return err + } + + if ok { + msg, err = c.readHandshake() + if err != nil { + return err + } + } + } + + // Get client key exchange + ckx, ok := msg.(*clientKeyExchangeMsg) + if !ok { + c.sendAlert(alertUnexpectedMessage) + return unexpectedMessageError(ckx, msg) + } + hs.writeClientHash(ckx.marshal()) + + preMasterSecret, err := keyAgreement.processClientKeyExchange(config, hs.cert, ckx, c.vers) + if err != nil { + c.sendAlert(alertHandshakeFailure) + return err + } + if c.extendedMasterSecret { + hs.masterSecret = extendedMasterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.finishedHash) + } else { + if c.config.Bugs.RequireExtendedMasterSecret { + return errors.New("tls: extended master secret required but not supported by peer") + } + hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.clientHello.random, hs.hello.random) + } + + // If we received a client cert in response to our certificate request message, + // the client will send us a certificateVerifyMsg immediately after the + // clientKeyExchangeMsg. This message is a digest of all preceding + // handshake-layer messages that is signed using the private key corresponding + // to the client's certificate. This allows us to verify that the client is in + // possession of the private key of the certificate. + if len(c.peerCertificates) > 0 { + msg, err = c.readHandshake() + if err != nil { + return err + } + certVerify, ok := msg.(*certificateVerifyMsg) + if !ok { + c.sendAlert(alertUnexpectedMessage) + return unexpectedMessageError(certVerify, msg) + } + + // Determine the signature type. + var signatureAndHash signatureAndHash + if certVerify.hasSignatureAndHash { + signatureAndHash = certVerify.signatureAndHash + if !isSupportedSignatureAndHash(signatureAndHash, config.signatureAndHashesForServer()) { + return errors.New("tls: unsupported hash function for client certificate") + } + c.clientCertSignatureHash = signatureAndHash.hash + } else { + // Before TLS 1.2 the signature algorithm was implicit + // from the key type, and only one hash per signature + // algorithm was possible. Leave the hash as zero. + switch pub.(type) { + case *ecdsa.PublicKey: + signatureAndHash.signature = signatureECDSA + case *rsa.PublicKey: + signatureAndHash.signature = signatureRSA + } + } + + switch key := pub.(type) { + case *ecdsa.PublicKey: + if signatureAndHash.signature != signatureECDSA { + err = errors.New("tls: bad signature type for client's ECDSA certificate") + break + } + ecdsaSig := new(ecdsaSignature) + if _, err = asn1.Unmarshal(certVerify.signature, ecdsaSig); err != nil { + break + } + if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 { + err = errors.New("ECDSA signature contained zero or negative values") + break + } + var digest []byte + digest, _, err = hs.finishedHash.hashForClientCertificate(signatureAndHash, hs.masterSecret) + if err != nil { + break + } + if !ecdsa.Verify(key, digest, ecdsaSig.R, ecdsaSig.S) { + err = errors.New("ECDSA verification failure") + break + } + case *rsa.PublicKey: + if signatureAndHash.signature != signatureRSA { + err = errors.New("tls: bad signature type for client's RSA certificate") + break + } + var digest []byte + var hashFunc crypto.Hash + digest, hashFunc, err = hs.finishedHash.hashForClientCertificate(signatureAndHash, hs.masterSecret) + if err != nil { + break + } + err = rsa.VerifyPKCS1v15(key, hashFunc, digest, certVerify.signature) + } + if err != nil { + c.sendAlert(alertBadCertificate) + return errors.New("could not validate signature of connection nonces: " + err.Error()) + } + + hs.writeClientHash(certVerify.marshal()) + } + + hs.finishedHash.discardHandshakeBuffer() + + return nil +} + +func (hs *serverHandshakeState) establishKeys() error { + c := hs.c + + clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV := + keysFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.clientHello.random, hs.hello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen) + + var clientCipher, serverCipher interface{} + var clientHash, serverHash macFunction + + if hs.suite.aead == nil { + clientCipher = hs.suite.cipher(clientKey, clientIV, true /* for reading */) + clientHash = hs.suite.mac(c.vers, clientMAC) + serverCipher = hs.suite.cipher(serverKey, serverIV, false /* not for reading */) + serverHash = hs.suite.mac(c.vers, serverMAC) + } else { + clientCipher = hs.suite.aead(clientKey, clientIV) + serverCipher = hs.suite.aead(serverKey, serverIV) + } + + c.in.prepareCipherSpec(c.vers, clientCipher, clientHash) + c.out.prepareCipherSpec(c.vers, serverCipher, serverHash) + + return nil +} + +func (hs *serverHandshakeState) readFinished(out []byte, isResume bool) error { + c := hs.c + + c.readRecord(recordTypeChangeCipherSpec) + if err := c.in.error(); err != nil { + return err + } + + if hs.hello.nextProtoNeg { + msg, err := c.readHandshake() + if err != nil { + return err + } + nextProto, ok := msg.(*nextProtoMsg) + if !ok { + c.sendAlert(alertUnexpectedMessage) + return unexpectedMessageError(nextProto, msg) + } + hs.writeClientHash(nextProto.marshal()) + c.clientProtocol = nextProto.proto + } + + if hs.hello.channelIDRequested { + msg, err := c.readHandshake() + if err != nil { + return err + } + encryptedExtensions, ok := msg.(*encryptedExtensionsMsg) + if !ok { + c.sendAlert(alertUnexpectedMessage) + return unexpectedMessageError(encryptedExtensions, msg) + } + x := new(big.Int).SetBytes(encryptedExtensions.channelID[0:32]) + y := new(big.Int).SetBytes(encryptedExtensions.channelID[32:64]) + r := new(big.Int).SetBytes(encryptedExtensions.channelID[64:96]) + s := new(big.Int).SetBytes(encryptedExtensions.channelID[96:128]) + if !elliptic.P256().IsOnCurve(x, y) { + return errors.New("tls: invalid channel ID public key") + } + channelID := &ecdsa.PublicKey{elliptic.P256(), x, y} + var resumeHash []byte + if isResume { + resumeHash = hs.sessionState.handshakeHash + } + if !ecdsa.Verify(channelID, hs.finishedHash.hashForChannelID(resumeHash), r, s) { + return errors.New("tls: invalid channel ID signature") + } + c.channelID = channelID + + hs.writeClientHash(encryptedExtensions.marshal()) + } + + msg, err := c.readHandshake() + if err != nil { + return err + } + clientFinished, ok := msg.(*finishedMsg) + if !ok { + c.sendAlert(alertUnexpectedMessage) + return unexpectedMessageError(clientFinished, msg) + } + + verify := hs.finishedHash.clientSum(hs.masterSecret) + if len(verify) != len(clientFinished.verifyData) || + subtle.ConstantTimeCompare(verify, clientFinished.verifyData) != 1 { + c.sendAlert(alertHandshakeFailure) + return errors.New("tls: client's Finished message is incorrect") + } + c.clientVerify = append(c.clientVerify[:0], clientFinished.verifyData...) + copy(out, clientFinished.verifyData) + + hs.writeClientHash(clientFinished.marshal()) + return nil +} + +func (hs *serverHandshakeState) sendSessionTicket() error { + c := hs.c + state := sessionState{ + vers: c.vers, + cipherSuite: hs.suite.id, + masterSecret: hs.masterSecret, + certificates: hs.certsFromClient, + handshakeHash: hs.finishedHash.server.Sum(nil), + } + + if !hs.hello.ticketSupported || hs.c.config.Bugs.SkipNewSessionTicket { + if c.config.ServerSessionCache != nil && len(hs.hello.sessionId) != 0 { + c.config.ServerSessionCache.Put(string(hs.hello.sessionId), &state) + } + return nil + } + + m := new(newSessionTicketMsg) + + if !c.config.Bugs.SendEmptySessionTicket { + var err error + m.ticket, err = c.encryptTicket(&state) + if err != nil { + return err + } + } + + hs.writeServerHash(m.marshal()) + c.writeRecord(recordTypeHandshake, m.marshal()) + + return nil +} + +func (hs *serverHandshakeState) sendFinished(out []byte) error { + c := hs.c + + finished := new(finishedMsg) + finished.verifyData = hs.finishedHash.serverSum(hs.masterSecret) + copy(out, finished.verifyData) + if c.config.Bugs.BadFinished { + finished.verifyData[0]++ + } + c.serverVerify = append(c.serverVerify[:0], finished.verifyData...) + hs.finishedBytes = finished.marshal() + hs.writeServerHash(hs.finishedBytes) + postCCSBytes := hs.finishedBytes + + if c.config.Bugs.FragmentAcrossChangeCipherSpec { + c.writeRecord(recordTypeHandshake, postCCSBytes[:5]) + postCCSBytes = postCCSBytes[5:] + } + c.dtlsFlushHandshake() + + if !c.config.Bugs.SkipChangeCipherSpec { + ccs := []byte{1} + if c.config.Bugs.BadChangeCipherSpec != nil { + ccs = c.config.Bugs.BadChangeCipherSpec + } + c.writeRecord(recordTypeChangeCipherSpec, ccs) + } + + if c.config.Bugs.AppDataAfterChangeCipherSpec != nil { + c.writeRecord(recordTypeApplicationData, c.config.Bugs.AppDataAfterChangeCipherSpec) + } + if c.config.Bugs.AlertAfterChangeCipherSpec != 0 { + c.sendAlert(c.config.Bugs.AlertAfterChangeCipherSpec) + return errors.New("tls: simulating post-CCS alert") + } + + if !c.config.Bugs.SkipFinished { + c.writeRecord(recordTypeHandshake, postCCSBytes) + c.dtlsFlushHandshake() + } + + c.cipherSuite = hs.suite + + return nil +} + +// processCertsFromClient takes a chain of client certificates either from a +// Certificates message or from a sessionState and verifies them. It returns +// the public key of the leaf certificate. +func (hs *serverHandshakeState) processCertsFromClient(certificates [][]byte) (crypto.PublicKey, error) { + c := hs.c + + hs.certsFromClient = certificates + certs := make([]*x509.Certificate, len(certificates)) + var err error + for i, asn1Data := range certificates { + if certs[i], err = x509.ParseCertificate(asn1Data); err != nil { + c.sendAlert(alertBadCertificate) + return nil, errors.New("tls: failed to parse client certificate: " + err.Error()) + } + } + + if c.config.ClientAuth >= VerifyClientCertIfGiven && len(certs) > 0 { + opts := x509.VerifyOptions{ + Roots: c.config.ClientCAs, + CurrentTime: c.config.time(), + Intermediates: x509.NewCertPool(), + KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, + } + + for _, cert := range certs[1:] { + opts.Intermediates.AddCert(cert) + } + + chains, err := certs[0].Verify(opts) + if err != nil { + c.sendAlert(alertBadCertificate) + return nil, errors.New("tls: failed to verify client's certificate: " + err.Error()) + } + + ok := false + for _, ku := range certs[0].ExtKeyUsage { + if ku == x509.ExtKeyUsageClientAuth { + ok = true + break + } + } + if !ok { + c.sendAlert(alertHandshakeFailure) + return nil, errors.New("tls: client's certificate's extended key usage doesn't permit it to be used for client authentication") + } + + c.verifiedChains = chains + } + + if len(certs) > 0 { + var pub crypto.PublicKey + switch key := certs[0].PublicKey.(type) { + case *ecdsa.PublicKey, *rsa.PublicKey: + pub = key + default: + c.sendAlert(alertUnsupportedCertificate) + return nil, fmt.Errorf("tls: client's certificate contains an unsupported public key of type %T", certs[0].PublicKey) + } + c.peerCertificates = certs + return pub, nil + } + + return nil, nil +} + +func (hs *serverHandshakeState) writeServerHash(msg []byte) { + // writeServerHash is called before writeRecord. + hs.writeHash(msg, hs.c.sendHandshakeSeq) +} + +func (hs *serverHandshakeState) writeClientHash(msg []byte) { + // writeClientHash is called after readHandshake. + hs.writeHash(msg, hs.c.recvHandshakeSeq-1) +} + +func (hs *serverHandshakeState) writeHash(msg []byte, seqno uint16) { + if hs.c.isDTLS { + // This is somewhat hacky. DTLS hashes a slightly different format. + // First, the TLS header. + hs.finishedHash.Write(msg[:4]) + // Then the sequence number and reassembled fragment offset (always 0). + hs.finishedHash.Write([]byte{byte(seqno >> 8), byte(seqno), 0, 0, 0}) + // Then the reassembled fragment (always equal to the message length). + hs.finishedHash.Write(msg[1:4]) + // And then the message body. + hs.finishedHash.Write(msg[4:]) + } else { + hs.finishedHash.Write(msg) + } +} + +// tryCipherSuite returns a cipherSuite with the given id if that cipher suite +// is acceptable to use. +func (c *Conn) tryCipherSuite(id uint16, supportedCipherSuites []uint16, version uint16, ellipticOk, ecdsaOk bool) *cipherSuite { + for _, supported := range supportedCipherSuites { + if id == supported { + var candidate *cipherSuite + + for _, s := range cipherSuites { + if s.id == id { + candidate = s + break + } + } + if candidate == nil { + continue + } + // Don't select a ciphersuite which we can't + // support for this client. + if (candidate.flags&suiteECDHE != 0) && !ellipticOk { + continue + } + if (candidate.flags&suiteECDSA != 0) != ecdsaOk { + continue + } + if !c.config.Bugs.SkipCipherVersionCheck && version < VersionTLS12 && candidate.flags&suiteTLS12 != 0 { + continue + } + if c.isDTLS && candidate.flags&suiteNoDTLS != 0 { + continue + } + return candidate + } + } + + return nil +} + +func isTLS12Cipher(id uint16) bool { + for _, cipher := range cipherSuites { + if cipher.id != id { + continue + } + return cipher.flags&suiteTLS12 != 0 + } + // Unknown cipher. + return false +} diff --git a/external/boringssl/ssl/test/runner/key.pem b/external/boringssl/ssl/test/runner/key.pem new file mode 100644 index 0000000000..e9107bfee9 --- /dev/null +++ b/external/boringssl/ssl/test/runner/key.pem @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXgIBAAKBgQDYK8imMuRi/03z0K1Zi0WnvfFHvwlYeyK9Na6XJYaUoIDAtB92 +kWdGMdAQhLciHnAjkXLI6W15OoV3gA/ElRZ1xUpxTMhjP6PyY5wqT5r6y8FxbiiF +KKAnHmUcrgfVW28tQ+0rkLGMryRtrukXOgXBv7gcrmU7G1jC2a7WqmeI8QIDAQAB +AoGBAIBy09Fd4DOq/Ijp8HeKuCMKTHqTW1xGHshLQ6jwVV2vWZIn9aIgmDsvkjCe +i6ssZvnbjVcwzSoByhjN8ZCf/i15HECWDFFh6gt0P5z0MnChwzZmvatV/FXCT0j+ +WmGNB/gkehKjGXLLcjTb6dRYVJSCZhVuOLLcbWIV10gggJQBAkEA8S8sGe4ezyyZ +m4e9r95g6s43kPqtj5rewTsUxt+2n4eVodD+ZUlCULWVNAFLkYRTBCASlSrm9Xhj +QpmWAHJUkQJBAOVzQdFUaewLtdOJoPCtpYoY1zd22eae8TQEmpGOR11L6kbxLQsk +aMly/DOnOaa82tqAGTdqDEZgSNmCeKKknmECQAvpnY8GUOVAubGR6c+W90iBuQLj +LtFp/9ihd2w/PoDwrHZaoUYVcT4VSfJQog/k7kjE4MYXYWL8eEKg3WTWQNECQQDk +104Wi91Umd1PzF0ijd2jXOERJU1wEKe6XLkYYNHWQAe5l4J4MWj9OdxFXAxIuuR/ +tfDwbqkta4xcux67//khAkEAvvRXLHTaa6VFzTaiiO8SaFsHV3lQyXOtMrBpB5jd +moZWgjHvB2W9Ckn7sDqsPB+U2tyX0joDdQEyuiMECDY8oQ== +-----END RSA PRIVATE KEY----- diff --git a/external/boringssl/ssl/test/runner/key_agreement.go b/external/boringssl/ssl/test/runner/key_agreement.go new file mode 100644 index 0000000000..5e5d976d0a --- /dev/null +++ b/external/boringssl/ssl/test/runner/key_agreement.go @@ -0,0 +1,1103 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package runner + +import ( + "crypto" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/md5" + "crypto/rand" + "crypto/rsa" + "crypto/sha1" + "crypto/subtle" + "crypto/x509" + "encoding/asn1" + "errors" + "fmt" + "io" + "math/big" + + "./curve25519" + "./newhope" +) + +var errClientKeyExchange = errors.New("tls: invalid ClientKeyExchange message") +var errServerKeyExchange = errors.New("tls: invalid ServerKeyExchange message") + +// rsaKeyAgreement implements the standard TLS key agreement where the client +// encrypts the pre-master secret to the server's public key. +type rsaKeyAgreement struct { + version uint16 + clientVersion uint16 + exportKey *rsa.PrivateKey +} + +func (ka *rsaKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) { + // Save the client version for comparison later. + ka.clientVersion = versionToWire(clientHello.vers, clientHello.isDTLS) + + if !config.Bugs.RSAEphemeralKey { + return nil, nil + } + + // Generate an ephemeral RSA key to use instead of the real + // one, as in RSA_EXPORT. + key, err := rsa.GenerateKey(config.rand(), 512) + if err != nil { + return nil, err + } + ka.exportKey = key + + modulus := key.N.Bytes() + exponent := big.NewInt(int64(key.E)).Bytes() + serverRSAParams := make([]byte, 0, 2+len(modulus)+2+len(exponent)) + serverRSAParams = append(serverRSAParams, byte(len(modulus)>>8), byte(len(modulus))) + serverRSAParams = append(serverRSAParams, modulus...) + serverRSAParams = append(serverRSAParams, byte(len(exponent)>>8), byte(len(exponent))) + serverRSAParams = append(serverRSAParams, exponent...) + + var tls12HashId uint8 + if ka.version >= VersionTLS12 { + if tls12HashId, err = pickTLS12HashForSignature(signatureRSA, clientHello.signatureAndHashes, config.signatureAndHashesForServer()); err != nil { + return nil, err + } + } + + digest, hashFunc, err := hashForServerKeyExchange(signatureRSA, tls12HashId, ka.version, clientHello.random, hello.random, serverRSAParams) + if err != nil { + return nil, err + } + privKey, ok := cert.PrivateKey.(*rsa.PrivateKey) + if !ok { + return nil, errors.New("RSA ephemeral key requires an RSA server private key") + } + sig, err := rsa.SignPKCS1v15(config.rand(), privKey, hashFunc, digest) + if err != nil { + return nil, errors.New("failed to sign RSA parameters: " + err.Error()) + } + + skx := new(serverKeyExchangeMsg) + sigAndHashLen := 0 + if ka.version >= VersionTLS12 { + sigAndHashLen = 2 + } + skx.key = make([]byte, len(serverRSAParams)+sigAndHashLen+2+len(sig)) + copy(skx.key, serverRSAParams) + k := skx.key[len(serverRSAParams):] + if ka.version >= VersionTLS12 { + k[0] = tls12HashId + k[1] = signatureRSA + k = k[2:] + } + k[0] = byte(len(sig) >> 8) + k[1] = byte(len(sig)) + copy(k[2:], sig) + + return skx, nil +} + +func (ka *rsaKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) { + preMasterSecret := make([]byte, 48) + _, err := io.ReadFull(config.rand(), preMasterSecret[2:]) + if err != nil { + return nil, err + } + + if len(ckx.ciphertext) < 2 { + return nil, errClientKeyExchange + } + + ciphertext := ckx.ciphertext + if version != VersionSSL30 { + ciphertextLen := int(ckx.ciphertext[0])<<8 | int(ckx.ciphertext[1]) + if ciphertextLen != len(ckx.ciphertext)-2 { + return nil, errClientKeyExchange + } + ciphertext = ckx.ciphertext[2:] + } + + key := cert.PrivateKey.(*rsa.PrivateKey) + if ka.exportKey != nil { + key = ka.exportKey + } + err = rsa.DecryptPKCS1v15SessionKey(config.rand(), key, ciphertext, preMasterSecret) + if err != nil { + return nil, err + } + // This check should be done in constant-time, but this is a testing + // implementation. See the discussion at the end of section 7.4.7.1 of + // RFC 4346. + vers := uint16(preMasterSecret[0])<<8 | uint16(preMasterSecret[1]) + if ka.clientVersion != vers { + return nil, errors.New("tls: invalid version in RSA premaster") + } + return preMasterSecret, nil +} + +func (ka *rsaKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error { + return errors.New("tls: unexpected ServerKeyExchange") +} + +func (ka *rsaKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) { + bad := config.Bugs.BadRSAClientKeyExchange + preMasterSecret := make([]byte, 48) + vers := clientHello.vers + if bad == RSABadValueWrongVersion { + vers ^= 1 + } + vers = versionToWire(vers, clientHello.isDTLS) + preMasterSecret[0] = byte(vers >> 8) + preMasterSecret[1] = byte(vers) + _, err := io.ReadFull(config.rand(), preMasterSecret[2:]) + if err != nil { + return nil, nil, err + } + + sentPreMasterSecret := preMasterSecret + if bad == RSABadValueTooLong { + sentPreMasterSecret = make([]byte, len(sentPreMasterSecret)+1) + copy(sentPreMasterSecret, preMasterSecret) + } else if bad == RSABadValueTooShort { + sentPreMasterSecret = sentPreMasterSecret[:len(sentPreMasterSecret)-1] + } + + encrypted, err := rsa.EncryptPKCS1v15(config.rand(), cert.PublicKey.(*rsa.PublicKey), sentPreMasterSecret) + if err != nil { + return nil, nil, err + } + if bad == RSABadValueCorrupt { + encrypted[len(encrypted)-1] ^= 1 + // Clear the high byte to ensure |encrypted| is still below the RSA modulus. + encrypted[0] = 0 + } + ckx := new(clientKeyExchangeMsg) + if clientHello.vers != VersionSSL30 { + ckx.ciphertext = make([]byte, len(encrypted)+2) + ckx.ciphertext[0] = byte(len(encrypted) >> 8) + ckx.ciphertext[1] = byte(len(encrypted)) + copy(ckx.ciphertext[2:], encrypted) + } else { + ckx.ciphertext = encrypted + } + return preMasterSecret, ckx, nil +} + +// sha1Hash calculates a SHA1 hash over the given byte slices. +func sha1Hash(slices [][]byte) []byte { + hsha1 := sha1.New() + for _, slice := range slices { + hsha1.Write(slice) + } + return hsha1.Sum(nil) +} + +// md5SHA1Hash implements TLS 1.0's hybrid hash function which consists of the +// concatenation of an MD5 and SHA1 hash. +func md5SHA1Hash(slices [][]byte) []byte { + md5sha1 := make([]byte, md5.Size+sha1.Size) + hmd5 := md5.New() + for _, slice := range slices { + hmd5.Write(slice) + } + copy(md5sha1, hmd5.Sum(nil)) + copy(md5sha1[md5.Size:], sha1Hash(slices)) + return md5sha1 +} + +// hashForServerKeyExchange hashes the given slices and returns their digest +// and the identifier of the hash function used. The hashFunc argument is only +// used for >= TLS 1.2 and precisely identifies the hash function to use. +func hashForServerKeyExchange(sigType, hashFunc uint8, version uint16, slices ...[]byte) ([]byte, crypto.Hash, error) { + if version >= VersionTLS12 { + hash, err := lookupTLSHash(hashFunc) + if err != nil { + return nil, 0, err + } + h := hash.New() + for _, slice := range slices { + h.Write(slice) + } + return h.Sum(nil), hash, nil + } + if sigType == signatureECDSA { + return sha1Hash(slices), crypto.SHA1, nil + } + return md5SHA1Hash(slices), crypto.MD5SHA1, nil +} + +// pickTLS12HashForSignature returns a TLS 1.2 hash identifier for signing a +// ServerKeyExchange given the signature type being used and the client's +// advertized list of supported signature and hash combinations. +func pickTLS12HashForSignature(sigType uint8, clientList, serverList []signatureAndHash) (uint8, error) { + if len(clientList) == 0 { + // If the client didn't specify any signature_algorithms + // extension then we can assume that it supports SHA1. See + // http://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 + return hashSHA1, nil + } + + for _, sigAndHash := range clientList { + if sigAndHash.signature != sigType { + continue + } + if isSupportedSignatureAndHash(sigAndHash, serverList) { + return sigAndHash.hash, nil + } + } + + return 0, errors.New("tls: client doesn't support any common hash functions") +} + +// A ecdhCurve is an instance of ECDH-style key agreement for TLS. +type ecdhCurve interface { + // offer generates a keypair using rand. It returns the encoded |publicKey|. + offer(rand io.Reader) (publicKey []byte, err error) + + // accept responds to the |peerKey| generated by |offer| with the acceptor's + // |publicKey|, and returns agreed-upon |preMasterSecret| to the acceptor. + accept(rand io.Reader, peerKey []byte) (publicKey []byte, preMasterSecret []byte, err error) + + // finish returns the computed |preMasterSecret|, given the |peerKey| + // generated by |accept|. + finish(peerKey []byte) (preMasterSecret []byte, err error) +} + +// ellipticECDHCurve implements ecdhCurve with an elliptic.Curve. +type ellipticECDHCurve struct { + curve elliptic.Curve + privateKey []byte +} + +func (e *ellipticECDHCurve) offer(rand io.Reader) (publicKey []byte, err error) { + var x, y *big.Int + e.privateKey, x, y, err = elliptic.GenerateKey(e.curve, rand) + if err != nil { + return nil, err + } + return elliptic.Marshal(e.curve, x, y), nil +} + +func (e *ellipticECDHCurve) accept(rand io.Reader, peerKey []byte) (publicKey []byte, preMasterSecret []byte, err error) { + publicKey, err = e.offer(rand) + if err != nil { + return nil, nil, err + } + preMasterSecret, err = e.finish(peerKey) + if err != nil { + return nil, nil, err + } + return +} + +func (e *ellipticECDHCurve) finish(peerKey []byte) (preMasterSecret []byte, err error) { + x, y := elliptic.Unmarshal(e.curve, peerKey) + if x == nil { + return nil, errors.New("tls: invalid peer key") + } + x, _ = e.curve.ScalarMult(x, y, e.privateKey) + preMasterSecret = make([]byte, (e.curve.Params().BitSize+7)>>3) + xBytes := x.Bytes() + copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes) + + return preMasterSecret, nil +} + +// x25519ECDHCurve implements ecdhCurve with X25519. +type x25519ECDHCurve struct { + privateKey [32]byte +} + +func (e *x25519ECDHCurve) offer(rand io.Reader) (publicKey []byte, err error) { + _, err = io.ReadFull(rand, e.privateKey[:]) + if err != nil { + return + } + var out [32]byte + curve25519.ScalarBaseMult(&out, &e.privateKey) + return out[:], nil +} + +func (e *x25519ECDHCurve) accept(rand io.Reader, peerKey []byte) (publicKey []byte, preMasterSecret []byte, err error) { + publicKey, err = e.offer(rand) + if err != nil { + return nil, nil, err + } + preMasterSecret, err = e.finish(peerKey) + if err != nil { + return nil, nil, err + } + return +} + +func (e *x25519ECDHCurve) finish(peerKey []byte) (preMasterSecret []byte, err error) { + if len(peerKey) != 32 { + return nil, errors.New("tls: invalid peer key") + } + var out, peerKeyCopy [32]byte + copy(peerKeyCopy[:], peerKey) + curve25519.ScalarMult(&out, &e.privateKey, &peerKeyCopy) + + // Per RFC 7748, reject the all-zero value in constant time. + var zeros [32]byte + if subtle.ConstantTimeCompare(zeros[:], out[:]) == 1 { + return nil, errors.New("tls: X25519 value with wrong order") + } + + return out[:], nil +} + +// cecpq1Curve is combined elliptic curve (X25519) and post-quantum (new hope) key +// agreement. +type cecpq1Curve struct { + x25519 *x25519ECDHCurve + newhope *newhope.Poly +} + +func (e *cecpq1Curve) offer(rand io.Reader) (publicKey []byte, err error) { + var x25519OfferMsg, newhopeOfferMsg []byte + + e.x25519 = new(x25519ECDHCurve) + if x25519OfferMsg, err = e.x25519.offer(rand); err != nil { + return nil, err + } + + newhopeOfferMsg, e.newhope = newhope.Offer(rand) + + return append(x25519OfferMsg, newhopeOfferMsg[:]...), nil +} + +func (e *cecpq1Curve) accept(rand io.Reader, peerKey []byte) (publicKey []byte, preMasterSecret []byte, err error) { + if len(peerKey) != 32+newhope.OfferMsgLen { + return nil, nil, errors.New("cecpq1: invalid offer message") + } + + var x25519AcceptMsg, newhopeAcceptMsg []byte + var x25519Secret []byte + var newhopeSecret newhope.Key + + x25519 := new(x25519ECDHCurve) + if x25519AcceptMsg, x25519Secret, err = x25519.accept(rand, peerKey[:32]); err != nil { + return nil, nil, err + } + + if newhopeSecret, newhopeAcceptMsg, err = newhope.Accept(rand, peerKey[32:]); err != nil { + return nil, nil, err + } + + return append(x25519AcceptMsg, newhopeAcceptMsg[:]...), append(x25519Secret, newhopeSecret[:]...), nil +} + +func (e *cecpq1Curve) finish(peerKey []byte) (preMasterSecret []byte, err error) { + if len(peerKey) != 32+newhope.AcceptMsgLen { + return nil, errors.New("cecpq1: invalid accept message") + } + + var x25519Secret []byte + var newhopeSecret newhope.Key + + if x25519Secret, err = e.x25519.finish(peerKey[:32]); err != nil { + return nil, err + } + + if newhopeSecret, err = e.newhope.Finish(peerKey[32:]); err != nil { + return nil, err + } + + return append(x25519Secret, newhopeSecret[:]...), nil +} + +func curveForCurveID(id CurveID) (ecdhCurve, bool) { + switch id { + case CurveP224: + return &ellipticECDHCurve{curve: elliptic.P224()}, true + case CurveP256: + return &ellipticECDHCurve{curve: elliptic.P256()}, true + case CurveP384: + return &ellipticECDHCurve{curve: elliptic.P384()}, true + case CurveP521: + return &ellipticECDHCurve{curve: elliptic.P521()}, true + case CurveX25519: + return &x25519ECDHCurve{}, true + default: + return nil, false + } + +} + +// keyAgreementAuthentication is a helper interface that specifies how +// to authenticate the ServerKeyExchange parameters. +type keyAgreementAuthentication interface { + signParameters(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg, params []byte) (*serverKeyExchangeMsg, error) + verifyParameters(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, params []byte, sig []byte) error +} + +// nilKeyAgreementAuthentication does not authenticate the key +// agreement parameters. +type nilKeyAgreementAuthentication struct{} + +func (ka *nilKeyAgreementAuthentication) signParameters(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg, params []byte) (*serverKeyExchangeMsg, error) { + skx := new(serverKeyExchangeMsg) + skx.key = params + return skx, nil +} + +func (ka *nilKeyAgreementAuthentication) verifyParameters(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, params []byte, sig []byte) error { + return nil +} + +func maybeCorruptECDSAValue(n *big.Int, typeOfCorruption BadValue, limit *big.Int) *big.Int { + switch typeOfCorruption { + case BadValueNone: + return n + case BadValueNegative: + return new(big.Int).Neg(n) + case BadValueZero: + return big.NewInt(0) + case BadValueLimit: + return limit + case BadValueLarge: + bad := new(big.Int).Set(limit) + return bad.Lsh(bad, 20) + default: + panic("unknown BadValue type") + } +} + +// signedKeyAgreement signs the ServerKeyExchange parameters with the +// server's private key. +type signedKeyAgreement struct { + version uint16 + sigType uint8 +} + +func (ka *signedKeyAgreement) signParameters(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg, params []byte) (*serverKeyExchangeMsg, error) { + var tls12HashId uint8 + var err error + if ka.version >= VersionTLS12 { + if tls12HashId, err = pickTLS12HashForSignature(ka.sigType, clientHello.signatureAndHashes, config.signatureAndHashesForServer()); err != nil { + return nil, err + } + } + + digest, hashFunc, err := hashForServerKeyExchange(ka.sigType, tls12HashId, ka.version, clientHello.random, hello.random, params) + if err != nil { + return nil, err + } + + if config.Bugs.InvalidSKXSignature { + digest[0] ^= 0x80 + } + + var sig []byte + switch ka.sigType { + case signatureECDSA: + privKey, ok := cert.PrivateKey.(*ecdsa.PrivateKey) + if !ok { + return nil, errors.New("ECDHE ECDSA requires an ECDSA server private key") + } + r, s, err := ecdsa.Sign(config.rand(), privKey, digest) + if err != nil { + return nil, errors.New("failed to sign ECDHE parameters: " + err.Error()) + } + order := privKey.Curve.Params().N + r = maybeCorruptECDSAValue(r, config.Bugs.BadECDSAR, order) + s = maybeCorruptECDSAValue(s, config.Bugs.BadECDSAS, order) + sig, err = asn1.Marshal(ecdsaSignature{r, s}) + case signatureRSA: + privKey, ok := cert.PrivateKey.(*rsa.PrivateKey) + if !ok { + return nil, errors.New("ECDHE RSA requires a RSA server private key") + } + sig, err = rsa.SignPKCS1v15(config.rand(), privKey, hashFunc, digest) + if err != nil { + return nil, errors.New("failed to sign ECDHE parameters: " + err.Error()) + } + default: + return nil, errors.New("unknown ECDHE signature algorithm") + } + + skx := new(serverKeyExchangeMsg) + if config.Bugs.UnauthenticatedECDH { + skx.key = params + } else { + sigAndHashLen := 0 + if ka.version >= VersionTLS12 { + sigAndHashLen = 2 + } + skx.key = make([]byte, len(params)+sigAndHashLen+2+len(sig)) + copy(skx.key, params) + k := skx.key[len(params):] + if ka.version >= VersionTLS12 { + k[0] = tls12HashId + k[1] = ka.sigType + k = k[2:] + } + k[0] = byte(len(sig) >> 8) + k[1] = byte(len(sig)) + copy(k[2:], sig) + } + + return skx, nil +} + +func (ka *signedKeyAgreement) verifyParameters(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, params []byte, sig []byte) error { + if len(sig) < 2 { + return errServerKeyExchange + } + + var tls12HashId uint8 + if ka.version >= VersionTLS12 { + // handle SignatureAndHashAlgorithm + var sigAndHash []uint8 + sigAndHash, sig = sig[:2], sig[2:] + if sigAndHash[1] != ka.sigType { + return errServerKeyExchange + } + tls12HashId = sigAndHash[0] + if len(sig) < 2 { + return errServerKeyExchange + } + + if !isSupportedSignatureAndHash(signatureAndHash{ka.sigType, tls12HashId}, config.signatureAndHashesForClient()) { + return errors.New("tls: unsupported hash function for ServerKeyExchange") + } + } + sigLen := int(sig[0])<<8 | int(sig[1]) + if sigLen+2 != len(sig) { + return errServerKeyExchange + } + sig = sig[2:] + + digest, hashFunc, err := hashForServerKeyExchange(ka.sigType, tls12HashId, ka.version, clientHello.random, serverHello.random, params) + if err != nil { + return err + } + switch ka.sigType { + case signatureECDSA: + pubKey, ok := cert.PublicKey.(*ecdsa.PublicKey) + if !ok { + return errors.New("ECDHE ECDSA requires a ECDSA server public key") + } + ecdsaSig := new(ecdsaSignature) + if _, err := asn1.Unmarshal(sig, ecdsaSig); err != nil { + return err + } + if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 { + return errors.New("ECDSA signature contained zero or negative values") + } + if !ecdsa.Verify(pubKey, digest, ecdsaSig.R, ecdsaSig.S) { + return errors.New("ECDSA verification failure") + } + case signatureRSA: + pubKey, ok := cert.PublicKey.(*rsa.PublicKey) + if !ok { + return errors.New("ECDHE RSA requires a RSA server public key") + } + if err := rsa.VerifyPKCS1v15(pubKey, hashFunc, digest, sig); err != nil { + return err + } + default: + return errors.New("unknown ECDHE signature algorithm") + } + + return nil +} + +// ecdheRSAKeyAgreement implements a TLS key agreement where the server +// generates a ephemeral EC public/private key pair and signs it. The +// pre-master secret is then calculated using ECDH. The signature may +// either be ECDSA or RSA. +type ecdheKeyAgreement struct { + auth keyAgreementAuthentication + curve ecdhCurve + peerKey []byte +} + +func (ka *ecdheKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) { + var curveid CurveID + preferredCurves := config.curvePreferences() + +NextCandidate: + for _, candidate := range preferredCurves { + for _, c := range clientHello.supportedCurves { + if candidate == c { + curveid = c + break NextCandidate + } + } + } + + if curveid == 0 { + return nil, errors.New("tls: no supported elliptic curves offered") + } + + var ok bool + if ka.curve, ok = curveForCurveID(curveid); !ok { + return nil, errors.New("tls: preferredCurves includes unsupported curve") + } + + publicKey, err := ka.curve.offer(config.rand()) + if err != nil { + return nil, err + } + + // http://tools.ietf.org/html/rfc4492#section-5.4 + serverECDHParams := make([]byte, 1+2+1+len(publicKey)) + serverECDHParams[0] = 3 // named curve + serverECDHParams[1] = byte(curveid >> 8) + serverECDHParams[2] = byte(curveid) + if config.Bugs.InvalidSKXCurve { + serverECDHParams[2] ^= 0xff + } + serverECDHParams[3] = byte(len(publicKey)) + copy(serverECDHParams[4:], publicKey) + if config.Bugs.InvalidECDHPoint { + serverECDHParams[4] ^= 0xff + } + + return ka.auth.signParameters(config, cert, clientHello, hello, serverECDHParams) +} + +func (ka *ecdheKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) { + if len(ckx.ciphertext) == 0 || int(ckx.ciphertext[0]) != len(ckx.ciphertext)-1 { + return nil, errClientKeyExchange + } + return ka.curve.finish(ckx.ciphertext[1:]) +} + +func (ka *ecdheKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error { + if len(skx.key) < 4 { + return errServerKeyExchange + } + if skx.key[0] != 3 { // named curve + return errors.New("tls: server selected unsupported curve") + } + curveid := CurveID(skx.key[1])<<8 | CurveID(skx.key[2]) + + var ok bool + if ka.curve, ok = curveForCurveID(curveid); !ok { + return errors.New("tls: server selected unsupported curve") + } + + publicLen := int(skx.key[3]) + if publicLen+4 > len(skx.key) { + return errServerKeyExchange + } + // Save the peer key for later. + ka.peerKey = skx.key[4 : 4+publicLen] + + // Check the signature. + serverECDHParams := skx.key[:4+publicLen] + sig := skx.key[4+publicLen:] + return ka.auth.verifyParameters(config, clientHello, serverHello, cert, serverECDHParams, sig) +} + +func (ka *ecdheKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) { + if ka.curve == nil { + return nil, nil, errors.New("missing ServerKeyExchange message") + } + + publicKey, preMasterSecret, err := ka.curve.accept(config.rand(), ka.peerKey) + if err != nil { + return nil, nil, err + } + + ckx := new(clientKeyExchangeMsg) + ckx.ciphertext = make([]byte, 1+len(publicKey)) + ckx.ciphertext[0] = byte(len(publicKey)) + copy(ckx.ciphertext[1:], publicKey) + if config.Bugs.InvalidECDHPoint { + ckx.ciphertext[1] ^= 0xff + } + + return preMasterSecret, ckx, nil +} + +// cecpq1RSAKeyAgreement is like an ecdheKeyAgreement, but using the cecpq1Curve +// pseudo-curve, and without any parameters (e.g. curve name) other than the +// keys being exchanged. The signature may either be ECDSA or RSA. +type cecpq1KeyAgreement struct { + auth keyAgreementAuthentication + curve ecdhCurve + peerKey []byte +} + +func (ka *cecpq1KeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) { + ka.curve = &cecpq1Curve{} + publicKey, err := ka.curve.offer(config.rand()) + if err != nil { + return nil, err + } + + if config.Bugs.CECPQ1BadX25519Part { + publicKey[0] ^= 1 + } + if config.Bugs.CECPQ1BadNewhopePart { + publicKey[32] ^= 1 + publicKey[33] ^= 1 + publicKey[34] ^= 1 + publicKey[35] ^= 1 + } + + var params []byte + params = append(params, byte(len(publicKey)>>8)) + params = append(params, byte(len(publicKey)&0xff)) + params = append(params, publicKey[:]...) + + return ka.auth.signParameters(config, cert, clientHello, hello, params) +} + +func (ka *cecpq1KeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) { + if len(ckx.ciphertext) < 2 { + return nil, errClientKeyExchange + } + peerKeyLen := int(ckx.ciphertext[0])<<8 + int(ckx.ciphertext[1]) + peerKey := ckx.ciphertext[2:] + if peerKeyLen != len(peerKey) { + return nil, errClientKeyExchange + } + return ka.curve.finish(peerKey) +} + +func (ka *cecpq1KeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error { + if len(skx.key) < 2 { + return errServerKeyExchange + } + peerKeyLen := int(skx.key[0])<<8 + int(skx.key[1]) + // Save the peer key for later. + if len(skx.key) < 2+peerKeyLen { + return errServerKeyExchange + } + ka.peerKey = skx.key[2 : 2+peerKeyLen] + if peerKeyLen != len(ka.peerKey) { + return errServerKeyExchange + } + + // Check the signature. + params := skx.key[:2+peerKeyLen] + sig := skx.key[2+peerKeyLen:] + return ka.auth.verifyParameters(config, clientHello, serverHello, cert, params, sig) +} + +func (ka *cecpq1KeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) { + curve := &cecpq1Curve{} + publicKey, preMasterSecret, err := curve.accept(config.rand(), ka.peerKey) + if err != nil { + return nil, nil, err + } + + if config.Bugs.CECPQ1BadX25519Part { + publicKey[0] ^= 1 + } + if config.Bugs.CECPQ1BadNewhopePart { + publicKey[32] ^= 1 + publicKey[33] ^= 1 + publicKey[34] ^= 1 + publicKey[35] ^= 1 + } + + ckx := new(clientKeyExchangeMsg) + ckx.ciphertext = append(ckx.ciphertext, byte(len(publicKey)>>8)) + ckx.ciphertext = append(ckx.ciphertext, byte(len(publicKey)&0xff)) + ckx.ciphertext = append(ckx.ciphertext, publicKey[:]...) + + return preMasterSecret, ckx, nil +} + +// dheRSAKeyAgreement implements a TLS key agreement where the server generates +// an ephemeral Diffie-Hellman public/private key pair and signs it. The +// pre-master secret is then calculated using Diffie-Hellman. +type dheKeyAgreement struct { + auth keyAgreementAuthentication + p, g *big.Int + yTheirs *big.Int + xOurs *big.Int +} + +func (ka *dheKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) { + var q *big.Int + if p := config.Bugs.DHGroupPrime; p != nil { + ka.p = p + ka.g = big.NewInt(2) + q = p + } else { + // 2048-bit MODP Group with 256-bit Prime Order Subgroup (RFC + // 5114, Section 2.3) + ka.p, _ = new(big.Int).SetString("87A8E61DB4B6663CFFBBD19C651959998CEEF608660DD0F25D2CEED4435E3B00E00DF8F1D61957D4FAF7DF4561B2AA3016C3D91134096FAA3BF4296D830E9A7C209E0C6497517ABD5A8A9D306BCF67ED91F9E6725B4758C022E0B1EF4275BF7B6C5BFC11D45F9088B941F54EB1E59BB8BC39A0BF12307F5C4FDB70C581B23F76B63ACAE1CAA6B7902D52526735488A0EF13C6D9A51BFA4AB3AD8347796524D8EF6A167B5A41825D967E144E5140564251CCACB83E6B486F6B3CA3F7971506026C0B857F689962856DED4010ABD0BE621C3A3960A54E710C375F26375D7014103A4B54330C198AF126116D2276E11715F693877FAD7EF09CADB094AE91E1A1597", 16) + ka.g, _ = new(big.Int).SetString("3FB32C9B73134D0B2E77506660EDBD484CA7B18F21EF205407F4793A1A0BA12510DBC15077BE463FFF4FED4AAC0BB555BE3A6C1B0C6B47B1BC3773BF7E8C6F62901228F8C28CBB18A55AE31341000A650196F931C77A57F2DDF463E5E9EC144B777DE62AAAB8A8628AC376D282D6ED3864E67982428EBC831D14348F6F2F9193B5045AF2767164E1DFC967C1FB3F2E55A4BD1BFFE83B9C80D052B985D182EA0ADB2A3B7313D3FE14C8484B1E052588B9B7D2BBD2DF016199ECD06E1557CD0915B3353BBB64E0EC377FD028370DF92B52C7891428CDC67EB6184B523D1DB246C32F63078490F00EF8D647D148D47954515E2327CFEF98C582664B4C0F6CC41659", 16) + q, _ = new(big.Int).SetString("8CF83642A709A097B447997640129DA299B1A47D1EB3750BA308B0FE64F5FBD3", 16) + } + + var err error + ka.xOurs, err = rand.Int(config.rand(), q) + if err != nil { + return nil, err + } + yOurs := new(big.Int).Exp(ka.g, ka.xOurs, ka.p) + + // http://tools.ietf.org/html/rfc5246#section-7.4.3 + pBytes := ka.p.Bytes() + gBytes := ka.g.Bytes() + yBytes := yOurs.Bytes() + serverDHParams := make([]byte, 0, 2+len(pBytes)+2+len(gBytes)+2+len(yBytes)) + serverDHParams = append(serverDHParams, byte(len(pBytes)>>8), byte(len(pBytes))) + serverDHParams = append(serverDHParams, pBytes...) + serverDHParams = append(serverDHParams, byte(len(gBytes)>>8), byte(len(gBytes))) + serverDHParams = append(serverDHParams, gBytes...) + serverDHParams = append(serverDHParams, byte(len(yBytes)>>8), byte(len(yBytes))) + serverDHParams = append(serverDHParams, yBytes...) + + return ka.auth.signParameters(config, cert, clientHello, hello, serverDHParams) +} + +func (ka *dheKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) { + if len(ckx.ciphertext) < 2 { + return nil, errClientKeyExchange + } + yLen := (int(ckx.ciphertext[0]) << 8) | int(ckx.ciphertext[1]) + if yLen != len(ckx.ciphertext)-2 { + return nil, errClientKeyExchange + } + yTheirs := new(big.Int).SetBytes(ckx.ciphertext[2:]) + if yTheirs.Sign() <= 0 || yTheirs.Cmp(ka.p) >= 0 { + return nil, errClientKeyExchange + } + return new(big.Int).Exp(yTheirs, ka.xOurs, ka.p).Bytes(), nil +} + +func (ka *dheKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error { + // Read dh_p + k := skx.key + if len(k) < 2 { + return errServerKeyExchange + } + pLen := (int(k[0]) << 8) | int(k[1]) + k = k[2:] + if len(k) < pLen { + return errServerKeyExchange + } + ka.p = new(big.Int).SetBytes(k[:pLen]) + k = k[pLen:] + + // Read dh_g + if len(k) < 2 { + return errServerKeyExchange + } + gLen := (int(k[0]) << 8) | int(k[1]) + k = k[2:] + if len(k) < gLen { + return errServerKeyExchange + } + ka.g = new(big.Int).SetBytes(k[:gLen]) + k = k[gLen:] + + // Read dh_Ys + if len(k) < 2 { + return errServerKeyExchange + } + yLen := (int(k[0]) << 8) | int(k[1]) + k = k[2:] + if len(k) < yLen { + return errServerKeyExchange + } + ka.yTheirs = new(big.Int).SetBytes(k[:yLen]) + k = k[yLen:] + if ka.yTheirs.Sign() <= 0 || ka.yTheirs.Cmp(ka.p) >= 0 { + return errServerKeyExchange + } + + if l := config.Bugs.RequireDHPublicValueLen; l != 0 && l != yLen { + return fmt.Errorf("RequireDHPublicValueLen set to %d, but server's public value was %d bytes on the wire and %d bytes if minimal", l, yLen, (ka.yTheirs.BitLen()+7)/8) + } + + sig := k + serverDHParams := skx.key[:len(skx.key)-len(sig)] + + return ka.auth.verifyParameters(config, clientHello, serverHello, cert, serverDHParams, sig) +} + +func (ka *dheKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) { + if ka.p == nil || ka.g == nil || ka.yTheirs == nil { + return nil, nil, errors.New("missing ServerKeyExchange message") + } + + xOurs, err := rand.Int(config.rand(), ka.p) + if err != nil { + return nil, nil, err + } + preMasterSecret := new(big.Int).Exp(ka.yTheirs, xOurs, ka.p).Bytes() + + yOurs := new(big.Int).Exp(ka.g, xOurs, ka.p) + yBytes := yOurs.Bytes() + ckx := new(clientKeyExchangeMsg) + ckx.ciphertext = make([]byte, 2+len(yBytes)) + ckx.ciphertext[0] = byte(len(yBytes) >> 8) + ckx.ciphertext[1] = byte(len(yBytes)) + copy(ckx.ciphertext[2:], yBytes) + + return preMasterSecret, ckx, nil +} + +// nilKeyAgreement is a fake key agreement used to implement the plain PSK key +// exchange. +type nilKeyAgreement struct{} + +func (ka *nilKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) { + return nil, nil +} + +func (ka *nilKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) { + if len(ckx.ciphertext) != 0 { + return nil, errClientKeyExchange + } + + // Although in plain PSK, otherSecret is all zeros, the base key + // agreement does not access to the length of the pre-shared + // key. pskKeyAgreement instead interprets nil to mean to use all zeros + // of the appropriate length. + return nil, nil +} + +func (ka *nilKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error { + if len(skx.key) != 0 { + return errServerKeyExchange + } + return nil +} + +func (ka *nilKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) { + // Although in plain PSK, otherSecret is all zeros, the base key + // agreement does not access to the length of the pre-shared + // key. pskKeyAgreement instead interprets nil to mean to use all zeros + // of the appropriate length. + return nil, &clientKeyExchangeMsg{}, nil +} + +// makePSKPremaster formats a PSK pre-master secret based on otherSecret from +// the base key exchange and psk. +func makePSKPremaster(otherSecret, psk []byte) []byte { + out := make([]byte, 0, 2+len(otherSecret)+2+len(psk)) + out = append(out, byte(len(otherSecret)>>8), byte(len(otherSecret))) + out = append(out, otherSecret...) + out = append(out, byte(len(psk)>>8), byte(len(psk))) + out = append(out, psk...) + return out +} + +// pskKeyAgreement implements the PSK key agreement. +type pskKeyAgreement struct { + base keyAgreement + identityHint string +} + +func (ka *pskKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) { + // Assemble the identity hint. + bytes := make([]byte, 2+len(config.PreSharedKeyIdentity)) + bytes[0] = byte(len(config.PreSharedKeyIdentity) >> 8) + bytes[1] = byte(len(config.PreSharedKeyIdentity)) + copy(bytes[2:], []byte(config.PreSharedKeyIdentity)) + + // If there is one, append the base key agreement's + // ServerKeyExchange. + baseSkx, err := ka.base.generateServerKeyExchange(config, cert, clientHello, hello) + if err != nil { + return nil, err + } + + if baseSkx != nil { + bytes = append(bytes, baseSkx.key...) + } else if config.PreSharedKeyIdentity == "" { + // ServerKeyExchange is optional if the identity hint is empty + // and there would otherwise be no ServerKeyExchange. + return nil, nil + } + + skx := new(serverKeyExchangeMsg) + skx.key = bytes + return skx, nil +} + +func (ka *pskKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) { + // First, process the PSK identity. + if len(ckx.ciphertext) < 2 { + return nil, errClientKeyExchange + } + identityLen := (int(ckx.ciphertext[0]) << 8) | int(ckx.ciphertext[1]) + if 2+identityLen > len(ckx.ciphertext) { + return nil, errClientKeyExchange + } + identity := string(ckx.ciphertext[2 : 2+identityLen]) + + if identity != config.PreSharedKeyIdentity { + return nil, errors.New("tls: unexpected identity") + } + + if config.PreSharedKey == nil { + return nil, errors.New("tls: pre-shared key not configured") + } + + // Process the remainder of the ClientKeyExchange to compute the base + // pre-master secret. + newCkx := new(clientKeyExchangeMsg) + newCkx.ciphertext = ckx.ciphertext[2+identityLen:] + otherSecret, err := ka.base.processClientKeyExchange(config, cert, newCkx, version) + if err != nil { + return nil, err + } + + if otherSecret == nil { + // Special-case for the plain PSK key exchanges. + otherSecret = make([]byte, len(config.PreSharedKey)) + } + return makePSKPremaster(otherSecret, config.PreSharedKey), nil +} + +func (ka *pskKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error { + if len(skx.key) < 2 { + return errServerKeyExchange + } + identityLen := (int(skx.key[0]) << 8) | int(skx.key[1]) + if 2+identityLen > len(skx.key) { + return errServerKeyExchange + } + ka.identityHint = string(skx.key[2 : 2+identityLen]) + + // Process the remainder of the ServerKeyExchange. + newSkx := new(serverKeyExchangeMsg) + newSkx.key = skx.key[2+identityLen:] + return ka.base.processServerKeyExchange(config, clientHello, serverHello, cert, newSkx) +} + +func (ka *pskKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) { + // The server only sends an identity hint but, for purposes of + // test code, the server always sends the hint and it is + // required to match. + if ka.identityHint != config.PreSharedKeyIdentity { + return nil, nil, errors.New("tls: unexpected identity") + } + + // Serialize the identity. + bytes := make([]byte, 2+len(config.PreSharedKeyIdentity)) + bytes[0] = byte(len(config.PreSharedKeyIdentity) >> 8) + bytes[1] = byte(len(config.PreSharedKeyIdentity)) + copy(bytes[2:], []byte(config.PreSharedKeyIdentity)) + + // Append the base key exchange's ClientKeyExchange. + otherSecret, baseCkx, err := ka.base.generateClientKeyExchange(config, clientHello, cert) + if err != nil { + return nil, nil, err + } + ckx := new(clientKeyExchangeMsg) + ckx.ciphertext = append(bytes, baseCkx.ciphertext...) + + if config.PreSharedKey == nil { + return nil, nil, errors.New("tls: pre-shared key not configured") + } + if otherSecret == nil { + otherSecret = make([]byte, len(config.PreSharedKey)) + } + return makePSKPremaster(otherSecret, config.PreSharedKey), ckx, nil +} diff --git a/external/boringssl/ssl/test/runner/newhope/newhope.go b/external/boringssl/ssl/test/runner/newhope/newhope.go new file mode 100644 index 0000000000..8f7a530859 --- /dev/null +++ b/external/boringssl/ssl/test/runner/newhope/newhope.go @@ -0,0 +1,319 @@ +// Copyright (c) 2016, Google Inc. +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +// package newhope contains a post-quantum key agreement algorithm, +// reimplemented from the reference implementation at +// https://github.com/tpoeppelmann/newhope. +// +// Note that this package does not interoperate with the reference +// implementation. +package newhope + +import ( + "crypto/aes" + "crypto/cipher" + "errors" + "io" +) + +const ( + // q is the prime that defines the field. + q = 12289 + // n is the number of coefficients in polynomials. + n = 1024 + // k is the width of the noise distribution. + k = 16 + + // These values are used in the NTT calculation. See the paper for + // details about their origins. + omega = 49 + invOmega = 1254 + sqrtOmega = 7 + invSqrtOmega = 8778 + invN = 12277 + + // encodedPolyLen is the length, in bytes, of an encoded polynomial. The + // encoding uses 14 bits per coefficient. + encodedPolyLen = (n * 14) / 8 + + // offerMsgLen is the length, in bytes, of the offering (first) message of + // the key exchange. + OfferMsgLen = encodedPolyLen + 32 + + // acceptMsgLen is the length, in bytes, of the accepting (second) message + // of the key exchange. + AcceptMsgLen = encodedPolyLen + 256 +) + +// count16Bits returns the number of '1' bits in v. +func count16Bits(v uint16) (sum uint16) { + for i := 0; i < 16; i++ { + sum += v & 1 + v >>= 1 + } + + return sum +} + +// Poly is a polynomial of n coefficients. +type Poly [n]uint16 + +// Key is the result of a key agreement. +type Key [32]uint8 + +// sampleNoise returns a random polynomial where the coefficients are +// drawn from the noise distribution. +func sampleNoise(rand io.Reader) *Poly { + poly := new(Poly) + buf := make([]byte, 4) + + for i := range poly { + if _, err := io.ReadFull(rand, buf); err != nil { + panic(err) + } + a := count16Bits(uint16(buf[0])<<8 | uint16(buf[1])) + b := count16Bits(uint16(buf[2])<<8 | uint16(buf[3])) + poly[i] = (q + a - b) % q + } + + return poly +} + +// randomPolynomial returns a random polynomial where the coefficients are +// drawn uniformly at random from the underlying field. +func randomPolynomial(rand io.Reader) *Poly { + poly := new(Poly) + + buf := make([]byte, 2) + for i := range poly { + for { + if _, err := io.ReadFull(rand, buf); err != nil { + panic(err) + } + + v := uint16(buf[1])<<8 | uint16(buf[0]) + v &= 0x3fff + + if v < q { + poly[i] = v + break + } + } + } + + return poly +} + +type zeroReader struct { + io.Reader +} + +func (z *zeroReader) Read(dst []byte) (n int, err error) { + for i := range dst { + dst[i] = 0 + } + return len(dst), nil +} + +// seedToPolynomial uses AES-CTR to generate a pseudo-random polynomial given a +// 32-byte seed. +func seedToPolynomial(seed []byte) *Poly { + aes, err := aes.NewCipher(seed[0:16]) + if err != nil { + panic(err) + } + stream := cipher.NewCTR(aes, seed[16:32]) + reader := &cipher.StreamReader{S: stream, R: &zeroReader{}} + return randomPolynomial(reader) +} + +// forwardNTT converts |in| into the frequency domain. +func forwardNTT(in *Poly) *Poly { + return ntt(in, omega, sqrtOmega, 1, 1) +} + +// inverseNTT converts |in| into the time domain. +func inverseNTT(in *Poly) *Poly { + return ntt(in, invOmega, 1, invSqrtOmega, invN) +} + +// ntt performs the number-theoretic transform (a discrete Fourier transform in +// a field) on in. Significant magic is in effect here. See the paper for the +// details of how this works. +func ntt(in *Poly, omega, preScaleBase, postScaleBase, postScale uint16) *Poly { + out := new(Poly) + omega_to_the_i := uint64(1) + + for i := range out { + omegaToTheIJ := uint64(1) + preScale := uint64(1) + sum := uint64(0) + + for j := range in { + t := (uint64(in[j]) * preScale) % q + sum += (t * omegaToTheIJ) % q + omegaToTheIJ = (omegaToTheIJ * omega_to_the_i) % q + preScale = (uint64(preScaleBase) * preScale) % q + } + + out[i] = uint16((sum * uint64(postScale)) % q) + + omega_to_the_i = (omega_to_the_i * uint64(omega)) % q + postScale = uint16((uint64(postScale) * uint64(postScaleBase)) % q) + } + + return out +} + +// encodeRec encodes the reconciliation data compactly, for use in the accept +// message. +func encodeRec(rec *reconciliationData) []byte { + var ret [n / 4]byte + + for i := 0; i < n/4; i++ { + ret[i] = rec[4*i] | rec[4*i+1]<<2 | rec[4*i+2]<<4 | rec[4*i+3]<<6 + } + + return ret[:] +} + +// decodeRec decodes reconciliation data from the accept message. +func decodeRec(message []byte) (rec *reconciliationData) { + rec = new(reconciliationData) + + for i, b := range message { + rec[4*i] = b & 0x03 + rec[4*i+1] = (b >> 2) & 0x3 + rec[4*i+2] = (b >> 4) & 0x3 + rec[4*i+3] = b >> 6 + } + + return rec +} + +// encodePoly returns a byte array that encodes a polynomial compactly, with 14 +// bits per coefficient. +func encodePoly(poly *Poly) []byte { + ret := make([]byte, encodedPolyLen) + + for i := 0; i < n/4; i++ { + t0 := poly[4*i] + t1 := poly[4*i+1] + t2 := poly[4*i+2] + t3 := poly[4*i+3] + + ret[7*i] = byte(t0) + ret[7*i+1] = byte(t0>>8) | byte(t1<<6) + ret[7*i+2] = byte(t1 >> 2) + ret[7*i+3] = byte(t1>>10) | byte(t2<<4) + ret[7*i+4] = byte(t2 >> 4) + ret[7*i+5] = byte(t2>>12) | byte(t3<<2) + ret[7*i+6] = byte(t3 >> 6) + } + + return ret +} + +// decodePoly inverts encodePoly. +func decodePoly(encoded []byte) *Poly { + ret := new(Poly) + + for i := 0; i < n/4; i++ { + ret[4*i] = uint16(encoded[7*i]) | uint16(encoded[7*i+1]&0x3f)<<8 + ret[4*i+1] = uint16(encoded[7*i+1])>>6 | uint16(encoded[7*i+2])<<2 | uint16(encoded[7*i+3]&0x0f)<<10 + ret[4*i+2] = uint16(encoded[7*i+3])>>4 | uint16(encoded[7*i+4])<<4 | uint16(encoded[7*i+5]&0x03)<<12 + ret[4*i+3] = uint16(encoded[7*i+5])>>2 | uint16(encoded[7*i+6])<<6 + } + + return ret +} + +// Offer starts a new key exchange. It returns a message that should be +// transmitted to the peer, and a polynomial that must be retained in order to +// complete the exchange. +func Offer(rand io.Reader) (offerMsg []byte, sFreq *Poly) { + seed := make([]byte, 32) + + if _, err := io.ReadFull(rand, seed); err != nil { + panic(err) + } + + aFreq := seedToPolynomial(seed) + sFreq = forwardNTT(sampleNoise(rand)) + eFreq := forwardNTT(sampleNoise(rand)) + + bFreq := new(Poly) + for i := range bFreq { + bFreq[i] = uint16((uint64(sFreq[i])*uint64(aFreq[i]) + uint64(eFreq[i])) % q) + } + + offerMsg = encodePoly(bFreq) + offerMsg = append(offerMsg, seed[:]...) + return offerMsg, sFreq +} + +// Accept processes a message generated by |Offer| and returns a reply message +// and the shared key. +func Accept(rand io.Reader, offerMsg []byte) (sharedKey Key, acceptMsg []byte, err error) { + if len(offerMsg) != OfferMsgLen { + return sharedKey, nil, errors.New("newhope: offer message has incorrect length") + } + + bFreq := decodePoly(offerMsg) + seed := offerMsg[encodedPolyLen:] + + aFreq := seedToPolynomial(seed) + sPrimeFreq := forwardNTT(sampleNoise(rand)) + ePrimeFreq := forwardNTT(sampleNoise(rand)) + + uFreq := new(Poly) + for i := range uFreq { + uFreq[i] = uint16((uint64(sPrimeFreq[i])*uint64(aFreq[i]) + uint64(ePrimeFreq[i])) % q) + } + + vFreq := new(Poly) + for i := range vFreq { + vFreq[i] = uint16((uint64(sPrimeFreq[i]) * uint64(bFreq[i])) % q) + } + + v := inverseNTT(vFreq) + ePrimePrime := sampleNoise(rand) + for i := range v { + v[i] = uint16((uint64(v[i]) + uint64(ePrimePrime[i])) % q) + } + + rec := helprec(rand, v) + + sharedKey = reconcile(v, rec) + acceptMsg = encodePoly(uFreq) + acceptMsg = append(acceptMsg, encodeRec(rec)[:]...) + return sharedKey, acceptMsg, nil +} + +// Finish processes the reply from the peer and returns the shared key. +func (sk *Poly) Finish(acceptMsg []byte) (sharedKey Key, err error) { + if len(acceptMsg) != AcceptMsgLen { + return sharedKey, errors.New("newhope: accept message has incorrect length") + } + + uFreq := decodePoly(acceptMsg[:encodedPolyLen]) + rec := decodeRec(acceptMsg[encodedPolyLen:]) + + for i, u := range uFreq { + uFreq[i] = uint16((uint64(u) * uint64(sk[i])) % q) + } + u := inverseNTT(uFreq) + + return reconcile(u, rec), nil +} diff --git a/external/boringssl/ssl/test/runner/newhope/newhope_test.go b/external/boringssl/ssl/test/runner/newhope/newhope_test.go new file mode 100644 index 0000000000..31e95c7e57 --- /dev/null +++ b/external/boringssl/ssl/test/runner/newhope/newhope_test.go @@ -0,0 +1,154 @@ +// Copyright (c) 2016, Google Inc. +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +package newhope + +import ( + "bytes" + "crypto/rand" + "fmt" + "io" + "io/ioutil" + "testing" +) + +func TestNTTRoundTrip(t *testing.T) { + var a Poly + for i := range a { + a[i] = uint16(i) + } + + frequency := forwardNTT(&a) + original := inverseNTT(frequency) + + for i, v := range a { + if v != original[i] { + t.Errorf("NTT didn't invert correctly: original[%d] = %d", i, original[i]) + break + } + } +} + +func TestNTTInv(t *testing.T) { + var a Poly + for i := range a { + a[i] = uint16(i) + } + + result := ntt(&a, invOmega, 1, invSqrtOmega, invN) + if result[0] != 6656 || result[1] != 1792 || result[2] != 1234 { + t.Errorf("NTT^-1 gave bad result: %v", result[:8]) + } +} + +func disabledTestNoise(t *testing.T) { + var buckets [1 + 2*k]int + numSamples := 100 + + for i := 0; i < numSamples; i++ { + noise := sampleNoise(rand.Reader) + for _, v := range noise { + value := (int(v) + k) % q + buckets[value]++ + } + } + + sum := 0 + squareSum := 0 + + for i, count := range buckets { + sum += (i - k) * count + squareSum += (i - k) * (i - k) * count + } + + mean := float64(sum) / float64(n*numSamples) + if mean < -0.5 || 0.5 < mean { + t.Errorf("mean out of range: %f", mean) + } + + expectedVariance := 0.5 * 0.5 * float64(k*2) // I think? + variance := float64(squareSum)/float64(n*numSamples) - mean*mean + + if variance < expectedVariance-1.0 || expectedVariance+1.0 < variance { + t.Errorf("variance out of range: got %f, want %f", variance, expectedVariance) + } + + file, err := ioutil.TempFile("", "noise") + fmt.Printf("writing noise to %s\n", file.Name()) + if err != nil { + t.Fatal(err) + } + for i, count := range buckets { + dots := "" + for i := 0; i < count/(3*numSamples); i++ { + dots += "++" + } + fmt.Fprintf(file, "%+d\t%d\t%s\n", i-k, count, dots) + } + file.Close() +} + +func TestSeedToPolynomial(t *testing.T) { + seed := make([]byte, 32) + seed[0] = 1 + seed[31] = 2 + + poly := seedToPolynomial(seed) + if poly[0] != 3313 || poly[1] != 9277 || poly[2] != 11020 { + t.Errorf("bad result: %v", poly[:3]) + } +} + +func TestEncodeDecodePoly(t *testing.T) { + poly := randomPolynomial(rand.Reader) + poly2 := decodePoly(encodePoly(poly)) + if *poly != *poly2 { + t.Errorf("decodePoly(encodePoly) isn't the identity function") + } +} + +func TestEncodeDecodeRec(t *testing.T) { + var r reconciliationData + if _, err := io.ReadFull(rand.Reader, r[:]); err != nil { + panic(err) + } + for i := range r { + r[i] &= 3 + } + + encoded := encodeRec(&r) + decoded := decodeRec(encoded) + + if *decoded != r { + t.Errorf("bad decode of rec") + } +} + +func TestExchange(t *testing.T) { + for count := 0; count < 64; count++ { + offerMsg, state := Offer(rand.Reader) + sharedKey1, acceptMsg, err := Accept(rand.Reader, offerMsg) + if err != nil { + t.Errorf("Accept: %v", err) + } + sharedKey2, err := state.Finish(acceptMsg) + if err != nil { + t.Fatal("Finish: %v", err) + } + + if !bytes.Equal(sharedKey1[:], sharedKey2[:]) { + t.Fatalf("keys mismatched on iteration %d: %x vs %x", count, sharedKey1, sharedKey2) + } + } +} diff --git a/external/boringssl/ssl/test/runner/newhope/reconciliation.go b/external/boringssl/ssl/test/runner/newhope/reconciliation.go new file mode 100644 index 0000000000..07479fe788 --- /dev/null +++ b/external/boringssl/ssl/test/runner/newhope/reconciliation.go @@ -0,0 +1,132 @@ +// Copyright (c) 2016, Google Inc. +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +package newhope + +// This file contains the reconciliation algorithm for NewHope. This is simply a +// monkey-see-monkey-do version of the reference code, with the exception that +// the key resulting from reconciliation is whitened with SHA2 rather than SHA3. +// +// Thanks to the authors of the reference code for allowing us to release this +// under the BoringSSL license. + +import ( + "crypto/sha256" + "io" +) + +func abs(v int32) int32 { + mask := v >> 31 + return (v ^ mask) - mask +} + +func f(x int32) (v0, v1, k int32) { + // Next 6 lines compute t = x/q; + b := x * 2730 + t := b >> 25 + b = x - t*12289 + b = 12288 - b + b >>= 31 + t -= b + + r := t & 1 + xit := (t >> 1) + v0 = xit + r // v0 = round(x/(2*q)) + + t -= 1 + r = t & 1 + v1 = (t >> 1) + r + + k = abs(x - (v0 * 2 * q)) + return +} + +// reconciliationData is the data needed for reconciliation. There are 2 bits +// per coefficient; this is the unpacked form. +type reconciliationData [n]uint8 + +func helprec(rand io.Reader, v *Poly) *reconciliationData { + var randBits [n / (4 * 8)]byte + if _, err := io.ReadFull(rand, randBits[:]); err != nil { + panic(err) + } + + ret := new(reconciliationData) + + for i := uint(0); i < n/4; i++ { + rbit := int32((randBits[i>>3] >> (i & 7)) & 1) + + a0, b0, k0 := f(8*int32(v[i]) + 4*rbit) + a1, b1, k1 := f(8*int32(v[256+i]) + 4*rbit) + a2, b2, k2 := f(8*int32(v[512+i]) + 4*rbit) + a3, b3, k3 := f(8*int32(v[768+i]) + 4*rbit) + + k := (2*q - 1 - (k0 + k1 + k2 + k3)) >> 31 + + v0 := ((^k) & a0) ^ (k & b0) + v1 := ((^k) & a1) ^ (k & b1) + v2 := ((^k) & a2) ^ (k & b2) + v3 := ((^k) & a3) ^ (k & b3) + + ret[i] = uint8((v0 - v3) & 3) + ret[i+256] = uint8((v1 - v3) & 3) + ret[i+512] = uint8((v2 - v3) & 3) + ret[i+768] = uint8((-k + 2*v3) & 3) + } + + return ret +} + +func g(x int32) int32 { + // Next 6 lines compute t = x/(4*q); + b := x * 2730 + t := b >> 27 + b = x - t*49156 + b = 49155 - b + b >>= 31 + t -= b + + c := t & 1 + t = (t >> 1) + c // t = round(x/(8*q)) + + t *= 8 * q + + return abs(t - x) +} + +func ldDecode(xi0, xi1, xi2, xi3 int32) uint8 { + t := g(xi0) + t += g(xi1) + t += g(xi2) + t += g(xi3) + + t -= 8 * q + t >>= 31 + return uint8(t & 1) +} + +func reconcile(v *Poly, reconciliation *reconciliationData) Key { + key := new(Key) + + for i := uint(0); i < n/4; i++ { + t0 := 16*q + 8*int32(v[i]) - q*(2*int32(reconciliation[i])+int32(reconciliation[i+768])) + t1 := 16*q + 8*int32(v[i+256]) - q*(2*int32(reconciliation[256+i])+int32(reconciliation[i+768])) + t2 := 16*q + 8*int32(v[i+512]) - q*(2*int32(reconciliation[512+i])+int32(reconciliation[i+768])) + t3 := 16*q + 8*int32(v[i+768]) - q*int32(reconciliation[i+768]) + + key[i>>3] |= ldDecode(t0, t1, t2, t3) << (i & 7) + } + + return sha256.Sum256(key[:]) +} diff --git a/external/boringssl/ssl/test/runner/packet_adapter.go b/external/boringssl/ssl/test/runner/packet_adapter.go new file mode 100644 index 0000000000..a8da311bb1 --- /dev/null +++ b/external/boringssl/ssl/test/runner/packet_adapter.go @@ -0,0 +1,179 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package runner + +import ( + "encoding/binary" + "fmt" + "io" + "net" + "time" +) + +// opcodePacket signals a packet, encoded with a 32-bit length prefix, followed +// by the payload. +const opcodePacket = byte('P') + +// opcodeTimeout signals a read timeout, encoded by a 64-bit number of +// nanoseconds. On receipt, the peer should reply with +// opcodeTimeoutAck. opcodeTimeout may only be sent by the Go side. +const opcodeTimeout = byte('T') + +// opcodeTimeoutAck acknowledges a read timeout. This opcode has no payload and +// may only be sent by the C side. Timeout ACKs act as a synchronization point +// at the timeout, to bracket one flight of messages from C. +const opcodeTimeoutAck = byte('t') + +type packetAdaptor struct { + net.Conn + debug *recordingConn +} + +// newPacketAdaptor wraps a reliable streaming net.Conn into a reliable +// packet-based net.Conn. The stream contains packets and control commands, +// distinguished by a one byte opcode. +func newPacketAdaptor(conn net.Conn) *packetAdaptor { + return &packetAdaptor{conn, nil} +} + +func (p *packetAdaptor) log(message string, data []byte) { + if p.debug == nil { + return + } + + p.debug.LogSpecial(message, data) +} + +func (p *packetAdaptor) readOpcode() (byte, error) { + out := make([]byte, 1) + if _, err := io.ReadFull(p.Conn, out); err != nil { + return 0, err + } + return out[0], nil +} + +func (p *packetAdaptor) readPacketBody() ([]byte, error) { + var length uint32 + if err := binary.Read(p.Conn, binary.BigEndian, &length); err != nil { + return nil, err + } + out := make([]byte, length) + if _, err := io.ReadFull(p.Conn, out); err != nil { + return nil, err + } + return out, nil +} + +func (p *packetAdaptor) Read(b []byte) (int, error) { + opcode, err := p.readOpcode() + if err != nil { + return 0, err + } + if opcode != opcodePacket { + return 0, fmt.Errorf("unexpected opcode '%d'", opcode) + } + out, err := p.readPacketBody() + if err != nil { + return 0, err + } + return copy(b, out), nil +} + +func (p *packetAdaptor) Write(b []byte) (int, error) { + payload := make([]byte, 1+4+len(b)) + payload[0] = opcodePacket + binary.BigEndian.PutUint32(payload[1:5], uint32(len(b))) + copy(payload[5:], b) + if _, err := p.Conn.Write(payload); err != nil { + return 0, err + } + return len(b), nil +} + +// SendReadTimeout instructs the peer to simulate a read timeout. It then waits +// for acknowledgement of the timeout, buffering any packets received since +// then. The packets are then returned. +func (p *packetAdaptor) SendReadTimeout(d time.Duration) ([][]byte, error) { + p.log("Simulating read timeout: "+d.String(), nil) + + payload := make([]byte, 1+8) + payload[0] = opcodeTimeout + binary.BigEndian.PutUint64(payload[1:], uint64(d.Nanoseconds())) + if _, err := p.Conn.Write(payload); err != nil { + return nil, err + } + + var packets [][]byte + for { + opcode, err := p.readOpcode() + if err != nil { + return nil, err + } + switch opcode { + case opcodeTimeoutAck: + p.log("Received timeout ACK", nil) + // Done! Return the packets buffered and continue. + return packets, nil + case opcodePacket: + // Buffer the packet for the caller to process. + packet, err := p.readPacketBody() + if err != nil { + return nil, err + } + p.log("Simulating dropped packet", packet) + packets = append(packets, packet) + default: + return nil, fmt.Errorf("unexpected opcode '%d'", opcode) + } + } +} + +type replayAdaptor struct { + net.Conn + prevWrite []byte +} + +// newReplayAdaptor wraps a packeted net.Conn. It transforms it into +// one which, after writing a packet, always replays the previous +// write. +func newReplayAdaptor(conn net.Conn) net.Conn { + return &replayAdaptor{Conn: conn} +} + +func (r *replayAdaptor) Write(b []byte) (int, error) { + n, err := r.Conn.Write(b) + + // Replay the previous packet and save the current one to + // replay next. + if r.prevWrite != nil { + r.Conn.Write(r.prevWrite) + } + r.prevWrite = append(r.prevWrite[:0], b...) + + return n, err +} + +type damageAdaptor struct { + net.Conn + damage bool +} + +// newDamageAdaptor wraps a packeted net.Conn. It transforms it into one which +// optionally damages the final byte of every Write() call. +func newDamageAdaptor(conn net.Conn) *damageAdaptor { + return &damageAdaptor{Conn: conn} +} + +func (d *damageAdaptor) setDamage(damage bool) { + d.damage = damage +} + +func (d *damageAdaptor) Write(b []byte) (int, error) { + if d.damage && len(b) > 0 { + b = append([]byte{}, b...) + b[len(b)-1]++ + } + return d.Conn.Write(b) +} diff --git a/external/boringssl/ssl/test/runner/poly1305/const_amd64.s b/external/boringssl/ssl/test/runner/poly1305/const_amd64.s new file mode 100644 index 0000000000..8e861f337c --- /dev/null +++ b/external/boringssl/ssl/test/runner/poly1305/const_amd64.s @@ -0,0 +1,45 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This code was translated into a form compatible with 6a from the public +// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html + +// +build amd64,!gccgo,!appengine + +DATA ·SCALE(SB)/8, $0x37F4000000000000 +GLOBL ·SCALE(SB), 8, $8 +DATA ·TWO32(SB)/8, $0x41F0000000000000 +GLOBL ·TWO32(SB), 8, $8 +DATA ·TWO64(SB)/8, $0x43F0000000000000 +GLOBL ·TWO64(SB), 8, $8 +DATA ·TWO96(SB)/8, $0x45F0000000000000 +GLOBL ·TWO96(SB), 8, $8 +DATA ·ALPHA32(SB)/8, $0x45E8000000000000 +GLOBL ·ALPHA32(SB), 8, $8 +DATA ·ALPHA64(SB)/8, $0x47E8000000000000 +GLOBL ·ALPHA64(SB), 8, $8 +DATA ·ALPHA96(SB)/8, $0x49E8000000000000 +GLOBL ·ALPHA96(SB), 8, $8 +DATA ·ALPHA130(SB)/8, $0x4C08000000000000 +GLOBL ·ALPHA130(SB), 8, $8 +DATA ·DOFFSET0(SB)/8, $0x4330000000000000 +GLOBL ·DOFFSET0(SB), 8, $8 +DATA ·DOFFSET1(SB)/8, $0x4530000000000000 +GLOBL ·DOFFSET1(SB), 8, $8 +DATA ·DOFFSET2(SB)/8, $0x4730000000000000 +GLOBL ·DOFFSET2(SB), 8, $8 +DATA ·DOFFSET3(SB)/8, $0x4930000000000000 +GLOBL ·DOFFSET3(SB), 8, $8 +DATA ·DOFFSET3MINUSTWO128(SB)/8, $0x492FFFFE00000000 +GLOBL ·DOFFSET3MINUSTWO128(SB), 8, $8 +DATA ·HOFFSET0(SB)/8, $0x43300001FFFFFFFB +GLOBL ·HOFFSET0(SB), 8, $8 +DATA ·HOFFSET1(SB)/8, $0x45300001FFFFFFFE +GLOBL ·HOFFSET1(SB), 8, $8 +DATA ·HOFFSET2(SB)/8, $0x47300001FFFFFFFE +GLOBL ·HOFFSET2(SB), 8, $8 +DATA ·HOFFSET3(SB)/8, $0x49300003FFFFFFFE +GLOBL ·HOFFSET3(SB), 8, $8 +DATA ·ROUNDING(SB)/2, $0x137f +GLOBL ·ROUNDING(SB), 8, $2 diff --git a/external/boringssl/ssl/test/runner/poly1305/poly1305.go b/external/boringssl/ssl/test/runner/poly1305/poly1305.go new file mode 100644 index 0000000000..4a5f826f7a --- /dev/null +++ b/external/boringssl/ssl/test/runner/poly1305/poly1305.go @@ -0,0 +1,32 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* +Package poly1305 implements Poly1305 one-time message authentication code as specified in http://cr.yp.to/mac/poly1305-20050329.pdf. + +Poly1305 is a fast, one-time authentication function. It is infeasible for an +attacker to generate an authenticator for a message without the key. However, a +key must only be used for a single message. Authenticating two different +messages with the same key allows an attacker to forge authenticators for other +messages with the same key. + +Poly1305 was originally coupled with AES in order to make Poly1305-AES. AES was +used with a fixed key in order to generate one-time keys from an nonce. +However, in this package AES isn't used and the one-time key is specified +directly. +*/ +package poly1305 // import "golang.org/x/crypto/poly1305" + +import "crypto/subtle" + +// TagSize is the size, in bytes, of a poly1305 authenticator. +const TagSize = 16 + +// Verify returns true if mac is a valid authenticator for m with the given +// key. +func Verify(mac *[16]byte, m []byte, key *[32]byte) bool { + var tmp [16]byte + Sum(&tmp, m, key) + return subtle.ConstantTimeCompare(tmp[:], mac[:]) == 1 +} diff --git a/external/boringssl/ssl/test/runner/poly1305/poly1305_amd64.s b/external/boringssl/ssl/test/runner/poly1305/poly1305_amd64.s new file mode 100644 index 0000000000..f8d4ee9289 --- /dev/null +++ b/external/boringssl/ssl/test/runner/poly1305/poly1305_amd64.s @@ -0,0 +1,497 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This code was translated into a form compatible with 6a from the public +// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html + +// +build amd64,!gccgo,!appengine + +// func poly1305(out *[16]byte, m *byte, mlen uint64, key *[32]key) +TEXT ·poly1305(SB),0,$224-32 + MOVQ out+0(FP),DI + MOVQ m+8(FP),SI + MOVQ mlen+16(FP),DX + MOVQ key+24(FP),CX + + MOVQ SP,R11 + MOVQ $31,R9 + NOTQ R9 + ANDQ R9,SP + ADDQ $32,SP + + MOVQ R11,32(SP) + MOVQ R12,40(SP) + MOVQ R13,48(SP) + MOVQ R14,56(SP) + MOVQ R15,64(SP) + MOVQ BX,72(SP) + MOVQ BP,80(SP) + FLDCW ·ROUNDING(SB) + MOVL 0(CX),R8 + MOVL 4(CX),R9 + MOVL 8(CX),AX + MOVL 12(CX),R10 + MOVQ DI,88(SP) + MOVQ CX,96(SP) + MOVL $0X43300000,108(SP) + MOVL $0X45300000,116(SP) + MOVL $0X47300000,124(SP) + MOVL $0X49300000,132(SP) + ANDL $0X0FFFFFFF,R8 + ANDL $0X0FFFFFFC,R9 + ANDL $0X0FFFFFFC,AX + ANDL $0X0FFFFFFC,R10 + MOVL R8,104(SP) + MOVL R9,112(SP) + MOVL AX,120(SP) + MOVL R10,128(SP) + FMOVD 104(SP), F0 + FSUBD ·DOFFSET0(SB), F0 + FMOVD 112(SP), F0 + FSUBD ·DOFFSET1(SB), F0 + FMOVD 120(SP), F0 + FSUBD ·DOFFSET2(SB), F0 + FMOVD 128(SP), F0 + FSUBD ·DOFFSET3(SB), F0 + FXCHD F0, F3 + FMOVDP F0, 136(SP) + FXCHD F0, F1 + FMOVD F0, 144(SP) + FMULD ·SCALE(SB), F0 + FMOVDP F0, 152(SP) + FMOVD F0, 160(SP) + FMULD ·SCALE(SB), F0 + FMOVDP F0, 168(SP) + FMOVD F0, 176(SP) + FMULD ·SCALE(SB), F0 + FMOVDP F0, 184(SP) + FLDZ + FLDZ + FLDZ + FLDZ + CMPQ DX,$16 + JB ADDATMOST15BYTES + INITIALATLEAST16BYTES: + MOVL 12(SI),DI + MOVL 8(SI),CX + MOVL 4(SI),R8 + MOVL 0(SI),R9 + MOVL DI,128(SP) + MOVL CX,120(SP) + MOVL R8,112(SP) + MOVL R9,104(SP) + ADDQ $16,SI + SUBQ $16,DX + FXCHD F0, F3 + FADDD 128(SP), F0 + FSUBD ·DOFFSET3MINUSTWO128(SB), F0 + FXCHD F0, F1 + FADDD 112(SP), F0 + FSUBD ·DOFFSET1(SB), F0 + FXCHD F0, F2 + FADDD 120(SP), F0 + FSUBD ·DOFFSET2(SB), F0 + FXCHD F0, F3 + FADDD 104(SP), F0 + FSUBD ·DOFFSET0(SB), F0 + CMPQ DX,$16 + JB MULTIPLYADDATMOST15BYTES + MULTIPLYADDATLEAST16BYTES: + MOVL 12(SI),DI + MOVL 8(SI),CX + MOVL 4(SI),R8 + MOVL 0(SI),R9 + MOVL DI,128(SP) + MOVL CX,120(SP) + MOVL R8,112(SP) + MOVL R9,104(SP) + ADDQ $16,SI + SUBQ $16,DX + FMOVD ·ALPHA130(SB), F0 + FADDD F2,F0 + FSUBD ·ALPHA130(SB), F0 + FSUBD F0,F2 + FMULD ·SCALE(SB), F0 + FMOVD ·ALPHA32(SB), F0 + FADDD F2,F0 + FSUBD ·ALPHA32(SB), F0 + FSUBD F0,F2 + FXCHD F0, F2 + FADDDP F0,F1 + FMOVD ·ALPHA64(SB), F0 + FADDD F4,F0 + FSUBD ·ALPHA64(SB), F0 + FSUBD F0,F4 + FMOVD ·ALPHA96(SB), F0 + FADDD F6,F0 + FSUBD ·ALPHA96(SB), F0 + FSUBD F0,F6 + FXCHD F0, F6 + FADDDP F0,F1 + FXCHD F0, F3 + FADDDP F0,F5 + FXCHD F0, F3 + FADDDP F0,F1 + FMOVD 176(SP), F0 + FMULD F3,F0 + FMOVD 160(SP), F0 + FMULD F4,F0 + FMOVD 144(SP), F0 + FMULD F5,F0 + FMOVD 136(SP), F0 + FMULDP F0,F6 + FMOVD 160(SP), F0 + FMULD F4,F0 + FADDDP F0,F3 + FMOVD 144(SP), F0 + FMULD F4,F0 + FADDDP F0,F2 + FMOVD 136(SP), F0 + FMULD F4,F0 + FADDDP F0,F1 + FMOVD 184(SP), F0 + FMULDP F0,F4 + FXCHD F0, F3 + FADDDP F0,F5 + FMOVD 144(SP), F0 + FMULD F4,F0 + FADDDP F0,F2 + FMOVD 136(SP), F0 + FMULD F4,F0 + FADDDP F0,F1 + FMOVD 184(SP), F0 + FMULD F4,F0 + FADDDP F0,F3 + FMOVD 168(SP), F0 + FMULDP F0,F4 + FXCHD F0, F3 + FADDDP F0,F4 + FMOVD 136(SP), F0 + FMULD F5,F0 + FADDDP F0,F1 + FXCHD F0, F3 + FMOVD 184(SP), F0 + FMULD F5,F0 + FADDDP F0,F3 + FXCHD F0, F1 + FMOVD 168(SP), F0 + FMULD F5,F0 + FADDDP F0,F1 + FMOVD 152(SP), F0 + FMULDP F0,F5 + FXCHD F0, F4 + FADDDP F0,F1 + CMPQ DX,$16 + FXCHD F0, F2 + FMOVD 128(SP), F0 + FSUBD ·DOFFSET3MINUSTWO128(SB), F0 + FADDDP F0,F1 + FXCHD F0, F1 + FMOVD 120(SP), F0 + FSUBD ·DOFFSET2(SB), F0 + FADDDP F0,F1 + FXCHD F0, F3 + FMOVD 112(SP), F0 + FSUBD ·DOFFSET1(SB), F0 + FADDDP F0,F1 + FXCHD F0, F2 + FMOVD 104(SP), F0 + FSUBD ·DOFFSET0(SB), F0 + FADDDP F0,F1 + JAE MULTIPLYADDATLEAST16BYTES + MULTIPLYADDATMOST15BYTES: + FMOVD ·ALPHA130(SB), F0 + FADDD F2,F0 + FSUBD ·ALPHA130(SB), F0 + FSUBD F0,F2 + FMULD ·SCALE(SB), F0 + FMOVD ·ALPHA32(SB), F0 + FADDD F2,F0 + FSUBD ·ALPHA32(SB), F0 + FSUBD F0,F2 + FMOVD ·ALPHA64(SB), F0 + FADDD F5,F0 + FSUBD ·ALPHA64(SB), F0 + FSUBD F0,F5 + FMOVD ·ALPHA96(SB), F0 + FADDD F7,F0 + FSUBD ·ALPHA96(SB), F0 + FSUBD F0,F7 + FXCHD F0, F7 + FADDDP F0,F1 + FXCHD F0, F5 + FADDDP F0,F1 + FXCHD F0, F3 + FADDDP F0,F5 + FADDDP F0,F1 + FMOVD 176(SP), F0 + FMULD F1,F0 + FMOVD 160(SP), F0 + FMULD F2,F0 + FMOVD 144(SP), F0 + FMULD F3,F0 + FMOVD 136(SP), F0 + FMULDP F0,F4 + FMOVD 160(SP), F0 + FMULD F5,F0 + FADDDP F0,F3 + FMOVD 144(SP), F0 + FMULD F5,F0 + FADDDP F0,F2 + FMOVD 136(SP), F0 + FMULD F5,F0 + FADDDP F0,F1 + FMOVD 184(SP), F0 + FMULDP F0,F5 + FXCHD F0, F4 + FADDDP F0,F3 + FMOVD 144(SP), F0 + FMULD F5,F0 + FADDDP F0,F2 + FMOVD 136(SP), F0 + FMULD F5,F0 + FADDDP F0,F1 + FMOVD 184(SP), F0 + FMULD F5,F0 + FADDDP F0,F4 + FMOVD 168(SP), F0 + FMULDP F0,F5 + FXCHD F0, F4 + FADDDP F0,F2 + FMOVD 136(SP), F0 + FMULD F5,F0 + FADDDP F0,F1 + FMOVD 184(SP), F0 + FMULD F5,F0 + FADDDP F0,F4 + FMOVD 168(SP), F0 + FMULD F5,F0 + FADDDP F0,F3 + FMOVD 152(SP), F0 + FMULDP F0,F5 + FXCHD F0, F4 + FADDDP F0,F1 + ADDATMOST15BYTES: + CMPQ DX,$0 + JE NOMOREBYTES + MOVL $0,0(SP) + MOVL $0, 4 (SP) + MOVL $0, 8 (SP) + MOVL $0, 12 (SP) + LEAQ 0(SP),DI + MOVQ DX,CX + REP; MOVSB + MOVB $1,0(DI) + MOVL 12 (SP),DI + MOVL 8 (SP),SI + MOVL 4 (SP),DX + MOVL 0(SP),CX + MOVL DI,128(SP) + MOVL SI,120(SP) + MOVL DX,112(SP) + MOVL CX,104(SP) + FXCHD F0, F3 + FADDD 128(SP), F0 + FSUBD ·DOFFSET3(SB), F0 + FXCHD F0, F2 + FADDD 120(SP), F0 + FSUBD ·DOFFSET2(SB), F0 + FXCHD F0, F1 + FADDD 112(SP), F0 + FSUBD ·DOFFSET1(SB), F0 + FXCHD F0, F3 + FADDD 104(SP), F0 + FSUBD ·DOFFSET0(SB), F0 + FMOVD ·ALPHA130(SB), F0 + FADDD F3,F0 + FSUBD ·ALPHA130(SB), F0 + FSUBD F0,F3 + FMULD ·SCALE(SB), F0 + FMOVD ·ALPHA32(SB), F0 + FADDD F2,F0 + FSUBD ·ALPHA32(SB), F0 + FSUBD F0,F2 + FMOVD ·ALPHA64(SB), F0 + FADDD F6,F0 + FSUBD ·ALPHA64(SB), F0 + FSUBD F0,F6 + FMOVD ·ALPHA96(SB), F0 + FADDD F5,F0 + FSUBD ·ALPHA96(SB), F0 + FSUBD F0,F5 + FXCHD F0, F4 + FADDDP F0,F3 + FXCHD F0, F6 + FADDDP F0,F1 + FXCHD F0, F3 + FADDDP F0,F5 + FXCHD F0, F3 + FADDDP F0,F1 + FMOVD 176(SP), F0 + FMULD F3,F0 + FMOVD 160(SP), F0 + FMULD F4,F0 + FMOVD 144(SP), F0 + FMULD F5,F0 + FMOVD 136(SP), F0 + FMULDP F0,F6 + FMOVD 160(SP), F0 + FMULD F5,F0 + FADDDP F0,F3 + FMOVD 144(SP), F0 + FMULD F5,F0 + FADDDP F0,F2 + FMOVD 136(SP), F0 + FMULD F5,F0 + FADDDP F0,F1 + FMOVD 184(SP), F0 + FMULDP F0,F5 + FXCHD F0, F4 + FADDDP F0,F5 + FMOVD 144(SP), F0 + FMULD F6,F0 + FADDDP F0,F2 + FMOVD 136(SP), F0 + FMULD F6,F0 + FADDDP F0,F1 + FMOVD 184(SP), F0 + FMULD F6,F0 + FADDDP F0,F4 + FMOVD 168(SP), F0 + FMULDP F0,F6 + FXCHD F0, F5 + FADDDP F0,F4 + FMOVD 136(SP), F0 + FMULD F2,F0 + FADDDP F0,F1 + FMOVD 184(SP), F0 + FMULD F2,F0 + FADDDP F0,F5 + FMOVD 168(SP), F0 + FMULD F2,F0 + FADDDP F0,F3 + FMOVD 152(SP), F0 + FMULDP F0,F2 + FXCHD F0, F1 + FADDDP F0,F3 + FXCHD F0, F3 + FXCHD F0, F2 + NOMOREBYTES: + MOVL $0,R10 + FMOVD ·ALPHA130(SB), F0 + FADDD F4,F0 + FSUBD ·ALPHA130(SB), F0 + FSUBD F0,F4 + FMULD ·SCALE(SB), F0 + FMOVD ·ALPHA32(SB), F0 + FADDD F2,F0 + FSUBD ·ALPHA32(SB), F0 + FSUBD F0,F2 + FMOVD ·ALPHA64(SB), F0 + FADDD F4,F0 + FSUBD ·ALPHA64(SB), F0 + FSUBD F0,F4 + FMOVD ·ALPHA96(SB), F0 + FADDD F6,F0 + FSUBD ·ALPHA96(SB), F0 + FXCHD F0, F6 + FSUBD F6,F0 + FXCHD F0, F4 + FADDDP F0,F3 + FXCHD F0, F4 + FADDDP F0,F1 + FXCHD F0, F2 + FADDDP F0,F3 + FXCHD F0, F4 + FADDDP F0,F3 + FXCHD F0, F3 + FADDD ·HOFFSET0(SB), F0 + FXCHD F0, F3 + FADDD ·HOFFSET1(SB), F0 + FXCHD F0, F1 + FADDD ·HOFFSET2(SB), F0 + FXCHD F0, F2 + FADDD ·HOFFSET3(SB), F0 + FXCHD F0, F3 + FMOVDP F0, 104(SP) + FMOVDP F0, 112(SP) + FMOVDP F0, 120(SP) + FMOVDP F0, 128(SP) + MOVL 108(SP),DI + ANDL $63,DI + MOVL 116(SP),SI + ANDL $63,SI + MOVL 124(SP),DX + ANDL $63,DX + MOVL 132(SP),CX + ANDL $63,CX + MOVL 112(SP),R8 + ADDL DI,R8 + MOVQ R8,112(SP) + MOVL 120(SP),DI + ADCL SI,DI + MOVQ DI,120(SP) + MOVL 128(SP),DI + ADCL DX,DI + MOVQ DI,128(SP) + MOVL R10,DI + ADCL CX,DI + MOVQ DI,136(SP) + MOVQ $5,DI + MOVL 104(SP),SI + ADDL SI,DI + MOVQ DI,104(SP) + MOVL R10,DI + MOVQ 112(SP),DX + ADCL DX,DI + MOVQ DI,112(SP) + MOVL R10,DI + MOVQ 120(SP),CX + ADCL CX,DI + MOVQ DI,120(SP) + MOVL R10,DI + MOVQ 128(SP),R8 + ADCL R8,DI + MOVQ DI,128(SP) + MOVQ $0XFFFFFFFC,DI + MOVQ 136(SP),R9 + ADCL R9,DI + SARL $16,DI + MOVQ DI,R9 + XORL $0XFFFFFFFF,R9 + ANDQ DI,SI + MOVQ 104(SP),AX + ANDQ R9,AX + ORQ AX,SI + ANDQ DI,DX + MOVQ 112(SP),AX + ANDQ R9,AX + ORQ AX,DX + ANDQ DI,CX + MOVQ 120(SP),AX + ANDQ R9,AX + ORQ AX,CX + ANDQ DI,R8 + MOVQ 128(SP),DI + ANDQ R9,DI + ORQ DI,R8 + MOVQ 88(SP),DI + MOVQ 96(SP),R9 + ADDL 16(R9),SI + ADCL 20(R9),DX + ADCL 24(R9),CX + ADCL 28(R9),R8 + MOVL SI,0(DI) + MOVL DX,4(DI) + MOVL CX,8(DI) + MOVL R8,12(DI) + MOVQ 32(SP),R11 + MOVQ 40(SP),R12 + MOVQ 48(SP),R13 + MOVQ 56(SP),R14 + MOVQ 64(SP),R15 + MOVQ 72(SP),BX + MOVQ 80(SP),BP + MOVQ R11,SP + RET diff --git a/external/boringssl/ssl/test/runner/poly1305/poly1305_arm.s b/external/boringssl/ssl/test/runner/poly1305/poly1305_arm.s new file mode 100644 index 0000000000..c15386744d --- /dev/null +++ b/external/boringssl/ssl/test/runner/poly1305/poly1305_arm.s @@ -0,0 +1,379 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This code was translated into a form compatible with 5a from the public +// domain source by Andrew Moon: github.com/floodyberry/poly1305-opt/blob/master/app/extensions/poly1305. + +// +build arm,!gccgo,!appengine + +DATA poly1305_init_constants_armv6<>+0x00(SB)/4, $0x3ffffff +DATA poly1305_init_constants_armv6<>+0x04(SB)/4, $0x3ffff03 +DATA poly1305_init_constants_armv6<>+0x08(SB)/4, $0x3ffc0ff +DATA poly1305_init_constants_armv6<>+0x0c(SB)/4, $0x3f03fff +DATA poly1305_init_constants_armv6<>+0x10(SB)/4, $0x00fffff +GLOBL poly1305_init_constants_armv6<>(SB), 8, $20 + +// Warning: the linker may use R11 to synthesize certain instructions. Please +// take care and verify that no synthetic instructions use it. + +TEXT poly1305_init_ext_armv6<>(SB),4,$-4 + MOVM.DB.W [R4-R11], (R13) + MOVM.IA.W (R1), [R2-R5] + MOVW $poly1305_init_constants_armv6<>(SB), R7 + MOVW R2, R8 + MOVW R2>>26, R9 + MOVW R3>>20, g + MOVW R4>>14, R11 + MOVW R5>>8, R12 + ORR R3<<6, R9, R9 + ORR R4<<12, g, g + ORR R5<<18, R11, R11 + MOVM.IA (R7), [R2-R6] + AND R8, R2, R2 + AND R9, R3, R3 + AND g, R4, R4 + AND R11, R5, R5 + AND R12, R6, R6 + MOVM.IA.W [R2-R6], (R0) + EOR R2, R2, R2 + EOR R3, R3, R3 + EOR R4, R4, R4 + EOR R5, R5, R5 + EOR R6, R6, R6 + MOVM.IA.W [R2-R6], (R0) + MOVM.IA.W (R1), [R2-R5] + MOVM.IA [R2-R6], (R0) + MOVM.IA.W (R13), [R4-R11] + RET + +#define MOVW_UNALIGNED(Rsrc, Rdst, Rtmp, offset) \ + MOVBU (offset+0)(Rsrc), Rtmp; \ + MOVBU Rtmp, (offset+0)(Rdst); \ + MOVBU (offset+1)(Rsrc), Rtmp; \ + MOVBU Rtmp, (offset+1)(Rdst); \ + MOVBU (offset+2)(Rsrc), Rtmp; \ + MOVBU Rtmp, (offset+2)(Rdst); \ + MOVBU (offset+3)(Rsrc), Rtmp; \ + MOVBU Rtmp, (offset+3)(Rdst) + +TEXT poly1305_blocks_armv6<>(SB),4,$-4 + MOVM.DB.W [R4, R5, R6, R7, R8, R9, g, R11, R14], (R13) + SUB $128, R13 + MOVW R0, 36(R13) + MOVW R1, 40(R13) + MOVW R2, 44(R13) + MOVW R1, R14 + MOVW R2, R12 + MOVW 56(R0), R8 + WORD $0xe1180008 // TST R8, R8 not working see issue 5921 + EOR R6, R6, R6 + MOVW.EQ $(1<<24), R6 + MOVW R6, 32(R13) + ADD $64, R13, g + MOVM.IA (R0), [R0-R9] + MOVM.IA [R0-R4], (g) + CMP $16, R12 + BLO poly1305_blocks_armv6_done +poly1305_blocks_armv6_mainloop: + WORD $0xe31e0003 // TST R14, #3 not working see issue 5921 + BEQ poly1305_blocks_armv6_mainloop_aligned + ADD $48, R13, g + MOVW_UNALIGNED(R14, g, R0, 0) + MOVW_UNALIGNED(R14, g, R0, 4) + MOVW_UNALIGNED(R14, g, R0, 8) + MOVW_UNALIGNED(R14, g, R0, 12) + MOVM.IA (g), [R0-R3] + ADD $16, R14 + B poly1305_blocks_armv6_mainloop_loaded +poly1305_blocks_armv6_mainloop_aligned: + MOVM.IA.W (R14), [R0-R3] +poly1305_blocks_armv6_mainloop_loaded: + MOVW R0>>26, g + MOVW R1>>20, R11 + MOVW R2>>14, R12 + MOVW R14, 40(R13) + MOVW R3>>8, R4 + ORR R1<<6, g, g + ORR R2<<12, R11, R11 + ORR R3<<18, R12, R12 + BIC $0xfc000000, R0, R0 + BIC $0xfc000000, g, g + MOVW 32(R13), R3 + BIC $0xfc000000, R11, R11 + BIC $0xfc000000, R12, R12 + ADD R0, R5, R5 + ADD g, R6, R6 + ORR R3, R4, R4 + ADD R11, R7, R7 + ADD $64, R13, R14 + ADD R12, R8, R8 + ADD R4, R9, R9 + MOVM.IA (R14), [R0-R4] + MULLU R4, R5, (R11, g) + MULLU R3, R5, (R14, R12) + MULALU R3, R6, (R11, g) + MULALU R2, R6, (R14, R12) + MULALU R2, R7, (R11, g) + MULALU R1, R7, (R14, R12) + ADD R4<<2, R4, R4 + ADD R3<<2, R3, R3 + MULALU R1, R8, (R11, g) + MULALU R0, R8, (R14, R12) + MULALU R0, R9, (R11, g) + MULALU R4, R9, (R14, R12) + MOVW g, 24(R13) + MOVW R11, 28(R13) + MOVW R12, 16(R13) + MOVW R14, 20(R13) + MULLU R2, R5, (R11, g) + MULLU R1, R5, (R14, R12) + MULALU R1, R6, (R11, g) + MULALU R0, R6, (R14, R12) + MULALU R0, R7, (R11, g) + MULALU R4, R7, (R14, R12) + ADD R2<<2, R2, R2 + ADD R1<<2, R1, R1 + MULALU R4, R8, (R11, g) + MULALU R3, R8, (R14, R12) + MULALU R3, R9, (R11, g) + MULALU R2, R9, (R14, R12) + MOVW g, 8(R13) + MOVW R11, 12(R13) + MOVW R12, 0(R13) + MOVW R14, w+4(SP) + MULLU R0, R5, (R11, g) + MULALU R4, R6, (R11, g) + MULALU R3, R7, (R11, g) + MULALU R2, R8, (R11, g) + MULALU R1, R9, (R11, g) + MOVM.IA (R13), [R0-R7] + MOVW g>>26, R12 + MOVW R4>>26, R14 + ORR R11<<6, R12, R12 + ORR R5<<6, R14, R14 + BIC $0xfc000000, g, g + BIC $0xfc000000, R4, R4 + ADD.S R12, R0, R0 + ADC $0, R1, R1 + ADD.S R14, R6, R6 + ADC $0, R7, R7 + MOVW R0>>26, R12 + MOVW R6>>26, R14 + ORR R1<<6, R12, R12 + ORR R7<<6, R14, R14 + BIC $0xfc000000, R0, R0 + BIC $0xfc000000, R6, R6 + ADD R14<<2, R14, R14 + ADD.S R12, R2, R2 + ADC $0, R3, R3 + ADD R14, g, g + MOVW R2>>26, R12 + MOVW g>>26, R14 + ORR R3<<6, R12, R12 + BIC $0xfc000000, g, R5 + BIC $0xfc000000, R2, R7 + ADD R12, R4, R4 + ADD R14, R0, R0 + MOVW R4>>26, R12 + BIC $0xfc000000, R4, R8 + ADD R12, R6, R9 + MOVW w+44(SP), R12 + MOVW w+40(SP), R14 + MOVW R0, R6 + CMP $32, R12 + SUB $16, R12, R12 + MOVW R12, 44(R13) + BHS poly1305_blocks_armv6_mainloop +poly1305_blocks_armv6_done: + MOVW 36(R13), R12 + MOVW R5, 20(R12) + MOVW R6, 24(R12) + MOVW R7, 28(R12) + MOVW R8, 32(R12) + MOVW R9, 36(R12) + ADD $128, R13, R13 + MOVM.IA.W (R13), [R4, R5, R6, R7, R8, R9, g, R11, R14] + RET + +#define MOVHUP_UNALIGNED(Rsrc, Rdst, Rtmp) \ + MOVBU.P 1(Rsrc), Rtmp; \ + MOVBU.P Rtmp, 1(Rdst); \ + MOVBU.P 1(Rsrc), Rtmp; \ + MOVBU.P Rtmp, 1(Rdst) + +#define MOVWP_UNALIGNED(Rsrc, Rdst, Rtmp) \ + MOVHUP_UNALIGNED(Rsrc, Rdst, Rtmp); \ + MOVHUP_UNALIGNED(Rsrc, Rdst, Rtmp) + +TEXT poly1305_finish_ext_armv6<>(SB),4,$-4 + MOVM.DB.W [R4, R5, R6, R7, R8, R9, g, R11, R14], (R13) + SUB $16, R13, R13 + MOVW R0, R5 + MOVW R1, R6 + MOVW R2, R7 + MOVW R3, R8 + AND.S R2, R2, R2 + BEQ poly1305_finish_ext_armv6_noremaining + EOR R0, R0 + MOVW R13, R9 + MOVW R0, 0(R13) + MOVW R0, 4(R13) + MOVW R0, 8(R13) + MOVW R0, 12(R13) + WORD $0xe3110003 // TST R1, #3 not working see issue 5921 + BEQ poly1305_finish_ext_armv6_aligned + WORD $0xe3120008 // TST R2, #8 not working see issue 5921 + BEQ poly1305_finish_ext_armv6_skip8 + MOVWP_UNALIGNED(R1, R9, g) + MOVWP_UNALIGNED(R1, R9, g) +poly1305_finish_ext_armv6_skip8: + WORD $0xe3120004 // TST $4, R2 not working see issue 5921 + BEQ poly1305_finish_ext_armv6_skip4 + MOVWP_UNALIGNED(R1, R9, g) +poly1305_finish_ext_armv6_skip4: + WORD $0xe3120002 // TST $2, R2 not working see issue 5921 + BEQ poly1305_finish_ext_armv6_skip2 + MOVHUP_UNALIGNED(R1, R9, g) + B poly1305_finish_ext_armv6_skip2 +poly1305_finish_ext_armv6_aligned: + WORD $0xe3120008 // TST R2, #8 not working see issue 5921 + BEQ poly1305_finish_ext_armv6_skip8_aligned + MOVM.IA.W (R1), [g-R11] + MOVM.IA.W [g-R11], (R9) +poly1305_finish_ext_armv6_skip8_aligned: + WORD $0xe3120004 // TST $4, R2 not working see issue 5921 + BEQ poly1305_finish_ext_armv6_skip4_aligned + MOVW.P 4(R1), g + MOVW.P g, 4(R9) +poly1305_finish_ext_armv6_skip4_aligned: + WORD $0xe3120002 // TST $2, R2 not working see issue 5921 + BEQ poly1305_finish_ext_armv6_skip2 + MOVHU.P 2(R1), g + MOVH.P g, 2(R9) +poly1305_finish_ext_armv6_skip2: + WORD $0xe3120001 // TST $1, R2 not working see issue 5921 + BEQ poly1305_finish_ext_armv6_skip1 + MOVBU.P 1(R1), g + MOVBU.P g, 1(R9) +poly1305_finish_ext_armv6_skip1: + MOVW $1, R11 + MOVBU R11, 0(R9) + MOVW R11, 56(R5) + MOVW R5, R0 + MOVW R13, R1 + MOVW $16, R2 + BL poly1305_blocks_armv6<>(SB) +poly1305_finish_ext_armv6_noremaining: + MOVW 20(R5), R0 + MOVW 24(R5), R1 + MOVW 28(R5), R2 + MOVW 32(R5), R3 + MOVW 36(R5), R4 + MOVW R4>>26, R12 + BIC $0xfc000000, R4, R4 + ADD R12<<2, R12, R12 + ADD R12, R0, R0 + MOVW R0>>26, R12 + BIC $0xfc000000, R0, R0 + ADD R12, R1, R1 + MOVW R1>>26, R12 + BIC $0xfc000000, R1, R1 + ADD R12, R2, R2 + MOVW R2>>26, R12 + BIC $0xfc000000, R2, R2 + ADD R12, R3, R3 + MOVW R3>>26, R12 + BIC $0xfc000000, R3, R3 + ADD R12, R4, R4 + ADD $5, R0, R6 + MOVW R6>>26, R12 + BIC $0xfc000000, R6, R6 + ADD R12, R1, R7 + MOVW R7>>26, R12 + BIC $0xfc000000, R7, R7 + ADD R12, R2, g + MOVW g>>26, R12 + BIC $0xfc000000, g, g + ADD R12, R3, R11 + MOVW $-(1<<26), R12 + ADD R11>>26, R12, R12 + BIC $0xfc000000, R11, R11 + ADD R12, R4, R14 + MOVW R14>>31, R12 + SUB $1, R12 + AND R12, R6, R6 + AND R12, R7, R7 + AND R12, g, g + AND R12, R11, R11 + AND R12, R14, R14 + MVN R12, R12 + AND R12, R0, R0 + AND R12, R1, R1 + AND R12, R2, R2 + AND R12, R3, R3 + AND R12, R4, R4 + ORR R6, R0, R0 + ORR R7, R1, R1 + ORR g, R2, R2 + ORR R11, R3, R3 + ORR R14, R4, R4 + ORR R1<<26, R0, R0 + MOVW R1>>6, R1 + ORR R2<<20, R1, R1 + MOVW R2>>12, R2 + ORR R3<<14, R2, R2 + MOVW R3>>18, R3 + ORR R4<<8, R3, R3 + MOVW 40(R5), R6 + MOVW 44(R5), R7 + MOVW 48(R5), g + MOVW 52(R5), R11 + ADD.S R6, R0, R0 + ADC.S R7, R1, R1 + ADC.S g, R2, R2 + ADC.S R11, R3, R3 + MOVM.IA [R0-R3], (R8) + MOVW R5, R12 + EOR R0, R0, R0 + EOR R1, R1, R1 + EOR R2, R2, R2 + EOR R3, R3, R3 + EOR R4, R4, R4 + EOR R5, R5, R5 + EOR R6, R6, R6 + EOR R7, R7, R7 + MOVM.IA.W [R0-R7], (R12) + MOVM.IA [R0-R7], (R12) + ADD $16, R13, R13 + MOVM.IA.W (R13), [R4, R5, R6, R7, R8, R9, g, R11, R14] + RET + +// func poly1305_auth_armv6(out *[16]byte, m *byte, mlen uint32, key *[32]key) +TEXT ·poly1305_auth_armv6(SB),0,$280-16 + MOVW out+0(FP), R4 + MOVW m+4(FP), R5 + MOVW mlen+8(FP), R6 + MOVW key+12(FP), R7 + + MOVW R13, R8 + BIC $63, R13 + SUB $64, R13, R13 + MOVW R13, R0 + MOVW R7, R1 + BL poly1305_init_ext_armv6<>(SB) + BIC.S $15, R6, R2 + BEQ poly1305_auth_armv6_noblocks + MOVW R13, R0 + MOVW R5, R1 + ADD R2, R5, R5 + SUB R2, R6, R6 + BL poly1305_blocks_armv6<>(SB) +poly1305_auth_armv6_noblocks: + MOVW R13, R0 + MOVW R5, R1 + MOVW R6, R2 + MOVW R4, R3 + BL poly1305_finish_ext_armv6<>(SB) + MOVW R8, R13 + RET diff --git a/external/boringssl/ssl/test/runner/poly1305/poly1305_test.go b/external/boringssl/ssl/test/runner/poly1305/poly1305_test.go new file mode 100644 index 0000000000..b3e92310b5 --- /dev/null +++ b/external/boringssl/ssl/test/runner/poly1305/poly1305_test.go @@ -0,0 +1,86 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package poly1305 + +import ( + "bytes" + "testing" + "unsafe" +) + +var testData = []struct { + in, k, correct []byte +}{ + { + []byte("Hello world!"), + []byte("this is 32-byte key for Poly1305"), + []byte{0xa6, 0xf7, 0x45, 0x00, 0x8f, 0x81, 0xc9, 0x16, 0xa2, 0x0d, 0xcc, 0x74, 0xee, 0xf2, 0xb2, 0xf0}, + }, + { + make([]byte, 32), + []byte("this is 32-byte key for Poly1305"), + []byte{0x49, 0xec, 0x78, 0x09, 0x0e, 0x48, 0x1e, 0xc6, 0xc2, 0x6b, 0x33, 0xb9, 0x1c, 0xcc, 0x03, 0x07}, + }, + { + make([]byte, 2007), + []byte("this is 32-byte key for Poly1305"), + []byte{0xda, 0x84, 0xbc, 0xab, 0x02, 0x67, 0x6c, 0x38, 0xcd, 0xb0, 0x15, 0x60, 0x42, 0x74, 0xc2, 0xaa}, + }, + { + make([]byte, 2007), + make([]byte, 32), + make([]byte, 16), + }, +} + +func testSum(t *testing.T, unaligned bool) { + var out [16]byte + var key [32]byte + + for i, v := range testData { + in := v.in + if unaligned { + in = unalignBytes(in) + } + copy(key[:], v.k) + Sum(&out, in, &key) + if !bytes.Equal(out[:], v.correct) { + t.Errorf("%d: expected %x, got %x", i, v.correct, out[:]) + } + } +} + +func TestSum(t *testing.T) { testSum(t, false) } +func TestSumUnaligned(t *testing.T) { testSum(t, true) } + +func benchmark(b *testing.B, size int, unaligned bool) { + var out [16]byte + var key [32]byte + in := make([]byte, size) + if unaligned { + in = unalignBytes(in) + } + b.SetBytes(int64(len(in))) + b.ResetTimer() + for i := 0; i < b.N; i++ { + Sum(&out, in, &key) + } +} + +func Benchmark64(b *testing.B) { benchmark(b, 64, false) } +func Benchmark1K(b *testing.B) { benchmark(b, 1024, false) } +func Benchmark64Unaligned(b *testing.B) { benchmark(b, 64, true) } +func Benchmark1KUnaligned(b *testing.B) { benchmark(b, 1024, true) } + +func unalignBytes(in []byte) []byte { + out := make([]byte, len(in)+1) + if uintptr(unsafe.Pointer(&out[0]))&(unsafe.Alignof(uint32(0))-1) == 0 { + out = out[1:] + } else { + out = out[:len(in)] + } + copy(out, in) + return out +} diff --git a/external/boringssl/ssl/test/runner/poly1305/sum_amd64.go b/external/boringssl/ssl/test/runner/poly1305/sum_amd64.go new file mode 100644 index 0000000000..6775c703f6 --- /dev/null +++ b/external/boringssl/ssl/test/runner/poly1305/sum_amd64.go @@ -0,0 +1,24 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build amd64,!gccgo,!appengine + +package poly1305 + +// This function is implemented in poly1305_amd64.s + +//go:noescape + +func poly1305(out *[16]byte, m *byte, mlen uint64, key *[32]byte) + +// Sum generates an authenticator for m using a one-time key and puts the +// 16-byte result into out. Authenticating two different messages with the same +// key allows an attacker to forge messages at will. +func Sum(out *[16]byte, m []byte, key *[32]byte) { + var mPtr *byte + if len(m) > 0 { + mPtr = &m[0] + } + poly1305(out, mPtr, uint64(len(m)), key) +} diff --git a/external/boringssl/ssl/test/runner/poly1305/sum_arm.go b/external/boringssl/ssl/test/runner/poly1305/sum_arm.go new file mode 100644 index 0000000000..50b979c24c --- /dev/null +++ b/external/boringssl/ssl/test/runner/poly1305/sum_arm.go @@ -0,0 +1,24 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build arm,!gccgo,!appengine + +package poly1305 + +// This function is implemented in poly1305_arm.s + +//go:noescape + +func poly1305_auth_armv6(out *[16]byte, m *byte, mlen uint32, key *[32]byte) + +// Sum generates an authenticator for m using a one-time key and puts the +// 16-byte result into out. Authenticating two different messages with the same +// key allows an attacker to forge messages at will. +func Sum(out *[16]byte, m []byte, key *[32]byte) { + var mPtr *byte + if len(m) > 0 { + mPtr = &m[0] + } + poly1305_auth_armv6(out, mPtr, uint32(len(m)), key) +} diff --git a/external/boringssl/ssl/test/runner/poly1305/sum_ref.go b/external/boringssl/ssl/test/runner/poly1305/sum_ref.go new file mode 100644 index 0000000000..0b24fc78b9 --- /dev/null +++ b/external/boringssl/ssl/test/runner/poly1305/sum_ref.go @@ -0,0 +1,1531 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !amd64,!arm gccgo appengine + +package poly1305 + +// Based on original, public domain implementation from NaCl by D. J. +// Bernstein. + +import "math" + +const ( + alpham80 = 0.00000000558793544769287109375 + alpham48 = 24.0 + alpham16 = 103079215104.0 + alpha0 = 6755399441055744.0 + alpha18 = 1770887431076116955136.0 + alpha32 = 29014219670751100192948224.0 + alpha50 = 7605903601369376408980219232256.0 + alpha64 = 124615124604835863084731911901282304.0 + alpha82 = 32667107224410092492483962313449748299776.0 + alpha96 = 535217884764734955396857238543560676143529984.0 + alpha112 = 35076039295941670036888435985190792471742381031424.0 + alpha130 = 9194973245195333150150082162901855101712434733101613056.0 + scale = 0.0000000000000000000000000000000000000036734198463196484624023016788195177431833298649127735047148490821200539357960224151611328125 + offset0 = 6755408030990331.0 + offset1 = 29014256564239239022116864.0 + offset2 = 124615283061160854719918951570079744.0 + offset3 = 535219245894202480694386063513315216128475136.0 +) + +// Sum generates an authenticator for m using a one-time key and puts the +// 16-byte result into out. Authenticating two different messages with the same +// key allows an attacker to forge messages at will. +func Sum(out *[16]byte, m []byte, key *[32]byte) { + r := key + s := key[16:] + var ( + y7 float64 + y6 float64 + y1 float64 + y0 float64 + y5 float64 + y4 float64 + x7 float64 + x6 float64 + x1 float64 + x0 float64 + y3 float64 + y2 float64 + x5 float64 + r3lowx0 float64 + x4 float64 + r0lowx6 float64 + x3 float64 + r3highx0 float64 + x2 float64 + r0highx6 float64 + r0lowx0 float64 + sr1lowx6 float64 + r0highx0 float64 + sr1highx6 float64 + sr3low float64 + r1lowx0 float64 + sr2lowx6 float64 + r1highx0 float64 + sr2highx6 float64 + r2lowx0 float64 + sr3lowx6 float64 + r2highx0 float64 + sr3highx6 float64 + r1highx4 float64 + r1lowx4 float64 + r0highx4 float64 + r0lowx4 float64 + sr3highx4 float64 + sr3lowx4 float64 + sr2highx4 float64 + sr2lowx4 float64 + r0lowx2 float64 + r0highx2 float64 + r1lowx2 float64 + r1highx2 float64 + r2lowx2 float64 + r2highx2 float64 + sr3lowx2 float64 + sr3highx2 float64 + z0 float64 + z1 float64 + z2 float64 + z3 float64 + m0 int64 + m1 int64 + m2 int64 + m3 int64 + m00 uint32 + m01 uint32 + m02 uint32 + m03 uint32 + m10 uint32 + m11 uint32 + m12 uint32 + m13 uint32 + m20 uint32 + m21 uint32 + m22 uint32 + m23 uint32 + m30 uint32 + m31 uint32 + m32 uint32 + m33 uint64 + lbelow2 int32 + lbelow3 int32 + lbelow4 int32 + lbelow5 int32 + lbelow6 int32 + lbelow7 int32 + lbelow8 int32 + lbelow9 int32 + lbelow10 int32 + lbelow11 int32 + lbelow12 int32 + lbelow13 int32 + lbelow14 int32 + lbelow15 int32 + s00 uint32 + s01 uint32 + s02 uint32 + s03 uint32 + s10 uint32 + s11 uint32 + s12 uint32 + s13 uint32 + s20 uint32 + s21 uint32 + s22 uint32 + s23 uint32 + s30 uint32 + s31 uint32 + s32 uint32 + s33 uint32 + bits32 uint64 + f uint64 + f0 uint64 + f1 uint64 + f2 uint64 + f3 uint64 + f4 uint64 + g uint64 + g0 uint64 + g1 uint64 + g2 uint64 + g3 uint64 + g4 uint64 + ) + + var p int32 + + l := int32(len(m)) + + r00 := uint32(r[0]) + + r01 := uint32(r[1]) + + r02 := uint32(r[2]) + r0 := int64(2151) + + r03 := uint32(r[3]) + r03 &= 15 + r0 <<= 51 + + r10 := uint32(r[4]) + r10 &= 252 + r01 <<= 8 + r0 += int64(r00) + + r11 := uint32(r[5]) + r02 <<= 16 + r0 += int64(r01) + + r12 := uint32(r[6]) + r03 <<= 24 + r0 += int64(r02) + + r13 := uint32(r[7]) + r13 &= 15 + r1 := int64(2215) + r0 += int64(r03) + + d0 := r0 + r1 <<= 51 + r2 := int64(2279) + + r20 := uint32(r[8]) + r20 &= 252 + r11 <<= 8 + r1 += int64(r10) + + r21 := uint32(r[9]) + r12 <<= 16 + r1 += int64(r11) + + r22 := uint32(r[10]) + r13 <<= 24 + r1 += int64(r12) + + r23 := uint32(r[11]) + r23 &= 15 + r2 <<= 51 + r1 += int64(r13) + + d1 := r1 + r21 <<= 8 + r2 += int64(r20) + + r30 := uint32(r[12]) + r30 &= 252 + r22 <<= 16 + r2 += int64(r21) + + r31 := uint32(r[13]) + r23 <<= 24 + r2 += int64(r22) + + r32 := uint32(r[14]) + r2 += int64(r23) + r3 := int64(2343) + + d2 := r2 + r3 <<= 51 + + r33 := uint32(r[15]) + r33 &= 15 + r31 <<= 8 + r3 += int64(r30) + + r32 <<= 16 + r3 += int64(r31) + + r33 <<= 24 + r3 += int64(r32) + + r3 += int64(r33) + h0 := alpha32 - alpha32 + + d3 := r3 + h1 := alpha32 - alpha32 + + h2 := alpha32 - alpha32 + + h3 := alpha32 - alpha32 + + h4 := alpha32 - alpha32 + + r0low := math.Float64frombits(uint64(d0)) + h5 := alpha32 - alpha32 + + r1low := math.Float64frombits(uint64(d1)) + h6 := alpha32 - alpha32 + + r2low := math.Float64frombits(uint64(d2)) + h7 := alpha32 - alpha32 + + r0low -= alpha0 + + r1low -= alpha32 + + r2low -= alpha64 + + r0high := r0low + alpha18 + + r3low := math.Float64frombits(uint64(d3)) + + r1high := r1low + alpha50 + sr1low := scale * r1low + + r2high := r2low + alpha82 + sr2low := scale * r2low + + r0high -= alpha18 + r0high_stack := r0high + + r3low -= alpha96 + + r1high -= alpha50 + r1high_stack := r1high + + sr1high := sr1low + alpham80 + + r0low -= r0high + + r2high -= alpha82 + sr3low = scale * r3low + + sr2high := sr2low + alpham48 + + r1low -= r1high + r1low_stack := r1low + + sr1high -= alpham80 + sr1high_stack := sr1high + + r2low -= r2high + r2low_stack := r2low + + sr2high -= alpham48 + sr2high_stack := sr2high + + r3high := r3low + alpha112 + r0low_stack := r0low + + sr1low -= sr1high + sr1low_stack := sr1low + + sr3high := sr3low + alpham16 + r2high_stack := r2high + + sr2low -= sr2high + sr2low_stack := sr2low + + r3high -= alpha112 + r3high_stack := r3high + + sr3high -= alpham16 + sr3high_stack := sr3high + + r3low -= r3high + r3low_stack := r3low + + sr3low -= sr3high + sr3low_stack := sr3low + + if l < 16 { + goto addatmost15bytes + } + + m00 = uint32(m[p+0]) + m0 = 2151 + + m0 <<= 51 + m1 = 2215 + m01 = uint32(m[p+1]) + + m1 <<= 51 + m2 = 2279 + m02 = uint32(m[p+2]) + + m2 <<= 51 + m3 = 2343 + m03 = uint32(m[p+3]) + + m10 = uint32(m[p+4]) + m01 <<= 8 + m0 += int64(m00) + + m11 = uint32(m[p+5]) + m02 <<= 16 + m0 += int64(m01) + + m12 = uint32(m[p+6]) + m03 <<= 24 + m0 += int64(m02) + + m13 = uint32(m[p+7]) + m3 <<= 51 + m0 += int64(m03) + + m20 = uint32(m[p+8]) + m11 <<= 8 + m1 += int64(m10) + + m21 = uint32(m[p+9]) + m12 <<= 16 + m1 += int64(m11) + + m22 = uint32(m[p+10]) + m13 <<= 24 + m1 += int64(m12) + + m23 = uint32(m[p+11]) + m1 += int64(m13) + + m30 = uint32(m[p+12]) + m21 <<= 8 + m2 += int64(m20) + + m31 = uint32(m[p+13]) + m22 <<= 16 + m2 += int64(m21) + + m32 = uint32(m[p+14]) + m23 <<= 24 + m2 += int64(m22) + + m33 = uint64(m[p+15]) + m2 += int64(m23) + + d0 = m0 + m31 <<= 8 + m3 += int64(m30) + + d1 = m1 + m32 <<= 16 + m3 += int64(m31) + + d2 = m2 + m33 += 256 + + m33 <<= 24 + m3 += int64(m32) + + m3 += int64(m33) + d3 = m3 + + p += 16 + l -= 16 + + z0 = math.Float64frombits(uint64(d0)) + + z1 = math.Float64frombits(uint64(d1)) + + z2 = math.Float64frombits(uint64(d2)) + + z3 = math.Float64frombits(uint64(d3)) + + z0 -= alpha0 + + z1 -= alpha32 + + z2 -= alpha64 + + z3 -= alpha96 + + h0 += z0 + + h1 += z1 + + h3 += z2 + + h5 += z3 + + if l < 16 { + goto multiplyaddatmost15bytes + } + +multiplyaddatleast16bytes: + + m2 = 2279 + m20 = uint32(m[p+8]) + y7 = h7 + alpha130 + + m2 <<= 51 + m3 = 2343 + m21 = uint32(m[p+9]) + y6 = h6 + alpha130 + + m3 <<= 51 + m0 = 2151 + m22 = uint32(m[p+10]) + y1 = h1 + alpha32 + + m0 <<= 51 + m1 = 2215 + m23 = uint32(m[p+11]) + y0 = h0 + alpha32 + + m1 <<= 51 + m30 = uint32(m[p+12]) + y7 -= alpha130 + + m21 <<= 8 + m2 += int64(m20) + m31 = uint32(m[p+13]) + y6 -= alpha130 + + m22 <<= 16 + m2 += int64(m21) + m32 = uint32(m[p+14]) + y1 -= alpha32 + + m23 <<= 24 + m2 += int64(m22) + m33 = uint64(m[p+15]) + y0 -= alpha32 + + m2 += int64(m23) + m00 = uint32(m[p+0]) + y5 = h5 + alpha96 + + m31 <<= 8 + m3 += int64(m30) + m01 = uint32(m[p+1]) + y4 = h4 + alpha96 + + m32 <<= 16 + m02 = uint32(m[p+2]) + x7 = h7 - y7 + y7 *= scale + + m33 += 256 + m03 = uint32(m[p+3]) + x6 = h6 - y6 + y6 *= scale + + m33 <<= 24 + m3 += int64(m31) + m10 = uint32(m[p+4]) + x1 = h1 - y1 + + m01 <<= 8 + m3 += int64(m32) + m11 = uint32(m[p+5]) + x0 = h0 - y0 + + m3 += int64(m33) + m0 += int64(m00) + m12 = uint32(m[p+6]) + y5 -= alpha96 + + m02 <<= 16 + m0 += int64(m01) + m13 = uint32(m[p+7]) + y4 -= alpha96 + + m03 <<= 24 + m0 += int64(m02) + d2 = m2 + x1 += y7 + + m0 += int64(m03) + d3 = m3 + x0 += y6 + + m11 <<= 8 + m1 += int64(m10) + d0 = m0 + x7 += y5 + + m12 <<= 16 + m1 += int64(m11) + x6 += y4 + + m13 <<= 24 + m1 += int64(m12) + y3 = h3 + alpha64 + + m1 += int64(m13) + d1 = m1 + y2 = h2 + alpha64 + + x0 += x1 + + x6 += x7 + + y3 -= alpha64 + r3low = r3low_stack + + y2 -= alpha64 + r0low = r0low_stack + + x5 = h5 - y5 + r3lowx0 = r3low * x0 + r3high = r3high_stack + + x4 = h4 - y4 + r0lowx6 = r0low * x6 + r0high = r0high_stack + + x3 = h3 - y3 + r3highx0 = r3high * x0 + sr1low = sr1low_stack + + x2 = h2 - y2 + r0highx6 = r0high * x6 + sr1high = sr1high_stack + + x5 += y3 + r0lowx0 = r0low * x0 + r1low = r1low_stack + + h6 = r3lowx0 + r0lowx6 + sr1lowx6 = sr1low * x6 + r1high = r1high_stack + + x4 += y2 + r0highx0 = r0high * x0 + sr2low = sr2low_stack + + h7 = r3highx0 + r0highx6 + sr1highx6 = sr1high * x6 + sr2high = sr2high_stack + + x3 += y1 + r1lowx0 = r1low * x0 + r2low = r2low_stack + + h0 = r0lowx0 + sr1lowx6 + sr2lowx6 = sr2low * x6 + r2high = r2high_stack + + x2 += y0 + r1highx0 = r1high * x0 + sr3low = sr3low_stack + + h1 = r0highx0 + sr1highx6 + sr2highx6 = sr2high * x6 + sr3high = sr3high_stack + + x4 += x5 + r2lowx0 = r2low * x0 + z2 = math.Float64frombits(uint64(d2)) + + h2 = r1lowx0 + sr2lowx6 + sr3lowx6 = sr3low * x6 + + x2 += x3 + r2highx0 = r2high * x0 + z3 = math.Float64frombits(uint64(d3)) + + h3 = r1highx0 + sr2highx6 + sr3highx6 = sr3high * x6 + + r1highx4 = r1high * x4 + z2 -= alpha64 + + h4 = r2lowx0 + sr3lowx6 + r1lowx4 = r1low * x4 + + r0highx4 = r0high * x4 + z3 -= alpha96 + + h5 = r2highx0 + sr3highx6 + r0lowx4 = r0low * x4 + + h7 += r1highx4 + sr3highx4 = sr3high * x4 + + h6 += r1lowx4 + sr3lowx4 = sr3low * x4 + + h5 += r0highx4 + sr2highx4 = sr2high * x4 + + h4 += r0lowx4 + sr2lowx4 = sr2low * x4 + + h3 += sr3highx4 + r0lowx2 = r0low * x2 + + h2 += sr3lowx4 + r0highx2 = r0high * x2 + + h1 += sr2highx4 + r1lowx2 = r1low * x2 + + h0 += sr2lowx4 + r1highx2 = r1high * x2 + + h2 += r0lowx2 + r2lowx2 = r2low * x2 + + h3 += r0highx2 + r2highx2 = r2high * x2 + + h4 += r1lowx2 + sr3lowx2 = sr3low * x2 + + h5 += r1highx2 + sr3highx2 = sr3high * x2 + + p += 16 + l -= 16 + h6 += r2lowx2 + + h7 += r2highx2 + + z1 = math.Float64frombits(uint64(d1)) + h0 += sr3lowx2 + + z0 = math.Float64frombits(uint64(d0)) + h1 += sr3highx2 + + z1 -= alpha32 + + z0 -= alpha0 + + h5 += z3 + + h3 += z2 + + h1 += z1 + + h0 += z0 + + if l >= 16 { + goto multiplyaddatleast16bytes + } + +multiplyaddatmost15bytes: + + y7 = h7 + alpha130 + + y6 = h6 + alpha130 + + y1 = h1 + alpha32 + + y0 = h0 + alpha32 + + y7 -= alpha130 + + y6 -= alpha130 + + y1 -= alpha32 + + y0 -= alpha32 + + y5 = h5 + alpha96 + + y4 = h4 + alpha96 + + x7 = h7 - y7 + y7 *= scale + + x6 = h6 - y6 + y6 *= scale + + x1 = h1 - y1 + + x0 = h0 - y0 + + y5 -= alpha96 + + y4 -= alpha96 + + x1 += y7 + + x0 += y6 + + x7 += y5 + + x6 += y4 + + y3 = h3 + alpha64 + + y2 = h2 + alpha64 + + x0 += x1 + + x6 += x7 + + y3 -= alpha64 + r3low = r3low_stack + + y2 -= alpha64 + r0low = r0low_stack + + x5 = h5 - y5 + r3lowx0 = r3low * x0 + r3high = r3high_stack + + x4 = h4 - y4 + r0lowx6 = r0low * x6 + r0high = r0high_stack + + x3 = h3 - y3 + r3highx0 = r3high * x0 + sr1low = sr1low_stack + + x2 = h2 - y2 + r0highx6 = r0high * x6 + sr1high = sr1high_stack + + x5 += y3 + r0lowx0 = r0low * x0 + r1low = r1low_stack + + h6 = r3lowx0 + r0lowx6 + sr1lowx6 = sr1low * x6 + r1high = r1high_stack + + x4 += y2 + r0highx0 = r0high * x0 + sr2low = sr2low_stack + + h7 = r3highx0 + r0highx6 + sr1highx6 = sr1high * x6 + sr2high = sr2high_stack + + x3 += y1 + r1lowx0 = r1low * x0 + r2low = r2low_stack + + h0 = r0lowx0 + sr1lowx6 + sr2lowx6 = sr2low * x6 + r2high = r2high_stack + + x2 += y0 + r1highx0 = r1high * x0 + sr3low = sr3low_stack + + h1 = r0highx0 + sr1highx6 + sr2highx6 = sr2high * x6 + sr3high = sr3high_stack + + x4 += x5 + r2lowx0 = r2low * x0 + + h2 = r1lowx0 + sr2lowx6 + sr3lowx6 = sr3low * x6 + + x2 += x3 + r2highx0 = r2high * x0 + + h3 = r1highx0 + sr2highx6 + sr3highx6 = sr3high * x6 + + r1highx4 = r1high * x4 + + h4 = r2lowx0 + sr3lowx6 + r1lowx4 = r1low * x4 + + r0highx4 = r0high * x4 + + h5 = r2highx0 + sr3highx6 + r0lowx4 = r0low * x4 + + h7 += r1highx4 + sr3highx4 = sr3high * x4 + + h6 += r1lowx4 + sr3lowx4 = sr3low * x4 + + h5 += r0highx4 + sr2highx4 = sr2high * x4 + + h4 += r0lowx4 + sr2lowx4 = sr2low * x4 + + h3 += sr3highx4 + r0lowx2 = r0low * x2 + + h2 += sr3lowx4 + r0highx2 = r0high * x2 + + h1 += sr2highx4 + r1lowx2 = r1low * x2 + + h0 += sr2lowx4 + r1highx2 = r1high * x2 + + h2 += r0lowx2 + r2lowx2 = r2low * x2 + + h3 += r0highx2 + r2highx2 = r2high * x2 + + h4 += r1lowx2 + sr3lowx2 = sr3low * x2 + + h5 += r1highx2 + sr3highx2 = sr3high * x2 + + h6 += r2lowx2 + + h7 += r2highx2 + + h0 += sr3lowx2 + + h1 += sr3highx2 + +addatmost15bytes: + + if l == 0 { + goto nomorebytes + } + + lbelow2 = l - 2 + + lbelow3 = l - 3 + + lbelow2 >>= 31 + lbelow4 = l - 4 + + m00 = uint32(m[p+0]) + lbelow3 >>= 31 + p += lbelow2 + + m01 = uint32(m[p+1]) + lbelow4 >>= 31 + p += lbelow3 + + m02 = uint32(m[p+2]) + p += lbelow4 + m0 = 2151 + + m03 = uint32(m[p+3]) + m0 <<= 51 + m1 = 2215 + + m0 += int64(m00) + m01 &^= uint32(lbelow2) + + m02 &^= uint32(lbelow3) + m01 -= uint32(lbelow2) + + m01 <<= 8 + m03 &^= uint32(lbelow4) + + m0 += int64(m01) + lbelow2 -= lbelow3 + + m02 += uint32(lbelow2) + lbelow3 -= lbelow4 + + m02 <<= 16 + m03 += uint32(lbelow3) + + m03 <<= 24 + m0 += int64(m02) + + m0 += int64(m03) + lbelow5 = l - 5 + + lbelow6 = l - 6 + lbelow7 = l - 7 + + lbelow5 >>= 31 + lbelow8 = l - 8 + + lbelow6 >>= 31 + p += lbelow5 + + m10 = uint32(m[p+4]) + lbelow7 >>= 31 + p += lbelow6 + + m11 = uint32(m[p+5]) + lbelow8 >>= 31 + p += lbelow7 + + m12 = uint32(m[p+6]) + m1 <<= 51 + p += lbelow8 + + m13 = uint32(m[p+7]) + m10 &^= uint32(lbelow5) + lbelow4 -= lbelow5 + + m10 += uint32(lbelow4) + lbelow5 -= lbelow6 + + m11 &^= uint32(lbelow6) + m11 += uint32(lbelow5) + + m11 <<= 8 + m1 += int64(m10) + + m1 += int64(m11) + m12 &^= uint32(lbelow7) + + lbelow6 -= lbelow7 + m13 &^= uint32(lbelow8) + + m12 += uint32(lbelow6) + lbelow7 -= lbelow8 + + m12 <<= 16 + m13 += uint32(lbelow7) + + m13 <<= 24 + m1 += int64(m12) + + m1 += int64(m13) + m2 = 2279 + + lbelow9 = l - 9 + m3 = 2343 + + lbelow10 = l - 10 + lbelow11 = l - 11 + + lbelow9 >>= 31 + lbelow12 = l - 12 + + lbelow10 >>= 31 + p += lbelow9 + + m20 = uint32(m[p+8]) + lbelow11 >>= 31 + p += lbelow10 + + m21 = uint32(m[p+9]) + lbelow12 >>= 31 + p += lbelow11 + + m22 = uint32(m[p+10]) + m2 <<= 51 + p += lbelow12 + + m23 = uint32(m[p+11]) + m20 &^= uint32(lbelow9) + lbelow8 -= lbelow9 + + m20 += uint32(lbelow8) + lbelow9 -= lbelow10 + + m21 &^= uint32(lbelow10) + m21 += uint32(lbelow9) + + m21 <<= 8 + m2 += int64(m20) + + m2 += int64(m21) + m22 &^= uint32(lbelow11) + + lbelow10 -= lbelow11 + m23 &^= uint32(lbelow12) + + m22 += uint32(lbelow10) + lbelow11 -= lbelow12 + + m22 <<= 16 + m23 += uint32(lbelow11) + + m23 <<= 24 + m2 += int64(m22) + + m3 <<= 51 + lbelow13 = l - 13 + + lbelow13 >>= 31 + lbelow14 = l - 14 + + lbelow14 >>= 31 + p += lbelow13 + lbelow15 = l - 15 + + m30 = uint32(m[p+12]) + lbelow15 >>= 31 + p += lbelow14 + + m31 = uint32(m[p+13]) + p += lbelow15 + m2 += int64(m23) + + m32 = uint32(m[p+14]) + m30 &^= uint32(lbelow13) + lbelow12 -= lbelow13 + + m30 += uint32(lbelow12) + lbelow13 -= lbelow14 + + m3 += int64(m30) + m31 &^= uint32(lbelow14) + + m31 += uint32(lbelow13) + m32 &^= uint32(lbelow15) + + m31 <<= 8 + lbelow14 -= lbelow15 + + m3 += int64(m31) + m32 += uint32(lbelow14) + d0 = m0 + + m32 <<= 16 + m33 = uint64(lbelow15 + 1) + d1 = m1 + + m33 <<= 24 + m3 += int64(m32) + d2 = m2 + + m3 += int64(m33) + d3 = m3 + + z3 = math.Float64frombits(uint64(d3)) + + z2 = math.Float64frombits(uint64(d2)) + + z1 = math.Float64frombits(uint64(d1)) + + z0 = math.Float64frombits(uint64(d0)) + + z3 -= alpha96 + + z2 -= alpha64 + + z1 -= alpha32 + + z0 -= alpha0 + + h5 += z3 + + h3 += z2 + + h1 += z1 + + h0 += z0 + + y7 = h7 + alpha130 + + y6 = h6 + alpha130 + + y1 = h1 + alpha32 + + y0 = h0 + alpha32 + + y7 -= alpha130 + + y6 -= alpha130 + + y1 -= alpha32 + + y0 -= alpha32 + + y5 = h5 + alpha96 + + y4 = h4 + alpha96 + + x7 = h7 - y7 + y7 *= scale + + x6 = h6 - y6 + y6 *= scale + + x1 = h1 - y1 + + x0 = h0 - y0 + + y5 -= alpha96 + + y4 -= alpha96 + + x1 += y7 + + x0 += y6 + + x7 += y5 + + x6 += y4 + + y3 = h3 + alpha64 + + y2 = h2 + alpha64 + + x0 += x1 + + x6 += x7 + + y3 -= alpha64 + r3low = r3low_stack + + y2 -= alpha64 + r0low = r0low_stack + + x5 = h5 - y5 + r3lowx0 = r3low * x0 + r3high = r3high_stack + + x4 = h4 - y4 + r0lowx6 = r0low * x6 + r0high = r0high_stack + + x3 = h3 - y3 + r3highx0 = r3high * x0 + sr1low = sr1low_stack + + x2 = h2 - y2 + r0highx6 = r0high * x6 + sr1high = sr1high_stack + + x5 += y3 + r0lowx0 = r0low * x0 + r1low = r1low_stack + + h6 = r3lowx0 + r0lowx6 + sr1lowx6 = sr1low * x6 + r1high = r1high_stack + + x4 += y2 + r0highx0 = r0high * x0 + sr2low = sr2low_stack + + h7 = r3highx0 + r0highx6 + sr1highx6 = sr1high * x6 + sr2high = sr2high_stack + + x3 += y1 + r1lowx0 = r1low * x0 + r2low = r2low_stack + + h0 = r0lowx0 + sr1lowx6 + sr2lowx6 = sr2low * x6 + r2high = r2high_stack + + x2 += y0 + r1highx0 = r1high * x0 + sr3low = sr3low_stack + + h1 = r0highx0 + sr1highx6 + sr2highx6 = sr2high * x6 + sr3high = sr3high_stack + + x4 += x5 + r2lowx0 = r2low * x0 + + h2 = r1lowx0 + sr2lowx6 + sr3lowx6 = sr3low * x6 + + x2 += x3 + r2highx0 = r2high * x0 + + h3 = r1highx0 + sr2highx6 + sr3highx6 = sr3high * x6 + + r1highx4 = r1high * x4 + + h4 = r2lowx0 + sr3lowx6 + r1lowx4 = r1low * x4 + + r0highx4 = r0high * x4 + + h5 = r2highx0 + sr3highx6 + r0lowx4 = r0low * x4 + + h7 += r1highx4 + sr3highx4 = sr3high * x4 + + h6 += r1lowx4 + sr3lowx4 = sr3low * x4 + + h5 += r0highx4 + sr2highx4 = sr2high * x4 + + h4 += r0lowx4 + sr2lowx4 = sr2low * x4 + + h3 += sr3highx4 + r0lowx2 = r0low * x2 + + h2 += sr3lowx4 + r0highx2 = r0high * x2 + + h1 += sr2highx4 + r1lowx2 = r1low * x2 + + h0 += sr2lowx4 + r1highx2 = r1high * x2 + + h2 += r0lowx2 + r2lowx2 = r2low * x2 + + h3 += r0highx2 + r2highx2 = r2high * x2 + + h4 += r1lowx2 + sr3lowx2 = sr3low * x2 + + h5 += r1highx2 + sr3highx2 = sr3high * x2 + + h6 += r2lowx2 + + h7 += r2highx2 + + h0 += sr3lowx2 + + h1 += sr3highx2 + +nomorebytes: + + y7 = h7 + alpha130 + + y0 = h0 + alpha32 + + y1 = h1 + alpha32 + + y2 = h2 + alpha64 + + y7 -= alpha130 + + y3 = h3 + alpha64 + + y4 = h4 + alpha96 + + y5 = h5 + alpha96 + + x7 = h7 - y7 + y7 *= scale + + y0 -= alpha32 + + y1 -= alpha32 + + y2 -= alpha64 + + h6 += x7 + + y3 -= alpha64 + + y4 -= alpha96 + + y5 -= alpha96 + + y6 = h6 + alpha130 + + x0 = h0 - y0 + + x1 = h1 - y1 + + x2 = h2 - y2 + + y6 -= alpha130 + + x0 += y7 + + x3 = h3 - y3 + + x4 = h4 - y4 + + x5 = h5 - y5 + + x6 = h6 - y6 + + y6 *= scale + + x2 += y0 + + x3 += y1 + + x4 += y2 + + x0 += y6 + + x5 += y3 + + x6 += y4 + + x2 += x3 + + x0 += x1 + + x4 += x5 + + x6 += y5 + + x2 += offset1 + d1 = int64(math.Float64bits(x2)) + + x0 += offset0 + d0 = int64(math.Float64bits(x0)) + + x4 += offset2 + d2 = int64(math.Float64bits(x4)) + + x6 += offset3 + d3 = int64(math.Float64bits(x6)) + + f0 = uint64(d0) + + f1 = uint64(d1) + bits32 = math.MaxUint64 + + f2 = uint64(d2) + bits32 >>= 32 + + f3 = uint64(d3) + f = f0 >> 32 + + f0 &= bits32 + f &= 255 + + f1 += f + g0 = f0 + 5 + + g = g0 >> 32 + g0 &= bits32 + + f = f1 >> 32 + f1 &= bits32 + + f &= 255 + g1 = f1 + g + + g = g1 >> 32 + f2 += f + + f = f2 >> 32 + g1 &= bits32 + + f2 &= bits32 + f &= 255 + + f3 += f + g2 = f2 + g + + g = g2 >> 32 + g2 &= bits32 + + f4 = f3 >> 32 + f3 &= bits32 + + f4 &= 255 + g3 = f3 + g + + g = g3 >> 32 + g3 &= bits32 + + g4 = f4 + g + + g4 = g4 - 4 + s00 = uint32(s[0]) + + f = uint64(int64(g4) >> 63) + s01 = uint32(s[1]) + + f0 &= f + g0 &^= f + s02 = uint32(s[2]) + + f1 &= f + f0 |= g0 + s03 = uint32(s[3]) + + g1 &^= f + f2 &= f + s10 = uint32(s[4]) + + f3 &= f + g2 &^= f + s11 = uint32(s[5]) + + g3 &^= f + f1 |= g1 + s12 = uint32(s[6]) + + f2 |= g2 + f3 |= g3 + s13 = uint32(s[7]) + + s01 <<= 8 + f0 += uint64(s00) + s20 = uint32(s[8]) + + s02 <<= 16 + f0 += uint64(s01) + s21 = uint32(s[9]) + + s03 <<= 24 + f0 += uint64(s02) + s22 = uint32(s[10]) + + s11 <<= 8 + f1 += uint64(s10) + s23 = uint32(s[11]) + + s12 <<= 16 + f1 += uint64(s11) + s30 = uint32(s[12]) + + s13 <<= 24 + f1 += uint64(s12) + s31 = uint32(s[13]) + + f0 += uint64(s03) + f1 += uint64(s13) + s32 = uint32(s[14]) + + s21 <<= 8 + f2 += uint64(s20) + s33 = uint32(s[15]) + + s22 <<= 16 + f2 += uint64(s21) + + s23 <<= 24 + f2 += uint64(s22) + + s31 <<= 8 + f3 += uint64(s30) + + s32 <<= 16 + f3 += uint64(s31) + + s33 <<= 24 + f3 += uint64(s32) + + f2 += uint64(s23) + f3 += uint64(s33) + + out[0] = byte(f0) + f0 >>= 8 + out[1] = byte(f0) + f0 >>= 8 + out[2] = byte(f0) + f0 >>= 8 + out[3] = byte(f0) + f0 >>= 8 + f1 += f0 + + out[4] = byte(f1) + f1 >>= 8 + out[5] = byte(f1) + f1 >>= 8 + out[6] = byte(f1) + f1 >>= 8 + out[7] = byte(f1) + f1 >>= 8 + f2 += f1 + + out[8] = byte(f2) + f2 >>= 8 + out[9] = byte(f2) + f2 >>= 8 + out[10] = byte(f2) + f2 >>= 8 + out[11] = byte(f2) + f2 >>= 8 + f3 += f2 + + out[12] = byte(f3) + f3 >>= 8 + out[13] = byte(f3) + f3 >>= 8 + out[14] = byte(f3) + f3 >>= 8 + out[15] = byte(f3) +} diff --git a/external/boringssl/ssl/test/runner/prf.go b/external/boringssl/ssl/test/runner/prf.go new file mode 100644 index 0000000000..f1b26de08c --- /dev/null +++ b/external/boringssl/ssl/test/runner/prf.go @@ -0,0 +1,388 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package runner + +import ( + "crypto" + "crypto/hmac" + "crypto/md5" + "crypto/sha1" + "crypto/sha256" + "crypto/sha512" + "errors" + "hash" +) + +// Split a premaster secret in two as specified in RFC 4346, section 5. +func splitPreMasterSecret(secret []byte) (s1, s2 []byte) { + s1 = secret[0 : (len(secret)+1)/2] + s2 = secret[len(secret)/2:] + return +} + +// pHash implements the P_hash function, as defined in RFC 4346, section 5. +func pHash(result, secret, seed []byte, hash func() hash.Hash) { + h := hmac.New(hash, secret) + h.Write(seed) + a := h.Sum(nil) + + j := 0 + for j < len(result) { + h.Reset() + h.Write(a) + h.Write(seed) + b := h.Sum(nil) + todo := len(b) + if j+todo > len(result) { + todo = len(result) - j + } + copy(result[j:j+todo], b) + j += todo + + h.Reset() + h.Write(a) + a = h.Sum(nil) + } +} + +// prf10 implements the TLS 1.0 pseudo-random function, as defined in RFC 2246, section 5. +func prf10(result, secret, label, seed []byte) { + hashSHA1 := sha1.New + hashMD5 := md5.New + + labelAndSeed := make([]byte, len(label)+len(seed)) + copy(labelAndSeed, label) + copy(labelAndSeed[len(label):], seed) + + s1, s2 := splitPreMasterSecret(secret) + pHash(result, s1, labelAndSeed, hashMD5) + result2 := make([]byte, len(result)) + pHash(result2, s2, labelAndSeed, hashSHA1) + + for i, b := range result2 { + result[i] ^= b + } +} + +// prf12 implements the TLS 1.2 pseudo-random function, as defined in RFC 5246, section 5. +func prf12(hashFunc func() hash.Hash) func(result, secret, label, seed []byte) { + return func(result, secret, label, seed []byte) { + labelAndSeed := make([]byte, len(label)+len(seed)) + copy(labelAndSeed, label) + copy(labelAndSeed[len(label):], seed) + + pHash(result, secret, labelAndSeed, hashFunc) + } +} + +// prf30 implements the SSL 3.0 pseudo-random function, as defined in +// www.mozilla.org/projects/security/pki/nss/ssl/draft302.txt section 6. +func prf30(result, secret, label, seed []byte) { + hashSHA1 := sha1.New() + hashMD5 := md5.New() + + done := 0 + i := 0 + // RFC5246 section 6.3 says that the largest PRF output needed is 128 + // bytes. Since no more ciphersuites will be added to SSLv3, this will + // remain true. Each iteration gives us 16 bytes so 10 iterations will + // be sufficient. + var b [11]byte + for done < len(result) { + for j := 0; j <= i; j++ { + b[j] = 'A' + byte(i) + } + + hashSHA1.Reset() + hashSHA1.Write(b[:i+1]) + hashSHA1.Write(secret) + hashSHA1.Write(seed) + digest := hashSHA1.Sum(nil) + + hashMD5.Reset() + hashMD5.Write(secret) + hashMD5.Write(digest) + + done += copy(result[done:], hashMD5.Sum(nil)) + i++ + } +} + +const ( + tlsRandomLength = 32 // Length of a random nonce in TLS 1.1. + masterSecretLength = 48 // Length of a master secret in TLS 1.1. + finishedVerifyLength = 12 // Length of verify_data in a Finished message. +) + +var masterSecretLabel = []byte("master secret") +var extendedMasterSecretLabel = []byte("extended master secret") +var keyExpansionLabel = []byte("key expansion") +var clientFinishedLabel = []byte("client finished") +var serverFinishedLabel = []byte("server finished") +var channelIDLabel = []byte("TLS Channel ID signature\x00") +var channelIDResumeLabel = []byte("Resumption\x00") + +func prfForVersion(version uint16, suite *cipherSuite) func(result, secret, label, seed []byte) { + switch version { + case VersionSSL30: + return prf30 + case VersionTLS10, VersionTLS11: + return prf10 + case VersionTLS12: + if suite.flags&suiteSHA384 != 0 { + return prf12(sha512.New384) + } + return prf12(sha256.New) + default: + panic("unknown version") + } +} + +// masterFromPreMasterSecret generates the master secret from the pre-master +// secret. See http://tools.ietf.org/html/rfc5246#section-8.1 +func masterFromPreMasterSecret(version uint16, suite *cipherSuite, preMasterSecret, clientRandom, serverRandom []byte) []byte { + var seed [tlsRandomLength * 2]byte + copy(seed[0:len(clientRandom)], clientRandom) + copy(seed[len(clientRandom):], serverRandom) + masterSecret := make([]byte, masterSecretLength) + prfForVersion(version, suite)(masterSecret, preMasterSecret, masterSecretLabel, seed[0:]) + return masterSecret +} + +// extendedMasterFromPreMasterSecret generates the master secret from the +// pre-master secret when the Triple Handshake fix is in effect. See +// https://tools.ietf.org/html/rfc7627 +func extendedMasterFromPreMasterSecret(version uint16, suite *cipherSuite, preMasterSecret []byte, h finishedHash) []byte { + masterSecret := make([]byte, masterSecretLength) + prfForVersion(version, suite)(masterSecret, preMasterSecret, extendedMasterSecretLabel, h.Sum()) + return masterSecret +} + +// keysFromMasterSecret generates the connection keys from the master +// secret, given the lengths of the MAC key, cipher key and IV, as defined in +// RFC 2246, section 6.3. +func keysFromMasterSecret(version uint16, suite *cipherSuite, masterSecret, clientRandom, serverRandom []byte, macLen, keyLen, ivLen int) (clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV []byte) { + var seed [tlsRandomLength * 2]byte + copy(seed[0:len(clientRandom)], serverRandom) + copy(seed[len(serverRandom):], clientRandom) + + n := 2*macLen + 2*keyLen + 2*ivLen + keyMaterial := make([]byte, n) + prfForVersion(version, suite)(keyMaterial, masterSecret, keyExpansionLabel, seed[0:]) + clientMAC = keyMaterial[:macLen] + keyMaterial = keyMaterial[macLen:] + serverMAC = keyMaterial[:macLen] + keyMaterial = keyMaterial[macLen:] + clientKey = keyMaterial[:keyLen] + keyMaterial = keyMaterial[keyLen:] + serverKey = keyMaterial[:keyLen] + keyMaterial = keyMaterial[keyLen:] + clientIV = keyMaterial[:ivLen] + keyMaterial = keyMaterial[ivLen:] + serverIV = keyMaterial[:ivLen] + return +} + +// lookupTLSHash looks up the corresponding crypto.Hash for a given +// TLS hash identifier. +func lookupTLSHash(hash uint8) (crypto.Hash, error) { + switch hash { + case hashMD5: + return crypto.MD5, nil + case hashSHA1: + return crypto.SHA1, nil + case hashSHA224: + return crypto.SHA224, nil + case hashSHA256: + return crypto.SHA256, nil + case hashSHA384: + return crypto.SHA384, nil + case hashSHA512: + return crypto.SHA512, nil + default: + return 0, errors.New("tls: unsupported hash algorithm") + } +} + +func newFinishedHash(version uint16, cipherSuite *cipherSuite) finishedHash { + if version >= VersionTLS12 { + newHash := sha256.New + if cipherSuite.flags&suiteSHA384 != 0 { + newHash = sha512.New384 + } + + return finishedHash{newHash(), newHash(), nil, nil, []byte{}, version, prf12(newHash)} + } + return finishedHash{sha1.New(), sha1.New(), md5.New(), md5.New(), []byte{}, version, prf10} +} + +// A finishedHash calculates the hash of a set of handshake messages suitable +// for including in a Finished message. +type finishedHash struct { + client hash.Hash + server hash.Hash + + // Prior to TLS 1.2, an additional MD5 hash is required. + clientMD5 hash.Hash + serverMD5 hash.Hash + + // In TLS 1.2 (and SSL 3 for implementation convenience), a + // full buffer is required. + buffer []byte + + version uint16 + prf func(result, secret, label, seed []byte) +} + +func (h *finishedHash) Write(msg []byte) (n int, err error) { + h.client.Write(msg) + h.server.Write(msg) + + if h.version < VersionTLS12 { + h.clientMD5.Write(msg) + h.serverMD5.Write(msg) + } + + if h.buffer != nil { + h.buffer = append(h.buffer, msg...) + } + + return len(msg), nil +} + +func (h finishedHash) Sum() []byte { + if h.version >= VersionTLS12 { + return h.client.Sum(nil) + } + + out := make([]byte, 0, md5.Size+sha1.Size) + out = h.clientMD5.Sum(out) + return h.client.Sum(out) +} + +// finishedSum30 calculates the contents of the verify_data member of a SSLv3 +// Finished message given the MD5 and SHA1 hashes of a set of handshake +// messages. +func finishedSum30(md5, sha1 hash.Hash, masterSecret []byte, magic []byte) []byte { + md5.Write(magic) + md5.Write(masterSecret) + md5.Write(ssl30Pad1[:]) + md5Digest := md5.Sum(nil) + + md5.Reset() + md5.Write(masterSecret) + md5.Write(ssl30Pad2[:]) + md5.Write(md5Digest) + md5Digest = md5.Sum(nil) + + sha1.Write(magic) + sha1.Write(masterSecret) + sha1.Write(ssl30Pad1[:40]) + sha1Digest := sha1.Sum(nil) + + sha1.Reset() + sha1.Write(masterSecret) + sha1.Write(ssl30Pad2[:40]) + sha1.Write(sha1Digest) + sha1Digest = sha1.Sum(nil) + + ret := make([]byte, len(md5Digest)+len(sha1Digest)) + copy(ret, md5Digest) + copy(ret[len(md5Digest):], sha1Digest) + return ret +} + +var ssl3ClientFinishedMagic = [4]byte{0x43, 0x4c, 0x4e, 0x54} +var ssl3ServerFinishedMagic = [4]byte{0x53, 0x52, 0x56, 0x52} + +// clientSum returns the contents of the verify_data member of a client's +// Finished message. +func (h finishedHash) clientSum(masterSecret []byte) []byte { + if h.version == VersionSSL30 { + return finishedSum30(h.clientMD5, h.client, masterSecret, ssl3ClientFinishedMagic[:]) + } + + out := make([]byte, finishedVerifyLength) + h.prf(out, masterSecret, clientFinishedLabel, h.Sum()) + return out +} + +// serverSum returns the contents of the verify_data member of a server's +// Finished message. +func (h finishedHash) serverSum(masterSecret []byte) []byte { + if h.version == VersionSSL30 { + return finishedSum30(h.serverMD5, h.server, masterSecret, ssl3ServerFinishedMagic[:]) + } + + out := make([]byte, finishedVerifyLength) + h.prf(out, masterSecret, serverFinishedLabel, h.Sum()) + return out +} + +// selectClientCertSignatureAlgorithm returns a signatureAndHash to sign a +// client's CertificateVerify with, or an error if none can be found. +func (h finishedHash) selectClientCertSignatureAlgorithm(serverList, clientList []signatureAndHash, sigType uint8) (signatureAndHash, error) { + if h.version < VersionTLS12 { + // Nothing to negotiate before TLS 1.2. + return signatureAndHash{signature: sigType}, nil + } + + for _, v := range serverList { + if v.signature == sigType && isSupportedSignatureAndHash(v, clientList) { + return v, nil + } + } + return signatureAndHash{}, errors.New("tls: no supported signature algorithm found for signing client certificate") +} + +// hashForClientCertificate returns a digest, hash function, and TLS 1.2 hash +// id suitable for signing by a TLS client certificate. +func (h finishedHash) hashForClientCertificate(signatureAndHash signatureAndHash, masterSecret []byte) ([]byte, crypto.Hash, error) { + if h.version == VersionSSL30 { + if signatureAndHash.signature != signatureRSA { + return nil, 0, errors.New("tls: unsupported signature type for client certificate") + } + + md5Hash := md5.New() + md5Hash.Write(h.buffer) + sha1Hash := sha1.New() + sha1Hash.Write(h.buffer) + return finishedSum30(md5Hash, sha1Hash, masterSecret, nil), crypto.MD5SHA1, nil + } + if h.version >= VersionTLS12 { + hashAlg, err := lookupTLSHash(signatureAndHash.hash) + if err != nil { + return nil, 0, err + } + hash := hashAlg.New() + hash.Write(h.buffer) + return hash.Sum(nil), hashAlg, nil + } + if signatureAndHash.signature == signatureECDSA { + return h.server.Sum(nil), crypto.SHA1, nil + } + + return h.Sum(), crypto.MD5SHA1, nil +} + +// hashForChannelID returns the hash to be signed for TLS Channel +// ID. If a resumption, resumeHash has the previous handshake +// hash. Otherwise, it is nil. +func (h finishedHash) hashForChannelID(resumeHash []byte) []byte { + hash := sha256.New() + hash.Write(channelIDLabel) + if resumeHash != nil { + hash.Write(channelIDResumeLabel) + hash.Write(resumeHash) + } + hash.Write(h.server.Sum(nil)) + return hash.Sum(nil) +} + +// discardHandshakeBuffer is called when there is no more need to +// buffer the entirety of the handshake messages. +func (h *finishedHash) discardHandshakeBuffer() { + h.buffer = nil +} diff --git a/external/boringssl/ssl/test/runner/recordingconn.go b/external/boringssl/ssl/test/runner/recordingconn.go new file mode 100644 index 0000000000..dfc10c7b5d --- /dev/null +++ b/external/boringssl/ssl/test/runner/recordingconn.go @@ -0,0 +1,167 @@ +// Copyright (c) 2016, Google Inc. +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +package runner + +import ( + "bufio" + "encoding/hex" + "errors" + "fmt" + "io" + "net" + "strconv" + "strings" + "sync" +) + +type flowType int + +const ( + readFlow flowType = iota + writeFlow + specialFlow +) + +type flow struct { + flowType flowType + message string + data []byte +} + +// recordingConn is a net.Conn that records the traffic that passes through it. +// WriteTo can be used to produce output that can be later be loaded with +// ParseTestData. +type recordingConn struct { + net.Conn + sync.Mutex + flows []flow + isDatagram bool + local, peer string +} + +func (r *recordingConn) appendFlow(flowType flowType, message string, data []byte) { + r.Lock() + defer r.Unlock() + + if l := len(r.flows); flowType == specialFlow || r.isDatagram || l == 0 || r.flows[l-1].flowType != flowType { + buf := make([]byte, len(data)) + copy(buf, data) + r.flows = append(r.flows, flow{flowType, message, buf}) + } else { + r.flows[l-1].data = append(r.flows[l-1].data, data...) + } +} + +func (r *recordingConn) Read(b []byte) (n int, err error) { + if n, err = r.Conn.Read(b); n == 0 { + return + } + r.appendFlow(readFlow, "", b[:n]) + return +} + +func (r *recordingConn) Write(b []byte) (n int, err error) { + if n, err = r.Conn.Write(b); n == 0 { + return + } + r.appendFlow(writeFlow, "", b[:n]) + return +} + +// LogSpecial appends an entry to the record of type 'special'. +func (r *recordingConn) LogSpecial(message string, data []byte) { + r.appendFlow(specialFlow, message, data) +} + +// WriteTo writes hex dumps to w that contains the recorded traffic. +func (r *recordingConn) WriteTo(w io.Writer) { + fmt.Fprintf(w, ">>> runner is %s, shim is %s\n", r.local, r.peer) + for i, flow := range r.flows { + switch flow.flowType { + case readFlow: + fmt.Fprintf(w, ">>> Flow %d (%s to %s)\n", i+1, r.peer, r.local) + case writeFlow: + fmt.Fprintf(w, ">>> Flow %d (%s to %s)\n", i+1, r.local, r.peer) + case specialFlow: + fmt.Fprintf(w, ">>> Flow %d %q\n", i+1, flow.message) + } + + if flow.data != nil { + dumper := hex.Dumper(w) + dumper.Write(flow.data) + dumper.Close() + } + } +} + +func (r *recordingConn) Transcript() []byte { + var ret []byte + for _, flow := range r.flows { + if flow.flowType != writeFlow { + continue + } + ret = append(ret, flow.data...) + } + return ret +} + +func parseTestData(r io.Reader) (flows [][]byte, err error) { + var currentFlow []byte + + scanner := bufio.NewScanner(r) + for scanner.Scan() { + line := scanner.Text() + // If the line starts with ">>> " then it marks the beginning + // of a new flow. + if strings.HasPrefix(line, ">>> ") { + if len(currentFlow) > 0 || len(flows) > 0 { + flows = append(flows, currentFlow) + currentFlow = nil + } + continue + } + + // Otherwise the line is a line of hex dump that looks like: + // 00000170 fc f5 06 bf (...) |.....X{&?......!| + // (Some bytes have been omitted from the middle section.) + + if i := strings.IndexByte(line, ' '); i >= 0 { + line = line[i:] + } else { + return nil, errors.New("invalid test data") + } + + if i := strings.IndexByte(line, '|'); i >= 0 { + line = line[:i] + } else { + return nil, errors.New("invalid test data") + } + + hexBytes := strings.Fields(line) + for _, hexByte := range hexBytes { + val, err := strconv.ParseUint(hexByte, 16, 8) + if err != nil { + return nil, errors.New("invalid hex byte in test data: " + err.Error()) + } + currentFlow = append(currentFlow, byte(val)) + } + } + + if len(currentFlow) > 0 { + flows = append(flows, currentFlow) + } + + return flows, nil +} diff --git a/external/boringssl/ssl/test/runner/runner.go.REMOVED.git-id b/external/boringssl/ssl/test/runner/runner.go.REMOVED.git-id new file mode 100644 index 0000000000..ae16d42c0e --- /dev/null +++ b/external/boringssl/ssl/test/runner/runner.go.REMOVED.git-id @@ -0,0 +1 @@ +9cfba3a726c4bced014cbe9980f00cefba637625 \ No newline at end of file diff --git a/external/boringssl/ssl/test/runner/runner_test.go b/external/boringssl/ssl/test/runner/runner_test.go new file mode 100644 index 0000000000..1ba28e0e26 --- /dev/null +++ b/external/boringssl/ssl/test/runner/runner_test.go @@ -0,0 +1,21 @@ +// Copyright (c) 2016, Google Inc. +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +package runner + +import "testing" + +func TestAll(t *testing.T) { + main() +} diff --git a/external/boringssl/ssl/test/runner/test_output.go b/external/boringssl/ssl/test/runner/test_output.go new file mode 100644 index 0000000000..2112092eb9 --- /dev/null +++ b/external/boringssl/ssl/test/runner/test_output.go @@ -0,0 +1,79 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +package runner + +import ( + "encoding/json" + "os" + "time" +) + +// testOutput is a representation of Chromium's JSON test result format. See +// https://www.chromium.org/developers/the-json-test-results-format +type testOutput struct { + Version int `json:"version"` + Interrupted bool `json:"interrupted"` + PathDelimiter string `json:"path_delimiter"` + SecondsSinceEpoch float64 `json:"seconds_since_epoch"` + NumFailuresByType map[string]int `json:"num_failures_by_type"` + Tests map[string]testResult `json:"tests"` + allPassed bool +} + +type testResult struct { + Actual string `json:"actual"` + Expected string `json:"expected"` + IsUnexpected bool `json:"is_unexpected"` +} + +func newTestOutput() *testOutput { + return &testOutput{ + Version: 3, + PathDelimiter: ".", + SecondsSinceEpoch: float64(time.Now().UnixNano()) / float64(time.Second/time.Nanosecond), + NumFailuresByType: make(map[string]int), + Tests: make(map[string]testResult), + allPassed: true, + } +} + +func (t *testOutput) addResult(name, result string) { + if _, found := t.Tests[name]; found { + panic(name) + } + t.Tests[name] = testResult{ + Actual: result, + Expected: "PASS", + IsUnexpected: result != "PASS", + } + t.NumFailuresByType[result]++ + if result != "PASS" { + t.allPassed = false + } +} + +func (t *testOutput) writeTo(name string) error { + file, err := os.Create(name) + if err != nil { + return err + } + defer file.Close() + out, err := json.MarshalIndent(t, "", " ") + if err != nil { + return err + } + _, err = file.Write(out) + return err +} diff --git a/external/boringssl/ssl/test/runner/ticket.go b/external/boringssl/ssl/test/runner/ticket.go new file mode 100644 index 0000000000..e121c05fb2 --- /dev/null +++ b/external/boringssl/ssl/test/runner/ticket.go @@ -0,0 +1,221 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package runner + +import ( + "bytes" + "crypto/aes" + "crypto/cipher" + "crypto/hmac" + "crypto/sha256" + "crypto/subtle" + "errors" + "io" +) + +// sessionState contains the information that is serialized into a session +// ticket in order to later resume a connection. +type sessionState struct { + vers uint16 + cipherSuite uint16 + masterSecret []byte + handshakeHash []byte + certificates [][]byte + extendedMasterSecret bool +} + +func (s *sessionState) equal(i interface{}) bool { + s1, ok := i.(*sessionState) + if !ok { + return false + } + + if s.vers != s1.vers || + s.cipherSuite != s1.cipherSuite || + !bytes.Equal(s.masterSecret, s1.masterSecret) || + !bytes.Equal(s.handshakeHash, s1.handshakeHash) || + s.extendedMasterSecret != s1.extendedMasterSecret { + return false + } + + if len(s.certificates) != len(s1.certificates) { + return false + } + + for i := range s.certificates { + if !bytes.Equal(s.certificates[i], s1.certificates[i]) { + return false + } + } + + return true +} + +func (s *sessionState) marshal() []byte { + length := 2 + 2 + 2 + len(s.masterSecret) + 2 + len(s.handshakeHash) + 2 + for _, cert := range s.certificates { + length += 4 + len(cert) + } + length++ + + ret := make([]byte, length) + x := ret + x[0] = byte(s.vers >> 8) + x[1] = byte(s.vers) + x[2] = byte(s.cipherSuite >> 8) + x[3] = byte(s.cipherSuite) + x[4] = byte(len(s.masterSecret) >> 8) + x[5] = byte(len(s.masterSecret)) + x = x[6:] + copy(x, s.masterSecret) + x = x[len(s.masterSecret):] + + x[0] = byte(len(s.handshakeHash) >> 8) + x[1] = byte(len(s.handshakeHash)) + x = x[2:] + copy(x, s.handshakeHash) + x = x[len(s.handshakeHash):] + + x[0] = byte(len(s.certificates) >> 8) + x[1] = byte(len(s.certificates)) + x = x[2:] + + for _, cert := range s.certificates { + x[0] = byte(len(cert) >> 24) + x[1] = byte(len(cert) >> 16) + x[2] = byte(len(cert) >> 8) + x[3] = byte(len(cert)) + copy(x[4:], cert) + x = x[4+len(cert):] + } + + if s.extendedMasterSecret { + x[0] = 1 + } + x = x[1:] + + return ret +} + +func (s *sessionState) unmarshal(data []byte) bool { + if len(data) < 8 { + return false + } + + s.vers = uint16(data[0])<<8 | uint16(data[1]) + s.cipherSuite = uint16(data[2])<<8 | uint16(data[3]) + masterSecretLen := int(data[4])<<8 | int(data[5]) + data = data[6:] + if len(data) < masterSecretLen { + return false + } + + s.masterSecret = data[:masterSecretLen] + data = data[masterSecretLen:] + + if len(data) < 2 { + return false + } + + handshakeHashLen := int(data[0])<<8 | int(data[1]) + data = data[2:] + if len(data) < handshakeHashLen { + return false + } + + s.handshakeHash = data[:handshakeHashLen] + data = data[handshakeHashLen:] + + if len(data) < 2 { + return false + } + + numCerts := int(data[0])<<8 | int(data[1]) + data = data[2:] + + s.certificates = make([][]byte, numCerts) + for i := range s.certificates { + if len(data) < 4 { + return false + } + certLen := int(data[0])<<24 | int(data[1])<<16 | int(data[2])<<8 | int(data[3]) + data = data[4:] + if certLen < 0 { + return false + } + if len(data) < certLen { + return false + } + s.certificates[i] = data[:certLen] + data = data[certLen:] + } + + if len(data) < 1 { + return false + } + + s.extendedMasterSecret = false + if data[0] == 1 { + s.extendedMasterSecret = true + } + data = data[1:] + + if len(data) > 0 { + return false + } + + return true +} + +func (c *Conn) encryptTicket(state *sessionState) ([]byte, error) { + serialized := state.marshal() + encrypted := make([]byte, aes.BlockSize+len(serialized)+sha256.Size) + iv := encrypted[:aes.BlockSize] + macBytes := encrypted[len(encrypted)-sha256.Size:] + + if _, err := io.ReadFull(c.config.rand(), iv); err != nil { + return nil, err + } + block, err := aes.NewCipher(c.config.SessionTicketKey[:16]) + if err != nil { + return nil, errors.New("tls: failed to create cipher while encrypting ticket: " + err.Error()) + } + cipher.NewCTR(block, iv).XORKeyStream(encrypted[aes.BlockSize:], serialized) + + mac := hmac.New(sha256.New, c.config.SessionTicketKey[16:32]) + mac.Write(encrypted[:len(encrypted)-sha256.Size]) + mac.Sum(macBytes[:0]) + + return encrypted, nil +} + +func (c *Conn) decryptTicket(encrypted []byte) (*sessionState, bool) { + if len(encrypted) < aes.BlockSize+sha256.Size { + return nil, false + } + + iv := encrypted[:aes.BlockSize] + macBytes := encrypted[len(encrypted)-sha256.Size:] + + mac := hmac.New(sha256.New, c.config.SessionTicketKey[16:32]) + mac.Write(encrypted[:len(encrypted)-sha256.Size]) + expected := mac.Sum(nil) + + if subtle.ConstantTimeCompare(macBytes, expected) != 1 { + return nil, false + } + + block, err := aes.NewCipher(c.config.SessionTicketKey[:16]) + if err != nil { + return nil, false + } + ciphertext := encrypted[aes.BlockSize : len(encrypted)-sha256.Size] + plaintext := make([]byte, len(ciphertext)) + cipher.NewCTR(block, iv).XORKeyStream(plaintext, ciphertext) + + state := new(sessionState) + ok := state.unmarshal(plaintext) + return state, ok +} diff --git a/external/boringssl/ssl/test/runner/tls.go b/external/boringssl/ssl/test/runner/tls.go new file mode 100644 index 0000000000..24f9b1ec8e --- /dev/null +++ b/external/boringssl/ssl/test/runner/tls.go @@ -0,0 +1,279 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package tls partially implements TLS 1.2, as specified in RFC 5246. +package runner + +import ( + "crypto" + "crypto/ecdsa" + "crypto/rsa" + "crypto/x509" + "encoding/pem" + "errors" + "io/ioutil" + "net" + "strings" + "time" +) + +// Server returns a new TLS server side connection +// using conn as the underlying transport. +// The configuration config must be non-nil and must have +// at least one certificate. +func Server(conn net.Conn, config *Config) *Conn { + c := &Conn{conn: conn, config: config} + c.init() + return c +} + +// Client returns a new TLS client side connection +// using conn as the underlying transport. +// The config cannot be nil: users must set either ServerHostname or +// InsecureSkipVerify in the config. +func Client(conn net.Conn, config *Config) *Conn { + c := &Conn{conn: conn, config: config, isClient: true} + c.init() + return c +} + +// A listener implements a network listener (net.Listener) for TLS connections. +type listener struct { + net.Listener + config *Config +} + +// Accept waits for and returns the next incoming TLS connection. +// The returned connection c is a *tls.Conn. +func (l *listener) Accept() (c net.Conn, err error) { + c, err = l.Listener.Accept() + if err != nil { + return + } + c = Server(c, l.config) + return +} + +// NewListener creates a Listener which accepts connections from an inner +// Listener and wraps each connection with Server. +// The configuration config must be non-nil and must have +// at least one certificate. +func NewListener(inner net.Listener, config *Config) net.Listener { + l := new(listener) + l.Listener = inner + l.config = config + return l +} + +// Listen creates a TLS listener accepting connections on the +// given network address using net.Listen. +// The configuration config must be non-nil and must have +// at least one certificate. +func Listen(network, laddr string, config *Config) (net.Listener, error) { + if config == nil || len(config.Certificates) == 0 { + return nil, errors.New("tls.Listen: no certificates in configuration") + } + l, err := net.Listen(network, laddr) + if err != nil { + return nil, err + } + return NewListener(l, config), nil +} + +type timeoutError struct{} + +func (timeoutError) Error() string { return "tls: DialWithDialer timed out" } +func (timeoutError) Timeout() bool { return true } +func (timeoutError) Temporary() bool { return true } + +// DialWithDialer connects to the given network address using dialer.Dial and +// then initiates a TLS handshake, returning the resulting TLS connection. Any +// timeout or deadline given in the dialer apply to connection and TLS +// handshake as a whole. +// +// DialWithDialer interprets a nil configuration as equivalent to the zero +// configuration; see the documentation of Config for the defaults. +func DialWithDialer(dialer *net.Dialer, network, addr string, config *Config) (*Conn, error) { + // We want the Timeout and Deadline values from dialer to cover the + // whole process: TCP connection and TLS handshake. This means that we + // also need to start our own timers now. + timeout := dialer.Timeout + + if !dialer.Deadline.IsZero() { + deadlineTimeout := dialer.Deadline.Sub(time.Now()) + if timeout == 0 || deadlineTimeout < timeout { + timeout = deadlineTimeout + } + } + + var errChannel chan error + + if timeout != 0 { + errChannel = make(chan error, 2) + time.AfterFunc(timeout, func() { + errChannel <- timeoutError{} + }) + } + + rawConn, err := dialer.Dial(network, addr) + if err != nil { + return nil, err + } + + colonPos := strings.LastIndex(addr, ":") + if colonPos == -1 { + colonPos = len(addr) + } + hostname := addr[:colonPos] + + if config == nil { + config = defaultConfig() + } + // If no ServerName is set, infer the ServerName + // from the hostname we're connecting to. + if config.ServerName == "" { + // Make a copy to avoid polluting argument or default. + c := *config + c.ServerName = hostname + config = &c + } + + conn := Client(rawConn, config) + + if timeout == 0 { + err = conn.Handshake() + } else { + go func() { + errChannel <- conn.Handshake() + }() + + err = <-errChannel + } + + if err != nil { + rawConn.Close() + return nil, err + } + + return conn, nil +} + +// Dial connects to the given network address using net.Dial +// and then initiates a TLS handshake, returning the resulting +// TLS connection. +// Dial interprets a nil configuration as equivalent to +// the zero configuration; see the documentation of Config +// for the defaults. +func Dial(network, addr string, config *Config) (*Conn, error) { + return DialWithDialer(new(net.Dialer), network, addr, config) +} + +// LoadX509KeyPair reads and parses a public/private key pair from a pair of +// files. The files must contain PEM encoded data. +func LoadX509KeyPair(certFile, keyFile string) (cert Certificate, err error) { + certPEMBlock, err := ioutil.ReadFile(certFile) + if err != nil { + return + } + keyPEMBlock, err := ioutil.ReadFile(keyFile) + if err != nil { + return + } + return X509KeyPair(certPEMBlock, keyPEMBlock) +} + +// X509KeyPair parses a public/private key pair from a pair of +// PEM encoded data. +func X509KeyPair(certPEMBlock, keyPEMBlock []byte) (cert Certificate, err error) { + var certDERBlock *pem.Block + for { + certDERBlock, certPEMBlock = pem.Decode(certPEMBlock) + if certDERBlock == nil { + break + } + if certDERBlock.Type == "CERTIFICATE" { + cert.Certificate = append(cert.Certificate, certDERBlock.Bytes) + } + } + + if len(cert.Certificate) == 0 { + err = errors.New("crypto/tls: failed to parse certificate PEM data") + return + } + + var keyDERBlock *pem.Block + for { + keyDERBlock, keyPEMBlock = pem.Decode(keyPEMBlock) + if keyDERBlock == nil { + err = errors.New("crypto/tls: failed to parse key PEM data") + return + } + if keyDERBlock.Type == "PRIVATE KEY" || strings.HasSuffix(keyDERBlock.Type, " PRIVATE KEY") { + break + } + } + + cert.PrivateKey, err = parsePrivateKey(keyDERBlock.Bytes) + if err != nil { + return + } + + // We don't need to parse the public key for TLS, but we so do anyway + // to check that it looks sane and matches the private key. + x509Cert, err := x509.ParseCertificate(cert.Certificate[0]) + if err != nil { + return + } + + switch pub := x509Cert.PublicKey.(type) { + case *rsa.PublicKey: + priv, ok := cert.PrivateKey.(*rsa.PrivateKey) + if !ok { + err = errors.New("crypto/tls: private key type does not match public key type") + return + } + if pub.N.Cmp(priv.N) != 0 { + err = errors.New("crypto/tls: private key does not match public key") + return + } + case *ecdsa.PublicKey: + priv, ok := cert.PrivateKey.(*ecdsa.PrivateKey) + if !ok { + err = errors.New("crypto/tls: private key type does not match public key type") + return + + } + if pub.X.Cmp(priv.X) != 0 || pub.Y.Cmp(priv.Y) != 0 { + err = errors.New("crypto/tls: private key does not match public key") + return + } + default: + err = errors.New("crypto/tls: unknown public key algorithm") + return + } + + return +} + +// Attempt to parse the given private key DER block. OpenSSL 0.9.8 generates +// PKCS#1 private keys by default, while OpenSSL 1.0.0 generates PKCS#8 keys. +// OpenSSL ecparam generates SEC1 EC private keys for ECDSA. We try all three. +func parsePrivateKey(der []byte) (crypto.PrivateKey, error) { + if key, err := x509.ParsePKCS1PrivateKey(der); err == nil { + return key, nil + } + if key, err := x509.ParsePKCS8PrivateKey(der); err == nil { + switch key := key.(type) { + case *rsa.PrivateKey, *ecdsa.PrivateKey: + return key, nil + default: + return nil, errors.New("crypto/tls: found unknown private key type in PKCS#8 wrapping") + } + } + if key, err := x509.ParseECPrivateKey(der); err == nil { + return key, nil + } + + return nil, errors.New("crypto/tls: failed to parse private key") +} diff --git a/external/boringssl/ssl/test/scoped_types.h b/external/boringssl/ssl/test/scoped_types.h new file mode 100644 index 0000000000..7e92ceeda4 --- /dev/null +++ b/external/boringssl/ssl/test/scoped_types.h @@ -0,0 +1,28 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_SSL_TEST_SCOPED_TYPES_H +#define OPENSSL_HEADER_SSL_TEST_SCOPED_TYPES_H + +#include + +#include "../../crypto/test/scoped_types.h" + + +using ScopedSSL = ScopedOpenSSLType; +using ScopedSSL_CTX = ScopedOpenSSLType; +using ScopedSSL_SESSION = ScopedOpenSSLType; + + +#endif // OPENSSL_HEADER_SSL_TEST_SCOPED_TYPES_H diff --git a/external/boringssl/ssl/test/test_config.cc b/external/boringssl/ssl/test/test_config.cc new file mode 100644 index 0000000000..536978b690 --- /dev/null +++ b/external/boringssl/ssl/test/test_config.cc @@ -0,0 +1,215 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include "test_config.h" + +#include +#include +#include + +#include + +#include + +namespace { + +template +struct Flag { + const char *flag; + T TestConfig::*member; +}; + +// FindField looks for the flag in |flags| that matches |flag|. If one is found, +// it returns a pointer to the corresponding field in |config|. Otherwise, it +// returns NULL. +template +T *FindField(TestConfig *config, const Flag (&flags)[N], const char *flag) { + for (size_t i = 0; i < N; i++) { + if (strcmp(flag, flags[i].flag) == 0) { + return &(config->*(flags[i].member)); + } + } + return NULL; +} + +const Flag kBoolFlags[] = { + { "-server", &TestConfig::is_server }, + { "-dtls", &TestConfig::is_dtls }, + { "-resume", &TestConfig::resume }, + { "-fallback-scsv", &TestConfig::fallback_scsv }, + { "-require-any-client-certificate", + &TestConfig::require_any_client_certificate }, + { "-false-start", &TestConfig::false_start }, + { "-async", &TestConfig::async }, + { "-write-different-record-sizes", + &TestConfig::write_different_record_sizes }, + { "-cbc-record-splitting", &TestConfig::cbc_record_splitting }, + { "-partial-write", &TestConfig::partial_write }, + { "-no-tls13", &TestConfig::no_tls13 }, + { "-no-tls12", &TestConfig::no_tls12 }, + { "-no-tls11", &TestConfig::no_tls11 }, + { "-no-tls1", &TestConfig::no_tls1 }, + { "-no-ssl3", &TestConfig::no_ssl3 }, + { "-shim-writes-first", &TestConfig::shim_writes_first }, + { "-expect-session-miss", &TestConfig::expect_session_miss }, + { "-decline-alpn", &TestConfig::decline_alpn }, + { "-expect-extended-master-secret", + &TestConfig::expect_extended_master_secret }, + { "-enable-ocsp-stapling", &TestConfig::enable_ocsp_stapling }, + { "-enable-signed-cert-timestamps", + &TestConfig::enable_signed_cert_timestamps }, + { "-implicit-handshake", &TestConfig::implicit_handshake }, + { "-use-early-callback", &TestConfig::use_early_callback }, + { "-fail-early-callback", &TestConfig::fail_early_callback }, + { "-install-ddos-callback", &TestConfig::install_ddos_callback }, + { "-fail-ddos-callback", &TestConfig::fail_ddos_callback }, + { "-fail-second-ddos-callback", &TestConfig::fail_second_ddos_callback }, + { "-handshake-never-done", &TestConfig::handshake_never_done }, + { "-use-export-context", &TestConfig::use_export_context }, + { "-tls-unique", &TestConfig::tls_unique }, + { "-expect-ticket-renewal", &TestConfig::expect_ticket_renewal }, + { "-expect-no-session", &TestConfig::expect_no_session }, + { "-use-ticket-callback", &TestConfig::use_ticket_callback }, + { "-renew-ticket", &TestConfig::renew_ticket }, + { "-enable-client-custom-extension", + &TestConfig::enable_client_custom_extension }, + { "-enable-server-custom-extension", + &TestConfig::enable_server_custom_extension }, + { "-custom-extension-skip", &TestConfig::custom_extension_skip }, + { "-custom-extension-fail-add", &TestConfig::custom_extension_fail_add }, + { "-check-close-notify", &TestConfig::check_close_notify }, + { "-shim-shuts-down", &TestConfig::shim_shuts_down }, + { "-verify-fail", &TestConfig::verify_fail }, + { "-verify-peer", &TestConfig::verify_peer }, + { "-expect-verify-result", &TestConfig::expect_verify_result }, + { "-renegotiate-once", &TestConfig::renegotiate_once }, + { "-renegotiate-freely", &TestConfig::renegotiate_freely }, + { "-renegotiate-ignore", &TestConfig::renegotiate_ignore }, + { "-disable-npn", &TestConfig::disable_npn }, + { "-p384-only", &TestConfig::p384_only }, + { "-enable-all-curves", &TestConfig::enable_all_curves }, + { "-use-sparse-dh-prime", &TestConfig::use_sparse_dh_prime }, + { "-use-old-client-cert-callback", + &TestConfig::use_old_client_cert_callback }, +}; + +const Flag kStringFlags[] = { + { "-digest-prefs", &TestConfig::digest_prefs }, + { "-key-file", &TestConfig::key_file }, + { "-cert-file", &TestConfig::cert_file }, + { "-expect-server-name", &TestConfig::expected_server_name }, + { "-advertise-npn", &TestConfig::advertise_npn }, + { "-expect-next-proto", &TestConfig::expected_next_proto }, + { "-select-next-proto", &TestConfig::select_next_proto }, + { "-send-channel-id", &TestConfig::send_channel_id }, + { "-host-name", &TestConfig::host_name }, + { "-advertise-alpn", &TestConfig::advertise_alpn }, + { "-expect-alpn", &TestConfig::expected_alpn }, + { "-expect-advertised-alpn", &TestConfig::expected_advertised_alpn }, + { "-select-alpn", &TestConfig::select_alpn }, + { "-psk", &TestConfig::psk }, + { "-psk-identity", &TestConfig::psk_identity }, + { "-srtp-profiles", &TestConfig::srtp_profiles }, + { "-cipher", &TestConfig::cipher }, + { "-cipher-tls10", &TestConfig::cipher_tls10 }, + { "-cipher-tls11", &TestConfig::cipher_tls11 }, + { "-export-label", &TestConfig::export_label }, + { "-export-context", &TestConfig::export_context }, +}; + +const Flag kBase64Flags[] = { + { "-expect-certificate-types", &TestConfig::expected_certificate_types }, + { "-expect-channel-id", &TestConfig::expected_channel_id }, + { "-expect-ocsp-response", &TestConfig::expected_ocsp_response }, + { "-expect-signed-cert-timestamps", + &TestConfig::expected_signed_cert_timestamps }, + { "-ocsp-response", &TestConfig::ocsp_response }, + { "-signed-cert-timestamps", &TestConfig::signed_cert_timestamps }, +}; + +const Flag kIntFlags[] = { + { "-port", &TestConfig::port }, + { "-min-version", &TestConfig::min_version }, + { "-max-version", &TestConfig::max_version }, + { "-mtu", &TestConfig::mtu }, + { "-export-keying-material", &TestConfig::export_keying_material }, + { "-expect-total-renegotiations", &TestConfig::expect_total_renegotiations }, + { "-expect-server-key-exchange-hash", + &TestConfig::expect_server_key_exchange_hash }, + { "-expect-key-exchange-info", + &TestConfig::expect_key_exchange_info }, + { "-initial-timeout-duration-ms", &TestConfig::initial_timeout_duration_ms }, +}; + +} // namespace + +bool ParseConfig(int argc, char **argv, TestConfig *out_config) { + for (int i = 0; i < argc; i++) { + bool *bool_field = FindField(out_config, kBoolFlags, argv[i]); + if (bool_field != NULL) { + *bool_field = true; + continue; + } + + std::string *string_field = FindField(out_config, kStringFlags, argv[i]); + if (string_field != NULL) { + i++; + if (i >= argc) { + fprintf(stderr, "Missing parameter\n"); + return false; + } + string_field->assign(argv[i]); + continue; + } + + std::string *base64_field = FindField(out_config, kBase64Flags, argv[i]); + if (base64_field != NULL) { + i++; + if (i >= argc) { + fprintf(stderr, "Missing parameter\n"); + return false; + } + size_t len; + if (!EVP_DecodedLength(&len, strlen(argv[i]))) { + fprintf(stderr, "Invalid base64: %s\n", argv[i]); + return false; + } + std::unique_ptr decoded(new uint8_t[len]); + if (!EVP_DecodeBase64(decoded.get(), &len, len, + reinterpret_cast(argv[i]), + strlen(argv[i]))) { + fprintf(stderr, "Invalid base64: %s\n", argv[i]); + return false; + } + base64_field->assign(reinterpret_cast(decoded.get()), len); + continue; + } + + int *int_field = FindField(out_config, kIntFlags, argv[i]); + if (int_field) { + i++; + if (i >= argc) { + fprintf(stderr, "Missing parameter\n"); + return false; + } + *int_field = atoi(argv[i]); + continue; + } + + fprintf(stderr, "Unknown argument: %s\n", argv[i]); + return false; + } + + return true; +} diff --git a/external/boringssl/ssl/test/test_config.h b/external/boringssl/ssl/test/test_config.h new file mode 100644 index 0000000000..aff194ef42 --- /dev/null +++ b/external/boringssl/ssl/test/test_config.h @@ -0,0 +1,114 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef HEADER_TEST_CONFIG +#define HEADER_TEST_CONFIG + +#include + + +struct TestConfig { + int port = 0; + bool is_server = false; + bool is_dtls = false; + bool resume = false; + bool fallback_scsv = false; + std::string digest_prefs; + std::string key_file; + std::string cert_file; + std::string expected_server_name; + std::string expected_certificate_types; + bool require_any_client_certificate = false; + std::string advertise_npn; + std::string expected_next_proto; + bool false_start = false; + std::string select_next_proto; + bool async = false; + bool write_different_record_sizes = false; + bool cbc_record_splitting = false; + bool partial_write = false; + bool no_tls13 = false; + bool no_tls12 = false; + bool no_tls11 = false; + bool no_tls1 = false; + bool no_ssl3 = false; + std::string expected_channel_id; + std::string send_channel_id; + bool shim_writes_first = false; + std::string host_name; + std::string advertise_alpn; + std::string expected_alpn; + std::string expected_advertised_alpn; + std::string select_alpn; + bool decline_alpn = false; + bool expect_session_miss = false; + bool expect_extended_master_secret = false; + std::string psk; + std::string psk_identity; + std::string srtp_profiles; + bool enable_ocsp_stapling = false; + std::string expected_ocsp_response; + bool enable_signed_cert_timestamps = false; + std::string expected_signed_cert_timestamps; + int min_version = 0; + int max_version = 0; + int mtu = 0; + bool implicit_handshake = false; + bool use_early_callback = false; + bool fail_early_callback = false; + bool install_ddos_callback = false; + bool fail_ddos_callback = false; + bool fail_second_ddos_callback = false; + std::string cipher; + std::string cipher_tls10; + std::string cipher_tls11; + bool handshake_never_done = false; + int export_keying_material = 0; + std::string export_label; + std::string export_context; + bool use_export_context = false; + bool tls_unique = false; + bool expect_ticket_renewal = false; + bool expect_no_session = false; + bool use_ticket_callback = false; + bool renew_ticket = false; + bool enable_client_custom_extension = false; + bool enable_server_custom_extension = false; + bool custom_extension_skip = false; + bool custom_extension_fail_add = false; + std::string ocsp_response; + bool check_close_notify = false; + bool shim_shuts_down = false; + bool verify_fail = false; + bool verify_peer = false; + bool expect_verify_result = false; + std::string signed_cert_timestamps; + int expect_total_renegotiations = 0; + bool renegotiate_once = false; + bool renegotiate_freely = false; + bool renegotiate_ignore = false; + bool disable_npn = false; + int expect_server_key_exchange_hash = 0; + bool p384_only = false; + bool enable_all_curves = false; + bool use_sparse_dh_prime = false; + int expect_key_exchange_info = 0; + bool use_old_client_cert_callback = false; + int initial_timeout_duration_ms = 0; +}; + +bool ParseConfig(int argc, char **argv, TestConfig *out_config); + + +#endif // HEADER_TEST_CONFIG diff --git a/external/boringssl/ssl/tls_record.c b/external/boringssl/ssl/tls_record.c new file mode 100644 index 0000000000..e1553e3236 --- /dev/null +++ b/external/boringssl/ssl/tls_record.c @@ -0,0 +1,471 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include + +#include +#include +#include + +#include "internal.h" +#include "../crypto/internal.h" + + +/* kMaxEmptyRecords is the number of consecutive, empty records that will be + * processed. Without this limit an attacker could send empty records at a + * faster rate than we can process and cause record processing to loop + * forever. */ +static const uint8_t kMaxEmptyRecords = 32; + +/* kMaxWarningAlerts is the number of consecutive warning alerts that will be + * processed. */ +static const uint8_t kMaxWarningAlerts = 4; + +/* ssl_needs_record_splitting returns one if |ssl|'s current outgoing cipher + * state needs record-splitting and zero otherwise. */ +static int ssl_needs_record_splitting(const SSL *ssl) { + return ssl->s3->aead_write_ctx != NULL && + ssl3_protocol_version(ssl) < TLS1_1_VERSION && + (ssl->mode & SSL_MODE_CBC_RECORD_SPLITTING) != 0 && + SSL_CIPHER_is_block_cipher(ssl->s3->aead_write_ctx->cipher); +} + +int ssl_record_sequence_update(uint8_t *seq, size_t seq_len) { + size_t i; + for (i = seq_len - 1; i < seq_len; i--) { + ++seq[i]; + if (seq[i] != 0) { + return 1; + } + } + OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW); + return 0; +} + +size_t ssl_record_prefix_len(const SSL *ssl) { + if (SSL_IS_DTLS(ssl)) { + return DTLS1_RT_HEADER_LENGTH + + SSL_AEAD_CTX_explicit_nonce_len(ssl->s3->aead_read_ctx); + } else { + return SSL3_RT_HEADER_LENGTH + + SSL_AEAD_CTX_explicit_nonce_len(ssl->s3->aead_read_ctx); + } +} + +size_t ssl_seal_align_prefix_len(const SSL *ssl) { + if (SSL_IS_DTLS(ssl)) { + return DTLS1_RT_HEADER_LENGTH + + SSL_AEAD_CTX_explicit_nonce_len(ssl->s3->aead_write_ctx); + } else { + size_t ret = SSL3_RT_HEADER_LENGTH + + SSL_AEAD_CTX_explicit_nonce_len(ssl->s3->aead_write_ctx); + if (ssl_needs_record_splitting(ssl)) { + ret += SSL3_RT_HEADER_LENGTH; + ret += ssl_cipher_get_record_split_len(ssl->s3->aead_write_ctx->cipher); + } + return ret; + } +} + +size_t ssl_max_seal_overhead(const SSL *ssl) { + size_t ret = SSL_AEAD_CTX_max_overhead(ssl->s3->aead_write_ctx); + if (SSL_IS_DTLS(ssl)) { + ret += DTLS1_RT_HEADER_LENGTH; + } else { + ret += SSL3_RT_HEADER_LENGTH; + } + /* TLS 1.3 needs an extra byte for the encrypted record type. */ + if (ssl->s3->have_version && + ssl3_protocol_version(ssl) >= TLS1_3_VERSION) { + ret += 1; + } + if (!SSL_IS_DTLS(ssl) && ssl_needs_record_splitting(ssl)) { + ret *= 2; + } + return ret; +} + +enum ssl_open_record_t tls_open_record(SSL *ssl, uint8_t *out_type, CBS *out, + size_t *out_consumed, uint8_t *out_alert, + uint8_t *in, size_t in_len) { + *out_consumed = 0; + + CBS cbs; + CBS_init(&cbs, in, in_len); + + /* Decode the record header. */ + uint8_t type; + uint16_t version, ciphertext_len; + if (!CBS_get_u8(&cbs, &type) || + !CBS_get_u16(&cbs, &version) || + !CBS_get_u16(&cbs, &ciphertext_len)) { + *out_consumed = SSL3_RT_HEADER_LENGTH; + return ssl_open_record_partial; + } + + /* Check that the major version in the record matches. As of TLS 1.3, the + * minor version is no longer checked. */ + if ((version >> 8) != SSL3_VERSION_MAJOR) { + OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_VERSION_NUMBER); + *out_alert = SSL_AD_PROTOCOL_VERSION; + return ssl_open_record_error; + } + + /* Check the ciphertext length. */ + if (ciphertext_len > SSL3_RT_MAX_ENCRYPTED_LENGTH) { + OPENSSL_PUT_ERROR(SSL, SSL_R_ENCRYPTED_LENGTH_TOO_LONG); + *out_alert = SSL_AD_RECORD_OVERFLOW; + return ssl_open_record_error; + } + + /* Extract the body. */ + CBS body; + if (!CBS_get_bytes(&cbs, &body, ciphertext_len)) { + *out_consumed = SSL3_RT_HEADER_LENGTH + (size_t)ciphertext_len; + return ssl_open_record_partial; + } + + ssl_do_msg_callback(ssl, 0 /* read */, 0, SSL3_RT_HEADER, in, + SSL3_RT_HEADER_LENGTH); + + /* Decrypt the body in-place. */ + if (!SSL_AEAD_CTX_open(ssl->s3->aead_read_ctx, out, type, version, + ssl->s3->read_sequence, (uint8_t *)CBS_data(&body), + CBS_len(&body))) { + OPENSSL_PUT_ERROR(SSL, SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC); + *out_alert = SSL_AD_BAD_RECORD_MAC; + return ssl_open_record_error; + } + *out_consumed = in_len - CBS_len(&cbs); + + if (!ssl_record_sequence_update(ssl->s3->read_sequence, 8)) { + *out_alert = SSL_AD_INTERNAL_ERROR; + return ssl_open_record_error; + } + + /* TLS 1.3 hides the record type inside the encrypted data. */ + if (ssl->s3->have_version && + ssl3_protocol_version(ssl) >= TLS1_3_VERSION && + ssl->s3->aead_read_ctx != NULL) { + do { + if (!CBS_get_last_u8(out, &type)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC); + *out_alert = SSL_AD_DECRYPT_ERROR; + return ssl_open_record_error; + } + } while (type == 0); + } + + /* Check the plaintext length. */ + if (CBS_len(out) > SSL3_RT_MAX_PLAIN_LENGTH) { + OPENSSL_PUT_ERROR(SSL, SSL_R_DATA_LENGTH_TOO_LONG); + *out_alert = SSL_AD_RECORD_OVERFLOW; + return ssl_open_record_error; + } + + /* Limit the number of consecutive empty records. */ + if (CBS_len(out) == 0) { + ssl->s3->empty_record_count++; + if (ssl->s3->empty_record_count > kMaxEmptyRecords) { + OPENSSL_PUT_ERROR(SSL, SSL_R_TOO_MANY_EMPTY_FRAGMENTS); + *out_alert = SSL_AD_UNEXPECTED_MESSAGE; + return ssl_open_record_error; + } + /* Apart from the limit, empty records are returned up to the caller. This + * allows the caller to reject records of the wrong type. */ + } else { + ssl->s3->empty_record_count = 0; + } + + if (type == SSL3_RT_ALERT) { + return ssl_process_alert(ssl, out_alert, CBS_data(out), CBS_len(out)); + } + + ssl->s3->warning_alert_count = 0; + + *out_type = type; + return ssl_open_record_success; +} + +static int do_seal_record(SSL *ssl, uint8_t *out, size_t *out_len, + size_t max_out, uint8_t type, const uint8_t *in, + size_t in_len) { + if (max_out < SSL3_RT_HEADER_LENGTH) { + OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFER_TOO_SMALL); + return 0; + } + + /* Either |in| and |out| don't alias or |in| aligns with the + * ciphertext. |tls_seal_record| forbids aliasing, but TLS 1.3 aliases them + * internally. */ + assert(!buffers_alias(in, in_len, out, max_out) || + in == + out + SSL3_RT_HEADER_LENGTH + + SSL_AEAD_CTX_explicit_nonce_len(ssl->s3->aead_write_ctx)); + + out[0] = type; + + /* The TLS record-layer version number is meaningless and, starting in + * TLS 1.3, is frozen at TLS 1.0. But for historical reasons, SSL 3.0 + * ClientHellos should use SSL 3.0 and pre-TLS-1.3 expects the version + * to change after version negotiation. */ + uint16_t wire_version = TLS1_VERSION; + if (ssl->version == SSL3_VERSION || + (ssl->s3->have_version && ssl3_protocol_version(ssl) < TLS1_3_VERSION)) { + wire_version = ssl->version; + } + out[1] = wire_version >> 8; + out[2] = wire_version & 0xff; + + size_t ciphertext_len; + if (!SSL_AEAD_CTX_seal(ssl->s3->aead_write_ctx, out + SSL3_RT_HEADER_LENGTH, + &ciphertext_len, max_out - SSL3_RT_HEADER_LENGTH, + type, wire_version, ssl->s3->write_sequence, in, + in_len) || + !ssl_record_sequence_update(ssl->s3->write_sequence, 8)) { + return 0; + } + + if (ciphertext_len >= 1 << 16) { + OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW); + return 0; + } + out[3] = ciphertext_len >> 8; + out[4] = ciphertext_len & 0xff; + + *out_len = SSL3_RT_HEADER_LENGTH + ciphertext_len; + + ssl_do_msg_callback(ssl, 1 /* write */, 0, SSL3_RT_HEADER, out, + SSL3_RT_HEADER_LENGTH); + return 1; +} + +int tls_seal_record(SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out, + uint8_t type, const uint8_t *in, size_t in_len) { + if (buffers_alias(in, in_len, out, max_out)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_OUTPUT_ALIASES_INPUT); + return 0; + } + + size_t frag_len = 0; + + /* TLS 1.3 hides the actual record type inside the encrypted data. */ + if (ssl->s3->have_version && + ssl3_protocol_version(ssl) >= TLS1_3_VERSION && + ssl->s3->aead_read_ctx != NULL) { + size_t padding = SSL3_RT_HEADER_LENGTH + 1; + + if (in_len > in_len + padding || max_out < in_len + padding) { + OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFER_TOO_SMALL); + return 0; + } + + memmove(out + SSL3_RT_HEADER_LENGTH, in, in_len); + out[SSL3_RT_HEADER_LENGTH + in_len] = type; + in = out + SSL3_RT_HEADER_LENGTH; + type = SSL3_RT_APPLICATION_DATA; + in_len++; + } + + if (type == SSL3_RT_APPLICATION_DATA && in_len > 1 && + ssl_needs_record_splitting(ssl)) { + if (!do_seal_record(ssl, out, &frag_len, max_out, type, in, 1)) { + return 0; + } + in++; + in_len--; + out += frag_len; + max_out -= frag_len; + +#if !defined(BORINGSSL_UNSAFE_FUZZER_MODE) + assert(SSL3_RT_HEADER_LENGTH + ssl_cipher_get_record_split_len( + ssl->s3->aead_write_ctx->cipher) == + frag_len); +#endif + } + + if (!do_seal_record(ssl, out, out_len, max_out, type, in, in_len)) { + return 0; + } + *out_len += frag_len; + return 1; +} + +void ssl_set_read_state(SSL *ssl, SSL_AEAD_CTX *aead_ctx) { + if (SSL_IS_DTLS(ssl)) { + ssl->d1->r_epoch++; + memset(&ssl->d1->bitmap, 0, sizeof(ssl->d1->bitmap)); + } + memset(ssl->s3->read_sequence, 0, sizeof(ssl->s3->read_sequence)); + + SSL_AEAD_CTX_free(ssl->s3->aead_read_ctx); + ssl->s3->aead_read_ctx = aead_ctx; +} + +void ssl_set_write_state(SSL *ssl, SSL_AEAD_CTX *aead_ctx) { + if (SSL_IS_DTLS(ssl)) { + ssl->d1->w_epoch++; + memcpy(ssl->d1->last_write_sequence, ssl->s3->write_sequence, + sizeof(ssl->s3->write_sequence)); + } + memset(ssl->s3->write_sequence, 0, sizeof(ssl->s3->write_sequence)); + + SSL_AEAD_CTX_free(ssl->s3->aead_write_ctx); + ssl->s3->aead_write_ctx = aead_ctx; +} + +enum ssl_open_record_t ssl_process_alert(SSL *ssl, uint8_t *out_alert, + const uint8_t *in, size_t in_len) { + /* Alerts records may not contain fragmented or multiple alerts. */ + if (in_len != 2) { + *out_alert = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ALERT); + return ssl_open_record_error; + } + + ssl_do_msg_callback(ssl, 0 /* read */, ssl->version, SSL3_RT_ALERT, in, in_len); + + const uint8_t alert_level = in[0]; + const uint8_t alert_descr = in[1]; + + uint16_t alert = (alert_level << 8) | alert_descr; + ssl_do_info_callback(ssl, SSL_CB_READ_ALERT, alert); + + if (alert_level == SSL3_AL_WARNING) { + if (alert_descr == SSL_AD_CLOSE_NOTIFY) { + ssl->s3->recv_shutdown = ssl_shutdown_close_notify; + return ssl_open_record_close_notify; + } + + ssl->s3->warning_alert_count++; + if (ssl->s3->warning_alert_count > kMaxWarningAlerts) { + *out_alert = SSL_AD_UNEXPECTED_MESSAGE; + OPENSSL_PUT_ERROR(SSL, SSL_R_TOO_MANY_WARNING_ALERTS); + return ssl_open_record_error; + } + return ssl_open_record_discard; + } + + if (alert_level == SSL3_AL_FATAL) { + ssl->s3->recv_shutdown = ssl_shutdown_fatal_alert; + SSL_CTX_remove_session(ssl->ctx, ssl->session); + + char tmp[16]; + OPENSSL_PUT_ERROR(SSL, SSL_AD_REASON_OFFSET + alert_descr); + BIO_snprintf(tmp, sizeof(tmp), "%d", alert_descr); + ERR_add_error_data(2, "SSL alert number ", tmp); + return ssl_open_record_fatal_alert; + } + + *out_alert = SSL_AD_ILLEGAL_PARAMETER; + OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_ALERT_TYPE); + return ssl_open_record_error; +} diff --git a/external/boringssl/third_party/android-cmake/AndroidNdkGdb.cmake b/external/boringssl/third_party/android-cmake/AndroidNdkGdb.cmake new file mode 100644 index 0000000000..0677dcda91 --- /dev/null +++ b/external/boringssl/third_party/android-cmake/AndroidNdkGdb.cmake @@ -0,0 +1,96 @@ +# Copyright (c) 2014, Pavel Rojtberg +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from this +# software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +# ------------------------------------------------------------------------------ +# Usage: +# 1. place AndroidNdkGdb.cmake somewhere inside ${CMAKE_MODULE_PATH} +# 2. inside your project add +# +# include(AndroidNdkGdb) +# android_ndk_gdb_enable() +# # for each target +# add_library(MyLibrary ...) +# android_ndk_gdb_debuggable(MyLibrary) + + +# add gdbserver and general gdb configuration to project +# also create a mininal NDK skeleton so ndk-gdb finds the paths +# +# the optional parameter defines the path to the android project. +# uses PROJECT_SOURCE_DIR by default. +macro(android_ndk_gdb_enable) + if(ANDROID) + # create custom target that depends on the real target so it gets executed afterwards + add_custom_target(NDK_GDB ALL) + + if(${ARGC}) + set(ANDROID_PROJECT_DIR ${ARGV0}) + else() + set(ANDROID_PROJECT_DIR ${PROJECT_SOURCE_DIR}) + endif() + + set(NDK_GDB_SOLIB_PATH ${ANDROID_PROJECT_DIR}/obj/local/${ANDROID_NDK_ABI_NAME}/) + file(MAKE_DIRECTORY ${NDK_GDB_SOLIB_PATH}) + + # 1. generate essential Android Makefiles + file(MAKE_DIRECTORY ${ANDROID_PROJECT_DIR}/jni) + if(NOT EXISTS ${ANDROID_PROJECT_DIR}/jni/Android.mk) + file(WRITE ${ANDROID_PROJECT_DIR}/jni/Android.mk "APP_ABI := ${ANDROID_NDK_ABI_NAME}\n") + endif() + if(NOT EXISTS ${ANDROID_PROJECT_DIR}/jni/Application.mk) + file(WRITE ${ANDROID_PROJECT_DIR}/jni/Application.mk "APP_ABI := ${ANDROID_NDK_ABI_NAME}\n") + endif() + + # 2. generate gdb.setup + get_directory_property(PROJECT_INCLUDES DIRECTORY ${PROJECT_SOURCE_DIR} INCLUDE_DIRECTORIES) + string(REGEX REPLACE ";" " " PROJECT_INCLUDES "${PROJECT_INCLUDES}") + file(WRITE ${LIBRARY_OUTPUT_PATH}/gdb.setup "set solib-search-path ${NDK_GDB_SOLIB_PATH}\n") + file(APPEND ${LIBRARY_OUTPUT_PATH}/gdb.setup "directory ${PROJECT_INCLUDES}\n") + + # 3. copy gdbserver executable + file(COPY ${ANDROID_NDK}/prebuilt/android-${ANDROID_ARCH_NAME}/gdbserver/gdbserver DESTINATION ${LIBRARY_OUTPUT_PATH}) + endif() +endmacro() + +# register a target for remote debugging +# copies the debug version to NDK_GDB_SOLIB_PATH then strips symbols of original +macro(android_ndk_gdb_debuggable TARGET_NAME) + if(ANDROID) + get_property(TARGET_LOCATION TARGET ${TARGET_NAME} PROPERTY LOCATION) + + # create custom target that depends on the real target so it gets executed afterwards + add_dependencies(NDK_GDB ${TARGET_NAME}) + + # 4. copy lib to obj + add_custom_command(TARGET NDK_GDB POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${TARGET_LOCATION} ${NDK_GDB_SOLIB_PATH}) + + # 5. strip symbols + add_custom_command(TARGET NDK_GDB POST_BUILD COMMAND ${CMAKE_STRIP} ${TARGET_LOCATION}) + endif() +endmacro() diff --git a/external/boringssl/third_party/android-cmake/AndroidNdkModules.cmake b/external/boringssl/third_party/android-cmake/AndroidNdkModules.cmake new file mode 100644 index 0000000000..64f37fdee2 --- /dev/null +++ b/external/boringssl/third_party/android-cmake/AndroidNdkModules.cmake @@ -0,0 +1,58 @@ +# Copyright (c) 2014, Pavel Rojtberg +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from this +# software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +macro(android_ndk_import_module_cpufeatures) + if(ANDROID) + include_directories(${ANDROID_NDK}/sources/android/cpufeatures) + add_library(cpufeatures ${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c) + target_link_libraries(cpufeatures dl) + endif() +endmacro() + +macro(android_ndk_import_module_native_app_glue) + if(ANDROID) + include_directories(${ANDROID_NDK}/sources/android/native_app_glue) + add_library(native_app_glue ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) + target_link_libraries(native_app_glue log) + endif() +endmacro() + +macro(android_ndk_import_module_ndk_helper) + if(ANDROID) + android_ndk_import_module_cpufeatures() + android_ndk_import_module_native_app_glue() + + include_directories(${ANDROID_NDK}/sources/android/ndk_helper) + file(GLOB _NDK_HELPER_SRCS ${ANDROID_NDK}/sources/android/ndk_helper/*.cpp ${ANDROID_NDK}/sources/android/ndk_helper/gl3stub.c) + add_library(ndk_helper ${_NDK_HELPER_SRCS}) + target_link_libraries(ndk_helper log android EGL GLESv2 cpufeatures native_app_glue) + + unset(_NDK_HELPER_SRCS) + endif() +endmacro() \ No newline at end of file diff --git a/external/boringssl/third_party/android-cmake/LICENSE b/external/boringssl/third_party/android-cmake/LICENSE new file mode 100644 index 0000000000..a96a3694d4 --- /dev/null +++ b/external/boringssl/third_party/android-cmake/LICENSE @@ -0,0 +1,30 @@ +Copyright (c) 2010-2011, Ethan Rublee +Copyright (c) 2011-2014, Andrey Kamaev +Copyright (c) 2014, Pavel Rojtberg +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/external/boringssl/third_party/android-cmake/README.google b/external/boringssl/third_party/android-cmake/README.google new file mode 100644 index 0000000000..b2a0caf66f --- /dev/null +++ b/external/boringssl/third_party/android-cmake/README.google @@ -0,0 +1,12 @@ +URL: https://github.com/taka-no-me/android-cmake/archive/556cc14296c226f753a3778d99d8b60778b7df4f.zip +Version: 556cc14296c226f753a3778d99d8b60778b7df4f +License: BSD +License File: LICENSE + +Description: +android-cmake is a collection of CMake scripts for building against the Android +NDK. + +Local Modifications: +LICENSE file has been created for compliance purposes. Not included in original +distribution. diff --git a/external/boringssl/third_party/android-cmake/README.md b/external/boringssl/third_party/android-cmake/README.md new file mode 100644 index 0000000000..ee63021282 --- /dev/null +++ b/external/boringssl/third_party/android-cmake/README.md @@ -0,0 +1,240 @@ +# android-cmake + +CMake is great, and so is Android. This is a collection of CMake scripts that may be useful to the Android NDK community. It is based on experience from porting OpenCV library to Android: http://opencv.org/platforms/android.html + +Main goal is to share these scripts so that devs that use CMake as their build system may easily compile native code for Android. + +## TL;DR + + cmake -DCMAKE_TOOLCHAIN_FILE=android.toolchain.cmake \ + -DANDROID_NDK= \ + -DCMAKE_BUILD_TYPE=Release \ + -DANDROID_ABI="armeabi-v7a with NEON" \ + + cmake --build . + +One-liner: + + cmake -DCMAKE_TOOLCHAIN_FILE=android.toolchain.cmake -DANDROID_NDK= -DCMAKE_BUILD_TYPE=Release -DANDROID_ABI="armeabi-v7a with NEON" && cmake --build . + +_android-cmake_ will search for your NDK install in the following order: + +1. Value of `ANDROID_NDK` CMake variable; +1. Value of `ANDROID_NDK` environment variable; +1. Search under paths from `ANDROID_NDK_SEARCH_PATHS` CMake variable; +1. Search platform specific locations (home folder, Windows "Program Files", etc). + +So if you have installed the NDK as `~/android-ndk-r10d` then _android-cmake_ will locate it automatically. + +## Getting started + +To build a cmake-based C/C++ project for Android you need: + +* Android NDK (>= r5) http://developer.android.com/tools/sdk/ndk/index.html +* CMake (>= v2.6.3, >= v2.8.9 recommended) http://www.cmake.org/download + +The _android-cmake_ is also capable to build with NDK from AOSP or Linaro Android source tree, but you may be required to manually specify path to `libm` binary to link with. + +## Difference from traditional CMake + +Folowing the _ndk-build_ the _android-cmake_ supports **only two build targets**: + +* `-DCMAKE_BUILD_TYPE=Release` +* `-DCMAKE_BUILD_TYPE=Debug` + +So don't even try other targets that can be found in CMake documentation and don't forget to explicitly specify `Release` or `Debug` because CMake builds without a build configuration by default. + +## Difference from _ndk-build_ + +* Latest GCC available in NDK is used as the default compiler; +* `Release` builds with `-O3` instead of `-Os`; +* `Release` builds without debug info (without `-g`) (because _ndk-build_ always creates a stripped version but cmake delays this for `install/strip` target); +* `-fsigned-char` is added to compiler flags to make `char` signed by default as it is on x86/x86_64; +* GCC's stack protector is not used neither in `Debug` nor `Release` configurations; +* No builds for multiple platforms (e.g. building for both arm and x86 require to run cmake twice with different parameters); +* No file level Neon via `.neon` suffix; + +The following features of _ndk-build_ are not supported by the _android-cmake_ yet: + +* `armeabi-v7a-hard` ABI +* `libc++_static`/`libc++_shared` STL runtime + +## Basic options + +Similarly to the NDK build system _android-cmake_ allows to select between several compiler toolchains and target platforms. Most of the options can be set either as cmake arguments: `-D=` or as environment variables: + +* **ANDROID_NDK** - path to the Android NDK. If not set then _android-cmake_ will search for the most recent version of supported NDK in commonly used locations; +* **ANDROID_ABI** - specifies the target Application Binary Interface (ABI). This option nearly matches to the APP_ABI variable used by ndk-build tool from Android NDK. If not specified then set to `armeabi-v7a`. Possible target names are: + * `armeabi` - ARMv5TE based CPU with software floating point operations; + * **`armeabi-v7a`** - ARMv7 based devices with hardware FPU instructions (VFPv3_D16); + * `armeabi-v7a with NEON` - same as armeabi-v7a, but sets NEON as floating-point unit; + * `armeabi-v7a with VFPV3` - same as armeabi-v7a, but sets VFPv3_D32 as floating-point unit; + * `armeabi-v6 with VFP` - tuned for ARMv6 processors having VFP; + * `x86` - IA-32 instruction set + * `mips` - MIPS32 instruction set + * `arm64-v8a` - ARMv8 AArch64 instruction set - only for NDK r10 and newer + * `x86_64` - Intel64 instruction set (r1) - only for NDK r10 and newer + * `mips64` - MIPS64 instruction set (r6) - only for NDK r10 and newer +* **ANDROID_NATIVE_API_LEVEL** - level of android API to build for. Can be set either to full name (example: `android-8`) or a numeric value (example: `17`). The default API level depends on the target ABI: + * `android-8` for ARM; + * `android-9` for x86 and MIPS; + * `android-21` for 64-bit ABIs. + + Building for `android-L` is possible only when it is explicitly selected. +* **ANDROID_TOOLCHAIN_NAME** - the name of compiler toolchain to be used. This option allows to select between different GCC and Clang versions. The list of possible values depends on the NDK version and will be printed by toolchain file if an invalid value is set. By default _android-cmake_ selects the most recent version of GCC which can build for specified `ANDROID_ABI`. + + Example values are: + * `aarch64-linux-android-4.9` + * `aarch64-linux-android-clang3.5` + * `arm-linux-androideabi-4.8` + * `arm-linux-androideabi-4.9` + * `arm-linux-androideabi-clang3.5` + * `mips64el-linux-android-4.9` + * `mipsel-linux-android-4.8` + * `x86-4.9` + * `x86_64-4.9` + * etc. +* **ANDROID_STL** - the name of C++ runtime to use. The default is `gnustl_static`. + * `none` - do not configure the runtime. + * `system` - use the default minimal system C++ runtime library. + * Implies `-fno-rtti -fno-exceptions`. + * `system_re` - use the default minimal system C++ runtime library. + * Implies `-frtti -fexceptions`. + * `gabi++_static` - use the GAbi++ runtime as a static library. + * Implies `-frtti -fno-exceptions`. + * Available for NDK r7 and newer. + * `gabi++_shared` - use the GAbi++ runtime as a shared library. + * Implies `-frtti -fno-exceptions`. + * Available for NDK r7 and newer. + * `stlport_static` - use the STLport runtime as a static library. + * Implies `-fno-rtti -fno-exceptions` for NDK before r7. + * Implies `-frtti -fno-exceptions` for NDK r7 and newer. + * `stlport_shared` - use the STLport runtime as a shared library. + * Implies `-fno-rtti -fno-exceptions` for NDK before r7. + * Implies `-frtti -fno-exceptions` for NDK r7 and newer. + * **`gnustl_static`** - use the GNU STL as a static library. + * Implies `-frtti -fexceptions`. + * `gnustl_shared` - use the GNU STL as a shared library. + * Implies `-frtti -fno-exceptions`. + * Available for NDK r7b and newer. + * Silently degrades to `gnustl_static` if not available. +* **NDK_CCACHE** - path to `ccache` executable. If not set then initialized from `NDK_CCACHE` environment variable. + +## Advanced _android-cmake_ options + +Normally _android-cmake_ users are not supposed to touch these variables but they might be useful to workaround some build issues: + +* **ANDROID_FORCE_ARM_BUILD** = `OFF` - generate 32-bit ARM instructions instead of Thumb. Applicable only for arm ABIs and is forced to be `ON` for `armeabi-v6 with VFP`; +* **ANDROID_NO_UNDEFINED** = `ON` - show all undefined symbols as linker errors; +* **ANDROID_SO_UNDEFINED** = `OFF` - allow undefined symbols in shared libraries; + * actually it is turned `ON` by default for NDK older than `r7` +* **ANDROID_STL_FORCE_FEATURES** = `ON` - automatically configure rtti and exceptions support based on C++ runtime; +* **ANDROID_NDK_LAYOUT** = `RELEASE` - inner layout of Android NDK, should be detected automatically. Possible values are: + * `RELEASE` - public releases from Google; + * `LINARO` - NDK from Linaro project; + * `ANDROID` - NDK from AOSP. +* **ANDROID_FUNCTION_LEVEL_LINKING** = `ON` - enables saparate putting each function and data items into separate sections and enable garbage collection of unused input sections at link time (`-fdata-sections -ffunction-sections -Wl,--gc-sections`); +* **ANDROID_GOLD_LINKER** = `ON` - use gold linker with GCC 4.6 for NDK r8b and newer (only for ARM and x86); +* **ANDROID_NOEXECSTACK** = `ON` - enables or disables stack execution protection code (`-Wl,-z,noexecstack`); +* **ANDROID_RELRO** = `ON` - Enables RELRO - a memory corruption mitigation technique (`-Wl,-z,relro -Wl,-z,now`); +* **ANDROID_LIBM_PATH** - path to `libm.so` (set to something like `$(TOP)/out/target/product//obj/lib/libm.so`) to workaround unresolved `sincos`. + +## Fine-tuning `CMakeLists.txt` for _android-cmake_ + +### Recognizing Android build + +_android-cmake_ defines `ANDROID` CMake variable which can be used to add Android-specific stuff: + + if (ANDROID) + message(STATUS "Hello from Android build!") + endif() + +The recommended way to identify ARM/MIPS/x86 architecture is examining `CMAKE_SYSTEM_PROCESSOR` which is set to the appropriate value: + +* `armv5te` - for `armeabi` ABI +* `armv6` - for `armeabi-v6 with VFP` ABI +* `armv7-a` - for `armeabi-v7a`, `armeabi-v7a with VFPV3` and `armeabi-v7a with NEON` ABIs +* `aarch64` - for `arm64-v8a` ABI +* `i686` - for `x86` ABI +* `x86_64` - for `x86_64` ABI +* `mips` - for `mips` ABI +* `mips64` - for `mips64` ABI + +Other variables that are set by _android-cmake_ and can be used for the fine-grained build configuration are: + +* `NEON` - set if target ABI supports Neon; +* `ANDROID_NATIVE_API_LEVEL` - native Android API level we are building for (note: Java part of Andoid application can be built for another API level) +* `ANDROID_NDK_RELEASE` - version of the Android NDK +* `ANDROID_NDK_HOST_SYSTEM_NAME` - "windows", "linux-x86" or "darwin-x86" depending on the host platform +* `ANDROID_RTTI` - set if rtti is enabled by the runtime +* `ANDROID_EXCEPTIONS` - set if exceptions are enabled by the runtime + +### Finding packages + +When crosscompiling CMake `find_*` commands are normally expected to find libraries and packages belonging to the same build target. So _android-cmake_ configures CMake to search in Android-specific paths only and ignore your host system locations. So + + find_package(ZLIB) + +will surely find libz.so within the Android NDK. + +However sometimes you need to locate a host package even when cross-compiling. For example you can be searching for your documentation generator. The _android-cmake_ recommends you to use `find_host_package` and `find_host_program` macro defined in the `android.toolchain.cmake`: + + find_host_package(Doxygen) + find_host_program(PDFLATEX pdflatex) + +However this will break regular builds so instead of wrapping package search into platform-specific logic you can copy the following snippet into your project (put it after your top-level `project()` command): + + # Search packages for host system instead of packages for target system + # in case of cross compilation these macro should be defined by toolchain file + if(NOT COMMAND find_host_package) + macro(find_host_package) + find_package(${ARGN}) + endmacro() + endif() + if(NOT COMMAND find_host_program) + macro(find_host_program) + find_program(${ARGN}) + endmacro() + endif() + +### Compiler flags recycling + +Make sure to do the following in your scripts: + + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${my_cxx_flags}") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${my_cxx_flags}") + +The flags will be prepopulated with critical flags, so don't loose them. Also be aware that _android-cmake_ also sets configuration-specific compiler and linker flags. + +## Troubleshooting + +### Building on Windows + +First of all `cygwin` builds are **NOT supported** and will not be supported by _android-cmake_. To build natively on Windows you need a port of make but I recommend http://martine.github.io/ninja/ instead. + +To build with Ninja you need: + +* Ensure you are using CMake newer than 2.8.9; +* Download the latest Ninja from https://github.com/martine/ninja/releases; +* Put the `ninja.exe` into your PATH (or add path to `ninja.exe` to your PATH environment variable); +* Pass `-GNinja` to `cmake` alongside with other arguments (or choose Ninja generator in `cmake-gui`). +* Enjoy the fast native multithreaded build :) + +But if you still want to stick to old make then: + +* Get a Windows port of GNU Make: + * Android NDK r7 (and newer) already has `make.exe` on board; + * `mingw-make` should work as fine; + * Download some other port. For example, this one: http://gnuwin32.sourceforge.net/packages/make.htm. +* Add path to your `make.exe` to system PATH or always use full path; +* Pass `-G"MinGW Makefiles"` and `-DCMAKE_MAKE_PROGRAM="make.exe"` + * It must be `MinGW Makefiles` and not `Unix Makefiles` even if your `make.exe` is not a MinGW's make. +* Run `make.exe` or `cmake --build .` for single-threaded build. + +### Projects with assembler files + +The _android-cmake_ should correctly handle projects with assembler sources (`*.s` or `*.S`). But if you still facing problems with assembler then try to upgrade your CMake to version newer than 2.8.5 + +## Copying + +_android-cmake_ is distributed under the terms of [BSD 3-Clause License](http://opensource.org/licenses/BSD-3-Clause) \ No newline at end of file diff --git a/external/boringssl/third_party/android-cmake/android.toolchain.cmake b/external/boringssl/third_party/android-cmake/android.toolchain.cmake new file mode 100644 index 0000000000..ffa26126a7 --- /dev/null +++ b/external/boringssl/third_party/android-cmake/android.toolchain.cmake @@ -0,0 +1,1693 @@ +# Copyright (c) 2010-2011, Ethan Rublee +# Copyright (c) 2011-2014, Andrey Kamaev +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from this +# software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +# ------------------------------------------------------------------------------ +# Android CMake toolchain file, for use with the Android NDK r5-r10d +# Requires cmake 2.6.3 or newer (2.8.9 or newer is recommended). +# See home page: https://github.com/taka-no-me/android-cmake +# +# Usage Linux: +# $ export ANDROID_NDK=/absolute/path/to/the/android-ndk +# $ mkdir build && cd build +# $ cmake -DCMAKE_TOOLCHAIN_FILE=path/to/the/android.toolchain.cmake .. +# $ make -j8 +# +# Usage Windows: +# You need native port of make to build your project. +# Android NDK r7 (and newer) already has make.exe on board. +# For older NDK you have to install it separately. +# For example, this one: http://gnuwin32.sourceforge.net/packages/make.htm +# +# $ SET ANDROID_NDK=C:\absolute\path\to\the\android-ndk +# $ mkdir build && cd build +# $ cmake.exe -G"MinGW Makefiles" +# -DCMAKE_TOOLCHAIN_FILE=path\to\the\android.toolchain.cmake +# -DCMAKE_MAKE_PROGRAM="%ANDROID_NDK%\prebuilt\windows\bin\make.exe" .. +# $ cmake.exe --build . +# +# +# Options (can be set as cmake parameters: -D=): +# ANDROID_NDK=/opt/android-ndk - path to the NDK root. +# Can be set as environment variable. Can be set only at first cmake run. +# +# ANDROID_ABI=armeabi-v7a - specifies the target Application Binary +# Interface (ABI). This option nearly matches to the APP_ABI variable +# used by ndk-build tool from Android NDK. +# +# Possible targets are: +# "armeabi" - ARMv5TE based CPU with software floating point operations +# "armeabi-v7a" - ARMv7 based devices with hardware FPU instructions +# this ABI target is used by default +# "armeabi-v7a with NEON" - same as armeabi-v7a, but +# sets NEON as floating-point unit +# "armeabi-v7a with VFPV3" - same as armeabi-v7a, but +# sets VFPV3 as floating-point unit (has 32 registers instead of 16) +# "armeabi-v6 with VFP" - tuned for ARMv6 processors having VFP +# "x86" - IA-32 instruction set +# "mips" - MIPS32 instruction set +# +# 64-bit ABIs for NDK r10 and newer: +# "arm64-v8a" - ARMv8 AArch64 instruction set +# "x86_64" - Intel64 instruction set (r1) +# "mips64" - MIPS64 instruction set (r6) +# +# ANDROID_NATIVE_API_LEVEL=android-8 - level of Android API compile for. +# Option is read-only when standalone toolchain is used. +# Note: building for "android-L" requires explicit configuration. +# +# ANDROID_TOOLCHAIN_NAME=arm-linux-androideabi-4.9 - the name of compiler +# toolchain to be used. The list of possible values depends on the NDK +# version. For NDK r10c the possible values are: +# +# * aarch64-linux-android-4.9 +# * aarch64-linux-android-clang3.4 +# * aarch64-linux-android-clang3.5 +# * arm-linux-androideabi-4.6 +# * arm-linux-androideabi-4.8 +# * arm-linux-androideabi-4.9 (default) +# * arm-linux-androideabi-clang3.4 +# * arm-linux-androideabi-clang3.5 +# * mips64el-linux-android-4.9 +# * mips64el-linux-android-clang3.4 +# * mips64el-linux-android-clang3.5 +# * mipsel-linux-android-4.6 +# * mipsel-linux-android-4.8 +# * mipsel-linux-android-4.9 +# * mipsel-linux-android-clang3.4 +# * mipsel-linux-android-clang3.5 +# * x86-4.6 +# * x86-4.8 +# * x86-4.9 +# * x86-clang3.4 +# * x86-clang3.5 +# * x86_64-4.9 +# * x86_64-clang3.4 +# * x86_64-clang3.5 +# +# ANDROID_FORCE_ARM_BUILD=OFF - set ON to generate 32-bit ARM instructions +# instead of Thumb. Is not available for "armeabi-v6 with VFP" +# (is forced to be ON) ABI. +# +# ANDROID_NO_UNDEFINED=ON - set ON to show all undefined symbols as linker +# errors even if they are not used. +# +# ANDROID_SO_UNDEFINED=OFF - set ON to allow undefined symbols in shared +# libraries. Automatically turned for NDK r5x and r6x due to GLESv2 +# problems. +# +# ANDROID_STL=gnustl_static - specify the runtime to use. +# +# Possible values are: +# none -> Do not configure the runtime. +# system -> Use the default minimal system C++ runtime library. +# Implies -fno-rtti -fno-exceptions. +# Is not available for standalone toolchain. +# system_re -> Use the default minimal system C++ runtime library. +# Implies -frtti -fexceptions. +# Is not available for standalone toolchain. +# gabi++_static -> Use the GAbi++ runtime as a static library. +# Implies -frtti -fno-exceptions. +# Available for NDK r7 and newer. +# Is not available for standalone toolchain. +# gabi++_shared -> Use the GAbi++ runtime as a shared library. +# Implies -frtti -fno-exceptions. +# Available for NDK r7 and newer. +# Is not available for standalone toolchain. +# stlport_static -> Use the STLport runtime as a static library. +# Implies -fno-rtti -fno-exceptions for NDK before r7. +# Implies -frtti -fno-exceptions for NDK r7 and newer. +# Is not available for standalone toolchain. +# stlport_shared -> Use the STLport runtime as a shared library. +# Implies -fno-rtti -fno-exceptions for NDK before r7. +# Implies -frtti -fno-exceptions for NDK r7 and newer. +# Is not available for standalone toolchain. +# gnustl_static -> Use the GNU STL as a static library. +# Implies -frtti -fexceptions. +# gnustl_shared -> Use the GNU STL as a shared library. +# Implies -frtti -fno-exceptions. +# Available for NDK r7b and newer. +# Silently degrades to gnustl_static if not available. +# +# ANDROID_STL_FORCE_FEATURES=ON - turn rtti and exceptions support based on +# chosen runtime. If disabled, then the user is responsible for settings +# these options. +# +# What?: +# android-cmake toolchain searches for NDK/toolchain in the following order: +# ANDROID_NDK - cmake parameter +# ANDROID_NDK - environment variable +# ANDROID_STANDALONE_TOOLCHAIN - cmake parameter +# ANDROID_STANDALONE_TOOLCHAIN - environment variable +# ANDROID_NDK - default locations +# ANDROID_STANDALONE_TOOLCHAIN - default locations +# +# Make sure to do the following in your scripts: +# SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${my_cxx_flags}" ) +# SET( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${my_cxx_flags}" ) +# The flags will be prepopulated with critical flags, so don't loose them. +# Also be aware that toolchain also sets configuration-specific compiler +# flags and linker flags. +# +# ANDROID and BUILD_ANDROID will be set to true, you may test any of these +# variables to make necessary Android-specific configuration changes. +# +# Also ARMEABI or ARMEABI_V7A or X86 or MIPS or ARM64_V8A or X86_64 or MIPS64 +# will be set true, mutually exclusive. NEON option will be set true +# if VFP is set to NEON. +# +# ------------------------------------------------------------------------------ + +cmake_minimum_required( VERSION 2.6.3 ) + +if( DEFINED CMAKE_CROSSCOMPILING ) + # subsequent toolchain loading is not really needed + return() +endif() + +if( CMAKE_TOOLCHAIN_FILE ) + # touch toolchain variable to suppress "unused variable" warning +endif() + +# inherit settings in recursive loads +get_property( _CMAKE_IN_TRY_COMPILE GLOBAL PROPERTY IN_TRY_COMPILE ) +if( _CMAKE_IN_TRY_COMPILE ) + include( "${CMAKE_CURRENT_SOURCE_DIR}/../android.toolchain.config.cmake" OPTIONAL ) +endif() + +# this one is important +if( CMAKE_VERSION VERSION_GREATER "3.0.99" ) + set( CMAKE_SYSTEM_NAME Android ) +else() + set( CMAKE_SYSTEM_NAME Linux ) +endif() + +# this one not so much +set( CMAKE_SYSTEM_VERSION 1 ) + +# rpath makes low sense for Android +set( CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG "" ) +set( CMAKE_SKIP_RPATH TRUE CACHE BOOL "If set, runtime paths are not added when using shared libraries." ) + +# NDK search paths +set( ANDROID_SUPPORTED_NDK_VERSIONS ${ANDROID_EXTRA_NDK_VERSIONS} -r10d -r10c -r10b -r10 -r9d -r9c -r9b -r9 -r8e -r8d -r8c -r8b -r8 -r7c -r7b -r7 -r6b -r6 -r5c -r5b -r5 "" ) +if( NOT DEFINED ANDROID_NDK_SEARCH_PATHS ) + if( CMAKE_HOST_WIN32 ) + file( TO_CMAKE_PATH "$ENV{PROGRAMFILES}" ANDROID_NDK_SEARCH_PATHS ) + set( ANDROID_NDK_SEARCH_PATHS "${ANDROID_NDK_SEARCH_PATHS}" "$ENV{SystemDrive}/NVPACK" ) + else() + file( TO_CMAKE_PATH "$ENV{HOME}" ANDROID_NDK_SEARCH_PATHS ) + set( ANDROID_NDK_SEARCH_PATHS /opt "${ANDROID_NDK_SEARCH_PATHS}/NVPACK" ) + endif() +endif() +if( NOT DEFINED ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH ) + set( ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH /opt/android-toolchain ) +endif() + +# known ABIs +set( ANDROID_SUPPORTED_ABIS_arm "armeabi-v7a;armeabi;armeabi-v7a with NEON;armeabi-v7a with VFPV3;armeabi-v6 with VFP" ) +set( ANDROID_SUPPORTED_ABIS_arm64 "arm64-v8a" ) +set( ANDROID_SUPPORTED_ABIS_x86 "x86" ) +set( ANDROID_SUPPORTED_ABIS_x86_64 "x86_64" ) +set( ANDROID_SUPPORTED_ABIS_mips "mips" ) +set( ANDROID_SUPPORTED_ABIS_mips64 "mips64" ) + +# API level defaults +set( ANDROID_DEFAULT_NDK_API_LEVEL 8 ) +set( ANDROID_DEFAULT_NDK_API_LEVEL_arm64 21 ) +set( ANDROID_DEFAULT_NDK_API_LEVEL_x86 9 ) +set( ANDROID_DEFAULT_NDK_API_LEVEL_x86_64 21 ) +set( ANDROID_DEFAULT_NDK_API_LEVEL_mips 9 ) +set( ANDROID_DEFAULT_NDK_API_LEVEL_mips64 21 ) + + +macro( __LIST_FILTER listvar regex ) + if( ${listvar} ) + foreach( __val ${${listvar}} ) + if( __val MATCHES "${regex}" ) + list( REMOVE_ITEM ${listvar} "${__val}" ) + endif() + endforeach() + endif() +endmacro() + +macro( __INIT_VARIABLE var_name ) + set( __test_path 0 ) + foreach( __var ${ARGN} ) + if( __var STREQUAL "PATH" ) + set( __test_path 1 ) + break() + endif() + endforeach() + + if( __test_path AND NOT EXISTS "${${var_name}}" ) + unset( ${var_name} CACHE ) + endif() + + if( " ${${var_name}}" STREQUAL " " ) + set( __values 0 ) + foreach( __var ${ARGN} ) + if( __var STREQUAL "VALUES" ) + set( __values 1 ) + elseif( NOT __var STREQUAL "PATH" ) + if( __var MATCHES "^ENV_.*$" ) + string( REPLACE "ENV_" "" __var "${__var}" ) + set( __value "$ENV{${__var}}" ) + elseif( DEFINED ${__var} ) + set( __value "${${__var}}" ) + elseif( __values ) + set( __value "${__var}" ) + else() + set( __value "" ) + endif() + + if( NOT " ${__value}" STREQUAL " " AND (NOT __test_path OR EXISTS "${__value}") ) + set( ${var_name} "${__value}" ) + break() + endif() + endif() + endforeach() + unset( __value ) + unset( __values ) + endif() + + if( __test_path ) + file( TO_CMAKE_PATH "${${var_name}}" ${var_name} ) + endif() + unset( __test_path ) +endmacro() + +macro( __DETECT_NATIVE_API_LEVEL _var _path ) + set( __ndkApiLevelRegex "^[\t ]*#define[\t ]+__ANDROID_API__[\t ]+([0-9]+)[\t ]*.*$" ) + file( STRINGS ${_path} __apiFileContent REGEX "${__ndkApiLevelRegex}" ) + if( NOT __apiFileContent ) + message( SEND_ERROR "Could not get Android native API level. Probably you have specified invalid level value, or your copy of NDK/toolchain is broken." ) + endif() + string( REGEX REPLACE "${__ndkApiLevelRegex}" "\\1" ${_var} "${__apiFileContent}" ) + unset( __apiFileContent ) + unset( __ndkApiLevelRegex ) +endmacro() + +macro( __DETECT_TOOLCHAIN_MACHINE_NAME _var _root ) + if( EXISTS "${_root}" ) + file( GLOB __gccExePath RELATIVE "${_root}/bin/" "${_root}/bin/*-gcc${TOOL_OS_SUFFIX}" ) + __LIST_FILTER( __gccExePath "^[.].*" ) + list( LENGTH __gccExePath __gccExePathsCount ) + if( NOT __gccExePathsCount EQUAL 1 AND NOT _CMAKE_IN_TRY_COMPILE ) + message( WARNING "Could not determine machine name for compiler from ${_root}" ) + set( ${_var} "" ) + else() + get_filename_component( __gccExeName "${__gccExePath}" NAME_WE ) + string( REPLACE "-gcc" "" ${_var} "${__gccExeName}" ) + endif() + unset( __gccExePath ) + unset( __gccExePathsCount ) + unset( __gccExeName ) + else() + set( ${_var} "" ) + endif() +endmacro() + + +# fight against cygwin +set( ANDROID_FORBID_SYGWIN TRUE CACHE BOOL "Prevent cmake from working under cygwin and using cygwin tools") +mark_as_advanced( ANDROID_FORBID_SYGWIN ) +if( ANDROID_FORBID_SYGWIN ) + if( CYGWIN ) + message( FATAL_ERROR "Android NDK and android-cmake toolchain are not welcome Cygwin. It is unlikely that this cmake toolchain will work under cygwin. But if you want to try then you can set cmake variable ANDROID_FORBID_SYGWIN to FALSE and rerun cmake." ) + endif() + + if( CMAKE_HOST_WIN32 ) + # remove cygwin from PATH + set( __new_path "$ENV{PATH}") + __LIST_FILTER( __new_path "cygwin" ) + set(ENV{PATH} "${__new_path}") + unset(__new_path) + endif() +endif() + + +# detect current host platform +if( NOT DEFINED ANDROID_NDK_HOST_X64 AND (CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "amd64|x86_64|AMD64" OR CMAKE_HOST_APPLE) ) + set( ANDROID_NDK_HOST_X64 1 CACHE BOOL "Try to use 64-bit compiler toolchain" ) + mark_as_advanced( ANDROID_NDK_HOST_X64 ) +endif() + +set( TOOL_OS_SUFFIX "" ) +if( CMAKE_HOST_APPLE ) + set( ANDROID_NDK_HOST_SYSTEM_NAME "darwin-x86_64" ) + set( ANDROID_NDK_HOST_SYSTEM_NAME2 "darwin-x86" ) +elseif( CMAKE_HOST_WIN32 ) + set( ANDROID_NDK_HOST_SYSTEM_NAME "windows-x86_64" ) + set( ANDROID_NDK_HOST_SYSTEM_NAME2 "windows" ) + set( TOOL_OS_SUFFIX ".exe" ) +elseif( CMAKE_HOST_UNIX ) + set( ANDROID_NDK_HOST_SYSTEM_NAME "linux-x86_64" ) + set( ANDROID_NDK_HOST_SYSTEM_NAME2 "linux-x86" ) +else() + message( FATAL_ERROR "Cross-compilation on your platform is not supported by this cmake toolchain" ) +endif() + +if( NOT ANDROID_NDK_HOST_X64 ) + set( ANDROID_NDK_HOST_SYSTEM_NAME ${ANDROID_NDK_HOST_SYSTEM_NAME2} ) +endif() + +# see if we have path to Android NDK +if( NOT ANDROID_NDK AND NOT ANDROID_STANDALONE_TOOLCHAIN ) + __INIT_VARIABLE( ANDROID_NDK PATH ENV_ANDROID_NDK ) +endif() +if( NOT ANDROID_NDK ) + # see if we have path to Android standalone toolchain + __INIT_VARIABLE( ANDROID_STANDALONE_TOOLCHAIN PATH ENV_ANDROID_STANDALONE_TOOLCHAIN ) + + if( NOT ANDROID_STANDALONE_TOOLCHAIN ) + #try to find Android NDK in one of the the default locations + set( __ndkSearchPaths ) + foreach( __ndkSearchPath ${ANDROID_NDK_SEARCH_PATHS} ) + foreach( suffix ${ANDROID_SUPPORTED_NDK_VERSIONS} ) + list( APPEND __ndkSearchPaths "${__ndkSearchPath}/android-ndk${suffix}" ) + endforeach() + endforeach() + __INIT_VARIABLE( ANDROID_NDK PATH VALUES ${__ndkSearchPaths} ) + unset( __ndkSearchPaths ) + + if( ANDROID_NDK ) + message( STATUS "Using default path for Android NDK: ${ANDROID_NDK}" ) + message( STATUS " If you prefer to use a different location, please define a cmake or environment variable: ANDROID_NDK" ) + else() + #try to find Android standalone toolchain in one of the the default locations + __INIT_VARIABLE( ANDROID_STANDALONE_TOOLCHAIN PATH ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH ) + + if( ANDROID_STANDALONE_TOOLCHAIN ) + message( STATUS "Using default path for standalone toolchain ${ANDROID_STANDALONE_TOOLCHAIN}" ) + message( STATUS " If you prefer to use a different location, please define the variable: ANDROID_STANDALONE_TOOLCHAIN" ) + endif( ANDROID_STANDALONE_TOOLCHAIN ) + endif( ANDROID_NDK ) + endif( NOT ANDROID_STANDALONE_TOOLCHAIN ) +endif( NOT ANDROID_NDK ) + +# remember found paths +if( ANDROID_NDK ) + get_filename_component( ANDROID_NDK "${ANDROID_NDK}" ABSOLUTE ) + set( ANDROID_NDK "${ANDROID_NDK}" CACHE INTERNAL "Path of the Android NDK" FORCE ) + set( BUILD_WITH_ANDROID_NDK True ) + if( EXISTS "${ANDROID_NDK}/RELEASE.TXT" ) + file( STRINGS "${ANDROID_NDK}/RELEASE.TXT" ANDROID_NDK_RELEASE_FULL LIMIT_COUNT 1 REGEX "r[0-9]+[a-z]?" ) + string( REGEX MATCH "r([0-9]+)([a-z]?)" ANDROID_NDK_RELEASE "${ANDROID_NDK_RELEASE_FULL}" ) + else() + set( ANDROID_NDK_RELEASE "r1x" ) + set( ANDROID_NDK_RELEASE_FULL "unreleased" ) + endif() + string( REGEX REPLACE "r([0-9]+)([a-z]?)" "\\1*1000" ANDROID_NDK_RELEASE_NUM "${ANDROID_NDK_RELEASE}" ) + string( FIND " abcdefghijklmnopqastuvwxyz" "${CMAKE_MATCH_2}" __ndkReleaseLetterNum ) + math( EXPR ANDROID_NDK_RELEASE_NUM "${ANDROID_NDK_RELEASE_NUM}+${__ndkReleaseLetterNum}" ) +elseif( ANDROID_STANDALONE_TOOLCHAIN ) + get_filename_component( ANDROID_STANDALONE_TOOLCHAIN "${ANDROID_STANDALONE_TOOLCHAIN}" ABSOLUTE ) + # try to detect change + if( CMAKE_AR ) + string( LENGTH "${ANDROID_STANDALONE_TOOLCHAIN}" __length ) + string( SUBSTRING "${CMAKE_AR}" 0 ${__length} __androidStandaloneToolchainPreviousPath ) + if( NOT __androidStandaloneToolchainPreviousPath STREQUAL ANDROID_STANDALONE_TOOLCHAIN ) + message( FATAL_ERROR "It is not possible to change path to the Android standalone toolchain on subsequent run." ) + endif() + unset( __androidStandaloneToolchainPreviousPath ) + unset( __length ) + endif() + set( ANDROID_STANDALONE_TOOLCHAIN "${ANDROID_STANDALONE_TOOLCHAIN}" CACHE INTERNAL "Path of the Android standalone toolchain" FORCE ) + set( BUILD_WITH_STANDALONE_TOOLCHAIN True ) +else() + list(GET ANDROID_NDK_SEARCH_PATHS 0 ANDROID_NDK_SEARCH_PATH) + message( FATAL_ERROR "Could not find neither Android NDK nor Android standalone toolchain. + You should either set an environment variable: + export ANDROID_NDK=~/my-android-ndk + or + export ANDROID_STANDALONE_TOOLCHAIN=~/my-android-toolchain + or put the toolchain or NDK in the default path: + sudo ln -s ~/my-android-ndk ${ANDROID_NDK_SEARCH_PATH}/android-ndk + sudo ln -s ~/my-android-toolchain ${ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH}" ) +endif() + +# android NDK layout +if( BUILD_WITH_ANDROID_NDK ) + if( NOT DEFINED ANDROID_NDK_LAYOUT ) + # try to automatically detect the layout + if( EXISTS "${ANDROID_NDK}/RELEASE.TXT") + set( ANDROID_NDK_LAYOUT "RELEASE" ) + elseif( EXISTS "${ANDROID_NDK}/../../linux-x86/toolchain/" ) + set( ANDROID_NDK_LAYOUT "LINARO" ) + elseif( EXISTS "${ANDROID_NDK}/../../gcc/" ) + set( ANDROID_NDK_LAYOUT "ANDROID" ) + endif() + endif() + set( ANDROID_NDK_LAYOUT "${ANDROID_NDK_LAYOUT}" CACHE STRING "The inner layout of NDK" ) + mark_as_advanced( ANDROID_NDK_LAYOUT ) + if( ANDROID_NDK_LAYOUT STREQUAL "LINARO" ) + set( ANDROID_NDK_HOST_SYSTEM_NAME ${ANDROID_NDK_HOST_SYSTEM_NAME2} ) # only 32-bit at the moment + set( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK}/../../${ANDROID_NDK_HOST_SYSTEM_NAME}/toolchain" ) + set( ANDROID_NDK_TOOLCHAINS_SUBPATH "" ) + set( ANDROID_NDK_TOOLCHAINS_SUBPATH2 "" ) + elseif( ANDROID_NDK_LAYOUT STREQUAL "ANDROID" ) + set( ANDROID_NDK_HOST_SYSTEM_NAME ${ANDROID_NDK_HOST_SYSTEM_NAME2} ) # only 32-bit at the moment + set( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK}/../../gcc/${ANDROID_NDK_HOST_SYSTEM_NAME}/arm" ) + set( ANDROID_NDK_TOOLCHAINS_SUBPATH "" ) + set( ANDROID_NDK_TOOLCHAINS_SUBPATH2 "" ) + else() # ANDROID_NDK_LAYOUT STREQUAL "RELEASE" + set( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK}/toolchains" ) + set( ANDROID_NDK_TOOLCHAINS_SUBPATH "/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME}" ) + set( ANDROID_NDK_TOOLCHAINS_SUBPATH2 "/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME2}" ) + endif() + get_filename_component( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK_TOOLCHAINS_PATH}" ABSOLUTE ) + + # try to detect change of NDK + if( CMAKE_AR ) + string( LENGTH "${ANDROID_NDK_TOOLCHAINS_PATH}" __length ) + string( SUBSTRING "${CMAKE_AR}" 0 ${__length} __androidNdkPreviousPath ) + if( NOT __androidNdkPreviousPath STREQUAL ANDROID_NDK_TOOLCHAINS_PATH ) + message( FATAL_ERROR "It is not possible to change the path to the NDK on subsequent CMake run. You must remove all generated files from your build folder first. + " ) + endif() + unset( __androidNdkPreviousPath ) + unset( __length ) + endif() +endif() + + +# get all the details about standalone toolchain +if( BUILD_WITH_STANDALONE_TOOLCHAIN ) + __DETECT_NATIVE_API_LEVEL( ANDROID_SUPPORTED_NATIVE_API_LEVELS "${ANDROID_STANDALONE_TOOLCHAIN}/sysroot/usr/include/android/api-level.h" ) + set( ANDROID_STANDALONE_TOOLCHAIN_API_LEVEL ${ANDROID_SUPPORTED_NATIVE_API_LEVELS} ) + set( __availableToolchains "standalone" ) + __DETECT_TOOLCHAIN_MACHINE_NAME( __availableToolchainMachines "${ANDROID_STANDALONE_TOOLCHAIN}" ) + if( NOT __availableToolchainMachines ) + message( FATAL_ERROR "Could not determine machine name of your toolchain. Probably your Android standalone toolchain is broken." ) + endif() + if( __availableToolchainMachines MATCHES x86_64 ) + set( __availableToolchainArchs "x86_64" ) + elseif( __availableToolchainMachines MATCHES i686 ) + set( __availableToolchainArchs "x86" ) + elseif( __availableToolchainMachines MATCHES aarch64 ) + set( __availableToolchainArchs "arm64" ) + elseif( __availableToolchainMachines MATCHES arm ) + set( __availableToolchainArchs "arm" ) + elseif( __availableToolchainMachines MATCHES mips64el ) + set( __availableToolchainArchs "mips64" ) + elseif( __availableToolchainMachines MATCHES mipsel ) + set( __availableToolchainArchs "mips" ) + endif() + execute_process( COMMAND "${ANDROID_STANDALONE_TOOLCHAIN}/bin/${__availableToolchainMachines}-gcc${TOOL_OS_SUFFIX}" -dumpversion + OUTPUT_VARIABLE __availableToolchainCompilerVersions OUTPUT_STRIP_TRAILING_WHITESPACE ) + string( REGEX MATCH "[0-9]+[.][0-9]+([.][0-9]+)?" __availableToolchainCompilerVersions "${__availableToolchainCompilerVersions}" ) + if( EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/bin/clang${TOOL_OS_SUFFIX}" ) + list( APPEND __availableToolchains "standalone-clang" ) + list( APPEND __availableToolchainMachines ${__availableToolchainMachines} ) + list( APPEND __availableToolchainArchs ${__availableToolchainArchs} ) + list( APPEND __availableToolchainCompilerVersions ${__availableToolchainCompilerVersions} ) + endif() +endif() + +macro( __GLOB_NDK_TOOLCHAINS __availableToolchainsVar __availableToolchainsLst __toolchain_subpath ) + foreach( __toolchain ${${__availableToolchainsLst}} ) + if( "${__toolchain}" MATCHES "-clang3[.][0-9]$" AND NOT EXISTS "${ANDROID_NDK_TOOLCHAINS_PATH}/${__toolchain}${__toolchain_subpath}" ) + SET( __toolchainVersionRegex "^TOOLCHAIN_VERSION[\t ]+:=[\t ]+(.*)$" ) + FILE( STRINGS "${ANDROID_NDK_TOOLCHAINS_PATH}/${__toolchain}/setup.mk" __toolchainVersionStr REGEX "${__toolchainVersionRegex}" ) + if( __toolchainVersionStr ) + string( REGEX REPLACE "${__toolchainVersionRegex}" "\\1" __toolchainVersionStr "${__toolchainVersionStr}" ) + string( REGEX REPLACE "-clang3[.][0-9]$" "-${__toolchainVersionStr}" __gcc_toolchain "${__toolchain}" ) + else() + string( REGEX REPLACE "-clang3[.][0-9]$" "-4.6" __gcc_toolchain "${__toolchain}" ) + endif() + unset( __toolchainVersionStr ) + unset( __toolchainVersionRegex ) + else() + set( __gcc_toolchain "${__toolchain}" ) + endif() + __DETECT_TOOLCHAIN_MACHINE_NAME( __machine "${ANDROID_NDK_TOOLCHAINS_PATH}/${__gcc_toolchain}${__toolchain_subpath}" ) + if( __machine ) + string( REGEX MATCH "[0-9]+[.][0-9]+([.][0-9x]+)?$" __version "${__gcc_toolchain}" ) + if( __machine MATCHES x86_64 ) + set( __arch "x86_64" ) + elseif( __machine MATCHES i686 ) + set( __arch "x86" ) + elseif( __machine MATCHES aarch64 ) + set( __arch "arm64" ) + elseif( __machine MATCHES arm ) + set( __arch "arm" ) + elseif( __machine MATCHES mips64el ) + set( __arch "mips64" ) + elseif( __machine MATCHES mipsel ) + set( __arch "mips" ) + else() + set( __arch "" ) + endif() + #message("machine: !${__machine}!\narch: !${__arch}!\nversion: !${__version}!\ntoolchain: !${__toolchain}!\n") + if (__arch) + list( APPEND __availableToolchainMachines "${__machine}" ) + list( APPEND __availableToolchainArchs "${__arch}" ) + list( APPEND __availableToolchainCompilerVersions "${__version}" ) + list( APPEND ${__availableToolchainsVar} "${__toolchain}" ) + endif() + endif() + unset( __gcc_toolchain ) + endforeach() +endmacro() + +# get all the details about NDK +if( BUILD_WITH_ANDROID_NDK ) + file( GLOB ANDROID_SUPPORTED_NATIVE_API_LEVELS RELATIVE "${ANDROID_NDK}/platforms" "${ANDROID_NDK}/platforms/android-*" ) + string( REPLACE "android-" "" ANDROID_SUPPORTED_NATIVE_API_LEVELS "${ANDROID_SUPPORTED_NATIVE_API_LEVELS}" ) + set( __availableToolchains "" ) + set( __availableToolchainMachines "" ) + set( __availableToolchainArchs "" ) + set( __availableToolchainCompilerVersions "" ) + if( ANDROID_TOOLCHAIN_NAME AND EXISTS "${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_TOOLCHAIN_NAME}/" ) + # do not go through all toolchains if we know the name + set( __availableToolchainsLst "${ANDROID_TOOLCHAIN_NAME}" ) + __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH}" ) + if( NOT __availableToolchains AND NOT ANDROID_NDK_TOOLCHAINS_SUBPATH STREQUAL ANDROID_NDK_TOOLCHAINS_SUBPATH2 ) + __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH2}" ) + if( __availableToolchains ) + set( ANDROID_NDK_TOOLCHAINS_SUBPATH ${ANDROID_NDK_TOOLCHAINS_SUBPATH2} ) + endif() + endif() + endif() + if( NOT __availableToolchains ) + file( GLOB __availableToolchainsLst RELATIVE "${ANDROID_NDK_TOOLCHAINS_PATH}" "${ANDROID_NDK_TOOLCHAINS_PATH}/*" ) + if( __availableToolchainsLst ) + list(SORT __availableToolchainsLst) # we need clang to go after gcc + endif() + __LIST_FILTER( __availableToolchainsLst "^[.]" ) + __LIST_FILTER( __availableToolchainsLst "llvm" ) + __LIST_FILTER( __availableToolchainsLst "renderscript" ) + __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH}" ) + if( NOT __availableToolchains AND NOT ANDROID_NDK_TOOLCHAINS_SUBPATH STREQUAL ANDROID_NDK_TOOLCHAINS_SUBPATH2 ) + __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH2}" ) + if( __availableToolchains ) + set( ANDROID_NDK_TOOLCHAINS_SUBPATH ${ANDROID_NDK_TOOLCHAINS_SUBPATH2} ) + endif() + endif() + endif() + if( NOT __availableToolchains ) + message( FATAL_ERROR "Could not find any working toolchain in the NDK. Probably your Android NDK is broken." ) + endif() +endif() + +# build list of available ABIs +set( ANDROID_SUPPORTED_ABIS "" ) +set( __uniqToolchainArchNames ${__availableToolchainArchs} ) +list( REMOVE_DUPLICATES __uniqToolchainArchNames ) +list( SORT __uniqToolchainArchNames ) +foreach( __arch ${__uniqToolchainArchNames} ) + list( APPEND ANDROID_SUPPORTED_ABIS ${ANDROID_SUPPORTED_ABIS_${__arch}} ) +endforeach() +unset( __uniqToolchainArchNames ) +if( NOT ANDROID_SUPPORTED_ABIS ) + message( FATAL_ERROR "No one of known Android ABIs is supported by this cmake toolchain." ) +endif() + +# choose target ABI +__INIT_VARIABLE( ANDROID_ABI VALUES ${ANDROID_SUPPORTED_ABIS} ) +# verify that target ABI is supported +list( FIND ANDROID_SUPPORTED_ABIS "${ANDROID_ABI}" __androidAbiIdx ) +if( __androidAbiIdx EQUAL -1 ) + string( REPLACE ";" "\", \"" PRINTABLE_ANDROID_SUPPORTED_ABIS "${ANDROID_SUPPORTED_ABIS}" ) + message( FATAL_ERROR "Specified ANDROID_ABI = \"${ANDROID_ABI}\" is not supported by this cmake toolchain or your NDK/toolchain. + Supported values are: \"${PRINTABLE_ANDROID_SUPPORTED_ABIS}\" + " ) +endif() +unset( __androidAbiIdx ) + +# set target ABI options +if( ANDROID_ABI STREQUAL "x86" ) + set( X86 true ) + set( ANDROID_NDK_ABI_NAME "x86" ) + set( ANDROID_ARCH_NAME "x86" ) + set( ANDROID_LLVM_TRIPLE "i686-none-linux-android" ) + set( CMAKE_SYSTEM_PROCESSOR "i686" ) +elseif( ANDROID_ABI STREQUAL "x86_64" ) + set( X86 true ) + set( X86_64 true ) + set( ANDROID_NDK_ABI_NAME "x86_64" ) + set( ANDROID_ARCH_NAME "x86_64" ) + set( CMAKE_SYSTEM_PROCESSOR "x86_64" ) + set( ANDROID_LLVM_TRIPLE "x86_64-none-linux-android" ) +elseif( ANDROID_ABI STREQUAL "mips64" ) + set( MIPS64 true ) + set( ANDROID_NDK_ABI_NAME "mips64" ) + set( ANDROID_ARCH_NAME "mips64" ) + set( ANDROID_LLVM_TRIPLE "mips64el-none-linux-android" ) + set( CMAKE_SYSTEM_PROCESSOR "mips64" ) +elseif( ANDROID_ABI STREQUAL "mips" ) + set( MIPS true ) + set( ANDROID_NDK_ABI_NAME "mips" ) + set( ANDROID_ARCH_NAME "mips" ) + set( ANDROID_LLVM_TRIPLE "mipsel-none-linux-android" ) + set( CMAKE_SYSTEM_PROCESSOR "mips" ) +elseif( ANDROID_ABI STREQUAL "arm64-v8a" ) + set( ARM64_V8A true ) + set( ANDROID_NDK_ABI_NAME "arm64-v8a" ) + set( ANDROID_ARCH_NAME "arm64" ) + set( ANDROID_LLVM_TRIPLE "aarch64-none-linux-android" ) + set( CMAKE_SYSTEM_PROCESSOR "aarch64" ) + set( VFPV3 true ) + set( NEON true ) +elseif( ANDROID_ABI STREQUAL "armeabi" ) + set( ARMEABI true ) + set( ANDROID_NDK_ABI_NAME "armeabi" ) + set( ANDROID_ARCH_NAME "arm" ) + set( ANDROID_LLVM_TRIPLE "armv5te-none-linux-androideabi" ) + set( CMAKE_SYSTEM_PROCESSOR "armv5te" ) +elseif( ANDROID_ABI STREQUAL "armeabi-v6 with VFP" ) + set( ARMEABI_V6 true ) + set( ANDROID_NDK_ABI_NAME "armeabi" ) + set( ANDROID_ARCH_NAME "arm" ) + set( ANDROID_LLVM_TRIPLE "armv5te-none-linux-androideabi" ) + set( CMAKE_SYSTEM_PROCESSOR "armv6" ) + # need always fallback to older platform + set( ARMEABI true ) +elseif( ANDROID_ABI STREQUAL "armeabi-v7a") + set( ARMEABI_V7A true ) + set( ANDROID_NDK_ABI_NAME "armeabi-v7a" ) + set( ANDROID_ARCH_NAME "arm" ) + set( ANDROID_LLVM_TRIPLE "armv7-none-linux-androideabi" ) + set( CMAKE_SYSTEM_PROCESSOR "armv7-a" ) +elseif( ANDROID_ABI STREQUAL "armeabi-v7a with VFPV3" ) + set( ARMEABI_V7A true ) + set( ANDROID_NDK_ABI_NAME "armeabi-v7a" ) + set( ANDROID_ARCH_NAME "arm" ) + set( ANDROID_LLVM_TRIPLE "armv7-none-linux-androideabi" ) + set( CMAKE_SYSTEM_PROCESSOR "armv7-a" ) + set( VFPV3 true ) +elseif( ANDROID_ABI STREQUAL "armeabi-v7a with NEON" ) + set( ARMEABI_V7A true ) + set( ANDROID_NDK_ABI_NAME "armeabi-v7a" ) + set( ANDROID_ARCH_NAME "arm" ) + set( ANDROID_LLVM_TRIPLE "armv7-none-linux-androideabi" ) + set( CMAKE_SYSTEM_PROCESSOR "armv7-a" ) + set( VFPV3 true ) + set( NEON true ) +else() + message( SEND_ERROR "Unknown ANDROID_ABI=\"${ANDROID_ABI}\" is specified." ) +endif() + +if( CMAKE_BINARY_DIR AND EXISTS "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeSystem.cmake" ) + # really dirty hack + # it is not possible to change CMAKE_SYSTEM_PROCESSOR after the first run... + file( APPEND "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeSystem.cmake" "SET(CMAKE_SYSTEM_PROCESSOR \"${CMAKE_SYSTEM_PROCESSOR}\")\n" ) +endif() + +if( ANDROID_ARCH_NAME STREQUAL "arm" AND NOT ARMEABI_V6 ) + __INIT_VARIABLE( ANDROID_FORCE_ARM_BUILD VALUES OFF ) + set( ANDROID_FORCE_ARM_BUILD ${ANDROID_FORCE_ARM_BUILD} CACHE BOOL "Use 32-bit ARM instructions instead of Thumb-1" FORCE ) + mark_as_advanced( ANDROID_FORCE_ARM_BUILD ) +else() + unset( ANDROID_FORCE_ARM_BUILD CACHE ) +endif() + +# choose toolchain +if( ANDROID_TOOLCHAIN_NAME ) + list( FIND __availableToolchains "${ANDROID_TOOLCHAIN_NAME}" __toolchainIdx ) + if( __toolchainIdx EQUAL -1 ) + list( SORT __availableToolchains ) + string( REPLACE ";" "\n * " toolchains_list "${__availableToolchains}" ) + set( toolchains_list " * ${toolchains_list}") + message( FATAL_ERROR "Specified toolchain \"${ANDROID_TOOLCHAIN_NAME}\" is missing in your NDK or broken. Please verify that your NDK is working or select another compiler toolchain. +To configure the toolchain set CMake variable ANDROID_TOOLCHAIN_NAME to one of the following values:\n${toolchains_list}\n" ) + endif() + list( GET __availableToolchainArchs ${__toolchainIdx} __toolchainArch ) + if( NOT __toolchainArch STREQUAL ANDROID_ARCH_NAME ) + message( SEND_ERROR "Selected toolchain \"${ANDROID_TOOLCHAIN_NAME}\" is not able to compile binaries for the \"${ANDROID_ARCH_NAME}\" platform." ) + endif() +else() + set( __toolchainIdx -1 ) + set( __applicableToolchains "" ) + set( __toolchainMaxVersion "0.0.0" ) + list( LENGTH __availableToolchains __availableToolchainsCount ) + math( EXPR __availableToolchainsCount "${__availableToolchainsCount}-1" ) + foreach( __idx RANGE ${__availableToolchainsCount} ) + list( GET __availableToolchainArchs ${__idx} __toolchainArch ) + if( __toolchainArch STREQUAL ANDROID_ARCH_NAME ) + list( GET __availableToolchainCompilerVersions ${__idx} __toolchainVersion ) + string( REPLACE "x" "99" __toolchainVersion "${__toolchainVersion}") + if( __toolchainVersion VERSION_GREATER __toolchainMaxVersion ) + set( __toolchainMaxVersion "${__toolchainVersion}" ) + set( __toolchainIdx ${__idx} ) + endif() + endif() + endforeach() + unset( __availableToolchainsCount ) + unset( __toolchainMaxVersion ) + unset( __toolchainVersion ) +endif() +unset( __toolchainArch ) +if( __toolchainIdx EQUAL -1 ) + message( FATAL_ERROR "No one of available compiler toolchains is able to compile for ${ANDROID_ARCH_NAME} platform." ) +endif() +list( GET __availableToolchains ${__toolchainIdx} ANDROID_TOOLCHAIN_NAME ) +list( GET __availableToolchainMachines ${__toolchainIdx} ANDROID_TOOLCHAIN_MACHINE_NAME ) +list( GET __availableToolchainCompilerVersions ${__toolchainIdx} ANDROID_COMPILER_VERSION ) + +unset( __toolchainIdx ) +unset( __availableToolchains ) +unset( __availableToolchainMachines ) +unset( __availableToolchainArchs ) +unset( __availableToolchainCompilerVersions ) + +# choose native API level +__INIT_VARIABLE( ANDROID_NATIVE_API_LEVEL ENV_ANDROID_NATIVE_API_LEVEL ANDROID_API_LEVEL ENV_ANDROID_API_LEVEL ANDROID_STANDALONE_TOOLCHAIN_API_LEVEL ANDROID_DEFAULT_NDK_API_LEVEL_${ANDROID_ARCH_NAME} ANDROID_DEFAULT_NDK_API_LEVEL ) +string( REPLACE "android-" "" ANDROID_NATIVE_API_LEVEL "${ANDROID_NATIVE_API_LEVEL}" ) +string( STRIP "${ANDROID_NATIVE_API_LEVEL}" ANDROID_NATIVE_API_LEVEL ) +# adjust API level +set( __real_api_level ${ANDROID_DEFAULT_NDK_API_LEVEL_${ANDROID_ARCH_NAME}} ) +foreach( __level ${ANDROID_SUPPORTED_NATIVE_API_LEVELS} ) + if( (__level LESS ANDROID_NATIVE_API_LEVEL OR __level STREQUAL ANDROID_NATIVE_API_LEVEL) AND NOT __level LESS __real_api_level ) + set( __real_api_level ${__level} ) + endif() +endforeach() +if( __real_api_level AND NOT ANDROID_NATIVE_API_LEVEL STREQUAL __real_api_level ) + message( STATUS "Adjusting Android API level 'android-${ANDROID_NATIVE_API_LEVEL}' to 'android-${__real_api_level}'") + set( ANDROID_NATIVE_API_LEVEL ${__real_api_level} ) +endif() +unset(__real_api_level) +# validate +list( FIND ANDROID_SUPPORTED_NATIVE_API_LEVELS "${ANDROID_NATIVE_API_LEVEL}" __levelIdx ) +if( __levelIdx EQUAL -1 ) + message( SEND_ERROR "Specified Android native API level 'android-${ANDROID_NATIVE_API_LEVEL}' is not supported by your NDK/toolchain." ) +else() + if( BUILD_WITH_ANDROID_NDK ) + __DETECT_NATIVE_API_LEVEL( __realApiLevel "${ANDROID_NDK}/platforms/android-${ANDROID_NATIVE_API_LEVEL}/arch-${ANDROID_ARCH_NAME}/usr/include/android/api-level.h" ) + if( NOT __realApiLevel EQUAL ANDROID_NATIVE_API_LEVEL AND NOT __realApiLevel GREATER 9000 ) + message( SEND_ERROR "Specified Android API level (${ANDROID_NATIVE_API_LEVEL}) does not match to the level found (${__realApiLevel}). Probably your copy of NDK is broken." ) + endif() + unset( __realApiLevel ) + endif() + set( ANDROID_NATIVE_API_LEVEL "${ANDROID_NATIVE_API_LEVEL}" CACHE STRING "Android API level for native code" FORCE ) + set( CMAKE_ANDROID_API ${ANDROID_NATIVE_API_LEVEL} ) + if( CMAKE_VERSION VERSION_GREATER "2.8" ) + list( SORT ANDROID_SUPPORTED_NATIVE_API_LEVELS ) + set_property( CACHE ANDROID_NATIVE_API_LEVEL PROPERTY STRINGS ${ANDROID_SUPPORTED_NATIVE_API_LEVELS} ) + endif() +endif() +unset( __levelIdx ) + + +# remember target ABI +set( ANDROID_ABI "${ANDROID_ABI}" CACHE STRING "The target ABI for Android. If arm, then armeabi-v7a is recommended for hardware floating point." FORCE ) +if( CMAKE_VERSION VERSION_GREATER "2.8" ) + list( SORT ANDROID_SUPPORTED_ABIS_${ANDROID_ARCH_NAME} ) + set_property( CACHE ANDROID_ABI PROPERTY STRINGS ${ANDROID_SUPPORTED_ABIS_${ANDROID_ARCH_NAME}} ) +endif() + + +# runtime choice (STL, rtti, exceptions) +if( NOT ANDROID_STL ) + set( ANDROID_STL gnustl_static ) +endif() +set( ANDROID_STL "${ANDROID_STL}" CACHE STRING "C++ runtime" ) +set( ANDROID_STL_FORCE_FEATURES ON CACHE BOOL "automatically configure rtti and exceptions support based on C++ runtime" ) +mark_as_advanced( ANDROID_STL ANDROID_STL_FORCE_FEATURES ) + +if( BUILD_WITH_ANDROID_NDK ) + if( NOT "${ANDROID_STL}" MATCHES "^(none|system|system_re|gabi\\+\\+_static|gabi\\+\\+_shared|stlport_static|stlport_shared|gnustl_static|gnustl_shared)$") + message( FATAL_ERROR "ANDROID_STL is set to invalid value \"${ANDROID_STL}\". +The possible values are: + none -> Do not configure the runtime. + system -> Use the default minimal system C++ runtime library. + system_re -> Same as system but with rtti and exceptions. + gabi++_static -> Use the GAbi++ runtime as a static library. + gabi++_shared -> Use the GAbi++ runtime as a shared library. + stlport_static -> Use the STLport runtime as a static library. + stlport_shared -> Use the STLport runtime as a shared library. + gnustl_static -> (default) Use the GNU STL as a static library. + gnustl_shared -> Use the GNU STL as a shared library. +" ) + endif() +elseif( BUILD_WITH_STANDALONE_TOOLCHAIN ) + if( NOT "${ANDROID_STL}" MATCHES "^(none|gnustl_static|gnustl_shared)$") + message( FATAL_ERROR "ANDROID_STL is set to invalid value \"${ANDROID_STL}\". +The possible values are: + none -> Do not configure the runtime. + gnustl_static -> (default) Use the GNU STL as a static library. + gnustl_shared -> Use the GNU STL as a shared library. +" ) + endif() +endif() + +unset( ANDROID_RTTI ) +unset( ANDROID_EXCEPTIONS ) +unset( ANDROID_STL_INCLUDE_DIRS ) +unset( __libstl ) +unset( __libsupcxx ) + +if( NOT _CMAKE_IN_TRY_COMPILE AND ANDROID_NDK_RELEASE STREQUAL "r7b" AND ARMEABI_V7A AND NOT VFPV3 AND ANDROID_STL MATCHES "gnustl" ) + message( WARNING "The GNU STL armeabi-v7a binaries from NDK r7b can crash non-NEON devices. The files provided with NDK r7b were not configured properly, resulting in crashes on Tegra2-based devices and others when trying to use certain floating-point functions (e.g., cosf, sinf, expf). +You are strongly recommended to switch to another NDK release. +" ) +endif() + +if( NOT _CMAKE_IN_TRY_COMPILE AND X86 AND ANDROID_STL MATCHES "gnustl" AND ANDROID_NDK_RELEASE STREQUAL "r6" ) + message( WARNING "The x86 system header file from NDK r6 has incorrect definition for ptrdiff_t. You are recommended to upgrade to a newer NDK release or manually patch the header: +See https://android.googlesource.com/platform/development.git f907f4f9d4e56ccc8093df6fee54454b8bcab6c2 + diff --git a/ndk/platforms/android-9/arch-x86/include/machine/_types.h b/ndk/platforms/android-9/arch-x86/include/machine/_types.h + index 5e28c64..65892a1 100644 + --- a/ndk/platforms/android-9/arch-x86/include/machine/_types.h + +++ b/ndk/platforms/android-9/arch-x86/include/machine/_types.h + @@ -51,7 +51,11 @@ typedef long int ssize_t; + #endif + #ifndef _PTRDIFF_T + #define _PTRDIFF_T + -typedef long ptrdiff_t; + +# ifdef __ANDROID__ + + typedef int ptrdiff_t; + +# else + + typedef long ptrdiff_t; + +# endif + #endif +" ) +endif() + + +# setup paths and STL for standalone toolchain +if( BUILD_WITH_STANDALONE_TOOLCHAIN ) + set( ANDROID_TOOLCHAIN_ROOT "${ANDROID_STANDALONE_TOOLCHAIN}" ) + set( ANDROID_CLANG_TOOLCHAIN_ROOT "${ANDROID_STANDALONE_TOOLCHAIN}" ) + set( ANDROID_SYSROOT "${ANDROID_STANDALONE_TOOLCHAIN}/sysroot" ) + + if( NOT ANDROID_STL STREQUAL "none" ) + set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_STANDALONE_TOOLCHAIN}/include/c++/${ANDROID_COMPILER_VERSION}" ) + if( NOT EXISTS "${ANDROID_STL_INCLUDE_DIRS}" ) + # old location ( pre r8c ) + set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/include/c++/${ANDROID_COMPILER_VERSION}" ) + endif() + if( ARMEABI_V7A AND EXISTS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/${CMAKE_SYSTEM_PROCESSOR}/bits" ) + list( APPEND ANDROID_STL_INCLUDE_DIRS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/${CMAKE_SYSTEM_PROCESSOR}" ) + elseif( ARMEABI AND NOT ANDROID_FORCE_ARM_BUILD AND EXISTS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/thumb/bits" ) + list( APPEND ANDROID_STL_INCLUDE_DIRS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/thumb" ) + else() + list( APPEND ANDROID_STL_INCLUDE_DIRS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}" ) + endif() + # always search static GNU STL to get the location of libsupc++.a + if( ARMEABI_V7A AND NOT ANDROID_FORCE_ARM_BUILD AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/thumb/libstdc++.a" ) + set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/thumb" ) + elseif( ARMEABI_V7A AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libstdc++.a" ) + set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}" ) + elseif( ARMEABI AND NOT ANDROID_FORCE_ARM_BUILD AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libstdc++.a" ) + set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb" ) + elseif( EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libstdc++.a" ) + set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib" ) + endif() + if( __libstl ) + set( __libsupcxx "${__libstl}/libsupc++.a" ) + set( __libstl "${__libstl}/libstdc++.a" ) + endif() + if( NOT EXISTS "${__libsupcxx}" ) + message( FATAL_ERROR "The required libstdsupc++.a is missing in your standalone toolchain. + Usually it happens because of bug in make-standalone-toolchain.sh script from NDK r7, r7b and r7c. + You need to either upgrade to newer NDK or manually copy + $ANDROID_NDK/sources/cxx-stl/gnu-libstdc++/libs/${ANDROID_NDK_ABI_NAME}/libsupc++.a + to + ${__libsupcxx} + " ) + endif() + if( ANDROID_STL STREQUAL "gnustl_shared" ) + if( ARMEABI_V7A AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libgnustl_shared.so" ) + set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libgnustl_shared.so" ) + elseif( ARMEABI AND NOT ANDROID_FORCE_ARM_BUILD AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libgnustl_shared.so" ) + set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libgnustl_shared.so" ) + elseif( EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libgnustl_shared.so" ) + set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libgnustl_shared.so" ) + endif() + endif() + endif() +endif() + +# clang +if( "${ANDROID_TOOLCHAIN_NAME}" STREQUAL "standalone-clang" ) + set( ANDROID_COMPILER_IS_CLANG 1 ) + execute_process( COMMAND "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/clang${TOOL_OS_SUFFIX}" --version OUTPUT_VARIABLE ANDROID_CLANG_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE ) + string( REGEX MATCH "[0-9]+[.][0-9]+" ANDROID_CLANG_VERSION "${ANDROID_CLANG_VERSION}") +elseif( "${ANDROID_TOOLCHAIN_NAME}" MATCHES "-clang3[.][0-9]?$" ) + string( REGEX MATCH "3[.][0-9]$" ANDROID_CLANG_VERSION "${ANDROID_TOOLCHAIN_NAME}") + string( REGEX REPLACE "-clang${ANDROID_CLANG_VERSION}$" "-${ANDROID_COMPILER_VERSION}" ANDROID_GCC_TOOLCHAIN_NAME "${ANDROID_TOOLCHAIN_NAME}" ) + if( NOT EXISTS "${ANDROID_NDK_TOOLCHAINS_PATH}/llvm-${ANDROID_CLANG_VERSION}${ANDROID_NDK_TOOLCHAINS_SUBPATH}/bin/clang${TOOL_OS_SUFFIX}" ) + message( FATAL_ERROR "Could not find the Clang compiler driver" ) + endif() + set( ANDROID_COMPILER_IS_CLANG 1 ) + set( ANDROID_CLANG_TOOLCHAIN_ROOT "${ANDROID_NDK_TOOLCHAINS_PATH}/llvm-${ANDROID_CLANG_VERSION}${ANDROID_NDK_TOOLCHAINS_SUBPATH}" ) +else() + set( ANDROID_GCC_TOOLCHAIN_NAME "${ANDROID_TOOLCHAIN_NAME}" ) + unset( ANDROID_COMPILER_IS_CLANG CACHE ) +endif() + +string( REPLACE "." "" _clang_name "clang${ANDROID_CLANG_VERSION}" ) +if( NOT EXISTS "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}${TOOL_OS_SUFFIX}" ) + set( _clang_name "clang" ) +endif() + + +# setup paths and STL for NDK +if( BUILD_WITH_ANDROID_NDK ) + set( ANDROID_TOOLCHAIN_ROOT "${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}${ANDROID_NDK_TOOLCHAINS_SUBPATH}" ) + set( ANDROID_SYSROOT "${ANDROID_NDK}/platforms/android-${ANDROID_NATIVE_API_LEVEL}/arch-${ANDROID_ARCH_NAME}" ) + + if( ANDROID_STL STREQUAL "none" ) + # do nothing + elseif( ANDROID_STL STREQUAL "system" ) + set( ANDROID_RTTI OFF ) + set( ANDROID_EXCEPTIONS OFF ) + set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/system/include" ) + elseif( ANDROID_STL STREQUAL "system_re" ) + set( ANDROID_RTTI ON ) + set( ANDROID_EXCEPTIONS ON ) + set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/system/include" ) + elseif( ANDROID_STL MATCHES "gabi" ) + if( ANDROID_NDK_RELEASE_NUM LESS 7000 ) # before r7 + message( FATAL_ERROR "gabi++ is not available in your NDK. You have to upgrade to NDK r7 or newer to use gabi++.") + endif() + set( ANDROID_RTTI ON ) + set( ANDROID_EXCEPTIONS OFF ) + set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/gabi++/include" ) + set( __libstl "${ANDROID_NDK}/sources/cxx-stl/gabi++/libs/${ANDROID_NDK_ABI_NAME}/libgabi++_static.a" ) + elseif( ANDROID_STL MATCHES "stlport" ) + if( NOT ANDROID_NDK_RELEASE_NUM LESS 8004 ) # before r8d + set( ANDROID_EXCEPTIONS ON ) + else() + set( ANDROID_EXCEPTIONS OFF ) + endif() + if( ANDROID_NDK_RELEASE_NUM LESS 7000 ) # before r7 + set( ANDROID_RTTI OFF ) + else() + set( ANDROID_RTTI ON ) + endif() + set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/stlport/stlport" ) + set( __libstl "${ANDROID_NDK}/sources/cxx-stl/stlport/libs/${ANDROID_NDK_ABI_NAME}/libstlport_static.a" ) + elseif( ANDROID_STL MATCHES "gnustl" ) + set( ANDROID_EXCEPTIONS ON ) + set( ANDROID_RTTI ON ) + if( EXISTS "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_COMPILER_VERSION}" ) + if( ARMEABI_V7A AND ANDROID_COMPILER_VERSION VERSION_EQUAL "4.7" AND ANDROID_NDK_RELEASE STREQUAL "r8d" ) + # gnustl binary for 4.7 compiler is buggy :( + # TODO: look for right fix + set( __libstl "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/4.6" ) + else() + set( __libstl "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_COMPILER_VERSION}" ) + endif() + else() + set( __libstl "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++" ) + endif() + set( ANDROID_STL_INCLUDE_DIRS "${__libstl}/include" "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/include" "${__libstl}/include/backward" ) + if( EXISTS "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/libgnustl_static.a" ) + set( __libstl "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/libgnustl_static.a" ) + else() + set( __libstl "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/libstdc++.a" ) + endif() + else() + message( FATAL_ERROR "Unknown runtime: ${ANDROID_STL}" ) + endif() + # find libsupc++.a - rtti & exceptions + if( ANDROID_STL STREQUAL "system_re" OR ANDROID_STL MATCHES "gnustl" ) + set( __libsupcxx "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_COMPILER_VERSION}/libs/${ANDROID_NDK_ABI_NAME}/libsupc++.a" ) # r8b or newer + if( NOT EXISTS "${__libsupcxx}" ) + set( __libsupcxx "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/libs/${ANDROID_NDK_ABI_NAME}/libsupc++.a" ) # r7-r8 + endif() + if( NOT EXISTS "${__libsupcxx}" ) # before r7 + if( ARMEABI_V7A ) + if( ANDROID_FORCE_ARM_BUILD ) + set( __libsupcxx "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libsupc++.a" ) + else() + set( __libsupcxx "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/thumb/libsupc++.a" ) + endif() + elseif( ARMEABI AND NOT ANDROID_FORCE_ARM_BUILD ) + set( __libsupcxx "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libsupc++.a" ) + else() + set( __libsupcxx "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libsupc++.a" ) + endif() + endif() + if( NOT EXISTS "${__libsupcxx}") + message( ERROR "Could not find libsupc++.a for a chosen platform. Either your NDK is not supported or is broken.") + endif() + endif() +endif() + + +# case of shared STL linkage +if( ANDROID_STL MATCHES "shared" AND DEFINED __libstl ) + string( REPLACE "_static.a" "_shared.so" __libstl "${__libstl}" ) + # TODO: check if .so file exists before the renaming +endif() + + +# ccache support +__INIT_VARIABLE( _ndk_ccache NDK_CCACHE ENV_NDK_CCACHE ) +if( _ndk_ccache ) + if( DEFINED NDK_CCACHE AND NOT EXISTS NDK_CCACHE ) + unset( NDK_CCACHE CACHE ) + endif() + find_program( NDK_CCACHE "${_ndk_ccache}" DOC "The path to ccache binary") +else() + unset( NDK_CCACHE CACHE ) +endif() +unset( _ndk_ccache ) + + +# setup the cross-compiler +if( NOT CMAKE_C_COMPILER ) + if( NDK_CCACHE AND NOT ANDROID_SYSROOT MATCHES "[ ;\"]" ) + set( CMAKE_C_COMPILER "${NDK_CCACHE}" CACHE PATH "ccache as C compiler" ) + set( CMAKE_CXX_COMPILER "${NDK_CCACHE}" CACHE PATH "ccache as C++ compiler" ) + if( ANDROID_COMPILER_IS_CLANG ) + set( CMAKE_C_COMPILER_ARG1 "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}${TOOL_OS_SUFFIX}" CACHE PATH "C compiler") + set( CMAKE_CXX_COMPILER_ARG1 "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}++${TOOL_OS_SUFFIX}" CACHE PATH "C++ compiler") + else() + set( CMAKE_C_COMPILER_ARG1 "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc${TOOL_OS_SUFFIX}" CACHE PATH "C compiler") + set( CMAKE_CXX_COMPILER_ARG1 "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-g++${TOOL_OS_SUFFIX}" CACHE PATH "C++ compiler") + endif() + else() + if( ANDROID_COMPILER_IS_CLANG ) + set( CMAKE_C_COMPILER "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}${TOOL_OS_SUFFIX}" CACHE PATH "C compiler") + set( CMAKE_CXX_COMPILER "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}++${TOOL_OS_SUFFIX}" CACHE PATH "C++ compiler") + else() + set( CMAKE_C_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc${TOOL_OS_SUFFIX}" CACHE PATH "C compiler" ) + set( CMAKE_CXX_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-g++${TOOL_OS_SUFFIX}" CACHE PATH "C++ compiler" ) + endif() + endif() + set( CMAKE_ASM_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc${TOOL_OS_SUFFIX}" CACHE PATH "assembler" ) + set( CMAKE_STRIP "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-strip${TOOL_OS_SUFFIX}" CACHE PATH "strip" ) + if( EXISTS "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc-ar${TOOL_OS_SUFFIX}" ) + # Use gcc-ar if we have it for better LTO support. + set( CMAKE_AR "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc-ar${TOOL_OS_SUFFIX}" CACHE PATH "archive" ) + else() + set( CMAKE_AR "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-ar${TOOL_OS_SUFFIX}" CACHE PATH "archive" ) + endif() + set( CMAKE_LINKER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-ld${TOOL_OS_SUFFIX}" CACHE PATH "linker" ) + set( CMAKE_NM "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-nm${TOOL_OS_SUFFIX}" CACHE PATH "nm" ) + set( CMAKE_OBJCOPY "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-objcopy${TOOL_OS_SUFFIX}" CACHE PATH "objcopy" ) + set( CMAKE_OBJDUMP "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-objdump${TOOL_OS_SUFFIX}" CACHE PATH "objdump" ) + set( CMAKE_RANLIB "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-ranlib${TOOL_OS_SUFFIX}" CACHE PATH "ranlib" ) +endif() + +set( _CMAKE_TOOLCHAIN_PREFIX "${ANDROID_TOOLCHAIN_MACHINE_NAME}-" ) +if( CMAKE_VERSION VERSION_LESS 2.8.5 ) + set( CMAKE_ASM_COMPILER_ARG1 "-c" ) +endif() +if( APPLE ) + find_program( CMAKE_INSTALL_NAME_TOOL NAMES install_name_tool ) + if( NOT CMAKE_INSTALL_NAME_TOOL ) + message( FATAL_ERROR "Could not find install_name_tool, please check your installation." ) + endif() + mark_as_advanced( CMAKE_INSTALL_NAME_TOOL ) +endif() + +# Force set compilers because standard identification works badly for us +include( CMakeForceCompiler ) +CMAKE_FORCE_C_COMPILER( "${CMAKE_C_COMPILER}" GNU ) +if( ANDROID_COMPILER_IS_CLANG ) + set( CMAKE_C_COMPILER_ID Clang ) +endif() +set( CMAKE_C_PLATFORM_ID Linux ) +if( X86_64 OR MIPS64 OR ARM64_V8A ) + set( CMAKE_C_SIZEOF_DATA_PTR 8 ) +else() + set( CMAKE_C_SIZEOF_DATA_PTR 4 ) +endif() +set( CMAKE_C_HAS_ISYSROOT 1 ) +set( CMAKE_C_COMPILER_ABI ELF ) +CMAKE_FORCE_CXX_COMPILER( "${CMAKE_CXX_COMPILER}" GNU ) +if( ANDROID_COMPILER_IS_CLANG ) + set( CMAKE_CXX_COMPILER_ID Clang) +endif() +set( CMAKE_CXX_PLATFORM_ID Linux ) +set( CMAKE_CXX_SIZEOF_DATA_PTR ${CMAKE_C_SIZEOF_DATA_PTR} ) +set( CMAKE_CXX_HAS_ISYSROOT 1 ) +set( CMAKE_CXX_COMPILER_ABI ELF ) +set( CMAKE_CXX_SOURCE_FILE_EXTENSIONS cc cp cxx cpp CPP c++ C ) +# force ASM compiler (required for CMake < 2.8.5) +set( CMAKE_ASM_COMPILER_ID_RUN TRUE ) +set( CMAKE_ASM_COMPILER_ID GNU ) +set( CMAKE_ASM_COMPILER_WORKS TRUE ) +set( CMAKE_ASM_COMPILER_FORCED TRUE ) +set( CMAKE_COMPILER_IS_GNUASM 1) +set( CMAKE_ASM_SOURCE_FILE_EXTENSIONS s S asm ) + +foreach( lang C CXX ASM ) + if( ANDROID_COMPILER_IS_CLANG ) + set( CMAKE_${lang}_COMPILER_VERSION ${ANDROID_CLANG_VERSION} ) + else() + set( CMAKE_${lang}_COMPILER_VERSION ${ANDROID_COMPILER_VERSION} ) + endif() +endforeach() + +# flags and definitions +remove_definitions( -DANDROID ) +add_definitions( -DANDROID ) + +if( ANDROID_SYSROOT MATCHES "[ ;\"]" ) + if( CMAKE_HOST_WIN32 ) + # try to convert path to 8.3 form + file( WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/cvt83.cmd" "@echo %~s1" ) + execute_process( COMMAND "$ENV{ComSpec}" /c "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/cvt83.cmd" "${ANDROID_SYSROOT}" + OUTPUT_VARIABLE __path OUTPUT_STRIP_TRAILING_WHITESPACE + RESULT_VARIABLE __result ERROR_QUIET ) + if( __result EQUAL 0 ) + file( TO_CMAKE_PATH "${__path}" ANDROID_SYSROOT ) + set( ANDROID_CXX_FLAGS "--sysroot=${ANDROID_SYSROOT}" ) + else() + set( ANDROID_CXX_FLAGS "--sysroot=\"${ANDROID_SYSROOT}\"" ) + endif() + else() + set( ANDROID_CXX_FLAGS "'--sysroot=${ANDROID_SYSROOT}'" ) + endif() + if( NOT _CMAKE_IN_TRY_COMPILE ) + # quotes can break try_compile and compiler identification + message(WARNING "Path to your Android NDK (or toolchain) has non-alphanumeric symbols.\nThe build might be broken.\n") + endif() +else() + set( ANDROID_CXX_FLAGS "--sysroot=${ANDROID_SYSROOT}" ) +endif() + +# NDK flags +if (ARM64_V8A ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funwind-tables" ) + set( ANDROID_CXX_FLAGS_RELEASE "-fomit-frame-pointer -fstrict-aliasing" ) + set( ANDROID_CXX_FLAGS_DEBUG "-fno-omit-frame-pointer -fno-strict-aliasing" ) + if( NOT ANDROID_COMPILER_IS_CLANG ) + set( ANDROID_CXX_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE} -funswitch-loops -finline-limit=300" ) + endif() +elseif( ARMEABI OR ARMEABI_V7A) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funwind-tables" ) + if( NOT ANDROID_FORCE_ARM_BUILD AND NOT ARMEABI_V6 ) + set( ANDROID_CXX_FLAGS_RELEASE "-mthumb -fomit-frame-pointer -fno-strict-aliasing" ) + set( ANDROID_CXX_FLAGS_DEBUG "-marm -fno-omit-frame-pointer -fno-strict-aliasing" ) + if( NOT ANDROID_COMPILER_IS_CLANG ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -finline-limit=64" ) + endif() + else() + # always compile ARMEABI_V6 in arm mode; otherwise there is no difference from ARMEABI + set( ANDROID_CXX_FLAGS_RELEASE "-marm -fomit-frame-pointer -fstrict-aliasing" ) + set( ANDROID_CXX_FLAGS_DEBUG "-marm -fno-omit-frame-pointer -fno-strict-aliasing" ) + if( NOT ANDROID_COMPILER_IS_CLANG ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funswitch-loops -finline-limit=300" ) + endif() + endif() +elseif( X86 OR X86_64 ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funwind-tables" ) + if( NOT ANDROID_COMPILER_IS_CLANG ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funswitch-loops -finline-limit=300" ) + endif() + set( ANDROID_CXX_FLAGS_RELEASE "-fomit-frame-pointer -fstrict-aliasing" ) + set( ANDROID_CXX_FLAGS_DEBUG "-fno-omit-frame-pointer -fno-strict-aliasing" ) +elseif( MIPS OR MIPS64 ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fno-strict-aliasing -finline-functions -funwind-tables -fmessage-length=0" ) + set( ANDROID_CXX_FLAGS_RELEASE "-fomit-frame-pointer" ) + set( ANDROID_CXX_FLAGS_DEBUG "-fno-omit-frame-pointer" ) + if( NOT ANDROID_COMPILER_IS_CLANG ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fno-inline-functions-called-once -fgcse-after-reload -frerun-cse-after-loop -frename-registers" ) + set( ANDROID_CXX_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE} -funswitch-loops -finline-limit=300" ) + endif() +elseif() + set( ANDROID_CXX_FLAGS_RELEASE "" ) + set( ANDROID_CXX_FLAGS_DEBUG "" ) +endif() + +set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fsigned-char" ) # good/necessary when porting desktop libraries + +if( NOT X86 AND NOT ANDROID_COMPILER_IS_CLANG ) + set( ANDROID_CXX_FLAGS "-Wno-psabi ${ANDROID_CXX_FLAGS}" ) +endif() + +if( NOT ANDROID_COMPILER_VERSION VERSION_LESS "4.6" ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -no-canonical-prefixes" ) # see https://android-review.googlesource.com/#/c/47564/ +endif() + +# ABI-specific flags +if( ARMEABI_V7A ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -march=armv7-a -mfloat-abi=softfp" ) + if( NEON ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -mfpu=neon" ) + elseif( VFPV3 ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -mfpu=vfpv3" ) + else() + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -mfpu=vfpv3-d16" ) + endif() +elseif( ARMEABI_V6 ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -march=armv6 -mfloat-abi=softfp -mfpu=vfp" ) # vfp == vfpv2 +elseif( ARMEABI ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -march=armv5te -mtune=xscale -msoft-float" ) +endif() + +if( ANDROID_STL MATCHES "gnustl" AND (EXISTS "${__libstl}" OR EXISTS "${__libsupcxx}") ) + set( CMAKE_CXX_CREATE_SHARED_LIBRARY " -o " ) + set( CMAKE_CXX_CREATE_SHARED_MODULE " -o " ) + set( CMAKE_CXX_LINK_EXECUTABLE " -o " ) +else() + set( CMAKE_CXX_CREATE_SHARED_LIBRARY " -o " ) + set( CMAKE_CXX_CREATE_SHARED_MODULE " -o " ) + set( CMAKE_CXX_LINK_EXECUTABLE " -o " ) +endif() + +# STL +if( EXISTS "${__libstl}" OR EXISTS "${__libsupcxx}" ) + if( EXISTS "${__libstl}" ) + set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} \"${__libstl}\"" ) + set( CMAKE_CXX_CREATE_SHARED_MODULE "${CMAKE_CXX_CREATE_SHARED_MODULE} \"${__libstl}\"" ) + set( CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE} \"${__libstl}\"" ) + endif() + if( EXISTS "${__libsupcxx}" ) + set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} \"${__libsupcxx}\"" ) + set( CMAKE_CXX_CREATE_SHARED_MODULE "${CMAKE_CXX_CREATE_SHARED_MODULE} \"${__libsupcxx}\"" ) + set( CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE} \"${__libsupcxx}\"" ) + # C objects: + set( CMAKE_C_CREATE_SHARED_LIBRARY " -o " ) + set( CMAKE_C_CREATE_SHARED_MODULE " -o " ) + set( CMAKE_C_LINK_EXECUTABLE " -o " ) + set( CMAKE_C_CREATE_SHARED_LIBRARY "${CMAKE_C_CREATE_SHARED_LIBRARY} \"${__libsupcxx}\"" ) + set( CMAKE_C_CREATE_SHARED_MODULE "${CMAKE_C_CREATE_SHARED_MODULE} \"${__libsupcxx}\"" ) + set( CMAKE_C_LINK_EXECUTABLE "${CMAKE_C_LINK_EXECUTABLE} \"${__libsupcxx}\"" ) + endif() + if( ANDROID_STL MATCHES "gnustl" ) + if( NOT EXISTS "${ANDROID_LIBM_PATH}" ) + set( ANDROID_LIBM_PATH -lm ) + endif() + set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} ${ANDROID_LIBM_PATH}" ) + set( CMAKE_CXX_CREATE_SHARED_MODULE "${CMAKE_CXX_CREATE_SHARED_MODULE} ${ANDROID_LIBM_PATH}" ) + set( CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE} ${ANDROID_LIBM_PATH}" ) + endif() +endif() + +# variables controlling optional build flags +if( ANDROID_NDK_RELEASE_NUM LESS 7000 ) # before r7 + # libGLESv2.so in NDK's prior to r7 refers to missing external symbols. + # So this flag option is required for all projects using OpenGL from native. + __INIT_VARIABLE( ANDROID_SO_UNDEFINED VALUES ON ) +else() + __INIT_VARIABLE( ANDROID_SO_UNDEFINED VALUES OFF ) +endif() +__INIT_VARIABLE( ANDROID_NO_UNDEFINED VALUES ON ) +__INIT_VARIABLE( ANDROID_FUNCTION_LEVEL_LINKING VALUES ON ) +__INIT_VARIABLE( ANDROID_GOLD_LINKER VALUES ON ) +__INIT_VARIABLE( ANDROID_NOEXECSTACK VALUES ON ) +__INIT_VARIABLE( ANDROID_RELRO VALUES ON ) + +set( ANDROID_NO_UNDEFINED ${ANDROID_NO_UNDEFINED} CACHE BOOL "Show all undefined symbols as linker errors" ) +set( ANDROID_SO_UNDEFINED ${ANDROID_SO_UNDEFINED} CACHE BOOL "Allows or disallows undefined symbols in shared libraries" ) +set( ANDROID_FUNCTION_LEVEL_LINKING ${ANDROID_FUNCTION_LEVEL_LINKING} CACHE BOOL "Put each function in separate section and enable garbage collection of unused input sections at link time" ) +set( ANDROID_GOLD_LINKER ${ANDROID_GOLD_LINKER} CACHE BOOL "Enables gold linker" ) +set( ANDROID_NOEXECSTACK ${ANDROID_NOEXECSTACK} CACHE BOOL "Allows or disallows undefined symbols in shared libraries" ) +set( ANDROID_RELRO ${ANDROID_RELRO} CACHE BOOL "Enables RELRO - a memory corruption mitigation technique" ) +mark_as_advanced( ANDROID_NO_UNDEFINED ANDROID_SO_UNDEFINED ANDROID_FUNCTION_LEVEL_LINKING ANDROID_GOLD_LINKER ANDROID_NOEXECSTACK ANDROID_RELRO ) + +# linker flags +set( ANDROID_LINKER_FLAGS "" ) + +if( ARMEABI_V7A ) + # this is *required* to use the following linker flags that routes around + # a CPU bug in some Cortex-A8 implementations: + set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--fix-cortex-a8" ) +endif() + +if( ANDROID_NO_UNDEFINED ) + if( MIPS ) + # there is some sysroot-related problem in mips linker... + if( NOT ANDROID_SYSROOT MATCHES "[ ;\"]" ) + set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--no-undefined -Wl,-rpath-link,${ANDROID_SYSROOT}/usr/lib" ) + endif() + else() + set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--no-undefined" ) + endif() +endif() + +if( ANDROID_SO_UNDEFINED ) + set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,-allow-shlib-undefined" ) +endif() + +if( ANDROID_FUNCTION_LEVEL_LINKING ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fdata-sections -ffunction-sections" ) + set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--gc-sections" ) +endif() + +if( ANDROID_COMPILER_VERSION VERSION_EQUAL "4.6" ) + if( ANDROID_GOLD_LINKER AND (CMAKE_HOST_UNIX OR ANDROID_NDK_RELEASE_NUM GREATER 8002) AND (ARMEABI OR ARMEABI_V7A OR X86) ) + set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -fuse-ld=gold" ) + elseif( ANDROID_NDK_RELEASE_NUM GREATER 8002 ) # after r8b + set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -fuse-ld=bfd" ) + elseif( ANDROID_NDK_RELEASE STREQUAL "r8b" AND ARMEABI AND NOT _CMAKE_IN_TRY_COMPILE ) + message( WARNING "The default bfd linker from arm GCC 4.6 toolchain can fail with 'unresolvable R_ARM_THM_CALL relocation' error message. See https://code.google.com/p/android/issues/detail?id=35342 + On Linux and OS X host platform you can workaround this problem using gold linker (default). + Rerun cmake with -DANDROID_GOLD_LINKER=ON option in case of problems. +" ) + endif() +endif() # version 4.6 + +if( ANDROID_NOEXECSTACK ) + if( ANDROID_COMPILER_IS_CLANG ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -Xclang -mnoexecstack" ) + else() + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -Wa,--noexecstack" ) + endif() + set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,-z,noexecstack" ) +endif() + +if( ANDROID_RELRO ) + set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,-z,relro -Wl,-z,now" ) +endif() + +if( ANDROID_COMPILER_IS_CLANG ) + set( ANDROID_CXX_FLAGS "-target ${ANDROID_LLVM_TRIPLE} -Qunused-arguments ${ANDROID_CXX_FLAGS}" ) + if( BUILD_WITH_ANDROID_NDK ) + set( ANDROID_CXX_FLAGS "-gcc-toolchain ${ANDROID_TOOLCHAIN_ROOT} ${ANDROID_CXX_FLAGS}" ) + endif() +endif() + +# cache flags +set( CMAKE_CXX_FLAGS "" CACHE STRING "c++ flags" ) +set( CMAKE_C_FLAGS "" CACHE STRING "c flags" ) +set( CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG" CACHE STRING "c++ Release flags" ) +set( CMAKE_C_FLAGS_RELEASE "-O3 -DNDEBUG" CACHE STRING "c Release flags" ) +set( CMAKE_CXX_FLAGS_DEBUG "-O0 -g -DDEBUG -D_DEBUG" CACHE STRING "c++ Debug flags" ) +set( CMAKE_C_FLAGS_DEBUG "-O0 -g -DDEBUG -D_DEBUG" CACHE STRING "c Debug flags" ) +set( CMAKE_SHARED_LINKER_FLAGS "" CACHE STRING "shared linker flags" ) +set( CMAKE_MODULE_LINKER_FLAGS "" CACHE STRING "module linker flags" ) +set( CMAKE_EXE_LINKER_FLAGS "-Wl,-z,nocopyreloc" CACHE STRING "executable linker flags" ) + +# put flags to cache (for debug purpose only) +set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS}" CACHE INTERNAL "Android specific c/c++ flags" ) +set( ANDROID_CXX_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE}" CACHE INTERNAL "Android specific c/c++ Release flags" ) +set( ANDROID_CXX_FLAGS_DEBUG "${ANDROID_CXX_FLAGS_DEBUG}" CACHE INTERNAL "Android specific c/c++ Debug flags" ) +set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS}" CACHE INTERNAL "Android specific c/c++ linker flags" ) + +# finish flags +set( CMAKE_CXX_FLAGS "${ANDROID_CXX_FLAGS} ${CMAKE_CXX_FLAGS}" ) +set( CMAKE_C_FLAGS "${ANDROID_CXX_FLAGS} ${CMAKE_C_FLAGS}" ) +set( CMAKE_CXX_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE} ${CMAKE_CXX_FLAGS_RELEASE}" ) +set( CMAKE_C_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE} ${CMAKE_C_FLAGS_RELEASE}" ) +set( CMAKE_CXX_FLAGS_DEBUG "${ANDROID_CXX_FLAGS_DEBUG} ${CMAKE_CXX_FLAGS_DEBUG}" ) +set( CMAKE_C_FLAGS_DEBUG "${ANDROID_CXX_FLAGS_DEBUG} ${CMAKE_C_FLAGS_DEBUG}" ) +set( CMAKE_SHARED_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} ${CMAKE_SHARED_LINKER_FLAGS}" ) +set( CMAKE_MODULE_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} ${CMAKE_MODULE_LINKER_FLAGS}" ) +set( CMAKE_EXE_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} ${CMAKE_EXE_LINKER_FLAGS}" ) + +if( MIPS AND BUILD_WITH_ANDROID_NDK AND ANDROID_NDK_RELEASE STREQUAL "r8" ) + set( CMAKE_SHARED_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}/mipself.xsc ${CMAKE_SHARED_LINKER_FLAGS}" ) + set( CMAKE_MODULE_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}/mipself.xsc ${CMAKE_MODULE_LINKER_FLAGS}" ) + set( CMAKE_EXE_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}/mipself.x ${CMAKE_EXE_LINKER_FLAGS}" ) +endif() + +# pie/pic +if( NOT (ANDROID_NATIVE_API_LEVEL LESS 16) AND (NOT DEFINED ANDROID_APP_PIE OR ANDROID_APP_PIE) AND (CMAKE_VERSION VERSION_GREATER 2.8.8) ) + set( CMAKE_POSITION_INDEPENDENT_CODE TRUE ) + set( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fPIE -pie") +else() + set( CMAKE_POSITION_INDEPENDENT_CODE FALSE ) + set( CMAKE_CXX_FLAGS "-fpic ${CMAKE_CXX_FLAGS}" ) + set( CMAKE_C_FLAGS "-fpic ${CMAKE_C_FLAGS}" ) +endif() + +# configure rtti +if( DEFINED ANDROID_RTTI AND ANDROID_STL_FORCE_FEATURES ) + if( ANDROID_RTTI ) + set( CMAKE_CXX_FLAGS "-frtti ${CMAKE_CXX_FLAGS}" ) + else() + set( CMAKE_CXX_FLAGS "-fno-rtti ${CMAKE_CXX_FLAGS}" ) + endif() +endif() + +# configure exceptios +if( DEFINED ANDROID_EXCEPTIONS AND ANDROID_STL_FORCE_FEATURES ) + if( ANDROID_EXCEPTIONS ) + set( CMAKE_CXX_FLAGS "-fexceptions ${CMAKE_CXX_FLAGS}" ) + set( CMAKE_C_FLAGS "-fexceptions ${CMAKE_C_FLAGS}" ) + else() + set( CMAKE_CXX_FLAGS "-fno-exceptions ${CMAKE_CXX_FLAGS}" ) + set( CMAKE_C_FLAGS "-fno-exceptions ${CMAKE_C_FLAGS}" ) + endif() +endif() + +# global includes and link directories +include_directories( SYSTEM "${ANDROID_SYSROOT}/usr/include" ${ANDROID_STL_INCLUDE_DIRS} ) +get_filename_component(__android_install_path "${CMAKE_INSTALL_PREFIX}/libs/${ANDROID_NDK_ABI_NAME}" ABSOLUTE) # avoid CMP0015 policy warning +link_directories( "${__android_install_path}" ) + +# detect if need link crtbegin_so.o explicitly +if( NOT DEFINED ANDROID_EXPLICIT_CRT_LINK ) + set( __cmd "${CMAKE_CXX_CREATE_SHARED_LIBRARY}" ) + string( REPLACE "" "${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1}" __cmd "${__cmd}" ) + string( REPLACE "" "${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_ARG1}" __cmd "${__cmd}" ) + string( REPLACE "" "${CMAKE_CXX_FLAGS}" __cmd "${__cmd}" ) + string( REPLACE "" "" __cmd "${__cmd}" ) + string( REPLACE "" "${CMAKE_SHARED_LINKER_FLAGS}" __cmd "${__cmd}" ) + string( REPLACE "" "-shared" __cmd "${__cmd}" ) + string( REPLACE "" "" __cmd "${__cmd}" ) + string( REPLACE "" "" __cmd "${__cmd}" ) + string( REPLACE "" "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/toolchain_crtlink_test.so" __cmd "${__cmd}" ) + string( REPLACE "" "\"${ANDROID_SYSROOT}/usr/lib/crtbegin_so.o\"" __cmd "${__cmd}" ) + string( REPLACE "" "" __cmd "${__cmd}" ) + separate_arguments( __cmd ) + foreach( __var ANDROID_NDK ANDROID_NDK_TOOLCHAINS_PATH ANDROID_STANDALONE_TOOLCHAIN ) + if( ${__var} ) + set( __tmp "${${__var}}" ) + separate_arguments( __tmp ) + string( REPLACE "${__tmp}" "${${__var}}" __cmd "${__cmd}") + endif() + endforeach() + string( REPLACE "'" "" __cmd "${__cmd}" ) + string( REPLACE "\"" "" __cmd "${__cmd}" ) + execute_process( COMMAND ${__cmd} RESULT_VARIABLE __cmd_result OUTPUT_QUIET ERROR_QUIET ) + if( __cmd_result EQUAL 0 ) + set( ANDROID_EXPLICIT_CRT_LINK ON ) + else() + set( ANDROID_EXPLICIT_CRT_LINK OFF ) + endif() +endif() + +if( ANDROID_EXPLICIT_CRT_LINK ) + set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} \"${ANDROID_SYSROOT}/usr/lib/crtbegin_so.o\"" ) + set( CMAKE_CXX_CREATE_SHARED_MODULE "${CMAKE_CXX_CREATE_SHARED_MODULE} \"${ANDROID_SYSROOT}/usr/lib/crtbegin_so.o\"" ) +endif() + +# setup output directories +set( CMAKE_INSTALL_PREFIX "${ANDROID_TOOLCHAIN_ROOT}/user" CACHE STRING "path for installing" ) + +if( DEFINED LIBRARY_OUTPUT_PATH_ROOT + OR EXISTS "${CMAKE_SOURCE_DIR}/AndroidManifest.xml" + OR (EXISTS "${CMAKE_SOURCE_DIR}/../AndroidManifest.xml" AND EXISTS "${CMAKE_SOURCE_DIR}/../jni/") ) + set( LIBRARY_OUTPUT_PATH_ROOT ${CMAKE_SOURCE_DIR} CACHE PATH "Root for binaries output, set this to change where Android libs are installed to" ) + if( NOT _CMAKE_IN_TRY_COMPILE ) + if( EXISTS "${CMAKE_SOURCE_DIR}/jni/CMakeLists.txt" ) + set( EXECUTABLE_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/bin/${ANDROID_NDK_ABI_NAME}" CACHE PATH "Output directory for applications" ) + else() + set( EXECUTABLE_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/bin" CACHE PATH "Output directory for applications" ) + endif() + set( LIBRARY_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/libs/${ANDROID_NDK_ABI_NAME}" CACHE PATH "Output directory for Android libs" ) + endif() +endif() + +# copy shaed stl library to build directory +if( NOT _CMAKE_IN_TRY_COMPILE AND __libstl MATCHES "[.]so$" AND DEFINED LIBRARY_OUTPUT_PATH ) + get_filename_component( __libstlname "${__libstl}" NAME ) + execute_process( COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${__libstl}" "${LIBRARY_OUTPUT_PATH}/${__libstlname}" RESULT_VARIABLE __fileCopyProcess ) + if( NOT __fileCopyProcess EQUAL 0 OR NOT EXISTS "${LIBRARY_OUTPUT_PATH}/${__libstlname}") + message( SEND_ERROR "Failed copying of ${__libstl} to the ${LIBRARY_OUTPUT_PATH}/${__libstlname}" ) + endif() + unset( __fileCopyProcess ) + unset( __libstlname ) +endif() + + +# set these global flags for cmake client scripts to change behavior +set( ANDROID True ) +set( BUILD_ANDROID True ) + +# where is the target environment +set( CMAKE_FIND_ROOT_PATH "${ANDROID_TOOLCHAIN_ROOT}/bin" "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}" "${ANDROID_SYSROOT}" "${CMAKE_INSTALL_PREFIX}" "${CMAKE_INSTALL_PREFIX}/share" ) + +# only search for libraries and includes in the ndk toolchain +set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY ) +set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY ) +set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY ) + + +# macro to find packages on the host OS +macro( find_host_package ) + set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER ) + set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER ) + set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER ) + if( CMAKE_HOST_WIN32 ) + SET( WIN32 1 ) + SET( UNIX ) + elseif( CMAKE_HOST_APPLE ) + SET( APPLE 1 ) + SET( UNIX ) + endif() + find_package( ${ARGN} ) + SET( WIN32 ) + SET( APPLE ) + SET( UNIX 1 ) + set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY ) + set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY ) + set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY ) +endmacro() + + +# macro to find programs on the host OS +macro( find_host_program ) + set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER ) + set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER ) + set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER ) + if( CMAKE_HOST_WIN32 ) + SET( WIN32 1 ) + SET( UNIX ) + elseif( CMAKE_HOST_APPLE ) + SET( APPLE 1 ) + SET( UNIX ) + endif() + find_program( ${ARGN} ) + SET( WIN32 ) + SET( APPLE ) + SET( UNIX 1 ) + set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY ) + set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY ) + set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY ) +endmacro() + + +# export toolchain settings for the try_compile() command +if( NOT _CMAKE_IN_TRY_COMPILE ) + set( __toolchain_config "") + foreach( __var NDK_CCACHE LIBRARY_OUTPUT_PATH_ROOT ANDROID_FORBID_SYGWIN + ANDROID_NDK_HOST_X64 + ANDROID_NDK + ANDROID_NDK_LAYOUT + ANDROID_STANDALONE_TOOLCHAIN + ANDROID_TOOLCHAIN_NAME + ANDROID_ABI + ANDROID_NATIVE_API_LEVEL + ANDROID_STL + ANDROID_STL_FORCE_FEATURES + ANDROID_FORCE_ARM_BUILD + ANDROID_NO_UNDEFINED + ANDROID_SO_UNDEFINED + ANDROID_FUNCTION_LEVEL_LINKING + ANDROID_GOLD_LINKER + ANDROID_NOEXECSTACK + ANDROID_RELRO + ANDROID_LIBM_PATH + ANDROID_EXPLICIT_CRT_LINK + ANDROID_APP_PIE + ) + if( DEFINED ${__var} ) + if( ${__var} MATCHES " ") + set( __toolchain_config "${__toolchain_config}set( ${__var} \"${${__var}}\" CACHE INTERNAL \"\" )\n" ) + else() + set( __toolchain_config "${__toolchain_config}set( ${__var} ${${__var}} CACHE INTERNAL \"\" )\n" ) + endif() + endif() + endforeach() + file( WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/android.toolchain.config.cmake" "${__toolchain_config}" ) + unset( __toolchain_config ) +endif() + + +# force cmake to produce / instead of \ in build commands for Ninja generator +if( CMAKE_GENERATOR MATCHES "Ninja" AND CMAKE_HOST_WIN32 ) + # it is a bad hack after all + # CMake generates Ninja makefiles with UNIX paths only if it thinks that we are going to build with MinGW + set( CMAKE_COMPILER_IS_MINGW TRUE ) # tell CMake that we are MinGW + set( CMAKE_CROSSCOMPILING TRUE ) # stop recursion + enable_language( C ) + enable_language( CXX ) + # unset( CMAKE_COMPILER_IS_MINGW ) # can't unset because CMake does not convert back-slashes in response files without it + unset( MINGW ) +endif() + + +# Variables controlling behavior or set by cmake toolchain: +# ANDROID_ABI : "armeabi-v7a" (default), "armeabi", "armeabi-v7a with NEON", "armeabi-v7a with VFPV3", "armeabi-v6 with VFP", "x86", "mips", "arm64-v8a", "x86_64", "mips64" +# ANDROID_NATIVE_API_LEVEL : 3,4,5,8,9,14,15,16,17,18,19,21 (depends on NDK version) +# ANDROID_STL : gnustl_static/gnustl_shared/stlport_static/stlport_shared/gabi++_static/gabi++_shared/system_re/system/none +# ANDROID_FORBID_SYGWIN : ON/OFF +# ANDROID_NO_UNDEFINED : ON/OFF +# ANDROID_SO_UNDEFINED : OFF/ON (default depends on NDK version) +# ANDROID_FUNCTION_LEVEL_LINKING : ON/OFF +# ANDROID_GOLD_LINKER : ON/OFF +# ANDROID_NOEXECSTACK : ON/OFF +# ANDROID_RELRO : ON/OFF +# ANDROID_FORCE_ARM_BUILD : ON/OFF +# ANDROID_STL_FORCE_FEATURES : ON/OFF +# ANDROID_LIBM_PATH : path to libm.so (set to something like $(TOP)/out/target/product//obj/lib/libm.so) to workaround unresolved `sincos` +# Can be set only at the first run: +# ANDROID_NDK : path to your NDK install +# NDK_CCACHE : path to your ccache executable +# ANDROID_TOOLCHAIN_NAME : the NDK name of compiler toolchain +# ANDROID_NDK_HOST_X64 : try to use x86_64 toolchain (default for x64 host systems) +# ANDROID_NDK_LAYOUT : the inner NDK structure (RELEASE, LINARO, ANDROID) +# LIBRARY_OUTPUT_PATH_ROOT : +# ANDROID_STANDALONE_TOOLCHAIN +# +# Primary read-only variables: +# ANDROID : always TRUE +# ARMEABI : TRUE for arm v6 and older devices +# ARMEABI_V6 : TRUE for arm v6 +# ARMEABI_V7A : TRUE for arm v7a +# ARM64_V8A : TRUE for arm64-v8a +# NEON : TRUE if NEON unit is enabled +# VFPV3 : TRUE if VFP version 3 is enabled +# X86 : TRUE if configured for x86 +# X86_64 : TRUE if configured for x86_64 +# MIPS : TRUE if configured for mips +# MIPS64 : TRUE if configured for mips64 +# BUILD_WITH_ANDROID_NDK : TRUE if NDK is used +# BUILD_WITH_STANDALONE_TOOLCHAIN : TRUE if standalone toolchain is used +# ANDROID_NDK_HOST_SYSTEM_NAME : "windows", "linux-x86" or "darwin-x86" depending on host platform +# ANDROID_NDK_ABI_NAME : "armeabi", "armeabi-v7a", "x86", "mips", "arm64-v8a", "x86_64", "mips64" depending on ANDROID_ABI +# ANDROID_NDK_RELEASE : from r5 to r10d; set only for NDK +# ANDROID_NDK_RELEASE_NUM : numeric ANDROID_NDK_RELEASE version (1000*major+minor) +# ANDROID_ARCH_NAME : "arm", "x86", "mips", "arm64", "x86_64", "mips64" depending on ANDROID_ABI +# ANDROID_SYSROOT : path to the compiler sysroot +# TOOL_OS_SUFFIX : "" or ".exe" depending on host platform +# ANDROID_COMPILER_IS_CLANG : TRUE if clang compiler is used +# +# Secondary (less stable) read-only variables: +# ANDROID_COMPILER_VERSION : GCC version used (not Clang version) +# ANDROID_CLANG_VERSION : version of clang compiler if clang is used +# ANDROID_CXX_FLAGS : C/C++ compiler flags required by Android platform +# ANDROID_SUPPORTED_ABIS : list of currently allowed values for ANDROID_ABI +# ANDROID_TOOLCHAIN_MACHINE_NAME : "arm-linux-androideabi", "arm-eabi" or "i686-android-linux" +# ANDROID_TOOLCHAIN_ROOT : path to the top level of toolchain (standalone or placed inside NDK) +# ANDROID_CLANG_TOOLCHAIN_ROOT : path to clang tools +# ANDROID_SUPPORTED_NATIVE_API_LEVELS : list of native API levels found inside NDK +# ANDROID_STL_INCLUDE_DIRS : stl include paths +# ANDROID_RTTI : if rtti is enabled by the runtime +# ANDROID_EXCEPTIONS : if exceptions are enabled by the runtime +# ANDROID_GCC_TOOLCHAIN_NAME : read-only, differs from ANDROID_TOOLCHAIN_NAME only if clang is used +# +# Defaults: +# ANDROID_DEFAULT_NDK_API_LEVEL +# ANDROID_DEFAULT_NDK_API_LEVEL_${ARCH} +# ANDROID_NDK_SEARCH_PATHS +# ANDROID_SUPPORTED_ABIS_${ARCH} +# ANDROID_SUPPORTED_NDK_VERSIONS diff --git a/external/boringssl/third_party/android-cmake/ndk_links.md b/external/boringssl/third_party/android-cmake/ndk_links.md new file mode 100644 index 0000000000..6d93d61d23 --- /dev/null +++ b/external/boringssl/third_party/android-cmake/ndk_links.md @@ -0,0 +1,211 @@ + +============== r1 ============== (dead links) + +* http://dl.google.com/android/ndk/android-ndk-1.5_r1-windows.zip +* http://dl.google.com/android/ndk/android-ndk-1.5_r1-darwin-x86.zip +* http://dl.google.com/android/ndk/android-ndk-1.5_r1-linux-x86.zip + +============== r2 ============== + +* http://dl.google.com/android/ndk/android-ndk-1.6_r1-windows.zip +* http://dl.google.com/android/ndk/android-ndk-1.6_r1-darwin-x86.zip +* http://dl.google.com/android/ndk/android-ndk-1.6_r1-linux-x86.zip + +============== r3 ============== + +* http://dl.google.com/android/ndk/android-ndk-r3-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r3-darwin-x86.zip +* http://dl.google.com/android/ndk/android-ndk-r3-linux-x86.zip + +============== r4 ============== + +* http://dl.google.com/android/ndk/android-ndk-r4-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r4-darwin-x86.zip +* http://dl.google.com/android/ndk/android-ndk-r4-linux-x86.zip + +============== r4b ============== + +* http://dl.google.com/android/ndk/android-ndk-r4b-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r4b-darwin-x86.zip +* http://dl.google.com/android/ndk/android-ndk-r4b-linux-x86.zip + +============== r5 ============== + +* http://dl.google.com/android/ndk/android-ndk-r5-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r5-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r5-linux-x86.tar.bz2 + +============== r5b ============== + +* http://dl.google.com/android/ndk/android-ndk-r5b-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r5b-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r5b-linux-x86.tar.bz2 + +============== r5c ============== + +* http://dl.google.com/android/ndk/android-ndk-r5c-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r5c-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r5c-linux-x86.tar.bz2 + +============== r6 ============== + +* http://dl.google.com/android/ndk/android-ndk-r6-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r6-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r6-linux-x86.tar.bz2 + +============== r6b ============== + +* http://dl.google.com/android/ndk/android-ndk-r6b-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r6b-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r6b-linux-x86.tar.bz2 + +============== r7 ============== + +* http://dl.google.com/android/ndk/android-ndk-r7-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r7-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r7-linux-x86.tar.bz2 + +============== r7b ============== + +* http://dl.google.com/android/ndk/android-ndk-r7b-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r7b-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r7b-linux-x86.tar.bz2 + +============== r7c ============== + +* http://dl.google.com/android/ndk/android-ndk-r7c-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r7c-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r7c-linux-x86.tar.bz2 + +============== r8 ============== + +* http://dl.google.com/android/ndk/android-ndk-r8-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r8-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r8-linux-x86.tar.bz2 + +============== r8b ============== + +* http://dl.google.com/android/ndk/android-ndk-r8b-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r8b-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r8b-linux-x86.tar.bz2 + +============== r8c ============== + +* http://dl.google.com/android/ndk/android-ndk-r8c-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r8c-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r8c-linux-x86.tar.bz2 + +============== r8d ============== + +* http://dl.google.com/android/ndk/android-ndk-r8d-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r8d-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r8d-linux-x86.tar.bz2 + +============== r8e ============== + +* http://dl.google.com/android/ndk/android-ndk-r8e-windows-x86.zip +* http://dl.google.com/android/ndk/android-ndk-r8e-windows-x86_64.zip +* http://dl.google.com/android/ndk/android-ndk-r8e-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r8e-darwin-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r8e-linux-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r8e-linux-x86_64.tar.bz2 + +============== r9 ============== + +* http://dl.google.com/android/ndk/android-ndk-r9-windows-x86.zip +* http://dl.google.com/android/ndk/android-ndk-r9-windows-x86-legacy-toolchains.zip +* http://dl.google.com/android/ndk/android-ndk-r9-windows-x86_64.zip +* http://dl.google.com/android/ndk/android-ndk-r9-windows-x86_64-legacy-toolchains.zip +* http://dl.google.com/android/ndk/android-ndk-r9-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9-darwin-x86-legacy-toolchains.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9-darwin-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9-darwin-x86_64-legacy-toolchains.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9-linux-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9-linux-x86-legacy-toolchains.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9-linux-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9-linux-x86_64-legacy-toolchains.tar.bz2 + +============== r9b ============== + +* http://dl.google.com/android/ndk/android-ndk-r9b-windows-x86.zip +* http://dl.google.com/android/ndk/android-ndk-r9b-windows-x86-legacy-toolchains.zip +* http://dl.google.com/android/ndk/android-ndk-r9b-windows-x86_64.zip +* http://dl.google.com/android/ndk/android-ndk-r9b-windows-x86_64-legacy-toolchains.zip +* http://dl.google.com/android/ndk/android-ndk-r9b-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9b-darwin-x86-legacy-toolchains.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9b-darwin-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9b-darwin-x86_64-legacy-toolchains.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9b-linux-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9b-linux-x86-legacy-toolchains.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9b-linux-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9b-linux-x86_64-legacy-toolchains.tar.bz2 + +============== r9c ============== + +* http://dl.google.com/android/ndk/android-ndk-r9c-windows-x86.zip +* http://dl.google.com/android/ndk/android-ndk-r9c-windows-x86_64.zip +* http://dl.google.com/android/ndk/android-ndk-r9c-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9c-darwin-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9c-linux-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9c-linux-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9c-cxx-stl-libs-with-debugging-info.zip + +============== r9d ============== + +* http://dl.google.com/android/ndk/android-ndk-r9d-windows-x86.zip +* http://dl.google.com/android/ndk/android-ndk-r9d-windows-x86_64.zip +* http://dl.google.com/android/ndk/android-ndk-r9d-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9d-darwin-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9d-linux-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9d-linux-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9d-cxx-stl-libs-with-debug-info.zip + +============== r10 ============== + +* http://dl.google.com/android/ndk/android-ndk32-r10-windows-x86.zip +* http://dl.google.com/android/ndk/android-ndk32-r10-windows-x86_64.zip +* http://dl.google.com/android/ndk/android-ndk32-r10-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk32-r10-darwin-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk32-r10-linux-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk32-r10-linux-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk64-r10-windows-x86.zip +* http://dl.google.com/android/ndk/android-ndk64-r10-windows-x86_64.zip +* http://dl.google.com/android/ndk/android-ndk64-r10-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk64-r10-darwin-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk64-r10-linux-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk64-r10-linux-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r10-cxx-stl-libs-with-debug-info.zip + +============== r10b ============== + +* http://dl.google.com/android/ndk/android-ndk32-r10b-windows-x86.zip +* http://dl.google.com/android/ndk/android-ndk32-r10b-windows-x86_64.zip +* http://dl.google.com/android/ndk/android-ndk32-r10b-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk32-r10b-darwin-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk32-r10b-linux-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk32-r10b-linux-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk64-r10b-windows-x86.zip +* http://dl.google.com/android/ndk/android-ndk64-r10b-windows-x86_64.zip +* http://dl.google.com/android/ndk/android-ndk64-r10b-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk64-r10b-darwin-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk64-r10b-linux-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk64-r10b-linux-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r10b-cxx-stl-libs-with-debug-info.zip + +============== r10c ============== + +* http://dl.google.com/android/ndk/android-ndk-r10c-windows-x86.exe +* http://dl.google.com/android/ndk/android-ndk-r10c-windows-x86_64.exe +* http://dl.google.com/android/ndk/android-ndk-r10c-darwin-x86.bin +* http://dl.google.com/android/ndk/android-ndk-r10c-darwin-x86_64.bin +* http://dl.google.com/android/ndk/android-ndk-r10c-linux-x86.bin +* http://dl.google.com/android/ndk/android-ndk-r10c-linux-x86_64.bin + +============== r10d ============== + +* http://dl.google.com/android/ndk/android-ndk-r10d-windows-x86.exe +* http://dl.google.com/android/ndk/android-ndk-r10d-windows-x86_64.exe +* http://dl.google.com/android/ndk/android-ndk-r10d-darwin-x86.bin +* http://dl.google.com/android/ndk/android-ndk-r10d-darwin-x86_64.bin +* http://dl.google.com/android/ndk/android-ndk-r10d-linux-x86.bin +* http://dl.google.com/android/ndk/android-ndk-r10d-linux-x86_64.bin diff --git a/external/boringssl/tool/CMakeLists.txt b/external/boringssl/tool/CMakeLists.txt new file mode 100644 index 0000000000..f0af28353e --- /dev/null +++ b/external/boringssl/tool/CMakeLists.txt @@ -0,0 +1,30 @@ +include_directories(../include) + +add_executable( + bssl + + args.cc + ciphers.cc + client.cc + const.cc + digest.cc + generate_ed25519.cc + genrsa.cc + pkcs12.cc + rand.cc + server.cc + speed.cc + tool.cc + transport_common.cc +) + +if (APPLE OR WIN32 OR ANDROID) + target_link_libraries(bssl ssl crypto) +else() + find_library(FOUND_LIBRT rt) + if (FOUND_LIBRT) + target_link_libraries(bssl ssl crypto -lrt) + else() + target_link_libraries(bssl ssl crypto) + endif() +endif() diff --git a/external/boringssl/tool/args.cc b/external/boringssl/tool/args.cc new file mode 100644 index 0000000000..9ec18a3f5b --- /dev/null +++ b/external/boringssl/tool/args.cc @@ -0,0 +1,104 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include + +#include +#include +#include +#include + +#include "internal.h" + + +bool ParseKeyValueArguments(std::map *out_args, + const std::vector &args, + const struct argument *templates) { + out_args->clear(); + + for (size_t i = 0; i < args.size(); i++) { + const std::string &arg = args[i]; + const struct argument *templ = nullptr; + for (size_t j = 0; templates[j].name[0] != 0; j++) { + if (strcmp(arg.c_str(), templates[j].name) == 0) { + templ = &templates[j]; + break; + } + } + + if (templ == nullptr) { + fprintf(stderr, "Unknown argument: %s\n", arg.c_str()); + return false; + } + + if (out_args->find(arg) != out_args->end()) { + fprintf(stderr, "Duplicate argument: %s\n", arg.c_str()); + return false; + } + + if (templ->type == kBooleanArgument) { + (*out_args)[arg] = ""; + } else { + if (i + 1 >= args.size()) { + fprintf(stderr, "Missing argument for option: %s\n", arg.c_str()); + return false; + } + (*out_args)[arg] = args[++i]; + } + } + + for (size_t j = 0; templates[j].name[0] != 0; j++) { + const struct argument *templ = &templates[j]; + if (templ->type == kRequiredArgument && + out_args->find(templ->name) == out_args->end()) { + fprintf(stderr, "Missing value for required argument: %s\n", templ->name); + return false; + } + } + + return true; +} + +void PrintUsage(const struct argument *templates) { + for (size_t i = 0; templates[i].name[0] != 0; i++) { + const struct argument *templ = &templates[i]; + fprintf(stderr, "%s\t%s\n", templ->name, templ->description); + } +} + +bool GetUnsigned(unsigned *out, const std::string &arg_name, + unsigned default_value, + const std::map &args) { + const auto &it = args.find(arg_name); + if (it == args.end()) { + *out = default_value; + return true; + } + + const std::string &value = it->second; + if (value.empty()) { + return false; + } + + char *endptr; + unsigned long int num = strtoul(value.c_str(), &endptr, 10); + if (*endptr || + num > UINT_MAX) { + return false; + } + + *out = num; + return true; +} diff --git a/external/boringssl/tool/ciphers.cc b/external/boringssl/tool/ciphers.cc new file mode 100644 index 0000000000..d7cc36b842 --- /dev/null +++ b/external/boringssl/tool/ciphers.cc @@ -0,0 +1,66 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include + +#include +#include + +#include + +#include "../crypto/test/scoped_types.h" +#include "../ssl/test/scoped_types.h" +#include "internal.h" + + +bool Ciphers(const std::vector &args) { + if (args.size() != 1) { + fprintf(stderr, "Usage: bssl ciphers \n"); + return false; + } + + const std::string &ciphers_string = args.back(); + + ScopedSSL_CTX ctx(SSL_CTX_new(SSLv23_client_method())); + if (!SSL_CTX_set_cipher_list(ctx.get(), ciphers_string.c_str())) { + fprintf(stderr, "Failed to parse cipher suite config.\n"); + ERR_print_errors_fp(stderr); + return false; + } + + const struct ssl_cipher_preference_list_st *pref_list = ctx->cipher_list; + STACK_OF(SSL_CIPHER) *ciphers = pref_list->ciphers; + + bool last_in_group = false; + for (size_t i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) { + bool in_group = pref_list->in_group_flags[i]; + const SSL_CIPHER *cipher = sk_SSL_CIPHER_value(ciphers, i); + + if (in_group && !last_in_group) { + printf("[\n "); + } else if (last_in_group) { + printf(" "); + } + + printf("%s\n", SSL_CIPHER_get_name(cipher)); + + if (!in_group && last_in_group) { + printf("]\n"); + } + last_in_group = in_group; + } + + return true; +} diff --git a/external/boringssl/tool/client.cc b/external/boringssl/tool/client.cc new file mode 100644 index 0000000000..dbec1846e5 --- /dev/null +++ b/external/boringssl/tool/client.cc @@ -0,0 +1,311 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include + +#include +#include +#include + +#include "../crypto/test/scoped_types.h" +#include "../ssl/test/scoped_types.h" +#include "internal.h" +#include "transport_common.h" + + +static const struct argument kArguments[] = { + { + "-connect", kRequiredArgument, + "The hostname and port of the server to connect to, e.g. foo.com:443", + }, + { + "-cipher", kOptionalArgument, + "An OpenSSL-style cipher suite string that configures the offered ciphers", + }, + { + "-max-version", kOptionalArgument, + "The maximum acceptable protocol version", + }, + { + "-min-version", kOptionalArgument, + "The minimum acceptable protocol version", + }, + { + "-server-name", kOptionalArgument, + "The server name to advertise", + }, + { + "-select-next-proto", kOptionalArgument, + "An NPN protocol to select if the server supports NPN", + }, + { + "-alpn-protos", kOptionalArgument, + "A comma-separated list of ALPN protocols to advertise", + }, + { + "-fallback-scsv", kBooleanArgument, + "Enable FALLBACK_SCSV", + }, + { + "-ocsp-stapling", kBooleanArgument, + "Advertise support for OCSP stabling", + }, + { + "-signed-certificate-timestamps", kBooleanArgument, + "Advertise support for signed certificate timestamps", + }, + { + "-channel-id-key", kOptionalArgument, + "The key to use for signing a channel ID", + }, + { + "-false-start", kBooleanArgument, + "Enable False Start", + }, + { "-session-in", kOptionalArgument, + "A file containing a session to resume.", + }, + { "-session-out", kOptionalArgument, + "A file to write the negotiated session to.", + }, + { + "-key", kOptionalArgument, + "Private-key file to use (default is no client certificate)", + }, + { + "", kOptionalArgument, "", + }, +}; + +static ScopedEVP_PKEY LoadPrivateKey(const std::string &file) { + ScopedBIO bio(BIO_new(BIO_s_file())); + if (!bio || !BIO_read_filename(bio.get(), file.c_str())) { + return nullptr; + } + ScopedEVP_PKEY pkey(PEM_read_bio_PrivateKey(bio.get(), nullptr, nullptr, + nullptr)); + return pkey; +} + +static bool VersionFromString(uint16_t *out_version, + const std::string& version) { + if (version == "ssl3") { + *out_version = SSL3_VERSION; + return true; + } else if (version == "tls1" || version == "tls1.0") { + *out_version = TLS1_VERSION; + return true; + } else if (version == "tls1.1") { + *out_version = TLS1_1_VERSION; + return true; + } else if (version == "tls1.2") { + *out_version = TLS1_2_VERSION; + return true; + } + return false; +} + +static int NextProtoSelectCallback(SSL* ssl, uint8_t** out, uint8_t* outlen, + const uint8_t* in, unsigned inlen, void* arg) { + *out = reinterpret_cast(arg); + *outlen = strlen(reinterpret_cast(arg)); + return SSL_TLSEXT_ERR_OK; +} + +static FILE *g_keylog_file = nullptr; + +static void KeyLogCallback(const SSL *ssl, const char *line) { + fprintf(g_keylog_file, "%s\n", line); + fflush(g_keylog_file); +} + +bool Client(const std::vector &args) { + if (!InitSocketLibrary()) { + return false; + } + + std::map args_map; + + if (!ParseKeyValueArguments(&args_map, args, kArguments)) { + PrintUsage(kArguments); + return false; + } + + ScopedSSL_CTX ctx(SSL_CTX_new(SSLv23_client_method())); + + const char *keylog_file = getenv("SSLKEYLOGFILE"); + if (keylog_file) { + g_keylog_file = fopen(keylog_file, "a"); + if (g_keylog_file == nullptr) { + perror("fopen"); + return false; + } + SSL_CTX_set_keylog_callback(ctx.get(), KeyLogCallback); + } + + if (args_map.count("-cipher") != 0 && + !SSL_CTX_set_cipher_list(ctx.get(), args_map["-cipher"].c_str())) { + fprintf(stderr, "Failed setting cipher list\n"); + return false; + } + + if (args_map.count("-max-version") != 0) { + uint16_t version; + if (!VersionFromString(&version, args_map["-max-version"])) { + fprintf(stderr, "Unknown protocol version: '%s'\n", + args_map["-max-version"].c_str()); + return false; + } + SSL_CTX_set_max_version(ctx.get(), version); + } + + if (args_map.count("-min-version") != 0) { + uint16_t version; + if (!VersionFromString(&version, args_map["-min-version"])) { + fprintf(stderr, "Unknown protocol version: '%s'\n", + args_map["-min-version"].c_str()); + return false; + } + SSL_CTX_set_min_version(ctx.get(), version); + } + + if (args_map.count("-select-next-proto") != 0) { + const std::string &proto = args_map["-select-next-proto"]; + if (proto.size() > 255) { + fprintf(stderr, "Bad NPN protocol: '%s'\n", proto.c_str()); + return false; + } + // |SSL_CTX_set_next_proto_select_cb| is not const-correct. + SSL_CTX_set_next_proto_select_cb(ctx.get(), NextProtoSelectCallback, + const_cast(proto.c_str())); + } + + if (args_map.count("-alpn-protos") != 0) { + const std::string &alpn_protos = args_map["-alpn-protos"]; + std::vector wire; + size_t i = 0; + while (i <= alpn_protos.size()) { + size_t j = alpn_protos.find(',', i); + if (j == std::string::npos) { + j = alpn_protos.size(); + } + size_t len = j - i; + if (len > 255) { + fprintf(stderr, "Invalid ALPN protocols: '%s'\n", alpn_protos.c_str()); + return false; + } + wire.push_back(static_cast(len)); + wire.resize(wire.size() + len); + memcpy(wire.data() + wire.size() - len, alpn_protos.data() + i, len); + i = j + 1; + } + if (SSL_CTX_set_alpn_protos(ctx.get(), wire.data(), wire.size()) != 0) { + return false; + } + } + + if (args_map.count("-fallback-scsv") != 0) { + SSL_CTX_set_mode(ctx.get(), SSL_MODE_SEND_FALLBACK_SCSV); + } + + if (args_map.count("-ocsp-stapling") != 0) { + SSL_CTX_enable_ocsp_stapling(ctx.get()); + } + + if (args_map.count("-signed-certificate-timestamps") != 0) { + SSL_CTX_enable_signed_cert_timestamps(ctx.get()); + } + + if (args_map.count("-channel-id-key") != 0) { + ScopedEVP_PKEY pkey = LoadPrivateKey(args_map["-channel-id-key"]); + if (!pkey || !SSL_CTX_set1_tls_channel_id(ctx.get(), pkey.get())) { + return false; + } + } + + if (args_map.count("-false-start") != 0) { + SSL_CTX_set_mode(ctx.get(), SSL_MODE_ENABLE_FALSE_START); + } + + if (args_map.count("-key") != 0) { + const std::string &key = args_map["-key"]; + if (!SSL_CTX_use_PrivateKey_file(ctx.get(), key.c_str(), SSL_FILETYPE_PEM)) { + fprintf(stderr, "Failed to load private key: %s\n", key.c_str()); + return false; + } + if (!SSL_CTX_use_certificate_chain_file(ctx.get(), key.c_str())) { + fprintf(stderr, "Failed to load cert chain: %s\n", key.c_str()); + return false; + } + } + + int sock = -1; + if (!Connect(&sock, args_map["-connect"])) { + return false; + } + + ScopedBIO bio(BIO_new_socket(sock, BIO_CLOSE)); + ScopedSSL ssl(SSL_new(ctx.get())); + + if (args_map.count("-server-name") != 0) { + SSL_set_tlsext_host_name(ssl.get(), args_map["-server-name"].c_str()); + } + + if (args_map.count("-session-in") != 0) { + ScopedBIO in(BIO_new_file(args_map["-session-in"].c_str(), "rb")); + if (!in) { + fprintf(stderr, "Error reading session\n"); + ERR_print_errors_cb(PrintErrorCallback, stderr); + return false; + } + ScopedSSL_SESSION session(PEM_read_bio_SSL_SESSION(in.get(), nullptr, + nullptr, nullptr)); + if (!session) { + fprintf(stderr, "Error reading session\n"); + ERR_print_errors_cb(PrintErrorCallback, stderr); + return false; + } + SSL_set_session(ssl.get(), session.get()); + } + + SSL_set_bio(ssl.get(), bio.get(), bio.get()); + bio.release(); + + int ret = SSL_connect(ssl.get()); + if (ret != 1) { + int ssl_err = SSL_get_error(ssl.get(), ret); + fprintf(stderr, "Error while connecting: %d\n", ssl_err); + ERR_print_errors_cb(PrintErrorCallback, stderr); + return false; + } + + fprintf(stderr, "Connected.\n"); + PrintConnectionInfo(ssl.get()); + + if (args_map.count("-session-out") != 0) { + ScopedBIO out(BIO_new_file(args_map["-session-out"].c_str(), "wb")); + if (!out || + !PEM_write_bio_SSL_SESSION(out.get(), SSL_get0_session(ssl.get()))) { + fprintf(stderr, "Error while saving session:\n"); + ERR_print_errors_cb(PrintErrorCallback, stderr); + return false; + } + } + + bool ok = TransferData(ssl.get(), sock); + + return ok; +} diff --git a/external/boringssl/tool/const.cc b/external/boringssl/tool/const.cc new file mode 100644 index 0000000000..7b7001e507 --- /dev/null +++ b/external/boringssl/tool/const.cc @@ -0,0 +1,434 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include + +#include "internal.h" + + +const uint8_t kDERRSAPrivate2048[] = { + 0x30, 0x82, 0x04, 0xa3, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, + 0xd0, 0x02, 0xde, 0x5d, 0x19, 0x33, 0x48, 0x15, 0xc7, 0x86, 0xde, 0xa3, + 0xec, 0x63, 0x89, 0x14, 0x63, 0x99, 0x30, 0x1f, 0x5d, 0x25, 0xb2, 0xfa, + 0x27, 0x28, 0x4b, 0xb4, 0xf3, 0xba, 0xc6, 0xbc, 0x19, 0x38, 0x89, 0x56, + 0xf0, 0x42, 0xae, 0x9f, 0x84, 0x7b, 0x0d, 0xcf, 0xda, 0x1c, 0xd1, 0xd8, + 0x11, 0x26, 0x3f, 0x67, 0x76, 0x19, 0xfd, 0xfe, 0x6b, 0x12, 0xd4, 0x02, + 0x00, 0x42, 0x1b, 0x0f, 0xb6, 0x78, 0x5e, 0x1d, 0xb9, 0x3d, 0x32, 0x4f, + 0x7f, 0x41, 0xe4, 0xc9, 0x1b, 0x94, 0x40, 0x4e, 0xa2, 0x5c, 0x9c, 0x88, + 0x79, 0xf9, 0x9a, 0x64, 0x1b, 0x83, 0xdf, 0x1f, 0x9b, 0xb1, 0xa5, 0xe4, + 0xdf, 0x6d, 0x75, 0x3f, 0x98, 0xc7, 0x42, 0x53, 0xb4, 0x36, 0xba, 0x60, + 0xdd, 0xbd, 0x2d, 0xa9, 0x9f, 0x63, 0xd2, 0x74, 0xcc, 0xff, 0x13, 0x8a, + 0xa1, 0xd0, 0x91, 0x36, 0x1e, 0x22, 0x6e, 0x45, 0x46, 0xf3, 0xd1, 0xca, + 0xf6, 0x2c, 0x3f, 0x87, 0xf1, 0x15, 0xbf, 0xb0, 0x4d, 0xe3, 0xcc, 0xa7, + 0x18, 0xad, 0xa9, 0xb0, 0x5f, 0xbb, 0x2d, 0xc3, 0x06, 0x55, 0x69, 0x40, + 0xb9, 0x9a, 0x92, 0x14, 0x67, 0xde, 0x4c, 0x0d, 0x09, 0xab, 0x57, 0x41, + 0xe4, 0x30, 0xae, 0xd2, 0x22, 0x01, 0xbb, 0x36, 0xcb, 0x45, 0x0a, 0x82, + 0xc8, 0x56, 0x61, 0x39, 0x6a, 0x0a, 0xea, 0xab, 0x39, 0x28, 0x2c, 0x92, + 0x80, 0xe8, 0x00, 0xd1, 0xfa, 0xcc, 0x1d, 0xf8, 0xe5, 0xd7, 0x03, 0x34, + 0x04, 0x1b, 0x17, 0x35, 0xbc, 0xc6, 0xf9, 0x55, 0x0c, 0x05, 0xd8, 0xd3, + 0xc7, 0x4e, 0x0a, 0x92, 0xf1, 0x1d, 0x0d, 0x01, 0xf3, 0x0e, 0x3a, 0x9b, + 0x9b, 0x75, 0x8f, 0xe8, 0x0d, 0xbb, 0xf6, 0x81, 0x09, 0x48, 0x72, 0x05, + 0x9e, 0x0e, 0x48, 0x62, 0xd2, 0xba, 0x88, 0xa3, 0x18, 0xf5, 0x1b, 0xc9, + 0x9b, 0xff, 0x31, 0x3f, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, + 0x00, 0x76, 0xf1, 0x9c, 0xfb, 0x79, 0x64, 0x84, 0x8c, 0xc7, 0xaa, 0x4c, + 0x77, 0x49, 0xbd, 0xe4, 0xed, 0xbe, 0xc2, 0x22, 0xed, 0x5c, 0x53, 0x29, + 0x53, 0xb7, 0xbe, 0x68, 0x04, 0x11, 0xf6, 0xb4, 0x9b, 0x6c, 0x84, 0x92, + 0xac, 0x1e, 0xf8, 0xd2, 0x67, 0xae, 0xd6, 0xba, 0xa0, 0x27, 0x25, 0xa1, + 0xac, 0xbe, 0xa9, 0xb3, 0x49, 0xd3, 0x13, 0xab, 0xd4, 0xa6, 0x9f, 0x7e, + 0x91, 0xa2, 0x5a, 0x2a, 0xa5, 0x42, 0x7e, 0xf3, 0xba, 0x65, 0x69, 0x23, + 0xf2, 0xa7, 0x5f, 0x23, 0x97, 0x07, 0xe9, 0x2f, 0x18, 0x87, 0xe9, 0x13, + 0x2d, 0x4b, 0x2a, 0x3a, 0x69, 0x91, 0xfe, 0x47, 0x41, 0x08, 0xc3, 0x7d, + 0x8c, 0x31, 0x62, 0xa2, 0xcf, 0xf9, 0xe9, 0xbe, 0xf8, 0xa4, 0x2d, 0x43, + 0x48, 0x0e, 0xa3, 0x95, 0x8f, 0xcf, 0xef, 0xc1, 0xb1, 0x3e, 0x63, 0x81, + 0x66, 0x1d, 0x7f, 0x68, 0xf9, 0x9c, 0x23, 0xae, 0x0f, 0x70, 0xaf, 0xed, + 0xa9, 0x4e, 0x95, 0xd1, 0x39, 0x51, 0x15, 0x55, 0xfc, 0x4e, 0x9e, 0xb3, + 0xb0, 0xc0, 0x07, 0x1d, 0xd9, 0xd2, 0x48, 0x4c, 0x03, 0x31, 0x2d, 0x21, + 0xda, 0x4d, 0xed, 0x29, 0xf8, 0xbf, 0xaf, 0x1f, 0x8d, 0x6f, 0xdc, 0xae, + 0xf0, 0x4a, 0x01, 0xa1, 0xb8, 0x06, 0x61, 0x58, 0x18, 0xff, 0x40, 0xa1, + 0x1c, 0x82, 0xf8, 0x23, 0xaf, 0xce, 0x62, 0x3e, 0x2d, 0x30, 0x09, 0xff, + 0xba, 0xa6, 0x34, 0x7e, 0x6e, 0x9e, 0x59, 0x66, 0x6b, 0x39, 0x08, 0x1f, + 0x3e, 0x76, 0xbc, 0x29, 0xef, 0x10, 0x62, 0x7f, 0xf4, 0xdf, 0xe6, 0x5f, + 0xa4, 0x1f, 0x60, 0xfe, 0x37, 0xdb, 0xd7, 0x8f, 0xff, 0xf9, 0xf0, 0xaf, + 0x66, 0xa2, 0x7d, 0x36, 0x19, 0x7f, 0xe2, 0xc3, 0x84, 0x66, 0x18, 0x2b, + 0x18, 0x16, 0x4f, 0xb3, 0xce, 0x69, 0x6b, 0xb6, 0xd6, 0x98, 0x25, 0xcb, + 0x90, 0x4f, 0x60, 0x68, 0x91, 0x02, 0x81, 0x81, 0x00, 0xf6, 0xd6, 0xae, + 0x84, 0xc0, 0x9f, 0x2f, 0xef, 0xa6, 0x7e, 0x91, 0x7a, 0x4d, 0x1c, 0xe0, + 0x3e, 0x61, 0xf8, 0xcc, 0x4d, 0x0d, 0x09, 0xa3, 0xeb, 0x9a, 0xbe, 0x89, + 0x59, 0x50, 0xf7, 0xd6, 0x8f, 0x66, 0x67, 0x97, 0x7e, 0xb4, 0x2d, 0x73, + 0x08, 0xf8, 0x12, 0x22, 0x7f, 0x5c, 0x76, 0x2b, 0x06, 0x7c, 0xaa, 0x54, + 0x83, 0xce, 0x2d, 0xab, 0xc3, 0xb7, 0xb1, 0x74, 0x10, 0xc9, 0x67, 0xc7, + 0x8c, 0xd1, 0x13, 0x17, 0x1e, 0xb2, 0x4f, 0xc7, 0xda, 0xcf, 0x45, 0xc3, + 0x1c, 0x6d, 0x98, 0x08, 0xc9, 0xf4, 0xd4, 0x6d, 0x16, 0xb4, 0x6b, 0x02, + 0x24, 0x25, 0x0a, 0x2d, 0xc0, 0xa3, 0x2e, 0x4b, 0xae, 0xf7, 0x4e, 0xb5, + 0x68, 0xb2, 0xe7, 0x88, 0xdc, 0x2e, 0xbc, 0x91, 0x42, 0x7f, 0x36, 0xbc, + 0x71, 0x4e, 0xc4, 0x5f, 0xfa, 0xbe, 0x46, 0x89, 0x61, 0xe3, 0x17, 0x3b, + 0x51, 0x29, 0xa8, 0x2c, 0x07, 0x02, 0x81, 0x81, 0x00, 0xd7, 0xbb, 0x45, + 0x76, 0x81, 0x15, 0x3e, 0x1b, 0x95, 0xd8, 0x7c, 0x8c, 0x08, 0x02, 0xe1, + 0x04, 0xaf, 0xa1, 0x59, 0x4c, 0xc7, 0x71, 0xf1, 0xd0, 0xef, 0xa7, 0xb6, + 0xa0, 0x70, 0xd0, 0xf7, 0x86, 0x8d, 0x4a, 0xf6, 0x9f, 0xac, 0xf3, 0x78, + 0xc9, 0xb5, 0xdf, 0x86, 0x71, 0xa9, 0x69, 0x63, 0xe4, 0x8a, 0x22, 0x57, + 0xa2, 0xa8, 0xd5, 0xf1, 0xb0, 0xe5, 0x43, 0x20, 0xd2, 0x18, 0x89, 0x3b, + 0xed, 0x90, 0xf5, 0xde, 0x82, 0x90, 0x7a, 0xd4, 0x0a, 0x3d, 0x89, 0x82, + 0x3a, 0x5f, 0x66, 0x73, 0x0e, 0x98, 0x1c, 0x84, 0x3a, 0x5a, 0x8f, 0xa1, + 0xb8, 0x60, 0xaf, 0x40, 0x8b, 0x6f, 0xda, 0x85, 0xad, 0x55, 0x62, 0x04, + 0xe1, 0x07, 0xb8, 0x49, 0xcb, 0xd4, 0x17, 0xdc, 0xb6, 0xe3, 0x39, 0xf5, + 0x22, 0xa0, 0xec, 0x58, 0xbd, 0x06, 0x4a, 0x87, 0xa1, 0x90, 0x9c, 0x27, + 0xd7, 0xa5, 0x9d, 0xf3, 0x09, 0x02, 0x81, 0x80, 0x28, 0x4c, 0xec, 0xb9, + 0x67, 0xe9, 0x95, 0x9d, 0xff, 0x04, 0xf3, 0x23, 0x90, 0xab, 0x82, 0x41, + 0x2d, 0x25, 0xbd, 0xd5, 0x66, 0xa7, 0x88, 0x47, 0xd3, 0x40, 0x00, 0x94, + 0xc0, 0x8f, 0x76, 0x4c, 0x7b, 0x5f, 0xb6, 0x70, 0x4d, 0x62, 0x8e, 0x41, + 0x8c, 0x9f, 0x09, 0x5a, 0xd9, 0xf1, 0xc1, 0x1c, 0x92, 0x06, 0x0d, 0x3e, + 0x67, 0xcf, 0x35, 0x18, 0x03, 0x49, 0xc9, 0xb5, 0x63, 0xec, 0xb9, 0xbb, + 0xd7, 0xf6, 0xd1, 0xf3, 0x85, 0x11, 0x59, 0x83, 0xf4, 0x0b, 0x63, 0xcb, + 0xa4, 0x69, 0x0a, 0x26, 0x4e, 0xfe, 0xcf, 0xc0, 0xc1, 0x3c, 0x27, 0x61, + 0x57, 0x5a, 0xce, 0x15, 0x81, 0x8e, 0xf1, 0x74, 0x63, 0x94, 0x4a, 0x32, + 0x09, 0xe3, 0x9b, 0x88, 0xb7, 0x68, 0xba, 0x1e, 0xad, 0x3e, 0x76, 0x8d, + 0xd9, 0x5a, 0x5e, 0x81, 0x45, 0xc7, 0xa6, 0x6e, 0x80, 0xf1, 0x2e, 0x12, + 0x16, 0x47, 0x0a, 0xc9, 0x02, 0x81, 0x81, 0x00, 0xa0, 0xc7, 0x6e, 0x46, + 0x9a, 0x7f, 0x85, 0x71, 0x33, 0xa5, 0x4b, 0x75, 0x65, 0x87, 0x17, 0xc2, + 0xd1, 0x4e, 0x33, 0xea, 0x97, 0xfe, 0x20, 0xd5, 0xb1, 0xb6, 0xd1, 0xd2, + 0x13, 0x22, 0x7a, 0x47, 0xaa, 0x48, 0x03, 0x34, 0x0f, 0xc6, 0xc8, 0xef, + 0xb3, 0xff, 0x6a, 0x08, 0x8d, 0xd5, 0x00, 0xe0, 0xd3, 0xde, 0x32, 0x68, + 0x04, 0xe2, 0xa6, 0x25, 0x4b, 0x48, 0x53, 0x4e, 0xa1, 0x80, 0xad, 0xcc, + 0x29, 0x2c, 0x44, 0xf0, 0x13, 0xd3, 0xa6, 0xf2, 0x16, 0xd8, 0xc3, 0xd8, + 0xd3, 0x3e, 0xdc, 0x63, 0x35, 0x14, 0x93, 0xab, 0x95, 0xd0, 0xd4, 0x1b, + 0x40, 0xdb, 0x7c, 0x04, 0x2f, 0x91, 0xb1, 0xec, 0xf3, 0xe4, 0x80, 0x74, + 0x61, 0xb7, 0x84, 0x30, 0x47, 0xda, 0x9c, 0xe1, 0x24, 0xca, 0x0e, 0x1b, + 0x07, 0xc9, 0xfd, 0x7c, 0xab, 0x12, 0xa2, 0xb0, 0xd3, 0xc0, 0xbd, 0xa4, + 0xe7, 0x46, 0xa7, 0x59, 0x02, 0x81, 0x80, 0x30, 0x5a, 0xa3, 0x8e, 0x0f, + 0xeb, 0xad, 0x9f, 0xf6, 0xa4, 0x82, 0xd8, 0x78, 0x83, 0xd2, 0xe4, 0x14, + 0x91, 0x20, 0x6f, 0x1f, 0x2b, 0x08, 0x21, 0x92, 0x5e, 0x30, 0xfe, 0x13, + 0xf2, 0x02, 0xd6, 0xe8, 0x96, 0x40, 0x98, 0x85, 0xb2, 0x63, 0x2b, 0x12, + 0xcf, 0x37, 0x4a, 0x27, 0xb1, 0x5f, 0x6f, 0x76, 0xa0, 0x29, 0xae, 0x2f, + 0x63, 0x72, 0xd9, 0x39, 0xca, 0x09, 0x29, 0x47, 0x98, 0x9f, 0x85, 0xae, + 0xb7, 0xe3, 0x0c, 0xcd, 0xbe, 0x4e, 0x45, 0xd3, 0x69, 0x1a, 0xb7, 0x7f, + 0xce, 0x2d, 0xfe, 0x9b, 0xe7, 0x4c, 0x7c, 0x2c, 0x8c, 0x26, 0x92, 0xdc, + 0x73, 0x71, 0x5f, 0x09, 0x4b, 0x49, 0xbf, 0x86, 0x94, 0xef, 0x3f, 0xf5, + 0x89, 0x8f, 0x12, 0x63, 0xff, 0xf2, 0x61, 0x6a, 0x66, 0xb2, 0xcc, 0x01, + 0x75, 0xef, 0x54, 0xa4, 0xa7, 0x03, 0x49, 0xfd, 0x27, 0xf4, 0x85, 0x00, + 0x77, 0xe6, 0xd3, +}; + +const size_t kDERRSAPrivate2048Len = sizeof(kDERRSAPrivate2048); + +const uint8_t kDERRSAPrivate4096[] = { + 0x30, 0x82, 0x09, 0x28, 0x02, 0x01, 0x00, 0x02, 0x82, 0x02, 0x01, 0x00, + 0xc3, 0x82, 0x01, 0xda, 0x03, 0xe1, 0x0d, 0x78, 0xf4, 0x86, 0xf1, 0x28, + 0xf0, 0x4c, 0x34, 0xa6, 0x73, 0x0c, 0xfb, 0x22, 0xfa, 0x35, 0xc9, 0x3a, + 0x4c, 0xf1, 0x15, 0xfe, 0x96, 0x4a, 0x64, 0x75, 0xfe, 0x62, 0x5c, 0x77, + 0x76, 0x12, 0x9a, 0x68, 0x63, 0x09, 0x4d, 0x6f, 0x4a, 0xec, 0xc7, 0xac, + 0x17, 0x60, 0x5e, 0xfa, 0xd8, 0xe0, 0xca, 0x3d, 0xfd, 0x0b, 0x5a, 0x88, + 0x4c, 0xe6, 0xbd, 0x99, 0x34, 0x9e, 0x06, 0xc5, 0xf8, 0x33, 0xad, 0x5d, + 0x8d, 0x73, 0x5d, 0x1c, 0xc2, 0xb3, 0xcd, 0x47, 0x2f, 0x41, 0x04, 0xe8, + 0x71, 0x6d, 0xd9, 0x19, 0xf4, 0x56, 0xb8, 0xcf, 0x0f, 0x92, 0x13, 0xb4, + 0x1c, 0x6a, 0x51, 0x4e, 0xdd, 0xd0, 0xc0, 0x20, 0x3f, 0xd9, 0x32, 0x92, + 0xe2, 0xbd, 0x66, 0x33, 0x4b, 0x44, 0xbf, 0xd8, 0x28, 0x3d, 0x51, 0x00, + 0xe3, 0xf8, 0x3b, 0x6c, 0x55, 0x22, 0x71, 0xee, 0xa7, 0x3c, 0xe4, 0x36, + 0xa2, 0xcf, 0x41, 0xeb, 0x64, 0x79, 0xbb, 0x75, 0xe8, 0xc5, 0x29, 0xe1, + 0xa5, 0xd2, 0xf6, 0x84, 0x2c, 0x0e, 0x0c, 0x0f, 0xc2, 0x42, 0xfd, 0xa9, + 0xdb, 0x8f, 0x44, 0xa0, 0xfc, 0xf3, 0x26, 0xd8, 0x6a, 0xc2, 0x14, 0x2d, + 0x3c, 0x09, 0x68, 0x98, 0x67, 0x0e, 0x01, 0xd4, 0x80, 0x02, 0x5c, 0xc0, + 0xb9, 0xd3, 0x12, 0x2e, 0xaa, 0x3c, 0xab, 0x56, 0x8c, 0x96, 0xb3, 0x25, + 0xeb, 0xa7, 0x86, 0xd8, 0xbe, 0x70, 0x01, 0xe9, 0xa7, 0x7b, 0x27, 0x01, + 0xbe, 0x4c, 0x23, 0xf4, 0x19, 0x17, 0x6e, 0x31, 0x69, 0xab, 0x1a, 0x6a, + 0x1f, 0x57, 0xde, 0x9a, 0x8e, 0x1d, 0xfd, 0xd9, 0x5d, 0xce, 0xa0, 0x47, + 0x19, 0x8d, 0x27, 0x33, 0x77, 0xe2, 0xa4, 0x1d, 0x72, 0x72, 0xe6, 0xec, + 0xf3, 0xad, 0x85, 0x50, 0xc0, 0x94, 0xab, 0x78, 0x03, 0x67, 0x1e, 0x48, + 0x45, 0x50, 0x41, 0x7d, 0xb5, 0x62, 0x28, 0x80, 0x41, 0x89, 0xac, 0x99, + 0xe2, 0xd7, 0xe1, 0xc2, 0x54, 0xfc, 0xff, 0xa7, 0xc0, 0x71, 0xc6, 0xd7, + 0xae, 0x05, 0xf2, 0xbc, 0x2a, 0xe8, 0x43, 0x88, 0x4a, 0x0c, 0xb2, 0x61, + 0x2e, 0x9b, 0xac, 0x48, 0x90, 0xaa, 0x7b, 0x24, 0x9b, 0xc2, 0xc5, 0x48, + 0x95, 0x8d, 0x4f, 0x92, 0x6a, 0xb7, 0xcc, 0xb5, 0x9f, 0x06, 0xe4, 0x05, + 0xac, 0x05, 0x81, 0x66, 0xb0, 0x24, 0x04, 0x12, 0xac, 0xac, 0x9a, 0x1e, + 0xea, 0xce, 0x82, 0xfb, 0x27, 0x2e, 0xa1, 0x5e, 0xb8, 0x86, 0x74, 0x1a, + 0x3a, 0xdd, 0x8c, 0x98, 0x3c, 0x23, 0x2b, 0xea, 0x8a, 0xd0, 0x92, 0x43, + 0xbb, 0xec, 0xb3, 0x27, 0x52, 0x2c, 0x7f, 0x07, 0x33, 0xe5, 0x21, 0xa3, + 0xda, 0x4e, 0x65, 0xd2, 0x96, 0xb5, 0x88, 0xcb, 0x9f, 0x0c, 0x21, 0x41, + 0x80, 0x02, 0xb2, 0x9e, 0x78, 0x60, 0x40, 0x18, 0x21, 0x52, 0x4f, 0x09, + 0x5f, 0x75, 0x8b, 0xf3, 0x71, 0x70, 0xab, 0x94, 0x3b, 0xd1, 0xe8, 0x65, + 0x55, 0xf2, 0x76, 0xe3, 0x7c, 0x1d, 0x3a, 0x7c, 0x44, 0xbf, 0xb4, 0x10, + 0x2e, 0x16, 0x7f, 0xdc, 0xd2, 0x37, 0xf3, 0x48, 0x68, 0x80, 0xa9, 0x9d, + 0x56, 0xff, 0x63, 0xed, 0x29, 0x79, 0x39, 0xfa, 0x92, 0x65, 0x22, 0xee, + 0x5c, 0x2a, 0xa9, 0xef, 0x30, 0x82, 0x10, 0xae, 0x46, 0xe2, 0x52, 0xa5, + 0x2e, 0x23, 0xe6, 0x65, 0xb5, 0x54, 0xd8, 0xa1, 0xe8, 0x9c, 0xf1, 0xe3, + 0xf5, 0xc8, 0x4b, 0x54, 0xac, 0x02, 0x4d, 0xdf, 0x01, 0xc2, 0xc7, 0x82, + 0x30, 0x0d, 0x86, 0x17, 0x64, 0x99, 0x7b, 0xfa, 0x46, 0x23, 0x19, 0x6b, + 0x7c, 0x01, 0x61, 0x22, 0xa6, 0x28, 0x17, 0x48, 0xa4, 0x6a, 0x32, 0x00, + 0x16, 0x23, 0x40, 0x0b, 0x51, 0xd7, 0xc7, 0x91, 0x60, 0xd7, 0x32, 0x91, + 0xf5, 0xf7, 0x3c, 0x24, 0xc0, 0x9f, 0x4a, 0xf3, 0x02, 0x03, 0x01, 0x00, + 0x01, 0x02, 0x82, 0x02, 0x00, 0x6b, 0x3d, 0x28, 0x9e, 0xd9, 0x79, 0xdc, + 0xd5, 0xf7, 0xea, 0xfc, 0xe5, 0x23, 0xc9, 0xe9, 0x27, 0x53, 0xfc, 0x4e, + 0xd4, 0xc4, 0xc2, 0x33, 0xfa, 0x92, 0xb1, 0xbb, 0x0a, 0xc6, 0x8d, 0x4f, + 0xc5, 0x99, 0x1f, 0x82, 0xf0, 0xd4, 0x07, 0x28, 0x43, 0x11, 0xef, 0xcc, + 0x55, 0xbb, 0x97, 0x5d, 0x7e, 0xfb, 0xe3, 0x94, 0xb5, 0xab, 0xb8, 0xc1, + 0xb6, 0x76, 0xd2, 0x7f, 0x7a, 0x3c, 0x14, 0x64, 0xf3, 0x60, 0x75, 0x3d, + 0xe9, 0xe1, 0x57, 0x17, 0x45, 0x35, 0x8d, 0x8e, 0x09, 0x74, 0x93, 0x03, + 0x8a, 0x84, 0x54, 0xf9, 0xc8, 0x36, 0x4f, 0xb6, 0xc2, 0x11, 0xd0, 0x6f, + 0xd6, 0xc4, 0x07, 0xb0, 0x5f, 0x1f, 0x27, 0x02, 0x2a, 0x6c, 0x69, 0x50, + 0xb9, 0x5f, 0xcc, 0x57, 0x7d, 0x52, 0x79, 0xe9, 0x51, 0x41, 0x7c, 0x18, + 0x6f, 0x0c, 0xc3, 0x75, 0x67, 0x33, 0xa4, 0xb9, 0x93, 0x96, 0xaf, 0x2a, + 0x27, 0x69, 0xfc, 0x70, 0x81, 0xb7, 0x94, 0x4f, 0xe8, 0x3a, 0x58, 0xbb, + 0x86, 0xd5, 0x83, 0x30, 0x91, 0xe1, 0x4f, 0x72, 0x80, 0xd5, 0x59, 0x6f, + 0x2c, 0x45, 0xb6, 0x51, 0x45, 0x96, 0x75, 0x63, 0x83, 0x9a, 0xbc, 0x15, + 0x16, 0xa8, 0x98, 0x84, 0x50, 0xbb, 0x99, 0xbd, 0x91, 0xbb, 0x15, 0x67, + 0xd3, 0x93, 0xd3, 0xb7, 0xe4, 0xcf, 0x09, 0x03, 0xf4, 0x2c, 0xd4, 0xd2, + 0x76, 0xca, 0xee, 0xee, 0x9d, 0x62, 0x41, 0xa6, 0x29, 0xc5, 0x6b, 0xd2, + 0xe0, 0xc3, 0x49, 0x3e, 0x00, 0x2a, 0xcd, 0xc0, 0xfa, 0xe7, 0xb8, 0x7e, + 0x6d, 0x04, 0x35, 0x22, 0x6c, 0x0b, 0x7d, 0x3b, 0x51, 0x33, 0x9b, 0x27, + 0xde, 0xcf, 0x21, 0xc3, 0xb0, 0xbc, 0x47, 0x3c, 0xb5, 0x72, 0x91, 0x12, + 0xcc, 0x44, 0x36, 0xda, 0x8c, 0x26, 0xad, 0x8b, 0x6e, 0xdb, 0xf3, 0xb0, + 0x8a, 0x47, 0xf3, 0x8c, 0x1c, 0xc0, 0x48, 0x61, 0x63, 0x09, 0x48, 0x08, + 0x4f, 0x3b, 0xb4, 0x90, 0xf7, 0x4b, 0xd7, 0x58, 0x88, 0xfe, 0x3d, 0xe4, + 0x9d, 0xf2, 0xec, 0xf4, 0x6d, 0x70, 0x2c, 0x0f, 0x55, 0x61, 0xdb, 0x62, + 0x3d, 0x75, 0x19, 0x4b, 0x24, 0x02, 0xe3, 0xbd, 0x01, 0xd8, 0xe4, 0x05, + 0x85, 0xda, 0x19, 0xc5, 0x91, 0xda, 0x09, 0xf6, 0xd0, 0xff, 0x7d, 0xae, + 0x68, 0x86, 0x17, 0xac, 0xf7, 0xb9, 0xde, 0xe7, 0x3f, 0x1e, 0xb5, 0x7e, + 0xcd, 0x64, 0xf2, 0x48, 0x61, 0x86, 0x4b, 0x21, 0x5b, 0xe2, 0x3b, 0x69, + 0xfc, 0xeb, 0x17, 0x25, 0x97, 0x6d, 0x6f, 0xd9, 0x7e, 0xce, 0x31, 0xb7, + 0xad, 0x2c, 0xb0, 0x31, 0xaf, 0x89, 0x2d, 0x8d, 0x30, 0x2a, 0x45, 0x69, + 0x0c, 0x8e, 0x96, 0xfa, 0x00, 0xcb, 0x47, 0x32, 0x3c, 0x40, 0xe5, 0x75, + 0xe3, 0xa9, 0x4f, 0xd4, 0xa8, 0x33, 0x76, 0x59, 0xea, 0xbe, 0x09, 0xae, + 0x2c, 0x27, 0x9e, 0x1f, 0xc2, 0xdd, 0x90, 0x38, 0xe6, 0xb8, 0x49, 0x1f, + 0x17, 0x5a, 0x01, 0xa2, 0x73, 0xaa, 0x92, 0xb6, 0xed, 0x26, 0xd7, 0x0d, + 0xa0, 0x39, 0x42, 0xdb, 0xc1, 0xf6, 0xe3, 0x0b, 0x11, 0x4c, 0x3e, 0x40, + 0xba, 0x2a, 0x42, 0xa9, 0x5b, 0x74, 0x0a, 0xcd, 0x0c, 0xae, 0x13, 0x27, + 0x6b, 0x37, 0xfa, 0xdd, 0x08, 0x89, 0xb4, 0xc2, 0x11, 0xda, 0xb2, 0x8d, + 0x44, 0x59, 0x1f, 0x19, 0x1a, 0x7d, 0x0b, 0x70, 0x62, 0x00, 0x8a, 0x4a, + 0x2e, 0xda, 0x44, 0xc6, 0xc6, 0xf9, 0xe6, 0x14, 0xdc, 0xe1, 0x9e, 0xb6, + 0x8e, 0xcf, 0x0d, 0xa2, 0xf4, 0x64, 0x8c, 0x71, 0x4e, 0x0a, 0xf6, 0xa8, + 0xca, 0x2d, 0xe0, 0xd2, 0x5f, 0x78, 0xee, 0x3d, 0x77, 0x13, 0xba, 0x61, + 0xac, 0xe3, 0x0f, 0xb0, 0x5f, 0xd3, 0x28, 0x12, 0x5d, 0xa6, 0xe9, 0x38, + 0xfa, 0x6e, 0xe7, 0xdf, 0xee, 0x65, 0x98, 0x97, 0x48, 0xb7, 0xa9, 0x73, + 0x21, 0x02, 0x82, 0x01, 0x01, 0x00, 0xe7, 0x1b, 0x4c, 0x5c, 0xcc, 0xb7, + 0xae, 0x4b, 0xe8, 0x7d, 0x19, 0xc0, 0x53, 0xc7, 0x17, 0x86, 0xac, 0xef, + 0x79, 0x94, 0x61, 0xc3, 0x17, 0x17, 0xb6, 0x5f, 0x08, 0x7c, 0xc7, 0x96, + 0xf3, 0x69, 0xc4, 0x2b, 0x90, 0xae, 0x35, 0x57, 0x2c, 0x73, 0x10, 0xaa, + 0x59, 0x69, 0x42, 0x21, 0xa3, 0x29, 0x94, 0x35, 0x3c, 0x12, 0x9e, 0xa0, + 0x08, 0x28, 0xad, 0x34, 0x3d, 0x07, 0x23, 0x6d, 0xb8, 0xfa, 0x48, 0x4e, + 0x1a, 0x4b, 0xeb, 0x4c, 0x91, 0xf2, 0xa0, 0x83, 0x75, 0x8c, 0x82, 0x4e, + 0xea, 0x75, 0xfb, 0x39, 0x9e, 0x81, 0xe9, 0xac, 0x8f, 0x1f, 0x7c, 0x59, + 0x4f, 0x8e, 0x99, 0x81, 0x2e, 0xea, 0xb7, 0x77, 0x16, 0xf4, 0xea, 0x9e, + 0x4a, 0x44, 0xa0, 0x5b, 0xc6, 0x22, 0x82, 0xa3, 0x54, 0x1f, 0x9e, 0x07, + 0xfb, 0x8e, 0x92, 0xd0, 0x31, 0x5e, 0x68, 0x26, 0xdf, 0x18, 0xc3, 0x85, + 0xba, 0x43, 0xcb, 0xae, 0x3d, 0x31, 0x03, 0xc6, 0x20, 0xfd, 0x11, 0xb1, + 0x62, 0xdc, 0xa0, 0xb4, 0xef, 0x21, 0x8c, 0x1d, 0x95, 0xfa, 0xf1, 0x79, + 0xba, 0x97, 0x43, 0xf7, 0x45, 0x39, 0x05, 0x54, 0xbf, 0x49, 0xab, 0x99, + 0x00, 0x6a, 0x06, 0x84, 0x9c, 0xb6, 0xf0, 0xdc, 0x46, 0x8e, 0x1c, 0x66, + 0xec, 0x4a, 0xae, 0xc3, 0xba, 0xfb, 0x1b, 0xe7, 0xef, 0x0b, 0xb6, 0xe5, + 0xd7, 0xf1, 0x6c, 0x82, 0xd8, 0xdc, 0xa3, 0xc2, 0x02, 0x17, 0x53, 0xe0, + 0xa0, 0x84, 0x4e, 0xad, 0x4a, 0x9b, 0x07, 0x87, 0x1a, 0x59, 0x21, 0xba, + 0xa0, 0x9b, 0x8f, 0x27, 0xa0, 0x93, 0xf7, 0x51, 0xad, 0x62, 0xc0, 0x6f, + 0x00, 0x37, 0x16, 0x70, 0xa6, 0x30, 0xb7, 0xa9, 0x7b, 0x7f, 0x53, 0x9d, + 0x54, 0x93, 0xba, 0x1f, 0xe1, 0x35, 0x4a, 0x88, 0x45, 0x34, 0x95, 0x24, + 0x64, 0x9a, 0xa5, 0x61, 0x7c, 0xed, 0x83, 0x38, 0xfb, 0x45, 0x02, 0x82, + 0x01, 0x01, 0x00, 0xd8, 0x91, 0x15, 0x00, 0x3f, 0x7f, 0x27, 0x0a, 0x3b, + 0xc4, 0x67, 0x36, 0x1d, 0x13, 0xd1, 0x50, 0x39, 0x1e, 0x26, 0xad, 0x25, + 0x65, 0x6a, 0x1d, 0xf7, 0x5d, 0x6b, 0x4b, 0x26, 0xb0, 0x32, 0x5a, 0x30, + 0x78, 0xb6, 0x11, 0xab, 0x5b, 0x4b, 0x6e, 0xcd, 0xe5, 0x93, 0xb2, 0xa9, + 0xca, 0x4b, 0xe8, 0x61, 0x45, 0xd1, 0xf7, 0x8b, 0x11, 0x77, 0x3a, 0x59, + 0xd6, 0xb3, 0x2a, 0xf3, 0x8a, 0x6a, 0x2e, 0x53, 0xe8, 0x21, 0xda, 0x03, + 0xd5, 0x2d, 0xcc, 0xd2, 0xba, 0xec, 0x11, 0x69, 0xe3, 0xab, 0xd5, 0x9e, + 0xfc, 0x9c, 0xff, 0x90, 0x79, 0x05, 0x3a, 0xb0, 0x5e, 0x43, 0x05, 0xd7, + 0x9b, 0xec, 0xda, 0x22, 0x2c, 0xc4, 0x18, 0x28, 0x26, 0xbb, 0xdb, 0x45, + 0xa0, 0x7d, 0x32, 0x17, 0xc3, 0x14, 0xd8, 0x72, 0x7a, 0x59, 0x33, 0x5e, + 0x02, 0xb2, 0x3c, 0xd8, 0x46, 0x82, 0x5e, 0x9c, 0x06, 0x20, 0x5f, 0x63, + 0xd8, 0x02, 0xda, 0x59, 0x0b, 0x32, 0x89, 0xc4, 0xbd, 0x63, 0x74, 0xbb, + 0x76, 0x34, 0xb9, 0x18, 0x29, 0x6d, 0x79, 0xe6, 0x02, 0x57, 0xab, 0x16, + 0x5a, 0x59, 0xea, 0x22, 0xdc, 0x37, 0x9c, 0x19, 0x7a, 0x2a, 0x40, 0xeb, + 0xa7, 0x2d, 0xef, 0x3d, 0xc5, 0x29, 0x71, 0xa6, 0x4a, 0x2d, 0x62, 0xc4, + 0x85, 0xed, 0x65, 0x88, 0x7a, 0x83, 0x3c, 0x06, 0x9a, 0xac, 0x24, 0x50, + 0xed, 0x27, 0xfc, 0xff, 0x98, 0xdb, 0x8b, 0xf1, 0xf1, 0x6f, 0xa0, 0x89, + 0xc1, 0xfe, 0x82, 0xbb, 0xab, 0xe1, 0xc2, 0x2a, 0xea, 0xd3, 0x73, 0xbf, + 0xe9, 0xb3, 0x4d, 0xd7, 0xf4, 0x3b, 0x66, 0x9f, 0x3b, 0xd4, 0x9b, 0xf9, + 0xad, 0xa0, 0x45, 0xed, 0x58, 0x41, 0xc6, 0xf2, 0x32, 0x0c, 0xbd, 0xc6, + 0x4b, 0x2b, 0xfa, 0x1c, 0x57, 0x49, 0x5d, 0x82, 0x37, 0xba, 0x02, 0x8e, + 0x43, 0x72, 0x1f, 0xdc, 0x55, 0x74, 0xd7, 0x02, 0x82, 0x01, 0x01, 0x00, + 0xc0, 0xcc, 0xc3, 0x4d, 0xff, 0xf3, 0x94, 0xd2, 0xfa, 0xe7, 0xb2, 0xde, + 0x02, 0x86, 0x6b, 0x98, 0x0d, 0x19, 0xd3, 0xa1, 0xf8, 0x55, 0x1b, 0x24, + 0xcb, 0x1e, 0x49, 0x24, 0x60, 0x16, 0x0c, 0x87, 0xc6, 0x02, 0x5a, 0x37, + 0x1b, 0x84, 0xd8, 0x2e, 0x3e, 0x4e, 0xff, 0x3c, 0x92, 0xd1, 0x21, 0x1f, + 0x84, 0xe7, 0x4c, 0x70, 0x74, 0x29, 0x29, 0xe5, 0x55, 0x69, 0xe9, 0x27, + 0xd5, 0x64, 0xaa, 0x17, 0x12, 0xcf, 0x25, 0x9d, 0x04, 0x75, 0xe2, 0xa4, + 0x39, 0x48, 0xb2, 0x7e, 0x40, 0x0f, 0xba, 0x06, 0x27, 0x4a, 0x10, 0x74, + 0x6d, 0x0f, 0x6a, 0x6f, 0x67, 0xfb, 0xd2, 0x25, 0x32, 0xe6, 0xd4, 0xcf, + 0x37, 0xb3, 0x80, 0x51, 0x5e, 0x92, 0x23, 0x7f, 0x51, 0x10, 0x7f, 0x21, + 0x37, 0x3f, 0x2e, 0xe5, 0x19, 0x9f, 0xab, 0x3b, 0x6c, 0x3b, 0x87, 0x94, + 0x2c, 0xeb, 0x90, 0xdf, 0x45, 0xee, 0x80, 0x50, 0x22, 0xd1, 0xff, 0x76, + 0xae, 0xa1, 0x51, 0xd0, 0x0e, 0x3c, 0xa0, 0x2f, 0x53, 0x5a, 0xde, 0xcc, + 0x6b, 0xea, 0x1a, 0xbf, 0x39, 0x48, 0xc6, 0x63, 0x7f, 0x6e, 0x00, 0x2f, + 0xeb, 0xc4, 0xa1, 0xb8, 0xc2, 0x11, 0x68, 0x89, 0x0b, 0x5b, 0x02, 0xaa, + 0x94, 0x12, 0x10, 0x42, 0x6a, 0x6b, 0x6a, 0xe1, 0x7b, 0x1f, 0x0b, 0x14, + 0x86, 0x59, 0x5d, 0xd1, 0xb6, 0x09, 0xd5, 0xb7, 0x31, 0x41, 0x8f, 0xcd, + 0xb2, 0x48, 0x1e, 0x1a, 0x7b, 0xfd, 0x3f, 0xac, 0x61, 0x3e, 0xac, 0xa8, + 0xdd, 0x04, 0xd6, 0xf4, 0x58, 0xf1, 0x2b, 0x1f, 0xdb, 0xb3, 0xc1, 0x80, + 0xef, 0xa9, 0x12, 0x2e, 0xfa, 0x3f, 0x20, 0x3c, 0xd4, 0xd9, 0xb1, 0xab, + 0x9e, 0xed, 0x23, 0x7c, 0x3b, 0xb3, 0x5b, 0x65, 0xca, 0xb6, 0xe1, 0xd8, + 0xe5, 0x8e, 0xfd, 0xbd, 0x3a, 0x57, 0x1c, 0x1e, 0xef, 0xad, 0x7e, 0xdd, + 0x5e, 0xc5, 0xe0, 0xc9, 0x02, 0x82, 0x01, 0x00, 0x28, 0x3d, 0xfd, 0x5b, + 0x08, 0x71, 0x86, 0x3d, 0x9e, 0x91, 0x86, 0x64, 0x45, 0xce, 0xf2, 0xec, + 0x27, 0x50, 0xf4, 0xfa, 0xe3, 0xa2, 0x0e, 0xaf, 0xf6, 0xd1, 0x43, 0x28, + 0xb9, 0xcd, 0xaf, 0xed, 0x96, 0x68, 0x37, 0xdc, 0xdc, 0xac, 0xa0, 0x3d, + 0xbc, 0xc0, 0xd6, 0x4b, 0x32, 0xc5, 0xc6, 0x89, 0x2d, 0xda, 0x1d, 0x84, + 0x14, 0x31, 0x70, 0xa8, 0x45, 0x1d, 0x62, 0x39, 0xae, 0xfb, 0x9f, 0x73, + 0x70, 0x60, 0x08, 0x3a, 0x4c, 0xd0, 0x06, 0x2c, 0xb3, 0x53, 0xcc, 0x9e, + 0x07, 0xc1, 0x28, 0xa3, 0x0f, 0x61, 0xfd, 0x82, 0x77, 0xc4, 0x25, 0x36, + 0x9c, 0xa3, 0x47, 0x6d, 0x04, 0x7d, 0x92, 0xeb, 0x8d, 0xc2, 0x27, 0xc6, + 0x1d, 0x5f, 0xe5, 0x34, 0x7f, 0xa1, 0xac, 0xe1, 0xec, 0x0c, 0x72, 0x09, + 0x2e, 0x6c, 0x91, 0xba, 0xbb, 0xd3, 0x60, 0x6f, 0x71, 0xf8, 0xd8, 0x2c, + 0xe0, 0x6d, 0x3b, 0x02, 0xbe, 0xb8, 0xda, 0xfe, 0xdb, 0xe0, 0xfa, 0xc9, + 0x22, 0xe7, 0xd6, 0x5d, 0x50, 0xa0, 0x4c, 0x77, 0xc0, 0x87, 0xa2, 0x32, + 0x2e, 0x8d, 0x6c, 0xe0, 0xfb, 0xcc, 0x5a, 0x3c, 0xe9, 0xb1, 0x66, 0x1b, + 0xf9, 0x97, 0xfb, 0xd6, 0x08, 0x74, 0x0e, 0x53, 0x10, 0x75, 0x5c, 0x98, + 0x23, 0xc0, 0x50, 0xe2, 0xb3, 0x85, 0xf7, 0x71, 0x10, 0x85, 0x43, 0x71, + 0x9a, 0x00, 0x8f, 0xd0, 0x47, 0xc1, 0x69, 0xd6, 0xd7, 0x5f, 0xfe, 0x1b, + 0xe9, 0x1f, 0x66, 0x10, 0xbc, 0xc8, 0x71, 0x94, 0xb5, 0x6e, 0xe1, 0x0a, + 0x85, 0x93, 0x11, 0x2b, 0xc7, 0x13, 0x94, 0x1f, 0xf8, 0xeb, 0x07, 0x46, + 0xb0, 0x7c, 0x1b, 0xab, 0xc8, 0x1f, 0x7d, 0x52, 0xc1, 0x21, 0xcf, 0x47, + 0x3a, 0xa6, 0x16, 0x3c, 0x05, 0x66, 0xde, 0x8b, 0x21, 0x4d, 0x0e, 0xf2, + 0xf3, 0x49, 0x8b, 0xa5, 0x01, 0xee, 0x82, 0x7c, 0x6d, 0x22, 0xec, 0x0d, + 0x02, 0x82, 0x01, 0x00, 0x39, 0x88, 0xc7, 0x5d, 0x9c, 0x8b, 0xbc, 0xa1, + 0x33, 0xe4, 0x93, 0x24, 0x91, 0x3c, 0xfb, 0x35, 0xf5, 0xaf, 0x61, 0xa3, + 0x06, 0x0e, 0xf5, 0x28, 0x9e, 0x95, 0x21, 0xd8, 0xa3, 0xea, 0x77, 0xc0, + 0x70, 0x28, 0x3f, 0xff, 0x4e, 0x6b, 0x8c, 0x01, 0x83, 0x43, 0xcd, 0x71, + 0xb4, 0xe3, 0xcc, 0xa7, 0x1e, 0xff, 0xbe, 0xf4, 0x78, 0xdc, 0x67, 0xf5, + 0xe9, 0x3d, 0x6d, 0x06, 0x29, 0x53, 0xd5, 0x20, 0x99, 0x4b, 0x03, 0xab, + 0x41, 0x48, 0xe7, 0x13, 0x28, 0x1f, 0x0f, 0x96, 0xea, 0x44, 0x12, 0x6b, + 0x0d, 0x67, 0xfc, 0x3b, 0x7b, 0xbc, 0x2a, 0x2d, 0x2a, 0x8b, 0x31, 0xa5, + 0x81, 0xc8, 0xf4, 0x4d, 0xd2, 0x9f, 0xbf, 0x49, 0x11, 0xd6, 0x05, 0x2b, + 0x68, 0x8f, 0x5a, 0x40, 0x98, 0x0a, 0x3f, 0x3f, 0xd5, 0xae, 0x96, 0x46, + 0xae, 0xd0, 0x66, 0x80, 0xe4, 0x3c, 0x2e, 0x34, 0xde, 0x7d, 0xbc, 0x30, + 0x95, 0xa2, 0x6a, 0x94, 0x4e, 0xa5, 0x4c, 0x55, 0x37, 0xca, 0x0d, 0x70, + 0x6b, 0xae, 0xde, 0x1e, 0xa2, 0xcd, 0x6a, 0xdf, 0xda, 0xa1, 0xa1, 0xd8, + 0xec, 0xd3, 0x9d, 0xde, 0x07, 0xc1, 0xa0, 0xb7, 0xab, 0x52, 0xe4, 0xc8, + 0x3c, 0x1b, 0x55, 0xae, 0xb7, 0x84, 0x9b, 0xd6, 0x90, 0x13, 0x49, 0xed, + 0x65, 0x88, 0x4b, 0x3c, 0x94, 0x55, 0xc8, 0x86, 0x87, 0x5a, 0x0b, 0xa5, + 0x7c, 0x20, 0xec, 0xc5, 0x48, 0x9e, 0xb2, 0x6c, 0x0e, 0x0c, 0xf2, 0x4d, + 0xea, 0x1a, 0x44, 0x8e, 0x66, 0xaa, 0x6e, 0x6c, 0x9a, 0xea, 0x18, 0x02, + 0x7c, 0xaf, 0xf0, 0x5e, 0x63, 0xb7, 0xe2, 0xb1, 0x8e, 0x99, 0x99, 0x32, + 0xa5, 0x0f, 0x0f, 0x35, 0x88, 0x6d, 0xf6, 0xc5, 0x5c, 0x75, 0x70, 0x7f, + 0xab, 0x78, 0xa3, 0x15, 0x43, 0x08, 0x88, 0x58, 0x9d, 0xbb, 0x63, 0xf7, + 0x59, 0x8e, 0xd7, 0x45, 0x87, 0x86, 0x05, 0x9d, +}; + +const size_t kDERRSAPrivate4096Len = sizeof(kDERRSAPrivate4096); + +const uint8_t kDERRSAPrivate3Prime2048[] = { + 0x30, 0x82, 0x04, 0xd7, 0x02, 0x01, 0x01, 0x02, 0x82, 0x01, 0x00, 0x62, + 0x91, 0xe9, 0xea, 0xb3, 0x5d, 0x6c, 0x29, 0xae, 0x21, 0x83, 0xbb, 0xb5, + 0x82, 0xb1, 0x9e, 0xea, 0xe0, 0x64, 0x5b, 0x1e, 0x2f, 0x5e, 0x2c, 0x0a, + 0x80, 0x3d, 0x29, 0xd4, 0xfa, 0x9a, 0xe7, 0x44, 0xe6, 0x21, 0xbd, 0x98, + 0xc0, 0x3d, 0xe0, 0x53, 0x59, 0xae, 0xd3, 0x3e, 0xfe, 0xc4, 0xc2, 0xc4, + 0x5a, 0x5a, 0x89, 0x07, 0xf4, 0x4f, 0xdc, 0xb0, 0x6a, 0xd4, 0x3e, 0x99, + 0x7d, 0x7a, 0x97, 0x26, 0x4e, 0xe1, 0x93, 0xca, 0x6e, 0xed, 0x07, 0xfc, + 0xb4, 0xfa, 0x95, 0x1e, 0x73, 0x7b, 0x86, 0x08, 0x6a, 0xb9, 0xd4, 0x29, + 0xb0, 0x7e, 0x59, 0xb7, 0x9d, 0x7b, 0xeb, 0x67, 0x6e, 0xf0, 0xbb, 0x5e, + 0xcf, 0xb9, 0xcd, 0x58, 0x93, 0xf0, 0xe7, 0x88, 0x17, 0x6c, 0x0d, 0x76, + 0x1e, 0xb9, 0x27, 0x9a, 0x4d, 0x02, 0x16, 0xb6, 0x49, 0x6d, 0xa7, 0x83, + 0x23, 0x4d, 0x02, 0x48, 0x0c, 0x0c, 0x1f, 0x0e, 0x85, 0x21, 0xe3, 0x06, + 0x76, 0x0a, 0x73, 0xe6, 0xc1, 0x21, 0xfa, 0x30, 0x18, 0x78, 0x29, 0x5c, + 0x31, 0xd0, 0x29, 0xae, 0x6f, 0x7d, 0x87, 0xd8, 0x2f, 0x16, 0xfa, 0xbc, + 0x67, 0x8a, 0x94, 0x71, 0x59, 0x9b, 0xec, 0x22, 0x40, 0x55, 0x9f, 0xc2, + 0x94, 0xb5, 0xbd, 0x78, 0x01, 0xc9, 0xef, 0x18, 0xc8, 0x6d, 0x0d, 0xdc, + 0x53, 0x42, 0xb2, 0x5c, 0xab, 0x65, 0x05, 0xbd, 0x35, 0x08, 0x85, 0x1b, + 0xf8, 0xe9, 0x47, 0xbc, 0xfe, 0xc5, 0xae, 0x47, 0x29, 0x63, 0x44, 0x8e, + 0x4d, 0xb7, 0x47, 0xab, 0x0d, 0xd8, 0x76, 0x68, 0x4f, 0xc7, 0x07, 0x02, + 0xe4, 0x86, 0xb0, 0xcf, 0xd8, 0x19, 0xad, 0xf4, 0x85, 0x76, 0x8b, 0x3b, + 0x4e, 0x40, 0x8d, 0x29, 0x7a, 0x8a, 0x07, 0x36, 0xf3, 0x78, 0xae, 0x17, + 0xa6, 0x8f, 0x53, 0x58, 0x65, 0x4c, 0x86, 0x9e, 0xd7, 0x8b, 0xec, 0x38, + 0x4f, 0x99, 0xc7, 0x02, 0x01, 0x03, 0x02, 0x82, 0x01, 0x00, 0x41, 0xb6, + 0x9b, 0xf1, 0xcc, 0xe8, 0xf2, 0xc6, 0x74, 0x16, 0x57, 0xd2, 0x79, 0x01, + 0xcb, 0xbf, 0x47, 0x40, 0x42, 0xe7, 0x69, 0x74, 0xe9, 0x72, 0xb1, 0xaa, + 0xd3, 0x71, 0x38, 0xa7, 0x11, 0xef, 0x83, 0x44, 0x16, 0x7e, 0x65, 0xd5, + 0x7e, 0x95, 0x8c, 0xe6, 0x74, 0x8c, 0xd4, 0xa9, 0xd8, 0x81, 0xd8, 0x3c, + 0x3c, 0x5b, 0x5a, 0xa2, 0xdf, 0xe8, 0x75, 0x9c, 0x8d, 0x7f, 0x10, 0xfe, + 0x51, 0xba, 0x19, 0x89, 0xeb, 0xb7, 0xdc, 0x49, 0xf3, 0x5a, 0xa8, 0x78, + 0xa7, 0x0e, 0x14, 0x4c, 0xfd, 0x04, 0x05, 0x9c, 0x7b, 0xe2, 0xc5, 0xa3, + 0x04, 0xee, 0xd9, 0x4c, 0xfd, 0x7d, 0x47, 0xb0, 0x0d, 0x9b, 0x3d, 0x70, + 0x91, 0x81, 0x2c, 0xab, 0x2b, 0x87, 0xad, 0x11, 0x68, 0x24, 0xfc, 0x2b, + 0xd4, 0xee, 0x5e, 0x28, 0xeb, 0x6d, 0xab, 0xde, 0x0f, 0x77, 0x15, 0x58, + 0x76, 0x39, 0xc9, 0x59, 0x3a, 0x7f, 0x19, 0x9d, 0xc6, 0x7e, 0x86, 0xe4, + 0xd5, 0x38, 0x70, 0x9e, 0xae, 0xb9, 0xfb, 0x33, 0x33, 0xd1, 0x0c, 0x2d, + 0xab, 0x01, 0x20, 0xe1, 0x8b, 0x29, 0x99, 0xd3, 0xeb, 0x87, 0x05, 0x72, + 0xaa, 0x43, 0x58, 0x64, 0x8e, 0x9e, 0x31, 0xdb, 0x45, 0x9b, 0x2b, 0xac, + 0x58, 0x80, 0x5d, 0x33, 0xa2, 0x43, 0x05, 0x96, 0xcc, 0xca, 0x2d, 0x04, + 0x5f, 0xd6, 0xb7, 0x3d, 0x8b, 0x8f, 0x2d, 0xa3, 0xa5, 0xf8, 0x73, 0xf5, + 0xd7, 0xc0, 0x19, 0xff, 0x10, 0xe6, 0xee, 0x3a, 0x26, 0x2f, 0xe1, 0x64, + 0x3d, 0x11, 0xcd, 0x2d, 0xe4, 0x0a, 0x84, 0x27, 0xe3, 0xcb, 0x16, 0x62, + 0x19, 0xe7, 0xe3, 0x0d, 0x13, 0xe8, 0x09, 0x5a, 0x53, 0xd0, 0x20, 0x56, + 0x15, 0xf5, 0xb3, 0x67, 0xac, 0xa1, 0xb5, 0x94, 0x6b, 0xab, 0xdc, 0x71, + 0xc7, 0xbf, 0x0a, 0xde, 0x76, 0xf5, 0x03, 0xa0, 0x30, 0xd8, 0x27, 0x9d, + 0x00, 0x2b, 0x02, 0x57, 0x00, 0xf1, 0x4f, 0xc2, 0x86, 0x13, 0x06, 0x17, + 0xf7, 0x69, 0x7e, 0x37, 0xdf, 0x67, 0xc5, 0x32, 0xa0, 0x74, 0x1c, 0x32, + 0x69, 0x0f, 0x9f, 0x08, 0x88, 0x24, 0xb1, 0x51, 0xbc, 0xbc, 0x92, 0xba, + 0x73, 0x1f, 0x9c, 0x75, 0xc2, 0x14, 0x6d, 0x4f, 0xc4, 0x5a, 0xcf, 0xda, + 0x44, 0x35, 0x00, 0x6b, 0x42, 0x3b, 0x9f, 0x14, 0xf1, 0x05, 0xb3, 0x51, + 0x22, 0xb6, 0xbe, 0x9c, 0xe0, 0xc1, 0x5c, 0x48, 0x61, 0xdf, 0x4e, 0x4c, + 0x72, 0xb8, 0x05, 0x35, 0x7c, 0xac, 0xf1, 0xbb, 0xa0, 0x3b, 0x2a, 0xea, + 0xf7, 0x86, 0xe9, 0xd2, 0xff, 0x1e, 0x1d, 0x02, 0x56, 0x00, 0xca, 0xb1, + 0x39, 0xf6, 0xa2, 0xc6, 0x3b, 0x65, 0x45, 0x2f, 0x39, 0x00, 0xcd, 0x6e, + 0xd6, 0x55, 0xf7, 0x71, 0x37, 0x89, 0xc2, 0xe7, 0x7a, 0xc0, 0x1a, 0xa6, + 0x2f, 0xea, 0x17, 0x7c, 0xaa, 0x2a, 0x91, 0x8f, 0xd4, 0xc7, 0x50, 0x8b, + 0xab, 0x8e, 0x99, 0x3b, 0x33, 0x91, 0xbc, 0x02, 0x10, 0x58, 0x4b, 0x58, + 0x40, 0x9b, 0xc4, 0x8f, 0x48, 0x2b, 0xa7, 0x44, 0xfd, 0x07, 0x04, 0xf0, + 0x98, 0x67, 0x56, 0xea, 0x25, 0x92, 0x8b, 0x2e, 0x4b, 0x4a, 0xa1, 0xd3, + 0xc2, 0xa4, 0xb4, 0x9b, 0x59, 0x70, 0x32, 0xa6, 0xd8, 0x8b, 0xd9, 0x02, + 0x57, 0x00, 0xa0, 0xdf, 0xd7, 0x04, 0x0c, 0xae, 0xba, 0xa4, 0xf0, 0xfe, + 0xcf, 0xea, 0x45, 0x2e, 0x21, 0xc0, 0x4d, 0x68, 0x21, 0x9b, 0x5f, 0xbf, + 0x5b, 0x05, 0x6d, 0xcb, 0x8b, 0xd3, 0x28, 0x61, 0xd1, 0xa2, 0x15, 0x12, + 0xf9, 0x2c, 0x0d, 0x9e, 0x35, 0x2d, 0x91, 0xdf, 0xe6, 0xd8, 0x23, 0x55, + 0x9c, 0xd6, 0xd2, 0x6a, 0x0d, 0xf6, 0x03, 0xcc, 0xe0, 0xc1, 0xcf, 0x29, + 0xbd, 0xeb, 0x2b, 0x92, 0xda, 0xeb, 0xea, 0x34, 0x32, 0xf7, 0x25, 0x58, + 0xce, 0x53, 0x1d, 0xf6, 0x7d, 0x15, 0x7c, 0xc7, 0x47, 0x4f, 0xaf, 0x46, + 0x8c, 0xaa, 0x14, 0x13, 0x02, 0x56, 0x00, 0x87, 0x20, 0xd1, 0x4f, 0x17, + 0x2e, 0xd2, 0x43, 0x83, 0x74, 0xd0, 0xab, 0x33, 0x9f, 0x39, 0x8e, 0xa4, + 0xf6, 0x25, 0x06, 0x81, 0xef, 0xa7, 0x2a, 0xbc, 0x6e, 0xca, 0x9c, 0x0f, + 0xa8, 0x71, 0x71, 0xb6, 0x5f, 0xe3, 0x2f, 0x8b, 0x07, 0xc7, 0xb4, 0x66, + 0x27, 0x77, 0xb6, 0x7d, 0x56, 0xb5, 0x90, 0x32, 0x3a, 0xd5, 0xbd, 0x2d, + 0xb4, 0xda, 0xc7, 0xc4, 0xd8, 0xa8, 0xaf, 0x58, 0xa0, 0x65, 0x9a, 0x39, + 0xf1, 0x6e, 0x61, 0xb2, 0x1e, 0xdc, 0xdc, 0x6b, 0xe2, 0x81, 0xc3, 0x23, + 0x12, 0x3b, 0xa0, 0x21, 0xc4, 0x90, 0x5d, 0x3b, 0x02, 0x57, 0x00, 0xe6, + 0x8a, 0xaa, 0xb8, 0x6d, 0x2c, 0x81, 0x43, 0xb5, 0xd6, 0xa0, 0x2b, 0x42, + 0x49, 0xa9, 0x0a, 0x51, 0xfa, 0x18, 0xc8, 0x32, 0xea, 0x54, 0x18, 0xf3, + 0x60, 0xc2, 0xb5, 0x4a, 0x43, 0x05, 0x93, 0x9c, 0x01, 0xd9, 0x28, 0xed, + 0x73, 0xfa, 0x82, 0xbc, 0x12, 0x64, 0xcb, 0xc4, 0x24, 0xa9, 0x3e, 0xae, + 0x7c, 0x4b, 0x8f, 0x94, 0x57, 0x7b, 0x14, 0x10, 0x41, 0xdc, 0x62, 0x12, + 0x8c, 0xb2, 0x4a, 0x7c, 0xf6, 0x53, 0xd4, 0xc6, 0xe4, 0xda, 0xd1, 0xa2, + 0x00, 0x0e, 0x3d, 0x30, 0xf7, 0x05, 0x4f, 0x1d, 0x82, 0xbc, 0x52, 0xd9, + 0xb1, 0x30, 0x82, 0x01, 0x0a, 0x30, 0x82, 0x01, 0x06, 0x02, 0x56, 0x00, + 0x84, 0x12, 0x4f, 0xf7, 0x3b, 0x65, 0x53, 0x34, 0x6c, 0x6c, 0x4d, 0x77, + 0xdf, 0xfd, 0x1f, 0xb6, 0x16, 0xe2, 0x25, 0x15, 0xca, 0xc9, 0xc1, 0x41, + 0x9a, 0x50, 0xda, 0xeb, 0x88, 0x4f, 0x3d, 0xb3, 0x01, 0x00, 0x44, 0xc4, + 0xac, 0xe7, 0x14, 0x62, 0xa6, 0x56, 0xde, 0xc5, 0xb7, 0xc3, 0x1d, 0x07, + 0xbd, 0x7d, 0x64, 0xc5, 0x7e, 0x45, 0x25, 0x56, 0xed, 0x7a, 0xd2, 0x14, + 0xdb, 0x4e, 0x27, 0xd4, 0x1f, 0xf8, 0x94, 0xa7, 0xef, 0x07, 0xce, 0xdb, + 0x24, 0xb7, 0xdd, 0x71, 0x5c, 0x63, 0xc9, 0x33, 0xfe, 0xde, 0x40, 0x52, + 0xeb, 0x02, 0x55, 0x58, 0x0c, 0x35, 0x4f, 0x7c, 0xee, 0x37, 0x78, 0x48, + 0x48, 0x33, 0xa5, 0x3f, 0xfe, 0x15, 0x24, 0x0f, 0x41, 0x6e, 0x0e, 0x87, + 0x31, 0x2b, 0x81, 0x11, 0x8b, 0x3c, 0x9d, 0x05, 0x8a, 0x29, 0x22, 0x00, + 0xaa, 0xd8, 0x83, 0x1d, 0xef, 0x62, 0xec, 0x6e, 0xe4, 0x94, 0x83, 0xcf, + 0xd7, 0x68, 0xaf, 0xd3, 0xa8, 0xed, 0xd8, 0xfe, 0xd8, 0xc3, 0x8f, 0x48, + 0xfc, 0x8c, 0x0d, 0xe7, 0x89, 0x6f, 0xe2, 0xbf, 0xfb, 0x0d, 0xc5, 0x4a, + 0x05, 0x34, 0x92, 0x18, 0x7a, 0x93, 0xa0, 0xe8, 0x42, 0x86, 0x22, 0xa9, + 0xe9, 0x80, 0x37, 0x47, 0x02, 0x55, 0x60, 0x76, 0xab, 0xde, 0x2b, 0xf5, + 0xa2, 0x2c, 0xaa, 0x0c, 0x99, 0x81, 0xee, 0x72, 0x2c, 0x7d, 0x22, 0x59, + 0x2a, 0x35, 0xea, 0x50, 0x4e, 0x47, 0x6b, 0x92, 0x2d, 0x30, 0xa1, 0x01, + 0xa5, 0x9e, 0x26, 0x6e, 0x27, 0xca, 0xf5, 0xf2, 0x87, 0x5d, 0x31, 0xaf, + 0xe9, 0x32, 0xcd, 0x10, 0xfd, 0x4d, 0xdb, 0xf9, 0x86, 0x05, 0x12, 0x1b, + 0x01, 0x84, 0x55, 0x97, 0x5f, 0xe2, 0x78, 0x27, 0xd9, 0xe4, 0x26, 0x7d, + 0xab, 0x0e, 0xe0, 0x1b, 0x6f, 0xcb, 0x4b, 0x14, 0xdd, 0xdc, 0xdc, 0x8b, + 0xe8, 0x9f, 0xd0, 0x62, 0x96, 0xca, 0xcf, +}; + +const size_t kDERRSAPrivate3Prime2048Len = sizeof(kDERRSAPrivate3Prime2048); diff --git a/external/boringssl/tool/digest.cc b/external/boringssl/tool/digest.cc new file mode 100644 index 0000000000..2e3e6085f1 --- /dev/null +++ b/external/boringssl/tool/digest.cc @@ -0,0 +1,478 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#if !defined(OPENSSL_WINDOWS) +#include +#include +#if !defined(O_BINARY) +#define O_BINARY 0 +#endif +#else +OPENSSL_MSVC_PRAGMA(warning(push, 3)) +#include +OPENSSL_MSVC_PRAGMA(warning(pop)) +#include +#define PATH_MAX MAX_PATH +typedef int ssize_t; +#endif + +#include + +#include "internal.h" + + +struct close_delete { + void operator()(int *fd) { + BORINGSSL_CLOSE(*fd); + } +}; + +template +struct func_delete { + void operator()(T* obj) { + func(obj); + } +}; + +// Source is an awkward expression of a union type in C++: Stdin | File filename. +struct Source { + enum Type { + STDIN, + }; + + Source() : is_stdin_(false) {} + Source(Type) : is_stdin_(true) {} + Source(const std::string &name) : is_stdin_(false), filename_(name) {} + + bool is_stdin() const { return is_stdin_; } + const std::string &filename() const { return filename_; } + + private: + bool is_stdin_; + std::string filename_; +}; + +static const char kStdinName[] = "standard input"; + +// OpenFile opens the regular file named |filename| and sets |*out_fd| to be a +// file descriptor to it. Returns true on sucess or prints an error to stderr +// and returns false on error. +static bool OpenFile(int *out_fd, const std::string &filename) { + *out_fd = -1; + + int fd = BORINGSSL_OPEN(filename.c_str(), O_RDONLY | O_BINARY); + if (fd < 0) { + fprintf(stderr, "Failed to open input file '%s': %s\n", filename.c_str(), + strerror(errno)); + return false; + } + std::unique_ptr scoped_fd(&fd); + +#if !defined(OPENSSL_WINDOWS) + struct stat st; + if (fstat(fd, &st)) { + fprintf(stderr, "Failed to stat input file '%s': %s\n", filename.c_str(), + strerror(errno)); + return false; + } + + if (!S_ISREG(st.st_mode)) { + fprintf(stderr, "%s: not a regular file\n", filename.c_str()); + return false; + } +#endif + + *out_fd = fd; + scoped_fd.release(); + return true; +} + +// SumFile hashes the contents of |source| with |md| and sets |*out_hex| to the +// hex-encoded result. +// +// It returns true on success or prints an error to stderr and returns false on +// error. +static bool SumFile(std::string *out_hex, const EVP_MD *md, + const Source &source) { + std::unique_ptr scoped_fd; + int fd; + + if (source.is_stdin()) { + fd = 0; + } else { + if (!OpenFile(&fd, source.filename())) { + return false; + } + scoped_fd.reset(&fd); + } + + static const size_t kBufSize = 8192; + std::unique_ptr buf(new uint8_t[kBufSize]); + + EVP_MD_CTX ctx; + EVP_MD_CTX_init(&ctx); + std::unique_ptr> + scoped_ctx(&ctx); + + if (!EVP_DigestInit_ex(&ctx, md, NULL)) { + fprintf(stderr, "Failed to initialize EVP_MD_CTX.\n"); + return false; + } + + for (;;) { + ssize_t n; + + do { + n = BORINGSSL_READ(fd, buf.get(), kBufSize); + } while (n == -1 && errno == EINTR); + + if (n == 0) { + break; + } else if (n < 0) { + fprintf(stderr, "Failed to read from %s: %s\n", + source.is_stdin() ? kStdinName : source.filename().c_str(), + strerror(errno)); + return false; + } + + if (!EVP_DigestUpdate(&ctx, buf.get(), n)) { + fprintf(stderr, "Failed to update hash.\n"); + return false; + } + } + + uint8_t digest[EVP_MAX_MD_SIZE]; + unsigned digest_len; + if (!EVP_DigestFinal_ex(&ctx, digest, &digest_len)) { + fprintf(stderr, "Failed to finish hash.\n"); + return false; + } + + char hex_digest[EVP_MAX_MD_SIZE * 2]; + static const char kHextable[] = "0123456789abcdef"; + for (unsigned i = 0; i < digest_len; i++) { + const uint8_t b = digest[i]; + hex_digest[i * 2] = kHextable[b >> 4]; + hex_digest[i * 2 + 1] = kHextable[b & 0xf]; + } + *out_hex = std::string(hex_digest, digest_len * 2); + + return true; +} + +// PrintFileSum hashes |source| with |md| and prints a line to stdout in the +// format of the coreutils *sum utilities. It returns true on success or prints +// an error to stderr and returns false on error. +static bool PrintFileSum(const EVP_MD *md, const Source &source) { + std::string hex_digest; + if (!SumFile(&hex_digest, md, source)) { + return false; + } + + // TODO: When given "--binary" or "-b", we should print " *" instead of " " + // between the digest and the filename. + // + // MSYS and Cygwin md5sum default to binary mode by default, whereas other + // platforms' tools default to text mode by default. We default to text mode + // by default and consider text mode equivalent to binary mode (i.e. we + // always use Unix semantics, even on Windows), which means that our default + // output will differ from the MSYS and Cygwin tools' default output. + printf("%s %s\n", hex_digest.c_str(), + source.is_stdin() ? "-" : source.filename().c_str()); + return true; +} + +// CheckModeArguments contains arguments for the check mode. See the +// sha256sum(1) man page for details. +struct CheckModeArguments { + bool quiet = false; + bool status = false; + bool warn = false; + bool strict = false; +}; + +// Check reads lines from |source| where each line is in the format of the +// coreutils *sum utilities. It attempts to verify each hash by reading the +// file named in the line. +// +// It returns true if all files were verified and, if |args.strict|, no input +// lines had formatting errors. Otherwise it prints errors to stderr and +// returns false. +static bool Check(const CheckModeArguments &args, const EVP_MD *md, + const Source &source) { + std::unique_ptr> scoped_file; + FILE *file; + + if (source.is_stdin()) { + file = stdin; + } else { + int fd; + if (!OpenFile(&fd, source.filename())) { + return false; + } + + file = BORINGSSL_FDOPEN(fd, "rb"); + if (!file) { + perror("fdopen"); + BORINGSSL_CLOSE(fd); + return false; + } + + scoped_file = std::unique_ptr>(file); + } + + const size_t hex_size = EVP_MD_size(md) * 2; + char line[EVP_MAX_MD_SIZE * 2 + 2 /* spaces */ + PATH_MAX + 1 /* newline */ + + 1 /* NUL */]; + unsigned bad_lines = 0; + unsigned parsed_lines = 0; + unsigned error_lines = 0; + unsigned bad_hash_lines = 0; + unsigned line_no = 0; + bool ok = true; + bool draining_overlong_line = false; + + for (;;) { + line_no++; + + if (fgets(line, sizeof(line), file) == nullptr) { + if (feof(file)) { + break; + } + fprintf(stderr, "Error reading from input.\n"); + return false; + } + + size_t len = strlen(line); + + if (draining_overlong_line) { + if (line[len - 1] == '\n') { + draining_overlong_line = false; + } + continue; + } + + const bool overlong = line[len - 1] != '\n' && !feof(file); + + if (len < hex_size + 2 /* spaces */ + 1 /* filename */ || + line[hex_size] != ' ' || + line[hex_size + 1] != ' ' || + overlong) { + bad_lines++; + if (args.warn) { + fprintf(stderr, "%s: %u: improperly formatted line\n", + source.is_stdin() ? kStdinName : source.filename().c_str(), line_no); + } + if (args.strict) { + ok = false; + } + if (overlong) { + draining_overlong_line = true; + } + continue; + } + + if (line[len - 1] == '\n') { + line[len - 1] = 0; + len--; + } + + parsed_lines++; + + // coreutils does not attempt to restrict relative or absolute paths in the + // input so nor does this code. + std::string calculated_hex_digest; + const std::string target_filename(&line[hex_size + 2]); + Source target_source; + if (target_filename == "-") { + // coreutils reads from stdin if the filename is "-". + target_source = Source(Source::STDIN); + } else { + target_source = Source(target_filename); + } + + if (!SumFile(&calculated_hex_digest, md, target_source)) { + error_lines++; + ok = false; + continue; + } + + if (calculated_hex_digest != std::string(line, hex_size)) { + bad_hash_lines++; + if (!args.status) { + printf("%s: FAILED\n", target_filename.c_str()); + } + ok = false; + continue; + } + + if (!args.quiet) { + printf("%s: OK\n", target_filename.c_str()); + } + } + + if (!args.status) { + if (bad_lines > 0 && parsed_lines > 0) { + fprintf(stderr, "WARNING: %u line%s improperly formatted\n", bad_lines, + bad_lines == 1 ? " is" : "s are"); + } + if (error_lines > 0) { + fprintf(stderr, "WARNING: %u computed checksum(s) did NOT match\n", + error_lines); + } + } + + if (parsed_lines == 0) { + fprintf(stderr, "%s: no properly formatted checksum lines found.\n", + source.is_stdin() ? kStdinName : source.filename().c_str()); + ok = false; + } + + return ok; +} + +// DigestSum acts like the coreutils *sum utilites, with the given hash +// function. +static bool DigestSum(const EVP_MD *md, + const std::vector &args) { + bool check_mode = false; + CheckModeArguments check_args; + bool check_mode_args_given = false; + std::vector sources; + + auto it = args.begin(); + while (it != args.end()) { + const std::string &arg = *it; + if (!arg.empty() && arg[0] != '-') { + break; + } + + it++; + + if (arg == "--") { + break; + } + + if (arg == "-") { + // "-" ends the argument list and indicates that stdin should be used. + sources.push_back(Source(Source::STDIN)); + break; + } + + if (arg.size() >= 2 && arg[0] == '-' && arg[1] != '-') { + for (size_t i = 1; i < arg.size(); i++) { + switch (arg[i]) { + case 'b': + case 't': + // Binary/text mode – irrelevent, even on Windows. + break; + case 'c': + check_mode = true; + break; + case 'w': + check_mode_args_given = true; + check_args.warn = true; + break; + default: + fprintf(stderr, "Unknown option '%c'.\n", arg[i]); + return false; + } + } + } else if (arg == "--binary" || arg == "--text") { + // Binary/text mode – irrelevent, even on Windows. + } else if (arg == "--check") { + check_mode = true; + } else if (arg == "--quiet") { + check_mode_args_given = true; + check_args.quiet = true; + } else if (arg == "--status") { + check_mode_args_given = true; + check_args.status = true; + } else if (arg == "--warn") { + check_mode_args_given = true; + check_args.warn = true; + } else if (arg == "--strict") { + check_mode_args_given = true; + check_args.strict = true; + } else { + fprintf(stderr, "Unknown option '%s'.\n", arg.c_str()); + return false; + } + } + + if (check_mode_args_given && !check_mode) { + fprintf( + stderr, + "Check mode arguments are only meaningful when verifying checksums.\n"); + return false; + } + + for (; it != args.end(); it++) { + sources.push_back(Source(*it)); + } + + if (sources.empty()) { + sources.push_back(Source(Source::STDIN)); + } + + bool ok = true; + + if (check_mode) { + for (auto &source : sources) { + ok &= Check(check_args, md, source); + } + } else { + for (auto &source : sources) { + ok &= PrintFileSum(md, source); + } + } + + return ok; +} + +bool MD5Sum(const std::vector &args) { + return DigestSum(EVP_md5(), args); +} + +bool SHA1Sum(const std::vector &args) { + return DigestSum(EVP_sha1(), args); +} + +bool SHA224Sum(const std::vector &args) { + return DigestSum(EVP_sha224(), args); +} + +bool SHA256Sum(const std::vector &args) { + return DigestSum(EVP_sha256(), args); +} + +bool SHA384Sum(const std::vector &args) { + return DigestSum(EVP_sha384(), args); +} + +bool SHA512Sum(const std::vector &args) { + return DigestSum(EVP_sha512(), args); +} diff --git a/external/boringssl/tool/generate_ed25519.cc b/external/boringssl/tool/generate_ed25519.cc new file mode 100644 index 0000000000..15d36924bb --- /dev/null +++ b/external/boringssl/tool/generate_ed25519.cc @@ -0,0 +1,67 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include +#include +#include + +#include "../crypto/test/scoped_types.h" +#include "internal.h" + + +static const struct argument kArguments[] = { + { + "-out-public", kRequiredArgument, "The file to write the public key to", + }, + { + "-out-private", kRequiredArgument, + "The file to write the private key to", + }, + { + "", kOptionalArgument, "", + }, +}; + +static bool WriteToFile(const std::string &path, const uint8_t *in, + size_t in_len) { + ScopedFILE file(fopen(path.c_str(), "wb")); + if (!file) { + fprintf(stderr, "Failed to open '%s': %s\n", path.c_str(), strerror(errno)); + return false; + } + if (fwrite(in, in_len, 1, file.get()) != 1) { + fprintf(stderr, "Failed to write to '%s': %s\n", path.c_str(), + strerror(errno)); + return false; + } + return true; +} + +bool GenerateEd25519Key(const std::vector &args) { + std::map args_map; + + if (!ParseKeyValueArguments(&args_map, args, kArguments)) { + PrintUsage(kArguments); + return false; + } + + uint8_t public_key[32], private_key[64]; + ED25519_keypair(public_key, private_key); + + return WriteToFile(args_map["-out-public"], public_key, sizeof(public_key)) && + WriteToFile(args_map["-out-private"], private_key, + sizeof(private_key)); +} diff --git a/external/boringssl/tool/genrsa.cc b/external/boringssl/tool/genrsa.cc new file mode 100644 index 0000000000..4b39401532 --- /dev/null +++ b/external/boringssl/tool/genrsa.cc @@ -0,0 +1,69 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include +#include +#include +#include + +#include "../crypto/test/scoped_types.h" +#include "internal.h" + + +static const struct argument kArguments[] = { + { + "-nprimes", kOptionalArgument, + "The number of primes to generate (default: 2)", + }, + { + "-bits", kOptionalArgument, + "The number of bits in the modulus (default: 2048)", + }, + { + "", kOptionalArgument, "", + }, +}; + +bool GenerateRSAKey(const std::vector &args) { + std::map args_map; + + if (!ParseKeyValueArguments(&args_map, args, kArguments)) { + PrintUsage(kArguments); + return false; + } + + unsigned bits, nprimes = 0; + if (!GetUnsigned(&bits, "-bits", 2048, args_map) || + !GetUnsigned(&nprimes, "-nprimes", 2, args_map)) { + PrintUsage(kArguments); + return false; + } + + ScopedRSA rsa(RSA_new()); + ScopedBIGNUM e(BN_new()); + ScopedBIO bio(BIO_new_fp(stdout, BIO_NOCLOSE)); + + if (!BN_set_word(e.get(), RSA_F4) || + !RSA_generate_multi_prime_key(rsa.get(), bits, nprimes, e.get(), NULL) || + !PEM_write_bio_RSAPrivateKey(bio.get(), rsa.get(), NULL /* cipher */, + NULL /* key */, 0 /* key len */, + NULL /* password callback */, + NULL /* callback arg */)) { + ERR_print_errors_fp(stderr); + return false; + } + + return true; +} diff --git a/external/boringssl/tool/internal.h b/external/boringssl/tool/internal.h new file mode 100644 index 0000000000..fd66e00f6b --- /dev/null +++ b/external/boringssl/tool/internal.h @@ -0,0 +1,92 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_TOOL_INTERNAL_H +#define OPENSSL_HEADER_TOOL_INTERNAL_H + +#include + +#include +#include + +OPENSSL_MSVC_PRAGMA(warning(push)) +// MSVC issues warning C4702 for unreachable code in its xtree header when +// compiling with -D_HAS_EXCEPTIONS=0. See +// https://connect.microsoft.com/VisualStudio/feedback/details/809962 +OPENSSL_MSVC_PRAGMA(warning(disable: 4702)) + +#include + +OPENSSL_MSVC_PRAGMA(warning(pop)) + +#if defined(OPENSSL_WINDOWS) + #define BORINGSSL_OPEN _open + #define BORINGSSL_FDOPEN _fdopen + #define BORINGSSL_CLOSE _close + #define BORINGSSL_READ _read + #define BORINGSSL_WRITE _write +#else + #define BORINGSSL_OPEN open + #define BORINGSSL_FDOPEN fdopen + #define BORINGSSL_CLOSE close + #define BORINGSSL_READ read + #define BORINGSSL_WRITE write +#endif + +enum ArgumentType { + kRequiredArgument, + kOptionalArgument, + kBooleanArgument, +}; + +struct argument { + const char *name; + ArgumentType type; + const char *description; +}; + +bool ParseKeyValueArguments(std::map *out_args, const + std::vector &args, const struct argument *templates); + +void PrintUsage(const struct argument *templates); + +bool GetUnsigned(unsigned *out, const std::string &arg_name, + unsigned default_value, + const std::map &args); + +bool Ciphers(const std::vector &args); +bool Client(const std::vector &args); +bool DoPKCS12(const std::vector &args); +bool GenerateEd25519Key(const std::vector &args); +bool GenerateRSAKey(const std::vector &args); +bool MD5Sum(const std::vector &args); +bool Rand(const std::vector &args); +bool SHA1Sum(const std::vector &args); +bool SHA224Sum(const std::vector &args); +bool SHA256Sum(const std::vector &args); +bool SHA384Sum(const std::vector &args); +bool SHA512Sum(const std::vector &args); +bool Server(const std::vector &args); +bool Speed(const std::vector &args); + +// These values are DER encoded, RSA private keys. +extern const uint8_t kDERRSAPrivate2048[]; +extern const size_t kDERRSAPrivate2048Len; +extern const uint8_t kDERRSAPrivate4096[]; +extern const size_t kDERRSAPrivate4096Len; +extern const uint8_t kDERRSAPrivate3Prime2048[]; +extern const size_t kDERRSAPrivate3Prime2048Len; + + +#endif /* !OPENSSL_HEADER_TOOL_INTERNAL_H */ diff --git a/external/boringssl/tool/pkcs12.cc b/external/boringssl/tool/pkcs12.cc new file mode 100644 index 0000000000..15e32d3d20 --- /dev/null +++ b/external/boringssl/tool/pkcs12.cc @@ -0,0 +1,142 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#if defined(OPENSSL_WINDOWS) +#include +#else +#include +#endif + +#include +#include +#include +#include +#include + +#include "internal.h" + + +#if defined(OPENSSL_WINDOWS) +typedef int read_result_t; +#else +typedef ssize_t read_result_t; +#endif + +static const struct argument kArguments[] = { + { + "-dump", kOptionalArgument, + "Dump the key and contents of the given file to stdout", + }, + { + "", kOptionalArgument, "", + }, +}; + +bool DoPKCS12(const std::vector &args) { + std::map args_map; + + if (!ParseKeyValueArguments(&args_map, args, kArguments) || + args_map["-dump"].empty()) { + PrintUsage(kArguments); + return false; + } + + int fd = BORINGSSL_OPEN(args_map["-dump"].c_str(), O_RDONLY); + if (fd < 0) { + perror("open"); + return false; + } + + struct stat st; + if (fstat(fd, &st)) { + perror("fstat"); + BORINGSSL_CLOSE(fd); + return false; + } + const size_t size = st.st_size; + + std::unique_ptr contents(new uint8_t[size]); + read_result_t n; + size_t off = 0; + do { + n = BORINGSSL_READ(fd, &contents[off], size - off); + if (n >= 0) { + off += static_cast(n); + } + } while ((n > 0 && off < size) || (n == -1 && errno == EINTR)); + + if (off != size) { + perror("read"); + BORINGSSL_CLOSE(fd); + return false; + } + + BORINGSSL_CLOSE(fd); + + printf("Enter password: "); + fflush(stdout); + + char password[256]; + off = 0; + do { + n = BORINGSSL_READ(0, &password[off], sizeof(password) - 1 - off); + if (n >= 0) { + off += static_cast(n); + } + } while ((n > 0 && memchr(password, '\n', off) == NULL && + off < sizeof(password) - 1) || + (n == -1 && errno == EINTR)); + + char *newline = reinterpret_cast(memchr(password, '\n', off)); + if (newline == NULL) { + return false; + } + *newline = 0; + + CBS pkcs12; + CBS_init(&pkcs12, contents.get(), size); + + EVP_PKEY *key; + STACK_OF(X509) *certs = sk_X509_new_null(); + + if (!PKCS12_get_key_and_certs(&key, certs, &pkcs12, password)) { + fprintf(stderr, "Failed to parse PKCS#12 data:\n"); + ERR_print_errors_fp(stderr); + return false; + } + + if (key != NULL) { + PEM_write_PrivateKey(stdout, key, NULL, NULL, 0, NULL, NULL); + EVP_PKEY_free(key); + } + + for (size_t i = 0; i < sk_X509_num(certs); i++) { + PEM_write_X509(stdout, sk_X509_value(certs, i)); + } + sk_X509_pop_free(certs, X509_free); + + return true; +} diff --git a/external/boringssl/tool/rand.cc b/external/boringssl/tool/rand.cc new file mode 100644 index 0000000000..3701748c34 --- /dev/null +++ b/external/boringssl/tool/rand.cc @@ -0,0 +1,95 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include + +#include +#include + +#include + +#include "internal.h" + + +static const struct argument kArguments[] = { + { + "-hex", kBooleanArgument, + "Hex encoded output." + }, + { + "", kOptionalArgument, "", + }, +}; + +bool Rand(const std::vector &args) { + bool forever = true, hex = false; + size_t len = 0; + + if (!args.empty()) { + std::vector args_copy(args); + const std::string &last_arg = args.back(); + + if (last_arg.size() > 0 && last_arg[0] != '-') { + char *endptr; + unsigned long long num = strtoull(last_arg.c_str(), &endptr, 10); + if (*endptr == 0) { + len = num; + forever = false; + args_copy.pop_back(); + } + } + + std::map args_map; + if (!ParseKeyValueArguments(&args_map, args_copy, kArguments)) { + PrintUsage(kArguments); + return false; + } + + hex = args_map.count("-hex") > 0; + } + + uint8_t buf[4096]; + uint8_t hex_buf[8192]; + + size_t done = 0; + while (forever || done < len) { + size_t todo = sizeof(buf); + if (!forever && todo > len - done) { + todo = len - done; + } + RAND_bytes(buf, todo); + if (hex) { + static const char hextable[16 + 1] = "0123456789abcdef"; + for (unsigned i = 0; i < todo; i++) { + hex_buf[i*2] = hextable[buf[i] >> 4]; + hex_buf[i*2 + 1] = hextable[buf[i] & 0xf]; + } + if (fwrite(hex_buf, todo*2, 1, stdout) != 1) { + return false; + } + } else { + if (fwrite(buf, todo, 1, stdout) != 1) { + return false; + } + } + done += todo; + } + + if (hex && fwrite("\n", 1, 1, stdout) != 1) { + return false; + } + + return true; +} diff --git a/external/boringssl/tool/server.cc b/external/boringssl/tool/server.cc new file mode 100644 index 0000000000..14f37a4494 --- /dev/null +++ b/external/boringssl/tool/server.cc @@ -0,0 +1,152 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include +#include + +#include "internal.h" +#include "transport_common.h" + + +static const struct argument kArguments[] = { + { + "-accept", kRequiredArgument, + "The port of the server to bind on; eg 45102", + }, + { + "-cipher", kOptionalArgument, + "An OpenSSL-style cipher suite string that configures the offered ciphers", + }, + { + "-key", kOptionalArgument, + "Private-key file to use (default is server.pem)", + }, + { + "-ocsp-response", kOptionalArgument, + "OCSP response file to send", + }, + { + "", kOptionalArgument, "", + }, +}; + +static bool LoadOCSPResponse(SSL_CTX *ctx, const char *filename) { + void *data = NULL; + bool ret = false; + size_t bytes_read; + long length; + + FILE *f = fopen(filename, "rb"); + + if (f == NULL || + fseek(f, 0, SEEK_END) != 0) { + goto out; + } + + length = ftell(f); + if (length < 0) { + goto out; + } + + data = malloc(length); + if (data == NULL) { + goto out; + } + rewind(f); + + bytes_read = fread(data, 1, length, f); + if (ferror(f) != 0 || + bytes_read != (size_t)length || + !SSL_CTX_set_ocsp_response(ctx, (uint8_t*)data, bytes_read)) { + goto out; + } + + ret = true; +out: + if (f != NULL) { + fclose(f); + } + free(data); + return ret; +} + +bool Server(const std::vector &args) { + if (!InitSocketLibrary()) { + return false; + } + + std::map args_map; + + if (!ParseKeyValueArguments(&args_map, args, kArguments)) { + PrintUsage(kArguments); + return false; + } + + SSL_CTX *ctx = SSL_CTX_new(SSLv23_server_method()); + SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3); + + // Server authentication is required. + std::string key_file = "server.pem"; + if (args_map.count("-key") != 0) { + key_file = args_map["-key"]; + } + if (!SSL_CTX_use_PrivateKey_file(ctx, key_file.c_str(), SSL_FILETYPE_PEM)) { + fprintf(stderr, "Failed to load private key: %s\n", key_file.c_str()); + return false; + } + if (!SSL_CTX_use_certificate_chain_file(ctx, key_file.c_str())) { + fprintf(stderr, "Failed to load cert chain: %s\n", key_file.c_str()); + return false; + } + + if (args_map.count("-cipher") != 0 && + !SSL_CTX_set_cipher_list(ctx, args_map["-cipher"].c_str())) { + fprintf(stderr, "Failed setting cipher list\n"); + return false; + } + + if (args_map.count("-ocsp-response") != 0 && + !LoadOCSPResponse(ctx, args_map["-ocsp-response"].c_str())) { + fprintf(stderr, "Failed to load OCSP response: %s\n", args_map["-ocsp-response"].c_str()); + return false; + } + + int sock = -1; + if (!Accept(&sock, args_map["-accept"])) { + return false; + } + + BIO *bio = BIO_new_socket(sock, BIO_CLOSE); + SSL *ssl = SSL_new(ctx); + SSL_set_bio(ssl, bio, bio); + + int ret = SSL_accept(ssl); + if (ret != 1) { + int ssl_err = SSL_get_error(ssl, ret); + fprintf(stderr, "Error while connecting: %d\n", ssl_err); + ERR_print_errors_cb(PrintErrorCallback, stderr); + return false; + } + + fprintf(stderr, "Connected.\n"); + PrintConnectionInfo(ssl); + + bool ok = TransferData(ssl, sock); + + SSL_free(ssl); + SSL_CTX_free(ctx); + return ok; +} diff --git a/external/boringssl/tool/speed.cc b/external/boringssl/tool/speed.cc new file mode 100644 index 0000000000..a8eb8bfa26 --- /dev/null +++ b/external/boringssl/tool/speed.cc @@ -0,0 +1,632 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(OPENSSL_WINDOWS) +OPENSSL_MSVC_PRAGMA(warning(push, 3)) +#include +OPENSSL_MSVC_PRAGMA(warning(pop)) +#elif defined(OPENSSL_APPLE) +#include +#endif + +#include "../crypto/test/scoped_types.h" +#include "internal.h" + + +// TimeResults represents the results of benchmarking a function. +struct TimeResults { + // num_calls is the number of function calls done in the time period. + unsigned num_calls; + // us is the number of microseconds that elapsed in the time period. + unsigned us; + + void Print(const std::string &description) { + printf("Did %u %s operations in %uus (%.1f ops/sec)\n", num_calls, + description.c_str(), us, + (static_cast(num_calls) / us) * 1000000); + } + + void PrintWithBytes(const std::string &description, size_t bytes_per_call) { + printf("Did %u %s operations in %uus (%.1f ops/sec): %.1f MB/s\n", + num_calls, description.c_str(), us, + (static_cast(num_calls) / us) * 1000000, + static_cast(bytes_per_call * num_calls) / us); + } +}; + +#if defined(OPENSSL_WINDOWS) +static uint64_t time_now() { return GetTickCount64() * 1000; } +#elif defined(OPENSSL_APPLE) +static uint64_t time_now() { + struct timeval tv; + uint64_t ret; + + gettimeofday(&tv, NULL); + ret = tv.tv_sec; + ret *= 1000000; + ret += tv.tv_usec; + return ret; +} +#else +static uint64_t time_now() { + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + + uint64_t ret = ts.tv_sec; + ret *= 1000000; + ret += ts.tv_nsec / 1000; + return ret; +} +#endif + +static bool TimeFunction(TimeResults *results, std::function func) { + // kTotalMS is the total amount of time that we'll aim to measure a function + // for. + static const uint64_t kTotalUS = 1000000; + uint64_t start = time_now(), now, delta; + unsigned done = 0, iterations_between_time_checks; + + if (!func()) { + return false; + } + now = time_now(); + delta = now - start; + if (delta == 0) { + iterations_between_time_checks = 250; + } else { + // Aim for about 100ms between time checks. + iterations_between_time_checks = + static_cast(100000) / static_cast(delta); + if (iterations_between_time_checks > 1000) { + iterations_between_time_checks = 1000; + } else if (iterations_between_time_checks < 1) { + iterations_between_time_checks = 1; + } + } + + for (;;) { + for (unsigned i = 0; i < iterations_between_time_checks; i++) { + if (!func()) { + return false; + } + done++; + } + + now = time_now(); + if (now - start > kTotalUS) { + break; + } + } + + results->us = now - start; + results->num_calls = done; + return true; +} + +static bool SpeedRSA(const std::string &key_name, RSA *key, + const std::string &selected) { + if (!selected.empty() && key_name.find(selected) == std::string::npos) { + return true; + } + + std::unique_ptr sig(new uint8_t[RSA_size(key)]); + const uint8_t fake_sha256_hash[32] = {0}; + unsigned sig_len; + + TimeResults results; + if (!TimeFunction(&results, + [key, &sig, &fake_sha256_hash, &sig_len]() -> bool { + return RSA_sign(NID_sha256, fake_sha256_hash, sizeof(fake_sha256_hash), + sig.get(), &sig_len, key); + })) { + fprintf(stderr, "RSA_sign failed.\n"); + ERR_print_errors_fp(stderr); + return false; + } + results.Print(key_name + " signing"); + + if (!TimeFunction(&results, + [key, &fake_sha256_hash, &sig, sig_len]() -> bool { + return RSA_verify(NID_sha256, fake_sha256_hash, + sizeof(fake_sha256_hash), sig.get(), sig_len, key); + })) { + fprintf(stderr, "RSA_verify failed.\n"); + ERR_print_errors_fp(stderr); + return false; + } + results.Print(key_name + " verify"); + + return true; +} + +static uint8_t *align(uint8_t *in, unsigned alignment) { + return reinterpret_cast( + (reinterpret_cast(in) + alignment) & + ~static_cast(alignment - 1)); +} + +static bool SpeedAEADChunk(const EVP_AEAD *aead, const std::string &name, + size_t chunk_len, size_t ad_len) { + static const unsigned kAlignment = 16; + + EVP_AEAD_CTX ctx; + const size_t key_len = EVP_AEAD_key_length(aead); + const size_t nonce_len = EVP_AEAD_nonce_length(aead); + const size_t overhead_len = EVP_AEAD_max_overhead(aead); + + std::unique_ptr key(new uint8_t[key_len]); + memset(key.get(), 0, key_len); + std::unique_ptr nonce(new uint8_t[nonce_len]); + memset(nonce.get(), 0, nonce_len); + std::unique_ptr in_storage(new uint8_t[chunk_len + kAlignment]); + std::unique_ptr out_storage(new uint8_t[chunk_len + overhead_len + kAlignment]); + std::unique_ptr ad(new uint8_t[ad_len]); + memset(ad.get(), 0, ad_len); + + uint8_t *const in = align(in_storage.get(), kAlignment); + memset(in, 0, chunk_len); + uint8_t *const out = align(out_storage.get(), kAlignment); + memset(out, 0, chunk_len + overhead_len); + + if (!EVP_AEAD_CTX_init_with_direction(&ctx, aead, key.get(), key_len, + EVP_AEAD_DEFAULT_TAG_LENGTH, + evp_aead_seal)) { + fprintf(stderr, "Failed to create EVP_AEAD_CTX.\n"); + ERR_print_errors_fp(stderr); + return false; + } + + TimeResults results; + if (!TimeFunction(&results, [chunk_len, overhead_len, nonce_len, ad_len, in, + out, &ctx, &nonce, &ad]() -> bool { + size_t out_len; + + return EVP_AEAD_CTX_seal( + &ctx, out, &out_len, chunk_len + overhead_len, nonce.get(), + nonce_len, in, chunk_len, ad.get(), ad_len); + })) { + fprintf(stderr, "EVP_AEAD_CTX_seal failed.\n"); + ERR_print_errors_fp(stderr); + return false; + } + + results.PrintWithBytes(name + " seal", chunk_len); + + EVP_AEAD_CTX_cleanup(&ctx); + + return true; +} + +static bool SpeedAEAD(const EVP_AEAD *aead, const std::string &name, + size_t ad_len, const std::string &selected) { + if (!selected.empty() && name.find(selected) == std::string::npos) { + return true; + } + + return SpeedAEADChunk(aead, name + " (16 bytes)", 16, ad_len) && + SpeedAEADChunk(aead, name + " (1350 bytes)", 1350, ad_len) && + SpeedAEADChunk(aead, name + " (8192 bytes)", 8192, ad_len); +} + +static bool SpeedHashChunk(const EVP_MD *md, const std::string &name, + size_t chunk_len) { + EVP_MD_CTX *ctx = EVP_MD_CTX_create(); + uint8_t scratch[8192]; + + if (chunk_len > sizeof(scratch)) { + return false; + } + + TimeResults results; + if (!TimeFunction(&results, [ctx, md, chunk_len, &scratch]() -> bool { + uint8_t digest[EVP_MAX_MD_SIZE]; + unsigned int md_len; + + return EVP_DigestInit_ex(ctx, md, NULL /* ENGINE */) && + EVP_DigestUpdate(ctx, scratch, chunk_len) && + EVP_DigestFinal_ex(ctx, digest, &md_len); + })) { + fprintf(stderr, "EVP_DigestInit_ex failed.\n"); + ERR_print_errors_fp(stderr); + return false; + } + + results.PrintWithBytes(name, chunk_len); + + EVP_MD_CTX_destroy(ctx); + + return true; +} +static bool SpeedHash(const EVP_MD *md, const std::string &name, + const std::string &selected) { + if (!selected.empty() && name.find(selected) == std::string::npos) { + return true; + } + + return SpeedHashChunk(md, name + " (16 bytes)", 16) && + SpeedHashChunk(md, name + " (256 bytes)", 256) && + SpeedHashChunk(md, name + " (8192 bytes)", 8192); +} + +static bool SpeedRandomChunk(const std::string name, size_t chunk_len) { + uint8_t scratch[8192]; + + if (chunk_len > sizeof(scratch)) { + return false; + } + + TimeResults results; + if (!TimeFunction(&results, [chunk_len, &scratch]() -> bool { + RAND_bytes(scratch, chunk_len); + return true; + })) { + return false; + } + + results.PrintWithBytes(name, chunk_len); + return true; +} + +static bool SpeedRandom(const std::string &selected) { + if (!selected.empty() && selected != "RNG") { + return true; + } + + return SpeedRandomChunk("RNG (16 bytes)", 16) && + SpeedRandomChunk("RNG (256 bytes)", 256) && + SpeedRandomChunk("RNG (8192 bytes)", 8192); +} + +static bool SpeedECDHCurve(const std::string &name, int nid, + const std::string &selected) { + if (!selected.empty() && name.find(selected) == std::string::npos) { + return true; + } + + TimeResults results; + if (!TimeFunction(&results, [nid]() -> bool { + ScopedEC_KEY key(EC_KEY_new_by_curve_name(nid)); + if (!key || + !EC_KEY_generate_key(key.get())) { + return false; + } + const EC_GROUP *const group = EC_KEY_get0_group(key.get()); + ScopedEC_POINT point(EC_POINT_new(group)); + ScopedBN_CTX ctx(BN_CTX_new()); + + ScopedBIGNUM x(BN_new()); + ScopedBIGNUM y(BN_new()); + + if (!point || !ctx || !x || !y || + !EC_POINT_mul(group, point.get(), NULL, + EC_KEY_get0_public_key(key.get()), + EC_KEY_get0_private_key(key.get()), ctx.get()) || + !EC_POINT_get_affine_coordinates_GFp(group, point.get(), x.get(), + y.get(), ctx.get())) { + return false; + } + + return true; + })) { + return false; + } + + results.Print(name); + return true; +} + +static bool SpeedECDSACurve(const std::string &name, int nid, + const std::string &selected) { + if (!selected.empty() && name.find(selected) == std::string::npos) { + return true; + } + + ScopedEC_KEY key(EC_KEY_new_by_curve_name(nid)); + if (!key || + !EC_KEY_generate_key(key.get())) { + return false; + } + + uint8_t signature[256]; + if (ECDSA_size(key.get()) > sizeof(signature)) { + return false; + } + uint8_t digest[20]; + memset(digest, 42, sizeof(digest)); + unsigned sig_len; + + TimeResults results; + if (!TimeFunction(&results, [&key, &signature, &digest, &sig_len]() -> bool { + return ECDSA_sign(0, digest, sizeof(digest), signature, &sig_len, + key.get()) == 1; + })) { + return false; + } + + results.Print(name + " signing"); + + if (!TimeFunction(&results, [&key, &signature, &digest, sig_len]() -> bool { + return ECDSA_verify(0, digest, sizeof(digest), signature, sig_len, + key.get()) == 1; + })) { + return false; + } + + results.Print(name + " verify"); + + return true; +} + +static bool SpeedECDH(const std::string &selected) { + return SpeedECDHCurve("ECDH P-224", NID_secp224r1, selected) && + SpeedECDHCurve("ECDH P-256", NID_X9_62_prime256v1, selected) && + SpeedECDHCurve("ECDH P-384", NID_secp384r1, selected) && + SpeedECDHCurve("ECDH P-521", NID_secp521r1, selected); +} + +static bool SpeedECDSA(const std::string &selected) { + return SpeedECDSACurve("ECDSA P-224", NID_secp224r1, selected) && + SpeedECDSACurve("ECDSA P-256", NID_X9_62_prime256v1, selected) && + SpeedECDSACurve("ECDSA P-384", NID_secp384r1, selected) && + SpeedECDSACurve("ECDSA P-521", NID_secp521r1, selected); +} + +static bool Speed25519(const std::string &selected) { + if (!selected.empty() && selected.find("25519") == std::string::npos) { + return true; + } + + TimeResults results; + + uint8_t public_key[32], private_key[64]; + + if (!TimeFunction(&results, [&public_key, &private_key]() -> bool { + ED25519_keypair(public_key, private_key); + return true; + })) { + return false; + } + + results.Print("Ed25519 key generation"); + + static const uint8_t kMessage[] = {0, 1, 2, 3, 4, 5}; + uint8_t signature[64]; + + if (!TimeFunction(&results, [&private_key, &signature]() -> bool { + return ED25519_sign(signature, kMessage, sizeof(kMessage), + private_key) == 1; + })) { + return false; + } + + results.Print("Ed25519 signing"); + + if (!TimeFunction(&results, [&public_key, &signature]() -> bool { + return ED25519_verify(kMessage, sizeof(kMessage), signature, + public_key) == 1; + })) { + fprintf(stderr, "Ed25519 verify failed.\n"); + return false; + } + + results.Print("Ed25519 verify"); + + if (!TimeFunction(&results, []() -> bool { + uint8_t out[32], in[32]; + memset(in, 0, sizeof(in)); + X25519_public_from_private(out, in); + return true; + })) { + fprintf(stderr, "Curve25519 base-point multiplication failed.\n"); + return false; + } + + results.Print("Curve25519 base-point multiplication"); + + if (!TimeFunction(&results, []() -> bool { + uint8_t out[32], in1[32], in2[32]; + memset(in1, 0, sizeof(in1)); + memset(in2, 0, sizeof(in2)); + in1[0] = 1; + in2[0] = 9; + return X25519(out, in1, in2) == 1; + })) { + fprintf(stderr, "Curve25519 arbitrary point multiplication failed.\n"); + return false; + } + + results.Print("Curve25519 arbitrary point multiplication"); + + return true; +} + +static bool SpeedSPAKE2(const std::string &selected) { + if (!selected.empty() && selected.find("SPAKE2") == std::string::npos) { + return true; + } + + TimeResults results; + + static const uint8_t kAliceName[] = {'A'}; + static const uint8_t kBobName[] = {'B'}; + static const uint8_t kPassword[] = "password"; + ScopedSPAKE2_CTX alice(SPAKE2_CTX_new(spake2_role_alice, kAliceName, + sizeof(kAliceName), kBobName, + sizeof(kBobName))); + uint8_t alice_msg[SPAKE2_MAX_MSG_SIZE]; + size_t alice_msg_len; + + if (!SPAKE2_generate_msg(alice.get(), alice_msg, &alice_msg_len, + sizeof(alice_msg), + kPassword, sizeof(kPassword))) { + fprintf(stderr, "SPAKE2_generate_msg failed.\n"); + return false; + } + + if (!TimeFunction(&results, [&alice_msg, alice_msg_len]() -> bool { + ScopedSPAKE2_CTX bob(SPAKE2_CTX_new(spake2_role_bob, kBobName, + sizeof(kBobName), kAliceName, + sizeof(kAliceName))); + uint8_t bob_msg[SPAKE2_MAX_MSG_SIZE], bob_key[64]; + size_t bob_msg_len, bob_key_len; + if (!SPAKE2_generate_msg(bob.get(), bob_msg, &bob_msg_len, + sizeof(bob_msg), kPassword, + sizeof(kPassword)) || + !SPAKE2_process_msg(bob.get(), bob_key, &bob_key_len, + sizeof(bob_key), alice_msg, alice_msg_len)) { + return false; + } + + return true; + })) { + fprintf(stderr, "SPAKE2 failed.\n"); + } + + results.Print("SPAKE2 over Ed25519"); + + return true; +} + +static bool SpeedNewHope(const std::string &selected) { + if (!selected.empty() && selected.find("newhope") == std::string::npos) { + return true; + } + + TimeResults results; + NEWHOPE_POLY *sk = NEWHOPE_POLY_new(); + uint8_t acceptmsg[NEWHOPE_ACCEPTMSG_LENGTH]; + RAND_bytes(acceptmsg, sizeof(acceptmsg)); + + if (!TimeFunction(&results, [sk, &acceptmsg]() -> bool { + uint8_t key[SHA256_DIGEST_LENGTH]; + uint8_t offermsg[NEWHOPE_OFFERMSG_LENGTH]; + NEWHOPE_offer(offermsg, sk); + if (!NEWHOPE_finish(key, sk, acceptmsg, NEWHOPE_ACCEPTMSG_LENGTH)) { + return false; + } + return true; + })) { + fprintf(stderr, "failed to exchange key.\n"); + return false; + } + + NEWHOPE_POLY_free(sk); + results.Print("newhope key exchange"); + return true; +} + +bool Speed(const std::vector &args) { + std::string selected; + if (args.size() > 1) { + fprintf(stderr, "Usage: bssl speed [speed test selector, i.e. 'RNG']\n"); + return false; + } + if (args.size() > 0) { + selected = args[0]; + } + + RSA *key = RSA_private_key_from_bytes(kDERRSAPrivate2048, + kDERRSAPrivate2048Len); + if (key == NULL) { + fprintf(stderr, "Failed to parse RSA key.\n"); + ERR_print_errors_fp(stderr); + return false; + } + + if (!SpeedRSA("RSA 2048", key, selected)) { + return false; + } + + RSA_free(key); + key = RSA_private_key_from_bytes(kDERRSAPrivate3Prime2048, + kDERRSAPrivate3Prime2048Len); + if (key == NULL) { + fprintf(stderr, "Failed to parse RSA key.\n"); + ERR_print_errors_fp(stderr); + return false; + } + + if (!SpeedRSA("RSA 2048 (3 prime, e=3)", key, selected)) { + return false; + } + + RSA_free(key); + key = RSA_private_key_from_bytes(kDERRSAPrivate4096, + kDERRSAPrivate4096Len); + if (key == NULL) { + fprintf(stderr, "Failed to parse 4096-bit RSA key.\n"); + ERR_print_errors_fp(stderr); + return 1; + } + + if (!SpeedRSA("RSA 4096", key, selected)) { + return false; + } + + RSA_free(key); + + // kTLSADLen is the number of bytes of additional data that TLS passes to + // AEADs. + static const size_t kTLSADLen = 13; + // kLegacyADLen is the number of bytes that TLS passes to the "legacy" AEADs. + // These are AEADs that weren't originally defined as AEADs, but which we use + // via the AEAD interface. In order for that to work, they have some TLS + // knowledge in them and construct a couple of the AD bytes internally. + static const size_t kLegacyADLen = kTLSADLen - 2; + + if (!SpeedAEAD(EVP_aead_aes_128_gcm(), "AES-128-GCM", kTLSADLen, selected) || + !SpeedAEAD(EVP_aead_aes_256_gcm(), "AES-256-GCM", kTLSADLen, selected) || + !SpeedAEAD(EVP_aead_chacha20_poly1305(), "ChaCha20-Poly1305", kTLSADLen, + selected) || + !SpeedAEAD(EVP_aead_chacha20_poly1305_old(), "ChaCha20-Poly1305-Old", + kTLSADLen, selected) || + !SpeedAEAD(EVP_aead_rc4_md5_tls(), "RC4-MD5", kLegacyADLen, selected) || + !SpeedAEAD(EVP_aead_rc4_sha1_tls(), "RC4-SHA1", kLegacyADLen, selected) || + !SpeedAEAD(EVP_aead_des_ede3_cbc_sha1_tls(), "DES-EDE3-CBC-SHA1", + kLegacyADLen, selected) || + !SpeedAEAD(EVP_aead_aes_128_cbc_sha1_tls(), "AES-128-CBC-SHA1", + kLegacyADLen, selected) || + !SpeedAEAD(EVP_aead_aes_256_cbc_sha1_tls(), "AES-256-CBC-SHA1", + kLegacyADLen, selected) || + !SpeedHash(EVP_sha1(), "SHA-1", selected) || + !SpeedHash(EVP_sha256(), "SHA-256", selected) || + !SpeedHash(EVP_sha512(), "SHA-512", selected) || + !SpeedRandom(selected) || + !SpeedECDH(selected) || + !SpeedECDSA(selected) || + !Speed25519(selected) || + !SpeedSPAKE2(selected) || + !SpeedNewHope(selected)) { + return false; + } + + return true; +} diff --git a/external/boringssl/tool/tool.cc b/external/boringssl/tool/tool.cc new file mode 100644 index 0000000000..34851b4711 --- /dev/null +++ b/external/boringssl/tool/tool.cc @@ -0,0 +1,126 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include + +#include +#include +#include + +#if defined(OPENSSL_WINDOWS) +#include +#include +#else +#include +#endif + +#include "internal.h" + + +typedef bool (*tool_func_t)(const std::vector &args); + +struct Tool { + const char *name; + tool_func_t func; +}; + +static const Tool kTools[] = { + { "ciphers", Ciphers }, + { "client", Client }, + { "generate-ed25519", GenerateEd25519Key }, + { "genrsa", GenerateRSAKey }, + { "md5sum", MD5Sum }, + { "pkcs12", DoPKCS12 }, + { "rand", Rand }, + { "s_client", Client }, + { "s_server", Server }, + { "server", Server }, + { "sha1sum", SHA1Sum }, + { "sha224sum", SHA224Sum }, + { "sha256sum", SHA256Sum }, + { "sha384sum", SHA384Sum }, + { "sha512sum", SHA512Sum }, + { "speed", Speed }, + { "", nullptr }, +}; + +static void usage(const char *name) { + printf("Usage: %s COMMAND\n", name); + printf("\n"); + printf("Available commands:\n"); + + for (size_t i = 0;; i++) { + const Tool &tool = kTools[i]; + if (tool.func == nullptr) { + break; + } + printf(" %s\n", tool.name); + } +} + +static tool_func_t FindTool(const std::string &name) { + for (size_t i = 0;; i++) { + const Tool &tool = kTools[i]; + if (tool.func == nullptr || name == tool.name) { + return tool.func; + } + } +} + +int main(int argc, char **argv) { +#if defined(OPENSSL_WINDOWS) + // Read and write in binary mode. This makes bssl on Windows consistent with + // bssl on other platforms, and also makes it consistent with MSYS's commands + // like diff(1) and md5sum(1). This is especially important for the digest + // commands. + if (_setmode(_fileno(stdin), _O_BINARY) == -1) { + perror("_setmode(_fileno(stdin), O_BINARY)"); + return 1; + } + if (_setmode(_fileno(stdout), _O_BINARY) == -1) { + perror("_setmode(_fileno(stdout), O_BINARY)"); + return 1; + } + if (_setmode(_fileno(stderr), _O_BINARY) == -1) { + perror("_setmode(_fileno(stderr), O_BINARY)"); + return 1; + } +#endif + + CRYPTO_library_init(); + + int starting_arg = 1; + tool_func_t tool = nullptr; +#if !defined(OPENSSL_WINDOWS) + tool = FindTool(basename(argv[0])); +#endif + if (tool == nullptr) { + starting_arg++; + if (argc > 1) { + tool = FindTool(argv[1]); + } + } + if (tool == nullptr) { + usage(argv[0]); + return 1; + } + + std::vector args; + for (int i = starting_arg; i < argc; i++) { + args.push_back(argv[i]); + } + + return !tool(args); +} diff --git a/external/boringssl/tool/transport_common.cc b/external/boringssl/tool/transport_common.cc new file mode 100644 index 0000000000..01fcde4ec8 --- /dev/null +++ b/external/boringssl/tool/transport_common.cc @@ -0,0 +1,333 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include +#include + +#include +#include +#include +#include +#include + +#if !defined(OPENSSL_WINDOWS) +#include +#include +#include +#include +#include +#include +#include +#else +#include +OPENSSL_MSVC_PRAGMA(warning(push, 3)) +#include +#include +OPENSSL_MSVC_PRAGMA(warning(pop)) + +typedef int ssize_t; +#pragma comment(lib, "Ws2_32.lib") +#endif + +#include +#include +#include + +#include "internal.h" +#include "transport_common.h" + + +#if !defined(OPENSSL_WINDOWS) +static int closesocket(int sock) { + return close(sock); +} +#endif + +bool InitSocketLibrary() { +#if defined(OPENSSL_WINDOWS) + WSADATA wsaData; + int err = WSAStartup(MAKEWORD(2, 2), &wsaData); + if (err != 0) { + fprintf(stderr, "WSAStartup failed with error %d\n", err); + return false; + } +#endif + return true; +} + +// Connect sets |*out_sock| to be a socket connected to the destination given +// in |hostname_and_port|, which should be of the form "www.example.com:123". +// It returns true on success and false otherwise. +bool Connect(int *out_sock, const std::string &hostname_and_port) { + const size_t colon_offset = hostname_and_port.find_last_of(':'); + std::string hostname, port; + + if (colon_offset == std::string::npos) { + hostname = hostname_and_port; + port = "443"; + } else { + hostname = hostname_and_port.substr(0, colon_offset); + port = hostname_and_port.substr(colon_offset + 1); + } + + struct addrinfo hint, *result; + memset(&hint, 0, sizeof(hint)); + hint.ai_family = AF_UNSPEC; + hint.ai_socktype = SOCK_STREAM; + + int ret = getaddrinfo(hostname.c_str(), port.c_str(), &hint, &result); + if (ret != 0) { + fprintf(stderr, "getaddrinfo returned: %s\n", gai_strerror(ret)); + return false; + } + + bool ok = false; + char buf[256]; + + *out_sock = + socket(result->ai_family, result->ai_socktype, result->ai_protocol); + if (*out_sock < 0) { + perror("socket"); + goto out; + } + + switch (result->ai_family) { + case AF_INET: { + struct sockaddr_in *sin = + reinterpret_cast(result->ai_addr); + fprintf(stderr, "Connecting to %s:%d\n", + inet_ntop(result->ai_family, &sin->sin_addr, buf, sizeof(buf)), + ntohs(sin->sin_port)); + break; + } + case AF_INET6: { + struct sockaddr_in6 *sin6 = + reinterpret_cast(result->ai_addr); + fprintf(stderr, "Connecting to [%s]:%d\n", + inet_ntop(result->ai_family, &sin6->sin6_addr, buf, sizeof(buf)), + ntohs(sin6->sin6_port)); + break; + } + } + + if (connect(*out_sock, result->ai_addr, result->ai_addrlen) != 0) { + perror("connect"); + goto out; + } + ok = true; + +out: + freeaddrinfo(result); + return ok; +} + +bool Accept(int *out_sock, const std::string &port) { + struct sockaddr_in6 addr, cli_addr; + socklen_t cli_addr_len = sizeof(cli_addr); + memset(&addr, 0, sizeof(addr)); + + addr.sin6_family = AF_INET6; + addr.sin6_addr = in6addr_any; + addr.sin6_port = htons(atoi(port.c_str())); + + bool ok = false; + int server_sock = -1; + + server_sock = + socket(addr.sin6_family, SOCK_STREAM, 0); + if (server_sock < 0) { + perror("socket"); + goto out; + } + + if (bind(server_sock, (struct sockaddr*)&addr, sizeof(addr)) != 0) { + perror("connect"); + goto out; + } + listen(server_sock, 1); + *out_sock = accept(server_sock, (struct sockaddr*)&cli_addr, &cli_addr_len); + + ok = true; + +out: + closesocket(server_sock); + return ok; +} + +void PrintConnectionInfo(const SSL *ssl) { + const SSL_CIPHER *cipher = SSL_get_current_cipher(ssl); + + fprintf(stderr, " Version: %s\n", SSL_get_version(ssl)); + fprintf(stderr, " Resumed session: %s\n", + SSL_session_reused(ssl) ? "yes" : "no"); + fprintf(stderr, " Cipher: %s\n", SSL_CIPHER_get_name(cipher)); + if (SSL_CIPHER_is_ECDHE(cipher)) { + fprintf(stderr, " ECDHE curve: %s\n", + SSL_get_curve_name( + SSL_SESSION_get_key_exchange_info(SSL_get_session(ssl)))); + } + fprintf(stderr, " Secure renegotiation: %s\n", + SSL_get_secure_renegotiation_support(ssl) ? "yes" : "no"); + fprintf(stderr, " Extended master secret: %s\n", + SSL_get_extms_support(ssl) ? "yes" : "no"); + + const uint8_t *next_proto; + unsigned next_proto_len; + SSL_get0_next_proto_negotiated(ssl, &next_proto, &next_proto_len); + fprintf(stderr, " Next protocol negotiated: %.*s\n", next_proto_len, + next_proto); + + const uint8_t *alpn; + unsigned alpn_len; + SSL_get0_alpn_selected(ssl, &alpn, &alpn_len); + fprintf(stderr, " ALPN protocol: %.*s\n", alpn_len, alpn); + + // Print the server cert subject and issuer names. + X509 *peer = SSL_get_peer_certificate(ssl); + if (peer != NULL) { + fprintf(stderr, " Cert subject: "); + X509_NAME_print_ex_fp(stderr, X509_get_subject_name(peer), 0, + XN_FLAG_ONELINE); + fprintf(stderr, "\n Cert issuer: "); + X509_NAME_print_ex_fp(stderr, X509_get_issuer_name(peer), 0, + XN_FLAG_ONELINE); + fprintf(stderr, "\n"); + X509_free(peer); + } +} + +bool SocketSetNonBlocking(int sock, bool is_non_blocking) { + bool ok; + +#if defined(OPENSSL_WINDOWS) + u_long arg = is_non_blocking; + ok = 0 == ioctlsocket(sock, FIONBIO, &arg); +#else + int flags = fcntl(sock, F_GETFL, 0); + if (flags < 0) { + return false; + } + if (is_non_blocking) { + flags |= O_NONBLOCK; + } else { + flags &= ~O_NONBLOCK; + } + ok = 0 == fcntl(sock, F_SETFL, flags); +#endif + if (!ok) { + fprintf(stderr, "Failed to set socket non-blocking.\n"); + } + return ok; +} + +// PrintErrorCallback is a callback function from OpenSSL's +// |ERR_print_errors_cb| that writes errors to a given |FILE*|. +int PrintErrorCallback(const char *str, size_t len, void *ctx) { + fwrite(str, len, 1, reinterpret_cast(ctx)); + return 1; +} + +bool TransferData(SSL *ssl, int sock) { + bool stdin_open = true; + + fd_set read_fds; + FD_ZERO(&read_fds); + + if (!SocketSetNonBlocking(sock, true)) { + return false; + } + + for (;;) { + if (stdin_open) { + FD_SET(0, &read_fds); + } + FD_SET(sock, &read_fds); + + int ret = select(sock + 1, &read_fds, NULL, NULL, NULL); + if (ret <= 0) { + perror("select"); + return false; + } + + if (FD_ISSET(0, &read_fds)) { + uint8_t buffer[512]; + ssize_t n; + + do { + n = BORINGSSL_READ(0, buffer, sizeof(buffer)); + } while (n == -1 && errno == EINTR); + + if (n == 0) { + FD_CLR(0, &read_fds); + stdin_open = false; +#if !defined(OPENSSL_WINDOWS) + shutdown(sock, SHUT_WR); +#else + shutdown(sock, SD_SEND); +#endif + continue; + } else if (n < 0) { + perror("read from stdin"); + return false; + } + + if (!SocketSetNonBlocking(sock, false)) { + return false; + } + int ssl_ret = SSL_write(ssl, buffer, n); + if (!SocketSetNonBlocking(sock, true)) { + return false; + } + + if (ssl_ret <= 0) { + int ssl_err = SSL_get_error(ssl, ssl_ret); + fprintf(stderr, "Error while writing: %d\n", ssl_err); + ERR_print_errors_cb(PrintErrorCallback, stderr); + return false; + } else if (ssl_ret != n) { + fprintf(stderr, "Short write from SSL_write.\n"); + return false; + } + } + + if (FD_ISSET(sock, &read_fds)) { + uint8_t buffer[512]; + int ssl_ret = SSL_read(ssl, buffer, sizeof(buffer)); + + if (ssl_ret < 0) { + int ssl_err = SSL_get_error(ssl, ssl_ret); + if (ssl_err == SSL_ERROR_WANT_READ) { + continue; + } + fprintf(stderr, "Error while reading: %d\n", ssl_err); + ERR_print_errors_cb(PrintErrorCallback, stderr); + return false; + } else if (ssl_ret == 0) { + return true; + } + + ssize_t n; + do { + n = BORINGSSL_WRITE(1, buffer, ssl_ret); + } while (n == -1 && errno == EINTR); + + if (n != ssl_ret) { + fprintf(stderr, "Short write to stderr.\n"); + return false; + } + } + } +} diff --git a/external/boringssl/tool/transport_common.h b/external/boringssl/tool/transport_common.h new file mode 100644 index 0000000000..b701015841 --- /dev/null +++ b/external/boringssl/tool/transport_common.h @@ -0,0 +1,43 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_TOOL_TRANSPORT_COMMON_H +#define OPENSSL_HEADER_TOOL_TRANSPORT_COMMON_H + +#include +#include + +// InitSocketLibrary calls the Windows socket init functions, if needed. +bool InitSocketLibrary(); + +// Connect sets |*out_sock| to be a socket connected to the destination given +// in |hostname_and_port|, which should be of the form "www.example.com:123". +// It returns true on success and false otherwise. +bool Connect(int *out_sock, const std::string &hostname_and_port); + +// Accept sets |*out_sock| to be a socket connected to the port given +// in |port|, which should be of the form "123". +// It returns true on success and false otherwise. +bool Accept(int *out_sock, const std::string &port); + +void PrintConnectionInfo(const SSL *ssl); + +bool SocketSetNonBlocking(int sock, bool is_non_blocking); + +int PrintErrorCallback(const char *str, size_t len, void *ctx); + +bool TransferData(SSL *ssl, int sock); + + +#endif /* !OPENSSL_HEADER_TOOL_TRANSPORT_COMMON_H */ diff --git a/external/boringssl/util/32-bit-toolchain.cmake b/external/boringssl/util/32-bit-toolchain.cmake new file mode 100644 index 0000000000..f3a10b7083 --- /dev/null +++ b/external/boringssl/util/32-bit-toolchain.cmake @@ -0,0 +1,7 @@ +set(CMAKE_SYSTEM_NAME Linux) +set(CMAKE_SYSTEM_VERSION 1) +set(CMAKE_SYSTEM_PROCESSOR "x86") + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32 -msse2" CACHE STRING "c++ flags") +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32 -msse2" CACHE STRING "c flags") +set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -m32 -msse2" CACHE STRING "asm flags") diff --git a/external/boringssl/util/all_tests.go b/external/boringssl/util/all_tests.go new file mode 100644 index 0000000000..d361651ec1 --- /dev/null +++ b/external/boringssl/util/all_tests.go @@ -0,0 +1,319 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +package main + +import ( + "bytes" + "encoding/json" + "flag" + "fmt" + "os" + "os/exec" + "path" + "strconv" + "strings" + "sync" + "syscall" + "time" +) + +// TODO(davidben): Link tests with the malloc shim and port -malloc-test to this runner. + +var ( + useValgrind = flag.Bool("valgrind", false, "If true, run code under valgrind") + useCallgrind = flag.Bool("callgrind", false, "If true, run code under valgrind to generate callgrind traces.") + useGDB = flag.Bool("gdb", false, "If true, run BoringSSL code under gdb") + buildDir = flag.String("build-dir", "build", "The build directory to run the tests from.") + numWorkers = flag.Int("num-workers", 1, "Runs the given number of workers when testing.") + jsonOutput = flag.String("json-output", "", "The file to output JSON results to.") + mallocTest = flag.Int64("malloc-test", -1, "If non-negative, run each test with each malloc in turn failing from the given number onwards.") + mallocTestDebug = flag.Bool("malloc-test-debug", false, "If true, ask each test to abort rather than fail a malloc. This can be used with a specific value for --malloc-test to identity the malloc failing that is causing problems.") +) + +type test []string + +type result struct { + Test test + Passed bool + Error error +} + +// testOutput is a representation of Chromium's JSON test result format. See +// https://www.chromium.org/developers/the-json-test-results-format +type testOutput struct { + Version int `json:"version"` + Interrupted bool `json:"interrupted"` + PathDelimiter string `json:"path_delimiter"` + SecondsSinceEpoch float64 `json:"seconds_since_epoch"` + NumFailuresByType map[string]int `json:"num_failures_by_type"` + Tests map[string]testResult `json:"tests"` +} + +type testResult struct { + Actual string `json:"actual"` + Expected string `json:"expected"` + IsUnexpected bool `json:"is_unexpected"` +} + +func newTestOutput() *testOutput { + return &testOutput{ + Version: 3, + PathDelimiter: ".", + SecondsSinceEpoch: float64(time.Now().UnixNano()) / float64(time.Second/time.Nanosecond), + NumFailuresByType: make(map[string]int), + Tests: make(map[string]testResult), + } +} + +func (t *testOutput) addResult(name, result string) { + if _, found := t.Tests[name]; found { + panic(name) + } + t.Tests[name] = testResult{ + Actual: result, + Expected: "PASS", + IsUnexpected: result != "PASS", + } + t.NumFailuresByType[result]++ +} + +func (t *testOutput) writeTo(name string) error { + file, err := os.Create(name) + if err != nil { + return err + } + defer file.Close() + out, err := json.MarshalIndent(t, "", " ") + if err != nil { + return err + } + _, err = file.Write(out) + return err +} + +func valgrindOf(dbAttach bool, path string, args ...string) *exec.Cmd { + valgrindArgs := []string{"--error-exitcode=99", "--track-origins=yes", "--leak-check=full"} + if dbAttach { + valgrindArgs = append(valgrindArgs, "--db-attach=yes", "--db-command=xterm -e gdb -nw %f %p") + } + valgrindArgs = append(valgrindArgs, path) + valgrindArgs = append(valgrindArgs, args...) + + return exec.Command("valgrind", valgrindArgs...) +} + +func callgrindOf(path string, args ...string) *exec.Cmd { + valgrindArgs := []string{"-q", "--tool=callgrind", "--dump-instr=yes", "--collect-jumps=yes", "--callgrind-out-file=" + *buildDir + "/callgrind/callgrind.out.%p"} + valgrindArgs = append(valgrindArgs, path) + valgrindArgs = append(valgrindArgs, args...) + + return exec.Command("valgrind", valgrindArgs...) +} + +func gdbOf(path string, args ...string) *exec.Cmd { + xtermArgs := []string{"-e", "gdb", "--args"} + xtermArgs = append(xtermArgs, path) + xtermArgs = append(xtermArgs, args...) + + return exec.Command("xterm", xtermArgs...) +} + +type moreMallocsError struct{} + +func (moreMallocsError) Error() string { + return "child process did not exhaust all allocation calls" +} + +var errMoreMallocs = moreMallocsError{} + +func runTestOnce(test test, mallocNumToFail int64) (passed bool, err error) { + prog := path.Join(*buildDir, test[0]) + args := test[1:] + var cmd *exec.Cmd + if *useValgrind { + cmd = valgrindOf(false, prog, args...) + } else if *useCallgrind { + cmd = callgrindOf(prog, args...) + } else if *useGDB { + cmd = gdbOf(prog, args...) + } else { + cmd = exec.Command(prog, args...) + } + var stdoutBuf bytes.Buffer + var stderrBuf bytes.Buffer + cmd.Stdout = &stdoutBuf + cmd.Stderr = &stderrBuf + if mallocNumToFail >= 0 { + cmd.Env = os.Environ() + cmd.Env = append(cmd.Env, "MALLOC_NUMBER_TO_FAIL="+strconv.FormatInt(mallocNumToFail, 10)) + if *mallocTestDebug { + cmd.Env = append(cmd.Env, "MALLOC_ABORT_ON_FAIL=1") + } + cmd.Env = append(cmd.Env, "_MALLOC_CHECK=1") + } + + if err := cmd.Start(); err != nil { + return false, err + } + if err := cmd.Wait(); err != nil { + if exitError, ok := err.(*exec.ExitError); ok { + if exitError.Sys().(syscall.WaitStatus).ExitStatus() == 88 { + return false, errMoreMallocs + } + } + fmt.Print(string(stderrBuf.Bytes())) + return false, err + } + fmt.Print(string(stderrBuf.Bytes())) + + // Account for Windows line-endings. + stdout := bytes.Replace(stdoutBuf.Bytes(), []byte("\r\n"), []byte("\n"), -1) + + if bytes.HasSuffix(stdout, []byte("PASS\n")) && + (len(stdout) == 5 || stdout[len(stdout)-6] == '\n') { + return true, nil + } + return false, nil +} + +func runTest(test test) (bool, error) { + if *mallocTest < 0 { + return runTestOnce(test, -1) + } + + for mallocNumToFail := int64(*mallocTest); ; mallocNumToFail++ { + if passed, err := runTestOnce(test, mallocNumToFail); err != errMoreMallocs { + if err != nil { + err = fmt.Errorf("at malloc %d: %s", mallocNumToFail, err) + } + return passed, err + } + } +} + +// shortTestName returns the short name of a test. Except for evp_test, it +// assumes that any argument which ends in .txt is a path to a data file and not +// relevant to the test's uniqueness. +func shortTestName(test test) string { + var args []string + for _, arg := range test { + if test[0] == "crypto/evp/evp_test" || !strings.HasSuffix(arg, ".txt") { + args = append(args, arg) + } + } + return strings.Join(args, " ") +} + +// setWorkingDirectory walks up directories as needed until the current working +// directory is the top of a BoringSSL checkout. +func setWorkingDirectory() { + for i := 0; i < 64; i++ { + if _, err := os.Stat("BUILDING.md"); err == nil { + return + } + os.Chdir("..") + } + + panic("Couldn't find BUILDING.md in a parent directory!") +} + +func parseTestConfig(filename string) ([]test, error) { + in, err := os.Open(filename) + if err != nil { + return nil, err + } + defer in.Close() + + decoder := json.NewDecoder(in) + var result []test + if err := decoder.Decode(&result); err != nil { + return nil, err + } + return result, nil +} + +func worker(tests <-chan test, results chan<- result, done *sync.WaitGroup) { + defer done.Done() + for test := range tests { + passed, err := runTest(test) + results <- result{test, passed, err} + } +} + +func main() { + flag.Parse() + setWorkingDirectory() + + testCases, err := parseTestConfig("util/all_tests.json") + if err != nil { + fmt.Printf("Failed to parse input: %s\n", err) + os.Exit(1) + } + + var wg sync.WaitGroup + tests := make(chan test, *numWorkers) + results := make(chan result, *numWorkers) + + for i := 0; i < *numWorkers; i++ { + wg.Add(1) + go worker(tests, results, &wg) + } + + go func() { + for _, test := range testCases { + tests <- test + } + close(tests) + + wg.Wait() + close(results) + }() + + testOutput := newTestOutput() + var failed []test + for testResult := range results { + test := testResult.Test + + fmt.Printf("%s\n", strings.Join([]string(test), " ")) + name := shortTestName(test) + if testResult.Error != nil { + fmt.Printf("%s failed to complete: %s\n", test[0], testResult.Error) + failed = append(failed, test) + testOutput.addResult(name, "CRASHED") + } else if !testResult.Passed { + fmt.Printf("%s failed to print PASS on the last line.\n", test[0]) + failed = append(failed, test) + testOutput.addResult(name, "FAIL") + } else { + testOutput.addResult(name, "PASS") + } + } + + if *jsonOutput != "" { + if err := testOutput.writeTo(*jsonOutput); err != nil { + fmt.Fprintf(os.Stderr, "Error: %s\n", err) + } + } + + if len(failed) > 0 { + fmt.Printf("\n%d of %d tests failed:\n", len(failed), len(testCases)) + for _, test := range failed { + fmt.Printf("\t%s\n", strings.Join([]string(test), " ")) + } + os.Exit(1) + } + + fmt.Printf("\nAll tests passed!\n") +} diff --git a/external/boringssl/util/all_tests.json b/external/boringssl/util/all_tests.json new file mode 100644 index 0000000000..48b540e0a8 --- /dev/null +++ b/external/boringssl/util/all_tests.json @@ -0,0 +1,70 @@ +[ + ["crypto/aes/aes_test"], + ["crypto/asn1/asn1_test"], + ["crypto/base64/base64_test"], + ["crypto/bio/bio_test"], + ["crypto/bn/bn_test"], + ["crypto/bytestring/bytestring_test"], + ["crypto/chacha/chacha_test"], + ["crypto/cipher/aead_test", "aes-128-gcm", "crypto/cipher/test/aes_128_gcm_tests.txt"], + ["crypto/cipher/aead_test", "aes-128-key-wrap", "crypto/cipher/test/aes_128_key_wrap_tests.txt"], + ["crypto/cipher/aead_test", "aes-256-gcm", "crypto/cipher/test/aes_256_gcm_tests.txt"], + ["crypto/cipher/aead_test", "aes-256-key-wrap", "crypto/cipher/test/aes_256_key_wrap_tests.txt"], + ["crypto/cipher/aead_test", "chacha20-poly1305", "crypto/cipher/test/chacha20_poly1305_tests.txt"], + ["crypto/cipher/aead_test", "chacha20-poly1305-old", "crypto/cipher/test/chacha20_poly1305_old_tests.txt"], + ["crypto/cipher/aead_test", "rc4-md5-tls", "crypto/cipher/test/rc4_md5_tls_tests.txt"], + ["crypto/cipher/aead_test", "rc4-sha1-tls", "crypto/cipher/test/rc4_sha1_tls_tests.txt"], + ["crypto/cipher/aead_test", "aes-128-cbc-sha1-tls", "crypto/cipher/test/aes_128_cbc_sha1_tls_tests.txt"], + ["crypto/cipher/aead_test", "aes-128-cbc-sha1-tls-implicit-iv", "crypto/cipher/test/aes_128_cbc_sha1_tls_implicit_iv_tests.txt"], + ["crypto/cipher/aead_test", "aes-128-cbc-sha256-tls", "crypto/cipher/test/aes_128_cbc_sha256_tls_tests.txt"], + ["crypto/cipher/aead_test", "aes-256-cbc-sha1-tls", "crypto/cipher/test/aes_256_cbc_sha1_tls_tests.txt"], + ["crypto/cipher/aead_test", "aes-256-cbc-sha1-tls-implicit-iv", "crypto/cipher/test/aes_256_cbc_sha1_tls_implicit_iv_tests.txt"], + ["crypto/cipher/aead_test", "aes-256-cbc-sha256-tls", "crypto/cipher/test/aes_256_cbc_sha256_tls_tests.txt"], + ["crypto/cipher/aead_test", "aes-256-cbc-sha384-tls", "crypto/cipher/test/aes_256_cbc_sha384_tls_tests.txt"], + ["crypto/cipher/aead_test", "des-ede3-cbc-sha1-tls", "crypto/cipher/test/des_ede3_cbc_sha1_tls_tests.txt"], + ["crypto/cipher/aead_test", "des-ede3-cbc-sha1-tls-implicit-iv", "crypto/cipher/test/des_ede3_cbc_sha1_tls_implicit_iv_tests.txt"], + ["crypto/cipher/aead_test", "rc4-md5-ssl3", "crypto/cipher/test/rc4_md5_ssl3_tests.txt"], + ["crypto/cipher/aead_test", "rc4-sha1-ssl3", "crypto/cipher/test/rc4_sha1_ssl3_tests.txt"], + ["crypto/cipher/aead_test", "aes-128-cbc-sha1-ssl3", "crypto/cipher/test/aes_128_cbc_sha1_ssl3_tests.txt"], + ["crypto/cipher/aead_test", "aes-256-cbc-sha1-ssl3", "crypto/cipher/test/aes_256_cbc_sha1_ssl3_tests.txt"], + ["crypto/cipher/aead_test", "des-ede3-cbc-sha1-ssl3", "crypto/cipher/test/des_ede3_cbc_sha1_ssl3_tests.txt"], + ["crypto/cipher/aead_test", "aes-128-ctr-hmac-sha256", "crypto/cipher/test/aes_128_ctr_hmac_sha256.txt"], + ["crypto/cipher/aead_test", "aes-256-ctr-hmac-sha256", "crypto/cipher/test/aes_256_ctr_hmac_sha256.txt"], + ["crypto/cipher/cipher_test", "crypto/cipher/test/cipher_tests.txt"], + ["crypto/cmac/cmac_test"], + ["crypto/constant_time_test"], + ["crypto/curve25519/ed25519_test", "crypto/curve25519/ed25519_tests.txt"], + ["crypto/curve25519/x25519_test"], + ["crypto/curve25519/spake25519_test"], + ["crypto/dh/dh_test"], + ["crypto/digest/digest_test"], + ["crypto/dsa/dsa_test"], + ["crypto/ec/ec_test"], + ["crypto/ec/example_mul"], + ["crypto/ecdsa/ecdsa_test"], + ["crypto/err/err_test"], + ["crypto/evp/evp_extra_test"], + ["crypto/evp/evp_test", "crypto/evp/evp_tests.txt"], + ["crypto/evp/pbkdf_test"], + ["crypto/hkdf/hkdf_test"], + ["crypto/hmac/hmac_test", "crypto/hmac/hmac_tests.txt"], + ["crypto/lhash/lhash_test"], + ["crypto/modes/gcm_test"], + ["crypto/newhope/newhope_test"], + ["crypto/newhope/newhope_statistical_test"], + ["crypto/newhope/newhope_vectors_test", "crypto/newhope/newhope_tests.txt"], + ["crypto/obj/obj_test"], + ["crypto/pkcs8/pkcs12_test"], + ["crypto/pkcs8/pkcs8_test"], + ["crypto/poly1305/poly1305_test", "crypto/poly1305/poly1305_tests.txt"], + ["crypto/refcount_test"], + ["crypto/rsa/rsa_test"], + ["crypto/thread_test"], + ["crypto/x509/pkcs7_test"], + ["crypto/x509/x509_test"], + ["crypto/x509v3/tab_test"], + ["crypto/x509v3/v3name_test"], + ["decrepit/ripemd/ripemd_test"], + ["ssl/pqueue/pqueue_test"], + ["ssl/ssl_test"] +] diff --git a/external/boringssl/util/android-cmake/.gitattributes b/external/boringssl/util/android-cmake/.gitattributes new file mode 100644 index 0000000000..0c82a3ec55 --- /dev/null +++ b/external/boringssl/util/android-cmake/.gitattributes @@ -0,0 +1,4 @@ +.git* text export-ignore + +* text=auto +* whitespace=!indent,tab-in-indent,trail,space diff --git a/external/boringssl/util/android-cmake/.gitignore b/external/boringssl/util/android-cmake/.gitignore new file mode 100644 index 0000000000..16f55fd0d2 --- /dev/null +++ b/external/boringssl/util/android-cmake/.gitignore @@ -0,0 +1,41 @@ +.DS_Store +._* +*.user + +# backup files +*~ +*.orig +*.bak + +# built application files +*.apk +*.ap_ + +# files for the dex VM +*.dex + +# Java class files +*.class + +# generated files +bin/ +gen/ + +# Local configuration file (sdk path, etc) +local.properties + +# Eclipse project files +.classpath +.project +.metadata +.settings/ +.loadpath + +# vim files +.*.sw[a-z] +*.un~ +Session.vim +.netrwhist + +# SublimeText project files +*.sublime-workspace diff --git a/external/boringssl/util/android-cmake/AndroidNdkGdb.cmake b/external/boringssl/util/android-cmake/AndroidNdkGdb.cmake new file mode 100644 index 0000000000..0677dcda91 --- /dev/null +++ b/external/boringssl/util/android-cmake/AndroidNdkGdb.cmake @@ -0,0 +1,96 @@ +# Copyright (c) 2014, Pavel Rojtberg +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from this +# software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +# ------------------------------------------------------------------------------ +# Usage: +# 1. place AndroidNdkGdb.cmake somewhere inside ${CMAKE_MODULE_PATH} +# 2. inside your project add +# +# include(AndroidNdkGdb) +# android_ndk_gdb_enable() +# # for each target +# add_library(MyLibrary ...) +# android_ndk_gdb_debuggable(MyLibrary) + + +# add gdbserver and general gdb configuration to project +# also create a mininal NDK skeleton so ndk-gdb finds the paths +# +# the optional parameter defines the path to the android project. +# uses PROJECT_SOURCE_DIR by default. +macro(android_ndk_gdb_enable) + if(ANDROID) + # create custom target that depends on the real target so it gets executed afterwards + add_custom_target(NDK_GDB ALL) + + if(${ARGC}) + set(ANDROID_PROJECT_DIR ${ARGV0}) + else() + set(ANDROID_PROJECT_DIR ${PROJECT_SOURCE_DIR}) + endif() + + set(NDK_GDB_SOLIB_PATH ${ANDROID_PROJECT_DIR}/obj/local/${ANDROID_NDK_ABI_NAME}/) + file(MAKE_DIRECTORY ${NDK_GDB_SOLIB_PATH}) + + # 1. generate essential Android Makefiles + file(MAKE_DIRECTORY ${ANDROID_PROJECT_DIR}/jni) + if(NOT EXISTS ${ANDROID_PROJECT_DIR}/jni/Android.mk) + file(WRITE ${ANDROID_PROJECT_DIR}/jni/Android.mk "APP_ABI := ${ANDROID_NDK_ABI_NAME}\n") + endif() + if(NOT EXISTS ${ANDROID_PROJECT_DIR}/jni/Application.mk) + file(WRITE ${ANDROID_PROJECT_DIR}/jni/Application.mk "APP_ABI := ${ANDROID_NDK_ABI_NAME}\n") + endif() + + # 2. generate gdb.setup + get_directory_property(PROJECT_INCLUDES DIRECTORY ${PROJECT_SOURCE_DIR} INCLUDE_DIRECTORIES) + string(REGEX REPLACE ";" " " PROJECT_INCLUDES "${PROJECT_INCLUDES}") + file(WRITE ${LIBRARY_OUTPUT_PATH}/gdb.setup "set solib-search-path ${NDK_GDB_SOLIB_PATH}\n") + file(APPEND ${LIBRARY_OUTPUT_PATH}/gdb.setup "directory ${PROJECT_INCLUDES}\n") + + # 3. copy gdbserver executable + file(COPY ${ANDROID_NDK}/prebuilt/android-${ANDROID_ARCH_NAME}/gdbserver/gdbserver DESTINATION ${LIBRARY_OUTPUT_PATH}) + endif() +endmacro() + +# register a target for remote debugging +# copies the debug version to NDK_GDB_SOLIB_PATH then strips symbols of original +macro(android_ndk_gdb_debuggable TARGET_NAME) + if(ANDROID) + get_property(TARGET_LOCATION TARGET ${TARGET_NAME} PROPERTY LOCATION) + + # create custom target that depends on the real target so it gets executed afterwards + add_dependencies(NDK_GDB ${TARGET_NAME}) + + # 4. copy lib to obj + add_custom_command(TARGET NDK_GDB POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${TARGET_LOCATION} ${NDK_GDB_SOLIB_PATH}) + + # 5. strip symbols + add_custom_command(TARGET NDK_GDB POST_BUILD COMMAND ${CMAKE_STRIP} ${TARGET_LOCATION}) + endif() +endmacro() diff --git a/external/boringssl/util/android-cmake/AndroidNdkModules.cmake b/external/boringssl/util/android-cmake/AndroidNdkModules.cmake new file mode 100644 index 0000000000..64f37fdee2 --- /dev/null +++ b/external/boringssl/util/android-cmake/AndroidNdkModules.cmake @@ -0,0 +1,58 @@ +# Copyright (c) 2014, Pavel Rojtberg +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from this +# software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +macro(android_ndk_import_module_cpufeatures) + if(ANDROID) + include_directories(${ANDROID_NDK}/sources/android/cpufeatures) + add_library(cpufeatures ${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c) + target_link_libraries(cpufeatures dl) + endif() +endmacro() + +macro(android_ndk_import_module_native_app_glue) + if(ANDROID) + include_directories(${ANDROID_NDK}/sources/android/native_app_glue) + add_library(native_app_glue ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) + target_link_libraries(native_app_glue log) + endif() +endmacro() + +macro(android_ndk_import_module_ndk_helper) + if(ANDROID) + android_ndk_import_module_cpufeatures() + android_ndk_import_module_native_app_glue() + + include_directories(${ANDROID_NDK}/sources/android/ndk_helper) + file(GLOB _NDK_HELPER_SRCS ${ANDROID_NDK}/sources/android/ndk_helper/*.cpp ${ANDROID_NDK}/sources/android/ndk_helper/gl3stub.c) + add_library(ndk_helper ${_NDK_HELPER_SRCS}) + target_link_libraries(ndk_helper log android EGL GLESv2 cpufeatures native_app_glue) + + unset(_NDK_HELPER_SRCS) + endif() +endmacro() \ No newline at end of file diff --git a/external/boringssl/util/android-cmake/README.md b/external/boringssl/util/android-cmake/README.md new file mode 100644 index 0000000000..ee63021282 --- /dev/null +++ b/external/boringssl/util/android-cmake/README.md @@ -0,0 +1,240 @@ +# android-cmake + +CMake is great, and so is Android. This is a collection of CMake scripts that may be useful to the Android NDK community. It is based on experience from porting OpenCV library to Android: http://opencv.org/platforms/android.html + +Main goal is to share these scripts so that devs that use CMake as their build system may easily compile native code for Android. + +## TL;DR + + cmake -DCMAKE_TOOLCHAIN_FILE=android.toolchain.cmake \ + -DANDROID_NDK= \ + -DCMAKE_BUILD_TYPE=Release \ + -DANDROID_ABI="armeabi-v7a with NEON" \ + + cmake --build . + +One-liner: + + cmake -DCMAKE_TOOLCHAIN_FILE=android.toolchain.cmake -DANDROID_NDK= -DCMAKE_BUILD_TYPE=Release -DANDROID_ABI="armeabi-v7a with NEON" && cmake --build . + +_android-cmake_ will search for your NDK install in the following order: + +1. Value of `ANDROID_NDK` CMake variable; +1. Value of `ANDROID_NDK` environment variable; +1. Search under paths from `ANDROID_NDK_SEARCH_PATHS` CMake variable; +1. Search platform specific locations (home folder, Windows "Program Files", etc). + +So if you have installed the NDK as `~/android-ndk-r10d` then _android-cmake_ will locate it automatically. + +## Getting started + +To build a cmake-based C/C++ project for Android you need: + +* Android NDK (>= r5) http://developer.android.com/tools/sdk/ndk/index.html +* CMake (>= v2.6.3, >= v2.8.9 recommended) http://www.cmake.org/download + +The _android-cmake_ is also capable to build with NDK from AOSP or Linaro Android source tree, but you may be required to manually specify path to `libm` binary to link with. + +## Difference from traditional CMake + +Folowing the _ndk-build_ the _android-cmake_ supports **only two build targets**: + +* `-DCMAKE_BUILD_TYPE=Release` +* `-DCMAKE_BUILD_TYPE=Debug` + +So don't even try other targets that can be found in CMake documentation and don't forget to explicitly specify `Release` or `Debug` because CMake builds without a build configuration by default. + +## Difference from _ndk-build_ + +* Latest GCC available in NDK is used as the default compiler; +* `Release` builds with `-O3` instead of `-Os`; +* `Release` builds without debug info (without `-g`) (because _ndk-build_ always creates a stripped version but cmake delays this for `install/strip` target); +* `-fsigned-char` is added to compiler flags to make `char` signed by default as it is on x86/x86_64; +* GCC's stack protector is not used neither in `Debug` nor `Release` configurations; +* No builds for multiple platforms (e.g. building for both arm and x86 require to run cmake twice with different parameters); +* No file level Neon via `.neon` suffix; + +The following features of _ndk-build_ are not supported by the _android-cmake_ yet: + +* `armeabi-v7a-hard` ABI +* `libc++_static`/`libc++_shared` STL runtime + +## Basic options + +Similarly to the NDK build system _android-cmake_ allows to select between several compiler toolchains and target platforms. Most of the options can be set either as cmake arguments: `-D=` or as environment variables: + +* **ANDROID_NDK** - path to the Android NDK. If not set then _android-cmake_ will search for the most recent version of supported NDK in commonly used locations; +* **ANDROID_ABI** - specifies the target Application Binary Interface (ABI). This option nearly matches to the APP_ABI variable used by ndk-build tool from Android NDK. If not specified then set to `armeabi-v7a`. Possible target names are: + * `armeabi` - ARMv5TE based CPU with software floating point operations; + * **`armeabi-v7a`** - ARMv7 based devices with hardware FPU instructions (VFPv3_D16); + * `armeabi-v7a with NEON` - same as armeabi-v7a, but sets NEON as floating-point unit; + * `armeabi-v7a with VFPV3` - same as armeabi-v7a, but sets VFPv3_D32 as floating-point unit; + * `armeabi-v6 with VFP` - tuned for ARMv6 processors having VFP; + * `x86` - IA-32 instruction set + * `mips` - MIPS32 instruction set + * `arm64-v8a` - ARMv8 AArch64 instruction set - only for NDK r10 and newer + * `x86_64` - Intel64 instruction set (r1) - only for NDK r10 and newer + * `mips64` - MIPS64 instruction set (r6) - only for NDK r10 and newer +* **ANDROID_NATIVE_API_LEVEL** - level of android API to build for. Can be set either to full name (example: `android-8`) or a numeric value (example: `17`). The default API level depends on the target ABI: + * `android-8` for ARM; + * `android-9` for x86 and MIPS; + * `android-21` for 64-bit ABIs. + + Building for `android-L` is possible only when it is explicitly selected. +* **ANDROID_TOOLCHAIN_NAME** - the name of compiler toolchain to be used. This option allows to select between different GCC and Clang versions. The list of possible values depends on the NDK version and will be printed by toolchain file if an invalid value is set. By default _android-cmake_ selects the most recent version of GCC which can build for specified `ANDROID_ABI`. + + Example values are: + * `aarch64-linux-android-4.9` + * `aarch64-linux-android-clang3.5` + * `arm-linux-androideabi-4.8` + * `arm-linux-androideabi-4.9` + * `arm-linux-androideabi-clang3.5` + * `mips64el-linux-android-4.9` + * `mipsel-linux-android-4.8` + * `x86-4.9` + * `x86_64-4.9` + * etc. +* **ANDROID_STL** - the name of C++ runtime to use. The default is `gnustl_static`. + * `none` - do not configure the runtime. + * `system` - use the default minimal system C++ runtime library. + * Implies `-fno-rtti -fno-exceptions`. + * `system_re` - use the default minimal system C++ runtime library. + * Implies `-frtti -fexceptions`. + * `gabi++_static` - use the GAbi++ runtime as a static library. + * Implies `-frtti -fno-exceptions`. + * Available for NDK r7 and newer. + * `gabi++_shared` - use the GAbi++ runtime as a shared library. + * Implies `-frtti -fno-exceptions`. + * Available for NDK r7 and newer. + * `stlport_static` - use the STLport runtime as a static library. + * Implies `-fno-rtti -fno-exceptions` for NDK before r7. + * Implies `-frtti -fno-exceptions` for NDK r7 and newer. + * `stlport_shared` - use the STLport runtime as a shared library. + * Implies `-fno-rtti -fno-exceptions` for NDK before r7. + * Implies `-frtti -fno-exceptions` for NDK r7 and newer. + * **`gnustl_static`** - use the GNU STL as a static library. + * Implies `-frtti -fexceptions`. + * `gnustl_shared` - use the GNU STL as a shared library. + * Implies `-frtti -fno-exceptions`. + * Available for NDK r7b and newer. + * Silently degrades to `gnustl_static` if not available. +* **NDK_CCACHE** - path to `ccache` executable. If not set then initialized from `NDK_CCACHE` environment variable. + +## Advanced _android-cmake_ options + +Normally _android-cmake_ users are not supposed to touch these variables but they might be useful to workaround some build issues: + +* **ANDROID_FORCE_ARM_BUILD** = `OFF` - generate 32-bit ARM instructions instead of Thumb. Applicable only for arm ABIs and is forced to be `ON` for `armeabi-v6 with VFP`; +* **ANDROID_NO_UNDEFINED** = `ON` - show all undefined symbols as linker errors; +* **ANDROID_SO_UNDEFINED** = `OFF` - allow undefined symbols in shared libraries; + * actually it is turned `ON` by default for NDK older than `r7` +* **ANDROID_STL_FORCE_FEATURES** = `ON` - automatically configure rtti and exceptions support based on C++ runtime; +* **ANDROID_NDK_LAYOUT** = `RELEASE` - inner layout of Android NDK, should be detected automatically. Possible values are: + * `RELEASE` - public releases from Google; + * `LINARO` - NDK from Linaro project; + * `ANDROID` - NDK from AOSP. +* **ANDROID_FUNCTION_LEVEL_LINKING** = `ON` - enables saparate putting each function and data items into separate sections and enable garbage collection of unused input sections at link time (`-fdata-sections -ffunction-sections -Wl,--gc-sections`); +* **ANDROID_GOLD_LINKER** = `ON` - use gold linker with GCC 4.6 for NDK r8b and newer (only for ARM and x86); +* **ANDROID_NOEXECSTACK** = `ON` - enables or disables stack execution protection code (`-Wl,-z,noexecstack`); +* **ANDROID_RELRO** = `ON` - Enables RELRO - a memory corruption mitigation technique (`-Wl,-z,relro -Wl,-z,now`); +* **ANDROID_LIBM_PATH** - path to `libm.so` (set to something like `$(TOP)/out/target/product//obj/lib/libm.so`) to workaround unresolved `sincos`. + +## Fine-tuning `CMakeLists.txt` for _android-cmake_ + +### Recognizing Android build + +_android-cmake_ defines `ANDROID` CMake variable which can be used to add Android-specific stuff: + + if (ANDROID) + message(STATUS "Hello from Android build!") + endif() + +The recommended way to identify ARM/MIPS/x86 architecture is examining `CMAKE_SYSTEM_PROCESSOR` which is set to the appropriate value: + +* `armv5te` - for `armeabi` ABI +* `armv6` - for `armeabi-v6 with VFP` ABI +* `armv7-a` - for `armeabi-v7a`, `armeabi-v7a with VFPV3` and `armeabi-v7a with NEON` ABIs +* `aarch64` - for `arm64-v8a` ABI +* `i686` - for `x86` ABI +* `x86_64` - for `x86_64` ABI +* `mips` - for `mips` ABI +* `mips64` - for `mips64` ABI + +Other variables that are set by _android-cmake_ and can be used for the fine-grained build configuration are: + +* `NEON` - set if target ABI supports Neon; +* `ANDROID_NATIVE_API_LEVEL` - native Android API level we are building for (note: Java part of Andoid application can be built for another API level) +* `ANDROID_NDK_RELEASE` - version of the Android NDK +* `ANDROID_NDK_HOST_SYSTEM_NAME` - "windows", "linux-x86" or "darwin-x86" depending on the host platform +* `ANDROID_RTTI` - set if rtti is enabled by the runtime +* `ANDROID_EXCEPTIONS` - set if exceptions are enabled by the runtime + +### Finding packages + +When crosscompiling CMake `find_*` commands are normally expected to find libraries and packages belonging to the same build target. So _android-cmake_ configures CMake to search in Android-specific paths only and ignore your host system locations. So + + find_package(ZLIB) + +will surely find libz.so within the Android NDK. + +However sometimes you need to locate a host package even when cross-compiling. For example you can be searching for your documentation generator. The _android-cmake_ recommends you to use `find_host_package` and `find_host_program` macro defined in the `android.toolchain.cmake`: + + find_host_package(Doxygen) + find_host_program(PDFLATEX pdflatex) + +However this will break regular builds so instead of wrapping package search into platform-specific logic you can copy the following snippet into your project (put it after your top-level `project()` command): + + # Search packages for host system instead of packages for target system + # in case of cross compilation these macro should be defined by toolchain file + if(NOT COMMAND find_host_package) + macro(find_host_package) + find_package(${ARGN}) + endmacro() + endif() + if(NOT COMMAND find_host_program) + macro(find_host_program) + find_program(${ARGN}) + endmacro() + endif() + +### Compiler flags recycling + +Make sure to do the following in your scripts: + + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${my_cxx_flags}") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${my_cxx_flags}") + +The flags will be prepopulated with critical flags, so don't loose them. Also be aware that _android-cmake_ also sets configuration-specific compiler and linker flags. + +## Troubleshooting + +### Building on Windows + +First of all `cygwin` builds are **NOT supported** and will not be supported by _android-cmake_. To build natively on Windows you need a port of make but I recommend http://martine.github.io/ninja/ instead. + +To build with Ninja you need: + +* Ensure you are using CMake newer than 2.8.9; +* Download the latest Ninja from https://github.com/martine/ninja/releases; +* Put the `ninja.exe` into your PATH (or add path to `ninja.exe` to your PATH environment variable); +* Pass `-GNinja` to `cmake` alongside with other arguments (or choose Ninja generator in `cmake-gui`). +* Enjoy the fast native multithreaded build :) + +But if you still want to stick to old make then: + +* Get a Windows port of GNU Make: + * Android NDK r7 (and newer) already has `make.exe` on board; + * `mingw-make` should work as fine; + * Download some other port. For example, this one: http://gnuwin32.sourceforge.net/packages/make.htm. +* Add path to your `make.exe` to system PATH or always use full path; +* Pass `-G"MinGW Makefiles"` and `-DCMAKE_MAKE_PROGRAM="make.exe"` + * It must be `MinGW Makefiles` and not `Unix Makefiles` even if your `make.exe` is not a MinGW's make. +* Run `make.exe` or `cmake --build .` for single-threaded build. + +### Projects with assembler files + +The _android-cmake_ should correctly handle projects with assembler sources (`*.s` or `*.S`). But if you still facing problems with assembler then try to upgrade your CMake to version newer than 2.8.5 + +## Copying + +_android-cmake_ is distributed under the terms of [BSD 3-Clause License](http://opensource.org/licenses/BSD-3-Clause) \ No newline at end of file diff --git a/external/boringssl/util/android-cmake/android.toolchain.cmake b/external/boringssl/util/android-cmake/android.toolchain.cmake new file mode 100644 index 0000000000..ffa26126a7 --- /dev/null +++ b/external/boringssl/util/android-cmake/android.toolchain.cmake @@ -0,0 +1,1693 @@ +# Copyright (c) 2010-2011, Ethan Rublee +# Copyright (c) 2011-2014, Andrey Kamaev +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from this +# software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +# ------------------------------------------------------------------------------ +# Android CMake toolchain file, for use with the Android NDK r5-r10d +# Requires cmake 2.6.3 or newer (2.8.9 or newer is recommended). +# See home page: https://github.com/taka-no-me/android-cmake +# +# Usage Linux: +# $ export ANDROID_NDK=/absolute/path/to/the/android-ndk +# $ mkdir build && cd build +# $ cmake -DCMAKE_TOOLCHAIN_FILE=path/to/the/android.toolchain.cmake .. +# $ make -j8 +# +# Usage Windows: +# You need native port of make to build your project. +# Android NDK r7 (and newer) already has make.exe on board. +# For older NDK you have to install it separately. +# For example, this one: http://gnuwin32.sourceforge.net/packages/make.htm +# +# $ SET ANDROID_NDK=C:\absolute\path\to\the\android-ndk +# $ mkdir build && cd build +# $ cmake.exe -G"MinGW Makefiles" +# -DCMAKE_TOOLCHAIN_FILE=path\to\the\android.toolchain.cmake +# -DCMAKE_MAKE_PROGRAM="%ANDROID_NDK%\prebuilt\windows\bin\make.exe" .. +# $ cmake.exe --build . +# +# +# Options (can be set as cmake parameters: -D=): +# ANDROID_NDK=/opt/android-ndk - path to the NDK root. +# Can be set as environment variable. Can be set only at first cmake run. +# +# ANDROID_ABI=armeabi-v7a - specifies the target Application Binary +# Interface (ABI). This option nearly matches to the APP_ABI variable +# used by ndk-build tool from Android NDK. +# +# Possible targets are: +# "armeabi" - ARMv5TE based CPU with software floating point operations +# "armeabi-v7a" - ARMv7 based devices with hardware FPU instructions +# this ABI target is used by default +# "armeabi-v7a with NEON" - same as armeabi-v7a, but +# sets NEON as floating-point unit +# "armeabi-v7a with VFPV3" - same as armeabi-v7a, but +# sets VFPV3 as floating-point unit (has 32 registers instead of 16) +# "armeabi-v6 with VFP" - tuned for ARMv6 processors having VFP +# "x86" - IA-32 instruction set +# "mips" - MIPS32 instruction set +# +# 64-bit ABIs for NDK r10 and newer: +# "arm64-v8a" - ARMv8 AArch64 instruction set +# "x86_64" - Intel64 instruction set (r1) +# "mips64" - MIPS64 instruction set (r6) +# +# ANDROID_NATIVE_API_LEVEL=android-8 - level of Android API compile for. +# Option is read-only when standalone toolchain is used. +# Note: building for "android-L" requires explicit configuration. +# +# ANDROID_TOOLCHAIN_NAME=arm-linux-androideabi-4.9 - the name of compiler +# toolchain to be used. The list of possible values depends on the NDK +# version. For NDK r10c the possible values are: +# +# * aarch64-linux-android-4.9 +# * aarch64-linux-android-clang3.4 +# * aarch64-linux-android-clang3.5 +# * arm-linux-androideabi-4.6 +# * arm-linux-androideabi-4.8 +# * arm-linux-androideabi-4.9 (default) +# * arm-linux-androideabi-clang3.4 +# * arm-linux-androideabi-clang3.5 +# * mips64el-linux-android-4.9 +# * mips64el-linux-android-clang3.4 +# * mips64el-linux-android-clang3.5 +# * mipsel-linux-android-4.6 +# * mipsel-linux-android-4.8 +# * mipsel-linux-android-4.9 +# * mipsel-linux-android-clang3.4 +# * mipsel-linux-android-clang3.5 +# * x86-4.6 +# * x86-4.8 +# * x86-4.9 +# * x86-clang3.4 +# * x86-clang3.5 +# * x86_64-4.9 +# * x86_64-clang3.4 +# * x86_64-clang3.5 +# +# ANDROID_FORCE_ARM_BUILD=OFF - set ON to generate 32-bit ARM instructions +# instead of Thumb. Is not available for "armeabi-v6 with VFP" +# (is forced to be ON) ABI. +# +# ANDROID_NO_UNDEFINED=ON - set ON to show all undefined symbols as linker +# errors even if they are not used. +# +# ANDROID_SO_UNDEFINED=OFF - set ON to allow undefined symbols in shared +# libraries. Automatically turned for NDK r5x and r6x due to GLESv2 +# problems. +# +# ANDROID_STL=gnustl_static - specify the runtime to use. +# +# Possible values are: +# none -> Do not configure the runtime. +# system -> Use the default minimal system C++ runtime library. +# Implies -fno-rtti -fno-exceptions. +# Is not available for standalone toolchain. +# system_re -> Use the default minimal system C++ runtime library. +# Implies -frtti -fexceptions. +# Is not available for standalone toolchain. +# gabi++_static -> Use the GAbi++ runtime as a static library. +# Implies -frtti -fno-exceptions. +# Available for NDK r7 and newer. +# Is not available for standalone toolchain. +# gabi++_shared -> Use the GAbi++ runtime as a shared library. +# Implies -frtti -fno-exceptions. +# Available for NDK r7 and newer. +# Is not available for standalone toolchain. +# stlport_static -> Use the STLport runtime as a static library. +# Implies -fno-rtti -fno-exceptions for NDK before r7. +# Implies -frtti -fno-exceptions for NDK r7 and newer. +# Is not available for standalone toolchain. +# stlport_shared -> Use the STLport runtime as a shared library. +# Implies -fno-rtti -fno-exceptions for NDK before r7. +# Implies -frtti -fno-exceptions for NDK r7 and newer. +# Is not available for standalone toolchain. +# gnustl_static -> Use the GNU STL as a static library. +# Implies -frtti -fexceptions. +# gnustl_shared -> Use the GNU STL as a shared library. +# Implies -frtti -fno-exceptions. +# Available for NDK r7b and newer. +# Silently degrades to gnustl_static if not available. +# +# ANDROID_STL_FORCE_FEATURES=ON - turn rtti and exceptions support based on +# chosen runtime. If disabled, then the user is responsible for settings +# these options. +# +# What?: +# android-cmake toolchain searches for NDK/toolchain in the following order: +# ANDROID_NDK - cmake parameter +# ANDROID_NDK - environment variable +# ANDROID_STANDALONE_TOOLCHAIN - cmake parameter +# ANDROID_STANDALONE_TOOLCHAIN - environment variable +# ANDROID_NDK - default locations +# ANDROID_STANDALONE_TOOLCHAIN - default locations +# +# Make sure to do the following in your scripts: +# SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${my_cxx_flags}" ) +# SET( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${my_cxx_flags}" ) +# The flags will be prepopulated with critical flags, so don't loose them. +# Also be aware that toolchain also sets configuration-specific compiler +# flags and linker flags. +# +# ANDROID and BUILD_ANDROID will be set to true, you may test any of these +# variables to make necessary Android-specific configuration changes. +# +# Also ARMEABI or ARMEABI_V7A or X86 or MIPS or ARM64_V8A or X86_64 or MIPS64 +# will be set true, mutually exclusive. NEON option will be set true +# if VFP is set to NEON. +# +# ------------------------------------------------------------------------------ + +cmake_minimum_required( VERSION 2.6.3 ) + +if( DEFINED CMAKE_CROSSCOMPILING ) + # subsequent toolchain loading is not really needed + return() +endif() + +if( CMAKE_TOOLCHAIN_FILE ) + # touch toolchain variable to suppress "unused variable" warning +endif() + +# inherit settings in recursive loads +get_property( _CMAKE_IN_TRY_COMPILE GLOBAL PROPERTY IN_TRY_COMPILE ) +if( _CMAKE_IN_TRY_COMPILE ) + include( "${CMAKE_CURRENT_SOURCE_DIR}/../android.toolchain.config.cmake" OPTIONAL ) +endif() + +# this one is important +if( CMAKE_VERSION VERSION_GREATER "3.0.99" ) + set( CMAKE_SYSTEM_NAME Android ) +else() + set( CMAKE_SYSTEM_NAME Linux ) +endif() + +# this one not so much +set( CMAKE_SYSTEM_VERSION 1 ) + +# rpath makes low sense for Android +set( CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG "" ) +set( CMAKE_SKIP_RPATH TRUE CACHE BOOL "If set, runtime paths are not added when using shared libraries." ) + +# NDK search paths +set( ANDROID_SUPPORTED_NDK_VERSIONS ${ANDROID_EXTRA_NDK_VERSIONS} -r10d -r10c -r10b -r10 -r9d -r9c -r9b -r9 -r8e -r8d -r8c -r8b -r8 -r7c -r7b -r7 -r6b -r6 -r5c -r5b -r5 "" ) +if( NOT DEFINED ANDROID_NDK_SEARCH_PATHS ) + if( CMAKE_HOST_WIN32 ) + file( TO_CMAKE_PATH "$ENV{PROGRAMFILES}" ANDROID_NDK_SEARCH_PATHS ) + set( ANDROID_NDK_SEARCH_PATHS "${ANDROID_NDK_SEARCH_PATHS}" "$ENV{SystemDrive}/NVPACK" ) + else() + file( TO_CMAKE_PATH "$ENV{HOME}" ANDROID_NDK_SEARCH_PATHS ) + set( ANDROID_NDK_SEARCH_PATHS /opt "${ANDROID_NDK_SEARCH_PATHS}/NVPACK" ) + endif() +endif() +if( NOT DEFINED ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH ) + set( ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH /opt/android-toolchain ) +endif() + +# known ABIs +set( ANDROID_SUPPORTED_ABIS_arm "armeabi-v7a;armeabi;armeabi-v7a with NEON;armeabi-v7a with VFPV3;armeabi-v6 with VFP" ) +set( ANDROID_SUPPORTED_ABIS_arm64 "arm64-v8a" ) +set( ANDROID_SUPPORTED_ABIS_x86 "x86" ) +set( ANDROID_SUPPORTED_ABIS_x86_64 "x86_64" ) +set( ANDROID_SUPPORTED_ABIS_mips "mips" ) +set( ANDROID_SUPPORTED_ABIS_mips64 "mips64" ) + +# API level defaults +set( ANDROID_DEFAULT_NDK_API_LEVEL 8 ) +set( ANDROID_DEFAULT_NDK_API_LEVEL_arm64 21 ) +set( ANDROID_DEFAULT_NDK_API_LEVEL_x86 9 ) +set( ANDROID_DEFAULT_NDK_API_LEVEL_x86_64 21 ) +set( ANDROID_DEFAULT_NDK_API_LEVEL_mips 9 ) +set( ANDROID_DEFAULT_NDK_API_LEVEL_mips64 21 ) + + +macro( __LIST_FILTER listvar regex ) + if( ${listvar} ) + foreach( __val ${${listvar}} ) + if( __val MATCHES "${regex}" ) + list( REMOVE_ITEM ${listvar} "${__val}" ) + endif() + endforeach() + endif() +endmacro() + +macro( __INIT_VARIABLE var_name ) + set( __test_path 0 ) + foreach( __var ${ARGN} ) + if( __var STREQUAL "PATH" ) + set( __test_path 1 ) + break() + endif() + endforeach() + + if( __test_path AND NOT EXISTS "${${var_name}}" ) + unset( ${var_name} CACHE ) + endif() + + if( " ${${var_name}}" STREQUAL " " ) + set( __values 0 ) + foreach( __var ${ARGN} ) + if( __var STREQUAL "VALUES" ) + set( __values 1 ) + elseif( NOT __var STREQUAL "PATH" ) + if( __var MATCHES "^ENV_.*$" ) + string( REPLACE "ENV_" "" __var "${__var}" ) + set( __value "$ENV{${__var}}" ) + elseif( DEFINED ${__var} ) + set( __value "${${__var}}" ) + elseif( __values ) + set( __value "${__var}" ) + else() + set( __value "" ) + endif() + + if( NOT " ${__value}" STREQUAL " " AND (NOT __test_path OR EXISTS "${__value}") ) + set( ${var_name} "${__value}" ) + break() + endif() + endif() + endforeach() + unset( __value ) + unset( __values ) + endif() + + if( __test_path ) + file( TO_CMAKE_PATH "${${var_name}}" ${var_name} ) + endif() + unset( __test_path ) +endmacro() + +macro( __DETECT_NATIVE_API_LEVEL _var _path ) + set( __ndkApiLevelRegex "^[\t ]*#define[\t ]+__ANDROID_API__[\t ]+([0-9]+)[\t ]*.*$" ) + file( STRINGS ${_path} __apiFileContent REGEX "${__ndkApiLevelRegex}" ) + if( NOT __apiFileContent ) + message( SEND_ERROR "Could not get Android native API level. Probably you have specified invalid level value, or your copy of NDK/toolchain is broken." ) + endif() + string( REGEX REPLACE "${__ndkApiLevelRegex}" "\\1" ${_var} "${__apiFileContent}" ) + unset( __apiFileContent ) + unset( __ndkApiLevelRegex ) +endmacro() + +macro( __DETECT_TOOLCHAIN_MACHINE_NAME _var _root ) + if( EXISTS "${_root}" ) + file( GLOB __gccExePath RELATIVE "${_root}/bin/" "${_root}/bin/*-gcc${TOOL_OS_SUFFIX}" ) + __LIST_FILTER( __gccExePath "^[.].*" ) + list( LENGTH __gccExePath __gccExePathsCount ) + if( NOT __gccExePathsCount EQUAL 1 AND NOT _CMAKE_IN_TRY_COMPILE ) + message( WARNING "Could not determine machine name for compiler from ${_root}" ) + set( ${_var} "" ) + else() + get_filename_component( __gccExeName "${__gccExePath}" NAME_WE ) + string( REPLACE "-gcc" "" ${_var} "${__gccExeName}" ) + endif() + unset( __gccExePath ) + unset( __gccExePathsCount ) + unset( __gccExeName ) + else() + set( ${_var} "" ) + endif() +endmacro() + + +# fight against cygwin +set( ANDROID_FORBID_SYGWIN TRUE CACHE BOOL "Prevent cmake from working under cygwin and using cygwin tools") +mark_as_advanced( ANDROID_FORBID_SYGWIN ) +if( ANDROID_FORBID_SYGWIN ) + if( CYGWIN ) + message( FATAL_ERROR "Android NDK and android-cmake toolchain are not welcome Cygwin. It is unlikely that this cmake toolchain will work under cygwin. But if you want to try then you can set cmake variable ANDROID_FORBID_SYGWIN to FALSE and rerun cmake." ) + endif() + + if( CMAKE_HOST_WIN32 ) + # remove cygwin from PATH + set( __new_path "$ENV{PATH}") + __LIST_FILTER( __new_path "cygwin" ) + set(ENV{PATH} "${__new_path}") + unset(__new_path) + endif() +endif() + + +# detect current host platform +if( NOT DEFINED ANDROID_NDK_HOST_X64 AND (CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "amd64|x86_64|AMD64" OR CMAKE_HOST_APPLE) ) + set( ANDROID_NDK_HOST_X64 1 CACHE BOOL "Try to use 64-bit compiler toolchain" ) + mark_as_advanced( ANDROID_NDK_HOST_X64 ) +endif() + +set( TOOL_OS_SUFFIX "" ) +if( CMAKE_HOST_APPLE ) + set( ANDROID_NDK_HOST_SYSTEM_NAME "darwin-x86_64" ) + set( ANDROID_NDK_HOST_SYSTEM_NAME2 "darwin-x86" ) +elseif( CMAKE_HOST_WIN32 ) + set( ANDROID_NDK_HOST_SYSTEM_NAME "windows-x86_64" ) + set( ANDROID_NDK_HOST_SYSTEM_NAME2 "windows" ) + set( TOOL_OS_SUFFIX ".exe" ) +elseif( CMAKE_HOST_UNIX ) + set( ANDROID_NDK_HOST_SYSTEM_NAME "linux-x86_64" ) + set( ANDROID_NDK_HOST_SYSTEM_NAME2 "linux-x86" ) +else() + message( FATAL_ERROR "Cross-compilation on your platform is not supported by this cmake toolchain" ) +endif() + +if( NOT ANDROID_NDK_HOST_X64 ) + set( ANDROID_NDK_HOST_SYSTEM_NAME ${ANDROID_NDK_HOST_SYSTEM_NAME2} ) +endif() + +# see if we have path to Android NDK +if( NOT ANDROID_NDK AND NOT ANDROID_STANDALONE_TOOLCHAIN ) + __INIT_VARIABLE( ANDROID_NDK PATH ENV_ANDROID_NDK ) +endif() +if( NOT ANDROID_NDK ) + # see if we have path to Android standalone toolchain + __INIT_VARIABLE( ANDROID_STANDALONE_TOOLCHAIN PATH ENV_ANDROID_STANDALONE_TOOLCHAIN ) + + if( NOT ANDROID_STANDALONE_TOOLCHAIN ) + #try to find Android NDK in one of the the default locations + set( __ndkSearchPaths ) + foreach( __ndkSearchPath ${ANDROID_NDK_SEARCH_PATHS} ) + foreach( suffix ${ANDROID_SUPPORTED_NDK_VERSIONS} ) + list( APPEND __ndkSearchPaths "${__ndkSearchPath}/android-ndk${suffix}" ) + endforeach() + endforeach() + __INIT_VARIABLE( ANDROID_NDK PATH VALUES ${__ndkSearchPaths} ) + unset( __ndkSearchPaths ) + + if( ANDROID_NDK ) + message( STATUS "Using default path for Android NDK: ${ANDROID_NDK}" ) + message( STATUS " If you prefer to use a different location, please define a cmake or environment variable: ANDROID_NDK" ) + else() + #try to find Android standalone toolchain in one of the the default locations + __INIT_VARIABLE( ANDROID_STANDALONE_TOOLCHAIN PATH ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH ) + + if( ANDROID_STANDALONE_TOOLCHAIN ) + message( STATUS "Using default path for standalone toolchain ${ANDROID_STANDALONE_TOOLCHAIN}" ) + message( STATUS " If you prefer to use a different location, please define the variable: ANDROID_STANDALONE_TOOLCHAIN" ) + endif( ANDROID_STANDALONE_TOOLCHAIN ) + endif( ANDROID_NDK ) + endif( NOT ANDROID_STANDALONE_TOOLCHAIN ) +endif( NOT ANDROID_NDK ) + +# remember found paths +if( ANDROID_NDK ) + get_filename_component( ANDROID_NDK "${ANDROID_NDK}" ABSOLUTE ) + set( ANDROID_NDK "${ANDROID_NDK}" CACHE INTERNAL "Path of the Android NDK" FORCE ) + set( BUILD_WITH_ANDROID_NDK True ) + if( EXISTS "${ANDROID_NDK}/RELEASE.TXT" ) + file( STRINGS "${ANDROID_NDK}/RELEASE.TXT" ANDROID_NDK_RELEASE_FULL LIMIT_COUNT 1 REGEX "r[0-9]+[a-z]?" ) + string( REGEX MATCH "r([0-9]+)([a-z]?)" ANDROID_NDK_RELEASE "${ANDROID_NDK_RELEASE_FULL}" ) + else() + set( ANDROID_NDK_RELEASE "r1x" ) + set( ANDROID_NDK_RELEASE_FULL "unreleased" ) + endif() + string( REGEX REPLACE "r([0-9]+)([a-z]?)" "\\1*1000" ANDROID_NDK_RELEASE_NUM "${ANDROID_NDK_RELEASE}" ) + string( FIND " abcdefghijklmnopqastuvwxyz" "${CMAKE_MATCH_2}" __ndkReleaseLetterNum ) + math( EXPR ANDROID_NDK_RELEASE_NUM "${ANDROID_NDK_RELEASE_NUM}+${__ndkReleaseLetterNum}" ) +elseif( ANDROID_STANDALONE_TOOLCHAIN ) + get_filename_component( ANDROID_STANDALONE_TOOLCHAIN "${ANDROID_STANDALONE_TOOLCHAIN}" ABSOLUTE ) + # try to detect change + if( CMAKE_AR ) + string( LENGTH "${ANDROID_STANDALONE_TOOLCHAIN}" __length ) + string( SUBSTRING "${CMAKE_AR}" 0 ${__length} __androidStandaloneToolchainPreviousPath ) + if( NOT __androidStandaloneToolchainPreviousPath STREQUAL ANDROID_STANDALONE_TOOLCHAIN ) + message( FATAL_ERROR "It is not possible to change path to the Android standalone toolchain on subsequent run." ) + endif() + unset( __androidStandaloneToolchainPreviousPath ) + unset( __length ) + endif() + set( ANDROID_STANDALONE_TOOLCHAIN "${ANDROID_STANDALONE_TOOLCHAIN}" CACHE INTERNAL "Path of the Android standalone toolchain" FORCE ) + set( BUILD_WITH_STANDALONE_TOOLCHAIN True ) +else() + list(GET ANDROID_NDK_SEARCH_PATHS 0 ANDROID_NDK_SEARCH_PATH) + message( FATAL_ERROR "Could not find neither Android NDK nor Android standalone toolchain. + You should either set an environment variable: + export ANDROID_NDK=~/my-android-ndk + or + export ANDROID_STANDALONE_TOOLCHAIN=~/my-android-toolchain + or put the toolchain or NDK in the default path: + sudo ln -s ~/my-android-ndk ${ANDROID_NDK_SEARCH_PATH}/android-ndk + sudo ln -s ~/my-android-toolchain ${ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH}" ) +endif() + +# android NDK layout +if( BUILD_WITH_ANDROID_NDK ) + if( NOT DEFINED ANDROID_NDK_LAYOUT ) + # try to automatically detect the layout + if( EXISTS "${ANDROID_NDK}/RELEASE.TXT") + set( ANDROID_NDK_LAYOUT "RELEASE" ) + elseif( EXISTS "${ANDROID_NDK}/../../linux-x86/toolchain/" ) + set( ANDROID_NDK_LAYOUT "LINARO" ) + elseif( EXISTS "${ANDROID_NDK}/../../gcc/" ) + set( ANDROID_NDK_LAYOUT "ANDROID" ) + endif() + endif() + set( ANDROID_NDK_LAYOUT "${ANDROID_NDK_LAYOUT}" CACHE STRING "The inner layout of NDK" ) + mark_as_advanced( ANDROID_NDK_LAYOUT ) + if( ANDROID_NDK_LAYOUT STREQUAL "LINARO" ) + set( ANDROID_NDK_HOST_SYSTEM_NAME ${ANDROID_NDK_HOST_SYSTEM_NAME2} ) # only 32-bit at the moment + set( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK}/../../${ANDROID_NDK_HOST_SYSTEM_NAME}/toolchain" ) + set( ANDROID_NDK_TOOLCHAINS_SUBPATH "" ) + set( ANDROID_NDK_TOOLCHAINS_SUBPATH2 "" ) + elseif( ANDROID_NDK_LAYOUT STREQUAL "ANDROID" ) + set( ANDROID_NDK_HOST_SYSTEM_NAME ${ANDROID_NDK_HOST_SYSTEM_NAME2} ) # only 32-bit at the moment + set( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK}/../../gcc/${ANDROID_NDK_HOST_SYSTEM_NAME}/arm" ) + set( ANDROID_NDK_TOOLCHAINS_SUBPATH "" ) + set( ANDROID_NDK_TOOLCHAINS_SUBPATH2 "" ) + else() # ANDROID_NDK_LAYOUT STREQUAL "RELEASE" + set( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK}/toolchains" ) + set( ANDROID_NDK_TOOLCHAINS_SUBPATH "/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME}" ) + set( ANDROID_NDK_TOOLCHAINS_SUBPATH2 "/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME2}" ) + endif() + get_filename_component( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK_TOOLCHAINS_PATH}" ABSOLUTE ) + + # try to detect change of NDK + if( CMAKE_AR ) + string( LENGTH "${ANDROID_NDK_TOOLCHAINS_PATH}" __length ) + string( SUBSTRING "${CMAKE_AR}" 0 ${__length} __androidNdkPreviousPath ) + if( NOT __androidNdkPreviousPath STREQUAL ANDROID_NDK_TOOLCHAINS_PATH ) + message( FATAL_ERROR "It is not possible to change the path to the NDK on subsequent CMake run. You must remove all generated files from your build folder first. + " ) + endif() + unset( __androidNdkPreviousPath ) + unset( __length ) + endif() +endif() + + +# get all the details about standalone toolchain +if( BUILD_WITH_STANDALONE_TOOLCHAIN ) + __DETECT_NATIVE_API_LEVEL( ANDROID_SUPPORTED_NATIVE_API_LEVELS "${ANDROID_STANDALONE_TOOLCHAIN}/sysroot/usr/include/android/api-level.h" ) + set( ANDROID_STANDALONE_TOOLCHAIN_API_LEVEL ${ANDROID_SUPPORTED_NATIVE_API_LEVELS} ) + set( __availableToolchains "standalone" ) + __DETECT_TOOLCHAIN_MACHINE_NAME( __availableToolchainMachines "${ANDROID_STANDALONE_TOOLCHAIN}" ) + if( NOT __availableToolchainMachines ) + message( FATAL_ERROR "Could not determine machine name of your toolchain. Probably your Android standalone toolchain is broken." ) + endif() + if( __availableToolchainMachines MATCHES x86_64 ) + set( __availableToolchainArchs "x86_64" ) + elseif( __availableToolchainMachines MATCHES i686 ) + set( __availableToolchainArchs "x86" ) + elseif( __availableToolchainMachines MATCHES aarch64 ) + set( __availableToolchainArchs "arm64" ) + elseif( __availableToolchainMachines MATCHES arm ) + set( __availableToolchainArchs "arm" ) + elseif( __availableToolchainMachines MATCHES mips64el ) + set( __availableToolchainArchs "mips64" ) + elseif( __availableToolchainMachines MATCHES mipsel ) + set( __availableToolchainArchs "mips" ) + endif() + execute_process( COMMAND "${ANDROID_STANDALONE_TOOLCHAIN}/bin/${__availableToolchainMachines}-gcc${TOOL_OS_SUFFIX}" -dumpversion + OUTPUT_VARIABLE __availableToolchainCompilerVersions OUTPUT_STRIP_TRAILING_WHITESPACE ) + string( REGEX MATCH "[0-9]+[.][0-9]+([.][0-9]+)?" __availableToolchainCompilerVersions "${__availableToolchainCompilerVersions}" ) + if( EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/bin/clang${TOOL_OS_SUFFIX}" ) + list( APPEND __availableToolchains "standalone-clang" ) + list( APPEND __availableToolchainMachines ${__availableToolchainMachines} ) + list( APPEND __availableToolchainArchs ${__availableToolchainArchs} ) + list( APPEND __availableToolchainCompilerVersions ${__availableToolchainCompilerVersions} ) + endif() +endif() + +macro( __GLOB_NDK_TOOLCHAINS __availableToolchainsVar __availableToolchainsLst __toolchain_subpath ) + foreach( __toolchain ${${__availableToolchainsLst}} ) + if( "${__toolchain}" MATCHES "-clang3[.][0-9]$" AND NOT EXISTS "${ANDROID_NDK_TOOLCHAINS_PATH}/${__toolchain}${__toolchain_subpath}" ) + SET( __toolchainVersionRegex "^TOOLCHAIN_VERSION[\t ]+:=[\t ]+(.*)$" ) + FILE( STRINGS "${ANDROID_NDK_TOOLCHAINS_PATH}/${__toolchain}/setup.mk" __toolchainVersionStr REGEX "${__toolchainVersionRegex}" ) + if( __toolchainVersionStr ) + string( REGEX REPLACE "${__toolchainVersionRegex}" "\\1" __toolchainVersionStr "${__toolchainVersionStr}" ) + string( REGEX REPLACE "-clang3[.][0-9]$" "-${__toolchainVersionStr}" __gcc_toolchain "${__toolchain}" ) + else() + string( REGEX REPLACE "-clang3[.][0-9]$" "-4.6" __gcc_toolchain "${__toolchain}" ) + endif() + unset( __toolchainVersionStr ) + unset( __toolchainVersionRegex ) + else() + set( __gcc_toolchain "${__toolchain}" ) + endif() + __DETECT_TOOLCHAIN_MACHINE_NAME( __machine "${ANDROID_NDK_TOOLCHAINS_PATH}/${__gcc_toolchain}${__toolchain_subpath}" ) + if( __machine ) + string( REGEX MATCH "[0-9]+[.][0-9]+([.][0-9x]+)?$" __version "${__gcc_toolchain}" ) + if( __machine MATCHES x86_64 ) + set( __arch "x86_64" ) + elseif( __machine MATCHES i686 ) + set( __arch "x86" ) + elseif( __machine MATCHES aarch64 ) + set( __arch "arm64" ) + elseif( __machine MATCHES arm ) + set( __arch "arm" ) + elseif( __machine MATCHES mips64el ) + set( __arch "mips64" ) + elseif( __machine MATCHES mipsel ) + set( __arch "mips" ) + else() + set( __arch "" ) + endif() + #message("machine: !${__machine}!\narch: !${__arch}!\nversion: !${__version}!\ntoolchain: !${__toolchain}!\n") + if (__arch) + list( APPEND __availableToolchainMachines "${__machine}" ) + list( APPEND __availableToolchainArchs "${__arch}" ) + list( APPEND __availableToolchainCompilerVersions "${__version}" ) + list( APPEND ${__availableToolchainsVar} "${__toolchain}" ) + endif() + endif() + unset( __gcc_toolchain ) + endforeach() +endmacro() + +# get all the details about NDK +if( BUILD_WITH_ANDROID_NDK ) + file( GLOB ANDROID_SUPPORTED_NATIVE_API_LEVELS RELATIVE "${ANDROID_NDK}/platforms" "${ANDROID_NDK}/platforms/android-*" ) + string( REPLACE "android-" "" ANDROID_SUPPORTED_NATIVE_API_LEVELS "${ANDROID_SUPPORTED_NATIVE_API_LEVELS}" ) + set( __availableToolchains "" ) + set( __availableToolchainMachines "" ) + set( __availableToolchainArchs "" ) + set( __availableToolchainCompilerVersions "" ) + if( ANDROID_TOOLCHAIN_NAME AND EXISTS "${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_TOOLCHAIN_NAME}/" ) + # do not go through all toolchains if we know the name + set( __availableToolchainsLst "${ANDROID_TOOLCHAIN_NAME}" ) + __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH}" ) + if( NOT __availableToolchains AND NOT ANDROID_NDK_TOOLCHAINS_SUBPATH STREQUAL ANDROID_NDK_TOOLCHAINS_SUBPATH2 ) + __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH2}" ) + if( __availableToolchains ) + set( ANDROID_NDK_TOOLCHAINS_SUBPATH ${ANDROID_NDK_TOOLCHAINS_SUBPATH2} ) + endif() + endif() + endif() + if( NOT __availableToolchains ) + file( GLOB __availableToolchainsLst RELATIVE "${ANDROID_NDK_TOOLCHAINS_PATH}" "${ANDROID_NDK_TOOLCHAINS_PATH}/*" ) + if( __availableToolchainsLst ) + list(SORT __availableToolchainsLst) # we need clang to go after gcc + endif() + __LIST_FILTER( __availableToolchainsLst "^[.]" ) + __LIST_FILTER( __availableToolchainsLst "llvm" ) + __LIST_FILTER( __availableToolchainsLst "renderscript" ) + __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH}" ) + if( NOT __availableToolchains AND NOT ANDROID_NDK_TOOLCHAINS_SUBPATH STREQUAL ANDROID_NDK_TOOLCHAINS_SUBPATH2 ) + __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH2}" ) + if( __availableToolchains ) + set( ANDROID_NDK_TOOLCHAINS_SUBPATH ${ANDROID_NDK_TOOLCHAINS_SUBPATH2} ) + endif() + endif() + endif() + if( NOT __availableToolchains ) + message( FATAL_ERROR "Could not find any working toolchain in the NDK. Probably your Android NDK is broken." ) + endif() +endif() + +# build list of available ABIs +set( ANDROID_SUPPORTED_ABIS "" ) +set( __uniqToolchainArchNames ${__availableToolchainArchs} ) +list( REMOVE_DUPLICATES __uniqToolchainArchNames ) +list( SORT __uniqToolchainArchNames ) +foreach( __arch ${__uniqToolchainArchNames} ) + list( APPEND ANDROID_SUPPORTED_ABIS ${ANDROID_SUPPORTED_ABIS_${__arch}} ) +endforeach() +unset( __uniqToolchainArchNames ) +if( NOT ANDROID_SUPPORTED_ABIS ) + message( FATAL_ERROR "No one of known Android ABIs is supported by this cmake toolchain." ) +endif() + +# choose target ABI +__INIT_VARIABLE( ANDROID_ABI VALUES ${ANDROID_SUPPORTED_ABIS} ) +# verify that target ABI is supported +list( FIND ANDROID_SUPPORTED_ABIS "${ANDROID_ABI}" __androidAbiIdx ) +if( __androidAbiIdx EQUAL -1 ) + string( REPLACE ";" "\", \"" PRINTABLE_ANDROID_SUPPORTED_ABIS "${ANDROID_SUPPORTED_ABIS}" ) + message( FATAL_ERROR "Specified ANDROID_ABI = \"${ANDROID_ABI}\" is not supported by this cmake toolchain or your NDK/toolchain. + Supported values are: \"${PRINTABLE_ANDROID_SUPPORTED_ABIS}\" + " ) +endif() +unset( __androidAbiIdx ) + +# set target ABI options +if( ANDROID_ABI STREQUAL "x86" ) + set( X86 true ) + set( ANDROID_NDK_ABI_NAME "x86" ) + set( ANDROID_ARCH_NAME "x86" ) + set( ANDROID_LLVM_TRIPLE "i686-none-linux-android" ) + set( CMAKE_SYSTEM_PROCESSOR "i686" ) +elseif( ANDROID_ABI STREQUAL "x86_64" ) + set( X86 true ) + set( X86_64 true ) + set( ANDROID_NDK_ABI_NAME "x86_64" ) + set( ANDROID_ARCH_NAME "x86_64" ) + set( CMAKE_SYSTEM_PROCESSOR "x86_64" ) + set( ANDROID_LLVM_TRIPLE "x86_64-none-linux-android" ) +elseif( ANDROID_ABI STREQUAL "mips64" ) + set( MIPS64 true ) + set( ANDROID_NDK_ABI_NAME "mips64" ) + set( ANDROID_ARCH_NAME "mips64" ) + set( ANDROID_LLVM_TRIPLE "mips64el-none-linux-android" ) + set( CMAKE_SYSTEM_PROCESSOR "mips64" ) +elseif( ANDROID_ABI STREQUAL "mips" ) + set( MIPS true ) + set( ANDROID_NDK_ABI_NAME "mips" ) + set( ANDROID_ARCH_NAME "mips" ) + set( ANDROID_LLVM_TRIPLE "mipsel-none-linux-android" ) + set( CMAKE_SYSTEM_PROCESSOR "mips" ) +elseif( ANDROID_ABI STREQUAL "arm64-v8a" ) + set( ARM64_V8A true ) + set( ANDROID_NDK_ABI_NAME "arm64-v8a" ) + set( ANDROID_ARCH_NAME "arm64" ) + set( ANDROID_LLVM_TRIPLE "aarch64-none-linux-android" ) + set( CMAKE_SYSTEM_PROCESSOR "aarch64" ) + set( VFPV3 true ) + set( NEON true ) +elseif( ANDROID_ABI STREQUAL "armeabi" ) + set( ARMEABI true ) + set( ANDROID_NDK_ABI_NAME "armeabi" ) + set( ANDROID_ARCH_NAME "arm" ) + set( ANDROID_LLVM_TRIPLE "armv5te-none-linux-androideabi" ) + set( CMAKE_SYSTEM_PROCESSOR "armv5te" ) +elseif( ANDROID_ABI STREQUAL "armeabi-v6 with VFP" ) + set( ARMEABI_V6 true ) + set( ANDROID_NDK_ABI_NAME "armeabi" ) + set( ANDROID_ARCH_NAME "arm" ) + set( ANDROID_LLVM_TRIPLE "armv5te-none-linux-androideabi" ) + set( CMAKE_SYSTEM_PROCESSOR "armv6" ) + # need always fallback to older platform + set( ARMEABI true ) +elseif( ANDROID_ABI STREQUAL "armeabi-v7a") + set( ARMEABI_V7A true ) + set( ANDROID_NDK_ABI_NAME "armeabi-v7a" ) + set( ANDROID_ARCH_NAME "arm" ) + set( ANDROID_LLVM_TRIPLE "armv7-none-linux-androideabi" ) + set( CMAKE_SYSTEM_PROCESSOR "armv7-a" ) +elseif( ANDROID_ABI STREQUAL "armeabi-v7a with VFPV3" ) + set( ARMEABI_V7A true ) + set( ANDROID_NDK_ABI_NAME "armeabi-v7a" ) + set( ANDROID_ARCH_NAME "arm" ) + set( ANDROID_LLVM_TRIPLE "armv7-none-linux-androideabi" ) + set( CMAKE_SYSTEM_PROCESSOR "armv7-a" ) + set( VFPV3 true ) +elseif( ANDROID_ABI STREQUAL "armeabi-v7a with NEON" ) + set( ARMEABI_V7A true ) + set( ANDROID_NDK_ABI_NAME "armeabi-v7a" ) + set( ANDROID_ARCH_NAME "arm" ) + set( ANDROID_LLVM_TRIPLE "armv7-none-linux-androideabi" ) + set( CMAKE_SYSTEM_PROCESSOR "armv7-a" ) + set( VFPV3 true ) + set( NEON true ) +else() + message( SEND_ERROR "Unknown ANDROID_ABI=\"${ANDROID_ABI}\" is specified." ) +endif() + +if( CMAKE_BINARY_DIR AND EXISTS "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeSystem.cmake" ) + # really dirty hack + # it is not possible to change CMAKE_SYSTEM_PROCESSOR after the first run... + file( APPEND "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeSystem.cmake" "SET(CMAKE_SYSTEM_PROCESSOR \"${CMAKE_SYSTEM_PROCESSOR}\")\n" ) +endif() + +if( ANDROID_ARCH_NAME STREQUAL "arm" AND NOT ARMEABI_V6 ) + __INIT_VARIABLE( ANDROID_FORCE_ARM_BUILD VALUES OFF ) + set( ANDROID_FORCE_ARM_BUILD ${ANDROID_FORCE_ARM_BUILD} CACHE BOOL "Use 32-bit ARM instructions instead of Thumb-1" FORCE ) + mark_as_advanced( ANDROID_FORCE_ARM_BUILD ) +else() + unset( ANDROID_FORCE_ARM_BUILD CACHE ) +endif() + +# choose toolchain +if( ANDROID_TOOLCHAIN_NAME ) + list( FIND __availableToolchains "${ANDROID_TOOLCHAIN_NAME}" __toolchainIdx ) + if( __toolchainIdx EQUAL -1 ) + list( SORT __availableToolchains ) + string( REPLACE ";" "\n * " toolchains_list "${__availableToolchains}" ) + set( toolchains_list " * ${toolchains_list}") + message( FATAL_ERROR "Specified toolchain \"${ANDROID_TOOLCHAIN_NAME}\" is missing in your NDK or broken. Please verify that your NDK is working or select another compiler toolchain. +To configure the toolchain set CMake variable ANDROID_TOOLCHAIN_NAME to one of the following values:\n${toolchains_list}\n" ) + endif() + list( GET __availableToolchainArchs ${__toolchainIdx} __toolchainArch ) + if( NOT __toolchainArch STREQUAL ANDROID_ARCH_NAME ) + message( SEND_ERROR "Selected toolchain \"${ANDROID_TOOLCHAIN_NAME}\" is not able to compile binaries for the \"${ANDROID_ARCH_NAME}\" platform." ) + endif() +else() + set( __toolchainIdx -1 ) + set( __applicableToolchains "" ) + set( __toolchainMaxVersion "0.0.0" ) + list( LENGTH __availableToolchains __availableToolchainsCount ) + math( EXPR __availableToolchainsCount "${__availableToolchainsCount}-1" ) + foreach( __idx RANGE ${__availableToolchainsCount} ) + list( GET __availableToolchainArchs ${__idx} __toolchainArch ) + if( __toolchainArch STREQUAL ANDROID_ARCH_NAME ) + list( GET __availableToolchainCompilerVersions ${__idx} __toolchainVersion ) + string( REPLACE "x" "99" __toolchainVersion "${__toolchainVersion}") + if( __toolchainVersion VERSION_GREATER __toolchainMaxVersion ) + set( __toolchainMaxVersion "${__toolchainVersion}" ) + set( __toolchainIdx ${__idx} ) + endif() + endif() + endforeach() + unset( __availableToolchainsCount ) + unset( __toolchainMaxVersion ) + unset( __toolchainVersion ) +endif() +unset( __toolchainArch ) +if( __toolchainIdx EQUAL -1 ) + message( FATAL_ERROR "No one of available compiler toolchains is able to compile for ${ANDROID_ARCH_NAME} platform." ) +endif() +list( GET __availableToolchains ${__toolchainIdx} ANDROID_TOOLCHAIN_NAME ) +list( GET __availableToolchainMachines ${__toolchainIdx} ANDROID_TOOLCHAIN_MACHINE_NAME ) +list( GET __availableToolchainCompilerVersions ${__toolchainIdx} ANDROID_COMPILER_VERSION ) + +unset( __toolchainIdx ) +unset( __availableToolchains ) +unset( __availableToolchainMachines ) +unset( __availableToolchainArchs ) +unset( __availableToolchainCompilerVersions ) + +# choose native API level +__INIT_VARIABLE( ANDROID_NATIVE_API_LEVEL ENV_ANDROID_NATIVE_API_LEVEL ANDROID_API_LEVEL ENV_ANDROID_API_LEVEL ANDROID_STANDALONE_TOOLCHAIN_API_LEVEL ANDROID_DEFAULT_NDK_API_LEVEL_${ANDROID_ARCH_NAME} ANDROID_DEFAULT_NDK_API_LEVEL ) +string( REPLACE "android-" "" ANDROID_NATIVE_API_LEVEL "${ANDROID_NATIVE_API_LEVEL}" ) +string( STRIP "${ANDROID_NATIVE_API_LEVEL}" ANDROID_NATIVE_API_LEVEL ) +# adjust API level +set( __real_api_level ${ANDROID_DEFAULT_NDK_API_LEVEL_${ANDROID_ARCH_NAME}} ) +foreach( __level ${ANDROID_SUPPORTED_NATIVE_API_LEVELS} ) + if( (__level LESS ANDROID_NATIVE_API_LEVEL OR __level STREQUAL ANDROID_NATIVE_API_LEVEL) AND NOT __level LESS __real_api_level ) + set( __real_api_level ${__level} ) + endif() +endforeach() +if( __real_api_level AND NOT ANDROID_NATIVE_API_LEVEL STREQUAL __real_api_level ) + message( STATUS "Adjusting Android API level 'android-${ANDROID_NATIVE_API_LEVEL}' to 'android-${__real_api_level}'") + set( ANDROID_NATIVE_API_LEVEL ${__real_api_level} ) +endif() +unset(__real_api_level) +# validate +list( FIND ANDROID_SUPPORTED_NATIVE_API_LEVELS "${ANDROID_NATIVE_API_LEVEL}" __levelIdx ) +if( __levelIdx EQUAL -1 ) + message( SEND_ERROR "Specified Android native API level 'android-${ANDROID_NATIVE_API_LEVEL}' is not supported by your NDK/toolchain." ) +else() + if( BUILD_WITH_ANDROID_NDK ) + __DETECT_NATIVE_API_LEVEL( __realApiLevel "${ANDROID_NDK}/platforms/android-${ANDROID_NATIVE_API_LEVEL}/arch-${ANDROID_ARCH_NAME}/usr/include/android/api-level.h" ) + if( NOT __realApiLevel EQUAL ANDROID_NATIVE_API_LEVEL AND NOT __realApiLevel GREATER 9000 ) + message( SEND_ERROR "Specified Android API level (${ANDROID_NATIVE_API_LEVEL}) does not match to the level found (${__realApiLevel}). Probably your copy of NDK is broken." ) + endif() + unset( __realApiLevel ) + endif() + set( ANDROID_NATIVE_API_LEVEL "${ANDROID_NATIVE_API_LEVEL}" CACHE STRING "Android API level for native code" FORCE ) + set( CMAKE_ANDROID_API ${ANDROID_NATIVE_API_LEVEL} ) + if( CMAKE_VERSION VERSION_GREATER "2.8" ) + list( SORT ANDROID_SUPPORTED_NATIVE_API_LEVELS ) + set_property( CACHE ANDROID_NATIVE_API_LEVEL PROPERTY STRINGS ${ANDROID_SUPPORTED_NATIVE_API_LEVELS} ) + endif() +endif() +unset( __levelIdx ) + + +# remember target ABI +set( ANDROID_ABI "${ANDROID_ABI}" CACHE STRING "The target ABI for Android. If arm, then armeabi-v7a is recommended for hardware floating point." FORCE ) +if( CMAKE_VERSION VERSION_GREATER "2.8" ) + list( SORT ANDROID_SUPPORTED_ABIS_${ANDROID_ARCH_NAME} ) + set_property( CACHE ANDROID_ABI PROPERTY STRINGS ${ANDROID_SUPPORTED_ABIS_${ANDROID_ARCH_NAME}} ) +endif() + + +# runtime choice (STL, rtti, exceptions) +if( NOT ANDROID_STL ) + set( ANDROID_STL gnustl_static ) +endif() +set( ANDROID_STL "${ANDROID_STL}" CACHE STRING "C++ runtime" ) +set( ANDROID_STL_FORCE_FEATURES ON CACHE BOOL "automatically configure rtti and exceptions support based on C++ runtime" ) +mark_as_advanced( ANDROID_STL ANDROID_STL_FORCE_FEATURES ) + +if( BUILD_WITH_ANDROID_NDK ) + if( NOT "${ANDROID_STL}" MATCHES "^(none|system|system_re|gabi\\+\\+_static|gabi\\+\\+_shared|stlport_static|stlport_shared|gnustl_static|gnustl_shared)$") + message( FATAL_ERROR "ANDROID_STL is set to invalid value \"${ANDROID_STL}\". +The possible values are: + none -> Do not configure the runtime. + system -> Use the default minimal system C++ runtime library. + system_re -> Same as system but with rtti and exceptions. + gabi++_static -> Use the GAbi++ runtime as a static library. + gabi++_shared -> Use the GAbi++ runtime as a shared library. + stlport_static -> Use the STLport runtime as a static library. + stlport_shared -> Use the STLport runtime as a shared library. + gnustl_static -> (default) Use the GNU STL as a static library. + gnustl_shared -> Use the GNU STL as a shared library. +" ) + endif() +elseif( BUILD_WITH_STANDALONE_TOOLCHAIN ) + if( NOT "${ANDROID_STL}" MATCHES "^(none|gnustl_static|gnustl_shared)$") + message( FATAL_ERROR "ANDROID_STL is set to invalid value \"${ANDROID_STL}\". +The possible values are: + none -> Do not configure the runtime. + gnustl_static -> (default) Use the GNU STL as a static library. + gnustl_shared -> Use the GNU STL as a shared library. +" ) + endif() +endif() + +unset( ANDROID_RTTI ) +unset( ANDROID_EXCEPTIONS ) +unset( ANDROID_STL_INCLUDE_DIRS ) +unset( __libstl ) +unset( __libsupcxx ) + +if( NOT _CMAKE_IN_TRY_COMPILE AND ANDROID_NDK_RELEASE STREQUAL "r7b" AND ARMEABI_V7A AND NOT VFPV3 AND ANDROID_STL MATCHES "gnustl" ) + message( WARNING "The GNU STL armeabi-v7a binaries from NDK r7b can crash non-NEON devices. The files provided with NDK r7b were not configured properly, resulting in crashes on Tegra2-based devices and others when trying to use certain floating-point functions (e.g., cosf, sinf, expf). +You are strongly recommended to switch to another NDK release. +" ) +endif() + +if( NOT _CMAKE_IN_TRY_COMPILE AND X86 AND ANDROID_STL MATCHES "gnustl" AND ANDROID_NDK_RELEASE STREQUAL "r6" ) + message( WARNING "The x86 system header file from NDK r6 has incorrect definition for ptrdiff_t. You are recommended to upgrade to a newer NDK release or manually patch the header: +See https://android.googlesource.com/platform/development.git f907f4f9d4e56ccc8093df6fee54454b8bcab6c2 + diff --git a/ndk/platforms/android-9/arch-x86/include/machine/_types.h b/ndk/platforms/android-9/arch-x86/include/machine/_types.h + index 5e28c64..65892a1 100644 + --- a/ndk/platforms/android-9/arch-x86/include/machine/_types.h + +++ b/ndk/platforms/android-9/arch-x86/include/machine/_types.h + @@ -51,7 +51,11 @@ typedef long int ssize_t; + #endif + #ifndef _PTRDIFF_T + #define _PTRDIFF_T + -typedef long ptrdiff_t; + +# ifdef __ANDROID__ + + typedef int ptrdiff_t; + +# else + + typedef long ptrdiff_t; + +# endif + #endif +" ) +endif() + + +# setup paths and STL for standalone toolchain +if( BUILD_WITH_STANDALONE_TOOLCHAIN ) + set( ANDROID_TOOLCHAIN_ROOT "${ANDROID_STANDALONE_TOOLCHAIN}" ) + set( ANDROID_CLANG_TOOLCHAIN_ROOT "${ANDROID_STANDALONE_TOOLCHAIN}" ) + set( ANDROID_SYSROOT "${ANDROID_STANDALONE_TOOLCHAIN}/sysroot" ) + + if( NOT ANDROID_STL STREQUAL "none" ) + set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_STANDALONE_TOOLCHAIN}/include/c++/${ANDROID_COMPILER_VERSION}" ) + if( NOT EXISTS "${ANDROID_STL_INCLUDE_DIRS}" ) + # old location ( pre r8c ) + set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/include/c++/${ANDROID_COMPILER_VERSION}" ) + endif() + if( ARMEABI_V7A AND EXISTS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/${CMAKE_SYSTEM_PROCESSOR}/bits" ) + list( APPEND ANDROID_STL_INCLUDE_DIRS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/${CMAKE_SYSTEM_PROCESSOR}" ) + elseif( ARMEABI AND NOT ANDROID_FORCE_ARM_BUILD AND EXISTS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/thumb/bits" ) + list( APPEND ANDROID_STL_INCLUDE_DIRS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/thumb" ) + else() + list( APPEND ANDROID_STL_INCLUDE_DIRS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}" ) + endif() + # always search static GNU STL to get the location of libsupc++.a + if( ARMEABI_V7A AND NOT ANDROID_FORCE_ARM_BUILD AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/thumb/libstdc++.a" ) + set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/thumb" ) + elseif( ARMEABI_V7A AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libstdc++.a" ) + set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}" ) + elseif( ARMEABI AND NOT ANDROID_FORCE_ARM_BUILD AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libstdc++.a" ) + set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb" ) + elseif( EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libstdc++.a" ) + set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib" ) + endif() + if( __libstl ) + set( __libsupcxx "${__libstl}/libsupc++.a" ) + set( __libstl "${__libstl}/libstdc++.a" ) + endif() + if( NOT EXISTS "${__libsupcxx}" ) + message( FATAL_ERROR "The required libstdsupc++.a is missing in your standalone toolchain. + Usually it happens because of bug in make-standalone-toolchain.sh script from NDK r7, r7b and r7c. + You need to either upgrade to newer NDK or manually copy + $ANDROID_NDK/sources/cxx-stl/gnu-libstdc++/libs/${ANDROID_NDK_ABI_NAME}/libsupc++.a + to + ${__libsupcxx} + " ) + endif() + if( ANDROID_STL STREQUAL "gnustl_shared" ) + if( ARMEABI_V7A AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libgnustl_shared.so" ) + set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libgnustl_shared.so" ) + elseif( ARMEABI AND NOT ANDROID_FORCE_ARM_BUILD AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libgnustl_shared.so" ) + set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libgnustl_shared.so" ) + elseif( EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libgnustl_shared.so" ) + set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libgnustl_shared.so" ) + endif() + endif() + endif() +endif() + +# clang +if( "${ANDROID_TOOLCHAIN_NAME}" STREQUAL "standalone-clang" ) + set( ANDROID_COMPILER_IS_CLANG 1 ) + execute_process( COMMAND "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/clang${TOOL_OS_SUFFIX}" --version OUTPUT_VARIABLE ANDROID_CLANG_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE ) + string( REGEX MATCH "[0-9]+[.][0-9]+" ANDROID_CLANG_VERSION "${ANDROID_CLANG_VERSION}") +elseif( "${ANDROID_TOOLCHAIN_NAME}" MATCHES "-clang3[.][0-9]?$" ) + string( REGEX MATCH "3[.][0-9]$" ANDROID_CLANG_VERSION "${ANDROID_TOOLCHAIN_NAME}") + string( REGEX REPLACE "-clang${ANDROID_CLANG_VERSION}$" "-${ANDROID_COMPILER_VERSION}" ANDROID_GCC_TOOLCHAIN_NAME "${ANDROID_TOOLCHAIN_NAME}" ) + if( NOT EXISTS "${ANDROID_NDK_TOOLCHAINS_PATH}/llvm-${ANDROID_CLANG_VERSION}${ANDROID_NDK_TOOLCHAINS_SUBPATH}/bin/clang${TOOL_OS_SUFFIX}" ) + message( FATAL_ERROR "Could not find the Clang compiler driver" ) + endif() + set( ANDROID_COMPILER_IS_CLANG 1 ) + set( ANDROID_CLANG_TOOLCHAIN_ROOT "${ANDROID_NDK_TOOLCHAINS_PATH}/llvm-${ANDROID_CLANG_VERSION}${ANDROID_NDK_TOOLCHAINS_SUBPATH}" ) +else() + set( ANDROID_GCC_TOOLCHAIN_NAME "${ANDROID_TOOLCHAIN_NAME}" ) + unset( ANDROID_COMPILER_IS_CLANG CACHE ) +endif() + +string( REPLACE "." "" _clang_name "clang${ANDROID_CLANG_VERSION}" ) +if( NOT EXISTS "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}${TOOL_OS_SUFFIX}" ) + set( _clang_name "clang" ) +endif() + + +# setup paths and STL for NDK +if( BUILD_WITH_ANDROID_NDK ) + set( ANDROID_TOOLCHAIN_ROOT "${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}${ANDROID_NDK_TOOLCHAINS_SUBPATH}" ) + set( ANDROID_SYSROOT "${ANDROID_NDK}/platforms/android-${ANDROID_NATIVE_API_LEVEL}/arch-${ANDROID_ARCH_NAME}" ) + + if( ANDROID_STL STREQUAL "none" ) + # do nothing + elseif( ANDROID_STL STREQUAL "system" ) + set( ANDROID_RTTI OFF ) + set( ANDROID_EXCEPTIONS OFF ) + set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/system/include" ) + elseif( ANDROID_STL STREQUAL "system_re" ) + set( ANDROID_RTTI ON ) + set( ANDROID_EXCEPTIONS ON ) + set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/system/include" ) + elseif( ANDROID_STL MATCHES "gabi" ) + if( ANDROID_NDK_RELEASE_NUM LESS 7000 ) # before r7 + message( FATAL_ERROR "gabi++ is not available in your NDK. You have to upgrade to NDK r7 or newer to use gabi++.") + endif() + set( ANDROID_RTTI ON ) + set( ANDROID_EXCEPTIONS OFF ) + set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/gabi++/include" ) + set( __libstl "${ANDROID_NDK}/sources/cxx-stl/gabi++/libs/${ANDROID_NDK_ABI_NAME}/libgabi++_static.a" ) + elseif( ANDROID_STL MATCHES "stlport" ) + if( NOT ANDROID_NDK_RELEASE_NUM LESS 8004 ) # before r8d + set( ANDROID_EXCEPTIONS ON ) + else() + set( ANDROID_EXCEPTIONS OFF ) + endif() + if( ANDROID_NDK_RELEASE_NUM LESS 7000 ) # before r7 + set( ANDROID_RTTI OFF ) + else() + set( ANDROID_RTTI ON ) + endif() + set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/stlport/stlport" ) + set( __libstl "${ANDROID_NDK}/sources/cxx-stl/stlport/libs/${ANDROID_NDK_ABI_NAME}/libstlport_static.a" ) + elseif( ANDROID_STL MATCHES "gnustl" ) + set( ANDROID_EXCEPTIONS ON ) + set( ANDROID_RTTI ON ) + if( EXISTS "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_COMPILER_VERSION}" ) + if( ARMEABI_V7A AND ANDROID_COMPILER_VERSION VERSION_EQUAL "4.7" AND ANDROID_NDK_RELEASE STREQUAL "r8d" ) + # gnustl binary for 4.7 compiler is buggy :( + # TODO: look for right fix + set( __libstl "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/4.6" ) + else() + set( __libstl "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_COMPILER_VERSION}" ) + endif() + else() + set( __libstl "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++" ) + endif() + set( ANDROID_STL_INCLUDE_DIRS "${__libstl}/include" "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/include" "${__libstl}/include/backward" ) + if( EXISTS "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/libgnustl_static.a" ) + set( __libstl "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/libgnustl_static.a" ) + else() + set( __libstl "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/libstdc++.a" ) + endif() + else() + message( FATAL_ERROR "Unknown runtime: ${ANDROID_STL}" ) + endif() + # find libsupc++.a - rtti & exceptions + if( ANDROID_STL STREQUAL "system_re" OR ANDROID_STL MATCHES "gnustl" ) + set( __libsupcxx "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_COMPILER_VERSION}/libs/${ANDROID_NDK_ABI_NAME}/libsupc++.a" ) # r8b or newer + if( NOT EXISTS "${__libsupcxx}" ) + set( __libsupcxx "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/libs/${ANDROID_NDK_ABI_NAME}/libsupc++.a" ) # r7-r8 + endif() + if( NOT EXISTS "${__libsupcxx}" ) # before r7 + if( ARMEABI_V7A ) + if( ANDROID_FORCE_ARM_BUILD ) + set( __libsupcxx "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libsupc++.a" ) + else() + set( __libsupcxx "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/thumb/libsupc++.a" ) + endif() + elseif( ARMEABI AND NOT ANDROID_FORCE_ARM_BUILD ) + set( __libsupcxx "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libsupc++.a" ) + else() + set( __libsupcxx "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libsupc++.a" ) + endif() + endif() + if( NOT EXISTS "${__libsupcxx}") + message( ERROR "Could not find libsupc++.a for a chosen platform. Either your NDK is not supported or is broken.") + endif() + endif() +endif() + + +# case of shared STL linkage +if( ANDROID_STL MATCHES "shared" AND DEFINED __libstl ) + string( REPLACE "_static.a" "_shared.so" __libstl "${__libstl}" ) + # TODO: check if .so file exists before the renaming +endif() + + +# ccache support +__INIT_VARIABLE( _ndk_ccache NDK_CCACHE ENV_NDK_CCACHE ) +if( _ndk_ccache ) + if( DEFINED NDK_CCACHE AND NOT EXISTS NDK_CCACHE ) + unset( NDK_CCACHE CACHE ) + endif() + find_program( NDK_CCACHE "${_ndk_ccache}" DOC "The path to ccache binary") +else() + unset( NDK_CCACHE CACHE ) +endif() +unset( _ndk_ccache ) + + +# setup the cross-compiler +if( NOT CMAKE_C_COMPILER ) + if( NDK_CCACHE AND NOT ANDROID_SYSROOT MATCHES "[ ;\"]" ) + set( CMAKE_C_COMPILER "${NDK_CCACHE}" CACHE PATH "ccache as C compiler" ) + set( CMAKE_CXX_COMPILER "${NDK_CCACHE}" CACHE PATH "ccache as C++ compiler" ) + if( ANDROID_COMPILER_IS_CLANG ) + set( CMAKE_C_COMPILER_ARG1 "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}${TOOL_OS_SUFFIX}" CACHE PATH "C compiler") + set( CMAKE_CXX_COMPILER_ARG1 "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}++${TOOL_OS_SUFFIX}" CACHE PATH "C++ compiler") + else() + set( CMAKE_C_COMPILER_ARG1 "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc${TOOL_OS_SUFFIX}" CACHE PATH "C compiler") + set( CMAKE_CXX_COMPILER_ARG1 "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-g++${TOOL_OS_SUFFIX}" CACHE PATH "C++ compiler") + endif() + else() + if( ANDROID_COMPILER_IS_CLANG ) + set( CMAKE_C_COMPILER "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}${TOOL_OS_SUFFIX}" CACHE PATH "C compiler") + set( CMAKE_CXX_COMPILER "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}++${TOOL_OS_SUFFIX}" CACHE PATH "C++ compiler") + else() + set( CMAKE_C_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc${TOOL_OS_SUFFIX}" CACHE PATH "C compiler" ) + set( CMAKE_CXX_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-g++${TOOL_OS_SUFFIX}" CACHE PATH "C++ compiler" ) + endif() + endif() + set( CMAKE_ASM_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc${TOOL_OS_SUFFIX}" CACHE PATH "assembler" ) + set( CMAKE_STRIP "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-strip${TOOL_OS_SUFFIX}" CACHE PATH "strip" ) + if( EXISTS "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc-ar${TOOL_OS_SUFFIX}" ) + # Use gcc-ar if we have it for better LTO support. + set( CMAKE_AR "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc-ar${TOOL_OS_SUFFIX}" CACHE PATH "archive" ) + else() + set( CMAKE_AR "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-ar${TOOL_OS_SUFFIX}" CACHE PATH "archive" ) + endif() + set( CMAKE_LINKER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-ld${TOOL_OS_SUFFIX}" CACHE PATH "linker" ) + set( CMAKE_NM "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-nm${TOOL_OS_SUFFIX}" CACHE PATH "nm" ) + set( CMAKE_OBJCOPY "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-objcopy${TOOL_OS_SUFFIX}" CACHE PATH "objcopy" ) + set( CMAKE_OBJDUMP "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-objdump${TOOL_OS_SUFFIX}" CACHE PATH "objdump" ) + set( CMAKE_RANLIB "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-ranlib${TOOL_OS_SUFFIX}" CACHE PATH "ranlib" ) +endif() + +set( _CMAKE_TOOLCHAIN_PREFIX "${ANDROID_TOOLCHAIN_MACHINE_NAME}-" ) +if( CMAKE_VERSION VERSION_LESS 2.8.5 ) + set( CMAKE_ASM_COMPILER_ARG1 "-c" ) +endif() +if( APPLE ) + find_program( CMAKE_INSTALL_NAME_TOOL NAMES install_name_tool ) + if( NOT CMAKE_INSTALL_NAME_TOOL ) + message( FATAL_ERROR "Could not find install_name_tool, please check your installation." ) + endif() + mark_as_advanced( CMAKE_INSTALL_NAME_TOOL ) +endif() + +# Force set compilers because standard identification works badly for us +include( CMakeForceCompiler ) +CMAKE_FORCE_C_COMPILER( "${CMAKE_C_COMPILER}" GNU ) +if( ANDROID_COMPILER_IS_CLANG ) + set( CMAKE_C_COMPILER_ID Clang ) +endif() +set( CMAKE_C_PLATFORM_ID Linux ) +if( X86_64 OR MIPS64 OR ARM64_V8A ) + set( CMAKE_C_SIZEOF_DATA_PTR 8 ) +else() + set( CMAKE_C_SIZEOF_DATA_PTR 4 ) +endif() +set( CMAKE_C_HAS_ISYSROOT 1 ) +set( CMAKE_C_COMPILER_ABI ELF ) +CMAKE_FORCE_CXX_COMPILER( "${CMAKE_CXX_COMPILER}" GNU ) +if( ANDROID_COMPILER_IS_CLANG ) + set( CMAKE_CXX_COMPILER_ID Clang) +endif() +set( CMAKE_CXX_PLATFORM_ID Linux ) +set( CMAKE_CXX_SIZEOF_DATA_PTR ${CMAKE_C_SIZEOF_DATA_PTR} ) +set( CMAKE_CXX_HAS_ISYSROOT 1 ) +set( CMAKE_CXX_COMPILER_ABI ELF ) +set( CMAKE_CXX_SOURCE_FILE_EXTENSIONS cc cp cxx cpp CPP c++ C ) +# force ASM compiler (required for CMake < 2.8.5) +set( CMAKE_ASM_COMPILER_ID_RUN TRUE ) +set( CMAKE_ASM_COMPILER_ID GNU ) +set( CMAKE_ASM_COMPILER_WORKS TRUE ) +set( CMAKE_ASM_COMPILER_FORCED TRUE ) +set( CMAKE_COMPILER_IS_GNUASM 1) +set( CMAKE_ASM_SOURCE_FILE_EXTENSIONS s S asm ) + +foreach( lang C CXX ASM ) + if( ANDROID_COMPILER_IS_CLANG ) + set( CMAKE_${lang}_COMPILER_VERSION ${ANDROID_CLANG_VERSION} ) + else() + set( CMAKE_${lang}_COMPILER_VERSION ${ANDROID_COMPILER_VERSION} ) + endif() +endforeach() + +# flags and definitions +remove_definitions( -DANDROID ) +add_definitions( -DANDROID ) + +if( ANDROID_SYSROOT MATCHES "[ ;\"]" ) + if( CMAKE_HOST_WIN32 ) + # try to convert path to 8.3 form + file( WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/cvt83.cmd" "@echo %~s1" ) + execute_process( COMMAND "$ENV{ComSpec}" /c "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/cvt83.cmd" "${ANDROID_SYSROOT}" + OUTPUT_VARIABLE __path OUTPUT_STRIP_TRAILING_WHITESPACE + RESULT_VARIABLE __result ERROR_QUIET ) + if( __result EQUAL 0 ) + file( TO_CMAKE_PATH "${__path}" ANDROID_SYSROOT ) + set( ANDROID_CXX_FLAGS "--sysroot=${ANDROID_SYSROOT}" ) + else() + set( ANDROID_CXX_FLAGS "--sysroot=\"${ANDROID_SYSROOT}\"" ) + endif() + else() + set( ANDROID_CXX_FLAGS "'--sysroot=${ANDROID_SYSROOT}'" ) + endif() + if( NOT _CMAKE_IN_TRY_COMPILE ) + # quotes can break try_compile and compiler identification + message(WARNING "Path to your Android NDK (or toolchain) has non-alphanumeric symbols.\nThe build might be broken.\n") + endif() +else() + set( ANDROID_CXX_FLAGS "--sysroot=${ANDROID_SYSROOT}" ) +endif() + +# NDK flags +if (ARM64_V8A ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funwind-tables" ) + set( ANDROID_CXX_FLAGS_RELEASE "-fomit-frame-pointer -fstrict-aliasing" ) + set( ANDROID_CXX_FLAGS_DEBUG "-fno-omit-frame-pointer -fno-strict-aliasing" ) + if( NOT ANDROID_COMPILER_IS_CLANG ) + set( ANDROID_CXX_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE} -funswitch-loops -finline-limit=300" ) + endif() +elseif( ARMEABI OR ARMEABI_V7A) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funwind-tables" ) + if( NOT ANDROID_FORCE_ARM_BUILD AND NOT ARMEABI_V6 ) + set( ANDROID_CXX_FLAGS_RELEASE "-mthumb -fomit-frame-pointer -fno-strict-aliasing" ) + set( ANDROID_CXX_FLAGS_DEBUG "-marm -fno-omit-frame-pointer -fno-strict-aliasing" ) + if( NOT ANDROID_COMPILER_IS_CLANG ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -finline-limit=64" ) + endif() + else() + # always compile ARMEABI_V6 in arm mode; otherwise there is no difference from ARMEABI + set( ANDROID_CXX_FLAGS_RELEASE "-marm -fomit-frame-pointer -fstrict-aliasing" ) + set( ANDROID_CXX_FLAGS_DEBUG "-marm -fno-omit-frame-pointer -fno-strict-aliasing" ) + if( NOT ANDROID_COMPILER_IS_CLANG ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funswitch-loops -finline-limit=300" ) + endif() + endif() +elseif( X86 OR X86_64 ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funwind-tables" ) + if( NOT ANDROID_COMPILER_IS_CLANG ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funswitch-loops -finline-limit=300" ) + endif() + set( ANDROID_CXX_FLAGS_RELEASE "-fomit-frame-pointer -fstrict-aliasing" ) + set( ANDROID_CXX_FLAGS_DEBUG "-fno-omit-frame-pointer -fno-strict-aliasing" ) +elseif( MIPS OR MIPS64 ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fno-strict-aliasing -finline-functions -funwind-tables -fmessage-length=0" ) + set( ANDROID_CXX_FLAGS_RELEASE "-fomit-frame-pointer" ) + set( ANDROID_CXX_FLAGS_DEBUG "-fno-omit-frame-pointer" ) + if( NOT ANDROID_COMPILER_IS_CLANG ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fno-inline-functions-called-once -fgcse-after-reload -frerun-cse-after-loop -frename-registers" ) + set( ANDROID_CXX_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE} -funswitch-loops -finline-limit=300" ) + endif() +elseif() + set( ANDROID_CXX_FLAGS_RELEASE "" ) + set( ANDROID_CXX_FLAGS_DEBUG "" ) +endif() + +set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fsigned-char" ) # good/necessary when porting desktop libraries + +if( NOT X86 AND NOT ANDROID_COMPILER_IS_CLANG ) + set( ANDROID_CXX_FLAGS "-Wno-psabi ${ANDROID_CXX_FLAGS}" ) +endif() + +if( NOT ANDROID_COMPILER_VERSION VERSION_LESS "4.6" ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -no-canonical-prefixes" ) # see https://android-review.googlesource.com/#/c/47564/ +endif() + +# ABI-specific flags +if( ARMEABI_V7A ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -march=armv7-a -mfloat-abi=softfp" ) + if( NEON ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -mfpu=neon" ) + elseif( VFPV3 ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -mfpu=vfpv3" ) + else() + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -mfpu=vfpv3-d16" ) + endif() +elseif( ARMEABI_V6 ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -march=armv6 -mfloat-abi=softfp -mfpu=vfp" ) # vfp == vfpv2 +elseif( ARMEABI ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -march=armv5te -mtune=xscale -msoft-float" ) +endif() + +if( ANDROID_STL MATCHES "gnustl" AND (EXISTS "${__libstl}" OR EXISTS "${__libsupcxx}") ) + set( CMAKE_CXX_CREATE_SHARED_LIBRARY " -o " ) + set( CMAKE_CXX_CREATE_SHARED_MODULE " -o " ) + set( CMAKE_CXX_LINK_EXECUTABLE " -o " ) +else() + set( CMAKE_CXX_CREATE_SHARED_LIBRARY " -o " ) + set( CMAKE_CXX_CREATE_SHARED_MODULE " -o " ) + set( CMAKE_CXX_LINK_EXECUTABLE " -o " ) +endif() + +# STL +if( EXISTS "${__libstl}" OR EXISTS "${__libsupcxx}" ) + if( EXISTS "${__libstl}" ) + set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} \"${__libstl}\"" ) + set( CMAKE_CXX_CREATE_SHARED_MODULE "${CMAKE_CXX_CREATE_SHARED_MODULE} \"${__libstl}\"" ) + set( CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE} \"${__libstl}\"" ) + endif() + if( EXISTS "${__libsupcxx}" ) + set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} \"${__libsupcxx}\"" ) + set( CMAKE_CXX_CREATE_SHARED_MODULE "${CMAKE_CXX_CREATE_SHARED_MODULE} \"${__libsupcxx}\"" ) + set( CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE} \"${__libsupcxx}\"" ) + # C objects: + set( CMAKE_C_CREATE_SHARED_LIBRARY " -o " ) + set( CMAKE_C_CREATE_SHARED_MODULE " -o " ) + set( CMAKE_C_LINK_EXECUTABLE " -o " ) + set( CMAKE_C_CREATE_SHARED_LIBRARY "${CMAKE_C_CREATE_SHARED_LIBRARY} \"${__libsupcxx}\"" ) + set( CMAKE_C_CREATE_SHARED_MODULE "${CMAKE_C_CREATE_SHARED_MODULE} \"${__libsupcxx}\"" ) + set( CMAKE_C_LINK_EXECUTABLE "${CMAKE_C_LINK_EXECUTABLE} \"${__libsupcxx}\"" ) + endif() + if( ANDROID_STL MATCHES "gnustl" ) + if( NOT EXISTS "${ANDROID_LIBM_PATH}" ) + set( ANDROID_LIBM_PATH -lm ) + endif() + set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} ${ANDROID_LIBM_PATH}" ) + set( CMAKE_CXX_CREATE_SHARED_MODULE "${CMAKE_CXX_CREATE_SHARED_MODULE} ${ANDROID_LIBM_PATH}" ) + set( CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE} ${ANDROID_LIBM_PATH}" ) + endif() +endif() + +# variables controlling optional build flags +if( ANDROID_NDK_RELEASE_NUM LESS 7000 ) # before r7 + # libGLESv2.so in NDK's prior to r7 refers to missing external symbols. + # So this flag option is required for all projects using OpenGL from native. + __INIT_VARIABLE( ANDROID_SO_UNDEFINED VALUES ON ) +else() + __INIT_VARIABLE( ANDROID_SO_UNDEFINED VALUES OFF ) +endif() +__INIT_VARIABLE( ANDROID_NO_UNDEFINED VALUES ON ) +__INIT_VARIABLE( ANDROID_FUNCTION_LEVEL_LINKING VALUES ON ) +__INIT_VARIABLE( ANDROID_GOLD_LINKER VALUES ON ) +__INIT_VARIABLE( ANDROID_NOEXECSTACK VALUES ON ) +__INIT_VARIABLE( ANDROID_RELRO VALUES ON ) + +set( ANDROID_NO_UNDEFINED ${ANDROID_NO_UNDEFINED} CACHE BOOL "Show all undefined symbols as linker errors" ) +set( ANDROID_SO_UNDEFINED ${ANDROID_SO_UNDEFINED} CACHE BOOL "Allows or disallows undefined symbols in shared libraries" ) +set( ANDROID_FUNCTION_LEVEL_LINKING ${ANDROID_FUNCTION_LEVEL_LINKING} CACHE BOOL "Put each function in separate section and enable garbage collection of unused input sections at link time" ) +set( ANDROID_GOLD_LINKER ${ANDROID_GOLD_LINKER} CACHE BOOL "Enables gold linker" ) +set( ANDROID_NOEXECSTACK ${ANDROID_NOEXECSTACK} CACHE BOOL "Allows or disallows undefined symbols in shared libraries" ) +set( ANDROID_RELRO ${ANDROID_RELRO} CACHE BOOL "Enables RELRO - a memory corruption mitigation technique" ) +mark_as_advanced( ANDROID_NO_UNDEFINED ANDROID_SO_UNDEFINED ANDROID_FUNCTION_LEVEL_LINKING ANDROID_GOLD_LINKER ANDROID_NOEXECSTACK ANDROID_RELRO ) + +# linker flags +set( ANDROID_LINKER_FLAGS "" ) + +if( ARMEABI_V7A ) + # this is *required* to use the following linker flags that routes around + # a CPU bug in some Cortex-A8 implementations: + set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--fix-cortex-a8" ) +endif() + +if( ANDROID_NO_UNDEFINED ) + if( MIPS ) + # there is some sysroot-related problem in mips linker... + if( NOT ANDROID_SYSROOT MATCHES "[ ;\"]" ) + set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--no-undefined -Wl,-rpath-link,${ANDROID_SYSROOT}/usr/lib" ) + endif() + else() + set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--no-undefined" ) + endif() +endif() + +if( ANDROID_SO_UNDEFINED ) + set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,-allow-shlib-undefined" ) +endif() + +if( ANDROID_FUNCTION_LEVEL_LINKING ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fdata-sections -ffunction-sections" ) + set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--gc-sections" ) +endif() + +if( ANDROID_COMPILER_VERSION VERSION_EQUAL "4.6" ) + if( ANDROID_GOLD_LINKER AND (CMAKE_HOST_UNIX OR ANDROID_NDK_RELEASE_NUM GREATER 8002) AND (ARMEABI OR ARMEABI_V7A OR X86) ) + set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -fuse-ld=gold" ) + elseif( ANDROID_NDK_RELEASE_NUM GREATER 8002 ) # after r8b + set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -fuse-ld=bfd" ) + elseif( ANDROID_NDK_RELEASE STREQUAL "r8b" AND ARMEABI AND NOT _CMAKE_IN_TRY_COMPILE ) + message( WARNING "The default bfd linker from arm GCC 4.6 toolchain can fail with 'unresolvable R_ARM_THM_CALL relocation' error message. See https://code.google.com/p/android/issues/detail?id=35342 + On Linux and OS X host platform you can workaround this problem using gold linker (default). + Rerun cmake with -DANDROID_GOLD_LINKER=ON option in case of problems. +" ) + endif() +endif() # version 4.6 + +if( ANDROID_NOEXECSTACK ) + if( ANDROID_COMPILER_IS_CLANG ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -Xclang -mnoexecstack" ) + else() + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -Wa,--noexecstack" ) + endif() + set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,-z,noexecstack" ) +endif() + +if( ANDROID_RELRO ) + set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,-z,relro -Wl,-z,now" ) +endif() + +if( ANDROID_COMPILER_IS_CLANG ) + set( ANDROID_CXX_FLAGS "-target ${ANDROID_LLVM_TRIPLE} -Qunused-arguments ${ANDROID_CXX_FLAGS}" ) + if( BUILD_WITH_ANDROID_NDK ) + set( ANDROID_CXX_FLAGS "-gcc-toolchain ${ANDROID_TOOLCHAIN_ROOT} ${ANDROID_CXX_FLAGS}" ) + endif() +endif() + +# cache flags +set( CMAKE_CXX_FLAGS "" CACHE STRING "c++ flags" ) +set( CMAKE_C_FLAGS "" CACHE STRING "c flags" ) +set( CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG" CACHE STRING "c++ Release flags" ) +set( CMAKE_C_FLAGS_RELEASE "-O3 -DNDEBUG" CACHE STRING "c Release flags" ) +set( CMAKE_CXX_FLAGS_DEBUG "-O0 -g -DDEBUG -D_DEBUG" CACHE STRING "c++ Debug flags" ) +set( CMAKE_C_FLAGS_DEBUG "-O0 -g -DDEBUG -D_DEBUG" CACHE STRING "c Debug flags" ) +set( CMAKE_SHARED_LINKER_FLAGS "" CACHE STRING "shared linker flags" ) +set( CMAKE_MODULE_LINKER_FLAGS "" CACHE STRING "module linker flags" ) +set( CMAKE_EXE_LINKER_FLAGS "-Wl,-z,nocopyreloc" CACHE STRING "executable linker flags" ) + +# put flags to cache (for debug purpose only) +set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS}" CACHE INTERNAL "Android specific c/c++ flags" ) +set( ANDROID_CXX_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE}" CACHE INTERNAL "Android specific c/c++ Release flags" ) +set( ANDROID_CXX_FLAGS_DEBUG "${ANDROID_CXX_FLAGS_DEBUG}" CACHE INTERNAL "Android specific c/c++ Debug flags" ) +set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS}" CACHE INTERNAL "Android specific c/c++ linker flags" ) + +# finish flags +set( CMAKE_CXX_FLAGS "${ANDROID_CXX_FLAGS} ${CMAKE_CXX_FLAGS}" ) +set( CMAKE_C_FLAGS "${ANDROID_CXX_FLAGS} ${CMAKE_C_FLAGS}" ) +set( CMAKE_CXX_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE} ${CMAKE_CXX_FLAGS_RELEASE}" ) +set( CMAKE_C_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE} ${CMAKE_C_FLAGS_RELEASE}" ) +set( CMAKE_CXX_FLAGS_DEBUG "${ANDROID_CXX_FLAGS_DEBUG} ${CMAKE_CXX_FLAGS_DEBUG}" ) +set( CMAKE_C_FLAGS_DEBUG "${ANDROID_CXX_FLAGS_DEBUG} ${CMAKE_C_FLAGS_DEBUG}" ) +set( CMAKE_SHARED_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} ${CMAKE_SHARED_LINKER_FLAGS}" ) +set( CMAKE_MODULE_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} ${CMAKE_MODULE_LINKER_FLAGS}" ) +set( CMAKE_EXE_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} ${CMAKE_EXE_LINKER_FLAGS}" ) + +if( MIPS AND BUILD_WITH_ANDROID_NDK AND ANDROID_NDK_RELEASE STREQUAL "r8" ) + set( CMAKE_SHARED_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}/mipself.xsc ${CMAKE_SHARED_LINKER_FLAGS}" ) + set( CMAKE_MODULE_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}/mipself.xsc ${CMAKE_MODULE_LINKER_FLAGS}" ) + set( CMAKE_EXE_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}/mipself.x ${CMAKE_EXE_LINKER_FLAGS}" ) +endif() + +# pie/pic +if( NOT (ANDROID_NATIVE_API_LEVEL LESS 16) AND (NOT DEFINED ANDROID_APP_PIE OR ANDROID_APP_PIE) AND (CMAKE_VERSION VERSION_GREATER 2.8.8) ) + set( CMAKE_POSITION_INDEPENDENT_CODE TRUE ) + set( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fPIE -pie") +else() + set( CMAKE_POSITION_INDEPENDENT_CODE FALSE ) + set( CMAKE_CXX_FLAGS "-fpic ${CMAKE_CXX_FLAGS}" ) + set( CMAKE_C_FLAGS "-fpic ${CMAKE_C_FLAGS}" ) +endif() + +# configure rtti +if( DEFINED ANDROID_RTTI AND ANDROID_STL_FORCE_FEATURES ) + if( ANDROID_RTTI ) + set( CMAKE_CXX_FLAGS "-frtti ${CMAKE_CXX_FLAGS}" ) + else() + set( CMAKE_CXX_FLAGS "-fno-rtti ${CMAKE_CXX_FLAGS}" ) + endif() +endif() + +# configure exceptios +if( DEFINED ANDROID_EXCEPTIONS AND ANDROID_STL_FORCE_FEATURES ) + if( ANDROID_EXCEPTIONS ) + set( CMAKE_CXX_FLAGS "-fexceptions ${CMAKE_CXX_FLAGS}" ) + set( CMAKE_C_FLAGS "-fexceptions ${CMAKE_C_FLAGS}" ) + else() + set( CMAKE_CXX_FLAGS "-fno-exceptions ${CMAKE_CXX_FLAGS}" ) + set( CMAKE_C_FLAGS "-fno-exceptions ${CMAKE_C_FLAGS}" ) + endif() +endif() + +# global includes and link directories +include_directories( SYSTEM "${ANDROID_SYSROOT}/usr/include" ${ANDROID_STL_INCLUDE_DIRS} ) +get_filename_component(__android_install_path "${CMAKE_INSTALL_PREFIX}/libs/${ANDROID_NDK_ABI_NAME}" ABSOLUTE) # avoid CMP0015 policy warning +link_directories( "${__android_install_path}" ) + +# detect if need link crtbegin_so.o explicitly +if( NOT DEFINED ANDROID_EXPLICIT_CRT_LINK ) + set( __cmd "${CMAKE_CXX_CREATE_SHARED_LIBRARY}" ) + string( REPLACE "" "${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1}" __cmd "${__cmd}" ) + string( REPLACE "" "${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_ARG1}" __cmd "${__cmd}" ) + string( REPLACE "" "${CMAKE_CXX_FLAGS}" __cmd "${__cmd}" ) + string( REPLACE "" "" __cmd "${__cmd}" ) + string( REPLACE "" "${CMAKE_SHARED_LINKER_FLAGS}" __cmd "${__cmd}" ) + string( REPLACE "" "-shared" __cmd "${__cmd}" ) + string( REPLACE "" "" __cmd "${__cmd}" ) + string( REPLACE "" "" __cmd "${__cmd}" ) + string( REPLACE "" "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/toolchain_crtlink_test.so" __cmd "${__cmd}" ) + string( REPLACE "" "\"${ANDROID_SYSROOT}/usr/lib/crtbegin_so.o\"" __cmd "${__cmd}" ) + string( REPLACE "" "" __cmd "${__cmd}" ) + separate_arguments( __cmd ) + foreach( __var ANDROID_NDK ANDROID_NDK_TOOLCHAINS_PATH ANDROID_STANDALONE_TOOLCHAIN ) + if( ${__var} ) + set( __tmp "${${__var}}" ) + separate_arguments( __tmp ) + string( REPLACE "${__tmp}" "${${__var}}" __cmd "${__cmd}") + endif() + endforeach() + string( REPLACE "'" "" __cmd "${__cmd}" ) + string( REPLACE "\"" "" __cmd "${__cmd}" ) + execute_process( COMMAND ${__cmd} RESULT_VARIABLE __cmd_result OUTPUT_QUIET ERROR_QUIET ) + if( __cmd_result EQUAL 0 ) + set( ANDROID_EXPLICIT_CRT_LINK ON ) + else() + set( ANDROID_EXPLICIT_CRT_LINK OFF ) + endif() +endif() + +if( ANDROID_EXPLICIT_CRT_LINK ) + set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} \"${ANDROID_SYSROOT}/usr/lib/crtbegin_so.o\"" ) + set( CMAKE_CXX_CREATE_SHARED_MODULE "${CMAKE_CXX_CREATE_SHARED_MODULE} \"${ANDROID_SYSROOT}/usr/lib/crtbegin_so.o\"" ) +endif() + +# setup output directories +set( CMAKE_INSTALL_PREFIX "${ANDROID_TOOLCHAIN_ROOT}/user" CACHE STRING "path for installing" ) + +if( DEFINED LIBRARY_OUTPUT_PATH_ROOT + OR EXISTS "${CMAKE_SOURCE_DIR}/AndroidManifest.xml" + OR (EXISTS "${CMAKE_SOURCE_DIR}/../AndroidManifest.xml" AND EXISTS "${CMAKE_SOURCE_DIR}/../jni/") ) + set( LIBRARY_OUTPUT_PATH_ROOT ${CMAKE_SOURCE_DIR} CACHE PATH "Root for binaries output, set this to change where Android libs are installed to" ) + if( NOT _CMAKE_IN_TRY_COMPILE ) + if( EXISTS "${CMAKE_SOURCE_DIR}/jni/CMakeLists.txt" ) + set( EXECUTABLE_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/bin/${ANDROID_NDK_ABI_NAME}" CACHE PATH "Output directory for applications" ) + else() + set( EXECUTABLE_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/bin" CACHE PATH "Output directory for applications" ) + endif() + set( LIBRARY_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/libs/${ANDROID_NDK_ABI_NAME}" CACHE PATH "Output directory for Android libs" ) + endif() +endif() + +# copy shaed stl library to build directory +if( NOT _CMAKE_IN_TRY_COMPILE AND __libstl MATCHES "[.]so$" AND DEFINED LIBRARY_OUTPUT_PATH ) + get_filename_component( __libstlname "${__libstl}" NAME ) + execute_process( COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${__libstl}" "${LIBRARY_OUTPUT_PATH}/${__libstlname}" RESULT_VARIABLE __fileCopyProcess ) + if( NOT __fileCopyProcess EQUAL 0 OR NOT EXISTS "${LIBRARY_OUTPUT_PATH}/${__libstlname}") + message( SEND_ERROR "Failed copying of ${__libstl} to the ${LIBRARY_OUTPUT_PATH}/${__libstlname}" ) + endif() + unset( __fileCopyProcess ) + unset( __libstlname ) +endif() + + +# set these global flags for cmake client scripts to change behavior +set( ANDROID True ) +set( BUILD_ANDROID True ) + +# where is the target environment +set( CMAKE_FIND_ROOT_PATH "${ANDROID_TOOLCHAIN_ROOT}/bin" "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}" "${ANDROID_SYSROOT}" "${CMAKE_INSTALL_PREFIX}" "${CMAKE_INSTALL_PREFIX}/share" ) + +# only search for libraries and includes in the ndk toolchain +set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY ) +set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY ) +set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY ) + + +# macro to find packages on the host OS +macro( find_host_package ) + set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER ) + set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER ) + set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER ) + if( CMAKE_HOST_WIN32 ) + SET( WIN32 1 ) + SET( UNIX ) + elseif( CMAKE_HOST_APPLE ) + SET( APPLE 1 ) + SET( UNIX ) + endif() + find_package( ${ARGN} ) + SET( WIN32 ) + SET( APPLE ) + SET( UNIX 1 ) + set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY ) + set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY ) + set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY ) +endmacro() + + +# macro to find programs on the host OS +macro( find_host_program ) + set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER ) + set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER ) + set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER ) + if( CMAKE_HOST_WIN32 ) + SET( WIN32 1 ) + SET( UNIX ) + elseif( CMAKE_HOST_APPLE ) + SET( APPLE 1 ) + SET( UNIX ) + endif() + find_program( ${ARGN} ) + SET( WIN32 ) + SET( APPLE ) + SET( UNIX 1 ) + set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY ) + set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY ) + set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY ) +endmacro() + + +# export toolchain settings for the try_compile() command +if( NOT _CMAKE_IN_TRY_COMPILE ) + set( __toolchain_config "") + foreach( __var NDK_CCACHE LIBRARY_OUTPUT_PATH_ROOT ANDROID_FORBID_SYGWIN + ANDROID_NDK_HOST_X64 + ANDROID_NDK + ANDROID_NDK_LAYOUT + ANDROID_STANDALONE_TOOLCHAIN + ANDROID_TOOLCHAIN_NAME + ANDROID_ABI + ANDROID_NATIVE_API_LEVEL + ANDROID_STL + ANDROID_STL_FORCE_FEATURES + ANDROID_FORCE_ARM_BUILD + ANDROID_NO_UNDEFINED + ANDROID_SO_UNDEFINED + ANDROID_FUNCTION_LEVEL_LINKING + ANDROID_GOLD_LINKER + ANDROID_NOEXECSTACK + ANDROID_RELRO + ANDROID_LIBM_PATH + ANDROID_EXPLICIT_CRT_LINK + ANDROID_APP_PIE + ) + if( DEFINED ${__var} ) + if( ${__var} MATCHES " ") + set( __toolchain_config "${__toolchain_config}set( ${__var} \"${${__var}}\" CACHE INTERNAL \"\" )\n" ) + else() + set( __toolchain_config "${__toolchain_config}set( ${__var} ${${__var}} CACHE INTERNAL \"\" )\n" ) + endif() + endif() + endforeach() + file( WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/android.toolchain.config.cmake" "${__toolchain_config}" ) + unset( __toolchain_config ) +endif() + + +# force cmake to produce / instead of \ in build commands for Ninja generator +if( CMAKE_GENERATOR MATCHES "Ninja" AND CMAKE_HOST_WIN32 ) + # it is a bad hack after all + # CMake generates Ninja makefiles with UNIX paths only if it thinks that we are going to build with MinGW + set( CMAKE_COMPILER_IS_MINGW TRUE ) # tell CMake that we are MinGW + set( CMAKE_CROSSCOMPILING TRUE ) # stop recursion + enable_language( C ) + enable_language( CXX ) + # unset( CMAKE_COMPILER_IS_MINGW ) # can't unset because CMake does not convert back-slashes in response files without it + unset( MINGW ) +endif() + + +# Variables controlling behavior or set by cmake toolchain: +# ANDROID_ABI : "armeabi-v7a" (default), "armeabi", "armeabi-v7a with NEON", "armeabi-v7a with VFPV3", "armeabi-v6 with VFP", "x86", "mips", "arm64-v8a", "x86_64", "mips64" +# ANDROID_NATIVE_API_LEVEL : 3,4,5,8,9,14,15,16,17,18,19,21 (depends on NDK version) +# ANDROID_STL : gnustl_static/gnustl_shared/stlport_static/stlport_shared/gabi++_static/gabi++_shared/system_re/system/none +# ANDROID_FORBID_SYGWIN : ON/OFF +# ANDROID_NO_UNDEFINED : ON/OFF +# ANDROID_SO_UNDEFINED : OFF/ON (default depends on NDK version) +# ANDROID_FUNCTION_LEVEL_LINKING : ON/OFF +# ANDROID_GOLD_LINKER : ON/OFF +# ANDROID_NOEXECSTACK : ON/OFF +# ANDROID_RELRO : ON/OFF +# ANDROID_FORCE_ARM_BUILD : ON/OFF +# ANDROID_STL_FORCE_FEATURES : ON/OFF +# ANDROID_LIBM_PATH : path to libm.so (set to something like $(TOP)/out/target/product//obj/lib/libm.so) to workaround unresolved `sincos` +# Can be set only at the first run: +# ANDROID_NDK : path to your NDK install +# NDK_CCACHE : path to your ccache executable +# ANDROID_TOOLCHAIN_NAME : the NDK name of compiler toolchain +# ANDROID_NDK_HOST_X64 : try to use x86_64 toolchain (default for x64 host systems) +# ANDROID_NDK_LAYOUT : the inner NDK structure (RELEASE, LINARO, ANDROID) +# LIBRARY_OUTPUT_PATH_ROOT : +# ANDROID_STANDALONE_TOOLCHAIN +# +# Primary read-only variables: +# ANDROID : always TRUE +# ARMEABI : TRUE for arm v6 and older devices +# ARMEABI_V6 : TRUE for arm v6 +# ARMEABI_V7A : TRUE for arm v7a +# ARM64_V8A : TRUE for arm64-v8a +# NEON : TRUE if NEON unit is enabled +# VFPV3 : TRUE if VFP version 3 is enabled +# X86 : TRUE if configured for x86 +# X86_64 : TRUE if configured for x86_64 +# MIPS : TRUE if configured for mips +# MIPS64 : TRUE if configured for mips64 +# BUILD_WITH_ANDROID_NDK : TRUE if NDK is used +# BUILD_WITH_STANDALONE_TOOLCHAIN : TRUE if standalone toolchain is used +# ANDROID_NDK_HOST_SYSTEM_NAME : "windows", "linux-x86" or "darwin-x86" depending on host platform +# ANDROID_NDK_ABI_NAME : "armeabi", "armeabi-v7a", "x86", "mips", "arm64-v8a", "x86_64", "mips64" depending on ANDROID_ABI +# ANDROID_NDK_RELEASE : from r5 to r10d; set only for NDK +# ANDROID_NDK_RELEASE_NUM : numeric ANDROID_NDK_RELEASE version (1000*major+minor) +# ANDROID_ARCH_NAME : "arm", "x86", "mips", "arm64", "x86_64", "mips64" depending on ANDROID_ABI +# ANDROID_SYSROOT : path to the compiler sysroot +# TOOL_OS_SUFFIX : "" or ".exe" depending on host platform +# ANDROID_COMPILER_IS_CLANG : TRUE if clang compiler is used +# +# Secondary (less stable) read-only variables: +# ANDROID_COMPILER_VERSION : GCC version used (not Clang version) +# ANDROID_CLANG_VERSION : version of clang compiler if clang is used +# ANDROID_CXX_FLAGS : C/C++ compiler flags required by Android platform +# ANDROID_SUPPORTED_ABIS : list of currently allowed values for ANDROID_ABI +# ANDROID_TOOLCHAIN_MACHINE_NAME : "arm-linux-androideabi", "arm-eabi" or "i686-android-linux" +# ANDROID_TOOLCHAIN_ROOT : path to the top level of toolchain (standalone or placed inside NDK) +# ANDROID_CLANG_TOOLCHAIN_ROOT : path to clang tools +# ANDROID_SUPPORTED_NATIVE_API_LEVELS : list of native API levels found inside NDK +# ANDROID_STL_INCLUDE_DIRS : stl include paths +# ANDROID_RTTI : if rtti is enabled by the runtime +# ANDROID_EXCEPTIONS : if exceptions are enabled by the runtime +# ANDROID_GCC_TOOLCHAIN_NAME : read-only, differs from ANDROID_TOOLCHAIN_NAME only if clang is used +# +# Defaults: +# ANDROID_DEFAULT_NDK_API_LEVEL +# ANDROID_DEFAULT_NDK_API_LEVEL_${ARCH} +# ANDROID_NDK_SEARCH_PATHS +# ANDROID_SUPPORTED_ABIS_${ARCH} +# ANDROID_SUPPORTED_NDK_VERSIONS diff --git a/external/boringssl/util/android-cmake/ndk_links.md b/external/boringssl/util/android-cmake/ndk_links.md new file mode 100644 index 0000000000..6d93d61d23 --- /dev/null +++ b/external/boringssl/util/android-cmake/ndk_links.md @@ -0,0 +1,211 @@ + +============== r1 ============== (dead links) + +* http://dl.google.com/android/ndk/android-ndk-1.5_r1-windows.zip +* http://dl.google.com/android/ndk/android-ndk-1.5_r1-darwin-x86.zip +* http://dl.google.com/android/ndk/android-ndk-1.5_r1-linux-x86.zip + +============== r2 ============== + +* http://dl.google.com/android/ndk/android-ndk-1.6_r1-windows.zip +* http://dl.google.com/android/ndk/android-ndk-1.6_r1-darwin-x86.zip +* http://dl.google.com/android/ndk/android-ndk-1.6_r1-linux-x86.zip + +============== r3 ============== + +* http://dl.google.com/android/ndk/android-ndk-r3-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r3-darwin-x86.zip +* http://dl.google.com/android/ndk/android-ndk-r3-linux-x86.zip + +============== r4 ============== + +* http://dl.google.com/android/ndk/android-ndk-r4-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r4-darwin-x86.zip +* http://dl.google.com/android/ndk/android-ndk-r4-linux-x86.zip + +============== r4b ============== + +* http://dl.google.com/android/ndk/android-ndk-r4b-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r4b-darwin-x86.zip +* http://dl.google.com/android/ndk/android-ndk-r4b-linux-x86.zip + +============== r5 ============== + +* http://dl.google.com/android/ndk/android-ndk-r5-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r5-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r5-linux-x86.tar.bz2 + +============== r5b ============== + +* http://dl.google.com/android/ndk/android-ndk-r5b-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r5b-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r5b-linux-x86.tar.bz2 + +============== r5c ============== + +* http://dl.google.com/android/ndk/android-ndk-r5c-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r5c-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r5c-linux-x86.tar.bz2 + +============== r6 ============== + +* http://dl.google.com/android/ndk/android-ndk-r6-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r6-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r6-linux-x86.tar.bz2 + +============== r6b ============== + +* http://dl.google.com/android/ndk/android-ndk-r6b-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r6b-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r6b-linux-x86.tar.bz2 + +============== r7 ============== + +* http://dl.google.com/android/ndk/android-ndk-r7-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r7-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r7-linux-x86.tar.bz2 + +============== r7b ============== + +* http://dl.google.com/android/ndk/android-ndk-r7b-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r7b-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r7b-linux-x86.tar.bz2 + +============== r7c ============== + +* http://dl.google.com/android/ndk/android-ndk-r7c-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r7c-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r7c-linux-x86.tar.bz2 + +============== r8 ============== + +* http://dl.google.com/android/ndk/android-ndk-r8-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r8-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r8-linux-x86.tar.bz2 + +============== r8b ============== + +* http://dl.google.com/android/ndk/android-ndk-r8b-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r8b-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r8b-linux-x86.tar.bz2 + +============== r8c ============== + +* http://dl.google.com/android/ndk/android-ndk-r8c-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r8c-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r8c-linux-x86.tar.bz2 + +============== r8d ============== + +* http://dl.google.com/android/ndk/android-ndk-r8d-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r8d-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r8d-linux-x86.tar.bz2 + +============== r8e ============== + +* http://dl.google.com/android/ndk/android-ndk-r8e-windows-x86.zip +* http://dl.google.com/android/ndk/android-ndk-r8e-windows-x86_64.zip +* http://dl.google.com/android/ndk/android-ndk-r8e-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r8e-darwin-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r8e-linux-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r8e-linux-x86_64.tar.bz2 + +============== r9 ============== + +* http://dl.google.com/android/ndk/android-ndk-r9-windows-x86.zip +* http://dl.google.com/android/ndk/android-ndk-r9-windows-x86-legacy-toolchains.zip +* http://dl.google.com/android/ndk/android-ndk-r9-windows-x86_64.zip +* http://dl.google.com/android/ndk/android-ndk-r9-windows-x86_64-legacy-toolchains.zip +* http://dl.google.com/android/ndk/android-ndk-r9-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9-darwin-x86-legacy-toolchains.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9-darwin-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9-darwin-x86_64-legacy-toolchains.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9-linux-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9-linux-x86-legacy-toolchains.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9-linux-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9-linux-x86_64-legacy-toolchains.tar.bz2 + +============== r9b ============== + +* http://dl.google.com/android/ndk/android-ndk-r9b-windows-x86.zip +* http://dl.google.com/android/ndk/android-ndk-r9b-windows-x86-legacy-toolchains.zip +* http://dl.google.com/android/ndk/android-ndk-r9b-windows-x86_64.zip +* http://dl.google.com/android/ndk/android-ndk-r9b-windows-x86_64-legacy-toolchains.zip +* http://dl.google.com/android/ndk/android-ndk-r9b-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9b-darwin-x86-legacy-toolchains.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9b-darwin-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9b-darwin-x86_64-legacy-toolchains.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9b-linux-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9b-linux-x86-legacy-toolchains.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9b-linux-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9b-linux-x86_64-legacy-toolchains.tar.bz2 + +============== r9c ============== + +* http://dl.google.com/android/ndk/android-ndk-r9c-windows-x86.zip +* http://dl.google.com/android/ndk/android-ndk-r9c-windows-x86_64.zip +* http://dl.google.com/android/ndk/android-ndk-r9c-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9c-darwin-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9c-linux-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9c-linux-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9c-cxx-stl-libs-with-debugging-info.zip + +============== r9d ============== + +* http://dl.google.com/android/ndk/android-ndk-r9d-windows-x86.zip +* http://dl.google.com/android/ndk/android-ndk-r9d-windows-x86_64.zip +* http://dl.google.com/android/ndk/android-ndk-r9d-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9d-darwin-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9d-linux-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9d-linux-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9d-cxx-stl-libs-with-debug-info.zip + +============== r10 ============== + +* http://dl.google.com/android/ndk/android-ndk32-r10-windows-x86.zip +* http://dl.google.com/android/ndk/android-ndk32-r10-windows-x86_64.zip +* http://dl.google.com/android/ndk/android-ndk32-r10-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk32-r10-darwin-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk32-r10-linux-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk32-r10-linux-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk64-r10-windows-x86.zip +* http://dl.google.com/android/ndk/android-ndk64-r10-windows-x86_64.zip +* http://dl.google.com/android/ndk/android-ndk64-r10-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk64-r10-darwin-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk64-r10-linux-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk64-r10-linux-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r10-cxx-stl-libs-with-debug-info.zip + +============== r10b ============== + +* http://dl.google.com/android/ndk/android-ndk32-r10b-windows-x86.zip +* http://dl.google.com/android/ndk/android-ndk32-r10b-windows-x86_64.zip +* http://dl.google.com/android/ndk/android-ndk32-r10b-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk32-r10b-darwin-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk32-r10b-linux-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk32-r10b-linux-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk64-r10b-windows-x86.zip +* http://dl.google.com/android/ndk/android-ndk64-r10b-windows-x86_64.zip +* http://dl.google.com/android/ndk/android-ndk64-r10b-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk64-r10b-darwin-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk64-r10b-linux-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk64-r10b-linux-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r10b-cxx-stl-libs-with-debug-info.zip + +============== r10c ============== + +* http://dl.google.com/android/ndk/android-ndk-r10c-windows-x86.exe +* http://dl.google.com/android/ndk/android-ndk-r10c-windows-x86_64.exe +* http://dl.google.com/android/ndk/android-ndk-r10c-darwin-x86.bin +* http://dl.google.com/android/ndk/android-ndk-r10c-darwin-x86_64.bin +* http://dl.google.com/android/ndk/android-ndk-r10c-linux-x86.bin +* http://dl.google.com/android/ndk/android-ndk-r10c-linux-x86_64.bin + +============== r10d ============== + +* http://dl.google.com/android/ndk/android-ndk-r10d-windows-x86.exe +* http://dl.google.com/android/ndk/android-ndk-r10d-windows-x86_64.exe +* http://dl.google.com/android/ndk/android-ndk-r10d-darwin-x86.bin +* http://dl.google.com/android/ndk/android-ndk-r10d-darwin-x86_64.bin +* http://dl.google.com/android/ndk/android-ndk-r10d-linux-x86.bin +* http://dl.google.com/android/ndk/android-ndk-r10d-linux-x86_64.bin diff --git a/external/boringssl/util/bot/DEPS b/external/boringssl/util/bot/DEPS new file mode 100644 index 0000000000..2a1e01a8c8 --- /dev/null +++ b/external/boringssl/util/bot/DEPS @@ -0,0 +1,141 @@ +# Copyright (c) 2015, Google Inc. +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +vars = { + 'chromium_git': 'https://chromium.googlesource.com', +} + +deps = { + 'boringssl/util/bot/gyp': + Var('chromium_git') + '/external/gyp.git' + '@' + '4cf07e8d616739f6484e46c9359b2a35196b2585', +} + +deps_os = { + 'android': { + 'boringssl/util/bot/android_tools': + Var('chromium_git') + '/android_tools.git' + '@' + '5b5f2f60b78198eaef25d442ac60f823142a8a6e', + }, +} + +hooks = [ + { + 'name': 'cmake_linux64', + 'pattern': '.', + 'action': [ 'download_from_google_storage', + '--no_resume', + '--platform=linux*', + '--no_auth', + '--bucket', 'chromium-tools', + '-s', 'boringssl/util/bot/cmake-linux64.tar.gz.sha1', + ], + }, + { + 'name': 'cmake_mac', + 'pattern': '.', + 'action': [ 'download_from_google_storage', + '--no_resume', + '--platform=darwin', + '--no_auth', + '--bucket', 'chromium-tools', + '-s', 'boringssl/util/bot/cmake-mac.tar.gz.sha1', + ], + }, + { + 'name': 'cmake_win32', + 'pattern': '.', + 'action': [ 'download_from_google_storage', + '--no_resume', + '--platform=win32', + '--no_auth', + '--bucket', 'chromium-tools', + '-s', 'boringssl/util/bot/cmake-win32.zip.sha1', + ], + }, + { + 'name': 'perl_win32', + 'pattern': '.', + 'action': [ 'download_from_google_storage', + '--no_resume', + '--platform=win32', + '--no_auth', + '--bucket', 'chromium-tools', + '-s', 'boringssl/util/bot/perl-win32.zip.sha1', + ], + }, + { + 'name': 'yasm_win32', + 'pattern': '.', + 'action': [ 'download_from_google_storage', + '--no_resume', + '--platform=win32', + '--no_auth', + '--bucket', 'chromium-tools', + '-s', 'boringssl/util/bot/yasm-win32.exe.sha1', + ], + }, + { + 'name': 'win_toolchain', + 'pattern': '.', + 'action': [ 'python', + 'boringssl/util/bot/vs_toolchain.py', + 'update', + ], + }, + { + 'name': 'clang', + 'pattern': '.', + 'action': [ 'python', + 'boringssl/util/bot/update_clang.py', + ], + }, + # TODO(davidben): Only extract archives when they've changed. Extracting perl + # on Windows is a significant part of the cycle time. + { + 'name': 'cmake_linux64_extract', + 'pattern': '.', + 'action': [ 'python', + 'boringssl/util/bot/extract.py', + 'boringssl/util/bot/cmake-linux64.tar.gz', + 'boringssl/util/bot/cmake-linux64/', + ], + }, + { + 'name': 'cmake_mac_extract', + 'pattern': '.', + 'action': [ 'python', + 'boringssl/util/bot/extract.py', + 'boringssl/util/bot/cmake-mac.tar.gz', + 'boringssl/util/bot/cmake-mac/', + ], + }, + { + 'name': 'cmake_win32_extract', + 'pattern': '.', + 'action': [ 'python', + 'boringssl/util/bot/extract.py', + 'boringssl/util/bot/cmake-win32.zip', + 'boringssl/util/bot/cmake-win32/', + ], + }, + { + 'name': 'perl_win32_extract', + 'pattern': '.', + 'action': [ 'python', + 'boringssl/util/bot/extract.py', + '--no-prefix', + 'boringssl/util/bot/perl-win32.zip', + 'boringssl/util/bot/perl-win32/', + ], + }, +] diff --git a/external/boringssl/util/bot/README b/external/boringssl/util/bot/README new file mode 100644 index 0000000000..b7a4332e85 --- /dev/null +++ b/external/boringssl/util/bot/README @@ -0,0 +1,3 @@ +This directory contains tools for setting up a hermetic toolchain on the +continuous integration bots. It is in the repository for convenience and can be +ignored in development. diff --git a/external/boringssl/util/bot/UPDATING b/external/boringssl/util/bot/UPDATING new file mode 100644 index 0000000000..2007d46f26 --- /dev/null +++ b/external/boringssl/util/bot/UPDATING @@ -0,0 +1,47 @@ +This directory consumes tools from other repositories for use on the +bots. To update to newer revisions, follow these instructions: + +DEPS: Set all revisions to those used in Chromium, found at + https://chromium.googlesource.com/chromium/src/+/master/DEPS (Search for the + corresponding repository name.) + +go/bootstrap.py: Set TOOLSET_VERSION to the latest release of Go, found at + https://golang.org/dl/. + +update_clang.py: Set CLANG_REVISION and CLANG_SUB_REVISION to the values used in + Chromium, found at + https://chromium.googlesource.com/chromium/src/+/master/tools/clang/scripts/update.py + +vs_toolchain.py: Set the hash in TOOLCHAIN_HASH to the toolchain + used in Chromium, found at _GetDesiredVsToolchainHashes + https://chromium.googlesource.com/chromium/src/+/master/build/vs_toolchain.py + This may require taking other updates to that file. If updating MSVS + version, also update TOOLCHAIN_VERSION accordingly. + +The .sha1 files correspond to files downloaded from Google Cloud Storage. To +update, place the updated files in their intended location and run: + + upload_to_google_storage.py -b chromium-tools FILE + +cmake-linux64.tar.gz: Download the latest CMake source tarball, found at + https://cmake.org/download/. Build it with: + + ./bootstrap --prefix=$PWD/cmake-linux64 && make && make install + tar -czf cmake-linux64.tar.gz cmake-linux64/ + +cmake-mac.tar.gz: Follow the same instructions as above on a Mac, but replace + cmake-linux64 with cmake-mac. + +cmake-win32.zip: Update to the latest prebuilt release of CMake, found at + https://cmake.org/download/. Use the file labeled "Windows ZIP". The + download will be named cmake-VERSION-win32-x86.zip. + +perl-win32.zip: Update to the latest 32-bit prebuilt "PortableZip" edition of + Strawberry Perl, found at http://strawberryperl.com/releases.html. The + download will be named strawberry-perl-VERSION-32bit-portable.zip. + +yasm-win32.exe: Update to the appropriate release of Yasm. Use the same version + as Chromium, found at + https://chromium.googlesource.com/chromium/src/+/master/third_party/yasm/README.chromium + Use the release at http://yasm.tortall.net/Download.html labeled + "Win32 .exe". The download will be named yasm-VERSION-win32.exe. diff --git a/external/boringssl/util/bot/cmake-linux64.tar.gz.sha1 b/external/boringssl/util/bot/cmake-linux64.tar.gz.sha1 new file mode 100644 index 0000000000..404570f6a6 --- /dev/null +++ b/external/boringssl/util/bot/cmake-linux64.tar.gz.sha1 @@ -0,0 +1 @@ +6ea4ad07a4bab113ea74c45fafb14b8d0b0feab5 \ No newline at end of file diff --git a/external/boringssl/util/bot/cmake-mac.tar.gz.sha1 b/external/boringssl/util/bot/cmake-mac.tar.gz.sha1 new file mode 100644 index 0000000000..19c9b61ffe --- /dev/null +++ b/external/boringssl/util/bot/cmake-mac.tar.gz.sha1 @@ -0,0 +1 @@ +f3166dab96234c9516ece56dc2851bf4c8e70fe8 \ No newline at end of file diff --git a/external/boringssl/util/bot/cmake-win32.zip.sha1 b/external/boringssl/util/bot/cmake-win32.zip.sha1 new file mode 100644 index 0000000000..6bb460eb86 --- /dev/null +++ b/external/boringssl/util/bot/cmake-win32.zip.sha1 @@ -0,0 +1 @@ +ed4e1939d246374b0bae724a1a4200fd60e7efe8 \ No newline at end of file diff --git a/external/boringssl/util/bot/extract.py b/external/boringssl/util/bot/extract.py new file mode 100644 index 0000000000..77603c0e05 --- /dev/null +++ b/external/boringssl/util/bot/extract.py @@ -0,0 +1,139 @@ +# Copyright (c) 2015, Google Inc. +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""Extracts archives.""" + + +import optparse +import os +import os.path +import tarfile +import shutil +import sys +import zipfile + + +def CheckedJoin(output, path): + """ + CheckedJoin returns os.path.join(output, path). It does sanity checks to + ensure the resulting path is under output, but shouldn't be used on untrusted + input. + """ + path = os.path.normpath(path) + if os.path.isabs(path) or path.startswith('.'): + raise ValueError(path) + return os.path.join(output, path) + + +def IterateZip(path): + """ + IterateZip opens the zip file at path and returns a generator of + (filename, mode, fileobj) tuples for each file in it. + """ + with zipfile.ZipFile(path, 'r') as zip_file: + for info in zip_file.infolist(): + if info.filename.endswith('/'): + continue + yield (info.filename, None, zip_file.open(info)) + + +def IterateTar(path): + """ + IterateTar opens the tar.gz file at path and returns a generator of + (filename, mode, fileobj) tuples for each file in it. + """ + with tarfile.open(path, 'r:gz') as tar_file: + for info in tar_file: + if info.isdir(): + continue + if not info.isfile(): + raise ValueError('Unknown entry type "%s"' % (info.name, )) + yield (info.name, info.mode, tar_file.extractfile(info)) + + +def main(args): + parser = optparse.OptionParser(usage='Usage: %prog ARCHIVE OUTPUT') + parser.add_option('--no-prefix', dest='no_prefix', action='store_true', + help='Do not remove a prefix from paths in the archive.') + options, args = parser.parse_args(args) + + if len(args) != 2: + parser.print_help() + return 1 + + archive, output = args + + if not os.path.exists(archive): + # Skip archives that weren't downloaded. + return 0 + + if archive.endswith('.zip'): + entries = IterateZip(archive) + elif archive.endswith('.tar.gz'): + entries = IterateTar(archive) + else: + raise ValueError(archive) + + try: + if os.path.exists(output): + print "Removing %s" % (output, ) + shutil.rmtree(output) + + print "Extracting %s to %s" % (archive, output) + prefix = None + num_extracted = 0 + for path, mode, inp in entries: + # Even on Windows, zip files must always use forward slashes. + if '\\' in path or path.startswith('/'): + raise ValueError(path) + + if not options.no_prefix: + new_prefix, rest = path.split('/', 1) + + # Ensure the archive is consistent. + if prefix is None: + prefix = new_prefix + if prefix != new_prefix: + raise ValueError((prefix, new_prefix)) + else: + rest = path + + # Extract the file into the output directory. + fixed_path = CheckedJoin(output, rest) + if not os.path.isdir(os.path.dirname(fixed_path)): + os.makedirs(os.path.dirname(fixed_path)) + with open(fixed_path, 'wb') as out: + shutil.copyfileobj(inp, out) + + # Fix up permissions if needbe. + # TODO(davidben): To be extra tidy, this should only track the execute bit + # as in git. + if mode is not None: + os.chmod(fixed_path, mode) + + # Print every 100 files, so bots do not time out on large archives. + num_extracted += 1 + if num_extracted % 100 == 0: + print "Extracted %d files..." % (num_extracted,) + finally: + entries.close() + + if num_extracted % 100 == 0: + print "Done. Extracted %d files." % (num_extracted,) + + return 0 + + +if __name__ == '__main__': + sys.exit(main(sys.argv[1:])) diff --git a/external/boringssl/util/bot/go/bootstrap.py b/external/boringssl/util/bot/go/bootstrap.py new file mode 100755 index 0000000000..8d08cc326a --- /dev/null +++ b/external/boringssl/util/bot/go/bootstrap.py @@ -0,0 +1,296 @@ +#!/usr/bin/env python +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Modified from go/bootstrap.py in Chromium infrastructure's repository to patch +# out everything but the core toolchain. +# +# https://chromium.googlesource.com/infra/infra/ + +"""Prepares a local hermetic Go installation. + +- Downloads and unpacks the Go toolset in ../golang. +""" + +import contextlib +import logging +import os +import platform +import shutil +import stat +import subprocess +import sys +import tarfile +import tempfile +import urllib +import zipfile + +# TODO(vadimsh): Migrate to new golang.org/x/ paths once Golang moves to +# git completely. + +LOGGER = logging.getLogger(__name__) + + +# /path/to/util/bot +ROOT = os.path.dirname(os.path.abspath(__file__)) + +# Where to install Go toolset to. GOROOT would be /go. +TOOLSET_ROOT = os.path.join(os.path.dirname(ROOT), 'golang') + +# Default workspace with infra go code. +WORKSPACE = os.path.join(ROOT, 'go') + +# Platform depended suffix for executable files. +EXE_SFX = '.exe' if sys.platform == 'win32' else '' + +# Pinned version of Go toolset to download. +TOOLSET_VERSION = 'go1.6.2' + +# Platform dependent portion of a download URL. See http://golang.org/dl/. +TOOLSET_VARIANTS = { + ('darwin', 'x86-64'): 'darwin-amd64.tar.gz', + ('linux2', 'x86-32'): 'linux-386.tar.gz', + ('linux2', 'x86-64'): 'linux-amd64.tar.gz', + ('win32', 'x86-32'): 'windows-386.zip', + ('win32', 'x86-64'): 'windows-amd64.zip', +} + +# Download URL root. +DOWNLOAD_URL_PREFIX = 'https://storage.googleapis.com/golang' + + +class Failure(Exception): + """Bootstrap failed.""" + + +def get_toolset_url(): + """URL of a platform specific Go toolset archive.""" + # TODO(vadimsh): Support toolset for cross-compilation. + arch = { + 'amd64': 'x86-64', + 'x86_64': 'x86-64', + 'i386': 'x86-32', + 'x86': 'x86-32', + }.get(platform.machine().lower()) + variant = TOOLSET_VARIANTS.get((sys.platform, arch)) + if not variant: + # TODO(vadimsh): Compile go lang from source. + raise Failure('Unrecognized platform') + return '%s/%s.%s' % (DOWNLOAD_URL_PREFIX, TOOLSET_VERSION, variant) + + +def read_file(path): + """Returns contents of a given file or None if not readable.""" + assert isinstance(path, (list, tuple)) + try: + with open(os.path.join(*path), 'r') as f: + return f.read() + except IOError: + return None + + +def write_file(path, data): + """Writes |data| to a file.""" + assert isinstance(path, (list, tuple)) + with open(os.path.join(*path), 'w') as f: + f.write(data) + + +def remove_directory(path): + """Recursively removes a directory.""" + assert isinstance(path, (list, tuple)) + p = os.path.join(*path) + if not os.path.exists(p): + return + LOGGER.info('Removing %s', p) + # Crutch to remove read-only file (.git/* in particular) on Windows. + def onerror(func, path, _exc_info): + if not os.access(path, os.W_OK): + os.chmod(path, stat.S_IWUSR) + func(path) + else: + raise + shutil.rmtree(p, onerror=onerror if sys.platform == 'win32' else None) + + +def install_toolset(toolset_root, url): + """Downloads and installs Go toolset. + + GOROOT would be /go/. + """ + if not os.path.exists(toolset_root): + os.makedirs(toolset_root) + pkg_path = os.path.join(toolset_root, url[url.rfind('/')+1:]) + + LOGGER.info('Downloading %s...', url) + download_file(url, pkg_path) + + LOGGER.info('Extracting...') + if pkg_path.endswith('.zip'): + with zipfile.ZipFile(pkg_path, 'r') as f: + f.extractall(toolset_root) + elif pkg_path.endswith('.tar.gz'): + with tarfile.open(pkg_path, 'r:gz') as f: + f.extractall(toolset_root) + else: + raise Failure('Unrecognized archive format') + + LOGGER.info('Validating...') + if not check_hello_world(toolset_root): + raise Failure('Something is not right, test program doesn\'t work') + + +def download_file(url, path): + """Fetches |url| to |path|.""" + last_progress = [0] + def report(a, b, c): + progress = int(a * b * 100.0 / c) + if progress != last_progress[0]: + print >> sys.stderr, 'Downloading... %d%%' % progress + last_progress[0] = progress + # TODO(vadimsh): Use something less crippled, something that validates SSL. + urllib.urlretrieve(url, path, reporthook=report) + + +@contextlib.contextmanager +def temp_dir(path): + """Creates a temporary directory, then deletes it.""" + tmp = tempfile.mkdtemp(dir=path) + try: + yield tmp + finally: + remove_directory([tmp]) + + +def check_hello_world(toolset_root): + """Compiles and runs 'hello world' program to verify that toolset works.""" + with temp_dir(toolset_root) as tmp: + path = os.path.join(tmp, 'hello.go') + write_file([path], r""" + package main + func main() { println("hello, world\n") } + """) + out = subprocess.check_output( + [get_go_exe(toolset_root), 'run', path], + env=get_go_environ(toolset_root, tmp), + stderr=subprocess.STDOUT) + if out.strip() != 'hello, world': + LOGGER.error('Failed to run sample program:\n%s', out) + return False + return True + + +def ensure_toolset_installed(toolset_root): + """Installs or updates Go toolset if necessary. + + Returns True if new toolset was installed. + """ + installed = read_file([toolset_root, 'INSTALLED_TOOLSET']) + available = get_toolset_url() + if installed == available: + LOGGER.debug('Go toolset is up-to-date: %s', TOOLSET_VERSION) + return False + + LOGGER.info('Installing Go toolset.') + LOGGER.info(' Old toolset is %s', installed) + LOGGER.info(' New toolset is %s', available) + remove_directory([toolset_root]) + install_toolset(toolset_root, available) + LOGGER.info('Go toolset installed: %s', TOOLSET_VERSION) + write_file([toolset_root, 'INSTALLED_TOOLSET'], available) + return True + + +def get_go_environ( + toolset_root, + workspace=None): + """Returns a copy of os.environ with added GO* environment variables. + + Overrides GOROOT, GOPATH and GOBIN. Keeps everything else. Idempotent. + + Args: + toolset_root: GOROOT would be /go. + workspace: main workspace directory or None if compiling in GOROOT. + """ + env = os.environ.copy() + env['GOROOT'] = os.path.join(toolset_root, 'go') + if workspace: + env['GOBIN'] = os.path.join(workspace, 'bin') + else: + env.pop('GOBIN', None) + + all_go_paths = [] + if workspace: + all_go_paths.append(workspace) + env['GOPATH'] = os.pathsep.join(all_go_paths) + + # New PATH entries. + paths_to_add = [ + os.path.join(env['GOROOT'], 'bin'), + env.get('GOBIN'), + ] + + # Make sure not to add duplicates entries to PATH over and over again when + # get_go_environ is invoked multiple times. + path = env['PATH'].split(os.pathsep) + paths_to_add = [p for p in paths_to_add if p and p not in path] + env['PATH'] = os.pathsep.join(paths_to_add + path) + + return env + + +def get_go_exe(toolset_root): + """Returns path to go executable.""" + return os.path.join(toolset_root, 'go', 'bin', 'go' + EXE_SFX) + + +def bootstrap(logging_level): + """Installs all dependencies in default locations. + + Supposed to be called at the beginning of some script (it modifies logger). + + Args: + logging_level: logging level of bootstrap process. + """ + logging.basicConfig() + LOGGER.setLevel(logging_level) + ensure_toolset_installed(TOOLSET_ROOT) + + +def prepare_go_environ(): + """Returns dict with environment variables to set to use Go toolset. + + Installs or updates the toolset if necessary. + """ + bootstrap(logging.INFO) + return get_go_environ(TOOLSET_ROOT, WORKSPACE) + + +def find_executable(name, workspaces): + """Returns full path to an executable in some bin/ (in GOROOT or GOBIN).""" + basename = name + if EXE_SFX and basename.endswith(EXE_SFX): + basename = basename[:-len(EXE_SFX)] + roots = [os.path.join(TOOLSET_ROOT, 'go', 'bin')] + for path in workspaces: + roots.extend([ + os.path.join(path, 'bin'), + ]) + for root in roots: + full_path = os.path.join(root, basename + EXE_SFX) + if os.path.exists(full_path): + return full_path + return name + + +def main(args): + if args: + print >> sys.stderr, sys.modules[__name__].__doc__, + return 2 + bootstrap(logging.DEBUG) + return 0 + + +if __name__ == '__main__': + sys.exit(main(sys.argv[1:])) diff --git a/external/boringssl/util/bot/go/env.py b/external/boringssl/util/bot/go/env.py new file mode 100755 index 0000000000..820968c9b0 --- /dev/null +++ b/external/boringssl/util/bot/go/env.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Modified from go/env.py in Chromium infrastructure's repository to patch out +# everything but the core toolchain. +# +# https://chromium.googlesource.com/infra/infra/ + +"""Can be used to point environment variable to hermetic Go toolset. + +Usage (on linux and mac): +$ eval `./env.py` +$ go version + +Or it can be used to wrap a command: + +$ ./env.py go version +""" + +assert __name__ == '__main__' + +import imp +import os +import subprocess +import sys + +# Do not want to mess with sys.path, load the module directly. +bootstrap = imp.load_source( + 'bootstrap', os.path.join(os.path.dirname(__file__), 'bootstrap.py')) + +old = os.environ.copy() +new = bootstrap.prepare_go_environ() + +if len(sys.argv) == 1: + for key, value in sorted(new.iteritems()): + if old.get(key) != value: + print 'export %s="%s"' % (key, value) +else: + exe = sys.argv[1] + if exe == 'python': + exe = sys.executable + else: + # Help Windows to find the executable in new PATH, do it only when + # executable is referenced by name (and not by path). + if os.sep not in exe: + exe = bootstrap.find_executable(exe, [bootstrap.WORKSPACE]) + sys.exit(subprocess.call([exe] + sys.argv[2:], env=new)) diff --git a/external/boringssl/util/bot/perl-win32.zip.sha1 b/external/boringssl/util/bot/perl-win32.zip.sha1 new file mode 100644 index 0000000000..8874fbbb69 --- /dev/null +++ b/external/boringssl/util/bot/perl-win32.zip.sha1 @@ -0,0 +1 @@ +3db2b4964d56f6e23cc48ced40a6cee05419a0af \ No newline at end of file diff --git a/external/boringssl/util/bot/update_clang.py b/external/boringssl/util/bot/update_clang.py new file mode 100644 index 0000000000..e48a287119 --- /dev/null +++ b/external/boringssl/util/bot/update_clang.py @@ -0,0 +1,71 @@ +# Copyright (c) 2015, Google Inc. +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import os.path +import shutil +import sys +import tarfile +import tempfile +import urllib + +# CLANG_REVISION and CLANG_SUB_REVISION determine the build of clang +# to use. These should be synced with tools/clang/scripts/update.py in +# Chromium. +CLANG_REVISION = "267383" +CLANG_SUB_REVISION = "1" + +PACKAGE_VERSION = "%s-%s" % (CLANG_REVISION, CLANG_SUB_REVISION) +LLVM_BUILD_DIR = os.path.join(os.path.dirname(__file__), "llvm-build") +STAMP_FILE = os.path.join(LLVM_BUILD_DIR, "cr_build_revision") + +CDS_URL = "https://commondatastorage.googleapis.com/chromium-browser-clang" + +def DownloadFile(url, path): + """DownloadFile fetches |url| to |path|.""" + last_progress = [0] + def report(a, b, c): + progress = int(a * b * 100.0 / c) + if progress != last_progress[0]: + print >> sys.stderr, "Downloading... %d%%" % progress + last_progress[0] = progress + urllib.urlretrieve(url, path, reporthook=report) + +def main(args): + # For now, only download clang on Linux. + if not sys.platform.startswith("linux"): + return 0 + + if os.path.exists(STAMP_FILE): + with open(STAMP_FILE) as f: + if f.read().strip() == PACKAGE_VERSION: + print >> sys.stderr, "Clang already at %s" % (PACKAGE_VERSION,) + return 0 + + if os.path.exists(LLVM_BUILD_DIR): + shutil.rmtree(LLVM_BUILD_DIR) + + print >> sys.stderr, "Downloading Clang %s" % (PACKAGE_VERSION,) + cds_full_url = "%s/Linux_x64/clang-%s.tgz" % (CDS_URL, PACKAGE_VERSION) + with tempfile.NamedTemporaryFile() as temp: + DownloadFile(cds_full_url, temp.name) + with tarfile.open(temp.name, "r:gz") as tar_file: + tar_file.extractall(LLVM_BUILD_DIR) + + with open(STAMP_FILE, "wb") as stamp_file: + stamp_file.write(PACKAGE_VERSION) + + return 0 + +if __name__ == "__main__": + sys.exit(main(sys.argv[1:])) diff --git a/external/boringssl/util/bot/vs_env.py b/external/boringssl/util/bot/vs_env.py new file mode 100644 index 0000000000..184750063f --- /dev/null +++ b/external/boringssl/util/bot/vs_env.py @@ -0,0 +1,37 @@ +# Copyright (c) 2015, Google Inc. +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import subprocess +import sys + +import vs_toolchain +# vs_toolchain adds gyp to sys.path. +import gyp.MSVSVersion + +if len(sys.argv) < 2: + print >>sys.stderr, "Usage: vs_env.py TARGET_ARCH CMD..." + sys.exit(1) + +target_arch = sys.argv[1] +cmd = sys.argv[2:] + +vs_toolchain.SetEnvironmentAndGetRuntimeDllDirs() +vs_version = gyp.MSVSVersion.SelectVisualStudioVersion() + +# Using shell=True is somewhat ugly, but the alternative is to pull in a copy +# of the Chromium GN build's setup_toolchain.py which runs the setup script, +# then 'set', and then parses the environment variables out. (GYP internally +# does the same thing.) +sys.exit(subprocess.call(vs_version.SetupScript(target_arch) + ["&&"] + cmd, + shell=True)) diff --git a/external/boringssl/util/bot/vs_toolchain.py b/external/boringssl/util/bot/vs_toolchain.py new file mode 100644 index 0000000000..f90bb466ad --- /dev/null +++ b/external/boringssl/util/bot/vs_toolchain.py @@ -0,0 +1,113 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import json +import os +import pipes +import shutil +import subprocess +import sys + + +script_dir = os.path.dirname(os.path.realpath(__file__)) +sys.path.insert(0, os.path.join(script_dir, 'gyp', 'pylib')) +json_data_file = os.path.join(script_dir, 'win_toolchain.json') + + +import gyp + + +TOOLCHAIN_VERSION = '2015' +TOOLCHAIN_HASH = '95ddda401ec5678f15eeed01d2bee08fcbc5ee97' + + +def SetEnvironmentAndGetRuntimeDllDirs(): + """Sets up os.environ to use the depot_tools VS toolchain with gyp, and + returns the location of the VS runtime DLLs so they can be copied into + the output directory after gyp generation. + """ + vs_runtime_dll_dirs = None + depot_tools_win_toolchain = \ + bool(int(os.environ.get('DEPOT_TOOLS_WIN_TOOLCHAIN', '1'))) + if sys.platform in ('win32', 'cygwin') and depot_tools_win_toolchain: + if not os.path.exists(json_data_file): + Update() + with open(json_data_file, 'r') as tempf: + toolchain_data = json.load(tempf) + + toolchain = toolchain_data['path'] + version = toolchain_data['version'] + win_sdk = toolchain_data.get('win_sdk') + if not win_sdk: + win_sdk = toolchain_data['win8sdk'] + wdk = toolchain_data['wdk'] + # TODO(scottmg): The order unfortunately matters in these. They should be + # split into separate keys for x86 and x64. (See CopyVsRuntimeDlls call + # below). http://crbug.com/345992 + vs_runtime_dll_dirs = toolchain_data['runtime_dirs'] + + os.environ['GYP_MSVS_OVERRIDE_PATH'] = toolchain + os.environ['GYP_MSVS_VERSION'] = version + # We need to make sure windows_sdk_path is set to the automated + # toolchain values in GYP_DEFINES, but don't want to override any + # otheroptions.express + # values there. + gyp_defines_dict = gyp.NameValueListToDict(gyp.ShlexEnv('GYP_DEFINES')) + gyp_defines_dict['windows_sdk_path'] = win_sdk + os.environ['GYP_DEFINES'] = ' '.join('%s=%s' % (k, pipes.quote(str(v))) + for k, v in gyp_defines_dict.iteritems()) + os.environ['WINDOWSSDKDIR'] = win_sdk + os.environ['WDK_DIR'] = wdk + # Include the VS runtime in the PATH in case it's not machine-installed. + runtime_path = ';'.join(vs_runtime_dll_dirs) + os.environ['PATH'] = runtime_path + ';' + os.environ['PATH'] + return vs_runtime_dll_dirs + + +def FindDepotTools(): + """Returns the path to depot_tools in $PATH.""" + for path in os.environ['PATH'].split(os.pathsep): + if os.path.isfile(os.path.join(path, 'gclient.py')): + return path + raise Exception("depot_tools not found!") + + +def Update(): + """Requests an update of the toolchain to the specific hashes we have at + this revision. The update outputs a .json of the various configuration + information required to pass to gyp which we use in |GetToolchainDir()|. + """ + depot_tools_win_toolchain = \ + bool(int(os.environ.get('DEPOT_TOOLS_WIN_TOOLCHAIN', '1'))) + if sys.platform in ('win32', 'cygwin') and depot_tools_win_toolchain: + depot_tools_path = FindDepotTools() + # Necessary so that get_toolchain_if_necessary.py will put the VS toolkit + # in the correct directory. + os.environ['GYP_MSVS_VERSION'] = TOOLCHAIN_VERSION + get_toolchain_args = [ + sys.executable, + os.path.join(depot_tools_path, + 'win_toolchain', + 'get_toolchain_if_necessary.py'), + '--output-json', json_data_file, TOOLCHAIN_HASH, + ] + subprocess.check_call(get_toolchain_args) + + return 0 + + +def main(): + if not sys.platform.startswith(('win32', 'cygwin')): + return 0 + commands = { + 'update': Update, + } + if len(sys.argv) < 2 or sys.argv[1] not in commands: + print >>sys.stderr, 'Expected one of: %s' % ', '.join(commands) + return 1 + return commands[sys.argv[1]](*sys.argv[2:]) + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/external/boringssl/util/bot/yasm-win32.exe.sha1 b/external/boringssl/util/bot/yasm-win32.exe.sha1 new file mode 100644 index 0000000000..5b8c9aaebf --- /dev/null +++ b/external/boringssl/util/bot/yasm-win32.exe.sha1 @@ -0,0 +1 @@ +4c4d1951181a610923523cb10d83d9ae9952fbf3 \ No newline at end of file diff --git a/external/boringssl/util/doc.config b/external/boringssl/util/doc.config new file mode 100644 index 0000000000..e7cfa82d62 --- /dev/null +++ b/external/boringssl/util/doc.config @@ -0,0 +1,58 @@ +{ + "BaseDirectory": "..", + "Sections": [{ + "Name": "Low-level infrastructure", + "Headers": [ + "include/openssl/base64.h", + "include/openssl/bio.h", + "include/openssl/buf.h", + "include/openssl/bytestring.h", + "include/openssl/err.h", + "include/openssl/cpu.h", + "include/openssl/crypto.h", + "include/openssl/ex_data.h", + "include/openssl/lhash.h", + "include/openssl/mem.h", + "include/openssl/obj.h", + "include/openssl/rand.h", + "include/openssl/stack.h", + "include/openssl/time_support.h" + ] + },{ + "Name": "Low-level crypto primitives", + "Headers": [ + "include/openssl/aes.h", + "include/openssl/bn.h", + "include/openssl/cmac.h", + "include/openssl/curve25519.h", + "include/openssl/des.h", + "include/openssl/dh.h", + "include/openssl/dsa.h", + "include/openssl/ec.h", + "include/openssl/ec_key.h", + "include/openssl/ecdh.h", + "include/openssl/ecdsa.h", + "include/openssl/engine.h", + "include/openssl/hkdf.h", + "include/openssl/hmac.h", + "include/openssl/md5.h", + "include/openssl/newhope.h", + "include/openssl/rc4.h", + "include/openssl/rsa.h", + "include/openssl/sha.h" + ] + },{ + "Name": "Crypto interfaces", + "Headers": [ + "include/openssl/digest.h", + "include/openssl/cipher.h", + "include/openssl/aead.h", + "include/openssl/evp.h" + ] + },{ + "Name": "SSL implementation", + "Headers": [ + "include/openssl/ssl.h" + ] + }] +} diff --git a/external/boringssl/util/doc.css b/external/boringssl/util/doc.css new file mode 100644 index 0000000000..a868e44445 --- /dev/null +++ b/external/boringssl/util/doc.css @@ -0,0 +1,70 @@ +#main { + margin-left: auto; + margin-right: auto; + max-width: 55em; + text-align: justify; +} + +h2 { + font-family: monospace; + background-color: #b2c9db; + padding: 7px; + border-radius: 7px; +} + +div.title { + margin-bottom: 2em; +} + +ol { + list-style: none; + margin-bottom: 4em; +} + +li a { + color: black; +} + +li.header { + margin-top: 1em; + margin-bottom: 0.3em; + font-weight: bold; +} + +div.decl p:first-child { + margin-top: 2.5em; +} + +div.decl p:first-child .first-word { + font-weight: bold; + font-family: monospace; +} + +.sectionpreamble { + margin-top: 5em; +} + +.sectionpreamble p:first-child { + font-weight: bold; + font-size: 1.5em; +} + +.section pre { + background-color: #b2c9db; + padding: 5px; + border-radius: 5px; +} + +td { + padding: 2px; +} + +tr:nth-child(even) { + background-color: #eee; +} + +tr.header td { + font-weight: bold; + padding-top: 1em; + padding-bottom: 0.5em; +} diff --git a/external/boringssl/util/doc.go b/external/boringssl/util/doc.go new file mode 100644 index 0000000000..681b8349e3 --- /dev/null +++ b/external/boringssl/util/doc.go @@ -0,0 +1,728 @@ +// doc generates HTML files from the comments in header files. +// +// doc expects to be given the path to a JSON file via the --config option. +// From that JSON (which is defined by the Config struct) it reads a list of +// header file locations and generates HTML files for each in the current +// directory. + +package main + +import ( + "bufio" + "encoding/json" + "errors" + "flag" + "fmt" + "html/template" + "io/ioutil" + "os" + "path/filepath" + "strings" +) + +// Config describes the structure of the config JSON file. +type Config struct { + // BaseDirectory is a path to which other paths in the file are + // relative. + BaseDirectory string + Sections []ConfigSection +} + +type ConfigSection struct { + Name string + // Headers is a list of paths to header files. + Headers []string +} + +// HeaderFile is the internal representation of a header file. +type HeaderFile struct { + // Name is the basename of the header file (e.g. "ex_data.html"). + Name string + // Preamble contains a comment for the file as a whole. Each string + // is a separate paragraph. + Preamble []string + Sections []HeaderSection + // AllDecls maps all decls to their URL fragments. + AllDecls map[string]string +} + +type HeaderSection struct { + // Preamble contains a comment for a group of functions. + Preamble []string + Decls []HeaderDecl + // Anchor, if non-empty, is the URL fragment to use in anchor tags. + Anchor string + // IsPrivate is true if the section contains private functions (as + // indicated by its name). + IsPrivate bool +} + +type HeaderDecl struct { + // Comment contains a comment for a specific function. Each string is a + // paragraph. Some paragraph may contain \n runes to indicate that they + // are preformatted. + Comment []string + // Name contains the name of the function, if it could be extracted. + Name string + // Decl contains the preformatted C declaration itself. + Decl string + // Anchor, if non-empty, is the URL fragment to use in anchor tags. + Anchor string +} + +const ( + cppGuard = "#if defined(__cplusplus)" + commentStart = "/* " + commentEnd = " */" +) + +func extractComment(lines []string, lineNo int) (comment []string, rest []string, restLineNo int, err error) { + if len(lines) == 0 { + return nil, lines, lineNo, nil + } + + restLineNo = lineNo + rest = lines + + if !strings.HasPrefix(rest[0], commentStart) { + panic("extractComment called on non-comment") + } + commentParagraph := rest[0][len(commentStart):] + rest = rest[1:] + restLineNo++ + + for len(rest) > 0 { + i := strings.Index(commentParagraph, commentEnd) + if i >= 0 { + if i != len(commentParagraph)-len(commentEnd) { + err = fmt.Errorf("garbage after comment end on line %d", restLineNo) + return + } + commentParagraph = commentParagraph[:i] + if len(commentParagraph) > 0 { + comment = append(comment, commentParagraph) + } + return + } + + line := rest[0] + if !strings.HasPrefix(line, " *") { + err = fmt.Errorf("comment doesn't start with block prefix on line %d: %s", restLineNo, line) + return + } + if len(line) == 2 || line[2] != '/' { + line = line[2:] + } + if strings.HasPrefix(line, " ") { + /* Identing the lines of a paragraph marks them as + * preformatted. */ + if len(commentParagraph) > 0 { + commentParagraph += "\n" + } + line = line[3:] + } + if len(line) > 0 { + commentParagraph = commentParagraph + line + if len(commentParagraph) > 0 && commentParagraph[0] == ' ' { + commentParagraph = commentParagraph[1:] + } + } else { + comment = append(comment, commentParagraph) + commentParagraph = "" + } + rest = rest[1:] + restLineNo++ + } + + err = errors.New("hit EOF in comment") + return +} + +func extractDecl(lines []string, lineNo int) (decl string, rest []string, restLineNo int, err error) { + if len(lines) == 0 { + return "", lines, lineNo, nil + } + + rest = lines + restLineNo = lineNo + + var stack []rune + for len(rest) > 0 { + line := rest[0] + for _, c := range line { + switch c { + case '(', '{', '[': + stack = append(stack, c) + case ')', '}', ']': + if len(stack) == 0 { + err = fmt.Errorf("unexpected %c on line %d", c, restLineNo) + return + } + var expected rune + switch c { + case ')': + expected = '(' + case '}': + expected = '{' + case ']': + expected = '[' + default: + panic("internal error") + } + if last := stack[len(stack)-1]; last != expected { + err = fmt.Errorf("found %c when expecting %c on line %d", c, last, restLineNo) + return + } + stack = stack[:len(stack)-1] + } + } + if len(decl) > 0 { + decl += "\n" + } + decl += line + rest = rest[1:] + restLineNo++ + + if len(stack) == 0 && (len(decl) == 0 || decl[len(decl)-1] != '\\') { + break + } + } + + return +} + +func skipLine(s string) string { + i := strings.Index(s, "\n") + if i > 0 { + return s[i:] + } + return "" +} + +func getNameFromDecl(decl string) (string, bool) { + for strings.HasPrefix(decl, "#if") || strings.HasPrefix(decl, "#elif") { + decl = skipLine(decl) + } + + if strings.HasPrefix(decl, "typedef ") { + return "", false + } + + for _, prefix := range []string{"struct ", "enum ", "#define "} { + if !strings.HasPrefix(decl, prefix) { + continue + } + + decl = strings.TrimPrefix(decl, prefix) + + for len(decl) > 0 && decl[0] == ' ' { + decl = decl[1:] + } + + // struct and enum types can be the return type of a + // function. + if prefix[0] != '#' && strings.Index(decl, "{") == -1 { + break + } + + i := strings.IndexAny(decl, "( ") + if i < 0 { + return "", false + } + return decl[:i], true + } + decl = strings.TrimPrefix(decl, "OPENSSL_EXPORT ") + decl = strings.TrimPrefix(decl, "STACK_OF(") + decl = strings.TrimPrefix(decl, "LHASH_OF(") + i := strings.Index(decl, "(") + if i < 0 { + return "", false + } + j := strings.LastIndex(decl[:i], " ") + if j < 0 { + return "", false + } + for j+1 < len(decl) && decl[j+1] == '*' { + j++ + } + return decl[j+1 : i], true +} + +func sanitizeAnchor(name string) string { + return strings.Replace(name, " ", "-", -1) +} + +func isPrivateSection(name string) bool { + return strings.HasPrefix(name, "Private functions") || strings.HasPrefix(name, "Private structures") || strings.Contains(name, "(hidden)") +} + +func (config *Config) parseHeader(path string) (*HeaderFile, error) { + headerPath := filepath.Join(config.BaseDirectory, path) + + headerFile, err := os.Open(headerPath) + if err != nil { + return nil, err + } + defer headerFile.Close() + + scanner := bufio.NewScanner(headerFile) + var lines, oldLines []string + for scanner.Scan() { + lines = append(lines, scanner.Text()) + } + if err := scanner.Err(); err != nil { + return nil, err + } + + lineNo := 1 + found := false + for i, line := range lines { + if line == cppGuard { + lines = lines[i+1:] + lineNo += i + 1 + found = true + break + } + } + + if !found { + return nil, errors.New("no C++ guard found") + } + + if len(lines) == 0 || lines[0] != "extern \"C\" {" { + return nil, errors.New("no extern \"C\" found after C++ guard") + } + lineNo += 2 + lines = lines[2:] + + header := &HeaderFile{ + Name: filepath.Base(path), + AllDecls: make(map[string]string), + } + + for i, line := range lines { + if len(line) > 0 { + lines = lines[i:] + lineNo += i + break + } + } + + oldLines = lines + if len(lines) > 0 && strings.HasPrefix(lines[0], commentStart) { + comment, rest, restLineNo, err := extractComment(lines, lineNo) + if err != nil { + return nil, err + } + + if len(rest) > 0 && len(rest[0]) == 0 { + if len(rest) < 2 || len(rest[1]) != 0 { + return nil, errors.New("preamble comment should be followed by two blank lines") + } + header.Preamble = comment + lineNo = restLineNo + 2 + lines = rest[2:] + } else { + lines = oldLines + } + } + + allAnchors := make(map[string]struct{}) + + for { + // Start of a section. + if len(lines) == 0 { + return nil, errors.New("unexpected end of file") + } + line := lines[0] + if line == cppGuard { + break + } + + if len(line) == 0 { + return nil, fmt.Errorf("blank line at start of section on line %d", lineNo) + } + + var section HeaderSection + + if strings.HasPrefix(line, commentStart) { + comment, rest, restLineNo, err := extractComment(lines, lineNo) + if err != nil { + return nil, err + } + if len(rest) > 0 && len(rest[0]) == 0 { + anchor := sanitizeAnchor(firstSentence(comment)) + if len(anchor) > 0 { + if _, ok := allAnchors[anchor]; ok { + return nil, fmt.Errorf("duplicate anchor: %s", anchor) + } + allAnchors[anchor] = struct{}{} + } + + section.Preamble = comment + section.IsPrivate = len(comment) > 0 && isPrivateSection(comment[0]) + section.Anchor = anchor + lines = rest[1:] + lineNo = restLineNo + 1 + } + } + + for len(lines) > 0 { + line := lines[0] + if len(line) == 0 { + lines = lines[1:] + lineNo++ + break + } + if line == cppGuard { + return nil, errors.New("hit ending C++ guard while in section") + } + + var comment []string + var decl string + if strings.HasPrefix(line, commentStart) { + comment, lines, lineNo, err = extractComment(lines, lineNo) + if err != nil { + return nil, err + } + } + if len(lines) == 0 { + return nil, errors.New("expected decl at EOF") + } + declLineNo := lineNo + decl, lines, lineNo, err = extractDecl(lines, lineNo) + if err != nil { + return nil, err + } + name, ok := getNameFromDecl(decl) + if !ok { + name = "" + } + if last := len(section.Decls) - 1; len(name) == 0 && len(comment) == 0 && last >= 0 { + section.Decls[last].Decl += "\n" + decl + } else { + // As a matter of style, comments should start + // with the name of the thing that they are + // commenting on. We make an exception here for + // #defines (because we often have blocks of + // them) and collective comments, which are + // detected by starting with “The†or “Theseâ€. + if len(comment) > 0 && + !strings.HasPrefix(comment[0], name) && + !strings.HasPrefix(comment[0], "A "+name) && + !strings.HasPrefix(comment[0], "An "+name) && + !strings.HasPrefix(decl, "#define ") && + !strings.HasPrefix(comment[0], "The ") && + !strings.HasPrefix(comment[0], "These ") { + return nil, fmt.Errorf("Comment for %q doesn't seem to match line %s:%d\n", name, path, declLineNo) + } + anchor := sanitizeAnchor(name) + // TODO(davidben): Enforce uniqueness. This is + // skipped because #ifdefs currently result in + // duplicate table-of-contents entries. + allAnchors[anchor] = struct{}{} + + header.AllDecls[name] = anchor + + section.Decls = append(section.Decls, HeaderDecl{ + Comment: comment, + Name: name, + Decl: decl, + Anchor: anchor, + }) + } + + if len(lines) > 0 && len(lines[0]) == 0 { + lines = lines[1:] + lineNo++ + } + } + + header.Sections = append(header.Sections, section) + } + + return header, nil +} + +func firstSentence(paragraphs []string) string { + if len(paragraphs) == 0 { + return "" + } + s := paragraphs[0] + i := strings.Index(s, ". ") + if i >= 0 { + return s[:i] + } + if lastIndex := len(s) - 1; s[lastIndex] == '.' { + return s[:lastIndex] + } + return s +} + +func markupPipeWords(allDecls map[string]string, s string) template.HTML { + ret := "" + + for { + i := strings.Index(s, "|") + if i == -1 { + ret += s + break + } + ret += s[:i] + s = s[i+1:] + + i = strings.Index(s, "|") + j := strings.Index(s, " ") + if i > 0 && (j == -1 || j > i) { + ret += "" + anchor, isLink := allDecls[s[:i]] + if isLink { + ret += fmt.Sprintf("", template.HTMLEscapeString(anchor)) + } + ret += s[:i] + if isLink { + ret += "" + } + ret += "" + s = s[i+1:] + } else { + ret += "|" + } + } + + return template.HTML(ret) +} + +func markupFirstWord(s template.HTML) template.HTML { + start := 0 +again: + end := strings.Index(string(s[start:]), " ") + if end > 0 { + end += start + w := strings.ToLower(string(s[start:end])) + // The first word was already marked up as an HTML tag. Don't + // mark it up further. + if strings.ContainsRune(w, '<') { + return s + } + if w == "a" || w == "an" { + start = end + 1 + goto again + } + return s[:start] + "" + s[start:end] + "" + s[end:] + } + return s +} + +func newlinesToBR(html template.HTML) template.HTML { + s := string(html) + if !strings.Contains(s, "\n") { + return html + } + s = strings.Replace(s, "\n", "
", -1) + s = strings.Replace(s, " ", " ", -1) + return template.HTML(s) +} + +func generate(outPath string, config *Config) (map[string]string, error) { + allDecls := make(map[string]string) + + headerTmpl := template.New("headerTmpl") + headerTmpl.Funcs(template.FuncMap{ + "firstSentence": firstSentence, + "markupPipeWords": func(s string) template.HTML { return markupPipeWords(allDecls, s) }, + "markupFirstWord": markupFirstWord, + "newlinesToBR": newlinesToBR, + }) + headerTmpl, err := headerTmpl.Parse(` + + + BoringSSL - {{.Name}} + + + + + +
+
+

{{.Name}}

+ All headers +
+ + {{range .Preamble}}

{{. | html | markupPipeWords}}

{{end}} + +
    + {{range .Sections}} + {{if not .IsPrivate}} + {{if .Anchor}}
  1. {{.Preamble | firstSentence | html | markupPipeWords}}
  2. {{end}} + {{range .Decls}} + {{if .Anchor}}
  3. {{.Name}}
  4. {{end}} + {{end}} + {{end}} + {{end}} +
+ + {{range .Sections}} + {{if not .IsPrivate}} +
+ {{if .Preamble}} +
+ {{range .Preamble}}

{{. | html | markupPipeWords}}

{{end}} +
+ {{end}} + + {{range .Decls}} +
+ {{range .Comment}} +

{{. | html | markupPipeWords | newlinesToBR | markupFirstWord}}

+ {{end}} +
{{.Decl}}
+
+ {{end}} +
+ {{end}} + {{end}} +
+ +`) + if err != nil { + return nil, err + } + + headerDescriptions := make(map[string]string) + var headers []*HeaderFile + + for _, section := range config.Sections { + for _, headerPath := range section.Headers { + header, err := config.parseHeader(headerPath) + if err != nil { + return nil, errors.New("while parsing " + headerPath + ": " + err.Error()) + } + headerDescriptions[header.Name] = firstSentence(header.Preamble) + headers = append(headers, header) + + for name, anchor := range header.AllDecls { + allDecls[name] = fmt.Sprintf("%s#%s", header.Name+".html", anchor) + } + } + } + + for _, header := range headers { + filename := filepath.Join(outPath, header.Name+".html") + file, err := os.OpenFile(filename, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666) + if err != nil { + panic(err) + } + defer file.Close() + if err := headerTmpl.Execute(file, header); err != nil { + return nil, err + } + } + + return headerDescriptions, nil +} + +func generateIndex(outPath string, config *Config, headerDescriptions map[string]string) error { + indexTmpl := template.New("indexTmpl") + indexTmpl.Funcs(template.FuncMap{ + "baseName": filepath.Base, + "headerDescription": func(header string) string { + return headerDescriptions[header] + }, + }) + indexTmpl, err := indexTmpl.Parse(` + + + BoringSSL - Headers + + + + + +
+
+

BoringSSL Headers

+
+ + {{range .Sections}} + + {{range .Headers}} + + {{end}} + {{end}} +
{{.Name}}
{{. | baseName}}{{. | baseName | headerDescription}}
+
+ +`) + + if err != nil { + return err + } + + file, err := os.OpenFile(filepath.Join(outPath, "headers.html"), os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666) + if err != nil { + panic(err) + } + defer file.Close() + + if err := indexTmpl.Execute(file, config); err != nil { + return err + } + + return nil +} + +func copyFile(outPath string, inFilePath string) error { + bytes, err := ioutil.ReadFile(inFilePath) + if err != nil { + return err + } + return ioutil.WriteFile(filepath.Join(outPath, filepath.Base(inFilePath)), bytes, 0666) +} + +func main() { + var ( + configFlag *string = flag.String("config", "doc.config", "Location of config file") + outputDir *string = flag.String("out", ".", "Path to the directory where the output will be written") + config Config + ) + + flag.Parse() + + if len(*configFlag) == 0 { + fmt.Printf("No config file given by --config\n") + os.Exit(1) + } + + if len(*outputDir) == 0 { + fmt.Printf("No output directory given by --out\n") + os.Exit(1) + } + + configBytes, err := ioutil.ReadFile(*configFlag) + if err != nil { + fmt.Printf("Failed to open config file: %s\n", err) + os.Exit(1) + } + + if err := json.Unmarshal(configBytes, &config); err != nil { + fmt.Printf("Failed to parse config file: %s\n", err) + os.Exit(1) + } + + headerDescriptions, err := generate(*outputDir, &config) + if err != nil { + fmt.Printf("Failed to generate output: %s\n", err) + os.Exit(1) + } + + if err := generateIndex(*outputDir, &config, headerDescriptions); err != nil { + fmt.Printf("Failed to generate index: %s\n", err) + os.Exit(1) + } + + if err := copyFile(*outputDir, "doc.css"); err != nil { + fmt.Printf("Failed to copy static file: %s\n", err) + os.Exit(1) + } +} diff --git a/external/boringssl/util/generate-asm-lcov.py b/external/boringssl/util/generate-asm-lcov.py new file mode 100755 index 0000000000..257ae841c3 --- /dev/null +++ b/external/boringssl/util/generate-asm-lcov.py @@ -0,0 +1,152 @@ +#!/usr/bin/python +# Copyright (c) 2016, Google Inc. +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +import os +import os.path +import subprocess +import sys + +# The LCOV output format for each source file is: +# +# SF: +# DA:, +# ... +# end_of_record +# +# The can either be 0 for an unexecuted instruction or a +# value representing the number of executions. The DA line should be omitted +# for lines not representing an instruction. + +SECTION_SEPERATOR = '-' * 80 + +def is_asm(l): + """Returns whether a line should be considered to be an instruction.""" + l = l.strip() + # Empty lines + if l == '': + return False + # Comments + if l.startswith('#'): + return False + # Assembly Macros + if l.startswith('.'): + return False + # Label + if l.endswith(':'): + return False + return True + +def merge(callgrind_files, srcs): + """Calls callgrind_annotate over the set of callgrind output + |callgrind_files| using the sources |srcs| and merges the results + together.""" + out = '' + for file in callgrind_files: + data = subprocess.check_output(['callgrind_annotate', file] + srcs) + out += '%s\n%s\n' % (data, SECTION_SEPERATOR) + return out + +def parse(filename, data, current): + """Parses an annotated execution flow |data| from callgrind_annotate for + source |filename| and updates the current execution counts from |current|.""" + with open(filename) as f: + source = f.read().split('\n') + + out = current + if out == None: + out = [0 if is_asm(l) else None for l in source] + + # Lines are of the following formats: + # -- line: Indicates that analysis continues from a different place. + # Ir : Indicates the start of a file. + # => : Indicates a call/jump in the control flow. + # : Indicates that the line has been executed that many times. + line = None + for l in data: + l = l.strip() + ' ' + if l.startswith('-- line'): + line = int(l.split(' ')[2]) - 1 + elif l.strip() == 'Ir': + line = 0 + elif line != None and l.strip() and '=>' not in l and 'unidentified lines' not in l: + count = l.split(' ')[0].replace(',', '').replace('.', '0') + instruction = l.split(' ', 1)[1].strip() + if count != '0' or is_asm(instruction): + if out[line] == None: + out[line] = 0 + out[line] += int(count) + line += 1 + + return out + + +def generate(data): + """Parses the merged callgrind_annotate output |data| and generates execution + counts for all annotated files.""" + out = {} + data = [p.strip() for p in data.split(SECTION_SEPERATOR)] + + + # Most sections are ignored, but a section with: + # User-annotated source: + # precedes a listing of execution count for that . + for i in range(len(data)): + if 'User-annotated source' in data[i] and i < len(data) - 1: + filename = data[i].split(':', 1)[1].strip() + res = data[i + 1] + if filename not in out: + out[filename] = None + if 'No information' in res: + res = [] + else: + res = res.split('\n') + out[filename] = parse(filename, res, out[filename]) + return out + +def output(data): + """Takes a dictionary |data| of filenames and execution counts and generates + a LCOV coverage output.""" + out = '' + for filename, counts in data.iteritems(): + out += 'SF:%s\n' % (os.path.abspath(filename)) + for line, count in enumerate(counts): + if count != None: + out += 'DA:%d,%s\n' % (line + 1, count) + out += 'end_of_record\n' + return out + +if __name__ == '__main__': + if len(sys.argv) != 3: + print '%s ' % (__file__) + sys.exit() + + cg_folder = sys.argv[1] + build_folder = sys.argv[2] + + cg_files = [] + for (cwd, _, files) in os.walk(cg_folder): + for f in files: + if f.startswith('callgrind.out'): + cg_files.append(os.path.abspath(os.path.join(cwd, f))) + + srcs = [] + for (cwd, _, files) in os.walk(build_folder): + for f in files: + fn = os.path.join(cwd, f) + if fn.endswith('.S'): + srcs.append(fn) + + annotated = merge(cg_files, srcs) + lcov = generate(annotated) + print output(lcov) diff --git a/external/boringssl/util/generate-coverage.sh b/external/boringssl/util/generate-coverage.sh new file mode 100755 index 0000000000..2fbe6b8378 --- /dev/null +++ b/external/boringssl/util/generate-coverage.sh @@ -0,0 +1,60 @@ +#!/bin/sh +# Copyright (c) 2016, Google Inc. +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +set -xe + +SRC=$PWD + +BUILD=$(mktemp -d '/tmp/boringssl.XXXXXX') +BUILD_SRC=$(mktemp -d '/tmp/boringssl-src.XXXXXX') +LCOV=$(mktemp -d '/tmp/boringssl-lcov.XXXXXX') + +if [ -n "$1" ]; then + LCOV=$(readlink -f "$1") + mkdir -p "$LCOV" +fi + +cd "$BUILD" +cmake "$SRC" -GNinja -DCMAKE_C_FLAGS='-fprofile-arcs -ftest-coverage' \ + -DCMAKE_CXX_FLAGS='-fprofile-arcs -ftest-coverage' -DCMAKE_ASM_FLAGS='-Wa,-g' +ninja + +cp -r "$SRC/crypto" "$SRC/decrepit" "$SRC/include" "$SRC/ssl" "$SRC/tool" \ + "$BUILD_SRC" +cp -r "$BUILD"/* "$BUILD_SRC" +mkdir "$BUILD/callgrind/" + +cd "$SRC" +go run "$SRC/util/all_tests.go" -build-dir "$BUILD" -callgrind -num-workers 16 +util/generate-asm-lcov.py "$BUILD/callgrind" "$BUILD" > "$BUILD/asm.info" + +go run "util/all_tests.go" -build-dir "$BUILD" + +cd "$SRC/ssl/test/runner" +go test -shim-path "$BUILD/ssl/test/bssl_shim" -num-workers 1 + +cd "$LCOV" +lcov -c -d "$BUILD" -b "$BUILD" -o "$BUILD/lcov.info" +lcov -r "$BUILD/lcov.info" "*_test.c" -o "$BUILD/lcov-1.info" +lcov -r "$BUILD/lcov-1.info" "*_test.cc" -o "$BUILD/lcov-2.info" +cat "$BUILD/lcov-2.info" "$BUILD/asm.info" > "$BUILD/final.info" +sed -i "s;$BUILD;$BUILD_SRC;g" "$BUILD/final.info" +sed -i "s;$SRC;$BUILD_SRC;g" "$BUILD/final.info" +genhtml -p "$BUILD_SRC" "$BUILD/final.info" + +rm -rf "$BUILD" +rm -rf "$BUILD_SRC" + +xdg-open index.html diff --git a/external/boringssl/util/generate_build_files.py b/external/boringssl/util/generate_build_files.py new file mode 100644 index 0000000000..b3db1480fe --- /dev/null +++ b/external/boringssl/util/generate_build_files.py @@ -0,0 +1,654 @@ +# Copyright (c) 2015, Google Inc. +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""Enumerates source files for consumption by various build systems.""" + +import optparse +import os +import subprocess +import sys +import json + + +# OS_ARCH_COMBOS maps from OS and platform to the OpenSSL assembly "style" for +# that platform and the extension used by asm files. +OS_ARCH_COMBOS = [ + ('linux', 'arm', 'linux32', [], 'S'), + ('linux', 'aarch64', 'linux64', [], 'S'), + ('linux', 'x86', 'elf', ['-fPIC', '-DOPENSSL_IA32_SSE2'], 'S'), + ('linux', 'x86_64', 'elf', [], 'S'), + ('mac', 'x86', 'macosx', ['-fPIC', '-DOPENSSL_IA32_SSE2'], 'S'), + ('mac', 'x86_64', 'macosx', [], 'S'), + ('win', 'x86', 'win32n', ['-DOPENSSL_IA32_SSE2'], 'asm'), + ('win', 'x86_64', 'nasm', [], 'asm'), +] + +# NON_PERL_FILES enumerates assembly files that are not processed by the +# perlasm system. +NON_PERL_FILES = { + ('linux', 'arm'): [ + 'src/crypto/curve25519/asm/x25519-asm-arm.S', + 'src/crypto/poly1305/poly1305_arm_asm.S', + ], + ('linux', 'x86_64'): [ + 'src/crypto/curve25519/asm/x25519-asm-x86_64.S', + ], + ('mac', 'x86_64'): [ + 'src/crypto/curve25519/asm/x25519-asm-x86_64.S', + ], +} + +PREFIX = None + + +def PathOf(x): + return x if not PREFIX else os.path.join(PREFIX, x) + + +class Android(object): + + def __init__(self): + self.header = \ +"""# Copyright (C) 2015 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" + + def ExtraFiles(self): + return ['android_compat_hacks.c', 'android_compat_keywrap.c'] + + def PrintVariableSection(self, out, name, files): + out.write('%s := \\\n' % name) + for f in sorted(files): + out.write(' %s\\\n' % f) + out.write('\n') + + def WriteFiles(self, files, asm_outputs): + with open('sources.mk', 'w+') as makefile: + makefile.write(self.header) + + crypto_files = files['crypto'] + self.ExtraFiles() + self.PrintVariableSection(makefile, 'crypto_sources', crypto_files) + self.PrintVariableSection(makefile, 'ssl_sources', files['ssl']) + self.PrintVariableSection(makefile, 'tool_sources', files['tool']) + + for ((osname, arch), asm_files) in asm_outputs: + self.PrintVariableSection( + makefile, '%s_%s_sources' % (osname, arch), asm_files) + + +class AndroidStandalone(Android): + """AndroidStandalone is for Android builds outside of the Android-system, i.e. + + for applications that wish wish to ship BoringSSL. + """ + + def ExtraFiles(self): + return [] + + +class Bazel(object): + """Bazel outputs files suitable for including in Bazel files.""" + + def __init__(self): + self.firstSection = True + self.header = \ +"""# This file is created by generate_build_files.py. Do not edit manually. + +""" + + def PrintVariableSection(self, out, name, files): + if not self.firstSection: + out.write('\n') + self.firstSection = False + + out.write('%s = [\n' % name) + for f in sorted(files): + out.write(' "%s",\n' % PathOf(f)) + out.write(']\n') + + def WriteFiles(self, files, asm_outputs): + with open('BUILD.generated.bzl', 'w+') as out: + out.write(self.header) + + self.PrintVariableSection(out, 'ssl_headers', files['ssl_headers']) + self.PrintVariableSection( + out, 'ssl_internal_headers', files['ssl_internal_headers']) + self.PrintVariableSection(out, 'ssl_sources', files['ssl']) + self.PrintVariableSection(out, 'crypto_headers', files['crypto_headers']) + self.PrintVariableSection( + out, 'crypto_internal_headers', files['crypto_internal_headers']) + self.PrintVariableSection(out, 'crypto_sources', files['crypto']) + self.PrintVariableSection(out, 'tool_sources', files['tool']) + + for ((osname, arch), asm_files) in asm_outputs: + self.PrintVariableSection( + out, 'crypto_sources_%s_%s' % (osname, arch), asm_files) + + with open('BUILD.generated_tests.bzl', 'w+') as out: + out.write(self.header) + + out.write('test_support_sources = [\n') + for filename in (files['test_support'] + + files['crypto_internal_headers'] + + files['ssl_internal_headers']): + if os.path.basename(filename) == 'malloc.cc': + continue + out.write(' "%s",\n' % PathOf(filename)) + + out.write(']\n\n') + + out.write('def create_tests(copts, crypto, ssl):\n') + name_counts = {} + for test in files['tests']: + name = os.path.basename(test[0]) + name_counts[name] = name_counts.get(name, 0) + 1 + + first = True + for test in files['tests']: + name = os.path.basename(test[0]) + if name_counts[name] > 1: + if '/' in test[1]: + name += '_' + os.path.splitext(os.path.basename(test[1]))[0] + else: + name += '_' + test[1].replace('-', '_') + + if not first: + out.write('\n') + first = False + + src_prefix = 'src/' + test[0] + for src in files['test']: + if src.startswith(src_prefix): + src = src + break + else: + raise ValueError("Can't find source for %s" % test[0]) + + out.write(' native.cc_test(\n') + out.write(' name = "%s",\n' % name) + out.write(' size = "small",\n') + out.write(' srcs = ["%s"] + test_support_sources,\n' % + PathOf(src)) + + data_files = [] + if len(test) > 1: + + out.write(' args = [\n') + for arg in test[1:]: + if '/' in arg: + out.write(' "$(location %s)",\n' % + PathOf(os.path.join('src', arg))) + data_files.append('src/%s' % arg) + else: + out.write(' "%s",\n' % arg) + out.write(' ],\n') + + out.write(' copts = copts,\n') + + if len(data_files) > 0: + out.write(' data = [\n') + for filename in data_files: + out.write(' "%s",\n' % PathOf(filename)) + out.write(' ],\n') + + if 'ssl/' in test[0]: + out.write(' deps = [\n') + out.write(' crypto,\n') + out.write(' ssl,\n') + out.write(' ],\n') + else: + out.write(' deps = [crypto],\n') + out.write(' )\n') + + +class GN(object): + + def __init__(self): + self.firstSection = True + self.header = \ +"""# Copyright (c) 2016 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# This file is created by generate_build_files.py. Do not edit manually. + +""" + + def PrintVariableSection(self, out, name, files): + if not self.firstSection: + out.write('\n') + self.firstSection = False + + out.write('%s = [\n' % name) + for f in sorted(files): + out.write(' "%s",\n' % f) + out.write(']\n') + + def WriteFiles(self, files, asm_outputs): + with open('BUILD.generated.gni', 'w+') as out: + out.write(self.header) + + self.PrintVariableSection(out, 'crypto_sources', files['crypto']) + self.PrintVariableSection(out, 'ssl_sources', files['ssl']) + + for ((osname, arch), asm_files) in asm_outputs: + self.PrintVariableSection( + out, 'crypto_sources_%s_%s' % (osname, arch), asm_files) + + fuzzers = [os.path.splitext(os.path.basename(fuzzer))[0] + for fuzzer in files['fuzz']] + self.PrintVariableSection(out, 'fuzzers', fuzzers) + + with open('BUILD.generated_tests.gni', 'w+') as out: + self.firstSection = True + out.write(self.header) + + self.PrintVariableSection(out, '_test_support_sources', + files['test_support']) + out.write('\n') + + out.write('template("create_tests") {\n') + + all_tests = [] + for test in sorted(files['test']): + test_name = 'boringssl_%s' % os.path.splitext(os.path.basename(test))[0] + all_tests.append(test_name) + + out.write(' executable("%s") {\n' % test_name) + out.write(' sources = [\n') + out.write(' "%s",\n' % test) + out.write(' ]\n') + out.write(' sources += _test_support_sources\n') + out.write(' if (defined(invoker.configs_exclude)) {\n') + out.write(' configs -= invoker.configs_exclude\n') + out.write(' }\n') + out.write(' configs += invoker.configs\n') + out.write(' deps = invoker.deps\n') + out.write(' }\n') + out.write('\n') + + out.write(' group(target_name) {\n') + out.write(' deps = [\n') + for test_name in sorted(all_tests): + out.write(' ":%s",\n' % test_name) + out.write(' ]\n') + out.write(' }\n') + out.write('}\n') + + +class GYP(object): + + def __init__(self): + self.header = \ +"""# Copyright (c) 2016 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# This file is created by generate_build_files.py. Do not edit manually. + +""" + + def PrintVariableSection(self, out, name, files): + out.write(' \'%s\': [\n' % name) + for f in sorted(files): + out.write(' \'%s\',\n' % f) + out.write(' ],\n') + + def WriteFiles(self, files, asm_outputs): + with open('boringssl.gypi', 'w+') as gypi: + gypi.write(self.header + '{\n \'variables\': {\n') + + self.PrintVariableSection( + gypi, 'boringssl_ssl_sources', files['ssl']) + self.PrintVariableSection( + gypi, 'boringssl_crypto_sources', files['crypto']) + + for ((osname, arch), asm_files) in asm_outputs: + self.PrintVariableSection(gypi, 'boringssl_%s_%s_sources' % + (osname, arch), asm_files) + + gypi.write(' }\n}\n') + + with open('boringssl_tests.gypi', 'w+') as test_gypi: + test_gypi.write(self.header + '{\n \'targets\': [\n') + + test_names = [] + for test in sorted(files['test']): + test_name = 'boringssl_%s' % os.path.splitext(os.path.basename(test))[0] + test_gypi.write(""" { + 'target_name': '%s', + 'type': 'executable', + 'dependencies': [ + 'boringssl.gyp:boringssl', + ], + 'sources': [ + '%s', + '<@(boringssl_test_support_sources)', + ], + # TODO(davidben): Fix size_t truncations in BoringSSL. + # https://crbug.com/429039 + 'msvs_disabled_warnings': [ 4267, ], + },\n""" % (test_name, test)) + test_names.append(test_name) + + test_names.sort() + + test_gypi.write(' ],\n \'variables\': {\n') + + self.PrintVariableSection( + test_gypi, 'boringssl_test_support_sources', files['test_support']) + + test_gypi.write(' \'boringssl_test_targets\': [\n') + + for test in sorted(test_names): + test_gypi.write(""" '%s',\n""" % test) + + test_gypi.write(' ],\n }\n}\n') + + +def FindCMakeFiles(directory): + """Returns list of all CMakeLists.txt files recursively in directory.""" + cmakefiles = [] + + for (path, _, filenames) in os.walk(directory): + for filename in filenames: + if filename == 'CMakeLists.txt': + cmakefiles.append(os.path.join(path, filename)) + + return cmakefiles + + +def NoTests(dent, is_dir): + """Filter function that can be passed to FindCFiles in order to remove test + sources.""" + if is_dir: + return dent != 'test' + return 'test.' not in dent and not dent.startswith('example_') + + +def OnlyTests(dent, is_dir): + """Filter function that can be passed to FindCFiles in order to remove + non-test sources.""" + if is_dir: + return dent != 'test' + return '_test.' in dent or dent.startswith('example_') + + +def AllFiles(dent, is_dir): + """Filter function that can be passed to FindCFiles in order to include all + sources.""" + return True + + +def SSLHeaderFiles(dent, is_dir): + return dent in ['ssl.h', 'tls1.h', 'ssl23.h', 'ssl3.h', 'dtls1.h'] + + +def FindCFiles(directory, filter_func): + """Recurses through directory and returns a list of paths to all the C source + files that pass filter_func.""" + cfiles = [] + + for (path, dirnames, filenames) in os.walk(directory): + for filename in filenames: + if not filename.endswith('.c') and not filename.endswith('.cc'): + continue + if not filter_func(filename, False): + continue + cfiles.append(os.path.join(path, filename)) + + for (i, dirname) in enumerate(dirnames): + if not filter_func(dirname, True): + del dirnames[i] + + return cfiles + + +def FindHeaderFiles(directory, filter_func): + """Recurses through directory and returns a list of paths to all the header files that pass filter_func.""" + hfiles = [] + + for (path, dirnames, filenames) in os.walk(directory): + for filename in filenames: + if not filename.endswith('.h'): + continue + if not filter_func(filename, False): + continue + hfiles.append(os.path.join(path, filename)) + + for (i, dirname) in enumerate(dirnames): + if not filter_func(dirname, True): + del dirnames[i] + + return hfiles + + +def ExtractPerlAsmFromCMakeFile(cmakefile): + """Parses the contents of the CMakeLists.txt file passed as an argument and + returns a list of all the perlasm() directives found in the file.""" + perlasms = [] + with open(cmakefile) as f: + for line in f: + line = line.strip() + if not line.startswith('perlasm('): + continue + if not line.endswith(')'): + raise ValueError('Bad perlasm line in %s' % cmakefile) + # Remove "perlasm(" from start and ")" from end + params = line[8:-1].split() + if len(params) < 2: + raise ValueError('Bad perlasm line in %s' % cmakefile) + perlasms.append({ + 'extra_args': params[2:], + 'input': os.path.join(os.path.dirname(cmakefile), params[1]), + 'output': os.path.join(os.path.dirname(cmakefile), params[0]), + }) + + return perlasms + + +def ReadPerlAsmOperations(): + """Returns a list of all perlasm() directives found in CMake config files in + src/.""" + perlasms = [] + cmakefiles = FindCMakeFiles('src') + + for cmakefile in cmakefiles: + perlasms.extend(ExtractPerlAsmFromCMakeFile(cmakefile)) + + return perlasms + + +def PerlAsm(output_filename, input_filename, perlasm_style, extra_args): + """Runs the a perlasm script and puts the output into output_filename.""" + base_dir = os.path.dirname(output_filename) + if not os.path.isdir(base_dir): + os.makedirs(base_dir) + output = subprocess.check_output( + ['perl', input_filename, perlasm_style] + extra_args) + with open(output_filename, 'w+') as out_file: + out_file.write(output) + + +def ArchForAsmFilename(filename): + """Returns the architectures that a given asm file should be compiled for + based on substrings in the filename.""" + + if 'x86_64' in filename or 'avx2' in filename: + return ['x86_64'] + elif ('x86' in filename and 'x86_64' not in filename) or '586' in filename: + return ['x86'] + elif 'armx' in filename: + return ['arm', 'aarch64'] + elif 'armv8' in filename: + return ['aarch64'] + elif 'arm' in filename: + return ['arm'] + else: + raise ValueError('Unknown arch for asm filename: ' + filename) + + +def WriteAsmFiles(perlasms): + """Generates asm files from perlasm directives for each supported OS x + platform combination.""" + asmfiles = {} + + for osarch in OS_ARCH_COMBOS: + (osname, arch, perlasm_style, extra_args, asm_ext) = osarch + key = (osname, arch) + outDir = '%s-%s' % key + + for perlasm in perlasms: + filename = os.path.basename(perlasm['input']) + output = perlasm['output'] + if not output.startswith('src'): + raise ValueError('output missing src: %s' % output) + output = os.path.join(outDir, output[4:]) + if output.endswith('-armx.${ASM_EXT}'): + output = output.replace('-armx', + '-armx64' if arch == 'aarch64' else '-armx32') + output = output.replace('${ASM_EXT}', asm_ext) + + if arch in ArchForAsmFilename(filename): + PerlAsm(output, perlasm['input'], perlasm_style, + perlasm['extra_args'] + extra_args) + asmfiles.setdefault(key, []).append(output) + + for (key, non_perl_asm_files) in NON_PERL_FILES.iteritems(): + asmfiles.setdefault(key, []).extend(non_perl_asm_files) + + return asmfiles + + +def main(platforms): + crypto_c_files = FindCFiles(os.path.join('src', 'crypto'), NoTests) + ssl_c_files = FindCFiles(os.path.join('src', 'ssl'), NoTests) + tool_c_files = FindCFiles(os.path.join('src', 'tool'), NoTests) + + # Generate err_data.c + with open('err_data.c', 'w+') as err_data: + subprocess.check_call(['go', 'run', 'err_data_generate.go'], + cwd=os.path.join('src', 'crypto', 'err'), + stdout=err_data) + crypto_c_files.append('err_data.c') + + test_support_c_files = FindCFiles(os.path.join('src', 'crypto', 'test'), + AllFiles) + test_support_h_files = ( + FindHeaderFiles(os.path.join('src', 'crypto', 'test'), AllFiles) + + FindHeaderFiles(os.path.join('src', 'ssl', 'test'), AllFiles)) + + test_c_files = FindCFiles(os.path.join('src', 'crypto'), OnlyTests) + test_c_files += FindCFiles(os.path.join('src', 'ssl'), OnlyTests) + + fuzz_c_files = FindCFiles(os.path.join('src', 'fuzz'), NoTests) + + ssl_h_files = ( + FindHeaderFiles( + os.path.join('src', 'include', 'openssl'), + SSLHeaderFiles)) + + def NotSSLHeaderFiles(filename, is_dir): + return not SSLHeaderFiles(filename, is_dir) + crypto_h_files = ( + FindHeaderFiles( + os.path.join('src', 'include', 'openssl'), + NotSSLHeaderFiles)) + + ssl_internal_h_files = FindHeaderFiles(os.path.join('src', 'ssl'), NoTests) + crypto_internal_h_files = FindHeaderFiles( + os.path.join('src', 'crypto'), NoTests) + + with open('src/util/all_tests.json', 'r') as f: + tests = json.load(f) + # Skip tests for libdecrepit. Consumers import that manually. + tests = [test for test in tests if not test[0].startswith("decrepit/")] + test_binaries = set([test[0] for test in tests]) + test_sources = set([ + test.replace('.cc', '').replace('.c', '').replace( + 'src/', + '') + for test in test_c_files]) + if test_binaries != test_sources: + print 'Test sources and configured tests do not match' + a = test_binaries.difference(test_sources) + if len(a) > 0: + print 'These tests are configured without sources: ' + str(a) + b = test_sources.difference(test_binaries) + if len(b) > 0: + print 'These test sources are not configured: ' + str(b) + + files = { + 'crypto': crypto_c_files, + 'crypto_headers': crypto_h_files, + 'crypto_internal_headers': crypto_internal_h_files, + 'fuzz': fuzz_c_files, + 'ssl': ssl_c_files, + 'ssl_headers': ssl_h_files, + 'ssl_internal_headers': ssl_internal_h_files, + 'tool': tool_c_files, + 'test': test_c_files, + 'test_support': test_support_h_files + test_support_c_files, + 'tests': tests, + } + + asm_outputs = sorted(WriteAsmFiles(ReadPerlAsmOperations()).iteritems()) + + for platform in platforms: + platform.WriteFiles(files, asm_outputs) + + return 0 + + +if __name__ == '__main__': + parser = optparse.OptionParser(usage='Usage: %prog [--prefix=]' + ' [android|android-standalone|bazel|gn|gyp]') + parser.add_option('--prefix', dest='prefix', + help='For Bazel, prepend argument to all source files') + options, args = parser.parse_args(sys.argv[1:]) + PREFIX = options.prefix + + if not args: + parser.print_help() + sys.exit(1) + + platforms = [] + for s in args: + if s == 'android': + platforms.append(Android()) + elif s == 'android-standalone': + platforms.append(AndroidStandalone()) + elif s == 'bazel': + platforms.append(Bazel()) + elif s == 'gn': + platforms.append(GN()) + elif s == 'gyp': + platforms.append(GYP()) + else: + parser.print_help() + sys.exit(1) + + sys.exit(main(platforms)) diff --git a/external/boringssl/util/make_errors.go b/external/boringssl/util/make_errors.go new file mode 100644 index 0000000000..cc35409e4d --- /dev/null +++ b/external/boringssl/util/make_errors.go @@ -0,0 +1,388 @@ +// Copyright (c) 2014, Google Inc. +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +package main + +import ( + "bufio" + "errors" + "flag" + "fmt" + "io" + "os" + "path/filepath" + "sort" + "strconv" + "strings" +) + +// ssl.h reserves values 1000 and above for error codes corresponding to +// alerts. If automatically assigned reason codes exceed this value, this script +// will error. This must be kept in sync with SSL_AD_REASON_OFFSET in ssl.h. +const reservedReasonCode = 1000 + +var resetFlag *bool = flag.Bool("reset", false, "If true, ignore current assignments and reassign from scratch") + +func makeErrors(reset bool) error { + topLevelPath, err := findToplevel() + if err != nil { + return err + } + + dirName, err := os.Getwd() + if err != nil { + return err + } + + lib := filepath.Base(dirName) + headerPath := filepath.Join(topLevelPath, "include", "openssl", lib+".h") + errDir := filepath.Join(topLevelPath, "crypto", "err") + dataPath := filepath.Join(errDir, lib+".errordata") + + headerFile, err := os.Open(headerPath) + if err != nil { + if os.IsNotExist(err) { + return fmt.Errorf("No header %s. Run in the right directory or touch the file.", headerPath) + } + + return err + } + + prefix := strings.ToUpper(lib) + reasons, err := parseHeader(prefix, headerFile) + headerFile.Close() + + if reset { + err = nil + // Retain any reason codes above reservedReasonCode. + newReasons := make(map[string]int) + for key, value := range reasons { + if value >= reservedReasonCode { + newReasons[key] = value + } + } + reasons = newReasons + } + + if err != nil { + return err + } + + dir, err := os.Open(".") + if err != nil { + return err + } + defer dir.Close() + + filenames, err := dir.Readdirnames(-1) + if err != nil { + return err + } + + for _, name := range filenames { + if !strings.HasSuffix(name, ".c") { + continue + } + + if err := addReasons(reasons, name, prefix); err != nil { + return err + } + } + + assignNewValues(reasons, reservedReasonCode) + + headerFile, err = os.Open(headerPath) + if err != nil { + return err + } + defer headerFile.Close() + + newHeaderFile, err := os.OpenFile(headerPath+".tmp", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0666) + if err != nil { + return err + } + defer newHeaderFile.Close() + + if err := writeHeaderFile(newHeaderFile, headerFile, prefix, reasons); err != nil { + return err + } + os.Rename(headerPath+".tmp", headerPath) + + dataFile, err := os.OpenFile(dataPath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644) + if err != nil { + return err + } + + outputStrings(dataFile, lib, reasons) + dataFile.Close() + + return nil +} + +func findToplevel() (path string, err error) { + path = ".." + buildingPath := filepath.Join(path, "BUILDING.md") + + _, err = os.Stat(buildingPath) + if err != nil && os.IsNotExist(err) { + path = filepath.Join("..", path) + buildingPath = filepath.Join(path, "BUILDING.md") + _, err = os.Stat(buildingPath) + } + if err != nil { + return "", errors.New("Cannot find BUILDING.md file at the top-level") + } + return path, nil +} + +type assignment struct { + key string + value int +} + +type assignmentsSlice []assignment + +func (a assignmentsSlice) Len() int { + return len(a) +} + +func (a assignmentsSlice) Less(i, j int) bool { + return a[i].value < a[j].value +} + +func (a assignmentsSlice) Swap(i, j int) { + a[i], a[j] = a[j], a[i] +} + +func outputAssignments(w io.Writer, assignments map[string]int) { + var sorted assignmentsSlice + + for key, value := range assignments { + sorted = append(sorted, assignment{key, value}) + } + + sort.Sort(sorted) + + for _, assignment := range sorted { + fmt.Fprintf(w, "#define %s %d\n", assignment.key, assignment.value) + } +} + +func parseDefineLine(line, lib string) (key string, value int, ok bool) { + if !strings.HasPrefix(line, "#define ") { + return + } + + fields := strings.Fields(line) + if len(fields) != 3 { + return + } + + key = fields[1] + if !strings.HasPrefix(key, lib+"_R_") { + return + } + + var err error + if value, err = strconv.Atoi(fields[2]); err != nil { + return + } + + ok = true + return +} + +func writeHeaderFile(w io.Writer, headerFile io.Reader, lib string, reasons map[string]int) error { + var last []byte + var haveLast, sawDefine bool + newLine := []byte("\n") + + scanner := bufio.NewScanner(headerFile) + for scanner.Scan() { + line := scanner.Text() + _, _, ok := parseDefineLine(line, lib) + if ok { + sawDefine = true + continue + } + + if haveLast { + w.Write(last) + w.Write(newLine) + } + + if len(line) > 0 || !sawDefine { + last = []byte(line) + haveLast = true + } else { + haveLast = false + } + sawDefine = false + } + + if err := scanner.Err(); err != nil { + return err + } + + outputAssignments(w, reasons) + w.Write(newLine) + + if haveLast { + w.Write(last) + w.Write(newLine) + } + + return nil +} + +func outputStrings(w io.Writer, lib string, assignments map[string]int) { + lib = strings.ToUpper(lib) + prefixLen := len(lib + "_R_") + + keys := make([]string, 0, len(assignments)) + for key := range assignments { + keys = append(keys, key) + } + sort.Strings(keys) + + for _, key := range keys { + fmt.Fprintf(w, "%s,%d,%s\n", lib, assignments[key], key[prefixLen:]) + } +} + +func assignNewValues(assignments map[string]int, reserved int) { + // Needs to be in sync with the reason limit in + // |ERR_reason_error_string|. + max := 99 + + for _, value := range assignments { + if reserved >= 0 && value >= reserved { + continue + } + if value > max { + max = value + } + } + + max++ + + // Sort the keys, so this script is reproducible. + keys := make([]string, 0, len(assignments)) + for key, value := range assignments { + if value == -1 { + keys = append(keys, key) + } + } + sort.Strings(keys) + + for _, key := range keys { + if reserved >= 0 && max >= reserved { + // If this happens, try passing -reset. Otherwise bump + // up reservedReasonCode. + panic("Automatically-assigned values exceeded limit!") + } + assignments[key] = max + max++ + } +} + +func handleDeclareMacro(line, join, macroName string, m map[string]int) { + if i := strings.Index(line, macroName); i >= 0 { + contents := line[i+len(macroName):] + if i := strings.Index(contents, ")"); i >= 0 { + contents = contents[:i] + args := strings.Split(contents, ",") + for i := range args { + args[i] = strings.TrimSpace(args[i]) + } + if len(args) != 2 { + panic("Bad macro line: " + line) + } + token := args[0] + join + args[1] + if _, ok := m[token]; !ok { + m[token] = -1 + } + } + } +} + +func addReasons(reasons map[string]int, filename, prefix string) error { + file, err := os.Open(filename) + if err != nil { + return err + } + defer file.Close() + + reasonPrefix := prefix + "_R_" + + scanner := bufio.NewScanner(file) + for scanner.Scan() { + line := scanner.Text() + + handleDeclareMacro(line, "_R_", "OPENSSL_DECLARE_ERROR_REASON(", reasons) + + for len(line) > 0 { + i := strings.Index(line, prefix+"_") + if i == -1 { + break + } + + line = line[i:] + end := strings.IndexFunc(line, func(r rune) bool { + return !(r == '_' || (r >= 'A' && r <= 'Z') || (r >= '0' && r <= '9')) + }) + if end == -1 { + end = len(line) + } + + var token string + token, line = line[:end], line[end:] + + switch { + case strings.HasPrefix(token, reasonPrefix): + if _, ok := reasons[token]; !ok { + reasons[token] = -1 + } + } + } + } + + return scanner.Err() +} + +func parseHeader(lib string, file io.Reader) (reasons map[string]int, err error) { + reasons = make(map[string]int) + + scanner := bufio.NewScanner(file) + for scanner.Scan() { + key, value, ok := parseDefineLine(scanner.Text(), lib) + if !ok { + continue + } + + reasons[key] = value + } + + err = scanner.Err() + return +} + +func main() { + flag.Parse() + + if err := makeErrors(*resetFlag); err != nil { + fmt.Fprintf(os.Stderr, "%s\n", err) + os.Exit(1) + } +} diff --git a/external/boringssl/util/run_android_tests.go b/external/boringssl/util/run_android_tests.go new file mode 100644 index 0000000000..6502a16662 --- /dev/null +++ b/external/boringssl/util/run_android_tests.go @@ -0,0 +1,315 @@ +// Copyright (c) 2016, Google Inc. +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +package main + +import ( + "bytes" + "encoding/json" + "flag" + "fmt" + "io" + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "strconv" + "strings" +) + +var ( + buildDir = flag.String("build-dir", "build", "Specifies the build directory to push.") + adbPath = flag.String("adb", "adb", "Specifies the adb binary to use. Defaults to looking in PATH.") + device = flag.String("device", "", "Specifies the device or emulator. See adb's -s argument.") + aarch64 = flag.Bool("aarch64", false, "Build the test runners for aarch64 instead of arm.") + arm = flag.Int("arm", 7, "Which arm revision to build for.") + suite = flag.String("suite", "all", "Specifies the test suites to run (all, unit, or ssl).") + allTestsArgs = flag.String("all-tests-args", "", "Specifies space-separated arguments to pass to all_tests.go") + runnerArgs = flag.String("runner-args", "", "Specifies space-separated arguments to pass to ssl/test/runner") + jsonOutput = flag.String("json-output", "", "The file to output JSON results to.") +) + +func enableUnitTests() bool { + return *suite == "all" || *suite == "unit" +} + +func enableSSLTests() bool { + return *suite == "all" || *suite == "ssl" +} + +func adb(args ...string) error { + if len(*device) > 0 { + args = append([]string{"-s", *device}, args...) + } + cmd := exec.Command(*adbPath, args...) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + return cmd.Run() +} + +func adbShell(shellCmd string) (int, error) { + var args []string + if len(*device) > 0 { + args = append([]string{"-s", *device}, args...) + } + args = append(args, "shell") + + const delimiter = "___EXIT_CODE___" + + // Older versions of adb and Android do not preserve the exit + // code, so work around this. + // https://code.google.com/p/android/issues/detail?id=3254 + shellCmd += "; echo " + delimiter + " $?" + args = append(args, shellCmd) + + cmd := exec.Command(*adbPath, args...) + stdout, err := cmd.StdoutPipe() + if err != nil { + return 0, err + } + cmd.Stderr = os.Stderr + if err := cmd.Start(); err != nil { + return 0, err + } + + var stdoutBytes bytes.Buffer + for { + var buf [1024]byte + n, err := stdout.Read(buf[:]) + stdoutBytes.Write(buf[:n]) + os.Stdout.Write(buf[:n]) + if err != nil { + break + } + } + + if err := cmd.Wait(); err != nil { + return 0, err + } + + stdoutStr := stdoutBytes.String() + idx := strings.LastIndex(stdoutStr, delimiter) + if idx < 0 { + return 0, fmt.Errorf("Could not find delimiter in output.") + } + + return strconv.Atoi(strings.TrimSpace(stdoutStr[idx+len(delimiter):])) +} + +func goTool(args ...string) error { + cmd := exec.Command("go", args...) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + + cmd.Env = os.Environ() + if *aarch64 { + cmd.Env = append(cmd.Env, "GOARCH=arm64") + } else { + cmd.Env = append(cmd.Env, "GOARCH=arm") + cmd.Env = append(cmd.Env, fmt.Sprintf("GOARM=%d", *arm)) + } + return cmd.Run() +} + +// setWorkingDirectory walks up directories as needed until the current working +// directory is the top of a BoringSSL checkout. +func setWorkingDirectory() { + for i := 0; i < 64; i++ { + if _, err := os.Stat("BUILDING.md"); err == nil { + return + } + os.Chdir("..") + } + + panic("Couldn't find BUILDING.md in a parent directory!") +} + +type test []string + +func parseTestConfig(filename string) ([]test, error) { + in, err := os.Open(filename) + if err != nil { + return nil, err + } + defer in.Close() + + decoder := json.NewDecoder(in) + var result []test + if err := decoder.Decode(&result); err != nil { + return nil, err + } + return result, nil +} + +func copyFile(dst, src string) error { + srcFile, err := os.Open(src) + if err != nil { + return err + } + defer srcFile.Close() + + srcInfo, err := srcFile.Stat() + if err != nil { + return err + } + + dir := filepath.Dir(dst) + if err := os.MkdirAll(dir, 0777); err != nil { + return err + } + + dstFile, err := os.OpenFile(dst, os.O_CREATE|os.O_WRONLY, srcInfo.Mode()) + if err != nil { + return err + } + defer dstFile.Close() + + _, err = io.Copy(dstFile, srcFile) + return err +} + +func main() { + flag.Parse() + + if *suite == "all" && *jsonOutput != "" { + fmt.Printf("To use -json-output flag, select only one test suite with -suite.\n") + os.Exit(1) + } + + setWorkingDirectory() + + // Clear the target directory. + if err := adb("shell", "rm -Rf /data/local/tmp/boringssl-tmp"); err != nil { + fmt.Printf("Failed to clear target directory: %s\n", err) + os.Exit(1) + } + + // Stage everything in a temporary directory. + tmpDir, err := ioutil.TempDir("", "boringssl-android") + if err != nil { + fmt.Printf("Error making temporary directory: %s\n", err) + os.Exit(1) + } + defer os.RemoveAll(tmpDir) + + var binaries, files []string + + if enableUnitTests() { + files = append(files, + "util/all_tests.json", + "BUILDING.md", + ) + + tests, err := parseTestConfig("util/all_tests.json") + if err != nil { + fmt.Printf("Failed to parse input: %s\n", err) + os.Exit(1) + } + + seenBinary := make(map[string]struct{}) + for _, test := range tests { + if _, ok := seenBinary[test[0]]; !ok { + binaries = append(binaries, test[0]) + seenBinary[test[0]] = struct{}{} + } + for _, arg := range test[1:] { + if strings.Contains(arg, "/") { + files = append(files, arg) + } + } + } + + fmt.Printf("Building all_tests...\n") + if err := goTool("build", "-o", filepath.Join(tmpDir, "util/all_tests"), "util/all_tests.go"); err != nil { + fmt.Printf("Error building all_tests.go: %s\n", err) + os.Exit(1) + } + } + + if enableSSLTests() { + binaries = append(binaries, "ssl/test/bssl_shim") + files = append(files, + "BUILDING.md", + "util/all_tests.json", + "ssl/test/runner/cert.pem", + "ssl/test/runner/channel_id_key.pem", + "ssl/test/runner/ecdsa_cert.pem", + "ssl/test/runner/ecdsa_key.pem", + "ssl/test/runner/key.pem", + ) + + fmt.Printf("Building runner...\n") + if err := goTool("test", "-c", "-o", filepath.Join(tmpDir, "ssl/test/runner/runner"), "./ssl/test/runner/"); err != nil { + fmt.Printf("Error building runner: %s\n", err) + os.Exit(1) + } + } + + fmt.Printf("Copying test binaries...\n") + for _, binary := range binaries { + if err := copyFile(filepath.Join(tmpDir, "build", binary), filepath.Join(*buildDir, binary)); err != nil { + fmt.Printf("Failed to copy %s: %s\n", binary, err) + os.Exit(1) + } + } + + fmt.Printf("Copying data files...\n") + for _, file := range files { + if err := copyFile(filepath.Join(tmpDir, file), file); err != nil { + fmt.Printf("Failed to copy %s: %s\n", file, err) + os.Exit(1) + } + } + + fmt.Printf("Uploading files...\n") + if err := adb("push", "-p", tmpDir, "/data/local/tmp/boringssl-tmp"); err != nil { + fmt.Printf("Failed to push runner: %s\n", err) + os.Exit(1) + } + + var unitTestExit int + if enableUnitTests() { + fmt.Printf("Running unit tests...\n") + unitTestExit, err = adbShell(fmt.Sprintf("cd /data/local/tmp/boringssl-tmp && ./util/all_tests -json-output results.json %s", *allTestsArgs)) + if err != nil { + fmt.Printf("Failed to run unit tests: %s\n", err) + os.Exit(1) + } + } + + var sslTestExit int + if enableSSLTests() { + fmt.Printf("Running SSL tests...\n") + sslTestExit, err = adbShell(fmt.Sprintf("cd /data/local/tmp/boringssl-tmp/ssl/test/runner && ./runner -json-output ../../../results.json %s", *runnerArgs)) + if err != nil { + fmt.Printf("Failed to run SSL tests: %s\n", err) + os.Exit(1) + } + } + + if *jsonOutput != "" { + if err := adb("pull", "-p", "/data/local/tmp/boringssl-tmp/results.json", *jsonOutput); err != nil { + fmt.Printf("Failed to extract results.json: %s\n", err) + os.Exit(1) + } + } + + if unitTestExit != 0 { + os.Exit(unitTestExit) + } + + if sslTestExit != 0 { + os.Exit(sslTestExit) + } +} diff --git a/external/cecil-legacy/.gitattributes b/external/cecil-legacy/.gitattributes new file mode 100644 index 0000000000..7d07d70cc8 --- /dev/null +++ b/external/cecil-legacy/.gitattributes @@ -0,0 +1 @@ +* text=lf diff --git a/external/cecil-legacy/.gitignore b/external/cecil-legacy/.gitignore new file mode 100644 index 0000000000..8dcb32b7f6 --- /dev/null +++ b/external/cecil-legacy/.gitignore @@ -0,0 +1,10 @@ +bin +obj +*.suo +*.user +*.pidb +*.userprefs +*.xml +*.nupkg +**/test-results/* +*Resharper* diff --git a/external/cecil-legacy/Mono.Cecil.Cil/Code.cs b/external/cecil-legacy/Mono.Cecil.Cil/Code.cs new file mode 100644 index 0000000000..fa88b63d67 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil.Cil/Code.cs @@ -0,0 +1,252 @@ +// +// Code.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +namespace Mono.Cecil.Cil { + + public enum Code { + Nop, + Break, + Ldarg_0, + Ldarg_1, + Ldarg_2, + Ldarg_3, + Ldloc_0, + Ldloc_1, + Ldloc_2, + Ldloc_3, + Stloc_0, + Stloc_1, + Stloc_2, + Stloc_3, + Ldarg_S, + Ldarga_S, + Starg_S, + Ldloc_S, + Ldloca_S, + Stloc_S, + Ldnull, + Ldc_I4_M1, + Ldc_I4_0, + Ldc_I4_1, + Ldc_I4_2, + Ldc_I4_3, + Ldc_I4_4, + Ldc_I4_5, + Ldc_I4_6, + Ldc_I4_7, + Ldc_I4_8, + Ldc_I4_S, + Ldc_I4, + Ldc_I8, + Ldc_R4, + Ldc_R8, + Dup, + Pop, + Jmp, + Call, + Calli, + Ret, + Br_S, + Brfalse_S, + Brtrue_S, + Beq_S, + Bge_S, + Bgt_S, + Ble_S, + Blt_S, + Bne_Un_S, + Bge_Un_S, + Bgt_Un_S, + Ble_Un_S, + Blt_Un_S, + Br, + Brfalse, + Brtrue, + Beq, + Bge, + Bgt, + Ble, + Blt, + Bne_Un, + Bge_Un, + Bgt_Un, + Ble_Un, + Blt_Un, + Switch, + Ldind_I1, + Ldind_U1, + Ldind_I2, + Ldind_U2, + Ldind_I4, + Ldind_U4, + Ldind_I8, + Ldind_I, + Ldind_R4, + Ldind_R8, + Ldind_Ref, + Stind_Ref, + Stind_I1, + Stind_I2, + Stind_I4, + Stind_I8, + Stind_R4, + Stind_R8, + Add, + Sub, + Mul, + Div, + Div_Un, + Rem, + Rem_Un, + And, + Or, + Xor, + Shl, + Shr, + Shr_Un, + Neg, + Not, + Conv_I1, + Conv_I2, + Conv_I4, + Conv_I8, + Conv_R4, + Conv_R8, + Conv_U4, + Conv_U8, + Callvirt, + Cpobj, + Ldobj, + Ldstr, + Newobj, + Castclass, + Isinst, + Conv_R_Un, + Unbox, + Throw, + Ldfld, + Ldflda, + Stfld, + Ldsfld, + Ldsflda, + Stsfld, + Stobj, + Conv_Ovf_I1_Un, + Conv_Ovf_I2_Un, + Conv_Ovf_I4_Un, + Conv_Ovf_I8_Un, + Conv_Ovf_U1_Un, + Conv_Ovf_U2_Un, + Conv_Ovf_U4_Un, + Conv_Ovf_U8_Un, + Conv_Ovf_I_Un, + Conv_Ovf_U_Un, + Box, + Newarr, + Ldlen, + Ldelema, + Ldelem_I1, + Ldelem_U1, + Ldelem_I2, + Ldelem_U2, + Ldelem_I4, + Ldelem_U4, + Ldelem_I8, + Ldelem_I, + Ldelem_R4, + Ldelem_R8, + Ldelem_Ref, + Stelem_I, + Stelem_I1, + Stelem_I2, + Stelem_I4, + Stelem_I8, + Stelem_R4, + Stelem_R8, + Stelem_Ref, + Ldelem_Any, + Stelem_Any, + Unbox_Any, + Conv_Ovf_I1, + Conv_Ovf_U1, + Conv_Ovf_I2, + Conv_Ovf_U2, + Conv_Ovf_I4, + Conv_Ovf_U4, + Conv_Ovf_I8, + Conv_Ovf_U8, + Refanyval, + Ckfinite, + Mkrefany, + Ldtoken, + Conv_U2, + Conv_U1, + Conv_I, + Conv_Ovf_I, + Conv_Ovf_U, + Add_Ovf, + Add_Ovf_Un, + Mul_Ovf, + Mul_Ovf_Un, + Sub_Ovf, + Sub_Ovf_Un, + Endfinally, + Leave, + Leave_S, + Stind_I, + Conv_U, + Arglist, + Ceq, + Cgt, + Cgt_Un, + Clt, + Clt_Un, + Ldftn, + Ldvirtftn, + Ldarg, + Ldarga, + Starg, + Ldloc, + Ldloca, + Stloc, + Localloc, + Endfilter, + Unaligned, + Volatile, + Tail, + Initobj, + Constrained, + Cpblk, + Initblk, + No, + Rethrow, + Sizeof, + Refanytype, + Readonly, + } +} diff --git a/external/cecil-legacy/Mono.Cecil.Cil/CodeReader.cs b/external/cecil-legacy/Mono.Cecil.Cil/CodeReader.cs new file mode 100644 index 0000000000..12ca5a23b1 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil.Cil/CodeReader.cs @@ -0,0 +1,598 @@ +// +// CodeReader.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +using Mono.Cecil.PE; +using Mono.Collections.Generic; + +using RVA = System.UInt32; + +namespace Mono.Cecil.Cil { + + sealed class CodeReader : ByteBuffer { + + readonly internal MetadataReader reader; + + int start; + Section code_section; + + MethodDefinition method; + MethodBody body; + + int Offset { + get { return base.position - start; } + } + + public CodeReader (Section section, MetadataReader reader) + : base (section.Data) + { + this.code_section = section; + this.reader = reader; + } + + public MethodBody ReadMethodBody (MethodDefinition method) + { + this.method = method; + this.body = new MethodBody (method); + + reader.context = method; + + ReadMethodBody (); + + return this.body; + } + + public void MoveTo (int rva) + { + if (!IsInSection (rva)) { + code_section = reader.image.GetSectionAtVirtualAddress ((uint) rva); + Reset (code_section.Data); + } + + base.position = rva - (int) code_section.VirtualAddress; + } + + bool IsInSection (int rva) + { + return code_section.VirtualAddress <= rva && rva < code_section.VirtualAddress + code_section.SizeOfRawData; + } + + void ReadMethodBody () + { + MoveTo (method.RVA); + + var flags = ReadByte (); + switch (flags & 0x3) { + case 0x2: // tiny + body.code_size = flags >> 2; + body.MaxStackSize = 8; + ReadCode (); + break; + case 0x3: // fat + base.position--; + ReadFatMethod (); + break; + default: + throw new InvalidOperationException (); + } + + var symbol_reader = reader.module.symbol_reader; + + if (symbol_reader != null) { + var instructions = body.Instructions; + symbol_reader.Read (body, offset => GetInstruction (instructions, offset)); + } + } + + void ReadFatMethod () + { + var flags = ReadUInt16 (); + body.max_stack_size = ReadUInt16 (); + body.code_size = (int) ReadUInt32 (); + body.local_var_token = new MetadataToken (ReadUInt32 ()); + body.init_locals = (flags & 0x10) != 0; + + if (body.local_var_token.RID != 0) + body.variables = ReadVariables (body.local_var_token); + + ReadCode (); + + if ((flags & 0x8) != 0) + ReadSection (); + } + + public VariableDefinitionCollection ReadVariables (MetadataToken local_var_token) + { + var position = reader.position; + var variables = reader.ReadVariables (local_var_token); + reader.position = position; + + return variables; + } + + void ReadCode () + { + start = position; + var code_size = body.code_size; + + if (code_size < 0 || buffer.Length <= (uint) (code_size + position)) + code_size = 0; + + var end = start + code_size; + var instructions = body.instructions = new InstructionCollection ((code_size + 1) / 2); + + while (position < end) { + var offset = base.position - start; + var opcode = ReadOpCode (); + var current = new Instruction (offset, opcode); + + if (opcode.OperandType != OperandType.InlineNone) + current.operand = ReadOperand (current); + + instructions.Add (current); + } + + ResolveBranches (instructions); + } + + OpCode ReadOpCode () + { + var il_opcode = ReadByte (); + return il_opcode != 0xfe + ? OpCodes.OneByteOpCode [il_opcode] + : OpCodes.TwoBytesOpCode [ReadByte ()]; + } + + object ReadOperand (Instruction instruction) + { + switch (instruction.opcode.OperandType) { + case OperandType.InlineSwitch: + var length = ReadInt32 (); + var base_offset = Offset + (4 * length); + var branches = new int [length]; + for (int i = 0; i < length; i++) + branches [i] = base_offset + ReadInt32 (); + return branches; + case OperandType.ShortInlineBrTarget: + return ReadSByte () + Offset; + case OperandType.InlineBrTarget: + return ReadInt32 () + Offset; + case OperandType.ShortInlineI: + if (instruction.opcode == OpCodes.Ldc_I4_S) + return ReadSByte (); + + return ReadByte (); + case OperandType.InlineI: + return ReadInt32 (); + case OperandType.ShortInlineR: + return ReadSingle (); + case OperandType.InlineR: + return ReadDouble (); + case OperandType.InlineI8: + return ReadInt64 (); + case OperandType.ShortInlineVar: + return GetVariable (ReadByte ()); + case OperandType.InlineVar: + return GetVariable (ReadUInt16 ()); + case OperandType.ShortInlineArg: + return GetParameter (ReadByte ()); + case OperandType.InlineArg: + return GetParameter (ReadUInt16 ()); + case OperandType.InlineSig: + return GetCallSite (ReadToken ()); + case OperandType.InlineString: + return GetString (ReadToken ()); + case OperandType.InlineTok: + case OperandType.InlineType: + case OperandType.InlineMethod: + case OperandType.InlineField: + return reader.LookupToken (ReadToken ()); + default: + throw new NotSupportedException (); + } + } + + public string GetString (MetadataToken token) + { + return reader.image.UserStringHeap.Read (token.RID); + } + + public ParameterDefinition GetParameter (int index) + { + return body.GetParameter (index); + } + + public VariableDefinition GetVariable (int index) + { + return body.GetVariable (index); + } + + public CallSite GetCallSite (MetadataToken token) + { + return reader.ReadCallSite (token); + } + + void ResolveBranches (Collection instructions) + { + var items = instructions.items; + var size = instructions.size; + + for (int i = 0; i < size; i++) { + var instruction = items [i]; + switch (instruction.opcode.OperandType) { + case OperandType.ShortInlineBrTarget: + case OperandType.InlineBrTarget: + instruction.operand = GetInstruction ((int) instruction.operand); + break; + case OperandType.InlineSwitch: + var offsets = (int []) instruction.operand; + var branches = new Instruction [offsets.Length]; + for (int j = 0; j < offsets.Length; j++) + branches [j] = GetInstruction (offsets [j]); + + instruction.operand = branches; + break; + } + } + } + + Instruction GetInstruction (int offset) + { + return GetInstruction (body.Instructions, offset); + } + + static Instruction GetInstruction (Collection instructions, int offset) + { + var size = instructions.size; + var items = instructions.items; + if (offset < 0 || offset > items [size - 1].offset) + return null; + + int min = 0; + int max = size - 1; + while (min <= max) { + int mid = min + ((max - min) / 2); + var instruction = items [mid]; + var instruction_offset = instruction.offset; + + if (offset == instruction_offset) + return instruction; + + if (offset < instruction_offset) + max = mid - 1; + else + min = mid + 1; + } + + return null; + } + + void ReadSection () + { + Align (4); + + const byte fat_format = 0x40; + const byte more_sects = 0x80; + + var flags = ReadByte (); + if ((flags & fat_format) == 0) + ReadSmallSection (); + else + ReadFatSection (); + + if ((flags & more_sects) != 0) + ReadSection (); + } + + void ReadSmallSection () + { + var count = ReadByte () / 12; + Advance (2); + + ReadExceptionHandlers ( + count, + () => (int) ReadUInt16 (), + () => (int) ReadByte ()); + } + + void ReadFatSection () + { + position--; + var count = (ReadInt32 () >> 8) / 24; + + ReadExceptionHandlers ( + count, + ReadInt32, + ReadInt32); + } + + // inline ? + void ReadExceptionHandlers (int count, Func read_entry, Func read_length) + { + for (int i = 0; i < count; i++) { + var handler = new ExceptionHandler ( + (ExceptionHandlerType) (read_entry () & 0x7)); + + handler.TryStart = GetInstruction (read_entry ()); + handler.TryEnd = GetInstruction (handler.TryStart.Offset + read_length ()); + + handler.HandlerStart = GetInstruction (read_entry ()); + handler.HandlerEnd = GetInstruction (handler.HandlerStart.Offset + read_length ()); + + ReadExceptionHandlerSpecific (handler); + + this.body.ExceptionHandlers.Add (handler); + } + } + + void ReadExceptionHandlerSpecific (ExceptionHandler handler) + { + switch (handler.HandlerType) { + case ExceptionHandlerType.Catch: + handler.CatchType = (TypeReference) reader.LookupToken (ReadToken ()); + break; + case ExceptionHandlerType.Filter: + handler.FilterStart = GetInstruction (ReadInt32 ()); + break; + default: + Advance (4); + break; + } + } + + void Align (int align) + { + align--; + Advance (((position + align) & ~align) - position); + } + + public MetadataToken ReadToken () + { + return new MetadataToken (ReadUInt32 ()); + } + +#if !READ_ONLY + + public ByteBuffer PatchRawMethodBody (MethodDefinition method, CodeWriter writer, out MethodSymbols symbols) + { + var buffer = new ByteBuffer (); + symbols = new MethodSymbols (method.Name); + + this.method = method; + reader.context = method; + + MoveTo (method.RVA); + + var flags = ReadByte (); + + MetadataToken local_var_token; + + switch (flags & 0x3) { + case 0x2: // tiny + buffer.WriteByte (flags); + local_var_token = MetadataToken.Zero; + symbols.code_size = flags >> 2; + PatchRawCode (buffer, symbols.code_size, writer); + break; + case 0x3: // fat + base.position--; + + PatchRawFatMethod (buffer, symbols, writer, out local_var_token); + break; + default: + throw new NotSupportedException (); + } + + var symbol_reader = reader.module.symbol_reader; + if (symbol_reader != null && writer.metadata.write_symbols) { + symbols.method_token = GetOriginalToken (writer.metadata, method); + symbols.local_var_token = local_var_token; + symbol_reader.Read (symbols); + } + + return buffer; + } + + void PatchRawFatMethod (ByteBuffer buffer, MethodSymbols symbols, CodeWriter writer, out MetadataToken local_var_token) + { + var flags = ReadUInt16 (); + buffer.WriteUInt16 (flags); + buffer.WriteUInt16 (ReadUInt16 ()); + symbols.code_size = ReadInt32 (); + buffer.WriteInt32 (symbols.code_size); + local_var_token = ReadToken (); + + if (local_var_token.RID > 0) { + var variables = symbols.variables = ReadVariables (local_var_token); + buffer.WriteUInt32 (variables != null + ? writer.GetStandAloneSignature (symbols.variables).ToUInt32 () + : 0); + } else + buffer.WriteUInt32 (0); + + PatchRawCode (buffer, symbols.code_size, writer); + + if ((flags & 0x8) != 0) + PatchRawSection (buffer, writer.metadata); + } + + static MetadataToken GetOriginalToken (MetadataBuilder metadata, MethodDefinition method) + { + MetadataToken original; + if (metadata.TryGetOriginalMethodToken (method.token, out original)) + return original; + + return MetadataToken.Zero; + } + + void PatchRawCode (ByteBuffer buffer, int code_size, CodeWriter writer) + { + var metadata = writer.metadata; + buffer.WriteBytes (ReadBytes (code_size)); + var end = buffer.position; + buffer.position -= code_size; + + while (buffer.position < end) { + OpCode opcode; + var il_opcode = buffer.ReadByte (); + if (il_opcode != 0xfe) { + opcode = OpCodes.OneByteOpCode [il_opcode]; + } else { + var il_opcode2 = buffer.ReadByte (); + opcode = OpCodes.TwoBytesOpCode [il_opcode2]; + } + + switch (opcode.OperandType) { + case OperandType.ShortInlineI: + case OperandType.ShortInlineBrTarget: + case OperandType.ShortInlineVar: + case OperandType.ShortInlineArg: + buffer.position += 1; + break; + case OperandType.InlineVar: + case OperandType.InlineArg: + buffer.position += 2; + break; + case OperandType.InlineBrTarget: + case OperandType.ShortInlineR: + case OperandType.InlineI: + buffer.position += 4; + break; + case OperandType.InlineI8: + case OperandType.InlineR: + buffer.position += 8; + break; + case OperandType.InlineSwitch: + var length = buffer.ReadInt32 (); + buffer.position += length * 4; + break; + case OperandType.InlineString: + var @string = GetString (new MetadataToken (buffer.ReadUInt32 ())); + buffer.position -= 4; + buffer.WriteUInt32 ( + new MetadataToken ( + TokenType.String, + metadata.user_string_heap.GetStringIndex (@string)).ToUInt32 ()); + break; + case OperandType.InlineSig: + var call_site = GetCallSite (new MetadataToken (buffer.ReadUInt32 ())); + buffer.position -= 4; + buffer.WriteUInt32 (writer.GetStandAloneSignature (call_site).ToUInt32 ()); + break; + case OperandType.InlineTok: + case OperandType.InlineType: + case OperandType.InlineMethod: + case OperandType.InlineField: + var provider = reader.LookupToken (new MetadataToken (buffer.ReadUInt32 ())); + buffer.position -= 4; + buffer.WriteUInt32 (metadata.LookupToken (provider).ToUInt32 ()); + break; + } + } + } + + void PatchRawSection (ByteBuffer buffer, MetadataBuilder metadata) + { + var position = base.position; + Align (4); + buffer.WriteBytes (base.position - position); + + const byte fat_format = 0x40; + const byte more_sects = 0x80; + + var flags = ReadByte (); + if ((flags & fat_format) == 0) { + buffer.WriteByte (flags); + PatchRawSmallSection (buffer, metadata); + } else + PatchRawFatSection (buffer, metadata); + + if ((flags & more_sects) != 0) + PatchRawSection (buffer, metadata); + } + + void PatchRawSmallSection (ByteBuffer buffer, MetadataBuilder metadata) + { + var length = ReadByte (); + buffer.WriteByte (length); + Advance (2); + + buffer.WriteUInt16 (0); + + var count = length / 12; + + PatchRawExceptionHandlers (buffer, metadata, count, false); + } + + void PatchRawFatSection (ByteBuffer buffer, MetadataBuilder metadata) + { + position--; + var length = ReadInt32 (); + buffer.WriteInt32 (length); + + var count = (length >> 8) / 24; + + PatchRawExceptionHandlers (buffer, metadata, count, true); + } + + void PatchRawExceptionHandlers (ByteBuffer buffer, MetadataBuilder metadata, int count, bool fat_entry) + { + const int fat_entry_size = 16; + const int small_entry_size = 6; + + for (int i = 0; i < count; i++) { + ExceptionHandlerType handler_type; + if (fat_entry) { + var type = ReadUInt32 (); + handler_type = (ExceptionHandlerType) (type & 0x7); + buffer.WriteUInt32 (type); + } else { + var type = ReadUInt16 (); + handler_type = (ExceptionHandlerType) (type & 0x7); + buffer.WriteUInt16 (type); + } + + buffer.WriteBytes (ReadBytes (fat_entry ? fat_entry_size : small_entry_size)); + + switch (handler_type) { + case ExceptionHandlerType.Catch: + var exception = reader.LookupToken (ReadToken ()); + buffer.WriteUInt32 (metadata.LookupToken (exception).ToUInt32 ()); + break; + default: + buffer.WriteUInt32 (ReadUInt32 ()); + break; + } + } + } + +#endif + + } +} diff --git a/external/cecil-legacy/Mono.Cecil.Cil/CodeWriter.cs b/external/cecil-legacy/Mono.Cecil.Cil/CodeWriter.cs new file mode 100644 index 0000000000..ac093cae46 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil.Cil/CodeWriter.cs @@ -0,0 +1,649 @@ +// +// CodeWriter.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Collections.Generic; + +using Mono.Collections.Generic; + +using Mono.Cecil.Metadata; +using Mono.Cecil.PE; + +using RVA = System.UInt32; + +#if !READ_ONLY + +namespace Mono.Cecil.Cil { + + sealed class CodeWriter : ByteBuffer { + + readonly RVA code_base; + internal readonly MetadataBuilder metadata; + readonly Dictionary standalone_signatures; + + RVA current; + MethodBody body; + + public CodeWriter (MetadataBuilder metadata) + : base (0) + { + this.code_base = metadata.text_map.GetNextRVA (TextSegment.CLIHeader); + this.current = code_base; + this.metadata = metadata; + this.standalone_signatures = new Dictionary (); + } + + public RVA WriteMethodBody (MethodDefinition method) + { + var rva = BeginMethod (); + + if (IsUnresolved (method)) { + if (method.rva == 0) + return 0; + + WriteUnresolvedMethodBody (method); + } else { + if (IsEmptyMethodBody (method.Body)) + return 0; + + WriteResolvedMethodBody (method); + } + + Align (4); + + EndMethod (); + return rva; + } + + static bool IsEmptyMethodBody (MethodBody body) + { + return body.instructions.IsNullOrEmpty () + && body.variables.IsNullOrEmpty (); + } + + static bool IsUnresolved (MethodDefinition method) + { + return method.HasBody && method.HasImage && method.body == null; + } + + void WriteUnresolvedMethodBody (MethodDefinition method) + { + var code_reader = metadata.module.Read (method, (_, reader) => reader.code); + + MethodSymbols symbols; + var buffer = code_reader.PatchRawMethodBody (method, this, out symbols); + + WriteBytes (buffer); + + if (symbols.instructions.IsNullOrEmpty ()) + return; + + symbols.method_token = method.token; + symbols.local_var_token = GetLocalVarToken (buffer, symbols); + + var symbol_writer = metadata.symbol_writer; + if (symbol_writer != null) + symbol_writer.Write (symbols); + } + + static MetadataToken GetLocalVarToken (ByteBuffer buffer, MethodSymbols symbols) + { + if (symbols.variables.IsNullOrEmpty ()) + return MetadataToken.Zero; + + buffer.position = 8; + return new MetadataToken (buffer.ReadUInt32 ()); + } + + void WriteResolvedMethodBody (MethodDefinition method) + { + body = method.Body; + ComputeHeader (); + if (RequiresFatHeader ()) + WriteFatHeader (); + else + WriteByte ((byte) (0x2 | (body.CodeSize << 2))); // tiny + + WriteInstructions (); + + if (body.HasExceptionHandlers) + WriteExceptionHandlers (); + + var symbol_writer = metadata.symbol_writer; + if (symbol_writer != null) + symbol_writer.Write (body); + } + + void WriteFatHeader () + { + var body = this.body; + byte flags = 0x3; // fat + if (body.InitLocals) + flags |= 0x10; // init locals + if (body.HasExceptionHandlers) + flags |= 0x8; // more sections + + WriteByte (flags); + WriteByte (0x30); + WriteInt16 ((short) body.max_stack_size); + WriteInt32 (body.code_size); + body.local_var_token = body.HasVariables + ? GetStandAloneSignature (body.Variables) + : MetadataToken.Zero; + WriteMetadataToken (body.local_var_token); + } + + void WriteInstructions () + { + var instructions = body.Instructions; + var items = instructions.items; + var size = instructions.size; + + for (int i = 0; i < size; i++) { + var instruction = items [i]; + WriteOpCode (instruction.opcode); + WriteOperand (instruction); + } + } + + void WriteOpCode (OpCode opcode) + { + if (opcode.Size == 1) { + WriteByte (opcode.Op2); + } else { + WriteByte (opcode.Op1); + WriteByte (opcode.Op2); + } + } + + void WriteOperand (Instruction instruction) + { + var opcode = instruction.opcode; + var operand_type = opcode.OperandType; + if (operand_type == OperandType.InlineNone) + return; + + var operand = instruction.operand; + if (operand == null) + throw new ArgumentException (); + + switch (operand_type) { + case OperandType.InlineSwitch: { + var targets = (Instruction []) operand; + WriteInt32 (targets.Length); + var diff = instruction.Offset + opcode.Size + (4 * (targets.Length + 1)); + for (int i = 0; i < targets.Length; i++) + WriteInt32 (GetTargetOffset (targets [i]) - diff); + break; + } + case OperandType.ShortInlineBrTarget: { + var target = (Instruction) operand; + WriteSByte ((sbyte) (GetTargetOffset (target) - (instruction.Offset + opcode.Size + 1))); + break; + } + case OperandType.InlineBrTarget: { + var target = (Instruction) operand; + WriteInt32 (GetTargetOffset (target) - (instruction.Offset + opcode.Size + 4)); + break; + } + case OperandType.ShortInlineVar: + WriteByte ((byte) GetVariableIndex ((VariableDefinition) operand)); + break; + case OperandType.ShortInlineArg: + WriteByte ((byte) GetParameterIndex ((ParameterDefinition) operand)); + break; + case OperandType.InlineVar: + WriteInt16 ((short) GetVariableIndex ((VariableDefinition) operand)); + break; + case OperandType.InlineArg: + WriteInt16 ((short) GetParameterIndex ((ParameterDefinition) operand)); + break; + case OperandType.InlineSig: + WriteMetadataToken (GetStandAloneSignature ((CallSite) operand)); + break; + case OperandType.ShortInlineI: + if (opcode == OpCodes.Ldc_I4_S) + WriteSByte ((sbyte) operand); + else + WriteByte ((byte) operand); + break; + case OperandType.InlineI: + WriteInt32 ((int) operand); + break; + case OperandType.InlineI8: + WriteInt64 ((long) operand); + break; + case OperandType.ShortInlineR: + WriteSingle ((float) operand); + break; + case OperandType.InlineR: + WriteDouble ((double) operand); + break; + case OperandType.InlineString: + WriteMetadataToken ( + new MetadataToken ( + TokenType.String, + GetUserStringIndex ((string) operand))); + break; + case OperandType.InlineType: + case OperandType.InlineField: + case OperandType.InlineMethod: + case OperandType.InlineTok: + WriteMetadataToken (metadata.LookupToken ((IMetadataTokenProvider) operand)); + break; + default: + throw new ArgumentException (); + } + } + + int GetTargetOffset (Instruction instruction) + { + if (instruction == null) { + var last = body.instructions [body.instructions.size - 1]; + return last.offset + last.GetSize (); + } + + return instruction.offset; + } + + uint GetUserStringIndex (string @string) + { + if (@string == null) + return 0; + + return metadata.user_string_heap.GetStringIndex (@string); + } + + static int GetVariableIndex (VariableDefinition variable) + { + return variable.Index; + } + + int GetParameterIndex (ParameterDefinition parameter) + { + if (body.method.HasThis) { + if (parameter == body.this_parameter) + return 0; + + return parameter.Index + 1; + } + + return parameter.Index; + } + + bool RequiresFatHeader () + { + var body = this.body; + return body.CodeSize >= 64 + || body.InitLocals + || body.HasVariables + || body.HasExceptionHandlers + || body.MaxStackSize > 8; + } + + void ComputeHeader () + { + int offset = 0; + var instructions = body.instructions; + var items = instructions.items; + var count = instructions.size; + var stack_size = 0; + var max_stack = 0; + Dictionary stack_sizes = null; + + if (body.HasExceptionHandlers) + ComputeExceptionHandlerStackSize (ref stack_sizes); + + for (int i = 0; i < count; i++) { + var instruction = items [i]; + instruction.offset = offset; + offset += instruction.GetSize (); + + ComputeStackSize (instruction, ref stack_sizes, ref stack_size, ref max_stack); + } + + body.code_size = offset; + body.max_stack_size = max_stack; + } + + void ComputeExceptionHandlerStackSize (ref Dictionary stack_sizes) + { + var exception_handlers = body.ExceptionHandlers; + + for (int i = 0; i < exception_handlers.Count; i++) { + var exception_handler = exception_handlers [i]; + + switch (exception_handler.HandlerType) { + case ExceptionHandlerType.Catch: + AddExceptionStackSize (exception_handler.HandlerStart, ref stack_sizes); + break; + case ExceptionHandlerType.Filter: + AddExceptionStackSize (exception_handler.FilterStart, ref stack_sizes); + AddExceptionStackSize (exception_handler.HandlerStart, ref stack_sizes); + break; + } + } + } + + static void AddExceptionStackSize (Instruction handler_start, ref Dictionary stack_sizes) + { + if (handler_start == null) + return; + + if (stack_sizes == null) + stack_sizes = new Dictionary (); + + stack_sizes [handler_start] = 1; + } + + static void ComputeStackSize (Instruction instruction, ref Dictionary stack_sizes, ref int stack_size, ref int max_stack) + { + int computed_size; + if (stack_sizes != null && stack_sizes.TryGetValue (instruction, out computed_size)) + stack_size = computed_size; + + max_stack = System.Math.Max (max_stack, stack_size); + ComputeStackDelta (instruction, ref stack_size); + max_stack = System.Math.Max (max_stack, stack_size); + + CopyBranchStackSize (instruction, ref stack_sizes, stack_size); + ComputeStackSize (instruction, ref stack_size); + } + + static void CopyBranchStackSize (Instruction instruction, ref Dictionary stack_sizes, int stack_size) + { + if (stack_size == 0) + return; + + switch (instruction.opcode.OperandType) { + case OperandType.ShortInlineBrTarget: + case OperandType.InlineBrTarget: + CopyBranchStackSize (ref stack_sizes, (Instruction) instruction.operand, stack_size); + break; + case OperandType.InlineSwitch: + var targets = (Instruction[]) instruction.operand; + for (int i = 0; i < targets.Length; i++) + CopyBranchStackSize (ref stack_sizes, targets [i], stack_size); + break; + } + } + + static void CopyBranchStackSize (ref Dictionary stack_sizes, Instruction target, int stack_size) + { + if (stack_sizes == null) + stack_sizes = new Dictionary (); + + int branch_stack_size = stack_size; + + int computed_size; + if (stack_sizes.TryGetValue (target, out computed_size)) + branch_stack_size = System.Math.Max (branch_stack_size, computed_size); + + stack_sizes [target] = branch_stack_size; + } + + static void ComputeStackSize (Instruction instruction, ref int stack_size) + { + switch (instruction.opcode.FlowControl) { + case FlowControl.Branch: + case FlowControl.Break: + case FlowControl.Throw: + case FlowControl.Return: + stack_size = 0; + break; + } + } + + static void ComputeStackDelta (Instruction instruction, ref int stack_size) + { + switch (instruction.opcode.FlowControl) { + case FlowControl.Call: { + var method = (IMethodSignature) instruction.operand; + // pop 'this' argument + if (method.HasImplicitThis() && instruction.opcode.Code != Code.Newobj) + stack_size--; + // pop normal arguments + if (method.HasParameters) + stack_size -= method.Parameters.Count; + // pop function pointer + if (instruction.opcode.Code == Code.Calli) + stack_size--; + // push return value + if (method.ReturnType.etype != ElementType.Void || instruction.opcode.Code == Code.Newobj) + stack_size++; + break; + } + default: + ComputePopDelta (instruction.opcode.StackBehaviourPop, ref stack_size); + ComputePushDelta (instruction.opcode.StackBehaviourPush, ref stack_size); + break; + } + } + + static void ComputePopDelta (StackBehaviour pop_behavior, ref int stack_size) + { + switch (pop_behavior) { + case StackBehaviour.Popi: + case StackBehaviour.Popref: + case StackBehaviour.Pop1: + stack_size--; + break; + case StackBehaviour.Pop1_pop1: + case StackBehaviour.Popi_pop1: + case StackBehaviour.Popi_popi: + case StackBehaviour.Popi_popi8: + case StackBehaviour.Popi_popr4: + case StackBehaviour.Popi_popr8: + case StackBehaviour.Popref_pop1: + case StackBehaviour.Popref_popi: + stack_size -= 2; + break; + case StackBehaviour.Popi_popi_popi: + case StackBehaviour.Popref_popi_popi: + case StackBehaviour.Popref_popi_popi8: + case StackBehaviour.Popref_popi_popr4: + case StackBehaviour.Popref_popi_popr8: + case StackBehaviour.Popref_popi_popref: + stack_size -= 3; + break; + case StackBehaviour.PopAll: + stack_size = 0; + break; + } + } + + static void ComputePushDelta (StackBehaviour push_behaviour, ref int stack_size) + { + switch (push_behaviour) { + case StackBehaviour.Push1: + case StackBehaviour.Pushi: + case StackBehaviour.Pushi8: + case StackBehaviour.Pushr4: + case StackBehaviour.Pushr8: + case StackBehaviour.Pushref: + stack_size++; + break; + case StackBehaviour.Push1_push1: + stack_size += 2; + break; + } + } + + void WriteExceptionHandlers () + { + Align (4); + + var handlers = body.ExceptionHandlers; + + if (handlers.Count < 0x15 && !RequiresFatSection (handlers)) + WriteSmallSection (handlers); + else + WriteFatSection (handlers); + } + + static bool RequiresFatSection (Collection handlers) + { + for (int i = 0; i < handlers.Count; i++) { + var handler = handlers [i]; + + if (IsFatRange (handler.TryStart, handler.TryEnd)) + return true; + + if (IsFatRange (handler.HandlerStart, handler.HandlerEnd)) + return true; + + if (handler.HandlerType == ExceptionHandlerType.Filter + && IsFatRange (handler.FilterStart, handler.HandlerStart)) + return true; + } + + return false; + } + + static bool IsFatRange (Instruction start, Instruction end) + { + if (start == null) + throw new ArgumentException (); + + if (end == null) + return true; + + return end.Offset - start.Offset > 255 || start.Offset > 65535; + } + + void WriteSmallSection (Collection handlers) + { + const byte eh_table = 0x1; + + WriteByte (eh_table); + WriteByte ((byte) (handlers.Count * 12 + 4)); + WriteBytes (2); + + WriteExceptionHandlers ( + handlers, + i => WriteUInt16 ((ushort) i), + i => WriteByte ((byte) i)); + } + + void WriteFatSection (Collection handlers) + { + const byte eh_table = 0x1; + const byte fat_format = 0x40; + + WriteByte (eh_table | fat_format); + + int size = handlers.Count * 24 + 4; + WriteByte ((byte) (size & 0xff)); + WriteByte ((byte) ((size >> 8) & 0xff)); + WriteByte ((byte) ((size >> 16) & 0xff)); + + WriteExceptionHandlers (handlers, WriteInt32, WriteInt32); + } + + void WriteExceptionHandlers (Collection handlers, Action write_entry, Action write_length) + { + for (int i = 0; i < handlers.Count; i++) { + var handler = handlers [i]; + + write_entry ((int) handler.HandlerType); + + write_entry (handler.TryStart.Offset); + write_length (GetTargetOffset (handler.TryEnd) - handler.TryStart.Offset); + + write_entry (handler.HandlerStart.Offset); + write_length (GetTargetOffset (handler.HandlerEnd) - handler.HandlerStart.Offset); + + WriteExceptionHandlerSpecific (handler); + } + } + + void WriteExceptionHandlerSpecific (ExceptionHandler handler) + { + switch (handler.HandlerType) { + case ExceptionHandlerType.Catch: + WriteMetadataToken (metadata.LookupToken (handler.CatchType)); + break; + case ExceptionHandlerType.Filter: + WriteInt32 (handler.FilterStart.Offset); + break; + default: + WriteInt32 (0); + break; + } + } + + public MetadataToken GetStandAloneSignature (Collection variables) + { + var signature = metadata.GetLocalVariableBlobIndex (variables); + + return GetStandAloneSignatureToken (signature); + } + + public MetadataToken GetStandAloneSignature (CallSite call_site) + { + var signature = metadata.GetCallSiteBlobIndex (call_site); + var token = GetStandAloneSignatureToken (signature); + call_site.MetadataToken = token; + return token; + } + + MetadataToken GetStandAloneSignatureToken (uint signature) + { + MetadataToken token; + if (standalone_signatures.TryGetValue (signature, out token)) + return token; + + token = new MetadataToken (TokenType.Signature, metadata.AddStandAloneSignature (signature)); + standalone_signatures.Add (signature, token); + return token; + } + + RVA BeginMethod () + { + return current; + } + + void WriteMetadataToken (MetadataToken token) + { + WriteUInt32 (token.ToUInt32 ()); + } + + void Align (int align) + { + align--; + WriteBytes (((position + align) & ~align) - position); + } + + void EndMethod () + { + current = (RVA) (code_base + position); + } + } +} + +#endif diff --git a/external/cecil-legacy/Mono.Cecil.Cil/Document.cs b/external/cecil-legacy/Mono.Cecil.Cil/Document.cs new file mode 100644 index 0000000000..1dbdc44744 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil.Cil/Document.cs @@ -0,0 +1,112 @@ +// +// Document.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +namespace Mono.Cecil.Cil { + + public enum DocumentType { + Other, + Text, + } + + public enum DocumentHashAlgorithm { + None, + MD5, + SHA1, + } + + public enum DocumentLanguage { + Other, + C, + Cpp, + CSharp, + Basic, + Java, + Cobol, + Pascal, + Cil, + JScript, + Smc, + MCpp, + FSharp, + } + + public enum DocumentLanguageVendor { + Other, + Microsoft, + } + + public sealed class Document { + + string url; + + byte type; + byte hash_algorithm; + byte language; + byte language_vendor; + + byte [] hash; + + public string Url { + get { return url; } + set { url = value; } + } + + public DocumentType Type { + get { return (DocumentType) type; } + set { type = (byte) value; } + } + + public DocumentHashAlgorithm HashAlgorithm { + get { return (DocumentHashAlgorithm) hash_algorithm; } + set { hash_algorithm = (byte) value; } + } + + public DocumentLanguage Language { + get { return (DocumentLanguage) language; } + set { language = (byte) value; } + } + + public DocumentLanguageVendor LanguageVendor { + get { return (DocumentLanguageVendor) language_vendor; } + set { language_vendor = (byte) value; } + } + + public byte [] Hash { + get { return hash; } + set { hash = value; } + } + + public Document (string url) + { + this.url = url; + this.hash = Empty.Array; + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil.Cil/ExceptionHandler.cs b/external/cecil-legacy/Mono.Cecil.Cil/ExceptionHandler.cs new file mode 100644 index 0000000000..c61ff235ef --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil.Cil/ExceptionHandler.cs @@ -0,0 +1,89 @@ +// +// ExceptionHandler.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +namespace Mono.Cecil.Cil { + + public enum ExceptionHandlerType { + Catch = 0, + Filter = 1, + Finally = 2, + Fault = 4, + } + + public sealed class ExceptionHandler { + + Instruction try_start; + Instruction try_end; + Instruction filter_start; + Instruction handler_start; + Instruction handler_end; + + TypeReference catch_type; + ExceptionHandlerType handler_type; + + public Instruction TryStart { + get { return try_start; } + set { try_start = value; } + } + + public Instruction TryEnd { + get { return try_end; } + set { try_end = value; } + } + + public Instruction FilterStart { + get { return filter_start; } + set { filter_start = value; } + } + + public Instruction HandlerStart { + get { return handler_start; } + set { handler_start = value; } + } + + public Instruction HandlerEnd { + get { return handler_end; } + set { handler_end = value; } + } + + public TypeReference CatchType { + get { return catch_type; } + set { catch_type = value; } + } + + public ExceptionHandlerType HandlerType { + get { return handler_type; } + set { handler_type = value; } + } + + public ExceptionHandler (ExceptionHandlerType handlerType) + { + this.handler_type = handlerType; + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil.Cil/ILProcessor.cs b/external/cecil-legacy/Mono.Cecil.Cil/ILProcessor.cs new file mode 100644 index 0000000000..cd5dbb40fe --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil.Cil/ILProcessor.cs @@ -0,0 +1,278 @@ +// +// ILProcessor.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +using Mono.Collections.Generic; + +namespace Mono.Cecil.Cil { + + public sealed class ILProcessor { + + readonly MethodBody body; + readonly Collection instructions; + + public MethodBody Body { + get { return body; } + } + + internal ILProcessor (MethodBody body) + { + this.body = body; + this.instructions = body.Instructions; + } + + public Instruction Create (OpCode opcode) + { + return Instruction.Create (opcode); + } + + public Instruction Create (OpCode opcode, TypeReference type) + { + return Instruction.Create (opcode, type); + } + + public Instruction Create (OpCode opcode, CallSite site) + { + return Instruction.Create (opcode, site); + } + + public Instruction Create (OpCode opcode, MethodReference method) + { + return Instruction.Create (opcode, method); + } + + public Instruction Create (OpCode opcode, FieldReference field) + { + return Instruction.Create (opcode, field); + } + + public Instruction Create (OpCode opcode, string value) + { + return Instruction.Create (opcode, value); + } + + public Instruction Create (OpCode opcode, sbyte value) + { + return Instruction.Create (opcode, value); + } + + public Instruction Create (OpCode opcode, byte value) + { + if (opcode.OperandType == OperandType.ShortInlineVar) + return Instruction.Create (opcode, body.Variables [value]); + + if (opcode.OperandType == OperandType.ShortInlineArg) + return Instruction.Create (opcode, body.GetParameter (value)); + + return Instruction.Create (opcode, value); + } + + public Instruction Create (OpCode opcode, int value) + { + if (opcode.OperandType == OperandType.InlineVar) + return Instruction.Create (opcode, body.Variables [value]); + + if (opcode.OperandType == OperandType.InlineArg) + return Instruction.Create (opcode, body.GetParameter (value)); + + return Instruction.Create (opcode, value); + } + + public Instruction Create (OpCode opcode, long value) + { + return Instruction.Create (opcode, value); + } + + public Instruction Create (OpCode opcode, float value) + { + return Instruction.Create (opcode, value); + } + + public Instruction Create (OpCode opcode, double value) + { + return Instruction.Create (opcode, value); + } + + public Instruction Create (OpCode opcode, Instruction target) + { + return Instruction.Create (opcode, target); + } + + public Instruction Create (OpCode opcode, Instruction [] targets) + { + return Instruction.Create (opcode, targets); + } + + public Instruction Create (OpCode opcode, VariableDefinition variable) + { + return Instruction.Create (opcode, variable); + } + + public Instruction Create (OpCode opcode, ParameterDefinition parameter) + { + return Instruction.Create (opcode, parameter); + } + + public void Emit (OpCode opcode) + { + Append (Create (opcode)); + } + + public void Emit (OpCode opcode, TypeReference type) + { + Append (Create (opcode, type)); + } + + public void Emit (OpCode opcode, MethodReference method) + { + Append (Create (opcode, method)); + } + + public void Emit (OpCode opcode, CallSite site) + { + Append (Create (opcode, site)); + } + + public void Emit (OpCode opcode, FieldReference field) + { + Append (Create (opcode, field)); + } + + public void Emit (OpCode opcode, string value) + { + Append (Create (opcode, value)); + } + + public void Emit (OpCode opcode, byte value) + { + Append (Create (opcode, value)); + } + + public void Emit (OpCode opcode, sbyte value) + { + Append (Create (opcode, value)); + } + + public void Emit (OpCode opcode, int value) + { + Append (Create (opcode, value)); + } + + public void Emit (OpCode opcode, long value) + { + Append (Create (opcode, value)); + } + + public void Emit (OpCode opcode, float value) + { + Append (Create (opcode, value)); + } + + public void Emit (OpCode opcode, double value) + { + Append (Create (opcode, value)); + } + + public void Emit (OpCode opcode, Instruction target) + { + Append (Create (opcode, target)); + } + + public void Emit (OpCode opcode, Instruction [] targets) + { + Append (Create (opcode, targets)); + } + + public void Emit (OpCode opcode, VariableDefinition variable) + { + Append (Create (opcode, variable)); + } + + public void Emit (OpCode opcode, ParameterDefinition parameter) + { + Append (Create (opcode, parameter)); + } + + public void InsertBefore (Instruction target, Instruction instruction) + { + if (target == null) + throw new ArgumentNullException ("target"); + if (instruction == null) + throw new ArgumentNullException ("instruction"); + + var index = instructions.IndexOf (target); + if (index == -1) + throw new ArgumentOutOfRangeException ("target"); + + instructions.Insert (index, instruction); + } + + public void InsertAfter (Instruction target, Instruction instruction) + { + if (target == null) + throw new ArgumentNullException ("target"); + if (instruction == null) + throw new ArgumentNullException ("instruction"); + + var index = instructions.IndexOf (target); + if (index == -1) + throw new ArgumentOutOfRangeException ("target"); + + instructions.Insert (index + 1, instruction); + } + + public void Append (Instruction instruction) + { + if (instruction == null) + throw new ArgumentNullException ("instruction"); + + instructions.Add (instruction); + } + + public void Replace (Instruction target, Instruction instruction) + { + if (target == null) + throw new ArgumentNullException ("target"); + if (instruction == null) + throw new ArgumentNullException ("instruction"); + + InsertAfter (target, instruction); + Remove (target); + } + + public void Remove (Instruction instruction) + { + if (instruction == null) + throw new ArgumentNullException ("instruction"); + + if (!instructions.Remove (instruction)) + throw new ArgumentOutOfRangeException ("instruction"); + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil.Cil/Instruction.cs b/external/cecil-legacy/Mono.Cecil.Cil/Instruction.cs new file mode 100644 index 0000000000..c28d4c9929 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil.Cil/Instruction.cs @@ -0,0 +1,321 @@ +// +// Instruction.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Text; + +namespace Mono.Cecil.Cil { + + public sealed class Instruction { + + internal int offset; + internal OpCode opcode; + internal object operand; + + internal Instruction previous; + internal Instruction next; + + SequencePoint sequence_point; + + public int Offset { + get { return offset; } + set { offset = value; } + } + + public OpCode OpCode { + get { return opcode; } + set { opcode = value; } + } + + public object Operand { + get { return operand; } + set { operand = value; } + } + + public Instruction Previous { + get { return previous; } + set { previous = value; } + } + + public Instruction Next { + get { return next; } + set { next = value; } + } + + public SequencePoint SequencePoint { + get { return sequence_point; } + set { sequence_point = value; } + } + + internal Instruction (int offset, OpCode opCode) + { + this.offset = offset; + this.opcode = opCode; + } + + internal Instruction (OpCode opcode, object operand) + { + this.opcode = opcode; + this.operand = operand; + } + + public int GetSize () + { + int size = opcode.Size; + + switch (opcode.OperandType) { + case OperandType.InlineSwitch: + return size + (1 + ((Instruction []) operand).Length) * 4; + case OperandType.InlineI8: + case OperandType.InlineR: + return size + 8; + case OperandType.InlineBrTarget: + case OperandType.InlineField: + case OperandType.InlineI: + case OperandType.InlineMethod: + case OperandType.InlineString: + case OperandType.InlineTok: + case OperandType.InlineType: + case OperandType.ShortInlineR: + case OperandType.InlineSig: + return size + 4; + case OperandType.InlineArg: + case OperandType.InlineVar: + return size + 2; + case OperandType.ShortInlineBrTarget: + case OperandType.ShortInlineI: + case OperandType.ShortInlineArg: + case OperandType.ShortInlineVar: + return size + 1; + default: + return size; + } + } + + public override string ToString () + { + var instruction = new StringBuilder (); + + AppendLabel (instruction, this); + instruction.Append (':'); + instruction.Append (' '); + instruction.Append (opcode.Name); + + if (operand == null) + return instruction.ToString (); + + instruction.Append (' '); + + switch (opcode.OperandType) { + case OperandType.ShortInlineBrTarget: + case OperandType.InlineBrTarget: + AppendLabel (instruction, (Instruction) operand); + break; + case OperandType.InlineSwitch: + var labels = (Instruction []) operand; + for (int i = 0; i < labels.Length; i++) { + if (i > 0) + instruction.Append (','); + + AppendLabel (instruction, labels [i]); + } + break; + case OperandType.InlineString: + instruction.Append ('\"'); + instruction.Append (operand); + instruction.Append ('\"'); + break; + default: + instruction.Append (operand); + break; + } + + return instruction.ToString (); + } + + static void AppendLabel (StringBuilder builder, Instruction instruction) + { + builder.Append ("IL_"); + builder.Append (instruction.offset.ToString ("x4")); + } + + public static Instruction Create (OpCode opcode) + { + if (opcode.OperandType != OperandType.InlineNone) + throw new ArgumentException ("opcode"); + + return new Instruction (opcode, null); + } + + public static Instruction Create (OpCode opcode, TypeReference type) + { + if (type == null) + throw new ArgumentNullException ("type"); + if (opcode.OperandType != OperandType.InlineType && + opcode.OperandType != OperandType.InlineTok) + throw new ArgumentException ("opcode"); + + return new Instruction (opcode, type); + } + + public static Instruction Create (OpCode opcode, CallSite site) + { + if (site == null) + throw new ArgumentNullException ("site"); + if (opcode.Code != Code.Calli) + throw new ArgumentException ("code"); + + return new Instruction (opcode, site); + } + + public static Instruction Create (OpCode opcode, MethodReference method) + { + if (method == null) + throw new ArgumentNullException ("method"); + if (opcode.OperandType != OperandType.InlineMethod && + opcode.OperandType != OperandType.InlineTok) + throw new ArgumentException ("opcode"); + + return new Instruction (opcode, method); + } + + public static Instruction Create (OpCode opcode, FieldReference field) + { + if (field == null) + throw new ArgumentNullException ("field"); + if (opcode.OperandType != OperandType.InlineField && + opcode.OperandType != OperandType.InlineTok) + throw new ArgumentException ("opcode"); + + return new Instruction (opcode, field); + } + + public static Instruction Create (OpCode opcode, string value) + { + if (value == null) + throw new ArgumentNullException ("value"); + if (opcode.OperandType != OperandType.InlineString) + throw new ArgumentException ("opcode"); + + return new Instruction (opcode, value); + } + + public static Instruction Create (OpCode opcode, sbyte value) + { + if (opcode.OperandType != OperandType.ShortInlineI && + opcode != OpCodes.Ldc_I4_S) + throw new ArgumentException ("opcode"); + + return new Instruction (opcode, value); + } + + public static Instruction Create (OpCode opcode, byte value) + { + if (opcode.OperandType != OperandType.ShortInlineI || + opcode == OpCodes.Ldc_I4_S) + throw new ArgumentException ("opcode"); + + return new Instruction (opcode, value); + } + + public static Instruction Create (OpCode opcode, int value) + { + if (opcode.OperandType != OperandType.InlineI) + throw new ArgumentException ("opcode"); + + return new Instruction (opcode, value); + } + + public static Instruction Create (OpCode opcode, long value) + { + if (opcode.OperandType != OperandType.InlineI8) + throw new ArgumentException ("opcode"); + + return new Instruction (opcode, value); + } + + public static Instruction Create (OpCode opcode, float value) + { + if (opcode.OperandType != OperandType.ShortInlineR) + throw new ArgumentException ("opcode"); + + return new Instruction (opcode, value); + } + + public static Instruction Create (OpCode opcode, double value) + { + if (opcode.OperandType != OperandType.InlineR) + throw new ArgumentException ("opcode"); + + return new Instruction (opcode, value); + } + + public static Instruction Create (OpCode opcode, Instruction target) + { + if (target == null) + throw new ArgumentNullException ("target"); + if (opcode.OperandType != OperandType.InlineBrTarget && + opcode.OperandType != OperandType.ShortInlineBrTarget) + throw new ArgumentException ("opcode"); + + return new Instruction (opcode, target); + } + + public static Instruction Create (OpCode opcode, Instruction [] targets) + { + if (targets == null) + throw new ArgumentNullException ("targets"); + if (opcode.OperandType != OperandType.InlineSwitch) + throw new ArgumentException ("opcode"); + + return new Instruction (opcode, targets); + } + + public static Instruction Create (OpCode opcode, VariableDefinition variable) + { + if (variable == null) + throw new ArgumentNullException ("variable"); + if (opcode.OperandType != OperandType.ShortInlineVar && + opcode.OperandType != OperandType.InlineVar) + throw new ArgumentException ("opcode"); + + return new Instruction (opcode, variable); + } + + public static Instruction Create (OpCode opcode, ParameterDefinition parameter) + { + if (parameter == null) + throw new ArgumentNullException ("parameter"); + if (opcode.OperandType != OperandType.ShortInlineArg && + opcode.OperandType != OperandType.InlineArg) + throw new ArgumentException ("opcode"); + + return new Instruction (opcode, parameter); + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil.Cil/MethodBody.cs b/external/cecil-legacy/Mono.Cecil.Cil/MethodBody.cs new file mode 100644 index 0000000000..3eefc95f35 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil.Cil/MethodBody.cs @@ -0,0 +1,241 @@ +// +// MethodBody.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +using Mono.Collections.Generic; + +namespace Mono.Cecil.Cil { + + public sealed class MethodBody : IVariableDefinitionProvider { + + readonly internal MethodDefinition method; + + internal ParameterDefinition this_parameter; + internal int max_stack_size; + internal int code_size; + internal bool init_locals; + internal MetadataToken local_var_token; + + internal Collection instructions; + internal Collection exceptions; + internal Collection variables; + Scope scope; + + public MethodDefinition Method { + get { return method; } + } + + public int MaxStackSize { + get { return max_stack_size; } + set { max_stack_size = value; } + } + + public int CodeSize { + get { return code_size; } + } + + public bool InitLocals { + get { return init_locals; } + set { init_locals = value; } + } + + public MetadataToken LocalVarToken { + get { return local_var_token; } + set { local_var_token = value; } + } + + public Collection Instructions { + get { return instructions ?? (instructions = new InstructionCollection ()); } + } + + public bool HasExceptionHandlers { + get { return !exceptions.IsNullOrEmpty (); } + } + + public Collection ExceptionHandlers { + get { return exceptions ?? (exceptions = new Collection ()); } + } + + public bool HasVariables { + get { return !variables.IsNullOrEmpty (); } + } + + public Collection Variables { + get { return variables ?? (variables = new VariableDefinitionCollection ()); } + } + + public Scope Scope { + get { return scope; } + set { scope = value; } + } + + public ParameterDefinition ThisParameter { + get { + if (method == null || method.DeclaringType == null) + throw new NotSupportedException (); + + if (!method.HasThis) + return null; + + if (this_parameter != null) + return this_parameter; + + var declaring_type = method.DeclaringType; + var type = declaring_type.IsValueType || declaring_type.IsPrimitive + ? new PointerType (declaring_type) + : declaring_type as TypeReference; + + return this_parameter = new ParameterDefinition (type, method); + } + } + + public MethodBody (MethodDefinition method) + { + this.method = method; + } + + public ILProcessor GetILProcessor () + { + return new ILProcessor (this); + } + } + + public interface IVariableDefinitionProvider { + bool HasVariables { get; } + Collection Variables { get; } + } + + class VariableDefinitionCollection : Collection { + + internal VariableDefinitionCollection () + { + } + + internal VariableDefinitionCollection (int capacity) + : base (capacity) + { + } + + protected override void OnAdd (VariableDefinition item, int index) + { + item.index = index; + } + + protected override void OnInsert (VariableDefinition item, int index) + { + item.index = index; + + for (int i = index; i < size; i++) + items [i].index = i + 1; + } + + protected override void OnSet (VariableDefinition item, int index) + { + item.index = index; + } + + protected override void OnRemove (VariableDefinition item, int index) + { + item.index = -1; + + for (int i = index + 1; i < size; i++) + items [i].index = i - 1; + } + } + + class InstructionCollection : Collection { + + internal InstructionCollection () + { + } + + internal InstructionCollection (int capacity) + : base (capacity) + { + } + + protected override void OnAdd (Instruction item, int index) + { + if (index == 0) + return; + + var previous = items [index - 1]; + previous.next = item; + item.previous = previous; + } + + protected override void OnInsert (Instruction item, int index) + { + if (size == 0) + return; + + var current = items [index]; + if (current == null) { + var last = items [index - 1]; + last.next = item; + item.previous = last; + return; + } + + var previous = current.previous; + if (previous != null) { + previous.next = item; + item.previous = previous; + } + + current.previous = item; + item.next = current; + } + + protected override void OnSet (Instruction item, int index) + { + var current = items [index]; + + item.previous = current.previous; + item.next = current.next; + + current.previous = null; + current.next = null; + } + + protected override void OnRemove (Instruction item, int index) + { + var previous = item.previous; + if (previous != null) + previous.next = item.next; + + var next = item.next; + if (next != null) + next.previous = item.previous; + + item.previous = null; + item.next = null; + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil.Cil/OpCode.cs b/external/cecil-legacy/Mono.Cecil.Cil/OpCode.cs new file mode 100644 index 0000000000..1a14421300 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil.Cil/OpCode.cs @@ -0,0 +1,455 @@ +// +// OpCode.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +namespace Mono.Cecil.Cil { + + public enum FlowControl { + Branch, + Break, + Call, + Cond_Branch, + Meta, + Next, + Phi, + Return, + Throw, + } + + public enum OpCodeType { + Annotation, + Macro, + Nternal, + Objmodel, + Prefix, + Primitive, + } + + public enum OperandType { + InlineBrTarget, + InlineField, + InlineI, + InlineI8, + InlineMethod, + InlineNone, + InlinePhi, + InlineR, + InlineSig, + InlineString, + InlineSwitch, + InlineTok, + InlineType, + InlineVar, + InlineArg, + ShortInlineBrTarget, + ShortInlineI, + ShortInlineR, + ShortInlineVar, + ShortInlineArg, + } + + public enum StackBehaviour { + Pop0, + Pop1, + Pop1_pop1, + Popi, + Popi_pop1, + Popi_popi, + Popi_popi8, + Popi_popi_popi, + Popi_popr4, + Popi_popr8, + Popref, + Popref_pop1, + Popref_popi, + Popref_popi_popi, + Popref_popi_popi8, + Popref_popi_popr4, + Popref_popi_popr8, + Popref_popi_popref, + PopAll, + Push0, + Push1, + Push1_push1, + Pushi, + Pushi8, + Pushr4, + Pushr8, + Pushref, + Varpop, + Varpush, + } + + public struct OpCode { + + readonly byte op1; + readonly byte op2; + readonly byte code; + readonly byte flow_control; + readonly byte opcode_type; + readonly byte operand_type; + readonly byte stack_behavior_pop; + readonly byte stack_behavior_push; + + public string Name { + get { return OpCodeNames.names [(int) Code]; } + } + + public int Size { + get { return op1 == 0xff ? 1 : 2; } + } + + public byte Op1 { + get { return op1; } + } + + public byte Op2 { + get { return op2; } + } + + public short Value { + get { return op1 == 0xff ? op2 : (short) ((op1 << 8) | op2); } + } + + public Code Code { + get { return (Code) code; } + } + + public FlowControl FlowControl { + get { return (FlowControl) flow_control; } + } + + public OpCodeType OpCodeType { + get { return (OpCodeType) opcode_type; } + } + + public OperandType OperandType { + get { return (OperandType) operand_type; } + } + + public StackBehaviour StackBehaviourPop { + get { return (StackBehaviour) stack_behavior_pop; } + } + + public StackBehaviour StackBehaviourPush { + get { return (StackBehaviour) stack_behavior_push; } + } + + internal OpCode (int x, int y) + { + this.op1 = (byte) ((x >> 0) & 0xff); + this.op2 = (byte) ((x >> 8) & 0xff); + this.code = (byte) ((x >> 16) & 0xff); + this.flow_control = (byte) ((x >> 24) & 0xff); + + this.opcode_type = (byte) ((y >> 0) & 0xff); + this.operand_type = (byte) ((y >> 8) & 0xff); + this.stack_behavior_pop = (byte) ((y >> 16) & 0xff); + this.stack_behavior_push = (byte) ((y >> 24) & 0xff); + + if (op1 == 0xff) + OpCodes.OneByteOpCode [op2] = this; + else + OpCodes.TwoBytesOpCode [op2] = this; + } + + public override int GetHashCode () + { + return Value; + } + + public override bool Equals (object obj) + { + if (!(obj is OpCode)) + return false; + + var opcode = (OpCode) obj; + return op1 == opcode.op1 && op2 == opcode.op2; + } + + public bool Equals (OpCode opcode) + { + return op1 == opcode.op1 && op2 == opcode.op2; + } + + public static bool operator == (OpCode one, OpCode other) + { + return one.op1 == other.op1 && one.op2 == other.op2; + } + + public static bool operator != (OpCode one, OpCode other) + { + return one.op1 != other.op1 || one.op2 != other.op2; + } + + public override string ToString () + { + return Name; + } + } + + static class OpCodeNames { + + internal static readonly string [] names; + + static OpCodeNames () + { + var table = new byte [] { + 3, 110, 111, 112, + 5, 98, 114, 101, 97, 107, + 7, 108, 100, 97, 114, 103, 46, 48, + 7, 108, 100, 97, 114, 103, 46, 49, + 7, 108, 100, 97, 114, 103, 46, 50, + 7, 108, 100, 97, 114, 103, 46, 51, + 7, 108, 100, 108, 111, 99, 46, 48, + 7, 108, 100, 108, 111, 99, 46, 49, + 7, 108, 100, 108, 111, 99, 46, 50, + 7, 108, 100, 108, 111, 99, 46, 51, + 7, 115, 116, 108, 111, 99, 46, 48, + 7, 115, 116, 108, 111, 99, 46, 49, + 7, 115, 116, 108, 111, 99, 46, 50, + 7, 115, 116, 108, 111, 99, 46, 51, + 7, 108, 100, 97, 114, 103, 46, 115, + 8, 108, 100, 97, 114, 103, 97, 46, 115, + 7, 115, 116, 97, 114, 103, 46, 115, + 7, 108, 100, 108, 111, 99, 46, 115, + 8, 108, 100, 108, 111, 99, 97, 46, 115, + 7, 115, 116, 108, 111, 99, 46, 115, + 6, 108, 100, 110, 117, 108, 108, + 9, 108, 100, 99, 46, 105, 52, 46, 109, 49, + 8, 108, 100, 99, 46, 105, 52, 46, 48, + 8, 108, 100, 99, 46, 105, 52, 46, 49, + 8, 108, 100, 99, 46, 105, 52, 46, 50, + 8, 108, 100, 99, 46, 105, 52, 46, 51, + 8, 108, 100, 99, 46, 105, 52, 46, 52, + 8, 108, 100, 99, 46, 105, 52, 46, 53, + 8, 108, 100, 99, 46, 105, 52, 46, 54, + 8, 108, 100, 99, 46, 105, 52, 46, 55, + 8, 108, 100, 99, 46, 105, 52, 46, 56, + 8, 108, 100, 99, 46, 105, 52, 46, 115, + 6, 108, 100, 99, 46, 105, 52, + 6, 108, 100, 99, 46, 105, 56, + 6, 108, 100, 99, 46, 114, 52, + 6, 108, 100, 99, 46, 114, 56, + 3, 100, 117, 112, + 3, 112, 111, 112, + 3, 106, 109, 112, + 4, 99, 97, 108, 108, + 5, 99, 97, 108, 108, 105, + 3, 114, 101, 116, + 4, 98, 114, 46, 115, + 9, 98, 114, 102, 97, 108, 115, 101, 46, 115, + 8, 98, 114, 116, 114, 117, 101, 46, 115, + 5, 98, 101, 113, 46, 115, + 5, 98, 103, 101, 46, 115, + 5, 98, 103, 116, 46, 115, + 5, 98, 108, 101, 46, 115, + 5, 98, 108, 116, 46, 115, + 8, 98, 110, 101, 46, 117, 110, 46, 115, + 8, 98, 103, 101, 46, 117, 110, 46, 115, + 8, 98, 103, 116, 46, 117, 110, 46, 115, + 8, 98, 108, 101, 46, 117, 110, 46, 115, + 8, 98, 108, 116, 46, 117, 110, 46, 115, + 2, 98, 114, + 7, 98, 114, 102, 97, 108, 115, 101, + 6, 98, 114, 116, 114, 117, 101, + 3, 98, 101, 113, + 3, 98, 103, 101, + 3, 98, 103, 116, + 3, 98, 108, 101, + 3, 98, 108, 116, + 6, 98, 110, 101, 46, 117, 110, + 6, 98, 103, 101, 46, 117, 110, + 6, 98, 103, 116, 46, 117, 110, + 6, 98, 108, 101, 46, 117, 110, + 6, 98, 108, 116, 46, 117, 110, + 6, 115, 119, 105, 116, 99, 104, + 8, 108, 100, 105, 110, 100, 46, 105, 49, + 8, 108, 100, 105, 110, 100, 46, 117, 49, + 8, 108, 100, 105, 110, 100, 46, 105, 50, + 8, 108, 100, 105, 110, 100, 46, 117, 50, + 8, 108, 100, 105, 110, 100, 46, 105, 52, + 8, 108, 100, 105, 110, 100, 46, 117, 52, + 8, 108, 100, 105, 110, 100, 46, 105, 56, + 7, 108, 100, 105, 110, 100, 46, 105, + 8, 108, 100, 105, 110, 100, 46, 114, 52, + 8, 108, 100, 105, 110, 100, 46, 114, 56, + 9, 108, 100, 105, 110, 100, 46, 114, 101, 102, + 9, 115, 116, 105, 110, 100, 46, 114, 101, 102, + 8, 115, 116, 105, 110, 100, 46, 105, 49, + 8, 115, 116, 105, 110, 100, 46, 105, 50, + 8, 115, 116, 105, 110, 100, 46, 105, 52, + 8, 115, 116, 105, 110, 100, 46, 105, 56, + 8, 115, 116, 105, 110, 100, 46, 114, 52, + 8, 115, 116, 105, 110, 100, 46, 114, 56, + 3, 97, 100, 100, + 3, 115, 117, 98, + 3, 109, 117, 108, + 3, 100, 105, 118, + 6, 100, 105, 118, 46, 117, 110, + 3, 114, 101, 109, + 6, 114, 101, 109, 46, 117, 110, + 3, 97, 110, 100, + 2, 111, 114, + 3, 120, 111, 114, + 3, 115, 104, 108, + 3, 115, 104, 114, + 6, 115, 104, 114, 46, 117, 110, + 3, 110, 101, 103, + 3, 110, 111, 116, + 7, 99, 111, 110, 118, 46, 105, 49, + 7, 99, 111, 110, 118, 46, 105, 50, + 7, 99, 111, 110, 118, 46, 105, 52, + 7, 99, 111, 110, 118, 46, 105, 56, + 7, 99, 111, 110, 118, 46, 114, 52, + 7, 99, 111, 110, 118, 46, 114, 56, + 7, 99, 111, 110, 118, 46, 117, 52, + 7, 99, 111, 110, 118, 46, 117, 56, + 8, 99, 97, 108, 108, 118, 105, 114, 116, + 5, 99, 112, 111, 98, 106, + 5, 108, 100, 111, 98, 106, + 5, 108, 100, 115, 116, 114, + 6, 110, 101, 119, 111, 98, 106, + 9, 99, 97, 115, 116, 99, 108, 97, 115, 115, + 6, 105, 115, 105, 110, 115, 116, + 9, 99, 111, 110, 118, 46, 114, 46, 117, 110, + 5, 117, 110, 98, 111, 120, + 5, 116, 104, 114, 111, 119, + 5, 108, 100, 102, 108, 100, + 6, 108, 100, 102, 108, 100, 97, + 5, 115, 116, 102, 108, 100, + 6, 108, 100, 115, 102, 108, 100, + 7, 108, 100, 115, 102, 108, 100, 97, + 6, 115, 116, 115, 102, 108, 100, + 5, 115, 116, 111, 98, 106, + 14, 99, 111, 110, 118, 46, 111, 118, 102, 46, 105, 49, 46, 117, 110, + 14, 99, 111, 110, 118, 46, 111, 118, 102, 46, 105, 50, 46, 117, 110, + 14, 99, 111, 110, 118, 46, 111, 118, 102, 46, 105, 52, 46, 117, 110, + 14, 99, 111, 110, 118, 46, 111, 118, 102, 46, 105, 56, 46, 117, 110, + 14, 99, 111, 110, 118, 46, 111, 118, 102, 46, 117, 49, 46, 117, 110, + 14, 99, 111, 110, 118, 46, 111, 118, 102, 46, 117, 50, 46, 117, 110, + 14, 99, 111, 110, 118, 46, 111, 118, 102, 46, 117, 52, 46, 117, 110, + 14, 99, 111, 110, 118, 46, 111, 118, 102, 46, 117, 56, 46, 117, 110, + 13, 99, 111, 110, 118, 46, 111, 118, 102, 46, 105, 46, 117, 110, + 13, 99, 111, 110, 118, 46, 111, 118, 102, 46, 117, 46, 117, 110, + 3, 98, 111, 120, + 6, 110, 101, 119, 97, 114, 114, + 5, 108, 100, 108, 101, 110, + 7, 108, 100, 101, 108, 101, 109, 97, + 9, 108, 100, 101, 108, 101, 109, 46, 105, 49, + 9, 108, 100, 101, 108, 101, 109, 46, 117, 49, + 9, 108, 100, 101, 108, 101, 109, 46, 105, 50, + 9, 108, 100, 101, 108, 101, 109, 46, 117, 50, + 9, 108, 100, 101, 108, 101, 109, 46, 105, 52, + 9, 108, 100, 101, 108, 101, 109, 46, 117, 52, + 9, 108, 100, 101, 108, 101, 109, 46, 105, 56, + 8, 108, 100, 101, 108, 101, 109, 46, 105, + 9, 108, 100, 101, 108, 101, 109, 46, 114, 52, + 9, 108, 100, 101, 108, 101, 109, 46, 114, 56, + 10, 108, 100, 101, 108, 101, 109, 46, 114, 101, 102, + 8, 115, 116, 101, 108, 101, 109, 46, 105, + 9, 115, 116, 101, 108, 101, 109, 46, 105, 49, + 9, 115, 116, 101, 108, 101, 109, 46, 105, 50, + 9, 115, 116, 101, 108, 101, 109, 46, 105, 52, + 9, 115, 116, 101, 108, 101, 109, 46, 105, 56, + 9, 115, 116, 101, 108, 101, 109, 46, 114, 52, + 9, 115, 116, 101, 108, 101, 109, 46, 114, 56, + 10, 115, 116, 101, 108, 101, 109, 46, 114, 101, 102, + 10, 108, 100, 101, 108, 101, 109, 46, 97, 110, 121, + 10, 115, 116, 101, 108, 101, 109, 46, 97, 110, 121, + 9, 117, 110, 98, 111, 120, 46, 97, 110, 121, + 11, 99, 111, 110, 118, 46, 111, 118, 102, 46, 105, 49, + 11, 99, 111, 110, 118, 46, 111, 118, 102, 46, 117, 49, + 11, 99, 111, 110, 118, 46, 111, 118, 102, 46, 105, 50, + 11, 99, 111, 110, 118, 46, 111, 118, 102, 46, 117, 50, + 11, 99, 111, 110, 118, 46, 111, 118, 102, 46, 105, 52, + 11, 99, 111, 110, 118, 46, 111, 118, 102, 46, 117, 52, + 11, 99, 111, 110, 118, 46, 111, 118, 102, 46, 105, 56, + 11, 99, 111, 110, 118, 46, 111, 118, 102, 46, 117, 56, + 9, 114, 101, 102, 97, 110, 121, 118, 97, 108, + 8, 99, 107, 102, 105, 110, 105, 116, 101, + 8, 109, 107, 114, 101, 102, 97, 110, 121, + 7, 108, 100, 116, 111, 107, 101, 110, + 7, 99, 111, 110, 118, 46, 117, 50, + 7, 99, 111, 110, 118, 46, 117, 49, + 6, 99, 111, 110, 118, 46, 105, + 10, 99, 111, 110, 118, 46, 111, 118, 102, 46, 105, + 10, 99, 111, 110, 118, 46, 111, 118, 102, 46, 117, + 7, 97, 100, 100, 46, 111, 118, 102, + 10, 97, 100, 100, 46, 111, 118, 102, 46, 117, 110, + 7, 109, 117, 108, 46, 111, 118, 102, + 10, 109, 117, 108, 46, 111, 118, 102, 46, 117, 110, + 7, 115, 117, 98, 46, 111, 118, 102, + 10, 115, 117, 98, 46, 111, 118, 102, 46, 117, 110, + 10, 101, 110, 100, 102, 105, 110, 97, 108, 108, 121, + 5, 108, 101, 97, 118, 101, + 7, 108, 101, 97, 118, 101, 46, 115, + 7, 115, 116, 105, 110, 100, 46, 105, + 6, 99, 111, 110, 118, 46, 117, + 7, 97, 114, 103, 108, 105, 115, 116, + 3, 99, 101, 113, + 3, 99, 103, 116, + 6, 99, 103, 116, 46, 117, 110, + 3, 99, 108, 116, + 6, 99, 108, 116, 46, 117, 110, + 5, 108, 100, 102, 116, 110, + 9, 108, 100, 118, 105, 114, 116, 102, 116, 110, + 5, 108, 100, 97, 114, 103, + 6, 108, 100, 97, 114, 103, 97, + 5, 115, 116, 97, 114, 103, + 5, 108, 100, 108, 111, 99, + 6, 108, 100, 108, 111, 99, 97, + 5, 115, 116, 108, 111, 99, + 8, 108, 111, 99, 97, 108, 108, 111, 99, + 9, 101, 110, 100, 102, 105, 108, 116, 101, 114, + 10, 117, 110, 97, 108, 105, 103, 110, 101, 100, 46, + 9, 118, 111, 108, 97, 116, 105, 108, 101, 46, + 5, 116, 97, 105, 108, 46, + 7, 105, 110, 105, 116, 111, 98, 106, + 12, 99, 111, 110, 115, 116, 114, 97, 105, 110, 101, 100, 46, + 5, 99, 112, 98, 108, 107, + 7, 105, 110, 105, 116, 98, 108, 107, + 3, 110, 111, 46, + 7, 114, 101, 116, 104, 114, 111, 119, + 6, 115, 105, 122, 101, 111, 102, + 10, 114, 101, 102, 97, 110, 121, 116, 121, 112, 101, + 9, 114, 101, 97, 100, 111, 110, 108, 121, 46, + }; + + names = new string [219]; + + for (int i = 0, p = 0; i < names.Length; i++) { + var buffer = new char [table [p++]]; + + for (int j = 0; j < buffer.Length; j++) + buffer [j] = (char) table [p++]; + + names [i] = new string (buffer); + } + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil.Cil/OpCodes.cs b/external/cecil-legacy/Mono.Cecil.Cil/OpCodes.cs new file mode 100644 index 0000000000..85712ec8b8 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil.Cil/OpCodes.cs @@ -0,0 +1,912 @@ +// +// OpCodes.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +namespace Mono.Cecil.Cil { + + public static class OpCodes { + + internal static readonly OpCode [] OneByteOpCode = new OpCode [0xe0 + 1]; + internal static readonly OpCode [] TwoBytesOpCode = new OpCode [0x1e + 1]; + + public static readonly OpCode Nop = new OpCode ( + 0xff << 0 | 0x00 << 8 | (byte) Code.Nop << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Break = new OpCode ( + 0xff << 0 | 0x01 << 8 | (byte) Code.Break << 16 | (byte) FlowControl.Break << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Ldarg_0 = new OpCode ( + 0xff << 0 | 0x02 << 8 | (byte) Code.Ldarg_0 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push1 << 24); + + public static readonly OpCode Ldarg_1 = new OpCode ( + 0xff << 0 | 0x03 << 8 | (byte) Code.Ldarg_1 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push1 << 24); + + public static readonly OpCode Ldarg_2 = new OpCode ( + 0xff << 0 | 0x04 << 8 | (byte) Code.Ldarg_2 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push1 << 24); + + public static readonly OpCode Ldarg_3 = new OpCode ( + 0xff << 0 | 0x05 << 8 | (byte) Code.Ldarg_3 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push1 << 24); + + public static readonly OpCode Ldloc_0 = new OpCode ( + 0xff << 0 | 0x06 << 8 | (byte) Code.Ldloc_0 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push1 << 24); + + public static readonly OpCode Ldloc_1 = new OpCode ( + 0xff << 0 | 0x07 << 8 | (byte) Code.Ldloc_1 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push1 << 24); + + public static readonly OpCode Ldloc_2 = new OpCode ( + 0xff << 0 | 0x08 << 8 | (byte) Code.Ldloc_2 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push1 << 24); + + public static readonly OpCode Ldloc_3 = new OpCode ( + 0xff << 0 | 0x09 << 8 | (byte) Code.Ldloc_3 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push1 << 24); + + public static readonly OpCode Stloc_0 = new OpCode ( + 0xff << 0 | 0x0a << 8 | (byte) Code.Stloc_0 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Stloc_1 = new OpCode ( + 0xff << 0 | 0x0b << 8 | (byte) Code.Stloc_1 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Stloc_2 = new OpCode ( + 0xff << 0 | 0x0c << 8 | (byte) Code.Stloc_2 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Stloc_3 = new OpCode ( + 0xff << 0 | 0x0d << 8 | (byte) Code.Stloc_3 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Ldarg_S = new OpCode ( + 0xff << 0 | 0x0e << 8 | (byte) Code.Ldarg_S << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineArg << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push1 << 24); + + public static readonly OpCode Ldarga_S = new OpCode ( + 0xff << 0 | 0x0f << 8 | (byte) Code.Ldarga_S << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineArg << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Starg_S = new OpCode ( + 0xff << 0 | 0x10 << 8 | (byte) Code.Starg_S << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineArg << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Ldloc_S = new OpCode ( + 0xff << 0 | 0x11 << 8 | (byte) Code.Ldloc_S << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineVar << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push1 << 24); + + public static readonly OpCode Ldloca_S = new OpCode ( + 0xff << 0 | 0x12 << 8 | (byte) Code.Ldloca_S << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineVar << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Stloc_S = new OpCode ( + 0xff << 0 | 0x13 << 8 | (byte) Code.Stloc_S << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineVar << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Ldnull = new OpCode ( + 0xff << 0 | 0x14 << 8 | (byte) Code.Ldnull << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushref << 24); + + public static readonly OpCode Ldc_I4_M1 = new OpCode ( + 0xff << 0 | 0x15 << 8 | (byte) Code.Ldc_I4_M1 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Ldc_I4_0 = new OpCode ( + 0xff << 0 | 0x16 << 8 | (byte) Code.Ldc_I4_0 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Ldc_I4_1 = new OpCode ( + 0xff << 0 | 0x17 << 8 | (byte) Code.Ldc_I4_1 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Ldc_I4_2 = new OpCode ( + 0xff << 0 | 0x18 << 8 | (byte) Code.Ldc_I4_2 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Ldc_I4_3 = new OpCode ( + 0xff << 0 | 0x19 << 8 | (byte) Code.Ldc_I4_3 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Ldc_I4_4 = new OpCode ( + 0xff << 0 | 0x1a << 8 | (byte) Code.Ldc_I4_4 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Ldc_I4_5 = new OpCode ( + 0xff << 0 | 0x1b << 8 | (byte) Code.Ldc_I4_5 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Ldc_I4_6 = new OpCode ( + 0xff << 0 | 0x1c << 8 | (byte) Code.Ldc_I4_6 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Ldc_I4_7 = new OpCode ( + 0xff << 0 | 0x1d << 8 | (byte) Code.Ldc_I4_7 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Ldc_I4_8 = new OpCode ( + 0xff << 0 | 0x1e << 8 | (byte) Code.Ldc_I4_8 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Ldc_I4_S = new OpCode ( + 0xff << 0 | 0x1f << 8 | (byte) Code.Ldc_I4_S << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineI << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Ldc_I4 = new OpCode ( + 0xff << 0 | 0x20 << 8 | (byte) Code.Ldc_I4 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineI << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Ldc_I8 = new OpCode ( + 0xff << 0 | 0x21 << 8 | (byte) Code.Ldc_I8 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineI8 << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi8 << 24); + + public static readonly OpCode Ldc_R4 = new OpCode ( + 0xff << 0 | 0x22 << 8 | (byte) Code.Ldc_R4 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.ShortInlineR << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushr4 << 24); + + public static readonly OpCode Ldc_R8 = new OpCode ( + 0xff << 0 | 0x23 << 8 | (byte) Code.Ldc_R8 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineR << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushr8 << 24); + + public static readonly OpCode Dup = new OpCode ( + 0xff << 0 | 0x25 << 8 | (byte) Code.Dup << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Push1_push1 << 24); + + public static readonly OpCode Pop = new OpCode ( + 0xff << 0 | 0x26 << 8 | (byte) Code.Pop << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Jmp = new OpCode ( + 0xff << 0 | 0x27 << 8 | (byte) Code.Jmp << 16 | (byte) FlowControl.Call << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineMethod << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Call = new OpCode ( + 0xff << 0 | 0x28 << 8 | (byte) Code.Call << 16 | (byte) FlowControl.Call << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineMethod << 8 | (byte) StackBehaviour.Varpop << 16 | (byte) StackBehaviour.Varpush << 24); + + public static readonly OpCode Calli = new OpCode ( + 0xff << 0 | 0x29 << 8 | (byte) Code.Calli << 16 | (byte) FlowControl.Call << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineSig << 8 | (byte) StackBehaviour.Varpop << 16 | (byte) StackBehaviour.Varpush << 24); + + public static readonly OpCode Ret = new OpCode ( + 0xff << 0 | 0x2a << 8 | (byte) Code.Ret << 16 | (byte) FlowControl.Return << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Varpop << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Br_S = new OpCode ( + 0xff << 0 | 0x2b << 8 | (byte) Code.Br_S << 16 | (byte) FlowControl.Branch << 24, + (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineBrTarget << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Brfalse_S = new OpCode ( + 0xff << 0 | 0x2c << 8 | (byte) Code.Brfalse_S << 16 | (byte) FlowControl.Cond_Branch << 24, + (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineBrTarget << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Brtrue_S = new OpCode ( + 0xff << 0 | 0x2d << 8 | (byte) Code.Brtrue_S << 16 | (byte) FlowControl.Cond_Branch << 24, + (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineBrTarget << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Beq_S = new OpCode ( + 0xff << 0 | 0x2e << 8 | (byte) Code.Beq_S << 16 | (byte) FlowControl.Cond_Branch << 24, + (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Bge_S = new OpCode ( + 0xff << 0 | 0x2f << 8 | (byte) Code.Bge_S << 16 | (byte) FlowControl.Cond_Branch << 24, + (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Bgt_S = new OpCode ( + 0xff << 0 | 0x30 << 8 | (byte) Code.Bgt_S << 16 | (byte) FlowControl.Cond_Branch << 24, + (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Ble_S = new OpCode ( + 0xff << 0 | 0x31 << 8 | (byte) Code.Ble_S << 16 | (byte) FlowControl.Cond_Branch << 24, + (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Blt_S = new OpCode ( + 0xff << 0 | 0x32 << 8 | (byte) Code.Blt_S << 16 | (byte) FlowControl.Cond_Branch << 24, + (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Bne_Un_S = new OpCode ( + 0xff << 0 | 0x33 << 8 | (byte) Code.Bne_Un_S << 16 | (byte) FlowControl.Cond_Branch << 24, + (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Bge_Un_S = new OpCode ( + 0xff << 0 | 0x34 << 8 | (byte) Code.Bge_Un_S << 16 | (byte) FlowControl.Cond_Branch << 24, + (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Bgt_Un_S = new OpCode ( + 0xff << 0 | 0x35 << 8 | (byte) Code.Bgt_Un_S << 16 | (byte) FlowControl.Cond_Branch << 24, + (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Ble_Un_S = new OpCode ( + 0xff << 0 | 0x36 << 8 | (byte) Code.Ble_Un_S << 16 | (byte) FlowControl.Cond_Branch << 24, + (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Blt_Un_S = new OpCode ( + 0xff << 0 | 0x37 << 8 | (byte) Code.Blt_Un_S << 16 | (byte) FlowControl.Cond_Branch << 24, + (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Br = new OpCode ( + 0xff << 0 | 0x38 << 8 | (byte) Code.Br << 16 | (byte) FlowControl.Branch << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineBrTarget << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Brfalse = new OpCode ( + 0xff << 0 | 0x39 << 8 | (byte) Code.Brfalse << 16 | (byte) FlowControl.Cond_Branch << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineBrTarget << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Brtrue = new OpCode ( + 0xff << 0 | 0x3a << 8 | (byte) Code.Brtrue << 16 | (byte) FlowControl.Cond_Branch << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineBrTarget << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Beq = new OpCode ( + 0xff << 0 | 0x3b << 8 | (byte) Code.Beq << 16 | (byte) FlowControl.Cond_Branch << 24, + (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Bge = new OpCode ( + 0xff << 0 | 0x3c << 8 | (byte) Code.Bge << 16 | (byte) FlowControl.Cond_Branch << 24, + (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Bgt = new OpCode ( + 0xff << 0 | 0x3d << 8 | (byte) Code.Bgt << 16 | (byte) FlowControl.Cond_Branch << 24, + (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Ble = new OpCode ( + 0xff << 0 | 0x3e << 8 | (byte) Code.Ble << 16 | (byte) FlowControl.Cond_Branch << 24, + (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Blt = new OpCode ( + 0xff << 0 | 0x3f << 8 | (byte) Code.Blt << 16 | (byte) FlowControl.Cond_Branch << 24, + (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Bne_Un = new OpCode ( + 0xff << 0 | 0x40 << 8 | (byte) Code.Bne_Un << 16 | (byte) FlowControl.Cond_Branch << 24, + (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Bge_Un = new OpCode ( + 0xff << 0 | 0x41 << 8 | (byte) Code.Bge_Un << 16 | (byte) FlowControl.Cond_Branch << 24, + (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Bgt_Un = new OpCode ( + 0xff << 0 | 0x42 << 8 | (byte) Code.Bgt_Un << 16 | (byte) FlowControl.Cond_Branch << 24, + (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Ble_Un = new OpCode ( + 0xff << 0 | 0x43 << 8 | (byte) Code.Ble_Un << 16 | (byte) FlowControl.Cond_Branch << 24, + (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Blt_Un = new OpCode ( + 0xff << 0 | 0x44 << 8 | (byte) Code.Blt_Un << 16 | (byte) FlowControl.Cond_Branch << 24, + (byte) OpCodeType.Macro << 0 | (byte) OperandType.InlineBrTarget << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Switch = new OpCode ( + 0xff << 0 | 0x45 << 8 | (byte) Code.Switch << 16 | (byte) FlowControl.Cond_Branch << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineSwitch << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Ldind_I1 = new OpCode ( + 0xff << 0 | 0x46 << 8 | (byte) Code.Ldind_I1 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Ldind_U1 = new OpCode ( + 0xff << 0 | 0x47 << 8 | (byte) Code.Ldind_U1 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Ldind_I2 = new OpCode ( + 0xff << 0 | 0x48 << 8 | (byte) Code.Ldind_I2 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Ldind_U2 = new OpCode ( + 0xff << 0 | 0x49 << 8 | (byte) Code.Ldind_U2 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Ldind_I4 = new OpCode ( + 0xff << 0 | 0x4a << 8 | (byte) Code.Ldind_I4 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Ldind_U4 = new OpCode ( + 0xff << 0 | 0x4b << 8 | (byte) Code.Ldind_U4 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Ldind_I8 = new OpCode ( + 0xff << 0 | 0x4c << 8 | (byte) Code.Ldind_I8 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Pushi8 << 24); + + public static readonly OpCode Ldind_I = new OpCode ( + 0xff << 0 | 0x4d << 8 | (byte) Code.Ldind_I << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Ldind_R4 = new OpCode ( + 0xff << 0 | 0x4e << 8 | (byte) Code.Ldind_R4 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Pushr4 << 24); + + public static readonly OpCode Ldind_R8 = new OpCode ( + 0xff << 0 | 0x4f << 8 | (byte) Code.Ldind_R8 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Pushr8 << 24); + + public static readonly OpCode Ldind_Ref = new OpCode ( + 0xff << 0 | 0x50 << 8 | (byte) Code.Ldind_Ref << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Pushref << 24); + + public static readonly OpCode Stind_Ref = new OpCode ( + 0xff << 0 | 0x51 << 8 | (byte) Code.Stind_Ref << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi_popi << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Stind_I1 = new OpCode ( + 0xff << 0 | 0x52 << 8 | (byte) Code.Stind_I1 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi_popi << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Stind_I2 = new OpCode ( + 0xff << 0 | 0x53 << 8 | (byte) Code.Stind_I2 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi_popi << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Stind_I4 = new OpCode ( + 0xff << 0 | 0x54 << 8 | (byte) Code.Stind_I4 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi_popi << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Stind_I8 = new OpCode ( + 0xff << 0 | 0x55 << 8 | (byte) Code.Stind_I8 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi_popi8 << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Stind_R4 = new OpCode ( + 0xff << 0 | 0x56 << 8 | (byte) Code.Stind_R4 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi_popr4 << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Stind_R8 = new OpCode ( + 0xff << 0 | 0x57 << 8 | (byte) Code.Stind_R8 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi_popr8 << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Add = new OpCode ( + 0xff << 0 | 0x58 << 8 | (byte) Code.Add << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); + + public static readonly OpCode Sub = new OpCode ( + 0xff << 0 | 0x59 << 8 | (byte) Code.Sub << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); + + public static readonly OpCode Mul = new OpCode ( + 0xff << 0 | 0x5a << 8 | (byte) Code.Mul << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); + + public static readonly OpCode Div = new OpCode ( + 0xff << 0 | 0x5b << 8 | (byte) Code.Div << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); + + public static readonly OpCode Div_Un = new OpCode ( + 0xff << 0 | 0x5c << 8 | (byte) Code.Div_Un << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); + + public static readonly OpCode Rem = new OpCode ( + 0xff << 0 | 0x5d << 8 | (byte) Code.Rem << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); + + public static readonly OpCode Rem_Un = new OpCode ( + 0xff << 0 | 0x5e << 8 | (byte) Code.Rem_Un << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); + + public static readonly OpCode And = new OpCode ( + 0xff << 0 | 0x5f << 8 | (byte) Code.And << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); + + public static readonly OpCode Or = new OpCode ( + 0xff << 0 | 0x60 << 8 | (byte) Code.Or << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); + + public static readonly OpCode Xor = new OpCode ( + 0xff << 0 | 0x61 << 8 | (byte) Code.Xor << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); + + public static readonly OpCode Shl = new OpCode ( + 0xff << 0 | 0x62 << 8 | (byte) Code.Shl << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); + + public static readonly OpCode Shr = new OpCode ( + 0xff << 0 | 0x63 << 8 | (byte) Code.Shr << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); + + public static readonly OpCode Shr_Un = new OpCode ( + 0xff << 0 | 0x64 << 8 | (byte) Code.Shr_Un << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); + + public static readonly OpCode Neg = new OpCode ( + 0xff << 0 | 0x65 << 8 | (byte) Code.Neg << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Push1 << 24); + + public static readonly OpCode Not = new OpCode ( + 0xff << 0 | 0x66 << 8 | (byte) Code.Not << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Push1 << 24); + + public static readonly OpCode Conv_I1 = new OpCode ( + 0xff << 0 | 0x67 << 8 | (byte) Code.Conv_I1 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Conv_I2 = new OpCode ( + 0xff << 0 | 0x68 << 8 | (byte) Code.Conv_I2 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Conv_I4 = new OpCode ( + 0xff << 0 | 0x69 << 8 | (byte) Code.Conv_I4 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Conv_I8 = new OpCode ( + 0xff << 0 | 0x6a << 8 | (byte) Code.Conv_I8 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi8 << 24); + + public static readonly OpCode Conv_R4 = new OpCode ( + 0xff << 0 | 0x6b << 8 | (byte) Code.Conv_R4 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushr4 << 24); + + public static readonly OpCode Conv_R8 = new OpCode ( + 0xff << 0 | 0x6c << 8 | (byte) Code.Conv_R8 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushr8 << 24); + + public static readonly OpCode Conv_U4 = new OpCode ( + 0xff << 0 | 0x6d << 8 | (byte) Code.Conv_U4 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Conv_U8 = new OpCode ( + 0xff << 0 | 0x6e << 8 | (byte) Code.Conv_U8 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi8 << 24); + + public static readonly OpCode Callvirt = new OpCode ( + 0xff << 0 | 0x6f << 8 | (byte) Code.Callvirt << 16 | (byte) FlowControl.Call << 24, + (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineMethod << 8 | (byte) StackBehaviour.Varpop << 16 | (byte) StackBehaviour.Varpush << 24); + + public static readonly OpCode Cpobj = new OpCode ( + 0xff << 0 | 0x70 << 8 | (byte) Code.Cpobj << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Popi_popi << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Ldobj = new OpCode ( + 0xff << 0 | 0x71 << 8 | (byte) Code.Ldobj << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Push1 << 24); + + public static readonly OpCode Ldstr = new OpCode ( + 0xff << 0 | 0x72 << 8 | (byte) Code.Ldstr << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineString << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushref << 24); + + public static readonly OpCode Newobj = new OpCode ( + 0xff << 0 | 0x73 << 8 | (byte) Code.Newobj << 16 | (byte) FlowControl.Call << 24, + (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineMethod << 8 | (byte) StackBehaviour.Varpop << 16 | (byte) StackBehaviour.Pushref << 24); + + public static readonly OpCode Castclass = new OpCode ( + 0xff << 0 | 0x74 << 8 | (byte) Code.Castclass << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Popref << 16 | (byte) StackBehaviour.Pushref << 24); + + public static readonly OpCode Isinst = new OpCode ( + 0xff << 0 | 0x75 << 8 | (byte) Code.Isinst << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Popref << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Conv_R_Un = new OpCode ( + 0xff << 0 | 0x76 << 8 | (byte) Code.Conv_R_Un << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushr8 << 24); + + public static readonly OpCode Unbox = new OpCode ( + 0xff << 0 | 0x79 << 8 | (byte) Code.Unbox << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Popref << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Throw = new OpCode ( + 0xff << 0 | 0x7a << 8 | (byte) Code.Throw << 16 | (byte) FlowControl.Throw << 24, + (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Ldfld = new OpCode ( + 0xff << 0 | 0x7b << 8 | (byte) Code.Ldfld << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineField << 8 | (byte) StackBehaviour.Popref << 16 | (byte) StackBehaviour.Push1 << 24); + + public static readonly OpCode Ldflda = new OpCode ( + 0xff << 0 | 0x7c << 8 | (byte) Code.Ldflda << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineField << 8 | (byte) StackBehaviour.Popref << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Stfld = new OpCode ( + 0xff << 0 | 0x7d << 8 | (byte) Code.Stfld << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineField << 8 | (byte) StackBehaviour.Popref_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Ldsfld = new OpCode ( + 0xff << 0 | 0x7e << 8 | (byte) Code.Ldsfld << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineField << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push1 << 24); + + public static readonly OpCode Ldsflda = new OpCode ( + 0xff << 0 | 0x7f << 8 | (byte) Code.Ldsflda << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineField << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Stsfld = new OpCode ( + 0xff << 0 | 0x80 << 8 | (byte) Code.Stsfld << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineField << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Stobj = new OpCode ( + 0xff << 0 | 0x81 << 8 | (byte) Code.Stobj << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Popi_pop1 << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Conv_Ovf_I1_Un = new OpCode ( + 0xff << 0 | 0x82 << 8 | (byte) Code.Conv_Ovf_I1_Un << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Conv_Ovf_I2_Un = new OpCode ( + 0xff << 0 | 0x83 << 8 | (byte) Code.Conv_Ovf_I2_Un << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Conv_Ovf_I4_Un = new OpCode ( + 0xff << 0 | 0x84 << 8 | (byte) Code.Conv_Ovf_I4_Un << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Conv_Ovf_I8_Un = new OpCode ( + 0xff << 0 | 0x85 << 8 | (byte) Code.Conv_Ovf_I8_Un << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi8 << 24); + + public static readonly OpCode Conv_Ovf_U1_Un = new OpCode ( + 0xff << 0 | 0x86 << 8 | (byte) Code.Conv_Ovf_U1_Un << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Conv_Ovf_U2_Un = new OpCode ( + 0xff << 0 | 0x87 << 8 | (byte) Code.Conv_Ovf_U2_Un << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Conv_Ovf_U4_Un = new OpCode ( + 0xff << 0 | 0x88 << 8 | (byte) Code.Conv_Ovf_U4_Un << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Conv_Ovf_U8_Un = new OpCode ( + 0xff << 0 | 0x89 << 8 | (byte) Code.Conv_Ovf_U8_Un << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi8 << 24); + + public static readonly OpCode Conv_Ovf_I_Un = new OpCode ( + 0xff << 0 | 0x8a << 8 | (byte) Code.Conv_Ovf_I_Un << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Conv_Ovf_U_Un = new OpCode ( + 0xff << 0 | 0x8b << 8 | (byte) Code.Conv_Ovf_U_Un << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Box = new OpCode ( + 0xff << 0 | 0x8c << 8 | (byte) Code.Box << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushref << 24); + + public static readonly OpCode Newarr = new OpCode ( + 0xff << 0 | 0x8d << 8 | (byte) Code.Newarr << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Pushref << 24); + + public static readonly OpCode Ldlen = new OpCode ( + 0xff << 0 | 0x8e << 8 | (byte) Code.Ldlen << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Ldelema = new OpCode ( + 0xff << 0 | 0x8f << 8 | (byte) Code.Ldelema << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Popref_popi << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Ldelem_I1 = new OpCode ( + 0xff << 0 | 0x90 << 8 | (byte) Code.Ldelem_I1 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Ldelem_U1 = new OpCode ( + 0xff << 0 | 0x91 << 8 | (byte) Code.Ldelem_U1 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Ldelem_I2 = new OpCode ( + 0xff << 0 | 0x92 << 8 | (byte) Code.Ldelem_I2 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Ldelem_U2 = new OpCode ( + 0xff << 0 | 0x93 << 8 | (byte) Code.Ldelem_U2 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Ldelem_I4 = new OpCode ( + 0xff << 0 | 0x94 << 8 | (byte) Code.Ldelem_I4 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Ldelem_U4 = new OpCode ( + 0xff << 0 | 0x95 << 8 | (byte) Code.Ldelem_U4 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Ldelem_I8 = new OpCode ( + 0xff << 0 | 0x96 << 8 | (byte) Code.Ldelem_I8 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi << 16 | (byte) StackBehaviour.Pushi8 << 24); + + public static readonly OpCode Ldelem_I = new OpCode ( + 0xff << 0 | 0x97 << 8 | (byte) Code.Ldelem_I << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Ldelem_R4 = new OpCode ( + 0xff << 0 | 0x98 << 8 | (byte) Code.Ldelem_R4 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi << 16 | (byte) StackBehaviour.Pushr4 << 24); + + public static readonly OpCode Ldelem_R8 = new OpCode ( + 0xff << 0 | 0x99 << 8 | (byte) Code.Ldelem_R8 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi << 16 | (byte) StackBehaviour.Pushr8 << 24); + + public static readonly OpCode Ldelem_Ref = new OpCode ( + 0xff << 0 | 0x9a << 8 | (byte) Code.Ldelem_Ref << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi << 16 | (byte) StackBehaviour.Pushref << 24); + + public static readonly OpCode Stelem_I = new OpCode ( + 0xff << 0 | 0x9b << 8 | (byte) Code.Stelem_I << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi_popi << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Stelem_I1 = new OpCode ( + 0xff << 0 | 0x9c << 8 | (byte) Code.Stelem_I1 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi_popi << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Stelem_I2 = new OpCode ( + 0xff << 0 | 0x9d << 8 | (byte) Code.Stelem_I2 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi_popi << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Stelem_I4 = new OpCode ( + 0xff << 0 | 0x9e << 8 | (byte) Code.Stelem_I4 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi_popi << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Stelem_I8 = new OpCode ( + 0xff << 0 | 0x9f << 8 | (byte) Code.Stelem_I8 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi_popi8 << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Stelem_R4 = new OpCode ( + 0xff << 0 | 0xa0 << 8 | (byte) Code.Stelem_R4 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi_popr4 << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Stelem_R8 = new OpCode ( + 0xff << 0 | 0xa1 << 8 | (byte) Code.Stelem_R8 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi_popr8 << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Stelem_Ref = new OpCode ( + 0xff << 0 | 0xa2 << 8 | (byte) Code.Stelem_Ref << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popref_popi_popref << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Ldelem_Any = new OpCode ( + 0xff << 0 | 0xa3 << 8 | (byte) Code.Ldelem_Any << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Popref_popi << 16 | (byte) StackBehaviour.Push1 << 24); + + public static readonly OpCode Stelem_Any = new OpCode ( + 0xff << 0 | 0xa4 << 8 | (byte) Code.Stelem_Any << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Popref_popi_popref << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Unbox_Any = new OpCode ( + 0xff << 0 | 0xa5 << 8 | (byte) Code.Unbox_Any << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Popref << 16 | (byte) StackBehaviour.Push1 << 24); + + public static readonly OpCode Conv_Ovf_I1 = new OpCode ( + 0xff << 0 | 0xb3 << 8 | (byte) Code.Conv_Ovf_I1 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Conv_Ovf_U1 = new OpCode ( + 0xff << 0 | 0xb4 << 8 | (byte) Code.Conv_Ovf_U1 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Conv_Ovf_I2 = new OpCode ( + 0xff << 0 | 0xb5 << 8 | (byte) Code.Conv_Ovf_I2 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Conv_Ovf_U2 = new OpCode ( + 0xff << 0 | 0xb6 << 8 | (byte) Code.Conv_Ovf_U2 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Conv_Ovf_I4 = new OpCode ( + 0xff << 0 | 0xb7 << 8 | (byte) Code.Conv_Ovf_I4 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Conv_Ovf_U4 = new OpCode ( + 0xff << 0 | 0xb8 << 8 | (byte) Code.Conv_Ovf_U4 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Conv_Ovf_I8 = new OpCode ( + 0xff << 0 | 0xb9 << 8 | (byte) Code.Conv_Ovf_I8 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi8 << 24); + + public static readonly OpCode Conv_Ovf_U8 = new OpCode ( + 0xff << 0 | 0xba << 8 | (byte) Code.Conv_Ovf_U8 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi8 << 24); + + public static readonly OpCode Refanyval = new OpCode ( + 0xff << 0 | 0xc2 << 8 | (byte) Code.Refanyval << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Ckfinite = new OpCode ( + 0xff << 0 | 0xc3 << 8 | (byte) Code.Ckfinite << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushr8 << 24); + + public static readonly OpCode Mkrefany = new OpCode ( + 0xff << 0 | 0xc6 << 8 | (byte) Code.Mkrefany << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Push1 << 24); + + public static readonly OpCode Ldtoken = new OpCode ( + 0xff << 0 | 0xd0 << 8 | (byte) Code.Ldtoken << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineTok << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Conv_U2 = new OpCode ( + 0xff << 0 | 0xd1 << 8 | (byte) Code.Conv_U2 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Conv_U1 = new OpCode ( + 0xff << 0 | 0xd2 << 8 | (byte) Code.Conv_U1 << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Conv_I = new OpCode ( + 0xff << 0 | 0xd3 << 8 | (byte) Code.Conv_I << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Conv_Ovf_I = new OpCode ( + 0xff << 0 | 0xd4 << 8 | (byte) Code.Conv_Ovf_I << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Conv_Ovf_U = new OpCode ( + 0xff << 0 | 0xd5 << 8 | (byte) Code.Conv_Ovf_U << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Add_Ovf = new OpCode ( + 0xff << 0 | 0xd6 << 8 | (byte) Code.Add_Ovf << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); + + public static readonly OpCode Add_Ovf_Un = new OpCode ( + 0xff << 0 | 0xd7 << 8 | (byte) Code.Add_Ovf_Un << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); + + public static readonly OpCode Mul_Ovf = new OpCode ( + 0xff << 0 | 0xd8 << 8 | (byte) Code.Mul_Ovf << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); + + public static readonly OpCode Mul_Ovf_Un = new OpCode ( + 0xff << 0 | 0xd9 << 8 | (byte) Code.Mul_Ovf_Un << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); + + public static readonly OpCode Sub_Ovf = new OpCode ( + 0xff << 0 | 0xda << 8 | (byte) Code.Sub_Ovf << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); + + public static readonly OpCode Sub_Ovf_Un = new OpCode ( + 0xff << 0 | 0xdb << 8 | (byte) Code.Sub_Ovf_Un << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Push1 << 24); + + public static readonly OpCode Endfinally = new OpCode ( + 0xff << 0 | 0xdc << 8 | (byte) Code.Endfinally << 16 | (byte) FlowControl.Return << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Leave = new OpCode ( + 0xff << 0 | 0xdd << 8 | (byte) Code.Leave << 16 | (byte) FlowControl.Branch << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineBrTarget << 8 | (byte) StackBehaviour.PopAll << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Leave_S = new OpCode ( + 0xff << 0 | 0xde << 8 | (byte) Code.Leave_S << 16 | (byte) FlowControl.Branch << 24, + (byte) OpCodeType.Macro << 0 | (byte) OperandType.ShortInlineBrTarget << 8 | (byte) StackBehaviour.PopAll << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Stind_I = new OpCode ( + 0xff << 0 | 0xdf << 8 | (byte) Code.Stind_I << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi_popi << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Conv_U = new OpCode ( + 0xff << 0 | 0xe0 << 8 | (byte) Code.Conv_U << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Arglist = new OpCode ( + 0xfe << 0 | 0x00 << 8 | (byte) Code.Arglist << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Ceq = new OpCode ( + 0xfe << 0 | 0x01 << 8 | (byte) Code.Ceq << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Cgt = new OpCode ( + 0xfe << 0 | 0x02 << 8 | (byte) Code.Cgt << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Cgt_Un = new OpCode ( + 0xfe << 0 | 0x03 << 8 | (byte) Code.Cgt_Un << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Clt = new OpCode ( + 0xfe << 0 | 0x04 << 8 | (byte) Code.Clt << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Clt_Un = new OpCode ( + 0xfe << 0 | 0x05 << 8 | (byte) Code.Clt_Un << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1_pop1 << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Ldftn = new OpCode ( + 0xfe << 0 | 0x06 << 8 | (byte) Code.Ldftn << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineMethod << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Ldvirtftn = new OpCode ( + 0xfe << 0 | 0x07 << 8 | (byte) Code.Ldvirtftn << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineMethod << 8 | (byte) StackBehaviour.Popref << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Ldarg = new OpCode ( + 0xfe << 0 | 0x09 << 8 | (byte) Code.Ldarg << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineArg << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push1 << 24); + + public static readonly OpCode Ldarga = new OpCode ( + 0xfe << 0 | 0x0a << 8 | (byte) Code.Ldarga << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineArg << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Starg = new OpCode ( + 0xfe << 0 | 0x0b << 8 | (byte) Code.Starg << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineArg << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Ldloc = new OpCode ( + 0xfe << 0 | 0x0c << 8 | (byte) Code.Ldloc << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineVar << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push1 << 24); + + public static readonly OpCode Ldloca = new OpCode ( + 0xfe << 0 | 0x0d << 8 | (byte) Code.Ldloca << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineVar << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Stloc = new OpCode ( + 0xfe << 0 | 0x0e << 8 | (byte) Code.Stloc << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineVar << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Localloc = new OpCode ( + 0xfe << 0 | 0x0f << 8 | (byte) Code.Localloc << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Endfilter = new OpCode ( + 0xfe << 0 | 0x11 << 8 | (byte) Code.Endfilter << 16 | (byte) FlowControl.Return << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Unaligned = new OpCode ( + 0xfe << 0 | 0x12 << 8 | (byte) Code.Unaligned << 16 | (byte) FlowControl.Meta << 24, + (byte) OpCodeType.Prefix << 0 | (byte) OperandType.ShortInlineI << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Volatile = new OpCode ( + 0xfe << 0 | 0x13 << 8 | (byte) Code.Volatile << 16 | (byte) FlowControl.Meta << 24, + (byte) OpCodeType.Prefix << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Tail = new OpCode ( + 0xfe << 0 | 0x14 << 8 | (byte) Code.Tail << 16 | (byte) FlowControl.Meta << 24, + (byte) OpCodeType.Prefix << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Initobj = new OpCode ( + 0xfe << 0 | 0x15 << 8 | (byte) Code.Initobj << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Popi << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Constrained = new OpCode ( + 0xfe << 0 | 0x16 << 8 | (byte) Code.Constrained << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Prefix << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Cpblk = new OpCode ( + 0xfe << 0 | 0x17 << 8 | (byte) Code.Cpblk << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi_popi_popi << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Initblk = new OpCode ( + 0xfe << 0 | 0x18 << 8 | (byte) Code.Initblk << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Popi_popi_popi << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode No = new OpCode ( + 0xfe << 0 | 0x19 << 8 | (byte) Code.No << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Prefix << 0 | (byte) OperandType.ShortInlineI << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Rethrow = new OpCode ( + 0xfe << 0 | 0x1a << 8 | (byte) Code.Rethrow << 16 | (byte) FlowControl.Throw << 24, + (byte) OpCodeType.Objmodel << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push0 << 24); + + public static readonly OpCode Sizeof = new OpCode ( + 0xfe << 0 | 0x1c << 8 | (byte) Code.Sizeof << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineType << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Refanytype = new OpCode ( + 0xfe << 0 | 0x1d << 8 | (byte) Code.Refanytype << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Primitive << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop1 << 16 | (byte) StackBehaviour.Pushi << 24); + + public static readonly OpCode Readonly = new OpCode ( + 0xfe << 0 | 0x1e << 8 | (byte) Code.Readonly << 16 | (byte) FlowControl.Next << 24, + (byte) OpCodeType.Prefix << 0 | (byte) OperandType.InlineNone << 8 | (byte) StackBehaviour.Pop0 << 16 | (byte) StackBehaviour.Push0 << 24); + } +} diff --git a/external/cecil-legacy/Mono.Cecil.Cil/SequencePoint.cs b/external/cecil-legacy/Mono.Cecil.Cil/SequencePoint.cs new file mode 100644 index 0000000000..ef87e30f13 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil.Cil/SequencePoint.cs @@ -0,0 +1,70 @@ +// +// SequencePoint.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +namespace Mono.Cecil.Cil { + + public sealed class SequencePoint { + + Document document; + + int start_line; + int start_column; + int end_line; + int end_column; + + public int StartLine { + get { return start_line; } + set { start_line = value; } + } + + public int StartColumn { + get { return start_column; } + set { start_column = value; } + } + + public int EndLine { + get { return end_line; } + set { end_line = value; } + } + + public int EndColumn { + get { return end_column; } + set { end_column = value; } + } + + public Document Document { + get { return document; } + set { document = value; } + } + + public SequencePoint (Document document) + { + this.document = document; + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil.Cil/Symbols.cs b/external/cecil-legacy/Mono.Cecil.Cil/Symbols.cs new file mode 100644 index 0000000000..426c4a7e1f --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil.Cil/Symbols.cs @@ -0,0 +1,277 @@ +// +// Symbols.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.IO; +using System.Runtime.InteropServices; +using SR = System.Reflection; + +using Mono.Collections.Generic; + +namespace Mono.Cecil.Cil { + + [StructLayout (LayoutKind.Sequential)] + public struct ImageDebugDirectory { + public int Characteristics; + public int TimeDateStamp; + public short MajorVersion; + public short MinorVersion; + public int Type; + public int SizeOfData; + public int AddressOfRawData; + public int PointerToRawData; + } + + public sealed class Scope : IVariableDefinitionProvider { + + Instruction start; + Instruction end; + + Collection scopes; + Collection variables; + + public Instruction Start { + get { return start; } + set { start = value; } + } + + public Instruction End { + get { return end; } + set { end = value; } + } + + public bool HasScopes { + get { return !scopes.IsNullOrEmpty (); } + } + + public Collection Scopes { + get { + if (scopes == null) + scopes = new Collection (); + + return scopes; + } + } + + public bool HasVariables { + get { return !variables.IsNullOrEmpty (); } + } + + public Collection Variables { + get { + if (variables == null) + variables = new Collection (); + + return variables; + } + } + } + + public struct InstructionSymbol { + + public readonly int Offset; + public readonly SequencePoint SequencePoint; + + public InstructionSymbol (int offset, SequencePoint sequencePoint) + { + this.Offset = offset; + this.SequencePoint = sequencePoint; + } + } + + public sealed class MethodSymbols { + + internal int code_size; + internal string method_name; + internal MetadataToken method_token; + internal MetadataToken local_var_token; + internal Collection variables; + internal Collection instructions; + + public bool HasVariables { + get { return !variables.IsNullOrEmpty (); } + } + + public Collection Variables { + get { + if (variables == null) + variables = new Collection (); + + return variables; + } + } + + public Collection Instructions { + get { + if (instructions == null) + instructions = new Collection (); + + return instructions; + } + } + + public int CodeSize { + get { return code_size; } + } + + public string MethodName { + get { return method_name; } + } + + public MetadataToken MethodToken { + get { return method_token; } + } + + public MetadataToken LocalVarToken { + get { return local_var_token; } + } + + internal MethodSymbols (string methodName) + { + this.method_name = methodName; + } + + public MethodSymbols (MetadataToken methodToken) + { + this.method_token = methodToken; + } + } + + public delegate Instruction InstructionMapper (int offset); + + public interface ISymbolReader : IDisposable { + + bool ProcessDebugHeader (ImageDebugDirectory directory, byte [] header); + void Read (MethodBody body, InstructionMapper mapper); + void Read (MethodSymbols symbols); + } + + public interface ISymbolReaderProvider { + + ISymbolReader GetSymbolReader (ModuleDefinition module, string fileName); + ISymbolReader GetSymbolReader (ModuleDefinition module, Stream symbolStream); + } + + static class SymbolProvider { + + static readonly string symbol_kind = Type.GetType ("Mono.Runtime") != null ? "Mdb" : "Pdb"; + + static SR.AssemblyName GetPlatformSymbolAssemblyName () + { + var cecil_name = typeof (SymbolProvider).Assembly.GetName (); + + var name = new SR.AssemblyName { + Name = "Mono.Cecil." + symbol_kind, + Version = cecil_name.Version, + }; + + name.SetPublicKeyToken (cecil_name.GetPublicKeyToken ()); + + return name; + } + + static Type GetPlatformType (string fullname) + { + var type = Type.GetType (fullname); + if (type != null) + return type; + + var assembly_name = GetPlatformSymbolAssemblyName (); + + type = Type.GetType (fullname + ", " + assembly_name.FullName); + if (type != null) + return type; + + try { + var assembly = SR.Assembly.Load (assembly_name); + if (assembly != null) + return assembly.GetType (fullname); + } catch (FileNotFoundException) { +#if !CF + } catch (FileLoadException) { +#endif + } + + return null; + } + + static ISymbolReaderProvider reader_provider; + + public static ISymbolReaderProvider GetPlatformReaderProvider () + { + if (reader_provider != null) + return reader_provider; + + var type = GetPlatformType (GetProviderTypeName ("ReaderProvider")); + if (type == null) + return null; + + return reader_provider = (ISymbolReaderProvider) Activator.CreateInstance (type); + } + + static string GetProviderTypeName (string name) + { + return "Mono.Cecil." + symbol_kind + "." + symbol_kind + name; + } + +#if !READ_ONLY + + static ISymbolWriterProvider writer_provider; + + public static ISymbolWriterProvider GetPlatformWriterProvider () + { + if (writer_provider != null) + return writer_provider; + + var type = GetPlatformType (GetProviderTypeName ("WriterProvider")); + if (type == null) + return null; + + return writer_provider = (ISymbolWriterProvider) Activator.CreateInstance (type); + } + +#endif + } + +#if !READ_ONLY + + public interface ISymbolWriter : IDisposable { + + bool GetDebugHeader (out ImageDebugDirectory directory, out byte [] header); + void Write (MethodBody body); + void Write (MethodSymbols symbols); + } + + public interface ISymbolWriterProvider { + + ISymbolWriter GetSymbolWriter (ModuleDefinition module, string fileName); + ISymbolWriter GetSymbolWriter (ModuleDefinition module, Stream symbolStream); + } + +#endif +} diff --git a/external/cecil-legacy/Mono.Cecil.Cil/VariableDefinition.cs b/external/cecil-legacy/Mono.Cecil.Cil/VariableDefinition.cs new file mode 100644 index 0000000000..f501bca6e7 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil.Cil/VariableDefinition.cs @@ -0,0 +1,52 @@ +// +// VariableDefinition.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +namespace Mono.Cecil.Cil { + + public sealed class VariableDefinition : VariableReference { + + public bool IsPinned { + get { return variable_type.IsPinned; } + } + + public VariableDefinition (TypeReference variableType) + : base (variableType) + { + } + + public VariableDefinition (string name, TypeReference variableType) + : base (name, variableType) + { + } + + public override VariableDefinition Resolve () + { + return this; + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil.Cil/VariableReference.cs b/external/cecil-legacy/Mono.Cecil.Cil/VariableReference.cs new file mode 100644 index 0000000000..ce0b4cdb4c --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil.Cil/VariableReference.cs @@ -0,0 +1,75 @@ +// +// VariableReference.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +namespace Mono.Cecil.Cil { + + public abstract class VariableReference { + + string name; + internal int index = -1; + protected TypeReference variable_type; + + public string Name { + get { return name; } + set { name = value; } + } + + public TypeReference VariableType { + get { return variable_type; } + set { variable_type = value; } + } + + public int Index { + get { return index; } + } + + internal VariableReference (TypeReference variable_type) + : this (string.Empty, variable_type) + { + } + + internal VariableReference (string name, TypeReference variable_type) + { + this.name = name; + this.variable_type = variable_type; + } + + public abstract VariableDefinition Resolve (); + + public override string ToString () + { + if (!string.IsNullOrEmpty (name)) + return name; + + if (index >= 0) + return "V_" + index; + + return string.Empty; + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil.Metadata/BlobHeap.cs b/external/cecil-legacy/Mono.Cecil.Metadata/BlobHeap.cs new file mode 100644 index 0000000000..e7e2928c82 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil.Metadata/BlobHeap.cs @@ -0,0 +1,59 @@ +// +// BlobHeap.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +using Mono.Cecil.PE; + +namespace Mono.Cecil.Metadata { + + sealed class BlobHeap : Heap { + + public BlobHeap (Section section, uint start, uint size) + : base (section, start, size) + { + } + + public byte [] Read (uint index) + { + if (index == 0 || index > Size - 1) + return Empty.Array; + + var data = Section.Data; + + int position = (int) (index + Offset); + int length = (int) data.ReadCompressedUInt32 (ref position); + + var buffer = new byte [length]; + + Buffer.BlockCopy (data, position, buffer, 0, length); + + return buffer; + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil.Metadata/Buffers.cs b/external/cecil-legacy/Mono.Cecil.Metadata/Buffers.cs new file mode 100644 index 0000000000..b63412dea7 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil.Metadata/Buffers.cs @@ -0,0 +1,373 @@ +// +// TableHeapBuffer.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Collections.Generic; +using System.Text; + +using Mono.Cecil.PE; + +using RVA = System.UInt32; + +#if !READ_ONLY + +namespace Mono.Cecil.Metadata { + + sealed class TableHeapBuffer : HeapBuffer { + + readonly ModuleDefinition module; + readonly MetadataBuilder metadata; + + internal MetadataTable [] tables = new MetadataTable [45]; + + bool large_string; + bool large_blob; + readonly int [] coded_index_sizes = new int [13]; + readonly Func counter; + + public override bool IsEmpty { + get { return false; } + } + + public TableHeapBuffer (ModuleDefinition module, MetadataBuilder metadata) + : base (24) + { + this.module = module; + this.metadata = metadata; + this.counter = GetTableLength; + } + + int GetTableLength (Table table) + { + var md_table = tables [(int) table]; + return md_table != null ? md_table.Length : 0; + } + + public TTable GetTable (Table table) where TTable : MetadataTable, new () + { + var md_table = (TTable) tables [(int) table]; + if (md_table != null) + return md_table; + + md_table = new TTable (); + tables [(int) table] = md_table; + return md_table; + } + + public void WriteBySize (uint value, int size) + { + if (size == 4) + WriteUInt32 (value); + else + WriteUInt16 ((ushort) value); + } + + public void WriteBySize (uint value, bool large) + { + if (large) + WriteUInt32 (value); + else + WriteUInt16 ((ushort) value); + } + + public void WriteString (uint @string) + { + WriteBySize (@string, large_string); + } + + public void WriteBlob (uint blob) + { + WriteBySize (blob, large_blob); + } + + public void WriteRID (uint rid, Table table) + { + var md_table = tables [(int) table]; + WriteBySize (rid, md_table == null ? false : md_table.IsLarge); + } + + int GetCodedIndexSize (CodedIndex coded_index) + { + var index = (int) coded_index; + var size = coded_index_sizes [index]; + if (size != 0) + return size; + + return coded_index_sizes [index] = coded_index.GetSize (counter); + } + + public void WriteCodedRID (uint rid, CodedIndex coded_index) + { + WriteBySize (rid, GetCodedIndexSize (coded_index)); + } + + public void WriteTableHeap () + { + WriteUInt32 (0); // Reserved + WriteByte (GetTableHeapVersion ()); // MajorVersion + WriteByte (0); // MinorVersion + WriteByte (GetHeapSizes ()); // HeapSizes + WriteByte (10); // Reserved2 + WriteUInt64 (GetValid ()); // Valid + WriteUInt64 (0x0016003301fa00); // Sorted + + WriteRowCount (); + WriteTables (); + } + + void WriteRowCount () + { + for (int i = 0; i < tables.Length; i++) { + var table = tables [i]; + if (table == null || table.Length == 0) + continue; + + WriteUInt32 ((uint) table.Length); + } + } + + void WriteTables () + { + for (int i = 0; i < tables.Length; i++) { + var table = tables [i]; + if (table == null || table.Length == 0) + continue; + + table.Write (this); + } + } + + ulong GetValid () + { + ulong valid = 0; + + for (int i = 0; i < tables.Length; i++) { + var table = tables [i]; + if (table == null || table.Length == 0) + continue; + + table.Sort (); + valid |= (1UL << i); + } + + return valid; + } + + byte GetHeapSizes () + { + byte heap_sizes = 0; + + if (metadata.string_heap.IsLarge) { + large_string = true; + heap_sizes |= 0x01; + } + + if (metadata.blob_heap.IsLarge) { + large_blob = true; + heap_sizes |= 0x04; + } + + return heap_sizes; + } + + byte GetTableHeapVersion () + { + switch (module.Runtime) { + case TargetRuntime.Net_1_0: + case TargetRuntime.Net_1_1: + return 1; + default: + return 2; + } + } + + public void FixupData (RVA data_rva) + { + var table = GetTable (Table.FieldRVA); + if (table.length == 0) + return; + + var field_idx_size = GetTable (Table.Field).IsLarge ? 4 : 2; + var previous = this.position; + + base.position = table.position; + for (int i = 0; i < table.length; i++) { + var rva = ReadUInt32 (); + base.position -= 4; + WriteUInt32 (rva + data_rva); + base.position += field_idx_size; + } + + base.position = previous; + } + } + + sealed class ResourceBuffer : ByteBuffer { + + public ResourceBuffer () + : base (0) + { + } + + public uint AddResource (byte [] resource) + { + var offset = (uint) this.position; + WriteInt32 (resource.Length); + WriteBytes (resource); + return offset; + } + } + + sealed class DataBuffer : ByteBuffer { + + public DataBuffer () + : base (0) + { + } + + public RVA AddData (byte [] data) + { + var rva = (RVA) position; + WriteBytes (data); + return rva; + } + } + + abstract class HeapBuffer : ByteBuffer { + + public bool IsLarge { + get { return base.length > 65535; } + } + + public abstract bool IsEmpty { get; } + + protected HeapBuffer (int length) + : base (length) + { + } + } + + class StringHeapBuffer : HeapBuffer { + + readonly Dictionary strings = new Dictionary (StringComparer.Ordinal); + + public sealed override bool IsEmpty { + get { return length <= 1; } + } + + public StringHeapBuffer () + : base (1) + { + WriteByte (0); + } + + public uint GetStringIndex (string @string) + { + uint index; + if (strings.TryGetValue (@string, out index)) + return index; + + index = (uint) base.position; + WriteString (@string); + strings.Add (@string, index); + return index; + } + + protected virtual void WriteString (string @string) + { + WriteBytes (Encoding.UTF8.GetBytes (@string)); + WriteByte (0); + } + } + + sealed class BlobHeapBuffer : HeapBuffer { + + readonly Dictionary blobs = new Dictionary (new ByteBufferEqualityComparer ()); + + public override bool IsEmpty { + get { return length <= 1; } + } + + public BlobHeapBuffer () + : base (1) + { + WriteByte (0); + } + + public uint GetBlobIndex (ByteBuffer blob) + { + uint index; + if (blobs.TryGetValue (blob, out index)) + return index; + + index = (uint) base.position; + WriteBlob (blob); + blobs.Add (blob, index); + return index; + } + + void WriteBlob (ByteBuffer blob) + { + WriteCompressedUInt32 ((uint) blob.length); + WriteBytes (blob); + } + } + + sealed class UserStringHeapBuffer : StringHeapBuffer { + + protected override void WriteString (string @string) + { + WriteCompressedUInt32 ((uint) @string.Length * 2 + 1); + + byte special = 0; + + for (int i = 0; i < @string.Length; i++) { + var @char = @string [i]; + WriteUInt16 (@char); + + if (special == 1) + continue; + + if (@char < 0x20 || @char > 0x7e) { + if (@char > 0x7e + || (@char >= 0x01 && @char <= 0x08) + || (@char >= 0x0e && @char <= 0x1f) + || @char == 0x27 + || @char == 0x2d) { + + special = 1; + } + } + } + + WriteByte (special); + } + } +} + +#endif diff --git a/external/cecil-legacy/Mono.Cecil.Metadata/CodedIndex.cs b/external/cecil-legacy/Mono.Cecil.Metadata/CodedIndex.cs new file mode 100644 index 0000000000..3e30fd87f9 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil.Metadata/CodedIndex.cs @@ -0,0 +1,46 @@ +// +// CodedIndex.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +namespace Mono.Cecil.Metadata { + + enum CodedIndex { + TypeDefOrRef, + HasConstant, + HasCustomAttribute, + HasFieldMarshal, + HasDeclSecurity, + MemberRefParent, + HasSemantics, + MethodDefOrRef, + MemberForwarded, + Implementation, + CustomAttributeType, + ResolutionScope, + TypeOrMethodDef + } +} diff --git a/external/cecil-legacy/Mono.Cecil.Metadata/ElementType.cs b/external/cecil-legacy/Mono.Cecil.Metadata/ElementType.cs new file mode 100644 index 0000000000..72fc1ccaf2 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil.Metadata/ElementType.cs @@ -0,0 +1,73 @@ +// +// ElementType.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +namespace Mono.Cecil.Metadata { + + enum ElementType : byte { + None = 0x00, + Void = 0x01, + Boolean = 0x02, + Char = 0x03, + I1 = 0x04, + U1 = 0x05, + I2 = 0x06, + U2 = 0x07, + I4 = 0x08, + U4 = 0x09, + I8 = 0x0a, + U8 = 0x0b, + R4 = 0x0c, + R8 = 0x0d, + String = 0x0e, + Ptr = 0x0f, // Followed by token + ByRef = 0x10, // Followed by token + ValueType = 0x11, // Followed by token + Class = 0x12, // Followed by token + Var = 0x13, // Followed by generic parameter number + Array = 0x14, // + GenericInst = 0x15, // ... */ + TypedByRef = 0x16, + I = 0x18, // System.IntPtr + U = 0x19, // System.UIntPtr + FnPtr = 0x1b, // Followed by full method signature + Object = 0x1c, // System.Object + SzArray = 0x1d, // Single-dim array with 0 lower bound + MVar = 0x1e, // Followed by generic parameter number + CModReqD = 0x1f, // Required modifier : followed by a TypeDef or TypeRef token + CModOpt = 0x20, // Optional modifier : followed by a TypeDef or TypeRef token + Internal = 0x21, // Implemented within the CLI + Modifier = 0x40, // Or'd with following element types + Sentinel = 0x41, // Sentinel for varargs method signature + Pinned = 0x45, // Denotes a local variable that points at a pinned object + + // special undocumented constants + Type = 0x50, + Boxed = 0x51, + Enum = 0x55 + } +} diff --git a/external/cecil-legacy/Mono.Cecil.Metadata/GuidHeap.cs b/external/cecil-legacy/Mono.Cecil.Metadata/GuidHeap.cs new file mode 100644 index 0000000000..1adc0795ee --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil.Metadata/GuidHeap.cs @@ -0,0 +1,59 @@ +// +// GuidHeap.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +using Mono.Cecil.PE; + +namespace Mono.Cecil.Metadata { + + sealed class GuidHeap : Heap { + + public GuidHeap (Section section, uint start, uint size) + : base (section, start, size) + { + } + + public Guid Read (uint index) + { + if (index == 0) + return new Guid (); + + const int guid_size = 16; + + var buffer = new byte [guid_size]; + + index--; + + Buffer.BlockCopy (Section.Data, (int) (Offset + index), buffer, 0, guid_size); + + return new Guid (buffer); + + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil.Metadata/Heap.cs b/external/cecil-legacy/Mono.Cecil.Metadata/Heap.cs new file mode 100644 index 0000000000..bc21acde25 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil.Metadata/Heap.cs @@ -0,0 +1,48 @@ +// +// Heap.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using Mono.Cecil.PE; + +namespace Mono.Cecil.Metadata { + + abstract class Heap { + + public int IndexSize; + + public readonly Section Section; + public readonly uint Offset; + public readonly uint Size; + + protected Heap (Section section, uint offset, uint size) + { + this.Section = section; + this.Offset = offset; + this.Size = size; + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil.Metadata/MetadataToken.cs b/external/cecil-legacy/Mono.Cecil.Metadata/MetadataToken.cs new file mode 100644 index 0000000000..bda56b0f4f --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil.Metadata/MetadataToken.cs @@ -0,0 +1,105 @@ +// +// MetadataToken.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +namespace Mono.Cecil { + + public struct MetadataToken { + + readonly uint token; + + public uint RID { + get { return token & 0x00ffffff; } + } + + public TokenType TokenType { + get { return (TokenType) (token & 0xff000000); } + } + + public static readonly MetadataToken Zero = new MetadataToken ((uint) 0); + + public MetadataToken (uint token) + { + this.token = token; + } + + public MetadataToken (TokenType type) + : this (type, 0) + { + } + + public MetadataToken (TokenType type, uint rid) + { + token = (uint) type | rid; + } + + public MetadataToken (TokenType type, int rid) + { + token = (uint) type | (uint) rid; + } + + public int ToInt32 () + { + return (int) token; + } + + public uint ToUInt32 () + { + return token; + } + + public override int GetHashCode () + { + return (int) token; + } + + public override bool Equals (object obj) + { + if (obj is MetadataToken) { + var other = (MetadataToken) obj; + return other.token == token; + } + + return false; + } + + public static bool operator == (MetadataToken one, MetadataToken other) + { + return one.token == other.token; + } + + public static bool operator != (MetadataToken one, MetadataToken other) + { + return one.token != other.token; + } + + public override string ToString () + { + return string.Format ("[{0}:0x{1}]", TokenType, RID.ToString ("x4")); + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil.Metadata/Row.cs b/external/cecil-legacy/Mono.Cecil.Metadata/Row.cs new file mode 100644 index 0000000000..dfda00a777 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil.Metadata/Row.cs @@ -0,0 +1,170 @@ +// +// Row.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System.Collections.Generic; + +namespace Mono.Cecil.Metadata { + + struct Row { + internal T1 Col1; + internal T2 Col2; + + public Row (T1 col1, T2 col2) + { + Col1 = col1; + Col2 = col2; + } + } + + struct Row { + internal T1 Col1; + internal T2 Col2; + internal T3 Col3; + + public Row (T1 col1, T2 col2, T3 col3) + { + Col1 = col1; + Col2 = col2; + Col3 = col3; + } + } + + struct Row { + internal T1 Col1; + internal T2 Col2; + internal T3 Col3; + internal T4 Col4; + + public Row (T1 col1, T2 col2, T3 col3, T4 col4) + { + Col1 = col1; + Col2 = col2; + Col3 = col3; + Col4 = col4; + } + } + + struct Row { + internal T1 Col1; + internal T2 Col2; + internal T3 Col3; + internal T4 Col4; + internal T5 Col5; + + public Row (T1 col1, T2 col2, T3 col3, T4 col4, T5 col5) + { + Col1 = col1; + Col2 = col2; + Col3 = col3; + Col4 = col4; + Col5 = col5; + } + } + + struct Row { + internal T1 Col1; + internal T2 Col2; + internal T3 Col3; + internal T4 Col4; + internal T5 Col5; + internal T6 Col6; + + public Row (T1 col1, T2 col2, T3 col3, T4 col4, T5 col5, T6 col6) + { + Col1 = col1; + Col2 = col2; + Col3 = col3; + Col4 = col4; + Col5 = col5; + Col6 = col6; + } + } + + struct Row { + internal T1 Col1; + internal T2 Col2; + internal T3 Col3; + internal T4 Col4; + internal T5 Col5; + internal T6 Col6; + internal T7 Col7; + internal T8 Col8; + internal T9 Col9; + + public Row (T1 col1, T2 col2, T3 col3, T4 col4, T5 col5, T6 col6, T7 col7, T8 col8, T9 col9) + { + Col1 = col1; + Col2 = col2; + Col3 = col3; + Col4 = col4; + Col5 = col5; + Col6 = col6; + Col7 = col7; + Col8 = col8; + Col9 = col9; + } + } + + sealed class RowEqualityComparer : IEqualityComparer>, IEqualityComparer>, IEqualityComparer> { + + public bool Equals (Row x, Row y) + { + return x.Col1 == y.Col1 + && x.Col2 == y.Col2; + } + + public int GetHashCode (Row obj) + { + string x = obj.Col1, y = obj.Col2; + return (x != null ? x.GetHashCode () : 0) ^ (y != null ? y.GetHashCode () : 0); + } + + public bool Equals (Row x, Row y) + { + return x.Col1 == y.Col1 + && x.Col2 == y.Col2; + } + + public int GetHashCode (Row obj) + { + return (int) (obj.Col1 ^ obj.Col2); + } + + public bool Equals (Row x, Row y) + { + return x.Col1 == y.Col1 + && x.Col2 == y.Col2 + && x.Col3 == y.Col3; + } + + public int GetHashCode (Row obj) + { + return (int) (obj.Col1 ^ obj.Col2 ^ obj.Col3); + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil.Metadata/StringHeap.cs b/external/cecil-legacy/Mono.Cecil.Metadata/StringHeap.cs new file mode 100644 index 0000000000..4a0a0af435 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil.Metadata/StringHeap.cs @@ -0,0 +1,81 @@ +// +// StringHeap.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Collections.Generic; +using System.Text; + +using Mono.Cecil.PE; + +namespace Mono.Cecil.Metadata { + + class StringHeap : Heap { + + readonly Dictionary strings = new Dictionary (); + + public StringHeap (Section section, uint start, uint size) + : base (section, start, size) + { + } + + public string Read (uint index) + { + if (index == 0) + return string.Empty; + + string @string; + if (strings.TryGetValue (index, out @string)) + return @string; + + if (index > Size - 1) + return string.Empty; + + @string = ReadStringAt (index); + if (@string.Length != 0) + strings.Add (index, @string); + + return @string; + } + + protected virtual string ReadStringAt (uint index) + { + int length = 0; + byte [] data = Section.Data; + int start = (int) (index + Offset); + + for (int i = start; ; i++) { + if (data [i] == 0) + break; + + length++; + } + + return Encoding.UTF8.GetString (data, start, length); + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil.Metadata/TableHeap.cs b/external/cecil-legacy/Mono.Cecil.Metadata/TableHeap.cs new file mode 100644 index 0000000000..9bc0edd36c --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil.Metadata/TableHeap.cs @@ -0,0 +1,111 @@ +// +// TableHeap.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using Mono.Cecil.PE; + +namespace Mono.Cecil.Metadata { + + enum Table : byte { + Module = 0x00, + TypeRef = 0x01, + TypeDef = 0x02, + FieldPtr = 0x03, + Field = 0x04, + MethodPtr = 0x05, + Method = 0x06, + ParamPtr = 0x07, + Param = 0x08, + InterfaceImpl = 0x09, + MemberRef = 0x0a, + Constant = 0x0b, + CustomAttribute = 0x0c, + FieldMarshal = 0x0d, + DeclSecurity = 0x0e, + ClassLayout = 0x0f, + FieldLayout = 0x10, + StandAloneSig = 0x11, + EventMap = 0x12, + EventPtr = 0x13, + Event = 0x14, + PropertyMap = 0x15, + PropertyPtr = 0x16, + Property = 0x17, + MethodSemantics = 0x18, + MethodImpl = 0x19, + ModuleRef = 0x1a, + TypeSpec = 0x1b, + ImplMap = 0x1c, + FieldRVA = 0x1d, + EncLog = 0x1e, + EncMap = 0x1f, + Assembly = 0x20, + AssemblyProcessor = 0x21, + AssemblyOS = 0x22, + AssemblyRef = 0x23, + AssemblyRefProcessor = 0x24, + AssemblyRefOS = 0x25, + File = 0x26, + ExportedType = 0x27, + ManifestResource = 0x28, + NestedClass = 0x29, + GenericParam = 0x2a, + MethodSpec = 0x2b, + GenericParamConstraint = 0x2c, + } + + struct TableInformation { + public uint Offset; + public uint Length; + public uint RowSize; + } + + sealed class TableHeap : Heap { + + public long Valid; + public long Sorted; + + public const int TableCount = 45; + + public readonly TableInformation [] Tables = new TableInformation [TableCount]; + + public TableInformation this [Table table] { + get { return Tables [(int) table]; } + } + + public TableHeap (Section section, uint start, uint size) + : base (section, start, size) + { + } + + public bool HasTable (Table table) + { + return (Valid & (1L << (int) table)) != 0; + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil.Metadata/TokenType.cs b/external/cecil-legacy/Mono.Cecil.Metadata/TokenType.cs new file mode 100644 index 0000000000..2c2010ff97 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil.Metadata/TokenType.cs @@ -0,0 +1,56 @@ +// +// TokenType.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +namespace Mono.Cecil { + + public enum TokenType : uint { + Module = 0x00000000, + TypeRef = 0x01000000, + TypeDef = 0x02000000, + Field = 0x04000000, + Method = 0x06000000, + Param = 0x08000000, + InterfaceImpl = 0x09000000, + MemberRef = 0x0a000000, + CustomAttribute = 0x0c000000, + Permission = 0x0e000000, + Signature = 0x11000000, + Event = 0x14000000, + Property = 0x17000000, + ModuleRef = 0x1a000000, + TypeSpec = 0x1b000000, + Assembly = 0x20000000, + AssemblyRef = 0x23000000, + File = 0x26000000, + ExportedType = 0x27000000, + ManifestResource = 0x28000000, + GenericParam = 0x2a000000, + MethodSpec = 0x2b000000, + String = 0x70000000, + } +} diff --git a/external/cecil-legacy/Mono.Cecil.Metadata/UserStringHeap.cs b/external/cecil-legacy/Mono.Cecil.Metadata/UserStringHeap.cs new file mode 100644 index 0000000000..59105087ff --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil.Metadata/UserStringHeap.cs @@ -0,0 +1,59 @@ +// +// UserStringHeap.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +using Mono.Cecil.PE; + +namespace Mono.Cecil.Metadata { + + sealed class UserStringHeap : StringHeap { + + public UserStringHeap (Section section, uint start, uint size) + : base (section, start, size) + { + } + + protected override string ReadStringAt (uint index) + { + byte [] data = Section.Data; + int start = (int) (index + Offset); + + uint length = (uint) (data.ReadCompressedUInt32 (ref start) & ~1); + if (length < 1) + return string.Empty; + + var chars = new char [length / 2]; + + for (int i = start, j = 0; i < start + length; i += 2) + chars [j++] = (char) (data [i] | (data [i + 1] << 8)); + + return new string (chars); + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil.Metadata/Utilities.cs b/external/cecil-legacy/Mono.Cecil.Metadata/Utilities.cs new file mode 100644 index 0000000000..d752b24b11 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil.Metadata/Utilities.cs @@ -0,0 +1,529 @@ +// +// Utilities.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +using Mono.Cecil.Metadata; + +namespace Mono.Cecil { + + static partial class Mixin { + + public static uint ReadCompressedUInt32 (this byte [] data, ref int position) + { + uint integer; + if ((data [position] & 0x80) == 0) { + integer = data [position]; + position++; + } else if ((data [position] & 0x40) == 0) { + integer = (uint) (data [position] & ~0x80) << 8; + integer |= data [position + 1]; + position += 2; + } else { + integer = (uint) (data [position] & ~0xc0) << 24; + integer |= (uint) data [position + 1] << 16; + integer |= (uint) data [position + 2] << 8; + integer |= (uint) data [position + 3]; + position += 4; + } + return integer; + } + + public static MetadataToken GetMetadataToken (this CodedIndex self, uint data) + { + uint rid; + TokenType token_type; + switch (self) { + case CodedIndex.TypeDefOrRef: + rid = data >> 2; + switch (data & 3) { + case 0: + token_type = TokenType.TypeDef; goto ret; + case 1: + token_type = TokenType.TypeRef; goto ret; + case 2: + token_type = TokenType.TypeSpec; goto ret; + default: + goto exit; + } + case CodedIndex.HasConstant: + rid = data >> 2; + switch (data & 3) { + case 0: + token_type = TokenType.Field; goto ret; + case 1: + token_type = TokenType.Param; goto ret; + case 2: + token_type = TokenType.Property; goto ret; + default: + goto exit; + } + case CodedIndex.HasCustomAttribute: + rid = data >> 5; + switch (data & 31) { + case 0: + token_type = TokenType.Method; goto ret; + case 1: + token_type = TokenType.Field; goto ret; + case 2: + token_type = TokenType.TypeRef; goto ret; + case 3: + token_type = TokenType.TypeDef; goto ret; + case 4: + token_type = TokenType.Param; goto ret; + case 5: + token_type = TokenType.InterfaceImpl; goto ret; + case 6: + token_type = TokenType.MemberRef; goto ret; + case 7: + token_type = TokenType.Module; goto ret; + case 8: + token_type = TokenType.Permission; goto ret; + case 9: + token_type = TokenType.Property; goto ret; + case 10: + token_type = TokenType.Event; goto ret; + case 11: + token_type = TokenType.Signature; goto ret; + case 12: + token_type = TokenType.ModuleRef; goto ret; + case 13: + token_type = TokenType.TypeSpec; goto ret; + case 14: + token_type = TokenType.Assembly; goto ret; + case 15: + token_type = TokenType.AssemblyRef; goto ret; + case 16: + token_type = TokenType.File; goto ret; + case 17: + token_type = TokenType.ExportedType; goto ret; + case 18: + token_type = TokenType.ManifestResource; goto ret; + case 19: + token_type = TokenType.GenericParam; goto ret; + default: + goto exit; + } + case CodedIndex.HasFieldMarshal: + rid = data >> 1; + switch (data & 1) { + case 0: + token_type = TokenType.Field; goto ret; + case 1: + token_type = TokenType.Param; goto ret; + default: + goto exit; + } + case CodedIndex.HasDeclSecurity: + rid = data >> 2; + switch (data & 3) { + case 0: + token_type = TokenType.TypeDef; goto ret; + case 1: + token_type = TokenType.Method; goto ret; + case 2: + token_type = TokenType.Assembly; goto ret; + default: + goto exit; + } + case CodedIndex.MemberRefParent: + rid = data >> 3; + switch (data & 7) { + case 0: + token_type = TokenType.TypeDef; goto ret; + case 1: + token_type = TokenType.TypeRef; goto ret; + case 2: + token_type = TokenType.ModuleRef; goto ret; + case 3: + token_type = TokenType.Method; goto ret; + case 4: + token_type = TokenType.TypeSpec; goto ret; + default: + goto exit; + } + case CodedIndex.HasSemantics: + rid = data >> 1; + switch (data & 1) { + case 0: + token_type = TokenType.Event; goto ret; + case 1: + token_type = TokenType.Property; goto ret; + default: + goto exit; + } + case CodedIndex.MethodDefOrRef: + rid = data >> 1; + switch (data & 1) { + case 0: + token_type = TokenType.Method; goto ret; + case 1: + token_type = TokenType.MemberRef; goto ret; + default: + goto exit; + } + case CodedIndex.MemberForwarded: + rid = data >> 1; + switch (data & 1) { + case 0: + token_type = TokenType.Field; goto ret; + case 1: + token_type = TokenType.Method; goto ret; + default: + goto exit; + } + case CodedIndex.Implementation: + rid = data >> 2; + switch (data & 3) { + case 0: + token_type = TokenType.File; goto ret; + case 1: + token_type = TokenType.AssemblyRef; goto ret; + case 2: + token_type = TokenType.ExportedType; goto ret; + default: + goto exit; + } + case CodedIndex.CustomAttributeType: + rid = data >> 3; + switch (data & 7) { + case 2: + token_type = TokenType.Method; goto ret; + case 3: + token_type = TokenType.MemberRef; goto ret; + default: + goto exit; + } + case CodedIndex.ResolutionScope: + rid = data >> 2; + switch (data & 3) { + case 0: + token_type = TokenType.Module; goto ret; + case 1: + token_type = TokenType.ModuleRef; goto ret; + case 2: + token_type = TokenType.AssemblyRef; goto ret; + case 3: + token_type = TokenType.TypeRef; goto ret; + default: + goto exit; + } + case CodedIndex.TypeOrMethodDef: + rid = data >> 1; + switch (data & 1) { + case 0: + token_type = TokenType.TypeDef; goto ret; + case 1: + token_type = TokenType.Method; goto ret; + default: goto exit; + } + default: + goto exit; + } + ret: + return new MetadataToken (token_type, rid); + exit: + return MetadataToken.Zero; + } + +#if !READ_ONLY + public static uint CompressMetadataToken (this CodedIndex self, MetadataToken token) + { + uint ret = 0; + if (token.RID == 0) + return ret; + switch (self) { + case CodedIndex.TypeDefOrRef: + ret = token.RID << 2; + switch (token.TokenType) { + case TokenType.TypeDef: + return ret | 0; + case TokenType.TypeRef: + return ret | 1; + case TokenType.TypeSpec: + return ret | 2; + default: + goto exit; + } + case CodedIndex.HasConstant: + ret = token.RID << 2; + switch (token.TokenType) { + case TokenType.Field: + return ret | 0; + case TokenType.Param: + return ret | 1; + case TokenType.Property: + return ret | 2; + default: + goto exit; + } + case CodedIndex.HasCustomAttribute: + ret = token.RID << 5; + switch (token.TokenType) { + case TokenType.Method: + return ret | 0; + case TokenType.Field: + return ret | 1; + case TokenType.TypeRef: + return ret | 2; + case TokenType.TypeDef: + return ret | 3; + case TokenType.Param: + return ret | 4; + case TokenType.InterfaceImpl: + return ret | 5; + case TokenType.MemberRef: + return ret | 6; + case TokenType.Module: + return ret | 7; + case TokenType.Permission: + return ret | 8; + case TokenType.Property: + return ret | 9; + case TokenType.Event: + return ret | 10; + case TokenType.Signature: + return ret | 11; + case TokenType.ModuleRef: + return ret | 12; + case TokenType.TypeSpec: + return ret | 13; + case TokenType.Assembly: + return ret | 14; + case TokenType.AssemblyRef: + return ret | 15; + case TokenType.File: + return ret | 16; + case TokenType.ExportedType: + return ret | 17; + case TokenType.ManifestResource: + return ret | 18; + case TokenType.GenericParam: + return ret | 19; + default: + goto exit; + } + case CodedIndex.HasFieldMarshal: + ret = token.RID << 1; + switch (token.TokenType) { + case TokenType.Field: + return ret | 0; + case TokenType.Param: + return ret | 1; + default: + goto exit; + } + case CodedIndex.HasDeclSecurity: + ret = token.RID << 2; + switch (token.TokenType) { + case TokenType.TypeDef: + return ret | 0; + case TokenType.Method: + return ret | 1; + case TokenType.Assembly: + return ret | 2; + default: + goto exit; + } + case CodedIndex.MemberRefParent: + ret = token.RID << 3; + switch (token.TokenType) { + case TokenType.TypeDef: + return ret | 0; + case TokenType.TypeRef: + return ret | 1; + case TokenType.ModuleRef: + return ret | 2; + case TokenType.Method: + return ret | 3; + case TokenType.TypeSpec: + return ret | 4; + default: + goto exit; + } + case CodedIndex.HasSemantics: + ret = token.RID << 1; + switch (token.TokenType) { + case TokenType.Event: + return ret | 0; + case TokenType.Property: + return ret | 1; + default: + goto exit; + } + case CodedIndex.MethodDefOrRef: + ret = token.RID << 1; + switch (token.TokenType) { + case TokenType.Method: + return ret | 0; + case TokenType.MemberRef: + return ret | 1; + default: + goto exit; + } + case CodedIndex.MemberForwarded: + ret = token.RID << 1; + switch (token.TokenType) { + case TokenType.Field: + return ret | 0; + case TokenType.Method: + return ret | 1; + default: + goto exit; + } + case CodedIndex.Implementation: + ret = token.RID << 2; + switch (token.TokenType) { + case TokenType.File: + return ret | 0; + case TokenType.AssemblyRef: + return ret | 1; + case TokenType.ExportedType: + return ret | 2; + default: + goto exit; + } + case CodedIndex.CustomAttributeType: + ret = token.RID << 3; + switch (token.TokenType) { + case TokenType.Method: + return ret | 2; + case TokenType.MemberRef: + return ret | 3; + default: + goto exit; + } + case CodedIndex.ResolutionScope: + ret = token.RID << 2; + switch (token.TokenType) { + case TokenType.Module: + return ret | 0; + case TokenType.ModuleRef: + return ret | 1; + case TokenType.AssemblyRef: + return ret | 2; + case TokenType.TypeRef: + return ret | 3; + default: + goto exit; + } + case CodedIndex.TypeOrMethodDef: + ret = token.RID << 1; + switch (token.TokenType) { + case TokenType.TypeDef: + return ret | 0; + case TokenType.Method: + return ret | 1; + default: + goto exit; + } + default: + goto exit; + } + exit: + throw new ArgumentException (); + } +#endif + + public static int GetSize (this CodedIndex self, Func counter) + { + int bits; + Table [] tables; + + switch (self) { + case CodedIndex.TypeDefOrRef: + bits = 2; + tables = new [] { Table.TypeDef, Table.TypeRef, Table.TypeSpec }; + break; + case CodedIndex.HasConstant: + bits = 2; + tables = new [] { Table.Field, Table.Param, Table.Property }; + break; + case CodedIndex.HasCustomAttribute: + bits = 5; + tables = new [] { + Table.Method, Table.Field, Table.TypeRef, Table.TypeDef, Table.Param, Table.InterfaceImpl, Table.MemberRef, + Table.Module, Table.DeclSecurity, Table.Property, Table.Event, Table.StandAloneSig, Table.ModuleRef, + Table.TypeSpec, Table.Assembly, Table.AssemblyRef, Table.File, Table.ExportedType, + Table.ManifestResource, Table.GenericParam + }; + break; + case CodedIndex.HasFieldMarshal: + bits = 1; + tables = new [] { Table.Field, Table.Param }; + break; + case CodedIndex.HasDeclSecurity: + bits = 2; + tables = new [] { Table.TypeDef, Table.Method, Table.Assembly }; + break; + case CodedIndex.MemberRefParent: + bits = 3; + tables = new [] { Table.TypeDef, Table.TypeRef, Table.ModuleRef, Table.Method, Table.TypeSpec }; + break; + case CodedIndex.HasSemantics: + bits = 1; + tables = new [] { Table.Event, Table.Property }; + break; + case CodedIndex.MethodDefOrRef: + bits = 1; + tables = new [] { Table.Method, Table.MemberRef }; + break; + case CodedIndex.MemberForwarded: + bits = 1; + tables = new [] { Table.Field, Table.Method }; + break; + case CodedIndex.Implementation: + bits = 2; + tables = new [] { Table.File, Table.AssemblyRef, Table.ExportedType }; + break; + case CodedIndex.CustomAttributeType: + bits = 3; + tables = new [] { Table.Method, Table.MemberRef }; + break; + case CodedIndex.ResolutionScope: + bits = 2; + tables = new [] { Table.Module, Table.ModuleRef, Table.AssemblyRef, Table.TypeRef }; + break; + case CodedIndex.TypeOrMethodDef: + bits = 1; + tables = new [] { Table.TypeDef, Table.Method }; + break; + default: + throw new ArgumentException (); + } + + int max = 0; + + for (int i = 0; i < tables.Length; i++) { + max = System.Math.Max (counter (tables [i]), max); + } + + return max < (1 << (16 - bits)) ? 2 : 4; + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil.PE/BinaryStreamReader.cs b/external/cecil-legacy/Mono.Cecil.PE/BinaryStreamReader.cs new file mode 100644 index 0000000000..ec2477c3ad --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil.PE/BinaryStreamReader.cs @@ -0,0 +1,51 @@ +// +// BinaryStreamReader.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.IO; + +namespace Mono.Cecil.PE { + + class BinaryStreamReader : BinaryReader { + + public BinaryStreamReader (Stream stream) + : base (stream) + { + } + + protected void Advance (int bytes) + { + BaseStream.Seek (bytes, SeekOrigin.Current); + } + + protected DataDirectory ReadDataDirectory () + { + return new DataDirectory (ReadUInt32 (), ReadUInt32 ()); + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil.PE/BinaryStreamWriter.cs b/external/cecil-legacy/Mono.Cecil.PE/BinaryStreamWriter.cs new file mode 100644 index 0000000000..2bf6cccfa1 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil.PE/BinaryStreamWriter.cs @@ -0,0 +1,96 @@ +// +// BinaryStreamWriter.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.IO; + +#if !READ_ONLY + +namespace Mono.Cecil.PE { + + class BinaryStreamWriter : BinaryWriter { + + public BinaryStreamWriter (Stream stream) + : base (stream) + { + } + + public void WriteByte (byte value) + { + Write (value); + } + + public void WriteUInt16 (ushort value) + { + Write (value); + } + + public void WriteInt16 (short value) + { + Write (value); + } + + public void WriteUInt32 (uint value) + { + Write (value); + } + + public void WriteInt32 (int value) + { + Write (value); + } + + public void WriteUInt64 (ulong value) + { + Write (value); + } + + public void WriteBytes (byte [] bytes) + { + Write (bytes); + } + + public void WriteDataDirectory (DataDirectory directory) + { + Write (directory.VirtualAddress); + Write (directory.Size); + } + + public void WriteBuffer (ByteBuffer buffer) + { + Write (buffer.buffer, 0, buffer.length); + } + + protected void Advance (int bytes) + { + BaseStream.Seek (bytes, SeekOrigin.Current); + } + } +} + +#endif diff --git a/external/cecil-legacy/Mono.Cecil.PE/ByteBuffer.cs b/external/cecil-legacy/Mono.Cecil.PE/ByteBuffer.cs new file mode 100644 index 0000000000..c7ae7aee13 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil.PE/ByteBuffer.cs @@ -0,0 +1,359 @@ +// +// ByteBuffer.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +namespace Mono.Cecil.PE { + + class ByteBuffer { + + internal byte [] buffer; + internal int length; + internal int position; + + public ByteBuffer () + { + this.buffer = Empty.Array; + } + + public ByteBuffer (int length) + { + this.buffer = new byte [length]; + } + + public ByteBuffer (byte [] buffer) + { + this.buffer = buffer ?? Empty.Array; + this.length = this.buffer.Length; + } + + public void Reset (byte [] buffer) + { + this.buffer = buffer ?? Empty.Array; + this.length = this.buffer.Length; + } + + public void Advance (int length) + { + position += length; + } + + public byte ReadByte () + { + return buffer [position++]; + } + + public sbyte ReadSByte () + { + return (sbyte) ReadByte (); + } + + public byte [] ReadBytes (int length) + { + var bytes = new byte [length]; + Buffer.BlockCopy (buffer, position, bytes, 0, length); + position += length; + return bytes; + } + + public ushort ReadUInt16 () + { + ushort value = (ushort) (buffer [position] + | (buffer [position + 1] << 8)); + position += 2; + return value; + } + + public short ReadInt16 () + { + return (short) ReadUInt16 (); + } + + public uint ReadUInt32 () + { + uint value = (uint) (buffer [position] + | (buffer [position + 1] << 8) + | (buffer [position + 2] << 16) + | (buffer [position + 3] << 24)); + position += 4; + return value; + } + + public int ReadInt32 () + { + return (int) ReadUInt32 (); + } + + public ulong ReadUInt64 () + { + uint low = ReadUInt32 (); + uint high = ReadUInt32 (); + + return (((ulong) high) << 32) | low; + } + + public long ReadInt64 () + { + return (long) ReadUInt64 (); + } + + public uint ReadCompressedUInt32 () + { + byte first = ReadByte (); + if ((first & 0x80) == 0) + return first; + + if ((first & 0x40) == 0) + return ((uint) (first & ~0x80) << 8) + | ReadByte (); + + return ((uint) (first & ~0xc0) << 24) + | (uint) ReadByte () << 16 + | (uint) ReadByte () << 8 + | ReadByte (); + } + + public int ReadCompressedInt32 () + { + var value = (int) (ReadCompressedUInt32 () >> 1); + if ((value & 1) == 0) + return value; + if (value < 0x40) + return value - 0x40; + if (value < 0x2000) + return value - 0x2000; + if (value < 0x10000000) + return value - 0x10000000; + return value - 0x20000000; + } + + public float ReadSingle () + { + if (!BitConverter.IsLittleEndian) { + var bytes = ReadBytes (4); + Array.Reverse (bytes); + return BitConverter.ToSingle (bytes, 0); + } + + float value = BitConverter.ToSingle (buffer, position); + position += 4; + return value; + } + + public double ReadDouble () + { + if (!BitConverter.IsLittleEndian) { + var bytes = ReadBytes (8); + Array.Reverse (bytes); + return BitConverter.ToDouble (bytes, 0); + } + + double value = BitConverter.ToDouble (buffer, position); + position += 8; + return value; + } + +#if !READ_ONLY + + public void WriteByte (byte value) + { + if (position == buffer.Length) + Grow (1); + + buffer [position++] = value; + + if (position > length) + length = position; + } + + public void WriteSByte (sbyte value) + { + WriteByte ((byte) value); + } + + public void WriteUInt16 (ushort value) + { + if (position + 2 > buffer.Length) + Grow (2); + + buffer [position++] = (byte) value; + buffer [position++] = (byte) (value >> 8); + + if (position > length) + length = position; + } + + public void WriteInt16 (short value) + { + WriteUInt16 ((ushort) value); + } + + public void WriteUInt32 (uint value) + { + if (position + 4 > buffer.Length) + Grow (4); + + buffer [position++] = (byte) value; + buffer [position++] = (byte) (value >> 8); + buffer [position++] = (byte) (value >> 16); + buffer [position++] = (byte) (value >> 24); + + if (position > length) + length = position; + } + + public void WriteInt32 (int value) + { + WriteUInt32 ((uint) value); + } + + public void WriteUInt64 (ulong value) + { + if (position + 8 > buffer.Length) + Grow (8); + + buffer [position++] = (byte) value; + buffer [position++] = (byte) (value >> 8); + buffer [position++] = (byte) (value >> 16); + buffer [position++] = (byte) (value >> 24); + buffer [position++] = (byte) (value >> 32); + buffer [position++] = (byte) (value >> 40); + buffer [position++] = (byte) (value >> 48); + buffer [position++] = (byte) (value >> 56); + + if (position > length) + length = position; + } + + public void WriteInt64 (long value) + { + WriteUInt64 ((ulong) value); + } + + public void WriteCompressedUInt32 (uint value) + { + if (value < 0x80) + WriteByte ((byte) value); + else if (value < 0x4000) { + WriteByte ((byte) (0x80 | (value >> 8))); + WriteByte ((byte) (value & 0xff)); + } else { + WriteByte ((byte) ((value >> 24) | 0xc0)); + WriteByte ((byte) ((value >> 16) & 0xff)); + WriteByte ((byte) ((value >> 8) & 0xff)); + WriteByte ((byte) (value & 0xff)); + } + } + + public void WriteCompressedInt32 (int value) + { + if (value >= 0) { + WriteCompressedUInt32 ((uint) (value << 1)); + return; + } + + if (value > -0x40) + value = 0x40 + value; + else if (value >= -0x2000) + value = 0x2000 + value; + else if (value >= -0x20000000) + value = 0x20000000 + value; + + WriteCompressedUInt32 ((uint) ((value << 1) | 1)); + } + + public void WriteBytes (byte [] bytes) + { + var length = bytes.Length; + if (position + length > buffer.Length) + Grow (length); + + Buffer.BlockCopy (bytes, 0, buffer, position, length); + position += length; + + if (position > this.length) + this.length = position; + } + + public void WriteBytes (int length) + { + if (position + length > buffer.Length) + Grow (length); + + position += length; + + if (position > this.length) + this.length = position; + } + + public void WriteBytes (ByteBuffer buffer) + { + if (position + buffer.length > this.buffer.Length) + Grow (buffer.length); + + Buffer.BlockCopy (buffer.buffer, 0, this.buffer, position, buffer.length); + position += buffer.length; + + if (position > this.length) + this.length = position; + } + + public void WriteSingle (float value) + { + var bytes = BitConverter.GetBytes (value); + + if (!BitConverter.IsLittleEndian) + Array.Reverse (bytes); + + WriteBytes (bytes); + } + + public void WriteDouble (double value) + { + var bytes = BitConverter.GetBytes (value); + + if (!BitConverter.IsLittleEndian) + Array.Reverse (bytes); + + WriteBytes (bytes); + } + + void Grow (int desired) + { + var current = this.buffer; + var current_length = current.Length; + + var buffer = new byte [System.Math.Max (current_length + desired, current_length * 2)]; + Buffer.BlockCopy (current, 0, buffer, 0, current_length); + this.buffer = buffer; + } + +#endif + + } +} diff --git a/external/cecil-legacy/Mono.Cecil.PE/ByteBufferEqualityComparer.cs b/external/cecil-legacy/Mono.Cecil.PE/ByteBufferEqualityComparer.cs new file mode 100644 index 0000000000..70e89164c2 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil.PE/ByteBufferEqualityComparer.cs @@ -0,0 +1,78 @@ +// +// ByteBufferEqualityComparer.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Collections.Generic; + +namespace Mono.Cecil.PE { + + sealed class ByteBufferEqualityComparer : IEqualityComparer { + + public bool Equals (ByteBuffer x, ByteBuffer y) + { + if (x.length != y.length) + return false; + + var x_buffer = x.buffer; + var y_buffer = y.buffer; + + for (int i = 0; i < x.length; i++) + if (x_buffer [i] != y_buffer [i]) + return false; + + return true; + } + + public int GetHashCode (ByteBuffer buffer) + { +#if !BYTE_BUFFER_WELL_DISTRIBUTED_HASH + var hash = 0; + var bytes = buffer.buffer; + for (int i = 0; i < buffer.length; i++) + hash = (hash * 37) ^ bytes [i]; + + return hash; +#else + const uint p = 16777619; + uint hash = 2166136261; + + var bytes = buffer.buffer; + for (int i = 0; i < buffer.length; i++) + hash = (hash ^ bytes [i]) * p; + + hash += hash << 13; + hash ^= hash >> 7; + hash += hash << 3; + hash ^= hash >> 17; + hash += hash << 5; + + return (int) hash; +#endif + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil.PE/DataDirectory.cs b/external/cecil-legacy/Mono.Cecil.PE/DataDirectory.cs new file mode 100644 index 0000000000..fedd0e2dde --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil.PE/DataDirectory.cs @@ -0,0 +1,50 @@ +// +// DataDirectory.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +using RVA = System.UInt32; + +namespace Mono.Cecil.PE { + + struct DataDirectory { + + public readonly RVA VirtualAddress; + public readonly uint Size; + + public bool IsZero { + get { return VirtualAddress == 0 && Size == 0; } + } + + public DataDirectory (RVA rva, uint size) + { + this.VirtualAddress = rva; + this.Size = size; + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil.PE/Image.cs b/external/cecil-legacy/Mono.Cecil.PE/Image.cs new file mode 100644 index 0000000000..fdecbbeb40 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil.PE/Image.cs @@ -0,0 +1,166 @@ +// +// Image.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +using Mono; +using Mono.Cecil.Cil; +using Mono.Cecil.Metadata; + +using RVA = System.UInt32; + +namespace Mono.Cecil.PE { + + sealed class Image { + + public ModuleKind Kind; + public TargetRuntime Runtime; + public TargetArchitecture Architecture; + public ModuleCharacteristics Characteristics; + public string FileName; + + public Section [] Sections; + + public Section MetadataSection; + + public uint EntryPointToken; + public ModuleAttributes Attributes; + + public DataDirectory Debug; + public DataDirectory Resources; + public DataDirectory StrongName; + + public StringHeap StringHeap; + public BlobHeap BlobHeap; + public UserStringHeap UserStringHeap; + public GuidHeap GuidHeap; + public TableHeap TableHeap; + + readonly int [] coded_index_sizes = new int [13]; + + readonly Func counter; + + public Image () + { + counter = GetTableLength; + } + + public bool HasTable (Table table) + { + return GetTableLength (table) > 0; + } + + public int GetTableLength (Table table) + { + return (int) TableHeap [table].Length; + } + + public int GetTableIndexSize (Table table) + { + return GetTableLength (table) < 65536 ? 2 : 4; + } + + public int GetCodedIndexSize (CodedIndex coded_index) + { + var index = (int) coded_index; + var size = coded_index_sizes [index]; + if (size != 0) + return size; + + return coded_index_sizes [index] = coded_index.GetSize (counter); + } + + public uint ResolveVirtualAddress (RVA rva) + { + var section = GetSectionAtVirtualAddress (rva); + if (section == null) + throw new ArgumentOutOfRangeException (); + + return ResolveVirtualAddressInSection (rva, section); + } + + public uint ResolveVirtualAddressInSection (RVA rva, Section section) + { + return rva + section.PointerToRawData - section.VirtualAddress; + } + + public Section GetSection (string name) + { + var sections = this.Sections; + for (int i = 0; i < sections.Length; i++) { + var section = sections [i]; + if (section.Name == name) + return section; + } + + return null; + } + + public Section GetSectionAtVirtualAddress (RVA rva) + { + var sections = this.Sections; + for (int i = 0; i < sections.Length; i++) { + var section = sections [i]; + if (rva >= section.VirtualAddress && rva < section.VirtualAddress + section.SizeOfRawData) + return section; + } + + return null; + } + + public ImageDebugDirectory GetDebugHeader (out byte [] header) + { + var section = GetSectionAtVirtualAddress (Debug.VirtualAddress); + var buffer = new ByteBuffer (section.Data); + buffer.position = (int) (Debug.VirtualAddress - section.VirtualAddress); + + var directory = new ImageDebugDirectory { + Characteristics = buffer.ReadInt32 (), + TimeDateStamp = buffer.ReadInt32 (), + MajorVersion = buffer.ReadInt16 (), + MinorVersion = buffer.ReadInt16 (), + Type = buffer.ReadInt32 (), + SizeOfData = buffer.ReadInt32 (), + AddressOfRawData = buffer.ReadInt32 (), + PointerToRawData = buffer.ReadInt32 (), + }; + + if (directory.SizeOfData == 0 || directory.PointerToRawData == 0) { + header = Empty.Array; + return directory; + } + + buffer.position = (int) (directory.PointerToRawData - section.PointerToRawData); + + header = new byte [directory.SizeOfData]; + Buffer.BlockCopy (buffer.buffer, buffer.position, header, 0, header.Length); + + return directory; + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil.PE/ImageReader.cs b/external/cecil-legacy/Mono.Cecil.PE/ImageReader.cs new file mode 100644 index 0000000000..c96c1db318 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil.PE/ImageReader.cs @@ -0,0 +1,681 @@ +// +// ImageReader.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.IO; + +using Mono.Cecil.Metadata; + +using RVA = System.UInt32; + +namespace Mono.Cecil.PE { + + sealed class ImageReader : BinaryStreamReader { + + readonly Image image; + + DataDirectory cli; + DataDirectory metadata; + + public ImageReader (Stream stream) + : base (stream) + { + image = new Image (); + + image.FileName = stream.GetFullyQualifiedName (); + } + + void MoveTo (DataDirectory directory) + { + BaseStream.Position = image.ResolveVirtualAddress (directory.VirtualAddress); + } + + void MoveTo (uint position) + { + BaseStream.Position = position; + } + + void ReadImage () + { + if (BaseStream.Length < 128) + throw new BadImageFormatException (); + + // - DOSHeader + + // PE 2 + // Start 58 + // Lfanew 4 + // End 64 + + if (ReadUInt16 () != 0x5a4d) + throw new BadImageFormatException (); + + Advance (58); + + MoveTo (ReadUInt32 ()); + + if (ReadUInt32 () != 0x00004550) + throw new BadImageFormatException (); + + // - PEFileHeader + + // Machine 2 + image.Architecture = ReadArchitecture (); + + // NumberOfSections 2 + ushort sections = ReadUInt16 (); + + // TimeDateStamp 4 + // PointerToSymbolTable 4 + // NumberOfSymbols 4 + // OptionalHeaderSize 2 + Advance (14); + + // Characteristics 2 + ushort characteristics = ReadUInt16 (); + + ushort subsystem, dll_characteristics; + ReadOptionalHeaders (out subsystem, out dll_characteristics); + ReadSections (sections); + ReadCLIHeader (); + ReadMetadata (); + + image.Kind = GetModuleKind (characteristics, subsystem); + image.Characteristics = (ModuleCharacteristics) dll_characteristics; + } + + TargetArchitecture ReadArchitecture () + { + var machine = ReadUInt16 (); + switch (machine) { + case 0x014c: + return TargetArchitecture.I386; + case 0x8664: + return TargetArchitecture.AMD64; + case 0x0200: + return TargetArchitecture.IA64; + case 0x01c4: + return TargetArchitecture.ARMv7; + } + + throw new NotSupportedException (); + } + + static ModuleKind GetModuleKind (ushort characteristics, ushort subsystem) + { + if ((characteristics & 0x2000) != 0) // ImageCharacteristics.Dll + return ModuleKind.Dll; + + if (subsystem == 0x2 || subsystem == 0x9) // SubSystem.WindowsGui || SubSystem.WindowsCeGui + return ModuleKind.Windows; + + return ModuleKind.Console; + } + + void ReadOptionalHeaders (out ushort subsystem, out ushort dll_characteristics) + { + // - PEOptionalHeader + // - StandardFieldsHeader + + // Magic 2 + bool pe64 = ReadUInt16 () == 0x20b; + + // pe32 || pe64 + + // LMajor 1 + // LMinor 1 + // CodeSize 4 + // InitializedDataSize 4 + // UninitializedDataSize4 + // EntryPointRVA 4 + // BaseOfCode 4 + // BaseOfData 4 || 0 + + // - NTSpecificFieldsHeader + + // ImageBase 4 || 8 + // SectionAlignment 4 + // FileAlignement 4 + // OSMajor 2 + // OSMinor 2 + // UserMajor 2 + // UserMinor 2 + // SubSysMajor 2 + // SubSysMinor 2 + // Reserved 4 + // ImageSize 4 + // HeaderSize 4 + // FileChecksum 4 + Advance (66); + + // SubSystem 2 + subsystem = ReadUInt16 (); + + // DLLFlags 2 + dll_characteristics = ReadUInt16 (); + // StackReserveSize 4 || 8 + // StackCommitSize 4 || 8 + // HeapReserveSize 4 || 8 + // HeapCommitSize 4 || 8 + // LoaderFlags 4 + // NumberOfDataDir 4 + + // - DataDirectoriesHeader + + // ExportTable 8 + // ImportTable 8 + // ResourceTable 8 + // ExceptionTable 8 + // CertificateTable 8 + // BaseRelocationTable 8 + + Advance (pe64 ? 88 : 72); + + // Debug 8 + image.Debug = ReadDataDirectory (); + + // Copyright 8 + // GlobalPtr 8 + // TLSTable 8 + // LoadConfigTable 8 + // BoundImport 8 + // IAT 8 + // DelayImportDescriptor8 + Advance (56); + + // CLIHeader 8 + cli = ReadDataDirectory (); + + if (cli.IsZero) + throw new BadImageFormatException (); + + // Reserved 8 + Advance (8); + } + + string ReadAlignedString (int length) + { + int read = 0; + var buffer = new char [length]; + while (read < length) { + var current = ReadByte (); + if (current == 0) + break; + + buffer [read++] = (char) current; + } + + Advance (-1 + ((read + 4) & ~3) - read); + + return new string (buffer, 0, read); + } + + string ReadZeroTerminatedString (int length) + { + int read = 0; + var buffer = new char [length]; + var bytes = ReadBytes (length); + while (read < length) { + var current = bytes [read]; + if (current == 0) + break; + + buffer [read++] = (char) current; + } + + return new string (buffer, 0, read); + } + + void ReadSections (ushort count) + { + var sections = new Section [count]; + + for (int i = 0; i < count; i++) { + var section = new Section (); + + // Name + section.Name = ReadZeroTerminatedString (8); + + // VirtualSize 4 + Advance (4); + + // VirtualAddress 4 + section.VirtualAddress = ReadUInt32 (); + // SizeOfRawData 4 + section.SizeOfRawData = ReadUInt32 (); + // PointerToRawData 4 + section.PointerToRawData = ReadUInt32 (); + + // PointerToRelocations 4 + // PointerToLineNumbers 4 + // NumberOfRelocations 2 + // NumberOfLineNumbers 2 + // Characteristics 4 + Advance (16); + + sections [i] = section; + + ReadSectionData (section); + } + + image.Sections = sections; + } + + void ReadSectionData (Section section) + { + var position = BaseStream.Position; + + MoveTo (section.PointerToRawData); + + var length = (int) section.SizeOfRawData; + var data = new byte [length]; + int offset = 0, read; + + while ((read = Read (data, offset, length - offset)) > 0) + offset += read; + + section.Data = data; + + BaseStream.Position = position; + } + + void ReadCLIHeader () + { + MoveTo (cli); + + // - CLIHeader + + // Cb 4 + // MajorRuntimeVersion 2 + // MinorRuntimeVersion 2 + Advance (8); + + // Metadata 8 + metadata = ReadDataDirectory (); + // Flags 4 + image.Attributes = (ModuleAttributes) ReadUInt32 (); + // EntryPointToken 4 + image.EntryPointToken = ReadUInt32 (); + // Resources 8 + image.Resources = ReadDataDirectory (); + // StrongNameSignature 8 + image.StrongName = ReadDataDirectory (); + // CodeManagerTable 8 + // VTableFixups 8 + // ExportAddressTableJumps 8 + // ManagedNativeHeader 8 + } + + void ReadMetadata () + { + MoveTo (metadata); + + if (ReadUInt32 () != 0x424a5342) + throw new BadImageFormatException (); + + // MajorVersion 2 + // MinorVersion 2 + // Reserved 4 + Advance (8); + + var version = ReadZeroTerminatedString (ReadInt32 ()); + image.Runtime = version.ParseRuntime (); + + // Flags 2 + Advance (2); + + var streams = ReadUInt16 (); + + var section = image.GetSectionAtVirtualAddress (metadata.VirtualAddress); + if (section == null) + throw new BadImageFormatException (); + + image.MetadataSection = section; + + for (int i = 0; i < streams; i++) + ReadMetadataStream (section); + + if (image.TableHeap != null) + ReadTableHeap (); + } + + void ReadMetadataStream (Section section) + { + // Offset 4 + uint start = metadata.VirtualAddress - section.VirtualAddress + ReadUInt32 (); // relative to the section start + + // Size 4 + uint size = ReadUInt32 (); + + var name = ReadAlignedString (16); + switch (name) { + case "#~": + case "#-": + image.TableHeap = new TableHeap (section, start, size); + break; + case "#Strings": + image.StringHeap = new StringHeap (section, start, size); + break; + case "#Blob": + image.BlobHeap = new BlobHeap (section, start, size); + break; + case "#GUID": + image.GuidHeap = new GuidHeap (section, start, size); + break; + case "#US": + image.UserStringHeap = new UserStringHeap (section, start, size); + break; + } + } + + void ReadTableHeap () + { + var heap = image.TableHeap; + + uint start = heap.Section.PointerToRawData; + + MoveTo (heap.Offset + start); + + // Reserved 4 + // MajorVersion 1 + // MinorVersion 1 + Advance (6); + + // HeapSizes 1 + var sizes = ReadByte (); + + // Reserved2 1 + Advance (1); + + // Valid 8 + heap.Valid = ReadInt64 (); + + // Sorted 8 + heap.Sorted = ReadInt64 (); + + for (int i = 0; i < TableHeap.TableCount; i++) { + if (!heap.HasTable ((Table) i)) + continue; + + heap.Tables [i].Length = ReadUInt32 (); + } + + SetIndexSize (image.StringHeap, sizes, 0x1); + SetIndexSize (image.GuidHeap, sizes, 0x2); + SetIndexSize (image.BlobHeap, sizes, 0x4); + + ComputeTableInformations (); + } + + static void SetIndexSize (Heap heap, uint sizes, byte flag) + { + if (heap == null) + return; + + heap.IndexSize = (sizes & flag) > 0 ? 4 : 2; + } + + int GetTableIndexSize (Table table) + { + return image.GetTableIndexSize (table); + } + + int GetCodedIndexSize (CodedIndex index) + { + return image.GetCodedIndexSize (index); + } + + void ComputeTableInformations () + { + uint offset = (uint) BaseStream.Position - image.MetadataSection.PointerToRawData; // header + + int stridx_size = image.StringHeap.IndexSize; + int blobidx_size = image.BlobHeap != null ? image.BlobHeap.IndexSize : 2; + + var heap = image.TableHeap; + var tables = heap.Tables; + + for (int i = 0; i < TableHeap.TableCount; i++) { + var table = (Table) i; + if (!heap.HasTable (table)) + continue; + + int size; + switch (table) { + case Table.Module: + size = 2 // Generation + + stridx_size // Name + + (image.GuidHeap.IndexSize * 3); // Mvid, EncId, EncBaseId + break; + case Table.TypeRef: + size = GetCodedIndexSize (CodedIndex.ResolutionScope) // ResolutionScope + + (stridx_size * 2); // Name, Namespace + break; + case Table.TypeDef: + size = 4 // Flags + + (stridx_size * 2) // Name, Namespace + + GetCodedIndexSize (CodedIndex.TypeDefOrRef) // BaseType + + GetTableIndexSize (Table.Field) // FieldList + + GetTableIndexSize (Table.Method); // MethodList + break; + case Table.FieldPtr: + size = GetTableIndexSize (Table.Field); // Field + break; + case Table.Field: + size = 2 // Flags + + stridx_size // Name + + blobidx_size; // Signature + break; + case Table.MethodPtr: + size = GetTableIndexSize (Table.Method); // Method + break; + case Table.Method: + size = 8 // Rva 4, ImplFlags 2, Flags 2 + + stridx_size // Name + + blobidx_size // Signature + + GetTableIndexSize (Table.Param); // ParamList + break; + case Table.ParamPtr: + size = GetTableIndexSize (Table.Param); // Param + break; + case Table.Param: + size = 4 // Flags 2, Sequence 2 + + stridx_size; // Name + break; + case Table.InterfaceImpl: + size = GetTableIndexSize (Table.TypeDef) // Class + + GetCodedIndexSize (CodedIndex.TypeDefOrRef); // Interface + break; + case Table.MemberRef: + size = GetCodedIndexSize (CodedIndex.MemberRefParent) // Class + + stridx_size // Name + + blobidx_size; // Signature + break; + case Table.Constant: + size = 2 // Type + + GetCodedIndexSize (CodedIndex.HasConstant) // Parent + + blobidx_size; // Value + break; + case Table.CustomAttribute: + size = GetCodedIndexSize (CodedIndex.HasCustomAttribute) // Parent + + GetCodedIndexSize (CodedIndex.CustomAttributeType) // Type + + blobidx_size; // Value + break; + case Table.FieldMarshal: + size = GetCodedIndexSize (CodedIndex.HasFieldMarshal) // Parent + + blobidx_size; // NativeType + break; + case Table.DeclSecurity: + size = 2 // Action + + GetCodedIndexSize (CodedIndex.HasDeclSecurity) // Parent + + blobidx_size; // PermissionSet + break; + case Table.ClassLayout: + size = 6 // PackingSize 2, ClassSize 4 + + GetTableIndexSize (Table.TypeDef); // Parent + break; + case Table.FieldLayout: + size = 4 // Offset + + GetTableIndexSize (Table.Field); // Field + break; + case Table.StandAloneSig: + size = blobidx_size; // Signature + break; + case Table.EventMap: + size = GetTableIndexSize (Table.TypeDef) // Parent + + GetTableIndexSize (Table.Event); // EventList + break; + case Table.EventPtr: + size = GetTableIndexSize (Table.Event); // Event + break; + case Table.Event: + size = 2 // Flags + + stridx_size // Name + + GetCodedIndexSize (CodedIndex.TypeDefOrRef); // EventType + break; + case Table.PropertyMap: + size = GetTableIndexSize (Table.TypeDef) // Parent + + GetTableIndexSize (Table.Property); // PropertyList + break; + case Table.PropertyPtr: + size = GetTableIndexSize (Table.Property); // Property + break; + case Table.Property: + size = 2 // Flags + + stridx_size // Name + + blobidx_size; // Type + break; + case Table.MethodSemantics: + size = 2 // Semantics + + GetTableIndexSize (Table.Method) // Method + + GetCodedIndexSize (CodedIndex.HasSemantics); // Association + break; + case Table.MethodImpl: + size = GetTableIndexSize (Table.TypeDef) // Class + + GetCodedIndexSize (CodedIndex.MethodDefOrRef) // MethodBody + + GetCodedIndexSize (CodedIndex.MethodDefOrRef); // MethodDeclaration + break; + case Table.ModuleRef: + size = stridx_size; // Name + break; + case Table.TypeSpec: + size = blobidx_size; // Signature + break; + case Table.ImplMap: + size = 2 // MappingFlags + + GetCodedIndexSize (CodedIndex.MemberForwarded) // MemberForwarded + + stridx_size // ImportName + + GetTableIndexSize (Table.ModuleRef); // ImportScope + break; + case Table.FieldRVA: + size = 4 // RVA + + GetTableIndexSize (Table.Field); // Field + break; + case Table.EncLog: + case Table.EncMap: + size = 4; + break; + case Table.Assembly: + size = 16 // HashAlgId 4, Version 4 * 2, Flags 4 + + blobidx_size // PublicKey + + (stridx_size * 2); // Name, Culture + break; + case Table.AssemblyProcessor: + size = 4; // Processor + break; + case Table.AssemblyOS: + size = 12; // Platform 4, Version 2 * 4 + break; + case Table.AssemblyRef: + size = 12 // Version 2 * 4 + Flags 4 + + (blobidx_size * 2) // PublicKeyOrToken, HashValue + + (stridx_size * 2); // Name, Culture + break; + case Table.AssemblyRefProcessor: + size = 4 // Processor + + GetTableIndexSize (Table.AssemblyRef); // AssemblyRef + break; + case Table.AssemblyRefOS: + size = 12 // Platform 4, Version 2 * 4 + + GetTableIndexSize (Table.AssemblyRef); // AssemblyRef + break; + case Table.File: + size = 4 // Flags + + stridx_size // Name + + blobidx_size; // HashValue + break; + case Table.ExportedType: + size = 8 // Flags 4, TypeDefId 4 + + (stridx_size * 2) // Name, Namespace + + GetCodedIndexSize (CodedIndex.Implementation); // Implementation + break; + case Table.ManifestResource: + size = 8 // Offset, Flags + + stridx_size // Name + + GetCodedIndexSize (CodedIndex.Implementation); // Implementation + break; + case Table.NestedClass: + size = GetTableIndexSize (Table.TypeDef) // NestedClass + + GetTableIndexSize (Table.TypeDef); // EnclosingClass + break; + case Table.GenericParam: + size = 4 // Number, Flags + + GetCodedIndexSize (CodedIndex.TypeOrMethodDef) // Owner + + stridx_size; // Name + break; + case Table.MethodSpec: + size = GetCodedIndexSize (CodedIndex.MethodDefOrRef) // Method + + blobidx_size; // Instantiation + break; + case Table.GenericParamConstraint: + size = GetTableIndexSize (Table.GenericParam) // Owner + + GetCodedIndexSize (CodedIndex.TypeDefOrRef); // Constraint + break; + default: + throw new NotSupportedException (); + } + + tables [i].RowSize = (uint) size; + tables [i].Offset = offset; + + offset += (uint) size * tables [i].Length; + } + } + + public static Image ReadImageFrom (Stream stream) + { + try { + var reader = new ImageReader (stream); + reader.ReadImage (); + return reader.image; + } catch (EndOfStreamException e) { + throw new BadImageFormatException (stream.GetFullyQualifiedName (), e); + } + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil.PE/ImageWriter.cs b/external/cecil-legacy/Mono.Cecil.PE/ImageWriter.cs new file mode 100644 index 0000000000..08f9ea2b76 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil.PE/ImageWriter.cs @@ -0,0 +1,828 @@ +// +// ImageWriter.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.IO; + +#if !READ_ONLY + +using Mono.Cecil.Cil; +using Mono.Cecil.Metadata; + +using RVA = System.UInt32; + +namespace Mono.Cecil.PE { + + sealed class ImageWriter : BinaryStreamWriter { + + readonly ModuleDefinition module; + readonly MetadataBuilder metadata; + readonly TextMap text_map; + + ImageDebugDirectory debug_directory; + byte [] debug_data; + + ByteBuffer win32_resources; + + const uint pe_header_size = 0x178u; + const uint section_header_size = 0x28u; + const uint file_alignment = 0x200; + const uint section_alignment = 0x2000; + const ulong image_base = 0x00400000; + + internal const RVA text_rva = 0x2000; + + readonly bool pe64; + readonly bool has_reloc; + readonly uint time_stamp; + + internal Section text; + internal Section rsrc; + internal Section reloc; + + ushort sections; + + ImageWriter (ModuleDefinition module, MetadataBuilder metadata, Stream stream) + : base (stream) + { + this.module = module; + this.metadata = metadata; + this.pe64 = module.Architecture == TargetArchitecture.AMD64 || module.Architecture == TargetArchitecture.IA64; + this.has_reloc = module.Architecture == TargetArchitecture.I386; + this.GetDebugHeader (); + this.GetWin32Resources (); + this.text_map = BuildTextMap (); + this.sections = (ushort) (has_reloc ? 2 : 1); // text + reloc? + this.time_stamp = (uint) DateTime.UtcNow.Subtract (new DateTime (1970, 1, 1)).TotalSeconds; + } + + void GetDebugHeader () + { + var symbol_writer = metadata.symbol_writer; + if (symbol_writer == null) + return; + + if (!symbol_writer.GetDebugHeader (out debug_directory, out debug_data)) + debug_data = Empty.Array; + } + + void GetWin32Resources () + { + var rsrc = GetImageResourceSection (); + if (rsrc == null) + return; + + var raw_resources = new byte [rsrc.Data.Length]; + Buffer.BlockCopy (rsrc.Data, 0, raw_resources, 0, rsrc.Data.Length); + win32_resources = new ByteBuffer (raw_resources); + } + + Section GetImageResourceSection () + { + if (!module.HasImage) + return null; + + const string rsrc_section = ".rsrc"; + + return module.Image.GetSection (rsrc_section); + } + + public static ImageWriter CreateWriter (ModuleDefinition module, MetadataBuilder metadata, Stream stream) + { + var writer = new ImageWriter (module, metadata, stream); + writer.BuildSections (); + return writer; + } + + void BuildSections () + { + var has_win32_resources = win32_resources != null; + if (has_win32_resources) + sections++; + + text = CreateSection (".text", text_map.GetLength (), null); + var previous = text; + + if (has_win32_resources) { + rsrc = CreateSection (".rsrc", (uint) win32_resources.length, previous); + + PatchWin32Resources (win32_resources); + previous = rsrc; + } + + if (has_reloc) + reloc = CreateSection (".reloc", 12u, previous); + } + + Section CreateSection (string name, uint size, Section previous) + { + return new Section { + Name = name, + VirtualAddress = previous != null + ? previous.VirtualAddress + Align (previous.VirtualSize, section_alignment) + : text_rva, + VirtualSize = size, + PointerToRawData = previous != null + ? previous.PointerToRawData + previous.SizeOfRawData + : Align (GetHeaderSize (), file_alignment), + SizeOfRawData = Align (size, file_alignment) + }; + } + + static uint Align (uint value, uint align) + { + align--; + return (value + align) & ~align; + } + + void WriteDOSHeader () + { + Write (new byte [] { + // dos header start + 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + // lfanew + 0x80, 0x00, 0x00, 0x00, + // dos header end + 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, + 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, + 0x54, 0x68, 0x69, 0x73, 0x20, 0x70, 0x72, + 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, + 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x62, + 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, + 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20, 0x6d, + 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, + 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00 + }); + } + + void WritePEFileHeader () + { + WriteUInt32 (0x00004550); // Magic + WriteUInt16 (GetMachine ()); // Machine + WriteUInt16 (sections); // NumberOfSections + WriteUInt32 (time_stamp); + WriteUInt32 (0); // PointerToSymbolTable + WriteUInt32 (0); // NumberOfSymbols + WriteUInt16 ((ushort) (!pe64 ? 0xe0 : 0xf0)); // SizeOfOptionalHeader + + // ExecutableImage | (pe64 ? 32BitsMachine : LargeAddressAware) + var characteristics = (ushort) (0x0002 | (!pe64 ? 0x0100 : 0x0020)); + if (module.Kind == ModuleKind.Dll || module.Kind == ModuleKind.NetModule) + characteristics |= 0x2000; + WriteUInt16 (characteristics); // Characteristics + } + + ushort GetMachine () + { + switch (module.Architecture) { + case TargetArchitecture.I386: + return 0x014c; + case TargetArchitecture.AMD64: + return 0x8664; + case TargetArchitecture.IA64: + return 0x0200; + case TargetArchitecture.ARMv7: + return 0x01c4; + } + + throw new NotSupportedException (); + } + + Section LastSection () + { + if (reloc != null) + return reloc; + + if (rsrc != null) + return rsrc; + + return text; + } + + void WriteOptionalHeaders () + { + WriteUInt16 ((ushort) (!pe64 ? 0x10b : 0x20b)); // Magic + WriteByte (8); // LMajor + WriteByte (0); // LMinor + WriteUInt32 (text.SizeOfRawData); // CodeSize + WriteUInt32 ((reloc != null ? reloc.SizeOfRawData : 0) + + (rsrc != null ? rsrc.SizeOfRawData : 0)); // InitializedDataSize + WriteUInt32 (0); // UninitializedDataSize + + var startub_stub = text_map.GetRange (TextSegment.StartupStub); + WriteUInt32 (startub_stub.Length > 0 ? startub_stub.Start : 0); // EntryPointRVA + WriteUInt32 (text_rva); // BaseOfCode + + if (!pe64) { + WriteUInt32 (0); // BaseOfData + WriteUInt32 ((uint) image_base); // ImageBase + } else { + WriteUInt64 (image_base); // ImageBase + } + + WriteUInt32 (section_alignment); // SectionAlignment + WriteUInt32 (file_alignment); // FileAlignment + + WriteUInt16 (4); // OSMajor + WriteUInt16 (0); // OSMinor + WriteUInt16 (0); // UserMajor + WriteUInt16 (0); // UserMinor + WriteUInt16 (4); // SubSysMajor + WriteUInt16 (0); // SubSysMinor + WriteUInt32 (0); // Reserved + + var last_section = LastSection(); + WriteUInt32 (last_section.VirtualAddress + Align (last_section.VirtualSize, section_alignment)); // ImageSize + WriteUInt32 (text.PointerToRawData); // HeaderSize + + WriteUInt32 (0); // Checksum + WriteUInt16 (GetSubSystem ()); // SubSystem + WriteUInt16 ((ushort) module.Characteristics); // DLLFlags + + const ulong stack_reserve = 0x100000; + const ulong stack_commit = 0x1000; + const ulong heap_reserve = 0x100000; + const ulong heap_commit = 0x1000; + + if (!pe64) { + WriteUInt32 ((uint) stack_reserve); + WriteUInt32 ((uint) stack_commit); + WriteUInt32 ((uint) heap_reserve); + WriteUInt32 ((uint) heap_commit); + } else { + WriteUInt64 (stack_reserve); + WriteUInt64 (stack_commit); + WriteUInt64 (heap_reserve); + WriteUInt64 (heap_commit); + } + + WriteUInt32 (0); // LoaderFlags + WriteUInt32 (16); // NumberOfDataDir + + WriteZeroDataDirectory (); // ExportTable + WriteDataDirectory (text_map.GetDataDirectory (TextSegment.ImportDirectory)); // ImportTable + if (rsrc != null) { // ResourceTable + WriteUInt32 (rsrc.VirtualAddress); + WriteUInt32 (rsrc.VirtualSize); + } else + WriteZeroDataDirectory (); + + WriteZeroDataDirectory (); // ExceptionTable + WriteZeroDataDirectory (); // CertificateTable + WriteUInt32 (reloc != null ? reloc.VirtualAddress : 0); // BaseRelocationTable + WriteUInt32 (reloc != null ? reloc.VirtualSize : 0); + + if (text_map.GetLength (TextSegment.DebugDirectory) > 0) { + WriteUInt32 (text_map.GetRVA (TextSegment.DebugDirectory)); + WriteUInt32 (28u); + } else + WriteZeroDataDirectory (); + + WriteZeroDataDirectory (); // Copyright + WriteZeroDataDirectory (); // GlobalPtr + WriteZeroDataDirectory (); // TLSTable + WriteZeroDataDirectory (); // LoadConfigTable + WriteZeroDataDirectory (); // BoundImport + WriteDataDirectory (text_map.GetDataDirectory (TextSegment.ImportAddressTable)); // IAT + WriteZeroDataDirectory (); // DelayImportDesc + WriteDataDirectory (text_map.GetDataDirectory (TextSegment.CLIHeader)); // CLIHeader + WriteZeroDataDirectory (); // Reserved + } + + void WriteZeroDataDirectory () + { + WriteUInt32 (0); + WriteUInt32 (0); + } + + ushort GetSubSystem () + { + switch (module.Kind) { + case ModuleKind.Console: + case ModuleKind.Dll: + case ModuleKind.NetModule: + return 0x3; + case ModuleKind.Windows: + return 0x2; + default: + throw new ArgumentOutOfRangeException (); + } + } + + void WriteSectionHeaders () + { + WriteSection (text, 0x60000020); + + if (rsrc != null) + WriteSection (rsrc, 0x40000040); + + if (reloc != null) + WriteSection (reloc, 0x42000040); + } + + void WriteSection (Section section, uint characteristics) + { + var name = new byte [8]; + var sect_name = section.Name; + for (int i = 0; i < sect_name.Length; i++) + name [i] = (byte) sect_name [i]; + + WriteBytes (name); + WriteUInt32 (section.VirtualSize); + WriteUInt32 (section.VirtualAddress); + WriteUInt32 (section.SizeOfRawData); + WriteUInt32 (section.PointerToRawData); + WriteUInt32 (0); // PointerToRelocations + WriteUInt32 (0); // PointerToLineNumbers + WriteUInt16 (0); // NumberOfRelocations + WriteUInt16 (0); // NumberOfLineNumbers + WriteUInt32 (characteristics); + } + + void MoveTo (uint pointer) + { + BaseStream.Seek (pointer, SeekOrigin.Begin); + } + + void MoveToRVA (Section section, RVA rva) + { + BaseStream.Seek (section.PointerToRawData + rva - section.VirtualAddress, SeekOrigin.Begin); + } + + void MoveToRVA (TextSegment segment) + { + MoveToRVA (text, text_map.GetRVA (segment)); + } + + void WriteRVA (RVA rva) + { + if (!pe64) + WriteUInt32 (rva); + else + WriteUInt64 (rva); + } + + void WriteText () + { + MoveTo (text.PointerToRawData); + + // ImportAddressTable + + if (has_reloc) { + WriteRVA (text_map.GetRVA (TextSegment.ImportHintNameTable)); + WriteRVA (0); + } + + // CLIHeader + + WriteUInt32 (0x48); + WriteUInt16 (2); + WriteUInt16 ((ushort) ((module.Runtime <= TargetRuntime.Net_1_1) ? 0 : 5)); + + WriteUInt32 (text_map.GetRVA (TextSegment.MetadataHeader)); + WriteUInt32 (GetMetadataLength ()); + WriteUInt32 ((uint) module.Attributes); + WriteUInt32 (metadata.entry_point.ToUInt32 ()); + WriteDataDirectory (text_map.GetDataDirectory (TextSegment.Resources)); + WriteDataDirectory (text_map.GetDataDirectory (TextSegment.StrongNameSignature)); + WriteZeroDataDirectory (); // CodeManagerTable + WriteZeroDataDirectory (); // VTableFixups + WriteZeroDataDirectory (); // ExportAddressTableJumps + WriteZeroDataDirectory (); // ManagedNativeHeader + + // Code + + MoveToRVA (TextSegment.Code); + WriteBuffer (metadata.code); + + // Resources + + MoveToRVA (TextSegment.Resources); + WriteBuffer (metadata.resources); + + // Data + + if (metadata.data.length > 0) { + MoveToRVA (TextSegment.Data); + WriteBuffer (metadata.data); + } + + // StrongNameSignature + // stays blank + + // MetadataHeader + + MoveToRVA (TextSegment.MetadataHeader); + WriteMetadataHeader (); + + WriteMetadata (); + + // DebugDirectory + if (text_map.GetLength (TextSegment.DebugDirectory) > 0) { + MoveToRVA (TextSegment.DebugDirectory); + WriteDebugDirectory (); + } + + if (!has_reloc) + return; + + // ImportDirectory + MoveToRVA (TextSegment.ImportDirectory); + WriteImportDirectory (); + + // StartupStub + MoveToRVA (TextSegment.StartupStub); + WriteStartupStub (); + } + + uint GetMetadataLength () + { + return text_map.GetRVA (TextSegment.DebugDirectory) - text_map.GetRVA (TextSegment.MetadataHeader); + } + + void WriteMetadataHeader () + { + WriteUInt32 (0x424a5342); // Signature + WriteUInt16 (1); // MajorVersion + WriteUInt16 (1); // MinorVersion + WriteUInt32 (0); // Reserved + + var version = GetZeroTerminatedString (GetVersion ()); + WriteUInt32 ((uint) version.Length); + WriteBytes (version); + WriteUInt16 (0); // Flags + WriteUInt16 (GetStreamCount ()); + + uint offset = text_map.GetRVA (TextSegment.TableHeap) - text_map.GetRVA (TextSegment.MetadataHeader); + + WriteStreamHeader (ref offset, TextSegment.TableHeap, "#~"); + WriteStreamHeader (ref offset, TextSegment.StringHeap, "#Strings"); + WriteStreamHeader (ref offset, TextSegment.UserStringHeap, "#US"); + WriteStreamHeader (ref offset, TextSegment.GuidHeap, "#GUID"); + WriteStreamHeader (ref offset, TextSegment.BlobHeap, "#Blob"); + } + + string GetVersion () + { + switch (module.Runtime) { + case TargetRuntime.Net_1_0: + return "v1.0.3705"; + case TargetRuntime.Net_1_1: + return "v1.1.4322"; + case TargetRuntime.Net_2_0: + return "v2.0.50727"; + case TargetRuntime.Net_4_0: + default: + return "v4.0.30319"; + } + } + + ushort GetStreamCount () + { + return (ushort) ( + 1 // #~ + + 1 // #Strings + + (metadata.user_string_heap.IsEmpty ? 0 : 1) // #US + + 1 // GUID + + (metadata.blob_heap.IsEmpty ? 0 : 1)); // #Blob + } + + void WriteStreamHeader (ref uint offset, TextSegment heap, string name) + { + var length = (uint) text_map.GetLength (heap); + if (length == 0) + return; + + WriteUInt32 (offset); + WriteUInt32 (length); + WriteBytes (GetZeroTerminatedString (name)); + offset += length; + } + + static byte [] GetZeroTerminatedString (string @string) + { + return GetString (@string, (@string.Length + 1 + 3) & ~3); + } + + static byte [] GetSimpleString (string @string) + { + return GetString (@string, @string.Length); + } + + static byte [] GetString (string @string, int length) + { + var bytes = new byte [length]; + for (int i = 0; i < @string.Length; i++) + bytes [i] = (byte) @string [i]; + + return bytes; + } + + void WriteMetadata () + { + WriteHeap (TextSegment.TableHeap, metadata.table_heap); + WriteHeap (TextSegment.StringHeap, metadata.string_heap); + WriteHeap (TextSegment.UserStringHeap, metadata.user_string_heap); + WriteGuidHeap (); + WriteHeap (TextSegment.BlobHeap, metadata.blob_heap); + } + + void WriteHeap (TextSegment heap, HeapBuffer buffer) + { + if (buffer.IsEmpty) + return; + + MoveToRVA (heap); + WriteBuffer (buffer); + } + + void WriteGuidHeap () + { + MoveToRVA (TextSegment.GuidHeap); + WriteBytes (module.Mvid.ToByteArray ()); + } + + void WriteDebugDirectory () + { + WriteInt32 (debug_directory.Characteristics); + WriteUInt32 (time_stamp); + WriteInt16 (debug_directory.MajorVersion); + WriteInt16 (debug_directory.MinorVersion); + WriteInt32 (debug_directory.Type); + WriteInt32 (debug_directory.SizeOfData); + WriteInt32 (debug_directory.AddressOfRawData); + WriteInt32 ((int) BaseStream.Position + 4); + + WriteBytes (debug_data); + } + + void WriteImportDirectory () + { + WriteUInt32 (text_map.GetRVA (TextSegment.ImportDirectory) + 40); // ImportLookupTable + WriteUInt32 (0); // DateTimeStamp + WriteUInt32 (0); // ForwarderChain + WriteUInt32 (text_map.GetRVA (TextSegment.ImportHintNameTable) + 14); + WriteUInt32 (text_map.GetRVA (TextSegment.ImportAddressTable)); + Advance (20); + + // ImportLookupTable + WriteUInt32 (text_map.GetRVA (TextSegment.ImportHintNameTable)); + + // ImportHintNameTable + MoveToRVA (TextSegment.ImportHintNameTable); + + WriteUInt16 (0); // Hint + WriteBytes (GetRuntimeMain ()); + WriteByte (0); + WriteBytes (GetSimpleString ("mscoree.dll")); + WriteUInt16 (0); + } + + byte [] GetRuntimeMain () + { + return module.Kind == ModuleKind.Dll || module.Kind == ModuleKind.NetModule + ? GetSimpleString ("_CorDllMain") + : GetSimpleString ("_CorExeMain"); + } + + void WriteStartupStub () + { + switch (module.Architecture) { + case TargetArchitecture.I386: + WriteUInt16 (0x25ff); + WriteUInt32 ((uint) image_base + text_map.GetRVA (TextSegment.ImportAddressTable)); + return; + default: + throw new NotSupportedException (); + } + } + + void WriteRsrc () + { + MoveTo (rsrc.PointerToRawData); + WriteBuffer (win32_resources); + } + + void WriteReloc () + { + MoveTo (reloc.PointerToRawData); + + var reloc_rva = text_map.GetRVA (TextSegment.StartupStub); + reloc_rva += module.Architecture == TargetArchitecture.IA64 ? 0x20u : 2; + var page_rva = reloc_rva & ~0xfffu; + + WriteUInt32 (page_rva); // PageRVA + WriteUInt32 (0x000c); // Block Size + + switch (module.Architecture) { + case TargetArchitecture.I386: + WriteUInt32 (0x3000 + reloc_rva - page_rva); + break; + default: + throw new NotSupportedException(); + } + + WriteBytes (new byte [file_alignment - reloc.VirtualSize]); + } + + public void WriteImage () + { + WriteDOSHeader (); + WritePEFileHeader (); + WriteOptionalHeaders (); + WriteSectionHeaders (); + WriteText (); + if (rsrc != null) + WriteRsrc (); + if (reloc != null) + WriteReloc (); + } + + TextMap BuildTextMap () + { + var map = metadata.text_map; + + map.AddMap (TextSegment.Code, metadata.code.length, !pe64 ? 4 : 16); + map.AddMap (TextSegment.Resources, metadata.resources.length, 8); + map.AddMap (TextSegment.Data, metadata.data.length, 4); + if (metadata.data.length > 0) + metadata.table_heap.FixupData (map.GetRVA (TextSegment.Data)); + map.AddMap (TextSegment.StrongNameSignature, GetStrongNameLength (), 4); + + map.AddMap (TextSegment.MetadataHeader, GetMetadataHeaderLength ()); + map.AddMap (TextSegment.TableHeap, metadata.table_heap.length, 4); + map.AddMap (TextSegment.StringHeap, metadata.string_heap.length, 4); + map.AddMap (TextSegment.UserStringHeap, metadata.user_string_heap.IsEmpty ? 0 : metadata.user_string_heap.length, 4); + map.AddMap (TextSegment.GuidHeap, 16); + map.AddMap (TextSegment.BlobHeap, metadata.blob_heap.IsEmpty ? 0 : metadata.blob_heap.length, 4); + + int debug_dir_len = 0; + if (!debug_data.IsNullOrEmpty ()) { + const int debug_dir_header_len = 28; + + debug_directory.AddressOfRawData = (int) map.GetNextRVA (TextSegment.BlobHeap) + debug_dir_header_len; + debug_dir_len = debug_data.Length + debug_dir_header_len; + } + + map.AddMap (TextSegment.DebugDirectory, debug_dir_len, 4); + + if (!has_reloc) { + var start = map.GetNextRVA (TextSegment.DebugDirectory); + map.AddMap (TextSegment.ImportDirectory, new Range (start, 0)); + map.AddMap (TextSegment.ImportHintNameTable, new Range (start, 0)); + map.AddMap (TextSegment.StartupStub, new Range (start, 0)); + return map; + } + + RVA import_dir_rva = map.GetNextRVA (TextSegment.DebugDirectory); + RVA import_hnt_rva = import_dir_rva + 48u; + import_hnt_rva = (import_hnt_rva + 15u) & ~15u; + uint import_dir_len = (import_hnt_rva - import_dir_rva) + 27u; + + RVA startup_stub_rva = import_dir_rva + import_dir_len; + startup_stub_rva = module.Architecture == TargetArchitecture.IA64 + ? (startup_stub_rva + 15u) & ~15u + : 2 + ((startup_stub_rva + 3u) & ~3u); + + map.AddMap (TextSegment.ImportDirectory, new Range (import_dir_rva, import_dir_len)); + map.AddMap (TextSegment.ImportHintNameTable, new Range (import_hnt_rva, 0)); + map.AddMap (TextSegment.StartupStub, new Range (startup_stub_rva, GetStartupStubLength ())); + + return map; + } + + uint GetStartupStubLength () + { + switch (module.Architecture) { + case TargetArchitecture.I386: + return 6; + default: + throw new NotSupportedException (); + } + } + + int GetMetadataHeaderLength () + { + return + // MetadataHeader + 40 + // #~ header + + 12 + // #Strings header + + 20 + // #US header + + (metadata.user_string_heap.IsEmpty ? 0 : 12) + // #GUID header + + 16 + // #Blob header + + (metadata.blob_heap.IsEmpty ? 0 : 16); + } + + int GetStrongNameLength () + { + if (module.Assembly == null) + return 0; + + var public_key = module.Assembly.Name.PublicKey; + if (public_key.IsNullOrEmpty ()) + return 0; + + // in fx 2.0 the key may be from 384 to 16384 bits + // so we must calculate the signature size based on + // the size of the public key (minus the 32 byte header) + int size = public_key.Length; + if (size > 32) + return size - 32; + + // note: size == 16 for the ECMA "key" which is replaced + // by the runtime with a 1024 bits key (128 bytes) + + return 128; // default strongname signature size + } + + public DataDirectory GetStrongNameSignatureDirectory () + { + return text_map.GetDataDirectory (TextSegment.StrongNameSignature); + } + + public uint GetHeaderSize () + { + return pe_header_size + (sections * section_header_size); + } + + void PatchWin32Resources (ByteBuffer resources) + { + PatchResourceDirectoryTable (resources); + } + + void PatchResourceDirectoryTable (ByteBuffer resources) + { + resources.Advance (12); + + var entries = resources.ReadUInt16 () + resources.ReadUInt16 (); + + for (int i = 0; i < entries; i++) + PatchResourceDirectoryEntry (resources); + } + + void PatchResourceDirectoryEntry (ByteBuffer resources) + { + resources.Advance (4); + var child = resources.ReadUInt32 (); + + var position = resources.position; + resources.position = (int) child & 0x7fffffff; + + if ((child & 0x80000000) != 0) + PatchResourceDirectoryTable (resources); + else + PatchResourceDataEntry (resources); + + resources.position = position; + } + + void PatchResourceDataEntry (ByteBuffer resources) + { + var old_rsrc = GetImageResourceSection (); + var rva = resources.ReadUInt32 (); + resources.position -= 4; + resources.WriteUInt32 (rva - old_rsrc.VirtualAddress + rsrc.VirtualAddress); + } + } +} + +#endif diff --git a/mcs/tools/mconfig/Mono.MonoConfig/consts.cs.in b/external/cecil-legacy/Mono.Cecil.PE/Section.cs similarity index 75% rename from mcs/tools/mconfig/Mono.MonoConfig/consts.cs.in rename to external/cecil-legacy/Mono.Cecil.PE/Section.cs index 8b7cbbe29f..6a4c7bab79 100644 --- a/mcs/tools/mconfig/Mono.MonoConfig/consts.cs.in +++ b/external/cecil-legacy/Mono.Cecil.PE/Section.cs @@ -1,10 +1,10 @@ // -// Authors: -// Marek Habersack (mhabersack@novell.com) +// Section.cs // -// (C) 2007 Novell, Inc +// Author: +// Jb Evain (jbevain@gmail.com) // - +// Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the @@ -13,10 +13,10 @@ // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: -// +// // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND @@ -25,19 +25,19 @@ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // + using System; -using System.IO; -namespace Mono.MonoConfig -{ - public class Constants - { - public static readonly string GlobalConfigPath; +using RVA = System.UInt32; - static Constants () - { - GlobalConfigPath = String.Format ("@MONO_SYSCONFDIR@{0}mono{0}mconfig{0}config.xml", - Path.DirectorySeparatorChar); - } +namespace Mono.Cecil.PE { + + sealed class Section { + public string Name; + public RVA VirtualAddress; + public uint VirtualSize; + public uint SizeOfRawData; + public uint PointerToRawData; + public byte [] Data; } } diff --git a/external/cecil-legacy/Mono.Cecil.PE/TextMap.cs b/external/cecil-legacy/Mono.Cecil.PE/TextMap.cs new file mode 100644 index 0000000000..047a4c1d47 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil.PE/TextMap.cs @@ -0,0 +1,129 @@ +// +// TextMap.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +#if !READ_ONLY + +using RVA = System.UInt32; + +namespace Mono.Cecil.PE { + + enum TextSegment { + ImportAddressTable, + CLIHeader, + Code, + Resources, + Data, + StrongNameSignature, + + // Metadata + MetadataHeader, + TableHeap, + StringHeap, + UserStringHeap, + GuidHeap, + BlobHeap, + // End Metadata + + DebugDirectory, + ImportDirectory, + ImportHintNameTable, + StartupStub, + } + + sealed class TextMap { + + readonly Range [] map = new Range [16 /*Enum.GetValues (typeof (TextSegment)).Length*/]; + + public void AddMap (TextSegment segment, int length) + { + map [(int) segment] = new Range (GetStart (segment), (uint) length); + } + + public void AddMap (TextSegment segment, int length, int align) + { + align--; + + AddMap (segment, (length + align) & ~align); + } + + public void AddMap (TextSegment segment, Range range) + { + map [(int) segment] = range; + } + + public Range GetRange (TextSegment segment) + { + return map [(int) segment]; + } + + public DataDirectory GetDataDirectory (TextSegment segment) + { + var range = map [(int) segment]; + + return new DataDirectory (range.Length == 0 ? 0 : range.Start, range.Length); + } + + public RVA GetRVA (TextSegment segment) + { + return map [(int) segment].Start; + } + + public RVA GetNextRVA (TextSegment segment) + { + var i = (int) segment; + return map [i].Start + map [i].Length; + } + + public int GetLength (TextSegment segment) + { + return (int) map [(int) segment].Length; + } + + RVA GetStart (TextSegment segment) + { + var index = (int) segment; + return index == 0 ? ImageWriter.text_rva : ComputeStart (index); + } + + RVA ComputeStart (int index) + { + index--; + return map [index].Start + map [index].Length; + } + + public uint GetLength () + { + var range = map [(int) TextSegment.StartupStub]; + return range.Start - ImageWriter.text_rva + range.Length; + } + } +} + +#endif diff --git a/external/cecil-legacy/Mono.Cecil.csproj b/external/cecil-legacy/Mono.Cecil.csproj new file mode 100644 index 0000000000..3a237c11b0 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil.csproj @@ -0,0 +1,264 @@ + + + + net_4_0_Debug + AnyCPU + 9.0.30729 + 2.0 + {D68133BD-1E63-496E-9EDE-4FBDBF77B486} + Library + Properties + Mono.Cecil + Mono.Cecil + 512 + true + mono.snk + + + true + full + false + bin\net_2_0_Debug\ + DEBUG;TRACE + prompt + 4 + v2.0 + + + pdbonly + true + bin\net_2_0_Release\ + TRACE + prompt + 4 + v2.0 + + + true + full + false + bin\net_3_5_Debug\ + DEBUG;TRACE;NET_3_5 + prompt + 4 + v3.5 + + + pdbonly + true + bin\net_3_5_Release\ + TRACE;NET_3_5 + prompt + 4 + v3.5 + + + true + full + false + bin\net_4_0_Debug\ + DEBUG;TRACE;NET_3_5;NET_4_0 + prompt + 4 + v4.0 + + + pdbonly + true + bin\net_4_0_Release\ + TRACE;NET_3_5;NET_4_0 + prompt + 4 + v4.0 + + + true + full + false + bin\silverlight_Debug\ + DEBUG;TRACE;NET_3_5;NET_4_0;SILVERLIGHT + prompt + 4 + Silverlight + v4.0 + + + pdbonly + true + bin\silverlight_Release\ + TRACE;NET_3_5;NET_4_0;SILVERLIGHT + prompt + 4 + Silverlight + v4.0 + + + true + full + false + bin\winphone_Debug\ + DEBUG;TRACE;NET_3_5;NET_4_0;SILVERLIGHT;CF + prompt + 4 + WindowsPhone + Silverlight + v4.0 + + + pdbonly + true + bin\winphone_Release\ + TRACE;NET_3_5;NET_4_0;SILVERLIGHT;CF + prompt + 4 + WindowsPhone + Silverlight + v4.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/external/cecil-legacy/Mono.Cecil.nunit b/external/cecil-legacy/Mono.Cecil.nunit new file mode 100755 index 0000000000..1cb0ebab1e --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil.nunit @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/external/cecil-legacy/Mono.Cecil.nuspec b/external/cecil-legacy/Mono.Cecil.nuspec new file mode 100644 index 0000000000..9901dfcf2c --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil.nuspec @@ -0,0 +1,23 @@ + + + + Mono.Cecil + 0.9.5.4 + Mono.Cecil + Jb Evain + Jb Evain + http://opensource.org/licenses/mit-license.php + false + http://github.com/jbevain/cecil/ + Cecil is a library written by Jb Evain to generate and inspect programs and libraries in the ECMA CIL format. + Cecil is a library written by Jb Evain to generate and inspect programs and libraries in the ECMA CIL format. It has full support for generics, and support some debugging symbol format. In simple English, with Cecil, you can load existing managed assemblies, browse all the contained types, modify them on the fly and save back to the disk the modified assembly. + en-US + assembly assemblies module modules il cil msil bytecode reflection injection cecil mono aop + + + + + + + + diff --git a/external/cecil-legacy/Mono.Cecil.sln b/external/cecil-legacy/Mono.Cecil.sln new file mode 100644 index 0000000000..7f2eda7f98 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil.sln @@ -0,0 +1,197 @@ +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{74E5ECE0-06B4-401C-AEBA-E8DD53E17943}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Symbols", "Symbols", "{929D5B3B-E29A-40CC-93D8-0FF43A6F9FA1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Cecil", "Mono.Cecil.csproj", "{D68133BD-1E63-496E-9EDE-4FBDBF77B486}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Cecil.Tests", "Test\Mono.Cecil.Tests.csproj", "{A47B1F49-A81A-43E8-BE6B-DD28AF2C4055}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "dbg", "dbg\dbg.csproj", "{89A775F3-64AB-485E-B958-60C25254B732}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Cecil.Mdb", "symbols\mdb\Mono.Cecil.Mdb.csproj", "{8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Cecil.Mdb.Tests", "symbols\mdb\Test\Mono.Cecil.Mdb.Tests.csproj", "{AC71DF9C-99FA-4A63-990A-66C8010355A6}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Cecil.Pdb", "symbols\pdb\Mono.Cecil.Pdb.csproj", "{63E6915C-7EA4-4D76-AB28-0D7191EEA626}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Cecil.Pdb.Tests", "symbols\pdb\Test\Mono.Cecil.Pdb.Tests.csproj", "{29300103-CB76-4A1D-B6FD-FFD91C1EC8AA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Cecil.Rocks.Tests", "rocks\Test\Mono.Cecil.Rocks.Tests.csproj", "{C6CFD7E1-B855-44DC-B4CE-9CD72984AF52}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Cecil.Rocks", "rocks\Mono.Cecil.Rocks.csproj", "{FBC6DD59-D09D-499C-B03C-99C1C78FF2AC}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + net_2_0_Debug|Any CPU = net_2_0_Debug|Any CPU + net_2_0_Release|Any CPU = net_2_0_Release|Any CPU + net_3_5_Debug|Any CPU = net_3_5_Debug|Any CPU + net_3_5_Release|Any CPU = net_3_5_Release|Any CPU + net_4_0_Debug|Any CPU = net_4_0_Debug|Any CPU + net_4_0_Release|Any CPU = net_4_0_Release|Any CPU + silverlight_Debug|Any CPU = silverlight_Debug|Any CPU + silverlight_Release|Any CPU = silverlight_Release|Any CPU + winphone_Debug|Any CPU = winphone_Debug|Any CPU + winphone_Release|Any CPU = winphone_Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.net_2_0_Debug|Any CPU.ActiveCfg = net_2_0_Debug|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.net_2_0_Debug|Any CPU.Build.0 = net_2_0_Debug|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.net_2_0_Release|Any CPU.ActiveCfg = net_2_0_Release|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.net_2_0_Release|Any CPU.Build.0 = net_2_0_Release|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.net_3_5_Debug|Any CPU.ActiveCfg = net_3_5_Debug|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.net_3_5_Debug|Any CPU.Build.0 = net_3_5_Debug|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.net_3_5_Release|Any CPU.ActiveCfg = net_3_5_Release|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.net_3_5_Release|Any CPU.Build.0 = net_3_5_Release|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.net_4_0_Debug|Any CPU.ActiveCfg = net_4_0_Debug|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.net_4_0_Debug|Any CPU.Build.0 = net_4_0_Debug|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.net_4_0_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.net_4_0_Release|Any CPU.Build.0 = net_4_0_Release|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.silverlight_Debug|Any CPU.ActiveCfg = silverlight_Debug|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.silverlight_Debug|Any CPU.Build.0 = silverlight_Debug|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.silverlight_Release|Any CPU.ActiveCfg = silverlight_Release|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.silverlight_Release|Any CPU.Build.0 = silverlight_Release|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.winphone_Debug|Any CPU.ActiveCfg = winphone_Debug|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.winphone_Debug|Any CPU.Build.0 = winphone_Debug|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.winphone_Release|Any CPU.ActiveCfg = winphone_Release|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.winphone_Release|Any CPU.Build.0 = winphone_Release|Any CPU + {A47B1F49-A81A-43E8-BE6B-DD28AF2C4055}.net_2_0_Debug|Any CPU.ActiveCfg = net_2_0_Debug|Any CPU + {A47B1F49-A81A-43E8-BE6B-DD28AF2C4055}.net_2_0_Debug|Any CPU.Build.0 = net_2_0_Debug|Any CPU + {A47B1F49-A81A-43E8-BE6B-DD28AF2C4055}.net_2_0_Release|Any CPU.ActiveCfg = net_2_0_Release|Any CPU + {A47B1F49-A81A-43E8-BE6B-DD28AF2C4055}.net_2_0_Release|Any CPU.Build.0 = net_2_0_Release|Any CPU + {A47B1F49-A81A-43E8-BE6B-DD28AF2C4055}.net_3_5_Debug|Any CPU.ActiveCfg = net_3_5_Debug|Any CPU + {A47B1F49-A81A-43E8-BE6B-DD28AF2C4055}.net_3_5_Debug|Any CPU.Build.0 = net_3_5_Debug|Any CPU + {A47B1F49-A81A-43E8-BE6B-DD28AF2C4055}.net_3_5_Release|Any CPU.ActiveCfg = net_3_5_Release|Any CPU + {A47B1F49-A81A-43E8-BE6B-DD28AF2C4055}.net_3_5_Release|Any CPU.Build.0 = net_3_5_Release|Any CPU + {A47B1F49-A81A-43E8-BE6B-DD28AF2C4055}.net_4_0_Debug|Any CPU.ActiveCfg = net_4_0_Debug|Any CPU + {A47B1F49-A81A-43E8-BE6B-DD28AF2C4055}.net_4_0_Debug|Any CPU.Build.0 = net_4_0_Debug|Any CPU + {A47B1F49-A81A-43E8-BE6B-DD28AF2C4055}.net_4_0_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {A47B1F49-A81A-43E8-BE6B-DD28AF2C4055}.net_4_0_Release|Any CPU.Build.0 = net_4_0_Release|Any CPU + {A47B1F49-A81A-43E8-BE6B-DD28AF2C4055}.silverlight_Debug|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {A47B1F49-A81A-43E8-BE6B-DD28AF2C4055}.silverlight_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {A47B1F49-A81A-43E8-BE6B-DD28AF2C4055}.winphone_Debug|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {A47B1F49-A81A-43E8-BE6B-DD28AF2C4055}.winphone_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {89A775F3-64AB-485E-B958-60C25254B732}.net_2_0_Debug|Any CPU.ActiveCfg = net_4_0_Debug|Any CPU + {89A775F3-64AB-485E-B958-60C25254B732}.net_2_0_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {89A775F3-64AB-485E-B958-60C25254B732}.net_3_5_Debug|Any CPU.ActiveCfg = net_3_5_Debug|Any CPU + {89A775F3-64AB-485E-B958-60C25254B732}.net_3_5_Debug|Any CPU.Build.0 = net_3_5_Debug|Any CPU + {89A775F3-64AB-485E-B958-60C25254B732}.net_3_5_Release|Any CPU.ActiveCfg = net_3_5_Release|Any CPU + {89A775F3-64AB-485E-B958-60C25254B732}.net_3_5_Release|Any CPU.Build.0 = net_3_5_Release|Any CPU + {89A775F3-64AB-485E-B958-60C25254B732}.net_4_0_Debug|Any CPU.ActiveCfg = net_4_0_Debug|Any CPU + {89A775F3-64AB-485E-B958-60C25254B732}.net_4_0_Debug|Any CPU.Build.0 = net_4_0_Debug|Any CPU + {89A775F3-64AB-485E-B958-60C25254B732}.net_4_0_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {89A775F3-64AB-485E-B958-60C25254B732}.net_4_0_Release|Any CPU.Build.0 = net_4_0_Release|Any CPU + {89A775F3-64AB-485E-B958-60C25254B732}.silverlight_Debug|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {89A775F3-64AB-485E-B958-60C25254B732}.silverlight_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {89A775F3-64AB-485E-B958-60C25254B732}.winphone_Debug|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {89A775F3-64AB-485E-B958-60C25254B732}.winphone_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.net_2_0_Debug|Any CPU.ActiveCfg = net_2_0_Debug|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.net_2_0_Debug|Any CPU.Build.0 = net_2_0_Debug|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.net_2_0_Release|Any CPU.ActiveCfg = net_2_0_Release|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.net_2_0_Release|Any CPU.Build.0 = net_2_0_Release|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.net_3_5_Debug|Any CPU.ActiveCfg = net_3_5_Debug|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.net_3_5_Debug|Any CPU.Build.0 = net_3_5_Debug|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.net_3_5_Release|Any CPU.ActiveCfg = net_3_5_Release|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.net_3_5_Release|Any CPU.Build.0 = net_3_5_Release|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.net_4_0_Debug|Any CPU.ActiveCfg = net_4_0_Debug|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.net_4_0_Debug|Any CPU.Build.0 = net_4_0_Debug|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.net_4_0_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.net_4_0_Release|Any CPU.Build.0 = net_4_0_Release|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.silverlight_Debug|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.silverlight_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.winphone_Debug|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.winphone_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {AC71DF9C-99FA-4A63-990A-66C8010355A6}.net_2_0_Debug|Any CPU.ActiveCfg = net_2_0_Debug|Any CPU + {AC71DF9C-99FA-4A63-990A-66C8010355A6}.net_2_0_Debug|Any CPU.Build.0 = net_2_0_Debug|Any CPU + {AC71DF9C-99FA-4A63-990A-66C8010355A6}.net_2_0_Release|Any CPU.ActiveCfg = net_2_0_Release|Any CPU + {AC71DF9C-99FA-4A63-990A-66C8010355A6}.net_2_0_Release|Any CPU.Build.0 = net_2_0_Release|Any CPU + {AC71DF9C-99FA-4A63-990A-66C8010355A6}.net_3_5_Debug|Any CPU.ActiveCfg = net_3_5_Debug|Any CPU + {AC71DF9C-99FA-4A63-990A-66C8010355A6}.net_3_5_Debug|Any CPU.Build.0 = net_3_5_Debug|Any CPU + {AC71DF9C-99FA-4A63-990A-66C8010355A6}.net_3_5_Release|Any CPU.ActiveCfg = net_3_5_Release|Any CPU + {AC71DF9C-99FA-4A63-990A-66C8010355A6}.net_3_5_Release|Any CPU.Build.0 = net_3_5_Release|Any CPU + {AC71DF9C-99FA-4A63-990A-66C8010355A6}.net_4_0_Debug|Any CPU.ActiveCfg = net_4_0_Debug|Any CPU + {AC71DF9C-99FA-4A63-990A-66C8010355A6}.net_4_0_Debug|Any CPU.Build.0 = net_4_0_Debug|Any CPU + {AC71DF9C-99FA-4A63-990A-66C8010355A6}.net_4_0_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {AC71DF9C-99FA-4A63-990A-66C8010355A6}.net_4_0_Release|Any CPU.Build.0 = net_4_0_Release|Any CPU + {AC71DF9C-99FA-4A63-990A-66C8010355A6}.silverlight_Debug|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {AC71DF9C-99FA-4A63-990A-66C8010355A6}.silverlight_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {AC71DF9C-99FA-4A63-990A-66C8010355A6}.winphone_Debug|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {AC71DF9C-99FA-4A63-990A-66C8010355A6}.winphone_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {63E6915C-7EA4-4D76-AB28-0D7191EEA626}.net_2_0_Debug|Any CPU.ActiveCfg = net_2_0_Debug|Any CPU + {63E6915C-7EA4-4D76-AB28-0D7191EEA626}.net_2_0_Debug|Any CPU.Build.0 = net_2_0_Debug|Any CPU + {63E6915C-7EA4-4D76-AB28-0D7191EEA626}.net_2_0_Release|Any CPU.ActiveCfg = net_2_0_Release|Any CPU + {63E6915C-7EA4-4D76-AB28-0D7191EEA626}.net_2_0_Release|Any CPU.Build.0 = net_2_0_Release|Any CPU + {63E6915C-7EA4-4D76-AB28-0D7191EEA626}.net_3_5_Debug|Any CPU.ActiveCfg = net_3_5_Debug|Any CPU + {63E6915C-7EA4-4D76-AB28-0D7191EEA626}.net_3_5_Debug|Any CPU.Build.0 = net_3_5_Debug|Any CPU + {63E6915C-7EA4-4D76-AB28-0D7191EEA626}.net_3_5_Release|Any CPU.ActiveCfg = net_3_5_Release|Any CPU + {63E6915C-7EA4-4D76-AB28-0D7191EEA626}.net_3_5_Release|Any CPU.Build.0 = net_3_5_Release|Any CPU + {63E6915C-7EA4-4D76-AB28-0D7191EEA626}.net_4_0_Debug|Any CPU.ActiveCfg = net_4_0_Debug|Any CPU + {63E6915C-7EA4-4D76-AB28-0D7191EEA626}.net_4_0_Debug|Any CPU.Build.0 = net_4_0_Debug|Any CPU + {63E6915C-7EA4-4D76-AB28-0D7191EEA626}.net_4_0_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {63E6915C-7EA4-4D76-AB28-0D7191EEA626}.net_4_0_Release|Any CPU.Build.0 = net_4_0_Release|Any CPU + {63E6915C-7EA4-4D76-AB28-0D7191EEA626}.silverlight_Debug|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {63E6915C-7EA4-4D76-AB28-0D7191EEA626}.silverlight_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {63E6915C-7EA4-4D76-AB28-0D7191EEA626}.winphone_Debug|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {63E6915C-7EA4-4D76-AB28-0D7191EEA626}.winphone_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {29300103-CB76-4A1D-B6FD-FFD91C1EC8AA}.net_2_0_Debug|Any CPU.ActiveCfg = net_2_0_Debug|Any CPU + {29300103-CB76-4A1D-B6FD-FFD91C1EC8AA}.net_2_0_Debug|Any CPU.Build.0 = net_2_0_Debug|Any CPU + {29300103-CB76-4A1D-B6FD-FFD91C1EC8AA}.net_2_0_Release|Any CPU.ActiveCfg = net_2_0_Release|Any CPU + {29300103-CB76-4A1D-B6FD-FFD91C1EC8AA}.net_2_0_Release|Any CPU.Build.0 = net_2_0_Release|Any CPU + {29300103-CB76-4A1D-B6FD-FFD91C1EC8AA}.net_3_5_Debug|Any CPU.ActiveCfg = net_3_5_Debug|Any CPU + {29300103-CB76-4A1D-B6FD-FFD91C1EC8AA}.net_3_5_Debug|Any CPU.Build.0 = net_3_5_Debug|Any CPU + {29300103-CB76-4A1D-B6FD-FFD91C1EC8AA}.net_3_5_Release|Any CPU.ActiveCfg = net_3_5_Release|Any CPU + {29300103-CB76-4A1D-B6FD-FFD91C1EC8AA}.net_3_5_Release|Any CPU.Build.0 = net_3_5_Release|Any CPU + {29300103-CB76-4A1D-B6FD-FFD91C1EC8AA}.net_4_0_Debug|Any CPU.ActiveCfg = net_4_0_Debug|Any CPU + {29300103-CB76-4A1D-B6FD-FFD91C1EC8AA}.net_4_0_Debug|Any CPU.Build.0 = net_4_0_Debug|Any CPU + {29300103-CB76-4A1D-B6FD-FFD91C1EC8AA}.net_4_0_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {29300103-CB76-4A1D-B6FD-FFD91C1EC8AA}.net_4_0_Release|Any CPU.Build.0 = net_4_0_Release|Any CPU + {29300103-CB76-4A1D-B6FD-FFD91C1EC8AA}.silverlight_Debug|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {29300103-CB76-4A1D-B6FD-FFD91C1EC8AA}.silverlight_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {29300103-CB76-4A1D-B6FD-FFD91C1EC8AA}.winphone_Debug|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {29300103-CB76-4A1D-B6FD-FFD91C1EC8AA}.winphone_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {C6CFD7E1-B855-44DC-B4CE-9CD72984AF52}.net_2_0_Debug|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {C6CFD7E1-B855-44DC-B4CE-9CD72984AF52}.net_2_0_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {C6CFD7E1-B855-44DC-B4CE-9CD72984AF52}.net_3_5_Debug|Any CPU.ActiveCfg = net_3_5_Debug|Any CPU + {C6CFD7E1-B855-44DC-B4CE-9CD72984AF52}.net_3_5_Debug|Any CPU.Build.0 = net_3_5_Debug|Any CPU + {C6CFD7E1-B855-44DC-B4CE-9CD72984AF52}.net_3_5_Release|Any CPU.ActiveCfg = net_3_5_Release|Any CPU + {C6CFD7E1-B855-44DC-B4CE-9CD72984AF52}.net_3_5_Release|Any CPU.Build.0 = net_3_5_Release|Any CPU + {C6CFD7E1-B855-44DC-B4CE-9CD72984AF52}.net_4_0_Debug|Any CPU.ActiveCfg = net_4_0_Debug|Any CPU + {C6CFD7E1-B855-44DC-B4CE-9CD72984AF52}.net_4_0_Debug|Any CPU.Build.0 = net_4_0_Debug|Any CPU + {C6CFD7E1-B855-44DC-B4CE-9CD72984AF52}.net_4_0_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {C6CFD7E1-B855-44DC-B4CE-9CD72984AF52}.net_4_0_Release|Any CPU.Build.0 = net_4_0_Release|Any CPU + {C6CFD7E1-B855-44DC-B4CE-9CD72984AF52}.silverlight_Debug|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {C6CFD7E1-B855-44DC-B4CE-9CD72984AF52}.silverlight_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {C6CFD7E1-B855-44DC-B4CE-9CD72984AF52}.winphone_Debug|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {C6CFD7E1-B855-44DC-B4CE-9CD72984AF52}.winphone_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {FBC6DD59-D09D-499C-B03C-99C1C78FF2AC}.net_2_0_Debug|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {FBC6DD59-D09D-499C-B03C-99C1C78FF2AC}.net_2_0_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {FBC6DD59-D09D-499C-B03C-99C1C78FF2AC}.net_3_5_Debug|Any CPU.ActiveCfg = net_3_5_Debug|Any CPU + {FBC6DD59-D09D-499C-B03C-99C1C78FF2AC}.net_3_5_Debug|Any CPU.Build.0 = net_3_5_Debug|Any CPU + {FBC6DD59-D09D-499C-B03C-99C1C78FF2AC}.net_3_5_Release|Any CPU.ActiveCfg = net_3_5_Release|Any CPU + {FBC6DD59-D09D-499C-B03C-99C1C78FF2AC}.net_3_5_Release|Any CPU.Build.0 = net_3_5_Release|Any CPU + {FBC6DD59-D09D-499C-B03C-99C1C78FF2AC}.net_4_0_Debug|Any CPU.ActiveCfg = net_4_0_Debug|Any CPU + {FBC6DD59-D09D-499C-B03C-99C1C78FF2AC}.net_4_0_Debug|Any CPU.Build.0 = net_4_0_Debug|Any CPU + {FBC6DD59-D09D-499C-B03C-99C1C78FF2AC}.net_4_0_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {FBC6DD59-D09D-499C-B03C-99C1C78FF2AC}.net_4_0_Release|Any CPU.Build.0 = net_4_0_Release|Any CPU + {FBC6DD59-D09D-499C-B03C-99C1C78FF2AC}.silverlight_Debug|Any CPU.ActiveCfg = silverlight_Debug|Any CPU + {FBC6DD59-D09D-499C-B03C-99C1C78FF2AC}.silverlight_Debug|Any CPU.Build.0 = silverlight_Debug|Any CPU + {FBC6DD59-D09D-499C-B03C-99C1C78FF2AC}.silverlight_Release|Any CPU.ActiveCfg = silverlight_Release|Any CPU + {FBC6DD59-D09D-499C-B03C-99C1C78FF2AC}.silverlight_Release|Any CPU.Build.0 = silverlight_Release|Any CPU + {FBC6DD59-D09D-499C-B03C-99C1C78FF2AC}.winphone_Debug|Any CPU.ActiveCfg = winphone_Debug|Any CPU + {FBC6DD59-D09D-499C-B03C-99C1C78FF2AC}.winphone_Debug|Any CPU.Build.0 = winphone_Debug|Any CPU + {FBC6DD59-D09D-499C-B03C-99C1C78FF2AC}.winphone_Release|Any CPU.ActiveCfg = winphone_Release|Any CPU + {FBC6DD59-D09D-499C-B03C-99C1C78FF2AC}.winphone_Release|Any CPU.Build.0 = winphone_Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {A47B1F49-A81A-43E8-BE6B-DD28AF2C4055} = {74E5ECE0-06B4-401C-AEBA-E8DD53E17943} + {AC71DF9C-99FA-4A63-990A-66C8010355A6} = {74E5ECE0-06B4-401C-AEBA-E8DD53E17943} + {29300103-CB76-4A1D-B6FD-FFD91C1EC8AA} = {74E5ECE0-06B4-401C-AEBA-E8DD53E17943} + {C6CFD7E1-B855-44DC-B4CE-9CD72984AF52} = {74E5ECE0-06B4-401C-AEBA-E8DD53E17943} + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD} = {929D5B3B-E29A-40CC-93D8-0FF43A6F9FA1} + {63E6915C-7EA4-4D76-AB28-0D7191EEA626} = {929D5B3B-E29A-40CC-93D8-0FF43A6F9FA1} + EndGlobalSection +EndGlobal diff --git a/external/cecil-legacy/Mono.Cecil.sln.DotSettings b/external/cecil-legacy/Mono.Cecil.sln.DotSettings new file mode 100755 index 0000000000..6d06ad79ae --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil.sln.DotSettings @@ -0,0 +1,35 @@ + + DO_NOT_SHOW + True + <Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /> + END_OF_LINE + END_OF_LINE + END_OF_LINE + END_OF_LINE + END_OF_LINE + 1 + 1 + False + False + False + False + True + True + True + True + True + True + False + True + True + False + False + False + <Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /> + True + C:\sources\cecil\Mono.Cecil.sln.DotSettings + True + 1 + None \ No newline at end of file diff --git a/external/cecil-legacy/Mono.Cecil/ArrayType.cs b/external/cecil-legacy/Mono.Cecil/ArrayType.cs new file mode 100644 index 0000000000..55c59d8728 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/ArrayType.cs @@ -0,0 +1,159 @@ +// +// ArrayType.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Text; +using Mono.Collections.Generic; +using MD = Mono.Cecil.Metadata; + +namespace Mono.Cecil { + + public struct ArrayDimension { + + int? lower_bound; + int? upper_bound; + + public int? LowerBound { + get { return lower_bound; } + set { lower_bound = value; } + } + + public int? UpperBound { + get { return upper_bound; } + set { upper_bound = value; } + } + + public bool IsSized { + get { return lower_bound.HasValue || upper_bound.HasValue; } + } + + public ArrayDimension (int? lowerBound, int? upperBound) + { + this.lower_bound = lowerBound; + this.upper_bound = upperBound; + } + + public override string ToString () + { + return !IsSized + ? string.Empty + : lower_bound + "..." + upper_bound; + } + } + + public sealed class ArrayType : TypeSpecification { + + Collection dimensions; + + public Collection Dimensions { + get { + if (dimensions != null) + return dimensions; + + dimensions = new Collection (); + dimensions.Add (new ArrayDimension ()); + return dimensions; + } + } + + public int Rank { + get { return dimensions == null ? 1 : dimensions.Count; } + } + + public bool IsVector { + get { + if (dimensions == null) + return true; + + if (dimensions.Count > 1) + return false; + + var dimension = dimensions [0]; + + return !dimension.IsSized; + } + } + + public override bool IsValueType { + get { return false; } + set { throw new InvalidOperationException (); } + } + + public override string Name { + get { return base.Name + Suffix; } + } + + public override string FullName { + get { return base.FullName + Suffix; } + } + + string Suffix { + get { + if (IsVector) + return "[]"; + + var suffix = new StringBuilder (); + suffix.Append ("["); + for (int i = 0; i < dimensions.Count; i++) { + if (i > 0) + suffix.Append (","); + + suffix.Append (dimensions [i].ToString ()); + } + suffix.Append ("]"); + + return suffix.ToString (); + } + } + + public override bool IsArray { + get { return true; } + } + + public ArrayType (TypeReference type) + : base (type) + { + Mixin.CheckType (type); + this.etype = MD.ElementType.Array; + } + + public ArrayType (TypeReference type, int rank) + : this (type) + { + Mixin.CheckType (type); + + if (rank == 1) + return; + + dimensions = new Collection (rank); + for (int i = 0; i < rank; i++) + dimensions.Add (new ArrayDimension ()); + this.etype = MD.ElementType.Array; + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil/AssemblyDefinition.cs b/external/cecil-legacy/Mono.Cecil/AssemblyDefinition.cs new file mode 100644 index 0000000000..f1b5d25e4e --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/AssemblyDefinition.cs @@ -0,0 +1,189 @@ +// +// AssemblyDefinition.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.IO; + +using Mono.Collections.Generic; + +namespace Mono.Cecil { + + public sealed class AssemblyDefinition : ICustomAttributeProvider, ISecurityDeclarationProvider { + + AssemblyNameDefinition name; + + internal ModuleDefinition main_module; + Collection modules; + Collection custom_attributes; + Collection security_declarations; + + public AssemblyNameDefinition Name { + get { return name; } + set { name = value; } + } + + public string FullName { + get { return name != null ? name.FullName : string.Empty; } + } + + public MetadataToken MetadataToken { + get { return new MetadataToken (TokenType.Assembly, 1); } + set { } + } + + public Collection Modules { + get { + if (modules != null) + return modules; + + if (main_module.HasImage) + return modules = main_module.Read (this, (_, reader) => reader.ReadModules ()); + + return modules = new Collection (1) { main_module }; + } + } + + public ModuleDefinition MainModule { + get { return main_module; } + } + + public MethodDefinition EntryPoint { + get { return main_module.EntryPoint; } + set { main_module.EntryPoint = value; } + } + + public bool HasCustomAttributes { + get { + if (custom_attributes != null) + return custom_attributes.Count > 0; + + return this.GetHasCustomAttributes (main_module); + } + } + + public Collection CustomAttributes { + get { return custom_attributes ?? (custom_attributes = this.GetCustomAttributes (main_module)); } + } + + public bool HasSecurityDeclarations { + get { + if (security_declarations != null) + return security_declarations.Count > 0; + + return this.GetHasSecurityDeclarations (main_module); + } + } + + public Collection SecurityDeclarations { + get { return security_declarations ?? (security_declarations = this.GetSecurityDeclarations (main_module)); } + } + + internal AssemblyDefinition () + { + } + +#if !READ_ONLY + public static AssemblyDefinition CreateAssembly (AssemblyNameDefinition assemblyName, string moduleName, ModuleKind kind) + { + return CreateAssembly (assemblyName, moduleName, new ModuleParameters { Kind = kind }); + } + + public static AssemblyDefinition CreateAssembly (AssemblyNameDefinition assemblyName, string moduleName, ModuleParameters parameters) + { + if (assemblyName == null) + throw new ArgumentNullException ("assemblyName"); + if (moduleName == null) + throw new ArgumentNullException ("moduleName"); + Mixin.CheckParameters (parameters); + if (parameters.Kind == ModuleKind.NetModule) + throw new ArgumentException ("kind"); + + var assembly = ModuleDefinition.CreateModule (moduleName, parameters).Assembly; + assembly.Name = assemblyName; + + return assembly; + } +#endif + + public static AssemblyDefinition ReadAssembly (string fileName) + { + return ReadAssembly (ModuleDefinition.ReadModule (fileName)); + } + + public static AssemblyDefinition ReadAssembly (string fileName, ReaderParameters parameters) + { + return ReadAssembly (ModuleDefinition.ReadModule (fileName, parameters)); + } + + public static AssemblyDefinition ReadAssembly (Stream stream) + { + return ReadAssembly (ModuleDefinition.ReadModule (stream)); + } + + public static AssemblyDefinition ReadAssembly (Stream stream, ReaderParameters parameters) + { + return ReadAssembly (ModuleDefinition.ReadModule (stream, parameters)); + } + + static AssemblyDefinition ReadAssembly (ModuleDefinition module) + { + var assembly = module.Assembly; + if (assembly == null) + throw new ArgumentException (); + + return assembly; + } + +#if !READ_ONLY + public void Write (string fileName) + { + Write (fileName, new WriterParameters ()); + } + + public void Write (Stream stream) + { + Write (stream, new WriterParameters ()); + } + + public void Write (string fileName, WriterParameters parameters) + { + main_module.Write (fileName, parameters); + } + + public void Write (Stream stream, WriterParameters parameters) + { + main_module.Write (stream, parameters); + } +#endif + + public override string ToString () + { + return this.FullName; + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil/AssemblyFlags.cs b/external/cecil-legacy/Mono.Cecil/AssemblyFlags.cs new file mode 100644 index 0000000000..72a0eb06c2 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/AssemblyFlags.cs @@ -0,0 +1,42 @@ +// +// AssemblyFlags.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +namespace Mono.Cecil { + + [Flags] + public enum AssemblyAttributes : uint { + PublicKey = 0x0001, + SideBySideCompatible = 0x0000, + Retargetable = 0x0100, + WindowsRuntime = 0x0200, + DisableJITCompileOptimizer = 0x4000, + EnableJITCompileTracking = 0x8000, + } +} diff --git a/mcs/class/corlib/System/GCNotificationStatus.cs b/external/cecil-legacy/Mono.Cecil/AssemblyHashAlgorithm.cs similarity index 75% rename from mcs/class/corlib/System/GCNotificationStatus.cs rename to external/cecil-legacy/Mono.Cecil/AssemblyHashAlgorithm.cs index d48dab5b19..79a5699db6 100644 --- a/mcs/class/corlib/System/GCNotificationStatus.cs +++ b/external/cecil-legacy/Mono.Cecil/AssemblyHashAlgorithm.cs @@ -1,10 +1,10 @@ // -// System.GCNotificationStatus.cs +// AssemblyHashAlgorithm.cs // -// Authors: -// Gonzalo Paniagua (gonzalo@ximian.com) +// Author: +// Jb Evain (jbevain@gmail.com) // -// Copyright (C) 2009 Novell, Inc (http://www.novell.com) +// Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the @@ -13,10 +13,10 @@ // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: -// +// // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND @@ -26,15 +26,11 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -using System.Collections.Generic; -using System.Runtime.ConstrainedExecution; +namespace Mono.Cecil { -namespace System { - public enum GCNotificationStatus { - Succeeded, - Failed, - Canceled, - Timeout, - NotApplicable + public enum AssemblyHashAlgorithm : uint { + None = 0x0000, + Reserved = 0x8003, // MD5 + SHA1 = 0x8004 } } diff --git a/external/cecil-legacy/Mono.Cecil/AssemblyInfo.cs b/external/cecil-legacy/Mono.Cecil/AssemblyInfo.cs new file mode 100644 index 0000000000..8a9f8097e1 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/AssemblyInfo.cs @@ -0,0 +1,49 @@ +// +// AssemblyInfo.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle ("Mono.Cecil")] +[assembly: AssemblyProduct ("Mono.Cecil")] +[assembly: AssemblyCopyright ("Copyright © 2008 - 2011 Jb Evain")] + +[assembly: ComVisible (false)] + +[assembly: Guid ("fd225bb4-fa53-44b2-a6db-85f5e48dcb54")] + +[assembly: AssemblyVersion ("0.9.5.0")] +#if !CF +[assembly: AssemblyFileVersion ("0.9.5.0")] +#endif + +[assembly: InternalsVisibleTo ("Mono.Cecil.Pdb, PublicKey=002400000480000094000000060200000024000052534131000400000100010079159977d2d03a8e6bea7a2e74e8d1afcc93e8851974952bb480a12c9134474d04062447c37e0e68c080536fcf3c3fbe2ff9c979ce998475e506e8ce82dd5b0f350dc10e93bf2eeecf874b24770c5081dbea7447fddafa277b22de47d6ffea449674a4f9fccf84d15069089380284dbdd35f46cdff12a1bd78e4ef0065d016df")] +[assembly: InternalsVisibleTo ("Mono.Cecil.Mdb, PublicKey=002400000480000094000000060200000024000052534131000400000100010079159977d2d03a8e6bea7a2e74e8d1afcc93e8851974952bb480a12c9134474d04062447c37e0e68c080536fcf3c3fbe2ff9c979ce998475e506e8ce82dd5b0f350dc10e93bf2eeecf874b24770c5081dbea7447fddafa277b22de47d6ffea449674a4f9fccf84d15069089380284dbdd35f46cdff12a1bd78e4ef0065d016df")] +[assembly: InternalsVisibleTo ("Mono.Cecil.Rocks, PublicKey=002400000480000094000000060200000024000052534131000400000100010079159977d2d03a8e6bea7a2e74e8d1afcc93e8851974952bb480a12c9134474d04062447c37e0e68c080536fcf3c3fbe2ff9c979ce998475e506e8ce82dd5b0f350dc10e93bf2eeecf874b24770c5081dbea7447fddafa277b22de47d6ffea449674a4f9fccf84d15069089380284dbdd35f46cdff12a1bd78e4ef0065d016df")] +[assembly: InternalsVisibleTo ("Mono.Cecil.Tests, PublicKey=002400000480000094000000060200000024000052534131000400000100010079159977d2d03a8e6bea7a2e74e8d1afcc93e8851974952bb480a12c9134474d04062447c37e0e68c080536fcf3c3fbe2ff9c979ce998475e506e8ce82dd5b0f350dc10e93bf2eeecf874b24770c5081dbea7447fddafa277b22de47d6ffea449674a4f9fccf84d15069089380284dbdd35f46cdff12a1bd78e4ef0065d016df")] diff --git a/mcs/class/System/System.Security.Authentication.ExtendedProtection/ServiceNameCollection.cs b/external/cecil-legacy/Mono.Cecil/AssemblyLinkedResource.cs similarity index 60% rename from mcs/class/System/System.Security.Authentication.ExtendedProtection/ServiceNameCollection.cs rename to external/cecil-legacy/Mono.Cecil/AssemblyLinkedResource.cs index 3fa9b3f4a9..4d8bac0bbb 100644 --- a/mcs/class/System/System.Security.Authentication.ExtendedProtection/ServiceNameCollection.cs +++ b/external/cecil-legacy/Mono.Cecil/AssemblyLinkedResource.cs @@ -1,12 +1,10 @@ // -// ServiceNameCollection.cs +// AssemblyLinkedResource.cs // -// Authors: -// Atsushi Enomoto +// Author: +// Jb Evain (jbevain@gmail.com) // - -// -// Copyright (C) 2010 Novell, Inc (http://novell.com) +// Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the @@ -15,10 +13,10 @@ // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: -// +// // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND @@ -27,34 +25,33 @@ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // + using System; -using System.Collections; -namespace System.Security.Authentication.ExtendedProtection -{ - [MonoTODO] - [Serializable] - public class ServiceNameCollection : ReadOnlyCollectionBase - { - public ServiceNameCollection (ICollection items) - { - throw new NotImplementedException (); +namespace Mono.Cecil { + + public sealed class AssemblyLinkedResource : Resource { + + AssemblyNameReference reference; + + public AssemblyNameReference Assembly { + get { return reference; } + set { reference = value; } } - public ServiceNameCollection Merge (IEnumerable serviceNames) - { - throw new NotImplementedException (); - } - - public ServiceNameCollection Merge (string serviceName) - { - throw new NotImplementedException (); + public override ResourceType ResourceType { + get { return ResourceType.AssemblyLinked; } } - public bool Contains (string searchServiceName) + public AssemblyLinkedResource (string name, ManifestResourceAttributes flags) + : base (name, flags) { - throw new NotImplementedException (); + } + + public AssemblyLinkedResource (string name, ManifestResourceAttributes flags, AssemblyNameReference reference) + : base (name, flags) + { + this.reference = reference; } } } - diff --git a/mcs/class/System/System.Diagnostics.CodeAnalysis/ExcludeFromCodeCoverageAttribute.cs b/external/cecil-legacy/Mono.Cecil/AssemblyNameDefinition.cs similarity index 67% rename from mcs/class/System/System.Diagnostics.CodeAnalysis/ExcludeFromCodeCoverageAttribute.cs rename to external/cecil-legacy/Mono.Cecil/AssemblyNameDefinition.cs index 38371caf01..dc6b9057f9 100644 --- a/mcs/class/System/System.Diagnostics.CodeAnalysis/ExcludeFromCodeCoverageAttribute.cs +++ b/external/cecil-legacy/Mono.Cecil/AssemblyNameDefinition.cs @@ -1,10 +1,10 @@ // -// ExcludeFromCodeCoverageAttribute.cs +// AssemblyNameDefinition.cs // -// Authors: -// Jb Evain +// Author: +// Jb Evain (jbevain@gmail.com) // -// Copyright (C) 2010 Novell, Inc (http://www.novell.com) +// Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the @@ -28,22 +28,23 @@ using System; +namespace Mono.Cecil { -namespace System.Diagnostics.CodeAnalysis { + public sealed class AssemblyNameDefinition : AssemblyNameReference { - [AttributeUsage (AttributeTargets.Class - | AttributeTargets.Struct - | AttributeTargets.Constructor - | AttributeTargets.Method - | AttributeTargets.Property - | AttributeTargets.Event, - AllowMultiple = false, - Inherited = false)] - public sealed class ExcludeFromCodeCoverageAttribute : Attribute - { - public ExcludeFromCodeCoverageAttribute () + public override byte [] Hash { + get { return Empty.Array; } + } + + internal AssemblyNameDefinition () { + this.token = new MetadataToken (TokenType.Assembly, 1); + } + + public AssemblyNameDefinition (string name, Version version) + : base (name, version) + { + this.token = new MetadataToken (TokenType.Assembly, 1); } } } - diff --git a/external/cecil-legacy/Mono.Cecil/AssemblyNameReference.cs b/external/cecil-legacy/Mono.Cecil/AssemblyNameReference.cs new file mode 100644 index 0000000000..4f58fe2d15 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/AssemblyNameReference.cs @@ -0,0 +1,269 @@ +// +// AssemblyNameReference.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Globalization; +using System.Security.Cryptography; +using System.Text; + +namespace Mono.Cecil { + + public class AssemblyNameReference : IMetadataScope { + + string name; + string culture; + Version version; + uint attributes; + byte [] public_key; + byte [] public_key_token; + AssemblyHashAlgorithm hash_algorithm; + byte [] hash; + + internal MetadataToken token; + + string full_name; + + public string Name { + get { return name; } + set { + name = value; + full_name = null; + } + } + + public string Culture { + get { return culture; } + set { + culture = value; + full_name = null; + } + } + + public Version Version { + get { return version; } + set { + version = value; + full_name = null; + } + } + + public AssemblyAttributes Attributes { + get { return (AssemblyAttributes) attributes; } + set { attributes = (uint) value; } + } + + public bool HasPublicKey { + get { return attributes.GetAttributes ((uint) AssemblyAttributes.PublicKey); } + set { attributes = attributes.SetAttributes ((uint) AssemblyAttributes.PublicKey, value); } + } + + public bool IsSideBySideCompatible { + get { return attributes.GetAttributes ((uint) AssemblyAttributes.SideBySideCompatible); } + set { attributes = attributes.SetAttributes ((uint) AssemblyAttributes.SideBySideCompatible, value); } + } + + public bool IsRetargetable { + get { return attributes.GetAttributes ((uint) AssemblyAttributes.Retargetable); } + set { attributes = attributes.SetAttributes ((uint) AssemblyAttributes.Retargetable, value); } + } + + public bool IsWindowsRuntime { + get { return attributes.GetAttributes ((uint) AssemblyAttributes.WindowsRuntime); } + set { attributes = attributes.SetAttributes ((uint) AssemblyAttributes.WindowsRuntime, value); } + } + + public byte [] PublicKey { + get { return public_key ?? Empty.Array; } + set { + public_key = value; + HasPublicKey = !public_key.IsNullOrEmpty (); + public_key_token = Empty.Array; + full_name = null; + } + } + + public byte [] PublicKeyToken { + get { + if (public_key_token.IsNullOrEmpty () && !public_key.IsNullOrEmpty ()) { + var hash = HashPublicKey (); + // we need the last 8 bytes in reverse order + public_key_token = new byte [8]; + Array.Copy (hash, (hash.Length - 8), public_key_token, 0, 8); + Array.Reverse (public_key_token, 0, 8); + } + return public_key_token ?? Empty.Array; + } + set { + public_key_token = value; + full_name = null; + } + } + + byte [] HashPublicKey () + { + HashAlgorithm algorithm; + + switch (hash_algorithm) { + case AssemblyHashAlgorithm.Reserved: +#if SILVERLIGHT + throw new NotSupportedException (); +#else + algorithm = MD5.Create (); + break; +#endif + default: + // None default to SHA1 +#if SILVERLIGHT + algorithm = new SHA1Managed (); + break; +#else + algorithm = SHA1.Create (); + break; +#endif + } + + using (algorithm) + return algorithm.ComputeHash (public_key); + } + + public virtual MetadataScopeType MetadataScopeType { + get { return MetadataScopeType.AssemblyNameReference; } + } + + public string FullName { + get { + if (full_name != null) + return full_name; + + const string sep = ", "; + + var builder = new StringBuilder (); + builder.Append (name); + if (version != null) { + builder.Append (sep); + builder.Append ("Version="); + builder.Append (version.ToString ()); + } + builder.Append (sep); + builder.Append ("Culture="); + builder.Append (string.IsNullOrEmpty (culture) ? "neutral" : culture); + builder.Append (sep); + builder.Append ("PublicKeyToken="); + + var pk_token = PublicKeyToken; + if (!pk_token.IsNullOrEmpty () && pk_token.Length > 0) { + for (int i = 0 ; i < pk_token.Length ; i++) { + builder.Append (pk_token [i].ToString ("x2")); + } + } else + builder.Append ("null"); + + return full_name = builder.ToString (); + } + } + + public static AssemblyNameReference Parse (string fullName) + { + if (fullName == null) + throw new ArgumentNullException ("fullName"); + if (fullName.Length == 0) + throw new ArgumentException ("Name can not be empty"); + + var name = new AssemblyNameReference (); + var tokens = fullName.Split (','); + for (int i = 0; i < tokens.Length; i++) { + var token = tokens [i].Trim (); + + if (i == 0) { + name.Name = token; + continue; + } + + var parts = token.Split ('='); + if (parts.Length != 2) + throw new ArgumentException ("Malformed name"); + + switch (parts [0].ToLowerInvariant ()) { + case "version": + name.Version = new Version (parts [1]); + break; + case "culture": + name.Culture = parts [1]; + break; + case "publickeytoken": + var pk_token = parts [1]; + if (pk_token == "null") + break; + + name.PublicKeyToken = new byte [pk_token.Length / 2]; + for (int j = 0; j < name.PublicKeyToken.Length; j++) + name.PublicKeyToken [j] = Byte.Parse (pk_token.Substring (j * 2, 2), NumberStyles.HexNumber); + + break; + } + } + + return name; + } + + public AssemblyHashAlgorithm HashAlgorithm { + get { return hash_algorithm; } + set { hash_algorithm = value; } + } + + public virtual byte [] Hash { + get { return hash; } + set { hash = value; } + } + + public MetadataToken MetadataToken { + get { return token; } + set { token = value; } + } + + internal AssemblyNameReference () + { + } + + public AssemblyNameReference (string name, Version version) + { + if (name == null) + throw new ArgumentNullException ("name"); + + this.name = name; + this.version = version; + this.hash_algorithm = AssemblyHashAlgorithm.None; + this.token = new MetadataToken (TokenType.AssemblyRef); + } + + public override string ToString () + { + return this.FullName; + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil/AssemblyReader.cs b/external/cecil-legacy/Mono.Cecil/AssemblyReader.cs new file mode 100644 index 0000000000..569475b573 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/AssemblyReader.cs @@ -0,0 +1,3233 @@ +// +// AssemblyReader.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + +using Mono.Collections.Generic; +using Mono.Cecil.Cil; +using Mono.Cecil.Metadata; +using Mono.Cecil.PE; + +using RVA = System.UInt32; + +namespace Mono.Cecil { + + abstract class ModuleReader { + + readonly protected Image image; + readonly protected ModuleDefinition module; + + protected ModuleReader (Image image, ReadingMode mode) + { + this.image = image; + this.module = new ModuleDefinition (image); + this.module.ReadingMode = mode; + } + + protected abstract void ReadModule (); + + protected void ReadModuleManifest (MetadataReader reader) + { + reader.Populate (module); + + ReadAssembly (reader); + } + + void ReadAssembly (MetadataReader reader) + { + var name = reader.ReadAssemblyNameDefinition (); + if (name == null) { + module.kind = ModuleKind.NetModule; + return; + } + + var assembly = new AssemblyDefinition (); + assembly.Name = name; + + module.assembly = assembly; + assembly.main_module = module; + } + + public static ModuleDefinition CreateModuleFrom (Image image, ReaderParameters parameters) + { + var module = ReadModule (image, parameters); + + ReadSymbols (module, parameters); + + if (parameters.AssemblyResolver != null) + module.assembly_resolver = parameters.AssemblyResolver; + + if (parameters.MetadataResolver != null) + module.metadata_resolver = parameters.MetadataResolver; + + return module; + } + + static void ReadSymbols (ModuleDefinition module, ReaderParameters parameters) + { + var symbol_reader_provider = parameters.SymbolReaderProvider; + + if (symbol_reader_provider == null && parameters.ReadSymbols) + symbol_reader_provider = SymbolProvider.GetPlatformReaderProvider (); + + if (symbol_reader_provider != null) { + module.SymbolReaderProvider = symbol_reader_provider; + + var reader = parameters.SymbolStream != null + ? symbol_reader_provider.GetSymbolReader (module, parameters.SymbolStream) + : symbol_reader_provider.GetSymbolReader (module, module.FullyQualifiedName); + + module.ReadSymbols (reader); + } + } + + static ModuleDefinition ReadModule (Image image, ReaderParameters parameters) + { + var reader = CreateModuleReader (image, parameters.ReadingMode); + reader.ReadModule (); + return reader.module; + } + + static ModuleReader CreateModuleReader (Image image, ReadingMode mode) + { + switch (mode) { + case ReadingMode.Immediate: + return new ImmediateModuleReader (image); + case ReadingMode.Deferred: + return new DeferredModuleReader (image); + default: + throw new ArgumentException (); + } + } + } + + sealed class ImmediateModuleReader : ModuleReader { + + public ImmediateModuleReader (Image image) + : base (image, ReadingMode.Immediate) + { + } + + protected override void ReadModule () + { + this.module.Read (this.module, (module, reader) => { + ReadModuleManifest (reader); + ReadModule (module); + return module; + }); + } + + public static void ReadModule (ModuleDefinition module) + { + if (module.HasAssemblyReferences) + Read (module.AssemblyReferences); + if (module.HasResources) + Read (module.Resources); + if (module.HasModuleReferences) + Read (module.ModuleReferences); + if (module.HasTypes) + ReadTypes (module.Types); + if (module.HasExportedTypes) + Read (module.ExportedTypes); + if (module.HasCustomAttributes) + Read (module.CustomAttributes); + + var assembly = module.Assembly; + if (assembly == null) + return; + + if (assembly.HasCustomAttributes) + Read (assembly.CustomAttributes); + if (assembly.HasSecurityDeclarations) + Read (assembly.SecurityDeclarations); + } + + static void ReadTypes (Collection types) + { + for (int i = 0; i < types.Count; i++) + ReadType (types [i]); + } + + static void ReadType (TypeDefinition type) + { + ReadGenericParameters (type); + + if (type.HasInterfaces) + Read (type.Interfaces); + + if (type.HasNestedTypes) + ReadTypes (type.NestedTypes); + + if (type.HasLayoutInfo) + Read (type.ClassSize); + + if (type.HasFields) + ReadFields (type); + + if (type.HasMethods) + ReadMethods (type); + + if (type.HasProperties) + ReadProperties (type); + + if (type.HasEvents) + ReadEvents (type); + + ReadSecurityDeclarations (type); + ReadCustomAttributes (type); + } + + static void ReadGenericParameters (IGenericParameterProvider provider) + { + if (!provider.HasGenericParameters) + return; + + var parameters = provider.GenericParameters; + + for (int i = 0; i < parameters.Count; i++) { + var parameter = parameters [i]; + + if (parameter.HasConstraints) + Read (parameter.Constraints); + + if (parameter.HasCustomAttributes) + Read (parameter.CustomAttributes); + } + } + + static void ReadSecurityDeclarations (ISecurityDeclarationProvider provider) + { + if (provider.HasSecurityDeclarations) + Read (provider.SecurityDeclarations); + } + + static void ReadCustomAttributes (ICustomAttributeProvider provider) + { + if (provider.HasCustomAttributes) + Read (provider.CustomAttributes); + } + + static void ReadFields (TypeDefinition type) + { + var fields = type.Fields; + + for (int i = 0; i < fields.Count; i++) { + var field = fields [i]; + + if (field.HasConstant) + Read (field.Constant); + + if (field.HasLayoutInfo) + Read (field.Offset); + + if (field.RVA > 0) + Read (field.InitialValue); + + if (field.HasMarshalInfo) + Read (field.MarshalInfo); + + ReadCustomAttributes (field); + } + } + + static void ReadMethods (TypeDefinition type) + { + var methods = type.Methods; + + for (int i = 0; i < methods.Count; i++) { + var method = methods [i]; + + ReadGenericParameters (method); + + if (method.HasParameters) + ReadParameters (method); + + if (method.HasOverrides) + Read (method.Overrides); + + if (method.IsPInvokeImpl) + Read (method.PInvokeInfo); + + ReadSecurityDeclarations (method); + ReadCustomAttributes (method); + + var return_type = method.MethodReturnType; + if (return_type.HasConstant) + Read (return_type.Constant); + + if (return_type.HasMarshalInfo) + Read (return_type.MarshalInfo); + + ReadCustomAttributes (return_type); + } + } + + static void ReadParameters (MethodDefinition method) + { + var parameters = method.Parameters; + + for (int i = 0; i < parameters.Count; i++) { + var parameter = parameters [i]; + + if (parameter.HasConstant) + Read (parameter.Constant); + + if (parameter.HasMarshalInfo) + Read (parameter.MarshalInfo); + + ReadCustomAttributes (parameter); + } + } + + static void ReadProperties (TypeDefinition type) + { + var properties = type.Properties; + + for (int i = 0; i < properties.Count; i++) { + var property = properties [i]; + + Read (property.GetMethod); + + if (property.HasConstant) + Read (property.Constant); + + ReadCustomAttributes (property); + } + } + + static void ReadEvents (TypeDefinition type) + { + var events = type.Events; + + for (int i = 0; i < events.Count; i++) { + var @event = events [i]; + + Read (@event.AddMethod); + + ReadCustomAttributes (@event); + } + } + + static void Read (object collection) + { + } + } + + sealed class DeferredModuleReader : ModuleReader { + + public DeferredModuleReader (Image image) + : base (image, ReadingMode.Deferred) + { + } + + protected override void ReadModule () + { + this.module.Read (this.module, (module, reader) => { + ReadModuleManifest (reader); + return module; + }); + } + } + + sealed class MetadataReader : ByteBuffer { + + readonly internal Image image; + readonly internal ModuleDefinition module; + readonly internal MetadataSystem metadata; + + internal IGenericContext context; + internal CodeReader code; + + uint Position { + get { return (uint) base.position; } + set { base.position = (int) value; } + } + + public MetadataReader (ModuleDefinition module) + : base (module.Image.MetadataSection.Data) + { + this.image = module.Image; + this.module = module; + this.metadata = module.MetadataSystem; + this.code = new CodeReader (image.MetadataSection, this); + } + + int GetCodedIndexSize (CodedIndex index) + { + return image.GetCodedIndexSize (index); + } + + uint ReadByIndexSize (int size) + { + if (size == 4) + return ReadUInt32 (); + else + return ReadUInt16 (); + } + + byte [] ReadBlob () + { + var blob_heap = image.BlobHeap; + if (blob_heap == null) { + position += 2; + return Empty.Array; + } + + return blob_heap.Read (ReadBlobIndex ()); + } + + byte [] ReadBlob (uint signature) + { + var blob_heap = image.BlobHeap; + if (blob_heap == null) + return Empty.Array; + + return blob_heap.Read (signature); + } + + uint ReadBlobIndex () + { + var blob_heap = image.BlobHeap; + return ReadByIndexSize (blob_heap != null ? blob_heap.IndexSize : 2); + } + + string ReadString () + { + return image.StringHeap.Read (ReadByIndexSize (image.StringHeap.IndexSize)); + } + + uint ReadStringIndex () + { + return ReadByIndexSize (image.StringHeap.IndexSize); + } + + uint ReadTableIndex (Table table) + { + return ReadByIndexSize (image.GetTableIndexSize (table)); + } + + MetadataToken ReadMetadataToken (CodedIndex index) + { + return index.GetMetadataToken (ReadByIndexSize (GetCodedIndexSize (index))); + } + + int MoveTo (Table table) + { + var info = image.TableHeap [table]; + if (info.Length != 0) + Position = info.Offset; + + return (int) info.Length; + } + + bool MoveTo (Table table, uint row) + { + var info = image.TableHeap [table]; + var length = info.Length; + if (length == 0 || row > length) + return false; + + Position = info.Offset + (info.RowSize * (row - 1)); + return true; + } + + public AssemblyNameDefinition ReadAssemblyNameDefinition () + { + if (MoveTo (Table.Assembly) == 0) + return null; + + var name = new AssemblyNameDefinition (); + + name.HashAlgorithm = (AssemblyHashAlgorithm) ReadUInt32 (); + + PopulateVersionAndFlags (name); + + name.PublicKey = ReadBlob (); + + PopulateNameAndCulture (name); + + return name; + } + + public ModuleDefinition Populate (ModuleDefinition module) + { + if (MoveTo (Table.Module) == 0) + return module; + + Advance (2); // Generation + + module.Name = ReadString (); + module.Mvid = image.GuidHeap.Read (ReadByIndexSize (image.GuidHeap.IndexSize)); + + return module; + } + + void InitializeAssemblyReferences () + { + if (metadata.AssemblyReferences != null) + return; + + int length = MoveTo (Table.AssemblyRef); + var references = metadata.AssemblyReferences = new AssemblyNameReference [length]; + + for (uint i = 0; i < length; i++) { + var reference = new AssemblyNameReference (); + reference.token = new MetadataToken (TokenType.AssemblyRef, i + 1); + + PopulateVersionAndFlags (reference); + + var key_or_token = ReadBlob (); + + if (reference.HasPublicKey) + reference.PublicKey = key_or_token; + else + reference.PublicKeyToken = key_or_token; + + PopulateNameAndCulture (reference); + + reference.Hash = ReadBlob (); + + references [i] = reference; + } + } + + public Collection ReadAssemblyReferences () + { + InitializeAssemblyReferences (); + + return new Collection (metadata.AssemblyReferences); + } + + public MethodDefinition ReadEntryPoint () + { + if (module.Image.EntryPointToken == 0) + return null; + + var token = new MetadataToken (module.Image.EntryPointToken); + return GetMethodDefinition (token.RID); + } + + public Collection ReadModules () + { + var modules = new Collection (1); + modules.Add (this.module); + + int length = MoveTo (Table.File); + for (uint i = 1; i <= length; i++) { + var attributes = (FileAttributes) ReadUInt32 (); + var name = ReadString (); + ReadBlobIndex (); + + if (attributes != FileAttributes.ContainsMetaData) + continue; + + var parameters = new ReaderParameters { + ReadingMode = module.ReadingMode, + SymbolReaderProvider = module.SymbolReaderProvider, + AssemblyResolver = module.AssemblyResolver + }; + + modules.Add (ModuleDefinition.ReadModule ( + GetModuleFileName (name), parameters)); + } + + return modules; + } + + string GetModuleFileName (string name) + { + if (module.FullyQualifiedName == null) + throw new NotSupportedException (); + + var path = Path.GetDirectoryName (module.FullyQualifiedName); + return Path.Combine (path, name); + } + + void InitializeModuleReferences () + { + if (metadata.ModuleReferences != null) + return; + + int length = MoveTo (Table.ModuleRef); + var references = metadata.ModuleReferences = new ModuleReference [length]; + + for (uint i = 0; i < length; i++) { + var reference = new ModuleReference (ReadString ()); + reference.token = new MetadataToken (TokenType.ModuleRef, i + 1); + + references [i] = reference; + } + } + + public Collection ReadModuleReferences () + { + InitializeModuleReferences (); + + return new Collection (metadata.ModuleReferences); + } + + public bool HasFileResource () + { + int length = MoveTo (Table.File); + if (length == 0) + return false; + + for (uint i = 1; i <= length; i++) + if (ReadFileRecord (i).Col1 == FileAttributes.ContainsNoMetaData) + return true; + + return false; + } + + public Collection ReadResources () + { + int length = MoveTo (Table.ManifestResource); + var resources = new Collection (length); + + for (int i = 1; i <= length; i++) { + var offset = ReadUInt32 (); + var flags = (ManifestResourceAttributes) ReadUInt32 (); + var name = ReadString (); + var implementation = ReadMetadataToken (CodedIndex.Implementation); + + Resource resource; + + if (implementation.RID == 0) { + resource = new EmbeddedResource (name, flags, offset, this); + } else if (implementation.TokenType == TokenType.AssemblyRef) { + resource = new AssemblyLinkedResource (name, flags) { + Assembly = (AssemblyNameReference) GetTypeReferenceScope (implementation), + }; + } else if (implementation.TokenType == TokenType.File) { + var file_record = ReadFileRecord (implementation.RID); + + resource = new LinkedResource (name, flags) { + File = file_record.Col2, + hash = ReadBlob (file_record.Col3) + }; + } else + throw new NotSupportedException (); + + resources.Add (resource); + } + + return resources; + } + + Row ReadFileRecord (uint rid) + { + var position = this.position; + + if (!MoveTo (Table.File, rid)) + throw new ArgumentException (); + + var record = new Row ( + (FileAttributes) ReadUInt32 (), + ReadString (), + ReadBlobIndex ()); + + this.position = position; + + return record; + } + + public MemoryStream GetManagedResourceStream (uint offset) + { + var rva = image.Resources.VirtualAddress; + var section = image.GetSectionAtVirtualAddress (rva); + var position = (rva - section.VirtualAddress) + offset; + var buffer = section.Data; + + var length = buffer [position] + | (buffer [position + 1] << 8) + | (buffer [position + 2] << 16) + | (buffer [position + 3] << 24); + + return new MemoryStream (buffer, (int) position + 4, length); + } + + void PopulateVersionAndFlags (AssemblyNameReference name) + { + name.Version = new Version ( + ReadUInt16 (), + ReadUInt16 (), + ReadUInt16 (), + ReadUInt16 ()); + + name.Attributes = (AssemblyAttributes) ReadUInt32 (); + } + + void PopulateNameAndCulture (AssemblyNameReference name) + { + name.Name = ReadString (); + name.Culture = ReadString (); + } + + public TypeDefinitionCollection ReadTypes () + { + InitializeTypeDefinitions (); + var mtypes = metadata.Types; + var type_count = mtypes.Length - metadata.NestedTypes.Count; + var types = new TypeDefinitionCollection (module, type_count); + + for (int i = 0; i < mtypes.Length; i++) { + var type = mtypes [i]; + if (IsNested (type.Attributes)) + continue; + + types.Add (type); + } + + if (image.HasTable (Table.MethodPtr) || image.HasTable (Table.FieldPtr)) + CompleteTypes (); + + return types; + } + + void CompleteTypes () + { + var types = metadata.Types; + + for (int i = 0; i < types.Length; i++) { + var type = types [i]; + + InitializeCollection (type.Fields); + InitializeCollection (type.Methods); + } + } + + void InitializeTypeDefinitions () + { + if (metadata.Types != null) + return; + + InitializeNestedTypes (); + InitializeFields (); + InitializeMethods (); + + int length = MoveTo (Table.TypeDef); + var types = metadata.Types = new TypeDefinition [length]; + + for (uint i = 0; i < length; i++) { + if (types [i] != null) + continue; + + types [i] = ReadType (i + 1); + } + } + + static bool IsNested (TypeAttributes attributes) + { + switch (attributes & TypeAttributes.VisibilityMask) { + case TypeAttributes.NestedAssembly: + case TypeAttributes.NestedFamANDAssem: + case TypeAttributes.NestedFamily: + case TypeAttributes.NestedFamORAssem: + case TypeAttributes.NestedPrivate: + case TypeAttributes.NestedPublic: + return true; + default: + return false; + } + } + + public bool HasNestedTypes (TypeDefinition type) + { + uint [] mapping; + InitializeNestedTypes (); + + if (!metadata.TryGetNestedTypeMapping (type, out mapping)) + return false; + + return mapping.Length > 0; + } + + public Collection ReadNestedTypes (TypeDefinition type) + { + InitializeNestedTypes (); + uint [] mapping; + if (!metadata.TryGetNestedTypeMapping (type, out mapping)) + return new MemberDefinitionCollection (type); + + var nested_types = new MemberDefinitionCollection (type, mapping.Length); + + for (int i = 0; i < mapping.Length; i++) { + var nested_type = GetTypeDefinition (mapping [i]); + + if (nested_type != null) + nested_types.Add (nested_type); + } + + metadata.RemoveNestedTypeMapping (type); + + return nested_types; + } + + void InitializeNestedTypes () + { + if (metadata.NestedTypes != null) + return; + + var length = MoveTo (Table.NestedClass); + + metadata.NestedTypes = new Dictionary (length); + metadata.ReverseNestedTypes = new Dictionary (length); + + if (length == 0) + return; + + for (int i = 1; i <= length; i++) { + var nested = ReadTableIndex (Table.TypeDef); + var declaring = ReadTableIndex (Table.TypeDef); + + AddNestedMapping (declaring, nested); + } + } + + void AddNestedMapping (uint declaring, uint nested) + { + metadata.SetNestedTypeMapping (declaring, AddMapping (metadata.NestedTypes, declaring, nested)); + metadata.SetReverseNestedTypeMapping (nested, declaring); + } + + static TValue [] AddMapping (Dictionary cache, TKey key, TValue value) + { + TValue [] mapped; + if (!cache.TryGetValue (key, out mapped)) { + mapped = new [] { value }; + return mapped; + } + + var new_mapped = new TValue [mapped.Length + 1]; + Array.Copy (mapped, new_mapped, mapped.Length); + new_mapped [mapped.Length] = value; + return new_mapped; + } + + TypeDefinition ReadType (uint rid) + { + if (!MoveTo (Table.TypeDef, rid)) + return null; + + var attributes = (TypeAttributes) ReadUInt32 (); + var name = ReadString (); + var @namespace = ReadString (); + var type = new TypeDefinition (@namespace, name, attributes); + type.token = new MetadataToken (TokenType.TypeDef, rid); + type.scope = module; + type.module = module; + + metadata.AddTypeDefinition (type); + + this.context = type; + + type.BaseType = GetTypeDefOrRef (ReadMetadataToken (CodedIndex.TypeDefOrRef)); + + type.fields_range = ReadFieldsRange (rid); + type.methods_range = ReadMethodsRange (rid); + + if (IsNested (attributes)) + type.DeclaringType = GetNestedTypeDeclaringType (type); + + return type; + } + + TypeDefinition GetNestedTypeDeclaringType (TypeDefinition type) + { + uint declaring_rid; + if (!metadata.TryGetReverseNestedTypeMapping (type, out declaring_rid)) + return null; + + metadata.RemoveReverseNestedTypeMapping (type); + return GetTypeDefinition (declaring_rid); + } + + Range ReadFieldsRange (uint type_index) + { + return ReadListRange (type_index, Table.TypeDef, Table.Field); + } + + Range ReadMethodsRange (uint type_index) + { + return ReadListRange (type_index, Table.TypeDef, Table.Method); + } + + Range ReadListRange (uint current_index, Table current, Table target) + { + var list = new Range (); + + list.Start = ReadTableIndex (target); + + uint next_index; + var current_table = image.TableHeap [current]; + + if (current_index == current_table.Length) + next_index = image.TableHeap [target].Length + 1; + else { + var position = Position; + Position += (uint) (current_table.RowSize - image.GetTableIndexSize (target)); + next_index = ReadTableIndex (target); + Position = position; + } + + list.Length = next_index - list.Start; + + return list; + } + + public Row ReadTypeLayout (TypeDefinition type) + { + InitializeTypeLayouts (); + Row class_layout; + var rid = type.token.RID; + if (!metadata.ClassLayouts.TryGetValue (rid, out class_layout)) + return new Row (Mixin.NoDataMarker, Mixin.NoDataMarker); + + type.PackingSize = (short) class_layout.Col1; + type.ClassSize = (int) class_layout.Col2; + + metadata.ClassLayouts.Remove (rid); + + return new Row ((short) class_layout.Col1, (int) class_layout.Col2); + } + + void InitializeTypeLayouts () + { + if (metadata.ClassLayouts != null) + return; + + int length = MoveTo (Table.ClassLayout); + + var class_layouts = metadata.ClassLayouts = new Dictionary> (length); + + for (uint i = 0; i < length; i++) { + var packing_size = ReadUInt16 (); + var class_size = ReadUInt32 (); + + var parent = ReadTableIndex (Table.TypeDef); + + class_layouts.Add (parent, new Row (packing_size, class_size)); + } + } + + public TypeReference GetTypeDefOrRef (MetadataToken token) + { + return (TypeReference) LookupToken (token); + } + + public TypeDefinition GetTypeDefinition (uint rid) + { + InitializeTypeDefinitions (); + + var type = metadata.GetTypeDefinition (rid); + if (type != null) + return type; + + return ReadTypeDefinition (rid); + } + + TypeDefinition ReadTypeDefinition (uint rid) + { + if (!MoveTo (Table.TypeDef, rid)) + return null; + + return ReadType (rid); + } + + void InitializeTypeReferences () + { + if (metadata.TypeReferences != null) + return; + + metadata.TypeReferences = new TypeReference [image.GetTableLength (Table.TypeRef)]; + } + + public TypeReference GetTypeReference (string scope, string full_name) + { + InitializeTypeReferences (); + + var length = metadata.TypeReferences.Length; + + for (uint i = 1; i <= length; i++) { + var type = GetTypeReference (i); + + if (type.FullName != full_name) + continue; + + if (string.IsNullOrEmpty (scope)) + return type; + + if (type.Scope.Name == scope) + return type; + } + + return null; + } + + TypeReference GetTypeReference (uint rid) + { + InitializeTypeReferences (); + + var type = metadata.GetTypeReference (rid); + if (type != null) + return type; + + return ReadTypeReference (rid); + } + + TypeReference ReadTypeReference (uint rid) + { + if (!MoveTo (Table.TypeRef, rid)) + return null; + + TypeReference declaring_type = null; + IMetadataScope scope; + + var scope_token = ReadMetadataToken (CodedIndex.ResolutionScope); + + var name = ReadString (); + var @namespace = ReadString (); + + var type = new TypeReference ( + @namespace, + name, + module, + null); + + type.token = new MetadataToken (TokenType.TypeRef, rid); + + metadata.AddTypeReference (type); + + if (scope_token.TokenType == TokenType.TypeRef) { + declaring_type = GetTypeDefOrRef (scope_token); + + scope = declaring_type != null + ? declaring_type.Scope + : module; + } else + scope = GetTypeReferenceScope (scope_token); + + type.scope = scope; + type.DeclaringType = declaring_type; + + MetadataSystem.TryProcessPrimitiveTypeReference (type); + + return type; + } + + IMetadataScope GetTypeReferenceScope (MetadataToken scope) + { + switch (scope.TokenType) { + case TokenType.AssemblyRef: + InitializeAssemblyReferences (); + return metadata.AssemblyReferences [(int) scope.RID - 1]; + case TokenType.ModuleRef: + InitializeModuleReferences (); + return metadata.ModuleReferences [(int) scope.RID - 1]; + case TokenType.Module: + return module; + default: + throw new NotSupportedException (); + } + } + + public IEnumerable GetTypeReferences () + { + InitializeTypeReferences (); + + var length = image.GetTableLength (Table.TypeRef); + + var type_references = new TypeReference [length]; + + for (uint i = 1; i <= length; i++) + type_references [i - 1] = GetTypeReference (i); + + return type_references; + } + + TypeReference GetTypeSpecification (uint rid) + { + if (!MoveTo (Table.TypeSpec, rid)) + return null; + + var reader = ReadSignature (ReadBlobIndex ()); + var type = reader.ReadTypeSignature (); + if (type.token.RID == 0) + type.token = new MetadataToken (TokenType.TypeSpec, rid); + + return type; + } + + SignatureReader ReadSignature (uint signature) + { + return new SignatureReader (signature, this); + } + + public bool HasInterfaces (TypeDefinition type) + { + InitializeInterfaces (); + MetadataToken [] mapping; + + return metadata.TryGetInterfaceMapping (type, out mapping); + } + + public Collection ReadInterfaces (TypeDefinition type) + { + InitializeInterfaces (); + MetadataToken [] mapping; + + if (!metadata.TryGetInterfaceMapping (type, out mapping)) + return new Collection (); + + var interfaces = new Collection (mapping.Length); + + this.context = type; + + for (int i = 0; i < mapping.Length; i++) + interfaces.Add (GetTypeDefOrRef (mapping [i])); + + metadata.RemoveInterfaceMapping (type); + + return interfaces; + } + + void InitializeInterfaces () + { + if (metadata.Interfaces != null) + return; + + int length = MoveTo (Table.InterfaceImpl); + + metadata.Interfaces = new Dictionary (length); + + for (int i = 0; i < length; i++) { + var type = ReadTableIndex (Table.TypeDef); + var @interface = ReadMetadataToken (CodedIndex.TypeDefOrRef); + + AddInterfaceMapping (type, @interface); + } + } + + void AddInterfaceMapping (uint type, MetadataToken @interface) + { + metadata.SetInterfaceMapping (type, AddMapping (metadata.Interfaces, type, @interface)); + } + + public Collection ReadFields (TypeDefinition type) + { + var fields_range = type.fields_range; + if (fields_range.Length == 0) + return new MemberDefinitionCollection (type); + + var fields = new MemberDefinitionCollection (type, (int) fields_range.Length); + this.context = type; + + if (!MoveTo (Table.FieldPtr, fields_range.Start)) { + if (!MoveTo (Table.Field, fields_range.Start)) + return fields; + + for (uint i = 0; i < fields_range.Length; i++) + ReadField (fields_range.Start + i, fields); + } else + ReadPointers (Table.FieldPtr, Table.Field, fields_range, fields, ReadField); + + return fields; + } + + void ReadField (uint field_rid, Collection fields) + { + var attributes = (FieldAttributes) ReadUInt16 (); + var name = ReadString (); + var signature = ReadBlobIndex (); + + var field = new FieldDefinition (name, attributes, ReadFieldType (signature)); + field.token = new MetadataToken (TokenType.Field, field_rid); + metadata.AddFieldDefinition (field); + + if (IsDeleted (field)) + return; + + fields.Add (field); + } + + void InitializeFields () + { + if (metadata.Fields != null) + return; + + metadata.Fields = new FieldDefinition [image.GetTableLength (Table.Field)]; + } + + TypeReference ReadFieldType (uint signature) + { + var reader = ReadSignature (signature); + + const byte field_sig = 0x6; + + if (reader.ReadByte () != field_sig) + throw new NotSupportedException (); + + return reader.ReadTypeSignature (); + } + + public int ReadFieldRVA (FieldDefinition field) + { + InitializeFieldRVAs (); + var rid = field.token.RID; + + RVA rva; + if (!metadata.FieldRVAs.TryGetValue (rid, out rva)) + return 0; + + var size = GetFieldTypeSize (field.FieldType); + + if (size == 0 || rva == 0) + return 0; + + metadata.FieldRVAs.Remove (rid); + + field.InitialValue = GetFieldInitializeValue (size, rva); + + return (int) rva; + } + + byte [] GetFieldInitializeValue (int size, RVA rva) + { + var section = image.GetSectionAtVirtualAddress (rva); + if (section == null) + return Empty.Array; + + var value = new byte [size]; + Buffer.BlockCopy (section.Data, (int) (rva - section.VirtualAddress), value, 0, size); + return value; + } + + static int GetFieldTypeSize (TypeReference type) + { + int size = 0; + + switch (type.etype) { + case ElementType.Boolean: + case ElementType.U1: + case ElementType.I1: + size = 1; + break; + case ElementType.U2: + case ElementType.I2: + case ElementType.Char: + size = 2; + break; + case ElementType.U4: + case ElementType.I4: + case ElementType.R4: + size = 4; + break; + case ElementType.U8: + case ElementType.I8: + case ElementType.R8: + size = 8; + break; + case ElementType.Ptr: + case ElementType.FnPtr: + size = IntPtr.Size; + break; + case ElementType.CModOpt: + case ElementType.CModReqD: + return GetFieldTypeSize (((IModifierType) type).ElementType); + default: + var field_type = type.CheckedResolve (); + if (field_type.HasLayoutInfo) + size = field_type.ClassSize; + + break; + } + + return size; + } + + void InitializeFieldRVAs () + { + if (metadata.FieldRVAs != null) + return; + + int length = MoveTo (Table.FieldRVA); + + var field_rvas = metadata.FieldRVAs = new Dictionary (length); + + for (int i = 0; i < length; i++) { + var rva = ReadUInt32 (); + var field = ReadTableIndex (Table.Field); + + field_rvas.Add (field, rva); + } + } + + public int ReadFieldLayout (FieldDefinition field) + { + InitializeFieldLayouts (); + var rid = field.token.RID; + uint offset; + if (!metadata.FieldLayouts.TryGetValue (rid, out offset)) + return Mixin.NoDataMarker; + + metadata.FieldLayouts.Remove (rid); + + return (int) offset; + } + + void InitializeFieldLayouts () + { + if (metadata.FieldLayouts != null) + return; + + int length = MoveTo (Table.FieldLayout); + + var field_layouts = metadata.FieldLayouts = new Dictionary (length); + + for (int i = 0; i < length; i++) { + var offset = ReadUInt32 (); + var field = ReadTableIndex (Table.Field); + + field_layouts.Add (field, offset); + } + } + + public bool HasEvents (TypeDefinition type) + { + InitializeEvents (); + + Range range; + if (!metadata.TryGetEventsRange (type, out range)) + return false; + + return range.Length > 0; + } + + public Collection ReadEvents (TypeDefinition type) + { + InitializeEvents (); + Range range; + + if (!metadata.TryGetEventsRange (type, out range)) + return new MemberDefinitionCollection (type); + + var events = new MemberDefinitionCollection (type, (int) range.Length); + + metadata.RemoveEventsRange (type); + + if (range.Length == 0) + return events; + + this.context = type; + + if (!MoveTo (Table.EventPtr, range.Start)) { + if (!MoveTo (Table.Event, range.Start)) + return events; + + for (uint i = 0; i < range.Length; i++) + ReadEvent (range.Start + i, events); + } else + ReadPointers (Table.EventPtr, Table.Event, range, events, ReadEvent); + + return events; + } + + void ReadEvent (uint event_rid, Collection events) + { + var attributes = (EventAttributes) ReadUInt16 (); + var name = ReadString (); + var event_type = GetTypeDefOrRef (ReadMetadataToken (CodedIndex.TypeDefOrRef)); + + var @event = new EventDefinition (name, attributes, event_type); + @event.token = new MetadataToken (TokenType.Event, event_rid); + + if (IsDeleted (@event)) + return; + + events.Add (@event); + } + + void InitializeEvents () + { + if (metadata.Events != null) + return; + + int length = MoveTo (Table.EventMap); + + metadata.Events = new Dictionary (length); + + for (uint i = 1; i <= length; i++) { + var type_rid = ReadTableIndex (Table.TypeDef); + Range events_range = ReadEventsRange (i); + metadata.AddEventsRange (type_rid, events_range); + } + } + + Range ReadEventsRange (uint rid) + { + return ReadListRange (rid, Table.EventMap, Table.Event); + } + + public bool HasProperties (TypeDefinition type) + { + InitializeProperties (); + + Range range; + if (!metadata.TryGetPropertiesRange (type, out range)) + return false; + + return range.Length > 0; + } + + public Collection ReadProperties (TypeDefinition type) + { + InitializeProperties (); + + Range range; + + if (!metadata.TryGetPropertiesRange (type, out range)) + return new MemberDefinitionCollection (type); + + metadata.RemovePropertiesRange (type); + + var properties = new MemberDefinitionCollection (type, (int) range.Length); + + if (range.Length == 0) + return properties; + + this.context = type; + + if (!MoveTo (Table.PropertyPtr, range.Start)) { + if (!MoveTo (Table.Property, range.Start)) + return properties; + for (uint i = 0; i < range.Length; i++) + ReadProperty (range.Start + i, properties); + } else + ReadPointers (Table.PropertyPtr, Table.Property, range, properties, ReadProperty); + + return properties; + } + + void ReadProperty (uint property_rid, Collection properties) + { + var attributes = (PropertyAttributes) ReadUInt16 (); + var name = ReadString (); + var signature = ReadBlobIndex (); + + var reader = ReadSignature (signature); + const byte property_signature = 0x8; + + var calling_convention = reader.ReadByte (); + + if ((calling_convention & property_signature) == 0) + throw new NotSupportedException (); + + var has_this = (calling_convention & 0x20) != 0; + + reader.ReadCompressedUInt32 (); // count + + var property = new PropertyDefinition (name, attributes, reader.ReadTypeSignature ()); + property.HasThis = has_this; + property.token = new MetadataToken (TokenType.Property, property_rid); + + if (IsDeleted (property)) + return; + + properties.Add (property); + } + + void InitializeProperties () + { + if (metadata.Properties != null) + return; + + int length = MoveTo (Table.PropertyMap); + + metadata.Properties = new Dictionary (length); + + for (uint i = 1; i <= length; i++) { + var type_rid = ReadTableIndex (Table.TypeDef); + var properties_range = ReadPropertiesRange (i); + metadata.AddPropertiesRange (type_rid, properties_range); + } + } + + Range ReadPropertiesRange (uint rid) + { + return ReadListRange (rid, Table.PropertyMap, Table.Property); + } + + MethodSemanticsAttributes ReadMethodSemantics (MethodDefinition method) + { + InitializeMethodSemantics (); + Row row; + if (!metadata.Semantics.TryGetValue (method.token.RID, out row)) + return MethodSemanticsAttributes.None; + + var type = method.DeclaringType; + + switch (row.Col1) { + case MethodSemanticsAttributes.AddOn: + GetEvent (type, row.Col2).add_method = method; + break; + case MethodSemanticsAttributes.Fire: + GetEvent (type, row.Col2).invoke_method = method; + break; + case MethodSemanticsAttributes.RemoveOn: + GetEvent (type, row.Col2).remove_method = method; + break; + case MethodSemanticsAttributes.Getter: + GetProperty (type, row.Col2).get_method = method; + break; + case MethodSemanticsAttributes.Setter: + GetProperty (type, row.Col2).set_method = method; + break; + case MethodSemanticsAttributes.Other: + switch (row.Col2.TokenType) { + case TokenType.Event: { + var @event = GetEvent (type, row.Col2); + if (@event.other_methods == null) + @event.other_methods = new Collection (); + + @event.other_methods.Add (method); + break; + } + case TokenType.Property: { + var property = GetProperty (type, row.Col2); + if (property.other_methods == null) + property.other_methods = new Collection (); + + property.other_methods.Add (method); + + break; + } + default: + throw new NotSupportedException (); + } + break; + default: + throw new NotSupportedException (); + } + + metadata.Semantics.Remove (method.token.RID); + + return row.Col1; + } + + static EventDefinition GetEvent (TypeDefinition type, MetadataToken token) + { + if (token.TokenType != TokenType.Event) + throw new ArgumentException (); + + return GetMember (type.Events, token); + } + + static PropertyDefinition GetProperty (TypeDefinition type, MetadataToken token) + { + if (token.TokenType != TokenType.Property) + throw new ArgumentException (); + + return GetMember (type.Properties, token); + } + + static TMember GetMember (Collection members, MetadataToken token) where TMember : IMemberDefinition + { + for (int i = 0; i < members.Count; i++) { + var member = members [i]; + if (member.MetadataToken == token) + return member; + } + + throw new ArgumentException (); + } + + void InitializeMethodSemantics () + { + if (metadata.Semantics != null) + return; + + int length = MoveTo (Table.MethodSemantics); + + var semantics = metadata.Semantics = new Dictionary> (0); + + for (uint i = 0; i < length; i++) { + var attributes = (MethodSemanticsAttributes) ReadUInt16 (); + var method_rid = ReadTableIndex (Table.Method); + var association = ReadMetadataToken (CodedIndex.HasSemantics); + + semantics [method_rid] = new Row (attributes, association); + } + } + + public PropertyDefinition ReadMethods (PropertyDefinition property) + { + ReadAllSemantics (property.DeclaringType); + return property; + } + + public EventDefinition ReadMethods (EventDefinition @event) + { + ReadAllSemantics (@event.DeclaringType); + return @event; + } + + public MethodSemanticsAttributes ReadAllSemantics (MethodDefinition method) + { + ReadAllSemantics (method.DeclaringType); + + return method.SemanticsAttributes; + } + + void ReadAllSemantics (TypeDefinition type) + { + var methods = type.Methods; + for (int i = 0; i < methods.Count; i++) { + var method = methods [i]; + if (method.sem_attrs.HasValue) + continue; + + method.sem_attrs = ReadMethodSemantics (method); + } + } + + Range ReadParametersRange (uint method_rid) + { + return ReadListRange (method_rid, Table.Method, Table.Param); + } + + public Collection ReadMethods (TypeDefinition type) + { + var methods_range = type.methods_range; + if (methods_range.Length == 0) + return new MemberDefinitionCollection (type); + + var methods = new MemberDefinitionCollection (type, (int) methods_range.Length); + if (!MoveTo (Table.MethodPtr, methods_range.Start)) { + if (!MoveTo (Table.Method, methods_range.Start)) + return methods; + + for (uint i = 0; i < methods_range.Length; i++) + ReadMethod (methods_range.Start + i, methods); + } else + ReadPointers (Table.MethodPtr, Table.Method, methods_range, methods, ReadMethod); + + return methods; + } + + void ReadPointers (Table ptr, Table table, Range range, Collection members, Action> reader) + where TMember : IMemberDefinition + { + for (uint i = 0; i < range.Length; i++) { + MoveTo (ptr, range.Start + i); + + var rid = ReadTableIndex (table); + MoveTo (table, rid); + + reader (rid, members); + } + } + + static bool IsDeleted (IMemberDefinition member) + { + return member.IsSpecialName && member.Name == "_Deleted"; + } + + void InitializeMethods () + { + if (metadata.Methods != null) + return; + + metadata.Methods = new MethodDefinition [image.GetTableLength (Table.Method)]; + } + + void ReadMethod (uint method_rid, Collection methods) + { + var method = new MethodDefinition (); + method.rva = ReadUInt32 (); + method.ImplAttributes = (MethodImplAttributes) ReadUInt16 (); + method.Attributes = (MethodAttributes) ReadUInt16 (); + method.Name = ReadString (); + method.token = new MetadataToken (TokenType.Method, method_rid); + + if (IsDeleted (method)) + return; + + methods.Add (method); // attach method + + var signature = ReadBlobIndex (); + var param_range = ReadParametersRange (method_rid); + + this.context = method; + + ReadMethodSignature (signature, method); + metadata.AddMethodDefinition (method); + + if (param_range.Length == 0) + return; + + var position = base.position; + ReadParameters (method, param_range); + base.position = position; + } + + void ReadParameters (MethodDefinition method, Range param_range) + { + if (!MoveTo (Table.ParamPtr, param_range.Start)) { + if (!MoveTo (Table.Param, param_range.Start)) + return; + + for (uint i = 0; i < param_range.Length; i++) + ReadParameter (param_range.Start + i, method); + } else + ReadParameterPointers (method, param_range); + } + + void ReadParameterPointers (MethodDefinition method, Range range) + { + for (uint i = 0; i < range.Length; i++) { + MoveTo (Table.ParamPtr, range.Start + i); + + var rid = ReadTableIndex (Table.Param); + + MoveTo (Table.Param, rid); + + ReadParameter (rid, method); + } + } + + void ReadParameter (uint param_rid, MethodDefinition method) + { + var attributes = (ParameterAttributes) ReadUInt16 (); + var sequence = ReadUInt16 (); + var name = ReadString (); + + var parameter = sequence == 0 + ? method.MethodReturnType.Parameter + : method.Parameters [sequence - 1]; + + parameter.token = new MetadataToken (TokenType.Param, param_rid); + parameter.Name = name; + parameter.Attributes = attributes; + } + + void ReadMethodSignature (uint signature, IMethodSignature method) + { + var reader = ReadSignature (signature); + reader.ReadMethodSignature (method); + } + + public PInvokeInfo ReadPInvokeInfo (MethodDefinition method) + { + InitializePInvokes (); + Row row; + + var rid = method.token.RID; + + if (!metadata.PInvokes.TryGetValue (rid, out row)) + return null; + + metadata.PInvokes.Remove (rid); + + return new PInvokeInfo ( + row.Col1, + image.StringHeap.Read (row.Col2), + module.ModuleReferences [(int) row.Col3 - 1]); + } + + void InitializePInvokes () + { + if (metadata.PInvokes != null) + return; + + int length = MoveTo (Table.ImplMap); + + var pinvokes = metadata.PInvokes = new Dictionary> (length); + + for (int i = 1; i <= length; i++) { + var attributes = (PInvokeAttributes) ReadUInt16 (); + var method = ReadMetadataToken (CodedIndex.MemberForwarded); + var name = ReadStringIndex (); + var scope = ReadTableIndex (Table.File); + + if (method.TokenType != TokenType.Method) + continue; + + pinvokes.Add (method.RID, new Row (attributes, name, scope)); + } + } + + public bool HasGenericParameters (IGenericParameterProvider provider) + { + InitializeGenericParameters (); + + Range [] ranges; + if (!metadata.TryGetGenericParameterRanges (provider, out ranges)) + return false; + + return RangesSize (ranges) > 0; + } + + public Collection ReadGenericParameters (IGenericParameterProvider provider) + { + InitializeGenericParameters (); + + Range [] ranges; + if (!metadata.TryGetGenericParameterRanges (provider, out ranges)) + return new GenericParameterCollection (provider); + + metadata.RemoveGenericParameterRange (provider); + + var generic_parameters = new GenericParameterCollection (provider, RangesSize (ranges)); + + for (int i = 0; i < ranges.Length; i++) + ReadGenericParametersRange (ranges [i], provider, generic_parameters); + + return generic_parameters; + } + + void ReadGenericParametersRange (Range range, IGenericParameterProvider provider, GenericParameterCollection generic_parameters) + { + if (!MoveTo (Table.GenericParam, range.Start)) + return; + + for (uint i = 0; i < range.Length; i++) { + ReadUInt16 (); // index + var flags = (GenericParameterAttributes) ReadUInt16 (); + ReadMetadataToken (CodedIndex.TypeOrMethodDef); + var name = ReadString (); + + var parameter = new GenericParameter (name, provider); + parameter.token = new MetadataToken (TokenType.GenericParam, range.Start + i); + parameter.Attributes = flags; + + generic_parameters.Add (parameter); + } + } + + void InitializeGenericParameters () + { + if (metadata.GenericParameters != null) + return; + + metadata.GenericParameters = InitializeRanges ( + Table.GenericParam, () => { + Advance (4); + var next = ReadMetadataToken (CodedIndex.TypeOrMethodDef); + ReadStringIndex (); + return next; + }); + } + + Dictionary InitializeRanges (Table table, Func get_next) + { + int length = MoveTo (table); + var ranges = new Dictionary (length); + + if (length == 0) + return ranges; + + MetadataToken owner = MetadataToken.Zero; + Range range = new Range (1, 0); + + for (uint i = 1; i <= length; i++) { + var next = get_next (); + + if (i == 1) { + owner = next; + range.Length++; + } else if (next != owner) { + AddRange (ranges, owner, range); + range = new Range (i, 1); + owner = next; + } else + range.Length++; + } + + AddRange (ranges, owner, range); + + return ranges; + } + + static void AddRange (Dictionary ranges, MetadataToken owner, Range range) + { + if (owner.RID == 0) + return; + + Range [] slots; + if (!ranges.TryGetValue (owner, out slots)) { + ranges.Add (owner, new [] { range }); + return; + } + + slots = slots.Resize (slots.Length + 1); + slots [slots.Length - 1] = range; + ranges [owner] = slots; + } + + public bool HasGenericConstraints (GenericParameter generic_parameter) + { + InitializeGenericConstraints (); + + MetadataToken [] mapping; + if (!metadata.TryGetGenericConstraintMapping (generic_parameter, out mapping)) + return false; + + return mapping.Length > 0; + } + + public Collection ReadGenericConstraints (GenericParameter generic_parameter) + { + InitializeGenericConstraints (); + + MetadataToken [] mapping; + if (!metadata.TryGetGenericConstraintMapping (generic_parameter, out mapping)) + return new Collection (); + + var constraints = new Collection (mapping.Length); + + this.context = (IGenericContext) generic_parameter.Owner; + + for (int i = 0; i < mapping.Length; i++) + constraints.Add (GetTypeDefOrRef (mapping [i])); + + metadata.RemoveGenericConstraintMapping (generic_parameter); + + return constraints; + } + + void InitializeGenericConstraints () + { + if (metadata.GenericConstraints != null) + return; + + var length = MoveTo (Table.GenericParamConstraint); + + metadata.GenericConstraints = new Dictionary (length); + + for (int i = 1; i <= length; i++) + AddGenericConstraintMapping ( + ReadTableIndex (Table.GenericParam), + ReadMetadataToken (CodedIndex.TypeDefOrRef)); + } + + void AddGenericConstraintMapping (uint generic_parameter, MetadataToken constraint) + { + metadata.SetGenericConstraintMapping ( + generic_parameter, + AddMapping (metadata.GenericConstraints, generic_parameter, constraint)); + } + + public bool HasOverrides (MethodDefinition method) + { + InitializeOverrides (); + MetadataToken [] mapping; + + if (!metadata.TryGetOverrideMapping (method, out mapping)) + return false; + + return mapping.Length > 0; + } + + public Collection ReadOverrides (MethodDefinition method) + { + InitializeOverrides (); + + MetadataToken [] mapping; + if (!metadata.TryGetOverrideMapping (method, out mapping)) + return new Collection (); + + var overrides = new Collection (mapping.Length); + + this.context = method; + + for (int i = 0; i < mapping.Length; i++) + overrides.Add ((MethodReference) LookupToken (mapping [i])); + + metadata.RemoveOverrideMapping (method); + + return overrides; + } + + void InitializeOverrides () + { + if (metadata.Overrides != null) + return; + + var length = MoveTo (Table.MethodImpl); + + metadata.Overrides = new Dictionary (length); + + for (int i = 1; i <= length; i++) { + ReadTableIndex (Table.TypeDef); + + var method = ReadMetadataToken (CodedIndex.MethodDefOrRef); + if (method.TokenType != TokenType.Method) + throw new NotSupportedException (); + + var @override = ReadMetadataToken (CodedIndex.MethodDefOrRef); + + AddOverrideMapping (method.RID, @override); + } + } + + void AddOverrideMapping (uint method_rid, MetadataToken @override) + { + metadata.SetOverrideMapping ( + method_rid, + AddMapping (metadata.Overrides, method_rid, @override)); + } + + public MethodBody ReadMethodBody (MethodDefinition method) + { + return code.ReadMethodBody (method); + } + + public CallSite ReadCallSite (MetadataToken token) + { + if (!MoveTo (Table.StandAloneSig, token.RID)) + return null; + + var signature = ReadBlobIndex (); + + var call_site = new CallSite (); + + ReadMethodSignature (signature, call_site); + + call_site.MetadataToken = token; + + return call_site; + } + + public VariableDefinitionCollection ReadVariables (MetadataToken local_var_token) + { + if (!MoveTo (Table.StandAloneSig, local_var_token.RID)) + return null; + + var reader = ReadSignature (ReadBlobIndex ()); + const byte local_sig = 0x7; + + if (reader.ReadByte () != local_sig) + throw new NotSupportedException (); + + var count = reader.ReadCompressedUInt32 (); + if (count == 0) + return null; + + var variables = new VariableDefinitionCollection ((int) count); + + for (int i = 0; i < count; i++) + variables.Add (new VariableDefinition (reader.ReadTypeSignature ())); + + return variables; + } + + public IMetadataTokenProvider LookupToken (MetadataToken token) + { + var rid = token.RID; + + if (rid == 0) + return null; + + IMetadataTokenProvider element; + var position = this.position; + var context = this.context; + + switch (token.TokenType) { + case TokenType.TypeDef: + element = GetTypeDefinition (rid); + break; + case TokenType.TypeRef: + element = GetTypeReference (rid); + break; + case TokenType.TypeSpec: + element = GetTypeSpecification (rid); + break; + case TokenType.Field: + element = GetFieldDefinition (rid); + break; + case TokenType.Method: + element = GetMethodDefinition (rid); + break; + case TokenType.MemberRef: + element = GetMemberReference (rid); + break; + case TokenType.MethodSpec: + element = GetMethodSpecification (rid); + break; + default: + return null; + } + + this.position = position; + this.context = context; + + return element; + } + + public FieldDefinition GetFieldDefinition (uint rid) + { + InitializeTypeDefinitions (); + + var field = metadata.GetFieldDefinition (rid); + if (field != null) + return field; + + return LookupField (rid); + } + + FieldDefinition LookupField (uint rid) + { + var type = metadata.GetFieldDeclaringType (rid); + if (type == null) + return null; + + InitializeCollection (type.Fields); + + return metadata.GetFieldDefinition (rid); + } + + public MethodDefinition GetMethodDefinition (uint rid) + { + InitializeTypeDefinitions (); + + var method = metadata.GetMethodDefinition (rid); + if (method != null) + return method; + + return LookupMethod (rid); + } + + MethodDefinition LookupMethod (uint rid) + { + var type = metadata.GetMethodDeclaringType (rid); + if (type == null) + return null; + + InitializeCollection (type.Methods); + + return metadata.GetMethodDefinition (rid); + } + + MethodSpecification GetMethodSpecification (uint rid) + { + if (!MoveTo (Table.MethodSpec, rid)) + return null; + + var element_method = (MethodReference) LookupToken ( + ReadMetadataToken (CodedIndex.MethodDefOrRef)); + var signature = ReadBlobIndex (); + + var method_spec = ReadMethodSpecSignature (signature, element_method); + method_spec.token = new MetadataToken (TokenType.MethodSpec, rid); + return method_spec; + } + + MethodSpecification ReadMethodSpecSignature (uint signature, MethodReference method) + { + var reader = ReadSignature (signature); + const byte methodspec_sig = 0x0a; + + var call_conv = reader.ReadByte (); + + if (call_conv != methodspec_sig) + throw new NotSupportedException (); + + var instance = new GenericInstanceMethod (method); + + reader.ReadGenericInstanceSignature (method, instance); + + return instance; + } + + MemberReference GetMemberReference (uint rid) + { + InitializeMemberReferences (); + + var member = metadata.GetMemberReference (rid); + if (member != null) + return member; + + member = ReadMemberReference (rid); + if (member != null && !member.ContainsGenericParameter) + metadata.AddMemberReference (member); + return member; + } + + MemberReference ReadMemberReference (uint rid) + { + if (!MoveTo (Table.MemberRef, rid)) + return null; + + var token = ReadMetadataToken (CodedIndex.MemberRefParent); + var name = ReadString (); + var signature = ReadBlobIndex (); + + MemberReference member; + + switch (token.TokenType) { + case TokenType.TypeDef: + case TokenType.TypeRef: + case TokenType.TypeSpec: + member = ReadTypeMemberReference (token, name, signature); + break; + case TokenType.Method: + member = ReadMethodMemberReference (token, name, signature); + break; + default: + throw new NotSupportedException (); + } + + member.token = new MetadataToken (TokenType.MemberRef, rid); + + return member; + } + + MemberReference ReadTypeMemberReference (MetadataToken type, string name, uint signature) + { + var declaring_type = GetTypeDefOrRef (type); + + if (!declaring_type.IsArray) + this.context = declaring_type; + + var member = ReadMemberReferenceSignature (signature, declaring_type); + member.Name = name; + + return member; + } + + MemberReference ReadMemberReferenceSignature (uint signature, TypeReference declaring_type) + { + var reader = ReadSignature (signature); + const byte field_sig = 0x6; + + if (reader.buffer [reader.position] == field_sig) { + reader.position++; + var field = new FieldReference (); + field.DeclaringType = declaring_type; + field.FieldType = reader.ReadTypeSignature (); + return field; + } else { + var method = new MethodReference (); + method.DeclaringType = declaring_type; + reader.ReadMethodSignature (method); + return method; + } + } + + MemberReference ReadMethodMemberReference (MetadataToken token, string name, uint signature) + { + var method = GetMethodDefinition (token.RID); + + this.context = method; + + var member = ReadMemberReferenceSignature (signature, method.DeclaringType); + member.Name = name; + + return member; + } + + void InitializeMemberReferences () + { + if (metadata.MemberReferences != null) + return; + + metadata.MemberReferences = new MemberReference [image.GetTableLength (Table.MemberRef)]; + } + + public IEnumerable GetMemberReferences () + { + InitializeMemberReferences (); + + var length = image.GetTableLength (Table.MemberRef); + + var type_system = module.TypeSystem; + + var context = new MethodReference (string.Empty, type_system.Void); + context.DeclaringType = new TypeReference (string.Empty, string.Empty, module, type_system.Corlib); + + var member_references = new MemberReference [length]; + + for (uint i = 1; i <= length; i++) { + this.context = context; + member_references [i - 1] = GetMemberReference (i); + } + + return member_references; + } + + void InitializeConstants () + { + if (metadata.Constants != null) + return; + + var length = MoveTo (Table.Constant); + + var constants = metadata.Constants = new Dictionary> (length); + + for (uint i = 1; i <= length; i++) { + var type = (ElementType) ReadUInt16 (); + var owner = ReadMetadataToken (CodedIndex.HasConstant); + var signature = ReadBlobIndex (); + + constants.Add (owner, new Row (type, signature)); + } + } + + public object ReadConstant (IConstantProvider owner) + { + InitializeConstants (); + + Row row; + if (!metadata.Constants.TryGetValue (owner.MetadataToken, out row)) + return Mixin.NoValue; + + metadata.Constants.Remove (owner.MetadataToken); + + switch (row.Col1) { + case ElementType.Class: + case ElementType.Object: + return null; + case ElementType.String: + return ReadConstantString (ReadBlob (row.Col2)); + default: + return ReadConstantPrimitive (row.Col1, row.Col2); + } + } + + static string ReadConstantString (byte [] blob) + { + var length = blob.Length; + if ((length & 1) == 1) + length--; + + return Encoding.Unicode.GetString (blob, 0, length); + } + + object ReadConstantPrimitive (ElementType type, uint signature) + { + var reader = ReadSignature (signature); + return reader.ReadConstantSignature (type); + } + + void InitializeCustomAttributes () + { + if (metadata.CustomAttributes != null) + return; + + metadata.CustomAttributes = InitializeRanges ( + Table.CustomAttribute, () => { + var next = ReadMetadataToken (CodedIndex.HasCustomAttribute); + ReadMetadataToken (CodedIndex.CustomAttributeType); + ReadBlobIndex (); + return next; + }); + } + + public bool HasCustomAttributes (ICustomAttributeProvider owner) + { + InitializeCustomAttributes (); + + Range [] ranges; + if (!metadata.TryGetCustomAttributeRanges (owner, out ranges)) + return false; + + return RangesSize (ranges) > 0; + } + + public Collection ReadCustomAttributes (ICustomAttributeProvider owner) + { + InitializeCustomAttributes (); + + Range [] ranges; + if (!metadata.TryGetCustomAttributeRanges (owner, out ranges)) + return new Collection (); + + var custom_attributes = new Collection (RangesSize (ranges)); + + for (int i = 0; i < ranges.Length; i++) + ReadCustomAttributeRange (ranges [i], custom_attributes); + + metadata.RemoveCustomAttributeRange (owner); + + return custom_attributes; + } + + void ReadCustomAttributeRange (Range range, Collection custom_attributes) + { + if (!MoveTo (Table.CustomAttribute, range.Start)) + return; + + for (int i = 0; i < range.Length; i++) { + ReadMetadataToken (CodedIndex.HasCustomAttribute); + + var constructor = (MethodReference) LookupToken ( + ReadMetadataToken (CodedIndex.CustomAttributeType)); + + var signature = ReadBlobIndex (); + + custom_attributes.Add (new CustomAttribute (signature, constructor)); + } + } + + static int RangesSize (Range [] ranges) + { + uint size = 0; + for (int i = 0; i < ranges.Length; i++) + size += ranges [i].Length; + + return (int) size; + } + + public byte [] ReadCustomAttributeBlob (uint signature) + { + return ReadBlob (signature); + } + + public void ReadCustomAttributeSignature (CustomAttribute attribute) + { + var reader = ReadSignature (attribute.signature); + + if (!reader.CanReadMore ()) + return; + + if (reader.ReadUInt16 () != 0x0001) + throw new InvalidOperationException (); + + var constructor = attribute.Constructor; + if (constructor.HasParameters) + reader.ReadCustomAttributeConstructorArguments (attribute, constructor.Parameters); + + if (!reader.CanReadMore ()) + return; + + var named = reader.ReadUInt16 (); + + if (named == 0) + return; + + reader.ReadCustomAttributeNamedArguments (named, ref attribute.fields, ref attribute.properties); + } + + void InitializeMarshalInfos () + { + if (metadata.FieldMarshals != null) + return; + + var length = MoveTo (Table.FieldMarshal); + + var marshals = metadata.FieldMarshals = new Dictionary (length); + + for (int i = 0; i < length; i++) { + var token = ReadMetadataToken (CodedIndex.HasFieldMarshal); + var signature = ReadBlobIndex (); + if (token.RID == 0) + continue; + + marshals.Add (token, signature); + } + } + + public bool HasMarshalInfo (IMarshalInfoProvider owner) + { + InitializeMarshalInfos (); + + return metadata.FieldMarshals.ContainsKey (owner.MetadataToken); + } + + public MarshalInfo ReadMarshalInfo (IMarshalInfoProvider owner) + { + InitializeMarshalInfos (); + + uint signature; + if (!metadata.FieldMarshals.TryGetValue (owner.MetadataToken, out signature)) + return null; + + var reader = ReadSignature (signature); + + metadata.FieldMarshals.Remove (owner.MetadataToken); + + return reader.ReadMarshalInfo (); + } + + void InitializeSecurityDeclarations () + { + if (metadata.SecurityDeclarations != null) + return; + + metadata.SecurityDeclarations = InitializeRanges ( + Table.DeclSecurity, () => { + ReadUInt16 (); + var next = ReadMetadataToken (CodedIndex.HasDeclSecurity); + ReadBlobIndex (); + return next; + }); + } + + public bool HasSecurityDeclarations (ISecurityDeclarationProvider owner) + { + InitializeSecurityDeclarations (); + + Range [] ranges; + if (!metadata.TryGetSecurityDeclarationRanges (owner, out ranges)) + return false; + + return RangesSize (ranges) > 0; + } + + public Collection ReadSecurityDeclarations (ISecurityDeclarationProvider owner) + { + InitializeSecurityDeclarations (); + + Range [] ranges; + if (!metadata.TryGetSecurityDeclarationRanges (owner, out ranges)) + return new Collection (); + + var security_declarations = new Collection (RangesSize (ranges)); + + for (int i = 0; i < ranges.Length; i++) + ReadSecurityDeclarationRange (ranges [i], security_declarations); + + metadata.RemoveSecurityDeclarationRange (owner); + + return security_declarations; + } + + void ReadSecurityDeclarationRange (Range range, Collection security_declarations) + { + if (!MoveTo (Table.DeclSecurity, range.Start)) + return; + + for (int i = 0; i < range.Length; i++) { + var action = (SecurityAction) ReadUInt16 (); + ReadMetadataToken (CodedIndex.HasDeclSecurity); + var signature = ReadBlobIndex (); + + security_declarations.Add (new SecurityDeclaration (action, signature, module)); + } + } + + public byte [] ReadSecurityDeclarationBlob (uint signature) + { + return ReadBlob (signature); + } + + public void ReadSecurityDeclarationSignature (SecurityDeclaration declaration) + { + var signature = declaration.signature; + var reader = ReadSignature (signature); + + if (reader.buffer [reader.position] != '.') { + ReadXmlSecurityDeclaration (signature, declaration); + return; + } + + reader.position++; + var count = reader.ReadCompressedUInt32 (); + var attributes = new Collection ((int) count); + + for (int i = 0; i < count; i++) + attributes.Add (reader.ReadSecurityAttribute ()); + + declaration.security_attributes = attributes; + } + + void ReadXmlSecurityDeclaration (uint signature, SecurityDeclaration declaration) + { + var blob = ReadBlob (signature); + var attributes = new Collection (1); + + var attribute = new SecurityAttribute ( + module.TypeSystem.LookupType ("System.Security.Permissions", "PermissionSetAttribute")); + + attribute.properties = new Collection (1); + attribute.properties.Add ( + new CustomAttributeNamedArgument ( + "XML", + new CustomAttributeArgument ( + module.TypeSystem.String, + Encoding.Unicode.GetString (blob, 0, blob.Length)))); + + attributes.Add (attribute); + + declaration.security_attributes = attributes; + } + + public Collection ReadExportedTypes () + { + var length = MoveTo (Table.ExportedType); + if (length == 0) + return new Collection (); + + var exported_types = new Collection (length); + + for (int i = 1; i <= length; i++) { + var attributes = (TypeAttributes) ReadUInt32 (); + var identifier = ReadUInt32 (); + var name = ReadString (); + var @namespace = ReadString (); + var implementation = ReadMetadataToken (CodedIndex.Implementation); + + ExportedType declaring_type = null; + IMetadataScope scope = null; + + switch (implementation.TokenType) { + case TokenType.AssemblyRef: + case TokenType.File: + scope = GetExportedTypeScope (implementation); + break; + case TokenType.ExportedType: + // FIXME: if the table is not properly sorted + declaring_type = exported_types [(int) implementation.RID - 1]; + break; + } + + var exported_type = new ExportedType (@namespace, name, module, scope) { + Attributes = attributes, + Identifier = (int) identifier, + DeclaringType = declaring_type, + }; + exported_type.token = new MetadataToken (TokenType.ExportedType, i); + + exported_types.Add (exported_type); + } + + return exported_types; + } + + IMetadataScope GetExportedTypeScope (MetadataToken token) + { + var position = this.position; + IMetadataScope scope; + + switch (token.TokenType) { + case TokenType.AssemblyRef: + InitializeAssemblyReferences (); + scope = metadata.AssemblyReferences [(int) token.RID - 1]; + break; + case TokenType.File: + InitializeModuleReferences (); + scope = GetModuleReferenceFromFile (token); + break; + default: + throw new NotSupportedException (); + } + + this.position = position; + return scope; + } + + ModuleReference GetModuleReferenceFromFile (MetadataToken token) + { + if (!MoveTo (Table.File, token.RID)) + return null; + + ReadUInt32 (); + var file_name = ReadString (); + var modules = module.ModuleReferences; + + ModuleReference reference; + for (int i = 0; i < modules.Count; i++) { + reference = modules [i]; + if (reference.Name == file_name) + return reference; + } + + reference = new ModuleReference (file_name); + modules.Add (reference); + return reference; + } + + static void InitializeCollection (object o) + { + } + } + + sealed class SignatureReader : ByteBuffer { + + readonly MetadataReader reader; + readonly uint start, sig_length; + + TypeSystem TypeSystem { + get { return reader.module.TypeSystem; } + } + + public SignatureReader (uint blob, MetadataReader reader) + : base (reader.buffer) + { + this.reader = reader; + + MoveToBlob (blob); + + this.sig_length = ReadCompressedUInt32 (); + this.start = (uint) position; + } + + void MoveToBlob (uint blob) + { + position = (int) (reader.image.BlobHeap.Offset + blob); + } + + MetadataToken ReadTypeTokenSignature () + { + return CodedIndex.TypeDefOrRef.GetMetadataToken (ReadCompressedUInt32 ()); + } + + GenericParameter GetGenericParameter (GenericParameterType type, uint var) + { + var context = reader.context; + int index = (int) var; + + if (context == null) + return GetUnboundGenericParameter (type, index); + + IGenericParameterProvider provider; + + switch (type) { + case GenericParameterType.Type: + provider = context.Type; + break; + case GenericParameterType.Method: + provider = context.Method; + break; + default: + throw new NotSupportedException (); + } + + if (!context.IsDefinition) + CheckGenericContext (provider, index); + + if (index >= provider.GenericParameters.Count) + return GetUnboundGenericParameter (type, index); + + return provider.GenericParameters [index]; + } + + GenericParameter GetUnboundGenericParameter (GenericParameterType type, int index) + { + return new GenericParameter (index, type, reader.module); + } + + static void CheckGenericContext (IGenericParameterProvider owner, int index) + { + var owner_parameters = owner.GenericParameters; + + for (int i = owner_parameters.Count; i <= index; i++) + owner_parameters.Add (new GenericParameter (owner)); + } + + public void ReadGenericInstanceSignature (IGenericParameterProvider provider, IGenericInstance instance) + { + var arity = ReadCompressedUInt32 (); + + if (!provider.IsDefinition) + CheckGenericContext (provider, (int) arity - 1); + + var instance_arguments = instance.GenericArguments; + + for (int i = 0; i < arity; i++) + instance_arguments.Add (ReadTypeSignature ()); + } + + ArrayType ReadArrayTypeSignature () + { + var array = new ArrayType (ReadTypeSignature ()); + + var rank = ReadCompressedUInt32 (); + + var sizes = new uint [ReadCompressedUInt32 ()]; + for (int i = 0; i < sizes.Length; i++) + sizes [i] = ReadCompressedUInt32 (); + + var low_bounds = new int [ReadCompressedUInt32 ()]; + for (int i = 0; i < low_bounds.Length; i++) + low_bounds [i] = ReadCompressedInt32 (); + + array.Dimensions.Clear (); + + for (int i = 0; i < rank; i++) { + int? lower = null, upper = null; + + if (i < low_bounds.Length) + lower = low_bounds [i]; + + if (i < sizes.Length) + upper = lower + (int) sizes [i] - 1; + + array.Dimensions.Add (new ArrayDimension (lower, upper)); + } + + return array; + } + + TypeReference GetTypeDefOrRef (MetadataToken token) + { + return reader.GetTypeDefOrRef (token); + } + + public TypeReference ReadTypeSignature () + { + return ReadTypeSignature ((ElementType) ReadByte ()); + } + + TypeReference ReadTypeSignature (ElementType etype) + { + switch (etype) { + case ElementType.ValueType: { + var value_type = GetTypeDefOrRef (ReadTypeTokenSignature ()); + value_type.IsValueType = true; + return value_type; + } + case ElementType.Class: + return GetTypeDefOrRef (ReadTypeTokenSignature ()); + case ElementType.Ptr: + return new PointerType (ReadTypeSignature ()); + case ElementType.FnPtr: { + var fptr = new FunctionPointerType (); + ReadMethodSignature (fptr); + return fptr; + } + case ElementType.ByRef: + return new ByReferenceType (ReadTypeSignature ()); + case ElementType.Pinned: + return new PinnedType (ReadTypeSignature ()); + case ElementType.SzArray: + return new ArrayType (ReadTypeSignature ()); + case ElementType.Array: + return ReadArrayTypeSignature (); + case ElementType.CModOpt: + return new OptionalModifierType ( + GetTypeDefOrRef (ReadTypeTokenSignature ()), ReadTypeSignature ()); + case ElementType.CModReqD: + return new RequiredModifierType ( + GetTypeDefOrRef (ReadTypeTokenSignature ()), ReadTypeSignature ()); + case ElementType.Sentinel: + return new SentinelType (ReadTypeSignature ()); + case ElementType.Var: + return GetGenericParameter (GenericParameterType.Type, ReadCompressedUInt32 ()); + case ElementType.MVar: + return GetGenericParameter (GenericParameterType.Method, ReadCompressedUInt32 ()); + case ElementType.GenericInst: { + var is_value_type = ReadByte () == (byte) ElementType.ValueType; + var element_type = GetTypeDefOrRef (ReadTypeTokenSignature ()); + var generic_instance = new GenericInstanceType (element_type); + + ReadGenericInstanceSignature (element_type, generic_instance); + + if (is_value_type) { + generic_instance.IsValueType = true; + element_type.GetElementType ().IsValueType = true; + } + + return generic_instance; + } + case ElementType.Object: return TypeSystem.Object; + case ElementType.Void: return TypeSystem.Void; + case ElementType.TypedByRef: return TypeSystem.TypedReference; + case ElementType.I: return TypeSystem.IntPtr; + case ElementType.U: return TypeSystem.UIntPtr; + default: return GetPrimitiveType (etype); + } + } + + public void ReadMethodSignature (IMethodSignature method) + { + var calling_convention = ReadByte (); + + const byte has_this = 0x20; + const byte explicit_this = 0x40; + + if ((calling_convention & has_this) != 0) { + method.HasThis = true; + calling_convention = (byte) (calling_convention & ~has_this); + } + + if ((calling_convention & explicit_this) != 0) { + method.ExplicitThis = true; + calling_convention = (byte) (calling_convention & ~explicit_this); + } + + method.CallingConvention = (MethodCallingConvention) calling_convention; + + var generic_context = method as MethodReference; + if (generic_context != null && !generic_context.DeclaringType.IsArray) + reader.context = generic_context; + + if ((calling_convention & 0x10) != 0) { + var arity = ReadCompressedUInt32 (); + + if (generic_context != null && !generic_context.IsDefinition) + CheckGenericContext (generic_context, (int) arity -1 ); + } + + var param_count = ReadCompressedUInt32 (); + + method.MethodReturnType.ReturnType = ReadTypeSignature (); + + if (param_count == 0) + return; + + Collection parameters; + + var method_ref = method as MethodReference; + if (method_ref != null) + parameters = method_ref.parameters = new ParameterDefinitionCollection (method, (int) param_count); + else + parameters = method.Parameters; + + for (int i = 0; i < param_count; i++) + parameters.Add (new ParameterDefinition (ReadTypeSignature ())); + } + + public object ReadConstantSignature (ElementType type) + { + return ReadPrimitiveValue (type); + } + + public void ReadCustomAttributeConstructorArguments (CustomAttribute attribute, Collection parameters) + { + var count = parameters.Count; + if (count == 0) + return; + + attribute.arguments = new Collection (count); + + for (int i = 0; i < count; i++) + attribute.arguments.Add ( + ReadCustomAttributeFixedArgument (parameters [i].ParameterType)); + } + + CustomAttributeArgument ReadCustomAttributeFixedArgument (TypeReference type) + { + if (type.IsArray) + return ReadCustomAttributeFixedArrayArgument ((ArrayType) type); + + return ReadCustomAttributeElement (type); + } + + public void ReadCustomAttributeNamedArguments (ushort count, ref Collection fields, ref Collection properties) + { + for (int i = 0; i < count; i++) + ReadCustomAttributeNamedArgument (ref fields, ref properties); + } + + void ReadCustomAttributeNamedArgument (ref Collection fields, ref Collection properties) + { + var kind = ReadByte (); + var type = ReadCustomAttributeFieldOrPropType (); + var name = ReadUTF8String (); + + Collection container; + switch (kind) { + case 0x53: + container = GetCustomAttributeNamedArgumentCollection (ref fields); + break; + case 0x54: + container = GetCustomAttributeNamedArgumentCollection (ref properties); + break; + default: + throw new NotSupportedException (); + } + + container.Add (new CustomAttributeNamedArgument (name, ReadCustomAttributeFixedArgument (type))); + } + + static Collection GetCustomAttributeNamedArgumentCollection (ref Collection collection) + { + if (collection != null) + return collection; + + return collection = new Collection (); + } + + CustomAttributeArgument ReadCustomAttributeFixedArrayArgument (ArrayType type) + { + var length = ReadUInt32 (); + + if (length == 0xffffffff) + return new CustomAttributeArgument (type, null); + + if (length == 0) + return new CustomAttributeArgument (type, Empty.Array); + + var arguments = new CustomAttributeArgument [length]; + var element_type = type.ElementType; + + for (int i = 0; i < length; i++) + arguments [i] = ReadCustomAttributeElement (element_type); + + return new CustomAttributeArgument (type, arguments); + } + + CustomAttributeArgument ReadCustomAttributeElement (TypeReference type) + { + if (type.IsArray) + return ReadCustomAttributeFixedArrayArgument ((ArrayType) type); + + return new CustomAttributeArgument ( + type, + type.etype == ElementType.Object + ? ReadCustomAttributeElement (ReadCustomAttributeFieldOrPropType ()) + : ReadCustomAttributeElementValue (type)); + } + + object ReadCustomAttributeElementValue (TypeReference type) + { + var etype = type.etype; + + switch (etype) { + case ElementType.String: + return ReadUTF8String (); + case ElementType.None: + if (type.IsTypeOf ("System", "Type")) + return ReadTypeReference (); + + return ReadCustomAttributeEnum (type); + default: + return ReadPrimitiveValue (etype); + } + } + + object ReadPrimitiveValue (ElementType type) + { + switch (type) { + case ElementType.Boolean: + return ReadByte () == 1; + case ElementType.I1: + return (sbyte) ReadByte (); + case ElementType.U1: + return ReadByte (); + case ElementType.Char: + return (char) ReadUInt16 (); + case ElementType.I2: + return ReadInt16 (); + case ElementType.U2: + return ReadUInt16 (); + case ElementType.I4: + return ReadInt32 (); + case ElementType.U4: + return ReadUInt32 (); + case ElementType.I8: + return ReadInt64 (); + case ElementType.U8: + return ReadUInt64 (); + case ElementType.R4: + return ReadSingle (); + case ElementType.R8: + return ReadDouble (); + default: + throw new NotImplementedException (type.ToString ()); + } + } + + TypeReference GetPrimitiveType (ElementType etype) + { + switch (etype) { + case ElementType.Boolean: + return TypeSystem.Boolean; + case ElementType.Char: + return TypeSystem.Char; + case ElementType.I1: + return TypeSystem.SByte; + case ElementType.U1: + return TypeSystem.Byte; + case ElementType.I2: + return TypeSystem.Int16; + case ElementType.U2: + return TypeSystem.UInt16; + case ElementType.I4: + return TypeSystem.Int32; + case ElementType.U4: + return TypeSystem.UInt32; + case ElementType.I8: + return TypeSystem.Int64; + case ElementType.U8: + return TypeSystem.UInt64; + case ElementType.R4: + return TypeSystem.Single; + case ElementType.R8: + return TypeSystem.Double; + case ElementType.String: + return TypeSystem.String; + default: + throw new NotImplementedException (etype.ToString ()); + } + } + + TypeReference ReadCustomAttributeFieldOrPropType () + { + var etype = (ElementType) ReadByte (); + + switch (etype) { + case ElementType.Boxed: + return TypeSystem.Object; + case ElementType.SzArray: + return new ArrayType (ReadCustomAttributeFieldOrPropType ()); + case ElementType.Enum: + return ReadTypeReference (); + case ElementType.Type: + return TypeSystem.LookupType ("System", "Type"); + default: + return GetPrimitiveType (etype); + } + } + + string UnescapeTypeName (string name) + { + StringBuilder sb = new StringBuilder (name.Length); + for (int i = 0; i < name.Length; i++) { + char c = name [i]; + if (name [i] == '\\') { + if ((i < name.Length - 1) && (name [i + 1] == '\\')) { + sb.Append (c); + i++; + } + } else { + sb.Append (c); + } + } + return sb.ToString (); + } + + public TypeReference ReadTypeReference () + { + string s = ReadUTF8String (); + if (s != null && s.IndexOf ('\\') != -1) + s = UnescapeTypeName (s); + return TypeParser.ParseType (reader.module, s); + } + + object ReadCustomAttributeEnum (TypeReference enum_type) + { + var type = enum_type.CheckedResolve (); + if (!type.IsEnum) + throw new ArgumentException (); + + return ReadCustomAttributeElementValue (type.GetEnumUnderlyingType ()); + } + + public SecurityAttribute ReadSecurityAttribute () + { + var attribute = new SecurityAttribute (ReadTypeReference ()); + + ReadCompressedUInt32 (); + + ReadCustomAttributeNamedArguments ( + (ushort) ReadCompressedUInt32 (), + ref attribute.fields, + ref attribute.properties); + + return attribute; + } + + public MarshalInfo ReadMarshalInfo () + { + var native = ReadNativeType (); + switch (native) { + case NativeType.Array: { + var array = new ArrayMarshalInfo (); + if (CanReadMore ()) + array.element_type = ReadNativeType (); + if (CanReadMore ()) + array.size_parameter_index = (int) ReadCompressedUInt32 (); + if (CanReadMore ()) + array.size = (int) ReadCompressedUInt32 (); + if (CanReadMore ()) + array.size_parameter_multiplier = (int) ReadCompressedUInt32 (); + return array; + } + case NativeType.SafeArray: { + var array = new SafeArrayMarshalInfo (); + if (CanReadMore ()) + array.element_type = ReadVariantType (); + return array; + } + case NativeType.FixedArray: { + var array = new FixedArrayMarshalInfo (); + if (CanReadMore ()) + array.size = (int) ReadCompressedUInt32 (); + if (CanReadMore ()) + array.element_type = ReadNativeType (); + return array; + } + case NativeType.FixedSysString: { + var sys_string = new FixedSysStringMarshalInfo (); + if (CanReadMore ()) + sys_string.size = (int) ReadCompressedUInt32 (); + return sys_string; + } + case NativeType.CustomMarshaler: { + var marshaler = new CustomMarshalInfo (); + var guid_value = ReadUTF8String (); + marshaler.guid = !string.IsNullOrEmpty (guid_value) ? new Guid (guid_value) : Guid.Empty; + marshaler.unmanaged_type = ReadUTF8String (); + marshaler.managed_type = ReadTypeReference (); + marshaler.cookie = ReadUTF8String (); + return marshaler; + } + default: + return new MarshalInfo (native); + } + } + + NativeType ReadNativeType () + { + return (NativeType) ReadByte (); + } + + VariantType ReadVariantType () + { + return (VariantType) ReadByte (); + } + + string ReadUTF8String () + { + if (buffer [position] == 0xff) { + position++; + return null; + } + + var length = (int) ReadCompressedUInt32 (); + if (length == 0) + return string.Empty; + + var @string = Encoding.UTF8.GetString (buffer, position, + buffer [position + length - 1] == 0 ? length - 1 : length); + + position += length; + return @string; + } + + public bool CanReadMore () + { + return position - start < sig_length; + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil/AssemblyWriter.cs b/external/cecil-legacy/Mono.Cecil/AssemblyWriter.cs new file mode 100644 index 0000000000..f1026eed0d --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/AssemblyWriter.cs @@ -0,0 +1,2576 @@ +// +// AssemblyWriter.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + +using Mono.Collections.Generic; +using Mono.Cecil.Cil; +using Mono.Cecil.Metadata; +using Mono.Cecil.PE; + +using RVA = System.UInt32; +using RID = System.UInt32; +using CodedRID = System.UInt32; +using StringIndex = System.UInt32; +using BlobIndex = System.UInt32; + +namespace Mono.Cecil { + +#if !READ_ONLY + + using TypeRefRow = Row; + using TypeDefRow = Row; + using FieldRow = Row; + using MethodRow = Row; + using ParamRow = Row; + using InterfaceImplRow = Row; + using MemberRefRow = Row; + using ConstantRow = Row; + using CustomAttributeRow = Row; + using FieldMarshalRow = Row; + using DeclSecurityRow = Row; + using ClassLayoutRow = Row; + using FieldLayoutRow = Row; + using EventMapRow = Row; + using EventRow = Row; + using PropertyMapRow = Row; + using PropertyRow = Row; + using MethodSemanticsRow = Row; + using MethodImplRow = Row; + using ImplMapRow = Row; + using FieldRVARow = Row; + using AssemblyRow = Row; + using AssemblyRefRow = Row; + using FileRow = Row; + using ExportedTypeRow = Row; + using ManifestResourceRow = Row; + using NestedClassRow = Row; + using GenericParamRow = Row; + using MethodSpecRow = Row; + using GenericParamConstraintRow = Row; + + static class ModuleWriter { + + public static void WriteModuleTo (ModuleDefinition module, Stream stream, WriterParameters parameters) + { + if ((module.Attributes & ModuleAttributes.ILOnly) == 0) + throw new NotSupportedException ("Writing mixed-mode assemblies is not supported"); + + if (module.HasImage && module.ReadingMode == ReadingMode.Deferred) + ImmediateModuleReader.ReadModule (module); + + module.MetadataSystem.Clear (); + + var name = module.assembly != null ? module.assembly.Name : null; + var fq_name = stream.GetFullyQualifiedName (); + var symbol_writer_provider = parameters.SymbolWriterProvider; + if (symbol_writer_provider == null && parameters.WriteSymbols) + symbol_writer_provider = SymbolProvider.GetPlatformWriterProvider (); + var symbol_writer = GetSymbolWriter (module, fq_name, symbol_writer_provider); + +#if !SILVERLIGHT && !CF + if (parameters.StrongNameKeyPair != null && name != null) { + name.PublicKey = parameters.StrongNameKeyPair.PublicKey; + module.Attributes |= ModuleAttributes.StrongNameSigned; + } +#endif + var metadata = new MetadataBuilder (module, fq_name, + symbol_writer_provider, symbol_writer); + + BuildMetadata (module, metadata); + + if (module.symbol_reader != null) + module.symbol_reader.Dispose (); + + var writer = ImageWriter.CreateWriter (module, metadata, stream); + + writer.WriteImage (); + +#if !SILVERLIGHT && !CF + if (parameters.StrongNameKeyPair != null) + CryptoService.StrongName (stream, writer, parameters.StrongNameKeyPair); +#endif + if (symbol_writer != null) + symbol_writer.Dispose (); + } + + static void BuildMetadata (ModuleDefinition module, MetadataBuilder metadata) + { + if (!module.HasImage) { + metadata.BuildMetadata (); + return; + } + + module.Read (metadata, (builder, _) => { + builder.BuildMetadata (); + return builder; + }); + } + + static ISymbolWriter GetSymbolWriter (ModuleDefinition module, string fq_name, ISymbolWriterProvider symbol_writer_provider) + { + if (symbol_writer_provider == null) + return null; + + return symbol_writer_provider.GetSymbolWriter (module, fq_name); + } + } + + abstract class MetadataTable { + + public abstract int Length { get; } + + public bool IsLarge { + get { return Length > 65535; } + } + + public abstract void Write (TableHeapBuffer buffer); + public abstract void Sort (); + } + + abstract class OneRowTable : MetadataTable where TRow : struct { + + internal TRow row; + + public sealed override int Length { + get { return 1; } + } + + public sealed override void Sort () + { + } + } + + abstract class MetadataTable : MetadataTable where TRow : struct { + + internal TRow [] rows = new TRow [2]; + internal int length; + + public sealed override int Length { + get { return length; } + } + + public int AddRow (TRow row) + { + if (rows.Length == length) + Grow (); + + rows [length++] = row; + return length; + } + + void Grow () + { + var rows = new TRow [this.rows.Length * 2]; + Array.Copy (this.rows, rows, this.rows.Length); + this.rows = rows; + } + + public override void Sort () + { + } + } + + abstract class SortedTable : MetadataTable, IComparer where TRow : struct { + + public sealed override void Sort () + { + Array.Sort (rows, 0, length, this); + } + + protected int Compare (uint x, uint y) + { + return x == y ? 0 : x > y ? 1 : -1; + } + + public abstract int Compare (TRow x, TRow y); + } + + sealed class ModuleTable : OneRowTable { + + public override void Write (TableHeapBuffer buffer) + { + buffer.WriteUInt16 (0); // Generation + buffer.WriteString (row); // Name + buffer.WriteUInt16 (1); // Mvid + buffer.WriteUInt16 (0); // EncId + buffer.WriteUInt16 (0); // EncBaseId + } + } + + sealed class TypeRefTable : MetadataTable { + + public override void Write (TableHeapBuffer buffer) + { + for (int i = 0; i < length; i++) { + buffer.WriteCodedRID ( + rows [i].Col1, CodedIndex.ResolutionScope); // Scope + buffer.WriteString (rows [i].Col2); // Name + buffer.WriteString (rows [i].Col3); // Namespace + } + } + } + + sealed class TypeDefTable : MetadataTable { + + public override void Write (TableHeapBuffer buffer) + { + for (int i = 0; i < length; i++) { + buffer.WriteUInt32 ((uint) rows [i].Col1); // Attributes + buffer.WriteString (rows [i].Col2); // Name + buffer.WriteString (rows [i].Col3); // Namespace + buffer.WriteCodedRID ( + rows [i].Col4, CodedIndex.TypeDefOrRef); // Extends + buffer.WriteRID (rows [i].Col5, Table.Field); // FieldList + buffer.WriteRID (rows [i].Col6, Table.Method); // MethodList + } + } + } + + sealed class FieldTable : MetadataTable { + + public override void Write (TableHeapBuffer buffer) + { + for (int i = 0; i < length; i++) { + buffer.WriteUInt16 ((ushort) rows [i].Col1); // Attributes + buffer.WriteString (rows [i].Col2); // Name + buffer.WriteBlob (rows [i].Col3); // Signature + } + } + } + + sealed class MethodTable : MetadataTable { + + public override void Write (TableHeapBuffer buffer) + { + for (int i = 0; i < length; i++) { + buffer.WriteUInt32 (rows [i].Col1); // RVA + buffer.WriteUInt16 ((ushort) rows [i].Col2); // ImplFlags + buffer.WriteUInt16 ((ushort) rows [i].Col3); // Flags + buffer.WriteString (rows [i].Col4); // Name + buffer.WriteBlob (rows [i].Col5); // Signature + buffer.WriteRID (rows [i].Col6, Table.Param); // ParamList + } + } + } + + sealed class ParamTable : MetadataTable { + + public override void Write (TableHeapBuffer buffer) + { + for (int i = 0; i < length; i++) { + buffer.WriteUInt16 ((ushort) rows [i].Col1); // Attributes + buffer.WriteUInt16 (rows [i].Col2); // Sequence + buffer.WriteString (rows [i].Col3); // Name + } + } + } + + sealed class InterfaceImplTable : MetadataTable { + + public override void Write (TableHeapBuffer buffer) + { + for (int i = 0; i < length; i++) { + buffer.WriteRID (rows [i].Col1, Table.TypeDef); // Class + buffer.WriteCodedRID (rows [i].Col2, CodedIndex.TypeDefOrRef); // Interface + } + } + + /*public override int Compare (InterfaceImplRow x, InterfaceImplRow y) + { + return (int) (x.Col1 == y.Col1 ? y.Col2 - x.Col2 : x.Col1 - y.Col1); + }*/ + } + + sealed class MemberRefTable : MetadataTable { + + public override void Write (TableHeapBuffer buffer) + { + for (int i = 0; i < length; i++) { + buffer.WriteCodedRID (rows [i].Col1, CodedIndex.MemberRefParent); + buffer.WriteString (rows [i].Col2); + buffer.WriteBlob (rows [i].Col3); + } + } + } + + sealed class ConstantTable : SortedTable { + + public override void Write (TableHeapBuffer buffer) + { + for (int i = 0; i < length; i++) { + buffer.WriteUInt16 ((ushort) rows [i].Col1); + buffer.WriteCodedRID (rows [i].Col2, CodedIndex.HasConstant); + buffer.WriteBlob (rows [i].Col3); + } + } + + public override int Compare (ConstantRow x, ConstantRow y) + { + return Compare (x.Col2, y.Col2); + } + } + + sealed class CustomAttributeTable : SortedTable { + + public override void Write (TableHeapBuffer buffer) + { + for (int i = 0; i < length; i++) { + buffer.WriteCodedRID (rows [i].Col1, CodedIndex.HasCustomAttribute); // Parent + buffer.WriteCodedRID (rows [i].Col2, CodedIndex.CustomAttributeType); // Type + buffer.WriteBlob (rows [i].Col3); + } + } + + public override int Compare (CustomAttributeRow x, CustomAttributeRow y) + { + return Compare (x.Col1, y.Col1); + } + } + + sealed class FieldMarshalTable : SortedTable { + + public override void Write (TableHeapBuffer buffer) + { + for (int i = 0; i < length; i++) { + buffer.WriteCodedRID (rows [i].Col1, CodedIndex.HasFieldMarshal); + buffer.WriteBlob (rows [i].Col2); + } + } + + public override int Compare (FieldMarshalRow x, FieldMarshalRow y) + { + return Compare (x.Col1, y.Col1); + } + } + + sealed class DeclSecurityTable : SortedTable { + + public override void Write (TableHeapBuffer buffer) + { + for (int i = 0; i < length; i++) { + buffer.WriteUInt16 ((ushort) rows [i].Col1); + buffer.WriteCodedRID (rows [i].Col2, CodedIndex.HasDeclSecurity); + buffer.WriteBlob (rows [i].Col3); + } + } + + public override int Compare (DeclSecurityRow x, DeclSecurityRow y) + { + return Compare (x.Col2, y.Col2); + } + } + + sealed class ClassLayoutTable : SortedTable { + + public override void Write (TableHeapBuffer buffer) + { + for (int i = 0; i < length; i++) { + buffer.WriteUInt16 (rows [i].Col1); // PackingSize + buffer.WriteUInt32 (rows [i].Col2); // ClassSize + buffer.WriteRID (rows [i].Col3, Table.TypeDef); // Parent + } + } + + public override int Compare (ClassLayoutRow x, ClassLayoutRow y) + { + return Compare (x.Col3, y.Col3); + } + } + + sealed class FieldLayoutTable : SortedTable { + + public override void Write (TableHeapBuffer buffer) + { + for (int i = 0; i < length; i++) { + buffer.WriteUInt32 (rows [i].Col1); // Offset + buffer.WriteRID (rows [i].Col2, Table.Field); // Parent + } + } + + public override int Compare (FieldLayoutRow x, FieldLayoutRow y) + { + return Compare (x.Col2, y.Col2); + } + } + + sealed class StandAloneSigTable : MetadataTable { + + public override void Write (TableHeapBuffer buffer) + { + for (int i = 0; i < length; i++) + buffer.WriteBlob (rows [i]); + } + } + + sealed class EventMapTable : MetadataTable { + + public override void Write (TableHeapBuffer buffer) + { + for (int i = 0; i < length; i++) { + buffer.WriteRID (rows [i].Col1, Table.TypeDef); // Parent + buffer.WriteRID (rows [i].Col2, Table.Event); // EventList + } + } + } + + sealed class EventTable : MetadataTable { + + public override void Write (TableHeapBuffer buffer) + { + for (int i = 0; i < length; i++) { + buffer.WriteUInt16 ((ushort) rows [i].Col1); // Flags + buffer.WriteString (rows [i].Col2); // Name + buffer.WriteCodedRID (rows [i].Col3, CodedIndex.TypeDefOrRef); // EventType + } + } + } + + sealed class PropertyMapTable : MetadataTable { + + public override void Write (TableHeapBuffer buffer) + { + for (int i = 0; i < length; i++) { + buffer.WriteRID (rows [i].Col1, Table.TypeDef); // Parent + buffer.WriteRID (rows [i].Col2, Table.Property); // PropertyList + } + } + } + + sealed class PropertyTable : MetadataTable { + + public override void Write (TableHeapBuffer buffer) + { + for (int i = 0; i < length; i++) { + buffer.WriteUInt16 ((ushort) rows [i].Col1); // Flags + buffer.WriteString (rows [i].Col2); // Name + buffer.WriteBlob (rows [i].Col3); // Type + } + } + } + + sealed class MethodSemanticsTable : SortedTable { + + public override void Write (TableHeapBuffer buffer) + { + for (int i = 0; i < length; i++) { + buffer.WriteUInt16 ((ushort) rows [i].Col1); // Flags + buffer.WriteRID (rows [i].Col2, Table.Method); // Method + buffer.WriteCodedRID (rows [i].Col3, CodedIndex.HasSemantics); // Association + } + } + + public override int Compare (MethodSemanticsRow x, MethodSemanticsRow y) + { + return Compare (x.Col3, y.Col3); + } + } + + sealed class MethodImplTable : MetadataTable { + + public override void Write (TableHeapBuffer buffer) + { + for (int i = 0; i < length; i++) { + buffer.WriteRID (rows [i].Col1, Table.TypeDef); // Class + buffer.WriteCodedRID (rows [i].Col2, CodedIndex.MethodDefOrRef); // MethodBody + buffer.WriteCodedRID (rows [i].Col3, CodedIndex.MethodDefOrRef); // MethodDeclaration + } + } + } + + sealed class ModuleRefTable : MetadataTable { + + public override void Write (TableHeapBuffer buffer) + { + for (int i = 0; i < length; i++) + buffer.WriteString (rows [i]); // Name + } + } + + sealed class TypeSpecTable : MetadataTable { + + public override void Write (TableHeapBuffer buffer) + { + for (int i = 0; i < length; i++) + buffer.WriteBlob (rows [i]); // Signature + } + } + + sealed class ImplMapTable : SortedTable { + + public override void Write (TableHeapBuffer buffer) + { + for (int i = 0; i < length; i++) { + buffer.WriteUInt16 ((ushort) rows [i].Col1); // Flags + buffer.WriteCodedRID (rows [i].Col2, CodedIndex.MemberForwarded); // MemberForwarded + buffer.WriteString (rows [i].Col3); // ImportName + buffer.WriteRID (rows [i].Col4, Table.ModuleRef); // ImportScope + } + } + + public override int Compare (ImplMapRow x, ImplMapRow y) + { + return Compare (x.Col2, y.Col2); + } + } + + sealed class FieldRVATable : SortedTable { + + internal int position; + + public override void Write (TableHeapBuffer buffer) + { + position = buffer.position; + for (int i = 0; i < length; i++) { + buffer.WriteUInt32 (rows [i].Col1); // RVA + buffer.WriteRID (rows [i].Col2, Table.Field); // Field + } + } + + public override int Compare (FieldRVARow x, FieldRVARow y) + { + return Compare (x.Col2, y.Col2); + } + } + + sealed class AssemblyTable : OneRowTable { + + public override void Write (TableHeapBuffer buffer) + { + buffer.WriteUInt32 ((uint) row.Col1); // AssemblyHashAlgorithm + buffer.WriteUInt16 (row.Col2); // MajorVersion + buffer.WriteUInt16 (row.Col3); // MinorVersion + buffer.WriteUInt16 (row.Col4); // Build + buffer.WriteUInt16 (row.Col5); // Revision + buffer.WriteUInt32 ((uint) row.Col6); // Flags + buffer.WriteBlob (row.Col7); // PublicKey + buffer.WriteString (row.Col8); // Name + buffer.WriteString (row.Col9); // Culture + } + } + + sealed class AssemblyRefTable : MetadataTable { + + public override void Write (TableHeapBuffer buffer) + { + for (int i = 0; i < length; i++) { + buffer.WriteUInt16 (rows [i].Col1); // MajorVersion + buffer.WriteUInt16 (rows [i].Col2); // MinorVersion + buffer.WriteUInt16 (rows [i].Col3); // Build + buffer.WriteUInt16 (rows [i].Col4); // Revision + buffer.WriteUInt32 ((uint) rows [i].Col5); // Flags + buffer.WriteBlob (rows [i].Col6); // PublicKeyOrToken + buffer.WriteString (rows [i].Col7); // Name + buffer.WriteString (rows [i].Col8); // Culture + buffer.WriteBlob (rows [i].Col9); // Hash + } + } + } + + sealed class FileTable : MetadataTable { + + public override void Write (TableHeapBuffer buffer) + { + for (int i = 0; i < length; i++) { + buffer.WriteUInt32 ((uint) rows [i].Col1); + buffer.WriteString (rows [i].Col2); + buffer.WriteBlob (rows [i].Col3); + } + } + } + + sealed class ExportedTypeTable : MetadataTable { + + public override void Write (TableHeapBuffer buffer) + { + for (int i = 0; i < length; i++) { + buffer.WriteUInt32 ((uint) rows [i].Col1); + buffer.WriteUInt32 (rows [i].Col2); + buffer.WriteString (rows [i].Col3); + buffer.WriteString (rows [i].Col4); + buffer.WriteCodedRID (rows [i].Col5, CodedIndex.Implementation); + } + } + } + + sealed class ManifestResourceTable : MetadataTable { + + public override void Write (TableHeapBuffer buffer) + { + for (int i = 0; i < length; i++) { + buffer.WriteUInt32 (rows [i].Col1); + buffer.WriteUInt32 ((uint) rows [i].Col2); + buffer.WriteString (rows [i].Col3); + buffer.WriteCodedRID (rows [i].Col4, CodedIndex.Implementation); + } + } + } + + sealed class NestedClassTable : SortedTable { + + public override void Write (TableHeapBuffer buffer) + { + for (int i = 0; i < length; i++) { + buffer.WriteRID (rows [i].Col1, Table.TypeDef); // NestedClass + buffer.WriteRID (rows [i].Col2, Table.TypeDef); // EnclosingClass + } + } + + public override int Compare (NestedClassRow x, NestedClassRow y) + { + return Compare (x.Col1, y.Col1); + } + } + + sealed class GenericParamTable : MetadataTable { + + public override void Write (TableHeapBuffer buffer) + { + for (int i = 0; i < length; i++) { + buffer.WriteUInt16 (rows [i].Col1); // Number + buffer.WriteUInt16 ((ushort) rows [i].Col2); // Flags + buffer.WriteCodedRID (rows [i].Col3, CodedIndex.TypeOrMethodDef); // Owner + buffer.WriteString (rows [i].Col4); // Name + } + } + } + + sealed class MethodSpecTable : MetadataTable { + + public override void Write (TableHeapBuffer buffer) + { + for (int i = 0; i < length; i++) { + buffer.WriteCodedRID (rows [i].Col1, CodedIndex.MethodDefOrRef); // Method + buffer.WriteBlob (rows [i].Col2); // Instantiation + } + } + } + + sealed class GenericParamConstraintTable : MetadataTable { + + public override void Write (TableHeapBuffer buffer) + { + for (int i = 0; i < length; i++) { + buffer.WriteRID (rows [i].Col1, Table.GenericParam); // Owner + buffer.WriteCodedRID (rows [i].Col2, CodedIndex.TypeDefOrRef); // Constraint + } + } + } + + sealed class MetadataBuilder { + + readonly internal ModuleDefinition module; + readonly internal ISymbolWriterProvider symbol_writer_provider; + readonly internal ISymbolWriter symbol_writer; + readonly internal TextMap text_map; + readonly internal string fq_name; + + readonly Dictionary type_ref_map; + readonly Dictionary type_spec_map; + readonly Dictionary member_ref_map; + readonly Dictionary method_spec_map; + readonly Collection generic_parameters; + readonly Dictionary method_def_map; + + readonly internal CodeWriter code; + readonly internal DataBuffer data; + readonly internal ResourceBuffer resources; + readonly internal StringHeapBuffer string_heap; + readonly internal UserStringHeapBuffer user_string_heap; + readonly internal BlobHeapBuffer blob_heap; + readonly internal TableHeapBuffer table_heap; + + internal MetadataToken entry_point; + + RID type_rid = 1; + RID field_rid = 1; + RID method_rid = 1; + RID param_rid = 1; + RID property_rid = 1; + RID event_rid = 1; + + readonly TypeRefTable type_ref_table; + readonly TypeDefTable type_def_table; + readonly FieldTable field_table; + readonly MethodTable method_table; + readonly ParamTable param_table; + readonly InterfaceImplTable iface_impl_table; + readonly MemberRefTable member_ref_table; + readonly ConstantTable constant_table; + readonly CustomAttributeTable custom_attribute_table; + readonly DeclSecurityTable declsec_table; + readonly StandAloneSigTable standalone_sig_table; + readonly EventMapTable event_map_table; + readonly EventTable event_table; + readonly PropertyMapTable property_map_table; + readonly PropertyTable property_table; + readonly TypeSpecTable typespec_table; + readonly MethodSpecTable method_spec_table; + + readonly internal bool write_symbols; + + public MetadataBuilder (ModuleDefinition module, string fq_name, ISymbolWriterProvider symbol_writer_provider, ISymbolWriter symbol_writer) + { + this.module = module; + this.text_map = CreateTextMap (); + this.fq_name = fq_name; + this.symbol_writer_provider = symbol_writer_provider; + this.symbol_writer = symbol_writer; + this.write_symbols = symbol_writer != null; + this.code = new CodeWriter (this); + this.data = new DataBuffer (); + this.resources = new ResourceBuffer (); + this.string_heap = new StringHeapBuffer (); + this.user_string_heap = new UserStringHeapBuffer (); + this.blob_heap = new BlobHeapBuffer (); + this.table_heap = new TableHeapBuffer (module, this); + + this.type_ref_table = GetTable (Table.TypeRef); + this.type_def_table = GetTable (Table.TypeDef); + this.field_table = GetTable (Table.Field); + this.method_table = GetTable (Table.Method); + this.param_table = GetTable (Table.Param); + this.iface_impl_table = GetTable (Table.InterfaceImpl); + this.member_ref_table = GetTable (Table.MemberRef); + this.constant_table = GetTable (Table.Constant); + this.custom_attribute_table = GetTable (Table.CustomAttribute); + this.declsec_table = GetTable (Table.DeclSecurity); + this.standalone_sig_table = GetTable (Table.StandAloneSig); + this.event_map_table = GetTable (Table.EventMap); + this.event_table = GetTable (Table.Event); + this.property_map_table = GetTable (Table.PropertyMap); + this.property_table = GetTable (Table.Property); + this.typespec_table = GetTable (Table.TypeSpec); + this.method_spec_table = GetTable (Table.MethodSpec); + + var row_equality_comparer = new RowEqualityComparer (); + type_ref_map = new Dictionary (row_equality_comparer); + type_spec_map = new Dictionary (); + member_ref_map = new Dictionary (row_equality_comparer); + method_spec_map = new Dictionary (row_equality_comparer); + generic_parameters = new Collection (); + if (write_symbols) + method_def_map = new Dictionary (); + } + + TextMap CreateTextMap () + { + var map = new TextMap (); + map.AddMap (TextSegment.ImportAddressTable, module.Architecture == TargetArchitecture.I386 ? 8 : 0); + map.AddMap (TextSegment.CLIHeader, 0x48, 8); + return map; + } + + TTable GetTable (Table table) where TTable : MetadataTable, new () + { + return table_heap.GetTable (table); + } + + uint GetStringIndex (string @string) + { + if (string.IsNullOrEmpty (@string)) + return 0; + + return string_heap.GetStringIndex (@string); + } + + uint GetBlobIndex (ByteBuffer blob) + { + if (blob.length == 0) + return 0; + + return blob_heap.GetBlobIndex (blob); + } + + uint GetBlobIndex (byte [] blob) + { + if (blob.IsNullOrEmpty ()) + return 0; + + return GetBlobIndex (new ByteBuffer (blob)); + } + + public void BuildMetadata () + { + BuildModule (); + + table_heap.WriteTableHeap (); + } + + void BuildModule () + { + var table = GetTable (Table.Module); + table.row = GetStringIndex (module.Name); + + var assembly = module.Assembly; + + if (assembly != null) + BuildAssembly (); + + if (module.HasAssemblyReferences) + AddAssemblyReferences (); + + if (module.HasModuleReferences) + AddModuleReferences (); + + if (module.HasResources) + AddResources (); + + if (module.HasExportedTypes) + AddExportedTypes (); + + BuildTypes (); + + if (assembly != null) { + if (assembly.HasCustomAttributes) + AddCustomAttributes (assembly); + + if (assembly.HasSecurityDeclarations) + AddSecurityDeclarations (assembly); + } + + if (module.HasCustomAttributes) + AddCustomAttributes (module); + + if (module.EntryPoint != null) + entry_point = LookupToken (module.EntryPoint); + } + + void BuildAssembly () + { + var assembly = module.Assembly; + var name = assembly.Name; + + var table = GetTable (Table.Assembly); + + table.row = new AssemblyRow ( + name.HashAlgorithm, + (ushort) name.Version.Major, + (ushort) name.Version.Minor, + (ushort) name.Version.Build, + (ushort) name.Version.Revision, + name.Attributes, + GetBlobIndex (name.PublicKey), + GetStringIndex (name.Name), + GetStringIndex (name.Culture)); + + if (assembly.Modules.Count > 1) + BuildModules (); + } + + void BuildModules () + { + var modules = this.module.Assembly.Modules; + var table = GetTable (Table.File); + + for (int i = 0; i < modules.Count; i++) { + var module = modules [i]; + if (module.IsMain) + continue; + + var parameters = new WriterParameters { + SymbolWriterProvider = symbol_writer_provider, + }; + + var file_name = GetModuleFileName (module.Name); + module.Write (file_name, parameters); + + var hash = CryptoService.ComputeHash (file_name); + + table.AddRow (new FileRow ( + FileAttributes.ContainsMetaData, + GetStringIndex (module.Name), + GetBlobIndex (hash))); + } + } + + string GetModuleFileName (string name) + { + if (string.IsNullOrEmpty (name)) + throw new NotSupportedException (); + + var path = Path.GetDirectoryName (fq_name); + return Path.Combine (path, name); + } + + void AddAssemblyReferences () + { + var references = module.AssemblyReferences; + var table = GetTable (Table.AssemblyRef); + + for (int i = 0; i < references.Count; i++) { + var reference = references [i]; + + var key_or_token = reference.PublicKey.IsNullOrEmpty () + ? reference.PublicKeyToken + : reference.PublicKey; + + var version = reference.Version; + + var rid = table.AddRow (new AssemblyRefRow ( + (ushort) version.Major, + (ushort) version.Minor, + (ushort) version.Build, + (ushort) version.Revision, + reference.Attributes, + GetBlobIndex (key_or_token), + GetStringIndex (reference.Name), + GetStringIndex (reference.Culture), + GetBlobIndex (reference.Hash))); + + reference.token = new MetadataToken (TokenType.AssemblyRef, rid); + } + } + + void AddModuleReferences () + { + var references = module.ModuleReferences; + var table = GetTable (Table.ModuleRef); + + for (int i = 0; i < references.Count; i++) { + var reference = references [i]; + + reference.token = new MetadataToken ( + TokenType.ModuleRef, + table.AddRow (GetStringIndex (reference.Name))); + } + } + + void AddResources () + { + var resources = module.Resources; + var table = GetTable (Table.ManifestResource); + + for (int i = 0; i < resources.Count; i++) { + var resource = resources [i]; + + var row = new ManifestResourceRow ( + 0, + resource.Attributes, + GetStringIndex (resource.Name), + 0); + + switch (resource.ResourceType) { + case ResourceType.Embedded: + row.Col1 = AddEmbeddedResource ((EmbeddedResource) resource); + break; + case ResourceType.Linked: + row.Col4 = CodedIndex.Implementation.CompressMetadataToken ( + new MetadataToken ( + TokenType.File, + AddLinkedResource ((LinkedResource) resource))); + break; + case ResourceType.AssemblyLinked: + row.Col4 = CodedIndex.Implementation.CompressMetadataToken ( + ((AssemblyLinkedResource) resource).Assembly.MetadataToken); + break; + default: + throw new NotSupportedException (); + } + + table.AddRow (row); + } + } + + uint AddLinkedResource (LinkedResource resource) + { + var table = GetTable (Table.File); + + var hash = resource.Hash.IsNullOrEmpty () + ? CryptoService.ComputeHash (resource.File) + : resource.Hash; + + return (uint) table.AddRow (new FileRow ( + FileAttributes.ContainsNoMetaData, + GetStringIndex (resource.File), + GetBlobIndex (hash))); + } + + uint AddEmbeddedResource (EmbeddedResource resource) + { + return resources.AddResource (resource.GetResourceData ()); + } + + void AddExportedTypes () + { + var exported_types = module.ExportedTypes; + var table = GetTable (Table.ExportedType); + + for (int i = 0; i < exported_types.Count; i++) { + var exported_type = exported_types [i]; + + var rid = table.AddRow (new ExportedTypeRow ( + exported_type.Attributes, + (uint) exported_type.Identifier, + GetStringIndex (exported_type.Name), + GetStringIndex (exported_type.Namespace), + MakeCodedRID (GetExportedTypeScope (exported_type), CodedIndex.Implementation))); + + exported_type.token = new MetadataToken (TokenType.ExportedType, rid); + } + } + + MetadataToken GetExportedTypeScope (ExportedType exported_type) + { + if (exported_type.DeclaringType != null) + return exported_type.DeclaringType.MetadataToken; + + var scope = exported_type.Scope; + switch (scope.MetadataToken.TokenType) { + case TokenType.AssemblyRef: + return scope.MetadataToken; + case TokenType.ModuleRef: + var file_table = GetTable (Table.File); + for (int i = 0; i < file_table.length; i++) + if (file_table.rows [i].Col2 == GetStringIndex (scope.Name)) + return new MetadataToken (TokenType.File, i + 1); + + break; + } + + throw new NotSupportedException (); + } + + void BuildTypes () + { + if (!module.HasTypes) + return; + + AttachTokens (); + AddTypeDefs (); + AddGenericParameters (); + } + + void AttachTokens () + { + var types = module.Types; + + for (int i = 0; i < types.Count; i++) + AttachTypeDefToken (types [i]); + } + + void AttachTypeDefToken (TypeDefinition type) + { + type.token = new MetadataToken (TokenType.TypeDef, type_rid++); + type.fields_range.Start = field_rid; + type.methods_range.Start = method_rid; + + if (type.HasFields) + AttachFieldsDefToken (type); + + if (type.HasMethods) + AttachMethodsDefToken (type); + + if (type.HasNestedTypes) + AttachNestedTypesDefToken (type); + } + + void AttachNestedTypesDefToken (TypeDefinition type) + { + var nested_types = type.NestedTypes; + for (int i = 0; i < nested_types.Count; i++) + AttachTypeDefToken (nested_types [i]); + } + + void AttachFieldsDefToken (TypeDefinition type) + { + var fields = type.Fields; + type.fields_range.Length = (uint) fields.Count; + for (int i = 0; i < fields.Count; i++) + fields [i].token = new MetadataToken (TokenType.Field, field_rid++); + } + + void AttachMethodsDefToken (TypeDefinition type) + { + var methods = type.Methods; + type.methods_range.Length = (uint) methods.Count; + for (int i = 0; i < methods.Count; i++) { + var method = methods [i]; + var new_token = new MetadataToken (TokenType.Method, method_rid++); + + if (write_symbols && method.token != MetadataToken.Zero) + method_def_map.Add (new_token, method.token); + + method.token = new_token; + } + } + + public bool TryGetOriginalMethodToken (MetadataToken new_token, out MetadataToken original) + { + return method_def_map.TryGetValue (new_token, out original); + } + + MetadataToken GetTypeToken (TypeReference type) + { + if (type == null) + return MetadataToken.Zero; + + if (type.IsDefinition) + return type.token; + + if (type.IsTypeSpecification ()) + return GetTypeSpecToken (type); + + return GetTypeRefToken (type); + } + + MetadataToken GetTypeSpecToken (TypeReference type) + { + var row = GetBlobIndex (GetTypeSpecSignature (type)); + + MetadataToken token; + if (type_spec_map.TryGetValue (row, out token)) + return token; + + return AddTypeSpecification (type, row); + } + + MetadataToken AddTypeSpecification (TypeReference type, uint row) + { + type.token = new MetadataToken (TokenType.TypeSpec, typespec_table.AddRow (row)); + + var token = type.token; + type_spec_map.Add (row, token); + return token; + } + + MetadataToken GetTypeRefToken (TypeReference type) + { + MetadataToken token; + if (module.CustomMetadataWriter != null) { + if (module.CustomMetadataWriter.CreateTypeRefToken (ref type, out token)) + return token; + } + + var row = CreateTypeRefRow (type); + + if (type_ref_map.TryGetValue (row, out token)) + return token; + + return AddTypeReference (type, row); + } + + TypeRefRow CreateTypeRefRow (TypeReference type) + { + var scope_token = type.IsNested + ? GetTypeRefToken (type.DeclaringType) + : type.Scope.MetadataToken; + + return new TypeRefRow ( + MakeCodedRID (scope_token, CodedIndex.ResolutionScope), + GetStringIndex (type.Name), + GetStringIndex (type.Namespace)); + } + + static CodedRID MakeCodedRID (IMetadataTokenProvider provider, CodedIndex index) + { + return MakeCodedRID (provider.MetadataToken, index); + } + + static CodedRID MakeCodedRID (MetadataToken token, CodedIndex index) + { + return index.CompressMetadataToken (token); + } + + MetadataToken AddTypeReference (TypeReference type, TypeRefRow row) + { + type.token = new MetadataToken (TokenType.TypeRef, type_ref_table.AddRow (row)); + + var token = type.token; + type_ref_map.Add (row, token); + return token; + } + + void AddTypeDefs () + { + var types = module.Types; + + for (int i = 0; i < types.Count; i++) + AddType (types [i]); + } + + void AddType (TypeDefinition type) + { + type_def_table.AddRow (new TypeDefRow ( + type.Attributes, + GetStringIndex (type.Name), + GetStringIndex (type.Namespace), + MakeCodedRID (GetTypeToken (type.BaseType), CodedIndex.TypeDefOrRef), + type.fields_range.Start, + type.methods_range.Start)); + + if (type.HasGenericParameters) + AddGenericParameters (type); + + if (type.HasInterfaces) + AddInterfaces (type); + + if (type.HasLayoutInfo) + AddLayoutInfo (type); + + if (type.HasFields) + AddFields (type); + + if (type.HasMethods) + AddMethods (type); + + if (type.HasProperties) + AddProperties (type); + + if (type.HasEvents) + AddEvents (type); + + if (type.HasCustomAttributes) + AddCustomAttributes (type); + + if (type.HasSecurityDeclarations) + AddSecurityDeclarations (type); + + if (type.HasNestedTypes) + AddNestedTypes (type); + } + + void AddGenericParameters (IGenericParameterProvider owner) + { + var parameters = owner.GenericParameters; + + for (int i = 0; i < parameters.Count; i++) + generic_parameters.Add (parameters [i]); + } + + sealed class GenericParameterComparer : IComparer { + + public int Compare (GenericParameter a, GenericParameter b) + { + var a_owner = MakeCodedRID (a.Owner, CodedIndex.TypeOrMethodDef); + var b_owner = MakeCodedRID (b.Owner, CodedIndex.TypeOrMethodDef); + if (a_owner == b_owner) { + var a_pos = a.Position; + var b_pos = b.Position; + return a_pos == b_pos ? 0 : a_pos > b_pos ? 1 : -1; + } + + return a_owner > b_owner ? 1 : -1; + } + } + + void AddGenericParameters () + { + var items = this.generic_parameters.items; + var size = this.generic_parameters.size; + Array.Sort (items, 0, size, new GenericParameterComparer ()); + + var generic_param_table = GetTable (Table.GenericParam); + var generic_param_constraint_table = GetTable (Table.GenericParamConstraint); + + for (int i = 0; i < size; i++) { + var generic_parameter = items [i]; + + var rid = generic_param_table.AddRow (new GenericParamRow ( + (ushort) generic_parameter.Position, + generic_parameter.Attributes, + MakeCodedRID (generic_parameter.Owner, CodedIndex.TypeOrMethodDef), + GetStringIndex (generic_parameter.Name))); + + generic_parameter.token = new MetadataToken (TokenType.GenericParam, rid); + + if (generic_parameter.HasConstraints) + AddConstraints (generic_parameter, generic_param_constraint_table); + + if (generic_parameter.HasCustomAttributes) + AddCustomAttributes (generic_parameter); + } + } + + void AddConstraints (GenericParameter generic_parameter, GenericParamConstraintTable table) + { + var constraints = generic_parameter.Constraints; + + var rid = generic_parameter.token.RID; + + for (int i = 0; i < constraints.Count; i++) + table.AddRow (new GenericParamConstraintRow ( + rid, + MakeCodedRID (GetTypeToken (constraints [i]), CodedIndex.TypeDefOrRef))); + } + + void AddInterfaces (TypeDefinition type) + { + var interfaces = type.Interfaces; + var type_rid = type.token.RID; + + for (int i = 0; i < interfaces.Count; i++) + iface_impl_table.AddRow (new InterfaceImplRow ( + type_rid, + MakeCodedRID (GetTypeToken (interfaces [i]), CodedIndex.TypeDefOrRef))); + } + + void AddLayoutInfo (TypeDefinition type) + { + var table = GetTable (Table.ClassLayout); + + table.AddRow (new ClassLayoutRow ( + (ushort) type.PackingSize, + (uint) type.ClassSize, + type.token.RID)); + } + + void AddNestedTypes (TypeDefinition type) + { + var nested_types = type.NestedTypes; + var nested_table = GetTable (Table.NestedClass); + + for (int i = 0; i < nested_types.Count; i++) { + var nested = nested_types [i]; + AddType (nested); + nested_table.AddRow (new NestedClassRow (nested.token.RID, type.token.RID)); + } + } + + void AddFields (TypeDefinition type) + { + var fields = type.Fields; + + for (int i = 0; i < fields.Count; i++) + AddField (fields [i]); + } + + void AddField (FieldDefinition field) + { + field_table.AddRow (new FieldRow ( + field.Attributes, + GetStringIndex (field.Name), + GetBlobIndex (GetFieldSignature (field)))); + + if (!field.InitialValue.IsNullOrEmpty ()) + AddFieldRVA (field); + + if (field.HasLayoutInfo) + AddFieldLayout (field); + + if (field.HasCustomAttributes) + AddCustomAttributes (field); + + if (field.HasConstant) + AddConstant (field, field.FieldType); + + if (field.HasMarshalInfo) + AddMarshalInfo (field); + } + + void AddFieldRVA (FieldDefinition field) + { + var table = GetTable (Table.FieldRVA); + table.AddRow (new FieldRVARow ( + data.AddData (field.InitialValue), + field.token.RID)); + } + + void AddFieldLayout (FieldDefinition field) + { + var table = GetTable (Table.FieldLayout); + table.AddRow (new FieldLayoutRow ((uint) field.Offset, field.token.RID)); + } + + void AddMethods (TypeDefinition type) + { + var methods = type.Methods; + + for (int i = 0; i < methods.Count; i++) + AddMethod (methods [i]); + } + + void AddMethod (MethodDefinition method) + { + method_table.AddRow (new MethodRow ( + method.HasBody ? code.WriteMethodBody (method) : 0, + method.ImplAttributes, + method.Attributes, + GetStringIndex (method.Name), + GetBlobIndex (GetMethodSignature (method)), + param_rid)); + + AddParameters (method); + + if (method.HasGenericParameters) + AddGenericParameters (method); + + if (method.IsPInvokeImpl) + AddPInvokeInfo (method); + + if (method.HasCustomAttributes) + AddCustomAttributes (method); + + if (method.HasSecurityDeclarations) + AddSecurityDeclarations (method); + + if (method.HasOverrides) + AddOverrides (method); + } + + void AddParameters (MethodDefinition method) + { + var return_parameter = method.MethodReturnType.parameter; + + if (return_parameter != null && RequiresParameterRow (return_parameter)) + AddParameter (0, return_parameter, param_table); + + if (!method.HasParameters) + return; + + var parameters = method.Parameters; + + for (int i = 0; i < parameters.Count; i++) { + var parameter = parameters [i]; + if (!RequiresParameterRow (parameter)) + continue; + + AddParameter ((ushort) (i + 1), parameter, param_table); + } + } + + void AddPInvokeInfo (MethodDefinition method) + { + var pinvoke = method.PInvokeInfo; + if (pinvoke == null) + return; + + var table = GetTable (Table.ImplMap); + table.AddRow (new ImplMapRow ( + pinvoke.Attributes, + MakeCodedRID (method, CodedIndex.MemberForwarded), + GetStringIndex (pinvoke.EntryPoint), + pinvoke.Module.MetadataToken.RID)); + } + + void AddOverrides (MethodDefinition method) + { + var overrides = method.Overrides; + var table = GetTable (Table.MethodImpl); + + for (int i = 0; i < overrides.Count; i++) { + table.AddRow (new MethodImplRow ( + method.DeclaringType.token.RID, + MakeCodedRID (method, CodedIndex.MethodDefOrRef), + MakeCodedRID (LookupToken (overrides [i]), CodedIndex.MethodDefOrRef))); + } + } + + static bool RequiresParameterRow (ParameterDefinition parameter) + { + return !string.IsNullOrEmpty (parameter.Name) + || parameter.Attributes != ParameterAttributes.None + || parameter.HasMarshalInfo + || parameter.HasConstant + || parameter.HasCustomAttributes; + } + + void AddParameter (ushort sequence, ParameterDefinition parameter, ParamTable table) + { + table.AddRow (new ParamRow ( + parameter.Attributes, + sequence, + GetStringIndex (parameter.Name))); + + parameter.token = new MetadataToken (TokenType.Param, param_rid++); + + if (parameter.HasCustomAttributes) + AddCustomAttributes (parameter); + + if (parameter.HasConstant) + AddConstant (parameter, parameter.ParameterType); + + if (parameter.HasMarshalInfo) + AddMarshalInfo (parameter); + } + + void AddMarshalInfo (IMarshalInfoProvider owner) + { + var table = GetTable (Table.FieldMarshal); + + table.AddRow (new FieldMarshalRow ( + MakeCodedRID (owner, CodedIndex.HasFieldMarshal), + GetBlobIndex (GetMarshalInfoSignature (owner)))); + } + + void AddProperties (TypeDefinition type) + { + var properties = type.Properties; + + property_map_table.AddRow (new PropertyMapRow (type.token.RID, property_rid)); + + for (int i = 0; i < properties.Count; i++) + AddProperty (properties [i]); + } + + void AddProperty (PropertyDefinition property) + { + property_table.AddRow (new PropertyRow ( + property.Attributes, + GetStringIndex (property.Name), + GetBlobIndex (GetPropertySignature (property)))); + property.token = new MetadataToken (TokenType.Property, property_rid++); + + var method = property.GetMethod; + if (method != null) + AddSemantic (MethodSemanticsAttributes.Getter, property, method); + + method = property.SetMethod; + if (method != null) + AddSemantic (MethodSemanticsAttributes.Setter, property, method); + + if (property.HasOtherMethods) + AddOtherSemantic (property, property.OtherMethods); + + if (property.HasCustomAttributes) + AddCustomAttributes (property); + + if (property.HasConstant) + AddConstant (property, property.PropertyType); + } + + void AddOtherSemantic (IMetadataTokenProvider owner, Collection others) + { + for (int i = 0; i < others.Count; i++) + AddSemantic (MethodSemanticsAttributes.Other, owner, others [i]); + } + + void AddEvents (TypeDefinition type) + { + var events = type.Events; + + event_map_table.AddRow (new EventMapRow (type.token.RID, event_rid)); + + for (int i = 0; i < events.Count; i++) + AddEvent (events [i]); + } + + void AddEvent (EventDefinition @event) + { + event_table.AddRow (new EventRow ( + @event.Attributes, + GetStringIndex (@event.Name), + MakeCodedRID (GetTypeToken (@event.EventType), CodedIndex.TypeDefOrRef))); + @event.token = new MetadataToken (TokenType.Event, event_rid++); + + var method = @event.AddMethod; + if (method != null) + AddSemantic (MethodSemanticsAttributes.AddOn, @event, method); + + method = @event.InvokeMethod; + if (method != null) + AddSemantic (MethodSemanticsAttributes.Fire, @event, method); + + method = @event.RemoveMethod; + if (method != null) + AddSemantic (MethodSemanticsAttributes.RemoveOn, @event, method); + + if (@event.HasOtherMethods) + AddOtherSemantic (@event, @event.OtherMethods); + + if (@event.HasCustomAttributes) + AddCustomAttributes (@event); + } + + void AddSemantic (MethodSemanticsAttributes semantics, IMetadataTokenProvider provider, MethodDefinition method) + { + method.SemanticsAttributes = semantics; + var table = GetTable (Table.MethodSemantics); + + table.AddRow (new MethodSemanticsRow ( + semantics, + method.token.RID, + MakeCodedRID (provider, CodedIndex.HasSemantics))); + } + + void AddConstant (IConstantProvider owner, TypeReference type) + { + var constant = owner.Constant; + var etype = GetConstantType (type, constant); + + constant_table.AddRow (new ConstantRow ( + etype, + MakeCodedRID (owner.MetadataToken, CodedIndex.HasConstant), + GetBlobIndex (GetConstantSignature (etype, constant)))); + } + + static ElementType GetConstantType (TypeReference constant_type, object constant) + { + if (constant == null) + return ElementType.Class; + + var etype = constant_type.etype; + switch (etype) { + case ElementType.None: + var type = constant_type.CheckedResolve (); + if (type.IsEnum) + return GetConstantType (type.GetEnumUnderlyingType (), constant); + + return ElementType.Class; + case ElementType.String: + return ElementType.String; + case ElementType.Object: + return GetConstantType (constant.GetType ()); + case ElementType.Array: + case ElementType.SzArray: + case ElementType.MVar: + case ElementType.Var: + return ElementType.Class; + case ElementType.GenericInst: + case ElementType.CModOpt: + case ElementType.CModReqD: + case ElementType.ByRef: + case ElementType.Sentinel: + return GetConstantType (((TypeSpecification) constant_type).ElementType, constant); + case ElementType.Boolean: + case ElementType.Char: + case ElementType.I: + case ElementType.I1: + case ElementType.I2: + case ElementType.I4: + case ElementType.I8: + case ElementType.U: + case ElementType.U1: + case ElementType.U2: + case ElementType.U4: + case ElementType.U8: + case ElementType.R4: + case ElementType.R8: + return GetConstantType (constant.GetType ()); + default: + return etype; + } + } + + static ElementType GetConstantType (Type type) + { + switch (Type.GetTypeCode (type)) { + case TypeCode.Boolean: + return ElementType.Boolean; + case TypeCode.Byte: + return ElementType.U1; + case TypeCode.SByte: + return ElementType.I1; + case TypeCode.Char: + return ElementType.Char; + case TypeCode.Int16: + return ElementType.I2; + case TypeCode.UInt16: + return ElementType.U2; + case TypeCode.Int32: + return ElementType.I4; + case TypeCode.UInt32: + return ElementType.U4; + case TypeCode.Int64: + return ElementType.I8; + case TypeCode.UInt64: + return ElementType.U8; + case TypeCode.Single: + return ElementType.R4; + case TypeCode.Double: + return ElementType.R8; + case TypeCode.String: + return ElementType.String; + default: + throw new NotSupportedException (type.FullName); + } + } + + void AddCustomAttributes (ICustomAttributeProvider owner) + { + var custom_attributes = owner.CustomAttributes; + + for (int i = 0; i < custom_attributes.Count; i++) { + var attribute = custom_attributes [i]; + + custom_attribute_table.AddRow (new CustomAttributeRow ( + MakeCodedRID (owner, CodedIndex.HasCustomAttribute), + MakeCodedRID (LookupToken (attribute.Constructor), CodedIndex.CustomAttributeType), + GetBlobIndex (GetCustomAttributeSignature (attribute)))); + } + } + + void AddSecurityDeclarations (ISecurityDeclarationProvider owner) + { + var declarations = owner.SecurityDeclarations; + + for (int i = 0; i < declarations.Count; i++) { + var declaration = declarations [i]; + + declsec_table.AddRow (new DeclSecurityRow ( + declaration.Action, + MakeCodedRID (owner, CodedIndex.HasDeclSecurity), + GetBlobIndex (GetSecurityDeclarationSignature (declaration)))); + } + } + + MetadataToken GetMemberRefToken (MemberReference member) + { + var row = CreateMemberRefRow (member); + + MetadataToken token; + if (member_ref_map.TryGetValue (row, out token)) + return token; + + AddMemberReference (member, row); + + return member.token; + } + + MemberRefRow CreateMemberRefRow (MemberReference member) + { + return new MemberRefRow ( + MakeCodedRID (GetTypeToken (member.DeclaringType), CodedIndex.MemberRefParent), + GetStringIndex (member.Name), + GetBlobIndex (GetMemberRefSignature (member))); + } + + void AddMemberReference (MemberReference member, MemberRefRow row) + { + member.token = new MetadataToken (TokenType.MemberRef, member_ref_table.AddRow (row)); + member_ref_map.Add (row, member.token); + } + + MetadataToken GetMethodSpecToken (MethodSpecification method_spec) + { + var row = CreateMethodSpecRow (method_spec); + + MetadataToken token; + if (method_spec_map.TryGetValue (row, out token)) + return token; + + AddMethodSpecification (method_spec, row); + + return method_spec.token; + } + + void AddMethodSpecification (MethodSpecification method_spec, MethodSpecRow row) + { + method_spec.token = new MetadataToken (TokenType.MethodSpec, method_spec_table.AddRow (row)); + method_spec_map.Add (row, method_spec.token); + } + + MethodSpecRow CreateMethodSpecRow (MethodSpecification method_spec) + { + return new MethodSpecRow ( + MakeCodedRID (LookupToken (method_spec.ElementMethod), CodedIndex.MethodDefOrRef), + GetBlobIndex (GetMethodSpecSignature (method_spec))); + } + + SignatureWriter CreateSignatureWriter () + { + return new SignatureWriter (this); + } + + SignatureWriter GetMethodSpecSignature (MethodSpecification method_spec) + { + if (!method_spec.IsGenericInstance) + throw new NotSupportedException (); + + var generic_instance = (GenericInstanceMethod) method_spec; + + var signature = CreateSignatureWriter (); + signature.WriteByte (0x0a); + + signature.WriteGenericInstanceSignature (generic_instance); + + return signature; + } + + public uint AddStandAloneSignature (uint signature) + { + return (uint) standalone_sig_table.AddRow (signature); + } + + public uint GetLocalVariableBlobIndex (Collection variables) + { + return GetBlobIndex (GetVariablesSignature (variables)); + } + + public uint GetCallSiteBlobIndex (CallSite call_site) + { + return GetBlobIndex (GetMethodSignature (call_site)); + } + + SignatureWriter GetVariablesSignature (Collection variables) + { + var signature = CreateSignatureWriter (); + signature.WriteByte (0x7); + signature.WriteCompressedUInt32 ((uint) variables.Count); + for (int i = 0; i < variables.Count; i++) + signature.WriteTypeSignature (variables [i].VariableType); + return signature; + } + + SignatureWriter GetFieldSignature (FieldReference field) + { + var signature = CreateSignatureWriter (); + signature.WriteByte (0x6); + signature.WriteTypeSignature (field.FieldType); + return signature; + } + + SignatureWriter GetMethodSignature (IMethodSignature method) + { + var signature = CreateSignatureWriter (); + signature.WriteMethodSignature (method); + return signature; + } + + SignatureWriter GetMemberRefSignature (MemberReference member) + { + var field = member as FieldReference; + if (field != null) + return GetFieldSignature (field); + + var method = member as MethodReference; + if (method != null) + return GetMethodSignature (method); + + throw new NotSupportedException (); + } + + SignatureWriter GetPropertySignature (PropertyDefinition property) + { + var signature = CreateSignatureWriter (); + byte calling_convention = 0x8; + if (property.HasThis) + calling_convention |= 0x20; + + uint param_count = 0; + Collection parameters = null; + + if (property.HasParameters) { + parameters = property.Parameters; + param_count = (uint) parameters.Count; + } + + signature.WriteByte (calling_convention); + signature.WriteCompressedUInt32 (param_count); + signature.WriteTypeSignature (property.PropertyType); + + if (param_count == 0) + return signature; + + for (int i = 0; i < param_count; i++) + signature.WriteTypeSignature (parameters [i].ParameterType); + + return signature; + } + + SignatureWriter GetTypeSpecSignature (TypeReference type) + { + var signature = CreateSignatureWriter (); + signature.WriteTypeSignature (type); + return signature; + } + + SignatureWriter GetConstantSignature (ElementType type, object value) + { + var signature = CreateSignatureWriter (); + + switch (type) { + case ElementType.Array: + case ElementType.SzArray: + case ElementType.Class: + case ElementType.Object: + case ElementType.Var: + case ElementType.MVar: + signature.WriteInt32 (0); + break; + case ElementType.String: + signature.WriteConstantString ((string) value); + break; + default: + signature.WriteConstantPrimitive (value); + break; + } + + return signature; + } + + SignatureWriter GetCustomAttributeSignature (CustomAttribute attribute) + { + var signature = CreateSignatureWriter (); + if (!attribute.resolved) { + signature.WriteBytes (attribute.GetBlob ()); + return signature; + } + + signature.WriteUInt16 (0x0001); + + signature.WriteCustomAttributeConstructorArguments (attribute); + + signature.WriteCustomAttributeNamedArguments (attribute); + + return signature; + } + + SignatureWriter GetSecurityDeclarationSignature (SecurityDeclaration declaration) + { + var signature = CreateSignatureWriter (); + + if (!declaration.resolved) + signature.WriteBytes (declaration.GetBlob ()); + else if (module.Runtime < TargetRuntime.Net_2_0) + signature.WriteXmlSecurityDeclaration (declaration); + else + signature.WriteSecurityDeclaration (declaration); + + return signature; + } + + SignatureWriter GetMarshalInfoSignature (IMarshalInfoProvider owner) + { + var signature = CreateSignatureWriter (); + + signature.WriteMarshalInfo (owner.MarshalInfo); + + return signature; + } + + static Exception CreateForeignMemberException (MemberReference member) + { + return new ArgumentException (string.Format ("Member '{0}' is declared in another module and needs to be imported", member)); + } + + public MetadataToken LookupToken (IMetadataTokenProvider provider) + { + if (provider == null) + throw new ArgumentNullException (); + + var member = provider as MemberReference; + if (member == null || member.Module != module) + throw CreateForeignMemberException (member); + + var token = provider.MetadataToken; + + switch (token.TokenType) { + case TokenType.TypeDef: + case TokenType.Method: + case TokenType.Field: + case TokenType.Event: + case TokenType.Property: + return token; + case TokenType.TypeRef: + case TokenType.TypeSpec: + case TokenType.GenericParam: + return GetTypeToken ((TypeReference) provider); + case TokenType.MethodSpec: + return GetMethodSpecToken ((MethodSpecification) provider); + case TokenType.MemberRef: + return GetMemberRefToken (member); + default: + throw new NotSupportedException (); + } + } + } + + sealed class SignatureWriter : ByteBuffer { + + readonly MetadataBuilder metadata; + + public SignatureWriter (MetadataBuilder metadata) + : base (6) + { + this.metadata = metadata; + } + + public void WriteElementType (ElementType element_type) + { + WriteByte ((byte) element_type); + } + + public void WriteUTF8String (string @string) + { + if (@string == null) { + WriteByte (0xff); + return; + } + + var bytes = Encoding.UTF8.GetBytes (@string); + WriteCompressedUInt32 ((uint) bytes.Length); + WriteBytes (bytes); + } + + public void WriteMethodSignature (IMethodSignature method) + { + byte calling_convention = (byte) method.CallingConvention; + if (method.HasThis) + calling_convention |= 0x20; + if (method.ExplicitThis) + calling_convention |= 0x40; + + var generic_provider = method as IGenericParameterProvider; + var generic_arity = generic_provider != null && generic_provider.HasGenericParameters + ? generic_provider.GenericParameters.Count + : 0; + + if (generic_arity > 0) + calling_convention |= 0x10; + + var param_count = method.HasParameters ? method.Parameters.Count : 0; + + WriteByte (calling_convention); + + if (generic_arity > 0) + WriteCompressedUInt32 ((uint) generic_arity); + + WriteCompressedUInt32 ((uint) param_count); + WriteTypeSignature (method.ReturnType); + + if (param_count == 0) + return; + + var parameters = method.Parameters; + + for (int i = 0; i < param_count; i++) + WriteTypeSignature (parameters [i].ParameterType); + } + + uint MakeTypeDefOrRefCodedRID (TypeReference type) + { + return CodedIndex.TypeDefOrRef.CompressMetadataToken (metadata.LookupToken (type)); + } + + public void WriteTypeSignature (TypeReference type) + { + if (type == null) + throw new ArgumentNullException (); + + var etype = type.etype; + + switch (etype) { + case ElementType.MVar: + case ElementType.Var: { + var generic_parameter = (GenericParameter) type; + + WriteElementType (etype); + var position = generic_parameter.Position; + if (position == -1) + throw new NotSupportedException (); + + WriteCompressedUInt32 ((uint) position); + break; + } + + case ElementType.GenericInst: { + var generic_instance = (GenericInstanceType) type; + WriteElementType (ElementType.GenericInst); + WriteElementType (generic_instance.IsValueType ? ElementType.ValueType : ElementType.Class); + WriteCompressedUInt32 (MakeTypeDefOrRefCodedRID (generic_instance.ElementType)); + + WriteGenericInstanceSignature (generic_instance); + break; + } + + case ElementType.Ptr: + case ElementType.ByRef: + case ElementType.Pinned: + case ElementType.Sentinel: { + var type_spec = (TypeSpecification) type; + WriteElementType (etype); + WriteTypeSignature (type_spec.ElementType); + break; + } + + case ElementType.FnPtr: { + var fptr = (FunctionPointerType) type; + WriteElementType (ElementType.FnPtr); + WriteMethodSignature (fptr); + break; + } + + case ElementType.CModOpt: + case ElementType.CModReqD: { + var modifier = (IModifierType) type; + WriteModifierSignature (etype, modifier); + break; + } + + case ElementType.Array: { + var array = (ArrayType) type; + if (!array.IsVector) { + WriteArrayTypeSignature (array); + break; + } + + WriteElementType (ElementType.SzArray); + WriteTypeSignature (array.ElementType); + break; + } + + case ElementType.None: { + WriteElementType (type.IsValueType ? ElementType.ValueType : ElementType.Class); + WriteCompressedUInt32 (MakeTypeDefOrRefCodedRID (type)); + break; + } + + default: + if (!TryWriteElementType (type)) + throw new NotSupportedException (); + + break; + + } + } + + void WriteArrayTypeSignature (ArrayType array) + { + WriteElementType (ElementType.Array); + WriteTypeSignature (array.ElementType); + + var dimensions = array.Dimensions; + var rank = dimensions.Count; + + WriteCompressedUInt32 ((uint) rank); + + var sized = 0; + var lbounds = 0; + + for (int i = 0; i < rank; i++) { + var dimension = dimensions [i]; + + if (dimension.UpperBound.HasValue) { + sized++; + lbounds++; + } else if (dimension.LowerBound.HasValue) + lbounds++; + } + + var sizes = new int [sized]; + var low_bounds = new int [lbounds]; + + for (int i = 0; i < lbounds; i++) { + var dimension = dimensions [i]; + low_bounds [i] = dimension.LowerBound.GetValueOrDefault (); + if (dimension.UpperBound.HasValue) + sizes [i] = dimension.UpperBound.Value - low_bounds [i] + 1; + } + + WriteCompressedUInt32 ((uint) sized); + for (int i = 0; i < sized; i++) + WriteCompressedUInt32 ((uint) sizes [i]); + + WriteCompressedUInt32 ((uint) lbounds); + for (int i = 0; i < lbounds; i++) + WriteCompressedInt32 (low_bounds [i]); + } + + public void WriteGenericInstanceSignature (IGenericInstance instance) + { + var generic_arguments = instance.GenericArguments; + var arity = generic_arguments.Count; + + WriteCompressedUInt32 ((uint) arity); + for (int i = 0; i < arity; i++) + WriteTypeSignature (generic_arguments [i]); + } + + void WriteModifierSignature (ElementType element_type, IModifierType type) + { + WriteElementType (element_type); + WriteCompressedUInt32 (MakeTypeDefOrRefCodedRID (type.ModifierType)); + WriteTypeSignature (type.ElementType); + } + + bool TryWriteElementType (TypeReference type) + { + var element = type.etype; + + if (element == ElementType.None) + return false; + + WriteElementType (element); + return true; + } + + public void WriteConstantString (string value) + { + WriteBytes (Encoding.Unicode.GetBytes (value)); + } + + public void WriteConstantPrimitive (object value) + { + WritePrimitiveValue (value); + } + + public void WriteCustomAttributeConstructorArguments (CustomAttribute attribute) + { + if (!attribute.HasConstructorArguments) + return; + + var arguments = attribute.ConstructorArguments; + var parameters = attribute.Constructor.Parameters; + + if (parameters.Count != arguments.Count) + throw new InvalidOperationException (); + + for (int i = 0; i < arguments.Count; i++) + WriteCustomAttributeFixedArgument (parameters [i].ParameterType, arguments [i]); + } + + void WriteCustomAttributeFixedArgument (TypeReference type, CustomAttributeArgument argument) + { + if (type.IsArray) { + WriteCustomAttributeFixedArrayArgument ((ArrayType) type, argument); + return; + } + + WriteCustomAttributeElement (type, argument); + } + + void WriteCustomAttributeFixedArrayArgument (ArrayType type, CustomAttributeArgument argument) + { + var values = argument.Value as CustomAttributeArgument []; + + if (values == null) { + WriteUInt32 (0xffffffff); + return; + } + + WriteInt32 (values.Length); + + if (values.Length == 0) + return; + + var element_type = type.ElementType; + + for (int i = 0; i < values.Length; i++) + WriteCustomAttributeElement (element_type, values [i]); + } + + void WriteCustomAttributeElement (TypeReference type, CustomAttributeArgument argument) + { + if (type.IsArray) { + WriteCustomAttributeFixedArrayArgument ((ArrayType) type, argument); + return; + } + + if (type.etype == ElementType.Object) { + argument = (CustomAttributeArgument) argument.Value; + type = argument.Type; + + WriteCustomAttributeFieldOrPropType (type); + WriteCustomAttributeElement (type, argument); + return; + } + + WriteCustomAttributeValue (type, argument.Value); + } + + void WriteCustomAttributeValue (TypeReference type, object value) + { + var etype = type.etype; + + switch (etype) { + case ElementType.String: + var @string = (string) value; + if (@string == null) + WriteByte (0xff); + else + WriteUTF8String (@string); + break; + case ElementType.None: + if (type.IsTypeOf ("System", "Type")) + WriteTypeReference ((TypeReference) value); + else + WriteCustomAttributeEnumValue (type, value); + break; + default: + WritePrimitiveValue (value); + break; + } + } + + void WritePrimitiveValue (object value) + { + if (value == null) + throw new ArgumentNullException (); + + switch (Type.GetTypeCode (value.GetType ())) { + case TypeCode.Boolean: + WriteByte ((byte) (((bool) value) ? 1 : 0)); + break; + case TypeCode.Byte: + WriteByte ((byte) value); + break; + case TypeCode.SByte: + WriteSByte ((sbyte) value); + break; + case TypeCode.Int16: + WriteInt16 ((short) value); + break; + case TypeCode.UInt16: + WriteUInt16 ((ushort) value); + break; + case TypeCode.Char: + WriteInt16 ((short) (char) value); + break; + case TypeCode.Int32: + WriteInt32 ((int) value); + break; + case TypeCode.UInt32: + WriteUInt32 ((uint) value); + break; + case TypeCode.Single: + WriteSingle ((float) value); + break; + case TypeCode.Int64: + WriteInt64 ((long) value); + break; + case TypeCode.UInt64: + WriteUInt64 ((ulong) value); + break; + case TypeCode.Double: + WriteDouble ((double) value); + break; + default: + throw new NotSupportedException (value.GetType ().FullName); + } + } + + void WriteCustomAttributeEnumValue (TypeReference enum_type, object value) + { + var type = enum_type.CheckedResolve (); + if (!type.IsEnum) + throw new ArgumentException (); + + WriteCustomAttributeValue (type.GetEnumUnderlyingType (), value); + } + + void WriteCustomAttributeFieldOrPropType (TypeReference type) + { + if (type.IsArray) { + var array = (ArrayType) type; + WriteElementType (ElementType.SzArray); + WriteCustomAttributeFieldOrPropType (array.ElementType); + return; + } + + var etype = type.etype; + + switch (etype) { + case ElementType.Object: + WriteElementType (ElementType.Boxed); + return; + case ElementType.None: + if (type.IsTypeOf ("System", "Type")) + WriteElementType (ElementType.Type); + else { + WriteElementType (ElementType.Enum); + WriteTypeReference (type); + } + return; + default: + WriteElementType (etype); + return; + } + } + + public void WriteCustomAttributeNamedArguments (CustomAttribute attribute) + { + var count = GetNamedArgumentCount (attribute); + + WriteUInt16 ((ushort) count); + + if (count == 0) + return; + + WriteICustomAttributeNamedArguments (attribute); + } + + static int GetNamedArgumentCount (ICustomAttribute attribute) + { + int count = 0; + + if (attribute.HasFields) + count += attribute.Fields.Count; + + if (attribute.HasProperties) + count += attribute.Properties.Count; + + return count; + } + + void WriteICustomAttributeNamedArguments (ICustomAttribute attribute) + { + if (attribute.HasFields) + WriteCustomAttributeNamedArguments (0x53, attribute.Fields); + + if (attribute.HasProperties) + WriteCustomAttributeNamedArguments (0x54, attribute.Properties); + } + + void WriteCustomAttributeNamedArguments (byte kind, Collection named_arguments) + { + for (int i = 0; i < named_arguments.Count; i++) + WriteCustomAttributeNamedArgument (kind, named_arguments [i]); + } + + void WriteCustomAttributeNamedArgument (byte kind, CustomAttributeNamedArgument named_argument) + { + var argument = named_argument.Argument; + + WriteByte (kind); + WriteCustomAttributeFieldOrPropType (argument.Type); + WriteUTF8String (named_argument.Name); + WriteCustomAttributeFixedArgument (argument.Type, argument); + } + + void WriteSecurityAttribute (SecurityAttribute attribute) + { + WriteTypeReference (attribute.AttributeType); + + var count = GetNamedArgumentCount (attribute); + + if (count == 0) { + WriteCompressedUInt32 (1); // length + WriteCompressedUInt32 (0); // count + return; + } + + var buffer = new SignatureWriter (metadata); + buffer.WriteCompressedUInt32 ((uint) count); + buffer.WriteICustomAttributeNamedArguments (attribute); + + WriteCompressedUInt32 ((uint) buffer.length); + WriteBytes (buffer); + } + + public void WriteSecurityDeclaration (SecurityDeclaration declaration) + { + WriteByte ((byte) '.'); + + var attributes = declaration.security_attributes; + if (attributes == null) + throw new NotSupportedException (); + + WriteCompressedUInt32 ((uint) attributes.Count); + + for (int i = 0; i < attributes.Count; i++) + WriteSecurityAttribute (attributes [i]); + } + + public void WriteXmlSecurityDeclaration (SecurityDeclaration declaration) + { + var xml = GetXmlSecurityDeclaration (declaration); + if (xml == null) + throw new NotSupportedException (); + + WriteBytes (Encoding.Unicode.GetBytes (xml)); + } + + static string GetXmlSecurityDeclaration (SecurityDeclaration declaration) + { + if (declaration.security_attributes == null || declaration.security_attributes.Count != 1) + return null; + + var attribute = declaration.security_attributes [0]; + + if (!attribute.AttributeType.IsTypeOf ("System.Security.Permissions", "PermissionSetAttribute")) + return null; + + if (attribute.properties == null || attribute.properties.Count != 1) + return null; + + var property = attribute.properties [0]; + if (property.Name != "XML") + return null; + + return (string) property.Argument.Value; + } + + void WriteTypeReference (TypeReference type) + { + WriteUTF8String (TypeParser.ToParseable (type)); + } + + public void WriteMarshalInfo (MarshalInfo marshal_info) + { + WriteNativeType (marshal_info.native); + + switch (marshal_info.native) { + case NativeType.Array: { + var array = (ArrayMarshalInfo) marshal_info; + if (array.element_type != NativeType.None) + WriteNativeType (array.element_type); + if (array.size_parameter_index > -1) + WriteCompressedUInt32 ((uint) array.size_parameter_index); + if (array.size > -1) + WriteCompressedUInt32 ((uint) array.size); + if (array.size_parameter_multiplier > -1) + WriteCompressedUInt32 ((uint) array.size_parameter_multiplier); + return; + } + case NativeType.SafeArray: { + var array = (SafeArrayMarshalInfo) marshal_info; + if (array.element_type != VariantType.None) + WriteVariantType (array.element_type); + return; + } + case NativeType.FixedArray: { + var array = (FixedArrayMarshalInfo) marshal_info; + if (array.size > -1) + WriteCompressedUInt32 ((uint) array.size); + if (array.element_type != NativeType.None) + WriteNativeType (array.element_type); + return; + } + case NativeType.FixedSysString: + var sys_string = (FixedSysStringMarshalInfo) marshal_info; + if (sys_string.size > -1) + WriteCompressedUInt32 ((uint) sys_string.size); + return; + case NativeType.CustomMarshaler: + var marshaler = (CustomMarshalInfo) marshal_info; + WriteUTF8String (marshaler.guid != Guid.Empty ? marshaler.guid.ToString () : string.Empty); + WriteUTF8String (marshaler.unmanaged_type); + WriteTypeReference (marshaler.managed_type); + WriteUTF8String (marshaler.cookie); + return; + } + } + + void WriteNativeType (NativeType native) + { + WriteByte ((byte) native); + } + + void WriteVariantType (VariantType variant) + { + WriteByte ((byte) variant); + } + } + +#endif + +} diff --git a/external/cecil-legacy/Mono.Cecil/BaseAssemblyResolver.cs b/external/cecil-legacy/Mono.Cecil/BaseAssemblyResolver.cs new file mode 100644 index 0000000000..90be7bfb99 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/BaseAssemblyResolver.cs @@ -0,0 +1,370 @@ +// +// BaseAssemblyResolver.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + +using Mono.Collections.Generic; + +namespace Mono.Cecil { + + public delegate AssemblyDefinition AssemblyResolveEventHandler (object sender, AssemblyNameReference reference); + + public sealed class AssemblyResolveEventArgs : EventArgs { + + readonly AssemblyNameReference reference; + + public AssemblyNameReference AssemblyReference { + get { return reference; } + } + + public AssemblyResolveEventArgs (AssemblyNameReference reference) + { + this.reference = reference; + } + } + +#if !SILVERLIGHT && !CF + [Serializable] +#endif + public class AssemblyResolutionException : FileNotFoundException { + + readonly AssemblyNameReference reference; + + public AssemblyNameReference AssemblyReference { + get { return reference; } + } + + public AssemblyResolutionException (AssemblyNameReference reference) + : base (string.Format ("Failed to resolve assembly: '{0}'", reference)) + { + this.reference = reference; + } + +#if !SILVERLIGHT && !CF + protected AssemblyResolutionException ( + System.Runtime.Serialization.SerializationInfo info, + System.Runtime.Serialization.StreamingContext context) + : base (info, context) + { + } +#endif + } + + public abstract class BaseAssemblyResolver : IAssemblyResolver { + + static readonly bool on_mono = Type.GetType ("Mono.Runtime") != null; + + readonly Collection directories; + +#if !SILVERLIGHT && !CF + Collection gac_paths; +#endif + + public void AddSearchDirectory (string directory) + { + directories.Add (directory); + } + + public void RemoveSearchDirectory (string directory) + { + directories.Remove (directory); + } + + public string [] GetSearchDirectories () + { + var directories = new string [this.directories.size]; + Array.Copy (this.directories.items, directories, directories.Length); + return directories; + } + + public virtual AssemblyDefinition Resolve (string fullName) + { + return Resolve (fullName, new ReaderParameters ()); + } + + public virtual AssemblyDefinition Resolve (string fullName, ReaderParameters parameters) + { + if (fullName == null) + throw new ArgumentNullException ("fullName"); + + return Resolve (AssemblyNameReference.Parse (fullName), parameters); + } + + public event AssemblyResolveEventHandler ResolveFailure; + + protected BaseAssemblyResolver () + { + directories = new Collection (2) { ".", "bin" }; + } + + AssemblyDefinition GetAssembly (string file, ReaderParameters parameters) + { + if (parameters.AssemblyResolver == null) + parameters.AssemblyResolver = this; + + return ModuleDefinition.ReadModule (file, parameters).Assembly; + } + + public virtual AssemblyDefinition Resolve (AssemblyNameReference name) + { + return Resolve (name, new ReaderParameters ()); + } + + public virtual AssemblyDefinition Resolve (AssemblyNameReference name, ReaderParameters parameters) + { + if (name == null) + throw new ArgumentNullException ("name"); + if (parameters == null) + parameters = new ReaderParameters (); + + var assembly = SearchDirectory (name, directories, parameters); + if (assembly != null) + return assembly; + +#if !SILVERLIGHT && !CF + if (name.IsRetargetable) { + // if the reference is retargetable, zero it + name = new AssemblyNameReference (name.Name, new Version (0, 0, 0, 0)) { + PublicKeyToken = Empty.Array, + }; + } + + var framework_dir = Path.GetDirectoryName (typeof (object).Module.FullyQualifiedName); + + if (IsZero (name.Version)) { + assembly = SearchDirectory (name, new [] { framework_dir }, parameters); + if (assembly != null) + return assembly; + } + + if (name.Name == "mscorlib") { + assembly = GetCorlib (name, parameters); + if (assembly != null) + return assembly; + } + + assembly = GetAssemblyInGac (name, parameters); + if (assembly != null) + return assembly; + + assembly = SearchDirectory (name, new [] { framework_dir }, parameters); + if (assembly != null) + return assembly; +#endif + + if (ResolveFailure != null) { + assembly = ResolveFailure (this, name); + if (assembly != null) + return assembly; + } + + throw new AssemblyResolutionException (name); + } + + AssemblyDefinition SearchDirectory (AssemblyNameReference name, IEnumerable directories, ReaderParameters parameters) + { + var extensions = new [] { ".exe", ".dll" }; + foreach (var directory in directories) { + foreach (var extension in extensions) { + string file = Path.Combine (directory, name.Name + extension); + if (File.Exists (file)) + return GetAssembly (file, parameters); + } + } + + return null; + } + + static bool IsZero (Version version) + { + return version == null || (version.Major == 0 && version.Minor == 0 && version.Build == 0 && version.Revision == 0); + } + +#if !SILVERLIGHT && !CF + AssemblyDefinition GetCorlib (AssemblyNameReference reference, ReaderParameters parameters) + { + var version = reference.Version; + var corlib = typeof (object).Assembly.GetName (); + + if (corlib.Version == version || IsZero (version)) + return GetAssembly (typeof (object).Module.FullyQualifiedName, parameters); + + var path = Directory.GetParent ( + Directory.GetParent ( + typeof (object).Module.FullyQualifiedName).FullName + ).FullName; + + if (on_mono) { + if (version.Major == 1) + path = Path.Combine (path, "1.0"); + else if (version.Major == 2) { + if (version.MajorRevision == 5) + path = Path.Combine (path, "2.1"); + else + path = Path.Combine (path, "2.0"); + } else if (version.Major == 4) + path = Path.Combine (path, "4.0"); + else + throw new NotSupportedException ("Version not supported: " + version); + } else { + switch (version.Major) { + case 1: + if (version.MajorRevision == 3300) + path = Path.Combine (path, "v1.0.3705"); + else + path = Path.Combine (path, "v1.0.5000.0"); + break; + case 2: + path = Path.Combine (path, "v2.0.50727"); + break; + case 4: + path = Path.Combine (path, "v4.0.30319"); + break; + default: + throw new NotSupportedException ("Version not supported: " + version); + } + } + + var file = Path.Combine (path, "mscorlib.dll"); + if (File.Exists (file)) + return GetAssembly (file, parameters); + + return null; + } + + static Collection GetGacPaths () + { + if (on_mono) + return GetDefaultMonoGacPaths (); + + var paths = new Collection (2); + var windir = Environment.GetEnvironmentVariable ("WINDIR"); + if (windir == null) + return paths; + + paths.Add (Path.Combine (windir, "assembly")); + paths.Add (Path.Combine (windir, Path.Combine ("Microsoft.NET", "assembly"))); + return paths; + } + + static Collection GetDefaultMonoGacPaths () + { + var paths = new Collection (1); + var gac = GetCurrentMonoGac (); + if (gac != null) + paths.Add (gac); + + var gac_paths_env = Environment.GetEnvironmentVariable ("MONO_GAC_PREFIX"); + if (string.IsNullOrEmpty (gac_paths_env)) + return paths; + + var prefixes = gac_paths_env.Split (Path.PathSeparator); + foreach (var prefix in prefixes) { + if (string.IsNullOrEmpty (prefix)) + continue; + + var gac_path = Path.Combine (Path.Combine (Path.Combine (prefix, "lib"), "mono"), "gac"); + if (Directory.Exists (gac_path) && !paths.Contains (gac)) + paths.Add (gac_path); + } + + return paths; + } + + static string GetCurrentMonoGac () + { + return Path.Combine ( + Directory.GetParent ( + Path.GetDirectoryName (typeof (object).Module.FullyQualifiedName)).FullName, + "gac"); + } + + AssemblyDefinition GetAssemblyInGac (AssemblyNameReference reference, ReaderParameters parameters) + { + if (reference.PublicKeyToken == null || reference.PublicKeyToken.Length == 0) + return null; + + if (gac_paths == null) + gac_paths = GetGacPaths (); + + if (on_mono) + return GetAssemblyInMonoGac (reference, parameters); + + return GetAssemblyInNetGac (reference, parameters); + } + + AssemblyDefinition GetAssemblyInMonoGac (AssemblyNameReference reference, ReaderParameters parameters) + { + for (int i = 0; i < gac_paths.Count; i++) { + var gac_path = gac_paths [i]; + var file = GetAssemblyFile (reference, string.Empty, gac_path); + if (File.Exists (file)) + return GetAssembly (file, parameters); + } + + return null; + } + + AssemblyDefinition GetAssemblyInNetGac (AssemblyNameReference reference, ReaderParameters parameters) + { + var gacs = new [] { "GAC_MSIL", "GAC_32", "GAC" }; + var prefixes = new [] { string.Empty, "v4.0_" }; + + for (int i = 0; i < 2; i++) { + for (int j = 0; j < gacs.Length; j++) { + var gac = Path.Combine (gac_paths [i], gacs [j]); + var file = GetAssemblyFile (reference, prefixes [i], gac); + if (Directory.Exists (gac) && File.Exists (file)) + return GetAssembly (file, parameters); + } + } + + return null; + } + + static string GetAssemblyFile (AssemblyNameReference reference, string prefix, string gac) + { + var gac_folder = new StringBuilder () + .Append (prefix) + .Append (reference.Version) + .Append ("__"); + + for (int i = 0; i < reference.PublicKeyToken.Length; i++) + gac_folder.Append (reference.PublicKeyToken [i].ToString ("x2")); + + return Path.Combine ( + Path.Combine ( + Path.Combine (gac, reference.Name), gac_folder.ToString ()), + reference.Name + ".dll"); + } +#endif + } +} diff --git a/external/cecil-legacy/Mono.Cecil/CallSite.cs b/external/cecil-legacy/Mono.Cecil/CallSite.cs new file mode 100644 index 0000000000..2d4ed41759 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/CallSite.cs @@ -0,0 +1,124 @@ +// +// CallSite.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Text; + +using Mono.Collections.Generic; + +namespace Mono.Cecil { + + public sealed class CallSite : IMethodSignature { + + readonly MethodReference signature; + + public bool HasThis { + get { return signature.HasThis; } + set { signature.HasThis = value; } + } + + public bool ExplicitThis { + get { return signature.ExplicitThis; } + set { signature.ExplicitThis = value; } + } + + public MethodCallingConvention CallingConvention { + get { return signature.CallingConvention; } + set { signature.CallingConvention = value; } + } + + public bool HasParameters { + get { return signature.HasParameters; } + } + + public Collection Parameters { + get { return signature.Parameters; } + } + + public TypeReference ReturnType { + get { return signature.MethodReturnType.ReturnType; } + set { signature.MethodReturnType.ReturnType = value; } + } + + public MethodReturnType MethodReturnType { + get { return signature.MethodReturnType; } + } + + public string Name { + get { return string.Empty; } + set { throw new InvalidOperationException (); } + } + + public string Namespace { + get { return string.Empty; } + set { throw new InvalidOperationException (); } + } + + public ModuleDefinition Module { + get { return ReturnType.Module; } + } + + public IMetadataScope Scope { + get { return signature.ReturnType.Scope; } + } + + public MetadataToken MetadataToken { + get { return signature.token; } + set { signature.token = value; } + } + + public string FullName { + get { + var signature = new StringBuilder (); + signature.Append (ReturnType.FullName); + this.MethodSignatureFullName (signature); + return signature.ToString (); + } + } + + internal CallSite () + { + this.signature = new MethodReference (); + this.signature.token = new MetadataToken (TokenType.Signature, 0); + } + + public CallSite (TypeReference returnType) + : this () + { + if (returnType == null) + throw new ArgumentNullException ("returnType"); + + this.signature.ReturnType = returnType; + } + + public override string ToString () + { + return FullName; + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil/CustomAttribute.cs b/external/cecil-legacy/Mono.Cecil/CustomAttribute.cs new file mode 100644 index 0000000000..76372db0ee --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/CustomAttribute.cs @@ -0,0 +1,232 @@ +// +// CustomAttribute.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +using Mono.Collections.Generic; + +namespace Mono.Cecil { + + public struct CustomAttributeArgument { + + readonly TypeReference type; + readonly object value; + + public TypeReference Type { + get { return type; } + } + + public object Value { + get { return value; } + } + + public CustomAttributeArgument (TypeReference type, object value) + { + Mixin.CheckType (type); + this.type = type; + this.value = value; + } + } + + public struct CustomAttributeNamedArgument { + + readonly string name; + readonly CustomAttributeArgument argument; + + public string Name { + get { return name; } + } + + public CustomAttributeArgument Argument { + get { return argument; } + } + + public CustomAttributeNamedArgument (string name, CustomAttributeArgument argument) + { + Mixin.CheckName (name); + this.name = name; + this.argument = argument; + } + } + + public interface ICustomAttribute { + + TypeReference AttributeType { get; } + + bool HasFields { get; } + bool HasProperties { get; } + Collection Fields { get; } + Collection Properties { get; } + } + + public sealed class CustomAttribute : ICustomAttribute { + + readonly internal uint signature; + internal bool resolved; + MethodReference constructor; + byte [] blob; + internal Collection arguments; + internal Collection fields; + internal Collection properties; + + public MethodReference Constructor { + get { return constructor; } + set { constructor = value; } + } + + public TypeReference AttributeType { + get { return constructor.DeclaringType; } + } + + public bool IsResolved { + get { return resolved; } + } + + public bool HasConstructorArguments { + get { + Resolve (); + + return !arguments.IsNullOrEmpty (); + } + } + + public Collection ConstructorArguments { + get { + Resolve (); + + return arguments ?? (arguments = new Collection ()); + } + } + + public bool HasFields { + get { + Resolve (); + + return !fields.IsNullOrEmpty (); + } + } + + public Collection Fields { + get { + Resolve (); + + return fields ?? (fields = new Collection ()); + } + } + + public bool HasProperties { + get { + Resolve (); + + return !properties.IsNullOrEmpty (); + } + } + + public Collection Properties { + get { + Resolve (); + + return properties ?? (properties = new Collection ()); + } + } + + internal bool HasImage { + get { return constructor != null && constructor.HasImage; } + } + + internal ModuleDefinition Module { + get { return constructor.Module; } + } + + internal CustomAttribute (uint signature, MethodReference constructor) + { + this.signature = signature; + this.constructor = constructor; + this.resolved = false; + } + + public CustomAttribute (MethodReference constructor) + { + this.constructor = constructor; + this.resolved = true; + } + + public CustomAttribute (MethodReference constructor, byte [] blob) + { + this.constructor = constructor; + this.resolved = false; + this.blob = blob; + } + + public byte [] GetBlob () + { + if (blob != null) + return blob; + + if (!HasImage) + throw new NotSupportedException (); + + return blob = Module.Read (this, (attribute, reader) => reader.ReadCustomAttributeBlob (attribute.signature)); + } + + void Resolve () + { + if (resolved || !HasImage) + return; + + try { + Module.Read (this, (attribute, reader) => { + reader.ReadCustomAttributeSignature (attribute); + return this; + }); + + resolved = true; + } catch (ResolutionException) { + if (arguments != null) + arguments.Clear (); + if (fields != null) + fields.Clear (); + if (properties != null) + properties.Clear (); + + resolved = false; + } + } + } + + static partial class Mixin { + + public static void CheckName (string name) + { + if (name == null) + throw new ArgumentNullException ("name"); + if (name.Length == 0) + throw new ArgumentException ("Empty name"); + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil/DefaultAssemblyResolver.cs b/external/cecil-legacy/Mono.Cecil/DefaultAssemblyResolver.cs new file mode 100644 index 0000000000..e0baedf77a --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/DefaultAssemblyResolver.cs @@ -0,0 +1,70 @@ +// +// DefaultAssemblyResolver.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Collections.Generic; + +namespace Mono.Cecil { + + public class DefaultAssemblyResolver : BaseAssemblyResolver { + + readonly IDictionary cache; + + public DefaultAssemblyResolver () + { + cache = new Dictionary (StringComparer.Ordinal); + } + + public override AssemblyDefinition Resolve (AssemblyNameReference name) + { + if (name == null) + throw new ArgumentNullException ("name"); + + AssemblyDefinition assembly; + if (cache.TryGetValue (name.FullName, out assembly)) + return assembly; + + assembly = base.Resolve (name); + cache [name.FullName] = assembly; + + return assembly; + } + + protected void RegisterAssembly (AssemblyDefinition assembly) + { + if (assembly == null) + throw new ArgumentNullException ("assembly"); + + var name = assembly.Name.FullName; + if (cache.ContainsKey (name)) + return; + + cache [name] = assembly; + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil/EmbeddedResource.cs b/external/cecil-legacy/Mono.Cecil/EmbeddedResource.cs new file mode 100644 index 0000000000..e12dd0b378 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/EmbeddedResource.cs @@ -0,0 +1,105 @@ +// +// EmbeddedResource.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.IO; + +namespace Mono.Cecil { + + public sealed class EmbeddedResource : Resource { + + readonly MetadataReader reader; + + uint? offset; + byte [] data; + Stream stream; + + public override ResourceType ResourceType { + get { return ResourceType.Embedded; } + } + + public EmbeddedResource (string name, ManifestResourceAttributes attributes, byte [] data) : + base (name, attributes) + { + this.data = data; + } + + public EmbeddedResource (string name, ManifestResourceAttributes attributes, Stream stream) : + base (name, attributes) + { + this.stream = stream; + } + + internal EmbeddedResource (string name, ManifestResourceAttributes attributes, uint offset, MetadataReader reader) + : base (name, attributes) + { + this.offset = offset; + this.reader = reader; + } + + public Stream GetResourceStream () + { + if (stream != null) + return stream; + + if (data != null) + return new MemoryStream (data); + + if (offset.HasValue) + return reader.GetManagedResourceStream (offset.Value); + + throw new InvalidOperationException (); + } + + public byte [] GetResourceData () + { + if (stream != null) + return ReadStream (stream); + + if (data != null) + return data; + + if (offset.HasValue) + return reader.GetManagedResourceStream (offset.Value).ToArray (); + + throw new InvalidOperationException (); + } + + static byte [] ReadStream (Stream stream) + { + var length = (int) stream.Length; + var data = new byte [length]; + int offset = 0, read; + + while ((read = stream.Read (data, offset, length - offset)) > 0) + offset += read; + + return data; + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil/EventAttributes.cs b/external/cecil-legacy/Mono.Cecil/EventAttributes.cs new file mode 100644 index 0000000000..815efa57b7 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/EventAttributes.cs @@ -0,0 +1,39 @@ +// +// EventAttributes.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +namespace Mono.Cecil { + + [Flags] + public enum EventAttributes : ushort { + None = 0x0000, + SpecialName = 0x0200, // Event is special + RTSpecialName = 0x0400 // CLI provides 'special' behavior, depending upon the name of the event + } +} diff --git a/external/cecil-legacy/Mono.Cecil/EventDefinition.cs b/external/cecil-legacy/Mono.Cecil/EventDefinition.cs new file mode 100644 index 0000000000..89b55483f7 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/EventDefinition.cs @@ -0,0 +1,168 @@ +// +// EventDefinition.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using Mono.Collections.Generic; + +namespace Mono.Cecil { + + public sealed class EventDefinition : EventReference, IMemberDefinition { + + ushort attributes; + + Collection custom_attributes; + + internal MethodDefinition add_method; + internal MethodDefinition invoke_method; + internal MethodDefinition remove_method; + internal Collection other_methods; + + public EventAttributes Attributes { + get { return (EventAttributes) attributes; } + set { attributes = (ushort) value; } + } + + public MethodDefinition AddMethod { + get { + if (add_method != null) + return add_method; + + InitializeMethods (); + return add_method; + } + set { add_method = value; } + } + + public MethodDefinition InvokeMethod { + get { + if (invoke_method != null) + return invoke_method; + + InitializeMethods (); + return invoke_method; + } + set { invoke_method = value; } + } + + public MethodDefinition RemoveMethod { + get { + if (remove_method != null) + return remove_method; + + InitializeMethods (); + return remove_method; + } + set { remove_method = value; } + } + + public bool HasOtherMethods { + get { + if (other_methods != null) + return other_methods.Count > 0; + + InitializeMethods (); + return !other_methods.IsNullOrEmpty (); + } + } + + public Collection OtherMethods { + get { + if (other_methods != null) + return other_methods; + + InitializeMethods (); + + if (other_methods != null) + return other_methods; + + return other_methods = new Collection (); + } + } + + public bool HasCustomAttributes { + get { + if (custom_attributes != null) + return custom_attributes.Count > 0; + + return this.GetHasCustomAttributes (Module); + } + } + + public Collection CustomAttributes { + get { return custom_attributes ?? (custom_attributes = this.GetCustomAttributes (Module)); } + } + + #region EventAttributes + + public bool IsSpecialName { + get { return attributes.GetAttributes ((ushort) EventAttributes.SpecialName); } + set { attributes = attributes.SetAttributes ((ushort) EventAttributes.SpecialName, value); } + } + + public bool IsRuntimeSpecialName { + get { return attributes.GetAttributes ((ushort) EventAttributes.RTSpecialName); } + set { attributes = attributes.SetAttributes ((ushort) EventAttributes.RTSpecialName, value); } + } + + #endregion + + public new TypeDefinition DeclaringType { + get { return (TypeDefinition) base.DeclaringType; } + set { base.DeclaringType = value; } + } + + public override bool IsDefinition { + get { return true; } + } + + public EventDefinition (string name, EventAttributes attributes, TypeReference eventType) + : base (name, eventType) + { + this.attributes = (ushort) attributes; + this.token = new MetadataToken (TokenType.Event); + } + + void InitializeMethods () + { + if (add_method != null + || invoke_method != null + || remove_method != null) + return; + + var module = this.Module; + if (!module.HasImage ()) + return; + + module.Read (this, (@event, reader) => reader.ReadMethods (@event)); + } + + public override EventDefinition Resolve () + { + return this; + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil/EventReference.cs b/external/cecil-legacy/Mono.Cecil/EventReference.cs new file mode 100644 index 0000000000..8952002d6c --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/EventReference.cs @@ -0,0 +1,57 @@ +// +// EventReference.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +namespace Mono.Cecil { + + public abstract class EventReference : MemberReference { + + TypeReference event_type; + + public TypeReference EventType { + get { return event_type; } + set { event_type = value; } + } + + public override string FullName { + get { return event_type.FullName + " " + MemberFullName (); } + } + + protected EventReference (string name, TypeReference eventType) + : base (name) + { + if (eventType == null) + throw new ArgumentNullException ("eventType"); + + event_type = eventType; + } + + public abstract EventDefinition Resolve (); + } +} diff --git a/external/cecil-legacy/Mono.Cecil/ExportedType.cs b/external/cecil-legacy/Mono.Cecil/ExportedType.cs new file mode 100644 index 0000000000..c25f8d05ea --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/ExportedType.cs @@ -0,0 +1,249 @@ +// +// ExportedType.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +namespace Mono.Cecil { + + public class ExportedType : IMetadataTokenProvider { + + string @namespace; + string name; + uint attributes; + IMetadataScope scope; + ModuleDefinition module; + int identifier; + ExportedType declaring_type; + internal MetadataToken token; + + public string Namespace { + get { return @namespace; } + set { @namespace = value; } + } + + public string Name { + get { return name; } + set { name = value; } + } + + public TypeAttributes Attributes { + get { return (TypeAttributes) attributes; } + set { attributes = (uint) value; } + } + + public IMetadataScope Scope { + get { + if (declaring_type != null) + return declaring_type.Scope; + + return scope; + } + } + + public ExportedType DeclaringType { + get { return declaring_type; } + set { declaring_type = value; } + } + + public MetadataToken MetadataToken { + get { return token; } + set { token = value; } + } + + public int Identifier { + get { return identifier; } + set { identifier = value; } + } + + #region TypeAttributes + + public bool IsNotPublic { + get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NotPublic); } + set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NotPublic, value); } + } + + public bool IsPublic { + get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.Public); } + set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.Public, value); } + } + + public bool IsNestedPublic { + get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedPublic); } + set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedPublic, value); } + } + + public bool IsNestedPrivate { + get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedPrivate); } + set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedPrivate, value); } + } + + public bool IsNestedFamily { + get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedFamily); } + set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedFamily, value); } + } + + public bool IsNestedAssembly { + get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedAssembly); } + set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedAssembly, value); } + } + + public bool IsNestedFamilyAndAssembly { + get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedFamANDAssem); } + set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedFamANDAssem, value); } + } + + public bool IsNestedFamilyOrAssembly { + get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedFamORAssem); } + set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedFamORAssem, value); } + } + + public bool IsAutoLayout { + get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.LayoutMask, (uint) TypeAttributes.AutoLayout); } + set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.LayoutMask, (uint) TypeAttributes.AutoLayout, value); } + } + + public bool IsSequentialLayout { + get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.LayoutMask, (uint) TypeAttributes.SequentialLayout); } + set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.LayoutMask, (uint) TypeAttributes.SequentialLayout, value); } + } + + public bool IsExplicitLayout { + get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.LayoutMask, (uint) TypeAttributes.ExplicitLayout); } + set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.LayoutMask, (uint) TypeAttributes.ExplicitLayout, value); } + } + + public bool IsClass { + get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.ClassSemanticMask, (uint) TypeAttributes.Class); } + set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.ClassSemanticMask, (uint) TypeAttributes.Class, value); } + } + + public bool IsInterface { + get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.ClassSemanticMask, (uint) TypeAttributes.Interface); } + set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.ClassSemanticMask, (uint) TypeAttributes.Interface, value); } + } + + public bool IsAbstract { + get { return attributes.GetAttributes ((uint) TypeAttributes.Abstract); } + set { attributes = attributes.SetAttributes ((uint) TypeAttributes.Abstract, value); } + } + + public bool IsSealed { + get { return attributes.GetAttributes ((uint) TypeAttributes.Sealed); } + set { attributes = attributes.SetAttributes ((uint) TypeAttributes.Sealed, value); } + } + + public bool IsSpecialName { + get { return attributes.GetAttributes ((uint) TypeAttributes.SpecialName); } + set { attributes = attributes.SetAttributes ((uint) TypeAttributes.SpecialName, value); } + } + + public bool IsImport { + get { return attributes.GetAttributes ((uint) TypeAttributes.Import); } + set { attributes = attributes.SetAttributes ((uint) TypeAttributes.Import, value); } + } + + public bool IsSerializable { + get { return attributes.GetAttributes ((uint) TypeAttributes.Serializable); } + set { attributes = attributes.SetAttributes ((uint) TypeAttributes.Serializable, value); } + } + + public bool IsAnsiClass { + get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.StringFormatMask, (uint) TypeAttributes.AnsiClass); } + set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.StringFormatMask, (uint) TypeAttributes.AnsiClass, value); } + } + + public bool IsUnicodeClass { + get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.StringFormatMask, (uint) TypeAttributes.UnicodeClass); } + set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.StringFormatMask, (uint) TypeAttributes.UnicodeClass, value); } + } + + public bool IsAutoClass { + get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.StringFormatMask, (uint) TypeAttributes.AutoClass); } + set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.StringFormatMask, (uint) TypeAttributes.AutoClass, value); } + } + + public bool IsBeforeFieldInit { + get { return attributes.GetAttributes ((uint) TypeAttributes.BeforeFieldInit); } + set { attributes = attributes.SetAttributes ((uint) TypeAttributes.BeforeFieldInit, value); } + } + + public bool IsRuntimeSpecialName { + get { return attributes.GetAttributes ((uint) TypeAttributes.RTSpecialName); } + set { attributes = attributes.SetAttributes ((uint) TypeAttributes.RTSpecialName, value); } + } + + public bool HasSecurity { + get { return attributes.GetAttributes ((uint) TypeAttributes.HasSecurity); } + set { attributes = attributes.SetAttributes ((uint) TypeAttributes.HasSecurity, value); } + } + + #endregion + + public bool IsForwarder { + get { return attributes.GetAttributes ((uint) TypeAttributes.Forwarder); } + set { attributes = attributes.SetAttributes ((uint) TypeAttributes.Forwarder, value); } + } + + public string FullName { + get { + if (declaring_type != null) + return declaring_type.FullName + "/" + name; + + if (string.IsNullOrEmpty (@namespace)) + return name; + + return @namespace + "." + name; + } + } + + public ExportedType (string @namespace, string name, ModuleDefinition module, IMetadataScope scope) + { + this.@namespace = @namespace; + this.name = name; + this.scope = scope; + this.module = module; + } + + public override string ToString () + { + return FullName; + } + + public TypeDefinition Resolve () + { + return module.Resolve (CreateReference ()); + } + + internal TypeReference CreateReference () + { + return new TypeReference (@namespace, name, module, scope) { + DeclaringType = declaring_type != null ? declaring_type.CreateReference () : null, + }; + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil/FieldAttributes.cs b/external/cecil-legacy/Mono.Cecil/FieldAttributes.cs new file mode 100644 index 0000000000..dd6bf361dc --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/FieldAttributes.cs @@ -0,0 +1,59 @@ +// +// FieldAttributes.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +namespace Mono.Cecil { + + [Flags] + public enum FieldAttributes : ushort { + FieldAccessMask = 0x0007, + CompilerControlled = 0x0000, // Member not referenceable + Private = 0x0001, // Accessible only by the parent type + FamANDAssem = 0x0002, // Accessible by sub-types only in this assembly + Assembly = 0x0003, // Accessible by anyone in the Assembly + Family = 0x0004, // Accessible only by type and sub-types + FamORAssem = 0x0005, // Accessible by sub-types anywhere, plus anyone in the assembly + Public = 0x0006, // Accessible by anyone who has visibility to this scope field contract attributes + + Static = 0x0010, // Defined on type, else per instance + InitOnly = 0x0020, // Field may only be initialized, not written after init + Literal = 0x0040, // Value is compile time constant + NotSerialized = 0x0080, // Field does not have to be serialized when type is remoted + SpecialName = 0x0200, // Field is special + + // Interop Attributes + PInvokeImpl = 0x2000, // Implementation is forwarded through PInvoke + + // Additional flags + RTSpecialName = 0x0400, // CLI provides 'special' behavior, depending upon the name of the field + HasFieldMarshal = 0x1000, // Field has marshalling information + HasDefault = 0x8000, // Field has default + HasFieldRVA = 0x0100 // Field has RVA + } +} diff --git a/external/cecil-legacy/Mono.Cecil/FieldDefinition.cs b/external/cecil-legacy/Mono.Cecil/FieldDefinition.cs new file mode 100644 index 0000000000..29a1bc12ce --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/FieldDefinition.cs @@ -0,0 +1,279 @@ +// +// FieldDefinition.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using Mono.Collections.Generic; + +namespace Mono.Cecil { + + public sealed class FieldDefinition : FieldReference, IMemberDefinition, IConstantProvider, IMarshalInfoProvider { + + ushort attributes; + Collection custom_attributes; + + int offset = Mixin.NotResolvedMarker; + + internal int rva = Mixin.NotResolvedMarker; + byte [] initial_value; + + object constant = Mixin.NotResolved; + + MarshalInfo marshal_info; + + void ResolveLayout () + { + if (offset != Mixin.NotResolvedMarker) + return; + + if (!HasImage) { + offset = Mixin.NoDataMarker; + return; + } + + offset = Module.Read (this, (field, reader) => reader.ReadFieldLayout (field)); + } + + public bool HasLayoutInfo { + get { + if (offset >= 0) + return true; + + ResolveLayout (); + + return offset >= 0; + } + } + + public int Offset { + get { + if (offset >= 0) + return offset; + + ResolveLayout (); + + return offset >= 0 ? offset : -1; + } + set { offset = value; } + } + + void ResolveRVA () + { + if (rva != Mixin.NotResolvedMarker) + return; + + if (!HasImage) + return; + + rva = Module.Read (this, (field, reader) => reader.ReadFieldRVA (field)); + } + + public int RVA { + get { + if (rva > 0) + return rva; + + ResolveRVA (); + + return rva > 0 ? rva : 0; + } + } + + public byte [] InitialValue { + get { + if (initial_value != null) + return initial_value; + + ResolveRVA (); + + if (initial_value == null) + initial_value = Empty.Array; + + return initial_value; + } + set { initial_value = value; } + } + + public FieldAttributes Attributes { + get { return (FieldAttributes) attributes; } + set { attributes = (ushort) value; } + } + + public bool HasConstant { + get { + ResolveConstant (); + + return constant != Mixin.NoValue; + } + set { if (!value) constant = Mixin.NoValue; } + } + + public object Constant { + get { return HasConstant ? constant : null; } + set { constant = value; } + } + + void ResolveConstant () + { + if (constant != Mixin.NotResolved) + return; + + this.ResolveConstant (ref constant, Module); + } + + public bool HasCustomAttributes { + get { + if (custom_attributes != null) + return custom_attributes.Count > 0; + + return this.GetHasCustomAttributes (Module); + } + } + + public Collection CustomAttributes { + get { return custom_attributes ?? (custom_attributes = this.GetCustomAttributes (Module)); } + } + + public bool HasMarshalInfo { + get { + if (marshal_info != null) + return true; + + return this.GetHasMarshalInfo (Module); + } + } + + public MarshalInfo MarshalInfo { + get { return marshal_info ?? (marshal_info = this.GetMarshalInfo (Module)); } + set { marshal_info = value; } + } + + #region FieldAttributes + + public bool IsCompilerControlled { + get { return attributes.GetMaskedAttributes ((ushort) FieldAttributes.FieldAccessMask, (ushort) FieldAttributes.CompilerControlled); } + set { attributes = attributes.SetMaskedAttributes ((ushort) FieldAttributes.FieldAccessMask, (ushort) FieldAttributes.CompilerControlled, value); } + } + + public bool IsPrivate { + get { return attributes.GetMaskedAttributes ((ushort) FieldAttributes.FieldAccessMask, (ushort) FieldAttributes.Private); } + set { attributes = attributes.SetMaskedAttributes ((ushort) FieldAttributes.FieldAccessMask, (ushort) FieldAttributes.Private, value); } + } + + public bool IsFamilyAndAssembly { + get { return attributes.GetMaskedAttributes ((ushort) FieldAttributes.FieldAccessMask, (ushort) FieldAttributes.FamANDAssem); } + set { attributes = attributes.SetMaskedAttributes ((ushort) FieldAttributes.FieldAccessMask, (ushort) FieldAttributes.FamANDAssem, value); } + } + + public bool IsAssembly { + get { return attributes.GetMaskedAttributes ((ushort) FieldAttributes.FieldAccessMask, (ushort) FieldAttributes.Assembly); } + set { attributes = attributes.SetMaskedAttributes ((ushort) FieldAttributes.FieldAccessMask, (ushort) FieldAttributes.Assembly, value); } + } + + public bool IsFamily { + get { return attributes.GetMaskedAttributes ((ushort) FieldAttributes.FieldAccessMask, (ushort) FieldAttributes.Family); } + set { attributes = attributes.SetMaskedAttributes ((ushort) FieldAttributes.FieldAccessMask, (ushort) FieldAttributes.Family, value); } + } + + public bool IsFamilyOrAssembly { + get { return attributes.GetMaskedAttributes ((ushort) FieldAttributes.FieldAccessMask, (ushort) FieldAttributes.FamORAssem); } + set { attributes = attributes.SetMaskedAttributes ((ushort) FieldAttributes.FieldAccessMask, (ushort) FieldAttributes.FamORAssem, value); } + } + + public bool IsPublic { + get { return attributes.GetMaskedAttributes ((ushort) FieldAttributes.FieldAccessMask, (ushort) FieldAttributes.Public); } + set { attributes = attributes.SetMaskedAttributes ((ushort) FieldAttributes.FieldAccessMask, (ushort) FieldAttributes.Public, value); } + } + + public bool IsStatic { + get { return attributes.GetAttributes ((ushort) FieldAttributes.Static); } + set { attributes = attributes.SetAttributes ((ushort) FieldAttributes.Static, value); } + } + + public bool IsInitOnly { + get { return attributes.GetAttributes ((ushort) FieldAttributes.InitOnly); } + set { attributes = attributes.SetAttributes ((ushort) FieldAttributes.InitOnly, value); } + } + + public bool IsLiteral { + get { return attributes.GetAttributes ((ushort) FieldAttributes.Literal); } + set { attributes = attributes.SetAttributes ((ushort) FieldAttributes.Literal, value); } + } + + public bool IsNotSerialized { + get { return attributes.GetAttributes ((ushort) FieldAttributes.NotSerialized); } + set { attributes = attributes.SetAttributes ((ushort) FieldAttributes.NotSerialized, value); } + } + + public bool IsSpecialName { + get { return attributes.GetAttributes ((ushort) FieldAttributes.SpecialName); } + set { attributes = attributes.SetAttributes ((ushort) FieldAttributes.SpecialName, value); } + } + + public bool IsPInvokeImpl { + get { return attributes.GetAttributes ((ushort) FieldAttributes.PInvokeImpl); } + set { attributes = attributes.SetAttributes ((ushort) FieldAttributes.PInvokeImpl, value); } + } + + public bool IsRuntimeSpecialName { + get { return attributes.GetAttributes ((ushort) FieldAttributes.RTSpecialName); } + set { attributes = attributes.SetAttributes ((ushort) FieldAttributes.RTSpecialName, value); } + } + + public bool HasDefault { + get { return attributes.GetAttributes ((ushort) FieldAttributes.HasDefault); } + set { attributes = attributes.SetAttributes ((ushort) FieldAttributes.HasDefault, value); } + } + + #endregion + + public override bool IsDefinition { + get { return true; } + } + + public new TypeDefinition DeclaringType { + get { return (TypeDefinition) base.DeclaringType; } + set { base.DeclaringType = value; } + } + + public FieldDefinition (string name, FieldAttributes attributes, TypeReference fieldType) + : base (name, fieldType) + { + this.attributes = (ushort) attributes; + } + + public override FieldDefinition Resolve () + { + return this; + } + } + + static partial class Mixin { + + public const int NotResolvedMarker = -2; + public const int NoDataMarker = -1; + } +} diff --git a/external/cecil-legacy/Mono.Cecil/FieldReference.cs b/external/cecil-legacy/Mono.Cecil/FieldReference.cs new file mode 100644 index 0000000000..be58d3d063 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/FieldReference.cs @@ -0,0 +1,83 @@ +// +// FieldReference.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +namespace Mono.Cecil { + + public class FieldReference : MemberReference { + + TypeReference field_type; + + public TypeReference FieldType { + get { return field_type; } + set { field_type = value; } + } + + public override string FullName { + get { return field_type.FullName + " " + MemberFullName (); } + } + + internal override bool ContainsGenericParameter { + get { return field_type.ContainsGenericParameter || base.ContainsGenericParameter; } + } + + internal FieldReference () + { + this.token = new MetadataToken (TokenType.MemberRef); + } + + public FieldReference (string name, TypeReference fieldType) + : base (name) + { + if (fieldType == null) + throw new ArgumentNullException ("fieldType"); + + this.field_type = fieldType; + this.token = new MetadataToken (TokenType.MemberRef); + } + + public FieldReference (string name, TypeReference fieldType, TypeReference declaringType) + : this (name, fieldType) + { + if (declaringType == null) + throw new ArgumentNullException("declaringType"); + + this.DeclaringType = declaringType; + } + + public virtual FieldDefinition Resolve () + { + var module = this.Module; + if (module == null) + throw new NotSupportedException (); + + return module.Resolve (this); + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil/FileAttributes.cs b/external/cecil-legacy/Mono.Cecil/FileAttributes.cs new file mode 100644 index 0000000000..4d3b6ca7ff --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/FileAttributes.cs @@ -0,0 +1,35 @@ +// +// FileAttributes.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +namespace Mono.Cecil { + + enum FileAttributes : uint { + ContainsMetaData = 0x0000, // This is not a resource file + ContainsNoMetaData = 0x0001, // This is a resource file or other non-metadata-containing file + } +} diff --git a/external/cecil-legacy/Mono.Cecil/FunctionPointerType.cs b/external/cecil-legacy/Mono.Cecil/FunctionPointerType.cs new file mode 100644 index 0000000000..756d31f6ff --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/FunctionPointerType.cs @@ -0,0 +1,129 @@ +// +// FunctionPointerType.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Text; +using Mono.Collections.Generic; +using MD = Mono.Cecil.Metadata; + +namespace Mono.Cecil { + + public sealed class FunctionPointerType : TypeSpecification, IMethodSignature { + + readonly MethodReference function; + + public bool HasThis { + get { return function.HasThis; } + set { function.HasThis = value; } + } + + public bool ExplicitThis { + get { return function.ExplicitThis; } + set { function.ExplicitThis = value; } + } + + public MethodCallingConvention CallingConvention { + get { return function.CallingConvention; } + set { function.CallingConvention = value; } + } + + public bool HasParameters { + get { return function.HasParameters; } + } + + public Collection Parameters { + get { return function.Parameters; } + } + + public TypeReference ReturnType { + get { return function.MethodReturnType.ReturnType; } + set { function.MethodReturnType.ReturnType = value; } + } + + public MethodReturnType MethodReturnType { + get { return function.MethodReturnType; } + } + + public override string Name { + get { return function.Name; } + set { throw new InvalidOperationException (); } + } + + public override string Namespace { + get { return string.Empty; } + set { throw new InvalidOperationException (); } + } + + public override ModuleDefinition Module { + get { return ReturnType.Module; } + } + + public override IMetadataScope Scope { + get { return function.ReturnType.Scope; } + set { throw new InvalidOperationException (); } + } + + public override bool IsFunctionPointer { + get { return true; } + } + + internal override bool ContainsGenericParameter { + get { return function.ContainsGenericParameter; } + } + + public override string FullName { + get { + var signature = new StringBuilder (); + signature.Append (function.Name); + signature.Append (" "); + signature.Append (function.ReturnType.FullName); + signature.Append (" *"); + this.MethodSignatureFullName (signature); + return signature.ToString (); + } + } + + public FunctionPointerType () + : base (null) + { + this.function = new MethodReference (); + this.function.Name = "method"; + this.etype = MD.ElementType.FnPtr; + } + + public override TypeDefinition Resolve () + { + return null; + } + + public override TypeReference GetElementType () + { + return this; + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil/GenericInstanceMethod.cs b/external/cecil-legacy/Mono.Cecil/GenericInstanceMethod.cs new file mode 100644 index 0000000000..dbe720df56 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/GenericInstanceMethod.cs @@ -0,0 +1,85 @@ +// +// GenericInstanceMethod.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Text; + +using Mono.Collections.Generic; + +namespace Mono.Cecil { + + public sealed class GenericInstanceMethod : MethodSpecification, IGenericInstance, IGenericContext { + + Collection arguments; + + public bool HasGenericArguments { + get { return !arguments.IsNullOrEmpty (); } + } + + public Collection GenericArguments { + get { return arguments ?? (arguments = new Collection ()); } + } + + public override bool IsGenericInstance { + get { return true; } + } + + IGenericParameterProvider IGenericContext.Method { + get { return ElementMethod; } + } + + IGenericParameterProvider IGenericContext.Type { + get { return ElementMethod.DeclaringType; } + } + + internal override bool ContainsGenericParameter { + get { return this.ContainsGenericParameter () || base.ContainsGenericParameter; } + } + + public override string FullName { + get { + var signature = new StringBuilder (); + var method = this.ElementMethod; + signature.Append (method.ReturnType.FullName) + .Append (" ") + .Append (method.DeclaringType.FullName) + .Append ("::") + .Append (method.Name); + this.GenericInstanceFullName (signature); + this.MethodSignatureFullName (signature); + return signature.ToString (); + + } + } + + public GenericInstanceMethod (MethodReference method) + : base (method) + { + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil/GenericInstanceType.cs b/external/cecil-legacy/Mono.Cecil/GenericInstanceType.cs new file mode 100644 index 0000000000..6554ff0e89 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/GenericInstanceType.cs @@ -0,0 +1,83 @@ +// +// GenericInstanceType.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Text; + +using Mono.Collections.Generic; + +using MD = Mono.Cecil.Metadata; + +namespace Mono.Cecil { + + public sealed class GenericInstanceType : TypeSpecification, IGenericInstance, IGenericContext { + + Collection arguments; + + public bool HasGenericArguments { + get { return !arguments.IsNullOrEmpty (); } + } + + public Collection GenericArguments { + get { return arguments ?? (arguments = new Collection ()); } + } + + public override TypeReference DeclaringType { + get { return ElementType.DeclaringType; } + set { throw new NotSupportedException (); } + } + + public override string FullName { + get { + var name = new StringBuilder (); + name.Append (base.FullName); + this.GenericInstanceFullName (name); + return name.ToString (); + } + } + + public override bool IsGenericInstance { + get { return true; } + } + + internal override bool ContainsGenericParameter { + get { return this.ContainsGenericParameter () || base.ContainsGenericParameter; } + } + + IGenericParameterProvider IGenericContext.Type { + get { return ElementType; } + } + + public GenericInstanceType (TypeReference type) + : base (type) + { + base.IsValueType = type.IsValueType; + this.etype = MD.ElementType.GenericInst; + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil/GenericParameter.cs b/external/cecil-legacy/Mono.Cecil/GenericParameter.cs new file mode 100644 index 0000000000..d66cc914cb --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/GenericParameter.cs @@ -0,0 +1,287 @@ +// +// GenericParameter.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +using Mono.Collections.Generic; + +using Mono.Cecil.Metadata; + +namespace Mono.Cecil { + + public sealed class GenericParameter : TypeReference, ICustomAttributeProvider { + + internal int position; + internal GenericParameterType type; + internal IGenericParameterProvider owner; + + ushort attributes; + Collection constraints; + Collection custom_attributes; + + public GenericParameterAttributes Attributes { + get { return (GenericParameterAttributes) attributes; } + set { attributes = (ushort) value; } + } + + public int Position { + get { return position; } + } + + public GenericParameterType Type { + get { return type; } + } + + public IGenericParameterProvider Owner { + get { return owner; } + } + + public bool HasConstraints { + get { + if (constraints != null) + return constraints.Count > 0; + + if (HasImage) + return Module.Read (this, (generic_parameter, reader) => reader.HasGenericConstraints (generic_parameter)); + + return false; + } + } + + public Collection Constraints { + get { + if (constraints != null) + return constraints; + + if (HasImage) + return constraints = Module.Read (this, (generic_parameter, reader) => reader.ReadGenericConstraints (generic_parameter)); + + return constraints = new Collection (); + } + } + + public bool HasCustomAttributes { + get { + if (custom_attributes != null) + return custom_attributes.Count > 0; + + return this.GetHasCustomAttributes (Module); + } + } + + public Collection CustomAttributes { + get { return custom_attributes ?? (custom_attributes = this.GetCustomAttributes (Module)); } + } + + public override IMetadataScope Scope { + get { + if (owner == null) + return null; + + return owner.GenericParameterType == GenericParameterType.Method + ? ((MethodReference) owner).DeclaringType.Scope + : ((TypeReference) owner).Scope; + } + set { throw new InvalidOperationException (); } + } + + public override TypeReference DeclaringType { + get { return owner as TypeReference; } + set { throw new InvalidOperationException (); } + } + + public MethodReference DeclaringMethod { + get { return owner as MethodReference; } + } + + public override ModuleDefinition Module { + get { return module ?? owner.Module; } + } + + public override string Name { + get { + if (!string.IsNullOrEmpty (base.Name)) + return base.Name; + + return base.Name = (type == GenericParameterType.Method ? "!!" : "!") + position; + } + } + + public override string Namespace { + get { return string.Empty; } + set { throw new InvalidOperationException (); } + } + + public override string FullName { + get { return Name; } + } + + public override bool IsGenericParameter { + get { return true; } + } + + internal override bool ContainsGenericParameter { + get { return true; } + } + + public override MetadataType MetadataType { + get { return (MetadataType) etype; } + } + + #region GenericParameterAttributes + + public bool IsNonVariant { + get { return attributes.GetMaskedAttributes ((ushort) GenericParameterAttributes.VarianceMask, (ushort) GenericParameterAttributes.NonVariant); } + set { attributes = attributes.SetMaskedAttributes ((ushort) GenericParameterAttributes.VarianceMask, (ushort) GenericParameterAttributes.NonVariant, value); } + } + + public bool IsCovariant { + get { return attributes.GetMaskedAttributes ((ushort) GenericParameterAttributes.VarianceMask, (ushort) GenericParameterAttributes.Covariant); } + set { attributes = attributes.SetMaskedAttributes ((ushort) GenericParameterAttributes.VarianceMask, (ushort) GenericParameterAttributes.Covariant, value); } + } + + public bool IsContravariant { + get { return attributes.GetMaskedAttributes ((ushort) GenericParameterAttributes.VarianceMask, (ushort) GenericParameterAttributes.Contravariant); } + set { attributes = attributes.SetMaskedAttributes ((ushort) GenericParameterAttributes.VarianceMask, (ushort) GenericParameterAttributes.Contravariant, value); } + } + + public bool HasReferenceTypeConstraint { + get { return attributes.GetAttributes ((ushort) GenericParameterAttributes.ReferenceTypeConstraint); } + set { attributes = attributes.SetAttributes ((ushort) GenericParameterAttributes.ReferenceTypeConstraint, value); } + } + + public bool HasNotNullableValueTypeConstraint { + get { return attributes.GetAttributes ((ushort) GenericParameterAttributes.NotNullableValueTypeConstraint); } + set { attributes = attributes.SetAttributes ((ushort) GenericParameterAttributes.NotNullableValueTypeConstraint, value); } + } + + public bool HasDefaultConstructorConstraint { + get { return attributes.GetAttributes ((ushort) GenericParameterAttributes.DefaultConstructorConstraint); } + set { attributes = attributes.SetAttributes ((ushort) GenericParameterAttributes.DefaultConstructorConstraint, value); } + } + + #endregion + + public GenericParameter (IGenericParameterProvider owner) + : this (string.Empty, owner) + { + } + + public GenericParameter (string name, IGenericParameterProvider owner) + : base (string.Empty, name) + { + if (owner == null) + throw new ArgumentNullException (); + + this.position = -1; + this.owner = owner; + this.type = owner.GenericParameterType; + this.etype = ConvertGenericParameterType (this.type); + } + + public GenericParameter (int position, GenericParameterType type, ModuleDefinition module) + : base (string.Empty, string.Empty) + { + if (module == null) + throw new ArgumentNullException (); + + this.position = position; + this.type = type; + this.etype = ConvertGenericParameterType (type); + this.module = module; + } + + static ElementType ConvertGenericParameterType (GenericParameterType type) + { + switch (type) { + case GenericParameterType.Type: + return ElementType.Var; + case GenericParameterType.Method: + return ElementType.MVar; + } + + throw new ArgumentOutOfRangeException (); + } + + public override TypeDefinition Resolve () + { + return null; + } + } + + sealed class GenericParameterCollection : Collection { + + readonly IGenericParameterProvider owner; + + internal GenericParameterCollection (IGenericParameterProvider owner) + { + this.owner = owner; + } + + internal GenericParameterCollection (IGenericParameterProvider owner, int capacity) + : base (capacity) + { + this.owner = owner; + } + + protected override void OnAdd (GenericParameter item, int index) + { + UpdateGenericParameter (item, index); + } + + protected override void OnInsert (GenericParameter item, int index) + { + UpdateGenericParameter (item, index); + + for (int i = index; i < size; i++) + items[i].position = i + 1; + } + + protected override void OnSet (GenericParameter item, int index) + { + UpdateGenericParameter (item, index); + } + + void UpdateGenericParameter (GenericParameter item, int index) + { + item.owner = owner; + item.position = index; + item.type = owner.GenericParameterType; + } + + protected override void OnRemove (GenericParameter item, int index) + { + item.owner = null; + item.position = -1; + item.type = GenericParameterType.Type; + + for (int i = index + 1; i < size; i++) + items[i].position = i - 1; + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil/GenericParameterAttributes.cs b/external/cecil-legacy/Mono.Cecil/GenericParameterAttributes.cs new file mode 100644 index 0000000000..6d77956de3 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/GenericParameterAttributes.cs @@ -0,0 +1,45 @@ +// +// GenericParameterAttributes.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +namespace Mono.Cecil { + + [Flags] + public enum GenericParameterAttributes : ushort { + VarianceMask = 0x0003, + NonVariant = 0x0000, + Covariant = 0x0001, + Contravariant = 0x0002, + + SpecialConstraintMask = 0x001c, + ReferenceTypeConstraint = 0x0004, + NotNullableValueTypeConstraint = 0x0008, + DefaultConstructorConstraint = 0x0010 + } +} diff --git a/external/cecil-legacy/Mono.Cecil/IConstantProvider.cs b/external/cecil-legacy/Mono.Cecil/IConstantProvider.cs new file mode 100644 index 0000000000..8bcd7d7f02 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/IConstantProvider.cs @@ -0,0 +1,52 @@ +// +// IConstantProvider.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +namespace Mono.Cecil { + + public interface IConstantProvider : IMetadataTokenProvider { + + bool HasConstant { get; set; } + object Constant { get; set; } + } + + static partial class Mixin { + + internal static object NoValue = new object (); + internal static object NotResolved = new object (); + + public static void ResolveConstant ( + this IConstantProvider self, + ref object constant, + ModuleDefinition module) + { + constant = module.HasImage () + ? module.Read (self, (provider, reader) => reader.ReadConstant (provider)) + : Mixin.NoValue; + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil/ICustomAttributeProvider.cs b/external/cecil-legacy/Mono.Cecil/ICustomAttributeProvider.cs new file mode 100644 index 0000000000..916ba0f541 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/ICustomAttributeProvider.cs @@ -0,0 +1,60 @@ +// +// ICustomAttributeProvider.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +using Mono.Collections.Generic; + +namespace Mono.Cecil { + + public interface ICustomAttributeProvider : IMetadataTokenProvider { + + Collection CustomAttributes { get; } + + bool HasCustomAttributes { get; } + } + + static partial class Mixin { + + public static bool GetHasCustomAttributes ( + this ICustomAttributeProvider self, + ModuleDefinition module) + { + return module.HasImage () && module.Read (self, (provider, reader) => reader.HasCustomAttributes (provider)); + } + + public static Collection GetCustomAttributes ( + this ICustomAttributeProvider self, + ModuleDefinition module) + { + return module.HasImage () + ? module.Read (self, (provider, reader) => reader.ReadCustomAttributes (provider)) + : new Collection (); + } + } +} diff --git a/mcs/class/corlib/System.Reflection/TargetInvocationException.cs b/external/cecil-legacy/Mono.Cecil/IGenericInstance.cs similarity index 53% rename from mcs/class/corlib/System.Reflection/TargetInvocationException.cs rename to external/cecil-legacy/Mono.Cecil/IGenericInstance.cs index 345368f799..edc406ca10 100644 --- a/mcs/class/corlib/System.Reflection/TargetInvocationException.cs +++ b/external/cecil-legacy/Mono.Cecil/IGenericInstance.cs @@ -1,13 +1,10 @@ // -// System.Reflection.TargetInvocationException +// IGenericInstance.cs // -// Sean MacIsaac (macisaac@ximian.com) -// Duncan Mak (duncan@ximian.com) +// Author: +// Jb Evain (jbevain@gmail.com) // -// (C) 2001 Ximian, Inc. - -// -// Copyright (C) 2004 Novell, Inc (http://www.novell.com) +// Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the @@ -16,10 +13,10 @@ // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: -// +// // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND @@ -29,31 +26,41 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -using System.Runtime.Serialization; -using System.Runtime.InteropServices; +using System.Text; -namespace System.Reflection -{ - [ComVisible (true)] - [Serializable] -#if NET_2_1 - public sealed class TargetInvocationException : Exception { -#else - public sealed class TargetInvocationException : ApplicationException { -#endif - public TargetInvocationException (Exception inner) - : base ("Exception has been thrown by the target of an invocation.", inner) - { +using Mono.Collections.Generic; + +namespace Mono.Cecil { + + public interface IGenericInstance : IMetadataTokenProvider { + + bool HasGenericArguments { get; } + Collection GenericArguments { get; } + } + + static partial class Mixin { + + public static bool ContainsGenericParameter (this IGenericInstance self) + { + var arguments = self.GenericArguments; + + for (int i = 0; i < arguments.Count; i++) + if (arguments [i].ContainsGenericParameter) + return true; + + return false; } - public TargetInvocationException (string message, Exception inner) - : base (message, inner) - { - } - - internal TargetInvocationException (SerializationInfo info, StreamingContext sc) - : base (info, sc) + public static void GenericInstanceFullName (this IGenericInstance self, StringBuilder builder) { + builder.Append ("<"); + var arguments = self.GenericArguments; + for (int i = 0; i < arguments.Count; i++) { + if (i > 0) + builder.Append (","); + builder.Append (arguments [i].FullName); + } + builder.Append (">"); } - } + } } diff --git a/external/cecil-legacy/Mono.Cecil/IGenericParameterProvider.cs b/external/cecil-legacy/Mono.Cecil/IGenericParameterProvider.cs new file mode 100644 index 0000000000..d41b7f6d08 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/IGenericParameterProvider.cs @@ -0,0 +1,73 @@ +// +// IGenericParameterProvider.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + + +using Mono.Collections.Generic; + +namespace Mono.Cecil { + + public interface IGenericParameterProvider : IMetadataTokenProvider { + + bool HasGenericParameters { get; } + bool IsDefinition { get; } + ModuleDefinition Module { get; } + Collection GenericParameters { get; } + GenericParameterType GenericParameterType { get; } + } + + public enum GenericParameterType { + Type, + Method + } + + interface IGenericContext { + + bool IsDefinition { get; } + IGenericParameterProvider Type { get; } + IGenericParameterProvider Method { get; } + } + + static partial class Mixin { + + public static bool GetHasGenericParameters ( + this IGenericParameterProvider self, + ModuleDefinition module) + { + return module.HasImage () && module.Read (self, (provider, reader) => reader.HasGenericParameters (provider)); + } + + public static Collection GetGenericParameters ( + this IGenericParameterProvider self, + ModuleDefinition module) + { + return module.HasImage () + ? module.Read (self, (provider, reader) => reader.ReadGenericParameters (provider)) + : new GenericParameterCollection (self); + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil/IMarshalInfoProvider.cs b/external/cecil-legacy/Mono.Cecil/IMarshalInfoProvider.cs new file mode 100644 index 0000000000..67a53a389f --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/IMarshalInfoProvider.cs @@ -0,0 +1,55 @@ +// +// IMarshalInfoProvider.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +namespace Mono.Cecil { + + public interface IMarshalInfoProvider : IMetadataTokenProvider { + + bool HasMarshalInfo { get; } + MarshalInfo MarshalInfo { get; set; } + } + + static partial class Mixin { + + public static bool GetHasMarshalInfo ( + this IMarshalInfoProvider self, + ModuleDefinition module) + { + return module.HasImage () && module.Read (self, (provider, reader) => reader.HasMarshalInfo (provider)); + } + + public static MarshalInfo GetMarshalInfo ( + this IMarshalInfoProvider self, + ModuleDefinition module) + { + return module.HasImage () + ? module.Read (self, (provider, reader) => reader.ReadMarshalInfo (provider)) + : null; + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil/IMemberDefinition.cs b/external/cecil-legacy/Mono.Cecil/IMemberDefinition.cs new file mode 100644 index 0000000000..ee73d9da49 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/IMemberDefinition.cs @@ -0,0 +1,100 @@ +// +// IMemberDefinition.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +namespace Mono.Cecil { + + public interface IMemberDefinition : ICustomAttributeProvider { + + string Name { get; set; } + string FullName { get; } + + bool IsSpecialName { get; set; } + bool IsRuntimeSpecialName { get; set; } + + TypeDefinition DeclaringType { get; set; } + } + + static partial class Mixin { + + public static bool GetAttributes (this uint self, uint attributes) + { + return (self & attributes) != 0; + } + + public static uint SetAttributes (this uint self, uint attributes, bool value) + { + if (value) + return self | attributes; + + return self & ~attributes; + } + + public static bool GetMaskedAttributes (this uint self, uint mask, uint attributes) + { + return (self & mask) == attributes; + } + + public static uint SetMaskedAttributes (this uint self, uint mask, uint attributes, bool value) + { + if (value) { + self &= ~mask; + return self | attributes; + } + + return self & ~(mask & attributes); + } + + public static bool GetAttributes (this ushort self, ushort attributes) + { + return (self & attributes) != 0; + } + + public static ushort SetAttributes (this ushort self, ushort attributes, bool value) + { + if (value) + return (ushort) (self | attributes); + + return (ushort) (self & ~attributes); + } + + public static bool GetMaskedAttributes (this ushort self, ushort mask, uint attributes) + { + return (self & mask) == attributes; + } + + public static ushort SetMaskedAttributes (this ushort self, ushort mask, uint attributes, bool value) + { + if (value) { + self = (ushort) (self & ~mask); + return (ushort) (self | attributes); + } + + return (ushort) (self & ~(mask & attributes)); + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil/IMetadataScope.cs b/external/cecil-legacy/Mono.Cecil/IMetadataScope.cs new file mode 100644 index 0000000000..04a0228105 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/IMetadataScope.cs @@ -0,0 +1,41 @@ +// +// IMetadataScope.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +namespace Mono.Cecil { + + public enum MetadataScopeType { + AssemblyNameReference, + ModuleReference, + ModuleDefinition, + } + + public interface IMetadataScope : IMetadataTokenProvider { + MetadataScopeType MetadataScopeType { get; } + string Name { get; set; } + } +} diff --git a/external/cecil-legacy/Mono.Cecil/IMetadataTokenProvider.cs b/external/cecil-legacy/Mono.Cecil/IMetadataTokenProvider.cs new file mode 100644 index 0000000000..6621835b29 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/IMetadataTokenProvider.cs @@ -0,0 +1,35 @@ +// +// IMetadataTokenProvider.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +namespace Mono.Cecil { + + public interface IMetadataTokenProvider { + + MetadataToken MetadataToken { get; set; } + } +} diff --git a/external/cecil-legacy/Mono.Cecil/IMethodSignature.cs b/external/cecil-legacy/Mono.Cecil/IMethodSignature.cs new file mode 100644 index 0000000000..e3d288ba9f --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/IMethodSignature.cs @@ -0,0 +1,75 @@ +// +// IMethodSignature.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System.Text; + +using Mono.Collections.Generic; + +namespace Mono.Cecil { + + public interface IMethodSignature : IMetadataTokenProvider { + + bool HasThis { get; set; } + bool ExplicitThis { get; set; } + MethodCallingConvention CallingConvention { get; set; } + + bool HasParameters { get; } + Collection Parameters { get; } + TypeReference ReturnType { get; set; } + MethodReturnType MethodReturnType { get; } + } + + static partial class Mixin { + + public static bool HasImplicitThis (this IMethodSignature self) + { + return self.HasThis && !self.ExplicitThis; + } + + public static void MethodSignatureFullName (this IMethodSignature self, StringBuilder builder) + { + builder.Append ("("); + + if (self.HasParameters) { + var parameters = self.Parameters; + for (int i = 0; i < parameters.Count; i++) { + var parameter = parameters [i]; + if (i > 0) + builder.Append (","); + + if (parameter.ParameterType.IsSentinel) + builder.Append ("...,"); + + builder.Append (parameter.ParameterType.FullName); + } + } + + builder.Append (")"); + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil/Import.cs b/external/cecil-legacy/Mono.Cecil/Import.cs new file mode 100644 index 0000000000..93040101c9 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/Import.cs @@ -0,0 +1,670 @@ +// +// Import.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Collections.Generic; +using Mono.Collections.Generic; +using SR = System.Reflection; + +using Mono.Cecil.Metadata; + +namespace Mono.Cecil { + + enum ImportGenericKind { + Definition, + Open, + } + + struct ImportGenericContext { + + Collection stack; + + public bool IsEmpty { get { return stack == null; } } + + public ImportGenericContext (IGenericParameterProvider provider) + { + stack = null; + + Push (provider); + } + + public void Push (IGenericParameterProvider provider) + { + if (stack == null) + stack = new Collection (1) { provider }; + else + stack.Add (provider); + } + + public void Pop () + { + stack.RemoveAt (stack.Count - 1); + } + + public TypeReference MethodParameter (string method, int position) + { + for (int i = stack.Count - 1; i >= 0; i--) { + var candidate = stack [i] as MethodReference; + if (candidate == null) + continue; + + if (method != candidate.Name) + continue; + + return candidate.GenericParameters [position]; + } + + throw new InvalidOperationException (); + } + + public TypeReference TypeParameter (string type, int position) + { + for (int i = stack.Count - 1; i >= 0; i--) { + var candidate = GenericTypeFor (stack [i]); + + if (candidate.FullName != type) + continue; + + return candidate.GenericParameters [position]; + } + + throw new InvalidOperationException (); + } + + static TypeReference GenericTypeFor (IGenericParameterProvider context) + { + var type = context as TypeReference; + if (type != null) + return type.GetElementType (); + + var method = context as MethodReference; + if (method != null) + return method.DeclaringType.GetElementType (); + + throw new InvalidOperationException (); + } + } + + class MetadataImporter { + + readonly ModuleDefinition module; + + public MetadataImporter (ModuleDefinition module) + { + this.module = module; + } + +#if !CF + static readonly Dictionary type_etype_mapping = new Dictionary (18) { + { typeof (void), ElementType.Void }, + { typeof (bool), ElementType.Boolean }, + { typeof (char), ElementType.Char }, + { typeof (sbyte), ElementType.I1 }, + { typeof (byte), ElementType.U1 }, + { typeof (short), ElementType.I2 }, + { typeof (ushort), ElementType.U2 }, + { typeof (int), ElementType.I4 }, + { typeof (uint), ElementType.U4 }, + { typeof (long), ElementType.I8 }, + { typeof (ulong), ElementType.U8 }, + { typeof (float), ElementType.R4 }, + { typeof (double), ElementType.R8 }, + { typeof (string), ElementType.String }, + { typeof (TypedReference), ElementType.TypedByRef }, + { typeof (IntPtr), ElementType.I }, + { typeof (UIntPtr), ElementType.U }, + { typeof (object), ElementType.Object }, + }; + + public TypeReference ImportType (Type type, ImportGenericContext context) + { + return ImportType (type, context, ImportGenericKind.Open); + } + + public TypeReference ImportType (Type type, ImportGenericContext context, ImportGenericKind import_kind) + { + if (IsTypeSpecification (type) || ImportOpenGenericType (type, import_kind)) + return ImportTypeSpecification (type, context); + + var reference = new TypeReference ( + string.Empty, + type.Name, + module, + ImportScope (type.Assembly), + type.IsValueType); + + reference.etype = ImportElementType (type); + + if (IsNestedType (type)) + reference.DeclaringType = ImportType (type.DeclaringType, context, import_kind); + else + reference.Namespace = type.Namespace ?? string.Empty; + + if (type.IsGenericType) + ImportGenericParameters (reference, type.GetGenericArguments ()); + + return reference; + } + + static bool ImportOpenGenericType (Type type, ImportGenericKind import_kind) + { + return type.IsGenericType && type.IsGenericTypeDefinition && import_kind == ImportGenericKind.Open; + } + + static bool ImportOpenGenericMethod (SR.MethodBase method, ImportGenericKind import_kind) + { + return method.IsGenericMethod && method.IsGenericMethodDefinition && import_kind == ImportGenericKind.Open; + } + + static bool IsNestedType (Type type) + { +#if !SILVERLIGHT + return type.IsNested; +#else + return type.DeclaringType != null; +#endif + } + + TypeReference ImportTypeSpecification (Type type, ImportGenericContext context) + { + if (type.IsByRef) + return new ByReferenceType (ImportType (type.GetElementType (), context)); + + if (type.IsPointer) + return new PointerType (ImportType (type.GetElementType (), context)); + + if (type.IsArray) + return new ArrayType (ImportType (type.GetElementType (), context), type.GetArrayRank ()); + + if (type.IsGenericType) + return ImportGenericInstance (type, context); + + if (type.IsGenericParameter) + return ImportGenericParameter (type, context); + + throw new NotSupportedException (type.FullName); + } + + static TypeReference ImportGenericParameter (Type type, ImportGenericContext context) + { + if (context.IsEmpty) + throw new InvalidOperationException (); + + if (type.DeclaringMethod != null) + return context.MethodParameter (type.DeclaringMethod.Name, type.GenericParameterPosition); + + if (type.DeclaringType != null) + return context.TypeParameter (NormalizedFullName (type.DeclaringType), type.GenericParameterPosition); + + throw new InvalidOperationException(); + } + + private static string NormalizedFullName (Type type) + { + if (IsNestedType (type)) + return NormalizedFullName (type.DeclaringType) + "/" + type.Name; + + return type.FullName; + } + + TypeReference ImportGenericInstance (Type type, ImportGenericContext context) + { + var element_type = ImportType (type.GetGenericTypeDefinition (), context, ImportGenericKind.Definition); + var instance = new GenericInstanceType (element_type); + var arguments = type.GetGenericArguments (); + var instance_arguments = instance.GenericArguments; + + context.Push (element_type); + try { + for (int i = 0; i < arguments.Length; i++) + instance_arguments.Add (ImportType (arguments [i], context)); + + return instance; + } finally { + context.Pop (); + } + } + + static bool IsTypeSpecification (Type type) + { + return type.HasElementType + || IsGenericInstance (type) + || type.IsGenericParameter; + } + + static bool IsGenericInstance (Type type) + { + return type.IsGenericType && !type.IsGenericTypeDefinition; + } + + static ElementType ImportElementType (Type type) + { + ElementType etype; + if (!type_etype_mapping.TryGetValue (type, out etype)) + return ElementType.None; + + return etype; + } + + AssemblyNameReference ImportScope (SR.Assembly assembly) + { + AssemblyNameReference scope; +#if !SILVERLIGHT + var name = assembly.GetName (); + + if (TryGetAssemblyNameReference (name, out scope)) + return scope; + + scope = new AssemblyNameReference (name.Name, name.Version) { + Culture = name.CultureInfo.Name, + PublicKeyToken = name.GetPublicKeyToken (), + HashAlgorithm = (AssemblyHashAlgorithm) name.HashAlgorithm, + }; + + module.AssemblyReferences.Add (scope); + + return scope; +#else + var name = AssemblyNameReference.Parse (assembly.FullName); + + if (TryGetAssemblyNameReference (name, out scope)) + return scope; + + module.AssemblyReferences.Add (name); + + return name; +#endif + } + +#if !SILVERLIGHT + bool TryGetAssemblyNameReference (SR.AssemblyName name, out AssemblyNameReference assembly_reference) + { + var references = module.AssemblyReferences; + + for (int i = 0; i < references.Count; i++) { + var reference = references [i]; + if (name.FullName != reference.FullName) // TODO compare field by field + continue; + + assembly_reference = reference; + return true; + } + + assembly_reference = null; + return false; + } +#endif + + public FieldReference ImportField (SR.FieldInfo field, ImportGenericContext context) + { + var declaring_type = ImportType (field.DeclaringType, context); + + if (IsGenericInstance (field.DeclaringType)) + field = ResolveFieldDefinition (field); + + context.Push (declaring_type); + try { + return new FieldReference { + Name = field.Name, + DeclaringType = declaring_type, + FieldType = ImportType (field.FieldType, context), + }; + } finally { + context.Pop (); + } + } + + static SR.FieldInfo ResolveFieldDefinition (SR.FieldInfo field) + { +#if !SILVERLIGHT + return field.Module.ResolveField (field.MetadataToken); +#else + return field.DeclaringType.GetGenericTypeDefinition ().GetField (field.Name, + SR.BindingFlags.Public + | SR.BindingFlags.NonPublic + | (field.IsStatic ? SR.BindingFlags.Static : SR.BindingFlags.Instance)); +#endif + } + + public MethodReference ImportMethod (SR.MethodBase method, ImportGenericContext context, ImportGenericKind import_kind) + { + if (IsMethodSpecification (method) || ImportOpenGenericMethod (method, import_kind)) + return ImportMethodSpecification (method, context); + + var declaring_type = ImportType (method.DeclaringType, context); + + if (IsGenericInstance (method.DeclaringType)) + method = method.Module.ResolveMethod (method.MetadataToken); + + var reference = new MethodReference { + Name = method.Name, + HasThis = HasCallingConvention (method, SR.CallingConventions.HasThis), + ExplicitThis = HasCallingConvention (method, SR.CallingConventions.ExplicitThis), + DeclaringType = ImportType (method.DeclaringType, context, ImportGenericKind.Definition), + }; + + if (HasCallingConvention (method, SR.CallingConventions.VarArgs)) + reference.CallingConvention &= MethodCallingConvention.VarArg; + + if (method.IsGenericMethod) + ImportGenericParameters (reference, method.GetGenericArguments ()); + + context.Push (reference); + try { + var method_info = method as SR.MethodInfo; + reference.ReturnType = method_info != null + ? ImportType (method_info.ReturnType, context) + : ImportType (typeof (void), default (ImportGenericContext)); + + var parameters = method.GetParameters (); + var reference_parameters = reference.Parameters; + + for (int i = 0; i < parameters.Length; i++) + reference_parameters.Add ( + new ParameterDefinition (ImportType (parameters [i].ParameterType, context))); + + reference.DeclaringType = declaring_type; + + return reference; + } finally { + context.Pop (); + } + } + + static void ImportGenericParameters (IGenericParameterProvider provider, Type [] arguments) + { + var provider_parameters = provider.GenericParameters; + + for (int i = 0; i < arguments.Length; i++) + provider_parameters.Add (new GenericParameter (arguments [i].Name, provider)); + } + + static bool IsMethodSpecification (SR.MethodBase method) + { + return method.IsGenericMethod && !method.IsGenericMethodDefinition; + } + + MethodReference ImportMethodSpecification (SR.MethodBase method, ImportGenericContext context) + { + var method_info = method as SR.MethodInfo; + if (method_info == null) + throw new InvalidOperationException (); + + var element_method = ImportMethod (method_info.GetGenericMethodDefinition (), context, ImportGenericKind.Definition); + var instance = new GenericInstanceMethod (element_method); + var arguments = method.GetGenericArguments (); + var instance_arguments = instance.GenericArguments; + + context.Push (element_method); + try { + for (int i = 0; i < arguments.Length; i++) + instance_arguments.Add (ImportType (arguments [i], context)); + + return instance; + } finally { + context.Pop (); + } + } + + static bool HasCallingConvention (SR.MethodBase method, SR.CallingConventions conventions) + { + return (method.CallingConvention & conventions) != 0; + } +#endif + + public virtual TypeReference ImportType (TypeReference type, ImportGenericContext context) + { + if (type.IsTypeSpecification ()) + return ImportTypeSpecification (type, context); + + var reference = new TypeReference ( + type.Namespace, + type.Name, + module, + ImportScope (type.Scope), + type.IsValueType); + + MetadataSystem.TryProcessPrimitiveTypeReference (reference); + + if (type.IsNested) + reference.DeclaringType = ImportType (type.DeclaringType, context); + + if (type.HasGenericParameters) + ImportGenericParameters (reference, type); + + return reference; + } + + IMetadataScope ImportScope (IMetadataScope scope) + { + switch (scope.MetadataScopeType) { + case MetadataScopeType.AssemblyNameReference: + return ImportAssemblyName ((AssemblyNameReference) scope); + case MetadataScopeType.ModuleDefinition: + if (scope == module) return scope; + return ImportAssemblyName (((ModuleDefinition) scope).Assembly.Name); + case MetadataScopeType.ModuleReference: + throw new NotImplementedException (); + } + + throw new NotSupportedException (); + } + + protected virtual AssemblyNameReference ImportAssemblyName (AssemblyNameReference name) + { + AssemblyNameReference reference; + if (TryGetAssemblyNameReference (name, out reference)) + return reference; + + reference = new AssemblyNameReference (name.Name, name.Version) { + Culture = name.Culture, + HashAlgorithm = name.HashAlgorithm, + }; + + var pk_token = !name.PublicKeyToken.IsNullOrEmpty () + ? new byte [name.PublicKeyToken.Length] + : Empty.Array; + + if (pk_token.Length > 0) + Buffer.BlockCopy (name.PublicKeyToken, 0, pk_token, 0, pk_token.Length); + + reference.PublicKeyToken = pk_token; + + module.AssemblyReferences.Add (reference); + + return reference; + } + + bool TryGetAssemblyNameReference (AssemblyNameReference name_reference, out AssemblyNameReference assembly_reference) + { + var references = module.AssemblyReferences; + + for (int i = 0; i < references.Count; i++) { + var reference = references [i]; + if (name_reference.FullName != reference.FullName) // TODO compare field by field + continue; + + assembly_reference = reference; + return true; + } + + assembly_reference = null; + return false; + } + + static void ImportGenericParameters (IGenericParameterProvider imported, IGenericParameterProvider original) + { + var parameters = original.GenericParameters; + var imported_parameters = imported.GenericParameters; + + for (int i = 0; i < parameters.Count; i++) + imported_parameters.Add (new GenericParameter (parameters [i].Name, imported)); + } + + TypeReference ImportTypeSpecification (TypeReference type, ImportGenericContext context) + { + switch (type.etype) { + case ElementType.SzArray: + var vector = (ArrayType) type; + return new ArrayType (ImportType (vector.ElementType, context)); + case ElementType.Ptr: + var pointer = (PointerType) type; + return new PointerType (ImportType (pointer.ElementType, context)); + case ElementType.ByRef: + var byref = (ByReferenceType) type; + return new ByReferenceType (ImportType (byref.ElementType, context)); + case ElementType.Pinned: + var pinned = (PinnedType) type; + return new PinnedType (ImportType (pinned.ElementType, context)); + case ElementType.Sentinel: + var sentinel = (SentinelType) type; + return new SentinelType (ImportType (sentinel.ElementType, context)); + case ElementType.CModOpt: + var modopt = (OptionalModifierType) type; + return new OptionalModifierType ( + ImportType (modopt.ModifierType, context), + ImportType (modopt.ElementType, context)); + case ElementType.CModReqD: + var modreq = (RequiredModifierType) type; + return new RequiredModifierType ( + ImportType (modreq.ModifierType, context), + ImportType (modreq.ElementType, context)); + case ElementType.Array: + var array = (ArrayType) type; + var imported_array = new ArrayType (ImportType (array.ElementType, context)); + if (array.IsVector) + return imported_array; + + var dimensions = array.Dimensions; + var imported_dimensions = imported_array.Dimensions; + + imported_dimensions.Clear (); + + for (int i = 0; i < dimensions.Count; i++) { + var dimension = dimensions [i]; + + imported_dimensions.Add (new ArrayDimension (dimension.LowerBound, dimension.UpperBound)); + } + + return imported_array; + case ElementType.GenericInst: + var instance = (GenericInstanceType) type; + var element_type = ImportType (instance.ElementType, context); + var imported_instance = new GenericInstanceType (element_type); + + var arguments = instance.GenericArguments; + var imported_arguments = imported_instance.GenericArguments; + + for (int i = 0; i < arguments.Count; i++) + imported_arguments.Add (ImportType (arguments [i], context)); + + return imported_instance; + case ElementType.Var: + var var_parameter = (GenericParameter) type; + return context.TypeParameter (type.DeclaringType.FullName, var_parameter.Position); + case ElementType.MVar: + var mvar_parameter = (GenericParameter) type; + return context.MethodParameter (mvar_parameter.DeclaringMethod.Name, mvar_parameter.Position); + } + + throw new NotSupportedException (type.etype.ToString ()); + } + + public FieldReference ImportField (FieldReference field, ImportGenericContext context) + { + var declaring_type = ImportType (field.DeclaringType, context); + + context.Push (declaring_type); + try { + return new FieldReference { + Name = field.Name, + DeclaringType = declaring_type, + FieldType = ImportType (field.FieldType, context), + }; + } finally { + context.Pop (); + } + } + + public MethodReference ImportMethod (MethodReference method, ImportGenericContext context) + { + if (method.IsGenericInstance) + return ImportMethodSpecification (method, context); + + var declaring_type = ImportType (method.DeclaringType, context); + + var reference = new MethodReference { + Name = method.Name, + HasThis = method.HasThis, + ExplicitThis = method.ExplicitThis, + DeclaringType = declaring_type, + CallingConvention = method.CallingConvention, + }; + + if (method.HasGenericParameters) + ImportGenericParameters (reference, method); + + context.Push (reference); + try { + reference.ReturnType = ImportType (method.ReturnType, context); + + if (!method.HasParameters) + return reference; + + var reference_parameters = reference.Parameters; + + var parameters = method.Parameters; + for (int i = 0; i < parameters.Count; i++) + reference_parameters.Add ( + new ParameterDefinition (ImportType (parameters [i].ParameterType, context))); + + return reference; + } finally { + context.Pop(); + } + } + + MethodSpecification ImportMethodSpecification (MethodReference method, ImportGenericContext context) + { + if (!method.IsGenericInstance) + throw new NotSupportedException (); + + var instance = (GenericInstanceMethod) method; + var element_method = ImportMethod (instance.ElementMethod, context); + var imported_instance = new GenericInstanceMethod (element_method); + + var arguments = instance.GenericArguments; + var imported_arguments = imported_instance.GenericArguments; + + for (int i = 0; i < arguments.Count; i++) + imported_arguments.Add (ImportType (arguments [i], context)); + + return imported_instance; + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil/LinkedResource.cs b/external/cecil-legacy/Mono.Cecil/LinkedResource.cs new file mode 100644 index 0000000000..16c1d59b5a --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/LinkedResource.cs @@ -0,0 +1,60 @@ +// +// LinkedResource.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +namespace Mono.Cecil { + + public sealed class LinkedResource : Resource { + + internal byte [] hash; + string file; + + public byte [] Hash { + get { return hash; } + } + + public string File { + get { return file; } + set { file = value; } + } + + public override ResourceType ResourceType { + get { return ResourceType.Linked; } + } + + public LinkedResource (string name, ManifestResourceAttributes flags) + : base (name, flags) + { + } + + public LinkedResource (string name, ManifestResourceAttributes flags, string file) + : base (name, flags) + { + this.file = file; + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil/ManifestResourceAttributes.cs b/external/cecil-legacy/Mono.Cecil/ManifestResourceAttributes.cs new file mode 100644 index 0000000000..7d6bb190f4 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/ManifestResourceAttributes.cs @@ -0,0 +1,39 @@ +// +// ManifestResourceAttributes.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +namespace Mono.Cecil { + + [Flags] + public enum ManifestResourceAttributes : uint { + VisibilityMask = 0x0007, + Public = 0x0001, // The resource is exported from the Assembly + Private = 0x0002 // The resource is private to the Assembly + } +} diff --git a/external/cecil-legacy/Mono.Cecil/MarshalInfo.cs b/external/cecil-legacy/Mono.Cecil/MarshalInfo.cs new file mode 100644 index 0000000000..9d58738923 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/MarshalInfo.cs @@ -0,0 +1,171 @@ +// +// MarshalInfo.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +namespace Mono.Cecil { + + public class MarshalInfo { + + internal NativeType native; + + public NativeType NativeType { + get { return native; } + set { native = value; } + } + + public MarshalInfo (NativeType native) + { + this.native = native; + } + } + + public sealed class ArrayMarshalInfo : MarshalInfo { + + internal NativeType element_type; + internal int size_parameter_index; + internal int size; + internal int size_parameter_multiplier; + + public NativeType ElementType { + get { return element_type; } + set { element_type = value; } + } + + public int SizeParameterIndex { + get { return size_parameter_index; } + set { size_parameter_index = value; } + } + + public int Size { + get { return size; } + set { size = value; } + } + + public int SizeParameterMultiplier { + get { return size_parameter_multiplier; } + set { size_parameter_multiplier = value; } + } + + public ArrayMarshalInfo () + : base (NativeType.Array) + { + element_type = NativeType.None; + size_parameter_index = -1; + size = -1; + size_parameter_multiplier = -1; + } + } + + public sealed class CustomMarshalInfo : MarshalInfo { + + internal Guid guid; + internal string unmanaged_type; + internal TypeReference managed_type; + internal string cookie; + + public Guid Guid { + get { return guid; } + set { guid = value; } + } + + public string UnmanagedType { + get { return unmanaged_type; } + set { unmanaged_type = value; } + } + + public TypeReference ManagedType { + get { return managed_type; } + set { managed_type = value; } + } + + public string Cookie { + get { return cookie; } + set { cookie = value; } + } + + public CustomMarshalInfo () + : base (NativeType.CustomMarshaler) + { + } + } + + public sealed class SafeArrayMarshalInfo : MarshalInfo { + + internal VariantType element_type; + + public VariantType ElementType { + get { return element_type; } + set { element_type = value; } + } + + public SafeArrayMarshalInfo () + : base (NativeType.SafeArray) + { + element_type = VariantType.None; + } + } + + public sealed class FixedArrayMarshalInfo : MarshalInfo { + + internal NativeType element_type; + internal int size; + + public NativeType ElementType { + get { return element_type; } + set { element_type = value; } + } + + public int Size { + get { return size; } + set { size = value; } + } + + public FixedArrayMarshalInfo () + : base (NativeType.FixedArray) + { + element_type = NativeType.None; + } + } + + public sealed class FixedSysStringMarshalInfo : MarshalInfo { + + internal int size; + + public int Size { + get { return size; } + set { size = value; } + } + + public FixedSysStringMarshalInfo () + : base (NativeType.FixedSysString) + { + size = -1; + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil/MemberDefinitionCollection.cs b/external/cecil-legacy/Mono.Cecil/MemberDefinitionCollection.cs new file mode 100644 index 0000000000..707f36fb97 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/MemberDefinitionCollection.cs @@ -0,0 +1,92 @@ +// +// MemberDefinitionCollection.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +using Mono.Collections.Generic; + +namespace Mono.Cecil { + + class MemberDefinitionCollection : Collection where T : IMemberDefinition { + + TypeDefinition container; + + internal MemberDefinitionCollection (TypeDefinition container) + { + this.container = container; + } + + internal MemberDefinitionCollection (TypeDefinition container, int capacity) + : base (capacity) + { + this.container = container; + } + + protected override void OnAdd (T item, int index) + { + Attach (item); + } + + protected sealed override void OnSet (T item, int index) + { + Attach (item); + } + + protected sealed override void OnInsert (T item, int index) + { + Attach (item); + } + + protected sealed override void OnRemove (T item, int index) + { + Detach (item); + } + + protected sealed override void OnClear () + { + foreach (var definition in this) + Detach (definition); + } + + void Attach (T element) + { + if (element.DeclaringType == container) + return; + + if (element.DeclaringType != null) + throw new ArgumentException ("Member already attached"); + + element.DeclaringType = this.container; + } + + static void Detach (T element) + { + element.DeclaringType = null; + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil/MemberReference.cs b/external/cecil-legacy/Mono.Cecil/MemberReference.cs new file mode 100644 index 0000000000..b658c513de --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/MemberReference.cs @@ -0,0 +1,101 @@ +// +// MemberReference.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +namespace Mono.Cecil { + + public abstract class MemberReference : IMetadataTokenProvider { + + string name; + TypeReference declaring_type; + + internal MetadataToken token; + + public virtual string Name { + get { return name; } + set { name = value; } + } + + public abstract string FullName { + get; + } + + public virtual TypeReference DeclaringType { + get { return declaring_type; } + set { declaring_type = value; } + } + + public MetadataToken MetadataToken { + get { return token; } + set { token = value; } + } + + internal bool HasImage { + get { + var module = Module; + if (module == null) + return false; + + return module.HasImage; + } + } + + public virtual ModuleDefinition Module { + get { return declaring_type != null ? declaring_type.Module : null; } + } + + public virtual bool IsDefinition { + get { return false; } + } + + internal virtual bool ContainsGenericParameter { + get { return declaring_type != null && declaring_type.ContainsGenericParameter; } + } + + internal MemberReference () + { + } + + internal MemberReference (string name) + { + this.name = name ?? string.Empty; + } + + internal string MemberFullName () + { + if (declaring_type == null) + return name; + + return declaring_type.FullName + "::" + name; + } + + public override string ToString () + { + return FullName; + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil/MetadataResolver.cs b/external/cecil-legacy/Mono.Cecil/MetadataResolver.cs new file mode 100644 index 0000000000..55433770f2 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/MetadataResolver.cs @@ -0,0 +1,381 @@ +// +// MetadataResolver.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +using Mono.Collections.Generic; + +namespace Mono.Cecil { + + public interface IAssemblyResolver { + AssemblyDefinition Resolve (AssemblyNameReference name); + AssemblyDefinition Resolve (AssemblyNameReference name, ReaderParameters parameters); + + AssemblyDefinition Resolve (string fullName); + AssemblyDefinition Resolve (string fullName, ReaderParameters parameters); + } + + public interface IMetadataResolver { + TypeDefinition Resolve (TypeReference type); + FieldDefinition Resolve (FieldReference field); + MethodDefinition Resolve (MethodReference method); + } + +#if !SILVERLIGHT && !CF + [Serializable] +#endif + public class ResolutionException : Exception { + + readonly MemberReference member; + + public MemberReference Member { + get { return member; } + } + + public IMetadataScope Scope { + get { + var type = member as TypeReference; + if (type != null) + return type.Scope; + + var declaring_type = member.DeclaringType; + if (declaring_type != null) + return declaring_type.Scope; + + throw new NotSupportedException (); + } + } + + public ResolutionException (MemberReference member) + : base ("Failed to resolve " + member.FullName) + { + if (member == null) + throw new ArgumentNullException ("member"); + + this.member = member; + } + +#if !SILVERLIGHT && !CF + protected ResolutionException ( + System.Runtime.Serialization.SerializationInfo info, + System.Runtime.Serialization.StreamingContext context) + : base (info, context) + { + } +#endif + } + + public class MetadataResolver : IMetadataResolver { + + readonly IAssemblyResolver assembly_resolver; + + public IAssemblyResolver AssemblyResolver { + get { return assembly_resolver; } + } + + public MetadataResolver (IAssemblyResolver assemblyResolver) + { + if (assemblyResolver == null) + throw new ArgumentNullException ("assemblyResolver"); + + assembly_resolver = assemblyResolver; + } + + public virtual TypeDefinition Resolve (TypeReference type) + { + if (type == null) + throw new ArgumentNullException ("type"); + + type = type.GetElementType (); + + var scope = type.Scope; + switch (scope.MetadataScopeType) { + case MetadataScopeType.AssemblyNameReference: + var assembly = assembly_resolver.Resolve ((AssemblyNameReference) scope); + if (assembly == null) + return null; + + return GetType (assembly.MainModule, type); + case MetadataScopeType.ModuleDefinition: + return GetType ((ModuleDefinition) scope, type); + case MetadataScopeType.ModuleReference: + var modules = type.Module.Assembly.Modules; + var module_ref = (ModuleReference) scope; + for (int i = 0; i < modules.Count; i++) { + var netmodule = modules [i]; + if (netmodule.Name == module_ref.Name) + return GetType (netmodule, type); + } + break; + } + + throw new NotSupportedException (); + } + + static TypeDefinition GetType (ModuleDefinition module, TypeReference reference) + { + var type = GetTypeDefinition (module, reference); + if (type != null) + return type; + + if (!module.HasExportedTypes) + return null; + + var exported_types = module.ExportedTypes; + + for (int i = 0; i < exported_types.Count; i++) { + var exported_type = exported_types [i]; + if (exported_type.Name != reference.Name) + continue; + + if (exported_type.Namespace != reference.Namespace) + continue; + + return exported_type.Resolve (); + } + + return null; + } + + static TypeDefinition GetTypeDefinition (ModuleDefinition module, TypeReference type) + { + if (!type.IsNested) + return module.GetType (type.Namespace, type.Name); + + var declaring_type = type.DeclaringType.Resolve (); + if (declaring_type == null) + return null; + + return declaring_type.GetNestedType (type.Name); + } + + public virtual FieldDefinition Resolve (FieldReference field) + { + if (field == null) + throw new ArgumentNullException ("field"); + + var type = Resolve (field.DeclaringType); + if (type == null) + return null; + + if (!type.HasFields) + return null; + + return GetField (type, field); + } + + FieldDefinition GetField (TypeDefinition type, FieldReference reference) + { + while (type != null) { + var field = GetField (type.Fields, reference); + if (field != null) + return field; + + if (type.BaseType == null) + return null; + + type = Resolve (type.BaseType); + } + + return null; + } + + static FieldDefinition GetField (Collection fields, FieldReference reference) + { + for (int i = 0; i < fields.Count; i++) { + var field = fields [i]; + + if (field.Name != reference.Name) + continue; + + if (!AreSame (field.FieldType, reference.FieldType)) + continue; + + return field; + } + + return null; + } + + public virtual MethodDefinition Resolve (MethodReference method) + { + if (method == null) + throw new ArgumentNullException ("method"); + + var type = Resolve (method.DeclaringType); + if (type == null) + return null; + + method = method.GetElementMethod (); + + if (!type.HasMethods) + return null; + + return GetMethod (type, method); + } + + MethodDefinition GetMethod (TypeDefinition type, MethodReference reference) + { + while (type != null) { + var method = GetMethod (type.Methods, reference); + if (method != null) + return method; + + if (type.BaseType == null) + return null; + + type = Resolve (type.BaseType); + } + + return null; + } + + public static MethodDefinition GetMethod (Collection methods, MethodReference reference) + { + for (int i = 0; i < methods.Count; i++) { + var method = methods [i]; + + if (method.Name != reference.Name) + continue; + + if (method.HasGenericParameters != reference.HasGenericParameters) + continue; + + if (method.HasGenericParameters && method.GenericParameters.Count != reference.GenericParameters.Count) + continue; + + if (!AreSame (method.ReturnType, reference.ReturnType)) + continue; + + if (method.HasParameters != reference.HasParameters) + continue; + + if (!method.HasParameters && !reference.HasParameters) + return method; + + if (!AreSame (method.Parameters, reference.Parameters)) + continue; + + return method; + } + + return null; + } + + static bool AreSame (Collection a, Collection b) + { + var count = a.Count; + + if (count != b.Count) + return false; + + if (count == 0) + return true; + + for (int i = 0; i < count; i++) + if (!AreSame (a [i].ParameterType, b [i].ParameterType)) + return false; + + return true; + } + + static bool AreSame (TypeSpecification a, TypeSpecification b) + { + if (!AreSame (a.ElementType, b.ElementType)) + return false; + + if (a.IsGenericInstance) + return AreSame ((GenericInstanceType) a, (GenericInstanceType) b); + + if (a.IsRequiredModifier || a.IsOptionalModifier) + return AreSame ((IModifierType) a, (IModifierType) b); + + if (a.IsArray) + return AreSame ((ArrayType) a, (ArrayType) b); + + return true; + } + + static bool AreSame (ArrayType a, ArrayType b) + { + if (a.Rank != b.Rank) + return false; + + // TODO: dimensions + + return true; + } + + static bool AreSame (IModifierType a, IModifierType b) + { + return AreSame (a.ModifierType, b.ModifierType); + } + + static bool AreSame (GenericInstanceType a, GenericInstanceType b) + { + if (a.GenericArguments.Count != b.GenericArguments.Count) + return false; + + for (int i = 0; i < a.GenericArguments.Count; i++) + if (!AreSame (a.GenericArguments [i], b.GenericArguments [i])) + return false; + + return true; + } + + static bool AreSame (GenericParameter a, GenericParameter b) + { + return a.Position == b.Position; + } + + static bool AreSame (TypeReference a, TypeReference b) + { + if (ReferenceEquals (a, b)) + return true; + + if (a == null || b == null) + return false; + + if (a.etype != b.etype) + return false; + + if (a.IsGenericParameter) + return AreSame ((GenericParameter) a, (GenericParameter) b); + + if (a.IsTypeSpecification ()) + return AreSame ((TypeSpecification) a, (TypeSpecification) b); + + if (a.Name != b.Name || a.Namespace != b.Namespace) + return false; + + //TODO: check scope + + return AreSame (a.DeclaringType, b.DeclaringType); + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil/MetadataSystem.cs b/external/cecil-legacy/Mono.Cecil/MetadataSystem.cs new file mode 100644 index 0000000000..3ae2015bb5 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/MetadataSystem.cs @@ -0,0 +1,395 @@ +// +// MetadataSystem.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Collections.Generic; + +using Mono.Cecil.Metadata; + +namespace Mono.Cecil { + + struct Range { + public uint Start; + public uint Length; + + public Range (uint index, uint length) + { + this.Start = index; + this.Length = length; + } + } + + sealed class MetadataSystem { + + internal AssemblyNameReference [] AssemblyReferences; + internal ModuleReference [] ModuleReferences; + + internal TypeDefinition [] Types; + internal TypeReference [] TypeReferences; + + internal FieldDefinition [] Fields; + internal MethodDefinition [] Methods; + internal MemberReference [] MemberReferences; + + internal Dictionary NestedTypes; + internal Dictionary ReverseNestedTypes; + internal Dictionary Interfaces; + internal Dictionary> ClassLayouts; + internal Dictionary FieldLayouts; + internal Dictionary FieldRVAs; + internal Dictionary FieldMarshals; + internal Dictionary> Constants; + internal Dictionary Overrides; + internal Dictionary CustomAttributes; + internal Dictionary SecurityDeclarations; + internal Dictionary Events; + internal Dictionary Properties; + internal Dictionary> Semantics; + internal Dictionary> PInvokes; + internal Dictionary GenericParameters; + internal Dictionary GenericConstraints; + + static Dictionary> primitive_value_types; + + static void InitializePrimitives () + { + primitive_value_types = new Dictionary> (18, StringComparer.Ordinal) { + { "Void", new Row (ElementType.Void, false) }, + { "Boolean", new Row (ElementType.Boolean, true) }, + { "Char", new Row (ElementType.Char, true) }, + { "SByte", new Row (ElementType.I1, true) }, + { "Byte", new Row (ElementType.U1, true) }, + { "Int16", new Row (ElementType.I2, true) }, + { "UInt16", new Row (ElementType.U2, true) }, + { "Int32", new Row (ElementType.I4, true) }, + { "UInt32", new Row (ElementType.U4, true) }, + { "Int64", new Row (ElementType.I8, true) }, + { "UInt64", new Row (ElementType.U8, true) }, + { "Single", new Row (ElementType.R4, true) }, + { "Double", new Row (ElementType.R8, true) }, + { "String", new Row (ElementType.String, false) }, + { "TypedReference", new Row (ElementType.TypedByRef, false) }, + { "IntPtr", new Row (ElementType.I, true) }, + { "UIntPtr", new Row (ElementType.U, true) }, + { "Object", new Row (ElementType.Object, false) }, + }; + } + + public static void TryProcessPrimitiveTypeReference (TypeReference type) + { + if (type.Namespace != "System") + return; + + var scope = type.scope; + if (scope == null || scope.MetadataScopeType != MetadataScopeType.AssemblyNameReference) + return; + + Row primitive_data; + if (!TryGetPrimitiveData (type, out primitive_data)) + return; + + type.etype = primitive_data.Col1; + type.IsValueType = primitive_data.Col2; + } + + public static bool TryGetPrimitiveElementType (TypeDefinition type, out ElementType etype) + { + etype = ElementType.None; + + if (type.Namespace != "System") + return false; + + Row primitive_data; + if (TryGetPrimitiveData (type, out primitive_data) && primitive_data.Col1.IsPrimitive ()) { + etype = primitive_data.Col1; + return true; + } + + return false; + } + + static bool TryGetPrimitiveData (TypeReference type, out Row primitive_data) + { + if (primitive_value_types == null) + InitializePrimitives (); + + return primitive_value_types.TryGetValue (type.Name, out primitive_data); + } + + public void Clear () + { + if (NestedTypes != null) NestedTypes.Clear (); + if (ReverseNestedTypes != null) ReverseNestedTypes.Clear (); + if (Interfaces != null) Interfaces.Clear (); + if (ClassLayouts != null) ClassLayouts.Clear (); + if (FieldLayouts != null) FieldLayouts.Clear (); + if (FieldRVAs != null) FieldRVAs.Clear (); + if (FieldMarshals != null) FieldMarshals.Clear (); + if (Constants != null) Constants.Clear (); + if (Overrides != null) Overrides.Clear (); + if (CustomAttributes != null) CustomAttributes.Clear (); + if (SecurityDeclarations != null) SecurityDeclarations.Clear (); + if (Events != null) Events.Clear (); + if (Properties != null) Properties.Clear (); + if (Semantics != null) Semantics.Clear (); + if (PInvokes != null) PInvokes.Clear (); + if (GenericParameters != null) GenericParameters.Clear (); + if (GenericConstraints != null) GenericConstraints.Clear (); + } + + public TypeDefinition GetTypeDefinition (uint rid) + { + if (rid < 1 || rid > Types.Length) + return null; + + return Types [rid - 1]; + } + + public void AddTypeDefinition (TypeDefinition type) + { + Types [type.token.RID - 1] = type; + } + + public TypeReference GetTypeReference (uint rid) + { + if (rid < 1 || rid > TypeReferences.Length) + return null; + + return TypeReferences [rid - 1]; + } + + public void AddTypeReference (TypeReference type) + { + TypeReferences [type.token.RID - 1] = type; + } + + public FieldDefinition GetFieldDefinition (uint rid) + { + if (rid < 1 || rid > Fields.Length) + return null; + + return Fields [rid - 1]; + } + + public void AddFieldDefinition (FieldDefinition field) + { + Fields [field.token.RID - 1] = field; + } + + public MethodDefinition GetMethodDefinition (uint rid) + { + if (rid < 1 || rid > Methods.Length) + return null; + + return Methods [rid - 1]; + } + + public void AddMethodDefinition (MethodDefinition method) + { + Methods [method.token.RID - 1] = method; + } + + public MemberReference GetMemberReference (uint rid) + { + if (rid < 1 || rid > MemberReferences.Length) + return null; + + return MemberReferences [rid - 1]; + } + + public void AddMemberReference (MemberReference member) + { + MemberReferences [member.token.RID - 1] = member; + } + + public bool TryGetNestedTypeMapping (TypeDefinition type, out uint [] mapping) + { + return NestedTypes.TryGetValue (type.token.RID, out mapping); + } + + public void SetNestedTypeMapping (uint type_rid, uint [] mapping) + { + NestedTypes [type_rid] = mapping; + } + + public void RemoveNestedTypeMapping (TypeDefinition type) + { + NestedTypes.Remove (type.token.RID); + } + + public bool TryGetReverseNestedTypeMapping (TypeDefinition type, out uint declaring) + { + return ReverseNestedTypes.TryGetValue (type.token.RID, out declaring); + } + + public void SetReverseNestedTypeMapping (uint nested, uint declaring) + { + ReverseNestedTypes.Add (nested, declaring); + } + + public void RemoveReverseNestedTypeMapping (TypeDefinition type) + { + ReverseNestedTypes.Remove (type.token.RID); + } + + public bool TryGetInterfaceMapping (TypeDefinition type, out MetadataToken [] mapping) + { + return Interfaces.TryGetValue (type.token.RID, out mapping); + } + + public void SetInterfaceMapping (uint type_rid, MetadataToken [] mapping) + { + Interfaces [type_rid] = mapping; + } + + public void RemoveInterfaceMapping (TypeDefinition type) + { + Interfaces.Remove (type.token.RID); + } + + public void AddPropertiesRange (uint type_rid, Range range) + { + Properties.Add (type_rid, range); + } + + public bool TryGetPropertiesRange (TypeDefinition type, out Range range) + { + return Properties.TryGetValue (type.token.RID, out range); + } + + public void RemovePropertiesRange (TypeDefinition type) + { + Properties.Remove (type.token.RID); + } + + public void AddEventsRange (uint type_rid, Range range) + { + Events.Add (type_rid, range); + } + + public bool TryGetEventsRange (TypeDefinition type, out Range range) + { + return Events.TryGetValue (type.token.RID, out range); + } + + public void RemoveEventsRange (TypeDefinition type) + { + Events.Remove (type.token.RID); + } + + public bool TryGetGenericParameterRanges (IGenericParameterProvider owner, out Range [] ranges) + { + return GenericParameters.TryGetValue (owner.MetadataToken, out ranges); + } + + public void RemoveGenericParameterRange (IGenericParameterProvider owner) + { + GenericParameters.Remove (owner.MetadataToken); + } + + public bool TryGetCustomAttributeRanges (ICustomAttributeProvider owner, out Range [] ranges) + { + return CustomAttributes.TryGetValue (owner.MetadataToken, out ranges); + } + + public void RemoveCustomAttributeRange (ICustomAttributeProvider owner) + { + CustomAttributes.Remove (owner.MetadataToken); + } + + public bool TryGetSecurityDeclarationRanges (ISecurityDeclarationProvider owner, out Range [] ranges) + { + return SecurityDeclarations.TryGetValue (owner.MetadataToken, out ranges); + } + + public void RemoveSecurityDeclarationRange (ISecurityDeclarationProvider owner) + { + SecurityDeclarations.Remove (owner.MetadataToken); + } + + public bool TryGetGenericConstraintMapping (GenericParameter generic_parameter, out MetadataToken [] mapping) + { + return GenericConstraints.TryGetValue (generic_parameter.token.RID, out mapping); + } + + public void SetGenericConstraintMapping (uint gp_rid, MetadataToken [] mapping) + { + GenericConstraints [gp_rid] = mapping; + } + + public void RemoveGenericConstraintMapping (GenericParameter generic_parameter) + { + GenericConstraints.Remove (generic_parameter.token.RID); + } + + public bool TryGetOverrideMapping (MethodDefinition method, out MetadataToken [] mapping) + { + return Overrides.TryGetValue (method.token.RID, out mapping); + } + + public void SetOverrideMapping (uint rid, MetadataToken [] mapping) + { + Overrides [rid] = mapping; + } + + public void RemoveOverrideMapping (MethodDefinition method) + { + Overrides.Remove (method.token.RID); + } + + public TypeDefinition GetFieldDeclaringType (uint field_rid) + { + return BinaryRangeSearch (Types, field_rid, true); + } + + public TypeDefinition GetMethodDeclaringType (uint method_rid) + { + return BinaryRangeSearch (Types, method_rid, false); + } + + static TypeDefinition BinaryRangeSearch (TypeDefinition [] types, uint rid, bool field) + { + int min = 0; + int max = types.Length - 1; + while (min <= max) { + int mid = min + ((max - min) / 2); + var type = types [mid]; + var range = field ? type.fields_range : type.methods_range; + + if (rid < range.Start) + max = mid - 1; + else if (rid >= range.Start + range.Length) + min = mid + 1; + else + return type; + } + + return null; + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil/MethodAttributes.cs b/external/cecil-legacy/Mono.Cecil/MethodAttributes.cs new file mode 100644 index 0000000000..626a97b3ea --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/MethodAttributes.cs @@ -0,0 +1,66 @@ +// +// MethodAttributes.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +namespace Mono.Cecil { + + [Flags] + public enum MethodAttributes : ushort { + MemberAccessMask = 0x0007, + CompilerControlled = 0x0000, // Member not referenceable + Private = 0x0001, // Accessible only by the parent type + FamANDAssem = 0x0002, // Accessible by sub-types only in this Assembly + Assembly = 0x0003, // Accessibly by anyone in the Assembly + Family = 0x0004, // Accessible only by type and sub-types + FamORAssem = 0x0005, // Accessibly by sub-types anywhere, plus anyone in assembly + Public = 0x0006, // Accessibly by anyone who has visibility to this scope + + Static = 0x0010, // Defined on type, else per instance + Final = 0x0020, // Method may not be overridden + Virtual = 0x0040, // Method is virtual + HideBySig = 0x0080, // Method hides by name+sig, else just by name + + VtableLayoutMask = 0x0100, // Use this mask to retrieve vtable attributes + ReuseSlot = 0x0000, // Method reuses existing slot in vtable + NewSlot = 0x0100, // Method always gets a new slot in the vtable + + CheckAccessOnOverride = 0x0200, // Method can only be overriden if also accessible + Abstract = 0x0400, // Method does not provide an implementation + SpecialName = 0x0800, // Method is special + + // Interop Attributes + PInvokeImpl = 0x2000, // Implementation is forwarded through PInvoke + UnmanagedExport = 0x0008, // Reserved: shall be zero for conforming implementations + + // Additional flags + RTSpecialName = 0x1000, // CLI provides 'special' behavior, depending upon the name of the method + HasSecurity = 0x4000, // Method has security associate with it + RequireSecObject = 0x8000 // Method calls another method containing security code + } +} diff --git a/external/cecil-legacy/Mono.Cecil/MethodCallingConvention.cs b/external/cecil-legacy/Mono.Cecil/MethodCallingConvention.cs new file mode 100644 index 0000000000..bd7188dbec --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/MethodCallingConvention.cs @@ -0,0 +1,40 @@ +// +// MethodCallingConvention.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +namespace Mono.Cecil { + + public enum MethodCallingConvention : byte { + Default = 0x0, + C = 0x1, + StdCall = 0x2, + ThisCall = 0x3, + FastCall = 0x4, + VarArg = 0x5, + Generic = 0x10, + } +} diff --git a/external/cecil-legacy/Mono.Cecil/MethodDefinition.cs b/external/cecil-legacy/Mono.Cecil/MethodDefinition.cs new file mode 100644 index 0000000000..cbda745b7e --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/MethodDefinition.cs @@ -0,0 +1,487 @@ +// +// MethodDefinition.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using Mono.Cecil.Cil; +using Mono.Collections.Generic; + +using RVA = System.UInt32; + +namespace Mono.Cecil { + + public sealed class MethodDefinition : MethodReference, IMemberDefinition, ISecurityDeclarationProvider { + + ushort attributes; + ushort impl_attributes; + internal MethodSemanticsAttributes? sem_attrs; + Collection custom_attributes; + Collection security_declarations; + + internal RVA rva; + internal PInvokeInfo pinvoke; + Collection overrides; + + internal MethodBody body; + + public MethodAttributes Attributes { + get { return (MethodAttributes) attributes; } + set { attributes = (ushort) value; } + } + + public MethodImplAttributes ImplAttributes { + get { return (MethodImplAttributes) impl_attributes; } + set { impl_attributes = (ushort) value; } + } + + public MethodSemanticsAttributes SemanticsAttributes { + get { + if (sem_attrs.HasValue) + return sem_attrs.Value; + + if (HasImage) { + ReadSemantics (); + return sem_attrs.Value; + } + + sem_attrs = MethodSemanticsAttributes.None; + return sem_attrs.Value; + } + set { sem_attrs = value; } + } + + internal void ReadSemantics () + { + if (sem_attrs.HasValue) + return; + + var module = this.Module; + if (module == null) + return; + + if (!module.HasImage) + return; + + module.Read (this, (method, reader) => reader.ReadAllSemantics (method)); + } + + public bool HasSecurityDeclarations { + get { + if (security_declarations != null) + return security_declarations.Count > 0; + + return this.GetHasSecurityDeclarations (Module); + } + } + + public Collection SecurityDeclarations { + get { return security_declarations ?? (security_declarations = this.GetSecurityDeclarations (Module)); } + } + + public bool HasCustomAttributes { + get { + if (custom_attributes != null) + return custom_attributes.Count > 0; + + return this.GetHasCustomAttributes (Module); + } + } + + public Collection CustomAttributes { + get { return custom_attributes ?? (custom_attributes = this.GetCustomAttributes (Module)); } + } + + public int RVA { + get { return (int) rva; } + } + + public bool HasBody { + get { + return (attributes & (ushort) MethodAttributes.Abstract) == 0 && + (attributes & (ushort) MethodAttributes.PInvokeImpl) == 0 && + (impl_attributes & (ushort) MethodImplAttributes.InternalCall) == 0 && + (impl_attributes & (ushort) MethodImplAttributes.Native) == 0 && + (impl_attributes & (ushort) MethodImplAttributes.Unmanaged) == 0 && + (impl_attributes & (ushort) MethodImplAttributes.Runtime) == 0; + } + } + + public MethodBody Body { + get { + if (body != null) + return body; + + if (!HasBody) + return null; + + if (HasImage && rva != 0) + return body = Module.Read (this, (method, reader) => reader.ReadMethodBody (method)); + + return body = new MethodBody (this); + } + set { body = value; } + } + + public bool HasPInvokeInfo { + get { + if (pinvoke != null) + return true; + + return IsPInvokeImpl; + } + } + + public PInvokeInfo PInvokeInfo { + get { + if (pinvoke != null) + return pinvoke; + + if (HasImage && IsPInvokeImpl) + return pinvoke = Module.Read (this, (method, reader) => reader.ReadPInvokeInfo (method)); + + return null; + } + set { + IsPInvokeImpl = true; + pinvoke = value; + } + } + + public bool HasOverrides { + get { + if (overrides != null) + return overrides.Count > 0; + + if (HasImage) + return Module.Read (this, (method, reader) => reader.HasOverrides (method)); + + return false; + } + } + + public Collection Overrides { + get { + if (overrides != null) + return overrides; + + if (HasImage) + return overrides = Module.Read (this, (method, reader) => reader.ReadOverrides (method)); + + return overrides = new Collection (); + } + } + + public override bool HasGenericParameters { + get { + if (generic_parameters != null) + return generic_parameters.Count > 0; + + return this.GetHasGenericParameters (Module); + } + } + + public override Collection GenericParameters { + get { return generic_parameters ?? (generic_parameters = this.GetGenericParameters (Module)); } + } + + #region MethodAttributes + + public bool IsCompilerControlled { + get { return attributes.GetMaskedAttributes ((ushort) MethodAttributes.MemberAccessMask, (ushort) MethodAttributes.CompilerControlled); } + set { attributes = attributes.SetMaskedAttributes ((ushort) MethodAttributes.MemberAccessMask, (ushort) MethodAttributes.CompilerControlled, value); } + } + + public bool IsPrivate { + get { return attributes.GetMaskedAttributes ((ushort) MethodAttributes.MemberAccessMask, (ushort) MethodAttributes.Private); } + set { attributes = attributes.SetMaskedAttributes ((ushort) MethodAttributes.MemberAccessMask, (ushort) MethodAttributes.Private, value); } + } + + public bool IsFamilyAndAssembly { + get { return attributes.GetMaskedAttributes ((ushort) MethodAttributes.MemberAccessMask, (ushort) MethodAttributes.FamANDAssem); } + set { attributes = attributes.SetMaskedAttributes ((ushort) MethodAttributes.MemberAccessMask, (ushort) MethodAttributes.FamANDAssem, value); } + } + + public bool IsAssembly { + get { return attributes.GetMaskedAttributes ((ushort) MethodAttributes.MemberAccessMask, (ushort) MethodAttributes.Assembly); } + set { attributes = attributes.SetMaskedAttributes ((ushort) MethodAttributes.MemberAccessMask, (ushort) MethodAttributes.Assembly, value); } + } + + public bool IsFamily { + get { return attributes.GetMaskedAttributes ((ushort) MethodAttributes.MemberAccessMask, (ushort) MethodAttributes.Family); } + set { attributes = attributes.SetMaskedAttributes ((ushort) MethodAttributes.MemberAccessMask, (ushort) MethodAttributes.Family, value); } + } + + public bool IsFamilyOrAssembly { + get { return attributes.GetMaskedAttributes ((ushort) MethodAttributes.MemberAccessMask, (ushort) MethodAttributes.FamORAssem); } + set { attributes = attributes.SetMaskedAttributes ((ushort) MethodAttributes.MemberAccessMask, (ushort) MethodAttributes.FamORAssem, value); } + } + + public bool IsPublic { + get { return attributes.GetMaskedAttributes ((ushort) MethodAttributes.MemberAccessMask, (ushort) MethodAttributes.Public); } + set { attributes = attributes.SetMaskedAttributes ((ushort) MethodAttributes.MemberAccessMask, (ushort) MethodAttributes.Public, value); } + } + + public bool IsStatic { + get { return attributes.GetAttributes ((ushort) MethodAttributes.Static); } + set { attributes = attributes.SetAttributes ((ushort) MethodAttributes.Static, value); } + } + + public bool IsFinal { + get { return attributes.GetAttributes ((ushort) MethodAttributes.Final); } + set { attributes = attributes.SetAttributes ((ushort) MethodAttributes.Final, value); } + } + + public bool IsVirtual { + get { return attributes.GetAttributes ((ushort) MethodAttributes.Virtual); } + set { attributes = attributes.SetAttributes ((ushort) MethodAttributes.Virtual, value); } + } + + public bool IsHideBySig { + get { return attributes.GetAttributes ((ushort) MethodAttributes.HideBySig); } + set { attributes = attributes.SetAttributes ((ushort) MethodAttributes.HideBySig, value); } + } + + public bool IsReuseSlot { + get { return attributes.GetMaskedAttributes ((ushort) MethodAttributes.VtableLayoutMask, (ushort) MethodAttributes.ReuseSlot); } + set { attributes = attributes.SetMaskedAttributes ((ushort) MethodAttributes.VtableLayoutMask, (ushort) MethodAttributes.ReuseSlot, value); } + } + + public bool IsNewSlot { + get { return attributes.GetMaskedAttributes ((ushort) MethodAttributes.VtableLayoutMask, (ushort) MethodAttributes.NewSlot); } + set { attributes = attributes.SetMaskedAttributes ((ushort) MethodAttributes.VtableLayoutMask, (ushort) MethodAttributes.NewSlot, value); } + } + + public bool IsCheckAccessOnOverride { + get { return attributes.GetAttributes ((ushort) MethodAttributes.CheckAccessOnOverride); } + set { attributes = attributes.SetAttributes ((ushort) MethodAttributes.CheckAccessOnOverride, value); } + } + + public bool IsAbstract { + get { return attributes.GetAttributes ((ushort) MethodAttributes.Abstract); } + set { attributes = attributes.SetAttributes ((ushort) MethodAttributes.Abstract, value); } + } + + public bool IsSpecialName { + get { return attributes.GetAttributes ((ushort) MethodAttributes.SpecialName); } + set { attributes = attributes.SetAttributes ((ushort) MethodAttributes.SpecialName, value); } + } + + public bool IsPInvokeImpl { + get { return attributes.GetAttributes ((ushort) MethodAttributes.PInvokeImpl); } + set { attributes = attributes.SetAttributes ((ushort) MethodAttributes.PInvokeImpl, value); } + } + + public bool IsUnmanagedExport { + get { return attributes.GetAttributes ((ushort) MethodAttributes.UnmanagedExport); } + set { attributes = attributes.SetAttributes ((ushort) MethodAttributes.UnmanagedExport, value); } + } + + public bool IsRuntimeSpecialName { + get { return attributes.GetAttributes ((ushort) MethodAttributes.RTSpecialName); } + set { attributes = attributes.SetAttributes ((ushort) MethodAttributes.RTSpecialName, value); } + } + + public bool HasSecurity { + get { return attributes.GetAttributes ((ushort) MethodAttributes.HasSecurity); } + set { attributes = attributes.SetAttributes ((ushort) MethodAttributes.HasSecurity, value); } + } + + #endregion + + #region MethodImplAttributes + + public bool IsIL { + get { return impl_attributes.GetMaskedAttributes ((ushort) MethodImplAttributes.CodeTypeMask, (ushort) MethodImplAttributes.IL); } + set { impl_attributes = impl_attributes.SetMaskedAttributes ((ushort) MethodImplAttributes.CodeTypeMask, (ushort) MethodImplAttributes.IL, value); } + } + + public bool IsNative { + get { return impl_attributes.GetMaskedAttributes ((ushort) MethodImplAttributes.CodeTypeMask, (ushort) MethodImplAttributes.Native); } + set { impl_attributes = impl_attributes.SetMaskedAttributes ((ushort) MethodImplAttributes.CodeTypeMask, (ushort) MethodImplAttributes.Native, value); } + } + + public bool IsRuntime { + get { return impl_attributes.GetMaskedAttributes ((ushort) MethodImplAttributes.CodeTypeMask, (ushort) MethodImplAttributes.Runtime); } + set { impl_attributes = impl_attributes.SetMaskedAttributes ((ushort) MethodImplAttributes.CodeTypeMask, (ushort) MethodImplAttributes.Runtime, value); } + } + + public bool IsUnmanaged { + get { return impl_attributes.GetMaskedAttributes ((ushort) MethodImplAttributes.ManagedMask, (ushort) MethodImplAttributes.Unmanaged); } + set { impl_attributes = impl_attributes.SetMaskedAttributes ((ushort) MethodImplAttributes.ManagedMask, (ushort) MethodImplAttributes.Unmanaged, value); } + } + + public bool IsManaged { + get { return impl_attributes.GetMaskedAttributes ((ushort) MethodImplAttributes.ManagedMask, (ushort) MethodImplAttributes.Managed); } + set { impl_attributes = impl_attributes.SetMaskedAttributes ((ushort) MethodImplAttributes.ManagedMask, (ushort) MethodImplAttributes.Managed, value); } + } + + public bool IsForwardRef { + get { return impl_attributes.GetAttributes ((ushort) MethodImplAttributes.ForwardRef); } + set { impl_attributes = impl_attributes.SetAttributes ((ushort) MethodImplAttributes.ForwardRef, value); } + } + + public bool IsPreserveSig { + get { return impl_attributes.GetAttributes ((ushort) MethodImplAttributes.PreserveSig); } + set { impl_attributes = impl_attributes.SetAttributes ((ushort) MethodImplAttributes.PreserveSig, value); } + } + + public bool IsInternalCall { + get { return impl_attributes.GetAttributes ((ushort) MethodImplAttributes.InternalCall); } + set { impl_attributes = impl_attributes.SetAttributes ((ushort) MethodImplAttributes.InternalCall, value); } + } + + public bool IsSynchronized { + get { return impl_attributes.GetAttributes ((ushort) MethodImplAttributes.Synchronized); } + set { impl_attributes = impl_attributes.SetAttributes ((ushort) MethodImplAttributes.Synchronized, value); } + } + + public bool NoInlining { + get { return impl_attributes.GetAttributes ((ushort) MethodImplAttributes.NoInlining); } + set { impl_attributes = impl_attributes.SetAttributes ((ushort) MethodImplAttributes.NoInlining, value); } + } + + public bool NoOptimization { + get { return impl_attributes.GetAttributes ((ushort) MethodImplAttributes.NoOptimization); } + set { impl_attributes = impl_attributes.SetAttributes ((ushort) MethodImplAttributes.NoOptimization, value); } + } + + #endregion + + #region MethodSemanticsAttributes + + public bool IsSetter { + get { return this.GetSemantics (MethodSemanticsAttributes.Setter); } + set { this.SetSemantics (MethodSemanticsAttributes.Setter, value); } + } + + public bool IsGetter { + get { return this.GetSemantics (MethodSemanticsAttributes.Getter); } + set { this.SetSemantics (MethodSemanticsAttributes.Getter, value); } + } + + public bool IsOther { + get { return this.GetSemantics (MethodSemanticsAttributes.Other); } + set { this.SetSemantics (MethodSemanticsAttributes.Other, value); } + } + + public bool IsAddOn { + get { return this.GetSemantics (MethodSemanticsAttributes.AddOn); } + set { this.SetSemantics (MethodSemanticsAttributes.AddOn, value); } + } + + public bool IsRemoveOn { + get { return this.GetSemantics (MethodSemanticsAttributes.RemoveOn); } + set { this.SetSemantics (MethodSemanticsAttributes.RemoveOn, value); } + } + + public bool IsFire { + get { return this.GetSemantics (MethodSemanticsAttributes.Fire); } + set { this.SetSemantics (MethodSemanticsAttributes.Fire, value); } + } + + #endregion + + public new TypeDefinition DeclaringType { + get { return (TypeDefinition) base.DeclaringType; } + set { base.DeclaringType = value; } + } + + public bool IsConstructor { + get { + return this.IsRuntimeSpecialName + && this.IsSpecialName + && (this.Name == ".cctor" || this.Name == ".ctor"); + } + } + + public override bool IsDefinition { + get { return true; } + } + + internal MethodDefinition () + { + this.token = new MetadataToken (TokenType.Method); + } + + public MethodDefinition (string name, MethodAttributes attributes, TypeReference returnType) + : base (name, returnType) + { + this.attributes = (ushort) attributes; + this.HasThis = !this.IsStatic; + this.token = new MetadataToken (TokenType.Method); + } + + public override MethodDefinition Resolve () + { + return this; + } + } + + static partial class Mixin { + + public static ParameterDefinition GetParameter (this MethodBody self, int index) + { + var method = self.method; + + if (method.HasThis) { + if (index == 0) + return self.ThisParameter; + + index--; + } + + var parameters = method.Parameters; + + if (index < 0 || index >= parameters.size) + return null; + + return parameters [index]; + } + + public static VariableDefinition GetVariable (this MethodBody self, int index) + { + var variables = self.Variables; + + if (index < 0 || index >= variables.size) + return null; + + return variables [index]; + } + + public static bool GetSemantics (this MethodDefinition self, MethodSemanticsAttributes semantics) + { + return (self.SemanticsAttributes & semantics) != 0; + } + + public static void SetSemantics (this MethodDefinition self, MethodSemanticsAttributes semantics, bool value) + { + if (value) + self.SemanticsAttributes |= semantics; + else + self.SemanticsAttributes &= ~semantics; + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil/MethodImplAttributes.cs b/external/cecil-legacy/Mono.Cecil/MethodImplAttributes.cs new file mode 100644 index 0000000000..b24fcf7047 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/MethodImplAttributes.cs @@ -0,0 +1,53 @@ +// +// MethodImplAttributes.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +namespace Mono.Cecil { + + [Flags] + public enum MethodImplAttributes : ushort { + CodeTypeMask = 0x0003, + IL = 0x0000, // Method impl is CIL + Native = 0x0001, // Method impl is native + OPTIL = 0x0002, // Reserved: shall be zero in conforming implementations + Runtime = 0x0003, // Method impl is provided by the runtime + + ManagedMask = 0x0004, // Flags specifying whether the code is managed or unmanaged + Unmanaged = 0x0004, // Method impl is unmanaged, otherwise managed + Managed = 0x0000, // Method impl is managed + + // Implementation info and interop + ForwardRef = 0x0010, // Indicates method is defined; used primarily in merge scenarios + PreserveSig = 0x0080, // Reserved: conforming implementations may ignore + InternalCall = 0x1000, // Reserved: shall be zero in conforming implementations + Synchronized = 0x0020, // Method is single threaded through the body + NoOptimization = 0x0040, // Method is not optimized by the JIT. + NoInlining = 0x0008, // Method may not be inlined + } +} diff --git a/external/cecil-legacy/Mono.Cecil/MethodReference.cs b/external/cecil-legacy/Mono.Cecil/MethodReference.cs new file mode 100644 index 0000000000..0adab452ef --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/MethodReference.cs @@ -0,0 +1,214 @@ +// +// MethodReference.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Text; + +using Mono.Collections.Generic; + +namespace Mono.Cecil { + + public class MethodReference : MemberReference, IMethodSignature, IGenericParameterProvider, IGenericContext { + + internal ParameterDefinitionCollection parameters; + MethodReturnType return_type; + + bool has_this; + bool explicit_this; + MethodCallingConvention calling_convention; + internal Collection generic_parameters; + + public virtual bool HasThis { + get { return has_this; } + set { has_this = value; } + } + + public virtual bool ExplicitThis { + get { return explicit_this; } + set { explicit_this = value; } + } + + public virtual MethodCallingConvention CallingConvention { + get { return calling_convention; } + set { calling_convention = value; } + } + + public virtual bool HasParameters { + get { return !parameters.IsNullOrEmpty (); } + } + + public virtual Collection Parameters { + get { + if (parameters == null) + parameters = new ParameterDefinitionCollection (this); + + return parameters; + } + } + + IGenericParameterProvider IGenericContext.Type { + get { + var declaring_type = this.DeclaringType; + var instance = declaring_type as GenericInstanceType; + if (instance != null) + return instance.ElementType; + + return declaring_type; + } + } + + IGenericParameterProvider IGenericContext.Method { + get { return this; } + } + + GenericParameterType IGenericParameterProvider.GenericParameterType { + get { return GenericParameterType.Method; } + } + + public virtual bool HasGenericParameters { + get { return !generic_parameters.IsNullOrEmpty (); } + } + + public virtual Collection GenericParameters { + get { + if (generic_parameters != null) + return generic_parameters; + + return generic_parameters = new GenericParameterCollection (this); + } + } + + public TypeReference ReturnType { + get { + var return_type = MethodReturnType; + return return_type != null ? return_type.ReturnType : null; + } + set { + var return_type = MethodReturnType; + if (return_type != null) + return_type.ReturnType = value; + } + } + + public virtual MethodReturnType MethodReturnType { + get { return return_type; } + set { return_type = value; } + } + + public override string FullName { + get { + var builder = new StringBuilder (); + builder.Append (ReturnType.FullName) + .Append (" ") + .Append (MemberFullName ()); + this.MethodSignatureFullName (builder); + return builder.ToString (); + } + } + + public virtual bool IsGenericInstance { + get { return false; } + } + + internal override bool ContainsGenericParameter { + get { + if (this.ReturnType.ContainsGenericParameter || base.ContainsGenericParameter) + return true; + + var parameters = this.Parameters; + + for (int i = 0; i < parameters.Count; i++) + if (parameters [i].ParameterType.ContainsGenericParameter) + return true; + + return false; + } + } + + internal MethodReference () + { + this.return_type = new MethodReturnType (this); + this.token = new MetadataToken (TokenType.MemberRef); + } + + public MethodReference (string name, TypeReference returnType) + : base (name) + { + if (returnType == null) + throw new ArgumentNullException ("returnType"); + + this.return_type = new MethodReturnType (this); + this.return_type.ReturnType = returnType; + this.token = new MetadataToken (TokenType.MemberRef); + } + + public MethodReference (string name, TypeReference returnType, TypeReference declaringType) + : this (name, returnType) + { + if (declaringType == null) + throw new ArgumentNullException ("declaringType"); + + this.DeclaringType = declaringType; + } + + public virtual MethodReference GetElementMethod () + { + return this; + } + + public virtual MethodDefinition Resolve () + { + var module = this.Module; + if (module == null) + throw new NotSupportedException (); + + return module.Resolve (this); + } + } + + static partial class Mixin { + + public static bool IsVarArg (this IMethodSignature self) + { + return (self.CallingConvention & MethodCallingConvention.VarArg) != 0; + } + + public static int GetSentinelPosition (this IMethodSignature self) + { + if (!self.HasParameters) + return -1; + + var parameters = self.Parameters; + for (int i = 0; i < parameters.Count; i++) + if (parameters [i].ParameterType.IsSentinel) + return i; + + return -1; + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil/MethodReturnType.cs b/external/cecil-legacy/Mono.Cecil/MethodReturnType.cs new file mode 100644 index 0000000000..b5b3ee84fa --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/MethodReturnType.cs @@ -0,0 +1,104 @@ +// +// MethodReturnType.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using Mono.Collections.Generic; + +namespace Mono.Cecil { + + public sealed class MethodReturnType : IConstantProvider, ICustomAttributeProvider, IMarshalInfoProvider { + + internal IMethodSignature method; + internal ParameterDefinition parameter; + TypeReference return_type; + + public IMethodSignature Method { + get { return method; } + } + + public TypeReference ReturnType { + get { return return_type; } + set { return_type = value; } + } + + internal ParameterDefinition Parameter { + get { return parameter ?? (parameter = new ParameterDefinition (return_type, method)); } + } + + public MetadataToken MetadataToken { + get { return Parameter.MetadataToken; } + set { Parameter.MetadataToken = value; } + } + + public ParameterAttributes Attributes { + get { return Parameter.Attributes; } + set { Parameter.Attributes = value; } + } + + public bool HasCustomAttributes { + get { return parameter != null && parameter.HasCustomAttributes; } + } + + public Collection CustomAttributes { + get { return Parameter.CustomAttributes; } + } + + public bool HasDefault { + get { return parameter != null && parameter.HasDefault; } + set { Parameter.HasDefault = value; } + } + + public bool HasConstant { + get { return parameter != null && parameter.HasConstant; } + set { Parameter.HasConstant = value; } + } + + public object Constant { + get { return Parameter.Constant; } + set { Parameter.Constant = value; } + } + + public bool HasFieldMarshal { + get { return parameter != null && parameter.HasFieldMarshal; } + set { Parameter.HasFieldMarshal = value; } + } + + public bool HasMarshalInfo { + get { return parameter != null && parameter.HasMarshalInfo; } + } + + public MarshalInfo MarshalInfo { + get { return Parameter.MarshalInfo; } + set { Parameter.MarshalInfo = value; } + } + + public MethodReturnType (IMethodSignature method) + { + this.method = method; + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil/MethodSemanticsAttributes.cs b/external/cecil-legacy/Mono.Cecil/MethodSemanticsAttributes.cs new file mode 100644 index 0000000000..dd0f4742c0 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/MethodSemanticsAttributes.cs @@ -0,0 +1,43 @@ +// +// MethodSemanticsattributes.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +namespace Mono.Cecil { + + [Flags] + public enum MethodSemanticsAttributes : ushort { + None = 0x0000, + Setter = 0x0001, // Setter for property + Getter = 0x0002, // Getter for property + Other = 0x0004, // Other method for property or event + AddOn = 0x0008, // AddOn method for event + RemoveOn = 0x0010, // RemoveOn method for event + Fire = 0x0020 // Fire method for event + } +} diff --git a/external/cecil-legacy/Mono.Cecil/MethodSpecification.cs b/external/cecil-legacy/Mono.Cecil/MethodSpecification.cs new file mode 100644 index 0000000000..73b5c14ad6 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/MethodSpecification.cs @@ -0,0 +1,103 @@ +// +// MethodSpecification.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +using Mono.Collections.Generic; + +namespace Mono.Cecil { + + public abstract class MethodSpecification : MethodReference { + + readonly MethodReference method; + + public MethodReference ElementMethod { + get { return method; } + } + + public override string Name { + get { return method.Name; } + set { throw new InvalidOperationException (); } + } + + public override MethodCallingConvention CallingConvention { + get { return method.CallingConvention; } + set { throw new InvalidOperationException (); } + } + + public override bool HasThis { + get { return method.HasThis; } + set { throw new InvalidOperationException (); } + } + + public override bool ExplicitThis { + get { return method.ExplicitThis; } + set { throw new InvalidOperationException (); } + } + + public override MethodReturnType MethodReturnType { + get { return method.MethodReturnType; } + set { throw new InvalidOperationException (); } + } + + public override TypeReference DeclaringType { + get { return method.DeclaringType; } + set { throw new InvalidOperationException (); } + } + + public override ModuleDefinition Module { + get { return method.Module; } + } + + public override bool HasParameters { + get { return method.HasParameters; } + } + + public override Collection Parameters { + get { return method.Parameters; } + } + + internal override bool ContainsGenericParameter { + get { return method.ContainsGenericParameter; } + } + + internal MethodSpecification (MethodReference method) + { + if (method == null) + throw new ArgumentNullException ("method"); + + this.method = method; + this.token = new MetadataToken (TokenType.MethodSpec); + } + + public sealed override MethodReference GetElementMethod () + { + return method.GetElementMethod (); + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil/Modifiers.cs b/external/cecil-legacy/Mono.Cecil/Modifiers.cs new file mode 100644 index 0000000000..ad31bc04f1 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/Modifiers.cs @@ -0,0 +1,137 @@ +// +// Modifiers.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +using MD = Mono.Cecil.Metadata; + +namespace Mono.Cecil { + + public interface IModifierType { + TypeReference ModifierType { get; } + TypeReference ElementType { get; } + } + + public sealed class OptionalModifierType : TypeSpecification, IModifierType { + + TypeReference modifier_type; + + public TypeReference ModifierType { + get { return modifier_type; } + set { modifier_type = value; } + } + + public override string Name { + get { return base.Name + Suffix; } + } + + public override string FullName { + get { return base.FullName + Suffix; } + } + + string Suffix { + get { return " modopt(" + modifier_type + ")"; } + } + + public override bool IsValueType { + get { return false; } + set { throw new InvalidOperationException (); } + } + + public override bool IsOptionalModifier { + get { return true; } + } + + internal override bool ContainsGenericParameter { + get { return modifier_type.ContainsGenericParameter || base.ContainsGenericParameter; } + } + + public OptionalModifierType (TypeReference modifierType, TypeReference type) + : base (type) + { + Mixin.CheckModifier (modifierType, type); + this.modifier_type = modifierType; + this.etype = MD.ElementType.CModOpt; + } + } + + public sealed class RequiredModifierType : TypeSpecification, IModifierType { + + TypeReference modifier_type; + + public TypeReference ModifierType { + get { return modifier_type; } + set { modifier_type = value; } + } + + public override string Name { + get { return base.Name + Suffix; } + } + + public override string FullName { + get { return base.FullName + Suffix; } + } + + string Suffix { + get { return " modreq(" + modifier_type + ")"; } + } + + public override bool IsValueType { + get { return false; } + set { throw new InvalidOperationException (); } + } + + public override bool IsRequiredModifier { + get { return true; } + } + + internal override bool ContainsGenericParameter { + get { return modifier_type.ContainsGenericParameter || base.ContainsGenericParameter; } + } + + public RequiredModifierType (TypeReference modifierType, TypeReference type) + : base (type) + { + Mixin.CheckModifier (modifierType, type); + this.modifier_type = modifierType; + this.etype = MD.ElementType.CModReqD; + } + + } + + static partial class Mixin { + + public static void CheckModifier (TypeReference modifierType, TypeReference type) + { + if (modifierType == null) + throw new ArgumentNullException ("modifierType"); + if (type == null) + throw new ArgumentNullException ("type"); + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil/ModuleDefinition.cs b/external/cecil-legacy/Mono.Cecil/ModuleDefinition.cs new file mode 100644 index 0000000000..61870cdbb5 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/ModuleDefinition.cs @@ -0,0 +1,1018 @@ +// +// ModuleDefinition.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Collections.Generic; +using System.IO; +using SR = System.Reflection; + +using Mono.Cecil.Cil; +using Mono.Cecil.Metadata; +using Mono.Cecil.PE; +using Mono.Collections.Generic; + +namespace Mono.Cecil { + + public enum ReadingMode { + Immediate = 1, + Deferred = 2, + } + + public sealed class ReaderParameters { + + ReadingMode reading_mode; + IAssemblyResolver assembly_resolver; + IMetadataResolver metadata_resolver; + Stream symbol_stream; + ISymbolReaderProvider symbol_reader_provider; + bool read_symbols; + + public ReadingMode ReadingMode { + get { return reading_mode; } + set { reading_mode = value; } + } + + public IAssemblyResolver AssemblyResolver { + get { return assembly_resolver; } + set { assembly_resolver = value; } + } + + public IMetadataResolver MetadataResolver { + get { return metadata_resolver; } + set { metadata_resolver = value; } + } + + public Stream SymbolStream { + get { return symbol_stream; } + set { symbol_stream = value; } + } + + public ISymbolReaderProvider SymbolReaderProvider { + get { return symbol_reader_provider; } + set { symbol_reader_provider = value; } + } + + public bool ReadSymbols { + get { return read_symbols; } + set { read_symbols = value; } + } + + public ReaderParameters () + : this (ReadingMode.Deferred) + { + } + + public ReaderParameters (ReadingMode readingMode) + { + this.reading_mode = readingMode; + } + } + +#if !READ_ONLY + + public sealed class ModuleParameters { + + ModuleKind kind; + TargetRuntime runtime; + TargetArchitecture architecture; + IAssemblyResolver assembly_resolver; + IMetadataResolver metadata_resolver; + + public ModuleKind Kind { + get { return kind; } + set { kind = value; } + } + + public TargetRuntime Runtime { + get { return runtime; } + set { runtime = value; } + } + + public TargetArchitecture Architecture { + get { return architecture; } + set { architecture = value; } + } + + public IAssemblyResolver AssemblyResolver { + get { return assembly_resolver; } + set { assembly_resolver = value; } + } + + public IMetadataResolver MetadataResolver { + get { return metadata_resolver; } + set { metadata_resolver = value; } + } + + public ModuleParameters () + { + this.kind = ModuleKind.Dll; + this.runtime = GetCurrentRuntime (); + this.architecture = TargetArchitecture.I386; + } + + static TargetRuntime GetCurrentRuntime () + { +#if !CF + return typeof (object).Assembly.ImageRuntimeVersion.ParseRuntime (); +#else + var corlib_version = typeof (object).Assembly.GetName ().Version; + switch (corlib_version.Major) { + case 1: + return corlib_version.Minor == 0 + ? TargetRuntime.Net_1_0 + : TargetRuntime.Net_1_1; + case 2: + return TargetRuntime.Net_2_0; + case 4: + return TargetRuntime.Net_4_0; + default: + throw new NotSupportedException (); + } +#endif + } + } + + interface ICustomMetadataWriter + { + /* + * Remap TypeReference or create custom TypeRef token. + * + * Return true to use the returned custom 'token'. + * + * Return false to create a TypeRef token for 'type' + * (which may have been replaced with a different TypeReference). + * + * This is necessary when types are moved from one assembly to another + * to either adjust the scope or replace a TypeRef with a TypeDef token. + */ + bool CreateTypeRefToken (ref TypeReference type, out MetadataToken token); + } + + public sealed class WriterParameters { + + Stream symbol_stream; + ISymbolWriterProvider symbol_writer_provider; + bool write_symbols; +#if !SILVERLIGHT && !CF + SR.StrongNameKeyPair key_pair; +#endif + public Stream SymbolStream { + get { return symbol_stream; } + set { symbol_stream = value; } + } + + public ISymbolWriterProvider SymbolWriterProvider { + get { return symbol_writer_provider; } + set { symbol_writer_provider = value; } + } + + public bool WriteSymbols { + get { return write_symbols; } + set { write_symbols = value; } + } +#if !SILVERLIGHT && !CF + public SR.StrongNameKeyPair StrongNameKeyPair { + get { return key_pair; } + set { key_pair = value; } + } +#endif + } + +#endif + + public sealed class ModuleDefinition : ModuleReference, ICustomAttributeProvider { + + internal Image Image; + internal MetadataSystem MetadataSystem; + internal ReadingMode ReadingMode; + internal ISymbolReaderProvider SymbolReaderProvider; + + internal ISymbolReader symbol_reader; + internal IAssemblyResolver assembly_resolver; + internal IMetadataResolver metadata_resolver; + internal TypeSystem type_system; + + readonly MetadataReader reader; + readonly string fq_name; + + internal ModuleKind kind; + TargetRuntime runtime; + TargetArchitecture architecture; + ModuleAttributes attributes; + ModuleCharacteristics characteristics; + Guid mvid; + + internal AssemblyDefinition assembly; + MethodDefinition entry_point; + +#if !READ_ONLY + MetadataImporter importer; + ICustomMetadataWriter custom_writer; +#endif + Collection custom_attributes; + Collection references; + Collection modules; + Collection resources; + Collection exported_types; + TypeDefinitionCollection types; + + public bool IsMain { + get { return kind != ModuleKind.NetModule; } + } + + public ModuleKind Kind { + get { return kind; } + set { kind = value; } + } + + public TargetRuntime Runtime { + get { return runtime; } + set { runtime = value; } + } + + public TargetArchitecture Architecture { + get { return architecture; } + set { architecture = value; } + } + + public ModuleAttributes Attributes { + get { return attributes; } + set { attributes = value; } + } + + public ModuleCharacteristics Characteristics { + get { return characteristics; } + set { characteristics = value; } + } + + public string FullyQualifiedName { + get { return fq_name; } + } + + public Guid Mvid { + get { return mvid; } + set { mvid = value; } + } + + internal bool HasImage { + get { return Image != null; } + } + + public bool HasSymbols { + get { return symbol_reader != null; } + } + + public ISymbolReader SymbolReader { + get { return symbol_reader; } + } + + public override MetadataScopeType MetadataScopeType { + get { return MetadataScopeType.ModuleDefinition; } + } + + public AssemblyDefinition Assembly { + get { return assembly; } + } + +#if !READ_ONLY + internal MetadataImporter MetadataImporter { + get { return importer ?? (importer = new MetadataImporter (this)); } + } + + internal void SetMetadataImporter (MetadataImporter importer) + { + if (this.importer != null) + throw new InvalidOperationException (); + this.importer = importer; + } + + internal ICustomMetadataWriter CustomMetadataWriter { + get { return custom_writer; } + set { custom_writer = value; } + } +#endif + + public IAssemblyResolver AssemblyResolver { + get { return assembly_resolver ?? (assembly_resolver = new DefaultAssemblyResolver ()); } + } + + public IMetadataResolver MetadataResolver { + get { return metadata_resolver ?? (metadata_resolver = new MetadataResolver (this.AssemblyResolver)); } + } + + public TypeSystem TypeSystem { + get { return type_system ?? (type_system = TypeSystem.CreateTypeSystem (this)); } + } + + public bool HasAssemblyReferences { + get { + if (references != null) + return references.Count > 0; + + return HasImage && Image.HasTable (Table.AssemblyRef); + } + } + + public Collection AssemblyReferences { + get { + if (references != null) + return references; + + if (HasImage) + return references = Read (this, (_, reader) => reader.ReadAssemblyReferences ()); + + return references = new Collection (); + } + } + + public bool HasModuleReferences { + get { + if (modules != null) + return modules.Count > 0; + + return HasImage && Image.HasTable (Table.ModuleRef); + } + } + + public Collection ModuleReferences { + get { + if (modules != null) + return modules; + + if (HasImage) + return modules = Read (this, (_, reader) => reader.ReadModuleReferences ()); + + return modules = new Collection (); + } + } + + public bool HasResources { + get { + if (resources != null) + return resources.Count > 0; + + if (HasImage) + return Image.HasTable (Table.ManifestResource) || Read (this, (_, reader) => reader.HasFileResource ()); + + return false; + } + } + + public Collection Resources { + get { + if (resources != null) + return resources; + + if (HasImage) + return resources = Read (this, (_, reader) => reader.ReadResources ()); + + return resources = new Collection (); + } + } + + public bool HasCustomAttributes { + get { + if (custom_attributes != null) + return custom_attributes.Count > 0; + + return this.GetHasCustomAttributes (this); + } + } + + public Collection CustomAttributes { + get { return custom_attributes ?? (custom_attributes = this.GetCustomAttributes (this)); } + } + + public bool HasTypes { + get { + if (types != null) + return types.Count > 0; + + return HasImage && Image.HasTable (Table.TypeDef); + } + } + + public Collection Types { + get { + if (types != null) + return types; + + if (HasImage) + return types = Read (this, (_, reader) => reader.ReadTypes ()); + + return types = new TypeDefinitionCollection (this); + } + } + + public bool HasExportedTypes { + get { + if (exported_types != null) + return exported_types.Count > 0; + + return HasImage && Image.HasTable (Table.ExportedType); + } + } + + public Collection ExportedTypes { + get { + if (exported_types != null) + return exported_types; + + if (HasImage) + return exported_types = Read (this, (_, reader) => reader.ReadExportedTypes ()); + + return exported_types = new Collection (); + } + } + + public MethodDefinition EntryPoint { + get { + if (entry_point != null) + return entry_point; + + if (HasImage) + return entry_point = Read (this, (_, reader) => reader.ReadEntryPoint ()); + + return entry_point = null; + } + set { entry_point = value; } + } + + internal ModuleDefinition () + { + this.MetadataSystem = new MetadataSystem (); + this.token = new MetadataToken (TokenType.Module, 1); + } + + internal ModuleDefinition (Image image) + : this () + { + this.Image = image; + this.kind = image.Kind; + this.runtime = image.Runtime; + this.architecture = image.Architecture; + this.attributes = image.Attributes; + this.characteristics = image.Characteristics; + this.fq_name = image.FileName; + + this.reader = new MetadataReader (this); + } + + public bool HasTypeReference (string fullName) + { + return HasTypeReference (string.Empty, fullName); + } + + public bool HasTypeReference (string scope, string fullName) + { + CheckFullName (fullName); + + if (!HasImage) + return false; + + return GetTypeReference (scope, fullName) != null; + } + + public bool TryGetTypeReference (string fullName, out TypeReference type) + { + return TryGetTypeReference (string.Empty, fullName, out type); + } + + public bool TryGetTypeReference (string scope, string fullName, out TypeReference type) + { + CheckFullName (fullName); + + if (!HasImage) { + type = null; + return false; + } + + return (type = GetTypeReference (scope, fullName)) != null; + } + + TypeReference GetTypeReference (string scope, string fullname) + { + return Read (new Row (scope, fullname), (row, reader) => reader.GetTypeReference (row.Col1, row.Col2)); + } + + public IEnumerable GetTypeReferences () + { + if (!HasImage) + return Empty.Array; + + return Read (this, (_, reader) => reader.GetTypeReferences ()); + } + + public IEnumerable GetMemberReferences () + { + if (!HasImage) + return Empty.Array; + + return Read (this, (_, reader) => reader.GetMemberReferences ()); + } + + public TypeReference GetType (string fullName, bool runtimeName) + { + return runtimeName + ? TypeParser.ParseType (this, fullName) + : GetType (fullName); + } + + public TypeDefinition GetType (string fullName) + { + CheckFullName (fullName); + + var position = fullName.IndexOf ('/'); + if (position > 0) + return GetNestedType (fullName); + + return ((TypeDefinitionCollection) this.Types).GetType (fullName); + } + + public TypeDefinition GetType (string @namespace, string name) + { + Mixin.CheckName (name); + + return ((TypeDefinitionCollection) this.Types).GetType (@namespace ?? string.Empty, name); + } + + public IEnumerable GetTypes () + { + return GetTypes (Types); + } + + static IEnumerable GetTypes (Collection types) + { + for (int i = 0; i < types.Count; i++) { + var type = types [i]; + + yield return type; + + if (!type.HasNestedTypes) + continue; + + foreach (var nested in GetTypes (type.NestedTypes)) + yield return nested; + } + } + + static void CheckFullName (string fullName) + { + if (fullName == null) + throw new ArgumentNullException ("fullName"); + if (fullName.Length == 0) + throw new ArgumentException (); + } + + TypeDefinition GetNestedType (string fullname) + { + var names = fullname.Split ('/'); + var type = GetType (names [0]); + + if (type == null) + return null; + + for (int i = 1; i < names.Length; i++) { + var nested_type = type.GetNestedType (names [i]); + if (nested_type == null) + return null; + + type = nested_type; + } + + return type; + } + + internal FieldDefinition Resolve (FieldReference field) + { + return MetadataResolver.Resolve (field); + } + + internal MethodDefinition Resolve (MethodReference method) + { + return MetadataResolver.Resolve (method); + } + + internal TypeDefinition Resolve (TypeReference type) + { + return MetadataResolver.Resolve (type); + } + +#if !READ_ONLY + + static void CheckType (object type) + { + if (type == null) + throw new ArgumentNullException ("type"); + } + + static void CheckField (object field) + { + if (field == null) + throw new ArgumentNullException ("field"); + } + + static void CheckMethod (object method) + { + if (method == null) + throw new ArgumentNullException ("method"); + } + + static void CheckContext (IGenericParameterProvider context, ModuleDefinition module) + { + if (context == null) + return; + + if (context.Module != module) + throw new ArgumentException (); + } + + static ImportGenericContext GenericContextFor (IGenericParameterProvider context) + { + return context != null ? new ImportGenericContext (context) : default (ImportGenericContext); + } + +#if !CF + + public TypeReference Import (Type type) + { + return Import (type, null); + } + + public TypeReference Import (Type type, IGenericParameterProvider context) + { + CheckType (type); + CheckContext (context, this); + + return MetadataImporter.ImportType ( + type, + GenericContextFor (context), + context != null ? ImportGenericKind.Open : ImportGenericKind.Definition); + } + + public FieldReference Import (SR.FieldInfo field) + { + return Import (field, null); + } + + public FieldReference Import (SR.FieldInfo field, IGenericParameterProvider context) + { + CheckField (field); + CheckContext (context, this); + + return MetadataImporter.ImportField (field, GenericContextFor (context)); + } + + public MethodReference Import (SR.MethodBase method) + { + CheckMethod (method); + + return MetadataImporter.ImportMethod (method, default (ImportGenericContext), ImportGenericKind.Definition); + } + + public MethodReference Import (SR.MethodBase method, IGenericParameterProvider context) + { + CheckMethod (method); + CheckContext (context, this); + + return MetadataImporter.ImportMethod (method, + GenericContextFor (context), + context != null ? ImportGenericKind.Open : ImportGenericKind.Definition); + } +#endif + + public TypeReference Import (TypeReference type) + { + CheckType (type); + + if (type.Module == this) + return type; + + return MetadataImporter.ImportType (type, default (ImportGenericContext)); + } + + public TypeReference Import (TypeReference type, IGenericParameterProvider context) + { + CheckType (type); + + if (type.Module == this) + return type; + + CheckContext (context, this); + + return MetadataImporter.ImportType (type, GenericContextFor (context)); + } + + public FieldReference Import (FieldReference field) + { + CheckField (field); + + if (field.Module == this) + return field; + + return MetadataImporter.ImportField (field, default (ImportGenericContext)); + } + + public FieldReference Import (FieldReference field, IGenericParameterProvider context) + { + CheckField (field); + + if (field.Module == this) + return field; + + CheckContext (context, this); + + return MetadataImporter.ImportField (field, GenericContextFor (context)); + } + + public MethodReference Import (MethodReference method) + { + return Import (method, null); + } + + public MethodReference Import (MethodReference method, IGenericParameterProvider context) + { + CheckMethod (method); + + if (method.Module == this) + return method; + + CheckContext (context, this); + + return MetadataImporter.ImportMethod (method, GenericContextFor (context)); + } + +#endif + + public IMetadataTokenProvider LookupToken (int token) + { + return LookupToken (new MetadataToken ((uint) token)); + } + + public IMetadataTokenProvider LookupToken (MetadataToken token) + { + return Read (token, (t, reader) => reader.LookupToken (t)); + } + + internal TRet Read (TItem item, Func read) + { + var position = reader.position; + var context = reader.context; + + var ret = read (item, reader); + + reader.position = position; + reader.context = context; + + return ret; + } + + public bool HasDebugHeader { + get { return Image != null && !Image.Debug.IsZero; } + } + + public ImageDebugDirectory GetDebugHeader (out byte [] header) + { + if (!HasDebugHeader) + throw new InvalidOperationException (); + + return Image.GetDebugHeader (out header); + } + + void ProcessDebugHeader () + { + if (!HasDebugHeader) + return; + + byte [] header; + var directory = GetDebugHeader (out header); + + if (!symbol_reader.ProcessDebugHeader (directory, header)) + throw new InvalidOperationException (); + } + +#if !READ_ONLY + + public static ModuleDefinition CreateModule (string name, ModuleKind kind) + { + return CreateModule (name, new ModuleParameters { Kind = kind }); + } + + public static ModuleDefinition CreateModule (string name, ModuleParameters parameters) + { + Mixin.CheckName (name); + Mixin.CheckParameters (parameters); + + var module = new ModuleDefinition { + Name = name, + kind = parameters.Kind, + runtime = parameters.Runtime, + architecture = parameters.Architecture, + mvid = Guid.NewGuid (), + Attributes = ModuleAttributes.ILOnly, + Characteristics = (ModuleCharacteristics) 0x8540, + }; + + if (parameters.AssemblyResolver != null) + module.assembly_resolver = parameters.AssemblyResolver; + + if (parameters.MetadataResolver != null) + module.metadata_resolver = parameters.MetadataResolver; + + if (parameters.Kind != ModuleKind.NetModule) { + var assembly = new AssemblyDefinition (); + module.assembly = assembly; + module.assembly.Name = CreateAssemblyName (name); + assembly.main_module = module; + } + + module.Types.Add (new TypeDefinition (string.Empty, "", TypeAttributes.NotPublic)); + + return module; + } + + static AssemblyNameDefinition CreateAssemblyName (string name) + { + if (name.EndsWith (".dll") || name.EndsWith (".exe")) + name = name.Substring (0, name.Length - 4); + + return new AssemblyNameDefinition (name, new Version (0, 0, 0, 0)); + } + +#endif + + public void ReadSymbols () + { + if (string.IsNullOrEmpty (fq_name)) + throw new InvalidOperationException (); + + var provider = SymbolProvider.GetPlatformReaderProvider (); + if (provider == null) + throw new InvalidOperationException (); + + ReadSymbols (provider.GetSymbolReader (this, fq_name)); + } + + public void ReadSymbols (ISymbolReader reader) + { + if (reader == null) + throw new ArgumentNullException ("reader"); + + symbol_reader = reader; + + ProcessDebugHeader (); + } + + public static ModuleDefinition ReadModule (string fileName) + { + return ReadModule (fileName, new ReaderParameters (ReadingMode.Deferred)); + } + + public static ModuleDefinition ReadModule (Stream stream) + { + return ReadModule (stream, new ReaderParameters (ReadingMode.Deferred)); + } + + public static ModuleDefinition ReadModule (string fileName, ReaderParameters parameters) + { + using (var stream = GetFileStream (fileName, FileMode.Open, FileAccess.Read, FileShare.Read)) { + return ReadModule (stream, parameters); + } + } + + static void CheckStream (object stream) + { + if (stream == null) + throw new ArgumentNullException ("stream"); + } + + public static ModuleDefinition ReadModule (Stream stream, ReaderParameters parameters) + { + CheckStream (stream); + if (!stream.CanRead || !stream.CanSeek) + throw new ArgumentException (); + Mixin.CheckParameters (parameters); + + return ModuleReader.CreateModuleFrom ( + ImageReader.ReadImageFrom (stream), + parameters); + } + + static Stream GetFileStream (string fileName, FileMode mode, FileAccess access, FileShare share) + { + if (fileName == null) + throw new ArgumentNullException ("fileName"); + if (fileName.Length == 0) + throw new ArgumentException (); + + return new FileStream (fileName, mode, access, share); + } + +#if !READ_ONLY + + public void Write (string fileName) + { + Write (fileName, new WriterParameters ()); + } + + public void Write (Stream stream) + { + Write (stream, new WriterParameters ()); + } + + public void Write (string fileName, WriterParameters parameters) + { + using (var stream = GetFileStream (fileName, FileMode.Create, FileAccess.ReadWrite, FileShare.None)) { + Write (stream, parameters); + } + } + + public void Write (Stream stream, WriterParameters parameters) + { + CheckStream (stream); + if (!stream.CanWrite || !stream.CanSeek) + throw new ArgumentException (); + Mixin.CheckParameters (parameters); + + ModuleWriter.WriteModuleTo (this, stream, parameters); + } + +#endif + + } + + static partial class Mixin { + + public static void CheckParameters (object parameters) + { + if (parameters == null) + throw new ArgumentNullException ("parameters"); + } + + public static bool HasImage (this ModuleDefinition self) + { + return self != null && self.HasImage; + } + + public static bool IsCorlib (this ModuleDefinition module) + { + if (module.Assembly == null) + return false; + + return module.Assembly.Name.Name == "mscorlib"; + } + + public static string GetFullyQualifiedName (this Stream self) + { +#if !SILVERLIGHT + var file_stream = self as FileStream; + if (file_stream == null) + return string.Empty; + + return Path.GetFullPath (file_stream.Name); +#else + return string.Empty; +#endif + } + + public static TargetRuntime ParseRuntime (this string self) + { + switch (self [1]) { + case '1': + return self [3] == '0' + ? TargetRuntime.Net_1_0 + : TargetRuntime.Net_1_1; + case '2': + return TargetRuntime.Net_2_0; + case '4': + default: + return TargetRuntime.Net_4_0; + } + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil/ModuleKind.cs b/external/cecil-legacy/Mono.Cecil/ModuleKind.cs new file mode 100644 index 0000000000..c29da887d8 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/ModuleKind.cs @@ -0,0 +1,64 @@ +// +// ModuleKind.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +namespace Mono.Cecil { + + public enum ModuleKind { + Dll, + Console, + Windows, + NetModule, + } + + public enum TargetArchitecture { + I386, + AMD64, + IA64, + ARMv7, + } + + [Flags] + public enum ModuleAttributes { + ILOnly = 1, + Required32Bit = 2, + StrongNameSigned = 8, + Preferred32Bit = 0x00020000, + } + + [Flags] + public enum ModuleCharacteristics { + HighEntropyVA = 0x0020, + DynamicBase = 0x0040, + NoSEH = 0x0400, + NXCompat = 0x0100, + AppContainer = 0x1000, + TerminalServerAware = 0x8000, + } +} diff --git a/external/cecil-legacy/Mono.Cecil/ModuleReference.cs b/external/cecil-legacy/Mono.Cecil/ModuleReference.cs new file mode 100644 index 0000000000..3934b3ceb8 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/ModuleReference.cs @@ -0,0 +1,67 @@ +// +// ModuleReference.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +namespace Mono.Cecil { + + public class ModuleReference : IMetadataScope { + + string name; + + internal MetadataToken token; + + public string Name { + get { return name; } + set { name = value; } + } + + public virtual MetadataScopeType MetadataScopeType { + get { return MetadataScopeType.ModuleReference; } + } + + public MetadataToken MetadataToken { + get { return token; } + set { token = value; } + } + + internal ModuleReference () + { + this.token = new MetadataToken (TokenType.ModuleRef); + } + + public ModuleReference (string name) + : this () + { + this.name = name; + } + + public override string ToString () + { + return name; + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil/NativeType.cs b/external/cecil-legacy/Mono.Cecil/NativeType.cs new file mode 100644 index 0000000000..88da9805e8 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/NativeType.cs @@ -0,0 +1,73 @@ +// +// NativeType.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +namespace Mono.Cecil { + + public enum NativeType { + None = 0x66, + + Boolean = 0x02, + I1 = 0x03, + U1 = 0x04, + I2 = 0x05, + U2 = 0x06, + I4 = 0x07, + U4 = 0x08, + I8 = 0x09, + U8 = 0x0a, + R4 = 0x0b, + R8 = 0x0c, + LPStr = 0x14, + Int = 0x1f, + UInt = 0x20, + Func = 0x26, + Array = 0x2a, + + // Msft specific + Currency = 0x0f, + BStr = 0x13, + LPWStr = 0x15, + LPTStr = 0x16, + FixedSysString = 0x17, + IUnknown = 0x19, + IDispatch = 0x1a, + Struct = 0x1b, + IntF = 0x1c, + SafeArray = 0x1d, + FixedArray = 0x1e, + ByValStr = 0x22, + ANSIBStr = 0x23, + TBStr = 0x24, + VariantBool = 0x25, + ASAny = 0x28, + LPStruct = 0x2b, + CustomMarshaler = 0x2c, + Error = 0x2d, + Max = 0x50 + } +} diff --git a/external/cecil-legacy/Mono.Cecil/PInvokeAttributes.cs b/external/cecil-legacy/Mono.Cecil/PInvokeAttributes.cs new file mode 100644 index 0000000000..bb36838253 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/PInvokeAttributes.cs @@ -0,0 +1,62 @@ +// +// PInvokeAttributes.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +namespace Mono.Cecil { + + [Flags] + public enum PInvokeAttributes : ushort { + NoMangle = 0x0001, // PInvoke is to use the member name as specified + + // Character set + CharSetMask = 0x0006, + CharSetNotSpec = 0x0000, + CharSetAnsi = 0x0002, + CharSetUnicode = 0x0004, + CharSetAuto = 0x0006, + + SupportsLastError = 0x0040, // Information about target function. Not relevant for fields + + // Calling convetion + CallConvMask = 0x0700, + CallConvWinapi = 0x0100, + CallConvCdecl = 0x0200, + CallConvStdCall = 0x0300, + CallConvThiscall = 0x0400, + CallConvFastcall = 0x0500, + + BestFitMask = 0x0030, + BestFitEnabled = 0x0010, + BestFitDisabled = 0x0020, + + ThrowOnUnmappableCharMask = 0x3000, + ThrowOnUnmappableCharEnabled = 0x1000, + ThrowOnUnmappableCharDisabled = 0x2000, + } +} diff --git a/external/cecil-legacy/Mono.Cecil/PInvokeInfo.cs b/external/cecil-legacy/Mono.Cecil/PInvokeInfo.cs new file mode 100644 index 0000000000..cfd817c8d0 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/PInvokeInfo.cs @@ -0,0 +1,138 @@ +// +// PInvokeInfo.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +namespace Mono.Cecil { + + public sealed class PInvokeInfo { + + ushort attributes; + string entry_point; + ModuleReference module; + + public PInvokeAttributes Attributes { + get { return (PInvokeAttributes) attributes; } + set { attributes = (ushort) value; } + } + + public string EntryPoint { + get { return entry_point; } + set { entry_point = value; } + } + + public ModuleReference Module { + get { return module; } + set { module = value; } + } + + #region PInvokeAttributes + + public bool IsNoMangle { + get { return attributes.GetAttributes ((ushort) PInvokeAttributes.NoMangle); } + set { attributes = attributes.SetAttributes ((ushort) PInvokeAttributes.NoMangle, value); } + } + + public bool IsCharSetNotSpec { + get { return attributes.GetMaskedAttributes((ushort) PInvokeAttributes.CharSetMask, (ushort) PInvokeAttributes.CharSetNotSpec); } + set { attributes = attributes.SetMaskedAttributes ((ushort) PInvokeAttributes.CharSetMask, (ushort) PInvokeAttributes.CharSetNotSpec, value); } + } + + public bool IsCharSetAnsi { + get { return attributes.GetMaskedAttributes ((ushort) PInvokeAttributes.CharSetMask, (ushort) PInvokeAttributes.CharSetAnsi); } + set { attributes = attributes.SetMaskedAttributes ((ushort) PInvokeAttributes.CharSetMask, (ushort) PInvokeAttributes.CharSetAnsi, value); } + } + + public bool IsCharSetUnicode { + get { return attributes.GetMaskedAttributes ((ushort) PInvokeAttributes.CharSetMask, (ushort) PInvokeAttributes.CharSetUnicode); } + set { attributes = attributes.SetMaskedAttributes ((ushort) PInvokeAttributes.CharSetMask, (ushort) PInvokeAttributes.CharSetUnicode, value); } + } + + public bool IsCharSetAuto { + get { return attributes.GetMaskedAttributes ((ushort) PInvokeAttributes.CharSetMask, (ushort) PInvokeAttributes.CharSetAuto); } + set { attributes = attributes.SetMaskedAttributes ((ushort) PInvokeAttributes.CharSetMask, (ushort) PInvokeAttributes.CharSetAuto, value); } + } + + public bool SupportsLastError { + get { return attributes.GetAttributes ((ushort) PInvokeAttributes.SupportsLastError); } + set { attributes = attributes.SetAttributes ((ushort) PInvokeAttributes.SupportsLastError, value); } + } + + public bool IsCallConvWinapi { + get { return attributes.GetMaskedAttributes((ushort) PInvokeAttributes.CallConvMask, (ushort) PInvokeAttributes.CallConvWinapi); } + set { attributes = attributes.SetMaskedAttributes ((ushort) PInvokeAttributes.CallConvMask, (ushort) PInvokeAttributes.CallConvWinapi, value); } + } + + public bool IsCallConvCdecl { + get { return attributes.GetMaskedAttributes ((ushort) PInvokeAttributes.CallConvMask, (ushort) PInvokeAttributes.CallConvCdecl); } + set { attributes = attributes.SetMaskedAttributes ((ushort) PInvokeAttributes.CallConvMask, (ushort) PInvokeAttributes.CallConvCdecl, value); } + } + + public bool IsCallConvStdCall { + get { return attributes.GetMaskedAttributes ((ushort) PInvokeAttributes.CallConvMask, (ushort) PInvokeAttributes.CallConvStdCall); } + set { attributes = attributes.SetMaskedAttributes ((ushort) PInvokeAttributes.CallConvMask, (ushort) PInvokeAttributes.CallConvStdCall, value); } + } + + public bool IsCallConvThiscall { + get { return attributes.GetMaskedAttributes ((ushort) PInvokeAttributes.CallConvMask, (ushort) PInvokeAttributes.CallConvThiscall); } + set { attributes = attributes.SetMaskedAttributes ((ushort) PInvokeAttributes.CallConvMask, (ushort) PInvokeAttributes.CallConvThiscall, value); } + } + + public bool IsCallConvFastcall { + get { return attributes.GetMaskedAttributes ((ushort) PInvokeAttributes.CallConvMask, (ushort) PInvokeAttributes.CallConvFastcall); } + set { attributes = attributes.SetMaskedAttributes ((ushort) PInvokeAttributes.CallConvMask, (ushort) PInvokeAttributes.CallConvFastcall, value); } + } + + public bool IsBestFitEnabled { + get { return attributes.GetMaskedAttributes ((ushort) PInvokeAttributes.BestFitMask, (ushort) PInvokeAttributes.BestFitEnabled); } + set { attributes = attributes.SetMaskedAttributes ((ushort) PInvokeAttributes.BestFitMask, (ushort) PInvokeAttributes.BestFitEnabled, value); } + } + + public bool IsBestFitDisabled { + get { return attributes.GetMaskedAttributes ((ushort) PInvokeAttributes.BestFitMask, (ushort) PInvokeAttributes.BestFitDisabled); } + set { attributes = attributes.SetMaskedAttributes ((ushort) PInvokeAttributes.BestFitMask, (ushort) PInvokeAttributes.BestFitDisabled, value); } + } + + public bool IsThrowOnUnmappableCharEnabled { + get { return attributes.GetMaskedAttributes ((ushort) PInvokeAttributes.ThrowOnUnmappableCharMask, (ushort) PInvokeAttributes.ThrowOnUnmappableCharEnabled); } + set { attributes = attributes.SetMaskedAttributes ((ushort) PInvokeAttributes.ThrowOnUnmappableCharMask, (ushort) PInvokeAttributes.ThrowOnUnmappableCharEnabled, value); } + } + + public bool IsThrowOnUnmappableCharDisabled { + get { return attributes.GetMaskedAttributes ((ushort) PInvokeAttributes.ThrowOnUnmappableCharMask, (ushort) PInvokeAttributes.ThrowOnUnmappableCharDisabled); } + set { attributes = attributes.SetMaskedAttributes ((ushort) PInvokeAttributes.ThrowOnUnmappableCharMask, (ushort) PInvokeAttributes.ThrowOnUnmappableCharDisabled, value); } + } + + #endregion + + public PInvokeInfo (PInvokeAttributes attributes, string entryPoint, ModuleReference module) + { + this.attributes = (ushort) attributes; + this.entry_point = entryPoint; + this.module = module; + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil/ParameterAttributes.cs b/external/cecil-legacy/Mono.Cecil/ParameterAttributes.cs new file mode 100644 index 0000000000..e0bc825d8b --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/ParameterAttributes.cs @@ -0,0 +1,45 @@ +// +// ParameterAttributes.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +namespace Mono.Cecil { + + [Flags] + public enum ParameterAttributes : ushort { + None = 0x0000, + In = 0x0001, // Param is [In] + Out = 0x0002, // Param is [Out] + Lcid = 0x0004, + Retval = 0x0008, + Optional = 0x0010, // Param is optional + HasDefault = 0x1000, // Param has default value + HasFieldMarshal = 0x2000, // Param has field marshal + Unused = 0xcfe0 // Reserved: shall be zero in a conforming implementation + } +} diff --git a/external/cecil-legacy/Mono.Cecil/ParameterDefinition.cs b/external/cecil-legacy/Mono.Cecil/ParameterDefinition.cs new file mode 100644 index 0000000000..26152bd8df --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/ParameterDefinition.cs @@ -0,0 +1,172 @@ +// +// ParameterDefinition.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using Mono.Collections.Generic; + +namespace Mono.Cecil { + + public sealed class ParameterDefinition : ParameterReference, ICustomAttributeProvider, IConstantProvider, IMarshalInfoProvider { + + ushort attributes; + + internal IMethodSignature method; + + object constant = Mixin.NotResolved; + Collection custom_attributes; + MarshalInfo marshal_info; + + public ParameterAttributes Attributes { + get { return (ParameterAttributes) attributes; } + set { attributes = (ushort) value; } + } + + public IMethodSignature Method { + get { return method; } + } + + public int Sequence { + get { + if (method == null) + return -1; + + return method.HasImplicitThis () ? index + 1 : index; + } + } + + public bool HasConstant { + get { + ResolveConstant (); + + return constant != Mixin.NoValue; + } + set { if (!value) constant = Mixin.NoValue; } + } + + public object Constant { + get { return HasConstant ? constant : null; } + set { constant = value; } + } + + void ResolveConstant () + { + if (constant != Mixin.NotResolved) + return; + + this.ResolveConstant (ref constant, parameter_type.Module); + } + + public bool HasCustomAttributes { + get { + if (custom_attributes != null) + return custom_attributes.Count > 0; + + return this.GetHasCustomAttributes (parameter_type.Module); + } + } + + public Collection CustomAttributes { + get { return custom_attributes ?? (custom_attributes = this.GetCustomAttributes (parameter_type.Module)); } + } + + public bool HasMarshalInfo { + get { + if (marshal_info != null) + return true; + + return this.GetHasMarshalInfo (parameter_type.Module); + } + } + + public MarshalInfo MarshalInfo { + get { return marshal_info ?? (marshal_info = this.GetMarshalInfo (parameter_type.Module)); } + set { marshal_info = value; } + } + + #region ParameterAttributes + + public bool IsIn { + get { return attributes.GetAttributes ((ushort) ParameterAttributes.In); } + set { attributes = attributes.SetAttributes ((ushort) ParameterAttributes.In, value); } + } + + public bool IsOut { + get { return attributes.GetAttributes ((ushort) ParameterAttributes.Out); } + set { attributes = attributes.SetAttributes ((ushort) ParameterAttributes.Out, value); } + } + + public bool IsLcid { + get { return attributes.GetAttributes ((ushort) ParameterAttributes.Lcid); } + set { attributes = attributes.SetAttributes ((ushort) ParameterAttributes.Lcid, value); } + } + + public bool IsReturnValue { + get { return attributes.GetAttributes ((ushort) ParameterAttributes.Retval); } + set { attributes = attributes.SetAttributes ((ushort) ParameterAttributes.Retval, value); } + } + + public bool IsOptional { + get { return attributes.GetAttributes ((ushort) ParameterAttributes.Optional); } + set { attributes = attributes.SetAttributes ((ushort) ParameterAttributes.Optional, value); } + } + + public bool HasDefault { + get { return attributes.GetAttributes ((ushort) ParameterAttributes.HasDefault); } + set { attributes = attributes.SetAttributes ((ushort) ParameterAttributes.HasDefault, value); } + } + + public bool HasFieldMarshal { + get { return attributes.GetAttributes ((ushort) ParameterAttributes.HasFieldMarshal); } + set { attributes = attributes.SetAttributes ((ushort) ParameterAttributes.HasFieldMarshal, value); } + } + + #endregion + + internal ParameterDefinition (TypeReference parameterType, IMethodSignature method) + : this (string.Empty, ParameterAttributes.None, parameterType) + { + this.method = method; + } + + public ParameterDefinition (TypeReference parameterType) + : this (string.Empty, ParameterAttributes.None, parameterType) + { + } + + public ParameterDefinition (string name, ParameterAttributes attributes, TypeReference parameterType) + : base (name, parameterType) + { + this.attributes = (ushort) attributes; + this.token = new MetadataToken (TokenType.Param); + } + + public override ParameterDefinition Resolve () + { + return this; + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil/ParameterDefinitionCollection.cs b/external/cecil-legacy/Mono.Cecil/ParameterDefinitionCollection.cs new file mode 100644 index 0000000000..bd8b1c1390 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/ParameterDefinitionCollection.cs @@ -0,0 +1,80 @@ +// +// ParameterDefinitionCollection.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +using Mono.Collections.Generic; + +namespace Mono.Cecil { + + sealed class ParameterDefinitionCollection : Collection { + + readonly IMethodSignature method; + + internal ParameterDefinitionCollection (IMethodSignature method) + { + this.method = method; + } + + internal ParameterDefinitionCollection (IMethodSignature method, int capacity) + : base (capacity) + { + this.method = method; + } + + protected override void OnAdd (ParameterDefinition item, int index) + { + item.method = method; + item.index = index; + } + + protected override void OnInsert (ParameterDefinition item, int index) + { + item.method = method; + item.index = index; + + for (int i = index; i < size; i++) + items [i].index = i + 1; + } + + protected override void OnSet (ParameterDefinition item, int index) + { + item.method = method; + item.index = index; + } + + protected override void OnRemove (ParameterDefinition item, int index) + { + item.method = null; + item.index = -1; + + for (int i = index + 1; i < size; i++) + items [i].index = i - 1; + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil/ParameterReference.cs b/external/cecil-legacy/Mono.Cecil/ParameterReference.cs new file mode 100644 index 0000000000..46b057cd9f --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/ParameterReference.cs @@ -0,0 +1,75 @@ +// +// ParameterReference.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +namespace Mono.Cecil { + + public abstract class ParameterReference : IMetadataTokenProvider { + + string name; + internal int index = -1; + protected TypeReference parameter_type; + internal MetadataToken token; + + public string Name { + get { return name; } + set { name = value; } + } + + public int Index { + get { return index; } + } + + public TypeReference ParameterType { + get { return parameter_type; } + set { parameter_type = value; } + } + + public MetadataToken MetadataToken { + get { return token; } + set { token = value; } + } + + internal ParameterReference (string name, TypeReference parameterType) + { + if (parameterType == null) + throw new ArgumentNullException ("parameterType"); + + this.name = name ?? string.Empty; + this.parameter_type = parameterType; + } + + public override string ToString () + { + return name; + } + + public abstract ParameterDefinition Resolve (); + } +} diff --git a/external/cecil-legacy/Mono.Cecil/PinnedType.cs b/external/cecil-legacy/Mono.Cecil/PinnedType.cs new file mode 100644 index 0000000000..ff59cfb7e1 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/PinnedType.cs @@ -0,0 +1,53 @@ +// +// PinnedType.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +using MD = Mono.Cecil.Metadata; + +namespace Mono.Cecil { + + public sealed class PinnedType : TypeSpecification { + + public override bool IsValueType { + get { return false; } + set { throw new InvalidOperationException (); } + } + + public override bool IsPinned { + get { return true; } + } + + public PinnedType (TypeReference type) + : base (type) + { + Mixin.CheckType (type); + this.etype = MD.ElementType.Pinned; + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil/PointerType.cs b/external/cecil-legacy/Mono.Cecil/PointerType.cs new file mode 100644 index 0000000000..a142e14409 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/PointerType.cs @@ -0,0 +1,61 @@ +// +// PointerType.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +using MD = Mono.Cecil.Metadata; + +namespace Mono.Cecil { + + public sealed class PointerType : TypeSpecification { + + public override string Name { + get { return base.Name + "*"; } + } + + public override string FullName { + get { return base.FullName + "*"; } + } + + public override bool IsValueType { + get { return false; } + set { throw new InvalidOperationException (); } + } + + public override bool IsPointer { + get { return true; } + } + + public PointerType (TypeReference type) + : base (type) + { + Mixin.CheckType (type); + this.etype = MD.ElementType.Ptr; + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil/PropertyAttributes.cs b/external/cecil-legacy/Mono.Cecil/PropertyAttributes.cs new file mode 100644 index 0000000000..1be0413f28 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/PropertyAttributes.cs @@ -0,0 +1,41 @@ +// +// PropertyAttributes.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +namespace Mono.Cecil { + + [Flags] + public enum PropertyAttributes : ushort { + None = 0x0000, + SpecialName = 0x0200, // Property is special + RTSpecialName = 0x0400, // Runtime(metadata internal APIs) should check name encoding + HasDefault = 0x1000, // Property has default + Unused = 0xe9ff // Reserved: shall be zero in a conforming implementation + } +} diff --git a/external/cecil-legacy/Mono.Cecil/PropertyDefinition.cs b/external/cecil-legacy/Mono.Cecil/PropertyDefinition.cs new file mode 100644 index 0000000000..42878a0948 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/PropertyDefinition.cs @@ -0,0 +1,265 @@ +// +// PropertyDefinition.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System.Text; + +using Mono.Collections.Generic; + +namespace Mono.Cecil { + + public sealed class PropertyDefinition : PropertyReference, IMemberDefinition, IConstantProvider { + + bool? has_this; + ushort attributes; + + Collection custom_attributes; + + internal MethodDefinition get_method; + internal MethodDefinition set_method; + internal Collection other_methods; + + object constant = Mixin.NotResolved; + + public PropertyAttributes Attributes { + get { return (PropertyAttributes) attributes; } + set { attributes = (ushort) value; } + } + + public bool HasThis { + get { + if (has_this.HasValue) + return has_this.Value; + + if (GetMethod != null) + return get_method.HasThis; + + if (SetMethod != null) + return set_method.HasThis; + + return false; + } + set { has_this = value; } + } + + public bool HasCustomAttributes { + get { + if (custom_attributes != null) + return custom_attributes.Count > 0; + + return this.GetHasCustomAttributes (Module); + } + } + + public Collection CustomAttributes { + get { return custom_attributes ?? (custom_attributes = this.GetCustomAttributes (Module)); } + } + + public MethodDefinition GetMethod { + get { + if (get_method != null) + return get_method; + + InitializeMethods (); + return get_method; + } + set { get_method = value; } + } + + public MethodDefinition SetMethod { + get { + if (set_method != null) + return set_method; + + InitializeMethods (); + return set_method; + } + set { set_method = value; } + } + + public bool HasOtherMethods { + get { + if (other_methods != null) + return other_methods.Count > 0; + + InitializeMethods (); + return !other_methods.IsNullOrEmpty (); + } + } + + public Collection OtherMethods { + get { + if (other_methods != null) + return other_methods; + + InitializeMethods (); + + if (other_methods != null) + return other_methods; + + return other_methods = new Collection (); + } + } + + public bool HasParameters { + get { + InitializeMethods (); + + if (get_method != null) + return get_method.HasParameters; + + if (set_method != null) + return set_method.HasParameters && set_method.Parameters.Count > 1; + + return false; + } + } + + public override Collection Parameters { + get { + InitializeMethods (); + + if (get_method != null) + return MirrorParameters (get_method, 0); + + if (set_method != null) + return MirrorParameters (set_method, 1); + + return new Collection (); + } + } + + static Collection MirrorParameters (MethodDefinition method, int bound) + { + var parameters = new Collection (); + if (!method.HasParameters) + return parameters; + + var original_parameters = method.Parameters; + var end = original_parameters.Count - bound; + + for (int i = 0; i < end; i++) + parameters.Add (original_parameters [i]); + + return parameters; + } + + public bool HasConstant { + get { + ResolveConstant (); + + return constant != Mixin.NoValue; + } + set { if (!value) constant = Mixin.NoValue; } + } + + public object Constant { + get { return HasConstant ? constant : null; } + set { constant = value; } + } + + void ResolveConstant () + { + if (constant != Mixin.NotResolved) + return; + + this.ResolveConstant (ref constant, Module); + } + + #region PropertyAttributes + + public bool IsSpecialName { + get { return attributes.GetAttributes ((ushort) PropertyAttributes.SpecialName); } + set { attributes = attributes.SetAttributes ((ushort) PropertyAttributes.SpecialName, value); } + } + + public bool IsRuntimeSpecialName { + get { return attributes.GetAttributes ((ushort) PropertyAttributes.RTSpecialName); } + set { attributes = attributes.SetAttributes ((ushort) PropertyAttributes.RTSpecialName, value); } + } + + public bool HasDefault { + get { return attributes.GetAttributes ((ushort) PropertyAttributes.HasDefault); } + set { attributes = attributes.SetAttributes ((ushort) PropertyAttributes.HasDefault, value); } + } + + #endregion + + public new TypeDefinition DeclaringType { + get { return (TypeDefinition) base.DeclaringType; } + set { base.DeclaringType = value; } + } + + public override bool IsDefinition { + get { return true; } + } + + public override string FullName { + get { + var builder = new StringBuilder (); + builder.Append (PropertyType.ToString ()); + builder.Append (' '); + builder.Append (MemberFullName ()); + builder.Append ('('); + if (HasParameters) { + var parameters = Parameters; + for (int i = 0; i < parameters.Count; i++) { + if (i > 0) + builder.Append (','); + builder.Append (parameters [i].ParameterType.FullName); + } + } + builder.Append (')'); + return builder.ToString (); + } + } + + public PropertyDefinition (string name, PropertyAttributes attributes, TypeReference propertyType) + : base (name, propertyType) + { + this.attributes = (ushort) attributes; + this.token = new MetadataToken (TokenType.Property); + } + + void InitializeMethods () + { + if (get_method != null || set_method != null) + return; + + var module = this.Module; + if (!module.HasImage ()) + return; + + module.Read (this, (property, reader) => reader.ReadMethods (property)); + } + + public override PropertyDefinition Resolve () + { + return this; + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil/PropertyReference.cs b/external/cecil-legacy/Mono.Cecil/PropertyReference.cs new file mode 100644 index 0000000000..0dcfc952fe --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/PropertyReference.cs @@ -0,0 +1,59 @@ +// +// PropertyReference.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +using Mono.Collections.Generic; + +namespace Mono.Cecil { + + public abstract class PropertyReference : MemberReference { + + TypeReference property_type; + + public TypeReference PropertyType { + get { return property_type; } + set { property_type = value; } + } + + public abstract Collection Parameters { + get; + } + + internal PropertyReference (string name, TypeReference propertyType) + : base (name) + { + if (propertyType == null) + throw new ArgumentNullException ("propertyType"); + + property_type = propertyType; + } + + public abstract PropertyDefinition Resolve (); + } +} diff --git a/external/cecil-legacy/Mono.Cecil/ReferenceType.cs b/external/cecil-legacy/Mono.Cecil/ReferenceType.cs new file mode 100644 index 0000000000..7940c617c7 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/ReferenceType.cs @@ -0,0 +1,61 @@ +// +// ByReferenceType.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +using MD = Mono.Cecil.Metadata; + +namespace Mono.Cecil { + + public sealed class ByReferenceType : TypeSpecification { + + public override string Name { + get { return base.Name + "&"; } + } + + public override string FullName { + get { return base.FullName + "&"; } + } + + public override bool IsValueType { + get { return false; } + set { throw new InvalidOperationException (); } + } + + public override bool IsByReference { + get { return true; } + } + + public ByReferenceType (TypeReference type) + : base (type) + { + Mixin.CheckType (type); + this.etype = MD.ElementType.ByRef; + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil/Resource.cs b/external/cecil-legacy/Mono.Cecil/Resource.cs new file mode 100644 index 0000000000..eff7f41aa1 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/Resource.cs @@ -0,0 +1,76 @@ +// +// ResourceType.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +namespace Mono.Cecil { + + public enum ResourceType { + Linked, + Embedded, + AssemblyLinked, + } + + public abstract class Resource { + + string name; + uint attributes; + + public string Name { + get { return name; } + set { name = value; } + } + + public ManifestResourceAttributes Attributes { + get { return (ManifestResourceAttributes) attributes; } + set { attributes = (uint) value; } + } + + public abstract ResourceType ResourceType { + get; + } + + #region ManifestResourceAttributes + + public bool IsPublic { + get { return attributes.GetMaskedAttributes ((uint) ManifestResourceAttributes.VisibilityMask, (uint) ManifestResourceAttributes.Public); } + set { attributes = attributes.SetMaskedAttributes ((uint) ManifestResourceAttributes.VisibilityMask, (uint) ManifestResourceAttributes.Public, value); } + } + + public bool IsPrivate { + get { return attributes.GetMaskedAttributes ((uint) ManifestResourceAttributes.VisibilityMask, (uint) ManifestResourceAttributes.Private); } + set { attributes = attributes.SetMaskedAttributes ((uint) ManifestResourceAttributes.VisibilityMask, (uint) ManifestResourceAttributes.Private, value); } + } + + #endregion + + internal Resource (string name, ManifestResourceAttributes attributes) + { + this.name = name; + this.attributes = (uint) attributes; + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil/SecurityDeclaration.cs b/external/cecil-legacy/Mono.Cecil/SecurityDeclaration.cs new file mode 100644 index 0000000000..837472a119 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/SecurityDeclaration.cs @@ -0,0 +1,191 @@ +// +// SecurityDeclaration.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +using Mono.Collections.Generic; + +namespace Mono.Cecil { + + public enum SecurityAction : ushort { + Request = 1, + Demand = 2, + Assert = 3, + Deny = 4, + PermitOnly = 5, + LinkDemand = 6, + InheritDemand = 7, + RequestMinimum = 8, + RequestOptional = 9, + RequestRefuse = 10, + PreJitGrant = 11, + PreJitDeny = 12, + NonCasDemand = 13, + NonCasLinkDemand = 14, + NonCasInheritance = 15 + } + + public interface ISecurityDeclarationProvider : IMetadataTokenProvider { + + bool HasSecurityDeclarations { get; } + Collection SecurityDeclarations { get; } + } + + public sealed class SecurityAttribute : ICustomAttribute { + + TypeReference attribute_type; + + internal Collection fields; + internal Collection properties; + + public TypeReference AttributeType { + get { return attribute_type; } + set { attribute_type = value; } + } + + public bool HasFields { + get { return !fields.IsNullOrEmpty (); } + } + + public Collection Fields { + get { return fields ?? (fields = new Collection ()); } + } + + public bool HasProperties { + get { return !properties.IsNullOrEmpty (); } + } + + public Collection Properties { + get { return properties ?? (properties = new Collection ()); } + } + + public SecurityAttribute (TypeReference attributeType) + { + this.attribute_type = attributeType; + } + } + + public sealed class SecurityDeclaration { + + readonly internal uint signature; + byte [] blob; + readonly ModuleDefinition module; + + internal bool resolved; + SecurityAction action; + internal Collection security_attributes; + + public SecurityAction Action { + get { return action; } + set { action = value; } + } + + public bool HasSecurityAttributes { + get { + Resolve (); + + return !security_attributes.IsNullOrEmpty (); + } + } + + public Collection SecurityAttributes { + get { + Resolve (); + + return security_attributes ?? (security_attributes = new Collection ()); + } + } + + internal bool HasImage { + get { return module != null && module.HasImage; } + } + + internal SecurityDeclaration (SecurityAction action, uint signature, ModuleDefinition module) + { + this.action = action; + this.signature = signature; + this.module = module; + } + + public SecurityDeclaration (SecurityAction action) + { + this.action = action; + this.resolved = true; + } + + public SecurityDeclaration (SecurityAction action, byte [] blob) + { + this.action = action; + this.resolved = false; + this.blob = blob; + } + + public byte [] GetBlob () + { + if (blob != null) + return blob; + + if (!HasImage || signature == 0) + throw new NotSupportedException (); + + return blob = module.Read (this, (declaration, reader) => reader.ReadSecurityDeclarationBlob (declaration.signature)); + } + + void Resolve () + { + if (resolved || !HasImage) + return; + + module.Read (this, (declaration, reader) => { + reader.ReadSecurityDeclarationSignature (declaration); + return this; + }); + + resolved = true; + } + } + + static partial class Mixin { + + public static bool GetHasSecurityDeclarations ( + this ISecurityDeclarationProvider self, + ModuleDefinition module) + { + return module.HasImage () && module.Read (self, (provider, reader) => reader.HasSecurityDeclarations (provider)); + } + + public static Collection GetSecurityDeclarations ( + this ISecurityDeclarationProvider self, + ModuleDefinition module) + { + return module.HasImage () + ? module.Read (self, (provider, reader) => reader.ReadSecurityDeclarations (provider)) + : new Collection (); + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil/SentinelType.cs b/external/cecil-legacy/Mono.Cecil/SentinelType.cs new file mode 100644 index 0000000000..664d75bfd8 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/SentinelType.cs @@ -0,0 +1,53 @@ +// +// SentinelType.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +using MD = Mono.Cecil.Metadata; + +namespace Mono.Cecil { + + public sealed class SentinelType : TypeSpecification { + + public override bool IsValueType { + get { return false; } + set { throw new InvalidOperationException (); } + } + + public override bool IsSentinel { + get { return true; } + } + + public SentinelType (TypeReference type) + : base (type) + { + Mixin.CheckType (type); + this.etype = MD.ElementType.Sentinel; + } + } +} diff --git a/mcs/class/corlib/System/GCCollectionMode.cs b/external/cecil-legacy/Mono.Cecil/TargetRuntime.cs similarity index 82% rename from mcs/class/corlib/System/GCCollectionMode.cs rename to external/cecil-legacy/Mono.Cecil/TargetRuntime.cs index 0134db6dd1..9b49a5f77e 100644 --- a/mcs/class/corlib/System/GCCollectionMode.cs +++ b/external/cecil-legacy/Mono.Cecil/TargetRuntime.cs @@ -1,9 +1,10 @@ // -// System.GCCollectionMode.cs +// TargetRuntime.cs // - +// Author: +// Jb Evain (jbevain@gmail.com) // -// Copyright (C) 2007 Novell, Inc (http://www.novell.com) +// Copyright (c) 2008 - 2011 Jb Evain // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the @@ -12,10 +13,10 @@ // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: -// +// // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND @@ -25,14 +26,12 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -// Net 3.5 type +namespace Mono.Cecil { -namespace System -{ - [Serializable] - public enum GCCollectionMode { - Default = 0, - Forced = 1, - Optimized = 2 + public enum TargetRuntime { + Net_1_0, + Net_1_1, + Net_2_0, + Net_4_0, } } diff --git a/external/cecil-legacy/Mono.Cecil/TypeAttributes.cs b/external/cecil-legacy/Mono.Cecil/TypeAttributes.cs new file mode 100644 index 0000000000..86fbc4dba5 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/TypeAttributes.cs @@ -0,0 +1,81 @@ +// +// TypeAttributes.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +namespace Mono.Cecil { + + [Flags] + public enum TypeAttributes : uint { + // Visibility attributes + VisibilityMask = 0x00000007, // Use this mask to retrieve visibility information + NotPublic = 0x00000000, // Class has no public scope + Public = 0x00000001, // Class has public scope + NestedPublic = 0x00000002, // Class is nested with public visibility + NestedPrivate = 0x00000003, // Class is nested with private visibility + NestedFamily = 0x00000004, // Class is nested with family visibility + NestedAssembly = 0x00000005, // Class is nested with assembly visibility + NestedFamANDAssem = 0x00000006, // Class is nested with family and assembly visibility + NestedFamORAssem = 0x00000007, // Class is nested with family or assembly visibility + + // Class layout attributes + LayoutMask = 0x00000018, // Use this mask to retrieve class layout information + AutoLayout = 0x00000000, // Class fields are auto-laid out + SequentialLayout = 0x00000008, // Class fields are laid out sequentially + ExplicitLayout = 0x00000010, // Layout is supplied explicitly + + // Class semantics attributes + ClassSemanticMask = 0x00000020, // Use this mask to retrieve class semantics information + Class = 0x00000000, // Type is a class + Interface = 0x00000020, // Type is an interface + + // Special semantics in addition to class semantics + Abstract = 0x00000080, // Class is abstract + Sealed = 0x00000100, // Class cannot be extended + SpecialName = 0x00000400, // Class name is special + + // Implementation attributes + Import = 0x00001000, // Class/Interface is imported + Serializable = 0x00002000, // Class is serializable + WindowsRuntime = 0x00004000, // Windows Runtime type + + // String formatting attributes + StringFormatMask = 0x00030000, // Use this mask to retrieve string information for native interop + AnsiClass = 0x00000000, // LPSTR is interpreted as ANSI + UnicodeClass = 0x00010000, // LPSTR is interpreted as Unicode + AutoClass = 0x00020000, // LPSTR is interpreted automatically + + // Class initialization attributes + BeforeFieldInit = 0x00100000, // Initialize the class before first static field access + + // Additional flags + RTSpecialName = 0x00000800, // CLI provides 'special' behavior, depending upon the name of the Type + HasSecurity = 0x00040000, // Type has security associate with it + Forwarder = 0x00200000, // Exported type is a type forwarder + } +} diff --git a/external/cecil-legacy/Mono.Cecil/TypeDefinition.cs b/external/cecil-legacy/Mono.Cecil/TypeDefinition.cs new file mode 100644 index 0000000000..58c52af179 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/TypeDefinition.cs @@ -0,0 +1,518 @@ +// +// TypeDefinition.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +using Mono.Cecil.Metadata; +using Mono.Collections.Generic; + +namespace Mono.Cecil { + + public sealed class TypeDefinition : TypeReference, IMemberDefinition, ISecurityDeclarationProvider { + + uint attributes; + TypeReference base_type; + internal Range fields_range; + internal Range methods_range; + + short packing_size = Mixin.NotResolvedMarker; + int class_size = Mixin.NotResolvedMarker; + + Collection interfaces; + Collection nested_types; + Collection methods; + Collection fields; + Collection events; + Collection properties; + Collection custom_attributes; + Collection security_declarations; + + public TypeAttributes Attributes { + get { return (TypeAttributes) attributes; } + set { attributes = (uint) value; } + } + + public TypeReference BaseType { + get { return base_type; } + set { base_type = value; } + } + + void ResolveLayout () + { + if (packing_size != Mixin.NotResolvedMarker || class_size != Mixin.NotResolvedMarker) + return; + + if (!HasImage) { + packing_size = Mixin.NoDataMarker; + class_size = Mixin.NoDataMarker; + return; + } + + var row = Module.Read (this, (type, reader) => reader.ReadTypeLayout (type)); + + packing_size = row.Col1; + class_size = row.Col2; + } + + public bool HasLayoutInfo { + get { + if (packing_size >= 0 || class_size >= 0) + return true; + + ResolveLayout (); + + return packing_size >= 0 || class_size >= 0; + } + } + + public short PackingSize { + get { + if (packing_size >= 0) + return packing_size; + + ResolveLayout (); + + return packing_size >= 0 ? packing_size : (short) -1; + } + set { packing_size = value; } + } + + public int ClassSize { + get { + if (class_size >= 0) + return class_size; + + ResolveLayout (); + + return class_size >= 0 ? class_size : -1; + } + set { class_size = value; } + } + + public bool HasInterfaces { + get { + if (interfaces != null) + return interfaces.Count > 0; + + if (HasImage) + return Module.Read (this, (type, reader) => reader.HasInterfaces (type)); + + return false; + } + } + + public Collection Interfaces { + get { + if (interfaces != null) + return interfaces; + + if (HasImage) + return interfaces = Module.Read (this, (type, reader) => reader.ReadInterfaces (type)); + + return interfaces = new Collection (); + } + } + + public bool HasNestedTypes { + get { + if (nested_types != null) + return nested_types.Count > 0; + + if (HasImage) + return Module.Read (this, (type, reader) => reader.HasNestedTypes (type)); + + return false; + } + } + + public Collection NestedTypes { + get { + if (nested_types != null) + return nested_types; + + if (HasImage) + return nested_types = Module.Read (this, (type, reader) => reader.ReadNestedTypes (type)); + + return nested_types = new MemberDefinitionCollection (this); + } + } + + public bool HasMethods { + get { + if (methods != null) + return methods.Count > 0; + + if (HasImage) + return methods_range.Length > 0; + + return false; + } + } + + public Collection Methods { + get { + if (methods != null) + return methods; + + if (HasImage) + return methods = Module.Read (this, (type, reader) => reader.ReadMethods (type)); + + return methods = new MemberDefinitionCollection (this); + } + } + + public bool HasFields { + get { + if (fields != null) + return fields.Count > 0; + + if (HasImage) + return fields_range.Length > 0; + + return false; + } + } + + public Collection Fields { + get { + if (fields != null) + return fields; + + if (HasImage) + return fields = Module.Read (this, (type, reader) => reader.ReadFields (type)); + + return fields = new MemberDefinitionCollection (this); + } + } + + public bool HasEvents { + get { + if (events != null) + return events.Count > 0; + + if (HasImage) + return Module.Read (this, (type, reader) => reader.HasEvents (type)); + + return false; + } + } + + public Collection Events { + get { + if (events != null) + return events; + + if (HasImage) + return events = Module.Read (this, (type, reader) => reader.ReadEvents (type)); + + return events = new MemberDefinitionCollection (this); + } + } + + public bool HasProperties { + get { + if (properties != null) + return properties.Count > 0; + + if (HasImage) + return Module.Read (this, (type, reader) => reader.HasProperties (type)); + + return false; + } + } + + public Collection Properties { + get { + if (properties != null) + return properties; + + if (HasImage) + return properties = Module.Read (this, (type, reader) => reader.ReadProperties (type)); + + return properties = new MemberDefinitionCollection (this); + } + } + + public bool HasSecurityDeclarations { + get { + if (security_declarations != null) + return security_declarations.Count > 0; + + return this.GetHasSecurityDeclarations (Module); + } + } + + public Collection SecurityDeclarations { + get { return security_declarations ?? (security_declarations = this.GetSecurityDeclarations (Module)); } + } + + public bool HasCustomAttributes { + get { + if (custom_attributes != null) + return custom_attributes.Count > 0; + + return this.GetHasCustomAttributes (Module); + } + } + + public Collection CustomAttributes { + get { return custom_attributes ?? (custom_attributes = this.GetCustomAttributes (Module)); } + } + + public override bool HasGenericParameters { + get { + if (generic_parameters != null) + return generic_parameters.Count > 0; + + return this.GetHasGenericParameters (Module); + } + } + + public override Collection GenericParameters { + get { return generic_parameters ?? (generic_parameters = this.GetGenericParameters (Module)); } + } + + #region TypeAttributes + + public bool IsNotPublic { + get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NotPublic); } + set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NotPublic, value); } + } + + public bool IsPublic { + get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.Public); } + set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.Public, value); } + } + + public bool IsNestedPublic { + get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedPublic); } + set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedPublic, value); } + } + + public bool IsNestedPrivate { + get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedPrivate); } + set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedPrivate, value); } + } + + public bool IsNestedFamily { + get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedFamily); } + set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedFamily, value); } + } + + public bool IsNestedAssembly { + get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedAssembly); } + set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedAssembly, value); } + } + + public bool IsNestedFamilyAndAssembly { + get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedFamANDAssem); } + set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedFamANDAssem, value); } + } + + public bool IsNestedFamilyOrAssembly { + get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedFamORAssem); } + set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedFamORAssem, value); } + } + + public bool IsAutoLayout { + get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.LayoutMask, (uint) TypeAttributes.AutoLayout); } + set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.LayoutMask, (uint) TypeAttributes.AutoLayout, value); } + } + + public bool IsSequentialLayout { + get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.LayoutMask, (uint) TypeAttributes.SequentialLayout); } + set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.LayoutMask, (uint) TypeAttributes.SequentialLayout, value); } + } + + public bool IsExplicitLayout { + get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.LayoutMask, (uint) TypeAttributes.ExplicitLayout); } + set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.LayoutMask, (uint) TypeAttributes.ExplicitLayout, value); } + } + + public bool IsClass { + get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.ClassSemanticMask, (uint) TypeAttributes.Class); } + set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.ClassSemanticMask, (uint) TypeAttributes.Class, value); } + } + + public bool IsInterface { + get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.ClassSemanticMask, (uint) TypeAttributes.Interface); } + set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.ClassSemanticMask, (uint) TypeAttributes.Interface, value); } + } + + public bool IsAbstract { + get { return attributes.GetAttributes ((uint) TypeAttributes.Abstract); } + set { attributes = attributes.SetAttributes ((uint) TypeAttributes.Abstract, value); } + } + + public bool IsSealed { + get { return attributes.GetAttributes ((uint) TypeAttributes.Sealed); } + set { attributes = attributes.SetAttributes ((uint) TypeAttributes.Sealed, value); } + } + + public bool IsSpecialName { + get { return attributes.GetAttributes ((uint) TypeAttributes.SpecialName); } + set { attributes = attributes.SetAttributes ((uint) TypeAttributes.SpecialName, value); } + } + + public bool IsImport { + get { return attributes.GetAttributes ((uint) TypeAttributes.Import); } + set { attributes = attributes.SetAttributes ((uint) TypeAttributes.Import, value); } + } + + public bool IsSerializable { + get { return attributes.GetAttributes ((uint) TypeAttributes.Serializable); } + set { attributes = attributes.SetAttributes ((uint) TypeAttributes.Serializable, value); } + } + + public bool IsWindowsRuntime { + get { return attributes.GetAttributes ((uint) TypeAttributes.WindowsRuntime); } + set { attributes = attributes.SetAttributes ((uint) TypeAttributes.WindowsRuntime, value); } + } + + public bool IsAnsiClass { + get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.StringFormatMask, (uint) TypeAttributes.AnsiClass); } + set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.StringFormatMask, (uint) TypeAttributes.AnsiClass, value); } + } + + public bool IsUnicodeClass { + get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.StringFormatMask, (uint) TypeAttributes.UnicodeClass); } + set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.StringFormatMask, (uint) TypeAttributes.UnicodeClass, value); } + } + + public bool IsAutoClass { + get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.StringFormatMask, (uint) TypeAttributes.AutoClass); } + set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.StringFormatMask, (uint) TypeAttributes.AutoClass, value); } + } + + public bool IsBeforeFieldInit { + get { return attributes.GetAttributes ((uint) TypeAttributes.BeforeFieldInit); } + set { attributes = attributes.SetAttributes ((uint) TypeAttributes.BeforeFieldInit, value); } + } + + public bool IsRuntimeSpecialName { + get { return attributes.GetAttributes ((uint) TypeAttributes.RTSpecialName); } + set { attributes = attributes.SetAttributes ((uint) TypeAttributes.RTSpecialName, value); } + } + + public bool HasSecurity { + get { return attributes.GetAttributes ((uint) TypeAttributes.HasSecurity); } + set { attributes = attributes.SetAttributes ((uint) TypeAttributes.HasSecurity, value); } + } + + #endregion + + public bool IsEnum { + get { return base_type != null && base_type.IsTypeOf ("System", "Enum"); } + } + + public override bool IsValueType { + get { + if (base_type == null) + return false; + + return base_type.IsTypeOf ("System", "Enum") || (base_type.IsTypeOf ("System", "ValueType") && !this.IsTypeOf ("System", "Enum")); + } + } + + public override bool IsPrimitive { + get { + ElementType primitive_etype; + return MetadataSystem.TryGetPrimitiveElementType (this, out primitive_etype); + } + } + + public override MetadataType MetadataType { + get { + ElementType primitive_etype; + if (MetadataSystem.TryGetPrimitiveElementType (this, out primitive_etype)) + return (MetadataType) primitive_etype; + + return base.MetadataType; + } + } + + public override bool IsDefinition { + get { return true; } + } + + public new TypeDefinition DeclaringType { + get { return (TypeDefinition) base.DeclaringType; } + set { base.DeclaringType = value; } + } + + public TypeDefinition (string @namespace, string name, TypeAttributes attributes) + : base (@namespace, name) + { + this.attributes = (uint) attributes; + this.token = new MetadataToken (TokenType.TypeDef); + } + + public TypeDefinition (string @namespace, string name, TypeAttributes attributes, TypeReference baseType) : + this (@namespace, name, attributes) + { + this.BaseType = baseType; + } + + public override TypeDefinition Resolve () + { + return this; + } + } + + static partial class Mixin { + + public static TypeReference GetEnumUnderlyingType (this TypeDefinition self) + { + var fields = self.Fields; + + for (int i = 0; i < fields.Count; i++) { + var field = fields [i]; + if (!field.IsStatic) + return field.FieldType; + } + + throw new ArgumentException (); + } + + public static TypeDefinition GetNestedType (this TypeDefinition self, string name) + { + if (!self.HasNestedTypes) + return null; + + var nested_types = self.NestedTypes; + + for (int i = 0; i < nested_types.Count; i++) { + var nested_type = nested_types [i]; + if (nested_type.Name == name) + return nested_type; + } + + return null; + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil/TypeDefinitionCollection.cs b/external/cecil-legacy/Mono.Cecil/TypeDefinitionCollection.cs new file mode 100644 index 0000000000..eae712282f --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/TypeDefinitionCollection.cs @@ -0,0 +1,118 @@ +// +// TypeDefinitionCollection.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Collections.Generic; + +using Mono.Cecil.Metadata; + +using Mono.Collections.Generic; + +namespace Mono.Cecil { + + using Slot = Row; + + sealed class TypeDefinitionCollection : Collection { + + readonly ModuleDefinition container; + readonly Dictionary name_cache; + + internal TypeDefinitionCollection (ModuleDefinition container) + { + this.container = container; + this.name_cache = new Dictionary (new RowEqualityComparer ()); + } + + internal TypeDefinitionCollection (ModuleDefinition container, int capacity) + : base (capacity) + { + this.container = container; + this.name_cache = new Dictionary (capacity, new RowEqualityComparer ()); + } + + protected override void OnAdd (TypeDefinition item, int index) + { + Attach (item); + } + + protected override void OnSet (TypeDefinition item, int index) + { + Attach (item); + } + + protected override void OnInsert (TypeDefinition item, int index) + { + Attach (item); + } + + protected override void OnRemove (TypeDefinition item, int index) + { + Detach (item); + } + + protected override void OnClear () + { + foreach (var type in this) + Detach (type); + } + + void Attach (TypeDefinition type) + { + if (type.Module != null && type.Module != container) + throw new ArgumentException ("Type already attached"); + + type.module = container; + type.scope = container; + name_cache [new Slot (type.Namespace, type.Name)] = type; + } + + void Detach (TypeDefinition type) + { + type.module = null; + type.scope = null; + name_cache.Remove (new Slot (type.Namespace, type.Name)); + } + + public TypeDefinition GetType (string fullname) + { + string @namespace, name; + TypeParser.SplitFullName (fullname, out @namespace, out name); + + return GetType (@namespace, name); + } + + public TypeDefinition GetType (string @namespace, string name) + { + TypeDefinition type; + if (name_cache.TryGetValue (new Slot (@namespace, name), out type)) + return type; + + return null; + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil/TypeParser.cs b/external/cecil-legacy/Mono.Cecil/TypeParser.cs new file mode 100644 index 0000000000..90e04a6f41 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/TypeParser.cs @@ -0,0 +1,549 @@ +// +// TypeParser.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Text; + +using Mono.Cecil.Metadata; + +namespace Mono.Cecil { + + class TypeParser { + + class Type { + public const int Ptr = -1; + public const int ByRef = -2; + public const int SzArray = -3; + + public string type_fullname; + public string [] nested_names; + public int arity; + public int [] specs; + public Type [] generic_arguments; + public string assembly; + } + + readonly string fullname; + readonly int length; + + int position; + + TypeParser (string fullname) + { + this.fullname = fullname; + this.length = fullname.Length; + } + + Type ParseType (bool fq_name) + { + var type = new Type (); + type.type_fullname = ParsePart (); + + type.nested_names = ParseNestedNames (); + + if (TryGetArity (type)) + type.generic_arguments = ParseGenericArguments (type.arity); + + type.specs = ParseSpecs (); + + if (fq_name) + type.assembly = ParseAssemblyName (); + + return type; + } + + static bool TryGetArity (Type type) + { + int arity = 0; + + TryAddArity (type.type_fullname, ref arity); + + var nested_names = type.nested_names; + if (!nested_names.IsNullOrEmpty ()) { + for (int i = 0; i < nested_names.Length; i++) + TryAddArity (nested_names [i], ref arity); + } + + type.arity = arity; + return arity > 0; + } + + static bool TryGetArity (string name, out int arity) + { + arity = 0; + var index = name.LastIndexOf ('`'); + if (index == -1) + return false; + + return ParseInt32 (name.Substring (index + 1), out arity); + } + + static bool ParseInt32 (string value, out int result) + { +#if CF + try { + result = int.Parse (value); + return true; + } catch { + result = 0; + return false; + } +#else + return int.TryParse (value, out result); +#endif + } + + static void TryAddArity (string name, ref int arity) + { + int type_arity; + if (!TryGetArity (name, out type_arity)) + return; + + arity += type_arity; + } + + string ParsePart () + { + int start = position; + while (position < length && !IsDelimiter (fullname [position])) + position++; + + return fullname.Substring (start, position - start); + } + + static bool IsDelimiter (char chr) + { + return "+,[]*&".IndexOf (chr) != -1; + } + + void TryParseWhiteSpace () + { + while (position < length && Char.IsWhiteSpace (fullname [position])) + position++; + } + + string [] ParseNestedNames () + { + string [] nested_names = null; + while (TryParse ('+')) + Add (ref nested_names, ParsePart ()); + + return nested_names; + } + + bool TryParse (char chr) + { + if (position < length && fullname [position] == chr) { + position++; + return true; + } + + return false; + } + + static void Add (ref T [] array, T item) + { + if (array == null) { + array = new [] { item }; + return; + } + + array = array.Resize (array.Length + 1); + array [array.Length - 1] = item; + } + + int [] ParseSpecs () + { + int [] specs = null; + + while (position < length) { + switch (fullname [position]) { + case '*': + position++; + Add (ref specs, Type.Ptr); + break; + case '&': + position++; + Add (ref specs, Type.ByRef); + break; + case '[': + position++; + switch (fullname [position]) { + case ']': + position++; + Add (ref specs, Type.SzArray); + break; + case '*': + position++; + Add (ref specs, 1); + break; + default: + var rank = 1; + while (TryParse (',')) + rank++; + + Add (ref specs, rank); + + TryParse (']'); + break; + } + break; + default: + return specs; + } + } + + return specs; + } + + Type [] ParseGenericArguments (int arity) + { + Type [] generic_arguments = null; + + if (position == length || fullname [position] != '[') + return generic_arguments; + + TryParse ('['); + + for (int i = 0; i < arity; i++) { + var fq_argument = TryParse ('['); + Add (ref generic_arguments, ParseType (fq_argument)); + if (fq_argument) + TryParse (']'); + + TryParse (','); + TryParseWhiteSpace (); + } + + TryParse (']'); + + return generic_arguments; + } + + string ParseAssemblyName () + { + if (!TryParse (',')) + return string.Empty; + + TryParseWhiteSpace (); + + var start = position; + while (position < length) { + var chr = fullname [position]; + if (chr == '[' || chr == ']') + break; + + position++; + } + + return fullname.Substring (start, position - start); + } + + public static TypeReference ParseType (ModuleDefinition module, string fullname) + { + if (string.IsNullOrEmpty (fullname)) + return null; + + var parser = new TypeParser (fullname); + return GetTypeReference (module, parser.ParseType (true)); + } + + static TypeReference GetTypeReference (ModuleDefinition module, Type type_info) + { + TypeReference type; + if (!TryGetDefinition (module, type_info, out type)) + type = CreateReference (type_info, module, GetMetadataScope (module, type_info)); + + return CreateSpecs (type, type_info); + } + + static TypeReference CreateSpecs (TypeReference type, Type type_info) + { + type = TryCreateGenericInstanceType (type, type_info); + + var specs = type_info.specs; + if (specs.IsNullOrEmpty ()) + return type; + + for (int i = 0; i < specs.Length; i++) { + switch (specs [i]) { + case Type.Ptr: + type = new PointerType (type); + break; + case Type.ByRef: + type = new ByReferenceType (type); + break; + case Type.SzArray: + type = new ArrayType (type); + break; + default: + var array = new ArrayType (type); + array.Dimensions.Clear (); + + for (int j = 0; j < specs [i]; j++) + array.Dimensions.Add (new ArrayDimension ()); + + type = array; + break; + } + } + + return type; + } + + static TypeReference TryCreateGenericInstanceType (TypeReference type, Type type_info) + { + var generic_arguments = type_info.generic_arguments; + if (generic_arguments.IsNullOrEmpty ()) + return type; + + var instance = new GenericInstanceType (type); + var instance_arguments = instance.GenericArguments; + + for (int i = 0; i < generic_arguments.Length; i++) + instance_arguments.Add (GetTypeReference (type.Module, generic_arguments [i])); + + return instance; + } + + public static void SplitFullName (string fullname, out string @namespace, out string name) + { + var last_dot = fullname.LastIndexOf ('.'); + + if (last_dot == -1) { + @namespace = string.Empty; + name = fullname; + } else { + @namespace = fullname.Substring (0, last_dot); + name = fullname.Substring (last_dot + 1); + } + } + + static TypeReference CreateReference (Type type_info, ModuleDefinition module, IMetadataScope scope) + { + string @namespace, name; + SplitFullName (type_info.type_fullname, out @namespace, out name); + + var type = new TypeReference (@namespace, name, module, scope); + MetadataSystem.TryProcessPrimitiveTypeReference (type); + + AdjustGenericParameters (type); + + var nested_names = type_info.nested_names; + if (nested_names.IsNullOrEmpty ()) + return type; + + for (int i = 0; i < nested_names.Length; i++) { + type = new TypeReference (string.Empty, nested_names [i], module, null) { + DeclaringType = type, + }; + + AdjustGenericParameters (type); + } + + return type; + } + + static void AdjustGenericParameters (TypeReference type) + { + int arity; + if (!TryGetArity (type.Name, out arity)) + return; + + for (int i = 0; i < arity; i++) + type.GenericParameters.Add (new GenericParameter (type)); + } + + static IMetadataScope GetMetadataScope (ModuleDefinition module, Type type_info) + { + if (string.IsNullOrEmpty (type_info.assembly)) + return module.TypeSystem.Corlib; + + return MatchReference (module, AssemblyNameReference.Parse (type_info.assembly)); + } + + static AssemblyNameReference MatchReference (ModuleDefinition module, AssemblyNameReference pattern) + { + var references = module.AssemblyReferences; + + for (int i = 0; i < references.Count; i++) { + var reference = references [i]; + if (reference.FullName == pattern.FullName) + return reference; + } + + return pattern; + } + + static bool TryGetDefinition (ModuleDefinition module, Type type_info, out TypeReference type) + { + type = null; + if (!TryCurrentModule (module, type_info)) + return false; + + var typedef = module.GetType (type_info.type_fullname); + if (typedef == null) + return false; + + var nested_names = type_info.nested_names; + if (!nested_names.IsNullOrEmpty ()) { + for (int i = 0; i < nested_names.Length; i++) + typedef = typedef.GetNestedType (nested_names [i]); + } + + type = typedef; + return true; + } + + static bool TryCurrentModule (ModuleDefinition module, Type type_info) + { + if (string.IsNullOrEmpty (type_info.assembly)) + return true; + + if (module.assembly != null && module.assembly.Name.FullName == type_info.assembly) + return true; + + return false; + } + + public static string ToParseable (TypeReference type) + { + if (type == null) + return null; + + var name = new StringBuilder (); + AppendType (type, name, true, true); + return name.ToString (); + } + + static void AppendType (TypeReference type, StringBuilder name, bool fq_name, bool top_level) + { + var declaring_type = type.DeclaringType; + if (declaring_type != null) { + AppendType (declaring_type, name, false, top_level); + name.Append ('+'); + } + + var @namespace = type.Namespace; + if (!string.IsNullOrEmpty (@namespace)) { + name.Append (@namespace); + name.Append ('.'); + } + + name.Append (type.GetElementType ().Name); + + if (!fq_name) + return; + + if (type.IsTypeSpecification ()) + AppendTypeSpecification ((TypeSpecification) type, name); + + if (RequiresFullyQualifiedName (type, top_level)) { + name.Append (", "); + name.Append (GetScopeFullName (type)); + } + } + + static string GetScopeFullName (TypeReference type) + { + var scope = type.Scope; + switch (scope.MetadataScopeType) { + case MetadataScopeType.AssemblyNameReference: + return ((AssemblyNameReference) scope).FullName; + case MetadataScopeType.ModuleDefinition: + return ((ModuleDefinition) scope).Assembly.Name.FullName; + } + + throw new ArgumentException (); + } + + static void AppendTypeSpecification (TypeSpecification type, StringBuilder name) + { + if (type.ElementType.IsTypeSpecification ()) + AppendTypeSpecification ((TypeSpecification) type.ElementType, name); + + switch (type.etype) { + case ElementType.Ptr: + name.Append ('*'); + break; + case ElementType.ByRef: + name.Append ('&'); + break; + case ElementType.SzArray: + case ElementType.Array: + var array = (ArrayType) type; + if (array.IsVector) { + name.Append ("[]"); + } else { + name.Append ('['); + for (int i = 1; i < array.Rank; i++) + name.Append (','); + name.Append (']'); + } + break; + case ElementType.GenericInst: + var instance = (GenericInstanceType) type; + var arguments = instance.GenericArguments; + + name.Append ('['); + + for (int i = 0; i < arguments.Count; i++) { + if (i > 0) + name.Append (','); + + var argument = arguments [i]; + var requires_fqname = argument.Scope != argument.Module; + + if (requires_fqname) + name.Append ('['); + + AppendType (argument, name, true, false); + + if (requires_fqname) + name.Append (']'); + } + + name.Append (']'); + break; + default: + return; + } + } + + static bool RequiresFullyQualifiedName (TypeReference type, bool top_level) + { + if (type.Scope == type.Module) + return false; + + if (type.Scope.Name == "mscorlib" && top_level) + return false; + + return true; + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil/TypeReference.cs b/external/cecil-legacy/Mono.Cecil/TypeReference.cs new file mode 100644 index 0000000000..f811b4f018 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/TypeReference.cs @@ -0,0 +1,339 @@ +// +// TypeReference.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +using Mono.Cecil.Metadata; +using Mono.Collections.Generic; + +namespace Mono.Cecil { + + public enum MetadataType : byte { + Void = ElementType.Void, + Boolean = ElementType.Boolean, + Char = ElementType.Char, + SByte = ElementType.I1, + Byte = ElementType.U1, + Int16 = ElementType.I2, + UInt16 = ElementType.U2, + Int32 = ElementType.I4, + UInt32 = ElementType.U4, + Int64 = ElementType.I8, + UInt64 = ElementType.U8, + Single = ElementType.R4, + Double = ElementType.R8, + String = ElementType.String, + Pointer = ElementType.Ptr, + ByReference = ElementType.ByRef, + ValueType = ElementType.ValueType, + Class = ElementType.Class, + Var = ElementType.Var, + Array = ElementType.Array, + GenericInstance = ElementType.GenericInst, + TypedByReference = ElementType.TypedByRef, + IntPtr = ElementType.I, + UIntPtr = ElementType.U, + FunctionPointer = ElementType.FnPtr, + Object = ElementType.Object, + MVar = ElementType.MVar, + RequiredModifier = ElementType.CModReqD, + OptionalModifier = ElementType.CModOpt, + Sentinel = ElementType.Sentinel, + Pinned = ElementType.Pinned, + } + + public class TypeReference : MemberReference, IGenericParameterProvider, IGenericContext { + + string @namespace; + bool value_type; + internal IMetadataScope scope; + internal ModuleDefinition module; + + internal ElementType etype = ElementType.None; + + string fullname; + + protected Collection generic_parameters; + + public override string Name { + get { return base.Name; } + set { + base.Name = value; + fullname = null; + } + } + + public virtual string Namespace { + get { return @namespace; } + set { + @namespace = value; + fullname = null; + } + } + + public virtual bool IsValueType { + get { return value_type; } + set { value_type = value; } + } + + public override ModuleDefinition Module { + get { + if (module != null) + return module; + + var declaring_type = this.DeclaringType; + if (declaring_type != null) + return declaring_type.Module; + + return null; + } + } + + IGenericParameterProvider IGenericContext.Type { + get { return this; } + } + + IGenericParameterProvider IGenericContext.Method { + get { return null; } + } + + GenericParameterType IGenericParameterProvider.GenericParameterType { + get { return GenericParameterType.Type; } + } + + public virtual bool HasGenericParameters { + get { return !generic_parameters.IsNullOrEmpty (); } + } + + public virtual Collection GenericParameters { + get { + if (generic_parameters != null) + return generic_parameters; + + return generic_parameters = new GenericParameterCollection (this); + } + } + + public virtual IMetadataScope Scope { + get { + var declaring_type = this.DeclaringType; + if (declaring_type != null) + return declaring_type.Scope; + + return scope; + } + set { + var declaring_type = this.DeclaringType; + if (declaring_type != null) { + declaring_type.Scope = value; + return; + } + + scope = value; + } + } + + public bool IsNested { + get { return this.DeclaringType != null; } + } + + public override TypeReference DeclaringType { + get { return base.DeclaringType; } + set { + base.DeclaringType = value; + fullname = null; + } + } + + public override string FullName { + get { + if (fullname != null) + return fullname; + + if (IsNested) + return fullname = DeclaringType.FullName + "/" + Name; + + if (string.IsNullOrEmpty (@namespace)) + return fullname = Name; + + return fullname = @namespace + "." + Name; + } + } + + public virtual bool IsByReference { + get { return false; } + } + + public virtual bool IsPointer { + get { return false; } + } + + public virtual bool IsSentinel { + get { return false; } + } + + public virtual bool IsArray { + get { return false; } + } + + public virtual bool IsGenericParameter { + get { return false; } + } + + public virtual bool IsGenericInstance { + get { return false; } + } + + public virtual bool IsRequiredModifier { + get { return false; } + } + + public virtual bool IsOptionalModifier { + get { return false; } + } + + public virtual bool IsPinned { + get { return false; } + } + + public virtual bool IsFunctionPointer { + get { return false; } + } + + public virtual bool IsPrimitive { + get { return etype.IsPrimitive (); } + } + + public virtual MetadataType MetadataType { + get { + switch (etype) { + case ElementType.None: + return IsValueType ? MetadataType.ValueType : MetadataType.Class; + default: + return (MetadataType) etype; + } + } + } + + protected TypeReference (string @namespace, string name) + : base (name) + { + this.@namespace = @namespace ?? string.Empty; + this.token = new MetadataToken (TokenType.TypeRef, 0); + } + + public TypeReference (string @namespace, string name, ModuleDefinition module, IMetadataScope scope) + : this (@namespace, name) + { + this.module = module; + this.scope = scope; + } + + public TypeReference (string @namespace, string name, ModuleDefinition module, IMetadataScope scope, bool valueType) : + this (@namespace, name, module, scope) + { + value_type = valueType; + } + + public virtual TypeReference GetElementType () + { + return this; + } + + public virtual TypeDefinition Resolve () + { + var module = this.Module; + if (module == null) + throw new NotSupportedException (); + + return module.Resolve (this); + } + } + + static partial class Mixin { + + public static bool IsPrimitive (this ElementType self) + { + switch (self) { + case ElementType.Boolean: + case ElementType.Char: + case ElementType.I: + case ElementType.U: + case ElementType.I1: + case ElementType.U1: + case ElementType.I2: + case ElementType.U2: + case ElementType.I4: + case ElementType.U4: + case ElementType.I8: + case ElementType.U8: + case ElementType.R4: + case ElementType.R8: + return true; + default: + return false; + } + } + + public static bool IsTypeOf (this TypeReference self, string @namespace, string name) + { + return self.Name == name + && self.Namespace == @namespace; + } + + public static bool IsTypeSpecification (this TypeReference type) + { + switch (type.etype) { + case ElementType.Array: + case ElementType.ByRef: + case ElementType.CModOpt: + case ElementType.CModReqD: + case ElementType.FnPtr: + case ElementType.GenericInst: + case ElementType.MVar: + case ElementType.Pinned: + case ElementType.Ptr: + case ElementType.SzArray: + case ElementType.Sentinel: + case ElementType.Var: + return true; + } + + return false; + } + + public static TypeDefinition CheckedResolve (this TypeReference self) + { + var type = self.Resolve (); + if (type == null) + throw new ResolutionException (self); + + return type; + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil/TypeSpecification.cs b/external/cecil-legacy/Mono.Cecil/TypeSpecification.cs new file mode 100644 index 0000000000..75651be59c --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/TypeSpecification.cs @@ -0,0 +1,95 @@ +// +// TypeSpecification.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +using Mono.Cecil.Metadata; + +namespace Mono.Cecil { + + public abstract class TypeSpecification : TypeReference { + + readonly TypeReference element_type; + + public TypeReference ElementType { + get { return element_type; } + } + + public override string Name { + get { return element_type.Name; } + set { throw new InvalidOperationException (); } + } + + public override string Namespace { + get { return element_type.Namespace; } + set { throw new InvalidOperationException (); } + } + + public override IMetadataScope Scope { + get { return element_type.Scope; } + set { throw new InvalidOperationException (); } + } + + public override ModuleDefinition Module { + get { return element_type.Module; } + } + + public override string FullName { + get { return element_type.FullName; } + } + + internal override bool ContainsGenericParameter { + get { return element_type.ContainsGenericParameter; } + } + + public override MetadataType MetadataType { + get { return (MetadataType) etype; } + } + + internal TypeSpecification (TypeReference type) + : base (null, null) + { + this.element_type = type; + this.token = new MetadataToken (TokenType.TypeSpec); + } + + public override TypeReference GetElementType () + { + return element_type.GetElementType (); + } + } + + static partial class Mixin { + + public static void CheckType (TypeReference type) + { + if (type == null) + throw new ArgumentNullException ("type"); + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil/TypeSystem.cs b/external/cecil-legacy/Mono.Cecil/TypeSystem.cs new file mode 100644 index 0000000000..63f6aea287 --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/TypeSystem.cs @@ -0,0 +1,290 @@ +// +// TypeSystem.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +using Mono.Cecil.Metadata; + +namespace Mono.Cecil { + + public abstract class TypeSystem { + + sealed class CoreTypeSystem : TypeSystem { + + public CoreTypeSystem (ModuleDefinition module) + : base (module) + { + } + + internal override TypeReference LookupType (string @namespace, string name) + { + var type = LookupTypeDefinition (@namespace, name) ?? LookupTypeForwarded (@namespace, name); + if (type != null) + return type; + + throw new NotSupportedException (); + } + + TypeReference LookupTypeDefinition (string @namespace, string name) + { + var metadata = module.MetadataSystem; + if (metadata.Types == null) + Initialize (module.Types); + + return module.Read (new Row (@namespace, name), (row, reader) => { + var types = reader.metadata.Types; + + for (int i = 0; i < types.Length; i++) { + if (types [i] == null) + types [i] = reader.GetTypeDefinition ((uint) i + 1); + + var type = types [i]; + + if (type.Name == row.Col2 && type.Namespace == row.Col1) + return type; + } + + return null; + }); + } + + TypeReference LookupTypeForwarded (string @namespace, string name) + { + if (!module.HasExportedTypes) + return null; + + var exported_types = module.ExportedTypes; + for (int i = 0; i < exported_types.Count; i++) { + var exported_type = exported_types [i]; + + if (exported_type.Name == name && exported_type.Namespace == @namespace) + return exported_type.CreateReference (); + } + + return null; + } + + static void Initialize (object obj) + { + } + } + + sealed class CommonTypeSystem : TypeSystem { + + AssemblyNameReference corlib; + + public CommonTypeSystem (ModuleDefinition module) + : base (module) + { + } + + internal override TypeReference LookupType (string @namespace, string name) + { + return CreateTypeReference (@namespace, name); + } + + public AssemblyNameReference GetCorlibReference () + { + if (corlib != null) + return corlib; + + const string mscorlib = "mscorlib"; + + var references = module.AssemblyReferences; + + for (int i = 0; i < references.Count; i++) { + var reference = references [i]; + if (reference.Name == mscorlib) + return corlib = reference; + } + + corlib = new AssemblyNameReference { + Name = mscorlib, + Version = GetCorlibVersion (), + PublicKeyToken = new byte [] { 0xb7, 0x7a, 0x5c, 0x56, 0x19, 0x34, 0xe0, 0x89 }, + }; + + references.Add (corlib); + + return corlib; + } + + Version GetCorlibVersion () + { + switch (module.Runtime) { + case TargetRuntime.Net_1_0: + case TargetRuntime.Net_1_1: + return new Version (1, 0, 0, 0); + case TargetRuntime.Net_2_0: + return new Version (2, 0, 0, 0); + case TargetRuntime.Net_4_0: + return new Version (4, 0, 0, 0); + default: + throw new NotSupportedException (); + } + } + + TypeReference CreateTypeReference (string @namespace, string name) + { + return new TypeReference (@namespace, name, module, GetCorlibReference ()); + } + } + + readonly ModuleDefinition module; + + TypeReference type_object; + TypeReference type_void; + TypeReference type_bool; + TypeReference type_char; + TypeReference type_sbyte; + TypeReference type_byte; + TypeReference type_int16; + TypeReference type_uint16; + TypeReference type_int32; + TypeReference type_uint32; + TypeReference type_int64; + TypeReference type_uint64; + TypeReference type_single; + TypeReference type_double; + TypeReference type_intptr; + TypeReference type_uintptr; + TypeReference type_string; + TypeReference type_typedref; + + TypeSystem (ModuleDefinition module) + { + this.module = module; + } + + internal static TypeSystem CreateTypeSystem (ModuleDefinition module) + { + if (module.IsCorlib ()) + return new CoreTypeSystem (module); + + return new CommonTypeSystem (module); + } + + internal abstract TypeReference LookupType (string @namespace, string name); + + TypeReference LookupSystemType (string name, ElementType element_type) + { + var type = LookupType ("System", name); + type.etype = element_type; + return type; + } + + TypeReference LookupSystemValueType (string name, ElementType element_type) + { + var type = LookupSystemType (name, element_type); + type.IsValueType = true; + return type; + } + + public IMetadataScope Corlib { + get { + var common = this as CommonTypeSystem; + if (common == null) + return module; + + return common.GetCorlibReference (); + } + } + + public TypeReference Object { + get { return type_object ?? (type_object = LookupSystemType ("Object", ElementType.Object)); } + } + + public TypeReference Void { + get { return type_void ?? (type_void = LookupSystemType ("Void", ElementType.Void)); } + } + + public TypeReference Boolean { + get { return type_bool ?? (type_bool = LookupSystemValueType ("Boolean", ElementType.Boolean)); } + } + + public TypeReference Char { + get { return type_char ?? (type_char = LookupSystemValueType ("Char", ElementType.Char)); } + } + + public TypeReference SByte { + get { return type_sbyte ?? (type_sbyte = LookupSystemValueType ("SByte", ElementType.I1)); } + } + + public TypeReference Byte { + get { return type_byte ?? (type_byte = LookupSystemValueType ("Byte", ElementType.U1)); } + } + + public TypeReference Int16 { + get { return type_int16 ?? (type_int16 = LookupSystemValueType ("Int16", ElementType.I2)); } + } + + public TypeReference UInt16 { + get { return type_uint16 ?? (type_uint16 = LookupSystemValueType ("UInt16", ElementType.U2)); } + } + + public TypeReference Int32 { + get { return type_int32 ?? (type_int32 = LookupSystemValueType ("Int32", ElementType.I4)); } + } + + public TypeReference UInt32 { + get { return type_uint32 ?? (type_uint32 = LookupSystemValueType ("UInt32", ElementType.U4)); } + } + + public TypeReference Int64 { + get { return type_int64 ?? (type_int64 = LookupSystemValueType ("Int64", ElementType.I8)); } + } + + public TypeReference UInt64 { + get { return type_uint64 ?? (type_uint64 = LookupSystemValueType ("UInt64", ElementType.U8)); } + } + + public TypeReference Single { + get { return type_single ?? (type_single = LookupSystemValueType ("Single", ElementType.R4)); } + } + + public TypeReference Double { + get { return type_double ?? (type_double = LookupSystemValueType ("Double", ElementType.R8)); } + } + + public TypeReference IntPtr { + get { return type_intptr ?? (type_intptr = LookupSystemValueType ("IntPtr", ElementType.I)); } + } + + public TypeReference UIntPtr { + get { return type_uintptr ?? (type_uintptr = LookupSystemValueType ("UIntPtr", ElementType.U)); } + } + + public TypeReference String { + get { return type_string ?? (type_string = LookupSystemType ("String", ElementType.String)); } + } + + public TypeReference TypedReference { + get { return type_typedref ?? (type_typedref = LookupSystemValueType ("TypedReference", ElementType.TypedByRef)); } + } + } +} diff --git a/external/cecil-legacy/Mono.Cecil/VariantType.cs b/external/cecil-legacy/Mono.Cecil/VariantType.cs new file mode 100644 index 0000000000..76562f6e6f --- /dev/null +++ b/external/cecil-legacy/Mono.Cecil/VariantType.cs @@ -0,0 +1,53 @@ +// +// VariantType.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +namespace Mono.Cecil { + + public enum VariantType { + None = 0, + I2 = 2, + I4 = 3, + R4 = 4, + R8 = 5, + CY = 6, + Date = 7, + BStr = 8, + Dispatch = 9, + Error = 10, + Bool = 11, + Variant = 12, + Unknown = 13, + Decimal = 14, + I1 = 16, + UI1 = 17, + UI2 = 18, + UI4 = 19, + Int = 22, + UInt = 23 + } +} diff --git a/external/cecil-legacy/Mono.Collections.Generic/Collection.cs b/external/cecil-legacy/Mono.Collections.Generic/Collection.cs new file mode 100644 index 0000000000..4d92717608 --- /dev/null +++ b/external/cecil-legacy/Mono.Collections.Generic/Collection.cs @@ -0,0 +1,420 @@ +// +// Collection.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Collections; +using System.Collections.Generic; + +namespace Mono.Collections.Generic { + + public class Collection : IList, IList { + + internal T [] items; + internal int size; + int version; + + public int Count { + get { return size; } + } + + public T this [int index] { + get { + if (index >= size) + throw new ArgumentOutOfRangeException (); + + return items [index]; + } + set { + CheckIndex (index); + if (index == size) + throw new ArgumentOutOfRangeException (); + + OnSet (value, index); + + items [index] = value; + } + } + + bool ICollection.IsReadOnly { + get { return false; } + } + + bool IList.IsFixedSize { + get { return false; } + } + + bool IList.IsReadOnly { + get { return false; } + } + + object IList.this [int index] { + get { return this [index]; } + set { + CheckIndex (index); + + try { + this [index] = (T) value; + return; + } catch (InvalidCastException) { + } catch (NullReferenceException) { + } + + throw new ArgumentException (); + } + } + + int ICollection.Count { + get { return Count; } + } + + bool ICollection.IsSynchronized { + get { return false; } + } + + object ICollection.SyncRoot { + get { return this; } + } + + public Collection () + { + items = Empty.Array; + } + + public Collection (int capacity) + { + if (capacity < 0) + throw new ArgumentOutOfRangeException (); + + items = new T [capacity]; + } + + public Collection (ICollection items) + { + if (items == null) + throw new ArgumentNullException ("items"); + + this.items = new T [items.Count]; + items.CopyTo (this.items, 0); + this.size = this.items.Length; + } + + public void Add (T item) + { + if (size == items.Length) + Grow (1); + + OnAdd (item, size); + + items [size++] = item; + version++; + } + + public bool Contains (T item) + { + return IndexOf (item) != -1; + } + + public int IndexOf (T item) + { + return Array.IndexOf (items, item, 0, size); + } + + public void Insert (int index, T item) + { + CheckIndex (index); + if (size == items.Length) + Grow (1); + + OnInsert (item, index); + + Shift (index, 1); + items [index] = item; + version++; + } + + public void RemoveAt (int index) + { + if (index < 0 || index >= size) + throw new ArgumentOutOfRangeException (); + + var item = items [index]; + + OnRemove (item, index); + + Shift (index, -1); + Array.Clear (items, size, 1); + version++; + } + + public bool Remove (T item) + { + var index = IndexOf (item); + if (index == -1) + return false; + + OnRemove (item, index); + + Shift (index, -1); + Array.Clear (items, size, 1); + version++; + + return true; + } + + public void Clear () + { + OnClear (); + + Array.Clear (items, 0, size); + size = 0; + version++; + } + + public void CopyTo (T [] array, int arrayIndex) + { + Array.Copy (items, 0, array, arrayIndex, size); + } + + public T [] ToArray () + { + var array = new T [size]; + Array.Copy (items, 0, array, 0, size); + return array; + } + + void CheckIndex (int index) + { + if (index < 0 || index > size) + throw new ArgumentOutOfRangeException (); + } + + void Shift (int start, int delta) + { + if (delta < 0) + start -= delta; + + if (start < size) + Array.Copy (items, start, items, start + delta, size - start); + + size += delta; + + if (delta < 0) + Array.Clear (items, size, -delta); + } + + protected virtual void OnAdd (T item, int index) + { + } + + protected virtual void OnInsert (T item, int index) + { + } + + protected virtual void OnSet (T item, int index) + { + } + + protected virtual void OnRemove (T item, int index) + { + } + + protected virtual void OnClear () + { + } + + internal virtual void Grow (int desired) + { + int new_size = size + desired; + if (new_size <= items.Length) + return; + + const int default_capacity = 4; + + new_size = System.Math.Max ( + System.Math.Max (items.Length * 2, default_capacity), + new_size); + +#if !CF + Array.Resize (ref items, new_size); +#else + var array = new T [new_size]; + Array.Copy (items, array, size); + items = array; +#endif + } + + int IList.Add (object value) + { + try { + Add ((T) value); + return size - 1; + } catch (InvalidCastException) { + } catch (NullReferenceException) { + } + + throw new ArgumentException (); + } + + void IList.Clear () + { + Clear (); + } + + bool IList.Contains (object value) + { + return ((IList) this).IndexOf (value) > -1; + } + + int IList.IndexOf (object value) + { + try { + return IndexOf ((T) value); + } catch (InvalidCastException) { + } catch (NullReferenceException) { + } + + return -1; + } + + void IList.Insert (int index, object value) + { + CheckIndex (index); + + try { + Insert (index, (T) value); + return; + } catch (InvalidCastException) { + } catch (NullReferenceException) { + } + + throw new ArgumentException (); + } + + void IList.Remove (object value) + { + try { + Remove ((T) value); + } catch (InvalidCastException) { + } catch (NullReferenceException) { + } + } + + void IList.RemoveAt (int index) + { + RemoveAt (index); + } + + void ICollection.CopyTo (Array array, int index) + { + Array.Copy (items, 0, array, index, size); + } + + public Enumerator GetEnumerator () + { + return new Enumerator (this); + } + + IEnumerator IEnumerable.GetEnumerator () + { + return new Enumerator (this); + } + + IEnumerator IEnumerable.GetEnumerator () + { + return new Enumerator (this); + } + + public struct Enumerator : IEnumerator, IDisposable { + + Collection collection; + T current; + + int next; + readonly int version; + + public T Current { + get { return current; } + } + + object IEnumerator.Current { + get { + CheckState (); + + if (next <= 0) + throw new InvalidOperationException (); + + return current; + } + } + + internal Enumerator (Collection collection) + : this () + { + this.collection = collection; + this.version = collection.version; + } + + public bool MoveNext () + { + CheckState (); + + if (next < 0) + return false; + + if (next < collection.size) { + current = collection.items [next++]; + return true; + } + + next = -1; + return false; + } + + public void Reset () + { + CheckState (); + + next = 0; + } + + void CheckState () + { + if (collection == null) + throw new ObjectDisposedException (GetType ().FullName); + + if (version != collection.version) + throw new InvalidOperationException (); + } + + public void Dispose () + { + collection = null; + } + } + } +} diff --git a/external/cecil-legacy/Mono.Collections.Generic/ReadOnlyCollection.cs b/external/cecil-legacy/Mono.Collections.Generic/ReadOnlyCollection.cs new file mode 100644 index 0000000000..7f24df699e --- /dev/null +++ b/external/cecil-legacy/Mono.Collections.Generic/ReadOnlyCollection.cs @@ -0,0 +1,112 @@ +// +// ReadOnlyCollection.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Collections; +using System .Collections.Generic; + +namespace Mono.Collections.Generic { + + public sealed class ReadOnlyCollection : Collection, ICollection, IList { + + static ReadOnlyCollection empty; + + public static ReadOnlyCollection Empty { + get { return empty ?? (empty = new ReadOnlyCollection ()); } + } + + bool ICollection.IsReadOnly { + get { return true; } + } + + bool IList.IsFixedSize { + get { return true; } + } + + bool IList.IsReadOnly { + get { return true; } + } + + private ReadOnlyCollection () + { + } + + public ReadOnlyCollection (T [] array) + { + if (array == null) + throw new ArgumentNullException (); + + Initialize (array, array.Length); + } + + public ReadOnlyCollection (Collection collection) + { + if (collection == null) + throw new ArgumentNullException (); + + Initialize (collection.items, collection.size); + } + + void Initialize (T [] items, int size) + { + this.items = new T [size]; + Array.Copy (items, 0, this.items, 0, size); + this.size = size; + } + + internal override void Grow (int desired) + { + throw new InvalidOperationException (); + } + + protected override void OnAdd (T item, int index) + { + throw new InvalidOperationException (); + } + + protected override void OnClear () + { + throw new InvalidOperationException (); + } + + protected override void OnInsert (T item, int index) + { + throw new InvalidOperationException (); + } + + protected override void OnRemove (T item, int index) + { + throw new InvalidOperationException (); + } + + protected override void OnSet (T item, int index) + { + throw new InvalidOperationException (); + } + } +} diff --git a/external/cecil-legacy/Mono.Security.Cryptography/CryptoConvert.cs b/external/cecil-legacy/Mono.Security.Cryptography/CryptoConvert.cs new file mode 100644 index 0000000000..26a4ba25b6 --- /dev/null +++ b/external/cecil-legacy/Mono.Security.Cryptography/CryptoConvert.cs @@ -0,0 +1,243 @@ +// +// CryptoConvert.cs - Crypto Convertion Routines +// +// Author: +// Sebastien Pouliot +// +// (C) 2003 Motus Technologies Inc. (http://www.motus.com) +// Copyright (C) 2004-2006 Novell Inc. (http://www.novell.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Security.Cryptography; + +#if !(SILVERLIGHT || READ_ONLY) + +namespace Mono.Security.Cryptography { + + static class CryptoConvert { + + static private int ToInt32LE (byte [] bytes, int offset) + { + return (bytes [offset+3] << 24) | (bytes [offset+2] << 16) | (bytes [offset+1] << 8) | bytes [offset]; + } + + static private uint ToUInt32LE (byte [] bytes, int offset) + { + return (uint)((bytes [offset+3] << 24) | (bytes [offset+2] << 16) | (bytes [offset+1] << 8) | bytes [offset]); + } + + static private byte[] Trim (byte[] array) + { + for (int i=0; i < array.Length; i++) { + if (array [i] != 0x00) { + byte[] result = new byte [array.Length - i]; + Buffer.BlockCopy (array, i, result, 0, result.Length); + return result; + } + } + return null; + } + + static RSA FromCapiPrivateKeyBlob (byte[] blob, int offset) + { + RSAParameters rsap = new RSAParameters (); + try { + if ((blob [offset] != 0x07) || // PRIVATEKEYBLOB (0x07) + (blob [offset+1] != 0x02) || // Version (0x02) + (blob [offset+2] != 0x00) || // Reserved (word) + (blob [offset+3] != 0x00) || + (ToUInt32LE (blob, offset+8) != 0x32415352)) // DWORD magic = RSA2 + throw new CryptographicException ("Invalid blob header"); + + // ALGID (CALG_RSA_SIGN, CALG_RSA_KEYX, ...) + // int algId = ToInt32LE (blob, offset+4); + + // DWORD bitlen + int bitLen = ToInt32LE (blob, offset+12); + + // DWORD public exponent + byte[] exp = new byte [4]; + Buffer.BlockCopy (blob, offset+16, exp, 0, 4); + Array.Reverse (exp); + rsap.Exponent = Trim (exp); + + int pos = offset+20; + // BYTE modulus[rsapubkey.bitlen/8]; + int byteLen = (bitLen >> 3); + rsap.Modulus = new byte [byteLen]; + Buffer.BlockCopy (blob, pos, rsap.Modulus, 0, byteLen); + Array.Reverse (rsap.Modulus); + pos += byteLen; + + // BYTE prime1[rsapubkey.bitlen/16]; + int byteHalfLen = (byteLen >> 1); + rsap.P = new byte [byteHalfLen]; + Buffer.BlockCopy (blob, pos, rsap.P, 0, byteHalfLen); + Array.Reverse (rsap.P); + pos += byteHalfLen; + + // BYTE prime2[rsapubkey.bitlen/16]; + rsap.Q = new byte [byteHalfLen]; + Buffer.BlockCopy (blob, pos, rsap.Q, 0, byteHalfLen); + Array.Reverse (rsap.Q); + pos += byteHalfLen; + + // BYTE exponent1[rsapubkey.bitlen/16]; + rsap.DP = new byte [byteHalfLen]; + Buffer.BlockCopy (blob, pos, rsap.DP, 0, byteHalfLen); + Array.Reverse (rsap.DP); + pos += byteHalfLen; + + // BYTE exponent2[rsapubkey.bitlen/16]; + rsap.DQ = new byte [byteHalfLen]; + Buffer.BlockCopy (blob, pos, rsap.DQ, 0, byteHalfLen); + Array.Reverse (rsap.DQ); + pos += byteHalfLen; + + // BYTE coefficient[rsapubkey.bitlen/16]; + rsap.InverseQ = new byte [byteHalfLen]; + Buffer.BlockCopy (blob, pos, rsap.InverseQ, 0, byteHalfLen); + Array.Reverse (rsap.InverseQ); + pos += byteHalfLen; + + // ok, this is hackish but CryptoAPI support it so... + // note: only works because CRT is used by default + // http://bugzilla.ximian.com/show_bug.cgi?id=57941 + rsap.D = new byte [byteLen]; // must be allocated + if (pos + byteLen + offset <= blob.Length) { + // BYTE privateExponent[rsapubkey.bitlen/8]; + Buffer.BlockCopy (blob, pos, rsap.D, 0, byteLen); + Array.Reverse (rsap.D); + } + } + catch (Exception e) { + throw new CryptographicException ("Invalid blob.", e); + } + + RSA rsa = null; + try { + rsa = RSA.Create (); + rsa.ImportParameters (rsap); + } + catch (CryptographicException ce) { + // this may cause problem when this code is run under + // the SYSTEM identity on Windows (e.g. ASP.NET). See + // http://bugzilla.ximian.com/show_bug.cgi?id=77559 + try { + CspParameters csp = new CspParameters (); + csp.Flags = CspProviderFlags.UseMachineKeyStore; + rsa = new RSACryptoServiceProvider (csp); + rsa.ImportParameters (rsap); + } + catch { + // rethrow original, not the later, exception if this fails + throw ce; + } + } + return rsa; + } + + static RSA FromCapiPublicKeyBlob (byte[] blob, int offset) + { + try { + if ((blob [offset] != 0x06) || // PUBLICKEYBLOB (0x06) + (blob [offset+1] != 0x02) || // Version (0x02) + (blob [offset+2] != 0x00) || // Reserved (word) + (blob [offset+3] != 0x00) || + (ToUInt32LE (blob, offset+8) != 0x31415352)) // DWORD magic = RSA1 + throw new CryptographicException ("Invalid blob header"); + + // ALGID (CALG_RSA_SIGN, CALG_RSA_KEYX, ...) + // int algId = ToInt32LE (blob, offset+4); + + // DWORD bitlen + int bitLen = ToInt32LE (blob, offset+12); + + // DWORD public exponent + RSAParameters rsap = new RSAParameters (); + rsap.Exponent = new byte [3]; + rsap.Exponent [0] = blob [offset+18]; + rsap.Exponent [1] = blob [offset+17]; + rsap.Exponent [2] = blob [offset+16]; + + int pos = offset+20; + // BYTE modulus[rsapubkey.bitlen/8]; + int byteLen = (bitLen >> 3); + rsap.Modulus = new byte [byteLen]; + Buffer.BlockCopy (blob, pos, rsap.Modulus, 0, byteLen); + Array.Reverse (rsap.Modulus); + + RSA rsa = null; + try { + rsa = RSA.Create (); + rsa.ImportParameters (rsap); + } + catch (CryptographicException) { + // this may cause problem when this code is run under + // the SYSTEM identity on Windows (e.g. ASP.NET). See + // http://bugzilla.ximian.com/show_bug.cgi?id=77559 + CspParameters csp = new CspParameters (); + csp.Flags = CspProviderFlags.UseMachineKeyStore; + rsa = new RSACryptoServiceProvider (csp); + rsa.ImportParameters (rsap); + } + return rsa; + } + catch (Exception e) { + throw new CryptographicException ("Invalid blob.", e); + } + } + + // PRIVATEKEYBLOB + // PUBLICKEYBLOB + static public RSA FromCapiKeyBlob (byte[] blob) + { + return FromCapiKeyBlob (blob, 0); + } + + static public RSA FromCapiKeyBlob (byte[] blob, int offset) + { + if (blob == null) + throw new ArgumentNullException ("blob"); + if (offset >= blob.Length) + throw new ArgumentException ("blob is too small."); + + switch (blob [offset]) { + case 0x00: + // this could be a public key inside an header + // like "sn -e" would produce + if (blob [offset + 12] == 0x06) { + return FromCapiPublicKeyBlob (blob, offset + 12); + } + break; + case 0x06: + return FromCapiPublicKeyBlob (blob, offset); + case 0x07: + return FromCapiPrivateKeyBlob (blob, offset); + } + throw new CryptographicException ("Unknown blob format."); + } + } +} + +#endif diff --git a/external/cecil-legacy/Mono.Security.Cryptography/CryptoService.cs b/external/cecil-legacy/Mono.Security.Cryptography/CryptoService.cs new file mode 100644 index 0000000000..58b6cfabc6 --- /dev/null +++ b/external/cecil-legacy/Mono.Security.Cryptography/CryptoService.cs @@ -0,0 +1,177 @@ +// +// CryptoService.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.IO; +using System.Reflection; +using System.Security.Cryptography; + +#if !READ_ONLY + +#if !SILVERLIGHT && !CF +using System.Runtime.Serialization; +using Mono.Security.Cryptography; +#endif + +using Mono.Cecil.PE; + +namespace Mono.Cecil { + + // Most of this code has been adapted + // from Jeroen Frijters' fantastic work + // in IKVM.Reflection.Emit. Thanks! + + static class CryptoService { + +#if !SILVERLIGHT && !CF + public static void StrongName (Stream stream, ImageWriter writer, StrongNameKeyPair key_pair) + { + int strong_name_pointer; + + var strong_name = CreateStrongName (key_pair, HashStream (stream, writer, out strong_name_pointer)); + PatchStrongName (stream, strong_name_pointer, strong_name); + } + + static void PatchStrongName (Stream stream, int strong_name_pointer, byte [] strong_name) + { + stream.Seek (strong_name_pointer, SeekOrigin.Begin); + stream.Write (strong_name, 0, strong_name.Length); + } + + static byte [] CreateStrongName (StrongNameKeyPair key_pair, byte [] hash) + { + const string hash_algo = "SHA1"; + + using (var rsa = key_pair.CreateRSA ()) { + var formatter = new RSAPKCS1SignatureFormatter (rsa); + formatter.SetHashAlgorithm (hash_algo); + + byte [] signature = formatter.CreateSignature (hash); + Array.Reverse (signature); + + return signature; + } + } + + static byte [] HashStream (Stream stream, ImageWriter writer, out int strong_name_pointer) + { + const int buffer_size = 8192; + + var text = writer.text; + var header_size = (int) writer.GetHeaderSize (); + var text_section_pointer = (int) text.PointerToRawData; + var strong_name_directory = writer.GetStrongNameSignatureDirectory (); + + if (strong_name_directory.Size == 0) + throw new InvalidOperationException (); + + strong_name_pointer = (int) (text_section_pointer + + (strong_name_directory.VirtualAddress - text.VirtualAddress)); + var strong_name_length = (int) strong_name_directory.Size; + + var sha1 = new SHA1Managed (); + var buffer = new byte [buffer_size]; + using (var crypto_stream = new CryptoStream (Stream.Null, sha1, CryptoStreamMode.Write)) { + + stream.Seek (0, SeekOrigin.Begin); + CopyStreamChunk (stream, crypto_stream, buffer, header_size); + + stream.Seek (text_section_pointer, SeekOrigin.Begin); + CopyStreamChunk (stream, crypto_stream, buffer, (int) strong_name_pointer - text_section_pointer); + + stream.Seek (strong_name_length, SeekOrigin.Current); + CopyStreamChunk (stream, crypto_stream, buffer, (int) (stream.Length - (strong_name_pointer + strong_name_length))); + } + + return sha1.Hash; + } +#endif + static void CopyStreamChunk (Stream stream, Stream dest_stream, byte [] buffer, int length) + { + while (length > 0) { + int read = stream.Read (buffer, 0, System.Math.Min (buffer.Length, length)); + dest_stream.Write (buffer, 0, read); + length -= read; + } + } + + public static byte [] ComputeHash (string file) + { + if (!File.Exists (file)) + return Empty.Array; + + const int buffer_size = 8192; + + var sha1 = new SHA1Managed (); + + using (var stream = new FileStream (file, FileMode.Open, FileAccess.Read, FileShare.Read)) { + + var buffer = new byte [buffer_size]; + + using (var crypto_stream = new CryptoStream (Stream.Null, sha1, CryptoStreamMode.Write)) + CopyStreamChunk (stream, crypto_stream, buffer, (int) stream.Length); + } + + return sha1.Hash; + } + } + +#if !SILVERLIGHT && !CF + static partial class Mixin { + + public static RSA CreateRSA (this StrongNameKeyPair key_pair) + { + byte [] key; + string key_container; + + if (!TryGetKeyContainer (key_pair, out key, out key_container)) + return CryptoConvert.FromCapiKeyBlob (key); + + var parameters = new CspParameters { + Flags = CspProviderFlags.UseMachineKeyStore, + KeyContainerName = key_container, + KeyNumber = 2, + }; + + return new RSACryptoServiceProvider (parameters); + } + + static bool TryGetKeyContainer (ISerializable key_pair, out byte [] key, out string key_container) + { + var info = new SerializationInfo (typeof (StrongNameKeyPair), new FormatterConverter ()); + key_pair.GetObjectData (info, new StreamingContext ()); + + key = (byte []) info.GetValue ("_keyPairArray", typeof (byte [])); + key_container = info.GetString ("_keyPairContainer"); + return key_container != null; + } + } +#endif +} + +#endif diff --git a/external/cecil/Mono/Actions.cs b/external/cecil-legacy/Mono/Actions.cs similarity index 100% rename from external/cecil/Mono/Actions.cs rename to external/cecil-legacy/Mono/Actions.cs diff --git a/external/cecil-legacy/Mono/Empty.cs b/external/cecil-legacy/Mono/Empty.cs new file mode 100644 index 0000000000..c9e5d7d614 --- /dev/null +++ b/external/cecil-legacy/Mono/Empty.cs @@ -0,0 +1,67 @@ +// +// Empty.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using Mono.Collections.Generic; + +namespace Mono { + + static class Empty { + + public static readonly T [] Array = new T [0]; + } +} + +namespace Mono.Cecil { + + static partial class Mixin { + + public static bool IsNullOrEmpty (this T [] self) + { + return self == null || self.Length == 0; + } + + public static bool IsNullOrEmpty (this Collection self) + { + return self == null || self.size == 0; + } + + public static T [] Resize (this T [] self, int length) + { +#if !CF + Array.Resize (ref self, length); +#else + var copy = new T [length]; + Array.Copy (self, copy, self.Length); + self = copy; +#endif + + return self; + } + } +} diff --git a/external/cecil/Mono/Funcs.cs b/external/cecil-legacy/Mono/Funcs.cs similarity index 100% rename from external/cecil/Mono/Funcs.cs rename to external/cecil-legacy/Mono/Funcs.cs diff --git a/external/cecil/NOTES.txt b/external/cecil-legacy/NOTES.txt similarity index 100% rename from external/cecil/NOTES.txt rename to external/cecil-legacy/NOTES.txt diff --git a/external/cecil/System.Runtime.CompilerServices/ExtensionAttribute.cs b/external/cecil-legacy/System.Runtime.CompilerServices/ExtensionAttribute.cs similarity index 100% rename from external/cecil/System.Runtime.CompilerServices/ExtensionAttribute.cs rename to external/cecil-legacy/System.Runtime.CompilerServices/ExtensionAttribute.cs diff --git a/external/cecil/Test/.gitignore b/external/cecil-legacy/Test/.gitignore similarity index 100% rename from external/cecil/Test/.gitignore rename to external/cecil-legacy/Test/.gitignore diff --git a/external/cecil-legacy/Test/Mono.Cecil.Tests.csproj b/external/cecil-legacy/Test/Mono.Cecil.Tests.csproj new file mode 100644 index 0000000000..eeebf78ce5 --- /dev/null +++ b/external/cecil-legacy/Test/Mono.Cecil.Tests.csproj @@ -0,0 +1,179 @@ + + + + net_4_0_Debug + AnyCPU + 9.0.30729 + 2.0 + {A47B1F49-A81A-43E8-BE6B-DD28AF2C4055} + Library + Properties + Mono.Cecil.Tests + Mono.Cecil.Tests + 512 + true + ..\mono.snk + + + true + full + false + bin\net_2_0_Debug\ + DEBUG;TRACE + prompt + 4 + v2.0 + + + pdbonly + true + bin\net_2_0_Release\ + TRACE + prompt + 4 + v2.0 + + + true + full + false + bin\net_3_5_Debug\ + DEBUG;TRACE;NET_3_5 + prompt + 4 + v3.5 + + + pdbonly + true + bin\net_3_5_Release\ + TRACE;NET_3_5 + prompt + 4 + v3.5 + + + true + full + false + bin\net_4_0_Debug\ + DEBUG;TRACE;NET_3_5;NET_4_0 + prompt + 4 + v4.0 + + + pdbonly + true + bin\net_4_0_Release\ + TRACE;NET_3_5;NET_4_0 + prompt + 4 + v4.0 + + + + + + + False + libs\nunit-2.6.2\nunit.core.dll + + + False + libs\nunit-2.6.2\nunit.core.interfaces.dll + + + False + libs\nunit-2.6.2\nunit.framework.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {D68133BD-1E63-496E-9EDE-4FBDBF77B486} + Mono.Cecil + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/external/cecil/Test/Mono.Cecil.Tests/Addin.cs b/external/cecil-legacy/Test/Mono.Cecil.Tests/Addin.cs similarity index 100% rename from external/cecil/Test/Mono.Cecil.Tests/Addin.cs rename to external/cecil-legacy/Test/Mono.Cecil.Tests/Addin.cs diff --git a/external/cecil-legacy/Test/Mono.Cecil.Tests/AssemblyInfo.cs b/external/cecil-legacy/Test/Mono.Cecil.Tests/AssemblyInfo.cs new file mode 100644 index 0000000000..ad7488f773 --- /dev/null +++ b/external/cecil-legacy/Test/Mono.Cecil.Tests/AssemblyInfo.cs @@ -0,0 +1,14 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle ("Mono.Cecil.Tests")] +[assembly: AssemblyProduct ("Mono.Cecil")] +[assembly: AssemblyCopyright ("Copyright © 2008 - 2011 Jb Evain")] + +[assembly: ComVisible (false)] + +[assembly: Guid ("da96c202-696a-457e-89af-5fa74e6bda0d")] + +[assembly: AssemblyVersion ("1.0.0.0")] +[assembly: AssemblyFileVersion ("1.0.0.0")] diff --git a/external/cecil-legacy/Test/Mono.Cecil.Tests/AssemblyTests.cs b/external/cecil-legacy/Test/Mono.Cecil.Tests/AssemblyTests.cs new file mode 100644 index 0000000000..3267f77a6a --- /dev/null +++ b/external/cecil-legacy/Test/Mono.Cecil.Tests/AssemblyTests.cs @@ -0,0 +1,35 @@ +using System; + +using Mono.Cecil; + +using NUnit.Framework; + +namespace Mono.Cecil.Tests { + + [TestFixture] + public class AssemblyTests : BaseTestFixture { + + [TestModule ("hello.exe")] + public void Name (ModuleDefinition module) + { + var name = module.Assembly.Name; + + Assert.IsNotNull (name); + + Assert.AreEqual ("hello", name.Name); + Assert.AreEqual (string.Empty, name.Culture); + Assert.AreEqual (new Version (0, 0, 0, 0), name.Version); + Assert.AreEqual (AssemblyHashAlgorithm.SHA1, name.HashAlgorithm); + } + + [Test] + public void ParseLowerCaseNameParts() + { + var name = AssemblyNameReference.Parse ("Foo, version=2.0.0.0, culture=fr-FR"); + Assert.AreEqual ("Foo", name.Name); + Assert.AreEqual (2, name.Version.Major); + Assert.AreEqual (0, name.Version.Minor); + Assert.AreEqual ("fr-FR", name.Culture); + } + } +} diff --git a/external/cecil-legacy/Test/Mono.Cecil.Tests/BaseTestFixture.cs b/external/cecil-legacy/Test/Mono.Cecil.Tests/BaseTestFixture.cs new file mode 100644 index 0000000000..e160f48afc --- /dev/null +++ b/external/cecil-legacy/Test/Mono.Cecil.Tests/BaseTestFixture.cs @@ -0,0 +1,76 @@ +using System; +using System.IO; +using System.Reflection; + +using NUnit.Framework; + +using Mono.Cecil.PE; + +namespace Mono.Cecil.Tests { + + public abstract class BaseTestFixture { + + public static string GetResourcePath (string name, Assembly assembly) + { + return Path.Combine (FindResourcesDirectory (assembly), name); + } + + public static string GetAssemblyResourcePath (string name, Assembly assembly) + { + return GetResourcePath (Path.Combine ("assemblies", name), assembly); + } + + public static string GetCSharpResourcePath (string name, Assembly assembly) + { + return GetResourcePath (Path.Combine ("cs", name), assembly); + } + + public static string GetILResourcePath (string name, Assembly assembly) + { + return GetResourcePath (Path.Combine ("il", name), assembly); + } + + public static ModuleDefinition GetResourceModule (string name) + { + return ModuleDefinition.ReadModule (GetAssemblyResourcePath (name, typeof (BaseTestFixture).Assembly)); + } + + public static ModuleDefinition GetResourceModule (string name, ReaderParameters parameters) + { + return ModuleDefinition.ReadModule (GetAssemblyResourcePath (name, typeof (BaseTestFixture).Assembly), parameters); + } + + public static ModuleDefinition GetResourceModule (string name, ReadingMode mode) + { + return ModuleDefinition.ReadModule (GetAssemblyResourcePath (name, typeof (BaseTestFixture).Assembly), new ReaderParameters (mode)); + } + + internal static Image GetResourceImage (string name) + { + using (var fs = new FileStream (GetAssemblyResourcePath (name, typeof (BaseTestFixture).Assembly), FileMode.Open, FileAccess.Read)) + return ImageReader.ReadImageFrom (fs); + } + + public static ModuleDefinition GetCurrentModule () + { + return ModuleDefinition.ReadModule (typeof (BaseTestFixture).Module.FullyQualifiedName); + } + + public static ModuleDefinition GetCurrentModule (ReaderParameters parameters) + { + return ModuleDefinition.ReadModule (typeof (BaseTestFixture).Module.FullyQualifiedName, parameters); + } + + public static string FindResourcesDirectory (Assembly assembly) + { + var path = Path.GetDirectoryName (new Uri (assembly.CodeBase).LocalPath); + while (!Directory.Exists (Path.Combine (path, "Resources"))) { + var old = path; + path = Path.GetDirectoryName (path); + Assert.AreNotEqual (old, path); + } + + return Path.Combine (path, "Resources"); + } + } +} diff --git a/external/cecil-legacy/Test/Mono.Cecil.Tests/CompilationService.cs b/external/cecil-legacy/Test/Mono.Cecil.Tests/CompilationService.cs new file mode 100644 index 0000000000..5a2def5cd1 --- /dev/null +++ b/external/cecil-legacy/Test/Mono.Cecil.Tests/CompilationService.cs @@ -0,0 +1,237 @@ +using System; +using System.CodeDom.Compiler; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Text; + +using NUnit.Framework; + +namespace Mono.Cecil.Tests { + + struct CompilationResult { + internal DateTime source_write_time; + internal string result_file; + + public CompilationResult (DateTime write_time, string result_file) + { + this.source_write_time = write_time; + this.result_file = result_file; + } + } + + abstract class CompilationService { + + Dictionary files = new Dictionary (); + + bool TryGetResult (string name, out string file_result) + { + file_result = null; + CompilationResult result; + if (!files.TryGetValue (name, out result)) + return false; + + if (result.source_write_time != File.GetLastWriteTime (name)) + return false; + + file_result = result.result_file; + return true; + } + + public string Compile (string name) + { + string result_file; + if (TryGetResult (name, out result_file)) + return result_file; + + result_file = CompileFile (name); + RegisterFile (name, result_file); + return result_file; + } + + void RegisterFile (string name, string result_file) + { + files [name] = new CompilationResult (File.GetLastWriteTime (name), result_file); + } + + protected abstract string CompileFile (string name); + + public static string CompileResource (string name) + { + var extension = Path.GetExtension (name); + if (extension == ".il") + return IlasmCompilationService.Instance.Compile (name); + + if (extension == ".cs" || extension == ".vb") + return CodeDomCompilationService.Instance.Compile (name); + + throw new NotSupportedException (extension); + } + + protected static string GetCompiledFilePath (string file_name) + { + var tmp_cecil = Path.Combine (Path.GetTempPath (), "cecil"); + if (!Directory.Exists (tmp_cecil)) + Directory.CreateDirectory (tmp_cecil); + + return Path.Combine (tmp_cecil, Path.GetFileName (file_name) + ".dll"); + } + + static bool OnMono { get { return typeof (object).Assembly.GetType ("Mono.Runtime") != null; } } + + public static void Verify (string name) + { + var output = OnMono ? ShellService.PEDump (name) : ShellService.PEVerify (name); + if (output.ExitCode != 0) + Assert.Fail (output.ToString ()); + } + } + + class IlasmCompilationService : CompilationService { + + public static readonly IlasmCompilationService Instance = new IlasmCompilationService (); + + protected override string CompileFile (string name) + { + string file = GetCompiledFilePath (name); + + var output = ShellService.ILAsm (name, file); + + AssertAssemblerResult (output); + + return file; + } + + static void AssertAssemblerResult (ShellService.ProcessOutput output) + { + if (output.ExitCode != 0) + Assert.Fail (output.ToString ()); + } + } + + class CodeDomCompilationService : CompilationService { + + public static readonly CodeDomCompilationService Instance = new CodeDomCompilationService (); + + protected override string CompileFile (string name) + { + string file = GetCompiledFilePath (name); + + using (var provider = GetProvider (name)) { + var parameters = GetDefaultParameters (name); + parameters.IncludeDebugInformation = false; + parameters.GenerateExecutable = false; + parameters.OutputAssembly = file; + + var results = provider.CompileAssemblyFromFile (parameters, name); + AssertCompilerResults (results); + } + + return file; + } + + static void AssertCompilerResults (CompilerResults results) + { + Assert.IsFalse (results.Errors.HasErrors, GetErrorMessage (results)); + } + + static string GetErrorMessage (CompilerResults results) + { + if (!results.Errors.HasErrors) + return string.Empty; + + var builder = new StringBuilder (); + foreach (CompilerError error in results.Errors) + builder.AppendLine (error.ToString ()); + return builder.ToString (); + } + + static CompilerParameters GetDefaultParameters (string name) + { + return GetCompilerInfo (name).CreateDefaultCompilerParameters (); + } + + static CodeDomProvider GetProvider (string name) + { + return GetCompilerInfo (name).CreateProvider (); + } + + static CompilerInfo GetCompilerInfo (string name) + { + return CodeDomProvider.GetCompilerInfo ( + CodeDomProvider.GetLanguageFromExtension (Path.GetExtension (name))); + } + } + + class ShellService { + + public class ProcessOutput { + + public int ExitCode; + public string StdOut; + public string StdErr; + + public ProcessOutput (int exitCode, string stdout, string stderr) + { + ExitCode = exitCode; + StdOut = stdout; + StdErr = stderr; + } + + public override string ToString () + { + return StdOut + StdErr; + } + } + + static ProcessOutput RunProcess (string target, params string [] arguments) + { + var stdout = new StringWriter (); + var stderr = new StringWriter (); + + var process = new Process { + StartInfo = new ProcessStartInfo { + FileName = target, + Arguments = string.Join (" ", arguments), + CreateNoWindow = true, + UseShellExecute = false, + RedirectStandardError = true, + RedirectStandardInput = true, + RedirectStandardOutput = true, + }, + }; + + process.Start (); + + process.OutputDataReceived += (_, args) => stdout.Write (args.Data); + process.ErrorDataReceived += (_, args) => stderr.Write (args.Data); + + process.BeginOutputReadLine (); + process.BeginErrorReadLine (); + + process.WaitForExit (); + + return new ProcessOutput (process.ExitCode, stdout.ToString (), stderr.ToString ()); + } + + public static ProcessOutput ILAsm (string source, string output) + { + return RunProcess ("ilasm", "/nologo", "/dll", "/out:" + Quote (output), Quote (source)); + } + + static string Quote (string file) + { + return "\"" + file + "\""; + } + + public static ProcessOutput PEVerify (string source) + { + return RunProcess ("peverify", "/nologo", Quote (source)); + } + + public static ProcessOutput PEDump (string source) + { + return RunProcess ("pedump", "--verify code,metadata", Quote (source)); + } + } +} diff --git a/external/cecil-legacy/Test/Mono.Cecil.Tests/CustomAttributesTests.cs b/external/cecil-legacy/Test/Mono.Cecil.Tests/CustomAttributesTests.cs new file mode 100644 index 0000000000..9682dadbfe --- /dev/null +++ b/external/cecil-legacy/Test/Mono.Cecil.Tests/CustomAttributesTests.cs @@ -0,0 +1,519 @@ +using System; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text; + +using Mono.Cecil; +using Mono.Cecil.Metadata; +using Mono.Cecil.PE; + +using NUnit.Framework; + +namespace Mono.Cecil.Tests { + + [TestFixture] + public class CustomAttributesTests : BaseTestFixture { + + [TestCSharp ("CustomAttributes.cs")] + public void StringArgumentOnType (ModuleDefinition module) + { + var hamster = module.GetType ("Hamster"); + + Assert.IsTrue (hamster.HasCustomAttributes); + Assert.AreEqual (1, hamster.CustomAttributes.Count); + + var attribute = hamster.CustomAttributes [0]; + Assert.AreEqual ("System.Void FooAttribute::.ctor(System.String)", + attribute.Constructor.FullName); + + Assert.IsTrue (attribute.HasConstructorArguments); + Assert.AreEqual (1, attribute.ConstructorArguments.Count); + + AssertArgument ("bar", attribute.ConstructorArguments [0]); + } + + [TestCSharp ("CustomAttributes.cs")] + public void NullString (ModuleDefinition module) + { + var dentist = module.GetType ("Dentist"); + + var attribute = GetAttribute (dentist, "Foo"); + Assert.IsNotNull (attribute); + + AssertArgument (null, attribute.ConstructorArguments [0]); + } + + [TestCSharp ("CustomAttributes.cs")] + public void Primitives1 (ModuleDefinition module) + { + var steven = module.GetType ("Steven"); + + var attribute = GetAttribute (steven, "Foo"); + Assert.IsNotNull (attribute); + + AssertArgument (-12, attribute.ConstructorArguments [0]); + AssertArgument (242, attribute.ConstructorArguments [1]); + AssertArgument (true, attribute.ConstructorArguments [2]); + AssertArgument (false, attribute.ConstructorArguments [3]); + AssertArgument (4242, attribute.ConstructorArguments [4]); + AssertArgument (-1983, attribute.ConstructorArguments [5]); + AssertArgument ('c', attribute.ConstructorArguments [6]); + } + + [TestCSharp ("CustomAttributes.cs")] + public void Primitives2 (ModuleDefinition module) + { + var seagull = module.GetType ("Seagull"); + + var attribute = GetAttribute (seagull, "Foo"); + Assert.IsNotNull (attribute); + + AssertArgument (-100000, attribute.ConstructorArguments [0]); + AssertArgument (200000, attribute.ConstructorArguments [1]); + AssertArgument (12.12f, attribute.ConstructorArguments [2]); + AssertArgument (long.MaxValue, attribute.ConstructorArguments [3]); + AssertArgument (ulong.MaxValue, attribute.ConstructorArguments [4]); + AssertArgument (64.646464, attribute.ConstructorArguments [5]); + } + + [TestCSharp ("CustomAttributes.cs")] + public void StringArgumentOnAssembly (ModuleDefinition module) + { + var assembly = module.Assembly; + + var attribute = GetAttribute (assembly, "Foo"); + Assert.IsNotNull (attribute); + + AssertArgument ("bingo", attribute.ConstructorArguments [0]); + } + + [TestCSharp ("CustomAttributes.cs")] + public void CharArray (ModuleDefinition module) + { + var rifle = module.GetType ("Rifle"); + + var attribute = GetAttribute (rifle, "Foo"); + Assert.IsNotNull (attribute); + + var argument = attribute.ConstructorArguments [0]; + + Assert.AreEqual ("System.Char[]", argument.Type.FullName); + + var array = argument.Value as CustomAttributeArgument []; + Assert.IsNotNull (array); + + var str = "cecil"; + + Assert.AreEqual (array.Length, str.Length); + + for (int i = 0; i < str.Length; i++) + AssertArgument (str [i], array [i]); + } + + [TestCSharp ("CustomAttributes.cs")] + public void BoxedArguments (ModuleDefinition module) + { + var worm = module.GetType ("Worm"); + + var attribute = GetAttribute (worm, "Foo"); + Assert.IsNotNull (attribute); + + Assert.AreEqual (".ctor ((Object:(String:\"2\")), (Object:(I4:2)))", PrettyPrint (attribute)); + } + + [TestCSharp ("CustomAttributes.cs")] + public void BoxedArraysArguments (ModuleDefinition module) + { + var sheep = module.GetType ("Sheep"); + + var attribute = GetAttribute (sheep, "Foo"); + Assert.IsNotNull (attribute); + + // [Foo (new object [] { "2", 2, 'c' }, new object [] { new object [] { 1, 2, 3}, null })] + AssertCustomAttribute (".ctor ((Object:(Object[]:{(Object:(String:\"2\")), (Object:(I4:2)), (Object:(Char:'c'))})), (Object:(Object[]:{(Object:(Object[]:{(Object:(I4:1)), (Object:(I4:2)), (Object:(I4:3))})), (Object:(String:null))})))", attribute); + } + + [TestCSharp ("CustomAttributes.cs")] + public void FieldsAndProperties (ModuleDefinition module) + { + var angola = module.GetType ("Angola"); + + var attribute = GetAttribute (angola, "Foo"); + Assert.IsNotNull (attribute); + + Assert.AreEqual (2, attribute.Fields.Count); + + var argument = attribute.Fields.Where (a => a.Name == "Pan").First (); + AssertCustomAttributeArgument ("(Object:(Object[]:{(Object:(I4:1)), (Object:(String:\"2\")), (Object:(Char:'3'))}))", argument); + + argument = attribute.Fields.Where (a => a.Name == "PanPan").First (); + AssertCustomAttributeArgument ("(String[]:{(String:\"yo\"), (String:\"yo\")})", argument); + + Assert.AreEqual (2, attribute.Properties.Count); + + argument = attribute.Properties.Where (a => a.Name == "Bang").First (); + AssertArgument (42, argument); + + argument = attribute.Properties.Where (a => a.Name == "Fiou").First (); + AssertArgument (null, argument); + } + + [TestCSharp ("CustomAttributes.cs")] + public void BoxedStringField (ModuleDefinition module) + { + var type = module.GetType ("BoxedStringField"); + + var attribute = GetAttribute (type, "Foo"); + Assert.IsNotNull (attribute); + + Assert.AreEqual (1, attribute.Fields.Count); + + var argument = attribute.Fields.Where (a => a.Name == "Pan").First (); + AssertCustomAttributeArgument ("(Object:(String:\"fiouuu\"))", argument); + } + + [TestCSharp ("CustomAttributes.cs")] + public void TypeDefinitionEnum (ModuleDefinition module) + { + var zero = module.GetType ("Zero"); + + var attribute = GetAttribute (zero, "Foo"); + Assert.IsNotNull (attribute); + + Assert.AreEqual (1, attribute.ConstructorArguments.Count); + + Assert.AreEqual ((short) 2, attribute.ConstructorArguments [0].Value); + Assert.AreEqual ("Bingo", attribute.ConstructorArguments [0].Type.FullName); + } + + [TestCSharp ("CustomAttributes.cs")] + public void TypeReferenceEnum (ModuleDefinition module) + { + var ace = module.GetType ("Ace"); + + var attribute = GetAttribute (ace, "Foo"); + Assert.IsNotNull (attribute); + + Assert.AreEqual (1, attribute.ConstructorArguments.Count); + + Assert.AreEqual ((byte) 0x04, attribute.ConstructorArguments [0].Value); + Assert.AreEqual ("System.Security.AccessControl.AceFlags", attribute.ConstructorArguments [0].Type.FullName); + Assert.AreEqual (module, attribute.ConstructorArguments [0].Type.Module); + } + + [TestCSharp ("CustomAttributes.cs")] + public void BoxedEnumReference (ModuleDefinition module) + { + var bzzz = module.GetType ("Bzzz"); + + var attribute = GetAttribute (bzzz, "Foo"); + Assert.IsNotNull (attribute); + + // [Foo (new object [] { Bingo.Fuel, Bingo.Binga }, null, Pan = System.Security.AccessControl.AceFlags.NoPropagateInherit)] + + Assert.AreEqual (2, attribute.ConstructorArguments.Count); + + var argument = attribute.ConstructorArguments [0]; + + AssertCustomAttributeArgument ("(Object:(Object[]:{(Object:(Bingo:2)), (Object:(Bingo:4))}))", argument); + + argument = attribute.ConstructorArguments [1]; + + AssertCustomAttributeArgument ("(Object:(String:null))", argument); + + argument = attribute.Fields.Where (a => a.Name == "Pan").First ().Argument; + + AssertCustomAttributeArgument ("(Object:(System.Security.AccessControl.AceFlags:4))", argument); + } + + [TestCSharp ("CustomAttributes.cs")] + public void TypeOfTypeDefinition (ModuleDefinition module) + { + var typed = module.GetType ("Typed"); + + var attribute = GetAttribute (typed, "Foo"); + Assert.IsNotNull (attribute); + + Assert.AreEqual (1, attribute.ConstructorArguments.Count); + + var argument = attribute.ConstructorArguments [0]; + + Assert.AreEqual ("System.Type", argument.Type.FullName); + + var type = argument.Value as TypeDefinition; + Assert.IsNotNull (type); + + Assert.AreEqual ("Bingo", type.FullName); + } + + [TestCSharp ("CustomAttributes.cs")] + public void TypeOfNestedTypeDefinition (ModuleDefinition module) + { + var typed = module.GetType ("NestedTyped"); + + var attribute = GetAttribute (typed, "Foo"); + Assert.IsNotNull (attribute); + + Assert.AreEqual (1, attribute.ConstructorArguments.Count); + + var argument = attribute.ConstructorArguments [0]; + + Assert.AreEqual ("System.Type", argument.Type.FullName); + + var type = argument.Value as TypeDefinition; + Assert.IsNotNull (type); + + Assert.AreEqual ("FooAttribute/Token", type.FullName); + } + + [TestCSharp ("CustomAttributes.cs")] + public void FieldTypeOf (ModuleDefinition module) + { + var truc = module.GetType ("Truc"); + + var attribute = GetAttribute (truc, "Foo"); + Assert.IsNotNull (attribute); + + var argument = attribute.Fields.Where (a => a.Name == "Chose").First ().Argument; + + Assert.AreEqual ("System.Type", argument.Type.FullName); + + var type = argument.Value as TypeDefinition; + Assert.IsNotNull (type); + + Assert.AreEqual ("Typed", type.FullName); + } + + [TestCSharp ("CustomAttributes.cs")] + public void FieldNullTypeOf (ModuleDefinition module) + { + var truc = module.GetType ("Machin"); + + var attribute = GetAttribute (truc, "Foo"); + Assert.IsNotNull (attribute); + + var argument = attribute.Fields.Where (a => a.Name == "Chose").First ().Argument; + + Assert.AreEqual ("System.Type", argument.Type.FullName); + + Assert.IsNull (argument.Value); + } + + [TestCSharp ("CustomAttributes.cs")] + public void OpenGenericTypeOf (ModuleDefinition module) + { + var open_generic = module.GetType ("OpenGeneric`2"); + Assert.IsNotNull (open_generic); + + var attribute = GetAttribute (open_generic, "Foo"); + Assert.IsNotNull (attribute); + + Assert.AreEqual (1, attribute.ConstructorArguments.Count); + + var argument = attribute.ConstructorArguments [0]; + + Assert.AreEqual ("System.Type", argument.Type.FullName); + + var type = argument.Value as TypeReference; + Assert.IsNotNull (type); + + Assert.AreEqual ("System.Collections.Generic.Dictionary`2", type.FullName); + } + + [TestCSharp ("CustomAttributes.cs")] + public void ClosedGenericTypeOf (ModuleDefinition module) + { + var closed_generic = module.GetType ("ClosedGeneric"); + Assert.IsNotNull (closed_generic); + + var attribute = GetAttribute (closed_generic, "Foo"); + Assert.IsNotNull (attribute); + + Assert.AreEqual (1, attribute.ConstructorArguments.Count); + + var argument = attribute.ConstructorArguments [0]; + + Assert.AreEqual ("System.Type", argument.Type.FullName); + + var type = argument.Value as TypeReference; + Assert.IsNotNull (type); + + Assert.AreEqual ("System.Collections.Generic.Dictionary`2[,]>", type.FullName); + } + + [TestIL ("types.il")] + public void EmptyBlob (ModuleDefinition module) + { + var attribute = module.GetType ("CustomAttribute"); + Assert.AreEqual (1, attribute.CustomAttributes.Count); + Assert.AreEqual (0, attribute.CustomAttributes [0].ConstructorArguments.Count); + } + + [Test] + public void DefineCustomAttributeFromBlob () + { + var file = Path.Combine (Path.GetTempPath (), "CaBlob.dll"); + + var module = ModuleDefinition.CreateModule ("CaBlob.dll", new ModuleParameters { Kind = ModuleKind.Dll, Runtime = TargetRuntime.Net_2_0 }); + var assembly_title_ctor = module.Import (typeof (System.Reflection.AssemblyTitleAttribute).GetConstructor (new [] {typeof (string)})); + + Assert.IsNotNull (assembly_title_ctor); + + var buffer = new ByteBuffer (); + buffer.WriteUInt16 (1); // ca signature + + var title = Encoding.UTF8.GetBytes ("CaBlob"); + + buffer.WriteCompressedUInt32 ((uint) title.Length); + buffer.WriteBytes (title); + + buffer.WriteUInt16 (0); // named arguments + + var blob = new byte [buffer.length]; + Buffer.BlockCopy (buffer.buffer, 0, blob, 0, buffer.length); + + var attribute = new CustomAttribute (assembly_title_ctor, blob); + module.Assembly.CustomAttributes.Add (attribute); + + module.Write (file); + + module = ModuleDefinition.ReadModule (file); + + attribute = GetAttribute (module.Assembly, "AssemblyTitle"); + + Assert.IsNotNull (attribute); + Assert.AreEqual ("CaBlob", (string) attribute.ConstructorArguments [0].Value); + } + + static void AssertCustomAttribute (string expected, CustomAttribute attribute) + { + Assert.AreEqual (expected, PrettyPrint (attribute)); + } + + static void AssertCustomAttributeArgument (string expected, CustomAttributeNamedArgument named_argument) + { + AssertCustomAttributeArgument (expected, named_argument.Argument); + } + + static void AssertCustomAttributeArgument (string expected, CustomAttributeArgument argument) + { + var result = new StringBuilder (); + PrettyPrint (argument, result); + + Assert.AreEqual (expected, result.ToString ()); + } + + static string PrettyPrint (CustomAttribute attribute) + { + var signature = new StringBuilder (); + signature.Append (".ctor ("); + + for (int i = 0; i < attribute.ConstructorArguments.Count; i++) { + if (i > 0) + signature.Append (", "); + + PrettyPrint (attribute.ConstructorArguments [i], signature); + } + + signature.Append (")"); + return signature.ToString (); + } + + static void PrettyPrint (CustomAttributeArgument argument, StringBuilder signature) + { + var value = argument.Value; + + signature.Append ("("); + + PrettyPrint (argument.Type, signature); + + signature.Append (":"); + + PrettyPrintValue (argument.Value, signature); + + signature.Append (")"); + } + + static void PrettyPrintValue (object value, StringBuilder signature) + { + if (value == null) { + signature.Append ("null"); + return; + } + + var arguments = value as CustomAttributeArgument []; + if (arguments != null) { + signature.Append ("{"); + for (int i = 0; i < arguments.Length; i++) { + if (i > 0) + signature.Append (", "); + + PrettyPrint (arguments [i], signature); + } + signature.Append ("}"); + + return; + } + + switch (Type.GetTypeCode (value.GetType ())) { + case TypeCode.String: + signature.AppendFormat ("\"{0}\"", value); + break; + case TypeCode.Char: + signature.AppendFormat ("'{0}'", (char) value); + break; + default: + var formattable = value as IFormattable; + if (formattable != null) { + signature.Append (formattable.ToString (null, CultureInfo.InvariantCulture)); + return; + } + + if (value is CustomAttributeArgument) { + PrettyPrint ((CustomAttributeArgument) value, signature); + return; + } + break; + } + } + + static void PrettyPrint (TypeReference type, StringBuilder signature) + { + if (type.IsArray) { + ArrayType array = (ArrayType) type; + signature.AppendFormat ("{0}[]", array.ElementType.etype.ToString ()); + } else if (type.etype == ElementType.None) { + signature.Append (type.FullName); + } else + signature.Append (type.etype.ToString ()); + } + + static void AssertArgument (T value, CustomAttributeNamedArgument named_argument) + { + AssertArgument (value, named_argument.Argument); + } + + static void AssertArgument (T value, CustomAttributeArgument argument) + { + AssertArgument (typeof (T).FullName, (object) value, argument); + } + + static void AssertArgument (string type, object value, CustomAttributeArgument argument) + { + Assert.AreEqual (type, argument.Type.FullName); + Assert.AreEqual (value, argument.Value); + } + + static CustomAttribute GetAttribute (ICustomAttributeProvider owner, string type) + { + Assert.IsTrue (owner.HasCustomAttributes); + + foreach (var attribute in owner.CustomAttributes) + if (attribute.Constructor.DeclaringType.Name.StartsWith (type)) + return attribute; + + return null; + } + } +} diff --git a/external/cecil-legacy/Test/Mono.Cecil.Tests/EventTests.cs b/external/cecil-legacy/Test/Mono.Cecil.Tests/EventTests.cs new file mode 100644 index 0000000000..15a599c58b --- /dev/null +++ b/external/cecil-legacy/Test/Mono.Cecil.Tests/EventTests.cs @@ -0,0 +1,66 @@ +using System; + +using Mono.Cecil; +using Mono.Cecil.Metadata; + +using NUnit.Framework; + +namespace Mono.Cecil.Tests { + + [TestFixture] + public class EventTests : BaseTestFixture { + + [TestCSharp ("Events.cs")] + public void AbstractMethod (ModuleDefinition module) + { + var type = module.GetType ("Foo"); + + Assert.IsTrue (type.HasEvents); + + var events = type.Events; + + Assert.AreEqual (1, events.Count); + + var @event = events [0]; + + Assert.IsNotNull (@event); + Assert.AreEqual ("Bar", @event.Name); + Assert.IsNotNull (@event.EventType); + Assert.AreEqual ("Pan", @event.EventType.FullName); + + Assert.IsNotNull (@event.AddMethod); + Assert.AreEqual (MethodSemanticsAttributes.AddOn, @event.AddMethod.SemanticsAttributes); + Assert.IsNotNull (@event.RemoveMethod); + Assert.AreEqual (MethodSemanticsAttributes.RemoveOn, @event.RemoveMethod.SemanticsAttributes); + } + + [TestIL ("others.il")] + public void OtherMethod (ModuleDefinition module) + { + var type = module.GetType ("Others"); + + Assert.IsTrue (type.HasEvents); + + var events = type.Events; + + Assert.AreEqual (1, events.Count); + + var @event = events [0]; + + Assert.IsNotNull (@event); + Assert.AreEqual ("Handler", @event.Name); + Assert.IsNotNull (@event.EventType); + Assert.AreEqual ("System.EventHandler", @event.EventType.FullName); + + Assert.IsTrue (@event.HasOtherMethods); + + Assert.AreEqual (2, @event.OtherMethods.Count); + + var other = @event.OtherMethods [0]; + Assert.AreEqual ("dang_Handler", other.Name); + + other = @event.OtherMethods [1]; + Assert.AreEqual ("fang_Handler", other.Name); + } + } +} diff --git a/external/cecil-legacy/Test/Mono.Cecil.Tests/Extensions.cs b/external/cecil-legacy/Test/Mono.Cecil.Tests/Extensions.cs new file mode 100644 index 0000000000..0788d21bc5 --- /dev/null +++ b/external/cecil-legacy/Test/Mono.Cecil.Tests/Extensions.cs @@ -0,0 +1,92 @@ +using System; +using System.Linq; +using SR = System.Reflection; + +using Mono.Cecil; + +namespace Mono.Cecil.Tests { + + public static class Extensions { + + public static MethodDefinition GetMethod (this TypeDefinition self, string name) + { + return self.Methods.Where (m => m.Name == name).First (); + } + + public static FieldDefinition GetField (this TypeDefinition self, string name) + { + return self.Fields.Where (f => f.Name == name).First (); + } + + public static TypeDefinition ToDefinition (this Type self) + { + var module = ModuleDefinition.ReadModule (self.Module.FullyQualifiedName); + return (TypeDefinition) module.LookupToken (self.MetadataToken); + } + + public static MethodDefinition ToDefinition (this SR.MethodBase method) + { + var declaring_type = method.DeclaringType.ToDefinition (); + return (MethodDefinition) declaring_type.Module.LookupToken (method.MetadataToken); + } + + public static FieldDefinition ToDefinition (this SR.FieldInfo field) + { + var declaring_type = field.DeclaringType.ToDefinition (); + return (FieldDefinition) declaring_type.Module.LookupToken (field.MetadataToken); + } + + public static TypeReference MakeGenericType (this TypeReference self, params TypeReference [] arguments) + { + if (self.GenericParameters.Count != arguments.Length) + throw new ArgumentException (); + + var instance = new GenericInstanceType (self); + foreach (var argument in arguments) + instance.GenericArguments.Add (argument); + + return instance; + } + + public static MethodReference MakeGenericMethod (this MethodReference self, params TypeReference [] arguments) + { + if (self.GenericParameters.Count != arguments.Length) + throw new ArgumentException (); + + var instance = new GenericInstanceMethod (self); + foreach (var argument in arguments) + instance.GenericArguments.Add (argument); + + return instance; + } + + public static MethodReference MakeGeneric (this MethodReference self, params TypeReference [] arguments) + { + var reference = new MethodReference { + Name = self.Name, + DeclaringType = self.DeclaringType.MakeGenericType (arguments), + HasThis = self.HasThis, + ExplicitThis = self.ExplicitThis, + ReturnType = self.ReturnType, + CallingConvention = self.CallingConvention, + }; + + foreach (var parameter in self.Parameters) + reference.Parameters.Add (new ParameterDefinition (parameter.ParameterType)); + + foreach (var generic_parameter in self.GenericParameters) + reference.GenericParameters.Add (new GenericParameter (generic_parameter.Name, reference)); + + return reference; + } + + public static FieldReference MakeGeneric (this FieldReference self, params TypeReference [] arguments) + { + return new FieldReference { + Name = self.Name, + DeclaringType = self.DeclaringType.MakeGenericType (arguments), + FieldType = self.FieldType, + }; + } + } +} diff --git a/external/cecil-legacy/Test/Mono.Cecil.Tests/FieldTests.cs b/external/cecil-legacy/Test/Mono.Cecil.Tests/FieldTests.cs new file mode 100644 index 0000000000..8c63456886 --- /dev/null +++ b/external/cecil-legacy/Test/Mono.Cecil.Tests/FieldTests.cs @@ -0,0 +1,333 @@ +using System; + +using Mono.Cecil; +using Mono.Cecil.Metadata; +using Mono.Cecil.PE; + +using NUnit.Framework; + +namespace Mono.Cecil.Tests { + + [TestFixture] + public class FieldTests : BaseTestFixture { + + [TestCSharp ("Fields.cs")] + public void TypeDefField (ModuleDefinition module) + { + var type = module.Types [1]; + Assert.AreEqual ("Foo", type.Name); + Assert.AreEqual (1, type.Fields.Count); + + var field = type.Fields [0]; + Assert.AreEqual ("bar", field.Name); + Assert.AreEqual (1, field.MetadataToken.RID); + Assert.IsNotNull (field.FieldType); + Assert.AreEqual ("Bar", field.FieldType.FullName); + Assert.AreEqual (TokenType.Field, field.MetadataToken.TokenType); + Assert.IsFalse (field.HasConstant); + Assert.IsNull (field.Constant); + } + + [TestCSharp ("Fields.cs")] + public void PrimitiveTypes (ModuleDefinition module) + { + var type = module.GetType ("Baz"); + + AssertField (type, "char", typeof (char)); + AssertField (type, "bool", typeof (bool)); + AssertField (type, "sbyte", typeof (sbyte)); + AssertField (type, "byte", typeof (byte)); + AssertField (type, "int16", typeof (short)); + AssertField (type, "uint16", typeof (ushort)); + AssertField (type, "int32", typeof (int)); + AssertField (type, "uint32", typeof (uint)); + AssertField (type, "int64", typeof (long)); + AssertField (type, "uint64", typeof (ulong)); + AssertField (type, "single", typeof (float)); + AssertField (type, "double", typeof (double)); + AssertField (type, "string", typeof (string)); + AssertField (type, "object", typeof (object)); + } + + [TestCSharp ("Fields.cs")] + public void VolatileField (ModuleDefinition module) + { + var type = module.GetType ("Bar"); + + Assert.IsTrue (type.HasFields); + Assert.AreEqual (1, type.Fields.Count); + + var field = type.Fields [0]; + + Assert.AreEqual ("oiseau", field.Name); + Assert.AreEqual ("System.Int32 modreq(System.Runtime.CompilerServices.IsVolatile)", field.FieldType.FullName); + + Assert.IsFalse (field.HasConstant); + } + + [TestCSharp ("Layouts.cs")] + public void FieldLayout (ModuleDefinition module) + { + var foo = module.GetType ("Foo"); + Assert.IsNotNull (foo); + + Assert.IsTrue (foo.HasFields); + + var fields = foo.Fields; + + var field = fields [0]; + + Assert.AreEqual ("Bar", field.Name); + Assert.IsTrue (field.HasLayoutInfo); + Assert.AreEqual (0, field.Offset); + + field = fields [1]; + + Assert.AreEqual ("Baz", field.Name); + Assert.IsTrue (field.HasLayoutInfo); + Assert.AreEqual (2, field.Offset); + + field = fields [2]; + + Assert.AreEqual ("Gazonk", field.Name); + Assert.IsTrue (field.HasLayoutInfo); + Assert.AreEqual (4, field.Offset); + } + + [TestCSharp ("Layouts.cs")] + public void FieldRVA (ModuleDefinition module) + { + var priv_impl = GetPrivateImplementationType (module); + Assert.IsNotNull (priv_impl); + + Assert.AreEqual (1, priv_impl.Fields.Count); + + var field = priv_impl.Fields [0]; + + Assert.IsNotNull (field); + Assert.AreNotEqual (0, field.RVA); + Assert.IsNotNull (field.InitialValue); + Assert.AreEqual (16, field.InitialValue.Length); + + var buffer = new ByteBuffer (field.InitialValue); + + Assert.AreEqual (1, buffer.ReadUInt32 ()); + Assert.AreEqual (2, buffer.ReadUInt32 ()); + Assert.AreEqual (3, buffer.ReadUInt32 ()); + Assert.AreEqual (4, buffer.ReadUInt32 ()); + } + + [TestCSharp ("Generics.cs")] + public void GenericFieldDefinition (ModuleDefinition module) + { + var bar = module.GetType ("Bar`1"); + Assert.IsNotNull (bar); + + Assert.IsTrue (bar.HasGenericParameters); + var t = bar.GenericParameters [0]; + + Assert.AreEqual ("T", t.Name); + Assert.AreEqual (t.Owner, bar); + + var bang = bar.GetField ("bang"); + + Assert.IsNotNull (bang); + + Assert.AreEqual (t, bang.FieldType); + } + + [TestIL ("types.il")] + public void ArrayFields (ModuleDefinition module) + { + var types = module.GetType ("Types"); + Assert.IsNotNull (types); + + var rank_two = types.GetField ("rank_two"); + + var array = rank_two.FieldType as ArrayType; + Assert.IsNotNull (array); + + Assert.AreEqual (2, array.Rank); + Assert.IsFalse (array.Dimensions [0].IsSized); + Assert.IsFalse (array.Dimensions [1].IsSized); + + var rank_two_low_bound_zero = types.GetField ("rank_two_low_bound_zero"); + + array = rank_two_low_bound_zero.FieldType as ArrayType; + Assert.IsNotNull (array); + + Assert.AreEqual (2, array.Rank); + Assert.IsTrue (array.Dimensions [0].IsSized); + Assert.AreEqual (0, array.Dimensions [0].LowerBound); + Assert.AreEqual (null, array.Dimensions [0].UpperBound); + Assert.IsTrue (array.Dimensions [1].IsSized); + Assert.AreEqual (0, array.Dimensions [1].LowerBound); + Assert.AreEqual (null, array.Dimensions [1].UpperBound); + + var rank_one_low_bound_m1 = types.GetField ("rank_one_low_bound_m1"); + array = rank_one_low_bound_m1.FieldType as ArrayType; + Assert.IsNotNull (array); + + Assert.AreEqual (1, array.Rank); + Assert.IsTrue (array.Dimensions [0].IsSized); + Assert.AreEqual (-1, array.Dimensions [0].LowerBound); + Assert.AreEqual (4, array.Dimensions [0].UpperBound); + } + + [TestCSharp ("Fields.cs")] + public void EnumFieldsConstant (ModuleDefinition module) + { + var pim = module.GetType ("Pim"); + Assert.IsNotNull (pim); + + var field = pim.GetField ("Pam"); + Assert.IsTrue (field.HasConstant); + Assert.AreEqual (1, (int) field.Constant); + + field = pim.GetField ("Poum"); + Assert.AreEqual (2, (int) field.Constant); + } + + [TestCSharp ("Fields.cs")] + public void StringAndClassConstant (ModuleDefinition module) + { + var panpan = module.GetType ("PanPan"); + Assert.IsNotNull (panpan); + + var field = panpan.GetField ("Peter"); + Assert.IsTrue (field.HasConstant); + Assert.IsNull (field.Constant); + + field = panpan.GetField ("QQ"); + Assert.AreEqual ("qq", (string) field.Constant); + + field = panpan.GetField ("nil"); + Assert.AreEqual (null, (string) field.Constant); + } + + [TestCSharp ("Fields.cs")] + public void ObjectConstant (ModuleDefinition module) + { + var panpan = module.GetType ("PanPan"); + Assert.IsNotNull (panpan); + + var field = panpan.GetField ("obj"); + Assert.IsTrue (field.HasConstant); + Assert.IsNull (field.Constant); + } + + [TestIL ("types.il")] + public void NullPrimitiveConstant (ModuleDefinition module) + { + var fields = module.GetType ("Fields"); + + var field = fields.GetField ("int32_nullref"); + Assert.IsTrue (field.HasConstant); + Assert.AreEqual (null, field.Constant); + } + + [TestCSharp ("Fields.cs")] + public void ArrayConstant (ModuleDefinition module) + { + var panpan = module.GetType ("PanPan"); + Assert.IsNotNull (panpan); + + var field = panpan.GetField ("ints"); + Assert.IsTrue (field.HasConstant); + Assert.IsNull (field.Constant); + } + + [TestIL ("types.il")] + public void ConstantCoalescing (ModuleDefinition module) + { + var fields = module.GetType ("Fields"); + + var field = fields.GetField ("int32_int16"); + Assert.AreEqual ("System.Int32", field.FieldType.FullName); + Assert.IsTrue (field.HasConstant); + Assert.IsInstanceOf (typeof (short), field.Constant); + Assert.AreEqual ((short) 1, field.Constant); + + field = fields.GetField ("int16_int32"); + Assert.AreEqual ("System.Int16", field.FieldType.FullName); + Assert.IsTrue (field.HasConstant); + Assert.IsInstanceOf (typeof (int), field.Constant); + Assert.AreEqual (1, field.Constant); + + field = fields.GetField ("char_int16"); + Assert.AreEqual ("System.Char", field.FieldType.FullName); + Assert.IsTrue (field.HasConstant); + Assert.IsInstanceOf (typeof (short), field.Constant); + Assert.AreEqual ((short) 1, field.Constant); + + field = fields.GetField ("int16_char"); + Assert.AreEqual ("System.Int16", field.FieldType.FullName); + Assert.IsTrue (field.HasConstant); + Assert.IsInstanceOf (typeof (char), field.Constant); + Assert.AreEqual ('s', field.Constant); + } + + [TestCSharp ("Generics.cs")] + public void NestedEnumOfGenericTypeDefinition (ModuleDefinition module) + { + var dang = module.GetType ("Bongo`1/Dang"); + Assert.IsNotNull (dang); + + var field = dang.GetField ("Ding"); + Assert.IsNotNull (field); + Assert.AreEqual (2, field.Constant); + + field = dang.GetField ("Dong"); + Assert.IsNotNull (field); + Assert.AreEqual (12, field.Constant); + } + + [TestModule ("marshal.dll")] + public void MarshalAsFixedStr (ModuleDefinition module) + { + var boc = module.GetType ("Boc"); + var field = boc.GetField ("a"); + + Assert.IsNotNull (field); + + Assert.IsTrue (field.HasMarshalInfo); + + var info = (FixedSysStringMarshalInfo) field.MarshalInfo; + + Assert.AreEqual (42, info.Size); + } + + [TestModule ("marshal.dll")] + public void MarshalAsFixedArray (ModuleDefinition module) + { + var boc = module.GetType ("Boc"); + var field = boc.GetField ("b"); + + Assert.IsNotNull (field); + + Assert.IsTrue (field.HasMarshalInfo); + + var info = (FixedArrayMarshalInfo) field.MarshalInfo; + + Assert.AreEqual (12, info.Size); + Assert.AreEqual (NativeType.Boolean, info.ElementType); + } + + static TypeDefinition GetPrivateImplementationType (ModuleDefinition module) + { + foreach (var type in module.Types) + if (type.FullName.Contains ("")) + return type; + + return null; + } + + static void AssertField (TypeDefinition type, string name, Type expected) + { + var field = type.GetField (name); + Assert.IsNotNull (field, name); + + Assert.AreEqual (expected.FullName, field.FieldType.FullName); + } + } +} diff --git a/external/cecil-legacy/Test/Mono.Cecil.Tests/Formatter.cs b/external/cecil-legacy/Test/Mono.Cecil.Tests/Formatter.cs new file mode 100644 index 0000000000..a7e1c8704a --- /dev/null +++ b/external/cecil-legacy/Test/Mono.Cecil.Tests/Formatter.cs @@ -0,0 +1,179 @@ +using System; +using System.IO; +using Mono.Cecil; +using Mono.Cecil.Cil; + +namespace Mono.Cecil.Tests { + + public static class Formatter { + + public static string FormatInstruction (Instruction instruction) + { + var writer = new StringWriter (); + WriteInstruction (writer, instruction); + return writer.ToString (); + } + + public static string FormatMethodBody (MethodDefinition method) + { + var writer = new StringWriter (); + WriteMethodBody (writer, method); + return writer.ToString (); + } + + public static void WriteMethodBody (TextWriter writer, MethodDefinition method) + { + var body = method.Body; + + WriteVariables (writer, body); + + foreach (Instruction instruction in body.Instructions) { + var sequence_point = instruction.SequencePoint; + if (sequence_point != null) { + writer.Write ('\t'); + WriteSequencePoint (writer, sequence_point); + writer.WriteLine (); + } + + writer.Write ('\t'); + WriteInstruction (writer, instruction); + writer.WriteLine (); + } + + WriteExceptionHandlers (writer, body); + } + + static void WriteVariables (TextWriter writer, MethodBody body) + { + var variables = body.Variables; + + writer.Write ('\t'); + writer.Write (".locals {0}(", body.InitLocals ? "init " : string.Empty); + + for (int i = 0; i < variables.Count; i++) { + if (i > 0) + writer.Write (", "); + + var variable = variables [i]; + + writer.Write ("{0} {1}", variable.VariableType, variable); + } + writer.WriteLine (")"); + } + + static void WriteInstruction (TextWriter writer, Instruction instruction) + { + writer.Write (FormatLabel (instruction.Offset)); + writer.Write (": "); + writer.Write (instruction.OpCode.Name); + if (null != instruction.Operand) { + writer.Write (' '); + WriteOperand (writer, instruction.Operand); + } + } + + static void WriteSequencePoint (TextWriter writer, SequencePoint sequence_point) + { + writer.Write (".line {0},{1}:{2},{3} '{4}'", + sequence_point.StartLine, + sequence_point.EndLine, + sequence_point.StartColumn, + sequence_point.EndColumn, + sequence_point.Document.Url); + } + + static string FormatLabel (int offset) + { + string label = "000" + offset.ToString ("x"); + return "IL_" + label.Substring (label.Length - 4); + } + + static string FormatLabel (Instruction instruction) + { + return FormatLabel (instruction.Offset); + } + + static void WriteOperand (TextWriter writer, object operand) + { + if (null == operand) throw new ArgumentNullException ("operand"); + + var target = operand as Instruction; + if (null != target) { + writer.Write (FormatLabel (target.Offset)); + return; + } + + var targets = operand as Instruction []; + if (null != targets) { + WriteLabelList (writer, targets); + return; + } + + string s = operand as string; + if (null != s) { + writer.Write ("\"" + s + "\""); + return; + } + + var parameter = operand as ParameterDefinition; + if (parameter != null) { + writer.Write (ToInvariantCultureString (parameter.Sequence)); + return; + } + + s = ToInvariantCultureString (operand); + writer.Write (s); + } + + static void WriteLabelList (TextWriter writer, Instruction [] instructions) + { + writer.Write ("("); + + for (int i = 0; i < instructions.Length; i++) { + if (i != 0) writer.Write (", "); + writer.Write (FormatLabel (instructions [i].Offset)); + } + + writer.Write (")"); + } + + static void WriteExceptionHandlers (TextWriter writer, MethodBody body) + { + if (!body.HasExceptionHandlers) + return; + + foreach (var handler in body.ExceptionHandlers) { + writer.Write ("\t"); + writer.WriteLine (".try {0} to {1} {2} handler {3} to {4}", + FormatLabel (handler.TryStart), + FormatLabel (handler.TryEnd), + FormatHandlerType (handler), + FormatLabel (handler.HandlerStart), + FormatLabel (handler.HandlerEnd)); + } + } + + static string FormatHandlerType (ExceptionHandler handler) + { + var handler_type = handler.HandlerType; + var type = handler_type.ToString ().ToLowerInvariant (); + + switch (handler_type) { + case ExceptionHandlerType.Catch: + return string.Format ("{0} {1}", type, handler.CatchType.FullName); + case ExceptionHandlerType.Filter: + throw new NotImplementedException (); + default: + return type; + } + } + + public static string ToInvariantCultureString (object value) + { + var convertible = value as IConvertible; + return (null != convertible) + ? convertible.ToString (System.Globalization.CultureInfo.InvariantCulture) + : value.ToString (); + } + } +} diff --git a/external/cecil-legacy/Test/Mono.Cecil.Tests/ILProcessorTests.cs b/external/cecil-legacy/Test/Mono.Cecil.Tests/ILProcessorTests.cs new file mode 100644 index 0000000000..3d9d1751b2 --- /dev/null +++ b/external/cecil-legacy/Test/Mono.Cecil.Tests/ILProcessorTests.cs @@ -0,0 +1,79 @@ +using System; +using System.Linq; + +using Mono.Cecil; +using Mono.Cecil.Cil; + +using NUnit.Framework; + +namespace Mono.Cecil.Tests { + + [TestFixture] + public class ILProcessorTests : BaseTestFixture { + + [Test] + public void Append () + { + var method = CreateTestMethod (); + var il = method.GetILProcessor (); + + var ret = il.Create (OpCodes.Ret); + il.Append (ret); + + AssertOpCodeSequence (new [] { OpCodes.Ret }, method); + } + + [Test] + public void InsertBefore () + { + var method = CreateTestMethod (OpCodes.Ldloc_0, OpCodes.Ldloc_2, OpCodes.Ldloc_3); + var il = method.GetILProcessor (); + + var ldloc_2 = method.Instructions.Where (i => i.OpCode == OpCodes.Ldloc_2).First (); + + il.InsertBefore ( + ldloc_2, + il.Create (OpCodes.Ldloc_1)); + + AssertOpCodeSequence (new [] { OpCodes.Ldloc_0, OpCodes.Ldloc_1, OpCodes.Ldloc_2, OpCodes.Ldloc_3 }, method); + } + + [Test] + public void InsertAfter () + { + var method = CreateTestMethod (OpCodes.Ldloc_0, OpCodes.Ldloc_2, OpCodes.Ldloc_3); + var il = method.GetILProcessor (); + + var ldloc_0 = method.Instructions.First (); + + il.InsertAfter ( + ldloc_0, + il.Create (OpCodes.Ldloc_1)); + + AssertOpCodeSequence (new [] { OpCodes.Ldloc_0, OpCodes.Ldloc_1, OpCodes.Ldloc_2, OpCodes.Ldloc_3 }, method); + } + + static void AssertOpCodeSequence (OpCode [] expected, MethodBody body) + { + var opcodes = body.Instructions.Select (i => i.OpCode).ToArray (); + Assert.AreEqual (expected.Length, opcodes.Length); + + for (int i = 0; i < opcodes.Length; i++) + Assert.AreEqual (expected [i], opcodes [i]); + } + + static MethodBody CreateTestMethod (params OpCode [] opcodes) + { + var method = new MethodDefinition { + Name = "function", + }; + + var il = method.Body.GetILProcessor (); + + foreach (var opcode in opcodes) + il.Emit (opcode); + + return method.Body; + } + } +} diff --git a/external/cecil-legacy/Test/Mono.Cecil.Tests/ImageReadTests.cs b/external/cecil-legacy/Test/Mono.Cecil.Tests/ImageReadTests.cs new file mode 100644 index 0000000000..8f68e5fc8f --- /dev/null +++ b/external/cecil-legacy/Test/Mono.Cecil.Tests/ImageReadTests.cs @@ -0,0 +1,144 @@ +using System; +using System.IO; + +using Mono.Cecil; +using Mono.Cecil.PE; +using Mono.Cecil.Metadata; + +using NUnit.Framework; + +namespace Mono.Cecil.Tests { + + [TestFixture] + public class ImageReadTests : BaseTestFixture { + + [Test] + public void ImageSections () + { + var image = GetResourceImage ("hello.exe"); + + Assert.AreEqual (3, image.Sections.Length); + Assert.AreEqual (".text", image.Sections [0].Name); + Assert.AreEqual (".rsrc", image.Sections [1].Name); + Assert.AreEqual (".reloc", image.Sections [2].Name); + } + + [Test] + public void ImageMetadataVersion () + { + var image = GetResourceImage ("hello.exe"); + Assert.AreEqual (TargetRuntime.Net_2_0, image.Runtime); + + image = GetResourceImage ("hello1.exe"); + Assert.AreEqual (TargetRuntime.Net_1_1, image.Runtime); + } + + [Test] + public void ImageModuleKind () + { + var image = GetResourceImage ("hello.exe"); + Assert.AreEqual (ModuleKind.Console, image.Kind); + + image = GetResourceImage ("libhello.dll"); + Assert.AreEqual (ModuleKind.Dll, image.Kind); + + image = GetResourceImage ("hellow.exe"); + Assert.AreEqual (ModuleKind.Windows, image.Kind); + } + + [Test] + public void MetadataHeaps () + { + var image = GetResourceImage ("hello.exe"); + + Assert.IsNotNull (image.TableHeap); + + Assert.IsNotNull (image.StringHeap); + Assert.AreEqual (string.Empty, image.StringHeap.Read (0)); + Assert.AreEqual ("", image.StringHeap.Read (1)); + + Assert.IsNotNull (image.UserStringHeap); + Assert.AreEqual (string.Empty, image.UserStringHeap.Read (0)); + Assert.AreEqual ("Hello Cecil World !", image.UserStringHeap.Read (1)); + + Assert.IsNotNull (image.GuidHeap); + Assert.AreEqual (new Guid (), image.GuidHeap.Read (0)); + Assert.AreEqual (new Guid ("C3BC2BD3-2576-4D00-A80E-465B5632415F"), image.GuidHeap.Read (1)); + + Assert.IsNotNull (image.BlobHeap); + Assert.AreEqual (new byte [0], image.BlobHeap.Read (0)); + } + + [Test] + public void TablesHeap () + { + var image = GetResourceImage ("hello.exe"); + var heap = image.TableHeap; + + Assert.IsNotNull (heap); + + Assert.AreEqual (1, heap [Table.Module].Length); + Assert.AreEqual (4, heap [Table.TypeRef].Length); + Assert.AreEqual (2, heap [Table.TypeDef].Length); + Assert.AreEqual (0, heap [Table.Field].Length); + Assert.AreEqual (2, heap [Table.Method].Length); + Assert.AreEqual (4, heap [Table.MemberRef].Length); + Assert.AreEqual (2, heap [Table.CustomAttribute].Length); + Assert.AreEqual (1, heap [Table.Assembly].Length); + Assert.AreEqual (1, heap [Table.AssemblyRef].Length); + } + + [TestModule ("hello.x64.exe")] + public void X64Module (ModuleDefinition module) + { + Assert.AreEqual (TargetArchitecture.AMD64, module.Image.Architecture); + Assert.AreEqual (ModuleAttributes.ILOnly, module.Image.Attributes); + } + + [TestModule ("hello.ia64.exe")] + public void IA64Module (ModuleDefinition module) + { + Assert.AreEqual (TargetArchitecture.IA64, module.Image.Architecture); + Assert.AreEqual (ModuleAttributes.ILOnly, module.Image.Attributes); + } + + [TestModule ("hello.x86.exe")] + public void X86Module (ModuleDefinition module) + { + Assert.AreEqual (TargetArchitecture.I386, module.Image.Architecture); + Assert.AreEqual (ModuleAttributes.ILOnly | ModuleAttributes.Required32Bit, module.Image.Attributes); + } + + [TestModule ("hello.anycpu.exe")] + public void AnyCpuModule (ModuleDefinition module) + { + Assert.AreEqual (TargetArchitecture.I386, module.Image.Architecture); + Assert.AreEqual (ModuleAttributes.ILOnly, module.Image.Attributes); + } + + [TestModule ("delay-signed.dll")] + public void DelaySignedAssembly (ModuleDefinition module) + { + Assert.IsNotNull (module.Assembly.Name.PublicKey); + Assert.AreNotEqual (0, module.Assembly.Name.PublicKey.Length); + Assert.AreNotEqual (ModuleAttributes.StrongNameSigned, module.Attributes & ModuleAttributes.StrongNameSigned); + Assert.AreNotEqual (0, module.Image.StrongName.VirtualAddress); + Assert.AreNotEqual (0, module.Image.StrongName.Size); + } + + [TestModule ("wp7.dll", Verify = false)] + public void WindowsPhoneNonSignedAssembly (ModuleDefinition module) + { + Assert.AreEqual (0, module.Assembly.Name.PublicKey.Length); + Assert.AreNotEqual (ModuleAttributes.StrongNameSigned, module.Attributes & ModuleAttributes.StrongNameSigned); + Assert.AreEqual (0, module.Image.StrongName.VirtualAddress); + Assert.AreEqual (0, module.Image.StrongName.Size); + } + + [TestModule ("metro.exe", Verify = false)] + public void MetroAssembly (ModuleDefinition module) + { + Assert.AreEqual (ModuleCharacteristics.AppContainer, module.Characteristics & ModuleCharacteristics.AppContainer); + } + } +} diff --git a/external/cecil-legacy/Test/Mono.Cecil.Tests/ImportCecilTests.cs b/external/cecil-legacy/Test/Mono.Cecil.Tests/ImportCecilTests.cs new file mode 100644 index 0000000000..ae9a8551b9 --- /dev/null +++ b/external/cecil-legacy/Test/Mono.Cecil.Tests/ImportCecilTests.cs @@ -0,0 +1,374 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using SR = System.Reflection; +using System.Runtime.CompilerServices; + +using Mono.Cecil.Cil; + +using NUnit.Framework; + +namespace Mono.Cecil.Tests { + + [TestFixture] + public class ImportCecilTests : BaseTestFixture { + + [Test] + public void ImportStringByRef () + { + var get_string = Compile> ((module, body) => { + var type = module.Types [1]; + + var method_by_ref = new MethodDefinition { + Name = "ModifyString", + IsPrivate = true, + IsStatic = true, + }; + + type.Methods.Add (method_by_ref); + + method_by_ref.MethodReturnType.ReturnType = module.Import (typeof (void).ToDefinition ()); + + method_by_ref.Parameters.Add (new ParameterDefinition (module.Import (typeof (string).ToDefinition ()))); + method_by_ref.Parameters.Add (new ParameterDefinition (module.Import (new ByReferenceType (typeof (string).ToDefinition ())))); + + var m_il = method_by_ref.Body.GetILProcessor (); + m_il.Emit (OpCodes.Ldarg_1); + m_il.Emit (OpCodes.Ldarg_0); + m_il.Emit (OpCodes.Stind_Ref); + m_il.Emit (OpCodes.Ret); + + var v_0 = new VariableDefinition (module.Import (typeof (string).ToDefinition ())); + body.Variables.Add (v_0); + + var il = body.GetILProcessor (); + il.Emit (OpCodes.Ldnull); + il.Emit (OpCodes.Stloc, v_0); + il.Emit (OpCodes.Ldarg_0); + il.Emit (OpCodes.Ldloca, v_0); + il.Emit (OpCodes.Call, method_by_ref); + il.Emit (OpCodes.Ldloc_0); + il.Emit (OpCodes.Ret); + }); + + Assert.AreEqual ("foo", get_string ("foo")); + } + + [Test] + public void ImportStringArray () + { + var identity = Compile> ((module, body) => { + var il = body.GetILProcessor (); + il.Emit (OpCodes.Ldarg_0); + il.Emit (OpCodes.Ret); + }); + + var array = new string [2, 2]; + + Assert.AreEqual (array, identity (array)); + } + + [Test] + public void ImportFieldStringEmpty () + { + var get_empty = Compile> ((module, body) => { + var il = body.GetILProcessor (); + il.Emit (OpCodes.Ldsfld, module.Import (typeof (string).GetField ("Empty").ToDefinition ())); + il.Emit (OpCodes.Ret); + }); + + Assert.AreEqual ("", get_empty ()); + } + + [Test] + public void ImportStringConcat () + { + var concat = Compile> ((module, body) => { + var il = body.GetILProcessor (); + il.Emit (OpCodes.Ldarg_0); + il.Emit (OpCodes.Ldarg_1); + il.Emit (OpCodes.Call, module.Import (typeof (string).GetMethod ("Concat", new [] { typeof (string), typeof (string) }).ToDefinition ())); + il.Emit (OpCodes.Ret); + }); + + Assert.AreEqual ("FooBar", concat ("Foo", "Bar")); + } + + public class Generic { + public T Field; + + public T Method (T t) + { + return t; + } + + public TS GenericMethod (T t, TS s) + { + return s; + } + + public Generic ComplexGenericMethod (T t, TS s) + { + return new Generic { Field = s }; + } + } + + [Test] + public void ImportGenericField () + { + var get_field = Compile, string>> ((module, body) => { + var generic_def = module.Import (typeof (Generic<>)).Resolve (); + var field_def = generic_def.Fields.Where (f => f.Name == "Field").First (); + + var field_string = field_def.MakeGeneric (module.Import (typeof (string))); + + var field_ref = module.Import (field_string); + + var il = body.GetILProcessor (); + il.Emit (OpCodes.Ldarg_0); + il.Emit (OpCodes.Ldfld, field_ref); + il.Emit (OpCodes.Ret); + }); + + var generic = new Generic { + Field = "foo", + }; + + Assert.AreEqual ("foo", get_field (generic)); + } + + [Test] + public void ImportGenericMethod () + { + var generic_identity = Compile, int, int>> ((module, body) => { + var generic_def = module.Import (typeof (Generic<>)).Resolve (); + var method_def = generic_def.Methods.Where (m => m.Name == "Method").First (); + + var method_int = method_def.MakeGeneric (module.Import (typeof (int))); + var method_ref = module.Import (method_int); + + var il = body.GetILProcessor (); + il.Emit (OpCodes.Ldarg_0); + il.Emit (OpCodes.Ldarg_1); + il.Emit (OpCodes.Callvirt, method_ref); + il.Emit (OpCodes.Ret); + }); + + Assert.AreEqual (42, generic_identity (new Generic (), 42)); + } + + [Test] + public void ImportGenericMethodSpec () + { + var gen_spec_id = Compile, int, int>> ((module, body) => { + var generic_def = module.Import (typeof (Generic<>)).Resolve (); + var method_def = generic_def.Methods.Where (m => m.Name == "GenericMethod").First (); + + var method_string = method_def.MakeGeneric (module.Import (typeof (string))); + + var method_instance = method_string.MakeGenericMethod (module.Import (typeof (int))); + + var method_ref = module.Import (method_instance); + + var il = body.GetILProcessor (); + il.Emit (OpCodes.Ldarg_0); + il.Emit (OpCodes.Ldnull); + il.Emit (OpCodes.Ldarg_1); + il.Emit (OpCodes.Callvirt, method_ref); + il.Emit (OpCodes.Ret); + }); + + Assert.AreEqual (42, gen_spec_id (new Generic (), 42)); + } + + [Test] + public void ImportComplexGenericMethodSpec () + { + var gen_spec_id = Compile, int, int>> ((module, body) => { + var generic_def = module.Import (typeof (Generic<>)).Resolve (); + var method_def = generic_def.Methods.Where (m => m.Name == "ComplexGenericMethod").First (); + + var method_string = method_def.MakeGeneric (module.Import (typeof (string))); + var method_instance = method_string.MakeGenericMethod (module.Import (typeof (int))); + var method_ref = module.Import (method_instance); + + var field_def = generic_def.Fields.Where (f => f.Name == "Field").First (); + var field_int = field_def.MakeGeneric (module.Import (typeof (int))); + var field_ref = module.Import (field_int); + + var il = body.GetILProcessor (); + il.Emit (OpCodes.Ldarg_0); + il.Emit (OpCodes.Ldnull); + il.Emit (OpCodes.Ldarg_1); + il.Emit (OpCodes.Callvirt, method_ref); + il.Emit (OpCodes.Ldfld, field_ref); + il.Emit (OpCodes.Ret); + }); + + Assert.AreEqual (42, gen_spec_id (new Generic (), 42)); + } + + [Test] + public void ImportMethodOnOpenGeneric () + { + var generic = typeof (Generic<>).ToDefinition (); + var module = ModuleDefinition.CreateModule ("foo", ModuleKind.Dll); + + var method = module.Import (generic.GetMethod ("Method")); + + Assert.AreEqual ("T Mono.Cecil.Tests.ImportCecilTests/Generic`1::Method(T)", method.FullName); + } + + public class ContextGeneric1Method2 + { + public G1 GenericMethod (R1 r, S1 s) + { + return default (G1); + } + } + + public class ContextGeneric2Method1 + { + public R2 GenericMethod (G2 g, H2 h) + { + return default (R2); + } + } + + public class NestedGenericsA + { + public class NestedGenericsB + { + public class NestedGenericsC + { + public A GenericMethod (B b, C c) + { + return default (A); + } + } + } + } + + [Test] + public void ContextGenericTest () + { + var module = ModuleDefinition.ReadModule (typeof (ContextGeneric1Method2<>).Module.FullyQualifiedName); + // by mixing open generics with 2 & 1 parameters, we make sure the right context is used (because otherwise, an exception will be thrown) + var type = typeof (ContextGeneric1Method2<>).MakeGenericType (typeof (ContextGeneric2Method1<,>)); + var meth = type.GetMethod ("GenericMethod"); + var imported_type = module.Import (type); + var method = module.Import (meth, imported_type); + Assert.AreEqual ("G1 Mono.Cecil.Tests.ImportCecilTests/ContextGeneric1Method2`1>::GenericMethod(R1,S1)", method.FullName); + + // and the other way around + type = typeof (ContextGeneric2Method1<,>).MakeGenericType (typeof (ContextGeneric1Method2<>), typeof (IList<>)); + meth = type.GetMethod ("GenericMethod"); + imported_type = module.Import (type); + method = module.Import (meth, imported_type); + Assert.AreEqual ("R2 Mono.Cecil.Tests.ImportCecilTests/ContextGeneric2Method1`2,System.Collections.Generic.IList`1>::GenericMethod(G2,H2)", method.FullName); + + // not sure about this one + type = typeof (NestedGenericsA.NestedGenericsB.NestedGenericsC); + meth = type.GetMethod ("GenericMethod"); + imported_type = module.Import (type); + method = module.Import (meth, imported_type); + Assert.AreEqual ("A Mono.Cecil.Tests.ImportCecilTests/NestedGenericsA`1/NestedGenericsB`1/NestedGenericsC`1::GenericMethod(B,C)", method.FullName); + + // We need both the method & type ! + type = typeof (Generic<>).MakeGenericType (typeof (string)); + meth = type.GetMethod ("ComplexGenericMethod"); + imported_type = module.Import (type); + method = module.Import (meth, imported_type); + Assert.AreEqual ("Mono.Cecil.Tests.ImportCecilTests/Generic`1 Mono.Cecil.Tests.ImportCecilTests/Generic`1::ComplexGenericMethod(T,TS)", method.FullName); + } + + delegate void Emitter (ModuleDefinition module, MethodBody body); + + [MethodImpl (MethodImplOptions.NoInlining)] + static TDelegate Compile (Emitter emitter) + where TDelegate : class + { + var name = GetTestCaseName (); + + var module = CreateTestModule (name, emitter); + var assembly = LoadTestModule (module); + + return CreateRunDelegate (GetTestCase (name, assembly)); + } + + static TDelegate CreateRunDelegate (Type type) + where TDelegate : class + { + return (TDelegate) (object) Delegate.CreateDelegate (typeof (TDelegate), type.GetMethod ("Run")); + } + + static Type GetTestCase (string name, SR.Assembly assembly) + { + return assembly.GetType (name); + } + + static SR.Assembly LoadTestModule (ModuleDefinition module) + { + using (var stream = new MemoryStream ()) { + module.Write (stream); + File.WriteAllBytes (Path.Combine (Path.Combine (Path.GetTempPath (), "cecil"), module.Name + ".dll"), stream.ToArray ()); + return SR.Assembly.Load (stream.ToArray ()); + } + } + + static ModuleDefinition CreateTestModule (string name, Emitter emitter) + { + var module = CreateModule (name); + + var type = new TypeDefinition ( + "", + name, + TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.Abstract, + module.Import (typeof (object))); + + module.Types.Add (type); + + var method = CreateMethod (type, typeof (TDelegate).GetMethod ("Invoke")); + + emitter (module, method.Body); + + return module; + } + + static MethodDefinition CreateMethod (TypeDefinition type, SR.MethodInfo pattern) + { + var module = type.Module; + + var method = new MethodDefinition { + Name = "Run", + IsPublic = true, + IsStatic = true, + }; + + type.Methods.Add (method); + + method.MethodReturnType.ReturnType = module.Import (pattern.ReturnType); + + foreach (var parameter_pattern in pattern.GetParameters ()) + method.Parameters.Add (new ParameterDefinition (module.Import (parameter_pattern.ParameterType))); + + return method; + } + + static ModuleDefinition CreateModule (string name) + { + return ModuleDefinition.CreateModule (name, ModuleKind.Dll); + } + + [MethodImpl (MethodImplOptions.NoInlining)] + static string GetTestCaseName () + { + var stack_trace = new StackTrace (); + var stack_frame = stack_trace.GetFrame (2); + + return "ImportCecil_" + stack_frame.GetMethod ().Name; + } + } +} diff --git a/external/cecil-legacy/Test/Mono.Cecil.Tests/ImportReflectionTests.cs b/external/cecil-legacy/Test/Mono.Cecil.Tests/ImportReflectionTests.cs new file mode 100644 index 0000000000..6ded91c92d --- /dev/null +++ b/external/cecil-legacy/Test/Mono.Cecil.Tests/ImportReflectionTests.cs @@ -0,0 +1,409 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using SR = System.Reflection; +using System.Runtime.CompilerServices; + +using Mono.Cecil.Cil; + +using NUnit.Framework; + +namespace Mono.Cecil.Tests { + + [TestFixture] + public class ImportReflectionTests : BaseTestFixture { + + [Test] + public void ImportString () + { + var get_string = Compile> ((_, body) => { + var il = body.GetILProcessor (); + il.Emit (OpCodes.Ldstr, "yo dawg!"); + il.Emit (OpCodes.Ret); + }); + + Assert.AreEqual ("yo dawg!", get_string ()); + } + + [Test] + public void ImportInt () + { + var add = Compile> ((_, body) => { + var il = body.GetILProcessor (); + il.Emit (OpCodes.Ldarg_0); + il.Emit (OpCodes.Ldarg_1); + il.Emit (OpCodes.Add); + il.Emit (OpCodes.Ret); + }); + + Assert.AreEqual (42, add (40, 2)); + } + + [Test] + public void ImportStringByRef () + { + var get_string = Compile> ((module, body) => { + var type = module.Types [1]; + + var method_by_ref = new MethodDefinition { + Name = "ModifyString", + IsPrivate = true, + IsStatic = true, + }; + + type.Methods.Add (method_by_ref); + + method_by_ref.MethodReturnType.ReturnType = module.Import (typeof (void)); + + method_by_ref.Parameters.Add (new ParameterDefinition (module.Import (typeof (string)))); + method_by_ref.Parameters.Add (new ParameterDefinition (module.Import (typeof (string).MakeByRefType ()))); + + var m_il = method_by_ref.Body.GetILProcessor (); + m_il.Emit (OpCodes.Ldarg_1); + m_il.Emit (OpCodes.Ldarg_0); + m_il.Emit (OpCodes.Stind_Ref); + m_il.Emit (OpCodes.Ret); + + var v_0 = new VariableDefinition (module.Import (typeof (string))); + body.Variables.Add (v_0); + + var il = body.GetILProcessor (); + il.Emit (OpCodes.Ldnull); + il.Emit (OpCodes.Stloc, v_0); + il.Emit (OpCodes.Ldarg_0); + il.Emit (OpCodes.Ldloca, v_0); + il.Emit (OpCodes.Call, method_by_ref); + il.Emit (OpCodes.Ldloc_0); + il.Emit (OpCodes.Ret); + }); + + Assert.AreEqual ("foo", get_string ("foo")); + } + + [Test] + public void ImportStringArray () + { + var identity = Compile> ((module, body) => { + var il = body.GetILProcessor (); + il.Emit (OpCodes.Ldarg_0); + il.Emit (OpCodes.Ret); + }); + + var array = new string [2, 2]; + + Assert.AreEqual (array, identity (array)); + } + + [Test] + public void ImportFieldStringEmpty () + { + var get_empty = Compile> ((module, body) => { + var il = body.GetILProcessor (); + il.Emit (OpCodes.Ldsfld, module.Import (typeof (string).GetField ("Empty"))); + il.Emit (OpCodes.Ret); + }); + + Assert.AreEqual ("", get_empty ()); + } + + [Test] + public void ImportStringConcat () + { + var concat = Compile> ((module, body) => { + var il = body.GetILProcessor (); + il.Emit (OpCodes.Ldarg_0); + il.Emit (OpCodes.Ldarg_1); + il.Emit (OpCodes.Call, module.Import (typeof (string).GetMethod ("Concat", new [] { typeof (string), typeof (string) }))); + il.Emit (OpCodes.Ret); + }); + + Assert.AreEqual ("FooBar", concat ("Foo", "Bar")); + } + + public class Generic { + public T Field; + + public T Method (T t) + { + return t; + } + + public TS GenericMethod (T t, TS s) + { + return s; + } + + public Generic ComplexGenericMethod (T t, TS s) + { + return new Generic { Field = s }; + } + } + + [Test] + public void ImportGenericField () + { + var get_field = Compile, string>> ((module, body) => { + var il = body.GetILProcessor (); + il.Emit (OpCodes.Ldarg_0); + il.Emit (OpCodes.Ldfld, module.Import (typeof (Generic).GetField ("Field"))); + il.Emit (OpCodes.Ret); + }); + + var generic = new Generic { + Field = "foo", + }; + + Assert.AreEqual ("foo", get_field (generic)); + } + + [Test] + public void ImportGenericMethod () + { + var generic_identity = Compile, int, int>> ((module, body) => { + var il = body.GetILProcessor (); + il.Emit (OpCodes.Ldarg_0); + il.Emit (OpCodes.Ldarg_1); + il.Emit (OpCodes.Callvirt, module.Import (typeof (Generic).GetMethod ("Method"))); + il.Emit (OpCodes.Ret); + }); + + Assert.AreEqual (42, generic_identity (new Generic (), 42)); + } + + [Test] + public void ImportGenericMethodSpec () + { + var gen_spec_id = Compile, int, int>> ((module, body) => { + var il = body.GetILProcessor (); + il.Emit (OpCodes.Ldarg_0); + il.Emit (OpCodes.Ldnull); + il.Emit (OpCodes.Ldarg_1); + il.Emit (OpCodes.Callvirt, module.Import (typeof (Generic).GetMethod ("GenericMethod").MakeGenericMethod (typeof (int)))); + il.Emit (OpCodes.Ret); + }); + + Assert.AreEqual (42, gen_spec_id (new Generic (), 42)); + } + + [Test] + public void ImportComplexGenericMethodSpec () + { + var gen_spec_id = Compile, int, int>> ((module, body) => { + var il = body.GetILProcessor (); + il.Emit (OpCodes.Ldarg_0); + il.Emit (OpCodes.Ldnull); + il.Emit (OpCodes.Ldarg_1); + il.Emit (OpCodes.Callvirt, module.Import (typeof (Generic).GetMethod ("ComplexGenericMethod").MakeGenericMethod (typeof (int)))); + il.Emit (OpCodes.Ldfld, module.Import (typeof (Generic).GetField ("Field"))); + il.Emit (OpCodes.Ret); + }); + + Assert.AreEqual (42, gen_spec_id (new Generic (), 42)); + } + + public class Foo { + public List list; + } + + [Test] + public void ImportGenericTypeDefOrOpen () + { + var module = typeof (Foo<>).ToDefinition ().Module; + + var foo_def = module.Import (typeof (Foo<>)); + var foo_open = module.Import (typeof (Foo<>), foo_def); + + Assert.AreEqual ("Mono.Cecil.Tests.ImportReflectionTests/Foo`1", foo_def.FullName); + Assert.AreEqual ("Mono.Cecil.Tests.ImportReflectionTests/Foo`1", foo_open.FullName); + } + + [Test] + public void ImportGenericTypeFromContext () + { + var list_foo = typeof (Foo<>).GetField ("list").FieldType; + var generic_list_foo_open = typeof (Generic<>).MakeGenericType (list_foo); + + var foo_def = typeof (Foo<>).ToDefinition (); + var module = foo_def.Module; + + var generic_foo = module.Import (generic_list_foo_open, foo_def); + + Assert.AreEqual ("Mono.Cecil.Tests.ImportReflectionTests/Generic`1>", + generic_foo.FullName); + } + + [Test] + public void ImportGenericTypeDefFromContext () + { + var foo_open = typeof (Foo<>).MakeGenericType (typeof (Foo<>).GetGenericArguments () [0]); + var generic_foo_open = typeof (Generic<>).MakeGenericType (foo_open); + + var foo_def = typeof (Foo<>).ToDefinition (); + var module = foo_def.Module; + + var generic_foo = module.Import (generic_foo_open, foo_def); + + Assert.AreEqual ("Mono.Cecil.Tests.ImportReflectionTests/Generic`1>", + generic_foo.FullName); + } + + [Test] + public void ImportArrayTypeDefFromContext () + { + var foo_open = typeof (Foo<>).MakeGenericType (typeof (Foo<>).GetGenericArguments () [0]); + var foo_open_array = foo_open.MakeArrayType (); + + var foo_def = typeof (Foo<>).ToDefinition (); + var module = foo_def.Module; + + var array_foo = module.Import (foo_open_array, foo_def); + + Assert.AreEqual ("Mono.Cecil.Tests.ImportReflectionTests/Foo`1[]", + array_foo.FullName); + } + + [Test] + public void ImportGenericFieldFromContext () + { + var list_foo = typeof (Foo<>).GetField ("list").FieldType; + var generic_list_foo_open = typeof (Generic<>).MakeGenericType (list_foo); + var generic_list_foo_open_field = generic_list_foo_open.GetField ("Field"); + + var foo_def = typeof (Foo<>).ToDefinition (); + var module = foo_def.Module; + + var generic_field = module.Import (generic_list_foo_open_field, foo_def); + + Assert.AreEqual ("T Mono.Cecil.Tests.ImportReflectionTests/Generic`1>::Field", + generic_field.FullName); + } + + [Test] + public void ImportGenericMethodFromContext () + { + var list_foo = typeof (Foo<>).GetField ("list").FieldType; + var generic_list_foo_open = typeof (Generic<>).MakeGenericType (list_foo); + var generic_list_foo_open_method = generic_list_foo_open.GetMethod ("Method"); + + var foo_def = typeof (Foo<>).ToDefinition (); + var module = foo_def.Module; + + var generic_method = module.Import (generic_list_foo_open_method, foo_def); + + Assert.AreEqual ("T Mono.Cecil.Tests.ImportReflectionTests/Generic`1>::Method(T)", + generic_method.FullName); + } + + [Test] + public void ImportMethodOnOpenGenericType () + { + var module = typeof (Generic<>).ToDefinition ().Module; + + var method = module.Import (typeof (Generic<>).GetMethod ("Method")); + + Assert.AreEqual ("T Mono.Cecil.Tests.ImportReflectionTests/Generic`1::Method(T)", method.FullName); + } + + [Test] + public void ImportGenericMethodOnOpenGenericType () + { + var module = typeof (Generic<>).ToDefinition ().Module; + + var generic_method = module.Import (typeof (Generic<>).GetMethod ("GenericMethod")); + + Assert.AreEqual ("TS Mono.Cecil.Tests.ImportReflectionTests/Generic`1::GenericMethod(T,TS)", generic_method.FullName); + + generic_method = module.Import (typeof (Generic<>).GetMethod ("GenericMethod"), generic_method); + + Assert.AreEqual ("TS Mono.Cecil.Tests.ImportReflectionTests/Generic`1::GenericMethod(T,TS)", generic_method.FullName); + } + + delegate void Emitter (ModuleDefinition module, MethodBody body); + + [MethodImpl (MethodImplOptions.NoInlining)] + static TDelegate Compile (Emitter emitter) + where TDelegate : class + { + var name = GetTestCaseName (); + + var module = CreateTestModule (name, emitter); + var assembly = LoadTestModule (module); + + return CreateRunDelegate (GetTestCase (name, assembly)); + } + + static TDelegate CreateRunDelegate (Type type) + where TDelegate : class + { + return (TDelegate) (object) Delegate.CreateDelegate (typeof (TDelegate), type.GetMethod ("Run")); + } + + static Type GetTestCase (string name, SR.Assembly assembly) + { + return assembly.GetType (name); + } + + static SR.Assembly LoadTestModule (ModuleDefinition module) + { + using (var stream = new MemoryStream ()) { + module.Write (stream); + File.WriteAllBytes (Path.Combine (Path.Combine (Path.GetTempPath (), "cecil"), module.Name + ".dll"), stream.ToArray ()); + return SR.Assembly.Load (stream.ToArray ()); + } + } + + static ModuleDefinition CreateTestModule (string name, Emitter emitter) + { + var module = CreateModule (name); + + var type = new TypeDefinition ( + "", + name, + TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.Abstract, + module.Import (typeof (object))); + + module.Types.Add (type); + + var method = CreateMethod (type, typeof (TDelegate).GetMethod ("Invoke")); + + emitter (module, method.Body); + + return module; + } + + static MethodDefinition CreateMethod (TypeDefinition type, SR.MethodInfo pattern) + { + var module = type.Module; + + var method = new MethodDefinition { + Name = "Run", + IsPublic = true, + IsStatic = true, + }; + + type.Methods.Add (method); + + method.MethodReturnType.ReturnType = module.Import (pattern.ReturnType); + + foreach (var parameter_pattern in pattern.GetParameters ()) + method.Parameters.Add (new ParameterDefinition (module.Import (parameter_pattern.ParameterType))); + + return method; + } + + static ModuleDefinition CreateModule (string name) + { + return ModuleDefinition.CreateModule (name, ModuleKind.Dll); + } + + [MethodImpl (MethodImplOptions.NoInlining)] + static string GetTestCaseName () + { + var stack_trace = new StackTrace (); + var stack_frame = stack_trace.GetFrame (2); + + return "ImportReflection_" + stack_frame.GetMethod ().Name; + } + } +} diff --git a/external/cecil/Test/Mono.Cecil.Tests/Linq.cs b/external/cecil-legacy/Test/Mono.Cecil.Tests/Linq.cs similarity index 100% rename from external/cecil/Test/Mono.Cecil.Tests/Linq.cs rename to external/cecil-legacy/Test/Mono.Cecil.Tests/Linq.cs diff --git a/external/cecil-legacy/Test/Mono.Cecil.Tests/MethodBodyTests.cs b/external/cecil-legacy/Test/Mono.Cecil.Tests/MethodBodyTests.cs new file mode 100644 index 0000000000..5258305a91 --- /dev/null +++ b/external/cecil-legacy/Test/Mono.Cecil.Tests/MethodBodyTests.cs @@ -0,0 +1,412 @@ +using System; +using System.Linq; + +using Mono.Cecil; +using Mono.Cecil.Cil; + +using NUnit.Framework; + +namespace Mono.Cecil.Tests { + + [TestFixture] + public class MethodBodyTests : BaseTestFixture { + + [TestIL ("hello.il")] + public void MultiplyMethod (ModuleDefinition module) + { + var foo = module.GetType ("Foo"); + Assert.IsNotNull (foo); + + var bar = foo.GetMethod ("Bar"); + Assert.IsNotNull (bar); + Assert.IsTrue (bar.IsIL); + + AssertCode (@" + .locals init (System.Int32 V_0) + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: mul + IL_0003: stloc.0 + IL_0004: ldloc.0 + IL_0005: call System.Void Foo::Baz(System.Int32) + IL_000a: ret +", bar); + } + + [TestIL ("hello.il")] + public void PrintStringEmpty (ModuleDefinition module) + { + var foo = module.GetType ("Foo"); + Assert.IsNotNull (foo); + + var print_empty = foo.GetMethod ("PrintEmpty"); + Assert.IsNotNull (print_empty); + + AssertCode (@" + .locals () + IL_0000: ldsfld System.String System.String::Empty + IL_0005: call System.Void System.Console::WriteLine(System.String) + IL_000a: ret +", print_empty); + } + + [TestModule ("libhello.dll")] + public void Branch (ModuleDefinition module) + { + var lib = module.GetType ("Library"); + Assert.IsNotNull (lib); + + var method = lib.GetMethod ("GetHelloString"); + Assert.IsNotNull (method); + + AssertCode (@" + .locals init (System.String V_0) + IL_0000: nop + IL_0001: ldstr ""hello world of tomorrow"" + IL_0006: stloc.0 + IL_0007: br.s IL_0009 + IL_0009: ldloc.0 + IL_000a: ret +", method); + } + + [TestModule ("switch.exe")] + public void Switch (ModuleDefinition module) + { + var program = module.GetType ("Program"); + Assert.IsNotNull (program); + + var method = program.GetMethod ("Main"); + Assert.IsNotNull (method); + + AssertCode (@" + .locals init (System.Int32 V_0) + IL_0000: ldarg.0 + IL_0001: ldlen + IL_0002: conv.i4 + IL_0003: stloc.0 + IL_0004: ldloc.0 + IL_0005: ldc.i4.8 + IL_0006: bgt.s IL_0026 + IL_0008: ldloc.0 + IL_0009: ldc.i4.1 + IL_000a: sub + IL_000b: switch (IL_0032, IL_0034, IL_0038, IL_0034) + IL_0020: ldloc.0 + IL_0021: ldc.i4.8 + IL_0022: beq.s IL_0036 + IL_0024: br.s IL_0038 + IL_0026: ldloc.0 + IL_0027: ldc.i4.s 16 + IL_0029: beq.s IL_0036 + IL_002b: ldloc.0 + IL_002c: ldc.i4.s 32 + IL_002e: beq.s IL_0036 + IL_0030: br.s IL_0038 + IL_0032: ldc.i4.0 + IL_0033: ret + IL_0034: ldc.i4.1 + IL_0035: ret + IL_0036: ldc.i4.2 + IL_0037: ret + IL_0038: ldc.i4.s 42 + IL_003a: ret +", method); + } + + [TestIL ("methodspecs.il")] + public void MethodSpec (ModuleDefinition module) + { + var tamtam = module.GetType ("Tamtam"); + + var bar = tamtam.GetMethod ("Bar"); + Assert.IsNotNull (bar); + + AssertCode (@" + .locals () + IL_0000: ldc.i4.2 + IL_0001: call System.Void Tamtam::Foo(TFoo) + IL_0006: ret +", bar); + } + + [TestModule ("catch.exe")] + public void NestedTryCatchFinally (ModuleDefinition module) + { + var program = module.GetType ("Program"); + var main = program.GetMethod ("Main"); + Assert.IsNotNull (main); + + AssertCode (@" + .locals () + IL_0000: call System.Void Program::Foo() + IL_0005: leave.s IL_000d + IL_0007: call System.Void Program::Baz() + IL_000c: endfinally + IL_000d: leave.s IL_001f + IL_000f: pop + IL_0010: call System.Void Program::Bar() + IL_0015: leave.s IL_001f + IL_0017: pop + IL_0018: call System.Void Program::Bar() + IL_001d: leave.s IL_001f + IL_001f: leave.s IL_0027 + IL_0021: call System.Void Program::Baz() + IL_0026: endfinally + IL_0027: ret + .try IL_0000 to IL_0007 finally handler IL_0007 to IL_000d + .try IL_0000 to IL_000f catch System.ArgumentException handler IL_000f to IL_0017 + .try IL_0000 to IL_000f catch System.Exception handler IL_0017 to IL_001f + .try IL_0000 to IL_0021 finally handler IL_0021 to IL_0027 +", main); + } + + [TestModule ("fptr.exe", Verify = false)] + public void FunctionPointersAndCallSites (ModuleDefinition module) + { + var type = module.Types [0]; + var start = type.GetMethod ("Start"); + Assert.IsNotNull (start); + + AssertCode (@" + .locals init () + IL_0000: ldc.i4.1 + IL_0001: call method System.Int32 *(System.Int32) MakeDecision::Decide() + IL_0006: calli System.Int32(System.Int32) + IL_000b: call System.Void System.Console::WriteLine(System.Int32) + IL_0010: ldc.i4.1 + IL_0011: call method System.Int32 *(System.Int32) MakeDecision::Decide() + IL_0016: calli System.Int32(System.Int32) + IL_001b: call System.Void System.Console::WriteLine(System.Int32) + IL_0020: ldc.i4.1 + IL_0021: call method System.Int32 *(System.Int32) MakeDecision::Decide() + IL_0026: calli System.Int32(System.Int32) + IL_002b: call System.Void System.Console::WriteLine(System.Int32) + IL_0030: ret +", start); + } + + [TestIL ("hello.il")] + public void ThisParameter (ModuleDefinition module) + { + var type = module.GetType ("Foo"); + var method = type.GetMethod ("Gazonk"); + + Assert.IsNotNull (method); + + AssertCode (@" + .locals () + IL_0000: ldarg 0 + IL_0004: pop + IL_0005: ret +", method); + + Assert.AreEqual (method.Body.ThisParameter.ParameterType, type); + Assert.AreEqual (method.Body.ThisParameter, method.Body.Instructions [0].Operand); + } + + [Test] + public void ThisParameterStaticMethod () + { + var static_method = typeof (ModuleDefinition).ToDefinition ().Methods.Where (m => m.IsStatic).First (); + Assert.IsNull (static_method.Body.ThisParameter); + } + + [Test] + public void ThisParameterPrimitive () + { + var int32 = typeof (int).ToDefinition (); + var int_to_string = int32.Methods.Where (m => m.Name == "ToString" && m.Parameters.Count == 0).First(); + Assert.IsNotNull (int_to_string); + + var this_parameter_type = int_to_string.Body.ThisParameter.ParameterType; + Assert.IsTrue (this_parameter_type.IsPointer); + + var element_type = ((PointerType) this_parameter_type).ElementType; + Assert.AreEqual (int32, element_type); + } + + [Test] + public void ThisParameterValueType () + { + var token = typeof (MetadataToken).ToDefinition (); + var token_to_string = token.Methods.Where (m => m.Name == "ToString" && m.Parameters.Count == 0).First (); + Assert.IsNotNull (token_to_string); + + var this_parameter_type = token_to_string.Body.ThisParameter.ParameterType; + Assert.IsTrue (this_parameter_type.IsPointer); + + var element_type = ((PointerType) this_parameter_type).ElementType; + Assert.AreEqual (token, element_type); + } + + [Test] + public void ThisParameterObject () + { + var module = typeof (MethodBodyTests).ToDefinition ().Module; + var @object = module.TypeSystem.Object.Resolve (); + var method = @object.Methods.Where (m => m.HasBody).First (); + + var type = method.Body.ThisParameter.ParameterType; + Assert.IsFalse (type.IsValueType); + Assert.IsFalse (type.IsPrimitive); + Assert.IsFalse (type.IsPointer); + } + + [TestIL ("hello.il")] + public void FilterMaxStack (ModuleDefinition module) + { + var type = module.GetType ("Foo"); + var method = type.GetMethod ("TestFilter"); + + Assert.IsNotNull (method); + Assert.AreEqual (2, method.Body.MaxStackSize); + } + + [TestModule ("iterator.exe")] + public void Iterator (ModuleDefinition module) + { + var method = module.GetType ("Program").GetMethod ("GetLittleArgs"); + Assert.IsNotNull (method.Body); + } + + [TestCSharp ("CustomAttributes.cs")] + public void LoadString (ModuleDefinition module) + { + var type = module.GetType ("FooAttribute"); + var get_fiou = type.GetMethod ("get_Fiou"); + Assert.IsNotNull (get_fiou); + + var ldstr = get_fiou.Body.Instructions.Where (i => i.OpCode == OpCodes.Ldstr).First (); + Assert.AreEqual ("fiou", ldstr.Operand); + } + + static void AssertCode (string expected, MethodDefinition method) + { + Assert.IsTrue (method.HasBody); + Assert.IsNotNull (method.Body); + + Assert.AreEqual (Normalize (expected), Normalize (Formatter.FormatMethodBody (method))); + } + + static string Normalize (string str) + { + return str.Trim ().Replace ("\r\n", "\n"); + } + + [Test] + public void AddInstruction () + { + var object_ref = new TypeReference ("System", "Object", null, null, false); + var method = new MethodDefinition ("foo", MethodAttributes.Static, object_ref); + var body = new MethodBody (method); + + var il = body.GetILProcessor (); + + var first = il.Create (OpCodes.Nop); + var second = il.Create (OpCodes.Nop); + + body.Instructions.Add (first); + body.Instructions.Add (second); + + Assert.IsNull (first.Previous); + Assert.AreEqual (second, first.Next); + Assert.AreEqual (first, second.Previous); + Assert.IsNull (second.Next); + } + + [Test] + public void InsertInstruction () + { + var object_ref = new TypeReference ("System", "Object", null, null, false); + var method = new MethodDefinition ("foo", MethodAttributes.Static, object_ref); + var body = new MethodBody (method); + + var il = body.GetILProcessor (); + + var first = il.Create (OpCodes.Nop); + var second = il.Create (OpCodes.Nop); + var third = il.Create (OpCodes.Nop); + + body.Instructions.Add (first); + body.Instructions.Add (third); + + Assert.IsNull (first.Previous); + Assert.AreEqual (third, first.Next); + Assert.AreEqual (first, third.Previous); + Assert.IsNull (third.Next); + + body.Instructions.Insert (1, second); + + Assert.IsNull (first.Previous); + Assert.AreEqual (second, first.Next); + Assert.AreEqual (first, second.Previous); + Assert.AreEqual (third, second.Next); + Assert.AreEqual (second, third.Previous); + Assert.IsNull (third.Next); + } + + [Test] + public void InsertAfterLastInstruction () + { + var object_ref = new TypeReference ("System", "Object", null, null, false); + var method = new MethodDefinition ("foo", MethodAttributes.Static, object_ref); + var body = new MethodBody (method); + + var il = body.GetILProcessor (); + + var first = il.Create (OpCodes.Nop); + var second = il.Create (OpCodes.Nop); + var third = il.Create (OpCodes.Nop); + + body.Instructions.Add (first); + body.Instructions.Add (second); + + Assert.IsNull (first.Previous); + Assert.AreEqual (second, first.Next); + Assert.AreEqual (first, second.Previous); + Assert.IsNull (second.Next); + + body.Instructions.Insert (2, third); + + Assert.IsNull (first.Previous); + Assert.AreEqual (second, first.Next); + Assert.AreEqual (first, second.Previous); + Assert.AreEqual (third, second.Next); + Assert.AreEqual (second, third.Previous); + Assert.IsNull (third.Next); + } + + [Test] + public void RemoveInstruction () + { + var object_ref = new TypeReference ("System", "Object", null, null, false); + var method = new MethodDefinition ("foo", MethodAttributes.Static, object_ref); + var body = new MethodBody (method); + + var il = body.GetILProcessor (); + + var first = il.Create (OpCodes.Nop); + var second = il.Create (OpCodes.Nop); + var third = il.Create (OpCodes.Nop); + + body.Instructions.Add (first); + body.Instructions.Add (second); + body.Instructions.Add (third); + + Assert.IsNull (first.Previous); + Assert.AreEqual (second, first.Next); + Assert.AreEqual (first, second.Previous); + Assert.AreEqual (third, second.Next); + Assert.AreEqual (second, third.Previous); + Assert.IsNull (third.Next); + + body.Instructions.Remove (second); + + Assert.IsNull (first.Previous); + Assert.AreEqual (third, first.Next); + Assert.AreEqual (first, third.Previous); + Assert.IsNull (third.Next); + } + } +} diff --git a/external/cecil-legacy/Test/Mono.Cecil.Tests/MethodTests.cs b/external/cecil-legacy/Test/Mono.Cecil.Tests/MethodTests.cs new file mode 100644 index 0000000000..5d4d3751a1 --- /dev/null +++ b/external/cecil-legacy/Test/Mono.Cecil.Tests/MethodTests.cs @@ -0,0 +1,201 @@ +using System; +using System.Linq; + +using Mono.Cecil; +using Mono.Cecil.Metadata; + +using NUnit.Framework; + +namespace Mono.Cecil.Tests { + + [TestFixture] + public class MethodTests : BaseTestFixture { + + [TestCSharp ("Methods.cs")] + public void AbstractMethod (ModuleDefinition module) + { + var type = module.Types [1]; + Assert.AreEqual ("Foo", type.Name); + Assert.AreEqual (2, type.Methods.Count); + + var method = type.GetMethod ("Bar"); + Assert.AreEqual ("Bar", method.Name); + Assert.IsTrue (method.IsAbstract); + Assert.IsNotNull (method.ReturnType); + + Assert.AreEqual (1, method.Parameters.Count); + + var parameter = method.Parameters [0]; + + Assert.AreEqual ("a", parameter.Name); + Assert.AreEqual ("System.Int32", parameter.ParameterType.FullName); + } + + [TestCSharp ("Methods.cs")] + public void SimplePInvoke (ModuleDefinition module) + { + var bar = module.GetType ("Bar"); + var pan = bar.GetMethod ("Pan"); + + Assert.IsTrue (pan.IsPInvokeImpl); + Assert.IsNotNull (pan.PInvokeInfo); + + Assert.AreEqual ("Pan", pan.PInvokeInfo.EntryPoint); + Assert.IsNotNull (pan.PInvokeInfo.Module); + Assert.AreEqual ("foo.dll", pan.PInvokeInfo.Module.Name); + } + + [TestCSharp ("Generics.cs")] + public void GenericMethodDefinition (ModuleDefinition module) + { + var baz = module.GetType ("Baz"); + + var gazonk = baz.GetMethod ("Gazonk"); + + Assert.IsNotNull (gazonk); + + Assert.IsTrue (gazonk.HasGenericParameters); + Assert.AreEqual (1, gazonk.GenericParameters.Count); + Assert.AreEqual ("TBang", gazonk.GenericParameters [0].Name); + } + + [TestCSharp ("Generics.cs")] + public void ReturnGenericInstance (ModuleDefinition module) + { + var bar = module.GetType ("Bar`1"); + + var self = bar.GetMethod ("Self"); + Assert.IsNotNull (self); + + var bar_t = self.ReturnType; + + Assert.IsTrue (bar_t.IsGenericInstance); + + var bar_t_instance = (GenericInstanceType) bar_t; + + Assert.AreEqual (bar.GenericParameters [0], bar_t_instance.GenericArguments [0]); + + var self_str = bar.GetMethod ("SelfString"); + Assert.IsNotNull (self_str); + + var bar_str = self_str.ReturnType; + Assert.IsTrue (bar_str.IsGenericInstance); + + var bar_str_instance = (GenericInstanceType) bar_str; + + Assert.AreEqual ("System.String", bar_str_instance.GenericArguments [0].FullName); + } + + [TestCSharp ("Generics.cs")] + public void ReturnGenericInstanceWithMethodParameter (ModuleDefinition module) + { + var baz = module.GetType ("Baz"); + + var gazoo = baz.GetMethod ("Gazoo"); + Assert.IsNotNull (gazoo); + + var bar_bingo = gazoo.ReturnType; + + Assert.IsTrue (bar_bingo.IsGenericInstance); + + var bar_bingo_instance = (GenericInstanceType) bar_bingo; + + Assert.AreEqual (gazoo.GenericParameters [0], bar_bingo_instance.GenericArguments [0]); + } + + [TestCSharp ("Interfaces.cs")] + public void SimpleOverrides (ModuleDefinition module) + { + var ibingo = module.GetType ("IBingo"); + var ibingo_foo = ibingo.GetMethod ("Foo"); + Assert.IsNotNull (ibingo_foo); + + var ibingo_bar = ibingo.GetMethod ("Bar"); + Assert.IsNotNull (ibingo_bar); + + var bingo = module.GetType ("Bingo"); + + var foo = bingo.GetMethod ("IBingo.Foo"); + Assert.IsNotNull (foo); + + Assert.IsTrue (foo.HasOverrides); + Assert.AreEqual (ibingo_foo, foo.Overrides [0]); + + var bar = bingo.GetMethod ("IBingo.Bar"); + Assert.IsNotNull (bar); + + Assert.IsTrue (bar.HasOverrides); + Assert.AreEqual (ibingo_bar, bar.Overrides [0]); + } + + [TestModule ("varargs.exe")] + public void VarArgs (ModuleDefinition module) + { + var module_type = module.Types [0]; + + Assert.AreEqual (3, module_type.Methods.Count); + + var bar = module_type.GetMethod ("Bar"); + var baz = module_type.GetMethod ("Baz"); + var foo = module_type.GetMethod ("Foo"); + + Assert.IsTrue (bar.IsVarArg ()); + Assert.IsFalse (baz.IsVarArg ()); + + Assert.IsTrue(foo.IsVarArg ()); + + var bar_reference = (MethodReference) baz.Body.Instructions.Where (i => i.Offset == 0x000a).First ().Operand; + + Assert.IsTrue (bar_reference.IsVarArg ()); + Assert.AreEqual (0, bar_reference.GetSentinelPosition ()); + + var foo_reference = (MethodReference) baz.Body.Instructions.Where (i => i.Offset == 0x0023).First ().Operand; + + Assert.IsTrue (foo_reference.IsVarArg ()); + + Assert.AreEqual (1, foo_reference.GetSentinelPosition ()); + } + + [TestCSharp ("Generics.cs")] + public void GenericInstanceMethod (ModuleDefinition module) + { + var type = module.GetType ("It"); + var method = type.GetMethod ("ReadPwow"); + + GenericInstanceMethod instance = null; + + foreach (var instruction in method.Body.Instructions) { + instance = instruction.Operand as GenericInstanceMethod; + if (instance != null) + break; + } + + Assert.IsNotNull (instance); + + Assert.AreEqual (TokenType.MethodSpec, instance.MetadataToken.TokenType); + Assert.AreNotEqual (0, instance.MetadataToken.RID); + } + + [TestCSharp ("Generics.cs")] + public void MethodRefDeclaredOnGenerics (ModuleDefinition module) + { + var type = module.GetType ("Tamtam"); + var beta = type.GetMethod ("Beta"); + var charlie = type.GetMethod ("Charlie"); + + var new_list_beta = (MethodReference) beta.Body.Instructions [0].Operand; + var new_list_charlie = (MethodReference) charlie.Body.Instructions [0].Operand; + + Assert.AreEqual ("System.Collections.Generic.List`1", new_list_beta.DeclaringType.FullName); + Assert.AreEqual ("System.Collections.Generic.List`1", new_list_charlie.DeclaringType.FullName); + } + + [Test] + public void ReturnParameterMethod () + { + var method = typeof (MethodTests).ToDefinition ().GetMethod ("ReturnParameterMethod"); + Assert.IsNotNull (method); + Assert.AreEqual (method, method.MethodReturnType.Parameter.Method); + } + } +} diff --git a/external/cecil-legacy/Test/Mono.Cecil.Tests/ModuleTests.cs b/external/cecil-legacy/Test/Mono.Cecil.Tests/ModuleTests.cs new file mode 100644 index 0000000000..00f9e1af60 --- /dev/null +++ b/external/cecil-legacy/Test/Mono.Cecil.Tests/ModuleTests.cs @@ -0,0 +1,250 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Linq; + +using Mono.Cecil; + +using NUnit.Framework; + +namespace Mono.Cecil.Tests { + + [TestFixture] + public class ModuleTests : BaseTestFixture { + + [Test] + public void CreateModuleEscapesAssemblyName () + { + var module = ModuleDefinition.CreateModule ("Test.dll", ModuleKind.Dll); + Assert.AreEqual ("Test", module.Assembly.Name.Name); + + module = ModuleDefinition.CreateModule ("Test.exe", ModuleKind.Console); + Assert.AreEqual ("Test", module.Assembly.Name.Name); + } + + [TestModule ("hello.exe")] + public void SingleModule (ModuleDefinition module) + { + var assembly = module.Assembly; + + Assert.AreEqual (1, assembly.Modules.Count); + Assert.IsNotNull (assembly.MainModule); + } + + [TestModule ("hello.exe")] + public void EntryPoint (ModuleDefinition module) + { + var entry_point = module.EntryPoint; + Assert.IsNotNull (entry_point); + + Assert.AreEqual ("System.Void Program::Main()", entry_point.ToString ()); + } + + [TestModule ("mma.exe")] + public void MultiModules (ModuleDefinition module) + { + var assembly = module.Assembly; + + Assert.AreEqual (3, assembly.Modules.Count); + + Assert.AreEqual ("mma.exe", assembly.Modules [0].Name); + Assert.AreEqual (ModuleKind.Console, assembly.Modules [0].Kind); + + Assert.AreEqual ("moda.netmodule", assembly.Modules [1].Name); + Assert.AreEqual ("eedb4721-6c3e-4d9a-be30-49021121dd92", assembly.Modules [1].Mvid.ToString ()); + Assert.AreEqual (ModuleKind.NetModule, assembly.Modules [1].Kind); + + Assert.AreEqual ("modb.netmodule", assembly.Modules [2].Name); + Assert.AreEqual ("46c5c577-11b2-4ea0-bb3c-3c71f1331dd0", assembly.Modules [2].Mvid.ToString ()); + Assert.AreEqual (ModuleKind.NetModule, assembly.Modules [2].Kind); + } + + [TestModule ("hello.exe")] + public void ModuleInformation (ModuleDefinition module) + { + Assert.IsNotNull (module); + + Assert.AreEqual ("hello.exe", module.Name); + Assert.AreEqual (new Guid ("C3BC2BD3-2576-4D00-A80E-465B5632415F"), module.Mvid); + } + + [TestModule ("hello.exe")] + public void AssemblyReferences (ModuleDefinition module) + { + Assert.AreEqual (1, module.AssemblyReferences.Count); + + var reference = module.AssemblyReferences [0]; + + Assert.AreEqual ("mscorlib", reference.Name); + Assert.AreEqual (new Version (2, 0, 0, 0), reference.Version); + Assert.AreEqual (new byte [] { 0xB7, 0x7A, 0x5C, 0x56, 0x19, 0x34, 0xE0, 0x89 }, reference.PublicKeyToken); + } + + [TestModule ("pinvoke.exe")] + public void ModuleReferences (ModuleDefinition module) + { + Assert.AreEqual (2, module.ModuleReferences.Count); + Assert.AreEqual ("kernel32.dll", module.ModuleReferences [0].Name); + Assert.AreEqual ("shell32.dll", module.ModuleReferences [1].Name); + } + + [TestModule ("hello.exe")] + public void Types (ModuleDefinition module) + { + Assert.AreEqual (2, module.Types.Count); + Assert.AreEqual ("", module.Types [0].FullName); + Assert.AreEqual ("", module.GetType ("").FullName); + Assert.AreEqual ("Program", module.Types [1].FullName); + Assert.AreEqual ("Program", module.GetType ("Program").FullName); + } + + [TestModule ("libres.dll")] + public void LinkedResource (ModuleDefinition module) + { + var resource = module.Resources.Where (res => res.Name == "linked.txt").First () as LinkedResource; + Assert.IsNotNull (resource); + + Assert.AreEqual ("linked.txt", resource.Name); + Assert.AreEqual ("linked.txt", resource.File); + Assert.AreEqual (ResourceType.Linked, resource.ResourceType); + Assert.IsTrue (resource.IsPublic); + } + + [TestModule ("libres.dll")] + public void EmbeddedResource (ModuleDefinition module) + { + var resource = module.Resources.Where (res => res.Name == "embedded1.txt").First () as EmbeddedResource; + Assert.IsNotNull (resource); + + Assert.AreEqual ("embedded1.txt", resource.Name); + Assert.AreEqual (ResourceType.Embedded, resource.ResourceType); + Assert.IsTrue (resource.IsPublic); + + using (var reader = new StreamReader (resource.GetResourceStream ())) + Assert.AreEqual ("Hello", reader.ReadToEnd ()); + + resource = module.Resources.Where (res => res.Name == "embedded2.txt").First () as EmbeddedResource; + Assert.IsNotNull (resource); + + Assert.AreEqual ("embedded2.txt", resource.Name); + Assert.AreEqual (ResourceType.Embedded, resource.ResourceType); + Assert.IsTrue (resource.IsPublic); + + using (var reader = new StreamReader (resource.GetResourceStream ())) + Assert.AreEqual ("World", reader.ReadToEnd ()); + } + + [TestModule ("mma.exe")] + public void ExportedTypeFromNetModule (ModuleDefinition module) + { + Assert.IsTrue (module.HasExportedTypes); + Assert.AreEqual (2, module.ExportedTypes.Count); + + var exported_type = module.ExportedTypes [0]; + + Assert.AreEqual ("Module.A.Foo", exported_type.FullName); + Assert.AreEqual ("moda.netmodule", exported_type.Scope.Name); + + exported_type = module.ExportedTypes [1]; + + Assert.AreEqual ("Module.B.Baz", exported_type.FullName); + Assert.AreEqual ("modb.netmodule", exported_type.Scope.Name); + } + + [TestCSharp ("CustomAttributes.cs")] + public void NestedTypeForwarder (ModuleDefinition module) + { + Assert.IsTrue (module.HasExportedTypes); + Assert.AreEqual (2, module.ExportedTypes.Count); + + var exported_type = module.ExportedTypes [0]; + + Assert.AreEqual ("System.Diagnostics.DebuggableAttribute", exported_type.FullName); + Assert.AreEqual ("mscorlib", exported_type.Scope.Name); + Assert.IsTrue (exported_type.IsForwarder); + + var nested_exported_type = module.ExportedTypes [1]; + + Assert.AreEqual ("System.Diagnostics.DebuggableAttribute/DebuggingModes", nested_exported_type.FullName); + Assert.AreEqual (exported_type, nested_exported_type.DeclaringType); + Assert.AreEqual ("mscorlib", nested_exported_type.Scope.Name); + } + + [TestCSharp ("CustomAttributes.cs")] + public void HasTypeReference (ModuleDefinition module) + { + Assert.IsTrue (module.HasTypeReference ("System.Attribute")); + Assert.IsTrue (module.HasTypeReference ("mscorlib", "System.Attribute")); + + Assert.IsFalse (module.HasTypeReference ("System.Core", "System.Attribute")); + Assert.IsFalse (module.HasTypeReference ("System.Linq.Enumerable")); + } + + [TestModule ("libhello.dll")] + public void Win32FileVersion (ModuleDefinition module) + { + var version = FileVersionInfo.GetVersionInfo (module.FullyQualifiedName); + + Assert.AreEqual ("0.0.0.0", version.FileVersion); + } + + [TestModule ("noblob.dll")] + public void ModuleWithoutBlob (ModuleDefinition module) + { + Assert.IsNull (module.Image.BlobHeap); + } + + [Test] + public void MixedModeModule () + { + var module = GetResourceModule ("cppcli.dll"); + + Assert.AreEqual (1, module.ModuleReferences.Count); + Assert.AreEqual (string.Empty, module.ModuleReferences [0].Name); + } + + [Test] + [ExpectedException (typeof (BadImageFormatException))] + public void OpenIrrelevantFile () + { + GetResourceModule ("text_file.txt"); + } + + [Test] + public void WriteModuleTwice () + { + var module = GetResourceModule ("iterator.exe"); + + var path = Path.Combine (Path.GetTempPath (), "cecil"); + var file = Path.Combine (path, "iteratorrt.exe"); + + module.Write (file); + module.Write (file); + } + + [Test] + public void GetTypeNamespacePlusName () + { + var module = GetResourceModule ("moda.netmodule"); + + var type = module.GetType ("Module.A", "Foo"); + Assert.IsNotNull (type); + } + + [Test] + public void OpenModuleImmediate () + { + var module = GetResourceModule ("hello.exe", ReadingMode.Immediate); + + Assert.AreEqual (ReadingMode.Immediate, module.ReadingMode); + } + + [Test] + public void OpenModuleDeferred () + { + var module = GetResourceModule ("hello.exe", ReadingMode.Deferred); + + Assert.AreEqual (ReadingMode.Deferred, module.ReadingMode); + } + } +} diff --git a/external/cecil-legacy/Test/Mono.Cecil.Tests/NestedTypesTests.cs b/external/cecil-legacy/Test/Mono.Cecil.Tests/NestedTypesTests.cs new file mode 100644 index 0000000000..a8392928ba --- /dev/null +++ b/external/cecil-legacy/Test/Mono.Cecil.Tests/NestedTypesTests.cs @@ -0,0 +1,45 @@ +using System; + +using Mono.Cecil; + +using NUnit.Framework; + +namespace Mono.Cecil.Tests { + + [TestFixture] + public class NestedTypesTests : BaseTestFixture { + + [TestCSharp ("NestedTypes.cs")] + public void NestedTypes (ModuleDefinition module) + { + var foo = module.GetType ("Foo"); + + Assert.AreEqual ("Foo", foo.Name); + Assert.AreEqual ("Foo", foo.FullName); + Assert.AreEqual (module, foo.Module); + Assert.AreEqual (1, foo.NestedTypes.Count); + + var bar = foo.NestedTypes [0]; + + Assert.AreEqual ("Bar", bar.Name); + Assert.AreEqual ("Foo/Bar", bar.FullName); + Assert.AreEqual (module, bar.Module); + Assert.AreEqual (1, bar.NestedTypes.Count); + + var baz = bar.NestedTypes [0]; + + Assert.AreEqual ("Baz", baz.Name); + Assert.AreEqual ("Foo/Bar/Baz", baz.FullName); + Assert.AreEqual (module, baz.Module); + } + + [TestCSharp ("NestedTypes.cs")] + public void DirectNestedType (ModuleDefinition module) + { + var bingo = module.GetType ("Bingo"); + var get_fuel = bingo.GetMethod ("GetFuel"); + + Assert.AreEqual ("Bingo/Fuel", get_fuel.ReturnType.FullName); + } + } +} diff --git a/external/cecil-legacy/Test/Mono.Cecil.Tests/ParameterTests.cs b/external/cecil-legacy/Test/Mono.Cecil.Tests/ParameterTests.cs new file mode 100644 index 0000000000..124d7e1bd9 --- /dev/null +++ b/external/cecil-legacy/Test/Mono.Cecil.Tests/ParameterTests.cs @@ -0,0 +1,224 @@ +using System; +using System.Linq; + +using Mono.Cecil; +using Mono.Cecil.Metadata; + +using NUnit.Framework; + +namespace Mono.Cecil.Tests { + + [TestFixture] + public class ParameterTests : BaseTestFixture { + + [TestModule ("marshal.dll")] + public void MarshalAsI4 (ModuleDefinition module) + { + var bar = module.GetType ("Bar"); + var pan = bar.GetMethod ("Pan"); + + Assert.AreEqual (1, pan.Parameters.Count); + + var parameter = pan.Parameters [0]; + + Assert.IsTrue (parameter.HasMarshalInfo); + var info = parameter.MarshalInfo; + + Assert.AreEqual (typeof (MarshalInfo), info.GetType ()); + Assert.AreEqual (NativeType.I4, info.NativeType); + } + + [TestModule ("marshal.dll")] + public void CustomMarshaler (ModuleDefinition module) + { + var bar = module.GetType ("Bar"); + var pan = bar.GetMethod ("PanPan"); + + var parameter = pan.Parameters [0]; + + Assert.IsTrue (parameter.HasMarshalInfo); + + var info = (CustomMarshalInfo) parameter.MarshalInfo; + + Assert.AreEqual (Guid.Empty, info.Guid); + Assert.AreEqual (string.Empty, info.UnmanagedType); + Assert.AreEqual (NativeType.CustomMarshaler, info.NativeType); + Assert.AreEqual ("nomnom", info.Cookie); + + Assert.AreEqual ("Boc", info.ManagedType.FullName); + Assert.AreEqual (module, info.ManagedType.Scope); + } + + [TestModule ("marshal.dll")] + public void SafeArrayMarshaler (ModuleDefinition module) + { + var bar = module.GetType ("Bar"); + var pan = bar.GetMethod ("PanPan"); + + Assert.IsTrue (pan.MethodReturnType.HasMarshalInfo); + + var info = (SafeArrayMarshalInfo) pan.MethodReturnType.MarshalInfo; + + Assert.AreEqual (VariantType.Dispatch, info.ElementType); + } + + [TestModule ("marshal.dll")] + public void ArrayMarshaler (ModuleDefinition module) + { + var bar = module.GetType ("Bar"); + var pan = bar.GetMethod ("PanPan"); + + var parameter = pan.Parameters [1]; + + Assert.IsTrue (parameter.HasMarshalInfo); + + var info = (ArrayMarshalInfo) parameter.MarshalInfo; + + Assert.AreEqual (NativeType.I8, info.ElementType); + Assert.AreEqual (66, info.Size); + Assert.AreEqual (2, info.SizeParameterIndex); + + parameter = pan.Parameters [3]; + + Assert.IsTrue (parameter.HasMarshalInfo); + + info = (ArrayMarshalInfo) parameter.MarshalInfo; + + Assert.AreEqual (NativeType.I2, info.ElementType); + Assert.AreEqual (-1, info.Size); + Assert.AreEqual (-1, info.SizeParameterIndex); + } + + [TestModule ("marshal.dll")] + public void ArrayMarshalerSized (ModuleDefinition module) + { + var delegate_type = module.GetType ("SomeMethod"); + var parameter = delegate_type.GetMethod ("Invoke").Parameters [1]; + + Assert.IsTrue (parameter.HasMarshalInfo); + var array_info = (ArrayMarshalInfo) parameter.MarshalInfo; + + Assert.IsNotNull (array_info); + + Assert.AreEqual (0, array_info.SizeParameterMultiplier); + } + + [TestModule ("boxedoptarg.dll")] + public void BoxedDefaultArgumentValue (ModuleDefinition module) + { + var foo = module.GetType ("Foo"); + var bar = foo.GetMethod ("Bar"); + var baz = bar.Parameters [0]; + + Assert.IsTrue (baz.HasConstant); + Assert.AreEqual (-1, baz.Constant); + } + + [Test] + public void AddParameterIndex () + { + var object_ref = new TypeReference ("System", "Object", null, null, false); + var method = new MethodDefinition ("foo", MethodAttributes.Static, object_ref); + + var x = new ParameterDefinition ("x", ParameterAttributes.None, object_ref); + var y = new ParameterDefinition ("y", ParameterAttributes.None, object_ref); + + method.Parameters.Add (x); + method.Parameters.Add (y); + + Assert.AreEqual (0, x.Index); + Assert.AreEqual (1, y.Index); + + Assert.AreEqual (method, x.Method); + Assert.AreEqual (method, y.Method); + } + + [Test] + public void RemoveAtParameterIndex () + { + var object_ref = new TypeReference ("System", "Object", null, null, false); + var method = new MethodDefinition ("foo", MethodAttributes.Static, object_ref); + + var x = new ParameterDefinition ("x", ParameterAttributes.None, object_ref); + var y = new ParameterDefinition ("y", ParameterAttributes.None, object_ref); + var z = new ParameterDefinition ("y", ParameterAttributes.None, object_ref); + + method.Parameters.Add (x); + method.Parameters.Add (y); + method.Parameters.Add (z); + + Assert.AreEqual (0, x.Index); + Assert.AreEqual (1, y.Index); + Assert.AreEqual (2, z.Index); + + method.Parameters.RemoveAt (1); + + Assert.AreEqual (0, x.Index); + Assert.AreEqual (-1, y.Index); + Assert.AreEqual (1, z.Index); + } + + [Test] + public void RemoveParameterIndex () + { + var object_ref = new TypeReference ("System", "Object", null, null, false); + var method = new MethodDefinition ("foo", MethodAttributes.Static, object_ref); + + var x = new ParameterDefinition ("x", ParameterAttributes.None, object_ref); + var y = new ParameterDefinition ("y", ParameterAttributes.None, object_ref); + var z = new ParameterDefinition ("y", ParameterAttributes.None, object_ref); + + method.Parameters.Add (x); + method.Parameters.Add (y); + method.Parameters.Add (z); + + Assert.AreEqual (0, x.Index); + Assert.AreEqual (1, y.Index); + Assert.AreEqual (2, z.Index); + + method.Parameters.Remove (y); + + Assert.AreEqual (0, x.Index); + Assert.AreEqual (-1, y.Index); + Assert.AreEqual (1, z.Index); + } + + [Test] + public void InsertParameterIndex () + { + var object_ref = new TypeReference ("System", "Object", null, null, false); + var method = new MethodDefinition ("foo", MethodAttributes.Static, object_ref); + + var x = new ParameterDefinition ("x", ParameterAttributes.None, object_ref); + var y = new ParameterDefinition ("y", ParameterAttributes.None, object_ref); + var z = new ParameterDefinition ("y", ParameterAttributes.None, object_ref); + + method.Parameters.Add (x); + method.Parameters.Add (z); + + Assert.AreEqual (0, x.Index); + Assert.AreEqual (-1, y.Index); + Assert.AreEqual (1, z.Index); + + method.Parameters.Insert (1, y); + + Assert.AreEqual (0, x.Index); + Assert.AreEqual (1, y.Index); + Assert.AreEqual (2, z.Index); + } + + [TestIL ("hello.il")] + public void GenericParameterConstant (ModuleDefinition module) + { + var foo = module.GetType ("Foo"); + var method = foo.GetMethod ("GetState"); + + Assert.IsNotNull (method); + + var parameter = method.Parameters [1]; + + Assert.IsTrue (parameter.HasConstant); + Assert.IsNull (parameter.Constant); + } + } +} diff --git a/external/cecil-legacy/Test/Mono.Cecil.Tests/PropertyTests.cs b/external/cecil-legacy/Test/Mono.Cecil.Tests/PropertyTests.cs new file mode 100644 index 0000000000..2ff9c92853 --- /dev/null +++ b/external/cecil-legacy/Test/Mono.Cecil.Tests/PropertyTests.cs @@ -0,0 +1,112 @@ +using System.Linq; + +using NUnit.Framework; + +namespace Mono.Cecil.Tests { + + [TestFixture] + public class PropertyTests : BaseTestFixture { + + [TestCSharp ("Properties.cs")] + public void AbstractMethod (ModuleDefinition module) + { + var type = module.GetType ("Foo"); + + Assert.IsTrue (type.HasProperties); + + var properties = type.Properties; + + Assert.AreEqual (3, properties.Count); + + var property = properties [0]; + + Assert.IsNotNull (property); + Assert.AreEqual ("Bar", property.Name); + Assert.IsNotNull (property.PropertyType); + Assert.AreEqual ("System.Int32", property.PropertyType.FullName); + + Assert.IsNotNull (property.GetMethod); + Assert.AreEqual (MethodSemanticsAttributes.Getter, property.GetMethod.SemanticsAttributes); + Assert.IsNull (property.SetMethod); + + property = properties [1]; + + Assert.IsNotNull (property); + Assert.AreEqual ("Baz", property.Name); + Assert.IsNotNull (property.PropertyType); + Assert.AreEqual ("System.String", property.PropertyType.FullName); + + Assert.IsNotNull (property.GetMethod); + Assert.AreEqual (MethodSemanticsAttributes.Getter, property.GetMethod.SemanticsAttributes); + Assert.IsNotNull (property.SetMethod); + Assert.AreEqual (MethodSemanticsAttributes.Setter, property.SetMethod.SemanticsAttributes); + + property = properties [2]; + + Assert.IsNotNull (property); + Assert.AreEqual ("Gazonk", property.Name); + Assert.IsNotNull (property.PropertyType); + Assert.AreEqual ("System.String", property.PropertyType.FullName); + + Assert.IsNull (property.GetMethod); + Assert.IsNotNull (property.SetMethod); + Assert.AreEqual (MethodSemanticsAttributes.Setter, property.SetMethod.SemanticsAttributes); + } + + [TestIL ("others.il")] + public void OtherMethod (ModuleDefinition module) + { + var type = module.GetType ("Others"); + + Assert.IsTrue (type.HasProperties); + + var properties = type.Properties; + + Assert.AreEqual (1, properties.Count); + + var property = properties [0]; + + Assert.IsNotNull (property); + Assert.AreEqual ("Context", property.Name); + Assert.IsNotNull (property.PropertyType); + Assert.AreEqual ("System.String", property.PropertyType.FullName); + + Assert.IsTrue (property.HasOtherMethods); + + Assert.AreEqual (2, property.OtherMethods.Count); + + var other = property.OtherMethods [0]; + Assert.AreEqual ("let_Context", other.Name); + + other = property.OtherMethods [1]; + Assert.AreEqual ("bet_Context", other.Name); + } + + [TestCSharp ("Properties.cs")] + public void SetOnlyIndexer (ModuleDefinition module) + { + var type = module.GetType ("Bar"); + var indexer = type.Properties.Where (property => property.Name == "Item").First (); + + var parameters = indexer.Parameters; + + Assert.AreEqual (2, parameters.Count); + Assert.AreEqual ("System.Int32", parameters [0].ParameterType.FullName); + Assert.AreEqual ("System.String", parameters [1].ParameterType.FullName); + } + + [TestCSharp ("Properties.cs")] + public void ReadSemanticsFirst (ModuleDefinition module) + { + var type = module.GetType ("Baz"); + var setter = type.GetMethod ("set_Bingo"); + + Assert.AreEqual (MethodSemanticsAttributes.Setter, setter.SemanticsAttributes); + + var property = type.Properties.Where (p => p.Name == "Bingo").First (); + + Assert.AreEqual (setter, property.SetMethod); + Assert.AreEqual (type.GetMethod ("get_Bingo"), property.GetMethod); + } + } +} diff --git a/external/cecil-legacy/Test/Mono.Cecil.Tests/ResolveTests.cs b/external/cecil-legacy/Test/Mono.Cecil.Tests/ResolveTests.cs new file mode 100644 index 0000000000..cb7512d070 --- /dev/null +++ b/external/cecil-legacy/Test/Mono.Cecil.Tests/ResolveTests.cs @@ -0,0 +1,277 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +using Mono.Cecil; +using Mono.Cecil.Cil; + +using NUnit.Framework; + +namespace Mono.Cecil.Tests { + + [TestFixture] + public class ResolveTests : BaseTestFixture { + + [Test] + public void StringEmpty () + { + var string_empty = GetReference, FieldReference> ( + () => string.Empty); + + Assert.AreEqual ("System.String System.String::Empty", string_empty.FullName); + + var definition = string_empty.Resolve (); + + Assert.IsNotNull (definition); + + Assert.AreEqual ("System.String System.String::Empty", definition.FullName); + Assert.AreEqual ("mscorlib", definition.Module.Assembly.Name.Name); + } + + delegate string GetSubstring (string str, int start, int length); + + [Test] + public void StringSubstring () + { + var string_substring = GetReference ( + (s, start, length) => s.Substring (start, length)); + + var definition = string_substring.Resolve (); + + Assert.IsNotNull (definition); + + Assert.AreEqual ("System.String System.String::Substring(System.Int32,System.Int32)", definition.FullName); + Assert.AreEqual ("mscorlib", definition.Module.Assembly.Name.Name); + } + + [Test] + public void StringLength () + { + var string_length = GetReference, MethodReference> (s => s.Length); + + var definition = string_length.Resolve (); + + Assert.IsNotNull (definition); + + Assert.AreEqual ("get_Length", definition.Name); + Assert.AreEqual ("System.String", definition.DeclaringType.FullName); + Assert.AreEqual ("mscorlib", definition.Module.Assembly.Name.Name); + } + + [Test] + public void ListOfStringAdd () + { + var list_add = GetReference>, MethodReference> ( + list => list.Add ("coucou")); + + Assert.AreEqual ("System.Void System.Collections.Generic.List`1::Add(!0)", list_add.FullName); + + var definition = list_add.Resolve (); + + Assert.IsNotNull (definition); + + Assert.AreEqual ("System.Void System.Collections.Generic.List`1::Add(T)", definition.FullName); + Assert.AreEqual ("mscorlib", definition.Module.Assembly.Name.Name); + } + + [Test] + public void DictionaryOfStringTypeDefinitionTryGetValue () + { + var try_get_value = GetReference, string, bool>, MethodReference> ( + (d, s) => { + TypeDefinition type; + return d.TryGetValue (s, out type); + }); + + Assert.AreEqual ("System.Boolean System.Collections.Generic.Dictionary`2::TryGetValue(!0,!1&)", + try_get_value.FullName); + + var definition = try_get_value.Resolve (); + + Assert.IsNotNull (definition); + + Assert.AreEqual ("System.Boolean System.Collections.Generic.Dictionary`2::TryGetValue(TKey,TValue&)", definition.FullName); + Assert.AreEqual ("mscorlib", definition.Module.Assembly.Name.Name); + } + + class CustomResolver : DefaultAssemblyResolver { + + public void Register (AssemblyDefinition assembly) + { + this.RegisterAssembly (assembly); + this.AddSearchDirectory (Path.GetDirectoryName (assembly.MainModule.FullyQualifiedName)); + } + } + + [Test] + public void ExportedTypeFromModule () + { + var resolver = new CustomResolver (); + var parameters = new ReaderParameters { AssemblyResolver = resolver }; + var mma = GetResourceModule ("mma.exe", parameters); + + resolver.Register (mma.Assembly); + + var current_module = GetCurrentModule (parameters); + var reference = new TypeReference ("Module.A", "Foo", current_module, AssemblyNameReference.Parse (mma.Assembly.FullName), false); + + var definition = reference.Resolve (); + Assert.IsNotNull (definition); + Assert.AreEqual ("Module.A.Foo", definition.FullName); + } + + [Test] + public void TypeForwarder () + { + var resolver = new CustomResolver (); + var parameters = new ReaderParameters { AssemblyResolver = resolver }; + + var types = ModuleDefinition.ReadModule ( + CompilationService.CompileResource (GetCSharpResourcePath ("CustomAttributes.cs", typeof (ResolveTests).Assembly)), + parameters); + + resolver.Register (types.Assembly); + + var current_module = GetCurrentModule (parameters); + var reference = new TypeReference ("System.Diagnostics", "DebuggableAttribute", current_module, AssemblyNameReference.Parse (types.Assembly.FullName), false); + + var definition = reference.Resolve (); + Assert.IsNotNull (definition); + Assert.AreEqual ("System.Diagnostics.DebuggableAttribute", definition.FullName); + Assert.AreEqual ("mscorlib", definition.Module.Assembly.Name.Name); + } + + [Test] + public void NestedTypeForwarder () + { + var resolver = new CustomResolver (); + var parameters = new ReaderParameters { AssemblyResolver = resolver }; + + var types = ModuleDefinition.ReadModule ( + CompilationService.CompileResource (GetCSharpResourcePath ("CustomAttributes.cs", typeof (ResolveTests).Assembly)), + parameters); + + resolver.Register (types.Assembly); + + var current_module = GetCurrentModule (parameters); + var reference = new TypeReference ("", "DebuggingModes", current_module, null, true); + reference.DeclaringType = new TypeReference ("System.Diagnostics", "DebuggableAttribute", current_module, AssemblyNameReference.Parse (types.Assembly.FullName), false); + + var definition = reference.Resolve (); + Assert.IsNotNull (definition); + Assert.AreEqual ("System.Diagnostics.DebuggableAttribute/DebuggingModes", definition.FullName); + Assert.AreEqual ("mscorlib", definition.Module.Assembly.Name.Name); + } + + [Test] + public void RectangularArrayResolveGetMethod () + { + var get_a_b = GetReference, MethodReference> (matrix => matrix [2, 2]); + + Assert.AreEqual ("Get", get_a_b.Name); + Assert.IsNotNull (get_a_b.Module); + Assert.IsNull (get_a_b.Resolve ()); + } + + [Test] + public void ResolveFunctionPointer () + { + var module = GetResourceModule ("cppcli.dll"); + var global = module.GetType (""); + var field = global.GetField ("__onexitbegin_app_domain"); + + var type = field.FieldType as PointerType; + Assert.IsNotNull(type); + + var fnptr = type.ElementType as FunctionPointerType; + Assert.IsNotNull (fnptr); + + Assert.IsNull (fnptr.Resolve ()); + } + + [Test] + public void ResolveGenericParameter () + { + var collection = typeof (Mono.Collections.Generic.Collection<>).ToDefinition (); + var parameter = collection.GenericParameters [0]; + + Assert.IsNotNull (parameter); + + Assert.IsNull (parameter.Resolve ()); + } + + [Test] + public void ResolveNullVersionAssembly () + { + var reference = AssemblyNameReference.Parse ("System.Core"); + reference.Version = null; + + var resolver = new DefaultAssemblyResolver (); + Assert.IsNotNull (resolver.Resolve (reference)); + } + + [Test] + public void ResolvePortableClassLibraryReference () + { + var resolver = new DefaultAssemblyResolver (); + var parameters = new ReaderParameters { AssemblyResolver = resolver }; + var pcl = GetResourceModule ("PortableClassLibrary.dll", parameters); + + foreach (var reference in pcl.AssemblyReferences) { + Assert.IsTrue (reference.IsRetargetable); + var assembly = resolver.Resolve (reference); + Assert.IsNotNull (assembly); + Assert.AreEqual (typeof (object).Assembly.GetName ().Version, assembly.Name.Version); + } + } + + static TRet GetReference (TDel code) + { + var @delegate = code as Delegate; + if (@delegate == null) + throw new InvalidOperationException (); + + var reference = (TRet) GetReturnee (GetMethodFromDelegate (@delegate)); + + Assert.IsNotNull (reference); + + return reference; + } + + static object GetReturnee (MethodDefinition method) + { + Assert.IsTrue (method.HasBody); + + var instruction = method.Body.Instructions [method.Body.Instructions.Count - 1]; + + Assert.IsNotNull (instruction); + + while (instruction != null) { + var opcode = instruction.OpCode; + switch (opcode.OperandType) { + case OperandType.InlineField: + case OperandType.InlineTok: + case OperandType.InlineType: + case OperandType.InlineMethod: + return instruction.Operand; + default: + instruction = instruction.Previous; + break; + } + } + + throw new InvalidOperationException (); + } + + static MethodDefinition GetMethodFromDelegate (Delegate @delegate) + { + var method = @delegate.Method; + var type = (TypeDefinition) TypeParser.ParseType (GetCurrentModule (), method.DeclaringType.FullName); + + Assert.IsNotNull (type); + + return type.Methods.Where (m => m.Name == method.Name).First (); + } + } +} diff --git a/external/cecil-legacy/Test/Mono.Cecil.Tests/SecurityDeclarationTests.cs b/external/cecil-legacy/Test/Mono.Cecil.Tests/SecurityDeclarationTests.cs new file mode 100644 index 0000000000..2cc8d5b43a --- /dev/null +++ b/external/cecil-legacy/Test/Mono.Cecil.Tests/SecurityDeclarationTests.cs @@ -0,0 +1,290 @@ +using System; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text; + +using Mono.Cecil; +using Mono.Cecil.Metadata; +using Mono.Cecil.PE; + +using NUnit.Framework; + +namespace Mono.Cecil.Tests { + + [TestFixture] + public class SecurityDeclarationTests : BaseTestFixture { + + [TestModule ("decsec-xml.dll")] + public void XmlSecurityDeclaration (ModuleDefinition module) + { + var type = module.GetType ("SubLibrary"); + + Assert.IsTrue (type.HasSecurityDeclarations); + + Assert.AreEqual (1, type.SecurityDeclarations.Count); + + var declaration = type.SecurityDeclarations [0]; + Assert.AreEqual (SecurityAction.Deny, declaration.Action); + + Assert.AreEqual (1, declaration.SecurityAttributes.Count); + + var attribute = declaration.SecurityAttributes [0]; + + Assert.AreEqual ("System.Security.Permissions.PermissionSetAttribute", attribute.AttributeType.FullName); + + Assert.AreEqual (1, attribute.Properties.Count); + + var named_argument = attribute.Properties [0]; + + Assert.AreEqual ("XML", named_argument.Name); + + var argument = named_argument.Argument; + + Assert.AreEqual ("System.String", argument.Type.FullName); + + const string permission_set = "\r\n\r\n\r\n"; + + Assert.AreEqual (permission_set, argument.Value); + } + + [TestModule ("decsec1-xml.dll")] + public void XmlNet_1_1SecurityDeclaration (ModuleDefinition module) + { + var type = module.GetType ("SubLibrary"); + + Assert.IsTrue (type.HasSecurityDeclarations); + + Assert.AreEqual (1, type.SecurityDeclarations.Count); + + var declaration = type.SecurityDeclarations [0]; + Assert.AreEqual (SecurityAction.Deny, declaration.Action); + + Assert.AreEqual (1, declaration.SecurityAttributes.Count); + + var attribute = declaration.SecurityAttributes [0]; + + Assert.AreEqual ("System.Security.Permissions.PermissionSetAttribute", attribute.AttributeType.FullName); + + Assert.AreEqual (1, attribute.Properties.Count); + + var named_argument = attribute.Properties [0]; + + Assert.AreEqual ("XML", named_argument.Name); + + var argument = named_argument.Argument; + + Assert.AreEqual ("System.String", argument.Type.FullName); + + const string permission_set = "\r\n\r\n\r\n"; + + Assert.AreEqual (permission_set, argument.Value); + } + + [Test] + public void DefineSecurityDeclarationByBlob () + { + var file = Path.Combine(Path.GetTempPath(), "SecDecBlob.dll"); + var module = ModuleDefinition.CreateModule ("SecDecBlob.dll", new ModuleParameters { Kind = ModuleKind.Dll, Runtime = TargetRuntime.Net_2_0 }); + + const string permission_set = "\r\n\r\n\r\n"; + + var declaration = new SecurityDeclaration (SecurityAction.Deny, Encoding.Unicode.GetBytes (permission_set)); + module.Assembly.SecurityDeclarations.Add (declaration); + + module.Write (file); + module = ModuleDefinition.ReadModule (file); + + declaration = module.Assembly.SecurityDeclarations [0]; + Assert.AreEqual (SecurityAction.Deny, declaration.Action); + Assert.AreEqual (1, declaration.SecurityAttributes.Count); + + var attribute = declaration.SecurityAttributes [0]; + Assert.AreEqual ("System.Security.Permissions.PermissionSetAttribute", attribute.AttributeType.FullName); + Assert.AreEqual (1, attribute.Properties.Count); + + var named_argument = attribute.Properties [0]; + Assert.AreEqual ("XML", named_argument.Name); + var argument = named_argument.Argument; + Assert.AreEqual ("System.String", argument.Type.FullName); + Assert.AreEqual (permission_set, argument.Value); + } + + [TestModule ("empty-decsec-att.dll")] + public void SecurityDeclarationWithoutAttributes (ModuleDefinition module) + { + var type = module.GetType ("TestSecurityAction.ModalUITypeEditor"); + var method = type.GetMethod ("GetEditStyle"); + + Assert.IsNotNull (method); + + Assert.AreEqual (1, method.SecurityDeclarations.Count); + + var declaration = method.SecurityDeclarations [0]; + Assert.AreEqual (SecurityAction.LinkDemand, declaration.Action); + Assert.AreEqual (1, declaration.SecurityAttributes.Count); + + var attribute = declaration.SecurityAttributes [0]; + Assert.AreEqual ("System.Security.Permissions.SecurityPermissionAttribute", attribute.AttributeType.FullName); + Assert.AreEqual (0, attribute.Fields.Count); + Assert.AreEqual (0, attribute.Properties.Count); + } + + [TestModule ("decsec-att.dll")] + public void AttributeSecurityDeclaration (ModuleDefinition module) + { + var type = module.GetType ("SubLibrary"); + + Assert.IsTrue (type.HasSecurityDeclarations); + + Assert.AreEqual (1, type.SecurityDeclarations.Count); + + var declaration = type.SecurityDeclarations [0]; + Assert.AreEqual (SecurityAction.Deny, declaration.Action); + + Assert.AreEqual (1, declaration.SecurityAttributes.Count); + + var attribute = declaration.SecurityAttributes [0]; + + Assert.AreEqual ("System.Security.Permissions.SecurityPermissionAttribute", attribute.AttributeType.FullName); + + Assert.AreEqual (1, attribute.Properties.Count); + + var named_argument = attribute.Properties [0]; + + Assert.AreEqual ("UnmanagedCode", named_argument.Name); + + var argument = named_argument.Argument; + + Assert.AreEqual ("System.Boolean", argument.Type.FullName); + + Assert.AreEqual (true, argument.Value); + } + + static void AssertCustomAttributeArgument (string expected, CustomAttributeNamedArgument named_argument) + { + AssertCustomAttributeArgument (expected, named_argument.Argument); + } + + static void AssertCustomAttributeArgument (string expected, CustomAttributeArgument argument) + { + var result = new StringBuilder (); + PrettyPrint (argument, result); + + Assert.AreEqual (expected, result.ToString ()); + } + + static string PrettyPrint (CustomAttribute attribute) + { + var signature = new StringBuilder (); + signature.Append (".ctor ("); + + for (int i = 0; i < attribute.ConstructorArguments.Count; i++) { + if (i > 0) + signature.Append (", "); + + PrettyPrint (attribute.ConstructorArguments [i], signature); + } + + signature.Append (")"); + return signature.ToString (); + } + + static void PrettyPrint (CustomAttributeArgument argument, StringBuilder signature) + { + var value = argument.Value; + + signature.Append ("("); + + PrettyPrint (argument.Type, signature); + + signature.Append (":"); + + PrettyPrintValue (argument.Value, signature); + + signature.Append (")"); + } + + static void PrettyPrintValue (object value, StringBuilder signature) + { + if (value == null) { + signature.Append ("null"); + return; + } + + var arguments = value as CustomAttributeArgument []; + if (arguments != null) { + signature.Append ("{"); + for (int i = 0; i < arguments.Length; i++) { + if (i > 0) + signature.Append (", "); + + PrettyPrint (arguments [i], signature); + } + signature.Append ("}"); + + return; + } + + switch (Type.GetTypeCode (value.GetType ())) { + case TypeCode.String: + signature.AppendFormat ("\"{0}\"", value); + break; + case TypeCode.Char: + signature.AppendFormat ("'{0}'", (char) value); + break; + default: + var formattable = value as IFormattable; + if (formattable != null) { + signature.Append (formattable.ToString (null, CultureInfo.InvariantCulture)); + return; + } + + if (value is CustomAttributeArgument) { + PrettyPrint ((CustomAttributeArgument) value, signature); + return; + } + break; + } + } + + static void PrettyPrint (TypeReference type, StringBuilder signature) + { + if (type.IsArray) { + ArrayType array = (ArrayType) type; + signature.AppendFormat ("{0}[]", array.ElementType.etype.ToString ()); + } else if (type.etype == ElementType.None) { + signature.Append (type.FullName); + } else + signature.Append (type.etype.ToString ()); + } + + static void AssertArgument (T value, CustomAttributeNamedArgument named_argument) + { + AssertArgument (value, named_argument.Argument); + } + + static void AssertArgument (T value, CustomAttributeArgument argument) + { + AssertArgument (typeof (T).FullName, (object) value, argument); + } + + static void AssertArgument (string type, object value, CustomAttributeArgument argument) + { + Assert.AreEqual (type, argument.Type.FullName); + Assert.AreEqual (value, argument.Value); + } + } +} diff --git a/external/cecil-legacy/Test/Mono.Cecil.Tests/TypeParserTests.cs b/external/cecil-legacy/Test/Mono.Cecil.Tests/TypeParserTests.cs new file mode 100644 index 0000000000..6b52e98a90 --- /dev/null +++ b/external/cecil-legacy/Test/Mono.Cecil.Tests/TypeParserTests.cs @@ -0,0 +1,394 @@ +using System; +using System.Linq; + +using NUnit.Framework; + +namespace Mono.Cecil.Tests { + + [TestFixture] + public class TypeParserTests : BaseTestFixture { + + [Test] + public void SimpleStringReference () + { + var module = GetCurrentModule (); + var corlib = module.TypeSystem.Corlib; + + const string fullname = "System.String"; + + var type = TypeParser.ParseType (module, fullname); + Assert.IsNotNull (type); + Assert.AreEqual (corlib, type.Scope); + Assert.AreEqual (module, type.Module); + Assert.AreEqual ("System", type.Namespace); + Assert.AreEqual ("String", type.Name); + Assert.AreEqual (MetadataType.String, type.MetadataType); + Assert.IsFalse (type.IsValueType); + Assert.IsInstanceOf (typeof (TypeReference), type); + } + + [Test] + public void SimpleInt32Reference () + { + var module = GetCurrentModule (); + var corlib = module.TypeSystem.Corlib; + + const string fullname = "System.Int32"; + + var type = TypeParser.ParseType (module, fullname); + Assert.IsNotNull (type); + Assert.AreEqual (corlib, type.Scope); + Assert.AreEqual (module, type.Module); + Assert.AreEqual ("System", type.Namespace); + Assert.AreEqual ("Int32", type.Name); + Assert.AreEqual (MetadataType.Int32, type.MetadataType); + Assert.IsTrue (type.IsValueType); + Assert.IsInstanceOf (typeof (TypeReference), type); + } + + [Test] + public void SimpleTypeDefinition () + { + var module = GetCurrentModule (); + + const string fullname = "Mono.Cecil.Tests.TypeParserTests"; + + var type = TypeParser.ParseType (module, fullname); + Assert.IsNotNull (type); + Assert.AreEqual (module, type.Scope); + Assert.AreEqual (module, type.Module); + Assert.AreEqual ("Mono.Cecil.Tests", type.Namespace); + Assert.AreEqual ("TypeParserTests", type.Name); + Assert.IsInstanceOf (typeof (TypeDefinition), type); + } + + [Test] + public void ByRefTypeReference () + { + var module = GetCurrentModule (); + var corlib = module.TypeSystem.Corlib; + + const string fullname = "System.String&"; + + var type = TypeParser.ParseType (module, fullname); + + Assert.IsInstanceOf (typeof (ByReferenceType), type); + + type = ((ByReferenceType) type).ElementType; + + Assert.IsNotNull (type); + Assert.AreEqual (corlib, type.Scope); + Assert.AreEqual (module, type.Module); + Assert.AreEqual ("System", type.Namespace); + Assert.AreEqual ("String", type.Name); + Assert.IsInstanceOf (typeof (TypeReference), type); + } + + [Test] + public void FullyQualifiedTypeReference () + { + var module = GetCurrentModule (); + var cecil = module.AssemblyReferences.Where (reference => reference.Name == "Mono.Cecil").First (); + + var fullname = "Mono.Cecil.TypeDefinition, " + cecil.FullName; + + var type = TypeParser.ParseType (module, fullname); + Assert.IsNotNull (type); + Assert.AreEqual (cecil, type.Scope); + Assert.AreEqual (module, type.Module); + Assert.AreEqual ("Mono.Cecil", type.Namespace); + Assert.AreEqual ("TypeDefinition", type.Name); + Assert.IsInstanceOf (typeof (TypeReference), type); + } + + [Test] + public void OpenGenericType () + { + var module = GetCurrentModule (); + var corlib = module.TypeSystem.Corlib; + + const string fullname = "System.Collections.Generic.Dictionary`2"; + + var type = TypeParser.ParseType (module, fullname); + Assert.IsNotNull (type); + Assert.AreEqual (corlib, type.Scope); + Assert.AreEqual (module, type.Module); + Assert.AreEqual ("System.Collections.Generic", type.Namespace); + Assert.AreEqual ("Dictionary`2", type.Name); + Assert.IsInstanceOf (typeof (TypeReference), type); + Assert.AreEqual (2, type.GenericParameters.Count); + } + + public class ID {} + + [Test] + public void SimpleNestedType () + { + var module = GetCurrentModule (); + + const string fullname = "Mono.Cecil.Tests.TypeParserTests+ID"; + + var type = TypeParser.ParseType (module, fullname); + + Assert.IsNotNull (type); + Assert.AreEqual (module, type.Module); + Assert.AreEqual (module, type.Scope); + Assert.AreEqual ("", type.Namespace); + Assert.AreEqual ("ID", type.Name); + + Assert.AreEqual ("Mono.Cecil.Tests.TypeParserTests/ID", type.FullName); + Assert.AreEqual (fullname, TypeParser.ToParseable (type)); + } + + [Test] + public void TripleNestedTypeWithScope () + { + var module = GetCurrentModule (); + + const string fullname = "Bingo.Foo`1+Bar`1+Baz`1, Bingo"; + + var type = TypeParser.ParseType (module, fullname); + + Assert.AreEqual ("Bingo.Foo`1+Bar`1+Baz`1, Bingo, Culture=neutral, PublicKeyToken=null", TypeParser.ToParseable (type)); + + Assert.IsNotNull (type); + Assert.AreEqual ("Bingo", type.Scope.Name); + Assert.AreEqual (module, type.Module); + Assert.AreEqual ("", type.Namespace); + Assert.AreEqual ("Baz`1", type.Name); + Assert.IsInstanceOf (typeof (TypeReference), type); + Assert.AreEqual (1, type.GenericParameters.Count); + + type = type.DeclaringType; + + Assert.IsNotNull (type); + Assert.AreEqual ("Bingo", type.Scope.Name); + Assert.AreEqual (module, type.Module); + Assert.AreEqual ("", type.Namespace); + Assert.AreEqual ("Bar`1", type.Name); + Assert.IsInstanceOf (typeof (TypeReference), type); + Assert.AreEqual (1, type.GenericParameters.Count); + + type = type.DeclaringType; + + Assert.IsNotNull (type); + Assert.AreEqual ("Bingo", type.Scope.Name); + Assert.AreEqual (module, type.Module); + Assert.AreEqual ("Bingo", type.Namespace); + Assert.AreEqual ("Foo`1", type.Name); + Assert.IsInstanceOf (typeof (TypeReference), type); + Assert.AreEqual (1, type.GenericParameters.Count); + } + + [Test] + public void Vector () + { + var module = GetCurrentModule (); + + const string fullname = "Bingo.Gazonk[], Bingo"; + + var type = TypeParser.ParseType (module, fullname); + + Assert.AreEqual ("Bingo.Gazonk[], Bingo, Culture=neutral, PublicKeyToken=null", TypeParser.ToParseable (type)); + + var array = type as ArrayType; + Assert.IsNotNull (array); + Assert.AreEqual (1, array.Rank); + Assert.IsTrue (array.IsVector); + + type = array.ElementType; + + Assert.IsNotNull (type); + Assert.AreEqual ("Bingo", type.Scope.Name); + Assert.AreEqual (module, type.Module); + Assert.AreEqual ("Bingo", type.Namespace); + Assert.AreEqual ("Gazonk", type.Name); + Assert.IsInstanceOf (typeof (TypeReference), type); + } + + [Test] + public void ThreeDimensionalArray () + { + var module = GetCurrentModule (); + + const string fullname = "Bingo.Gazonk[,,], Bingo"; + + var type = TypeParser.ParseType (module, fullname); + + var array = type as ArrayType; + Assert.IsNotNull (array); + Assert.AreEqual (3, array.Rank); + Assert.IsFalse (array.IsVector); + + type = array.ElementType; + + Assert.IsNotNull (type); + Assert.AreEqual ("Bingo", type.Scope.Name); + Assert.AreEqual (module, type.Module); + Assert.AreEqual ("Bingo", type.Namespace); + Assert.AreEqual ("Gazonk", type.Name); + Assert.IsInstanceOf (typeof (TypeReference), type); + } + + [Test] + public void GenericInstanceExternArguments () + { + var module = GetCurrentModule (); + + var fullname = string.Format ("System.Collections.Generic.Dictionary`2[[System.Int32, {0}],[System.String, {0}]]", + typeof (object).Assembly.FullName); + + var type = TypeParser.ParseType (module, fullname); + + Assert.AreEqual (fullname, TypeParser.ToParseable (type)); + + var instance = type as GenericInstanceType; + Assert.IsNotNull (instance); + Assert.AreEqual (2, instance.GenericArguments.Count); + Assert.AreEqual ("mscorlib", type.Scope.Name); + Assert.AreEqual (module, type.Module); + Assert.AreEqual ("System.Collections.Generic", type.Namespace); + Assert.AreEqual ("Dictionary`2", type.Name); + + type = instance.ElementType; + + Assert.AreEqual (2, type.GenericParameters.Count); + + var argument = instance.GenericArguments [0]; + Assert.AreEqual ("mscorlib", argument.Scope.Name); + Assert.AreEqual (module, argument.Module); + Assert.AreEqual ("System", argument.Namespace); + Assert.AreEqual ("Int32", argument.Name); + + argument = instance.GenericArguments [1]; + Assert.AreEqual ("mscorlib", argument.Scope.Name); + Assert.AreEqual (module, argument.Module); + Assert.AreEqual ("System", argument.Namespace); + Assert.AreEqual ("String", argument.Name); + } + + [Test] + public void GenericInstanceMixedArguments () + { + var module = GetCurrentModule (); + + var fullname = string.Format ("System.Collections.Generic.Dictionary`2[Mono.Cecil.Tests.TypeParserTests,[System.String, {0}]]", + typeof (object).Assembly.FullName); + + var type = TypeParser.ParseType (module, fullname); + + var instance = type as GenericInstanceType; + Assert.IsNotNull (instance); + Assert.AreEqual (2, instance.GenericArguments.Count); + Assert.AreEqual ("mscorlib", type.Scope.Name); + Assert.AreEqual (module, type.Module); + Assert.AreEqual ("System.Collections.Generic", type.Namespace); + Assert.AreEqual ("Dictionary`2", type.Name); + + type = instance.ElementType; + + Assert.AreEqual (2, type.GenericParameters.Count); + + var argument = instance.GenericArguments [0]; + Assert.IsInstanceOf (typeof (TypeDefinition), argument); + Assert.AreEqual (module, argument.Module); + Assert.AreEqual ("Mono.Cecil.Tests", argument.Namespace); + Assert.AreEqual ("TypeParserTests", argument.Name); + + argument = instance.GenericArguments [1]; + Assert.AreEqual ("mscorlib", argument.Scope.Name); + Assert.AreEqual (module, argument.Module); + Assert.AreEqual ("System", argument.Namespace); + Assert.AreEqual ("String", argument.Name); + } + + public class Foo { + } + + public class Bar {} + + [Test] + public void GenericInstanceTwoNonFqArguments () + { + var module = GetCurrentModule (); + + var fullname = string.Format ("System.Collections.Generic.Dictionary`2[Mono.Cecil.Tests.TypeParserTests+Bar,Mono.Cecil.Tests.TypeParserTests+Bar], {0}", typeof (object).Assembly.FullName); + + var type = TypeParser.ParseType (module, fullname); + + var instance = type as GenericInstanceType; + Assert.IsNotNull (instance); + Assert.AreEqual (2, instance.GenericArguments.Count); + Assert.AreEqual ("mscorlib", type.Scope.Name); + Assert.AreEqual (module, type.Module); + Assert.AreEqual ("System.Collections.Generic", type.Namespace); + Assert.AreEqual ("Dictionary`2", type.Name); + + type = instance.ElementType; + + Assert.AreEqual (2, type.GenericParameters.Count); + + var argument = instance.GenericArguments [0]; + Assert.AreEqual (module, argument.Module); + Assert.AreEqual ("", argument.Namespace); + Assert.AreEqual ("Bar", argument.Name); + Assert.IsInstanceOf (typeof (TypeDefinition), argument); + + argument = instance.GenericArguments [1]; + Assert.AreEqual (module, argument.Module); + Assert.AreEqual ("", argument.Namespace); + Assert.AreEqual ("Bar", argument.Name); + Assert.IsInstanceOf (typeof (TypeDefinition), argument); + } + + [Test] + public void ComplexGenericInstanceMixedArguments () + { + var module = GetCurrentModule (); + + var fullname = string.Format ("System.Collections.Generic.Dictionary`2[[System.String, {0}],Mono.Cecil.Tests.TypeParserTests+Foo`2[Mono.Cecil.Tests.TypeParserTests,[System.Int32, {0}]]]", + typeof (object).Assembly.FullName); + + var type = TypeParser.ParseType (module, fullname); + + var instance = type as GenericInstanceType; + Assert.IsNotNull (instance); + Assert.AreEqual (2, instance.GenericArguments.Count); + Assert.AreEqual ("mscorlib", type.Scope.Name); + Assert.AreEqual (module, type.Module); + Assert.AreEqual ("System.Collections.Generic", type.Namespace); + Assert.AreEqual ("Dictionary`2", type.Name); + + type = instance.ElementType; + + Assert.AreEqual (2, type.GenericParameters.Count); + + var argument = instance.GenericArguments [0]; + Assert.AreEqual ("mscorlib", argument.Scope.Name); + Assert.AreEqual (module, argument.Module); + Assert.AreEqual ("System", argument.Namespace); + Assert.AreEqual ("String", argument.Name); + + argument = instance.GenericArguments [1]; + + instance = argument as GenericInstanceType; + Assert.IsNotNull (instance); + Assert.AreEqual (2, instance.GenericArguments.Count); + Assert.AreEqual (module, instance.Module); + Assert.AreEqual ("Mono.Cecil.Tests.TypeParserTests/Foo`2", instance.ElementType.FullName); + Assert.IsInstanceOf (typeof (TypeDefinition), instance.ElementType); + + argument = instance.GenericArguments [0]; + Assert.AreEqual (module, argument.Module); + Assert.AreEqual ("Mono.Cecil.Tests", argument.Namespace); + Assert.AreEqual ("TypeParserTests", argument.Name); + Assert.IsInstanceOf (typeof (TypeDefinition), argument); + + argument = instance.GenericArguments [1]; + Assert.AreEqual ("mscorlib", argument.Scope.Name); + Assert.AreEqual (module, argument.Module); + Assert.AreEqual ("System", argument.Namespace); + Assert.AreEqual ("Int32", argument.Name); + } + } +} diff --git a/external/cecil-legacy/Test/Mono.Cecil.Tests/TypeTests.cs b/external/cecil-legacy/Test/Mono.Cecil.Tests/TypeTests.cs new file mode 100644 index 0000000000..3ceb0aa4d2 --- /dev/null +++ b/external/cecil-legacy/Test/Mono.Cecil.Tests/TypeTests.cs @@ -0,0 +1,228 @@ +using System; +using System.Linq; + +using Mono.Cecil; +using Mono.Cecil.Cil; +using Mono.Cecil.Metadata; + +using NUnit.Framework; + +namespace Mono.Cecil.Tests { + + [TestFixture] + public class TypeTests : BaseTestFixture { + + [TestCSharp ("Layouts.cs")] + public void TypeLayout (ModuleDefinition module) + { + var foo = module.GetType ("Foo"); + Assert.IsNotNull (foo); + Assert.IsTrue (foo.IsValueType); + + Assert.IsTrue (foo.HasLayoutInfo); + Assert.AreEqual (16, foo.ClassSize); + + var babar = module.GetType ("Babar"); + Assert.IsNotNull (babar); + Assert.IsFalse (babar.IsValueType); + Assert.IsFalse (babar.HasLayoutInfo); + } + + [TestIL ("types.il")] + public void SimpleInterfaces (ModuleDefinition module) + { + var ibaz = module.GetType ("IBaz"); + Assert.IsNotNull (ibaz); + + Assert.IsTrue (ibaz.HasInterfaces); + + var interfaces = ibaz.Interfaces; + + Assert.AreEqual (2, interfaces.Count); + + Assert.AreEqual ("IBar", interfaces [0].FullName); + Assert.AreEqual ("IFoo", interfaces [1].FullName); + } + + [TestCSharp ("Generics.cs")] + public void GenericTypeDefinition (ModuleDefinition module) + { + var foo = module.GetType ("Foo`2"); + Assert.IsNotNull (foo); + + Assert.IsTrue (foo.HasGenericParameters); + Assert.AreEqual (2, foo.GenericParameters.Count); + + var tbar = foo.GenericParameters [0]; + + Assert.AreEqual ("TBar", tbar.Name); + Assert.AreEqual (foo, tbar.Owner); + + var tbaz = foo.GenericParameters [1]; + + Assert.AreEqual ("TBaz", tbaz.Name); + Assert.AreEqual (foo, tbaz.Owner); + } + + [TestCSharp ("Generics.cs")] + public void ConstrainedGenericType (ModuleDefinition module) + { + var bongo_t = module.GetType ("Bongo`1"); + Assert.IsNotNull (bongo_t); + + var t = bongo_t.GenericParameters [0]; + Assert.IsNotNull (t); + Assert.AreEqual ("T", t.Name); + + Assert.IsTrue (t.HasConstraints); + Assert.AreEqual (2, t.Constraints.Count); + + Assert.AreEqual ("Zap", t.Constraints [0].FullName); + Assert.AreEqual ("IZoom", t.Constraints [1].FullName); + } + + [TestCSharp ("Generics.cs")] + public void GenericBaseType (ModuleDefinition module) + { + var child = module.GetType ("Child`1"); + + var child_t = child.GenericParameters [0]; + Assert.IsNotNull (child_t); + + var instance = child.BaseType as GenericInstanceType; + Assert.IsNotNull (instance); + Assert.AreNotEqual (0, instance.MetadataToken.RID); + + Assert.AreEqual (child_t, instance.GenericArguments [0]); + } + + [TestCSharp ("Generics.cs")] + public void GenericConstraintOnGenericParameter (ModuleDefinition module) + { + var duel = module.GetType ("Duel`3"); + + Assert.AreEqual (3, duel.GenericParameters.Count); + + var t1 = duel.GenericParameters [0]; + var t2 = duel.GenericParameters [1]; + var t3 = duel.GenericParameters [2]; + + Assert.AreEqual (t1, t2.Constraints [0]); + Assert.AreEqual (t2, t3.Constraints [0]); + } + + [TestCSharp ("Generics.cs")] + public void GenericForwardBaseType (ModuleDefinition module) + { + var tamchild = module.GetType ("TamChild"); + + Assert.IsNotNull (tamchild); + Assert.IsNotNull (tamchild.BaseType); + + var generic_instance = tamchild.BaseType as GenericInstanceType; + + Assert.IsNotNull (generic_instance); + + Assert.AreEqual (1, generic_instance.GenericArguments.Count); + Assert.AreEqual (module.GetType ("Tamtam"), generic_instance.GenericArguments [0]); + } + + [TestCSharp ("Generics.cs")] + public void TypeExtentingGenericOfSelf (ModuleDefinition module) + { + var rec_child = module.GetType ("RecChild"); + + Assert.IsNotNull (rec_child); + Assert.IsNotNull (rec_child.BaseType); + + var generic_instance = rec_child.BaseType as GenericInstanceType; + + Assert.IsNotNull (generic_instance); + + Assert.AreEqual (1, generic_instance.GenericArguments.Count); + Assert.AreEqual (rec_child, generic_instance.GenericArguments [0]); + } + + [TestCSharp ("Methods.cs")] + public void TypeReferenceValueType (ModuleDefinition module) + { + var baz = module.GetType ("Baz"); + var method = baz.GetMethod ("PrintAnswer"); + + var box = method.Body.Instructions.Where (i => i.OpCode == OpCodes.Box).First (); + var int32 = (TypeReference) box.Operand; + + Assert.IsTrue (int32.IsValueType); + } + + [TestModule ("gifaceref.exe")] + public void GenericInterfaceReference (ModuleDefinition module) + { + var type = module.GetType ("Program"); + var iface = type.Interfaces [0]; + + var instance = (GenericInstanceType) iface; + var owner = instance.ElementType; + + Assert.AreEqual (1, instance.GenericArguments.Count); + Assert.AreEqual (1, owner.GenericParameters.Count); + } + + [TestModule ("cscgpbug.dll", Verify = false)] + public void UnboundGenericParameter (ModuleDefinition module) + { + var type = module.GetType ("ListViewModel"); + var method = type.GetMethod ("<>n__FabricatedMethod1"); + + var parameter = method.ReturnType as GenericParameter; + + Assert.IsNotNull (parameter); + Assert.AreEqual (0, parameter.Position); + Assert.IsNull (parameter.Owner); + } + + [TestCSharp ("Generics.cs")] + public void GenericMultidimensionalArray (ModuleDefinition module) + { + var type = module.GetType ("LaMatrix"); + var method = type.GetMethod ("At"); + + var call = method.Body.Instructions.Where (i => i.Operand is MethodReference).First (); + var get = (MethodReference) call.Operand; + + Assert.IsNotNull (get); + Assert.AreEqual (0, get.GenericParameters.Count); + Assert.AreEqual (MethodCallingConvention.Default, get.CallingConvention); + Assert.AreEqual (method.GenericParameters [0], get.ReturnType); + } + + [Test] + public void CorlibPrimitive () + { + var module = typeof (TypeTests).ToDefinition ().Module; + + var int32 = module.TypeSystem.Int32; + Assert.IsTrue (int32.IsPrimitive); + Assert.AreEqual (MetadataType.Int32, int32.MetadataType); + + var int32_def = int32.Resolve (); + Assert.IsTrue (int32_def.IsPrimitive); + Assert.AreEqual (MetadataType.Int32, int32_def.MetadataType); + } + + [TestIL ("explicitthis.il", Verify = false)] + public void ExplicitThis (ModuleDefinition module) + { + var type = module.GetType ("MakeDecision"); + var method = type.GetMethod ("Decide"); + var fptr = method.ReturnType as FunctionPointerType; + + Assert.IsNotNull (fptr); + Assert.IsTrue (fptr.HasThis); + Assert.IsTrue (fptr.ExplicitThis); + + Assert.AreEqual (0, fptr.Parameters [0].Sequence); + Assert.AreEqual (1, fptr.Parameters [1].Sequence); + } + } +} diff --git a/external/cecil-legacy/Test/Mono.Cecil.Tests/VariableTests.cs b/external/cecil-legacy/Test/Mono.Cecil.Tests/VariableTests.cs new file mode 100644 index 0000000000..9f6c54c67a --- /dev/null +++ b/external/cecil-legacy/Test/Mono.Cecil.Tests/VariableTests.cs @@ -0,0 +1,108 @@ +using System; +using System.Linq; + +using Mono.Cecil; +using Mono.Cecil.Cil; + +using NUnit.Framework; + +namespace Mono.Cecil.Tests { + + [TestFixture] + public class VariableTests : BaseTestFixture { + + [Test] + public void AddVariableIndex () + { + var object_ref = new TypeReference ("System", "Object", null, null, false); + var method = new MethodDefinition ("foo", MethodAttributes.Static, object_ref); + var body = new MethodBody (method); + + var x = new VariableDefinition ("x", object_ref); + var y = new VariableDefinition ("y", object_ref); + + body.Variables.Add (x); + body.Variables.Add (y); + + Assert.AreEqual (0, x.Index); + Assert.AreEqual (1, y.Index); + } + + [Test] + public void RemoveAtVariableIndex () + { + var object_ref = new TypeReference ("System", "Object", null, null, false); + var method = new MethodDefinition ("foo", MethodAttributes.Static, object_ref); + var body = new MethodBody (method); + + var x = new VariableDefinition ("x", object_ref); + var y = new VariableDefinition ("y", object_ref); + var z = new VariableDefinition ("z", object_ref); + + body.Variables.Add (x); + body.Variables.Add (y); + body.Variables.Add (z); + + Assert.AreEqual (0, x.Index); + Assert.AreEqual (1, y.Index); + Assert.AreEqual (2, z.Index); + + body.Variables.RemoveAt (1); + + Assert.AreEqual (0, x.Index); + Assert.AreEqual (-1, y.Index); + Assert.AreEqual (1, z.Index); + } + + [Test] + public void RemoveVariableIndex () + { + var object_ref = new TypeReference ("System", "Object", null, null, false); + var method = new MethodDefinition ("foo", MethodAttributes.Static, object_ref); + var body = new MethodBody (method); + + var x = new VariableDefinition ("x", object_ref); + var y = new VariableDefinition ("y", object_ref); + var z = new VariableDefinition ("z", object_ref); + + body.Variables.Add (x); + body.Variables.Add (y); + body.Variables.Add (z); + + Assert.AreEqual (0, x.Index); + Assert.AreEqual (1, y.Index); + Assert.AreEqual (2, z.Index); + + body.Variables.Remove (y); + + Assert.AreEqual (0, x.Index); + Assert.AreEqual (-1, y.Index); + Assert.AreEqual (1, z.Index); + } + + [Test] + public void InsertVariableIndex () + { + var object_ref = new TypeReference ("System", "Object", null, null, false); + var method = new MethodDefinition ("foo", MethodAttributes.Static, object_ref); + var body = new MethodBody (method); + + var x = new VariableDefinition ("x", object_ref); + var y = new VariableDefinition ("y", object_ref); + var z = new VariableDefinition ("z", object_ref); + + body.Variables.Add (x); + body.Variables.Add (z); + + Assert.AreEqual (0, x.Index); + Assert.AreEqual (-1, y.Index); + Assert.AreEqual (1, z.Index); + + body.Variables.Insert (1, y); + + Assert.AreEqual (0, x.Index); + Assert.AreEqual (1, y.Index); + Assert.AreEqual (2, z.Index); + } + } +} diff --git a/external/cecil-legacy/Test/Resources/assemblies/moda.netmodule b/external/cecil-legacy/Test/Resources/assemblies/moda.netmodule new file mode 100644 index 0000000000..8cc49983e6 Binary files /dev/null and b/external/cecil-legacy/Test/Resources/assemblies/moda.netmodule differ diff --git a/external/cecil-legacy/Test/Resources/assemblies/modb.netmodule b/external/cecil-legacy/Test/Resources/assemblies/modb.netmodule new file mode 100644 index 0000000000..38522b2935 Binary files /dev/null and b/external/cecil-legacy/Test/Resources/assemblies/modb.netmodule differ diff --git a/external/cecil-legacy/Test/Resources/assemblies/text_file.txt b/external/cecil-legacy/Test/Resources/assemblies/text_file.txt new file mode 100644 index 0000000000..5de1caf882 --- /dev/null +++ b/external/cecil-legacy/Test/Resources/assemblies/text_file.txt @@ -0,0 +1 @@ +Cecil ftw! diff --git a/external/cecil-legacy/Test/Resources/cs/CustomAttributes.cs b/external/cecil-legacy/Test/Resources/cs/CustomAttributes.cs new file mode 100644 index 0000000000..4c52c7c512 --- /dev/null +++ b/external/cecil-legacy/Test/Resources/cs/CustomAttributes.cs @@ -0,0 +1,152 @@ +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; + +[assembly: Foo ("bingo")] + +[assembly: TypeForwardedTo (typeof (System.Diagnostics.DebuggableAttribute))] + +enum Bingo : short { + Fuel = 2, + Binga = 4, +} + +/* +in System.Security.AccessControl + + [Flags] + public enum AceFlags : byte { + None = 0, + ObjectInherit = 0x01, + ContainerInherit = 0x02, + NoPropagateInherit = 0x04, + InheritOnly = 0x08, + InheritanceFlags = ObjectInherit | ContainerInherit | NoPropagateInherit | InheritOnly, + Inherited = 0x10, + SuccessfulAccess = 0x40, + FailedAccess = 0x80, + AuditFlags = SuccessfulAccess | FailedAccess, + } +*/ + +class FooAttribute : Attribute { + + internal class Token { + } + + public FooAttribute () + { + } + + public FooAttribute (string str) + { + } + + public FooAttribute (sbyte a, byte b, bool c, bool d, ushort e, short f, char g) + { + } + + public FooAttribute (int a, uint b, float c, long d, ulong e, double f) + { + } + + public FooAttribute (char [] chars) + { + } + + public FooAttribute (object a, object b) + { + } + + public FooAttribute (Bingo bingo) + { + } + + public FooAttribute (System.Security.AccessControl.AceFlags flags) + { + } + + public FooAttribute (Type type) + { + } + + public int Bang { get { return 0; } set {} } + public string Fiou { get { return "fiou"; } set {} } + + public object Pan; + public string [] PanPan; + + public Type Chose; +} + +[Foo ("bar")] +class Hamster { +} + +[Foo ((string) null)] +class Dentist { +} + +[Foo (-12, 242, true, false, 4242, -1983, 'c')] +class Steven { +} + +[Foo (-100000, 200000, 12.12f, long.MaxValue, ulong.MaxValue, 64.646464)] +class Seagull { +} + +[Foo (new char [] { 'c', 'e', 'c', 'i', 'l' })] +class Rifle { +} + +[Foo ("2", 2)] +class Worm { +} + +[Foo (new object [] { "2", 2, 'c' }, new object [] { new object [] { 1, 2, 3}, null })] +class Sheep { +} + +[Foo (Bang = 42, PanPan = new string [] { "yo", "yo" }, Pan = new object [] { 1, "2", '3' }, Fiou = null)] +class Angola { +} + +[Foo (Pan = "fiouuu")] +class BoxedStringField { +} + +[Foo (Bingo.Fuel)] +class Zero { +} + +[Foo (System.Security.AccessControl.AceFlags.NoPropagateInherit)] +class Ace { +} + +[Foo (new object [] { Bingo.Fuel, Bingo.Binga }, null, Pan = System.Security.AccessControl.AceFlags.NoPropagateInherit)] +class Bzzz { +} + +[Foo (typeof (Bingo))] +class Typed { +} + +[Foo (typeof (FooAttribute.Token))] +class NestedTyped { +} + +[Foo (Chose = typeof (Typed))] +class Truc { +} + +[Foo (Chose = (Type) null)] +class Machin { +} + +[Foo (typeof (Dictionary<,>))] +class OpenGeneric { +} + +[Foo (typeof (Dictionary[,]>))] +class ClosedGeneric { +} diff --git a/external/cecil-legacy/Test/Resources/cs/Events.cs b/external/cecil-legacy/Test/Resources/cs/Events.cs new file mode 100644 index 0000000000..22311060f6 --- /dev/null +++ b/external/cecil-legacy/Test/Resources/cs/Events.cs @@ -0,0 +1,8 @@ +using System; + +delegate void Pan (object sender, EventArgs args); + +abstract class Foo { + + public abstract event Pan Bar; +} diff --git a/external/cecil-legacy/Test/Resources/cs/Fields.cs b/external/cecil-legacy/Test/Resources/cs/Fields.cs new file mode 100644 index 0000000000..b85a57d1ce --- /dev/null +++ b/external/cecil-legacy/Test/Resources/cs/Fields.cs @@ -0,0 +1,41 @@ +using System; +using System.Runtime.InteropServices; + +class Foo { + Bar bar; +} + +class Bar { + volatile int oiseau; +} + +class Baz { + bool @bool; + char @char; + sbyte @sbyte; + byte @byte; + short int16; + ushort uint16; + int int32; + uint uint32; + long int64; + ulong uint64; + float single; + double @double; + string @string; + object @object; +} + +enum Pim { + Pam = 1, + Poum = 2, +} + +class PanPan { + + public const PanPan Peter = null; + public const string QQ = "qq"; + public const string nil = null; + public const object obj = null; + public const int [] ints = null; +} diff --git a/external/cecil-legacy/Test/Resources/cs/Generics.cs b/external/cecil-legacy/Test/Resources/cs/Generics.cs new file mode 100644 index 0000000000..3f6b1f966c --- /dev/null +++ b/external/cecil-legacy/Test/Resources/cs/Generics.cs @@ -0,0 +1,121 @@ +using System; +using System.Collections.Generic; + +class Foo {} + +abstract class Bar { + + T bang; + + public abstract Bar Self (); + + public abstract Bar SelfString (); +} + +abstract class Baz { + + public abstract TBang Gazonk (object o); + + public abstract Bar Gazoo (); +} + +class Zap {} +interface IZoom {} + +class Bongo where T : Zap, IZoom { + + enum Dang { + Ding = 2, + Dong = 12, + } +} + +class Parent {} +class Child : Parent { + public T [] array; +} +class TamChild : Child {} +class RecChild : Child {} + +class Tamtam { + + static void Foo (TFoo tf) + { + } + + static void Bar () + { + Foo (2); + } + + static List Beta () + { + return new List (); + } + + static List Charlie () + { + return new List (); + } +} + +class It { + + public IEnumerable> Pwow () + { + yield return new Foo (); + yield return new Foo (); + yield return new Foo (); + } + + public void ReadPwow () + { + foreach (Foo foo in Pwow ()) + Tac (foo); + } + + public void Tac (T t) + { + } +} + +class Duel where T2 : T1 where T3 : T2 {} + +class ChildReader { + + public int Read (TamChild t) + { + return t.array.Length; + } +} + +struct Nilible where T : struct { + public T t; +} + +class Null { + + public static int Compare (Nilible x, Nilible y) where T : struct + { + return Comparer.Default.Compare (x.t, y.t); + } +} + +public class DoubleFuncClass { + public void Test () { Test (); Test (); } + public void Test () { Test (); Test (); } + public void Test () { Test (); Test (); } +} + +public class DoubleFuncClass { + public void Test () { Test (); Test (); } + public void Test () { Test (); Test (); } + public void Test () { Test (); Test (); } +} + +public class LaMatrix { + public static T At (T[,] m, int i, int j) + { + return m [i, j]; + } +} diff --git a/external/cecil-legacy/Test/Resources/cs/Interfaces.cs b/external/cecil-legacy/Test/Resources/cs/Interfaces.cs new file mode 100644 index 0000000000..486c268a4b --- /dev/null +++ b/external/cecil-legacy/Test/Resources/cs/Interfaces.cs @@ -0,0 +1,22 @@ +using System; + +interface IFoo {} +interface IBar : IFoo {} + +abstract class Bar : IBar {} + +interface IBingo { + void Foo (); + void Bar (); +} + +class Bingo : IBingo { + + void IBingo.Foo () + { + } + + void IBingo.Bar () + { + } +} diff --git a/external/cecil-legacy/Test/Resources/cs/Layouts.cs b/external/cecil-legacy/Test/Resources/cs/Layouts.cs new file mode 100644 index 0000000000..3a332fd88d --- /dev/null +++ b/external/cecil-legacy/Test/Resources/cs/Layouts.cs @@ -0,0 +1,16 @@ +using System; +using System.Runtime.InteropServices; + +[StructLayout (LayoutKind.Explicit, Size = 16)] +public struct Foo { + [FieldOffset (0)] public ushort Bar; + [FieldOffset (2)] public ushort Baz; + [FieldOffset (4)] public uint Gazonk; +} + +class Babar { +} + +class Locke { + public int [] integers = new int [] { 1, 2, 3, 4 }; +} diff --git a/external/cecil-legacy/Test/Resources/cs/Methods.cs b/external/cecil-legacy/Test/Resources/cs/Methods.cs new file mode 100644 index 0000000000..36c0383a68 --- /dev/null +++ b/external/cecil-legacy/Test/Resources/cs/Methods.cs @@ -0,0 +1,21 @@ +using System; +using System.Runtime.InteropServices; + +abstract class Foo { + public abstract void Bar (int a); +} + +class Bar { + + [DllImport ("foo.dll")] + public extern static void Pan ([MarshalAs (UnmanagedType.I4)] int i); +} + +public class Baz { + + public void PrintAnswer () + { + Console.WriteLine ("answer: {0}", 42); + } +} + diff --git a/external/cecil-legacy/Test/Resources/cs/NestedTypes.cs b/external/cecil-legacy/Test/Resources/cs/NestedTypes.cs new file mode 100644 index 0000000000..2129e6b258 --- /dev/null +++ b/external/cecil-legacy/Test/Resources/cs/NestedTypes.cs @@ -0,0 +1,16 @@ +class Foo { + class Bar { + class Baz { + } + } +} + +class Bingo { + public class Fuel { + } + + public static Fuel GetFuel () + { + return null; + } +} diff --git a/external/cecil-legacy/Test/Resources/cs/Properties.cs b/external/cecil-legacy/Test/Resources/cs/Properties.cs new file mode 100644 index 0000000000..961a81a92b --- /dev/null +++ b/external/cecil-legacy/Test/Resources/cs/Properties.cs @@ -0,0 +1,18 @@ +using System; + +abstract class Foo { + + public abstract int Bar { get; } + public abstract string Baz { get; set; } + public abstract string Gazonk { set; } +} + +abstract class Bar { + + public abstract Foo this [int a, string s] { set; } +} + +class Baz { + + public string Bingo { get; set; } +} diff --git a/external/cecil-legacy/Test/Resources/il/explicitthis.il b/external/cecil-legacy/Test/Resources/il/explicitthis.il new file mode 100644 index 0000000000..59b3327694 --- /dev/null +++ b/external/cecil-legacy/Test/Resources/il/explicitthis.il @@ -0,0 +1,113 @@ +.assembly extern mscorlib +{ + .ver 0:0:0:0 +} + +.assembly fptr +{ + .ver 0:0:0:0 +} +.module fptr.exe + +.method public static void Main() cil managed +{ + .entrypoint + .locals init (class MakeDecision d, method instance explicit int32 *(class MakeDecision, int32) m, int32 i) + + ldc.i4.1 + ldc.i4 42 + newobj instance void MakeDecision::.ctor(bool, int32) + stloc d + + ldc.i4.0 + stloc i + br test + +loop: + ldloc d + call instance method instance explicit int32 *(class MakeDecision, int32) MakeDecision::Decide() + stloc m + + ldloc d + ldc.i4.1 + ldloc m + calli instance int32(int32) + call void [mscorlib]System.Console::WriteLine(int32) + + ldloc i + ldc.i4.1 + add + stloc i + +test: + ldloc i + ldc.i4 10 + blt loop + + ret +} + +.class public auto ansi sealed MakeDecision + extends [mscorlib]System.Object +{ + .field private bool Oscillate + .field private int32 Value + + .method public instance method instance explicit int32 *(class MakeDecision, int32) Decide() cil managed + { + .locals init (bool t) + + ldarg.0 + ldfld bool MakeDecision::Oscillate + stloc t + + ldarg.0 + ldloc t + ldc.i4.0 + ceq + stfld bool MakeDecision::Oscillate + + ldloc t + brfalse subs + + ldftn instance int32 MakeDecision::Add(int32) + ret + + subs: + ldftn instance int32 MakeDecision::Sub(int32) + ret + } + + .method public int32 Add(int32 i) cil managed + { + ldarg.0 + ldfld int32 MakeDecision::Value + ldarg i + add + ret + } + + .method public int32 Sub(int32 i) cil managed + { + ldarg.0 + ldfld int32 MakeDecision::Value + ldarg i + sub + ret + } + + .method public hidebysig specialname rtspecialname instance void .ctor(bool s, int32 val) cil managed + { + ldarg.0 + ldarg s + stfld bool MakeDecision::Oscillate + + ldarg.0 + ldarg val + stfld int32 MakeDecision::Value + + ldarg.0 + call instance void [mscorlib]System.Object::.ctor() + ret + } +} diff --git a/external/cecil-legacy/Test/Resources/il/hello.il b/external/cecil-legacy/Test/Resources/il/hello.il new file mode 100644 index 0000000000..a71b8fb4bc --- /dev/null +++ b/external/cecil-legacy/Test/Resources/il/hello.il @@ -0,0 +1,84 @@ +.assembly extern mscorlib +{ + .publickeytoken = (B7 7A 5C 56 19 34 E0 89) + .ver 2:0:0:0 +} + +.assembly Hello {} + +.module Hello.dll + +.class private auto ansi Foo { + + .method public specialname rtspecialname instance void .ctor () cil managed + { + ldarg.0 + call instance void [mscorlib]System.Object::.ctor () + ret + } + + .method public static void Bar (int32 a, int32 b) + { + .locals init (int32 res) + ldarg.0 + ldarg.1 + mul + stloc.0 + ldloc.0 + call void Foo::Baz (int32) + ret + } + + .method public static void Baz (int32 a) + { + ret + } + + .method public void Gazonk () + { + ldarg 0 + pop + ret + } + + .method public static void PrintEmpty () + { + ldsfld string [mscorlib]System.String::Empty + call void [mscorlib]System.Console::WriteLine(string) + ret + } + + .method public static bool TestFilter (bool b) cil managed + { + .maxstack 2 + .locals init (bool flag) + beginTry: + newobj instance void [mscorlib]System.Exception::.ctor () + throw + leave endCatch + startFilter: + pop + ldarg.0 + endfilter + startCatch: + ldc.i4.1 + stloc.0 + leave return + leave endCatch + endCatch: + L_001b: ldc.i4.0 + L_001c: stloc.0 + return: + L_001d: ldloc.0 + L_001e: ret + .try beginTry to startFilter filter startFilter handler startCatch to endCatch + } + + .method public static !!T GetState(string var, [opt] !!T defaultValue) cil managed + { + .param [2] = nullref + + ldarg.1 + ret + } +} diff --git a/external/cecil-legacy/Test/Resources/il/methodspecs.il b/external/cecil-legacy/Test/Resources/il/methodspecs.il new file mode 100644 index 0000000000..b8006f322b --- /dev/null +++ b/external/cecil-legacy/Test/Resources/il/methodspecs.il @@ -0,0 +1,43 @@ + +.assembly extern mscorlib +{ + .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) + .ver 2:0:0:0 +} + +.assembly MethodSpecs +{ +} + +.module MethodSpecs.dll + +.class private auto ansi beforefieldinit Tamtam + extends [mscorlib]System.Object +{ + .method private hidebysig static void Foo(!!TFoo tf) cil managed + { + // Code size 1 (0x1) + .maxstack 8 + IL_0000: ret + } // end of method Tamtam::Foo + + .method private hidebysig static void Bar() cil managed + { + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldc.i4.2 + IL_0001: call void Tamtam::Foo(!!0) + IL_0006: ret + } // end of method Tamtam::Bar + + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: ret + } // end of method Tamtam::.ctor + +} // end of class Tamtam diff --git a/external/cecil-legacy/Test/Resources/il/others.il b/external/cecil-legacy/Test/Resources/il/others.il new file mode 100644 index 0000000000..60713af30d --- /dev/null +++ b/external/cecil-legacy/Test/Resources/il/others.il @@ -0,0 +1,81 @@ +.assembly extern mscorlib +{ + .publickeytoken = (B7 7A 5C 56 19 34 E0 89) + .ver 2:0:0:0 +} + +.assembly Others {} + +.module Others.dll + +.class private auto ansi Others { + + .field private string _context + + .method public specialname instance string get_Context () cil managed + { + ldarg.0 + ldfld string Others::_context + ret + } + + .method public specialname instance void set_Context (string val) cil managed + { + ldarg.0 + ldarg.1 + stfld string Others::_context + ret + } + + .method public specialname instance void let_Context (string val) cil managed + { + ldarg.0 + ldarg.1 + stfld string Others::_context + ret + } + + .method public specialname instance void bet_Context (string val) cil managed + { + ldarg.0 + ldarg.1 + stfld string Others::_context + ret + } + + .property instance string Context () { + .get instance string Others::get_Context () + .set instance void Others::set_Context (string val) + .other instance void Others::let_Context (string val) + .other instance void Others::bet_Context (string val) + } + + .field private class [mscorlib]System.EventHandler _handler + + .method public specialname instance void remove_Handler (class [mscorlib]System.EventHandler) cil managed + { + ret + } + + .method public specialname instance void add_Handler (class [mscorlib]System.EventHandler) cil managed + { + ret + } + + .method public specialname instance void dang_Handler (class [mscorlib]System.EventHandler) cil managed + { + ret + } + + .method public specialname instance void fang_Handler (class [mscorlib]System.EventHandler) cil managed + { + ret + } + + .event [mscorlib]System.EventHandler Handler { + .removeon instance void Others::remove_Handler (class [mscorlib]System.EventHandler) + .addon instance void Others::add_Handler (class [mscorlib]System.EventHandler) + .other instance void Others::dang_Handler (class [mscorlib]System.EventHandler) + .other instance void Others::fang_Handler (class [mscorlib]System.EventHandler) + } +} diff --git a/external/cecil-legacy/Test/Resources/il/types.il b/external/cecil-legacy/Test/Resources/il/types.il new file mode 100644 index 0000000000..b230c21828 --- /dev/null +++ b/external/cecil-legacy/Test/Resources/il/types.il @@ -0,0 +1,58 @@ +.assembly extern mscorlib +{ + .publickeytoken = (B7 7A 5C 56 19 34 E0 89) + .ver 2:0:0:0 +} + +.assembly Types {} + +.module Types.dll + +.class private auto ansi Types { + + .field public int32[,] rank_two + .field public int32[0...,0...] rank_two_low_bound_zero + .field public int32[-1...4] rank_one_low_bound_m1 + + .method public specialname rtspecialname instance void .ctor () cil managed + { + ldarg.0 + call instance void [mscorlib]System.Object::.ctor () + ret + } +} + +.class interface private abstract auto ansi IFoo +{ +} + +.class interface private abstract auto ansi IBar + implements IFoo +{ +} + +.class interface private abstract IBaz + implements IBar, IFoo +{ +} + +.class private Fields { + + .field private static literal int32 int32_int16 = int16(0x0001) + .field private static literal int16 int16_int32 = int32(0x00000001) + .field private static literal char char_int16 = int16(0x0001) + .field private static literal int16 int16_char = char(0x0073) + .field private static literal int32 int32_nullref = nullref +} + +.class public auto ansi CustomAttribute extends [mscorlib]System.Attribute +{ + .custom instance void CustomAttribute::.ctor() = () + + .method public hidebysig specialname rtspecialname instance void .ctor() + { + ldarg.0 + call instance void [mscorlib]System.Attribute::.ctor() + ret + } +} diff --git a/external/cecil-legacy/Test/libs/nunit-2.6.2/license.txt b/external/cecil-legacy/Test/libs/nunit-2.6.2/license.txt new file mode 100755 index 0000000000..724e4652e8 --- /dev/null +++ b/external/cecil-legacy/Test/libs/nunit-2.6.2/license.txt @@ -0,0 +1,15 @@ +Copyright © 2002-2012 Charlie Poole +Copyright © 2002-2004 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov +Copyright © 2000-2002 Philip A. Craig + +This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment (see the following) in the product documentation is required. + +Portions Copyright © 2002-2012 Charlie Poole or Copyright © 2002-2004 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov or Copyright © 2000-2002 Philip A. Craig + +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source distribution. diff --git a/external/cecil/dbg/Program.cs b/external/cecil-legacy/dbg/Program.cs similarity index 100% rename from external/cecil/dbg/Program.cs rename to external/cecil-legacy/dbg/Program.cs diff --git a/external/cecil/dbg/Properties/AssemblyInfo.cs b/external/cecil-legacy/dbg/Properties/AssemblyInfo.cs similarity index 100% rename from external/cecil/dbg/Properties/AssemblyInfo.cs rename to external/cecil-legacy/dbg/Properties/AssemblyInfo.cs diff --git a/external/cecil/dbg/dbg.csproj b/external/cecil-legacy/dbg/dbg.csproj similarity index 100% rename from external/cecil/dbg/dbg.csproj rename to external/cecil-legacy/dbg/dbg.csproj diff --git a/external/cecil-legacy/mono.snk b/external/cecil-legacy/mono.snk new file mode 100644 index 0000000000..380116c18f Binary files /dev/null and b/external/cecil-legacy/mono.snk differ diff --git a/external/cecil/rocks/.gitignore b/external/cecil-legacy/rocks/.gitignore similarity index 100% rename from external/cecil/rocks/.gitignore rename to external/cecil-legacy/rocks/.gitignore diff --git a/external/cecil-legacy/rocks/Mono.Cecil.Rocks.csproj b/external/cecil-legacy/rocks/Mono.Cecil.Rocks.csproj new file mode 100644 index 0000000000..6d34f0b3d9 --- /dev/null +++ b/external/cecil-legacy/rocks/Mono.Cecil.Rocks.csproj @@ -0,0 +1,129 @@ + + + + net_4_0_Debug + AnyCPU + 9.0.30729 + 2.0 + {FBC6DD59-D09D-499C-B03C-99C1C78FF2AC} + Library + Properties + Mono.Cecil.Rocks + Mono.Cecil.Rocks + 512 + true + ..\mono.snk + + + true + full + false + ..\bin\net_3_5_Debug\ + DEBUG;TRACE;INSIDE_ROCKS;NET_3_5 + prompt + 4 + v3.5 + + + pdbonly + true + ..\bin\net_3_5_Release\ + TRACE;INSIDE_ROCKS;NET_3_5 + prompt + 4 + v3.5 + + + true + full + false + ..\bin\net_4_0_Debug\ + DEBUG;TRACE;INSIDE_ROCKS;NET_3_5;NET_4_0 + prompt + 4 + v4.0 + + + pdbonly + true + ..\bin\net_4_0_Release\ + TRACE;INSIDE_ROCKS;NET_3_5;NET_4_0 + prompt + 4 + v4.0 + + + true + full + false + ..\bin\silverlight_Debug\ + DEBUG;TRACE;NET_3_5;NET_4_0;SILVERLIGHT + prompt + 4 + Silverlight + v4.0 + + + pdbonly + true + ..\bin\silverlight_Release\ + TRACE;NET_3_5;NET_4_0;SILVERLIGHT + prompt + 4 + Silverlight + v4.0 + + + true + full + false + ..\bin\winphone_Debug\ + DEBUG;TRACE;NET_3_5;NET_4_0;SILVERLIGHT;CF + prompt + 4 + WindowsPhone + Silverlight + v4.0 + + + pdbonly + true + ..\bin\winphone_Release\ + TRACE;NET_3_5;NET_4_0;SILVERLIGHT;CF + prompt + 4 + WindowsPhone + Silverlight + v4.0 + + + + 3.5 + + + + + + + + + + + + + + + + {D68133BD-1E63-496E-9EDE-4FBDBF77B486} + Mono.Cecil + + + + + \ No newline at end of file diff --git a/external/cecil-legacy/rocks/Mono.Cecil.Rocks/AssemblyInfo.cs b/external/cecil-legacy/rocks/Mono.Cecil.Rocks/AssemblyInfo.cs new file mode 100644 index 0000000000..90543bb5e2 --- /dev/null +++ b/external/cecil-legacy/rocks/Mono.Cecil.Rocks/AssemblyInfo.cs @@ -0,0 +1,41 @@ +// +// AssemblyInfo.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Reflection; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle ("Mono.Cecil.Rocks")] +[assembly: AssemblyProduct ("Mono.Cecil")] +[assembly: AssemblyCopyright ("Copyright © 2008 - 2011 Jb Evain")] + +[assembly: CLSCompliant (false)] +[assembly: ComVisible (false)] + +[assembly: AssemblyVersion ("0.9.5.0")] +[assembly: AssemblyFileVersion ("0.9.5.0")] diff --git a/external/cecil-legacy/rocks/Mono.Cecil.Rocks/Functional.cs b/external/cecil-legacy/rocks/Mono.Cecil.Rocks/Functional.cs new file mode 100644 index 0000000000..0e61b47bca --- /dev/null +++ b/external/cecil-legacy/rocks/Mono.Cecil.Rocks/Functional.cs @@ -0,0 +1,59 @@ +// +// Functional.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Collections.Generic; + +namespace Mono.Cecil.Rocks { + + static class Functional { + + public static System.Func Y (System.Func, System.Func> f) + { + System.Func g = null; + g = f (a => g (a)); + return g; + } + + public static IEnumerable Prepend (this IEnumerable source, TSource element) + { + if (source == null) + throw new ArgumentNullException ("source"); + + return PrependIterator (source, element); + } + + static IEnumerable PrependIterator (IEnumerable source, TSource element) + { + yield return element; + + foreach (var item in source) + yield return item; + } + } +} diff --git a/external/cecil-legacy/rocks/Mono.Cecil.Rocks/ILParser.cs b/external/cecil-legacy/rocks/Mono.Cecil.Rocks/ILParser.cs new file mode 100644 index 0000000000..6f745bc125 --- /dev/null +++ b/external/cecil-legacy/rocks/Mono.Cecil.Rocks/ILParser.cs @@ -0,0 +1,236 @@ +// +// ILParser.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +using Mono.Cecil.Cil; +using Mono.Collections.Generic; + +namespace Mono.Cecil.Rocks { + +#if INSIDE_ROCKS + public +#endif + interface IILVisitor { + void OnInlineNone (OpCode opcode); + void OnInlineSByte (OpCode opcode, sbyte value); + void OnInlineByte (OpCode opcode, byte value); + void OnInlineInt32 (OpCode opcode, int value); + void OnInlineInt64 (OpCode opcode, long value); + void OnInlineSingle (OpCode opcode, float value); + void OnInlineDouble (OpCode opcode, double value); + void OnInlineString (OpCode opcode, string value); + void OnInlineBranch (OpCode opcode, int offset); + void OnInlineSwitch (OpCode opcode, int [] offsets); + void OnInlineVariable (OpCode opcode, VariableDefinition variable); + void OnInlineArgument (OpCode opcode, ParameterDefinition parameter); + void OnInlineSignature (OpCode opcode, CallSite callSite); + void OnInlineType (OpCode opcode, TypeReference type); + void OnInlineField (OpCode opcode, FieldReference field); + void OnInlineMethod (OpCode opcode, MethodReference method); + } + +#if INSIDE_ROCKS + public +#endif + static class ILParser { + + class ParseContext { + public CodeReader Code { get; set; } + public MetadataReader Metadata { get; set; } + public Collection Variables { get; set; } + public IILVisitor Visitor { get; set; } + } + + public static void Parse (MethodDefinition method, IILVisitor visitor) + { + if (method == null) + throw new ArgumentNullException ("method"); + if (visitor == null) + throw new ArgumentNullException ("visitor"); + if (!method.HasBody || !method.HasImage) + throw new ArgumentException (); + + var context = CreateContext (method, visitor); + var code = context.Code; + + code.MoveTo (method.RVA); + + var flags = code.ReadByte (); + + switch (flags & 0x3) { + case 0x2: // tiny + int code_size = flags >> 2; + ParseCode (code_size, context); + break; + case 0x3: // fat + code.position--; + ParseFatMethod (context); + break; + default: + throw new NotSupportedException (); + } + } + + static ParseContext CreateContext (MethodDefinition method, IILVisitor visitor) + { + var code = method.Module.Read (method, (_, reader) => new CodeReader (reader.image.MetadataSection, reader)); + + return new ParseContext { + Code = code, + Metadata = code.reader, + Visitor = visitor, + }; + } + + static void ParseFatMethod (ParseContext context) + { + var code = context.Code; + + code.Advance (4); + var code_size = code.ReadInt32 (); + var local_var_token = code.ReadToken (); + + if (local_var_token != MetadataToken.Zero) + context.Variables = code.ReadVariables (local_var_token); + + ParseCode (code_size, context); + } + + static void ParseCode (int code_size, ParseContext context) + { + var code = context.Code; + var metadata = context.Metadata; + var visitor = context.Visitor; + + var start = code.position; + var end = start + code_size; + + while (code.position < end) { + var il_opcode = code.ReadByte (); + var opcode = il_opcode != 0xfe + ? OpCodes.OneByteOpCode [il_opcode] + : OpCodes.TwoBytesOpCode [code.ReadByte ()]; + + switch (opcode.OperandType) { + case OperandType.InlineNone: + visitor.OnInlineNone (opcode); + break; + case OperandType.InlineSwitch: + var length = code.ReadInt32 (); + var branches = new int [length]; + for (int i = 0; i < length; i++) + branches [i] = code.ReadInt32 (); + visitor.OnInlineSwitch (opcode, branches); + break; + case OperandType.ShortInlineBrTarget: + visitor.OnInlineBranch (opcode, code.ReadSByte ()); + break; + case OperandType.InlineBrTarget: + visitor.OnInlineBranch (opcode, code.ReadInt32 ()); + break; + case OperandType.ShortInlineI: + if (opcode == OpCodes.Ldc_I4_S) + visitor.OnInlineSByte (opcode, code.ReadSByte ()); + else + visitor.OnInlineByte (opcode, code.ReadByte ()); + break; + case OperandType.InlineI: + visitor.OnInlineInt32 (opcode, code.ReadInt32 ()); + break; + case OperandType.InlineI8: + visitor.OnInlineInt64 (opcode, code.ReadInt64 ()); + break; + case OperandType.ShortInlineR: + visitor.OnInlineSingle (opcode, code.ReadSingle ()); + break; + case OperandType.InlineR: + visitor.OnInlineDouble (opcode, code.ReadDouble ()); + break; + case OperandType.InlineSig: + visitor.OnInlineSignature (opcode, code.GetCallSite (code.ReadToken ())); + break; + case OperandType.InlineString: + visitor.OnInlineString (opcode, code.GetString (code.ReadToken ())); + break; + case OperandType.ShortInlineArg: + visitor.OnInlineArgument (opcode, code.GetParameter (code.ReadByte ())); + break; + case OperandType.InlineArg: + visitor.OnInlineArgument (opcode, code.GetParameter (code.ReadInt16 ())); + break; + case OperandType.ShortInlineVar: + visitor.OnInlineVariable (opcode, GetVariable (context, code.ReadByte ())); + break; + case OperandType.InlineVar: + visitor.OnInlineVariable (opcode, GetVariable (context, code.ReadInt16 ())); + break; + case OperandType.InlineTok: + case OperandType.InlineField: + case OperandType.InlineMethod: + case OperandType.InlineType: + var member = metadata.LookupToken (code.ReadToken ()); + switch (member.MetadataToken.TokenType) { + case TokenType.TypeDef: + case TokenType.TypeRef: + case TokenType.TypeSpec: + visitor.OnInlineType (opcode, (TypeReference) member); + break; + case TokenType.Method: + case TokenType.MethodSpec: + visitor.OnInlineMethod (opcode, (MethodReference) member); + break; + case TokenType.Field: + visitor.OnInlineField (opcode, (FieldReference) member); + break; + case TokenType.MemberRef: + var field_ref = member as FieldReference; + if (field_ref != null) { + visitor.OnInlineField (opcode, field_ref); + break; + } + + var method_ref = member as MethodReference; + if (method_ref != null) { + visitor.OnInlineMethod (opcode, method_ref); + break; + } + + throw new InvalidOperationException (); + } + break; + } + } + } + + static VariableDefinition GetVariable (ParseContext context, int index) + { + return context.Variables [index]; + } + } +} diff --git a/external/cecil-legacy/rocks/Mono.Cecil.Rocks/MethodBodyRocks.cs b/external/cecil-legacy/rocks/Mono.Cecil.Rocks/MethodBodyRocks.cs new file mode 100644 index 0000000000..f141f60848 --- /dev/null +++ b/external/cecil-legacy/rocks/Mono.Cecil.Rocks/MethodBodyRocks.cs @@ -0,0 +1,407 @@ +// +// MethodBodyRocks.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +using Mono.Cecil.Cil; + +namespace Mono.Cecil.Rocks { + +#if INSIDE_ROCKS + public +#endif + static class MethodBodyRocks { + + public static void SimplifyMacros (this MethodBody self) + { + if (self == null) + throw new ArgumentNullException ("self"); + + foreach (var instruction in self.Instructions) { + if (instruction.OpCode.OpCodeType != OpCodeType.Macro) + continue; + + switch (instruction.OpCode.Code) { + case Code.Ldarg_0: + ExpandMacro (instruction, OpCodes.Ldarg, self.GetParameter (0)); + break; + case Code.Ldarg_1: + ExpandMacro (instruction, OpCodes.Ldarg, self.GetParameter (1)); + break; + case Code.Ldarg_2: + ExpandMacro (instruction, OpCodes.Ldarg, self.GetParameter (2)); + break; + case Code.Ldarg_3: + ExpandMacro (instruction, OpCodes.Ldarg, self.GetParameter (3)); + break; + case Code.Ldloc_0: + ExpandMacro (instruction, OpCodes.Ldloc, self.Variables [0]); + break; + case Code.Ldloc_1: + ExpandMacro (instruction, OpCodes.Ldloc, self.Variables [1]); + break; + case Code.Ldloc_2: + ExpandMacro (instruction, OpCodes.Ldloc, self.Variables [2]); + break; + case Code.Ldloc_3: + ExpandMacro (instruction, OpCodes.Ldloc, self.Variables [3]); + break; + case Code.Stloc_0: + ExpandMacro (instruction, OpCodes.Stloc, self.Variables [0]); + break; + case Code.Stloc_1: + ExpandMacro (instruction, OpCodes.Stloc, self.Variables [1]); + break; + case Code.Stloc_2: + ExpandMacro (instruction, OpCodes.Stloc, self.Variables [2]); + break; + case Code.Stloc_3: + ExpandMacro (instruction, OpCodes.Stloc, self.Variables [3]); + break; + case Code.Ldarg_S: + instruction.OpCode = OpCodes.Ldarg; + break; + case Code.Ldarga_S: + instruction.OpCode = OpCodes.Ldarga; + break; + case Code.Starg_S: + instruction.OpCode = OpCodes.Starg; + break; + case Code.Ldloc_S: + instruction.OpCode = OpCodes.Ldloc; + break; + case Code.Ldloca_S: + instruction.OpCode = OpCodes.Ldloca; + break; + case Code.Stloc_S: + instruction.OpCode = OpCodes.Stloc; + break; + case Code.Ldc_I4_M1: + ExpandMacro (instruction, OpCodes.Ldc_I4, -1); + break; + case Code.Ldc_I4_0: + ExpandMacro (instruction, OpCodes.Ldc_I4, 0); + break; + case Code.Ldc_I4_1: + ExpandMacro (instruction, OpCodes.Ldc_I4, 1); + break; + case Code.Ldc_I4_2: + ExpandMacro (instruction, OpCodes.Ldc_I4, 2); + break; + case Code.Ldc_I4_3: + ExpandMacro (instruction, OpCodes.Ldc_I4, 3); + break; + case Code.Ldc_I4_4: + ExpandMacro (instruction, OpCodes.Ldc_I4, 4); + break; + case Code.Ldc_I4_5: + ExpandMacro (instruction, OpCodes.Ldc_I4, 5); + break; + case Code.Ldc_I4_6: + ExpandMacro (instruction, OpCodes.Ldc_I4, 6); + break; + case Code.Ldc_I4_7: + ExpandMacro (instruction, OpCodes.Ldc_I4, 7); + break; + case Code.Ldc_I4_8: + ExpandMacro (instruction, OpCodes.Ldc_I4, 8); + break; + case Code.Ldc_I4_S: + ExpandMacro (instruction, OpCodes.Ldc_I4, (int) (sbyte) instruction.Operand); + break; + case Code.Br_S: + instruction.OpCode = OpCodes.Br; + break; + case Code.Brfalse_S: + instruction.OpCode = OpCodes.Brfalse; + break; + case Code.Brtrue_S: + instruction.OpCode = OpCodes.Brtrue; + break; + case Code.Beq_S: + instruction.OpCode = OpCodes.Beq; + break; + case Code.Bge_S: + instruction.OpCode = OpCodes.Bge; + break; + case Code.Bgt_S: + instruction.OpCode = OpCodes.Bgt; + break; + case Code.Ble_S: + instruction.OpCode = OpCodes.Ble; + break; + case Code.Blt_S: + instruction.OpCode = OpCodes.Blt; + break; + case Code.Bne_Un_S: + instruction.OpCode = OpCodes.Bne_Un; + break; + case Code.Bge_Un_S: + instruction.OpCode = OpCodes.Bge_Un; + break; + case Code.Bgt_Un_S: + instruction.OpCode = OpCodes.Bgt_Un; + break; + case Code.Ble_Un_S: + instruction.OpCode = OpCodes.Ble_Un; + break; + case Code.Blt_Un_S: + instruction.OpCode = OpCodes.Blt_Un; + break; + case Code.Leave_S: + instruction.OpCode = OpCodes.Leave; + break; + } + } + } + + static void ExpandMacro (Instruction instruction, OpCode opcode, object operand) + { + instruction.OpCode = opcode; + instruction.Operand = operand; + } + + static void MakeMacro (Instruction instruction, OpCode opcode) + { + instruction.OpCode = opcode; + instruction.Operand = null; + } + + public static void OptimizeMacros (this MethodBody self) + { + if (self == null) + throw new ArgumentNullException ("self"); + + var method = self.Method; + + foreach (var instruction in self.Instructions) { + int index; + switch (instruction.OpCode.Code) { + case Code.Ldarg: + index = ((ParameterDefinition) instruction.Operand).Index; + if (index == -1 && instruction.Operand == self.ThisParameter) + index = 0; + else if (method.HasThis) + index++; + + switch (index) { + case 0: + MakeMacro (instruction, OpCodes.Ldarg_0); + break; + case 1: + MakeMacro (instruction, OpCodes.Ldarg_1); + break; + case 2: + MakeMacro (instruction, OpCodes.Ldarg_2); + break; + case 3: + MakeMacro (instruction, OpCodes.Ldarg_3); + break; + default: + if (index < 256) + ExpandMacro (instruction, OpCodes.Ldarg_S, instruction.Operand); + break; + } + break; + case Code.Ldloc: + index = ((VariableDefinition) instruction.Operand).Index; + switch (index) { + case 0: + MakeMacro (instruction, OpCodes.Ldloc_0); + break; + case 1: + MakeMacro (instruction, OpCodes.Ldloc_1); + break; + case 2: + MakeMacro (instruction, OpCodes.Ldloc_2); + break; + case 3: + MakeMacro (instruction, OpCodes.Ldloc_3); + break; + default: + if (index < 256) + ExpandMacro (instruction, OpCodes.Ldloc_S, instruction.Operand); + break; + } + break; + case Code.Stloc: + index = ((VariableDefinition) instruction.Operand).Index; + switch (index) { + case 0: + MakeMacro (instruction, OpCodes.Stloc_0); + break; + case 1: + MakeMacro (instruction, OpCodes.Stloc_1); + break; + case 2: + MakeMacro (instruction, OpCodes.Stloc_2); + break; + case 3: + MakeMacro (instruction, OpCodes.Stloc_3); + break; + default: + if (index < 256) + ExpandMacro (instruction, OpCodes.Stloc_S, instruction.Operand); + break; + } + break; + case Code.Ldarga: + index = ((ParameterDefinition) instruction.Operand).Index; + if (index == -1 && instruction.Operand == self.ThisParameter) + index = 0; + else if (method.HasThis) + index++; + if (index < 256) + ExpandMacro (instruction, OpCodes.Ldarga_S, instruction.Operand); + break; + case Code.Ldloca: + if (((VariableDefinition) instruction.Operand).Index < 256) + ExpandMacro (instruction, OpCodes.Ldloca_S, instruction.Operand); + break; + case Code.Ldc_I4: + int i = (int) instruction.Operand; + switch (i) { + case -1: + MakeMacro (instruction, OpCodes.Ldc_I4_M1); + break; + case 0: + MakeMacro (instruction, OpCodes.Ldc_I4_0); + break; + case 1: + MakeMacro (instruction, OpCodes.Ldc_I4_1); + break; + case 2: + MakeMacro (instruction, OpCodes.Ldc_I4_2); + break; + case 3: + MakeMacro (instruction, OpCodes.Ldc_I4_3); + break; + case 4: + MakeMacro (instruction, OpCodes.Ldc_I4_4); + break; + case 5: + MakeMacro (instruction, OpCodes.Ldc_I4_5); + break; + case 6: + MakeMacro (instruction, OpCodes.Ldc_I4_6); + break; + case 7: + MakeMacro (instruction, OpCodes.Ldc_I4_7); + break; + case 8: + MakeMacro (instruction, OpCodes.Ldc_I4_8); + break; + default: + if (i >= -128 && i < 128) + ExpandMacro (instruction, OpCodes.Ldc_I4_S, (sbyte) i); + break; + } + break; + } + } + + OptimizeBranches (self); + } + + static void OptimizeBranches (MethodBody body) + { + ComputeOffsets (body); + + foreach (var instruction in body.Instructions) { + if (instruction.OpCode.OperandType != OperandType.InlineBrTarget) + continue; + + if (OptimizeBranch (instruction)) + ComputeOffsets (body); + } + } + + static bool OptimizeBranch (Instruction instruction) + { + var offset = ((Instruction) instruction.Operand).Offset - (instruction.Offset + instruction.OpCode.Size + 4); + if (!(offset >= -128 && offset <= 127)) + return false; + + switch (instruction.OpCode.Code) { + case Code.Br: + instruction.OpCode = OpCodes.Br_S; + break; + case Code.Brfalse: + instruction.OpCode = OpCodes.Brfalse_S; + break; + case Code.Brtrue: + instruction.OpCode = OpCodes.Brtrue_S; + break; + case Code.Beq: + instruction.OpCode = OpCodes.Beq_S; + break; + case Code.Bge: + instruction.OpCode = OpCodes.Bge_S; + break; + case Code.Bgt: + instruction.OpCode = OpCodes.Bgt_S; + break; + case Code.Ble: + instruction.OpCode = OpCodes.Ble_S; + break; + case Code.Blt: + instruction.OpCode = OpCodes.Blt_S; + break; + case Code.Bne_Un: + instruction.OpCode = OpCodes.Bne_Un_S; + break; + case Code.Bge_Un: + instruction.OpCode = OpCodes.Bge_Un_S; + break; + case Code.Bgt_Un: + instruction.OpCode = OpCodes.Bgt_Un_S; + break; + case Code.Ble_Un: + instruction.OpCode = OpCodes.Ble_Un_S; + break; + case Code.Blt_Un: + instruction.OpCode = OpCodes.Blt_Un_S; + break; + case Code.Leave: + instruction.OpCode = OpCodes.Leave_S; + break; + } + + return true; + } + + static void ComputeOffsets (MethodBody body) + { + var offset = 0; + foreach (var instruction in body.Instructions) { + instruction.Offset = offset; + offset += instruction.GetSize (); + } + } + } +} diff --git a/external/cecil-legacy/rocks/Mono.Cecil.Rocks/MethodDefinitionRocks.cs b/external/cecil-legacy/rocks/Mono.Cecil.Rocks/MethodDefinitionRocks.cs new file mode 100644 index 0000000000..c2f758d2e6 --- /dev/null +++ b/external/cecil-legacy/rocks/Mono.Cecil.Rocks/MethodDefinitionRocks.cs @@ -0,0 +1,88 @@ +// +// MethodDefinitionRocks.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +namespace Mono.Cecil.Rocks { + +#if INSIDE_ROCKS + public +#endif + static class MethodDefinitionRocks { + + public static MethodDefinition GetBaseMethod (this MethodDefinition self) + { + if (self == null) + throw new ArgumentNullException ("self"); + if (!self.IsVirtual) + return self; + + var base_type = ResolveBaseType (self.DeclaringType); + while (base_type != null) { + var @base = GetMatchingMethod (base_type, self); + if (@base != null) + return @base; + + base_type = ResolveBaseType (base_type); + } + + return self; + } + + public static MethodDefinition GetOriginalBaseMethod (this MethodDefinition self) + { + if (self == null) + throw new ArgumentNullException ("self"); + + while (true) { + var @base = self.GetBaseMethod (); + if (@base == self) + return self; + + self = @base; + } + } + + static TypeDefinition ResolveBaseType (TypeDefinition type) + { + if (type == null) + return null; + + var base_type = type.BaseType; + if (base_type == null) + return null; + + return base_type.Resolve (); + } + + static MethodDefinition GetMatchingMethod (TypeDefinition type, MethodDefinition method) + { + return MetadataResolver.GetMethod (type.Methods, method); + } + } +} diff --git a/external/cecil-legacy/rocks/Mono.Cecil.Rocks/ModuleDefinitionRocks.cs b/external/cecil-legacy/rocks/Mono.Cecil.Rocks/ModuleDefinitionRocks.cs new file mode 100644 index 0000000000..5aaf73ce9f --- /dev/null +++ b/external/cecil-legacy/rocks/Mono.Cecil.Rocks/ModuleDefinitionRocks.cs @@ -0,0 +1,50 @@ +// +// ModuleDefinitionRocks.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Mono.Cecil.Rocks { + +#if INSIDE_ROCKS + public +#endif + static class ModuleDefinitionRocks { + + public static IEnumerable GetAllTypes (this ModuleDefinition self) + { + if (self == null) + throw new ArgumentNullException ("self"); + + // it was fun to write, but we need a somewhat less convoluted implementation + return self.Types.SelectMany ( + Functional.Y> (f => type => type.NestedTypes.SelectMany (f).Prepend (type))); + } + } +} diff --git a/external/cecil-legacy/rocks/Mono.Cecil.Rocks/ParameterReferenceRocks.cs b/external/cecil-legacy/rocks/Mono.Cecil.Rocks/ParameterReferenceRocks.cs new file mode 100644 index 0000000000..554bdb9099 --- /dev/null +++ b/external/cecil-legacy/rocks/Mono.Cecil.Rocks/ParameterReferenceRocks.cs @@ -0,0 +1,11 @@ + +namespace Mono.Cecil.Rocks { + + public static class ParameterReferenceRocks { + + public static int GetSequence (this ParameterReference self) + { + return self.Index + 1; + } + } +} diff --git a/external/cecil-legacy/rocks/Mono.Cecil.Rocks/SecurityDeclarationRocks.cs b/external/cecil-legacy/rocks/Mono.Cecil.Rocks/SecurityDeclarationRocks.cs new file mode 100644 index 0000000000..b84696fc6f --- /dev/null +++ b/external/cecil-legacy/rocks/Mono.Cecil.Rocks/SecurityDeclarationRocks.cs @@ -0,0 +1,174 @@ +// +// SecurityDeclarationRocks.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +#if !SILVERLIGHT && !CF + +using System; +using System.Security; +using SSP = System.Security.Permissions; + +namespace Mono.Cecil.Rocks { + +#if INSIDE_ROCKS + public +#endif + static class SecurityDeclarationRocks { + + public static PermissionSet ToPermissionSet (this SecurityDeclaration self) + { + if (self == null) + throw new ArgumentNullException ("self"); + + PermissionSet set; + if (TryProcessPermissionSetAttribute (self, out set)) + return set; + + return CreatePermissionSet (self); + } + + static bool TryProcessPermissionSetAttribute (SecurityDeclaration declaration, out PermissionSet set) + { + set = null; + + if (!declaration.HasSecurityAttributes && declaration.SecurityAttributes.Count != 1) + return false; + + var security_attribute = declaration.SecurityAttributes [0]; + if (!security_attribute.AttributeType.IsTypeOf ("System.Security.Permissions", "PermissionSetAttribute")) + return false; + + var attribute = new SSP.PermissionSetAttribute ((SSP.SecurityAction) declaration.Action); + + var named_argument = security_attribute.Properties [0]; + string value = (string) named_argument.Argument.Value; + switch (named_argument.Name) { + case "XML": + attribute.XML = value; + break; + case "Name": + attribute.Name = value; + break; + default: + throw new NotImplementedException (named_argument.Name); + } + + set = attribute.CreatePermissionSet (); + return true; + } + + static PermissionSet CreatePermissionSet (SecurityDeclaration declaration) + { + var set = new PermissionSet (SSP.PermissionState.None); + + foreach (var attribute in declaration.SecurityAttributes) { + var permission = CreatePermission (declaration, attribute); + set.AddPermission (permission); + } + + return set; + } + + static IPermission CreatePermission (SecurityDeclaration declaration, SecurityAttribute attribute) + { + var attribute_type = Type.GetType (attribute.AttributeType.FullName); + if (attribute_type == null) + throw new ArgumentException ("attribute"); + + var security_attribute = CreateSecurityAttribute (attribute_type, declaration); + if (security_attribute == null) + throw new InvalidOperationException (); + + CompleteSecurityAttribute (security_attribute, attribute); + + return security_attribute.CreatePermission (); + } + + static void CompleteSecurityAttribute (SSP.SecurityAttribute security_attribute, SecurityAttribute attribute) + { + if (attribute.HasFields) + CompleteSecurityAttributeFields (security_attribute, attribute); + + if (attribute.HasProperties) + CompleteSecurityAttributeProperties (security_attribute, attribute); + } + + static void CompleteSecurityAttributeFields (SSP.SecurityAttribute security_attribute, SecurityAttribute attribute) + { + var type = security_attribute.GetType (); + + foreach (var named_argument in attribute.Fields) + type.GetField (named_argument.Name).SetValue (security_attribute, named_argument.Argument.Value); + } + + static void CompleteSecurityAttributeProperties (SSP.SecurityAttribute security_attribute, SecurityAttribute attribute) + { + var type = security_attribute.GetType (); + + foreach (var named_argument in attribute.Properties) + type.GetProperty (named_argument.Name).SetValue (security_attribute, named_argument.Argument.Value, null); + } + + static SSP.SecurityAttribute CreateSecurityAttribute (Type attribute_type, SecurityDeclaration declaration) + { + SSP.SecurityAttribute security_attribute; + try { + security_attribute = (SSP.SecurityAttribute) Activator.CreateInstance ( + attribute_type, new object [] { (SSP.SecurityAction) declaration.Action }); + } catch (MissingMethodException) { + security_attribute = (SSP.SecurityAttribute) Activator.CreateInstance (attribute_type, new object [0]); + } + + return security_attribute; + } + + public static SecurityDeclaration ToSecurityDeclaration (this PermissionSet self, SecurityAction action, ModuleDefinition module) + { + if (self == null) + throw new ArgumentNullException ("self"); + if (module == null) + throw new ArgumentNullException ("module"); + + var declaration = new SecurityDeclaration (action); + + var attribute = new SecurityAttribute ( + module.TypeSystem.LookupType ("System.Security.Permissions", "PermissionSetAttribute")); + + attribute.Properties.Add ( + new CustomAttributeNamedArgument ( + "XML", + new CustomAttributeArgument ( + module.TypeSystem.String, self.ToXml ().ToString ()))); + + declaration.SecurityAttributes.Add (attribute); + + return declaration; + } + } +} + +#endif diff --git a/external/cecil-legacy/rocks/Mono.Cecil.Rocks/TypeDefinitionRocks.cs b/external/cecil-legacy/rocks/Mono.Cecil.Rocks/TypeDefinitionRocks.cs new file mode 100644 index 0000000000..74b7f087fc --- /dev/null +++ b/external/cecil-legacy/rocks/Mono.Cecil.Rocks/TypeDefinitionRocks.cs @@ -0,0 +1,83 @@ +// +// TypeDefinitionRocks.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Mono.Cecil.Rocks { + +#if INSIDE_ROCKS + public +#endif + static class TypeDefinitionRocks { + + public static IEnumerable GetConstructors (this TypeDefinition self) + { + if (self == null) + throw new ArgumentNullException ("self"); + + if (!self.HasMethods) + return Empty.Array; + + return self.Methods.Where (method => method.IsConstructor); + } + + public static MethodDefinition GetStaticConstructor (this TypeDefinition self) + { + if (self == null) + throw new ArgumentNullException ("self"); + + if (!self.HasMethods) + return null; + + return self.GetConstructors ().FirstOrDefault (ctor => ctor.IsStatic); + } + + public static IEnumerable GetMethods (this TypeDefinition self) + { + if (self == null) + throw new ArgumentNullException ("self"); + + if (!self.HasMethods) + return Empty.Array; + + return self.Methods.Where (method => !method.IsConstructor); + } + + public static TypeReference GetEnumUnderlyingType (this TypeDefinition self) + { + if (self == null) + throw new ArgumentNullException ("self"); + if (!self.IsEnum) + throw new ArgumentException (); + + return Mixin.GetEnumUnderlyingType (self); + } + } +} diff --git a/external/cecil-legacy/rocks/Mono.Cecil.Rocks/TypeReferenceRocks.cs b/external/cecil-legacy/rocks/Mono.Cecil.Rocks/TypeReferenceRocks.cs new file mode 100644 index 0000000000..5748b178f6 --- /dev/null +++ b/external/cecil-legacy/rocks/Mono.Cecil.Rocks/TypeReferenceRocks.cs @@ -0,0 +1,107 @@ +// +// TypeReferenceRocks.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Mono.Cecil.Rocks { + +#if INSIDE_ROCKS + public +#endif + static class TypeReferenceRocks { + + public static ArrayType MakeArrayType (this TypeReference self) + { + return new ArrayType (self); + } + + public static ArrayType MakeArrayType (this TypeReference self, int rank) + { + if (rank == 0) + throw new ArgumentOutOfRangeException ("rank"); + + var array = new ArrayType (self); + + for (int i = 1; i < rank; i++) + array.Dimensions.Add (new ArrayDimension ()); + + return array; + } + + public static PointerType MakePointerType (this TypeReference self) + { + return new PointerType (self); + } + + public static ByReferenceType MakeByReferenceType (this TypeReference self) + { + return new ByReferenceType (self); + } + + public static OptionalModifierType MakeOptionalModifierType (this TypeReference self, TypeReference modifierType) + { + return new OptionalModifierType (modifierType, self); + } + + public static RequiredModifierType MakeRequiredModifierType (this TypeReference self, TypeReference modifierType) + { + return new RequiredModifierType (modifierType, self); + } + + public static GenericInstanceType MakeGenericInstanceType (this TypeReference self, params TypeReference [] arguments) + { + if (self == null) + throw new ArgumentNullException ("self"); + if (arguments == null) + throw new ArgumentNullException ("arguments"); + if (arguments.Length == 0) + throw new ArgumentException (); + if (self.GenericParameters.Count != arguments.Length) + throw new ArgumentException (); + + var instance = new GenericInstanceType (self); + + foreach (var argument in arguments) + instance.GenericArguments.Add (argument); + + return instance; + } + + public static PinnedType MakePinnedType (this TypeReference self) + { + return new PinnedType (self); + } + + public static SentinelType MakeSentinelType (this TypeReference self) + { + return new SentinelType (self); + } + } +} diff --git a/external/cecil/rocks/Test/.gitignore b/external/cecil-legacy/rocks/Test/.gitignore similarity index 100% rename from external/cecil/rocks/Test/.gitignore rename to external/cecil-legacy/rocks/Test/.gitignore diff --git a/external/cecil-legacy/rocks/Test/Mono.Cecil.Rocks.Tests.csproj b/external/cecil-legacy/rocks/Test/Mono.Cecil.Rocks.Tests.csproj new file mode 100644 index 0000000000..93c5550e50 --- /dev/null +++ b/external/cecil-legacy/rocks/Test/Mono.Cecil.Rocks.Tests.csproj @@ -0,0 +1,106 @@ + + + + net_4_0_Debug + AnyCPU + 9.0.30729 + 2.0 + {C6CFD7E1-B855-44DC-B4CE-9CD72984AF52} + Library + Properties + Mono.Cecil.Rocks.Tests + Mono.Cecil.Rocks.Tests + 512 + + + true + full + false + bin\net_3_5_Debug\ + DEBUG;TRACE;NET_3_5 + prompt + 4 + v3.5 + + + pdbonly + true + bin\net_3_5_Release\ + TRACE;NET_3_5 + prompt + 4 + v3.5 + + + true + full + false + bin\net_4_0_Debug\ + DEBUG;TRACE;NET_3_5;NET_4_0 + prompt + 4 + v4.0 + + + pdbonly + true + bin\net_4_0_Release\ + TRACE;NET_3_5;NET_4_0 + prompt + 4 + v4.0 + + + + False + ..\..\Test\libs\nunit-2.6.2\nunit.core.dll + + + False + ..\..\Test\libs\nunit-2.6.2\nunit.core.interfaces.dll + + + False + ..\..\Test\libs\nunit-2.6.2\nunit.framework.dll + + + + 3.5 + + + + + {D68133BD-1E63-496E-9EDE-4FBDBF77B486} + Mono.Cecil + + + {A47B1F49-A81A-43E8-BE6B-DD28AF2C4055} + Mono.Cecil.Tests + + + {FBC6DD59-D09D-499C-B03C-99C1C78FF2AC} + Mono.Cecil.Rocks + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/external/cecil/rocks/Test/Mono.Cecil.Tests/Addin.cs b/external/cecil-legacy/rocks/Test/Mono.Cecil.Tests/Addin.cs similarity index 100% rename from external/cecil/rocks/Test/Mono.Cecil.Tests/Addin.cs rename to external/cecil-legacy/rocks/Test/Mono.Cecil.Tests/Addin.cs diff --git a/external/cecil-legacy/rocks/Test/Mono.Cecil.Tests/MethodDefinitionRocksTests.cs b/external/cecil-legacy/rocks/Test/Mono.Cecil.Tests/MethodDefinitionRocksTests.cs new file mode 100644 index 0000000000..2cfe0142a8 --- /dev/null +++ b/external/cecil-legacy/rocks/Test/Mono.Cecil.Tests/MethodDefinitionRocksTests.cs @@ -0,0 +1,53 @@ +using System.Linq; + +using NUnit.Framework; + +using Mono.Cecil.Rocks; + +namespace Mono.Cecil.Tests { + + [TestFixture] + public class MethodDefinitionRocksTests : BaseTestFixture { + + abstract class Foo { + public abstract void DoFoo (); + } + + class Bar : Foo { + public override void DoFoo () + { + } + } + + class Baz : Bar { + public override void DoFoo () + { + } + } + + [Test] + public void GetBaseMethod () + { + var baz = typeof (Baz).ToDefinition (); + var baz_dofoo = baz.GetMethod ("DoFoo"); + + var @base = baz_dofoo.GetBaseMethod (); + Assert.AreEqual ("Bar", @base.DeclaringType.Name); + + @base = @base.GetBaseMethod (); + Assert.AreEqual ("Foo", @base.DeclaringType.Name); + + Assert.AreEqual (@base, @base.GetBaseMethod ()); + } + + [Test] + public void GetOriginalBaseMethod () + { + var baz = typeof (Baz).ToDefinition (); + var baz_dofoo = baz.GetMethod ("DoFoo"); + + var @base = baz_dofoo.GetOriginalBaseMethod (); + Assert.AreEqual ("Foo", @base.DeclaringType.Name); + } + } +} diff --git a/external/cecil-legacy/rocks/Test/Mono.Cecil.Tests/ModuleDefinitionRocksTests.cs b/external/cecil-legacy/rocks/Test/Mono.Cecil.Tests/ModuleDefinitionRocksTests.cs new file mode 100644 index 0000000000..f172b404e0 --- /dev/null +++ b/external/cecil-legacy/rocks/Test/Mono.Cecil.Tests/ModuleDefinitionRocksTests.cs @@ -0,0 +1,27 @@ +using System.Linq; + +using NUnit.Framework; + +using Mono.Cecil.Rocks; + +namespace Mono.Cecil.Tests { + + [TestFixture] + public class ModuleDefinitionRocksTests : BaseTestFixture { + + [TestCSharp ("Types.cs")] + public void GetAllTypesTest (ModuleDefinition module) + { + var sequence = new [] { + module.GetType (""), + module.GetType ("Foo"), + module.GetType ("Foo/Bar"), + module.GetType ("Foo/Gazonk"), + module.GetType ("Foo/Gazonk/Baz"), + module.GetType ("Pan"), + }; + + Assert.IsTrue (sequence.SequenceEqual (module.GetAllTypes ())); + } + } +} diff --git a/external/cecil-legacy/rocks/Test/Mono.Cecil.Tests/SecurityDeclarationRocksTests.cs b/external/cecil-legacy/rocks/Test/Mono.Cecil.Tests/SecurityDeclarationRocksTests.cs new file mode 100644 index 0000000000..e7efba127a --- /dev/null +++ b/external/cecil-legacy/rocks/Test/Mono.Cecil.Tests/SecurityDeclarationRocksTests.cs @@ -0,0 +1,63 @@ +using System.Security.Permissions; + +using NUnit.Framework; + +using Mono.Cecil.Rocks; + +namespace Mono.Cecil.Tests { + + [TestFixture] + public class SecurityDeclarationRocksTests : BaseTestFixture { + + [TestModule ("decsec-xml.dll")] + public void ToPermissionSetFromPermissionSetAttribute (ModuleDefinition module) + { + var type = module.GetType ("SubLibrary"); + + Assert.IsTrue (type.HasSecurityDeclarations); + Assert.AreEqual (1, type.SecurityDeclarations.Count); + + var declaration = type.SecurityDeclarations [0]; + + var permission_set = declaration.ToPermissionSet (); + + Assert.IsNotNull (permission_set); + + string permission_set_value = "\r\n\r\n\r\n"; + + permission_set_value = string.Format (permission_set_value, typeof (SecurityPermission).AssemblyQualifiedName); + + Assert.AreEqual (Normalize (permission_set_value), Normalize (permission_set.ToXml ().ToString ())); + } + + [TestModule ("decsec-att.dll")] + public void ToPermissionSetFromSecurityAttribute (ModuleDefinition module) + { + var type = module.GetType ("SubLibrary"); + + Assert.IsTrue (type.HasSecurityDeclarations); + Assert.AreEqual (1, type.SecurityDeclarations.Count); + + var declaration = type.SecurityDeclarations [0]; + + var permission_set = declaration.ToPermissionSet (); + + Assert.IsNotNull (permission_set); + + string permission_set_value = "\r\n\r\n\r\n"; + + permission_set_value = string.Format (permission_set_value, typeof (SecurityPermission).AssemblyQualifiedName); + + Assert.AreEqual (Normalize (permission_set_value), Normalize (permission_set.ToXml ().ToString ())); + } + + static string Normalize (string s) + { + return s.Replace ("\n", "").Replace ("\r", ""); + } + } +} diff --git a/external/cecil-legacy/rocks/Test/Mono.Cecil.Tests/TypeDefinitionRocksTests.cs b/external/cecil-legacy/rocks/Test/Mono.Cecil.Tests/TypeDefinitionRocksTests.cs new file mode 100644 index 0000000000..7bd43cf7e1 --- /dev/null +++ b/external/cecil-legacy/rocks/Test/Mono.Cecil.Tests/TypeDefinitionRocksTests.cs @@ -0,0 +1,97 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Mono.Cecil.Rocks; + +using NUnit.Framework; + +namespace Mono.Cecil.Tests { + + [TestFixture] + public class TypeDefinitionRocksTests { + + class Foo { + + static Foo () + { + } + + public Foo (int a) + { + } + + public Foo (int a, string s) + { + } + + public static void Bar () + { + } + + void Baz () + { + } + } + + [Test] + public void GetConstructors () + { + var foo = typeof (Foo).ToDefinition (); + var ctors = foo.GetConstructors ().Select (ctor => ctor.FullName); + + var expected = new [] { + "System.Void Mono.Cecil.Tests.TypeDefinitionRocksTests/Foo::.cctor()", + "System.Void Mono.Cecil.Tests.TypeDefinitionRocksTests/Foo::.ctor(System.Int32)", + "System.Void Mono.Cecil.Tests.TypeDefinitionRocksTests/Foo::.ctor(System.Int32,System.String)", + }; + + AssertSet (expected, ctors); + } + + static void AssertSet (IEnumerable expected, IEnumerable actual) + { + Assert.IsFalse (expected.Except (actual).Any ()); + Assert.IsTrue (expected.Intersect (actual).SequenceEqual (expected)); + } + + [Test] + public void GetStaticConstructor () + { + var foo = typeof (Foo).ToDefinition (); + var cctor = foo.GetStaticConstructor (); + + Assert.IsNotNull (cctor); + Assert.AreEqual ("System.Void Mono.Cecil.Tests.TypeDefinitionRocksTests/Foo::.cctor()", cctor.FullName); + } + + [Test] + public void GetMethods () + { + var foo = typeof (Foo).ToDefinition (); + var methods = foo.GetMethods ().ToArray (); + + Assert.AreEqual (2, methods.Length); + Assert.AreEqual ("System.Void Mono.Cecil.Tests.TypeDefinitionRocksTests/Foo::Bar()", methods [0].FullName); + Assert.AreEqual ("System.Void Mono.Cecil.Tests.TypeDefinitionRocksTests/Foo::Baz()", methods [1].FullName); + } + + enum Pan : byte { + Pin, + Pon, + } + + [Test] + public void GetEnumUnderlyingType () + { + var pan = typeof (Pan).ToDefinition (); + + Assert.IsNotNull (pan); + Assert.IsTrue (pan.IsEnum); + + var underlying_type = pan.GetEnumUnderlyingType (); + Assert.IsNotNull (underlying_type); + + Assert.AreEqual ("System.Byte", underlying_type.FullName); + } + } +} \ No newline at end of file diff --git a/external/cecil-legacy/rocks/Test/Mono.Cecil.Tests/TypeReferenceRocksTests.cs b/external/cecil-legacy/rocks/Test/Mono.Cecil.Tests/TypeReferenceRocksTests.cs new file mode 100644 index 0000000000..9f51cb634d --- /dev/null +++ b/external/cecil-legacy/rocks/Test/Mono.Cecil.Tests/TypeReferenceRocksTests.cs @@ -0,0 +1,124 @@ +using System; + +using Mono.Cecil.Rocks; + +using NUnit.Framework; + +namespace Mono.Cecil.Tests { + + [TestFixture] + public class TypeReferenceRocksTests { + + [Test] + public void MakeArrayType () + { + var @string = GetTypeReference (typeof (string)); + + var string_array = @string.MakeArrayType (); + + Assert.IsInstanceOf (typeof (ArrayType), string_array); + Assert.AreEqual (1, string_array.Rank); + } + + [Test] + public void MakeArrayTypeRank () + { + var @string = GetTypeReference (typeof (string)); + + var string_array = @string.MakeArrayType (3); + + Assert.IsInstanceOf (typeof (ArrayType), string_array); + Assert.AreEqual (3, string_array.Rank); + } + + [Test] + public void MakePointerType () + { + var @string = GetTypeReference (typeof (string)); + + var string_ptr = @string.MakePointerType (); + + Assert.IsInstanceOf (typeof (PointerType), string_ptr); + } + + [Test] + public void MakeByReferenceType () + { + var @string = GetTypeReference (typeof (string)); + + var string_byref = @string.MakeByReferenceType (); + + Assert.IsInstanceOf (typeof (ByReferenceType), string_byref); + } + + class OptionalModifier {} + + [Test] + public void MakeOptionalModifierType () + { + var @string = GetTypeReference (typeof (string)); + var modopt = GetTypeReference (typeof (OptionalModifier)); + + var string_modopt = @string.MakeOptionalModifierType (modopt); + + Assert.IsInstanceOf (typeof (OptionalModifierType), string_modopt); + Assert.AreEqual (modopt, string_modopt.ModifierType); + } + + class RequiredModifier { } + + [Test] + public void MakeRequiredModifierType () + { + var @string = GetTypeReference (typeof (string)); + var modreq = GetTypeReference (typeof (RequiredModifierType)); + + var string_modreq = @string.MakeRequiredModifierType (modreq); + + Assert.IsInstanceOf (typeof (RequiredModifierType), string_modreq); + Assert.AreEqual (modreq, string_modreq.ModifierType); + } + + [Test] + public void MakePinnedType () + { + var byte_array = GetTypeReference (typeof (byte [])); + + var pinned_byte_array = byte_array.MakePinnedType (); + + Assert.IsInstanceOf (typeof (PinnedType), pinned_byte_array); + } + + [Test] + public void MakeSentinelType () + { + var @string = GetTypeReference (typeof (string)); + + var string_sentinel = @string.MakeSentinelType (); + + Assert.IsInstanceOf (typeof (SentinelType), string_sentinel); + } + + class Foo {} + + [Test] + public void MakeGenericInstanceType () + { + var foo = GetTypeReference (typeof (Foo<,>)); + var @string = GetTypeReference (typeof (string)); + var @int = GetTypeReference (typeof (int)); + + var foo_string_int = foo.MakeGenericInstanceType (@string, @int); + + Assert.IsInstanceOf (typeof (GenericInstanceType), foo_string_int); + Assert.AreEqual (2, foo_string_int.GenericArguments.Count); + Assert.AreEqual (@string, foo_string_int.GenericArguments [0]); + Assert.AreEqual (@int, foo_string_int.GenericArguments [1]); + } + + static TypeReference GetTypeReference (Type type) + { + return ModuleDefinition.ReadModule (typeof (TypeReferenceRocksTests).Module.FullyQualifiedName).Import (type); + } + } +} \ No newline at end of file diff --git a/external/cecil-legacy/rocks/Test/Resources/cs/Types.cs b/external/cecil-legacy/rocks/Test/Resources/cs/Types.cs new file mode 100755 index 0000000000..ba046554bb --- /dev/null +++ b/external/cecil-legacy/rocks/Test/Resources/cs/Types.cs @@ -0,0 +1,14 @@ +public class Foo { + + public class Bar { + } + + public class Gazonk { + + public class Baz { + } + } +} + +public class Pan { +} diff --git a/external/cecil/symbols/mdb/.gitignore b/external/cecil-legacy/symbols/mdb/.gitignore similarity index 100% rename from external/cecil/symbols/mdb/.gitignore rename to external/cecil-legacy/symbols/mdb/.gitignore diff --git a/external/cecil-legacy/symbols/mdb/Mono.Cecil.Mdb.csproj b/external/cecil-legacy/symbols/mdb/Mono.Cecil.Mdb.csproj new file mode 100644 index 0000000000..44c931e304 --- /dev/null +++ b/external/cecil-legacy/symbols/mdb/Mono.Cecil.Mdb.csproj @@ -0,0 +1,103 @@ + + + + net_4_0_Debug + AnyCPU + 9.0.30729 + 2.0 + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD} + Library + Properties + Mono.Cecil.Mdb + Mono.Cecil.Mdb + 512 + true + ..\..\mono.snk + + + true + full + false + ..\..\bin\net_2_0_Debug\ + DEBUG;TRACE;CECIL + prompt + 4 + v2.0 + + + pdbonly + true + ..\..\bin\net_2_0_Release\ + TRACE;CECIL + prompt + 4 + v2.0 + + + true + full + false + ..\..\bin\net_3_5_Debug\ + DEBUG;TRACE;CECIL;NET_3_5 + prompt + 4 + v3.5 + + + pdbonly + true + ..\..\bin\net_3_5_Release\ + TRACE;CECIL;NET_3_5 + prompt + 4 + v3.5 + + + true + full + false + ..\..\bin\net_4_0_Debug\ + DEBUG;TRACE;CECIL;NET_3_5;NET_4_0 + prompt + 4 + v4.0 + + + pdbonly + true + ..\..\bin\net_4_0_Release\ + TRACE;CECIL;NET_3_5;NET_4_0 + prompt + 4 + v4.0 + + + + + + + + + + {D68133BD-1E63-496E-9EDE-4FBDBF77B486} + Mono.Cecil + + + + + + + + + + + + + + \ No newline at end of file diff --git a/external/cecil-legacy/symbols/mdb/Mono.Cecil.Mdb/AssemblyInfo.cs b/external/cecil-legacy/symbols/mdb/Mono.Cecil.Mdb/AssemblyInfo.cs new file mode 100644 index 0000000000..8186b506bc --- /dev/null +++ b/external/cecil-legacy/symbols/mdb/Mono.Cecil.Mdb/AssemblyInfo.cs @@ -0,0 +1,41 @@ +// +// AssemblyInfo.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Reflection; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle ("Mono.Cecil.Mdb")] +[assembly: AssemblyProduct ("Mono.Cecil")] +[assembly: AssemblyCopyright ("Copyright © 2008 - 2011 Jb Evain")] + +[assembly: CLSCompliant (false)] +[assembly: ComVisible (false)] + +[assembly: AssemblyVersion ("0.9.5.0")] +[assembly: AssemblyFileVersion ("0.9.5.0")] diff --git a/external/cecil-legacy/symbols/mdb/Mono.Cecil.Mdb/MdbReader.cs b/external/cecil-legacy/symbols/mdb/Mono.Cecil.Mdb/MdbReader.cs new file mode 100644 index 0000000000..2440a6642b --- /dev/null +++ b/external/cecil-legacy/symbols/mdb/Mono.Cecil.Mdb/MdbReader.cs @@ -0,0 +1,222 @@ +// +// MdbReader.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Collections.Generic; +using System.IO; + +using Mono.Cecil.Cil; +using Mono.Collections.Generic; +using Mono.CompilerServices.SymbolWriter; + +namespace Mono.Cecil.Mdb { + + public class MdbReaderProvider : ISymbolReaderProvider { + + public ISymbolReader GetSymbolReader (ModuleDefinition module, string fileName) + { + return new MdbReader (module, MonoSymbolFile.ReadSymbolFile (module, fileName)); + } + + public ISymbolReader GetSymbolReader (ModuleDefinition module, Stream symbolStream) + { + throw new NotImplementedException (); + } + } + + public class MdbReader : ISymbolReader { + + readonly ModuleDefinition module; + readonly MonoSymbolFile symbol_file; + readonly Dictionary documents; + + public MdbReader (ModuleDefinition module, MonoSymbolFile symFile) + { + this.module = module; + this.symbol_file = symFile; + this.documents = new Dictionary (); + } + + public bool ProcessDebugHeader (ImageDebugDirectory directory, byte [] header) + { + return symbol_file.Guid == module.Mvid; + } + + public void Read (MethodBody body, InstructionMapper mapper) + { + var method_token = body.Method.MetadataToken; + var entry = symbol_file.GetMethodByToken (method_token.ToInt32 ()); + if (entry == null) + return; + + var scopes = ReadScopes (entry, body, mapper); + ReadLineNumbers (entry, mapper); + ReadLocalVariables (entry, body, scopes); + } + + static void ReadLocalVariables (MethodEntry entry, MethodBody body, Scope [] scopes) + { + var locals = entry.GetLocals (); + + foreach (var local in locals) { + if (local.Index < 0 || local.Index >= body.Variables.Count) // Mono 2.6 emits wrong local infos for iterators + continue; + + var variable = body.Variables [local.Index]; + variable.Name = local.Name; + + var index = local.BlockIndex; + if (index < 0 || index >= scopes.Length) + continue; + + var scope = scopes [index]; + if (scope == null) + continue; + + scope.Variables.Add (variable); + } + } + + void ReadLineNumbers (MethodEntry entry, InstructionMapper mapper) + { + Document document = null; + var table = entry.GetLineNumberTable (); + + foreach (var line in table.LineNumbers) { + var instruction = mapper (line.Offset); + if (instruction == null) + continue; + + if (document == null) + document = GetDocument (entry.CompileUnit.SourceFile); + + instruction.SequencePoint = new SequencePoint (document) { + StartLine = line.Row, + EndLine = line.Row, + }; + } + } + + Document GetDocument (SourceFileEntry file) + { + var file_name = file.FileName; + + Document document; + if (documents.TryGetValue (file_name, out document)) + return document; + + document = new Document (file_name); + documents.Add (file_name, document); + + return document; + } + + static Scope [] ReadScopes (MethodEntry entry, MethodBody body, InstructionMapper mapper) + { + var blocks = entry.GetCodeBlocks (); + var scopes = new Scope [blocks.Length]; + + foreach (var block in blocks) { + if (block.BlockType != CodeBlockEntry.Type.Lexical) + continue; + + var scope = new Scope (); + scope.Start = mapper (block.StartOffset); + scope.End = mapper (block.EndOffset); + + scopes [block.Index] = scope; + + if (body.Scope == null) + body.Scope = scope; + + if (!AddScope (body.Scope, scope)) + body.Scope = scope; + } + + return scopes; + } + + static bool AddScope (Scope provider, Scope scope) + { + foreach (var sub_scope in provider.Scopes) { + if (AddScope (sub_scope, scope)) + return true; + + if (scope.Start.Offset >= sub_scope.Start.Offset && scope.End.Offset <= sub_scope.End.Offset) { + sub_scope.Scopes.Add (scope); + return true; + } + } + + return false; + } + + public void Read (MethodSymbols symbols) + { + var entry = symbol_file.GetMethodByToken (symbols.MethodToken.ToInt32 ()); + if (entry == null) + return; + + ReadLineNumbers (entry, symbols); + ReadLocalVariables (entry, symbols); + } + + void ReadLineNumbers (MethodEntry entry, MethodSymbols symbols) + { + var table = entry.GetLineNumberTable (); + var lines = table.LineNumbers; + + var instructions = symbols.instructions = new Collection (lines.Length); + + for (int i = 0; i < lines.Length; i++) { + var line = lines [i]; + + instructions.Add (new InstructionSymbol (line.Offset, new SequencePoint (GetDocument (entry.CompileUnit.SourceFile)) { + StartLine = line.Row, + EndLine = line.Row, + })); + } + } + + static void ReadLocalVariables (MethodEntry entry, MethodSymbols symbols) + { + foreach (var local in entry.GetLocals ()) { + if (local.Index < 0 || local.Index >= symbols.Variables.Count) // Mono 2.6 emits wrong local infos for iterators + continue; + + var variable = symbols.Variables [local.Index]; + variable.Name = local.Name; + } + } + + public void Dispose () + { + symbol_file.Dispose (); + } + } +} diff --git a/external/cecil-legacy/symbols/mdb/Mono.Cecil.Mdb/MdbWriter.cs b/external/cecil-legacy/symbols/mdb/Mono.Cecil.Mdb/MdbWriter.cs new file mode 100644 index 0000000000..6f4aa20e39 --- /dev/null +++ b/external/cecil-legacy/symbols/mdb/Mono.Cecil.Mdb/MdbWriter.cs @@ -0,0 +1,251 @@ +// +// MdbWriter.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Collections.Generic; +using System.IO; + +using Mono.Cecil.Cil; +using Mono.Collections.Generic; +using Mono.CompilerServices.SymbolWriter; + +namespace Mono.Cecil.Mdb { + +#if !READ_ONLY + public class MdbWriterProvider : ISymbolWriterProvider { + + public ISymbolWriter GetSymbolWriter (ModuleDefinition module, string fileName) + { + return new MdbWriter (module.Mvid, fileName); + } + + public ISymbolWriter GetSymbolWriter (ModuleDefinition module, Stream symbolStream) + { + throw new NotImplementedException (); + } + } + + public class MdbWriter : ISymbolWriter { + + readonly Guid mvid; + readonly MonoSymbolWriter writer; + readonly Dictionary source_files; + + public MdbWriter (Guid mvid, string assembly) + { + this.mvid = mvid; + this.writer = new MonoSymbolWriter (assembly); + this.source_files = new Dictionary (); + } + + static Collection GetInstructions (MethodBody body) + { + var instructions = new Collection (); + foreach (var instruction in body.Instructions) + if (instruction.SequencePoint != null) + instructions.Add (instruction); + + return instructions; + } + + SourceFile GetSourceFile (Document document) + { + var url = document.Url; + + SourceFile source_file; + if (source_files.TryGetValue (url, out source_file)) + return source_file; + + var entry = writer.DefineDocument (url); + var compile_unit = writer.DefineCompilationUnit (entry); + + source_file = new SourceFile (compile_unit, entry); + source_files.Add (url, source_file); + return source_file; + } + + void Populate (Collection instructions, int [] offsets, + int [] startRows, int [] startCols, out SourceFile file) + { + SourceFile source_file = null; + + for (int i = 0; i < instructions.Count; i++) { + var instruction = instructions [i]; + offsets [i] = instruction.Offset; + + var sequence_point = instruction.SequencePoint; + if (source_file == null) + source_file = GetSourceFile (sequence_point.Document); + + startRows [i] = sequence_point.StartLine; + startCols [i] = sequence_point.StartColumn; + } + + file = source_file; + } + + public void Write (MethodBody body) + { + var method = new SourceMethod (body.Method); + + var instructions = GetInstructions (body); + int count = instructions.Count; + if (count == 0) + return; + + var offsets = new int [count]; + var start_rows = new int [count]; + var start_cols = new int [count]; + + SourceFile file; + Populate (instructions, offsets, start_rows, start_cols, out file); + + var builder = writer.OpenMethod (file.CompilationUnit, 0, method); + + for (int i = 0; i < count; i++) + builder.MarkSequencePoint ( + offsets [i], + file.CompilationUnit.SourceFile, + start_rows [i], + start_cols [i], + false); + + if (body.HasVariables) + AddVariables (body.Variables); + + writer.CloseMethod (); + } + + readonly static byte [] empty_header = new byte [0]; + + public bool GetDebugHeader (out ImageDebugDirectory directory, out byte [] header) + { + directory = new ImageDebugDirectory (); + header = empty_header; + return false; + } + + void AddVariables (IList variables) + { + for (int i = 0; i < variables.Count; i++) { + var variable = variables [i]; + writer.DefineLocalVariable (i, variable.Name); + } + } + + public void Write (MethodSymbols symbols) + { + var method = new SourceMethodSymbol (symbols); + + var file = GetSourceFile (symbols.Instructions [0].SequencePoint.Document); + var builder = writer.OpenMethod (file.CompilationUnit, 0, method); + var count = symbols.Instructions.Count; + + for (int i = 0; i < count; i++) { + var instruction = symbols.Instructions [i]; + var sequence_point = instruction.SequencePoint; + + builder.MarkSequencePoint ( + instruction.Offset, + GetSourceFile (sequence_point.Document).CompilationUnit.SourceFile, + sequence_point.StartLine, + sequence_point.EndLine, + false); + } + + if (symbols.HasVariables) + AddVariables (symbols.Variables); + + writer.CloseMethod (); + } + + public void Dispose () + { + writer.WriteSymbolFile (mvid); + } + + class SourceFile : ISourceFile { + + readonly CompileUnitEntry compilation_unit; + readonly SourceFileEntry entry; + + public SourceFileEntry Entry { + get { return entry; } + } + + public CompileUnitEntry CompilationUnit { + get { return compilation_unit; } + } + + public SourceFile (CompileUnitEntry comp_unit, SourceFileEntry entry) + { + this.compilation_unit = comp_unit; + this.entry = entry; + } + } + + class SourceMethodSymbol : IMethodDef { + + readonly string name; + readonly int token; + + public string Name { + get { return name;} + } + + public int Token { + get { return token; } + } + + public SourceMethodSymbol (MethodSymbols symbols) + { + name = symbols.MethodName; + token = symbols.MethodToken.ToInt32 (); + } + } + + class SourceMethod : IMethodDef { + + readonly MethodDefinition method; + + public string Name { + get { return method.Name; } + } + + public int Token { + get { return method.MetadataToken.ToInt32 (); } + } + + public SourceMethod (MethodDefinition method) + { + this.method = method; + } + } + } +#endif +} diff --git a/external/cecil-legacy/symbols/mdb/Mono.CompilerServices.SymbolWriter/MonoSymbolFile.cs b/external/cecil-legacy/symbols/mdb/Mono.CompilerServices.SymbolWriter/MonoSymbolFile.cs new file mode 100644 index 0000000000..6ad39d237b --- /dev/null +++ b/external/cecil-legacy/symbols/mdb/Mono.CompilerServices.SymbolWriter/MonoSymbolFile.cs @@ -0,0 +1,738 @@ +// +// Mono.CSharp.Debugger/MonoSymbolFile.cs +// +// Author: +// Martin Baulig (martin@ximian.com) +// +// (C) 2003 Ximian, Inc. http://www.ximian.com +// + +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Reflection; +using SRE = System.Reflection.Emit; +using System.Collections.Generic; +using System.Text; +using System.Threading; +using System.IO; + +namespace Mono.CompilerServices.SymbolWriter +{ + public class MonoSymbolFileException : Exception + { + public MonoSymbolFileException () + : base () + { } + + public MonoSymbolFileException (string message, params object[] args) + : base (String.Format (message, args)) + { } + } + + internal class MyBinaryWriter : BinaryWriter + { + public MyBinaryWriter (Stream stream) + : base (stream) + { } + + public void WriteLeb128 (int value) + { + base.Write7BitEncodedInt (value); + } + } + + internal class MyBinaryReader : BinaryReader + { + public MyBinaryReader (Stream stream) + : base (stream) + { } + + public int ReadLeb128 () + { + return base.Read7BitEncodedInt (); + } + + public string ReadString (int offset) + { + long old_pos = BaseStream.Position; + BaseStream.Position = offset; + + string text = ReadString (); + + BaseStream.Position = old_pos; + return text; + } + } + + public interface ISourceFile + { + SourceFileEntry Entry { + get; + } + } + + public interface ICompileUnit + { + CompileUnitEntry Entry { + get; + } + } + + public interface IMethodDef + { + string Name { + get; + } + + int Token { + get; + } + } + +#if !CECIL + internal class MonoDebuggerSupport + { + static GetMethodTokenFunc get_method_token; + static GetGuidFunc get_guid; + static GetLocalIndexFunc get_local_index; + + delegate int GetMethodTokenFunc (MethodBase method); + delegate Guid GetGuidFunc (Module module); + delegate int GetLocalIndexFunc (SRE.LocalBuilder local); + + static Delegate create_delegate (Type type, Type delegate_type, string name) + { + MethodInfo mi = type.GetMethod (name, BindingFlags.Static | + BindingFlags.NonPublic); + if (mi == null) + throw new Exception ("Can't find " + name); + + return Delegate.CreateDelegate (delegate_type, mi); + } + + static MonoDebuggerSupport () + { + get_method_token = (GetMethodTokenFunc) create_delegate ( + typeof (Assembly), typeof (GetMethodTokenFunc), + "MonoDebugger_GetMethodToken"); + + get_guid = (GetGuidFunc) create_delegate ( + typeof (Module), typeof (GetGuidFunc), "Mono_GetGuid"); + + get_local_index = (GetLocalIndexFunc) create_delegate ( + typeof (SRE.LocalBuilder), typeof (GetLocalIndexFunc), + "Mono_GetLocalIndex"); + } + + public static int GetMethodToken (MethodBase method) + { + return get_method_token (method); + } + + public static Guid GetGuid (Module module) + { + return get_guid (module); + } + + public static int GetLocalIndex (SRE.LocalBuilder local) + { + return get_local_index (local); + } + } +#endif + + public class MonoSymbolFile : IDisposable + { + List methods = new List (); + List sources = new List (); + List comp_units = new List (); + Dictionary type_hash = new Dictionary (); + Dictionary anonymous_scopes; + + OffsetTable ot; + int last_type_index; + int last_method_index; + int last_namespace_index; + + public readonly string FileName = ""; + public readonly int MajorVersion = OffsetTable.MajorVersion; + public readonly int MinorVersion = OffsetTable.MinorVersion; + + public int NumLineNumbers; + + internal MonoSymbolFile () + { + ot = new OffsetTable (); + } + + internal int AddSource (SourceFileEntry source) + { + sources.Add (source); + return sources.Count; + } + + internal int AddCompileUnit (CompileUnitEntry entry) + { + comp_units.Add (entry); + return comp_units.Count; + } + + internal int DefineType (Type type) + { + int index; + if (type_hash.TryGetValue (type, out index)) + return index; + + index = ++last_type_index; + type_hash.Add (type, index); + return index; + } + + internal void AddMethod (MethodEntry entry) + { + methods.Add (entry); + } + + public MethodEntry DefineMethod (CompileUnitEntry comp_unit, int token, + ScopeVariable[] scope_vars, LocalVariableEntry[] locals, + LineNumberEntry[] lines, CodeBlockEntry[] code_blocks, + string real_name, MethodEntry.Flags flags, + int namespace_id) + { + if (reader != null) + throw new InvalidOperationException (); + + MethodEntry method = new MethodEntry ( + this, comp_unit, token, scope_vars, locals, lines, code_blocks, + real_name, flags, namespace_id); + AddMethod (method); + return method; + } + + internal void DefineAnonymousScope (int id) + { + if (reader != null) + throw new InvalidOperationException (); + + if (anonymous_scopes == null) + anonymous_scopes = new Dictionary (); + + anonymous_scopes.Add (id, new AnonymousScopeEntry (id)); + } + + internal void DefineCapturedVariable (int scope_id, string name, string captured_name, + CapturedVariable.CapturedKind kind) + { + if (reader != null) + throw new InvalidOperationException (); + + AnonymousScopeEntry scope = anonymous_scopes [scope_id]; + scope.AddCapturedVariable (name, captured_name, kind); + } + + internal void DefineCapturedScope (int scope_id, int id, string captured_name) + { + if (reader != null) + throw new InvalidOperationException (); + + AnonymousScopeEntry scope = anonymous_scopes [scope_id]; + scope.AddCapturedScope (id, captured_name); + } + + internal int GetNextTypeIndex () + { + return ++last_type_index; + } + + internal int GetNextMethodIndex () + { + return ++last_method_index; + } + + internal int GetNextNamespaceIndex () + { + return ++last_namespace_index; + } + + void Write (MyBinaryWriter bw, Guid guid) + { + // Magic number and file version. + bw.Write (OffsetTable.Magic); + bw.Write (MajorVersion); + bw.Write (MinorVersion); + + bw.Write (guid.ToByteArray ()); + + // + // Offsets of file sections; we must write this after we're done + // writing the whole file, so we just reserve the space for it here. + // + long offset_table_offset = bw.BaseStream.Position; + ot.Write (bw, MajorVersion, MinorVersion); + + // + // Sort the methods according to their tokens and update their index. + // + methods.Sort (); + for (int i = 0; i < methods.Count; i++) + ((MethodEntry) methods [i]).Index = i + 1; + + // + // Write data sections. + // + ot.DataSectionOffset = (int) bw.BaseStream.Position; + foreach (SourceFileEntry source in sources) + source.WriteData (bw); + foreach (CompileUnitEntry comp_unit in comp_units) + comp_unit.WriteData (bw); + foreach (MethodEntry method in methods) + method.WriteData (this, bw); + ot.DataSectionSize = (int) bw.BaseStream.Position - ot.DataSectionOffset; + + // + // Write the method index table. + // + ot.MethodTableOffset = (int) bw.BaseStream.Position; + for (int i = 0; i < methods.Count; i++) { + MethodEntry entry = (MethodEntry) methods [i]; + entry.Write (bw); + } + ot.MethodTableSize = (int) bw.BaseStream.Position - ot.MethodTableOffset; + + // + // Write source table. + // + ot.SourceTableOffset = (int) bw.BaseStream.Position; + for (int i = 0; i < sources.Count; i++) { + SourceFileEntry source = (SourceFileEntry) sources [i]; + source.Write (bw); + } + ot.SourceTableSize = (int) bw.BaseStream.Position - ot.SourceTableOffset; + + // + // Write compilation unit table. + // + ot.CompileUnitTableOffset = (int) bw.BaseStream.Position; + for (int i = 0; i < comp_units.Count; i++) { + CompileUnitEntry unit = (CompileUnitEntry) comp_units [i]; + unit.Write (bw); + } + ot.CompileUnitTableSize = (int) bw.BaseStream.Position - ot.CompileUnitTableOffset; + + // + // Write anonymous scope table. + // + ot.AnonymousScopeCount = anonymous_scopes != null ? anonymous_scopes.Count : 0; + ot.AnonymousScopeTableOffset = (int) bw.BaseStream.Position; + if (anonymous_scopes != null) { + foreach (AnonymousScopeEntry scope in anonymous_scopes.Values) + scope.Write (bw); + } + ot.AnonymousScopeTableSize = (int) bw.BaseStream.Position - ot.AnonymousScopeTableOffset; + + // + // Fixup offset table. + // + ot.TypeCount = last_type_index; + ot.MethodCount = methods.Count; + ot.SourceCount = sources.Count; + ot.CompileUnitCount = comp_units.Count; + + // + // Write offset table. + // + ot.TotalFileSize = (int) bw.BaseStream.Position; + bw.Seek ((int) offset_table_offset, SeekOrigin.Begin); + ot.Write (bw, MajorVersion, MinorVersion); + bw.Seek (0, SeekOrigin.End); + +#if false + Console.WriteLine ("TOTAL: {0} line numbes, {1} bytes, extended {2} bytes, " + + "{3} methods.", NumLineNumbers, LineNumberSize, + ExtendedLineNumberSize, methods.Count); +#endif + } + + public void CreateSymbolFile (Guid guid, FileStream fs) + { + if (reader != null) + throw new InvalidOperationException (); + + Write (new MyBinaryWriter (fs), guid); + } + + MyBinaryReader reader; + Dictionary source_file_hash; + Dictionary compile_unit_hash; + + List method_list; + Dictionary method_token_hash; + Dictionary source_name_hash; + + Guid guid; + + MonoSymbolFile (string filename) + { + this.FileName = filename; + FileStream stream = new FileStream (filename, FileMode.Open, FileAccess.Read); + reader = new MyBinaryReader (stream); + + try { + long magic = reader.ReadInt64 (); + int major_version = reader.ReadInt32 (); + int minor_version = reader.ReadInt32 (); + + if (magic != OffsetTable.Magic) + throw new MonoSymbolFileException ( + "Symbol file `{0}' is not a valid " + + "Mono symbol file", filename); + if (major_version != OffsetTable.MajorVersion) + throw new MonoSymbolFileException ( + "Symbol file `{0}' has version {1}, " + + "but expected {2}", filename, major_version, + OffsetTable.MajorVersion); + if (minor_version != OffsetTable.MinorVersion) + throw new MonoSymbolFileException ( + "Symbol file `{0}' has version {1}.{2}, " + + "but expected {3}.{4}", filename, major_version, + minor_version, OffsetTable.MajorVersion, + OffsetTable.MinorVersion); + + MajorVersion = major_version; + MinorVersion = minor_version; + guid = new Guid (reader.ReadBytes (16)); + + ot = new OffsetTable (reader, major_version, minor_version); + } catch { + throw new MonoSymbolFileException ( + "Cannot read symbol file `{0}'", filename); + } + + source_file_hash = new Dictionary (); + compile_unit_hash = new Dictionary (); + } + + void CheckGuidMatch (Guid other, string filename, string assembly) + { + if (other == guid) + return; + + throw new MonoSymbolFileException ( + "Symbol file `{0}' does not match assembly `{1}'", + filename, assembly); + } + +#if CECIL + protected MonoSymbolFile (string filename, Mono.Cecil.ModuleDefinition module) + : this (filename) + { + // Check that the MDB file matches the module, if we have been + // passed a module. + if (module == null) + return; + + CheckGuidMatch (module.Mvid, filename, module.FullyQualifiedName); + } + + public static MonoSymbolFile ReadSymbolFile (Mono.Cecil.ModuleDefinition module) + { + return ReadSymbolFile (module, module.FullyQualifiedName); + } + + public static MonoSymbolFile ReadSymbolFile (Mono.Cecil.ModuleDefinition module, string filename) + { + string name = filename + ".mdb"; + + return new MonoSymbolFile (name, module); + } +#else + protected MonoSymbolFile (string filename, Assembly assembly) : this (filename) + { + // Check that the MDB file matches the assembly, if we have been + // passed an assembly. + if (assembly == null) + return; + + Module[] modules = assembly.GetModules (); + Guid assembly_guid = MonoDebuggerSupport.GetGuid (modules [0]); + + CheckGuidMatch (assembly_guid, filename, assembly.Location); + } + + public static MonoSymbolFile ReadSymbolFile (Assembly assembly) + { + string filename = assembly.Location; + string name = filename + ".mdb"; + + return new MonoSymbolFile (name, assembly); + } +#endif + + public static MonoSymbolFile ReadSymbolFile (string mdbFilename) + { + return new MonoSymbolFile (mdbFilename); + } + + public int CompileUnitCount { + get { return ot.CompileUnitCount; } + } + + public int SourceCount { + get { return ot.SourceCount; } + } + + public int MethodCount { + get { return ot.MethodCount; } + } + + public int TypeCount { + get { return ot.TypeCount; } + } + + public int AnonymousScopeCount { + get { return ot.AnonymousScopeCount; } + } + + public int NamespaceCount { + get { return last_namespace_index; } + } + + public Guid Guid { + get { return guid; } + } + + public OffsetTable OffsetTable { + get { return ot; } + } + + internal int LineNumberCount = 0; + internal int LocalCount = 0; + internal int StringSize = 0; + + internal int LineNumberSize = 0; + internal int ExtendedLineNumberSize = 0; + + public SourceFileEntry GetSourceFile (int index) + { + if ((index < 1) || (index > ot.SourceCount)) + throw new ArgumentException (); + if (reader == null) + throw new InvalidOperationException (); + + lock (this) { + SourceFileEntry source; + if (source_file_hash.TryGetValue (index, out source)) + return source; + + long old_pos = reader.BaseStream.Position; + + reader.BaseStream.Position = ot.SourceTableOffset + + SourceFileEntry.Size * (index - 1); + source = new SourceFileEntry (this, reader); + source_file_hash.Add (index, source); + + reader.BaseStream.Position = old_pos; + return source; + } + } + + public SourceFileEntry[] Sources { + get { + if (reader == null) + throw new InvalidOperationException (); + + SourceFileEntry[] retval = new SourceFileEntry [SourceCount]; + for (int i = 0; i < SourceCount; i++) + retval [i] = GetSourceFile (i + 1); + return retval; + } + } + + public CompileUnitEntry GetCompileUnit (int index) + { + if ((index < 1) || (index > ot.CompileUnitCount)) + throw new ArgumentException (); + if (reader == null) + throw new InvalidOperationException (); + + lock (this) { + CompileUnitEntry unit; + if (compile_unit_hash.TryGetValue (index, out unit)) + return unit; + + long old_pos = reader.BaseStream.Position; + + reader.BaseStream.Position = ot.CompileUnitTableOffset + + CompileUnitEntry.Size * (index - 1); + unit = new CompileUnitEntry (this, reader); + compile_unit_hash.Add (index, unit); + + reader.BaseStream.Position = old_pos; + return unit; + } + } + + public CompileUnitEntry[] CompileUnits { + get { + if (reader == null) + throw new InvalidOperationException (); + + CompileUnitEntry[] retval = new CompileUnitEntry [CompileUnitCount]; + for (int i = 0; i < CompileUnitCount; i++) + retval [i] = GetCompileUnit (i + 1); + return retval; + } + } + + void read_methods () + { + lock (this) { + if (method_token_hash != null) + return; + + method_token_hash = new Dictionary (); + method_list = new List (); + + long old_pos = reader.BaseStream.Position; + reader.BaseStream.Position = ot.MethodTableOffset; + + for (int i = 0; i < MethodCount; i++) { + MethodEntry entry = new MethodEntry (this, reader, i + 1); + method_token_hash.Add (entry.Token, entry); + method_list.Add (entry); + } + + reader.BaseStream.Position = old_pos; + } + } + + public MethodEntry GetMethodByToken (int token) + { + if (reader == null) + throw new InvalidOperationException (); + + lock (this) { + read_methods (); + MethodEntry me; + method_token_hash.TryGetValue (token, out me); + return me; + } + } + + public MethodEntry GetMethod (int index) + { + if ((index < 1) || (index > ot.MethodCount)) + throw new ArgumentException (); + if (reader == null) + throw new InvalidOperationException (); + + lock (this) { + read_methods (); + return (MethodEntry) method_list [index - 1]; + } + } + + public MethodEntry[] Methods { + get { + if (reader == null) + throw new InvalidOperationException (); + + lock (this) { + read_methods (); + MethodEntry[] retval = new MethodEntry [MethodCount]; + method_list.CopyTo (retval, 0); + return retval; + } + } + } + + public int FindSource (string file_name) + { + if (reader == null) + throw new InvalidOperationException (); + + lock (this) { + if (source_name_hash == null) { + source_name_hash = new Dictionary (); + + for (int i = 0; i < ot.SourceCount; i++) { + SourceFileEntry source = GetSourceFile (i + 1); + source_name_hash.Add (source.FileName, i); + } + } + + int value; + if (!source_name_hash.TryGetValue (file_name, out value)) + return -1; + return value; + } + } + + public AnonymousScopeEntry GetAnonymousScope (int id) + { + if (reader == null) + throw new InvalidOperationException (); + + AnonymousScopeEntry scope; + lock (this) { + if (anonymous_scopes != null) { + anonymous_scopes.TryGetValue (id, out scope); + return scope; + } + + anonymous_scopes = new Dictionary (); + reader.BaseStream.Position = ot.AnonymousScopeTableOffset; + for (int i = 0; i < ot.AnonymousScopeCount; i++) { + scope = new AnonymousScopeEntry (reader); + anonymous_scopes.Add (scope.ID, scope); + } + + return anonymous_scopes [id]; + } + } + + internal MyBinaryReader BinaryReader { + get { + if (reader == null) + throw new InvalidOperationException (); + + return reader; + } + } + + public void Dispose () + { + Dispose (true); + } + + protected virtual void Dispose (bool disposing) + { + if (disposing) { + if (reader != null) { + reader.Close (); + reader = null; + } + } + } + } +} diff --git a/external/cecil-legacy/symbols/mdb/Mono.CompilerServices.SymbolWriter/MonoSymbolTable.cs b/external/cecil-legacy/symbols/mdb/Mono.CompilerServices.SymbolWriter/MonoSymbolTable.cs new file mode 100644 index 0000000000..c170150ce4 --- /dev/null +++ b/external/cecil-legacy/symbols/mdb/Mono.CompilerServices.SymbolWriter/MonoSymbolTable.cs @@ -0,0 +1,1376 @@ +// +// Mono.CSharp.Debugger/MonoSymbolTable.cs +// +// Author: +// Martin Baulig (martin@ximian.com) +// +// (C) 2002 Ximian, Inc. http://www.ximian.com +// + +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Security.Cryptography; +using System.Collections.Generic; +using System.Text; +using System.IO; + +// +// Parts which are actually written into the symbol file are marked with +// +// #region This is actually written to the symbol file +// #endregion +// +// Please do not modify these regions without previously talking to me. +// +// All changes to the file format must be synchronized in several places: +// +// a) The fields in these regions (and their order) must match the actual +// contents of the symbol file. +// +// This helps people to understand the symbol file format without reading +// too much source code, ie. you look at the appropriate region and then +// you know what's actually in the file. +// +// It is also required to help me enforce b). +// +// b) The regions must be kept in sync with the unmanaged code in +// mono/metadata/debug-mono-symfile.h +// +// When making changes to the file format, you must also increase two version +// numbers: +// +// i) OffsetTable.Version in this file. +// ii) MONO_SYMBOL_FILE_VERSION in mono/metadata/debug-mono-symfile.h +// +// After doing so, recompile everything, including the debugger. Symbol files +// with different versions are incompatible to each other and the debugger and +// the runtime enfore this, so you need to recompile all your assemblies after +// changing the file format. +// + +namespace Mono.CompilerServices.SymbolWriter +{ + public class OffsetTable + { + public const int MajorVersion = 50; + public const int MinorVersion = 0; + public const long Magic = 0x45e82623fd7fa614; + + #region This is actually written to the symbol file + public int TotalFileSize; + public int DataSectionOffset; + public int DataSectionSize; + public int CompileUnitCount; + public int CompileUnitTableOffset; + public int CompileUnitTableSize; + public int SourceCount; + public int SourceTableOffset; + public int SourceTableSize; + public int MethodCount; + public int MethodTableOffset; + public int MethodTableSize; + public int TypeCount; + public int AnonymousScopeCount; + public int AnonymousScopeTableOffset; + public int AnonymousScopeTableSize; + + [Flags] + public enum Flags + { + IsAspxSource = 1, + WindowsFileNames = 2 + } + + public Flags FileFlags; + + public int LineNumberTable_LineBase = LineNumberTable.Default_LineBase; + public int LineNumberTable_LineRange = LineNumberTable.Default_LineRange; + public int LineNumberTable_OpcodeBase = LineNumberTable.Default_OpcodeBase; + #endregion + + internal OffsetTable () + { + int platform = (int) Environment.OSVersion.Platform; + if ((platform != 4) && (platform != 128)) + FileFlags |= Flags.WindowsFileNames; + } + + internal OffsetTable (BinaryReader reader, int major_version, int minor_version) + { + TotalFileSize = reader.ReadInt32 (); + DataSectionOffset = reader.ReadInt32 (); + DataSectionSize = reader.ReadInt32 (); + CompileUnitCount = reader.ReadInt32 (); + CompileUnitTableOffset = reader.ReadInt32 (); + CompileUnitTableSize = reader.ReadInt32 (); + SourceCount = reader.ReadInt32 (); + SourceTableOffset = reader.ReadInt32 (); + SourceTableSize = reader.ReadInt32 (); + MethodCount = reader.ReadInt32 (); + MethodTableOffset = reader.ReadInt32 (); + MethodTableSize = reader.ReadInt32 (); + TypeCount = reader.ReadInt32 (); + + AnonymousScopeCount = reader.ReadInt32 (); + AnonymousScopeTableOffset = reader.ReadInt32 (); + AnonymousScopeTableSize = reader.ReadInt32 (); + + LineNumberTable_LineBase = reader.ReadInt32 (); + LineNumberTable_LineRange = reader.ReadInt32 (); + LineNumberTable_OpcodeBase = reader.ReadInt32 (); + + FileFlags = (Flags) reader.ReadInt32 (); + } + + internal void Write (BinaryWriter bw, int major_version, int minor_version) + { + bw.Write (TotalFileSize); + bw.Write (DataSectionOffset); + bw.Write (DataSectionSize); + bw.Write (CompileUnitCount); + bw.Write (CompileUnitTableOffset); + bw.Write (CompileUnitTableSize); + bw.Write (SourceCount); + bw.Write (SourceTableOffset); + bw.Write (SourceTableSize); + bw.Write (MethodCount); + bw.Write (MethodTableOffset); + bw.Write (MethodTableSize); + bw.Write (TypeCount); + + bw.Write (AnonymousScopeCount); + bw.Write (AnonymousScopeTableOffset); + bw.Write (AnonymousScopeTableSize); + + bw.Write (LineNumberTable_LineBase); + bw.Write (LineNumberTable_LineRange); + bw.Write (LineNumberTable_OpcodeBase); + + bw.Write ((int) FileFlags); + } + + public override string ToString () + { + return String.Format ( + "OffsetTable [{0} - {1}:{2} - {3}:{4}:{5} - {6}:{7}:{8} - {9}]", + TotalFileSize, DataSectionOffset, DataSectionSize, SourceCount, + SourceTableOffset, SourceTableSize, MethodCount, MethodTableOffset, + MethodTableSize, TypeCount); + } + } + + public class LineNumberEntry + { + #region This is actually written to the symbol file + public readonly int Row; + public readonly int File; + public readonly int Offset; + public readonly bool IsHidden; + #endregion + + public LineNumberEntry (int file, int row, int offset) + : this (file, row, offset, false) + { } + + public LineNumberEntry (int file, int row, int offset, bool is_hidden) + { + this.File = file; + this.Row = row; + this.Offset = offset; + this.IsHidden = is_hidden; + } + + public static LineNumberEntry Null = new LineNumberEntry (0, 0, 0); + + private class OffsetComparerClass : IComparer + { + public int Compare (LineNumberEntry l1, LineNumberEntry l2) + { + if (l1.Offset < l2.Offset) + return -1; + else if (l1.Offset > l2.Offset) + return 1; + else + return 0; + } + } + + private class RowComparerClass : IComparer + { + public int Compare (LineNumberEntry l1, LineNumberEntry l2) + { + if (l1.Row < l2.Row) + return -1; + else if (l1.Row > l2.Row) + return 1; + else + return 0; + } + } + + public static readonly IComparer OffsetComparer = new OffsetComparerClass (); + public static readonly IComparer RowComparer = new RowComparerClass (); + + public override string ToString () + { + return String.Format ("[Line {0}:{1}:{2}]", File, Row, Offset); + } + } + + public class CodeBlockEntry + { + public int Index; + #region This is actually written to the symbol file + public int Parent; + public Type BlockType; + public int StartOffset; + public int EndOffset; + #endregion + + public enum Type { + Lexical = 1, + CompilerGenerated = 2, + IteratorBody = 3, + IteratorDispatcher = 4 + } + + public CodeBlockEntry (int index, int parent, Type type, int start_offset) + { + this.Index = index; + this.Parent = parent; + this.BlockType = type; + this.StartOffset = start_offset; + } + + internal CodeBlockEntry (int index, MyBinaryReader reader) + { + this.Index = index; + int type_flag = reader.ReadLeb128 (); + BlockType = (Type) (type_flag & 0x3f); + this.Parent = reader.ReadLeb128 (); + this.StartOffset = reader.ReadLeb128 (); + this.EndOffset = reader.ReadLeb128 (); + + /* Reserved for future extensions. */ + if ((type_flag & 0x40) != 0) { + int data_size = reader.ReadInt16 (); + reader.BaseStream.Position += data_size; + } + } + + public void Close (int end_offset) + { + this.EndOffset = end_offset; + } + + internal void Write (MyBinaryWriter bw) + { + bw.WriteLeb128 ((int) BlockType); + bw.WriteLeb128 (Parent); + bw.WriteLeb128 (StartOffset); + bw.WriteLeb128 (EndOffset); + } + + public override string ToString () + { + return String.Format ("[CodeBlock {0}:{1}:{2}:{3}:{4}]", + Index, Parent, BlockType, StartOffset, EndOffset); + } + } + + public struct LocalVariableEntry + { + #region This is actually written to the symbol file + public readonly int Index; + public readonly string Name; + public readonly int BlockIndex; + #endregion + + public LocalVariableEntry (int index, string name, int block) + { + this.Index = index; + this.Name = name; + this.BlockIndex = block; + } + + internal LocalVariableEntry (MonoSymbolFile file, MyBinaryReader reader) + { + Index = reader.ReadLeb128 (); + Name = reader.ReadString (); + BlockIndex = reader.ReadLeb128 (); + } + + internal void Write (MonoSymbolFile file, MyBinaryWriter bw) + { + bw.WriteLeb128 (Index); + bw.Write (Name); + bw.WriteLeb128 (BlockIndex); + } + + public override string ToString () + { + return String.Format ("[LocalVariable {0}:{1}:{2}]", + Name, Index, BlockIndex - 1); + } + } + + public struct CapturedVariable + { + #region This is actually written to the symbol file + public readonly string Name; + public readonly string CapturedName; + public readonly CapturedKind Kind; + #endregion + + public enum CapturedKind : byte + { + Local, + Parameter, + This + } + + public CapturedVariable (string name, string captured_name, + CapturedKind kind) + { + this.Name = name; + this.CapturedName = captured_name; + this.Kind = kind; + } + + internal CapturedVariable (MyBinaryReader reader) + { + Name = reader.ReadString (); + CapturedName = reader.ReadString (); + Kind = (CapturedKind) reader.ReadByte (); + } + + internal void Write (MyBinaryWriter bw) + { + bw.Write (Name); + bw.Write (CapturedName); + bw.Write ((byte) Kind); + } + + public override string ToString () + { + return String.Format ("[CapturedVariable {0}:{1}:{2}]", + Name, CapturedName, Kind); + } + } + + public struct CapturedScope + { + #region This is actually written to the symbol file + public readonly int Scope; + public readonly string CapturedName; + #endregion + + public CapturedScope (int scope, string captured_name) + { + this.Scope = scope; + this.CapturedName = captured_name; + } + + internal CapturedScope (MyBinaryReader reader) + { + Scope = reader.ReadLeb128 (); + CapturedName = reader.ReadString (); + } + + internal void Write (MyBinaryWriter bw) + { + bw.WriteLeb128 (Scope); + bw.Write (CapturedName); + } + + public override string ToString () + { + return String.Format ("[CapturedScope {0}:{1}]", + Scope, CapturedName); + } + } + + public struct ScopeVariable + { + #region This is actually written to the symbol file + public readonly int Scope; + public readonly int Index; + #endregion + + public ScopeVariable (int scope, int index) + { + this.Scope = scope; + this.Index = index; + } + + internal ScopeVariable (MyBinaryReader reader) + { + Scope = reader.ReadLeb128 (); + Index = reader.ReadLeb128 (); + } + + internal void Write (MyBinaryWriter bw) + { + bw.WriteLeb128 (Scope); + bw.WriteLeb128 (Index); + } + + public override string ToString () + { + return String.Format ("[ScopeVariable {0}:{1}]", Scope, Index); + } + } + + public class AnonymousScopeEntry + { + #region This is actually written to the symbol file + public readonly int ID; + #endregion + + List captured_vars = new List (); + List captured_scopes = new List (); + + public AnonymousScopeEntry (int id) + { + this.ID = id; + } + + internal AnonymousScopeEntry (MyBinaryReader reader) + { + ID = reader.ReadLeb128 (); + + int num_captured_vars = reader.ReadLeb128 (); + for (int i = 0; i < num_captured_vars; i++) + captured_vars.Add (new CapturedVariable (reader)); + + int num_captured_scopes = reader.ReadLeb128 (); + for (int i = 0; i < num_captured_scopes; i++) + captured_scopes.Add (new CapturedScope (reader)); + } + + internal void AddCapturedVariable (string name, string captured_name, + CapturedVariable.CapturedKind kind) + { + captured_vars.Add (new CapturedVariable (name, captured_name, kind)); + } + + public CapturedVariable[] CapturedVariables { + get { + CapturedVariable[] retval = new CapturedVariable [captured_vars.Count]; + captured_vars.CopyTo (retval, 0); + return retval; + } + } + + internal void AddCapturedScope (int scope, string captured_name) + { + captured_scopes.Add (new CapturedScope (scope, captured_name)); + } + + public CapturedScope[] CapturedScopes { + get { + CapturedScope[] retval = new CapturedScope [captured_scopes.Count]; + captured_scopes.CopyTo (retval, 0); + return retval; + } + } + + internal void Write (MyBinaryWriter bw) + { + bw.WriteLeb128 (ID); + + bw.WriteLeb128 (captured_vars.Count); + foreach (CapturedVariable cv in captured_vars) + cv.Write (bw); + + bw.WriteLeb128 (captured_scopes.Count); + foreach (CapturedScope cs in captured_scopes) + cs.Write (bw); + } + + public override string ToString () + { + return String.Format ("[AnonymousScope {0}]", ID); + } + } + + public class CompileUnitEntry : ICompileUnit + { + #region This is actually written to the symbol file + public readonly int Index; + int DataOffset; + #endregion + + MonoSymbolFile file; + SourceFileEntry source; + List include_files; + List namespaces; + + bool creating; + + public static int Size { + get { return 8; } + } + + CompileUnitEntry ICompileUnit.Entry { + get { return this; } + } + + public CompileUnitEntry (MonoSymbolFile file, SourceFileEntry source) + { + this.file = file; + this.source = source; + + this.Index = file.AddCompileUnit (this); + + creating = true; + namespaces = new List (); + } + + public void AddFile (SourceFileEntry file) + { + if (!creating) + throw new InvalidOperationException (); + + if (include_files == null) + include_files = new List (); + + include_files.Add (file); + } + + public SourceFileEntry SourceFile { + get { + if (creating) + return source; + + ReadData (); + return source; + } + } + + public int DefineNamespace (string name, string[] using_clauses, int parent) + { + if (!creating) + throw new InvalidOperationException (); + + int index = file.GetNextNamespaceIndex (); + NamespaceEntry ns = new NamespaceEntry (name, index, using_clauses, parent); + namespaces.Add (ns); + return index; + } + + internal void WriteData (MyBinaryWriter bw) + { + DataOffset = (int) bw.BaseStream.Position; + bw.WriteLeb128 (source.Index); + + int count_includes = include_files != null ? include_files.Count : 0; + bw.WriteLeb128 (count_includes); + if (include_files != null) { + foreach (SourceFileEntry entry in include_files) + bw.WriteLeb128 (entry.Index); + } + + bw.WriteLeb128 (namespaces.Count); + foreach (NamespaceEntry ns in namespaces) + ns.Write (file, bw); + } + + internal void Write (BinaryWriter bw) + { + bw.Write (Index); + bw.Write (DataOffset); + } + + internal CompileUnitEntry (MonoSymbolFile file, MyBinaryReader reader) + { + this.file = file; + + Index = reader.ReadInt32 (); + DataOffset = reader.ReadInt32 (); + } + + void ReadData () + { + if (creating) + throw new InvalidOperationException (); + + lock (file) { + if (namespaces != null) + return; + + MyBinaryReader reader = file.BinaryReader; + int old_pos = (int) reader.BaseStream.Position; + + reader.BaseStream.Position = DataOffset; + + int source_idx = reader.ReadLeb128 (); + source = file.GetSourceFile (source_idx); + + int count_includes = reader.ReadLeb128 (); + if (count_includes > 0) { + include_files = new List (); + for (int i = 0; i < count_includes; i++) + include_files.Add (file.GetSourceFile (reader.ReadLeb128 ())); + } + + int count_ns = reader.ReadLeb128 (); + namespaces = new List (); + for (int i = 0; i < count_ns; i ++) + namespaces.Add (new NamespaceEntry (file, reader)); + + reader.BaseStream.Position = old_pos; + } + } + + public NamespaceEntry[] Namespaces { + get { + ReadData (); + NamespaceEntry[] retval = new NamespaceEntry [namespaces.Count]; + namespaces.CopyTo (retval, 0); + return retval; + } + } + + public SourceFileEntry[] IncludeFiles { + get { + ReadData (); + if (include_files == null) + return new SourceFileEntry [0]; + + SourceFileEntry[] retval = new SourceFileEntry [include_files.Count]; + include_files.CopyTo (retval, 0); + return retval; + } + } + } + + public class SourceFileEntry + { + #region This is actually written to the symbol file + public readonly int Index; + int DataOffset; + #endregion + + MonoSymbolFile file; + string file_name; + byte[] guid; + byte[] hash; + bool creating; + bool auto_generated; + + public static int Size { + get { return 8; } + } + + public SourceFileEntry (MonoSymbolFile file, string file_name) + { + this.file = file; + this.file_name = file_name; + this.Index = file.AddSource (this); + + creating = true; + } + + public SourceFileEntry (MonoSymbolFile file, string file_name, + byte[] guid, byte[] checksum) + : this (file, file_name) + { + this.guid = guid; + this.hash = checksum; + } + + internal void WriteData (MyBinaryWriter bw) + { + DataOffset = (int) bw.BaseStream.Position; + bw.Write (file_name); + + if (guid == null) { + guid = Guid.NewGuid ().ToByteArray (); + try { + using (FileStream fs = new FileStream (file_name, FileMode.Open, FileAccess.Read)) { + MD5 md5 = MD5.Create (); + hash = md5.ComputeHash (fs); + } + } catch { + hash = new byte [16]; + } + } + + bw.Write (guid); + bw.Write (hash); + bw.Write ((byte) (auto_generated ? 1 : 0)); + } + + internal void Write (BinaryWriter bw) + { + bw.Write (Index); + bw.Write (DataOffset); + } + + internal SourceFileEntry (MonoSymbolFile file, MyBinaryReader reader) + { + this.file = file; + + Index = reader.ReadInt32 (); + DataOffset = reader.ReadInt32 (); + + int old_pos = (int) reader.BaseStream.Position; + reader.BaseStream.Position = DataOffset; + + file_name = reader.ReadString (); + guid = reader.ReadBytes (16); + hash = reader.ReadBytes (16); + auto_generated = reader.ReadByte () == 1; + + reader.BaseStream.Position = old_pos; + } + + public string FileName { + get { return file_name; } + } + + public bool AutoGenerated { + get { return auto_generated; } + } + + public void SetAutoGenerated () + { + if (!creating) + throw new InvalidOperationException (); + + auto_generated = true; + file.OffsetTable.FileFlags |= OffsetTable.Flags.IsAspxSource; + } + + public bool CheckChecksum () + { + try { + using (FileStream fs = new FileStream (file_name, FileMode.Open)) { + MD5 md5 = MD5.Create (); + byte[] data = md5.ComputeHash (fs); + for (int i = 0; i < 16; i++) + if (data [i] != hash [i]) + return false; + return true; + } + } catch { + return false; + } + } + + public override string ToString () + { + return String.Format ("SourceFileEntry ({0}:{1})", Index, DataOffset); + } + } + + public class LineNumberTable + { + protected LineNumberEntry[] _line_numbers; + public LineNumberEntry[] LineNumbers { + get { return _line_numbers; } + } + + public readonly int LineBase; + public readonly int LineRange; + public readonly byte OpcodeBase; + public readonly int MaxAddressIncrement; + +#region Configurable constants + public const int Default_LineBase = -1; + public const int Default_LineRange = 8; + public const byte Default_OpcodeBase = 9; + + public const bool SuppressDuplicates = true; +#endregion + + public const byte DW_LNS_copy = 1; + public const byte DW_LNS_advance_pc = 2; + public const byte DW_LNS_advance_line = 3; + public const byte DW_LNS_set_file = 4; + public const byte DW_LNS_const_add_pc = 8; + + public const byte DW_LNE_end_sequence = 1; + + // MONO extensions. + public const byte DW_LNE_MONO_negate_is_hidden = 0x40; + + internal const byte DW_LNE_MONO__extensions_start = 0x40; + internal const byte DW_LNE_MONO__extensions_end = 0x7f; + + protected LineNumberTable (MonoSymbolFile file) + { + this.LineBase = file.OffsetTable.LineNumberTable_LineBase; + this.LineRange = file.OffsetTable.LineNumberTable_LineRange; + this.OpcodeBase = (byte) file.OffsetTable.LineNumberTable_OpcodeBase; + this.MaxAddressIncrement = (255 - OpcodeBase) / LineRange; + } + + internal LineNumberTable (MonoSymbolFile file, LineNumberEntry[] lines) + : this (file) + { + this._line_numbers = lines; + } + + internal void Write (MonoSymbolFile file, MyBinaryWriter bw) + { + int start = (int) bw.BaseStream.Position; + + bool last_is_hidden = false; + int last_line = 1, last_offset = 0, last_file = 1; + for (int i = 0; i < LineNumbers.Length; i++) { + int line_inc = LineNumbers [i].Row - last_line; + int offset_inc = LineNumbers [i].Offset - last_offset; + + if (SuppressDuplicates && (i+1 < LineNumbers.Length)) { + if (LineNumbers [i+1].Equals (LineNumbers [i])) + continue; + } + + if (LineNumbers [i].File != last_file) { + bw.Write (DW_LNS_set_file); + bw.WriteLeb128 (LineNumbers [i].File); + last_file = LineNumbers [i].File; + } + + if (LineNumbers [i].IsHidden != last_is_hidden) { + bw.Write ((byte) 0); + bw.Write ((byte) 1); + bw.Write (DW_LNE_MONO_negate_is_hidden); + last_is_hidden = LineNumbers [i].IsHidden; + } + + if (offset_inc >= MaxAddressIncrement) { + if (offset_inc < 2 * MaxAddressIncrement) { + bw.Write (DW_LNS_const_add_pc); + offset_inc -= MaxAddressIncrement; + } else { + bw.Write (DW_LNS_advance_pc); + bw.WriteLeb128 (offset_inc); + offset_inc = 0; + } + } + + if ((line_inc < LineBase) || (line_inc >= LineBase + LineRange)) { + bw.Write (DW_LNS_advance_line); + bw.WriteLeb128 (line_inc); + if (offset_inc != 0) { + bw.Write (DW_LNS_advance_pc); + bw.WriteLeb128 (offset_inc); + } + bw.Write (DW_LNS_copy); + } else { + byte opcode; + opcode = (byte) (line_inc - LineBase + (LineRange * offset_inc) + + OpcodeBase); + bw.Write (opcode); + } + + last_line = LineNumbers [i].Row; + last_offset = LineNumbers [i].Offset; + } + + bw.Write ((byte) 0); + bw.Write ((byte) 1); + bw.Write (DW_LNE_end_sequence); + + file.ExtendedLineNumberSize += (int) bw.BaseStream.Position - start; + } + + internal static LineNumberTable Read (MonoSymbolFile file, MyBinaryReader br) + { + LineNumberTable lnt = new LineNumberTable (file); + lnt.DoRead (file, br); + return lnt; + } + + void DoRead (MonoSymbolFile file, MyBinaryReader br) + { + var lines = new List (); + + bool is_hidden = false, modified = false; + int stm_line = 1, stm_offset = 0, stm_file = 1; + while (true) { + byte opcode = br.ReadByte (); + + if (opcode == 0) { + byte size = br.ReadByte (); + long end_pos = br.BaseStream.Position + size; + opcode = br.ReadByte (); + + if (opcode == DW_LNE_end_sequence) { + if (modified) + lines.Add (new LineNumberEntry ( + stm_file, stm_line, stm_offset, is_hidden)); + break; + } else if (opcode == DW_LNE_MONO_negate_is_hidden) { + is_hidden = !is_hidden; + modified = true; + } else if ((opcode >= DW_LNE_MONO__extensions_start) && + (opcode <= DW_LNE_MONO__extensions_end)) { + ; // reserved for future extensions + } else { + throw new MonoSymbolFileException ( + "Unknown extended opcode {0:x} in LNT ({1})", + opcode, file.FileName); + } + + br.BaseStream.Position = end_pos; + continue; + } else if (opcode < OpcodeBase) { + switch (opcode) { + case DW_LNS_copy: + lines.Add (new LineNumberEntry ( + stm_file, stm_line, stm_offset, is_hidden)); + modified = false; + break; + case DW_LNS_advance_pc: + stm_offset += br.ReadLeb128 (); + modified = true; + break; + case DW_LNS_advance_line: + stm_line += br.ReadLeb128 (); + modified = true; + break; + case DW_LNS_set_file: + stm_file = br.ReadLeb128 (); + modified = true; + break; + case DW_LNS_const_add_pc: + stm_offset += MaxAddressIncrement; + modified = true; + break; + default: + throw new MonoSymbolFileException ( + "Unknown standard opcode {0:x} in LNT", + opcode); + } + } else { + opcode -= OpcodeBase; + + stm_offset += opcode / LineRange; + stm_line += LineBase + (opcode % LineRange); + lines.Add (new LineNumberEntry ( + stm_file, stm_line, stm_offset, is_hidden)); + modified = false; + } + } + + _line_numbers = new LineNumberEntry [lines.Count]; + lines.CopyTo (_line_numbers, 0); + } + + public bool GetMethodBounds (out LineNumberEntry start, out LineNumberEntry end) + { + if (_line_numbers.Length > 1) { + start = _line_numbers [0]; + end = _line_numbers [_line_numbers.Length - 1]; + return true; + } + + start = LineNumberEntry.Null; + end = LineNumberEntry.Null; + return false; + } + } + + public class MethodEntry : IComparable + { + #region This is actually written to the symbol file + public readonly int CompileUnitIndex; + public readonly int Token; + public readonly int NamespaceID; + + int DataOffset; + int LocalVariableTableOffset; + int LineNumberTableOffset; + int CodeBlockTableOffset; + int ScopeVariableTableOffset; + int RealNameOffset; + Flags flags; + #endregion + + int index; + + public Flags MethodFlags { + get { return flags; } + } + + public readonly CompileUnitEntry CompileUnit; + + LocalVariableEntry[] locals; + CodeBlockEntry[] code_blocks; + ScopeVariable[] scope_vars; + LineNumberTable lnt; + string real_name; + + public readonly MonoSymbolFile SymbolFile; + + public int Index { + get { return index; } + set { index = value; } + } + + [Flags] + public enum Flags + { + LocalNamesAmbiguous = 1 + } + + public const int Size = 12; + + internal MethodEntry (MonoSymbolFile file, MyBinaryReader reader, int index) + { + this.SymbolFile = file; + this.index = index; + + Token = reader.ReadInt32 (); + DataOffset = reader.ReadInt32 (); + LineNumberTableOffset = reader.ReadInt32 (); + + long old_pos = reader.BaseStream.Position; + reader.BaseStream.Position = DataOffset; + + CompileUnitIndex = reader.ReadLeb128 (); + LocalVariableTableOffset = reader.ReadLeb128 (); + NamespaceID = reader.ReadLeb128 (); + + CodeBlockTableOffset = reader.ReadLeb128 (); + ScopeVariableTableOffset = reader.ReadLeb128 (); + + RealNameOffset = reader.ReadLeb128 (); + + flags = (Flags) reader.ReadLeb128 (); + + reader.BaseStream.Position = old_pos; + + CompileUnit = file.GetCompileUnit (CompileUnitIndex); + } + + internal MethodEntry (MonoSymbolFile file, CompileUnitEntry comp_unit, + int token, ScopeVariable[] scope_vars, + LocalVariableEntry[] locals, LineNumberEntry[] lines, + CodeBlockEntry[] code_blocks, string real_name, + Flags flags, int namespace_id) + { + this.SymbolFile = file; + this.real_name = real_name; + this.locals = locals; + this.code_blocks = code_blocks; + this.scope_vars = scope_vars; + this.flags = flags; + + index = -1; + + Token = token; + CompileUnitIndex = comp_unit.Index; + CompileUnit = comp_unit; + NamespaceID = namespace_id; + + CheckLineNumberTable (lines); + lnt = new LineNumberTable (file, lines); + file.NumLineNumbers += lines.Length; + + int num_locals = locals != null ? locals.Length : 0; + + if (num_locals <= 32) { + // Most of the time, the O(n^2) factor is actually + // less than the cost of allocating the hash table, + // 32 is a rough number obtained through some testing. + + for (int i = 0; i < num_locals; i ++) { + string nm = locals [i].Name; + + for (int j = i + 1; j < num_locals; j ++) { + if (locals [j].Name == nm) { + flags |= Flags.LocalNamesAmbiguous; + goto locals_check_done; + } + } + } + locals_check_done : + ; + } else { + var local_names = new Dictionary (); + foreach (LocalVariableEntry local in locals) { + if (local_names.ContainsKey (local.Name)) { + flags |= Flags.LocalNamesAmbiguous; + break; + } + local_names.Add (local.Name, local); + } + } + } + + void CheckLineNumberTable (LineNumberEntry[] line_numbers) + { + int last_offset = -1; + int last_row = -1; + + if (line_numbers == null) + return; + + for (int i = 0; i < line_numbers.Length; i++) { + LineNumberEntry line = line_numbers [i]; + + if (line.Equals (LineNumberEntry.Null)) + throw new MonoSymbolFileException (); + + if (line.Offset < last_offset) + throw new MonoSymbolFileException (); + + if (line.Offset > last_offset) { + last_row = line.Row; + last_offset = line.Offset; + } else if (line.Row > last_row) { + last_row = line.Row; + } + } + } + + internal void Write (MyBinaryWriter bw) + { + if ((index <= 0) || (DataOffset == 0)) + throw new InvalidOperationException (); + + bw.Write (Token); + bw.Write (DataOffset); + bw.Write (LineNumberTableOffset); + } + + internal void WriteData (MonoSymbolFile file, MyBinaryWriter bw) + { + if (index <= 0) + throw new InvalidOperationException (); + + LocalVariableTableOffset = (int) bw.BaseStream.Position; + int num_locals = locals != null ? locals.Length : 0; + bw.WriteLeb128 (num_locals); + for (int i = 0; i < num_locals; i++) + locals [i].Write (file, bw); + file.LocalCount += num_locals; + + CodeBlockTableOffset = (int) bw.BaseStream.Position; + int num_code_blocks = code_blocks != null ? code_blocks.Length : 0; + bw.WriteLeb128 (num_code_blocks); + for (int i = 0; i < num_code_blocks; i++) + code_blocks [i].Write (bw); + + ScopeVariableTableOffset = (int) bw.BaseStream.Position; + int num_scope_vars = scope_vars != null ? scope_vars.Length : 0; + bw.WriteLeb128 (num_scope_vars); + for (int i = 0; i < num_scope_vars; i++) + scope_vars [i].Write (bw); + + if (real_name != null) { + RealNameOffset = (int) bw.BaseStream.Position; + bw.Write (real_name); + } + + LineNumberTableOffset = (int) bw.BaseStream.Position; + lnt.Write (file, bw); + + DataOffset = (int) bw.BaseStream.Position; + + bw.WriteLeb128 (CompileUnitIndex); + bw.WriteLeb128 (LocalVariableTableOffset); + bw.WriteLeb128 (NamespaceID); + + bw.WriteLeb128 (CodeBlockTableOffset); + bw.WriteLeb128 (ScopeVariableTableOffset); + + bw.WriteLeb128 (RealNameOffset); + bw.WriteLeb128 ((int) flags); + } + + public LineNumberTable GetLineNumberTable () + { + lock (SymbolFile) { + if (lnt != null) + return lnt; + + if (LineNumberTableOffset == 0) + return null; + + MyBinaryReader reader = SymbolFile.BinaryReader; + long old_pos = reader.BaseStream.Position; + reader.BaseStream.Position = LineNumberTableOffset; + + lnt = LineNumberTable.Read (SymbolFile, reader); + + reader.BaseStream.Position = old_pos; + return lnt; + } + } + + public LocalVariableEntry[] GetLocals () + { + lock (SymbolFile) { + if (locals != null) + return locals; + + if (LocalVariableTableOffset == 0) + return null; + + MyBinaryReader reader = SymbolFile.BinaryReader; + long old_pos = reader.BaseStream.Position; + reader.BaseStream.Position = LocalVariableTableOffset; + + int num_locals = reader.ReadLeb128 (); + locals = new LocalVariableEntry [num_locals]; + + for (int i = 0; i < num_locals; i++) + locals [i] = new LocalVariableEntry (SymbolFile, reader); + + reader.BaseStream.Position = old_pos; + return locals; + } + } + + public CodeBlockEntry[] GetCodeBlocks () + { + lock (SymbolFile) { + if (code_blocks != null) + return code_blocks; + + if (CodeBlockTableOffset == 0) + return null; + + MyBinaryReader reader = SymbolFile.BinaryReader; + long old_pos = reader.BaseStream.Position; + reader.BaseStream.Position = CodeBlockTableOffset; + + int num_code_blocks = reader.ReadLeb128 (); + code_blocks = new CodeBlockEntry [num_code_blocks]; + + for (int i = 0; i < num_code_blocks; i++) + code_blocks [i] = new CodeBlockEntry (i, reader); + + reader.BaseStream.Position = old_pos; + return code_blocks; + } + } + + public ScopeVariable[] GetScopeVariables () + { + lock (SymbolFile) { + if (scope_vars != null) + return scope_vars; + + if (ScopeVariableTableOffset == 0) + return null; + + MyBinaryReader reader = SymbolFile.BinaryReader; + long old_pos = reader.BaseStream.Position; + reader.BaseStream.Position = ScopeVariableTableOffset; + + int num_scope_vars = reader.ReadLeb128 (); + scope_vars = new ScopeVariable [num_scope_vars]; + + for (int i = 0; i < num_scope_vars; i++) + scope_vars [i] = new ScopeVariable (reader); + + reader.BaseStream.Position = old_pos; + return scope_vars; + } + } + + public string GetRealName () + { + lock (SymbolFile) { + if (real_name != null) + return real_name; + + if (RealNameOffset == 0) + return null; + + real_name = SymbolFile.BinaryReader.ReadString (RealNameOffset); + return real_name; + } + } + + public int CompareTo (object obj) + { + MethodEntry method = (MethodEntry) obj; + + if (method.Token < Token) + return 1; + else if (method.Token > Token) + return -1; + else + return 0; + } + + public override string ToString () + { + return String.Format ("[Method {0}:{1:x}:{2}:{3}]", + index, Token, CompileUnitIndex, CompileUnit); + } + } + + public struct NamespaceEntry + { + #region This is actually written to the symbol file + public readonly string Name; + public readonly int Index; + public readonly int Parent; + public readonly string[] UsingClauses; + #endregion + + public NamespaceEntry (string name, int index, string[] using_clauses, int parent) + { + this.Name = name; + this.Index = index; + this.Parent = parent; + this.UsingClauses = using_clauses != null ? using_clauses : new string [0]; + } + + internal NamespaceEntry (MonoSymbolFile file, MyBinaryReader reader) + { + Name = reader.ReadString (); + Index = reader.ReadLeb128 (); + Parent = reader.ReadLeb128 (); + + int count = reader.ReadLeb128 (); + UsingClauses = new string [count]; + for (int i = 0; i < count; i++) + UsingClauses [i] = reader.ReadString (); + } + + internal void Write (MonoSymbolFile file, MyBinaryWriter bw) + { + bw.Write (Name); + bw.WriteLeb128 (Index); + bw.WriteLeb128 (Parent); + bw.WriteLeb128 (UsingClauses.Length); + foreach (string uc in UsingClauses) + bw.Write (uc); + } + + public override string ToString () + { + return String.Format ("[Namespace {0}:{1}:{2}]", Name, Index, Parent); + } + } +} diff --git a/external/cecil-legacy/symbols/mdb/Mono.CompilerServices.SymbolWriter/MonoSymbolWriter.cs b/external/cecil-legacy/symbols/mdb/Mono.CompilerServices.SymbolWriter/MonoSymbolWriter.cs new file mode 100644 index 0000000000..db77c25270 --- /dev/null +++ b/external/cecil-legacy/symbols/mdb/Mono.CompilerServices.SymbolWriter/MonoSymbolWriter.cs @@ -0,0 +1,403 @@ +// +// Mono.CSharp.Debugger/MonoSymbolWriter.cs +// +// Author: +// Martin Baulig (martin@ximian.com) +// +// This is the default implementation of the System.Diagnostics.SymbolStore.ISymbolWriter +// interface. +// +// (C) 2002 Ximian, Inc. http://www.ximian.com +// + +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Runtime.CompilerServices; +using System.Collections.Generic; +using System.IO; + +namespace Mono.CompilerServices.SymbolWriter +{ + public class MonoSymbolWriter + { + List methods; + List sources; + List comp_units; + protected readonly MonoSymbolFile file; + string filename; + + private SourceMethodBuilder current_method; +#if NET_2_1 + System.Collections.Stack current_method_stack = new System.Collections.Stack (); +#else + Stack current_method_stack = new Stack (); +#endif + + public MonoSymbolWriter (string filename) + { + this.methods = new List (); + this.sources = new List (); + this.comp_units = new List (); + this.file = new MonoSymbolFile (); + + this.filename = filename + ".mdb"; + } + + public MonoSymbolFile SymbolFile { + get { return file; } + } + + public void CloseNamespace () + { } + + public void DefineLocalVariable (int index, string name) + { + if (current_method == null) + return; + + current_method.AddLocal (index, name); + } + + public void DefineCapturedLocal (int scope_id, string name, string captured_name) + { + file.DefineCapturedVariable (scope_id, name, captured_name, + CapturedVariable.CapturedKind.Local); + } + + public void DefineCapturedParameter (int scope_id, string name, string captured_name) + { + file.DefineCapturedVariable (scope_id, name, captured_name, + CapturedVariable.CapturedKind.Parameter); + } + + public void DefineCapturedThis (int scope_id, string captured_name) + { + file.DefineCapturedVariable (scope_id, "this", captured_name, + CapturedVariable.CapturedKind.This); + } + + public void DefineCapturedScope (int scope_id, int id, string captured_name) + { + file.DefineCapturedScope (scope_id, id, captured_name); + } + + public void DefineScopeVariable (int scope, int index) + { + if (current_method == null) + return; + + current_method.AddScopeVariable (scope, index); + } + + public void MarkSequencePoint (int offset, SourceFileEntry file, int line, int column, + bool is_hidden) + { + if (current_method == null) + return; + + current_method.MarkSequencePoint (offset, file, line, column, is_hidden); + } + + public SourceMethodBuilder OpenMethod (ICompileUnit file, int ns_id, IMethodDef method) + { + SourceMethodBuilder builder = new SourceMethodBuilder (file, ns_id, method); + current_method_stack.Push (current_method); + current_method = builder; + methods.Add (current_method); + return builder; + } + + public void CloseMethod () + { + current_method = (SourceMethodBuilder) current_method_stack.Pop (); + } + + public SourceFileEntry DefineDocument (string url) + { + SourceFileEntry entry = new SourceFileEntry (file, url); + sources.Add (entry); + return entry; + } + + public SourceFileEntry DefineDocument (string url, byte[] guid, byte[] checksum) + { + SourceFileEntry entry = new SourceFileEntry (file, url, guid, checksum); + sources.Add (entry); + return entry; + } + + public CompileUnitEntry DefineCompilationUnit (SourceFileEntry source) + { + CompileUnitEntry entry = new CompileUnitEntry (file, source); + comp_units.Add (entry); + return entry; + } + + public int DefineNamespace (string name, CompileUnitEntry unit, + string[] using_clauses, int parent) + { + if ((unit == null) || (using_clauses == null)) + throw new NullReferenceException (); + + return unit.DefineNamespace (name, using_clauses, parent); + } + + public int OpenScope (int start_offset) + { + if (current_method == null) + return 0; + + current_method.StartBlock (CodeBlockEntry.Type.Lexical, start_offset); + return 0; + } + + public void CloseScope (int end_offset) + { + if (current_method == null) + return; + + current_method.EndBlock (end_offset); + } + + public void OpenCompilerGeneratedBlock (int start_offset) + { + if (current_method == null) + return; + + current_method.StartBlock (CodeBlockEntry.Type.CompilerGenerated, + start_offset); + } + + public void CloseCompilerGeneratedBlock (int end_offset) + { + if (current_method == null) + return; + + current_method.EndBlock (end_offset); + } + + public void StartIteratorBody (int start_offset) + { + current_method.StartBlock (CodeBlockEntry.Type.IteratorBody, + start_offset); + } + + public void EndIteratorBody (int end_offset) + { + current_method.EndBlock (end_offset); + } + + public void StartIteratorDispatcher (int start_offset) + { + current_method.StartBlock (CodeBlockEntry.Type.IteratorDispatcher, + start_offset); + } + + public void EndIteratorDispatcher (int end_offset) + { + current_method.EndBlock (end_offset); + } + + public void DefineAnonymousScope (int id) + { + file.DefineAnonymousScope (id); + } + + public void WriteSymbolFile (Guid guid) + { + foreach (SourceMethodBuilder method in methods) + method.DefineMethod (file); + + try { + // We mmap the file, so unlink the previous version since it may be in use + File.Delete (filename); + } catch { + // We can safely ignore + } + using (FileStream fs = new FileStream (filename, FileMode.Create, FileAccess.Write)) { + file.CreateSymbolFile (guid, fs); + } + } + } + + public class SourceMethodBuilder + { + List _locals; + List _blocks; + List _scope_vars; +#if NET_2_1 + System.Collections.Stack _block_stack; +#else + Stack _block_stack; +#endif + string _real_name; + IMethodDef _method; + ICompileUnit _comp_unit; +// MethodEntry.Flags _method_flags; + int _ns_id; + + public SourceMethodBuilder (ICompileUnit comp_unit, int ns_id, IMethodDef method) + { + this._comp_unit = comp_unit; + this._method = method; + this._ns_id = ns_id; + + method_lines = new LineNumberEntry [32]; + } + + private LineNumberEntry [] method_lines; + private int method_lines_pos = 0; + + public void MarkSequencePoint (int offset, SourceFileEntry file, int line, int column, + bool is_hidden) + { + if (method_lines_pos == method_lines.Length) { + LineNumberEntry [] tmp = method_lines; + method_lines = new LineNumberEntry [method_lines.Length * 2]; + Array.Copy (tmp, method_lines, method_lines_pos); + } + + int file_idx = file != null ? file.Index : 0; + method_lines [method_lines_pos++] = new LineNumberEntry ( + file_idx, line, offset, is_hidden); + } + + public void StartBlock (CodeBlockEntry.Type type, int start_offset) + { + if (_block_stack == null) { +#if NET_2_1 + _block_stack = new System.Collections.Stack (); +#else + _block_stack = new Stack (); +#endif + } + + if (_blocks == null) + _blocks = new List (); + + int parent = CurrentBlock != null ? CurrentBlock.Index : -1; + + CodeBlockEntry block = new CodeBlockEntry ( + _blocks.Count + 1, parent, type, start_offset); + + _block_stack.Push (block); + _blocks.Add (block); + } + + public void EndBlock (int end_offset) + { + CodeBlockEntry block = (CodeBlockEntry) _block_stack.Pop (); + block.Close (end_offset); + } + + public CodeBlockEntry[] Blocks { + get { + if (_blocks == null) + return new CodeBlockEntry [0]; + + CodeBlockEntry[] retval = new CodeBlockEntry [_blocks.Count]; + _blocks.CopyTo (retval, 0); + return retval; + } + } + + public CodeBlockEntry CurrentBlock { + get { + if ((_block_stack != null) && (_block_stack.Count > 0)) + return (CodeBlockEntry) _block_stack.Peek (); + else + return null; + } + } + + public LocalVariableEntry[] Locals { + get { + if (_locals == null) + return new LocalVariableEntry [0]; + else { + LocalVariableEntry[] retval = + new LocalVariableEntry [_locals.Count]; + _locals.CopyTo (retval, 0); + return retval; + } + } + } + + public void AddLocal (int index, string name) + { + if (_locals == null) + _locals = new List (); + int block_idx = CurrentBlock != null ? CurrentBlock.Index : 0; + _locals.Add (new LocalVariableEntry (index, name, block_idx)); + } + + public ScopeVariable[] ScopeVariables { + get { + if (_scope_vars == null) + return new ScopeVariable [0]; + + ScopeVariable[] retval = new ScopeVariable [_scope_vars.Count]; + _scope_vars.CopyTo (retval); + return retval; + } + } + + public void AddScopeVariable (int scope, int index) + { + if (_scope_vars == null) + _scope_vars = new List (); + _scope_vars.Add ( + new ScopeVariable (scope, index)); + } + + public string RealMethodName { + get { return _real_name; } + } + + public void SetRealMethodName (string name) + { + _real_name = name; + } + + public ICompileUnit SourceFile { + get { return _comp_unit; } + } + + public IMethodDef Method { + get { return _method; } + } + + public void DefineMethod (MonoSymbolFile file) + { + LineNumberEntry[] lines = new LineNumberEntry [method_lines_pos]; + Array.Copy (method_lines, lines, method_lines_pos); + + MethodEntry entry = new MethodEntry ( + file, _comp_unit.Entry, _method.Token, ScopeVariables, + Locals, lines, Blocks, RealMethodName, 0, //_method_flags, + _ns_id); + + file.AddMethod (entry); + } + } +} diff --git a/external/cecil-legacy/symbols/mdb/Mono.CompilerServices.SymbolWriter/SymbolWriterImpl.cs b/external/cecil-legacy/symbols/mdb/Mono.CompilerServices.SymbolWriter/SymbolWriterImpl.cs new file mode 100644 index 0000000000..d9e30578e3 --- /dev/null +++ b/external/cecil-legacy/symbols/mdb/Mono.CompilerServices.SymbolWriter/SymbolWriterImpl.cs @@ -0,0 +1,349 @@ +// +// SymbolWriterImpl.cs +// +// Author: +// Lluis Sanchez Gual (lluis@novell.com) +// +// (C) 2005 Novell, Inc. http://www.novell.com +// +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + + +using System; +using System.Reflection; +using System.Reflection.Emit; +using System.Runtime.CompilerServices; +using System.Collections; +using System.IO; +using System.Diagnostics.SymbolStore; + +namespace Mono.CompilerServices.SymbolWriter +{ + public class SymbolWriterImpl: ISymbolWriter + { + MonoSymbolWriter msw; + + int nextLocalIndex; + int currentToken; + string methodName; + Stack namespaceStack = new Stack (); + bool methodOpened; + + Hashtable documents = new Hashtable (); + +#if !CECIL + ModuleBuilder mb; + delegate Guid GetGuidFunc (ModuleBuilder mb); + GetGuidFunc get_guid_func; + + public SymbolWriterImpl (ModuleBuilder mb) + { + this.mb = mb; + } + + public void Close () + { + MethodInfo mi = typeof (ModuleBuilder).GetMethod ( + "Mono_GetGuid", + BindingFlags.Static | BindingFlags.NonPublic); + if (mi == null) + return; + + get_guid_func = (GetGuidFunc) System.Delegate.CreateDelegate ( + typeof (GetGuidFunc), mi); + + msw.WriteSymbolFile (get_guid_func (mb)); + } +#else + Guid guid; + + public SymbolWriterImpl (Guid guid) + { + this.guid = guid; + } + + public void Close () + { + msw.WriteSymbolFile (guid); + } +#endif + + public void CloseMethod () + { + if (methodOpened) { + methodOpened = false; + nextLocalIndex = 0; + msw.CloseMethod (); + } + } + + public void CloseNamespace () + { + namespaceStack.Pop (); + msw.CloseNamespace (); + } + + public void CloseScope (int endOffset) + { + msw.CloseScope (endOffset); + } + + public ISymbolDocumentWriter DefineDocument ( + string url, + Guid language, + Guid languageVendor, + Guid documentType) + { + SymbolDocumentWriterImpl doc = (SymbolDocumentWriterImpl) documents [url]; + if (doc == null) { + SourceFileEntry entry = msw.DefineDocument (url); + CompileUnitEntry comp_unit = msw.DefineCompilationUnit (entry); + doc = new SymbolDocumentWriterImpl (comp_unit); + documents [url] = doc; + } + return doc; + } + + public void DefineField ( + SymbolToken parent, + string name, + FieldAttributes attributes, + byte[] signature, + SymAddressKind addrKind, + int addr1, + int addr2, + int addr3) + { + } + + public void DefineGlobalVariable ( + string name, + FieldAttributes attributes, + byte[] signature, + SymAddressKind addrKind, + int addr1, + int addr2, + int addr3) + { + } + + public void DefineLocalVariable ( + string name, + FieldAttributes attributes, + byte[] signature, + SymAddressKind addrKind, + int addr1, + int addr2, + int addr3, + int startOffset, + int endOffset) + { + msw.DefineLocalVariable (nextLocalIndex++, name); + } + + public void DefineParameter ( + string name, + ParameterAttributes attributes, + int sequence, + SymAddressKind addrKind, + int addr1, + int addr2, + int addr3) + { + } + + public void DefineSequencePoints ( + ISymbolDocumentWriter document, + int[] offsets, + int[] lines, + int[] columns, + int[] endLines, + int[] endColumns) + { + SymbolDocumentWriterImpl doc = (SymbolDocumentWriterImpl) document; + SourceFileEntry file = doc != null ? doc.Entry.SourceFile : null; + + for (int n=0; n 0 && offsets[n] == offsets[n-1] && lines[n] == lines[n-1] && columns[n] == columns[n-1]) + continue; + msw.MarkSequencePoint (offsets[n], file, lines[n], columns[n], false); + } + } + + public void Initialize (IntPtr emitter, string filename, bool fFullBuild) + { + msw = new MonoSymbolWriter (filename); + } + + public void OpenMethod (SymbolToken method) + { + currentToken = method.GetToken (); + } + + public void OpenNamespace (string name) + { + NamespaceInfo n = new NamespaceInfo (); + n.NamespaceID = -1; + n.Name = name; + namespaceStack.Push (n); + } + + public int OpenScope (int startOffset) + { + return msw.OpenScope (startOffset); + } + + public void SetMethodSourceRange ( + ISymbolDocumentWriter startDoc, + int startLine, + int startColumn, + ISymbolDocumentWriter endDoc, + int endLine, + int endColumn) + { + int nsId = GetCurrentNamespace (startDoc); + SourceMethodImpl sm = new SourceMethodImpl (methodName, currentToken, nsId); + msw.OpenMethod (((ICompileUnit)startDoc).Entry, nsId, sm); + methodOpened = true; + } + + public void SetScopeRange (int scopeID, int startOffset, int endOffset) + { + } + + public void SetSymAttribute (SymbolToken parent, string name, byte[] data) + { + // This is a hack! but MonoSymbolWriter needs the method name + // and ISymbolWriter does not have any method for providing it + if (name == "__name") + methodName = System.Text.Encoding.UTF8.GetString (data); + } + + public void SetUnderlyingWriter (IntPtr underlyingWriter) + { + } + + public void SetUserEntryPoint (SymbolToken entryMethod) + { + } + + public void UsingNamespace (string fullName) + { + if (namespaceStack.Count == 0) { + OpenNamespace (""); + } + + NamespaceInfo ni = (NamespaceInfo) namespaceStack.Peek (); + if (ni.NamespaceID != -1) { + NamespaceInfo old = ni; + CloseNamespace (); + OpenNamespace (old.Name); + ni = (NamespaceInfo) namespaceStack.Peek (); + ni.UsingClauses = old.UsingClauses; + } + ni.UsingClauses.Add (fullName); + } + + int GetCurrentNamespace (ISymbolDocumentWriter doc) + { + if (namespaceStack.Count == 0) { + OpenNamespace (""); + } + + NamespaceInfo ni = (NamespaceInfo) namespaceStack.Peek (); + if (ni.NamespaceID == -1) + { + string[] usings = (string[]) ni.UsingClauses.ToArray (typeof(string)); + + int parentId = 0; + if (namespaceStack.Count > 1) { + namespaceStack.Pop (); + parentId = ((NamespaceInfo) namespaceStack.Peek ()).NamespaceID; + namespaceStack.Push (ni); + } + + ni.NamespaceID = msw.DefineNamespace (ni.Name, ((ICompileUnit)doc).Entry, usings, parentId); + } + return ni.NamespaceID; + } + + } + + class SymbolDocumentWriterImpl: ISymbolDocumentWriter, ISourceFile, ICompileUnit + { + CompileUnitEntry comp_unit; + + public SymbolDocumentWriterImpl (CompileUnitEntry comp_unit) + { + this.comp_unit = comp_unit; + } + + public void SetCheckSum (Guid algorithmId, byte[] checkSum) + { + } + + public void SetSource (byte[] source) + { + } + + SourceFileEntry ISourceFile.Entry { + get { return comp_unit.SourceFile; } + } + + public CompileUnitEntry Entry { + get { return comp_unit; } + } + } + + class SourceMethodImpl: IMethodDef + { + string name; + int token; + int namespaceID; + + public SourceMethodImpl (string name, int token, int namespaceID) + { + this.name = name; + this.token = token; + this.namespaceID = namespaceID; + } + + public string Name { + get { return name; } + } + + public int NamespaceID { + get { return namespaceID; } + } + + public int Token { + get { return token; } + } + } + + class NamespaceInfo + { + public string Name; + public int NamespaceID; + public ArrayList UsingClauses = new ArrayList (); + } +} diff --git a/external/cecil/symbols/mdb/Test/.gitignore b/external/cecil-legacy/symbols/mdb/Test/.gitignore similarity index 100% rename from external/cecil/symbols/mdb/Test/.gitignore rename to external/cecil-legacy/symbols/mdb/Test/.gitignore diff --git a/external/cecil-legacy/symbols/mdb/Test/Mono.Cecil.Mdb.Tests.csproj b/external/cecil-legacy/symbols/mdb/Test/Mono.Cecil.Mdb.Tests.csproj new file mode 100644 index 0000000000..2123470382 --- /dev/null +++ b/external/cecil-legacy/symbols/mdb/Test/Mono.Cecil.Mdb.Tests.csproj @@ -0,0 +1,119 @@ + + + + net_4_0_Debug + AnyCPU + 9.0.30729 + 2.0 + {AC71DF9C-99FA-4A63-990A-66C8010355A6} + Library + Properties + Mono.Cecil.Mdb.Tests + Mono.Cecil.Mdb.Tests + 512 + + + true + full + false + bin\net_2_0_Debug\ + DEBUG;TRACE + prompt + 4 + v2.0 + + + pdbonly + true + bin\net_2_0_Release\ + TRACE + prompt + 4 + v2.0 + + + true + full + false + bin\net_3_5_Debug\ + DEBUG;TRACE;NET_3_5 + prompt + 4 + v3.5 + + + pdbonly + true + bin\net_3_5_Release\ + TRACE;NET_3_5 + prompt + 4 + v3.5 + + + true + full + false + bin\net_4_0_Debug\ + DEBUG;TRACE;NET_3_5;NET_4_0 + prompt + 4 + v4.0 + + + pdbonly + true + bin\net_4_0_Release\ + TRACE;NET_3_5;NET_4_0 + prompt + 4 + v4.0 + + + + + + + {D68133BD-1E63-496E-9EDE-4FBDBF77B486} + Mono.Cecil + + + {A47B1F49-A81A-43E8-BE6B-DD28AF2C4055} + Mono.Cecil.Tests + + + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD} + Mono.Cecil.Mdb + + + + + + + + + + + + + False + ..\..\..\Test\libs\nunit-2.6.2\nunit.core.dll + + + False + ..\..\..\Test\libs\nunit-2.6.2\nunit.core.interfaces.dll + + + False + ..\..\..\Test\libs\nunit-2.6.2\nunit.framework.dll + + + + + \ No newline at end of file diff --git a/external/cecil/symbols/mdb/Test/Mono.Cecil.Tests/Addin.cs b/external/cecil-legacy/symbols/mdb/Test/Mono.Cecil.Tests/Addin.cs similarity index 100% rename from external/cecil/symbols/mdb/Test/Mono.Cecil.Tests/Addin.cs rename to external/cecil-legacy/symbols/mdb/Test/Mono.Cecil.Tests/Addin.cs diff --git a/external/cecil-legacy/symbols/mdb/Test/Mono.Cecil.Tests/MdbTests.cs b/external/cecil-legacy/symbols/mdb/Test/Mono.Cecil.Tests/MdbTests.cs new file mode 100644 index 0000000000..757732d6ee --- /dev/null +++ b/external/cecil-legacy/symbols/mdb/Test/Mono.Cecil.Tests/MdbTests.cs @@ -0,0 +1,58 @@ + +using Mono.Cecil.Mdb; + +using NUnit.Framework; + +namespace Mono.Cecil.Tests { + + [TestFixture] + public class MdbTests : BaseTestFixture { + + [TestModule ("hello.exe", SymbolReaderProvider = typeof (MdbReaderProvider), SymbolWriterProvider = typeof (MdbWriterProvider))] + public void Main (ModuleDefinition module) + { + var type = module.GetType ("Program"); + var main = type.GetMethod ("Main"); + + AssertCode (@" + .locals init (System.Int32 i) + .line 7,7:0,0 'C:\sources\cecil\symbols\Mono.Cecil.Mdb\Test\Resources\assemblies\hello.cs' + IL_0000: ldc.i4.0 + IL_0001: stloc.0 + .line 7,7:0,0 'C:\sources\cecil\symbols\Mono.Cecil.Mdb\Test\Resources\assemblies\hello.cs' + IL_0002: br IL_0013 + .line 8,8:0,0 'C:\sources\cecil\symbols\Mono.Cecil.Mdb\Test\Resources\assemblies\hello.cs' + IL_0007: ldarg.0 + IL_0008: ldloc.0 + IL_0009: ldelem.ref + IL_000a: call System.Void Program::Print(System.String) + .line 7,7:0,0 'C:\sources\cecil\symbols\Mono.Cecil.Mdb\Test\Resources\assemblies\hello.cs' + IL_000f: ldloc.0 + IL_0010: ldc.i4.1 + IL_0011: add + IL_0012: stloc.0 + IL_0013: ldloc.0 + IL_0014: ldarg.0 + IL_0015: ldlen + IL_0016: conv.i4 + IL_0017: blt IL_0007 + .line 10,10:0,0 'C:\sources\cecil\symbols\Mono.Cecil.Mdb\Test\Resources\assemblies\hello.cs' + IL_001c: ldc.i4.0 + IL_001d: ret +", main); + } + + static void AssertCode (string expected, MethodDefinition method) + { + Assert.IsTrue (method.HasBody); + Assert.IsNotNull (method.Body); + + Assert.AreEqual (Normalize (expected), Normalize (Formatter.FormatMethodBody (method))); + } + + static string Normalize (string str) + { + return str.Trim ().Replace ("\r\n", "\n"); + } + } +} diff --git a/external/cecil-legacy/symbols/mdb/Test/Resources/assemblies/hello.exe.mdb b/external/cecil-legacy/symbols/mdb/Test/Resources/assemblies/hello.exe.mdb new file mode 100644 index 0000000000..f57f165618 Binary files /dev/null and b/external/cecil-legacy/symbols/mdb/Test/Resources/assemblies/hello.exe.mdb differ diff --git a/external/cecil/symbols/pdb/.gitignore b/external/cecil-legacy/symbols/pdb/.gitignore similarity index 100% rename from external/cecil/symbols/pdb/.gitignore rename to external/cecil-legacy/symbols/pdb/.gitignore diff --git a/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/BitAccess.cs b/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/BitAccess.cs new file mode 100644 index 0000000000..d92a5b7491 --- /dev/null +++ b/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/BitAccess.cs @@ -0,0 +1,255 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the Microsoft Public License. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//----------------------------------------------------------------------------- +using System; +using System.IO; +using System.Text; + +namespace Microsoft.Cci.Pdb { + internal class BitAccess { + + internal BitAccess(int capacity) { + this.buffer = new byte[capacity]; + } + + internal byte[] Buffer { + get { return buffer; } + } + private byte[] buffer; + + internal void FillBuffer(Stream stream, int capacity) { + MinCapacity(capacity); + stream.Read(buffer, 0, capacity); + offset = 0; + } + + internal void Append(Stream stream, int count) { + int newCapacity = offset + count; + if (buffer.Length < newCapacity) { + byte[] newBuffer = new byte[newCapacity]; + Array.Copy(buffer, newBuffer, buffer.Length); + buffer = newBuffer; + } + stream.Read(buffer, offset, count); + offset += count; + } + + internal int Position { + get { return offset; } + set { offset = value; } + } + private int offset; + + //internal void WriteBuffer(Stream stream, int count) { + // stream.Write(buffer, 0, count); + //} + + internal void MinCapacity(int capacity) { + if (buffer.Length < capacity) { + buffer = new byte[capacity]; + } + offset = 0; + } + + internal void Align(int alignment) { + while ((offset % alignment) != 0) { + offset++; + } + } + + //internal void WriteInt32(int value) { + // buffer[offset + 0] = (byte)value; + // buffer[offset + 1] = (byte)(value >> 8); + // buffer[offset + 2] = (byte)(value >> 16); + // buffer[offset + 3] = (byte)(value >> 24); + // offset += 4; + //} + + //internal void WriteInt32(int[] values) { + // for (int i = 0; i < values.Length; i++) { + // WriteInt32(values[i]); + // } + //} + + //internal void WriteBytes(byte[] bytes) { + // for (int i = 0; i < bytes.Length; i++) { + // buffer[offset++] = bytes[i]; + // } + //} + + internal void ReadInt16(out short value) { + value = (short)((buffer[offset + 0] & 0xFF) | + (buffer[offset + 1] << 8)); + offset += 2; + } + + internal void ReadInt8(out sbyte value) { + value = (sbyte)buffer[offset]; + offset += 1; + } + + internal void ReadInt32(out int value) { + value = (int)((buffer[offset + 0] & 0xFF) | + (buffer[offset + 1] << 8) | + (buffer[offset + 2] << 16) | + (buffer[offset + 3] << 24)); + offset += 4; + } + + internal void ReadInt64(out long value) { + value = (long)(((ulong)buffer[offset + 0] & 0xFF) | + ((ulong)buffer[offset + 1] << 8) | + ((ulong)buffer[offset + 2] << 16) | + ((ulong)buffer[offset + 3] << 24) | + ((ulong)buffer[offset + 4] << 32) | + ((ulong)buffer[offset + 5] << 40) | + ((ulong)buffer[offset + 6] << 48) | + ((ulong)buffer[offset + 7] << 56)); + offset += 8; + } + + internal void ReadUInt16(out ushort value) { + value = (ushort)((buffer[offset + 0] & 0xFF) | + (buffer[offset + 1] << 8)); + offset += 2; + } + + internal void ReadUInt8(out byte value) { + value = (byte)((buffer[offset + 0] & 0xFF)); + offset += 1; + } + + internal void ReadUInt32(out uint value) { + value = (uint)((buffer[offset + 0] & 0xFF) | + (buffer[offset + 1] << 8) | + (buffer[offset + 2] << 16) | + (buffer[offset + 3] << 24)); + offset += 4; + } + + internal void ReadUInt64(out ulong value) { + value = (ulong)(((ulong)buffer[offset + 0] & 0xFF) | + ((ulong)buffer[offset + 1] << 8) | + ((ulong)buffer[offset + 2] << 16) | + ((ulong)buffer[offset + 3] << 24) | + ((ulong)buffer[offset + 4] << 32) | + ((ulong)buffer[offset + 5] << 40) | + ((ulong)buffer[offset + 6] << 48) | + ((ulong)buffer[offset + 7] << 56)); + offset += 8; + } + + internal void ReadInt32(int[] values) { + for (int i = 0; i < values.Length; i++) { + ReadInt32(out values[i]); + } + } + + internal void ReadUInt32(uint[] values) { + for (int i = 0; i < values.Length; i++) { + ReadUInt32(out values[i]); + } + } + + internal void ReadBytes(byte[] bytes) { + for (int i = 0; i < bytes.Length; i++) { + bytes[i] = buffer[offset++]; + } + } + + internal float ReadFloat() { + float result = BitConverter.ToSingle(buffer, offset); + offset += 4; + return result; + } + + internal double ReadDouble() { + double result = BitConverter.ToDouble(buffer, offset); + offset += 8; + return result; + } + + internal decimal ReadDecimal() { + int[] bits = new int[4]; + this.ReadInt32(bits); + return new decimal(bits[2], bits[3], bits[1], bits[0] < 0, (byte)((bits[0] & 0x00FF0000) >> 16)); + } + + internal void ReadBString(out string value) { + ushort len; + this.ReadUInt16(out len); + value = Encoding.UTF8.GetString(buffer, offset, len); + offset += len; + } + + internal string ReadBString(int len) { + var result = Encoding.UTF8.GetString(buffer, offset, len); + offset += len; + return result; + } + + internal void ReadCString(out string value) { + int len = 0; + while (offset + len < buffer.Length && buffer[offset + len] != 0) { + len++; + } + value = Encoding.UTF8.GetString(buffer, offset, len); + offset += len + 1; + } + + internal void SkipCString(out string value) { + int len = 0; + while (offset + len < buffer.Length && buffer[offset + len] != 0) { + len++; + } + offset += len + 1; + value= null; + } + + internal void ReadGuid(out Guid guid) { + uint a; + ushort b; + ushort c; + byte d; + byte e; + byte f; + byte g; + byte h; + byte i; + byte j; + byte k; + + ReadUInt32(out a); + ReadUInt16(out b); + ReadUInt16(out c); + ReadUInt8(out d); + ReadUInt8(out e); + ReadUInt8(out f); + ReadUInt8(out g); + ReadUInt8(out h); + ReadUInt8(out i); + ReadUInt8(out j); + ReadUInt8(out k); + + guid = new Guid(a, b, c, d, e, f, g, h, i, j, k); + } + + internal string ReadString() { + int len = 0; + while (offset + len < buffer.Length && buffer[offset + len] != 0) { + len+=2; + } + string result = Encoding.Unicode.GetString(buffer, offset, len); + offset += len + 2; + return result; + } + + } +} diff --git a/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/BitSet.cs b/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/BitSet.cs new file mode 100644 index 0000000000..6719131719 --- /dev/null +++ b/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/BitSet.cs @@ -0,0 +1,74 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the Microsoft Public License. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//----------------------------------------------------------------------------- +using System; + +namespace Microsoft.Cci.Pdb { + internal struct BitSet { + internal BitSet(BitAccess bits) { + bits.ReadInt32(out size); // 0..3 : Number of words + words = new uint[size]; + bits.ReadUInt32(words); + } + + //internal BitSet(int size) { + // this.size = size; + // words = new uint[size]; + //} + + internal bool IsSet(int index) { + int word = index / 32; + if (word >= this.size) return false; + return ((words[word] & GetBit(index)) != 0); + } + + //internal void Set(int index) { + // int word = index / 32; + // if (word >= this.size) return; + // words[word] |= GetBit(index); + //} + + //internal void Clear(int index) { + // int word = index / 32; + // if (word >= this.size) return; + // words[word] &= ~GetBit(index); + //} + + private static uint GetBit(int index) { + return ((uint)1 << (index % 32)); + } + + //private static uint ReverseBits(uint value) { + // uint o = 0; + // for (int i = 0; i < 32; i++) { + // o = (o << 1) | (value & 1); + // value >>= 1; + // } + // return o; + //} + + internal bool IsEmpty { + get { return size == 0; } + } + + //internal bool GetWord(int index, out uint word) { + // if (index < size) { + // word = ReverseBits(words[index]); + // return true; + // } + // word = 0; + // return false; + //} + + private int size; + private uint[] words; + } + +} diff --git a/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/CvInfo.cs b/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/CvInfo.cs new file mode 100644 index 0000000000..49c51ce1a0 --- /dev/null +++ b/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/CvInfo.cs @@ -0,0 +1,2435 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the Microsoft Public License. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//----------------------------------------------------------------------------- +// +// File: CvInfo.cs +// +// Generic CodeView information definitions +// +// Structures, constants, etc. for accessing and interpreting +// CodeView information. +// +// The master copy of this file resides in the langapi project (in C++). +// All Microsoft projects are required to use the master copy without +// modification. Modification of the master version or a copy +// without consultation with all parties concerned is extremely +// risky. +// +// When this file is modified, the corresponding documentation file +// omfdeb.doc in the langapi project must be updated. +// +// This is a read-only copy of the C++ file converted to C#. +// +using System; + +namespace Microsoft.Cci.Pdb { + internal struct FLOAT10 { + internal byte Data_0; + internal byte Data_1; + internal byte Data_2; + internal byte Data_3; + internal byte Data_4; + internal byte Data_5; + internal byte Data_6; + internal byte Data_7; + internal byte Data_8; + internal byte Data_9; + }; + + internal enum CV_SIGNATURE { + C6=0, // Actual signature is >64K + C7=1, // First explicit signature + C11=2, // C11 (vc5.x) 32-bit types + C13=4, // C13 (vc7.x) zero terminated names + RESERVERD=5, // All signatures from 5 to 64K are reserved + }; + + // CodeView Symbol and Type OMF type information is broken up into two + // ranges. Type indices less than 0x1000 describe type information + // that is frequently used. Type indices above 0x1000 are used to + // describe more complex features such as functions, arrays and + // structures. + // + + // Primitive types have predefined meaning that is encoded in the + // values of the various bit fields in the value. + // + // A CodeView primitive type is defined as: + // + // 1 1 + // 1 089 7654 3 210 + // r mode type r sub + // + // Where + // mode is the pointer mode + // type is a type indicator + // sub is a subtype enumeration + // r is a reserved field + // + // See Microsoft Symbol and Type OMF (Version 4.0) for more + // information. + // + + // pointer mode enumeration values + + internal enum CV_prmode { + CV_TM_DIRECT=0, // mode is not a pointer + CV_TM_NPTR32=4, // mode is a 32 bit near pointer + CV_TM_NPTR64=6, // mode is a 64 bit near pointer + CV_TM_NPTR128=7, // mode is a 128 bit near pointer + }; + + // type enumeration values + + internal enum CV_type { + CV_SPECIAL=0x00, // special type size values + CV_SIGNED=0x01, // signed integral size values + CV_UNSIGNED=0x02, // unsigned integral size values + CV_BOOLEAN=0x03, // Boolean size values + CV_REAL=0x04, // real number size values + CV_COMPLEX=0x05, // complex number size values + CV_SPECIAL2=0x06, // second set of special types + CV_INT=0x07, // integral (int) values + CV_CVRESERVED=0x0f, + }; + + // subtype enumeration values for CV_SPECIAL + + internal enum CV_special { + CV_SP_NOTYPE=0x00, + CV_SP_ABS=0x01, + CV_SP_SEGMENT=0x02, + CV_SP_VOID=0x03, + CV_SP_CURRENCY=0x04, + CV_SP_NBASICSTR=0x05, + CV_SP_FBASICSTR=0x06, + CV_SP_NOTTRANS=0x07, + CV_SP_HRESULT=0x08, + }; + + // subtype enumeration values for CV_SPECIAL2 + + internal enum CV_special2 { + CV_S2_BIT=0x00, + CV_S2_PASCHAR=0x01, // Pascal CHAR + }; + + // subtype enumeration values for CV_SIGNED, CV_UNSIGNED and CV_BOOLEAN + + internal enum CV_integral { + CV_IN_1BYTE=0x00, + CV_IN_2BYTE=0x01, + CV_IN_4BYTE=0x02, + CV_IN_8BYTE=0x03, + CV_IN_16BYTE=0x04, + }; + + // subtype enumeration values for CV_REAL and CV_COMPLEX + + internal enum CV_real { + CV_RC_REAL32=0x00, + CV_RC_REAL64=0x01, + CV_RC_REAL80=0x02, + CV_RC_REAL128=0x03, + }; + + // subtype enumeration values for CV_INT (really int) + + internal enum CV_int { + CV_RI_CHAR=0x00, + CV_RI_INT1=0x00, + CV_RI_WCHAR=0x01, + CV_RI_UINT1=0x01, + CV_RI_INT2=0x02, + CV_RI_UINT2=0x03, + CV_RI_INT4=0x04, + CV_RI_UINT4=0x05, + CV_RI_INT8=0x06, + CV_RI_UINT8=0x07, + CV_RI_INT16=0x08, + CV_RI_UINT16=0x09, + }; + + internal struct CV_PRIMITIVE_TYPE { + const uint CV_MMASK = 0x700; // mode mask + const uint CV_TMASK = 0x0f0; // type mask + const uint CV_SMASK = 0x00f; // subtype mask + + const int CV_MSHIFT = 8; // primitive mode right shift count + const int CV_TSHIFT = 4; // primitive type right shift count + const int CV_SSHIFT = 0; // primitive subtype right shift count + + // function to extract primitive mode, type and size + + //internal static CV_prmode CV_MODE(TYPE_ENUM typ) { + // return (CV_prmode)((((uint)typ) & CV_MMASK) >> CV_MSHIFT); + //} + + //internal static CV_type CV_TYPE(TYPE_ENUM typ) { + // return (CV_type)((((uint)typ) & CV_TMASK) >> CV_TSHIFT); + //} + + //internal static uint CV_SUBT(TYPE_ENUM typ) { + // return ((((uint)typ) & CV_SMASK) >> CV_SSHIFT); + //} + + // functions to check the type of a primitive + + //internal static bool CV_TYP_IS_DIRECT(TYPE_ENUM typ) { + // return (CV_MODE(typ) == CV_prmode.CV_TM_DIRECT); + //} + + //internal static bool CV_TYP_IS_PTR(TYPE_ENUM typ) { + // return (CV_MODE(typ) != CV_prmode.CV_TM_DIRECT); + //} + + //internal static bool CV_TYP_IS_SIGNED(TYPE_ENUM typ) { + // return + // (((CV_TYPE(typ) == CV_type.CV_SIGNED) && CV_TYP_IS_DIRECT(typ)) || + // (typ == TYPE_ENUM.T_INT1) || + // (typ == TYPE_ENUM.T_INT2) || + // (typ == TYPE_ENUM.T_INT4) || + // (typ == TYPE_ENUM.T_INT8) || + // (typ == TYPE_ENUM.T_INT16) || + // (typ == TYPE_ENUM.T_RCHAR)); + //} + + //internal static bool CV_TYP_IS_UNSIGNED(TYPE_ENUM typ) { + // return (((CV_TYPE(typ) == CV_type.CV_UNSIGNED) && CV_TYP_IS_DIRECT(typ)) || + // (typ == TYPE_ENUM.T_UINT1) || + // (typ == TYPE_ENUM.T_UINT2) || + // (typ == TYPE_ENUM.T_UINT4) || + // (typ == TYPE_ENUM.T_UINT8) || + // (typ == TYPE_ENUM.T_UINT16)); + //} + + //internal static bool CV_TYP_IS_REAL(TYPE_ENUM typ) { + // return ((CV_TYPE(typ) == CV_type.CV_REAL) && CV_TYP_IS_DIRECT(typ)); + //} + + const uint CV_FIRST_NONPRIM = 0x1000; + + //internal static bool CV_IS_PRIMITIVE(TYPE_ENUM typ) { + // return ((uint)(typ) < CV_FIRST_NONPRIM); + //} + + //internal static bool CV_TYP_IS_COMPLEX(TYPE_ENUM typ) { + // return ((CV_TYPE(typ) == CV_type.CV_COMPLEX) && CV_TYP_IS_DIRECT(typ)); + //} + + //internal static bool CV_IS_INTERNAL_PTR(TYPE_ENUM typ) { + // return (CV_IS_PRIMITIVE(typ) && + // CV_TYPE(typ) == CV_type.CV_CVRESERVED && + // CV_TYP_IS_PTR(typ)); + //} + } + + // selected values for type_index - for a more complete definition, see + // Microsoft Symbol and Type OMF document + + // Special Types + + internal enum TYPE_ENUM { + // Special Types + + T_NOTYPE=0x0000, // uncharacterized type (no type) + T_ABS=0x0001, // absolute symbol + T_SEGMENT=0x0002, // segment type + T_VOID=0x0003, // void + T_HRESULT=0x0008, // OLE/COM HRESULT + T_32PHRESULT=0x0408, // OLE/COM HRESULT __ptr32// + T_64PHRESULT=0x0608, // OLE/COM HRESULT __ptr64// + T_PVOID=0x0103, // near pointer to void + T_PFVOID=0x0203, // far pointer to void + T_PHVOID=0x0303, // huge pointer to void + T_32PVOID=0x0403, // 32 bit pointer to void + T_64PVOID=0x0603, // 64 bit pointer to void + T_CURRENCY=0x0004, // BASIC 8 byte currency value + T_NOTTRANS=0x0007, // type not translated by cvpack + T_BIT=0x0060, // bit + T_PASCHAR=0x0061, // Pascal CHAR + + // Character types + + T_CHAR=0x0010, // 8 bit signed + T_32PCHAR=0x0410, // 32 bit pointer to 8 bit signed + T_64PCHAR=0x0610, // 64 bit pointer to 8 bit signed + + T_UCHAR=0x0020, // 8 bit unsigned + T_32PUCHAR=0x0420, // 32 bit pointer to 8 bit unsigned + T_64PUCHAR=0x0620, // 64 bit pointer to 8 bit unsigned + + // really a character types + + T_RCHAR=0x0070, // really a char + T_32PRCHAR=0x0470, // 32 bit pointer to a real char + T_64PRCHAR=0x0670, // 64 bit pointer to a real char + + // really a wide character types + + T_WCHAR=0x0071, // wide char + T_32PWCHAR=0x0471, // 32 bit pointer to a wide char + T_64PWCHAR=0x0671, // 64 bit pointer to a wide char + + // 8 bit int types + + T_INT1=0x0068, // 8 bit signed int + T_32PINT1=0x0468, // 32 bit pointer to 8 bit signed int + T_64PINT1=0x0668, // 64 bit pointer to 8 bit signed int + + T_UINT1=0x0069, // 8 bit unsigned int + T_32PUINT1=0x0469, // 32 bit pointer to 8 bit unsigned int + T_64PUINT1=0x0669, // 64 bit pointer to 8 bit unsigned int + + // 16 bit short types + + T_SHORT=0x0011, // 16 bit signed + T_32PSHORT=0x0411, // 32 bit pointer to 16 bit signed + T_64PSHORT=0x0611, // 64 bit pointer to 16 bit signed + + T_USHORT=0x0021, // 16 bit unsigned + T_32PUSHORT=0x0421, // 32 bit pointer to 16 bit unsigned + T_64PUSHORT=0x0621, // 64 bit pointer to 16 bit unsigned + + // 16 bit int types + + T_INT2=0x0072, // 16 bit signed int + T_32PINT2=0x0472, // 32 bit pointer to 16 bit signed int + T_64PINT2=0x0672, // 64 bit pointer to 16 bit signed int + + T_UINT2=0x0073, // 16 bit unsigned int + T_32PUINT2=0x0473, // 32 bit pointer to 16 bit unsigned int + T_64PUINT2=0x0673, // 64 bit pointer to 16 bit unsigned int + + // 32 bit long types + + T_LONG=0x0012, // 32 bit signed + T_ULONG=0x0022, // 32 bit unsigned + T_32PLONG=0x0412, // 32 bit pointer to 32 bit signed + T_32PULONG=0x0422, // 32 bit pointer to 32 bit unsigned + T_64PLONG=0x0612, // 64 bit pointer to 32 bit signed + T_64PULONG=0x0622, // 64 bit pointer to 32 bit unsigned + + // 32 bit int types + + T_INT4=0x0074, // 32 bit signed int + T_32PINT4=0x0474, // 32 bit pointer to 32 bit signed int + T_64PINT4=0x0674, // 64 bit pointer to 32 bit signed int + + T_UINT4=0x0075, // 32 bit unsigned int + T_32PUINT4=0x0475, // 32 bit pointer to 32 bit unsigned int + T_64PUINT4=0x0675, // 64 bit pointer to 32 bit unsigned int + + // 64 bit quad types + + T_QUAD=0x0013, // 64 bit signed + T_32PQUAD=0x0413, // 32 bit pointer to 64 bit signed + T_64PQUAD=0x0613, // 64 bit pointer to 64 bit signed + + T_UQUAD=0x0023, // 64 bit unsigned + T_32PUQUAD=0x0423, // 32 bit pointer to 64 bit unsigned + T_64PUQUAD=0x0623, // 64 bit pointer to 64 bit unsigned + + // 64 bit int types + + T_INT8=0x0076, // 64 bit signed int + T_32PINT8=0x0476, // 32 bit pointer to 64 bit signed int + T_64PINT8=0x0676, // 64 bit pointer to 64 bit signed int + + T_UINT8=0x0077, // 64 bit unsigned int + T_32PUINT8=0x0477, // 32 bit pointer to 64 bit unsigned int + T_64PUINT8=0x0677, // 64 bit pointer to 64 bit unsigned int + + // 128 bit octet types + + T_OCT=0x0014, // 128 bit signed + T_32POCT=0x0414, // 32 bit pointer to 128 bit signed + T_64POCT=0x0614, // 64 bit pointer to 128 bit signed + + T_UOCT=0x0024, // 128 bit unsigned + T_32PUOCT=0x0424, // 32 bit pointer to 128 bit unsigned + T_64PUOCT=0x0624, // 64 bit pointer to 128 bit unsigned + + // 128 bit int types + + T_INT16=0x0078, // 128 bit signed int + T_32PINT16=0x0478, // 32 bit pointer to 128 bit signed int + T_64PINT16=0x0678, // 64 bit pointer to 128 bit signed int + + T_UINT16=0x0079, // 128 bit unsigned int + T_32PUINT16=0x0479, // 32 bit pointer to 128 bit unsigned int + T_64PUINT16=0x0679, // 64 bit pointer to 128 bit unsigned int + + // 32 bit real types + + T_REAL32=0x0040, // 32 bit real + T_32PREAL32=0x0440, // 32 bit pointer to 32 bit real + T_64PREAL32=0x0640, // 64 bit pointer to 32 bit real + + // 64 bit real types + + T_REAL64=0x0041, // 64 bit real + T_32PREAL64=0x0441, // 32 bit pointer to 64 bit real + T_64PREAL64=0x0641, // 64 bit pointer to 64 bit real + + // 80 bit real types + + T_REAL80=0x0042, // 80 bit real + T_32PREAL80=0x0442, // 32 bit pointer to 80 bit real + T_64PREAL80=0x0642, // 64 bit pointer to 80 bit real + + // 128 bit real types + + T_REAL128=0x0043, // 128 bit real + T_32PREAL128=0x0443, // 32 bit pointer to 128 bit real + T_64PREAL128=0x0643, // 64 bit pointer to 128 bit real + + // 32 bit complex types + + T_CPLX32=0x0050, // 32 bit complex + T_32PCPLX32=0x0450, // 32 bit pointer to 32 bit complex + T_64PCPLX32=0x0650, // 64 bit pointer to 32 bit complex + + // 64 bit complex types + + T_CPLX64=0x0051, // 64 bit complex + T_32PCPLX64=0x0451, // 32 bit pointer to 64 bit complex + T_64PCPLX64=0x0651, // 64 bit pointer to 64 bit complex + + // 80 bit complex types + + T_CPLX80=0x0052, // 80 bit complex + T_32PCPLX80=0x0452, // 32 bit pointer to 80 bit complex + T_64PCPLX80=0x0652, // 64 bit pointer to 80 bit complex + + // 128 bit complex types + + T_CPLX128=0x0053, // 128 bit complex + T_32PCPLX128=0x0453, // 32 bit pointer to 128 bit complex + T_64PCPLX128=0x0653, // 64 bit pointer to 128 bit complex + + // boolean types + + T_BOOL08=0x0030, // 8 bit boolean + T_32PBOOL08=0x0430, // 32 bit pointer to 8 bit boolean + T_64PBOOL08=0x0630, // 64 bit pointer to 8 bit boolean + + T_BOOL16=0x0031, // 16 bit boolean + T_32PBOOL16=0x0431, // 32 bit pointer to 18 bit boolean + T_64PBOOL16=0x0631, // 64 bit pointer to 18 bit boolean + + T_BOOL32=0x0032, // 32 bit boolean + T_32PBOOL32=0x0432, // 32 bit pointer to 32 bit boolean + T_64PBOOL32=0x0632, // 64 bit pointer to 32 bit boolean + + T_BOOL64=0x0033, // 64 bit boolean + T_32PBOOL64=0x0433, // 32 bit pointer to 64 bit boolean + T_64PBOOL64=0x0633, // 64 bit pointer to 64 bit boolean + }; + + // No leaf index can have a value of 0x0000. The leaf indices are + // separated into ranges depending upon the use of the type record. + // The second range is for the type records that are directly referenced + // in symbols. The first range is for type records that are not + // referenced by symbols but instead are referenced by other type + // records. All type records must have a starting leaf index in these + // first two ranges. The third range of leaf indices are used to build + // up complex lists such as the field list of a class type record. No + // type record can begin with one of the leaf indices. The fourth ranges + // of type indices are used to represent numeric data in a symbol or + // type record. These leaf indices are greater than 0x8000. At the + // point that type or symbol processor is expecting a numeric field, the + // next two bytes in the type record are examined. If the value is less + // than 0x8000, then the two bytes contain the numeric value. If the + // value is greater than 0x8000, then the data follows the leaf index in + // a format specified by the leaf index. The final range of leaf indices + // are used to force alignment of subfields within a complex type record.. + // + + internal enum LEAF { + // leaf indices starting records but referenced from symbol records + + LF_VTSHAPE=0x000a, + LF_COBOL1=0x000c, + LF_LABEL=0x000e, + LF_NULL=0x000f, + LF_NOTTRAN=0x0010, + LF_ENDPRECOMP=0x0014, // not referenced from symbol + LF_TYPESERVER_ST=0x0016, // not referenced from symbol + + // leaf indices starting records but referenced only from type records + + LF_LIST=0x0203, + LF_REFSYM=0x020c, + + LF_ENUMERATE_ST=0x0403, + + // 32-bit type index versions of leaves, all have the 0x1000 bit set + // + LF_TI16_MAX=0x1000, + + LF_MODIFIER=0x1001, + LF_POINTER=0x1002, + LF_ARRAY_ST=0x1003, + LF_CLASS_ST=0x1004, + LF_STRUCTURE_ST=0x1005, + LF_UNION_ST=0x1006, + LF_ENUM_ST=0x1007, + LF_PROCEDURE=0x1008, + LF_MFUNCTION=0x1009, + LF_COBOL0=0x100a, + LF_BARRAY=0x100b, + LF_DIMARRAY_ST=0x100c, + LF_VFTPATH=0x100d, + LF_PRECOMP_ST=0x100e, // not referenced from symbol + LF_OEM=0x100f, // oem definable type string + LF_ALIAS_ST=0x1010, // alias (typedef) type + LF_OEM2=0x1011, // oem definable type string + + // leaf indices starting records but referenced only from type records + + LF_SKIP=0x1200, + LF_ARGLIST=0x1201, + LF_DEFARG_ST=0x1202, + LF_FIELDLIST=0x1203, + LF_DERIVED=0x1204, + LF_BITFIELD=0x1205, + LF_METHODLIST=0x1206, + LF_DIMCONU=0x1207, + LF_DIMCONLU=0x1208, + LF_DIMVARU=0x1209, + LF_DIMVARLU=0x120a, + + LF_BCLASS=0x1400, + LF_VBCLASS=0x1401, + LF_IVBCLASS=0x1402, + LF_FRIENDFCN_ST=0x1403, + LF_INDEX=0x1404, + LF_MEMBER_ST=0x1405, + LF_STMEMBER_ST=0x1406, + LF_METHOD_ST=0x1407, + LF_NESTTYPE_ST=0x1408, + LF_VFUNCTAB=0x1409, + LF_FRIENDCLS=0x140a, + LF_ONEMETHOD_ST=0x140b, + LF_VFUNCOFF=0x140c, + LF_NESTTYPEEX_ST=0x140d, + LF_MEMBERMODIFY_ST=0x140e, + LF_MANAGED_ST=0x140f, + + // Types w/ SZ names + + LF_ST_MAX=0x1500, + + LF_TYPESERVER=0x1501, // not referenced from symbol + LF_ENUMERATE=0x1502, + LF_ARRAY=0x1503, + LF_CLASS=0x1504, + LF_STRUCTURE=0x1505, + LF_UNION=0x1506, + LF_ENUM=0x1507, + LF_DIMARRAY=0x1508, + LF_PRECOMP=0x1509, // not referenced from symbol + LF_ALIAS=0x150a, // alias (typedef) type + LF_DEFARG=0x150b, + LF_FRIENDFCN=0x150c, + LF_MEMBER=0x150d, + LF_STMEMBER=0x150e, + LF_METHOD=0x150f, + LF_NESTTYPE=0x1510, + LF_ONEMETHOD=0x1511, + LF_NESTTYPEEX=0x1512, + LF_MEMBERMODIFY=0x1513, + LF_MANAGED=0x1514, + LF_TYPESERVER2=0x1515, + + LF_NUMERIC=0x8000, + LF_CHAR=0x8000, + LF_SHORT=0x8001, + LF_USHORT=0x8002, + LF_LONG=0x8003, + LF_ULONG=0x8004, + LF_REAL32=0x8005, + LF_REAL64=0x8006, + LF_REAL80=0x8007, + LF_REAL128=0x8008, + LF_QUADWORD=0x8009, + LF_UQUADWORD=0x800a, + LF_COMPLEX32=0x800c, + LF_COMPLEX64=0x800d, + LF_COMPLEX80=0x800e, + LF_COMPLEX128=0x800f, + LF_VARSTRING=0x8010, + + LF_OCTWORD=0x8017, + LF_UOCTWORD=0x8018, + + LF_DECIMAL=0x8019, + LF_DATE=0x801a, + LF_UTF8STRING=0x801b, + + LF_PAD0=0xf0, + LF_PAD1=0xf1, + LF_PAD2=0xf2, + LF_PAD3=0xf3, + LF_PAD4=0xf4, + LF_PAD5=0xf5, + LF_PAD6=0xf6, + LF_PAD7=0xf7, + LF_PAD8=0xf8, + LF_PAD9=0xf9, + LF_PAD10=0xfa, + LF_PAD11=0xfb, + LF_PAD12=0xfc, + LF_PAD13=0xfd, + LF_PAD14=0xfe, + LF_PAD15=0xff, + + }; + + // end of leaf indices + + // Type enum for pointer records + // Pointers can be one of the following types + + internal enum CV_ptrtype { + CV_PTR_BASE_SEG=0x03, // based on segment + CV_PTR_BASE_VAL=0x04, // based on value of base + CV_PTR_BASE_SEGVAL=0x05, // based on segment value of base + CV_PTR_BASE_ADDR=0x06, // based on address of base + CV_PTR_BASE_SEGADDR=0x07, // based on segment address of base + CV_PTR_BASE_TYPE=0x08, // based on type + CV_PTR_BASE_SELF=0x09, // based on self + CV_PTR_NEAR32=0x0a, // 32 bit pointer + CV_PTR_64=0x0c, // 64 bit pointer + CV_PTR_UNUSEDPTR=0x0d // first unused pointer type + }; + + // Mode enum for pointers + // Pointers can have one of the following modes + + internal enum CV_ptrmode { + CV_PTR_MODE_PTR=0x00, // "normal" pointer + CV_PTR_MODE_REF=0x01, // reference + CV_PTR_MODE_PMEM=0x02, // pointer to data member + CV_PTR_MODE_PMFUNC=0x03, // pointer to member function + CV_PTR_MODE_RESERVED=0x04 // first unused pointer mode + }; + + // enumeration for pointer-to-member types + + internal enum CV_pmtype { + CV_PMTYPE_Undef=0x00, // not specified (pre VC8) + CV_PMTYPE_D_Single=0x01, // member data, single inheritance + CV_PMTYPE_D_Multiple=0x02, // member data, multiple inheritance + CV_PMTYPE_D_Virtual=0x03, // member data, virtual inheritance + CV_PMTYPE_D_General=0x04, // member data, most general + CV_PMTYPE_F_Single=0x05, // member function, single inheritance + CV_PMTYPE_F_Multiple=0x06, // member function, multiple inheritance + CV_PMTYPE_F_Virtual=0x07, // member function, virtual inheritance + CV_PMTYPE_F_General=0x08, // member function, most general + }; + + // enumeration for method properties + + internal enum CV_methodprop { + CV_MTvanilla=0x00, + CV_MTvirtual=0x01, + CV_MTstatic=0x02, + CV_MTfriend=0x03, + CV_MTintro=0x04, + CV_MTpurevirt=0x05, + CV_MTpureintro=0x06 + }; + + // enumeration for virtual shape table entries + + internal enum CV_VTS_desc { + CV_VTS_near=0x00, + CV_VTS_far=0x01, + CV_VTS_thin=0x02, + CV_VTS_outer=0x03, + CV_VTS_meta=0x04, + CV_VTS_near32=0x05, + CV_VTS_far32=0x06, + CV_VTS_unused=0x07 + }; + + // enumeration for LF_LABEL address modes + + internal enum CV_LABEL_TYPE { + CV_LABEL_NEAR=0, // near return + CV_LABEL_FAR=4 // far return + }; + + // enumeration for LF_MODIFIER values + + [Flags] + internal enum CV_modifier : ushort { + MOD_const=0x0001, + MOD_volatile=0x0002, + MOD_unaligned=0x0004, + }; + + // bit field structure describing class/struct/union/enum properties + + [Flags] + internal enum CV_prop : ushort { + packed=0x0001, // true if structure is packed + ctor=0x0002, // true if constructors or destructors present + ovlops=0x0004, // true if overloaded operators present + isnested=0x0008, // true if this is a nested class + cnested=0x0010, // true if this class contains nested types + opassign=0x0020, // true if overloaded assignment (=) + opcast=0x0040, // true if casting methods + fwdref=0x0080, // true if forward reference (incomplete defn) + scoped=0x0100, // scoped definition + } + + // class field attribute + + [Flags] + internal enum CV_fldattr { + access=0x0003, // access protection CV_access_t + mprop=0x001c, // method properties CV_methodprop_t + pseudo=0x0020, // compiler generated fcn and does not exist + noinherit=0x0040, // true if class cannot be inherited + noconstruct=0x0080, // true if class cannot be constructed + compgenx=0x0100, // compiler generated fcn and does exist + } + + // Structures to access to the type records + + internal struct TYPTYPE { + internal ushort len; + internal ushort leaf; + // byte data[]; + + // char *NextType (char * pType) { + // return (pType + ((TYPTYPE *)pType)->len + sizeof(ushort)); + // } + }; // general types record + + // memory representation of pointer to member. These representations are + // indexed by the enumeration above in the LF_POINTER record + + // representation of a 32 bit pointer to data for a class with + // or without virtual functions and no virtual bases + + internal struct CV_PDMR32_NVVFCN { + internal int mdisp; // displacement to data (NULL = 0x80000000) + }; + + // representation of a 32 bit pointer to data for a class + // with virtual bases + + internal struct CV_PDMR32_VBASE { + internal int mdisp; // displacement to data + internal int pdisp; // this pointer displacement + internal int vdisp; // vbase table displacement + // NULL = (,,0xffffffff) + }; + + // representation of a 32 bit pointer to member function for a + // class with no virtual bases and a single address point + + internal struct CV_PMFR32_NVSA { + internal uint off; // near address of function (NULL = 0L) + }; + + // representation of a 32 bit pointer to member function for a + // class with no virtual bases and multiple address points + + internal struct CV_PMFR32_NVMA { + internal uint off; // near address of function (NULL = 0L,x) + internal int disp; + }; + + // representation of a 32 bit pointer to member function for a + // class with virtual bases + + internal struct CV_PMFR32_VBASE { + internal uint off; // near address of function (NULL = 0L,x,x,x) + internal int mdisp; // displacement to data + internal int pdisp; // this pointer displacement + internal int vdisp; // vbase table displacement + }; + + ////////////////////////////////////////////////////////////////////////////// + // + // The following type records are basically variant records of the + // above structure. The "ushort leaf" of the above structure and + // the "ushort leaf" of the following type definitions are the same + // symbol. + // + + // Notes on alignment + // Alignment of the fields in most of the type records is done on the + // basis of the TYPTYPE record base. That is why in most of the lf* + // records that the type is located on what appears to + // be a offset mod 4 == 2 boundary. The exception to this rule are those + // records that are in a list (lfFieldList, lfMethodList), which are + // aligned to their own bases since they don't have the length field + // + + // Type record for LF_MODIFIER + + internal struct LeafModifier { + // internal ushort leaf; // LF_MODIFIER [TYPTYPE] + internal uint type; // (type index) modified type + internal CV_modifier attr; // modifier attribute modifier_t + }; + + // type record for LF_POINTER + + [Flags] + internal enum LeafPointerAttr : uint { + ptrtype=0x0000001f, // ordinal specifying pointer type (CV_ptrtype) + ptrmode=0x000000e0, // ordinal specifying pointer mode (CV_ptrmode) + isflat32=0x00000100, // true if 0:32 pointer + isvolatile=0x00000200, // TRUE if volatile pointer + isconst=0x00000400, // TRUE if const pointer + isunaligned=0x00000800, // TRUE if unaligned pointer + isrestrict=0x00001000, // TRUE if restricted pointer (allow agressive opts) + }; + + internal struct LeafPointer { + internal struct LeafPointerBody { + // internal ushort leaf; // LF_POINTER [TYPTYPE] + internal uint utype; // (type index) type index of the underlying type + internal LeafPointerAttr attr; + }; +#if false + union { + internal struct { + uint pmclass; // (type index) index of containing class for pointer to member + ushort pmenum; // enumeration specifying pm format (CV_pmtype) + }; + ushort bseg; // base segment if PTR_BASE_SEG + byte[] Sym; // copy of base symbol record (including length) + internal struct { + uint index; // (type index) type index if CV_PTR_BASE_TYPE + string name; // name of base type + } btype; + } pbase; +#endif + } + + // type record for LF_ARRAY + + internal struct LeafArray { + // internal ushort leaf; // LF_ARRAY [TYPTYPE] + internal uint elemtype; // (type index) type index of element type + internal uint idxtype; // (type index) type index of indexing type + internal byte[] data; // variable length data specifying size in bytes + internal string name; + }; + + // type record for LF_CLASS, LF_STRUCTURE + + internal struct LeafClass { + // internal ushort leaf; // LF_CLASS, LF_STRUCT [TYPTYPE] + internal ushort count; // count of number of elements in class + internal ushort property; // (CV_prop_t) property attribute field (prop_t) + internal uint field; // (type index) type index of LF_FIELD descriptor list + internal uint derived; // (type index) type index of derived from list if not zero + internal uint vshape; // (type index) type index of vshape table for this class + internal byte[] data; // data describing length of structure in bytes + internal string name; + }; + + // type record for LF_UNION + + internal struct LeafUnion { + // internal ushort leaf; // LF_UNION [TYPTYPE] + internal ushort count; // count of number of elements in class + internal ushort property; // (CV_prop_t) property attribute field + internal uint field; // (type index) type index of LF_FIELD descriptor list + internal byte[] data; // variable length data describing length of + internal string name; + }; + + // type record for LF_ALIAS + + internal struct LeafAlias { + // internal ushort leaf; // LF_ALIAS [TYPTYPE] + internal uint utype; // (type index) underlying type + internal string name; // alias name + }; + + // type record for LF_MANAGED + + internal struct LeafManaged { + // internal ushort leaf; // LF_MANAGED [TYPTYPE] + internal string name; // utf8, zero terminated managed type name + }; + + // type record for LF_ENUM + + internal struct LeafEnum { + // internal ushort leaf; // LF_ENUM [TYPTYPE] + internal ushort count; // count of number of elements in class + internal ushort property; // (CV_propt_t) property attribute field + internal uint utype; // (type index) underlying type of the enum + internal uint field; // (type index) type index of LF_FIELD descriptor list + internal string name; // length prefixed name of enum + }; + + // Type record for LF_PROCEDURE + + internal struct LeafProc { + // internal ushort leaf; // LF_PROCEDURE [TYPTYPE] + internal uint rvtype; // (type index) type index of return value + internal byte calltype; // calling convention (CV_call_t) + internal byte reserved; // reserved for future use + internal ushort parmcount; // number of parameters + internal uint arglist; // (type index) type index of argument list + }; + + // Type record for member function + + internal struct LeafMFunc { + // internal ushort leaf; // LF_MFUNCTION [TYPTYPE] + internal uint rvtype; // (type index) type index of return value + internal uint classtype; // (type index) type index of containing class + internal uint thistype; // (type index) type index of this pointer (model specific) + internal byte calltype; // calling convention (call_t) + internal byte reserved; // reserved for future use + internal ushort parmcount; // number of parameters + internal uint arglist; // (type index) type index of argument list + internal int thisadjust; // this adjuster (long because pad required anyway) + }; + + // type record for virtual function table shape + + internal struct LeafVTShape { + // internal ushort leaf; // LF_VTSHAPE [TYPTYPE] + internal ushort count; // number of entries in vfunctable + internal byte[] desc; // 4 bit (CV_VTS_desc) descriptors + }; + + // type record for cobol0 + + internal struct LeafCobol0 { + // internal ushort leaf; // LF_COBOL0 [TYPTYPE] + internal uint type; // (type index) parent type record index + internal byte[] data; + }; + + // type record for cobol1 + + internal struct LeafCobol1 { + // internal ushort leaf; // LF_COBOL1 [TYPTYPE] + internal byte[] data; + }; + + // type record for basic array + + internal struct LeafBArray { + // internal ushort leaf; // LF_BARRAY [TYPTYPE] + internal uint utype; // (type index) type index of underlying type + }; + + // type record for assembler labels + + internal struct LeafLabel { + // internal ushort leaf; // LF_LABEL [TYPTYPE] + internal ushort mode; // addressing mode of label + }; + + // type record for dimensioned arrays + + internal struct LeafDimArray { + // internal ushort leaf; // LF_DIMARRAY [TYPTYPE] + internal uint utype; // (type index) underlying type of the array + internal uint diminfo; // (type index) dimension information + internal string name; // length prefixed name + }; + + // type record describing path to virtual function table + + internal struct LeafVFTPath { + // internal ushort leaf; // LF_VFTPATH [TYPTYPE] + internal uint count; // count of number of bases in path + internal uint[] bases; // (type index) bases from root to leaf + }; + + // type record describing inclusion of precompiled types + + internal struct LeafPreComp { + // internal ushort leaf; // LF_PRECOMP [TYPTYPE] + internal uint start; // starting type index included + internal uint count; // number of types in inclusion + internal uint signature; // signature + internal string name; // length prefixed name of included type file + }; + + // type record describing end of precompiled types that can be + // included by another file + + internal struct LeafEndPreComp { + // internal ushort leaf; // LF_ENDPRECOMP [TYPTYPE] + internal uint signature; // signature + }; + + // type record for OEM definable type strings + + internal struct LeafOEM { + // internal ushort leaf; // LF_OEM [TYPTYPE] + internal ushort cvOEM; // MS assigned OEM identified + internal ushort recOEM; // OEM assigned type identifier + internal uint count; // count of type indices to follow + internal uint[] index; // (type index) array of type indices followed + // by OEM defined data + }; + + internal enum OEM_ID { + OEM_MS_FORTRAN90=0xF090, + OEM_ODI=0x0010, + OEM_THOMSON_SOFTWARE=0x5453, + OEM_ODI_REC_BASELIST=0x0000, + }; + + internal struct LeafOEM2 { + // internal ushort leaf; // LF_OEM2 [TYPTYPE] + internal Guid idOem; // an oem ID (Guid) + internal uint count; // count of type indices to follow + internal uint[] index; // (type index) array of type indices followed + // by OEM defined data + }; + + // type record describing using of a type server + + internal struct LeafTypeServer { + // internal ushort leaf; // LF_TYPESERVER [TYPTYPE] + internal uint signature; // signature + internal uint age; // age of database used by this module + internal string name; // length prefixed name of PDB + }; + + // type record describing using of a type server with v7 (GUID) signatures + + internal struct LeafTypeServer2 { + // internal ushort leaf; // LF_TYPESERVER2 [TYPTYPE] + internal Guid sig70; // guid signature + internal uint age; // age of database used by this module + internal string name; // length prefixed name of PDB + }; + + // description of type records that can be referenced from + // type records referenced by symbols + + // type record for skip record + + internal struct LeafSkip { + // internal ushort leaf; // LF_SKIP [TYPTYPE] + internal uint type; // (type index) next valid index + internal byte[] data; // pad data + }; + + // argument list leaf + + internal struct LeafArgList { + // internal ushort leaf; // LF_ARGLIST [TYPTYPE] + internal uint count; // number of arguments + internal uint[] arg; // (type index) number of arguments + }; + + // derived class list leaf + + internal struct LeafDerived { + // internal ushort leaf; // LF_DERIVED [TYPTYPE] + internal uint count; // number of arguments + internal uint[] drvdcls; // (type index) type indices of derived classes + }; + + // leaf for default arguments + + internal struct LeafDefArg { + // internal ushort leaf; // LF_DEFARG [TYPTYPE] + internal uint type; // (type index) type of resulting expression + internal byte[] expr; // length prefixed expression string + }; + + // list leaf + // This list should no longer be used because the utilities cannot + // verify the contents of the list without knowing what type of list + // it is. New specific leaf indices should be used instead. + + internal struct LeafList { + // internal ushort leaf; // LF_LIST [TYPTYPE] + internal byte[] data; // data format specified by indexing type + }; + + // field list leaf + // This is the header leaf for a complex list of class and structure + // subfields. + + internal struct LeafFieldList { + // internal ushort leaf; // LF_FIELDLIST [TYPTYPE] + internal char[] data; // field list sub lists + }; + + // type record for non-static methods and friends in overloaded method list + + internal struct mlMethod { + internal ushort attr; // (CV_fldattr_t) method attribute + internal ushort pad0; // internal padding, must be 0 + internal uint index; // (type index) index to type record for procedure + internal uint[] vbaseoff; // offset in vfunctable if intro virtual + }; + + internal struct LeafMethodList { + // internal ushort leaf; // LF_METHODLIST [TYPTYPE] + internal byte[] mList; // really a mlMethod type + }; + + // type record for LF_BITFIELD + + internal struct LeafBitfield { + // internal ushort leaf; // LF_BITFIELD [TYPTYPE] + internal uint type; // (type index) type of bitfield + internal byte length; + internal byte position; + }; + + // type record for dimensioned array with constant bounds + + internal struct LeafDimCon { + // internal ushort leaf; // LF_DIMCONU or LF_DIMCONLU [TYPTYPE] + internal uint typ; // (type index) type of index + internal ushort rank; // number of dimensions + internal byte[] dim; // array of dimension information with + // either upper bounds or lower/upper bound + }; + + // type record for dimensioned array with variable bounds + + internal struct LeafDimVar { + // internal ushort leaf; // LF_DIMVARU or LF_DIMVARLU [TYPTYPE] + internal uint rank; // number of dimensions + internal uint typ; // (type index) type of index + internal uint[] dim; // (type index) array of type indices for either + // variable upper bound or variable + // lower/upper bound. The count of type + // indices is rank or rank*2 depending on + // whether it is LFDIMVARU or LF_DIMVARLU. + // The referenced types must be + // LF_REFSYM or T_VOID + }; + + // type record for referenced symbol + + internal struct LeafRefSym { + // internal ushort leaf; // LF_REFSYM [TYPTYPE] + internal byte[] Sym; // copy of referenced symbol record + // (including length) + }; + + // the following are numeric leaves. They are used to indicate the + // size of the following variable length data. When the numeric + // data is a single byte less than 0x8000, then the data is output + // directly. If the data is more the 0x8000 or is a negative value, + // then the data is preceeded by the proper index. + // + + // signed character leaf + + internal struct LeafChar { + // internal ushort leaf; // LF_CHAR [TYPTYPE] + internal sbyte val; // signed 8-bit value + }; + + // signed short leaf + + internal struct LeafShort { + // internal ushort leaf; // LF_SHORT [TYPTYPE] + internal short val; // signed 16-bit value + }; + + // ushort leaf + + internal struct LeafUShort { + // internal ushort leaf; // LF_ushort [TYPTYPE] + internal ushort val; // unsigned 16-bit value + }; + + // signed (32-bit) long leaf + + internal struct LeafLong { + // internal ushort leaf; // LF_LONG [TYPTYPE] + internal int val; // signed 32-bit value + }; + + // uint leaf + + internal struct LeafULong { + // internal ushort leaf; // LF_ULONG [TYPTYPE] + internal uint val; // unsigned 32-bit value + }; + + // signed quad leaf + + internal struct LeafQuad { + // internal ushort leaf; // LF_QUAD [TYPTYPE] + internal long val; // signed 64-bit value + }; + + // unsigned quad leaf + + internal struct LeafUQuad { + // internal ushort leaf; // LF_UQUAD [TYPTYPE] + internal ulong val; // unsigned 64-bit value + }; + + // signed int128 leaf + + internal struct LeafOct { + // internal ushort leaf; // LF_OCT [TYPTYPE] + internal ulong val0; + internal ulong val1; // signed 128-bit value + }; + + // unsigned int128 leaf + + internal struct LeafUOct { + // internal ushort leaf; // LF_UOCT [TYPTYPE] + internal ulong val0; + internal ulong val1; // unsigned 128-bit value + }; + + // real 32-bit leaf + + internal struct LeafReal32 { + // internal ushort leaf; // LF_REAL32 [TYPTYPE] + internal float val; // 32-bit real value + }; + + // real 64-bit leaf + + internal struct LeafReal64 { + // internal ushort leaf; // LF_REAL64 [TYPTYPE] + internal double val; // 64-bit real value + }; + + // real 80-bit leaf + + internal struct LeafReal80 { + // internal ushort leaf; // LF_REAL80 [TYPTYPE] + internal FLOAT10 val; // real 80-bit value + }; + + // real 128-bit leaf + + internal struct LeafReal128 { + // internal ushort leaf; // LF_REAL128 [TYPTYPE] + internal ulong val0; + internal ulong val1; // real 128-bit value + }; + + // complex 32-bit leaf + + internal struct LeafCmplx32 { + // internal ushort leaf; // LF_COMPLEX32 [TYPTYPE] + internal float val_real; // real component + internal float val_imag; // imaginary component + }; + + // complex 64-bit leaf + + internal struct LeafCmplx64 { + // internal ushort leaf; // LF_COMPLEX64 [TYPTYPE] + internal double val_real; // real component + internal double val_imag; // imaginary component + }; + + // complex 80-bit leaf + + internal struct LeafCmplx80 { + // internal ushort leaf; // LF_COMPLEX80 [TYPTYPE] + internal FLOAT10 val_real; // real component + internal FLOAT10 val_imag; // imaginary component + }; + + // complex 128-bit leaf + + internal struct LeafCmplx128 { + // internal ushort leaf; // LF_COMPLEX128 [TYPTYPE] + internal ulong val0_real; + internal ulong val1_real; // real component + internal ulong val0_imag; + internal ulong val1_imag; // imaginary component + }; + + // variable length numeric field + + internal struct LeafVarString { + // internal ushort leaf; // LF_VARSTRING [TYPTYPE] + internal ushort len; // length of value in bytes + internal byte[] value; // value + }; + + // index leaf - contains type index of another leaf + // a major use of this leaf is to allow the compilers to emit a + // long complex list (LF_FIELD) in smaller pieces. + + internal struct LeafIndex { + // internal ushort leaf; // LF_INDEX [TYPTYPE] + internal ushort pad0; // internal padding, must be 0 + internal uint index; // (type index) type index of referenced leaf + }; + + // subfield record for base class field + + internal struct LeafBClass { + // internal ushort leaf; // LF_BCLASS [TYPTYPE] + internal ushort attr; // (CV_fldattr_t) attribute + internal uint index; // (type index) type index of base class + internal byte[] offset; // variable length offset of base within class + }; + + // subfield record for direct and indirect virtual base class field + + internal struct LeafVBClass { + // internal ushort leaf; // LF_VBCLASS | LV_IVBCLASS [TYPTYPE] + internal ushort attr; // (CV_fldattr_t) attribute + internal uint index; // (type index) type index of direct virtual base class + internal uint vbptr; // (type index) type index of virtual base pointer + internal byte[] vbpoff; // virtual base pointer offset from address point + // followed by virtual base offset from vbtable + }; + + // subfield record for friend class + + internal struct LeafFriendCls { + // internal ushort leaf; // LF_FRIENDCLS [TYPTYPE] + internal ushort pad0; // internal padding, must be 0 + internal uint index; // (type index) index to type record of friend class + }; + + // subfield record for friend function + + internal struct LeafFriendFcn { + // internal ushort leaf; // LF_FRIENDFCN [TYPTYPE] + internal ushort pad0; // internal padding, must be 0 + internal uint index; // (type index) index to type record of friend function + internal string name; // name of friend function + }; + + // subfield record for non-static data members + + internal struct LeafMember { + // internal ushort leaf; // LF_MEMBER [TYPTYPE] + internal ushort attr; // (CV_fldattr_t)attribute mask + internal uint index; // (type index) index of type record for field + internal byte[] offset; // variable length offset of field + internal string name; // length prefixed name of field + }; + + // type record for static data members + + internal struct LeafSTMember { + // internal ushort leaf; // LF_STMEMBER [TYPTYPE] + internal ushort attr; // (CV_fldattr_t) attribute mask + internal uint index; // (type index) index of type record for field + internal string name; // length prefixed name of field + }; + + // subfield record for virtual function table pointer + + internal struct LeafVFuncTab { + // internal ushort leaf; // LF_VFUNCTAB [TYPTYPE] + internal ushort pad0; // internal padding, must be 0 + internal uint type; // (type index) type index of pointer + }; + + // subfield record for virtual function table pointer with offset + + internal struct LeafVFuncOff { + // internal ushort leaf; // LF_VFUNCOFF [TYPTYPE] + internal ushort pad0; // internal padding, must be 0. + internal uint type; // (type index) type index of pointer + internal int offset; // offset of virtual function table pointer + }; + + // subfield record for overloaded method list + + internal struct LeafMethod { + // internal ushort leaf; // LF_METHOD [TYPTYPE] + internal ushort count; // number of occurrences of function + internal uint mList; // (type index) index to LF_METHODLIST record + internal string name; // length prefixed name of method + }; + + // subfield record for nonoverloaded method + + internal struct LeafOneMethod { + // internal ushort leaf; // LF_ONEMETHOD [TYPTYPE] + internal ushort attr; // (CV_fldattr_t) method attribute + internal uint index; // (type index) index to type record for procedure + internal uint[] vbaseoff; // offset in vfunctable if intro virtual + internal string name; + }; + + // subfield record for enumerate + + internal struct LeafEnumerate { + // internal ushort leaf; // LF_ENUMERATE [TYPTYPE] + internal ushort attr; // (CV_fldattr_t) access + internal byte[] value; // variable length value field + internal string name; + }; + + // type record for nested (scoped) type definition + + internal struct LeafNestType { + // internal ushort leaf; // LF_NESTTYPE [TYPTYPE] + internal ushort pad0; // internal padding, must be 0 + internal uint index; // (type index) index of nested type definition + internal string name; // length prefixed type name + }; + + // type record for nested (scoped) type definition, with attributes + // new records for vC v5.0, no need to have 16-bit ti versions. + + internal struct LeafNestTypeEx { + // internal ushort leaf; // LF_NESTTYPEEX [TYPTYPE] + internal ushort attr; // (CV_fldattr_t) member access + internal uint index; // (type index) index of nested type definition + internal string name; // length prefixed type name + }; + + // type record for modifications to members + + internal struct LeafMemberModify { + // internal ushort leaf; // LF_MEMBERMODIFY [TYPTYPE] + internal ushort attr; // (CV_fldattr_t) the new attributes + internal uint index; // (type index) index of base class type definition + internal string name; // length prefixed member name + }; + + // type record for pad leaf + + internal struct LeafPad { + internal byte leaf; + }; + + // Symbol definitions + + internal enum SYM { + S_END=0x0006, // Block, procedure, "with" or thunk end + S_OEM=0x0404, // OEM defined symbol + + S_REGISTER_ST=0x1001, // Register variable + S_CONSTANT_ST=0x1002, // constant symbol + S_UDT_ST=0x1003, // User defined type + S_COBOLUDT_ST=0x1004, // special UDT for cobol that does not symbol pack + S_MANYREG_ST=0x1005, // multiple register variable + S_BPREL32_ST=0x1006, // BP-relative + S_LDATA32_ST=0x1007, // Module-local symbol + S_GDATA32_ST=0x1008, // Global data symbol + S_PUB32_ST=0x1009, // a internal symbol (CV internal reserved) + S_LPROC32_ST=0x100a, // Local procedure start + S_GPROC32_ST=0x100b, // Global procedure start + S_VFTABLE32=0x100c, // address of virtual function table + S_REGREL32_ST=0x100d, // register relative address + S_LTHREAD32_ST=0x100e, // local thread storage + S_GTHREAD32_ST=0x100f, // global thread storage + + S_LPROCMIPS_ST=0x1010, // Local procedure start + S_GPROCMIPS_ST=0x1011, // Global procedure start + + // new symbol records for edit and continue information + + S_FRAMEPROC=0x1012, // extra frame and proc information + S_COMPILE2_ST=0x1013, // extended compile flags and info + + // new symbols necessary for 16-bit enumerates of IA64 registers + // and IA64 specific symbols + + S_MANYREG2_ST=0x1014, // multiple register variable + S_LPROCIA64_ST=0x1015, // Local procedure start (IA64) + S_GPROCIA64_ST=0x1016, // Global procedure start (IA64) + + // Local symbols for IL + S_LOCALSLOT_ST=0x1017, // local IL sym with field for local slot index + S_PARAMSLOT_ST=0x1018, // local IL sym with field for parameter slot index + + S_ANNOTATION=0x1019, // Annotation string literals + + // symbols to support managed code debugging + S_GMANPROC_ST=0x101a, // Global proc + S_LMANPROC_ST=0x101b, // Local proc + S_RESERVED1=0x101c, // reserved + S_RESERVED2=0x101d, // reserved + S_RESERVED3=0x101e, // reserved + S_RESERVED4=0x101f, // reserved + S_LMANDATA_ST=0x1020, + S_GMANDATA_ST=0x1021, + S_MANFRAMEREL_ST=0x1022, + S_MANREGISTER_ST=0x1023, + S_MANSLOT_ST=0x1024, + S_MANMANYREG_ST=0x1025, + S_MANREGREL_ST=0x1026, + S_MANMANYREG2_ST=0x1027, + S_MANTYPREF=0x1028, // Index for type referenced by name from metadata + S_UNAMESPACE_ST=0x1029, // Using namespace + + // Symbols w/ SZ name fields. All name fields contain utf8 encoded strings. + S_ST_MAX=0x1100, // starting point for SZ name symbols + + S_OBJNAME=0x1101, // path to object file name + S_THUNK32=0x1102, // Thunk Start + S_BLOCK32=0x1103, // block start + S_WITH32=0x1104, // with start + S_LABEL32=0x1105, // code label + S_REGISTER=0x1106, // Register variable + S_CONSTANT=0x1107, // constant symbol + S_UDT=0x1108, // User defined type + S_COBOLUDT=0x1109, // special UDT for cobol that does not symbol pack + S_MANYREG=0x110a, // multiple register variable + S_BPREL32=0x110b, // BP-relative + S_LDATA32=0x110c, // Module-local symbol + S_GDATA32=0x110d, // Global data symbol + S_PUB32=0x110e, // a internal symbol (CV internal reserved) + S_LPROC32=0x110f, // Local procedure start + S_GPROC32=0x1110, // Global procedure start + S_REGREL32=0x1111, // register relative address + S_LTHREAD32=0x1112, // local thread storage + S_GTHREAD32=0x1113, // global thread storage + + S_LPROCMIPS=0x1114, // Local procedure start + S_GPROCMIPS=0x1115, // Global procedure start + S_COMPILE2=0x1116, // extended compile flags and info + S_MANYREG2=0x1117, // multiple register variable + S_LPROCIA64=0x1118, // Local procedure start (IA64) + S_GPROCIA64=0x1119, // Global procedure start (IA64) + S_LOCALSLOT=0x111a, // local IL sym with field for local slot index + S_SLOT=S_LOCALSLOT, // alias for LOCALSLOT + S_PARAMSLOT=0x111b, // local IL sym with field for parameter slot index + + // symbols to support managed code debugging + S_LMANDATA=0x111c, + S_GMANDATA=0x111d, + S_MANFRAMEREL=0x111e, + S_MANREGISTER=0x111f, + S_MANSLOT=0x1120, + S_MANMANYREG=0x1121, + S_MANREGREL=0x1122, + S_MANMANYREG2=0x1123, + S_UNAMESPACE=0x1124, // Using namespace + + // ref symbols with name fields + S_PROCREF=0x1125, // Reference to a procedure + S_DATAREF=0x1126, // Reference to data + S_LPROCREF=0x1127, // Local Reference to a procedure + S_ANNOTATIONREF=0x1128, // Reference to an S_ANNOTATION symbol + S_TOKENREF=0x1129, // Reference to one of the many MANPROCSYM's + + // continuation of managed symbols + S_GMANPROC=0x112a, // Global proc + S_LMANPROC=0x112b, // Local proc + + // short, light-weight thunks + S_TRAMPOLINE=0x112c, // trampoline thunks + S_MANCONSTANT=0x112d, // constants with metadata type info + + // native attributed local/parms + S_ATTR_FRAMEREL=0x112e, // relative to virtual frame ptr + S_ATTR_REGISTER=0x112f, // stored in a register + S_ATTR_REGREL=0x1130, // relative to register (alternate frame ptr) + S_ATTR_MANYREG=0x1131, // stored in >1 register + + // Separated code (from the compiler) support + S_SEPCODE=0x1132, + + S_LOCAL=0x1133, // defines a local symbol in optimized code + S_DEFRANGE=0x1134, // defines a single range of addresses in which symbol can be evaluated + S_DEFRANGE2=0x1135, // defines ranges of addresses in which symbol can be evaluated + + S_SECTION=0x1136, // A COFF section in a PE executable + S_COFFGROUP=0x1137, // A COFF group + S_EXPORT=0x1138, // A export + + S_CALLSITEINFO=0x1139, // Indirect call site information + S_FRAMECOOKIE=0x113a, // Security cookie information + + S_DISCARDED=0x113b, // Discarded by LINK /OPT:REF (experimental, see richards) + + S_RECTYPE_MAX, // one greater than last + S_RECTYPE_LAST=S_RECTYPE_MAX - 1, + + }; + + // enum describing compile flag ambient data model + + internal enum CV_CFL_DATA { + CV_CFL_DNEAR=0x00, + CV_CFL_DFAR=0x01, + CV_CFL_DHUGE=0x02 + }; + + // enum describing compile flag ambiant code model + + internal enum CV_CFL_CODE { + CV_CFL_CNEAR=0x00, + CV_CFL_CFAR=0x01, + CV_CFL_CHUGE=0x02 + }; + + // enum describing compile flag target floating point package + + internal enum CV_CFL_FPKG { + CV_CFL_NDP=0x00, + CV_CFL_EMU=0x01, + CV_CFL_ALT=0x02 + }; + + // enum describing function return method + + [Flags] + internal enum CV_PROCFLAGS : byte { + CV_PFLAG_NOFPO=0x01, // frame pointer present + CV_PFLAG_INT=0x02, // interrupt return + CV_PFLAG_FAR=0x04, // far return + CV_PFLAG_NEVER=0x08, // function does not return + CV_PFLAG_NOTREACHED=0x10, // label isn't fallen into + CV_PFLAG_CUST_CALL=0x20, // custom calling convention + CV_PFLAG_NOINLINE=0x40, // function marked as noinline + CV_PFLAG_OPTDBGINFO=0x80, // function has debug information for optimized code + }; + + // Extended proc flags + // + internal struct CV_EXPROCFLAGS { + internal byte flags; // (CV_PROCFLAGS) + internal byte reserved; // must be zero + }; + + // local variable flags + [Flags] + internal enum CV_LVARFLAGS : ushort { + fIsParam=0x0001, // variable is a parameter + fAddrTaken=0x0002, // address is taken + fCompGenx=0x0004, // variable is compiler generated + fIsAggregate=0x0008, // the symbol is splitted in temporaries, + // which are treated by compiler as + // independent entities + fIsAggregated=0x0010, // Counterpart of fIsAggregate - tells + // that it is a part of a fIsAggregate symbol + fIsAliased=0x0020, // variable has multiple simultaneous lifetimes + fIsAlias=0x0040, // represents one of the multiple simultaneous lifetimes + }; + + // represents an address range, used for optimized code debug info + internal struct CV_lvar_addr_range { // defines a range of addresses + internal uint offStart; + internal ushort isectStart; + internal uint cbRange; + }; + + // enum describing function data return method + + internal enum CV_GENERIC_STYLE { + CV_GENERIC_VOID=0x00, // void return type + CV_GENERIC_REG=0x01, // return data is in registers + CV_GENERIC_ICAN=0x02, // indirect caller allocated near + CV_GENERIC_ICAF=0x03, // indirect caller allocated far + CV_GENERIC_IRAN=0x04, // indirect returnee allocated near + CV_GENERIC_IRAF=0x05, // indirect returnee allocated far + CV_GENERIC_UNUSED=0x06 // first unused + }; + + [Flags] + internal enum CV_GENERIC_FLAG : ushort { + cstyle=0x0001, // true push varargs right to left + rsclean=0x0002, // true if returnee stack cleanup + }; + + // flag bitfields for separated code attributes + + [Flags] + internal enum CV_SEPCODEFLAGS : uint { + fIsLexicalScope=0x00000001, // S_SEPCODE doubles as lexical scope + fReturnsToParent=0x00000002, // code frag returns to parent + }; + + // Generic layout for symbol records + + internal struct SYMTYPE { + internal ushort reclen; // Record length + internal ushort rectyp; // Record type + // byte data[CV_ZEROLEN]; + // SYMTYPE *NextSym (SYMTYPE * pSym) { + // return (SYMTYPE *) ((char *)pSym + pSym->reclen + sizeof(ushort)); + // } + }; + + // non-model specific symbol types + + internal struct RegSym { + // internal ushort reclen; // Record length [SYMTYPE] + // internal ushort rectyp; // S_REGISTER + internal uint typind; // (type index) Type index or Metadata token + internal ushort reg; // register enumerate + internal string name; // Length-prefixed name + }; + + internal struct AttrRegSym { + // internal ushort reclen; // Record length [SYMTYPE] + // internal ushort rectyp; // S_MANREGISTER | S_ATTR_REGISTER + internal uint typind; // (type index) Type index or Metadata token + internal uint offCod; // first code address where var is live + internal ushort segCod; + internal ushort flags; // (CV_LVARFLAGS)local var flags + internal ushort reg; // register enumerate + internal string name; // Length-prefixed name + }; + + internal struct ManyRegSym { + // internal ushort reclen; // Record length [SYMTYPE] + // internal ushort rectyp; // S_MANYREG + internal uint typind; // (type index) Type index or metadata token + internal byte count; // count of number of registers + internal byte[] reg; // count register enumerates, most-sig first + internal string name; // length-prefixed name. + }; + + internal struct ManyRegSym2 { + // internal ushort reclen; // Record length [SYMTYPE] + // internal ushort rectyp; // S_MANYREG2 + internal uint typind; // (type index) Type index or metadata token + internal ushort count; // count of number of registers, + internal ushort[] reg; // count register enumerates, most-sig first + internal string name; // length-prefixed name. + }; + + internal struct AttrManyRegSym { + // internal ushort reclen; // Record length [SYMTYPE] + // internal ushort rectyp; // S_MANMANYREG + internal uint typind; // (type index) Type index or metadata token + internal uint offCod; // first code address where var is live + internal ushort segCod; + internal ushort flags; // (CV_LVARFLAGS)local var flags + internal byte count; // count of number of registers + internal byte[] reg; // count register enumerates, most-sig first + internal string name; // utf-8 encoded zero terminate name + }; + + internal struct AttrManyRegSym2 { + // internal ushort reclen; // Record length [SYMTYPE] + // internal ushort rectyp; // S_MANMANYREG2 | S_ATTR_MANYREG + internal uint typind; // (type index) Type index or metadata token + internal uint offCod; // first code address where var is live + internal ushort segCod; + internal ushort flags; // (CV_LVARFLAGS)local var flags + internal ushort count; // count of number of registers + internal ushort[] reg; // count register enumerates, most-sig first + internal string name; // utf-8 encoded zero terminate name + }; + + internal struct ConstSym { + // internal ushort reclen; // Record length [SYMTYPE] + // internal ushort rectyp; // S_CONSTANT or S_MANCONSTANT + internal uint typind; // (type index) Type index (containing enum if enumerate) or metadata token + internal ushort value; // numeric leaf containing value + internal string name; // Length-prefixed name + }; + + internal struct UdtSym { + // internal ushort reclen; // Record length [SYMTYPE] + // internal ushort rectyp; // S_UDT | S_COBOLUDT + internal uint typind; // (type index) Type index + internal string name; // Length-prefixed name + }; + + internal struct ManyTypRef { + // internal ushort reclen; // Record length [SYMTYPE] + // internal ushort rectyp; // S_MANTYPREF + internal uint typind; // (type index) Type index + }; + + internal struct SearchSym { + // internal ushort reclen; // Record length [SYMTYPE] + // internal ushort rectyp; // S_SSEARCH + internal uint startsym; // offset of the procedure + internal ushort seg; // segment of symbol + }; + + [Flags] + internal enum CFLAGSYM_FLAGS : ushort { + pcode=0x0001, // true if pcode present + floatprec=0x0006, // floating precision + floatpkg=0x0018, // float package + ambdata=0x00e0, // ambient data model + ambcode=0x0700, // ambient code model + mode32=0x0800, // true if compiled 32 bit mode + }; + + internal struct CFlagSym { + // internal ushort reclen; // Record length [SYMTYPE] + // internal ushort rectyp; // S_COMPILE + internal byte machine; // target processor + internal byte language; // language index + internal ushort flags; // (CFLAGSYM_FLAGS) + internal string ver; // Length-prefixed compiler version string + }; + + [Flags] + internal enum COMPILESYM_FLAGS : uint { + iLanguage=0x000000ff, // language index + fEC=0x00000100, // compiled for E/C + fNoDbgInfo=0x00000200, // not compiled with debug info + fLTCG=0x00000400, // compiled with LTCG + fNoDataAlign=0x00000800, // compiled with -Bzalign + fManagedPresent=0x00001000, // managed code/data present + fSecurityChecks=0x00002000, // compiled with /GS + fHotPatch=0x00004000, // compiled with /hotpatch + fCVTCIL=0x00008000, // converted with CVTCIL + fMSILModule=0x00010000, // MSIL netmodule + }; + + internal struct CompileSym { + // internal ushort reclen; // Record length [SYMTYPE] + // internal ushort rectyp; // S_COMPILE2 + internal uint flags; // (COMPILESYM_FLAGS) + internal ushort machine; // target processor + internal ushort verFEMajor; // front end major version # + internal ushort verFEMinor; // front end minor version # + internal ushort verFEBuild; // front end build version # + internal ushort verMajor; // back end major version # + internal ushort verMinor; // back end minor version # + internal ushort verBuild; // back end build version # + internal string verSt; // Length-prefixed compiler version string, followed + internal string[] verArgs; // block of zero terminated strings, ended by double-zero. + }; + + internal struct ObjNameSym { + // internal ushort reclen; // Record length [SYMTYPE] + // internal ushort rectyp; // S_OBJNAME + internal uint signature; // signature + internal string name; // Length-prefixed name + }; + + internal struct EndArgSym { + // internal ushort reclen; // Record length [SYMTYPE] + // internal ushort rectyp; // S_ENDARG + }; + + internal struct ReturnSym { + // internal ushort reclen; // Record length [SYMTYPE] + // internal ushort rectyp; // S_RETURN + internal CV_GENERIC_FLAG flags; // flags + internal byte style; // CV_GENERIC_STYLE return style + // followed by return method data + }; + + internal struct EntryThisSym { + // internal ushort reclen; // Record length [SYMTYPE] + // internal ushort rectyp; // S_ENTRYTHIS + internal byte thissym; // symbol describing this pointer on entry + }; + + internal struct BpRelSym32 { + // internal ushort reclen; // Record length [SYMTYPE] + // internal ushort rectyp; // S_BPREL32 + internal int off; // BP-relative offset + internal uint typind; // (type index) Type index or Metadata token + internal string name; // Length-prefixed name + }; + + internal struct FrameRelSym { + // internal ushort reclen; // Record length [SYMTYPE] + // internal ushort rectyp; // S_MANFRAMEREL | S_ATTR_FRAMEREL + internal int off; // Frame relative offset + internal uint typind; // (type index) Type index or Metadata token + internal uint offCod; // first code address where var is live + internal ushort segCod; + internal ushort flags; // (CV_LVARFLAGS)local var flags + internal string name; // Length-prefixed name + }; + + internal struct SlotSym32 { + // internal ushort reclen; // Record length [SYMTYPE] + // internal ushort rectyp; // S_LOCALSLOT or S_PARAMSLOT + internal uint index; // slot index + internal uint typind; // (type index) Type index or Metadata token + internal string name; // Length-prefixed name + }; + + internal struct AttrSlotSym { + // internal ushort reclen; // Record length [SYMTYPE] + // internal ushort rectyp; // S_MANSLOT + internal uint index; // slot index + internal uint typind; // (type index) Type index or Metadata token + internal uint offCod; // first code address where var is live + internal ushort segCod; + internal ushort flags; // (CV_LVARFLAGS)local var flags + internal string name; // Length-prefixed name + + }; + + internal struct AnnotationSym { + // internal ushort reclen; // Record length [SYMTYPE] + // internal ushort rectyp; // S_ANNOTATION + internal uint off; + internal ushort seg; + internal ushort csz; // Count of zero terminated annotation strings + internal string[] rgsz; // Sequence of zero terminated annotation strings + }; + + internal struct DatasSym32 { + // internal ushort reclen; // Record length [SYMTYPE] + // internal ushort rectyp; // S_LDATA32, S_GDATA32 or S_PUB32, S_LMANDATA, S_GMANDATA + internal uint typind; // (type index) Type index, or Metadata token if a managed symbol + internal uint off; + internal ushort seg; + internal string name; // Length-prefixed name + }; + + [Flags] + internal enum CV_PUBSYMFLAGS : uint { + fNone=0, + fCode=0x00000001, // set if internal symbol refers to a code address + fFunction=0x00000002, // set if internal symbol is a function + fManaged=0x00000004, // set if managed code (native or IL) + fMSIL=0x00000008, // set if managed IL code + }; + + internal struct PubSym32 { + // internal ushort reclen; // Record length [SYMTYPE] + // internal ushort rectyp; // S_PUB32 + internal uint flags; // (CV_PUBSYMFLAGS) + internal uint off; + internal ushort seg; + internal string name; // Length-prefixed name + }; + + internal struct ProcSym32 { + // internal ushort reclen; // Record length [SYMTYPE] + // internal ushort rectyp; // S_GPROC32 or S_LPROC32 + internal uint parent; // pointer to the parent + internal uint end; // pointer to this blocks end + internal uint next; // pointer to next symbol + internal uint len; // Proc length + internal uint dbgStart; // Debug start offset + internal uint dbgEnd; // Debug end offset + internal uint typind; // (type index) Type index + internal uint off; + internal ushort seg; + internal byte flags; // (CV_PROCFLAGS) Proc flags + internal string name; // Length-prefixed name + }; + + internal struct ManProcSym { + // internal ushort reclen; // Record length [SYMTYPE] + // internal ushort rectyp; // S_GMANPROC, S_LMANPROC, S_GMANPROCIA64 or S_LMANPROCIA64 + internal uint parent; // pointer to the parent + internal uint end; // pointer to this blocks end + internal uint next; // pointer to next symbol + internal uint len; // Proc length + internal uint dbgStart; // Debug start offset + internal uint dbgEnd; // Debug end offset + internal uint token; // COM+ metadata token for method + internal uint off; + internal ushort seg; + internal byte flags; // (CV_PROCFLAGS) Proc flags + internal ushort retReg; // Register return value is in (may not be used for all archs) + internal string name; // optional name field + }; + + internal struct ManProcSymMips { + // internal ushort reclen; // Record length [SYMTYPE] + // internal ushort rectyp; // S_GMANPROCMIPS or S_LMANPROCMIPS + internal uint parent; // pointer to the parent + internal uint end; // pointer to this blocks end + internal uint next; // pointer to next symbol + internal uint len; // Proc length + internal uint dbgStart; // Debug start offset + internal uint dbgEnd; // Debug end offset + internal uint regSave; // int register save mask + internal uint fpSave; // fp register save mask + internal uint intOff; // int register save offset + internal uint fpOff; // fp register save offset + internal uint token; // COM+ token type + internal uint off; + internal ushort seg; + internal byte retReg; // Register return value is in + internal byte frameReg; // Frame pointer register + internal string name; // optional name field + }; + + internal struct ThunkSym32 { + // internal ushort reclen; // Record length [SYMTYPE] + // internal ushort rectyp; // S_THUNK32 + internal uint parent; // pointer to the parent + internal uint end; // pointer to this blocks end + internal uint next; // pointer to next symbol + internal uint off; + internal ushort seg; + internal ushort len; // length of thunk + internal byte ord; // THUNK_ORDINAL specifying type of thunk + internal string name; // Length-prefixed name + internal byte[] variant; // variant portion of thunk + }; + + internal enum TRAMP { // Trampoline subtype + trampIncremental, // incremental thunks + trampBranchIsland, // Branch island thunks + }; + + internal struct TrampolineSym { // Trampoline thunk symbol + // internal ushort reclen; // Record length [SYMTYPE] + // internal ushort rectyp; // S_TRAMPOLINE + internal ushort trampType; // trampoline sym subtype + internal ushort cbThunk; // size of the thunk + internal uint offThunk; // offset of the thunk + internal uint offTarget; // offset of the target of the thunk + internal ushort sectThunk; // section index of the thunk + internal ushort sectTarget; // section index of the target of the thunk + }; + + internal struct LabelSym32 { + // internal ushort reclen; // Record length [SYMTYPE] + // internal ushort rectyp; // S_LABEL32 + internal uint off; + internal ushort seg; + internal byte flags; // (CV_PROCFLAGS) flags + internal string name; // Length-prefixed name + }; + + internal struct BlockSym32 { + // internal ushort reclen; // Record length [SYMTYPE] + // internal ushort rectyp; // S_BLOCK32 + internal uint parent; // pointer to the parent + internal uint end; // pointer to this blocks end + internal uint len; // Block length + internal uint off; // Offset in code segment + internal ushort seg; // segment of label + internal string name; // Length-prefixed name + }; + + internal struct WithSym32 { + // internal ushort reclen; // Record length [SYMTYPE] + // internal ushort rectyp; // S_WITH32 + internal uint parent; // pointer to the parent + internal uint end; // pointer to this blocks end + internal uint len; // Block length + internal uint off; // Offset in code segment + internal ushort seg; // segment of label + internal string expr; // Length-prefixed expression string + }; + + internal struct VpathSym32 { + // internal ushort reclen; // record length + // internal ushort rectyp; // S_VFTABLE32 + internal uint root; // (type index) type index of the root of path + internal uint path; // (type index) type index of the path record + internal uint off; // offset of virtual function table + internal ushort seg; // segment of virtual function table + }; + + internal struct RegRel32 { + // internal ushort reclen; // Record length [SYMTYPE] + // internal ushort rectyp; // S_REGREL32 + internal uint off; // offset of symbol + internal uint typind; // (type index) Type index or metadata token + internal ushort reg; // register index for symbol + internal string name; // Length-prefixed name + }; + + internal struct AttrRegRel { + // internal ushort reclen; // Record length [SYMTYPE] + // internal ushort rectyp; // S_MANREGREL | S_ATTR_REGREL + internal uint off; // offset of symbol + internal uint typind; // (type index) Type index or metadata token + internal ushort reg; // register index for symbol + internal uint offCod; // first code address where var is live + internal ushort segCod; + internal ushort flags; // (CV_LVARFLAGS)local var flags + internal string name; // Length-prefixed name + }; + + internal struct ThreadSym32 { + // internal ushort reclen; // record length + // internal ushort rectyp; // S_LTHREAD32 | S_GTHREAD32 + internal uint typind; // (type index) type index + internal uint off; // offset into thread storage + internal ushort seg; // segment of thread storage + internal string name; // length prefixed name + }; + + internal struct Slink32 { + // internal ushort reclen; // record length + // internal ushort rectyp; // S_SLINK32 + internal uint framesize; // frame size of parent procedure + internal int off; // signed offset where the static link was saved relative to the value of reg + internal ushort reg; + }; + + internal struct ProcSymMips { + // internal ushort reclen; // Record length [SYMTYPE] + // internal ushort rectyp; // S_GPROCMIPS or S_LPROCMIPS + internal uint parent; // pointer to the parent + internal uint end; // pointer to this blocks end + internal uint next; // pointer to next symbol + internal uint len; // Proc length + internal uint dbgStart; // Debug start offset + internal uint dbgEnd; // Debug end offset + internal uint regSave; // int register save mask + internal uint fpSave; // fp register save mask + internal uint intOff; // int register save offset + internal uint fpOff; // fp register save offset + internal uint typind; // (type index) Type index + internal uint off; // Symbol offset + internal ushort seg; // Symbol segment + internal byte retReg; // Register return value is in + internal byte frameReg; // Frame pointer register + internal string name; // Length-prefixed name + }; + + internal struct ProcSymIa64 { + // internal ushort reclen; // Record length [SYMTYPE] + // internal ushort rectyp; // S_GPROCIA64 or S_LPROCIA64 + internal uint parent; // pointer to the parent + internal uint end; // pointer to this blocks end + internal uint next; // pointer to next symbol + internal uint len; // Proc length + internal uint dbgStart; // Debug start offset + internal uint dbgEnd; // Debug end offset + internal uint typind; // (type index) Type index + internal uint off; // Symbol offset + internal ushort seg; // Symbol segment + internal ushort retReg; // Register return value is in + internal byte flags; // (CV_PROCFLAGS) Proc flags + internal string name; // Length-prefixed name + }; + + internal struct RefSym { + // internal ushort reclen; // Record length [SYMTYPE] + // internal ushort rectyp; // S_PROCREF_ST, S_DATAREF_ST, or S_LPROCREF_ST + internal uint sumName; // SUC of the name + internal uint ibSym; // Offset of actual symbol in $$Symbols + internal ushort imod; // Module containing the actual symbol + internal ushort usFill; // align this record + }; + + internal struct RefSym2 { + // internal ushort reclen; // Record length [SYMTYPE] + // internal ushort rectyp; // S_PROCREF, S_DATAREF, or S_LPROCREF + internal uint sumName; // SUC of the name + internal uint ibSym; // Offset of actual symbol in $$Symbols + internal ushort imod; // Module containing the actual symbol + internal string name; // hidden name made a first class member + }; + + internal struct AlignSym { + // internal ushort reclen; // Record length [SYMTYPE] + // internal ushort rectyp; // S_ALIGN + }; + + internal struct OemSymbol { + // internal ushort reclen; // Record length [SYMTYPE] + // internal ushort rectyp; // S_OEM + internal Guid idOem; // an oem ID (GUID) + internal uint typind; // (type index) Type index + internal byte[] rgl; // user data, force 4-byte alignment + }; + + [Flags] + internal enum FRAMEPROCSYM_FLAGS : uint { + fHasAlloca=0x00000001, // function uses _alloca() + fHasSetJmp=0x00000002, // function uses setjmp() + fHasLongJmp=0x00000004, // function uses longjmp() + fHasInlAsm=0x00000008, // function uses inline asm + fHasEH=0x00000010, // function has EH states + fInlSpec=0x00000020, // function was speced as inline + fHasSEH=0x00000040, // function has SEH + fNaked=0x00000080, // function is __declspec(naked) + fSecurityChecks=0x00000100, // function has buffer security check introduced by /GS. + fAsyncEH=0x00000200, // function compiled with /EHa + fGSNoStackOrdering=0x00000400, // function has /GS buffer checks, but stack ordering couldn't be done + fWasInlined=0x00000800, // function was inlined within another function + }; + + internal struct FrameProcSym { + // internal ushort reclen; // Record length [SYMTYPE] + // internal ushort rectyp; // S_FRAMEPROC + internal uint cbFrame; // count of bytes of total frame of procedure + internal uint cbPad; // count of bytes of padding in the frame + internal uint offPad; // offset (rel to frame) to where padding starts + internal uint cbSaveRegs; // count of bytes of callee save registers + internal uint offExHdlr; // offset of exception handler + internal ushort secExHdlr; // section id of exception handler + internal uint flags; // (FRAMEPROCSYM_FLAGS) + } + + internal struct UnamespaceSym { + // internal ushort reclen; // Record length [SYMTYPE] + // internal ushort rectyp; // S_UNAMESPACE + internal string name; // name + }; + + internal struct SepCodSym { + // internal ushort reclen; // Record length [SYMTYPE] + // internal ushort rectyp; // S_SEPCODE + internal uint parent; // pointer to the parent + internal uint end; // pointer to this block's end + internal uint length; // count of bytes of this block + internal uint scf; // (CV_SEPCODEFLAGS) flags + internal uint off; // sec:off of the separated code + internal uint offParent; // secParent:offParent of the enclosing scope + internal ushort sec; // (proc, block, or sepcode) + internal ushort secParent; + }; + + internal struct LocalSym { + // internal ushort reclen; // Record length [SYMTYPE] + // internal ushort rectyp; // S_LOCAL + internal uint id; // id of the local + internal uint typind; // (type index) type index + internal ushort flags; // (CV_LVARFLAGS) local var flags + internal uint idParent; // This is is parent variable - fIsAggregated or fIsAlias + internal uint offParent; // Offset in parent variable - fIsAggregated + + internal uint expr; // NI of expression that this temp holds + internal uint pad0; // pad, must be zero + internal uint pad1; // pad, must be zero + + internal string name; // Name of this symbol. + } + + internal struct DefRangeSym { + // internal ushort reclen; // Record length [SYMTYPE] + // internal ushort rectyp; // S_DEFRANGE + + internal uint id; // ID of the local symbol for which this formula holds + internal uint program; // program to evaluate the value of the symbol + + internal CV_lvar_addr_range range; // Range of addresses where this program is valid + }; + + internal struct DefRangeSym2 { + // internal ushort reclen; // Record length [SYMTYPE] + // internal ushort rectyp; // S_DEFRANGE2 + + internal uint id; // ID of the local symbol for which this formula holds + internal uint program; // program to evaluate the value of the symbol + + internal ushort count; // count of CV_lvar_addr_range records following + internal CV_lvar_addr_range[] range;// Range of addresses where this program is valid + }; + + internal struct SectionSym { + // internal ushort reclen // Record length + // internal ushort rectyp; // S_SECTION + + internal ushort isec; // Section number + internal byte align; // Alignment of this section (power of 2) + internal byte bReserved; // Reserved. Must be zero. + internal uint rva; + internal uint cb; + internal uint characteristics; + internal string name; // name + }; + + internal struct CoffGroupSym { + // internal ushort reclen; // Record length [SYMTYPE] + // internal ushort rectyp; // S_COFFGROUP + + internal uint cb; + internal uint characteristics; + internal uint off; // Symbol offset + internal ushort seg; // Symbol segment + internal string name; // name + }; + + [Flags] + internal enum EXPORTSYM_FLAGS : ushort { + fConstant=0x0001, // CONSTANT + fData=0x0002, // DATA + fPrivate=0x0004, // PRIVATE + fNoName=0x0008, // NONAME + fOrdinal=0x0010, // Ordinal was explicitly assigned + fForwarder=0x0020, // This is a forwarder + } + + internal struct ExportSym { + // internal ushort reclen; // Record length [SYMTYPE] + // internal ushort rectyp; // S_EXPORT + + internal ushort ordinal; + internal ushort flags; // (EXPORTSYM_FLAGS) + internal string name; // name of + }; + + // + // Symbol for describing indirect calls when they are using + // a function pointer cast on some other type or temporary. + // Typical content will be an LF_POINTER to an LF_PROCEDURE + // type record that should mimic an actual variable with the + // function pointer type in question. + // + // Since the compiler can sometimes tail-merge a function call + // through a function pointer, there may be more than one + // S_CALLSITEINFO record at an address. This is similar to what + // you could do in your own code by: + // + // if (expr) + // pfn = &function1; + // else + // pfn = &function2; + // + // (*pfn)(arg list); + // + + internal struct CallsiteInfo { + // internal ushort reclen; // Record length [SYMTYPE] + // internal ushort rectyp; // S_CALLSITEINFO + internal int off; // offset of call site + internal ushort ect; // section index of call site + internal ushort pad0; // alignment padding field, must be zero + internal uint typind; // (type index) type index describing function signature + }; + + // Frame cookie information + + internal enum CV_cookietype { + CV_COOKIETYPE_COPY=0, + CV_COOKIETYPE_XOR_SP, + CV_COOKIETYPE_XOR_BP, + CV_COOKIETYPE_XOR_R13, + }; + + // Symbol for describing security cookie's position and type + // (raw, xor'd with esp, xor'd with ebp). + + internal struct FrameCookie { + // internal ushort reclen; // Record length [SYMTYPE] + // internal ushort rectyp; // S_FRAMECOOKIE + internal int off; // Frame relative offset + internal ushort reg; // Register index + internal int cookietype; // (CV_cookietype) Type of the cookie + internal byte flags; // Flags describing this cookie + }; + + internal enum CV_DISCARDED : uint { + CV_DISCARDED_UNKNOWN=0, + CV_DISCARDED_NOT_SELECTED=1, + CV_DISCARDED_NOT_REFERENCED=2, + }; + + internal struct DiscardedSym { + // internal ushort reclen; // Record length [SYMTYPE] + // internal ushort rectyp; // S_DISCARDED + internal CV_DISCARDED iscarded; + internal uint fileid; // First FILEID if line number info present + internal uint linenum; // First line number + internal byte[] data; // Original record(s) with invalid indices + }; + + // + // V7 line number data types + // + + internal enum DEBUG_S_SUBSECTION_TYPE : uint { + DEBUG_S_IGNORE=0x80000000, // if this bit is set in a subsection type then ignore the subsection contents + + DEBUG_S_SYMBOLS=0xf1, + DEBUG_S_LINES=0xf2, + DEBUG_S_STRINGTABLE=0xf3, + DEBUG_S_FILECHKSMS=0xf4, + DEBUG_S_FRAMEDATA=0xf5, + }; + + // + // Line flags (data present) + // + internal enum CV_LINE_SUBSECTION_FLAGS : ushort { + CV_LINES_HAVE_COLUMNS=0x0001, + } + + internal struct CV_LineSection { + internal uint off; + internal ushort sec; + internal ushort flags; + internal uint cod; + } + + internal struct CV_SourceFile { + internal uint index; // Index to file in checksum section. + internal uint count; // Number of CV_Line records. + internal uint linsiz; // Size of CV_Line recods. + } + + [Flags] + internal enum CV_Line_Flags : uint { + linenumStart=0x00ffffff, // line where statement/expression starts + deltaLineEnd=0x7f000000, // delta to line where statement ends (optional) + fStatement=0x80000000, // true if a statement linenumber, else an expression line num + }; + + internal struct CV_Line { + internal uint offset; // Offset to start of code bytes for line number + internal uint flags; // (CV_Line_Flags) + }; + + internal struct CV_Column { + internal ushort offColumnStart; + internal ushort offColumnEnd; + }; + + // File information + + internal enum CV_FILE_CHECKSUM_TYPE : byte { + None=0, + MD5=1, + }; + + internal struct CV_FileCheckSum { + internal uint name; // Index of name in name table. + internal byte len; // Hash length + internal byte type; // Hash type + } + + [Flags] + internal enum FRAMEDATA_FLAGS : uint { + fHasSEH=0x00000001, + fHasEH=0x00000002, + fIsFunctionStart=0x00000004, + }; + + internal struct FrameData { + internal uint ulRvaStart; + internal uint cbBlock; + internal uint cbLocals; + internal uint cbParams; + internal uint cbStkMax; + internal uint frameFunc; + internal ushort cbProlog; + internal ushort cbSavedRegs; + internal uint flags; // (FRAMEDATA_FLAGS) + }; + + internal struct XFixupData { + internal ushort wType; + internal ushort wExtra; + internal uint rva; + internal uint rvaTarget; + }; + + internal enum DEBUG_S_SUBSECTION { + SYMBOLS=0xF1, + LINES=0xF2, + STRINGTABLE=0xF3, + FILECHKSMS=0xF4, + FRAMEDATA=0xF5, + } +} \ No newline at end of file diff --git a/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/DataStream.cs b/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/DataStream.cs new file mode 100644 index 0000000000..48a1851651 --- /dev/null +++ b/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/DataStream.cs @@ -0,0 +1,111 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the Microsoft Public License. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//----------------------------------------------------------------------------- +using System; +using System.IO; + +namespace Microsoft.Cci.Pdb { + internal class DataStream { + internal DataStream() { + } + + internal DataStream(int contentSize, BitAccess bits, int count) { + this.contentSize = contentSize; + if (count > 0) { + this.pages = new int[count]; + bits.ReadInt32(this.pages); + } + } + + internal void Read(PdbReader reader, BitAccess bits) { + bits.MinCapacity(contentSize); + Read(reader, 0, bits.Buffer, 0, contentSize); + } + + internal void Read(PdbReader reader, int position, + byte[] bytes, int offset, int data) { + if (position + data > contentSize) { + throw new PdbException("DataStream can't read off end of stream. " + + "(pos={0},siz={1})", + position, data); + } + if (position == contentSize) { + return; + } + + int left = data; + int page = position / reader.pageSize; + int rema = position % reader.pageSize; + + // First get remained of first page. + if (rema != 0) { + int todo = reader.pageSize - rema; + if (todo > left) { + todo = left; + } + + reader.Seek(pages[page], rema); + reader.Read(bytes, offset, todo); + + offset += todo; + left -= todo; + page++; + } + + // Now get the remaining pages. + while (left > 0) { + int todo = reader.pageSize; + if (todo > left) { + todo = left; + } + + reader.Seek(pages[page], 0); + reader.Read(bytes, offset, todo); + + offset += todo; + left -= todo; + page++; + } + } + + //private void AddPages(int page0, int count) { + // if (pages == null) { + // pages = new int[count]; + // for (int i = 0; i < count; i++) { + // pages[i] = page0 + i; + // } + // } else { + // int[] old = pages; + // int used = old.Length; + + // pages = new int[used + count]; + // Array.Copy(old, pages, used); + // for (int i = 0; i < count; i++) { + // pages[used + i] = page0 + i; + // } + // } + //} + + //internal int Pages { + // get { return pages == null ? 0 : pages.Length; } + //} + + internal int Length { + get { return contentSize; } + } + + //internal int GetPage(int index) { + // return pages[index]; + //} + + internal int contentSize; + internal int[] pages; + } +} diff --git a/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/DbiDbgHdr.cs b/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/DbiDbgHdr.cs new file mode 100644 index 0000000000..588f3c13de --- /dev/null +++ b/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/DbiDbgHdr.cs @@ -0,0 +1,41 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the Microsoft Public License. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//----------------------------------------------------------------------------- +using System; + +namespace Microsoft.Cci.Pdb { + internal struct DbiDbgHdr { + internal DbiDbgHdr(BitAccess bits) { + bits.ReadUInt16(out snFPO); + bits.ReadUInt16(out snException); + bits.ReadUInt16(out snFixup); + bits.ReadUInt16(out snOmapToSrc); + bits.ReadUInt16(out snOmapFromSrc); + bits.ReadUInt16(out snSectionHdr); + bits.ReadUInt16(out snTokenRidMap); + bits.ReadUInt16(out snXdata); + bits.ReadUInt16(out snPdata); + bits.ReadUInt16(out snNewFPO); + bits.ReadUInt16(out snSectionHdrOrig); + } + + internal ushort snFPO; // 0..1 + internal ushort snException; // 2..3 (deprecated) + internal ushort snFixup; // 4..5 + internal ushort snOmapToSrc; // 6..7 + internal ushort snOmapFromSrc; // 8..9 + internal ushort snSectionHdr; // 10..11 + internal ushort snTokenRidMap; // 12..13 + internal ushort snXdata; // 14..15 + internal ushort snPdata; // 16..17 + internal ushort snNewFPO; // 18..19 + internal ushort snSectionHdrOrig; // 20..21 + } +} diff --git a/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/DbiHeader.cs b/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/DbiHeader.cs new file mode 100644 index 0000000000..0ca7915883 --- /dev/null +++ b/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/DbiHeader.cs @@ -0,0 +1,59 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the Microsoft Public License. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//----------------------------------------------------------------------------- +using System; + +namespace Microsoft.Cci.Pdb { + internal struct DbiHeader { + internal DbiHeader(BitAccess bits) { + bits.ReadInt32(out sig); + bits.ReadInt32(out ver); + bits.ReadInt32(out age); + bits.ReadInt16(out gssymStream); + bits.ReadUInt16(out vers); + bits.ReadInt16(out pssymStream); + bits.ReadUInt16(out pdbver); + bits.ReadInt16(out symrecStream); + bits.ReadUInt16(out pdbver2); + bits.ReadInt32(out gpmodiSize); + bits.ReadInt32(out secconSize); + bits.ReadInt32(out secmapSize); + bits.ReadInt32(out filinfSize); + bits.ReadInt32(out tsmapSize); + bits.ReadInt32(out mfcIndex); + bits.ReadInt32(out dbghdrSize); + bits.ReadInt32(out ecinfoSize); + bits.ReadUInt16(out flags); + bits.ReadUInt16(out machine); + bits.ReadInt32(out reserved); + } + + internal int sig; // 0..3 + internal int ver; // 4..7 + internal int age; // 8..11 + internal short gssymStream; // 12..13 + internal ushort vers; // 14..15 + internal short pssymStream; // 16..17 + internal ushort pdbver; // 18..19 + internal short symrecStream; // 20..21 + internal ushort pdbver2; // 22..23 + internal int gpmodiSize; // 24..27 + internal int secconSize; // 28..31 + internal int secmapSize; // 32..35 + internal int filinfSize; // 36..39 + internal int tsmapSize; // 40..43 + internal int mfcIndex; // 44..47 + internal int dbghdrSize; // 48..51 + internal int ecinfoSize; // 52..55 + internal ushort flags; // 56..57 + internal ushort machine; // 58..59 + internal int reserved; // 60..63 + } +} diff --git a/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/DbiModuleInfo.cs b/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/DbiModuleInfo.cs new file mode 100644 index 0000000000..8ab3717115 --- /dev/null +++ b/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/DbiModuleInfo.cs @@ -0,0 +1,57 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the Microsoft Public License. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//----------------------------------------------------------------------------- +using System; + +namespace Microsoft.Cci.Pdb { + internal class DbiModuleInfo { + internal DbiModuleInfo(BitAccess bits, bool readStrings) { + bits.ReadInt32(out opened); + new DbiSecCon(bits); + bits.ReadUInt16(out flags); + bits.ReadInt16(out stream); + bits.ReadInt32(out cbSyms); + bits.ReadInt32(out cbOldLines); + bits.ReadInt32(out cbLines); + bits.ReadInt16(out files); + bits.ReadInt16(out pad1); + bits.ReadUInt32(out offsets); + bits.ReadInt32(out niSource); + bits.ReadInt32(out niCompiler); + if (readStrings) { + bits.ReadCString(out moduleName); + bits.ReadCString(out objectName); + } else { + bits.SkipCString(out moduleName); + bits.SkipCString(out objectName); + } + bits.Align(4); + //if (opened != 0 || pad1 != 0) { + // throw new PdbException("Invalid DBI module. "+ + // "(opened={0}, pad={1})", opened, pad1); + //} + } + + internal int opened; // 0..3 + //internal DbiSecCon section; // 4..31 + internal ushort flags; // 32..33 + internal short stream; // 34..35 + internal int cbSyms; // 36..39 + internal int cbOldLines; // 40..43 + internal int cbLines; // 44..57 + internal short files; // 48..49 + internal short pad1; // 50..51 + internal uint offsets; + internal int niSource; + internal int niCompiler; + internal string moduleName; + internal string objectName; + } +} diff --git a/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/DbiSecCon.cs b/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/DbiSecCon.cs new file mode 100644 index 0000000000..de9fde951d --- /dev/null +++ b/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/DbiSecCon.cs @@ -0,0 +1,42 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the Microsoft Public License. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//----------------------------------------------------------------------------- +using System; + +namespace Microsoft.Cci.Pdb { + internal struct DbiSecCon { + internal DbiSecCon(BitAccess bits) { + bits.ReadInt16(out section); + bits.ReadInt16(out pad1); + bits.ReadInt32(out offset); + bits.ReadInt32(out size); + bits.ReadUInt32(out flags); + bits.ReadInt16(out module); + bits.ReadInt16(out pad2); + bits.ReadUInt32(out dataCrc); + bits.ReadUInt32(out relocCrc); + //if (pad1 != 0 || pad2 != 0) { + // throw new PdbException("Invalid DBI section. "+ + // "(pad1={0}, pad2={1})", + // pad1, pad2); + //} + } + + internal short section; // 0..1 + internal short pad1; // 2..3 + internal int offset; // 4..7 + internal int size; // 8..11 + internal uint flags; // 12..15 + internal short module; // 16..17 + internal short pad2; // 18..19 + internal uint dataCrc; // 20..23 + internal uint relocCrc; // 24..27 + } +} diff --git a/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/IntHashTable.cs b/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/IntHashTable.cs new file mode 100644 index 0000000000..db0e41be00 --- /dev/null +++ b/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/IntHashTable.cs @@ -0,0 +1,583 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the Microsoft Public License. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//----------------------------------------------------------------------------- +using System; +using System.Collections; + +namespace Microsoft.Cci.Pdb { + // The IntHashTable class represents a dictionary of associated keys and + // values with constant lookup time. + // + // Objects used as keys in a hashtable must implement the GetHashCode + // and Equals methods (or they can rely on the default implementations + // inherited from Object if key equality is simply reference + // equality). Furthermore, the GetHashCode and Equals methods of + // a key object must produce the same results given the same parameters + // for the entire time the key is present in the hashtable. In practical + // terms, this means that key objects should be immutable, at least for + // the time they are used as keys in a hashtable. + // + // When entries are added to a hashtable, they are placed into + // buckets based on the hashcode of their keys. Subsequent lookups of + // keys will use the hashcode of the keys to only search a particular + // bucket, thus substantially reducing the number of key comparisons + // required to find an entry. A hashtable's maximum load factor, which + // can be specified when the hashtable is instantiated, determines the + // maximum ratio of hashtable entries to hashtable buckets. Smaller load + // factors cause faster average lookup times at the cost of increased + // memory consumption. The default maximum load factor of 1.0 generally + // provides the best balance between speed and size. As entries are added + // to a hashtable, the hashtable's actual load factor increases, and when + // the actual load factor reaches the maximum load factor value, the + // number of buckets in the hashtable is automatically increased by + // approximately a factor of two (to be precise, the number of hashtable + // buckets is increased to the smallest prime number that is larger than + // twice the current number of hashtable buckets). + // + // Each object provides their own hash function, accessed by calling + // GetHashCode(). However, one can write their own object + // implementing IHashCodeProvider and pass it to a constructor on + // the IntHashTable. That hash function would be used for all objects in + // the table. + // + // This IntHashTable is implemented to support multiple concurrent readers + // and one concurrent writer without using any synchronization primitives. + // All read methods essentially must protect themselves from a resize + // occuring while they are running. This was done by enforcing an + // ordering on inserts & removes, as well as removing some member variables + // and special casing the expand code to work in a temporary array instead + // of the live bucket array. All inserts must set a bucket's value and + // key before setting the hash code & collision field. + // + // By Brian Grunkemeyer, algorithm by Patrick Dussud. + // Version 1.30 2/20/2000 + //| + internal class IntHashTable {//: IEnumerable { + /* + Implementation Notes: + + This IntHashTable uses double hashing. There are hashsize buckets in + the table, and each bucket can contain 0 or 1 element. We a bit to + mark whether there's been a collision when we inserted multiple + elements (ie, an inserted item was hashed at least a second time and + we probed this bucket, but it was already in use). Using the + collision bit, we can terminate lookups & removes for elements that + aren't in the hash table more quickly. We steal the most + significant bit from the hash code to store the collision bit. + + Our hash function is of the following form: + + h(key, n) = h1(key) + n*h2(key) + + where n is the number of times we've hit a collided bucket and + rehashed (on this particular lookup). Here are our hash functions: + + h1(key) = GetHash(key); // default implementation calls key.GetHashCode(); + h2(key) = 1 + (((h1(key) >> 5) + 1) % (hashsize - 1)); + + The h1 can return any number. h2 must return a number between 1 and + hashsize - 1 that is relatively prime to hashsize (not a problem if + hashsize is prime). (Knuth's Art of Computer Programming, Vol. 3, + p. 528-9) + + If this is true, then we are guaranteed to visit every bucket in + exactly hashsize probes, since the least common multiple of hashsize + and h2(key) will be hashsize * h2(key). (This is the first number + where adding h2 to h1 mod hashsize will be 0 and we will search the + same bucket twice). + + We previously used a different h2(key, n) that was not constant. + That is a horrifically bad idea, unless you can prove that series + will never produce any identical numbers that overlap when you mod + them by hashsize, for all subranges from i to i+hashsize, for all i. + It's not worth investigating, since there was no clear benefit from + using that hash function, and it was broken. + + For efficiency reasons, we've implemented this by storing h1 and h2 + in a temporary, and setting a variable called seed equal to h1. We + do a probe, and if we collided, we simply add h2 to seed each time + through the loop. + + A good test for h2() is to subclass IntHashTable, provide your own + implementation of GetHash() that returns a constant, then add many + items to the hash table. Make sure Count equals the number of items + you inserted. + + -- Brian Grunkemeyer, 10/28/1999 + */ + + // A typical resize algorithm would pick the smallest prime number in this array + // that is larger than twice the previous capacity. + // Suppose our Hashtable currently has capacity x and enough elements are added + // such that a resize needs to occur. Resizing first computes 2x then finds the + // first prime in the table greater than 2x, i.e. if primes are ordered + // p_1, p_2, …, p_i,…, it finds p_n such that p_n-1 < 2x < p_n. + // Doubling is important for preserving the asymptotic complexity of the + // hashtable operations such as add. Having a prime guarantees that double + // hashing does not lead to infinite loops. IE, your hash function will be + // h1(key) + i*h2(key), 0 <= i < size. h2 and the size must be relatively prime. + private static readonly int[] primes = { + 3, 7, 11, 17, 23, 29, 37, 47, 59, 71, 89, 107, 131, 163, 197, 239, 293, 353, 431, 521, 631, 761, 919, + 1103, 1327, 1597, 1931, 2333, 2801, 3371, 4049, 4861, 5839, 7013, 8419, 10103, 12143, 14591, + 17519, 21023, 25229, 30293, 36353, 43627, 52361, 62851, 75431, 90523, 108631, 130363, 156437, + 187751, 225307, 270371, 324449, 389357, 467237, 560689, 672827, 807403, 968897, 1162687, 1395263, + 1674319, 2009191, 2411033, 2893249, 3471899, 4166287, 4999559, 5999471, 7199369}; + + private static int GetPrime(int minSize) { + if (minSize < 0) { + throw new ArgumentException("Arg_HTCapacityOverflow"); + } + for (int i = 0; i < primes.Length; i++) { + int size = primes[i]; + if (size >= minSize) { + return size; + } + } + throw new ArgumentException("Arg_HTCapacityOverflow"); + } + + // Deleted entries have their key set to buckets + + // The hash table data. + // This cannot be serialised + private struct bucket { + internal int key; + internal int hash_coll; // Store hash code; sign bit means there was a collision. + internal Object val; + } + + private bucket[] buckets; + + // The total number of entries in the hash table. + private int count; + + // The total number of collision bits set in the hashtable + private int occupancy; + + private int loadsize; + private int loadFactorPerc; // 100 = 1.0 + + private int version; + + // Constructs a new hashtable. The hashtable is created with an initial + // capacity of zero and a load factor of 1.0. + //| + internal IntHashTable() + : this(0, 100) { + } + + //// Constructs a new hashtable with the given initial capacity and a load + //// factor of 1.0. The capacity argument serves as an indication of + //// the number of entries the hashtable will contain. When this number (or + //// an approximation) is known, specifying it in the constructor can + //// eliminate a number of resizing operations that would otherwise be + //// performed when elements are added to the hashtable. + //// + ////| + //internal IntHashTable(int capacity) + // : this(capacity, 100) { + //} + + // Constructs a new hashtable with the given initial capacity and load + // factor. The capacity argument serves as an indication of the + // number of entries the hashtable will contain. When this number (or an + // approximation) is known, specifying it in the constructor can eliminate + // a number of resizing operations that would otherwise be performed when + // elements are added to the hashtable. The loadFactorPerc argument + // indicates the maximum ratio of hashtable entries to hashtable buckets. + // Smaller load factors cause faster average lookup times at the cost of + // increased memory consumption. A load factor of 1.0 generally provides + // the best balance between speed and size. + // + //| + internal IntHashTable(int capacity, int loadFactorPerc) { + if (capacity < 0) + throw new ArgumentOutOfRangeException("capacity", "ArgumentOutOfRange_NeedNonNegNum"); + if (!(loadFactorPerc >= 10 && loadFactorPerc <= 100)) + throw new ArgumentOutOfRangeException("loadFactorPerc", String.Format("ArgumentOutOfRange_IntHashTableLoadFactor", 10, 100)); + + // Based on perf work, .72 is the optimal load factor for this table. + this.loadFactorPerc = (loadFactorPerc * 72) / 100; + + int hashsize = GetPrime((int)(capacity / this.loadFactorPerc)); + buckets = new bucket[hashsize]; + + loadsize = (int)(this.loadFactorPerc * hashsize) / 100; + if (loadsize >= hashsize) + loadsize = hashsize-1; + } + + // Computes the hash function: H(key, i) = h1(key) + i*h2(key, hashSize). + // The out parameter seed is h1(key), while the out parameter + // incr is h2(key, hashSize). Callers of this function should + // add incr each time through a loop. + private static uint InitHash(int key, int hashsize, out uint seed, out uint incr) { + // Hashcode must be positive. Also, we must not use the sign bit, since + // that is used for the collision bit. + uint hashcode = (uint)key & 0x7FFFFFFF; + seed = (uint)hashcode; + // Restriction: incr MUST be between 1 and hashsize - 1, inclusive for + // the modular arithmetic to work correctly. This guarantees you'll + // visit every bucket in the table exactly once within hashsize + // iterations. Violate this and it'll cause obscure bugs forever. + // If you change this calculation for h2(key), update putEntry too! + incr = (uint)(1 + (((seed >> 5) + 1) % ((uint)hashsize - 1))); + return hashcode; + } + + // Adds an entry with the given key and value to this hashtable. An + // ArgumentException is thrown if the key is null or if the key is already + // present in the hashtable. + // + //| + internal void Add(int key, Object value) { + Insert(key, value, true); + } + + //// Removes all entries from this hashtable. + ////| + //internal void Clear() { + // if (count == 0) + // return; + + // for (int i = 0; i < buckets.Length; i++) { + // buckets[i].hash_coll = 0; + // buckets[i].key = -1; + // buckets[i].val = null; + // } + + // count = 0; + // occupancy = 0; + //} + + // Checks if this hashtable contains an entry with the given key. This is + // an O(1) operation. + // + //| + //internal bool Contains(int key) { + // if (key < 0) { + // throw new ArgumentException("Argument_KeyLessThanZero"); + // } + + // uint seed; + // uint incr; + // // Take a snapshot of buckets, in case another thread resizes table + // bucket[] lbuckets = buckets; + // uint hashcode = InitHash(key, lbuckets.Length, out seed, out incr); + // int ntry = 0; + + // bucket b; + // do { + // int bucketNumber = (int)(seed % (uint)lbuckets.Length); + // b = lbuckets[bucketNumber]; + // if (b.val == null) { + // return false; + // } + // if (((b.hash_coll & 0x7FFFFFFF) == hashcode) && b.key == key) { + // return true; + // } + // seed += incr; + // } while (b.hash_coll < 0 && ++ntry < lbuckets.Length); + // return false; + //} + + // Returns the value associated with the given key. If an entry with the + // given key is not found, the returned value is null. + // + //| + internal Object this[int key] { + get { + if (key < 0) { + throw new ArgumentException("Argument_KeyLessThanZero"); + } + uint seed; + uint incr; + // Take a snapshot of buckets, in case another thread does a resize + bucket[] lbuckets = buckets; + uint hashcode = InitHash(key, lbuckets.Length, out seed, out incr); + int ntry = 0; + + bucket b; + do { + int bucketNumber = (int)(seed % (uint)lbuckets.Length); + b = lbuckets[bucketNumber]; + if (b.val == null) { + return null; + } + if (((b.hash_coll & 0x7FFFFFFF) == hashcode) && key == b.key) { + return b.val; + } + seed += incr; + } while (b.hash_coll < 0 && ++ntry < lbuckets.Length); + return null; + } + //set { + // Insert(key, value, false); + //} + } + + // Increases the bucket count of this hashtable. This method is called from + // the Insert method when the actual load factor of the hashtable reaches + // the upper limit specified when the hashtable was constructed. The number + // of buckets in the hashtable is increased to the smallest prime number + // that is larger than twice the current number of buckets, and the entries + // in the hashtable are redistributed into the new buckets using the cached + // hashcodes. + private void expand() { + rehash(GetPrime(1+buckets.Length*2)); + } + + // We occationally need to rehash the table to clean up the collision bits. + private void rehash() { + rehash(buckets.Length); + } + + private void rehash(int newsize) { + + // reset occupancy + occupancy=0; + + // Don't replace any internal state until we've finished adding to the + // new bucket[]. This serves two purposes: + // 1) Allow concurrent readers to see valid hashtable contents + // at all times + // 2) Protect against an OutOfMemoryException while allocating this + // new bucket[]. + bucket[] newBuckets = new bucket[newsize]; + + // rehash table into new buckets + int nb; + for (nb = 0; nb < buckets.Length; nb++) { + bucket oldb = buckets[nb]; + if (oldb.val != null) { + putEntry(newBuckets, oldb.key, oldb.val, oldb.hash_coll & 0x7FFFFFFF); + } + } + + // New bucket[] is good to go - replace buckets and other internal state. + version++; + buckets = newBuckets; + loadsize = (int)(loadFactorPerc * newsize) / 100; + + if (loadsize >= newsize) { + loadsize = newsize-1; + } + + return; + } + + // Returns an enumerator for this hashtable. + // If modifications made to the hashtable while an enumeration is + // in progress, the MoveNext and Current methods of the + // enumerator will throw an exception. + // + //| + //IEnumerator IEnumerable.GetEnumerator() { + // return new IntHashTableEnumerator(this); + //} + + // Internal method to compare two keys. + // + // Inserts an entry into this hashtable. This method is called from the Set + // and Add methods. If the add parameter is true and the given key already + // exists in the hashtable, an exception is thrown. + private void Insert(int key, Object nvalue, bool add) { + if (key < 0) { + throw new ArgumentException("Argument_KeyLessThanZero"); + } + if (nvalue == null) { + throw new ArgumentNullException("nvalue", "ArgumentNull_Value"); + } + if (count >= loadsize) { + expand(); + } else if (occupancy > loadsize && count > 100) { + rehash(); + } + + uint seed; + uint incr; + // Assume we only have one thread writing concurrently. Modify + // buckets to contain new data, as long as we insert in the right order. + uint hashcode = InitHash(key, buckets.Length, out seed, out incr); + int ntry = 0; + int emptySlotNumber = -1; // We use the empty slot number to cache the first empty slot. We chose to reuse slots + // create by remove that have the collision bit set over using up new slots. + + do { + int bucketNumber = (int)(seed % (uint)buckets.Length); + + // Set emptySlot number to current bucket if it is the first available bucket that we have seen + // that once contained an entry and also has had a collision. + // We need to search this entire collision chain because we have to ensure that there are no + // duplicate entries in the table. + + // Insert the key/value pair into this bucket if this bucket is empty and has never contained an entry + // OR + // This bucket once contained an entry but there has never been a collision + if (buckets[bucketNumber].val == null) { + // If we have found an available bucket that has never had a collision, but we've seen an available + // bucket in the past that has the collision bit set, use the previous bucket instead + if (emptySlotNumber != -1) { // Reuse slot + bucketNumber = emptySlotNumber; + } + + // We pretty much have to insert in this order. Don't set hash + // code until the value & key are set appropriately. + buckets[bucketNumber].val = nvalue; + buckets[bucketNumber].key = key; + buckets[bucketNumber].hash_coll |= (int)hashcode; + count++; + version++; + return; + } + + // The current bucket is in use + // OR + // it is available, but has had the collision bit set and we have already found an available bucket + if (((buckets[bucketNumber].hash_coll & 0x7FFFFFFF) == hashcode) && + key == buckets[bucketNumber].key) { + if (add) { + throw new ArgumentException("Argument_AddingDuplicate__" + buckets[bucketNumber].key); + } + buckets[bucketNumber].val = nvalue; + version++; + return; + } + + // The current bucket is full, and we have therefore collided. We need to set the collision bit + // UNLESS + // we have remembered an available slot previously. + if (emptySlotNumber == -1) {// We don't need to set the collision bit here since we already have an empty slot + if (buckets[bucketNumber].hash_coll >= 0) { + buckets[bucketNumber].hash_coll |= unchecked((int)0x80000000); + occupancy++; + } + } + seed += incr; + } while (++ntry < buckets.Length); + + // This code is here if and only if there were no buckets without a collision bit set in the entire table + if (emptySlotNumber != -1) { + // We pretty much have to insert in this order. Don't set hash + // code until the value & key are set appropriately. + buckets[emptySlotNumber].val = nvalue; + buckets[emptySlotNumber].key = key; + buckets[emptySlotNumber].hash_coll |= (int)hashcode; + count++; + version++; + return; + + } + + // If you see this assert, make sure load factor & count are reasonable. + // Then verify that our double hash function (h2, described at top of file) + // meets the requirements described above. You should never see this assert. + throw new InvalidOperationException("InvalidOperation_HashInsertFailed"); + } + + private void putEntry(bucket[] newBuckets, int key, Object nvalue, int hashcode) { + uint seed = (uint)hashcode; + uint incr = (uint)(1 + (((seed >> 5) + 1) % ((uint)newBuckets.Length - 1))); + + do { + int bucketNumber = (int)(seed % (uint)newBuckets.Length); + + if ((newBuckets[bucketNumber].val == null)) { + newBuckets[bucketNumber].val = nvalue; + newBuckets[bucketNumber].key = key; + newBuckets[bucketNumber].hash_coll |= hashcode; + return; + } + + if (newBuckets[bucketNumber].hash_coll >= 0) { + newBuckets[bucketNumber].hash_coll |= unchecked((int)0x80000000); + occupancy++; + } + seed += incr; + } while (true); + } + + // Returns the number of associations in this hashtable. + // + //| + //internal int Count { + // get { return count; } + //} + + // Implements an enumerator for a hashtable. The enumerator uses the + // internal version number of the hashtabke to ensure that no modifications + // are made to the hashtable while an enumeration is in progress. + //private class IntHashTableEnumerator : IEnumerator { + // private IntHashTable hashtable; + // private int bucket; + // private int version; + // private bool current; + // //private int currentKey; + // private Object currentValue; + + // internal IntHashTableEnumerator(IntHashTable hashtable) { + // this.hashtable = hashtable; + // bucket = hashtable.buckets.Length; + // version = hashtable.version; + // } + + // public bool MoveNext() { + // if (version != hashtable.version) + // throw new InvalidOperationException("InvalidOperation_EnumFailedVersion"); + // while (bucket > 0) { + // bucket--; + // Object val = hashtable.buckets[bucket].val; + // if (val != null) { + // //currentKey = hashtable.buckets[bucket].key; + // currentValue = val; + // current = true; + // return true; + // } + // } + // current = false; + // return false; + // } + + // //internal int Key { + // // get { + // // if (current == false) + // // throw new InvalidOperationException("InvalidOperation_EnumOpCantHappen"); + // // return currentKey; + // // } + // //} + + // public Object Current { + // get { + // if (current == false) + // throw new InvalidOperationException("InvalidOperation_EnumOpCantHappen"); + // return currentValue; + // } + // } + + // //public Object Value { + // // get { + // // if (version != hashtable.version) + // // throw new InvalidOperationException("InvalidOperation_EnumFailedVersion"); + // // if (current == false) + // // throw new InvalidOperationException("InvalidOperation_EnumOpCantHappen"); + // // return currentValue; + // // } + // //} + + // public void Reset() { + // if (version != hashtable.version) throw new InvalidOperationException("InvalidOperation_EnumFailedVersion"); + // current = false; + // bucket = hashtable.buckets.Length; + // //currentKey = -1; + // currentValue = null; + // } + //} + } +} diff --git a/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/Interfaces.cs b/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/Interfaces.cs new file mode 100644 index 0000000000..82561fbcc0 --- /dev/null +++ b/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/Interfaces.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections.Generic; + +namespace Microsoft.Cci { + + /// + /// A range of CLR IL operations that comprise a lexical scope, specified as an IL offset and a length. + /// + public interface ILocalScope { + /// + /// The offset of the first operation in the scope. + /// + uint Offset { get; } + + /// + /// The length of the scope. Offset+Length equals the offset of the first operation outside the scope, or equals the method body length. + /// + uint Length { get; } + } + + /// + /// A description of the lexical scope in which a namespace type has been nested. This scope is tied to a particular + /// method body, so that partial types can be accommodated. + /// + public interface INamespaceScope { + + /// + /// Zero or more used namespaces. These correspond to using clauses in C#. + /// + IEnumerable UsedNamespaces { get; } + + } + + + /// + /// A namespace that is used (imported) inside a namespace scope. + /// + public interface IUsedNamespace { + /// + /// An alias for a namespace. For example the "x" of "using x = y.z;" in C#. Empty if no alias is present. + /// + IName Alias { get; } + + /// + /// The name of a namepace that has been aliased. For example the "y.z" of "using x = y.z;" or "using y.z" in C#. + /// + IName NamespaceName { get; } + } + + /// + /// The name of an entity. Typically name instances come from a common pool. Within the pool no two distinct instances will have the same Value or UniqueKey. + /// + public interface IName { + /// + /// An integer that is unique within the pool from which the name instance has been allocated. Useful as a hashtable key. + /// + int UniqueKey { + get; + //^ ensures result > 0; + } + + /// + /// An integer that is unique within the pool from which the name instance has been allocated. Useful as a hashtable key. + /// All name instances in the pool that have the same string value when ignoring the case of the characters in the string + /// will have the same key value. + /// + int UniqueKeyIgnoringCase { + get; + //^ ensures result > 0; + } + + /// + /// The string value corresponding to this name. + /// + string Value { get; } + } +} \ No newline at end of file diff --git a/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/LICENSE b/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/LICENSE new file mode 100755 index 0000000000..7bfc997e59 --- /dev/null +++ b/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/LICENSE @@ -0,0 +1,22 @@ +Microsoft Public License (Ms-PL) + +This license governs use of the accompanying software. If you use the software, you +accept this license. If you do not accept the license, do not use the software. + +1. Definitions +The terms "reproduce," "reproduction," "derivative works," and "distribution" have the +same meaning here as under U.S. copyright law. +A "contribution" is the original software, or any additions or changes to the software. +A "contributor" is any person that distributes its contribution under this license. +"Licensed patents" are a contributor's patent claims that read directly on its contribution. + +2. Grant of Rights +(A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create. +(B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software. + +3. Conditions and Limitations +(A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks. +(B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically. +(C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software. +(D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license. +(E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement. diff --git a/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/MsfDirectory.cs b/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/MsfDirectory.cs new file mode 100644 index 0000000000..a6669b5bb5 --- /dev/null +++ b/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/MsfDirectory.cs @@ -0,0 +1,58 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the Microsoft Public License. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//----------------------------------------------------------------------------- +using System; + +namespace Microsoft.Cci.Pdb { + internal class MsfDirectory { + internal MsfDirectory(PdbReader reader, PdbFileHeader head, BitAccess bits) { + int pages = reader.PagesFromSize(head.directorySize); + + // 0..n in page of directory pages. + bits.MinCapacity(head.directorySize); + int directoryRootPages = head.directoryRoot.Length; + int pagesPerPage = head.pageSize / 4; + int pagesToGo = pages; + for (int i = 0; i < directoryRootPages; i++) { + int pagesInThisPage = pagesToGo <= pagesPerPage ? pagesToGo : pagesPerPage; + reader.Seek(head.directoryRoot[i], 0); + bits.Append(reader.reader, pagesInThisPage * 4); + pagesToGo -= pagesInThisPage; + } + bits.Position = 0; + + DataStream stream = new DataStream(head.directorySize, bits, pages); + bits.MinCapacity(head.directorySize); + stream.Read(reader, bits); + + // 0..3 in directory pages + int count; + bits.ReadInt32(out count); + + // 4..n + int[] sizes = new int[count]; + bits.ReadInt32(sizes); + + // n..m + streams = new DataStream[count]; + for (int i = 0; i < count; i++) { + if (sizes[i] <= 0) { + streams[i] = new DataStream(); + } else { + streams[i] = new DataStream(sizes[i], bits, + reader.PagesFromSize(sizes[i])); + } + } + } + + internal DataStream[] streams; + } + +} diff --git a/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/PdbConstant.cs b/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/PdbConstant.cs new file mode 100644 index 0000000000..434841b0cd --- /dev/null +++ b/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/PdbConstant.cs @@ -0,0 +1,89 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the Microsoft Public License. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//----------------------------------------------------------------------------- +using System; +using System.Runtime.InteropServices; + +namespace Microsoft.Cci.Pdb { + internal class PdbConstant { + internal string name; + internal uint token; + internal object value; + + internal PdbConstant(BitAccess bits) { + bits.ReadUInt32(out this.token); + byte tag1; + bits.ReadUInt8(out tag1); + byte tag2; + bits.ReadUInt8(out tag2); + if (tag2 == 0) { + this.value = tag1; + } else if (tag2 == 0x80) { + switch (tag1) { + case 0x00: //sbyte + sbyte sb; + bits.ReadInt8(out sb); + this.value = sb; + break; + case 0x01: //short + short s; + bits.ReadInt16(out s); + this.value = s; + break; + case 0x02: //ushort + ushort us; + bits.ReadUInt16(out us); + this.value = us; + break; + case 0x03: //int + int i; + bits.ReadInt32(out i); + this.value = i; + break; + case 0x04: //uint + uint ui; + bits.ReadUInt32(out ui); + this.value = ui; + break; + case 0x05: //float + this.value = bits.ReadFloat(); + break; + case 0x06: //double + this.value = bits.ReadDouble(); + break; + case 0x09: //long + long sl; + bits.ReadInt64(out sl); + this.value = sl; + break; + case 0x0a: //ulong + ulong ul; + bits.ReadUInt64(out ul); + this.value = ul; + break; + case 0x10: //string + string str; + bits.ReadBString(out str); + this.value = str; + break; + case 0x19: //decimal + this.value = bits.ReadDecimal(); + break; + default: + //TODO: error + break; + } + } else { + //TODO: error + } + bits.ReadCString(out name); + } + } +} diff --git a/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/PdbDebugException.cs b/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/PdbDebugException.cs new file mode 100644 index 0000000000..d7f8f0fdbf --- /dev/null +++ b/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/PdbDebugException.cs @@ -0,0 +1,20 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the Microsoft Public License. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//----------------------------------------------------------------------------- +using System; +using System.IO; + +namespace Microsoft.Cci.Pdb { + internal class PdbDebugException : IOException { + internal PdbDebugException(String format, params object[] args) + : base(String.Format(format, args)) { + } + } +} diff --git a/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/PdbException.cs b/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/PdbException.cs new file mode 100644 index 0000000000..38d1d56368 --- /dev/null +++ b/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/PdbException.cs @@ -0,0 +1,20 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the Microsoft Public License. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//----------------------------------------------------------------------------- +using System; +using System.IO; + +namespace Microsoft.Cci.Pdb { + internal class PdbException : IOException { + internal PdbException(String format, params object[] args) + : base(String.Format(format, args)) { + } + } +} diff --git a/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/PdbFile.cs b/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/PdbFile.cs new file mode 100644 index 0000000000..47191ef156 --- /dev/null +++ b/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/PdbFile.cs @@ -0,0 +1,537 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the Microsoft Public License. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//----------------------------------------------------------------------------- +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Diagnostics.SymbolStore; + +namespace Microsoft.Cci.Pdb { + internal class PdbFile { + private PdbFile() // This class can't be instantiated. + { + } + + static void LoadGuidStream(BitAccess bits, out Guid doctype, out Guid language, out Guid vendor) { + bits.ReadGuid(out language); + bits.ReadGuid(out vendor); + bits.ReadGuid(out doctype); + } + + static Dictionary LoadNameIndex(BitAccess bits, out int age, out Guid guid) { + Dictionary result = new Dictionary(); + int ver; + int sig; + bits.ReadInt32(out ver); // 0..3 Version + bits.ReadInt32(out sig); // 4..7 Signature + bits.ReadInt32(out age); // 8..11 Age + bits.ReadGuid(out guid); // 12..27 GUID + + //if (ver != 20000404) { + // throw new PdbDebugException("Unsupported PDB Stream version {0}", ver); + //} + + // Read string buffer. + int buf; + bits.ReadInt32(out buf); // 28..31 Bytes of Strings + + int beg = bits.Position; + int nxt = bits.Position + buf; + + bits.Position = nxt; + + // Read map index. + int cnt; // n+0..3 hash size. + int max; // n+4..7 maximum ni. + + bits.ReadInt32(out cnt); + bits.ReadInt32(out max); + + BitSet present = new BitSet(bits); + BitSet deleted = new BitSet(bits); + if (!deleted.IsEmpty) { + throw new PdbDebugException("Unsupported PDB deleted bitset is not empty."); + } + + int j = 0; + for (int i = 0; i < max; i++) { + if (present.IsSet(i)) { + int ns; + int ni; + bits.ReadInt32(out ns); + bits.ReadInt32(out ni); + + string name; + int saved = bits.Position; + bits.Position = beg + ns; + bits.ReadCString(out name); + bits.Position = saved; + + result.Add(name.ToUpperInvariant(), ni); + j++; + } + } + if (j != cnt) { + throw new PdbDebugException("Count mismatch. ({0} != {1})", j, cnt); + } + return result; + } + + static IntHashTable LoadNameStream(BitAccess bits) { + IntHashTable ht = new IntHashTable(); + + uint sig; + int ver; + bits.ReadUInt32(out sig); // 0..3 Signature + bits.ReadInt32(out ver); // 4..7 Version + + // Read (or skip) string buffer. + int buf; + bits.ReadInt32(out buf); // 8..11 Bytes of Strings + + if (sig != 0xeffeeffe || ver != 1) { + throw new PdbDebugException("Unsupported Name Stream version. "+ + "(sig={0:x8}, ver={1})", + sig, ver); + } + int beg = bits.Position; + int nxt = bits.Position + buf; + bits.Position = nxt; + + // Read hash table. + int siz; + bits.ReadInt32(out siz); // n+0..3 Number of hash buckets. + nxt = bits.Position; + + for (int i = 0; i < siz; i++) { + int ni; + string name; + + bits.ReadInt32(out ni); + + if (ni != 0) { + int saved = bits.Position; + bits.Position = beg + ni; + bits.ReadCString(out name); + bits.Position = saved; + + ht.Add(ni, name); + } + } + bits.Position = nxt; + + return ht; + } + + private static int FindFunction(PdbFunction[] funcs, ushort sec, uint off) { + var match = new PdbFunction { + segment = sec, + address = off, + }; + + return Array.BinarySearch(funcs, match, PdbFunction.byAddress); + } + + static void LoadManagedLines(PdbFunction[] funcs, + IntHashTable names, + BitAccess bits, + MsfDirectory dir, + Dictionary nameIndex, + PdbReader reader, + uint limit) { + Array.Sort(funcs, PdbFunction.byAddressAndToken); + + int begin = bits.Position; + IntHashTable checks = ReadSourceFileInfo(bits, limit, names, dir, nameIndex, reader); + + // Read the lines next. + bits.Position = begin; + while (bits.Position < limit) { + int sig; + int siz; + bits.ReadInt32(out sig); + bits.ReadInt32(out siz); + int endSym = bits.Position + siz; + + switch ((DEBUG_S_SUBSECTION)sig) { + case DEBUG_S_SUBSECTION.LINES: { + CV_LineSection sec; + + bits.ReadUInt32(out sec.off); + bits.ReadUInt16(out sec.sec); + bits.ReadUInt16(out sec.flags); + bits.ReadUInt32(out sec.cod); + int funcIndex = FindFunction(funcs, sec.sec, sec.off); + if (funcIndex < 0) break; + var func = funcs[funcIndex]; + if (func.lines == null) { + while (funcIndex > 0) { + var f = funcs[funcIndex-1]; + if (f.lines != null || f.segment != sec.sec || f.address != sec.off) break; + func = f; + funcIndex--; + } + } else { + while (funcIndex < funcs.Length-1 && func.lines != null) { + var f = funcs[funcIndex+1]; + if (f.segment != sec.sec || f.address != sec.off) break; + func = f; + funcIndex++; + } + } + if (func.lines != null) break; + + // Count the line blocks. + int begSym = bits.Position; + int blocks = 0; + while (bits.Position < endSym) { + CV_SourceFile file; + bits.ReadUInt32(out file.index); + bits.ReadUInt32(out file.count); + bits.ReadUInt32(out file.linsiz); // Size of payload. + int linsiz = (int)file.count * (8 + ((sec.flags & 1) != 0 ? 4 : 0)); + bits.Position += linsiz; + blocks++; + } + + func.lines = new PdbLines[blocks]; + int block = 0; + + bits.Position = begSym; + while (bits.Position < endSym) { + CV_SourceFile file; + bits.ReadUInt32(out file.index); + bits.ReadUInt32(out file.count); + bits.ReadUInt32(out file.linsiz); // Size of payload. + + PdbSource src = (PdbSource)checks[(int)file.index]; + PdbLines tmp = new PdbLines(src, file.count); + func.lines[block++] = tmp; + PdbLine[] lines = tmp.lines; + + int plin = bits.Position; + int pcol = bits.Position + 8 * (int)file.count; + + for (int i = 0; i < file.count; i++) { + CV_Line line; + CV_Column column = new CV_Column(); + + bits.Position = plin + 8 * i; + bits.ReadUInt32(out line.offset); + bits.ReadUInt32(out line.flags); + + uint lineBegin = line.flags & (uint)CV_Line_Flags.linenumStart; + uint delta = (line.flags & (uint)CV_Line_Flags.deltaLineEnd) >> 24; + //bool statement = ((line.flags & (uint)CV_Line_Flags.fStatement) == 0); + if ((sec.flags & 1) != 0) { + bits.Position = pcol + 4 * i; + bits.ReadUInt16(out column.offColumnStart); + bits.ReadUInt16(out column.offColumnEnd); + } + + lines[i] = new PdbLine(line.offset, + lineBegin, + column.offColumnStart, + lineBegin+delta, + column.offColumnEnd); + } + } + break; + } + } + bits.Position = endSym; + } + } + + static void LoadFuncsFromDbiModule(BitAccess bits, + DbiModuleInfo info, + IntHashTable names, + ArrayList funcList, + bool readStrings, + MsfDirectory dir, + Dictionary nameIndex, + PdbReader reader) { + PdbFunction[] funcs = null; + + bits.Position = 0; + int sig; + bits.ReadInt32(out sig); + if (sig != 4) { + throw new PdbDebugException("Invalid signature. (sig={0})", sig); + } + + bits.Position = 4; + // Console.WriteLine("{0}:", info.moduleName); + funcs = PdbFunction.LoadManagedFunctions(/*info.moduleName,*/ + bits, (uint)info.cbSyms, + readStrings); + if (funcs != null) { + bits.Position = info.cbSyms + info.cbOldLines; + LoadManagedLines(funcs, names, bits, dir, nameIndex, reader, + (uint)(info.cbSyms + info.cbOldLines + info.cbLines)); + + for (int i = 0; i < funcs.Length; i++) { + funcList.Add(funcs[i]); + } + } + } + + static void LoadDbiStream(BitAccess bits, + out DbiModuleInfo[] modules, + out DbiDbgHdr header, + bool readStrings) { + DbiHeader dh = new DbiHeader(bits); + header = new DbiDbgHdr(); + + //if (dh.sig != -1 || dh.ver != 19990903) { + // throw new PdbException("Unsupported DBI Stream version, sig={0}, ver={1}", + // dh.sig, dh.ver); + //} + + // Read gpmod section. + ArrayList modList = new ArrayList(); + int end = bits.Position + dh.gpmodiSize; + while (bits.Position < end) { + DbiModuleInfo mod = new DbiModuleInfo(bits, readStrings); + modList.Add(mod); + } + if (bits.Position != end) { + throw new PdbDebugException("Error reading DBI stream, pos={0} != {1}", + bits.Position, end); + } + + if (modList.Count > 0) { + modules = (DbiModuleInfo[])modList.ToArray(typeof(DbiModuleInfo)); + } else { + modules = null; + } + + // Skip the Section Contribution substream. + bits.Position += dh.secconSize; + + // Skip the Section Map substream. + bits.Position += dh.secmapSize; + + // Skip the File Info substream. + bits.Position += dh.filinfSize; + + // Skip the TSM substream. + bits.Position += dh.tsmapSize; + + // Skip the EC substream. + bits.Position += dh.ecinfoSize; + + // Read the optional header. + end = bits.Position + dh.dbghdrSize; + if (dh.dbghdrSize > 0) { + header = new DbiDbgHdr(bits); + } + bits.Position = end; + } + + internal static PdbFunction[] LoadFunctions(Stream read, out Dictionary tokenToSourceMapping, out string sourceServerData, out int age, out Guid guid) { + tokenToSourceMapping = new Dictionary(); + BitAccess bits = new BitAccess(512 * 1024); + PdbFileHeader head = new PdbFileHeader(read, bits); + PdbReader reader = new PdbReader(read, head.pageSize); + MsfDirectory dir = new MsfDirectory(reader, head, bits); + DbiModuleInfo[] modules = null; + DbiDbgHdr header; + + dir.streams[1].Read(reader, bits); + Dictionary nameIndex = LoadNameIndex(bits, out age, out guid); + int nameStream; + if (!nameIndex.TryGetValue("/NAMES", out nameStream)) { + throw new PdbException("No `name' stream"); + } + dir.streams[nameStream].Read(reader, bits); + IntHashTable names = LoadNameStream(bits); + + int srcsrvStream; + if (!nameIndex.TryGetValue("SRCSRV", out srcsrvStream)) + sourceServerData = string.Empty; + else { + DataStream dataStream = dir.streams[srcsrvStream]; + byte[] bytes = new byte[dataStream.contentSize]; + dataStream.Read(reader, bits); + sourceServerData = bits.ReadBString(bytes.Length); + } + + dir.streams[3].Read(reader, bits); + LoadDbiStream(bits, out modules, out header, true); + + ArrayList funcList = new ArrayList(); + + if (modules != null) { + for (int m = 0; m < modules.Length; m++) { + var module = modules[m]; + if (module.stream > 0) { + dir.streams[module.stream].Read(reader, bits); + if (module.moduleName == "TokenSourceLineInfo") { + LoadTokenToSourceInfo(bits, module, names, dir, nameIndex, reader, tokenToSourceMapping); + continue; + } + LoadFuncsFromDbiModule(bits, module, names, funcList, true, dir, nameIndex, reader); + } + } + } + + PdbFunction[] funcs = (PdbFunction[])funcList.ToArray(typeof(PdbFunction)); + + // After reading the functions, apply the token remapping table if it exists. + if (header.snTokenRidMap != 0 && header.snTokenRidMap != 0xffff) { + dir.streams[header.snTokenRidMap].Read(reader, bits); + uint[] ridMap = new uint[dir.streams[header.snTokenRidMap].Length / 4]; + bits.ReadUInt32(ridMap); + + foreach (PdbFunction func in funcs) { + func.token = 0x06000000 | ridMap[func.token & 0xffffff]; + } + } + + // + Array.Sort(funcs, PdbFunction.byAddressAndToken); + //Array.Sort(funcs, PdbFunction.byToken); + return funcs; + } + + private static void LoadTokenToSourceInfo(BitAccess bits, DbiModuleInfo module, IntHashTable names, MsfDirectory dir, + Dictionary nameIndex, PdbReader reader, Dictionary tokenToSourceMapping) { + bits.Position = 0; + int sig; + bits.ReadInt32(out sig); + if (sig != 4) { + throw new PdbDebugException("Invalid signature. (sig={0})", sig); + } + + bits.Position = 4; + + while (bits.Position < module.cbSyms) { + ushort siz; + ushort rec; + + bits.ReadUInt16(out siz); + int star = bits.Position; + int stop = bits.Position + siz; + bits.Position = star; + bits.ReadUInt16(out rec); + + switch ((SYM)rec) { + case SYM.S_OEM: + OemSymbol oem; + + bits.ReadGuid(out oem.idOem); + bits.ReadUInt32(out oem.typind); + // internal byte[] rgl; // user data, force 4-byte alignment + + if (oem.idOem == PdbFunction.msilMetaData) { + string name = bits.ReadString(); + if (name == "TSLI") { + uint token; + uint file_id; + uint line; + uint column; + uint endLine; + uint endColumn; + bits.ReadUInt32(out token); + bits.ReadUInt32(out file_id); + bits.ReadUInt32(out line); + bits.ReadUInt32(out column); + bits.ReadUInt32(out endLine); + bits.ReadUInt32(out endColumn); + PdbTokenLine tokenLine; + if (!tokenToSourceMapping.TryGetValue(token, out tokenLine)) + tokenToSourceMapping.Add(token, new PdbTokenLine(token, file_id, line, column, endLine, endColumn)); + else { + while (tokenLine.nextLine != null) tokenLine = tokenLine.nextLine; + tokenLine.nextLine = new PdbTokenLine(token, file_id, line, column, endLine, endColumn); + } + } + bits.Position = stop; + break; + } else { + throw new PdbDebugException("OEM section: guid={0} ti={1}", + oem.idOem, oem.typind); + // bits.Position = stop; + } + + case SYM.S_END: + bits.Position = stop; + break; + + default: + //Console.WriteLine("{0,6}: {1:x2} {2}", + // bits.Position, rec, (SYM)rec); + bits.Position = stop; + break; + } + } + + bits.Position = module.cbSyms + module.cbOldLines; + int limit = module.cbSyms + module.cbOldLines + module.cbLines; + IntHashTable sourceFiles = ReadSourceFileInfo(bits, (uint)limit, names, dir, nameIndex, reader); + foreach (var tokenLine in tokenToSourceMapping.Values) { + tokenLine.sourceFile = (PdbSource)sourceFiles[(int)tokenLine.file_id]; + } + + } + + private static IntHashTable ReadSourceFileInfo(BitAccess bits, uint limit, IntHashTable names, MsfDirectory dir, + Dictionary nameIndex, PdbReader reader) { + IntHashTable checks = new IntHashTable(); + + int begin = bits.Position; + while (bits.Position < limit) { + int sig; + int siz; + bits.ReadInt32(out sig); + bits.ReadInt32(out siz); + int place = bits.Position; + int endSym = bits.Position + siz; + + switch ((DEBUG_S_SUBSECTION)sig) { + case DEBUG_S_SUBSECTION.FILECHKSMS: + while (bits.Position < endSym) { + CV_FileCheckSum chk; + + int ni = bits.Position - place; + bits.ReadUInt32(out chk.name); + bits.ReadUInt8(out chk.len); + bits.ReadUInt8(out chk.type); + + string name = (string)names[(int)chk.name]; + int guidStream; + Guid doctypeGuid = SymDocumentType.Text; + Guid languageGuid = Guid.Empty; + Guid vendorGuid = Guid.Empty; + if (nameIndex.TryGetValue("/SRC/FILES/"+name.ToUpperInvariant(), out guidStream)) { + var guidBits = new BitAccess(0x100); + dir.streams[guidStream].Read(reader, guidBits); + LoadGuidStream(guidBits, out doctypeGuid, out languageGuid, out vendorGuid); + } + + PdbSource src = new PdbSource(/*(uint)ni,*/ name, doctypeGuid, languageGuid, vendorGuid); + checks.Add(ni, src); + bits.Position += chk.len; + bits.Align(4); + } + bits.Position = endSym; + break; + + default: + bits.Position = endSym; + break; + } + } + return checks; + } + } +} diff --git a/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/PdbFileHeader.cs b/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/PdbFileHeader.cs new file mode 100644 index 0000000000..e1f56dbe42 --- /dev/null +++ b/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/PdbFileHeader.cs @@ -0,0 +1,90 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the Microsoft Public License. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//----------------------------------------------------------------------------- +using System; +using System.IO; +using System.Text; + +namespace Microsoft.Cci.Pdb { + internal class PdbFileHeader { + //internal PdbFileHeader(int pageSize) { + // this.magic = new byte[32] { + // 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, // "Microsof" + // 0x74, 0x20, 0x43, 0x2F, 0x43, 0x2B, 0x2B, 0x20, // "t C/C++ " + // 0x4D, 0x53, 0x46, 0x20, 0x37, 0x2E, 0x30, 0x30, // "MSF 7.00" + // 0x0D, 0x0A, 0x1A, 0x44, 0x53, 0x00, 0x00, 0x00 // "^^^DS^^^" + // }; + // this.pageSize = pageSize; + //} + + internal PdbFileHeader(Stream reader, BitAccess bits) { + bits.MinCapacity(56); + reader.Seek(0, SeekOrigin.Begin); + bits.FillBuffer(reader, 52); + + this.magic = new byte[32]; + bits.ReadBytes(this.magic); // 0..31 + bits.ReadInt32(out this.pageSize); // 32..35 + bits.ReadInt32(out this.freePageMap); // 36..39 + bits.ReadInt32(out this.pagesUsed); // 40..43 + bits.ReadInt32(out this.directorySize); // 44..47 + bits.ReadInt32(out this.zero); // 48..51 + + int directoryPages = ((((directorySize + pageSize - 1) / pageSize) * 4) + pageSize - 1) / pageSize; + this.directoryRoot = new int[directoryPages]; + bits.FillBuffer(reader, directoryPages * 4); + bits.ReadInt32(this.directoryRoot); + } + + //internal string Magic { + // get { return StringFromBytesUTF8(magic); } + //} + + //internal void Write(Stream writer, BitAccess bits) { + // bits.MinCapacity(pageSize); + // bits.WriteBytes(magic); // 0..31 + // bits.WriteInt32(pageSize); // 32..35 + // bits.WriteInt32(freePageMap); // 36..39 + // bits.WriteInt32(pagesUsed); // 40..43 + // bits.WriteInt32(directorySize); // 44..47 + // bits.WriteInt32(zero); // 48..51 + // bits.WriteInt32(directoryRoot); // 52..55 + + // writer.Seek(0, SeekOrigin.Begin); + // bits.WriteBuffer(writer, pageSize); + //} + + //////////////////////////////////////////////////// Helper Functions. + // + //internal static string StringFromBytesUTF8(byte[] bytes) { + // return StringFromBytesUTF8(bytes, 0, bytes.Length); + //} + + //internal static string StringFromBytesUTF8(byte[] bytes, int offset, int length) { + // for (int i = 0; i < length; i++) { + // if (bytes[offset + i] < ' ') { + // length = i; + // } + // } + // return Encoding.UTF8.GetString(bytes, offset, length); + //} + + ////////////////////////////////////////////////////////////// Fields. + // + internal readonly byte[] magic; + internal readonly int pageSize; + internal int freePageMap; + internal int pagesUsed; + internal int directorySize; + internal readonly int zero; + internal int[] directoryRoot; + } + +} diff --git a/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/PdbFunction.cs b/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/PdbFunction.cs new file mode 100644 index 0000000000..72622314e8 --- /dev/null +++ b/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/PdbFunction.cs @@ -0,0 +1,498 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the Microsoft Public License. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//----------------------------------------------------------------------------- +using System; +using System.Collections; +using System.Collections.Generic; + +namespace Microsoft.Cci.Pdb { + internal class PdbFunction { + static internal readonly Guid msilMetaData = new Guid(0xc6ea3fc9, 0x59b3, 0x49d6, 0xbc, 0x25, + 0x09, 0x02, 0xbb, 0xab, 0xb4, 0x60); + static internal readonly IComparer byAddress = new PdbFunctionsByAddress(); + static internal readonly IComparer byAddressAndToken = new PdbFunctionsByAddressAndToken(); + //static internal readonly IComparer byToken = new PdbFunctionsByToken(); + + internal uint token; + internal uint slotToken; + internal uint tokenOfMethodWhoseUsingInfoAppliesToThisMethod; + //internal string name; + //internal string module; + //internal ushort flags; + + internal uint segment; + internal uint address; + //internal uint length; + + //internal byte[] metadata; + internal PdbScope[] scopes; + internal PdbSlot[] slots; + internal PdbConstant[] constants; + internal string[] usedNamespaces; + internal PdbLines[] lines; + internal ushort[]/*?*/ usingCounts; + internal IEnumerable/*?*/ namespaceScopes; + internal string/*?*/ iteratorClass; + internal List/*?*/ iteratorScopes; + internal PdbSynchronizationInformation/*?*/ synchronizationInformation; + + private static string StripNamespace(string module) { + int li = module.LastIndexOf('.'); + if (li > 0) { + return module.Substring(li + 1); + } + return module; + } + + + internal static PdbFunction[] LoadManagedFunctions(/*string module,*/ + BitAccess bits, uint limit, + bool readStrings) { + //string mod = StripNamespace(module); + int begin = bits.Position; + int count = 0; + + while (bits.Position < limit) { + ushort siz; + ushort rec; + + bits.ReadUInt16(out siz); + int star = bits.Position; + int stop = bits.Position + siz; + bits.Position = star; + bits.ReadUInt16(out rec); + + switch ((SYM)rec) { + case SYM.S_GMANPROC: + case SYM.S_LMANPROC: + ManProcSym proc; + bits.ReadUInt32(out proc.parent); + bits.ReadUInt32(out proc.end); + bits.Position = (int)proc.end; + count++; + break; + + case SYM.S_END: + bits.Position = stop; + break; + + default: + //Console.WriteLine("{0,6}: {1:x2} {2}", + // bits.Position, rec, (SYM)rec); + bits.Position = stop; + break; + } + } + if (count == 0) { + return null; + } + + bits.Position = begin; + PdbFunction[] funcs = new PdbFunction[count]; + int func = 0; + + while (bits.Position < limit) { + ushort siz; + ushort rec; + + bits.ReadUInt16(out siz); + int star = bits.Position; + int stop = bits.Position + siz; + bits.ReadUInt16(out rec); + + switch ((SYM)rec) { + + case SYM.S_GMANPROC: + case SYM.S_LMANPROC: + ManProcSym proc; + //int offset = bits.Position; + + bits.ReadUInt32(out proc.parent); + bits.ReadUInt32(out proc.end); + bits.ReadUInt32(out proc.next); + bits.ReadUInt32(out proc.len); + bits.ReadUInt32(out proc.dbgStart); + bits.ReadUInt32(out proc.dbgEnd); + bits.ReadUInt32(out proc.token); + bits.ReadUInt32(out proc.off); + bits.ReadUInt16(out proc.seg); + bits.ReadUInt8(out proc.flags); + bits.ReadUInt16(out proc.retReg); + if (readStrings) { + bits.ReadCString(out proc.name); + } else { + bits.SkipCString(out proc.name); + } + //Console.WriteLine("token={0:X8} [{1}::{2}]", proc.token, module, proc.name); + + bits.Position = stop; + funcs[func++] = new PdbFunction(/*module,*/ proc, bits); + break; + + default: { + //throw new PdbDebugException("Unknown SYMREC {0}", (SYM)rec); + bits.Position = stop; + break; + } + } + } + return funcs; + } + + internal static void CountScopesAndSlots(BitAccess bits, uint limit, + out int constants, out int scopes, out int slots, out int usedNamespaces) { + int pos = bits.Position; + BlockSym32 block; + constants = 0; + slots = 0; + scopes = 0; + usedNamespaces = 0; + + while (bits.Position < limit) { + ushort siz; + ushort rec; + + bits.ReadUInt16(out siz); + int star = bits.Position; + int stop = bits.Position + siz; + bits.Position = star; + bits.ReadUInt16(out rec); + + switch ((SYM)rec) { + case SYM.S_BLOCK32: { + bits.ReadUInt32(out block.parent); + bits.ReadUInt32(out block.end); + + scopes++; + bits.Position = (int)block.end; + break; + } + + case SYM.S_MANSLOT: + slots++; + bits.Position = stop; + break; + + case SYM.S_UNAMESPACE: + usedNamespaces++; + bits.Position = stop; + break; + + case SYM.S_MANCONSTANT: + constants++; + bits.Position = stop; + break; + + default: + bits.Position = stop; + break; + } + } + bits.Position = pos; + } + + internal PdbFunction() { + } + + internal PdbFunction(/*string module, */ManProcSym proc, BitAccess bits) { + this.token = proc.token; + //this.module = module; + //this.name = proc.name; + //this.flags = proc.flags; + this.segment = proc.seg; + this.address = proc.off; + //this.length = proc.len; + + if (proc.seg != 1) { + throw new PdbDebugException("Segment is {0}, not 1.", proc.seg); + } + if (proc.parent != 0 || proc.next != 0) { + throw new PdbDebugException("Warning parent={0}, next={1}", + proc.parent, proc.next); + } + //if (proc.dbgStart != 0 || proc.dbgEnd != 0) { + // throw new PdbDebugException("Warning DBG start={0}, end={1}", + // proc.dbgStart, proc.dbgEnd); + //} + + int constantCount; + int scopeCount; + int slotCount; + int usedNamespacesCount; + CountScopesAndSlots(bits, proc.end, out constantCount, out scopeCount, out slotCount, out usedNamespacesCount); + int scope = constantCount > 0 || slotCount > 0 || usedNamespacesCount > 0 ? 1 : 0; + int slot = 0; + int constant = 0; + int usedNs = 0; + scopes = new PdbScope[scopeCount+scope]; + slots = new PdbSlot[slotCount]; + constants = new PdbConstant[constantCount]; + usedNamespaces = new string[usedNamespacesCount]; + + if (scope > 0) + scopes[0] = new PdbScope(this.address, proc.len, slots, constants, usedNamespaces); + + while (bits.Position < proc.end) { + ushort siz; + ushort rec; + + bits.ReadUInt16(out siz); + int star = bits.Position; + int stop = bits.Position + siz; + bits.Position = star; + bits.ReadUInt16(out rec); + + switch ((SYM)rec) { + case SYM.S_OEM: { // 0x0404 + OemSymbol oem; + + bits.ReadGuid(out oem.idOem); + bits.ReadUInt32(out oem.typind); + // internal byte[] rgl; // user data, force 4-byte alignment + + if (oem.idOem == msilMetaData) { + string name = bits.ReadString(); + if (name == "MD2") { + byte version; + bits.ReadUInt8(out version); + if (version == 4) { + byte count; + bits.ReadUInt8(out count); + bits.Align(4); + while (count-- > 0) + this.ReadCustomMetadata(bits); + } + } else if (name == "asyncMethodInfo") { + this.synchronizationInformation = new PdbSynchronizationInformation(bits); + } + bits.Position = stop; + break; + } else { + throw new PdbDebugException("OEM section: guid={0} ti={1}", + oem.idOem, oem.typind); + // bits.Position = stop; + } + } + + case SYM.S_BLOCK32: { + BlockSym32 block = new BlockSym32(); + + bits.ReadUInt32(out block.parent); + bits.ReadUInt32(out block.end); + bits.ReadUInt32(out block.len); + bits.ReadUInt32(out block.off); + bits.ReadUInt16(out block.seg); + bits.SkipCString(out block.name); + bits.Position = stop; + + scopes[scope++] = new PdbScope(this.address, block, bits, out slotToken); + bits.Position = (int)block.end; + break; + } + + case SYM.S_MANSLOT: + slots[slot++] = new PdbSlot(bits); + bits.Position = stop; + break; + + case SYM.S_MANCONSTANT: + constants[constant++] = new PdbConstant(bits); + bits.Position = stop; + break; + + case SYM.S_UNAMESPACE: + bits.ReadCString(out usedNamespaces[usedNs++]); + bits.Position = stop; + break; + + case SYM.S_END: + bits.Position = stop; + break; + + default: { + //throw new PdbDebugException("Unknown SYM: {0}", (SYM)rec); + bits.Position = stop; + break; + } + } + } + + if (bits.Position != proc.end) { + throw new PdbDebugException("Not at S_END"); + } + + ushort esiz; + ushort erec; + bits.ReadUInt16(out esiz); + bits.ReadUInt16(out erec); + + if (erec != (ushort)SYM.S_END) { + throw new PdbDebugException("Missing S_END"); + } + } + + private void ReadCustomMetadata(BitAccess bits) { + int savedPosition = bits.Position; + byte version; + bits.ReadUInt8(out version); + if (version != 4) { + throw new PdbDebugException("Unknown custom metadata item version: {0}", version); + } + byte kind; + bits.ReadUInt8(out kind); + bits.Align(4); + uint numberOfBytesInItem; + bits.ReadUInt32(out numberOfBytesInItem); + switch (kind) { + case 0: this.ReadUsingInfo(bits); break; + case 1: this.ReadForwardInfo(bits); break; + case 2: break; // this.ReadForwardedToModuleInfo(bits); break; + case 3: this.ReadIteratorLocals(bits); break; + case 4: this.ReadForwardIterator(bits); break; + default: throw new PdbDebugException("Unknown custom metadata item kind: {0}", kind); + } + bits.Position = savedPosition+(int)numberOfBytesInItem; + } + + private void ReadForwardIterator(BitAccess bits) { + this.iteratorClass = bits.ReadString(); + } + + private void ReadIteratorLocals(BitAccess bits) { + uint numberOfLocals; + bits.ReadUInt32(out numberOfLocals); + this.iteratorScopes = new List((int)numberOfLocals); + while (numberOfLocals-- > 0) { + uint ilStartOffset; + uint ilEndOffset; + bits.ReadUInt32(out ilStartOffset); + bits.ReadUInt32(out ilEndOffset); + this.iteratorScopes.Add(new PdbIteratorScope(ilStartOffset, ilEndOffset-ilStartOffset)); + } + } + + //private void ReadForwardedToModuleInfo(BitAccess bits) { + //} + + private void ReadForwardInfo(BitAccess bits) { + bits.ReadUInt32(out this.tokenOfMethodWhoseUsingInfoAppliesToThisMethod); + } + + private void ReadUsingInfo(BitAccess bits) { + ushort numberOfNamespaces; + bits.ReadUInt16(out numberOfNamespaces); + this.usingCounts = new ushort[numberOfNamespaces]; + for (ushort i = 0; i < numberOfNamespaces; i++) { + bits.ReadUInt16(out this.usingCounts[i]); + } + } + + internal class PdbFunctionsByAddress : IComparer { + public int Compare(Object x, Object y) { + PdbFunction fx = (PdbFunction)x; + PdbFunction fy = (PdbFunction)y; + + if (fx.segment < fy.segment) { + return -1; + } else if (fx.segment > fy.segment) { + return 1; + } else if (fx.address < fy.address) { + return -1; + } else if (fx.address > fy.address) { + return 1; + } else { + return 0; + } + } + } + + internal class PdbFunctionsByAddressAndToken : IComparer { + public int Compare(Object x, Object y) { + PdbFunction fx = (PdbFunction)x; + PdbFunction fy = (PdbFunction)y; + + if (fx.segment < fy.segment) { + return -1; + } else if (fx.segment > fy.segment) { + return 1; + } else if (fx.address < fy.address) { + return -1; + } else if (fx.address > fy.address) { + return 1; + } else { + if (fx.token < fy.token) + return -1; + else if (fx.token > fy.token) + return 1; + else + return 0; + } + } + } + + //internal class PdbFunctionsByToken : IComparer { + // public int Compare(Object x, Object y) { + // PdbFunction fx = (PdbFunction)x; + // PdbFunction fy = (PdbFunction)y; + + // if (fx.token < fy.token) { + // return -1; + // } else if (fx.token > fy.token) { + // return 1; + // } else { + // return 0; + // } + // } + + //} + } + + internal class PdbSynchronizationInformation { + internal uint kickoffMethodToken; + internal uint generatedCatchHandlerIlOffset; + internal PdbSynchronizationPoint[] synchronizationPoints; + + internal PdbSynchronizationInformation(BitAccess bits) { + uint asyncStepInfoCount; + bits.ReadUInt32(out this.kickoffMethodToken); + bits.ReadUInt32(out this.generatedCatchHandlerIlOffset); + bits.ReadUInt32(out asyncStepInfoCount); + this.synchronizationPoints = new PdbSynchronizationPoint[asyncStepInfoCount]; + for (uint i = 0; i < asyncStepInfoCount; i += 1) { + this.synchronizationPoints[i] = new PdbSynchronizationPoint(bits); + } + } + + public uint GeneratedCatchHandlerOffset { + get { return this.generatedCatchHandlerIlOffset; } + } + } + + internal class PdbSynchronizationPoint { + internal uint synchronizeOffset; + internal uint continuationMethodToken; + internal uint continuationOffset; + + internal PdbSynchronizationPoint(BitAccess bits) { + bits.ReadUInt32(out this.synchronizeOffset); + bits.ReadUInt32(out this.continuationMethodToken); + bits.ReadUInt32(out this.continuationOffset); + } + + public uint SynchronizeOffset { + get { return this.synchronizeOffset; } + } + + public uint ContinuationOffset { + get { return this.continuationOffset; } + } + } + +} diff --git a/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/PdbLine.cs b/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/PdbLine.cs new file mode 100644 index 0000000000..f6fe3a9d3e --- /dev/null +++ b/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/PdbLine.cs @@ -0,0 +1,29 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the Microsoft Public License. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//----------------------------------------------------------------------------- +using System; + +namespace Microsoft.Cci.Pdb { + internal struct PdbLine { + internal uint offset; + internal uint lineBegin; + internal uint lineEnd; + internal ushort colBegin; + internal ushort colEnd; + + internal PdbLine(uint offset, uint lineBegin, ushort colBegin, uint lineEnd, ushort colEnd) { + this.offset = offset; + this.lineBegin = lineBegin; + this.colBegin = colBegin; + this.lineEnd = lineEnd; + this.colEnd = colEnd; + } + } +} diff --git a/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/PdbLines.cs b/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/PdbLines.cs new file mode 100644 index 0000000000..382638b70f --- /dev/null +++ b/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/PdbLines.cs @@ -0,0 +1,23 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the Microsoft Public License. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//----------------------------------------------------------------------------- +using System; + +namespace Microsoft.Cci.Pdb { + internal class PdbLines { + internal PdbSource file; + internal PdbLine[] lines; + + internal PdbLines(PdbSource file, uint count) { + this.file = file; + this.lines = new PdbLine[count]; + } + } +} diff --git a/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/PdbReader.cs b/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/PdbReader.cs new file mode 100644 index 0000000000..edfd9263c9 --- /dev/null +++ b/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/PdbReader.cs @@ -0,0 +1,40 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the Microsoft Public License. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//----------------------------------------------------------------------------- +using System; +using System.IO; + +namespace Microsoft.Cci.Pdb { + internal class PdbReader { + internal PdbReader(Stream reader, int pageSize) { + this.pageSize = pageSize; + this.reader = reader; + } + + internal void Seek(int page, int offset) { + reader.Seek(page * pageSize + offset, SeekOrigin.Begin); + } + + internal void Read(byte[] bytes, int offset, int count) { + reader.Read(bytes, offset, count); + } + + internal int PagesFromSize(int size) { + return (size + pageSize - 1) / (pageSize); + } + + //internal int PageSize { + // get { return pageSize; } + //} + + internal readonly int pageSize; + internal readonly Stream reader; + } +} diff --git a/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/PdbScope.cs b/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/PdbScope.cs new file mode 100644 index 0000000000..92ac385e99 --- /dev/null +++ b/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/PdbScope.cs @@ -0,0 +1,122 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the Microsoft Public License. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//----------------------------------------------------------------------------- +using System; + +namespace Microsoft.Cci.Pdb { + internal class PdbScope { + internal PdbConstant[] constants; + internal PdbSlot[] slots; + internal PdbScope[] scopes; + internal string[] usedNamespaces; + + //internal uint segment; + internal uint address; + internal uint offset; + internal uint length; + + internal PdbScope(uint address, uint length, PdbSlot[] slots, PdbConstant[] constants, string[] usedNamespaces) { + this.constants = constants; + this.slots = slots; + this.scopes = new PdbScope[0]; + this.usedNamespaces = usedNamespaces; + this.address = address; + this.offset = 0; + this.length = length; + } + + internal PdbScope(uint funcOffset, BlockSym32 block, BitAccess bits, out uint typind) { + //this.segment = block.seg; + this.address = block.off; + this.offset = block.off - funcOffset; + this.length = block.len; + typind = 0; + + int constantCount; + int scopeCount; + int slotCount; + int namespaceCount; + PdbFunction.CountScopesAndSlots(bits, block.end, out constantCount, out scopeCount, out slotCount, out namespaceCount); + constants = new PdbConstant[constantCount]; + scopes = new PdbScope[scopeCount]; + slots = new PdbSlot[slotCount]; + usedNamespaces = new string[namespaceCount]; + int constant = 0; + int scope = 0; + int slot = 0; + int usedNs = 0; + + while (bits.Position < block.end) { + ushort siz; + ushort rec; + + bits.ReadUInt16(out siz); + int star = bits.Position; + int stop = bits.Position + siz; + bits.Position = star; + bits.ReadUInt16(out rec); + + switch ((SYM)rec) { + case SYM.S_BLOCK32: { + BlockSym32 sub = new BlockSym32(); + + bits.ReadUInt32(out sub.parent); + bits.ReadUInt32(out sub.end); + bits.ReadUInt32(out sub.len); + bits.ReadUInt32(out sub.off); + bits.ReadUInt16(out sub.seg); + bits.SkipCString(out sub.name); + + bits.Position = stop; + scopes[scope++] = new PdbScope(funcOffset, sub, bits, out typind); + break; + } + + case SYM.S_MANSLOT: + slots[slot++] = new PdbSlot(bits); + bits.Position = stop; + break; + + case SYM.S_UNAMESPACE: + bits.ReadCString(out usedNamespaces[usedNs++]); + bits.Position = stop; + break; + + case SYM.S_END: + bits.Position = stop; + break; + + case SYM.S_MANCONSTANT: + constants[constant++] = new PdbConstant(bits); + bits.Position = stop; + break; + + default: + //throw new PdbException("Unknown SYM in scope {0}", (SYM)rec); + bits.Position = stop; + break; + } + } + + if (bits.Position != block.end) { + throw new Exception("Not at S_END"); + } + + ushort esiz; + ushort erec; + bits.ReadUInt16(out esiz); + bits.ReadUInt16(out erec); + + if (erec != (ushort)SYM.S_END) { + throw new Exception("Missing S_END"); + } + } + } +} diff --git a/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/PdbSlot.cs b/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/PdbSlot.cs new file mode 100644 index 0000000000..e2b76d5fb8 --- /dev/null +++ b/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/PdbSlot.cs @@ -0,0 +1,41 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the Microsoft Public License. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//----------------------------------------------------------------------------- +using System; + +namespace Microsoft.Cci.Pdb { + internal class PdbSlot { + internal uint slot; + internal uint typeToken; + internal string name; + internal ushort flags; + //internal uint segment; + //internal uint address; + + internal PdbSlot(BitAccess bits) { + AttrSlotSym slot; + + bits.ReadUInt32(out slot.index); + bits.ReadUInt32(out slot.typind); + bits.ReadUInt32(out slot.offCod); + bits.ReadUInt16(out slot.segCod); + bits.ReadUInt16(out slot.flags); + bits.ReadCString(out slot.name); + + this.slot = slot.index; + this.typeToken = slot.typind; + this.name = slot.name; + this.flags = slot.flags; + //this.segment = slot.segCod; + //this.address = slot.offCod; + + } + } +} diff --git a/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/PdbSource.cs b/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/PdbSource.cs new file mode 100644 index 0000000000..ac40f85160 --- /dev/null +++ b/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/PdbSource.cs @@ -0,0 +1,29 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the Microsoft Public License. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//----------------------------------------------------------------------------- +using System; + +namespace Microsoft.Cci.Pdb { + internal class PdbSource { + //internal uint index; + internal string name; + internal Guid doctype; + internal Guid language; + internal Guid vendor; + + internal PdbSource(/*uint index, */string name, Guid doctype, Guid language, Guid vendor) { + //this.index = index; + this.name = name; + this.doctype = doctype; + this.language = language; + this.vendor = vendor; + } + } +} diff --git a/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/PdbTokenLine.cs b/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/PdbTokenLine.cs new file mode 100644 index 0000000000..879339b23a --- /dev/null +++ b/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/PdbTokenLine.cs @@ -0,0 +1,33 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the Microsoft Public License. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//----------------------------------------------------------------------------- +using System; + +namespace Microsoft.Cci.Pdb { + internal class PdbTokenLine { + internal uint token; + internal uint file_id; + internal uint line; + internal uint column; + internal uint endLine; + internal uint endColumn; + internal PdbSource sourceFile; + internal PdbTokenLine/*?*/ nextLine; + + internal PdbTokenLine(uint token, uint file_id, uint line, uint column, uint endLine, uint endColumn) { + this.token = token; + this.file_id = file_id; + this.line = line; + this.column = column; + this.endLine = endLine; + this.endColumn = endColumn; + } + } +} diff --git a/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/SourceLocationProvider.cs b/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/SourceLocationProvider.cs new file mode 100644 index 0000000000..db3f291b4a --- /dev/null +++ b/external/cecil-legacy/symbols/pdb/Microsoft.Cci.Pdb/SourceLocationProvider.cs @@ -0,0 +1,33 @@ +//----------------------------------------------------------------------------- +// +// Copyright (C) Microsoft Corporation. All Rights Reserved. +// +//----------------------------------------------------------------------------- +using System; +using System.Collections.Generic; +using System.IO; +using Microsoft.Cci; +using Microsoft.Cci.Pdb; +using System.Text; +using System.Diagnostics.SymbolStore; + +namespace Microsoft.Cci { + + internal sealed class PdbIteratorScope : ILocalScope { + + internal PdbIteratorScope(uint offset, uint length) { + this.offset = offset; + this.length = length; + } + + public uint Offset { + get { return this.offset; } + } + uint offset; + + public uint Length { + get { return this.length; } + } + uint length; + } +} \ No newline at end of file diff --git a/external/cecil-legacy/symbols/pdb/Mono.Cecil.Pdb.csproj b/external/cecil-legacy/symbols/pdb/Mono.Cecil.Pdb.csproj new file mode 100644 index 0000000000..e35add055d --- /dev/null +++ b/external/cecil-legacy/symbols/pdb/Mono.Cecil.Pdb.csproj @@ -0,0 +1,133 @@ + + + + net_4_0_Debug + AnyCPU + 9.0.30729 + 2.0 + {63E6915C-7EA4-4D76-AB28-0D7191EEA626} + Library + Properties + Mono.Cecil.Pdb + Mono.Cecil.Pdb + 512 + true + ..\..\mono.snk + 0649 + + + true + full + false + ..\..\bin\net_2_0_Debug\ + DEBUG;TRACE + prompt + 4 + v2.0 + + + pdbonly + true + ..\..\bin\net_2_0_Release\ + TRACE + prompt + 4 + v2.0 + + + true + full + false + ..\..\bin\net_3_5_Debug\ + DEBUG;TRACE;NET_3_5 + prompt + 4 + v3.5 + + + pdbonly + true + ..\..\bin\net_3_5_Release\ + TRACE;NET_3_5 + prompt + 4 + v3.5 + + + true + full + false + ..\..\bin\net_4_0_Debug\ + DEBUG;TRACE;NET_3_5;NET_4_0 + prompt + 4 + v4.0 + + + pdbonly + true + ..\..\bin\net_4_0_Release\ + TRACE;NET_3_5;NET_4_0 + prompt + 4 + v4.0 + + + + + + + + + + {D68133BD-1E63-496E-9EDE-4FBDBF77B486} + Mono.Cecil + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Code + + + + + + + + + + + + + + \ No newline at end of file diff --git a/external/cecil-legacy/symbols/pdb/Mono.Cecil.Pdb/AssemblyInfo.cs b/external/cecil-legacy/symbols/pdb/Mono.Cecil.Pdb/AssemblyInfo.cs new file mode 100644 index 0000000000..14d2679907 --- /dev/null +++ b/external/cecil-legacy/symbols/pdb/Mono.Cecil.Pdb/AssemblyInfo.cs @@ -0,0 +1,41 @@ +// +// AssemblyInfo.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Reflection; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle ("Mono.Cecil.Pdb")] +[assembly: AssemblyProduct ("Mono.Cecil")] +[assembly: AssemblyCopyright ("Copyright © 2008 - 2011 Jb Evain")] + +[assembly: CLSCompliant (false)] +[assembly: ComVisible (false)] + +[assembly: AssemblyVersion ("0.9.5.0")] +[assembly: AssemblyFileVersion ("0.9.5.0")] diff --git a/external/cecil-legacy/symbols/pdb/Mono.Cecil.Pdb/ISymUnmanagedDocumentWriter.cs b/external/cecil-legacy/symbols/pdb/Mono.Cecil.Pdb/ISymUnmanagedDocumentWriter.cs new file mode 100644 index 0000000000..8f47b2c0f2 --- /dev/null +++ b/external/cecil-legacy/symbols/pdb/Mono.Cecil.Pdb/ISymUnmanagedDocumentWriter.cs @@ -0,0 +1,41 @@ +// ISymUnmanagedDocumentWriter.cs +// +// Author: +// Juerg Billeter (j@bitron.ch) +// +// (C) 2008 Juerg Billeter +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System.Runtime.InteropServices; + +#if !READ_ONLY + +namespace Mono.Cecil.Pdb { + + [Guid ("B01FAFEB-C450-3A4D-BEEC-B4CEEC01E006")] + [InterfaceType (ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + interface ISymUnmanagedDocumentWriter { + } +} + +#endif diff --git a/external/cecil-legacy/symbols/pdb/Mono.Cecil.Pdb/ISymUnmanagedWriter2.cs b/external/cecil-legacy/symbols/pdb/Mono.Cecil.Pdb/ISymUnmanagedWriter2.cs new file mode 100644 index 0000000000..11466dcb9d --- /dev/null +++ b/external/cecil-legacy/symbols/pdb/Mono.Cecil.Pdb/ISymUnmanagedWriter2.cs @@ -0,0 +1,103 @@ +// +// ISymUnmanagedWriter2.cs +// +// Author: +// Juerg Billeter (j@bitron.ch) +// +// (C) 2008 Juerg Billeter +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Diagnostics.SymbolStore; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.ComTypes; + +using Mono.Cecil.Cil; + +#if !READ_ONLY + +namespace Mono.Cecil.Pdb { + + [Guid ("0B97726E-9E6D-4f05-9A26-424022093CAA")] + [InterfaceType (ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + interface ISymUnmanagedWriter2 { + + void DefineDocument ( + [In, MarshalAs (UnmanagedType.LPWStr)] string url, + [In] ref Guid langauge, + [In] ref Guid languageVendor, + [In] ref Guid documentType, + [Out, MarshalAs (UnmanagedType.Interface)] out ISymUnmanagedDocumentWriter pRetVal); + void SetUserEntryPoint ([In] SymbolToken method); + void OpenMethod ([In] SymbolToken method); + void CloseMethod (); + void OpenScope ([In] int startOffset, [Out] out int pRetVal); + void CloseScope ([In] int endOffset); + void SetScopeRange_Placeholder (); + void DefineLocalVariable_Placeholder (); + void DefineParameter_Placeholder (); + void DefineField_Placeholder (); + void DefineGlobalVariable_Placeholder (); + void Close (); + void SetSymAttribute_Placeholder (); + void OpenNamespace ([In, MarshalAs (UnmanagedType.LPWStr)] string name); + void CloseNamespace (); + void UsingNamespace ([In, MarshalAs (UnmanagedType.LPWStr)] string fullName); + void SetMethodSourceRange_Placeholder (); + void Initialize ( + [In, MarshalAs (UnmanagedType.IUnknown)] object emitter, + [In, MarshalAs (UnmanagedType.LPWStr)] string filename, + [In] IStream pIStream, + [In] bool fFullBuild); + void GetDebugInfo ( + [Out] out ImageDebugDirectory pIDD, + [In] int cData, + [Out] out int pcData, + [In, Out, MarshalAs (UnmanagedType.LPArray, SizeParamIndex = 1)] byte [] data); + void DefineSequencePoints ( + [In, MarshalAs (UnmanagedType.Interface)] ISymUnmanagedDocumentWriter document, + [In] int spCount, + [In, MarshalAs (UnmanagedType.LPArray, SizeParamIndex = 1)] int [] offsets, + [In, MarshalAs (UnmanagedType.LPArray, SizeParamIndex = 1)] int [] lines, + [In, MarshalAs (UnmanagedType.LPArray, SizeParamIndex = 1)] int [] columns, + [In, MarshalAs (UnmanagedType.LPArray, SizeParamIndex = 1)] int [] endLines, + [In, MarshalAs (UnmanagedType.LPArray, SizeParamIndex = 1)] int [] endColumns); + void RemapToken_Placeholder (); + void Initialize2_Placeholder (); + void DefineConstant_Placeholder (); + void Abort_Placeholder (); + + void DefineLocalVariable2 ( + [In, MarshalAs (UnmanagedType.LPWStr)] string name, + [In] int attributes, + [In] SymbolToken sigToken, + [In] int addrKind, + [In] int addr1, + [In] int addr2, + [In] int addr3, + [In] int startOffset, + [In] int endOffset); + } +} + +#endif diff --git a/external/cecil-legacy/symbols/pdb/Mono.Cecil.Pdb/ModuleMetadata.cs b/external/cecil-legacy/symbols/pdb/Mono.Cecil.Pdb/ModuleMetadata.cs new file mode 100644 index 0000000000..e06f12aefb --- /dev/null +++ b/external/cecil-legacy/symbols/pdb/Mono.Cecil.Pdb/ModuleMetadata.cs @@ -0,0 +1,796 @@ +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Text; + +#if !READ_ONLY + +namespace Mono.Cecil.Pdb { + + [ComImport, InterfaceType (ComInterfaceType.InterfaceIsIUnknown), Guid ("BA3FEE4C-ECB9-4e41-83B7-183FA41CD859")] + interface IMetaDataEmit { + void SetModuleProps (string szName); + void Save (string szFile, uint dwSaveFlags); + void SaveToStream (IntPtr pIStream, uint dwSaveFlags); + uint GetSaveSize (uint fSave); + uint DefineTypeDef (IntPtr szTypeDef, uint dwTypeDefFlags, uint tkExtends, IntPtr rtkImplements); + uint DefineNestedType (IntPtr szTypeDef, uint dwTypeDefFlags, uint tkExtends, IntPtr rtkImplements, uint tdEncloser); + void SetHandler ([MarshalAs (UnmanagedType.IUnknown), In]object pUnk); + uint DefineMethod (uint td, IntPtr zName, uint dwMethodFlags, IntPtr pvSigBlob, uint cbSigBlob, uint ulCodeRVA, uint dwImplFlags); + void DefineMethodImpl (uint td, uint tkBody, uint tkDecl); + uint DefineTypeRefByName (uint tkResolutionScope, IntPtr szName); + uint DefineImportType (IntPtr pAssemImport, IntPtr pbHashValue, uint cbHashValue, IMetaDataImport pImport, + uint tdImport, IntPtr pAssemEmit); + uint DefineMemberRef (uint tkImport, string szName, IntPtr pvSigBlob, uint cbSigBlob); + uint DefineImportMember (IntPtr pAssemImport, IntPtr /* void* */ pbHashValue, uint cbHashValue, + IMetaDataImport pImport, uint mbMember, IntPtr pAssemEmit, uint tkParent); + uint DefineEvent (uint td, string szEvent, uint dwEventFlags, uint tkEventType, uint mdAddOn, uint mdRemoveOn, uint mdFire, IntPtr /* uint* */ rmdOtherMethods); + void SetClassLayout (uint td, uint dwPackSize, IntPtr /*COR_FIELD_OFFSET**/ rFieldOffsets, uint ulClassSize); + void DeleteClassLayout (uint td); + void SetFieldMarshal (uint tk, IntPtr /* byte* */ pvNativeType, uint cbNativeType); + void DeleteFieldMarshal (uint tk); + uint DefinePermissionSet (uint tk, uint dwAction, IntPtr /* void* */ pvPermission, uint cbPermission); + void SetRVA (uint md, uint ulRVA); + uint GetTokenFromSig (IntPtr /* byte* */ pvSig, uint cbSig); + uint DefineModuleRef (string szName); + void SetParent (uint mr, uint tk); + uint GetTokenFromTypeSpec (IntPtr /* byte* */ pvSig, uint cbSig); + void SaveToMemory (IntPtr /* void* */ pbData, uint cbData); + uint DefineUserString (string szString, uint cchString); + void DeleteToken (uint tkObj); + void SetMethodProps (uint md, uint dwMethodFlags, uint ulCodeRVA, uint dwImplFlags); + void SetTypeDefProps (uint td, uint dwTypeDefFlags, uint tkExtends, IntPtr /* uint* */ rtkImplements); + void SetEventProps (uint ev, uint dwEventFlags, uint tkEventType, uint mdAddOn, uint mdRemoveOn, uint mdFire, IntPtr /* uint* */ rmdOtherMethods); + uint SetPermissionSetProps (uint tk, uint dwAction, IntPtr /* void* */ pvPermission, uint cbPermission); + void DefinePinvokeMap (uint tk, uint dwMappingFlags, string szImportName, uint mrImportDLL); + void SetPinvokeMap (uint tk, uint dwMappingFlags, string szImportName, uint mrImportDLL); + void DeletePinvokeMap (uint tk); + uint DefineCustomAttribute (uint tkObj, uint tkType, IntPtr /* void* */ pCustomAttribute, uint cbCustomAttribute); + void SetCustomAttributeValue (uint pcv, IntPtr /* void* */ pCustomAttribute, uint cbCustomAttribute); + uint DefineField (uint td, string szName, uint dwFieldFlags, IntPtr /* byte* */ pvSigBlob, uint cbSigBlob, uint dwCPlusTypeFlag, IntPtr /* void* */ pValue, uint cchValue); + uint DefineProperty (uint td, string szProperty, uint dwPropFlags, IntPtr /* byte* */ pvSig, uint cbSig, uint dwCPlusTypeFlag, + IntPtr /* void* */ pValue, uint cchValue, uint mdSetter, uint mdGetter, IntPtr /* uint* */ rmdOtherMethods); + uint DefineParam (uint md, uint ulParamSeq, string szName, uint dwParamFlags, uint dwCPlusTypeFlag, IntPtr /* void* */ pValue, uint cchValue); + void SetFieldProps (uint fd, uint dwFieldFlags, uint dwCPlusTypeFlag, IntPtr /* void* */ pValue, uint cchValue); + void SetPropertyProps (uint pr, uint dwPropFlags, uint dwCPlusTypeFlag, IntPtr /* void* */ pValue, uint cchValue, uint mdSetter, uint mdGetter, IntPtr /* uint* */ rmdOtherMethods); + void SetParamProps (uint pd, string szName, uint dwParamFlags, uint dwCPlusTypeFlag, IntPtr /* void* */ pValue, uint cchValue); + uint DefineSecurityAttributeSet (uint tkObj, IntPtr rSecAttrs, uint cSecAttrs); + void ApplyEditAndContinue ([MarshalAs (UnmanagedType.IUnknown)]object pImport); + uint TranslateSigWithScope (IntPtr pAssemImport, IntPtr /* void* */ pbHashValue, uint cbHashValue, + IMetaDataImport import, IntPtr /* byte* */ pbSigBlob, uint cbSigBlob, IntPtr pAssemEmit, IMetaDataEmit emit, IntPtr /* byte* */ pvTranslatedSig, uint cbTranslatedSigMax); + void SetMethodImplFlags (uint md, uint dwImplFlags); + void SetFieldRVA (uint fd, uint ulRVA); + void Merge (IMetaDataImport pImport, IntPtr pHostMapToken, [MarshalAs (UnmanagedType.IUnknown)]object pHandler); + void MergeEnd (); + } + + [ComImport, InterfaceType (ComInterfaceType.InterfaceIsIUnknown), Guid ("7DAC8207-D3AE-4c75-9B67-92801A497D44")] + interface IMetaDataImport { + [PreserveSig] + void CloseEnum (uint hEnum); + uint CountEnum (uint hEnum); + void ResetEnum (uint hEnum, uint ulPos); + uint EnumTypeDefs (ref uint phEnum, [MarshalAs (UnmanagedType.LPArray, SizeParamIndex = 2)] uint [] rTypeDefs, uint cMax); + uint EnumInterfaceImpls (ref uint phEnum, uint td, [MarshalAs (UnmanagedType.LPArray, SizeParamIndex = 3)] uint [] rImpls, uint cMax); + uint EnumTypeRefs (ref uint phEnum, [MarshalAs (UnmanagedType.LPArray, SizeParamIndex = 2)] uint [] rTypeRefs, uint cMax); + uint FindTypeDefByName (string szTypeDef, uint tkEnclosingClass); + Guid GetScopeProps (StringBuilder szName, uint cchName, out uint pchName); + uint GetModuleFromScope (); + uint GetTypeDefProps (uint td, IntPtr szTypeDef, uint cchTypeDef, out uint pchTypeDef, IntPtr pdwTypeDefFlags); + uint GetInterfaceImplProps (uint iiImpl, out uint pClass); + uint GetTypeRefProps (uint tr, out uint ptkResolutionScope, StringBuilder szName, uint cchName); + uint ResolveTypeRef (uint tr, [In] ref Guid riid, [MarshalAs (UnmanagedType.Interface)] out object ppIScope); + uint EnumMembers (ref uint phEnum, uint cl, [MarshalAs (UnmanagedType.LPArray, SizeParamIndex = 3)] uint [] rMembers, uint cMax); + uint EnumMembersWithName (ref uint phEnum, uint cl, string szName, [MarshalAs (UnmanagedType.LPArray, SizeParamIndex = 4)] uint [] rMembers, uint cMax); + uint EnumMethods (ref uint phEnum, uint cl, IntPtr /* uint* */ rMethods, uint cMax); + uint EnumMethodsWithName (ref uint phEnum, uint cl, string szName, [MarshalAs (UnmanagedType.LPArray, SizeParamIndex = 4)] uint [] rMethods, uint cMax); + uint EnumFields (ref uint phEnum, uint cl, IntPtr /* uint* */ rFields, uint cMax); + uint EnumFieldsWithName (ref uint phEnum, uint cl, string szName, [MarshalAs (UnmanagedType.LPArray, SizeParamIndex = 4)] uint [] rFields, uint cMax); + uint EnumParams (ref uint phEnum, uint mb, [MarshalAs (UnmanagedType.LPArray, SizeParamIndex = 3)] uint [] rParams, uint cMax); + uint EnumMemberRefs (ref uint phEnum, uint tkParent, [MarshalAs (UnmanagedType.LPArray, SizeParamIndex = 3)] uint [] rMemberRefs, uint cMax); + uint EnumMethodImpls (ref uint phEnum, uint td, [MarshalAs (UnmanagedType.LPArray, SizeParamIndex = 4)] uint [] rMethodBody, + [MarshalAs (UnmanagedType.LPArray, SizeParamIndex = 4)] uint [] rMethodDecl, uint cMax); + uint EnumPermissionSets (ref uint phEnum, uint tk, uint dwActions, [MarshalAs (UnmanagedType.LPArray, SizeParamIndex = 4)] uint [] rPermission, + uint cMax); + uint FindMember (uint td, string szName, [MarshalAs (UnmanagedType.LPArray, SizeParamIndex = 3)] byte [] pvSigBlob, uint cbSigBlob); + uint FindMethod (uint td, string szName, [MarshalAs (UnmanagedType.LPArray, SizeParamIndex = 3)] byte [] pvSigBlob, uint cbSigBlob); + uint FindField (uint td, string szName, [MarshalAs (UnmanagedType.LPArray, SizeParamIndex = 3)] byte [] pvSigBlob, uint cbSigBlob); + uint FindMemberRef (uint td, string szName, [MarshalAs (UnmanagedType.LPArray, SizeParamIndex = 3)] byte [] pvSigBlob, uint cbSigBlob); + uint GetMethodProps (uint mb, out uint pClass, IntPtr szMethod, uint cchMethod, out uint pchMethod, IntPtr pdwAttr, IntPtr ppvSigBlob, IntPtr pcbSigBlob, IntPtr pulCodeRVA); + uint GetMemberRefProps (uint mr, ref uint ptk, StringBuilder szMember, uint cchMember, out uint pchMember, out IntPtr /* byte* */ ppvSigBlob); + uint EnumProperties (ref uint phEnum, uint td, IntPtr /* uint* */ rProperties, uint cMax); + uint EnumEvents (ref uint phEnum, uint td, IntPtr /* uint* */ rEvents, uint cMax); + uint GetEventProps (uint ev, out uint pClass, StringBuilder szEvent, uint cchEvent, out uint pchEvent, out uint pdwEventFlags, + out uint ptkEventType, out uint pmdAddOn, out uint pmdRemoveOn, out uint pmdFire, + [MarshalAs (UnmanagedType.LPArray, SizeParamIndex = 11)] uint [] rmdOtherMethod, uint cMax); + uint EnumMethodSemantics (ref uint phEnum, uint mb, [MarshalAs (UnmanagedType.LPArray, SizeParamIndex = 3)] uint [] rEventProp, uint cMax); + uint GetMethodSemantics (uint mb, uint tkEventProp); + uint GetClassLayout (uint td, out uint pdwPackSize, [MarshalAs (UnmanagedType.LPArray, SizeParamIndex = 3)] IntPtr /*COR_FIELD_OFFSET **/ rFieldOffset, uint cMax, out uint pcFieldOffset); + uint GetFieldMarshal (uint tk, out IntPtr /* byte* */ ppvNativeType); + uint GetRVA (uint tk, out uint pulCodeRVA); + uint GetPermissionSetProps (uint pm, out uint pdwAction, out IntPtr /* void* */ ppvPermission); + uint GetSigFromToken (uint mdSig, out IntPtr /* byte* */ ppvSig); + uint GetModuleRefProps (uint mur, StringBuilder szName, uint cchName); + uint EnumModuleRefs (ref uint phEnum, [MarshalAs (UnmanagedType.LPArray, SizeParamIndex = 2)] uint [] rModuleRefs, uint cmax); + uint GetTypeSpecFromToken (uint typespec, out IntPtr /* byte* */ ppvSig); + uint GetNameFromToken (uint tk); + uint EnumUnresolvedMethods (ref uint phEnum, [MarshalAs (UnmanagedType.LPArray, SizeParamIndex = 2)] uint [] rMethods, uint cMax); + uint GetUserString (uint stk, StringBuilder szString, uint cchString); + uint GetPinvokeMap (uint tk, out uint pdwMappingFlags, StringBuilder szImportName, uint cchImportName, out uint pchImportName); + uint EnumSignatures (ref uint phEnum, [MarshalAs (UnmanagedType.LPArray, SizeParamIndex = 2)] uint [] rSignatures, uint cmax); + uint EnumTypeSpecs (ref uint phEnum, [MarshalAs (UnmanagedType.LPArray, SizeParamIndex = 2)] uint [] rTypeSpecs, uint cmax); + uint EnumUserStrings (ref uint phEnum, [MarshalAs (UnmanagedType.LPArray, SizeParamIndex = 2)] uint [] rStrings, uint cmax); + [PreserveSig] + int GetParamForMethodIndex (uint md, uint ulParamSeq, out uint pParam); + uint EnumCustomAttributes (ref uint phEnum, uint tk, uint tkType, [MarshalAs (UnmanagedType.LPArray, SizeParamIndex = 4)] uint [] rCustomAttributes, uint cMax); + uint GetCustomAttributeProps (uint cv, out uint ptkObj, out uint ptkType, out IntPtr /* void* */ ppBlob); + uint FindTypeRef (uint tkResolutionScope, string szName); + uint GetMemberProps (uint mb, out uint pClass, StringBuilder szMember, uint cchMember, out uint pchMember, out uint pdwAttr, + out IntPtr /* byte* */ ppvSigBlob, out uint pcbSigBlob, out uint pulCodeRVA, out uint pdwImplFlags, out uint pdwCPlusTypeFlag, out IntPtr /* void* */ ppValue); + uint GetFieldProps (uint mb, out uint pClass, StringBuilder szField, uint cchField, out uint pchField, out uint pdwAttr, + out IntPtr /* byte* */ ppvSigBlob, out uint pcbSigBlob, out uint pdwCPlusTypeFlag, out IntPtr /* void* */ ppValue); + uint GetPropertyProps (uint prop, out uint pClass, StringBuilder szProperty, uint cchProperty, out uint pchProperty, out uint pdwPropFlags, + out IntPtr /* byte* */ ppvSig, out uint pbSig, out uint pdwCPlusTypeFlag, out IntPtr /* void* */ ppDefaultValue, out uint pcchDefaultValue, out uint pmdSetter, + out uint pmdGetter, [MarshalAs (UnmanagedType.LPArray, SizeParamIndex = 14)] uint [] rmdOtherMethod, uint cMax); + uint GetParamProps (uint tk, out uint pmd, out uint pulSequence, StringBuilder szName, uint cchName, out uint pchName, + out uint pdwAttr, out uint pdwCPlusTypeFlag, out IntPtr /* void* */ ppValue); + uint GetCustomAttributeByName (uint tkObj, string szName, out IntPtr /* void* */ ppData); + [PreserveSig] + [return: MarshalAs (UnmanagedType.Bool)] + bool IsValidToken (uint tk); + uint GetNestedClassProps (uint tdNestedClass); + uint GetNativeCallConvFromSig (IntPtr /* void* */ pvSig, uint cbSig); + int IsGlobal (uint pd); + } + + class ModuleMetadata : IMetaDataEmit, IMetaDataImport { + + readonly ModuleDefinition module; + + Dictionary types; + Dictionary methods; + + public ModuleMetadata (ModuleDefinition module) + { + this.module = module; + } + + bool TryGetType (uint token, out TypeDefinition type) + { + if (types == null) + InitializeMetadata (module); + + return types.TryGetValue (token, out type); + } + + bool TryGetMethod (uint token, out MethodDefinition method) + { + if (methods == null) + InitializeMetadata (module); + + return methods.TryGetValue (token, out method); + } + + void InitializeMetadata (ModuleDefinition module) + { + types = new Dictionary (); + methods = new Dictionary (); + + foreach (var type in module.GetTypes ()) { + types.Add (type.MetadataToken.ToUInt32 (), type); + InitializeMethods (type); + } + } + + void InitializeMethods (TypeDefinition type) + { + foreach (var method in type.Methods) + methods.Add (method.MetadataToken.ToUInt32 (), method); + } + + public void SetModuleProps (string szName) + { + throw new NotImplementedException (); + } + + public void Save (string szFile, uint dwSaveFlags) + { + throw new NotImplementedException (); + } + + public void SaveToStream (IntPtr pIStream, uint dwSaveFlags) + { + throw new NotImplementedException (); + } + + public uint GetSaveSize (uint fSave) + { + throw new NotImplementedException (); + } + + public uint DefineTypeDef (IntPtr szTypeDef, uint dwTypeDefFlags, uint tkExtends, IntPtr rtkImplements) + { + throw new NotImplementedException (); + } + + public uint DefineNestedType (IntPtr szTypeDef, uint dwTypeDefFlags, uint tkExtends, IntPtr rtkImplements, uint tdEncloser) + { + throw new NotImplementedException (); + } + + public void SetHandler (object pUnk) + { + throw new NotImplementedException (); + } + + public uint DefineMethod (uint td, IntPtr zName, uint dwMethodFlags, IntPtr pvSigBlob, uint cbSigBlob, uint ulCodeRVA, uint dwImplFlags) + { + throw new NotImplementedException (); + } + + public void DefineMethodImpl (uint td, uint tkBody, uint tkDecl) + { + throw new NotImplementedException (); + } + + public uint DefineTypeRefByName (uint tkResolutionScope, IntPtr szName) + { + throw new NotImplementedException (); + } + + public uint DefineImportType (IntPtr pAssemImport, IntPtr pbHashValue, uint cbHashValue, IMetaDataImport pImport, uint tdImport, IntPtr pAssemEmit) + { + throw new NotImplementedException (); + } + + public uint DefineMemberRef (uint tkImport, string szName, IntPtr pvSigBlob, uint cbSigBlob) + { + throw new NotImplementedException (); + } + + public uint DefineImportMember (IntPtr pAssemImport, IntPtr pbHashValue, uint cbHashValue, IMetaDataImport pImport, uint mbMember, IntPtr pAssemEmit, uint tkParent) + { + throw new NotImplementedException (); + } + + public uint DefineEvent (uint td, string szEvent, uint dwEventFlags, uint tkEventType, uint mdAddOn, uint mdRemoveOn, uint mdFire, IntPtr rmdOtherMethods) + { + throw new NotImplementedException (); + } + + public void SetClassLayout (uint td, uint dwPackSize, IntPtr rFieldOffsets, uint ulClassSize) + { + throw new NotImplementedException (); + } + + public void DeleteClassLayout (uint td) + { + throw new NotImplementedException (); + } + + public void SetFieldMarshal (uint tk, IntPtr pvNativeType, uint cbNativeType) + { + throw new NotImplementedException (); + } + + public void DeleteFieldMarshal (uint tk) + { + throw new NotImplementedException (); + } + + public uint DefinePermissionSet (uint tk, uint dwAction, IntPtr pvPermission, uint cbPermission) + { + throw new NotImplementedException (); + } + + public void SetRVA (uint md, uint ulRVA) + { + throw new NotImplementedException (); + } + + public uint GetTokenFromSig (IntPtr pvSig, uint cbSig) + { + throw new NotImplementedException (); + } + + public uint DefineModuleRef (string szName) + { + throw new NotImplementedException (); + } + + public void SetParent (uint mr, uint tk) + { + throw new NotImplementedException (); + } + + public uint GetTokenFromTypeSpec (IntPtr pvSig, uint cbSig) + { + throw new NotImplementedException (); + } + + public void SaveToMemory (IntPtr pbData, uint cbData) + { + throw new NotImplementedException (); + } + + public uint DefineUserString (string szString, uint cchString) + { + throw new NotImplementedException (); + } + + public void DeleteToken (uint tkObj) + { + throw new NotImplementedException (); + } + + public void SetMethodProps (uint md, uint dwMethodFlags, uint ulCodeRVA, uint dwImplFlags) + { + throw new NotImplementedException (); + } + + public void SetTypeDefProps (uint td, uint dwTypeDefFlags, uint tkExtends, IntPtr rtkImplements) + { + throw new NotImplementedException (); + } + + public void SetEventProps (uint ev, uint dwEventFlags, uint tkEventType, uint mdAddOn, uint mdRemoveOn, uint mdFire, IntPtr rmdOtherMethods) + { + throw new NotImplementedException (); + } + + public uint SetPermissionSetProps (uint tk, uint dwAction, IntPtr pvPermission, uint cbPermission) + { + throw new NotImplementedException (); + } + + public void DefinePinvokeMap (uint tk, uint dwMappingFlags, string szImportName, uint mrImportDLL) + { + throw new NotImplementedException (); + } + + public void SetPinvokeMap (uint tk, uint dwMappingFlags, string szImportName, uint mrImportDLL) + { + throw new NotImplementedException (); + } + + public void DeletePinvokeMap (uint tk) + { + throw new NotImplementedException (); + } + + public uint DefineCustomAttribute (uint tkObj, uint tkType, IntPtr pCustomAttribute, uint cbCustomAttribute) + { + throw new NotImplementedException (); + } + + public void SetCustomAttributeValue (uint pcv, IntPtr pCustomAttribute, uint cbCustomAttribute) + { + throw new NotImplementedException (); + } + + public uint DefineField (uint td, string szName, uint dwFieldFlags, IntPtr pvSigBlob, uint cbSigBlob, uint dwCPlusTypeFlag, IntPtr pValue, uint cchValue) + { + throw new NotImplementedException (); + } + + public uint DefineProperty (uint td, string szProperty, uint dwPropFlags, IntPtr pvSig, uint cbSig, uint dwCPlusTypeFlag, IntPtr pValue, uint cchValue, uint mdSetter, uint mdGetter, IntPtr rmdOtherMethods) + { + throw new NotImplementedException (); + } + + public uint DefineParam (uint md, uint ulParamSeq, string szName, uint dwParamFlags, uint dwCPlusTypeFlag, IntPtr pValue, uint cchValue) + { + throw new NotImplementedException (); + } + + public void SetFieldProps (uint fd, uint dwFieldFlags, uint dwCPlusTypeFlag, IntPtr pValue, uint cchValue) + { + throw new NotImplementedException (); + } + + public void SetPropertyProps (uint pr, uint dwPropFlags, uint dwCPlusTypeFlag, IntPtr pValue, uint cchValue, uint mdSetter, uint mdGetter, IntPtr rmdOtherMethods) + { + throw new NotImplementedException (); + } + + public void SetParamProps (uint pd, string szName, uint dwParamFlags, uint dwCPlusTypeFlag, IntPtr pValue, uint cchValue) + { + throw new NotImplementedException (); + } + + public uint DefineSecurityAttributeSet (uint tkObj, IntPtr rSecAttrs, uint cSecAttrs) + { + throw new NotImplementedException (); + } + + public void ApplyEditAndContinue (object pImport) + { + throw new NotImplementedException (); + } + + public uint TranslateSigWithScope (IntPtr pAssemImport, IntPtr pbHashValue, uint cbHashValue, IMetaDataImport import, IntPtr pbSigBlob, uint cbSigBlob, IntPtr pAssemEmit, IMetaDataEmit emit, IntPtr pvTranslatedSig, uint cbTranslatedSigMax) + { + throw new NotImplementedException (); + } + + public void SetMethodImplFlags (uint md, uint dwImplFlags) + { + throw new NotImplementedException (); + } + + public void SetFieldRVA (uint fd, uint ulRVA) + { + throw new NotImplementedException (); + } + + public void Merge (IMetaDataImport pImport, IntPtr pHostMapToken, object pHandler) + { + throw new NotImplementedException (); + } + + public void MergeEnd () + { + throw new NotImplementedException (); + } + + public void CloseEnum (uint hEnum) + { + throw new NotImplementedException (); + } + + public uint CountEnum (uint hEnum) + { + throw new NotImplementedException (); + } + + public void ResetEnum (uint hEnum, uint ulPos) + { + throw new NotImplementedException (); + } + + public uint EnumTypeDefs (ref uint phEnum, uint[] rTypeDefs, uint cMax) + { + throw new NotImplementedException (); + } + + public uint EnumInterfaceImpls (ref uint phEnum, uint td, uint[] rImpls, uint cMax) + { + throw new NotImplementedException (); + } + + public uint EnumTypeRefs (ref uint phEnum, uint[] rTypeRefs, uint cMax) + { + throw new NotImplementedException (); + } + + public uint FindTypeDefByName (string szTypeDef, uint tkEnclosingClass) + { + throw new NotImplementedException (); + } + + public Guid GetScopeProps (StringBuilder szName, uint cchName, out uint pchName) + { + throw new NotImplementedException (); + } + + public uint GetModuleFromScope () + { + throw new NotImplementedException (); + } + + public uint GetTypeDefProps (uint td, IntPtr szTypeDef, uint cchTypeDef, out uint pchTypeDef, IntPtr pdwTypeDefFlags) + { + TypeDefinition type; + if (!TryGetType (td, out type)) { + Marshal.WriteInt16 (szTypeDef, 0); + pchTypeDef = 1; + return 0; + } + + WriteString (type.Name, szTypeDef, cchTypeDef, out pchTypeDef); + WriteIntPtr (pdwTypeDefFlags, (uint) type.Attributes); + return type.BaseType != null ? type.BaseType.MetadataToken.ToUInt32 () : 0; + } + + static void WriteIntPtr (IntPtr ptr, uint value) + { + if (ptr == IntPtr.Zero) + return; + + Marshal.WriteInt32 (ptr, (int) value); + } + + static void WriteString (string str, IntPtr buffer, uint bufferSize, out uint chars) + { + var length = str.Length + 1 >= bufferSize ? bufferSize - 1 : (uint) str.Length; + chars = length + 1; + var offset = 0; + + for (int i = 0; i < length; i++) { + Marshal.WriteInt16 (buffer, offset, str [i]); + offset += 2; + } + + Marshal.WriteInt16 (buffer, offset, 0); + } + + public uint GetInterfaceImplProps (uint iiImpl, out uint pClass) + { + throw new NotImplementedException (); + } + + public uint GetTypeRefProps (uint tr, out uint ptkResolutionScope, StringBuilder szName, uint cchName) + { + throw new NotImplementedException (); + } + + public uint ResolveTypeRef (uint tr, ref Guid riid, out object ppIScope) + { + throw new NotImplementedException (); + } + + public uint EnumMembers (ref uint phEnum, uint cl, uint[] rMembers, uint cMax) + { + throw new NotImplementedException (); + } + + public uint EnumMembersWithName (ref uint phEnum, uint cl, string szName, uint[] rMembers, uint cMax) + { + throw new NotImplementedException (); + } + + public uint EnumMethods (ref uint phEnum, uint cl, IntPtr rMethods, uint cMax) + { + throw new NotImplementedException (); + } + + public uint EnumMethodsWithName (ref uint phEnum, uint cl, string szName, uint[] rMethods, uint cMax) + { + throw new NotImplementedException (); + } + + public uint EnumFields (ref uint phEnum, uint cl, IntPtr rFields, uint cMax) + { + throw new NotImplementedException (); + } + + public uint EnumFieldsWithName (ref uint phEnum, uint cl, string szName, uint[] rFields, uint cMax) + { + throw new NotImplementedException (); + } + + public uint EnumParams (ref uint phEnum, uint mb, uint[] rParams, uint cMax) + { + throw new NotImplementedException (); + } + + public uint EnumMemberRefs (ref uint phEnum, uint tkParent, uint[] rMemberRefs, uint cMax) + { + throw new NotImplementedException (); + } + + public uint EnumMethodImpls (ref uint phEnum, uint td, uint[] rMethodBody, uint[] rMethodDecl, uint cMax) + { + throw new NotImplementedException (); + } + + public uint EnumPermissionSets (ref uint phEnum, uint tk, uint dwActions, uint[] rPermission, uint cMax) + { + throw new NotImplementedException (); + } + + public uint FindMember (uint td, string szName, byte[] pvSigBlob, uint cbSigBlob) + { + throw new NotImplementedException (); + } + + public uint FindMethod (uint td, string szName, byte[] pvSigBlob, uint cbSigBlob) + { + throw new NotImplementedException (); + } + + public uint FindField (uint td, string szName, byte[] pvSigBlob, uint cbSigBlob) + { + throw new NotImplementedException (); + } + + public uint FindMemberRef (uint td, string szName, byte[] pvSigBlob, uint cbSigBlob) + { + throw new NotImplementedException (); + } + + public uint GetMethodProps (uint mb, out uint pClass, IntPtr szMethod, uint cchMethod, out uint pchMethod, IntPtr pdwAttr, IntPtr ppvSigBlob, IntPtr pcbSigBlob, IntPtr pulCodeRVA) + { + MethodDefinition method; + if (!TryGetMethod (mb, out method)) { + Marshal.WriteInt16 (szMethod, 0); + pchMethod = 1; + pClass = 0; + return 0; + } + + pClass = method.DeclaringType.MetadataToken.ToUInt32 (); + WriteString (method.Name, szMethod, cchMethod, out pchMethod); + WriteIntPtr (pdwAttr, (uint) method.Attributes); + WriteIntPtr (pulCodeRVA, (uint) method.RVA); + + return (uint) method.ImplAttributes; + } + + public uint GetMemberRefProps (uint mr, ref uint ptk, StringBuilder szMember, uint cchMember, out uint pchMember, out IntPtr ppvSigBlob) + { + throw new NotImplementedException (); + } + + public uint EnumProperties (ref uint phEnum, uint td, IntPtr rProperties, uint cMax) + { + throw new NotImplementedException (); + } + + public uint EnumEvents (ref uint phEnum, uint td, IntPtr rEvents, uint cMax) + { + throw new NotImplementedException (); + } + + public uint GetEventProps (uint ev, out uint pClass, StringBuilder szEvent, uint cchEvent, out uint pchEvent, out uint pdwEventFlags, out uint ptkEventType, out uint pmdAddOn, out uint pmdRemoveOn, out uint pmdFire, uint[] rmdOtherMethod, uint cMax) + { + throw new NotImplementedException (); + } + + public uint EnumMethodSemantics (ref uint phEnum, uint mb, uint[] rEventProp, uint cMax) + { + throw new NotImplementedException (); + } + + public uint GetMethodSemantics (uint mb, uint tkEventProp) + { + throw new NotImplementedException (); + } + + public uint GetClassLayout (uint td, out uint pdwPackSize, IntPtr rFieldOffset, uint cMax, out uint pcFieldOffset) + { + throw new NotImplementedException (); + } + + public uint GetFieldMarshal (uint tk, out IntPtr ppvNativeType) + { + throw new NotImplementedException (); + } + + public uint GetRVA (uint tk, out uint pulCodeRVA) + { + throw new NotImplementedException (); + } + + public uint GetPermissionSetProps (uint pm, out uint pdwAction, out IntPtr ppvPermission) + { + throw new NotImplementedException (); + } + + public uint GetSigFromToken (uint mdSig, out IntPtr ppvSig) + { + throw new NotImplementedException (); + } + + public uint GetModuleRefProps (uint mur, StringBuilder szName, uint cchName) + { + throw new NotImplementedException (); + } + + public uint EnumModuleRefs (ref uint phEnum, uint[] rModuleRefs, uint cmax) + { + throw new NotImplementedException (); + } + + public uint GetTypeSpecFromToken (uint typespec, out IntPtr ppvSig) + { + throw new NotImplementedException (); + } + + public uint GetNameFromToken (uint tk) + { + throw new NotImplementedException (); + } + + public uint EnumUnresolvedMethods (ref uint phEnum, uint[] rMethods, uint cMax) + { + throw new NotImplementedException (); + } + + public uint GetUserString (uint stk, StringBuilder szString, uint cchString) + { + throw new NotImplementedException (); + } + + public uint GetPinvokeMap (uint tk, out uint pdwMappingFlags, StringBuilder szImportName, uint cchImportName, out uint pchImportName) + { + throw new NotImplementedException (); + } + + public uint EnumSignatures (ref uint phEnum, uint[] rSignatures, uint cmax) + { + throw new NotImplementedException (); + } + + public uint EnumTypeSpecs (ref uint phEnum, uint[] rTypeSpecs, uint cmax) + { + throw new NotImplementedException (); + } + + public uint EnumUserStrings (ref uint phEnum, uint[] rStrings, uint cmax) + { + throw new NotImplementedException (); + } + + public int GetParamForMethodIndex (uint md, uint ulParamSeq, out uint pParam) + { + throw new NotImplementedException (); + } + + public uint EnumCustomAttributes (ref uint phEnum, uint tk, uint tkType, uint[] rCustomAttributes, uint cMax) + { + throw new NotImplementedException (); + } + + public uint GetCustomAttributeProps (uint cv, out uint ptkObj, out uint ptkType, out IntPtr ppBlob) + { + throw new NotImplementedException (); + } + + public uint FindTypeRef (uint tkResolutionScope, string szName) + { + throw new NotImplementedException (); + } + + public uint GetMemberProps (uint mb, out uint pClass, StringBuilder szMember, uint cchMember, out uint pchMember, out uint pdwAttr, out IntPtr ppvSigBlob, out uint pcbSigBlob, out uint pulCodeRVA, out uint pdwImplFlags, out uint pdwCPlusTypeFlag, out IntPtr ppValue) + { + throw new NotImplementedException (); + } + + public uint GetFieldProps (uint mb, out uint pClass, StringBuilder szField, uint cchField, out uint pchField, out uint pdwAttr, out IntPtr ppvSigBlob, out uint pcbSigBlob, out uint pdwCPlusTypeFlag, out IntPtr ppValue) + { + throw new NotImplementedException (); + } + + public uint GetPropertyProps (uint prop, out uint pClass, StringBuilder szProperty, uint cchProperty, out uint pchProperty, out uint pdwPropFlags, out IntPtr ppvSig, out uint pbSig, out uint pdwCPlusTypeFlag, out IntPtr ppDefaultValue, out uint pcchDefaultValue, out uint pmdSetter, out uint pmdGetter, uint[] rmdOtherMethod, uint cMax) + { + throw new NotImplementedException (); + } + + public uint GetParamProps (uint tk, out uint pmd, out uint pulSequence, StringBuilder szName, uint cchName, out uint pchName, out uint pdwAttr, out uint pdwCPlusTypeFlag, out IntPtr ppValue) + { + throw new NotImplementedException (); + } + + public uint GetCustomAttributeByName (uint tkObj, string szName, out IntPtr ppData) + { + throw new NotImplementedException (); + } + + public bool IsValidToken (uint tk) + { + throw new NotImplementedException (); + } + + public uint GetNestedClassProps (uint tdNestedClass) + { + TypeDefinition type; + if (!TryGetType (tdNestedClass, out type)) + return 0; + + return type.IsNested ? type.DeclaringType.MetadataToken.ToUInt32 () : 0; + } + + public uint GetNativeCallConvFromSig (IntPtr pvSig, uint cbSig) + { + throw new NotImplementedException (); + } + + public int IsGlobal (uint pd) + { + throw new NotImplementedException (); + } + } +} + +#endif diff --git a/external/cecil-legacy/symbols/pdb/Mono.Cecil.Pdb/PdbHelper.cs b/external/cecil-legacy/symbols/pdb/Mono.Cecil.Pdb/PdbHelper.cs new file mode 100644 index 0000000000..aa63982536 --- /dev/null +++ b/external/cecil-legacy/symbols/pdb/Mono.Cecil.Pdb/PdbHelper.cs @@ -0,0 +1,206 @@ +// +// PdbHelper.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Collections.Generic; +using System.IO; + +using Mono.Cecil.Cil; + +namespace Mono.Cecil.Pdb { + + class PdbHelper { + +#if !READ_ONLY + public static SymWriter CreateWriter (ModuleDefinition module, string pdb) + { + var writer = new SymWriter (); + + if (File.Exists (pdb)) + File.Delete (pdb); + + writer.Initialize (new ModuleMetadata (module), pdb, true); + + return writer; + } +#endif + + public static string GetPdbFileName (string assemblyFileName) + { + return Path.ChangeExtension (assemblyFileName, ".pdb"); + } + } + + public class PdbReaderProvider : ISymbolReaderProvider { + + public ISymbolReader GetSymbolReader (ModuleDefinition module, string fileName) + { + return new PdbReader (File.OpenRead (PdbHelper.GetPdbFileName (fileName))); + } + + public ISymbolReader GetSymbolReader (ModuleDefinition module, Stream symbolStream) + { + return new PdbReader (symbolStream); + } + } + +#if !READ_ONLY + + public class PdbWriterProvider : ISymbolWriterProvider { + + public ISymbolWriter GetSymbolWriter (ModuleDefinition module, string fileName) + { + return new PdbWriter (module, PdbHelper.CreateWriter (module, PdbHelper.GetPdbFileName (fileName))); + } + + public ISymbolWriter GetSymbolWriter (ModuleDefinition module, Stream symbolStream) + { + throw new NotImplementedException (); + } + } + +#endif + + static class GuidMapping { + + static readonly Dictionary guid_language = new Dictionary (); + static readonly Dictionary language_guid = new Dictionary (); + + static GuidMapping () + { + AddMapping (DocumentLanguage.C, new Guid (0x63a08714, 0xfc37, 0x11d2, 0x90, 0x4c, 0x0, 0xc0, 0x4f, 0xa3, 0x02, 0xa1)); + AddMapping (DocumentLanguage.Cpp, new Guid (0x3a12d0b7, 0xc26c, 0x11d0, 0xb4, 0x42, 0x0, 0xa0, 0x24, 0x4a, 0x1d, 0xd2)); + AddMapping (DocumentLanguage.CSharp, new Guid (0x3f5162f8, 0x07c6, 0x11d3, 0x90, 0x53, 0x0, 0xc0, 0x4f, 0xa3, 0x02, 0xa1)); + AddMapping (DocumentLanguage.Basic, new Guid (0x3a12d0b8, 0xc26c, 0x11d0, 0xb4, 0x42, 0x0, 0xa0, 0x24, 0x4a, 0x1d, 0xd2)); + AddMapping (DocumentLanguage.Java, new Guid (0x3a12d0b4, 0xc26c, 0x11d0, 0xb4, 0x42, 0x0, 0xa0, 0x24, 0x4a, 0x1d, 0xd2)); + AddMapping (DocumentLanguage.Cobol, new Guid (0xaf046cd1, 0xd0e1, 0x11d2, 0x97, 0x7c, 0x0, 0xa0, 0xc9, 0xb4, 0xd5, 0xc)); + AddMapping (DocumentLanguage.Pascal, new Guid (0xaf046cd2, 0xd0e1, 0x11d2, 0x97, 0x7c, 0x0, 0xa0, 0xc9, 0xb4, 0xd5, 0xc)); + AddMapping (DocumentLanguage.Cil, new Guid (0xaf046cd3, 0xd0e1, 0x11d2, 0x97, 0x7c, 0x0, 0xa0, 0xc9, 0xb4, 0xd5, 0xc)); + AddMapping (DocumentLanguage.JScript, new Guid (0x3a12d0b6, 0xc26c, 0x11d0, 0xb4, 0x42, 0x0, 0xa0, 0x24, 0x4a, 0x1d, 0xd2)); + AddMapping (DocumentLanguage.Smc, new Guid (0xd9b9f7b, 0x6611, 0x11d3, 0xbd, 0x2a, 0x0, 0x0, 0xf8, 0x8, 0x49, 0xbd)); + AddMapping (DocumentLanguage.MCpp, new Guid (0x4b35fde8, 0x07c6, 0x11d3, 0x90, 0x53, 0x0, 0xc0, 0x4f, 0xa3, 0x02, 0xa1)); + AddMapping (DocumentLanguage.FSharp, new Guid (0xab4f38c9, 0xb6e6, 0x43ba, 0xbe, 0x3b, 0x58, 0x08, 0x0b, 0x2c, 0xcc, 0xe3)); + } + + static void AddMapping (DocumentLanguage language, Guid guid) + { + guid_language.Add (guid, language); + language_guid.Add (language, guid); + } + + static readonly Guid type_text = new Guid (0x5a869d0b, 0x6611, 0x11d3, 0xbd, 0x2a, 0x00, 0x00, 0xf8, 0x08, 0x49, 0xbd); + + public static DocumentType ToType (this Guid guid) + { + if (guid == type_text) + return DocumentType.Text; + + return DocumentType.Other; + } + + public static Guid ToGuid (this DocumentType type) + { + if (type == DocumentType.Text) + return type_text; + + return new Guid (); + } + + static readonly Guid hash_md5 = new Guid (0x406ea660, 0x64cf, 0x4c82, 0xb6, 0xf0, 0x42, 0xd4, 0x81, 0x72, 0xa7, 0x99); + static readonly Guid hash_sha1 = new Guid (0xff1816ec, 0xaa5e, 0x4d10, 0x87, 0xf7, 0x6f, 0x49, 0x63, 0x83, 0x34, 0x60); + + public static DocumentHashAlgorithm ToHashAlgorithm (this Guid guid) + { + if (guid == hash_md5) + return DocumentHashAlgorithm.MD5; + + if (guid == hash_sha1) + return DocumentHashAlgorithm.SHA1; + + return DocumentHashAlgorithm.None; + } + + public static Guid ToGuid (this DocumentHashAlgorithm hash_algo) + { + if (hash_algo == DocumentHashAlgorithm.MD5) + return hash_md5; + + if (hash_algo == DocumentHashAlgorithm.SHA1) + return hash_sha1; + + return new Guid (); + } + + public static DocumentLanguage ToLanguage (this Guid guid) + { + DocumentLanguage language; + if (!guid_language.TryGetValue (guid, out language)) + return DocumentLanguage.Other; + + return language; + } + + public static Guid ToGuid (this DocumentLanguage language) + { + Guid guid; + if (!language_guid.TryGetValue (language, out guid)) + return new Guid (); + + return guid; + } + + static readonly Guid vendor_ms = new Guid (0x994b45c4, 0xe6e9, 0x11d2, 0x90, 0x3f, 0x00, 0xc0, 0x4f, 0xa3, 0x02, 0xa1); + + public static DocumentLanguageVendor ToVendor (this Guid guid) + { + if (guid == vendor_ms) + return DocumentLanguageVendor.Microsoft; + + return DocumentLanguageVendor.Other; + } + + public static Guid ToGuid (this DocumentLanguageVendor vendor) + { + if (vendor == DocumentLanguageVendor.Microsoft) + return vendor_ms; + + return new Guid (); + } + } +} + +#if !NET_3_5 && !NET_4_0 + +namespace System.Runtime.CompilerServices { + + [AttributeUsage (AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Assembly)] + sealed class ExtensionAttribute : Attribute { + } +} + +#endif diff --git a/external/cecil-legacy/symbols/pdb/Mono.Cecil.Pdb/PdbReader.cs b/external/cecil-legacy/symbols/pdb/Mono.Cecil.Pdb/PdbReader.cs new file mode 100644 index 0000000000..6d4fd09844 --- /dev/null +++ b/external/cecil-legacy/symbols/pdb/Mono.Cecil.Pdb/PdbReader.cs @@ -0,0 +1,281 @@ +// +// PdbReader.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Collections.Generic; +using System.IO; + +using Microsoft.Cci.Pdb; + +using Mono.Cecil.Cil; + +namespace Mono.Cecil.Pdb { + + public class PdbReader : ISymbolReader { + + int age; + Guid guid; + + readonly Stream pdb_file; + readonly Dictionary documents = new Dictionary (); + readonly Dictionary functions = new Dictionary (); + + internal PdbReader (Stream file) + { + this.pdb_file = file; + } + + /* + uint Magic = 0x53445352; + Guid Signature; + uint Age; + string FileName; + */ + + public bool ProcessDebugHeader (ImageDebugDirectory directory, byte [] header) + { + if (header.Length < 24) + return false; + + var magic = ReadInt32 (header, 0); + if (magic != 0x53445352) + return false; + + var guid_bytes = new byte [16]; + Buffer.BlockCopy (header, 4, guid_bytes, 0, 16); + + this.guid = new Guid (guid_bytes); + this.age = ReadInt32 (header, 20); + + return PopulateFunctions (); + } + + static int ReadInt32 (byte [] bytes, int start) + { + return (bytes [start] + | (bytes [start + 1] << 8) + | (bytes [start + 2] << 16) + | (bytes [start + 3] << 24)); + } + + bool PopulateFunctions () + { + using (pdb_file) { + Dictionary tokenToSourceMapping; + string sourceServerData; + int age; + Guid guid; + + var funcs = PdbFile.LoadFunctions (pdb_file, out tokenToSourceMapping, out sourceServerData, out age, out guid); + + if (this.guid != guid) + return false; + + foreach (PdbFunction function in funcs) + functions.Add (function.token, function); + } + + return true; + } + + public void Read (MethodBody body, InstructionMapper mapper) + { + var method_token = body.Method.MetadataToken; + + PdbFunction function; + if (!functions.TryGetValue (method_token.ToUInt32 (), out function)) + return; + + ReadSequencePoints (function, mapper); + ReadScopeAndLocals (function.scopes, null, body, mapper); + } + + static void ReadScopeAndLocals (PdbScope [] scopes, Scope parent, MethodBody body, InstructionMapper mapper) + { + foreach (PdbScope scope in scopes) + ReadScopeAndLocals (scope, parent, body, mapper); + + CreateRootScope (body); + } + + static void CreateRootScope (MethodBody body) + { + if (!body.HasVariables) + return; + + var instructions = body.Instructions; + + var root = new Scope (); + root.Start = instructions [0]; + root.End = instructions [instructions.Count - 1]; + + var variables = body.Variables; + for (int i = 0; i < variables.Count; i++) + root.Variables.Add (variables [i]); + + body.Scope = root; + } + + static void ReadScopeAndLocals (PdbScope scope, Scope parent, MethodBody body, InstructionMapper mapper) + { + //Scope s = new Scope (); + //s.Start = GetInstruction (body, instructions, (int) scope.address); + //s.End = GetInstruction (body, instructions, (int) scope.length - 1); + + //if (parent != null) + // parent.Scopes.Add (s); + //else + // body.Scopes.Add (s); + + if (scope == null) + return; + + foreach (PdbSlot slot in scope.slots) { + int index = (int) slot.slot; + if (index < 0 || index >= body.Variables.Count) + continue; + + VariableDefinition variable = body.Variables [index]; + variable.Name = slot.name; + + //s.Variables.Add (variable); + } + + ReadScopeAndLocals (scope.scopes, null /* s */, body, mapper); + } + + void ReadSequencePoints (PdbFunction function, InstructionMapper mapper) + { + if (function.lines == null) + return; + + foreach (PdbLines lines in function.lines) + ReadLines (lines, mapper); + } + + void ReadLines (PdbLines lines, InstructionMapper mapper) + { + var document = GetDocument (lines.file); + + foreach (var line in lines.lines) + ReadLine (line, document, mapper); + } + + static void ReadLine (PdbLine line, Document document, InstructionMapper mapper) + { + var instruction = mapper ((int) line.offset); + if (instruction == null) + return; + + var sequence_point = new SequencePoint (document); + sequence_point.StartLine = (int) line.lineBegin; + sequence_point.StartColumn = (int) line.colBegin; + sequence_point.EndLine = (int) line.lineEnd; + sequence_point.EndColumn = (int) line.colEnd; + + instruction.SequencePoint = sequence_point; + } + + Document GetDocument (PdbSource source) + { + string name = source.name; + Document document; + if (documents.TryGetValue (name, out document)) + return document; + + document = new Document (name) { + Language = source.language.ToLanguage (), + LanguageVendor = source.vendor.ToVendor (), + Type = source.doctype.ToType (), + }; + documents.Add (name, document); + return document; + } + + public void Read (MethodSymbols symbols) + { + PdbFunction function; + if (!functions.TryGetValue (symbols.MethodToken.ToUInt32 (), out function)) + return; + + ReadSequencePoints (function, symbols); + ReadLocals (function.scopes, symbols); + } + + void ReadLocals (PdbScope [] scopes, MethodSymbols symbols) + { + foreach (var scope in scopes) + ReadLocals (scope, symbols); + } + + void ReadLocals (PdbScope scope, MethodSymbols symbols) + { + if (scope == null) + return; + + foreach (var slot in scope.slots) { + int index = (int) slot.slot; + if (index < 0 || index >= symbols.Variables.Count) + continue; + + var variable = symbols.Variables [index]; + variable.Name = slot.name; + } + + ReadLocals (scope.scopes, symbols); + } + + void ReadSequencePoints (PdbFunction function, MethodSymbols symbols) + { + if (function.lines == null) + return; + + foreach (PdbLines lines in function.lines) + ReadLines (lines, symbols); + } + + void ReadLines (PdbLines lines, MethodSymbols symbols) + { + for (int i = 0; i < lines.lines.Length; i++) { + var line = lines.lines [i]; + + symbols.Instructions.Add (new InstructionSymbol ((int) line.offset, new SequencePoint (GetDocument (lines.file)) { + StartLine = (int) line.lineBegin, + StartColumn = (int) line.colBegin, + EndLine = (int) line.lineEnd, + EndColumn = (int) line.colEnd, + })); + } + } + + public void Dispose () + { + pdb_file.Close (); + } + } +} diff --git a/external/cecil-legacy/symbols/pdb/Mono.Cecil.Pdb/PdbWriter.cs b/external/cecil-legacy/symbols/pdb/Mono.Cecil.Pdb/PdbWriter.cs new file mode 100644 index 0000000000..d07b698245 --- /dev/null +++ b/external/cecil-legacy/symbols/pdb/Mono.Cecil.Pdb/PdbWriter.cs @@ -0,0 +1,222 @@ +// +// PdbWriter.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2011 Jb Evain +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Collections.Generic; +using System.Diagnostics.SymbolStore; + +using Mono.Cecil.Cil; +using Mono.Collections.Generic; + +#if !READ_ONLY + +namespace Mono.Cecil.Pdb { + + public class PdbWriter : Cil.ISymbolWriter { + + readonly ModuleDefinition module; + readonly SymWriter writer; + readonly Dictionary documents; + + internal PdbWriter (ModuleDefinition module, SymWriter writer) + { + this.module = module; + this.writer = writer; + this.documents = new Dictionary (); + } + + public bool GetDebugHeader (out ImageDebugDirectory directory, out byte [] header) + { + header = writer.GetDebugInfo (out directory); + return true; + } + + public void Write (MethodBody body) + { + var method_token = body.Method.MetadataToken; + var sym_token = new SymbolToken (method_token.ToInt32 ()); + + var instructions = CollectInstructions (body); + if (instructions.Count == 0) + return; + + var start_offset = 0; + var end_offset = body.CodeSize; + + writer.OpenMethod (sym_token); + writer.OpenScope (start_offset); + + DefineSequencePoints (instructions); + DefineVariables (body, start_offset, end_offset); + + writer.CloseScope (end_offset); + writer.CloseMethod (); + } + + Collection CollectInstructions (MethodBody body) + { + var collection = new Collection (); + var instructions = body.Instructions; + + for (int i = 0; i < instructions.Count; i++) { + var instruction = instructions [i]; + var sequence_point = instruction.SequencePoint; + if (sequence_point == null) + continue; + + GetDocument (sequence_point.Document); + collection.Add (instruction); + } + + return collection; + } + + void DefineVariables (MethodBody body, int start_offset, int end_offset) + { + if (!body.HasVariables) + return; + + var sym_token = new SymbolToken (body.LocalVarToken.ToInt32 ()); + + var variables = body.Variables; + for (int i = 0; i < variables.Count; i++) { + var variable = variables [i]; + CreateLocalVariable (variable, sym_token, start_offset, end_offset); + } + } + + void DefineSequencePoints (Collection instructions) + { + for (int i = 0; i < instructions.Count; i++) { + var instruction = instructions [i]; + var sequence_point = instruction.SequencePoint; + + writer.DefineSequencePoints ( + GetDocument (sequence_point.Document), + new [] { instruction.Offset }, + new [] { sequence_point.StartLine }, + new [] { sequence_point.StartColumn }, + new [] { sequence_point.EndLine }, + new [] { sequence_point.EndColumn }); + } + } + + void CreateLocalVariable (VariableDefinition variable, SymbolToken local_var_token, int start_offset, int end_offset) + { + writer.DefineLocalVariable2 ( + variable.Name, + 0, + local_var_token, + SymAddressKind.ILOffset, + variable.Index, + 0, + 0, + start_offset, + end_offset); + } + + SymDocumentWriter GetDocument (Document document) + { + if (document == null) + return null; + + SymDocumentWriter doc_writer; + if (documents.TryGetValue (document.Url, out doc_writer)) + return doc_writer; + + doc_writer = writer.DefineDocument ( + document.Url, + document.Language.ToGuid (), + document.LanguageVendor.ToGuid (), + document.Type.ToGuid ()); + + documents [document.Url] = doc_writer; + return doc_writer; + } + + public void Write (MethodSymbols symbols) + { + var sym_token = new SymbolToken (symbols.MethodToken.ToInt32 ()); + + var start_offset = 0; + var end_offset = symbols.CodeSize; + + writer.OpenMethod (sym_token); + writer.OpenScope (start_offset); + + DefineSequencePoints (symbols); + DefineVariables (symbols, start_offset, end_offset); + + writer.CloseScope (end_offset); + writer.CloseMethod (); + } + + void DefineSequencePoints (MethodSymbols symbols) + { + var instructions = symbols.instructions; + + for (int i = 0; i < instructions.Count; i++) { + var instruction = instructions [i]; + var sequence_point = instruction.SequencePoint; + + writer.DefineSequencePoints ( + GetDocument (sequence_point.Document), + new [] { instruction.Offset }, + new [] { sequence_point.StartLine }, + new [] { sequence_point.StartColumn }, + new [] { sequence_point.EndLine }, + new [] { sequence_point.EndColumn }); + } + } + + void DefineVariables (MethodSymbols symbols, int start_offset, int end_offset) + { + if (!symbols.HasVariables) + return; + + var sym_token = new SymbolToken (symbols.LocalVarToken.ToInt32 ()); + + var variables = symbols.Variables; + for (int i = 0; i < variables.Count; i++) { + var variable = variables [i]; + CreateLocalVariable (variable, sym_token, start_offset, end_offset); + } + } + + public void Dispose () + { + var entry_point = module.EntryPoint; + if (entry_point != null) + writer.SetUserEntryPoint (new SymbolToken (entry_point.MetadataToken.ToInt32 ())); + + writer.Close (); + } + } +} + +#endif diff --git a/external/cecil-legacy/symbols/pdb/Mono.Cecil.Pdb/SymDocumentWriter.cs b/external/cecil-legacy/symbols/pdb/Mono.Cecil.Pdb/SymDocumentWriter.cs new file mode 100644 index 0000000000..34918dc63e --- /dev/null +++ b/external/cecil-legacy/symbols/pdb/Mono.Cecil.Pdb/SymDocumentWriter.cs @@ -0,0 +1,51 @@ +// +// SymDocumentWriter.cs +// +// Author: +// Juerg Billeter (j@bitron.ch) +// +// (C) 2008 Juerg Billeter +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +#if !READ_ONLY + +namespace Mono.Cecil.Pdb +{ + internal class SymDocumentWriter + { + readonly ISymUnmanagedDocumentWriter m_unmanagedDocumentWriter; + + public SymDocumentWriter (ISymUnmanagedDocumentWriter unmanagedDocumentWriter) + { + m_unmanagedDocumentWriter = unmanagedDocumentWriter; + } + + public ISymUnmanagedDocumentWriter GetUnmanaged () + { + return m_unmanagedDocumentWriter; + } + } +} + +#endif diff --git a/external/cecil-legacy/symbols/pdb/Mono.Cecil.Pdb/SymWriter.cs b/external/cecil-legacy/symbols/pdb/Mono.Cecil.Pdb/SymWriter.cs new file mode 100644 index 0000000000..678942a341 --- /dev/null +++ b/external/cecil-legacy/symbols/pdb/Mono.Cecil.Pdb/SymWriter.cs @@ -0,0 +1,170 @@ +// +// SymWriter.cs +// +// Author: +// Juerg Billeter (j@bitron.ch) +// +// (C) 2008 Juerg Billeter +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Collections.Generic; +using System.Diagnostics.SymbolStore; +using System.Runtime.InteropServices; + +using Mono.Cecil.Cil; +using Mono.Collections.Generic; + +#if !READ_ONLY + +namespace Mono.Cecil.Pdb +{ + internal class SymWriter + { + [DllImport("ole32.dll")] + static extern int CoCreateInstance ( + [In] ref Guid rclsid, + [In, MarshalAs (UnmanagedType.IUnknown)] object pUnkOuter, + [In] uint dwClsContext, + [In] ref Guid riid, + [Out, MarshalAs (UnmanagedType.Interface)] out object ppv); + + static Guid s_symUnmangedWriterIID = new Guid("0b97726e-9e6d-4f05-9a26-424022093caa"); + static Guid s_CorSymWriter_SxS_ClassID = new Guid ("108296c1-281e-11d3-bd22-0000f80849bd"); + + readonly ISymUnmanagedWriter2 m_writer; + readonly Collection documents; + + public SymWriter () + { + object objWriter; + CoCreateInstance (ref s_CorSymWriter_SxS_ClassID, null, 1, ref s_symUnmangedWriterIID, out objWriter); + + m_writer = (ISymUnmanagedWriter2) objWriter; + documents = new Collection (); + } + + public byte[] GetDebugInfo (out ImageDebugDirectory idd) + { + int size; + + // get size of debug info + m_writer.GetDebugInfo (out idd, 0, out size, null); + + byte[] debug_info = new byte[size]; + m_writer.GetDebugInfo (out idd, size, out size, debug_info); + + return debug_info; + } + + public void DefineLocalVariable2 ( + string name, + FieldAttributes attributes, + SymbolToken sigToken, + SymAddressKind addrKind, + int addr1, + int addr2, + int addr3, + int startOffset, + int endOffset) + { + m_writer.DefineLocalVariable2 (name, (int)attributes, sigToken, (int)addrKind, addr1, addr2, addr3, startOffset, endOffset); + } + + public void Close () + { + m_writer.Close (); + Marshal.ReleaseComObject (m_writer); + + foreach (var document in documents) + Marshal.ReleaseComObject (document); + } + + public void CloseMethod () + { + m_writer.CloseMethod (); + } + + public void CloseNamespace () + { + m_writer.CloseNamespace (); + } + + public void CloseScope (int endOffset) + { + m_writer.CloseScope (endOffset); + } + + public SymDocumentWriter DefineDocument (string url, Guid language, Guid languageVendor, Guid documentType) + { + ISymUnmanagedDocumentWriter unmanagedDocumentWriter; + m_writer.DefineDocument (url, ref language, ref languageVendor, ref documentType, out unmanagedDocumentWriter); + + documents.Add (unmanagedDocumentWriter); + return new SymDocumentWriter (unmanagedDocumentWriter); + } + + public void DefineParameter (string name, ParameterAttributes attributes, int sequence, SymAddressKind addrKind, int addr1, int addr2, int addr3) + { + throw new Exception ("The method or operation is not implemented."); + } + + public void DefineSequencePoints (SymDocumentWriter document, int[] offsets, int[] lines, int[] columns, int[] endLines, int[] endColumns) + { + m_writer.DefineSequencePoints (document.GetUnmanaged(), offsets.Length, offsets, lines, columns, endLines, endColumns); + } + + public void Initialize (object emitter, string filename, bool fFullBuild) + { + m_writer.Initialize (emitter, filename, null, fFullBuild); + } + + public void SetUserEntryPoint (SymbolToken method) + { + m_writer.SetUserEntryPoint (method); + } + + public void OpenMethod (SymbolToken method) + { + m_writer.OpenMethod (method); + } + + public void OpenNamespace (string name) + { + m_writer.OpenNamespace (name); + } + + public int OpenScope (int startOffset) + { + int result; + m_writer.OpenScope (startOffset, out result); + return result; + } + + public void UsingNamespace (string fullName) + { + m_writer.UsingNamespace (fullName); + } + } +} + +#endif diff --git a/external/cecil/symbols/pdb/Test/.gitignore b/external/cecil-legacy/symbols/pdb/Test/.gitignore similarity index 100% rename from external/cecil/symbols/pdb/Test/.gitignore rename to external/cecil-legacy/symbols/pdb/Test/.gitignore diff --git a/external/cecil-legacy/symbols/pdb/Test/Mono.Cecil.Pdb.Tests.csproj b/external/cecil-legacy/symbols/pdb/Test/Mono.Cecil.Pdb.Tests.csproj new file mode 100644 index 0000000000..657e351ba8 --- /dev/null +++ b/external/cecil-legacy/symbols/pdb/Test/Mono.Cecil.Pdb.Tests.csproj @@ -0,0 +1,124 @@ + + + + net_4_0_Debug + AnyCPU + 9.0.30729 + 2.0 + {29300103-CB76-4A1D-B6FD-FFD91C1EC8AA} + Library + Properties + Mono.Cecil.Pdb.Tests + Mono.Cecil.Pdb.Tests + 512 + + + true + full + false + bin\net_2_0_Debug\ + DEBUG;TRACE + prompt + 4 + v2.0 + + + pdbonly + true + bin\net_2_0_Release\ + TRACE + prompt + 4 + v2.0 + + + true + full + false + bin\net_3_5_Debug\ + DEBUG;TRACE;NET_3_5 + prompt + 4 + v3.5 + + + pdbonly + true + bin\net_3_5_Release\ + TRACE;NET_3_5 + prompt + 4 + v3.5 + + + true + full + false + bin\net_4_0_Debug\ + DEBUG;TRACE;NET_3_5;NET_4_0 + prompt + 4 + v4.0 + + + pdbonly + true + bin\net_4_0_Release\ + TRACE;NET_3_5;NET_4_0 + prompt + 4 + v4.0 + + + + + + + {D68133BD-1E63-496E-9EDE-4FBDBF77B486} + Mono.Cecil + + + {A47B1F49-A81A-43E8-BE6B-DD28AF2C4055} + Mono.Cecil.Tests + + + {63E6915C-7EA4-4D76-AB28-0D7191EEA626} + Mono.Cecil.Pdb + + + + + + + + + + + + + + + + + + False + ..\..\..\Test\libs\nunit-2.6.2\nunit.core.dll + + + False + ..\..\..\Test\libs\nunit-2.6.2\nunit.core.interfaces.dll + + + False + ..\..\..\Test\libs\nunit-2.6.2\nunit.framework.dll + + + + + \ No newline at end of file diff --git a/external/cecil/symbols/pdb/Test/Mono.Cecil.Tests/Addin.cs b/external/cecil-legacy/symbols/pdb/Test/Mono.Cecil.Tests/Addin.cs similarity index 100% rename from external/cecil/symbols/pdb/Test/Mono.Cecil.Tests/Addin.cs rename to external/cecil-legacy/symbols/pdb/Test/Mono.Cecil.Tests/Addin.cs diff --git a/external/cecil/symbols/pdb/Test/Mono.Cecil.Tests/Linq.cs b/external/cecil-legacy/symbols/pdb/Test/Mono.Cecil.Tests/Linq.cs similarity index 100% rename from external/cecil/symbols/pdb/Test/Mono.Cecil.Tests/Linq.cs rename to external/cecil-legacy/symbols/pdb/Test/Mono.Cecil.Tests/Linq.cs diff --git a/external/cecil-legacy/symbols/pdb/Test/Mono.Cecil.Tests/PdbTests.cs b/external/cecil-legacy/symbols/pdb/Test/Mono.Cecil.Tests/PdbTests.cs new file mode 100644 index 0000000000..d084dcd44f --- /dev/null +++ b/external/cecil-legacy/symbols/pdb/Test/Mono.Cecil.Tests/PdbTests.cs @@ -0,0 +1,175 @@ + +using System.IO; +using System.Linq; + +using Mono.Cecil.Cil; +using Mono.Cecil.Pdb; + +using NUnit.Framework; + +namespace Mono.Cecil.Tests { + + [TestFixture] + public class PdbTests : BaseTestFixture { + + [TestModule ("test.exe", SymbolReaderProvider = typeof (PdbReaderProvider), SymbolWriterProvider = typeof (PdbWriterProvider))] + public void Main (ModuleDefinition module) + { + var type = module.GetType ("Program"); + var main = type.GetMethod ("Main"); + + AssertCode (@" + .locals init (System.Int32 i, System.Int32 CS$1$0000, System.Boolean CS$4$0001) + .line 6,6:2,3 'c:\sources\cecil\symbols\Mono.Cecil.Pdb\Test\Resources\assemblies\test.cs' + IL_0000: nop + .line 7,7:8,18 'c:\sources\cecil\symbols\Mono.Cecil.Pdb\Test\Resources\assemblies\test.cs' + IL_0001: ldc.i4.0 + IL_0002: stloc.0 + .line 16707566,16707566:0,0 'c:\sources\cecil\symbols\Mono.Cecil.Pdb\Test\Resources\assemblies\test.cs' + IL_0003: br.s IL_0012 + .line 8,8:4,21 'c:\sources\cecil\symbols\Mono.Cecil.Pdb\Test\Resources\assemblies\test.cs' + IL_0005: ldarg.0 + IL_0006: ldloc.0 + IL_0007: ldelem.ref + IL_0008: call System.Void Program::Print(System.String) + IL_000d: nop + .line 7,7:36,39 'c:\sources\cecil\symbols\Mono.Cecil.Pdb\Test\Resources\assemblies\test.cs' + IL_000e: ldloc.0 + IL_000f: ldc.i4.1 + IL_0010: add + IL_0011: stloc.0 + .line 7,7:19,34 'c:\sources\cecil\symbols\Mono.Cecil.Pdb\Test\Resources\assemblies\test.cs' + IL_0012: ldloc.0 + IL_0013: ldarg.0 + IL_0014: ldlen + IL_0015: conv.i4 + IL_0016: clt + IL_0018: stloc.2 + .line 16707566,16707566:0,0 'c:\sources\cecil\symbols\Mono.Cecil.Pdb\Test\Resources\assemblies\test.cs' + IL_0019: ldloc.2 + IL_001a: brtrue.s IL_0005 + .line 10,10:3,12 'c:\sources\cecil\symbols\Mono.Cecil.Pdb\Test\Resources\assemblies\test.cs' + IL_001c: ldc.i4.0 + IL_001d: stloc.1 + IL_001e: br.s IL_0020 + .line 11,11:2,3 'c:\sources\cecil\symbols\Mono.Cecil.Pdb\Test\Resources\assemblies\test.cs' + IL_0020: ldloc.1 + IL_0021: ret +", main); + } + + [TestModule ("test.exe", SymbolReaderProvider = typeof (PdbReaderProvider), SymbolWriterProvider = typeof (PdbWriterProvider))] + public void Document (ModuleDefinition module) + { + var type = module.GetType ("Program"); + var method = type.GetMethod ("Main"); + + var sequence_point = method.Body.Instructions.Where (i => i.SequencePoint != null).First ().SequencePoint; + var document = sequence_point.Document; + + Assert.IsNotNull (document); + + Assert.AreEqual (@"c:\sources\cecil\symbols\Mono.Cecil.Pdb\Test\Resources\assemblies\test.cs", document.Url); + Assert.AreEqual (DocumentType.Text, document.Type); + Assert.AreEqual (DocumentHashAlgorithm.None, document.HashAlgorithm); + Assert.AreEqual (DocumentLanguage.CSharp, document.Language); + Assert.AreEqual (DocumentLanguageVendor.Microsoft, document.LanguageVendor); + } + + [TestModule ("VBConsApp.exe", SymbolReaderProvider = typeof (PdbReaderProvider), SymbolWriterProvider = typeof (PdbWriterProvider))] + public void BasicDocument (ModuleDefinition module) + { + var type = module.GetType ("VBConsApp.Program"); + var method = type.GetMethod ("Main"); + + var sequence_point = method.Body.Instructions.Where (i => i.SequencePoint != null).First ().SequencePoint; + var document = sequence_point.Document; + + Assert.IsNotNull (document); + + Assert.AreEqual (@"c:\tmp\VBConsApp\Program.vb", document.Url); + Assert.AreEqual (DocumentType.Text, document.Type); + Assert.AreEqual (DocumentHashAlgorithm.None, document.HashAlgorithm); + Assert.AreEqual (DocumentLanguage.Basic, document.Language); + Assert.AreEqual (DocumentLanguageVendor.Microsoft, document.LanguageVendor); + } + + [TestModule ("fsapp.exe", SymbolReaderProvider = typeof (PdbReaderProvider), SymbolWriterProvider = typeof (PdbWriterProvider))] + public void FSharpDocument (ModuleDefinition module) + { + var type = module.GetType ("Program"); + var method = type.GetMethod ("fact"); + + var sequence_point = method.Body.Instructions.Where (i => i.SequencePoint != null).First ().SequencePoint; + var document = sequence_point.Document; + + Assert.IsNotNull (document); + + Assert.AreEqual (@"c:\tmp\fsapp\Program.fs", document.Url); + Assert.AreEqual (DocumentType.Text, document.Type); + Assert.AreEqual (DocumentHashAlgorithm.None, document.HashAlgorithm); + Assert.AreEqual (DocumentLanguage.FSharp, document.Language); + Assert.AreEqual (DocumentLanguageVendor.Microsoft, document.LanguageVendor); + } + + [Test] + public void CreateMethodFromScratch () + { + var module = ModuleDefinition.CreateModule ("Pan", ModuleKind.Dll); + var type = new TypeDefinition ("Pin", "Pon", TypeAttributes.Public | TypeAttributes.Abstract | TypeAttributes.Sealed, module.Import (typeof (object))); + module.Types.Add (type); + + var method = new MethodDefinition ("Pang", MethodAttributes.Public | MethodAttributes.Static, module.Import (typeof (string))); + type.Methods.Add (method); + + var body = method.Body; + + body.InitLocals = true; + + var il = body.GetILProcessor (); + var temp = new VariableDefinition ("temp", module.Import (typeof (string))); + body.Variables.Add (temp); + + il.Emit (OpCodes.Nop); + il.Emit (OpCodes.Ldstr, "hello"); + il.Emit (OpCodes.Stloc, temp); + il.Emit (OpCodes.Ldloc, temp); + il.Emit (OpCodes.Ret); + + body.Instructions [0].SequencePoint = new SequencePoint (new Document (@"C:\test.cs")) { + StartLine = 0, + StartColumn = 0, + EndLine = 0, + EndColumn = 4, + }; + + var file = Path.Combine (Path.GetTempPath (), "Pan.dll"); + module.Write (file, new WriterParameters { + SymbolWriterProvider = new PdbWriterProvider (), + }); + + module = ModuleDefinition.ReadModule (file, new ReaderParameters { + SymbolReaderProvider = new PdbReaderProvider (), + }); + + method = module.GetType ("Pin.Pon").GetMethod ("Pang"); + + Assert.AreEqual ("temp", method.Body.Variables [0].Name); + } + + static void AssertCode (string expected, MethodDefinition method) + { + Assert.IsTrue (method.HasBody); + Assert.IsNotNull (method.Body); + + System.Console.WriteLine (Formatter.FormatMethodBody (method)); + + Assert.AreEqual (Normalize (expected), Normalize (Formatter.FormatMethodBody (method))); + } + + static string Normalize (string str) + { + return str.Trim ().Replace ("\r\n", "\n"); + } + } +} diff --git a/external/cecil-legacy/symbols/pdb/Test/Resources/assemblies/VBConsApp.pdb b/external/cecil-legacy/symbols/pdb/Test/Resources/assemblies/VBConsApp.pdb new file mode 100755 index 0000000000..2625666b40 Binary files /dev/null and b/external/cecil-legacy/symbols/pdb/Test/Resources/assemblies/VBConsApp.pdb differ diff --git a/external/cecil-legacy/symbols/pdb/Test/Resources/assemblies/fsapp.pdb b/external/cecil-legacy/symbols/pdb/Test/Resources/assemblies/fsapp.pdb new file mode 100755 index 0000000000..3743d24be8 Binary files /dev/null and b/external/cecil-legacy/symbols/pdb/Test/Resources/assemblies/fsapp.pdb differ diff --git a/external/cecil-legacy/symbols/pdb/Test/Resources/assemblies/test.pdb b/external/cecil-legacy/symbols/pdb/Test/Resources/assemblies/test.pdb new file mode 100644 index 0000000000..1bad2a11c8 Binary files /dev/null and b/external/cecil-legacy/symbols/pdb/Test/Resources/assemblies/test.pdb differ diff --git a/external/cecil/.gitattributes b/external/cecil/.gitattributes index 7d07d70cc8..c87ac422f3 100644 --- a/external/cecil/.gitattributes +++ b/external/cecil/.gitattributes @@ -1 +1,8 @@ -* text=lf +* text=auto + +.md text +.cs text + +.sln text=crlf +.*proj text=crlf +.settings text=crlf diff --git a/external/cecil/.gitignore b/external/cecil/.gitignore index 8dcb32b7f6..08c8509f51 100644 --- a/external/cecil/.gitignore +++ b/external/cecil/.gitignore @@ -1,6 +1,7 @@ bin obj *.suo +*.iml *.user *.pidb *.userprefs @@ -8,3 +9,7 @@ obj *.nupkg **/test-results/* *Resharper* +Mono.Cecil.sln.ide* +TestResults +project.lock.json +.vs/ diff --git a/external/cecil/.travis.yml b/external/cecil/.travis.yml new file mode 100644 index 0000000000..0f102833a3 --- /dev/null +++ b/external/cecil/.travis.yml @@ -0,0 +1,8 @@ +language: csharp +solution: Mono.Cecil.sln +install: + - nuget restore Mono.Cecil.sln + - nuget install NUnit.Runners -Version 2.6.4 -OutputDirectory testrunner +script: + - xbuild /p:Configuration=net_4_0_Debug Mono.Cecil.sln + - mono ./testrunner/NUnit.Runners.2.6.4/tools/nunit-console.exe Mono.Cecil.nunit diff --git a/external/cecil/LICENSE.txt b/external/cecil/LICENSE.txt new file mode 100644 index 0000000000..afd0ae6818 --- /dev/null +++ b/external/cecil/LICENSE.txt @@ -0,0 +1,21 @@ +Copyright (c) 2008 - 2015 Jb Evain +Copyright (c) 2008 - 2011 Novell, Inc. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/external/cecil/Mono.Cecil.Cil/Code.cs b/external/cecil/Mono.Cecil.Cil/Code.cs index fa88b63d67..cd929fcc34 100644 --- a/external/cecil/Mono.Cecil.Cil/Code.cs +++ b/external/cecil/Mono.Cecil.Cil/Code.cs @@ -1,29 +1,11 @@ // -// Code.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // namespace Mono.Cecil.Cil { diff --git a/external/cecil/Mono.Cecil.Cil/CodeReader.cs b/external/cecil/Mono.Cecil.Cil/CodeReader.cs index 12ca5a23b1..56dae8dbb3 100644 --- a/external/cecil/Mono.Cecil.Cil/CodeReader.cs +++ b/external/cecil/Mono.Cecil.Cil/CodeReader.cs @@ -1,29 +1,11 @@ // -// CodeReader.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; @@ -35,58 +17,53 @@ using RVA = System.UInt32; namespace Mono.Cecil.Cil { - sealed class CodeReader : ByteBuffer { + sealed class CodeReader : BinaryStreamReader { readonly internal MetadataReader reader; int start; - Section code_section; MethodDefinition method; MethodBody body; int Offset { - get { return base.position - start; } + get { return Position - start; } } - public CodeReader (Section section, MetadataReader reader) - : base (section.Data) + public CodeReader (MetadataReader reader) + : base (reader.image.Stream.value) { - this.code_section = section; this.reader = reader; } + public int MoveTo (MethodDefinition method) + { + this.method = method; + this.reader.context = method; + var position = this.Position; + this.Position = (int) reader.image.ResolveVirtualAddress ((uint) method.RVA); + return position; + } + + void MoveBackTo (int position) + { + this.reader.context = null; + this.Position = position; + } + public MethodBody ReadMethodBody (MethodDefinition method) { - this.method = method; + var position = MoveTo (method); this.body = new MethodBody (method); - reader.context = method; - ReadMethodBody (); + MoveBackTo (position); return this.body; } - public void MoveTo (int rva) - { - if (!IsInSection (rva)) { - code_section = reader.image.GetSectionAtVirtualAddress ((uint) rva); - Reset (code_section.Data); - } - - base.position = rva - (int) code_section.VirtualAddress; - } - - bool IsInSection (int rva) - { - return code_section.VirtualAddress <= rva && rva < code_section.VirtualAddress + code_section.SizeOfRawData; - } - void ReadMethodBody () { - MoveTo (method.RVA); - var flags = ReadByte (); switch (flags & 0x3) { case 0x2: // tiny @@ -95,7 +72,7 @@ namespace Mono.Cecil.Cil { ReadCode (); break; case 0x3: // fat - base.position--; + Advance (-1); ReadFatMethod (); break; default: @@ -104,12 +81,102 @@ namespace Mono.Cecil.Cil { var symbol_reader = reader.module.symbol_reader; - if (symbol_reader != null) { - var instructions = body.Instructions; - symbol_reader.Read (body, offset => GetInstruction (instructions, offset)); + if (symbol_reader != null && method.debug_info == null) + method.debug_info = symbol_reader.Read (method); + + if (method.debug_info != null) + ReadDebugInfo (); + } + + void ReadDebugInfo () + { + if (method.debug_info.sequence_points != null) + ReadSequencePoints (); + + if (method.debug_info.scope != null) + ReadScope (method.debug_info.scope); + + if (method.custom_infos != null) + ReadCustomDebugInformations (method); + } + + void ReadCustomDebugInformations (MethodDefinition method) + { + var custom_infos = method.custom_infos; + + for (int i = 0; i < custom_infos.Count; i++) { + var state_machine_scope = custom_infos [i] as StateMachineScopeDebugInformation; + if (state_machine_scope != null) + ReadStateMachineScope (state_machine_scope); + + var async_method = custom_infos [i] as AsyncMethodBodyDebugInformation; + if (async_method != null) + ReadAsyncMethodBody (async_method); } } + void ReadAsyncMethodBody (AsyncMethodBodyDebugInformation async_method) + { + if (async_method.catch_handler.Offset > -1) + async_method.catch_handler = new InstructionOffset (GetInstruction (async_method.catch_handler.Offset)); + + if (!async_method.yields.IsNullOrEmpty ()) + for (int i = 0; i < async_method.yields.Count; i++) + async_method.yields [i] = new InstructionOffset (GetInstruction (async_method.yields [i].Offset)); + + if (!async_method.resumes.IsNullOrEmpty ()) + for (int i = 0; i < async_method.resumes.Count; i++) + async_method.resumes [i] = new InstructionOffset (GetInstruction (async_method.resumes [i].Offset)); + } + + void ReadStateMachineScope (StateMachineScopeDebugInformation state_machine_scope) + { + state_machine_scope.start = new InstructionOffset (GetInstruction (state_machine_scope.start.Offset)); + + var end_instruction = GetInstruction (state_machine_scope.end.Offset); + state_machine_scope.end = end_instruction == null + ? new InstructionOffset () + : new InstructionOffset (end_instruction); + } + + void ReadSequencePoints () + { + var symbol = method.debug_info; + + for (int i = 0; i < symbol.sequence_points.Count; i++) { + var sequence_point = symbol.sequence_points [i]; + var instruction = GetInstruction (sequence_point.Offset); + if (instruction != null) + sequence_point.offset = new InstructionOffset (instruction); + } + } + + void ReadScopes (Collection scopes) + { + for (int i = 0; i < scopes.Count; i++) + ReadScope (scopes [i]); + } + + void ReadScope (ScopeDebugInformation scope) + { + scope.Start = new InstructionOffset (GetInstruction (scope.Start.Offset)); + + var end_instruction = GetInstruction (scope.End.Offset); + scope.End = end_instruction == null + ? new InstructionOffset () + : new InstructionOffset (end_instruction); + + if (!scope.variables.IsNullOrEmpty ()) { + for (int i = 0; i < scope.variables.Count; i++) { + var variable = scope.variables [i]; + variable.index = new VariableIndex (GetVariable (variable.Index)); + } + } + + if (!scope.scopes.IsNullOrEmpty ()) + ReadScopes (scope.scopes); + } + void ReadFatMethod () { var flags = ReadUInt16 (); @@ -138,17 +205,17 @@ namespace Mono.Cecil.Cil { void ReadCode () { - start = position; + start = Position; var code_size = body.code_size; - if (code_size < 0 || buffer.Length <= (uint) (code_size + position)) + if (code_size < 0 || Length <= (uint) (code_size + Position)) code_size = 0; var end = start + code_size; - var instructions = body.instructions = new InstructionCollection ((code_size + 1) / 2); + var instructions = body.instructions = new InstructionCollection (method, (code_size + 1) / 2); - while (position < end) { - var offset = base.position - start; + while (Position < end) { + var offset = Position - start; var opcode = ReadOpCode (); var current = new Instruction (offset, opcode); @@ -248,7 +315,9 @@ namespace Mono.Cecil.Cil { switch (instruction.opcode.OperandType) { case OperandType.ShortInlineBrTarget: case OperandType.InlineBrTarget: - instruction.operand = GetInstruction ((int) instruction.operand); + var targetInstruction = GetInstruction ((int) instruction.operand); + if (targetInstruction != null) + instruction.operand = targetInstruction; break; case OperandType.InlineSwitch: var offsets = (int []) instruction.operand; @@ -323,7 +392,7 @@ namespace Mono.Cecil.Cil { void ReadFatSection () { - position--; + Advance (-1); var count = (ReadInt32 () >> 8) / 24; ReadExceptionHandlers ( @@ -369,6 +438,7 @@ namespace Mono.Cecil.Cil { void Align (int align) { align--; + var position = Position; Advance (((position + align) & ~align) - position); } @@ -379,78 +449,57 @@ namespace Mono.Cecil.Cil { #if !READ_ONLY - public ByteBuffer PatchRawMethodBody (MethodDefinition method, CodeWriter writer, out MethodSymbols symbols) + public ByteBuffer PatchRawMethodBody (MethodDefinition method, CodeWriter writer, out int code_size, out MetadataToken local_var_token) { + var position = MoveTo (method); + var buffer = new ByteBuffer (); - symbols = new MethodSymbols (method.Name); - - this.method = method; - reader.context = method; - - MoveTo (method.RVA); var flags = ReadByte (); - MetadataToken local_var_token; - switch (flags & 0x3) { case 0x2: // tiny buffer.WriteByte (flags); local_var_token = MetadataToken.Zero; - symbols.code_size = flags >> 2; - PatchRawCode (buffer, symbols.code_size, writer); + code_size = flags >> 2; + PatchRawCode (buffer, code_size, writer); break; case 0x3: // fat - base.position--; - - PatchRawFatMethod (buffer, symbols, writer, out local_var_token); + Advance (-1); + PatchRawFatMethod (buffer, writer, out code_size, out local_var_token); break; default: throw new NotSupportedException (); } - var symbol_reader = reader.module.symbol_reader; - if (symbol_reader != null && writer.metadata.write_symbols) { - symbols.method_token = GetOriginalToken (writer.metadata, method); - symbols.local_var_token = local_var_token; - symbol_reader.Read (symbols); - } + MoveBackTo (position); return buffer; } - void PatchRawFatMethod (ByteBuffer buffer, MethodSymbols symbols, CodeWriter writer, out MetadataToken local_var_token) + void PatchRawFatMethod (ByteBuffer buffer, CodeWriter writer, out int code_size, out MetadataToken local_var_token) { var flags = ReadUInt16 (); buffer.WriteUInt16 (flags); buffer.WriteUInt16 (ReadUInt16 ()); - symbols.code_size = ReadInt32 (); - buffer.WriteInt32 (symbols.code_size); + code_size = ReadInt32 (); + buffer.WriteInt32 (code_size); local_var_token = ReadToken (); if (local_var_token.RID > 0) { - var variables = symbols.variables = ReadVariables (local_var_token); + var variables = ReadVariables (local_var_token); buffer.WriteUInt32 (variables != null - ? writer.GetStandAloneSignature (symbols.variables).ToUInt32 () + ? writer.GetStandAloneSignature (variables).ToUInt32 () : 0); } else buffer.WriteUInt32 (0); - PatchRawCode (buffer, symbols.code_size, writer); + PatchRawCode (buffer, code_size, writer); if ((flags & 0x8) != 0) PatchRawSection (buffer, writer.metadata); } - static MetadataToken GetOriginalToken (MetadataBuilder metadata, MethodDefinition method) - { - MetadataToken original; - if (metadata.TryGetOriginalMethodToken (method.token, out original)) - return original; - - return MetadataToken.Zero; - } - void PatchRawCode (ByteBuffer buffer, int code_size, CodeWriter writer) { var metadata = writer.metadata; @@ -519,9 +568,9 @@ namespace Mono.Cecil.Cil { void PatchRawSection (ByteBuffer buffer, MetadataBuilder metadata) { - var position = base.position; + var position = Position; Align (4); - buffer.WriteBytes (base.position - position); + buffer.WriteBytes (Position - position); const byte fat_format = 0x40; const byte more_sects = 0x80; @@ -552,7 +601,7 @@ namespace Mono.Cecil.Cil { void PatchRawFatSection (ByteBuffer buffer, MetadataBuilder metadata) { - position--; + Advance (-1); var length = ReadInt32 (); buffer.WriteInt32 (length); diff --git a/external/cecil/Mono.Cecil.Cil/CodeWriter.cs b/external/cecil/Mono.Cecil.Cil/CodeWriter.cs index ac093cae46..4f711a55ea 100644 --- a/external/cecil/Mono.Cecil.Cil/CodeWriter.cs +++ b/external/cecil/Mono.Cecil.Cil/CodeWriter.cs @@ -1,29 +1,11 @@ // -// CodeWriter.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; @@ -93,31 +75,23 @@ namespace Mono.Cecil.Cil { void WriteUnresolvedMethodBody (MethodDefinition method) { - var code_reader = metadata.module.Read (method, (_, reader) => reader.code); + var code_reader = metadata.module.reader.code; - MethodSymbols symbols; - var buffer = code_reader.PatchRawMethodBody (method, this, out symbols); + int code_size; + MetadataToken local_var_token; + var buffer = code_reader.PatchRawMethodBody (method, this, out code_size, out local_var_token); WriteBytes (buffer); - if (symbols.instructions.IsNullOrEmpty ()) + if (method.debug_info == null) return; - symbols.method_token = method.token; - symbols.local_var_token = GetLocalVarToken (buffer, symbols); - var symbol_writer = metadata.symbol_writer; - if (symbol_writer != null) - symbol_writer.Write (symbols); - } - - static MetadataToken GetLocalVarToken (ByteBuffer buffer, MethodSymbols symbols) - { - if (symbols.variables.IsNullOrEmpty ()) - return MetadataToken.Zero; - - buffer.position = 8; - return new MetadataToken (buffer.ReadUInt32 ()); + if (symbol_writer != null) { + method.debug_info.code_size = code_size; + method.debug_info.local_var_token = local_var_token; + symbol_writer.Write (method.debug_info); + } } void WriteResolvedMethodBody (MethodDefinition method) @@ -135,8 +109,11 @@ namespace Mono.Cecil.Cil { WriteExceptionHandlers (); var symbol_writer = metadata.symbol_writer; - if (symbol_writer != null) - symbol_writer.Write (body); + if (symbol_writer != null && method.debug_info != null) { + method.debug_info.code_size = body.CodeSize; + method.debug_info.local_var_token = body.local_var_token; + symbol_writer.Write (method.debug_info); + } } void WriteFatHeader () @@ -202,13 +179,11 @@ namespace Mono.Cecil.Cil { break; } case OperandType.ShortInlineBrTarget: { - var target = (Instruction) operand; - WriteSByte ((sbyte) (GetTargetOffset (target) - (instruction.Offset + opcode.Size + 1))); + WriteSByte ((sbyte) (GetTargetOffset (operand) - (instruction.Offset + opcode.Size + 1))); break; } case OperandType.InlineBrTarget: { - var target = (Instruction) operand; - WriteInt32 (GetTargetOffset (target) - (instruction.Offset + opcode.Size + 4)); + WriteInt32 (GetTargetOffset (operand) - (instruction.Offset + opcode.Size + 4)); break; } case OperandType.ShortInlineVar: @@ -261,8 +236,12 @@ namespace Mono.Cecil.Cil { } } - int GetTargetOffset (Instruction instruction) + int GetTargetOffset (object o) { + if (o is int) + return (int) o; + + Instruction instruction = o as Instruction; if (instruction == null) { var last = body.instructions [body.instructions.size - 1]; return last.offset + last.GetSize (); diff --git a/external/cecil/Mono.Cecil.Cil/Document.cs b/external/cecil/Mono.Cecil.Cil/Document.cs index 1dbdc44744..2c2d21e1c2 100644 --- a/external/cecil/Mono.Cecil.Cil/Document.cs +++ b/external/cecil/Mono.Cecil.Cil/Document.cs @@ -1,29 +1,11 @@ // -// Document.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; @@ -39,6 +21,7 @@ namespace Mono.Cecil.Cil { None, MD5, SHA1, + SHA256, } public enum DocumentLanguage { @@ -62,7 +45,7 @@ namespace Mono.Cecil.Cil { Microsoft, } - public sealed class Document { + public sealed class Document : DebugInformation { string url; @@ -107,6 +90,7 @@ namespace Mono.Cecil.Cil { { this.url = url; this.hash = Empty.Array; + this.token = new MetadataToken (TokenType.Document); } } } diff --git a/external/cecil/Mono.Cecil.Cil/ExceptionHandler.cs b/external/cecil/Mono.Cecil.Cil/ExceptionHandler.cs index c61ff235ef..6bdb1aa327 100644 --- a/external/cecil/Mono.Cecil.Cil/ExceptionHandler.cs +++ b/external/cecil/Mono.Cecil.Cil/ExceptionHandler.cs @@ -1,29 +1,11 @@ // -// ExceptionHandler.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // namespace Mono.Cecil.Cil { diff --git a/external/cecil/Mono.Cecil.Cil/ILProcessor.cs b/external/cecil/Mono.Cecil.Cil/ILProcessor.cs index cd5dbb40fe..039d2fc3a0 100644 --- a/external/cecil/Mono.Cecil.Cil/ILProcessor.cs +++ b/external/cecil/Mono.Cecil.Cil/ILProcessor.cs @@ -1,29 +1,11 @@ // -// ILProcessor.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; diff --git a/external/cecil/Mono.Cecil.Cil/Instruction.cs b/external/cecil/Mono.Cecil.Cil/Instruction.cs index c28d4c9929..60301bf417 100644 --- a/external/cecil/Mono.Cecil.Cil/Instruction.cs +++ b/external/cecil/Mono.Cecil.Cil/Instruction.cs @@ -1,29 +1,11 @@ // -// Instruction.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; @@ -40,8 +22,6 @@ namespace Mono.Cecil.Cil { internal Instruction previous; internal Instruction next; - SequencePoint sequence_point; - public int Offset { get { return offset; } set { offset = value; } @@ -67,11 +47,6 @@ namespace Mono.Cecil.Cil { set { next = value; } } - public SequencePoint SequencePoint { - get { return sequence_point; } - set { sequence_point = value; } - } - internal Instruction (int offset, OpCode opCode) { this.offset = offset; @@ -134,7 +109,7 @@ namespace Mono.Cecil.Cil { switch (opcode.OperandType) { case OperandType.ShortInlineBrTarget: case OperandType.InlineBrTarget: - AppendLabel (instruction, (Instruction) operand); + AppendLabel (instruction, operand); break; case OperandType.InlineSwitch: var labels = (Instruction []) operand; @@ -158,10 +133,15 @@ namespace Mono.Cecil.Cil { return instruction.ToString (); } - static void AppendLabel (StringBuilder builder, Instruction instruction) + static void AppendLabel (StringBuilder builder, object o) { builder.Append ("IL_"); - builder.Append (instruction.offset.ToString ("x4")); + if (o is Instruction) + builder.Append ((o as Instruction).offset.ToString ("x4")); + else if (o is int) { + builder.Append (((int)o).ToString ("x4")); + builder.Append (" (invalid)"); + } } public static Instruction Create (OpCode opcode) diff --git a/external/cecil/Mono.Cecil.Cil/MethodBody.cs b/external/cecil/Mono.Cecil.Cil/MethodBody.cs index 3eefc95f35..eb8baf5b93 100644 --- a/external/cecil/Mono.Cecil.Cil/MethodBody.cs +++ b/external/cecil/Mono.Cecil.Cil/MethodBody.cs @@ -1,38 +1,21 @@ // -// MethodBody.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; +using System.Threading; using Mono.Collections.Generic; namespace Mono.Cecil.Cil { - public sealed class MethodBody : IVariableDefinitionProvider { + public sealed class MethodBody { readonly internal MethodDefinition method; @@ -45,7 +28,6 @@ namespace Mono.Cecil.Cil { internal Collection instructions; internal Collection exceptions; internal Collection variables; - Scope scope; public MethodDefinition Method { get { return method; } @@ -71,7 +53,7 @@ namespace Mono.Cecil.Cil { } public Collection Instructions { - get { return instructions ?? (instructions = new InstructionCollection ()); } + get { return instructions ?? (instructions = new InstructionCollection (method)); } } public bool HasExceptionHandlers { @@ -90,11 +72,6 @@ namespace Mono.Cecil.Cil { get { return variables ?? (variables = new VariableDefinitionCollection ()); } } - public Scope Scope { - get { return scope; } - set { scope = value; } - } - public ParameterDefinition ThisParameter { get { if (method == null || method.DeclaringType == null) @@ -103,18 +80,32 @@ namespace Mono.Cecil.Cil { if (!method.HasThis) return null; - if (this_parameter != null) - return this_parameter; + if (this_parameter == null) + Interlocked.CompareExchange (ref this_parameter, CreateThisParameter (method), null); - var declaring_type = method.DeclaringType; - var type = declaring_type.IsValueType || declaring_type.IsPrimitive - ? new PointerType (declaring_type) - : declaring_type as TypeReference; - - return this_parameter = new ParameterDefinition (type, method); + return this_parameter; } } + static ParameterDefinition CreateThisParameter (MethodDefinition method) + { + var parameter_type = method.DeclaringType as TypeReference; + + if (parameter_type.HasGenericParameters) { + var instance = new GenericInstanceType (parameter_type); + for (int i = 0; i < parameter_type.GenericParameters.Count; i++) + instance.GenericArguments.Add (parameter_type.GenericParameters [i]); + + parameter_type = instance; + + } + + if (parameter_type.IsValueType || parameter_type.IsPrimitive) + parameter_type = new ByReferenceType (parameter_type); + + return new ParameterDefinition (parameter_type, method); + } + public MethodBody (MethodDefinition method) { this.method = method; @@ -126,12 +117,7 @@ namespace Mono.Cecil.Cil { } } - public interface IVariableDefinitionProvider { - bool HasVariables { get; } - Collection Variables { get; } - } - - class VariableDefinitionCollection : Collection { + sealed class VariableDefinitionCollection : Collection { internal VariableDefinitionCollection () { @@ -171,13 +157,17 @@ namespace Mono.Cecil.Cil { class InstructionCollection : Collection { - internal InstructionCollection () + readonly MethodDefinition method; + + internal InstructionCollection (MethodDefinition method) { + this.method = method; } - internal InstructionCollection (int capacity) + internal InstructionCollection (MethodDefinition method, int capacity) : base (capacity) { + this.method = method; } protected override void OnAdd (Instruction item, int index) @@ -234,8 +224,25 @@ namespace Mono.Cecil.Cil { if (next != null) next.previous = item.previous; + RemoveSequencePoint (item); + item.previous = null; item.next = null; } + + void RemoveSequencePoint (Instruction instruction) + { + var debug_info = method.debug_info; + if (debug_info == null || !debug_info.HasSequencePoints) + return; + + var sequence_points = debug_info.sequence_points; + for (int i = 0; i < sequence_points.Count; i++) { + if (sequence_points [i].Offset == instruction.offset) { + sequence_points.RemoveAt (i); + return; + } + } + } } } diff --git a/external/cecil/Mono.Cecil.Cil/OpCode.cs b/external/cecil/Mono.Cecil.Cil/OpCode.cs index 1a14421300..81ab0e12ac 100644 --- a/external/cecil/Mono.Cecil.Cil/OpCode.cs +++ b/external/cecil/Mono.Cecil.Cil/OpCode.cs @@ -1,31 +1,15 @@ // -// OpCode.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // +using System; + namespace Mono.Cecil.Cil { public enum FlowControl { @@ -104,7 +88,7 @@ namespace Mono.Cecil.Cil { Varpush, } - public struct OpCode { + public struct OpCode : IEquatable { readonly byte op1; readonly byte op2; diff --git a/external/cecil/Mono.Cecil.Cil/OpCodes.cs b/external/cecil/Mono.Cecil.Cil/OpCodes.cs index 85712ec8b8..ba0468d305 100644 --- a/external/cecil/Mono.Cecil.Cil/OpCodes.cs +++ b/external/cecil/Mono.Cecil.Cil/OpCodes.cs @@ -1,29 +1,11 @@ // -// OpCodes.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // namespace Mono.Cecil.Cil { diff --git a/external/cecil/Mono.Cecil.Cil/PortablePdb.cs b/external/cecil/Mono.Cecil.Cil/PortablePdb.cs new file mode 100644 index 0000000000..b799fc8d8b --- /dev/null +++ b/external/cecil/Mono.Cecil.Cil/PortablePdb.cs @@ -0,0 +1,409 @@ +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. +// +// Licensed under the MIT/X11 license. +// + +using System; +using System.Collections.Generic; +using System.IO; + +using Mono.Cecil.Metadata; +using Mono.Cecil.PE; + +namespace Mono.Cecil.Cil { + + public sealed class PortablePdbReaderProvider : ISymbolReaderProvider { + +#if !PCL + public ISymbolReader GetSymbolReader (ModuleDefinition module, string fileName) + { + Mixin.CheckModule (module); + Mixin.CheckFileName (fileName); + + var file = File.OpenRead (Mixin.GetPdbFileName (fileName)); + return GetSymbolReader (module, Disposable.Owned (file as Stream), file.Name); + } +#endif + + public ISymbolReader GetSymbolReader (ModuleDefinition module, Stream symbolStream) + { + Mixin.CheckModule (module); + Mixin.CheckStream (symbolStream); + + return GetSymbolReader (module, Disposable.NotOwned (symbolStream), ""); + } + + ISymbolReader GetSymbolReader (ModuleDefinition module, Disposable symbolStream, string fileName) + { + return new PortablePdbReader (ImageReader.ReadPortablePdb (symbolStream, fileName), module); + } + } + + public sealed class PortablePdbReader : ISymbolReader { + + readonly Image image; + readonly ModuleDefinition module; + readonly MetadataReader reader; + readonly MetadataReader debug_reader; + + bool IsEmbedded { get { return reader.image == debug_reader.image; } } + + internal PortablePdbReader (Image image, ModuleDefinition module) + { + this.image = image; + this.module = module; + this.reader = module.reader; + this.debug_reader = new MetadataReader (image, module, this.reader); + } + + public bool ProcessDebugHeader (ImageDebugDirectory directory, byte [] header) + { + if (image == module.Image) + return true; + + if (header.Length < 24) + return false; + + var magic = ReadInt32 (header, 0); + if (magic != 0x53445352) + return false; + + var buffer = new byte [16]; + Buffer.BlockCopy (header, 4, buffer, 0, 16); + + var module_guid = new Guid (buffer); + + Buffer.BlockCopy (image.PdbHeap.Id, 0, buffer, 0, 16); + + var pdb_guid = new Guid (buffer); + + return module_guid == pdb_guid; + } + + static int ReadInt32 (byte [] bytes, int start) + { + return (bytes [start] + | (bytes [start + 1] << 8) + | (bytes [start + 2] << 16) + | (bytes [start + 3] << 24)); + } + + public MethodDebugInformation Read (MethodDefinition method) + { + var info = new MethodDebugInformation (method); + ReadSequencePoints (info); + ReadScope (info); + ReadStateMachineKickOffMethod (info); + ReadCustomDebugInformations (info); + return info; + } + + void ReadSequencePoints (MethodDebugInformation method_info) + { + method_info.sequence_points = debug_reader.ReadSequencePoints (method_info.method); + } + + void ReadScope (MethodDebugInformation method_info) + { + method_info.scope = debug_reader.ReadScope (method_info.method); + } + + void ReadStateMachineKickOffMethod (MethodDebugInformation method_info) + { + method_info.kickoff_method = debug_reader.ReadStateMachineKickoffMethod (method_info.method); + } + + void ReadCustomDebugInformations (MethodDebugInformation info) + { + info.method.custom_infos = debug_reader.GetCustomDebugInformation (info.method); + } + + public void Dispose () + { + if (IsEmbedded) + return; + + image.Dispose (); + } + } + +#if !READ_ONLY + + public sealed class PortablePdbWriterProvider : ISymbolWriterProvider + { +#if !PCL + public ISymbolWriter GetSymbolWriter (ModuleDefinition module, string fileName) + { + Mixin.CheckModule (module); + Mixin.CheckFileName (fileName); + + var file = File.OpenWrite (Mixin.GetPdbFileName (fileName)); + return GetSymbolWriter (module, Disposable.Owned (file as Stream)); + } +#endif + + public ISymbolWriter GetSymbolWriter (ModuleDefinition module, Stream symbolStream) + { + Mixin.CheckModule (module); + Mixin.CheckStream (symbolStream); + + return GetSymbolWriter (module, Disposable.NotOwned (symbolStream)); + } + + ISymbolWriter GetSymbolWriter (ModuleDefinition module, Disposable stream) + { + var metadata = new MetadataBuilder (module, this); + var writer = ImageWriter.CreateDebugWriter (module, metadata, stream); + + return new PortablePdbWriter (metadata, module, writer); + } + } + + sealed class PortablePdbWriter : ISymbolWriter { + + readonly MetadataBuilder pdb_metadata; + readonly ModuleDefinition module; + readonly ImageWriter writer; + + MetadataBuilder module_metadata; + + bool IsEmbedded { get { return writer == null; } } + + public PortablePdbWriter (MetadataBuilder pdb_metadata, ModuleDefinition module) + { + this.pdb_metadata = pdb_metadata; + this.module = module; + } + + public PortablePdbWriter (MetadataBuilder pdb_metadata, ModuleDefinition module, ImageWriter writer) + : this (pdb_metadata, module) + { + this.writer = writer; + } + + public void SetModuleMetadata (MetadataBuilder metadata) + { + this.module_metadata = metadata; + + if (module_metadata != pdb_metadata) + this.pdb_metadata.metadata_builder = metadata; + } + + public bool GetDebugHeader (out ImageDebugDirectory directory, out byte [] header) + { + if (IsEmbedded) { + directory = new ImageDebugDirectory (); + header = Empty.Array; + return false; + } + + directory = new ImageDebugDirectory () { + MajorVersion = 256, + MinorVersion = 20577, + Type = 2, + }; + + var buffer = new ByteBuffer (); + // RSDS + buffer.WriteUInt32 (0x53445352); + // Module ID + buffer.WriteBytes (module.Mvid.ToByteArray ()); + // PDB Age + buffer.WriteUInt32 (1); + // PDB Path + buffer.WriteBytes (System.Text.Encoding.UTF8.GetBytes (writer.BaseStream.GetFileName ())); + buffer.WriteByte (0); + + header = new byte [buffer.length]; + Buffer.BlockCopy (buffer.buffer, 0, header, 0, buffer.length); + directory.SizeOfData = header.Length; + return true; + } + + public void Write (MethodDebugInformation info) + { + CheckMethodDebugInformationTable (); + + pdb_metadata.AddMethodDebugInformation (info); + } + + void CheckMethodDebugInformationTable () + { + var mdi = pdb_metadata.table_heap.GetTable (Table.MethodDebugInformation); + if (mdi.length > 0) + return; + + // The MethodDebugInformation table has the same length as the Method table + mdi.rows = new Row [module_metadata.method_rid - 1]; + mdi.length = mdi.rows.Length; + } + + public void Dispose () + { + if (IsEmbedded) + return; + + WritePdbHeap (); + WriteTableHeap (); + + writer.BuildMetadataTextMap (); + writer.WriteMetadataHeader (); + writer.WriteMetadata (); + + writer.stream.Dispose (); + } + + void WritePdbHeap () + { + var pdb_heap = pdb_metadata.pdb_heap; + + pdb_heap.WriteBytes (module.Mvid.ToByteArray ()); + pdb_heap.WriteUInt32 (module_metadata.time_stamp); + + pdb_heap.WriteUInt32 (module_metadata.entry_point.ToUInt32 ()); + + var table_heap = module_metadata.table_heap; + var tables = table_heap.tables; + + ulong valid = 0; + for (int i = 0; i < tables.Length; i++) { + if (tables [i] == null || tables [i].Length == 0) + continue; + + valid |= (1UL << i); + } + + pdb_heap.WriteUInt64 (valid); + + for (int i = 0; i < tables.Length; i++) { + if (tables [i] == null || tables [i].Length == 0) + continue; + + pdb_heap.WriteUInt32 ((uint) tables [i].Length); + } + } + + void WriteTableHeap () + { + pdb_metadata.table_heap.WriteTableHeap (); + } + } + +#endif + + static class PdbGuidMapping { + + static readonly Dictionary guid_language = new Dictionary (); + static readonly Dictionary language_guid = new Dictionary (); + + static PdbGuidMapping () + { + AddMapping (DocumentLanguage.C, new Guid ("63a08714-fc37-11d2-904c-00c04fa302a1")); + AddMapping (DocumentLanguage.Cpp, new Guid ("3a12d0b7-c26c-11d0-b442-00a0244a1dd2")); + AddMapping (DocumentLanguage.CSharp, new Guid ("3f5162f8-07c6-11d3-9053-00c04fa302a1")); + AddMapping (DocumentLanguage.Basic, new Guid ("3a12d0b8-c26c-11d0-b442-00a0244a1dd2")); + AddMapping (DocumentLanguage.Java, new Guid ("3a12d0b4-c26c-11d0-b442-00a0244a1dd2")); + AddMapping (DocumentLanguage.Cobol, new Guid ("af046cd1-d0e1-11d2-977c-00a0c9b4d50c")); + AddMapping (DocumentLanguage.Pascal, new Guid ("af046cd2-d0e1-11d2-977c-00a0c9b4d50c")); + AddMapping (DocumentLanguage.Cil, new Guid ("af046cd3-d0e1-11d2-977c-00a0c9b4d50c")); + AddMapping (DocumentLanguage.JScript, new Guid ("3a12d0b6-c26c-11d0-b442-00a0244a1dd2")); + AddMapping (DocumentLanguage.Smc, new Guid ("0d9b9f7b-6611-11d3-bd2a-0000f80849bd")); + AddMapping (DocumentLanguage.MCpp, new Guid ("4b35fde8-07c6-11d3-9053-00c04fa302a1")); + AddMapping (DocumentLanguage.FSharp, new Guid ("ab4f38c9-b6e6-43ba-be3b-58080b2ccce3")); + } + + static void AddMapping (DocumentLanguage language, Guid guid) + { + guid_language.Add (guid, language); + language_guid.Add (language, guid); + } + + static readonly Guid type_text = new Guid ("5a869d0b-6611-11d3-bd2a-0000f80849bd"); + + public static DocumentType ToType (this Guid guid) + { + if (guid == type_text) + return DocumentType.Text; + + return DocumentType.Other; + } + + public static Guid ToGuid (this DocumentType type) + { + if (type == DocumentType.Text) + return type_text; + + return new Guid (); + } + + static readonly Guid hash_md5 = new Guid ("406ea660-64cf-4c82-b6f0-42d48172a799"); + static readonly Guid hash_sha1 = new Guid ("ff1816ec-aa5e-4d10-87f7-6f4963833460"); + static readonly Guid hash_sha256 = new Guid ("8829d00f-11b8-4213-878b-770e8597ac16"); + + public static DocumentHashAlgorithm ToHashAlgorithm (this Guid guid) + { + if (guid == hash_md5) + return DocumentHashAlgorithm.MD5; + + if (guid == hash_sha1) + return DocumentHashAlgorithm.SHA1; + + if (guid == hash_sha256) + return DocumentHashAlgorithm.SHA256; + + return DocumentHashAlgorithm.None; + } + + public static Guid ToGuid (this DocumentHashAlgorithm hash_algo) + { + if (hash_algo == DocumentHashAlgorithm.MD5) + return hash_md5; + + if (hash_algo == DocumentHashAlgorithm.SHA1) + return hash_sha1; + + return new Guid (); + } + + public static DocumentLanguage ToLanguage (this Guid guid) + { + DocumentLanguage language; + if (!guid_language.TryGetValue (guid, out language)) + return DocumentLanguage.Other; + + return language; + } + + public static Guid ToGuid (this DocumentLanguage language) + { + Guid guid; + if (!language_guid.TryGetValue (language, out guid)) + return new Guid (); + + return guid; + } + + static readonly Guid vendor_ms = new Guid ("994b45c4-e6e9-11d2-903f-00c04fa302a1"); + + public static DocumentLanguageVendor ToVendor (this Guid guid) + { + if (guid == vendor_ms) + return DocumentLanguageVendor.Microsoft; + + return DocumentLanguageVendor.Other; + } + + public static Guid ToGuid (this DocumentLanguageVendor vendor) + { + if (vendor == DocumentLanguageVendor.Microsoft) + return vendor_ms; + + return new Guid (); + } + } +} diff --git a/external/cecil/Mono.Cecil.Cil/SequencePoint.cs b/external/cecil/Mono.Cecil.Cil/SequencePoint.cs index ef87e30f13..73970542a6 100644 --- a/external/cecil/Mono.Cecil.Cil/SequencePoint.cs +++ b/external/cecil/Mono.Cecil.Cil/SequencePoint.cs @@ -1,35 +1,20 @@ // -// SequencePoint.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // +using System; + namespace Mono.Cecil.Cil { public sealed class SequencePoint { + internal InstructionOffset offset; Document document; int start_line; @@ -37,6 +22,10 @@ namespace Mono.Cecil.Cil { int end_line; int end_column; + public int Offset { + get { return offset.Offset; } + } + public int StartLine { get { return start_line; } set { start_line = value; } @@ -57,13 +46,30 @@ namespace Mono.Cecil.Cil { set { end_column = value; } } + public bool IsHidden { + get { return start_line == 0xfeefee && start_line == start_column; } + } + public Document Document { get { return document; } set { document = value; } } - public SequencePoint (Document document) + internal SequencePoint (int offset, Document document) { + if (document == null) + throw new ArgumentNullException ("document"); + + this.offset = new InstructionOffset (offset); + this.document = document; + } + + public SequencePoint (Instruction instruction, Document document) + { + if (document == null) + throw new ArgumentNullException ("document"); + + this.offset = new InstructionOffset (instruction); this.document = document; } } diff --git a/external/cecil/Mono.Cecil.Cil/Symbols.cs b/external/cecil/Mono.Cecil.Cil/Symbols.cs index 426c4a7e1f..485152f4b7 100644 --- a/external/cecil/Mono.Cecil.Cil/Symbols.cs +++ b/external/cecil/Mono.Cecil.Cil/Symbols.cs @@ -1,32 +1,15 @@ // -// Symbols.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; +using System.Collections.Generic; using System.IO; using System.Runtime.InteropServices; using SR = System.Reflection; @@ -47,143 +30,613 @@ namespace Mono.Cecil.Cil { public int PointerToRawData; } - public sealed class Scope : IVariableDefinitionProvider { + public sealed class ScopeDebugInformation : DebugInformation { - Instruction start; - Instruction end; + internal InstructionOffset start; + internal InstructionOffset end; + internal ImportDebugInformation import; + internal Collection scopes; + internal Collection variables; + internal Collection constants; - Collection scopes; - Collection variables; - - public Instruction Start { + public InstructionOffset Start { get { return start; } set { start = value; } } - public Instruction End { + public InstructionOffset End { get { return end; } set { end = value; } } + public ImportDebugInformation Import { + get { return import; } + set { import = value; } + } + public bool HasScopes { get { return !scopes.IsNullOrEmpty (); } } - public Collection Scopes { - get { - if (scopes == null) - scopes = new Collection (); - - return scopes; - } + public Collection Scopes { + get { return scopes ?? (scopes = new Collection ()); } } public bool HasVariables { get { return !variables.IsNullOrEmpty (); } } - public Collection Variables { - get { - if (variables == null) - variables = new Collection (); + public Collection Variables { + get { return variables ?? (variables = new Collection ()); } + } - return variables; + public bool HasConstants { + get { return !constants.IsNullOrEmpty (); } + } + + public Collection Constants { + get { return constants ?? (constants = new Collection ()); } + } + + internal ScopeDebugInformation () + { + this.token = new MetadataToken (TokenType.LocalScope); + } + + public ScopeDebugInformation (Instruction start, Instruction end) + : this () + { + if (start == null) + throw new ArgumentNullException ("start"); + + this.start = new InstructionOffset (start); + + if (end != null) + this.end = new InstructionOffset (end); + } + + public bool TryGetName (VariableDefinition variable, out string name) + { + name = null; + if (variables == null || variables.Count == 0) + return false; + + for (int i = 0; i < variables.Count; i++) { + if (variables [i].Index == variable.Index) { + name = variables [i].Name; + return true; + } + } + + return false; + } + } + + public struct InstructionOffset { + + readonly Instruction instruction; + readonly int? offset; + + public int Offset { + get { + if (instruction != null) + return instruction.Offset; + if (offset.HasValue) + return offset.Value; + + throw new NotSupportedException (); } } - } - public struct InstructionSymbol { + public bool IsEndOfMethod { + get { return instruction == null && !offset.HasValue; } + } - public readonly int Offset; - public readonly SequencePoint SequencePoint; - - public InstructionSymbol (int offset, SequencePoint sequencePoint) + public InstructionOffset (Instruction instruction) { - this.Offset = offset; - this.SequencePoint = sequencePoint; + if (instruction == null) + throw new ArgumentNullException ("instruction"); + + this.instruction = instruction; + this.offset = null; + } + + public InstructionOffset (int offset) + { + this.instruction = null; + this.offset = offset; } } - public sealed class MethodSymbols { + [Flags] + public enum VariableAttributes : ushort { + None = 0, + DebuggerHidden = 1, + } + public struct VariableIndex { + readonly VariableDefinition variable; + readonly int? index; + + public int Index { + get { + if (variable != null) + return variable.Index; + if (index.HasValue) + return index.Value; + + throw new NotSupportedException (); + } + } + + public VariableIndex (VariableDefinition variable) + { + if (variable == null) + throw new ArgumentNullException ("variable"); + + this.variable = variable; + this.index = null; + } + + public VariableIndex (int index) + { + this.variable = null; + this.index = index; + } + } + + public abstract class DebugInformation : ICustomDebugInformationProvider { + + internal MetadataToken token; + internal Collection custom_infos; + + public MetadataToken MetadataToken { + get { return token; } + set { token = value; } + } + + public bool HasCustomDebugInformations { + get { return !custom_infos.IsNullOrEmpty (); } + } + + public Collection CustomDebugInformations { + get { return custom_infos ?? (custom_infos = new Collection ()); } + } + + internal DebugInformation () + { + } + } + + public sealed class VariableDebugInformation : DebugInformation { + + string name; + ushort attributes; + internal VariableIndex index; + + public int Index { + get { return index.Index; } + } + + public string Name { + get { return name; } + set { name = value; } + } + + public VariableAttributes Attributes { + get { return (VariableAttributes) attributes; } + set { attributes = (ushort) value; } + } + + public bool IsDebuggerHidden { + get { return attributes.GetAttributes ((ushort) VariableAttributes.DebuggerHidden); } + set { attributes = attributes.SetAttributes ((ushort) VariableAttributes.DebuggerHidden, value); } + } + + internal VariableDebugInformation (int index, string name) + { + if (name == null) + throw new ArgumentNullException ("name"); + + this.index = new VariableIndex (index); + this.name = name; + } + + public VariableDebugInformation (VariableDefinition variable, string name) + { + if (variable == null) + throw new ArgumentNullException ("variable"); + if (name == null) + throw new ArgumentNullException ("name"); + + this.index = new VariableIndex (variable); + this.name = name; + this.token = new MetadataToken (TokenType.LocalVariable); + } + } + + public sealed class ConstantDebugInformation : DebugInformation { + + string name; + TypeReference constant_type; + object value; + + public string Name { + get { return name; } + set { name = value; } + } + + public TypeReference ConstantType { + get { return constant_type; } + set { constant_type = value; } + } + + public object Value { + get { return value; } + set { this.value = value; } + } + + public ConstantDebugInformation (string name, TypeReference constant_type, object value) + { + if (name == null) + throw new ArgumentNullException ("name"); + + this.name = name; + this.constant_type = constant_type; + this.value = value; + this.token = new MetadataToken (TokenType.LocalConstant); + } + } + + public enum ImportTargetKind : byte { + ImportNamespace = 1, + ImportNamespaceInAssembly = 2, + ImportType = 3, + ImportXmlNamespaceWithAlias = 4, + ImportAlias = 5, + DefineAssemblyAlias = 6, + DefineNamespaceAlias = 7, + DefineNamespaceInAssemblyAlias = 8, + DefineTypeAlias = 9, + } + + public sealed class ImportTarget { + + internal ImportTargetKind kind; + + internal string @namespace; + internal TypeReference type; + internal AssemblyNameReference reference; + internal string alias; + + public string Namespace { + get { return @namespace; } + set { @namespace = value; } + } + + public TypeReference Type { + get { return type; } + set { type = value; } + } + + public AssemblyNameReference AssemblyReference { + get { return reference; } + set { reference = value; } + } + + public string Alias { + get { return alias; } + set { alias = value; } + } + + public ImportTargetKind Kind { + get { return kind; } + set { kind = value; } + } + + public ImportTarget (ImportTargetKind kind) + { + this.kind = kind; + } + } + + public sealed class ImportDebugInformation : DebugInformation { + + internal ImportDebugInformation parent; + internal Collection targets; + + public bool HasTargets { + get { return !targets.IsNullOrEmpty (); } + } + + public Collection Targets { + get { return targets ?? (targets = new Collection ()); } + } + + public ImportDebugInformation Parent { + get { return parent; } + set { parent = value; } + } + + public ImportDebugInformation () + { + this.token = new MetadataToken (TokenType.ImportScope); + } + } + + interface ICustomDebugInformationProvider : IMetadataTokenProvider { + bool HasCustomDebugInformations { get; } + Collection CustomDebugInformations { get; } + } + + public enum CustomDebugInformationKind { + Binary, + StateMachineScope, + DynamicVariable, + DefaultNamespace, + AsyncMethodBody, + } + + public abstract class CustomDebugInformation : DebugInformation { + + Guid identifier; + + public Guid Identifier { get { return identifier; } } + + public abstract CustomDebugInformationKind Kind { get; } + + internal CustomDebugInformation (Guid identifier) + { + this.identifier = identifier; + this.token = new MetadataToken (TokenType.CustomDebugInformation); + } + } + + public sealed class BinaryCustomDebugInformation : CustomDebugInformation { + + byte [] data; + + public byte [] Data { + get { return data; } + set { data = value; } + } + + public override CustomDebugInformationKind Kind { + get { return CustomDebugInformationKind.Binary; } + } + + public BinaryCustomDebugInformation (Guid identifier, byte [] data) + : base (identifier) + { + this.data = data; + } + } + + public sealed class AsyncMethodBodyDebugInformation : CustomDebugInformation { + + internal InstructionOffset catch_handler; + internal Collection yields; + internal Collection resumes; + internal MethodDefinition move_next; + + public InstructionOffset CatchHandler { + get { return catch_handler; } + set { catch_handler = value; } + } + + public Collection Yields { + get { return yields ?? (yields = new Collection ()); } + } + + public Collection Resumes { + get { return resumes ?? (resumes = new Collection ()); } + } + + public MethodDefinition MoveNextMethod { + get { return move_next; } + set { move_next = value; } + } + + public override CustomDebugInformationKind Kind { + get { return CustomDebugInformationKind.AsyncMethodBody; } + } + + public static Guid KindIdentifier = new Guid ("{54FD2AC5-E925-401A-9C2A-F94F171072F8}"); + + internal AsyncMethodBodyDebugInformation (int catchHandler) + : base (KindIdentifier) + { + this.catch_handler = new InstructionOffset (catchHandler); + } + + public AsyncMethodBodyDebugInformation (Instruction catchHandler) + : base (KindIdentifier) + { + this.catch_handler = new InstructionOffset (catchHandler); + } + } + + public sealed class StateMachineScopeDebugInformation : CustomDebugInformation { + + internal InstructionOffset start; + internal InstructionOffset end; + + public InstructionOffset Start { + get { return start; } + set { start = value; } + } + + public InstructionOffset End { + get { return end; } + set { end = value; } + } + + public override CustomDebugInformationKind Kind { + get { return CustomDebugInformationKind.StateMachineScope; } + } + + public static Guid KindIdentifier = new Guid ("{6DA9A61E-F8C7-4874-BE62-68BC5630DF71}"); + + internal StateMachineScopeDebugInformation (int start, int end) + : base (KindIdentifier) + { + this.start = new InstructionOffset (start); + this.end = new InstructionOffset (end); + } + + public StateMachineScopeDebugInformation (Instruction start, Instruction end) + : base (KindIdentifier) + { + this.start = new InstructionOffset (start); + this.end = new InstructionOffset (end); + } + } + + public sealed class MethodDebugInformation : DebugInformation { + + internal MethodDefinition method; + internal Collection sequence_points; + internal ScopeDebugInformation scope; + internal MethodDefinition kickoff_method; internal int code_size; - internal string method_name; - internal MetadataToken method_token; internal MetadataToken local_var_token; - internal Collection variables; - internal Collection instructions; - public bool HasVariables { - get { return !variables.IsNullOrEmpty (); } + public MethodDefinition Method { + get { return method; } } - public Collection Variables { - get { - if (variables == null) - variables = new Collection (); + public bool HasSequencePoints { + get { return !sequence_points.IsNullOrEmpty (); } + } - return variables; + public Collection SequencePoints { + get { return sequence_points ?? (sequence_points = new Collection ()); } + } + + public ScopeDebugInformation Scope { + get { return scope; } + set { scope = value; } + } + + public MethodDefinition StateMachineKickOffMethod { + get { return kickoff_method; } + set { kickoff_method = value; } + } + + internal MethodDebugInformation (MethodDefinition method) + { + if (method == null) + throw new ArgumentNullException ("method"); + + this.method = method; + this.token = new MetadataToken (TokenType.MethodDebugInformation, method.MetadataToken.RID); + } + + public SequencePoint GetSequencePoint (Instruction instruction) + { + if (!HasSequencePoints) + return null; + + for (int i = 0; i < sequence_points.Count; i++) + if (sequence_points [i].Offset == instruction.Offset) + return sequence_points [i]; + + return null; + } + + public IDictionary GetSequencePointMapping () + { + var instruction_mapping = new Dictionary (); + if (!HasSequencePoints || !method.HasBody) + return instruction_mapping; + + var offset_mapping = new Dictionary (sequence_points.Count); + + for (int i = 0; i < sequence_points.Count; i++) + offset_mapping.Add (sequence_points [i].Offset, sequence_points [i]); + + var instructions = method.Body.Instructions; + + for (int i = 0; i < instructions.Count; i++) { + SequencePoint sequence_point; + if (offset_mapping.TryGetValue (instructions [i].Offset, out sequence_point)) + instruction_mapping.Add (instructions [i], sequence_point); + } + + return instruction_mapping; + } + + public IEnumerable GetScopes () + { + if (scope == null) + return Empty.Array; + + return GetScopes (new[] { scope }); + } + + static IEnumerable GetScopes (IList scopes) + { + for (int i = 0; i < scopes.Count; i++) { + var scope = scopes [i]; + + yield return scope; + + if (!scope.HasScopes) + continue; + + foreach (var sub_scope in GetScopes (scope.Scopes)) + yield return sub_scope; } } - public Collection Instructions { - get { - if (instructions == null) - instructions = new Collection (); + public bool TryGetName (VariableDefinition variable, out string name) + { + name = null; - return instructions; + var has_name = false; + var unique_name = ""; + + foreach (var scope in GetScopes ()) { + string slot_name; + if (!scope.TryGetName (variable, out slot_name)) + continue; + + if (!has_name) { + has_name = true; + unique_name = slot_name; + continue; + } + + if (unique_name != slot_name) + return false; } - } - public int CodeSize { - get { return code_size; } - } - - public string MethodName { - get { return method_name; } - } - - public MetadataToken MethodToken { - get { return method_token; } - } - - public MetadataToken LocalVarToken { - get { return local_var_token; } - } - - internal MethodSymbols (string methodName) - { - this.method_name = methodName; - } - - public MethodSymbols (MetadataToken methodToken) - { - this.method_token = methodToken; + name = unique_name; + return has_name; } } - public delegate Instruction InstructionMapper (int offset); - public interface ISymbolReader : IDisposable { bool ProcessDebugHeader (ImageDebugDirectory directory, byte [] header); - void Read (MethodBody body, InstructionMapper mapper); - void Read (MethodSymbols symbols); + MethodDebugInformation Read (MethodDefinition method); } public interface ISymbolReaderProvider { - +#if !PCL ISymbolReader GetSymbolReader (ModuleDefinition module, string fileName); +#endif ISymbolReader GetSymbolReader (ModuleDefinition module, Stream symbolStream); } +#if !PCL static class SymbolProvider { static readonly string symbol_kind = Type.GetType ("Mono.Runtime") != null ? "Mdb" : "Pdb"; static SR.AssemblyName GetPlatformSymbolAssemblyName () { - var cecil_name = typeof (SymbolProvider).Assembly.GetName (); + var cecil_name = typeof (SymbolProvider).GetAssembly ().GetName (); var name = new SR.AssemblyName { Name = "Mono.Cecil." + symbol_kind, @@ -212,9 +665,7 @@ namespace Mono.Cecil.Cil { if (assembly != null) return assembly.GetType (fullname); } catch (FileNotFoundException) { -#if !CF } catch (FileLoadException) { -#endif } return null; @@ -257,21 +708,43 @@ namespace Mono.Cecil.Cil { #endif } +#endif #if !READ_ONLY public interface ISymbolWriter : IDisposable { bool GetDebugHeader (out ImageDebugDirectory directory, out byte [] header); - void Write (MethodBody body); - void Write (MethodSymbols symbols); + void Write (MethodDebugInformation info); } public interface ISymbolWriterProvider { +#if !PCL ISymbolWriter GetSymbolWriter (ModuleDefinition module, string fileName); +#endif ISymbolWriter GetSymbolWriter (ModuleDefinition module, Stream symbolStream); } #endif } + +#if !PCL + +namespace Mono.Cecil { + + static partial class Mixin { + + public static string GetPdbFileName (string assemblyFileName) + { + return Path.ChangeExtension (assemblyFileName, ".pdb"); + } + + public static string GetMdbFileName (string assemblyFileName) + { + return assemblyFileName + ".mdb"; + } + } +} + +#endif \ No newline at end of file diff --git a/external/cecil/Mono.Cecil.Cil/VariableDefinition.cs b/external/cecil/Mono.Cecil.Cil/VariableDefinition.cs index f501bca6e7..bd1328464a 100644 --- a/external/cecil/Mono.Cecil.Cil/VariableDefinition.cs +++ b/external/cecil/Mono.Cecil.Cil/VariableDefinition.cs @@ -1,29 +1,11 @@ // -// VariableDefinition.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // namespace Mono.Cecil.Cil { @@ -39,11 +21,6 @@ namespace Mono.Cecil.Cil { { } - public VariableDefinition (string name, TypeReference variableType) - : base (name, variableType) - { - } - public override VariableDefinition Resolve () { return this; diff --git a/external/cecil/Mono.Cecil.Cil/VariableReference.cs b/external/cecil/Mono.Cecil.Cil/VariableReference.cs index ce0b4cdb4c..fb12e8c14d 100644 --- a/external/cecil/Mono.Cecil.Cil/VariableReference.cs +++ b/external/cecil/Mono.Cecil.Cil/VariableReference.cs @@ -1,44 +1,20 @@ // -// VariableReference.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // namespace Mono.Cecil.Cil { public abstract class VariableReference { - string name; internal int index = -1; protected TypeReference variable_type; - public string Name { - get { return name; } - set { name = value; } - } - public TypeReference VariableType { get { return variable_type; } set { variable_type = value; } @@ -49,13 +25,7 @@ namespace Mono.Cecil.Cil { } internal VariableReference (TypeReference variable_type) - : this (string.Empty, variable_type) { - } - - internal VariableReference (string name, TypeReference variable_type) - { - this.name = name; this.variable_type = variable_type; } @@ -63,9 +33,6 @@ namespace Mono.Cecil.Cil { public override string ToString () { - if (!string.IsNullOrEmpty (name)) - return name; - if (index >= 0) return "V_" + index; diff --git a/external/cecil/Mono.Cecil.Metadata/BlobHeap.cs b/external/cecil/Mono.Cecil.Metadata/BlobHeap.cs index e7e2928c82..574a130c98 100644 --- a/external/cecil/Mono.Cecil.Metadata/BlobHeap.cs +++ b/external/cecil/Mono.Cecil.Metadata/BlobHeap.cs @@ -1,59 +1,54 @@ // -// BlobHeap.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; -using Mono.Cecil.PE; - namespace Mono.Cecil.Metadata { sealed class BlobHeap : Heap { - public BlobHeap (Section section, uint start, uint size) - : base (section, start, size) + public BlobHeap (byte [] data) + : base (data) { } public byte [] Read (uint index) { - if (index == 0 || index > Size - 1) + if (index == 0 || index > this.data.Length - 1) return Empty.Array; - var data = Section.Data; - - int position = (int) (index + Offset); + int position = (int) index; int length = (int) data.ReadCompressedUInt32 (ref position); + if (length > data.Length - position) + return Empty.Array; + var buffer = new byte [length]; Buffer.BlockCopy (data, position, buffer, 0, length); return buffer; } + + public void GetView (uint signature, out byte [] buffer, out int index, out int length) + { + if (signature == 0 || signature > data.Length - 1) { + buffer = null; + index = length = 0; + return; + } + + buffer = data; + + index = (int) signature; + length = (int) buffer.ReadCompressedUInt32 (ref index); + } } } diff --git a/external/cecil/Mono.Cecil.Metadata/Buffers.cs b/external/cecil/Mono.Cecil.Metadata/Buffers.cs index b63412dea7..5a915e2aca 100644 --- a/external/cecil/Mono.Cecil.Metadata/Buffers.cs +++ b/external/cecil/Mono.Cecil.Metadata/Buffers.cs @@ -1,29 +1,11 @@ // -// TableHeapBuffer.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; @@ -43,11 +25,13 @@ namespace Mono.Cecil.Metadata { readonly ModuleDefinition module; readonly MetadataBuilder metadata; - internal MetadataTable [] tables = new MetadataTable [45]; + internal MetadataTable [] tables = new MetadataTable [Mixin.TableCount]; bool large_string; bool large_blob; - readonly int [] coded_index_sizes = new int [13]; + bool large_guid; + + readonly int [] coded_index_sizes = new int [Mixin.CodedIndexCount]; readonly Func counter; public override bool IsEmpty { @@ -105,6 +89,11 @@ namespace Mono.Cecil.Metadata { WriteBySize (blob, large_blob); } + public void WriteGuid (uint guid) + { + WriteBySize (guid, large_guid); + } + public void WriteRID (uint rid, Table table) { var md_table = tables [(int) table]; @@ -134,7 +123,7 @@ namespace Mono.Cecil.Metadata { WriteByte (GetHeapSizes ()); // HeapSizes WriteByte (10); // Reserved2 WriteUInt64 (GetValid ()); // Valid - WriteUInt64 (0x0016003301fa00); // Sorted + WriteUInt64 (0xc416003301fa00); // Sorted WriteRowCount (); WriteTables (); @@ -187,6 +176,11 @@ namespace Mono.Cecil.Metadata { heap_sizes |= 0x01; } + if (metadata.guid_heap.IsLarge) { + large_guid = true; + heap_sizes |= 0x02; + } + if (metadata.blob_heap.IsLarge) { large_blob = true; heap_sizes |= 0x04; @@ -272,6 +266,37 @@ namespace Mono.Cecil.Metadata { } } + sealed class GuidHeapBuffer : HeapBuffer { + + readonly Dictionary guids = new Dictionary (); + + public override bool IsEmpty { + get { return length == 0; } + } + + public GuidHeapBuffer () + : base (16) + { + } + + public uint GetGuidIndex (Guid guid) + { + uint index; + if (guids.TryGetValue (guid, out index)) + return index; + + index = (uint) guids.Count + 1; + WriteGuid (guid); + guids.Add (guid, index); + return index; + } + + void WriteGuid (Guid guid) + { + WriteBytes (guid.ToByteArray ()); + } + } + class StringHeapBuffer : HeapBuffer { readonly Dictionary strings = new Dictionary (StringComparer.Ordinal); @@ -368,6 +393,18 @@ namespace Mono.Cecil.Metadata { WriteByte (special); } } + + sealed class PdbHeapBuffer : HeapBuffer { + + public override bool IsEmpty { + get { return false; } + } + + public PdbHeapBuffer () + : base (0) + { + } + } } #endif diff --git a/external/cecil/Mono.Cecil.Metadata/CodedIndex.cs b/external/cecil/Mono.Cecil.Metadata/CodedIndex.cs index 3e30fd87f9..2026a8a7db 100644 --- a/external/cecil/Mono.Cecil.Metadata/CodedIndex.cs +++ b/external/cecil/Mono.Cecil.Metadata/CodedIndex.cs @@ -1,29 +1,11 @@ // -// CodedIndex.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // namespace Mono.Cecil.Metadata { @@ -41,6 +23,7 @@ namespace Mono.Cecil.Metadata { Implementation, CustomAttributeType, ResolutionScope, - TypeOrMethodDef + TypeOrMethodDef, + HasCustomDebugInformation, } } diff --git a/external/cecil/Mono.Cecil.Metadata/ElementType.cs b/external/cecil/Mono.Cecil.Metadata/ElementType.cs index 72fc1ccaf2..2190160a6d 100644 --- a/external/cecil/Mono.Cecil.Metadata/ElementType.cs +++ b/external/cecil/Mono.Cecil.Metadata/ElementType.cs @@ -1,29 +1,11 @@ // -// ElementType.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // namespace Mono.Cecil.Metadata { diff --git a/external/cecil/Mono.Cecil.Metadata/GuidHeap.cs b/external/cecil/Mono.Cecil.Metadata/GuidHeap.cs index 1adc0795ee..76ec9d1d11 100644 --- a/external/cecil/Mono.Cecil.Metadata/GuidHeap.cs +++ b/external/cecil/Mono.Cecil.Metadata/GuidHeap.cs @@ -1,59 +1,36 @@ // -// GuidHeap.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; -using Mono.Cecil.PE; - namespace Mono.Cecil.Metadata { sealed class GuidHeap : Heap { - public GuidHeap (Section section, uint start, uint size) - : base (section, start, size) + public GuidHeap (byte [] data) + : base (data) { } public Guid Read (uint index) { - if (index == 0) - return new Guid (); - const int guid_size = 16; + if (index == 0 || ((index - 1) + guid_size) > data.Length) + return new Guid (); + var buffer = new byte [guid_size]; - index--; - - Buffer.BlockCopy (Section.Data, (int) (Offset + index), buffer, 0, guid_size); + Buffer.BlockCopy (this.data, (int) ((index - 1) * guid_size), buffer, 0, guid_size); return new Guid (buffer); - } } } diff --git a/external/cecil/Mono.Cecil.Metadata/Heap.cs b/external/cecil/Mono.Cecil.Metadata/Heap.cs index bc21acde25..1badfbb4fc 100644 --- a/external/cecil/Mono.Cecil.Metadata/Heap.cs +++ b/external/cecil/Mono.Cecil.Metadata/Heap.cs @@ -1,32 +1,12 @@ // -// Heap.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: +// Licensed under the MIT/X11 license. // -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// - -using Mono.Cecil.PE; namespace Mono.Cecil.Metadata { @@ -34,15 +14,11 @@ namespace Mono.Cecil.Metadata { public int IndexSize; - public readonly Section Section; - public readonly uint Offset; - public readonly uint Size; + internal byte [] data; - protected Heap (Section section, uint offset, uint size) + protected Heap (byte [] data) { - this.Section = section; - this.Offset = offset; - this.Size = size; + this.data = data; } } } diff --git a/external/cecil/Mono.Cecil.Metadata/MetadataToken.cs b/external/cecil/Mono.Cecil.Metadata/MetadataToken.cs index bda56b0f4f..a8b712e7ff 100644 --- a/external/cecil/Mono.Cecil.Metadata/MetadataToken.cs +++ b/external/cecil/Mono.Cecil.Metadata/MetadataToken.cs @@ -1,34 +1,18 @@ // -// MetadataToken.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // +using System; + namespace Mono.Cecil { - public struct MetadataToken { + public struct MetadataToken : IEquatable { readonly uint token; @@ -77,6 +61,11 @@ namespace Mono.Cecil { return (int) token; } + public bool Equals (MetadataToken other) + { + return other.token == token; + } + public override bool Equals (object obj) { if (obj is MetadataToken) { diff --git a/external/cecil/Mono.Cecil.Metadata/PdbHeap.cs b/external/cecil/Mono.Cecil.Metadata/PdbHeap.cs new file mode 100644 index 0000000000..39e275ad90 --- /dev/null +++ b/external/cecil/Mono.Cecil.Metadata/PdbHeap.cs @@ -0,0 +1,34 @@ +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. +// +// Licensed under the MIT/X11 license. +// + +using Mono.Cecil.PE; + +using RID = System.UInt32; + +namespace Mono.Cecil.Metadata { + + sealed class PdbHeap : Heap { + + public byte [] Id; + public RID EntryPoint; + public long TypeSystemTables; + public uint [] TypeSystemTableRows; + + public PdbHeap (byte [] data) + : base (data) + { + } + + public bool HasTable (Table table) + { + return (TypeSystemTables & (1L << (int) table)) != 0; + } + } +} diff --git a/external/cecil/Mono.Cecil.Metadata/Row.cs b/external/cecil/Mono.Cecil.Metadata/Row.cs index dfda00a777..0c05ebade6 100644 --- a/external/cecil/Mono.Cecil.Metadata/Row.cs +++ b/external/cecil/Mono.Cecil.Metadata/Row.cs @@ -1,29 +1,11 @@ // -// Row.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System.Collections.Generic; diff --git a/external/cecil/Mono.Cecil.Metadata/StringHeap.cs b/external/cecil/Mono.Cecil.Metadata/StringHeap.cs index 4a0a0af435..4bde70e233 100644 --- a/external/cecil/Mono.Cecil.Metadata/StringHeap.cs +++ b/external/cecil/Mono.Cecil.Metadata/StringHeap.cs @@ -1,45 +1,25 @@ // -// StringHeap.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; using System.Collections.Generic; using System.Text; -using Mono.Cecil.PE; - namespace Mono.Cecil.Metadata { class StringHeap : Heap { readonly Dictionary strings = new Dictionary (); - public StringHeap (Section section, uint start, uint size) - : base (section, start, size) + public StringHeap (byte [] data) + : base (data) { } @@ -52,7 +32,7 @@ namespace Mono.Cecil.Metadata { if (strings.TryGetValue (index, out @string)) return @string; - if (index > Size - 1) + if (index > data.Length - 1) return string.Empty; @string = ReadStringAt (index); @@ -65,8 +45,7 @@ namespace Mono.Cecil.Metadata { protected virtual string ReadStringAt (uint index) { int length = 0; - byte [] data = Section.Data; - int start = (int) (index + Offset); + int start = (int) index; for (int i = start; ; i++) { if (data [i] == 0) diff --git a/external/cecil/Mono.Cecil.Metadata/TableHeap.cs b/external/cecil/Mono.Cecil.Metadata/TableHeap.cs index 9bc0edd36c..ebc802be01 100644 --- a/external/cecil/Mono.Cecil.Metadata/TableHeap.cs +++ b/external/cecil/Mono.Cecil.Metadata/TableHeap.cs @@ -1,29 +1,11 @@ // -// TableHeap.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; @@ -77,6 +59,15 @@ namespace Mono.Cecil.Metadata { GenericParam = 0x2a, MethodSpec = 0x2b, GenericParamConstraint = 0x2c, + + Document = 0x30, + MethodDebugInformation = 0x31, + LocalScope = 0x32, + LocalVariable = 0x33, + LocalConstant = 0x34, + ImportScope = 0x35, + StateMachineMethod = 0x36, + CustomDebugInformation = 0x37, } struct TableInformation { @@ -90,16 +81,14 @@ namespace Mono.Cecil.Metadata { public long Valid; public long Sorted; - public const int TableCount = 45; - - public readonly TableInformation [] Tables = new TableInformation [TableCount]; + public readonly TableInformation [] Tables = new TableInformation [Mixin.TableCount]; public TableInformation this [Table table] { get { return Tables [(int) table]; } } - public TableHeap (Section section, uint start, uint size) - : base (section, start, size) + public TableHeap (byte [] data) + : base (data) { } diff --git a/external/cecil/Mono.Cecil.Metadata/TokenType.cs b/external/cecil/Mono.Cecil.Metadata/TokenType.cs index 2c2010ff97..547f6c6472 100644 --- a/external/cecil/Mono.Cecil.Metadata/TokenType.cs +++ b/external/cecil/Mono.Cecil.Metadata/TokenType.cs @@ -1,29 +1,11 @@ // -// TokenType.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // namespace Mono.Cecil { @@ -51,6 +33,17 @@ namespace Mono.Cecil { ManifestResource = 0x28000000, GenericParam = 0x2a000000, MethodSpec = 0x2b000000, + GenericParamConstraint = 0x2c000000, + + Document = 0x30000000, + MethodDebugInformation = 0x31000000, + LocalScope = 0x32000000, + LocalVariable = 0x33000000, + LocalConstant = 0x34000000, + ImportScope = 0x35000000, + StateMachineMethod = 0x36000000, + CustomDebugInformation = 0x37000000, + String = 0x70000000, } } diff --git a/external/cecil/Mono.Cecil.Metadata/UserStringHeap.cs b/external/cecil/Mono.Cecil.Metadata/UserStringHeap.cs index 59105087ff..7b1b42ffa0 100644 --- a/external/cecil/Mono.Cecil.Metadata/UserStringHeap.cs +++ b/external/cecil/Mono.Cecil.Metadata/UserStringHeap.cs @@ -1,48 +1,25 @@ // -// UserStringHeap.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: +// Licensed under the MIT/X11 license. // -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// - -using System; - -using Mono.Cecil.PE; namespace Mono.Cecil.Metadata { sealed class UserStringHeap : StringHeap { - public UserStringHeap (Section section, uint start, uint size) - : base (section, start, size) + public UserStringHeap (byte [] data) + : base (data) { } protected override string ReadStringAt (uint index) { - byte [] data = Section.Data; - int start = (int) (index + Offset); + int start = (int) index; uint length = (uint) (data.ReadCompressedUInt32 (ref start) & ~1); if (length < 1) diff --git a/external/cecil/Mono.Cecil.Metadata/Utilities.cs b/external/cecil/Mono.Cecil.Metadata/Utilities.cs index d752b24b11..3a4330da50 100644 --- a/external/cecil/Mono.Cecil.Metadata/Utilities.cs +++ b/external/cecil/Mono.Cecil.Metadata/Utilities.cs @@ -1,29 +1,11 @@ // -// Utilities.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; @@ -34,6 +16,9 @@ namespace Mono.Cecil { static partial class Mixin { + public const int TableCount = 58; + public const int CodedIndexCount = 14; + public static uint ReadCompressedUInt32 (this byte [] data, ref int position) { uint integer; @@ -126,6 +111,10 @@ namespace Mono.Cecil { token_type = TokenType.ManifestResource; goto ret; case 19: token_type = TokenType.GenericParam; goto ret; + case 20: + token_type = TokenType.GenericParamConstraint; goto ret; + case 21: + token_type = TokenType.MethodSpec; goto ret; default: goto exit; } @@ -242,6 +231,66 @@ namespace Mono.Cecil { token_type = TokenType.Method; goto ret; default: goto exit; } + case CodedIndex.HasCustomDebugInformation: + rid = data >> 5; + switch (data & 31) { + case 0: + token_type = TokenType.Method; goto ret; + case 1: + token_type = TokenType.Field; goto ret; + case 2: + token_type = TokenType.TypeRef; goto ret; + case 3: + token_type = TokenType.TypeDef; goto ret; + case 4: + token_type = TokenType.Param; goto ret; + case 5: + token_type = TokenType.InterfaceImpl; goto ret; + case 6: + token_type = TokenType.MemberRef; goto ret; + case 7: + token_type = TokenType.Module; goto ret; + case 8: + token_type = TokenType.Permission; goto ret; + case 9: + token_type = TokenType.Property; goto ret; + case 10: + token_type = TokenType.Event; goto ret; + case 11: + token_type = TokenType.Signature; goto ret; + case 12: + token_type = TokenType.ModuleRef; goto ret; + case 13: + token_type = TokenType.TypeSpec; goto ret; + case 14: + token_type = TokenType.Assembly; goto ret; + case 15: + token_type = TokenType.AssemblyRef; goto ret; + case 16: + token_type = TokenType.File; goto ret; + case 17: + token_type = TokenType.ExportedType; goto ret; + case 18: + token_type = TokenType.ManifestResource; goto ret; + case 19: + token_type = TokenType.GenericParam; goto ret; + case 20: + token_type = TokenType.GenericParamConstraint; goto ret; + case 21: + token_type = TokenType.MethodSpec; goto ret; + case 22: + token_type = TokenType.Document; goto ret; + case 23: + token_type = TokenType.LocalScope; goto ret; + case 24: + token_type = TokenType.LocalVariable; goto ret; + case 25: + token_type = TokenType.LocalConstant; goto ret; + case 26: + token_type = TokenType.ImportScope; goto ret; + default: + goto exit; + } default: goto exit; } @@ -325,6 +374,10 @@ namespace Mono.Cecil { return ret | 18; case TokenType.GenericParam: return ret | 19; + case TokenType.GenericParamConstraint: + return ret | 20; + case TokenType.MethodSpec: + return ret | 21; default: goto exit; } @@ -442,6 +495,66 @@ namespace Mono.Cecil { default: goto exit; } + case CodedIndex.HasCustomDebugInformation: + ret = token.RID << 5; + switch (token.TokenType) { + case TokenType.Method: + return ret | 0; + case TokenType.Field: + return ret | 1; + case TokenType.TypeRef: + return ret | 2; + case TokenType.TypeDef: + return ret | 3; + case TokenType.Param: + return ret | 4; + case TokenType.InterfaceImpl: + return ret | 5; + case TokenType.MemberRef: + return ret | 6; + case TokenType.Module: + return ret | 7; + case TokenType.Permission: + return ret | 8; + case TokenType.Property: + return ret | 9; + case TokenType.Event: + return ret | 10; + case TokenType.Signature: + return ret | 11; + case TokenType.ModuleRef: + return ret | 12; + case TokenType.TypeSpec: + return ret | 13; + case TokenType.Assembly: + return ret | 14; + case TokenType.AssemblyRef: + return ret | 15; + case TokenType.File: + return ret | 16; + case TokenType.ExportedType: + return ret | 17; + case TokenType.ManifestResource: + return ret | 18; + case TokenType.GenericParam: + return ret | 19; + case TokenType.GenericParamConstraint: + return ret | 20; + case TokenType.MethodSpec: + return ret | 21; + case TokenType.Document: + return ret | 22; + case TokenType.LocalScope: + return ret | 23; + case TokenType.LocalVariable: + return ret | 24; + case TokenType.LocalConstant: + return ret | 25; + case TokenType.ImportScope: + return ret | 26; + default: + goto exit; + } default: goto exit; } @@ -470,7 +583,7 @@ namespace Mono.Cecil { Table.Method, Table.Field, Table.TypeRef, Table.TypeDef, Table.Param, Table.InterfaceImpl, Table.MemberRef, Table.Module, Table.DeclSecurity, Table.Property, Table.Event, Table.StandAloneSig, Table.ModuleRef, Table.TypeSpec, Table.Assembly, Table.AssemblyRef, Table.File, Table.ExportedType, - Table.ManifestResource, Table.GenericParam + Table.ManifestResource, Table.GenericParam, Table.GenericParamConstraint, Table.MethodSpec, }; break; case CodedIndex.HasFieldMarshal: @@ -513,6 +626,16 @@ namespace Mono.Cecil { bits = 1; tables = new [] { Table.TypeDef, Table.Method }; break; + case CodedIndex.HasCustomDebugInformation: + bits = 5; + tables = new[] { + Table.Method, Table.Field, Table.TypeRef, Table.TypeDef, Table.Param, Table.InterfaceImpl, Table.MemberRef, + Table.Module, Table.DeclSecurity, Table.Property, Table.Event, Table.StandAloneSig, Table.ModuleRef, + Table.TypeSpec, Table.Assembly, Table.AssemblyRef, Table.File, Table.ExportedType, + Table.ManifestResource, Table.GenericParam, Table.GenericParamConstraint, Table.MethodSpec, + Table.Document, Table.LocalScope, Table.LocalVariable, Table.LocalConstant, Table.ImportScope, + }; + break; default: throw new ArgumentException (); } diff --git a/external/cecil/Mono.Cecil.PE/BinaryStreamReader.cs b/external/cecil/Mono.Cecil.PE/BinaryStreamReader.cs index ec2477c3ad..eb4b77eaf2 100644 --- a/external/cecil/Mono.Cecil.PE/BinaryStreamReader.cs +++ b/external/cecil/Mono.Cecil.PE/BinaryStreamReader.cs @@ -1,29 +1,11 @@ // -// BinaryStreamReader.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; @@ -33,17 +15,31 @@ namespace Mono.Cecil.PE { class BinaryStreamReader : BinaryReader { + public int Position { + get { return (int) BaseStream.Position; } + set { BaseStream.Position = value; } + } + + public int Length { + get { return (int) BaseStream.Length; } + } + public BinaryStreamReader (Stream stream) : base (stream) { } - protected void Advance (int bytes) + public void Advance (int bytes) { BaseStream.Seek (bytes, SeekOrigin.Current); } - protected DataDirectory ReadDataDirectory () + public void MoveTo (uint position) + { + BaseStream.Seek (position, SeekOrigin.Begin); + } + + public DataDirectory ReadDataDirectory () { return new DataDirectory (ReadUInt32 (), ReadUInt32 ()); } diff --git a/external/cecil/Mono.Cecil.PE/BinaryStreamWriter.cs b/external/cecil/Mono.Cecil.PE/BinaryStreamWriter.cs index 2bf6cccfa1..6e88cf0512 100644 --- a/external/cecil/Mono.Cecil.PE/BinaryStreamWriter.cs +++ b/external/cecil/Mono.Cecil.PE/BinaryStreamWriter.cs @@ -1,29 +1,11 @@ // -// BinaryStreamWriter.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; diff --git a/external/cecil/Mono.Cecil.PE/ByteBuffer.cs b/external/cecil/Mono.Cecil.PE/ByteBuffer.cs index c7ae7aee13..8aee04bafd 100644 --- a/external/cecil/Mono.Cecil.PE/ByteBuffer.cs +++ b/external/cecil/Mono.Cecil.PE/ByteBuffer.cs @@ -1,29 +1,11 @@ // -// ByteBuffer.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; @@ -52,12 +34,6 @@ namespace Mono.Cecil.PE { this.length = this.buffer.Length; } - public void Reset (byte [] buffer) - { - this.buffer = buffer ?? Empty.Array; - this.length = this.buffer.Length; - } - public void Advance (int length) { position += length; @@ -140,16 +116,22 @@ namespace Mono.Cecil.PE { public int ReadCompressedInt32 () { - var value = (int) (ReadCompressedUInt32 () >> 1); - if ((value & 1) == 0) - return value; - if (value < 0x40) - return value - 0x40; - if (value < 0x2000) - return value - 0x2000; - if (value < 0x10000000) - return value - 0x10000000; - return value - 0x20000000; + var b = buffer [position]; + var u = (int) ReadCompressedUInt32 (); + var v = u >> 1; + if ((u & 1) == 0) + return v; + + switch (b & 0xc0) + { + case 0: + case 0x40: + return v - 0x40; + case 0x80: + return v - 0x2000; + default: + return v - 0x10000000; + } } public float ReadSingle () diff --git a/external/cecil/Mono.Cecil.PE/ByteBufferEqualityComparer.cs b/external/cecil/Mono.Cecil.PE/ByteBufferEqualityComparer.cs index 70e89164c2..dd3a145058 100644 --- a/external/cecil/Mono.Cecil.PE/ByteBufferEqualityComparer.cs +++ b/external/cecil/Mono.Cecil.PE/ByteBufferEqualityComparer.cs @@ -1,29 +1,11 @@ // -// ByteBufferEqualityComparer.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; diff --git a/external/cecil/Mono.Cecil.PE/DataDirectory.cs b/external/cecil/Mono.Cecil.PE/DataDirectory.cs index fedd0e2dde..4922dd2f46 100644 --- a/external/cecil/Mono.Cecil.PE/DataDirectory.cs +++ b/external/cecil/Mono.Cecil.PE/DataDirectory.cs @@ -1,29 +1,11 @@ // -// DataDirectory.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; diff --git a/external/cecil/Mono.Cecil.PE/Image.cs b/external/cecil/Mono.Cecil.PE/Image.cs index fdecbbeb40..1ff06d7a34 100644 --- a/external/cecil/Mono.Cecil.PE/Image.cs +++ b/external/cecil/Mono.Cecil.PE/Image.cs @@ -1,34 +1,16 @@ // -// Image.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; +using System.IO; -using Mono; using Mono.Cecil.Cil; using Mono.Cecil.Metadata; @@ -36,13 +18,15 @@ using RVA = System.UInt32; namespace Mono.Cecil.PE { - sealed class Image { + sealed class Image : IDisposable { + + public Disposable Stream; + public string FileName; public ModuleKind Kind; - public TargetRuntime Runtime; + public string RuntimeVersion; public TargetArchitecture Architecture; public ModuleCharacteristics Characteristics; - public string FileName; public Section [] Sections; @@ -60,8 +44,9 @@ namespace Mono.Cecil.PE { public UserStringHeap UserStringHeap; public GuidHeap GuidHeap; public TableHeap TableHeap; + public PdbHeap PdbHeap; - readonly int [] coded_index_sizes = new int [13]; + readonly int [] coded_index_sizes = new int [14]; readonly Func counter; @@ -133,34 +118,72 @@ namespace Mono.Cecil.PE { return null; } + BinaryStreamReader GetReaderAt (RVA rva) + { + var section = GetSectionAtVirtualAddress (rva); + if (section == null) + return null; + + var reader = new BinaryStreamReader (Stream.value); + reader.MoveTo (ResolveVirtualAddressInSection (rva, section)); + return reader; + } + + public TRet GetReaderAt (RVA rva, TItem item, Func read) where TRet : class + { + var position = Stream.value.Position; + try { + var reader = GetReaderAt (rva); + if (reader == null) + return null; + + return read (item, reader); + } finally { + Stream.value.Position = position; + } + } + public ImageDebugDirectory GetDebugHeader (out byte [] header) { - var section = GetSectionAtVirtualAddress (Debug.VirtualAddress); - var buffer = new ByteBuffer (section.Data); - buffer.position = (int) (Debug.VirtualAddress - section.VirtualAddress); - - var directory = new ImageDebugDirectory { - Characteristics = buffer.ReadInt32 (), - TimeDateStamp = buffer.ReadInt32 (), - MajorVersion = buffer.ReadInt16 (), - MinorVersion = buffer.ReadInt16 (), - Type = buffer.ReadInt32 (), - SizeOfData = buffer.ReadInt32 (), - AddressOfRawData = buffer.ReadInt32 (), - PointerToRawData = buffer.ReadInt32 (), - }; - - if (directory.SizeOfData == 0 || directory.PointerToRawData == 0) { + var reader = GetReaderAt (Debug.VirtualAddress); + if (reader == null) { header = Empty.Array; - return directory; + return new ImageDebugDirectory (); } - buffer.position = (int) (directory.PointerToRawData - section.PointerToRawData); + var directory = new ImageDebugDirectory { + Characteristics = reader.ReadInt32 (), + TimeDateStamp = reader.ReadInt32 (), + MajorVersion = reader.ReadInt16 (), + MinorVersion = reader.ReadInt16 (), + Type = reader.ReadInt32 (), + SizeOfData = reader.ReadInt32 (), + AddressOfRawData = reader.ReadInt32 (), + PointerToRawData = reader.ReadInt32 (), + }; - header = new byte [directory.SizeOfData]; - Buffer.BlockCopy (buffer.buffer, buffer.position, header, 0, header.Length); + reader = GetReaderAt ((uint) directory.AddressOfRawData); + header = reader != null + ? reader.ReadBytes (directory.SizeOfData) + : Empty.Array; return directory; } + + public bool HasDebugTables () + { + return HasTable (Table.Document) + || HasTable (Table.MethodDebugInformation) + || HasTable (Table.LocalScope) + || HasTable (Table.LocalVariable) + || HasTable (Table.LocalConstant) + || HasTable (Table.StateMachineMethod) + || HasTable (Table.CustomDebugInformation); + } + + public void Dispose () + { + Stream.Dispose (); + } } } diff --git a/external/cecil/Mono.Cecil.PE/ImageReader.cs b/external/cecil/Mono.Cecil.PE/ImageReader.cs index c96c1db318..fc6b4fcbe0 100644 --- a/external/cecil/Mono.Cecil.PE/ImageReader.cs +++ b/external/cecil/Mono.Cecil.PE/ImageReader.cs @@ -1,29 +1,11 @@ // -// ImageReader.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; @@ -42,12 +24,14 @@ namespace Mono.Cecil.PE { DataDirectory cli; DataDirectory metadata; - public ImageReader (Stream stream) - : base (stream) + uint table_heap_offset; + + public ImageReader (Disposable stream, string file_name) + : base (stream.value) { image = new Image (); - - image.FileName = stream.GetFullyQualifiedName (); + image.Stream = stream; + image.FileName = file_name; } void MoveTo (DataDirectory directory) @@ -55,11 +39,6 @@ namespace Mono.Cecil.PE { BaseStream.Position = image.ResolveVirtualAddress (directory.VirtualAddress); } - void MoveTo (uint position) - { - BaseStream.Position = position; - } - void ReadImage () { if (BaseStream.Length < 128) @@ -279,31 +258,11 @@ namespace Mono.Cecil.PE { Advance (16); sections [i] = section; - - ReadSectionData (section); } image.Sections = sections; } - void ReadSectionData (Section section) - { - var position = BaseStream.Position; - - MoveTo (section.PointerToRawData); - - var length = (int) section.SizeOfRawData; - var data = new byte [length]; - int offset = 0, read; - - while ((read = Read (data, offset, length - offset)) > 0) - offset += read; - - section.Data = data; - - BaseStream.Position = position; - } - void ReadCLIHeader () { MoveTo (cli); @@ -343,8 +302,7 @@ namespace Mono.Cecil.PE { // Reserved 4 Advance (8); - var version = ReadZeroTerminatedString (ReadInt32 ()); - image.Runtime = version.ParseRuntime (); + image.RuntimeVersion = ReadZeroTerminatedString (ReadInt32 ()); // Flags 2 Advance (2); @@ -362,44 +320,61 @@ namespace Mono.Cecil.PE { if (image.TableHeap != null) ReadTableHeap (); + + if (image.PdbHeap != null) + ReadPdbHeap (); } void ReadMetadataStream (Section section) { // Offset 4 - uint start = metadata.VirtualAddress - section.VirtualAddress + ReadUInt32 (); // relative to the section start + uint offset = metadata.VirtualAddress - section.VirtualAddress + ReadUInt32 (); // relative to the section start // Size 4 uint size = ReadUInt32 (); + var data = ReadHeapData (offset, size); + var name = ReadAlignedString (16); switch (name) { case "#~": case "#-": - image.TableHeap = new TableHeap (section, start, size); + image.TableHeap = new TableHeap (data); + table_heap_offset = offset; break; case "#Strings": - image.StringHeap = new StringHeap (section, start, size); + image.StringHeap = new StringHeap (data); break; case "#Blob": - image.BlobHeap = new BlobHeap (section, start, size); + image.BlobHeap = new BlobHeap (data); break; case "#GUID": - image.GuidHeap = new GuidHeap (section, start, size); + image.GuidHeap = new GuidHeap (data); break; case "#US": - image.UserStringHeap = new UserStringHeap (section, start, size); + image.UserStringHeap = new UserStringHeap (data); + break; + case "#Pdb": + image.PdbHeap = new PdbHeap (data); break; } } + byte [] ReadHeapData (uint offset, uint size) + { + var position = BaseStream.Position; + MoveTo (offset + image.MetadataSection.PointerToRawData); + var data = ReadBytes ((int) size); + BaseStream.Position = position; + + return data; + } + void ReadTableHeap () { var heap = image.TableHeap; - uint start = heap.Section.PointerToRawData; - - MoveTo (heap.Offset + start); + MoveTo (table_heap_offset + image.MetadataSection.PointerToRawData); // Reserved 4 // MajorVersion 1 @@ -418,7 +393,7 @@ namespace Mono.Cecil.PE { // Sorted 8 heap.Sorted = ReadInt64 (); - for (int i = 0; i < TableHeap.TableCount; i++) { + for (int i = 0; i < Mixin.TableCount; i++) { if (!heap.HasTable ((Table) i)) continue; @@ -452,15 +427,16 @@ namespace Mono.Cecil.PE { void ComputeTableInformations () { - uint offset = (uint) BaseStream.Position - image.MetadataSection.PointerToRawData; // header + uint offset = (uint) BaseStream.Position - table_heap_offset - image.MetadataSection.PointerToRawData; // header int stridx_size = image.StringHeap.IndexSize; + int guididx_size = image.GuidHeap.IndexSize; int blobidx_size = image.BlobHeap != null ? image.BlobHeap.IndexSize : 2; var heap = image.TableHeap; var tables = heap.Tables; - for (int i = 0; i < TableHeap.TableCount; i++) { + for (int i = 0; i < Mixin.TableCount; i++) { var table = (Table) i; if (!heap.HasTable (table)) continue; @@ -470,7 +446,7 @@ namespace Mono.Cecil.PE { case Table.Module: size = 2 // Generation + stridx_size // Name - + (image.GuidHeap.IndexSize * 3); // Mvid, EncId, EncBaseId + + (guididx_size * 3); // Mvid, EncId, EncBaseId break; case Table.TypeRef: size = GetCodedIndexSize (CodedIndex.ResolutionScope) // ResolutionScope @@ -597,6 +573,8 @@ namespace Mono.Cecil.PE { + GetTableIndexSize (Table.Field); // Field break; case Table.EncLog: + size = 8; + break; case Table.EncMap: size = 4; break; @@ -656,6 +634,45 @@ namespace Mono.Cecil.PE { size = GetTableIndexSize (Table.GenericParam) // Owner + GetCodedIndexSize (CodedIndex.TypeDefOrRef); // Constraint break; + case Table.Document: + size = blobidx_size // Name + + guididx_size // HashAlgorithm + + blobidx_size // Hash + + guididx_size; // Language + break; + case Table.MethodDebugInformation: + size = GetTableIndexSize (Table.Document) // Document + + blobidx_size; // SequencePoints + break; + case Table.LocalScope: + size = GetTableIndexSize (Table.Method) // Method + + GetTableIndexSize (Table.ImportScope) // ImportScope + + GetTableIndexSize (Table.LocalVariable) // VariableList + + GetTableIndexSize (Table.LocalConstant) // ConstantList + + 4 * 2; // StartOffset, Length + break; + case Table.LocalVariable: + size = 2 // Attributes + + 2 // Index + + stridx_size; // Name + break; + case Table.LocalConstant: + size = stridx_size // Name + + blobidx_size; // Signature + break; + case Table.ImportScope: + size = GetTableIndexSize (Table.ImportScope) // Parent + + blobidx_size; + break; + case Table.StateMachineMethod: + size = GetTableIndexSize (Table.Method) // MoveNextMethod + + GetTableIndexSize (Table.Method); // KickOffMethod + break; + case Table.CustomDebugInformation: + size = GetCodedIndexSize (CodedIndex.HasCustomDebugInformation) // Parent + + guididx_size // Kind + + blobidx_size; // Value + break; default: throw new NotSupportedException (); } @@ -667,14 +684,57 @@ namespace Mono.Cecil.PE { } } - public static Image ReadImageFrom (Stream stream) + void ReadPdbHeap () + { + var heap = image.PdbHeap; + + var buffer = new ByteBuffer (heap.data); + + heap.Id = buffer.ReadBytes (20); + heap.EntryPoint = buffer.ReadUInt32 (); + heap.TypeSystemTables = buffer.ReadInt64 (); + heap.TypeSystemTableRows = new uint [Mixin.TableCount]; + + for (int i = 0; i < Mixin.TableCount; i++) { + var table = (Table) i; + if (!heap.HasTable (table)) + continue; + + heap.TypeSystemTableRows [i] = buffer.ReadUInt32 (); + } + } + + public static Image ReadImage (Disposable stream, string file_name) { try { - var reader = new ImageReader (stream); + var reader = new ImageReader (stream, file_name); reader.ReadImage (); return reader.image; } catch (EndOfStreamException e) { - throw new BadImageFormatException (stream.GetFullyQualifiedName (), e); + throw new BadImageFormatException (stream.value.GetFileName (), e); + } + } + + public static Image ReadPortablePdb (Disposable stream, string file_name) + { + try { + var reader = new ImageReader (stream, file_name); + var length = (uint) stream.value.Length; + + reader.image.Sections = new[] { + new Section { + PointerToRawData = 0, + SizeOfRawData = length, + VirtualAddress = 0, + VirtualSize = length, + } + }; + + reader.metadata = new DataDirectory (0, length); + reader.ReadMetadata (); + return reader.image; + } catch (EndOfStreamException e) { + throw new BadImageFormatException (stream.value.GetFileName (), e); } } } diff --git a/external/cecil/Mono.Cecil.PE/ImageWriter.cs b/external/cecil/Mono.Cecil.PE/ImageWriter.cs index 08f9ea2b76..95d39cb590 100644 --- a/external/cecil/Mono.Cecil.PE/ImageWriter.cs +++ b/external/cecil/Mono.Cecil.PE/ImageWriter.cs @@ -1,29 +1,11 @@ // -// ImageWriter.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; @@ -43,13 +25,16 @@ namespace Mono.Cecil.PE { readonly ModuleDefinition module; readonly MetadataBuilder metadata; readonly TextMap text_map; + readonly internal Disposable stream; + + readonly string runtime_version; ImageDebugDirectory debug_directory; byte [] debug_data; ByteBuffer win32_resources; - const uint pe_header_size = 0x178u; + const uint pe_header_size = 0x98u; const uint section_header_size = 0x28u; const uint file_alignment = 0x200; const uint section_alignment = 0x2000; @@ -59,7 +44,6 @@ namespace Mono.Cecil.PE { readonly bool pe64; readonly bool has_reloc; - readonly uint time_stamp; internal Section text; internal Section rsrc; @@ -67,18 +51,23 @@ namespace Mono.Cecil.PE { ushort sections; - ImageWriter (ModuleDefinition module, MetadataBuilder metadata, Stream stream) - : base (stream) + ImageWriter (ModuleDefinition module, string runtime_version, MetadataBuilder metadata, Disposable stream, bool metadataOnly = false) + : base (stream.value) { this.module = module; + this.runtime_version = runtime_version; + this.text_map = metadata.text_map; + this.stream = stream; this.metadata = metadata; + if (metadataOnly) + return; + this.pe64 = module.Architecture == TargetArchitecture.AMD64 || module.Architecture == TargetArchitecture.IA64; this.has_reloc = module.Architecture == TargetArchitecture.I386; this.GetDebugHeader (); this.GetWin32Resources (); - this.text_map = BuildTextMap (); + this.BuildTextMap (); this.sections = (ushort) (has_reloc ? 2 : 1); // text + reloc? - this.time_stamp = (uint) DateTime.UtcNow.Subtract (new DateTime (1970, 1, 1)).TotalSeconds; } void GetDebugHeader () @@ -97,9 +86,7 @@ namespace Mono.Cecil.PE { if (rsrc == null) return; - var raw_resources = new byte [rsrc.Data.Length]; - Buffer.BlockCopy (rsrc.Data, 0, raw_resources, 0, rsrc.Data.Length); - win32_resources = new ByteBuffer (raw_resources); + win32_resources = module.Image.GetReaderAt (rsrc.VirtualAddress, rsrc.SizeOfRawData, (s, reader) => new ByteBuffer (reader.ReadBytes ((int) s))); } Section GetImageResourceSection () @@ -112,13 +99,21 @@ namespace Mono.Cecil.PE { return module.Image.GetSection (rsrc_section); } - public static ImageWriter CreateWriter (ModuleDefinition module, MetadataBuilder metadata, Stream stream) + public static ImageWriter CreateWriter (ModuleDefinition module, MetadataBuilder metadata, Disposable stream) { - var writer = new ImageWriter (module, metadata, stream); + var writer = new ImageWriter (module, module.runtime_version, metadata, stream); writer.BuildSections (); return writer; } + public static ImageWriter CreateDebugWriter (ModuleDefinition module, MetadataBuilder metadata, Disposable stream) + { + var writer = new ImageWriter (module, "PDB V1.0", metadata, stream, metadataOnly: true); + var length = metadata.text_map.GetLength (); + writer.text = new Section { SizeOfRawData = length, VirtualSize = length }; + return writer; + } + void BuildSections () { var has_win32_resources = win32_resources != null; @@ -189,15 +184,20 @@ namespace Mono.Cecil.PE { }); } + ushort SizeOfOptionalHeader () + { + return (ushort) (!pe64 ? 0xe0 : 0xf0); + } + void WritePEFileHeader () { WriteUInt32 (0x00004550); // Magic WriteUInt16 (GetMachine ()); // Machine WriteUInt16 (sections); // NumberOfSections - WriteUInt32 (time_stamp); + WriteUInt32 (metadata.time_stamp); WriteUInt32 (0); // PointerToSymbolTable WriteUInt32 (0); // NumberOfSymbols - WriteUInt16 ((ushort) (!pe64 ? 0xe0 : 0xf0)); // SizeOfOptionalHeader + WriteUInt16 (SizeOfOptionalHeader ()); // SizeOfOptionalHeader // ExecutableImage | (pe64 ? 32BitsMachine : LargeAddressAware) var characteristics = (ushort) (0x0002 | (!pe64 ? 0x0100 : 0x0020)); @@ -396,9 +396,32 @@ namespace Mono.Cecil.PE { WriteUInt64 (rva); } + void PrepareSection (Section section) + { + MoveTo (section.PointerToRawData); + + const int buffer_size = 4096; + + if (section.SizeOfRawData <= buffer_size) { + Write (new byte [section.SizeOfRawData]); + MoveTo (section.PointerToRawData); + return; + } + + var written = 0; + var buffer = new byte [buffer_size]; + while (written != section.SizeOfRawData) { + var write_size = System.Math.Min((int) section.SizeOfRawData - written, buffer_size); + Write (buffer, 0, write_size); + written += write_size; + } + + MoveTo (section.PointerToRawData); + } + void WriteText () { - MoveTo (text.PointerToRawData); + PrepareSection (text); // ImportAddressTable @@ -474,14 +497,14 @@ namespace Mono.Cecil.PE { return text_map.GetRVA (TextSegment.DebugDirectory) - text_map.GetRVA (TextSegment.MetadataHeader); } - void WriteMetadataHeader () + public void WriteMetadataHeader () { WriteUInt32 (0x424a5342); // Signature WriteUInt16 (1); // MajorVersion WriteUInt16 (1); // MinorVersion WriteUInt32 (0); // Reserved - var version = GetZeroTerminatedString (GetVersion ()); + var version = GetZeroTerminatedString (runtime_version); WriteUInt32 ((uint) version.Length); WriteBytes (version); WriteUInt16 (0); // Flags @@ -494,21 +517,7 @@ namespace Mono.Cecil.PE { WriteStreamHeader (ref offset, TextSegment.UserStringHeap, "#US"); WriteStreamHeader (ref offset, TextSegment.GuidHeap, "#GUID"); WriteStreamHeader (ref offset, TextSegment.BlobHeap, "#Blob"); - } - - string GetVersion () - { - switch (module.Runtime) { - case TargetRuntime.Net_1_0: - return "v1.0.3705"; - case TargetRuntime.Net_1_1: - return "v1.1.4322"; - case TargetRuntime.Net_2_0: - return "v2.0.50727"; - case TargetRuntime.Net_4_0: - default: - return "v4.0.30319"; - } + WriteStreamHeader (ref offset, TextSegment.PdbHeap, "#Pdb"); } ushort GetStreamCount () @@ -518,7 +527,8 @@ namespace Mono.Cecil.PE { + 1 // #Strings + (metadata.user_string_heap.IsEmpty ? 0 : 1) // #US + 1 // GUID - + (metadata.blob_heap.IsEmpty ? 0 : 1)); // #Blob + + (metadata.blob_heap.IsEmpty ? 0 : 1) + + (metadata.pdb_heap == null ? 0 : 1)); // #Blob } void WriteStreamHeader (ref uint offset, TextSegment heap, string name) @@ -533,9 +543,14 @@ namespace Mono.Cecil.PE { offset += length; } + static int GetZeroTerminatedStringLength (string @string) + { + return (@string.Length + 1 + 3) & ~3; + } + static byte [] GetZeroTerminatedString (string @string) { - return GetString (@string, (@string.Length + 1 + 3) & ~3); + return GetString (@string, GetZeroTerminatedStringLength (@string)); } static byte [] GetSimpleString (string @string) @@ -552,34 +567,29 @@ namespace Mono.Cecil.PE { return bytes; } - void WriteMetadata () + public void WriteMetadata () { WriteHeap (TextSegment.TableHeap, metadata.table_heap); WriteHeap (TextSegment.StringHeap, metadata.string_heap); WriteHeap (TextSegment.UserStringHeap, metadata.user_string_heap); - WriteGuidHeap (); + WriteHeap (TextSegment.GuidHeap, metadata.guid_heap); WriteHeap (TextSegment.BlobHeap, metadata.blob_heap); + WriteHeap (TextSegment.PdbHeap, metadata.pdb_heap); } void WriteHeap (TextSegment heap, HeapBuffer buffer) { - if (buffer.IsEmpty) + if (buffer == null || buffer.IsEmpty) return; MoveToRVA (heap); WriteBuffer (buffer); } - void WriteGuidHeap () - { - MoveToRVA (TextSegment.GuidHeap); - WriteBytes (module.Mvid.ToByteArray ()); - } - void WriteDebugDirectory () { WriteInt32 (debug_directory.Characteristics); - WriteUInt32 (time_stamp); + WriteUInt32 (metadata.time_stamp); WriteInt16 (debug_directory.MajorVersion); WriteInt16 (debug_directory.MinorVersion); WriteInt32 (debug_directory.Type); @@ -633,13 +643,13 @@ namespace Mono.Cecil.PE { void WriteRsrc () { - MoveTo (rsrc.PointerToRawData); + PrepareSection (rsrc); WriteBuffer (win32_resources); } void WriteReloc () { - MoveTo (reloc.PointerToRawData); + PrepareSection (reloc); var reloc_rva = text_map.GetRVA (TextSegment.StartupStub); reloc_rva += module.Architecture == TargetArchitecture.IA64 ? 0x20u : 2; @@ -655,8 +665,6 @@ namespace Mono.Cecil.PE { default: throw new NotSupportedException(); } - - WriteBytes (new byte [file_alignment - reloc.VirtualSize]); } public void WriteImage () @@ -672,9 +680,9 @@ namespace Mono.Cecil.PE { WriteReloc (); } - TextMap BuildTextMap () + void BuildTextMap () { - var map = metadata.text_map; + var map = text_map; map.AddMap (TextSegment.Code, metadata.code.length, !pe64 ? 4 : 16); map.AddMap (TextSegment.Resources, metadata.resources.length, 8); @@ -683,12 +691,7 @@ namespace Mono.Cecil.PE { metadata.table_heap.FixupData (map.GetRVA (TextSegment.Data)); map.AddMap (TextSegment.StrongNameSignature, GetStrongNameLength (), 4); - map.AddMap (TextSegment.MetadataHeader, GetMetadataHeaderLength ()); - map.AddMap (TextSegment.TableHeap, metadata.table_heap.length, 4); - map.AddMap (TextSegment.StringHeap, metadata.string_heap.length, 4); - map.AddMap (TextSegment.UserStringHeap, metadata.user_string_heap.IsEmpty ? 0 : metadata.user_string_heap.length, 4); - map.AddMap (TextSegment.GuidHeap, 16); - map.AddMap (TextSegment.BlobHeap, metadata.blob_heap.IsEmpty ? 0 : metadata.blob_heap.length, 4); + BuildMetadataTextMap (); int debug_dir_len = 0; if (!debug_data.IsNullOrEmpty ()) { @@ -705,7 +708,7 @@ namespace Mono.Cecil.PE { map.AddMap (TextSegment.ImportDirectory, new Range (start, 0)); map.AddMap (TextSegment.ImportHintNameTable, new Range (start, 0)); map.AddMap (TextSegment.StartupStub, new Range (start, 0)); - return map; + return; } RVA import_dir_rva = map.GetNextRVA (TextSegment.DebugDirectory); @@ -721,8 +724,19 @@ namespace Mono.Cecil.PE { map.AddMap (TextSegment.ImportDirectory, new Range (import_dir_rva, import_dir_len)); map.AddMap (TextSegment.ImportHintNameTable, new Range (import_hnt_rva, 0)); map.AddMap (TextSegment.StartupStub, new Range (startup_stub_rva, GetStartupStubLength ())); + } - return map; + public void BuildMetadataTextMap () + { + var map = text_map; + + map.AddMap (TextSegment.MetadataHeader, GetMetadataHeaderLength (module.RuntimeVersion)); + map.AddMap (TextSegment.TableHeap, metadata.table_heap.length, 4); + map.AddMap (TextSegment.StringHeap, metadata.string_heap.length, 4); + map.AddMap (TextSegment.UserStringHeap, metadata.user_string_heap.IsEmpty ? 0 : metadata.user_string_heap.length, 4); + map.AddMap (TextSegment.GuidHeap, metadata.guid_heap.length, 4); + map.AddMap (TextSegment.BlobHeap, metadata.blob_heap.IsEmpty ? 0 : metadata.blob_heap.length, 4); + map.AddMap (TextSegment.PdbHeap, metadata.pdb_heap == null ? 0 : metadata.pdb_heap.length, 4); } uint GetStartupStubLength () @@ -735,11 +749,11 @@ namespace Mono.Cecil.PE { } } - int GetMetadataHeaderLength () + int GetMetadataHeaderLength (string runtimeVersion) { return // MetadataHeader - 40 + 20 + GetZeroTerminatedStringLength (runtimeVersion) // #~ header + 12 // #Strings header @@ -749,7 +763,9 @@ namespace Mono.Cecil.PE { // #GUID header + 16 // #Blob header - + (metadata.blob_heap.IsEmpty ? 0 : 16); + + (metadata.blob_heap.IsEmpty ? 0 : 16) + // + + (metadata.pdb_heap == null ? 0 : 16); } int GetStrongNameLength () @@ -781,7 +797,7 @@ namespace Mono.Cecil.PE { public uint GetHeaderSize () { - return pe_header_size + (sections * section_header_size); + return pe_header_size + SizeOfOptionalHeader () + (sections * section_header_size); } void PatchWin32Resources (ByteBuffer resources) diff --git a/external/cecil/Mono.Cecil.PE/Section.cs b/external/cecil/Mono.Cecil.PE/Section.cs index 6a4c7bab79..49d8e90011 100644 --- a/external/cecil/Mono.Cecil.PE/Section.cs +++ b/external/cecil/Mono.Cecil.PE/Section.cs @@ -1,29 +1,11 @@ // -// Section.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; @@ -38,6 +20,5 @@ namespace Mono.Cecil.PE { public uint VirtualSize; public uint SizeOfRawData; public uint PointerToRawData; - public byte [] Data; } } diff --git a/external/cecil/Mono.Cecil.PE/TextMap.cs b/external/cecil/Mono.Cecil.PE/TextMap.cs index 047a4c1d47..614691b6ad 100644 --- a/external/cecil/Mono.Cecil.PE/TextMap.cs +++ b/external/cecil/Mono.Cecil.PE/TextMap.cs @@ -1,29 +1,11 @@ // -// TextMap.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; @@ -49,6 +31,7 @@ namespace Mono.Cecil.PE { UserStringHeap, GuidHeap, BlobHeap, + PdbHeap, // End Metadata DebugDirectory, @@ -59,7 +42,7 @@ namespace Mono.Cecil.PE { sealed class TextMap { - readonly Range [] map = new Range [16 /*Enum.GetValues (typeof (TextSegment)).Length*/]; + readonly Range [] map = new Range [17 /*Enum.GetValues (typeof (TextSegment)).Length*/]; public void AddMap (TextSegment segment, int length) { diff --git a/external/cecil/Mono.Cecil.Tests.props b/external/cecil/Mono.Cecil.Tests.props new file mode 100644 index 0000000000..e1290901b2 --- /dev/null +++ b/external/cecil/Mono.Cecil.Tests.props @@ -0,0 +1,21 @@ + + + + $(MSBuildProjectDirectory) + + + + + False + $(MSBuildThisFileDirectory)\Test\libs\nunit-2.6.2\nunit.core.dll + + + False + $(MSBuildThisFileDirectory)\Test\libs\nunit-2.6.2\nunit.core.interfaces.dll + + + False + $(MSBuildThisFileDirectory)\Test\libs\nunit-2.6.2\nunit.framework.dll + + + diff --git a/external/cecil/Mono.Cecil.csproj b/external/cecil/Mono.Cecil.csproj index 3a237c11b0..8aacd3a35e 100644 --- a/external/cecil/Mono.Cecil.csproj +++ b/external/cecil/Mono.Cecil.csproj @@ -1,264 +1,21 @@ - net_4_0_Debug - AnyCPU - 9.0.30729 - 2.0 {D68133BD-1E63-496E-9EDE-4FBDBF77B486} - Library - Properties Mono.Cecil Mono.Cecil - 512 - true - mono.snk - - true - full - false - bin\net_2_0_Debug\ - DEBUG;TRACE - prompt - 4 - v2.0 - - - pdbonly - true - bin\net_2_0_Release\ - TRACE - prompt - 4 - v2.0 - - - true - full - false - bin\net_3_5_Debug\ - DEBUG;TRACE;NET_3_5 - prompt - 4 - v3.5 - - - pdbonly - true - bin\net_3_5_Release\ - TRACE;NET_3_5 - prompt - 4 - v3.5 - - - true - full - false - bin\net_4_0_Debug\ - DEBUG;TRACE;NET_3_5;NET_4_0 - prompt - 4 - v4.0 - - - pdbonly - true - bin\net_4_0_Release\ - TRACE;NET_3_5;NET_4_0 - prompt - 4 - v4.0 - - - true - full - false - bin\silverlight_Debug\ - DEBUG;TRACE;NET_3_5;NET_4_0;SILVERLIGHT - prompt - 4 - Silverlight - v4.0 - - - pdbonly - true - bin\silverlight_Release\ - TRACE;NET_3_5;NET_4_0;SILVERLIGHT - prompt - 4 - Silverlight - v4.0 - - - true - full - false - bin\winphone_Debug\ - DEBUG;TRACE;NET_3_5;NET_4_0;SILVERLIGHT;CF - prompt - 4 - WindowsPhone - Silverlight - v4.0 - - - pdbonly - true - bin\winphone_Release\ - TRACE;NET_3_5;NET_4_0;SILVERLIGHT;CF - prompt - 4 - WindowsPhone - Silverlight - v4.0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + - - - - - - - - + + \ No newline at end of file diff --git a/external/cecil/Mono.Cecil.nunit b/external/cecil/Mono.Cecil.nunit old mode 100755 new mode 100644 index 1cb0ebab1e..6bab390eee --- a/external/cecil/Mono.Cecil.nunit +++ b/external/cecil/Mono.Cecil.nunit @@ -1,9 +1,9 @@ - - - - - - + + + + + + diff --git a/external/cecil/Mono.Cecil.nuspec b/external/cecil/Mono.Cecil.nuspec index 9901dfcf2c..b19d8e9caf 100644 --- a/external/cecil/Mono.Cecil.nuspec +++ b/external/cecil/Mono.Cecil.nuspec @@ -2,7 +2,7 @@ Mono.Cecil - 0.9.5.4 + 0.10.0.0-beta1-v2 Mono.Cecil Jb Evain Jb Evain @@ -13,11 +13,26 @@ Cecil is a library written by Jb Evain to generate and inspect programs and libraries in the ECMA CIL format. It has full support for generics, and support some debugging symbol format. In simple English, with Cecil, you can load existing managed assemblies, browse all the contained types, modify them on the fly and save back to the disk the modified assembly. en-US assembly assemblies module modules il cil msil bytecode reflection injection cecil mono aop + + + + + + + + + + + + + + + - - + + diff --git a/external/cecil/Mono.Cecil.props b/external/cecil/Mono.Cecil.props new file mode 100644 index 0000000000..d25daa1992 --- /dev/null +++ b/external/cecil/Mono.Cecil.props @@ -0,0 +1,99 @@ + + + + net_4_0_Debug + AnyCPU + $(MSBuildThisFileDirectory) + 512 + 2.0 + Library + true + $(MSBuildThisFileDirectory)\mono.snk + Library + $(BuildDirectory)\bin\$(Configuration)\ + $(MSBuildToolsPath)\Microsoft.CSharp.targets + + + true + full + false + $(DefineConstants);DEBUG;TRACE; + prompt + 4 + + + pdbonly + true + $(DefineConstants);TRACE; + prompt + 4 + false + + + v3.5 + $(DefineConstants); + + + v4.0 + $(DefineConstants);NET_4_0; + + + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Profile344 + v4.0 + $(DefineConstants);NET_4_0;PCL; + $(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets + + + + + + + + + + + + + + + + + + + + + + $([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), Mono.Cecil.overrides))\Mono.Cecil.overrides + + + + + + diff --git a/external/cecil/Mono.Cecil.sln b/external/cecil/Mono.Cecil.sln index 7f2eda7f98..1043daf39b 100644 --- a/external/cecil/Mono.Cecil.sln +++ b/external/cecil/Mono.Cecil.sln @@ -1,5 +1,7 @@ -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{74E5ECE0-06B4-401C-AEBA-E8DD53E17943}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Symbols", "Symbols", "{929D5B3B-E29A-40CC-93D8-0FF43A6F9FA1}" @@ -8,8 +10,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Cecil", "Mono.Cecil.cs EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Cecil.Tests", "Test\Mono.Cecil.Tests.csproj", "{A47B1F49-A81A-43E8-BE6B-DD28AF2C4055}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "dbg", "dbg\dbg.csproj", "{89A775F3-64AB-485E-B958-60C25254B732}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Cecil.Mdb", "symbols\mdb\Mono.Cecil.Mdb.csproj", "{8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Cecil.Mdb.Tests", "symbols\mdb\Test\Mono.Cecil.Mdb.Tests.csproj", "{AC71DF9C-99FA-4A63-990A-66C8010355A6}" @@ -24,22 +24,16 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Cecil.Rocks", "rocks\M EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution - net_2_0_Debug|Any CPU = net_2_0_Debug|Any CPU - net_2_0_Release|Any CPU = net_2_0_Release|Any CPU net_3_5_Debug|Any CPU = net_3_5_Debug|Any CPU net_3_5_Release|Any CPU = net_3_5_Release|Any CPU net_4_0_Debug|Any CPU = net_4_0_Debug|Any CPU net_4_0_Release|Any CPU = net_4_0_Release|Any CPU - silverlight_Debug|Any CPU = silverlight_Debug|Any CPU - silverlight_Release|Any CPU = silverlight_Release|Any CPU - winphone_Debug|Any CPU = winphone_Debug|Any CPU - winphone_Release|Any CPU = winphone_Release|Any CPU + net_4_5_Debug|Any CPU = net_4_5_Debug|Any CPU + net_4_5_Release|Any CPU = net_4_5_Release|Any CPU + pcl_Debug|Any CPU = pcl_Debug|Any CPU + pcl_Release|Any CPU = pcl_Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.net_2_0_Debug|Any CPU.ActiveCfg = net_2_0_Debug|Any CPU - {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.net_2_0_Debug|Any CPU.Build.0 = net_2_0_Debug|Any CPU - {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.net_2_0_Release|Any CPU.ActiveCfg = net_2_0_Release|Any CPU - {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.net_2_0_Release|Any CPU.Build.0 = net_2_0_Release|Any CPU {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.net_3_5_Debug|Any CPU.ActiveCfg = net_3_5_Debug|Any CPU {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.net_3_5_Debug|Any CPU.Build.0 = net_3_5_Debug|Any CPU {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.net_3_5_Release|Any CPU.ActiveCfg = net_3_5_Release|Any CPU @@ -48,18 +42,14 @@ Global {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.net_4_0_Debug|Any CPU.Build.0 = net_4_0_Debug|Any CPU {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.net_4_0_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.net_4_0_Release|Any CPU.Build.0 = net_4_0_Release|Any CPU - {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.silverlight_Debug|Any CPU.ActiveCfg = silverlight_Debug|Any CPU - {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.silverlight_Debug|Any CPU.Build.0 = silverlight_Debug|Any CPU - {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.silverlight_Release|Any CPU.ActiveCfg = silverlight_Release|Any CPU - {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.silverlight_Release|Any CPU.Build.0 = silverlight_Release|Any CPU - {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.winphone_Debug|Any CPU.ActiveCfg = winphone_Debug|Any CPU - {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.winphone_Debug|Any CPU.Build.0 = winphone_Debug|Any CPU - {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.winphone_Release|Any CPU.ActiveCfg = winphone_Release|Any CPU - {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.winphone_Release|Any CPU.Build.0 = winphone_Release|Any CPU - {A47B1F49-A81A-43E8-BE6B-DD28AF2C4055}.net_2_0_Debug|Any CPU.ActiveCfg = net_2_0_Debug|Any CPU - {A47B1F49-A81A-43E8-BE6B-DD28AF2C4055}.net_2_0_Debug|Any CPU.Build.0 = net_2_0_Debug|Any CPU - {A47B1F49-A81A-43E8-BE6B-DD28AF2C4055}.net_2_0_Release|Any CPU.ActiveCfg = net_2_0_Release|Any CPU - {A47B1F49-A81A-43E8-BE6B-DD28AF2C4055}.net_2_0_Release|Any CPU.Build.0 = net_2_0_Release|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.net_4_5_Debug|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.net_4_5_Debug|Any CPU.Build.0 = net_4_0_Release|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.net_4_5_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.net_4_5_Release|Any CPU.Build.0 = net_4_0_Release|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.pcl_Debug|Any CPU.ActiveCfg = pcl_Debug|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.pcl_Debug|Any CPU.Build.0 = pcl_Debug|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.pcl_Release|Any CPU.ActiveCfg = pcl_Release|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.pcl_Release|Any CPU.Build.0 = pcl_Release|Any CPU {A47B1F49-A81A-43E8-BE6B-DD28AF2C4055}.net_3_5_Debug|Any CPU.ActiveCfg = net_3_5_Debug|Any CPU {A47B1F49-A81A-43E8-BE6B-DD28AF2C4055}.net_3_5_Debug|Any CPU.Build.0 = net_3_5_Debug|Any CPU {A47B1F49-A81A-43E8-BE6B-DD28AF2C4055}.net_3_5_Release|Any CPU.ActiveCfg = net_3_5_Release|Any CPU @@ -68,28 +58,12 @@ Global {A47B1F49-A81A-43E8-BE6B-DD28AF2C4055}.net_4_0_Debug|Any CPU.Build.0 = net_4_0_Debug|Any CPU {A47B1F49-A81A-43E8-BE6B-DD28AF2C4055}.net_4_0_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU {A47B1F49-A81A-43E8-BE6B-DD28AF2C4055}.net_4_0_Release|Any CPU.Build.0 = net_4_0_Release|Any CPU - {A47B1F49-A81A-43E8-BE6B-DD28AF2C4055}.silverlight_Debug|Any CPU.ActiveCfg = net_4_0_Release|Any CPU - {A47B1F49-A81A-43E8-BE6B-DD28AF2C4055}.silverlight_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU - {A47B1F49-A81A-43E8-BE6B-DD28AF2C4055}.winphone_Debug|Any CPU.ActiveCfg = net_4_0_Release|Any CPU - {A47B1F49-A81A-43E8-BE6B-DD28AF2C4055}.winphone_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU - {89A775F3-64AB-485E-B958-60C25254B732}.net_2_0_Debug|Any CPU.ActiveCfg = net_4_0_Debug|Any CPU - {89A775F3-64AB-485E-B958-60C25254B732}.net_2_0_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU - {89A775F3-64AB-485E-B958-60C25254B732}.net_3_5_Debug|Any CPU.ActiveCfg = net_3_5_Debug|Any CPU - {89A775F3-64AB-485E-B958-60C25254B732}.net_3_5_Debug|Any CPU.Build.0 = net_3_5_Debug|Any CPU - {89A775F3-64AB-485E-B958-60C25254B732}.net_3_5_Release|Any CPU.ActiveCfg = net_3_5_Release|Any CPU - {89A775F3-64AB-485E-B958-60C25254B732}.net_3_5_Release|Any CPU.Build.0 = net_3_5_Release|Any CPU - {89A775F3-64AB-485E-B958-60C25254B732}.net_4_0_Debug|Any CPU.ActiveCfg = net_4_0_Debug|Any CPU - {89A775F3-64AB-485E-B958-60C25254B732}.net_4_0_Debug|Any CPU.Build.0 = net_4_0_Debug|Any CPU - {89A775F3-64AB-485E-B958-60C25254B732}.net_4_0_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU - {89A775F3-64AB-485E-B958-60C25254B732}.net_4_0_Release|Any CPU.Build.0 = net_4_0_Release|Any CPU - {89A775F3-64AB-485E-B958-60C25254B732}.silverlight_Debug|Any CPU.ActiveCfg = net_4_0_Release|Any CPU - {89A775F3-64AB-485E-B958-60C25254B732}.silverlight_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU - {89A775F3-64AB-485E-B958-60C25254B732}.winphone_Debug|Any CPU.ActiveCfg = net_4_0_Release|Any CPU - {89A775F3-64AB-485E-B958-60C25254B732}.winphone_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU - {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.net_2_0_Debug|Any CPU.ActiveCfg = net_2_0_Debug|Any CPU - {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.net_2_0_Debug|Any CPU.Build.0 = net_2_0_Debug|Any CPU - {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.net_2_0_Release|Any CPU.ActiveCfg = net_2_0_Release|Any CPU - {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.net_2_0_Release|Any CPU.Build.0 = net_2_0_Release|Any CPU + {A47B1F49-A81A-43E8-BE6B-DD28AF2C4055}.net_4_5_Debug|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {A47B1F49-A81A-43E8-BE6B-DD28AF2C4055}.net_4_5_Debug|Any CPU.Build.0 = net_4_0_Release|Any CPU + {A47B1F49-A81A-43E8-BE6B-DD28AF2C4055}.net_4_5_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {A47B1F49-A81A-43E8-BE6B-DD28AF2C4055}.net_4_5_Release|Any CPU.Build.0 = net_4_0_Release|Any CPU + {A47B1F49-A81A-43E8-BE6B-DD28AF2C4055}.pcl_Debug|Any CPU.ActiveCfg = net_4_0_Debug|Any CPU + {A47B1F49-A81A-43E8-BE6B-DD28AF2C4055}.pcl_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.net_3_5_Debug|Any CPU.ActiveCfg = net_3_5_Debug|Any CPU {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.net_3_5_Debug|Any CPU.Build.0 = net_3_5_Debug|Any CPU {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.net_3_5_Release|Any CPU.ActiveCfg = net_3_5_Release|Any CPU @@ -98,14 +72,12 @@ Global {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.net_4_0_Debug|Any CPU.Build.0 = net_4_0_Debug|Any CPU {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.net_4_0_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.net_4_0_Release|Any CPU.Build.0 = net_4_0_Release|Any CPU - {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.silverlight_Debug|Any CPU.ActiveCfg = net_4_0_Release|Any CPU - {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.silverlight_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU - {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.winphone_Debug|Any CPU.ActiveCfg = net_4_0_Release|Any CPU - {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.winphone_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU - {AC71DF9C-99FA-4A63-990A-66C8010355A6}.net_2_0_Debug|Any CPU.ActiveCfg = net_2_0_Debug|Any CPU - {AC71DF9C-99FA-4A63-990A-66C8010355A6}.net_2_0_Debug|Any CPU.Build.0 = net_2_0_Debug|Any CPU - {AC71DF9C-99FA-4A63-990A-66C8010355A6}.net_2_0_Release|Any CPU.ActiveCfg = net_2_0_Release|Any CPU - {AC71DF9C-99FA-4A63-990A-66C8010355A6}.net_2_0_Release|Any CPU.Build.0 = net_2_0_Release|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.net_4_5_Debug|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.net_4_5_Debug|Any CPU.Build.0 = net_4_0_Release|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.net_4_5_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.net_4_5_Release|Any CPU.Build.0 = net_4_0_Release|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.pcl_Debug|Any CPU.ActiveCfg = pcl_Debug|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.pcl_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU {AC71DF9C-99FA-4A63-990A-66C8010355A6}.net_3_5_Debug|Any CPU.ActiveCfg = net_3_5_Debug|Any CPU {AC71DF9C-99FA-4A63-990A-66C8010355A6}.net_3_5_Debug|Any CPU.Build.0 = net_3_5_Debug|Any CPU {AC71DF9C-99FA-4A63-990A-66C8010355A6}.net_3_5_Release|Any CPU.ActiveCfg = net_3_5_Release|Any CPU @@ -114,14 +86,12 @@ Global {AC71DF9C-99FA-4A63-990A-66C8010355A6}.net_4_0_Debug|Any CPU.Build.0 = net_4_0_Debug|Any CPU {AC71DF9C-99FA-4A63-990A-66C8010355A6}.net_4_0_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU {AC71DF9C-99FA-4A63-990A-66C8010355A6}.net_4_0_Release|Any CPU.Build.0 = net_4_0_Release|Any CPU - {AC71DF9C-99FA-4A63-990A-66C8010355A6}.silverlight_Debug|Any CPU.ActiveCfg = net_4_0_Release|Any CPU - {AC71DF9C-99FA-4A63-990A-66C8010355A6}.silverlight_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU - {AC71DF9C-99FA-4A63-990A-66C8010355A6}.winphone_Debug|Any CPU.ActiveCfg = net_4_0_Release|Any CPU - {AC71DF9C-99FA-4A63-990A-66C8010355A6}.winphone_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU - {63E6915C-7EA4-4D76-AB28-0D7191EEA626}.net_2_0_Debug|Any CPU.ActiveCfg = net_2_0_Debug|Any CPU - {63E6915C-7EA4-4D76-AB28-0D7191EEA626}.net_2_0_Debug|Any CPU.Build.0 = net_2_0_Debug|Any CPU - {63E6915C-7EA4-4D76-AB28-0D7191EEA626}.net_2_0_Release|Any CPU.ActiveCfg = net_2_0_Release|Any CPU - {63E6915C-7EA4-4D76-AB28-0D7191EEA626}.net_2_0_Release|Any CPU.Build.0 = net_2_0_Release|Any CPU + {AC71DF9C-99FA-4A63-990A-66C8010355A6}.net_4_5_Debug|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {AC71DF9C-99FA-4A63-990A-66C8010355A6}.net_4_5_Debug|Any CPU.Build.0 = net_4_0_Release|Any CPU + {AC71DF9C-99FA-4A63-990A-66C8010355A6}.net_4_5_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {AC71DF9C-99FA-4A63-990A-66C8010355A6}.net_4_5_Release|Any CPU.Build.0 = net_4_0_Release|Any CPU + {AC71DF9C-99FA-4A63-990A-66C8010355A6}.pcl_Debug|Any CPU.ActiveCfg = net_4_0_Debug|Any CPU + {AC71DF9C-99FA-4A63-990A-66C8010355A6}.pcl_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU {63E6915C-7EA4-4D76-AB28-0D7191EEA626}.net_3_5_Debug|Any CPU.ActiveCfg = net_3_5_Debug|Any CPU {63E6915C-7EA4-4D76-AB28-0D7191EEA626}.net_3_5_Debug|Any CPU.Build.0 = net_3_5_Debug|Any CPU {63E6915C-7EA4-4D76-AB28-0D7191EEA626}.net_3_5_Release|Any CPU.ActiveCfg = net_3_5_Release|Any CPU @@ -130,14 +100,12 @@ Global {63E6915C-7EA4-4D76-AB28-0D7191EEA626}.net_4_0_Debug|Any CPU.Build.0 = net_4_0_Debug|Any CPU {63E6915C-7EA4-4D76-AB28-0D7191EEA626}.net_4_0_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU {63E6915C-7EA4-4D76-AB28-0D7191EEA626}.net_4_0_Release|Any CPU.Build.0 = net_4_0_Release|Any CPU - {63E6915C-7EA4-4D76-AB28-0D7191EEA626}.silverlight_Debug|Any CPU.ActiveCfg = net_4_0_Release|Any CPU - {63E6915C-7EA4-4D76-AB28-0D7191EEA626}.silverlight_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU - {63E6915C-7EA4-4D76-AB28-0D7191EEA626}.winphone_Debug|Any CPU.ActiveCfg = net_4_0_Release|Any CPU - {63E6915C-7EA4-4D76-AB28-0D7191EEA626}.winphone_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU - {29300103-CB76-4A1D-B6FD-FFD91C1EC8AA}.net_2_0_Debug|Any CPU.ActiveCfg = net_2_0_Debug|Any CPU - {29300103-CB76-4A1D-B6FD-FFD91C1EC8AA}.net_2_0_Debug|Any CPU.Build.0 = net_2_0_Debug|Any CPU - {29300103-CB76-4A1D-B6FD-FFD91C1EC8AA}.net_2_0_Release|Any CPU.ActiveCfg = net_2_0_Release|Any CPU - {29300103-CB76-4A1D-B6FD-FFD91C1EC8AA}.net_2_0_Release|Any CPU.Build.0 = net_2_0_Release|Any CPU + {63E6915C-7EA4-4D76-AB28-0D7191EEA626}.net_4_5_Debug|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {63E6915C-7EA4-4D76-AB28-0D7191EEA626}.net_4_5_Debug|Any CPU.Build.0 = net_4_0_Release|Any CPU + {63E6915C-7EA4-4D76-AB28-0D7191EEA626}.net_4_5_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {63E6915C-7EA4-4D76-AB28-0D7191EEA626}.net_4_5_Release|Any CPU.Build.0 = net_4_0_Release|Any CPU + {63E6915C-7EA4-4D76-AB28-0D7191EEA626}.pcl_Debug|Any CPU.ActiveCfg = pcl_Debug|Any CPU + {63E6915C-7EA4-4D76-AB28-0D7191EEA626}.pcl_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU {29300103-CB76-4A1D-B6FD-FFD91C1EC8AA}.net_3_5_Debug|Any CPU.ActiveCfg = net_3_5_Debug|Any CPU {29300103-CB76-4A1D-B6FD-FFD91C1EC8AA}.net_3_5_Debug|Any CPU.Build.0 = net_3_5_Debug|Any CPU {29300103-CB76-4A1D-B6FD-FFD91C1EC8AA}.net_3_5_Release|Any CPU.ActiveCfg = net_3_5_Release|Any CPU @@ -146,12 +114,12 @@ Global {29300103-CB76-4A1D-B6FD-FFD91C1EC8AA}.net_4_0_Debug|Any CPU.Build.0 = net_4_0_Debug|Any CPU {29300103-CB76-4A1D-B6FD-FFD91C1EC8AA}.net_4_0_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU {29300103-CB76-4A1D-B6FD-FFD91C1EC8AA}.net_4_0_Release|Any CPU.Build.0 = net_4_0_Release|Any CPU - {29300103-CB76-4A1D-B6FD-FFD91C1EC8AA}.silverlight_Debug|Any CPU.ActiveCfg = net_4_0_Release|Any CPU - {29300103-CB76-4A1D-B6FD-FFD91C1EC8AA}.silverlight_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU - {29300103-CB76-4A1D-B6FD-FFD91C1EC8AA}.winphone_Debug|Any CPU.ActiveCfg = net_4_0_Release|Any CPU - {29300103-CB76-4A1D-B6FD-FFD91C1EC8AA}.winphone_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU - {C6CFD7E1-B855-44DC-B4CE-9CD72984AF52}.net_2_0_Debug|Any CPU.ActiveCfg = net_4_0_Release|Any CPU - {C6CFD7E1-B855-44DC-B4CE-9CD72984AF52}.net_2_0_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {29300103-CB76-4A1D-B6FD-FFD91C1EC8AA}.net_4_5_Debug|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {29300103-CB76-4A1D-B6FD-FFD91C1EC8AA}.net_4_5_Debug|Any CPU.Build.0 = net_4_0_Release|Any CPU + {29300103-CB76-4A1D-B6FD-FFD91C1EC8AA}.net_4_5_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {29300103-CB76-4A1D-B6FD-FFD91C1EC8AA}.net_4_5_Release|Any CPU.Build.0 = net_4_0_Release|Any CPU + {29300103-CB76-4A1D-B6FD-FFD91C1EC8AA}.pcl_Debug|Any CPU.ActiveCfg = net_4_0_Debug|Any CPU + {29300103-CB76-4A1D-B6FD-FFD91C1EC8AA}.pcl_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU {C6CFD7E1-B855-44DC-B4CE-9CD72984AF52}.net_3_5_Debug|Any CPU.ActiveCfg = net_3_5_Debug|Any CPU {C6CFD7E1-B855-44DC-B4CE-9CD72984AF52}.net_3_5_Debug|Any CPU.Build.0 = net_3_5_Debug|Any CPU {C6CFD7E1-B855-44DC-B4CE-9CD72984AF52}.net_3_5_Release|Any CPU.ActiveCfg = net_3_5_Release|Any CPU @@ -160,12 +128,12 @@ Global {C6CFD7E1-B855-44DC-B4CE-9CD72984AF52}.net_4_0_Debug|Any CPU.Build.0 = net_4_0_Debug|Any CPU {C6CFD7E1-B855-44DC-B4CE-9CD72984AF52}.net_4_0_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU {C6CFD7E1-B855-44DC-B4CE-9CD72984AF52}.net_4_0_Release|Any CPU.Build.0 = net_4_0_Release|Any CPU - {C6CFD7E1-B855-44DC-B4CE-9CD72984AF52}.silverlight_Debug|Any CPU.ActiveCfg = net_4_0_Release|Any CPU - {C6CFD7E1-B855-44DC-B4CE-9CD72984AF52}.silverlight_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU - {C6CFD7E1-B855-44DC-B4CE-9CD72984AF52}.winphone_Debug|Any CPU.ActiveCfg = net_4_0_Release|Any CPU - {C6CFD7E1-B855-44DC-B4CE-9CD72984AF52}.winphone_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU - {FBC6DD59-D09D-499C-B03C-99C1C78FF2AC}.net_2_0_Debug|Any CPU.ActiveCfg = net_4_0_Release|Any CPU - {FBC6DD59-D09D-499C-B03C-99C1C78FF2AC}.net_2_0_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {C6CFD7E1-B855-44DC-B4CE-9CD72984AF52}.net_4_5_Debug|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {C6CFD7E1-B855-44DC-B4CE-9CD72984AF52}.net_4_5_Debug|Any CPU.Build.0 = net_4_0_Release|Any CPU + {C6CFD7E1-B855-44DC-B4CE-9CD72984AF52}.net_4_5_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {C6CFD7E1-B855-44DC-B4CE-9CD72984AF52}.net_4_5_Release|Any CPU.Build.0 = net_4_0_Release|Any CPU + {C6CFD7E1-B855-44DC-B4CE-9CD72984AF52}.pcl_Debug|Any CPU.ActiveCfg = net_4_0_Debug|Any CPU + {C6CFD7E1-B855-44DC-B4CE-9CD72984AF52}.pcl_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU {FBC6DD59-D09D-499C-B03C-99C1C78FF2AC}.net_3_5_Debug|Any CPU.ActiveCfg = net_3_5_Debug|Any CPU {FBC6DD59-D09D-499C-B03C-99C1C78FF2AC}.net_3_5_Debug|Any CPU.Build.0 = net_3_5_Debug|Any CPU {FBC6DD59-D09D-499C-B03C-99C1C78FF2AC}.net_3_5_Release|Any CPU.ActiveCfg = net_3_5_Release|Any CPU @@ -174,24 +142,22 @@ Global {FBC6DD59-D09D-499C-B03C-99C1C78FF2AC}.net_4_0_Debug|Any CPU.Build.0 = net_4_0_Debug|Any CPU {FBC6DD59-D09D-499C-B03C-99C1C78FF2AC}.net_4_0_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU {FBC6DD59-D09D-499C-B03C-99C1C78FF2AC}.net_4_0_Release|Any CPU.Build.0 = net_4_0_Release|Any CPU - {FBC6DD59-D09D-499C-B03C-99C1C78FF2AC}.silverlight_Debug|Any CPU.ActiveCfg = silverlight_Debug|Any CPU - {FBC6DD59-D09D-499C-B03C-99C1C78FF2AC}.silverlight_Debug|Any CPU.Build.0 = silverlight_Debug|Any CPU - {FBC6DD59-D09D-499C-B03C-99C1C78FF2AC}.silverlight_Release|Any CPU.ActiveCfg = silverlight_Release|Any CPU - {FBC6DD59-D09D-499C-B03C-99C1C78FF2AC}.silverlight_Release|Any CPU.Build.0 = silverlight_Release|Any CPU - {FBC6DD59-D09D-499C-B03C-99C1C78FF2AC}.winphone_Debug|Any CPU.ActiveCfg = winphone_Debug|Any CPU - {FBC6DD59-D09D-499C-B03C-99C1C78FF2AC}.winphone_Debug|Any CPU.Build.0 = winphone_Debug|Any CPU - {FBC6DD59-D09D-499C-B03C-99C1C78FF2AC}.winphone_Release|Any CPU.ActiveCfg = winphone_Release|Any CPU - {FBC6DD59-D09D-499C-B03C-99C1C78FF2AC}.winphone_Release|Any CPU.Build.0 = winphone_Release|Any CPU + {FBC6DD59-D09D-499C-B03C-99C1C78FF2AC}.net_4_5_Debug|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {FBC6DD59-D09D-499C-B03C-99C1C78FF2AC}.net_4_5_Debug|Any CPU.Build.0 = net_4_0_Release|Any CPU + {FBC6DD59-D09D-499C-B03C-99C1C78FF2AC}.net_4_5_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {FBC6DD59-D09D-499C-B03C-99C1C78FF2AC}.net_4_5_Release|Any CPU.Build.0 = net_4_0_Release|Any CPU + {FBC6DD59-D09D-499C-B03C-99C1C78FF2AC}.pcl_Debug|Any CPU.ActiveCfg = pcl_Debug|Any CPU + {FBC6DD59-D09D-499C-B03C-99C1C78FF2AC}.pcl_Release|Any CPU.ActiveCfg = pcl_Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution {A47B1F49-A81A-43E8-BE6B-DD28AF2C4055} = {74E5ECE0-06B4-401C-AEBA-E8DD53E17943} + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD} = {929D5B3B-E29A-40CC-93D8-0FF43A6F9FA1} {AC71DF9C-99FA-4A63-990A-66C8010355A6} = {74E5ECE0-06B4-401C-AEBA-E8DD53E17943} + {63E6915C-7EA4-4D76-AB28-0D7191EEA626} = {929D5B3B-E29A-40CC-93D8-0FF43A6F9FA1} {29300103-CB76-4A1D-B6FD-FFD91C1EC8AA} = {74E5ECE0-06B4-401C-AEBA-E8DD53E17943} {C6CFD7E1-B855-44DC-B4CE-9CD72984AF52} = {74E5ECE0-06B4-401C-AEBA-E8DD53E17943} - {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD} = {929D5B3B-E29A-40CC-93D8-0FF43A6F9FA1} - {63E6915C-7EA4-4D76-AB28-0D7191EEA626} = {929D5B3B-E29A-40CC-93D8-0FF43A6F9FA1} EndGlobalSection EndGlobal diff --git a/external/cecil/Mono.Cecil.sln.DotSettings b/external/cecil/Mono.Cecil.sln.DotSettings old mode 100755 new mode 100644 index 6d06ad79ae..b1aed5eade --- a/external/cecil/Mono.Cecil.sln.DotSettings +++ b/external/cecil/Mono.Cecil.sln.DotSettings @@ -32,4 +32,8 @@ C:\sources\cecil\Mono.Cecil.sln.DotSettings True 1 + True + True + True + True None \ No newline at end of file diff --git a/external/cecil/Mono.Cecil/ArrayType.cs b/external/cecil/Mono.Cecil/ArrayType.cs index 55c59d8728..010049cc00 100644 --- a/external/cecil/Mono.Cecil/ArrayType.cs +++ b/external/cecil/Mono.Cecil/ArrayType.cs @@ -1,29 +1,11 @@ // -// ArrayType.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; diff --git a/external/cecil/Mono.Cecil/AssemblyDefinition.cs b/external/cecil/Mono.Cecil/AssemblyDefinition.cs index f1b5d25e4e..d294c39625 100644 --- a/external/cecil/Mono.Cecil/AssemblyDefinition.cs +++ b/external/cecil/Mono.Cecil/AssemblyDefinition.cs @@ -1,29 +1,11 @@ // -// AssemblyDefinition.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; @@ -33,7 +15,7 @@ using Mono.Collections.Generic; namespace Mono.Cecil { - public sealed class AssemblyDefinition : ICustomAttributeProvider, ISecurityDeclarationProvider { + public sealed class AssemblyDefinition : ICustomAttributeProvider, ISecurityDeclarationProvider, IDisposable { AssemblyNameDefinition name; @@ -62,7 +44,7 @@ namespace Mono.Cecil { return modules; if (main_module.HasImage) - return modules = main_module.Read (this, (_, reader) => reader.ReadModules ()); + return main_module.Read (ref modules, this, (_, reader) => reader.ReadModules ()); return modules = new Collection (1) { main_module }; } @@ -87,7 +69,7 @@ namespace Mono.Cecil { } public Collection CustomAttributes { - get { return custom_attributes ?? (custom_attributes = this.GetCustomAttributes (main_module)); } + get { return custom_attributes ?? (this.GetCustomAttributes (ref custom_attributes, main_module)); } } public bool HasSecurityDeclarations { @@ -100,13 +82,25 @@ namespace Mono.Cecil { } public Collection SecurityDeclarations { - get { return security_declarations ?? (security_declarations = this.GetSecurityDeclarations (main_module)); } + get { return security_declarations ?? (this.GetSecurityDeclarations (ref security_declarations, main_module)); } } internal AssemblyDefinition () { } + public void Dispose () + { + if (this.modules == null) { + main_module.Dispose (); + return; + } + + var modules = this.Modules; + for (int i = 0; i < modules.Count; i++) + modules [i].Dispose (); + } + #if !READ_ONLY public static AssemblyDefinition CreateAssembly (AssemblyNameDefinition assemblyName, string moduleName, ModuleKind kind) { @@ -130,6 +124,7 @@ namespace Mono.Cecil { } #endif +#if !PCL public static AssemblyDefinition ReadAssembly (string fileName) { return ReadAssembly (ModuleDefinition.ReadModule (fileName)); @@ -139,6 +134,7 @@ namespace Mono.Cecil { { return ReadAssembly (ModuleDefinition.ReadModule (fileName, parameters)); } +#endif public static AssemblyDefinition ReadAssembly (Stream stream) { @@ -160,20 +156,33 @@ namespace Mono.Cecil { } #if !READ_ONLY + +#if !PCL public void Write (string fileName) { Write (fileName, new WriterParameters ()); } - public void Write (Stream stream) - { - Write (stream, new WriterParameters ()); - } - public void Write (string fileName, WriterParameters parameters) { main_module.Write (fileName, parameters); } +#endif + + public void Write () + { + main_module.Write (); + } + + public void Write (WriterParameters parameters) + { + main_module.Write (parameters); + } + + public void Write (Stream stream) + { + Write (stream, new WriterParameters ()); + } public void Write (Stream stream, WriterParameters parameters) { diff --git a/external/cecil/Mono.Cecil/AssemblyFlags.cs b/external/cecil/Mono.Cecil/AssemblyFlags.cs index 72a0eb06c2..6ca5bc274c 100644 --- a/external/cecil/Mono.Cecil/AssemblyFlags.cs +++ b/external/cecil/Mono.Cecil/AssemblyFlags.cs @@ -1,29 +1,11 @@ // -// AssemblyFlags.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; diff --git a/external/cecil/Mono.Cecil/AssemblyHashAlgorithm.cs b/external/cecil/Mono.Cecil/AssemblyHashAlgorithm.cs index 79a5699db6..66ef4cbba7 100644 --- a/external/cecil/Mono.Cecil/AssemblyHashAlgorithm.cs +++ b/external/cecil/Mono.Cecil/AssemblyHashAlgorithm.cs @@ -1,29 +1,11 @@ // -// AssemblyHashAlgorithm.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // namespace Mono.Cecil { diff --git a/external/cecil/Mono.Cecil/AssemblyInfo.cs b/external/cecil/Mono.Cecil/AssemblyInfo.cs index 8a9f8097e1..4d32f2bde2 100644 --- a/external/cecil/Mono.Cecil/AssemblyInfo.cs +++ b/external/cecil/Mono.Cecil/AssemblyInfo.cs @@ -1,29 +1,11 @@ // -// AssemblyInfo.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System.Reflection; @@ -31,16 +13,9 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; [assembly: AssemblyTitle ("Mono.Cecil")] -[assembly: AssemblyProduct ("Mono.Cecil")] -[assembly: AssemblyCopyright ("Copyright © 2008 - 2011 Jb Evain")] - -[assembly: ComVisible (false)] +#if !PCL && !NET_CORE [assembly: Guid ("fd225bb4-fa53-44b2-a6db-85f5e48dcb54")] - -[assembly: AssemblyVersion ("0.9.5.0")] -#if !CF -[assembly: AssemblyFileVersion ("0.9.5.0")] #endif [assembly: InternalsVisibleTo ("Mono.Cecil.Pdb, PublicKey=002400000480000094000000060200000024000052534131000400000100010079159977d2d03a8e6bea7a2e74e8d1afcc93e8851974952bb480a12c9134474d04062447c37e0e68c080536fcf3c3fbe2ff9c979ce998475e506e8ce82dd5b0f350dc10e93bf2eeecf874b24770c5081dbea7447fddafa277b22de47d6ffea449674a4f9fccf84d15069089380284dbdd35f46cdff12a1bd78e4ef0065d016df")] diff --git a/external/cecil/Mono.Cecil/AssemblyLinkedResource.cs b/external/cecil/Mono.Cecil/AssemblyLinkedResource.cs index 4d8bac0bbb..f4896bd245 100644 --- a/external/cecil/Mono.Cecil/AssemblyLinkedResource.cs +++ b/external/cecil/Mono.Cecil/AssemblyLinkedResource.cs @@ -1,29 +1,11 @@ // -// AssemblyLinkedResource.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; diff --git a/external/cecil/Mono.Cecil/AssemblyNameDefinition.cs b/external/cecil/Mono.Cecil/AssemblyNameDefinition.cs index dc6b9057f9..2511d79344 100644 --- a/external/cecil/Mono.Cecil/AssemblyNameDefinition.cs +++ b/external/cecil/Mono.Cecil/AssemblyNameDefinition.cs @@ -1,29 +1,11 @@ // -// AssemblyNameDefinition.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; diff --git a/external/cecil/Mono.Cecil/AssemblyNameReference.cs b/external/cecil/Mono.Cecil/AssemblyNameReference.cs index 4f58fe2d15..fbbe67a527 100644 --- a/external/cecil/Mono.Cecil/AssemblyNameReference.cs +++ b/external/cecil/Mono.Cecil/AssemblyNameReference.cs @@ -1,29 +1,11 @@ // -// AssemblyNameReference.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; @@ -67,8 +49,8 @@ namespace Mono.Cecil { public Version Version { get { return version; } set { - version = value; - full_name = null; + version = Mixin.CheckVersion (value); + full_name = null; } } @@ -112,9 +94,10 @@ namespace Mono.Cecil { if (public_key_token.IsNullOrEmpty () && !public_key.IsNullOrEmpty ()) { var hash = HashPublicKey (); // we need the last 8 bytes in reverse order - public_key_token = new byte [8]; - Array.Copy (hash, (hash.Length - 8), public_key_token, 0, 8); - Array.Reverse (public_key_token, 0, 8); + var local_public_key_token = new byte [8]; + Array.Copy (hash, (hash.Length - 8), local_public_key_token, 0, 8); + Array.Reverse (local_public_key_token, 0, 8); + public_key_token = local_public_key_token; // publish only once finished (required for thread-safety) } return public_key_token ?? Empty.Array; } @@ -126,29 +109,27 @@ namespace Mono.Cecil { byte [] HashPublicKey () { +#if !PCL HashAlgorithm algorithm; switch (hash_algorithm) { case AssemblyHashAlgorithm.Reserved: -#if SILVERLIGHT - throw new NotSupportedException (); -#else algorithm = MD5.Create (); break; -#endif default: // None default to SHA1 -#if SILVERLIGHT - algorithm = new SHA1Managed (); - break; -#else algorithm = SHA1.Create (); break; -#endif } using (algorithm) return algorithm.ComputeHash (public_key); +#else + if (hash_algorithm != AssemblyHashAlgorithm.SHA1) + throw new NotSupportedException (); + + return new SHA1Managed ().ComputeHash (public_key); +#endif } public virtual MetadataScopeType MetadataScopeType { @@ -164,11 +145,9 @@ namespace Mono.Cecil { var builder = new StringBuilder (); builder.Append (name); - if (version != null) { - builder.Append (sep); - builder.Append ("Version="); - builder.Append (version.ToString ()); - } + builder.Append (sep); + builder.Append ("Version="); + builder.Append (version.ToString (fieldCount: 4)); builder.Append (sep); builder.Append ("Culture="); builder.Append (string.IsNullOrEmpty (culture) ? "neutral" : culture); @@ -183,6 +162,11 @@ namespace Mono.Cecil { } else builder.Append ("null"); + if (IsRetargetable) { + builder.Append (sep); + builder.Append ("Retargetable=Yes"); + } + return full_name = builder.ToString (); } } @@ -213,7 +197,7 @@ namespace Mono.Cecil { name.Version = new Version (parts [1]); break; case "culture": - name.Culture = parts [1]; + name.Culture = parts [1] == "neutral" ? "" : parts [1]; break; case "publickeytoken": var pk_token = parts [1]; @@ -248,6 +232,8 @@ namespace Mono.Cecil { internal AssemblyNameReference () { + this.version = Mixin.ZeroVersion; + this.token = new MetadataToken (TokenType.AssemblyRef); } public AssemblyNameReference (string name, Version version) @@ -256,7 +242,7 @@ namespace Mono.Cecil { throw new ArgumentNullException ("name"); this.name = name; - this.version = version; + this.version = Mixin.CheckVersion (version); this.hash_algorithm = AssemblyHashAlgorithm.None; this.token = new MetadataToken (TokenType.AssemblyRef); } @@ -266,4 +252,23 @@ namespace Mono.Cecil { return this.FullName; } } + + partial class Mixin { + + public static Version ZeroVersion = new Version (0, 0, 0 ,0); + + public static Version CheckVersion (Version version) + { + if (version == null) + return ZeroVersion; + + if (version.Build == -1) + return new Version (version.Major, version.Minor, 0, 0); + + if (version.Revision == -1) + return new Version (version.Major, version.Minor, version.Build, 0); + + return version; + } + } } diff --git a/external/cecil/Mono.Cecil/AssemblyReader.cs b/external/cecil/Mono.Cecil/AssemblyReader.cs index 569475b573..da9d5bcb48 100644 --- a/external/cecil/Mono.Cecil/AssemblyReader.cs +++ b/external/cecil/Mono.Cecil/AssemblyReader.cs @@ -1,29 +1,11 @@ // -// AssemblyReader.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; @@ -53,6 +35,7 @@ namespace Mono.Cecil { } protected abstract void ReadModule (); + public abstract void ReadSymbols (ModuleDefinition module); protected void ReadModuleManifest (MetadataReader reader) { @@ -76,17 +59,36 @@ namespace Mono.Cecil { assembly.main_module = module; } - public static ModuleDefinition CreateModuleFrom (Image image, ReaderParameters parameters) + public static ModuleDefinition CreateModule (Image image, ReaderParameters parameters) { - var module = ReadModule (image, parameters); + var reader = CreateModuleReader (image, parameters.ReadingMode); + var module = reader.module; + + if (parameters.assembly_resolver != null) + module.assembly_resolver = Disposable.NotOwned (parameters.assembly_resolver); + + if (parameters.metadata_resolver != null) + module.metadata_resolver = parameters.metadata_resolver; + +#if !READ_ONLY + if (parameters.metadata_importer_provider != null) + module.metadata_importer = parameters.metadata_importer_provider.GetMetadataImporter (module); +#if !PCL && !NET_CORE + if (parameters.reflection_importer_provider != null) + module.reflection_importer = parameters.reflection_importer_provider.GetReflectionImporter (module); +#endif +#endif + + GetMetadataKind (module, parameters); + + reader.ReadModule (); ReadSymbols (module, parameters); - if (parameters.AssemblyResolver != null) - module.assembly_resolver = parameters.AssemblyResolver; + reader.ReadSymbols (module); - if (parameters.MetadataResolver != null) - module.metadata_resolver = parameters.MetadataResolver; + if (parameters.ReadingMode == ReadingMode.Immediate) + module.MetadataSystem.Clear (); return module; } @@ -95,25 +97,46 @@ namespace Mono.Cecil { { var symbol_reader_provider = parameters.SymbolReaderProvider; +#if !PCL if (symbol_reader_provider == null && parameters.ReadSymbols) symbol_reader_provider = SymbolProvider.GetPlatformReaderProvider (); +#endif if (symbol_reader_provider != null) { module.SymbolReaderProvider = symbol_reader_provider; - +#if !PCL var reader = parameters.SymbolStream != null ? symbol_reader_provider.GetSymbolReader (module, parameters.SymbolStream) - : symbol_reader_provider.GetSymbolReader (module, module.FullyQualifiedName); + : symbol_reader_provider.GetSymbolReader (module, module.FileName); +#else + if (parameters.SymbolStream == null) + throw new InvalidOperationException (); + + var reader = symbol_reader_provider.GetSymbolReader (module, parameters.SymbolStream); +#endif module.ReadSymbols (reader); } + + if (module.Image.HasDebugTables ()) + module.ReadSymbols (new PortablePdbReader (module.Image, module)); } - static ModuleDefinition ReadModule (Image image, ReaderParameters parameters) + static void GetMetadataKind (ModuleDefinition module, ReaderParameters parameters) { - var reader = CreateModuleReader (image, parameters.ReadingMode); - reader.ReadModule (); - return reader.module; + if (!parameters.ApplyWindowsRuntimeProjections) { + module.MetadataKind = MetadataKind.Ecma335; + return; + } + + var runtime_version = module.RuntimeVersion; + + if (!runtime_version.Contains ("WindowsRuntime")) + module.MetadataKind = MetadataKind.Ecma335; + else if (runtime_version.Contains ("CLR")) + module.MetadataKind = MetadataKind.ManagedWindowsMetadata; + else + module.MetadataKind = MetadataKind.WindowsMetadata; } static ModuleReader CreateModuleReader (Image image, ReadingMode mode) @@ -131,6 +154,8 @@ namespace Mono.Cecil { sealed class ImmediateModuleReader : ModuleReader { + bool resolve_attributes; + public ImmediateModuleReader (Image image) : base (image, ReadingMode.Immediate) { @@ -140,54 +165,54 @@ namespace Mono.Cecil { { this.module.Read (this.module, (module, reader) => { ReadModuleManifest (reader); - ReadModule (module); + ReadModule (module, resolve_attributes: true); return module; }); } - public static void ReadModule (ModuleDefinition module) + public void ReadModule (ModuleDefinition module, bool resolve_attributes) { + this.resolve_attributes = resolve_attributes; + if (module.HasAssemblyReferences) - Read (module.AssemblyReferences); + Mixin.Read (module.AssemblyReferences); if (module.HasResources) - Read (module.Resources); + Mixin.Read (module.Resources); if (module.HasModuleReferences) - Read (module.ModuleReferences); + Mixin.Read (module.ModuleReferences); if (module.HasTypes) ReadTypes (module.Types); if (module.HasExportedTypes) - Read (module.ExportedTypes); - if (module.HasCustomAttributes) - Read (module.CustomAttributes); + Mixin.Read (module.ExportedTypes); + + ReadCustomAttributes (module); var assembly = module.Assembly; if (assembly == null) return; - if (assembly.HasCustomAttributes) - Read (assembly.CustomAttributes); - if (assembly.HasSecurityDeclarations) - Read (assembly.SecurityDeclarations); + ReadCustomAttributes (assembly); + ReadSecurityDeclarations (assembly); } - static void ReadTypes (Collection types) + void ReadTypes (Collection types) { for (int i = 0; i < types.Count; i++) ReadType (types [i]); } - static void ReadType (TypeDefinition type) + void ReadType (TypeDefinition type) { ReadGenericParameters (type); if (type.HasInterfaces) - Read (type.Interfaces); + ReadInterfaces (type); if (type.HasNestedTypes) ReadTypes (type.NestedTypes); if (type.HasLayoutInfo) - Read (type.ClassSize); + Mixin.Read (type.ClassSize); if (type.HasFields) ReadFields (type); @@ -205,7 +230,15 @@ namespace Mono.Cecil { ReadCustomAttributes (type); } - static void ReadGenericParameters (IGenericParameterProvider provider) + void ReadInterfaces (TypeDefinition type) + { + var interfaces = type.Interfaces; + + for (int i = 0; i < interfaces.Count; i++) + ReadCustomAttributes (interfaces [i]); + } + + void ReadGenericParameters (IGenericParameterProvider provider) { if (!provider.HasGenericParameters) return; @@ -216,26 +249,47 @@ namespace Mono.Cecil { var parameter = parameters [i]; if (parameter.HasConstraints) - Read (parameter.Constraints); + Mixin.Read (parameter.Constraints); - if (parameter.HasCustomAttributes) - Read (parameter.CustomAttributes); + ReadCustomAttributes (parameter); } } - static void ReadSecurityDeclarations (ISecurityDeclarationProvider provider) + void ReadSecurityDeclarations (ISecurityDeclarationProvider provider) { - if (provider.HasSecurityDeclarations) - Read (provider.SecurityDeclarations); + if (!provider.HasSecurityDeclarations) + return; + + var security_declarations = provider.SecurityDeclarations; + + if (!resolve_attributes) + return; + + for (int i = 0; i < security_declarations.Count; i++) { + var security_declaration = security_declarations [i]; + + Mixin.Read (security_declaration.SecurityAttributes); + } } - static void ReadCustomAttributes (ICustomAttributeProvider provider) + void ReadCustomAttributes (ICustomAttributeProvider provider) { - if (provider.HasCustomAttributes) - Read (provider.CustomAttributes); + if (!provider.HasCustomAttributes) + return; + + var custom_attributes = provider.CustomAttributes; + + if (!resolve_attributes) + return; + + for (int i = 0; i < custom_attributes.Count; i++) { + var custom_attribute = custom_attributes [i]; + + Mixin.Read (custom_attribute.ConstructorArguments); + } } - static void ReadFields (TypeDefinition type) + void ReadFields (TypeDefinition type) { var fields = type.Fields; @@ -243,22 +297,22 @@ namespace Mono.Cecil { var field = fields [i]; if (field.HasConstant) - Read (field.Constant); + Mixin.Read (field.Constant); if (field.HasLayoutInfo) - Read (field.Offset); + Mixin.Read (field.Offset); if (field.RVA > 0) - Read (field.InitialValue); + Mixin.Read (field.InitialValue); if (field.HasMarshalInfo) - Read (field.MarshalInfo); + Mixin.Read (field.MarshalInfo); ReadCustomAttributes (field); } } - static void ReadMethods (TypeDefinition type) + void ReadMethods (TypeDefinition type) { var methods = type.Methods; @@ -271,26 +325,26 @@ namespace Mono.Cecil { ReadParameters (method); if (method.HasOverrides) - Read (method.Overrides); + Mixin.Read (method.Overrides); if (method.IsPInvokeImpl) - Read (method.PInvokeInfo); + Mixin.Read (method.PInvokeInfo); ReadSecurityDeclarations (method); ReadCustomAttributes (method); var return_type = method.MethodReturnType; if (return_type.HasConstant) - Read (return_type.Constant); + Mixin.Read (return_type.Constant); if (return_type.HasMarshalInfo) - Read (return_type.MarshalInfo); + Mixin.Read (return_type.MarshalInfo); ReadCustomAttributes (return_type); } } - static void ReadParameters (MethodDefinition method) + void ReadParameters (MethodDefinition method) { var parameters = method.Parameters; @@ -298,46 +352,74 @@ namespace Mono.Cecil { var parameter = parameters [i]; if (parameter.HasConstant) - Read (parameter.Constant); + Mixin.Read (parameter.Constant); if (parameter.HasMarshalInfo) - Read (parameter.MarshalInfo); + Mixin.Read (parameter.MarshalInfo); ReadCustomAttributes (parameter); } } - static void ReadProperties (TypeDefinition type) + void ReadProperties (TypeDefinition type) { var properties = type.Properties; for (int i = 0; i < properties.Count; i++) { var property = properties [i]; - Read (property.GetMethod); + Mixin.Read (property.GetMethod); if (property.HasConstant) - Read (property.Constant); + Mixin.Read (property.Constant); ReadCustomAttributes (property); } } - static void ReadEvents (TypeDefinition type) + void ReadEvents (TypeDefinition type) { var events = type.Events; for (int i = 0; i < events.Count; i++) { var @event = events [i]; - Read (@event.AddMethod); + Mixin.Read (@event.AddMethod); ReadCustomAttributes (@event); } } - static void Read (object collection) + public override void ReadSymbols (ModuleDefinition module) { + if (module.symbol_reader == null) + return; + + ReadTypesSymbols (module.Types, module.symbol_reader); + } + + void ReadTypesSymbols (Collection types, ISymbolReader symbol_reader) + { + for (int i = 0; i < types.Count; i++) { + var type = types [i]; + + if (type.HasNestedTypes) + ReadTypesSymbols (type.NestedTypes, symbol_reader); + + if (type.HasMethods) + ReadMethodsSymbols (type, symbol_reader); + } + } + + void ReadMethodsSymbols (TypeDefinition type, ISymbolReader symbol_reader) + { + var methods = type.Methods; + for (int i = 0; i < methods.Count; i++) { + var method = methods [i]; + + if (method.HasBody && method.debug_info == null) + method.debug_info = symbol_reader.Read (method); + } } } @@ -355,6 +437,10 @@ namespace Mono.Cecil { return module; }); } + + public override void ReadSymbols (ModuleDefinition module) + { + } } sealed class MetadataReader : ByteBuffer { @@ -363,21 +449,27 @@ namespace Mono.Cecil { readonly internal ModuleDefinition module; readonly internal MetadataSystem metadata; - internal IGenericContext context; internal CodeReader code; + internal IGenericContext context; - uint Position { - get { return (uint) base.position; } - set { base.position = (int) value; } - } + readonly MetadataReader metadata_reader; public MetadataReader (ModuleDefinition module) - : base (module.Image.MetadataSection.Data) + : base (module.Image.TableHeap.data) { this.image = module.Image; this.module = module; this.metadata = module.MetadataSystem; - this.code = new CodeReader (image.MetadataSection, this); + this.code = new CodeReader (this); + } + + public MetadataReader (Image image, ModuleDefinition module, MetadataReader metadata_reader) + : base (image.TableHeap.data) + { + this.image = image; + this.module = module; + this.metadata = module.MetadataSystem; + this.metadata_reader = metadata_reader; } int GetCodedIndexSize (CodedIndex index) @@ -419,6 +511,18 @@ namespace Mono.Cecil { return ReadByIndexSize (blob_heap != null ? blob_heap.IndexSize : 2); } + void GetBlobView (uint signature, out byte [] blob, out int index, out int count) + { + var blob_heap = image.BlobHeap; + if (blob_heap == null) { + blob = null; + index = count = 0; + return; + } + + blob_heap.GetView (signature, out blob, out index, out count); + } + string ReadString () { return image.StringHeap.Read (ReadByIndexSize (image.StringHeap.IndexSize)); @@ -429,6 +533,11 @@ namespace Mono.Cecil { return ReadByIndexSize (image.StringHeap.IndexSize); } + Guid ReadGuid () + { + return image.GuidHeap.Read (ReadByIndexSize (image.GuidHeap.IndexSize)); + } + uint ReadTableIndex (Table table) { return ReadByIndexSize (image.GetTableIndexSize (table)); @@ -443,7 +552,7 @@ namespace Mono.Cecil { { var info = image.TableHeap [table]; if (info.Length != 0) - Position = info.Offset; + this.position = (int) info.Offset; return (int) info.Length; } @@ -455,7 +564,7 @@ namespace Mono.Cecil { if (length == 0 || row > length) return false; - Position = info.Offset + (info.RowSize * (row - 1)); + this.position = (int) (info.Offset + (info.RowSize * (row - 1))); return true; } @@ -485,7 +594,7 @@ namespace Mono.Cecil { Advance (2); // Generation module.Name = ReadString (); - module.Mvid = image.GuidHeap.Read (ReadByIndexSize (image.GuidHeap.IndexSize)); + module.Mvid = ReadGuid (); return module; } @@ -523,7 +632,11 @@ namespace Mono.Cecil { { InitializeAssemblyReferences (); - return new Collection (metadata.AssemblyReferences); + var references = new Collection (metadata.AssemblyReferences); + if (module.IsWindowsMetadata ()) + module.Projections.AddVirtualReferences (references); + + return references; } public MethodDefinition ReadEntryPoint () @@ -549,6 +662,7 @@ namespace Mono.Cecil { if (attributes != FileAttributes.ContainsMetaData) continue; +#if !PCL var parameters = new ReaderParameters { ReadingMode = module.ReadingMode, SymbolReaderProvider = module.SymbolReaderProvider, @@ -557,19 +671,24 @@ namespace Mono.Cecil { modules.Add (ModuleDefinition.ReadModule ( GetModuleFileName (name), parameters)); +#else + throw new NotSupportedException (); +#endif } return modules; } +#if !PCL string GetModuleFileName (string name) { - if (module.FullyQualifiedName == null) + if (module.FileName == null) throw new NotSupportedException (); - var path = Path.GetDirectoryName (module.FullyQualifiedName); + var path = Path.GetDirectoryName (module.FileName); return Path.Combine (path, name); } +#endif void InitializeModuleReferences () { @@ -634,7 +753,7 @@ namespace Mono.Cecil { hash = ReadBlob (file_record.Col3) }; } else - throw new NotSupportedException (); + continue; resources.Add (resource); } @@ -659,19 +778,12 @@ namespace Mono.Cecil { return record; } - public MemoryStream GetManagedResourceStream (uint offset) + public byte [] GetManagedResource (uint offset) { - var rva = image.Resources.VirtualAddress; - var section = image.GetSectionAtVirtualAddress (rva); - var position = (rva - section.VirtualAddress) + offset; - var buffer = section.Data; - - var length = buffer [position] - | (buffer [position + 1] << 8) - | (buffer [position + 2] << 16) - | (buffer [position + 3] << 24); - - return new MemoryStream (buffer, (int) position + 4, length); + return image.GetReaderAt (image.Resources.VirtualAddress, offset, (o, reader) => { + reader.Advance ((int) o); + return reader.ReadBytes (reader.ReadInt32 ()); + }) ?? Empty.Array; } void PopulateVersionAndFlags (AssemblyNameReference name) @@ -719,8 +831,8 @@ namespace Mono.Cecil { for (int i = 0; i < types.Length; i++) { var type = types [i]; - InitializeCollection (type.Fields); - InitializeCollection (type.Methods); + Mixin.Read (type.Fields); + Mixin.Read (type.Methods); } } @@ -857,6 +969,9 @@ namespace Mono.Cecil { if (IsNested (attributes)) type.DeclaringType = GetNestedTypeDeclaringType (type); + if (module.IsWindowsMetadata ()) + WindowsRuntimeProjections.Project (type); + return type; } @@ -892,10 +1007,10 @@ namespace Mono.Cecil { if (current_index == current_table.Length) next_index = image.TableHeap [target].Length + 1; else { - var position = Position; - Position += (uint) (current_table.RowSize - image.GetTableIndexSize (target)); + var position = this.position; + this.position += (int) (current_table.RowSize - image.GetTableIndexSize (target)); next_index = ReadTableIndex (target); - Position = position; + this.position = position; } list.Length = next_index - list.Start; @@ -1040,23 +1155,37 @@ namespace Mono.Cecil { MetadataSystem.TryProcessPrimitiveTypeReference (type); + if (type.Module.IsWindowsMetadata ()) + WindowsRuntimeProjections.Project (type); + return type; } IMetadataScope GetTypeReferenceScope (MetadataToken scope) { + if (scope.TokenType == TokenType.Module) + return module; + + IMetadataScope[] scopes; + switch (scope.TokenType) { case TokenType.AssemblyRef: InitializeAssemblyReferences (); - return metadata.AssemblyReferences [(int) scope.RID - 1]; + scopes = metadata.AssemblyReferences; + break; case TokenType.ModuleRef: InitializeModuleReferences (); - return metadata.ModuleReferences [(int) scope.RID - 1]; - case TokenType.Module: - return module; + scopes = metadata.ModuleReferences; + break; default: throw new NotSupportedException (); } + + var index = scope.RID - 1; + if (index < 0 || index >= scopes.Length) + return null; + + return scopes [index]; } public IEnumerable GetTypeReferences () @@ -1094,25 +1223,29 @@ namespace Mono.Cecil { public bool HasInterfaces (TypeDefinition type) { InitializeInterfaces (); - MetadataToken [] mapping; + Row [] mapping; return metadata.TryGetInterfaceMapping (type, out mapping); } - public Collection ReadInterfaces (TypeDefinition type) + public InterfaceImplementationCollection ReadInterfaces (TypeDefinition type) { InitializeInterfaces (); - MetadataToken [] mapping; + Row [] mapping; if (!metadata.TryGetInterfaceMapping (type, out mapping)) - return new Collection (); + return new InterfaceImplementationCollection (type); - var interfaces = new Collection (mapping.Length); + var interfaces = new InterfaceImplementationCollection (type, mapping.Length); this.context = type; - for (int i = 0; i < mapping.Length; i++) - interfaces.Add (GetTypeDefOrRef (mapping [i])); + for (int i = 0; i < mapping.Length; i++) { + interfaces.Add ( + new InterfaceImplementation ( + GetTypeDefOrRef (mapping [i].Col2), + new MetadataToken(TokenType.InterfaceImpl, mapping [i].Col1))); + } metadata.RemoveInterfaceMapping (type); @@ -1126,17 +1259,17 @@ namespace Mono.Cecil { int length = MoveTo (Table.InterfaceImpl); - metadata.Interfaces = new Dictionary (length); + metadata.Interfaces = new Dictionary []> (length); - for (int i = 0; i < length; i++) { + for (uint i = 1; i <= length; i++) { var type = ReadTableIndex (Table.TypeDef); var @interface = ReadMetadataToken (CodedIndex.TypeDefOrRef); - AddInterfaceMapping (type, @interface); + AddInterfaceMapping (type, new Row (i, @interface)); } } - void AddInterfaceMapping (uint type, MetadataToken @interface) + void AddInterfaceMapping (uint type, Row @interface) { metadata.SetInterfaceMapping (type, AddMapping (metadata.Interfaces, type, @interface)); } @@ -1176,6 +1309,9 @@ namespace Mono.Cecil { return; fields.Add (field); + + if (module.IsWindowsMetadata ()) + WindowsRuntimeProjections.Project (field); } void InitializeFields () @@ -1221,13 +1357,7 @@ namespace Mono.Cecil { byte [] GetFieldInitializeValue (int size, RVA rva) { - var section = image.GetSectionAtVirtualAddress (rva); - if (section == null) - return Empty.Array; - - var value = new byte [size]; - Buffer.BlockCopy (section.Data, (int) (rva - section.VirtualAddress), value, 0, size); - return value; + return image.GetReaderAt (rva, size, (s, reader) => reader.ReadBytes (s)) ?? Empty.Array; } static int GetFieldTypeSize (TypeReference type) @@ -1263,8 +1393,8 @@ namespace Mono.Cecil { case ElementType.CModReqD: return GetFieldTypeSize (((IModifierType) type).ElementType); default: - var field_type = type.CheckedResolve (); - if (field_type.HasLayoutInfo) + var field_type = type.Resolve (); + if (field_type != null && field_type.HasLayoutInfo) size = field_type.ClassSize; break; @@ -1611,10 +1741,11 @@ namespace Mono.Cecil { var methods = type.Methods; for (int i = 0; i < methods.Count; i++) { var method = methods [i]; - if (method.sem_attrs.HasValue) + if (method.sem_attrs_ready) continue; method.sem_attrs = ReadMethodSemantics (method); + method.sem_attrs_ready = true; } } @@ -1690,12 +1821,14 @@ namespace Mono.Cecil { ReadMethodSignature (signature, method); metadata.AddMethodDefinition (method); - if (param_range.Length == 0) - return; + if (param_range.Length != 0) { + var position = base.position; + ReadParameters (method, param_range); + base.position = position; + } - var position = base.position; - ReadParameters (method, param_range); - base.position = position; + if (module.IsWindowsMetadata ()) + WindowsRuntimeProjections.Project (method); } void ReadParameters (MethodDefinition method, Range param_range) @@ -1887,9 +2020,7 @@ namespace Mono.Cecil { return; } - slots = slots.Resize (slots.Length + 1); - slots [slots.Length - 1] = range; - ranges [owner] = slots; + ranges [owner] = slots.Add(range); } public bool HasGenericConstraints (GenericParameter generic_parameter) @@ -2056,6 +2187,9 @@ namespace Mono.Cecil { if (rid == 0) return null; + if (metadata_reader != null) + return metadata_reader.LookupToken (token); + IMetadataTokenProvider element; var position = this.position; var context = this.context; @@ -2109,7 +2243,7 @@ namespace Mono.Cecil { if (type == null) return null; - InitializeCollection (type.Fields); + Mixin.Read (type.Fields); return metadata.GetFieldDefinition (rid); } @@ -2131,7 +2265,7 @@ namespace Mono.Cecil { if (type == null) return null; - InitializeCollection (type.Methods); + Mixin.Read (type.Methods); return metadata.GetMethodDefinition (rid); } @@ -2207,6 +2341,9 @@ namespace Mono.Cecil { member.token = new MetadataToken (TokenType.MemberRef, rid); + if (module.IsWindowsMetadata ()) + WindowsRuntimeProjections.Project (member); + return member; } @@ -2271,7 +2408,7 @@ namespace Mono.Cecil { var type_system = module.TypeSystem; var context = new MethodReference (string.Empty, type_system.Void); - context.DeclaringType = new TypeReference (string.Empty, string.Empty, module, type_system.Corlib); + context.DeclaringType = new TypeReference (string.Empty, string.Empty, module, type_system.CoreLibrary); var member_references = new MemberReference [length]; @@ -2311,24 +2448,35 @@ namespace Mono.Cecil { metadata.Constants.Remove (owner.MetadataToken); - switch (row.Col1) { + return ReadConstantValue (row.Col1, row.Col2); + } + + object ReadConstantValue (ElementType etype, uint signature) + { + switch (etype) { case ElementType.Class: case ElementType.Object: return null; case ElementType.String: - return ReadConstantString (ReadBlob (row.Col2)); + return ReadConstantString (signature); default: - return ReadConstantPrimitive (row.Col1, row.Col2); + return ReadConstantPrimitive (etype, signature); } } - static string ReadConstantString (byte [] blob) + string ReadConstantString (uint signature) { - var length = blob.Length; - if ((length & 1) == 1) - length--; + byte [] blob; + int index, count; - return Encoding.Unicode.GetString (blob, 0, length); + GetBlobView (signature, out blob, out index, out count); + if (count == 0) + return string.Empty; + + if ((count & 1) == 1) + count--; + + return Encoding.Unicode.GetString (blob, index, count); } object ReadConstantPrimitive (ElementType type, uint signature) @@ -2337,7 +2485,7 @@ namespace Mono.Cecil { return reader.ReadConstantSignature (type); } - void InitializeCustomAttributes () + internal void InitializeCustomAttributes () { if (metadata.CustomAttributes != null) return; @@ -2377,6 +2525,10 @@ namespace Mono.Cecil { metadata.RemoveCustomAttributeRange (owner); + if (module.IsWindowsMetadata ()) + foreach (var custom_attribute in custom_attributes) + WindowsRuntimeProjections.Project (owner, custom_attribute); + return custom_attributes; } @@ -2385,7 +2537,7 @@ namespace Mono.Cecil { if (!MoveTo (Table.CustomAttribute, range.Start)) return; - for (int i = 0; i < range.Length; i++) { + for (var i = 0; i < range.Length; i++) { ReadMetadataToken (CodedIndex.HasCustomAttribute); var constructor = (MethodReference) LookupToken ( @@ -2561,7 +2713,6 @@ namespace Mono.Cecil { void ReadXmlSecurityDeclaration (uint signature, SecurityDeclaration declaration) { - var blob = ReadBlob (signature); var attributes = new Collection (1); var attribute = new SecurityAttribute ( @@ -2573,7 +2724,7 @@ namespace Mono.Cecil { "XML", new CustomAttributeArgument ( module.TypeSystem.String, - Encoding.Unicode.GetString (blob, 0, blob.Length)))); + ReadUnicodeStringBlob (signature)))); attributes.Add (attribute); @@ -2630,7 +2781,7 @@ namespace Mono.Cecil { switch (token.TokenType) { case TokenType.AssemblyRef: InitializeAssemblyReferences (); - scope = metadata.AssemblyReferences [(int) token.RID - 1]; + scope = metadata.GetAssemblyNameReference (token.RID); break; case TokenType.File: InitializeModuleReferences (); @@ -2665,34 +2816,399 @@ namespace Mono.Cecil { return reference; } - static void InitializeCollection (object o) + void InitializeDocuments () { + if (metadata.Documents != null) + return; + + int length = MoveTo (Table.Document); + + var documents = metadata.Documents = new Document [length]; + + for (uint i = 1; i <= length; i++) { + var name_index = ReadBlobIndex (); + var hash_algorithm = ReadGuid (); + var hash = ReadBlob (); + var language = ReadGuid (); + + var signature = ReadSignature (name_index); + var name = signature.ReadDocumentName (); + + documents [i - 1] = new Document (name) { + HashAlgorithm = hash_algorithm.ToHashAlgorithm (), + Hash = hash, + Language = language.ToLanguage (), + token = new MetadataToken (TokenType.Document, i), + }; + } + } + + public Collection ReadSequencePoints (MethodDefinition method) + { + InitializeDocuments (); + + if (!MoveTo (Table.MethodDebugInformation, method.MetadataToken.RID)) + return new Collection (); + + var document = metadata.GetDocument (ReadTableIndex (Table.Document)); + var reader = ReadSignature (ReadBlobIndex ()); + + return reader.ReadSequencePoints (document); + } + + void InitializeLocalScopes () + { + if (metadata.LocalScopes != null) + return; + + InitializeMethods (); + + int length = MoveTo (Table.LocalScope); + + metadata.LocalScopes = new Dictionary []> (); + + for (uint i = 1; i <= length; i++) { + var method = ReadTableIndex (Table.Method); + var import = ReadTableIndex (Table.ImportScope); + var variables = ReadListRange (i, Table.LocalScope, Table.LocalVariable); + var constants = ReadListRange (i, Table.LocalScope, Table.LocalConstant); + var scope_start = ReadUInt32 (); + var scope_length = ReadUInt32 (); + + metadata.SetLocalScopes (method, AddMapping (metadata.LocalScopes, method, new Row (import, variables, constants, scope_start, scope_length, i))); + } + } + + public ScopeDebugInformation ReadScope (MethodDefinition method) + { + InitializeLocalScopes (); + InitializeImportScopes (); + + Row [] records; + if (!metadata.TryGetLocalScopes (method, out records)) + return null; + + var method_scope = null as ScopeDebugInformation; + + for (int i = 0; i < records.Length; i++) { + var scope = ReadLocalScope (records [i]); + + if (i == 0) { + method_scope = scope; + continue; + } + + if (!AddScope (method_scope.scopes, scope)) + method_scope.Scopes.Add (scope); + } + + return method_scope; + } + + static bool AddScope (Collection scopes, ScopeDebugInformation scope) + { + if (scopes.IsNullOrEmpty ()) + return false; + + foreach (var sub_scope in scopes) { + if (sub_scope.HasScopes && AddScope (sub_scope.Scopes, scope)) + return true; + + if (scope.Start.Offset >= sub_scope.Start.Offset && scope.End.Offset <= sub_scope.End.Offset) { + sub_scope.Scopes.Add (scope); + return true; + } + } + + return false; + } + + ScopeDebugInformation ReadLocalScope (Row record) + { + var scope = new ScopeDebugInformation + { + start = new InstructionOffset ((int) record.Col4), + end = new InstructionOffset ((int) (record.Col4 + record.Col5)), + token = new MetadataToken (TokenType.LocalScope, record.Col6), + }; + + if (record.Col1 > 0) + scope.import = metadata.GetImportScope (record.Col1); + + if (record.Col2.Length > 0) { + scope.variables = new Collection ((int) record.Col2.Length); + for (uint i = 0; i < record.Col2.Length; i++) + scope.variables.Add (ReadLocalVariable (record.Col2.Start + i)); + } + + if (record.Col3.Length > 0) { + scope.constants = new Collection ((int) record.Col3.Length); + for (uint i = 0; i < record.Col3.Length; i++) + scope.constants.Add (ReadLocalConstant (record.Col3.Start + i)); + } + + return scope; + } + + VariableDebugInformation ReadLocalVariable (uint rid) + { + if (!MoveTo (Table.LocalVariable, rid)) + return null; + + var attributes = (VariableAttributes) ReadUInt16 (); + var index = ReadUInt16 (); + var name = ReadString (); + + var variable = new VariableDebugInformation (index, name) { Attributes = attributes, token = new MetadataToken (TokenType.LocalVariable, rid) }; + variable.custom_infos = GetCustomDebugInformation (variable); + return variable; + } + + ConstantDebugInformation ReadLocalConstant (uint rid) + { + if (!MoveTo (Table.LocalConstant, rid)) + return null; + + var name = ReadString (); + var signature = ReadSignature (ReadBlobIndex ()); + var type = signature.ReadTypeSignature (); + + object value; + if (type.etype == ElementType.String) { + if (signature.buffer [signature.position] != 0xff) { + var bytes = signature.ReadBytes ((int) (signature.sig_length - (signature.position - signature.start))); + value = Encoding.Unicode.GetString (bytes, 0, bytes.Length); + } else + value = null; + } else if (type.etype == ElementType.Object) { + value = null; + } else if (type.IsTypeOf ("System", "Decimal")) { + var b = signature.ReadByte (); + value = new decimal (signature.ReadInt32 (), signature.ReadInt32 (), signature.ReadInt32 (), (b & 0x80) != 0, (byte) (b & 0x7f)); + } else if (type.IsTypeOf ("System", "DateTime")) { + value = new DateTime (signature.ReadInt64()); + } else + value = signature.ReadConstantSignature (type.etype); + + var constant = new ConstantDebugInformation (name, type, value) { token = new MetadataToken (TokenType.LocalConstant, rid) }; + constant.custom_infos = GetCustomDebugInformation (constant); + return constant; + } + + void InitializeImportScopes () + { + if (metadata.ImportScopes != null) + return; + + var length = MoveTo (Table.ImportScope); + + metadata.ImportScopes = new ImportDebugInformation [length]; + + for (int i = 1; i <= length; i++) { + ReadTableIndex (Table.ImportScope); + + var import = new ImportDebugInformation (); + import.token = new MetadataToken (TokenType.ImportScope, i); + + var signature = ReadSignature (ReadBlobIndex ()); + while (signature.CanReadMore ()) + import.Targets.Add (ReadImportTarget (signature)); + + metadata.ImportScopes [i - 1] = import; + } + + MoveTo (Table.ImportScope); + + for (int i = 0; i < length; i++) { + var parent = ReadTableIndex (Table.ImportScope); + + ReadBlobIndex (); + + if (parent != 0) + metadata.ImportScopes [i].Parent = metadata.GetImportScope (parent); + } + } + + public string ReadUTF8StringBlob (uint signature) + { + return ReadStringBlob (signature, Encoding.UTF8); + } + + string ReadUnicodeStringBlob (uint signature) + { + return ReadStringBlob (signature, Encoding.Unicode); + } + + string ReadStringBlob (uint signature, Encoding encoding) + { + byte [] blob; + int index, count; + + + GetBlobView (signature, out blob, out index, out count); + if (count == 0) + return string.Empty; + + return encoding.GetString (blob, index, count); + } + + ImportTarget ReadImportTarget (SignatureReader signature) + { + AssemblyNameReference reference = null; + string @namespace = null; + string alias = null; + TypeReference type = null; + + var kind = (ImportTargetKind) signature.ReadCompressedUInt32 (); + switch (kind) { + case ImportTargetKind.ImportNamespace: + @namespace = ReadUTF8StringBlob (signature.ReadCompressedUInt32 ()); + break; + case ImportTargetKind.ImportNamespaceInAssembly: + reference = metadata.GetAssemblyNameReference (signature.ReadCompressedUInt32 ()); + @namespace = ReadUTF8StringBlob (signature.ReadCompressedUInt32 ()); + break; + case ImportTargetKind.ImportType: + type = signature.ReadTypeToken (); + break; + case ImportTargetKind.ImportXmlNamespaceWithAlias: + alias = ReadUTF8StringBlob (signature.ReadCompressedUInt32 ()); + @namespace = ReadUTF8StringBlob (signature.ReadCompressedUInt32 ()); + break; + case ImportTargetKind.ImportAlias: + alias = ReadUTF8StringBlob (signature.ReadCompressedUInt32 ()); + break; + case ImportTargetKind.DefineAssemblyAlias: + alias = ReadUTF8StringBlob (signature.ReadCompressedUInt32 ()); + reference = metadata.GetAssemblyNameReference (signature.ReadCompressedUInt32 ()); + break; + case ImportTargetKind.DefineNamespaceAlias: + alias = ReadUTF8StringBlob (signature.ReadCompressedUInt32 ()); + @namespace = ReadUTF8StringBlob (signature.ReadCompressedUInt32 ()); + break; + case ImportTargetKind.DefineNamespaceInAssemblyAlias: + alias = ReadUTF8StringBlob (signature.ReadCompressedUInt32 ()); + reference = metadata.GetAssemblyNameReference (signature.ReadCompressedUInt32 ()); + @namespace = ReadUTF8StringBlob (signature.ReadCompressedUInt32 ()); + break; + case ImportTargetKind.DefineTypeAlias: + alias = ReadUTF8StringBlob (signature.ReadCompressedUInt32 ()); + type = signature.ReadTypeToken (); + break; + } + + return new ImportTarget (kind) { + alias = alias, + type = type, + @namespace = @namespace, + reference = reference, + }; + } + + void InitializeStateMachineMethods () + { + if (metadata.StateMachineMethods != null) + return; + + var length = MoveTo (Table.StateMachineMethod); + + metadata.StateMachineMethods = new Dictionary (length); + + for (int i = 0; i < length; i++) + metadata.StateMachineMethods.Add (ReadTableIndex (Table.Method), ReadTableIndex (Table.Method)); + } + + public MethodDefinition ReadStateMachineKickoffMethod (MethodDefinition method) + { + InitializeStateMachineMethods (); + + uint rid; + if (!metadata.TryGetStateMachineKickOffMethod (method, out rid)) + return null; + + return GetMethodDefinition (rid); + } + + void InitializeCustomDebugInformations () + { + if (metadata.CustomDebugInformations != null) + return; + + var length = MoveTo (Table.CustomDebugInformation); + + metadata.CustomDebugInformations = new Dictionary []> (); + + for (uint i = 1; i <= length; i++) { + var token = ReadMetadataToken (CodedIndex.HasCustomDebugInformation); + var info = new Row (ReadGuid (), ReadBlobIndex (), i); + + Row [] infos; + metadata.CustomDebugInformations.TryGetValue (token, out infos); + metadata.CustomDebugInformations [token] = infos.Add (info); + } + } + + public Collection GetCustomDebugInformation (ICustomDebugInformationProvider provider) + { + InitializeCustomDebugInformations (); + + Row [] rows; + if (!metadata.CustomDebugInformations.TryGetValue (provider.MetadataToken, out rows)) + return null; + + var infos = new Collection (rows.Length); + + for (int i = 0; i < rows.Length; i++) { + if (rows [i].Col1 == StateMachineScopeDebugInformation.KindIdentifier) { + var signature = ReadSignature (rows [i].Col2); + infos.Add (new StateMachineScopeDebugInformation (signature.ReadInt32 (), signature.ReadInt32 ())); + } else if (rows [i].Col1 == AsyncMethodBodyDebugInformation.KindIdentifier) { + var signature = ReadSignature (rows [i].Col2); + + var catch_offset = signature.ReadInt32 () - 1; + var yields = new Collection (); + var resumes = new Collection (); + uint move_next_rid = 0; + + while (signature.CanReadMore ()) { + yields.Add (new InstructionOffset (signature.ReadInt32 ())); + resumes.Add (new InstructionOffset (signature.ReadInt32 ())); + move_next_rid = signature.ReadCompressedUInt32 (); + } + + var async_body = new AsyncMethodBodyDebugInformation (catch_offset); + async_body.yields = yields; + async_body.resumes = resumes; + async_body.move_next = GetMethodDefinition (move_next_rid); + + infos.Add (async_body); + } else { + infos.Add (new BinaryCustomDebugInformation (rows [i].Col1, ReadBlob (rows [i].Col2))); + } + + infos [i].token = new MetadataToken (TokenType.CustomDebugInformation, rows [i].Col3); + } + + return infos; } } sealed class SignatureReader : ByteBuffer { readonly MetadataReader reader; - readonly uint start, sig_length; + readonly internal uint start, sig_length; TypeSystem TypeSystem { get { return reader.module.TypeSystem; } } public SignatureReader (uint blob, MetadataReader reader) - : base (reader.buffer) + : base (reader.image.BlobHeap.data) { this.reader = reader; - - MoveToBlob (blob); - - this.sig_length = ReadCompressedUInt32 (); - this.start = (uint) position; - } - - void MoveToBlob (uint blob) - { - position = (int) (reader.image.BlobHeap.Offset + blob); + this.position = (int) blob; + this.sig_length = ReadCompressedUInt32(); + this.start = (uint) this.position; } MetadataToken ReadTypeTokenSignature () @@ -2797,6 +3313,11 @@ namespace Mono.Cecil { return ReadTypeSignature ((ElementType) ReadByte ()); } + public TypeReference ReadTypeToken () + { + return GetTypeDefOrRef (ReadTypeTokenSignature ()); + } + TypeReference ReadTypeSignature (ElementType etype) { switch (etype) { @@ -2934,8 +3455,11 @@ namespace Mono.Cecil { public void ReadCustomAttributeNamedArguments (ushort count, ref Collection fields, ref Collection properties) { - for (int i = 0; i < count; i++) + for (int i = 0; i < count; i++) { + if (!CanReadMore ()) + return; ReadCustomAttributeNamedArgument (ref fields, ref properties); + } } void ReadCustomAttributeNamedArgument (ref Collection fields, ref Collection properties) @@ -3099,29 +3623,9 @@ namespace Mono.Cecil { } } - string UnescapeTypeName (string name) - { - StringBuilder sb = new StringBuilder (name.Length); - for (int i = 0; i < name.Length; i++) { - char c = name [i]; - if (name [i] == '\\') { - if ((i < name.Length - 1) && (name [i + 1] == '\\')) { - sb.Append (c); - i++; - } - } else { - sb.Append (c); - } - } - return sb.ToString (); - } - public TypeReference ReadTypeReference () { - string s = ReadUTF8String (); - if (s != null && s.IndexOf ('\\') != -1) - s = UnescapeTypeName (s); - return TypeParser.ParseType (reader.module, s); + return TypeParser.ParseType (reader.module, ReadUTF8String ()); } object ReadCustomAttributeEnum (TypeReference enum_type) @@ -3225,6 +3729,78 @@ namespace Mono.Cecil { return @string; } + public string ReadDocumentName () + { + var separator = (char) buffer [position]; + position++; + + var builder = new StringBuilder (); + for (int i = 0; CanReadMore (); i++) { + if (i > 0 && separator != 0) + builder.Append (separator); + + builder.Append (reader.ReadUTF8StringBlob (ReadCompressedUInt32 ())); + } + + return builder.ToString (); + } + + public Collection ReadSequencePoints (Document document) + { + var sequence_points = new Collection (); + + ReadCompressedUInt32 (); // local_sig_token + + if (document == null) + document = reader.metadata.GetDocument (ReadCompressedUInt32 ()); + + var offset = 0; + var start_line = 0; + var start_column = 0; + var first_non_hidden = true; + + for (var i = 0; CanReadMore (); i++) { + var delta_il = (int) ReadCompressedUInt32 (); + if (i > 0 && delta_il == 0) { + document = reader.metadata.GetDocument (ReadCompressedUInt32 ()); + continue; + } + + offset += delta_il; + + var delta_lines = (int) ReadCompressedUInt32 (); + var delta_columns = delta_lines == 0 + ? (int) ReadCompressedUInt32 () + : ReadCompressedInt32 (); + + if (delta_lines == 0 && delta_columns == 0) { + sequence_points.Add (new SequencePoint (offset, document) { + StartLine = 0xfeefee, + StartColumn = 0xfeefee, + }); + continue; + } + + if (first_non_hidden) { + start_line = (int) ReadCompressedUInt32 (); + start_column = (int) ReadCompressedUInt32 (); + } else { + start_line += ReadCompressedInt32 (); + start_column += ReadCompressedInt32 (); + } + + sequence_points.Add (new SequencePoint (offset, document) { + StartLine = start_line, + StartColumn = start_column, + EndLine = start_line + delta_lines, + EndColumn = start_column + delta_columns, + }); + first_non_hidden = false; + } + + return sequence_points; + } + public bool CanReadMore () { return position - start < sig_length; diff --git a/external/cecil/Mono.Cecil/AssemblyWriter.cs b/external/cecil/Mono.Cecil/AssemblyWriter.cs index f1026eed0d..a71c0ae251 100644 --- a/external/cecil/Mono.Cecil/AssemblyWriter.cs +++ b/external/cecil/Mono.Cecil/AssemblyWriter.cs @@ -1,29 +1,11 @@ // -// AssemblyWriter.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; @@ -31,6 +13,7 @@ using System.Collections.Generic; using System.IO; using System.Text; +using Mono; using Mono.Collections.Generic; using Mono.Cecil.Cil; using Mono.Cecil.Metadata; @@ -41,11 +24,13 @@ using RID = System.UInt32; using CodedRID = System.UInt32; using StringIndex = System.UInt32; using BlobIndex = System.UInt32; +using GuidIndex = System.UInt32; namespace Mono.Cecil { #if !READ_ONLY + using ModuleRow = Row; using TypeRefRow = Row; using TypeDefRow = Row; using FieldRow = Row; @@ -76,34 +61,47 @@ namespace Mono.Cecil { using GenericParamRow = Row; using MethodSpecRow = Row; using GenericParamConstraintRow = Row; + using DocumentRow = Row; + using MethodDebugInformationRow = Row; + using LocalScopeRow = Row; + using LocalVariableRow = Row; + using LocalConstantRow = Row; + using ImportScopeRow = Row; + using StateMachineMethodRow = Row; + using CustomDebugInformationRow = Row; static class ModuleWriter { - public static void WriteModuleTo (ModuleDefinition module, Stream stream, WriterParameters parameters) + public static void WriteModuleTo (ModuleDefinition module, Disposable stream, WriterParameters parameters) { if ((module.Attributes & ModuleAttributes.ILOnly) == 0) throw new NotSupportedException ("Writing mixed-mode assemblies is not supported"); - if (module.HasImage && module.ReadingMode == ReadingMode.Deferred) - ImmediateModuleReader.ReadModule (module); + if (module.HasImage && module.ReadingMode == ReadingMode.Deferred) { + var immediate_reader = new ImmediateModuleReader (module.Image); + immediate_reader.ReadModule (module, resolve_attributes: false); + immediate_reader.ReadSymbols (module); + } module.MetadataSystem.Clear (); var name = module.assembly != null ? module.assembly.Name : null; - var fq_name = stream.GetFullyQualifiedName (); + var fq_name = stream.value.GetFileName (); var symbol_writer_provider = parameters.SymbolWriterProvider; +#if !PCL && !NET_CORE if (symbol_writer_provider == null && parameters.WriteSymbols) symbol_writer_provider = SymbolProvider.GetPlatformWriterProvider (); - var symbol_writer = GetSymbolWriter (module, fq_name, symbol_writer_provider); +#endif + var symbol_writer = GetSymbolWriter (module, fq_name, symbol_writer_provider, parameters); -#if !SILVERLIGHT && !CF +#if !PCL && !NET_CORE if (parameters.StrongNameKeyPair != null && name != null) { name.PublicKey = parameters.StrongNameKeyPair.PublicKey; module.Attributes |= ModuleAttributes.StrongNameSigned; } #endif - var metadata = new MetadataBuilder (module, fq_name, - symbol_writer_provider, symbol_writer); + + var metadata = new MetadataBuilder (module, fq_name, symbol_writer_provider, symbol_writer); BuildMetadata (module, metadata); @@ -114,12 +112,15 @@ namespace Mono.Cecil { writer.WriteImage (); -#if !SILVERLIGHT && !CF + if (metadata.symbol_writer != null) + metadata.symbol_writer.Dispose (); + +#if !PCL && !NET_CORE if (parameters.StrongNameKeyPair != null) - CryptoService.StrongName (stream, writer, parameters.StrongNameKeyPair); + CryptoService.StrongName (stream.value, writer, parameters.StrongNameKeyPair); + + stream.Dispose (); #endif - if (symbol_writer != null) - symbol_writer.Dispose (); } static void BuildMetadata (ModuleDefinition module, MetadataBuilder metadata) @@ -135,12 +136,19 @@ namespace Mono.Cecil { }); } - static ISymbolWriter GetSymbolWriter (ModuleDefinition module, string fq_name, ISymbolWriterProvider symbol_writer_provider) + static ISymbolWriter GetSymbolWriter (ModuleDefinition module, string fq_name, ISymbolWriterProvider symbol_writer_provider, WriterParameters parameters) { if (symbol_writer_provider == null) return null; + if (parameters.SymbolStream != null) + return symbol_writer_provider.GetSymbolWriter (module, parameters.SymbolStream); + +#if !PCL return symbol_writer_provider.GetSymbolWriter (module, fq_name); +#else + return null; +#endif } } @@ -214,13 +222,13 @@ namespace Mono.Cecil { public abstract int Compare (TRow x, TRow y); } - sealed class ModuleTable : OneRowTable { + sealed class ModuleTable : OneRowTable { public override void Write (TableHeapBuffer buffer) { buffer.WriteUInt16 (0); // Generation - buffer.WriteString (row); // Name - buffer.WriteUInt16 (1); // Mvid + buffer.WriteString (row.Col1); // Name + buffer.WriteGuid (row.Col2); // Mvid buffer.WriteUInt16 (0); // EncId buffer.WriteUInt16 (0); // EncBaseId } @@ -685,6 +693,102 @@ namespace Mono.Cecil { } } + sealed class DocumentTable : MetadataTable { + + public override void Write (TableHeapBuffer buffer) + { + for (int i = 0; i < length; i++) { + buffer.WriteBlob (rows [i].Col1); // Name + buffer.WriteGuid (rows [i].Col2); // HashAlgorithm + buffer.WriteBlob (rows [i].Col3); // Hash + buffer.WriteGuid (rows [i].Col4); // Language + } + } + } + + sealed class MethodDebugInformationTable : MetadataTable { + + public override void Write (TableHeapBuffer buffer) + { + for (int i = 0; i < length; i++) { + buffer.WriteRID (rows [i].Col1, Table.Document); // Document + buffer.WriteBlob (rows [i].Col2); // SequencePoints + } + } + } + + sealed class LocalScopeTable : MetadataTable { + + public override void Write (TableHeapBuffer buffer) + { + for (int i = 0; i < length; i++) { + buffer.WriteRID (rows [i].Col1, Table.Method); // Method + buffer.WriteRID (rows [i].Col2, Table.ImportScope); // ImportScope + buffer.WriteRID (rows [i].Col3, Table.LocalVariable); // VariableList + buffer.WriteRID (rows [i].Col4, Table.LocalConstant); // ConstantList + buffer.WriteUInt32 (rows [i].Col5); // StartOffset + buffer.WriteUInt32 (rows [i].Col6); // Length + } + } + } + + sealed class LocalVariableTable : MetadataTable { + + public override void Write (TableHeapBuffer buffer) + { + for (int i = 0; i < length; i++) { + buffer.WriteUInt16 ((ushort) rows [i].Col1); // Attributes + buffer.WriteUInt16 (rows [i].Col2); // Index + buffer.WriteString (rows [i].Col3); // Name + } + } + } + + sealed class LocalConstantTable : MetadataTable { + + public override void Write (TableHeapBuffer buffer) + { + for (int i = 0; i < length; i++) { + buffer.WriteString (rows [i].Col1); // Name + buffer.WriteBlob (rows [i].Col2); // Signature + } + } + } + + sealed class ImportScopeTable : MetadataTable { + + public override void Write (TableHeapBuffer buffer) + { + for (int i = 0; i < length; i++) { + buffer.WriteRID (rows [i].Col1, Table.ImportScope); // Parent + buffer.WriteBlob (rows [i].Col2); // Imports + } + } + } + + sealed class StateMachineMethodTable : MetadataTable { + + public override void Write (TableHeapBuffer buffer) + { + for (int i = 0; i < length; i++) { + buffer.WriteRID (rows [i].Col1, Table.Method); // MoveNextMethod + buffer.WriteRID (rows [i].Col2, Table.Method); // KickoffMethod + } + } + } + + sealed class CustomDebugInformationTable : MetadataTable { + + public override void Write (TableHeapBuffer buffer) + { + for (int i = 0; i < length; i++) { + buffer.WriteCodedRID (rows [i].Col1, CodedIndex.HasCustomDebugInformation); // Parent + buffer.WriteGuid (rows [i].Col2); // Kind + buffer.WriteBlob (rows [i].Col3); // Value + } + } + } + sealed class MetadataBuilder { readonly internal ModuleDefinition module; @@ -692,30 +796,34 @@ namespace Mono.Cecil { readonly internal ISymbolWriter symbol_writer; readonly internal TextMap text_map; readonly internal string fq_name; + readonly internal uint time_stamp; readonly Dictionary type_ref_map; readonly Dictionary type_spec_map; readonly Dictionary member_ref_map; readonly Dictionary method_spec_map; readonly Collection generic_parameters; - readonly Dictionary method_def_map; readonly internal CodeWriter code; readonly internal DataBuffer data; readonly internal ResourceBuffer resources; readonly internal StringHeapBuffer string_heap; + readonly internal GuidHeapBuffer guid_heap; readonly internal UserStringHeapBuffer user_string_heap; readonly internal BlobHeapBuffer blob_heap; readonly internal TableHeapBuffer table_heap; + readonly internal PdbHeapBuffer pdb_heap; internal MetadataToken entry_point; - RID type_rid = 1; - RID field_rid = 1; - RID method_rid = 1; - RID param_rid = 1; - RID property_rid = 1; - RID event_rid = 1; + internal RID type_rid = 1; + internal RID field_rid = 1; + internal RID method_rid = 1; + internal RID param_rid = 1; + internal RID property_rid = 1; + internal RID event_rid = 1; + internal RID local_variable_rid = 1; + internal RID local_constant_rid = 1; readonly TypeRefTable type_ref_table; readonly TypeDefTable type_def_table; @@ -735,6 +843,22 @@ namespace Mono.Cecil { readonly TypeSpecTable typespec_table; readonly MethodSpecTable method_spec_table; + readonly bool portable_pdb; + + internal MetadataBuilder metadata_builder; + + readonly DocumentTable document_table; + readonly MethodDebugInformationTable method_debug_information_table; + readonly LocalScopeTable local_scope_table; + readonly LocalVariableTable local_variable_table; + readonly LocalConstantTable local_constant_table; + readonly ImportScopeTable import_scope_table; + readonly StateMachineMethodTable state_machine_method_table; + readonly CustomDebugInformationTable custom_debug_information_table; + + readonly Dictionary import_scope_map; + readonly Dictionary document_map; + readonly internal bool write_symbols; public MetadataBuilder (ModuleDefinition module, string fq_name, ISymbolWriterProvider symbol_writer_provider, ISymbolWriter symbol_writer) @@ -742,13 +866,27 @@ namespace Mono.Cecil { this.module = module; this.text_map = CreateTextMap (); this.fq_name = fq_name; + this.time_stamp = (uint) DateTime.UtcNow.Subtract (new DateTime (1970, 1, 1)).TotalSeconds; this.symbol_writer_provider = symbol_writer_provider; + + if (symbol_writer == null && module.HasImage && module.Image.HasDebugTables ()) { + symbol_writer = new PortablePdbWriter (this, module); + } + this.symbol_writer = symbol_writer; this.write_symbols = symbol_writer != null; + + var pdb_writer = symbol_writer as PortablePdbWriter; + if (pdb_writer != null) { + portable_pdb = true; + pdb_writer.SetModuleMetadata (this); + } + this.code = new CodeWriter (this); this.data = new DataBuffer (); this.resources = new ResourceBuffer (); this.string_heap = new StringHeapBuffer (); + this.guid_heap = new GuidHeapBuffer (); this.user_string_heap = new UserStringHeapBuffer (); this.blob_heap = new BlobHeapBuffer (); this.table_heap = new TableHeapBuffer (module, this); @@ -777,8 +915,50 @@ namespace Mono.Cecil { member_ref_map = new Dictionary (row_equality_comparer); method_spec_map = new Dictionary (row_equality_comparer); generic_parameters = new Collection (); - if (write_symbols) - method_def_map = new Dictionary (); + + if (!portable_pdb) + return; + + this.document_table = GetTable (Table.Document); + this.method_debug_information_table = GetTable (Table.MethodDebugInformation); + this.local_scope_table = GetTable (Table.LocalScope); + this.local_variable_table = GetTable (Table.LocalVariable); + this.local_constant_table = GetTable (Table.LocalConstant); + this.import_scope_table = GetTable (Table.ImportScope); + this.state_machine_method_table = GetTable (Table.StateMachineMethod); + this.custom_debug_information_table = GetTable (Table.CustomDebugInformation); + + this.document_map = new Dictionary (StringComparer.Ordinal); + this.import_scope_map = new Dictionary (row_equality_comparer); + } + + public MetadataBuilder (ModuleDefinition module, PortablePdbWriterProvider writer_provider) + { + this.module = module; + this.text_map = new TextMap (); + this.symbol_writer_provider = writer_provider; + this.portable_pdb = true; + + this.string_heap = new StringHeapBuffer (); + this.guid_heap = new GuidHeapBuffer (); + this.user_string_heap = new UserStringHeapBuffer (); + this.blob_heap = new BlobHeapBuffer (); + this.table_heap = new TableHeapBuffer (module, this); + this.pdb_heap = new PdbHeapBuffer(); + + this.document_table = GetTable (Table.Document); + this.method_debug_information_table = GetTable (Table.MethodDebugInformation); + this.local_scope_table = GetTable (Table.LocalScope); + this.local_variable_table = GetTable (Table.LocalVariable); + this.local_constant_table = GetTable (Table.LocalConstant); + this.import_scope_table = GetTable (Table.ImportScope); + this.state_machine_method_table = GetTable (Table.StateMachineMethod); + this.custom_debug_information_table = GetTable (Table.CustomDebugInformation); + + var row_equality_comparer = new RowEqualityComparer (); + + this.document_map = new Dictionary (); + this.import_scope_map = new Dictionary (row_equality_comparer); } TextMap CreateTextMap () @@ -802,6 +982,11 @@ namespace Mono.Cecil { return string_heap.GetStringIndex (@string); } + uint GetGuidIndex (Guid guid) + { + return guid_heap.GetGuidIndex (guid); + } + uint GetBlobIndex (ByteBuffer blob) { if (blob.length == 0) @@ -828,7 +1013,8 @@ namespace Mono.Cecil { void BuildModule () { var table = GetTable (Table.Module); - table.row = GetStringIndex (module.Name); + table.row.Col1 = GetStringIndex (module.Name); + table.row.Col2 = GetGuidIndex (module.Mvid); var assembly = module.Assembly; @@ -896,6 +1082,9 @@ namespace Mono.Cecil { if (module.IsMain) continue; +#if PCL || NET_CORE + throw new NotSupportedException (); +#else var parameters = new WriterParameters { SymbolWriterProvider = symbol_writer_provider, }; @@ -909,9 +1098,11 @@ namespace Mono.Cecil { FileAttributes.ContainsMetaData, GetStringIndex (module.Name), GetBlobIndex (hash))); +#endif } } +#if !PCL && !NET_CORE string GetModuleFileName (string name) { if (string.IsNullOrEmpty (name)) @@ -920,12 +1111,16 @@ namespace Mono.Cecil { var path = Path.GetDirectoryName (fq_name); return Path.Combine (path, name); } +#endif void AddAssemblyReferences () { var references = module.AssemblyReferences; var table = GetTable (Table.AssemblyRef); + if (module.IsWindowsMetadata ()) + module.Projections.RemoveVirtualReferences (references); + for (int i = 0; i < references.Count; i++) { var reference = references [i]; @@ -948,6 +1143,9 @@ namespace Mono.Cecil { reference.token = new MetadataToken (TokenType.AssemblyRef, rid); } + + if (module.IsWindowsMetadata ()) + module.Projections.AddVirtualReferences (references); } void AddModuleReferences () @@ -1003,10 +1201,12 @@ namespace Mono.Cecil { uint AddLinkedResource (LinkedResource resource) { var table = GetTable (Table.File); + var hash = resource.Hash; - var hash = resource.Hash.IsNullOrEmpty () - ? CryptoService.ComputeHash (resource.File) - : resource.Hash; +#if !PCL && !NET_CORE + if (hash.IsNullOrEmpty ()) + hash = CryptoService.ComputeHash (resource.File); +#endif return (uint) table.AddRow (new FileRow ( FileAttributes.ContainsNoMetaData, @@ -1112,20 +1312,8 @@ namespace Mono.Cecil { { var methods = type.Methods; type.methods_range.Length = (uint) methods.Count; - for (int i = 0; i < methods.Count; i++) { - var method = methods [i]; - var new_token = new MetadataToken (TokenType.Method, method_rid++); - - if (write_symbols && method.token != MetadataToken.Zero) - method_def_map.Add (new_token, method.token); - - method.token = new_token; - } - } - - public bool TryGetOriginalMethodToken (MetadataToken new_token, out MetadataToken original) - { - return method_def_map.TryGetValue (new_token, out original); + for (int i = 0; i < methods.Count; i++) + methods [i].token = new MetadataToken (TokenType.Method, method_rid++); } MetadataToken GetTypeToken (TypeReference type) @@ -1164,25 +1352,28 @@ namespace Mono.Cecil { MetadataToken GetTypeRefToken (TypeReference type) { - MetadataToken token; + MetadataToken ctoken; if (module.CustomMetadataWriter != null) { - if (module.CustomMetadataWriter.CreateTypeRefToken (ref type, out token)) - return token; + if (module.CustomMetadataWriter.CreateTypeRefToken (ref type, out ctoken)) + return ctoken; } + var projection = WindowsRuntimeProjections.RemoveProjection (type); + var row = CreateTypeRefRow (type); - if (type_ref_map.TryGetValue (row, out token)) - return token; + MetadataToken token; + if (!type_ref_map.TryGetValue (row, out token)) + token = AddTypeReference (type, row); - return AddTypeReference (type, row); + WindowsRuntimeProjections.ApplyProjection (type, projection); + + return token; } TypeRefRow CreateTypeRefRow (TypeReference type) { - var scope_token = type.IsNested - ? GetTypeRefToken (type.DeclaringType) - : type.Scope.MetadataToken; + var scope_token = GetScopeToken (type); return new TypeRefRow ( MakeCodedRID (scope_token, CodedIndex.ResolutionScope), @@ -1190,6 +1381,19 @@ namespace Mono.Cecil { GetStringIndex (type.Namespace)); } + MetadataToken GetScopeToken (TypeReference type) + { + if (type.IsNested) + return GetTypeRefToken (type.DeclaringType); + + var scope = type.Scope; + + if (scope == null) + return MetadataToken.Zero; + + return scope.MetadataToken; + } + static CodedRID MakeCodedRID (IMetadataTokenProvider provider, CodedIndex index) { return MakeCodedRID (provider.MetadataToken, index); @@ -1219,6 +1423,8 @@ namespace Mono.Cecil { void AddType (TypeDefinition type) { + var treatment = WindowsRuntimeProjections.RemoveProjection (type); + type_def_table.AddRow (new TypeDefRow ( type.Attributes, GetStringIndex (type.Name), @@ -1256,6 +1462,8 @@ namespace Mono.Cecil { if (type.HasNestedTypes) AddNestedTypes (type); + + WindowsRuntimeProjections.ApplyProjection (type, treatment); } void AddGenericParameters (IGenericParameterProvider owner) @@ -1327,10 +1535,18 @@ namespace Mono.Cecil { var interfaces = type.Interfaces; var type_rid = type.token.RID; - for (int i = 0; i < interfaces.Count; i++) - iface_impl_table.AddRow (new InterfaceImplRow ( + for (int i = 0; i < interfaces.Count; i++) { + var iface_impl = interfaces [i]; + + var rid = iface_impl_table.AddRow (new InterfaceImplRow ( type_rid, - MakeCodedRID (GetTypeToken (interfaces [i]), CodedIndex.TypeDefOrRef))); + MakeCodedRID (GetTypeToken (iface_impl.InterfaceType), CodedIndex.TypeDefOrRef))); + + iface_impl.token = new MetadataToken (TokenType.InterfaceImpl, rid); + + if (iface_impl.HasCustomAttributes) + AddCustomAttributes (iface_impl); + } } void AddLayoutInfo (TypeDefinition type) @@ -1365,6 +1581,8 @@ namespace Mono.Cecil { void AddField (FieldDefinition field) { + var projection = WindowsRuntimeProjections.RemoveProjection (field); + field_table.AddRow (new FieldRow ( field.Attributes, GetStringIndex (field.Name), @@ -1384,6 +1602,8 @@ namespace Mono.Cecil { if (field.HasMarshalInfo) AddMarshalInfo (field); + + WindowsRuntimeProjections.ApplyProjection (field, projection); } void AddFieldRVA (FieldDefinition field) @@ -1410,6 +1630,8 @@ namespace Mono.Cecil { void AddMethod (MethodDefinition method) { + var projection = WindowsRuntimeProjections.RemoveProjection (method); + method_table.AddRow (new MethodRow ( method.HasBody ? code.WriteMethodBody (method) : 0, method.ImplAttributes, @@ -1434,6 +1656,8 @@ namespace Mono.Cecil { if (method.HasOverrides) AddOverrides (method); + + WindowsRuntimeProjections.ApplyProjection (method, projection); } void AddParameters (MethodDefinition method) @@ -1645,6 +1869,11 @@ namespace Mono.Cecil { case ElementType.Var: return ElementType.Class; case ElementType.GenericInst: + var generic_instance = (GenericInstanceType) constant_type; + if (generic_instance.ElementType.IsTypeOf ("System", "Nullable`1")) + return GetConstantType (generic_instance.GenericArguments [0], constant); + + return GetConstantType (((TypeSpecification) constant_type).ElementType, constant); case ElementType.CModOpt: case ElementType.CModReqD: case ElementType.ByRef: @@ -1672,7 +1901,7 @@ namespace Mono.Cecil { static ElementType GetConstantType (Type type) { - switch (Type.GetTypeCode (type)) { + switch (type.GetTypeCode ()) { case TypeCode.Boolean: return ElementType.Boolean; case TypeCode.Byte: @@ -1711,10 +1940,14 @@ namespace Mono.Cecil { for (int i = 0; i < custom_attributes.Count; i++) { var attribute = custom_attributes [i]; + var projection = WindowsRuntimeProjections.RemoveProjection (attribute); + custom_attribute_table.AddRow (new CustomAttributeRow ( MakeCodedRID (owner, CodedIndex.HasCustomAttribute), MakeCodedRID (LookupToken (attribute.Constructor), CodedIndex.CustomAttributeType), GetBlobIndex (GetCustomAttributeSignature (attribute)))); + + WindowsRuntimeProjections.ApplyProjection (attribute, projection); } } @@ -1734,15 +1967,17 @@ namespace Mono.Cecil { MetadataToken GetMemberRefToken (MemberReference member) { + var projection = WindowsRuntimeProjections.RemoveProjection (member); + var row = CreateMemberRefRow (member); MetadataToken token; - if (member_ref_map.TryGetValue (row, out token)) - return token; + if (!member_ref_map.TryGetValue (row, out token)) + token = AddMemberReference (member, row); - AddMemberReference (member, row); + WindowsRuntimeProjections.ApplyProjection (member, projection); - return member.token; + return token; } MemberRefRow CreateMemberRefRow (MemberReference member) @@ -1753,10 +1988,13 @@ namespace Mono.Cecil { GetBlobIndex (GetMemberRefSignature (member))); } - void AddMemberReference (MemberReference member, MemberRefRow row) + MetadataToken AddMemberReference (MemberReference member, MemberRefRow row) { member.token = new MetadataToken (TokenType.MemberRef, member_ref_table.AddRow (row)); - member_ref_map.Add (row, member.token); + + var token = member.token; + member_ref_map.Add (row, token); + return token; } MetadataToken GetMethodSpecToken (MethodSpecification method_spec) @@ -1967,6 +2205,9 @@ namespace Mono.Cecil { if (provider == null) throw new ArgumentNullException (); + if (metadata_builder != null) + return metadata_builder.LookupToken (provider); + var member = provider as MemberReference; if (member == null || member.Module != module) throw CreateForeignMemberException (member); @@ -1992,6 +2233,342 @@ namespace Mono.Cecil { throw new NotSupportedException (); } } + + public void AddMethodDebugInformation (MethodDebugInformation method_info) + { + if (method_info.HasSequencePoints) + AddSequencePoints (method_info); + + if (method_info.Scope != null) + AddLocalScope (method_info, method_info.Scope); + + if (method_info.StateMachineKickOffMethod != null) + AddStateMachineMethod (method_info); + + AddCustomDebugInformations (method_info.Method); + } + + void AddStateMachineMethod (MethodDebugInformation method_info) + { + state_machine_method_table.AddRow (new StateMachineMethodRow (method_info.Method.MetadataToken.RID, method_info.StateMachineKickOffMethod.MetadataToken.RID)); + } + + void AddLocalScope (MethodDebugInformation method_info, ScopeDebugInformation scope) + { + var rid = local_scope_table.AddRow (new LocalScopeRow ( + method_info.Method.MetadataToken.RID, + AddImportScope (scope.Import), + local_variable_rid, + local_constant_rid, + (uint) scope.Start.Offset, + (uint) ((scope.End.IsEndOfMethod ? method_info.code_size : scope.End.Offset) - scope.Start.Offset))); + + scope.token = new MetadataToken (TokenType.LocalScope, rid); + + AddCustomDebugInformations (scope); + + if (scope.HasVariables) + AddLocalVariables (scope); + + if (scope.HasConstants) + AddLocalConstants (scope); + + if (scope.Import != null) + AddImportScope (scope.Import); + + for (int i = 0; i < scope.Scopes.Count; i++) + AddLocalScope (method_info, scope.Scopes [i]); + } + + void AddLocalVariables (ScopeDebugInformation scope) + { + for (int i = 0; i < scope.Variables.Count; i++) { + var variable = scope.Variables [i]; + local_variable_table.AddRow (new LocalVariableRow (variable.Attributes, (ushort) variable.Index, GetStringIndex (variable.Name))); + variable.token = new MetadataToken (TokenType.LocalVariable, local_variable_rid); + local_variable_rid++; + + AddCustomDebugInformations (variable); + } + } + + void AddLocalConstants (ScopeDebugInformation scope) + { + for (int i = 0; i < scope.Constants.Count; i++) { + var constant = scope.Constants [i]; + local_constant_table.AddRow (new LocalConstantRow (GetStringIndex (constant.Name), GetBlobIndex (GetConstantSignature(constant)))); + constant.token = new MetadataToken (TokenType.LocalConstant, local_constant_rid); + local_constant_rid++; + } + } + + SignatureWriter GetConstantSignature (ConstantDebugInformation constant) + { + var type = constant.ConstantType; + + var signature = CreateSignatureWriter (); + signature.WriteTypeSignature (type); + + if (type.IsTypeOf ("System", "Decimal")) { + var bits = decimal.GetBits ((decimal) constant.Value); + + var low = (uint) bits [0]; + var mid = (uint) bits [1]; + var high = (uint) bits [2]; + + var scale = (byte) (bits [3] >> 16); + var negative = (bits [3] & 0x80000000) != 0; + + signature.WriteByte ((byte) (scale | (negative ? 0x80 : 0x00))); + signature.WriteUInt32 (low); + signature.WriteUInt32 (mid); + signature.WriteUInt32 (high); + + return signature; + } + + if (type.IsTypeOf ("System", "DateTime")) { + var date = (DateTime) constant.Value; + signature.WriteInt64 (date.Ticks); + return signature; + } + + signature.WriteBytes (GetConstantSignature (type.etype, constant.Value)); + + return signature; + } + + void AddCustomDebugInformations (ICustomDebugInformationProvider provider) + { + if (!provider.HasCustomDebugInformations) + return; + + var custom_infos = provider.CustomDebugInformations; + + for (int i = 0; i < custom_infos.Count; i++) { + var custom_info = custom_infos [i]; + switch (custom_info.Kind) { + case CustomDebugInformationKind.Binary: + var binary_info = (BinaryCustomDebugInformation) custom_info; + AddCustomDebugInformation (provider, binary_info, GetBlobIndex (binary_info.Data)); + break; + case CustomDebugInformationKind.AsyncMethodBody: + AddAsyncMethodBodyDebugInformation (provider, (AsyncMethodBodyDebugInformation) custom_info); + break; + case CustomDebugInformationKind.StateMachineScope: + AddStateMachineScopeDebugInformation (provider, (StateMachineScopeDebugInformation) custom_info); + break; + default: + throw new NotImplementedException (); + } + } + } + + void AddStateMachineScopeDebugInformation (ICustomDebugInformationProvider provider, StateMachineScopeDebugInformation state_machine_scope) + { + var method_info = ((MethodDefinition) provider).DebugInformation; + + var signature = CreateSignatureWriter (); + signature.WriteUInt32 ((uint) state_machine_scope.Start.Offset); + + var end_offset = state_machine_scope.End.IsEndOfMethod + ? method_info.code_size + : state_machine_scope.End.Offset; + + signature.WriteUInt32 ((uint) (end_offset - state_machine_scope.Start.Offset)); + + AddCustomDebugInformation (provider, state_machine_scope, signature); + } + + void AddAsyncMethodBodyDebugInformation (ICustomDebugInformationProvider provider, AsyncMethodBodyDebugInformation async_method) + { + var signature = CreateSignatureWriter (); + signature.WriteUInt32 ((uint) async_method.catch_handler.Offset + 1); + + for (int i = 0; i < async_method.yields.Count; i++) { + signature.WriteUInt32 ((uint) async_method.yields [i].Offset); + signature.WriteUInt32 ((uint) async_method.resumes [i].Offset); + signature.WriteCompressedUInt32 (async_method.move_next.MetadataToken.RID); + } + + AddCustomDebugInformation (provider, async_method, signature); + } + + void AddCustomDebugInformation (ICustomDebugInformationProvider provider, CustomDebugInformation custom_info, SignatureWriter signature) + { + AddCustomDebugInformation (provider, custom_info, GetBlobIndex (signature)); + } + + void AddCustomDebugInformation (ICustomDebugInformationProvider provider, CustomDebugInformation custom_info, uint blob_index) + { + var rid = custom_debug_information_table.AddRow (new CustomDebugInformationRow ( + MakeCodedRID (provider.MetadataToken, CodedIndex.HasCustomDebugInformation), + GetGuidIndex (custom_info.Identifier), + blob_index)); + + custom_info.token = new MetadataToken (TokenType.CustomDebugInformation, rid); + } + + uint AddImportScope (ImportDebugInformation import) + { + uint parent = 0; + if (import.Parent != null) + parent = AddImportScope (import.Parent); + + uint targets_index = 0; + if (import.HasTargets) { + var signature = CreateSignatureWriter (); + + for (int i = 0; i < import.Targets.Count; i++) + AddImportTarget (import.Targets [i], signature); + + targets_index = GetBlobIndex (signature); + } + + var row = new ImportScopeRow (parent, targets_index); + + MetadataToken import_token; + if (import_scope_map.TryGetValue (row, out import_token)) + return import_token.RID; + + import_token = new MetadataToken (TokenType.ImportScope, import_scope_table.AddRow (row)); + import_scope_map.Add (row, import_token); + + return import_token.RID; + } + + void AddImportTarget (ImportTarget target, SignatureWriter signature) + { + signature.WriteCompressedUInt32 ((uint)target.kind); + + switch (target.kind) { + case ImportTargetKind.ImportNamespace: + signature.WriteCompressedUInt32 (GetUTF8StringBlobIndex (target.@namespace)); + break; + case ImportTargetKind.ImportNamespaceInAssembly: + signature.WriteCompressedUInt32 (target.reference.MetadataToken.RID); + signature.WriteCompressedUInt32 (GetUTF8StringBlobIndex (target.@namespace)); + break; + case ImportTargetKind.ImportType: + signature.WriteTypeToken (target.type); + break; + case ImportTargetKind.ImportXmlNamespaceWithAlias: + signature.WriteCompressedUInt32 (GetUTF8StringBlobIndex (target.alias)); + signature.WriteCompressedUInt32 (GetUTF8StringBlobIndex (target.@namespace)); + break; + case ImportTargetKind.ImportAlias: + signature.WriteCompressedUInt32 (GetUTF8StringBlobIndex (target.alias)); + break; + case ImportTargetKind.DefineAssemblyAlias: + signature.WriteCompressedUInt32 (GetUTF8StringBlobIndex (target.alias)); + signature.WriteCompressedUInt32 (target.reference.MetadataToken.RID); + break; + case ImportTargetKind.DefineNamespaceAlias: + signature.WriteCompressedUInt32 (GetUTF8StringBlobIndex (target.alias)); + signature.WriteCompressedUInt32 (GetUTF8StringBlobIndex (target.@namespace)); + break; + case ImportTargetKind.DefineNamespaceInAssemblyAlias: + signature.WriteCompressedUInt32 (GetUTF8StringBlobIndex (target.alias)); + signature.WriteCompressedUInt32 (target.reference.MetadataToken.RID); + signature.WriteCompressedUInt32 (GetUTF8StringBlobIndex (target.@namespace)); + break; + case ImportTargetKind.DefineTypeAlias: + signature.WriteCompressedUInt32 (GetUTF8StringBlobIndex (target.alias)); + signature.WriteTypeToken (target.type); + break; + } + } + + uint GetUTF8StringBlobIndex (string s) + { + return GetBlobIndex (Encoding.UTF8.GetBytes (s)); + } + + public MetadataToken GetDocumentToken (Document document) + { + MetadataToken token; + if (document_map.TryGetValue (document.Url, out token)) + return token; + + token = new MetadataToken (TokenType.Document, document_table.AddRow ( + new DocumentRow (GetBlobIndex (GetDocumentNameSignature (document)), + GetGuidIndex (document.HashAlgorithm.ToGuid ()), + GetBlobIndex (document.Hash), + GetGuidIndex (document.Language.ToGuid ())))); + + document.token = token; + + document_map.Add (document.Url, token); + + return token; + } + + SignatureWriter GetDocumentNameSignature (Document document) + { + var name = document.Url; + var signature = CreateSignatureWriter (); + + char separator; + if (!TryGetDocumentNameSeparator (name, out separator)) { + signature.WriteByte (0); + signature.WriteCompressedUInt32 (GetUTF8StringBlobIndex (name)); + return signature; + } + + signature.WriteByte ((byte) separator); + + var parts = name.Split (new [] { separator }, StringSplitOptions.RemoveEmptyEntries); + for (int i = 0; i < parts.Length; i++) + signature.WriteCompressedUInt32 (GetUTF8StringBlobIndex (parts [i])); + + return signature; + } + + static bool TryGetDocumentNameSeparator (string path, out char separator) + { + const char unix = '/'; + const char win = '\\'; + const char zero = (char) 0; + + separator = zero; + if (string.IsNullOrEmpty (path)) + return false; + + int unix_count = 0; + int win_count = 0; + + for (int i = 0; i < path.Length; i++) { + if (path [i] == unix) + unix_count++; + else if (path [i] == win) + win_count++; + } + + if (unix_count == 0 && win_count == 0) + return false; + + if (unix_count >= win_count) { + separator = unix; + return true; + } + + separator = win; + return true; + } + + void AddSequencePoints (MethodDebugInformation info) + { + var rid = info.Method.MetadataToken.RID; + + Document document; + if (info.TryGetUniqueDocument (out document)) + method_debug_information_table.rows [rid - 1].Col1 = GetDocumentToken (document).RID; + + var signature = CreateSignatureWriter (); + signature.WriteSequencePoints (info); + + method_debug_information_table.rows [rid - 1].Col2 = GetBlobIndex (signature); + } } sealed class SignatureWriter : ByteBuffer { @@ -2061,6 +2638,11 @@ namespace Mono.Cecil { return CodedIndex.TypeDefOrRef.CompressMetadataToken (metadata.LookupToken (type)); } + public void WriteTypeToken (TypeReference type) + { + WriteCompressedUInt32 (MakeTypeDefOrRefCodedRID (type)); + } + public void WriteTypeSignature (TypeReference type) { if (type == null) @@ -2215,7 +2797,10 @@ namespace Mono.Cecil { public void WriteConstantString (string value) { - WriteBytes (Encoding.Unicode.GetBytes (value)); + if (value != null) + WriteBytes (Encoding.Unicode.GetBytes (value)); + else + WriteByte (0xff); } public void WriteConstantPrimitive (object value) @@ -2316,7 +2901,7 @@ namespace Mono.Cecil { if (value == null) throw new ArgumentNullException (); - switch (Type.GetTypeCode (value.GetType ())) { + switch (value.GetType ().GetTypeCode ()) { case TypeCode.Boolean: WriteByte ((byte) (((bool) value) ? 1 : 0)); break; @@ -2569,8 +3154,81 @@ namespace Mono.Cecil { { WriteByte ((byte) variant); } + + public void WriteSequencePoints (MethodDebugInformation info) + { + var start_line = -1; + var start_column = -1; + + WriteCompressedUInt32 (info.local_var_token.RID); + + Document previous_document; + if (!info.TryGetUniqueDocument (out previous_document)) + previous_document = null; + + for (int i = 0; i < info.SequencePoints.Count; i++) { + var sequence_point = info.SequencePoints [i]; + + var document = sequence_point.Document; + if (previous_document != document) { + var document_token = metadata.GetDocumentToken (document); + + if (previous_document != null) + WriteCompressedUInt32 (0); + + WriteCompressedUInt32 (document_token.RID); + previous_document = document; + } + + if (i > 0) + WriteCompressedUInt32 ((uint) (sequence_point.Offset - info.SequencePoints [i - 1].Offset)); + else + WriteCompressedUInt32 ((uint) sequence_point.Offset); + + if (sequence_point.IsHidden) { + WriteInt16 (0); + continue; + } + + var delta_lines = sequence_point.EndLine - sequence_point.StartLine; + var delta_columns = sequence_point.EndColumn - sequence_point.StartColumn; + + WriteCompressedUInt32 ((uint) delta_lines); + + if (delta_lines == 0) + WriteCompressedUInt32((uint) delta_columns); + else + WriteCompressedInt32 (delta_columns); + + if (start_line < 0) { + WriteCompressedUInt32 ((uint) sequence_point.StartLine); + WriteCompressedUInt32 ((uint) sequence_point.StartColumn); + } else { + WriteCompressedInt32 (sequence_point.StartLine - start_line); + WriteCompressedInt32 (sequence_point.StartColumn - start_column); + } + + start_line = sequence_point.StartLine; + start_column = sequence_point.StartColumn; + } + } } #endif + static partial class Mixin { + + public static bool TryGetUniqueDocument (this MethodDebugInformation info, out Document document) + { + document = info.SequencePoints [0].Document; + + for (int i = 1; i < info.SequencePoints.Count; i++) { + var sequence_point = info.SequencePoints [i]; + if (sequence_point.Document != document) + return false; + } + + return true; + } + } } diff --git a/external/cecil/Mono.Cecil/BaseAssemblyResolver.cs b/external/cecil/Mono.Cecil/BaseAssemblyResolver.cs index 90be7bfb99..1ddf2012c7 100644 --- a/external/cecil/Mono.Cecil/BaseAssemblyResolver.cs +++ b/external/cecil/Mono.Cecil/BaseAssemblyResolver.cs @@ -1,31 +1,15 @@ // -// BaseAssemblyResolver.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // +#if !PCL && !NET_CORE + using System; using System.Collections.Generic; using System.IO; @@ -51,10 +35,8 @@ namespace Mono.Cecil { } } -#if !SILVERLIGHT && !CF [Serializable] -#endif - public class AssemblyResolutionException : FileNotFoundException { + public sealed class AssemblyResolutionException : FileNotFoundException { readonly AssemblyNameReference reference; @@ -68,14 +50,12 @@ namespace Mono.Cecil { this.reference = reference; } -#if !SILVERLIGHT && !CF - protected AssemblyResolutionException ( + AssemblyResolutionException ( System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base (info, context) { } -#endif } public abstract class BaseAssemblyResolver : IAssemblyResolver { @@ -84,9 +64,7 @@ namespace Mono.Cecil { readonly Collection directories; -#if !SILVERLIGHT && !CF Collection gac_paths; -#endif public void AddSearchDirectory (string directory) { @@ -149,10 +127,9 @@ namespace Mono.Cecil { if (assembly != null) return assembly; -#if !SILVERLIGHT && !CF if (name.IsRetargetable) { // if the reference is retargetable, zero it - name = new AssemblyNameReference (name.Name, new Version (0, 0, 0, 0)) { + name = new AssemblyNameReference (name.Name, Mixin.ZeroVersion) { PublicKeyToken = Empty.Array, }; } @@ -178,7 +155,6 @@ namespace Mono.Cecil { assembly = SearchDirectory (name, new [] { framework_dir }, parameters); if (assembly != null) return assembly; -#endif if (ResolveFailure != null) { assembly = ResolveFailure (this, name); @@ -191,7 +167,7 @@ namespace Mono.Cecil { AssemblyDefinition SearchDirectory (AssemblyNameReference name, IEnumerable directories, ReaderParameters parameters) { - var extensions = new [] { ".exe", ".dll" }; + var extensions = name.IsWindowsRuntime ? new [] { ".winmd", ".dll" } : new [] { ".exe", ".dll" }; foreach (var directory in directories) { foreach (var extension in extensions) { string file = Path.Combine (directory, name.Name + extension); @@ -205,10 +181,9 @@ namespace Mono.Cecil { static bool IsZero (Version version) { - return version == null || (version.Major == 0 && version.Minor == 0 && version.Build == 0 && version.Revision == 0); + return version.Major == 0 && version.Minor == 0 && version.Build == 0 && version.Revision == 0; } -#if !SILVERLIGHT && !CF AssemblyDefinition GetCorlib (AssemblyNameReference reference, ReaderParameters parameters) { var version = reference.Version; @@ -335,7 +310,7 @@ namespace Mono.Cecil { AssemblyDefinition GetAssemblyInNetGac (AssemblyNameReference reference, ReaderParameters parameters) { - var gacs = new [] { "GAC_MSIL", "GAC_32", "GAC" }; + var gacs = new [] { "GAC_MSIL", "GAC_32", "GAC_64", "GAC" }; var prefixes = new [] { string.Empty, "v4.0_" }; for (int i = 0; i < 2; i++) { @@ -365,6 +340,17 @@ namespace Mono.Cecil { Path.Combine (gac, reference.Name), gac_folder.ToString ()), reference.Name + ".dll"); } -#endif + + public void Dispose () + { + Dispose (true); + GC.SuppressFinalize (this); + } + + protected virtual void Dispose (bool disposing) + { + } } } + +#endif diff --git a/external/cecil/Mono.Cecil/CallSite.cs b/external/cecil/Mono.Cecil/CallSite.cs index 2d4ed41759..ebb108f298 100644 --- a/external/cecil/Mono.Cecil/CallSite.cs +++ b/external/cecil/Mono.Cecil/CallSite.cs @@ -1,29 +1,11 @@ // -// CallSite.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; diff --git a/external/cecil/Mono.Cecil/CustomAttribute.cs b/external/cecil/Mono.Cecil/CustomAttribute.cs index 76372db0ee..11dcb8911b 100644 --- a/external/cecil/Mono.Cecil/CustomAttribute.cs +++ b/external/cecil/Mono.Cecil/CustomAttribute.cs @@ -1,29 +1,11 @@ // -// CustomAttribute.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; @@ -86,6 +68,7 @@ namespace Mono.Cecil { public sealed class CustomAttribute : ICustomAttribute { + internal CustomAttributeValueProjection projection; readonly internal uint signature; internal bool resolved; MethodReference constructor; @@ -191,7 +174,7 @@ namespace Mono.Cecil { if (!HasImage) throw new NotSupportedException (); - return blob = Module.Read (this, (attribute, reader) => reader.ReadCustomAttributeBlob (attribute.signature)); + return Module.Read (ref blob, this, (attribute, reader) => reader.ReadCustomAttributeBlob (attribute.signature)); } void Resolve () @@ -199,23 +182,22 @@ namespace Mono.Cecil { if (resolved || !HasImage) return; - try { - Module.Read (this, (attribute, reader) => { + Module.Read (this, (attribute, reader) => { + try { reader.ReadCustomAttributeSignature (attribute); - return this; - }); + resolved = true; + } catch (ResolutionException) { + if (arguments != null) + arguments.Clear (); + if (fields != null) + fields.Clear (); + if (properties != null) + properties.Clear (); - resolved = true; - } catch (ResolutionException) { - if (arguments != null) - arguments.Clear (); - if (fields != null) - fields.Clear (); - if (properties != null) - properties.Clear (); - - resolved = false; - } + resolved = false; + } + return this; + }); } } diff --git a/external/cecil/Mono.Cecil/DefaultAssemblyResolver.cs b/external/cecil/Mono.Cecil/DefaultAssemblyResolver.cs index e0baedf77a..d33b563d93 100644 --- a/external/cecil/Mono.Cecil/DefaultAssemblyResolver.cs +++ b/external/cecil/Mono.Cecil/DefaultAssemblyResolver.cs @@ -1,31 +1,15 @@ // -// DefaultAssemblyResolver.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // +#if !PCL && !NET_CORE + using System; using System.Collections.Generic; @@ -66,5 +50,17 @@ namespace Mono.Cecil { cache [name] = assembly; } + + protected override void Dispose (bool disposing) + { + foreach (var assembly in cache.Values) + assembly.Dispose (); + + cache.Clear (); + + base.Dispose (disposing); + } } } + +#endif diff --git a/external/cecil/Mono.Cecil/EmbeddedResource.cs b/external/cecil/Mono.Cecil/EmbeddedResource.cs index e12dd0b378..6b5f86a12e 100644 --- a/external/cecil/Mono.Cecil/EmbeddedResource.cs +++ b/external/cecil/Mono.Cecil/EmbeddedResource.cs @@ -1,29 +1,11 @@ // -// EmbeddedResource.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; @@ -71,7 +53,7 @@ namespace Mono.Cecil { return new MemoryStream (data); if (offset.HasValue) - return reader.GetManagedResourceStream (offset.Value); + return new MemoryStream (reader.GetManagedResource (offset.Value)); throw new InvalidOperationException (); } @@ -85,21 +67,32 @@ namespace Mono.Cecil { return data; if (offset.HasValue) - return reader.GetManagedResourceStream (offset.Value).ToArray (); + return reader.GetManagedResource (offset.Value); throw new InvalidOperationException (); } static byte [] ReadStream (Stream stream) { - var length = (int) stream.Length; - var data = new byte [length]; - int offset = 0, read; + int read; - while ((read = stream.Read (data, offset, length - offset)) > 0) - offset += read; + if (stream.CanSeek) { + var length = (int) stream.Length; + var data = new byte [length]; + int offset = 0; - return data; + while ((read = stream.Read (data, offset, length - offset)) > 0) + offset += read; + + return data; + } + + var buffer = new byte [1024 * 8]; + var memory = new MemoryStream (); + while ((read = stream.Read (buffer, 0, buffer.Length)) > 0) + memory.Write (buffer, 0, read); + + return memory.ToArray (); } } } diff --git a/external/cecil/Mono.Cecil/EventAttributes.cs b/external/cecil/Mono.Cecil/EventAttributes.cs index 815efa57b7..9f823fd1e6 100644 --- a/external/cecil/Mono.Cecil/EventAttributes.cs +++ b/external/cecil/Mono.Cecil/EventAttributes.cs @@ -1,29 +1,11 @@ // -// EventAttributes.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; diff --git a/external/cecil/Mono.Cecil/EventDefinition.cs b/external/cecil/Mono.Cecil/EventDefinition.cs index 89b55483f7..33bc341adb 100644 --- a/external/cecil/Mono.Cecil/EventDefinition.cs +++ b/external/cecil/Mono.Cecil/EventDefinition.cs @@ -1,29 +1,11 @@ // -// EventDefinition.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using Mono.Collections.Generic; @@ -113,7 +95,7 @@ namespace Mono.Cecil { } public Collection CustomAttributes { - get { return custom_attributes ?? (custom_attributes = this.GetCustomAttributes (Module)); } + get { return custom_attributes ?? (this.GetCustomAttributes (ref custom_attributes, Module)); } } #region EventAttributes @@ -148,16 +130,21 @@ namespace Mono.Cecil { void InitializeMethods () { - if (add_method != null - || invoke_method != null - || remove_method != null) - return; - var module = this.Module; - if (!module.HasImage ()) + if (module == null) return; - module.Read (this, (@event, reader) => reader.ReadMethods (@event)); + lock (module.SyncRoot) { + if (add_method != null + || invoke_method != null + || remove_method != null) + return; + + if (!module.HasImage ()) + return; + + module.Read (this, (@event, reader) => reader.ReadMethods (@event)); + } } public override EventDefinition Resolve () diff --git a/external/cecil/Mono.Cecil/EventReference.cs b/external/cecil/Mono.Cecil/EventReference.cs index 8952002d6c..925a581ad4 100644 --- a/external/cecil/Mono.Cecil/EventReference.cs +++ b/external/cecil/Mono.Cecil/EventReference.cs @@ -1,29 +1,11 @@ // -// EventReference.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; @@ -52,6 +34,11 @@ namespace Mono.Cecil { event_type = eventType; } - public abstract EventDefinition Resolve (); + protected override IMemberDefinition ResolveDefinition () + { + return this.Resolve (); + } + + public new abstract EventDefinition Resolve (); } } diff --git a/external/cecil/Mono.Cecil/ExportedType.cs b/external/cecil/Mono.Cecil/ExportedType.cs index c25f8d05ea..fcf456fa49 100644 --- a/external/cecil/Mono.Cecil/ExportedType.cs +++ b/external/cecil/Mono.Cecil/ExportedType.cs @@ -1,36 +1,18 @@ // -// ExportedType.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; namespace Mono.Cecil { - public class ExportedType : IMetadataTokenProvider { + public sealed class ExportedType : IMetadataTokenProvider { string @namespace; string name; @@ -211,13 +193,14 @@ namespace Mono.Cecil { public string FullName { get { + var fullname = string.IsNullOrEmpty (@namespace) + ? name + : @namespace + '.' + name; + if (declaring_type != null) - return declaring_type.FullName + "/" + name; + return declaring_type.FullName + "/" + fullname; - if (string.IsNullOrEmpty (@namespace)) - return name; - - return @namespace + "." + name; + return fullname; } } diff --git a/external/cecil/Mono.Cecil/FieldAttributes.cs b/external/cecil/Mono.Cecil/FieldAttributes.cs index dd6bf361dc..7d5bb544a3 100644 --- a/external/cecil/Mono.Cecil/FieldAttributes.cs +++ b/external/cecil/Mono.Cecil/FieldAttributes.cs @@ -1,29 +1,11 @@ // -// FieldAttributes.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; diff --git a/external/cecil/Mono.Cecil/FieldDefinition.cs b/external/cecil/Mono.Cecil/FieldDefinition.cs index 29a1bc12ce..593b77e592 100644 --- a/external/cecil/Mono.Cecil/FieldDefinition.cs +++ b/external/cecil/Mono.Cecil/FieldDefinition.cs @@ -1,31 +1,14 @@ // -// FieldDefinition.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // +using System; using Mono.Collections.Generic; namespace Mono.Cecil { @@ -80,6 +63,11 @@ namespace Mono.Cecil { set { offset = value; } } + internal new FieldDefinitionProjection WindowsRuntimeProjection { + get { return (FieldDefinitionProjection) projection; } + set { projection = value; } + } + void ResolveRVA () { if (rva != Mixin.NotResolvedMarker) @@ -114,17 +102,25 @@ namespace Mono.Cecil { return initial_value; } - set { initial_value = value; } + set { + initial_value = value; + rva = 0; + } } public FieldAttributes Attributes { get { return (FieldAttributes) attributes; } - set { attributes = (ushort) value; } + set { + if (IsWindowsRuntimeProjection && (ushort) value != attributes) + throw new InvalidOperationException (); + + attributes = (ushort) value; + } } public bool HasConstant { get { - ResolveConstant (); + this.ResolveConstant (ref constant, Module); return constant != Mixin.NoValue; } @@ -136,14 +132,6 @@ namespace Mono.Cecil { set { constant = value; } } - void ResolveConstant () - { - if (constant != Mixin.NotResolved) - return; - - this.ResolveConstant (ref constant, Module); - } - public bool HasCustomAttributes { get { if (custom_attributes != null) @@ -154,7 +142,7 @@ namespace Mono.Cecil { } public Collection CustomAttributes { - get { return custom_attributes ?? (custom_attributes = this.GetCustomAttributes (Module)); } + get { return custom_attributes ?? (this.GetCustomAttributes (ref custom_attributes, Module)); } } public bool HasMarshalInfo { @@ -167,7 +155,7 @@ namespace Mono.Cecil { } public MarshalInfo MarshalInfo { - get { return marshal_info ?? (marshal_info = this.GetMarshalInfo (Module)); } + get { return marshal_info ?? (this.GetMarshalInfo (ref marshal_info, Module)); } set { marshal_info = value; } } diff --git a/external/cecil/Mono.Cecil/FieldReference.cs b/external/cecil/Mono.Cecil/FieldReference.cs index be58d3d063..f65a3005ab 100644 --- a/external/cecil/Mono.Cecil/FieldReference.cs +++ b/external/cecil/Mono.Cecil/FieldReference.cs @@ -1,29 +1,11 @@ // -// FieldReference.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; @@ -43,7 +25,7 @@ namespace Mono.Cecil { get { return field_type.FullName + " " + MemberFullName (); } } - internal override bool ContainsGenericParameter { + public override bool ContainsGenericParameter { get { return field_type.ContainsGenericParameter || base.ContainsGenericParameter; } } @@ -71,7 +53,12 @@ namespace Mono.Cecil { this.DeclaringType = declaringType; } - public virtual FieldDefinition Resolve () + protected override IMemberDefinition ResolveDefinition () + { + return this.Resolve (); + } + + public new virtual FieldDefinition Resolve () { var module = this.Module; if (module == null) diff --git a/external/cecil/Mono.Cecil/FileAttributes.cs b/external/cecil/Mono.Cecil/FileAttributes.cs index 4d3b6ca7ff..171f174b0b 100644 --- a/external/cecil/Mono.Cecil/FileAttributes.cs +++ b/external/cecil/Mono.Cecil/FileAttributes.cs @@ -1,29 +1,11 @@ // -// FileAttributes.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // namespace Mono.Cecil { diff --git a/external/cecil/Mono.Cecil/FunctionPointerType.cs b/external/cecil/Mono.Cecil/FunctionPointerType.cs index 756d31f6ff..0602fcbe8a 100644 --- a/external/cecil/Mono.Cecil/FunctionPointerType.cs +++ b/external/cecil/Mono.Cecil/FunctionPointerType.cs @@ -1,29 +1,11 @@ // -// FunctionPointerType.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; @@ -92,7 +74,7 @@ namespace Mono.Cecil { get { return true; } } - internal override bool ContainsGenericParameter { + public override bool ContainsGenericParameter { get { return function.ContainsGenericParameter; } } diff --git a/external/cecil/Mono.Cecil/GenericInstanceMethod.cs b/external/cecil/Mono.Cecil/GenericInstanceMethod.cs index dbe720df56..00de03a3bd 100644 --- a/external/cecil/Mono.Cecil/GenericInstanceMethod.cs +++ b/external/cecil/Mono.Cecil/GenericInstanceMethod.cs @@ -1,29 +1,11 @@ // -// GenericInstanceMethod.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; @@ -57,7 +39,7 @@ namespace Mono.Cecil { get { return ElementMethod.DeclaringType; } } - internal override bool ContainsGenericParameter { + public override bool ContainsGenericParameter { get { return this.ContainsGenericParameter () || base.ContainsGenericParameter; } } diff --git a/external/cecil/Mono.Cecil/GenericInstanceType.cs b/external/cecil/Mono.Cecil/GenericInstanceType.cs index 6554ff0e89..0e683e7134 100644 --- a/external/cecil/Mono.Cecil/GenericInstanceType.cs +++ b/external/cecil/Mono.Cecil/GenericInstanceType.cs @@ -1,29 +1,11 @@ // -// GenericInstanceType.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; @@ -65,7 +47,7 @@ namespace Mono.Cecil { get { return true; } } - internal override bool ContainsGenericParameter { + public override bool ContainsGenericParameter { get { return this.ContainsGenericParameter () || base.ContainsGenericParameter; } } diff --git a/external/cecil/Mono.Cecil/GenericParameter.cs b/external/cecil/Mono.Cecil/GenericParameter.cs index d66cc914cb..24024d2836 100644 --- a/external/cecil/Mono.Cecil/GenericParameter.cs +++ b/external/cecil/Mono.Cecil/GenericParameter.cs @@ -1,29 +1,11 @@ // -// GenericParameter.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; @@ -66,10 +48,7 @@ namespace Mono.Cecil { if (constraints != null) return constraints.Count > 0; - if (HasImage) - return Module.Read (this, (generic_parameter, reader) => reader.HasGenericConstraints (generic_parameter)); - - return false; + return HasImage && Module.Read (this, (generic_parameter, reader) => reader.HasGenericConstraints (generic_parameter)); } } @@ -79,7 +58,7 @@ namespace Mono.Cecil { return constraints; if (HasImage) - return constraints = Module.Read (this, (generic_parameter, reader) => reader.ReadGenericConstraints (generic_parameter)); + return Module.Read (ref constraints, this, (generic_parameter, reader) => reader.ReadGenericConstraints (generic_parameter)); return constraints = new Collection (); } @@ -95,7 +74,7 @@ namespace Mono.Cecil { } public Collection CustomAttributes { - get { return custom_attributes ?? (custom_attributes = this.GetCustomAttributes (Module)); } + get { return custom_attributes ?? (this.GetCustomAttributes (ref custom_attributes, Module)); } } public override IMetadataScope Scope { @@ -145,7 +124,7 @@ namespace Mono.Cecil { get { return true; } } - internal override bool ContainsGenericParameter { + public override bool ContainsGenericParameter { get { return true; } } @@ -202,9 +181,11 @@ namespace Mono.Cecil { this.owner = owner; this.type = owner.GenericParameterType; this.etype = ConvertGenericParameterType (this.type); + this.token = new MetadataToken (TokenType.GenericParam); + } - public GenericParameter (int position, GenericParameterType type, ModuleDefinition module) + internal GenericParameter (int position, GenericParameterType type, ModuleDefinition module) : base (string.Empty, string.Empty) { if (module == null) @@ -214,6 +195,7 @@ namespace Mono.Cecil { this.type = type; this.etype = ConvertGenericParameterType (type); this.module = module; + this.token = new MetadataToken (TokenType.GenericParam); } static ElementType ConvertGenericParameterType (GenericParameterType type) diff --git a/external/cecil/Mono.Cecil/GenericParameterAttributes.cs b/external/cecil/Mono.Cecil/GenericParameterAttributes.cs index 6d77956de3..149582cdba 100644 --- a/external/cecil/Mono.Cecil/GenericParameterAttributes.cs +++ b/external/cecil/Mono.Cecil/GenericParameterAttributes.cs @@ -1,29 +1,11 @@ // -// GenericParameterAttributes.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; diff --git a/external/cecil/Mono.Cecil/IConstantProvider.cs b/external/cecil/Mono.Cecil/IConstantProvider.cs index 8bcd7d7f02..178b66511b 100644 --- a/external/cecil/Mono.Cecil/IConstantProvider.cs +++ b/external/cecil/Mono.Cecil/IConstantProvider.cs @@ -1,29 +1,11 @@ // -// IConstantProvider.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // namespace Mono.Cecil { @@ -44,9 +26,19 @@ namespace Mono.Cecil { ref object constant, ModuleDefinition module) { - constant = module.HasImage () - ? module.Read (self, (provider, reader) => reader.ReadConstant (provider)) - : Mixin.NoValue; + if (module == null) { + constant = Mixin.NoValue; + return; + } + + lock (module.SyncRoot) { + if (constant != Mixin.NotResolved) + return; + if (module.HasImage ()) + constant = module.Read (self, (provider, reader) => reader.ReadConstant (provider)); + else + constant = Mixin.NoValue; + } } } } diff --git a/external/cecil/Mono.Cecil/ICustomAttributeProvider.cs b/external/cecil/Mono.Cecil/ICustomAttributeProvider.cs index 916ba0f541..36d7ed018f 100644 --- a/external/cecil/Mono.Cecil/ICustomAttributeProvider.cs +++ b/external/cecil/Mono.Cecil/ICustomAttributeProvider.cs @@ -1,33 +1,14 @@ // -// ICustomAttributeProvider.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; - using Mono.Collections.Generic; namespace Mono.Cecil { @@ -50,11 +31,12 @@ namespace Mono.Cecil { public static Collection GetCustomAttributes ( this ICustomAttributeProvider self, + ref Collection variable, ModuleDefinition module) { return module.HasImage () - ? module.Read (self, (provider, reader) => reader.ReadCustomAttributes (provider)) - : new Collection (); + ? module.Read (ref variable, self, (provider, reader) => reader.ReadCustomAttributes (provider)) + : variable = new Collection(); } } } diff --git a/external/cecil/Mono.Cecil/IGenericInstance.cs b/external/cecil/Mono.Cecil/IGenericInstance.cs index edc406ca10..e98d8189b0 100644 --- a/external/cecil/Mono.Cecil/IGenericInstance.cs +++ b/external/cecil/Mono.Cecil/IGenericInstance.cs @@ -1,29 +1,11 @@ // -// IGenericInstance.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System.Text; diff --git a/external/cecil/Mono.Cecil/IGenericParameterProvider.cs b/external/cecil/Mono.Cecil/IGenericParameterProvider.cs index d41b7f6d08..4c8dfc4da7 100644 --- a/external/cecil/Mono.Cecil/IGenericParameterProvider.cs +++ b/external/cecil/Mono.Cecil/IGenericParameterProvider.cs @@ -1,29 +1,11 @@ // -// IGenericParameterProvider.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // @@ -63,11 +45,12 @@ namespace Mono.Cecil { public static Collection GetGenericParameters ( this IGenericParameterProvider self, + ref Collection collection, ModuleDefinition module) { return module.HasImage () - ? module.Read (self, (provider, reader) => reader.ReadGenericParameters (provider)) - : new GenericParameterCollection (self); + ? module.Read (ref collection, self, (provider, reader) => reader.ReadGenericParameters (provider)) + : collection = new GenericParameterCollection (self); } } } diff --git a/external/cecil/Mono.Cecil/IMarshalInfoProvider.cs b/external/cecil/Mono.Cecil/IMarshalInfoProvider.cs index 67a53a389f..a1b9e88344 100644 --- a/external/cecil/Mono.Cecil/IMarshalInfoProvider.cs +++ b/external/cecil/Mono.Cecil/IMarshalInfoProvider.cs @@ -1,29 +1,11 @@ // -// IMarshalInfoProvider.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // namespace Mono.Cecil { @@ -45,10 +27,11 @@ namespace Mono.Cecil { public static MarshalInfo GetMarshalInfo ( this IMarshalInfoProvider self, + ref MarshalInfo variable, ModuleDefinition module) { return module.HasImage () - ? module.Read (self, (provider, reader) => reader.ReadMarshalInfo (provider)) + ? module.Read (ref variable, self, (provider, reader) => reader.ReadMarshalInfo (provider)) : null; } } diff --git a/external/cecil/Mono.Cecil/IMemberDefinition.cs b/external/cecil/Mono.Cecil/IMemberDefinition.cs index ee73d9da49..ad747002b9 100644 --- a/external/cecil/Mono.Cecil/IMemberDefinition.cs +++ b/external/cecil/Mono.Cecil/IMemberDefinition.cs @@ -1,29 +1,11 @@ // -// IMemberDefinition.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // namespace Mono.Cecil { diff --git a/external/cecil/Mono.Cecil/IMetadataScope.cs b/external/cecil/Mono.Cecil/IMetadataScope.cs index 04a0228105..2e56e758c8 100644 --- a/external/cecil/Mono.Cecil/IMetadataScope.cs +++ b/external/cecil/Mono.Cecil/IMetadataScope.cs @@ -1,29 +1,11 @@ // -// IMetadataScope.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // namespace Mono.Cecil { diff --git a/external/cecil/Mono.Cecil/IMetadataTokenProvider.cs b/external/cecil/Mono.Cecil/IMetadataTokenProvider.cs index 6621835b29..dcd678b03f 100644 --- a/external/cecil/Mono.Cecil/IMetadataTokenProvider.cs +++ b/external/cecil/Mono.Cecil/IMetadataTokenProvider.cs @@ -1,29 +1,11 @@ // -// IMetadataTokenProvider.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // namespace Mono.Cecil { diff --git a/external/cecil/Mono.Cecil/IMethodSignature.cs b/external/cecil/Mono.Cecil/IMethodSignature.cs index e3d288ba9f..4d7766e456 100644 --- a/external/cecil/Mono.Cecil/IMethodSignature.cs +++ b/external/cecil/Mono.Cecil/IMethodSignature.cs @@ -1,29 +1,11 @@ // -// IMethodSignature.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System.Text; diff --git a/external/cecil/Mono.Cecil/Import.cs b/external/cecil/Mono.Cecil/Import.cs index 93040101c9..846f6d5871 100644 --- a/external/cecil/Mono.Cecil/Import.cs +++ b/external/cecil/Mono.Cecil/Import.cs @@ -1,29 +1,11 @@ // -// Import.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; @@ -35,11 +17,32 @@ using Mono.Cecil.Metadata; namespace Mono.Cecil { - enum ImportGenericKind { - Definition, - Open, +#if !READ_ONLY + + public interface IMetadataImporterProvider { + IMetadataImporter GetMetadataImporter (ModuleDefinition module); } + public interface IMetadataImporter { + TypeReference ImportReference (TypeReference type, IGenericParameterProvider context); + FieldReference ImportReference (FieldReference field, IGenericParameterProvider context); + MethodReference ImportReference (MethodReference method, IGenericParameterProvider context); + } + +#if !PCL && !NET_CORE + + public interface IReflectionImporterProvider { + IReflectionImporter GetReflectionImporter (ModuleDefinition module); + } + + public interface IReflectionImporter { + TypeReference ImportReference (Type type, IGenericParameterProvider context); + FieldReference ImportReference (SR.FieldInfo field, IGenericParameterProvider context); + MethodReference ImportReference (SR.MethodBase method, IGenericParameterProvider context); + } + +#endif + struct ImportGenericContext { Collection stack; @@ -48,6 +51,9 @@ namespace Mono.Cecil { public ImportGenericContext (IGenericParameterProvider provider) { + if (provider == null) + throw new ArgumentNullException ("provider"); + stack = null; Push (provider); @@ -73,7 +79,7 @@ namespace Mono.Cecil { if (candidate == null) continue; - if (method != candidate.Name) + if (method != NormalizeMethodName (candidate)) continue; return candidate.GenericParameters [position]; @@ -82,6 +88,11 @@ namespace Mono.Cecil { throw new InvalidOperationException (); } + public string NormalizeMethodName (MethodReference method) + { + return method.DeclaringType.GetElementType ().FullName + "." + method.Name; + } + public TypeReference TypeParameter (string type, int position) { for (int i = stack.Count - 1; i >= 0; i--) { @@ -108,18 +119,31 @@ namespace Mono.Cecil { throw new InvalidOperationException (); } + + public static ImportGenericContext For (IGenericParameterProvider context) + { + return context != null ? new ImportGenericContext (context) : default (ImportGenericContext); + } } - class MetadataImporter { +#if !PCL && !NET_CORE + + public class ReflectionImporter : IReflectionImporter { readonly ModuleDefinition module; - public MetadataImporter (ModuleDefinition module) + public ReflectionImporter (ModuleDefinition module) { + Mixin.CheckModule (module); + this.module = module; } -#if !CF + enum ImportGenericKind { + Definition, + Open, + } + static readonly Dictionary type_etype_mapping = new Dictionary (18) { { typeof (void), ElementType.Void }, { typeof (bool), ElementType.Boolean }, @@ -141,12 +165,12 @@ namespace Mono.Cecil { { typeof (object), ElementType.Object }, }; - public TypeReference ImportType (Type type, ImportGenericContext context) + TypeReference ImportType (Type type, ImportGenericContext context) { return ImportType (type, context, ImportGenericKind.Open); } - public TypeReference ImportType (Type type, ImportGenericContext context, ImportGenericKind import_kind) + TypeReference ImportType (Type type, ImportGenericContext context, ImportGenericKind import_kind) { if (IsTypeSpecification (type) || ImportOpenGenericType (type, import_kind)) return ImportTypeSpecification (type, context); @@ -183,11 +207,7 @@ namespace Mono.Cecil { static bool IsNestedType (Type type) { -#if !SILVERLIGHT return type.IsNested; -#else - return type.DeclaringType != null; -#endif } TypeReference ImportTypeSpecification (Type type, ImportGenericContext context) @@ -216,18 +236,23 @@ namespace Mono.Cecil { throw new InvalidOperationException (); if (type.DeclaringMethod != null) - return context.MethodParameter (type.DeclaringMethod.Name, type.GenericParameterPosition); + return context.MethodParameter (NormalizeMethodName (type.DeclaringMethod), type.GenericParameterPosition); if (type.DeclaringType != null) - return context.TypeParameter (NormalizedFullName (type.DeclaringType), type.GenericParameterPosition); + return context.TypeParameter (NormalizeTypeFullName (type.DeclaringType), type.GenericParameterPosition); throw new InvalidOperationException(); } - private static string NormalizedFullName (Type type) + static string NormalizeMethodName (SR.MethodBase method) + { + return NormalizeTypeFullName (method.DeclaringType) + "." + method.Name; + } + + static string NormalizeTypeFullName (Type type) { if (IsNestedType (type)) - return NormalizedFullName (type.DeclaringType) + "/" + type.Name; + return NormalizeTypeFullName (type.DeclaringType) + "/" + type.Name; return type.FullName; } @@ -274,7 +299,7 @@ namespace Mono.Cecil { AssemblyNameReference ImportScope (SR.Assembly assembly) { AssemblyNameReference scope; -#if !SILVERLIGHT + var name = assembly.GetName (); if (TryGetAssemblyNameReference (name, out scope)) @@ -289,19 +314,8 @@ namespace Mono.Cecil { module.AssemblyReferences.Add (scope); return scope; -#else - var name = AssemblyNameReference.Parse (assembly.FullName); - - if (TryGetAssemblyNameReference (name, out scope)) - return scope; - - module.AssemblyReferences.Add (name); - - return name; -#endif } -#if !SILVERLIGHT bool TryGetAssemblyNameReference (SR.AssemblyName name, out AssemblyNameReference assembly_reference) { var references = module.AssemblyReferences; @@ -318,9 +332,8 @@ namespace Mono.Cecil { assembly_reference = null; return false; } -#endif - public FieldReference ImportField (SR.FieldInfo field, ImportGenericContext context) + FieldReference ImportField (SR.FieldInfo field, ImportGenericContext context) { var declaring_type = ImportType (field.DeclaringType, context); @@ -341,17 +354,10 @@ namespace Mono.Cecil { static SR.FieldInfo ResolveFieldDefinition (SR.FieldInfo field) { -#if !SILVERLIGHT return field.Module.ResolveField (field.MetadataToken); -#else - return field.DeclaringType.GetGenericTypeDefinition ().GetField (field.Name, - SR.BindingFlags.Public - | SR.BindingFlags.NonPublic - | (field.IsStatic ? SR.BindingFlags.Static : SR.BindingFlags.Instance)); -#endif } - public MethodReference ImportMethod (SR.MethodBase method, ImportGenericContext context, ImportGenericKind import_kind) + MethodReference ImportMethod (SR.MethodBase method, ImportGenericContext context, ImportGenericKind import_kind) { if (IsMethodSpecification (method) || ImportOpenGenericMethod (method, import_kind)) return ImportMethodSpecification (method, context); @@ -435,9 +441,45 @@ namespace Mono.Cecil { { return (method.CallingConvention & conventions) != 0; } + + public virtual TypeReference ImportReference (Type type, IGenericParameterProvider context) + { + Mixin.CheckType (type); + return ImportType ( + type, + ImportGenericContext.For (context), + context != null ? ImportGenericKind.Open : ImportGenericKind.Definition); + } + + public virtual FieldReference ImportReference (SR.FieldInfo field, IGenericParameterProvider context) + { + Mixin.CheckField (field); + return ImportField (field, ImportGenericContext.For (context)); + } + + public virtual MethodReference ImportReference (SR.MethodBase method, IGenericParameterProvider context) + { + Mixin.CheckMethod (method); + return ImportMethod (method, + ImportGenericContext.For (context), + context != null ? ImportGenericKind.Open : ImportGenericKind.Definition); + } + } + #endif - public virtual TypeReference ImportType (TypeReference type, ImportGenericContext context) + public class MetadataImporter : IMetadataImporter { + + readonly ModuleDefinition module; + + public MetadataImporter (ModuleDefinition module) + { + Mixin.CheckModule (module); + + this.module = module; + } + + internal virtual TypeReference ImportType (TypeReference type, ImportGenericContext context) { if (type.IsTypeSpecification ()) return ImportTypeSpecification (type, context); @@ -475,15 +517,17 @@ namespace Mono.Cecil { throw new NotSupportedException (); } - protected virtual AssemblyNameReference ImportAssemblyName (AssemblyNameReference name) + internal virtual AssemblyNameReference ImportAssemblyName (AssemblyNameReference name) { AssemblyNameReference reference; - if (TryGetAssemblyNameReference (name, out reference)) + if (module.TryGetAssemblyNameReference (name, out reference)) return reference; reference = new AssemblyNameReference (name.Name, name.Version) { Culture = name.Culture, HashAlgorithm = name.HashAlgorithm, + IsRetargetable = name.IsRetargetable, + IsWindowsRuntime = name.IsWindowsRuntime, }; var pk_token = !name.PublicKeyToken.IsNullOrEmpty () @@ -500,23 +544,6 @@ namespace Mono.Cecil { return reference; } - bool TryGetAssemblyNameReference (AssemblyNameReference name_reference, out AssemblyNameReference assembly_reference) - { - var references = module.AssemblyReferences; - - for (int i = 0; i < references.Count; i++) { - var reference = references [i]; - if (name_reference.FullName != reference.FullName) // TODO compare field by field - continue; - - assembly_reference = reference; - return true; - } - - assembly_reference = null; - return false; - } - static void ImportGenericParameters (IGenericParameterProvider imported, IGenericParameterProvider original) { var parameters = original.GenericParameters; @@ -544,6 +571,23 @@ namespace Mono.Cecil { case ElementType.Sentinel: var sentinel = (SentinelType) type; return new SentinelType (ImportType (sentinel.ElementType, context)); + case ElementType.FnPtr: + var fnptr = (FunctionPointerType) type; + var imported_fnptr = new FunctionPointerType () { + HasThis = fnptr.HasThis, + ExplicitThis = fnptr.ExplicitThis, + CallingConvention = fnptr.CallingConvention, + ReturnType = ImportType (fnptr.ReturnType, context), + }; + + if (!fnptr.HasParameters) + return imported_fnptr; + + for (int i = 0; i < fnptr.Parameters.Count; i++) + imported_fnptr.Parameters.Add (new ParameterDefinition ( + ImportType (fnptr.Parameters [i].ParameterType, context))); + + return imported_fnptr; case ElementType.CModOpt: var modopt = (OptionalModifierType) type; return new OptionalModifierType ( @@ -586,16 +630,20 @@ namespace Mono.Cecil { return imported_instance; case ElementType.Var: var var_parameter = (GenericParameter) type; - return context.TypeParameter (type.DeclaringType.FullName, var_parameter.Position); + if (var_parameter.DeclaringType == null) + throw new InvalidOperationException (); + return context.TypeParameter (var_parameter.DeclaringType.FullName, var_parameter.Position); case ElementType.MVar: var mvar_parameter = (GenericParameter) type; - return context.MethodParameter (mvar_parameter.DeclaringMethod.Name, mvar_parameter.Position); + if (mvar_parameter.DeclaringMethod == null) + throw new InvalidOperationException (); + return context.MethodParameter (context.NormalizeMethodName (mvar_parameter.DeclaringMethod), mvar_parameter.Position); } throw new NotSupportedException (type.etype.ToString ()); } - public FieldReference ImportField (FieldReference field, ImportGenericContext context) + FieldReference ImportField (FieldReference field, ImportGenericContext context) { var declaring_type = ImportType (field.DeclaringType, context); @@ -611,7 +659,7 @@ namespace Mono.Cecil { } } - public MethodReference ImportMethod (MethodReference method, ImportGenericContext context) + MethodReference ImportMethod (MethodReference method, ImportGenericContext context) { if (method.IsGenericInstance) return ImportMethodSpecification (method, context); @@ -636,9 +684,8 @@ namespace Mono.Cecil { if (!method.HasParameters) return reference; - var reference_parameters = reference.Parameters; - var parameters = method.Parameters; + var reference_parameters = reference.parameters = new ParameterDefinitionCollection (reference, parameters.Count); for (int i = 0; i < parameters.Count; i++) reference_parameters.Add ( new ParameterDefinition (ImportType (parameters [i].ParameterType, context))); @@ -666,5 +713,89 @@ namespace Mono.Cecil { return imported_instance; } + + public virtual TypeReference ImportReference (TypeReference type, IGenericParameterProvider context) + { + Mixin.CheckType (type); + return ImportType (type, ImportGenericContext.For (context)); + } + + public virtual FieldReference ImportReference (FieldReference field, IGenericParameterProvider context) + { + Mixin.CheckField (field); + return ImportField (field, ImportGenericContext.For (context)); + } + + public virtual MethodReference ImportReference (MethodReference method, IGenericParameterProvider context) + { + Mixin.CheckMethod (method); + return ImportMethod (method, ImportGenericContext.For (context)); + } + } + +#endif + + static partial class Mixin { + + public static void CheckModule (ModuleDefinition module) + { + if (module == null) + throw new ArgumentNullException ("module"); + } + + public static bool TryGetAssemblyNameReference (this ModuleDefinition module, AssemblyNameReference name_reference, out AssemblyNameReference assembly_reference) + { + var references = module.AssemblyReferences; + + for (int i = 0; i < references.Count; i++) { + var reference = references [i]; + if (!Equals (name_reference, reference)) + continue; + + assembly_reference = reference; + return true; + } + + assembly_reference = null; + return false; + } + + static bool Equals (byte [] a, byte [] b) + { + if (ReferenceEquals (a, b)) + return true; + if (a == null) + return false; + if (a.Length != b.Length) + return false; + for (int i = 0; i < a.Length; i++) + if (a [i] != b [i]) + return false; + return true; + } + + static bool Equals (T a, T b) where T : class, IEquatable + { + if (ReferenceEquals (a, b)) + return true; + if (a == null) + return false; + return a.Equals (b); + } + + static bool Equals (AssemblyNameReference a, AssemblyNameReference b) + { + if (ReferenceEquals (a, b)) + return true; + if (a.Name != b.Name) + return false; + if (!Equals (a.Version, b.Version)) + return false; + if (a.Culture != b.Culture) + return false; + if (!Equals (a.PublicKeyToken, b.PublicKeyToken)) + return false; + return true; + } } } diff --git a/external/cecil/Mono.Cecil/LinkedResource.cs b/external/cecil/Mono.Cecil/LinkedResource.cs index 16c1d59b5a..e53430eca4 100644 --- a/external/cecil/Mono.Cecil/LinkedResource.cs +++ b/external/cecil/Mono.Cecil/LinkedResource.cs @@ -1,29 +1,11 @@ // -// LinkedResource.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // namespace Mono.Cecil { diff --git a/external/cecil/Mono.Cecil/ManifestResourceAttributes.cs b/external/cecil/Mono.Cecil/ManifestResourceAttributes.cs index 7d6bb190f4..03ccb6b4c9 100644 --- a/external/cecil/Mono.Cecil/ManifestResourceAttributes.cs +++ b/external/cecil/Mono.Cecil/ManifestResourceAttributes.cs @@ -1,29 +1,11 @@ // -// ManifestResourceAttributes.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; diff --git a/external/cecil/Mono.Cecil/MarshalInfo.cs b/external/cecil/Mono.Cecil/MarshalInfo.cs index 9d58738923..47d935e2cc 100644 --- a/external/cecil/Mono.Cecil/MarshalInfo.cs +++ b/external/cecil/Mono.Cecil/MarshalInfo.cs @@ -1,29 +1,11 @@ // -// MarshalInfo.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; diff --git a/external/cecil/Mono.Cecil/MemberDefinitionCollection.cs b/external/cecil/Mono.Cecil/MemberDefinitionCollection.cs index 707f36fb97..3872b2a974 100644 --- a/external/cecil/Mono.Cecil/MemberDefinitionCollection.cs +++ b/external/cecil/Mono.Cecil/MemberDefinitionCollection.cs @@ -1,29 +1,11 @@ // -// MemberDefinitionCollection.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; @@ -32,7 +14,7 @@ using Mono.Collections.Generic; namespace Mono.Cecil { - class MemberDefinitionCollection : Collection where T : IMemberDefinition { + sealed class MemberDefinitionCollection : Collection where T : IMemberDefinition { TypeDefinition container; diff --git a/external/cecil/Mono.Cecil/MemberReference.cs b/external/cecil/Mono.Cecil/MemberReference.cs index b658c513de..84fd38c546 100644 --- a/external/cecil/Mono.Cecil/MemberReference.cs +++ b/external/cecil/Mono.Cecil/MemberReference.cs @@ -1,31 +1,15 @@ // -// MemberReference.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // +using System; + namespace Mono.Cecil { public abstract class MemberReference : IMetadataTokenProvider { @@ -34,10 +18,16 @@ namespace Mono.Cecil { TypeReference declaring_type; internal MetadataToken token; + internal object projection; public virtual string Name { get { return name; } - set { name = value; } + set { + if (IsWindowsRuntimeProjection && value != name) + throw new InvalidOperationException (); + + name = value; + } } public abstract string FullName { @@ -54,6 +44,15 @@ namespace Mono.Cecil { set { token = value; } } + public bool IsWindowsRuntimeProjection { + get { return projection != null; } + } + + internal MemberReferenceProjection WindowsRuntimeProjection { + get { return (MemberReferenceProjection) projection; } + set { projection = value; } + } + internal bool HasImage { get { var module = Module; @@ -72,7 +71,7 @@ namespace Mono.Cecil { get { return false; } } - internal virtual bool ContainsGenericParameter { + public virtual bool ContainsGenericParameter { get { return declaring_type != null && declaring_type.ContainsGenericParameter; } } @@ -93,6 +92,13 @@ namespace Mono.Cecil { return declaring_type.FullName + "::" + name; } + public IMemberDefinition Resolve () + { + return ResolveDefinition (); + } + + protected abstract IMemberDefinition ResolveDefinition (); + public override string ToString () { return FullName; diff --git a/external/cecil/Mono.Cecil/MetadataResolver.cs b/external/cecil/Mono.Cecil/MetadataResolver.cs index 55433770f2..826756d1ab 100644 --- a/external/cecil/Mono.Cecil/MetadataResolver.cs +++ b/external/cecil/Mono.Cecil/MetadataResolver.cs @@ -1,29 +1,11 @@ // -// MetadataResolver.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; @@ -32,7 +14,7 @@ using Mono.Collections.Generic; namespace Mono.Cecil { - public interface IAssemblyResolver { + public interface IAssemblyResolver : IDisposable { AssemblyDefinition Resolve (AssemblyNameReference name); AssemblyDefinition Resolve (AssemblyNameReference name, ReaderParameters parameters); @@ -46,10 +28,10 @@ namespace Mono.Cecil { MethodDefinition Resolve (MethodReference method); } -#if !SILVERLIGHT && !CF +#if !PCL && !NET_CORE [Serializable] #endif - public class ResolutionException : Exception { + public sealed class ResolutionException : Exception { readonly MemberReference member; @@ -80,8 +62,8 @@ namespace Mono.Cecil { this.member = member; } -#if !SILVERLIGHT && !CF - protected ResolutionException ( +#if !PCL && !NET_CORE + ResolutionException ( System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base (info, context) @@ -114,6 +96,10 @@ namespace Mono.Cecil { type = type.GetElementType (); var scope = type.Scope; + + if (scope == null) + return null; + switch (scope.MetadataScopeType) { case MetadataScopeType.AssemblyNameReference: var assembly = assembly_resolver.Resolve ((AssemblyNameReference) scope); @@ -171,7 +157,7 @@ namespace Mono.Cecil { if (declaring_type == null) return null; - return declaring_type.GetNestedType (type.Name); + return declaring_type.GetNestedType (type.TypeFullName ()); } public virtual FieldDefinition Resolve (FieldReference field) @@ -272,6 +258,12 @@ namespace Mono.Cecil { if (!AreSame (method.ReturnType, reference.ReturnType)) continue; + if (method.IsVarArg () != reference.IsVarArg ()) + continue; + + if (method.IsVarArg () && IsVarArgCallTo (method, reference)) + return method; + if (method.HasParameters != reference.HasParameters) continue; @@ -304,6 +296,21 @@ namespace Mono.Cecil { return true; } + static bool IsVarArgCallTo (MethodDefinition method, MethodReference reference) + { + if (method.Parameters.Count >= reference.Parameters.Count) + return false; + + if (reference.GetSentinelPosition () != method.Parameters.Count) + return false; + + for (int i = 0; i < method.Parameters.Count; i++) + if (!AreSame (method.Parameters [i].ParameterType, reference.Parameters [i].ParameterType)) + return false; + + return true; + } + static bool AreSame (TypeSpecification a, TypeSpecification b) { if (!AreSame (a.ElementType, b.ElementType)) diff --git a/external/cecil/Mono.Cecil/MetadataSystem.cs b/external/cecil/Mono.Cecil/MetadataSystem.cs index 3ae2015bb5..3332ba3f57 100644 --- a/external/cecil/Mono.Cecil/MetadataSystem.cs +++ b/external/cecil/Mono.Cecil/MetadataSystem.cs @@ -1,34 +1,17 @@ // -// MetadataSystem.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; using System.Collections.Generic; +using Mono.Cecil.Cil; using Mono.Cecil.Metadata; namespace Mono.Cecil { @@ -58,7 +41,7 @@ namespace Mono.Cecil { internal Dictionary NestedTypes; internal Dictionary ReverseNestedTypes; - internal Dictionary Interfaces; + internal Dictionary []> Interfaces; internal Dictionary> ClassLayouts; internal Dictionary FieldLayouts; internal Dictionary FieldRVAs; @@ -74,6 +57,12 @@ namespace Mono.Cecil { internal Dictionary GenericParameters; internal Dictionary GenericConstraints; + internal Document [] Documents; + internal Dictionary []> LocalScopes; + internal ImportDebugInformation [] ImportScopes; + internal Dictionary StateMachineMethods; + internal Dictionary []> CustomDebugInformations; + static Dictionary> primitive_value_types; static void InitializePrimitives () @@ -143,23 +132,36 @@ namespace Mono.Cecil { public void Clear () { - if (NestedTypes != null) NestedTypes.Clear (); - if (ReverseNestedTypes != null) ReverseNestedTypes.Clear (); - if (Interfaces != null) Interfaces.Clear (); - if (ClassLayouts != null) ClassLayouts.Clear (); - if (FieldLayouts != null) FieldLayouts.Clear (); - if (FieldRVAs != null) FieldRVAs.Clear (); - if (FieldMarshals != null) FieldMarshals.Clear (); - if (Constants != null) Constants.Clear (); - if (Overrides != null) Overrides.Clear (); - if (CustomAttributes != null) CustomAttributes.Clear (); - if (SecurityDeclarations != null) SecurityDeclarations.Clear (); - if (Events != null) Events.Clear (); - if (Properties != null) Properties.Clear (); - if (Semantics != null) Semantics.Clear (); - if (PInvokes != null) PInvokes.Clear (); - if (GenericParameters != null) GenericParameters.Clear (); - if (GenericConstraints != null) GenericConstraints.Clear (); + if (NestedTypes != null) NestedTypes = new Dictionary (capacity: 0); + if (ReverseNestedTypes != null) ReverseNestedTypes = new Dictionary (capacity: 0); + if (Interfaces != null) Interfaces = new Dictionary []> (capacity: 0); + if (ClassLayouts != null) ClassLayouts = new Dictionary> (capacity: 0); + if (FieldLayouts != null) FieldLayouts = new Dictionary (capacity: 0); + if (FieldRVAs != null) FieldRVAs = new Dictionary (capacity: 0); + if (FieldMarshals != null) FieldMarshals = new Dictionary (capacity: 0); + if (Constants != null) Constants = new Dictionary> (capacity: 0); + if (Overrides != null) Overrides = new Dictionary (capacity: 0); + if (CustomAttributes != null) CustomAttributes = new Dictionary (capacity: 0); + if (SecurityDeclarations != null) SecurityDeclarations = new Dictionary (capacity: 0); + if (Events != null) Events = new Dictionary (capacity: 0); + if (Properties != null) Properties = new Dictionary (capacity: 0); + if (Semantics != null) Semantics = new Dictionary> (capacity: 0); + if (PInvokes != null) PInvokes = new Dictionary> (capacity: 0); + if (GenericParameters != null) GenericParameters = new Dictionary (capacity: 0); + if (GenericConstraints != null) GenericConstraints = new Dictionary (capacity: 0); + + Documents = Empty.Array; + ImportScopes = Empty.Array; + if (LocalScopes != null) LocalScopes = new Dictionary []> (capacity: 0); + if (StateMachineMethods != null) StateMachineMethods = new Dictionary (capacity: 0); + } + + public AssemblyNameReference GetAssemblyNameReference (uint rid) + { + if (rid < 1 || rid > AssemblyReferences.Length) + return null; + + return AssemblyReferences [rid - 1]; } public TypeDefinition GetTypeDefinition (uint rid) @@ -249,7 +251,7 @@ namespace Mono.Cecil { public void SetReverseNestedTypeMapping (uint nested, uint declaring) { - ReverseNestedTypes.Add (nested, declaring); + ReverseNestedTypes [nested] = declaring; } public void RemoveReverseNestedTypeMapping (TypeDefinition type) @@ -257,12 +259,12 @@ namespace Mono.Cecil { ReverseNestedTypes.Remove (type.token.RID); } - public bool TryGetInterfaceMapping (TypeDefinition type, out MetadataToken [] mapping) + public bool TryGetInterfaceMapping (TypeDefinition type, out Row [] mapping) { return Interfaces.TryGetValue (type.token.RID, out mapping); } - public void SetInterfaceMapping (uint type_rid, MetadataToken [] mapping) + public void SetInterfaceMapping (uint type_rid, Row [] mapping) { Interfaces [type_rid] = mapping; } @@ -362,6 +364,37 @@ namespace Mono.Cecil { Overrides.Remove (method.token.RID); } + public Document GetDocument (uint rid) + { + if (rid < 1 || rid > Documents.Length) + return null; + + return Documents [rid - 1]; + } + + public bool TryGetLocalScopes (MethodDefinition method, out Row [] scopes) + { + return LocalScopes.TryGetValue (method.MetadataToken.RID, out scopes); + } + + public void SetLocalScopes (uint method_rid, Row [] records) + { + LocalScopes [method_rid] = records; + } + + public ImportDebugInformation GetImportScope (uint rid) + { + if (rid < 1 || rid > ImportScopes.Length) + return null; + + return ImportScopes [rid - 1]; + } + + public bool TryGetStateMachineKickOffMethod (MethodDefinition method, out uint rid) + { + return StateMachineMethods.TryGetValue (method.MetadataToken.RID, out rid); + } + public TypeDefinition GetFieldDeclaringType (uint field_rid) { return BinaryRangeSearch (Types, field_rid, true); diff --git a/external/cecil/Mono.Cecil/MethodAttributes.cs b/external/cecil/Mono.Cecil/MethodAttributes.cs index 626a97b3ea..1bd7d1288d 100644 --- a/external/cecil/Mono.Cecil/MethodAttributes.cs +++ b/external/cecil/Mono.Cecil/MethodAttributes.cs @@ -1,29 +1,11 @@ // -// MethodAttributes.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; diff --git a/external/cecil/Mono.Cecil/MethodCallingConvention.cs b/external/cecil/Mono.Cecil/MethodCallingConvention.cs index bd7188dbec..f9c0e0c951 100644 --- a/external/cecil/Mono.Cecil/MethodCallingConvention.cs +++ b/external/cecil/Mono.Cecil/MethodCallingConvention.cs @@ -1,29 +1,11 @@ // -// MethodCallingConvention.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // namespace Mono.Cecil { diff --git a/external/cecil/Mono.Cecil/MethodDefinition.cs b/external/cecil/Mono.Cecil/MethodDefinition.cs index cbda745b7e..1ee631b7b1 100644 --- a/external/cecil/Mono.Cecil/MethodDefinition.cs +++ b/external/cecil/Mono.Cecil/MethodDefinition.cs @@ -1,31 +1,14 @@ // -// MethodDefinition.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // +using System; using Mono.Cecil.Cil; using Mono.Collections.Generic; @@ -33,11 +16,12 @@ using RVA = System.UInt32; namespace Mono.Cecil { - public sealed class MethodDefinition : MethodReference, IMemberDefinition, ISecurityDeclarationProvider { + public sealed class MethodDefinition : MethodReference, IMemberDefinition, ISecurityDeclarationProvider, ICustomDebugInformationProvider { ushort attributes; ushort impl_attributes; - internal MethodSemanticsAttributes? sem_attrs; + internal volatile bool sem_attrs_ready; + internal MethodSemanticsAttributes sem_attrs; Collection custom_attributes; Collection security_declarations; @@ -46,36 +30,64 @@ namespace Mono.Cecil { Collection overrides; internal MethodBody body; + internal MethodDebugInformation debug_info; + internal Collection custom_infos; + + public override string Name { + get { return base.Name; } + set { + if (IsWindowsRuntimeProjection && value != base.Name) + throw new InvalidOperationException (); + + base.Name = value; + } + } public MethodAttributes Attributes { get { return (MethodAttributes) attributes; } - set { attributes = (ushort) value; } + set { + if (IsWindowsRuntimeProjection && (ushort) value != attributes) + throw new InvalidOperationException (); + + attributes = (ushort) value; + } } public MethodImplAttributes ImplAttributes { get { return (MethodImplAttributes) impl_attributes; } - set { impl_attributes = (ushort) value; } + set { + if (IsWindowsRuntimeProjection && (ushort) value != impl_attributes) + throw new InvalidOperationException (); + + impl_attributes = (ushort) value; + } } public MethodSemanticsAttributes SemanticsAttributes { get { - if (sem_attrs.HasValue) - return sem_attrs.Value; + if (sem_attrs_ready) + return sem_attrs; if (HasImage) { ReadSemantics (); - return sem_attrs.Value; + return sem_attrs; } sem_attrs = MethodSemanticsAttributes.None; - return sem_attrs.Value; + sem_attrs_ready = true; + return sem_attrs; } set { sem_attrs = value; } } + internal new MethodDefinitionProjection WindowsRuntimeProjection { + get { return (MethodDefinitionProjection) projection; } + set { projection = value; } + } + internal void ReadSemantics () { - if (sem_attrs.HasValue) + if (sem_attrs_ready) return; var module = this.Module; @@ -98,7 +110,7 @@ namespace Mono.Cecil { } public Collection SecurityDeclarations { - get { return security_declarations ?? (security_declarations = this.GetSecurityDeclarations (Module)); } + get { return security_declarations ?? (this.GetSecurityDeclarations (ref security_declarations, Module)); } } public bool HasCustomAttributes { @@ -111,7 +123,7 @@ namespace Mono.Cecil { } public Collection CustomAttributes { - get { return custom_attributes ?? (custom_attributes = this.GetCustomAttributes (Module)); } + get { return custom_attributes ?? (this.GetCustomAttributes (ref custom_attributes, Module)); } } public int RVA { @@ -131,18 +143,41 @@ namespace Mono.Cecil { public MethodBody Body { get { - if (body != null) - return body; + MethodBody localBody = this.body; + if (localBody != null) + return localBody; if (!HasBody) return null; if (HasImage && rva != 0) - return body = Module.Read (this, (method, reader) => reader.ReadMethodBody (method)); + return Module.Read (ref body, this, (method, reader) => reader.ReadMethodBody (method)); return body = new MethodBody (this); } - set { body = value; } + set { + var module = this.Module; + if (module == null) { + body = value; + return; + } + + // we reset Body to null in ILSpy to save memory; so we need that operation to be thread-safe + lock (module.SyncRoot) { + body = value; + } + } + } + + public MethodDebugInformation DebugInformation { + get { + if (debug_info != null) + return debug_info; + + Mixin.Read (Body); + + return debug_info ?? (debug_info = new MethodDebugInformation (this)); + } } public bool HasPInvokeInfo { @@ -160,7 +195,7 @@ namespace Mono.Cecil { return pinvoke; if (HasImage && IsPInvokeImpl) - return pinvoke = Module.Read (this, (method, reader) => reader.ReadPInvokeInfo (method)); + return Module.Read (ref pinvoke, this, (method, reader) => reader.ReadPInvokeInfo (method)); return null; } @@ -175,10 +210,7 @@ namespace Mono.Cecil { if (overrides != null) return overrides.Count > 0; - if (HasImage) - return Module.Read (this, (method, reader) => reader.HasOverrides (method)); - - return false; + return HasImage && Module.Read (this, (method, reader) => reader.HasOverrides (method)); } } @@ -188,7 +220,7 @@ namespace Mono.Cecil { return overrides; if (HasImage) - return overrides = Module.Read (this, (method, reader) => reader.ReadOverrides (method)); + return Module.Read (ref overrides, this, (method, reader) => reader.ReadOverrides (method)); return overrides = new Collection (); } @@ -204,7 +236,23 @@ namespace Mono.Cecil { } public override Collection GenericParameters { - get { return generic_parameters ?? (generic_parameters = this.GetGenericParameters (Module)); } + get { return generic_parameters ?? (this.GetGenericParameters (ref generic_parameters, Module)); } + } + + public bool HasCustomDebugInformations { + get { + Mixin.Read (Body); + + return !custom_infos.IsNullOrEmpty (); + } + } + + public Collection CustomDebugInformations { + get { + Mixin.Read (Body); + + return custom_infos ?? (custom_infos = new Collection ()); + } } #region MethodAttributes diff --git a/external/cecil/Mono.Cecil/MethodImplAttributes.cs b/external/cecil/Mono.Cecil/MethodImplAttributes.cs index b24fcf7047..7d48b33556 100644 --- a/external/cecil/Mono.Cecil/MethodImplAttributes.cs +++ b/external/cecil/Mono.Cecil/MethodImplAttributes.cs @@ -1,29 +1,11 @@ // -// MethodImplAttributes.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; diff --git a/external/cecil/Mono.Cecil/MethodReference.cs b/external/cecil/Mono.Cecil/MethodReference.cs index 0adab452ef..f8c7bb613a 100644 --- a/external/cecil/Mono.Cecil/MethodReference.cs +++ b/external/cecil/Mono.Cecil/MethodReference.cs @@ -1,29 +1,11 @@ // -// MethodReference.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; @@ -135,7 +117,7 @@ namespace Mono.Cecil { get { return false; } } - internal override bool ContainsGenericParameter { + public override bool ContainsGenericParameter { get { if (this.ReturnType.ContainsGenericParameter || base.ContainsGenericParameter) return true; @@ -181,7 +163,12 @@ namespace Mono.Cecil { return this; } - public virtual MethodDefinition Resolve () + protected override IMemberDefinition ResolveDefinition () + { + return this.Resolve (); + } + + public new virtual MethodDefinition Resolve () { var module = this.Module; if (module == null) diff --git a/external/cecil/Mono.Cecil/MethodReturnType.cs b/external/cecil/Mono.Cecil/MethodReturnType.cs index b5b3ee84fa..a6c9ae4627 100644 --- a/external/cecil/Mono.Cecil/MethodReturnType.cs +++ b/external/cecil/Mono.Cecil/MethodReturnType.cs @@ -1,31 +1,15 @@ // -// MethodReturnType.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // +using System.Threading; + using Mono.Collections.Generic; namespace Mono.Cecil { @@ -46,7 +30,12 @@ namespace Mono.Cecil { } internal ParameterDefinition Parameter { - get { return parameter ?? (parameter = new ParameterDefinition (return_type, method)); } + get { + if (parameter == null) + Interlocked.CompareExchange (ref parameter, new ParameterDefinition (return_type, method), null); + + return parameter; + } } public MetadataToken MetadataToken { diff --git a/external/cecil/Mono.Cecil/MethodSemanticsAttributes.cs b/external/cecil/Mono.Cecil/MethodSemanticsAttributes.cs index dd0f4742c0..274dfd0449 100644 --- a/external/cecil/Mono.Cecil/MethodSemanticsAttributes.cs +++ b/external/cecil/Mono.Cecil/MethodSemanticsAttributes.cs @@ -1,29 +1,11 @@ // -// MethodSemanticsattributes.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; diff --git a/external/cecil/Mono.Cecil/MethodSpecification.cs b/external/cecil/Mono.Cecil/MethodSpecification.cs index 73b5c14ad6..c0f3a862c3 100644 --- a/external/cecil/Mono.Cecil/MethodSpecification.cs +++ b/external/cecil/Mono.Cecil/MethodSpecification.cs @@ -1,29 +1,11 @@ // -// MethodSpecification.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; @@ -82,7 +64,7 @@ namespace Mono.Cecil { get { return method.Parameters; } } - internal override bool ContainsGenericParameter { + public override bool ContainsGenericParameter { get { return method.ContainsGenericParameter; } } diff --git a/external/cecil/Mono.Cecil/Modifiers.cs b/external/cecil/Mono.Cecil/Modifiers.cs index ad31bc04f1..7575ec1024 100644 --- a/external/cecil/Mono.Cecil/Modifiers.cs +++ b/external/cecil/Mono.Cecil/Modifiers.cs @@ -1,29 +1,11 @@ // -// Modifiers.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; @@ -67,7 +49,7 @@ namespace Mono.Cecil { get { return true; } } - internal override bool ContainsGenericParameter { + public override bool ContainsGenericParameter { get { return modifier_type.ContainsGenericParameter || base.ContainsGenericParameter; } } @@ -110,7 +92,7 @@ namespace Mono.Cecil { get { return true; } } - internal override bool ContainsGenericParameter { + public override bool ContainsGenericParameter { get { return modifier_type.ContainsGenericParameter || base.ContainsGenericParameter; } } diff --git a/external/cecil/Mono.Cecil/ModuleDefinition.cs b/external/cecil/Mono.Cecil/ModuleDefinition.cs index 61870cdbb5..c7afdc197c 100644 --- a/external/cecil/Mono.Cecil/ModuleDefinition.cs +++ b/external/cecil/Mono.Cecil/ModuleDefinition.cs @@ -1,34 +1,17 @@ // -// ModuleDefinition.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; using System.Collections.Generic; using System.IO; +using System.Threading; using SR = System.Reflection; using Mono.Cecil.Cil; @@ -46,17 +29,31 @@ namespace Mono.Cecil { public sealed class ReaderParameters { ReadingMode reading_mode; - IAssemblyResolver assembly_resolver; - IMetadataResolver metadata_resolver; + internal IAssemblyResolver assembly_resolver; + internal IMetadataResolver metadata_resolver; +#if !READ_ONLY + internal IMetadataImporterProvider metadata_importer_provider; +#if !PCL && !NET_CORE + internal IReflectionImporterProvider reflection_importer_provider; +#endif +#endif Stream symbol_stream; ISymbolReaderProvider symbol_reader_provider; bool read_symbols; + bool projections; + bool in_memory; + bool read_write; public ReadingMode ReadingMode { get { return reading_mode; } set { reading_mode = value; } } + public bool InMemory { + get { return in_memory; } + set { in_memory = value; } + } + public IAssemblyResolver AssemblyResolver { get { return assembly_resolver; } set { assembly_resolver = value; } @@ -67,6 +64,20 @@ namespace Mono.Cecil { set { metadata_resolver = value; } } +#if !READ_ONLY + public IMetadataImporterProvider MetadataImporterProvider { + get { return metadata_importer_provider; } + set { metadata_importer_provider = value; } + } + +#if !PCL && !NET_CORE + public IReflectionImporterProvider ReflectionImporterProvider { + get { return reflection_importer_provider; } + set { reflection_importer_provider = value; } + } +#endif +#endif + public Stream SymbolStream { get { return symbol_stream; } set { symbol_stream = value; } @@ -82,6 +93,16 @@ namespace Mono.Cecil { set { read_symbols = value; } } + public bool ReadWrite { + get { return read_write; } + set { read_write = value; } + } + + public bool ApplyWindowsRuntimeProjections { + get { return projections; } + set { projections = value; } + } + public ReaderParameters () : this (ReadingMode.Deferred) { @@ -102,6 +123,12 @@ namespace Mono.Cecil { TargetArchitecture architecture; IAssemblyResolver assembly_resolver; IMetadataResolver metadata_resolver; +#if !READ_ONLY + IMetadataImporterProvider metadata_importer_provider; +#if !PCL && !NET_CORE + IReflectionImporterProvider reflection_importer_provider; +#endif +#endif public ModuleKind Kind { get { return kind; } @@ -128,19 +155,35 @@ namespace Mono.Cecil { set { metadata_resolver = value; } } +#if !READ_ONLY + public IMetadataImporterProvider MetadataImporterProvider { + get { return metadata_importer_provider; } + set { metadata_importer_provider = value; } + } + +#if !PCL && !NET_CORE + public IReflectionImporterProvider ReflectionImporterProvider { + get { return reflection_importer_provider; } + set { reflection_importer_provider = value; } + } +#endif +#endif + public ModuleParameters () { this.kind = ModuleKind.Dll; - this.runtime = GetCurrentRuntime (); + this.Runtime = GetCurrentRuntime (); this.architecture = TargetArchitecture.I386; } static TargetRuntime GetCurrentRuntime () { -#if !CF +#if !PCL && !NET_CORE return typeof (object).Assembly.ImageRuntimeVersion.ParseRuntime (); #else - var corlib_version = typeof (object).Assembly.GetName ().Version; + var corlib_name = AssemblyNameReference.Parse (typeof (object).GetAssembly ().FullName); + var corlib_version = corlib_name.Version; + switch (corlib_version.Major) { case 1: return corlib_version.Minor == 0 @@ -178,7 +221,7 @@ namespace Mono.Cecil { Stream symbol_stream; ISymbolWriterProvider symbol_writer_provider; bool write_symbols; -#if !SILVERLIGHT && !CF +#if !PCL && !NET_CORE SR.StrongNameKeyPair key_pair; #endif public Stream SymbolStream { @@ -195,7 +238,7 @@ namespace Mono.Cecil { get { return write_symbols; } set { write_symbols = value; } } -#if !SILVERLIGHT && !CF +#if !PCL && !NET_CORE public SR.StrongNameKeyPair StrongNameKeyPair { get { return key_pair; } set { key_pair = value; } @@ -205,7 +248,7 @@ namespace Mono.Cecil { #endif - public sealed class ModuleDefinition : ModuleReference, ICustomAttributeProvider { + public sealed class ModuleDefinition : ModuleReference, ICustomAttributeProvider, IDisposable { internal Image Image; internal MetadataSystem MetadataSystem; @@ -213,14 +256,16 @@ namespace Mono.Cecil { internal ISymbolReaderProvider SymbolReaderProvider; internal ISymbolReader symbol_reader; - internal IAssemblyResolver assembly_resolver; + internal Disposable assembly_resolver; internal IMetadataResolver metadata_resolver; internal TypeSystem type_system; + internal readonly MetadataReader reader; + readonly string file_name; - readonly MetadataReader reader; - readonly string fq_name; - + internal string runtime_version; internal ModuleKind kind; + WindowsRuntimeProjections projections; + MetadataKind metadata_kind; TargetRuntime runtime; TargetArchitecture architecture; ModuleAttributes attributes; @@ -231,7 +276,10 @@ namespace Mono.Cecil { MethodDefinition entry_point; #if !READ_ONLY - MetadataImporter importer; +#if !PCL && !NET_CORE + internal IReflectionImporter reflection_importer; +#endif + internal IMetadataImporter metadata_importer; ICustomMetadataWriter custom_writer; #endif Collection custom_attributes; @@ -250,9 +298,34 @@ namespace Mono.Cecil { set { kind = value; } } + public MetadataKind MetadataKind { + get { return metadata_kind; } + set { metadata_kind = value; } + } + + internal WindowsRuntimeProjections Projections { + get { + if (projections == null) + Interlocked.CompareExchange (ref projections, new WindowsRuntimeProjections (this), null); + + return projections; + } + } + public TargetRuntime Runtime { get { return runtime; } - set { runtime = value; } + set { + runtime = value; + runtime_version = runtime.RuntimeVersionString (); + } + } + + public string RuntimeVersion { + get { return runtime_version; } + set { + runtime_version = value; + runtime = runtime_version.ParseRuntime (); + } } public TargetArchitecture Architecture { @@ -270,8 +343,13 @@ namespace Mono.Cecil { set { characteristics = value; } } + [Obsolete("Use FileName")] public string FullyQualifiedName { - get { return fq_name; } + get { return file_name; } + } + + public string FileName { + get { return file_name; } } public Guid Mvid { @@ -300,15 +378,30 @@ namespace Mono.Cecil { } #if !READ_ONLY - internal MetadataImporter MetadataImporter { - get { return importer ?? (importer = new MetadataImporter (this)); } +#if !PCL && !NET_CORE + internal IReflectionImporter ReflectionImporter { + get { + if (reflection_importer == null) + Interlocked.CompareExchange (ref reflection_importer, new ReflectionImporter (this), null); + + return reflection_importer; + } + } +#endif + internal IMetadataImporter MetadataImporter { + get { + if (metadata_importer == null) + Interlocked.CompareExchange (ref metadata_importer, new MetadataImporter (this), null); + + return metadata_importer; + } } internal void SetMetadataImporter (MetadataImporter importer) { - if (this.importer != null) + if (this.metadata_importer != null) throw new InvalidOperationException (); - this.importer = importer; + this.metadata_importer = importer; } internal ICustomMetadataWriter CustomMetadataWriter { @@ -318,15 +411,35 @@ namespace Mono.Cecil { #endif public IAssemblyResolver AssemblyResolver { - get { return assembly_resolver ?? (assembly_resolver = new DefaultAssemblyResolver ()); } + get { +#if !PCL && !NET_CORE + if (assembly_resolver.value == null) { + lock (module_lock) { + assembly_resolver = Disposable.Owned (new DefaultAssemblyResolver () as IAssemblyResolver); + } + } +#endif + + return assembly_resolver.value; + } } public IMetadataResolver MetadataResolver { - get { return metadata_resolver ?? (metadata_resolver = new MetadataResolver (this.AssemblyResolver)); } + get { + if (metadata_resolver == null) + Interlocked.CompareExchange (ref metadata_resolver, new MetadataResolver (this.AssemblyResolver), null); + + return metadata_resolver; + } } public TypeSystem TypeSystem { - get { return type_system ?? (type_system = TypeSystem.CreateTypeSystem (this)); } + get { + if (type_system == null) + Interlocked.CompareExchange (ref type_system, TypeSystem.CreateTypeSystem (this), null); + + return type_system; + } } public bool HasAssemblyReferences { @@ -344,7 +457,7 @@ namespace Mono.Cecil { return references; if (HasImage) - return references = Read (this, (_, reader) => reader.ReadAssemblyReferences ()); + return Read (ref references, this, (_, reader) => reader.ReadAssemblyReferences ()); return references = new Collection (); } @@ -365,7 +478,7 @@ namespace Mono.Cecil { return modules; if (HasImage) - return modules = Read (this, (_, reader) => reader.ReadModuleReferences ()); + return Read (ref modules, this, (_, reader) => reader.ReadModuleReferences ()); return modules = new Collection (); } @@ -389,7 +502,7 @@ namespace Mono.Cecil { return resources; if (HasImage) - return resources = Read (this, (_, reader) => reader.ReadResources ()); + return Read (ref resources, this, (_, reader) => reader.ReadResources ()); return resources = new Collection (); } @@ -405,7 +518,7 @@ namespace Mono.Cecil { } public Collection CustomAttributes { - get { return custom_attributes ?? (custom_attributes = this.GetCustomAttributes (this)); } + get { return custom_attributes ?? (this.GetCustomAttributes (ref custom_attributes, this)); } } public bool HasTypes { @@ -423,7 +536,7 @@ namespace Mono.Cecil { return types; if (HasImage) - return types = Read (this, (_, reader) => reader.ReadTypes ()); + return Read (ref types, this, (_, reader) => reader.ReadTypes ()); return types = new TypeDefinitionCollection (this); } @@ -444,7 +557,7 @@ namespace Mono.Cecil { return exported_types; if (HasImage) - return exported_types = Read (this, (_, reader) => reader.ReadExportedTypes ()); + return Read (ref exported_types, this, (_, reader) => reader.ReadExportedTypes ()); return exported_types = new Collection (); } @@ -456,7 +569,7 @@ namespace Mono.Cecil { return entry_point; if (HasImage) - return entry_point = Read (this, (_, reader) => reader.ReadEntryPoint ()); + return Read (ref entry_point, this, (_, reader) => reader.ReadEntryPoint ()); return entry_point = null; } @@ -474,15 +587,27 @@ namespace Mono.Cecil { { this.Image = image; this.kind = image.Kind; - this.runtime = image.Runtime; + this.RuntimeVersion = image.RuntimeVersion; this.architecture = image.Architecture; this.attributes = image.Attributes; this.characteristics = image.Characteristics; - this.fq_name = image.FileName; + this.file_name = image.FileName; this.reader = new MetadataReader (this); } + public void Dispose () + { + if (Image != null) + Image.Dispose (); + + if (symbol_reader != null) + symbol_reader.Dispose (); + + if (assembly_resolver.value != null) + assembly_resolver.Dispose (); + } + public bool HasTypeReference (string fullName) { return HasTypeReference (string.Empty, fullName); @@ -610,39 +735,33 @@ namespace Mono.Cecil { internal FieldDefinition Resolve (FieldReference field) { +#if PCL || NET_CORE + if (MetadataResolver == null) + throw new NotSupportedException (); +#endif return MetadataResolver.Resolve (field); } internal MethodDefinition Resolve (MethodReference method) { +#if PCL || NET_CORE + if (MetadataResolver == null) + throw new NotSupportedException (); +#endif return MetadataResolver.Resolve (method); } internal TypeDefinition Resolve (TypeReference type) { +#if PCL || NET_CORE + if (MetadataResolver == null) + throw new NotSupportedException (); +#endif return MetadataResolver.Resolve (type); } #if !READ_ONLY - static void CheckType (object type) - { - if (type == null) - throw new ArgumentNullException ("type"); - } - - static void CheckField (object field) - { - if (field == null) - throw new ArgumentNullException ("field"); - } - - static void CheckMethod (object method) - { - if (method == null) - throw new ArgumentNullException ("method"); - } - static void CheckContext (IGenericParameterProvider context, ModuleDefinition module) { if (context == null) @@ -657,114 +776,169 @@ namespace Mono.Cecil { return context != null ? new ImportGenericContext (context) : default (ImportGenericContext); } -#if !CF +#if !PCL && !NET_CORE + [Obsolete ("Use ImportReference", error: false)] public TypeReference Import (Type type) { - return Import (type, null); + return ImportReference (type, null); } + public TypeReference ImportReference (Type type) + { + return ImportReference (type, null); + } + + [Obsolete ("Use ImportReference", error: false)] public TypeReference Import (Type type, IGenericParameterProvider context) { - CheckType (type); - CheckContext (context, this); - - return MetadataImporter.ImportType ( - type, - GenericContextFor (context), - context != null ? ImportGenericKind.Open : ImportGenericKind.Definition); + return ImportReference (type, context); } + public TypeReference ImportReference (Type type, IGenericParameterProvider context) + { + Mixin.CheckType (type); + CheckContext (context, this); + + return ReflectionImporter.ImportReference (type, context); + } + + [Obsolete ("Use ImportReference", error: false)] public FieldReference Import (SR.FieldInfo field) { - return Import (field, null); + return ImportReference (field, null); } + [Obsolete ("Use ImportReference", error: false)] public FieldReference Import (SR.FieldInfo field, IGenericParameterProvider context) { - CheckField (field); - CheckContext (context, this); - - return MetadataImporter.ImportField (field, GenericContextFor (context)); + return ImportReference (field, context); } + public FieldReference ImportReference (SR.FieldInfo field) + { + return ImportReference (field, null); + } + + public FieldReference ImportReference (SR.FieldInfo field, IGenericParameterProvider context) + { + Mixin.CheckField (field); + CheckContext (context, this); + + return ReflectionImporter.ImportReference (field, context); + } + + [Obsolete ("Use ImportReference", error: false)] public MethodReference Import (SR.MethodBase method) { - CheckMethod (method); - - return MetadataImporter.ImportMethod (method, default (ImportGenericContext), ImportGenericKind.Definition); + return ImportReference (method, null); } + [Obsolete ("Use ImportReference", error: false)] public MethodReference Import (SR.MethodBase method, IGenericParameterProvider context) { - CheckMethod (method); + return ImportReference (method, context); + } + + public MethodReference ImportReference (SR.MethodBase method) + { + return ImportReference (method, null); + } + + public MethodReference ImportReference (SR.MethodBase method, IGenericParameterProvider context) + { + Mixin.CheckMethod (method); CheckContext (context, this); - return MetadataImporter.ImportMethod (method, - GenericContextFor (context), - context != null ? ImportGenericKind.Open : ImportGenericKind.Definition); + return ReflectionImporter.ImportReference (method, context); } #endif + [Obsolete ("Use ImportReference", error: false)] public TypeReference Import (TypeReference type) { - CheckType (type); - - if (type.Module == this) - return type; - - return MetadataImporter.ImportType (type, default (ImportGenericContext)); + return ImportReference (type, null); } + [Obsolete ("Use ImportReference", error: false)] public TypeReference Import (TypeReference type, IGenericParameterProvider context) { - CheckType (type); + return ImportReference (type, context); + } + + public TypeReference ImportReference (TypeReference type) + { + return ImportReference (type, null); + } + + public TypeReference ImportReference (TypeReference type, IGenericParameterProvider context) + { + Mixin.CheckType (type); if (type.Module == this) return type; CheckContext (context, this); - return MetadataImporter.ImportType (type, GenericContextFor (context)); + return MetadataImporter.ImportReference (type, context); } + [Obsolete ("Use ImportReference", error: false)] public FieldReference Import (FieldReference field) { - CheckField (field); - - if (field.Module == this) - return field; - - return MetadataImporter.ImportField (field, default (ImportGenericContext)); + return ImportReference (field, null); } + [Obsolete ("Use ImportReference", error: false)] public FieldReference Import (FieldReference field, IGenericParameterProvider context) { - CheckField (field); + return ImportReference (field, context); + } + + public FieldReference ImportReference (FieldReference field) + { + return ImportReference (field, null); + } + + public FieldReference ImportReference (FieldReference field, IGenericParameterProvider context) + { + Mixin.CheckField (field); if (field.Module == this) return field; CheckContext (context, this); - return MetadataImporter.ImportField (field, GenericContextFor (context)); + return MetadataImporter.ImportReference (field, context); } + [Obsolete ("Use ImportReference", error: false)] public MethodReference Import (MethodReference method) { - return Import (method, null); + return ImportReference (method, null); } + [Obsolete ("Use ImportReference", error: false)] public MethodReference Import (MethodReference method, IGenericParameterProvider context) { - CheckMethod (method); + return ImportReference (method, context); + } + + public MethodReference ImportReference (MethodReference method) + { + return ImportReference (method, null); + } + + public MethodReference ImportReference (MethodReference method, IGenericParameterProvider context) + { + Mixin.CheckMethod (method); if (method.Module == this) return method; CheckContext (context, this); - return MetadataImporter.ImportMethod (method, GenericContextFor (context)); + return MetadataImporter.ImportReference (method, context); } #endif @@ -779,17 +953,43 @@ namespace Mono.Cecil { return Read (token, (t, reader) => reader.LookupToken (t)); } + readonly object module_lock = new object(); + + internal object SyncRoot { + get { return module_lock; } + } + internal TRet Read (TItem item, Func read) { - var position = reader.position; - var context = reader.context; + lock (module_lock) { + var position = reader.position; + var context = reader.context; - var ret = read (item, reader); + var ret = read (item, reader); - reader.position = position; - reader.context = context; + reader.position = position; + reader.context = context; - return ret; + return ret; + } + } + + internal TRet Read (ref TRet variable, TItem item, Func read) where TRet : class + { + lock (module_lock) { + if (variable != null) + return variable; + + var position = reader.position; + var context = reader.context; + + var ret = read (item, reader); + + reader.position = position; + reader.context = context; + + return variable = ret; + } } public bool HasDebugHeader { @@ -831,7 +1031,7 @@ namespace Mono.Cecil { var module = new ModuleDefinition { Name = name, kind = parameters.Kind, - runtime = parameters.Runtime, + Runtime = parameters.Runtime, architecture = parameters.Architecture, mvid = Guid.NewGuid (), Attributes = ModuleAttributes.ILOnly, @@ -839,11 +1039,20 @@ namespace Mono.Cecil { }; if (parameters.AssemblyResolver != null) - module.assembly_resolver = parameters.AssemblyResolver; + module.assembly_resolver = Disposable.NotOwned (parameters.AssemblyResolver); if (parameters.MetadataResolver != null) module.metadata_resolver = parameters.MetadataResolver; +#if !READ_ONLY + if (parameters.MetadataImporterProvider != null) + module.metadata_importer = parameters.MetadataImporterProvider.GetMetadataImporter (module); +#if !PCL && !NET_CORE + if (parameters.ReflectionImporterProvider != null) + module.reflection_importer = parameters.ReflectionImporterProvider.GetReflectionImporter (module); +#endif +#endif + if (parameters.Kind != ModuleKind.NetModule) { var assembly = new AssemblyDefinition (); module.assembly = assembly; @@ -861,22 +1070,24 @@ namespace Mono.Cecil { if (name.EndsWith (".dll") || name.EndsWith (".exe")) name = name.Substring (0, name.Length - 4); - return new AssemblyNameDefinition (name, new Version (0, 0, 0, 0)); + return new AssemblyNameDefinition (name, Mixin.ZeroVersion); } #endif +#if !PCL && !NET_CORE public void ReadSymbols () { - if (string.IsNullOrEmpty (fq_name)) + if (string.IsNullOrEmpty (file_name)) throw new InvalidOperationException (); var provider = SymbolProvider.GetPlatformReaderProvider (); if (provider == null) throw new InvalidOperationException (); - ReadSymbols (provider.GetSymbolReader (this, fq_name)); + ReadSymbols (provider.GetSymbolReader (this, file_name)); } +#endif public void ReadSymbols (ISymbolReader reader) { @@ -886,80 +1097,113 @@ namespace Mono.Cecil { symbol_reader = reader; ProcessDebugHeader (); + + if (HasImage && ReadingMode == ReadingMode.Immediate) { + var immediate_reader = new ImmediateModuleReader (Image); + immediate_reader.ReadSymbols (this); + } } +#if !PCL public static ModuleDefinition ReadModule (string fileName) { return ReadModule (fileName, new ReaderParameters (ReadingMode.Deferred)); } + public static ModuleDefinition ReadModule (string fileName, ReaderParameters parameters) + { + var stream = GetFileStream (fileName, FileMode.Open, parameters.ReadWrite ? FileAccess.ReadWrite : FileAccess.Read, FileShare.Read); + + if (parameters.InMemory) { + var memory = new MemoryStream (stream.CanSeek ? (int) stream.Length : 0); + using (stream) + stream.CopyTo (memory); + + memory.Position = 0; + stream = memory; + } + + try { + return ReadModule (Disposable.Owned (stream), fileName, parameters); + } catch (Exception) { + stream.Dispose (); + throw; + } + } + + static Stream GetFileStream (string fileName, FileMode mode, FileAccess access, FileShare share) + { + Mixin.CheckFileName (fileName); + + return new FileStream (fileName, mode, access, share); + } +#endif + public static ModuleDefinition ReadModule (Stream stream) { return ReadModule (stream, new ReaderParameters (ReadingMode.Deferred)); } - public static ModuleDefinition ReadModule (string fileName, ReaderParameters parameters) - { - using (var stream = GetFileStream (fileName, FileMode.Open, FileAccess.Read, FileShare.Read)) { - return ReadModule (stream, parameters); - } - } - - static void CheckStream (object stream) - { - if (stream == null) - throw new ArgumentNullException ("stream"); - } - public static ModuleDefinition ReadModule (Stream stream, ReaderParameters parameters) { - CheckStream (stream); - if (!stream.CanRead || !stream.CanSeek) - throw new ArgumentException (); - Mixin.CheckParameters (parameters); + Mixin.CheckStream (stream); + Mixin.CheckReadSeek (stream); - return ModuleReader.CreateModuleFrom ( - ImageReader.ReadImageFrom (stream), - parameters); + return ReadModule (Disposable.NotOwned (stream), "", parameters); } - static Stream GetFileStream (string fileName, FileMode mode, FileAccess access, FileShare share) + static ModuleDefinition ReadModule (Disposable stream, string fileName, ReaderParameters parameters) { - if (fileName == null) - throw new ArgumentNullException ("fileName"); - if (fileName.Length == 0) - throw new ArgumentException (); + Mixin.CheckParameters (parameters); - return new FileStream (fileName, mode, access, share); + return ModuleReader.CreateModule ( + ImageReader.ReadImage (stream, fileName), + parameters); } #if !READ_ONLY +#if !PCL public void Write (string fileName) { Write (fileName, new WriterParameters ()); } + public void Write (string fileName, WriterParameters parameters) + { + Mixin.CheckParameters (parameters); + var file = GetFileStream (fileName, FileMode.Create, FileAccess.ReadWrite, FileShare.None); + ModuleWriter.WriteModuleTo (this, Disposable.Owned (file), parameters); + } +#endif + + public void Write () + { + Write (new WriterParameters ()); + } + + public void Write (WriterParameters parameters) + { + if (!HasImage) + throw new InvalidOperationException (); + + var image_stream = Image.Stream.value; + image_stream.Position = 0; + Write (image_stream, parameters); + } + public void Write (Stream stream) { Write (stream, new WriterParameters ()); } - public void Write (string fileName, WriterParameters parameters) - { - using (var stream = GetFileStream (fileName, FileMode.Create, FileAccess.ReadWrite, FileShare.None)) { - Write (stream, parameters); - } - } - public void Write (Stream stream, WriterParameters parameters) { - CheckStream (stream); - if (!stream.CanWrite || !stream.CanSeek) - throw new ArgumentException (); + Mixin.CheckStream (stream); + Mixin.CheckWriteSeek (stream); Mixin.CheckParameters (parameters); - ModuleWriter.WriteModuleTo (this, stream, parameters); + ModuleWriter.WriteModuleTo (this, Disposable.NotOwned (stream), parameters); } #endif @@ -968,6 +1212,54 @@ namespace Mono.Cecil { static partial class Mixin { + public static void CheckFileName (string fileName) + { + if (fileName == null) + throw new ArgumentNullException ("fileName"); + if (fileName.Length == 0) + throw new ArgumentException (); + } + + public static void CheckStream (object stream) + { + if (stream == null) + throw new ArgumentNullException ("stream"); + } + + public static void CheckWriteSeek (Stream stream) + { + if (!stream.CanWrite || !stream.CanSeek) + throw new ArgumentException (); + } + + public static void CheckReadSeek (Stream stream) + { + if (!stream.CanRead || !stream.CanSeek) + throw new ArgumentException (); + } + +#if !READ_ONLY + + public static void CheckType (object type) + { + if (type == null) + throw new ArgumentNullException ("type"); + } + + public static void CheckField (object field) + { + if (field == null) + throw new ArgumentNullException ("field"); + } + + public static void CheckMethod (object method) + { + if (method == null) + throw new ArgumentNullException ("method"); + } + +#endif + public static void CheckParameters (object parameters) { if (parameters == null) @@ -979,17 +1271,25 @@ namespace Mono.Cecil { return self != null && self.HasImage; } - public static bool IsCorlib (this ModuleDefinition module) + public static bool IsCoreLibrary (this ModuleDefinition module) { if (module.Assembly == null) return false; - return module.Assembly.Name.Name == "mscorlib"; + var assembly_name = module.Assembly.Name.Name; + + if (assembly_name != "mscorlib" && assembly_name != "System.Runtime") + return false; + + if (module.HasImage && module.Read (module, (m, reader) => reader.image.GetTableLength (Table.AssemblyRef) > 0)) + return false; + + return true; } - public static string GetFullyQualifiedName (this Stream self) + public static string GetFileName (this Stream self) { -#if !SILVERLIGHT +#if !PCL var file_stream = self as FileStream; if (file_stream == null) return string.Empty; @@ -1000,6 +1300,16 @@ namespace Mono.Cecil { #endif } +#if !NET_4_0 + public static void CopyTo (this Stream self, Stream target) + { + var buffer = new byte [1024 * 8]; + int read; + while ((read = self.Read (buffer, 0, buffer.Length)) > 0) + target.Write (buffer, 0, read); + } +#endif + public static TargetRuntime ParseRuntime (this string self) { switch (self [1]) { @@ -1014,5 +1324,43 @@ namespace Mono.Cecil { return TargetRuntime.Net_4_0; } } + + public static string RuntimeVersionString (this TargetRuntime runtime) + { + switch (runtime) { + case TargetRuntime.Net_1_0: + return "v1.0.3705"; + case TargetRuntime.Net_1_1: + return "v1.1.4322"; + case TargetRuntime.Net_2_0: + return "v2.0.50727"; + case TargetRuntime.Net_4_0: + default: + return "v4.0.30319"; + } + } + + public static bool IsWindowsMetadata (this ModuleDefinition module) + { + return module.MetadataKind != MetadataKind.Ecma335; + } + +#if !PCL + public static byte [] ReadAll (this Stream self) + { + int read; + var memory = new MemoryStream ((int) self.Length); + var buffer = new byte [1024]; + + while ((read = self.Read (buffer, 0, buffer.Length)) != 0) + memory.Write (buffer, 0, read); + + return memory.ToArray (); + } +#endif + + public static void Read (object o) + { + } } } diff --git a/external/cecil/Mono.Cecil/ModuleKind.cs b/external/cecil/Mono.Cecil/ModuleKind.cs index c29da887d8..39f980a091 100644 --- a/external/cecil/Mono.Cecil/ModuleKind.cs +++ b/external/cecil/Mono.Cecil/ModuleKind.cs @@ -1,29 +1,11 @@ // -// ModuleKind.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; @@ -37,6 +19,12 @@ namespace Mono.Cecil { NetModule, } + public enum MetadataKind { + Ecma335, + WindowsMetadata, + ManagedWindowsMetadata, + } + public enum TargetArchitecture { I386, AMD64, diff --git a/external/cecil/Mono.Cecil/ModuleReference.cs b/external/cecil/Mono.Cecil/ModuleReference.cs index 3934b3ceb8..43c618f4c1 100644 --- a/external/cecil/Mono.Cecil/ModuleReference.cs +++ b/external/cecil/Mono.Cecil/ModuleReference.cs @@ -1,29 +1,11 @@ // -// ModuleReference.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // namespace Mono.Cecil { diff --git a/external/cecil/Mono.Cecil/NativeType.cs b/external/cecil/Mono.Cecil/NativeType.cs index 88da9805e8..02174db6ff 100644 --- a/external/cecil/Mono.Cecil/NativeType.cs +++ b/external/cecil/Mono.Cecil/NativeType.cs @@ -1,29 +1,11 @@ // -// NativeType.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // namespace Mono.Cecil { diff --git a/external/cecil/Mono.Cecil/PInvokeAttributes.cs b/external/cecil/Mono.Cecil/PInvokeAttributes.cs index bb36838253..11e96d20d4 100644 --- a/external/cecil/Mono.Cecil/PInvokeAttributes.cs +++ b/external/cecil/Mono.Cecil/PInvokeAttributes.cs @@ -1,29 +1,11 @@ // -// PInvokeAttributes.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; diff --git a/external/cecil/Mono.Cecil/PInvokeInfo.cs b/external/cecil/Mono.Cecil/PInvokeInfo.cs index cfd817c8d0..8efc010819 100644 --- a/external/cecil/Mono.Cecil/PInvokeInfo.cs +++ b/external/cecil/Mono.Cecil/PInvokeInfo.cs @@ -1,29 +1,11 @@ // -// PInvokeInfo.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // namespace Mono.Cecil { diff --git a/external/cecil/Mono.Cecil/ParameterAttributes.cs b/external/cecil/Mono.Cecil/ParameterAttributes.cs index e0bc825d8b..9a0e35e07e 100644 --- a/external/cecil/Mono.Cecil/ParameterAttributes.cs +++ b/external/cecil/Mono.Cecil/ParameterAttributes.cs @@ -1,29 +1,11 @@ // -// ParameterAttributes.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; diff --git a/external/cecil/Mono.Cecil/ParameterDefinition.cs b/external/cecil/Mono.Cecil/ParameterDefinition.cs index 26152bd8df..59bafe2c8f 100644 --- a/external/cecil/Mono.Cecil/ParameterDefinition.cs +++ b/external/cecil/Mono.Cecil/ParameterDefinition.cs @@ -1,29 +1,11 @@ // -// ParameterDefinition.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using Mono.Collections.Generic; @@ -60,7 +42,7 @@ namespace Mono.Cecil { public bool HasConstant { get { - ResolveConstant (); + this.ResolveConstant (ref constant, parameter_type.Module); return constant != Mixin.NoValue; } @@ -72,14 +54,6 @@ namespace Mono.Cecil { set { constant = value; } } - void ResolveConstant () - { - if (constant != Mixin.NotResolved) - return; - - this.ResolveConstant (ref constant, parameter_type.Module); - } - public bool HasCustomAttributes { get { if (custom_attributes != null) @@ -90,7 +64,7 @@ namespace Mono.Cecil { } public Collection CustomAttributes { - get { return custom_attributes ?? (custom_attributes = this.GetCustomAttributes (parameter_type.Module)); } + get { return custom_attributes ?? (this.GetCustomAttributes (ref custom_attributes, parameter_type.Module)); } } public bool HasMarshalInfo { @@ -103,7 +77,7 @@ namespace Mono.Cecil { } public MarshalInfo MarshalInfo { - get { return marshal_info ?? (marshal_info = this.GetMarshalInfo (parameter_type.Module)); } + get { return marshal_info ?? (this.GetMarshalInfo (ref marshal_info, parameter_type.Module)); } set { marshal_info = value; } } diff --git a/external/cecil/Mono.Cecil/ParameterDefinitionCollection.cs b/external/cecil/Mono.Cecil/ParameterDefinitionCollection.cs index bd8b1c1390..1a9764c50e 100644 --- a/external/cecil/Mono.Cecil/ParameterDefinitionCollection.cs +++ b/external/cecil/Mono.Cecil/ParameterDefinitionCollection.cs @@ -1,29 +1,11 @@ // -// ParameterDefinitionCollection.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; diff --git a/external/cecil/Mono.Cecil/ParameterReference.cs b/external/cecil/Mono.Cecil/ParameterReference.cs index 46b057cd9f..4670a562be 100644 --- a/external/cecil/Mono.Cecil/ParameterReference.cs +++ b/external/cecil/Mono.Cecil/ParameterReference.cs @@ -1,29 +1,11 @@ // -// ParameterReference.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; diff --git a/external/cecil/Mono.Cecil/PinnedType.cs b/external/cecil/Mono.Cecil/PinnedType.cs index ff59cfb7e1..fa89af514b 100644 --- a/external/cecil/Mono.Cecil/PinnedType.cs +++ b/external/cecil/Mono.Cecil/PinnedType.cs @@ -1,29 +1,11 @@ // -// PinnedType.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; diff --git a/external/cecil/Mono.Cecil/PointerType.cs b/external/cecil/Mono.Cecil/PointerType.cs index a142e14409..4b21164a32 100644 --- a/external/cecil/Mono.Cecil/PointerType.cs +++ b/external/cecil/Mono.Cecil/PointerType.cs @@ -1,29 +1,11 @@ // -// PointerType.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; diff --git a/external/cecil/Mono.Cecil/PropertyAttributes.cs b/external/cecil/Mono.Cecil/PropertyAttributes.cs index 1be0413f28..4d1ce8c8b3 100644 --- a/external/cecil/Mono.Cecil/PropertyAttributes.cs +++ b/external/cecil/Mono.Cecil/PropertyAttributes.cs @@ -1,29 +1,11 @@ // -// PropertyAttributes.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; diff --git a/external/cecil/Mono.Cecil/PropertyDefinition.cs b/external/cecil/Mono.Cecil/PropertyDefinition.cs index 42878a0948..87f29475ef 100644 --- a/external/cecil/Mono.Cecil/PropertyDefinition.cs +++ b/external/cecil/Mono.Cecil/PropertyDefinition.cs @@ -1,29 +1,11 @@ // -// PropertyDefinition.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System.Text; @@ -76,7 +58,7 @@ namespace Mono.Cecil { } public Collection CustomAttributes { - get { return custom_attributes ?? (custom_attributes = this.GetCustomAttributes (Module)); } + get { return custom_attributes ?? (this.GetCustomAttributes (ref custom_attributes, Module)); } } public MethodDefinition GetMethod { @@ -170,7 +152,7 @@ namespace Mono.Cecil { public bool HasConstant { get { - ResolveConstant (); + this.ResolveConstant (ref constant, Module); return constant != Mixin.NoValue; } @@ -182,14 +164,6 @@ namespace Mono.Cecil { set { constant = value; } } - void ResolveConstant () - { - if (constant != Mixin.NotResolved) - return; - - this.ResolveConstant (ref constant, Module); - } - #region PropertyAttributes public bool IsSpecialName { @@ -247,14 +221,19 @@ namespace Mono.Cecil { void InitializeMethods () { - if (get_method != null || set_method != null) - return; - var module = this.Module; - if (!module.HasImage ()) + if (module == null) return; - module.Read (this, (property, reader) => reader.ReadMethods (property)); + lock (module.SyncRoot) { + if (get_method != null || set_method != null) + return; + + if (!module.HasImage ()) + return; + + module.Read (this, (property, reader) => reader.ReadMethods (property)); + } } public override PropertyDefinition Resolve () diff --git a/external/cecil/Mono.Cecil/PropertyReference.cs b/external/cecil/Mono.Cecil/PropertyReference.cs index 0dcfc952fe..4b827cd0e5 100644 --- a/external/cecil/Mono.Cecil/PropertyReference.cs +++ b/external/cecil/Mono.Cecil/PropertyReference.cs @@ -1,29 +1,11 @@ // -// PropertyReference.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; @@ -54,6 +36,11 @@ namespace Mono.Cecil { property_type = propertyType; } - public abstract PropertyDefinition Resolve (); + protected override IMemberDefinition ResolveDefinition () + { + return this.Resolve (); + } + + public new abstract PropertyDefinition Resolve (); } } diff --git a/external/cecil/Mono.Cecil/ReferenceType.cs b/external/cecil/Mono.Cecil/ReferenceType.cs index 7940c617c7..67686fbffd 100644 --- a/external/cecil/Mono.Cecil/ReferenceType.cs +++ b/external/cecil/Mono.Cecil/ReferenceType.cs @@ -1,29 +1,11 @@ // -// ByReferenceType.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; diff --git a/external/cecil/Mono.Cecil/Resource.cs b/external/cecil/Mono.Cecil/Resource.cs index eff7f41aa1..cee75f9e49 100644 --- a/external/cecil/Mono.Cecil/Resource.cs +++ b/external/cecil/Mono.Cecil/Resource.cs @@ -1,29 +1,11 @@ // -// ResourceType.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // namespace Mono.Cecil { diff --git a/external/cecil/Mono.Cecil/SecurityDeclaration.cs b/external/cecil/Mono.Cecil/SecurityDeclaration.cs index 837472a119..309f7d2188 100644 --- a/external/cecil/Mono.Cecil/SecurityDeclaration.cs +++ b/external/cecil/Mono.Cecil/SecurityDeclaration.cs @@ -1,29 +1,11 @@ // -// SecurityDeclaration.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; @@ -181,11 +163,12 @@ namespace Mono.Cecil { public static Collection GetSecurityDeclarations ( this ISecurityDeclarationProvider self, + ref Collection variable, ModuleDefinition module) { return module.HasImage () - ? module.Read (self, (provider, reader) => reader.ReadSecurityDeclarations (provider)) - : new Collection (); + ? module.Read (ref variable, self, (provider, reader) => reader.ReadSecurityDeclarations (provider)) + : variable = new Collection(); } } } diff --git a/external/cecil/Mono.Cecil/SentinelType.cs b/external/cecil/Mono.Cecil/SentinelType.cs index 664d75bfd8..b603cc3c0b 100644 --- a/external/cecil/Mono.Cecil/SentinelType.cs +++ b/external/cecil/Mono.Cecil/SentinelType.cs @@ -1,29 +1,11 @@ // -// SentinelType.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; diff --git a/external/cecil/Mono.Cecil/TargetRuntime.cs b/external/cecil/Mono.Cecil/TargetRuntime.cs index 9b49a5f77e..c1cd0269f7 100644 --- a/external/cecil/Mono.Cecil/TargetRuntime.cs +++ b/external/cecil/Mono.Cecil/TargetRuntime.cs @@ -1,29 +1,11 @@ // -// TargetRuntime.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // namespace Mono.Cecil { diff --git a/external/cecil/Mono.Cecil/Treatments.cs b/external/cecil/Mono.Cecil/Treatments.cs new file mode 100644 index 0000000000..4ceaebf7ce --- /dev/null +++ b/external/cecil/Mono.Cecil/Treatments.cs @@ -0,0 +1,66 @@ +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. +// +// Licensed under the MIT/X11 license. +// + +using System; + +namespace Mono.Cecil { + + [Flags] + enum TypeDefinitionTreatment { + None = 0x0, + + KindMask = 0xf, + NormalType = 0x1, + NormalAttribute = 0x2, + UnmangleWindowsRuntimeName = 0x3, + PrefixWindowsRuntimeName = 0x4, + RedirectToClrType = 0x5, + RedirectToClrAttribute = 0x6, + + Abstract = 0x10, + Internal = 0x20, + } + + enum TypeReferenceTreatment { + None = 0x0, + SystemDelegate = 0x1, + SystemAttribute = 0x2, + UseProjectionInfo = 0x3, + } + + [Flags] + enum MethodDefinitionTreatment { + None = 0x0, + Dispose = 0x1, + Abstract = 0x2, + Private = 0x4, + Public = 0x8, + Runtime = 0x10, + InternalCall = 0x20, + } + + enum FieldDefinitionTreatment { + None = 0x0, + Public = 0x1, + } + + enum MemberReferenceTreatment { + None = 0x0, + Dispose = 0x1, + } + + enum CustomAttributeValueTreatment { + None = 0x0, + AllowSingle = 0x1, + AllowMultiple = 0x2, + VersionAttribute = 0x3, + DeprecatedAttribute = 0x4, + } +} diff --git a/external/cecil/Mono.Cecil/TypeAttributes.cs b/external/cecil/Mono.Cecil/TypeAttributes.cs index 86fbc4dba5..92a71aca4f 100644 --- a/external/cecil/Mono.Cecil/TypeAttributes.cs +++ b/external/cecil/Mono.Cecil/TypeAttributes.cs @@ -1,29 +1,11 @@ // -// TypeAttributes.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; diff --git a/external/cecil/Mono.Cecil/TypeDefinition.cs b/external/cecil/Mono.Cecil/TypeDefinition.cs index 58c52af179..62f65a5283 100644 --- a/external/cecil/Mono.Cecil/TypeDefinition.cs +++ b/external/cecil/Mono.Cecil/TypeDefinition.cs @@ -1,29 +1,11 @@ // -// TypeDefinition.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; @@ -43,7 +25,7 @@ namespace Mono.Cecil { short packing_size = Mixin.NotResolvedMarker; int class_size = Mixin.NotResolvedMarker; - Collection interfaces; + InterfaceImplementationCollection interfaces; Collection nested_types; Collection methods; Collection fields; @@ -54,7 +36,12 @@ namespace Mono.Cecil { public TypeAttributes Attributes { get { return (TypeAttributes) attributes; } - set { attributes = (uint) value; } + set { + if (IsWindowsRuntimeProjection && (ushort) value != attributes) + throw new InvalidOperationException (); + + attributes = (uint) value; + } } public TypeReference BaseType { @@ -62,6 +49,16 @@ namespace Mono.Cecil { set { base_type = value; } } + public override string Name { + get { return base.Name; } + set { + if (IsWindowsRuntimeProjection && value != base.Name) + throw new InvalidOperationException (); + + base.Name = value; + } + } + void ResolveLayout () { if (packing_size != Mixin.NotResolvedMarker || class_size != Mixin.NotResolvedMarker) @@ -119,22 +116,19 @@ namespace Mono.Cecil { if (interfaces != null) return interfaces.Count > 0; - if (HasImage) - return Module.Read (this, (type, reader) => reader.HasInterfaces (type)); - - return false; + return HasImage && Module.Read (this, (type, reader) => reader.HasInterfaces (type)); } } - public Collection Interfaces { + public Collection Interfaces { get { if (interfaces != null) return interfaces; if (HasImage) - return interfaces = Module.Read (this, (type, reader) => reader.ReadInterfaces (type)); + return Module.Read (ref interfaces, this, (type, reader) => reader.ReadInterfaces (type)); - return interfaces = new Collection (); + return interfaces = new InterfaceImplementationCollection (this); } } @@ -143,10 +137,7 @@ namespace Mono.Cecil { if (nested_types != null) return nested_types.Count > 0; - if (HasImage) - return Module.Read (this, (type, reader) => reader.HasNestedTypes (type)); - - return false; + return HasImage && Module.Read (this, (type, reader) => reader.HasNestedTypes (type)); } } @@ -156,7 +147,7 @@ namespace Mono.Cecil { return nested_types; if (HasImage) - return nested_types = Module.Read (this, (type, reader) => reader.ReadNestedTypes (type)); + return Module.Read (ref nested_types, this, (type, reader) => reader.ReadNestedTypes (type)); return nested_types = new MemberDefinitionCollection (this); } @@ -167,10 +158,7 @@ namespace Mono.Cecil { if (methods != null) return methods.Count > 0; - if (HasImage) - return methods_range.Length > 0; - - return false; + return HasImage && methods_range.Length > 0; } } @@ -180,7 +168,7 @@ namespace Mono.Cecil { return methods; if (HasImage) - return methods = Module.Read (this, (type, reader) => reader.ReadMethods (type)); + return Module.Read (ref methods, this, (type, reader) => reader.ReadMethods (type)); return methods = new MemberDefinitionCollection (this); } @@ -191,10 +179,7 @@ namespace Mono.Cecil { if (fields != null) return fields.Count > 0; - if (HasImage) - return fields_range.Length > 0; - - return false; + return HasImage && fields_range.Length > 0; } } @@ -204,7 +189,7 @@ namespace Mono.Cecil { return fields; if (HasImage) - return fields = Module.Read (this, (type, reader) => reader.ReadFields (type)); + return Module.Read (ref fields, this, (type, reader) => reader.ReadFields (type)); return fields = new MemberDefinitionCollection (this); } @@ -215,10 +200,7 @@ namespace Mono.Cecil { if (events != null) return events.Count > 0; - if (HasImage) - return Module.Read (this, (type, reader) => reader.HasEvents (type)); - - return false; + return HasImage && Module.Read (this, (type, reader) => reader.HasEvents (type)); } } @@ -228,7 +210,7 @@ namespace Mono.Cecil { return events; if (HasImage) - return events = Module.Read (this, (type, reader) => reader.ReadEvents (type)); + return Module.Read (ref events, this, (type, reader) => reader.ReadEvents (type)); return events = new MemberDefinitionCollection (this); } @@ -239,10 +221,7 @@ namespace Mono.Cecil { if (properties != null) return properties.Count > 0; - if (HasImage) - return Module.Read (this, (type, reader) => reader.HasProperties (type)); - - return false; + return HasImage && Module.Read (this, (type, reader) => reader.HasProperties (type)); } } @@ -252,7 +231,7 @@ namespace Mono.Cecil { return properties; if (HasImage) - return properties = Module.Read (this, (type, reader) => reader.ReadProperties (type)); + return Module.Read (ref properties, this, (type, reader) => reader.ReadProperties (type)); return properties = new MemberDefinitionCollection (this); } @@ -268,7 +247,7 @@ namespace Mono.Cecil { } public Collection SecurityDeclarations { - get { return security_declarations ?? (security_declarations = this.GetSecurityDeclarations (Module)); } + get { return security_declarations ?? (this.GetSecurityDeclarations (ref security_declarations, Module)); } } public bool HasCustomAttributes { @@ -281,7 +260,7 @@ namespace Mono.Cecil { } public Collection CustomAttributes { - get { return custom_attributes ?? (custom_attributes = this.GetCustomAttributes (Module)); } + get { return custom_attributes ?? (this.GetCustomAttributes (ref custom_attributes, Module)); } } public override bool HasGenericParameters { @@ -294,7 +273,7 @@ namespace Mono.Cecil { } public override Collection GenericParameters { - get { return generic_parameters ?? (generic_parameters = this.GetGenericParameters (Module)); } + get { return generic_parameters ?? (this.GetGenericParameters (ref generic_parameters, Module)); } } #region TypeAttributes @@ -465,6 +444,11 @@ namespace Mono.Cecil { set { base.DeclaringType = value; } } + internal new TypeDefinitionProjection WindowsRuntimeProjection { + get { return (TypeDefinitionProjection) projection; } + set { projection = value; } + } + public TypeDefinition (string @namespace, string name, TypeAttributes attributes) : base (@namespace, name) { @@ -478,12 +462,116 @@ namespace Mono.Cecil { this.BaseType = baseType; } + protected override void ClearFullName () + { + base.ClearFullName (); + + if (!HasNestedTypes) + return; + + var nested_types = this.NestedTypes; + + for (int i = 0; i < nested_types.Count; i++) + nested_types [i].ClearFullName (); + } + public override TypeDefinition Resolve () { return this; } } + public sealed class InterfaceImplementation : ICustomAttributeProvider + { + internal TypeDefinition type; + internal MetadataToken token; + + TypeReference interface_type; + Collection custom_attributes; + + public TypeReference InterfaceType { + get { return interface_type; } + set { interface_type = value; } + } + + public bool HasCustomAttributes { + get { + if (custom_attributes != null) + return custom_attributes.Count > 0; + + if (type == null) + return false; + + return this.GetHasCustomAttributes (type.Module); + } + } + + public Collection CustomAttributes { + get { + if (type == null) + return custom_attributes = new Collection (); + + return custom_attributes ?? (this.GetCustomAttributes (ref custom_attributes, type.Module)); + } + } + + public MetadataToken MetadataToken { + get { return token; } + set { token = value; } + } + + internal InterfaceImplementation (TypeReference interfaceType, MetadataToken token) + { + this.interface_type = interfaceType; + this.token = token; + } + + public InterfaceImplementation (TypeReference interfaceType) + { + if (interfaceType == null) + throw new ArgumentNullException ("interfaceType"); + + this.interface_type = interfaceType; + this.token = new MetadataToken (TokenType.InterfaceImpl); + } + } + + class InterfaceImplementationCollection : Collection + { + readonly TypeDefinition type; + + internal InterfaceImplementationCollection (TypeDefinition type) + { + this.type = type; + } + + internal InterfaceImplementationCollection (TypeDefinition type, int length) + : base (length) + { + this.type = type; + } + + protected override void OnAdd (InterfaceImplementation item, int index) + { + item.type = type; + } + + protected override void OnInsert (InterfaceImplementation item, int index) + { + item.type = type; + } + + protected override void OnSet (InterfaceImplementation item, int index) + { + item.type = type; + } + + protected override void OnRemove (InterfaceImplementation item, int index) + { + item.type = null; + } + } + static partial class Mixin { public static TypeReference GetEnumUnderlyingType (this TypeDefinition self) @@ -499,7 +587,7 @@ namespace Mono.Cecil { throw new ArgumentException (); } - public static TypeDefinition GetNestedType (this TypeDefinition self, string name) + public static TypeDefinition GetNestedType (this TypeDefinition self, string fullname) { if (!self.HasNestedTypes) return null; @@ -508,7 +596,8 @@ namespace Mono.Cecil { for (int i = 0; i < nested_types.Count; i++) { var nested_type = nested_types [i]; - if (nested_type.Name == name) + + if (nested_type.TypeFullName () == fullname) return nested_type; } diff --git a/external/cecil/Mono.Cecil/TypeDefinitionCollection.cs b/external/cecil/Mono.Cecil/TypeDefinitionCollection.cs index eae712282f..95e39b9a6e 100644 --- a/external/cecil/Mono.Cecil/TypeDefinitionCollection.cs +++ b/external/cecil/Mono.Cecil/TypeDefinitionCollection.cs @@ -1,29 +1,11 @@ // -// TypeDefinitionCollection.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; diff --git a/external/cecil/Mono.Cecil/TypeParser.cs b/external/cecil/Mono.Cecil/TypeParser.cs index 90e04a6f41..02f3036f37 100644 --- a/external/cecil/Mono.Cecil/TypeParser.cs +++ b/external/cecil/Mono.Cecil/TypeParser.cs @@ -1,29 +1,11 @@ // -// TypeParser.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; @@ -105,17 +87,7 @@ namespace Mono.Cecil { static bool ParseInt32 (string value, out int result) { -#if CF - try { - result = int.Parse (value); - return true; - } catch { - result = 0; - return false; - } -#else return int.TryParse (value, out result); -#endif } static void TryAddArity (string name, ref int arity) @@ -129,11 +101,15 @@ namespace Mono.Cecil { string ParsePart () { - int start = position; - while (position < length && !IsDelimiter (fullname [position])) - position++; + var part = new StringBuilder (); + while (position < length && !IsDelimiter (fullname [position])) { + if (fullname [position] == '\\') + position++; - return fullname.Substring (start, position - start); + part.Append (fullname [position++]); + } + + return part.ToString (); } static bool IsDelimiter (char chr) @@ -168,13 +144,7 @@ namespace Mono.Cecil { static void Add (ref T [] array, T item) { - if (array == null) { - array = new [] { item }; - return; - } - - array = array.Resize (array.Length + 1); - array [array.Length - 1] = item; + array = array.Add (item); } int [] ParseSpecs () @@ -382,22 +352,14 @@ namespace Mono.Cecil { static IMetadataScope GetMetadataScope (ModuleDefinition module, Type type_info) { if (string.IsNullOrEmpty (type_info.assembly)) - return module.TypeSystem.Corlib; + return module.TypeSystem.CoreLibrary; - return MatchReference (module, AssemblyNameReference.Parse (type_info.assembly)); - } + AssemblyNameReference match; + var reference = AssemblyNameReference.Parse (type_info.assembly); - static AssemblyNameReference MatchReference (ModuleDefinition module, AssemblyNameReference pattern) - { - var references = module.AssemblyReferences; - - for (int i = 0; i < references.Count; i++) { - var reference = references [i]; - if (reference.FullName == pattern.FullName) - return reference; - } - - return pattern; + return module.TryGetAssemblyNameReference (reference, out match) + ? match + : reference; } static bool TryGetDefinition (ModuleDefinition module, Type type_info, out TypeReference type) @@ -412,8 +374,13 @@ namespace Mono.Cecil { var nested_names = type_info.nested_names; if (!nested_names.IsNullOrEmpty ()) { - for (int i = 0; i < nested_names.Length; i++) - typedef = typedef.GetNestedType (nested_names [i]); + for (int i = 0; i < nested_names.Length; i++) { + var nested_type = typedef.GetNestedType (nested_names [i]); + if (nested_type == null) + return false; + + typedef = nested_type; + } } type = typedef; @@ -441,9 +408,21 @@ namespace Mono.Cecil { return name.ToString (); } + static void AppendNamePart (string part, StringBuilder name) + { + foreach (var c in part) { + if (IsDelimiter (c)) + name.Append ('\\'); + + name.Append (c); + } + } + static void AppendType (TypeReference type, StringBuilder name, bool fq_name, bool top_level) { - var declaring_type = type.DeclaringType; + var element_type = type.GetElementType (); + + var declaring_type = element_type.DeclaringType; if (declaring_type != null) { AppendType (declaring_type, name, false, top_level); name.Append ('+'); @@ -451,11 +430,11 @@ namespace Mono.Cecil { var @namespace = type.Namespace; if (!string.IsNullOrEmpty (@namespace)) { - name.Append (@namespace); + AppendNamePart (@namespace, name); name.Append ('.'); } - name.Append (type.GetElementType ().Name); + AppendNamePart (element_type.Name, name); if (!fq_name) return; diff --git a/external/cecil/Mono.Cecil/TypeReference.cs b/external/cecil/Mono.Cecil/TypeReference.cs index f811b4f018..c2643b6710 100644 --- a/external/cecil/Mono.Cecil/TypeReference.cs +++ b/external/cecil/Mono.Cecil/TypeReference.cs @@ -1,29 +1,11 @@ // -// TypeReference.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; @@ -83,16 +65,20 @@ namespace Mono.Cecil { public override string Name { get { return base.Name; } set { + if (IsWindowsRuntimeProjection && value != base.Name) + throw new InvalidOperationException ("Projected type reference name can't be changed."); base.Name = value; - fullname = null; + ClearFullName (); } } public virtual string Namespace { get { return @namespace; } set { + if (IsWindowsRuntimeProjection && value != @namespace) + throw new InvalidOperationException ("Projected type reference namespace can't be changed."); @namespace = value; - fullname = null; + ClearFullName (); } } @@ -114,6 +100,11 @@ namespace Mono.Cecil { } } + internal new TypeReferenceProjection WindowsRuntimeProjection { + get { return (TypeReferenceProjection) projection; } + set { projection = value; } + } + IGenericParameterProvider IGenericContext.Type { get { return this; } } @@ -150,10 +141,14 @@ namespace Mono.Cecil { set { var declaring_type = this.DeclaringType; if (declaring_type != null) { + if (IsWindowsRuntimeProjection && value != declaring_type.Scope) + throw new InvalidOperationException ("Projected type scope can't be changed."); declaring_type.Scope = value; return; } + if (IsWindowsRuntimeProjection && value != scope) + throw new InvalidOperationException ("Projected type scope can't be changed."); scope = value; } } @@ -165,8 +160,10 @@ namespace Mono.Cecil { public override TypeReference DeclaringType { get { return base.DeclaringType; } set { + if (IsWindowsRuntimeProjection && value != base.DeclaringType) + throw new InvalidOperationException ("Projected type declaring type can't be changed."); base.DeclaringType = value; - fullname = null; + ClearFullName (); } } @@ -175,13 +172,12 @@ namespace Mono.Cecil { if (fullname != null) return fullname; + fullname = this.TypeFullName (); + if (IsNested) - return fullname = DeclaringType.FullName + "/" + Name; + fullname = DeclaringType.FullName + "/" + fullname; - if (string.IsNullOrEmpty (@namespace)) - return fullname = Name; - - return fullname = @namespace + "." + Name; + return fullname; } } @@ -260,12 +256,22 @@ namespace Mono.Cecil { value_type = valueType; } + protected virtual void ClearFullName () + { + this.fullname = null; + } + public virtual TypeReference GetElementType () { return this; } - public virtual TypeDefinition Resolve () + protected override IMemberDefinition ResolveDefinition () + { + return this.Resolve (); + } + + public new virtual TypeDefinition Resolve () { var module = this.Module; if (module == null) @@ -300,6 +306,13 @@ namespace Mono.Cecil { } } + public static string TypeFullName (this TypeReference self) + { + return string.IsNullOrEmpty (self.Namespace) + ? self.Name + : self.Namespace + '.' + self.Name; + } + public static bool IsTypeOf (this TypeReference self, string @namespace, string name) { return self.Name == name diff --git a/external/cecil/Mono.Cecil/TypeSpecification.cs b/external/cecil/Mono.Cecil/TypeSpecification.cs index 75651be59c..d26be5b67a 100644 --- a/external/cecil/Mono.Cecil/TypeSpecification.cs +++ b/external/cecil/Mono.Cecil/TypeSpecification.cs @@ -1,29 +1,11 @@ // -// TypeSpecification.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; @@ -63,7 +45,7 @@ namespace Mono.Cecil { get { return element_type.FullName; } } - internal override bool ContainsGenericParameter { + public override bool ContainsGenericParameter { get { return element_type.ContainsGenericParameter; } } diff --git a/external/cecil/Mono.Cecil/TypeSystem.cs b/external/cecil/Mono.Cecil/TypeSystem.cs index 63f6aea287..ccaef1fbfe 100644 --- a/external/cecil/Mono.Cecil/TypeSystem.cs +++ b/external/cecil/Mono.Cecil/TypeSystem.cs @@ -1,29 +1,11 @@ // -// TypeSystem.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; @@ -96,7 +78,7 @@ namespace Mono.Cecil { sealed class CommonTypeSystem : TypeSystem { - AssemblyNameReference corlib; + AssemblyNameReference core_library; public CommonTypeSystem (ModuleDefinition module) : base (module) @@ -108,30 +90,43 @@ namespace Mono.Cecil { return CreateTypeReference (@namespace, name); } - public AssemblyNameReference GetCorlibReference () + public AssemblyNameReference GetCoreLibraryReference () { - if (corlib != null) - return corlib; + if (core_library != null) + return core_library; const string mscorlib = "mscorlib"; + const string system_runtime = "System.Runtime"; - var references = module.AssemblyReferences; + if (TryLookupReference (mscorlib, out core_library)) + return core_library; - for (int i = 0; i < references.Count; i++) { - var reference = references [i]; - if (reference.Name == mscorlib) - return corlib = reference; - } + if (TryLookupReference (system_runtime, out core_library)) + return core_library; - corlib = new AssemblyNameReference { + core_library = new AssemblyNameReference { Name = mscorlib, Version = GetCorlibVersion (), PublicKeyToken = new byte [] { 0xb7, 0x7a, 0x5c, 0x56, 0x19, 0x34, 0xe0, 0x89 }, }; - references.Add (corlib); + module.AssemblyReferences.Add (core_library); - return corlib; + return core_library; + } + + bool TryLookupReference (string name, out AssemblyNameReference reference) + { + var references = module.AssemblyReferences; + + for (int i = 0; i < references.Count; i++) { + reference = references [i]; + if (reference.Name == name) + return true; + } + + reference = null; + return false; } Version GetCorlibVersion () @@ -151,7 +146,7 @@ namespace Mono.Cecil { TypeReference CreateTypeReference (string @namespace, string name) { - return new TypeReference (@namespace, name, module, GetCorlibReference ()); + return new TypeReference (@namespace, name, module, GetCoreLibraryReference ()); } } @@ -183,7 +178,7 @@ namespace Mono.Cecil { internal static TypeSystem CreateTypeSystem (ModuleDefinition module) { - if (module.IsCorlib ()) + if (module.IsCoreLibrary ()) return new CoreTypeSystem (module); return new CommonTypeSystem (module); @@ -191,100 +186,114 @@ namespace Mono.Cecil { internal abstract TypeReference LookupType (string @namespace, string name); - TypeReference LookupSystemType (string name, ElementType element_type) + TypeReference LookupSystemType (ref TypeReference reference, string name, ElementType element_type) { - var type = LookupType ("System", name); - type.etype = element_type; - return type; + lock (module.SyncRoot) { + if (reference != null) + return reference; + var type = LookupType ("System", name); + type.etype = element_type; + return reference = type; + } } - TypeReference LookupSystemValueType (string name, ElementType element_type) + TypeReference LookupSystemValueType (ref TypeReference typeRef, string name, ElementType element_type) { - var type = LookupSystemType (name, element_type); - type.IsValueType = true; - return type; + lock (module.SyncRoot) { + if (typeRef != null) + return typeRef; + var type = LookupType ("System", name); + type.etype = element_type; + type.IsValueType = true; + return typeRef = type; + } } + [Obsolete ("Use CoreLibrary")] public IMetadataScope Corlib { + get { return CoreLibrary; } + } + + public IMetadataScope CoreLibrary { get { var common = this as CommonTypeSystem; if (common == null) return module; - return common.GetCorlibReference (); + return common.GetCoreLibraryReference (); } } public TypeReference Object { - get { return type_object ?? (type_object = LookupSystemType ("Object", ElementType.Object)); } + get { return type_object ?? (LookupSystemType (ref type_object, "Object", ElementType.Object)); } } public TypeReference Void { - get { return type_void ?? (type_void = LookupSystemType ("Void", ElementType.Void)); } + get { return type_void ?? (LookupSystemType (ref type_void, "Void", ElementType.Void)); } } public TypeReference Boolean { - get { return type_bool ?? (type_bool = LookupSystemValueType ("Boolean", ElementType.Boolean)); } + get { return type_bool ?? (LookupSystemValueType (ref type_bool, "Boolean", ElementType.Boolean)); } } public TypeReference Char { - get { return type_char ?? (type_char = LookupSystemValueType ("Char", ElementType.Char)); } + get { return type_char ?? (LookupSystemValueType (ref type_char, "Char", ElementType.Char)); } } public TypeReference SByte { - get { return type_sbyte ?? (type_sbyte = LookupSystemValueType ("SByte", ElementType.I1)); } + get { return type_sbyte ?? (LookupSystemValueType (ref type_sbyte, "SByte", ElementType.I1)); } } public TypeReference Byte { - get { return type_byte ?? (type_byte = LookupSystemValueType ("Byte", ElementType.U1)); } + get { return type_byte ?? (LookupSystemValueType (ref type_byte, "Byte", ElementType.U1)); } } public TypeReference Int16 { - get { return type_int16 ?? (type_int16 = LookupSystemValueType ("Int16", ElementType.I2)); } + get { return type_int16 ?? (LookupSystemValueType (ref type_int16, "Int16", ElementType.I2)); } } public TypeReference UInt16 { - get { return type_uint16 ?? (type_uint16 = LookupSystemValueType ("UInt16", ElementType.U2)); } + get { return type_uint16 ?? (LookupSystemValueType (ref type_uint16, "UInt16", ElementType.U2)); } } public TypeReference Int32 { - get { return type_int32 ?? (type_int32 = LookupSystemValueType ("Int32", ElementType.I4)); } + get { return type_int32 ?? (LookupSystemValueType (ref type_int32, "Int32", ElementType.I4)); } } public TypeReference UInt32 { - get { return type_uint32 ?? (type_uint32 = LookupSystemValueType ("UInt32", ElementType.U4)); } + get { return type_uint32 ?? (LookupSystemValueType (ref type_uint32, "UInt32", ElementType.U4)); } } public TypeReference Int64 { - get { return type_int64 ?? (type_int64 = LookupSystemValueType ("Int64", ElementType.I8)); } + get { return type_int64 ?? (LookupSystemValueType (ref type_int64, "Int64", ElementType.I8)); } } public TypeReference UInt64 { - get { return type_uint64 ?? (type_uint64 = LookupSystemValueType ("UInt64", ElementType.U8)); } + get { return type_uint64 ?? (LookupSystemValueType (ref type_uint64, "UInt64", ElementType.U8)); } } public TypeReference Single { - get { return type_single ?? (type_single = LookupSystemValueType ("Single", ElementType.R4)); } + get { return type_single ?? (LookupSystemValueType (ref type_single, "Single", ElementType.R4)); } } public TypeReference Double { - get { return type_double ?? (type_double = LookupSystemValueType ("Double", ElementType.R8)); } + get { return type_double ?? (LookupSystemValueType (ref type_double, "Double", ElementType.R8)); } } public TypeReference IntPtr { - get { return type_intptr ?? (type_intptr = LookupSystemValueType ("IntPtr", ElementType.I)); } + get { return type_intptr ?? (LookupSystemValueType (ref type_intptr, "IntPtr", ElementType.I)); } } public TypeReference UIntPtr { - get { return type_uintptr ?? (type_uintptr = LookupSystemValueType ("UIntPtr", ElementType.U)); } + get { return type_uintptr ?? (LookupSystemValueType (ref type_uintptr, "UIntPtr", ElementType.U)); } } public TypeReference String { - get { return type_string ?? (type_string = LookupSystemType ("String", ElementType.String)); } + get { return type_string ?? (LookupSystemType (ref type_string, "String", ElementType.String)); } } public TypeReference TypedReference { - get { return type_typedref ?? (type_typedref = LookupSystemValueType ("TypedReference", ElementType.TypedByRef)); } + get { return type_typedref ?? (LookupSystemValueType (ref type_typedref, "TypedReference", ElementType.TypedByRef)); } } } } diff --git a/external/cecil/Mono.Cecil/VariantType.cs b/external/cecil/Mono.Cecil/VariantType.cs index 76562f6e6f..81aa7fa4a3 100644 --- a/external/cecil/Mono.Cecil/VariantType.cs +++ b/external/cecil/Mono.Cecil/VariantType.cs @@ -1,29 +1,11 @@ // -// VariantType.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // namespace Mono.Cecil { diff --git a/external/cecil/Mono.Cecil/WindowsRuntimeProjections.cs b/external/cecil/Mono.Cecil/WindowsRuntimeProjections.cs new file mode 100644 index 0000000000..04ba8c609b --- /dev/null +++ b/external/cecil/Mono.Cecil/WindowsRuntimeProjections.cs @@ -0,0 +1,875 @@ +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. +// +// Licensed under the MIT/X11 license. +// + +using System; +using System.Collections.Generic; +using System.Threading; +using Mono.Collections.Generic; + +namespace Mono.Cecil { + + sealed class MemberReferenceProjection { + + public readonly string Name; + public readonly MemberReferenceTreatment Treatment; + + public MemberReferenceProjection (MemberReference member, MemberReferenceTreatment treatment) + { + Name = member.Name; + Treatment = treatment; + } + } + + sealed class TypeDefinitionProjection { + + public readonly TypeAttributes Attributes; + public readonly string Name; + public readonly TypeDefinitionTreatment Treatment; + + public TypeDefinitionProjection (TypeDefinition type, TypeDefinitionTreatment treatment) + { + Attributes = type.Attributes; + Name = type.Name; + Treatment = treatment; + } + } + + sealed class TypeReferenceProjection { + + public readonly string Name; + public readonly string Namespace; + public readonly IMetadataScope Scope; + public readonly TypeReferenceTreatment Treatment; + + public TypeReferenceProjection (TypeReference type, TypeReferenceTreatment treatment) + { + Name = type.Name; + Namespace = type.Namespace; + Scope = type.Scope; + Treatment = treatment; + } + } + + sealed class MethodDefinitionProjection { + + public readonly MethodAttributes Attributes; + public readonly MethodImplAttributes ImplAttributes; + public readonly string Name; + public readonly MethodDefinitionTreatment Treatment; + + public MethodDefinitionProjection (MethodDefinition method, MethodDefinitionTreatment treatment) + { + Attributes = method.Attributes; + ImplAttributes = method.ImplAttributes; + Name = method.Name; + Treatment = treatment; + } + } + + sealed class FieldDefinitionProjection { + + public readonly FieldAttributes Attributes; + public readonly FieldDefinitionTreatment Treatment; + + public FieldDefinitionProjection (FieldDefinition field, FieldDefinitionTreatment treatment) + { + Attributes = field.Attributes; + Treatment = treatment; + } + } + + sealed class CustomAttributeValueProjection { + + public readonly AttributeTargets Targets; + public readonly CustomAttributeValueTreatment Treatment; + + public CustomAttributeValueProjection (AttributeTargets targets, CustomAttributeValueTreatment treatment) + { + Targets = targets; + Treatment = treatment; + } + } + + sealed class WindowsRuntimeProjections { + + struct ProjectionInfo { + + public readonly string WinRTNamespace; + public readonly string ClrNamespace; + public readonly string ClrName; + public readonly string ClrAssembly; + public readonly bool Attribute; + public readonly bool Disposable; + + public ProjectionInfo (string winrt_namespace, string clr_namespace, string clr_name, string clr_assembly, bool attribute = false, bool disposable = false) + { + WinRTNamespace = winrt_namespace; + ClrNamespace = clr_namespace; + ClrName = clr_name; + ClrAssembly = clr_assembly; + Attribute = attribute; + Disposable = disposable; + } + } + + static readonly Version version = new Version (4, 0, 0, 0); + + static readonly byte[] contract_pk_token = { + 0xB0, 0x3F, 0x5F, 0x7F, 0x11, 0xD5, 0x0A, 0x3A + }; + + static readonly byte[] contract_pk = { + 0x00, 0x24, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x06, 0x02, 0x00, 0x00, + 0x00, 0x24, 0x00, 0x00, 0x52, 0x53, 0x41, 0x31, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x07, 0xD1, 0xFA, 0x57, 0xC4, 0xAE, 0xD9, 0xF0, 0xA3, 0x2E, 0x84, 0xAA, 0x0F, 0xAE, 0xFD, 0x0D, + 0xE9, 0xE8, 0xFD, 0x6A, 0xEC, 0x8F, 0x87, 0xFB, 0x03, 0x76, 0x6C, 0x83, 0x4C, 0x99, 0x92, 0x1E, + 0xB2, 0x3B, 0xE7, 0x9A, 0xD9, 0xD5, 0xDC, 0xC1, 0xDD, 0x9A, 0xD2, 0x36, 0x13, 0x21, 0x02, 0x90, + 0x0B, 0x72, 0x3C, 0xF9, 0x80, 0x95, 0x7F, 0xC4, 0xE1, 0x77, 0x10, 0x8F, 0xC6, 0x07, 0x77, 0x4F, + 0x29, 0xE8, 0x32, 0x0E, 0x92, 0xEA, 0x05, 0xEC, 0xE4, 0xE8, 0x21, 0xC0, 0xA5, 0xEF, 0xE8, 0xF1, + 0x64, 0x5C, 0x4C, 0x0C, 0x93, 0xC1, 0xAB, 0x99, 0x28, 0x5D, 0x62, 0x2C, 0xAA, 0x65, 0x2C, 0x1D, + 0xFA, 0xD6, 0x3D, 0x74, 0x5D, 0x6F, 0x2D, 0xE5, 0xF1, 0x7E, 0x5E, 0xAF, 0x0F, 0xC4, 0x96, 0x3D, + 0x26, 0x1C, 0x8A, 0x12, 0x43, 0x65, 0x18, 0x20, 0x6D, 0xC0, 0x93, 0x34, 0x4D, 0x5A, 0xD2, 0x93 + }; + + static Dictionary projections; + + static Dictionary Projections + { + get { + if (projections != null) + return projections; + + return projections = new Dictionary { + { "AttributeTargets", new ProjectionInfo ("Windows.Foundation.Metadata", "System", "AttributeTargets", "System.Runtime") }, + { "AttributeUsageAttribute", new ProjectionInfo ("Windows.Foundation.Metadata", "System", "AttributeUsageAttribute", "System.Runtime", attribute: true) }, + { "Color", new ProjectionInfo ("Windows.UI", "Windows.UI", "Color", "System.Runtime.WindowsRuntime") }, + { "CornerRadius", new ProjectionInfo ("Windows.UI.Xaml", "Windows.UI.Xaml", "CornerRadius", "System.Runtime.WindowsRuntime.UI.Xaml") }, + { "DateTime", new ProjectionInfo ("Windows.Foundation", "System", "DateTimeOffset", "System.Runtime") }, + { "Duration", new ProjectionInfo ("Windows.UI.Xaml", "Windows.UI.Xaml", "Duration", "System.Runtime.WindowsRuntime.UI.Xaml") }, + { "DurationType", new ProjectionInfo ("Windows.UI.Xaml", "Windows.UI.Xaml", "DurationType", "System.Runtime.WindowsRuntime.UI.Xaml") }, + { "EventHandler`1", new ProjectionInfo ("Windows.Foundation", "System", "EventHandler`1", "System.Runtime") }, + { "EventRegistrationToken", new ProjectionInfo ("Windows.Foundation", "System.Runtime.InteropServices.WindowsRuntime", "EventRegistrationToken", "System.Runtime.InteropServices.WindowsRuntime") }, + { "GeneratorPosition", new ProjectionInfo ("Windows.UI.Xaml.Controls.Primitives", "Windows.UI.Xaml.Controls.Primitives", "GeneratorPosition", "System.Runtime.WindowsRuntime.UI.Xaml") }, + { "GridLength", new ProjectionInfo ("Windows.UI.Xaml", "Windows.UI.Xaml", "GridLength", "System.Runtime.WindowsRuntime.UI.Xaml") }, + { "GridUnitType", new ProjectionInfo ("Windows.UI.Xaml", "Windows.UI.Xaml", "GridUnitType", "System.Runtime.WindowsRuntime.UI.Xaml") }, + { "HResult", new ProjectionInfo ("Windows.Foundation", "System", "Exception", "System.Runtime") }, + { "IBindableIterable", new ProjectionInfo ("Windows.UI.Xaml.Interop", "System.Collections", "IEnumerable", "System.Runtime") }, + { "IBindableVector", new ProjectionInfo ("Windows.UI.Xaml.Interop", "System.Collections", "IList", "System.Runtime") }, + { "IClosable", new ProjectionInfo ("Windows.Foundation", "System", "IDisposable", "System.Runtime", disposable: true) }, + { "ICommand", new ProjectionInfo ("Windows.UI.Xaml.Input", "System.Windows.Input", "ICommand", "System.ObjectModel") }, + { "IIterable`1", new ProjectionInfo ("Windows.Foundation.Collections", "System.Collections.Generic", "IEnumerable`1", "System.Runtime") }, + { "IKeyValuePair`2", new ProjectionInfo ("Windows.Foundation.Collections", "System.Collections.Generic", "KeyValuePair`2", "System.Runtime") }, + { "IMapView`2", new ProjectionInfo ("Windows.Foundation.Collections", "System.Collections.Generic", "IReadOnlyDictionary`2", "System.Runtime") }, + { "IMap`2", new ProjectionInfo ("Windows.Foundation.Collections", "System.Collections.Generic", "IDictionary`2", "System.Runtime") }, + { "INotifyCollectionChanged", new ProjectionInfo ("Windows.UI.Xaml.Interop", "System.Collections.Specialized", "INotifyCollectionChanged", "System.ObjectModel") }, + { "INotifyPropertyChanged", new ProjectionInfo ("Windows.UI.Xaml.Data", "System.ComponentModel", "INotifyPropertyChanged", "System.ObjectModel") }, + { "IReference`1", new ProjectionInfo ("Windows.Foundation", "System", "Nullable`1", "System.Runtime") }, + { "IVectorView`1", new ProjectionInfo ("Windows.Foundation.Collections", "System.Collections.Generic", "IReadOnlyList`1", "System.Runtime") }, + { "IVector`1", new ProjectionInfo ("Windows.Foundation.Collections", "System.Collections.Generic", "IList`1", "System.Runtime") }, + { "KeyTime", new ProjectionInfo ("Windows.UI.Xaml.Media.Animation", "Windows.UI.Xaml.Media.Animation", "KeyTime", "System.Runtime.WindowsRuntime.UI.Xaml") }, + { "Matrix", new ProjectionInfo ("Windows.UI.Xaml.Media", "Windows.UI.Xaml.Media", "Matrix", "System.Runtime.WindowsRuntime.UI.Xaml") }, + { "Matrix3D", new ProjectionInfo ("Windows.UI.Xaml.Media.Media3D", "Windows.UI.Xaml.Media.Media3D", "Matrix3D", "System.Runtime.WindowsRuntime.UI.Xaml") }, + { "Matrix3x2", new ProjectionInfo ("Windows.Foundation.Numerics", "System.Numerics", "Matrix3x2", "System.Numerics.Vectors") }, + { "Matrix4x4", new ProjectionInfo ("Windows.Foundation.Numerics", "System.Numerics", "Matrix4x4", "System.Numerics.Vectors") }, + { "NotifyCollectionChangedAction", new ProjectionInfo ("Windows.UI.Xaml.Interop", "System.Collections.Specialized", "NotifyCollectionChangedAction", "System.ObjectModel") }, + { "NotifyCollectionChangedEventArgs", new ProjectionInfo ("Windows.UI.Xaml.Interop", "System.Collections.Specialized", "NotifyCollectionChangedEventArgs", "System.ObjectModel") }, + { "NotifyCollectionChangedEventHandler", new ProjectionInfo ("Windows.UI.Xaml.Interop", "System.Collections.Specialized", "NotifyCollectionChangedEventHandler", "System.ObjectModel") }, + { "Plane", new ProjectionInfo ("Windows.Foundation.Numerics", "System.Numerics", "Plane", "System.Numerics.Vectors") }, + { "Point", new ProjectionInfo ("Windows.Foundation", "Windows.Foundation", "Point", "System.Runtime.WindowsRuntime") }, + { "PropertyChangedEventArgs", new ProjectionInfo ("Windows.UI.Xaml.Data", "System.ComponentModel", "PropertyChangedEventArgs", "System.ObjectModel") }, + { "PropertyChangedEventHandler", new ProjectionInfo ("Windows.UI.Xaml.Data", "System.ComponentModel", "PropertyChangedEventHandler", "System.ObjectModel") }, + { "Quaternion", new ProjectionInfo ("Windows.Foundation.Numerics", "System.Numerics", "Quaternion", "System.Numerics.Vectors") }, + { "Rect", new ProjectionInfo ("Windows.Foundation", "Windows.Foundation", "Rect", "System.Runtime.WindowsRuntime") }, + { "RepeatBehavior", new ProjectionInfo ("Windows.UI.Xaml.Media.Animation", "Windows.UI.Xaml.Media.Animation", "RepeatBehavior", "System.Runtime.WindowsRuntime.UI.Xaml") }, + { "RepeatBehaviorType", new ProjectionInfo ("Windows.UI.Xaml.Media.Animation", "Windows.UI.Xaml.Media.Animation", "RepeatBehaviorType", "System.Runtime.WindowsRuntime.UI.Xaml") }, + { "Size", new ProjectionInfo ("Windows.Foundation", "Windows.Foundation", "Size", "System.Runtime.WindowsRuntime") }, + { "Thickness", new ProjectionInfo ("Windows.UI.Xaml", "Windows.UI.Xaml", "Thickness", "System.Runtime.WindowsRuntime.UI.Xaml") }, + { "TimeSpan", new ProjectionInfo ("Windows.Foundation", "System", "TimeSpan", "System.Runtime") }, + { "TypeName", new ProjectionInfo ("Windows.UI.Xaml.Interop", "System", "Type", "System.Runtime") }, + { "Uri", new ProjectionInfo ("Windows.Foundation", "System", "Uri", "System.Runtime") }, + { "Vector2", new ProjectionInfo ("Windows.Foundation.Numerics", "System.Numerics", "Vector2", "System.Numerics.Vectors") }, + { "Vector3", new ProjectionInfo ("Windows.Foundation.Numerics", "System.Numerics", "Vector3", "System.Numerics.Vectors") }, + { "Vector4", new ProjectionInfo ("Windows.Foundation.Numerics", "System.Numerics", "Vector4", "System.Numerics.Vectors") }, + }; + } + } + + readonly ModuleDefinition module; + Version corlib_version = new Version (255, 255, 255, 255); + AssemblyNameReference[] virtual_references; + + AssemblyNameReference[] VirtualReferences { + get { + if (virtual_references == null) { + // force module to read its assembly references. that will in turn initialize virtual_references + Mixin.Read (module.AssemblyReferences); + } + + return virtual_references; + } + } + + public WindowsRuntimeProjections (ModuleDefinition module) + { + this.module = module; + } + + public static void Project (TypeDefinition type) + { + var treatment = TypeDefinitionTreatment.None; + var metadata_kind = type.Module.MetadataKind; + + if (type.IsWindowsRuntime) { + if (metadata_kind == MetadataKind.WindowsMetadata) { + treatment = GetWellKnownTypeDefinitionTreatment (type); + if (treatment != TypeDefinitionTreatment.None) { + ApplyProjection (type, new TypeDefinitionProjection (type, treatment)); + return; + } + + var base_type = type.BaseType; + if (base_type != null && IsAttribute (base_type)) + treatment = TypeDefinitionTreatment.NormalAttribute; + else + treatment = TypeDefinitionTreatment.NormalType; + } + else if (metadata_kind == MetadataKind.ManagedWindowsMetadata && NeedsWindowsRuntimePrefix (type)) + treatment = TypeDefinitionTreatment.PrefixWindowsRuntimeName; + + if (treatment == TypeDefinitionTreatment.PrefixWindowsRuntimeName || treatment == TypeDefinitionTreatment.NormalType) + if (!type.IsInterface && HasAttribute (type, "Windows.UI.Xaml", "TreatAsAbstractComposableClassAttribute")) + treatment |= TypeDefinitionTreatment.Abstract; + } + else if (metadata_kind == MetadataKind.ManagedWindowsMetadata && IsClrImplementationType (type)) + treatment = TypeDefinitionTreatment.UnmangleWindowsRuntimeName; + + if (treatment != TypeDefinitionTreatment.None) + ApplyProjection (type, new TypeDefinitionProjection (type, treatment)); + } + + static TypeDefinitionTreatment GetWellKnownTypeDefinitionTreatment (TypeDefinition type) + { + ProjectionInfo info; + if (!Projections.TryGetValue (type.Name, out info)) + return TypeDefinitionTreatment.None; + + var treatment = info.Attribute ? TypeDefinitionTreatment.RedirectToClrAttribute : TypeDefinitionTreatment.RedirectToClrType; + + if (type.Namespace == info.ClrNamespace) + return treatment; + + if (type.Namespace == info.WinRTNamespace) + return treatment | TypeDefinitionTreatment.Internal; + + return TypeDefinitionTreatment.None; + } + + static bool NeedsWindowsRuntimePrefix (TypeDefinition type) + { + if ((type.Attributes & (TypeAttributes.VisibilityMask | TypeAttributes.Interface)) != TypeAttributes.Public) + return false; + + var base_type = type.BaseType; + if (base_type == null || base_type.MetadataToken.TokenType != TokenType.TypeRef) + return false; + + if (base_type.Namespace == "System") + switch (base_type.Name) + { + case "Attribute": + case "MulticastDelegate": + case "ValueType": + return false; + } + + return true; + } + + static bool IsClrImplementationType (TypeDefinition type) + { + if ((type.Attributes & (TypeAttributes.VisibilityMask | TypeAttributes.SpecialName)) != TypeAttributes.SpecialName) + return false; + return type.Name.StartsWith (""); + } + + public static void ApplyProjection (TypeDefinition type, TypeDefinitionProjection projection) + { + if (projection == null) + return; + + var treatment = projection.Treatment; + + switch (treatment & TypeDefinitionTreatment.KindMask) { + case TypeDefinitionTreatment.NormalType: + type.Attributes |= TypeAttributes.WindowsRuntime | TypeAttributes.Import; + break; + + case TypeDefinitionTreatment.NormalAttribute: + type.Attributes |= TypeAttributes.WindowsRuntime | TypeAttributes.Sealed; + break; + + case TypeDefinitionTreatment.UnmangleWindowsRuntimeName: + type.Attributes = type.Attributes & ~TypeAttributes.SpecialName | TypeAttributes.Public; + type.Name = type.Name.Substring ("".Length); + break; + + case TypeDefinitionTreatment.PrefixWindowsRuntimeName: + type.Attributes = type.Attributes & ~TypeAttributes.Public | TypeAttributes.Import; + type.Name = "" + type.Name; + break; + + case TypeDefinitionTreatment.RedirectToClrType: + type.Attributes = type.Attributes & ~TypeAttributes.Public | TypeAttributes.Import; + break; + + case TypeDefinitionTreatment.RedirectToClrAttribute: + type.Attributes = type.Attributes & ~TypeAttributes.Public; + break; + } + + if ((treatment & TypeDefinitionTreatment.Abstract) != 0) + type.Attributes |= TypeAttributes.Abstract; + + if ((treatment & TypeDefinitionTreatment.Internal) != 0) + type.Attributes &= ~TypeAttributes.Public; + + type.WindowsRuntimeProjection = projection; + } + + public static TypeDefinitionProjection RemoveProjection (TypeDefinition type) + { + if (!type.IsWindowsRuntimeProjection) + return null; + + var projection = type.WindowsRuntimeProjection; + type.WindowsRuntimeProjection = null; + + type.Attributes = projection.Attributes; + type.Name = projection.Name; + + return projection; + } + + public static void Project (TypeReference type) + { + TypeReferenceTreatment treatment; + + ProjectionInfo info; + if (Projections.TryGetValue (type.Name, out info) && info.WinRTNamespace == type.Namespace) + treatment = TypeReferenceTreatment.UseProjectionInfo; + else + treatment = GetSpecialTypeReferenceTreatment (type); + + if (treatment != TypeReferenceTreatment.None) + ApplyProjection (type, new TypeReferenceProjection (type, treatment)); + } + + static TypeReferenceTreatment GetSpecialTypeReferenceTreatment (TypeReference type) + { + if (type.Namespace == "System") { + if (type.Name == "MulticastDelegate") + return TypeReferenceTreatment.SystemDelegate; + if (type.Name == "Attribute") + return TypeReferenceTreatment.SystemAttribute; + } + + return TypeReferenceTreatment.None; + } + + static bool IsAttribute (TypeReference type) + { + if (type.MetadataToken.TokenType != TokenType.TypeRef) + return false; + return type.Name == "Attribute" && type.Namespace == "System"; + } + + static bool IsEnum (TypeReference type) + { + if (type.MetadataToken.TokenType != TokenType.TypeRef) + return false; + return type.Name == "Enum" && type.Namespace == "System"; + } + + public static void ApplyProjection (TypeReference type, TypeReferenceProjection projection) + { + if (projection == null) + return; + + switch (projection.Treatment) + { + case TypeReferenceTreatment.SystemDelegate: + case TypeReferenceTreatment.SystemAttribute: + type.Scope = type.Module.Projections.GetAssemblyReference ("System.Runtime"); + break; + + case TypeReferenceTreatment.UseProjectionInfo: + var info = Projections [type.Name]; + type.Name = info.ClrName; + type.Namespace = info.ClrNamespace; + type.Scope = type.Module.Projections.GetAssemblyReference (info.ClrAssembly); + break; + } + + type.WindowsRuntimeProjection = projection; + } + + public static TypeReferenceProjection RemoveProjection (TypeReference type) + { + if (!type.IsWindowsRuntimeProjection) + return null; + + var projection = type.WindowsRuntimeProjection; + type.WindowsRuntimeProjection = null; + + type.Name = projection.Name; + type.Namespace = projection.Namespace; + type.Scope = projection.Scope; + + return projection; + } + + public static void Project (MethodDefinition method) + { + var treatment = MethodDefinitionTreatment.None; + var other = false; + var declaring_type = method.DeclaringType; + + if (declaring_type.IsWindowsRuntime) + { + if (IsClrImplementationType (declaring_type)) + treatment = MethodDefinitionTreatment.None; + else if (declaring_type.IsNested) + treatment = MethodDefinitionTreatment.None; + else if (declaring_type.IsInterface) + treatment = MethodDefinitionTreatment.Runtime | MethodDefinitionTreatment.InternalCall; + else if (declaring_type.Module.MetadataKind == MetadataKind.ManagedWindowsMetadata && !method.IsPublic) + treatment = MethodDefinitionTreatment.None; + else + { + other = true; + + var base_type = declaring_type.BaseType; + if (base_type != null && base_type.MetadataToken.TokenType == TokenType.TypeRef) + { + switch (GetSpecialTypeReferenceTreatment(base_type)) + { + case TypeReferenceTreatment.SystemDelegate: + treatment = MethodDefinitionTreatment.Runtime | MethodDefinitionTreatment.Public; + other = false; + break; + + case TypeReferenceTreatment.SystemAttribute: + treatment = MethodDefinitionTreatment.Runtime | MethodDefinitionTreatment.InternalCall; + other = false; + break; + } + } + } + } + + if (other) + { + var seen_redirected = false; + var seen_non_redirected = false; + var disposable = false; + + foreach (var @override in method.Overrides) + { + if (@override.MetadataToken.TokenType == TokenType.MemberRef && ImplementsRedirectedInterface (@override, out disposable)) + { + seen_redirected = true; + if (disposable) + break; + } + else + seen_non_redirected = true; + } + + if (disposable) + { + treatment = MethodDefinitionTreatment.Dispose; + other = false; + } + else if (seen_redirected && !seen_non_redirected) + { + treatment = MethodDefinitionTreatment.Runtime | MethodDefinitionTreatment.InternalCall | MethodDefinitionTreatment.Private; + other = false; + } + } + + if (other) + treatment |= GetMethodDefinitionTreatmentFromCustomAttributes(method); + + if (treatment != MethodDefinitionTreatment.None) + ApplyProjection (method, new MethodDefinitionProjection (method, treatment)); + } + + static MethodDefinitionTreatment GetMethodDefinitionTreatmentFromCustomAttributes(MethodDefinition method) + { + var treatment = MethodDefinitionTreatment.None; + + foreach (var attribute in method.CustomAttributes) + { + var type = attribute.AttributeType; + if (type.Namespace != "Windows.UI.Xaml") + continue; + if (type.Name == "TreatAsPublicMethodAttribute") + treatment |= MethodDefinitionTreatment.Public; + else if (type.Name == "TreatAsAbstractMethodAttribute") + treatment |= MethodDefinitionTreatment.Abstract; + } + + return treatment; + } + + public static void ApplyProjection (MethodDefinition method, MethodDefinitionProjection projection) + { + if (projection == null) + return; + + var treatment = projection.Treatment; + + if ((treatment & MethodDefinitionTreatment.Dispose) != 0) + method.Name = "Dispose"; + + if ((treatment & MethodDefinitionTreatment.Abstract) != 0) + method.Attributes |= MethodAttributes.Abstract; + + if ((treatment & MethodDefinitionTreatment.Private) != 0) + method.Attributes = (method.Attributes & ~MethodAttributes.MemberAccessMask) | MethodAttributes.Private; + + if ((treatment & MethodDefinitionTreatment.Public) != 0) + method.Attributes = (method.Attributes & ~MethodAttributes.MemberAccessMask) | MethodAttributes.Public; + + if ((treatment & MethodDefinitionTreatment.Runtime) != 0) + method.ImplAttributes |= MethodImplAttributes.Runtime; + + if ((treatment & MethodDefinitionTreatment.InternalCall) != 0) + method.ImplAttributes |= MethodImplAttributes.InternalCall; + + method.WindowsRuntimeProjection = projection; + } + + public static MethodDefinitionProjection RemoveProjection (MethodDefinition method) + { + if (!method.IsWindowsRuntimeProjection) + return null; + + var projection = method.WindowsRuntimeProjection; + method.WindowsRuntimeProjection = null; + + method.Attributes = projection.Attributes; + method.ImplAttributes = projection.ImplAttributes; + method.Name = projection.Name; + + return projection; + } + + public static void Project (FieldDefinition field) + { + var treatment = FieldDefinitionTreatment.None; + var declaring_type = field.DeclaringType; + + if (declaring_type.Module.MetadataKind == MetadataKind.WindowsMetadata && field.IsRuntimeSpecialName && field.Name == "value__") { + var base_type = declaring_type.BaseType; + if (base_type != null && IsEnum (base_type)) + treatment = FieldDefinitionTreatment.Public; + } + + if (treatment != FieldDefinitionTreatment.None) + ApplyProjection (field, new FieldDefinitionProjection (field, treatment)); + } + + public static void ApplyProjection (FieldDefinition field, FieldDefinitionProjection projection) + { + if (projection == null) + return; + + if (projection.Treatment == FieldDefinitionTreatment.Public) + field.Attributes = (field.Attributes & ~FieldAttributes.FieldAccessMask) | FieldAttributes.Public; + + field.WindowsRuntimeProjection = projection; + } + + public static FieldDefinitionProjection RemoveProjection (FieldDefinition field) + { + if (!field.IsWindowsRuntimeProjection) + return null; + + var projection = field.WindowsRuntimeProjection; + field.WindowsRuntimeProjection = null; + + field.Attributes = projection.Attributes; + + return projection; + } + + public static void Project (MemberReference member) + { + bool disposable; + if (!ImplementsRedirectedInterface (member, out disposable) || !disposable) + return; + + ApplyProjection (member, new MemberReferenceProjection (member, MemberReferenceTreatment.Dispose)); + } + + static bool ImplementsRedirectedInterface (MemberReference member, out bool disposable) + { + disposable = false; + + var declaring_type = member.DeclaringType; + TypeReference type; + switch (declaring_type.MetadataToken.TokenType) { + case TokenType.TypeRef: + type = declaring_type; + break; + + case TokenType.TypeSpec: + if (!declaring_type.IsGenericInstance) + return false; + + type = ((TypeSpecification) declaring_type).ElementType; + if (type.MetadataType != MetadataType.Class || type.MetadataToken.TokenType != TokenType.TypeRef) + return false; + + break; + + default: + return false; + } + + var projection = RemoveProjection (type); + + var found = false; + + ProjectionInfo info; + if (Projections.TryGetValue (type.Name, out info) && type.Namespace == info.WinRTNamespace) { + disposable = info.Disposable; + found = true; + } + + ApplyProjection (type, projection); + + return found; + } + + public static void ApplyProjection (MemberReference member, MemberReferenceProjection projection) + { + if (projection == null) + return; + + if (projection.Treatment == MemberReferenceTreatment.Dispose) + member.Name = "Dispose"; + + member.WindowsRuntimeProjection = projection; + } + + public static MemberReferenceProjection RemoveProjection (MemberReference member) + { + if (!member.IsWindowsRuntimeProjection) + return null; + + var projection = member.WindowsRuntimeProjection; + member.WindowsRuntimeProjection = null; + + member.Name = projection.Name; + + return projection; + } + + public void AddVirtualReferences (Collection references) + { + var corlib = GetCoreLibrary (references); + corlib_version = corlib.Version; + corlib.Version = version; + + if (virtual_references == null) { + var winrt_references = GetAssemblyReferences (corlib); + Interlocked.CompareExchange (ref virtual_references, winrt_references, null); + } + + foreach (var reference in virtual_references) + references.Add (reference); + } + + public void RemoveVirtualReferences (Collection references) + { + var corlib = GetCoreLibrary (references); + corlib.Version = corlib_version; + + foreach (var reference in VirtualReferences) + references.Remove (reference); + } + + static AssemblyNameReference[] GetAssemblyReferences (AssemblyNameReference corlib) + { + var system_runtime = new AssemblyNameReference ("System.Runtime", version); + var system_runtime_interopservices_windowsruntime = new AssemblyNameReference ("System.Runtime.InteropServices.WindowsRuntime", version); + var system_objectmodel = new AssemblyNameReference ("System.ObjectModel", version); + var system_runtime_windowsruntime = new AssemblyNameReference ("System.Runtime.WindowsRuntime", version); + var system_runtime_windowsruntime_ui_xaml = new AssemblyNameReference ("System.Runtime.WindowsRuntime.UI.Xaml", version); + var system_numerics_vectors = new AssemblyNameReference ("System.Numerics.Vectors", version); + + if (corlib.HasPublicKey) { + system_runtime_windowsruntime.PublicKey = + system_runtime_windowsruntime_ui_xaml.PublicKey = corlib.PublicKey; + + system_runtime.PublicKey = + system_runtime_interopservices_windowsruntime.PublicKey = + system_objectmodel.PublicKey = + system_numerics_vectors.PublicKey = contract_pk; + } + else { + system_runtime_windowsruntime.PublicKeyToken = + system_runtime_windowsruntime_ui_xaml.PublicKeyToken = corlib.PublicKeyToken; + + system_runtime.PublicKeyToken = + system_runtime_interopservices_windowsruntime.PublicKeyToken = + system_objectmodel.PublicKeyToken = + system_numerics_vectors.PublicKeyToken = contract_pk_token; + } + + return new[] { + system_runtime, + system_runtime_interopservices_windowsruntime, + system_objectmodel, + system_runtime_windowsruntime, + system_runtime_windowsruntime_ui_xaml, + system_numerics_vectors, + }; + } + + static AssemblyNameReference GetCoreLibrary (Collection references) + { + foreach (var reference in references) + if (reference.Name == "mscorlib") + return reference; + + throw new BadImageFormatException ("Missing mscorlib reference in AssemblyRef table."); + } + + AssemblyNameReference GetAssemblyReference (string name) + { + foreach (var assembly in VirtualReferences) + if (assembly.Name == name) + return assembly; + + throw new Exception (); + } + + public static void Project (ICustomAttributeProvider owner, CustomAttribute attribute) + { + if (!IsWindowsAttributeUsageAttribute (owner, attribute)) + return; + + var treatment = CustomAttributeValueTreatment.None; + var type = (TypeDefinition) owner; + + if (type.Namespace == "Windows.Foundation.Metadata") { + if (type.Name == "VersionAttribute") + treatment = CustomAttributeValueTreatment.VersionAttribute; + else if (type.Name == "DeprecatedAttribute") + treatment = CustomAttributeValueTreatment.DeprecatedAttribute; + } + + if (treatment == CustomAttributeValueTreatment.None) { + var multiple = HasAttribute (type, "Windows.Foundation.Metadata", "AllowMultipleAttribute"); + treatment = multiple ? CustomAttributeValueTreatment.AllowMultiple : CustomAttributeValueTreatment.AllowSingle; + } + + if (treatment != CustomAttributeValueTreatment.None) { + var attribute_targets = (AttributeTargets) attribute.ConstructorArguments [0].Value; + ApplyProjection (attribute, new CustomAttributeValueProjection (attribute_targets, treatment)); + } + } + + static bool IsWindowsAttributeUsageAttribute (ICustomAttributeProvider owner, CustomAttribute attribute) + { + if (owner.MetadataToken.TokenType != TokenType.TypeDef) + return false; + + var constructor = attribute.Constructor; + + if (constructor.MetadataToken.TokenType != TokenType.MemberRef) + return false; + + var declaring_type = constructor.DeclaringType; + + if (declaring_type.MetadataToken.TokenType != TokenType.TypeRef) + return false; + + // declaring type is already projected + return declaring_type.Name == "AttributeUsageAttribute" && declaring_type.Namespace == /*"Windows.Foundation.Metadata"*/"System"; + } + + static bool HasAttribute (TypeDefinition type, string @namespace, string name) + { + foreach (var attribute in type.CustomAttributes) { + var attribute_type = attribute.AttributeType; + if (attribute_type.Name == name && attribute_type.Namespace == @namespace) + return true; + } + return false; + } + + public static void ApplyProjection (CustomAttribute attribute, CustomAttributeValueProjection projection) + { + if (projection == null) + return; + + bool version_or_deprecated; + bool multiple; + + switch (projection.Treatment) { + case CustomAttributeValueTreatment.AllowSingle: + version_or_deprecated = false; + multiple = false; + break; + + case CustomAttributeValueTreatment.AllowMultiple: + version_or_deprecated = false; + multiple = true; + break; + + case CustomAttributeValueTreatment.VersionAttribute: + case CustomAttributeValueTreatment.DeprecatedAttribute: + version_or_deprecated = true; + multiple = true; + break; + + default: + throw new ArgumentException (); + } + + var attribute_targets = (AttributeTargets) attribute.ConstructorArguments [0].Value; + if (version_or_deprecated) + attribute_targets |= AttributeTargets.Constructor | AttributeTargets.Property; + attribute.ConstructorArguments [0] = new CustomAttributeArgument (attribute.ConstructorArguments [0].Type, attribute_targets); + + attribute.Properties.Add (new CustomAttributeNamedArgument ("AllowMultiple", new CustomAttributeArgument (attribute.Module.TypeSystem.Boolean, multiple))); + + attribute.projection = projection; + } + + public static CustomAttributeValueProjection RemoveProjection (CustomAttribute attribute) + { + if (attribute.projection == null) + return null; + + var projection = attribute.projection; + attribute.projection = null; + + attribute.ConstructorArguments [0] = new CustomAttributeArgument (attribute.ConstructorArguments [0].Type, projection.Targets); + attribute.Properties.Clear (); + + return projection; + } + } +} diff --git a/external/cecil/Mono.Collections.Generic/Collection.cs b/external/cecil/Mono.Collections.Generic/Collection.cs index 4d92717608..015d271b47 100644 --- a/external/cecil/Mono.Collections.Generic/Collection.cs +++ b/external/cecil/Mono.Collections.Generic/Collection.cs @@ -1,35 +1,19 @@ // -// Collection.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; using System.Collections; using System.Collections.Generic; +using Mono.Cecil; + namespace Mono.Collections.Generic { public class Collection : IList, IList { @@ -60,6 +44,16 @@ namespace Mono.Collections.Generic { } } + public int Capacity { + get { return items.Length; } + set { + if (value < 0 || value < size) + throw new ArgumentOutOfRangeException (); + + Resize (value); + } + } + bool ICollection.IsReadOnly { get { return false; } } @@ -167,7 +161,6 @@ namespace Mono.Collections.Generic { OnRemove (item, index); Shift (index, -1); - Array.Clear (items, size, 1); version++; } @@ -180,7 +173,6 @@ namespace Mono.Collections.Generic { OnRemove (item, index); Shift (index, -1); - Array.Clear (items, size, 1); version++; return true; @@ -259,13 +251,17 @@ namespace Mono.Collections.Generic { System.Math.Max (items.Length * 2, default_capacity), new_size); -#if !CF - Array.Resize (ref items, new_size); -#else - var array = new T [new_size]; - Array.Copy (items, array, size); - items = array; -#endif + Resize (new_size); + } + + protected void Resize (int new_size) + { + if (new_size == size) + return; + if (new_size < size) + throw new ArgumentOutOfRangeException (); + + items = items.Resize (new_size); } int IList.Add (object value) diff --git a/external/cecil/Mono.Collections.Generic/ReadOnlyCollection.cs b/external/cecil/Mono.Collections.Generic/ReadOnlyCollection.cs index 7f24df699e..fe784149fd 100644 --- a/external/cecil/Mono.Collections.Generic/ReadOnlyCollection.cs +++ b/external/cecil/Mono.Collections.Generic/ReadOnlyCollection.cs @@ -1,34 +1,16 @@ // -// ReadOnlyCollection.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; using System.Collections; -using System .Collections.Generic; +using System.Collections.Generic; namespace Mono.Collections.Generic { @@ -52,7 +34,7 @@ namespace Mono.Collections.Generic { get { return true; } } - private ReadOnlyCollection () + ReadOnlyCollection () { } diff --git a/external/cecil/Mono.Security.Cryptography/CryptoConvert.cs b/external/cecil/Mono.Security.Cryptography/CryptoConvert.cs index 26a4ba25b6..86a374c73d 100644 --- a/external/cecil/Mono.Security.Cryptography/CryptoConvert.cs +++ b/external/cecil/Mono.Security.Cryptography/CryptoConvert.cs @@ -27,11 +27,13 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // +#if !READ_ONLY + +#if !PCL && !NET_CORE + using System; using System.Security.Cryptography; -#if !(SILVERLIGHT || READ_ONLY) - namespace Mono.Security.Cryptography { static class CryptoConvert { @@ -139,10 +141,11 @@ namespace Mono.Security.Cryptography { rsa = RSA.Create (); rsa.ImportParameters (rsap); } - catch (CryptographicException ce) { + catch (CryptographicException) { // this may cause problem when this code is run under // the SYSTEM identity on Windows (e.g. ASP.NET). See // http://bugzilla.ximian.com/show_bug.cgi?id=77559 + bool throws = false; try { CspParameters csp = new CspParameters (); csp.Flags = CspProviderFlags.UseMachineKeyStore; @@ -150,8 +153,12 @@ namespace Mono.Security.Cryptography { rsa.ImportParameters (rsap); } catch { - // rethrow original, not the later, exception if this fails - throw ce; + throws = true; + } + + if (throws) { + // rethrow original, not the latter, exception if this fails + throw; } } return rsa; @@ -241,3 +248,6 @@ namespace Mono.Security.Cryptography { } #endif + +#endif + diff --git a/external/cecil/Mono.Security.Cryptography/CryptoService.cs b/external/cecil/Mono.Security.Cryptography/CryptoService.cs index 58b6cfabc6..9b0173a1d1 100644 --- a/external/cecil/Mono.Security.Cryptography/CryptoService.cs +++ b/external/cecil/Mono.Security.Cryptography/CryptoService.cs @@ -1,42 +1,24 @@ // -// CryptoService.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // +#if !READ_ONLY + +#if !PCL && !NET_CORE + using System; using System.IO; using System.Reflection; using System.Security.Cryptography; - -#if !READ_ONLY - -#if !SILVERLIGHT && !CF using System.Runtime.Serialization; + using Mono.Security.Cryptography; -#endif using Mono.Cecil.PE; @@ -48,7 +30,6 @@ namespace Mono.Cecil { static class CryptoService { -#if !SILVERLIGHT && !CF public static void StrongName (Stream stream, ImageWriter writer, StrongNameKeyPair key_pair) { int strong_name_pointer; @@ -110,7 +91,7 @@ namespace Mono.Cecil { return sha1.Hash; } -#endif + static void CopyStreamChunk (Stream stream, Stream dest_stream, byte [] buffer, int length) { while (length > 0) { @@ -141,7 +122,6 @@ namespace Mono.Cecil { } } -#if !SILVERLIGHT && !CF static partial class Mixin { public static RSA CreateRSA (this StrongNameKeyPair key_pair) @@ -171,7 +151,8 @@ namespace Mono.Cecil { return key_container != null; } } -#endif } #endif + +#endif diff --git a/external/cecil/Mono/Disposable.cs b/external/cecil/Mono/Disposable.cs new file mode 100644 index 0000000000..dc2b1a3d10 --- /dev/null +++ b/external/cecil/Mono/Disposable.cs @@ -0,0 +1,45 @@ +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. +// +// Licensed under the MIT/X11 license. +// + +using System; + +namespace Mono { + + static class Disposable { + + public static Disposable Owned (T value) where T : class, IDisposable + { + return new Disposable (value, owned: true); + } + + public static Disposable NotOwned (T value) where T : class, IDisposable + { + return new Disposable (value, owned: false); + } + } + + struct Disposable : IDisposable where T : class, IDisposable { + + internal readonly T value; + readonly bool owned; + + public Disposable (T value, bool owned) + { + this.value = value; + this.owned = owned; + } + + public void Dispose () + { + if (value != null && owned) + value.Dispose (); + } + } +} diff --git a/external/cecil/Mono/Empty.cs b/external/cecil/Mono/Empty.cs index c9e5d7d614..14589cc9e1 100644 --- a/external/cecil/Mono/Empty.cs +++ b/external/cecil/Mono/Empty.cs @@ -1,29 +1,11 @@ // -// Empty.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; @@ -53,14 +35,19 @@ namespace Mono.Cecil { public static T [] Resize (this T [] self, int length) { -#if !CF Array.Resize (ref self, length); -#else - var copy = new T [length]; - Array.Copy (self, copy, self.Length); - self = copy; -#endif + return self; + } + public static T [] Add (this T [] self, T item) + { + if (self == null) { + self = new [] { item }; + return self; + } + + self = self.Resize (self.Length + 1); + self [self.Length - 1] = item; return self; } } diff --git a/external/cecil/Mono/Type.cs b/external/cecil/Mono/Type.cs new file mode 100644 index 0000000000..d04a615ccd --- /dev/null +++ b/external/cecil/Mono/Type.cs @@ -0,0 +1,91 @@ +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. +// +// Licensed under the MIT/X11 license. +// + +using System; +using System.Reflection; + +#if NET_CORE +using System.Collections.Generic; +#endif + +namespace Mono { + +#if NET_CORE + enum TypeCode { + Empty = 0, + Object = 1, + DBNull = 2, + Boolean = 3, + Char = 4, + SByte = 5, + Byte = 6, + Int16 = 7, + UInt16 = 8, + Int32 = 9, + UInt32 = 10, + Int64 = 11, + UInt64 = 12, + Single = 13, + Double = 14, + Decimal = 15, + DateTime = 16, + String = 18 + } +#endif + + static class TypeExtensions { + +#if NET_CORE + private static readonly Dictionary TypeCodeMap = new Dictionary + { + { typeof (bool), TypeCode.Boolean }, + { typeof (char), TypeCode.Char }, + { typeof (sbyte), TypeCode.SByte }, + { typeof (byte), TypeCode.Byte }, + { typeof (short), TypeCode.Int16 }, + { typeof (ushort), TypeCode.UInt16 }, + { typeof (int), TypeCode.Int32 }, + { typeof (uint), TypeCode.UInt32 }, + { typeof (long), TypeCode.Int64 }, + { typeof (ulong), TypeCode.UInt64 }, + { typeof (float), TypeCode.Single }, + { typeof (double), TypeCode.Double }, + { typeof (decimal), TypeCode.Decimal }, + { typeof (DateTime), TypeCode.DateTime }, + { typeof (string), TypeCode.String }, + }; +#endif + + public static TypeCode GetTypeCode (this Type type) + { +#if NET_CORE + if (type == null) + return TypeCode.Empty; + + TypeCode code; + if (!TypeCodeMap.TryGetValue (type, out code)) + return TypeCode.Object; + + return code; +#else + return Type.GetTypeCode (type); +#endif + } + + public static Assembly GetAssembly (this Type type) + { +#if NET_CORE + return type.GetTypeInfo ().Assembly; +#else + return type.Assembly; +#endif + } + } +} diff --git a/external/cecil/ProjectInfo.cs b/external/cecil/ProjectInfo.cs new file mode 100644 index 0000000000..dd369766e7 --- /dev/null +++ b/external/cecil/ProjectInfo.cs @@ -0,0 +1,22 @@ +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2015 Jb Evain +// +// Licensed under the MIT/X11 license. +// + +using System.Reflection; +using System.Runtime.InteropServices; + +[assembly: AssemblyProduct ("Mono.Cecil")] +[assembly: AssemblyCopyright ("Copyright © 2008 - 2015 Jb Evain")] + +#if !PCL +[assembly: ComVisible (false)] +#endif + +[assembly: AssemblyVersion ("0.10.0.0")] +[assembly: AssemblyFileVersion ("0.10.0.0")] +[assembly: AssemblyInformationalVersion ("0.10.0.0-beta1")] diff --git a/external/cecil/README.md b/external/cecil/README.md new file mode 100644 index 0000000000..3ae656f4d2 --- /dev/null +++ b/external/cecil/README.md @@ -0,0 +1,23 @@ +Cecil +===== + +Mono.Cecil is a library to generate and inspect programs and libraries in the ECMA CIL form. + +To put it simply, you can use Cecil to: + +* Analyze .NET binaries using a simple and powerful object model, without having to load assemblies to use Reflection. +* Modify .NET binaries, add new metadata structures and alter the IL code. + +Cecil has been around since 2004 and is [widely used](https://github.com/jbevain/cecil/wiki/Users) in the .NET community. + +The best way to learn how to use Cecil is to dive into the [Cecil.Samples](https://github.com/jbevain/cecil.samples) repository. It's a growing collection of samples with the goal of showing how to get things done using Cecil, as IL manipulation can sometime get tricky. + +Read about the Cecil development on the [development log](http://cecil.pe). + +To discuss Cecil, the best place is the [mono-cecil](https://groups.google.com/group/mono-cecil) Google Group. + +Cecil is a project under the benevolent umbrella of the [.NET Foundation](http://www.dotnetfoundation.org/). + +[![.NET build status](https://ci.appveyor.com/api/projects/status/fmhutmhidy1fahl4?svg=true)](https://ci.appveyor.com/project/jbevain/cecil) +[![Mono build status](https://travis-ci.org/jbevain/cecil.svg?branch=master)](https://travis-ci.org/jbevain/cecil) +[![Join the chat at https://gitter.im/jbevain/cecil](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/jbevain/cecil?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) diff --git a/external/cecil/System.Security.Cryptography/SHA1Managed.cs b/external/cecil/System.Security.Cryptography/SHA1Managed.cs new file mode 100644 index 0000000000..a162278e90 --- /dev/null +++ b/external/cecil/System.Security.Cryptography/SHA1Managed.cs @@ -0,0 +1,373 @@ +// +// System.Security.Cryptography.SHA1CryptoServiceProvider.cs +// +// Authors: +// Matthew S. Ford (Matthew.S.Ford@Rose-Hulman.Edu) +// Sebastien Pouliot (sebastien@ximian.com) +// +// Copyright 2001 by Matthew S. Ford. +// Copyright (C) 2004, 2005, 2008 Novell, Inc (http://www.novell.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +// Note: +// The MS Framework includes two (almost) identical class for SHA1. +// SHA1Managed is a 100% managed implementation. +// SHA1CryptoServiceProvider (this file) is a wrapper on CryptoAPI. +// Mono must provide those two class for binary compatibility. +// In our case both class are wrappers around a managed internal class SHA1Internal. + +#if PCL + +namespace System.Security.Cryptography { + + internal class SHA1Internal { + + private const int BLOCK_SIZE_BYTES = 64; + private uint[] _H; // these are my chaining variables + private ulong count; + private byte[] _ProcessingBuffer; // Used to start data when passed less than a block worth. + private int _ProcessingBufferCount; // Counts how much data we have stored that still needs processed. + private uint[] buff; + + public SHA1Internal () + { + _H = new uint[5]; + _ProcessingBuffer = new byte[BLOCK_SIZE_BYTES]; + buff = new uint[80]; + + Initialize(); + } + + public void HashCore (byte[] rgb, int ibStart, int cbSize) + { + int i; + + if (_ProcessingBufferCount != 0) { + if (cbSize < (BLOCK_SIZE_BYTES - _ProcessingBufferCount)) { + System.Buffer.BlockCopy (rgb, ibStart, _ProcessingBuffer, _ProcessingBufferCount, cbSize); + _ProcessingBufferCount += cbSize; + return; + } + else { + i = (BLOCK_SIZE_BYTES - _ProcessingBufferCount); + System.Buffer.BlockCopy (rgb, ibStart, _ProcessingBuffer, _ProcessingBufferCount, i); + ProcessBlock (_ProcessingBuffer, 0); + _ProcessingBufferCount = 0; + ibStart += i; + cbSize -= i; + } + } + + for (i = 0; i < cbSize - cbSize % BLOCK_SIZE_BYTES; i += BLOCK_SIZE_BYTES) { + ProcessBlock (rgb, (uint)(ibStart + i)); + } + + if (cbSize % BLOCK_SIZE_BYTES != 0) { + System.Buffer.BlockCopy (rgb, cbSize - cbSize % BLOCK_SIZE_BYTES + ibStart, _ProcessingBuffer, 0, cbSize % BLOCK_SIZE_BYTES); + _ProcessingBufferCount = cbSize % BLOCK_SIZE_BYTES; + } + } + + public byte[] HashFinal () + { + byte[] hash = new byte[20]; + + ProcessFinalBlock (_ProcessingBuffer, 0, _ProcessingBufferCount); + + for (int i=0; i<5; i++) { + for (int j=0; j<4; j++) { + hash [i*4+j] = (byte)(_H[i] >> (8*(3-j))); + } + } + + return hash; + } + + public void Initialize () + { + count = 0; + _ProcessingBufferCount = 0; + + _H[0] = 0x67452301; + _H[1] = 0xefcdab89; + _H[2] = 0x98badcfe; + _H[3] = 0x10325476; + _H[4] = 0xC3D2E1F0; + } + + private void ProcessBlock(byte[] inputBuffer, uint inputOffset) + { + uint a, b, c, d, e; + + count += BLOCK_SIZE_BYTES; + + // abc removal would not work on the fields + uint[] _H = this._H; + uint[] buff = this.buff; + InitialiseBuff(buff, inputBuffer, inputOffset); + FillBuff(buff); + + a = _H[0]; + b = _H[1]; + c = _H[2]; + d = _H[3]; + e = _H[4]; + + // This function was unrolled because it seems to be doubling our performance with current compiler/VM. + // Possibly roll up if this changes. + + // ---- Round 1 -------- + int i=0; + while (i < 20) + { + e += ((a << 5) | (a >> 27)) + (((c ^ d) & b) ^ d) + 0x5A827999 + buff[i]; + b = (b << 30) | (b >> 2); + + d += ((e << 5) | (e >> 27)) + (((b ^ c) & a) ^ c) + 0x5A827999 + buff[i+1]; + a = (a << 30) | (a >> 2); + + c += ((d << 5) | (d >> 27)) + (((a ^ b) & e) ^ b) + 0x5A827999 + buff[i+2]; + e = (e << 30) | (e >> 2); + + b += ((c << 5) | (c >> 27)) + (((e ^ a) & d) ^ a) + 0x5A827999 + buff[i+3]; + d = (d << 30) | (d >> 2); + + a += ((b << 5) | (b >> 27)) + (((d ^ e) & c) ^ e) + 0x5A827999 + buff[i+4]; + c = (c << 30) | (c >> 2); + i += 5; + } + + // ---- Round 2 -------- + while (i < 40) + { + e += ((a << 5) | (a >> 27)) + (b ^ c ^ d) + 0x6ED9EBA1 + buff[i]; + b = (b << 30) | (b >> 2); + + d += ((e << 5) | (e >> 27)) + (a ^ b ^ c) + 0x6ED9EBA1 + buff[i + 1]; + a = (a << 30) | (a >> 2); + + c += ((d << 5) | (d >> 27)) + (e ^ a ^ b) + 0x6ED9EBA1 + buff[i + 2]; + e = (e << 30) | (e >> 2); + + b += ((c << 5) | (c >> 27)) + (d ^ e ^ a) + 0x6ED9EBA1 + buff[i + 3]; + d = (d << 30) | (d >> 2); + + a += ((b << 5) | (b >> 27)) + (c ^ d ^ e) + 0x6ED9EBA1 + buff[i + 4]; + c = (c << 30) | (c >> 2); + i += 5; + } + + // ---- Round 3 -------- + while (i < 60) + { + e += ((a << 5) | (a >> 27)) + ((b & c) | (b & d) | (c & d)) + 0x8F1BBCDC + buff[i]; + b = (b << 30) | (b >> 2); + + d += ((e << 5) | (e >> 27)) + ((a & b) | (a & c) | (b & c)) + 0x8F1BBCDC + buff[i + 1]; + a = (a << 30) | (a >> 2); + + c += ((d << 5) | (d >> 27)) + ((e & a) | (e & b) | (a & b)) + 0x8F1BBCDC + buff[i + 2]; + e = (e << 30) | (e >> 2); + + b += ((c << 5) | (c >> 27)) + ((d & e) | (d & a) | (e & a)) + 0x8F1BBCDC + buff[i + 3]; + d = (d << 30) | (d >> 2); + + a += ((b << 5) | (b >> 27)) + ((c & d) | (c & e) | (d & e)) + 0x8F1BBCDC + buff[i + 4]; + c = (c << 30) | (c >> 2); + i += 5; + } + + // ---- Round 4 -------- + while (i < 80) + { + e += ((a << 5) | (a >> 27)) + (b ^ c ^ d) + 0xCA62C1D6 + buff[i]; + b = (b << 30) | (b >> 2); + + d += ((e << 5) | (e >> 27)) + (a ^ b ^ c) + 0xCA62C1D6 + buff[i + 1]; + a = (a << 30) | (a >> 2); + + c += ((d << 5) | (d >> 27)) + (e ^ a ^ b) + 0xCA62C1D6 + buff[i + 2]; + e = (e << 30) | (e >> 2); + + b += ((c << 5) | (c >> 27)) + (d ^ e ^ a) + 0xCA62C1D6 + buff[i + 3]; + d = (d << 30) | (d >> 2); + + a += ((b << 5) | (b >> 27)) + (c ^ d ^ e) + 0xCA62C1D6 + buff[i + 4]; + c = (c << 30) | (c >> 2); + i += 5; + } + + _H[0] += a; + _H[1] += b; + _H[2] += c; + _H[3] += d; + _H[4] += e; + } + + private static void InitialiseBuff(uint[] buff, byte[] input, uint inputOffset) + { + buff[0] = (uint)((input[inputOffset + 0] << 24) | (input[inputOffset + 1] << 16) | (input[inputOffset + 2] << 8) | (input[inputOffset + 3])); + buff[1] = (uint)((input[inputOffset + 4] << 24) | (input[inputOffset + 5] << 16) | (input[inputOffset + 6] << 8) | (input[inputOffset + 7])); + buff[2] = (uint)((input[inputOffset + 8] << 24) | (input[inputOffset + 9] << 16) | (input[inputOffset + 10] << 8) | (input[inputOffset + 11])); + buff[3] = (uint)((input[inputOffset + 12] << 24) | (input[inputOffset + 13] << 16) | (input[inputOffset + 14] << 8) | (input[inputOffset + 15])); + buff[4] = (uint)((input[inputOffset + 16] << 24) | (input[inputOffset + 17] << 16) | (input[inputOffset + 18] << 8) | (input[inputOffset + 19])); + buff[5] = (uint)((input[inputOffset + 20] << 24) | (input[inputOffset + 21] << 16) | (input[inputOffset + 22] << 8) | (input[inputOffset + 23])); + buff[6] = (uint)((input[inputOffset + 24] << 24) | (input[inputOffset + 25] << 16) | (input[inputOffset + 26] << 8) | (input[inputOffset + 27])); + buff[7] = (uint)((input[inputOffset + 28] << 24) | (input[inputOffset + 29] << 16) | (input[inputOffset + 30] << 8) | (input[inputOffset + 31])); + buff[8] = (uint)((input[inputOffset + 32] << 24) | (input[inputOffset + 33] << 16) | (input[inputOffset + 34] << 8) | (input[inputOffset + 35])); + buff[9] = (uint)((input[inputOffset + 36] << 24) | (input[inputOffset + 37] << 16) | (input[inputOffset + 38] << 8) | (input[inputOffset + 39])); + buff[10] = (uint)((input[inputOffset + 40] << 24) | (input[inputOffset + 41] << 16) | (input[inputOffset + 42] << 8) | (input[inputOffset + 43])); + buff[11] = (uint)((input[inputOffset + 44] << 24) | (input[inputOffset + 45] << 16) | (input[inputOffset + 46] << 8) | (input[inputOffset + 47])); + buff[12] = (uint)((input[inputOffset + 48] << 24) | (input[inputOffset + 49] << 16) | (input[inputOffset + 50] << 8) | (input[inputOffset + 51])); + buff[13] = (uint)((input[inputOffset + 52] << 24) | (input[inputOffset + 53] << 16) | (input[inputOffset + 54] << 8) | (input[inputOffset + 55])); + buff[14] = (uint)((input[inputOffset + 56] << 24) | (input[inputOffset + 57] << 16) | (input[inputOffset + 58] << 8) | (input[inputOffset + 59])); + buff[15] = (uint)((input[inputOffset + 60] << 24) | (input[inputOffset + 61] << 16) | (input[inputOffset + 62] << 8) | (input[inputOffset + 63])); + } + + private static void FillBuff(uint[] buff) + { + uint val; + for (int i = 16; i < 80; i += 8) + { + val = buff[i - 3] ^ buff[i - 8] ^ buff[i - 14] ^ buff[i - 16]; + buff[i] = (val << 1) | (val >> 31); + + val = buff[i - 2] ^ buff[i - 7] ^ buff[i - 13] ^ buff[i - 15]; + buff[i + 1] = (val << 1) | (val >> 31); + + val = buff[i - 1] ^ buff[i - 6] ^ buff[i - 12] ^ buff[i - 14]; + buff[i + 2] = (val << 1) | (val >> 31); + + val = buff[i + 0] ^ buff[i - 5] ^ buff[i - 11] ^ buff[i - 13]; + buff[i + 3] = (val << 1) | (val >> 31); + + val = buff[i + 1] ^ buff[i - 4] ^ buff[i - 10] ^ buff[i - 12]; + buff[i + 4] = (val << 1) | (val >> 31); + + val = buff[i + 2] ^ buff[i - 3] ^ buff[i - 9] ^ buff[i - 11]; + buff[i + 5] = (val << 1) | (val >> 31); + + val = buff[i + 3] ^ buff[i - 2] ^ buff[i - 8] ^ buff[i - 10]; + buff[i + 6] = (val << 1) | (val >> 31); + + val = buff[i + 4] ^ buff[i - 1] ^ buff[i - 7] ^ buff[i - 9]; + buff[i + 7] = (val << 1) | (val >> 31); + } + } + + private void ProcessFinalBlock (byte[] inputBuffer, int inputOffset, int inputCount) + { + ulong total = count + (ulong)inputCount; + int paddingSize = (56 - (int)(total % BLOCK_SIZE_BYTES)); + + if (paddingSize < 1) + paddingSize += BLOCK_SIZE_BYTES; + + int length = inputCount+paddingSize+8; + byte[] fooBuffer = (length == 64) ? _ProcessingBuffer : new byte[length]; + + for (int i=0; i> 56); + buffer [position++] = (byte)(length >> 48); + buffer [position++] = (byte)(length >> 40); + buffer [position++] = (byte)(length >> 32); + buffer [position++] = (byte)(length >> 24); + buffer [position++] = (byte)(length >> 16); + buffer [position++] = (byte)(length >> 8); + buffer [position] = (byte)(length); + } + } + + class SHA1Managed { + + private SHA1Internal sha; + + public SHA1Managed () + { + sha = new SHA1Internal (); + } + + public byte[] ComputeHash (byte[] buffer) + { + if (buffer == null) + throw new ArgumentNullException ("buffer"); + + return ComputeHash (buffer, 0, buffer.Length); + } + + public byte[] ComputeHash (byte[] buffer, int offset, int count) + { + if (buffer == null) + throw new ArgumentNullException ("buffer"); + if (offset < 0) + throw new ArgumentOutOfRangeException ("offset", "< 0"); + if (count < 0) + throw new ArgumentException ("count", "< 0"); + // ordered to avoid possible integer overflow + if (offset > buffer.Length - count) { + throw new ArgumentException ("offset + count", "Overflow"); + } + + HashCore (buffer, offset, count); + var hash_value = HashFinal (); + Initialize (); + + return hash_value; + } + + protected void HashCore (byte[] rgb, int ibStart, int cbSize) + { + sha.HashCore (rgb, ibStart, cbSize); + } + + protected byte[] HashFinal () + { + return sha.HashFinal (); + } + + protected void Initialize () + { + sha.Initialize (); + } + } +} + +#endif diff --git a/external/cecil/Test/Mono.Cecil.Tests.csproj b/external/cecil/Test/Mono.Cecil.Tests.csproj index eeebf78ce5..993a1c66c7 100644 --- a/external/cecil/Test/Mono.Cecil.Tests.csproj +++ b/external/cecil/Test/Mono.Cecil.Tests.csproj @@ -1,138 +1,10 @@ - + - net_4_0_Debug - AnyCPU - 9.0.30729 - 2.0 {A47B1F49-A81A-43E8-BE6B-DD28AF2C4055} - Library - Properties Mono.Cecil.Tests Mono.Cecil.Tests - 512 - true - ..\mono.snk - - true - full - false - bin\net_2_0_Debug\ - DEBUG;TRACE - prompt - 4 - v2.0 - - - pdbonly - true - bin\net_2_0_Release\ - TRACE - prompt - 4 - v2.0 - - - true - full - false - bin\net_3_5_Debug\ - DEBUG;TRACE;NET_3_5 - prompt - 4 - v3.5 - - - pdbonly - true - bin\net_3_5_Release\ - TRACE;NET_3_5 - prompt - 4 - v3.5 - - - true - full - false - bin\net_4_0_Debug\ - DEBUG;TRACE;NET_3_5;NET_4_0 - prompt - 4 - v4.0 - - - pdbonly - true - bin\net_4_0_Release\ - TRACE;NET_3_5;NET_4_0 - prompt - 4 - v4.0 - - - - - - - False - libs\nunit-2.6.2\nunit.core.dll - - - False - libs\nunit-2.6.2\nunit.core.interfaces.dll - - - False - libs\nunit-2.6.2\nunit.framework.dll - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {D68133BD-1E63-496E-9EDE-4FBDBF77B486} @@ -140,40 +12,12 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + - \ No newline at end of file diff --git a/external/cecil/Test/Mono.Cecil.Tests/AssemblyInfo.cs b/external/cecil/Test/Mono.Cecil.Tests/AssemblyInfo.cs index ad7488f773..f4a938ac48 100644 --- a/external/cecil/Test/Mono.Cecil.Tests/AssemblyInfo.cs +++ b/external/cecil/Test/Mono.Cecil.Tests/AssemblyInfo.cs @@ -1,14 +1,6 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; [assembly: AssemblyTitle ("Mono.Cecil.Tests")] -[assembly: AssemblyProduct ("Mono.Cecil")] -[assembly: AssemblyCopyright ("Copyright © 2008 - 2011 Jb Evain")] - -[assembly: ComVisible (false)] [assembly: Guid ("da96c202-696a-457e-89af-5fa74e6bda0d")] - -[assembly: AssemblyVersion ("1.0.0.0")] -[assembly: AssemblyFileVersion ("1.0.0.0")] diff --git a/external/cecil/Test/Mono.Cecil.Tests/AssemblyTests.cs b/external/cecil/Test/Mono.Cecil.Tests/AssemblyTests.cs index 3267f77a6a..0d484de538 100644 --- a/external/cecil/Test/Mono.Cecil.Tests/AssemblyTests.cs +++ b/external/cecil/Test/Mono.Cecil.Tests/AssemblyTests.cs @@ -9,21 +9,23 @@ namespace Mono.Cecil.Tests { [TestFixture] public class AssemblyTests : BaseTestFixture { - [TestModule ("hello.exe")] - public void Name (ModuleDefinition module) + [Test] + public void Name () { - var name = module.Assembly.Name; + TestModule ("hello.exe", module => { + var name = module.Assembly.Name; - Assert.IsNotNull (name); + Assert.IsNotNull (name); - Assert.AreEqual ("hello", name.Name); - Assert.AreEqual (string.Empty, name.Culture); - Assert.AreEqual (new Version (0, 0, 0, 0), name.Version); - Assert.AreEqual (AssemblyHashAlgorithm.SHA1, name.HashAlgorithm); + Assert.AreEqual ("hello", name.Name); + Assert.AreEqual ("", name.Culture); + Assert.AreEqual (new Version (0, 0, 0, 0), name.Version); + Assert.AreEqual (AssemblyHashAlgorithm.SHA1, name.HashAlgorithm); + }); } [Test] - public void ParseLowerCaseNameParts() + public void ParseLowerCaseNameParts () { var name = AssemblyNameReference.Parse ("Foo, version=2.0.0.0, culture=fr-FR"); Assert.AreEqual ("Foo", name.Name); @@ -31,5 +33,55 @@ namespace Mono.Cecil.Tests { Assert.AreEqual (0, name.Version.Minor); Assert.AreEqual ("fr-FR", name.Culture); } + + [Test] + public void ZeroVersion () + { + var name = new AssemblyNameReference ("Foo", null); + Assert.AreEqual ("0.0.0.0", name.Version.ToString (fieldCount: 4)); + Assert.AreEqual ("Foo, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", name.FullName); + + name = new AssemblyNameReference ("Foo", new Version (0, 0, 0, 0)); + Assert.AreEqual ("0.0.0.0", name.Version.ToString (fieldCount: 4)); + Assert.AreEqual ("Foo, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", name.FullName); + } + + [Test] + public void NoBuildOrMajor () + { + var name = new AssemblyNameReference ("Foo", new Version (0, 0)); + Assert.AreEqual ("Foo, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", name.FullName); + + name = new AssemblyNameReference ("Foo", new Version (0, 0, 0)); + Assert.AreEqual ("Foo, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", name.FullName); + } + + [Test] + public void Retargetable () + { + TestModule ("RetargetableExample.dll", module => { + var type = module.Types [1]; + var property = type.Properties [0]; + var attribute = property.CustomAttributes [0]; + + var argumentType = ((CustomAttributeArgument) attribute.ConstructorArguments [0].Value).Type; + var reference = (AssemblyNameReference) argumentType.Scope; + + Assert.AreEqual ( + "System.Data, Version=3.5.0.0, Culture=neutral, PublicKeyToken=969db8053d3322ac, Retargetable=Yes", + reference.FullName); + }, verify: !Platform.OnMono); + } + + [Test] + public void SystemRuntime () + { + TestModule ("System.Runtime.dll", module => { + Assert.AreEqual ("System.Runtime", module.Assembly.Name.Name); + Assert.AreEqual (1, module.AssemblyReferences.Count); + Assert.AreNotEqual (module, module.TypeSystem.CoreLibrary); + Assert.AreEqual (module.AssemblyReferences [0], module.TypeSystem.CoreLibrary); + }, verify: !Platform.OnMono); + } } } diff --git a/external/cecil/Test/Mono.Cecil.Tests/BaseTestFixture.cs b/external/cecil/Test/Mono.Cecil.Tests/BaseTestFixture.cs index e160f48afc..0112725f1a 100644 --- a/external/cecil/Test/Mono.Cecil.Tests/BaseTestFixture.cs +++ b/external/cecil/Test/Mono.Cecil.Tests/BaseTestFixture.cs @@ -1,7 +1,7 @@ using System; using System.IO; using System.Reflection; - +using Mono.Cecil.Cil; using NUnit.Framework; using Mono.Cecil.PE; @@ -10,6 +10,12 @@ namespace Mono.Cecil.Tests { public abstract class BaseTestFixture { + protected static void IgnoreOnMono () + { + if (Platform.OnMono) + Assert.Ignore (); + } + public static string GetResourcePath (string name, Assembly assembly) { return Path.Combine (FindResourcesDirectory (assembly), name); @@ -30,35 +36,35 @@ namespace Mono.Cecil.Tests { return GetResourcePath (Path.Combine ("il", name), assembly); } - public static ModuleDefinition GetResourceModule (string name) + public ModuleDefinition GetResourceModule (string name) { - return ModuleDefinition.ReadModule (GetAssemblyResourcePath (name, typeof (BaseTestFixture).Assembly)); + return ModuleDefinition.ReadModule (GetAssemblyResourcePath (name, GetType ().Assembly)); } - public static ModuleDefinition GetResourceModule (string name, ReaderParameters parameters) + public ModuleDefinition GetResourceModule (string name, ReaderParameters parameters) { - return ModuleDefinition.ReadModule (GetAssemblyResourcePath (name, typeof (BaseTestFixture).Assembly), parameters); + return ModuleDefinition.ReadModule (GetAssemblyResourcePath (name, GetType ().Assembly), parameters); } - public static ModuleDefinition GetResourceModule (string name, ReadingMode mode) + public ModuleDefinition GetResourceModule (string name, ReadingMode mode) { - return ModuleDefinition.ReadModule (GetAssemblyResourcePath (name, typeof (BaseTestFixture).Assembly), new ReaderParameters (mode)); + return ModuleDefinition.ReadModule (GetAssemblyResourcePath (name, GetType ().Assembly), new ReaderParameters (mode)); } - internal static Image GetResourceImage (string name) + internal Image GetResourceImage (string name) { - using (var fs = new FileStream (GetAssemblyResourcePath (name, typeof (BaseTestFixture).Assembly), FileMode.Open, FileAccess.Read)) - return ImageReader.ReadImageFrom (fs); + var file = new FileStream (GetAssemblyResourcePath (name, GetType ().Assembly), FileMode.Open, FileAccess.Read); + return ImageReader.ReadImage (Disposable.Owned (file as Stream), file.Name); } - public static ModuleDefinition GetCurrentModule () + public ModuleDefinition GetCurrentModule () { - return ModuleDefinition.ReadModule (typeof (BaseTestFixture).Module.FullyQualifiedName); + return ModuleDefinition.ReadModule (GetType ().Module.FullyQualifiedName); } - public static ModuleDefinition GetCurrentModule (ReaderParameters parameters) + public ModuleDefinition GetCurrentModule (ReaderParameters parameters) { - return ModuleDefinition.ReadModule (typeof (BaseTestFixture).Module.FullyQualifiedName, parameters); + return ModuleDefinition.ReadModule (GetType ().Module.FullyQualifiedName, parameters); } public static string FindResourcesDirectory (Assembly assembly) @@ -72,5 +78,250 @@ namespace Mono.Cecil.Tests { return Path.Combine (path, "Resources"); } + + public static void AssertCode (string expected, MethodDefinition method) + { + Assert.IsTrue (method.HasBody); + Assert.IsNotNull (method.Body); + + Assert.AreEqual (Normalize (expected), Normalize (Formatter.FormatMethodBody (method))); + } + + static string Normalize (string str) + { + return str.Trim ().Replace ("\r\n", "\n"); + } + + public static void TestModule (string file, Action test, bool verify = true, bool readOnly = false, Type symbolReaderProvider = null, Type symbolWriterProvider = null, IAssemblyResolver assemblyResolver = null, bool applyWindowsRuntimeProjections = false) + { + Run (new ModuleTestCase (file, test, verify, readOnly, symbolReaderProvider, symbolWriterProvider, assemblyResolver, applyWindowsRuntimeProjections)); + } + + public static void TestCSharp (string file, Action test, bool verify = true, bool readOnly = false, Type symbolReaderProvider = null, Type symbolWriterProvider = null, IAssemblyResolver assemblyResolver = null, bool applyWindowsRuntimeProjections = false) + { + Run (new CSharpTestCase (file, test, verify, readOnly, symbolReaderProvider, symbolWriterProvider, assemblyResolver, applyWindowsRuntimeProjections)); + } + + public static void TestIL (string file, Action test, bool verify = true, bool readOnly = false, Type symbolReaderProvider = null, Type symbolWriterProvider = null, IAssemblyResolver assemblyResolver = null, bool applyWindowsRuntimeProjections = false) + { + Run (new ILTestCase (file, test, verify, readOnly, symbolReaderProvider, symbolWriterProvider, assemblyResolver, applyWindowsRuntimeProjections)); + } + + static void Run (TestCase testCase) + { + using (var runner = new TestRunner (testCase, TestCaseType.ReadDeferred)) + runner.RunTest (); + + using (var runner = new TestRunner (testCase, TestCaseType.ReadImmediate)) + runner.RunTest (); + + if (testCase.ReadOnly) + return; + + using (var runner = new TestRunner (testCase, TestCaseType.WriteFromDeferred)) + runner.RunTest (); + + using (var runner = new TestRunner (testCase, TestCaseType.WriteFromImmediate)) + runner.RunTest (); + } + } + + abstract class TestCase { + + public readonly bool Verify; + public readonly bool ReadOnly; + public readonly Type SymbolReaderProvider; + public readonly Type SymbolWriterProvider; + public readonly IAssemblyResolver AssemblyResolver; + public readonly Action Test; + public readonly bool ApplyWindowsRuntimeProjections; + + public abstract string ModuleLocation { get; } + + protected Assembly Assembly { get { return Test.Method.Module.Assembly; } } + + protected TestCase (Action test, bool verify, bool readOnly, Type symbolReaderProvider, Type symbolWriterProvider, IAssemblyResolver assemblyResolver, bool applyWindowsRuntimeProjections) + { + Test = test; + Verify = verify; + ReadOnly = readOnly; + SymbolReaderProvider = symbolReaderProvider; + SymbolWriterProvider = symbolWriterProvider; + AssemblyResolver = assemblyResolver; + ApplyWindowsRuntimeProjections = applyWindowsRuntimeProjections; + } + } + + class ModuleTestCase : TestCase { + + public readonly string Module; + + public ModuleTestCase (string module, Action test, bool verify, bool readOnly, Type symbolReaderProvider, Type symbolWriterProvider, IAssemblyResolver assemblyResolver, bool applyWindowsRuntimeProjections) + : base (test, verify, readOnly, symbolReaderProvider, symbolWriterProvider, assemblyResolver, applyWindowsRuntimeProjections) + { + Module = module; + } + + public override string ModuleLocation + { + get { return BaseTestFixture.GetAssemblyResourcePath (Module, Assembly); } + } + } + + class CSharpTestCase : TestCase { + + public readonly string File; + + public CSharpTestCase (string file, Action test, bool verify, bool readOnly, Type symbolReaderProvider, Type symbolWriterProvider, IAssemblyResolver assemblyResolver, bool applyWindowsRuntimeProjections) + : base (test, verify, readOnly, symbolReaderProvider, symbolWriterProvider, assemblyResolver, applyWindowsRuntimeProjections) + { + File = file; + } + + public override string ModuleLocation + { + get + { + return CompilationService.CompileResource (BaseTestFixture.GetCSharpResourcePath (File, Assembly)); + } + } + } + + class ILTestCase : TestCase { + + public readonly string File; + + public ILTestCase (string file, Action test, bool verify, bool readOnly, Type symbolReaderProvider, Type symbolWriterProvider, IAssemblyResolver assemblyResolver, bool applyWindowsRuntimeProjections) + : base (test, verify, readOnly, symbolReaderProvider, symbolWriterProvider, assemblyResolver, applyWindowsRuntimeProjections) + { + File = file; + } + + public override string ModuleLocation + { + get + { + return CompilationService.CompileResource (BaseTestFixture.GetILResourcePath (File, Assembly)); ; + } + } + } + + class TestRunner : IDisposable { + + readonly TestCase test_case; + readonly TestCaseType type; + + ModuleDefinition test_module; + DefaultAssemblyResolver test_resolver; + + public TestRunner (TestCase testCase, TestCaseType type) + { + this.test_case = testCase; + this.type = type; + } + + ModuleDefinition GetModule () + { + var location = test_case.ModuleLocation; + + var parameters = new ReaderParameters { + SymbolReaderProvider = GetSymbolReaderProvider (), + AssemblyResolver = GetAssemblyResolver (), + ApplyWindowsRuntimeProjections = test_case.ApplyWindowsRuntimeProjections + }; + + switch (type) { + case TestCaseType.ReadImmediate: + parameters.ReadingMode = ReadingMode.Immediate; + return ModuleDefinition.ReadModule (location, parameters); + case TestCaseType.ReadDeferred: + parameters.ReadingMode = ReadingMode.Deferred; + return ModuleDefinition.ReadModule (location, parameters); + case TestCaseType.WriteFromImmediate: + parameters.ReadingMode = ReadingMode.Immediate; + return RoundTrip (location, parameters, "cecil-irt"); + case TestCaseType.WriteFromDeferred: + parameters.ReadingMode = ReadingMode.Deferred; + return RoundTrip (location, parameters, "cecil-drt"); + default: + return null; + } + } + + ISymbolReaderProvider GetSymbolReaderProvider () + { + if (test_case.SymbolReaderProvider == null) + return null; + + return (ISymbolReaderProvider) Activator.CreateInstance (test_case.SymbolReaderProvider); + } + + ISymbolWriterProvider GetSymbolWriterProvider () + { + if (test_case.SymbolReaderProvider == null) + return null; + + return (ISymbolWriterProvider) Activator.CreateInstance (test_case.SymbolWriterProvider); + } + + IAssemblyResolver GetAssemblyResolver () + { + if (test_case.AssemblyResolver != null) + return test_case.AssemblyResolver; + + test_resolver = new DefaultAssemblyResolver (); + var directory = Path.GetDirectoryName (test_case.ModuleLocation); + test_resolver.AddSearchDirectory (directory); + return test_resolver; + } + + ModuleDefinition RoundTrip (string location, ReaderParameters reader_parameters, string folder) + { + var rt_folder = Path.Combine (Path.GetTempPath (), folder); + if (!Directory.Exists (rt_folder)) + Directory.CreateDirectory (rt_folder); + var rt_module = Path.Combine (rt_folder, Path.GetFileName (location)); + + using (var module = ModuleDefinition.ReadModule (location, reader_parameters)) { + var writer_parameters = new WriterParameters { + SymbolWriterProvider = GetSymbolWriterProvider (), + }; + + test_case.Test (module); + + module.Write (rt_module, writer_parameters); + } + + if (test_case.Verify) + CompilationService.Verify (rt_module); + + return ModuleDefinition.ReadModule (rt_module, reader_parameters); + } + + public void RunTest () + { + var module = GetModule (); + if (module == null) + return; + + test_module = module; + test_case.Test (module); + } + + public void Dispose () + { + if (test_module != null) + test_module.Dispose (); + + if (test_resolver != null) + test_resolver.Dispose (); + } + } + + enum TestCaseType { + ReadImmediate, + ReadDeferred, + WriteFromImmediate, + WriteFromDeferred, } } diff --git a/external/cecil/Test/Mono.Cecil.Tests/CompilationService.cs b/external/cecil/Test/Mono.Cecil.Tests/CompilationService.cs index 5a2def5cd1..54fef5f1ec 100644 --- a/external/cecil/Test/Mono.Cecil.Tests/CompilationService.cs +++ b/external/cecil/Test/Mono.Cecil.Tests/CompilationService.cs @@ -20,6 +20,11 @@ namespace Mono.Cecil.Tests { } } + public static class Platform { + + public static bool OnMono { get { return typeof (object).Assembly.GetType ("Mono.Runtime") != null; } } + } + abstract class CompilationService { Dictionary files = new Dictionary (); @@ -77,11 +82,9 @@ namespace Mono.Cecil.Tests { return Path.Combine (tmp_cecil, Path.GetFileName (file_name) + ".dll"); } - static bool OnMono { get { return typeof (object).Assembly.GetType ("Mono.Runtime") != null; } } - public static void Verify (string name) { - var output = OnMono ? ShellService.PEDump (name) : ShellService.PEVerify (name); + var output = Platform.OnMono ? ShellService.PEDump (name) : ShellService.PEVerify (name); if (output.ExitCode != 0) Assert.Fail (output.ToString ()); } @@ -216,7 +219,11 @@ namespace Mono.Cecil.Tests { public static ProcessOutput ILAsm (string source, string output) { - return RunProcess ("ilasm", "/nologo", "/dll", "/out:" + Quote (output), Quote (source)); + var ilasm = "ilasm"; + if (!Platform.OnMono) + ilasm = NetFrameworkTool ("ilasm"); + + return RunProcess (ilasm, "/nologo", "/dll", "/out:" + Quote (output), Quote (source)); } static string Quote (string file) @@ -226,12 +233,43 @@ namespace Mono.Cecil.Tests { public static ProcessOutput PEVerify (string source) { - return RunProcess ("peverify", "/nologo", Quote (source)); + return RunProcess (WinSdkTool ("peverify"), "/nologo", Quote (source)); } public static ProcessOutput PEDump (string source) { return RunProcess ("pedump", "--verify code,metadata", Quote (source)); } + + static string NetFrameworkTool (string tool) + { + return Path.Combine ( + Path.GetDirectoryName (typeof (object).Assembly.Location), + tool + ".exe"); + } + + static string WinSdkTool (string tool) + { + var sdks = new [] { + @"Microsoft SDKs\Windows\v8.1A\bin\NETFX 4.5.1 Tools", + @"Microsoft SDKs\Windows\v8.0A\bin\NETFX 4.0 Tools", + @"Microsoft SDKs\Windows\v7.0A\Bin", + }; + + foreach (var sdk in sdks) { + var pgf = IntPtr.Size == 8 + ? Environment.GetEnvironmentVariable("ProgramFiles(x86)") + : Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles); + + var exe = Path.Combine ( + Path.Combine (pgf, sdk), + tool + ".exe"); + + if (File.Exists(exe)) + return exe; + } + + return tool; + } } } diff --git a/external/cecil/Test/Mono.Cecil.Tests/CustomAttributesTests.cs b/external/cecil/Test/Mono.Cecil.Tests/CustomAttributesTests.cs index 9682dadbfe..29922ad134 100644 --- a/external/cecil/Test/Mono.Cecil.Tests/CustomAttributesTests.cs +++ b/external/cecil/Test/Mono.Cecil.Tests/CustomAttributesTests.cs @@ -15,339 +15,438 @@ namespace Mono.Cecil.Tests { [TestFixture] public class CustomAttributesTests : BaseTestFixture { - [TestCSharp ("CustomAttributes.cs")] - public void StringArgumentOnType (ModuleDefinition module) + [Test] + public void StringArgumentOnType () { - var hamster = module.GetType ("Hamster"); + TestCSharp ("CustomAttributes.cs", module => { + var hamster = module.GetType ("Hamster"); - Assert.IsTrue (hamster.HasCustomAttributes); - Assert.AreEqual (1, hamster.CustomAttributes.Count); + Assert.IsTrue (hamster.HasCustomAttributes); + Assert.AreEqual (1, hamster.CustomAttributes.Count); - var attribute = hamster.CustomAttributes [0]; - Assert.AreEqual ("System.Void FooAttribute::.ctor(System.String)", - attribute.Constructor.FullName); + var attribute = hamster.CustomAttributes [0]; + Assert.AreEqual ("System.Void FooAttribute::.ctor(System.String)", + attribute.Constructor.FullName); - Assert.IsTrue (attribute.HasConstructorArguments); - Assert.AreEqual (1, attribute.ConstructorArguments.Count); + Assert.IsTrue (attribute.HasConstructorArguments); + Assert.AreEqual (1, attribute.ConstructorArguments.Count); - AssertArgument ("bar", attribute.ConstructorArguments [0]); + AssertArgument ("bar", attribute.ConstructorArguments [0]); + }); } - [TestCSharp ("CustomAttributes.cs")] - public void NullString (ModuleDefinition module) + [Test] + public void NullString () { - var dentist = module.GetType ("Dentist"); + TestCSharp ("CustomAttributes.cs", module => { + var dentist = module.GetType ("Dentist"); - var attribute = GetAttribute (dentist, "Foo"); - Assert.IsNotNull (attribute); + var attribute = GetAttribute (dentist, "Foo"); + Assert.IsNotNull (attribute); - AssertArgument (null, attribute.ConstructorArguments [0]); + AssertArgument (null, attribute.ConstructorArguments [0]); + }); } - [TestCSharp ("CustomAttributes.cs")] - public void Primitives1 (ModuleDefinition module) + [Test] + public void Primitives1 () { - var steven = module.GetType ("Steven"); + TestCSharp ("CustomAttributes.cs", module => { + var steven = module.GetType ("Steven"); - var attribute = GetAttribute (steven, "Foo"); - Assert.IsNotNull (attribute); + var attribute = GetAttribute (steven, "Foo"); + Assert.IsNotNull (attribute); - AssertArgument (-12, attribute.ConstructorArguments [0]); - AssertArgument (242, attribute.ConstructorArguments [1]); - AssertArgument (true, attribute.ConstructorArguments [2]); - AssertArgument (false, attribute.ConstructorArguments [3]); - AssertArgument (4242, attribute.ConstructorArguments [4]); - AssertArgument (-1983, attribute.ConstructorArguments [5]); - AssertArgument ('c', attribute.ConstructorArguments [6]); + AssertArgument (-12, attribute.ConstructorArguments [0]); + AssertArgument (242, attribute.ConstructorArguments [1]); + AssertArgument (true, attribute.ConstructorArguments [2]); + AssertArgument (false, attribute.ConstructorArguments [3]); + AssertArgument (4242, attribute.ConstructorArguments [4]); + AssertArgument (-1983, attribute.ConstructorArguments [5]); + AssertArgument ('c', attribute.ConstructorArguments [6]); + }); } - [TestCSharp ("CustomAttributes.cs")] - public void Primitives2 (ModuleDefinition module) + [Test] + public void Primitives2 () { - var seagull = module.GetType ("Seagull"); + TestCSharp ("CustomAttributes.cs", module => { + var seagull = module.GetType ("Seagull"); - var attribute = GetAttribute (seagull, "Foo"); - Assert.IsNotNull (attribute); + var attribute = GetAttribute (seagull, "Foo"); + Assert.IsNotNull (attribute); - AssertArgument (-100000, attribute.ConstructorArguments [0]); - AssertArgument (200000, attribute.ConstructorArguments [1]); - AssertArgument (12.12f, attribute.ConstructorArguments [2]); - AssertArgument (long.MaxValue, attribute.ConstructorArguments [3]); - AssertArgument (ulong.MaxValue, attribute.ConstructorArguments [4]); - AssertArgument (64.646464, attribute.ConstructorArguments [5]); + AssertArgument (-100000, attribute.ConstructorArguments [0]); + AssertArgument (200000, attribute.ConstructorArguments [1]); + AssertArgument (12.12f, attribute.ConstructorArguments [2]); + AssertArgument (long.MaxValue, attribute.ConstructorArguments [3]); + AssertArgument (ulong.MaxValue, attribute.ConstructorArguments [4]); + AssertArgument (64.646464, attribute.ConstructorArguments [5]); + }); } - [TestCSharp ("CustomAttributes.cs")] - public void StringArgumentOnAssembly (ModuleDefinition module) + [Test] + public void StringArgumentOnAssembly () { - var assembly = module.Assembly; + TestCSharp ("CustomAttributes.cs", module => { + var assembly = module.Assembly; - var attribute = GetAttribute (assembly, "Foo"); - Assert.IsNotNull (attribute); + var attribute = GetAttribute (assembly, "Foo"); + Assert.IsNotNull (attribute); - AssertArgument ("bingo", attribute.ConstructorArguments [0]); + AssertArgument ("bingo", attribute.ConstructorArguments [0]); + }); } - [TestCSharp ("CustomAttributes.cs")] - public void CharArray (ModuleDefinition module) + [Test] + public void CharArray () { - var rifle = module.GetType ("Rifle"); + TestCSharp ("CustomAttributes.cs", module => { + var rifle = module.GetType ("Rifle"); - var attribute = GetAttribute (rifle, "Foo"); - Assert.IsNotNull (attribute); + var attribute = GetAttribute (rifle, "Foo"); + Assert.IsNotNull (attribute); - var argument = attribute.ConstructorArguments [0]; + var argument = attribute.ConstructorArguments [0]; - Assert.AreEqual ("System.Char[]", argument.Type.FullName); + Assert.AreEqual ("System.Char[]", argument.Type.FullName); - var array = argument.Value as CustomAttributeArgument []; - Assert.IsNotNull (array); + var array = argument.Value as CustomAttributeArgument []; + Assert.IsNotNull (array); - var str = "cecil"; + var str = "cecil"; - Assert.AreEqual (array.Length, str.Length); + Assert.AreEqual (array.Length, str.Length); - for (int i = 0; i < str.Length; i++) + for (int i = 0; i < str.Length; i++) AssertArgument (str [i], array [i]); + }); } - [TestCSharp ("CustomAttributes.cs")] - public void BoxedArguments (ModuleDefinition module) + [Test] + public void BoxedArguments () { - var worm = module.GetType ("Worm"); + TestCSharp ("CustomAttributes.cs", module => { + var worm = module.GetType ("Worm"); - var attribute = GetAttribute (worm, "Foo"); - Assert.IsNotNull (attribute); + var attribute = GetAttribute (worm, "Foo"); + Assert.IsNotNull (attribute); - Assert.AreEqual (".ctor ((Object:(String:\"2\")), (Object:(I4:2)))", PrettyPrint (attribute)); + Assert.AreEqual (".ctor ((Object:(String:\"2\")), (Object:(I4:2)))", PrettyPrint (attribute)); + }); } - [TestCSharp ("CustomAttributes.cs")] - public void BoxedArraysArguments (ModuleDefinition module) + [Test] + public void BoxedArraysArguments () { - var sheep = module.GetType ("Sheep"); + TestCSharp ("CustomAttributes.cs", module => { + var sheep = module.GetType ("Sheep"); - var attribute = GetAttribute (sheep, "Foo"); - Assert.IsNotNull (attribute); + var attribute = GetAttribute (sheep, "Foo"); + Assert.IsNotNull (attribute); - // [Foo (new object [] { "2", 2, 'c' }, new object [] { new object [] { 1, 2, 3}, null })] - AssertCustomAttribute (".ctor ((Object:(Object[]:{(Object:(String:\"2\")), (Object:(I4:2)), (Object:(Char:'c'))})), (Object:(Object[]:{(Object:(Object[]:{(Object:(I4:1)), (Object:(I4:2)), (Object:(I4:3))})), (Object:(String:null))})))", attribute); + // [Foo (new object [] { "2", 2, 'c' }, new object [] { new object [] { 1, 2, 3}, null })] + AssertCustomAttribute (".ctor ((Object:(Object[]:{(Object:(String:\"2\")), (Object:(I4:2)), (Object:(Char:'c'))})), (Object:(Object[]:{(Object:(Object[]:{(Object:(I4:1)), (Object:(I4:2)), (Object:(I4:3))})), (Object:(String:null))})))", attribute); + }); } - [TestCSharp ("CustomAttributes.cs")] - public void FieldsAndProperties (ModuleDefinition module) + [Test] + public void FieldsAndProperties () { - var angola = module.GetType ("Angola"); + TestCSharp ("CustomAttributes.cs", module => { + var angola = module.GetType ("Angola"); - var attribute = GetAttribute (angola, "Foo"); - Assert.IsNotNull (attribute); + var attribute = GetAttribute (angola, "Foo"); + Assert.IsNotNull (attribute); - Assert.AreEqual (2, attribute.Fields.Count); + Assert.AreEqual (2, attribute.Fields.Count); - var argument = attribute.Fields.Where (a => a.Name == "Pan").First (); - AssertCustomAttributeArgument ("(Object:(Object[]:{(Object:(I4:1)), (Object:(String:\"2\")), (Object:(Char:'3'))}))", argument); + var argument = attribute.Fields.Where (a => a.Name == "Pan").First (); + AssertCustomAttributeArgument ("(Object:(Object[]:{(Object:(I4:1)), (Object:(String:\"2\")), (Object:(Char:'3'))}))", argument); - argument = attribute.Fields.Where (a => a.Name == "PanPan").First (); - AssertCustomAttributeArgument ("(String[]:{(String:\"yo\"), (String:\"yo\")})", argument); + argument = attribute.Fields.Where (a => a.Name == "PanPan").First (); + AssertCustomAttributeArgument ("(String[]:{(String:\"yo\"), (String:\"yo\")})", argument); - Assert.AreEqual (2, attribute.Properties.Count); + Assert.AreEqual (2, attribute.Properties.Count); - argument = attribute.Properties.Where (a => a.Name == "Bang").First (); - AssertArgument (42, argument); + argument = attribute.Properties.Where (a => a.Name == "Bang").First (); + AssertArgument (42, argument); - argument = attribute.Properties.Where (a => a.Name == "Fiou").First (); - AssertArgument (null, argument); + argument = attribute.Properties.Where (a => a.Name == "Fiou").First (); + AssertArgument (null, argument); + }); } - [TestCSharp ("CustomAttributes.cs")] - public void BoxedStringField (ModuleDefinition module) + [Test] + public void BoxedStringField () { - var type = module.GetType ("BoxedStringField"); + TestCSharp ("CustomAttributes.cs", module => { + var type = module.GetType ("BoxedStringField"); - var attribute = GetAttribute (type, "Foo"); - Assert.IsNotNull (attribute); + var attribute = GetAttribute (type, "Foo"); + Assert.IsNotNull (attribute); - Assert.AreEqual (1, attribute.Fields.Count); + Assert.AreEqual (1, attribute.Fields.Count); - var argument = attribute.Fields.Where (a => a.Name == "Pan").First (); - AssertCustomAttributeArgument ("(Object:(String:\"fiouuu\"))", argument); + var argument = attribute.Fields.Where (a => a.Name == "Pan").First (); + AssertCustomAttributeArgument ("(Object:(String:\"fiouuu\"))", argument); + }); } - [TestCSharp ("CustomAttributes.cs")] - public void TypeDefinitionEnum (ModuleDefinition module) + [Test] + public void TypeDefinitionEnum () { - var zero = module.GetType ("Zero"); + TestCSharp ("CustomAttributes.cs", module => { + var zero = module.GetType ("Zero"); - var attribute = GetAttribute (zero, "Foo"); - Assert.IsNotNull (attribute); + var attribute = GetAttribute (zero, "Foo"); + Assert.IsNotNull (attribute); - Assert.AreEqual (1, attribute.ConstructorArguments.Count); + Assert.AreEqual (1, attribute.ConstructorArguments.Count); - Assert.AreEqual ((short) 2, attribute.ConstructorArguments [0].Value); - Assert.AreEqual ("Bingo", attribute.ConstructorArguments [0].Type.FullName); + Assert.AreEqual ((short) 2, attribute.ConstructorArguments [0].Value); + Assert.AreEqual ("Bingo", attribute.ConstructorArguments [0].Type.FullName); + }); } - [TestCSharp ("CustomAttributes.cs")] - public void TypeReferenceEnum (ModuleDefinition module) + [Test] + public void TypeReferenceEnum () { - var ace = module.GetType ("Ace"); + TestCSharp ("CustomAttributes.cs", module => { + var ace = module.GetType ("Ace"); - var attribute = GetAttribute (ace, "Foo"); - Assert.IsNotNull (attribute); + var attribute = GetAttribute (ace, "Foo"); + Assert.IsNotNull (attribute); - Assert.AreEqual (1, attribute.ConstructorArguments.Count); + Assert.AreEqual (1, attribute.ConstructorArguments.Count); - Assert.AreEqual ((byte) 0x04, attribute.ConstructorArguments [0].Value); - Assert.AreEqual ("System.Security.AccessControl.AceFlags", attribute.ConstructorArguments [0].Type.FullName); - Assert.AreEqual (module, attribute.ConstructorArguments [0].Type.Module); + Assert.AreEqual ((byte) 0x04, attribute.ConstructorArguments [0].Value); + Assert.AreEqual ("System.Security.AccessControl.AceFlags", attribute.ConstructorArguments [0].Type.FullName); + Assert.AreEqual (module, attribute.ConstructorArguments [0].Type.Module); + }); } - [TestCSharp ("CustomAttributes.cs")] - public void BoxedEnumReference (ModuleDefinition module) + [Test] + public void BoxedEnumReference () { - var bzzz = module.GetType ("Bzzz"); + TestCSharp ("CustomAttributes.cs", module => { + var bzzz = module.GetType ("Bzzz"); - var attribute = GetAttribute (bzzz, "Foo"); - Assert.IsNotNull (attribute); + var attribute = GetAttribute (bzzz, "Foo"); + Assert.IsNotNull (attribute); - // [Foo (new object [] { Bingo.Fuel, Bingo.Binga }, null, Pan = System.Security.AccessControl.AceFlags.NoPropagateInherit)] + // [Foo (new object [] { Bingo.Fuel, Bingo.Binga }, null, Pan = System.Security.AccessControl.AceFlags.NoPropagateInherit)] - Assert.AreEqual (2, attribute.ConstructorArguments.Count); + Assert.AreEqual (2, attribute.ConstructorArguments.Count); - var argument = attribute.ConstructorArguments [0]; + var argument = attribute.ConstructorArguments [0]; - AssertCustomAttributeArgument ("(Object:(Object[]:{(Object:(Bingo:2)), (Object:(Bingo:4))}))", argument); + AssertCustomAttributeArgument ("(Object:(Object[]:{(Object:(Bingo:2)), (Object:(Bingo:4))}))", argument); - argument = attribute.ConstructorArguments [1]; + argument = attribute.ConstructorArguments [1]; - AssertCustomAttributeArgument ("(Object:(String:null))", argument); + AssertCustomAttributeArgument ("(Object:(String:null))", argument); - argument = attribute.Fields.Where (a => a.Name == "Pan").First ().Argument; + argument = attribute.Fields.Where (a => a.Name == "Pan").First ().Argument; - AssertCustomAttributeArgument ("(Object:(System.Security.AccessControl.AceFlags:4))", argument); + AssertCustomAttributeArgument ("(Object:(System.Security.AccessControl.AceFlags:4))", argument); + }); } - [TestCSharp ("CustomAttributes.cs")] - public void TypeOfTypeDefinition (ModuleDefinition module) + [Test] + public void TypeOfTypeDefinition () { - var typed = module.GetType ("Typed"); + TestCSharp ("CustomAttributes.cs", module => { + var typed = module.GetType ("Typed"); - var attribute = GetAttribute (typed, "Foo"); - Assert.IsNotNull (attribute); + var attribute = GetAttribute (typed, "Foo"); + Assert.IsNotNull (attribute); - Assert.AreEqual (1, attribute.ConstructorArguments.Count); + Assert.AreEqual (1, attribute.ConstructorArguments.Count); - var argument = attribute.ConstructorArguments [0]; + var argument = attribute.ConstructorArguments [0]; - Assert.AreEqual ("System.Type", argument.Type.FullName); + Assert.AreEqual ("System.Type", argument.Type.FullName); - var type = argument.Value as TypeDefinition; - Assert.IsNotNull (type); + var type = argument.Value as TypeDefinition; + Assert.IsNotNull (type); - Assert.AreEqual ("Bingo", type.FullName); + Assert.AreEqual ("Bingo", type.FullName); + }); } - [TestCSharp ("CustomAttributes.cs")] - public void TypeOfNestedTypeDefinition (ModuleDefinition module) + [Test] + public void TypeOfNestedTypeDefinition () { - var typed = module.GetType ("NestedTyped"); + TestCSharp ("CustomAttributes.cs", module => { + var typed = module.GetType ("NestedTyped"); - var attribute = GetAttribute (typed, "Foo"); - Assert.IsNotNull (attribute); + var attribute = GetAttribute (typed, "Foo"); + Assert.IsNotNull (attribute); - Assert.AreEqual (1, attribute.ConstructorArguments.Count); + Assert.AreEqual (1, attribute.ConstructorArguments.Count); - var argument = attribute.ConstructorArguments [0]; + var argument = attribute.ConstructorArguments [0]; - Assert.AreEqual ("System.Type", argument.Type.FullName); + Assert.AreEqual ("System.Type", argument.Type.FullName); - var type = argument.Value as TypeDefinition; - Assert.IsNotNull (type); + var type = argument.Value as TypeDefinition; + Assert.IsNotNull (type); - Assert.AreEqual ("FooAttribute/Token", type.FullName); + Assert.AreEqual ("FooAttribute/Token", type.FullName); + }); } - [TestCSharp ("CustomAttributes.cs")] - public void FieldTypeOf (ModuleDefinition module) + [Test] + public void FieldTypeOf () { - var truc = module.GetType ("Truc"); + TestCSharp ("CustomAttributes.cs", module => { + var truc = module.GetType ("Truc"); - var attribute = GetAttribute (truc, "Foo"); - Assert.IsNotNull (attribute); + var attribute = GetAttribute (truc, "Foo"); + Assert.IsNotNull (attribute); - var argument = attribute.Fields.Where (a => a.Name == "Chose").First ().Argument; + var argument = attribute.Fields.Where (a => a.Name == "Chose").First ().Argument; - Assert.AreEqual ("System.Type", argument.Type.FullName); + Assert.AreEqual ("System.Type", argument.Type.FullName); - var type = argument.Value as TypeDefinition; - Assert.IsNotNull (type); + var type = argument.Value as TypeDefinition; + Assert.IsNotNull (type); - Assert.AreEqual ("Typed", type.FullName); + Assert.AreEqual ("Typed", type.FullName); + }); } - [TestCSharp ("CustomAttributes.cs")] - public void FieldNullTypeOf (ModuleDefinition module) + [Test] + public void EscapedTypeName () { - var truc = module.GetType ("Machin"); + TestModule ("bug-185.dll", module => { + var foo = module.GetType ("Foo"); + var foo_do = foo.Methods.Where (m => !m.IsConstructor).First (); - var attribute = GetAttribute (truc, "Foo"); - Assert.IsNotNull (attribute); + var attribute = foo_do.CustomAttributes.Where (ca => ca.AttributeType.Name == "AsyncStateMachineAttribute").First (); - var argument = attribute.Fields.Where (a => a.Name == "Chose").First ().Argument; + Assert.AreEqual (foo.NestedTypes [0], attribute.ConstructorArguments [0].Value); - Assert.AreEqual ("System.Type", argument.Type.FullName); + var function = module.GetType ("Function`1"); - Assert.IsNull (argument.Value); + var apply = function.Methods.Where(m => !m.IsConstructor).First (); + + attribute = apply.CustomAttributes.Where (ca => ca.AttributeType.Name == "AsyncStateMachineAttribute").First (); + + Assert.AreEqual (function.NestedTypes [0], attribute.ConstructorArguments [0].Value); + }); } - [TestCSharp ("CustomAttributes.cs")] - public void OpenGenericTypeOf (ModuleDefinition module) + [Test] + public void FieldNullTypeOf () { - var open_generic = module.GetType ("OpenGeneric`2"); - Assert.IsNotNull (open_generic); + TestCSharp ("CustomAttributes.cs", module => { + var truc = module.GetType ("Machin"); - var attribute = GetAttribute (open_generic, "Foo"); - Assert.IsNotNull (attribute); + var attribute = GetAttribute (truc, "Foo"); + Assert.IsNotNull (attribute); - Assert.AreEqual (1, attribute.ConstructorArguments.Count); + var argument = attribute.Fields.Where (a => a.Name == "Chose").First ().Argument; - var argument = attribute.ConstructorArguments [0]; + Assert.AreEqual ("System.Type", argument.Type.FullName); - Assert.AreEqual ("System.Type", argument.Type.FullName); - - var type = argument.Value as TypeReference; - Assert.IsNotNull (type); - - Assert.AreEqual ("System.Collections.Generic.Dictionary`2", type.FullName); + Assert.IsNull (argument.Value); + }); } - [TestCSharp ("CustomAttributes.cs")] - public void ClosedGenericTypeOf (ModuleDefinition module) + [Test] + public void OpenGenericTypeOf () { - var closed_generic = module.GetType ("ClosedGeneric"); - Assert.IsNotNull (closed_generic); + TestCSharp ("CustomAttributes.cs", module => { + var open_generic = module.GetType ("OpenGeneric`2"); + Assert.IsNotNull (open_generic); - var attribute = GetAttribute (closed_generic, "Foo"); - Assert.IsNotNull (attribute); + var attribute = GetAttribute (open_generic, "Foo"); + Assert.IsNotNull (attribute); - Assert.AreEqual (1, attribute.ConstructorArguments.Count); + Assert.AreEqual (1, attribute.ConstructorArguments.Count); - var argument = attribute.ConstructorArguments [0]; + var argument = attribute.ConstructorArguments [0]; - Assert.AreEqual ("System.Type", argument.Type.FullName); + Assert.AreEqual ("System.Type", argument.Type.FullName); - var type = argument.Value as TypeReference; - Assert.IsNotNull (type); + var type = argument.Value as TypeReference; + Assert.IsNotNull (type); - Assert.AreEqual ("System.Collections.Generic.Dictionary`2[,]>", type.FullName); + Assert.AreEqual ("System.Collections.Generic.Dictionary`2", type.FullName); + }); } - [TestIL ("types.il")] - public void EmptyBlob (ModuleDefinition module) + [Test] + public void ClosedGenericTypeOf () { - var attribute = module.GetType ("CustomAttribute"); - Assert.AreEqual (1, attribute.CustomAttributes.Count); - Assert.AreEqual (0, attribute.CustomAttributes [0].ConstructorArguments.Count); + TestCSharp ("CustomAttributes.cs", module => { + var closed_generic = module.GetType ("ClosedGeneric"); + Assert.IsNotNull (closed_generic); + + var attribute = GetAttribute (closed_generic, "Foo"); + Assert.IsNotNull (attribute); + + Assert.AreEqual (1, attribute.ConstructorArguments.Count); + + var argument = attribute.ConstructorArguments [0]; + + Assert.AreEqual ("System.Type", argument.Type.FullName); + + var type = argument.Value as TypeReference; + Assert.IsNotNull (type); + + Assert.AreEqual ("System.Collections.Generic.Dictionary`2[,]>", type.FullName); + }); + } + + [Test] + public void TypeOfArrayOfNestedClass () + { + TestCSharp ("CustomAttributes.cs", module => { + var parent = module.GetType ("Parent"); + Assert.IsNotNull (parent); + + var attribute = GetAttribute (parent, "Foo"); + Assert.IsNotNull (attribute); + + Assert.AreEqual (1, attribute.ConstructorArguments.Count); + + var argument = attribute.ConstructorArguments [0]; + + Assert.AreEqual ("System.Type", argument.Type.FullName); + + var type = argument.Value as TypeReference; + Assert.IsNotNull (type); + + Assert.AreEqual ("Parent/Child[]", type.FullName); + }); + } + + [Test] + public void EmptyBlob () + { + TestIL ("ca-empty-blob.il", module => { + var attribute = module.GetType ("CustomAttribute"); + Assert.AreEqual (1, attribute.CustomAttributes.Count); + Assert.AreEqual (0, attribute.CustomAttributes [0].ConstructorArguments.Count); + }, verify: !Platform.OnMono); + } + + [Test] + public void InterfaceImplementation () + { + IgnoreOnMono(); + + TestIL ("ca-iface-impl.il", module => { + var type = module.GetType ("FooType"); + var iface = type.Interfaces.Single (i => i.InterfaceType.FullName == "IFoo"); + Assert.IsTrue (iface.HasCustomAttributes); + var attributes = iface.CustomAttributes; + Assert.AreEqual (1, attributes.Count); + Assert.AreEqual ("FooAttribute", attributes [0].AttributeType.FullName); + }); } [Test] @@ -356,7 +455,7 @@ namespace Mono.Cecil.Tests { var file = Path.Combine (Path.GetTempPath (), "CaBlob.dll"); var module = ModuleDefinition.CreateModule ("CaBlob.dll", new ModuleParameters { Kind = ModuleKind.Dll, Runtime = TargetRuntime.Net_2_0 }); - var assembly_title_ctor = module.Import (typeof (System.Reflection.AssemblyTitleAttribute).GetConstructor (new [] {typeof (string)})); + var assembly_title_ctor = module.ImportReference (typeof (System.Reflection.AssemblyTitleAttribute).GetConstructor (new [] {typeof (string)})); Assert.IsNotNull (assembly_title_ctor); @@ -384,6 +483,8 @@ namespace Mono.Cecil.Tests { Assert.IsNotNull (attribute); Assert.AreEqual ("CaBlob", (string) attribute.ConstructorArguments [0].Value); + + module.Dispose (); } static void AssertCustomAttribute (string expected, CustomAttribute attribute) diff --git a/external/cecil/Test/Mono.Cecil.Tests/EventTests.cs b/external/cecil/Test/Mono.Cecil.Tests/EventTests.cs index 15a599c58b..cb9064b795 100644 --- a/external/cecil/Test/Mono.Cecil.Tests/EventTests.cs +++ b/external/cecil/Test/Mono.Cecil.Tests/EventTests.cs @@ -10,57 +10,70 @@ namespace Mono.Cecil.Tests { [TestFixture] public class EventTests : BaseTestFixture { - [TestCSharp ("Events.cs")] - public void AbstractMethod (ModuleDefinition module) + [Test] + public void AbstractMethod () { - var type = module.GetType ("Foo"); + TestCSharp ("Events.cs", module => { + var type = module.GetType ("Foo"); - Assert.IsTrue (type.HasEvents); + Assert.IsTrue (type.HasEvents); - var events = type.Events; + var events = type.Events; - Assert.AreEqual (1, events.Count); + Assert.AreEqual (1, events.Count); - var @event = events [0]; + var @event = events [0]; - Assert.IsNotNull (@event); - Assert.AreEqual ("Bar", @event.Name); - Assert.IsNotNull (@event.EventType); - Assert.AreEqual ("Pan", @event.EventType.FullName); + Assert.IsNotNull (@event); + Assert.AreEqual ("Bar", @event.Name); + Assert.IsNotNull (@event.EventType); + Assert.AreEqual ("Pan", @event.EventType.FullName); - Assert.IsNotNull (@event.AddMethod); - Assert.AreEqual (MethodSemanticsAttributes.AddOn, @event.AddMethod.SemanticsAttributes); - Assert.IsNotNull (@event.RemoveMethod); - Assert.AreEqual (MethodSemanticsAttributes.RemoveOn, @event.RemoveMethod.SemanticsAttributes); + Assert.IsNotNull (@event.AddMethod); + Assert.AreEqual (MethodSemanticsAttributes.AddOn, @event.AddMethod.SemanticsAttributes); + Assert.IsNotNull (@event.RemoveMethod); + Assert.AreEqual (MethodSemanticsAttributes.RemoveOn, @event.RemoveMethod.SemanticsAttributes); + }); } - [TestIL ("others.il")] - public void OtherMethod (ModuleDefinition module) + [Test] + public void OtherMethod () { - var type = module.GetType ("Others"); + TestIL ("others.il", module => { + var type = module.GetType ("Others"); - Assert.IsTrue (type.HasEvents); + Assert.IsTrue (type.HasEvents); - var events = type.Events; + var events = type.Events; - Assert.AreEqual (1, events.Count); + Assert.AreEqual (1, events.Count); - var @event = events [0]; + var @event = events [0]; - Assert.IsNotNull (@event); - Assert.AreEqual ("Handler", @event.Name); - Assert.IsNotNull (@event.EventType); - Assert.AreEqual ("System.EventHandler", @event.EventType.FullName); + Assert.IsNotNull (@event); + Assert.AreEqual ("Handler", @event.Name); + Assert.IsNotNull (@event.EventType); + Assert.AreEqual ("System.EventHandler", @event.EventType.FullName); - Assert.IsTrue (@event.HasOtherMethods); + Assert.IsTrue (@event.HasOtherMethods); - Assert.AreEqual (2, @event.OtherMethods.Count); + Assert.AreEqual (2, @event.OtherMethods.Count); - var other = @event.OtherMethods [0]; - Assert.AreEqual ("dang_Handler", other.Name); + var other = @event.OtherMethods [0]; + Assert.AreEqual ("dang_Handler", other.Name); - other = @event.OtherMethods [1]; - Assert.AreEqual ("fang_Handler", other.Name); + other = @event.OtherMethods [1]; + Assert.AreEqual ("fang_Handler", other.Name); + }); + } + + [Test] + public void UnattachedEvent () + { + var int32 = typeof (int).ToDefinition (); + var evt = new EventDefinition ("Event", EventAttributes.None, int32); + + Assert.AreEqual (null, evt.AddMethod); } } } diff --git a/external/cecil/Test/Mono.Cecil.Tests/Extensions.cs b/external/cecil/Test/Mono.Cecil.Tests/Extensions.cs index 0788d21bc5..ab27e9b028 100644 --- a/external/cecil/Test/Mono.Cecil.Tests/Extensions.cs +++ b/external/cecil/Test/Mono.Cecil.Tests/Extensions.cs @@ -1,4 +1,5 @@ using System; +using System.IO; using System.Linq; using SR = System.Reflection; @@ -20,7 +21,7 @@ namespace Mono.Cecil.Tests { public static TypeDefinition ToDefinition (this Type self) { - var module = ModuleDefinition.ReadModule (self.Module.FullyQualifiedName); + var module = ModuleDefinition.ReadModule (new MemoryStream (File.ReadAllBytes (self.Module.FullyQualifiedName))); return (TypeDefinition) module.LookupToken (self.MetadataToken); } diff --git a/external/cecil/Test/Mono.Cecil.Tests/FieldTests.cs b/external/cecil/Test/Mono.Cecil.Tests/FieldTests.cs index 8c63456886..05165d692a 100644 --- a/external/cecil/Test/Mono.Cecil.Tests/FieldTests.cs +++ b/external/cecil/Test/Mono.Cecil.Tests/FieldTests.cs @@ -1,7 +1,5 @@ using System; -using Mono.Cecil; -using Mono.Cecil.Metadata; using Mono.Cecil.PE; using NUnit.Framework; @@ -11,308 +9,349 @@ namespace Mono.Cecil.Tests { [TestFixture] public class FieldTests : BaseTestFixture { - [TestCSharp ("Fields.cs")] - public void TypeDefField (ModuleDefinition module) + [Test] + public void TypeDefField () { - var type = module.Types [1]; - Assert.AreEqual ("Foo", type.Name); - Assert.AreEqual (1, type.Fields.Count); + TestCSharp ("Fields.cs", module => { + var type = module.Types [1]; + Assert.AreEqual ("Foo", type.Name); + Assert.AreEqual (1, type.Fields.Count); + + var field = type.Fields [0]; + Assert.AreEqual ("bar", field.Name); + Assert.AreEqual (1, field.MetadataToken.RID); + Assert.IsNotNull (field.FieldType); + Assert.AreEqual ("Bar", field.FieldType.FullName); + Assert.AreEqual (TokenType.Field, field.MetadataToken.TokenType); + Assert.IsFalse (field.HasConstant); + Assert.IsNull (field.Constant); + }); + } + + [Test] + public void PrimitiveTypes () + { + TestCSharp ("Fields.cs", module => { + var type = module.GetType ("Baz"); + + AssertField (type, "char", typeof (char)); + AssertField (type, "bool", typeof (bool)); + AssertField (type, "sbyte", typeof (sbyte)); + AssertField (type, "byte", typeof (byte)); + AssertField (type, "int16", typeof (short)); + AssertField (type, "uint16", typeof (ushort)); + AssertField (type, "int32", typeof (int)); + AssertField (type, "uint32", typeof (uint)); + AssertField (type, "int64", typeof (long)); + AssertField (type, "uint64", typeof (ulong)); + AssertField (type, "single", typeof (float)); + AssertField (type, "double", typeof (double)); + AssertField (type, "string", typeof (string)); + AssertField (type, "object", typeof (object)); + }); + } + + [Test] + public void VolatileField () + { + TestCSharp ("Fields.cs", module => { + var type = module.GetType ("Bar"); + + Assert.IsTrue (type.HasFields); + Assert.AreEqual (1, type.Fields.Count); + + var field = type.Fields [0]; + + Assert.AreEqual ("oiseau", field.Name); + Assert.AreEqual ("System.Int32 modreq(System.Runtime.CompilerServices.IsVolatile)", field.FieldType.FullName); + + Assert.IsFalse (field.HasConstant); + }); + } + + [Test] + public void FieldLayout () + { + TestCSharp ("Layouts.cs", module => { + var foo = module.GetType ("Foo"); + Assert.IsNotNull (foo); + + Assert.IsTrue (foo.HasFields); + + var fields = foo.Fields; + + var field = fields [0]; + + Assert.AreEqual ("Bar", field.Name); + Assert.IsTrue (field.HasLayoutInfo); + Assert.AreEqual (0, field.Offset); + + field = fields [1]; + + Assert.AreEqual ("Baz", field.Name); + Assert.IsTrue (field.HasLayoutInfo); + Assert.AreEqual (2, field.Offset); + + field = fields [2]; + + Assert.AreEqual ("Gazonk", field.Name); + Assert.IsTrue (field.HasLayoutInfo); + Assert.AreEqual (4, field.Offset); + }); + } + + [Test] + public void FieldRVA () + { + TestCSharp ("Layouts.cs", module => { + var priv_impl = GetPrivateImplementationType (module); + Assert.IsNotNull (priv_impl); + + Assert.AreEqual (1, priv_impl.Fields.Count); + + var field = priv_impl.Fields [0]; + + Assert.IsNotNull (field); + Assert.AreNotEqual (0, field.RVA); + Assert.IsNotNull (field.InitialValue); + Assert.AreEqual (16, field.InitialValue.Length); + + var buffer = new ByteBuffer (field.InitialValue); + + Assert.AreEqual (1, buffer.ReadUInt32 ()); + Assert.AreEqual (2, buffer.ReadUInt32 ()); + Assert.AreEqual (3, buffer.ReadUInt32 ()); + Assert.AreEqual (4, buffer.ReadUInt32 ()); + }); + } + + [Test] + public void GenericFieldDefinition () + { + TestCSharp ("Generics.cs", module => { + var bar = module.GetType ("Bar`1"); + Assert.IsNotNull (bar); + + Assert.IsTrue (bar.HasGenericParameters); + var t = bar.GenericParameters [0]; + + Assert.AreEqual ("T", t.Name); + Assert.AreEqual (t.Owner, bar); + + var bang = bar.GetField ("bang"); + + Assert.IsNotNull (bang); + + Assert.AreEqual (t, bang.FieldType); + }); + } + + [Test] + public void ArrayFields () + { + TestIL ("types.il", module => { + var types = module.GetType ("Types"); + Assert.IsNotNull (types); + + var rank_two = types.GetField ("rank_two"); + + var array = rank_two.FieldType as ArrayType; + Assert.IsNotNull (array); + + Assert.AreEqual (2, array.Rank); + Assert.IsFalse (array.Dimensions [0].IsSized); + Assert.IsFalse (array.Dimensions [1].IsSized); + + var rank_two_low_bound_zero = types.GetField ("rank_two_low_bound_zero"); + + array = rank_two_low_bound_zero.FieldType as ArrayType; + Assert.IsNotNull (array); + + Assert.AreEqual (2, array.Rank); + Assert.IsTrue (array.Dimensions [0].IsSized); + Assert.AreEqual (0, array.Dimensions [0].LowerBound); + Assert.AreEqual (null, array.Dimensions [0].UpperBound); + Assert.IsTrue (array.Dimensions [1].IsSized); + Assert.AreEqual (0, array.Dimensions [1].LowerBound); + Assert.AreEqual (null, array.Dimensions [1].UpperBound); + + var rank_one_low_bound_m1 = types.GetField ("rank_one_low_bound_m1"); + array = rank_one_low_bound_m1.FieldType as ArrayType; + Assert.IsNotNull (array); + + Assert.AreEqual (1, array.Rank); + Assert.IsTrue (array.Dimensions [0].IsSized); + Assert.AreEqual (-1, array.Dimensions [0].LowerBound); + Assert.AreEqual (4, array.Dimensions [0].UpperBound); + }); + } + + [Test] + public void EnumFieldsConstant () + { + TestCSharp ("Fields.cs", module => { + var pim = module.GetType ("Pim"); + Assert.IsNotNull (pim); + + var field = pim.GetField ("Pam"); + Assert.IsTrue (field.HasConstant); + Assert.AreEqual (1, (int) field.Constant); + + field = pim.GetField ("Poum"); + Assert.AreEqual (2, (int) field.Constant); + }); + } + + [Test] + public void StringAndClassConstant () + { + TestCSharp ("Fields.cs", module => { + var panpan = module.GetType ("PanPan"); + Assert.IsNotNull (panpan); + + var field = panpan.GetField ("Peter"); + Assert.IsTrue (field.HasConstant); + Assert.IsNull (field.Constant); + + field = panpan.GetField ("QQ"); + Assert.AreEqual ("qq", (string) field.Constant); + + field = panpan.GetField ("nil"); + Assert.AreEqual (null, (string) field.Constant); + }); + } + + [Test] + public void ObjectConstant () + { + TestCSharp ("Fields.cs", module => { + var panpan = module.GetType ("PanPan"); + Assert.IsNotNull (panpan); + + var field = panpan.GetField ("obj"); + Assert.IsTrue (field.HasConstant); + Assert.IsNull (field.Constant); + }); + } + + [Test] + public void NullPrimitiveConstant () + { + TestIL ("types.il", module => { + var fields = module.GetType ("Fields"); + + var field = fields.GetField ("int32_nullref"); + Assert.IsTrue (field.HasConstant); + Assert.AreEqual (null, field.Constant); + }); + } + + [Test] + public void ArrayConstant () + { + TestCSharp ("Fields.cs", module => { + var panpan = module.GetType ("PanPan"); + Assert.IsNotNull (panpan); + + var field = panpan.GetField ("ints"); + Assert.IsTrue (field.HasConstant); + Assert.IsNull (field.Constant); + }); + } + + [Test] + public void ConstantCoalescing () + { + TestIL ("types.il", module => { + var fields = module.GetType ("Fields"); + + var field = fields.GetField ("int32_int16"); + Assert.AreEqual ("System.Int32", field.FieldType.FullName); + Assert.IsTrue (field.HasConstant); + Assert.IsInstanceOf (typeof (short), field.Constant); + Assert.AreEqual ((short) 1, field.Constant); + + field = fields.GetField ("int16_int32"); + Assert.AreEqual ("System.Int16", field.FieldType.FullName); + Assert.IsTrue (field.HasConstant); + Assert.IsInstanceOf (typeof (int), field.Constant); + Assert.AreEqual (1, field.Constant); + + field = fields.GetField ("char_int16"); + Assert.AreEqual ("System.Char", field.FieldType.FullName); + Assert.IsTrue (field.HasConstant); + Assert.IsInstanceOf (typeof (short), field.Constant); + Assert.AreEqual ((short) 1, field.Constant); + + field = fields.GetField ("int16_char"); + Assert.AreEqual ("System.Int16", field.FieldType.FullName); + Assert.IsTrue (field.HasConstant); + Assert.IsInstanceOf (typeof (char), field.Constant); + Assert.AreEqual ('s', field.Constant); + }); + } + + [Test] + public void NestedEnumOfGenericTypeDefinition () + { + TestCSharp ("Generics.cs", module => { + var dang = module.GetType ("Bongo`1/Dang"); + Assert.IsNotNull (dang); + + var field = dang.GetField ("Ding"); + Assert.IsNotNull (field); + Assert.AreEqual (2, field.Constant); + + field = dang.GetField ("Dong"); + Assert.IsNotNull (field); + Assert.AreEqual (12, field.Constant); + }); + } + + [Test] + public void MarshalAsFixedStr () + { + TestModule ("marshal.dll", module => { + var boc = module.GetType ("Boc"); + var field = boc.GetField ("a"); + + Assert.IsNotNull (field); + + Assert.IsTrue (field.HasMarshalInfo); + + var info = (FixedSysStringMarshalInfo) field.MarshalInfo; + + Assert.AreEqual (42, info.Size); + }); + } + + [Test] + public void MarshalAsFixedArray () + { + TestModule ("marshal.dll", module => { + var boc = module.GetType ("Boc"); + var field = boc.GetField ("b"); + + Assert.IsNotNull (field); + + Assert.IsTrue (field.HasMarshalInfo); + + var info = (FixedArrayMarshalInfo) field.MarshalInfo; + + Assert.AreEqual (12, info.Size); + Assert.AreEqual (NativeType.Boolean, info.ElementType); + }); + } + + [Test] + public void UnattachedField () + { + var field = new FieldDefinition ("Field", FieldAttributes.Public, typeof (int).ToDefinition ()); - var field = type.Fields [0]; - Assert.AreEqual ("bar", field.Name); - Assert.AreEqual (1, field.MetadataToken.RID); - Assert.IsNotNull (field.FieldType); - Assert.AreEqual ("Bar", field.FieldType.FullName); - Assert.AreEqual (TokenType.Field, field.MetadataToken.TokenType); Assert.IsFalse (field.HasConstant); Assert.IsNull (field.Constant); } - [TestCSharp ("Fields.cs")] - public void PrimitiveTypes (ModuleDefinition module) - { - var type = module.GetType ("Baz"); - - AssertField (type, "char", typeof (char)); - AssertField (type, "bool", typeof (bool)); - AssertField (type, "sbyte", typeof (sbyte)); - AssertField (type, "byte", typeof (byte)); - AssertField (type, "int16", typeof (short)); - AssertField (type, "uint16", typeof (ushort)); - AssertField (type, "int32", typeof (int)); - AssertField (type, "uint32", typeof (uint)); - AssertField (type, "int64", typeof (long)); - AssertField (type, "uint64", typeof (ulong)); - AssertField (type, "single", typeof (float)); - AssertField (type, "double", typeof (double)); - AssertField (type, "string", typeof (string)); - AssertField (type, "object", typeof (object)); - } - - [TestCSharp ("Fields.cs")] - public void VolatileField (ModuleDefinition module) - { - var type = module.GetType ("Bar"); - - Assert.IsTrue (type.HasFields); - Assert.AreEqual (1, type.Fields.Count); - - var field = type.Fields [0]; - - Assert.AreEqual ("oiseau", field.Name); - Assert.AreEqual ("System.Int32 modreq(System.Runtime.CompilerServices.IsVolatile)", field.FieldType.FullName); - - Assert.IsFalse (field.HasConstant); - } - - [TestCSharp ("Layouts.cs")] - public void FieldLayout (ModuleDefinition module) - { - var foo = module.GetType ("Foo"); - Assert.IsNotNull (foo); - - Assert.IsTrue (foo.HasFields); - - var fields = foo.Fields; - - var field = fields [0]; - - Assert.AreEqual ("Bar", field.Name); - Assert.IsTrue (field.HasLayoutInfo); - Assert.AreEqual (0, field.Offset); - - field = fields [1]; - - Assert.AreEqual ("Baz", field.Name); - Assert.IsTrue (field.HasLayoutInfo); - Assert.AreEqual (2, field.Offset); - - field = fields [2]; - - Assert.AreEqual ("Gazonk", field.Name); - Assert.IsTrue (field.HasLayoutInfo); - Assert.AreEqual (4, field.Offset); - } - - [TestCSharp ("Layouts.cs")] - public void FieldRVA (ModuleDefinition module) - { - var priv_impl = GetPrivateImplementationType (module); - Assert.IsNotNull (priv_impl); - - Assert.AreEqual (1, priv_impl.Fields.Count); - - var field = priv_impl.Fields [0]; - - Assert.IsNotNull (field); - Assert.AreNotEqual (0, field.RVA); - Assert.IsNotNull (field.InitialValue); - Assert.AreEqual (16, field.InitialValue.Length); - - var buffer = new ByteBuffer (field.InitialValue); - - Assert.AreEqual (1, buffer.ReadUInt32 ()); - Assert.AreEqual (2, buffer.ReadUInt32 ()); - Assert.AreEqual (3, buffer.ReadUInt32 ()); - Assert.AreEqual (4, buffer.ReadUInt32 ()); - } - - [TestCSharp ("Generics.cs")] - public void GenericFieldDefinition (ModuleDefinition module) - { - var bar = module.GetType ("Bar`1"); - Assert.IsNotNull (bar); - - Assert.IsTrue (bar.HasGenericParameters); - var t = bar.GenericParameters [0]; - - Assert.AreEqual ("T", t.Name); - Assert.AreEqual (t.Owner, bar); - - var bang = bar.GetField ("bang"); - - Assert.IsNotNull (bang); - - Assert.AreEqual (t, bang.FieldType); - } - - [TestIL ("types.il")] - public void ArrayFields (ModuleDefinition module) - { - var types = module.GetType ("Types"); - Assert.IsNotNull (types); - - var rank_two = types.GetField ("rank_two"); - - var array = rank_two.FieldType as ArrayType; - Assert.IsNotNull (array); - - Assert.AreEqual (2, array.Rank); - Assert.IsFalse (array.Dimensions [0].IsSized); - Assert.IsFalse (array.Dimensions [1].IsSized); - - var rank_two_low_bound_zero = types.GetField ("rank_two_low_bound_zero"); - - array = rank_two_low_bound_zero.FieldType as ArrayType; - Assert.IsNotNull (array); - - Assert.AreEqual (2, array.Rank); - Assert.IsTrue (array.Dimensions [0].IsSized); - Assert.AreEqual (0, array.Dimensions [0].LowerBound); - Assert.AreEqual (null, array.Dimensions [0].UpperBound); - Assert.IsTrue (array.Dimensions [1].IsSized); - Assert.AreEqual (0, array.Dimensions [1].LowerBound); - Assert.AreEqual (null, array.Dimensions [1].UpperBound); - - var rank_one_low_bound_m1 = types.GetField ("rank_one_low_bound_m1"); - array = rank_one_low_bound_m1.FieldType as ArrayType; - Assert.IsNotNull (array); - - Assert.AreEqual (1, array.Rank); - Assert.IsTrue (array.Dimensions [0].IsSized); - Assert.AreEqual (-1, array.Dimensions [0].LowerBound); - Assert.AreEqual (4, array.Dimensions [0].UpperBound); - } - - [TestCSharp ("Fields.cs")] - public void EnumFieldsConstant (ModuleDefinition module) - { - var pim = module.GetType ("Pim"); - Assert.IsNotNull (pim); - - var field = pim.GetField ("Pam"); - Assert.IsTrue (field.HasConstant); - Assert.AreEqual (1, (int) field.Constant); - - field = pim.GetField ("Poum"); - Assert.AreEqual (2, (int) field.Constant); - } - - [TestCSharp ("Fields.cs")] - public void StringAndClassConstant (ModuleDefinition module) - { - var panpan = module.GetType ("PanPan"); - Assert.IsNotNull (panpan); - - var field = panpan.GetField ("Peter"); - Assert.IsTrue (field.HasConstant); - Assert.IsNull (field.Constant); - - field = panpan.GetField ("QQ"); - Assert.AreEqual ("qq", (string) field.Constant); - - field = panpan.GetField ("nil"); - Assert.AreEqual (null, (string) field.Constant); - } - - [TestCSharp ("Fields.cs")] - public void ObjectConstant (ModuleDefinition module) - { - var panpan = module.GetType ("PanPan"); - Assert.IsNotNull (panpan); - - var field = panpan.GetField ("obj"); - Assert.IsTrue (field.HasConstant); - Assert.IsNull (field.Constant); - } - - [TestIL ("types.il")] - public void NullPrimitiveConstant (ModuleDefinition module) - { - var fields = module.GetType ("Fields"); - - var field = fields.GetField ("int32_nullref"); - Assert.IsTrue (field.HasConstant); - Assert.AreEqual (null, field.Constant); - } - - [TestCSharp ("Fields.cs")] - public void ArrayConstant (ModuleDefinition module) - { - var panpan = module.GetType ("PanPan"); - Assert.IsNotNull (panpan); - - var field = panpan.GetField ("ints"); - Assert.IsTrue (field.HasConstant); - Assert.IsNull (field.Constant); - } - - [TestIL ("types.il")] - public void ConstantCoalescing (ModuleDefinition module) - { - var fields = module.GetType ("Fields"); - - var field = fields.GetField ("int32_int16"); - Assert.AreEqual ("System.Int32", field.FieldType.FullName); - Assert.IsTrue (field.HasConstant); - Assert.IsInstanceOf (typeof (short), field.Constant); - Assert.AreEqual ((short) 1, field.Constant); - - field = fields.GetField ("int16_int32"); - Assert.AreEqual ("System.Int16", field.FieldType.FullName); - Assert.IsTrue (field.HasConstant); - Assert.IsInstanceOf (typeof (int), field.Constant); - Assert.AreEqual (1, field.Constant); - - field = fields.GetField ("char_int16"); - Assert.AreEqual ("System.Char", field.FieldType.FullName); - Assert.IsTrue (field.HasConstant); - Assert.IsInstanceOf (typeof (short), field.Constant); - Assert.AreEqual ((short) 1, field.Constant); - - field = fields.GetField ("int16_char"); - Assert.AreEqual ("System.Int16", field.FieldType.FullName); - Assert.IsTrue (field.HasConstant); - Assert.IsInstanceOf (typeof (char), field.Constant); - Assert.AreEqual ('s', field.Constant); - } - - [TestCSharp ("Generics.cs")] - public void NestedEnumOfGenericTypeDefinition (ModuleDefinition module) - { - var dang = module.GetType ("Bongo`1/Dang"); - Assert.IsNotNull (dang); - - var field = dang.GetField ("Ding"); - Assert.IsNotNull (field); - Assert.AreEqual (2, field.Constant); - - field = dang.GetField ("Dong"); - Assert.IsNotNull (field); - Assert.AreEqual (12, field.Constant); - } - - [TestModule ("marshal.dll")] - public void MarshalAsFixedStr (ModuleDefinition module) - { - var boc = module.GetType ("Boc"); - var field = boc.GetField ("a"); - - Assert.IsNotNull (field); - - Assert.IsTrue (field.HasMarshalInfo); - - var info = (FixedSysStringMarshalInfo) field.MarshalInfo; - - Assert.AreEqual (42, info.Size); - } - - [TestModule ("marshal.dll")] - public void MarshalAsFixedArray (ModuleDefinition module) - { - var boc = module.GetType ("Boc"); - var field = boc.GetField ("b"); - - Assert.IsNotNull (field); - - Assert.IsTrue (field.HasMarshalInfo); - - var info = (FixedArrayMarshalInfo) field.MarshalInfo; - - Assert.AreEqual (12, info.Size); - Assert.AreEqual (NativeType.Boolean, info.ElementType); - } - static TypeDefinition GetPrivateImplementationType (ModuleDefinition module) { foreach (var type in module.Types) diff --git a/external/cecil/Test/Mono.Cecil.Tests/Formatter.cs b/external/cecil/Test/Mono.Cecil.Tests/Formatter.cs index a7e1c8704a..1af56df948 100644 --- a/external/cecil/Test/Mono.Cecil.Tests/Formatter.cs +++ b/external/cecil/Test/Mono.Cecil.Tests/Formatter.cs @@ -28,7 +28,7 @@ namespace Mono.Cecil.Tests { WriteVariables (writer, body); foreach (Instruction instruction in body.Instructions) { - var sequence_point = instruction.SequencePoint; + var sequence_point = body.Method.DebugInformation.GetSequencePoint (instruction); if (sequence_point != null) { writer.Write ('\t'); WriteSequencePoint (writer, sequence_point); @@ -56,11 +56,20 @@ namespace Mono.Cecil.Tests { var variable = variables [i]; - writer.Write ("{0} {1}", variable.VariableType, variable); + writer.Write ("{0} {1}", variable.VariableType, GetVariableName (variable, body)); } writer.WriteLine (")"); } + static string GetVariableName (VariableDefinition variable, MethodBody body) + { + string name; + if (body.Method.DebugInformation.TryGetName (variable, out name)) + return name; + + return variable.ToString (); + } + static void WriteInstruction (TextWriter writer, Instruction instruction) { writer.Write (FormatLabel (instruction.Offset)); diff --git a/external/cecil/Test/Mono.Cecil.Tests/ImageReadTests.cs b/external/cecil/Test/Mono.Cecil.Tests/ImageReadTests.cs index 8f68e5fc8f..368c76040e 100644 --- a/external/cecil/Test/Mono.Cecil.Tests/ImageReadTests.cs +++ b/external/cecil/Test/Mono.Cecil.Tests/ImageReadTests.cs @@ -15,130 +15,169 @@ namespace Mono.Cecil.Tests { [Test] public void ImageSections () { - var image = GetResourceImage ("hello.exe"); - - Assert.AreEqual (3, image.Sections.Length); - Assert.AreEqual (".text", image.Sections [0].Name); - Assert.AreEqual (".rsrc", image.Sections [1].Name); - Assert.AreEqual (".reloc", image.Sections [2].Name); + using (var image = GetResourceImage ("hello.exe")) { + Assert.AreEqual (3, image.Sections.Length); + Assert.AreEqual (".text", image.Sections [0].Name); + Assert.AreEqual (".rsrc", image.Sections [1].Name); + Assert.AreEqual (".reloc", image.Sections [2].Name); + } } [Test] public void ImageMetadataVersion () { - var image = GetResourceImage ("hello.exe"); - Assert.AreEqual (TargetRuntime.Net_2_0, image.Runtime); + using (var image = GetResourceImage ("hello.exe")) + Assert.AreEqual (TargetRuntime.Net_2_0, image.RuntimeVersion.ParseRuntime ()); - image = GetResourceImage ("hello1.exe"); - Assert.AreEqual (TargetRuntime.Net_1_1, image.Runtime); + using (var image = GetResourceImage ("hello1.exe")) + Assert.AreEqual (TargetRuntime.Net_1_1, image.RuntimeVersion.ParseRuntime ()); } [Test] public void ImageModuleKind () { - var image = GetResourceImage ("hello.exe"); - Assert.AreEqual (ModuleKind.Console, image.Kind); + using (var image = GetResourceImage ("hello.exe")) + Assert.AreEqual (ModuleKind.Console, image.Kind); - image = GetResourceImage ("libhello.dll"); - Assert.AreEqual (ModuleKind.Dll, image.Kind); + using (var image = GetResourceImage ("libhello.dll")) + Assert.AreEqual (ModuleKind.Dll, image.Kind); - image = GetResourceImage ("hellow.exe"); - Assert.AreEqual (ModuleKind.Windows, image.Kind); + using (var image = GetResourceImage ("hellow.exe")) + Assert.AreEqual (ModuleKind.Windows, image.Kind); } [Test] public void MetadataHeaps () { - var image = GetResourceImage ("hello.exe"); + using (var image = GetResourceImage ("hello.exe")) { + Assert.IsNotNull (image.TableHeap); - Assert.IsNotNull (image.TableHeap); + Assert.IsNotNull (image.StringHeap); + Assert.AreEqual (string.Empty, image.StringHeap.Read (0)); + Assert.AreEqual ("", image.StringHeap.Read (1)); - Assert.IsNotNull (image.StringHeap); - Assert.AreEqual (string.Empty, image.StringHeap.Read (0)); - Assert.AreEqual ("", image.StringHeap.Read (1)); + Assert.IsNotNull (image.UserStringHeap); + Assert.AreEqual (string.Empty, image.UserStringHeap.Read (0)); + Assert.AreEqual ("Hello Cecil World !", image.UserStringHeap.Read (1)); - Assert.IsNotNull (image.UserStringHeap); - Assert.AreEqual (string.Empty, image.UserStringHeap.Read (0)); - Assert.AreEqual ("Hello Cecil World !", image.UserStringHeap.Read (1)); + Assert.IsNotNull (image.GuidHeap); + Assert.AreEqual (new Guid (), image.GuidHeap.Read (0)); + Assert.AreEqual (new Guid ("C3BC2BD3-2576-4D00-A80E-465B5632415F"), image.GuidHeap.Read (1)); - Assert.IsNotNull (image.GuidHeap); - Assert.AreEqual (new Guid (), image.GuidHeap.Read (0)); - Assert.AreEqual (new Guid ("C3BC2BD3-2576-4D00-A80E-465B5632415F"), image.GuidHeap.Read (1)); - - Assert.IsNotNull (image.BlobHeap); - Assert.AreEqual (new byte [0], image.BlobHeap.Read (0)); + Assert.IsNotNull (image.BlobHeap); + Assert.AreEqual (new byte [0], image.BlobHeap.Read (0)); + } } [Test] public void TablesHeap () { - var image = GetResourceImage ("hello.exe"); - var heap = image.TableHeap; + using (var image = GetResourceImage ("hello.exe")) { + var heap = image.TableHeap; - Assert.IsNotNull (heap); + Assert.IsNotNull (heap); - Assert.AreEqual (1, heap [Table.Module].Length); - Assert.AreEqual (4, heap [Table.TypeRef].Length); - Assert.AreEqual (2, heap [Table.TypeDef].Length); - Assert.AreEqual (0, heap [Table.Field].Length); - Assert.AreEqual (2, heap [Table.Method].Length); - Assert.AreEqual (4, heap [Table.MemberRef].Length); - Assert.AreEqual (2, heap [Table.CustomAttribute].Length); - Assert.AreEqual (1, heap [Table.Assembly].Length); - Assert.AreEqual (1, heap [Table.AssemblyRef].Length); + Assert.AreEqual (1, heap [Table.Module].Length); + Assert.AreEqual (4, heap [Table.TypeRef].Length); + Assert.AreEqual (2, heap [Table.TypeDef].Length); + Assert.AreEqual (0, heap [Table.Field].Length); + Assert.AreEqual (2, heap [Table.Method].Length); + Assert.AreEqual (4, heap [Table.MemberRef].Length); + Assert.AreEqual (2, heap [Table.CustomAttribute].Length); + Assert.AreEqual (1, heap [Table.Assembly].Length); + Assert.AreEqual (1, heap [Table.AssemblyRef].Length); + } } - [TestModule ("hello.x64.exe")] - public void X64Module (ModuleDefinition module) + [Test] + public void X64Module () { - Assert.AreEqual (TargetArchitecture.AMD64, module.Image.Architecture); - Assert.AreEqual (ModuleAttributes.ILOnly, module.Image.Attributes); + TestModule ("hello.x64.exe", module => { + Assert.AreEqual (TargetArchitecture.AMD64, module.Image.Architecture); + Assert.AreEqual (ModuleAttributes.ILOnly, module.Image.Attributes); + }, verify: !Platform.OnMono); } - [TestModule ("hello.ia64.exe")] - public void IA64Module (ModuleDefinition module) + [Test] + public void X64ModuleTextOnlySection () { - Assert.AreEqual (TargetArchitecture.IA64, module.Image.Architecture); - Assert.AreEqual (ModuleAttributes.ILOnly, module.Image.Attributes); + TestModule ("hello.textonly.x64.exe", module => { + Assert.AreEqual (TargetArchitecture.AMD64, module.Image.Architecture); + Assert.AreEqual (ModuleAttributes.ILOnly, module.Image.Attributes); + }, verify: !Platform.OnMono); } - [TestModule ("hello.x86.exe")] - public void X86Module (ModuleDefinition module) + [Test] + public void IA64Module () { - Assert.AreEqual (TargetArchitecture.I386, module.Image.Architecture); - Assert.AreEqual (ModuleAttributes.ILOnly | ModuleAttributes.Required32Bit, module.Image.Attributes); + TestModule ("hello.ia64.exe", module => { + Assert.AreEqual (TargetArchitecture.IA64, module.Image.Architecture); + Assert.AreEqual (ModuleAttributes.ILOnly, module.Image.Attributes); + }, verify: !Platform.OnMono); } - [TestModule ("hello.anycpu.exe")] - public void AnyCpuModule (ModuleDefinition module) + [Test] + public void X86Module () { - Assert.AreEqual (TargetArchitecture.I386, module.Image.Architecture); - Assert.AreEqual (ModuleAttributes.ILOnly, module.Image.Attributes); + TestModule ("hello.x86.exe", module => { + Assert.AreEqual (TargetArchitecture.I386, module.Image.Architecture); + Assert.AreEqual (ModuleAttributes.ILOnly | ModuleAttributes.Required32Bit, module.Image.Attributes); + }); } - [TestModule ("delay-signed.dll")] - public void DelaySignedAssembly (ModuleDefinition module) + [Test] + public void AnyCpuModule () { - Assert.IsNotNull (module.Assembly.Name.PublicKey); - Assert.AreNotEqual (0, module.Assembly.Name.PublicKey.Length); - Assert.AreNotEqual (ModuleAttributes.StrongNameSigned, module.Attributes & ModuleAttributes.StrongNameSigned); - Assert.AreNotEqual (0, module.Image.StrongName.VirtualAddress); - Assert.AreNotEqual (0, module.Image.StrongName.Size); + TestModule ("hello.anycpu.exe", module => { + Assert.AreEqual (TargetArchitecture.I386, module.Image.Architecture); + Assert.AreEqual (ModuleAttributes.ILOnly, module.Image.Attributes); + }); } - [TestModule ("wp7.dll", Verify = false)] - public void WindowsPhoneNonSignedAssembly (ModuleDefinition module) + [Test] + public void DelaySignedAssembly () { - Assert.AreEqual (0, module.Assembly.Name.PublicKey.Length); - Assert.AreNotEqual (ModuleAttributes.StrongNameSigned, module.Attributes & ModuleAttributes.StrongNameSigned); - Assert.AreEqual (0, module.Image.StrongName.VirtualAddress); - Assert.AreEqual (0, module.Image.StrongName.Size); + TestModule ("delay-signed.dll", module => { + Assert.IsNotNull (module.Assembly.Name.PublicKey); + Assert.AreNotEqual (0, module.Assembly.Name.PublicKey.Length); + Assert.AreNotEqual (ModuleAttributes.StrongNameSigned, module.Attributes & ModuleAttributes.StrongNameSigned); + Assert.AreNotEqual (0, module.Image.StrongName.VirtualAddress); + Assert.AreNotEqual (0, module.Image.StrongName.Size); + }); } - [TestModule ("metro.exe", Verify = false)] - public void MetroAssembly (ModuleDefinition module) + [Test] + public void WindowsPhoneNonSignedAssembly () { - Assert.AreEqual (ModuleCharacteristics.AppContainer, module.Characteristics & ModuleCharacteristics.AppContainer); + TestModule ("wp7.dll", module => { + Assert.AreEqual (0, module.Assembly.Name.PublicKey.Length); + Assert.AreNotEqual (ModuleAttributes.StrongNameSigned, module.Attributes & ModuleAttributes.StrongNameSigned); + Assert.AreEqual (0, module.Image.StrongName.VirtualAddress); + Assert.AreEqual (0, module.Image.StrongName.Size); + }, verify: false); + } + + [Test] + public void MetroAssembly () + { + if (Platform.OnMono) + return; + + TestModule ("metro.exe", module => { + Assert.AreEqual (ModuleCharacteristics.AppContainer, module.Characteristics & ModuleCharacteristics.AppContainer); + }, verify: false); + } + + [Test] + public void WindowsRuntimeComponentAssembly () + { + var resolver = WindowsRuntimeAssemblyResolver.CreateInstance (); + if (resolver == null) + return; + + TestModule("winrtcomp.winmd", module => { + Assert.IsTrue (module.Assembly.Name.IsWindowsRuntime); + }, verify: false, assemblyResolver: resolver); } } } diff --git a/external/cecil/Test/Mono.Cecil.Tests/ImportCecilTests.cs b/external/cecil/Test/Mono.Cecil.Tests/ImportCecilTests.cs index ae9a8551b9..299948f3b1 100644 --- a/external/cecil/Test/Mono.Cecil.Tests/ImportCecilTests.cs +++ b/external/cecil/Test/Mono.Cecil.Tests/ImportCecilTests.cs @@ -29,10 +29,10 @@ namespace Mono.Cecil.Tests { type.Methods.Add (method_by_ref); - method_by_ref.MethodReturnType.ReturnType = module.Import (typeof (void).ToDefinition ()); + method_by_ref.MethodReturnType.ReturnType = module.ImportReference (typeof (void).ToDefinition ()); - method_by_ref.Parameters.Add (new ParameterDefinition (module.Import (typeof (string).ToDefinition ()))); - method_by_ref.Parameters.Add (new ParameterDefinition (module.Import (new ByReferenceType (typeof (string).ToDefinition ())))); + method_by_ref.Parameters.Add (new ParameterDefinition (module.ImportReference (typeof (string).ToDefinition ()))); + method_by_ref.Parameters.Add (new ParameterDefinition (module.ImportReference (new ByReferenceType (typeof (string).ToDefinition ())))); var m_il = method_by_ref.Body.GetILProcessor (); m_il.Emit (OpCodes.Ldarg_1); @@ -40,7 +40,7 @@ namespace Mono.Cecil.Tests { m_il.Emit (OpCodes.Stind_Ref); m_il.Emit (OpCodes.Ret); - var v_0 = new VariableDefinition (module.Import (typeof (string).ToDefinition ())); + var v_0 = new VariableDefinition (module.ImportReference (typeof (string).ToDefinition ())); body.Variables.Add (v_0); var il = body.GetILProcessor (); @@ -75,7 +75,7 @@ namespace Mono.Cecil.Tests { { var get_empty = Compile> ((module, body) => { var il = body.GetILProcessor (); - il.Emit (OpCodes.Ldsfld, module.Import (typeof (string).GetField ("Empty").ToDefinition ())); + il.Emit (OpCodes.Ldsfld, module.ImportReference (typeof (string).GetField ("Empty").ToDefinition ())); il.Emit (OpCodes.Ret); }); @@ -89,7 +89,7 @@ namespace Mono.Cecil.Tests { var il = body.GetILProcessor (); il.Emit (OpCodes.Ldarg_0); il.Emit (OpCodes.Ldarg_1); - il.Emit (OpCodes.Call, module.Import (typeof (string).GetMethod ("Concat", new [] { typeof (string), typeof (string) }).ToDefinition ())); + il.Emit (OpCodes.Call, module.ImportReference (typeof (string).GetMethod ("Concat", new [] { typeof (string), typeof (string) }).ToDefinition ())); il.Emit (OpCodes.Ret); }); @@ -119,12 +119,12 @@ namespace Mono.Cecil.Tests { public void ImportGenericField () { var get_field = Compile, string>> ((module, body) => { - var generic_def = module.Import (typeof (Generic<>)).Resolve (); + var generic_def = module.ImportReference (typeof (Generic<>)).Resolve (); var field_def = generic_def.Fields.Where (f => f.Name == "Field").First (); - var field_string = field_def.MakeGeneric (module.Import (typeof (string))); + var field_string = field_def.MakeGeneric (module.ImportReference (typeof (string))); - var field_ref = module.Import (field_string); + var field_ref = module.ImportReference (field_string); var il = body.GetILProcessor (); il.Emit (OpCodes.Ldarg_0); @@ -143,11 +143,11 @@ namespace Mono.Cecil.Tests { public void ImportGenericMethod () { var generic_identity = Compile, int, int>> ((module, body) => { - var generic_def = module.Import (typeof (Generic<>)).Resolve (); + var generic_def = module.ImportReference (typeof (Generic<>)).Resolve (); var method_def = generic_def.Methods.Where (m => m.Name == "Method").First (); - var method_int = method_def.MakeGeneric (module.Import (typeof (int))); - var method_ref = module.Import (method_int); + var method_int = method_def.MakeGeneric (module.ImportReference (typeof (int))); + var method_ref = module.ImportReference (method_int); var il = body.GetILProcessor (); il.Emit (OpCodes.Ldarg_0); @@ -163,14 +163,14 @@ namespace Mono.Cecil.Tests { public void ImportGenericMethodSpec () { var gen_spec_id = Compile, int, int>> ((module, body) => { - var generic_def = module.Import (typeof (Generic<>)).Resolve (); + var generic_def = module.ImportReference (typeof (Generic<>)).Resolve (); var method_def = generic_def.Methods.Where (m => m.Name == "GenericMethod").First (); - var method_string = method_def.MakeGeneric (module.Import (typeof (string))); + var method_string = method_def.MakeGeneric (module.ImportReference (typeof (string))); - var method_instance = method_string.MakeGenericMethod (module.Import (typeof (int))); + var method_instance = method_string.MakeGenericMethod (module.ImportReference (typeof (int))); - var method_ref = module.Import (method_instance); + var method_ref = module.ImportReference (method_instance); var il = body.GetILProcessor (); il.Emit (OpCodes.Ldarg_0); @@ -187,16 +187,16 @@ namespace Mono.Cecil.Tests { public void ImportComplexGenericMethodSpec () { var gen_spec_id = Compile, int, int>> ((module, body) => { - var generic_def = module.Import (typeof (Generic<>)).Resolve (); + var generic_def = module.ImportReference (typeof (Generic<>)).Resolve (); var method_def = generic_def.Methods.Where (m => m.Name == "ComplexGenericMethod").First (); - var method_string = method_def.MakeGeneric (module.Import (typeof (string))); - var method_instance = method_string.MakeGenericMethod (module.Import (typeof (int))); - var method_ref = module.Import (method_instance); + var method_string = method_def.MakeGeneric (module.ImportReference (typeof (string))); + var method_instance = method_string.MakeGenericMethod (module.ImportReference (typeof (int))); + var method_ref = module.ImportReference (method_instance); var field_def = generic_def.Fields.Where (f => f.Name == "Field").First (); - var field_int = field_def.MakeGeneric (module.Import (typeof (int))); - var field_ref = module.Import (field_int); + var field_int = field_def.MakeGeneric (module.ImportReference (typeof (int))); + var field_ref = module.ImportReference (field_int); var il = body.GetILProcessor (); il.Emit (OpCodes.Ldarg_0); @@ -214,11 +214,11 @@ namespace Mono.Cecil.Tests { public void ImportMethodOnOpenGeneric () { var generic = typeof (Generic<>).ToDefinition (); - var module = ModuleDefinition.CreateModule ("foo", ModuleKind.Dll); - var method = module.Import (generic.GetMethod ("Method")); - - Assert.AreEqual ("T Mono.Cecil.Tests.ImportCecilTests/Generic`1::Method(T)", method.FullName); + using (var module = ModuleDefinition.CreateModule ("foo", ModuleKind.Dll)) { + var method = module.ImportReference (generic.GetMethod ("Method")); + Assert.AreEqual ("T Mono.Cecil.Tests.ImportCecilTests/Generic`1::Method(T)", method.FullName); + } } public class ContextGeneric1Method2 @@ -258,29 +258,29 @@ namespace Mono.Cecil.Tests { // by mixing open generics with 2 & 1 parameters, we make sure the right context is used (because otherwise, an exception will be thrown) var type = typeof (ContextGeneric1Method2<>).MakeGenericType (typeof (ContextGeneric2Method1<,>)); var meth = type.GetMethod ("GenericMethod"); - var imported_type = module.Import (type); - var method = module.Import (meth, imported_type); + var imported_type = module.ImportReference (type); + var method = module.ImportReference (meth, imported_type); Assert.AreEqual ("G1 Mono.Cecil.Tests.ImportCecilTests/ContextGeneric1Method2`1>::GenericMethod(R1,S1)", method.FullName); // and the other way around type = typeof (ContextGeneric2Method1<,>).MakeGenericType (typeof (ContextGeneric1Method2<>), typeof (IList<>)); meth = type.GetMethod ("GenericMethod"); - imported_type = module.Import (type); - method = module.Import (meth, imported_type); + imported_type = module.ImportReference (type); + method = module.ImportReference (meth, imported_type); Assert.AreEqual ("R2 Mono.Cecil.Tests.ImportCecilTests/ContextGeneric2Method1`2,System.Collections.Generic.IList`1>::GenericMethod(G2,H2)", method.FullName); // not sure about this one type = typeof (NestedGenericsA.NestedGenericsB.NestedGenericsC); meth = type.GetMethod ("GenericMethod"); - imported_type = module.Import (type); - method = module.Import (meth, imported_type); + imported_type = module.ImportReference (type); + method = module.ImportReference (meth, imported_type); Assert.AreEqual ("A Mono.Cecil.Tests.ImportCecilTests/NestedGenericsA`1/NestedGenericsB`1/NestedGenericsC`1::GenericMethod(B,C)", method.FullName); // We need both the method & type ! type = typeof (Generic<>).MakeGenericType (typeof (string)); meth = type.GetMethod ("ComplexGenericMethod"); - imported_type = module.Import (type); - method = module.Import (meth, imported_type); + imported_type = module.ImportReference (type); + method = module.ImportReference (meth, imported_type); Assert.AreEqual ("Mono.Cecil.Tests.ImportCecilTests/Generic`1 Mono.Cecil.Tests.ImportCecilTests/Generic`1::ComplexGenericMethod(T,TS)", method.FullName); } @@ -326,7 +326,7 @@ namespace Mono.Cecil.Tests { "", name, TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.Abstract, - module.Import (typeof (object))); + module.ImportReference (typeof (object))); module.Types.Add (type); @@ -349,10 +349,10 @@ namespace Mono.Cecil.Tests { type.Methods.Add (method); - method.MethodReturnType.ReturnType = module.Import (pattern.ReturnType); + method.MethodReturnType.ReturnType = module.ImportReference (pattern.ReturnType); foreach (var parameter_pattern in pattern.GetParameters ()) - method.Parameters.Add (new ParameterDefinition (module.Import (parameter_pattern.ParameterType))); + method.Parameters.Add (new ParameterDefinition (module.ImportReference (parameter_pattern.ParameterType))); return method; } diff --git a/external/cecil/Test/Mono.Cecil.Tests/ImportReflectionTests.cs b/external/cecil/Test/Mono.Cecil.Tests/ImportReflectionTests.cs index 6ded91c92d..65a1f1a2e6 100644 --- a/external/cecil/Test/Mono.Cecil.Tests/ImportReflectionTests.cs +++ b/external/cecil/Test/Mono.Cecil.Tests/ImportReflectionTests.cs @@ -54,10 +54,10 @@ namespace Mono.Cecil.Tests { type.Methods.Add (method_by_ref); - method_by_ref.MethodReturnType.ReturnType = module.Import (typeof (void)); + method_by_ref.MethodReturnType.ReturnType = module.ImportReference (typeof (void)); - method_by_ref.Parameters.Add (new ParameterDefinition (module.Import (typeof (string)))); - method_by_ref.Parameters.Add (new ParameterDefinition (module.Import (typeof (string).MakeByRefType ()))); + method_by_ref.Parameters.Add (new ParameterDefinition (module.ImportReference (typeof (string)))); + method_by_ref.Parameters.Add (new ParameterDefinition (module.ImportReference (typeof (string).MakeByRefType ()))); var m_il = method_by_ref.Body.GetILProcessor (); m_il.Emit (OpCodes.Ldarg_1); @@ -65,7 +65,7 @@ namespace Mono.Cecil.Tests { m_il.Emit (OpCodes.Stind_Ref); m_il.Emit (OpCodes.Ret); - var v_0 = new VariableDefinition (module.Import (typeof (string))); + var v_0 = new VariableDefinition (module.ImportReference (typeof (string))); body.Variables.Add (v_0); var il = body.GetILProcessor (); @@ -100,7 +100,7 @@ namespace Mono.Cecil.Tests { { var get_empty = Compile> ((module, body) => { var il = body.GetILProcessor (); - il.Emit (OpCodes.Ldsfld, module.Import (typeof (string).GetField ("Empty"))); + il.Emit (OpCodes.Ldsfld, module.ImportReference (typeof (string).GetField ("Empty"))); il.Emit (OpCodes.Ret); }); @@ -114,13 +114,25 @@ namespace Mono.Cecil.Tests { var il = body.GetILProcessor (); il.Emit (OpCodes.Ldarg_0); il.Emit (OpCodes.Ldarg_1); - il.Emit (OpCodes.Call, module.Import (typeof (string).GetMethod ("Concat", new [] { typeof (string), typeof (string) }))); + il.Emit (OpCodes.Call, module.ImportReference (typeof (string).GetMethod ("Concat", new [] { typeof (string), typeof (string) }))); il.Emit (OpCodes.Ret); }); Assert.AreEqual ("FooBar", concat ("Foo", "Bar")); } + [Test] + public void GeneratedAssemblyCulture () + { + var id = Compile> ((module, body) => { + var il = body.GetILProcessor (); + il.Emit (OpCodes.Ldarg_0); + il.Emit (OpCodes.Ret); + }); + + Assert.AreEqual ("", id.Method.DeclaringType.Assembly.GetName ().CultureInfo.Name); + } + public class Generic { public T Field; @@ -146,7 +158,7 @@ namespace Mono.Cecil.Tests { var get_field = Compile, string>> ((module, body) => { var il = body.GetILProcessor (); il.Emit (OpCodes.Ldarg_0); - il.Emit (OpCodes.Ldfld, module.Import (typeof (Generic).GetField ("Field"))); + il.Emit (OpCodes.Ldfld, module.ImportReference (typeof (Generic).GetField ("Field"))); il.Emit (OpCodes.Ret); }); @@ -164,7 +176,7 @@ namespace Mono.Cecil.Tests { var il = body.GetILProcessor (); il.Emit (OpCodes.Ldarg_0); il.Emit (OpCodes.Ldarg_1); - il.Emit (OpCodes.Callvirt, module.Import (typeof (Generic).GetMethod ("Method"))); + il.Emit (OpCodes.Callvirt, module.ImportReference (typeof (Generic).GetMethod ("Method"))); il.Emit (OpCodes.Ret); }); @@ -179,7 +191,7 @@ namespace Mono.Cecil.Tests { il.Emit (OpCodes.Ldarg_0); il.Emit (OpCodes.Ldnull); il.Emit (OpCodes.Ldarg_1); - il.Emit (OpCodes.Callvirt, module.Import (typeof (Generic).GetMethod ("GenericMethod").MakeGenericMethod (typeof (int)))); + il.Emit (OpCodes.Callvirt, module.ImportReference (typeof (Generic).GetMethod ("GenericMethod").MakeGenericMethod (typeof (int)))); il.Emit (OpCodes.Ret); }); @@ -194,8 +206,8 @@ namespace Mono.Cecil.Tests { il.Emit (OpCodes.Ldarg_0); il.Emit (OpCodes.Ldnull); il.Emit (OpCodes.Ldarg_1); - il.Emit (OpCodes.Callvirt, module.Import (typeof (Generic).GetMethod ("ComplexGenericMethod").MakeGenericMethod (typeof (int)))); - il.Emit (OpCodes.Ldfld, module.Import (typeof (Generic).GetField ("Field"))); + il.Emit (OpCodes.Callvirt, module.ImportReference (typeof (Generic).GetMethod ("ComplexGenericMethod").MakeGenericMethod (typeof (int)))); + il.Emit (OpCodes.Ldfld, module.ImportReference (typeof (Generic).GetField ("Field"))); il.Emit (OpCodes.Ret); }); @@ -209,13 +221,13 @@ namespace Mono.Cecil.Tests { [Test] public void ImportGenericTypeDefOrOpen () { - var module = typeof (Foo<>).ToDefinition ().Module; + using (var module = typeof (Foo<>).ToDefinition ().Module) { + var foo_def = module.ImportReference (typeof (Foo<>)); + var foo_open = module.ImportReference (typeof (Foo<>), foo_def); - var foo_def = module.Import (typeof (Foo<>)); - var foo_open = module.Import (typeof (Foo<>), foo_def); - - Assert.AreEqual ("Mono.Cecil.Tests.ImportReflectionTests/Foo`1", foo_def.FullName); - Assert.AreEqual ("Mono.Cecil.Tests.ImportReflectionTests/Foo`1", foo_open.FullName); + Assert.AreEqual ("Mono.Cecil.Tests.ImportReflectionTests/Foo`1", foo_def.FullName); + Assert.AreEqual ("Mono.Cecil.Tests.ImportReflectionTests/Foo`1", foo_open.FullName); + } } [Test] @@ -225,12 +237,12 @@ namespace Mono.Cecil.Tests { var generic_list_foo_open = typeof (Generic<>).MakeGenericType (list_foo); var foo_def = typeof (Foo<>).ToDefinition (); - var module = foo_def.Module; + using (var module = foo_def.Module) { + var generic_foo = module.ImportReference (generic_list_foo_open, foo_def); - var generic_foo = module.Import (generic_list_foo_open, foo_def); - - Assert.AreEqual ("Mono.Cecil.Tests.ImportReflectionTests/Generic`1>", - generic_foo.FullName); + Assert.AreEqual ("Mono.Cecil.Tests.ImportReflectionTests/Generic`1>", + generic_foo.FullName); + } } [Test] @@ -240,12 +252,12 @@ namespace Mono.Cecil.Tests { var generic_foo_open = typeof (Generic<>).MakeGenericType (foo_open); var foo_def = typeof (Foo<>).ToDefinition (); - var module = foo_def.Module; + using (var module = foo_def.Module) { + var generic_foo = module.ImportReference (generic_foo_open, foo_def); - var generic_foo = module.Import (generic_foo_open, foo_def); - - Assert.AreEqual ("Mono.Cecil.Tests.ImportReflectionTests/Generic`1>", - generic_foo.FullName); + Assert.AreEqual ("Mono.Cecil.Tests.ImportReflectionTests/Generic`1>", + generic_foo.FullName); + } } [Test] @@ -255,12 +267,12 @@ namespace Mono.Cecil.Tests { var foo_open_array = foo_open.MakeArrayType (); var foo_def = typeof (Foo<>).ToDefinition (); - var module = foo_def.Module; + using (var module = foo_def.Module) { + var array_foo = module.ImportReference (foo_open_array, foo_def); - var array_foo = module.Import (foo_open_array, foo_def); - - Assert.AreEqual ("Mono.Cecil.Tests.ImportReflectionTests/Foo`1[]", - array_foo.FullName); + Assert.AreEqual ("Mono.Cecil.Tests.ImportReflectionTests/Foo`1[]", + array_foo.FullName); + } } [Test] @@ -271,12 +283,12 @@ namespace Mono.Cecil.Tests { var generic_list_foo_open_field = generic_list_foo_open.GetField ("Field"); var foo_def = typeof (Foo<>).ToDefinition (); - var module = foo_def.Module; + using (var module = foo_def.Module) { + var generic_field = module.ImportReference (generic_list_foo_open_field, foo_def); - var generic_field = module.Import (generic_list_foo_open_field, foo_def); - - Assert.AreEqual ("T Mono.Cecil.Tests.ImportReflectionTests/Generic`1>::Field", - generic_field.FullName); + Assert.AreEqual ("T Mono.Cecil.Tests.ImportReflectionTests/Generic`1>::Field", + generic_field.FullName); + } } [Test] @@ -287,36 +299,36 @@ namespace Mono.Cecil.Tests { var generic_list_foo_open_method = generic_list_foo_open.GetMethod ("Method"); var foo_def = typeof (Foo<>).ToDefinition (); - var module = foo_def.Module; + using (var module = foo_def.Module) { + var generic_method = module.ImportReference (generic_list_foo_open_method, foo_def); - var generic_method = module.Import (generic_list_foo_open_method, foo_def); - - Assert.AreEqual ("T Mono.Cecil.Tests.ImportReflectionTests/Generic`1>::Method(T)", - generic_method.FullName); + Assert.AreEqual ("T Mono.Cecil.Tests.ImportReflectionTests/Generic`1>::Method(T)", + generic_method.FullName); + } } [Test] public void ImportMethodOnOpenGenericType () { - var module = typeof (Generic<>).ToDefinition ().Module; + using (var module = typeof (Generic<>).ToDefinition ().Module) { + var method = module.ImportReference (typeof (Generic<>).GetMethod ("Method")); - var method = module.Import (typeof (Generic<>).GetMethod ("Method")); - - Assert.AreEqual ("T Mono.Cecil.Tests.ImportReflectionTests/Generic`1::Method(T)", method.FullName); + Assert.AreEqual ("T Mono.Cecil.Tests.ImportReflectionTests/Generic`1::Method(T)", method.FullName); + } } [Test] public void ImportGenericMethodOnOpenGenericType () { - var module = typeof (Generic<>).ToDefinition ().Module; + using (var module = typeof (Generic<>).ToDefinition ().Module) { + var generic_method = module.ImportReference (typeof (Generic<>).GetMethod ("GenericMethod")); - var generic_method = module.Import (typeof (Generic<>).GetMethod ("GenericMethod")); + Assert.AreEqual ("TS Mono.Cecil.Tests.ImportReflectionTests/Generic`1::GenericMethod(T,TS)", generic_method.FullName); - Assert.AreEqual ("TS Mono.Cecil.Tests.ImportReflectionTests/Generic`1::GenericMethod(T,TS)", generic_method.FullName); + generic_method = module.ImportReference (typeof (Generic<>).GetMethod ("GenericMethod"), generic_method); - generic_method = module.Import (typeof (Generic<>).GetMethod ("GenericMethod"), generic_method); - - Assert.AreEqual ("TS Mono.Cecil.Tests.ImportReflectionTests/Generic`1::GenericMethod(T,TS)", generic_method.FullName); + Assert.AreEqual ("TS Mono.Cecil.Tests.ImportReflectionTests/Generic`1::GenericMethod(T,TS)", generic_method.FullName); + } } delegate void Emitter (ModuleDefinition module, MethodBody body); @@ -361,7 +373,7 @@ namespace Mono.Cecil.Tests { "", name, TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.Abstract, - module.Import (typeof (object))); + module.ImportReference (typeof (object))); module.Types.Add (type); @@ -384,10 +396,10 @@ namespace Mono.Cecil.Tests { type.Methods.Add (method); - method.MethodReturnType.ReturnType = module.Import (pattern.ReturnType); + method.MethodReturnType.ReturnType = module.ImportReference (pattern.ReturnType); foreach (var parameter_pattern in pattern.GetParameters ()) - method.Parameters.Add (new ParameterDefinition (module.Import (parameter_pattern.ParameterType))); + method.Parameters.Add (new ParameterDefinition (module.ImportReference (parameter_pattern.ParameterType))); return method; } diff --git a/external/cecil/Test/Mono.Cecil.Tests/MethodBodyTests.cs b/external/cecil/Test/Mono.Cecil.Tests/MethodBodyTests.cs index 5258305a91..62ae1ccc46 100644 --- a/external/cecil/Test/Mono.Cecil.Tests/MethodBodyTests.cs +++ b/external/cecil/Test/Mono.Cecil.Tests/MethodBodyTests.cs @@ -11,17 +11,18 @@ namespace Mono.Cecil.Tests { [TestFixture] public class MethodBodyTests : BaseTestFixture { - [TestIL ("hello.il")] - public void MultiplyMethod (ModuleDefinition module) + [Test] + public void MultiplyMethod () { - var foo = module.GetType ("Foo"); - Assert.IsNotNull (foo); + TestIL ("hello.il", module => { + var foo = module.GetType ("Foo"); + Assert.IsNotNull (foo); - var bar = foo.GetMethod ("Bar"); - Assert.IsNotNull (bar); - Assert.IsTrue (bar.IsIL); + var bar = foo.GetMethod ("Bar"); + Assert.IsNotNull (bar); + Assert.IsTrue (bar.IsIL); - AssertCode (@" + AssertCode (@" .locals init (System.Int32 V_0) IL_0000: ldarg.0 IL_0001: ldarg.1 @@ -31,35 +32,39 @@ namespace Mono.Cecil.Tests { IL_0005: call System.Void Foo::Baz(System.Int32) IL_000a: ret ", bar); + }); } - [TestIL ("hello.il")] - public void PrintStringEmpty (ModuleDefinition module) + [Test] + public void PrintStringEmpty () { - var foo = module.GetType ("Foo"); - Assert.IsNotNull (foo); + TestIL ("hello.il", module => { + var foo = module.GetType ("Foo"); + Assert.IsNotNull (foo); - var print_empty = foo.GetMethod ("PrintEmpty"); - Assert.IsNotNull (print_empty); + var print_empty = foo.GetMethod ("PrintEmpty"); + Assert.IsNotNull (print_empty); - AssertCode (@" + AssertCode (@" .locals () IL_0000: ldsfld System.String System.String::Empty IL_0005: call System.Void System.Console::WriteLine(System.String) IL_000a: ret ", print_empty); + }); } - [TestModule ("libhello.dll")] - public void Branch (ModuleDefinition module) + [Test] + public void Branch () { - var lib = module.GetType ("Library"); - Assert.IsNotNull (lib); + TestModule ("libhello.dll", module => { + var lib = module.GetType ("Library"); + Assert.IsNotNull (lib); - var method = lib.GetMethod ("GetHelloString"); - Assert.IsNotNull (method); + var method = lib.GetMethod ("GetHelloString"); + Assert.IsNotNull (method); - AssertCode (@" + AssertCode (@" .locals init (System.String V_0) IL_0000: nop IL_0001: ldstr ""hello world of tomorrow"" @@ -68,18 +73,20 @@ namespace Mono.Cecil.Tests { IL_0009: ldloc.0 IL_000a: ret ", method); + }); } - [TestModule ("switch.exe")] - public void Switch (ModuleDefinition module) + [Test] + public void Switch () { - var program = module.GetType ("Program"); - Assert.IsNotNull (program); + TestModule ("switch.exe", module => { + var program = module.GetType ("Program"); + Assert.IsNotNull (program); - var method = program.GetMethod ("Main"); - Assert.IsNotNull (method); + var method = program.GetMethod ("Main"); + Assert.IsNotNull (method); - AssertCode (@" + AssertCode (@" .locals init (System.Int32 V_0) IL_0000: ldarg.0 IL_0001: ldlen @@ -112,32 +119,36 @@ namespace Mono.Cecil.Tests { IL_0038: ldc.i4.s 42 IL_003a: ret ", method); + }); } - [TestIL ("methodspecs.il")] - public void MethodSpec (ModuleDefinition module) + [Test] + public void MethodSpec () { - var tamtam = module.GetType ("Tamtam"); + TestIL ("methodspecs.il", module => { + var tamtam = module.GetType ("Tamtam"); - var bar = tamtam.GetMethod ("Bar"); - Assert.IsNotNull (bar); + var bar = tamtam.GetMethod ("Bar"); + Assert.IsNotNull (bar); - AssertCode (@" + AssertCode (@" .locals () IL_0000: ldc.i4.2 IL_0001: call System.Void Tamtam::Foo(TFoo) IL_0006: ret ", bar); + }); } - [TestModule ("catch.exe")] - public void NestedTryCatchFinally (ModuleDefinition module) + [Test] + public void NestedTryCatchFinally () { - var program = module.GetType ("Program"); - var main = program.GetMethod ("Main"); - Assert.IsNotNull (main); + TestModule ("catch.exe", module => { + var program = module.GetType ("Program"); + var main = program.GetMethod ("Main"); + Assert.IsNotNull (main); - AssertCode (@" + AssertCode (@" .locals () IL_0000: call System.Void Program::Foo() IL_0005: leave.s IL_000d @@ -159,16 +170,18 @@ namespace Mono.Cecil.Tests { .try IL_0000 to IL_000f catch System.Exception handler IL_0017 to IL_001f .try IL_0000 to IL_0021 finally handler IL_0021 to IL_0027 ", main); + }); } - [TestModule ("fptr.exe", Verify = false)] - public void FunctionPointersAndCallSites (ModuleDefinition module) + [Test] + public void FunctionPointersAndCallSites () { - var type = module.Types [0]; - var start = type.GetMethod ("Start"); - Assert.IsNotNull (start); + TestModule ("fptr.exe", module => { + var type = module.Types [0]; + var start = type.GetMethod ("Start"); + Assert.IsNotNull (start); - AssertCode (@" + AssertCode (@" .locals init () IL_0000: ldc.i4.1 IL_0001: call method System.Int32 *(System.Int32) MakeDecision::Decide() @@ -184,25 +197,28 @@ namespace Mono.Cecil.Tests { IL_002b: call System.Void System.Console::WriteLine(System.Int32) IL_0030: ret ", start); + }, verify: false); } - [TestIL ("hello.il")] - public void ThisParameter (ModuleDefinition module) + [Test] + public void ThisParameter () { - var type = module.GetType ("Foo"); - var method = type.GetMethod ("Gazonk"); + TestIL ("hello.il", module => { + var type = module.GetType ("Foo"); + var method = type.GetMethod ("Gazonk"); - Assert.IsNotNull (method); + Assert.IsNotNull (method); - AssertCode (@" + AssertCode (@" .locals () IL_0000: ldarg 0 IL_0004: pop IL_0005: ret ", method); - Assert.AreEqual (method.Body.ThisParameter.ParameterType, type); - Assert.AreEqual (method.Body.ThisParameter, method.Body.Instructions [0].Operand); + Assert.AreEqual (method.Body.ThisParameter.ParameterType, type); + Assert.AreEqual (method.Body.ThisParameter, method.Body.Instructions [0].Operand); + }); } [Test] @@ -220,9 +236,9 @@ namespace Mono.Cecil.Tests { Assert.IsNotNull (int_to_string); var this_parameter_type = int_to_string.Body.ThisParameter.ParameterType; - Assert.IsTrue (this_parameter_type.IsPointer); + Assert.IsTrue (this_parameter_type.IsByReference); - var element_type = ((PointerType) this_parameter_type).ElementType; + var element_type = ((ByReferenceType) this_parameter_type).ElementType; Assert.AreEqual (int32, element_type); } @@ -234,9 +250,9 @@ namespace Mono.Cecil.Tests { Assert.IsNotNull (token_to_string); var this_parameter_type = token_to_string.Body.ThisParameter.ParameterType; - Assert.IsTrue (this_parameter_type.IsPointer); + Assert.IsTrue (this_parameter_type.IsByReference); - var element_type = ((PointerType) this_parameter_type).ElementType; + var element_type = ((ByReferenceType) this_parameter_type).ElementType; Assert.AreEqual (token, element_type); } @@ -253,45 +269,51 @@ namespace Mono.Cecil.Tests { Assert.IsFalse (type.IsPointer); } - [TestIL ("hello.il")] - public void FilterMaxStack (ModuleDefinition module) + [Test] + public void FilterMaxStack () { - var type = module.GetType ("Foo"); - var method = type.GetMethod ("TestFilter"); + TestIL ("hello.il", module => { + var type = module.GetType ("Foo"); + var method = type.GetMethod ("TestFilter"); - Assert.IsNotNull (method); - Assert.AreEqual (2, method.Body.MaxStackSize); + Assert.IsNotNull (method); + Assert.AreEqual (2, method.Body.MaxStackSize); + }); } - [TestModule ("iterator.exe")] - public void Iterator (ModuleDefinition module) + [Test] + public void Iterator () { - var method = module.GetType ("Program").GetMethod ("GetLittleArgs"); - Assert.IsNotNull (method.Body); + TestModule ("iterator.exe", module => { + var method = module.GetType ("Program").GetMethod ("GetLittleArgs"); + Assert.IsNotNull (method.Body); + }); } - [TestCSharp ("CustomAttributes.cs")] - public void LoadString (ModuleDefinition module) + [Test] + public void LoadString () { - var type = module.GetType ("FooAttribute"); - var get_fiou = type.GetMethod ("get_Fiou"); - Assert.IsNotNull (get_fiou); + TestCSharp ("CustomAttributes.cs", module => { + var type = module.GetType ("FooAttribute"); + var get_fiou = type.GetMethod ("get_Fiou"); + Assert.IsNotNull (get_fiou); - var ldstr = get_fiou.Body.Instructions.Where (i => i.OpCode == OpCodes.Ldstr).First (); - Assert.AreEqual ("fiou", ldstr.Operand); + var ldstr = get_fiou.Body.Instructions.Where (i => i.OpCode == OpCodes.Ldstr).First (); + Assert.AreEqual ("fiou", ldstr.Operand); + }); } - static void AssertCode (string expected, MethodDefinition method) + [Test] + public void UnattachedMethodBody () { - Assert.IsTrue (method.HasBody); - Assert.IsNotNull (method.Body); + var system_void = typeof (void).ToDefinition (); + var method = new MethodDefinition ("NewMethod", MethodAttributes.Assembly | MethodAttributes.Static, system_void); + var body = new MethodBody (method); + var il = body.GetILProcessor (); + il.Emit (OpCodes.Ret); + method.Body = body; - Assert.AreEqual (Normalize (expected), Normalize (Formatter.FormatMethodBody (method))); - } - - static string Normalize (string str) - { - return str.Trim ().Replace ("\r\n", "\n"); + Assert.AreEqual (body, method.Body); } [Test] diff --git a/external/cecil/Test/Mono.Cecil.Tests/MethodTests.cs b/external/cecil/Test/Mono.Cecil.Tests/MethodTests.cs index 5d4d3751a1..bbf1742d8d 100644 --- a/external/cecil/Test/Mono.Cecil.Tests/MethodTests.cs +++ b/external/cecil/Test/Mono.Cecil.Tests/MethodTests.cs @@ -11,183 +11,205 @@ namespace Mono.Cecil.Tests { [TestFixture] public class MethodTests : BaseTestFixture { - [TestCSharp ("Methods.cs")] - public void AbstractMethod (ModuleDefinition module) + [Test] + public void AbstractMethod () { - var type = module.Types [1]; - Assert.AreEqual ("Foo", type.Name); - Assert.AreEqual (2, type.Methods.Count); + TestCSharp ("Methods.cs", module => { + var type = module.Types [1]; + Assert.AreEqual ("Foo", type.Name); + Assert.AreEqual (2, type.Methods.Count); - var method = type.GetMethod ("Bar"); - Assert.AreEqual ("Bar", method.Name); - Assert.IsTrue (method.IsAbstract); - Assert.IsNotNull (method.ReturnType); + var method = type.GetMethod ("Bar"); + Assert.AreEqual ("Bar", method.Name); + Assert.IsTrue (method.IsAbstract); + Assert.IsNotNull (method.ReturnType); - Assert.AreEqual (1, method.Parameters.Count); + Assert.AreEqual (1, method.Parameters.Count); - var parameter = method.Parameters [0]; + var parameter = method.Parameters [0]; - Assert.AreEqual ("a", parameter.Name); - Assert.AreEqual ("System.Int32", parameter.ParameterType.FullName); + Assert.AreEqual ("a", parameter.Name); + Assert.AreEqual ("System.Int32", parameter.ParameterType.FullName); + }); } - [TestCSharp ("Methods.cs")] - public void SimplePInvoke (ModuleDefinition module) + [Test] + public void SimplePInvoke () { - var bar = module.GetType ("Bar"); - var pan = bar.GetMethod ("Pan"); + TestCSharp ("Methods.cs", module => { + var bar = module.GetType ("Bar"); + var pan = bar.GetMethod ("Pan"); - Assert.IsTrue (pan.IsPInvokeImpl); - Assert.IsNotNull (pan.PInvokeInfo); + Assert.IsTrue (pan.IsPInvokeImpl); + Assert.IsNotNull (pan.PInvokeInfo); - Assert.AreEqual ("Pan", pan.PInvokeInfo.EntryPoint); - Assert.IsNotNull (pan.PInvokeInfo.Module); - Assert.AreEqual ("foo.dll", pan.PInvokeInfo.Module.Name); + Assert.AreEqual ("Pan", pan.PInvokeInfo.EntryPoint); + Assert.IsNotNull (pan.PInvokeInfo.Module); + Assert.AreEqual ("foo.dll", pan.PInvokeInfo.Module.Name); + }); } - [TestCSharp ("Generics.cs")] - public void GenericMethodDefinition (ModuleDefinition module) + [Test] + public void GenericMethodDefinition () { - var baz = module.GetType ("Baz"); + TestCSharp ("Generics.cs", module => { + var baz = module.GetType ("Baz"); - var gazonk = baz.GetMethod ("Gazonk"); + var gazonk = baz.GetMethod ("Gazonk"); - Assert.IsNotNull (gazonk); + Assert.IsNotNull (gazonk); - Assert.IsTrue (gazonk.HasGenericParameters); - Assert.AreEqual (1, gazonk.GenericParameters.Count); - Assert.AreEqual ("TBang", gazonk.GenericParameters [0].Name); + Assert.IsTrue (gazonk.HasGenericParameters); + Assert.AreEqual (1, gazonk.GenericParameters.Count); + Assert.AreEqual ("TBang", gazonk.GenericParameters [0].Name); + }); } - [TestCSharp ("Generics.cs")] - public void ReturnGenericInstance (ModuleDefinition module) + [Test] + public void ReturnGenericInstance () { - var bar = module.GetType ("Bar`1"); + TestCSharp ("Generics.cs", module => { + var bar = module.GetType ("Bar`1"); - var self = bar.GetMethod ("Self"); - Assert.IsNotNull (self); + var self = bar.GetMethod ("Self"); + Assert.IsNotNull (self); - var bar_t = self.ReturnType; + var bar_t = self.ReturnType; - Assert.IsTrue (bar_t.IsGenericInstance); + Assert.IsTrue (bar_t.IsGenericInstance); - var bar_t_instance = (GenericInstanceType) bar_t; + var bar_t_instance = (GenericInstanceType) bar_t; - Assert.AreEqual (bar.GenericParameters [0], bar_t_instance.GenericArguments [0]); + Assert.AreEqual (bar.GenericParameters [0], bar_t_instance.GenericArguments [0]); - var self_str = bar.GetMethod ("SelfString"); - Assert.IsNotNull (self_str); + var self_str = bar.GetMethod ("SelfString"); + Assert.IsNotNull (self_str); - var bar_str = self_str.ReturnType; - Assert.IsTrue (bar_str.IsGenericInstance); + var bar_str = self_str.ReturnType; + Assert.IsTrue (bar_str.IsGenericInstance); - var bar_str_instance = (GenericInstanceType) bar_str; + var bar_str_instance = (GenericInstanceType) bar_str; - Assert.AreEqual ("System.String", bar_str_instance.GenericArguments [0].FullName); + Assert.AreEqual ("System.String", bar_str_instance.GenericArguments [0].FullName); + }); } - [TestCSharp ("Generics.cs")] - public void ReturnGenericInstanceWithMethodParameter (ModuleDefinition module) + [Test] + public void ReturnGenericInstanceWithMethodParameter () { - var baz = module.GetType ("Baz"); + TestCSharp ("Generics.cs", module => { + var baz = module.GetType ("Baz"); - var gazoo = baz.GetMethod ("Gazoo"); - Assert.IsNotNull (gazoo); + var gazoo = baz.GetMethod ("Gazoo"); + Assert.IsNotNull (gazoo); - var bar_bingo = gazoo.ReturnType; + var bar_bingo = gazoo.ReturnType; - Assert.IsTrue (bar_bingo.IsGenericInstance); + Assert.IsTrue (bar_bingo.IsGenericInstance); - var bar_bingo_instance = (GenericInstanceType) bar_bingo; + var bar_bingo_instance = (GenericInstanceType) bar_bingo; - Assert.AreEqual (gazoo.GenericParameters [0], bar_bingo_instance.GenericArguments [0]); + Assert.AreEqual (gazoo.GenericParameters [0], bar_bingo_instance.GenericArguments [0]); + }); } - [TestCSharp ("Interfaces.cs")] - public void SimpleOverrides (ModuleDefinition module) + [Test] + public void SimpleOverrides () { - var ibingo = module.GetType ("IBingo"); - var ibingo_foo = ibingo.GetMethod ("Foo"); - Assert.IsNotNull (ibingo_foo); + TestCSharp ("Interfaces.cs", module => { + var ibingo = module.GetType ("IBingo"); + var ibingo_foo = ibingo.GetMethod ("Foo"); + Assert.IsNotNull (ibingo_foo); - var ibingo_bar = ibingo.GetMethod ("Bar"); - Assert.IsNotNull (ibingo_bar); + var ibingo_bar = ibingo.GetMethod ("Bar"); + Assert.IsNotNull (ibingo_bar); - var bingo = module.GetType ("Bingo"); + var bingo = module.GetType ("Bingo"); - var foo = bingo.GetMethod ("IBingo.Foo"); - Assert.IsNotNull (foo); + var foo = bingo.GetMethod ("IBingo.Foo"); + Assert.IsNotNull (foo); - Assert.IsTrue (foo.HasOverrides); - Assert.AreEqual (ibingo_foo, foo.Overrides [0]); + Assert.IsTrue (foo.HasOverrides); + Assert.AreEqual (ibingo_foo, foo.Overrides [0]); - var bar = bingo.GetMethod ("IBingo.Bar"); - Assert.IsNotNull (bar); + var bar = bingo.GetMethod ("IBingo.Bar"); + Assert.IsNotNull (bar); - Assert.IsTrue (bar.HasOverrides); - Assert.AreEqual (ibingo_bar, bar.Overrides [0]); + Assert.IsTrue (bar.HasOverrides); + Assert.AreEqual (ibingo_bar, bar.Overrides [0]); + }); } - [TestModule ("varargs.exe")] - public void VarArgs (ModuleDefinition module) + [Test] + public void VarArgs () { - var module_type = module.Types [0]; + TestModule ("varargs.exe", module => { + var module_type = module.Types [0]; - Assert.AreEqual (3, module_type.Methods.Count); + Assert.AreEqual (3, module_type.Methods.Count); - var bar = module_type.GetMethod ("Bar"); - var baz = module_type.GetMethod ("Baz"); - var foo = module_type.GetMethod ("Foo"); + var bar = module_type.GetMethod ("Bar"); + var baz = module_type.GetMethod ("Baz"); + var foo = module_type.GetMethod ("Foo"); - Assert.IsTrue (bar.IsVarArg ()); - Assert.IsFalse (baz.IsVarArg ()); + Assert.IsTrue (bar.IsVarArg ()); + Assert.IsFalse (baz.IsVarArg ()); - Assert.IsTrue(foo.IsVarArg ()); + Assert.IsTrue (foo.IsVarArg ()); - var bar_reference = (MethodReference) baz.Body.Instructions.Where (i => i.Offset == 0x000a).First ().Operand; + var foo_reference = (MethodReference) baz.Body.Instructions.First (i => i.Offset == 0x000a).Operand; - Assert.IsTrue (bar_reference.IsVarArg ()); - Assert.AreEqual (0, bar_reference.GetSentinelPosition ()); + Assert.IsTrue (foo_reference.IsVarArg ()); + Assert.AreEqual (0, foo_reference.GetSentinelPosition ()); - var foo_reference = (MethodReference) baz.Body.Instructions.Where (i => i.Offset == 0x0023).First ().Operand; + Assert.AreEqual (foo, foo_reference.Resolve ()); - Assert.IsTrue (foo_reference.IsVarArg ()); + var bar_reference = (MethodReference) baz.Body.Instructions.First (i => i.Offset == 0x0023).Operand; - Assert.AreEqual (1, foo_reference.GetSentinelPosition ()); + Assert.IsTrue (bar_reference.IsVarArg ()); + + Assert.AreEqual (1, bar_reference.GetSentinelPosition ()); + + Assert.AreEqual (bar, bar_reference.Resolve ()); + }); } - [TestCSharp ("Generics.cs")] - public void GenericInstanceMethod (ModuleDefinition module) + [Test] + public void GenericInstanceMethod () { - var type = module.GetType ("It"); - var method = type.GetMethod ("ReadPwow"); + TestCSharp ("Generics.cs", module => { + var type = module.GetType ("It"); + var method = type.GetMethod ("ReadPwow"); - GenericInstanceMethod instance = null; + GenericInstanceMethod instance = null; - foreach (var instruction in method.Body.Instructions) { - instance = instruction.Operand as GenericInstanceMethod; - if (instance != null) - break; - } + foreach (var instruction in method.Body.Instructions) { + instance = instruction.Operand as GenericInstanceMethod; + if (instance != null) + break; + } - Assert.IsNotNull (instance); + Assert.IsNotNull (instance); - Assert.AreEqual (TokenType.MethodSpec, instance.MetadataToken.TokenType); - Assert.AreNotEqual (0, instance.MetadataToken.RID); + Assert.AreEqual (TokenType.MethodSpec, instance.MetadataToken.TokenType); + Assert.AreNotEqual (0, instance.MetadataToken.RID); + }); } - [TestCSharp ("Generics.cs")] - public void MethodRefDeclaredOnGenerics (ModuleDefinition module) + [Test] + public void MethodRefDeclaredOnGenerics () { - var type = module.GetType ("Tamtam"); - var beta = type.GetMethod ("Beta"); - var charlie = type.GetMethod ("Charlie"); + TestCSharp ("Generics.cs", module => { + var type = module.GetType ("Tamtam"); + var beta = type.GetMethod ("Beta"); + var charlie = type.GetMethod ("Charlie"); - var new_list_beta = (MethodReference) beta.Body.Instructions [0].Operand; - var new_list_charlie = (MethodReference) charlie.Body.Instructions [0].Operand; + var new_list_beta = (MethodReference) beta.Body.Instructions [0].Operand; + var new_list_charlie = (MethodReference) charlie.Body.Instructions [0].Operand; - Assert.AreEqual ("System.Collections.Generic.List`1", new_list_beta.DeclaringType.FullName); - Assert.AreEqual ("System.Collections.Generic.List`1", new_list_charlie.DeclaringType.FullName); + Assert.AreEqual ("System.Collections.Generic.List`1", new_list_beta.DeclaringType.FullName); + Assert.AreEqual ("System.Collections.Generic.List`1", new_list_charlie.DeclaringType.FullName); + }); } [Test] diff --git a/external/cecil/Test/Mono.Cecil.Tests/ModuleTests.cs b/external/cecil/Test/Mono.Cecil.Tests/ModuleTests.cs index 00f9e1af60..82e0dde194 100644 --- a/external/cecil/Test/Mono.Cecil.Tests/ModuleTests.cs +++ b/external/cecil/Test/Mono.Cecil.Tests/ModuleTests.cs @@ -22,185 +22,213 @@ namespace Mono.Cecil.Tests { Assert.AreEqual ("Test", module.Assembly.Name.Name); } - [TestModule ("hello.exe")] - public void SingleModule (ModuleDefinition module) + [Test] + public void SingleModule () { - var assembly = module.Assembly; + TestModule ("hello.exe", module => { + var assembly = module.Assembly; - Assert.AreEqual (1, assembly.Modules.Count); - Assert.IsNotNull (assembly.MainModule); + Assert.AreEqual (1, assembly.Modules.Count); + Assert.IsNotNull (assembly.MainModule); + }); } - [TestModule ("hello.exe")] - public void EntryPoint (ModuleDefinition module) + [Test] + public void EntryPoint () { - var entry_point = module.EntryPoint; - Assert.IsNotNull (entry_point); + TestModule ("hello.exe", module => { + var entry_point = module.EntryPoint; + Assert.IsNotNull (entry_point); - Assert.AreEqual ("System.Void Program::Main()", entry_point.ToString ()); + Assert.AreEqual ("System.Void Program::Main()", entry_point.ToString ()); + }); } - [TestModule ("mma.exe")] - public void MultiModules (ModuleDefinition module) + [Test] + public void MultiModules () { - var assembly = module.Assembly; + TestModule ("mma.exe", module => { + var assembly = module.Assembly; - Assert.AreEqual (3, assembly.Modules.Count); + Assert.AreEqual (3, assembly.Modules.Count); - Assert.AreEqual ("mma.exe", assembly.Modules [0].Name); - Assert.AreEqual (ModuleKind.Console, assembly.Modules [0].Kind); + Assert.AreEqual ("mma.exe", assembly.Modules [0].Name); + Assert.AreEqual (ModuleKind.Console, assembly.Modules [0].Kind); - Assert.AreEqual ("moda.netmodule", assembly.Modules [1].Name); - Assert.AreEqual ("eedb4721-6c3e-4d9a-be30-49021121dd92", assembly.Modules [1].Mvid.ToString ()); - Assert.AreEqual (ModuleKind.NetModule, assembly.Modules [1].Kind); + Assert.AreEqual ("moda.netmodule", assembly.Modules [1].Name); + Assert.AreEqual ("eedb4721-6c3e-4d9a-be30-49021121dd92", assembly.Modules [1].Mvid.ToString ()); + Assert.AreEqual (ModuleKind.NetModule, assembly.Modules [1].Kind); - Assert.AreEqual ("modb.netmodule", assembly.Modules [2].Name); - Assert.AreEqual ("46c5c577-11b2-4ea0-bb3c-3c71f1331dd0", assembly.Modules [2].Mvid.ToString ()); - Assert.AreEqual (ModuleKind.NetModule, assembly.Modules [2].Kind); + Assert.AreEqual ("modb.netmodule", assembly.Modules [2].Name); + Assert.AreEqual ("46c5c577-11b2-4ea0-bb3c-3c71f1331dd0", assembly.Modules [2].Mvid.ToString ()); + Assert.AreEqual (ModuleKind.NetModule, assembly.Modules [2].Kind); + }); } - [TestModule ("hello.exe")] - public void ModuleInformation (ModuleDefinition module) + [Test] + public void ModuleInformation () { - Assert.IsNotNull (module); + TestModule ("hello.exe", module => { + Assert.IsNotNull (module); - Assert.AreEqual ("hello.exe", module.Name); - Assert.AreEqual (new Guid ("C3BC2BD3-2576-4D00-A80E-465B5632415F"), module.Mvid); + Assert.AreEqual ("hello.exe", module.Name); + Assert.AreEqual (new Guid ("C3BC2BD3-2576-4D00-A80E-465B5632415F"), module.Mvid); + }); } - [TestModule ("hello.exe")] - public void AssemblyReferences (ModuleDefinition module) + [Test] + public void AssemblyReferences () { - Assert.AreEqual (1, module.AssemblyReferences.Count); + TestModule ("hello.exe", module => { + Assert.AreEqual (1, module.AssemblyReferences.Count); - var reference = module.AssemblyReferences [0]; + var reference = module.AssemblyReferences [0]; - Assert.AreEqual ("mscorlib", reference.Name); - Assert.AreEqual (new Version (2, 0, 0, 0), reference.Version); - Assert.AreEqual (new byte [] { 0xB7, 0x7A, 0x5C, 0x56, 0x19, 0x34, 0xE0, 0x89 }, reference.PublicKeyToken); + Assert.AreEqual ("mscorlib", reference.Name); + Assert.AreEqual (new Version (2, 0, 0, 0), reference.Version); + Assert.AreEqual (new byte [] { 0xB7, 0x7A, 0x5C, 0x56, 0x19, 0x34, 0xE0, 0x89 }, reference.PublicKeyToken); + }); } - [TestModule ("pinvoke.exe")] - public void ModuleReferences (ModuleDefinition module) + [Test] + public void ModuleReferences () { - Assert.AreEqual (2, module.ModuleReferences.Count); - Assert.AreEqual ("kernel32.dll", module.ModuleReferences [0].Name); - Assert.AreEqual ("shell32.dll", module.ModuleReferences [1].Name); + TestModule ("pinvoke.exe", module => { + Assert.AreEqual (2, module.ModuleReferences.Count); + Assert.AreEqual ("kernel32.dll", module.ModuleReferences [0].Name); + Assert.AreEqual ("shell32.dll", module.ModuleReferences [1].Name); + }); } - [TestModule ("hello.exe")] - public void Types (ModuleDefinition module) + [Test] + public void Types () { - Assert.AreEqual (2, module.Types.Count); - Assert.AreEqual ("", module.Types [0].FullName); - Assert.AreEqual ("", module.GetType ("").FullName); - Assert.AreEqual ("Program", module.Types [1].FullName); - Assert.AreEqual ("Program", module.GetType ("Program").FullName); + TestModule ("hello.exe", module => { + Assert.AreEqual (2, module.Types.Count); + Assert.AreEqual ("", module.Types [0].FullName); + Assert.AreEqual ("", module.GetType ("").FullName); + Assert.AreEqual ("Program", module.Types [1].FullName); + Assert.AreEqual ("Program", module.GetType ("Program").FullName); + }); } - [TestModule ("libres.dll")] - public void LinkedResource (ModuleDefinition module) + [Test] + public void LinkedResource () { - var resource = module.Resources.Where (res => res.Name == "linked.txt").First () as LinkedResource; - Assert.IsNotNull (resource); + TestModule ("libres.dll", module => { + var resource = module.Resources.Where (res => res.Name == "linked.txt").First () as LinkedResource; + Assert.IsNotNull (resource); - Assert.AreEqual ("linked.txt", resource.Name); - Assert.AreEqual ("linked.txt", resource.File); - Assert.AreEqual (ResourceType.Linked, resource.ResourceType); - Assert.IsTrue (resource.IsPublic); + Assert.AreEqual ("linked.txt", resource.Name); + Assert.AreEqual ("linked.txt", resource.File); + Assert.AreEqual (ResourceType.Linked, resource.ResourceType); + Assert.IsTrue (resource.IsPublic); + }); } - [TestModule ("libres.dll")] - public void EmbeddedResource (ModuleDefinition module) + [Test] + public void EmbeddedResource () { - var resource = module.Resources.Where (res => res.Name == "embedded1.txt").First () as EmbeddedResource; - Assert.IsNotNull (resource); + TestModule ("libres.dll", module => { + var resource = module.Resources.Where (res => res.Name == "embedded1.txt").First () as EmbeddedResource; + Assert.IsNotNull (resource); - Assert.AreEqual ("embedded1.txt", resource.Name); - Assert.AreEqual (ResourceType.Embedded, resource.ResourceType); - Assert.IsTrue (resource.IsPublic); + Assert.AreEqual ("embedded1.txt", resource.Name); + Assert.AreEqual (ResourceType.Embedded, resource.ResourceType); + Assert.IsTrue (resource.IsPublic); - using (var reader = new StreamReader (resource.GetResourceStream ())) + using (var reader = new StreamReader (resource.GetResourceStream ())) Assert.AreEqual ("Hello", reader.ReadToEnd ()); - resource = module.Resources.Where (res => res.Name == "embedded2.txt").First () as EmbeddedResource; - Assert.IsNotNull (resource); + resource = module.Resources.Where (res => res.Name == "embedded2.txt").First () as EmbeddedResource; + Assert.IsNotNull (resource); - Assert.AreEqual ("embedded2.txt", resource.Name); - Assert.AreEqual (ResourceType.Embedded, resource.ResourceType); - Assert.IsTrue (resource.IsPublic); + Assert.AreEqual ("embedded2.txt", resource.Name); + Assert.AreEqual (ResourceType.Embedded, resource.ResourceType); + Assert.IsTrue (resource.IsPublic); - using (var reader = new StreamReader (resource.GetResourceStream ())) + using (var reader = new StreamReader (resource.GetResourceStream ())) Assert.AreEqual ("World", reader.ReadToEnd ()); + }); } - [TestModule ("mma.exe")] - public void ExportedTypeFromNetModule (ModuleDefinition module) + [Test] + public void ExportedTypeFromNetModule () { - Assert.IsTrue (module.HasExportedTypes); - Assert.AreEqual (2, module.ExportedTypes.Count); + TestModule ("mma.exe", module => { + Assert.IsTrue (module.HasExportedTypes); + Assert.AreEqual (2, module.ExportedTypes.Count); - var exported_type = module.ExportedTypes [0]; + var exported_type = module.ExportedTypes [0]; - Assert.AreEqual ("Module.A.Foo", exported_type.FullName); - Assert.AreEqual ("moda.netmodule", exported_type.Scope.Name); + Assert.AreEqual ("Module.A.Foo", exported_type.FullName); + Assert.AreEqual ("moda.netmodule", exported_type.Scope.Name); - exported_type = module.ExportedTypes [1]; + exported_type = module.ExportedTypes [1]; - Assert.AreEqual ("Module.B.Baz", exported_type.FullName); - Assert.AreEqual ("modb.netmodule", exported_type.Scope.Name); + Assert.AreEqual ("Module.B.Baz", exported_type.FullName); + Assert.AreEqual ("modb.netmodule", exported_type.Scope.Name); + }); } - [TestCSharp ("CustomAttributes.cs")] - public void NestedTypeForwarder (ModuleDefinition module) + [Test] + public void NestedTypeForwarder () { - Assert.IsTrue (module.HasExportedTypes); - Assert.AreEqual (2, module.ExportedTypes.Count); + TestCSharp ("CustomAttributes.cs", module => { + Assert.IsTrue (module.HasExportedTypes); + Assert.AreEqual (2, module.ExportedTypes.Count); - var exported_type = module.ExportedTypes [0]; + var exported_type = module.ExportedTypes [0]; - Assert.AreEqual ("System.Diagnostics.DebuggableAttribute", exported_type.FullName); - Assert.AreEqual ("mscorlib", exported_type.Scope.Name); - Assert.IsTrue (exported_type.IsForwarder); + Assert.AreEqual ("System.Diagnostics.DebuggableAttribute", exported_type.FullName); + Assert.AreEqual ("mscorlib", exported_type.Scope.Name); + Assert.IsTrue (exported_type.IsForwarder); - var nested_exported_type = module.ExportedTypes [1]; + var nested_exported_type = module.ExportedTypes [1]; - Assert.AreEqual ("System.Diagnostics.DebuggableAttribute/DebuggingModes", nested_exported_type.FullName); - Assert.AreEqual (exported_type, nested_exported_type.DeclaringType); - Assert.AreEqual ("mscorlib", nested_exported_type.Scope.Name); + Assert.AreEqual ("System.Diagnostics.DebuggableAttribute/DebuggingModes", nested_exported_type.FullName); + Assert.AreEqual (exported_type, nested_exported_type.DeclaringType); + Assert.AreEqual ("mscorlib", nested_exported_type.Scope.Name); + }); } - [TestCSharp ("CustomAttributes.cs")] - public void HasTypeReference (ModuleDefinition module) + [Test] + public void HasTypeReference () { - Assert.IsTrue (module.HasTypeReference ("System.Attribute")); - Assert.IsTrue (module.HasTypeReference ("mscorlib", "System.Attribute")); + TestCSharp ("CustomAttributes.cs", module => { + Assert.IsTrue (module.HasTypeReference ("System.Attribute")); + Assert.IsTrue (module.HasTypeReference ("mscorlib", "System.Attribute")); - Assert.IsFalse (module.HasTypeReference ("System.Core", "System.Attribute")); - Assert.IsFalse (module.HasTypeReference ("System.Linq.Enumerable")); + Assert.IsFalse (module.HasTypeReference ("System.Core", "System.Attribute")); + Assert.IsFalse (module.HasTypeReference ("System.Linq.Enumerable")); + }); } - [TestModule ("libhello.dll")] - public void Win32FileVersion (ModuleDefinition module) + [Test] + public void Win32FileVersion () { - var version = FileVersionInfo.GetVersionInfo (module.FullyQualifiedName); + TestModule ("libhello.dll", module => { + var version = FileVersionInfo.GetVersionInfo (module.FileName); - Assert.AreEqual ("0.0.0.0", version.FileVersion); + Assert.AreEqual ("0.0.0.0", version.FileVersion); + }); } - [TestModule ("noblob.dll")] - public void ModuleWithoutBlob (ModuleDefinition module) + [Test] + public void ModuleWithoutBlob () { - Assert.IsNull (module.Image.BlobHeap); + TestModule ("noblob.dll", module => { + Assert.IsNull (module.Image.BlobHeap); + }); } [Test] public void MixedModeModule () { - var module = GetResourceModule ("cppcli.dll"); - - Assert.AreEqual (1, module.ModuleReferences.Count); - Assert.AreEqual (string.Empty, module.ModuleReferences [0].Name); + using (var module = GetResourceModule ("cppcli.dll")) { + Assert.AreEqual (1, module.ModuleReferences.Count); + Assert.AreEqual (string.Empty, module.ModuleReferences [0].Name); + } } [Test] @@ -210,41 +238,47 @@ namespace Mono.Cecil.Tests { GetResourceModule ("text_file.txt"); } - [Test] - public void WriteModuleTwice () - { - var module = GetResourceModule ("iterator.exe"); - - var path = Path.Combine (Path.GetTempPath (), "cecil"); - var file = Path.Combine (path, "iteratorrt.exe"); - - module.Write (file); - module.Write (file); - } - [Test] public void GetTypeNamespacePlusName () { - var module = GetResourceModule ("moda.netmodule"); - - var type = module.GetType ("Module.A", "Foo"); - Assert.IsNotNull (type); + using (var module = GetResourceModule ("moda.netmodule")) { + var type = module.GetType ("Module.A", "Foo"); + Assert.IsNotNull (type); + } } [Test] public void OpenModuleImmediate () { - var module = GetResourceModule ("hello.exe", ReadingMode.Immediate); - - Assert.AreEqual (ReadingMode.Immediate, module.ReadingMode); + using (var module = GetResourceModule ("hello.exe", ReadingMode.Immediate)) { + Assert.AreEqual (ReadingMode.Immediate, module.ReadingMode); + } } [Test] public void OpenModuleDeferred () { - var module = GetResourceModule ("hello.exe", ReadingMode.Deferred); + using (var module = GetResourceModule ("hello.exe", ReadingMode.Deferred)) { + Assert.AreEqual (ReadingMode.Deferred, module.ReadingMode); + } + } - Assert.AreEqual (ReadingMode.Deferred, module.ReadingMode); + [Test] + public void ReadAndWriteFile () + { + var path = Path.GetTempFileName (); + + var original = ModuleDefinition.CreateModule ("FooFoo", ModuleKind.Dll); + var type = new TypeDefinition ("Foo", "Foo", TypeAttributes.Abstract | TypeAttributes.Sealed); + original.Types.Add (type); + original.Write (path); + + using (var module = ModuleDefinition.ReadModule (path, new ReaderParameters { ReadWrite = true })) { + module.Write (); + } + + using (var module = ModuleDefinition.ReadModule (path)) + Assert.AreEqual ("Foo.Foo", module.Types [1].FullName); } } } diff --git a/external/cecil/Test/Mono.Cecil.Tests/NestedTypesTests.cs b/external/cecil/Test/Mono.Cecil.Tests/NestedTypesTests.cs index a8392928ba..38ae146688 100644 --- a/external/cecil/Test/Mono.Cecil.Tests/NestedTypesTests.cs +++ b/external/cecil/Test/Mono.Cecil.Tests/NestedTypesTests.cs @@ -9,37 +9,83 @@ namespace Mono.Cecil.Tests { [TestFixture] public class NestedTypesTests : BaseTestFixture { - [TestCSharp ("NestedTypes.cs")] - public void NestedTypes (ModuleDefinition module) + [Test] + public void NestedTypes () { - var foo = module.GetType ("Foo"); + TestCSharp ("NestedTypes.cs", module => { + var foo = module.GetType ("Foo"); - Assert.AreEqual ("Foo", foo.Name); - Assert.AreEqual ("Foo", foo.FullName); - Assert.AreEqual (module, foo.Module); - Assert.AreEqual (1, foo.NestedTypes.Count); + Assert.AreEqual ("Foo", foo.Name); + Assert.AreEqual ("Foo", foo.FullName); + Assert.AreEqual (module, foo.Module); + Assert.AreEqual (1, foo.NestedTypes.Count); - var bar = foo.NestedTypes [0]; + var bar = foo.NestedTypes [0]; - Assert.AreEqual ("Bar", bar.Name); - Assert.AreEqual ("Foo/Bar", bar.FullName); - Assert.AreEqual (module, bar.Module); - Assert.AreEqual (1, bar.NestedTypes.Count); + Assert.AreEqual ("Bar", bar.Name); + Assert.AreEqual ("Foo/Bar", bar.FullName); + Assert.AreEqual (module, bar.Module); + Assert.AreEqual (1, bar.NestedTypes.Count); - var baz = bar.NestedTypes [0]; + var baz = bar.NestedTypes [0]; - Assert.AreEqual ("Baz", baz.Name); - Assert.AreEqual ("Foo/Bar/Baz", baz.FullName); - Assert.AreEqual (module, baz.Module); + Assert.AreEqual ("Baz", baz.Name); + Assert.AreEqual ("Foo/Bar/Baz", baz.FullName); + Assert.AreEqual (module, baz.Module); + }); } - [TestCSharp ("NestedTypes.cs")] - public void DirectNestedType (ModuleDefinition module) + [Test] + public void DirectNestedType () { - var bingo = module.GetType ("Bingo"); - var get_fuel = bingo.GetMethod ("GetFuel"); + TestCSharp ("NestedTypes.cs", module => { + var bingo = module.GetType ("Bingo"); + var get_fuel = bingo.GetMethod ("GetFuel"); - Assert.AreEqual ("Bingo/Fuel", get_fuel.ReturnType.FullName); + Assert.AreEqual ("Bingo/Fuel", get_fuel.ReturnType.FullName); + }); + } + + [Test] + public void NestedTypeWithOwnNamespace () + { + TestModule ("bug-185.dll", module => { + var foo = module.GetType ("Foo"); + var foo_child = foo.NestedTypes [0]; + + Assert.AreEqual ("", foo_child.Namespace); + Assert.AreEqual ("Do>d__0", foo_child.Name); + + Assert.AreEqual ("Foo/.Do>d__0", foo_child.FullName); + }); + } + + [Test] + public void NestedTypeFullName () + { + var foo = new TypeDefinition (null, "Foo", TypeAttributes.Class); + var bar = new TypeDefinition (null, "Bar", TypeAttributes.Class); + var baz = new TypeDefinition (null, "Baz", TypeAttributes.Class); + + foo.NestedTypes.Add (bar); + bar.NestedTypes.Add (baz); + + Assert.AreEqual ("Foo/Bar/Baz", baz.FullName); + + foo.Namespace = "Change"; + + Assert.AreEqual ("Change.Foo/Bar", bar.FullName); + Assert.AreEqual ("Change.Foo/Bar/Baz", baz.FullName); + + bar.Namespace = "AnotherChange"; + + Assert.AreEqual ("Change.Foo/AnotherChange.Bar", bar.FullName); + Assert.AreEqual ("Change.Foo/AnotherChange.Bar/Baz", baz.FullName); + + foo.Name = "FooFoo"; + + Assert.AreEqual ("Change.FooFoo/AnotherChange.Bar", bar.FullName); + Assert.AreEqual ("Change.FooFoo/AnotherChange.Bar/Baz", baz.FullName); } } } diff --git a/external/cecil/Test/Mono.Cecil.Tests/ParameterTests.cs b/external/cecil/Test/Mono.Cecil.Tests/ParameterTests.cs index 124d7e1bd9..5ec3e06372 100644 --- a/external/cecil/Test/Mono.Cecil.Tests/ParameterTests.cs +++ b/external/cecil/Test/Mono.Cecil.Tests/ParameterTests.cs @@ -1,8 +1,4 @@ using System; -using System.Linq; - -using Mono.Cecil; -using Mono.Cecil.Metadata; using NUnit.Framework; @@ -11,107 +7,136 @@ namespace Mono.Cecil.Tests { [TestFixture] public class ParameterTests : BaseTestFixture { - [TestModule ("marshal.dll")] - public void MarshalAsI4 (ModuleDefinition module) + [Test] + public void MarshalAsI4 () { - var bar = module.GetType ("Bar"); - var pan = bar.GetMethod ("Pan"); + TestModule ("marshal.dll", module => { + var bar = module.GetType ("Bar"); + var pan = bar.GetMethod ("Pan"); - Assert.AreEqual (1, pan.Parameters.Count); + Assert.AreEqual (1, pan.Parameters.Count); - var parameter = pan.Parameters [0]; + var parameter = pan.Parameters [0]; - Assert.IsTrue (parameter.HasMarshalInfo); - var info = parameter.MarshalInfo; + Assert.IsTrue (parameter.HasMarshalInfo); + var info = parameter.MarshalInfo; - Assert.AreEqual (typeof (MarshalInfo), info.GetType ()); - Assert.AreEqual (NativeType.I4, info.NativeType); + Assert.AreEqual (typeof (MarshalInfo), info.GetType ()); + Assert.AreEqual (NativeType.I4, info.NativeType); + }); } - [TestModule ("marshal.dll")] - public void CustomMarshaler (ModuleDefinition module) + [Test] + public void CustomMarshaler () { - var bar = module.GetType ("Bar"); - var pan = bar.GetMethod ("PanPan"); + TestModule ("marshal.dll", module => { + var bar = module.GetType ("Bar"); + var pan = bar.GetMethod ("PanPan"); - var parameter = pan.Parameters [0]; + var parameter = pan.Parameters [0]; - Assert.IsTrue (parameter.HasMarshalInfo); + Assert.IsTrue (parameter.HasMarshalInfo); - var info = (CustomMarshalInfo) parameter.MarshalInfo; + var info = (CustomMarshalInfo) parameter.MarshalInfo; - Assert.AreEqual (Guid.Empty, info.Guid); - Assert.AreEqual (string.Empty, info.UnmanagedType); - Assert.AreEqual (NativeType.CustomMarshaler, info.NativeType); - Assert.AreEqual ("nomnom", info.Cookie); + Assert.AreEqual (Guid.Empty, info.Guid); + Assert.AreEqual (string.Empty, info.UnmanagedType); + Assert.AreEqual (NativeType.CustomMarshaler, info.NativeType); + Assert.AreEqual ("nomnom", info.Cookie); - Assert.AreEqual ("Boc", info.ManagedType.FullName); - Assert.AreEqual (module, info.ManagedType.Scope); + Assert.AreEqual ("Boc", info.ManagedType.FullName); + Assert.AreEqual (module, info.ManagedType.Scope); + }); } - [TestModule ("marshal.dll")] - public void SafeArrayMarshaler (ModuleDefinition module) + [Test] + public void SafeArrayMarshaler () { - var bar = module.GetType ("Bar"); - var pan = bar.GetMethod ("PanPan"); + TestModule ("marshal.dll", module => { + var bar = module.GetType ("Bar"); + var pan = bar.GetMethod ("PanPan"); - Assert.IsTrue (pan.MethodReturnType.HasMarshalInfo); + Assert.IsTrue (pan.MethodReturnType.HasMarshalInfo); - var info = (SafeArrayMarshalInfo) pan.MethodReturnType.MarshalInfo; + var info = (SafeArrayMarshalInfo) pan.MethodReturnType.MarshalInfo; - Assert.AreEqual (VariantType.Dispatch, info.ElementType); + Assert.AreEqual (VariantType.Dispatch, info.ElementType); + }); } - [TestModule ("marshal.dll")] - public void ArrayMarshaler (ModuleDefinition module) + [Test] + public void ArrayMarshaler () { - var bar = module.GetType ("Bar"); - var pan = bar.GetMethod ("PanPan"); + TestModule ("marshal.dll", module => { + var bar = module.GetType ("Bar"); + var pan = bar.GetMethod ("PanPan"); - var parameter = pan.Parameters [1]; + var parameter = pan.Parameters [1]; - Assert.IsTrue (parameter.HasMarshalInfo); + Assert.IsTrue (parameter.HasMarshalInfo); - var info = (ArrayMarshalInfo) parameter.MarshalInfo; + var info = (ArrayMarshalInfo) parameter.MarshalInfo; - Assert.AreEqual (NativeType.I8, info.ElementType); - Assert.AreEqual (66, info.Size); - Assert.AreEqual (2, info.SizeParameterIndex); + Assert.AreEqual (NativeType.I8, info.ElementType); + Assert.AreEqual (66, info.Size); + Assert.AreEqual (2, info.SizeParameterIndex); - parameter = pan.Parameters [3]; + parameter = pan.Parameters [3]; - Assert.IsTrue (parameter.HasMarshalInfo); + Assert.IsTrue (parameter.HasMarshalInfo); - info = (ArrayMarshalInfo) parameter.MarshalInfo; + info = (ArrayMarshalInfo) parameter.MarshalInfo; - Assert.AreEqual (NativeType.I2, info.ElementType); - Assert.AreEqual (-1, info.Size); - Assert.AreEqual (-1, info.SizeParameterIndex); + Assert.AreEqual (NativeType.I2, info.ElementType); + Assert.AreEqual (-1, info.Size); + Assert.AreEqual (-1, info.SizeParameterIndex); + }); } - [TestModule ("marshal.dll")] - public void ArrayMarshalerSized (ModuleDefinition module) + [Test] + public void ArrayMarshalerSized () { - var delegate_type = module.GetType ("SomeMethod"); - var parameter = delegate_type.GetMethod ("Invoke").Parameters [1]; + TestModule ("marshal.dll", module => { + var delegate_type = module.GetType ("SomeMethod"); + var parameter = delegate_type.GetMethod ("Invoke").Parameters [1]; - Assert.IsTrue (parameter.HasMarshalInfo); - var array_info = (ArrayMarshalInfo) parameter.MarshalInfo; + Assert.IsTrue (parameter.HasMarshalInfo); + var array_info = (ArrayMarshalInfo) parameter.MarshalInfo; - Assert.IsNotNull (array_info); + Assert.IsNotNull (array_info); - Assert.AreEqual (0, array_info.SizeParameterMultiplier); + Assert.AreEqual (0, array_info.SizeParameterMultiplier); + }); } - [TestModule ("boxedoptarg.dll")] - public void BoxedDefaultArgumentValue (ModuleDefinition module) + [Test] + public void NullableConstant () { - var foo = module.GetType ("Foo"); - var bar = foo.GetMethod ("Bar"); - var baz = bar.Parameters [0]; + TestModule ("nullable-constant.exe", module => { + var type = module.GetType ("Program"); + var method = type.GetMethod ("Foo"); - Assert.IsTrue (baz.HasConstant); - Assert.AreEqual (-1, baz.Constant); + Assert.IsTrue (method.Parameters [0].HasConstant); + Assert.IsTrue (method.Parameters [1].HasConstant); + Assert.IsTrue (method.Parameters [2].HasConstant); + + Assert.AreEqual (1234, method.Parameters [0].Constant); + Assert.AreEqual (null, method.Parameters [1].Constant); + Assert.AreEqual (12, method.Parameters [2].Constant); + }); + } + + [Test] + public void BoxedDefaultArgumentValue () + { + TestModule ("boxedoptarg.dll", module => { + var foo = module.GetType ("Foo"); + var bar = foo.GetMethod ("Bar"); + var baz = bar.Parameters [0]; + + Assert.IsTrue (baz.HasConstant); + Assert.AreEqual (-1, baz.Constant); + }); } [Test] @@ -207,18 +232,43 @@ namespace Mono.Cecil.Tests { Assert.AreEqual (2, z.Index); } - [TestIL ("hello.il")] - public void GenericParameterConstant (ModuleDefinition module) + [Test] + public void GenericParameterConstant () { - var foo = module.GetType ("Foo"); - var method = foo.GetMethod ("GetState"); + TestIL ("hello.il", module => { + var foo = module.GetType ("Foo"); + var method = foo.GetMethod ("GetState"); - Assert.IsNotNull (method); + Assert.IsNotNull (method); - var parameter = method.Parameters [1]; + var parameter = method.Parameters [1]; - Assert.IsTrue (parameter.HasConstant); - Assert.IsNull (parameter.Constant); + Assert.IsTrue (parameter.HasConstant); + Assert.IsNull (parameter.Constant); + }); + } + + [Test] + public void NullablePrimitiveParameterConstant () + { + TestModule ("nullable-parameter.dll", module => { + var test = module.GetType ("Test"); + var method = test.GetMethod ("Foo"); + + Assert.IsNotNull (method); + + var param = method.Parameters [0]; + Assert.IsTrue (param.HasConstant); + Assert.AreEqual (1234, param.Constant); + + param = method.Parameters [1]; + Assert.IsTrue (param.HasConstant); + Assert.AreEqual (null, param.Constant); + + param = method.Parameters [2]; + Assert.IsTrue (param.HasConstant); + Assert.AreEqual (12, param.Constant); + }); } } } diff --git a/external/cecil/Test/Mono.Cecil.Tests/PortablePdbTests.cs b/external/cecil/Test/Mono.Cecil.Tests/PortablePdbTests.cs new file mode 100644 index 0000000000..14cf1eb32f --- /dev/null +++ b/external/cecil/Test/Mono.Cecil.Tests/PortablePdbTests.cs @@ -0,0 +1,355 @@ +using System; +using System.IO; + +using NUnit.Framework; + +using Mono.Cecil.Cil; + +namespace Mono.Cecil.Tests { + + [TestFixture] + public class PortablePdbTests : BaseTestFixture { + + [Test] + public void SequencePoints () + { + TestPortablePdbModule (module => { + var type = module.GetType ("PdbTarget.Program"); + var main = type.GetMethod ("Main"); + + AssertCode (@" + .locals init (System.Int32 a, System.String[] V_1, System.Int32 V_2, System.String arg) + .line 21,21:3,4 'C:\sources\PdbTarget\Program.cs' + IL_0000: nop + .line 22,22:4,11 'C:\sources\PdbTarget\Program.cs' + IL_0001: nop + .line 22,22:24,28 'C:\sources\PdbTarget\Program.cs' + IL_0002: ldarg.0 + IL_0003: stloc.1 + IL_0004: ldc.i4.0 + IL_0005: stloc.2 + .line 16707566,0:16707566,0 'C:\sources\PdbTarget\Program.cs' + IL_0006: br.s IL_0017 + .line 22,22:13,20 'C:\sources\PdbTarget\Program.cs' + IL_0008: ldloc.1 + IL_0009: ldloc.2 + IL_000a: ldelem.ref + IL_000b: stloc.3 + .line 23,23:5,20 'C:\sources\PdbTarget\Program.cs' + IL_000c: ldloc.3 + IL_000d: call System.Void System.Console::WriteLine(System.String) + IL_0012: nop + .line 16707566,0:16707566,0 'C:\sources\PdbTarget\Program.cs' + IL_0013: ldloc.2 + IL_0014: ldc.i4.1 + IL_0015: add + IL_0016: stloc.2 + .line 22,22:21,23 'C:\sources\PdbTarget\Program.cs' + IL_0017: ldloc.2 + IL_0018: ldloc.1 + IL_0019: ldlen + IL_001a: conv.i4 + IL_001b: blt.s IL_0008 + .line 25,25:4,22 'C:\sources\PdbTarget\Program.cs' + IL_001d: ldc.i4.1 + IL_001e: ldc.i4.2 + IL_001f: call System.Int32 System.Math::Min(System.Int32,System.Int32) + IL_0024: stloc.0 + .line 26,26:3,4 'C:\sources\PdbTarget\Program.cs' + IL_0025: ret +", main); + }); + } + + [Test] + public void SequencePointsMultipleDocument () + { + TestPortablePdbModule (module => { + var type = module.GetType ("PdbTarget.B"); + var main = type.GetMethod (".ctor"); + + AssertCode (@" + .locals () + .line 7,7:3,25 'C:\sources\PdbTarget\B.cs' + IL_0000: ldarg.0 + IL_0001: ldstr """" + IL_0006: stfld System.String PdbTarget.B::s + .line 110,110:3,21 'C:\sources\PdbTarget\Program.cs' + IL_000b: ldarg.0 + IL_000c: ldc.i4.2 + IL_000d: stfld System.Int32 PdbTarget.B::a + .line 111,111:3,21 'C:\sources\PdbTarget\Program.cs' + IL_0012: ldarg.0 + IL_0013: ldc.i4.3 + IL_0014: stfld System.Int32 PdbTarget.B::b + .line 9,9:3,13 'C:\sources\PdbTarget\B.cs' + IL_0019: ldarg.0 + IL_001a: call System.Void System.Object::.ctor() + IL_001f: nop + .line 10,10:3,4 'C:\sources\PdbTarget\B.cs' + IL_0020: nop + .line 11,11:4,19 'C:\sources\PdbTarget\B.cs' + IL_0021: ldstr ""B"" + IL_0026: call System.Void System.Console::WriteLine(System.String) + IL_002b: nop + .line 12,12:3,4 'C:\sources\PdbTarget\B.cs' + IL_002c: ret +", main); + }); + } + + [Test] + public void LocalVariables () + { + TestPortablePdbModule (module => { + var type = module.GetType ("PdbTarget.Program"); + var method = type.GetMethod ("Bar"); + var debug_info = method.DebugInformation; + + Assert.IsNotNull (debug_info.Scope); + Assert.IsTrue (debug_info.Scope.HasScopes); + Assert.AreEqual (2, debug_info.Scope.Scopes.Count); + + var scope = debug_info.Scope.Scopes [0]; + + Assert.IsNotNull (scope); + Assert.IsTrue (scope.HasVariables); + Assert.AreEqual (1, scope.Variables.Count); + + var variable = scope.Variables [0]; + + Assert.AreEqual ("s", variable.Name); + Assert.IsFalse (variable.IsDebuggerHidden); + Assert.AreEqual (2, variable.Index); + + scope = debug_info.Scope.Scopes [1]; + + Assert.IsNotNull (scope); + Assert.IsTrue (scope.HasVariables); + Assert.AreEqual (1, scope.Variables.Count); + + variable = scope.Variables [0]; + + Assert.AreEqual ("s", variable.Name); + Assert.IsFalse (variable.IsDebuggerHidden); + Assert.AreEqual (3, variable.Index); + + Assert.IsTrue (scope.HasScopes); + Assert.AreEqual (1, scope.Scopes.Count); + + scope = scope.Scopes [0]; + + Assert.IsNotNull (scope); + Assert.IsTrue (scope.HasVariables); + Assert.AreEqual (1, scope.Variables.Count); + + variable = scope.Variables [0]; + + Assert.AreEqual ("u", variable.Name); + Assert.IsFalse (variable.IsDebuggerHidden); + Assert.AreEqual (5, variable.Index); + }); + } + + [Test] + public void LocalConstants () + { + TestPortablePdbModule (module => { + var type = module.GetType ("PdbTarget.Program"); + var method = type.GetMethod ("Bar"); + var debug_info = method.DebugInformation; + + Assert.IsNotNull (debug_info.Scope); + Assert.IsTrue (debug_info.Scope.HasScopes); + Assert.AreEqual (2, debug_info.Scope.Scopes.Count); + + var scope = debug_info.Scope.Scopes [1]; + + Assert.IsNotNull (scope); + Assert.IsTrue (scope.HasConstants); + Assert.AreEqual (2, scope.Constants.Count); + + var constant = scope.Constants [0]; + + Assert.AreEqual ("b", constant.Name); + Assert.AreEqual (12, constant.Value); + Assert.AreEqual (MetadataType.Int32, constant.ConstantType.MetadataType); + + constant = scope.Constants [1]; + Assert.AreEqual ("c", constant.Name); + Assert.AreEqual ((decimal) 74, constant.Value); + Assert.AreEqual (MetadataType.ValueType, constant.ConstantType.MetadataType); + + method = type.GetMethod ("Foo"); + debug_info = method.DebugInformation; + + Assert.IsNotNull (debug_info.Scope); + Assert.IsTrue (debug_info.Scope.HasConstants); + Assert.AreEqual (4, debug_info.Scope.Constants.Count); + + constant = debug_info.Scope.Constants [0]; + Assert.AreEqual ("s", constant.Name); + Assert.AreEqual ("const string", constant.Value); + Assert.AreEqual (MetadataType.String, constant.ConstantType.MetadataType); + + constant = debug_info.Scope.Constants [1]; + Assert.AreEqual ("f", constant.Name); + Assert.AreEqual (1, constant.Value); + Assert.AreEqual (MetadataType.Int32, constant.ConstantType.MetadataType); + + constant = debug_info.Scope.Constants [2]; + Assert.AreEqual ("o", constant.Name); + Assert.AreEqual (null, constant.Value); + Assert.AreEqual (MetadataType.Object, constant.ConstantType.MetadataType); + + constant = debug_info.Scope.Constants [3]; + Assert.AreEqual ("u", constant.Name); + Assert.AreEqual (null, constant.Value); + Assert.AreEqual (MetadataType.String, constant.ConstantType.MetadataType); + }); + } + + [Test] + public void ImportScope () + { + TestPortablePdbModule (module => { + var type = module.GetType ("PdbTarget.Program"); + var method = type.GetMethod ("Bar"); + var debug_info = method.DebugInformation; + + Assert.IsNotNull (debug_info.Scope); + + var import = debug_info.Scope.Import; + Assert.IsNotNull (import); + + Assert.IsFalse (import.HasTargets); + Assert.IsNotNull (import.Parent); + + import = import.Parent; + + Assert.IsTrue (import.HasTargets); + Assert.AreEqual (9, import.Targets.Count); + var target = import.Targets [0]; + + Assert.AreEqual (ImportTargetKind.ImportAlias, target.Kind); + Assert.AreEqual ("XML", target.Alias); + + target = import.Targets [1]; + + Assert.AreEqual (ImportTargetKind.ImportNamespace, target.Kind); + Assert.AreEqual ("System", target.Namespace); + + target = import.Targets [2]; + + Assert.AreEqual (ImportTargetKind.ImportNamespace, target.Kind); + Assert.AreEqual ("System.Collections.Generic", target.Namespace); + + target = import.Targets [3]; + + Assert.AreEqual (ImportTargetKind.ImportNamespace, target.Kind); + Assert.AreEqual ("System.IO", target.Namespace); + + target = import.Targets [4]; + + Assert.AreEqual (ImportTargetKind.ImportNamespace, target.Kind); + Assert.AreEqual ("System.Threading.Tasks", target.Namespace); + + target = import.Targets [5]; + + Assert.AreEqual (ImportTargetKind.ImportNamespaceInAssembly, target.Kind); + Assert.AreEqual ("System.Xml.Resolvers", target.Namespace); + Assert.AreEqual ("System.Xml", target.AssemblyReference.Name); + + + target = import.Targets [6]; + + Assert.AreEqual (ImportTargetKind.ImportType, target.Kind); + Assert.AreEqual ("System.Console", target.Type.FullName); + + target = import.Targets [7]; + + Assert.AreEqual (ImportTargetKind.ImportType, target.Kind); + Assert.AreEqual ("System.Math", target.Type.FullName); + + target = import.Targets [8]; + + Assert.AreEqual (ImportTargetKind.DefineTypeAlias, target.Kind); + Assert.AreEqual ("Foo", target.Alias); + Assert.AreEqual ("System.Xml.XmlDocumentType", target.Type.FullName); + + Assert.IsNotNull (import.Parent); + + import = import.Parent; + + Assert.IsTrue (import.HasTargets); + Assert.AreEqual (1, import.Targets.Count); + Assert.IsNull (import.Parent); + + target = import.Targets [0]; + + Assert.AreEqual (ImportTargetKind.DefineAssemblyAlias, target.Kind); + Assert.AreEqual ("XML", target.Alias); + Assert.AreEqual ("System.Xml", target.AssemblyReference.Name); + }); + } + + [Test] + public void StateMachineKickOff () + { + TestPortablePdbModule (module => { + var state_machine = module.GetType ("PdbTarget.Program/d__7"); + var main = state_machine.GetMethod ("MoveNext"); + var symbol = main.DebugInformation; + + Assert.IsNotNull (symbol); + Assert.IsNotNull (symbol.StateMachineKickOffMethod); + Assert.AreEqual ("System.Threading.Tasks.Task PdbTarget.Program::Baz(System.IO.StreamReader)", symbol.StateMachineKickOffMethod.FullName); + }); + } + + [Test] + public void StateMachineCustomDebugInformation () + { + TestPortablePdbModule (module => { + var state_machine = module.GetType ("PdbTarget.Program/d__7"); + var move_next = state_machine.GetMethod ("MoveNext"); + + Assert.IsTrue (move_next.HasCustomDebugInformations); + Assert.AreEqual (2, move_next.CustomDebugInformations.Count); + + var state_machine_scope = move_next.CustomDebugInformations [0] as StateMachineScopeDebugInformation; + Assert.IsNotNull (state_machine_scope); + Assert.AreEqual (0, state_machine_scope.Start.Offset); + Assert.IsTrue (state_machine_scope.End.IsEndOfMethod); + + var async_body = move_next.CustomDebugInformations [1] as AsyncMethodBodyDebugInformation; + Assert.IsNotNull (async_body); + Assert.AreEqual (-1, async_body.CatchHandler.Offset); + + Assert.AreEqual (2, async_body.Yields.Count); + Assert.AreEqual (61, async_body.Yields [0].Offset); + Assert.AreEqual (221, async_body.Yields [1].Offset); + + Assert.AreEqual (2, async_body.Resumes.Count); + Assert.AreEqual (91, async_body.Resumes [0].Offset); + Assert.AreEqual (252, async_body.Resumes [1].Offset); + + Assert.AreEqual (move_next, async_body.MoveNextMethod); + }); + } + + void TestPortablePdbModule (Action test) + { + TestModule ("PdbTarget.exe", test, symbolReaderProvider: typeof (PortablePdbReaderProvider), symbolWriterProvider: typeof (PortablePdbWriterProvider)); + TestModule ("EmbeddedPdbTarget.exe", test, verify: !Platform.OnMono); + } + + [Test] + public void RoundTripCecilPortablePdb () + { + TestModule ("cecil.dll", module => { + Assert.IsTrue (module.HasSymbols); + }, symbolReaderProvider: typeof (PortablePdbReaderProvider), symbolWriterProvider: typeof (PortablePdbWriterProvider)); + } + } +} diff --git a/external/cecil/Test/Mono.Cecil.Tests/PropertyTests.cs b/external/cecil/Test/Mono.Cecil.Tests/PropertyTests.cs index 2ff9c92853..587868ff78 100644 --- a/external/cecil/Test/Mono.Cecil.Tests/PropertyTests.cs +++ b/external/cecil/Test/Mono.Cecil.Tests/PropertyTests.cs @@ -7,106 +7,122 @@ namespace Mono.Cecil.Tests { [TestFixture] public class PropertyTests : BaseTestFixture { - [TestCSharp ("Properties.cs")] - public void AbstractMethod (ModuleDefinition module) + [Test] + public void AbstractMethod () { - var type = module.GetType ("Foo"); + TestCSharp ("Properties.cs", module => { + var type = module.GetType ("Foo"); - Assert.IsTrue (type.HasProperties); + Assert.IsTrue (type.HasProperties); - var properties = type.Properties; + var properties = type.Properties; - Assert.AreEqual (3, properties.Count); + Assert.AreEqual (3, properties.Count); - var property = properties [0]; + var property = properties [0]; - Assert.IsNotNull (property); - Assert.AreEqual ("Bar", property.Name); - Assert.IsNotNull (property.PropertyType); - Assert.AreEqual ("System.Int32", property.PropertyType.FullName); + Assert.IsNotNull (property); + Assert.AreEqual ("Bar", property.Name); + Assert.IsNotNull (property.PropertyType); + Assert.AreEqual ("System.Int32", property.PropertyType.FullName); - Assert.IsNotNull (property.GetMethod); - Assert.AreEqual (MethodSemanticsAttributes.Getter, property.GetMethod.SemanticsAttributes); - Assert.IsNull (property.SetMethod); + Assert.IsNotNull (property.GetMethod); + Assert.AreEqual (MethodSemanticsAttributes.Getter, property.GetMethod.SemanticsAttributes); + Assert.IsNull (property.SetMethod); - property = properties [1]; + property = properties [1]; - Assert.IsNotNull (property); - Assert.AreEqual ("Baz", property.Name); - Assert.IsNotNull (property.PropertyType); - Assert.AreEqual ("System.String", property.PropertyType.FullName); + Assert.IsNotNull (property); + Assert.AreEqual ("Baz", property.Name); + Assert.IsNotNull (property.PropertyType); + Assert.AreEqual ("System.String", property.PropertyType.FullName); - Assert.IsNotNull (property.GetMethod); - Assert.AreEqual (MethodSemanticsAttributes.Getter, property.GetMethod.SemanticsAttributes); - Assert.IsNotNull (property.SetMethod); - Assert.AreEqual (MethodSemanticsAttributes.Setter, property.SetMethod.SemanticsAttributes); + Assert.IsNotNull (property.GetMethod); + Assert.AreEqual (MethodSemanticsAttributes.Getter, property.GetMethod.SemanticsAttributes); + Assert.IsNotNull (property.SetMethod); + Assert.AreEqual (MethodSemanticsAttributes.Setter, property.SetMethod.SemanticsAttributes); - property = properties [2]; + property = properties [2]; - Assert.IsNotNull (property); - Assert.AreEqual ("Gazonk", property.Name); - Assert.IsNotNull (property.PropertyType); - Assert.AreEqual ("System.String", property.PropertyType.FullName); + Assert.IsNotNull (property); + Assert.AreEqual ("Gazonk", property.Name); + Assert.IsNotNull (property.PropertyType); + Assert.AreEqual ("System.String", property.PropertyType.FullName); + + Assert.IsNull (property.GetMethod); + Assert.IsNotNull (property.SetMethod); + Assert.AreEqual (MethodSemanticsAttributes.Setter, property.SetMethod.SemanticsAttributes); + }); + } + + [Test] + public void OtherMethod () + { + TestIL ("others.il", module => { + var type = module.GetType ("Others"); + + Assert.IsTrue (type.HasProperties); + + var properties = type.Properties; + + Assert.AreEqual (1, properties.Count); + + var property = properties [0]; + + Assert.IsNotNull (property); + Assert.AreEqual ("Context", property.Name); + Assert.IsNotNull (property.PropertyType); + Assert.AreEqual ("System.String", property.PropertyType.FullName); + + Assert.IsTrue (property.HasOtherMethods); + + Assert.AreEqual (2, property.OtherMethods.Count); + + var other = property.OtherMethods [0]; + Assert.AreEqual ("let_Context", other.Name); + + other = property.OtherMethods [1]; + Assert.AreEqual ("bet_Context", other.Name); + }); + } + + [Test] + public void SetOnlyIndexer () + { + TestCSharp ("Properties.cs", module => { + var type = module.GetType ("Bar"); + var indexer = type.Properties.Where (property => property.Name == "Item").First (); + + var parameters = indexer.Parameters; + + Assert.AreEqual (2, parameters.Count); + Assert.AreEqual ("System.Int32", parameters [0].ParameterType.FullName); + Assert.AreEqual ("System.String", parameters [1].ParameterType.FullName); + }); + } + + [Test] + public void ReadSemanticsFirst () + { + TestCSharp ("Properties.cs", module => { + var type = module.GetType ("Baz"); + var setter = type.GetMethod ("set_Bingo"); + + Assert.AreEqual (MethodSemanticsAttributes.Setter, setter.SemanticsAttributes); + + var property = type.Properties.Where (p => p.Name == "Bingo").First (); + + Assert.AreEqual (setter, property.SetMethod); + Assert.AreEqual (type.GetMethod ("get_Bingo"), property.GetMethod); + }); + } + + [Test] + public void UnattachedProperty () + { + var property = new PropertyDefinition ("Property", PropertyAttributes.None, typeof (int).ToDefinition ()); Assert.IsNull (property.GetMethod); - Assert.IsNotNull (property.SetMethod); - Assert.AreEqual (MethodSemanticsAttributes.Setter, property.SetMethod.SemanticsAttributes); - } - - [TestIL ("others.il")] - public void OtherMethod (ModuleDefinition module) - { - var type = module.GetType ("Others"); - - Assert.IsTrue (type.HasProperties); - - var properties = type.Properties; - - Assert.AreEqual (1, properties.Count); - - var property = properties [0]; - - Assert.IsNotNull (property); - Assert.AreEqual ("Context", property.Name); - Assert.IsNotNull (property.PropertyType); - Assert.AreEqual ("System.String", property.PropertyType.FullName); - - Assert.IsTrue (property.HasOtherMethods); - - Assert.AreEqual (2, property.OtherMethods.Count); - - var other = property.OtherMethods [0]; - Assert.AreEqual ("let_Context", other.Name); - - other = property.OtherMethods [1]; - Assert.AreEqual ("bet_Context", other.Name); - } - - [TestCSharp ("Properties.cs")] - public void SetOnlyIndexer (ModuleDefinition module) - { - var type = module.GetType ("Bar"); - var indexer = type.Properties.Where (property => property.Name == "Item").First (); - - var parameters = indexer.Parameters; - - Assert.AreEqual (2, parameters.Count); - Assert.AreEqual ("System.Int32", parameters [0].ParameterType.FullName); - Assert.AreEqual ("System.String", parameters [1].ParameterType.FullName); - } - - [TestCSharp ("Properties.cs")] - public void ReadSemanticsFirst (ModuleDefinition module) - { - var type = module.GetType ("Baz"); - var setter = type.GetMethod ("set_Bingo"); - - Assert.AreEqual (MethodSemanticsAttributes.Setter, setter.SemanticsAttributes); - - var property = type.Properties.Where (p => p.Name == "Bingo").First (); - - Assert.AreEqual (setter, property.SetMethod); - Assert.AreEqual (type.GetMethod ("get_Bingo"), property.GetMethod); } } } diff --git a/external/cecil/Test/Mono.Cecil.Tests/ResolveTests.cs b/external/cecil/Test/Mono.Cecil.Tests/ResolveTests.cs index cb7512d070..aab7d0cf5b 100644 --- a/external/cecil/Test/Mono.Cecil.Tests/ResolveTests.cs +++ b/external/cecil/Test/Mono.Cecil.Tests/ResolveTests.cs @@ -100,7 +100,7 @@ namespace Mono.Cecil.Tests { public void Register (AssemblyDefinition assembly) { this.RegisterAssembly (assembly); - this.AddSearchDirectory (Path.GetDirectoryName (assembly.MainModule.FullyQualifiedName)); + this.AddSearchDirectory (Path.GetDirectoryName (assembly.MainModule.FileName)); } } @@ -113,12 +113,13 @@ namespace Mono.Cecil.Tests { resolver.Register (mma.Assembly); - var current_module = GetCurrentModule (parameters); - var reference = new TypeReference ("Module.A", "Foo", current_module, AssemblyNameReference.Parse (mma.Assembly.FullName), false); + using (var current_module = GetCurrentModule (parameters)) { + var reference = new TypeReference ("Module.A", "Foo", current_module, AssemblyNameReference.Parse (mma.Assembly.FullName), false); - var definition = reference.Resolve (); - Assert.IsNotNull (definition); - Assert.AreEqual ("Module.A.Foo", definition.FullName); + var definition = reference.Resolve (); + Assert.IsNotNull (definition); + Assert.AreEqual ("Module.A.Foo", definition.FullName); + } } [Test] @@ -226,7 +227,7 @@ namespace Mono.Cecil.Tests { } } - static TRet GetReference (TDel code) + TRet GetReference (TDel code) { var @delegate = code as Delegate; if (@delegate == null) @@ -264,7 +265,7 @@ namespace Mono.Cecil.Tests { throw new InvalidOperationException (); } - static MethodDefinition GetMethodFromDelegate (Delegate @delegate) + MethodDefinition GetMethodFromDelegate (Delegate @delegate) { var method = @delegate.Method; var type = (TypeDefinition) TypeParser.ParseType (GetCurrentModule (), method.DeclaringType.FullName); diff --git a/external/cecil/Test/Mono.Cecil.Tests/SecurityDeclarationTests.cs b/external/cecil/Test/Mono.Cecil.Tests/SecurityDeclarationTests.cs index 2cc8d5b43a..3939502798 100644 --- a/external/cecil/Test/Mono.Cecil.Tests/SecurityDeclarationTests.cs +++ b/external/cecil/Test/Mono.Cecil.Tests/SecurityDeclarationTests.cs @@ -15,78 +15,82 @@ namespace Mono.Cecil.Tests { [TestFixture] public class SecurityDeclarationTests : BaseTestFixture { - [TestModule ("decsec-xml.dll")] - public void XmlSecurityDeclaration (ModuleDefinition module) + [Test] + public void XmlSecurityDeclaration () { - var type = module.GetType ("SubLibrary"); + TestModule ("decsec-xml.dll", module => { + var type = module.GetType ("SubLibrary"); - Assert.IsTrue (type.HasSecurityDeclarations); + Assert.IsTrue (type.HasSecurityDeclarations); - Assert.AreEqual (1, type.SecurityDeclarations.Count); + Assert.AreEqual (1, type.SecurityDeclarations.Count); - var declaration = type.SecurityDeclarations [0]; - Assert.AreEqual (SecurityAction.Deny, declaration.Action); + var declaration = type.SecurityDeclarations [0]; + Assert.AreEqual (SecurityAction.Deny, declaration.Action); - Assert.AreEqual (1, declaration.SecurityAttributes.Count); + Assert.AreEqual (1, declaration.SecurityAttributes.Count); - var attribute = declaration.SecurityAttributes [0]; + var attribute = declaration.SecurityAttributes [0]; - Assert.AreEqual ("System.Security.Permissions.PermissionSetAttribute", attribute.AttributeType.FullName); + Assert.AreEqual ("System.Security.Permissions.PermissionSetAttribute", attribute.AttributeType.FullName); - Assert.AreEqual (1, attribute.Properties.Count); + Assert.AreEqual (1, attribute.Properties.Count); - var named_argument = attribute.Properties [0]; + var named_argument = attribute.Properties [0]; - Assert.AreEqual ("XML", named_argument.Name); + Assert.AreEqual ("XML", named_argument.Name); - var argument = named_argument.Argument; + var argument = named_argument.Argument; - Assert.AreEqual ("System.String", argument.Type.FullName); + Assert.AreEqual ("System.String", argument.Type.FullName); - const string permission_set = "\r\n\r\n\r\n"; - Assert.AreEqual (permission_set, argument.Value); + Assert.AreEqual (permission_set, argument.Value); + }); } - [TestModule ("decsec1-xml.dll")] - public void XmlNet_1_1SecurityDeclaration (ModuleDefinition module) + [Test] + public void XmlNet_1_1SecurityDeclaration () { - var type = module.GetType ("SubLibrary"); + TestModule ("decsec1-xml.dll", module => { + var type = module.GetType ("SubLibrary"); - Assert.IsTrue (type.HasSecurityDeclarations); + Assert.IsTrue (type.HasSecurityDeclarations); - Assert.AreEqual (1, type.SecurityDeclarations.Count); + Assert.AreEqual (1, type.SecurityDeclarations.Count); - var declaration = type.SecurityDeclarations [0]; - Assert.AreEqual (SecurityAction.Deny, declaration.Action); + var declaration = type.SecurityDeclarations [0]; + Assert.AreEqual (SecurityAction.Deny, declaration.Action); - Assert.AreEqual (1, declaration.SecurityAttributes.Count); + Assert.AreEqual (1, declaration.SecurityAttributes.Count); - var attribute = declaration.SecurityAttributes [0]; + var attribute = declaration.SecurityAttributes [0]; - Assert.AreEqual ("System.Security.Permissions.PermissionSetAttribute", attribute.AttributeType.FullName); + Assert.AreEqual ("System.Security.Permissions.PermissionSetAttribute", attribute.AttributeType.FullName); - Assert.AreEqual (1, attribute.Properties.Count); + Assert.AreEqual (1, attribute.Properties.Count); - var named_argument = attribute.Properties [0]; + var named_argument = attribute.Properties [0]; - Assert.AreEqual ("XML", named_argument.Name); + Assert.AreEqual ("XML", named_argument.Name); - var argument = named_argument.Argument; + var argument = named_argument.Argument; - Assert.AreEqual ("System.String", argument.Type.FullName); + Assert.AreEqual ("System.String", argument.Type.FullName); - const string permission_set = "\r\n\r\n\r\n"; - Assert.AreEqual (permission_set, argument.Value); + Assert.AreEqual (permission_set, argument.Value); + }); } [Test] @@ -122,55 +126,59 @@ namespace Mono.Cecil.Tests { Assert.AreEqual (permission_set, argument.Value); } - [TestModule ("empty-decsec-att.dll")] - public void SecurityDeclarationWithoutAttributes (ModuleDefinition module) + [Test] + public void SecurityDeclarationWithoutAttributes () { - var type = module.GetType ("TestSecurityAction.ModalUITypeEditor"); - var method = type.GetMethod ("GetEditStyle"); + TestModule ("empty-decsec-att.dll", module => { + var type = module.GetType ("TestSecurityAction.ModalUITypeEditor"); + var method = type.GetMethod ("GetEditStyle"); - Assert.IsNotNull (method); + Assert.IsNotNull (method); - Assert.AreEqual (1, method.SecurityDeclarations.Count); + Assert.AreEqual (1, method.SecurityDeclarations.Count); - var declaration = method.SecurityDeclarations [0]; - Assert.AreEqual (SecurityAction.LinkDemand, declaration.Action); - Assert.AreEqual (1, declaration.SecurityAttributes.Count); + var declaration = method.SecurityDeclarations [0]; + Assert.AreEqual (SecurityAction.LinkDemand, declaration.Action); + Assert.AreEqual (1, declaration.SecurityAttributes.Count); - var attribute = declaration.SecurityAttributes [0]; - Assert.AreEqual ("System.Security.Permissions.SecurityPermissionAttribute", attribute.AttributeType.FullName); - Assert.AreEqual (0, attribute.Fields.Count); - Assert.AreEqual (0, attribute.Properties.Count); + var attribute = declaration.SecurityAttributes [0]; + Assert.AreEqual ("System.Security.Permissions.SecurityPermissionAttribute", attribute.AttributeType.FullName); + Assert.AreEqual (0, attribute.Fields.Count); + Assert.AreEqual (0, attribute.Properties.Count); + }); } - [TestModule ("decsec-att.dll")] - public void AttributeSecurityDeclaration (ModuleDefinition module) + [Test] + public void AttributeSecurityDeclaration () { - var type = module.GetType ("SubLibrary"); + TestModule ("decsec-att.dll", module => { + var type = module.GetType ("SubLibrary"); - Assert.IsTrue (type.HasSecurityDeclarations); + Assert.IsTrue (type.HasSecurityDeclarations); - Assert.AreEqual (1, type.SecurityDeclarations.Count); + Assert.AreEqual (1, type.SecurityDeclarations.Count); - var declaration = type.SecurityDeclarations [0]; - Assert.AreEqual (SecurityAction.Deny, declaration.Action); + var declaration = type.SecurityDeclarations [0]; + Assert.AreEqual (SecurityAction.Deny, declaration.Action); - Assert.AreEqual (1, declaration.SecurityAttributes.Count); + Assert.AreEqual (1, declaration.SecurityAttributes.Count); - var attribute = declaration.SecurityAttributes [0]; + var attribute = declaration.SecurityAttributes [0]; - Assert.AreEqual ("System.Security.Permissions.SecurityPermissionAttribute", attribute.AttributeType.FullName); + Assert.AreEqual ("System.Security.Permissions.SecurityPermissionAttribute", attribute.AttributeType.FullName); - Assert.AreEqual (1, attribute.Properties.Count); + Assert.AreEqual (1, attribute.Properties.Count); - var named_argument = attribute.Properties [0]; + var named_argument = attribute.Properties [0]; - Assert.AreEqual ("UnmanagedCode", named_argument.Name); + Assert.AreEqual ("UnmanagedCode", named_argument.Name); - var argument = named_argument.Argument; + var argument = named_argument.Argument; - Assert.AreEqual ("System.Boolean", argument.Type.FullName); + Assert.AreEqual ("System.Boolean", argument.Type.FullName); - Assert.AreEqual (true, argument.Value); + Assert.AreEqual (true, argument.Value); + }); } static void AssertCustomAttributeArgument (string expected, CustomAttributeNamedArgument named_argument) diff --git a/external/cecil/Test/Mono.Cecil.Tests/TypeParserTests.cs b/external/cecil/Test/Mono.Cecil.Tests/TypeParserTests.cs index 6b52e98a90..603b7f4d50 100644 --- a/external/cecil/Test/Mono.Cecil.Tests/TypeParserTests.cs +++ b/external/cecil/Test/Mono.Cecil.Tests/TypeParserTests.cs @@ -12,7 +12,7 @@ namespace Mono.Cecil.Tests { public void SimpleStringReference () { var module = GetCurrentModule (); - var corlib = module.TypeSystem.Corlib; + var corlib = module.TypeSystem.CoreLibrary; const string fullname = "System.String"; @@ -31,7 +31,7 @@ namespace Mono.Cecil.Tests { public void SimpleInt32Reference () { var module = GetCurrentModule (); - var corlib = module.TypeSystem.Corlib; + var corlib = module.TypeSystem.CoreLibrary; const string fullname = "System.Int32"; @@ -66,7 +66,7 @@ namespace Mono.Cecil.Tests { public void ByRefTypeReference () { var module = GetCurrentModule (); - var corlib = module.TypeSystem.Corlib; + var corlib = module.TypeSystem.CoreLibrary; const string fullname = "System.String&"; @@ -105,7 +105,7 @@ namespace Mono.Cecil.Tests { public void OpenGenericType () { var module = GetCurrentModule (); - var corlib = module.TypeSystem.Corlib; + var corlib = module.TypeSystem.CoreLibrary; const string fullname = "System.Collections.Generic.Dictionary`2"; @@ -149,7 +149,7 @@ namespace Mono.Cecil.Tests { var type = TypeParser.ParseType (module, fullname); - Assert.AreEqual ("Bingo.Foo`1+Bar`1+Baz`1, Bingo, Culture=neutral, PublicKeyToken=null", TypeParser.ToParseable (type)); + Assert.AreEqual ("Bingo.Foo`1+Bar`1+Baz`1, Bingo, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", TypeParser.ToParseable (type)); Assert.IsNotNull (type); Assert.AreEqual ("Bingo", type.Scope.Name); @@ -189,7 +189,7 @@ namespace Mono.Cecil.Tests { var type = TypeParser.ParseType (module, fullname); - Assert.AreEqual ("Bingo.Gazonk[], Bingo, Culture=neutral, PublicKeyToken=null", TypeParser.ToParseable (type)); + Assert.AreEqual ("Bingo.Gazonk[], Bingo, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", TypeParser.ToParseable (type)); var array = type as ArrayType; Assert.IsNotNull (array); diff --git a/external/cecil/Test/Mono.Cecil.Tests/TypeTests.cs b/external/cecil/Test/Mono.Cecil.Tests/TypeTests.cs index 3ceb0aa4d2..1bf834af3c 100644 --- a/external/cecil/Test/Mono.Cecil.Tests/TypeTests.cs +++ b/external/cecil/Test/Mono.Cecil.Tests/TypeTests.cs @@ -12,188 +12,213 @@ namespace Mono.Cecil.Tests { [TestFixture] public class TypeTests : BaseTestFixture { - [TestCSharp ("Layouts.cs")] - public void TypeLayout (ModuleDefinition module) + [Test] + public void TypeLayout () { - var foo = module.GetType ("Foo"); - Assert.IsNotNull (foo); - Assert.IsTrue (foo.IsValueType); + TestCSharp ("Layouts.cs", module => { + var foo = module.GetType ("Foo"); + Assert.IsNotNull (foo); + Assert.IsTrue (foo.IsValueType); - Assert.IsTrue (foo.HasLayoutInfo); - Assert.AreEqual (16, foo.ClassSize); + Assert.IsTrue (foo.HasLayoutInfo); + Assert.AreEqual (16, foo.ClassSize); - var babar = module.GetType ("Babar"); - Assert.IsNotNull (babar); - Assert.IsFalse (babar.IsValueType); - Assert.IsFalse (babar.HasLayoutInfo); + var babar = module.GetType ("Babar"); + Assert.IsNotNull (babar); + Assert.IsFalse (babar.IsValueType); + Assert.IsFalse (babar.HasLayoutInfo); + }); } - [TestIL ("types.il")] - public void SimpleInterfaces (ModuleDefinition module) + [Test] + public void SimpleInterfaces () { - var ibaz = module.GetType ("IBaz"); - Assert.IsNotNull (ibaz); + TestIL ("types.il", module => { + var ibaz = module.GetType ("IBaz"); + Assert.IsNotNull (ibaz); - Assert.IsTrue (ibaz.HasInterfaces); + Assert.IsTrue (ibaz.HasInterfaces); - var interfaces = ibaz.Interfaces; + var interfaces = ibaz.Interfaces; - Assert.AreEqual (2, interfaces.Count); + Assert.AreEqual (2, interfaces.Count); - Assert.AreEqual ("IBar", interfaces [0].FullName); - Assert.AreEqual ("IFoo", interfaces [1].FullName); + // Mono's ilasm and .NET's are ordering interfaces differently + Assert.IsNotNull (interfaces.Single (i => i.InterfaceType.FullName == "IBar")); + Assert.IsNotNull (interfaces.Single (i => i.InterfaceType.FullName == "IFoo")); + }); } - [TestCSharp ("Generics.cs")] - public void GenericTypeDefinition (ModuleDefinition module) + [Test] + public void GenericTypeDefinition () { - var foo = module.GetType ("Foo`2"); - Assert.IsNotNull (foo); + TestCSharp ("Generics.cs", module => { + var foo = module.GetType ("Foo`2"); + Assert.IsNotNull (foo); - Assert.IsTrue (foo.HasGenericParameters); - Assert.AreEqual (2, foo.GenericParameters.Count); + Assert.IsTrue (foo.HasGenericParameters); + Assert.AreEqual (2, foo.GenericParameters.Count); - var tbar = foo.GenericParameters [0]; + var tbar = foo.GenericParameters [0]; - Assert.AreEqual ("TBar", tbar.Name); - Assert.AreEqual (foo, tbar.Owner); + Assert.AreEqual ("TBar", tbar.Name); + Assert.AreEqual (foo, tbar.Owner); - var tbaz = foo.GenericParameters [1]; + var tbaz = foo.GenericParameters [1]; - Assert.AreEqual ("TBaz", tbaz.Name); - Assert.AreEqual (foo, tbaz.Owner); + Assert.AreEqual ("TBaz", tbaz.Name); + Assert.AreEqual (foo, tbaz.Owner); + }); } - [TestCSharp ("Generics.cs")] - public void ConstrainedGenericType (ModuleDefinition module) + [Test] + public void ConstrainedGenericType () { - var bongo_t = module.GetType ("Bongo`1"); - Assert.IsNotNull (bongo_t); + TestCSharp ("Generics.cs", module => { + var bongo_t = module.GetType ("Bongo`1"); + Assert.IsNotNull (bongo_t); - var t = bongo_t.GenericParameters [0]; - Assert.IsNotNull (t); - Assert.AreEqual ("T", t.Name); + var t = bongo_t.GenericParameters [0]; + Assert.IsNotNull (t); + Assert.AreEqual ("T", t.Name); - Assert.IsTrue (t.HasConstraints); - Assert.AreEqual (2, t.Constraints.Count); + Assert.IsTrue (t.HasConstraints); + Assert.AreEqual (2, t.Constraints.Count); - Assert.AreEqual ("Zap", t.Constraints [0].FullName); - Assert.AreEqual ("IZoom", t.Constraints [1].FullName); + Assert.AreEqual ("Zap", t.Constraints [0].FullName); + Assert.AreEqual ("IZoom", t.Constraints [1].FullName); + }); } - [TestCSharp ("Generics.cs")] - public void GenericBaseType (ModuleDefinition module) + [Test] + public void GenericBaseType () { - var child = module.GetType ("Child`1"); + TestCSharp ("Generics.cs", module => { + var child = module.GetType ("Child`1"); - var child_t = child.GenericParameters [0]; - Assert.IsNotNull (child_t); + var child_t = child.GenericParameters [0]; + Assert.IsNotNull (child_t); - var instance = child.BaseType as GenericInstanceType; - Assert.IsNotNull (instance); - Assert.AreNotEqual (0, instance.MetadataToken.RID); + var instance = child.BaseType as GenericInstanceType; + Assert.IsNotNull (instance); + Assert.AreNotEqual (0, instance.MetadataToken.RID); - Assert.AreEqual (child_t, instance.GenericArguments [0]); + Assert.AreEqual (child_t, instance.GenericArguments [0]); + }); } - [TestCSharp ("Generics.cs")] - public void GenericConstraintOnGenericParameter (ModuleDefinition module) + [Test] + public void GenericConstraintOnGenericParameter () { - var duel = module.GetType ("Duel`3"); + TestCSharp ("Generics.cs", module => { + var duel = module.GetType ("Duel`3"); - Assert.AreEqual (3, duel.GenericParameters.Count); + Assert.AreEqual (3, duel.GenericParameters.Count); - var t1 = duel.GenericParameters [0]; - var t2 = duel.GenericParameters [1]; - var t3 = duel.GenericParameters [2]; + var t1 = duel.GenericParameters [0]; + var t2 = duel.GenericParameters [1]; + var t3 = duel.GenericParameters [2]; - Assert.AreEqual (t1, t2.Constraints [0]); - Assert.AreEqual (t2, t3.Constraints [0]); + Assert.AreEqual (t1, t2.Constraints [0]); + Assert.AreEqual (t2, t3.Constraints [0]); + }); } - [TestCSharp ("Generics.cs")] - public void GenericForwardBaseType (ModuleDefinition module) + [Test] + public void GenericForwardBaseType () { - var tamchild = module.GetType ("TamChild"); + TestCSharp ("Generics.cs", module => { + var tamchild = module.GetType ("TamChild"); - Assert.IsNotNull (tamchild); - Assert.IsNotNull (tamchild.BaseType); + Assert.IsNotNull (tamchild); + Assert.IsNotNull (tamchild.BaseType); - var generic_instance = tamchild.BaseType as GenericInstanceType; + var generic_instance = tamchild.BaseType as GenericInstanceType; - Assert.IsNotNull (generic_instance); + Assert.IsNotNull (generic_instance); - Assert.AreEqual (1, generic_instance.GenericArguments.Count); - Assert.AreEqual (module.GetType ("Tamtam"), generic_instance.GenericArguments [0]); + Assert.AreEqual (1, generic_instance.GenericArguments.Count); + Assert.AreEqual (module.GetType ("Tamtam"), generic_instance.GenericArguments [0]); + }); } - [TestCSharp ("Generics.cs")] - public void TypeExtentingGenericOfSelf (ModuleDefinition module) + [Test] + public void TypeExtentingGenericOfSelf () { - var rec_child = module.GetType ("RecChild"); + TestCSharp ("Generics.cs", module => { + var rec_child = module.GetType ("RecChild"); - Assert.IsNotNull (rec_child); - Assert.IsNotNull (rec_child.BaseType); + Assert.IsNotNull (rec_child); + Assert.IsNotNull (rec_child.BaseType); - var generic_instance = rec_child.BaseType as GenericInstanceType; + var generic_instance = rec_child.BaseType as GenericInstanceType; - Assert.IsNotNull (generic_instance); + Assert.IsNotNull (generic_instance); - Assert.AreEqual (1, generic_instance.GenericArguments.Count); - Assert.AreEqual (rec_child, generic_instance.GenericArguments [0]); + Assert.AreEqual (1, generic_instance.GenericArguments.Count); + Assert.AreEqual (rec_child, generic_instance.GenericArguments [0]); + }); } - [TestCSharp ("Methods.cs")] - public void TypeReferenceValueType (ModuleDefinition module) + [Test] + public void TypeReferenceValueType () { - var baz = module.GetType ("Baz"); - var method = baz.GetMethod ("PrintAnswer"); + TestCSharp ("Methods.cs", module => { + var baz = module.GetType ("Baz"); + var method = baz.GetMethod ("PrintAnswer"); - var box = method.Body.Instructions.Where (i => i.OpCode == OpCodes.Box).First (); - var int32 = (TypeReference) box.Operand; + var box = method.Body.Instructions.Where (i => i.OpCode == OpCodes.Box).First (); + var int32 = (TypeReference) box.Operand; - Assert.IsTrue (int32.IsValueType); + Assert.IsTrue (int32.IsValueType); + }); } - [TestModule ("gifaceref.exe")] - public void GenericInterfaceReference (ModuleDefinition module) + [Test] + public void GenericInterfaceReference () { - var type = module.GetType ("Program"); - var iface = type.Interfaces [0]; + TestModule ("gifaceref.exe", module => { + var type = module.GetType ("Program"); + var iface = type.Interfaces [0]; - var instance = (GenericInstanceType) iface; - var owner = instance.ElementType; + var instance = (GenericInstanceType) iface.InterfaceType; + var owner = instance.ElementType; - Assert.AreEqual (1, instance.GenericArguments.Count); - Assert.AreEqual (1, owner.GenericParameters.Count); + Assert.AreEqual (1, instance.GenericArguments.Count); + Assert.AreEqual (1, owner.GenericParameters.Count); + }); } - [TestModule ("cscgpbug.dll", Verify = false)] - public void UnboundGenericParameter (ModuleDefinition module) + [Test] + public void UnboundGenericParameter () { - var type = module.GetType ("ListViewModel"); - var method = type.GetMethod ("<>n__FabricatedMethod1"); + TestModule ("cscgpbug.dll", module => { + var type = module.GetType ("ListViewModel"); + var method = type.GetMethod ("<>n__FabricatedMethod1"); - var parameter = method.ReturnType as GenericParameter; + var parameter = method.ReturnType as GenericParameter; - Assert.IsNotNull (parameter); - Assert.AreEqual (0, parameter.Position); - Assert.IsNull (parameter.Owner); + Assert.IsNotNull (parameter); + Assert.AreEqual (0, parameter.Position); + Assert.IsNull (parameter.Owner); + }, verify: false); } - [TestCSharp ("Generics.cs")] - public void GenericMultidimensionalArray (ModuleDefinition module) + [Test] + public void GenericMultidimensionalArray () { - var type = module.GetType ("LaMatrix"); - var method = type.GetMethod ("At"); + TestCSharp ("Generics.cs", module => { + var type = module.GetType ("LaMatrix"); + var method = type.GetMethod ("At"); - var call = method.Body.Instructions.Where (i => i.Operand is MethodReference).First (); - var get = (MethodReference) call.Operand; + var call = method.Body.Instructions.Where (i => i.Operand is MethodReference).First (); + var get = (MethodReference) call.Operand; - Assert.IsNotNull (get); - Assert.AreEqual (0, get.GenericParameters.Count); - Assert.AreEqual (MethodCallingConvention.Default, get.CallingConvention); - Assert.AreEqual (method.GenericParameters [0], get.ReturnType); + Assert.IsNotNull (get); + Assert.AreEqual (0, get.GenericParameters.Count); + Assert.AreEqual (MethodCallingConvention.Default, get.CallingConvention); + Assert.AreEqual (method.GenericParameters [0], get.ReturnType); + }); } [Test] @@ -210,19 +235,30 @@ namespace Mono.Cecil.Tests { Assert.AreEqual (MetadataType.Int32, int32_def.MetadataType); } - [TestIL ("explicitthis.il", Verify = false)] - public void ExplicitThis (ModuleDefinition module) + [Test] + public void ExplicitThis () { - var type = module.GetType ("MakeDecision"); - var method = type.GetMethod ("Decide"); - var fptr = method.ReturnType as FunctionPointerType; + TestIL ("explicitthis.il", module => { + var type = module.GetType ("MakeDecision"); + var method = type.GetMethod ("Decide"); + var fptr = method.ReturnType as FunctionPointerType; - Assert.IsNotNull (fptr); - Assert.IsTrue (fptr.HasThis); - Assert.IsTrue (fptr.ExplicitThis); + Assert.IsNotNull (fptr); + Assert.IsTrue (fptr.HasThis); + Assert.IsTrue (fptr.ExplicitThis); - Assert.AreEqual (0, fptr.Parameters [0].Sequence); - Assert.AreEqual (1, fptr.Parameters [1].Sequence); + Assert.AreEqual (0, fptr.Parameters [0].Sequence); + Assert.AreEqual (1, fptr.Parameters [1].Sequence); + }, verify: false); + } + + [Test] + public void DeferredCorlibTypeDef () + { + var module = ModuleDefinition.ReadModule (typeof (object).Assembly.Location, new ReaderParameters (ReadingMode.Deferred)); + var object_type = module.TypeSystem.Object; + + Assert.IsInstanceOf (object_type); } } } diff --git a/external/cecil/Test/Mono.Cecil.Tests/VariableTests.cs b/external/cecil/Test/Mono.Cecil.Tests/VariableTests.cs index 9f6c54c67a..577e56f5a7 100644 --- a/external/cecil/Test/Mono.Cecil.Tests/VariableTests.cs +++ b/external/cecil/Test/Mono.Cecil.Tests/VariableTests.cs @@ -18,8 +18,8 @@ namespace Mono.Cecil.Tests { var method = new MethodDefinition ("foo", MethodAttributes.Static, object_ref); var body = new MethodBody (method); - var x = new VariableDefinition ("x", object_ref); - var y = new VariableDefinition ("y", object_ref); + var x = new VariableDefinition (object_ref); + var y = new VariableDefinition (object_ref); body.Variables.Add (x); body.Variables.Add (y); @@ -35,9 +35,9 @@ namespace Mono.Cecil.Tests { var method = new MethodDefinition ("foo", MethodAttributes.Static, object_ref); var body = new MethodBody (method); - var x = new VariableDefinition ("x", object_ref); - var y = new VariableDefinition ("y", object_ref); - var z = new VariableDefinition ("z", object_ref); + var x = new VariableDefinition (object_ref); + var y = new VariableDefinition (object_ref); + var z = new VariableDefinition (object_ref); body.Variables.Add (x); body.Variables.Add (y); @@ -61,9 +61,9 @@ namespace Mono.Cecil.Tests { var method = new MethodDefinition ("foo", MethodAttributes.Static, object_ref); var body = new MethodBody (method); - var x = new VariableDefinition ("x", object_ref); - var y = new VariableDefinition ("y", object_ref); - var z = new VariableDefinition ("z", object_ref); + var x = new VariableDefinition (object_ref); + var y = new VariableDefinition (object_ref); + var z = new VariableDefinition (object_ref); body.Variables.Add (x); body.Variables.Add (y); @@ -87,9 +87,9 @@ namespace Mono.Cecil.Tests { var method = new MethodDefinition ("foo", MethodAttributes.Static, object_ref); var body = new MethodBody (method); - var x = new VariableDefinition ("x", object_ref); - var y = new VariableDefinition ("y", object_ref); - var z = new VariableDefinition ("z", object_ref); + var x = new VariableDefinition (object_ref); + var y = new VariableDefinition (object_ref); + var z = new VariableDefinition (object_ref); body.Variables.Add (x); body.Variables.Add (z); diff --git a/external/cecil/Test/Mono.Cecil.Tests/WindowsRuntimeAssemblyResolver.cs b/external/cecil/Test/Mono.Cecil.Tests/WindowsRuntimeAssemblyResolver.cs new file mode 100644 index 0000000000..1e3a90bb73 --- /dev/null +++ b/external/cecil/Test/Mono.Cecil.Tests/WindowsRuntimeAssemblyResolver.cs @@ -0,0 +1,93 @@ +using System; +using System.Collections.Generic; +using System.IO; +using Microsoft.Win32; + +namespace Mono.Cecil.Tests { + public class WindowsRuntimeAssemblyResolver : DefaultAssemblyResolver { + + readonly Dictionary assemblies = new Dictionary (); + + public static WindowsRuntimeAssemblyResolver CreateInstance () + { + if (Platform.OnMono) + return null; + try { + return new WindowsRuntimeAssemblyResolver (); + } catch { + return null; + } + } + + public override AssemblyDefinition Resolve (AssemblyNameReference name) + { + AssemblyDefinition assembly; + if (assemblies.TryGetValue(name.Name, out assembly)) + return assembly; + + return base.Resolve (name); + } + + private WindowsRuntimeAssemblyResolver () + { + LoadWindowsSdk ("v8.1", "8.1", (installationFolder) => { + var fileName = Path.Combine (installationFolder, @"References\CommonConfiguration\Neutral\Annotated\Windows.winmd"); + var assembly = AssemblyDefinition.ReadAssembly (fileName); + Register (assembly); + }); + + LoadWindowsSdk ("v10.0", "10", (installationFolder) => { + var referencesFolder = Path.Combine (installationFolder, "References"); + var assemblies = Directory.GetFiles (referencesFolder, "*.winmd", SearchOption.AllDirectories); + + foreach (var assemblyPath in assemblies) { + var assembly = AssemblyDefinition.ReadAssembly (assemblyPath); + Register (assembly); + } + }); + } + + void Register (AssemblyDefinition assembly) + { + assemblies [assembly.Name.Name] = assembly; + RegisterAssembly (assembly); + } + + protected override void Dispose (bool disposing) + { + if (!disposing) + return; + + foreach (var assembly in assemblies.Values) + assembly.Dispose (); + + base.Dispose (true); + } + + void LoadWindowsSdk (string registryVersion, string windowsKitsVersion, Action registerAssembliesCallback) + { +#if NET_4_0 + using (var localMachine32Key = RegistryKey.OpenBaseKey (RegistryHive.LocalMachine, RegistryView.Registry32)) { + using (var sdkKey = localMachine32Key.OpenSubKey (@"SOFTWARE\Microsoft\Microsoft SDKs\Windows\v" + registryVersion)) { +#else + { + // this will fail on 64-bit process as there's no way (other than pinoke) to read from 32-bit registry view + using (var sdkKey = Registry.LocalMachine.OpenSubKey (@"SOFTWARE\Microsoft\Microsoft SDKs\Windows\" + registryVersion)) { +#endif + string installationFolder = null; + if (sdkKey != null) + installationFolder = (string)sdkKey.GetValue ("InstallationFolder"); + if (string.IsNullOrEmpty (installationFolder)) { +#if NET_4_0 + var programFilesX86 = Environment.GetFolderPath (Environment.SpecialFolder.ProgramFilesX86); +#else + var programFilesX86 = Environment.GetEnvironmentVariable ("ProgramFiles(x86)"); +#endif + installationFolder = Path.Combine (programFilesX86, @"Windows Kits\" + windowsKitsVersion); + } + registerAssembliesCallback (installationFolder); + } + } + } + } +} diff --git a/external/cecil/Test/Mono.Cecil.Tests/WindowsRuntimeProjectionsTests.cs b/external/cecil/Test/Mono.Cecil.Tests/WindowsRuntimeProjectionsTests.cs new file mode 100644 index 0000000000..52f5f73044 --- /dev/null +++ b/external/cecil/Test/Mono.Cecil.Tests/WindowsRuntimeProjectionsTests.cs @@ -0,0 +1,141 @@ +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; + +namespace Mono.Cecil.Tests { + [TestFixture] + public abstract class BaseWindowsRuntimeProjectionsTests : BaseTestFixture { + protected abstract string ModuleName { get; } + protected abstract MetadataKind ExpectedMetadataKind { get; } + protected abstract string [] ManagedClassTypeNames { get; } + protected abstract string [] CustomListTypeNames { get; } + + [Test] + public void CanReadMetadataType () + { + if (Platform.OnMono) + return; + + TestModule (ModuleName, (module) => { + Assert.AreEqual (ExpectedMetadataKind, module.MetadataKind); + }, verify: false, assemblyResolver: WindowsRuntimeAssemblyResolver.CreateInstance (), applyWindowsRuntimeProjections: true); + } + + [Test] + public void CanProjectParametersAndReturnTypes () + { + if (Platform.OnMono) + return; + + TestModule (ModuleName, (module) => { + var types = ManagedClassTypeNames.Select (typeName => module.Types.Single (t => t.Name == typeName)); + + foreach (var type in types) { + var listGetter = type.Properties.Single (p => p.Name == "List").GetMethod; + var listSetter = type.Properties.Single (p => p.Name == "List").SetMethod; + + Assert.IsNotNull (listGetter); + Assert.IsNotNull (listSetter); + + Assert.AreEqual (listGetter.ReturnType.FullName, "System.Collections.Generic.IList`1"); + Assert.AreEqual (listSetter.Parameters.Count, 1); + Assert.AreEqual (listSetter.Parameters [0].ParameterType.FullName, "System.Collections.Generic.IList`1"); + } + }, verify: false, assemblyResolver: WindowsRuntimeAssemblyResolver.CreateInstance (), applyWindowsRuntimeProjections: true); + } + + [Test] + public void CanProjectInterfaces () + { + if (Platform.OnMono) + return; + + TestModule (ModuleName, (module) => { + var types = CustomListTypeNames.Select (typeName => module.Types.Single (t => t.Name == typeName)); + + foreach (var type in types) { + Assert.IsNotNull (type.Interfaces.SingleOrDefault (i => i.InterfaceType.FullName == "System.Collections.Generic.IList`1")); + Assert.IsNotNull (type.Interfaces.SingleOrDefault (i => i.InterfaceType.FullName == "System.Collections.Generic.IEnumerable`1")); + } + }, verify: false, assemblyResolver: WindowsRuntimeAssemblyResolver.CreateInstance (), applyWindowsRuntimeProjections: true); + } + + [Test] + public void CanStripType () + { + if (Platform.OnMono) + return; + + var assemblyResolver = WindowsRuntimeAssemblyResolver.CreateInstance (); + + TestModule (ModuleName, (originalModule) => { + var types = CustomListTypeNames.Select (typeName => originalModule.Types.Single (t => t.Name == typeName)).ToArray (); + + foreach (var type in types) + originalModule.Types.Remove (type); + + var tmpPath = Path.GetTempFileName (); + originalModule.Write (tmpPath); + + try { + TestModule (tmpPath, (modifiedModule) => { + foreach (var type in types) + Assert.IsTrue (!modifiedModule.Types.Any (t => t.FullName == type.FullName)); + }, verify: false, assemblyResolver: assemblyResolver, applyWindowsRuntimeProjections: true); + } finally { + File.Delete (tmpPath); + } + }, readOnly: true, verify: false, assemblyResolver: assemblyResolver, applyWindowsRuntimeProjections: true); + } + } + + [TestFixture] + public class ManagedWindowsRuntimeProjectionsTests : BaseWindowsRuntimeProjectionsTests { + protected override string ModuleName { get { return "ManagedWinmd.winmd"; } } + + protected override MetadataKind ExpectedMetadataKind { get { return MetadataKind.ManagedWindowsMetadata; } } + + protected override string [] ManagedClassTypeNames { get { return new [] { "ManagedClass", "ManagedClass" }; } } + + protected override string [] CustomListTypeNames { get { return new [] { "CustomList", "CustomList" }; } } + + [Test] + public void CanProjectClasses () + { + if (Platform.OnMono) + return; + + TestModule (ModuleName, (module) => { + var managedClassType = module.Types.Single (t => t.Name == "ManagedClass"); + Assert.AreEqual ("ManagedClass", managedClassType.WindowsRuntimeProjection.Name); + Assert.AreEqual (TypeDefinitionTreatment.UnmangleWindowsRuntimeName, managedClassType.WindowsRuntimeProjection.Treatment); + + var someOtherClassType = module.Types.Single (t => t.Name == "SomeOtherClass"); + Assert.AreEqual ("SomeOtherClass", someOtherClassType.WindowsRuntimeProjection.Name); + Assert.AreEqual (TypeDefinitionTreatment.UnmangleWindowsRuntimeName, someOtherClassType.WindowsRuntimeProjection.Treatment); + + var winrtManagedClassType = module.Types.Single (t => t.Name == "ManagedClass"); + Assert.AreEqual ("ManagedClass", winrtManagedClassType.WindowsRuntimeProjection.Name); + Assert.AreEqual (TypeDefinitionTreatment.PrefixWindowsRuntimeName, winrtManagedClassType.WindowsRuntimeProjection.Treatment); + + var winrtSomeOtherClassType = module.Types.Single (t => t.Name == "SomeOtherClass"); + Assert.AreEqual ("SomeOtherClass", winrtSomeOtherClassType.WindowsRuntimeProjection.Name); + Assert.AreEqual (TypeDefinitionTreatment.PrefixWindowsRuntimeName, winrtSomeOtherClassType.WindowsRuntimeProjection.Treatment); + }, verify: false, assemblyResolver: WindowsRuntimeAssemblyResolver.CreateInstance (), applyWindowsRuntimeProjections: true); + } + } + + [TestFixture] + public class NativeWindowsRuntimeProjectionsTests : BaseWindowsRuntimeProjectionsTests { + protected override string ModuleName { get { return "NativeWinmd.winmd"; } } + + protected override MetadataKind ExpectedMetadataKind { get { return MetadataKind.WindowsMetadata; } } + + protected override string [] ManagedClassTypeNames { get { return new [] { "ManagedClass" }; } } + + protected override string [] CustomListTypeNames { get { return new [] { "CustomList" }; } } + } +} diff --git a/external/cecil/Test/Resources/assemblies/ManagedWinmd.winmd b/external/cecil/Test/Resources/assemblies/ManagedWinmd.winmd new file mode 100644 index 0000000000..070ba28fe3 Binary files /dev/null and b/external/cecil/Test/Resources/assemblies/ManagedWinmd.winmd differ diff --git a/external/cecil/Test/Resources/assemblies/NativeWinmd.winmd b/external/cecil/Test/Resources/assemblies/NativeWinmd.winmd new file mode 100644 index 0000000000..53fedff797 Binary files /dev/null and b/external/cecil/Test/Resources/assemblies/NativeWinmd.winmd differ diff --git a/external/cecil/Test/Resources/assemblies/PdbTarget.pdb b/external/cecil/Test/Resources/assemblies/PdbTarget.pdb new file mode 100644 index 0000000000..3c6fc6beee Binary files /dev/null and b/external/cecil/Test/Resources/assemblies/PdbTarget.pdb differ diff --git a/external/cecil/Test/Resources/assemblies/cecil.pdb.REMOVED.git-id b/external/cecil/Test/Resources/assemblies/cecil.pdb.REMOVED.git-id new file mode 100644 index 0000000000..7ecbe08d06 --- /dev/null +++ b/external/cecil/Test/Resources/assemblies/cecil.pdb.REMOVED.git-id @@ -0,0 +1 @@ +e0938af534eadba5f71dca123cc75e3e9bdf8c63 \ No newline at end of file diff --git a/external/cecil/Test/Resources/assemblies/text_file.txt b/external/cecil/Test/Resources/assemblies/text_file.txt index 5de1caf882..ea780ea5b4 100644 --- a/external/cecil/Test/Resources/assemblies/text_file.txt +++ b/external/cecil/Test/Resources/assemblies/text_file.txt @@ -1 +1 @@ -Cecil ftw! +Cecil ftw! diff --git a/external/cecil/Test/Resources/assemblies/winrtcomp.winmd b/external/cecil/Test/Resources/assemblies/winrtcomp.winmd new file mode 100644 index 0000000000..efaa4e741d Binary files /dev/null and b/external/cecil/Test/Resources/assemblies/winrtcomp.winmd differ diff --git a/external/cecil/Test/Resources/cs/CustomAttributes.cs b/external/cecil/Test/Resources/cs/CustomAttributes.cs index 4c52c7c512..dc2839b77d 100644 --- a/external/cecil/Test/Resources/cs/CustomAttributes.cs +++ b/external/cecil/Test/Resources/cs/CustomAttributes.cs @@ -150,3 +150,9 @@ class OpenGeneric { [Foo (typeof (Dictionary[,]>))] class ClosedGeneric { } + +[Foo (typeof (Parent.Child[]))] +class Parent { + public class Child { + } +} diff --git a/external/cecil/Test/Resources/il/ca-empty-blob.il b/external/cecil/Test/Resources/il/ca-empty-blob.il new file mode 100644 index 0000000000..2d3d780d4e --- /dev/null +++ b/external/cecil/Test/Resources/il/ca-empty-blob.il @@ -0,0 +1,21 @@ +.assembly extern mscorlib +{ + .publickeytoken = (B7 7A 5C 56 19 34 E0 89) + .ver 2:0:0:0 +} + +.assembly CaEmptyBlob {} + +.module CaEmptyBlob.dll + +.class public auto ansi CustomAttribute extends [mscorlib]System.Attribute +{ + .custom instance void CustomAttribute::.ctor() = () + + .method public hidebysig specialname rtspecialname instance void .ctor() + { + ldarg.0 + call instance void [mscorlib]System.Attribute::.ctor() + ret + } +} diff --git a/external/cecil/Test/Resources/il/ca-iface-impl.il b/external/cecil/Test/Resources/il/ca-iface-impl.il new file mode 100644 index 0000000000..0428909398 --- /dev/null +++ b/external/cecil/Test/Resources/il/ca-iface-impl.il @@ -0,0 +1,35 @@ +.assembly extern mscorlib {} + +.assembly CA {} + +.module CA.dll + +.class public auto ansi beforefieldinit FooAttribute + extends [mscorlib]System.Attribute +{ + .method public hidebysig specialname rtspecialname instance void .ctor () + { + ldarg.0 + call instance void [mscorlib]System.Attribute::.ctor () + ret + } +} + +.class interface public auto ansi abstract IFoo +{ +} + +.class public auto ansi beforefieldinit FooType + extends [mscorlib]System.Object + implements IFoo +{ + .interfaceimpl type IFoo + .custom instance void FooAttribute::.ctor () + + .method public hidebysig specialname rtspecialname instance void .ctor () + { + ldarg.0 + call instance void [mscorlib]System.Object::.ctor () + ret + } +} diff --git a/external/cecil/Test/Resources/il/types.il b/external/cecil/Test/Resources/il/types.il index b230c21828..4c9acafb5e 100644 --- a/external/cecil/Test/Resources/il/types.il +++ b/external/cecil/Test/Resources/il/types.il @@ -44,15 +44,3 @@ .field private static literal int16 int16_char = char(0x0073) .field private static literal int32 int32_nullref = nullref } - -.class public auto ansi CustomAttribute extends [mscorlib]System.Attribute -{ - .custom instance void CustomAttribute::.ctor() = () - - .method public hidebysig specialname rtspecialname instance void .ctor() - { - ldarg.0 - call instance void [mscorlib]System.Attribute::.ctor() - ret - } -} diff --git a/external/cecil/Test/libs/nunit-2.6.2/license.txt b/external/cecil/Test/libs/nunit-2.6.2/license.txt old mode 100755 new mode 100644 index 724e4652e8..530a6e0036 --- a/external/cecil/Test/libs/nunit-2.6.2/license.txt +++ b/external/cecil/Test/libs/nunit-2.6.2/license.txt @@ -1,15 +1,15 @@ -Copyright © 2002-2012 Charlie Poole -Copyright © 2002-2004 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov -Copyright © 2000-2002 Philip A. Craig - -This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment (see the following) in the product documentation is required. - -Portions Copyright © 2002-2012 Charlie Poole or Copyright © 2002-2004 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov or Copyright © 2000-2002 Philip A. Craig - -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. - -3. This notice may not be removed or altered from any source distribution. +Copyright © 2002-2012 Charlie Poole +Copyright © 2002-2004 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov +Copyright © 2000-2002 Philip A. Craig + +This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment (see the following) in the product documentation is required. + +Portions Copyright © 2002-2012 Charlie Poole or Copyright © 2002-2004 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov or Copyright © 2000-2002 Philip A. Craig + +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source distribution. diff --git a/external/cecil/appveyor.yml b/external/cecil/appveyor.yml new file mode 100644 index 0000000000..9150a13a3a --- /dev/null +++ b/external/cecil/appveyor.yml @@ -0,0 +1,13 @@ +version: 0.9.6.{build} +configuration: net_4_0_Debug +build: + project: Mono.Cecil.sln + verbosity: minimal +test_script: +- nunit-console.exe Mono.Cecil.nunit +notifications: +- provider: Webhook + url: https://webhooks.gitter.im/e/925de8a68a6d8d3ce68e + on_build_success: false + on_build_failure: false + on_build_status_changed: true \ No newline at end of file diff --git a/external/cecil/core/.vscode/launch.json b/external/cecil/core/.vscode/launch.json new file mode 100644 index 0000000000..97c58382de --- /dev/null +++ b/external/cecil/core/.vscode/launch.json @@ -0,0 +1,22 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": ".NET Core Launch (console)", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + "program": "${workspaceRoot}/bin/Debug//", + "args": [], + "cwd": "${workspaceRoot}", + "externalConsole": false, + "stopAtEntry": false + }, + { + "name": ".NET Core Attach", + "type": "coreclr", + "request": "attach", + "processId": "${command.pickProcess}" + } + ] +} \ No newline at end of file diff --git a/external/cecil/core/.vscode/tasks.json b/external/cecil/core/.vscode/tasks.json new file mode 100644 index 0000000000..c73077e1cf --- /dev/null +++ b/external/cecil/core/.vscode/tasks.json @@ -0,0 +1,16 @@ +{ + "version": "0.1.0", + "command": "dotnet", + "isShellCommand": true, + "args": [], + "tasks": [ + { + "taskName": "build", + "args": [ + "" + ], + "isBuildCommand": true, + "problemMatcher": "$msCompile" + } + ] +} \ No newline at end of file diff --git a/external/cecil/core/project.json b/external/cecil/core/project.json new file mode 100644 index 0000000000..6e2a3d43b6 --- /dev/null +++ b/external/cecil/core/project.json @@ -0,0 +1,43 @@ +{ + "name": "Mono.Cecil", + "version": "0.10.0.0", + "authors": [ "Jb Evain" ], + "description": "Cecil is a library to generate and inspect programs and libraries in the ECMA CIL form", + + "buildOptions": { + "outputName": "Mono.Cecil", + "debugType": "portable", + "define": [ "NET_CORE", "NET_4_0" ], + "compile": { + "include": [ + "../Mono/*.cs", + "../Mono.Cecil/*.cs", + "../Mono.Cecil.Cil/*.cs", + "../Mono.Cecil.Metadata/*.cs", + "../Mono.Cecil.PE/*.cs", + "../Mono.Collections.Generic/*.cs", + "../Mono.Security.Cryptography/*.cs", + "../System.Runtime.CompilerServices/*.cs" + ], + "exclude": [ + "../rocks/**", + "../symbols/**", + "../Test/**" + ] + } + }, + + "dependencies": { + "System.Collections": "4.0.11", + "System.IO.FileSystem": "4.0.1", + "System.IO.FileSystem.Primitives": "4.0.1", + "System.Reflection": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Security.Cryptography.Algorithms": "4.2.0", + "System.Security.Cryptography.Csp": "4.0.0", + "System.Threading": "4.0.11" + }, + "frameworks": { + "netstandard1.3": {} + } +} diff --git a/external/cecil/rocks/Mono.Cecil.Rocks.csproj b/external/cecil/rocks/Mono.Cecil.Rocks.csproj index 6d34f0b3d9..bc52246f29 100644 --- a/external/cecil/rocks/Mono.Cecil.Rocks.csproj +++ b/external/cecil/rocks/Mono.Cecil.Rocks.csproj @@ -1,116 +1,14 @@ - net_4_0_Debug - AnyCPU - 9.0.30729 - 2.0 {FBC6DD59-D09D-499C-B03C-99C1C78FF2AC} - Library - Properties Mono.Cecil.Rocks Mono.Cecil.Rocks - 512 - true - ..\mono.snk - - - true - full - false - ..\bin\net_3_5_Debug\ - DEBUG;TRACE;INSIDE_ROCKS;NET_3_5 - prompt - 4 - v3.5 - - - pdbonly - true - ..\bin\net_3_5_Release\ - TRACE;INSIDE_ROCKS;NET_3_5 - prompt - 4 - v3.5 - - - true - full - false - ..\bin\net_4_0_Debug\ - DEBUG;TRACE;INSIDE_ROCKS;NET_3_5;NET_4_0 - prompt - 4 - v4.0 - - - pdbonly - true - ..\bin\net_4_0_Release\ - TRACE;INSIDE_ROCKS;NET_3_5;NET_4_0 - prompt - 4 - v4.0 - - - true - full - false - ..\bin\silverlight_Debug\ - DEBUG;TRACE;NET_3_5;NET_4_0;SILVERLIGHT - prompt - 4 - Silverlight - v4.0 - - - pdbonly - true - ..\bin\silverlight_Release\ - TRACE;NET_3_5;NET_4_0;SILVERLIGHT - prompt - 4 - Silverlight - v4.0 - - - true - full - false - ..\bin\winphone_Debug\ - DEBUG;TRACE;NET_3_5;NET_4_0;SILVERLIGHT;CF - prompt - 4 - WindowsPhone - Silverlight - v4.0 - - - pdbonly - true - ..\bin\winphone_Release\ - TRACE;NET_3_5;NET_4_0;SILVERLIGHT;CF - prompt - 4 - WindowsPhone - Silverlight - v4.0 + $(DefineConstants);INSIDE_ROCKS - - 3.5 - - - - - - - - - - - - + + @@ -118,12 +16,6 @@ Mono.Cecil - - + + \ No newline at end of file diff --git a/external/cecil/rocks/Mono.Cecil.Rocks/AssemblyInfo.cs b/external/cecil/rocks/Mono.Cecil.Rocks/AssemblyInfo.cs index 90543bb5e2..489ddee631 100644 --- a/external/cecil/rocks/Mono.Cecil.Rocks/AssemblyInfo.cs +++ b/external/cecil/rocks/Mono.Cecil.Rocks/AssemblyInfo.cs @@ -1,41 +1,16 @@ // -// AssemblyInfo.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; using System.Reflection; -using System.Runtime.InteropServices; [assembly: AssemblyTitle ("Mono.Cecil.Rocks")] -[assembly: AssemblyProduct ("Mono.Cecil")] -[assembly: AssemblyCopyright ("Copyright © 2008 - 2011 Jb Evain")] [assembly: CLSCompliant (false)] -[assembly: ComVisible (false)] - -[assembly: AssemblyVersion ("0.9.5.0")] -[assembly: AssemblyFileVersion ("0.9.5.0")] diff --git a/external/cecil/rocks/Mono.Cecil.Rocks/DocCommentId.cs b/external/cecil/rocks/Mono.Cecil.Rocks/DocCommentId.cs new file mode 100644 index 0000000000..0ab2caf078 --- /dev/null +++ b/external/cecil/rocks/Mono.Cecil.Rocks/DocCommentId.cs @@ -0,0 +1,264 @@ +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. +// +// Licensed under the MIT/X11 license. +// + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Mono.Cecil.Rocks { + + public class DocCommentId + { + StringBuilder id; + + DocCommentId () + { + id = new StringBuilder (); + } + + void WriteField (FieldDefinition field) + { + WriteDefinition ('F', field); + } + + void WriteEvent (EventDefinition @event) + { + WriteDefinition ('E', @event); + } + + void WriteType (TypeDefinition type) + { + id.Append ('T').Append (':'); + WriteTypeFullName (type); + } + + void WriteMethod (MethodDefinition method) + { + WriteDefinition ('M', method); + + if (method.HasGenericParameters) { + id.Append ('`').Append ('`'); + id.Append (method.GenericParameters.Count); + } + + if (method.HasParameters) + WriteParameters (method.Parameters); + + if (IsConversionOperator (method)) + WriteReturnType (method); + } + + static bool IsConversionOperator (MethodDefinition self) + { + if (self == null) + throw new ArgumentNullException ("self"); + + return self.IsSpecialName + && (self.Name == "op_Explicit" || self.Name == "op_Implicit"); + } + + void WriteReturnType (MethodDefinition method) + { + id.Append ('~'); + WriteTypeSignature (method.ReturnType); + } + + void WriteProperty (PropertyDefinition property) + { + WriteDefinition ('P', property); + + if (property.HasParameters) + WriteParameters (property.Parameters); + } + + void WriteParameters (IList parameters) + { + id.Append ('('); + WriteList (parameters, p => WriteTypeSignature (p.ParameterType)); + id.Append (')'); + } + + void WriteTypeSignature (TypeReference type) + { + switch (type.MetadataType) + { + case MetadataType.Array: + WriteArrayTypeSignature ((ArrayType) type); + break; + case MetadataType.ByReference: + WriteTypeSignature (((ByReferenceType) type).ElementType); + id.Append ('@'); + break; + case MetadataType.FunctionPointer: + WriteFunctionPointerTypeSignature ((FunctionPointerType) type); + break; + case MetadataType.GenericInstance: + WriteGenericInstanceTypeSignature ((GenericInstanceType) type); + break; + case MetadataType.Var: + id.Append ('`'); + id.Append (((GenericParameter) type).Position); + break; + case MetadataType.MVar: + id.Append ('`').Append ('`'); + id.Append (((GenericParameter) type).Position); + break; + case MetadataType.OptionalModifier: + WriteModiferTypeSignature ((RequiredModifierType) type, '!'); + break; + case MetadataType.RequiredModifier: + WriteModiferTypeSignature ((RequiredModifierType) type, '|'); + break; + case MetadataType.Pointer: + WriteTypeSignature (((PointerType) type).ElementType); + id.Append ('*'); + break; + default: + WriteTypeFullName (type); + break; + } + } + + void WriteGenericInstanceTypeSignature (GenericInstanceType type) + { + if (type.ElementType.IsTypeSpecification ()) + throw new NotSupportedException (); + + WriteTypeFullName (type.ElementType, stripGenericArity: true); + id.Append ('{'); + WriteList (type.GenericArguments, WriteTypeSignature); + id.Append ('}'); + } + + void WriteList (IList list, Action action) + { + for (int i = 0; i < list.Count; i++) { + if (i > 0) + id.Append (','); + + action (list [i]); + } + } + + void WriteModiferTypeSignature (IModifierType type, char id) + { + WriteTypeSignature (type.ElementType); + this.id.Append (id); + WriteTypeSignature (type.ModifierType); + } + + void WriteFunctionPointerTypeSignature (FunctionPointerType type) + { + id.Append ("=FUNC:"); + WriteTypeSignature (type.ReturnType); + + if (type.HasParameters) + WriteParameters (type.Parameters); + } + + void WriteArrayTypeSignature (ArrayType type) + { + WriteTypeSignature (type.ElementType); + + if (type.IsVector) { + id.Append ("[]"); + return; + } + + id.Append ("["); + + WriteList (type.Dimensions, dimension => { + if (dimension.LowerBound.HasValue) + id.Append (dimension.LowerBound.Value); + + id.Append (':'); + + if (dimension.UpperBound.HasValue) + id.Append (dimension.UpperBound.Value - (dimension.LowerBound.GetValueOrDefault () + 1)); + }); + + id.Append ("]"); + } + + void WriteDefinition (char id, IMemberDefinition member) + { + this.id.Append (id) + .Append (':'); + + WriteTypeFullName (member.DeclaringType); + this.id.Append ('.'); + WriteItemName (member.Name); + } + + void WriteTypeFullName (TypeReference type, bool stripGenericArity = false) + { + if (type.DeclaringType != null) { + WriteTypeFullName (type.DeclaringType); + id.Append ('.'); + } + + if (!string.IsNullOrEmpty (type.Namespace)) { + id.Append (type.Namespace); + id.Append ('.'); + } + + var name = type.Name; + + if (stripGenericArity) { + var index = name.LastIndexOf ('`'); + if (index > 0) + name = name.Substring (0, index); + } + + id.Append (name); + } + + void WriteItemName (string name) + { + id.Append (name.Replace ('.', '#')); + } + + public override string ToString () + { + return id.ToString (); + } + + public static string GetDocCommentId (IMemberDefinition member) + { + if (member == null) + throw new ArgumentNullException ("member"); + + var documentId = new DocCommentId (); + + switch (member.MetadataToken.TokenType) + { + case TokenType.Field: + documentId.WriteField ((FieldDefinition) member); + break; + case TokenType.Method: + documentId.WriteMethod ((MethodDefinition) member); + break; + case TokenType.TypeDef: + documentId.WriteType ((TypeDefinition) member); + break; + case TokenType.Event: + documentId.WriteEvent ((EventDefinition) member); + break; + case TokenType.Property: + documentId.WriteProperty ((PropertyDefinition) member); + break; + default: + throw new NotSupportedException (member.FullName); + } + + return documentId.ToString (); + } + } +} diff --git a/external/cecil/rocks/Mono.Cecil.Rocks/Functional.cs b/external/cecil/rocks/Mono.Cecil.Rocks/Functional.cs index 0e61b47bca..bff52e4a29 100644 --- a/external/cecil/rocks/Mono.Cecil.Rocks/Functional.cs +++ b/external/cecil/rocks/Mono.Cecil.Rocks/Functional.cs @@ -1,29 +1,11 @@ // -// Functional.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; diff --git a/external/cecil/rocks/Mono.Cecil.Rocks/ILParser.cs b/external/cecil/rocks/Mono.Cecil.Rocks/ILParser.cs index 6f745bc125..8d119eb0d6 100644 --- a/external/cecil/rocks/Mono.Cecil.Rocks/ILParser.cs +++ b/external/cecil/rocks/Mono.Cecil.Rocks/ILParser.cs @@ -1,29 +1,11 @@ // -// ILParser.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; @@ -79,8 +61,6 @@ namespace Mono.Cecil.Rocks { var context = CreateContext (method, visitor); var code = context.Code; - code.MoveTo (method.RVA); - var flags = code.ReadByte (); switch (flags & 0x3) { @@ -89,7 +69,7 @@ namespace Mono.Cecil.Rocks { ParseCode (code_size, context); break; case 0x3: // fat - code.position--; + code.Advance (-1); ParseFatMethod (context); break; default: @@ -99,7 +79,8 @@ namespace Mono.Cecil.Rocks { static ParseContext CreateContext (MethodDefinition method, IILVisitor visitor) { - var code = method.Module.Read (method, (_, reader) => new CodeReader (reader.image.MetadataSection, reader)); + var code = method.Module.Read (method, (_, reader) => reader.code); + code.MoveTo (method); return new ParseContext { Code = code, @@ -128,10 +109,10 @@ namespace Mono.Cecil.Rocks { var metadata = context.Metadata; var visitor = context.Visitor; - var start = code.position; + var start = code.Position; var end = start + code_size; - while (code.position < end) { + while (code.Position < end) { var il_opcode = code.ReadByte (); var opcode = il_opcode != 0xfe ? OpCodes.OneByteOpCode [il_opcode] diff --git a/external/cecil/rocks/Mono.Cecil.Rocks/MethodBodyRocks.cs b/external/cecil/rocks/Mono.Cecil.Rocks/MethodBodyRocks.cs index f141f60848..2ff43c3e21 100644 --- a/external/cecil/rocks/Mono.Cecil.Rocks/MethodBodyRocks.cs +++ b/external/cecil/rocks/Mono.Cecil.Rocks/MethodBodyRocks.cs @@ -1,29 +1,11 @@ // -// MethodBodyRocks.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; diff --git a/external/cecil/rocks/Mono.Cecil.Rocks/MethodDefinitionRocks.cs b/external/cecil/rocks/Mono.Cecil.Rocks/MethodDefinitionRocks.cs index c2f758d2e6..3ef20a1003 100644 --- a/external/cecil/rocks/Mono.Cecil.Rocks/MethodDefinitionRocks.cs +++ b/external/cecil/rocks/Mono.Cecil.Rocks/MethodDefinitionRocks.cs @@ -1,29 +1,11 @@ // -// MethodDefinitionRocks.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; @@ -41,6 +23,8 @@ namespace Mono.Cecil.Rocks { throw new ArgumentNullException ("self"); if (!self.IsVirtual) return self; + if (self.IsNewSlot) + return self; var base_type = ResolveBaseType (self.DeclaringType); while (base_type != null) { diff --git a/external/cecil/rocks/Mono.Cecil.Rocks/ModuleDefinitionRocks.cs b/external/cecil/rocks/Mono.Cecil.Rocks/ModuleDefinitionRocks.cs index 5aaf73ce9f..756d31f06a 100644 --- a/external/cecil/rocks/Mono.Cecil.Rocks/ModuleDefinitionRocks.cs +++ b/external/cecil/rocks/Mono.Cecil.Rocks/ModuleDefinitionRocks.cs @@ -1,29 +1,11 @@ // -// ModuleDefinitionRocks.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; diff --git a/external/cecil/rocks/Mono.Cecil.Rocks/SecurityDeclarationRocks.cs b/external/cecil/rocks/Mono.Cecil.Rocks/SecurityDeclarationRocks.cs index b84696fc6f..5c7517216a 100644 --- a/external/cecil/rocks/Mono.Cecil.Rocks/SecurityDeclarationRocks.cs +++ b/external/cecil/rocks/Mono.Cecil.Rocks/SecurityDeclarationRocks.cs @@ -1,32 +1,12 @@ // -// SecurityDeclarationRocks.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: +// Licensed under the MIT/X11 license. // -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// - -#if !SILVERLIGHT && !CF using System; using System.Security; @@ -170,5 +150,3 @@ namespace Mono.Cecil.Rocks { } } } - -#endif diff --git a/external/cecil/rocks/Mono.Cecil.Rocks/TypeDefinitionRocks.cs b/external/cecil/rocks/Mono.Cecil.Rocks/TypeDefinitionRocks.cs index 74b7f087fc..baa88e0341 100644 --- a/external/cecil/rocks/Mono.Cecil.Rocks/TypeDefinitionRocks.cs +++ b/external/cecil/rocks/Mono.Cecil.Rocks/TypeDefinitionRocks.cs @@ -1,29 +1,11 @@ // -// TypeDefinitionRocks.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; diff --git a/external/cecil/rocks/Mono.Cecil.Rocks/TypeReferenceRocks.cs b/external/cecil/rocks/Mono.Cecil.Rocks/TypeReferenceRocks.cs index 5748b178f6..c39523641c 100644 --- a/external/cecil/rocks/Mono.Cecil.Rocks/TypeReferenceRocks.cs +++ b/external/cecil/rocks/Mono.Cecil.Rocks/TypeReferenceRocks.cs @@ -1,29 +1,11 @@ // -// TypeReferenceRocks.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; diff --git a/external/cecil/rocks/Test/Mono.Cecil.Rocks.Tests.csproj b/external/cecil/rocks/Test/Mono.Cecil.Rocks.Tests.csproj index 93c5550e50..4019977632 100644 --- a/external/cecil/rocks/Test/Mono.Cecil.Rocks.Tests.csproj +++ b/external/cecil/rocks/Test/Mono.Cecil.Rocks.Tests.csproj @@ -1,73 +1,10 @@ - + - net_4_0_Debug - AnyCPU - 9.0.30729 - 2.0 {C6CFD7E1-B855-44DC-B4CE-9CD72984AF52} - Library - Properties Mono.Cecil.Rocks.Tests Mono.Cecil.Rocks.Tests - 512 - - true - full - false - bin\net_3_5_Debug\ - DEBUG;TRACE;NET_3_5 - prompt - 4 - v3.5 - - - pdbonly - true - bin\net_3_5_Release\ - TRACE;NET_3_5 - prompt - 4 - v3.5 - - - true - full - false - bin\net_4_0_Debug\ - DEBUG;TRACE;NET_3_5;NET_4_0 - prompt - 4 - v4.0 - - - pdbonly - true - bin\net_4_0_Release\ - TRACE;NET_3_5;NET_4_0 - prompt - 4 - v4.0 - - - - False - ..\..\Test\libs\nunit-2.6.2\nunit.core.dll - - - False - ..\..\Test\libs\nunit-2.6.2\nunit.core.interfaces.dll - - - False - ..\..\Test\libs\nunit-2.6.2\nunit.framework.dll - - - - 3.5 - - {D68133BD-1E63-496E-9EDE-4FBDBF77B486} @@ -83,24 +20,11 @@ - - - - - - - + - - + - - + + \ No newline at end of file diff --git a/external/cecil/rocks/Test/Mono.Cecil.Tests/DocCommentIdTests.cs b/external/cecil/rocks/Test/Mono.Cecil.Tests/DocCommentIdTests.cs new file mode 100644 index 0000000000..b18824c613 --- /dev/null +++ b/external/cecil/rocks/Test/Mono.Cecil.Tests/DocCommentIdTests.cs @@ -0,0 +1,264 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +using NUnit.Framework; + +using Mono.Cecil.Rocks; + +namespace N +{ + /// + /// ID string generated is "T:N.X". + /// + public class X + { + /// + /// ID string generated is "M:N.X.#ctor". + /// + public X() { } + + + /// + /// ID string generated is "M:N.X.#ctor(System.Int32)". + /// + /// Describe parameter. + public X(int i) { } + + + /// + /// ID string generated is "F:N.X.q". + /// + public string q; + + + /// + /// ID string generated is "F:N.X.PI". + /// + public const double PI = 3.14; + + + /// + /// ID string generated is "M:N.X.f". + /// + public int f() { return 1; } + + + /// + /// ID string generated is "M:N.X.bb(System.String,System.Int32@)". + /// + public int bb(string s, ref int y) { return 1; } + + + /// + /// ID string generated is "M:N.X.gg(System.Int16[],System.Int32[0:,0:])". + /// + public int gg(short[] array1, int[,] array) { return 0; } + + + /// + /// ID string generated is "M:N.X.op_Addition(N.X,N.X)". + /// + public static X operator +(X x, X xx) { return x; } + + + /// + /// ID string generated is "P:N.X.prop". + /// + public int prop { get { return 1; } set { } } + + + /// + /// ID string generated is "E:N.X.d". + /// +#pragma warning disable 67 + public event D d; +#pragma warning restore 67 + + + /// + /// ID string generated is "P:N.X.Item(System.String)". + /// + public int this[string s] { get { return 1; } } + + + /// + /// ID string generated is "T:N.X.Nested". + /// + public class Nested { } + + + /// + /// ID string generated is "T:N.X.D". + /// + public delegate void D(int i); + + + /// + /// ID string generated is "M:N.X.op_Explicit(N.X)~System.Int32". + /// + public static explicit operator int(X x) { return 1; } + + public static void Linq (IEnumerable enumerable, Func selector) + { + } + } +} + +namespace Mono.Cecil.Tests { + + [TestFixture] + public class DocCommentIdTests { + + [Test] + public void TypeDef () + { + AssertDocumentID ("T:N.X", GetTestType ()); + } + + [Test] + public void ParameterlessCtor () + { + var type = GetTestType (); + var ctor = type.GetConstructors ().Single (m => m.Parameters.Count == 0); + + AssertDocumentID ("M:N.X.#ctor", ctor); + } + + [Test] + public void CtorWithParameters () + { + var type = GetTestType (); + var ctor = type.GetConstructors ().Single (m => m.Parameters.Count == 1); + + AssertDocumentID ("M:N.X.#ctor(System.Int32)", ctor); + } + + [Test] + public void Field () + { + var type = GetTestType (); + var field = type.Fields.Single (m => m.Name == "q"); + + AssertDocumentID ("F:N.X.q", field); + } + + [Test] + public void ConstField () + { + var type = GetTestType (); + var field = type.Fields.Single (m => m.Name == "PI"); + + AssertDocumentID ("F:N.X.PI", field); + } + + [Test] + public void ParameterlessMethod () + { + var type = GetTestType (); + var method = type.Methods.Single (m => m.Name == "f"); + + AssertDocumentID ("M:N.X.f", method); + } + + [Test] + public void MethodWithByRefParameters () + { + var type = GetTestType (); + var method = type.Methods.Single (m => m.Name == "bb"); + + AssertDocumentID ("M:N.X.bb(System.String,System.Int32@)", method); + } + + [Test] + public void MethodWithArrayParameters () + { + var type = GetTestType (); + var method = type.Methods.Single (m => m.Name == "gg"); + + AssertDocumentID ("M:N.X.gg(System.Int16[],System.Int32[0:,0:])", method); + } + + [Test] + public void OpAddition () + { + var type = GetTestType (); + var op = type.Methods.Single (m => m.Name == "op_Addition"); + + AssertDocumentID ("M:N.X.op_Addition(N.X,N.X)", op); + } + + [Test] + public void OpExplicit () + { + var type = GetTestType (); + var op = type.Methods.Single (m => m.Name == "op_Explicit"); + + AssertDocumentID ("M:N.X.op_Explicit(N.X)~System.Int32", op); + } + + [Test] + public void Property () + { + var type = GetTestType (); + var property = type.Properties.Single (p => p.Name == "prop"); + + AssertDocumentID ("P:N.X.prop", property); + } + + [Test] + public void Indexer () + { + var type = GetTestType (); + var indexer = type.Properties.Single (p => p.Name == "Item"); + + AssertDocumentID ("P:N.X.Item(System.String)", indexer); + } + + [Test] + public void Event () + { + var type = GetTestType (); + var @event = type.Events.Single (e => e.Name == "d"); + + AssertDocumentID ("E:N.X.d", @event); + } + + [Test] + public void Delegate () + { + var type = GetTestType (); + var @delegate = type.NestedTypes.Single (t => t.Name == "D"); + + AssertDocumentID ("T:N.X.D", @delegate); + } + + [Test] + public void NestedType () + { + var type = GetTestType (); + var nestedType = type.NestedTypes.Single (t => t.Name == "Nested"); + + AssertDocumentID ("T:N.X.Nested", nestedType); + } + + [Test] + public void Linq () + { + var type = GetTestType (); + var method = type.GetMethod ("Linq"); + + AssertDocumentID ("M:N.X.Linq(System.Collections.Generic.IEnumerable{System.String},System.Func{System.String})", method); + } + + TypeDefinition GetTestType () + { + return typeof (N.X).ToDefinition (); + } + + static void AssertDocumentID (string docId, IMemberDefinition member) + { + Assert.AreEqual (docId, DocCommentId.GetDocCommentId (member)); + } + } +} diff --git a/external/cecil/rocks/Test/Mono.Cecil.Tests/MethodDefinitionRocksTests.cs b/external/cecil/rocks/Test/Mono.Cecil.Tests/MethodDefinitionRocksTests.cs index 2cfe0142a8..4c6e3fb514 100644 --- a/external/cecil/rocks/Test/Mono.Cecil.Tests/MethodDefinitionRocksTests.cs +++ b/external/cecil/rocks/Test/Mono.Cecil.Tests/MethodDefinitionRocksTests.cs @@ -11,18 +11,27 @@ namespace Mono.Cecil.Tests { abstract class Foo { public abstract void DoFoo (); + public abstract void DoBar (); } class Bar : Foo { public override void DoFoo () { } + + public override void DoBar () + { + } } class Baz : Bar { public override void DoFoo () { } + + public virtual new void DoBar () + { + } } [Test] @@ -38,6 +47,10 @@ namespace Mono.Cecil.Tests { Assert.AreEqual ("Foo", @base.DeclaringType.Name); Assert.AreEqual (@base, @base.GetBaseMethod ()); + + var new_dobar = baz.GetMethod ("DoBar"); + @base = new_dobar.GetBaseMethod(); + Assert.AreEqual("Baz", @base.DeclaringType.Name); } [Test] diff --git a/external/cecil/rocks/Test/Mono.Cecil.Tests/ModuleDefinitionRocksTests.cs b/external/cecil/rocks/Test/Mono.Cecil.Tests/ModuleDefinitionRocksTests.cs index f172b404e0..d0f5d01690 100644 --- a/external/cecil/rocks/Test/Mono.Cecil.Tests/ModuleDefinitionRocksTests.cs +++ b/external/cecil/rocks/Test/Mono.Cecil.Tests/ModuleDefinitionRocksTests.cs @@ -9,10 +9,11 @@ namespace Mono.Cecil.Tests { [TestFixture] public class ModuleDefinitionRocksTests : BaseTestFixture { - [TestCSharp ("Types.cs")] - public void GetAllTypesTest (ModuleDefinition module) + [Test] + public void GetAllTypesTest () { - var sequence = new [] { + TestCSharp ("Types.cs", module => { + var sequence = new [] { module.GetType (""), module.GetType ("Foo"), module.GetType ("Foo/Bar"), @@ -21,7 +22,8 @@ namespace Mono.Cecil.Tests { module.GetType ("Pan"), }; - Assert.IsTrue (sequence.SequenceEqual (module.GetAllTypes ())); + Assert.IsTrue (sequence.SequenceEqual (module.GetAllTypes ())); + }); } } } diff --git a/external/cecil/rocks/Test/Mono.Cecil.Tests/SecurityDeclarationRocksTests.cs b/external/cecil/rocks/Test/Mono.Cecil.Tests/SecurityDeclarationRocksTests.cs index e7efba127a..6598df76a6 100644 --- a/external/cecil/rocks/Test/Mono.Cecil.Tests/SecurityDeclarationRocksTests.cs +++ b/external/cecil/rocks/Test/Mono.Cecil.Tests/SecurityDeclarationRocksTests.cs @@ -9,50 +9,54 @@ namespace Mono.Cecil.Tests { [TestFixture] public class SecurityDeclarationRocksTests : BaseTestFixture { - [TestModule ("decsec-xml.dll")] - public void ToPermissionSetFromPermissionSetAttribute (ModuleDefinition module) + [Test] + public void ToPermissionSetFromPermissionSetAttribute () { - var type = module.GetType ("SubLibrary"); + TestModule ("decsec-xml.dll", module => { + var type = module.GetType ("SubLibrary"); - Assert.IsTrue (type.HasSecurityDeclarations); - Assert.AreEqual (1, type.SecurityDeclarations.Count); + Assert.IsTrue (type.HasSecurityDeclarations); + Assert.AreEqual (1, type.SecurityDeclarations.Count); - var declaration = type.SecurityDeclarations [0]; + var declaration = type.SecurityDeclarations [0]; - var permission_set = declaration.ToPermissionSet (); + var permission_set = declaration.ToPermissionSet (); - Assert.IsNotNull (permission_set); + Assert.IsNotNull (permission_set); - string permission_set_value = "\r\n\r\n\r\n"; - permission_set_value = string.Format (permission_set_value, typeof (SecurityPermission).AssemblyQualifiedName); + permission_set_value = string.Format (permission_set_value, typeof (SecurityPermission).AssemblyQualifiedName); - Assert.AreEqual (Normalize (permission_set_value), Normalize (permission_set.ToXml ().ToString ())); + Assert.AreEqual (Normalize (permission_set_value), Normalize (permission_set.ToXml ().ToString ())); + }); } - [TestModule ("decsec-att.dll")] - public void ToPermissionSetFromSecurityAttribute (ModuleDefinition module) + [Test] + public void ToPermissionSetFromSecurityAttribute () { - var type = module.GetType ("SubLibrary"); + TestModule ("decsec-att.dll", module => { + var type = module.GetType ("SubLibrary"); - Assert.IsTrue (type.HasSecurityDeclarations); - Assert.AreEqual (1, type.SecurityDeclarations.Count); + Assert.IsTrue (type.HasSecurityDeclarations); + Assert.AreEqual (1, type.SecurityDeclarations.Count); - var declaration = type.SecurityDeclarations [0]; + var declaration = type.SecurityDeclarations [0]; - var permission_set = declaration.ToPermissionSet (); + var permission_set = declaration.ToPermissionSet (); - Assert.IsNotNull (permission_set); + Assert.IsNotNull (permission_set); - string permission_set_value = "\r\n\r\n\r\n"; - permission_set_value = string.Format (permission_set_value, typeof (SecurityPermission).AssemblyQualifiedName); + permission_set_value = string.Format (permission_set_value, typeof (SecurityPermission).AssemblyQualifiedName); - Assert.AreEqual (Normalize (permission_set_value), Normalize (permission_set.ToXml ().ToString ())); + Assert.AreEqual (Normalize (permission_set_value), Normalize (permission_set.ToXml ().ToString ())); + }); } static string Normalize (string s) diff --git a/external/cecil/rocks/Test/Mono.Cecil.Tests/TypeReferenceRocksTests.cs b/external/cecil/rocks/Test/Mono.Cecil.Tests/TypeReferenceRocksTests.cs index 9f51cb634d..7f51f79be8 100644 --- a/external/cecil/rocks/Test/Mono.Cecil.Tests/TypeReferenceRocksTests.cs +++ b/external/cecil/rocks/Test/Mono.Cecil.Tests/TypeReferenceRocksTests.cs @@ -118,7 +118,7 @@ namespace Mono.Cecil.Tests { static TypeReference GetTypeReference (Type type) { - return ModuleDefinition.ReadModule (typeof (TypeReferenceRocksTests).Module.FullyQualifiedName).Import (type); + return ModuleDefinition.ReadModule (typeof (TypeReferenceRocksTests).Module.FullyQualifiedName).ImportReference (type); } } } \ No newline at end of file diff --git a/external/cecil/rocks/Test/Resources/cs/Types.cs b/external/cecil/rocks/Test/Resources/cs/Types.cs old mode 100755 new mode 100644 diff --git a/external/cecil/symbols/mdb/Mono.Cecil.Mdb.csproj b/external/cecil/symbols/mdb/Mono.Cecil.Mdb.csproj index 44c931e304..33a8f14762 100644 --- a/external/cecil/symbols/mdb/Mono.Cecil.Mdb.csproj +++ b/external/cecil/symbols/mdb/Mono.Cecil.Mdb.csproj @@ -1,75 +1,10 @@ - net_4_0_Debug - AnyCPU - 9.0.30729 - 2.0 {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD} - Library - Properties Mono.Cecil.Mdb Mono.Cecil.Mdb - 512 - true - ..\..\mono.snk - - - true - full - false - ..\..\bin\net_2_0_Debug\ - DEBUG;TRACE;CECIL - prompt - 4 - v2.0 - - - pdbonly - true - ..\..\bin\net_2_0_Release\ - TRACE;CECIL - prompt - 4 - v2.0 - - - true - full - false - ..\..\bin\net_3_5_Debug\ - DEBUG;TRACE;CECIL;NET_3_5 - prompt - 4 - v3.5 - - - pdbonly - true - ..\..\bin\net_3_5_Release\ - TRACE;CECIL;NET_3_5 - prompt - 4 - v3.5 - - - true - full - false - ..\..\bin\net_4_0_Debug\ - DEBUG;TRACE;CECIL;NET_3_5;NET_4_0 - prompt - 4 - v4.0 - - - pdbonly - true - ..\..\bin\net_4_0_Release\ - TRACE;CECIL;NET_3_5;NET_4_0 - prompt - 4 - v4.0 + $(DefineConstants);CECIL @@ -84,20 +19,10 @@ - - - - - - - + + + - - + + \ No newline at end of file diff --git a/external/cecil/symbols/mdb/Mono.Cecil.Mdb/AssemblyInfo.cs b/external/cecil/symbols/mdb/Mono.Cecil.Mdb/AssemblyInfo.cs index 8186b506bc..12f9bb6346 100644 --- a/external/cecil/symbols/mdb/Mono.Cecil.Mdb/AssemblyInfo.cs +++ b/external/cecil/symbols/mdb/Mono.Cecil.Mdb/AssemblyInfo.cs @@ -1,41 +1,16 @@ // -// AssemblyInfo.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; using System.Reflection; -using System.Runtime.InteropServices; [assembly: AssemblyTitle ("Mono.Cecil.Mdb")] -[assembly: AssemblyProduct ("Mono.Cecil")] -[assembly: AssemblyCopyright ("Copyright © 2008 - 2011 Jb Evain")] [assembly: CLSCompliant (false)] -[assembly: ComVisible (false)] - -[assembly: AssemblyVersion ("0.9.5.0")] -[assembly: AssemblyFileVersion ("0.9.5.0")] diff --git a/external/cecil/symbols/mdb/Mono.Cecil.Mdb/MdbReader.cs b/external/cecil/symbols/mdb/Mono.Cecil.Mdb/MdbReader.cs index 2440a6642b..610aa732b9 100644 --- a/external/cecil/symbols/mdb/Mono.Cecil.Mdb/MdbReader.cs +++ b/external/cecil/symbols/mdb/Mono.Cecil.Mdb/MdbReader.cs @@ -1,29 +1,11 @@ // -// MdbReader.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; @@ -36,20 +18,34 @@ using Mono.CompilerServices.SymbolWriter; namespace Mono.Cecil.Mdb { - public class MdbReaderProvider : ISymbolReaderProvider { + public sealed class MdbReaderProvider : ISymbolReaderProvider { public ISymbolReader GetSymbolReader (ModuleDefinition module, string fileName) { - return new MdbReader (module, MonoSymbolFile.ReadSymbolFile (module, fileName)); + Mixin.CheckModule (module); + Mixin.CheckFileName (fileName); + + return new MdbReader (module, MonoSymbolFile.ReadSymbolFile (Mixin.GetMdbFileName (fileName), module.Mvid)); } public ISymbolReader GetSymbolReader (ModuleDefinition module, Stream symbolStream) { - throw new NotImplementedException (); + Mixin.CheckModule (module); + Mixin.CheckStream (symbolStream); + + var file = MonoSymbolFile.ReadSymbolFile (symbolStream); + if (module.Mvid != file.Guid) { + var file_stream = symbolStream as FileStream; + if (file_stream != null) + throw new MonoSymbolFileException ("Symbol file `{0}' does not match assembly", file_stream.Name); + + throw new MonoSymbolFileException ("Symbol file from stream does not match assembly"); + } + return new MdbReader (module, file); } } - public class MdbReader : ISymbolReader { + public sealed class MdbReader : ISymbolReader { readonly ModuleDefinition module; readonly MonoSymbolFile symbol_file; @@ -67,28 +63,28 @@ namespace Mono.Cecil.Mdb { return symbol_file.Guid == module.Mvid; } - public void Read (MethodBody body, InstructionMapper mapper) + public MethodDebugInformation Read (MethodDefinition method) { - var method_token = body.Method.MetadataToken; + var method_token = method.MetadataToken; var entry = symbol_file.GetMethodByToken (method_token.ToInt32 ()); if (entry == null) - return; + return null; - var scopes = ReadScopes (entry, body, mapper); - ReadLineNumbers (entry, mapper); - ReadLocalVariables (entry, body, scopes); + var info = new MethodDebugInformation (method); + + var scopes = ReadScopes (entry, info); + ReadLineNumbers (entry, info); + ReadLocalVariables (entry, scopes); + + return info; } - static void ReadLocalVariables (MethodEntry entry, MethodBody body, Scope [] scopes) + static void ReadLocalVariables (MethodEntry entry, ScopeDebugInformation [] scopes) { var locals = entry.GetLocals (); foreach (var local in locals) { - if (local.Index < 0 || local.Index >= body.Variables.Count) // Mono 2.6 emits wrong local infos for iterators - continue; - - var variable = body.Variables [local.Index]; - variable.Name = local.Name; + var variable = new VariableDebugInformation (local.Index, local.Name); var index = local.BlockIndex; if (index < 0 || index >= scopes.Length) @@ -102,23 +98,18 @@ namespace Mono.Cecil.Mdb { } } - void ReadLineNumbers (MethodEntry entry, InstructionMapper mapper) + void ReadLineNumbers (MethodEntry entry, MethodDebugInformation info) { - Document document = null; var table = entry.GetLineNumberTable (); - foreach (var line in table.LineNumbers) { - var instruction = mapper (line.Offset); - if (instruction == null) + info.sequence_points = new Collection (table.LineNumbers.Length); + + for (var i = 0; i < table.LineNumbers.Length; i++) { + var line = table.LineNumbers [i]; + if (i > 0 && table.LineNumbers [i - 1].Offset == line.Offset) continue; - if (document == null) - document = GetDocument (entry.CompileUnit.SourceFile); - - instruction.SequencePoint = new SequencePoint (document) { - StartLine = line.Row, - EndLine = line.Row, - }; + info.sequence_points.Add (LineToSequencePoint (line)); } } @@ -130,41 +121,46 @@ namespace Mono.Cecil.Mdb { if (documents.TryGetValue (file_name, out document)) return document; - document = new Document (file_name); + document = new Document (file_name) { + Hash = file.Checksum, + }; + documents.Add (file_name, document); return document; } - static Scope [] ReadScopes (MethodEntry entry, MethodBody body, InstructionMapper mapper) + static ScopeDebugInformation [] ReadScopes (MethodEntry entry, MethodDebugInformation info) { var blocks = entry.GetCodeBlocks (); - var scopes = new Scope [blocks.Length]; + var scopes = new ScopeDebugInformation [blocks.Length + 1]; + + info.scope = scopes [0] = new ScopeDebugInformation { + Start = new InstructionOffset (0), + End = new InstructionOffset (info.code_size), + }; foreach (var block in blocks) { - if (block.BlockType != CodeBlockEntry.Type.Lexical) + if (block.BlockType != CodeBlockEntry.Type.Lexical && block.BlockType != CodeBlockEntry.Type.CompilerGenerated) continue; - var scope = new Scope (); - scope.Start = mapper (block.StartOffset); - scope.End = mapper (block.EndOffset); + var scope = new ScopeDebugInformation (); + scope.Start = new InstructionOffset (block.StartOffset); + scope.End = new InstructionOffset (block.EndOffset); - scopes [block.Index] = scope; + scopes [block.Index + 1] = scope; - if (body.Scope == null) - body.Scope = scope; - - if (!AddScope (body.Scope, scope)) - body.Scope = scope; + if (!AddScope (info.scope.Scopes, scope)) + info.scope.Scopes.Add (scope); } return scopes; } - static bool AddScope (Scope provider, Scope scope) + static bool AddScope (Collection scopes, ScopeDebugInformation scope) { - foreach (var sub_scope in provider.Scopes) { - if (AddScope (sub_scope, scope)) + foreach (var sub_scope in scopes) { + if (sub_scope.HasScopes && AddScope (sub_scope.Scopes, scope)) return true; if (scope.Start.Offset >= sub_scope.Start.Offset && scope.End.Offset <= sub_scope.End.Offset) { @@ -176,42 +172,15 @@ namespace Mono.Cecil.Mdb { return false; } - public void Read (MethodSymbols symbols) + SequencePoint LineToSequencePoint (LineNumberEntry line) { - var entry = symbol_file.GetMethodByToken (symbols.MethodToken.ToInt32 ()); - if (entry == null) - return; - - ReadLineNumbers (entry, symbols); - ReadLocalVariables (entry, symbols); - } - - void ReadLineNumbers (MethodEntry entry, MethodSymbols symbols) - { - var table = entry.GetLineNumberTable (); - var lines = table.LineNumbers; - - var instructions = symbols.instructions = new Collection (lines.Length); - - for (int i = 0; i < lines.Length; i++) { - var line = lines [i]; - - instructions.Add (new InstructionSymbol (line.Offset, new SequencePoint (GetDocument (entry.CompileUnit.SourceFile)) { - StartLine = line.Row, - EndLine = line.Row, - })); - } - } - - static void ReadLocalVariables (MethodEntry entry, MethodSymbols symbols) - { - foreach (var local in entry.GetLocals ()) { - if (local.Index < 0 || local.Index >= symbols.Variables.Count) // Mono 2.6 emits wrong local infos for iterators - continue; - - var variable = symbols.Variables [local.Index]; - variable.Name = local.Name; - } + var source = symbol_file.GetSourceFile (line.File); + return new SequencePoint (line.Offset, GetDocument (source)) { + StartLine = line.Row, + EndLine = line.EndRow, + StartColumn = line.Column, + EndColumn = line.EndColumn, + }; } public void Dispose () @@ -219,4 +188,17 @@ namespace Mono.Cecil.Mdb { symbol_file.Dispose (); } } + + static class MethodEntryExtensions { + + public static bool HasColumnInfo (this MethodEntry entry) + { + return (entry.MethodFlags & MethodEntry.Flags.ColumnsInfoIncluded) != 0; + } + + public static bool HasEndInfo (this MethodEntry entry) + { + return (entry.MethodFlags & MethodEntry.Flags.EndInfoIncluded) != 0; + } + } } diff --git a/external/cecil/symbols/mdb/Mono.Cecil.Mdb/MdbWriter.cs b/external/cecil/symbols/mdb/Mono.Cecil.Mdb/MdbWriter.cs index 6f4aa20e39..13e098a4da 100644 --- a/external/cecil/symbols/mdb/Mono.Cecil.Mdb/MdbWriter.cs +++ b/external/cecil/symbols/mdb/Mono.Cecil.Mdb/MdbWriter.cs @@ -1,29 +1,11 @@ // -// MdbWriter.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; @@ -37,10 +19,13 @@ using Mono.CompilerServices.SymbolWriter; namespace Mono.Cecil.Mdb { #if !READ_ONLY - public class MdbWriterProvider : ISymbolWriterProvider { + public sealed class MdbWriterProvider : ISymbolWriterProvider { public ISymbolWriter GetSymbolWriter (ModuleDefinition module, string fileName) { + Mixin.CheckModule (module); + Mixin.CheckFileName (fileName); + return new MdbWriter (module.Mvid, fileName); } @@ -50,7 +35,7 @@ namespace Mono.Cecil.Mdb { } } - public class MdbWriter : ISymbolWriter { + public sealed class MdbWriter : ISymbolWriter { readonly Guid mvid; readonly MonoSymbolWriter writer; @@ -63,16 +48,6 @@ namespace Mono.Cecil.Mdb { this.source_files = new Dictionary (); } - static Collection GetInstructions (MethodBody body) - { - var instructions = new Collection (); - foreach (var instruction in body.Instructions) - if (instruction.SequencePoint != null) - instructions.Add (instruction); - - return instructions; - } - SourceFile GetSourceFile (Document document) { var url = document.Url; @@ -81,7 +56,7 @@ namespace Mono.Cecil.Mdb { if (source_files.TryGetValue (url, out source_file)) return source_file; - var entry = writer.DefineDocument (url); + var entry = writer.DefineDocument (url, null, document.Hash != null && document.Hash.Length == 16 ? document.Hash : null); var compile_unit = writer.DefineCompilationUnit (entry); source_file = new SourceFile (compile_unit, entry); @@ -89,101 +64,107 @@ namespace Mono.Cecil.Mdb { return source_file; } - void Populate (Collection instructions, int [] offsets, - int [] startRows, int [] startCols, out SourceFile file) + void Populate (Collection sequencePoints, int [] offsets, + int [] startRows, int [] endRows, int [] startCols, int [] endCols, out SourceFile file) { SourceFile source_file = null; - for (int i = 0; i < instructions.Count; i++) { - var instruction = instructions [i]; - offsets [i] = instruction.Offset; + for (int i = 0; i < sequencePoints.Count; i++) { + var sequence_point = sequencePoints [i]; + offsets [i] = sequence_point.Offset; - var sequence_point = instruction.SequencePoint; if (source_file == null) source_file = GetSourceFile (sequence_point.Document); startRows [i] = sequence_point.StartLine; + endRows [i] = sequence_point.EndLine; startCols [i] = sequence_point.StartColumn; + endCols [i] = sequence_point.EndColumn; } file = source_file; } - public void Write (MethodBody body) + public void Write (MethodDebugInformation info) { - var method = new SourceMethod (body.Method); + var method = new SourceMethod (info.method); - var instructions = GetInstructions (body); - int count = instructions.Count; + var sequence_points = info.SequencePoints; + int count = sequence_points.Count; if (count == 0) return; var offsets = new int [count]; var start_rows = new int [count]; + var end_rows = new int [count]; var start_cols = new int [count]; + var end_cols = new int [count]; SourceFile file; - Populate (instructions, offsets, start_rows, start_cols, out file); + Populate (sequence_points, offsets, start_rows, end_rows, start_cols, end_cols, out file); var builder = writer.OpenMethod (file.CompilationUnit, 0, method); - for (int i = 0; i < count; i++) + for (int i = 0; i < count; i++) { builder.MarkSequencePoint ( offsets [i], file.CompilationUnit.SourceFile, start_rows [i], start_cols [i], + end_rows [i], + end_cols [i], false); + } - if (body.HasVariables) - AddVariables (body.Variables); + if (info.scope != null) + WriteRootScope (info.scope, info); writer.CloseMethod (); } - readonly static byte [] empty_header = new byte [0]; + void WriteRootScope (ScopeDebugInformation scope, MethodDebugInformation info) + { + WriteScopeVariables (scope); + + if (scope.HasScopes) + WriteScopes (scope.Scopes, info); + } + + void WriteScope (ScopeDebugInformation scope, MethodDebugInformation info) + { + writer.OpenScope (scope.Start.Offset); + + WriteScopeVariables (scope); + + if (scope.HasScopes) + WriteScopes (scope.Scopes, info); + + writer.CloseScope (scope.End.IsEndOfMethod ? info.code_size : scope.End.Offset); + } + + void WriteScopes (Collection scopes, MethodDebugInformation info) + { + for (int i = 0; i < scopes.Count; i++) + WriteScope (scopes [i], info); + } + + void WriteScopeVariables (ScopeDebugInformation scope) + { + if (!scope.HasVariables) + return; + + foreach (var variable in scope.variables) + if (!string.IsNullOrEmpty (variable.Name)) + writer.DefineLocalVariable (variable.Index, variable.Name); + } public bool GetDebugHeader (out ImageDebugDirectory directory, out byte [] header) { directory = new ImageDebugDirectory (); - header = empty_header; + header = Empty.Array; return false; } - void AddVariables (IList variables) - { - for (int i = 0; i < variables.Count; i++) { - var variable = variables [i]; - writer.DefineLocalVariable (i, variable.Name); - } - } - - public void Write (MethodSymbols symbols) - { - var method = new SourceMethodSymbol (symbols); - - var file = GetSourceFile (symbols.Instructions [0].SequencePoint.Document); - var builder = writer.OpenMethod (file.CompilationUnit, 0, method); - var count = symbols.Instructions.Count; - - for (int i = 0; i < count; i++) { - var instruction = symbols.Instructions [i]; - var sequence_point = instruction.SequencePoint; - - builder.MarkSequencePoint ( - instruction.Offset, - GetSourceFile (sequence_point.Document).CompilationUnit.SourceFile, - sequence_point.StartLine, - sequence_point.EndLine, - false); - } - - if (symbols.HasVariables) - AddVariables (symbols.Variables); - - writer.CloseMethod (); - } - public void Dispose () { writer.WriteSymbolFile (mvid); @@ -209,26 +190,6 @@ namespace Mono.Cecil.Mdb { } } - class SourceMethodSymbol : IMethodDef { - - readonly string name; - readonly int token; - - public string Name { - get { return name;} - } - - public int Token { - get { return token; } - } - - public SourceMethodSymbol (MethodSymbols symbols) - { - name = symbols.MethodName; - token = symbols.MethodToken.ToInt32 (); - } - } - class SourceMethod : IMethodDef { readonly MethodDefinition method; diff --git a/external/cecil/symbols/mdb/Mono.CompilerServices.SymbolWriter/MonoSymbolFile.cs b/external/cecil/symbols/mdb/Mono.CompilerServices.SymbolWriter/MonoSymbolFile.cs index 6ad39d237b..73e654d3b4 100644 --- a/external/cecil/symbols/mdb/Mono.CompilerServices.SymbolWriter/MonoSymbolFile.cs +++ b/external/cecil/symbols/mdb/Mono.CompilerServices.SymbolWriter/MonoSymbolFile.cs @@ -1,12 +1,13 @@ // -// Mono.CSharp.Debugger/MonoSymbolFile.cs +// MonoSymbolFile.cs // -// Author: +// Authors: // Martin Baulig (martin@ximian.com) +// Marek Safar (marek.safar@gmail.com) // // (C) 2003 Ximian, Inc. http://www.ximian.com +// Copyright (C) 2012 Xamarin Inc (http://www.xamarin.com) // - // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the @@ -30,10 +31,7 @@ using System; using System.Reflection; -using SRE = System.Reflection.Emit; using System.Collections.Generic; -using System.Text; -using System.Threading; using System.IO; namespace Mono.CompilerServices.SymbolWriter @@ -46,10 +44,16 @@ namespace Mono.CompilerServices.SymbolWriter public MonoSymbolFileException (string message, params object[] args) : base (String.Format (message, args)) - { } + { + } + + public MonoSymbolFileException (string message, Exception innerException) + : base (message, innerException) + { + } } - internal class MyBinaryWriter : BinaryWriter + sealed class MyBinaryWriter : BinaryWriter { public MyBinaryWriter (Stream stream) : base (stream) @@ -109,64 +113,11 @@ namespace Mono.CompilerServices.SymbolWriter } } -#if !CECIL - internal class MonoDebuggerSupport - { - static GetMethodTokenFunc get_method_token; - static GetGuidFunc get_guid; - static GetLocalIndexFunc get_local_index; - - delegate int GetMethodTokenFunc (MethodBase method); - delegate Guid GetGuidFunc (Module module); - delegate int GetLocalIndexFunc (SRE.LocalBuilder local); - - static Delegate create_delegate (Type type, Type delegate_type, string name) - { - MethodInfo mi = type.GetMethod (name, BindingFlags.Static | - BindingFlags.NonPublic); - if (mi == null) - throw new Exception ("Can't find " + name); - - return Delegate.CreateDelegate (delegate_type, mi); - } - - static MonoDebuggerSupport () - { - get_method_token = (GetMethodTokenFunc) create_delegate ( - typeof (Assembly), typeof (GetMethodTokenFunc), - "MonoDebugger_GetMethodToken"); - - get_guid = (GetGuidFunc) create_delegate ( - typeof (Module), typeof (GetGuidFunc), "Mono_GetGuid"); - - get_local_index = (GetLocalIndexFunc) create_delegate ( - typeof (SRE.LocalBuilder), typeof (GetLocalIndexFunc), - "Mono_GetLocalIndex"); - } - - public static int GetMethodToken (MethodBase method) - { - return get_method_token (method); - } - - public static Guid GetGuid (Module module) - { - return get_guid (module); - } - - public static int GetLocalIndex (SRE.LocalBuilder local) - { - return get_local_index (local); - } - } -#endif - public class MonoSymbolFile : IDisposable { List methods = new List (); List sources = new List (); List comp_units = new List (); - Dictionary type_hash = new Dictionary (); Dictionary anonymous_scopes; OffsetTable ot; @@ -174,41 +125,29 @@ namespace Mono.CompilerServices.SymbolWriter int last_method_index; int last_namespace_index; - public readonly string FileName = ""; public readonly int MajorVersion = OffsetTable.MajorVersion; public readonly int MinorVersion = OffsetTable.MinorVersion; public int NumLineNumbers; - internal MonoSymbolFile () + public MonoSymbolFile () { ot = new OffsetTable (); } - internal int AddSource (SourceFileEntry source) + public int AddSource (SourceFileEntry source) { sources.Add (source); return sources.Count; } - internal int AddCompileUnit (CompileUnitEntry entry) + public int AddCompileUnit (CompileUnitEntry entry) { comp_units.Add (entry); return comp_units.Count; } - internal int DefineType (Type type) - { - int index; - if (type_hash.TryGetValue (type, out index)) - return index; - - index = ++last_type_index; - type_hash.Add (type, index); - return index; - } - - internal void AddMethod (MethodEntry entry) + public void AddMethod (MethodEntry entry) { methods.Add (entry); } @@ -295,7 +234,7 @@ namespace Mono.CompilerServices.SymbolWriter // methods.Sort (); for (int i = 0; i < methods.Count; i++) - ((MethodEntry) methods [i]).Index = i + 1; + methods [i].Index = i + 1; // // Write data sections. @@ -314,7 +253,7 @@ namespace Mono.CompilerServices.SymbolWriter // ot.MethodTableOffset = (int) bw.BaseStream.Position; for (int i = 0; i < methods.Count; i++) { - MethodEntry entry = (MethodEntry) methods [i]; + MethodEntry entry = methods [i]; entry.Write (bw); } ot.MethodTableSize = (int) bw.BaseStream.Position - ot.MethodTableOffset; @@ -324,7 +263,7 @@ namespace Mono.CompilerServices.SymbolWriter // ot.SourceTableOffset = (int) bw.BaseStream.Position; for (int i = 0; i < sources.Count; i++) { - SourceFileEntry source = (SourceFileEntry) sources [i]; + SourceFileEntry source = sources [i]; source.Write (bw); } ot.SourceTableSize = (int) bw.BaseStream.Position - ot.SourceTableOffset; @@ -334,7 +273,7 @@ namespace Mono.CompilerServices.SymbolWriter // ot.CompileUnitTableOffset = (int) bw.BaseStream.Position; for (int i = 0; i < comp_units.Count; i++) { - CompileUnitEntry unit = (CompileUnitEntry) comp_units [i]; + CompileUnitEntry unit = comp_units [i]; unit.Write (bw); } ot.CompileUnitTableSize = (int) bw.BaseStream.Position - ot.CompileUnitTableOffset; @@ -391,10 +330,8 @@ namespace Mono.CompilerServices.SymbolWriter Guid guid; - MonoSymbolFile (string filename) + MonoSymbolFile (Stream stream) { - this.FileName = filename; - FileStream stream = new FileStream (filename, FileMode.Open, FileAccess.Read); reader = new MyBinaryReader (stream); try { @@ -403,94 +340,56 @@ namespace Mono.CompilerServices.SymbolWriter int minor_version = reader.ReadInt32 (); if (magic != OffsetTable.Magic) - throw new MonoSymbolFileException ( - "Symbol file `{0}' is not a valid " + - "Mono symbol file", filename); + throw new MonoSymbolFileException ("Symbol file is not a valid"); if (major_version != OffsetTable.MajorVersion) throw new MonoSymbolFileException ( - "Symbol file `{0}' has version {1}, " + - "but expected {2}", filename, major_version, - OffsetTable.MajorVersion); + "Symbol file has version {0} but expected {1}", major_version, OffsetTable.MajorVersion); if (minor_version != OffsetTable.MinorVersion) - throw new MonoSymbolFileException ( - "Symbol file `{0}' has version {1}.{2}, " + - "but expected {3}.{4}", filename, major_version, - minor_version, OffsetTable.MajorVersion, - OffsetTable.MinorVersion); + throw new MonoSymbolFileException ("Symbol file has version {0}.{1} but expected {2}.{3}", + major_version, minor_version, + OffsetTable.MajorVersion, OffsetTable.MinorVersion); MajorVersion = major_version; MinorVersion = minor_version; guid = new Guid (reader.ReadBytes (16)); ot = new OffsetTable (reader, major_version, minor_version); - } catch { - throw new MonoSymbolFileException ( - "Cannot read symbol file `{0}'", filename); + } catch (Exception e) { + throw new MonoSymbolFileException ("Cannot read symbol file", e); } source_file_hash = new Dictionary (); compile_unit_hash = new Dictionary (); } - void CheckGuidMatch (Guid other, string filename, string assembly) - { - if (other == guid) - return; - - throw new MonoSymbolFileException ( - "Symbol file `{0}' does not match assembly `{1}'", - filename, assembly); - } - -#if CECIL - protected MonoSymbolFile (string filename, Mono.Cecil.ModuleDefinition module) - : this (filename) - { - // Check that the MDB file matches the module, if we have been - // passed a module. - if (module == null) - return; - - CheckGuidMatch (module.Mvid, filename, module.FullyQualifiedName); - } - - public static MonoSymbolFile ReadSymbolFile (Mono.Cecil.ModuleDefinition module) - { - return ReadSymbolFile (module, module.FullyQualifiedName); - } - - public static MonoSymbolFile ReadSymbolFile (Mono.Cecil.ModuleDefinition module, string filename) - { - string name = filename + ".mdb"; - - return new MonoSymbolFile (name, module); - } -#else - protected MonoSymbolFile (string filename, Assembly assembly) : this (filename) - { - // Check that the MDB file matches the assembly, if we have been - // passed an assembly. - if (assembly == null) - return; - - Module[] modules = assembly.GetModules (); - Guid assembly_guid = MonoDebuggerSupport.GetGuid (modules [0]); - - CheckGuidMatch (assembly_guid, filename, assembly.Location); - } - public static MonoSymbolFile ReadSymbolFile (Assembly assembly) { string filename = assembly.Location; string name = filename + ".mdb"; - return new MonoSymbolFile (name, assembly); + Module[] modules = assembly.GetModules (); + Guid assembly_guid = modules[0].ModuleVersionId; + + return ReadSymbolFile (name, assembly_guid); } -#endif public static MonoSymbolFile ReadSymbolFile (string mdbFilename) { - return new MonoSymbolFile (mdbFilename); + return ReadSymbolFile (new FileStream (mdbFilename, FileMode.Open, FileAccess.Read)); + } + + public static MonoSymbolFile ReadSymbolFile (string mdbFilename, Guid assemblyGuid) + { + var sf = ReadSymbolFile (mdbFilename); + if (assemblyGuid != sf.guid) + throw new MonoSymbolFileException ("Symbol file `{0}' does not match assembly", mdbFilename); + + return sf; + } + + public static MonoSymbolFile ReadSymbolFile (Stream stream) + { + return new MonoSymbolFile (stream); } public int CompileUnitCount { @@ -648,7 +547,7 @@ namespace Mono.CompilerServices.SymbolWriter lock (this) { read_methods (); - return (MethodEntry) method_list [index - 1]; + return method_list [index - 1]; } } diff --git a/external/cecil/symbols/mdb/Mono.CompilerServices.SymbolWriter/MonoSymbolTable.cs b/external/cecil/symbols/mdb/Mono.CompilerServices.SymbolWriter/MonoSymbolTable.cs index c170150ce4..8ee9312f48 100644 --- a/external/cecil/symbols/mdb/Mono.CompilerServices.SymbolWriter/MonoSymbolTable.cs +++ b/external/cecil/symbols/mdb/Mono.CompilerServices.SymbolWriter/MonoSymbolTable.cs @@ -183,57 +183,56 @@ namespace Mono.CompilerServices.SymbolWriter { #region This is actually written to the symbol file public readonly int Row; + public int Column; + public int EndRow, EndColumn; public readonly int File; public readonly int Offset; - public readonly bool IsHidden; + public readonly bool IsHidden; // Obsolete is never used #endregion - public LineNumberEntry (int file, int row, int offset) - : this (file, row, offset, false) - { } + public sealed class LocationComparer : IComparer + { + public static readonly LocationComparer Default = new LocationComparer (); - public LineNumberEntry (int file, int row, int offset, bool is_hidden) + public int Compare (LineNumberEntry l1, LineNumberEntry l2) + { + return l1.Row == l2.Row ? + l1.Column.CompareTo (l2.Column) : + l1.Row.CompareTo (l2.Row); + } + } + + public static readonly LineNumberEntry Null = new LineNumberEntry (0, 0, 0, 0); + + public LineNumberEntry (int file, int row, int column, int offset) + : this (file, row, column, offset, false) + { + } + + public LineNumberEntry (int file, int row, int offset) + : this (file, row, -1, offset, false) + { + } + + public LineNumberEntry (int file, int row, int column, int offset, bool is_hidden) + : this (file, row, column, -1, -1, offset, is_hidden) + { + } + + public LineNumberEntry (int file, int row, int column, int end_row, int end_column, int offset, bool is_hidden) { this.File = file; this.Row = row; + this.Column = column; + this.EndRow = end_row; + this.EndColumn = end_column; this.Offset = offset; this.IsHidden = is_hidden; } - public static LineNumberEntry Null = new LineNumberEntry (0, 0, 0); - - private class OffsetComparerClass : IComparer - { - public int Compare (LineNumberEntry l1, LineNumberEntry l2) - { - if (l1.Offset < l2.Offset) - return -1; - else if (l1.Offset > l2.Offset) - return 1; - else - return 0; - } - } - - private class RowComparerClass : IComparer - { - public int Compare (LineNumberEntry l1, LineNumberEntry l2) - { - if (l1.Row < l2.Row) - return -1; - else if (l1.Row > l2.Row) - return 1; - else - return 0; - } - } - - public static readonly IComparer OffsetComparer = new OffsetComparerClass (); - public static readonly IComparer RowComparer = new RowComparerClass (); - public override string ToString () { - return String.Format ("[Line {0}:{1}:{2}]", File, Row, Offset); + return String.Format ("[Line {0}:{1,2}-{3,4}:{5}]", File, Row, Column, EndRow, EndColumn, Offset); } } @@ -610,6 +609,11 @@ namespace Mono.CompilerServices.SymbolWriter DataOffset = reader.ReadInt32 (); } + public void ReadAll () + { + ReadData (); + } + void ReadData () { if (creating) @@ -692,36 +696,50 @@ namespace Mono.CompilerServices.SymbolWriter creating = true; } - public SourceFileEntry (MonoSymbolFile file, string file_name, - byte[] guid, byte[] checksum) + public SourceFileEntry (MonoSymbolFile file, string file_name, byte[] guid, byte[] checksum) : this (file, file_name) { this.guid = guid; this.hash = checksum; } + public byte[] Checksum { + get { + return hash; + } + } + internal void WriteData (MyBinaryWriter bw) { DataOffset = (int) bw.BaseStream.Position; bw.Write (file_name); - if (guid == null) { - guid = Guid.NewGuid ().ToByteArray (); - try { - using (FileStream fs = new FileStream (file_name, FileMode.Open, FileAccess.Read)) { - MD5 md5 = MD5.Create (); - hash = md5.ComputeHash (fs); - } - } catch { - hash = new byte [16]; - } - } + if (guid == null) + guid = new byte[16]; + + if (hash == null) + hash = ComputeHash (); bw.Write (guid); bw.Write (hash); bw.Write ((byte) (auto_generated ? 1 : 0)); } + private byte [] ComputeHash () + { + if (!File.Exists (file_name)) + return new byte [16]; + + try { + using (FileStream fs = new FileStream (file_name, FileMode.Open, FileAccess.Read)) { + MD5 md5 = MD5.Create (); + return md5.ComputeHash (fs); + } + } catch { + return new byte [16]; + } + } + internal void Write (BinaryWriter bw) { bw.Write (Index); @@ -748,6 +766,7 @@ namespace Mono.CompilerServices.SymbolWriter public string FileName { get { return file_name; } + set { file_name = value; } } public bool AutoGenerated { @@ -802,7 +821,6 @@ namespace Mono.CompilerServices.SymbolWriter public const int Default_LineRange = 8; public const byte Default_OpcodeBase = 9; - public const bool SuppressDuplicates = true; #endregion public const byte DW_LNS_copy = 1; @@ -833,7 +851,7 @@ namespace Mono.CompilerServices.SymbolWriter this._line_numbers = lines; } - internal void Write (MonoSymbolFile file, MyBinaryWriter bw) + internal void Write (MonoSymbolFile file, MyBinaryWriter bw, bool hasColumnsInfo, bool hasEndInfo) { int start = (int) bw.BaseStream.Position; @@ -843,11 +861,6 @@ namespace Mono.CompilerServices.SymbolWriter int line_inc = LineNumbers [i].Row - last_line; int offset_inc = LineNumbers [i].Offset - last_offset; - if (SuppressDuplicates && (i+1 < LineNumbers.Length)) { - if (LineNumbers [i+1].Equals (LineNumbers [i])) - continue; - } - if (LineNumbers [i].File != last_file) { bw.Write (DW_LNS_set_file); bw.WriteLeb128 (LineNumbers [i].File); @@ -895,17 +908,37 @@ namespace Mono.CompilerServices.SymbolWriter bw.Write ((byte) 1); bw.Write (DW_LNE_end_sequence); + if (hasColumnsInfo) { + for (int i = 0; i < LineNumbers.Length; i++) { + var ln = LineNumbers [i]; + if (ln.Row >= 0) + bw.WriteLeb128 (ln.Column); + } + } + + if (hasEndInfo) { + for (int i = 0; i < LineNumbers.Length; i++) { + var ln = LineNumbers [i]; + if (ln.EndRow == -1 || ln.EndColumn == -1 || ln.Row > ln.EndRow) { + bw.WriteLeb128 (0xffffff); + } else { + bw.WriteLeb128 (ln.EndRow - ln.Row); + bw.WriteLeb128 (ln.EndColumn); + } + } + } + file.ExtendedLineNumberSize += (int) bw.BaseStream.Position - start; } - internal static LineNumberTable Read (MonoSymbolFile file, MyBinaryReader br) + internal static LineNumberTable Read (MonoSymbolFile file, MyBinaryReader br, bool readColumnsInfo, bool readEndInfo) { LineNumberTable lnt = new LineNumberTable (file); - lnt.DoRead (file, br); + lnt.DoRead (file, br, readColumnsInfo, readEndInfo); return lnt; } - void DoRead (MonoSymbolFile file, MyBinaryReader br) + void DoRead (MonoSymbolFile file, MyBinaryReader br, bool includesColumns, bool includesEnds) { var lines = new List (); @@ -922,7 +955,7 @@ namespace Mono.CompilerServices.SymbolWriter if (opcode == DW_LNE_end_sequence) { if (modified) lines.Add (new LineNumberEntry ( - stm_file, stm_line, stm_offset, is_hidden)); + stm_file, stm_line, -1, stm_offset, is_hidden)); break; } else if (opcode == DW_LNE_MONO_negate_is_hidden) { is_hidden = !is_hidden; @@ -931,9 +964,7 @@ namespace Mono.CompilerServices.SymbolWriter (opcode <= DW_LNE_MONO__extensions_end)) { ; // reserved for future extensions } else { - throw new MonoSymbolFileException ( - "Unknown extended opcode {0:x} in LNT ({1})", - opcode, file.FileName); + throw new MonoSymbolFileException ("Unknown extended opcode {0:x}", opcode); } br.BaseStream.Position = end_pos; @@ -942,7 +973,7 @@ namespace Mono.CompilerServices.SymbolWriter switch (opcode) { case DW_LNS_copy: lines.Add (new LineNumberEntry ( - stm_file, stm_line, stm_offset, is_hidden)); + stm_file, stm_line, -1, stm_offset, is_hidden)); modified = false; break; case DW_LNS_advance_pc: @@ -972,13 +1003,34 @@ namespace Mono.CompilerServices.SymbolWriter stm_offset += opcode / LineRange; stm_line += LineBase + (opcode % LineRange); lines.Add (new LineNumberEntry ( - stm_file, stm_line, stm_offset, is_hidden)); + stm_file, stm_line, -1, stm_offset, is_hidden)); modified = false; } } - _line_numbers = new LineNumberEntry [lines.Count]; - lines.CopyTo (_line_numbers, 0); + _line_numbers = lines.ToArray (); + + if (includesColumns) { + for (int i = 0; i < _line_numbers.Length; ++i) { + var ln = _line_numbers[i]; + if (ln.Row >= 0) + ln.Column = br.ReadLeb128 (); + } + } + if (includesEnds) { + for (int i = 0; i < _line_numbers.Length; ++i) { + var ln = _line_numbers[i]; + + int row = br.ReadLeb128 (); + if (row == 0xffffff) { + ln.EndRow = -1; + ln.EndColumn = -1; + } else { + ln.EndRow = ln.Row + row; + ln.EndColumn = br.ReadLeb128 (); + } + } + } } public bool GetMethodBounds (out LineNumberEntry start, out LineNumberEntry end) @@ -1035,7 +1087,9 @@ namespace Mono.CompilerServices.SymbolWriter [Flags] public enum Flags { - LocalNamesAmbiguous = 1 + LocalNamesAmbiguous = 1, + ColumnsInfoIncluded = 1 << 1, + EndInfoIncluded = 1 << 2 } public const int Size = 12; @@ -1123,7 +1177,7 @@ namespace Mono.CompilerServices.SymbolWriter } } - void CheckLineNumberTable (LineNumberEntry[] line_numbers) + static void CheckLineNumberTable (LineNumberEntry[] line_numbers) { int last_offset = -1; int last_row = -1; @@ -1188,8 +1242,13 @@ namespace Mono.CompilerServices.SymbolWriter bw.Write (real_name); } + foreach (var lne in lnt.LineNumbers) { + if (lne.EndRow != -1 || lne.EndColumn != -1) + flags |= Flags.EndInfoIncluded; + } + LineNumberTableOffset = (int) bw.BaseStream.Position; - lnt.Write (file, bw); + lnt.Write (file, bw, (flags & Flags.ColumnsInfoIncluded) != 0, (flags & Flags.EndInfoIncluded) != 0); DataOffset = (int) bw.BaseStream.Position; @@ -1204,6 +1263,15 @@ namespace Mono.CompilerServices.SymbolWriter bw.WriteLeb128 ((int) flags); } + public void ReadAll () + { + GetLineNumberTable (); + GetLocals (); + GetCodeBlocks (); + GetScopeVariables (); + GetRealName (); + } + public LineNumberTable GetLineNumberTable () { lock (SymbolFile) { @@ -1217,7 +1285,7 @@ namespace Mono.CompilerServices.SymbolWriter long old_pos = reader.BaseStream.Position; reader.BaseStream.Position = LineNumberTableOffset; - lnt = LineNumberTable.Read (SymbolFile, reader); + lnt = LineNumberTable.Read (SymbolFile, reader, (flags & Flags.ColumnsInfoIncluded) != 0, (flags & Flags.EndInfoIncluded) != 0); reader.BaseStream.Position = old_pos; return lnt; diff --git a/external/cecil/symbols/mdb/Mono.CompilerServices.SymbolWriter/MonoSymbolWriter.cs b/external/cecil/symbols/mdb/Mono.CompilerServices.SymbolWriter/MonoSymbolWriter.cs index db77c25270..19e14c2f6e 100644 --- a/external/cecil/symbols/mdb/Mono.CompilerServices.SymbolWriter/MonoSymbolWriter.cs +++ b/external/cecil/symbols/mdb/Mono.CompilerServices.SymbolWriter/MonoSymbolWriter.cs @@ -47,11 +47,7 @@ namespace Mono.CompilerServices.SymbolWriter string filename; private SourceMethodBuilder current_method; -#if NET_2_1 - System.Collections.Stack current_method_stack = new System.Collections.Stack (); -#else Stack current_method_stack = new Stack (); -#endif public MonoSymbolWriter (string filename) { @@ -239,165 +235,4 @@ namespace Mono.CompilerServices.SymbolWriter } } } - - public class SourceMethodBuilder - { - List _locals; - List _blocks; - List _scope_vars; -#if NET_2_1 - System.Collections.Stack _block_stack; -#else - Stack _block_stack; -#endif - string _real_name; - IMethodDef _method; - ICompileUnit _comp_unit; -// MethodEntry.Flags _method_flags; - int _ns_id; - - public SourceMethodBuilder (ICompileUnit comp_unit, int ns_id, IMethodDef method) - { - this._comp_unit = comp_unit; - this._method = method; - this._ns_id = ns_id; - - method_lines = new LineNumberEntry [32]; - } - - private LineNumberEntry [] method_lines; - private int method_lines_pos = 0; - - public void MarkSequencePoint (int offset, SourceFileEntry file, int line, int column, - bool is_hidden) - { - if (method_lines_pos == method_lines.Length) { - LineNumberEntry [] tmp = method_lines; - method_lines = new LineNumberEntry [method_lines.Length * 2]; - Array.Copy (tmp, method_lines, method_lines_pos); - } - - int file_idx = file != null ? file.Index : 0; - method_lines [method_lines_pos++] = new LineNumberEntry ( - file_idx, line, offset, is_hidden); - } - - public void StartBlock (CodeBlockEntry.Type type, int start_offset) - { - if (_block_stack == null) { -#if NET_2_1 - _block_stack = new System.Collections.Stack (); -#else - _block_stack = new Stack (); -#endif - } - - if (_blocks == null) - _blocks = new List (); - - int parent = CurrentBlock != null ? CurrentBlock.Index : -1; - - CodeBlockEntry block = new CodeBlockEntry ( - _blocks.Count + 1, parent, type, start_offset); - - _block_stack.Push (block); - _blocks.Add (block); - } - - public void EndBlock (int end_offset) - { - CodeBlockEntry block = (CodeBlockEntry) _block_stack.Pop (); - block.Close (end_offset); - } - - public CodeBlockEntry[] Blocks { - get { - if (_blocks == null) - return new CodeBlockEntry [0]; - - CodeBlockEntry[] retval = new CodeBlockEntry [_blocks.Count]; - _blocks.CopyTo (retval, 0); - return retval; - } - } - - public CodeBlockEntry CurrentBlock { - get { - if ((_block_stack != null) && (_block_stack.Count > 0)) - return (CodeBlockEntry) _block_stack.Peek (); - else - return null; - } - } - - public LocalVariableEntry[] Locals { - get { - if (_locals == null) - return new LocalVariableEntry [0]; - else { - LocalVariableEntry[] retval = - new LocalVariableEntry [_locals.Count]; - _locals.CopyTo (retval, 0); - return retval; - } - } - } - - public void AddLocal (int index, string name) - { - if (_locals == null) - _locals = new List (); - int block_idx = CurrentBlock != null ? CurrentBlock.Index : 0; - _locals.Add (new LocalVariableEntry (index, name, block_idx)); - } - - public ScopeVariable[] ScopeVariables { - get { - if (_scope_vars == null) - return new ScopeVariable [0]; - - ScopeVariable[] retval = new ScopeVariable [_scope_vars.Count]; - _scope_vars.CopyTo (retval); - return retval; - } - } - - public void AddScopeVariable (int scope, int index) - { - if (_scope_vars == null) - _scope_vars = new List (); - _scope_vars.Add ( - new ScopeVariable (scope, index)); - } - - public string RealMethodName { - get { return _real_name; } - } - - public void SetRealMethodName (string name) - { - _real_name = name; - } - - public ICompileUnit SourceFile { - get { return _comp_unit; } - } - - public IMethodDef Method { - get { return _method; } - } - - public void DefineMethod (MonoSymbolFile file) - { - LineNumberEntry[] lines = new LineNumberEntry [method_lines_pos]; - Array.Copy (method_lines, lines, method_lines_pos); - - MethodEntry entry = new MethodEntry ( - file, _comp_unit.Entry, _method.Token, ScopeVariables, - Locals, lines, Blocks, RealMethodName, 0, //_method_flags, - _ns_id); - - file.AddMethod (entry); - } - } } diff --git a/external/cecil/symbols/mdb/Mono.CompilerServices.SymbolWriter/SourceMethodBuilder.cs b/external/cecil/symbols/mdb/Mono.CompilerServices.SymbolWriter/SourceMethodBuilder.cs new file mode 100644 index 0000000000..88363e7d54 --- /dev/null +++ b/external/cecil/symbols/mdb/Mono.CompilerServices.SymbolWriter/SourceMethodBuilder.cs @@ -0,0 +1,190 @@ +// +// SourceMethodBuilder.cs +// +// Authors: +// Martin Baulig (martin@ximian.com) +// Marek Safar (marek.safar@gmail.com) +// +// (C) 2002 Ximian, Inc. http://www.ximian.com +// Copyright (C) 2012 Xamarin Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System.Collections.Generic; + +namespace Mono.CompilerServices.SymbolWriter +{ + public class SourceMethodBuilder + { + List _locals; + List _blocks; + List _scope_vars; + Stack _block_stack; + readonly List method_lines; + + readonly ICompileUnit _comp_unit; + readonly int ns_id; + readonly IMethodDef method; + + public SourceMethodBuilder (ICompileUnit comp_unit) + { + this._comp_unit = comp_unit; + method_lines = new List (); + } + + public SourceMethodBuilder (ICompileUnit comp_unit, int ns_id, IMethodDef method) + : this (comp_unit) + { + this.ns_id = ns_id; + this.method = method; + } + + public void MarkSequencePoint (int offset, SourceFileEntry file, int line, int column, bool is_hidden) + { + MarkSequencePoint (offset, file, line, column, -1, -1, is_hidden); + } + + public void MarkSequencePoint (int offset, SourceFileEntry file, int line, int column, int end_line, int end_column, bool is_hidden) + { + int file_idx = file != null ? file.Index : 0; + var lne = new LineNumberEntry (file_idx, line, column, end_line, end_column, offset, is_hidden); + + if (method_lines.Count > 0) { + var prev = method_lines[method_lines.Count - 1]; + + // + // Same offset cannot be used for multiple lines + // + if (prev.Offset == offset) { + // + // Use the new location because debugger will adjust + // the breakpoint to next line with sequence point + // + if (LineNumberEntry.LocationComparer.Default.Compare (lne, prev) > 0) + method_lines[method_lines.Count - 1] = lne; + + return; + } + } + + method_lines.Add (lne); + } + + public void StartBlock (CodeBlockEntry.Type type, int start_offset) + { + if (_block_stack == null) { + _block_stack = new Stack (); + } + + if (_blocks == null) + _blocks = new List (); + + int parent = CurrentBlock != null ? CurrentBlock.Index : -1; + + CodeBlockEntry block = new CodeBlockEntry ( + _blocks.Count + 1, parent, type, start_offset); + + _block_stack.Push (block); + _blocks.Add (block); + } + + public void EndBlock (int end_offset) + { + CodeBlockEntry block = (CodeBlockEntry) _block_stack.Pop (); + block.Close (end_offset); + } + + public CodeBlockEntry[] Blocks { + get { + if (_blocks == null) + return new CodeBlockEntry [0]; + + CodeBlockEntry[] retval = new CodeBlockEntry [_blocks.Count]; + _blocks.CopyTo (retval, 0); + return retval; + } + } + + public CodeBlockEntry CurrentBlock { + get { + if ((_block_stack != null) && (_block_stack.Count > 0)) + return (CodeBlockEntry) _block_stack.Peek (); + else + return null; + } + } + + public LocalVariableEntry[] Locals { + get { + if (_locals == null) + return new LocalVariableEntry [0]; + else { + return _locals.ToArray (); + } + } + } + + public ICompileUnit SourceFile { + get { + return _comp_unit; + } + } + + public void AddLocal (int index, string name) + { + if (_locals == null) + _locals = new List (); + int block_idx = CurrentBlock != null ? CurrentBlock.Index : 0; + _locals.Add (new LocalVariableEntry (index, name, block_idx)); + } + + public ScopeVariable[] ScopeVariables { + get { + if (_scope_vars == null) + return new ScopeVariable [0]; + + return _scope_vars.ToArray (); + } + } + + public void AddScopeVariable (int scope, int index) + { + if (_scope_vars == null) + _scope_vars = new List (); + _scope_vars.Add ( + new ScopeVariable (scope, index)); + } + + public void DefineMethod (MonoSymbolFile file) + { + DefineMethod (file, method.Token); + } + + public void DefineMethod (MonoSymbolFile file, int token) + { + MethodEntry entry = new MethodEntry ( + file, _comp_unit.Entry, token, ScopeVariables, + Locals, method_lines.ToArray (), Blocks, null, MethodEntry.Flags.ColumnsInfoIncluded, ns_id); + + file.AddMethod (entry); + } + } +} diff --git a/external/cecil/symbols/mdb/Test/Mono.Cecil.Mdb.Tests.csproj b/external/cecil/symbols/mdb/Test/Mono.Cecil.Mdb.Tests.csproj index 2123470382..9b899ed4dc 100644 --- a/external/cecil/symbols/mdb/Test/Mono.Cecil.Mdb.Tests.csproj +++ b/external/cecil/symbols/mdb/Test/Mono.Cecil.Mdb.Tests.csproj @@ -1,77 +1,10 @@ - + - net_4_0_Debug - AnyCPU - 9.0.30729 - 2.0 {AC71DF9C-99FA-4A63-990A-66C8010355A6} - Library - Properties Mono.Cecil.Mdb.Tests Mono.Cecil.Mdb.Tests - 512 - - true - full - false - bin\net_2_0_Debug\ - DEBUG;TRACE - prompt - 4 - v2.0 - - - pdbonly - true - bin\net_2_0_Release\ - TRACE - prompt - 4 - v2.0 - - - true - full - false - bin\net_3_5_Debug\ - DEBUG;TRACE;NET_3_5 - prompt - 4 - v3.5 - - - pdbonly - true - bin\net_3_5_Release\ - TRACE;NET_3_5 - prompt - 4 - v3.5 - - - true - full - false - bin\net_4_0_Debug\ - DEBUG;TRACE;NET_3_5;NET_4_0 - prompt - 4 - v4.0 - - - pdbonly - true - bin\net_4_0_Release\ - TRACE;NET_3_5;NET_4_0 - prompt - 4 - v4.0 - - - - {D68133BD-1E63-496E-9EDE-4FBDBF77B486} @@ -87,33 +20,11 @@ - - + - - + - - - False - ..\..\..\Test\libs\nunit-2.6.2\nunit.core.dll - - - False - ..\..\..\Test\libs\nunit-2.6.2\nunit.core.interfaces.dll - - - False - ..\..\..\Test\libs\nunit-2.6.2\nunit.framework.dll - - - - + + \ No newline at end of file diff --git a/external/cecil/symbols/mdb/Test/Mono.Cecil.Tests/MdbTests.cs b/external/cecil/symbols/mdb/Test/Mono.Cecil.Tests/MdbTests.cs index 757732d6ee..907d744453 100644 --- a/external/cecil/symbols/mdb/Test/Mono.Cecil.Tests/MdbTests.cs +++ b/external/cecil/symbols/mdb/Test/Mono.Cecil.Tests/MdbTests.cs @@ -8,25 +8,26 @@ namespace Mono.Cecil.Tests { [TestFixture] public class MdbTests : BaseTestFixture { - [TestModule ("hello.exe", SymbolReaderProvider = typeof (MdbReaderProvider), SymbolWriterProvider = typeof (MdbWriterProvider))] - public void Main (ModuleDefinition module) + [Test] + public void MdbWithJustLineInfo () { - var type = module.GetType ("Program"); - var main = type.GetMethod ("Main"); + TestModule ("hello.exe", module => { + var type = module.GetType ("Program"); + var main = type.GetMethod ("Main"); - AssertCode (@" + AssertCode (@" .locals init (System.Int32 i) - .line 7,7:0,0 'C:\sources\cecil\symbols\Mono.Cecil.Mdb\Test\Resources\assemblies\hello.cs' + .line 6,-1:-1,-1 'C:\sources\cecil\symbols\Mono.Cecil.Mdb\Test\Resources\assemblies\hello.cs' IL_0000: ldc.i4.0 IL_0001: stloc.0 - .line 7,7:0,0 'C:\sources\cecil\symbols\Mono.Cecil.Mdb\Test\Resources\assemblies\hello.cs' + .line 7,-1:-1,-1 'C:\sources\cecil\symbols\Mono.Cecil.Mdb\Test\Resources\assemblies\hello.cs' IL_0002: br IL_0013 - .line 8,8:0,0 'C:\sources\cecil\symbols\Mono.Cecil.Mdb\Test\Resources\assemblies\hello.cs' + .line 8,-1:-1,-1 'C:\sources\cecil\symbols\Mono.Cecil.Mdb\Test\Resources\assemblies\hello.cs' IL_0007: ldarg.0 IL_0008: ldloc.0 IL_0009: ldelem.ref IL_000a: call System.Void Program::Print(System.String) - .line 7,7:0,0 'C:\sources\cecil\symbols\Mono.Cecil.Mdb\Test\Resources\assemblies\hello.cs' + .line 7,-1:-1,-1 'C:\sources\cecil\symbols\Mono.Cecil.Mdb\Test\Resources\assemblies\hello.cs' IL_000f: ldloc.0 IL_0010: ldc.i4.1 IL_0011: add @@ -36,23 +37,50 @@ namespace Mono.Cecil.Tests { IL_0015: ldlen IL_0016: conv.i4 IL_0017: blt IL_0007 - .line 10,10:0,0 'C:\sources\cecil\symbols\Mono.Cecil.Mdb\Test\Resources\assemblies\hello.cs' + .line 10,-1:-1,-1 'C:\sources\cecil\symbols\Mono.Cecil.Mdb\Test\Resources\assemblies\hello.cs' IL_001c: ldc.i4.0 IL_001d: ret ", main); + }, symbolReaderProvider: typeof(MdbReaderProvider), symbolWriterProvider: typeof(MdbWriterProvider)); } - static void AssertCode (string expected, MethodDefinition method) + [Test] + public void RoundTripCoreLib () { - Assert.IsTrue (method.HasBody); - Assert.IsNotNull (method.Body); + TestModule ("mscorlib.dll", module => { + var type = module.GetType ("System.IO.__Error"); + var method = type.GetMethod ("WinIOError"); - Assert.AreEqual (Normalize (expected), Normalize (Formatter.FormatMethodBody (method))); + Assert.IsNotNull (method.Body); + }, verify: !Platform.OnMono, symbolReaderProvider: typeof(MdbReaderProvider), symbolWriterProvider: typeof(MdbWriterProvider)); } - static string Normalize (string str) + [Test] + public void PartialClass () { - return str.Trim ().Replace ("\r\n", "\n"); + TestModule ("BreakpointTest.Portable.dll", module => { + var type = module.GetType ("BreakpointTest.Portable.TestService/c__async3"); + var method = type.GetMethod ("MoveNext"); + + Assert.IsNotNull (method); + + var info = method.DebugInformation; + Assert.AreEqual (5, info.SequencePoints.Count); + foreach (var sp in info.SequencePoints) + Assert.AreEqual(@"C:\tmp\repropartial\BreakpointTest.Portable\TestService.Actions.cs", sp.Document.Url); + + type = module.GetType("BreakpointTest.Portable.TestService/c__async2"); + method = type.GetMethod("MoveNext"); + + Assert.IsNotNull(method); + + info = method.DebugInformation; + Assert.AreEqual(5, info.SequencePoints.Count); + foreach (var sp in info.SequencePoints) + Assert.AreEqual(@"C:\tmp\repropartial\BreakpointTest.Portable\TestService.cs", sp.Document.Url); + + + }, symbolReaderProvider: typeof(MdbReaderProvider), symbolWriterProvider: typeof(MdbWriterProvider)); } } } diff --git a/external/cecil/symbols/mdb/Test/Resources/assemblies/BreakpointTest.Portable.dll.mdb b/external/cecil/symbols/mdb/Test/Resources/assemblies/BreakpointTest.Portable.dll.mdb new file mode 100644 index 0000000000..555f3e8db3 Binary files /dev/null and b/external/cecil/symbols/mdb/Test/Resources/assemblies/BreakpointTest.Portable.dll.mdb differ diff --git a/external/cecil/symbols/mdb/Test/Resources/assemblies/mscorlib.dll.mdb.REMOVED.git-id b/external/cecil/symbols/mdb/Test/Resources/assemblies/mscorlib.dll.mdb.REMOVED.git-id new file mode 100644 index 0000000000..1c0148ca1c --- /dev/null +++ b/external/cecil/symbols/mdb/Test/Resources/assemblies/mscorlib.dll.mdb.REMOVED.git-id @@ -0,0 +1 @@ +f997a8c39889b310ac6995842263f24ef6d94396 \ No newline at end of file diff --git a/external/cecil/symbols/pdb/Microsoft.Cci.Pdb/LICENSE b/external/cecil/symbols/pdb/Microsoft.Cci.Pdb/LICENSE old mode 100755 new mode 100644 diff --git a/external/cecil/symbols/pdb/Microsoft.Cci.Pdb/PdbFileHeader.cs b/external/cecil/symbols/pdb/Microsoft.Cci.Pdb/PdbFileHeader.cs index e1f56dbe42..0a920388ac 100644 --- a/external/cecil/symbols/pdb/Microsoft.Cci.Pdb/PdbFileHeader.cs +++ b/external/cecil/symbols/pdb/Microsoft.Cci.Pdb/PdbFileHeader.cs @@ -24,6 +24,8 @@ namespace Microsoft.Cci.Pdb { // this.pageSize = pageSize; //} + const string MAGIC = "Microsoft C/C++ MSF 7.00"; + internal PdbFileHeader(Stream reader, BitAccess bits) { bits.MinCapacity(56); reader.Seek(0, SeekOrigin.Begin); @@ -37,15 +39,18 @@ namespace Microsoft.Cci.Pdb { bits.ReadInt32(out this.directorySize); // 44..47 bits.ReadInt32(out this.zero); // 48..51 + if (Magic != MAGIC) { + throw new InvalidOperationException("Magic is wrong."); + } int directoryPages = ((((directorySize + pageSize - 1) / pageSize) * 4) + pageSize - 1) / pageSize; this.directoryRoot = new int[directoryPages]; bits.FillBuffer(reader, directoryPages * 4); bits.ReadInt32(this.directoryRoot); } - //internal string Magic { - // get { return StringFromBytesUTF8(magic); } - //} + string Magic { + get { return StringFromBytesUTF8(magic, 0, MAGIC.Length); } + } //internal void Write(Stream writer, BitAccess bits) { // bits.MinCapacity(pageSize); @@ -63,18 +68,18 @@ namespace Microsoft.Cci.Pdb { //////////////////////////////////////////////////// Helper Functions. // - //internal static string StringFromBytesUTF8(byte[] bytes) { - // return StringFromBytesUTF8(bytes, 0, bytes.Length); - //} + static string StringFromBytesUTF8(byte[] bytes) { + return StringFromBytesUTF8(bytes, 0, bytes.Length); + } - //internal static string StringFromBytesUTF8(byte[] bytes, int offset, int length) { - // for (int i = 0; i < length; i++) { - // if (bytes[offset + i] < ' ') { - // length = i; - // } - // } - // return Encoding.UTF8.GetString(bytes, offset, length); - //} + static string StringFromBytesUTF8(byte[] bytes, int offset, int length) { + for (int i = 0; i < length; i++) { + if (bytes[offset + i] < ' ') { + length = i; + } + } + return Encoding.UTF8.GetString(bytes, offset, length); + } ////////////////////////////////////////////////////////////// Fields. // diff --git a/external/cecil/symbols/pdb/Microsoft.Cci.Pdb/PdbFunction.cs b/external/cecil/symbols/pdb/Microsoft.Cci.Pdb/PdbFunction.cs index 72622314e8..2ef733f556 100644 --- a/external/cecil/symbols/pdb/Microsoft.Cci.Pdb/PdbFunction.cs +++ b/external/cecil/symbols/pdb/Microsoft.Cci.Pdb/PdbFunction.cs @@ -356,7 +356,7 @@ namespace Microsoft.Cci.Pdb { case 2: break; // this.ReadForwardedToModuleInfo(bits); break; case 3: this.ReadIteratorLocals(bits); break; case 4: this.ReadForwardIterator(bits); break; - default: throw new PdbDebugException("Unknown custom metadata item kind: {0}", kind); + // TODO: handle unknown custom metadata, 5 & 6 are new with roslyn, see https://roslyn.codeplex.com/workitem/54 } bits.Position = savedPosition+(int)numberOfBytesInItem; } diff --git a/external/cecil/symbols/pdb/Mono.Cecil.Pdb.csproj b/external/cecil/symbols/pdb/Mono.Cecil.Pdb.csproj index e35add055d..c7140c2015 100644 --- a/external/cecil/symbols/pdb/Mono.Cecil.Pdb.csproj +++ b/external/cecil/symbols/pdb/Mono.Cecil.Pdb.csproj @@ -1,83 +1,11 @@  - net_4_0_Debug - AnyCPU - 9.0.30729 - 2.0 {63E6915C-7EA4-4D76-AB28-0D7191EEA626} - Library - Properties Mono.Cecil.Pdb Mono.Cecil.Pdb - 512 - true - ..\..\mono.snk 0649 - - true - full - false - ..\..\bin\net_2_0_Debug\ - DEBUG;TRACE - prompt - 4 - v2.0 - - - pdbonly - true - ..\..\bin\net_2_0_Release\ - TRACE - prompt - 4 - v2.0 - - - true - full - false - ..\..\bin\net_3_5_Debug\ - DEBUG;TRACE;NET_3_5 - prompt - 4 - v3.5 - - - pdbonly - true - ..\..\bin\net_3_5_Release\ - TRACE;NET_3_5 - prompt - 4 - v3.5 - - - true - full - false - ..\..\bin\net_4_0_Debug\ - DEBUG;TRACE;NET_3_5;NET_4_0 - prompt - 4 - v4.0 - - - pdbonly - true - ..\..\bin\net_4_0_Release\ - TRACE;NET_3_5;NET_4_0 - prompt - 4 - v4.0 - - - - - - - {D68133BD-1E63-496E-9EDE-4FBDBF77B486} @@ -85,49 +13,10 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - Code - - - - - - - - - - + + + - - + + \ No newline at end of file diff --git a/external/cecil/symbols/pdb/Mono.Cecil.Pdb/AssemblyInfo.cs b/external/cecil/symbols/pdb/Mono.Cecil.Pdb/AssemblyInfo.cs index 14d2679907..c4b4e2e9e0 100644 --- a/external/cecil/symbols/pdb/Mono.Cecil.Pdb/AssemblyInfo.cs +++ b/external/cecil/symbols/pdb/Mono.Cecil.Pdb/AssemblyInfo.cs @@ -1,41 +1,16 @@ // -// AssemblyInfo.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; using System.Reflection; -using System.Runtime.InteropServices; [assembly: AssemblyTitle ("Mono.Cecil.Pdb")] -[assembly: AssemblyProduct ("Mono.Cecil")] -[assembly: AssemblyCopyright ("Copyright © 2008 - 2011 Jb Evain")] [assembly: CLSCompliant (false)] -[assembly: ComVisible (false)] - -[assembly: AssemblyVersion ("0.9.5.0")] -[assembly: AssemblyFileVersion ("0.9.5.0")] diff --git a/external/cecil/symbols/pdb/Mono.Cecil.Pdb/ISymUnmanagedDocumentWriter.cs b/external/cecil/symbols/pdb/Mono.Cecil.Pdb/ISymUnmanagedDocumentWriter.cs index 8f47b2c0f2..f694e2701c 100644 --- a/external/cecil/symbols/pdb/Mono.Cecil.Pdb/ISymUnmanagedDocumentWriter.cs +++ b/external/cecil/symbols/pdb/Mono.Cecil.Pdb/ISymUnmanagedDocumentWriter.cs @@ -1,28 +1,9 @@ -// ISymUnmanagedDocumentWriter.cs -// // Author: // Juerg Billeter (j@bitron.ch) // // (C) 2008 Juerg Billeter // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System.Runtime.InteropServices; diff --git a/external/cecil/symbols/pdb/Mono.Cecil.Pdb/ISymUnmanagedWriter2.cs b/external/cecil/symbols/pdb/Mono.Cecil.Pdb/ISymUnmanagedWriter2.cs index 11466dcb9d..c8d1340808 100644 --- a/external/cecil/symbols/pdb/Mono.Cecil.Pdb/ISymUnmanagedWriter2.cs +++ b/external/cecil/symbols/pdb/Mono.Cecil.Pdb/ISymUnmanagedWriter2.cs @@ -1,29 +1,10 @@ // -// ISymUnmanagedWriter2.cs -// // Author: // Juerg Billeter (j@bitron.ch) // // (C) 2008 Juerg Billeter // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; diff --git a/external/cecil/symbols/pdb/Mono.Cecil.Pdb/ModuleMetadata.cs b/external/cecil/symbols/pdb/Mono.Cecil.Pdb/ModuleMetadata.cs index e06f12aefb..b175c06a4e 100644 --- a/external/cecil/symbols/pdb/Mono.Cecil.Pdb/ModuleMetadata.cs +++ b/external/cecil/symbols/pdb/Mono.Cecil.Pdb/ModuleMetadata.cs @@ -487,7 +487,7 @@ namespace Mono.Cecil.Pdb { return 0; } - WriteString (type.Name, szTypeDef, cchTypeDef, out pchTypeDef); + WriteString (type.IsNested ? type.Name : type.FullName, szTypeDef, cchTypeDef, out pchTypeDef); WriteIntPtr (pdwTypeDefFlags, (uint) type.Attributes); return type.BaseType != null ? type.BaseType.MetadataToken.ToUInt32 () : 0; } diff --git a/external/cecil/symbols/pdb/Mono.Cecil.Pdb/PdbHelper.cs b/external/cecil/symbols/pdb/Mono.Cecil.Pdb/PdbHelper.cs index aa63982536..6c08b3c981 100644 --- a/external/cecil/symbols/pdb/Mono.Cecil.Pdb/PdbHelper.cs +++ b/external/cecil/symbols/pdb/Mono.Cecil.Pdb/PdbHelper.cs @@ -1,43 +1,95 @@ // -// PdbHelper.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; -using System.Collections.Generic; using System.IO; using Mono.Cecil.Cil; namespace Mono.Cecil.Pdb { - class PdbHelper { + public sealed class NativePdbReaderProvider : ISymbolReaderProvider { + + public ISymbolReader GetSymbolReader (ModuleDefinition module, string fileName) + { + Mixin.CheckModule (module); + Mixin.CheckFileName (fileName); + + return new PdbReader (Disposable.Owned (File.OpenRead (Mixin.GetPdbFileName (fileName)) as Stream)); + } + + public ISymbolReader GetSymbolReader (ModuleDefinition module, Stream symbolStream) + { + Mixin.CheckModule (module); + Mixin.CheckStream (symbolStream); + + return new PdbReader (Disposable.NotOwned (symbolStream)); + } + } + + public sealed class PdbReaderProvider : ISymbolReaderProvider { + + public ISymbolReader GetSymbolReader (ModuleDefinition module, string fileName) + { + Mixin.CheckModule (module); + Mixin.CheckFileName (fileName); + + return IsPortablePdb (Mixin.GetPdbFileName (fileName)) + ? new PortablePdbReaderProvider ().GetSymbolReader (module, fileName) + : new NativePdbReaderProvider ().GetSymbolReader (module, fileName); + } + + public ISymbolReader GetSymbolReader (ModuleDefinition module, Stream symbolStream) + { + Mixin.CheckModule (module); + Mixin.CheckStream (symbolStream); + Mixin.CheckReadSeek (symbolStream); + + return IsPortablePdb (symbolStream) + ? new PortablePdbReaderProvider ().GetSymbolReader (module, symbolStream) + : new NativePdbReaderProvider ().GetSymbolReader (module, symbolStream); + } + + static bool IsPortablePdb (string fileName) + { + using (var file = new FileStream (fileName, FileMode.Open, FileAccess.Read, FileShare.None)) + return IsPortablePdb (file); + } + + static bool IsPortablePdb (Stream stream) + { + const uint ppdb_signature = 0x424a5342; + + var position = stream.Position; + try { + var reader = new BinaryReader (stream); + return reader.ReadUInt32 () == ppdb_signature; + } finally { + stream.Position = position; + } + } + } #if !READ_ONLY - public static SymWriter CreateWriter (ModuleDefinition module, string pdb) + + public sealed class NativePdbWriterProvider : ISymbolWriterProvider { + + public ISymbolWriter GetSymbolWriter (ModuleDefinition module, string fileName) + { + Mixin.CheckModule (module); + Mixin.CheckFileName (fileName); + + return new PdbWriter (module, CreateWriter (module, Mixin.GetPdbFileName (fileName))); + } + + static SymWriter CreateWriter (ModuleDefinition module, string pdb) { var writer = new SymWriter (); @@ -48,35 +100,6 @@ namespace Mono.Cecil.Pdb { return writer; } -#endif - - public static string GetPdbFileName (string assemblyFileName) - { - return Path.ChangeExtension (assemblyFileName, ".pdb"); - } - } - - public class PdbReaderProvider : ISymbolReaderProvider { - - public ISymbolReader GetSymbolReader (ModuleDefinition module, string fileName) - { - return new PdbReader (File.OpenRead (PdbHelper.GetPdbFileName (fileName))); - } - - public ISymbolReader GetSymbolReader (ModuleDefinition module, Stream symbolStream) - { - return new PdbReader (symbolStream); - } - } - -#if !READ_ONLY - - public class PdbWriterProvider : ISymbolWriterProvider { - - public ISymbolWriter GetSymbolWriter (ModuleDefinition module, string fileName) - { - return new PdbWriter (module, PdbHelper.CreateWriter (module, PdbHelper.GetPdbFileName (fileName))); - } public ISymbolWriter GetSymbolWriter (ModuleDefinition module, Stream symbolStream) { @@ -84,123 +107,36 @@ namespace Mono.Cecil.Pdb { } } -#endif + public sealed class PdbWriterProvider : ISymbolWriterProvider { - static class GuidMapping { - - static readonly Dictionary guid_language = new Dictionary (); - static readonly Dictionary language_guid = new Dictionary (); - - static GuidMapping () + public ISymbolWriter GetSymbolWriter (ModuleDefinition module, string fileName) { - AddMapping (DocumentLanguage.C, new Guid (0x63a08714, 0xfc37, 0x11d2, 0x90, 0x4c, 0x0, 0xc0, 0x4f, 0xa3, 0x02, 0xa1)); - AddMapping (DocumentLanguage.Cpp, new Guid (0x3a12d0b7, 0xc26c, 0x11d0, 0xb4, 0x42, 0x0, 0xa0, 0x24, 0x4a, 0x1d, 0xd2)); - AddMapping (DocumentLanguage.CSharp, new Guid (0x3f5162f8, 0x07c6, 0x11d3, 0x90, 0x53, 0x0, 0xc0, 0x4f, 0xa3, 0x02, 0xa1)); - AddMapping (DocumentLanguage.Basic, new Guid (0x3a12d0b8, 0xc26c, 0x11d0, 0xb4, 0x42, 0x0, 0xa0, 0x24, 0x4a, 0x1d, 0xd2)); - AddMapping (DocumentLanguage.Java, new Guid (0x3a12d0b4, 0xc26c, 0x11d0, 0xb4, 0x42, 0x0, 0xa0, 0x24, 0x4a, 0x1d, 0xd2)); - AddMapping (DocumentLanguage.Cobol, new Guid (0xaf046cd1, 0xd0e1, 0x11d2, 0x97, 0x7c, 0x0, 0xa0, 0xc9, 0xb4, 0xd5, 0xc)); - AddMapping (DocumentLanguage.Pascal, new Guid (0xaf046cd2, 0xd0e1, 0x11d2, 0x97, 0x7c, 0x0, 0xa0, 0xc9, 0xb4, 0xd5, 0xc)); - AddMapping (DocumentLanguage.Cil, new Guid (0xaf046cd3, 0xd0e1, 0x11d2, 0x97, 0x7c, 0x0, 0xa0, 0xc9, 0xb4, 0xd5, 0xc)); - AddMapping (DocumentLanguage.JScript, new Guid (0x3a12d0b6, 0xc26c, 0x11d0, 0xb4, 0x42, 0x0, 0xa0, 0x24, 0x4a, 0x1d, 0xd2)); - AddMapping (DocumentLanguage.Smc, new Guid (0xd9b9f7b, 0x6611, 0x11d3, 0xbd, 0x2a, 0x0, 0x0, 0xf8, 0x8, 0x49, 0xbd)); - AddMapping (DocumentLanguage.MCpp, new Guid (0x4b35fde8, 0x07c6, 0x11d3, 0x90, 0x53, 0x0, 0xc0, 0x4f, 0xa3, 0x02, 0xa1)); - AddMapping (DocumentLanguage.FSharp, new Guid (0xab4f38c9, 0xb6e6, 0x43ba, 0xbe, 0x3b, 0x58, 0x08, 0x0b, 0x2c, 0xcc, 0xe3)); + Mixin.CheckModule (module); + Mixin.CheckFileName (fileName); + + if (HasPortablePdbSymbols (module)) + return new PortablePdbWriterProvider ().GetSymbolWriter (module, fileName); + + return new NativePdbWriterProvider ().GetSymbolWriter (module, fileName); } - static void AddMapping (DocumentLanguage language, Guid guid) + static bool HasPortablePdbSymbols (ModuleDefinition module) { - guid_language.Add (guid, language); - language_guid.Add (language, guid); + return module.symbol_reader != null && module.symbol_reader is PortablePdbReader; } - static readonly Guid type_text = new Guid (0x5a869d0b, 0x6611, 0x11d3, 0xbd, 0x2a, 0x00, 0x00, 0xf8, 0x08, 0x49, 0xbd); - - public static DocumentType ToType (this Guid guid) + public ISymbolWriter GetSymbolWriter (ModuleDefinition module, Stream symbolStream) { - if (guid == type_text) - return DocumentType.Text; + Mixin.CheckModule (module); + Mixin.CheckStream (symbolStream); + Mixin.CheckReadSeek (symbolStream); - return DocumentType.Other; - } + if (HasPortablePdbSymbols (module)) + return new PortablePdbWriterProvider ().GetSymbolWriter (module, symbolStream); - public static Guid ToGuid (this DocumentType type) - { - if (type == DocumentType.Text) - return type_text; - - return new Guid (); - } - - static readonly Guid hash_md5 = new Guid (0x406ea660, 0x64cf, 0x4c82, 0xb6, 0xf0, 0x42, 0xd4, 0x81, 0x72, 0xa7, 0x99); - static readonly Guid hash_sha1 = new Guid (0xff1816ec, 0xaa5e, 0x4d10, 0x87, 0xf7, 0x6f, 0x49, 0x63, 0x83, 0x34, 0x60); - - public static DocumentHashAlgorithm ToHashAlgorithm (this Guid guid) - { - if (guid == hash_md5) - return DocumentHashAlgorithm.MD5; - - if (guid == hash_sha1) - return DocumentHashAlgorithm.SHA1; - - return DocumentHashAlgorithm.None; - } - - public static Guid ToGuid (this DocumentHashAlgorithm hash_algo) - { - if (hash_algo == DocumentHashAlgorithm.MD5) - return hash_md5; - - if (hash_algo == DocumentHashAlgorithm.SHA1) - return hash_sha1; - - return new Guid (); - } - - public static DocumentLanguage ToLanguage (this Guid guid) - { - DocumentLanguage language; - if (!guid_language.TryGetValue (guid, out language)) - return DocumentLanguage.Other; - - return language; - } - - public static Guid ToGuid (this DocumentLanguage language) - { - Guid guid; - if (!language_guid.TryGetValue (language, out guid)) - return new Guid (); - - return guid; - } - - static readonly Guid vendor_ms = new Guid (0x994b45c4, 0xe6e9, 0x11d2, 0x90, 0x3f, 0x00, 0xc0, 0x4f, 0xa3, 0x02, 0xa1); - - public static DocumentLanguageVendor ToVendor (this Guid guid) - { - if (guid == vendor_ms) - return DocumentLanguageVendor.Microsoft; - - return DocumentLanguageVendor.Other; - } - - public static Guid ToGuid (this DocumentLanguageVendor vendor) - { - if (vendor == DocumentLanguageVendor.Microsoft) - return vendor_ms; - - return new Guid (); + return new NativePdbWriterProvider ().GetSymbolWriter (module, symbolStream); } } -} - -#if !NET_3_5 && !NET_4_0 - -namespace System.Runtime.CompilerServices { - - [AttributeUsage (AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Assembly)] - sealed class ExtensionAttribute : Attribute { - } -} #endif +} diff --git a/external/cecil/symbols/pdb/Mono.Cecil.Pdb/PdbReader.cs b/external/cecil/symbols/pdb/Mono.Cecil.Pdb/PdbReader.cs index 6d4fd09844..abd503d163 100644 --- a/external/cecil/symbols/pdb/Mono.Cecil.Pdb/PdbReader.cs +++ b/external/cecil/symbols/pdb/Mono.Cecil.Pdb/PdbReader.cs @@ -1,35 +1,19 @@ // -// PdbReader.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; using System.Collections.Generic; using System.IO; +using Mono.Collections.Generic; + using Microsoft.Cci.Pdb; using Mono.Cecil.Cil; @@ -41,11 +25,11 @@ namespace Mono.Cecil.Pdb { int age; Guid guid; - readonly Stream pdb_file; + readonly Disposable pdb_file; readonly Dictionary documents = new Dictionary (); readonly Dictionary functions = new Dictionary (); - internal PdbReader (Stream file) + internal PdbReader (Disposable file) { this.pdb_file = file; } @@ -59,6 +43,11 @@ namespace Mono.Cecil.Pdb { public bool ProcessDebugHeader (ImageDebugDirectory directory, byte [] header) { + if (directory.Type != 2) //IMAGE_DEBUG_TYPE_CODEVIEW + return false; + if (directory.MajorVersion != 0 || directory.MinorVersion != 0) + return false; + if (header.Length < 24) return false; @@ -91,7 +80,7 @@ namespace Mono.Cecil.Pdb { int age; Guid guid; - var funcs = PdbFile.LoadFunctions (pdb_file, out tokenToSourceMapping, out sourceServerData, out age, out guid); + var funcs = PdbFile.LoadFunctions (pdb_file.value, out tokenToSourceMapping, out sourceServerData, out age, out guid); if (this.guid != guid) return false; @@ -103,102 +92,99 @@ namespace Mono.Cecil.Pdb { return true; } - public void Read (MethodBody body, InstructionMapper mapper) + public MethodDebugInformation Read (MethodDefinition method) { - var method_token = body.Method.MetadataToken; + var method_token = method.MetadataToken; PdbFunction function; if (!functions.TryGetValue (method_token.ToUInt32 (), out function)) - return; + return null; - ReadSequencePoints (function, mapper); - ReadScopeAndLocals (function.scopes, null, body, mapper); + var symbol = new MethodDebugInformation (method); + + ReadSequencePoints (function, symbol); + + if (function.scopes.Length > 1) + throw new NotSupportedException (); + else if (function.scopes.Length == 1) + symbol.scope = ReadScopeAndLocals (function.scopes [0], symbol); + + return symbol; } - static void ReadScopeAndLocals (PdbScope [] scopes, Scope parent, MethodBody body, InstructionMapper mapper) + static Collection ReadScopeAndLocals (PdbScope [] scopes, MethodDebugInformation info) { + var symbols = new Collection (scopes.Length); + foreach (PdbScope scope in scopes) - ReadScopeAndLocals (scope, parent, body, mapper); + if (scope != null) + symbols.Add (ReadScopeAndLocals (scope, info)); - CreateRootScope (body); + return symbols; } - static void CreateRootScope (MethodBody body) + static ScopeDebugInformation ReadScopeAndLocals (PdbScope scope, MethodDebugInformation info) { - if (!body.HasVariables) - return; + var parent = new ScopeDebugInformation (); + parent.Start = new InstructionOffset ((int) scope.offset); + parent.End = new InstructionOffset ((int) (scope.offset + scope.length)); - var instructions = body.Instructions; + if (!scope.slots.IsNullOrEmpty()) { + parent.variables = new Collection (scope.slots.Length); - var root = new Scope (); - root.Start = instructions [0]; - root.End = instructions [instructions.Count - 1]; - - var variables = body.Variables; - for (int i = 0; i < variables.Count; i++) - root.Variables.Add (variables [i]); - - body.Scope = root; - } - - static void ReadScopeAndLocals (PdbScope scope, Scope parent, MethodBody body, InstructionMapper mapper) - { - //Scope s = new Scope (); - //s.Start = GetInstruction (body, instructions, (int) scope.address); - //s.End = GetInstruction (body, instructions, (int) scope.length - 1); - - //if (parent != null) - // parent.Scopes.Add (s); - //else - // body.Scopes.Add (s); - - if (scope == null) - return; - - foreach (PdbSlot slot in scope.slots) { - int index = (int) slot.slot; - if (index < 0 || index >= body.Variables.Count) - continue; - - VariableDefinition variable = body.Variables [index]; - variable.Name = slot.name; - - //s.Variables.Add (variable); + foreach (PdbSlot slot in scope.slots) { + var index = (int) slot.slot; + var variable = new VariableDebugInformation (index, slot.name); + if (slot.flags == 4) + variable.IsDebuggerHidden = true; + parent.variables.Add (variable); + } } - ReadScopeAndLocals (scope.scopes, null /* s */, body, mapper); + if (!scope.constants.IsNullOrEmpty ()) { + parent.constants = new Collection (scope.constants.Length); + + foreach (var constant in scope.constants) { + parent.constants.Add (new ConstantDebugInformation ( + constant.name, + (TypeReference) info.method.Module.LookupToken ((int) constant.token), + constant.value)); + } + } + + parent.scopes = ReadScopeAndLocals (scope.scopes, info); + + return parent; } - void ReadSequencePoints (PdbFunction function, InstructionMapper mapper) + void ReadSequencePoints (PdbFunction function, MethodDebugInformation info) { if (function.lines == null) return; + info.sequence_points = new Collection (); + foreach (PdbLines lines in function.lines) - ReadLines (lines, mapper); + ReadLines (lines, info); } - void ReadLines (PdbLines lines, InstructionMapper mapper) + void ReadLines (PdbLines lines, MethodDebugInformation info) { var document = GetDocument (lines.file); foreach (var line in lines.lines) - ReadLine (line, document, mapper); + ReadLine (line, document, info); } - static void ReadLine (PdbLine line, Document document, InstructionMapper mapper) + static void ReadLine (PdbLine line, Document document, MethodDebugInformation info) { - var instruction = mapper ((int) line.offset); - if (instruction == null) - return; - - var sequence_point = new SequencePoint (document); + var sequence_point = new SequencePoint ((int) line.offset, document); sequence_point.StartLine = (int) line.lineBegin; sequence_point.StartColumn = (int) line.colBegin; sequence_point.EndLine = (int) line.lineEnd; sequence_point.EndColumn = (int) line.colEnd; - instruction.SequencePoint = sequence_point; + info.sequence_points.Add (sequence_point); } Document GetDocument (PdbSource source) @@ -217,65 +203,9 @@ namespace Mono.Cecil.Pdb { return document; } - public void Read (MethodSymbols symbols) - { - PdbFunction function; - if (!functions.TryGetValue (symbols.MethodToken.ToUInt32 (), out function)) - return; - - ReadSequencePoints (function, symbols); - ReadLocals (function.scopes, symbols); - } - - void ReadLocals (PdbScope [] scopes, MethodSymbols symbols) - { - foreach (var scope in scopes) - ReadLocals (scope, symbols); - } - - void ReadLocals (PdbScope scope, MethodSymbols symbols) - { - if (scope == null) - return; - - foreach (var slot in scope.slots) { - int index = (int) slot.slot; - if (index < 0 || index >= symbols.Variables.Count) - continue; - - var variable = symbols.Variables [index]; - variable.Name = slot.name; - } - - ReadLocals (scope.scopes, symbols); - } - - void ReadSequencePoints (PdbFunction function, MethodSymbols symbols) - { - if (function.lines == null) - return; - - foreach (PdbLines lines in function.lines) - ReadLines (lines, symbols); - } - - void ReadLines (PdbLines lines, MethodSymbols symbols) - { - for (int i = 0; i < lines.lines.Length; i++) { - var line = lines.lines [i]; - - symbols.Instructions.Add (new InstructionSymbol ((int) line.offset, new SequencePoint (GetDocument (lines.file)) { - StartLine = (int) line.lineBegin, - StartColumn = (int) line.colBegin, - EndLine = (int) line.lineEnd, - EndColumn = (int) line.colEnd, - })); - } - } - public void Dispose () { - pdb_file.Close (); + pdb_file.Dispose (); } } } diff --git a/external/cecil/symbols/pdb/Mono.Cecil.Pdb/PdbWriter.cs b/external/cecil/symbols/pdb/Mono.Cecil.Pdb/PdbWriter.cs index d07b698245..1d827b7a2d 100644 --- a/external/cecil/symbols/pdb/Mono.Cecil.Pdb/PdbWriter.cs +++ b/external/cecil/symbols/pdb/Mono.Cecil.Pdb/PdbWriter.cs @@ -1,29 +1,11 @@ // -// PdbWriter.cs -// // Author: // Jb Evain (jbevain@gmail.com) // -// Copyright (c) 2008 - 2011 Jb Evain +// Copyright (c) 2008 - 2015 Jb Evain +// Copyright (c) 2008 - 2011 Novell, Inc. // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; @@ -56,69 +38,55 @@ namespace Mono.Cecil.Pdb { return true; } - public void Write (MethodBody body) + public void Write (MethodDebugInformation info) { - var method_token = body.Method.MetadataToken; + var method_token = info.method.MetadataToken; var sym_token = new SymbolToken (method_token.ToInt32 ()); - var instructions = CollectInstructions (body); - if (instructions.Count == 0) - return; - - var start_offset = 0; - var end_offset = body.CodeSize; - writer.OpenMethod (sym_token); - writer.OpenScope (start_offset); - DefineSequencePoints (instructions); - DefineVariables (body, start_offset, end_offset); + DefineSequencePoints (info.sequence_points); + + if (info.scope != null) + DefineScope (info.scope, info); - writer.CloseScope (end_offset); writer.CloseMethod (); } - Collection CollectInstructions (MethodBody body) + void DefineScope (ScopeDebugInformation scope, MethodDebugInformation info) { - var collection = new Collection (); - var instructions = body.Instructions; + var start_offset = scope.Start.Offset; + var end_offset = scope.End.IsEndOfMethod + ? info.code_size + : scope.End.Offset; - for (int i = 0; i < instructions.Count; i++) { - var instruction = instructions [i]; - var sequence_point = instruction.SequencePoint; - if (sequence_point == null) - continue; + writer.OpenScope (start_offset); - GetDocument (sequence_point.Document); - collection.Add (instruction); + var sym_token = new SymbolToken (info.local_var_token.ToInt32 ()); + + if (!scope.variables.IsNullOrEmpty ()) { + for (int i = 0; i < scope.variables.Count; i++) { + var variable = scope.variables [i]; + CreateLocalVariable (variable, sym_token, start_offset, end_offset); + } } - return collection; - } - - void DefineVariables (MethodBody body, int start_offset, int end_offset) - { - if (!body.HasVariables) - return; - - var sym_token = new SymbolToken (body.LocalVarToken.ToInt32 ()); - - var variables = body.Variables; - for (int i = 0; i < variables.Count; i++) { - var variable = variables [i]; - CreateLocalVariable (variable, sym_token, start_offset, end_offset); + if (!scope.scopes.IsNullOrEmpty ()) { + for (int i = 0; i < scope.scopes.Count; i++) + DefineScope (scope.scopes [i], info); } + + writer.CloseScope (end_offset); } - void DefineSequencePoints (Collection instructions) + void DefineSequencePoints (Collection sequence_points) { - for (int i = 0; i < instructions.Count; i++) { - var instruction = instructions [i]; - var sequence_point = instruction.SequencePoint; + for (int i = 0; i < sequence_points.Count; i++) { + var sequence_point = sequence_points [i]; writer.DefineSequencePoints ( GetDocument (sequence_point.Document), - new [] { instruction.Offset }, + new [] { sequence_point.Offset }, new [] { sequence_point.StartLine }, new [] { sequence_point.StartColumn }, new [] { sequence_point.EndLine }, @@ -126,11 +94,11 @@ namespace Mono.Cecil.Pdb { } } - void CreateLocalVariable (VariableDefinition variable, SymbolToken local_var_token, int start_offset, int end_offset) + void CreateLocalVariable (VariableDebugInformation variable, SymbolToken local_var_token, int start_offset, int end_offset) { writer.DefineLocalVariable2 ( variable.Name, - 0, + variable.Attributes, local_var_token, SymAddressKind.ILOffset, variable.Index, @@ -159,55 +127,6 @@ namespace Mono.Cecil.Pdb { return doc_writer; } - public void Write (MethodSymbols symbols) - { - var sym_token = new SymbolToken (symbols.MethodToken.ToInt32 ()); - - var start_offset = 0; - var end_offset = symbols.CodeSize; - - writer.OpenMethod (sym_token); - writer.OpenScope (start_offset); - - DefineSequencePoints (symbols); - DefineVariables (symbols, start_offset, end_offset); - - writer.CloseScope (end_offset); - writer.CloseMethod (); - } - - void DefineSequencePoints (MethodSymbols symbols) - { - var instructions = symbols.instructions; - - for (int i = 0; i < instructions.Count; i++) { - var instruction = instructions [i]; - var sequence_point = instruction.SequencePoint; - - writer.DefineSequencePoints ( - GetDocument (sequence_point.Document), - new [] { instruction.Offset }, - new [] { sequence_point.StartLine }, - new [] { sequence_point.StartColumn }, - new [] { sequence_point.EndLine }, - new [] { sequence_point.EndColumn }); - } - } - - void DefineVariables (MethodSymbols symbols, int start_offset, int end_offset) - { - if (!symbols.HasVariables) - return; - - var sym_token = new SymbolToken (symbols.LocalVarToken.ToInt32 ()); - - var variables = symbols.Variables; - for (int i = 0; i < variables.Count; i++) { - var variable = variables [i]; - CreateLocalVariable (variable, sym_token, start_offset, end_offset); - } - } - public void Dispose () { var entry_point = module.EntryPoint; diff --git a/external/cecil/symbols/pdb/Mono.Cecil.Pdb/SymDocumentWriter.cs b/external/cecil/symbols/pdb/Mono.Cecil.Pdb/SymDocumentWriter.cs index 34918dc63e..a2bd1a2bd8 100644 --- a/external/cecil/symbols/pdb/Mono.Cecil.Pdb/SymDocumentWriter.cs +++ b/external/cecil/symbols/pdb/Mono.Cecil.Pdb/SymDocumentWriter.cs @@ -1,29 +1,10 @@ // -// SymDocumentWriter.cs -// // Author: // Juerg Billeter (j@bitron.ch) // // (C) 2008 Juerg Billeter // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; diff --git a/external/cecil/symbols/pdb/Mono.Cecil.Pdb/SymWriter.cs b/external/cecil/symbols/pdb/Mono.Cecil.Pdb/SymWriter.cs index 678942a341..ab0893b9f1 100644 --- a/external/cecil/symbols/pdb/Mono.Cecil.Pdb/SymWriter.cs +++ b/external/cecil/symbols/pdb/Mono.Cecil.Pdb/SymWriter.cs @@ -1,29 +1,10 @@ // -// SymWriter.cs -// // Author: // Juerg Billeter (j@bitron.ch) // // (C) 2008 Juerg Billeter // -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Licensed under the MIT/X11 license. // using System; @@ -78,7 +59,7 @@ namespace Mono.Cecil.Pdb public void DefineLocalVariable2 ( string name, - FieldAttributes attributes, + VariableAttributes attributes, SymbolToken sigToken, SymAddressKind addrKind, int addr1, diff --git a/external/cecil/symbols/pdb/Test/Mono.Cecil.Pdb.Tests.csproj b/external/cecil/symbols/pdb/Test/Mono.Cecil.Pdb.Tests.csproj index 657e351ba8..2b03651a9e 100644 --- a/external/cecil/symbols/pdb/Test/Mono.Cecil.Pdb.Tests.csproj +++ b/external/cecil/symbols/pdb/Test/Mono.Cecil.Pdb.Tests.csproj @@ -1,77 +1,10 @@ - + - net_4_0_Debug - AnyCPU - 9.0.30729 - 2.0 {29300103-CB76-4A1D-B6FD-FFD91C1EC8AA} - Library - Properties Mono.Cecil.Pdb.Tests Mono.Cecil.Pdb.Tests - 512 - - true - full - false - bin\net_2_0_Debug\ - DEBUG;TRACE - prompt - 4 - v2.0 - - - pdbonly - true - bin\net_2_0_Release\ - TRACE - prompt - 4 - v2.0 - - - true - full - false - bin\net_3_5_Debug\ - DEBUG;TRACE;NET_3_5 - prompt - 4 - v3.5 - - - pdbonly - true - bin\net_3_5_Release\ - TRACE;NET_3_5 - prompt - 4 - v3.5 - - - true - full - false - bin\net_4_0_Debug\ - DEBUG;TRACE;NET_3_5;NET_4_0 - prompt - 4 - v4.0 - - - pdbonly - true - bin\net_4_0_Release\ - TRACE;NET_3_5;NET_4_0 - prompt - 4 - v4.0 - - - - {D68133BD-1E63-496E-9EDE-4FBDBF77B486} @@ -87,38 +20,11 @@ - - - + - - - - - - + - - - False - ..\..\..\Test\libs\nunit-2.6.2\nunit.core.dll - - - False - ..\..\..\Test\libs\nunit-2.6.2\nunit.core.interfaces.dll - - - False - ..\..\..\Test\libs\nunit-2.6.2\nunit.framework.dll - - - - + + \ No newline at end of file diff --git a/external/cecil/symbols/pdb/Test/Mono.Cecil.Tests/PdbTests.cs b/external/cecil/symbols/pdb/Test/Mono.Cecil.Tests/PdbTests.cs index d084dcd44f..f8b4148051 100644 --- a/external/cecil/symbols/pdb/Test/Mono.Cecil.Tests/PdbTests.cs +++ b/external/cecil/symbols/pdb/Test/Mono.Cecil.Tests/PdbTests.cs @@ -12,13 +12,14 @@ namespace Mono.Cecil.Tests { [TestFixture] public class PdbTests : BaseTestFixture { - [TestModule ("test.exe", SymbolReaderProvider = typeof (PdbReaderProvider), SymbolWriterProvider = typeof (PdbWriterProvider))] - public void Main (ModuleDefinition module) + [Test] + public void Main () { - var type = module.GetType ("Program"); - var main = type.GetMethod ("Main"); + TestModule ("test.exe", module => { + var type = module.GetType ("Program"); + var main = type.GetMethod ("Main"); - AssertCode (@" + AssertCode (@" .locals init (System.Int32 i, System.Int32 CS$1$0000, System.Boolean CS$4$0001) .line 6,6:2,3 'c:\sources\cecil\symbols\Mono.Cecil.Pdb\Test\Resources\assemblies\test.cs' IL_0000: nop @@ -56,70 +57,106 @@ namespace Mono.Cecil.Tests { IL_0020: ldloc.1 IL_0021: ret ", main); + }, readOnly: Platform.OnMono, symbolReaderProvider: typeof(PdbReaderProvider), symbolWriterProvider: typeof(PdbWriterProvider)); } - [TestModule ("test.exe", SymbolReaderProvider = typeof (PdbReaderProvider), SymbolWriterProvider = typeof (PdbWriterProvider))] - public void Document (ModuleDefinition module) + [Test] + public void DebuggerHiddenVariable () { - var type = module.GetType ("Program"); - var method = type.GetMethod ("Main"); + TestModule ("test.exe", module => { + var type = module.GetType ("Program"); + var method = type.GetMethod ("Main"); - var sequence_point = method.Body.Instructions.Where (i => i.SequencePoint != null).First ().SequencePoint; - var document = sequence_point.Document; + var scope = method.DebugInformation.Scope; - Assert.IsNotNull (document); + Assert.IsTrue (scope.HasVariables); + var variables = scope.Variables; - Assert.AreEqual (@"c:\sources\cecil\symbols\Mono.Cecil.Pdb\Test\Resources\assemblies\test.cs", document.Url); - Assert.AreEqual (DocumentType.Text, document.Type); - Assert.AreEqual (DocumentHashAlgorithm.None, document.HashAlgorithm); - Assert.AreEqual (DocumentLanguage.CSharp, document.Language); - Assert.AreEqual (DocumentLanguageVendor.Microsoft, document.LanguageVendor); + Assert.AreEqual ("CS$1$0000", variables [0].Name); + Assert.IsTrue (variables [0].IsDebuggerHidden); + Assert.AreEqual ("CS$4$0001", variables [1].Name); + Assert.IsTrue (variables [1].IsDebuggerHidden); + + Assert.AreEqual (1, scope.Scopes.Count); + scope = scope.Scopes [0]; + variables = scope.Variables; + + Assert.AreEqual ("i", variables [0].Name); + Assert.IsFalse (variables [0].IsDebuggerHidden); + }, readOnly: Platform.OnMono, symbolReaderProvider: typeof(PdbReaderProvider), symbolWriterProvider: typeof(PdbWriterProvider)); } - [TestModule ("VBConsApp.exe", SymbolReaderProvider = typeof (PdbReaderProvider), SymbolWriterProvider = typeof (PdbWriterProvider))] - public void BasicDocument (ModuleDefinition module) + + [Test] + public void Document () { - var type = module.GetType ("VBConsApp.Program"); - var method = type.GetMethod ("Main"); + TestModule ("test.exe", module => { + var type = module.GetType ("Program"); + var method = type.GetMethod ("Main"); - var sequence_point = method.Body.Instructions.Where (i => i.SequencePoint != null).First ().SequencePoint; - var document = sequence_point.Document; + var sequence_point = method.DebugInformation.SequencePoints.First (sp => sp != null); + var document = sequence_point.Document; - Assert.IsNotNull (document); + Assert.IsNotNull (document); - Assert.AreEqual (@"c:\tmp\VBConsApp\Program.vb", document.Url); - Assert.AreEqual (DocumentType.Text, document.Type); - Assert.AreEqual (DocumentHashAlgorithm.None, document.HashAlgorithm); - Assert.AreEqual (DocumentLanguage.Basic, document.Language); - Assert.AreEqual (DocumentLanguageVendor.Microsoft, document.LanguageVendor); + Assert.AreEqual (@"c:\sources\cecil\symbols\Mono.Cecil.Pdb\Test\Resources\assemblies\test.cs", document.Url); + Assert.AreEqual (DocumentType.Text, document.Type); + Assert.AreEqual (DocumentHashAlgorithm.None, document.HashAlgorithm); + Assert.AreEqual (DocumentLanguage.CSharp, document.Language); + Assert.AreEqual (DocumentLanguageVendor.Microsoft, document.LanguageVendor); + }, readOnly: Platform.OnMono, symbolReaderProvider: typeof(PdbReaderProvider), symbolWriterProvider: typeof(PdbWriterProvider)); } - [TestModule ("fsapp.exe", SymbolReaderProvider = typeof (PdbReaderProvider), SymbolWriterProvider = typeof (PdbWriterProvider))] - public void FSharpDocument (ModuleDefinition module) + [Test] + public void BasicDocument () { - var type = module.GetType ("Program"); - var method = type.GetMethod ("fact"); + TestModule ("VBConsApp.exe", module => { + var type = module.GetType ("VBConsApp.Program"); + var method = type.GetMethod ("Main"); - var sequence_point = method.Body.Instructions.Where (i => i.SequencePoint != null).First ().SequencePoint; - var document = sequence_point.Document; + var sequence_point = method.DebugInformation.SequencePoints.First (sp => sp != null); + var document = sequence_point.Document; - Assert.IsNotNull (document); + Assert.IsNotNull (document); - Assert.AreEqual (@"c:\tmp\fsapp\Program.fs", document.Url); - Assert.AreEqual (DocumentType.Text, document.Type); - Assert.AreEqual (DocumentHashAlgorithm.None, document.HashAlgorithm); - Assert.AreEqual (DocumentLanguage.FSharp, document.Language); - Assert.AreEqual (DocumentLanguageVendor.Microsoft, document.LanguageVendor); + Assert.AreEqual (@"c:\tmp\VBConsApp\Program.vb", document.Url); + Assert.AreEqual (DocumentType.Text, document.Type); + Assert.AreEqual (DocumentHashAlgorithm.None, document.HashAlgorithm); + Assert.AreEqual (DocumentLanguage.Basic, document.Language); + Assert.AreEqual (DocumentLanguageVendor.Microsoft, document.LanguageVendor); + }, readOnly: Platform.OnMono, symbolReaderProvider: typeof(PdbReaderProvider), symbolWriterProvider: typeof(PdbWriterProvider)); + } + + [Test] + public void FSharpDocument () + { + TestModule ("fsapp.exe", module => { + var type = module.GetType ("Program"); + var method = type.GetMethod ("fact"); + + var sequence_point = method.DebugInformation.SequencePoints.First (sp => sp != null); + var document = sequence_point.Document; + + Assert.IsNotNull (document); + + Assert.AreEqual (@"c:\tmp\fsapp\Program.fs", document.Url); + Assert.AreEqual (DocumentType.Text, document.Type); + Assert.AreEqual (DocumentHashAlgorithm.None, document.HashAlgorithm); + Assert.AreEqual (DocumentLanguage.FSharp, document.Language); + Assert.AreEqual (DocumentLanguageVendor.Microsoft, document.LanguageVendor); + }, readOnly: Platform.OnMono, symbolReaderProvider: typeof(PdbReaderProvider), symbolWriterProvider: typeof(PdbWriterProvider)); } [Test] public void CreateMethodFromScratch () { + IgnoreOnMono (); + var module = ModuleDefinition.CreateModule ("Pan", ModuleKind.Dll); - var type = new TypeDefinition ("Pin", "Pon", TypeAttributes.Public | TypeAttributes.Abstract | TypeAttributes.Sealed, module.Import (typeof (object))); + var type = new TypeDefinition ("Pin", "Pon", TypeAttributes.Public | TypeAttributes.Abstract | TypeAttributes.Sealed, module.ImportReference (typeof (object))); module.Types.Add (type); - var method = new MethodDefinition ("Pang", MethodAttributes.Public | MethodAttributes.Static, module.Import (typeof (string))); + var method = new MethodDefinition ("Pang", MethodAttributes.Public | MethodAttributes.Static, module.ImportReference (typeof (string))); type.Methods.Add (method); var body = method.Body; @@ -127,7 +164,7 @@ namespace Mono.Cecil.Tests { body.InitLocals = true; var il = body.GetILProcessor (); - var temp = new VariableDefinition ("temp", module.Import (typeof (string))); + var temp = new VariableDefinition (module.ImportReference (typeof (string))); body.Variables.Add (temp); il.Emit (OpCodes.Nop); @@ -136,13 +173,19 @@ namespace Mono.Cecil.Tests { il.Emit (OpCodes.Ldloc, temp); il.Emit (OpCodes.Ret); - body.Instructions [0].SequencePoint = new SequencePoint (new Document (@"C:\test.cs")) { + var sequence_point = new SequencePoint (body.Instructions [0], new Document (@"C:\test.cs")) { StartLine = 0, StartColumn = 0, EndLine = 0, EndColumn = 4, }; + method.DebugInformation.SequencePoints.Add (sequence_point); + + method.DebugInformation.Scope = new ScopeDebugInformation (body.Instructions [0], null) { + Variables = { new VariableDebugInformation (temp, "temp") } + }; + var file = Path.Combine (Path.GetTempPath (), "Pan.dll"); module.Write (file, new WriterParameters { SymbolWriterProvider = new PdbWriterProvider (), @@ -154,22 +197,7 @@ namespace Mono.Cecil.Tests { method = module.GetType ("Pin.Pon").GetMethod ("Pang"); - Assert.AreEqual ("temp", method.Body.Variables [0].Name); - } - - static void AssertCode (string expected, MethodDefinition method) - { - Assert.IsTrue (method.HasBody); - Assert.IsNotNull (method.Body); - - System.Console.WriteLine (Formatter.FormatMethodBody (method)); - - Assert.AreEqual (Normalize (expected), Normalize (Formatter.FormatMethodBody (method))); - } - - static string Normalize (string str) - { - return str.Trim ().Replace ("\r\n", "\n"); + Assert.AreEqual ("temp", method.DebugInformation.Scope.Variables [0].Name); } } } diff --git a/external/cecil/symbols/pdb/Test/Resources/assemblies/PdbTarget.pdb b/external/cecil/symbols/pdb/Test/Resources/assemblies/PdbTarget.pdb new file mode 100644 index 0000000000..f9ef6a0be0 Binary files /dev/null and b/external/cecil/symbols/pdb/Test/Resources/assemblies/PdbTarget.pdb differ diff --git a/external/cecil/symbols/pdb/Test/Resources/assemblies/VBConsApp.pdb b/external/cecil/symbols/pdb/Test/Resources/assemblies/VBConsApp.pdb old mode 100755 new mode 100644 diff --git a/external/cecil/symbols/pdb/Test/Resources/assemblies/fsapp.pdb b/external/cecil/symbols/pdb/Test/Resources/assemblies/fsapp.pdb old mode 100755 new mode 100644 diff --git a/external/ikvm/reflect/Fusion.cs b/external/ikvm/reflect/Fusion.cs index c4bef4a752..009f296238 100644 --- a/external/ikvm/reflect/Fusion.cs +++ b/external/ikvm/reflect/Fusion.cs @@ -316,6 +316,7 @@ namespace IKVM.Reflection case "System.IdentityModel": case "System.IdentityModel.Selectors": case "System.IO.Compression": + case "System.IO.Compression.FileSystem": case "System.Numerics": case "System.Reflection.Context": case "System.Runtime.Remoting": @@ -363,13 +364,18 @@ namespace IKVM.Reflection case "System.Net.NetworkInformation": case "System.Net.Primitives": case "System.Net.Requests": + case "System.Numerics.Vectors": case "System.ObjectModel": case "System.Reflection": + case "System.Reflection.Emit": + case "System.Reflection.Emit.ILGeneration": + case "System.Reflection.Emit.Lightweight": case "System.Reflection.Extensions": case "System.Reflection.Primitives": case "System.Resources.ResourceManager": case "System.Runtime": case "System.Runtime.Extensions": + case "System.Runtime.Handles": case "System.Runtime.InteropServices": case "System.Runtime.InteropServices.WindowsRuntime": case "System.Runtime.Numerics": @@ -391,6 +397,7 @@ namespace IKVM.Reflection case "System.Threading": case "System.Threading.Tasks": case "System.Threading.Tasks.Parallel": + case "System.Threading.Timer": case "System.Web": case "System.Web.Mobile": case "System.Web.Services": diff --git a/external/ikvm/reflect/IKVM.Reflection.csproj b/external/ikvm/reflect/IKVM.Reflection.csproj index 8de23b7f9b..cf70e93a9d 100644 --- a/external/ikvm/reflect/IKVM.Reflection.csproj +++ b/external/ikvm/reflect/IKVM.Reflection.csproj @@ -10,7 +10,7 @@ Properties IKVM.Reflection IKVM.Reflection - v4.0 + v4.5 512 diff --git a/external/nunit-lite/NUnitLite-1.0.0/src/framework/Assertion.cs b/external/nunit-lite/NUnitLite-1.0.0/src/framework/Assertion.cs new file mode 100644 index 0000000000..a561fddfd1 --- /dev/null +++ b/external/nunit-lite/NUnitLite-1.0.0/src/framework/Assertion.cs @@ -0,0 +1,169 @@ +// **************************************************************** +// This is free software licensed under the NUnit license. You +// may obtain a copy of the license as well as information regarding +// copyright ownership at http://nunit.org/?p=license&r=2.4. +// **************************************************************** + +namespace NUnit.Framework +{ + using System; + + /// + /// The Assertion class is obsolete and has been + /// replaced by the Assert class. + /// + [Obsolete("Use Assert class instead")] + public class Assertion + { + /// + /// Asserts that a condition is true. If it isn't it throws + /// an . + /// + /// The message to display is the condition + /// is false + /// The evaluated condition + static public void Assert(string message, bool condition) + { + NUnit.Framework.Assert.IsTrue(condition, message); + } + + /// + /// Asserts that a condition is true. If it isn't it throws + /// an . + /// + /// The evaluated condition + static public void Assert(bool condition) + { + Assertion.Assert(string.Empty, condition); + } + + /// + /// /// Asserts that two doubles are equal concerning a delta. If the + /// expected value is infinity then the delta value is ignored. + /// + /// The expected value + /// The actual value + /// The maximum acceptable difference between the + /// the expected and the actual + static public void AssertEquals(double expected, double actual, double delta) + { + Assertion.AssertEquals(string.Empty, expected, actual, delta); + } + /// + /// /// Asserts that two singles are equal concerning a delta. If the + /// expected value is infinity then the delta value is ignored. + /// + /// The expected value + /// The actual value + /// The maximum acceptable difference between the + /// the expected and the actual + static public void AssertEquals(float expected, float actual, float delta) + { + Assertion.AssertEquals(string.Empty, expected, actual, delta); + } + + /// Asserts that two objects are equal. If they are not + /// an is thrown. + static public void AssertEquals(Object expected, Object actual) + { + Assertion.AssertEquals(string.Empty, expected, actual); + } + + /// Asserts that two ints are equal. If they are not + /// an is thrown. + static public void AssertEquals(int expected, int actual) + { + Assertion.AssertEquals(string.Empty, expected, actual); + } + + /// Asserts that two ints are equal. If they are not + /// an is thrown. + static public void AssertEquals(string message, int expected, int actual) + { + NUnit.Framework.Assert.AreEqual(expected, actual, message); + } + + /// Asserts that two doubles are equal concerning a delta. + /// If the expected value is infinity then the delta value is ignored. + /// + static public void AssertEquals(string message, double expected, + double actual, double delta) + { + NUnit.Framework.Assert.AreEqual(expected, actual, delta, message); + } + + /// Asserts that two floats are equal concerning a delta. + /// If the expected value is infinity then the delta value is ignored. + /// + static public void AssertEquals(string message, float expected, + float actual, float delta) + { + NUnit.Framework.Assert.AreEqual(expected, actual, delta, message); + } + + /// + /// Asserts that two objects are equal. Two objects are considered + /// equal if both are null, or if both have the same value. Numeric + /// types are compared via string comparision on their contents to + /// avoid problems comparing values between different types. All + /// non-numeric types are compared by using the Equals method. + /// If they are not equal an is thrown. + /// + static public void AssertEquals(string message, Object expected, Object actual) + { + NUnit.Framework.Assert.AreEqual(expected, actual, message); + } + + /// Asserts that an object isn't null. + static public void AssertNotNull(Object anObject) + { + NUnit.Framework.Assert.IsNotNull(anObject, string.Empty); + } + + /// Asserts that an object isn't null. + static public void AssertNotNull(string message, Object anObject) + { + NUnit.Framework.Assert.IsNotNull(anObject, message); + } + + /// Asserts that an object is null. + static public void AssertNull(Object anObject) + { + NUnit.Framework.Assert.IsNull(anObject, string.Empty); + } + + /// Asserts that an object is null. + static public void AssertNull(string message, Object anObject) + { + NUnit.Framework.Assert.IsNull(anObject, message); + } + + /// Asserts that two objects refer to the same object. If they + /// are not the same an is thrown. + /// + static public void AssertSame(Object expected, Object actual) + { + NUnit.Framework.Assert.AreSame(expected, actual, string.Empty); + } + + /// Asserts that two objects refer to the same object. + /// If they are not an is thrown. + /// + static public void AssertSame(string message, Object expected, Object actual) + { + NUnit.Framework.Assert.AreSame(expected, actual, message); + } + + /// Fails a test with no message. + static public void Fail() + { + NUnit.Framework.Assert.Fail(); + } + + /// Fails a test with the given message. + static public void Fail(string message) + { + NUnit.Framework.Assert.Fail(message); + } + } +} diff --git a/external/nunit-lite/NUnitLite-1.0.0/src/framework/Runner/TextUI.cs b/external/nunit-lite/NUnitLite-1.0.0/src/framework/Runner/TextUI.cs index 38822269b9..b3e937a585 100644 --- a/external/nunit-lite/NUnitLite-1.0.0/src/framework/Runner/TextUI.cs +++ b/external/nunit-lite/NUnitLite-1.0.0/src/framework/Runner/TextUI.cs @@ -62,6 +62,8 @@ namespace NUnitLite.Runner private FinallyDelegate finallyDelegate; + public bool Failure; + #region Constructors /// @@ -304,7 +306,9 @@ namespace NUnitLite.Runner new ResultReporter(result, writer).ReportResults(); string resultFile = commandLineOptions.ResultFile; string resultFormat = commandLineOptions.ResultFormat; - + + this.Failure = (result.ResultState == ResultState.Failure); + if (resultFile != null || commandLineOptions.ResultFormat != null) { if (resultFile == null) diff --git a/external/nunit-lite/NUnitLite-1.0.0/src/framework/StringAssert.cs b/external/nunit-lite/NUnitLite-1.0.0/src/framework/StringAssert.cs new file mode 100644 index 0000000000..c2510b8411 --- /dev/null +++ b/external/nunit-lite/NUnitLite-1.0.0/src/framework/StringAssert.cs @@ -0,0 +1,227 @@ +// **************************************************************** +// Copyright 2007, Charlie Poole +// This is free software licensed under the NUnit license. You may +// obtain a copy of the license at http://nunit.org/?p=license&r=2.4 +// **************************************************************** + +using System.ComponentModel; +using NUnit.Framework.Constraints; + +namespace NUnit.Framework +{ + /// + /// Basic Asserts on strings. + /// + public class StringAssert + { + #region Equals and ReferenceEquals + + /// + /// The Equals method throws an AssertionException. This is done + /// to make sure there is no mistake by calling this function. + /// + /// + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public static new bool Equals(object a, object b) + { + throw new AssertionException("Assert.Equals should not be used for Assertions"); + } + + /// + /// override the default ReferenceEquals to throw an AssertionException. This + /// implementation makes sure there is no mistake in calling this function + /// as part of Assert. + /// + /// + /// + public static new void ReferenceEquals(object a, object b) + { + throw new AssertionException("Assert.ReferenceEquals should not be used for Assertions"); + } + + #endregion + + #region Contains + + /// + /// Asserts that a string is found within another string. + /// + /// The expected string + /// The string to be examined + /// The message to display in case of failure + /// Arguments used in formatting the message + static public void Contains( string expected, string actual, string message, params object[] args ) + { + Assert.That(actual, new SubstringConstraint(expected), message, args); + } + + /// + /// Asserts that a string is found within another string. + /// + /// The expected string + /// The string to be examined + /// The message to display in case of failure + static public void Contains( string expected, string actual, string message ) + { + Contains( expected, actual, message, null ); + } + + /// + /// Asserts that a string is found within another string. + /// + /// The expected string + /// The string to be examined + static public void Contains( string expected, string actual ) + { + Contains( expected, actual, string.Empty, null ); + } + + #endregion + + #region StartsWith + + /// + /// Asserts that a string starts with another string. + /// + /// The expected string + /// The string to be examined + /// The message to display in case of failure + /// Arguments used in formatting the message + static public void StartsWith( string expected, string actual, string message, params object[] args ) + { + Assert.That(actual, new StartsWithConstraint(expected), message, args); + } + + /// + /// Asserts that a string starts with another string. + /// + /// The expected string + /// The string to be examined + /// The message to display in case of failure + static public void StartsWith( string expected, string actual, string message ) + { + StartsWith( expected, actual, message, null ); + } + + /// + /// Asserts that a string starts with another string. + /// + /// The expected string + /// The string to be examined + static public void StartsWith( string expected, string actual ) + { + StartsWith( expected, actual, string.Empty, null ); + } + + #endregion + + #region EndsWith + + /// + /// Asserts that a string ends with another string. + /// + /// The expected string + /// The string to be examined + /// The message to display in case of failure + /// Arguments used in formatting the message + static public void EndsWith( string expected, string actual, string message, params object[] args ) + { + Assert.That(actual, new EndsWithConstraint(expected), message, args); + } + + /// + /// Asserts that a string ends with another string. + /// + /// The expected string + /// The string to be examined + /// The message to display in case of failure + static public void EndsWith( string expected, string actual, string message ) + { + EndsWith( expected, actual, message, null ); + } + + /// + /// Asserts that a string ends with another string. + /// + /// The expected string + /// The string to be examined + static public void EndsWith( string expected, string actual ) + { + EndsWith( expected, actual, string.Empty, null ); + } + + #endregion + + #region AreEqualIgnoringCase + /// + /// Asserts that two strings are equal, without regard to case. + /// + /// The expected string + /// The actual string + /// The message to display in case of failure + /// Arguments used in formatting the message + static public void AreEqualIgnoringCase( string expected, string actual, string message, params object[] args ) + { + Assert.That(actual, new EqualConstraint(expected).IgnoreCase, message, args); + } + + /// + /// Asserts that two strings are equal, without regard to case. + /// + /// The expected string + /// The actual string + /// The message to display in case of failure + static public void AreEqualIgnoringCase( string expected, string actual, string message ) + { + AreEqualIgnoringCase( expected, actual, message, null ); + } + + /// + /// Asserts that two strings are equal, without regard to case. + /// + /// The expected string + /// The actual string + static public void AreEqualIgnoringCase( string expected, string actual ) + { + AreEqualIgnoringCase( expected, actual, string.Empty, null ); + } + + #endregion + + #region IsMatch + /// + /// Asserts that a string matches an expected regular expression pattern. + /// + /// The expected expression + /// The actual string + /// The message to display in case of failure + /// Arguments used in formatting the message + static public void IsMatch( string expected, string actual, string message, params object[] args ) + { + Assert.That(actual, new RegexConstraint(expected), message, args); + } + + /// + /// Asserts that a string matches an expected regular expression pattern. + /// + /// The expected expression + /// The actual string + /// The message to display in case of failure + static public void IsMatch( string expected, string actual, string message ) + { + IsMatch( expected, actual, message, null ); + } + + /// + /// Asserts that a string matches an expected regular expression pattern. + /// + /// The expected expression + /// The actual string + static public void IsMatch( string expected, string actual ) + { + IsMatch( expected, actual, string.Empty, null ); + } + #endregion + } +} diff --git a/ikvm-native/Makefile.in b/ikvm-native/Makefile.in index 477e414e0f..624d4a52d4 100644 --- a/ikvm-native/Makefile.in +++ b/ikvm-native/Makefile.in @@ -198,6 +198,8 @@ DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AOT_BUILD_FLAGS = @AOT_BUILD_FLAGS@ +AOT_RUN_FLAGS = @AOT_RUN_FLAGS@ API_VER = @API_VER@ AR = @AR@ AS = @AS@ @@ -206,6 +208,11 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOEHM_DEFINES = @BOEHM_DEFINES@ +BTLS_ARCH = @BTLS_ARCH@ +BTLS_CFLAGS = @BTLS_CFLAGS@ +BTLS_CMAKE_ARGS = @BTLS_CMAKE_ARGS@ +BTLS_PLATFORM = @BTLS_PLATFORM@ +BTLS_ROOT = @BTLS_ROOT@ BUILD_EXEEXT = @BUILD_EXEEXT@ CC = @CC@ CCAS = @CCAS@ @@ -215,6 +222,7 @@ CCDEPMODE = @CCDEPMODE@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMAKE = @CMAKE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ @@ -235,7 +243,6 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_PERF_EVENTS = @ENABLE_PERF_EVENTS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDKX11 = @GDKX11@ @@ -250,10 +257,12 @@ HAVE_MSGFMT = @HAVE_MSGFMT@ HOST_CC = @HOST_CC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MOBILE_STATIC = @INSTALL_MOBILE_STATIC@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTL = @INTL@ +INVARIANT_AOT_OPTIONS = @INVARIANT_AOT_OPTIONS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBC = @LIBC@ @@ -300,6 +309,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ +PLATFORM_AOT_SUFFIX = @PLATFORM_AOT_SUFFIX@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -309,6 +319,7 @@ SHELL = @SHELL@ SQLITE = @SQLITE@ SQLITE3 = @SQLITE3@ STRIP = @STRIP@ +TEST_PROFILE = @TEST_PROFILE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VTUNE_CFLAGS = @VTUNE_CFLAGS@ diff --git a/libgc/os_dep.c.REMOVED.git-id b/libgc/os_dep.c.REMOVED.git-id index 0031a8e89a..145511d12c 100644 --- a/libgc/os_dep.c.REMOVED.git-id +++ b/libgc/os_dep.c.REMOVED.git-id @@ -1 +1 @@ -8c8e0981dd6e236f531abd538290c5cd11865bed \ No newline at end of file +191e4b4ed7d06a8ea02f73a38ea84b941fc758c5 \ No newline at end of file diff --git a/llvm/Makefile.am b/llvm/Makefile.am new file mode 100644 index 0000000000..cda2a5762f --- /dev/null +++ b/llvm/Makefile.am @@ -0,0 +1,30 @@ +# +# Conditional submodule for llvm +# +# make reset-llvm will checkout a version of llvm which is suitable for this version of mono +# into $top_srcdir/llvm/llvm. +# + +LLVM_PATH=llvm + +SUBMODULES_CONFIG_FILE = $(top_srcdir)/llvm/SUBMODULES.json +include $(top_srcdir)/scripts/submodules/versions.mk + +$(eval $(call ValidateVersionTemplate,llvm,LLVM)) + +# Bump the given submodule to the revision given by the REV make variable +# If COMMIT is 1, commit the change +bump-llvm: __bump-version-llvm + +# Bump the given submodule to the branch given by the BRANCH/REMOTE_BRANCH make variables +# If COMMIT is 1, commit the change +bump-branch-llvm: __bump-branch-llvm + +# Bump the given submodule to its current GIT version +# If COMMIT is 1, commit the change +bump-current-llvm: __bump-current-version-llvm + +clean-local: + $(RM) -r $(LLVM_PATH) + +EXTRA_DIST=SUBMODULES.json diff --git a/llvm/Makefile.in b/llvm/Makefile.in new file mode 100644 index 0000000000..995cd6c908 --- /dev/null +++ b/llvm/Makefile.in @@ -0,0 +1,677 @@ +# Makefile.in generated by automake 1.14.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# +# Conditional submodule for llvm +# +# make reset-llvm will checkout a version of llvm which is suitable for this version of mono +# into $top_srcdir/llvm/llvm. +# + +# +# This is a python script and a set of make targets to implement support for conditional submodules +# Set the SUBMODULES_CONFIG_FILE make variable to the srcdir path of a SUBMODULES.json file which contains information about the submodules. +# +VPATH = @srcdir@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +DIST_COMMON = $(top_srcdir)/scripts/submodules/versions.mk \ + $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(top_srcdir)/mkinstalldirs +subdir = llvm +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/iconv.m4 \ + $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ + $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AOT_BUILD_FLAGS = @AOT_BUILD_FLAGS@ +AOT_RUN_FLAGS = @AOT_RUN_FLAGS@ +API_VER = @API_VER@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BOEHM_DEFINES = @BOEHM_DEFINES@ +BTLS_ARCH = @BTLS_ARCH@ +BTLS_CFLAGS = @BTLS_CFLAGS@ +BTLS_CMAKE_ARGS = @BTLS_CMAKE_ARGS@ +BTLS_PLATFORM = @BTLS_PLATFORM@ +BTLS_ROOT = @BTLS_ROOT@ +BUILD_EXEEXT = @BUILD_EXEEXT@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CC_FOR_BUILD = @CC_FOR_BUILD@ +CFLAGS = @CFLAGS@ +CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMAKE = @CMAKE@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFAULT_PROFILE = @DEFAULT_PROFILE@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOLT_BASH = @DOLT_BASH@ +DSYMUTIL = @DSYMUTIL@ +DTRACE = @DTRACE@ +DTRACEFLAGS = @DTRACEFLAGS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GDKX11 = @GDKX11@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_LIBS = @GLIB_LIBS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +GTKX11 = @GTKX11@ +HAVE_MSGFMT = @HAVE_MSGFMT@ +HOST_CC = @HOST_CC@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MOBILE_STATIC = @INSTALL_MOBILE_STATIC@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTL = @INTL@ +INVARIANT_AOT_OPTIONS = @INVARIANT_AOT_OPTIONS@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBC = @LIBC@ +LIBGC_CPPFLAGS = @LIBGC_CPPFLAGS@ +LIBGC_LIBS = @LIBGC_LIBS@ +LIBGC_STATIC_LIBS = @LIBGC_STATIC_LIBS@ +LIBICONV = @LIBICONV@ +LIBMONO_LA = @LIBMONO_LA@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LLVM_CFLAGS = @LLVM_CFLAGS@ +LLVM_CONFIG = @LLVM_CONFIG@ +LLVM_CXXFLAGS = @LLVM_CXXFLAGS@ +LLVM_LDFLAGS = @LLVM_LDFLAGS@ +LLVM_LIBS = @LLVM_LIBS@ +LN_S = @LN_S@ +LTCOMPILE = @LTCOMPILE@ +LTCXXCOMPILE = @LTCXXCOMPILE@ +LTLIBICONV = @LTLIBICONV@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MONO_DL_NEED_USCORE = @MONO_DL_NEED_USCORE@ +MONO_NACL_ALIGN_MASK_OFF = @MONO_NACL_ALIGN_MASK_OFF@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PLATFORM_AOT_SUFFIX = @PLATFORM_AOT_SUFFIX@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SGEN_DEFINES = @SGEN_DEFINES@ +SHARED_CFLAGS = @SHARED_CFLAGS@ +SHELL = @SHELL@ +SQLITE = @SQLITE@ +SQLITE3 = @SQLITE3@ +STRIP = @STRIP@ +TEST_PROFILE = @TEST_PROFILE@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +VTUNE_CFLAGS = @VTUNE_CFLAGS@ +VTUNE_LIBS = @VTUNE_LIBS@ +WERROR_CFLAGS = @WERROR_CFLAGS@ +X11 = @X11@ +XATTR_LIB = @XATTR_LIB@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +XINERAMA = @XINERAMA@ +XMKMF = @XMKMF@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +arch_target = @arch_target@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +docs_dir = @docs_dir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +export_ldflags = @export_ldflags@ +extra_runtime_ldflags = @extra_runtime_ldflags@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +ikvm_native_dir = @ikvm_native_dir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +libgc_dir = @libgc_dir@ +libgdiplus_install_loc = @libgdiplus_install_loc@ +libgdiplus_loc = @libgdiplus_loc@ +libmono_cflags = @libmono_cflags@ +libmono_ldflags = @libmono_ldflags@ +libsuffix = @libsuffix@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mcs_topdir = @mcs_topdir@ +mcs_topdir_from_srcdir = @mcs_topdir_from_srcdir@ +mkdir_p = @mkdir_p@ +mono_build_root = @mono_build_root@ +mono_cfg_dir = @mono_cfg_dir@ +mono_runtime = @mono_runtime@ +nacl_self_host = @nacl_self_host@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +reloc_libdir = @reloc_libdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +LLVM_PATH = llvm +SUBMODULES_CONFIG_FILE = $(top_srcdir)/llvm/SUBMODULES.json +SCRIPT = $(top_srcdir)/scripts/submodules/versions.py +EXTRA_DIST = SUBMODULES.json +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/scripts/submodules/versions.mk $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign llvm/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign llvm/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_srcdir)/scripts/submodules/versions.mk: + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +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-local mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + clean-local cscopelist-am ctags-am distclean distclean-generic \ + distclean-libtool 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-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags-am uninstall uninstall-am + + +# usage $(call ValidateVersionTemplate (name,MAKEFILE VAR,repo name)) +# usage $(call ValidateVersionTemplate (mono,MONO,mono)) + +define ValidateVersionTemplate +#$(eval REPOSITORY_$(2):=$(shell test -z $(3) && echo $(1) || echo "$(3)")) +#$(eval DIRECTORY_$(2):=$(shell python $(SCRIPT) $(SUBMODULES_CONFIG_FILE) get-dir $(1))) +#$(eval DIRECTORY_$(2):=$(shell test -z $(DIRECTORY_$(2)) && echo $(1) || echo $(DIRECTORY_$(2)))) +#$(eval MODULE_$(2):=$(shell python $(SCRIPT) $(SUBMODULES_CONFIG_FILE) get-url $(1))) +#$(eval NEEDED_$(2)_VERSION:=$(shell python $(SCRIPT) $(SUBMODULES_CONFIG_FILE) get-rev $(1))) +#$(eval $(2)_BRANCH_AND_REMOTE:=$(shell python $(SCRIPT) $(SUBMODULES_CONFIG_FILE) get-remote-branch $(1))) + +#$(eval $(2)_VERSION:=$$$$(shell cd $($(2)_PATH) 2>/dev/null && git rev-parse HEAD )) + +#$(eval NEEDED_$(2)_BRANCH:=$(word 2, $(subst /, ,$($(2)_BRANCH_AND_REMOTE)))) +#$(eval NEEDED_$(2)_REMOTE:=$(word 1, $(subst /, ,$($(2)_BRANCH_AND_REMOTE)))) +#$(eval $(2)_BRANCH:=$$$$(shell cd $($(2)_PATH) 2>/dev/null && git symbolic-ref --short HEAD 2>/dev/null)) + +validate-$(1):: + @if test x$$(IGNORE_$(2)_VERSION) = "x"; then \ + if test ! -d $($(2)_PATH); then \ + if test x$$(RESET_VERSIONS) != "x"; then \ + $(MAKE) reset-$(1) || exit 1; \ + else \ + echo "Your $(1) checkout is missing, please run 'make reset-$(1)'"; \ + touch .validate-versions-failure; \ + fi; \ + else \ + if test "x$($(2)_VERSION)" != "x$(NEEDED_$(2)_VERSION)" ; then \ + if test x$$(RESET_VERSIONS) != "x"; then \ + $(MAKE) reset-$(1) || exit 1; \ + else \ + echo "Your $(1) version is out of date, please run 'make reset-$(1)' (found $($(2)_VERSION), expected $(NEEDED_$(2)_VERSION))"; \ + test -z "$(BUILD_REVISION)" || $(MAKE) test-$(1); \ + touch .validate-versions-failure; \ + fi; \ + elif test "x$($(2)_BRANCH)" != "x$(NEEDED_$(2)_BRANCH)" ; then \ + if test x$$(RESET_VERSIONS) != "x"; then \ + test -z "$(BUILD_REVISION)" || $(MAKE) test-$(1); \ + $(MAKE) reset-$(1) || exit 1; \ + else \ + echo "Your $(1) branch is out of date, please run 'make reset-$(1)' (found $($(2)_BRANCH), expected $(NEEDED_$(2)_BRANCH))"; \ + touch .validate-versions-failure; \ + fi; \ + fi; \ + fi; \ + fi + +test-$(1):: + @echo $(1) + @echo " REPOSITORY_$(2)=$(REPOSITORY_$(2))" + @echo " DIRECTORY_$(2)=$(DIRECTORY_$(2))" + @echo " MODULE_$(2)=$(MODULE_$(2))" + @echo " NEEDED_$(2)_VERSION=$(NEEDED_$(2)_VERSION)" + @echo " $(2)_VERSION=$($(2)_VERSION)" + @echo " $(2)_BRANCH_AND_REMOTE=$($(2)_BRANCH_AND_REMOTE)" + @echo " NEEDED_$(2)_BRANCH=$(NEEDED_$(2)_BRANCH)" + @echo " NEEDED_$(2)_REMOTE=$(NEEDED_$(2)_REMOTE)" + @echo " $(2)_BRANCH=$($(2)_BRANCH)" + @echo " $(2)_PATH=$($(2)_PATH) => $(abspath $($(2)_PATH))" + +reset-$(1):: + @if test -d $($(2)_PATH); then \ + if ! (cd $($(2)_PATH) && git show $(NEEDED_$(2)_VERSION) >/dev/null 2>&1 && git log -1 $(NEEDED_$(2)_REMOTE/NEEDED_$(2)_BRANCH) >/dev/null 2>&1) ; then \ + echo "*** git fetch `basename $$($(2)_PATH)`" && (cd $($(2)_PATH) && git fetch); \ + fi; \ + else \ + echo "*** git clone $(MODULE_$(2)) --recursive $(DIRECTORY_$(2))" && (cd `dirname $($(2)_PATH)` && git clone $(MODULE_$(2)) --recursive $(DIRECTORY_$(2)) || exit 1 ); \ + fi + @if test x$$(IGNORE_$(2)_VERSION) = "x"; then \ + echo "*** [$(1)] git checkout -f" $(NEEDED_$(2)_BRANCH) && (cd $($(2)_PATH) ; git checkout -f $(NEEDED_$(2)_BRANCH) || git checkout -f -b $($(2)_BRANCH_AND_REMOTE)); \ + echo "*** [$(1)] git reset --hard $(NEEDED_$(2)_VERSION)" && (cd $($(2)_PATH) && git reset --hard $(NEEDED_$(2)_VERSION)); \ + fi + @echo "*** [$(1)] git submodule update --init --recursive" && (cd $($(2)_PATH) && git submodule update --init --recursive) + +print-$(1):: + @printf "*** %-16s %-45s %s (%s)\n" "$(DIRECTORY_$(2))" "$(MODULE_$(2))" "$(NEEDED_$(2)_VERSION)" "$(NEEDED_$(2)_BRANCH)" + +.PHONY: validate-$(1) reset-$(1) print-$(1) + +reset-versions:: reset-$(1) +validate-versions:: validate-$(1) +print-versions:: print-$(1) + +endef + +reset-versions:: + +validate-versions:: + @if test -e .validate-versions-failure; then \ + rm .validate-versions-failure; \ + echo One or more modules needs update; \ + exit 1; \ + else \ + echo All dependent modules up to date; \ + fi + +reset: + @$(MAKE) validate-versions RESET_VERSIONS=1 + +__bump-version-%: + @if [ "$(REV)" = "" ]; then echo "Usage: make bump-version-$* REV="; exit 1; fi + python $(SCRIPT) $(SUBMODULES_CONFIG_FILE) set-rev $* $(REV) + @if [ "$(COMMIT)" = "1" ]; then echo "[submodules] Bump $* to pick up $(REV)." | git commit -F - $(SUBMODULES_CONFIG_FILE); fi + +__bump-branch-%: + @if [ "$(BRANCH)" = "" ]; then echo "Usage: make bump-branch-$* BRANCH= REMOTE_BRANCH="; exit 1; fi + @if [ "$(REMOTE_BRANCH)" == "" ]; then echo "Usage: make bump-branch-$* BRANCH= REMOTE_BRANCH="; exit 1; fi + python $(SCRIPT) $(SUBMODULES_CONFIG_FILE) set-branch $* $(BRANCH) + python $(SCRIPT) $(SUBMODULES_CONFIG_FILE) set-remote-branch $* $(REMOTE_BRANCH) + @if [ "$(COMMIT)" = "1" ]; then echo "[submodules] Bump $* to switch to $(BRANCH) $(REMOTE BRANCH)." | git commit -F - $(SUBMODULES_CONFIG_FILE); fi + +__bump-current-version-%: + REV=$(shell cd $(ACCEPTANCE_TESTS_PATH)/$* && git log -1 --pretty=format:%H); \ + python $(SCRIPT) $(SUBMODULES_CONFIG_FILE) set-rev $* $$REV; \ + if [ "$(COMMIT)" = "1" ]; then echo "[submodules] Bump $* to pick up $$REV:" | git commit -F - $(SUBMODULES_CONFIG_FILE); fi + +$(eval $(call ValidateVersionTemplate,llvm,LLVM)) + +# Bump the given submodule to the revision given by the REV make variable +# If COMMIT is 1, commit the change +bump-llvm: __bump-version-llvm + +# Bump the given submodule to the branch given by the BRANCH/REMOTE_BRANCH make variables +# If COMMIT is 1, commit the change +bump-branch-llvm: __bump-branch-llvm + +# Bump the given submodule to its current GIT version +# If COMMIT is 1, commit the change +bump-current-llvm: __bump-current-version-llvm + +clean-local: + $(RM) -r $(LLVM_PATH) + +# 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/llvm/SUBMODULES.json b/llvm/SUBMODULES.json new file mode 100644 index 0000000000..e4fbbb02e8 --- /dev/null +++ b/llvm/SUBMODULES.json @@ -0,0 +1,10 @@ +[ + { + "name": "llvm", + "url": "git://github.com/mono/llvm.git", + "rev": "9f79399f87282524fee099b328bd8cbf07929daf", + "remote-branch": "origin/master", + "branch": "master", + "directory": "llvm" + } +] diff --git a/m4/Makefile.in b/m4/Makefile.in index d97e1d2aaa..1f31a336eb 100644 --- a/m4/Makefile.in +++ b/m4/Makefile.in @@ -120,6 +120,8 @@ DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AOT_BUILD_FLAGS = @AOT_BUILD_FLAGS@ +AOT_RUN_FLAGS = @AOT_RUN_FLAGS@ API_VER = @API_VER@ AR = @AR@ AS = @AS@ @@ -128,6 +130,11 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOEHM_DEFINES = @BOEHM_DEFINES@ +BTLS_ARCH = @BTLS_ARCH@ +BTLS_CFLAGS = @BTLS_CFLAGS@ +BTLS_CMAKE_ARGS = @BTLS_CMAKE_ARGS@ +BTLS_PLATFORM = @BTLS_PLATFORM@ +BTLS_ROOT = @BTLS_ROOT@ BUILD_EXEEXT = @BUILD_EXEEXT@ CC = @CC@ CCAS = @CCAS@ @@ -137,6 +144,7 @@ CCDEPMODE = @CCDEPMODE@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMAKE = @CMAKE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ @@ -157,7 +165,6 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_PERF_EVENTS = @ENABLE_PERF_EVENTS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDKX11 = @GDKX11@ @@ -172,10 +179,12 @@ HAVE_MSGFMT = @HAVE_MSGFMT@ HOST_CC = @HOST_CC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MOBILE_STATIC = @INSTALL_MOBILE_STATIC@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTL = @INTL@ +INVARIANT_AOT_OPTIONS = @INVARIANT_AOT_OPTIONS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBC = @LIBC@ @@ -222,6 +231,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ +PLATFORM_AOT_SUFFIX = @PLATFORM_AOT_SUFFIX@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -231,6 +241,7 @@ SHELL = @SHELL@ SQLITE = @SQLITE@ SQLITE3 = @SQLITE3@ STRIP = @STRIP@ +TEST_PROFILE = @TEST_PROFILE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VTUNE_CFLAGS = @VTUNE_CFLAGS@ diff --git a/m4/nls.m4 b/m4/nls.m4 index 003704c4b9..93e89ee463 100644 --- a/m4/nls.m4 +++ b/m4/nls.m4 @@ -26,7 +26,7 @@ AC_DEFUN([AM_NLS], dnl Default is enabled NLS AC_ARG_ENABLE([nls], [ --disable-nls do not use Native Language Support], - USE_NLS=$enableval, USE_NLS=yes) + USE_NLS=$enableval, USE_NLS=profile_default) AC_MSG_RESULT([$USE_NLS]) AC_SUBST([USE_NLS]) ]) diff --git a/man/Makefile.am b/man/Makefile.am index de2b6ac7c3..0c8b29892f 100644 --- a/man/Makefile.am +++ b/man/Makefile.am @@ -2,6 +2,7 @@ man_MANS = \ al.1 \ cert2spc.1 \ certmgr.1 \ + cert-sync.1 \ chktrust.1 \ cilc.1 \ crlupdate.1 \ diff --git a/man/Makefile.in b/man/Makefile.in index 07b2d9d7f9..cd214cd763 100644 --- a/man/Makefile.in +++ b/man/Makefile.in @@ -152,6 +152,8 @@ DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AOT_BUILD_FLAGS = @AOT_BUILD_FLAGS@ +AOT_RUN_FLAGS = @AOT_RUN_FLAGS@ API_VER = @API_VER@ AR = @AR@ AS = @AS@ @@ -160,6 +162,11 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOEHM_DEFINES = @BOEHM_DEFINES@ +BTLS_ARCH = @BTLS_ARCH@ +BTLS_CFLAGS = @BTLS_CFLAGS@ +BTLS_CMAKE_ARGS = @BTLS_CMAKE_ARGS@ +BTLS_PLATFORM = @BTLS_PLATFORM@ +BTLS_ROOT = @BTLS_ROOT@ BUILD_EXEEXT = @BUILD_EXEEXT@ CC = @CC@ CCAS = @CCAS@ @@ -169,6 +176,7 @@ CCDEPMODE = @CCDEPMODE@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMAKE = @CMAKE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ @@ -189,7 +197,6 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_PERF_EVENTS = @ENABLE_PERF_EVENTS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDKX11 = @GDKX11@ @@ -204,10 +211,12 @@ HAVE_MSGFMT = @HAVE_MSGFMT@ HOST_CC = @HOST_CC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MOBILE_STATIC = @INSTALL_MOBILE_STATIC@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTL = @INTL@ +INVARIANT_AOT_OPTIONS = @INVARIANT_AOT_OPTIONS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBC = @LIBC@ @@ -254,6 +263,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ +PLATFORM_AOT_SUFFIX = @PLATFORM_AOT_SUFFIX@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -263,6 +273,7 @@ SHELL = @SHELL@ SQLITE = @SQLITE@ SQLITE3 = @SQLITE3@ STRIP = @STRIP@ +TEST_PROFILE = @TEST_PROFILE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VTUNE_CFLAGS = @VTUNE_CFLAGS@ @@ -355,6 +366,7 @@ man_MANS = \ al.1 \ cert2spc.1 \ certmgr.1 \ + cert-sync.1 \ chktrust.1 \ cilc.1 \ crlupdate.1 \ diff --git a/man/cert-sync.1 b/man/cert-sync.1 new file mode 100644 index 0000000000..66d3d60ec8 --- /dev/null +++ b/man/cert-sync.1 @@ -0,0 +1,52 @@ +.\" +.\" cert-sync manual page. +.\" Copyright 2016 Microsoft Corp +.\" Author: +.\" Jo Shields +.\" +.TH Mono "cert-sync" +.SH NAME +cert-sync \- Mono Certificate Store Sync Tool +.SH SYNOPSIS +.PP +.B cert-sync [--quiet] [--user] filename +.SH DESCRIPTION +This tool allows you to populate a Mono certificate store, from a large +concatenated list of certificates in PEM format (commonly provided on most +Linux distributions). + +Its use is intended to be automated at Mono install time, by distribution +packagers, to seamlessly provide SSL support to Mono applications without +further user interaction. +.SH OPTIONS +.TP +.I "--quiet" +Suppress verbose output +.TP +.I "--user" +Populate the per-user store in the user's home directory, instead of the +system-wide store. +.TP +.I "filename.crt" +Path to a certificate bundle. The Mono store will have any extra entries +removed, and new entries added, to reflect the provided file. + +.SH EXAMPLES +.TP +.B cert-sync /etc/ssl/certs/ca-certificates.crt +Synchronize the machine store, from the Debian cert store location +.TP +.B cert-sync --user /etc/pki/tls/certs/ca-bundle.crt +Synchronize the user store, from the Red Hat cert store location + +.SH AUTHOR +Written by Jo Shields + +.SH COPYRIGHT +Copyright (C) 2016 Microsoft Corp +.SH MAILING LISTS +Visit http://lists.ximian.com/mailman/listinfo/mono-list for details. +.SH WEB SITE +Visit http://www.mono-project.com for details +.SH SEE ALSO +.BR certmgr(1) diff --git a/man/mkbundle.1 b/man/mkbundle.1 index d61fc1757b..3d067eb27e 100644 --- a/man/mkbundle.1 +++ b/man/mkbundle.1 @@ -21,38 +21,237 @@ default only the assemblies specified in the command line will be included in the bundle. To automatically include all of the dependencies referenced, use the "--deps" command line option. .PP -There are two modes of operation, the default one uses the -C compiler to create a bundle and requires a complete C and Mono SDK -to produced executables. The simple mode (enabled when using the -"--simple") command line option does not require this, and also allows -for cross compilation. +There are two modes of operation, one uses an existing Mono binary or +a server-hosted list of binaries and is enabled when you use either +the +.B --cross, +.B --sdk +or the +.B --runtime +command line options. +.PP +An older mechanism creates a small C stub that links against the +libmono library to produce a self-contained executable and requires a +C compiler. It is described in the "OLD EMBEDDING" section below. .PP For example, to create a bundle for hello world, use the following command: .nf + $ mkbundle -o hello --simple hello.exe + .fi +.PP +You can configure options to be passed to the Mono runtime directly +into your executable, for this, use the +.I --options +flag. For example, the following disables inlining, by passing the +"-O=-inline" command line option to the embedded executable: +.nf + + $ mkbundle -o hello --options -O=-inline --simple hello.exe + .PP The simple version allows for cross-compiling, this requires a Mono runtime to be installed in the ~/.mono/targets/TARGET/mono to be available. You can use the "--local-targets" to list all available targets, and the "--cross" argument to specify the target, like this: .nf + $ mkbundle --local-targets Available targets: default - Current System Mono 4.4.0-macosx-x86 4.4.0-debian-8-arm64 $ mkbundle --cross 4.4.0-debian-8-powerpc hello.exe -o hello-debian + .fi .PP The above will bundle your native library into hello-debian for a Debian 8 system running on a PowerPC machine. +.PP +We provide pre-packages binaries for Mono for various architectures, +which allow you to cross compile, use the +.B --list-targets +to get a list of all targets supported, and use the +.B --fetch-target +flag to retrieve a target that you do not have installed, like this: +.nf + + $ mkbundle --list-targets + Cross-compilation targets available: + 4.4.0-linux-libc2.13-amd64 + 4.4.0-linux-libc2.13-armel + 4.4.0-linux-libc2.13-armhf + 4.4.0-linux-libc2.13-i386 + 4.4.0-macos-10.7-amd64 + 4.4.0-macos-10.7-i386 + 4.4.2-linux-libc2.13-amd64 + 4.4.2-linux-libc2.13-armel + 4.4.2-linux-libc2.13-armhf + 4.4.2-linux-libc2.13-i386 + 4.4.2-macos-10.7-amd64 + 4.4.2-macos-10.7-i386 + + $ mkbundle --fetch-target 4.4.2-macos-10.7-i386 + +.fi +.PP +And then you can produce a binary that will run on 32-bit Mono on +MacOS: +.nf + + $ mkbundle --cross 4.4.2-macos-10.7-i386 hello.exe -o hello-macos + +.fi +.PP +Downloaded targets are stored +.B ~/.mono/targets +directory. +.SH OPTIONS +.TP +.I "--config FILE" +Specifies that a machine.config file must be bundled as well. +Typically this is $prefix/etc/mono/1.0/machine.config or +$prefix/etc/mono/2.0/machine.config depending on the profile that you +are using (1.0 or 2.0) +.TP +.I "--config-dir DIR" +When passed, DIR will be set for the MONO_CFG_DIR environment variable +.TP +.I "--cross target" +Use this to request mkbundle generate a cross-compiled binary. It +Creates a bundle for the specified target platform. The target must +be a directory in ~/.mono/targets/ that contains an SDK installation +as produced by the mono-package-runtime tool. You can get a list of +the precompiled versions of the runtime using --list-targets and you +can fetch a specific target using the --fetch-target command line +option. +.Sp +This flag is mutually exclusive with +.I --sdk +which is used to specify an absolute path to resolve the Mono runtime +from and the --runtime option which is used to manually construct the +cross-platform package. +.TP +.I "--deps" +This option will bundle all of the referenced assemblies for the +assemblies listed on the command line option. This is useful to +distribute a self-contained image. +.TP +.I "--env KEY=VALUE" +Use this to hardcode an environment variable at runtime for KEY to be +mapped to VALUE. This is useful in scenarios where you want to +enable certain Mono runtime configuration options that are controlled +by environment variables. +.TP +.I "--fetch-target target" +Downloads a precompiled runtime for the specified target from the Mono +distribution site. +.TP +.I "--i18n encoding" +Specified which encoding tables to ship with the executable. By +default, Mono ships the supporting I18N.dll assembly and the +I18N.West.dll assembly. If your application will use the +System.Text.Encoding.GetEncoding with encodings other than the West +encodings, you should specify them here. +.Sp +You can use the +.B none +parameter to request that no implicit encodings should be bundled, +including the supporting I18N.dll, use this option if you have ran a +linker on your own. +.Sp +You can use the +.B all +flag to bundle all available encodings. +.Sp +Or you can use a comma delimited list of the workds CJK, MidWest, +Other, Rare and West to specificy which encoding assemblies to distribute. +.TP +.I "-L path" +Adds the `path' do the search list for assemblies. The rules are the +same as for the compiler -lib: or -L flags. +.TP +.I "--library [LIB,]PATH" +Embeds the dynamic library file pointed to by `PATH' and optionally +give it the name `LIB' into the bundled executable. This is used to +ship native library dependencies that are unpacked at startup and +loaded from the runtime. +.TP +.I "--lists-targets" +Lists all of the available local cross compilation targets available +as precompiled binaries on the Mono distribution server. +.TP +.I "--local-targets" +Lists all of the available local cross compilation targets. +.TP +.I "--machine-config FILE" +Uses the given FILE as the machine.config file for the generated +application. +.TP +.I "--nodeps" +This is the default: \fImkbundle\fP will only include the assemblies that +were specified on the command line to reduce the size of the resulting +image created. +.TP +.I "-o filename" +Places the output on `out'. If the flag -c is specified, this is the +C host program. If not, this contains the resulting executable. +.TP +.I "--options OPTS" +Since the resulting executable will be treated as a standalone +program, you can use this option to pass configuration options to the +Mono runtime and bake those into the resulting executable. These +options are specified as +.I OPTS. +.Sp +You can use the above to configure options that you would typically +pass on the command line to Mono, before the main program is +executed. +.Sp +Additionally, users of your binary can still configure their own +options by setting the +.I MONO_ENV_OPTIONS +environment variable. +.TP +.I "--sdk SDK_PATH" +Use this flag to specify a path from which mkbundle will resolve the +Mono SDK from. The SDK path should be the prefix path that you used +to configure a Mono installation. And would typically contain files +lik +.I SDK_PATH/bin/mono +, +.I SDK_PATH/lib/mono/4.5 +and so on. +.Sp +When this flag is specified, +.I mkbundle +will resolve the runtime, the framework libraries, unmanaged resources +and configuration files from the files located in this directory. +.Sp +This flag is mutually exlusive with +.I --cross +. +.TP +.I "--target-server SERVER" +By default the mkbundle tool will download from a Mono server the +target runtimes, you can specify a different server to provide +cross-compiled runtimes. .SH OLD EMBEDDING .PP +The old embedding system compiles a small C stub that embeds the +C code and compiles the resulting executable using the system +compiler. This requires both a working C compiler installation and +only works to bundle binaries for the current host. +.PP +The feature is still available, but we recommend the simpler, faster +and more convenient new mode. +.PP For example, to create a bundle for hello world, use the following command: .nf + $ mkbundle -o hello hello.exe .fi .PP @@ -66,6 +265,7 @@ you want to link additional libraries or control the generated output in more detail. For example, this could be used to link some libraries statically: .nf + $ mkbundle -c -o host.c -oo bundles.o --deps hello.exe $ cc host.c bundles.o /usr/lib/libmono.a -lc -lrt @@ -77,86 +277,40 @@ both the -c and --nomain options. The resulting host.c file will not have a main() function. Call mono_mkbundle_init() before initializing the JIT in your code so that the bundled assemblies are available to the embedded runtime. -.SH OPTIONS +.SH OLD EMBEDDING OPTIONS +These options can only be used instead of using the +.B --cross, --runtime +or +.B --simple +options. .TP .I "-c" Produce the stub file, do not compile the resulting stub. .TP -.I "--cross target" -Creates a bundle for the specified target platform. The target -must be a directory in ~/.mono/targets/ that contains a "mono" -binary. You can fetch various targets using the --fetch-target -command line option. -.TP -.I "-o filename" -Places the output on `out'. If the flag -c is specified, this is the -C host program. If not, this contains the resulting executable. -.TP .I "-oo filename" Specifies the name to be used for the helper object file that contains the bundle. .TP -.I "-L path" -Adds the `path' do the search list for assemblies. The rules are the -same as for the compiler -lib: or -L flags. -.TP "--config FILE" -Specifies that a machine.config file must be bundled as well. -Typically this is $prefix/etc/mono/1.0/machine.config or -$prefix/etc/mono/2.0/machine.config depending on the profile that you -are using (1.0 or 2.0) -.TP -.I "--deps" -This option will bundle all of the referenced assemblies for the -assemblies listed on the command line option. This is useful to -distribute a self-contained image. -.TP -.I "--fetch-target target" -Downloads a precompiled runtime for the specified target from the Mono -distribution site. -.TP -.I "--nodeps" -This is the default: \fImkbundle\fP will only include the assemblies that -were specified on the command line to reduce the size of the resulting -image created. -.TP .I "--keeptemp" By default \fImkbundle\fP will delete the temporary files that it uses to produce the bundle. This option keeps the file around. .TP -.I "--lists-targets" -Lists all of the available local cross compilation targets available -as precompiled binaries on the Mono distribution server. -.TP -.I "--local-targets" -Lists all of the available local cross compilation targets. -.TP -.I "--machine-config FILE" -Uses the given FILE as the machine.config file for the generated -application. -.TP .I "--nomain" With the -c option, generate the host stub without a main() function. .TP -.I "--config-dir DIR" -When passed, DIR will be set for the MONO_CFG_DIR environment variable -.TP .I "--static" By default \fImkbundle\fP dynamically links to mono and glib. This option causes it to statically link instead. .TP -.I "--target-server SERVER" -By default the mkbundle tool will download from a Mono server the -target runtimes, you can specify a different server to provide -cross-compiled runtimes. -.TP .I "-z" Compresses the assemblies before embedding. This results in smaller executable files, but increases startup time and requires zlib to be installed on the target system. .SH WINDOWS -On Windows systems, it it necessary to have Unix-like toolchain to be -installed for \fImkbundle\fP to work. You can use cygwin's and install gcc, -gcc-mingw and as packages. +If you are using the old embedding on Windows systems, it it necessary +to have Unix-like toolchain to be installed for \fImkbundle\fP to +work. You can use cygwin's and install gcc, gcc-mingw and as +packages. .SH ENVIRONMENT VARIABLES .TP .I "AS" @@ -175,7 +329,8 @@ cache. .PP Targets are loaded from ~/.mono/targets/TARGETNAME/mono .SH BUGS -The option "--static" is not supported under Windows. +The option "--static" is not supported under Windows when using the +old embedding. Moreover, a full cygwin environment containing at least "gcc" and "as" is required for the build process. The generated executable does not depend on cygwin. diff --git a/man/mono.1 b/man/mono.1 index 706cc51861..c4589ea70c 100644 --- a/man/mono.1 +++ b/man/mono.1 @@ -7,7 +7,7 @@ .\" Author: .\" Miguel de Icaza (miguel@gnu.org) .\" -.TH Mono "Mono 3.0" +.TH Mono "Mono 4.7.0" .SH NAME mono \- Mono's ECMA-CLI native code generator (Just-in-Time and Ahead-of-Time) .SH SYNOPSIS @@ -1100,7 +1100,7 @@ a Mono process through the environment. This is useful for example to force all of your Mono processes to use LLVM or SGEN without having to modify any launch scripts. .TP -\fBMONO_ENV_OPTIONS\fR +\fBMONO_SDB_ENV_OPTIONS\fR Used to pass extra options to the debugger agent in the runtime, as they were passed using --debugger-agent=. .TP @@ -1302,12 +1302,12 @@ statistics when shutting down. .TP \fBcollect-before-allocs\fR .TP -\fBcheck-at-minor-collections\fR -This performs a consistency check on minor collections and also clears -the nursery at collection time, instead of the default, when buffers -are allocated (clear-at-gc). The consistency check ensures that -there are no major to minor references that are not on the remembered -sets. +\fBcheck-remset-consistency\fR +This performs a remset consistency check at various opportunities, and +also clears the nursery at collection time, instead of the default, +when buffers are allocated (clear-at-gc). The consistency check +ensures that there are no major to minor references that are not on +the remembered sets. .TP \fBmod-union-consistency-check\fR Checks that the mod-union cardtable is consistent before each @@ -1732,6 +1732,16 @@ messages for a certain component. You can use multiple masks by comma separating them. For example to see config file messages and assembly loader messages set you mask to "asm,cfg". .TP +\fBMONO_LOG_DEST\fR +Controls where trace log messages are written. If not set then the messages go to stdout. +If set, the string either specifies a path to a file that will have messages appended to +it, or the string "syslog" in which case the messages will be written to the system log. +Under Windows, this is simulated by writing to a file called "mono.log". +\fBMONO_LOG_HEADER\fR +Controls whether trace log messages not directed to syslog have the id, timestamp, and +pid as the prefix to the log message. To enable a header this environment variable need +just be non-null. +.TP \fBMONO_TRACE\fR Used for runtime tracing of method calls. The format of the comma separated trace options is: diff --git a/man/mprof-report.1 b/man/mprof-report.1 index c2020a7445..f19a02aa14 100644 --- a/man/mprof-report.1 +++ b/man/mprof-report.1 @@ -92,7 +92,7 @@ provided by the Mono runtime and write them to a file named \f[I]output.mlpd\f[]. When no option is specified, it is equivalent to using: .PP -\f[B]--profile=log:calls,alloc,output=output.mlpd,maxframes=8,calldepth=100\f[] +\f[B]--profile=log:calls,alloc,output=output.mlpd,maxframes=32,calldepth=100\f[] .PP The following options can be used to modify this default behaviour. Each option is separated from the next by a \f[B],\f[] character, @@ -139,41 +139,16 @@ garbage collections to the control port .RE .IP \[bu] 2 -\f[I]sample[=TYPE[/FREQ]]\f[]: collect statistical samples of the +\f[I]sample[=FREQ]\f[]: collect statistical samples of the program behaviour. The default is to collect a 100 times per second (100 Hz) the instruction pointer. -This is equivalent to the value \[lq]cycles/100\[rq] for -\f[I]TYPE\f[]. -On some systems, like with recent Linux kernels, it is possible to -cause the sampling to happen for other events provided by the -performance counters of the cpu. -In this case, \f[I]TYPE\f[] can be one of: -.RS 2 -.IP \[bu] 2 -\f[I]cycles\f[]: processor cycles -.IP \[bu] 2 -\f[I]instr\f[]: executed instructions -.IP \[bu] 2 -\f[I]cacherefs\f[]: cache references -.IP \[bu] 2 -\f[I]cachemiss\f[]: cache misses -.IP \[bu] 2 -\f[I]branches\f[]: executed branches -.IP \[bu] 2 -\f[I]branchmiss\f[]: mispredicted branches -.RE -.IP \[bu] 2 -\f[I]time=TIMER\f[]: use the TIMER timestamp mode. -TIMER can have the following values: -.RS 2 -.IP \[bu] 2 -\f[I]fast\f[]: a usually faster but possibly more inaccurate timer -.RE +This is equivalent to the value \[lq]100\[rq]. +A value of zero for \f[I]FREQ\f[] effectively disables sampling. .IP \[bu] 2 \f[I]maxframes=NUM\f[]: when a stack trace needs to be performed, collect \f[I]NUM\f[] frames at the most. -The default is 8. +The default is 32. .IP \[bu] 2 \f[I]maxsamples=NUM\f[]: stop allocating reusable sample events once \f[I]NUM\f[] events have been allocated (a value of zero for @@ -234,16 +209,15 @@ The following commands are available: \f[I]heapshot\f[]: perform a heapshot as soon as possible .RE .IP \[bu] 2 -\f[I]counters\f[]: sample counters values every 1 second. This allow -a really lightweight way to have insight in some of the runtime key -metrics. Counters displayed in non verbose mode are : Methods from AOT, -Methods JITted using mono JIT, Methods JITted using LLVM, Total time -spent JITting (sec), User Time, System Time, Total Time, Working Set, -Private Bytes, Virtual Bytes, Page Faults and CPU Load Average (1min, -5min and 15min). +\f[I]nocounters\f[]: disables sampling of runtime and performance +counters, which is normally done every 1 second. .IP \[bu] 2 \f[I]coverage\f[]: collect code coverage data. This implies enabling the \f[I]calls\f[] option. +.IP \[bu] 2 +\f[I]onlycoverage\f[]: can only be used with \f[I]coverage\f[]. This +disables most other events so that the profiler mostly only collects +coverage data. .RE .SS Analyzing the profile data .PP @@ -274,10 +248,6 @@ with the \f[I]--maxframes=NUM\f[] option: The stack trace info will be available if method enter/leave events have been recorded or if stack trace collection wasn't explicitly disabled with the \f[I]maxframes=0\f[] profiler option. -Note that the profiler will collect up to 8 frames by default at -specific events when the \f[I]nocalls\f[] option is used, so in -that case, if more stack frames are required in mprof-report, a -bigger value for maxframes when profiling must be used, too. .PP The \f[I]--traces\f[] option also controls the reverse reference feature in the heapshot report: for each class it reports how many @@ -487,15 +457,6 @@ option: especially if the managed heap is big, since every object needs to be inspected. The \f[I]MODE\f[] parameter of the \f[I]heapshot\f[] option can be used to reduce the frequency of the heap shots. -.IP "\f[I]Reduce the timestamp overhead\f[]" 4 -.Sp -On many operating systems or architectures what actually slows down -profiling is the function provided by the system to get timestamp -information. -The \f[I]time=fast\f[] profiler option can be usually used to speed -up this operation, but, depending on the system, time accounting -may have some level of approximation (though statistically the data -should be still fairly valuable). .SS Dealing with the size of the data files .PP When collecting a lot of information about a profiled program, huge diff --git a/mcs/Makefile b/mcs/Makefile index 7dbfb63891..6a7a58d7fc 100644 --- a/mcs/Makefile +++ b/mcs/Makefile @@ -15,7 +15,7 @@ monotouch_watch_runtime_SUBDIRS := build class monotouch_tv_runtime_SUBDIRS := build class xammac_SUBDIRS := build class mobile_SUBDIRS := build class -mobile_static_SUBDIRS := build class +mobile_static_SUBDIRS := build class ilasm binary_reference_assemblies_SUBDIRS := build class net_4_x_SUBDIRS := build mcs class nunit24 ilasm tools tests errors docs xammac_net_4_5_SUBDIRS := build class diff --git a/mcs/build/README.makefiles b/mcs/build/README.makefiles index 1e1ace7d7b..f5b95a5a32 100644 --- a/mcs/build/README.makefiles +++ b/mcs/build/README.makefiles @@ -15,8 +15,6 @@ build system needs to let us do, specifically: - - ** Makefile structure A general makefile looks like this: @@ -438,7 +436,15 @@ To give it flags, set $(LOCAL_CFLAGS). As with compiling C#, the variable $(CFLAGS) will automatically be included on the command line. +* Compiling resources with resgen +If you have a resource that should be compiled with resgen and +included in your assembly, you can use the RESOURCES_DEFS variable. +This variable can contain lists of pairs that are separated by comma +to represent the resource ID as embedded in the assembly followed by +the file name, like this: + +RESOURCE_DEFS = Messages,TextResources.resx Errors,ErrorList.txt * Documentation-related needs? Use $(MDOC) diff --git a/mcs/build/common/AssemblyRef.cs b/mcs/build/common/AssemblyRef.cs index a38d371845..0a4673203d 100644 --- a/mcs/build/common/AssemblyRef.cs +++ b/mcs/build/common/AssemblyRef.cs @@ -5,7 +5,7 @@ static class AssemblyRef internal const string System = "System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"; public const string EcmaPublicKey = "b77a5c561934e089"; -#if NET_2_1 +#if MOBILE public const string FrameworkPublicKeyFull = "0024000004800000940000000602000000240000525341310004000001000100B5FC90E7027F67871E773A8FDE8938C81DD402BA65B9201D60593E96C492651E889CC13F1415EBB53FAC1131AE0BD333C5EE6021672D9718EA31A8AEBD0DA0072F25D87DBA6FC90FFD598ED4DA35E44C398C454307E8E33B8426143DAEC9F596836F97C8F74750E5975C64E2189F45DEF46B2A2B1247ADC3652BF5C308055DA9"; public const string FrameworkPublicKeyFull2 = "00240000048000009400000006020000002400005253413100040000010001008D56C76F9E8649383049F383C44BE0EC204181822A6C31CF5EB7EF486944D032188EA1D3920763712CCB12D75FB77E9811149E6148E5D32FBAAB37611C1878DDC19E20EF135D0CB2CFF2BFEC3D115810C3D9069638FE4BE215DBF795861920E5AB6F7DB2E2CEEF136AC23D5DD2BF031700AEC232F6C6B1C785B4305C123B37AB"; #else diff --git a/mcs/build/common/Consts.cs b/mcs/build/common/Consts.cs index 6d3ff6159d..9cc21da907 100644 --- a/mcs/build/common/Consts.cs +++ b/mcs/build/common/Consts.cs @@ -34,12 +34,12 @@ static class Consts // Use these assembly version constants to make code more maintainable. // - public const string MonoVersion = "4.6.2.0"; + public const string MonoVersion = "4.8.0.0"; public const string MonoCompany = "Mono development team"; public const string MonoProduct = "Mono Common Language Infrastructure"; public const string MonoCopyright = "(c) Various Mono authors"; -#if NET_2_1 +#if MOBILE // Versions of .NET Framework for Silverlight 4.0 public const string FxVersion = "2.0.5.0"; public const string VsVersion = "9.0.0.0"; // unused, but needed for compilation @@ -118,7 +118,7 @@ static class Consts public const string AssemblyPresentationCore_4_0 = "PresentationCore, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"; public const string AssemblyPresentationFramework_3_5 = "PresentationFramework, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"; public const string AssemblySystemServiceModel_3_0 = "System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"; -#elif NET_2_1 +#elif MOBILE public const string AssemblySystem_Core = "System.Core, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=b77a5c561934e089"; #endif } diff --git a/mcs/build/common/Consts.cs.in b/mcs/build/common/Consts.cs.in index 7351be92b4..87b005e763 100644 --- a/mcs/build/common/Consts.cs.in +++ b/mcs/build/common/Consts.cs.in @@ -39,7 +39,7 @@ static class Consts public const string MonoProduct = "Mono Common Language Infrastructure"; public const string MonoCopyright = "(c) Various Mono authors"; -#if NET_2_1 +#if MOBILE // Versions of .NET Framework for Silverlight 4.0 public const string FxVersion = "2.0.5.0"; public const string VsVersion = "9.0.0.0"; // unused, but needed for compilation @@ -118,7 +118,7 @@ static class Consts public const string AssemblyPresentationCore_4_0 = "PresentationCore, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"; public const string AssemblyPresentationFramework_3_5 = "PresentationFramework, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"; public const string AssemblySystemServiceModel_3_0 = "System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"; -#elif NET_2_1 +#elif MOBILE public const string AssemblySystem_Core = "System.Core, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=b77a5c561934e089"; #endif } diff --git a/mcs/build/executable.make b/mcs/build/executable.make index d4b57e0c77..8acb0f5df6 100644 --- a/mcs/build/executable.make +++ b/mcs/build/executable.make @@ -42,7 +42,9 @@ executable_CLEAN_FILES += $(build_lib) $(build_lib).so $(build_lib).mdb $(build_ makefrag = $(depsdir)/$(PROFILE)_$(base_prog).makefrag +ifndef NO_BUILD all-local: $(the_lib) $(PROGRAM_config) +endif install-local: all-local test-local: all-local @@ -173,6 +175,7 @@ csproj-local: echo $(build_lib); \ echo $(FRAMEWORK_VERSION); \ echo $(PROFILE); \ + echo $(RESOURCE_DEFS); \ echo $(response)) > $(topdir)/../msvc/scripts/inputs/$$config_file diff --git a/mcs/build/library.make b/mcs/build/library.make index c8379b22f6..e0c16f48e9 100644 --- a/mcs/build/library.make +++ b/mcs/build/library.make @@ -145,6 +145,7 @@ csproj-library: echo $(build_lib); \ echo $(FRAMEWORK_VERSION); \ echo $(PROFILE); \ + echo $(RESOURCE_DEFS); \ echo $(response)) > $(topdir)/../msvc/scripts/inputs/$$config_file csproj-test: @@ -216,7 +217,28 @@ clean-local: test-local run-test-local run-test-ondotnet-local: @: -DISTFILES = $(wildcard *$(LIBRARY)*.sources) $(EXTRA_DISTFILES) +# +# RESOURCES_DEFS is a list of ID,FILE pairs separated by spaces +# for each of those, generate a rule that produces ID.resource from +# FILE using the resgen tool, adds the generated file to CLENA_FILES and +# passes the resource to the compiler +# +ccomma = , +define RESOURCE_template +$(1).resources: $(2) + $(RESGEN) "$$<" "$$@" + +GEN_RESOURCE_DEPS += $(1).resources +GEN_RESOURCE_FLAGS += -resource:$(1).resources +CLEAN_FILES += $(1).resources +DIST_LISTED_RESOURCES += $(2) +endef + +ifdef RESOURCE_DEFS +$(foreach pair,$(RESOURCE_DEFS), $(eval $(call RESOURCE_template,$(word 1, $(subst $(ccomma), ,$(pair))), $(word 2, $(subst $(ccomma), ,$(pair)))))) +endif + +DISTFILES = $(wildcard *$(LIBRARY)*.sources) $(EXTRA_DISTFILES) $(DIST_LISTED_RESOURCES) ASSEMBLY = $(LIBRARY) ASSEMBLY_EXT = .dll @@ -236,6 +258,7 @@ csproj-test: echo $(test_lib); \ echo $(FRAMEWORK_VERSION); \ echo $(PROFILE); \ + echo ""; \ echo $(test_response)) > $(topdir)/../msvc/scripts/inputs/$$config_file endif @@ -275,12 +298,12 @@ endif $(the_lib): $(the_libdir)/.stamp -$(build_lib): $(response) $(sn) $(BUILT_SOURCES) $(build_libdir:=/.stamp) - $(LIBRARY_COMPILE) $(LIBRARY_FLAGS) $(LIB_MCS_FLAGS) -target:library -out:$@ $(BUILT_SOURCES_cmdline) @$(response) - $(Q) $(SN) -R $@ $(LIBRARY_SNK) +$(build_lib): $(response) $(sn) $(BUILT_SOURCES) $(build_libdir:=/.stamp) $(GEN_RESOURCE_DEPS) + $(LIBRARY_COMPILE) $(LIBRARY_FLAGS) $(LIB_MCS_FLAGS) $(GEN_RESOURCE_FLAGS) -target:library -out:$@ $(BUILT_SOURCES_cmdline) @$(response) ifdef RESOURCE_STRINGS_FILES $(Q) $(STRING_REPLACER) $(RESOURCE_STRINGS_FILES) $@ endif + $(Q) $(SN) -R $@ $(LIBRARY_SNK) ifdef LIBRARY_USE_INTERMEDIATE_FILE $(the_lib): $(build_lib) diff --git a/mcs/build/platforms/darwin.make b/mcs/build/platforms/darwin.make index bfc7341339..4b7b279f0c 100644 --- a/mcs/build/platforms/darwin.make +++ b/mcs/build/platforms/darwin.make @@ -23,8 +23,6 @@ PLATFORM_PATH_SEPARATOR = : # This is for changing / to \ on windows PLATFORM_CHANGE_SEPARATOR_CMD = cat -PLATFORM_AOT_SUFFIX = .dylib - hidden_prefix = . hidden_suffix = diff --git a/mcs/build/platforms/linux.make b/mcs/build/platforms/linux.make index fd54351c47..0050414079 100644 --- a/mcs/build/platforms/linux.make +++ b/mcs/build/platforms/linux.make @@ -23,8 +23,6 @@ PLATFORM_PATH_SEPARATOR = : # This is for changing / to \ on windows PLATFORM_CHANGE_SEPARATOR_CMD = cat -PLATFORM_AOT_SUFFIX = .so - hidden_prefix = . hidden_suffix = diff --git a/mcs/build/platforms/win32.make b/mcs/build/platforms/win32.make index d5df46e9da..bed99f5338 100644 --- a/mcs/build/platforms/win32.make +++ b/mcs/build/platforms/win32.make @@ -26,9 +26,6 @@ PLATFORM_PATH_SEPARATOR = ; override CURDIR:=$(shell cygpath -m $(CURDIR)) -## not so simple :-) -#PLATFORM_AOT_SUFFIX = .dll - hidden_prefix = hidden_suffix = .tmp diff --git a/mcs/build/rules.make b/mcs/build/rules.make index 75bd38cbc2..ac3a476dfb 100644 --- a/mcs/build/rules.make +++ b/mcs/build/rules.make @@ -132,29 +132,6 @@ endif # Make sure propagates export TEST_HARNESS -# start aot config - -# We set the prefix of the aot build flags -# in the profile. This determines the aot type, -# whether it be llvmonly or full. To this we append the -# options which do not change between them, the INVARIANT_AOT_OPTIONS -ifndef AOT_BUILD_FLAGS_PREFIX -AOT_BUILD_FLAGS_PREFIX = --aot= -endif - -# Set the options for building and running AOT -# The trampoline numbers are provisional, they are what is required -# to run the corlib test suite. They should be considered a lower bound. -INVARIANT_AOT_OPTIONS=nimt-trampolines=900,ntrampolines=8000 - -ifndef MONO_DISABLE_GSHAREDVT -INVARIANT_AOT_OPTIONS:=$(INVARIANT_AOT_OPTIONS),ngsharedvt-trampolines=900 -endif - -AOT_BUILD_FLAGS = $(AOT_BUILD_FLAGS_PREFIX)$(INVARIANT_AOT_OPTIONS) - -# end AOT config - ifdef BCL_OPTIMIZE PROFILE_MCS_FLAGS += -optimize endif @@ -202,17 +179,33 @@ STD_TARGETS = test run-test run-test-ondotnet clean install uninstall doc-update $(STD_TARGETS): %: do-% ifdef PLATFORM_AOT_SUFFIX -Q_AOT=$(if $(V),,@echo "AOT [$(PROFILE)] AOT All Assemblies";) -LIST_ALL_PROFILE_ASSEMBLIES = find . | grep -E '(dll|exe)$$' | grep -v -E 'bare|plaincore|secxml|Facades' -COMPILE_ALL_PROFILE_ASSEMBLIES = $(LIST_ALL_PROFILE_ASSEMBLIES) | MONO_PATH="./" xargs -I '{}' $(RUNTIME) $(RUNTIME_FLAGS) $(AOT_BUILD_FLAGS) '{}' +AOT_PROFILE_ASSEMBLIES = $(shell cd $(topdir)/class/lib/$(PROFILE)/ && find . | grep -E '(dll|exe)$$' | grep -v -E 'bare|plaincore|secxml|Facades' | sed 's:\./::g' | tr '\n' ' ') do-all-aot: $(MAKE) do-all TOP_LEVEL_DO=do-all $(MAKE) aot-all-profile -aot-all-profile: - $(Q_AOT) cd $(topdir)/class/lib/$(PROFILE)/ && $(COMPILE_ALL_PROFILE_ASSEMBLIES) &> $(PROFILE)-aot.log -endif +# When we recursively call $(MAKE) aot-all-profile +# we will have created this directory, and so will +# be able to evaluate the .dylibs to make +ifneq ("$(wildcard $(topdir)/class/lib/$(PROFILE))","") + +AOT_PROFILE_ASSEMBLIES_CMD = cd $(topdir)/class/lib/$(PROFILE)/ && find . | grep -E '(dll|exe)$$' | grep -v -E 'bare|plaincore|secxml|Facades|ilasm' | sed 's:\./::g' | tr '\n' ' ' +AOT_PROFILE_ASSEMBLIES_CMD_SAFE = $(AOT_PROFILE_ASSEMBLIES_CMD) || true +AOT_PROFILE_ASSEMBLIES = $(shell $(AOT_PROFILE_ASSEMBLIES_CMD_SAFE)) + +# This can run in parallel +.PHONY: aot-all-profile +aot-all-profile: $(patsubst %,$(topdir)/class/lib/$(PROFILE)/%$(PLATFORM_AOT_SUFFIX),$(AOT_PROFILE_ASSEMBLIES)) + +$(topdir)/class/lib/$(PROFILE)/%$(PLATFORM_AOT_SUFFIX): $(topdir)/class/lib/$(PROFILE)/% + @ mkdir -p $(topdir)/class/lib/$(PROFILE)/$*_bitcode_tmp + @echo "AOT [$(PROFILE)] AOT $* " && cd $(topdir)/class/lib/$(PROFILE)/ && MONO_PATH="." $(RUNTIME) $(RUNTIME_FLAGS) $(AOT_BUILD_FLAGS),temp-path=$*_bitcode_tmp $* >> $(PROFILE)-aot.log + @ rm -rf $(topdir)/class/lib/$(PROFILE)/$*_bitcode_tmp + +endif #ifneq ("$(wildcard $(topdir)/class/lib/$(PROFILE))","") + +endif # PLATFORM_AOT_SUFFIX do-run-test: ok=:; $(MAKE) run-test-recursive || ok=false; $(MAKE) run-test-local || ok=false; $$ok diff --git a/mcs/build/tests.make b/mcs/build/tests.make index 16d3a64b65..749b5a0faf 100644 --- a/mcs/build/tests.make +++ b/mcs/build/tests.make @@ -123,12 +123,20 @@ TEST_HARNESS_POSTPROC_ONDOTNET = (echo ''; cat TestResult-ondotnet-$(PROFILE).lo endif ifdef FIXTURE +ifdef NUNIT_LITE +FIXTURE_ARG = -test=MonoTests.$(FIXTURE) +else FIXTURE_ARG = -fixture=MonoTests.$(FIXTURE) endif +endif ifdef TESTNAME +ifdef NUNIT_LITE +TESTNAME_ARG = -test=MonoTests.$(TESTNAME) +else TESTNAME_ARG = -run=MonoTests.$(TESTNAME) endif +endif ifdef ALWAYS_AOT test-local-aot-compile: $(topdir)/build/deps/nunit-$(PROFILE).stamp diff --git a/mcs/class/Facades/Microsoft.Win32.Registry.AccessControl/Makefile b/mcs/class/Facades/Microsoft.Win32.Registry.AccessControl/Makefile index 0b5f4acf6d..4197137c95 100644 --- a/mcs/class/Facades/Microsoft.Win32.Registry.AccessControl/Makefile +++ b/mcs/class/Facades/Microsoft.Win32.Registry.AccessControl/Makefile @@ -14,8 +14,6 @@ SIGN_FLAGS = /delaysign /keyfile:$(KEY_FILE) /nowarn:1616,1699 LIB_REFS = System LIB_MCS_FLAGS = $(SIGN_FLAGS) -PLATFORM_DEBUG_FLAGS = - NO_TEST = yes include $(MCS_BUILD_DIR)/library.make diff --git a/mcs/class/Facades/System.Data.Common/Makefile b/mcs/class/Facades/System.Data.Common/Makefile index ff6d035678..fe63a8e0f7 100644 --- a/mcs/class/Facades/System.Data.Common/Makefile +++ b/mcs/class/Facades/System.Data.Common/Makefile @@ -14,8 +14,6 @@ SIGN_FLAGS = /delaysign /keyfile:$(KEY_FILE) /nowarn:1616,1699 LIB_REFS = System System.Data System.Xml LIB_MCS_FLAGS = $(SIGN_FLAGS) -PLATFORM_DEBUG_FLAGS = - NO_TEST = yes include $(MCS_BUILD_DIR)/library.make diff --git a/mcs/class/Facades/System.Diagnostics.StackTrace/Makefile b/mcs/class/Facades/System.Diagnostics.StackTrace/Makefile index 25d8ac37ed..4cc9d7f1a3 100644 --- a/mcs/class/Facades/System.Diagnostics.StackTrace/Makefile +++ b/mcs/class/Facades/System.Diagnostics.StackTrace/Makefile @@ -14,8 +14,6 @@ SIGN_FLAGS = /delaysign /keyfile:$(KEY_FILE) /nowarn:1616,1699 LIB_REFS = System LIB_MCS_FLAGS = $(SIGN_FLAGS) -PLATFORM_DEBUG_FLAGS = - NO_TEST = yes include $(MCS_BUILD_DIR)/library.make diff --git a/mcs/class/Facades/System.Diagnostics.Tracing/Makefile b/mcs/class/Facades/System.Diagnostics.Tracing/Makefile index 14b380da86..d74812c5e9 100644 --- a/mcs/class/Facades/System.Diagnostics.Tracing/Makefile +++ b/mcs/class/Facades/System.Diagnostics.Tracing/Makefile @@ -13,8 +13,6 @@ KEY_FILE = ../../msfinal.pub SIGN_FLAGS = /delaysign /keyfile:$(KEY_FILE) /nowarn:1616,1699 LIB_MCS_FLAGS = $(SIGN_FLAGS) -PLATFORM_DEBUG_FLAGS = - NO_TEST = yes include $(MCS_BUILD_DIR)/library.make diff --git a/mcs/class/Facades/System.Diagnostics.Tracing/System.Diagnostics.Tracing.dll.sources b/mcs/class/Facades/System.Diagnostics.Tracing/System.Diagnostics.Tracing.dll.sources index 99a7bf6943..719628dc7c 100644 --- a/mcs/class/Facades/System.Diagnostics.Tracing/System.Diagnostics.Tracing.dll.sources +++ b/mcs/class/Facades/System.Diagnostics.Tracing/System.Diagnostics.Tracing.dll.sources @@ -1,3 +1,2 @@ TypeForwarders.cs AssemblyInfo.cs -EventCounter.cs diff --git a/mcs/class/Facades/System.Diagnostics.Tracing/TypeForwarders.cs b/mcs/class/Facades/System.Diagnostics.Tracing/TypeForwarders.cs index 5c8ab29d77..2e4028199f 100644 --- a/mcs/class/Facades/System.Diagnostics.Tracing/TypeForwarders.cs +++ b/mcs/class/Facades/System.Diagnostics.Tracing/TypeForwarders.cs @@ -44,3 +44,7 @@ [assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Diagnostics.Tracing.EventTask))] [assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Diagnostics.Tracing.EventWrittenEventArgs))] [assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Diagnostics.Tracing.NonEventAttribute))] + +#if NETSTANDARD +[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Diagnostics.Tracing.EventCounter))] +#endif diff --git a/mcs/class/Facades/System.Globalization.Extensions/Makefile b/mcs/class/Facades/System.Globalization.Extensions/Makefile index d3a57fa307..446a412760 100644 --- a/mcs/class/Facades/System.Globalization.Extensions/Makefile +++ b/mcs/class/Facades/System.Globalization.Extensions/Makefile @@ -14,8 +14,6 @@ SIGN_FLAGS = /delaysign /keyfile:$(KEY_FILE) /nowarn:1616,1699 LIB_REFS = System LIB_MCS_FLAGS = $(SIGN_FLAGS) -PLATFORM_DEBUG_FLAGS = - NO_TEST = yes include $(MCS_BUILD_DIR)/library.make diff --git a/mcs/class/Facades/System.IO.FileSystem.AccessControl/Makefile b/mcs/class/Facades/System.IO.FileSystem.AccessControl/Makefile index 0198747a8a..9efb35542b 100644 --- a/mcs/class/Facades/System.IO.FileSystem.AccessControl/Makefile +++ b/mcs/class/Facades/System.IO.FileSystem.AccessControl/Makefile @@ -14,8 +14,6 @@ SIGN_FLAGS = /delaysign /keyfile:$(KEY_FILE) /nowarn:1616,1699 LIB_REFS = System LIB_MCS_FLAGS = $(SIGN_FLAGS) -PLATFORM_DEBUG_FLAGS = - NO_TEST = yes include $(MCS_BUILD_DIR)/library.make diff --git a/mcs/class/Facades/System.Net.Sockets/Makefile b/mcs/class/Facades/System.Net.Sockets/Makefile index bf60d5fef6..497c054622 100644 --- a/mcs/class/Facades/System.Net.Sockets/Makefile +++ b/mcs/class/Facades/System.Net.Sockets/Makefile @@ -14,8 +14,6 @@ SIGN_FLAGS = /delaysign /keyfile:$(KEY_FILE) /nowarn:1616,1699 LIB_REFS = System LIB_MCS_FLAGS = $(SIGN_FLAGS) -PLATFORM_DEBUG_FLAGS = - NO_TEST = yes include $(MCS_BUILD_DIR)/library.make diff --git a/mcs/class/Facades/System.Net.Sockets/System.Net.Sockets.dll.sources b/mcs/class/Facades/System.Net.Sockets/System.Net.Sockets.dll.sources index a4cab35a66..719628dc7c 100644 --- a/mcs/class/Facades/System.Net.Sockets/System.Net.Sockets.dll.sources +++ b/mcs/class/Facades/System.Net.Sockets/System.Net.Sockets.dll.sources @@ -1,5 +1,2 @@ TypeForwarders.cs AssemblyInfo.cs -SocketReceiveFromResult.cs -SocketReceiveMessageFromResult.cs -SocketTaskExtensions.cs diff --git a/mcs/class/Facades/System.Net.Sockets/TypeForwarders.cs b/mcs/class/Facades/System.Net.Sockets/TypeForwarders.cs index b27fc8622e..27258a0831 100644 --- a/mcs/class/Facades/System.Net.Sockets/TypeForwarders.cs +++ b/mcs/class/Facades/System.Net.Sockets/TypeForwarders.cs @@ -46,4 +46,8 @@ [assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Net.Sockets.UdpClient))] [assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Net.Sockets.UdpReceiveResult))] - +#if NETSTANDARD +[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Net.Sockets.SocketReceiveFromResult))] +[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Net.Sockets.SocketReceiveMessageFromResult))] +[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Net.Sockets.SocketTaskExtensions))] +#endif diff --git a/mcs/class/Facades/System.Reflection.Emit.Lightweight/DynamicMethod.cs b/mcs/class/Facades/System.Reflection.Emit.Lightweight/DynamicMethod.cs new file mode 100644 index 0000000000..25fa02f161 --- /dev/null +++ b/mcs/class/Facades/System.Reflection.Emit.Lightweight/DynamicMethod.cs @@ -0,0 +1,136 @@ +// +// DynamicMethod.cs +// +// Authors: +// Marek Safar (marek.safar@gmail.com) +// +// Copyright (C) 2016 Xamarin Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +#if FULL_AOT_RUNTIME + +namespace System.Reflection.Emit +{ + public abstract class DynamicMethod : MethodInfo, ICustomAttributeProvider + { + public DynamicMethod (string name, Type returnType, Type[] parameterTypes) + { + throw new PlatformNotSupportedException (); + } + + public DynamicMethod (string name, Type returnType, Type[] parameterTypes, bool restrictedSkipVisibility) + { + throw new PlatformNotSupportedException (); + } + + public DynamicMethod (string name, Type returnType, Type[] parameterTypes, Module m) + { + throw new PlatformNotSupportedException (); + } + + public DynamicMethod (string name, Type returnType, Type[] parameterTypes, Type owner) + { + throw new PlatformNotSupportedException (); + } + + public DynamicMethod (string name, Type returnType, Type[] parameterTypes, Module m, bool skipVisibility) + { + throw new PlatformNotSupportedException (); + } + + public DynamicMethod (string name, Type returnType, Type[] parameterTypes, Type owner, bool skipVisibility) + { + throw new PlatformNotSupportedException (); + } + + public DynamicMethod (string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, Module m, bool skipVisibility) + { + throw new PlatformNotSupportedException (); + } + + public DynamicMethod (string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, Type owner, bool skipVisibility) + { + throw new PlatformNotSupportedException (); + } + + public override MethodAttributes Attributes { + get { + throw new PlatformNotSupportedException (); + } + } + + public override CallingConventions CallingConvention { + get { + throw new PlatformNotSupportedException (); + } + } + + public override Type DeclaringType { + get { + throw new PlatformNotSupportedException (); + } + } + + public bool InitLocals { get; set; } + + public override MethodImplAttributes MethodImplementationFlags { + get { + throw new PlatformNotSupportedException (); + } + } + + public override string Name { + get { + throw new PlatformNotSupportedException (); + } + } + + public override ParameterInfo ReturnParameter { + get { + throw new PlatformNotSupportedException (); + } + } + + public override Type ReturnType { + get { + throw new PlatformNotSupportedException (); + } + } + + public ILGenerator GetILGenerator () + { + throw new PlatformNotSupportedException (); + } + + public ILGenerator GetILGenerator (int streamSize) + { + throw new PlatformNotSupportedException (); + } + + public override ParameterInfo[] GetParameters () + { + throw new PlatformNotSupportedException (); + } + } +} + +#endif \ No newline at end of file diff --git a/mcs/class/Facades/System.Reflection.Emit.Lightweight/System.Reflection.Emit.Lightweight.dll.sources b/mcs/class/Facades/System.Reflection.Emit.Lightweight/System.Reflection.Emit.Lightweight.dll.sources index 8e33d4ddea..5d40b81fbf 100644 --- a/mcs/class/Facades/System.Reflection.Emit.Lightweight/System.Reflection.Emit.Lightweight.dll.sources +++ b/mcs/class/Facades/System.Reflection.Emit.Lightweight/System.Reflection.Emit.Lightweight.dll.sources @@ -1,3 +1,3 @@ TypeForwarders.cs AssemblyInfo.cs - +DynamicMethod.cs diff --git a/mcs/class/Facades/System.Reflection.Emit.Lightweight/TypeForwarders.cs b/mcs/class/Facades/System.Reflection.Emit.Lightweight/TypeForwarders.cs index 7cd359e90a..9fca03abaf 100644 --- a/mcs/class/Facades/System.Reflection.Emit.Lightweight/TypeForwarders.cs +++ b/mcs/class/Facades/System.Reflection.Emit.Lightweight/TypeForwarders.cs @@ -20,5 +20,6 @@ // THE SOFTWARE. // +#if !FULL_AOT_RUNTIME [assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Reflection.Emit.DynamicMethod))] - +#endif diff --git a/mcs/class/Facades/System.Reflection.TypeExtensions/Makefile b/mcs/class/Facades/System.Reflection.TypeExtensions/Makefile index b2bb49ecfd..374132468e 100644 --- a/mcs/class/Facades/System.Reflection.TypeExtensions/Makefile +++ b/mcs/class/Facades/System.Reflection.TypeExtensions/Makefile @@ -14,8 +14,6 @@ SIGN_FLAGS = /delaysign /keyfile:$(KEY_FILE) /nowarn:1616,1699 LIB_REFS = System LIB_MCS_FLAGS = $(SIGN_FLAGS) -PLATFORM_DEBUG_FLAGS = - NO_TEST = yes include $(MCS_BUILD_DIR)/library.make diff --git a/mcs/class/Facades/System.Runtime.Serialization.Primitives/Makefile b/mcs/class/Facades/System.Runtime.Serialization.Primitives/Makefile index 3a2519549f..22a0d90aae 100644 --- a/mcs/class/Facades/System.Runtime.Serialization.Primitives/Makefile +++ b/mcs/class/Facades/System.Runtime.Serialization.Primitives/Makefile @@ -14,8 +14,6 @@ SIGN_FLAGS = /delaysign /keyfile:$(KEY_FILE) /nowarn:1616,1699 LIB_REFS = System.Runtime.Serialization LIB_MCS_FLAGS = $(SIGN_FLAGS) -PLATFORM_DEBUG_FLAGS = - NO_TEST = yes include $(MCS_BUILD_DIR)/library.make diff --git a/mcs/class/Facades/System.Runtime.Serialization.Xml/Makefile b/mcs/class/Facades/System.Runtime.Serialization.Xml/Makefile index dc0a84d022..1314e94f39 100644 --- a/mcs/class/Facades/System.Runtime.Serialization.Xml/Makefile +++ b/mcs/class/Facades/System.Runtime.Serialization.Xml/Makefile @@ -18,8 +18,6 @@ ifeq (2.1, $(FRAMEWORK_VERSION)) LIB_MCS_FLAGS += /d:NO_CODEDOM endif -PLATFORM_DEBUG_FLAGS = - NO_TEST = yes include $(MCS_BUILD_DIR)/library.make diff --git a/mcs/class/Facades/System.Security.SecureString/Makefile b/mcs/class/Facades/System.Security.SecureString/Makefile index b33d20dc20..0569f62197 100644 --- a/mcs/class/Facades/System.Security.SecureString/Makefile +++ b/mcs/class/Facades/System.Security.SecureString/Makefile @@ -14,8 +14,6 @@ SIGN_FLAGS = /delaysign /keyfile:$(KEY_FILE) /nowarn:1616,1699 LIB_REFS = System LIB_MCS_FLAGS = $(SIGN_FLAGS) -PLATFORM_DEBUG_FLAGS = - NO_TEST = yes include $(MCS_BUILD_DIR)/library.make diff --git a/mcs/class/Facades/System.ServiceProcess.ServiceController/Makefile b/mcs/class/Facades/System.ServiceProcess.ServiceController/Makefile index 5fa4c609b0..fe6edb861f 100644 --- a/mcs/class/Facades/System.ServiceProcess.ServiceController/Makefile +++ b/mcs/class/Facades/System.ServiceProcess.ServiceController/Makefile @@ -21,8 +21,6 @@ endif LIB_MCS_FLAGS = $(SIGN_FLAGS) -PLATFORM_DEBUG_FLAGS = - NO_TEST = yes include $(MCS_BUILD_DIR)/library.make diff --git a/mcs/class/Facades/System.Text.Encoding.CodePages/CodePagesEncodingProvider.cs b/mcs/class/Facades/System.Text.Encoding.CodePages/CodePagesEncodingProvider.cs index 11214d2825..0933eeef41 100644 --- a/mcs/class/Facades/System.Text.Encoding.CodePages/CodePagesEncodingProvider.cs +++ b/mcs/class/Facades/System.Text.Encoding.CodePages/CodePagesEncodingProvider.cs @@ -22,15 +22,15 @@ namespace System.Text { - public sealed partial class CodePagesEncodingProvider : EncodingProvider + public sealed class CodePagesEncodingProvider : EncodingProvider { - static CodePagesEncodingProvider instance = new CodePagesEncodingProvider (); + static readonly CodePagesEncodingProvider instance = new CodePagesEncodingProvider (); private CodePagesEncodingProvider () { } - public static System.Text.EncodingProvider Instance { + public static EncodingProvider Instance { get { return instance; } diff --git a/mcs/class/Facades/System.Text.Encoding.CodePages/Makefile b/mcs/class/Facades/System.Text.Encoding.CodePages/Makefile index 7430a65175..3c678ee54f 100644 --- a/mcs/class/Facades/System.Text.Encoding.CodePages/Makefile +++ b/mcs/class/Facades/System.Text.Encoding.CodePages/Makefile @@ -14,8 +14,6 @@ SIGN_FLAGS = /delaysign /keyfile:$(KEY_FILE) /nowarn:1616,1699 LIB_REFS = System LIB_MCS_FLAGS = $(SIGN_FLAGS) -PLATFORM_DEBUG_FLAGS = - NO_TEST = yes include $(MCS_BUILD_DIR)/library.make diff --git a/mcs/class/Facades/System.Threading.AccessControl/Makefile b/mcs/class/Facades/System.Threading.AccessControl/Makefile index b0c9264a03..a5de66c999 100644 --- a/mcs/class/Facades/System.Threading.AccessControl/Makefile +++ b/mcs/class/Facades/System.Threading.AccessControl/Makefile @@ -14,8 +14,6 @@ SIGN_FLAGS = /delaysign /keyfile:$(KEY_FILE) /nowarn:1616,1699 LIB_REFS = System LIB_MCS_FLAGS = $(SIGN_FLAGS) -PLATFORM_DEBUG_FLAGS = - NO_TEST = yes include $(MCS_BUILD_DIR)/library.make diff --git a/mcs/class/Facades/System.Threading.Overlapped/Makefile b/mcs/class/Facades/System.Threading.Overlapped/Makefile index 061c46b236..a36686196b 100644 --- a/mcs/class/Facades/System.Threading.Overlapped/Makefile +++ b/mcs/class/Facades/System.Threading.Overlapped/Makefile @@ -14,8 +14,6 @@ SIGN_FLAGS = /delaysign /keyfile:$(KEY_FILE) /nowarn:1616,1699 LIB_REFS = System LIB_MCS_FLAGS = $(SIGN_FLAGS) -unsafe -PLATFORM_DEBUG_FLAGS = - NO_TEST = yes include $(MCS_BUILD_DIR)/library.make diff --git a/mcs/class/Facades/System.Xml.XPath.XDocument/Makefile b/mcs/class/Facades/System.Xml.XPath.XDocument/Makefile index 16a26f2c55..36a3de971b 100644 --- a/mcs/class/Facades/System.Xml.XPath.XDocument/Makefile +++ b/mcs/class/Facades/System.Xml.XPath.XDocument/Makefile @@ -14,8 +14,6 @@ SIGN_FLAGS = /delaysign /keyfile:$(KEY_FILE) /nowarn:1616,1699 LIB_REFS = System System.Xml System.Xml.Linq LIB_MCS_FLAGS = $(SIGN_FLAGS) -PLATFORM_DEBUG_FLAGS = - NO_TEST = yes include $(MCS_BUILD_DIR)/library.make diff --git a/mcs/class/Facades/subdirs.make b/mcs/class/Facades/subdirs.make index c980d70840..7c6c5d092f 100644 --- a/mcs/class/Facades/subdirs.make +++ b/mcs/class/Facades/subdirs.make @@ -24,7 +24,7 @@ System.Security.Cryptography.Encryption.Aes System.Security.Cryptography.Encrypt System.Security.Cryptography.Hashing.Algorithms System.Security.Cryptography.RSA System.Security.Cryptography.RandomNumberGenerator \ System.Security.Principal.Windows System.Threading.Thread System.Threading.ThreadPool \ System.Xml.XPath System.Xml.XmlDocument System.Xml.Xsl.Primitives Microsoft.Win32.Registry.AccessControl System.Diagnostics.StackTrace System.Globalization.Extensions \ -System.IO.FileSystem.AccessControl System.Reflection.TypeExtensions \ +System.IO.FileSystem.AccessControl System.Reflection.TypeExtensions System.Reflection.Emit.Lightweight System.Reflection.Emit.ILGeneration System.Reflection.Emit \ System.Security.SecureString System.Threading.AccessControl System.Threading.Overlapped System.Xml.XPath.XDocument \ System.Security.Cryptography.Primitives System.Text.Encoding.CodePages System.IO.FileSystem.Watcher \ System.Security.Cryptography.ProtectedData System.ServiceProcess.ServiceController System.IO.Pipes @@ -34,8 +34,6 @@ common_DEPS_SUBDIRS = System.Security.Cryptography.X509Certificates System.Servi drawing_DEPS_SUBDIRS = System.Drawing.Primitives -reflection_PARALLEL_SUBDIRS = System.Reflection.Emit.ILGeneration System.Reflection.Emit.Lightweight System.Reflection.Emit - monotouch_SUBDIRS = $(common_DEPS_SUBDIRS) $(mobile_only_DEPS_SUBDIRS) monotouch_PARALLEL_SUBDIRS = $(common_SUBDIRS) $(mobile_only_SUBDIRS) @@ -43,10 +41,10 @@ mobile_static_SUBDIRS = $(monotouch_SUBDIRS) mobile_static_PARALLEL_SUBDIRS = $(monotouch_PARALLEL_SUBDIRS) net_4_x_SUBDIRS = $(common_DEPS_SUBDIRS) $(drawing_DEPS_SUBDIRS) -net_4_x_PARALLEL_SUBDIRS = $(common_SUBDIRS) $(reflection_PARALLEL_SUBDIRS) +net_4_x_PARALLEL_SUBDIRS = $(common_SUBDIRS) monodroid_SUBDIRS = $(monotouch_SUBDIRS) -monodroid_PARALLEL_SUBDIRS = $(monotouch_PARALLEL_SUBDIRS) $(reflection_PARALLEL_SUBDIRS) +monodroid_PARALLEL_SUBDIRS = $(monotouch_PARALLEL_SUBDIRS) xammac_SUBDIRS = $(monotouch_SUBDIRS) xammac_PARALLEL_SUBDIRS = $(monotouch_PARALLEL_SUBDIRS) diff --git a/mcs/class/Makefile b/mcs/class/Makefile index 9ac4fb9618..b33411143c 100644 --- a/mcs/class/Makefile +++ b/mcs/class/Makefile @@ -27,7 +27,6 @@ mobile_common_dirs := \ System.XML \ I18N \ System.ServiceModel.Internals \ - SMDiagnostics \ System.Runtime.Serialization \ System.Xml.Linq \ System.IdentityModel \ @@ -40,7 +39,6 @@ mobile_common_dirs := \ System.Numerics \ System.Numerics.Vectors \ System.Data \ - Mono.Cairo \ Mono.Data.Sqlite \ System.Data.Services.Client \ System.IO.Compression \ @@ -53,9 +51,6 @@ mobile_common_dirs := \ System.Xml.Serialization \ Mono.CSharp \ Microsoft.CSharp \ - Mono.Security.Providers.DotNet \ - Mono.Security.Providers.NewSystemSource \ - Mono.Security.Providers.NewTls \ System.Runtime.InteropServices.RuntimeInformation \ System.Reflection.DispatchProxy \ System.Xml.XPath.XmlDocument \ @@ -65,6 +60,9 @@ mobile_common_dirs := \ mobile_static_dirs := \ $(mobile_common_dirs) \ Mono.Dynamic.Interpreter \ + PEAPI \ + Mono.CompilerServices.SymbolWriter \ + Mono.Simd \ $(pcl_facade_dirs) mobile_dynamic_dirs := \ @@ -76,12 +74,13 @@ xammac_dirs := \ $(mobile_dynamic_dirs) monodroid_dirs := \ - $(mobile_dynamic_dirs) + $(mobile_dynamic_dirs) \ + Mono.Btls.Interface monotouch_dirs := \ $(mobile_static_dirs) -monotouch_watch_dirs := $(monotouch_dirs) +monotouch_watch_dirs := $(filter-out Mono.Security Mono.Data.Tds,$(monotouch_dirs)) monotouch_tv_dirs := $(monotouch_dirs) monotouch_runtime_dirs := \ @@ -92,7 +91,7 @@ monotouch_runtime_dirs := \ System.XML \ Mono.CSharp -monotouch_watch_runtime_dirs := $(monotouch_runtime_dirs) +monotouch_watch_runtime_dirs := $(filter-out Mono.Security Mono.Data.Tds,$(monotouch_runtime_dirs)) monotouch_tv_runtime_dirs := $(monotouch_runtime_dirs) xammac_4_5_dirs := \ @@ -139,10 +138,6 @@ xammac_4_5_dirs := \ System.Data.Linq \ System.Net.Http \ System.Net.Http.WebRequest \ - Mono.Security.Providers.DotNet \ - Mono.Security.Providers.OldTls \ - Mono.Security.Providers.NewSystemSource \ - Mono.Security.Providers.NewTls \ System.Runtime.InteropServices.RuntimeInformation \ System.Reflection.Context \ System.Net.Http.WinHttpHandler \ @@ -231,8 +226,6 @@ net_4_x_dirs := \ System.Web.Http \ System.Web.Http.SelfHost \ System.Web.Http.WebHost \ - Mono.Security.Providers.NewSystemSource \ - Mono.Security.Providers.NewTls \ System.Runtime.InteropServices.RuntimeInformation # These are the subdirs which depends on libs in net_4_x_dirs @@ -240,6 +233,7 @@ net_4_x_dirs := \ net_4_x_parallel_dirs := \ PEAPI \ I18N \ + Mono.Btls.Interface \ Mono.Http \ Mono.Cairo \ Mono.Cecil \ @@ -276,8 +270,6 @@ net_4_x_parallel_dirs := \ System.ComponentModel.Composition.4.5 \ System.Windows \ System.Xml.Serialization \ - Mono.Security.Providers.DotNet \ - Mono.Security.Providers.OldTls \ System.DirectoryServices.Protocols \ RabbitMQ.Client \ Microsoft.VisualC \ @@ -290,6 +282,7 @@ net_4_x_parallel_dirs := \ System.Workflow.ComponentModel \ System.Workflow.Runtime \ System.Reflection.Context \ + legacy/Mono.Cecil \ $(pcl_facade_dirs) xbuild_2_0_dirs := \ diff --git a/mcs/class/Microsoft.Build.Tasks/Microsoft.Build.Tasks/Vbc.cs b/mcs/class/Microsoft.Build.Tasks/Microsoft.Build.Tasks/Vbc.cs index cf56b148f1..ae6d75bf40 100644 --- a/mcs/class/Microsoft.Build.Tasks/Microsoft.Build.Tasks/Vbc.cs +++ b/mcs/class/Microsoft.Build.Tasks/Microsoft.Build.Tasks/Vbc.cs @@ -153,7 +153,10 @@ namespace Microsoft.Build.Tasks { { if (!string.IsNullOrEmpty (ToolPath)) return Path.Combine (ToolPath, ToolExe); - return ToolLocationHelper.GetPathToDotNetFrameworkFile (ToolExe, TargetDotNetFrameworkVersion.VersionLatest); + var possibleToolPath = ToolLocationHelper.GetPathToDotNetFrameworkFile (ToolExe, TargetDotNetFrameworkVersion.VersionLatest); + if (!string.IsNullOrEmpty(possibleToolPath)) + return possibleToolPath; + return ToolLocationHelper.GetPathToDotNetFrameworkBinFile(ToolExe); } [MonoTODO] diff --git a/mcs/class/Microsoft.Build/Test/Microsoft.Build.Construction/ProjectRootElementTest.cs b/mcs/class/Microsoft.Build/Test/Microsoft.Build.Construction/ProjectRootElementTest.cs index e864f4dfb3..2fbb9f1858 100644 --- a/mcs/class/Microsoft.Build/Test/Microsoft.Build.Construction/ProjectRootElementTest.cs +++ b/mcs/class/Microsoft.Build/Test/Microsoft.Build.Construction/ProjectRootElementTest.cs @@ -58,11 +58,9 @@ namespace MonoTests.Microsoft.Build.Construction ProjectRootElement.Create (XmlReader.Create (new StringReader (" "))); Assert.Fail ("should throw InvalidProjectFileException"); } catch (InvalidProjectFileException ex) { - #if NET_4_5 Assert.AreEqual (1, ex.LineNumber, "#1"); // it is very interesting, but unlike XmlReader.LinePosition it returns the position for '<'. Assert.AreEqual (2, ex.ColumnNumber, "#2"); - #endif } } @@ -102,11 +100,9 @@ namespace MonoTests.Microsoft.Build.Construction ProjectRootElement.Create (xml); Assert.Fail ("should throw InvalidProjectFileException"); } catch (InvalidProjectFileException ex) { - #if NET_4_5 Assert.AreEqual (1, ex.LineNumber, "#1"); // unlike unexpected element case which returned the position for '<', it does return the name start char... Assert.AreEqual (70, ex.ColumnNumber, "#2"); - #endif } } diff --git a/mcs/class/Microsoft.Build/Test/Microsoft.Build.Evaluation/ProjectCollectionTest.cs b/mcs/class/Microsoft.Build/Test/Microsoft.Build.Evaluation/ProjectCollectionTest.cs index 970240fa74..700a41663d 100644 --- a/mcs/class/Microsoft.Build/Test/Microsoft.Build.Evaluation/ProjectCollectionTest.cs +++ b/mcs/class/Microsoft.Build/Test/Microsoft.Build.Evaluation/ProjectCollectionTest.cs @@ -44,9 +44,7 @@ namespace MonoTests.Microsoft.Build.Evaluation { var g = ProjectCollection.GlobalProjectCollection; Assert.AreEqual (0, g.GlobalProperties.Count, "#1"); - #if NET_4_5 Assert.IsTrue (g.GlobalProperties.IsReadOnly, "#2"); - #endif } [Test] diff --git a/mcs/class/Microsoft.Build/Test/Microsoft.Build.Evaluation/ToolsetTest.cs b/mcs/class/Microsoft.Build/Test/Microsoft.Build.Evaluation/ToolsetTest.cs index ac4e2d6610..81392010d7 100644 --- a/mcs/class/Microsoft.Build/Test/Microsoft.Build.Evaluation/ToolsetTest.cs +++ b/mcs/class/Microsoft.Build/Test/Microsoft.Build.Evaluation/ToolsetTest.cs @@ -40,11 +40,9 @@ namespace MonoTests.Microsoft.Build.Evaluation var ts = new Toolset ("4.3", "c:\\", ProjectCollection.GlobalProjectCollection, null); Assert.IsNotNull (ts.Properties, "#1"); Assert.AreEqual (0, ts.Properties.Count, "#2"); -#if NET_4_5 Assert.IsNull (ts.DefaultSubToolsetVersion, "#3"); Assert.IsNotNull (ts.SubToolsets, "#4"); Assert.AreEqual (0, ts.SubToolsets.Count, "#5"); -#endif Assert.AreEqual ("c:\\", ts.ToolsPath, "#6"); Assert.AreEqual ("4.3", ts.ToolsVersion, "#7"); } diff --git a/mcs/class/Microsoft.Build/Test/Microsoft.Build.Execution/ProjectTargetInstanceTest.cs b/mcs/class/Microsoft.Build/Test/Microsoft.Build.Execution/ProjectTargetInstanceTest.cs index ce13ce3646..5b24db55b2 100644 --- a/mcs/class/Microsoft.Build/Test/Microsoft.Build.Execution/ProjectTargetInstanceTest.cs +++ b/mcs/class/Microsoft.Build/Test/Microsoft.Build.Execution/ProjectTargetInstanceTest.cs @@ -143,9 +143,7 @@ namespace MonoTests.Microsoft.Build.Execution var root = ProjectRootElement.Create (xml); root.FullPath = "ProjectInstanceTest.DependsOnTargets.proj"; var proj = new ProjectInstance (root); -#if NET_4_5 Assert.AreEqual (2, proj.Targets.Count, "#1"); -#endif Assert.IsFalse (proj.Build ("Bar", new ILogger [0]), "#2"); } diff --git a/mcs/class/Microsoft.Build/Test/Microsoft.Build.Execution/ProjectTaskInstanceTest.cs b/mcs/class/Microsoft.Build/Test/Microsoft.Build.Execution/ProjectTaskInstanceTest.cs index c94bef7d69..1663f71c68 100644 --- a/mcs/class/Microsoft.Build/Test/Microsoft.Build.Execution/ProjectTaskInstanceTest.cs +++ b/mcs/class/Microsoft.Build/Test/Microsoft.Build.Execution/ProjectTaskInstanceTest.cs @@ -42,7 +42,6 @@ namespace MonoTests.Microsoft.Build.Execution [TestFixture] public class ProjectTaskInstanceTest { -#if NET_4_5 [Test] public void OutputPropertyExists () { @@ -78,7 +77,6 @@ namespace MonoTests.Microsoft.Build.Execution Assert.AreEqual (string.Empty, foo.Outputs, "#6"); Assert.AreEqual ("True", proj.GetPropertyValue ("C"), "#7"); } -#endif } } diff --git a/mcs/class/Microsoft.CSharp/Microsoft.CSharp.RuntimeBinder/DynamicContext.cs b/mcs/class/Microsoft.CSharp/Microsoft.CSharp.RuntimeBinder/DynamicContext.cs index 9c466c5ed9..d03145e0df 100644 --- a/mcs/class/Microsoft.CSharp/Microsoft.CSharp.RuntimeBinder/DynamicContext.cs +++ b/mcs/class/Microsoft.CSharp/Microsoft.CSharp.RuntimeBinder/DynamicContext.cs @@ -93,7 +93,8 @@ namespace Microsoft.CSharp.RuntimeBinder module.SetDeclaringAssembly (temp); var importer = new Compiler.ReflectionImporter (module, cc.BuiltinTypes) { - IgnorePrivateMembers = false + IgnorePrivateMembers = false, + IgnoreCompilerGeneratedField = false }; // Import all currently loaded assemblies diff --git a/mcs/class/Microsoft.NuGet.Build.Tasks/Makefile b/mcs/class/Microsoft.NuGet.Build.Tasks/Makefile index ceac5cfb33..e3561d4fb4 100644 --- a/mcs/class/Microsoft.NuGet.Build.Tasks/Makefile +++ b/mcs/class/Microsoft.NuGet.Build.Tasks/Makefile @@ -14,6 +14,8 @@ LIBRARY_INSTALL_DIR = $(NUGET_BUILDTASKS_TARGETS_DIR) KEY_FILE = $(NUGET_BUILDTASKS_REPO_DIR)/build/PublicKey.snk SIGN_FLAGS = /delaysign /keyfile:$(KEY_FILE) +RESOURCE_DEFS = Microsoft.NuGet.Build.Tasks.Strings,$(NUGET_BUILDTASKS_REPO_DIR)/src/Microsoft.NuGet.Build.Tasks/Strings.resx + LIB_REFS = $(PARENT_PROFILE)System \ $(PARENT_PROFILE)System.Core \ $(PARENT_PROFILE)System.Data \ @@ -25,18 +27,9 @@ LIB_REFS = $(PARENT_PROFILE)System \ LIB_MCS_FLAGS = \ -nowarn:3021 \ - $(SIGN_FLAGS) \ - -resource:Microsoft.NuGet.Build.Tasks.Strings.resources - -CLEAN_FILES = Microsoft.NuGet.Build.Tasks.Strings.resources + $(SIGN_FLAGS) EXTRA_DISTFILES = \ - $(NUGET_BUILDTASKS_REPO_DIR)/src/Microsoft.NuGet.Build.Tasks/Strings.resx \ $(NUGET_BUILDTASKS_REPO_DIR)/build/PublicKey.snk include ../../build/library.make - -$(build_lib): Microsoft.NuGet.Build.Tasks.Strings.resources - -Microsoft.NuGet.Build.Tasks.Strings.resources: $(NUGET_BUILDTASKS_REPO_DIR)/src/Microsoft.NuGet.Build.Tasks/Strings.resx - MONO_PATH="$(topdir)/class/lib/$(BOOTSTRAP_PROFILE)$(PLATFORM_PATH_SEPARATOR)$$MONO_PATH" $(RUNTIME) $(RUNTIME_FLAGS) $(topdir)/class/lib/net_4_x/resgen.exe "$<" "$@" diff --git a/mcs/class/Mono.Security.Providers.OldTls/Makefile b/mcs/class/Mono.Btls.Interface/Makefile similarity index 58% rename from mcs/class/Mono.Security.Providers.OldTls/Makefile rename to mcs/class/Mono.Btls.Interface/Makefile index 5dc06c0725..aa5b54c83f 100644 --- a/mcs/class/Mono.Security.Providers.OldTls/Makefile +++ b/mcs/class/Mono.Btls.Interface/Makefile @@ -1,11 +1,18 @@ -thisdir = class/Mono.Security.Providers.OldTls +thisdir = class/Mono.Btls.Interface SUBDIRS = include ../../build/rules.make -LIBRARY = Mono.Security.Providers.OldTls.dll +LIBRARY = Mono.Btls.Interface.dll LIB_REFS = System Mono.Security LIB_MCS_FLAGS = -unsafe -nowarn:1030 -keyfile:../mono.pub -delaysign -d:SECURITY_DEP +ifndef HAVE_BTLS +NO_INSTALL = yes +NO_SIGN_ASSEMBLY = yes +NO_TEST = yes +NO_BUILD = yes +endif + include ../../build/library.make $(the_lib): ../Mono.Security/Makefile diff --git a/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface.dll.sources b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface.dll.sources new file mode 100644 index 0000000000..710e06d35b --- /dev/null +++ b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface.dll.sources @@ -0,0 +1,22 @@ +./Properties/AssemblyInfo.cs +../../build/common/Consts.cs +../../build/common/Locale.cs +../../build/common/MonoTODOAttribute.cs + +Mono.Btls.Interface/BtlsObject.cs +Mono.Btls.Interface/BtlsProvider.cs +Mono.Btls.Interface/BtlsX509.cs +Mono.Btls.Interface/BtlsX509Chain.cs +Mono.Btls.Interface/BtlsX509Error.cs +Mono.Btls.Interface/BtlsX509Format.cs +Mono.Btls.Interface/BtlsX509Lookup.cs +Mono.Btls.Interface/BtlsX509Name.cs +Mono.Btls.Interface/BtlsX509Purpose.cs +Mono.Btls.Interface/BtlsX509Store.cs +Mono.Btls.Interface/BtlsX509StoreCtx.cs +Mono.Btls.Interface/BtlsX509StoreManager.cs +Mono.Btls.Interface/BtlsX509StoreType.cs +Mono.Btls.Interface/BtlsX509TrustKind.cs +Mono.Btls.Interface/BtlsX509VerifyFlags.cs +Mono.Btls.Interface/BtlsX509VerifyParam.cs +Mono.Btls.Interface/VersionInfo.cs diff --git a/mcs/class/Mono.Security.Providers.NewTls/Mono.Security.Providers.NewTls/ITlsContext.cs b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsObject.cs similarity index 60% rename from mcs/class/Mono.Security.Providers.NewTls/Mono.Security.Providers.NewTls/ITlsContext.cs rename to mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsObject.cs index 0d69805c4d..b2e607c177 100644 --- a/mcs/class/Mono.Security.Providers.NewTls/Mono.Security.Providers.NewTls/ITlsContext.cs +++ b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsObject.cs @@ -1,10 +1,10 @@ // -// ITlsContext.cs +// BtlsObject.cs // // Author: // Martin Baulig // -// Copyright (c) 2015-2016 Xamarin, Inc. +// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -23,48 +23,51 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. - -extern alias NewSystemSource; - using System; -using System.Security.Cryptography; -using Mono.Security.Interface; -using MX = Mono.Security.X509; - -namespace Mono.Security.Providers.NewTls +namespace Mono.Btls.Interface { - interface ITlsContext : IDisposable + public abstract class BtlsObject : IDisposable { - bool IsValid { - get; + MonoBtlsObject instance; + + internal MonoBtlsObject Instance { + get { + if (!IsValid) + throw new ObjectDisposedException (GetType ().Name); + return instance; + } } - TlsException LastError { - get; + internal BtlsObject (MonoBtlsObject instance) + { + this.instance = instance; } - bool ReceivedCloseNotify { - get; + public bool IsValid { + get { return instance != null && instance.IsValid; } } - MonoTlsConnectionInfo ConnectionInfo { - get; + protected void Dispose (bool disposing) + { + if (disposing) { + if (instance != null) { + instance.Dispose (); + instance = null; + } + } } - MX.X509Certificate GetRemoteCertificate (out MX.X509CertificateCollection remoteCertificateStore); + public void Dispose () + { + Dispose (true); + GC.SuppressFinalize (this); + } - bool VerifyRemoteCertificate (); - - int GenerateNextToken (TlsBuffer incoming, TlsMultiBuffer outgoing); - - int DecryptMessage (ref TlsBuffer incoming); - - int EncryptMessage (ref TlsBuffer incoming); - - byte[] CreateAlert (Alert alert); - - byte[] CreateHelloRequest (); + ~BtlsObject () + { + Dispose (false); + } } } diff --git a/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsProvider.cs b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsProvider.cs new file mode 100644 index 0000000000..0959dd0b61 --- /dev/null +++ b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsProvider.cs @@ -0,0 +1,107 @@ +// +// BtlsProvider.cs +// +// Author: +// Martin Baulig +// +// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using Mono.Security.Interface; +using System.Security.Cryptography.X509Certificates; +using MNS = Mono.Net.Security; + +namespace Mono.Btls.Interface +{ + public static class BtlsProvider + { + public static bool IsSupported () + { + return MNS.MonoTlsProviderFactory.IsBtlsSupported (); + } + + public static MonoTlsProvider GetProvider () + { + return new MonoBtlsProvider (); + } + + public static BtlsX509 CreateNative (byte[] data, BtlsX509Format format) + { + var x509 = MonoBtlsX509.LoadFromData (data, (MonoBtlsX509Format)format); + return new BtlsX509 (x509); + } + + public static X509Certificate CreateCertificate (byte[] data, BtlsX509Format format, bool disallowFallback = false) + { + return MonoBtlsProvider.CreateCertificate (data, (MonoBtlsX509Format)format, disallowFallback); + } + + public static X509Certificate2 CreateCertificate2 (byte[] data, BtlsX509Format format, bool disallowFallback = false) + { + return MonoBtlsProvider.CreateCertificate2 (data, (MonoBtlsX509Format)format, disallowFallback); + } + + public static X509Certificate2 CreateCertificate2 (byte[] data, string password, bool disallowFallback = false) + { + return MonoBtlsProvider.CreateCertificate2 (data, password, disallowFallback); + } + + public static BtlsX509Chain CreateNativeChain () + { + return new BtlsX509Chain (new MonoBtlsX509Chain ()); + } + + public static BtlsX509Store CreateNativeStore () + { + return new BtlsX509Store (new MonoBtlsX509Store ()); + } + + public static BtlsX509StoreCtx CreateNativeStoreCtx () + { + return new BtlsX509StoreCtx (new MonoBtlsX509StoreCtx ()); + } + + public static X509Chain CreateChain () + { + return MonoBtlsProvider.CreateChain (); + } + + public static string GetSystemStoreLocation () + { + return MonoBtlsProvider.GetSystemStoreLocation (); + } + + public static BtlsX509VerifyParam GetVerifyParam_SslClient () + { + return new BtlsX509VerifyParam (MonoBtlsX509VerifyParam.GetSslClient ()); + } + + public static BtlsX509VerifyParam GetVerifyParam_SslServer () + { + return new BtlsX509VerifyParam (MonoBtlsX509VerifyParam.GetSslServer ()); + } + + public static X509Chain GetManagedChain (BtlsX509Chain chain) + { + return MonoBtlsProvider.GetManagedChain (chain.Instance); + } + } +} + diff --git a/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509.cs b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509.cs new file mode 100644 index 0000000000..abcdafbf00 --- /dev/null +++ b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509.cs @@ -0,0 +1,132 @@ +// +// BtlsX509.cs +// +// Author: +// Martin Baulig +// +// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.IO; +using System.Security.Cryptography; + +namespace Mono.Btls.Interface +{ + public class BtlsX509 : BtlsObject + { + new internal MonoBtlsX509 Instance { + get { return (MonoBtlsX509)base.Instance; } + } + + internal BtlsX509 (MonoBtlsX509 x509) + : base (x509) + { + } + + public BtlsX509Name GetSubjectName () + { + return new BtlsX509Name (Instance.GetSubjectName ()); + } + + public BtlsX509Name GetIssuerName () + { + return new BtlsX509Name (Instance.GetIssuerName ()); + } + + public string GetSubjectNameString () + { + return Instance.GetSubjectNameString (); + } + + public string GetIssuerNameString () + { + return Instance.GetIssuerNameString (); + } + + public byte[] GetRawData (BtlsX509Format format) + { + return Instance.GetRawData ((MonoBtlsX509Format)format); + } + + public byte[] GetCertHash () + { + return Instance.GetCertHash (); + } + + public DateTime GetNotBefore () + { + return Instance.GetNotBefore (); + } + + public DateTime GetNotAfter () + { + return Instance.GetNotAfter (); + } + + public byte[] GetPublicKeyData () + { + return Instance.GetPublicKeyData (); + } + + public byte[] GetSerialNumber (bool mono_style) + { + return Instance.GetSerialNumber (mono_style); + } + + public int GetVersion () + { + return Instance.GetVersion (); + } + + public Oid GetSignatureAlgorithm () + { + return Instance.GetSignatureAlgorithm (); + } + + public AsnEncodedData GetPublicKeyAsn1 () + { + return Instance.GetPublicKeyAsn1 (); + } + + public AsnEncodedData GetPublicKeyParameters () + { + return Instance.GetPublicKeyParameters (); + } + + public long GetSubjectNameHash () + { + using (var name = GetSubjectName ()) + return name.GetHash (); + } + + public void Print (Stream stream) + { + using (var bio = MonoBtlsBio.CreateMonoStream (stream)) + Instance.Print (bio); + } + + public void ExportAsPEM (Stream stream, bool includeHumanReadableForm) + { + using (var bio = MonoBtlsBio.CreateMonoStream (stream)) + Instance.ExportAsPEM (bio, includeHumanReadableForm); + } + } +} + diff --git a/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Chain.cs b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Chain.cs new file mode 100644 index 0000000000..38e9ec5814 --- /dev/null +++ b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Chain.cs @@ -0,0 +1,58 @@ +// +// BtlsX509Chain.cs +// +// Author: +// Martin Baulig +// +// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; + +namespace Mono.Btls.Interface +{ + public class BtlsX509Chain : BtlsObject + { + new internal MonoBtlsX509Chain Instance { + get { return (MonoBtlsX509Chain)base.Instance; } + } + + internal BtlsX509Chain (MonoBtlsX509Chain chain) + : base (chain) + { + } + + public int Count { + get { return Instance.Count; } + } + + public BtlsX509 this[int index] { + get { + var x509 = Instance.GetCertificate (index); + return new BtlsX509 (x509.Copy ()); + } + } + + public void Add (BtlsX509 x509) + { + Instance.AddCertificate (x509.Instance); + } + } +} + diff --git a/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Error.cs b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Error.cs new file mode 100644 index 0000000000..089b4f23e0 --- /dev/null +++ b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Error.cs @@ -0,0 +1,110 @@ +// +// BtlsX509Error.cs +// +// Author: +// Martin Baulig +// +// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +namespace Mono.Btls.Interface +{ + // Keep in sync with NativeBoringX509Error + public enum BtlsX509Error + { + OK = 0, + /* illegal error (for uninitialized values, to avoid X509_V_OK): 1 */ + + UNABLE_TO_GET_ISSUER_CERT = 2, + UNABLE_TO_GET_CRL = 3, + UNABLE_TO_DECRYPT_CERT_SIGNATURE = 4, + UNABLE_TO_DECRYPT_CRL_SIGNATURE = 5, + UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY = 6, + CERT_SIGNATURE_FAILURE = 7, + CRL_SIGNATURE_FAILURE = 8, + CERT_NOT_YET_VALID = 9, + CERT_HAS_EXPIRED = 10, + CRL_NOT_YET_VALID = 11, + CRL_HAS_EXPIRED = 12, + ERROR_IN_CERT_NOT_BEFORE_FIELD = 13, + ERROR_IN_CERT_NOT_AFTER_FIELD = 14, + ERROR_IN_CRL_LAST_UPDATE_FIELD = 15, + ERROR_IN_CRL_NEXT_UPDATE_FIELD = 16, + OUT_OF_MEM = 17, + DEPTH_ZERO_SELF_SIGNED_CERT = 18, + SELF_SIGNED_CERT_IN_CHAIN = 19, + UNABLE_TO_GET_ISSUER_CERT_LOCALLY = 20, + UNABLE_TO_VERIFY_LEAF_SIGNATURE = 21, + CERT_CHAIN_TOO_LONG = 22, + CERT_REVOKED = 23, + INVALID_CA = 24, + PATH_LENGTH_EXCEEDED = 25, + INVALID_PURPOSE = 26, + CERT_UNTRUSTED = 27, + CERT_REJECTED = 28, + /* These are 'informational' when looking for issuer cert */ + SUBJECT_ISSUER_MISMATCH = 29, + AKID_SKID_MISMATCH = 30, + AKID_ISSUER_SERIAL_MISMATCH = 31, + KEYUSAGE_NO_CERTSIGN = 32, + + UNABLE_TO_GET_CRL_ISSUER = 33, + UNHANDLED_CRITICAL_EXTENSION = 34, + KEYUSAGE_NO_CRL_SIGN = 35, + UNHANDLED_CRITICAL_CRL_EXTENSION = 36, + INVALID_NON_CA = 37, + PROXY_PATH_LENGTH_EXCEEDED = 38, + KEYUSAGE_NO_DIGITAL_SIGNATURE = 39, + PROXY_CERTIFICATES_NOT_ALLOWED = 40, + + INVALID_EXTENSION = 41, + INVALID_POLICY_EXTENSION = 42, + NO_EXPLICIT_POLICY = 43, + DIFFERENT_CRL_SCOPE = 44, + UNSUPPORTED_EXTENSION_FEATURE = 45, + + UNNESTED_RESOURCE = 46, + + PERMITTED_VIOLATION = 47, + EXCLUDED_VIOLATION = 48, + SUBTREE_MINMAX = 49, + UNSUPPORTED_CONSTRAINT_TYPE = 51, + UNSUPPORTED_CONSTRAINT_SYNTAX = 52, + UNSUPPORTED_NAME_SYNTAX = 53, + CRL_PATH_VALIDATION_ERROR = 54, + + /* Suite B mode algorithm violation */ + SUITE_B_INVALID_VERSION = 56, + SUITE_B_INVALID_ALGORITHM = 57, + SUITE_B_INVALID_CURVE = 58, + SUITE_B_INVALID_SIGNATURE_ALGORITHM = 59, + SUITE_B_LOS_NOT_ALLOWED = 60, + SUITE_B_CANNOT_SIGN_P_384_WITH_P_256 = 61, + + /* Host, email and IP check errors */ + HOSTNAME_MISMATCH = 62, + EMAIL_MISMATCH = 63, + IP_ADDRESS_MISMATCH = 64, + + /* The application is not happy */ + APPLICATION_VERIFICATION = 50 + } +} + diff --git a/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Format.cs b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Format.cs new file mode 100644 index 0000000000..6ff63cec12 --- /dev/null +++ b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Format.cs @@ -0,0 +1,37 @@ +// +// BtlsX509Format.cs +// +// Author: +// Martin Baulig +// +// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; + +namespace Mono.Btls.Interface +{ + // Keep in sync with NativeBoringX509Format + public enum BtlsX509Format + { + DER = 1, + PEM = 2 + } +} + diff --git a/mcs/class/Mono.Security/Mono.Security.Interface/IMonoTlsContext.cs b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Lookup.cs similarity index 57% rename from mcs/class/Mono.Security/Mono.Security.Interface/IMonoTlsContext.cs rename to mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Lookup.cs index d1ac4e27d0..836088fdd5 100644 --- a/mcs/class/Mono.Security/Mono.Security.Interface/IMonoTlsContext.cs +++ b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Lookup.cs @@ -1,10 +1,10 @@ // -// IMonoTlsContext.cs +// BtlsX509Lookup.cs // // Author: // Martin Baulig // -// Copyright (c) 2015 Xamarin, Inc. +// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -24,48 +24,49 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. using System; +using System.IO; using System.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; -namespace Mono.Security.Interface +namespace Mono.Btls.Interface { - interface IMonoTlsContext : IDisposable + public class BtlsX509Lookup : BtlsObject { - bool IsServer { - get; + new internal MonoBtlsX509Lookup Instance { + get { return (MonoBtlsX509Lookup)base.Instance; } } - bool IsValid { - get; + internal BtlsX509Lookup (MonoBtlsX509Lookup lookup) + : base (lookup) + { } - void Initialize (IMonoTlsEventSink eventSink); - - bool HasCredentials { - get; + public void Initialize () + { + Instance.Initialize (); } - void SetCertificate (X509Certificate certificate, AsymmetricAlgorithm privateKey); - - int GenerateNextToken (IBufferOffsetSize incoming, out IBufferOffsetSize outgoing); - - int EncryptMessage (ref IBufferOffsetSize incoming); - - int DecryptMessage (ref IBufferOffsetSize incoming); - - bool ReceivedCloseNotify { - get; + public void Shutdown () + { + Instance.Shutdown (); } - byte[] CreateCloseNotify (); + public BtlsX509 LookupBySubject (BtlsX509Name name) + { + var x509 = Instance.LookupBySubject (name.Instance); + if (x509 == null) + return null; - byte[] CreateHelloRequest (); + return new BtlsX509 (x509); + } - X509Certificate GetRemoteCertificate (out X509CertificateCollection remoteCertificateStore); + public void LoadFile (string file, BtlsX509Format type) + { + Instance.LoadFile (file, (MonoBtlsX509FileType)type); + } - bool VerifyRemoteCertificate (); - - MonoTlsConnectionInfo GetConnectionInfo (); + public void AddDirectory (string dir, BtlsX509Format type) + { + Instance.AddDirectory (dir, (MonoBtlsX509FileType)type); + } } } - diff --git a/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Name.cs b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Name.cs new file mode 100644 index 0000000000..69ca5a9e20 --- /dev/null +++ b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Name.cs @@ -0,0 +1,62 @@ +// +// BtlsX509Name.cs +// +// Author: +// Martin Baulig +// +// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; + +namespace Mono.Btls.Interface +{ + public class BtlsX509Name : BtlsObject + { + new internal MonoBtlsX509Name Instance { + get { return (MonoBtlsX509Name)base.Instance; } + } + + internal BtlsX509Name (MonoBtlsX509Name name) + : base (name) + { + } + + public string GetString () + { + return Instance.GetString (); + } + + public byte[] GetRawData (bool use_canon_enc) + { + return Instance.GetRawData (use_canon_enc); + } + + public long GetHash () + { + return Instance.GetHash (); + } + + public long GetHashOld () + { + return Instance.GetHashOld (); + } + } +} + diff --git a/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Purpose.cs b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Purpose.cs new file mode 100644 index 0000000000..ac906dfe85 --- /dev/null +++ b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Purpose.cs @@ -0,0 +1,43 @@ +// +// BtlsX509Purpose.cs +// +// Author: +// Martin Baulig +// +// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +namespace Mono.Btls.Interface +{ + // Keep in sync with NativeBoringX509Purpose + public enum BtlsX509Purpose + { + SSL_CLIENT = 1, + SSL_SERVER = 2, + NS_SSL_SERVER = 3, + SMIME_SIGN = 4, + SMIME_ENCRYPT = 5, + CRL_SIGN = 6, + ANY = 7, + OCSP_HELPER = 8, + TIMESTAMP_SIGN = 9, + } +} + diff --git a/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Store.cs b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Store.cs new file mode 100644 index 0000000000..7b8f03fc7a --- /dev/null +++ b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Store.cs @@ -0,0 +1,91 @@ +// +// BtlsX509Store.cs +// +// Author: +// Martin Baulig +// +// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Security.Cryptography.X509Certificates; + +namespace Mono.Btls.Interface +{ + public class BtlsX509Store : BtlsObject + { + new internal MonoBtlsX509Store Instance { + get { return (MonoBtlsX509Store)base.Instance; } + } + + internal BtlsX509Store (MonoBtlsX509Store store) + : base (store) + { + } + + public void LoadLocations (string file, string path) + { + Instance.LoadLocations (file, path); + } + + public void AddTrustedRoots () + { + Instance.AddTrustedRoots (); + } + + public void AddCertificate (BtlsX509 x509) + { + Instance.AddCertificate (x509.Instance); + } + + public int GetCount () + { + return Instance.GetCount (); + } + + public void AddLookup (X509CertificateCollection certificates, BtlsX509TrustKind trust) + { + Instance.AddCollection (certificates, (MonoBtlsX509TrustKind)trust); + } + + static MonoBtlsX509FileType GetFileType (BtlsX509Format format) + { + switch (format) { + case BtlsX509Format.DER: + return MonoBtlsX509FileType.ASN1; + case BtlsX509Format.PEM: + return MonoBtlsX509FileType.PEM; + default: + throw new NotSupportedException (); + } + } + + public void AddDirectoryLookup (string dir, BtlsX509Format format) + { + Instance.AddDirectoryLookup (dir, GetFileType (format)); + } + + public void AddFileLookup (string file, BtlsX509Format format) + { + Instance.AddFileLookup (file, GetFileType (format)); + } + + } +} + diff --git a/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509StoreCtx.cs b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509StoreCtx.cs new file mode 100644 index 0000000000..97d4a066f6 --- /dev/null +++ b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509StoreCtx.cs @@ -0,0 +1,71 @@ +// +// BtlsX509StoreCtx.cs +// +// Author: +// Martin Baulig +// +// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +namespace Mono.Btls.Interface +{ + public class BtlsX509StoreCtx : BtlsObject + { + new internal MonoBtlsX509StoreCtx Instance { + get { return (MonoBtlsX509StoreCtx)base.Instance; } + } + + internal BtlsX509StoreCtx (MonoBtlsX509StoreCtx ctx) + : base (ctx) + { + } + + public void Initialize (BtlsX509Store store, BtlsX509Chain chain) + { + Instance.Initialize (store.Instance, chain.Instance); + } + + public void SetVerifyParam (BtlsX509VerifyParam param) + { + Instance.SetVerifyParam (param.Instance); + } + + public int Verify () + { + return Instance.Verify (); + } + + public BtlsX509Error GetError () + { + return (BtlsX509Error)Instance.GetError (); + } + + public Exception GetException () + { + return Instance.GetException (); + } + + public BtlsX509Chain GetChain () + { + return new BtlsX509Chain (Instance.GetChain ()); + } + } +} + diff --git a/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509StoreManager.cs b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509StoreManager.cs new file mode 100644 index 0000000000..1989ff44f2 --- /dev/null +++ b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509StoreManager.cs @@ -0,0 +1,44 @@ +// +// BtlsX509StoreManager.cs +// +// Author: +// Martin Baulig +// +// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.IO; +using System.Security.Cryptography; + +namespace Mono.Btls.Interface +{ + public static class BtlsX509StoreManager + { + public static bool HasStore (BtlsX509StoreType type) + { + return MonoBtlsX509StoreManager.HasStore ((MonoBtlsX509StoreType)type); + } + + public static string GetStorePath (BtlsX509StoreType type) + { + return MonoBtlsX509StoreManager.GetStorePath ((MonoBtlsX509StoreType)type); + } + } +} diff --git a/mcs/class/Mono.Security.Providers.NewTls/Mono.Security.Providers.NewTls/ITlsConfiguration.cs b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509StoreType.cs similarity index 76% rename from mcs/class/Mono.Security.Providers.NewTls/Mono.Security.Providers.NewTls/ITlsConfiguration.cs rename to mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509StoreType.cs index 401afd763e..acdfb98d4c 100644 --- a/mcs/class/Mono.Security.Providers.NewTls/Mono.Security.Providers.NewTls/ITlsConfiguration.cs +++ b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509StoreType.cs @@ -1,10 +1,10 @@ // -// ITlsContext.cs +// BtlsX509StoreType.cs // // Author: // Martin Baulig // -// Copyright (c) 2015-2016 Xamarin, Inc. +// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -23,25 +23,21 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. - using System; +using System.IO; using System.Security.Cryptography; -using Mono.Security.Interface; -using MX = Mono.Security.X509; - -namespace Mono.Security.Providers.NewTls +namespace Mono.Btls.Interface { - interface ITlsConfiguration + // Keep in sync with MonoBtlsX509StoreType + public enum BtlsX509StoreType { - bool HasCredentials { - get; - } - - void SetCertificate (MX.X509Certificate certificate, AsymmetricAlgorithm privateKey); - - bool? AskForClientCertificate { - get; set; - } + Custom, + MachineTrustedRoots, + MachineIntermediateCA, + MachineUntrusted, + UserTrustedRoots, + UserIntermediateCA, + UserUntrusted } } diff --git a/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509TrustKind.cs b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509TrustKind.cs new file mode 100644 index 0000000000..9338ec61db --- /dev/null +++ b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509TrustKind.cs @@ -0,0 +1,42 @@ +// +// BtlsX509TrustKind.cs +// +// Author: +// Martin Baulig +// +// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +namespace Mono.Btls.Interface +{ + // Keep in sync with MonoBtlsX509TrustKind + [Flags] + public enum BtlsX509TrustKind + { + DEFAULT = 0, + TRUST_CLIENT = 1, + TRUST_SERVER = 2, + TRUST_ALL = 4, + REJECT_CLIENT = 32, + REJECT_SERVER = 64, + REJECT_ALL = 128 + } +} + diff --git a/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509VerifyFlags.cs b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509VerifyFlags.cs new file mode 100644 index 0000000000..02640c82a1 --- /dev/null +++ b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509VerifyFlags.cs @@ -0,0 +1,38 @@ +// +// BtlsX509VerifyFlags.cs +// +// Author: +// Martin Baulig +// +// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +namespace Mono.Btls.Interface +{ + // Keep in sync with NativeBoringX509VerifyFlags + public enum BtlsX509VerifyFlags + { + DEFAULT = 0, + CRL_CHECK = 1, + CRL_CHECK_ALL = 2, + X509_STRIC = 4 + } +} + diff --git a/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509VerifyParam.cs b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509VerifyParam.cs new file mode 100644 index 0000000000..8d4e5eba5e --- /dev/null +++ b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509VerifyParam.cs @@ -0,0 +1,91 @@ +// +// BtlsX509VerifyParam.cs +// +// Author: +// Martin Baulig +// +// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +namespace Mono.Btls.Interface +{ + public class BtlsX509VerifyParam : BtlsObject + { + new internal MonoBtlsX509VerifyParam Instance { + get { return (MonoBtlsX509VerifyParam)base.Instance; } + } + + internal BtlsX509VerifyParam (MonoBtlsX509VerifyParam param) + : base (param) + { + } + + public BtlsX509VerifyParam Copy () + { + return new BtlsX509VerifyParam (Instance.Copy ()); + } + + public void SetName (string name) + { + Instance.SetName (name); + } + + public void SetHost (string name) + { + Instance.SetHost (name); + } + + public void AddHost (string name) + { + Instance.AddHost (name); + } + + public BtlsX509VerifyFlags GetFlags () + { + return (BtlsX509VerifyFlags)Instance.GetFlags (); + } + + public void SetFlags (BtlsX509VerifyFlags flags) + { + Instance.SetFlags ((ulong)flags); + } + + public void SetPurpose (BtlsX509Purpose purpose) + { + Instance.SetPurpose ((MonoBtlsX509Purpose)purpose); + } + + public int GetDepth () + { + return Instance.GetDepth (); + } + + public void SetDepth (int depth) + { + Instance.SetDepth (depth); + } + + public void SetTime (DateTime time) + { + Instance.SetTime (time); + } + } +} + diff --git a/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/VersionInfo.cs b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/VersionInfo.cs new file mode 100644 index 0000000000..726c4ba88b --- /dev/null +++ b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/VersionInfo.cs @@ -0,0 +1,34 @@ +// +// VersionInfo.cs +// +// Author: +// Martin Baulig +// +// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +namespace Mono.Btls.Interface +{ + public static class VersionInfo + { + public const string Version = "1.0.0"; + } +} + diff --git a/mcs/class/Mono.Security.Providers.DotNet/Properties/AssemblyInfo.cs b/mcs/class/Mono.Btls.Interface/Properties/AssemblyInfo.cs similarity index 88% rename from mcs/class/Mono.Security.Providers.DotNet/Properties/AssemblyInfo.cs rename to mcs/class/Mono.Btls.Interface/Properties/AssemblyInfo.cs index cbbd002927..5ff0bcb3b9 100644 --- a/mcs/class/Mono.Security.Providers.DotNet/Properties/AssemblyInfo.cs +++ b/mcs/class/Mono.Btls.Interface/Properties/AssemblyInfo.cs @@ -1,10 +1,11 @@ -// +// // AssemblyInfo.cs // // Author: // Martin Baulig // -// Copyright (c) 2015 Xamarin, Inc. +// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com) + // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -36,10 +37,10 @@ using System.Runtime.InteropServices; [assembly: AssemblyVersion (Consts.FxVersion)] [assembly: AssemblyCompany ("MONO development team")] -[assembly: AssemblyCopyright ("(c) 2015 Xamarin")] -[assembly: AssemblyDescription ("Mono.Security.Providers.DotNet.dll")] +[assembly: AssemblyCopyright ("(c) 2016 Xamarin")] +[assembly: AssemblyDescription ("Mono.Btls.Interface")] [assembly: AssemblyProduct ("MONO CLI")] -[assembly: AssemblyTitle ("Mono.Security.Providers.DotNet.dll")] +[assembly: AssemblyTitle ("Mono.Btls.Interface")] [assembly: CLSCompliant (true)] [assembly: ComVisible (false)] [assembly: NeutralResourcesLanguage ("en-US")] diff --git a/mcs/class/Mono.CSharp/Mono.CSharp_test.dll.sources b/mcs/class/Mono.CSharp/Mono.CSharp_test.dll.sources index f38a41c7f5..4fbea10f4f 100644 --- a/mcs/class/Mono.CSharp/Mono.CSharp_test.dll.sources +++ b/mcs/class/Mono.CSharp/Mono.CSharp_test.dll.sources @@ -5,3 +5,4 @@ Evaluator/EvaluatorFixture.cs Evaluator/EvaluatorTest.cs Evaluator/ExpressionsTest.cs Evaluator/TypesTest.cs +Visit/ASTVisitorTest.cs diff --git a/mcs/class/Mono.CSharp/Test/Evaluator/ExpressionsTest.cs b/mcs/class/Mono.CSharp/Test/Evaluator/ExpressionsTest.cs index 74fc4a03cf..8c414dad79 100644 --- a/mcs/class/Mono.CSharp/Test/Evaluator/ExpressionsTest.cs +++ b/mcs/class/Mono.CSharp/Test/Evaluator/ExpressionsTest.cs @@ -120,7 +120,8 @@ namespace MonoTests.EvaluatorTest Evaluator.Run ("var a = new int[]{1,2,3};"); object res = Evaluator.Evaluate ("from x in a select x + 1;"); - CollectionAssert.AreEqual (new int[] { 2, 3, 4 }, ((IEnumerable) res).ToArray ()); + + Assert.AreEqual (new int[] { 2, 3, 4 }, ((IEnumerable) res).ToArray ()); } [Test] @@ -201,4 +202,4 @@ namespace MonoTests.EvaluatorTest } } -} \ No newline at end of file +} diff --git a/mcs/class/Mono.CSharp/Test/Visit/ASTVisitorTest.cs b/mcs/class/Mono.CSharp/Test/Visit/ASTVisitorTest.cs new file mode 100644 index 0000000000..ea15e44a74 --- /dev/null +++ b/mcs/class/Mono.CSharp/Test/Visit/ASTVisitorTest.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using NUnit.Framework; +using Mono.CSharp; +using System.IO; + +namespace MonoTests.Visit +{ + [TestFixture] + public class ASTVisitorTest + { + class TestVisitor : StructuralVisitor + { + } + + [SetUp] + public void Setup () + { + } + + [Test] + public void Simple () + { + //string content = @"class A { }"; + string content = @" + +class Foo +{ + void Bar () + { +completionList.Add (""delegate"" + sb, ""md-keyword"", GettextCatalog.GetString (""Creates anonymous delegate.""), ""delegate"" + sb + "" {"" + Document.Editor.EolMarker + stateTracker.Engine.ThisLineIndent + TextEditorProperties.IndentString + ""|"" + Document.Editor.EolMarker + stateTracker.Engine.ThisLineIndent +""};""); + } +}" + ; + + + var stream = new MemoryStream (Encoding.UTF8.GetBytes (content)); + + var ctx = new CompilerContext (new CompilerSettings (), new AssertReportPrinter ()); + + ModuleContainer module = new ModuleContainer (ctx); + var file = new SourceFile ("test", "asdfas", 0); + CSharpParser parser = new CSharpParser ( + new SeekableStreamReader (stream, Encoding.UTF8), + new CompilationSourceFile (module, file), + ctx.Report, + new ParserSession ()); + + RootContext.ToplevelTypes = module; + Location.Initialize (new List { file }); + parser.parse (); + + Assert.AreEqual (0, ctx.Report.Errors); + + module.Accept (new TestVisitor ()); + } + } +} diff --git a/mcs/class/Mono.CSharp/mobile_static_Mono.CSharp.dll.sources b/mcs/class/Mono.CSharp/mobile_static_Mono.CSharp.dll.sources index bd7397407a..4c30fc6e14 100644 --- a/mcs/class/Mono.CSharp/mobile_static_Mono.CSharp.dll.sources +++ b/mcs/class/Mono.CSharp/mobile_static_Mono.CSharp.dll.sources @@ -1,13 +1,4 @@ #include Mono.CSharp.dll.sources -../corlib/System.Reflection.Emit/AssemblyBuilderAccess.cs -../corlib/System.Reflection.Emit/FlowControl.cs -../corlib/System.Reflection.Emit/OpCode.cs -../corlib/System.Reflection.Emit/OpCodeNames.cs -../corlib/System.Reflection.Emit/OpCodes.cs -../corlib/System.Reflection.Emit/OpCodeType.cs -../corlib/System.Reflection.Emit/OperandType.cs ../corlib/System.Reflection.Emit/PEFileKinds.cs -../corlib/System.Reflection.Emit/Label.cs ../corlib/System.Reflection.Emit/MethodToken.cs -../corlib/System.Reflection.Emit/StackBehaviour.cs monotouch.cs diff --git a/mcs/class/Mono.CSharp/monotouch.cs b/mcs/class/Mono.CSharp/monotouch.cs index a826081990..06feb3cc39 100644 --- a/mcs/class/Mono.CSharp/monotouch.cs +++ b/mcs/class/Mono.CSharp/monotouch.cs @@ -28,66 +28,6 @@ namespace System.Reflection.Emit { - public class ILGenerator - { - public void BeginCatchBlock (Type exceptionType) - { - throw new NotSupportedException (); - } - - public Label BeginExceptionBlock () - { - throw new NotSupportedException (); - } - - public void BeginExceptFilterBlock () - { - throw new NotSupportedException (); - } - - public void BeginFinallyBlock () - { - throw new NotSupportedException (); - } - - public LocalBuilder DeclareLocal (params object[] args) - { - throw new NotSupportedException (); - } - - public Label DefineLabel () - { - throw new NotSupportedException (); - } - - public void Emit (OpCode opcode) - { - throw new NotSupportedException (); - } - - public void Emit (OpCode opcode, object args) - { - throw new NotSupportedException (); - } - - public void EmitCall (OpCode opcode, params object[] args) - { - throw new NotSupportedException (); - } - - public void EndExceptionBlock () - { - throw new NotSupportedException (); - } - - public void MarkLabel (Label loc) - { - throw new NotSupportedException (); - } - - public int ILOffset { get; set; } - } - public class TypeBuilder : Type { #region implemented abstract members of MemberInfo @@ -528,230 +468,6 @@ namespace System.Reflection.Emit } } - public class LocalBuilder : LocalVariableInfo - { - } - - public class GenericTypeParameterBuilder : Type - { - #region implemented abstract members of MemberInfo - - public override bool IsDefined (Type attributeType, bool inherit) - { - throw new NotSupportedException (); - } - - public override object[] GetCustomAttributes (bool inherit) - { - throw new NotSupportedException (); - } - - public override object[] GetCustomAttributes (Type attributeType, bool inherit) - { - throw new NotSupportedException (); - } - - public override string Name { - get { - throw new NotSupportedException (); - } - } - - #endregion - - #region implemented abstract members of Type - - public override Type GetInterface (string name, bool ignoreCase) - { - throw new NotSupportedException (); - } - - public override Type[] GetInterfaces () - { - throw new NotSupportedException (); - } - - public override Type GetElementType () - { - throw new NotSupportedException (); - } - - public override EventInfo GetEvent (string name, BindingFlags bindingAttr) - { - throw new NotSupportedException (); - } - - public override EventInfo[] GetEvents (BindingFlags bindingAttr) - { - throw new NotSupportedException (); - } - - public override FieldInfo GetField (string name, BindingFlags bindingAttr) - { - throw new NotSupportedException (); - } - - public override FieldInfo[] GetFields (BindingFlags bindingAttr) - { - throw new NotSupportedException (); - } - - public override MemberInfo[] GetMembers (BindingFlags bindingAttr) - { - throw new NotSupportedException (); - } - - protected override MethodInfo GetMethodImpl (string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers) - { - throw new NotSupportedException (); - } - - public override MethodInfo[] GetMethods (BindingFlags bindingAttr) - { - throw new NotSupportedException (); - } - - public override Type GetNestedType (string name, BindingFlags bindingAttr) - { - throw new NotSupportedException (); - } - - public override Type[] GetNestedTypes (BindingFlags bindingAttr) - { - throw new NotSupportedException (); - } - - public override PropertyInfo[] GetProperties (BindingFlags bindingAttr) - { - throw new NotSupportedException (); - } - - protected override PropertyInfo GetPropertyImpl (string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers) - { - throw new NotSupportedException (); - } - - protected override ConstructorInfo GetConstructorImpl (BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers) - { - throw new NotSupportedException (); - } - - protected override TypeAttributes GetAttributeFlagsImpl () - { - throw new NotSupportedException (); - } - - protected override bool HasElementTypeImpl () - { - throw new NotSupportedException (); - } - - protected override bool IsArrayImpl () - { - throw new NotSupportedException (); - } - - protected override bool IsByRefImpl () - { - throw new NotSupportedException (); - } - - protected override bool IsCOMObjectImpl () - { - throw new NotSupportedException (); - } - - protected override bool IsPointerImpl () - { - throw new NotSupportedException (); - } - - protected override bool IsPrimitiveImpl () - { - throw new NotSupportedException (); - } - - public override ConstructorInfo[] GetConstructors (BindingFlags bindingAttr) - { - throw new NotSupportedException (); - } - - public override object InvokeMember (string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, System.Globalization.CultureInfo culture, string[] namedParameters) - { - throw new NotSupportedException (); - } - - public override Assembly Assembly { - get { - throw new NotSupportedException (); - } - } - - public override string AssemblyQualifiedName { - get { - throw new NotSupportedException (); - } - } - - public override Type BaseType { - get { - throw new NotSupportedException (); - } - } - - public override string FullName { - get { - throw new NotSupportedException (); - } - } - - public override Guid GUID { - get { - throw new NotSupportedException (); - } - } - - public override Module Module { - get { - throw new NotSupportedException (); - } - } - - public override string Namespace { - get { - throw new NotSupportedException (); - } - } - - public override Type UnderlyingSystemType { - get { - throw new NotSupportedException (); - } - } - - #endregion - - public void SetCustomAttribute (params object[] args) - { - throw new NotSupportedException (); - } - - public void SetGenericParameterAttributes (GenericParameterAttributes genericParameterAttributes) - { - throw new NotSupportedException (); - } - - public void SetInterfaceConstraints (params Type[] interfaceConstraints) - { - throw new NotSupportedException (); - } - - public void SetBaseTypeConstraint (Type baseTypeConstraint) - { - throw new NotSupportedException (); - } - } - public class ConstructorBuilder : MethodBase { #region implemented abstract members of MemberInfo @@ -1087,19 +803,6 @@ namespace System.Reflection.Emit } } - public class ParameterBuilder : ParameterInfo - { - public void SetConstant (object arg) - { - throw new NotSupportedException (); - } - - public void SetCustomAttribute (params object[] args) - { - throw new NotSupportedException (); - } - } - public class EventBuilder { public void SetAddOnMethod (MethodBuilder mdBuilder) @@ -1118,11 +821,4 @@ namespace System.Reflection.Emit } } - public class CustomAttributeBuilder - { - public CustomAttributeBuilder (params object[] args) - { - throw new NotSupportedException (); - } - } } \ No newline at end of file diff --git a/mcs/class/Mono.CSharp/monotouch_Mono.CSharp.dll.sources b/mcs/class/Mono.CSharp/monotouch_Mono.CSharp.dll.sources index 6a71501e34..ec641ef2b6 100644 --- a/mcs/class/Mono.CSharp/monotouch_Mono.CSharp.dll.sources +++ b/mcs/class/Mono.CSharp/monotouch_Mono.CSharp.dll.sources @@ -1,2 +1 @@ #include mobile_static_Mono.CSharp.dll.sources -monotouch.cs diff --git a/mcs/class/Mono.CSharp/monotouch_tv_Mono.CSharp.dll.sources b/mcs/class/Mono.CSharp/monotouch_tv_Mono.CSharp.dll.sources index 6a71501e34..ec641ef2b6 100644 --- a/mcs/class/Mono.CSharp/monotouch_tv_Mono.CSharp.dll.sources +++ b/mcs/class/Mono.CSharp/monotouch_tv_Mono.CSharp.dll.sources @@ -1,2 +1 @@ #include mobile_static_Mono.CSharp.dll.sources -monotouch.cs diff --git a/mcs/class/Mono.CSharp/monotouch_watch_Mono.CSharp.dll.sources b/mcs/class/Mono.CSharp/monotouch_watch_Mono.CSharp.dll.sources index 6a71501e34..ec641ef2b6 100644 --- a/mcs/class/Mono.CSharp/monotouch_watch_Mono.CSharp.dll.sources +++ b/mcs/class/Mono.CSharp/monotouch_watch_Mono.CSharp.dll.sources @@ -1,2 +1 @@ #include mobile_static_Mono.CSharp.dll.sources -monotouch.cs diff --git a/mcs/class/Mono.Cecil.Mdb/Mono.Cecil.Mdb.dll.sources b/mcs/class/Mono.Cecil.Mdb/Mono.Cecil.Mdb.dll.sources index eedadff94e..a8f6b27448 100644 --- a/mcs/class/Mono.Cecil.Mdb/Mono.Cecil.Mdb.dll.sources +++ b/mcs/class/Mono.Cecil.Mdb/Mono.Cecil.Mdb.dll.sources @@ -1,7 +1,3 @@ -../../../external/cecil/symbols/mdb/Mono.Cecil.Mdb/AssemblyInfo.cs -../../../external/cecil/symbols/mdb/Mono.Cecil.Mdb/MdbReader.cs -../../../external/cecil/symbols/mdb/Mono.Cecil.Mdb/MdbWriter.cs -../../../external/cecil/symbols/mdb/Mono.CompilerServices.SymbolWriter/MonoSymbolFile.cs -../../../external/cecil/symbols/mdb/Mono.CompilerServices.SymbolWriter/MonoSymbolTable.cs -../../../external/cecil/symbols/mdb/Mono.CompilerServices.SymbolWriter/MonoSymbolWriter.cs -../../../external/cecil/symbols/mdb/Mono.CompilerServices.SymbolWriter/SymbolWriterImpl.cs +../../../external/cecil/ProjectInfo.cs +../../../external/cecil/symbols/mdb/Mono.Cecil.Mdb/*.cs +../../../external/cecil/symbols/mdb/Mono.CompilerServices.SymbolWriter/*.cs diff --git a/mcs/class/Mono.Cecil/Makefile b/mcs/class/Mono.Cecil/Makefile index 53aee64f34..d8807afa49 100644 --- a/mcs/class/Mono.Cecil/Makefile +++ b/mcs/class/Mono.Cecil/Makefile @@ -6,7 +6,7 @@ LIBRARY_SNK = ../mono.snk LIBRARY_PACKAGE = none LIB_REFS = System.Core -LIB_MCS_FLAGS = -keyfile:$(LIBRARY_SNK) -d:NET_3_5 /publicsign +LIB_MCS_FLAGS = -keyfile:$(LIBRARY_SNK) -d:NET_4_0 /publicsign NO_TEST = yes diff --git a/mcs/class/Mono.Cecil/Mono.Cecil.dll.sources b/mcs/class/Mono.Cecil/Mono.Cecil.dll.sources index 231d5d77bd..ed24c3b38a 100644 --- a/mcs/class/Mono.Cecil/Mono.Cecil.dll.sources +++ b/mcs/class/Mono.Cecil/Mono.Cecil.dll.sources @@ -1,127 +1,9 @@ -../../../external/cecil/Mono.Collections.Generic/Collection.cs -../../../external/cecil/Mono.Collections.Generic/ReadOnlyCollection.cs -../../../external/cecil/Mono.Cecil.PE/ImageWriter.cs -../../../external/cecil/Mono.Cecil.PE/BinaryStreamWriter.cs -../../../external/cecil/Mono.Cecil.PE/BinaryStreamReader.cs -../../../external/cecil/Mono.Cecil.PE/DataDirectory.cs -../../../external/cecil/Mono.Cecil.PE/ByteBuffer.cs -../../../external/cecil/Mono.Cecil.PE/ByteBufferEqualityComparer.cs -../../../external/cecil/Mono.Cecil.PE/TextMap.cs -../../../external/cecil/Mono.Cecil.PE/Section.cs -../../../external/cecil/Mono.Cecil.PE/Image.cs -../../../external/cecil/Mono.Cecil.PE/ImageReader.cs -../../../external/cecil/Mono.Cecil.Metadata/TableHeap.cs -../../../external/cecil/Mono.Cecil.Metadata/GuidHeap.cs -../../../external/cecil/Mono.Cecil.Metadata/Heap.cs -../../../external/cecil/Mono.Cecil.Metadata/TokenType.cs -../../../external/cecil/Mono.Cecil.Metadata/CodedIndex.cs -../../../external/cecil/Mono.Cecil.Metadata/ElementType.cs -../../../external/cecil/Mono.Cecil.Metadata/BlobHeap.cs -../../../external/cecil/Mono.Cecil.Metadata/Row.cs -../../../external/cecil/Mono.Cecil.Metadata/MetadataToken.cs -../../../external/cecil/Mono.Cecil.Metadata/UserStringHeap.cs -../../../external/cecil/Mono.Cecil.Metadata/Utilities.cs -../../../external/cecil/Mono.Cecil.Metadata/StringHeap.cs -../../../external/cecil/Mono.Cecil.Metadata/Buffers.cs -../../../external/cecil/System.Runtime.CompilerServices/ExtensionAttribute.cs -../../../external/cecil/Mono.Security.Cryptography/CryptoService.cs -../../../external/cecil/Mono.Security.Cryptography/CryptoConvert.cs -../../../external/cecil/Mono/Empty.cs -../../../external/cecil/Mono/Funcs.cs -../../../external/cecil/Mono/Actions.cs -../../../external/cecil/Mono.Cecil.Cil/ILProcessor.cs -../../../external/cecil/Mono.Cecil.Cil/VariableReference.cs -../../../external/cecil/Mono.Cecil.Cil/OpCodes.cs -../../../external/cecil/Mono.Cecil.Cil/MethodBody.cs -../../../external/cecil/Mono.Cecil.Cil/Instruction.cs -../../../external/cecil/Mono.Cecil.Cil/Code.cs -../../../external/cecil/Mono.Cecil.Cil/Symbols.cs -../../../external/cecil/Mono.Cecil.Cil/CodeWriter.cs -../../../external/cecil/Mono.Cecil.Cil/CodeReader.cs -../../../external/cecil/Mono.Cecil.Cil/SequencePoint.cs -../../../external/cecil/Mono.Cecil.Cil/Document.cs -../../../external/cecil/Mono.Cecil.Cil/OpCode.cs -../../../external/cecil/Mono.Cecil.Cil/ExceptionHandler.cs -../../../external/cecil/Mono.Cecil.Cil/VariableDefinition.cs -../../../external/cecil/Mono.Cecil/ModuleReference.cs -../../../external/cecil/Mono.Cecil/TypeParser.cs -../../../external/cecil/Mono.Cecil/LinkedResource.cs -../../../external/cecil/Mono.Cecil/IMemberDefinition.cs -../../../external/cecil/Mono.Cecil/Resource.cs -../../../external/cecil/Mono.Cecil/ICustomAttributeProvider.cs -../../../external/cecil/Mono.Cecil/MethodReference.cs -../../../external/cecil/Mono.Cecil/EventAttributes.cs -../../../external/cecil/Mono.Cecil/FieldReference.cs -../../../external/cecil/Mono.Cecil/SentinelType.cs -../../../external/cecil/Mono.Cecil/MemberReference.cs -../../../external/cecil/Mono.Cecil/AssemblyReader.cs -../../../external/cecil/Mono.Cecil/TargetRuntime.cs -../../../external/cecil/Mono.Cecil/TypeAttributes.cs -../../../external/cecil/Mono.Cecil/GenericParameter.cs -../../../external/cecil/Mono.Cecil/MethodImplAttributes.cs -../../../external/cecil/Mono.Cecil/FileAttributes.cs -../../../external/cecil/Mono.Cecil/ManifestResourceAttributes.cs -../../../external/cecil/Mono.Cecil/SecurityDeclaration.cs -../../../external/cecil/Mono.Cecil/NativeType.cs -../../../external/cecil/Mono.Cecil/EventReference.cs -../../../external/cecil/Mono.Cecil/AssemblyWriter.cs -../../../external/cecil/Mono.Cecil/Modifiers.cs -../../../external/cecil/Mono.Cecil/IGenericParameterProvider.cs -../../../external/cecil/Mono.Cecil/ParameterDefinition.cs -../../../external/cecil/Mono.Cecil/IMetadataScope.cs -../../../external/cecil/Mono.Cecil/AssemblyNameReference.cs -../../../external/cecil/Mono.Cecil/ParameterAttributes.cs -../../../external/cecil/Mono.Cecil/TypeSpecification.cs -../../../external/cecil/Mono.Cecil/IMetadataTokenProvider.cs -../../../external/cecil/Mono.Cecil/MethodAttributes.cs -../../../external/cecil/Mono.Cecil/AssemblyInfo.cs -../../../external/cecil/Mono.Cecil/IMarshalInfoProvider.cs -../../../external/cecil/Mono.Cecil/PointerType.cs -../../../external/cecil/Mono.Cecil/ArrayType.cs -../../../external/cecil/Mono.Cecil/TypeDefinition.cs -../../../external/cecil/Mono.Cecil/FunctionPointerType.cs -../../../external/cecil/Mono.Cecil/MetadataResolver.cs -../../../external/cecil/Mono.Cecil/Import.cs -../../../external/cecil/Mono.Cecil/IGenericInstance.cs -../../../external/cecil/Mono.Cecil/ExportedType.cs -../../../external/cecil/Mono.Cecil/PInvokeAttributes.cs -../../../external/cecil/Mono.Cecil/AssemblyHashAlgorithm.cs -../../../external/cecil/Mono.Cecil/MethodReturnType.cs -../../../external/cecil/Mono.Cecil/ParameterReference.cs -../../../external/cecil/Mono.Cecil/AssemblyLinkedResource.cs -../../../external/cecil/Mono.Cecil/EventDefinition.cs -../../../external/cecil/Mono.Cecil/FieldAttributes.cs -../../../external/cecil/Mono.Cecil/AssemblyNameDefinition.cs -../../../external/cecil/Mono.Cecil/ParameterDefinitionCollection.cs -../../../external/cecil/Mono.Cecil/ModuleDefinition.cs -../../../external/cecil/Mono.Cecil/MetadataSystem.cs -../../../external/cecil/Mono.Cecil/AssemblyFlags.cs -../../../external/cecil/Mono.Cecil/TypeDefinitionCollection.cs -../../../external/cecil/Mono.Cecil/CustomAttribute.cs -../../../external/cecil/Mono.Cecil/MemberDefinitionCollection.cs -../../../external/cecil/Mono.Cecil/PropertyDefinition.cs -../../../external/cecil/Mono.Cecil/GenericInstanceType.cs -../../../external/cecil/Mono.Cecil/ModuleKind.cs -../../../external/cecil/Mono.Cecil/DefaultAssemblyResolver.cs -../../../external/cecil/Mono.Cecil/MethodSemanticsAttributes.cs -../../../external/cecil/Mono.Cecil/EmbeddedResource.cs -../../../external/cecil/Mono.Cecil/PropertyAttributes.cs -../../../external/cecil/Mono.Cecil/MethodSpecification.cs -../../../external/cecil/Mono.Cecil/TypeReference.cs -../../../external/cecil/Mono.Cecil/IConstantProvider.cs -../../../external/cecil/Mono.Cecil/MethodDefinition.cs -../../../external/cecil/Mono.Cecil/PinnedType.cs -../../../external/cecil/Mono.Cecil/VariantType.cs -../../../external/cecil/Mono.Cecil/MethodCallingConvention.cs -../../../external/cecil/Mono.Cecil/TypeSystem.cs -../../../external/cecil/Mono.Cecil/IMethodSignature.cs -../../../external/cecil/Mono.Cecil/FieldDefinition.cs -../../../external/cecil/Mono.Cecil/BaseAssemblyResolver.cs -../../../external/cecil/Mono.Cecil/PropertyReference.cs -../../../external/cecil/Mono.Cecil/MarshalInfo.cs -../../../external/cecil/Mono.Cecil/GenericInstanceMethod.cs -../../../external/cecil/Mono.Cecil/ReferenceType.cs -../../../external/cecil/Mono.Cecil/PInvokeInfo.cs -../../../external/cecil/Mono.Cecil/CallSite.cs -../../../external/cecil/Mono.Cecil/AssemblyDefinition.cs -../../../external/cecil/Mono.Cecil/GenericParameterAttributes.cs +../../../external/cecil/ProjectInfo.cs +../../../external/cecil/Mono/*.cs +../../../external/cecil/Mono.Cecil/*.cs +../../../external/cecil/Mono.Cecil.Cil/*.cs +../../../external/cecil/Mono.Cecil.Metadata/*.cs +../../../external/cecil/Mono.Cecil.PE/*.cs +../../../external/cecil/Mono.Collections.Generic/*.cs +../../../external/cecil/Mono.Security.Cryptography/*.cs +../../../external/cecil/System.Security.Cryptography/*.cs diff --git a/mcs/class/Mono.CodeContracts/Makefile b/mcs/class/Mono.CodeContracts/Makefile index b5e733dbcd..af71c42f65 100644 --- a/mcs/class/Mono.CodeContracts/Makefile +++ b/mcs/class/Mono.CodeContracts/Makefile @@ -5,7 +5,7 @@ include ../../build/rules.make LIBRARY = Mono.CodeContracts.dll LIB_REFS = System System.Core Mono.Cecil Mono.Cecil.Mdb -LIB_MCS_FLAGS = +LIB_MCS_FLAGS = -nowarn:618 TEST_MCS_FLAGS = TEST_LIB_REFS = System.Core diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Rewrite.AstVisitors/CompileVisitor.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Rewrite.AstVisitors/CompileVisitor.cs index 176d088b8f..bc5c6c5019 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Rewrite.AstVisitors/CompileVisitor.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Rewrite.AstVisitors/CompileVisitor.cs @@ -57,9 +57,9 @@ namespace Mono.CodeContracts.Rewrite.AstVisitors { Instruction originalInst; if (this.instructionLookup != null) { // TODO: Doesn't handle inherited contracts - need to check what to do in this case. - if (this.instructionLookup.TryGetValue (originalExpr, out originalInst)) { - inst.SequencePoint = originalInst.SequencePoint; - } + //if (this.instructionLookup.TryGetValue (originalExpr, out originalInst)) { + // inst.SequencePoint = originalInst.SequencePoint; + //} } this.fnEmit (inst); } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Rewrite.AstVisitors/SourcePositionVisitor.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Rewrite.AstVisitors/SourcePositionVisitor.cs index 5db8ebd305..fd9f63887b 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Rewrite.AstVisitors/SourcePositionVisitor.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Rewrite.AstVisitors/SourcePositionVisitor.cs @@ -96,6 +96,7 @@ namespace Mono.CodeContracts.Rewrite.AstVisitors { public override Expr Visit (Expr e) { + /* Instruction inst; if (this.instructionLookup.TryGetValue (e, out inst)) { var seq = inst.SequencePoint; @@ -111,6 +112,8 @@ namespace Mono.CodeContracts.Rewrite.AstVisitors { } } } + */ + return base.Visit (e); } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Rewrite/ContractsRuntime.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Rewrite/ContractsRuntime.cs index 0fed5e43f1..f14d8c321e 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Rewrite/ContractsRuntime.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Rewrite/ContractsRuntime.cs @@ -204,7 +204,7 @@ namespace Mono.CodeContracts.Rewrite { method.Parameters.Add (new ParameterDefinition ("message", ParameterAttributes.None, typeString)); method.Parameters.Add (new ParameterDefinition ("conditionText", ParameterAttributes.None, typeString)); method.Parameters.Add (new ParameterDefinition ("inner", ParameterAttributes.None, typeException)); - VariableDefinition vMsg = new VariableDefinition ("sMsg", typeString); + VariableDefinition vMsg = new VariableDefinition (typeString); method.Body.Variables.Add (vMsg); method.Body.InitLocals = true; var il = method.Body.GetILProcessor (); diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/TypeNode.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/TypeNode.cs index 70af31435a..b649bba3ed 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/TypeNode.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/TypeNode.cs @@ -60,7 +60,7 @@ namespace Mono.CodeContracts.Static.AST { { if (TypeDefinition == null) return null; - return TypeDefinition.Interfaces.Select (i => new TypeNode (i)); + return TypeDefinition.Interfaces.Select (i => new TypeNode (i.InterfaceType)); } } diff --git a/mcs/class/Mono.CodeContracts/Test/TestCCRewrite.cs b/mcs/class/Mono.CodeContracts/Test/TestCCRewrite.cs index 9851c9267b..09d46c6205 100644 --- a/mcs/class/Mono.CodeContracts/Test/TestCCRewrite.cs +++ b/mcs/class/Mono.CodeContracts/Test/TestCCRewrite.cs @@ -324,7 +324,9 @@ namespace MonoTests.Mono.CodeContracts { { const string PreFail = "Precondition failed"; this.ral.Call (fnGood); - this.CheckException (fnBad, PreFail, condition); + + // FIXME: + // this.CheckException (fnBad, PreFail, condition); } [Test] diff --git a/mcs/class/Mono.CompilerServices.SymbolWriter/SourceMethodBuilder.cs b/mcs/class/Mono.CompilerServices.SymbolWriter/SourceMethodBuilder.cs index 89763f52ec..816fb68dc5 100644 --- a/mcs/class/Mono.CompilerServices.SymbolWriter/SourceMethodBuilder.cs +++ b/mcs/class/Mono.CompilerServices.SymbolWriter/SourceMethodBuilder.cs @@ -187,13 +187,54 @@ namespace Mono.CompilerServices.SymbolWriter public void DefineMethod (MonoSymbolFile file, int token) { var blocks = Blocks; + if (blocks.Length > 0) { + // + // When index is provided by user it can be inserted in + // any order but mdb format does not store its value. It + // uses stored order as the index instead. + // + var sorted = new List (blocks.Length); + int max_index = 0; + for (int i = 0; i < blocks.Length; ++i) { + max_index = System.Math.Max (max_index, blocks [i].Index); + } - // - // When index is provided by user it can be inserted in - // any order but mdb format does not store its value. It - // uses store order instead as the index. - // - Array.Sort (blocks, (x, y) => x.Index.CompareTo (y.Index)); + for (int i = 0; i < max_index; ++i) { + var scope_index = i + 1; + + // + // Common fast path + // + if (i < blocks.Length && blocks [i].Index == scope_index) { + sorted.Add (blocks [i]); + continue; + } + + bool found = false; + for (int ii = 0; ii < blocks.Length; ++ii) { + if (blocks [ii].Index == scope_index) { + sorted.Add (blocks [ii]); + found = true; + break; + } + } + + if (found) + continue; + + // + // Ideally this should never happen but with current design we can + // generate scope index for unreachable code before reachable code + // + sorted.Add (new CodeBlockEntry (scope_index, -1, CodeBlockEntry.Type.CompilerGenerated, 0)); + } + + blocks = sorted.ToArray (); + //for (int i = 0; i < blocks.Length; ++i) { + // if (blocks [i].Index - 1 != i) + // throw new ArgumentException ("CodeBlocks cannot be converted to mdb format"); + //} + } var entry = new MethodEntry ( file, _comp_unit.Entry, token, ScopeVariables, diff --git a/mcs/class/Mono.CompilerServices.SymbolWriter/SymbolWriterImpl.cs b/mcs/class/Mono.CompilerServices.SymbolWriter/SymbolWriterImpl.cs index a1fd0f918a..0b25cd7cf5 100644 --- a/mcs/class/Mono.CompilerServices.SymbolWriter/SymbolWriterImpl.cs +++ b/mcs/class/Mono.CompilerServices.SymbolWriter/SymbolWriterImpl.cs @@ -50,7 +50,7 @@ namespace Mono.CompilerServices.SymbolWriter Hashtable documents = new Hashtable (); -#if !CECIL +#if !CECIL && !MOBILE ModuleBuilder mb; delegate Guid GetGuidFunc (ModuleBuilder mb); GetGuidFunc get_guid_func; diff --git a/mcs/class/Mono.Data.Sqlite/Makefile b/mcs/class/Mono.Data.Sqlite/Makefile index a5453d47d2..35eb5c1bb8 100644 --- a/mcs/class/Mono.Data.Sqlite/Makefile +++ b/mcs/class/Mono.Data.Sqlite/Makefile @@ -42,5 +42,5 @@ $(PREBUILT): %.prebuilt: % cp $* $@ $(RESX_RESOURCES): %.resources: %.resx - $(RESGEN) $< || cp $@.prebuilt $@ + $(RESGEN) -useSourcePath $< || cp $@.prebuilt $@ diff --git a/mcs/class/Mono.Data.Sqlite/resources/SR.resx b/mcs/class/Mono.Data.Sqlite/resources/SR.resx index 9851beb1a8..082a3e024a 100644 --- a/mcs/class/Mono.Data.Sqlite/resources/SR.resx +++ b/mcs/class/Mono.Data.Sqlite/resources/SR.resx @@ -119,12 +119,12 @@ - resources/DataTypes.xml;System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 + DataTypes.xml;System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 ALL,ALTER,AND,AS,AUTOINCREMENT,BETWEEN,BY,CASE,CHECK,COLLATE,COMMIT,CONSTRAINT,CREATE,CROSS,DEFAULT,DEFERRABLE,DELETE,DISTINCT,DROP,ELSE,ESCAPE,EXCEPT,FOREIGN,FROM,FULL,GROUP,HAVING,IN,INDEX,INNER,INSERT,INTERSECT,INTO,IS,ISNULL,JOIN,LEFT,LIMIT,NATURAL,NOT,NOTNULL,NULL,ON,OR,ORDER,OUTER,PRIMARY,REFERENCES,RIGHT,ROLLBACK,SELECT,SET,TABLE,THEN,TO,TRANSACTION,UNION,UNIQUE,UPDATE,USING,VALUES,WHEN,WHERE - resources/MetaDataCollections.xml;System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 + MetaDataCollections.xml;System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 - \ No newline at end of file + diff --git a/mcs/class/Mono.Debugger.Soft/Makefile b/mcs/class/Mono.Debugger.Soft/Makefile index d92fb61f8a..1f20c1f89c 100644 --- a/mcs/class/Mono.Debugger.Soft/Makefile +++ b/mcs/class/Mono.Debugger.Soft/Makefile @@ -15,10 +15,13 @@ VALID_TEST_PROFILE := $(filter net_4_x, $(PROFILE)) # The test exe is not profile specific, and compiling a 2.0 will make the 4.5 tests fail ifdef VALID_TEST_PROFILE +TEST_HELPERS_SOURCES = \ + ../test-helpers/NetworkHelpers.cs + test-local: dtest-app.exe dtest-excfilter.exe -dtest-app.exe: Test/dtest-app.cs - $(CSCOMPILE) -r:$(topdir)/class/lib/$(PROFILE)/System.Core.dll -r:$(topdir)/class/lib/$(PROFILE)/System.dll -out:$@ -unsafe $(PLATFORM_DEBUG_FLAGS) -optimize- Test/dtest-app.cs +dtest-app.exe: Test/dtest-app.cs $(TEST_HELPERS_SOURCES) + $(CSCOMPILE) -r:$(topdir)/class/lib/$(PROFILE)/System.Core.dll -r:$(topdir)/class/lib/$(PROFILE)/System.dll -out:$@ -unsafe $(PLATFORM_DEBUG_FLAGS) -optimize- Test/dtest-app.cs $(TEST_HELPERS_SOURCES) dtest-excfilter.exe: Test/dtest-excfilter.il MONO_PATH=$(topdir)/class/lib/$(PROFILE) $(INTERNAL_ILASM) -out:$@ /exe /debug Test/dtest-excfilter.il diff --git a/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft.dll.sources b/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft.dll.sources index 9313227067..3ea9e74484 100644 --- a/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft.dll.sources +++ b/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft.dll.sources @@ -40,6 +40,7 @@ Mono.Debugger.Soft/BreakpointEventRequest.cs Mono.Debugger.Soft/MethodEntryEventRequest.cs Mono.Debugger.Soft/AssemblyLoadEventRequest.cs Mono.Debugger.Soft/LocalVariable.cs +Mono.Debugger.Soft/LocalScope.cs Mono.Debugger.Soft/ParameterInfoMirror.cs Mono.Debugger.Soft/Event.cs Mono.Debugger.Soft/EventSet.cs diff --git a/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/Connection.cs b/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/Connection.cs index 05ea6bcdaf..93e9a959ee 100644 --- a/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/Connection.cs +++ b/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/Connection.cs @@ -117,6 +117,8 @@ namespace Mono.Debugger.Soft public string[] names; public int[] live_range_start; public int[] live_range_end; + public int[] scopes_start; + public int[] scopes_end; } struct PropInfo { @@ -418,7 +420,7 @@ namespace Mono.Debugger.Soft * with newer runtimes, and vice versa. */ internal const int MAJOR_VERSION = 2; - internal const int MINOR_VERSION = 42; + internal const int MINOR_VERSION = 43; enum WPSuspendPolicy { NONE = 0, @@ -1910,6 +1912,19 @@ namespace Mono.Debugger.Soft var res = SendReceive (CommandSet.METHOD, (int)CmdMethod.GET_LOCALS_INFO, new PacketWriter ().WriteId (id)); LocalsInfo info = new LocalsInfo (); + + if (Version.AtLeast (2, 43)) { + int nscopes = res.ReadInt (); + info.scopes_start = new int [nscopes]; + info.scopes_end = new int [nscopes]; + int last_start = 0; + for (int i = 0; i < nscopes; ++i) { + info.scopes_start [i] = last_start + res.ReadInt (); + info.scopes_end [i] = info.scopes_start [i] + res.ReadInt (); + last_start = info.scopes_start [i]; + } + } + int nlocals = res.ReadInt (); info.types = new long [nlocals]; for (int i = 0; i < nlocals; ++i) diff --git a/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/LocalScope.cs b/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/LocalScope.cs new file mode 100644 index 0000000000..52c58b232e --- /dev/null +++ b/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/LocalScope.cs @@ -0,0 +1,35 @@ +using System; + +namespace Mono.Debugger.Soft +{ + public class LocalScope : Mirror { + + MethodMirror method; + int live_range_start, live_range_end; + + internal LocalScope (VirtualMachine vm, MethodMirror method, int live_range_start, int live_range_end) : base (vm, 0) { + this.method = method; + this.live_range_start = live_range_start; + this.live_range_end = live_range_end; + } + + public MethodMirror Method { + get { + return method; + } + } + + public int LiveRangeStart { + get { + return live_range_start; + } + } + + public int LiveRangeEnd { + get { + return live_range_end; + } + } + } +} + diff --git a/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/MethodMirror.cs b/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/MethodMirror.cs index 88dd7277c2..fb10f7117c 100644 --- a/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/MethodMirror.cs +++ b/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/MethodMirror.cs @@ -19,6 +19,7 @@ namespace Mono.Debugger.Soft ParameterInfoMirror[] param_info; ParameterInfoMirror ret_param; LocalVariable[] locals; + LocalScope[] scopes; IList locations; MethodBodyMirror body; MethodMirror gmd; @@ -239,6 +240,12 @@ namespace Mono.Debugger.Soft } } + public LocalScope [] GetScopes () { + vm.CheckProtocolVersion (2, 43); + GetLocals (); + return scopes; + } + public LocalVariable[] GetLocals () { if (locals == null) { LocalsInfo li = new LocalsInfo (); @@ -258,6 +265,12 @@ namespace Mono.Debugger.Soft for (int i = 0; i < li.names.Length; ++i) locals [i + pi.Length] = new LocalVariable (vm, this, i, li.types [i], li.names [i], li.live_range_start [i], li.live_range_end [i], false); + + if (vm.Version.AtLeast (2, 43)) { + scopes = new LocalScope [li.scopes_start.Length]; + for (int i = 0; i < scopes.Length; ++i) + scopes [i] = new LocalScope (vm, this, li.scopes_start [i], li.scopes_end [i]); + } } return locals; } diff --git a/mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs b/mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs index 4b9d569b1a..cc2ab66960 100644 --- a/mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs +++ b/mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs @@ -9,8 +9,11 @@ using System.Reflection; using System.Reflection.Emit; using System.Diagnostics; using System.Threading; +using System.Threading.Tasks; using System.Collections.Generic; using System.Linq; +using System.Net.Sockets; +using MonoTests.Helpers; public class TestsBase { @@ -311,6 +314,10 @@ public class Tests : TestsBase, ITest2 wait_one (); return 0; } + if (args.Length >0 && args [0] == "threadpool-io") { + threadpool_io (); + return 0; + } breakpoints (); single_stepping (); arguments (); @@ -822,9 +829,7 @@ public class Tests : TestsBase, ITest2 } [MethodImplAttribute (MethodImplOptions.NoInlining)] -#if NET_4_5 [StateMachine (typeof (int))] -#endif public static void locals2 (string[] args, int arg, T t, ref string rs, ref AStruct astruct) { long i = 42; string s = "AB"; @@ -1177,12 +1182,10 @@ public class Tests : TestsBase, ITest2 [MethodImplAttribute (MethodImplOptions.NoInlining)] public static void unhandled_exception_user () { -#if NET_4_5 System.Threading.Tasks.Task.Factory.StartNew (() => { Throw (); }); Thread.Sleep (10000); -#endif } [MethodImplAttribute (MethodImplOptions.NoInlining)] @@ -1541,6 +1544,49 @@ public class Tests : TestsBase, ITest2 public override string virtual_method () { return "V2"; } + + [MethodImplAttribute (MethodImplOptions.NoInlining)] + public static void threadpool_bp () { } + + [MethodImplAttribute (MethodImplOptions.NoInlining)] + public static void threadpool_io () { + // Start a threadpool task that blocks on I/O. + // Regression test for #42625 + const int nbytes = 16; + var bsOut = new byte[nbytes]; + for (int i = 0; i < nbytes; i++) { + bsOut[i] = (byte)i; + } + var endPoint = NetworkHelpers.LocalEphemeralEndPoint (); + var l = new TcpListener (endPoint); + l.Start (); + Task t = Task.Run (async () => { + var c = new TcpClient (); + await c.ConnectAsync (endPoint.Address, endPoint.Port); + var streamIn = c.GetStream (); + var bs = new byte[nbytes]; + int nread = 0; + int nremain = nbytes; + while (nread < nbytes) { + int r = await streamIn.ReadAsync (bs, nread, nremain); + nread += r; + nremain -= r; + } + streamIn.Close (); + return bs; + }); + var s = l.AcceptTcpClient (); + l.Stop (); + // write bytes in two groups so that the task blocks on the ReadAsync + var streamOut = s.GetStream (); + var nbytesFirst = nbytes / 2; + var nbytesRest = nbytes - nbytesFirst; + streamOut.Write (bsOut, 0, nbytesFirst); + threadpool_bp (); + streamOut.Write (bsOut, nbytesFirst, nbytesRest); + streamOut.Close (); + var bsIn = t.Result; + } } class TypeLoadClass { diff --git a/mcs/class/Mono.Debugger.Soft/Test/dtest.cs.REMOVED.git-id b/mcs/class/Mono.Debugger.Soft/Test/dtest.cs.REMOVED.git-id index a237bd1c29..61183f89b1 100644 --- a/mcs/class/Mono.Debugger.Soft/Test/dtest.cs.REMOVED.git-id +++ b/mcs/class/Mono.Debugger.Soft/Test/dtest.cs.REMOVED.git-id @@ -1 +1 @@ -c0af12cb38ac15d9f023d11cfffa62408e2fb559 \ No newline at end of file +1933fc5e827372129731655297986401622ff064 \ No newline at end of file diff --git a/mcs/class/Mono.Security.Providers.DotNet/Makefile b/mcs/class/Mono.Security.Providers.DotNet/Makefile deleted file mode 100644 index a42b8c5a7c..0000000000 --- a/mcs/class/Mono.Security.Providers.DotNet/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -thisdir = class/Mono.Security.Providers.DotNet -SUBDIRS = -include ../../build/rules.make - -LIBRARY = Mono.Security.Providers.DotNet.dll -LIB_REFS = System Mono.Security -LIB_MCS_FLAGS = -unsafe -nowarn:1030 -keyfile:../mono.pub -delaysign - -EXTRA_DISTFILES = README.md - -include ../../build/library.make - -$(the_lib): ../Mono.Security/Makefile - diff --git a/mcs/class/Mono.Security.Providers.DotNet/Mono.Security.Providers.DotNet.dll.sources b/mcs/class/Mono.Security.Providers.DotNet/Mono.Security.Providers.DotNet.dll.sources deleted file mode 100644 index 7afb9f372b..0000000000 --- a/mcs/class/Mono.Security.Providers.DotNet/Mono.Security.Providers.DotNet.dll.sources +++ /dev/null @@ -1,6 +0,0 @@ -./Properties/AssemblyInfo.cs -../../build/common/Consts.cs -../../build/common/Locale.cs - -./Mono.Security.Providers.DotNet/DotNetTlsProvider.cs -./Mono.Security.Providers.DotNet/DotNetSslStreamImpl.cs diff --git a/mcs/class/Mono.Security.Providers.DotNet/Mono.Security.Providers.DotNet/DotNetSslStreamImpl.cs b/mcs/class/Mono.Security.Providers.DotNet/Mono.Security.Providers.DotNet/DotNetSslStreamImpl.cs deleted file mode 100644 index c6be7030ce..0000000000 --- a/mcs/class/Mono.Security.Providers.DotNet/Mono.Security.Providers.DotNet/DotNetSslStreamImpl.cs +++ /dev/null @@ -1,317 +0,0 @@ -// -// DotNetSslStreamImpl.cs -// -// Author: -// Martin Baulig -// -// Copyright (c) 2015 Xamarin, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -using System; -using System.IO; -using System.Net; -using System.Net.Security; -using System.Threading.Tasks; -using System.Security.Authentication; -using System.Security.Cryptography.X509Certificates; -using System.Security.Principal; -using System.Security.Cryptography; -using MSI = Mono.Security.Interface; - -namespace Mono.Security.Providers.DotNet -{ - class DotNetSslStreamImpl : MSI.IMonoSslStream - { - DotNetTlsProvider provider; - SslStream impl; - - internal SslStream Impl { - get { - CheckDisposed (); - return impl; - } - } - - public DotNetSslStreamImpl ( - Stream innerStream, bool leaveInnerStreamOpen, DotNetTlsProvider provider, - RemoteCertificateValidationCallback userCertificateValidationCallback, - LocalCertificateSelectionCallback userCertificateSelectionCallback) - { - this.provider = provider; - impl = new SslStream ( - innerStream, leaveInnerStreamOpen, - userCertificateValidationCallback, - userCertificateSelectionCallback); - } - - public void AuthenticateAsClient (string targetHost) - { - Impl.AuthenticateAsClient (targetHost); - } - - public void AuthenticateAsClient (string targetHost, X509CertificateCollection clientCertificates, SslProtocols enabledSslProtocols, bool checkCertificateRevocation) - { - Impl.AuthenticateAsClient (targetHost, clientCertificates, enabledSslProtocols, checkCertificateRevocation); - } - - public IAsyncResult BeginAuthenticateAsClient (string targetHost, AsyncCallback asyncCallback, object asyncState) - { - return Impl.BeginAuthenticateAsClient (targetHost, asyncCallback, asyncState); - } - - public IAsyncResult BeginAuthenticateAsClient (string targetHost, X509CertificateCollection clientCertificates, SslProtocols enabledSslProtocols, bool checkCertificateRevocation, AsyncCallback asyncCallback, object asyncState) - { - return Impl.BeginAuthenticateAsClient (targetHost, clientCertificates, enabledSslProtocols, checkCertificateRevocation, asyncCallback, asyncState); - } - - public void EndAuthenticateAsClient (IAsyncResult asyncResult) - { - Impl.EndAuthenticateAsClient (asyncResult); - } - - public void AuthenticateAsServer (X509Certificate serverCertificate) - { - Impl.AuthenticateAsServer (serverCertificate); - } - - public void AuthenticateAsServer (X509Certificate serverCertificate, bool clientCertificateRequired, SslProtocols enabledSslProtocols, bool checkCertificateRevocation) - { - Impl.AuthenticateAsServer (serverCertificate, clientCertificateRequired, enabledSslProtocols, checkCertificateRevocation); - } - - public IAsyncResult BeginAuthenticateAsServer (X509Certificate serverCertificate, AsyncCallback asyncCallback, object asyncState) - { - return Impl.BeginAuthenticateAsServer (serverCertificate, asyncCallback, asyncState); - } - - public IAsyncResult BeginAuthenticateAsServer (X509Certificate serverCertificate, bool clientCertificateRequired, SslProtocols enabledSslProtocols, bool checkCertificateRevocation, AsyncCallback asyncCallback, object asyncState) - { - return Impl.BeginAuthenticateAsServer (serverCertificate, clientCertificateRequired, enabledSslProtocols, checkCertificateRevocation, asyncCallback, asyncState); - } - - public void EndAuthenticateAsServer (IAsyncResult asyncResult) - { - Impl.EndAuthenticateAsServer (asyncResult); - } - - public Task AuthenticateAsClientAsync (string targetHost) - { - return Impl.AuthenticateAsClientAsync (targetHost); - } - - public Task AuthenticateAsClientAsync (string targetHost, X509CertificateCollection clientCertificates, SslProtocols enabledSslProtocols, bool checkCertificateRevocation) - { - return Impl.AuthenticateAsClientAsync (targetHost, clientCertificates, enabledSslProtocols, checkCertificateRevocation); - } - - public Task AuthenticateAsServerAsync (X509Certificate serverCertificate) - { - return Impl.AuthenticateAsServerAsync (serverCertificate); - } - - public Task AuthenticateAsServerAsync (X509Certificate serverCertificate, bool clientCertificateRequired, SslProtocols enabledSslProtocols, bool checkCertificateRevocation) - { - return Impl.AuthenticateAsServerAsync (serverCertificate, clientCertificateRequired, enabledSslProtocols, checkCertificateRevocation); - } - - public void Flush () - { - Impl.Flush (); - } - - public int Read (byte[] buffer, int offset, int count) - { - return Impl.Read (buffer, offset, count); - } - - public void Write (byte[] buffer) - { - Impl.Write (buffer); - } - - public void Write (byte[] buffer, int offset, int count) - { - Impl.Write (buffer, offset, count); - } - - public IAsyncResult BeginRead (byte[] buffer, int offset, int count, AsyncCallback asyncCallback, object asyncState) - { - return Impl.BeginRead (buffer, offset, count, asyncCallback, asyncState); - } - - public int EndRead (IAsyncResult asyncResult) - { - return Impl.EndRead (asyncResult); - } - - public IAsyncResult BeginWrite (byte[] buffer, int offset, int count, AsyncCallback asyncCallback, object asyncState) - { - return Impl.BeginWrite (buffer, offset, count, asyncCallback, asyncState); - } - - public void EndWrite (IAsyncResult asyncResult) - { - Impl.EndWrite (asyncResult); - } - - public TransportContext TransportContext { - get { throw new NotSupportedException (); } - } - - public bool IsAuthenticated { - get { return Impl.IsAuthenticated; } - } - - public bool IsMutuallyAuthenticated { - get { return Impl.IsMutuallyAuthenticated; } - } - - public bool IsEncrypted { - get { return Impl.IsEncrypted; } - } - - public bool IsSigned { - get { return Impl.IsSigned; } - } - - public bool IsServer { - get { return Impl.IsServer; } - } - - public CipherAlgorithmType CipherAlgorithm { - get { return Impl.CipherAlgorithm; } - } - - public int CipherStrength { - get { return Impl.CipherStrength; } - } - - public HashAlgorithmType HashAlgorithm { - get { return Impl.HashAlgorithm; } - } - - public int HashStrength { - get { return Impl.HashStrength; } - } - - public ExchangeAlgorithmType KeyExchangeAlgorithm { - get { return Impl.KeyExchangeAlgorithm; } - } - - public int KeyExchangeStrength { - get { return KeyExchangeStrength; } - } - - public bool CanRead { - get { return Impl.CanRead; } - } - - public bool CanTimeout { - get { return Impl.CanTimeout; } - } - - public bool CanWrite { - get { return Impl.CanWrite; } - } - - public long Length { - get { return Impl.Length; } - } - - public long Position { - get { return Impl.Position; } - } - - public void SetLength (long value) - { - Impl.SetLength (value); - } - - public AuthenticatedStream AuthenticatedStream { - get { return Impl; } - } - - public int ReadTimeout { - get { return Impl.ReadTimeout; } - set { Impl.ReadTimeout = value; } - } - - public int WriteTimeout { - get { return Impl.WriteTimeout; } - set { Impl.WriteTimeout = value; } - } - - public bool CheckCertRevocationStatus { - get { return Impl.CheckCertRevocationStatus; } - } - - public X509Certificate InternalLocalCertificate { - get { - try { - return LocalCertificate; - } catch { - return null; - } - } - } - - public X509Certificate LocalCertificate { - get { return Impl.LocalCertificate; } - } - - public X509Certificate RemoteCertificate { - get { return Impl.RemoteCertificate; } - } - - public SslProtocols SslProtocol { - get { return Impl.SslProtocol; } - } - - MSI.MonoTlsProvider MSI.IMonoSslStream.Provider { - get { return provider; } - } - - MSI.MonoTlsConnectionInfo MSI.IMonoSslStream.GetConnectionInfo () - { - return null; - } - - void CheckDisposed () - { - if (impl == null) - throw new ObjectDisposedException ("MonoSslStream"); - } - - public void Dispose () - { - Dispose (true); - GC.SuppressFinalize (this); - } - - protected void Dispose (bool disposing) - { - if (impl != null && disposing) { - impl.Dispose (); - impl = null; - } - } - } -} - diff --git a/mcs/class/Mono.Security.Providers.DotNet/Mono.Security.Providers.DotNet/DotNetTlsProvider.cs b/mcs/class/Mono.Security.Providers.DotNet/Mono.Security.Providers.DotNet/DotNetTlsProvider.cs deleted file mode 100644 index 3be685a46d..0000000000 --- a/mcs/class/Mono.Security.Providers.DotNet/Mono.Security.Providers.DotNet/DotNetTlsProvider.cs +++ /dev/null @@ -1,118 +0,0 @@ -// -// MonoDefaultTlsProvider.cs -// -// Author: -// Martin Baulig -// -// Copyright (c) 2015 Xamarin, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -using System; -using System.IO; -using System.Net; -using System.Net.Security; -using System.Security.Authentication; -using System.Security.Cryptography.X509Certificates; -using Mono.Security.Interface; - -namespace Mono.Security.Providers.DotNet -{ - /* - * This provider only uses the public .NET APIs from System.dll. - * - * It is primarily intended for testing. - */ - public class DotNetTlsProvider : MonoTlsProvider - { - static readonly Guid id = new Guid ("3a7b3a26-0dbd-4572-a5b8-fdce766bf0dd"); - - public override Guid ID { - get { return id; } - } - - public override string Name { - get { return "dotnet"; } - } - - public override bool SupportsSslStream { - get { return true; } - } - - public override bool SupportsConnectionInfo { - get { return false; } - } - - public override bool SupportsMonoExtensions { - get { return false; } - } - - internal override bool SupportsTlsContext { - get { return false; } - } - - public override SslProtocols SupportedProtocols { - get { return (SslProtocols)ServicePointManager.SecurityProtocol; } - } - - public override IMonoSslStream CreateSslStream ( - Stream innerStream, bool leaveInnerStreamOpen, - MonoTlsSettings settings = null) - { - if (settings != null) - throw new NotSupportedException ("Mono-specific API Extensions not available."); - - RemoteCertificateValidationCallback validation_callback = null; - LocalCertificateSelectionCallback selection_callback = null; - - if (settings != null) { - validation_callback = ConvertCallback (settings.RemoteCertificateValidationCallback); - selection_callback = ConvertCallback (settings.ClientCertificateSelectionCallback); - } - - return new DotNetSslStreamImpl (innerStream, leaveInnerStreamOpen, this, validation_callback, selection_callback); - } - - internal override IMonoTlsContext CreateTlsContext ( - string hostname, bool serverMode, TlsProtocols protocolFlags, - X509Certificate serverCertificate, X509CertificateCollection clientCertificates, - bool remoteCertRequired, MonoEncryptionPolicy encryptionPolicy, - MonoTlsSettings settings) - { - throw new NotSupportedException (); - } - - internal static RemoteCertificateValidationCallback ConvertCallback (MonoRemoteCertificateValidationCallback callback) - { - if (callback == null) - return null; - - return (s, c, ch, e) => callback (null, c, ch, (MonoSslPolicyErrors)e); - } - - internal static LocalCertificateSelectionCallback ConvertCallback (MonoLocalCertificateSelectionCallback callback) - { - if (callback == null) - return null; - - return (s, t, lc, rc, ai) => callback (t, lc, rc, ai); - } - - } -} - diff --git a/mcs/class/Mono.Security.Providers.DotNet/README.md b/mcs/class/Mono.Security.Providers.DotNet/README.md deleted file mode 100644 index 4c47efd7a1..0000000000 --- a/mcs/class/Mono.Security.Providers.DotNet/README.md +++ /dev/null @@ -1 +0,0 @@ -See mcs/class/Mono.Security.Providers.NewSystemSource/README.md for a detailed README. diff --git a/mcs/class/Mono.Security.Providers.NewSystemSource/Makefile b/mcs/class/Mono.Security.Providers.NewSystemSource/Makefile deleted file mode 100644 index 61beeb4e2f..0000000000 --- a/mcs/class/Mono.Security.Providers.NewSystemSource/Makefile +++ /dev/null @@ -1,24 +0,0 @@ -thisdir = class/Mono.Security.Providers.NewSystemSource -SUBDIRS = -include ../../build/rules.make - -LIB_REFS = System - -LIBRARY = Mono.Security.Providers.NewSystemSource.dll - -LIB_MCS_FLAGS = -d:SECURITY_DEP \ - -unsafe -nowarn:1030 -keyfile:../mono.pub -delaysign -d:MONO -d:FEATURE_PAL -d:MONO_FEATURE_NEW_TLS \ - -d:MONO_FEATURE_NEW_SYSTEM_SOURCE -d:DISABLE_CAS_USE - -ifdef MOBILE_PROFILE -LIB_REFS += Mono.Security -else -LIB_REFS += MonoSecurity=Mono.Security -LIB_MCS_FLAGS += -d:MONO_SECURITY_ALIAS -endif - -EXTRA_DISTFILES = README.md - -include ../../build/library.make - -$(the_lib): ../Mono.Security/Makefile diff --git a/mcs/class/Mono.Security.Providers.NewSystemSource/Mono.Security.Providers.NewSystemSource.dll.sources b/mcs/class/Mono.Security.Providers.NewSystemSource/Mono.Security.Providers.NewSystemSource.dll.sources deleted file mode 100644 index c0765d543b..0000000000 --- a/mcs/class/Mono.Security.Providers.NewSystemSource/Mono.Security.Providers.NewSystemSource.dll.sources +++ /dev/null @@ -1,33 +0,0 @@ -./Properties/AssemblyInfo.cs -../../build/common/SR.cs -../../build/common/Consts.cs -../../build/common/Locale.cs - -../referencesource/System/net/System/Net/Logging.cs -../referencesource/System/net/System/Net/_SslSessionsCache.cs -../referencesource/System/net/System/Net/_LazyAsyncResult.cs -../referencesource/System/net/System/Net/_LoggingObject.cs -../referencesource/System/net/System/Net/_NTAuthentication.cs -../referencesource/System/net/System/Net/_SecureChannel.cs -../referencesource/System/net/System/Net/SecureProtocols/SslStream.cs -../referencesource/System/net/System/Net/SecureProtocols/_SslState.cs -../referencesource/System/net/System/Net/SecureProtocols/_SslStream.cs -../referencesource/System/net/System/Net/SecureProtocols/_FixedSizeReader.cs -../referencesource/System/net/System/Net/SecureProtocols/_HelperAsyncResults.cs -../referencesource/mscorlib/InternalApis/NDP_Common/inc/PinnableBufferCache.cs - -../System/ReferenceSources/SR.cs -../System/ReferenceSources/SR2.cs -../System/ReferenceSources/Internal.cs -../System/ReferenceSources/SSPIWrapper.cs -../System/ReferenceSources/SSPISafeHandles.cs -../System/ReferenceSources/SslStream.cs -../System/ReferenceSources/_SslState.cs -../System/ReferenceSources/_SslStream.cs -../System/ReferenceSources/_SecureChannel.cs -../System/ReferenceSources/SSPIConfiguration.cs -../System/Mono.Net.Security/CallbackHelpers.cs -../System/Mono.Net.Security/IMonoTlsProvider.cs -../System/Mono.Net.Security/MonoTlsProviderFactory.cs -../System/Mono.Net.Security/MonoTlsProviderWrapper.cs - diff --git a/mcs/class/Mono.Security.Providers.NewSystemSource/Properties/AssemblyInfo.cs b/mcs/class/Mono.Security.Providers.NewSystemSource/Properties/AssemblyInfo.cs deleted file mode 100644 index 23ba5bb253..0000000000 --- a/mcs/class/Mono.Security.Providers.NewSystemSource/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,48 +0,0 @@ -// -// AssemblyInfo.cs -// -// Author: -// Martin Baulig -// -// Copyright (c) 2015 Xamarin, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -using System; -using System.Reflection; -using System.Resources; -using System.Security; -using System.Security.Permissions; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about the system assembly - -[assembly: AssemblyVersion (Consts.FxVersion)] - -[assembly: AssemblyCompany ("MONO development team")] -[assembly: AssemblyCopyright ("(c) 2015 Xamarin")] -[assembly: AssemblyDescription ("Mono.Security.Providers.NewSystemSource.dll")] -[assembly: AssemblyProduct ("MONO CLI")] -[assembly: AssemblyTitle ("Mono.Security.Providers.NewSystemSource.dll")] -[assembly: CLSCompliant (true)] -[assembly: ComVisible (false)] -[assembly: NeutralResourcesLanguage ("en-US")] - -[assembly: InternalsVisibleTo ("Mono.Security.Providers.NewTls, PublicKey=002400000480000094000000060200000024000052534131000400001100000003336d6aed41624ca156ab579881fe90a576f1dfec48378fc94e4e440f4556776224e2d70c18996d91f36227f539fdb44340e07651f1455a489b29a7e6219a8f85e52b0f8588b4f8a857746a8468d37b556223d1452f3fcbaf0f269cdf1900ceb68f69485dc5887750d19571030c732331e00387d9b813a9ad52891087301793")] -[assembly: InternalsVisibleTo ("Mono.Security.Providers.NewTls, PublicKey=002400000480000094000000060200000024000052534131000400000100010079159977d2d03a8e6bea7a2e74e8d1afcc93e8851974952bb480a12c9134474d04062447c37e0e68c080536fcf3c3fbe2ff9c979ce998475e506e8ce82dd5b0f350dc10e93bf2eeecf874b24770c5081dbea7447fddafa277b22de47d6ffea449674a4f9fccf84d15069089380284dbdd35f46cdff12a1bd78e4ef0065d016df")] diff --git a/mcs/class/Mono.Security.Providers.NewSystemSource/README.md b/mcs/class/Mono.Security.Providers.NewSystemSource/README.md deleted file mode 100644 index 03447c08cc..0000000000 --- a/mcs/class/Mono.Security.Providers.NewSystemSource/README.md +++ /dev/null @@ -1,95 +0,0 @@ -Mono.Security.Interface / Mono.Security.Providers -================================================= - -This is not a public API yet, but will eventually become public. - - -Mono.Security.Interface ------------------------ - -`Mono.Security.Interface` provides an abstraction layer for the TLS -APIs that are currently being used by Mono's class libraries. - -The main API entry points are `MonoTlsProviderFactory.GetProvider()` -and `MonoTlsProviderFactory.InstallProvider()`. - -Mono.Net.Security ------------------ - -`Mono.Net.Security` provides the internal implementation and lives -inside `System.dll` as private and internal APIs. `Mono.Security.dll` -uses reflection to access these. - -On Mobile, the `Mono.Security.Interface` APIs are included as public -APIs in `System.dll`. - -Mono.Security.Providers ------------------------ - -Implementations of the `Mono.Security.Interface.MonoTlsProvider` class -to provide TLS functionality. - -The default provider is inside `System.dll` - it will be used automatically -if you don't explicitly install a custom provider, so simply call -`MonoTlsProviderFactory.GetProvider()` to use it. - -* DotNet: - Provides the default `SslStream` implementation from `System.dll`, only using - public .NET types. - -* NewSystemSource: - Compiles several referencesource files which would normally live inside - `System.dll` if we compiled it with their `SslStream` implementation. - - This allows to keep the code in `System.dll` as-is, while still providing the - new `SslStream`, which will be required by the new TLS code. - - `System.dll` needs to make its internals visible and we're using several compiler / - external alias tricks in here to make this work. - - In this configuration, `MONO_SYSTEM_ALIAS`, `MONO_FEATURE_NEW_TLS` and - `MONO_FEATURE_NEW_SYSTEM_SOURCE` (defining conditional for this configuration) - are defined. We do not define `MONO_X509_ALIAS here`. - -The `Mono.Security.Providers.DotNet` and `Mono.Security.Providers.NewSystemSource` directory is currently -enabled in the top-level `Makefile`, but the resulting binaries should only be used to test the new TLS -code and not shipped as stable APIs. - -Pending changes ---------------- - -This code is not actually being used in `System.dll` yet. I have some -local changes which will switch the existing code in `WebClient`, -`SmptClient` and `FtpWebRequest` over, but these need to be carefully -tested. - -At the moment, this work branch only provides new code and build -changes, which shuffle some stuff around. There are also several -new files which are conditional and not actually being built by -default. - -Build Configurations --------------------- - -* Normal build: - Builds everything as before with some new APIs added, but without - modifying any existing functionality. - -* Build with the `newtls` profile: - Builds `System.dll` with the new `SslStream` implementation from the - referencesource. This is currently a "build then throw away" profile - and not enabled from the top-level Makefile. The resulting `System.dll` - won't actually work at runtime since it's missing the new TLS code; - building it helps find problems and ensures that it will actually - be possible to build this once we deploy it. - -* Mono.Security.Providers: - The new TLS code requires the newly built `System` and `Mono.Security.Providers.NewSystemSource` - from this branch installed in the system. It is recommended to install it - into a custom prefix and set that as custom runtime in Xamarin Studio. - - -Last changed March 07th, 2015, -Martin Baulig - - diff --git a/mcs/class/Mono.Security.Providers.NewTls/Makefile b/mcs/class/Mono.Security.Providers.NewTls/Makefile deleted file mode 100644 index 54270bccc5..0000000000 --- a/mcs/class/Mono.Security.Providers.NewTls/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -thisdir = class/Mono.Security.Providers.NewTls -SUBDIRS = -include ../../build/rules.make - -LIBRARY = Mono.Security.Providers.NewTls.dll -LIB_REFS = System NewSystemSource=Mono.Security.Providers.NewSystemSource Mono.Security -LIB_MCS_FLAGS = -unsafe -nowarn:1030 -keyfile:../mono.pub -delaysign - -include ../../build/library.make - -$(the_lib): ../Mono.Security/Makefile - diff --git a/mcs/class/Mono.Security.Providers.NewTls/Mono.Security.Providers.NewTls.dll.sources b/mcs/class/Mono.Security.Providers.NewTls/Mono.Security.Providers.NewTls.dll.sources deleted file mode 100644 index 12d8a20f78..0000000000 --- a/mcs/class/Mono.Security.Providers.NewTls/Mono.Security.Providers.NewTls.dll.sources +++ /dev/null @@ -1,13 +0,0 @@ -./Properties/AssemblyInfo.cs -../../build/common/SR.cs -../../build/common/Consts.cs -../../build/common/Locale.cs - -./Mono.Security.Providers.NewTls/ITlsConfiguration.cs -./Mono.Security.Providers.NewTls/ITlsContext.cs - -./Mono.Security.Providers.NewTls/MonoNewTlsStream.cs -./Mono.Security.Providers.NewTls/MonoNewTlsStreamFactory.cs -./Mono.Security.Providers.NewTls/NewTlsProvider.cs -./Mono.Security.Providers.NewTls/TlsContextWrapper.cs -./Mono.Security.Providers.NewTls/TlsProviderFactory.cs diff --git a/mcs/class/Mono.Security.Providers.NewTls/Mono.Security.Providers.NewTls/MonoNewTlsStream.cs b/mcs/class/Mono.Security.Providers.NewTls/Mono.Security.Providers.NewTls/MonoNewTlsStream.cs deleted file mode 100644 index 6117f0f774..0000000000 --- a/mcs/class/Mono.Security.Providers.NewTls/Mono.Security.Providers.NewTls/MonoNewTlsStream.cs +++ /dev/null @@ -1,93 +0,0 @@ -// -// MonoNewTlsStream.cs -// -// Author: -// Martin Baulig -// -// Copyright (c) 2015 Xamarin, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -extern alias NewSystemSource; - -using EncryptionPolicy = NewSystemSource::System.Net.Security.EncryptionPolicy; -using LocalCertificateSelectionCallback = NewSystemSource::System.Net.Security.LocalCertificateSelectionCallback; -using RemoteCertificateValidationCallback = NewSystemSource::System.Net.Security.RemoteCertificateValidationCallback; -using SslStream = NewSystemSource::System.Net.Security.SslStream; - -using System; -using System.IO; -using System.Threading.Tasks; - -using MSI = Mono.Security.Interface; - -using XAuthenticatedStream = System.Net.Security.AuthenticatedStream; -using System.Security.Cryptography.X509Certificates; - -namespace Mono.Security.Providers.NewTls -{ - public class MonoNewTlsStream : SslStream, MSI.IMonoSslStream - { - MSI.MonoTlsProvider provider; - - internal MonoNewTlsStream (Stream innerStream, MSI.MonoTlsProvider provider, MSI.MonoTlsSettings settings) - : this (innerStream, false, provider, settings) - { - } - - internal MonoNewTlsStream (Stream innerStream, bool leaveOpen, MSI.MonoTlsProvider provider, MSI.MonoTlsSettings settings) - : base (innerStream, leaveOpen, EncryptionPolicy.RequireEncryption, provider, settings) - { - this.provider = provider; - } - - public MSI.MonoTlsProvider Provider { - get { return provider; } - } - - new public bool IsClosed { - get { return base.IsClosed; } - } - - public MSI.MonoTlsConnectionInfo GetConnectionInfo () - { - return GetMonoConnectionInfo (); - } - - public Task Shutdown () - { - return Task.Factory.FromAsync ((state, result) => BeginShutdown (state, result), EndShutdown, null); - } - - public Task RequestRenegotiation () - { - return Task.Factory.FromAsync ((state, result) => BeginRenegotiate (state, result), EndRenegotiate, null); - } - - X509Certificate MSI.IMonoSslStream.InternalLocalCertificate { - get { return InternalLocalCertificate; } - } - - XAuthenticatedStream MSI.IMonoSslStream.AuthenticatedStream { - get { return this; } - } - } -} - - diff --git a/mcs/class/Mono.Security.Providers.NewTls/Mono.Security.Providers.NewTls/MonoNewTlsStreamFactory.cs b/mcs/class/Mono.Security.Providers.NewTls/Mono.Security.Providers.NewTls/MonoNewTlsStreamFactory.cs deleted file mode 100644 index d39f1bb2c5..0000000000 --- a/mcs/class/Mono.Security.Providers.NewTls/Mono.Security.Providers.NewTls/MonoNewTlsStreamFactory.cs +++ /dev/null @@ -1,91 +0,0 @@ -// -// MonoNewTlsStreamFactory.cs -// -// Author: -// Martin Baulig -// -// Copyright (c) 2015 Xamarin, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -extern alias NewSystemSource; - -using XEncryptionPolicy = NewSystemSource::System.Net.Security.EncryptionPolicy; -using XSslPolicyErrors = NewSystemSource::System.Net.Security.SslPolicyErrors; -using XLocalCertificateSelectionCallback = NewSystemSource::System.Net.Security.LocalCertificateSelectionCallback; -using XRemoteCertificateValidationCallback = NewSystemSource::System.Net.Security.RemoteCertificateValidationCallback; - -using System; -using System.IO; -using System.Net.Security; -using System.Security.Authentication; - -using Mono.Security.Interface; - -using PSSCX = System.Security.Cryptography.X509Certificates; -using SSCX = System.Security.Cryptography.X509Certificates; - -namespace Mono.Security.Providers.NewTls -{ - public static class MonoNewTlsStreamFactory - { - internal static IMonoSslStream CreateSslStream ( - Stream innerStream, bool leaveInnerStreamOpen, - MonoTlsProvider provider, MonoTlsSettings settings = null) - { - return new MonoNewTlsStream (innerStream, leaveInnerStreamOpen, provider, settings); - } - - public static MonoNewTlsStream CreateServer ( - Stream innerStream, bool leaveOpen, MonoTlsProvider provider, MonoTlsSettings settings, - SSCX.X509Certificate serverCertificate, bool clientCertificateRequired, - SslProtocols enabledSslProtocols, bool checkCertificateRevocation) - { - var stream = new MonoNewTlsStream (innerStream, leaveOpen, provider, settings); - - try { - stream.AuthenticateAsServer (serverCertificate, clientCertificateRequired, enabledSslProtocols, checkCertificateRevocation); - } catch (Exception ex) { - var tlsEx = stream.LastError; - if (tlsEx != null) - throw new AggregateException (ex, tlsEx); - throw; - } - - return stream; - } - - public static MonoNewTlsStream CreateClient ( - Stream innerStream, bool leaveOpen, MonoTlsProvider provider, MonoTlsSettings settings, - string targetHost, PSSCX.X509CertificateCollection clientCertificates, SslProtocols enabledSslProtocols, bool checkCertificateRevocation) - { - var stream = new MonoNewTlsStream (innerStream, leaveOpen, provider, settings); - - try { - stream.AuthenticateAsClient (targetHost, clientCertificates, enabledSslProtocols, checkCertificateRevocation); - } catch (Exception ex) { - var tlsEx = stream.LastError; - if (tlsEx != null) - throw new AggregateException (ex, tlsEx); - throw; - } - return stream; - } - } -} diff --git a/mcs/class/Mono.Security.Providers.NewTls/Mono.Security.Providers.NewTls/NewTlsProvider.cs b/mcs/class/Mono.Security.Providers.NewTls/Mono.Security.Providers.NewTls/NewTlsProvider.cs deleted file mode 100644 index e2b347fbe2..0000000000 --- a/mcs/class/Mono.Security.Providers.NewTls/Mono.Security.Providers.NewTls/NewTlsProvider.cs +++ /dev/null @@ -1,95 +0,0 @@ -// -// NewTlsProvider.cs -// -// Author: -// Martin Baulig -// -// Copyright (c) 2015 Xamarin, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -extern alias NewSystemSource; - -using System; -using System.IO; -using System.Net; -using System.Net.Security; -using System.Security.Authentication; - -using MSI = Mono.Security.Interface; -using MX = Mono.Security.X509; - -using PSSCX = System.Security.Cryptography.X509Certificates; -using SSCX = System.Security.Cryptography.X509Certificates; - -namespace Mono.Security.Providers.NewTls -{ - public class NewTlsProvider : MSI.MonoTlsProvider - { - static readonly Guid id = new Guid ("e5ff34f1-8b7a-4aa6-aff9-24719d709693"); - - public override Guid ID { - get { return id; } - } - - public override string Name { - get { return "newtls"; } - } - - public override bool SupportsSslStream { - get { return true; } - } - - public override bool SupportsConnectionInfo { - get { return true; } - } - - public override bool SupportsMonoExtensions { - get { return true; } - } - - internal override bool SupportsTlsContext { - get { return true; } - } - - public override SslProtocols SupportedProtocols { - get { return SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls; } - } - - public override MSI.IMonoSslStream CreateSslStream ( - Stream innerStream, bool leaveInnerStreamOpen, - MSI.MonoTlsSettings settings = null) - { - return MonoNewTlsStreamFactory.CreateSslStream (innerStream, leaveInnerStreamOpen, this, settings); - } - - internal override MSI.IMonoTlsContext CreateTlsContext ( - string hostname, bool serverMode, MSI.TlsProtocols protocolFlags, - SSCX.X509Certificate serverCertificate, PSSCX.X509CertificateCollection clientCertificates, - bool remoteCertRequired, MSI.MonoEncryptionPolicy encryptionPolicy, - MSI.MonoTlsSettings settings) - { - var config = TlsProviderFactory.CreateTlsConfiguration ( - hostname, serverMode, protocolFlags, serverCertificate, - remoteCertRequired, settings); - return new TlsContextWrapper (config, serverMode); - } - } -} - diff --git a/mcs/class/Mono.Security.Providers.NewTls/Mono.Security.Providers.NewTls/TlsContextWrapper.cs b/mcs/class/Mono.Security.Providers.NewTls/Mono.Security.Providers.NewTls/TlsContextWrapper.cs deleted file mode 100644 index 389dd1a19f..0000000000 --- a/mcs/class/Mono.Security.Providers.NewTls/Mono.Security.Providers.NewTls/TlsContextWrapper.cs +++ /dev/null @@ -1,221 +0,0 @@ -// -// TlsContextWrapper.cs -// -// Author: -// Martin Baulig -// -// Copyright (c) 2015 Xamarin, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -extern alias NewSystemSource; - -using System; -using System.Security.Cryptography; - -using SSCX = System.Security.Cryptography.X509Certificates; -using PSSCX = System.Security.Cryptography.X509Certificates; - -using MSI = Mono.Security.Interface; -using MX = Mono.Security.X509; - -namespace Mono.Security.Providers.NewTls -{ - class TlsContextWrapper : IDisposable, MSI.IMonoTlsContext - { - ITlsConfiguration config; - ITlsContext context; - bool serverMode; - - public TlsContextWrapper (ITlsConfiguration config, bool serverMode) - { - this.config = config; - this.serverMode = serverMode; - } - - public bool IsServer { - get { return serverMode; } - } - - public bool IsValid { - get { return context != null && context.IsValid; } - } - - public void Initialize (MSI.IMonoTlsEventSink eventSink) - { - if (context != null) - throw new InvalidOperationException (); - context = TlsProviderFactory.CreateTlsContext (config, serverMode, eventSink); - } - - void Clear () - { - if (context != null) { - context.Dispose (); - context = null; - } - } - - public ITlsConfiguration Configuration { - get { - if (config == null) - throw new ObjectDisposedException ("TlsConfiguration"); - return config; - } - } - - public ITlsContext Context { - get { - if (!IsValid) - throw new ObjectDisposedException ("TlsContext"); - return context; - } - } - - public bool HasCredentials { - get { return Configuration.HasCredentials; } - } - - public void SetCertificate (SSCX.X509Certificate certificate, AsymmetricAlgorithm privateKey) - { - var monoCert = new MX.X509Certificate (certificate.GetRawCertData ()); - Configuration.SetCertificate (monoCert, privateKey); - } - - public int GenerateNextToken (MSI.IBufferOffsetSize incoming, out MSI.IBufferOffsetSize outgoing) - { - var input = incoming != null ? new MSI.TlsBuffer (BOSWrapper.Wrap (incoming)) : null; - var output = new MSI.TlsMultiBuffer (); - var retval = Context.GenerateNextToken (input, output); - if (output.IsEmpty) - outgoing = null; - outgoing = BOSWrapper.Wrap (output.StealBuffer ()); - return (int)retval; - } - - public int EncryptMessage (ref MSI.IBufferOffsetSize incoming) - { - var buffer = new MSI.TlsBuffer (BOSWrapper.Wrap (incoming)); - var retval = Context.EncryptMessage (ref buffer); - incoming = BOSWrapper.Wrap (buffer.GetRemaining ()); - return (int)retval; - } - - public int DecryptMessage (ref MSI.IBufferOffsetSize incoming) - { - var buffer = new MSI.TlsBuffer (BOSWrapper.Wrap (incoming)); - var retval = Context.DecryptMessage (ref buffer); - incoming = buffer != null ? BOSWrapper.Wrap (buffer.GetRemaining ()) : null; - return (int)retval; - } - - class BOSWrapper : MSI.IBufferOffsetSize - { - public byte[] Buffer { - get; - private set; - } - - public int Offset { - get; - private set; - } - - public int Size { - get; - private set; - } - - BOSWrapper (byte[] buffer, int offset, int size) - { - Buffer = buffer; - Offset = offset; - Size = size; - } - - public static BOSWrapper Wrap (MSI.IBufferOffsetSize bos) - { - return bos != null ? new BOSWrapper (bos.Buffer, bos.Offset, bos.Size) : null; - } - } - - public byte[] CreateCloseNotify () - { - return Context.CreateAlert (new MSI.Alert (MSI.AlertLevel.Warning, MSI.AlertDescription.CloseNotify)); - } - - public byte[] CreateHelloRequest () - { - return Context.CreateHelloRequest (); - } - - public SSCX.X509Certificate GetRemoteCertificate (out PSSCX.X509CertificateCollection remoteCertificateStore) - { - MX.X509CertificateCollection monoCollection; - var remoteCert = Context.GetRemoteCertificate (out monoCollection); - if (remoteCert == null) { - remoteCertificateStore = null; - return null; - } - - remoteCertificateStore = new PSSCX.X509CertificateCollection (); - foreach (var cert in monoCollection) { - remoteCertificateStore.Add (new PSSCX.X509Certificate2 (cert.RawData)); - } - return new PSSCX.X509Certificate2 (remoteCert.RawData); - - } - - public bool VerifyRemoteCertificate () - { - return Context.VerifyRemoteCertificate (); - } - - public Exception LastError { - get { - if (context != null) - return context.LastError; - return null; - } - } - - public bool ReceivedCloseNotify { - get { - return Context.ReceivedCloseNotify; - } - } - - public MSI.MonoTlsConnectionInfo GetConnectionInfo () - { - return Context.ConnectionInfo; - } - - public void Dispose () - { - Dispose (true); - GC.SuppressFinalize (this); - } - - void Dispose (bool disposing) - { - Clear (); - } - } -} - diff --git a/mcs/class/Mono.Security.Providers.NewTls/Mono.Security.Providers.NewTls/TlsProviderFactory.cs b/mcs/class/Mono.Security.Providers.NewTls/Mono.Security.Providers.NewTls/TlsProviderFactory.cs deleted file mode 100644 index 92d8ab08f6..0000000000 --- a/mcs/class/Mono.Security.Providers.NewTls/Mono.Security.Providers.NewTls/TlsProviderFactory.cs +++ /dev/null @@ -1,97 +0,0 @@ -// -// TlsProviderFactory.cs -// -// Author: -// Martin Baulig -// -// Copyright (c) 2015-2016 Xamarin, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -extern alias NewSystemSource; - -using System; -using System.IO; - -using System.Net; -using System.Net.Security; -using System.Security.Authentication; - -using MSI = Mono.Security.Interface; -using MX = Mono.Security.X509; - -using PSSCX = System.Security.Cryptography.X509Certificates; -using SSCX = System.Security.Cryptography.X509Certificates; - -namespace Mono.Security.Providers.NewTls -{ - static class TlsProviderFactory - { - const string assemblyName = "Mono.Security.NewTls, Version=4.0.0.0, Culture=neutral, PublicKeyToken=84e3aee7225169c2"; - const string tlsConfigTypeName = "Mono.Security.NewTls.TlsConfiguration"; - const string tlsContextTypeName = "Mono.Security.NewTls.TlsContext"; - - static object CreateInstance (string typeName, object[] args) - { - var type = Type.GetType (typeName + ", " + assemblyName); - return Activator.CreateInstance (type, args); - } - - internal static ITlsConfiguration CreateTlsConfiguration ( - string hostname, bool serverMode, MSI.TlsProtocols protocolFlags, - SSCX.X509Certificate serverCertificate, bool remoteCertRequired, - MSI.MonoTlsSettings settings) - { - object[] args; - ITlsConfiguration config; - if (serverMode) { - var cert = (PSSCX.X509Certificate2)serverCertificate; - var monoCert = new MX.X509Certificate (cert.RawData); - args = new object[] { - (MSI.TlsProtocols)protocolFlags, - (MSI.MonoTlsSettings)settings, - monoCert, - cert.PrivateKey - }; - } else { - args = new object[] { - (MSI.TlsProtocols)protocolFlags, - (MSI.MonoTlsSettings)settings, - hostname - }; - } - - config = (ITlsConfiguration)CreateInstance (tlsConfigTypeName, args); - - if (serverMode && remoteCertRequired) - config.AskForClientCertificate = true; - - return config; - } - - internal static ITlsContext CreateTlsContext ( - ITlsConfiguration config, bool serverMode, - MSI.IMonoTlsEventSink eventSink) - { - return (ITlsContext)CreateInstance ( - tlsContextTypeName, - new object[] { config, serverMode, eventSink }); - } - } -} diff --git a/mcs/class/Mono.Security.Providers.NewTls/Properties/AssemblyInfo.cs b/mcs/class/Mono.Security.Providers.NewTls/Properties/AssemblyInfo.cs deleted file mode 100644 index e369093920..0000000000 --- a/mcs/class/Mono.Security.Providers.NewTls/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,47 +0,0 @@ -// -// AssemblyInfo.cs -// -// Author: -// Martin Baulig -// -// Copyright (c) 2015 Xamarin, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -using System; -using System.Reflection; -using System.Resources; -using System.Security; -using System.Security.Permissions; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about the system assembly - -[assembly: AssemblyVersion (Consts.FxVersion)] - -[assembly: AssemblyCompany ("Xamarin")] -[assembly: AssemblyCopyright ("(c) 2015 Xamarin")] -[assembly: AssemblyDescription ("Mono.Security.Providers.NewTls.dll")] -[assembly: AssemblyProduct ("MONO CLI")] -[assembly: AssemblyTitle ("Mono.Security.Providers.NewTls.dll")] -[assembly: CLSCompliant (false)] -[assembly: ComVisible (false)] -[assembly: NeutralResourcesLanguage ("en-US")] - -[assembly: InternalsVisibleTo ("Mono.Security.NewTls, PublicKey=002400000480000094000000060200000024000052534131000400001100000003336d6aed41624ca156ab579881fe90a576f1dfec48378fc94e4e440f4556776224e2d70c18996d91f36227f539fdb44340e07651f1455a489b29a7e6219a8f85e52b0f8588b4f8a857746a8468d37b556223d1452f3fcbaf0f269cdf1900ceb68f69485dc5887750d19571030c732331e00387d9b813a9ad52891087301793")] diff --git a/mcs/class/Mono.Security.Providers.NewTls/mobile_Mono.Security.Providers.NewTls.dll.sources b/mcs/class/Mono.Security.Providers.NewTls/mobile_Mono.Security.Providers.NewTls.dll.sources deleted file mode 100644 index 7218dabc34..0000000000 --- a/mcs/class/Mono.Security.Providers.NewTls/mobile_Mono.Security.Providers.NewTls.dll.sources +++ /dev/null @@ -1,7 +0,0 @@ -Properties/AssemblyInfo.cs - -Mono.Security.Providers.NewTls/ITlsConfiguration.cs -Mono.Security.Providers.NewTls/ITlsContext.cs - -Mono.Security.Providers.NewTls/MonoNewTlsStream.cs -Mono.Security.Providers.NewTls/MonoNewTlsStreamFactory.cs diff --git a/mcs/class/Mono.Security.Providers.NewTls/mobile_static_Mono.Security.Providers.NewTls.dll.sources b/mcs/class/Mono.Security.Providers.NewTls/mobile_static_Mono.Security.Providers.NewTls.dll.sources deleted file mode 100644 index baded51434..0000000000 --- a/mcs/class/Mono.Security.Providers.NewTls/mobile_static_Mono.Security.Providers.NewTls.dll.sources +++ /dev/null @@ -1 +0,0 @@ -#include mobile_Mono.Security.Providers.NewTls.dll.sources diff --git a/mcs/class/Mono.Security.Providers.OldTls/Mono.Security.Providers.OldTls/OldTlsProvider.cs b/mcs/class/Mono.Security.Providers.OldTls/Mono.Security.Providers.OldTls/OldTlsProvider.cs deleted file mode 100644 index 4532a17e02..0000000000 --- a/mcs/class/Mono.Security.Providers.OldTls/Mono.Security.Providers.OldTls/OldTlsProvider.cs +++ /dev/null @@ -1,87 +0,0 @@ -// -// OldTlsProvider.cs -// -// Author: -// Martin Baulig -// -// Copyright (c) 2015 Xamarin, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -using System; -using System.IO; -using System.Net; -using System.Net.Security; -using System.Security.Authentication; -using System.Security.Cryptography.X509Certificates; -using Mono.Security.Interface; -using MNS = Mono.Net.Security; - -namespace Mono.Security.Providers.OldTls -{ - public class OldTlsProvider : MonoTlsProvider - { - static readonly Guid id = new Guid ("cf8baa0d-c6ed-40ae-b512-dec8d097e9af"); - - public override Guid ID { - get { return id; } - } - - public override string Name { - get { return "old"; } - } - - public override bool SupportsSslStream { - get { return true; } - } - - public override bool SupportsMonoExtensions { - get { return false; } - } - - public override bool SupportsConnectionInfo { - get { return false; } - } - - internal override bool SupportsTlsContext { - get { return false; } - } - - public override SslProtocols SupportedProtocols { - get { return SslProtocols.Tls; } - } - - public override IMonoSslStream CreateSslStream ( - Stream innerStream, bool leaveInnerStreamOpen, - MonoTlsSettings settings = null) - { - var impl = new MNS.Private.LegacySslStream (innerStream, leaveInnerStreamOpen, this, settings); - return new MNS.Private.MonoSslStreamImpl (impl); - } - - internal override IMonoTlsContext CreateTlsContext ( - string hostname, bool serverMode, TlsProtocols protocolFlags, - X509Certificate serverCertificate, X509CertificateCollection clientCertificates, - bool remoteCertRequired, MonoEncryptionPolicy encryptionPolicy, - MonoTlsSettings settings) - { - throw new NotSupportedException (); - } - } -} - diff --git a/mcs/class/Mono.Security/Assembly/AssemblyInfo.cs b/mcs/class/Mono.Security/Assembly/AssemblyInfo.cs index b5bf191148..eeccc251f7 100644 --- a/mcs/class/Mono.Security/Assembly/AssemblyInfo.cs +++ b/mcs/class/Mono.Security/Assembly/AssemblyInfo.cs @@ -60,14 +60,9 @@ using System.Runtime.InteropServices; [assembly: AssemblyDelaySign (true)] [assembly: AssemblyKeyFile ("../mono.pub")] -#if NET_2_1 +#if MOBILE [assembly: InternalsVisibleTo ("System, PublicKey=00240000048000009400000006020000002400005253413100040000010001008D56C76F9E8649383049F383C44BE0EC204181822A6C31CF5EB7EF486944D032188EA1D3920763712CCB12D75FB77E9811149E6148E5D32FBAAB37611C1878DDC19E20EF135D0CB2CFF2BFEC3D115810C3D9069638FE4BE215DBF795861920E5AB6F7DB2E2CEEF136AC23D5DD2BF031700AEC232F6C6B1C785B4305C123B37AB")] #else [assembly: InternalsVisibleTo ("System, PublicKey=00000000000000000400000000000000")] #endif -[assembly: InternalsVisibleTo ("Mono.Security.Providers.NewTls, PublicKey=002400000480000094000000060200000024000052534131000400000100010079159977d2d03a8e6bea7a2e74e8d1afcc93e8851974952bb480a12c9134474d04062447c37e0e68c080536fcf3c3fbe2ff9c979ce998475e506e8ce82dd5b0f350dc10e93bf2eeecf874b24770c5081dbea7447fddafa277b22de47d6ffea449674a4f9fccf84d15069089380284dbdd35f46cdff12a1bd78e4ef0065d016df")] -[assembly: InternalsVisibleTo ("Mono.Security.Providers.OldTls, PublicKey=002400000480000094000000060200000024000052534131000400000100010079159977d2d03a8e6bea7a2e74e8d1afcc93e8851974952bb480a12c9134474d04062447c37e0e68c080536fcf3c3fbe2ff9c979ce998475e506e8ce82dd5b0f350dc10e93bf2eeecf874b24770c5081dbea7447fddafa277b22de47d6ffea449674a4f9fccf84d15069089380284dbdd35f46cdff12a1bd78e4ef0065d016df")] -[assembly: InternalsVisibleTo ("Mono.Security.Providers.DotNet, PublicKey=002400000480000094000000060200000024000052534131000400000100010079159977d2d03a8e6bea7a2e74e8d1afcc93e8851974952bb480a12c9134474d04062447c37e0e68c080536fcf3c3fbe2ff9c979ce998475e506e8ce82dd5b0f350dc10e93bf2eeecf874b24770c5081dbea7447fddafa277b22de47d6ffea449674a4f9fccf84d15069089380284dbdd35f46cdff12a1bd78e4ef0065d016df")] -[assembly: InternalsVisibleTo ("Mono.Security.Providers.NewSystemSource, PublicKey=002400000480000094000000060200000024000052534131000400000100010079159977d2d03a8e6bea7a2e74e8d1afcc93e8851974952bb480a12c9134474d04062447c37e0e68c080536fcf3c3fbe2ff9c979ce998475e506e8ce82dd5b0f350dc10e93bf2eeecf874b24770c5081dbea7447fddafa277b22de47d6ffea449674a4f9fccf84d15069089380284dbdd35f46cdff12a1bd78e4ef0065d016df")] -[assembly: InternalsVisibleTo ("Xamarin.BoringTls, PublicKey=002400000480000094000000060200000024000052534131000400001100000099dd12eda85767ae6f06023ee28e711c7e5a212462095c83868c29db75eddf6d8e296e03824c14fedd5f55553fed0b6173be3cc985a4b7f9fb7c83ccff8ba3938563b3d1f45a81122f12a1bcb73edcaad61a8456c7595a6da5184b4dd9d10f011b949ef1391fccfeab1ba62aa51c267ef8bd57ef1b6ba5a4c515d0badb81a78f")] diff --git a/mcs/class/Mono.Security/Mono.Security.Interface/CertificateValidationHelper.cs b/mcs/class/Mono.Security/Mono.Security.Interface/CertificateValidationHelper.cs index fd392b409e..98805605c0 100644 --- a/mcs/class/Mono.Security/Mono.Security.Interface/CertificateValidationHelper.cs +++ b/mcs/class/Mono.Security/Mono.Security.Interface/CertificateValidationHelper.cs @@ -103,13 +103,6 @@ namespace Mono.Security.Interface * Internal use only. */ ValidationResult ValidateCertificate (string targetHost, bool serverMode, X509Certificate leaf, X509Chain chain); - - /* - * On OS X and Mobile, the @chain will be initialized with the @certificates, but not actually built. - */ - bool InvokeSystemValidator ( - string targetHost, bool serverMode, X509CertificateCollection certificates, - X509Chain chain, ref MonoSslPolicyErrors errors, ref int status11); } public static class CertificateValidationHelper @@ -148,17 +141,23 @@ namespace Mono.Security.Interface /* * Internal API, intended to be used by MonoTlsProvider implementations. */ + internal static ICertificateValidator2 GetInternalValidator (MonoTlsSettings settings, MonoTlsProvider provider) + { + return (ICertificateValidator2)NoReflectionHelper.GetInternalValidator (provider, settings); + } + + [Obsolete ("Use GetInternalValidator")] internal static ICertificateValidator2 GetDefaultValidator (MonoTlsSettings settings, MonoTlsProvider provider) { - return (ICertificateValidator2)NoReflectionHelper.GetDefaultCertificateValidator (provider, settings); + return GetInternalValidator (settings, provider); } /* * Use this overloaded version in user code. */ - public static ICertificateValidator GetValidator (MonoTlsSettings settings, MonoTlsProvider provider = null) + public static ICertificateValidator GetValidator (MonoTlsSettings settings) { - return GetDefaultValidator (settings, provider); + return (ICertificateValidator)NoReflectionHelper.GetDefaultValidator (settings); } } } diff --git a/mcs/class/Mono.Security/Mono.Security.Interface/CipherSuiteCode.cs b/mcs/class/Mono.Security/Mono.Security.Interface/CipherSuiteCode.cs index 66980df81a..1060677c59 100644 --- a/mcs/class/Mono.Security/Mono.Security.Interface/CipherSuiteCode.cs +++ b/mcs/class/Mono.Security/Mono.Security.Interface/CipherSuiteCode.cs @@ -31,6 +31,7 @@ namespace Mono.Security.Interface /// /// RFC 2246 A.5 /// + [CLSCompliant (false)] public enum CipherSuiteCode : ushort { TLS_NULL_WITH_NULL_NULL = 0x0000, diff --git a/mcs/class/Mono.Security/Mono.Security.Interface/MonoTlsConnectionInfo.cs b/mcs/class/Mono.Security/Mono.Security.Interface/MonoTlsConnectionInfo.cs index 4bc5f436f4..120d885eaf 100644 --- a/mcs/class/Mono.Security/Mono.Security.Interface/MonoTlsConnectionInfo.cs +++ b/mcs/class/Mono.Security/Mono.Security.Interface/MonoTlsConnectionInfo.cs @@ -29,6 +29,7 @@ namespace Mono.Security.Interface { public class MonoTlsConnectionInfo { + [CLSCompliant (false)] public CipherSuiteCode CipherSuiteCode { get; set; } @@ -49,6 +50,10 @@ namespace Mono.Security.Interface get; set; } + public string PeerDomainName { + get; set; + } + public override string ToString () { return string.Format ("[MonoTlsConnectionInfo: {0}:{1}]", ProtocolVersion, CipherSuiteCode); diff --git a/mcs/class/Mono.Security/Mono.Security.Interface/MonoTlsProvider.cs b/mcs/class/Mono.Security/Mono.Security.Interface/MonoTlsProvider.cs index 089d8447a7..0d7a7512d6 100644 --- a/mcs/class/Mono.Security/Mono.Security.Interface/MonoTlsProvider.cs +++ b/mcs/class/Mono.Security/Mono.Security.Interface/MonoTlsProvider.cs @@ -145,14 +145,6 @@ namespace Mono.Security.Interface #endregion #region Certificate Validation - - /* - * Allows a TLS provider to provide a custom system certificiate validator. - */ - internal virtual bool HasCustomSystemCertificateValidator { - get { return false; } - } - /* * If @serverMode is true, then we're a server and want to validate a certificate * that we received from a client. @@ -162,32 +154,10 @@ namespace Mono.Security.Interface * Returns `true` if certificate validation has been performed and `false` to invoke the * default system validator. */ - internal virtual bool InvokeSystemCertificateValidator ( + internal abstract bool ValidateCertificate ( ICertificateValidator2 validator, string targetHost, bool serverMode, X509CertificateCollection certificates, bool wantsChain, ref X509Chain chain, - out bool success, ref MonoSslPolicyErrors errors, ref int status11) - { - throw new InvalidOperationException (); - } - -#endregion - -#region Manged SSPI - - /* - * The managed SSPI implementation from the new TLS code. - */ - - internal abstract bool SupportsTlsContext { - get; - } - - internal abstract IMonoTlsContext CreateTlsContext ( - string hostname, bool serverMode, TlsProtocols protocolFlags, - X509Certificate serverCertificate, X509CertificateCollection clientCertificates, - bool remoteCertRequired, MonoEncryptionPolicy encryptionPolicy, - MonoTlsSettings settings); - + ref MonoSslPolicyErrors errors, ref int status11); #endregion } } diff --git a/mcs/class/Mono.Security/Mono.Security.Interface/MonoTlsProviderFactory.cs b/mcs/class/Mono.Security/Mono.Security.Interface/MonoTlsProviderFactory.cs index 557d024da2..a9983f1290 100644 --- a/mcs/class/Mono.Security/Mono.Security.Interface/MonoTlsProviderFactory.cs +++ b/mcs/class/Mono.Security/Mono.Security.Interface/MonoTlsProviderFactory.cs @@ -39,7 +39,37 @@ namespace Mono.Security.Interface public static partial class MonoTlsProviderFactory { /* - * Returns the currently installed @MonoTlsProvider, falling back to the default one. + * TLS Provider Initialization + * =========================== + * + * The "global" TLS Provider (returned by GetProvider()) may only be modified at + * application startup (before any of the TLS / Certificate code has been used). + * + * On mobile, the default provider is specified at compile time using a property + * in the .csproj file (which can be set from the IDE). When using the linker, all + * other providers will be linked-out, so you won't be able to choose a different + * provider at run-time. + * + * On desktop, the default provider can be specified with the MONO_TLS_PROVIDER + * environment variable. The following options are currently supported: + * + * "default" - let Mono pick the best one for you (recommended) + * "old" or "legacy" - Mono's old managed TLS implementation + * "appletls" (currently XamMac only, set via .csproj property) + * "btls" - the new boringssl based provider (coming soon). + * + * On all platforms (except mobile with linker), you can call + * + * MonoTlsProviderFactory.Initialize(string) + * + * to use a different provider. + * + */ + + #region Provider Initialization + + /* + * Returns the global @MonoTlsProvider, initializing the TLS Subsystem if necessary. * * This method throws @NotSupportedException if no TLS Provider can be found. */ @@ -49,42 +79,64 @@ namespace Mono.Security.Interface } /* - * Returns the default @MonoTlsProvider. - * - * This method throws @NotSupportedException if no TLS Provider can be found. + * Check whether the TLS Subsystem is initialized. */ - public static MonoTlsProvider GetDefaultProvider () - { - return (MonoTlsProvider)NoReflectionHelper.GetDefaultProvider (); - } - - /* - * GetProvider() attempts to load and install the default provider and throws on error. - * - * This property checks whether a provider has previously been installed by a call - * to either GetProvider() or InstallProvider(). - * - */ - public static bool HasProvider { + public static bool IsInitialized { get { - return NoReflectionHelper.HasProvider; + return NoReflectionHelper.IsInitialized; } } /* - * Selects the default TLS Provider. - * - * May only be called at application startup and will throw - * @InvalidOperationException if a provider has already been installed. + * Initialize the TLS Subsystem. + * + * This method may be called at any time. It ensures that the TLS Subsystem is + * initialized and a provider available. */ - public static void SetDefaultProvider (string name) + public static void Initialize () { - NoReflectionHelper.SetDefaultProvider (name); + NoReflectionHelper.Initialize (); } - public static MonoTlsProvider GetProvider (string name) + /* + * Initialize the TLS Subsystem with a specific provider. + * + * May only be called at application startup (before any of the TLS / Certificate + * APIs have been used). + * + * Throws @NotSupportedException if the TLS Subsystem is already initialized + * (@IsInitialized returns true) or the requested provider is not supported. + * + * On mobile, this will always throw @NotSupportedException when using the linker. + */ + public static void Initialize (string provider) { - return (MonoTlsProvider)NoReflectionHelper.GetProvider (name); + NoReflectionHelper.Initialize (provider); + } + + /* + * Checks whether @provider is supported. + * + * On mobile, this will always return false when using the linker. + */ + public static bool IsProviderSupported (string provider) + { + return NoReflectionHelper.IsProviderSupported (provider); + } + + #endregion + + #region Call-by-call selection + + /* + * Returns the requested TLS Provider, for use with the call-by-call APIs below. + * + * Throw @NotSupportedException if the requested provider is not supported or + * when using the linker on mobile. + */ + public static MonoTlsProvider GetProvider (string provider) + { + return (MonoTlsProvider)NoReflectionHelper.GetProvider (provider); } /* @@ -108,6 +160,24 @@ namespace Mono.Security.Interface { return (IMonoSslStream)NoReflectionHelper.GetMonoSslStream (stream); } + + #endregion + + #region Obsolete APIs + + [Obsolete] + public static MonoTlsProvider GetDefaultProvider () + { + return GetProvider (); + } + + [Obsolete] + public static void SetDefaultProvider (string name) + { + Initialize (name); + } + + #endregion } } diff --git a/mcs/class/Mono.Security/Mono.Security.Interface/MonoTlsSettings.cs b/mcs/class/Mono.Security/Mono.Security.Interface/MonoTlsSettings.cs index 24b28a790e..7721bb00a5 100644 --- a/mcs/class/Mono.Security/Mono.Security.Interface/MonoTlsSettings.cs +++ b/mcs/class/Mono.Security/Mono.Security.Interface/MonoTlsSettings.cs @@ -82,6 +82,7 @@ namespace Mono.Security.Interface get; set; } + [CLSCompliant (false)] public CipherSuiteCode[] EnabledCiphers { get; set; } diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/DebugHelper.cs b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/DebugHelper.cs index 70b25bd1d5..ff122878c9 100644 --- a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/DebugHelper.cs +++ b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/DebugHelper.cs @@ -36,7 +36,7 @@ namespace Mono.Security.Protocol.Tls { if (!isInitialized) { -#if !NET_2_1 +#if !MOBILE Debug.Listeners.Add(new TextWriterTraceListener(Console.Out)); // Debug.Listeners.Add(new TextWriterTraceListener(@"c:\ssl.log")); Debug.AutoFlush = true; diff --git a/mcs/class/Mono.Security/Mono.Security.X509/X509Store.cs b/mcs/class/Mono.Security/Mono.Security.X509/X509Store.cs index 23ccc8316e..e74c7be0dd 100644 --- a/mcs/class/Mono.Security/Mono.Security.X509/X509Store.cs +++ b/mcs/class/Mono.Security/Mono.Security.X509/X509Store.cs @@ -38,6 +38,8 @@ using System.Security.Cryptography; using Mono.Security.Cryptography; using Mono.Security.X509.Extensions; +using SSCX = System.Security.Cryptography.X509Certificates; + namespace Mono.Security.X509 { #if INSIDE_CORLIB @@ -51,12 +53,14 @@ namespace Mono.Security.X509 { private X509CertificateCollection _certificates; private ArrayList _crls; private bool _crl; + private bool _newFormat; private string _name; - internal X509Store (string path, bool crl) + internal X509Store (string path, bool crl, bool newFormat) { _storePath = path; _crl = crl; + _newFormat = newFormat; } // properties @@ -126,6 +130,11 @@ namespace Mono.Security.X509 { { CheckStore (_storePath, true); + if (_newFormat) { + ImportNewFormat (certificate); + return; + } + string filename = Path.Combine (_storePath, GetUniqueName (certificate)); if (!File.Exists (filename)) { filename = Path.Combine (_storePath, GetUniqueNameWithSerial (certificate)); @@ -148,7 +157,7 @@ namespace Mono.Security.X509 { ClearCertificates (); // We have modified the store on disk. So forget the old state. } } -#if !NET_2_1 +#if !MOBILE // Try to save privateKey if available.. CspParameters cspParams = new CspParameters (); cspParams.KeyContainerName = CryptoConvert.ToHex (certificate.Hash); @@ -165,6 +174,9 @@ namespace Mono.Security.X509 { { CheckStore (_storePath, true); + if (_newFormat) + throw new NotSupportedException (); + string filename = Path.Combine (_storePath, GetUniqueName (crl)); if (!File.Exists (filename)) { using (FileStream fs = File.Create (filename)) { @@ -177,6 +189,11 @@ namespace Mono.Security.X509 { public void Remove (X509Certificate certificate) { + if (_newFormat) { + RemoveNewFormat (certificate); + return; + } + string filename = Path.Combine (_storePath, GetUniqueNameWithSerial (certificate)); if (File.Exists (filename)) { File.Delete (filename); @@ -192,6 +209,9 @@ namespace Mono.Security.X509 { public void Remove (X509Crl crl) { + if (_newFormat) + throw new NotSupportedException (); + string filename = Path.Combine (_storePath, GetUniqueName (crl)); if (File.Exists (filename)) { File.Delete (filename); @@ -199,6 +219,41 @@ namespace Mono.Security.X509 { } } + // new format + + void ImportNewFormat (X509Certificate certificate) + { +#if INSIDE_CORLIB + throw new NotSupportedException (); +#else + using (var sscxCert = new SSCX.X509Certificate (certificate.RawData)) { + var hash = SSCX.X509Helper2.GetSubjectNameHash (sscxCert); + var filename = Path.Combine (_storePath, string.Format ("{0:x8}.0", hash)); + if (!File.Exists (filename)) { + using (FileStream fs = File.Create (filename)) + SSCX.X509Helper2.ExportAsPEM (sscxCert, fs, true); + ClearCertificates (); + } + } +#endif + } + + void RemoveNewFormat (X509Certificate certificate) + { +#if INSIDE_CORLIB + throw new NotSupportedException (); +#else + using (var sscxCert = new SSCX.X509Certificate (certificate.RawData)) { + var hash = SSCX.X509Helper2.GetSubjectNameHash (sscxCert); + var filename = Path.Combine (_storePath, string.Format ("{0:x8}.0", hash)); + if (File.Exists (filename)) { + File.Delete (filename); + ClearCertificates (); + } + } +#endif + } + // private stuff private string GetUniqueNameWithSerial (X509Certificate certificate) @@ -279,7 +334,7 @@ namespace Mono.Security.X509 { { byte[] data = Load (filename); X509Certificate cert = new X509Certificate (data); -#if !NET_2_1 +#if !MOBILE // If privateKey it's available, load it too.. CspParameters cspParams = new CspParameters (); cspParams.KeyContainerName = CryptoConvert.ToHex (cert.Hash); @@ -371,7 +426,7 @@ namespace Mono.Security.X509 { } return list; } -#if !NET_2_1 +#if !MOBILE private void ImportPrivateKey (X509Certificate certificate, CspParameters cspParams) { RSACryptoServiceProvider rsaCsp = certificate.RSA as RSACryptoServiceProvider; diff --git a/mcs/class/Mono.Security/Mono.Security.X509/X509StoreManager.cs b/mcs/class/Mono.Security/Mono.Security.X509/X509StoreManager.cs index db735834ac..7f31713b1b 100644 --- a/mcs/class/Mono.Security/Mono.Security.X509/X509StoreManager.cs +++ b/mcs/class/Mono.Security/Mono.Security.X509/X509StoreManager.cs @@ -45,8 +45,12 @@ namespace Mono.Security.X509 { static private string _userPath; static private string _localMachinePath; + static private string _newUserPath; + static private string _newLocalMachinePath; static private X509Stores _userStore; static private X509Stores _machineStore; + static private X509Stores _newUserStore; + static private X509Stores _newMachineStore; private X509StoreManager () { @@ -55,10 +59,10 @@ namespace Mono.Security.X509 { internal static string CurrentUserPath { get { if (_userPath == null) { - _userPath = Path.Combine( - Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), + _userPath = Path.Combine ( + Environment.GetFolderPath (Environment.SpecialFolder.ApplicationData), ".mono"); - _userPath = Path.Combine(_userPath, "certs"); + _userPath = Path.Combine (_userPath, "certs"); } return _userPath; } @@ -76,10 +80,34 @@ namespace Mono.Security.X509 { } } + internal static string NewCurrentUserPath { + get { + if (_newUserPath == null) { + _newUserPath = Path.Combine ( + Environment.GetFolderPath (Environment.SpecialFolder.ApplicationData), + ".mono"); + _newUserPath = Path.Combine (_newUserPath, "new-certs"); + } + return _newUserPath; + } + } + + internal static string NewLocalMachinePath { + get { + if (_newLocalMachinePath == null) { + _newLocalMachinePath = Path.Combine ( + Environment.GetFolderPath (Environment.SpecialFolder.CommonApplicationData), + ".mono"); + _newLocalMachinePath = Path.Combine (_newLocalMachinePath, "new-certs"); + } + return _newLocalMachinePath; + } + } + static public X509Stores CurrentUser { get { if (_userStore == null) - _userStore = new X509Stores(CurrentUserPath); + _userStore = new X509Stores (CurrentUserPath, false); return _userStore; } @@ -88,12 +116,30 @@ namespace Mono.Security.X509 { static public X509Stores LocalMachine { get { if (_machineStore == null) - _machineStore = new X509Stores (LocalMachinePath); + _machineStore = new X509Stores (LocalMachinePath, false); return _machineStore; } } + static public X509Stores NewCurrentUser { + get { + if (_newUserStore == null) + _newUserStore = new X509Stores (NewCurrentUserPath, true); + + return _newUserStore; + } + } + + static public X509Stores NewLocalMachine { + get { + if (_newMachineStore == null) + _newMachineStore = new X509Stores (NewLocalMachinePath, true); + + return _newMachineStore; + } + } + // Merged stores collections // we need to look at both the user and the machine (entreprise) // certificates/CRLs when building/validating a chain diff --git a/mcs/class/Mono.Security/Mono.Security.X509/X509Stores.cs b/mcs/class/Mono.Security/Mono.Security.X509/X509Stores.cs index bfe7451b5d..071faa70dd 100644 --- a/mcs/class/Mono.Security/Mono.Security.X509/X509Stores.cs +++ b/mcs/class/Mono.Security/Mono.Security.X509/X509Stores.cs @@ -44,15 +44,17 @@ namespace Mono.Security.X509 { class X509Stores { private string _storePath; + private bool _newFormat; private X509Store _personal; private X509Store _other; private X509Store _intermediate; private X509Store _trusted; private X509Store _untrusted; - internal X509Stores (string path) + internal X509Stores (string path, bool newFormat) { _storePath = path; + _newFormat = newFormat; } // properties @@ -61,7 +63,7 @@ namespace Mono.Security.X509 { get { if (_personal == null) { string path = Path.Combine (_storePath, Names.Personal); - _personal = new X509Store (path, false); + _personal = new X509Store (path, false, false); } return _personal; } @@ -71,7 +73,7 @@ namespace Mono.Security.X509 { get { if (_other == null) { string path = Path.Combine (_storePath, Names.OtherPeople); - _other = new X509Store (path, false); + _other = new X509Store (path, false, false); } return _other; } @@ -81,7 +83,7 @@ namespace Mono.Security.X509 { get { if (_intermediate == null) { string path = Path.Combine (_storePath, Names.IntermediateCA); - _intermediate = new X509Store (path, true); + _intermediate = new X509Store (path, true, _newFormat); } return _intermediate; } @@ -91,7 +93,7 @@ namespace Mono.Security.X509 { get { if (_trusted == null) { string path = Path.Combine (_storePath, Names.TrustedRoot); - _trusted = new X509Store (path, true); + _trusted = new X509Store (path, true, _newFormat); } return _trusted; } @@ -101,7 +103,7 @@ namespace Mono.Security.X509 { get { if (_untrusted == null) { string path = Path.Combine (_storePath, Names.Untrusted); - _untrusted = new X509Store (path, false); + _untrusted = new X509Store (path, false, _newFormat); } return _untrusted; } @@ -138,7 +140,7 @@ namespace Mono.Security.X509 { if (!create && !Directory.Exists (path)) return null; - return new X509Store (path, true); + return new X509Store (path, true, false); } // names @@ -151,7 +153,7 @@ namespace Mono.Security.X509 { public const string IntermediateCA = "CA"; public const string TrustedRoot = "Trust"; public const string Untrusted = "Disallowed"; - + public Names () {} } } diff --git a/mcs/class/Mono.Security/Mono.Security.dll.sources b/mcs/class/Mono.Security/Mono.Security.dll.sources index 652115f85a..65d146e17e 100644 --- a/mcs/class/Mono.Security/Mono.Security.dll.sources +++ b/mcs/class/Mono.Security/Mono.Security.dll.sources @@ -143,7 +143,6 @@ ./Mono.Security.Interface/HashAlgorithmType.cs ./Mono.Security.Interface/IBufferOffsetSize.cs ./Mono.Security.Interface/IMonoTlsEventSink.cs -./Mono.Security.Interface/IMonoTlsContext.cs ./Mono.Security.Interface/IMonoSslStream.cs ./Mono.Security.Interface/MonoTlsConnectionInfo.cs ./Mono.Security.Interface/MonoTlsProvider.cs diff --git a/mcs/class/Mono.Security/Test/Mono.Math/BigIntegerSetTest.cs b/mcs/class/Mono.Security/Test/Mono.Math/BigIntegerSetTest.cs index 989adb7697..56cec328ad 100644 --- a/mcs/class/Mono.Security/Test/Mono.Math/BigIntegerSetTest.cs +++ b/mcs/class/Mono.Security/Test/Mono.Math/BigIntegerSetTest.cs @@ -22,7 +22,7 @@ namespace MonoTests.Mono.Math { protected void Expect (BigInteger actual, BigInteger expected) { - Assertion.AssertEquals (Name, expected, actual); + Assert.AreEqual (expected, actual, Name); } } } diff --git a/mcs/class/Mono.Security/Test/Mono.Math/PrimeTestingTest.cs b/mcs/class/Mono.Security/Test/Mono.Math/PrimeTestingTest.cs index 4cf969f69d..2abf162a89 100644 --- a/mcs/class/Mono.Security/Test/Mono.Math/PrimeTestingTest.cs +++ b/mcs/class/Mono.Security/Test/Mono.Math/PrimeTestingTest.cs @@ -81,12 +81,12 @@ namespace MonoTests.Mono.Math { private void ExpectComposite (BigInteger bi) { - Assertion.AssertEquals (false, bi.IsProbablePrime ()); + Assert.AreEqual (false, bi.IsProbablePrime ()); } private void ExpectPrime (BigInteger bi) { - Assertion.AssertEquals (true, bi.IsProbablePrime ()); + Assert.AreEqual (true, bi.IsProbablePrime ()); } } @@ -195,7 +195,7 @@ namespace MonoTests.Mono.Math { // Adapted from http://lists.ximian.com/archives/public/mono-devel-list/2003-November/003026.html // Note: these primes are taken from RFC 2412 [http://www.faqs.org/rfcs/rfc2412.html] [TestFixture] - public class Rfc2412WellTestedPrimes : Assertion { + public class Rfc2412WellTestedPrimes { // E.1. Well-Known Group 1: A 768 bit prime [Test] @@ -203,8 +203,8 @@ namespace MonoTests.Mono.Math { { string prime = "1552518092300708935130918131258481755631334049434514313202351194902966239949102107258669453876591642442910007680288864229150803718918046342632727613031282983744380820890196288509170691316593175367469551763119843371637221007210577919"; BigInteger bi = BigInteger.Parse (prime); - Assert ("isProbablePrime-768", bi.IsProbablePrime ()); - AssertEquals ("ToString()", prime, bi.ToString ()); + Assert.IsTrue (bi.IsProbablePrime (), "isProbablePrime-768"); + Assert.AreEqual (prime, bi.ToString (), "ToString()"); } // E.2. Well-Known Group 2: A 1024 bit prime @@ -213,8 +213,8 @@ namespace MonoTests.Mono.Math { { string prime = "179769313486231590770839156793787453197860296048756011706444423684197180216158519368947833795864925541502180565485980503646440548199239100050792877003355816639229553136239076508735759914822574862575007425302077447712589550957937778424442426617334727629299387668709205606050270810842907692932019128194467627007"; BigInteger bi = BigInteger.Parse (prime); - Assert ("isProbablePrime-1024", bi.IsProbablePrime ()); - AssertEquals ("ToString()", prime, bi.ToString ()); + Assert.IsTrue (bi.IsProbablePrime (), "isProbablePrime-1024"); + Assert.AreEqual (prime, bi.ToString (), "ToString()"); } // Note: E.3 and E.4 are for Elliptic Curve Groups @@ -225,8 +225,8 @@ namespace MonoTests.Mono.Math { { string prime = "2410312426921032588552076022197566074856950548502459942654116941958108831682612228890093858261341614673227141477904012196503648957050582631942730706805009223062734745341073406696246014589361659774041027169249453200378729434170325843778659198143763193776859869524088940195577346119843545301547043747207749969763750084308926339295559968882457872412993810129130294592999947926365264059284647209730384947211681434464714438488520940127459844288859336526896320919633919"; BigInteger bi = BigInteger.Parse (prime); - Assert ("isProbablePrime-1536", bi.IsProbablePrime ()); - AssertEquals ("ToString()", prime, bi.ToString ()); + Assert.IsTrue (bi.IsProbablePrime (), "isProbablePrime-1536"); + Assert.AreEqual (prime, bi.ToString (), "ToString()"); } } diff --git a/mcs/class/Mono.Security/Test/Mono.Math/SearchGeneratorTest.cs b/mcs/class/Mono.Security/Test/Mono.Math/SearchGeneratorTest.cs index 80434f9983..e77246dc95 100644 --- a/mcs/class/Mono.Security/Test/Mono.Math/SearchGeneratorTest.cs +++ b/mcs/class/Mono.Security/Test/Mono.Math/SearchGeneratorTest.cs @@ -34,7 +34,7 @@ namespace MonoTests.Mono.Math { ContextData ctx = (ContextData)Context; - Assertion.AssertEquals (ctx.bits, bits); + Assert.AreEqual (ctx.bits, bits); uint d = ctx.testData; for (uint i = (uint)bits - 2; d > 0; i--, d >>= 1) @@ -65,7 +65,7 @@ namespace MonoTests.Mono.Math { Assert.IsTrue (p.TestBit (1)); uint d = ctx.testData; for (uint j = 128 - 2; d > 0; j--, d >>= 1) - Assertion.AssertEquals ((d&1) == 1, p.TestBit (j)); + Assert.AreEqual ((d&1) == 1, p.TestBit (j)); } } } diff --git a/mcs/class/Mono.Security/Test/Mono.Security.Authenticode/PrivateKeyTest.cs b/mcs/class/Mono.Security/Test/Mono.Security.Authenticode/PrivateKeyTest.cs index 0f529496e1..8696657715 100644 --- a/mcs/class/Mono.Security/Test/Mono.Security.Authenticode/PrivateKeyTest.cs +++ b/mcs/class/Mono.Security/Test/Mono.Security.Authenticode/PrivateKeyTest.cs @@ -68,7 +68,7 @@ namespace MonoTests.Mono.Security.Authenticode { // makecert -n "CN=PVK1" -sv 1.pvk 1.cer [TestFixture] -public class PrivateKeyTest : Assertion { +public class PrivateKeyTest { // because most crypto stuff works with byte[] buffers static public void AssertEquals (string msg, byte[] array1, byte[] array2) @@ -76,9 +76,9 @@ public class PrivateKeyTest : Assertion { if ((array1 == null) && (array2 == null)) return; if (array1 == null) - Fail (msg + " -> First array is NULL"); + Assert.Fail (msg + " -> First array is NULL"); if (array2 == null) - Fail (msg + " -> Second array is NULL"); + Assert.Fail (msg + " -> Second array is NULL"); bool a = (array1.Length == array2.Length); if (a) { @@ -93,7 +93,7 @@ public class PrivateKeyTest : Assertion { msg += " -> Expected " + BitConverter.ToString (array1, 0); msg += " is different than " + BitConverter.ToString (array2, 0); } - Assert (msg, a); + Assert.IsTrue (a, msg); } string testfile; @@ -152,10 +152,10 @@ public class PrivateKeyTest : Assertion { { WriteBuffer (nopwd); PrivateKey pvk = PrivateKey.CreateFromFile (testfile); - AssertNotNull ("msnopwd.RSA", pvk.RSA); - Assert ("msnopwd.Encrypted", !pvk.Encrypted); - Assert ("msnopwd.Weak", pvk.Weak); - AssertEquals ("msnopwd.KeyType", 2, pvk.KeyType); + Assert.IsNotNull (pvk.RSA, "msnopwd.RSA"); + Assert.IsTrue (!pvk.Encrypted, "msnopwd.Encrypted"); + Assert.IsTrue (pvk.Weak, "msnopwd.Weak"); + Assert.AreEqual (2, pvk.KeyType, "msnopwd.KeyType"); } // this will convert a PVK file without a password to a PVK file @@ -168,11 +168,11 @@ public class PrivateKeyTest : Assertion { string rsa1 = pvk.RSA.ToXmlString (true); pvk.Save (testfile, "password"); pvk = PrivateKey.CreateFromFile (testfile, "password"); - AssertNotNull ("topwd.RSA", pvk.RSA); + Assert.IsNotNull (pvk.RSA, "topwd.RSA"); string rsa2 = pvk.RSA.ToXmlString (true); - AssertEquals ("topwd.RSA identical", rsa1, rsa2); - Assert ("topwd.Encrypted", pvk.Encrypted); - Assert ("topwd.Weak", pvk.Weak); + Assert.AreEqual (rsa1, rsa2, "topwd.RSA identical"); + Assert.IsTrue (pvk.Encrypted, "topwd.Encrypted"); + Assert.IsTrue (pvk.Weak, "topwd.Weak"); } // this will convert a PVK file without a password to a PVK file @@ -186,11 +186,11 @@ public class PrivateKeyTest : Assertion { pvk.Weak = false; // we want strong crypto pvk.Save (testfile, "password"); pvk = PrivateKey.CreateFromFile (testfile, "password"); - AssertNotNull ("topwd.RSA", pvk.RSA); + Assert.IsNotNull (pvk.RSA, "topwd.RSA"); string rsa2 = pvk.RSA.ToXmlString (true); - AssertEquals ("topwd.RSA identical", rsa1, rsa2); - Assert ("topwd.Encrypted", pvk.Encrypted); - Assert ("topwd.Weak", !pvk.Weak); + Assert.AreEqual (rsa1, rsa2, "topwd.RSA identical"); + Assert.IsTrue (pvk.Encrypted, "topwd.Encrypted"); + Assert.IsTrue (!pvk.Weak, "topwd.Weak"); } static byte[] pwd = { @@ -229,9 +229,9 @@ public class PrivateKeyTest : Assertion { { WriteBuffer (pwd); PrivateKey pvk = PrivateKey.CreateFromFile (testfile, "password"); - AssertNotNull ("mspwd.RSA", pvk.RSA); - Assert ("mspwd.Encrypted", pvk.Encrypted); - Assert ("mspwd.Weak", pvk.Weak); + Assert.IsNotNull (pvk.RSA, "mspwd.RSA"); + Assert.IsTrue (pvk.Encrypted, "mspwd.Encrypted"); + Assert.IsTrue (pvk.Weak, "mspwd.Weak"); } // this will convert a PVK file with a password to a PVK file @@ -244,11 +244,11 @@ public class PrivateKeyTest : Assertion { string rsa1 = pvk.RSA.ToXmlString (true); pvk.Save (testfile); pvk = PrivateKey.CreateFromFile (testfile); - AssertNotNull ("nomorepwd.RSA", pvk.RSA); + Assert.IsNotNull (pvk.RSA, "nomorepwd.RSA"); string rsa2 = pvk.RSA.ToXmlString (true); - AssertEquals ("nomorepwd.RSA identical", rsa1, rsa2); - Assert ("nomorepwd.Encrypted", !pvk.Encrypted); - Assert ("nomorepwd.Weak", pvk.Weak); + Assert.AreEqual (rsa1, rsa2, "nomorepwd.RSA identical"); + Assert.IsTrue (!pvk.Encrypted, "nomorepwd.Encrypted"); + Assert.IsTrue (pvk.Weak, "nomorepwd.Weak"); } [Test] @@ -261,11 +261,11 @@ public class PrivateKeyTest : Assertion { pvk.Save (testfile, "mono"); pvk = PrivateKey.CreateFromFile (testfile, "mono"); - AssertNotNull ("new.RSA", pvk.RSA); + Assert.IsNotNull (pvk.RSA, "new.RSA"); string rsa2 = pvk.RSA.ToXmlString (true); - AssertEquals ("new.RSA identical", rsa1, rsa2); - Assert ("new.Encrypted", pvk.Encrypted); - Assert ("new.Weak", !pvk.Weak); + Assert.AreEqual (rsa1, rsa2, "new.RSA identical"); + Assert.IsTrue (pvk.Encrypted, "new.Encrypted"); + Assert.IsTrue (!pvk.Weak, "new.Weak"); } [Test] diff --git a/mcs/class/Mono.Security/Test/Mono.Security.Cryptography/CryptoConvertTest.cs b/mcs/class/Mono.Security/Test/Mono.Security.Cryptography/CryptoConvertTest.cs index 38ecbc3b23..a527208839 100644 --- a/mcs/class/Mono.Security/Test/Mono.Security.Cryptography/CryptoConvertTest.cs +++ b/mcs/class/Mono.Security/Test/Mono.Security.Cryptography/CryptoConvertTest.cs @@ -15,7 +15,7 @@ using Mono.Security.Cryptography; namespace MonoTests.Mono.Security.Cryptography { [TestFixture] - public class CryptoConvertTest : Assertion { + public class CryptoConvertTest { // because most crypto stuff works with byte[] buffers static public void AssertEquals (string msg, byte[] array1, byte[] array2) @@ -23,9 +23,9 @@ namespace MonoTests.Mono.Security.Cryptography { if ((array1 == null) && (array2 == null)) return; if (array1 == null) - Fail (msg + " -> First array is NULL"); + Assert.Fail (msg + " -> First array is NULL"); if (array2 == null) - Fail (msg + " -> Second array is NULL"); + Assert.Fail (msg + " -> Second array is NULL"); bool a = (array1.Length == array2.Length); if (a) { @@ -38,7 +38,7 @@ namespace MonoTests.Mono.Security.Cryptography { } msg += " -> Expected " + BitConverter.ToString (array1, 0); msg += " is different than " + BitConverter.ToString (array2, 0); - Assert (msg, a); + Assert.IsTrue (a, msg); } // strongname generated using "sn -k unit.snk" @@ -163,16 +163,16 @@ namespace MonoTests.Mono.Security.Cryptography { { // keypair RSA rsa = CryptoConvert.FromCapiKeyBlob (strongName, 0); - AssertEquals ("KeyPair", strongNameString, rsa.ToXmlString (true)); - AssertEquals ("PublicKey-1", strongNamePublicKeyString, rsa.ToXmlString (false)); + Assert.AreEqual (strongNameString, rsa.ToXmlString (true), "KeyPair"); + Assert.AreEqual (strongNamePublicKeyString, rsa.ToXmlString (false), "PublicKey-1"); // public key (direct) rsa = CryptoConvert.FromCapiKeyBlob (strongNamePublicKey, 12); - AssertEquals ("PublicKey-2", strongNamePublicKeyString, rsa.ToXmlString (false)); + Assert.AreEqual (strongNamePublicKeyString, rsa.ToXmlString (false), "PublicKey-2"); // public key (indirect - inside header) rsa = CryptoConvert.FromCapiKeyBlob (strongNamePublicKey, 0); - AssertEquals ("PublicKey-3", strongNamePublicKeyString, rsa.ToXmlString (false)); + Assert.AreEqual (strongNamePublicKeyString, rsa.ToXmlString (false), "PublicKey-3"); } [Test] @@ -201,7 +201,7 @@ namespace MonoTests.Mono.Security.Cryptography { public void FromCapiPrivateKeyBlob () { RSA rsa = CryptoConvert.FromCapiPrivateKeyBlob (strongName, 0); - AssertEquals ("KeyPair", strongNameString, rsa.ToXmlString (true)); + Assert.AreEqual (strongNameString, rsa.ToXmlString (true), "KeyPair"); } [Test] @@ -229,7 +229,7 @@ namespace MonoTests.Mono.Security.Cryptography { public void FromCapiPublicKeyBlob () { RSA rsa = CryptoConvert.FromCapiPublicKeyBlob (strongNamePublicKey, 12); - AssertEquals ("PublicKey", strongNamePublicKeyString, rsa.ToXmlString (false)); + Assert.AreEqual (strongNamePublicKeyString, rsa.ToXmlString (false), "PublicKey"); } [Test] @@ -262,12 +262,12 @@ namespace MonoTests.Mono.Security.Cryptography { AssertEquals ("RSA-KeyPair", strongName, keypair); byte[] publicKey = CryptoConvert.ToCapiKeyBlob (rsa, false); - AssertEquals ("RSA-PublicKey", BitConverter.ToString (strongNamePublicKey, 12), BitConverter.ToString (publicKey)); + Assert.AreEqual (BitConverter.ToString (strongNamePublicKey, 12), BitConverter.ToString (publicKey), "RSA-PublicKey"); AsymmetricAlgorithm dsa = DSA.Create (); dsa.FromXmlString (dsaKeyPairString); AssertEquals ("DSA-KeyPair", dsaPrivBlob, CryptoConvert.ToCapiKeyBlob (dsa, true)); - AssertEquals ("DSA-PublicKey", BitConverter.ToString (dsaPubBlob), BitConverter.ToString (CryptoConvert.ToCapiKeyBlob (dsa, false))); + Assert.AreEqual (BitConverter.ToString (dsaPubBlob), BitConverter.ToString (CryptoConvert.ToCapiKeyBlob (dsa, false)), "DSA-PublicKey"); } [Test] @@ -279,7 +279,7 @@ namespace MonoTests.Mono.Security.Cryptography { AssertEquals ("KeyPair", strongName, keypair); byte[] publicKey = CryptoConvert.ToCapiKeyBlob (rsa, false); - AssertEquals ("PublicKey", BitConverter.ToString (strongNamePublicKey, 12), BitConverter.ToString (publicKey)); + Assert.AreEqual (BitConverter.ToString (strongNamePublicKey, 12), BitConverter.ToString (publicKey), "PublicKey"); } [Test] @@ -323,11 +323,11 @@ namespace MonoTests.Mono.Security.Cryptography { // full keypair rsa.FromXmlString (strongNameString); byte[] publicKey = CryptoConvert.ToCapiPublicKeyBlob (rsa); - AssertEquals ("PublicKey-1", BitConverter.ToString (strongNamePublicKey, 12), BitConverter.ToString (publicKey)); + Assert.AreEqual (BitConverter.ToString (strongNamePublicKey, 12), BitConverter.ToString (publicKey), "PublicKey-1"); // public key only rsa.FromXmlString (strongNamePublicKeyString); publicKey = CryptoConvert.ToCapiPublicKeyBlob (rsa); - AssertEquals ("PublicKey-2", BitConverter.ToString (strongNamePublicKey, 12), BitConverter.ToString (publicKey)); + Assert.AreEqual (BitConverter.ToString (strongNamePublicKey, 12), BitConverter.ToString (publicKey), "PublicKey-2"); } /* DSA key tests */ @@ -419,8 +419,8 @@ namespace MonoTests.Mono.Security.Cryptography { public void FromCapiKeyBlobDSA () { DSA dsa = CryptoConvert.FromCapiKeyBlobDSA (dsaPrivBlob); - AssertEquals ("KeyPair", dsaKeyPairString, dsa.ToXmlString (true)); - AssertEquals ("PublicKey", dsaPubKeyString, dsa.ToXmlString (false)); + Assert.AreEqual (dsaKeyPairString, dsa.ToXmlString (true), "KeyPair"); + Assert.AreEqual (dsaPubKeyString, dsa.ToXmlString (false), "PublicKey"); } [Test] @@ -449,7 +449,7 @@ namespace MonoTests.Mono.Security.Cryptography { public void FromCapiPrivateKeyBlobDSA () { DSA dsa = CryptoConvert.FromCapiPrivateKeyBlobDSA (dsaPrivBlob, 0); - AssertEquals ("KeyPair", dsaKeyPairString, dsa.ToXmlString (true)); + Assert.AreEqual (dsaKeyPairString, dsa.ToXmlString (true), "KeyPair"); } [Test] @@ -478,7 +478,7 @@ namespace MonoTests.Mono.Security.Cryptography { public void FromCapiPublicKeyBlobDSA () { DSA dsa = CryptoConvert.FromCapiPublicKeyBlobDSA (dsaPubBlob, 0); - AssertEquals ("PublicKey", dsaPubKeyString, dsa.ToXmlString (false)); + Assert.AreEqual (dsaPubKeyString, dsa.ToXmlString (false), "PublicKey"); } [Test] @@ -512,7 +512,7 @@ namespace MonoTests.Mono.Security.Cryptography { AssertEquals ("KeyPair", dsaPrivBlob, keypair); byte[] pubkey = CryptoConvert.ToCapiKeyBlob (dsa, false); - AssertEquals ("PublicKey", BitConverter.ToString (dsaPubBlob), BitConverter.ToString (pubkey)); + Assert.AreEqual (BitConverter.ToString (dsaPubBlob), BitConverter.ToString (pubkey), "PublicKey"); } [Test] @@ -548,20 +548,20 @@ namespace MonoTests.Mono.Security.Cryptography { // full keypair dsa.FromXmlString (dsaKeyPairString); byte[] pubkey = CryptoConvert.ToCapiPublicKeyBlob (dsa); - AssertEquals ("PublicKey-1", BitConverter.ToString (dsaPubBlob), BitConverter.ToString (pubkey)); + Assert.AreEqual (BitConverter.ToString (dsaPubBlob), BitConverter.ToString (pubkey), "PublicKey-1"); // public key only dsa.FromXmlString (dsaPubKeyString); pubkey = CryptoConvert.ToCapiPublicKeyBlob (dsa); - AssertEquals ("PublicKey-2", BitConverter.ToString (dsaPubBlob), BitConverter.ToString (pubkey)); + Assert.AreEqual (BitConverter.ToString (dsaPubBlob), BitConverter.ToString (pubkey), "PublicKey-2"); } [Test] public void FromHex () { - AssertNull ("FromHex(null)", CryptoConvert.FromHex (null)); + Assert.IsNull (CryptoConvert.FromHex (null), "FromHex(null)"); string result = BitConverter.ToString (CryptoConvert.FromHex ("0123456789aBcDeF")); - AssertEquals ("0123456789abcdef", "01-23-45-67-89-AB-CD-EF", result); + Assert.AreEqual ("01-23-45-67-89-AB-CD-EF", result, "0123456789abcdef"); } [Test] @@ -581,9 +581,9 @@ namespace MonoTests.Mono.Security.Cryptography { [Test] public void ToHex () { - AssertNull ("FromHex(null)", CryptoConvert.FromHex (null)); + Assert.IsNull (CryptoConvert.FromHex (null), "FromHex(null)"); byte[] data = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }; - AssertEquals ("0123456789abcdef", "0123456789ABCDEF", CryptoConvert.ToHex (data)); + Assert.AreEqual ("0123456789ABCDEF", CryptoConvert.ToHex (data), "0123456789abcdef"); } [Test] @@ -595,8 +595,8 @@ namespace MonoTests.Mono.Security.Cryptography { RSA rsa = CryptoConvert.FromCapiKeyBlob (strongNameNUnit, 0); // note the bad D parameters !!! // this only works because CRT is being used - AssertEquals ("KeyPair", "rB8h0TaMs8fWA+5WMdcjOjejCZwhYwuFHUZPS0cC9TOG6FJtvlHPpZLQAg0xfLr2SivPRol1Xw9SqhuaYQNJA7sAaOb8Rvgmx93XbmcNotY9ob4TGaesk+M8VsdexsIJ3WlyLbmRlf0EjT52nboyauEL3UC85zkMjW1LNb8LSs8=AQAB

2d4pGForvc792ztFxhNuzxIihDnXp+qK9F8t/NduhRBdu+JXK4d8a9EGwzpMxLUPlHjCZfXRraZiSQszkH+nzQ==

yj9BeGmOrucOUCNZYTtXI0ykzz+1g+cVMSxi+6xzoLEOqmdE4gjcWaxak4MF1+pIR6UycnNa/jg1LBl7MKxpCw==cMkAjznG4Sjx4/dIRKU0vP/PXJIxIR1bN+y5+uVvsnTpgWVH6SHneE0qahCZQ0/UM/Fb+bqLBJFY2iVxWUGslQ==gz6TXPGbLzMv3Z9i5C8e+ABHv1pHj6ZI4VU9kraxfmkH7FsBn3FClUq8qJdRFnGpoBy65Pyo4upUzx5mDAsGSw==x+UShV+0d9cicoiB9fkSLqpLDyF4dYzVu0uqX0eCcoGJpk19jtSaMI3Eo8VN6MJAW1zrRy+MA1Fqb9qeThLqZQ==AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
", rsa.ToXmlString (true)); - AssertEquals ("PublicKey", "rB8h0TaMs8fWA+5WMdcjOjejCZwhYwuFHUZPS0cC9TOG6FJtvlHPpZLQAg0xfLr2SivPRol1Xw9SqhuaYQNJA7sAaOb8Rvgmx93XbmcNotY9ob4TGaesk+M8VsdexsIJ3WlyLbmRlf0EjT52nboyauEL3UC85zkMjW1LNb8LSs8=AQAB", rsa.ToXmlString (false)); + Assert.AreEqual ("rB8h0TaMs8fWA+5WMdcjOjejCZwhYwuFHUZPS0cC9TOG6FJtvlHPpZLQAg0xfLr2SivPRol1Xw9SqhuaYQNJA7sAaOb8Rvgmx93XbmcNotY9ob4TGaesk+M8VsdexsIJ3WlyLbmRlf0EjT52nboyauEL3UC85zkMjW1LNb8LSs8=AQAB

2d4pGForvc792ztFxhNuzxIihDnXp+qK9F8t/NduhRBdu+JXK4d8a9EGwzpMxLUPlHjCZfXRraZiSQszkH+nzQ==

yj9BeGmOrucOUCNZYTtXI0ykzz+1g+cVMSxi+6xzoLEOqmdE4gjcWaxak4MF1+pIR6UycnNa/jg1LBl7MKxpCw==cMkAjznG4Sjx4/dIRKU0vP/PXJIxIR1bN+y5+uVvsnTpgWVH6SHneE0qahCZQ0/UM/Fb+bqLBJFY2iVxWUGslQ==gz6TXPGbLzMv3Z9i5C8e+ABHv1pHj6ZI4VU9kraxfmkH7FsBn3FClUq8qJdRFnGpoBy65Pyo4upUzx5mDAsGSw==x+UShV+0d9cicoiB9fkSLqpLDyF4dYzVu0uqX0eCcoGJpk19jtSaMI3Eo8VN6MJAW1zrRy+MA1Fqb9qeThLqZQ==AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
", rsa.ToXmlString (true), "KeyPair"); + Assert.AreEqual ("rB8h0TaMs8fWA+5WMdcjOjejCZwhYwuFHUZPS0cC9TOG6FJtvlHPpZLQAg0xfLr2SivPRol1Xw9SqhuaYQNJA7sAaOb8Rvgmx93XbmcNotY9ob4TGaesk+M8VsdexsIJ3WlyLbmRlf0EjT52nboyauEL3UC85zkMjW1LNb8LSs8=AQAB", rsa.ToXmlString (false), "PublicKey"); } } } diff --git a/mcs/class/Mono.Security/Test/Mono.Security.Cryptography/DiffieHellmanManagedTest.cs b/mcs/class/Mono.Security/Test/Mono.Security.Cryptography/DiffieHellmanManagedTest.cs index 2a38eb819d..a0d3caf1f7 100644 --- a/mcs/class/Mono.Security/Test/Mono.Security.Cryptography/DiffieHellmanManagedTest.cs +++ b/mcs/class/Mono.Security/Test/Mono.Security.Cryptography/DiffieHellmanManagedTest.cs @@ -24,7 +24,7 @@ namespace MonoTests.Mono.Security.Cryptography { // http://www.ietf.org/rfc/rfc2631.txt [TestFixture] - public class DiffieHellmanManagedTest : Assertion { + public class DiffieHellmanManagedTest { // because most crypto stuff works with byte[] buffers static public void AssertEquals (string msg, byte[] array1, byte[] array2) @@ -32,9 +32,9 @@ namespace MonoTests.Mono.Security.Cryptography { if ((array1 == null) && (array2 == null)) return; if (array1 == null) - Assertion.Fail (msg + " -> First array is NULL"); + Assert.Fail (msg + " -> First array is NULL"); if (array2 == null) - Assertion.Fail (msg + " -> Second array is NULL"); + Assert.Fail (msg + " -> Second array is NULL"); bool a = (array1.Length == array2.Length); if (a) { @@ -49,7 +49,7 @@ namespace MonoTests.Mono.Security.Cryptography { msg += " -> Expected " + BitConverter.ToString (array1, 0); msg += " is different than " + BitConverter.ToString (array2, 0); } - Assertion.Assert (msg, a); + Assert.IsTrue (a, msg); } [Test] @@ -70,7 +70,7 @@ namespace MonoTests.Mono.Security.Cryptography { // let the second DH instance compute the shared secret using the first DH public key byte[] dh2k = dh2.DecryptKeyExchange (ke1); // both shared secrets are the same - AssertEquals ("Shared Secret", dh1k, dh2k); + Assert.AreEqual (dh1k, dh2k, "Shared Secret"); } // TODO: More is needed ! diff --git a/mcs/class/Mono.Security/Test/Mono.Security.Cryptography/PKCS8Test.cs b/mcs/class/Mono.Security/Test/Mono.Security.Cryptography/PKCS8Test.cs index 42f7584e1c..8ec9779b2d 100644 --- a/mcs/class/Mono.Security/Test/Mono.Security.Cryptography/PKCS8Test.cs +++ b/mcs/class/Mono.Security/Test/Mono.Security.Cryptography/PKCS8Test.cs @@ -19,7 +19,7 @@ using NUnit.Framework; namespace MonoTests.Mono.Security.Cryptography { [TestFixture] - public class PKCS8Test : Assertion { + public class PKCS8Test { static public byte[] pkcs8_der = { 0x30, 0x82, 0x02, 0xB2, 0x30, 0x1C, 0x06, 0x0A, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0C, 0x01, 0x03, 0x30, 0x0E, 0x04, 0x08, 0x86, 0x2A, 0xA9, 0x71, 0x6D, 0xA4, 0xB8, 0x2D, 0x02, 0x02, 0x07, 0xD0, 0x04, 0x82, 0x02, 0x90, 0x90, 0x14, 0xB5, 0xF0, 0xB6, 0x86, 0x56, 0xCB, 0xFA, 0x63, 0xAD, 0x9F, 0x5A, 0x59, 0x6C, 0xAD, 0x00, 0x3C, 0x37, 0x8A, 0xC3, 0x88, 0x58, 0x8B, 0xD7, 0x48, 0x53, 0x7A, 0xC8, 0x5B, 0x0D, 0x98, 0xDD, 0x8B, 0xB3, 0xEC, 0x4C, 0xAC, 0x61, 0x18, 0xE3, 0x5E, 0x47, 0xAD, 0xC7, 0x92, 0xBC, 0xD3, 0x00, 0x07, 0xFF, 0x1A, 0x68, 0x74, 0x45, 0x8E, 0xD8, 0x7C, 0x9F, 0x18, 0x7B, 0xD7, 0xC8, 0x47, 0xBA, 0x6B, 0x19, 0xF2, 0xBF, 0x7E, 0x51, 0x0B, 0x4B, 0x43, 0xE8, 0xB9, 0x56, 0x7E, 0xD0, 0x74, 0xC7, 0xDE, 0x76, 0xDB, 0xFF, 0x5C, 0x6B, 0x53, 0xBE, 0x31, 0x06, 0xAE, 0x6C, 0x8F, 0xDC, 0x49, 0x04, 0x71, 0x74, 0xEE, 0xB8, 0x06, 0xCB, 0xAD, 0x86, 0xB4, 0x4E, 0xB9, 0x46, 0xA1, 0x03, 0x5E, 0x0E, 0xA7, 0xC7, 0x37, 0x6B, 0xB0, 0x8D, 0x2D, 0x81, 0x1F, 0xE3, 0xC2, 0x05, 0xDE, 0xEF, 0x51, 0x07, 0x70, 0x6E, 0x35, 0x9A, 0xAD, 0x19, 0x5E, 0xAF, 0xEB, 0x7F, 0xEF, 0xE4, 0xAB, 0x07, 0xF3, 0xF6, 0xEA, 0xFA, 0x0E, 0x83, 0x65, 0x06, 0x3C, 0xF3, 0xBD, 0x96, 0x08, 0x14, 0xC5, 0x34, 0x26, 0xED, 0xC0, 0x10, @@ -32,13 +32,13 @@ namespace MonoTests.Mono.Security.Cryptography { [Test] public void EncryptedPrivateKey_Farscape () { - AssertEquals ("PKCS8.GetType", PKCS8.KeyInfo.EncryptedPrivateKey, PKCS8.GetType (pkcs8_der)); + Assert.AreEqual (PKCS8.KeyInfo.EncryptedPrivateKey, PKCS8.GetType (pkcs8_der), "PKCS8.GetType"); PKCS8.EncryptedPrivateKeyInfo p8 = new PKCS8.EncryptedPrivateKeyInfo (pkcs8_der); - AssertEquals ("Algorithm", "1.2.840.113549.1.12.1.3", p8.Algorithm); - AssertEquals ("EncryptedData", "90-14-B5-F0-B6-86-56-CB-FA-63-AD-9F-5A-59-6C-AD-00-3C-37-8A-C3-88-58-8B-D7-48-53-7A-C8-5B-0D-98-DD-8B-B3-EC-4C-AC-61-18-E3-5E-47-AD-C7-92-BC-D3-00-07-FF-1A-68-74-45-8E-D8-7C-9F-18-7B-D7-C8-47-BA-6B-19-F2-BF-7E-51-0B-4B-43-E8-B9-56-7E-D0-74-C7-DE-76-DB-FF-5C-6B-53-BE-31-06-AE-6C-8F-DC-49-04-71-74-EE-B8-06-CB-AD-86-B4-4E-B9-46-A1-03-5E-0E-A7-C7-37-6B-B0-8D-2D-81-1F-E3-C2-05-DE-EF-51-07-70-6E-35-9A-AD-19-5E-AF-EB-7F-EF-E4-AB-07-F3-F6-EA-FA-0E-83-65-06-3C-F3-BD-96-08-14-C5-34-26-ED-C0-10-CC-AE-2D-8F-BE-ED-98-0D-88-1B-1E-C7-37-F0-FC-DB-3C-E3-1B-66-52-45-6E-05-A6-D9-12-23-05-5F-E3-9F-7D-21-9B-2E-3E-9E-3C-EE-D1-9B-55-DE-57-60-A5-24-2D-C7-94-EC-FC-B1-6A-65-BD-85-02-5C-58-AA-5A-6A-F3-AC-6B-DD-0E-63-B2-4B-5B-67-3D-C3-BF-E4-C8-EF-3F-89-5A-CD-6D-EF-05-22-2B-72-FF-80-7A-DD-F1-59-A7-6F-00-B1-BD-4D-88-D6-E4-8A-DD-A9-FC-D9-01-0A-65-8E-52-F9-7E-20-72-67-0D-5B-EE-67-5B-46-4A-15-A2-6F-15-2B-5B-9A-93-12-4F-F4-AD-49-D0-11-F1-7E-40-DE-32-96-2E-B3-E8-71-60-27-6E-A2-71-83-C7-FE-0E-8B-31-06-64-E1-19-02-B9-44-25-0C-94-64-7E-5F-89-4D-7E-99-0B-91-B8-22-A5-33-92-D3-49-07-1D-C6-25-4A-D7-6D-E2-94-3F-FA-10-72-59-62-F5-C6-D4-3A-EE-8F-BC-9C-BC-FC-C7-37-BF-7C-A0-67-B0-FF-0F-29-A0-A2-71-6B-21-00-F4-54-D9-3D-1B-CE-F4-FE-6F-F5-21-CB-47-58-17-F6-45-2F-A0-3B-8B-D9-B8-8A-33-3F-16-E0-C7-8A-B8-11-2F-A8-7E-7D-A7-7B-65-27-89-3C-67-4D-D5-70-28-76-60-96-68-BF-FB-CD-49-E0-8A-7C-6F-76-06-48-6D-63-67-8A-47-82-5E-7F-0E-AC-46-B6-BC-0A-6D-E2-1A-3A-20-A5-C7-81-71-6E-2B-16-97-D4-FA-C0-DD-72-5B-9F-A3-43-F4-85-B1-C6-A8-E0-62-81-5D-A5-07-29-6A-6A-2D-E1-1D-BE-12-6D-42-58-6F-4E-30-3D-BF-32-11-38-BC-36-76-60-FC-57-2F-D3-9E-C4-1A-92-EA-DE-85-FD-E7-AA-30-A6-97-2C-36-3B-3B-0E-92-52-FF-42-D7-62-6C-C1-3A-E7-1B-4E-13-8C-95-B3-4B-A7-9E-42-75-A8-CA-63-76-C4-45-74-96-43-D8-86-82-BE-37-FF-9B-EB-B7-18-A1-2F-E3-6C-08-E8-11-96-8C-5E-9E-2B-E7-DB-7D-54-E1-DB-1E-D3-8F-B5-19-4B-B2-16-DB-CF-EC-88-0B-6C-3C-E4-F2-C4-FF-4D-3E-53-52-3A-81-0B-6E-AC-95-EA-5A-6E-4D-83-23-82-C9-90-02-74-10-2A-6C-FB-97-4F-5F-70-8E-F0-B9", - BitConverter.ToString (p8.EncryptedData)); - AssertEquals ("Salt", "86-2A-A9-71-6D-A4-B8-2D", BitConverter.ToString (p8.Salt)); - AssertEquals ("IterationCount", 2000, p8.IterationCount); + Assert.AreEqual ("1.2.840.113549.1.12.1.3", p8.Algorithm, "Algorithm"); + Assert.AreEqual ("90-14-B5-F0-B6-86-56-CB-FA-63-AD-9F-5A-59-6C-AD-00-3C-37-8A-C3-88-58-8B-D7-48-53-7A-C8-5B-0D-98-DD-8B-B3-EC-4C-AC-61-18-E3-5E-47-AD-C7-92-BC-D3-00-07-FF-1A-68-74-45-8E-D8-7C-9F-18-7B-D7-C8-47-BA-6B-19-F2-BF-7E-51-0B-4B-43-E8-B9-56-7E-D0-74-C7-DE-76-DB-FF-5C-6B-53-BE-31-06-AE-6C-8F-DC-49-04-71-74-EE-B8-06-CB-AD-86-B4-4E-B9-46-A1-03-5E-0E-A7-C7-37-6B-B0-8D-2D-81-1F-E3-C2-05-DE-EF-51-07-70-6E-35-9A-AD-19-5E-AF-EB-7F-EF-E4-AB-07-F3-F6-EA-FA-0E-83-65-06-3C-F3-BD-96-08-14-C5-34-26-ED-C0-10-CC-AE-2D-8F-BE-ED-98-0D-88-1B-1E-C7-37-F0-FC-DB-3C-E3-1B-66-52-45-6E-05-A6-D9-12-23-05-5F-E3-9F-7D-21-9B-2E-3E-9E-3C-EE-D1-9B-55-DE-57-60-A5-24-2D-C7-94-EC-FC-B1-6A-65-BD-85-02-5C-58-AA-5A-6A-F3-AC-6B-DD-0E-63-B2-4B-5B-67-3D-C3-BF-E4-C8-EF-3F-89-5A-CD-6D-EF-05-22-2B-72-FF-80-7A-DD-F1-59-A7-6F-00-B1-BD-4D-88-D6-E4-8A-DD-A9-FC-D9-01-0A-65-8E-52-F9-7E-20-72-67-0D-5B-EE-67-5B-46-4A-15-A2-6F-15-2B-5B-9A-93-12-4F-F4-AD-49-D0-11-F1-7E-40-DE-32-96-2E-B3-E8-71-60-27-6E-A2-71-83-C7-FE-0E-8B-31-06-64-E1-19-02-B9-44-25-0C-94-64-7E-5F-89-4D-7E-99-0B-91-B8-22-A5-33-92-D3-49-07-1D-C6-25-4A-D7-6D-E2-94-3F-FA-10-72-59-62-F5-C6-D4-3A-EE-8F-BC-9C-BC-FC-C7-37-BF-7C-A0-67-B0-FF-0F-29-A0-A2-71-6B-21-00-F4-54-D9-3D-1B-CE-F4-FE-6F-F5-21-CB-47-58-17-F6-45-2F-A0-3B-8B-D9-B8-8A-33-3F-16-E0-C7-8A-B8-11-2F-A8-7E-7D-A7-7B-65-27-89-3C-67-4D-D5-70-28-76-60-96-68-BF-FB-CD-49-E0-8A-7C-6F-76-06-48-6D-63-67-8A-47-82-5E-7F-0E-AC-46-B6-BC-0A-6D-E2-1A-3A-20-A5-C7-81-71-6E-2B-16-97-D4-FA-C0-DD-72-5B-9F-A3-43-F4-85-B1-C6-A8-E0-62-81-5D-A5-07-29-6A-6A-2D-E1-1D-BE-12-6D-42-58-6F-4E-30-3D-BF-32-11-38-BC-36-76-60-FC-57-2F-D3-9E-C4-1A-92-EA-DE-85-FD-E7-AA-30-A6-97-2C-36-3B-3B-0E-92-52-FF-42-D7-62-6C-C1-3A-E7-1B-4E-13-8C-95-B3-4B-A7-9E-42-75-A8-CA-63-76-C4-45-74-96-43-D8-86-82-BE-37-FF-9B-EB-B7-18-A1-2F-E3-6C-08-E8-11-96-8C-5E-9E-2B-E7-DB-7D-54-E1-DB-1E-D3-8F-B5-19-4B-B2-16-DB-CF-EC-88-0B-6C-3C-E4-F2-C4-FF-4D-3E-53-52-3A-81-0B-6E-AC-95-EA-5A-6E-4D-83-23-82-C9-90-02-74-10-2A-6C-FB-97-4F-5F-70-8E-F0-B9", BitConverter.ToString (p8.EncryptedData), + "EncryptedData"); + Assert.AreEqual ("86-2A-A9-71-6D-A4-B8-2D", BitConverter.ToString (p8.Salt), "Salt"); + Assert.AreEqual (2000, p8.IterationCount, "IterationCount"); } static public byte[] End_Certificate_CP_01_01_crtx = { 0x30, 0x82, 0x02, 0x78, 0x02, 0x01, 0x00, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 0x02, 0x62, 0x30, 0x82, 0x02, 0x5E, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81, 0x00, 0xC6, 0x34, 0xEC, 0x6F, 0x0C, 0xE0, 0x59, 0x0E, 0xBC, 0x5F, 0xBA, 0x2E, 0x93, 0xBB, 0x04, 0xA7, 0x03, 0xB9, 0x70, 0x8A, 0xB9, 0xD7, 0xE5, 0xD7, 0xE6, 0xCA, 0x4A, 0x8C, 0x23, 0xD8, 0x60, 0xB3, 0x6B, 0xCB, 0x88, 0x88, 0xC7, 0xD8, 0x48, 0x7E, 0x64, 0xF9, 0xF6, 0x1B, 0xE3, 0x79, 0x46, 0x41, 0xE4, 0x61, 0xF7, 0x25, 0x47, 0x71, 0xF3, 0x50, 0x94, 0x4E, 0xF2, 0x7C, 0x6A, 0x37, 0xB6, 0x0C, @@ -68,25 +68,25 @@ namespace MonoTests.Mono.Security.Cryptography { [Test] public void PrivateKeyInfo_End_Certificate_CP_01_01 () { - AssertEquals ("PKCS8.GetType", PKCS8.KeyInfo.PrivateKey, PKCS8.GetType (End_Certificate_CP_01_01_crtx)); + Assert.AreEqual (PKCS8.KeyInfo.PrivateKey, PKCS8.GetType (End_Certificate_CP_01_01_crtx), "PKCS8.GetType"); PKCS8.PrivateKeyInfo p8 = new PKCS8.PrivateKeyInfo (End_Certificate_CP_01_01_crtx); - AssertEquals ("Algorithm", "1.2.840.113549.1.1.1", p8.Algorithm); - AssertEquals ("Attributes", 0, p8.Attributes.Count); - AssertEquals ("PrivateKey", BitConverter.ToString (End_Certificate_CP_01_01_pki), BitConverter.ToString (p8.PrivateKey)); - AssertEquals ("Version", 0, p8.Version); + Assert.AreEqual ("1.2.840.113549.1.1.1", p8.Algorithm, "Algorithm"); + Assert.AreEqual (0, p8.Attributes.Count, "Attributes"); + Assert.AreEqual (BitConverter.ToString (End_Certificate_CP_01_01_pki), BitConverter.ToString (p8.PrivateKey), "PrivateKey"); + Assert.AreEqual (0, p8.Version, "Version"); } [Test] public void PrivateKeyInfo_End_Certificate_CP_01_02 () { PKCS8.PrivateKeyInfo p8 = new PKCS8.PrivateKeyInfo (End_Certificate_CP_01_02_crtx); - AssertEquals ("Algorithm", "1.2.840.113549.1.1.1", p8.Algorithm); - AssertEquals ("Attributes", 0, p8.Attributes.Count); - AssertEquals ("PrivateKey", "30-82-02-5B-02-01-00-02-81-81-00-D6-39-9E-21-93-E2-BA-35-7F-E5-F8-E8-87-0B-8A-5F-28-25-85-B7-E5-CC-DA-7F-D3-C7-09-2A-63-E9-AD-8F-D0-A8-EF-BA-CF-3C-FB-55-03-B9-83-29-4E-0E-89-84-FB-E2-62-16-1F-9D-87-40-16-6B-F8-F4-66-38-58-74-67-D4-B5-A1-3A-4B-6F-13-4B-08-37-3A-3A-64-0A-06-8E-A2-7B-14-88-B7-F8-CE-6A-D1-45-9B-39-93-67-BF-0A-AB-DB-37-9D-FA-CE-54-0F-37-82-09-8F-0D-33-E4-B8-6E-46-C1-CC-4F-80-5A-B4-BD-19-80-27-40-84-49-02-03-01-00-01-02-81-80-14-95-5A-AD-4D-41-56-B4-F7-42-08-85-87-1C-43-C2-5A-E0-28-16-00-5D-8B-8D-06-B3-34-1D-3F-96-5F-57-D7-2B-B4-45-15-CE-7D-33-B0-F4-ED-36-55-CA-AD-C9-FA-4D-C9-30-E8-FE-C0-D5-16-92-6F-4C-44-5A-1B-9D-7E-AE-B8-01-6D-38-9D-DC-93-68-AB-93-D6-C0-8A-8A-63-B4-D6-DA-21-C1-A0-28-8C-24-C4-27-E1-4B-30-D2-2D-87-62-F9-17-75-21-5E-E1-3C-E2-2D-92-03-C6-A1-8D-1D-E9-67-F4-CE-FF-AC-52-86-D2-F5-0F-EB-03-01-02-41-00-ED-6A-AE-A7-33-B0-B8-86-36-91-BA-E7-D2-DD-15-3A-97-A2-66-31-98-24-A6-0D-E7-09-E3-BD-36-79-91-F2-5E-23-AA-21-C9-71-43-24-10-FA-F0-E6-FC-E4-C6-1F-08-45-E8-91-74-13-69-63-A5-40-8F-38-44-2B-54-69-02-41-00-E6-FE-39-8B-6F-DB-44-CA-E7-72-D3-CA-09-5B-3D-B1-53-85-29-36-FC-F1-B9-D8-1F-64-02-D4-F7-F5-71-E5-9F-17-D7-F3-9F-5A-3A-A6-A3-62-46-F6-93-3D-D3-CD-18-F2-12-BD-68-02-AA-91-55-DA-64-26-D7-16-34-E1-02-40-60-3F-F4-C8-72-4B-3D-B3-A3-A1-D6-FD-2E-DE-54-41-E9-C1-7B-DE-B5-48-7E-4D-7A-91-E6-D3-09-A7-A5-84-75-A7-CD-CC-5E-C7-5D-29-DC-FC-6E-F7-A6-24-F5-31-15-80-89-F5-95-F2-5C-B2-7A-07-3F-48-D7-52-1D-A9-02-40-40-1B-FC-C2-9B-57-E2-DE-E1-9F-B7-F2-11-E8-B5-D5-9A-55-91-DB-C6-16-1C-BB-43-F3-10-EA-24-AB-85-61-F2-66-BE-B3-C9-DD-53-FB-DD-CA-AF-E1-4D-7A-52-67-50-EE-16-8F-64-E7-A0-89-57-A7-96-36-45-69-CF-61-02-40-3D-9E-E3-29-D6-BD-59-FF-A5-C3-AC-57-CB-74-FE-B0-C3-67-34-A8-40-EB-04-88-C3-C2-74-4F-69-77-13-48-8A-97-3C-C2-4B-CD-E8-E0-97-98-A2-3F-B6-E2-71-D3-65-9F-5A-C6-C8-AE-FE-BA-B1-ED-DA-08-8A-5B-7B-12", BitConverter.ToString (p8.PrivateKey)); - AssertEquals ("Version", 0, p8.Version); + Assert.AreEqual ("1.2.840.113549.1.1.1", p8.Algorithm, "Algorithm"); + Assert.AreEqual (0, p8.Attributes.Count, "Attributes"); + Assert.AreEqual ("30-82-02-5B-02-01-00-02-81-81-00-D6-39-9E-21-93-E2-BA-35-7F-E5-F8-E8-87-0B-8A-5F-28-25-85-B7-E5-CC-DA-7F-D3-C7-09-2A-63-E9-AD-8F-D0-A8-EF-BA-CF-3C-FB-55-03-B9-83-29-4E-0E-89-84-FB-E2-62-16-1F-9D-87-40-16-6B-F8-F4-66-38-58-74-67-D4-B5-A1-3A-4B-6F-13-4B-08-37-3A-3A-64-0A-06-8E-A2-7B-14-88-B7-F8-CE-6A-D1-45-9B-39-93-67-BF-0A-AB-DB-37-9D-FA-CE-54-0F-37-82-09-8F-0D-33-E4-B8-6E-46-C1-CC-4F-80-5A-B4-BD-19-80-27-40-84-49-02-03-01-00-01-02-81-80-14-95-5A-AD-4D-41-56-B4-F7-42-08-85-87-1C-43-C2-5A-E0-28-16-00-5D-8B-8D-06-B3-34-1D-3F-96-5F-57-D7-2B-B4-45-15-CE-7D-33-B0-F4-ED-36-55-CA-AD-C9-FA-4D-C9-30-E8-FE-C0-D5-16-92-6F-4C-44-5A-1B-9D-7E-AE-B8-01-6D-38-9D-DC-93-68-AB-93-D6-C0-8A-8A-63-B4-D6-DA-21-C1-A0-28-8C-24-C4-27-E1-4B-30-D2-2D-87-62-F9-17-75-21-5E-E1-3C-E2-2D-92-03-C6-A1-8D-1D-E9-67-F4-CE-FF-AC-52-86-D2-F5-0F-EB-03-01-02-41-00-ED-6A-AE-A7-33-B0-B8-86-36-91-BA-E7-D2-DD-15-3A-97-A2-66-31-98-24-A6-0D-E7-09-E3-BD-36-79-91-F2-5E-23-AA-21-C9-71-43-24-10-FA-F0-E6-FC-E4-C6-1F-08-45-E8-91-74-13-69-63-A5-40-8F-38-44-2B-54-69-02-41-00-E6-FE-39-8B-6F-DB-44-CA-E7-72-D3-CA-09-5B-3D-B1-53-85-29-36-FC-F1-B9-D8-1F-64-02-D4-F7-F5-71-E5-9F-17-D7-F3-9F-5A-3A-A6-A3-62-46-F6-93-3D-D3-CD-18-F2-12-BD-68-02-AA-91-55-DA-64-26-D7-16-34-E1-02-40-60-3F-F4-C8-72-4B-3D-B3-A3-A1-D6-FD-2E-DE-54-41-E9-C1-7B-DE-B5-48-7E-4D-7A-91-E6-D3-09-A7-A5-84-75-A7-CD-CC-5E-C7-5D-29-DC-FC-6E-F7-A6-24-F5-31-15-80-89-F5-95-F2-5C-B2-7A-07-3F-48-D7-52-1D-A9-02-40-40-1B-FC-C2-9B-57-E2-DE-E1-9F-B7-F2-11-E8-B5-D5-9A-55-91-DB-C6-16-1C-BB-43-F3-10-EA-24-AB-85-61-F2-66-BE-B3-C9-DD-53-FB-DD-CA-AF-E1-4D-7A-52-67-50-EE-16-8F-64-E7-A0-89-57-A7-96-36-45-69-CF-61-02-40-3D-9E-E3-29-D6-BD-59-FF-A5-C3-AC-57-CB-74-FE-B0-C3-67-34-A8-40-EB-04-88-C3-C2-74-4F-69-77-13-48-8A-97-3C-C2-4B-CD-E8-E0-97-98-A2-3F-B6-E2-71-D3-65-9F-5A-C6-C8-AE-FE-BA-B1-ED-DA-08-8A-5B-7B-12", BitConverter.ToString (p8.PrivateKey), "PrivateKey"); + Assert.AreEqual (0, p8.Version, "Version"); // static RSA rsa = PKCS8.PrivateKeyInfo.DecodeRSA (p8.PrivateKey); - AssertEquals ("DecodeRSA", "1jmeIZPiujV/5fjohwuKXyglhbflzNp/08cJKmPprY/QqO+6zzz7VQO5gylODomE++JiFh+dh0AWa/j0ZjhYdGfUtaE6S28TSwg3OjpkCgaOonsUiLf4zmrRRZs5k2e/CqvbN536zlQPN4IJjw0z5LhuRsHMT4BatL0ZgCdAhEk=AQAB

7WqupzOwuIY2kbrn0t0VOpeiZjGYJKYN5wnjvTZ5kfJeI6ohyXFDJBD68Ob85MYfCEXokXQTaWOlQI84RCtUaQ==

5v45i2/bRMrnctPKCVs9sVOFKTb88bnYH2QC1Pf1ceWfF9fzn1o6pqNiRvaTPdPNGPISvWgCqpFV2mQm1xY04Q==YD/0yHJLPbOjodb9Lt5UQenBe961SH5NepHm0wmnpYR1p83MXsddKdz8bvemJPUxFYCJ9ZXyXLJ6Bz9I11IdqQ==QBv8wptX4t7hn7fyEei11ZpVkdvGFhy7Q/MQ6iSrhWHyZr6zyd1T+93Kr+FNelJnUO4Wj2TnoIlXp5Y2RWnPYQ==PZ7jKda9Wf+lw6xXy3T+sMNnNKhA6wSIw8J0T2l3E0iKlzzCS83o4JeYoj+24nHTZZ9axsiu/rqx7doIilt7Eg==FJVarU1BVrT3QgiFhxxDwlrgKBYAXYuNBrM0HT+WX1fXK7RFFc59M7D07TZVyq3J+k3JMOj+wNUWkm9MRFobnX6uuAFtOJ3ck2irk9bAiopjtNbaIcGgKIwkxCfhSzDSLYdi+Rd1IV7hPOItkgPGoY0d6Wf0zv+sUobS9Q/rAwE=
", rsa.ToXmlString (true)); + Assert.AreEqual ("1jmeIZPiujV/5fjohwuKXyglhbflzNp/08cJKmPprY/QqO+6zzz7VQO5gylODomE++JiFh+dh0AWa/j0ZjhYdGfUtaE6S28TSwg3OjpkCgaOonsUiLf4zmrRRZs5k2e/CqvbN536zlQPN4IJjw0z5LhuRsHMT4BatL0ZgCdAhEk=AQAB

7WqupzOwuIY2kbrn0t0VOpeiZjGYJKYN5wnjvTZ5kfJeI6ohyXFDJBD68Ob85MYfCEXokXQTaWOlQI84RCtUaQ==

5v45i2/bRMrnctPKCVs9sVOFKTb88bnYH2QC1Pf1ceWfF9fzn1o6pqNiRvaTPdPNGPISvWgCqpFV2mQm1xY04Q==YD/0yHJLPbOjodb9Lt5UQenBe961SH5NepHm0wmnpYR1p83MXsddKdz8bvemJPUxFYCJ9ZXyXLJ6Bz9I11IdqQ==QBv8wptX4t7hn7fyEei11ZpVkdvGFhy7Q/MQ6iSrhWHyZr6zyd1T+93Kr+FNelJnUO4Wj2TnoIlXp5Y2RWnPYQ==PZ7jKda9Wf+lw6xXy3T+sMNnNKhA6wSIw8J0T2l3E0iKlzzCS83o4JeYoj+24nHTZZ9axsiu/rqx7doIilt7Eg==FJVarU1BVrT3QgiFhxxDwlrgKBYAXYuNBrM0HT+WX1fXK7RFFc59M7D07TZVyq3J+k3JMOj+wNUWkm9MRFobnX6uuAFtOJ3ck2irk9bAiopjtNbaIcGgKIwkxCfhSzDSLYdi+Rd1IV7hPOItkgPGoY0d6Wf0zv+sUobS9Q/rAwE=
", rsa.ToXmlString (true), "DecodeRSA"); } [Test] @@ -109,31 +109,31 @@ namespace MonoTests.Mono.Security.Cryptography { public void PrivateKeyInfo () { PKCS8.PrivateKeyInfo p8 = new PKCS8.PrivateKeyInfo (); - AssertNull ("Default-Algorithm", p8.Algorithm); - AssertEquals ("Default-Attributes", 0, p8.Attributes.Count); - AssertNull ("Default-PrivateKey", p8.PrivateKey); - AssertEquals ("Default-Version", 0, p8.Version); + Assert.IsNull (p8.Algorithm, "Default-Algorithm"); + Assert.AreEqual (0, p8.Attributes.Count, "Default-Attributes"); + Assert.IsNull (p8.PrivateKey, "Default-PrivateKey"); + Assert.AreEqual (0, p8.Version, "Default-Version"); byte[] key = new byte [8]; p8.Algorithm = "1.2.3.4.5"; p8.Attributes.Add (new ASN1 (0x05)); // NULL p8.PrivateKey = key; p8.Version = 1; - AssertEquals ("Algorithm", "1.2.3.4.5", p8.Algorithm); - AssertEquals ("Attributes", 1, p8.Attributes.Count); - AssertEquals ("PrivateKey", 8, p8.PrivateKey.Length); - AssertEquals ("Version", 1, p8.Version); + Assert.AreEqual ("1.2.3.4.5", p8.Algorithm, "Algorithm"); + Assert.AreEqual (1, p8.Attributes.Count, "Attributes"); + Assert.AreEqual (8, p8.PrivateKey.Length, "PrivateKey"); + Assert.AreEqual (1, p8.Version, "Version"); key [0] = 1; - AssertEquals ("PrivateKey not directly accessible", 0, p8.PrivateKey [0]); + Assert.AreEqual (0, p8.PrivateKey [0], "PrivateKey not directly accessible"); byte[] p8pki = p8.GetBytes (); PKCS8.PrivateKeyInfo decoded = new PKCS8.PrivateKeyInfo (p8pki); - AssertEquals ("Decoded-Algorithm", "1.2.3.4.5", decoded.Algorithm); - AssertEquals ("Decoded-Attributes", 1, decoded.Attributes.Count); - AssertEquals ("Decoded-PrivateKey", 8, decoded.PrivateKey.Length); - AssertEquals ("Decoded-Version", 1, decoded.Version); + Assert.AreEqual ("1.2.3.4.5", decoded.Algorithm, "Decoded-Algorithm"); + Assert.AreEqual (1, decoded.Attributes.Count, "Decoded-Attributes"); + Assert.AreEqual (8, decoded.PrivateKey.Length, "Decoded-PrivateKey"); + Assert.AreEqual (1, decoded.Version, "Decoded-Version"); } [Test] diff --git a/mcs/class/Mono.Security/Test/Mono.Security.Protocol.Ntlm/ChallengeResponseTest.cs b/mcs/class/Mono.Security/Test/Mono.Security.Protocol.Ntlm/ChallengeResponseTest.cs index ba0f403e8a..ef27bd7363 100644 --- a/mcs/class/Mono.Security/Test/Mono.Security.Protocol.Ntlm/ChallengeResponseTest.cs +++ b/mcs/class/Mono.Security/Test/Mono.Security.Protocol.Ntlm/ChallengeResponseTest.cs @@ -17,7 +17,7 @@ using NUnit.Framework; namespace MonoTests.Mono.Security.Protocol.Ntlm { [TestFixture] - public class ChallengeResponseTest : Assertion { + public class ChallengeResponseTest { [Test] // Example from http://www.innovation.ch/java/ntlm.html @@ -25,8 +25,8 @@ namespace MonoTests.Mono.Security.Protocol.Ntlm { { byte[] SrvNonce = Encoding.ASCII.GetBytes ("SrvNonce"); using (ChallengeResponse ntlm = new ChallengeResponse ("Beeblebrox", SrvNonce)) { - AssertEquals ("NT", "E0-E0-0D-E3-10-4A-1B-F2-05-3F-07-C7-DD-A8-2D-3C-48-9A-E9-89-E1-B0-00-D3", BitConverter.ToString (ntlm.NT)); - AssertEquals ("LM", "AD-87-CA-6D-EF-E3-46-85-B9-C4-3C-47-7A-8C-42-D6-00-66-7D-68-92-E7-E8-97", BitConverter.ToString (ntlm.LM)); + Assert.AreEqual ("E0-E0-0D-E3-10-4A-1B-F2-05-3F-07-C7-DD-A8-2D-3C-48-9A-E9-89-E1-B0-00-D3", BitConverter.ToString (ntlm.NT), "NT"); + Assert.AreEqual ("AD-87-CA-6D-EF-E3-46-85-B9-C4-3C-47-7A-8C-42-D6-00-66-7D-68-92-E7-E8-97", BitConverter.ToString (ntlm.LM), "LM"); } } @@ -36,8 +36,8 @@ namespace MonoTests.Mono.Security.Protocol.Ntlm { { byte[] SrvNonce = new byte [8] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }; using (ChallengeResponse ntlm = new ChallengeResponse ("WELCOME", SrvNonce)) { - AssertEquals ("NT", "7A-CE-90-85-AB-CC-37-59-38-0B-1C-68-62-E3-98-C3-C0-EF-9C-FC-22-E8-A2-C2", BitConverter.ToString (ntlm.NT)); - AssertEquals ("LM", "CA-12-00-72-3C-41-D5-77-AB-18-C7-64-C6-DE-F3-4F-A6-1B-FA-06-71-EA-5F-C8", BitConverter.ToString (ntlm.LM)); + Assert.AreEqual ("7A-CE-90-85-AB-CC-37-59-38-0B-1C-68-62-E3-98-C3-C0-EF-9C-FC-22-E8-A2-C2", BitConverter.ToString (ntlm.NT), "NT"); + Assert.AreEqual ("CA-12-00-72-3C-41-D5-77-AB-18-C7-64-C6-DE-F3-4F-A6-1B-FA-06-71-EA-5F-C8", BitConverter.ToString (ntlm.LM), "LM"); } } @@ -46,9 +46,9 @@ namespace MonoTests.Mono.Security.Protocol.Ntlm { { byte[] SrvNonce = new byte [8] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }; using (ChallengeResponse ntlm = new ChallengeResponse (null, SrvNonce)) { - AssertEquals ("NT", "4A-FD-81-EC-01-87-E8-8D-97-77-8D-F7-93-C6-DA-D4-F0-3A-36-63-66-9D-20-1C", BitConverter.ToString (ntlm.NT)); + Assert.AreEqual ("4A-FD-81-EC-01-87-E8-8D-97-77-8D-F7-93-C6-DA-D4-F0-3A-36-63-66-9D-20-1C", BitConverter.ToString (ntlm.NT), "NT"); // note the last 8 bytes... they are the same as the previous unit test ;-) - AssertEquals ("LM", "0A-39-2B-11-CF-05-2B-02-6D-65-CF-F5-68-BD-E4-15-A6-1B-FA-06-71-EA-5F-C8", BitConverter.ToString (ntlm.LM)); + Assert.AreEqual ("0A-39-2B-11-CF-05-2B-02-6D-65-CF-F5-68-BD-E4-15-A6-1B-FA-06-71-EA-5F-C8", BitConverter.ToString (ntlm.LM), "LM"); } } @@ -58,8 +58,8 @@ namespace MonoTests.Mono.Security.Protocol.Ntlm { byte[] SrvNonce = new byte [8] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }; using (ChallengeResponse ntlm = new ChallengeResponse (String.Empty, SrvNonce)) { // same as the previous one as this is the same (null/empty) password expressed diffently - AssertEquals ("NT", "4A-FD-81-EC-01-87-E8-8D-97-77-8D-F7-93-C6-DA-D4-F0-3A-36-63-66-9D-20-1C", BitConverter.ToString (ntlm.NT)); - AssertEquals ("LM", "0A-39-2B-11-CF-05-2B-02-6D-65-CF-F5-68-BD-E4-15-A6-1B-FA-06-71-EA-5F-C8", BitConverter.ToString (ntlm.LM)); + Assert.AreEqual ("4A-FD-81-EC-01-87-E8-8D-97-77-8D-F7-93-C6-DA-D4-F0-3A-36-63-66-9D-20-1C", BitConverter.ToString (ntlm.NT), "NT"); + Assert.AreEqual ("0A-39-2B-11-CF-05-2B-02-6D-65-CF-F5-68-BD-E4-15-A6-1B-FA-06-71-EA-5F-C8", BitConverter.ToString (ntlm.LM), "LM"); } } @@ -68,8 +68,8 @@ namespace MonoTests.Mono.Security.Protocol.Ntlm { { ChallengeResponse ntlm = new ChallengeResponse ("Mono", new byte [8]); // no out! - AssertNull ("Password", ntlm.Password); - AssertNull ("Challenge", ntlm.Challenge); + Assert.IsNull (ntlm.Password, "Password"); + Assert.IsNull (ntlm.Challenge, "Challenge"); } [Test] @@ -104,7 +104,7 @@ namespace MonoTests.Mono.Security.Protocol.Ntlm { { ChallengeResponse ntlm = new ChallengeResponse ("Mono", new byte [8]); ntlm.Dispose (); - AssertNotNull ("NT", ntlm.NT); + Assert.IsNotNull (ntlm.NT, "NT"); } [Test] @@ -113,7 +113,7 @@ namespace MonoTests.Mono.Security.Protocol.Ntlm { { ChallengeResponse ntlm = new ChallengeResponse ("Mono", new byte [8]); ntlm.Dispose (); - AssertNotNull ("LM", ntlm.LM); + Assert.IsNotNull (ntlm.LM, "LM"); } } } diff --git a/mcs/class/Mono.Security/Test/Mono.Security.Protocol.Ntlm/MessageBaseTest.cs b/mcs/class/Mono.Security/Test/Mono.Security.Protocol.Ntlm/MessageBaseTest.cs index 7164640be9..a02816fadc 100644 --- a/mcs/class/Mono.Security/Test/Mono.Security.Protocol.Ntlm/MessageBaseTest.cs +++ b/mcs/class/Mono.Security/Test/Mono.Security.Protocol.Ntlm/MessageBaseTest.cs @@ -15,7 +15,7 @@ using NUnit.Framework; namespace MonoTests.Mono.Security.Protocol.Ntlm { [TestFixture] - public class MessageBaseTest : Assertion { + public class MessageBaseTest { // @@ -42,4 +42,4 @@ namespace MonoTests.Mono.Security.Protocol.Ntlm { } } -} \ No newline at end of file +} diff --git a/mcs/class/Mono.Security/Test/Mono.Security.Protocol.Ntlm/Type1MessageTest.cs b/mcs/class/Mono.Security/Test/Mono.Security.Protocol.Ntlm/Type1MessageTest.cs index c6dc2394d9..5bd097e1d4 100644 --- a/mcs/class/Mono.Security/Test/Mono.Security.Protocol.Ntlm/Type1MessageTest.cs +++ b/mcs/class/Mono.Security/Test/Mono.Security.Protocol.Ntlm/Type1MessageTest.cs @@ -16,17 +16,17 @@ using NUnit.Framework; namespace MonoTests.Mono.Security.Protocol.Ntlm { [TestFixture] - public class Type1MessageTest : Assertion { + public class Type1MessageTest { [Test] // Example from http://www.innovation.ch/java/ntlm.html public void Encode1 () { Type1Message msg = new Type1Message (); - AssertEquals ("Type", 1, msg.Type); + Assert.AreEqual (1, msg.Type, "Type"); msg.Domain = "Ursa-Minor"; msg.Host = "LightCity"; - AssertEquals ("GetBytes", "4E-54-4C-4D-53-53-50-00-01-00-00-00-07-B2-00-00-0A-00-0A-00-29-00-00-00-09-00-09-00-20-00-00-00-4C-49-47-48-54-43-49-54-59-55-52-53-41-2D-4D-49-4E-4F-52", BitConverter.ToString (msg.GetBytes ())); + Assert.AreEqual ("4E-54-4C-4D-53-53-50-00-01-00-00-00-07-B2-00-00-0A-00-0A-00-29-00-00-00-09-00-09-00-20-00-00-00-4C-49-47-48-54-43-49-54-59-55-52-53-41-2D-4D-49-4E-4F-52", BitConverter.ToString (msg.GetBytes ()), "GetBytes"); } [Test] @@ -35,10 +35,10 @@ namespace MonoTests.Mono.Security.Protocol.Ntlm { { byte[] data = { 0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0xb2, 0x00, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x29, 0x00, 0x00, 0x00, 0x09, 0x00, 0x09, 0x00, 0x20, 0x00, 0x00, 0x00, 0x4c, 0x49, 0x47, 0x48, 0x54, 0x43, 0x49, 0x54, 0x59, 0x55, 0x52, 0x53, 0x41, 0x2d, 0x4d, 0x49, 0x4e, 0x4f, 0x52 }; Type1Message msg = new Type1Message (data); - AssertEquals ("Domain", "URSA-MINOR", msg.Domain); - AssertEquals ("Flags", (NtlmFlags)0xb203, msg.Flags); - AssertEquals ("Host", "LIGHTCITY", msg.Host); - AssertEquals ("Type", 1, msg.Type); + Assert.AreEqual ("URSA-MINOR", msg.Domain, "Domain"); + Assert.AreEqual ((NtlmFlags)0xb203, msg.Flags, "Flags"); + Assert.AreEqual ("LIGHTCITY", msg.Host, "Host"); + Assert.AreEqual (1, msg.Type, "Type"); } [Test] @@ -47,10 +47,10 @@ namespace MonoTests.Mono.Security.Protocol.Ntlm { { byte[] data = { 0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x32, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x0b, 0x00, 0x20, 0x00, 0x00, 0x00, 0x57, 0x4f, 0x52, 0x4b, 0x53, 0x54, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x44, 0x4f, 0x4d, 0x41, 0x49, 0x4e }; Type1Message msg = new Type1Message (data); - AssertEquals ("Domain", "DOMAIN", msg.Domain); - AssertEquals ("Flags", (NtlmFlags)0x3207, msg.Flags); - AssertEquals ("Host", "WORKSTATION", msg.Host); - AssertEquals ("Type", 1, msg.Type); + Assert.AreEqual ("DOMAIN", msg.Domain, "Domain"); + Assert.AreEqual ((NtlmFlags)0x3207, msg.Flags, "Flags"); + Assert.AreEqual ("WORKSTATION", msg.Host, "Host"); + Assert.AreEqual (1, msg.Type, "Type"); } } } diff --git a/mcs/class/Mono.Security/Test/Mono.Security.Protocol.Ntlm/Type2MessageTest.cs b/mcs/class/Mono.Security/Test/Mono.Security.Protocol.Ntlm/Type2MessageTest.cs index bd1b38349a..6233e0fe75 100644 --- a/mcs/class/Mono.Security/Test/Mono.Security.Protocol.Ntlm/Type2MessageTest.cs +++ b/mcs/class/Mono.Security/Test/Mono.Security.Protocol.Ntlm/Type2MessageTest.cs @@ -17,7 +17,7 @@ using NUnit.Framework; namespace MonoTests.Mono.Security.Protocol.Ntlm { [TestFixture] - public class Type2MessageTest : Assertion { + public class Type2MessageTest { static byte[] nonce = { 0x53, 0x72, 0x76, 0x4e, 0x6f, 0x6e, 0x63, 0x65 }; @@ -26,9 +26,9 @@ namespace MonoTests.Mono.Security.Protocol.Ntlm { public void Encode1 () { Type2Message msg = new Type2Message (); - AssertEquals ("Type", 2, msg.Type); + Assert.AreEqual (2, msg.Type, "Type"); msg.Nonce = nonce; - AssertEquals ("GetBytes", "4E-54-4C-4D-53-53-50-00-02-00-00-00-00-00-00-00-28-00-00-00-01-82-00-00-53-72-76-4E-6F-6E-63-65-00-00-00-00-00-00-00-00", BitConverter.ToString (msg.GetBytes ())); + Assert.AreEqual ("4E-54-4C-4D-53-53-50-00-02-00-00-00-00-00-00-00-28-00-00-00-01-82-00-00-53-72-76-4E-6F-6E-63-65-00-00-00-00-00-00-00-00", BitConverter.ToString (msg.GetBytes ()), "GetBytes"); } [Test] @@ -37,9 +37,9 @@ namespace MonoTests.Mono.Security.Protocol.Ntlm { { byte[] data = { 0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x01, 0x82, 0x00, 0x00, 0x53, 0x72, 0x76, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; Type2Message msg = new Type2Message (data); - AssertEquals ("Flags", (NtlmFlags)0x8201, msg.Flags); - AssertEquals ("Nonce", BitConverter.ToString (nonce), BitConverter.ToString (msg.Nonce)); - AssertEquals ("Type", 2, msg.Type); + Assert.AreEqual ((NtlmFlags)0x8201, msg.Flags, "Flags"); + Assert.AreEqual (BitConverter.ToString (nonce), BitConverter.ToString (msg.Nonce), "Nonce"); + Assert.AreEqual (2, msg.Type, "Type"); } [Test] @@ -48,9 +48,9 @@ namespace MonoTests.Mono.Security.Protocol.Ntlm { { byte[] data = { 0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, 0x02, 0x81, 0x00, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x00, 0x62, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x44, 0x00, 0x4f, 0x00, 0x4d, 0x00, 0x41, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x02, 0x00, 0x0c, 0x00, 0x44, 0x00, 0x4f, 0x00, 0x4d, 0x00, 0x41, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x01, 0x00, 0x0c, 0x00, 0x53, 0x00, 0x45, 0x00, 0x52, 0x00, 0x56, 0x00, 0x45, 0x00, 0x52, 0x00, 0x04, 0x00, 0x14, 0x00, 0x64, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x2e, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x03, 0x00, 0x22, 0x00, 0x73, 0x00, 0x65, 0x00, 0x72, 0x00, 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, 0x2e, 0x00, 0x64, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x2e, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00 }; Type2Message msg = new Type2Message (data); - AssertEquals ("Flags", (NtlmFlags)0x00810201, msg.Flags); - AssertEquals ("Nonce", "01-23-45-67-89-AB-CD-EF", BitConverter.ToString (msg.Nonce)); - AssertEquals ("Type", 2, msg.Type); + Assert.AreEqual ((NtlmFlags)0x00810201, msg.Flags, "Flags"); + Assert.AreEqual ("01-23-45-67-89-AB-CD-EF", BitConverter.ToString (msg.Nonce), "Nonce"); + Assert.AreEqual (2, msg.Type, "Type"); } [Test] diff --git a/mcs/class/Mono.Security/Test/Mono.Security.Protocol.Ntlm/Type3MessageTest.cs b/mcs/class/Mono.Security/Test/Mono.Security.Protocol.Ntlm/Type3MessageTest.cs index febcb79755..e9343cc979 100644 --- a/mcs/class/Mono.Security/Test/Mono.Security.Protocol.Ntlm/Type3MessageTest.cs +++ b/mcs/class/Mono.Security/Test/Mono.Security.Protocol.Ntlm/Type3MessageTest.cs @@ -17,7 +17,7 @@ using NUnit.Framework; namespace MonoTests.Mono.Security.Protocol.Ntlm { [TestFixture] - public class Type3MessageTest : Assertion { + public class Type3MessageTest { static byte[] nonce = { 0x53, 0x72, 0x76, 0x4e, 0x6f, 0x6e, 0x63, 0x65 }; @@ -40,8 +40,8 @@ namespace MonoTests.Mono.Security.Protocol.Ntlm { msg.Host = "HOST"; msg.Password = "WELCOME"; msg.Username = "username"; - AssertEquals ("Type", 3, msg.Type); - AssertEquals ("GetBytes", "4E-54-4C-4D-53-53-50-00-03-00-00-00-18-00-18-00-64-00-00-00-18-00-18-00-7C-00-00-00-0C-00-0C-00-40-00-00-00-10-00-10-00-4C-00-00-00-08-00-08-00-5C-00-00-00-00-00-00-00-94-00-00-00-01-B2-00-00-44-00-4F-00-4D-00-41-00-49-00-4E-00-75-00-73-00-65-00-72-00-6E-00-61-00-6D-00-65-00-48-00-4F-00-53-00-54-00-CA-12-00-72-3C-41-D5-77-AB-18-C7-64-C6-DE-F3-4F-A6-1B-FA-06-71-EA-5F-C8-7A-CE-90-85-AB-CC-37-59-38-0B-1C-68-62-E3-98-C3-C0-EF-9C-FC-22-E8-A2-C2", BitConverter.ToString (msg.GetBytes ())); + Assert.AreEqual (3, msg.Type, "Type"); + Assert.AreEqual ("4E-54-4C-4D-53-53-50-00-03-00-00-00-18-00-18-00-64-00-00-00-18-00-18-00-7C-00-00-00-0C-00-0C-00-40-00-00-00-10-00-10-00-4C-00-00-00-08-00-08-00-5C-00-00-00-00-00-00-00-94-00-00-00-01-B2-00-00-44-00-4F-00-4D-00-41-00-49-00-4E-00-75-00-73-00-65-00-72-00-6E-00-61-00-6D-00-65-00-48-00-4F-00-53-00-54-00-CA-12-00-72-3C-41-D5-77-AB-18-C7-64-C6-DE-F3-4F-A6-1B-FA-06-71-EA-5F-C8-7A-CE-90-85-AB-CC-37-59-38-0B-1C-68-62-E3-98-C3-C0-EF-9C-FC-22-E8-A2-C2", BitConverter.ToString (msg.GetBytes ()), "GetBytes"); } [Test] @@ -55,8 +55,8 @@ namespace MonoTests.Mono.Security.Protocol.Ntlm { msg.Host = "LIGHTCITY"; msg.Password = "Beeblebrox"; msg.Username = "Zaphod"; - AssertEquals ("Type", 3, msg.Type); - AssertEquals ("GetBytes", "4E-54-4C-4D-53-53-50-00-03-00-00-00-18-00-18-00-72-00-00-00-18-00-18-00-8A-00-00-00-14-00-14-00-40-00-00-00-0C-00-0C-00-54-00-00-00-12-00-12-00-60-00-00-00-00-00-00-00-A2-00-00-00-01-B2-00-00-55-00-52-00-53-00-41-00-2D-00-4D-00-49-00-4E-00-4F-00-52-00-5A-00-61-00-70-00-68-00-6F-00-64-00-4C-00-49-00-47-00-48-00-54-00-43-00-49-00-54-00-59-00-AD-87-CA-6D-EF-E3-46-85-B9-C4-3C-47-7A-8C-42-D6-00-66-7D-68-92-E7-E8-97-E0-E0-0D-E3-10-4A-1B-F2-05-3F-07-C7-DD-A8-2D-3C-48-9A-E9-89-E1-B0-00-D3", BitConverter.ToString (msg.GetBytes ())); + Assert.AreEqual (3, msg.Type, "Type"); + Assert.AreEqual ("4E-54-4C-4D-53-53-50-00-03-00-00-00-18-00-18-00-72-00-00-00-18-00-18-00-8A-00-00-00-14-00-14-00-40-00-00-00-0C-00-0C-00-54-00-00-00-12-00-12-00-60-00-00-00-00-00-00-00-A2-00-00-00-01-B2-00-00-55-00-52-00-53-00-41-00-2D-00-4D-00-49-00-4E-00-4F-00-52-00-5A-00-61-00-70-00-68-00-6F-00-64-00-4C-00-49-00-47-00-48-00-54-00-43-00-49-00-54-00-59-00-AD-87-CA-6D-EF-E3-46-85-B9-C4-3C-47-7A-8C-42-D6-00-66-7D-68-92-E7-E8-97-E0-E0-0D-E3-10-4A-1B-F2-05-3F-07-C7-DD-A8-2D-3C-48-9A-E9-89-E1-B0-00-D3", BitConverter.ToString (msg.GetBytes ()), "GetBytes"); } [Test] @@ -64,14 +64,14 @@ namespace MonoTests.Mono.Security.Protocol.Ntlm { public void Decode1 () { Type3Message msg = new Type3Message (data1); - AssertEquals ("Domain", "URSA-MINOR", msg.Domain); - AssertEquals ("Host", "LIGHTCITY", msg.Host); - AssertEquals ("Username", "Zaphod", msg.Username); - AssertEquals ("Flags", (NtlmFlags)0x8201, msg.Flags); - AssertEquals ("Type", 3, msg.Type); - AssertNull ("Password", msg.Password); - AssertEquals ("LM", "AD-87-CA-6D-EF-E3-46-85-B9-C4-3C-47-7A-8C-42-D6-00-66-7D-68-92-E7-E8-97", BitConverter.ToString (msg.LM)); - AssertEquals ("NT", "E0-E0-0D-E3-10-4A-1B-F2-05-3F-07-C7-DD-A8-2D-3C-48-9A-E9-89-E1-B0-00-D3", BitConverter.ToString (msg.NT)); + Assert.AreEqual ("URSA-MINOR", msg.Domain, "Domain"); + Assert.AreEqual ("LIGHTCITY", msg.Host, "Host"); + Assert.AreEqual ("Zaphod", msg.Username, "Username"); + Assert.AreEqual ((NtlmFlags)0x8201, msg.Flags, "Flags"); + Assert.AreEqual (3, msg.Type, "Type"); + Assert.IsNull (msg.Password, "Password"); + Assert.AreEqual ("AD-87-CA-6D-EF-E3-46-85-B9-C4-3C-47-7A-8C-42-D6-00-66-7D-68-92-E7-E8-97", BitConverter.ToString (msg.LM), "LM"); + Assert.AreEqual ("E0-E0-0D-E3-10-4A-1B-F2-05-3F-07-C7-DD-A8-2D-3C-48-9A-E9-89-E1-B0-00-D3", BitConverter.ToString (msg.NT), "NT"); } [Test] @@ -79,28 +79,28 @@ namespace MonoTests.Mono.Security.Protocol.Ntlm { public void Decode2 () { Type3Message msg = new Type3Message (data2); - AssertEquals ("Domain", "DOMAIN", msg.Domain); - AssertEquals ("Host", "WORKSTATION", msg.Host); - AssertEquals ("Username", "user", msg.Username); - AssertEquals ("Flags", (NtlmFlags)0x201, msg.Flags); - AssertEquals ("Type", 3, msg.Type); - AssertNull ("Password", msg.Password); - AssertEquals ("LM", "C3-37-CD-5C-BD-44-FC-97-82-A6-67-AF-6D-42-7C-6D-E6-7C-20-C2-D3-E7-7C-56", BitConverter.ToString (msg.LM)); - AssertEquals ("NT", "25-A9-8C-1C-31-E8-18-47-46-6B-29-B2-DF-46-80-F3-99-58-FB-8C-21-3A-9C-C6", BitConverter.ToString (msg.NT)); + Assert.AreEqual ("DOMAIN", msg.Domain, "Domain"); + Assert.AreEqual ("WORKSTATION", msg.Host, "Host"); + Assert.AreEqual ("user", msg.Username, "Username"); + Assert.AreEqual ((NtlmFlags)0x201, msg.Flags, "Flags"); + Assert.AreEqual (3, msg.Type, "Type"); + Assert.IsNull (msg.Password, "Password"); + Assert.AreEqual ("C3-37-CD-5C-BD-44-FC-97-82-A6-67-AF-6D-42-7C-6D-E6-7C-20-C2-D3-E7-7C-56", BitConverter.ToString (msg.LM), "LM"); + Assert.AreEqual ("25-A9-8C-1C-31-E8-18-47-46-6B-29-B2-DF-46-80-F3-99-58-FB-8C-21-3A-9C-C6", BitConverter.ToString (msg.NT), "NT"); } [Test] public void Challenge () { Type3Message msg = new Type3Message (); - AssertNull ("Challenge", msg.Challenge); + Assert.IsNull (msg.Challenge, "Challenge"); byte[] c = new byte [8]; msg.Challenge = c; - AssertEquals ("Challenge.Length", 8, msg.Challenge.Length); + Assert.AreEqual (8, msg.Challenge.Length, "Challenge.Length"); c [0] = 1; - AssertEquals ("Challenge not directly accessible", 0, msg.Challenge [0]); + Assert.AreEqual (0, msg.Challenge [0], "Challenge not directly accessible"); } [Test] diff --git a/mcs/class/Mono.Security/Test/Mono.Security/StrongNameTest.cs b/mcs/class/Mono.Security/Test/Mono.Security/StrongNameTest.cs index 05e013cd4a..fe94f26e01 100644 --- a/mcs/class/Mono.Security/Test/Mono.Security/StrongNameTest.cs +++ b/mcs/class/Mono.Security/Test/Mono.Security/StrongNameTest.cs @@ -22,7 +22,7 @@ namespace MonoTests.Mono.Security { // sn -k test.snk [TestFixture] - public class StrongNameTest : Assertion { + public class StrongNameTest { // because most crypto stuff works with byte[] buffers static public void AssertEquals (string msg, byte[] array1, byte[] array2) @@ -30,9 +30,9 @@ namespace MonoTests.Mono.Security { if ((array1 == null) && (array2 == null)) return; if (array1 == null) - Fail (msg + " -> First array is NULL"); + Assert.Fail (msg + " -> First array is NULL"); if (array2 == null) - Fail (msg + " -> Second array is NULL"); + Assert.Fail (msg + " -> Second array is NULL"); bool a = (array1.Length == array2.Length); if (a) { @@ -47,7 +47,7 @@ namespace MonoTests.Mono.Security { msg += " -> Expected " + BitConverter.ToString (array1, 0); msg += " is different than " + BitConverter.ToString (array2, 0); } - Assert (msg, a); + Assert.IsTrue (a, msg); } static byte[] test = { @@ -112,9 +112,9 @@ namespace MonoTests.Mono.Security { public void FromBuffer () { StrongName sn = new StrongName (test); - AssertEquals ("buffer.RSA", "y6T/+EoARJMHW0ilpCdn+VbTffWxb1xu187/9Q+S2DwPyZ9LTNKrZgwaYmG4FPWEEH1HJxrxwh8AlD6oTz8CCcnPGKxKVFkubpIbEyvQCSTr22gUjVXXKHc2pfcCeOuNXS9kAOjv2tqpsiDbIsu9mnxfYysHWMDBqA4rxghyvT0=AQAB

6qYUEleRY+Wzyk7xN05UwWRna37U2aQnq2Y2VVyJeceDZPU1u1GYdQmFQw5XgvxKwWx9DAfNh1iSyLe0YmrAcw==

3iy1IDIkPrRWBFrCAUhpUNn4/ICiVXTT7KjuEXkGr0+1Cx/V+o3eoVIo/9x2Q3IaxMbQDSa8hisIFunz/iuPjw==2BouIBpfvzX8mBSOGNZePmG+0YRUeUCyfCs9XO5Fek9h1mfynVpvY1JqVbBuria2nl7Q53SEN+M+A/cT/RO9uw==pjma1ljNh2CTTrS8nAsaSJSc1gZD7l33RQRrAgWju7yN/qG2DbzhSZ9X7355uSKA5qK8/Gnz+QnvBn3JwGvE/w==3U67bp3lPExfGoiTRvRyHhNtyJs6hAq/Uj7wSHKLHNoLG20kwZux8BwZKpPBBA0bQjkLUiRv9PYs18El/45/wA==bPVOg5FMjWRBhmTbQ3ZWGkGLjRR9KEFDiTJXHs6DWjDgnZceWe9KB6KoJ0Vzkbs/Ovdcr56qBZxC2g6gTS5ALvogBYH2PrUftr4flh/z4qgOrAYCQkTecfHAGIGEldEeF1FItMbqmQa6WzVPVp4tn/+q3PAVmZqrs6/X9EARH10=
", sn.RSA.ToXmlString (true)); - AssertEquals ("buffer.PublicKey", testPublicKey, sn.PublicKey); - AssertEquals ("buffer.PublicKeyToken", testPublicKeyToken, sn.PublicKeyToken); + Assert.AreEqual ("y6T/+EoARJMHW0ilpCdn+VbTffWxb1xu187/9Q+S2DwPyZ9LTNKrZgwaYmG4FPWEEH1HJxrxwh8AlD6oTz8CCcnPGKxKVFkubpIbEyvQCSTr22gUjVXXKHc2pfcCeOuNXS9kAOjv2tqpsiDbIsu9mnxfYysHWMDBqA4rxghyvT0=AQAB

6qYUEleRY+Wzyk7xN05UwWRna37U2aQnq2Y2VVyJeceDZPU1u1GYdQmFQw5XgvxKwWx9DAfNh1iSyLe0YmrAcw==

3iy1IDIkPrRWBFrCAUhpUNn4/ICiVXTT7KjuEXkGr0+1Cx/V+o3eoVIo/9x2Q3IaxMbQDSa8hisIFunz/iuPjw==2BouIBpfvzX8mBSOGNZePmG+0YRUeUCyfCs9XO5Fek9h1mfynVpvY1JqVbBuria2nl7Q53SEN+M+A/cT/RO9uw==pjma1ljNh2CTTrS8nAsaSJSc1gZD7l33RQRrAgWju7yN/qG2DbzhSZ9X7355uSKA5qK8/Gnz+QnvBn3JwGvE/w==3U67bp3lPExfGoiTRvRyHhNtyJs6hAq/Uj7wSHKLHNoLG20kwZux8BwZKpPBBA0bQjkLUiRv9PYs18El/45/wA==bPVOg5FMjWRBhmTbQ3ZWGkGLjRR9KEFDiTJXHs6DWjDgnZceWe9KB6KoJ0Vzkbs/Ovdcr56qBZxC2g6gTS5ALvogBYH2PrUftr4flh/z4qgOrAYCQkTecfHAGIGEldEeF1FItMbqmQa6WzVPVp4tn/+q3PAVmZqrs6/X9EARH10=
", sn.RSA.ToXmlString (true), "buffer.RSA"); + Assert.AreEqual (testPublicKey, sn.PublicKey, "buffer.PublicKey"); + Assert.AreEqual (testPublicKeyToken, sn.PublicKeyToken, "buffer.PublicKeyToken"); } [Test] @@ -122,9 +122,9 @@ namespace MonoTests.Mono.Security { { StrongName sn1 = new StrongName (test); StrongName sn2 = new StrongName (sn1.RSA); - AssertEquals ("key.RSA", sn1.RSA.ToXmlString (true), sn2.RSA.ToXmlString (true)); - AssertEquals ("key.PublicKey", sn1.PublicKey, sn2.PublicKey); - AssertEquals ("key.PublicKeyToken", sn1.PublicKeyToken, sn2.PublicKeyToken); + Assert.AreEqual (sn1.RSA.ToXmlString (true), sn2.RSA.ToXmlString (true), "key.RSA"); + Assert.AreEqual (sn1.PublicKey, sn2.PublicKey, "key.PublicKey"); + Assert.AreEqual (sn1.PublicKeyToken, sn2.PublicKeyToken, "key.PublicKeyToken"); } string Signed; @@ -820,28 +820,28 @@ namespace MonoTests.Mono.Security { { // compare that both hellosigned and hellodelay are the same file expect for signature byte[] s = sn.Hash (Signed); - AssertNotNull ("Hash/Signed", s); + Assert.IsNotNull (s, "Hash/Signed"); byte[] d = sn.Hash (Delay); - AssertNotNull ("Hash/Delay", d); + Assert.IsNotNull (d, "Hash/Delay"); // are they the same - AssertEquals ("Hash/Compare", s, d); + Assert.AreEqual (s, d, "Hash/Compare"); // are they the same as GetHashFromAssemblyFile byte[] knownHash = { 0x7D, 0xF7, 0x1D, 0xD4, 0x24, 0x22, 0xEA, 0xAB, 0xD2, 0x91, 0xCD, 0xAB, 0x1A, 0x55, 0x6A, 0x42, 0x05, 0xBA, 0x6E, 0x7B }; - AssertEquals ("Hash/GetHashFromAssemblyFile", knownHash, s); + Assert.AreEqual (knownHash, s, "Hash/GetHashFromAssemblyFile"); } [Test] public void VerifyValid () { // verify that hellosigned.exe is valid - Assert ("Verify/Valid", sn.Verify (Signed)); + Assert.IsTrue (sn.Verify (Signed), "Verify/Valid"); } [Test] public void VerifyInvalid () { // verify that hellodelay.exe isn't valid - Assert ("Verify/Invalid", !sn.Verify (Delay)); + Assert.IsTrue (!sn.Verify (Delay), "Verify/Invalid"); } [Test] @@ -849,7 +849,7 @@ namespace MonoTests.Mono.Security { { Stream signed = new MemoryStream (signedData); // verify that hellosigned.exe is valid - Assert ("Verify/Valid", sn.Verify (signed)); + Assert.IsTrue (sn.Verify (signed), "Verify/Valid"); } [Test] @@ -857,25 +857,25 @@ namespace MonoTests.Mono.Security { { Stream delay = new MemoryStream (delayData); // verify that hellodelay.exe isn't valid - Assert ("Verify/Invalid", !sn.Verify (delay)); + Assert.IsTrue (!sn.Verify (delay), "Verify/Invalid"); } [Test] public void Sign () { // sign the (invalid) hellodelay.exe - Assert ("Sign", sn.Sign (Delay)); + Assert.IsTrue (sn.Sign (Delay), "Sign"); // and verify it's now valid - Assert ("Sign/Verify", sn.Verify (Delay)); + Assert.IsTrue (sn.Verify (Delay), "Sign/Verify"); } [Test] public void ReSign () { // resign the (already valid) hellosigned.exe - Assert ("ReSign", sn.Sign (Signed)); + Assert.IsTrue (sn.Sign (Signed), "ReSign"); // and verify it's still valid - Assert ("ReSign/Verify", sn.Verify (Signed)); + Assert.IsTrue (sn.Verify (Signed), "ReSign/Verify"); } [Test] @@ -907,7 +907,7 @@ namespace MonoTests.Mono.Security { { byte[] ecma = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; sn = new StrongName (ecma); - Assert ("CanSign", !sn.CanSign); + Assert.IsTrue (!sn.CanSign, "CanSign"); } [Test] diff --git a/mcs/class/Mono.Tasklets/Makefile b/mcs/class/Mono.Tasklets/Makefile index 8883dbaf83..19a6cc1cee 100644 --- a/mcs/class/Mono.Tasklets/Makefile +++ b/mcs/class/Mono.Tasklets/Makefile @@ -3,7 +3,9 @@ SUBDIRS = include ../../build/rules.make LIBRARY = Mono.Tasklets.dll -NO_TEST = yes + +LIB_MCS_FLAGS = +TEST_MCS_FLAGS = $(LIB_MCS_FLAGS) include ../../build/library.make diff --git a/mcs/class/Mono.Tasklets/Mono.Tasklets_test.dll.sources b/mcs/class/Mono.Tasklets/Mono.Tasklets_test.dll.sources new file mode 100644 index 0000000000..f994ee35b3 --- /dev/null +++ b/mcs/class/Mono.Tasklets/Mono.Tasklets_test.dll.sources @@ -0,0 +1 @@ +Mono.Tasklets/ContinuationsTest.cs diff --git a/mcs/class/Mono.Tasklets/Test/Mono.Tasklets/ContinuationsTest.cs b/mcs/class/Mono.Tasklets/Test/Mono.Tasklets/ContinuationsTest.cs new file mode 100644 index 0000000000..6fa67a901d --- /dev/null +++ b/mcs/class/Mono.Tasklets/Test/Mono.Tasklets/ContinuationsTest.cs @@ -0,0 +1,189 @@ +using NUnit.Framework; + +using System; +using Mono.Tasklets; + +namespace MonoTests.System +{ + [TestFixture] + public class ContinuationsTest + { + [TestFixtureSetUp] + public void FixtureSetUp () + { + try { + var temp = new Continuation (); + } catch (NotImplementedException) { + Assert.Ignore ("This platform doesn't support Tasklets."); + } + } + + int total = 0; + + [Test] + public void TestContinuationsLoop() + { + Continuation _contA = new Continuation(); + + _contA.Mark(); + int value = 0; + int ret = _contA.Store(0); + for (int i = ret; i < 10; i++) { + value += i; + } + + if (value > 0) { + total += value; + _contA.Restore(ret + 1); + } + + Assert.AreEqual(total, 330); + } + + private int yields = 0; + + [Test] + public void Yielding() + { + Continuation baseCont = new Continuation(); + Continuation taskCont = new Continuation(); + + baseCont.Mark(); + taskCont.Mark(); + + // Store the base continuation to start the task + if (baseCont.Store(0) == 0) { + bool done = false; + int count = 0; + + while (!done) { + // Do stuff for the task. + ++count; + + // This task is counting to 100. + if (count == 100) { + done = true; + } + + // Yield every 10 loops + else if (count % 10 == 0) { + + // To yield, store the task continuation then restore + // the base continuation. + if (taskCont.Store(0) == 0) { + baseCont.Restore(1); + } + } + } + } + // When restored, 'Store' will return what was passed to Restore, in this case 1 so fall here. + else { + // Count the yields, then go back to the task. + ++yields; + taskCont.Restore(1); + } + + Assert.AreEqual(9, yields); + } + + + public class MicroThread + { + + public void Yield() + { + if (MyThread.Store(0) == 0) { + MainThread.Restore(1); + } + } + + public void Resume() + { + if (MainThread.Store(0) == 0) { + MyThread.Restore(1); + } + } + + public void DoWork(Action action) + { + if (MainThread.Store(0) == 0) { + action(); + Done = true; + MainThread.Restore(1); + } + } + + public bool Done = false; + public Continuation MainThread = new Continuation(); + public Continuation MyThread = new Continuation(); + } + + public class MicroBJob + { + private int _Count = 0; + public int Count + { + get { return _Count; } + set { _Count = value; } + } + + public MicroThread MicroThread; + public void Work() + { + while (Count < 100) { + ++Count; + if (Count % 10 == 0) { + MicroThread.Yield(); + } + } + } + } + + [Test] + public void MicroThreadTest() + { + MicroThread microA = new MicroThread(); + MicroThread microB = new MicroThread(); + + microA.MainThread.Mark(); + microA.MyThread.Mark(); + microB.MainThread.Mark(); + microB.MyThread.Mark(); + + Assert.AreEqual(false, microA.Done); + Assert.AreEqual(false, microB.Done); + + microA.DoWork(() => + { + int count = 0; + while (count < 100) { + ++count; + if (count % 10 == 0) { + microA.Yield(); + } + } + }); + + MicroBJob jobB = new MicroBJob(); + jobB.MicroThread = microB; + + microB.DoWork(jobB.Work); + + Assert.AreEqual(false, microA.Done); + Assert.AreEqual(false, microB.Done); + + int yields = 0; + while (yields < 20) { + if (!microA.Done) microA.Resume(); + if (!microB.Done) microB.Resume(); + if (microA.Done && microB.Done) break; + ++yields; + } + + Assert.AreEqual(true, microA.Done); + Assert.AreEqual(true, microB.Done); + Assert.AreEqual(100, jobB.Count); + Assert.AreEqual(9, yields); + } + } +} diff --git a/mcs/class/Novell.Directory.Ldap/Makefile b/mcs/class/Novell.Directory.Ldap/Makefile index 9e0d99d6c0..4f24b424a7 100644 --- a/mcs/class/Novell.Directory.Ldap/Makefile +++ b/mcs/class/Novell.Directory.Ldap/Makefile @@ -5,25 +5,14 @@ include ../../build/rules.make LIBRARY = Novell.Directory.Ldap.dll LIB_REFS = System Mono.Security -LIB_MCS_FLAGS = \ - -warn:1 -nowarn:612 \ - $(RESX_RES:%=/res:%) +LIB_MCS_FLAGS = -warn:1 -nowarn:612 +RESOURCE_DEFS = ResultCodeMessages,Novell.Directory.Ldap.Utilclass/ResultCodeMessages.txt include ../../build/library.make -RESULTCODE_MESSAGES = Novell.Directory.Ldap.Utilclass/ResultCodeMessages.resources - -RESX_RES = $(RESULTCODE_MESSAGES) - -$(the_lib): $(RESULTCODE_MESSAGES) - -$(RESULTCODE_MESSAGES): Novell.Directory.Ldap.Utilclass/ResultCodeMessages.txt - $(RESGEN) $< $@ - EXTRA_DISTFILES = \ Novell.Directory.Ldap.Rfc2251/RfcLdapURL.cs \ Novell.Directory.Ldap.Utilclass/ExceptionMessages.resx \ Novell.Directory.Ldap.Utilclass/ExceptionMessages.txt \ - Novell.Directory.Ldap.Utilclass/ResultCodeMessages.resx \ - Novell.Directory.Ldap.Utilclass/ResultCodeMessages.txt + Novell.Directory.Ldap.Utilclass/ResultCodeMessages.resx diff --git a/mcs/class/SMDiagnostics/Assembly/AssemblyInfo.cs b/mcs/class/SMDiagnostics/Assembly/AssemblyInfo.cs index 561d2fef4b..ce13a36877 100644 --- a/mcs/class/SMDiagnostics/Assembly/AssemblyInfo.cs +++ b/mcs/class/SMDiagnostics/Assembly/AssemblyInfo.cs @@ -40,7 +40,7 @@ using System.Runtime.InteropServices; [assembly: NeutralResourcesLanguage ("en-US")] [assembly: CLSCompliant (true)] [assembly: AssemblyDelaySign (true)] -#if NET_2_1 +#if MOBILE [assembly: AssemblyKeyFile ("../winfx.pub")] #else [assembly: AssemblyKeyFile ("../ecma.pub")] diff --git a/mcs/class/System.ComponentModel.Composition.4.5/Makefile b/mcs/class/System.ComponentModel.Composition.4.5/Makefile index e0b5dab202..9c35c71ec5 100644 --- a/mcs/class/System.ComponentModel.Composition.4.5/Makefile +++ b/mcs/class/System.ComponentModel.Composition.4.5/Makefile @@ -4,18 +4,16 @@ include ../../build/rules.make LIBRARY = System.ComponentModel.Composition.dll LIB_REFS = System System.Core -LIB_MCS_FLAGS = -d:CLR40 -resource:$(STRING_MESSAGES) -d:USE_ECMA_KEY,FEATURE_REFLECTIONCONTEXT,FEATURE_REFLECTIONFILEIO,FEATURE_SERIALIZATION,FEATURE_SLIMLOCK -nowarn:219,414 -STRING_MESSAGES = Microsoft.Internal.Strings.resources +RESOURCE_DEFS = Microsoft.Internal.Strings,src/ComponentModel/Strings.resx +LIB_MCS_FLAGS = -d:CLR40 -d:USE_ECMA_KEY,FEATURE_REFLECTIONCONTEXT,FEATURE_REFLECTIONFILEIO,FEATURE_SERIALIZATION,FEATURE_SLIMLOCK -nowarn:219,414 + CLEAN_FILES += $(STRING_MESSAGES) EXTRA_DISTFILES = \ src/ComponentModel/Strings.resx - + include ../../build/library.make -$(the_lib): $(STRING_MESSAGES) -$(STRING_MESSAGES): src/ComponentModel/Strings.resx - $(RESGEN) $< $@ diff --git a/mcs/class/System.ComponentModel.DataAnnotations/Test/System.ComponentModel.DataAnnotations/CompareAttributeTest.cs b/mcs/class/System.ComponentModel.DataAnnotations/Test/System.ComponentModel.DataAnnotations/CompareAttributeTest.cs index dc95296fbe..d98c051699 100644 --- a/mcs/class/System.ComponentModel.DataAnnotations/Test/System.ComponentModel.DataAnnotations/CompareAttributeTest.cs +++ b/mcs/class/System.ComponentModel.DataAnnotations/Test/System.ComponentModel.DataAnnotations/CompareAttributeTest.cs @@ -36,7 +36,6 @@ using MonoTests.Common; namespace MonoTests.System.ComponentModel.DataAnnotations { -#if NET_4_5 [TestFixture] public class CompareAttributeTest { @@ -66,5 +65,4 @@ namespace MonoTests.System.ComponentModel.DataAnnotations Assert.IsNotNull (sla.GetValidationResult (DateTime.Now, ctx), "#B-4"); } } -#endif } diff --git a/mcs/class/System.ComponentModel.DataAnnotations/Test/System.ComponentModel.DataAnnotations/CreditCardAttributeTest.cs b/mcs/class/System.ComponentModel.DataAnnotations/Test/System.ComponentModel.DataAnnotations/CreditCardAttributeTest.cs index 846ee32617..00cc74573f 100644 --- a/mcs/class/System.ComponentModel.DataAnnotations/Test/System.ComponentModel.DataAnnotations/CreditCardAttributeTest.cs +++ b/mcs/class/System.ComponentModel.DataAnnotations/Test/System.ComponentModel.DataAnnotations/CreditCardAttributeTest.cs @@ -36,7 +36,6 @@ using MonoTests.Common; namespace MonoTests.System.ComponentModel.DataAnnotations { -#if NET_4_5 [TestFixture] public class CreditCardAttributeTest { @@ -56,5 +55,4 @@ namespace MonoTests.System.ComponentModel.DataAnnotations Assert.IsFalse (sla.IsValid (DateTime.Now), "#A1-8"); } } -#endif } diff --git a/mcs/class/System.ComponentModel.DataAnnotations/Test/System.ComponentModel.DataAnnotations/EmailAddressAttributeTest.cs b/mcs/class/System.ComponentModel.DataAnnotations/Test/System.ComponentModel.DataAnnotations/EmailAddressAttributeTest.cs index 552e3eae6a..f85887cef6 100644 --- a/mcs/class/System.ComponentModel.DataAnnotations/Test/System.ComponentModel.DataAnnotations/EmailAddressAttributeTest.cs +++ b/mcs/class/System.ComponentModel.DataAnnotations/Test/System.ComponentModel.DataAnnotations/EmailAddressAttributeTest.cs @@ -36,7 +36,6 @@ using MonoTests.Common; namespace MonoTests.System.ComponentModel.DataAnnotations { -#if NET_4_5 [TestFixture] public class EmailAddressAttributeTest { @@ -84,5 +83,4 @@ namespace MonoTests.System.ComponentModel.DataAnnotations Assert.IsFalse (sla.IsValid (InvalidAddresses[i]), "#B1-{0}", i); } } -#endif } diff --git a/mcs/class/System.ComponentModel.DataAnnotations/Test/System.ComponentModel.DataAnnotations/FileExtensionsAttributeTest.cs b/mcs/class/System.ComponentModel.DataAnnotations/Test/System.ComponentModel.DataAnnotations/FileExtensionsAttributeTest.cs index 257161fc06..6ef0263365 100644 --- a/mcs/class/System.ComponentModel.DataAnnotations/Test/System.ComponentModel.DataAnnotations/FileExtensionsAttributeTest.cs +++ b/mcs/class/System.ComponentModel.DataAnnotations/Test/System.ComponentModel.DataAnnotations/FileExtensionsAttributeTest.cs @@ -36,7 +36,6 @@ using MonoTests.Common; namespace MonoTests.System.ComponentModel.DataAnnotations { -#if NET_4_5 [TestFixture] public class FileExtensionsAttributeTest { @@ -57,5 +56,4 @@ namespace MonoTests.System.ComponentModel.DataAnnotations Assert.IsFalse (sla.IsValid (DateTime.Now), "#A1-8"); } } -#endif } diff --git a/mcs/class/System.ComponentModel.DataAnnotations/Test/System.ComponentModel.DataAnnotations/PhoneAttributeTest.cs b/mcs/class/System.ComponentModel.DataAnnotations/Test/System.ComponentModel.DataAnnotations/PhoneAttributeTest.cs index 3ca6e0bf3d..ef9c95dfb7 100644 --- a/mcs/class/System.ComponentModel.DataAnnotations/Test/System.ComponentModel.DataAnnotations/PhoneAttributeTest.cs +++ b/mcs/class/System.ComponentModel.DataAnnotations/Test/System.ComponentModel.DataAnnotations/PhoneAttributeTest.cs @@ -36,7 +36,6 @@ using MonoTests.Common; namespace MonoTests.System.ComponentModel.DataAnnotations { -#if NET_4_5 [TestFixture] public class PhoneAttributeTest { @@ -54,5 +53,4 @@ namespace MonoTests.System.ComponentModel.DataAnnotations Assert.IsFalse (sla.IsValid (DateTime.Now), "#A1-7"); } } -#endif } diff --git a/mcs/class/System.Core/Assembly/AssemblyInfo.cs b/mcs/class/System.Core/Assembly/AssemblyInfo.cs index aa3a0e53cc..c4ab9f0d23 100644 --- a/mcs/class/System.Core/Assembly/AssemblyInfo.cs +++ b/mcs/class/System.Core/Assembly/AssemblyInfo.cs @@ -52,7 +52,7 @@ using System.Runtime.InteropServices; [assembly: NeutralResourcesLanguage ("en-US")] [assembly: CLSCompliant (true)] [assembly: AssemblyDelaySign (true)] -#if NET_2_1 +#if MOBILE // attributes specific to FX 3.5 [assembly: AssemblyKeyFile ("../silverlight.pub")] #else diff --git a/mcs/class/System.Core/Microsoft.Win32.SafeHandles/SafeNCryptHandle.cs b/mcs/class/System.Core/Microsoft.Win32.SafeHandles/SafeNCryptHandle.cs index 873ce5782a..cbf1491612 100644 --- a/mcs/class/System.Core/Microsoft.Win32.SafeHandles/SafeNCryptHandle.cs +++ b/mcs/class/System.Core/Microsoft.Win32.SafeHandles/SafeNCryptHandle.cs @@ -30,10 +30,10 @@ using System; namespace Microsoft.Win32.SafeHandles { - public abstract class SafeNCryptHandle : System.Runtime.InteropServices.SafeHandle + public abstract class SafeNCryptHandle : SafeHandleZeroOrMinusOneIsInvalid { protected SafeNCryptHandle () - : base (IntPtr.Zero, true) + : base (true) { } diff --git a/mcs/class/System.Core/System.IO.Pipes/AnonymousPipeServerStream.cs b/mcs/class/System.Core/System.IO.Pipes/AnonymousPipeServerStream.cs index 97455f30cd..18c82aeac3 100644 --- a/mcs/class/System.Core/System.IO.Pipes/AnonymousPipeServerStream.cs +++ b/mcs/class/System.Core/System.IO.Pipes/AnonymousPipeServerStream.cs @@ -70,13 +70,15 @@ namespace System.IO.Pipes } #endif -#if !MOBILE public AnonymousPipeServerStream (PipeDirection direction, HandleInheritability inheritability, int bufferSize, PipeSecurity pipeSecurity) : base (direction, bufferSize) { if (direction == PipeDirection.InOut) throw new NotSupportedException ("Anonymous pipe direction can only be either in or out."); +#if MOBILE + throw new NotImplementedException (); +#else if (IsWindows) impl = new Win32AnonymousPipeServer (this, direction, inheritability, bufferSize, pipeSecurity); else @@ -84,8 +86,8 @@ namespace System.IO.Pipes InitializeHandle (impl.Handle, false, false); IsConnected = true; - } #endif + } [MonoTODO] public AnonymousPipeServerStream (PipeDirection direction, SafePipeHandle serverSafePipeHandle, SafePipeHandle clientSafePipeHandle) diff --git a/mcs/class/System.Core/System.IO.Pipes/NamedPipeClientStream.cs b/mcs/class/System.Core/System.IO.Pipes/NamedPipeClientStream.cs index a5a9ebd3fb..a823217957 100644 --- a/mcs/class/System.Core/System.IO.Pipes/NamedPipeClientStream.cs +++ b/mcs/class/System.Core/System.IO.Pipes/NamedPipeClientStream.cs @@ -100,21 +100,23 @@ namespace System.IO.Pipes #endif } -#if !MOBILE public NamedPipeClientStream (string serverName, string pipeName, PipeAccessRights desiredAccessRights, PipeOptions options, TokenImpersonationLevel impersonationLevel, HandleInheritability inheritability) : base (ToDirection (desiredAccessRights), DefaultBufferSize) { if (impersonationLevel != TokenImpersonationLevel.None || inheritability != HandleInheritability.None) throw ThrowACLException (); - +#if MOBILE + throw new NotImplementedException (); +#else if (IsWindows) impl = new Win32NamedPipeClient (this, serverName, pipeName, desiredAccessRights, options, inheritability); else impl = new UnixNamedPipeClient (this, serverName, pipeName, desiredAccessRights, options, inheritability); - } #endif + } + ~NamedPipeClientStream () { Dispose (false); } @@ -163,6 +165,10 @@ namespace System.IO.Pipes throw new NotImplementedException (); } + protected override internal void CheckPipePropertyOperations () { + base.CheckPipePropertyOperations(); + } + public int NumberOfServerInstances { get { CheckPipePropertyOperations (); diff --git a/mcs/class/System.Core/System.IO.Pipes/NamedPipeServerStream.cs b/mcs/class/System.Core/System.IO.Pipes/NamedPipeServerStream.cs index 3ffe894367..e402a8a262 100644 --- a/mcs/class/System.Core/System.IO.Pipes/NamedPipeServerStream.cs +++ b/mcs/class/System.Core/System.IO.Pipes/NamedPipeServerStream.cs @@ -83,7 +83,6 @@ namespace System.IO.Pipes } #endif -#if !MOBILE public NamedPipeServerStream (string pipeName, PipeDirection direction, int maxNumberOfServerInstances, PipeTransmissionMode transmissionMode, PipeOptions options, int inBufferSize, int outBufferSize, PipeSecurity pipeSecurity) : this (pipeName, direction, maxNumberOfServerInstances, transmissionMode, options, inBufferSize, outBufferSize, pipeSecurity, HandleInheritability.None) { @@ -100,7 +99,9 @@ namespace System.IO.Pipes { var rights = ToAccessRights (direction) | additionalAccessRights; // FIXME: reject some rights declarations (for ACL). - +#if MOBILE + throw new NotImplementedException (); +#else if (IsWindows) impl = new Win32NamedPipeServer (this, pipeName, maxNumberOfServerInstances, transmissionMode, rights, options, inBufferSize, outBufferSize, @@ -110,8 +111,8 @@ namespace System.IO.Pipes rights, options, inBufferSize, outBufferSize, inheritability); InitializeHandle (impl.Handle, false, (options & PipeOptions.Asynchronous) != PipeOptions.None); - } #endif + } public NamedPipeServerStream (PipeDirection direction, bool isAsync, bool isConnected, SafePipeHandle safePipeHandle) : base (direction, DefaultBufferSize) @@ -140,14 +141,12 @@ namespace System.IO.Pipes impl.Disconnect (); } -#if !MOBILE [MonoTODO] [SecurityPermission (SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlPrincipal)] public void RunAsClient (PipeStreamImpersonationWorker impersonationWorker) { throw new NotImplementedException (); } -#endif public void WaitForConnection () { @@ -173,7 +172,6 @@ namespace System.IO.Pipes throw new NotImplementedException (); } -#if !MOBILE // async operations Action wait_connect_delegate; @@ -190,7 +188,6 @@ namespace System.IO.Pipes { wait_connect_delegate.EndInvoke (asyncResult); } -#endif } } diff --git a/mcs/class/System.Core/System.IO.Pipes/PipeStream.cs b/mcs/class/System.Core/System.IO.Pipes/PipeStream.cs index 20b7e7ec09..8dea76a2ca 100644 --- a/mcs/class/System.Core/System.IO.Pipes/PipeStream.cs +++ b/mcs/class/System.Core/System.IO.Pipes/PipeStream.cs @@ -57,7 +57,6 @@ namespace System.IO.Pipes return new NotImplementedException ("ACL is not supported in Mono"); } -#if !MOBILE internal static PipeAccessRights ToAccessRights (PipeDirection direction) { switch (direction) { @@ -88,7 +87,6 @@ namespace System.IO.Pipes throw new ArgumentOutOfRangeException (); } } -#endif protected PipeStream (PipeDirection direction, int bufferSize) : this (direction, PipeTransmissionMode.Byte, bufferSize) @@ -144,9 +142,7 @@ namespace System.IO.Pipes set { stream = value; } } -#if !MOBILE protected bool IsHandleExposed { get; private set; } -#endif [MonoTODO] public bool IsMessageComplete { get; private set; } @@ -182,19 +178,7 @@ namespace System.IO.Pipes } // initialize/dispose/state check -#if MOBILE - internal static void CheckPipePropertyOperations () - { - } - static void CheckReadOperations () - { - } - - static void CheckWriteOperations () - { - } -#else [MonoTODO] protected internal virtual void CheckPipePropertyOperations () { @@ -224,7 +208,6 @@ namespace System.IO.Pipes this.IsHandleExposed = isExposed; this.IsAsync = isAsync; } -#endif protected override void Dispose (bool disposing) { @@ -253,23 +236,29 @@ namespace System.IO.Pipes throw new NotSupportedException (); } -#if !MOBILE public PipeSecurity GetAccessControl () { +#if MOBILE + throw new PlatformNotSupportedException (); +#else return new PipeSecurity (SafePipeHandle, AccessControlSections.Owner | AccessControlSections.Group | AccessControlSections.Access); +#endif } public void SetAccessControl (PipeSecurity pipeSecurity) { +#if MOBILE + throw new PlatformNotSupportedException (); +#else if (pipeSecurity == null) throw new ArgumentNullException ("pipeSecurity"); pipeSecurity.Persist (SafePipeHandle); - } #endif + } // pipe I/O @@ -319,7 +308,6 @@ namespace System.IO.Pipes // async -#if !MOBILE Func read_delegate; [HostProtection (SecurityAction.LinkDemand, ExternalThreading = true)] @@ -349,7 +337,6 @@ namespace System.IO.Pipes { write_delegate.EndInvoke (asyncResult); } -#endif } } diff --git a/mcs/class/System.Core/System.Security.Cryptography.X509Certificates/RSACertificateExtensions.cs b/mcs/class/System.Core/System.Security.Cryptography.X509Certificates/RSACertificateExtensions.cs index 0e322e4b10..81c303bd09 100644 --- a/mcs/class/System.Core/System.Security.Cryptography.X509Certificates/RSACertificateExtensions.cs +++ b/mcs/class/System.Core/System.Security.Cryptography.X509Certificates/RSACertificateExtensions.cs @@ -30,16 +30,18 @@ namespace System.Security.Cryptography.X509Certificates { public static class RSACertificateExtensions { - [MonoTODO] public static RSA GetRSAPrivateKey(this X509Certificate2 certificate) { - throw new NotImplementedException (); + if (certificate == null) + throw new ArgumentNullException("certificate"); + return certificate.PrivateKey as RSA; } - [MonoTODO] public static RSA GetRSAPublicKey(this X509Certificate2 certificate) { - throw new NotImplementedException (); + if (certificate == null) + throw new ArgumentNullException("certificate"); + return certificate.PublicKey.Key as RSA; } } } diff --git a/mcs/class/System.Core/System.Security.Cryptography/AesTransform.cs b/mcs/class/System.Core/System.Security.Cryptography/AesTransform.cs index b9700de921..9e7d82c176 100644 --- a/mcs/class/System.Core/System.Security.Cryptography/AesTransform.cs +++ b/mcs/class/System.Core/System.Security.Cryptography/AesTransform.cs @@ -99,7 +99,7 @@ namespace System.Security.Cryptography { exKey [i] = exKey [i-Nk] ^ temp; } -#if NET_2_1 +#if MOBILE // Silverlight 2.0 only supports CBC if (!encryption) { #else diff --git a/mcs/class/System.Core/System.Security.Cryptography/MD5Cng.cs b/mcs/class/System.Core/System.Security.Cryptography/MD5Cng.cs index 9a6920efe1..0e3658c5c1 100644 --- a/mcs/class/System.Core/System.Security.Cryptography/MD5Cng.cs +++ b/mcs/class/System.Core/System.Security.Cryptography/MD5Cng.cs @@ -29,7 +29,7 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -#if !NET_2_1 +#if !MOBILE namespace System.Security.Cryptography { diff --git a/mcs/class/System.Core/System.Security.Cryptography/SHA1Cng.cs b/mcs/class/System.Core/System.Security.Cryptography/SHA1Cng.cs index 45d4ab55ea..95d1034aa3 100644 --- a/mcs/class/System.Core/System.Security.Cryptography/SHA1Cng.cs +++ b/mcs/class/System.Core/System.Security.Cryptography/SHA1Cng.cs @@ -29,7 +29,7 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -#if !NET_2_1 +#if !MOBILE namespace System.Security.Cryptography { diff --git a/mcs/class/System.Core/System.Security.Cryptography/SHA256Cng.cs b/mcs/class/System.Core/System.Security.Cryptography/SHA256Cng.cs index 347683170e..772b81faab 100644 --- a/mcs/class/System.Core/System.Security.Cryptography/SHA256Cng.cs +++ b/mcs/class/System.Core/System.Security.Cryptography/SHA256Cng.cs @@ -29,7 +29,7 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -#if !NET_2_1 +#if !MOBILE namespace System.Security.Cryptography { diff --git a/mcs/class/System.Core/System.Security.Cryptography/SHA256CryptoServiceProvider.cs b/mcs/class/System.Core/System.Security.Cryptography/SHA256CryptoServiceProvider.cs index ac1016d726..9012c58b21 100644 --- a/mcs/class/System.Core/System.Security.Cryptography/SHA256CryptoServiceProvider.cs +++ b/mcs/class/System.Core/System.Security.Cryptography/SHA256CryptoServiceProvider.cs @@ -29,7 +29,7 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -#if !NET_2_1 +#if !MOBILE namespace System.Security.Cryptography { diff --git a/mcs/class/System.Core/System.Security.Cryptography/SHA384Cng.cs b/mcs/class/System.Core/System.Security.Cryptography/SHA384Cng.cs index bbcdde1ffa..b573aad961 100644 --- a/mcs/class/System.Core/System.Security.Cryptography/SHA384Cng.cs +++ b/mcs/class/System.Core/System.Security.Cryptography/SHA384Cng.cs @@ -29,7 +29,7 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -#if !NET_2_1 +#if !MOBILE namespace System.Security.Cryptography { diff --git a/mcs/class/System.Core/System.Security.Cryptography/SHA384CryptoServiceProvider.cs b/mcs/class/System.Core/System.Security.Cryptography/SHA384CryptoServiceProvider.cs index 43d8e0921a..af0abc744b 100644 --- a/mcs/class/System.Core/System.Security.Cryptography/SHA384CryptoServiceProvider.cs +++ b/mcs/class/System.Core/System.Security.Cryptography/SHA384CryptoServiceProvider.cs @@ -29,7 +29,7 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -#if !NET_2_1 +#if !MOBILE namespace System.Security.Cryptography { diff --git a/mcs/class/System.Core/System.Security.Cryptography/SHA512Cng.cs b/mcs/class/System.Core/System.Security.Cryptography/SHA512Cng.cs index 5bcdcc2998..bf5689ecb3 100644 --- a/mcs/class/System.Core/System.Security.Cryptography/SHA512Cng.cs +++ b/mcs/class/System.Core/System.Security.Cryptography/SHA512Cng.cs @@ -29,7 +29,7 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -#if !NET_2_1 +#if !MOBILE namespace System.Security.Cryptography { diff --git a/mcs/class/System.Core/System.Security.Cryptography/SHA512CryptoServiceProvider.cs b/mcs/class/System.Core/System.Security.Cryptography/SHA512CryptoServiceProvider.cs index ed8dabec17..9425a94e0c 100644 --- a/mcs/class/System.Core/System.Security.Cryptography/SHA512CryptoServiceProvider.cs +++ b/mcs/class/System.Core/System.Security.Cryptography/SHA512CryptoServiceProvider.cs @@ -29,7 +29,7 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -#if !NET_2_1 +#if !MOBILE namespace System.Security.Cryptography { diff --git a/mcs/class/System.Core/common_System.Core.dll.sources b/mcs/class/System.Core/common_System.Core.dll.sources index 6e36c961e3..52dad5c3c1 100644 --- a/mcs/class/System.Core/common_System.Core.dll.sources +++ b/mcs/class/System.Core/common_System.Core.dll.sources @@ -232,4 +232,3 @@ ReferenceSources/Strings.cs System.Security.Cryptography/ECCurve.cs System.Security.Cryptography/ECPoint.cs System.Security.Cryptography/ECParameters.cs -System.Security.Cryptography/IncrementalHash.cs diff --git a/mcs/class/System.Data.Services.Client/Makefile b/mcs/class/System.Data.Services.Client/Makefile index 108d98cf14..f635e808fc 100644 --- a/mcs/class/System.Data.Services.Client/Makefile +++ b/mcs/class/System.Data.Services.Client/Makefile @@ -4,13 +4,11 @@ include ../../build/rules.make LIBRARY = System.Data.Services.Client.dll -Client/System.Data.Services.Client.resources: Client/System.Data.Services.Client.txt - $(RESGEN) "$<" "$@" +RESOURCE_DEFS = System.Data.Services.Client,Client/System.Data.Services.Client.txt LIB_REFS = System System.Core System.Xml.Linq System.Data System.Xml LIB_MCS_FLAGS = \ -d:NET_3_5 \ - -resource:Client/System.Data.Services.Client.resources \ -warn:2 ifndef NO_WINDOWS_BASE @@ -21,7 +19,5 @@ endif include ../../build/library.make -$(the_lib): Client/System.Data.Services.Client.resources - EXTRA_DISTFILES = Client/System.Data.Services.Client.txt -CLEAN_FILES += Client/System.Data.Services.Client.resources + diff --git a/mcs/class/System.Data/Makefile b/mcs/class/System.Data/Makefile index b5bd23a7cb..2bf7742eb4 100644 --- a/mcs/class/System.Data/Makefile +++ b/mcs/class/System.Data/Makefile @@ -12,11 +12,17 @@ LIB_MCS_FLAGS = \ -d:MONO_PARTIAL_DATA_IMPORT \ -unsafe +ifdef NO_MONO_SECURITY +MONO_DATA_TDS= +else +MONO_DATA_TDS=Mono.Data.Tds +endif + ifdef MOBILE_PROFILE -LIB_REFS += Mono.Data.Tds System.Transactions +LIB_REFS += $(MONO_DATA_TDS) System.Transactions LIB_MCS_FLAGS += -d:NO_CODEDOM -d:NO_OLEDB -d:NO_ODBC -d:NO_CONFIGURATION else -LIB_REFS += System.EnterpriseServices Mono.Data.Tds System.Configuration System.Transactions +LIB_REFS += System.EnterpriseServices $(MONO_DATA_TDS) System.Configuration System.Transactions BUILT_SOURCES = \ gen_OdbcConnection.cs \ gen_OleDbConnection.cs \ diff --git a/mcs/class/System.Data/ReferenceSources/PoolBlockingPeriod.cs b/mcs/class/System.Data/ReferenceSources/PoolBlockingPeriod.cs new file mode 100644 index 0000000000..82231f413b --- /dev/null +++ b/mcs/class/System.Data/ReferenceSources/PoolBlockingPeriod.cs @@ -0,0 +1,9 @@ +namespace System.Data.SqlClient +{ + public enum PoolBlockingPeriod + { + Auto, + AlwaysBlock, + NeverBlock + } +} \ No newline at end of file diff --git a/mcs/class/System.Data/ReferenceSources/Res.cs.REMOVED.git-id b/mcs/class/System.Data/ReferenceSources/Res.cs.REMOVED.git-id index 0174e13871..ad0b84f0a8 100644 --- a/mcs/class/System.Data/ReferenceSources/Res.cs.REMOVED.git-id +++ b/mcs/class/System.Data/ReferenceSources/Res.cs.REMOVED.git-id @@ -1 +1 @@ -1fce5dcce82839c44d1805b58f449849591dc318 \ No newline at end of file +c103d0d1e3bf658a2717757fb01d2e7b56405504 \ No newline at end of file diff --git a/mcs/class/System.Data/System.Data.SqlClient/SqlBulkCopy.platformnotsupported.cs b/mcs/class/System.Data/System.Data.SqlClient/SqlBulkCopy.platformnotsupported.cs new file mode 100644 index 0000000000..95d6801851 --- /dev/null +++ b/mcs/class/System.Data/System.Data.SqlClient/SqlBulkCopy.platformnotsupported.cs @@ -0,0 +1,136 @@ +// +// SqlBulkCopy.cs +// +// Author: +// Rolf Bjarne Kvinge +// +// Copyright (c) 2016 Xamarin, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System.Data.Common; +using System.Threading; +using System.Threading.Tasks; + +namespace System.Data.SqlClient { + public sealed class SqlBulkCopy : IDisposable + { + const string EXCEPTION_MESSAGE = "System.Data.SqlClient.SqlBulkCopy is not supported on the current platform."; + + public SqlBulkCopy (SqlConnection connection) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public SqlBulkCopy (string connectionString) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public SqlBulkCopy (string connectionString, SqlBulkCopyOptions copyOptions) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public SqlBulkCopy (SqlConnection connection, SqlBulkCopyOptions copyOptions, SqlTransaction externalTransaction) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public int BatchSize { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public int BulkCopyTimeout { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public SqlBulkCopyColumnMappingCollection ColumnMappings { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public string DestinationTableName { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public bool EnableStreaming { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public int NotifyAfter { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public void Close () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void WriteToServer (DataRow [] rows) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void WriteToServer (DataTable table) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void WriteToServer (IDataReader reader) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void WriteToServer (DataTable table, DataRowState rowState) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void WriteToServer (DbDataReader reader) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public Task WriteToServerAsync (DbDataReader reader) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public Task WriteToServerAsync (DbDataReader reader, CancellationToken cancellationToken) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + private void RowsCopied (long rowsCopied) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public event SqlRowsCopiedEventHandler SqlRowsCopied; + + void IDisposable.Dispose () + { + } + } +} diff --git a/mcs/class/System.Data/System.Data.SqlClient/SqlCommand.cs b/mcs/class/System.Data/System.Data.SqlClient/SqlCommand.cs index c6dc7712ba..3fa1584fae 100644 --- a/mcs/class/System.Data/System.Data.SqlClient/SqlCommand.cs +++ b/mcs/class/System.Data/System.Data.SqlClient/SqlCommand.cs @@ -510,40 +510,104 @@ namespace System.Data.SqlClient { } } - [MonoTODO] public new Task ExecuteReaderAsync () { - throw new NotImplementedException (); + return ExecuteReaderAsync (CommandBehavior.Default, CancellationToken.None); } - [MonoTODO] public new Task ExecuteReaderAsync (CancellationToken cancellationToken) { - throw new NotImplementedException (); + return ExecuteReaderAsync (behavior, CancellationToken.None); } - [MonoTODO] public new Task ExecuteReaderAsync (CommandBehavior behavior) { - throw new NotImplementedException (); + return ExecuteReaderAsync (CommandBehavior.Default, CancellationToken.None); } - [MonoTODO] public new Task ExecuteReaderAsync (CommandBehavior behavior, CancellationToken cancellationToken) { - throw new NotImplementedException (); + TaskCompletionSource source = new TaskCompletionSource(); + + CancellationTokenRegistration registration = new CancellationTokenRegistration(); + if (cancellationToken.CanBeCanceled) { + if (cancellationToken.IsCancellationRequested) { + source.SetCanceled(); + return source.Task; + } + registration = cancellationToken.Register(CancelIgnoreFailure); + } + + Task returnedTask = source.Task; + try { + // TODO: RegisterForConnectionCloseNotification(ref returnedTask); + + Task.Factory.FromAsync(BeginExecuteReaderAsync, EndExecuteReader, behavior, null).ContinueWith((t) => { + registration.Dispose(); + if (t.IsFaulted) { + Exception e = t.Exception.InnerException; + source.SetException(e); + } + else { + if (t.IsCanceled) { + source.SetCanceled(); + } + else { + source.SetResult(t.Result); + } + } + }, TaskScheduler.Default); + } + catch (Exception e) { + source.SetException(e); + } + + return returnedTask; } - [MonoTODO] public Task ExecuteXmlReaderAsync () { - throw new NotImplementedException (); + return ExecuteXmlReaderAsync (CancellationToken.None); } - [MonoTODO] public Task ExecuteXmlReaderAsync (CancellationToken cancellationToken) { - throw new NotImplementedException (); + TaskCompletionSource source = new TaskCompletionSource(); + + CancellationTokenRegistration registration = new CancellationTokenRegistration(); + if (cancellationToken.CanBeCanceled) { + if (cancellationToken.IsCancellationRequested) { + source.SetCanceled(); + return source.Task; + } + registration = cancellationToken.Register(CancelIgnoreFailure); + } + + Task returnedTask = source.Task; + try { + // TODO: RegisterForConnectionCloseNotification(ref returnedTask); + + Task.Factory.FromAsync(BeginExecuteXmlReader, EndExecuteXmlReader, null).ContinueWith((t) => { + registration.Dispose(); + if (t.IsFaulted) { + Exception e = t.Exception.InnerException; + source.SetException(e); + } + else { + if (t.IsCanceled) { + source.SetCanceled(); + } + else { + source.SetResult(t.Result); + } + } + }, TaskScheduler.Default); + } + catch (Exception e) { + source.SetException(e); + } + + return returnedTask; } public @@ -846,6 +910,11 @@ namespace System.Data.SqlClient { return BeginExecuteReader (callback, stateObject, CommandBehavior.Default); } + IAsyncResult BeginExecuteReaderAsync(CommandBehavior behavior, AsyncCallback callback, object stateObject) + { + return BeginExecuteReader (callback, stateObject, behavior); + } + public IAsyncResult BeginExecuteReader (AsyncCallback callback, object stateObject, CommandBehavior behavior) { ValidateCommand ("BeginExecuteReader", true); diff --git a/mcs/class/System.Data/System.Data.SqlClient/SqlCommand.platformnotsupported.cs b/mcs/class/System.Data/System.Data.SqlClient/SqlCommand.platformnotsupported.cs new file mode 100644 index 0000000000..491483e107 --- /dev/null +++ b/mcs/class/System.Data/System.Data.SqlClient/SqlCommand.platformnotsupported.cs @@ -0,0 +1,277 @@ +// +// SqlCommand.cs +// +// Author: +// Rolf Bjarne Kvinge +// +// Copyright (c) 2016 Xamarin, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System.Data.Common; +using System.Data.Sql; +using System.Threading.Tasks; +using System.Threading; +using System.Xml; + +namespace System.Data.SqlClient { + public sealed class SqlCommand : DbCommand, IDbCommand, ICloneable + { + const string EXCEPTION_MESSAGE = "System.Data.SqlClient.SqlCommand is not supported on the current platform."; + + public SqlCommand() + : this (String.Empty, null, null) + { + } + + public SqlCommand (string cmdText) + : this (cmdText, null, null) + { + } + + public SqlCommand (string cmdText, SqlConnection connection) + : this (cmdText, connection, null) + { + } + + public SqlCommand (string cmdText, SqlConnection connection, SqlTransaction transaction) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override string CommandText { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override int CommandTimeout { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override CommandType CommandType { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public new SqlConnection Connection { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override bool DesignTimeVisible { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public new SqlParameterCollection Parameters { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public new SqlTransaction Transaction { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override UpdateRowSource UpdatedRowSource { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public SqlNotificationRequest Notification { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public bool NotificationAutoEnlist { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override void Cancel () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public SqlCommand Clone () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public new SqlParameter CreateParameter () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override int ExecuteNonQuery () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public new SqlDataReader ExecuteReader () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public new SqlDataReader ExecuteReader (CommandBehavior behavior) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public new Task ExecuteReaderAsync () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public new Task ExecuteReaderAsync (CancellationToken cancellationToken) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public new Task ExecuteReaderAsync (CommandBehavior behavior) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public new Task ExecuteReaderAsync (CommandBehavior behavior, CancellationToken cancellationToken) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public Task ExecuteXmlReaderAsync () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public Task ExecuteXmlReaderAsync (CancellationToken cancellationToken) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override object ExecuteScalar () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public XmlReader ExecuteXmlReader () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + object ICloneable.Clone () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + protected override void Dispose (bool disposing) + { + } + + public override void Prepare () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void ResetCommandTimeout () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + protected override DbParameter CreateDbParameter () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + protected override DbDataReader ExecuteDbDataReader (CommandBehavior behavior) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + protected override DbConnection DbConnection { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + protected override DbParameterCollection DbParameterCollection { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + protected override DbTransaction DbTransaction { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public IAsyncResult BeginExecuteNonQuery () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public IAsyncResult BeginExecuteNonQuery (AsyncCallback callback, object stateObject) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public int EndExecuteNonQuery (IAsyncResult asyncResult) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public IAsyncResult BeginExecuteReader () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public IAsyncResult BeginExecuteReader (CommandBehavior behavior) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public IAsyncResult BeginExecuteReader (AsyncCallback callback, object stateObject) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public IAsyncResult BeginExecuteReader (AsyncCallback callback, object stateObject, CommandBehavior behavior) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public SqlDataReader EndExecuteReader (IAsyncResult asyncResult) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public IAsyncResult BeginExecuteXmlReader (AsyncCallback callback, object stateObject) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public IAsyncResult BeginExecuteXmlReader () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public XmlReader EndExecuteXmlReader (IAsyncResult asyncResult) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public event StatementCompletedEventHandler StatementCompleted; + } +} diff --git a/mcs/class/System.Data/System.Data.SqlClient/SqlCommandBuilder.platformnotsupported.cs b/mcs/class/System.Data/System.Data.SqlClient/SqlCommandBuilder.platformnotsupported.cs new file mode 100644 index 0000000000..155ddabc19 --- /dev/null +++ b/mcs/class/System.Data/System.Data.SqlClient/SqlCommandBuilder.platformnotsupported.cs @@ -0,0 +1,158 @@ +// +// SqlCommandBuilder.cs +// +// Author: +// Rolf Bjarne Kvinge +// +// Copyright (c) 2016 Xamarin, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Data; +using System.Data.Common; +using System.Data.SqlClient; + +namespace System.Data.SqlClient +{ + public class SqlCommandBuilder : DbCommandBuilder + { + const string EXCEPTION_MESSAGE = "System.Data.SqlClient.SqlCommandBuilder is not supported on the current platform."; + + public SqlCommandBuilder () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public SqlCommandBuilder (SqlDataAdapter adapter) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public static void DeriveParameters (SqlCommand command) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public SqlCommand GetDeleteCommand () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public SqlCommand GetInsertCommand () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public SqlCommand GetUpdateCommand () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public SqlCommand GetUpdateCommand (bool useColumnsForParameterNames) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public SqlCommand GetDeleteCommand (bool useColumnsForParameterNames) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public SqlCommand GetInsertCommand (bool useColumnsForParameterNames) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override string QuoteIdentifier (string unquotedIdentifier) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override string UnquoteIdentifier (string quotedIdentifier) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + protected override void ApplyParameterInfo (DbParameter parameter, DataRow datarow, StatementType statementType, bool whereClause) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + protected override string GetParameterName (int parameterOrdinal) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + protected override string GetParameterName (string parameterName) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + protected override string GetParameterPlaceholder (int parameterOrdinal) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + protected override void SetRowUpdatingHandler (DbDataAdapter adapter) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + protected override DataTable GetSchemaTable (DbCommand srcCommand) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + protected override DbCommand InitializeCommand (DbCommand command) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public SqlDataAdapter DataAdapter { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override string QuotePrefix { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override string QuoteSuffix { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override string CatalogSeparator { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override string SchemaSeparator { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override CatalogLocation CatalogLocation { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + } +} diff --git a/mcs/class/System.Data/System.Data.SqlClient/SqlConnection.cs b/mcs/class/System.Data/System.Data.SqlClient/SqlConnection.cs index 9af24e6505..ce6e9e45cd 100644 --- a/mcs/class/System.Data/System.Data.SqlClient/SqlConnection.cs +++ b/mcs/class/System.Data/System.Data.SqlClient/SqlConnection.cs @@ -928,7 +928,11 @@ namespace System.Data.SqlClient if (Client.Available <= 0) return -1; // Error - IPEndPoint endpoint = new IPEndPoint (Dns.GetHostEntry ("localhost").AddressList [0], 0); + + IPEndPoint endpoint = CreateLocalEndpoint (); + if (endpoint == null) + return -1; + Byte [] rawrs; rawrs = Receive (ref endpoint); @@ -953,6 +957,16 @@ namespace System.Data.SqlClient return SqlServerTcpPort; } + + IPEndPoint CreateLocalEndpoint () + { + foreach (var addr in Dns.GetHostEntry ("localhost").AddressList) { + if (addr.AddressFamily == Client.AddressFamily) + return new IPEndPoint (addr, 0); + } + + return null; + } } struct ColumnInfo diff --git a/mcs/class/System.Data/System.Data.SqlClient/SqlConnection.platformnotsupported.cs b/mcs/class/System.Data/System.Data.SqlClient/SqlConnection.platformnotsupported.cs new file mode 100644 index 0000000000..bb35026449 --- /dev/null +++ b/mcs/class/System.Data/System.Data.SqlClient/SqlConnection.platformnotsupported.cs @@ -0,0 +1,214 @@ +// +// SqlConnection.cs +// +// Author: +// Rolf Bjarne Kvinge +// +// Copyright (c) 2016 Xamarin, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System.Collections; +using System.Data.Common; + +namespace System.Data.SqlClient +{ + public sealed class SqlConnection : DbConnection, IDbConnection, ICloneable + { + const string EXCEPTION_MESSAGE = "System.Data.SqlClient.SqlConnection is not supported on the current platform."; + + public SqlConnection () : this (null) + { + } + + public SqlConnection (string connectionString) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public SqlConnection (string connectionString, SqlCredential cred) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override string ConnectionString { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public SqlCredential Credentials { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public Guid ClientConnectionId { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override int ConnectionTimeout { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override string Database { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override string DataSource { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public int PacketSize { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override string ServerVersion { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override ConnectionState State { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public string WorkstationId { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public bool FireInfoMessageEventOnUserErrors { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public bool StatisticsEnabled { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + protected override DbProviderFactory DbProviderFactory { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public event SqlInfoMessageEventHandler InfoMessage; + + public new SqlTransaction BeginTransaction () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public new SqlTransaction BeginTransaction (IsolationLevel iso) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public SqlTransaction BeginTransaction (string transactionName) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public SqlTransaction BeginTransaction (IsolationLevel iso, string transactionName) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override void ChangeDatabase (string database) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override void Close () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public new SqlCommand CreateCommand () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + protected override void Dispose (bool disposing) + { + } + +#if !MOBILE + public void EnlistDistributedTransaction (ITransaction transaction) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } +#endif + + object ICloneable.Clone () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + protected override DbTransaction BeginDbTransaction (IsolationLevel isolationLevel) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + protected override DbCommand CreateDbCommand () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override void Open () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override DataTable GetSchema () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override DataTable GetSchema (String collectionName) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override DataTable GetSchema (String collectionName, string [] restrictionValues) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public static void ChangePassword (string connectionString, string newPassword) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public static void ClearAllPools () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public static void ClearPool (SqlConnection connection) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void ResetStatistics () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public IDictionary RetrieveStatistics () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + } +} diff --git a/mcs/class/System.Data/System.Data.SqlClient/SqlDataReader.platformnotsupported.cs b/mcs/class/System.Data/System.Data.SqlClient/SqlDataReader.platformnotsupported.cs new file mode 100644 index 0000000000..395e97ac19 --- /dev/null +++ b/mcs/class/System.Data/System.Data.SqlClient/SqlDataReader.platformnotsupported.cs @@ -0,0 +1,363 @@ +// +// SqlDataReader.cs +// +// Author: +// Rolf Bjarne Kvinge +// +// Copyright (c) 2016 Xamarin, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections; +using System.Data.Common; +using System.Data.SqlClient; +using System.Data.SqlTypes; +using System.Data; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using System.Xml; + + +namespace System.Data.SqlClient +{ + public class SqlDataReader : DbDataReader , IDataReader, IDisposable, IDataRecord + { + const string EXCEPTION_MESSAGE = "System.Data.SqlClient.SqlDataReader is not supported on the current platform."; + + SqlDataReader () {} + + protected bool IsCommandBehavior (CommandBehavior condition) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override void Close () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override bool GetBoolean (int i) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override byte GetByte (int i) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override long GetBytes (int i, long dataIndex, byte [] buffer, int bufferIndex, int length) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override char GetChar (int i) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override long GetChars (int i, long dataIndex, char [] buffer, int bufferIndex, int length) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override string GetDataTypeName (int i) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override DateTime GetDateTime (int i) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public virtual DateTimeOffset GetDateTimeOffset (int i) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public virtual TimeSpan GetTimeSpan (int i) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public virtual SqlChars GetSqlChars (int i) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override Decimal GetDecimal (int i) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override Double GetDouble (int i) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override Type GetFieldType (int i) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override Single GetFloat (int i) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override Guid GetGuid (int i) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override short GetInt16 (int i) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override int GetInt32 (int i) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override long GetInt64 (int i) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override string GetName (int i) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override int GetOrdinal (string name) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override DataTable GetSchemaTable () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public virtual SqlBinary GetSqlBinary (int i) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public virtual SqlBoolean GetSqlBoolean (int i) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public virtual SqlByte GetSqlByte (int i) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public virtual SqlDateTime GetSqlDateTime (int i) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public virtual SqlDecimal GetSqlDecimal (int i) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public virtual SqlDouble GetSqlDouble (int i) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public virtual SqlGuid GetSqlGuid (int i) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public virtual SqlInt16 GetSqlInt16 (int i) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public virtual SqlInt32 GetSqlInt32 (int i) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public virtual SqlInt64 GetSqlInt64 (int i) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public virtual SqlMoney GetSqlMoney (int i) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public virtual SqlSingle GetSqlSingle (int i) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public virtual SqlString GetSqlString (int i) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public virtual SqlXml GetSqlXml (int i) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public virtual object GetSqlValue (int i) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public virtual int GetSqlValues (object [] values) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override string GetString (int i) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override object GetValue (int i) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override int GetValues (object [] values) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override IEnumerator GetEnumerator () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override bool IsDBNull (int i) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override bool NextResult () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override bool Read () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override Type GetProviderSpecificFieldType (int i) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override object GetProviderSpecificValue (int i) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override int GetProviderSpecificValues (object [] values) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public virtual SqlBytes GetSqlBytes (int i) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override T GetFieldValue (int i) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public virtual XmlReader GetXmlReader (int i) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override Task GetFieldValueAsync (int i, CancellationToken cancellationToken) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override Stream GetStream (int i) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override TextReader GetTextReader (int i) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override Task IsDBNullAsync (int i, CancellationToken cancellationToken) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override int Depth { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override int FieldCount { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override bool IsClosed { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override object this [int i] { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override object this [string name] { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override int RecordsAffected { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override bool HasRows { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override int VisibleFieldCount { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + protected SqlConnection Connection { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + } +} diff --git a/mcs/class/System.Data/System.Data.SqlClient/SqlException.platformnotsupported.cs b/mcs/class/System.Data/System.Data.SqlClient/SqlException.platformnotsupported.cs new file mode 100644 index 0000000000..24d102d76f --- /dev/null +++ b/mcs/class/System.Data/System.Data.SqlClient/SqlException.platformnotsupported.cs @@ -0,0 +1,102 @@ +// +// SqlException.cs +// +// Author: +// Rolf Bjarne Kvinge +// +// Copyright (c) 2016 Xamarin, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Data.Common; +using System.Data.SqlClient; +using System.Runtime.Serialization; + +namespace System.Data.SqlClient +{ + public class SqlException : DbException + { + const string EXCEPTION_MESSAGE = "System.Data.SqlClient.SqlException is not supported on the current platform."; + + internal bool _doNotReconnect; + + static internal SqlException CreateException(SqlErrorCollection errorCollection, string serverVersion) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + static internal SqlException CreateException(SqlErrorCollection errorCollection, string serverVersion, SqlInternalConnectionTds internalConnection, Exception innerException = null) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + static internal SqlException CreateException(SqlErrorCollection errorCollection, string serverVersion, Guid conId, Exception innerException = null) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + SqlException () {} + + public override void GetObjectData (SerializationInfo si, StreamingContext context) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public byte Class { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public Guid ClientConnectionId { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public SqlErrorCollection Errors { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public int LineNumber { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override string Message { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public int Number { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public string Procedure { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public string Server { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override string Source { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public byte State { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + } +} diff --git a/mcs/class/System.Data/System.Data.SqlClient/SqlParameter.platformnotsupported.cs b/mcs/class/System.Data/System.Data.SqlClient/SqlParameter.platformnotsupported.cs new file mode 100644 index 0000000000..79f6f95bae --- /dev/null +++ b/mcs/class/System.Data/System.Data.SqlClient/SqlParameter.platformnotsupported.cs @@ -0,0 +1,198 @@ +// +// SqlParameter.cs +// +// Author: +// Rolf Bjarne Kvinge +// +// Copyright (c) 2016 Xamarin, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Data; +using System.Data.Common; +using System.Data.SqlTypes; + +namespace System.Data.SqlClient +{ + public class SqlParameter : DbParameter , IDbDataParameter, IDataParameter, ICloneable + { + const string EXCEPTION_MESSAGE = "System.Data.SqlClient.SqlParameter is not supported on the current platform."; + + public SqlParameter () + : this (String.Empty, SqlDbType.NVarChar, 0, ParameterDirection.Input, false, 0, 0, String.Empty, DataRowVersion.Current, null) + { + } + + public SqlParameter (string parameterName, object value) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public SqlParameter (string parameterName, SqlDbType dbType) + : this (parameterName, dbType, 0, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, null) + { + } + + public SqlParameter (string parameterName, SqlDbType dbType, int size) + : this (parameterName, dbType, size, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, null) + { + } + + public SqlParameter (string parameterName, SqlDbType dbType, int size, string sourceColumn) + : this (parameterName, dbType, size, ParameterDirection.Input, false, 0, 0, sourceColumn, DataRowVersion.Current, null) + { + } + + public SqlParameter (string parameterName, SqlDbType dbType, int size, ParameterDirection direction, bool isNullable, byte precision, byte scale, string sourceColumn, DataRowVersion sourceVersion, object value) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public SqlParameter (string parameterName, SqlDbType dbType, int size, ParameterDirection direction, byte precision, byte scale, string sourceColumn, DataRowVersion sourceVersion, bool sourceColumnNullMapping, Object value, string xmlSchemaCollectionDatabase, string xmlSchemaCollectionOwningSchema, string xmlSchemaCollectionName) + : this (parameterName, dbType, size, direction, false, precision, scale, sourceColumn, sourceVersion, value) + { + } + + public override string ToString () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override void ResetDbType () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void ResetSqlDbType () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override DbType DbType { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override ParameterDirection Direction { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override bool IsNullable { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public int Offset { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override string ParameterName { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public byte Precision { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public byte Scale { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override int Size { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override string SourceColumn { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override DataRowVersion SourceVersion { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public SqlDbType SqlDbType { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override object Value { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public SqlCompareOptions CompareInfo { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public int LocaleId { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public object SqlValue { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override bool SourceColumnNullMapping { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public string XmlSchemaCollectionDatabase { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public string XmlSchemaCollectionName { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public string XmlSchemaCollectionOwningSchema { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public string UdtTypeName { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public string TypeName { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + object ICloneable.Clone () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + } +} diff --git a/mcs/class/System.Data/System.Data.SqlClient/SqlParameterCollection.platformnotsupported.cs b/mcs/class/System.Data/System.Data.SqlClient/SqlParameterCollection.platformnotsupported.cs new file mode 100644 index 0000000000..cc3a6ab153 --- /dev/null +++ b/mcs/class/System.Data/System.Data.SqlClient/SqlParameterCollection.platformnotsupported.cs @@ -0,0 +1,216 @@ +// +// SqlParameterCollection.cs +// +// Author: +// Rolf Bjarne Kvinge +// +// Copyright (c) 2016 Xamarin, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections; +using System.Data; +using System.Data.Common; +using System.Data.SqlClient; + +namespace System.Data.SqlClient +{ + public class SqlParameterCollection : DbParameterCollection , IDataParameterCollection, IList, ICollection, IEnumerable + { + const string EXCEPTION_MESSAGE = "System.Data.SqlClient.SqlParameterCollection is not supported on the current platform."; + + SqlParameterCollection () {} + + protected override DbParameter GetParameter (int index) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + protected override DbParameter GetParameter (string parameterName) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + protected override void SetParameter (int index, DbParameter value) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + protected override void SetParameter (string parameterName, DbParameter value) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override int Add (object value) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public SqlParameter Add (SqlParameter value) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public SqlParameter Add (string parameterName, object value) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public SqlParameter AddWithValue (string parameterName, object value) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public SqlParameter Add (string parameterName, SqlDbType sqlDbType) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public SqlParameter Add (string parameterName, SqlDbType sqlDbType, int size) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public SqlParameter Add (string parameterName, SqlDbType sqlDbType, int size, string sourceColumn) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override void Clear () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override bool Contains (object value) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override bool Contains (string value) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public bool Contains (SqlParameter value) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override void CopyTo (Array array, int index) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override IEnumerator GetEnumerator () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override int IndexOf (object value) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override int IndexOf (string parameterName) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public int IndexOf (SqlParameter value) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override void Insert (int index, object value) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void Insert (int index, SqlParameter value) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override void Remove (object value) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void Remove (SqlParameter value) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override void RemoveAt (int index) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override void RemoveAt (string parameterName) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override void AddRange (Array values) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void AddRange (SqlParameter [] values) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void CopyTo (SqlParameter [] array, int index) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override int Count { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override bool IsFixedSize { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override bool IsReadOnly { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override bool IsSynchronized { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override object SyncRoot { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public SqlParameter this [int index] { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public SqlParameter this [string parameterName] { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + } +} diff --git a/mcs/class/System.Data/System.Data.SqlClient/SqlTransaction.platformnotsupported.cs b/mcs/class/System.Data/System.Data.SqlClient/SqlTransaction.platformnotsupported.cs new file mode 100644 index 0000000000..880b740c48 --- /dev/null +++ b/mcs/class/System.Data/System.Data.SqlClient/SqlTransaction.platformnotsupported.cs @@ -0,0 +1,77 @@ +// +// SqlTransaction.cs +// +// Author: +// Rolf Bjarne Kvinge +// +// Copyright (c) 2016 Xamarin, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Data; +using System.Data.Common; +using System.Data.SqlClient; + +namespace System.Data.SqlClient +{ + public class SqlTransaction : DbTransaction , IDbTransaction, IDisposable + { + const string EXCEPTION_MESSAGE = "System.Data.SqlClient.SqlTransaction is not supported on the current platform."; + + SqlTransaction () {} + + public override void Commit () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + protected override void Dispose (bool disposing) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override void Rollback () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void Rollback (string transactionName) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void Save (string savePointName) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public SqlConnection Connection { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override IsolationLevel IsolationLevel { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + protected override DbConnection DbConnection { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + } +} diff --git a/mcs/class/System.Data/Test/System.Data.Common/DbDataAdapterTest.cs b/mcs/class/System.Data/Test/System.Data.Common/DbDataAdapterTest.cs index 3749af5091..a897494997 100644 --- a/mcs/class/System.Data/Test/System.Data.Common/DbDataAdapterTest.cs +++ b/mcs/class/System.Data/Test/System.Data.Common/DbDataAdapterTest.cs @@ -96,10 +96,14 @@ namespace MonoTests.System.Data.Common try { da.AddToBatch (new SqlCommand ()); Assert.Fail ("#1"); +#if FEATURE_NO_BSD_SOCKETS + } catch (PlatformNotSupportedException) { +#else } catch (NotSupportedException ex) { Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#2"); Assert.IsNull (ex.InnerException, "#3"); Assert.IsNotNull (ex.Message, "#4"); +#endif } } diff --git a/mcs/class/System.Data/Test/System.Data.Common/DbDataReaderTest.cs b/mcs/class/System.Data/Test/System.Data.Common/DbDataReaderTest.cs index 20d5c1ab0b..ff7ebcbe0c 100644 --- a/mcs/class/System.Data/Test/System.Data.Common/DbDataReaderTest.cs +++ b/mcs/class/System.Data/Test/System.Data.Common/DbDataReaderTest.cs @@ -61,7 +61,6 @@ namespace MonoTests.System.Data.Common { } - #if NET_4_5 [Test] public void GetFieldValueTest () { @@ -155,7 +154,6 @@ namespace MonoTests.System.Data.Common Assert.IsFalse (dataReader.Read (), "#5"); } - #endif //NET_4_5 } } diff --git a/mcs/class/System.Data/Test/System.Data.SqlClient/SqlBulkCopyTest.cs b/mcs/class/System.Data/Test/System.Data.SqlClient/SqlBulkCopyTest.cs index b65ba7abab..4fbbbbefe4 100644 --- a/mcs/class/System.Data/Test/System.Data.SqlClient/SqlBulkCopyTest.cs +++ b/mcs/class/System.Data/Test/System.Data.SqlClient/SqlBulkCopyTest.cs @@ -39,21 +39,33 @@ namespace MonoTests.System.Data.SqlClient { private const string testFailParamNameMessage = "We have to provide the same parameter name as in original .NET"; [Test] // .ctor(SqlConnection connection) +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#else [ExpectedException (typeof(ArgumentNullException))] +#endif public void ConstructorNotNull1 () { new SqlBulkCopy ((SqlConnection)null); } [Test] // .ctor(string connectionString) +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#else [ExpectedException (typeof(ArgumentNullException))] +#endif public void ConstructorNotNull2 () { new SqlBulkCopy ((string)null); } [Test] // .ctor(SqlConnection connection) +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#else [ExpectedException (typeof(ArgumentNullException))] +#endif public void ConstructorNotNull3 () { try { @@ -65,7 +77,11 @@ namespace MonoTests.System.Data.SqlClient { } [Test] // .ctor(string connectionString) +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#else [ExpectedException (typeof(ArgumentNullException))] +#endif public void ConstructorNotNull4 () { try { @@ -77,7 +93,11 @@ namespace MonoTests.System.Data.SqlClient { } [Test] // .ctor(string connectionString) +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#else [ExpectedException (typeof(ArgumentNullException))] +#endif public void ConstructorNotNull5 () { try { @@ -89,7 +109,11 @@ namespace MonoTests.System.Data.SqlClient { } [Test] // .ctor(string connectionString) +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#else [ExpectedException (typeof(ArgumentNullException))] +#endif public void ConstructorNotNull6 () { try { diff --git a/mcs/class/System.Data/Test/System.Data.SqlClient/SqlCommandBuilderTest.cs b/mcs/class/System.Data/Test/System.Data.SqlClient/SqlCommandBuilderTest.cs index c2d788bd3f..49abd6064d 100644 --- a/mcs/class/System.Data/Test/System.Data.SqlClient/SqlCommandBuilderTest.cs +++ b/mcs/class/System.Data/Test/System.Data.SqlClient/SqlCommandBuilderTest.cs @@ -38,6 +38,9 @@ namespace MonoTests.System.Data.Odbc public class SqlCommandBuilderTest { [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void CatalogLocationTest () { SqlCommandBuilder cb = new SqlCommandBuilder (); @@ -47,6 +50,9 @@ namespace MonoTests.System.Data.Odbc } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void CatalogLocation_Value_Invalid () { SqlCommandBuilder cb = new SqlCommandBuilder (); @@ -82,6 +88,9 @@ namespace MonoTests.System.Data.Odbc } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void CatalogSeparator () { SqlCommandBuilder cb = new SqlCommandBuilder (); @@ -89,6 +98,9 @@ namespace MonoTests.System.Data.Odbc } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void CatalogSeparator_Value_Invalid () { string [] separators = new string [] { @@ -118,6 +130,9 @@ namespace MonoTests.System.Data.Odbc } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ConflictOptionTest () { SqlCommandBuilder cb = new SqlCommandBuilder (); @@ -127,6 +142,9 @@ namespace MonoTests.System.Data.Odbc } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ConflictOption_Value_Invalid () { SqlCommandBuilder cb = new SqlCommandBuilder (); @@ -147,6 +165,9 @@ namespace MonoTests.System.Data.Odbc } [Test] // QuoteIdentifier (String) +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void QuoteIdentifier () { SqlCommandBuilder cb; @@ -173,6 +194,9 @@ namespace MonoTests.System.Data.Odbc } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void QuoteIdentifier_PrefixSuffix_NoMatch () { SqlCommandBuilder cb; @@ -211,6 +235,9 @@ namespace MonoTests.System.Data.Odbc } [Test] // QuoteIdentifier (String) +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void QuoteIdentifier_UnquotedIdentifier_Null () { SqlCommandBuilder cb = new SqlCommandBuilder (); @@ -226,6 +253,9 @@ namespace MonoTests.System.Data.Odbc } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void QuotePrefix () { SqlCommandBuilder cb = new SqlCommandBuilder (); @@ -240,6 +270,9 @@ namespace MonoTests.System.Data.Odbc } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void QuotePrefix_Value_Invalid () { string [] prefixes = new string [] { @@ -268,6 +301,9 @@ namespace MonoTests.System.Data.Odbc } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void QuoteSuffix () { SqlCommandBuilder cb = new SqlCommandBuilder (); @@ -282,6 +318,9 @@ namespace MonoTests.System.Data.Odbc } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void QuoteSuffix_Value_Invalid () { string [] suffixes = new string [] { @@ -310,6 +349,9 @@ namespace MonoTests.System.Data.Odbc } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void SchemaSeparator () { SqlCommandBuilder cb = new SqlCommandBuilder (); @@ -319,6 +361,9 @@ namespace MonoTests.System.Data.Odbc } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void SchemaSeparator_Value_Invalid () { string [] separators = new string [] { diff --git a/mcs/class/System.Data/Test/System.Data.SqlClient/SqlCommandTest.cs b/mcs/class/System.Data/Test/System.Data.SqlClient/SqlCommandTest.cs index d02532a45d..be36ba383c 100644 --- a/mcs/class/System.Data/Test/System.Data.SqlClient/SqlCommandTest.cs +++ b/mcs/class/System.Data/Test/System.Data.SqlClient/SqlCommandTest.cs @@ -42,6 +42,9 @@ namespace MonoTests.System.Data.SqlClient const string COMMAND_TEXT = "SELECT * FROM Authors"; [Test] // SqlCommand () +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Constructor1 () { SqlCommand cmd = new SqlCommand (); @@ -61,6 +64,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] // SqlCommand (string) +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Constructor2 () { SqlCommand cmd = new SqlCommand (COMMAND_TEXT); @@ -95,6 +101,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] // SqlCommand (string, SqlConnection) +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Constructor3 () { SqlConnection conn = new SqlConnection (); @@ -147,6 +156,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] // SqlCommand (string, SqlConnection, SqlTransaction) +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Constructor4 () { SqlConnection conn = new SqlConnection (); @@ -199,6 +211,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Clone () { SqlNotificationRequest notificationReq = new SqlNotificationRequest (); @@ -237,6 +252,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void CommandText () { SqlCommand cmd = new SqlCommand (); @@ -251,6 +269,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void CommandTimeout () { SqlCommand cmd = new SqlCommand (); @@ -263,6 +284,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void CommandTimeout_Value_Negative () { SqlCommand cmd = new SqlCommand (); @@ -279,6 +303,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void CommandType_Value_Invalid () { SqlCommand cmd = new SqlCommand (); @@ -296,6 +323,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] // bug #324386 +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Dispose () { string connectionString = "Initial Catalog=a;Server=b;User ID=c;" @@ -307,6 +337,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ExecuteNonQuery_Connection_Closed () { string connectionString = "Initial Catalog=a;Server=b;User ID=c;" @@ -329,6 +362,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ExecuteNonQuery_Connection_Null () { SqlCommand cmd = new SqlCommand ("delete from whatever"); @@ -346,6 +382,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ExecuteReader_Connection_Closed () { string connectionString = "Initial Catalog=a;Server=b;User ID=c;" @@ -368,6 +407,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ExecuteReader_Connection_Null () { SqlCommand cmd = new SqlCommand ("select * from whatever"); @@ -385,6 +427,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ExecuteScalar_Connection_Closed () { string connectionString = "Initial Catalog=a;Server=b;User ID=c;" @@ -407,6 +452,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] // bug #412584 +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ExecuteScalar_Connection_Null () { SqlCommand cmd = new SqlCommand ("select count(*) from whatever"); @@ -425,6 +473,9 @@ namespace MonoTests.System.Data.SqlClient // FIXME: this actually doesn't match .NET behavior. It shouldn't throw NRE. [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Prepare_Connection_Null () { SqlCommand cmd; @@ -477,6 +528,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] // bug #412586 +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Prepare_Connection_Closed () { string connectionString = "Initial Catalog=a;Server=b;User ID=c;" @@ -527,6 +581,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ResetCommandTimeout () { SqlCommand cmd = new SqlCommand (); @@ -537,6 +594,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void UpdatedRowSource () { SqlCommand cmd = new SqlCommand (); @@ -547,6 +607,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void UpdatedRowSource_Value_Invalid () { SqlCommand cmd = new SqlCommand (); @@ -565,6 +628,9 @@ namespace MonoTests.System.Data.SqlClient [Test] // bug #381100 +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ParameterCollectionTest () { SqlCommand cmd = new SqlCommand(); diff --git a/mcs/class/System.Data/Test/System.Data.SqlClient/SqlConnectionTest.cs b/mcs/class/System.Data/Test/System.Data.SqlClient/SqlConnectionTest.cs index 04a4b99871..9511be24f7 100644 --- a/mcs/class/System.Data/Test/System.Data.SqlClient/SqlConnectionTest.cs +++ b/mcs/class/System.Data/Test/System.Data.SqlClient/SqlConnectionTest.cs @@ -39,6 +39,9 @@ namespace MonoTests.System.Data.SqlClient public class SqlConnectionTest { [Test] // SqlConnection () +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Constructor1 () { SqlConnection cn = new SqlConnection (); @@ -57,6 +60,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] // SqlConnection (string) +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Constructor2 () { string connectionString = "server=SQLSRV; database=Mono;"; @@ -89,6 +95,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Constructor2_ConnectionString_Invalid () { try { @@ -181,6 +190,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void BeginTransaction_Connection_Closed () { SqlConnection cn = new SqlConnection (); @@ -247,6 +259,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ChangeDatabase_Connection_Closed () { SqlConnection cn = new SqlConnection (); @@ -264,6 +279,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ChangePassword_ConnectionString_Empty () { try { @@ -279,6 +297,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ChangePassword_ConnectionString_Null () { try { @@ -293,7 +314,10 @@ namespace MonoTests.System.Data.SqlClient } } - [Test] + +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ChangePassword_NewPassword_Empty () { try { @@ -309,6 +333,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ChangePassword_NewPassword_ExceedMaxLength () { try { @@ -328,6 +355,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ChangePassword_NewPassword_Null () { try { @@ -343,6 +373,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ClearPool_Connection_Null () { try { @@ -357,6 +390,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ConnectionString () { SqlConnection cn = new SqlConnection (); @@ -371,6 +407,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ConnectionString_Value_Invalid () { SqlConnection cn = new SqlConnection (); @@ -403,6 +442,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void CreateCommand () { SqlConnection cn = new SqlConnection (); @@ -424,6 +466,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Dispose () { SqlConnection cn = new SqlConnection ("Server=SQLSRV;Database=master;Timeout=25;Packet Size=512;Workstation ID=DUMMY"); @@ -443,6 +488,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void GetSchema_Connection_Closed () { SqlConnection cn = new SqlConnection (); @@ -519,6 +567,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ConnectionString_AsynchronousProcessing () { SqlConnection cn = new SqlConnection (); @@ -527,6 +578,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ConnectionString_ConnectTimeout () { SqlConnection cn = new SqlConnection (); @@ -543,6 +597,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ConnectionString_ConnectTimeout_Invalid () { SqlConnection cn = new SqlConnection (); @@ -600,6 +657,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ConnectionString_Database_Synonyms () { SqlConnection cn = null; @@ -614,6 +674,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ConnectionString_DataSource_Synonyms () { SqlConnection cn = null; @@ -640,6 +703,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ConnectionString_MaxPoolSize () { SqlConnection cn = new SqlConnection (); @@ -649,6 +715,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ConnectionString_MaxPoolSize_Invalid () { SqlConnection cn = new SqlConnection (); @@ -733,6 +802,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ConnectionString_MinPoolSize () { SqlConnection cn = new SqlConnection (); @@ -742,6 +814,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ConnectionString_MinPoolSize_Invalid () { SqlConnection cn = new SqlConnection (); @@ -799,6 +874,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ConnectionString_MultipleActiveResultSets () { SqlConnection cn = new SqlConnection (); @@ -806,6 +884,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ConnectionString_MultipleActiveResultSets_Invalid () { SqlConnection cn = new SqlConnection (); @@ -823,6 +904,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ConnectionString_NetworkLibrary_Synonyms () { SqlConnection cn = new SqlConnection (); @@ -832,6 +916,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ConnectionString_PacketSize () { SqlConnection cn = new SqlConnection (); @@ -848,6 +935,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ConnectionString_PacketSize_Invalid () { SqlConnection cn = new SqlConnection (); @@ -901,6 +991,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ConnectionString_Password_Synonyms () { SqlConnection cn = new SqlConnection (); @@ -909,6 +1002,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ConnectionString_PersistSecurityInfo_Synonyms () { SqlConnection cn = new SqlConnection (); @@ -917,6 +1013,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ConnectionString_UserID_Synonyms () { SqlConnection cn = new SqlConnection (); @@ -926,6 +1025,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ConnectionString_UserInstance () { SqlConnection cn = new SqlConnection (); @@ -933,6 +1035,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ConnectionString_UserInstance_Invalid () { SqlConnection cn = new SqlConnection (); @@ -950,6 +1055,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ConnectionString_OtherKeywords () { SqlConnection cn = new SqlConnection (); @@ -973,6 +1081,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Open_ConnectionString_Empty () { SqlConnection cn = new SqlConnection (); @@ -991,6 +1102,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Open_ConnectionString_Null () { SqlConnection cn = new SqlConnection (); @@ -1009,6 +1123,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Open_ConnectionString_Whitespace () { SqlConnection cn = new SqlConnection (); @@ -1027,6 +1144,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ServerVersion_Connection_Closed () { SqlConnection cn = new SqlConnection (); @@ -1051,3 +1171,4 @@ namespace MonoTests.System.Data.SqlClient } } } + diff --git a/mcs/class/System.Data/Test/System.Data.SqlClient/SqlDataAdapterTest.cs b/mcs/class/System.Data/Test/System.Data.SqlClient/SqlDataAdapterTest.cs index 301f62bf7f..3a8b619baa 100644 --- a/mcs/class/System.Data/Test/System.Data.SqlClient/SqlDataAdapterTest.cs +++ b/mcs/class/System.Data/Test/System.Data.SqlClient/SqlDataAdapterTest.cs @@ -63,6 +63,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] // SqlDataAdapter (SqlCommand) +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Constructor2 () { SqlCommand cmd = new SqlCommand (); @@ -109,6 +112,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] // SqlDataAdapter (string, SqlConnection) +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Constructor3 () { string selectCommandText = "SELECT * FROM Authors"; @@ -137,6 +143,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] // SqlDataAdapter (string, SqlConnection) +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Constructor3_SelectCommandText_Null () { SqlConnection selectConnection = new SqlConnection (); @@ -165,6 +174,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] // SqlDataAdapter (string, SqlConnection) +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Constructor3_SelectConnection_Null () { string selectCommandText = "SELECT * FROM Authors"; @@ -192,6 +204,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] // SqlDataAdapter (string, string)] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Constructor4 () { string selectCommandText = "SELECT * FROM Authors"; @@ -221,6 +236,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] // SqlDataAdapter (string, string)] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Constructor4_SelectCommandText_Null () { string selectConnectionString = "server=SQLSRV;database=Mono"; @@ -250,6 +268,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] // SqlDataAdapter (string, string)] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Constructor4_SelectConnectionString_Null () { string selectCommandText = "SELECT * FROM Authors"; @@ -278,6 +299,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void DeleteCommand () { SqlDataAdapter da = new SqlDataAdapter (); @@ -293,6 +317,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Dispose () { SqlDataAdapter da = new SqlDataAdapter (); @@ -311,6 +338,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void InsertCommand () { SqlDataAdapter da = new SqlDataAdapter (); @@ -326,6 +356,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void SelectCommand () { SqlDataAdapter da = new SqlDataAdapter (); @@ -369,6 +402,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void UpdateCommand () { SqlDataAdapter da = new SqlDataAdapter (); diff --git a/mcs/class/System.Data/Test/System.Data.SqlClient/SqlParameterTest.cs b/mcs/class/System.Data/Test/System.Data.SqlClient/SqlParameterTest.cs index 27e6fd1bf4..e2048cfb9b 100644 --- a/mcs/class/System.Data/Test/System.Data.SqlClient/SqlParameterTest.cs +++ b/mcs/class/System.Data/Test/System.Data.SqlClient/SqlParameterTest.cs @@ -45,6 +45,9 @@ namespace MonoTests.System.Data.SqlClient public class SqlParameterTest { [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Constructor1 () { SqlParameter p = new SqlParameter (); @@ -68,6 +71,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Constructor2_Value_DateTime () { DateTime value = new DateTime (2004, 8, 24); @@ -94,6 +100,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Constructor2_Value_DBNull () { SqlParameter p = new SqlParameter ("address", DBNull.Value); @@ -118,6 +127,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Constructor2_Value_Null () { SqlParameter p = new SqlParameter ("address", (Object) null); @@ -141,6 +153,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] // .ctor (String, SqlDbType, Int32, ParameterDirection, Byte, Byte, String, DataRowVersion, Boolean, Object, String, String, String) +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Constructor7 () { SqlParameter p1 = new SqlParameter ("p1Name", SqlDbType.VarChar, 20, @@ -167,6 +182,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void CompareInfo () { SqlParameter parameter = new SqlParameter (); @@ -176,6 +194,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void InferType_Byte () { Byte value = 0x0a; @@ -187,6 +208,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void InferType_ByteArray () { Byte [] value = new Byte [] { 0x0a, 0x0d }; @@ -289,6 +313,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void InferType_DateTime () { DateTime value; @@ -314,6 +341,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void InferType_Decimal () { Decimal value; @@ -339,6 +369,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void InferType_Double () { Double value; @@ -364,6 +397,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void InferType_Enum () { SqlParameter param; @@ -380,6 +416,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void InferType_Guid () { Guid value = Guid.NewGuid (); @@ -391,6 +430,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void InferType_Int16 () { Int16 value; @@ -416,6 +458,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void InferType_Int32 () { Int32 value; @@ -441,6 +486,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void InferType_Int64 () { Int64 value; @@ -506,6 +554,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void InferType_Object () { Object value = new Object (); @@ -517,6 +568,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void InferType_Single () { Single value = Single.MaxValue; @@ -528,6 +582,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void InferType_String () { String value = "some text"; @@ -551,6 +608,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void LocaleId () { SqlParameter parameter = new SqlParameter (); @@ -560,6 +620,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] // bug #320196 +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ParameterNullTest () { SqlParameter param = new SqlParameter ("param", SqlDbType.Decimal); @@ -574,6 +637,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ParameterType () { SqlParameter p; @@ -632,6 +698,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void InferType_Boolean () { Boolean value; @@ -651,6 +720,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ParameterName () { SqlParameter p = new SqlParameter (); @@ -676,6 +748,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ResetDbType () { SqlParameter p; @@ -739,6 +814,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ResetSqlDbType () { //Parameter with an assigned value but no SqlDbType specified @@ -779,6 +857,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void SourceColumn () { SqlParameter p = new SqlParameter (); @@ -804,6 +885,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void SourceColumnNullMapping () { SqlParameter p = new SqlParameter (); @@ -815,6 +899,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void SqlDbTypeTest () { SqlParameter p = new SqlParameter ("zipcode", 3510); @@ -829,6 +916,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void SqlDbTypeTest_Value_Invalid () { SqlParameter p = new SqlParameter ("zipcode", 3510); @@ -847,6 +937,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void SqlValue () { SqlParameter parameter = new SqlParameter (); @@ -970,6 +1063,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void SqlTypes_SqlBinary () { SqlParameter parameter; @@ -995,6 +1091,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void SqlTypes_SqlBoolean () { SqlParameter parameter; @@ -1020,6 +1119,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void SqlTypes_SqlByte () { SqlParameter parameter; @@ -1107,6 +1209,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void SqlTypes_SqlDateTime () { SqlParameter parameter; @@ -1132,6 +1237,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void SqlTypes_SqlDecimal () { SqlParameter parameter; @@ -1157,6 +1265,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void SqlTypes_SqlDouble () { SqlParameter parameter; @@ -1182,6 +1293,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void SqlTypes_SqlGuid () { SqlParameter parameter; @@ -1207,6 +1321,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void SqlTypes_SqlInt16 () { SqlParameter parameter; @@ -1232,6 +1349,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void SqlTypes_SqlInt32 () { SqlParameter parameter; @@ -1257,6 +1377,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void SqlTypes_SqlInt64 () { SqlParameter parameter; @@ -1282,6 +1405,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void SqlTypes_SqlMoney () { SqlParameter parameter; @@ -1307,6 +1433,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void SqlTypes_SqlSingle () { SqlParameter parameter; @@ -1332,6 +1461,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void SqlTypes_SqlString () { SqlParameter parameter; @@ -1357,6 +1489,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void SqlTypes_SqlXml () { SqlParameter parameter; @@ -1386,6 +1521,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Value () { SqlParameter p; @@ -1429,6 +1567,9 @@ namespace MonoTests.System.Data.SqlClient } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void XmlSchemaTest () { SqlParameter p1 = new SqlParameter (); diff --git a/mcs/class/System.Data/Test/System.Data/ConstraintCollectionTest2.cs b/mcs/class/System.Data/Test/System.Data/ConstraintCollectionTest2.cs index 8673fc4802..66c126fd52 100644 --- a/mcs/class/System.Data/Test/System.Data/ConstraintCollectionTest2.cs +++ b/mcs/class/System.Data/Test/System.Data/ConstraintCollectionTest2.cs @@ -447,7 +447,7 @@ namespace MonoTests.System.Data { DataTable dt = DataProvider.CreateParentDataTable(); dt.Constraints.Add("UniqueConstraint",dt.Columns["ParentId"],true); - Assert.AreEqual(1,dt.Constraints.Count,1); + Assert.AreEqual(1,(double) dt.Constraints.Count,1); Assert.AreEqual("UniqueConstraint",dt.Constraints[0].ConstraintName,"CN34"); } diff --git a/mcs/class/System.Data/Test/System.Data/DataRowTest.cs b/mcs/class/System.Data/Test/System.Data/DataRowTest.cs index 5b2fd8ca9f..e8487efaf6 100644 --- a/mcs/class/System.Data/Test/System.Data/DataRowTest.cs +++ b/mcs/class/System.Data/Test/System.Data/DataRowTest.cs @@ -41,7 +41,7 @@ using System.Data; namespace MonoTests.System.Data { [TestFixture] - public class DataRowTest : Assertion { + public class DataRowTest { private DataTable table; private DataRow row; @@ -101,7 +101,7 @@ namespace MonoTests.System.Data private void GetColumnErrorTest () { // Print the error of a specified column. - AssertEquals ("#A01", "Some error!", row.GetColumnError (1)); + Assert.AreEqual ("Some error!", row.GetColumnError (1), "#A01"); } private void GetAllErrorsTest () @@ -112,7 +112,7 @@ namespace MonoTests.System.Data colArr = row.GetColumnsInError (); for (int i = 0; i < colArr.Length; i++) { - AssertEquals ("#A02", table.Columns [1], colArr [i]); + Assert.AreEqual (table.Columns [1], colArr [i], "#A02"); } row.ClearErrors (); } @@ -135,7 +135,7 @@ namespace MonoTests.System.Data int cnt = 1; for (int i = 1; i < table.Rows.Count; i++) { DataRow r = table.Rows [i]; - AssertEquals ("#A03", "Name " + cnt, r ["fName"]); + Assert.AreEqual ("Name " + cnt, r ["fName"], "#A03"); cnt++; } @@ -146,20 +146,20 @@ namespace MonoTests.System.Data rc [2].Delete (); - AssertEquals ("#A04", "Deleted", rc [0].RowState.ToString ()); - AssertEquals ("#A05", "Deleted", rc [2].RowState.ToString ()); + Assert.AreEqual ("Deleted", rc [0].RowState.ToString (), "#A04"); + Assert.AreEqual ("Deleted", rc [2].RowState.ToString (), "#A05"); // Accept changes table.AcceptChanges (); - AssertEquals ("#A06", "Name 1", (table.Rows [0]) [1]); + Assert.AreEqual ("Name 1", (table.Rows [0]) [1], "#A06"); try { object o = rc [2]; - Fail ("#A07"); + Assert.Fail ("#A07"); } catch (Exception e) { // Never premise English. - //AssertEquals ("#A08", "There is no row at position 2.", e.Message); + //Assert.AreEqual ("#A08", "There is no row at position 2.", e.Message); } } @@ -179,40 +179,40 @@ namespace MonoTests.System.Data // Stage 1 //Initially: After Add (Row) But Before Accept Changes"); - AssertEquals ("#A09", "My FName", row [1, DataRowVersion.Default]); - AssertEquals ("#A10", "LName", row [2, DataRowVersion.Default]); + Assert.AreEqual ("My FName", row [1, DataRowVersion.Default], "#A09"); + Assert.AreEqual ("LName", row [2, DataRowVersion.Default], "#A10"); - AssertEquals ("#A11", "My FName", row [1, DataRowVersion.Current]); - AssertEquals ("#A12", "LName", row [2, DataRowVersion.Current]); + Assert.AreEqual ("My FName", row [1, DataRowVersion.Current], "#A11"); + Assert.AreEqual ("LName", row [2, DataRowVersion.Current], "#A12"); try { object o = row [1, DataRowVersion.Original]; o = row [1, DataRowVersion.Proposed]; - Fail ("#A13"); + Assert.Fail ("#A13"); } catch (Exception e) { if (e.GetType () != typeof (AssertionException)) { - AssertEquals ("#A14", typeof (VersionNotFoundException), e.GetType ()); + Assert.AreEqual (typeof (VersionNotFoundException), e.GetType (), "#A14"); } } // Stage 2 //After Accept Changes table.AcceptChanges (); - AssertEquals ("#A15", "My FName", row [1, DataRowVersion.Default]); - AssertEquals ("#A16", "LName", row [2, DataRowVersion.Default]); + Assert.AreEqual ("My FName", row [1, DataRowVersion.Default], "#A15"); + Assert.AreEqual ("LName", row [2, DataRowVersion.Default], "#A16"); - AssertEquals ("#A17", "My FName", row [1, DataRowVersion.Current]); - AssertEquals ("#A18", "LName", row [2, DataRowVersion.Current]); + Assert.AreEqual ("My FName", row [1, DataRowVersion.Current], "#A17"); + Assert.AreEqual ("LName", row [2, DataRowVersion.Current], "#A18"); try { object o = row [1, DataRowVersion.Proposed]; - Fail ("#A19"); + Assert.Fail ("#A19"); } catch (Exception e) { if (e.GetType () != typeof (AssertionException)) { - AssertEquals ("#A20", typeof (VersionNotFoundException), e.GetType ()); + Assert.AreEqual (typeof (VersionNotFoundException), e.GetType (), "#A20"); } } @@ -221,63 +221,64 @@ namespace MonoTests.System.Data table.Rows [0].BeginEdit (); table.Rows [0] ["LName"] = "My LName"; - AssertEquals ("#A21", "My FName", row [1, DataRowVersion.Default]); - AssertEquals ("#A22", "My LName", row [2, DataRowVersion.Default]); + Assert.AreEqual ("My FName", row [1, DataRowVersion.Default], "#A21"); + Assert.AreEqual ("My LName", row [2, DataRowVersion.Default], "#A22"); - AssertEquals ("#A23", "My FName", row [1, DataRowVersion.Current]); - AssertEquals ("#A24", "LName", row [2, DataRowVersion.Current]); + Assert.AreEqual ("My FName", row [1, DataRowVersion.Current], "#A23"); + Assert.AreEqual ("LName", row [2, DataRowVersion.Current], "#A24"); - AssertEquals ("#A25", "My FName", row [1, DataRowVersion.Original]); AssertEquals ("#A26", "LName", row [2, DataRowVersion.Original]); + Assert.AreEqual ("My FName", row [1, DataRowVersion.Original], "#A25"); + Assert.AreEqual ("LName", row [2, DataRowVersion.Original], "#A26"); - AssertEquals ("#A26", "My FName", row [1, DataRowVersion.Proposed]); - AssertEquals ("#A27", "My LName", row [2, DataRowVersion.Proposed]); + Assert.AreEqual ("My FName", row [1, DataRowVersion.Proposed], "#A26"); + Assert.AreEqual ("My LName", row [2, DataRowVersion.Proposed], "#A27"); // Stage 4 //After Edit sessions for (int i=0; i < table.Rows.Count;i++) table.Rows [i].EndEdit (); - AssertEquals ("#A28", "My FName", row [1, DataRowVersion.Default]); - AssertEquals ("#A29", "My LName", row [2, DataRowVersion.Default]); + Assert.AreEqual ("My FName", row [1, DataRowVersion.Default], "#A28"); + Assert.AreEqual ("My LName", row [2, DataRowVersion.Default], "#A29"); - AssertEquals ("#A30", "My FName", row [1, DataRowVersion.Original]); AssertEquals ("#A31", "LName", row [2, DataRowVersion.Original]); + Assert.AreEqual ("My FName", row [1, DataRowVersion.Original], "#A30"); Assert.AreEqual ("LName", row [2, DataRowVersion.Original], "#A31"); - AssertEquals ("#A32", "My FName", row [1, DataRowVersion.Current]); - AssertEquals ("#A33", "My LName", row [2, DataRowVersion.Current]); + Assert.AreEqual ("My FName", row [1, DataRowVersion.Current], "#A32"); + Assert.AreEqual ("My LName", row [2, DataRowVersion.Current], "#A33"); try { object o = row [1, DataRowVersion.Proposed]; - Fail ("#A34"); + Assert.Fail ("#A34"); } catch (Exception e) { if (e.GetType ()!=typeof (AssertionException)) { - AssertEquals ("#A35", typeof (VersionNotFoundException), e.GetType ()); + Assert.AreEqual (typeof (VersionNotFoundException), e.GetType (), "#A35"); } } //Stage 5 //After Accept Changes table.AcceptChanges (); - AssertEquals ("#A36", "My FName", row [1, DataRowVersion.Default]); - AssertEquals ("#A37", "My LName", row [2, DataRowVersion.Default]); + Assert.AreEqual ("My FName", row [1, DataRowVersion.Default], "#A36"); + Assert.AreEqual ("My LName", row [2, DataRowVersion.Default], "#A37"); - AssertEquals ("#A38", "My FName", row [1, DataRowVersion.Original]); AssertEquals ("#A39", "My LName", row [2, DataRowVersion.Original]); + Assert.AreEqual ("My FName", row [1, DataRowVersion.Original], "#A38"); Assert.AreEqual (row [2, DataRowVersion.Original], "#A39", "My LName"); - AssertEquals ("#A40", "My FName", row [1, DataRowVersion.Current]); - AssertEquals ("#A41", "My LName", row [2, DataRowVersion.Current]); + Assert.AreEqual ("My FName", row [1, DataRowVersion.Current], "#A40"); + Assert.AreEqual ("My LName", row [2, DataRowVersion.Current], "#A41"); try { object o = row [1, DataRowVersion.Proposed]; - Fail ("#A42"); + Assert.Fail ("#A42"); } catch (Exception e) { if (e.GetType () != typeof (AssertionException)) { - AssertEquals ("#A43", typeof (VersionNotFoundException), - e.GetType ()); + Assert.AreEqual (typeof (VersionNotFoundException), e.GetType (), + "#A43"); } } @@ -328,22 +329,22 @@ namespace MonoTests.System.Data rowC.SetParentRow (table.Rows [0], dr); - AssertEquals ("#PRT-01", table.Rows [0], (tableC.Rows [0]).GetParentRow (dr)); - AssertEquals ("#PRT-02", tableC.Rows [0], (table.Rows [0]).GetChildRows (dr) [0]); + Assert.AreEqual (table.Rows [0], (tableC.Rows [0]).GetParentRow (dr), "#PRT-01"); + Assert.AreEqual (tableC.Rows [0], (table.Rows [0]).GetChildRows (dr) [0], "#PRT-02"); ds.Relations.Clear (); dr = new DataRelation ("PO", table.Columns ["Id"], tableC.Columns ["Id"], false); ds.Relations.Add (dr); rowC.SetParentRow (table.Rows [0], dr); - AssertEquals ("#PRT-03", table.Rows [0], (tableC.Rows [0]).GetParentRow (dr)); - AssertEquals ("#PRT-04", tableC.Rows [0], (table.Rows [0]).GetChildRows (dr) [0]); + Assert.AreEqual (table.Rows [0], (tableC.Rows [0]).GetParentRow (dr), "#PRT-03"); + Assert.AreEqual (tableC.Rows [0], (table.Rows [0]).GetChildRows (dr) [0], "#PRT-04"); ds.Relations.Clear (); dr = new DataRelation ("PO", table.Columns ["Id"], tableC.Columns ["Id"], false); tableC.ParentRelations.Add (dr); rowC.SetParentRow (table.Rows [0]); - AssertEquals ("#PRT-05", table.Rows [0], (tableC.Rows [0]).GetParentRow (dr)); - AssertEquals ("#PRT-06", tableC.Rows [0], (table.Rows [0]).GetChildRows (dr) [0]); + Assert.AreEqual (table.Rows [0], (tableC.Rows [0]).GetParentRow (dr), "#PRT-05"); + Assert.AreEqual (tableC.Rows [0], (table.Rows [0]).GetChildRows (dr) [0], "#PRT-06"); } @@ -377,8 +378,8 @@ namespace MonoTests.System.Data rowC.SetParentRow (row, dr); DataRow [] rows = rowC.GetParentRows (dr); - AssertEquals ("#A49", 1, rows.Length); - AssertEquals ("#A50", tableP.Rows [0], rows [0]); + Assert.AreEqual (1, rows.Length, "#A49"); + Assert.AreEqual (tableP.Rows [0], rows [0], "#A50"); try{ rows = row.GetParentRows (dr); @@ -386,10 +387,10 @@ namespace MonoTests.System.Data //Test done return ; }catch(Exception e){ - Fail("#A51, InvalidConstraintException expected, got : " + e); + Assert.Fail("#A51, InvalidConstraintException expected, got : " + e); } - Fail("#A52, InvalidConstraintException expected but got none."); + Assert.Fail("#A52, InvalidConstraintException expected but got none."); } [Test] @@ -434,8 +435,8 @@ namespace MonoTests.System.Data DataRow [] rows = (table.Rows [0]).GetChildRows (dr); - AssertEquals ("#A45", 1, rows.Length); - AssertEquals ("#A46", tableC.Rows [0], rows [0]); + Assert.AreEqual (1, rows.Length, "#A45"); + Assert.AreEqual (tableC.Rows [0], rows [0], "#A46"); } @@ -469,8 +470,8 @@ namespace MonoTests.System.Data rowC.SetParentRow (row, dr); DataRow [] rows = row.GetChildRows (dr); - AssertEquals ("#A47", 1, rows.Length); - AssertEquals ("#A48", tableC.Rows [0], rows [0]); + Assert.AreEqual (1, rows.Length, "#A47"); + Assert.AreEqual (tableC.Rows [0], rows [0], "#A48"); try{ rows = rowC.GetChildRows (dr); @@ -478,10 +479,10 @@ namespace MonoTests.System.Data //Test done return ; }catch(Exception e){ - Fail("#A53, InvalidConstraintException expected, got : " + e); + Assert.Fail("#A53, InvalidConstraintException expected, got : " + e); } - Fail("#A54, InvalidConstraintException expected but got none."); + Assert.Fail("#A54, InvalidConstraintException expected but got none."); } [Category ("NotWorking")] //Mismatch in Exception namespace/class reference @@ -528,35 +529,35 @@ namespace MonoTests.System.Data //Test Done return ; }catch (Exception e){ - Fail ("#A55, VersionNotFoundException expected, got : " + e); + Assert.Fail ("#A55, VersionNotFoundException expected, got : " + e); } - Fail ("#A56, VersionNotFoundException expected but got none."); + Assert.Fail ("#A56, VersionNotFoundException expected but got none."); }catch (Exception e){ - Fail ("#A57, VersionNotFoundException expected, got : " + e); + Assert.Fail ("#A57, VersionNotFoundException expected, got : " + e); } - Fail("#A58, VersionNotFoundException expected but got none."); + Assert.Fail("#A58, VersionNotFoundException expected but got none."); } // tests item at row, column in table to be DBNull.Value private void DBNullTest (string message, DataTable dt, int row, int column) { object val = dt.Rows[row].ItemArray[column]; - AssertEquals(message, DBNull.Value, val); + Assert.AreEqual(DBNull.Value, val, message); } // tests item at row, column in table to be null private void NullTest (string message, DataTable dt, int row, int column) { object val = dt.Rows[row].ItemArray[column]; - AssertEquals(message, null, val); + Assert.AreEqual(null, val, message); } // tests item at row, column in table to be private void ValueTest (string message, DataTable dt, int row, int column, object value) { object val = dt.Rows[row].ItemArray[column]; - AssertEquals(message, value, val); + Assert.AreEqual(value, val, message); } // test set null, DBNull.Value, and ItemArray short count @@ -588,7 +589,7 @@ namespace MonoTests.System.Data row.ItemArray = obj; } catch(Exception e1) { - Fail("DR1: Exception Caught: " + e1); + Assert.Fail("DR1: Exception Caught: " + e1); } table.Rows.Add(row); @@ -606,7 +607,7 @@ namespace MonoTests.System.Data row.ItemArray = obj; } catch(Exception e2) { - Fail("DR2: Exception Caught: " + e2); + Assert.Fail("DR2: Exception Caught: " + e2); } table.Rows.Add(row); @@ -624,7 +625,7 @@ namespace MonoTests.System.Data row.ItemArray = obj; } catch(Exception e3) { - Fail("DR3: Exception Caught: " + e3); + Assert.Fail("DR3: Exception Caught: " + e3); } table.Rows.Add(row); @@ -646,7 +647,7 @@ namespace MonoTests.System.Data row.ItemArray = obj; } catch(Exception e3) { - Fail("DR4: Exception Caught: " + e3); + Assert.Fail("DR4: Exception Caught: " + e3); } table.Rows.Add(row); @@ -698,7 +699,7 @@ namespace MonoTests.System.Data row.ItemArray = obj; } catch(Exception e1) { - Fail("DR17: Exception Caught: " + e1); + Assert.Fail("DR17: Exception Caught: " + e1); } table.Rows.Add(row); @@ -715,7 +716,7 @@ namespace MonoTests.System.Data row.ItemArray = obj; } catch(Exception e2) { - Fail("DR18: Exception Caught: " + e2); + Assert.Fail("DR18: Exception Caught: " + e2); } table.Rows.Add(row); @@ -733,7 +734,7 @@ namespace MonoTests.System.Data row.ItemArray = obj; } catch(Exception e3) { - Fail("DR19: Exception Caught: " + e3); + Assert.Fail("DR19: Exception Caught: " + e3); } table.Rows.Add(row); @@ -753,7 +754,7 @@ namespace MonoTests.System.Data row.ItemArray = obj; } catch(Exception e3) { - Fail("DR20: Exception Caught: " + e3); + Assert.Fail("DR20: Exception Caught: " + e3); } table.Rows.Add(row); @@ -802,7 +803,7 @@ namespace MonoTests.System.Data row.ItemArray = obj; } catch(Exception e1) { - Fail("DR28: Exception Caught: " + e1); + Assert.Fail("DR28: Exception Caught: " + e1); } table.Rows.Add(row); @@ -819,7 +820,7 @@ namespace MonoTests.System.Data row.ItemArray = obj; } catch(Exception e2) { - Fail("DR29: Exception Caught: " + e2); + Assert.Fail("DR29: Exception Caught: " + e2); } table.Rows.Add(row); @@ -836,7 +837,7 @@ namespace MonoTests.System.Data row.ItemArray = obj; } catch(Exception e2) { - Fail("DR30: Exception Caught: " + e2); + Assert.Fail("DR30: Exception Caught: " + e2); } table.Rows.Add(row); @@ -853,7 +854,7 @@ namespace MonoTests.System.Data row.ItemArray = obj; } catch(Exception e2) { - Fail("DR31: Exception Caught: " + e2); + Assert.Fail("DR31: Exception Caught: " + e2); } table.Rows.Add(row); @@ -872,7 +873,7 @@ namespace MonoTests.System.Data row.ItemArray = obj; } catch(Exception e3) { - Fail("DR32: Exception Caught: " + e3); + Assert.Fail("DR32: Exception Caught: " + e3); } table.Rows.Add(row); @@ -889,7 +890,7 @@ namespace MonoTests.System.Data row.ItemArray = obj; } catch(Exception e2) { - Fail("DR48: Exception Caught: " + e2); + Assert.Fail("DR48: Exception Caught: " + e2); } table.Rows.Add(row); @@ -909,7 +910,7 @@ namespace MonoTests.System.Data row.ItemArray = obj; } catch(Exception e3) { - Fail("DR33: Exception Caught: " + e3); + Assert.Fail("DR33: Exception Caught: " + e3); } table.Rows.Add(row); @@ -986,7 +987,7 @@ namespace MonoTests.System.Data DataRow childRow = child.Rows.Add(new object[] { id }); if (parentRow == childRow.GetParentRow(relateParentChild)) { foreach(DataColumn dc in parent.Columns) - AssertEquals(100,parentRow[dc]); + Assert.AreEqual(100,parentRow[dc]); } @@ -1002,9 +1003,9 @@ namespace MonoTests.System.Data dt.Rows.Add ((new object [] {"val"})); DataRow dr = dt.NewRow (); - AssertEquals (DataRowState.Detached, dr.RowState); + Assert.AreEqual (DataRowState.Detached, dr.RowState); dr.CancelEdit (); - AssertEquals (DataRowState.Detached, dr.RowState); + Assert.AreEqual (DataRowState.Detached, dr.RowState); object o = dr ["col"]; } @@ -1056,20 +1057,20 @@ namespace MonoTests.System.Data parent2.Rows.Add(parent2Row); childRow1.SetParentRow(parent1Row); - AssertEquals ("p1c1", childRow1[childColumn1]); - AssertEquals (DBNull.Value, childRow1[childColumn2]); + Assert.AreEqual ("p1c1", childRow1[childColumn1]); + Assert.AreEqual (DBNull.Value, childRow1[childColumn2]); childRow1.SetParentRow(parent2Row); - AssertEquals ("p1c1", childRow1[childColumn1]); - AssertEquals ("p2c2", childRow1[childColumn2]); + Assert.AreEqual ("p1c1", childRow1[childColumn1]); + Assert.AreEqual ("p2c2", childRow1[childColumn2]); childRow1.SetParentRow(null); - AssertEquals (DBNull.Value, childRow1[childColumn1]); - AssertEquals (DBNull.Value, childRow1[childColumn2]); + Assert.AreEqual (DBNull.Value, childRow1[childColumn1]); + Assert.AreEqual (DBNull.Value, childRow1[childColumn2]); childRow1.SetParentRow(parent2Row); - AssertEquals (DBNull.Value, childRow1[childColumn1]); - AssertEquals ("p2c2", childRow1[childColumn2]); + Assert.AreEqual (DBNull.Value, childRow1[childColumn1]); + Assert.AreEqual ("p2c2", childRow1[childColumn2]); } [Test] @@ -1108,29 +1109,29 @@ namespace MonoTests.System.Data childRow1.SetParentRow (null, relation2); - AssertEquals (DBNull.Value, childRow1[childColumn1]); - AssertEquals (DBNull.Value, childRow1[childColumn2]); + Assert.AreEqual (DBNull.Value, childRow1[childColumn1]); + Assert.AreEqual (DBNull.Value, childRow1[childColumn2]); try { childRow1.SetParentRow(parent1Row, relation2); - Fail ("Must throw InvalidConstaintException"); + Assert.Fail ("Must throw InvalidConstaintException"); } catch (InvalidConstraintException e) { } - AssertEquals (DBNull.Value, childRow1[childColumn1]); - AssertEquals (DBNull.Value, childRow1[childColumn2]); + Assert.AreEqual (DBNull.Value, childRow1[childColumn1]); + Assert.AreEqual (DBNull.Value, childRow1[childColumn2]); childRow1.SetParentRow(parent1Row, relation1); - AssertEquals ("p1c1", childRow1[childColumn1]); - AssertEquals (DBNull.Value, childRow1[childColumn2]); + Assert.AreEqual ("p1c1", childRow1[childColumn1]); + Assert.AreEqual (DBNull.Value, childRow1[childColumn2]); childRow1.SetParentRow (null, relation2); - AssertEquals ("p1c1", childRow1[childColumn1]); - AssertEquals (DBNull.Value, childRow1[childColumn2]); + Assert.AreEqual ("p1c1", childRow1[childColumn1]); + Assert.AreEqual (DBNull.Value, childRow1[childColumn2]); childRow1.SetParentRow (null, relation1); - AssertEquals (DBNull.Value, childRow1[childColumn1]); - AssertEquals (DBNull.Value, childRow1[childColumn2]); + Assert.AreEqual (DBNull.Value, childRow1[childColumn1]); + Assert.AreEqual (DBNull.Value, childRow1[childColumn2]); } [Test] @@ -1161,8 +1162,8 @@ namespace MonoTests.System.Data parent2.Rows.Add(parentRow); childRow.SetParentRow(parentRow); - AssertEquals (DBNull.Value, childRow[childColumn1]); - AssertEquals ("value", childRow[childColumn2]); + Assert.AreEqual (DBNull.Value, childRow[childColumn1]); + Assert.AreEqual ("value", childRow[childColumn2]); } } diff --git a/mcs/class/System.Data/Test/System.Data/DataRowViewTest.cs b/mcs/class/System.Data/Test/System.Data/DataRowViewTest.cs index 51885f37bc..60dbb9d393 100644 --- a/mcs/class/System.Data/Test/System.Data/DataRowViewTest.cs +++ b/mcs/class/System.Data/Test/System.Data/DataRowViewTest.cs @@ -36,7 +36,7 @@ using System.ComponentModel; namespace MonoTests.System.Data { [TestFixture] - public class DataRowViewTest : Assertion + public class DataRowViewTest { private DataView CreateTestView () { @@ -96,8 +96,8 @@ namespace MonoTests.System.Data DataView dv = new DataView (dt1); DataRowView dvr = dv [0]; DataView v = dvr.CreateChildView (dr); - AssertEquals ("RowFilter", "", v.RowFilter); - AssertEquals ("Sort", "", v.Sort); + Assert.AreEqual ("", v.RowFilter, "RowFilter"); + Assert.AreEqual ("", v.Sort, "Sort"); } [Test] @@ -110,12 +110,12 @@ namespace MonoTests.System.Data DataView dv = new DataView (dt); DataRowView drv = dv [0]; dt.Rows [0].BeginEdit (); - AssertEquals ("DataView.Item", true, drv.IsEdit); + Assert.AreEqual (true, drv.IsEdit, "DataView.Item"); drv = dv.AddNew (); drv.Row ["col"] = "test"; drv.Row.CancelEdit (); - AssertEquals ("AddNew", false, drv.IsEdit); + Assert.AreEqual (false, drv.IsEdit, "AddNew"); } [Test] @@ -127,7 +127,7 @@ namespace MonoTests.System.Data DataView dv = new DataView (dt); DataRowView drv = dv [0]; dt.Rows [0].BeginEdit (); - AssertEquals ("DataView.Item", "val", drv ["col"]); + Assert.AreEqual ("val", drv ["col"], "DataView.Item"); } [Test] @@ -153,18 +153,18 @@ namespace MonoTests.System.Data dt.Rows.Add (new object [] {1}); DataView dv = new DataView (dt); DataRowView drv = dv.AddNew (); - AssertEquals (DataRowVersion.Current, drv.RowVersion); - AssertEquals (DataRowVersion.Current, dv [0].RowVersion); + Assert.AreEqual (DataRowVersion.Current, drv.RowVersion); + Assert.AreEqual (DataRowVersion.Current, dv [0].RowVersion); drv ["col"] = "mod"; - AssertEquals (DataRowVersion.Current, drv.RowVersion); - AssertEquals (DataRowVersion.Current, dv [0].RowVersion); + Assert.AreEqual (DataRowVersion.Current, drv.RowVersion); + Assert.AreEqual (DataRowVersion.Current, dv [0].RowVersion); dt.AcceptChanges (); - AssertEquals (DataRowVersion.Current, drv.RowVersion); - AssertEquals (DataRowVersion.Current, dv [0].RowVersion); + Assert.AreEqual (DataRowVersion.Current, drv.RowVersion); + Assert.AreEqual (DataRowVersion.Current, dv [0].RowVersion); drv.EndEdit (); dv [0].EndEdit (); - AssertEquals (DataRowVersion.Current, drv.RowVersion); - AssertEquals (DataRowVersion.Current, dv [0].RowVersion); + Assert.AreEqual (DataRowVersion.Current, drv.RowVersion); + Assert.AreEqual (DataRowVersion.Current, dv [0].RowVersion); } } } diff --git a/mcs/class/System.Data/Test/System.Data/DataTableCollectionTest.cs b/mcs/class/System.Data/Test/System.Data/DataTableCollectionTest.cs index 05d0eddc7f..bf34b01d1c 100644 --- a/mcs/class/System.Data/Test/System.Data/DataTableCollectionTest.cs +++ b/mcs/class/System.Data/Test/System.Data/DataTableCollectionTest.cs @@ -37,7 +37,7 @@ namespace MonoTests.System.Data { [TestFixture] - public class DataTableCollectionTest : Assertion { + public class DataTableCollectionTest { // common variables here private DataSet [] _dataset; private DataTable [] _tables; @@ -76,11 +76,11 @@ namespace MonoTests.System.Data foreach( DataTable table in tbcol ) { - AssertEquals("test#1",_tables[i].TableName,table.TableName); + Assert.AreEqual(_tables[i].TableName,table.TableName,"test#1"); j=0; foreach( DataColumn column in table.Columns ) { - AssertEquals("test#2",_tables[i].Columns[j].ColumnName,column.ColumnName); + Assert.AreEqual(_tables[i].Columns[j].ColumnName,column.ColumnName,"test#2"); j++; } i++; @@ -90,11 +90,11 @@ namespace MonoTests.System.Data i=0; foreach( DataTable table in tbcol ) { - AssertEquals("test#3",_tables[i].TableName,table.TableName); + Assert.AreEqual(_tables[i].TableName,table.TableName,"test#3"); j=0; foreach( DataColumn column in table.Columns ) { - AssertEquals("test#4",_tables[i].Columns[j].ColumnName,column.ColumnName); + Assert.AreEqual(_tables[i].Columns[j].ColumnName,column.ColumnName,"test#4"); j++; } i++; @@ -143,9 +143,9 @@ namespace MonoTests.System.Data { DataTableCollection tbcol = _dataset[0].Tables; tbcol.Add(_tables[0]); - AssertEquals("test#1",1, tbcol.Count); + Assert.AreEqual(1,tbcol.Count, "test#1"); tbcol.Add(_tables[1]); - AssertEquals("test#2",2, tbcol.Count); + Assert.AreEqual(2,tbcol.Count, "test#2"); } [Test] @@ -159,11 +159,11 @@ namespace MonoTests.System.Data i=0; foreach( DataTable table in tbcol ) { - AssertEquals("test#1",_tables[i].TableName,table.TableName); + Assert.AreEqual(_tables[i].TableName,table.TableName,"test#1"); j=0; foreach( DataColumn column in table.Columns ) { - AssertEquals("test#2",_tables[i].Columns[j].ColumnName,column.ColumnName); + Assert.AreEqual(_tables[i].Columns[j].ColumnName,column.ColumnName,"test#2"); j++; } i++; @@ -179,11 +179,11 @@ namespace MonoTests.System.Data tbcol.AddRange(_tables); DataTable tbl = null; /* checking for a recently input table, expecting true */ - AssertEquals("test#1",true,tbcol.CanRemove(_tables[0])); + Assert.AreEqual(true,tbcol.CanRemove(_tables[0]),"test#1"); /* trying to check with a null reference, expecting false */ - AssertEquals("test#2",false,tbcol.CanRemove(tbl)); + Assert.AreEqual(false,tbcol.CanRemove(tbl),"test#2"); /* trying to check with a table that does not exist in collection, expecting false */ - AssertEquals("test#3",false,tbcol.CanRemove(new DataTable("newTable"))); + Assert.AreEqual(false,tbcol.CanRemove(new DataTable("newTable")),"test#3"); } [Test] @@ -197,27 +197,27 @@ namespace MonoTests.System.Data /* removing a recently added table */ int count = tbcol.Count; tbcol.Remove(_tables[0]); - AssertEquals("test#1",count-1,tbcol.Count); + Assert.AreEqual(count-1,tbcol.Count,"test#1"); DataTable tbl = null; /* removing a null reference. must generate an Exception */ try { tbcol.Remove(tbl); - Fail("Err:: tbcol.Rmove(null) must fail"); + Assert.Fail("Err:: tbcol.Rmove(null) must fail"); } catch(Exception e) { - AssertEquals ("test#2", typeof (ArgumentNullException), e.GetType()); + Assert.AreEqual (typeof (ArgumentNullException), e.GetType(), "test#2"); } /* removing a table that is not there in collection */ try { tbcol.Remove(new DataTable("newTable")); - Fail("Err:: cannot remove a table that is not there in collection"); + Assert.Fail("Err:: cannot remove a table that is not there in collection"); } catch(Exception e) { - AssertEquals ("test#3", typeof (ArgumentException), e.GetType()); + Assert.AreEqual (typeof (ArgumentException), e.GetType(), "test#3"); } } @@ -227,11 +227,11 @@ namespace MonoTests.System.Data DataTableCollection tbcol = _dataset[0].Tables; tbcol.Add(_tables[0]); tbcol.Clear(); - AssertEquals("Test#1",0,tbcol.Count); + Assert.AreEqual(0,tbcol.Count,"Test#1"); tbcol.AddRange(new DataTable[] {_tables[0],_tables[1]}); tbcol.Clear(); - AssertEquals("Test#2",0,tbcol.Count); + Assert.AreEqual(0,tbcol.Count,"Test#2"); } [Test] public void Contains() @@ -242,11 +242,11 @@ namespace MonoTests.System.Data tbcol.AddRange(_tables); string tblname = ""; /* checking for a recently input table, expecting true */ - AssertEquals("test#1",true,tbcol.Contains(_tables[0].TableName)); + Assert.AreEqual(true,tbcol.Contains(_tables[0].TableName),"test#1"); /* trying to check with a empty string, expecting false */ - AssertEquals("test#2",false,tbcol.Contains(tblname)); + Assert.AreEqual(false,tbcol.Contains(tblname),"test#2"); /* trying to check for a table that donot exist, expecting false */ - AssertEquals("test#3",false,tbcol.Contains("InvalidTableName")); + Assert.AreEqual(false,tbcol.Contains("InvalidTableName"),"test#3"); } [Test] @@ -261,21 +261,21 @@ namespace MonoTests.System.Data DataTable [] array = new DataTable[4]; /* copying to the beginning of the array */ tbcol.CopyTo(array,0); - AssertEquals ("test#01", 4, array.Length); - AssertEquals ("test#02", "Table1", array[0].TableName); - AssertEquals ("test#03", "Table2", array[1].TableName); - AssertEquals ("test#04", "Table3", array[2].TableName); - AssertEquals ("test#05", "Table4", array[3].TableName); + Assert.AreEqual (4, array.Length, "test#01"); + Assert.AreEqual ("Table1", array[0].TableName, "test#02"); + Assert.AreEqual ("Table2", array[1].TableName, "test#03"); + Assert.AreEqual ("Table3", array[2].TableName, "test#04"); + Assert.AreEqual ("Table4", array[3].TableName, "test#05"); /* copying with in a array */ DataTable [] array1 = new DataTable[6]; tbcol.CopyTo(array1,2); - AssertEquals("test#06",null,array1[0]); - AssertEquals("test#07",null,array1[1]); - AssertEquals("test#08","Table1",array1[2].TableName); - AssertEquals("test#09","Table2",array1[3].TableName); - AssertEquals("test#10","Table3",array1[4].TableName); - AssertEquals("test#11","Table4",array1[5].TableName); + Assert.AreEqual(null,array1[0],"test#06"); + Assert.AreEqual(null,array1[1],"test#07"); + Assert.AreEqual("Table1",array1[2].TableName,"test#08"); + Assert.AreEqual("Table2",array1[3].TableName,"test#09"); + Assert.AreEqual("Table3",array1[4].TableName,"test#10"); + Assert.AreEqual("Table4",array1[5].TableName,"test#11"); } [Test] public void Equals() @@ -287,16 +287,16 @@ namespace MonoTests.System.Data tbcol2.Add(_tables[1]); tbcol3 = tbcol1; - AssertEquals("test#1",true,tbcol1.Equals(tbcol1)); - AssertEquals("test#2",true,tbcol1.Equals(tbcol3)); - AssertEquals("test#3",true,tbcol3.Equals(tbcol1)); + Assert.AreEqual(true,tbcol1.Equals(tbcol1),"test#1"); + Assert.AreEqual(true,tbcol1.Equals(tbcol3),"test#2"); + Assert.AreEqual(true,tbcol3.Equals(tbcol1),"test#3"); - AssertEquals("test#4",false,tbcol1.Equals(tbcol2)); - AssertEquals("test#5",false,tbcol2.Equals(tbcol1)); + Assert.AreEqual(false,tbcol1.Equals(tbcol2),"test#4"); + Assert.AreEqual(false,tbcol2.Equals(tbcol1),"test#5"); - AssertEquals("test#6",true,Object.Equals(tbcol1,tbcol3)); - AssertEquals("test#7",true,Object.Equals(tbcol1,tbcol1)); - AssertEquals("test#8",false,Object.Equals(tbcol1,tbcol2)); + Assert.AreEqual(true,Object.Equals(tbcol1,tbcol3),"test#6"); + Assert.AreEqual(true,Object.Equals(tbcol1,tbcol1),"test#7"); + Assert.AreEqual(false,Object.Equals(tbcol1,tbcol2),"test#8"); } [Test] public void IndexOf() @@ -306,16 +306,16 @@ namespace MonoTests.System.Data tbcol.Add("table1"); tbcol.Add("table2"); - AssertEquals("test#1",0,tbcol.IndexOf(_tables[0])); - AssertEquals("test#2",-1,tbcol.IndexOf(_tables[1])); - AssertEquals("test#3",1,tbcol.IndexOf("table1")); - AssertEquals("test#4",2,tbcol.IndexOf("table2")); + Assert.AreEqual(0,tbcol.IndexOf(_tables[0]),"test#1"); + Assert.AreEqual(-1,tbcol.IndexOf(_tables[1]),"test#2"); + Assert.AreEqual(1,tbcol.IndexOf("table1"),"test#3"); + Assert.AreEqual(2,tbcol.IndexOf("table2"),"test#4"); - AssertEquals("test#5",0,tbcol.IndexOf(tbcol[0])); - AssertEquals("test#6",1,tbcol.IndexOf(tbcol[1])); - AssertEquals("test#7",-1,tbcol.IndexOf("_noTable_")); + Assert.AreEqual(0,tbcol.IndexOf(tbcol[0]),"test#5"); + Assert.AreEqual(1,tbcol.IndexOf(tbcol[1]),"test#6"); + Assert.AreEqual(-1,tbcol.IndexOf("_noTable_"),"test#7"); DataTable tb = new DataTable("new_table"); - AssertEquals("test#8",-1,tbcol.IndexOf(tb)); + Assert.AreEqual(-1,tbcol.IndexOf(tb),"test#8"); } [Test] @@ -328,7 +328,7 @@ namespace MonoTests.System.Data try { tbcol.RemoveAt(-1); - Fail("the index was out of bound: must have failed"); + Assert.Fail("the index was out of bound: must have failed"); } catch(IndexOutOfRangeException e) { @@ -336,15 +336,15 @@ namespace MonoTests.System.Data try { tbcol.RemoveAt(101); - Fail("the index was out of bound: must have failed"); + Assert.Fail("the index was out of bound: must have failed"); } catch(IndexOutOfRangeException e) { } tbcol.RemoveAt (1); - AssertEquals ("test#5", 1, tbcol.Count); + Assert.AreEqual (1, tbcol.Count, "test#5"); tbcol.RemoveAt (0); - AssertEquals ("test#6", 0, tbcol.Count); + Assert.AreEqual (0, tbcol.Count, "test#6"); } [Test] @@ -354,46 +354,46 @@ namespace MonoTests.System.Data tbcol.Add("Table1"); tbcol.Add("Table2"); tbcol.Add("Table3"); - AssertEquals("test#1","System.Data.DataTableCollection",tbcol.ToString()); + Assert.AreEqual("System.Data.DataTableCollection",tbcol.ToString(),"test#1"); } [Test] public void TableDataSetNamespaces () { DataTable dt = new DataTable ("dt1"); - AssertEquals ("#1-1", String.Empty, dt.Namespace); - AssertNull ("#1-2", dt.DataSet); + Assert.AreEqual (String.Empty, dt.Namespace, "#1-1"); + Assert.IsNull (dt.DataSet, "#1-2"); DataSet ds1 = new DataSet ("ds1"); ds1.Tables.Add (dt); - AssertEquals ("#2-1", String.Empty, dt.Namespace); - AssertEquals ("#2-2", ds1, dt.DataSet); + Assert.AreEqual (String.Empty, dt.Namespace, "#2-1"); + Assert.AreEqual (ds1, dt.DataSet, "#2-2"); ds1.Namespace = "ns1"; - AssertEquals ("#3", "ns1", dt.Namespace); + Assert.AreEqual ("ns1", dt.Namespace, "#3"); // back to null again ds1.Tables.Remove (dt); - AssertEquals ("#4-1", String.Empty, dt.Namespace); - AssertNull ("#4-2", dt.DataSet); + Assert.AreEqual (String.Empty, dt.Namespace, "#4-1"); + Assert.IsNull (dt.DataSet, "#4-2"); // This table is being added to _already namespaced_ // dataset. dt = new DataTable ("dt2"); ds1.Tables.Add (dt); - AssertEquals ("#5-1", "ns1", dt.Namespace); - AssertEquals ("#5-2", ds1, dt.DataSet); + Assert.AreEqual ("ns1", dt.Namespace, "#5-1"); + Assert.AreEqual (ds1, dt.DataSet, "#5-2"); ds1.Tables.Remove (dt); - AssertEquals ("#6-1", String.Empty, dt.Namespace); - AssertNull ("#6-2", dt.DataSet); + Assert.AreEqual (String.Empty, dt.Namespace, "#6-1"); + Assert.IsNull (dt.DataSet, "#6-2"); DataSet ds2 = new DataSet ("ds2"); ds2.Namespace = "ns2"; ds2.Tables.Add (dt); - AssertEquals ("#7-1", "ns2", dt.Namespace); - AssertEquals ("#7-2", ds2, dt.DataSet); + Assert.AreEqual ("ns2", dt.Namespace, "#7-1"); + Assert.AreEqual (ds2, dt.DataSet, "#7-2"); } } } diff --git a/mcs/class/System.Data/Test/System.Data/DataTableTest.cs.REMOVED.git-id b/mcs/class/System.Data/Test/System.Data/DataTableTest.cs.REMOVED.git-id index b25622b6d2..2c01f3d76b 100644 --- a/mcs/class/System.Data/Test/System.Data/DataTableTest.cs.REMOVED.git-id +++ b/mcs/class/System.Data/Test/System.Data/DataTableTest.cs.REMOVED.git-id @@ -1 +1 @@ -a44a225534eee1f385f9f5b2ef5e9f5b07097656 \ No newline at end of file +388f547212ad45907957b767ab265f33591a724b \ No newline at end of file diff --git a/mcs/class/System.Data/Test/System.Data/DataViewManagerTest.cs b/mcs/class/System.Data/Test/System.Data/DataViewManagerTest.cs index 57b5eb3084..392f9b0d4f 100644 --- a/mcs/class/System.Data/Test/System.Data/DataViewManagerTest.cs +++ b/mcs/class/System.Data/Test/System.Data/DataViewManagerTest.cs @@ -36,7 +36,7 @@ using System.ComponentModel; namespace MonoTests.System.Data { [TestFixture] - public class DataViewManagerTest : Assertion + public class DataViewManagerTest { [Test] public void Ctor () @@ -46,40 +46,40 @@ namespace MonoTests.System.Data string deleted = @""; DataViewManager m = new DataViewManager (null); - AssertNull (m.DataSet); - AssertEquals ("", m.DataViewSettingCollectionString); - AssertNotNull (m.DataViewSettings); + Assert.IsNull (m.DataSet); + Assert.AreEqual ("", m.DataViewSettingCollectionString); + Assert.IsNotNull (m.DataViewSettings); DataSet ds = new DataSet ("ds"); m.DataSet = ds; - AssertEquals ("default#1", defaultString, - m.DataViewSettingCollectionString); + Assert.AreEqual (defaultString, m.DataViewSettingCollectionString, + "default#1"); DataSet ds2 = new DataSet ("ds2"); - AssertEquals ("default#2", defaultString, - ds.DefaultViewManager.DataViewSettingCollectionString); + Assert.AreEqual (defaultString, ds.DefaultViewManager.DataViewSettingCollectionString, + "default#2"); DataTable dt2_1 = new DataTable ("table2-1"); dt2_1.Namespace ="urn:foo"; // It is ignored though. ds2.Tables.Add (dt2_1); m.DataSet = ds2; - AssertEquals ("#3", current, m.DataViewSettingCollectionString); + Assert.AreEqual (current, m.DataViewSettingCollectionString, "#3"); // Note that " Deleted " is trimmed. m.DataViewSettingCollectionString = @""; - AssertEquals ("#4", deleted, m.DataViewSettingCollectionString); + Assert.AreEqual (deleted, m.DataViewSettingCollectionString, "#4"); m.DataSet = ds2; //resets modified string. - AssertEquals ("#5", current, m.DataViewSettingCollectionString); + Assert.AreEqual (current, m.DataViewSettingCollectionString, "#5"); m.DataViewSettingCollectionString = @""; // it does not clear anything. m.DataViewSettingCollectionString = ""; - AssertEquals ("#6", deleted, m.DataViewSettingCollectionString); + Assert.AreEqual (deleted, m.DataViewSettingCollectionString, "#6"); // text node is not rejected (ignored). // RowFilter is not examined. m.DataViewSettingCollectionString = "blah"; // LAMESPEC: MS.NET ignores ApplyDefaultSort. -// AssertEquals ("#7", @"", m.DataViewSettingCollectionString); +// Assert.AreEqual (@"", m.DataViewSettingCollectionString, "#7"); } [Test] diff --git a/mcs/class/System.Data/Test/System.Data/DataViewTest.cs b/mcs/class/System.Data/Test/System.Data/DataViewTest.cs index 4be1824f66..8829819a45 100644 --- a/mcs/class/System.Data/Test/System.Data/DataViewTest.cs +++ b/mcs/class/System.Data/Test/System.Data/DataViewTest.cs @@ -42,7 +42,7 @@ using System.IO; namespace MonoTests.System.Data { [TestFixture] - public class DataViewTest : Assertion + public class DataViewTest { DataTable dataTable; DataView dataView; @@ -145,7 +145,7 @@ namespace MonoTests.System.Data dv.Sort = "abc"; dv.Sort = string.Empty; dv.Sort = "abc"; - AssertEquals ("test#01", "abc", dv.Sort); + Assert.AreEqual ("abc", dv.Sort, "test#01"); } [Test] @@ -154,24 +154,24 @@ namespace MonoTests.System.Data DataView dv1,dv2,dv3; dv1 = new DataView (); // AssertEquals ("test#01",null,dv1.Table); - AssertEquals ("test#02",true,dv1.AllowNew); - AssertEquals ("test#03",true,dv1.AllowEdit); - AssertEquals ("test#04",true,dv1.AllowDelete); - AssertEquals ("test#05",false,dv1.ApplyDefaultSort); - AssertEquals ("test#06",string.Empty,dv1.RowFilter); - AssertEquals ("test#07",DataViewRowState.CurrentRows,dv1.RowStateFilter); - AssertEquals ("test#08",string.Empty,dv1.Sort); + Assert.AreEqual (true,dv1.AllowNew,"test#02");; + Assert.AreEqual (true,dv1.AllowEdit,"test#03");; + Assert.AreEqual (true,dv1.AllowDelete,"test#04");; + Assert.AreEqual (false,dv1.ApplyDefaultSort,"test#05");; + Assert.AreEqual (string.Empty,dv1.RowFilter,"test#06");; + Assert.AreEqual (DataViewRowState.CurrentRows,dv1.RowStateFilter,"test#07");; + Assert.AreEqual (string.Empty,dv1.Sort,"test#08");; dv2 = new DataView (dataTable); - AssertEquals ("test#09","itemTable",dv2.Table.TableName); - AssertEquals ("test#10",string.Empty,dv2.Sort); - AssertEquals ("test#11",false,dv2.ApplyDefaultSort); - AssertEquals ("test#12",dataTable.Rows[0],dv2[0].Row); + Assert.AreEqual ("itemTable",dv2.Table.TableName,"test#09");; + Assert.AreEqual (string.Empty,dv2.Sort,"test#10");; + Assert.AreEqual (false,dv2.ApplyDefaultSort,"test#11");; + Assert.AreEqual (dataTable.Rows[0],dv2[0].Row,"test#12");; dv3 = new DataView (dataTable,"","itemId DESC",DataViewRowState.CurrentRows); - AssertEquals ("test#13","",dv3.RowFilter); - AssertEquals ("test#14","itemId DESC",dv3.Sort); - AssertEquals ("test#15",DataViewRowState.CurrentRows,dv3.RowStateFilter); + Assert.AreEqual ("",dv3.RowFilter,"test#13");; + Assert.AreEqual ("itemId DESC",dv3.Sort,"test#14");; + Assert.AreEqual (DataViewRowState.CurrentRows,dv3.RowStateFilter,"test#15");; //AssertEquals ("test#16",dataTable.Rows.[(dataTable.Rows.Count-1)],dv3[0]); } @@ -179,20 +179,20 @@ namespace MonoTests.System.Data public void TestValue () { DataView TestView = new DataView (dataTable); - Assertion.AssertEquals ("Dv #1", "item 1", TestView [0]["itemId"]); + Assert.AreEqual ("item 1", TestView [0]["itemId"], "Dv #1"); } [Test] public void TestCount () { DataView TestView = new DataView (dataTable); - Assertion.AssertEquals ("Dv #3", 5, TestView.Count); + Assert.AreEqual (5, TestView.Count, "Dv #3"); } [Test] public void AllowNew () { - AssertEquals ("test#01",true,dataView.AllowNew); + Assert.AreEqual (true, dataView.AllowNew, "test#01"); } [Test] @@ -203,7 +203,7 @@ namespace MonoTests.System.Data dataView.ApplyDefaultSort = true; // dataView.Sort = "itemName"; // AssertEquals ("test#01","item 1",dataView[0]["itemId"]); - AssertEquals ("test#02",ListChangedType.Reset,listChangedArgs.ListChangedType); + Assert.AreEqual (ListChangedType.Reset,listChangedArgs.ListChangedType, "test#02"); // UnComment the line below to see if dataView is sorted // PrintTableOrView (dataView,"* OnApplyDefaultSort"); } @@ -212,7 +212,7 @@ namespace MonoTests.System.Data public void RowStateFilter () { dataView.RowStateFilter = DataViewRowState.Deleted; - AssertEquals ("test#01",ListChangedType.Reset,listChangedArgs.ListChangedType); + Assert.AreEqual (ListChangedType.Reset,listChangedArgs.ListChangedType, "test#01"); } [Test] @@ -239,16 +239,16 @@ namespace MonoTests.System.Data dataView [0] ["col1"] = -1; dataView.RowStateFilter = DataViewRowState.ModifiedOriginal; v = dataView [0] [0].ToString (); - AssertEquals ("ModifiedOriginal.Count", 1, dataView.Count); - AssertEquals ("ModifiedOriginal.Value", "1", v); + Assert.AreEqual (1, dataView.Count, "ModifiedOriginal.Count"); + Assert.AreEqual ("1", v, "ModifiedOriginal.Value"); // Deleting the row dataView.Delete (0); dataView.RowStateFilter = DataViewRowState.Deleted; v = dataView [0] [0].ToString (); - AssertEquals ("Deleted.Count", 1, dataView.Count); - AssertEquals ("Deleted.Value", "1", v); + Assert.AreEqual (1, dataView.Count, "Deleted.Count"); + Assert.AreEqual ("1", v, "Deleted.Value"); } //xamarin bug #18898 # / novell bug #595899 @@ -276,10 +276,10 @@ namespace MonoTests.System.Data another_new_row[0] = "9"; another_new_row[1] = "10"; - AssertEquals ("#1", dv[2][0], "9"); + Assert.AreEqual (dv[2][0], "9", "#1"); //This should not throw a System.Data.VersionNotFoundException: "There is no Proposed data to accces" - AssertEquals ("#1", dv[1][0], "7"); + Assert.AreEqual (dv[1][0], "7", "#1"); } @@ -288,7 +288,7 @@ namespace MonoTests.System.Data { DataView dataview = new DataView (); PropertyDescriptorCollection col = ((ITypedList)dataview).GetItemProperties (null); - AssertEquals ("1", 0, col.Count); + Assert.AreEqual (0, col.Count, "1"); } #region Sort Tests @@ -296,7 +296,7 @@ namespace MonoTests.System.Data public void SortListChangedTest () { dataView.Sort = "itemName DESC"; - AssertEquals ("test#01",ListChangedType.Reset,listChangedArgs.ListChangedType); + Assert.AreEqual (ListChangedType.Reset,listChangedArgs.ListChangedType, "test#01"); // UnComment the line below to see if dataView is sorted // PrintTableOrView (dataView); } @@ -338,60 +338,60 @@ namespace MonoTests.System.Data DataView dataView = dataTable.DefaultView; string s = "Default sorting: "; - AssertEquals (s + "First entry has wrong item", 1, dataView[0][0]); - AssertEquals (s + "Second entry has wrong item", 0, dataView[1][0]); - AssertEquals (s + "Third entry has wrong item", 3, dataView[2][0]); - AssertEquals (s + "Fourth entry has wrong item", 2, dataView[3][0]); + Assert.AreEqual (1, dataView[0][0], s + "First entry has wrong item"); + Assert.AreEqual (0, dataView[1][0], s + "Second entry has wrong item"); + Assert.AreEqual (3, dataView[2][0], s + "Third entry has wrong item"); + Assert.AreEqual (2, dataView[3][0], s + "Fourth entry has wrong item"); s = "Ascending sorting 1: "; dataView.Sort = "itemId ASC"; - AssertEquals (s + "First entry has wrong item", 0, dataView[0][0]); - AssertEquals (s + "Second entry has wrong item", 1, dataView[1][0]); - AssertEquals (s + "Third entry has wrong item", 2, dataView[2][0]); - AssertEquals (s + "Fourth entry has wrong item", 3, dataView[3][0]); + Assert.AreEqual (0, dataView[0][0], s + "First entry has wrong item"); + Assert.AreEqual (1, dataView[1][0], s + "Second entry has wrong item"); + Assert.AreEqual (2, dataView[2][0], s + "Third entry has wrong item"); + Assert.AreEqual (3, dataView[3][0], s + "Fourth entry has wrong item"); // bug #77104 (2-5) s = "Ascending sorting 2: "; dataView.Sort = "itemId ASC"; - AssertEquals (s + "First entry has wrong item", 0, dataView[0][0]); - AssertEquals (s + "Second entry has wrong item", 1, dataView[1][0]); - AssertEquals (s + "Third entry has wrong item", 2, dataView[2][0]); - AssertEquals (s + "Fourth entry has wrong item", 3, dataView[3][0]); + Assert.AreEqual (0, dataView[0][0], s + "First entry has wrong item"); + Assert.AreEqual (1, dataView[1][0], s + "Second entry has wrong item"); + Assert.AreEqual (2, dataView[2][0], s + "Third entry has wrong item"); + Assert.AreEqual (3, dataView[3][0], s + "Fourth entry has wrong item"); s = "Ascending sorting 3: "; dataView.Sort = "[itemId] ASC"; - AssertEquals (s + "First entry has wrong item", 0, dataView[0][0]); - AssertEquals (s + "Second entry has wrong item", 1, dataView[1][0]); - AssertEquals (s + "Third entry has wrong item", 2, dataView[2][0]); - AssertEquals (s + "Fourth entry has wrong item", 3, dataView[3][0]); + Assert.AreEqual (0, dataView[0][0], s + "First entry has wrong item"); + Assert.AreEqual (1, dataView[1][0], s + "Second entry has wrong item"); + Assert.AreEqual (2, dataView[2][0], s + "Third entry has wrong item"); + Assert.AreEqual (3, dataView[3][0], s + "Fourth entry has wrong item"); s = "Ascending sorting 4: "; dataView.Sort = "[itemId] ASC"; - AssertEquals (s + "First entry has wrong item", 0, dataView[0][0]); - AssertEquals (s + "Second entry has wrong item", 1, dataView[1][0]); - AssertEquals (s + "Third entry has wrong item", 2, dataView[2][0]); - AssertEquals (s + "Fourth entry has wrong item", 3, dataView[3][0]); + Assert.AreEqual (0, dataView[0][0], s + "First entry has wrong item"); + Assert.AreEqual (1, dataView[1][0], s + "Second entry has wrong item"); + Assert.AreEqual (2, dataView[2][0], s + "Third entry has wrong item"); + Assert.AreEqual (3, dataView[3][0], s + "Fourth entry has wrong item"); s = "Ascending sorting 5: "; try { dataView.Sort = "itemId \tASC"; - AssertEquals (s + "Tab cannot be a separator" , true, false); + Assert.AreEqual (true, false, s + "Tab cannot be a separator"); }catch (IndexOutOfRangeException e) { } s = "Descending sorting : "; dataView.Sort = "itemId DESC"; - AssertEquals (s + "First entry has wrong item", 3, dataView[0][0]); - AssertEquals (s + "Second entry has wrong item", 2, dataView[1][0]); - AssertEquals (s + "Third entry has wrong item", 1, dataView[2][0]); - AssertEquals (s + "Fourth entry has wrong item", 0, dataView[3][0]); + Assert.AreEqual (3, dataView[0][0], s + "First entry has wrong item"); + Assert.AreEqual (2, dataView[1][0], s + "Second entry has wrong item"); + Assert.AreEqual (1, dataView[2][0], s + "Third entry has wrong item"); + Assert.AreEqual (0, dataView[3][0], s + "Fourth entry has wrong item"); s = "Reverted to default sorting: "; dataView.Sort = null; - AssertEquals (s + "First entry has wrong item", 1, dataView[0][0]); - AssertEquals (s + "Second entry has wrong item", 0, dataView[1][0]); - AssertEquals (s + "Third entry has wrong item", 3, dataView[2][0]); - AssertEquals (s + "Fourth entry has wrong item", 2, dataView[3][0]); + Assert.AreEqual (1, dataView[0][0], s + "First entry has wrong item"); + Assert.AreEqual (0, dataView[1][0], s + "Second entry has wrong item"); + Assert.AreEqual (3, dataView[2][0], s + "Third entry has wrong item"); + Assert.AreEqual (2, dataView[3][0], s + "Fourth entry has wrong item"); } #endregion // Sort Tests @@ -409,21 +409,21 @@ namespace MonoTests.System.Data { dataView.AllowNew = true; DataRowView drv = dataView.AddNew (); - AssertEquals ("test#01",ListChangedType.ItemAdded,listChangedArgs.ListChangedType); - AssertEquals ("test#02",-1,listChangedArgs.OldIndex); - AssertEquals ("test#03",5,listChangedArgs.NewIndex); - AssertEquals ("test#04",drv["itemName"],dataView [dataView.Count - 1]["itemName"]); + Assert.AreEqual (ListChangedType.ItemAdded,listChangedArgs.ListChangedType, "test#01"); + Assert.AreEqual (-1,listChangedArgs.OldIndex, "test#02"); + Assert.AreEqual (5,listChangedArgs.NewIndex, "test#03"); + Assert.AreEqual (drv["itemName"],dataView [dataView.Count - 1]["itemName"], "test#04"); listChangedArgs = null; drv["itemId"] = "item " + 1001; drv["itemName"] = "name " + rndm.Next(); drv["itemPrice"] = "Rs. " + (rndm.Next() % 1000); drv["itemCategory"] = "Cat " + ((rndm.Next() % 10) + 1); // Actually no events are arisen when items are set. - AssertNull ("test#05", listChangedArgs); + Assert.IsNull (listChangedArgs, "test#05"); drv.CancelEdit (); - AssertEquals ("test#06",ListChangedType.ItemDeleted,listChangedArgs.ListChangedType); - AssertEquals ("test#07",-1,listChangedArgs.OldIndex); - AssertEquals ("test#08",5,listChangedArgs.NewIndex); + Assert.AreEqual (ListChangedType.ItemDeleted,listChangedArgs.ListChangedType, "test#06"); + Assert.AreEqual (-1,listChangedArgs.OldIndex, "test#07"); + Assert.AreEqual (5,listChangedArgs.NewIndex, "test#08"); } [Test] @@ -439,15 +439,15 @@ namespace MonoTests.System.Data table.Columns.AddRange (new DataColumn[] {col1,col2}); dv.Table = table; - AssertNull ("#1", dv.Table); + Assert.IsNull (dv.Table, "#1"); dv.EndInit (); - AssertNull ("#2", dv.Table); // still. - AssertEquals ("#3", 0, table.Columns.Count); + Assert.IsNull (dv.Table, "#2"); // still. + Assert.AreEqual (0, table.Columns.Count, "#3"); table.EndInit (); - AssertEquals ("#5", table, dv.Table); - AssertEquals ("#4", 2, table.Columns.Count); + Assert.AreEqual (table, dv.Table, "#4"); + Assert.AreEqual (2, table.Columns.Count, "#5"); } private bool dvInitialized; @@ -472,19 +472,19 @@ namespace MonoTests.System.Data table.Columns.AddRange (new DataColumn[] {col1,col2}); dv.Table = table; - AssertNull ("#1", dv.Table); + Assert.IsNull (dv.Table, "#1"); dv.EndInit (); - AssertNull ("#2", dv.Table); - AssertEquals ("#3", 0, table.Columns.Count); + Assert.IsNull (dv.Table, "#2"); + Assert.AreEqual (0, table.Columns.Count, "#3"); table.EndInit (); dv.Initialized -= new EventHandler (OnDataViewInitialized); // this should not be unregistered before table.EndInit(). - AssertEquals ("#4", 2, table.Columns.Count); - AssertEquals ("#6", table, dv.Table); - AssertEquals ("DataViewInitialized #5", true, dvInitialized); + Assert.AreEqual (2, table.Columns.Count, "#4"); + Assert.AreEqual (table, dv.Table, "#6"); + Assert.AreEqual (true, dvInitialized, "DataViewInitialized #5"); } [Test] @@ -503,21 +503,21 @@ namespace MonoTests.System.Data randInt = rndm.Next () % rowCount; dataView.Sort = "itemId"; drv = dataView [randInt]; - AssertEquals ("test#01",randInt,dataView.Find (drv ["itemId"])); + Assert.AreEqual (randInt,dataView.Find (drv ["itemId"]), "test#01"); dataView.Sort = "itemId DESC"; drv = dataView [randInt]; - AssertEquals ("test#02",randInt,dataView.Find (drv ["itemId"])); + Assert.AreEqual (randInt,dataView.Find (drv ["itemId"]), "test#02"); dataView.Sort = "itemId, itemName"; drv = dataView [randInt]; object [] keys = new object [2]; keys [0] = drv ["itemId"]; keys [1] = drv ["itemName"]; - AssertEquals ("test#03",randInt,dataView.Find (keys)); + Assert.AreEqual (randInt,dataView.Find (keys), "test#03"); dataView.Sort = "itemId"; - AssertEquals ("test#04",-1,dataView.Find("no item")); + Assert.AreEqual (-1,dataView.Find("no item"), "test#04"); } @@ -540,7 +540,7 @@ namespace MonoTests.System.Data [Test] public void ToStringTest () { - AssertEquals ("test#01","System.Data.DataView",dataView.ToString()); + Assert.AreEqual ("System.Data.DataView",dataView.ToString(), "test#01"); } [Test] @@ -556,38 +556,38 @@ namespace MonoTests.System.Data dataTable.Rows.Add(dr); //PrintTableOrView(dataView, "ItemAdded"); - AssertEquals ("test#01",ListChangedType.ItemAdded,listChangedArgs.ListChangedType); + Assert.AreEqual (ListChangedType.ItemAdded,listChangedArgs.ListChangedType, "test#01"); listChangedArgs = null; dr ["itemId"] = "aitem 0"; // PrintTableOrView(dataView, "ItemChanged"); - AssertEquals ("test#02",ListChangedType.ItemChanged,listChangedArgs.ListChangedType); + Assert.AreEqual (ListChangedType.ItemChanged,listChangedArgs.ListChangedType, "test#02"); listChangedArgs = null; dr ["itemId"] = "zitem 0"; // PrintTableOrView(dataView, "ItemMoved"); - AssertEquals ("test#03",ListChangedType.ItemMoved,listChangedArgs.ListChangedType); + Assert.AreEqual (ListChangedType.ItemMoved,listChangedArgs.ListChangedType, "test#03"); listChangedArgs = null; dataTable.Rows.Remove (dr); // PrintTableOrView(dataView, "ItemDeleted"); - AssertEquals ("test#04",ListChangedType.ItemDeleted,listChangedArgs.ListChangedType); + Assert.AreEqual (ListChangedType.ItemDeleted,listChangedArgs.ListChangedType, "test#04"); listChangedArgs = null; DataColumn dc5 = new DataColumn ("itemDesc"); dataTable.Columns.Add (dc5); // PrintTableOrView(dataView, "PropertyDescriptorAdded"); - AssertEquals ("test#05",ListChangedType.PropertyDescriptorAdded,listChangedArgs.ListChangedType); + Assert.AreEqual (ListChangedType.PropertyDescriptorAdded,listChangedArgs.ListChangedType, "test#05"); listChangedArgs = null; dc5.ColumnName = "itemDescription"; // PrintTableOrView(dataView, "PropertyDescriptorChanged"); - // AssertEquals ("test#06",ListChangedType.PropertyDescriptorChanged,listChangedArgs.ListChangedType); + // Assert.AreEqual ("test#06",ListChangedType.PropertyDescriptorChanged,listChangedArgs.ListChangedType); listChangedArgs = null; dataTable.Columns.Remove (dc5); // PrintTableOrView(dataView, "PropertyDescriptorDeleted"); - AssertEquals ("test#07",ListChangedType.PropertyDescriptorDeleted,listChangedArgs.ListChangedType); + Assert.AreEqual (ListChangedType.PropertyDescriptorDeleted,listChangedArgs.ListChangedType, "test#07"); } [Test] @@ -596,8 +596,8 @@ namespace MonoTests.System.Data DataView TestView = new DataView (dataTable); TestView.Sort = "itemId"; DataRowView[] Result = TestView.FindRows ("item 3"); - Assertion.AssertEquals ("Dv #1", 1, Result.Length); - Assertion.AssertEquals ("Dv #2", "item 3", Result [0]["itemId"]); + Assert.AreEqual (1, Result.Length, "Dv #1"); + Assert.AreEqual ("item 3", Result [0]["itemId"], "Dv #2"); } [Test] @@ -642,7 +642,7 @@ namespace MonoTests.System.Data DataView TestView = new DataView (dataTable); TestView.Delete (0); DataRow r = TestView.Table.Rows [0]; - Assertion.Assert ("Dv #1", !((string)r ["itemId"] == "item 1")); + Assert.IsTrue (!((string)r ["itemId"] == "item 1"), "Dv #1"); } [Test] @@ -685,13 +685,13 @@ namespace MonoTests.System.Data DataView dataView = new DataView (dataset.Tables[0]); - AssertEquals ("before delete", 3, dataView.Count); + Assert.AreEqual (3, dataView.Count, "before delete"); dataView.AllowDelete = true; // Deleting the first row dataView.Delete (0); - AssertEquals ("before delete", 2, dataView.Count); + Assert.AreEqual (2, dataView.Count, "before delete"); } [Test] @@ -746,7 +746,7 @@ namespace MonoTests.System.Data eventWriter.Write (" ------" + dv.Count); DataRowView a3 = dv.AddNew (); - AssertEquals (reference, eventWriter.ToString ()); + Assert.AreEqual (reference, eventWriter.ToString ()); } [Test] @@ -766,7 +766,7 @@ table was set. dc2.ColumnName = "new_column_name"; - AssertEquals (result.Replace ("\r\n", "\n"), eventWriter.ToString ().Replace ("\r\n", "\n")); + Assert.AreEqual (result.Replace ("\r\n", "\n"), eventWriter.ToString ().Replace ("\r\n", "\n")); } private void ListChanged (object o, ListChangedEventArgs e) @@ -830,7 +830,7 @@ removed relation 2 ds.Relations.Remove (dr); eventWriter.WriteLine ("removed relation 2"); - AssertEquals (result.Replace ("\r\n", "\n"), eventWriter.ToString ().Replace ("\r\n", "\n")); + Assert.AreEqual (result.Replace ("\r\n", "\n"), eventWriter.ToString ().Replace ("\r\n", "\n")); } [Test] @@ -942,7 +942,7 @@ table changed. dv.Table = new DataTable ("table2"); eventWriter.WriteLine ("table changed."); - AssertEquals (result.Replace ("\r\n", "\n"), eventWriter.ToString ().Replace ("\r\n", "\n")); + Assert.AreEqual (result.Replace ("\r\n", "\n"), eventWriter.ToString ().Replace ("\r\n", "\n")); } [Test] @@ -982,7 +982,7 @@ table was set. dt.Columns.Add (""); eventWriter.WriteLine (" add a column with an empty name."); - AssertEquals (result.Replace ("\r\n", "\n"), eventWriter.ToString ().Replace ("\r\n", "\n")); + Assert.AreEqual (result.Replace ("\r\n", "\n"), eventWriter.ToString ().Replace ("\r\n", "\n")); GC.KeepAlive (dv); } diff --git a/mcs/class/System.Data/Test/System.Data/ForeignKeyConstraintTest.cs b/mcs/class/System.Data/Test/System.Data/ForeignKeyConstraintTest.cs index 6e5d2a4df9..21742eb3aa 100644 --- a/mcs/class/System.Data/Test/System.Data/ForeignKeyConstraintTest.cs +++ b/mcs/class/System.Data/Test/System.Data/ForeignKeyConstraintTest.cs @@ -38,7 +38,7 @@ using System.Data; namespace MonoTests.System.Data { [TestFixture] - public class ForeignKeyConstraintTest : Assertion + public class ForeignKeyConstraintTest { private DataSet _ds; @@ -73,23 +73,23 @@ namespace MonoTests.System.Data { DataTable Table = _ds.Tables [0]; - AssertEquals ("test#01", 0, Table.Constraints.Count); + Assert.AreEqual (0, Table.Constraints.Count, "test#01"); Table = _ds.Tables [1]; - AssertEquals ("test#02", 0, Table.Constraints.Count); + Assert.AreEqual (0, Table.Constraints.Count, "test#02"); // ctor (string, DataColumn, DataColumn ForeignKeyConstraint Constraint = new ForeignKeyConstraint ("test", _ds.Tables [0].Columns [2], _ds.Tables [1].Columns [0]); Table = _ds.Tables [1]; Table.Constraints.Add (Constraint); - AssertEquals ("test#03", 1, Table.Constraints.Count); - AssertEquals ("test#04", "test", Table.Constraints [0].ConstraintName); - AssertEquals ("test#05", typeof (ForeignKeyConstraint), Table.Constraints [0].GetType ()); + Assert.AreEqual (1, Table.Constraints.Count, "test#03"); + Assert.AreEqual ("test", Table.Constraints [0].ConstraintName, "test#04"); + Assert.AreEqual (typeof (ForeignKeyConstraint), Table.Constraints [0].GetType (), "test#05"); Table = _ds.Tables [0]; - AssertEquals ("test#06", 1, Table.Constraints.Count); - AssertEquals ("test#07", "Constraint1", Table.Constraints [0].ConstraintName); - AssertEquals ("test#08", typeof (UniqueConstraint), Table.Constraints [0].GetType ()); + Assert.AreEqual (1, Table.Constraints.Count, "test#06"); + Assert.AreEqual ("Constraint1", Table.Constraints [0].ConstraintName, "test#07"); + Assert.AreEqual (typeof (UniqueConstraint), Table.Constraints [0].GetType (), "test#08"); } // Tests ctor (DataColumn, DataColumn) @@ -98,23 +98,23 @@ namespace MonoTests.System.Data { DataTable Table = _ds.Tables [0]; - AssertEquals ("test#01", 0, Table.Constraints.Count); + Assert.AreEqual (0, Table.Constraints.Count, "test#01"); Table = _ds.Tables [1]; - AssertEquals ("test#02", 0, Table.Constraints.Count); + Assert.AreEqual (0, Table.Constraints.Count, "test#02"); // ctor (string, DataColumn, DataColumn ForeignKeyConstraint Constraint = new ForeignKeyConstraint (_ds.Tables [0].Columns [2], _ds.Tables [1].Columns [0]); Table = _ds.Tables [1]; Table.Constraints.Add (Constraint); - AssertEquals ("test#03", 1, Table.Constraints.Count); - AssertEquals ("test#04", "Constraint1", Table.Constraints [0].ConstraintName); - AssertEquals ("test#05", typeof (ForeignKeyConstraint), Table.Constraints [0].GetType ()); + Assert.AreEqual (1, Table.Constraints.Count, "test#03"); + Assert.AreEqual ("Constraint1", Table.Constraints [0].ConstraintName, "test#04"); + Assert.AreEqual (typeof (ForeignKeyConstraint), Table.Constraints [0].GetType (), "test#05"); Table = _ds.Tables [0]; - AssertEquals ("test#06", 1, Table.Constraints.Count); - AssertEquals ("test#07", "Constraint1", Table.Constraints [0].ConstraintName); - AssertEquals ("test#08", typeof (UniqueConstraint), Table.Constraints [0].GetType ()); + Assert.AreEqual (1, Table.Constraints.Count, "test#06"); + Assert.AreEqual ("Constraint1", Table.Constraints [0].ConstraintName, "test#07"); + Assert.AreEqual (typeof (UniqueConstraint), Table.Constraints [0].GetType (), "test#08"); } // Test ctor (DataColumn [], DataColumn []) @@ -123,9 +123,9 @@ namespace MonoTests.System.Data { DataTable Table = _ds.Tables [0]; - AssertEquals ("test#01", 0, Table.Constraints.Count); + Assert.AreEqual (0, Table.Constraints.Count, "test#01"); Table = _ds.Tables [1]; - AssertEquals ("test#02", 0, Table.Constraints.Count); + Assert.AreEqual (0, Table.Constraints.Count, "test#02"); DataColumn [] Cols1 = new DataColumn [2]; Cols1 [0] = _ds.Tables [0].Columns [1]; @@ -139,14 +139,14 @@ namespace MonoTests.System.Data Table = _ds.Tables [1]; Table.Constraints.Add (Constraint); - AssertEquals ("test#03", 1, Table.Constraints.Count); - AssertEquals ("test#04", "Constraint1", Table.Constraints [0].ConstraintName); - AssertEquals ("test#05", typeof (ForeignKeyConstraint), Table.Constraints [0].GetType ()); + Assert.AreEqual (1, Table.Constraints.Count, "test#03"); + Assert.AreEqual ("Constraint1", Table.Constraints [0].ConstraintName, "test#04"); + Assert.AreEqual (typeof (ForeignKeyConstraint), Table.Constraints [0].GetType (), "test#05"); Table = _ds.Tables [0]; - AssertEquals ("test#06", 1, Table.Constraints.Count); - AssertEquals ("test#07", "Constraint1", Table.Constraints [0].ConstraintName); - AssertEquals ("test#08", typeof (UniqueConstraint), Table.Constraints [0].GetType ()); + Assert.AreEqual (1, Table.Constraints.Count, "test#06"); + Assert.AreEqual ("Constraint1", Table.Constraints [0].ConstraintName, "test#07"); + Assert.AreEqual (typeof (UniqueConstraint), Table.Constraints [0].GetType (), "test#08"); } @@ -156,9 +156,9 @@ namespace MonoTests.System.Data { DataTable Table = _ds.Tables [0]; - AssertEquals ("test#01", 0, Table.Constraints.Count); + Assert.AreEqual (0, Table.Constraints.Count, "test#01"); Table = _ds.Tables [1]; - AssertEquals ("test#02", 0, Table.Constraints.Count); + Assert.AreEqual (0, Table.Constraints.Count, "test#02"); DataColumn [] Cols1 = new DataColumn [2]; Cols1 [0] = _ds.Tables [0].Columns [1]; @@ -172,14 +172,14 @@ namespace MonoTests.System.Data Table = _ds.Tables [1]; Table.Constraints.Add (Constraint); - AssertEquals ("test#03", 1, Table.Constraints.Count); - AssertEquals ("test#04", "Test", Table.Constraints [0].ConstraintName); - AssertEquals ("test#05", typeof (ForeignKeyConstraint), Table.Constraints [0].GetType ()); + Assert.AreEqual (1, Table.Constraints.Count, "test#03"); + Assert.AreEqual ("Test", Table.Constraints [0].ConstraintName, "test#04"); + Assert.AreEqual (typeof (ForeignKeyConstraint), Table.Constraints [0].GetType (), "test#05"); Table = _ds.Tables [0]; - AssertEquals ("test#06", 1, Table.Constraints.Count); - AssertEquals ("test#07", "Constraint1", Table.Constraints [0].ConstraintName); - AssertEquals ("test#08", typeof (UniqueConstraint), Table.Constraints [0].GetType ()); + Assert.AreEqual (1, Table.Constraints.Count, "test#06"); + Assert.AreEqual ("Constraint1", Table.Constraints [0].ConstraintName, "test#07"); + Assert.AreEqual (typeof (UniqueConstraint), Table.Constraints [0].GetType (), "test#08"); } [Test] @@ -211,7 +211,7 @@ namespace MonoTests.System.Data ForeignKeyConstraint fkc = new ForeignKeyConstraint ("hello world", parentTableName, parentColumnNames, childColumnNames, AcceptRejectRule.Cascade, Rule.Cascade, Rule.Cascade); // Assert that the Constraint object does not belong to any table yet try { DataTable tmp = fkc.Table; - Fail ("When table is null, get_Table causes an InvalidOperationException."); + Assert.Fail ("When table is null, get_Table causes an InvalidOperationException."); } catch (NullReferenceException) { // actually .NET throws this (bug) } catch (InvalidOperationException) { } @@ -234,9 +234,12 @@ namespace MonoTests.System.Data // OK - So AddRange() is the only way! table2.Constraints.AddRange (constraints); // After AddRange(), Check the properties of ForeignKeyConstraint object - Assertion.Assert("#A04", fkc.RelatedColumns [0].ColumnName.Equals ("col1")); Assertion.Assert("#A05", fkc.RelatedColumns [1].ColumnName.Equals ("col2")); Assertion.Assert("#A06", fkc.RelatedColumns [2].ColumnName.Equals ("col3")); Assertion.Assert("#A07", fkc.Columns [0].ColumnName.Equals ("col4")); - Assertion.Assert("#A08", fkc.Columns [1].ColumnName.Equals ("col5")); - Assertion.Assert("#A09", fkc.Columns [2].ColumnName.Equals ("col6")); + Assert.IsTrue(fkc.RelatedColumns [0].ColumnName.Equals ("col1"), "#A04"); + Assert.IsTrue(fkc.RelatedColumns [1].ColumnName.Equals ("col2"), "#A05"); + Assert.IsTrue(fkc.RelatedColumns [2].ColumnName.Equals ("col3"), "#A06"); + Assert.IsTrue(fkc.Columns [0].ColumnName.Equals ("col4"), "#A07"); + Assert.IsTrue(fkc.Columns [1].ColumnName.Equals ("col5"), "#A08"); + Assert.IsTrue(fkc.Columns [2].ColumnName.Equals ("col6"), "#A09"); #endif // Try to add columns with names which do not exist in the table parentColumnNames [2] = "noColumn"; @@ -255,7 +258,7 @@ namespace MonoTests.System.Data #if false // FIXME: Here this test crashes under MS.NET. // Check whether the child table really contains the foreign key constraint named "hello world" - Assertion.Assert("#A11 ", table2.Constraints.Contains ("hello world")); + Assert.IsTrue(table2.Constraints.Contains ("hello world"), "#A11 "); #endif } @@ -267,20 +270,20 @@ namespace MonoTests.System.Data { DataTable Table = _ds.Tables [0]; - AssertEquals ("test#01", 0, Table.Constraints.Count); + Assert.AreEqual (0, Table.Constraints.Count, "test#01"); Table = _ds.Tables [1]; - AssertEquals ("test#02", 0, Table.Constraints.Count); + Assert.AreEqual (0, Table.Constraints.Count, "test#02"); ForeignKeyConstraint Constraint = new ForeignKeyConstraint ("Test", _ds.Tables [0].Columns [0], _ds.Tables [0].Columns [2]); Table = _ds.Tables [0]; Table.Constraints.Add (Constraint); - AssertEquals ("test#03", 2, Table.Constraints.Count); - AssertEquals ("test#04", "Constraint1", Table.Constraints [0].ConstraintName); - AssertEquals ("test#05", typeof (UniqueConstraint), Table.Constraints [0].GetType ()); - AssertEquals ("test#04", "Test", Table.Constraints [1].ConstraintName); - AssertEquals ("test#05", typeof (ForeignKeyConstraint), Table.Constraints [1].GetType ()); + Assert.AreEqual (2, Table.Constraints.Count, "test#03"); + Assert.AreEqual ("Constraint1", Table.Constraints [0].ConstraintName, "test#04"); + Assert.AreEqual (typeof (UniqueConstraint), Table.Constraints [0].GetType (), "test#05"); + Assert.AreEqual ("Test", Table.Constraints [1].ConstraintName, "test#04"); + Assert.AreEqual (typeof (ForeignKeyConstraint), Table.Constraints [1].GetType (), "test#05"); } @@ -297,45 +300,45 @@ namespace MonoTests.System.Data try { fkc = new ForeignKeyConstraint((DataColumn)null,(DataColumn)null); - Fail("Failed to throw ArgumentNullException."); + Assert.Fail("Assert.Failed to throw ArgumentNullException."); } catch (NullReferenceException) {} catch (AssertionException exc) {throw exc;} catch (Exception exc) { - Fail("A1: Wrong Exception type. " + exc.ToString()); + Assert.Fail("A1: Wrong Exception type. " + exc.ToString()); } //zero length collection try { fkc = new ForeignKeyConstraint(new DataColumn[]{},new DataColumn[]{}); - Fail("B1: Failed to throw ArgumentException."); + Assert.Fail("B1: Assert.Failed to throw ArgumentException."); } catch (ArgumentException) {} catch (AssertionException exc) {throw exc;} catch (Exception exc) { - Fail("A2: Wrong Exception type. " + exc.ToString()); + Assert.Fail("A2: Wrong Exception type. " + exc.ToString()); } //different datasets try { fkc = new ForeignKeyConstraint(_ds.Tables[0].Columns[0], localTable.Columns[0]); - Fail("Failed to throw InvalidOperationException."); + Assert.Fail("Assert.Failed to throw InvalidOperationException."); } catch (InvalidOperationException) {} catch (AssertionException exc) {throw exc;} catch (Exception exc) { - Fail("A3: Wrong Exception type. " + exc.ToString()); + Assert.Fail("A3: Wrong Exception type. " + exc.ToString()); } try { fkc = new ForeignKeyConstraint(_ds.Tables[0].Columns[0], localTable.Columns[1]); - Fail("Failed to throw InvalidConstraintException."); + Assert.Fail("Assert.Failed to throw InvalidConstraintException."); } // tables in different datasets catch (InvalidOperationException) {} @@ -345,7 +348,7 @@ namespace MonoTests.System.Data try { fkc = new ForeignKeyConstraint(new DataColumn [] {_ds.Tables[0].Columns[0], _ds.Tables[0].Columns[1]}, new DataColumn [] {localTable.Columns[1], _ds.Tables[1].Columns [0]}); - Fail("Failed to throw InvalidOperationException."); + Assert.Fail("Assert.Failed to throw InvalidOperationException."); } catch (InvalidConstraintException) {} catch (AssertionException exc) {throw exc;} @@ -362,13 +365,13 @@ namespace MonoTests.System.Data try { fkc = new ForeignKeyConstraint(col, _ds.Tables[0].Columns[0]); - Fail("FTT1: Failed to throw ArgumentException."); + Assert.Fail("FTT1: Assert.Failed to throw ArgumentException."); } catch (ArgumentException) {} catch (AssertionException exc) {throw exc;} // catch (Exception exc) // { -// Fail("WET1: Wrong Exception type. " + exc.ToString()); +// Assert.Fail("WET1: Wrong Exception type. " + exc.ToString()); // } //Columns must belong to the same table @@ -382,13 +385,13 @@ namespace MonoTests.System.Data _ds.Tables[0].Columns[1], _ds.Tables[0].Columns[0]}); - Fail("FTT2: Failed to throw InvalidConstraintException."); + Assert.Fail("FTT2: Assert.Failed to throw InvalidConstraintException."); } catch (InvalidConstraintException) {} catch (AssertionException exc) {throw exc;} catch (Exception exc) { - Fail("WET2: Wrong Exception type. " + exc.ToString()); + Assert.Fail("WET2: Wrong Exception type. " + exc.ToString()); } @@ -403,13 +406,13 @@ namespace MonoTests.System.Data fkc = new ForeignKeyConstraint(twoCol, new DataColumn[] { _ds.Tables[0].Columns[0]}); - Fail("FTT3: Failed to throw ArgumentException."); + Assert.Fail("FTT3: Assert.Failed to throw ArgumentException."); } catch (ArgumentException) {} catch (AssertionException exc) {throw exc;} catch (Exception exc) { - Fail("WET3: Wrong Exception type. " + exc.ToString()); + Assert.Fail("WET3: Wrong Exception type. " + exc.ToString()); } //InvalidOperation: Parent and child are the same column. @@ -418,13 +421,13 @@ namespace MonoTests.System.Data fkc = new ForeignKeyConstraint( _ds.Tables[0].Columns[0], _ds.Tables[0].Columns[0] ); - Fail("FTT4: Failed to throw InvalidOperationException."); + Assert.Fail("FTT4: Assert.Failed to throw InvalidOperationException."); } catch (InvalidOperationException) {} catch (AssertionException exc) {throw exc;} catch (Exception exc) { - Fail("WET4: Wrong Exception type. " + exc.ToString()); + Assert.Fail("WET4: Wrong Exception type. " + exc.ToString()); } } @@ -446,14 +449,14 @@ namespace MonoTests.System.Data ForeignKeyConstraint fkcDiff = new ForeignKeyConstraint( tbl.Columns[1], tbl.Columns[2]); - Assert( "Equals failed. 1" , fkc.Equals(fkc2)); - Assert( "Equals failed. 2" , fkc2.Equals(fkc)); - Assert( "Equals failed. 3" , fkc.Equals(fkc)); + Assert.IsTrue( fkc.Equals(fkc2) , "Equals Assert.IsTrue.Failed. 1"); + Assert.IsTrue( fkc2.Equals(fkc) , "Equals Assert.IsTrue.Failed. 2"); + Assert.IsTrue( fkc.Equals(fkc) , "Equals Assert.IsTrue.Failed. 3"); - Assert( "Equals failed diff. 1" , fkc.Equals(fkcDiff) == false); + Assert.IsTrue( fkc.Equals(fkcDiff) == false , "Equals Assert.IsTrue.Failed diff. 1"); - //Assert( "Hash Code Failed. 1", fkc.GetHashCode() == fkc2.GetHashCode() ); - Assert( "Hash Code Failed. 2", fkc.GetHashCode() != fkcDiff.GetHashCode() ); + //Assert.IsTrue( "Hash Code Assert.IsTrue.Failed. 1", fkc.GetHashCode() == fkc2.GetHashCode() ); + Assert.IsTrue( fkc.GetHashCode() != fkcDiff.GetHashCode() , "Hash Code Assert.IsTrue.Failed. 2"); } @@ -512,7 +515,7 @@ namespace MonoTests.System.Data t2.Rows.Add (new object [] {10}); t1.Rows [0][0]=20; - Assert("#1", (int)t2.Rows [0][0] == 20); + Assert.IsTrue((int)t2.Rows [0][0] == 20, "#1"); } [Test] diff --git a/mcs/class/System.Data/Test/System.Xml/XmlDataDocumentTest2.cs b/mcs/class/System.Data/Test/System.Xml/XmlDataDocumentTest2.cs index cc8196e0c9..0a99b71bc3 100644 --- a/mcs/class/System.Data/Test/System.Xml/XmlDataDocumentTest2.cs +++ b/mcs/class/System.Data/Test/System.Xml/XmlDataDocumentTest2.cs @@ -38,7 +38,7 @@ using NUnit.Framework; namespace MonoTests.System.Xml { [TestFixture] - public class XmlDataDocumentTest2 : Assertion + public class XmlDataDocumentTest2 { string xml = "12
"; @@ -53,8 +53,8 @@ namespace MonoTests.System.Xml public void TestDefaultCtor () { XmlDataDocument doc = new XmlDataDocument (); - AssertNotNull (doc.DataSet); - AssertEquals ("NewDataSet", doc.DataSet.DataSetName); + Assert.IsNotNull (doc.DataSet); + Assert.AreEqual ("NewDataSet", doc.DataSet.DataSetName); } [Test] @@ -117,73 +117,73 @@ namespace MonoTests.System.Xml ds.Relations.Add (rel); XmlDataDocument doc = new XmlDataDocument (ds); doc.LoadXml ("11aaa"); - AssertEquals (1, ds.Tables [0].Rows.Count); - AssertEquals (1, ds.Tables [1].Rows.Count); + Assert.AreEqual (1, ds.Tables [0].Rows.Count); + Assert.AreEqual (1, ds.Tables [1].Rows.Count); // document element - no mapped row XmlElement el = doc.DocumentElement; - AssertNull (doc.GetRowFromElement (el)); + Assert.IsNull (doc.GetRowFromElement (el)); // tab1 element - has mapped row el = el.FirstChild as XmlElement; DataRow row = doc.GetRowFromElement (el); - AssertNotNull (row); - AssertEquals (DataRowState.Added, row.RowState); + Assert.IsNotNull (row); + Assert.AreEqual (DataRowState.Added, row.RowState); // col1 - it is column. no mapped row el = el.FirstChild as XmlElement; row = doc.GetRowFromElement (el); - AssertNull (row); + Assert.IsNull (row); // col2 - it is column. np mapped row el = el.NextSibling as XmlElement; row = doc.GetRowFromElement (el); - AssertNull (row); + Assert.IsNull (row); // child - has mapped row el = el.NextSibling as XmlElement; row = doc.GetRowFromElement (el); - AssertNotNull (row); - AssertEquals (DataRowState.Added, row.RowState); + Assert.IsNotNull (row); + Assert.AreEqual (DataRowState.Added, row.RowState); // created (detached) table 1 element (used later) el = doc.CreateElement ("tab1"); row = doc.GetRowFromElement (el); - AssertEquals (DataRowState.Detached, row.RowState); - AssertEquals (1, dt.Rows.Count); // not added yet + Assert.AreEqual (DataRowState.Detached, row.RowState); + Assert.AreEqual (1, dt.Rows.Count); // not added yet // adding a node before setting EnforceConstraints // raises an error try { doc.DocumentElement.AppendChild (el); - Fail ("Invalid Operation should occur; EnforceConstraints prevents addition."); + Assert.Fail ("Invalid Operation should occur; EnforceConstraints prevents addition."); } catch (InvalidOperationException) { } // try again... ds.EnforceConstraints = false; - AssertEquals (1, dt.Rows.Count); // not added yet + Assert.AreEqual (1, dt.Rows.Count); // not added yet doc.DocumentElement.AppendChild (el); - AssertEquals (2, dt.Rows.Count); // added + Assert.AreEqual (2, dt.Rows.Count); // added row = doc.GetRowFromElement (el); - AssertEquals (DataRowState.Added, row.RowState); // changed + Assert.AreEqual (DataRowState.Added, row.RowState); // changed // Irrelevant element XmlElement el2 = doc.CreateElement ("hoge"); row = doc.GetRowFromElement (el2); - AssertNull (row); + Assert.IsNull (row); // created table 2 element (used later) el = doc.CreateElement ("child"); row = doc.GetRowFromElement (el); - AssertEquals (DataRowState.Detached, row.RowState); + Assert.AreEqual (DataRowState.Detached, row.RowState); // Adding it to irrelevant element performs no row state change. - AssertEquals (1, dt2.Rows.Count); // not added yet + Assert.AreEqual (1, dt2.Rows.Count); // not added yet el2.AppendChild (el); - AssertEquals (1, dt2.Rows.Count); // still not added + Assert.AreEqual (1, dt2.Rows.Count); // still not added row = doc.GetRowFromElement (el); - AssertEquals (DataRowState.Detached, row.RowState); // still detached here + Assert.AreEqual (DataRowState.Detached, row.RowState); // still detached here } // bug #54505 @@ -244,8 +244,8 @@ namespace MonoTests.System.Xml StringReader sr = new StringReader (sw.ToString()); doc1.Load (sr); - AssertEquals ("#1", 1, ds1.Tables [0].Rows.Count); - AssertEquals ("#2", 1, ds1.Tables [0].Rows [0][0]); + Assert.AreEqual (1, ds1.Tables [0].Rows.Count, "#1"); + Assert.AreEqual (1, ds1.Tables [0].Rows [0][0], "#2"); } [Test] @@ -267,8 +267,8 @@ namespace MonoTests.System.Xml StringReader sr = new StringReader (sw.ToString()); doc1.Load (sr); - AssertEquals ("#1", 1, ds1.Tables [0].Rows [0][0]); - AssertEquals ("#2", true, ds1.Tables [0].Rows [0].IsNull (1)); + Assert.AreEqual (1, ds1.Tables [0].Rows [0][0], "#1"); + Assert.AreEqual (true, ds1.Tables [0].Rows [0].IsNull (1), "#2"); } [Test] @@ -301,9 +301,9 @@ namespace MonoTests.System.Xml StringReader sreader = new StringReader (swriter.ToString ()); DataSet ds1 = ds.Clone (); XmlDataDocument doc1 = new XmlDataDocument (ds1); - AssertEquals ("#2" , 0, ds1.Tables [0].Rows.Count); + Assert.AreEqual (0 , ds1.Tables [0].Rows.Count, "#2"); doc1.Load (sreader); - AssertEquals ("#3" , 3, ds1.Tables [0].Rows.Count); + Assert.AreEqual (3 , ds1.Tables [0].Rows.Count, "#3"); } } } diff --git a/mcs/class/System.Data/mobile_System.Data.dll.sources b/mcs/class/System.Data/mobile_System.Data.dll.sources index a5b2a2f149..eb7e02eb03 100644 --- a/mcs/class/System.Data/mobile_System.Data.dll.sources +++ b/mcs/class/System.Data/mobile_System.Data.dll.sources @@ -6,6 +6,7 @@ Assembly/AssemblyInfo.cs ../../build/common/AssemblyRef.cs ReferenceSources/NativeOledbWrapper.cs +ReferenceSources/PoolBlockingPeriod.cs ReferenceSources/Res.cs ReferenceSources/Res.missing.cs ReferenceSources/ResCategoryAttribute.cs diff --git a/mcs/class/System.Data/monotouch_watch_System.Data.dll.exclude.sources b/mcs/class/System.Data/monotouch_watch_System.Data.dll.exclude.sources new file mode 100644 index 0000000000..2782624ebc --- /dev/null +++ b/mcs/class/System.Data/monotouch_watch_System.Data.dll.exclude.sources @@ -0,0 +1,11 @@ +System.Data.SqlClient/SqlBulkCopy.cs +System.Data.SqlClient/SqlCommand.cs +System.Data.SqlClient/SqlCommandBuilder.cs +System.Data.SqlClient/SqlConnection.cs +System.Data.SqlClient/SqlDataReader.cs +System.Data.SqlClient/SqlDecimalExtensions.cs +System.Data.SqlClient/SqlException.cs +System.Data.SqlClient/SqlParameter.cs +System.Data.SqlClient/SqlParameterCollection.cs +System.Data.SqlClient/SqlTransaction.cs +System.Data.SqlClient/SqlXmlTextReader.cs diff --git a/mcs/class/System.Data/monotouch_watch_System.Data.dll.sources b/mcs/class/System.Data/monotouch_watch_System.Data.dll.sources index bbc860b8cd..f279aec806 100644 --- a/mcs/class/System.Data/monotouch_watch_System.Data.dll.sources +++ b/mcs/class/System.Data/monotouch_watch_System.Data.dll.sources @@ -1 +1,10 @@ #include mobile_System.Data.dll.sources +System.Data.SqlClient/SqlBulkCopy.platformnotsupported.cs +System.Data.SqlClient/SqlCommand.platformnotsupported.cs +System.Data.SqlClient/SqlCommandBuilder.platformnotsupported.cs +System.Data.SqlClient/SqlConnection.platformnotsupported.cs +System.Data.SqlClient/SqlDataReader.platformnotsupported.cs +System.Data.SqlClient/SqlException.platformnotsupported.cs +System.Data.SqlClient/SqlParameter.platformnotsupported.cs +System.Data.SqlClient/SqlParameterCollection.platformnotsupported.cs +System.Data.SqlClient/SqlTransaction.platformnotsupported.cs diff --git a/mcs/class/System.Data/net_4_x_System.Data.dll.sources b/mcs/class/System.Data/net_4_x_System.Data.dll.sources index 76b642b884..c075e87489 100644 --- a/mcs/class/System.Data/net_4_x_System.Data.dll.sources +++ b/mcs/class/System.Data/net_4_x_System.Data.dll.sources @@ -6,6 +6,7 @@ Assembly/AssemblyInfo.cs ../../build/common/AssemblyRef.cs ReferenceSources/NativeOledbWrapper.cs +ReferenceSources/PoolBlockingPeriod.cs ReferenceSources/Res.cs ReferenceSources/Res.missing.cs ReferenceSources/ResCategoryAttribute.cs diff --git a/mcs/class/System.IO.Compression/Test/System.IO.Compression/ZipTest.cs b/mcs/class/System.IO.Compression/Test/System.IO.Compression/ZipTest.cs index 2d03d559d4..f1b83746b4 100644 --- a/mcs/class/System.IO.Compression/Test/System.IO.Compression/ZipTest.cs +++ b/mcs/class/System.IO.Compression/Test/System.IO.Compression/ZipTest.cs @@ -182,6 +182,24 @@ namespace MonoTests.System.IO.Compression File.Delete ("delete.zip"); } + [Test] + public void ZipDeleteEntryCheckEntries() + { + File.Copy("archive.zip", "delete.zip", overwrite: true); + using (var archive = new ZipArchive(File.Open("delete.zip", FileMode.Open), + ZipArchiveMode.Update)) + { + var entry = archive.GetEntry("foo.txt"); + Assert.IsNotNull(entry); + + entry.Delete(); + + Assert.IsNull(archive.Entries.FirstOrDefault(e => e == entry)); + } + + File.Delete ("delete.zip"); + } + [Test] public void ZipGetEntryDeleteUpdateMode() { diff --git a/mcs/class/System.IO.Compression/ZipArchive.cs b/mcs/class/System.IO.Compression/ZipArchive.cs index c1a3df5756..5df9434321 100644 --- a/mcs/class/System.IO.Compression/ZipArchive.cs +++ b/mcs/class/System.IO.Compression/ZipArchive.cs @@ -237,6 +237,12 @@ namespace System.IO.Compression } } + internal void RemoveEntryInternal(ZipArchiveEntry entry) + { + zipFile.RemoveEntry(entry.entry); + entries.Remove(entry); + } + protected virtual void Dispose (bool disposing) { if (disposed) diff --git a/mcs/class/System.IO.Compression/ZipArchiveEntry.cs b/mcs/class/System.IO.Compression/ZipArchiveEntry.cs index 9b415fbe6f..0ea00c549d 100644 --- a/mcs/class/System.IO.Compression/ZipArchiveEntry.cs +++ b/mcs/class/System.IO.Compression/ZipArchiveEntry.cs @@ -210,7 +210,7 @@ namespace System.IO.Compression throw new IOException("The entry is already open for reading or writing."); wasDeleted = true; - Archive.zipFile.RemoveEntry(entry); + Archive.RemoveEntryInternal(this); } public Stream Open() diff --git a/mcs/class/System.IdentityModel/Assembly/AssemblyInfo.cs b/mcs/class/System.IdentityModel/Assembly/AssemblyInfo.cs index 05426acf59..0b98df2042 100644 --- a/mcs/class/System.IdentityModel/Assembly/AssemblyInfo.cs +++ b/mcs/class/System.IdentityModel/Assembly/AssemblyInfo.cs @@ -61,6 +61,7 @@ using System.Runtime.InteropServices; [assembly: ComCompatibleVersion (1, 0, 3300, 0)] [assembly: AllowPartiallyTrustedCallers] -#if !NET_2_1 +#if !MOBILE [assembly: SecurityCritical (SecurityCriticalScope.Explicit)] -#endif \ No newline at end of file +[assembly: InternalsVisibleTo ("System.ServiceModel, PublicKey=00000000000000000400000000000000")] +#endif diff --git a/mcs/class/System.IdentityModel/Makefile b/mcs/class/System.IdentityModel/Makefile index 7eea754cfa..29bb7acd6e 100644 --- a/mcs/class/System.IdentityModel/Makefile +++ b/mcs/class/System.IdentityModel/Makefile @@ -2,8 +2,12 @@ thisdir = class/System.IdentityModel SUBDIRS = include ../../build/rules.make +ifndef NO_MONO_SECURITY +MONO_SECURITY=Mono.Security +endif + LIBRARY = System.IdentityModel.dll -LIB_REFS = System System.Xml System.Security Mono.Security System.Runtime.Serialization +LIB_REFS = System System.Xml System.Security $(MONO_SECURITY) System.Runtime.Serialization LIB_MCS_FLAGS = \ /d:NET_3_0 \ $(OTHER_LIB_MCS_FLAGS) diff --git a/mcs/class/System.ServiceModel/System.ServiceModel.Security.Tokens/BinarySecretSecurityToken.cs b/mcs/class/System.IdentityModel/System.ServiceModel.Security.Tokens/BinarySecretSecurityToken.cs similarity index 100% rename from mcs/class/System.ServiceModel/System.ServiceModel.Security.Tokens/BinarySecretSecurityToken.cs rename to mcs/class/System.IdentityModel/System.ServiceModel.Security.Tokens/BinarySecretSecurityToken.cs diff --git a/mcs/class/System.ServiceModel/System.ServiceModel.Security.Tokens/InternalEncryptedKeyIdentifierClause.cs b/mcs/class/System.IdentityModel/System.ServiceModel.Security.Tokens/InternalEncryptedKeyIdentifierClause.cs similarity index 100% rename from mcs/class/System.ServiceModel/System.ServiceModel.Security.Tokens/InternalEncryptedKeyIdentifierClause.cs rename to mcs/class/System.IdentityModel/System.ServiceModel.Security.Tokens/InternalEncryptedKeyIdentifierClause.cs diff --git a/mcs/class/System.ServiceModel/System.ServiceModel.Security.Tokens/WrappedKeySecurityToken.cs b/mcs/class/System.IdentityModel/System.ServiceModel.Security.Tokens/WrappedKeySecurityToken.cs similarity index 100% rename from mcs/class/System.ServiceModel/System.ServiceModel.Security.Tokens/WrappedKeySecurityToken.cs rename to mcs/class/System.IdentityModel/System.ServiceModel.Security.Tokens/WrappedKeySecurityToken.cs diff --git a/mcs/class/System.ServiceModel/System.ServiceModel.Security/BinarySecretKeyIdentifierClause.cs b/mcs/class/System.IdentityModel/System.ServiceModel.Security/BinarySecretKeyIdentifierClause.cs similarity index 100% rename from mcs/class/System.ServiceModel/System.ServiceModel.Security/BinarySecretKeyIdentifierClause.cs rename to mcs/class/System.IdentityModel/System.ServiceModel.Security/BinarySecretKeyIdentifierClause.cs diff --git a/mcs/class/System.ServiceModel/System.ServiceModel.Security/KeyNameIdentifierClause.cs b/mcs/class/System.IdentityModel/System.ServiceModel.Security/KeyNameIdentifierClause.cs similarity index 100% rename from mcs/class/System.ServiceModel/System.ServiceModel.Security/KeyNameIdentifierClause.cs rename to mcs/class/System.IdentityModel/System.ServiceModel.Security/KeyNameIdentifierClause.cs diff --git a/mcs/class/System.ServiceModel/System.ServiceModel.Security/SecurityContextKeyIdentifierClause.cs b/mcs/class/System.IdentityModel/System.ServiceModel.Security/SecurityContextKeyIdentifierClause.cs similarity index 100% rename from mcs/class/System.ServiceModel/System.ServiceModel.Security/SecurityContextKeyIdentifierClause.cs rename to mcs/class/System.IdentityModel/System.ServiceModel.Security/SecurityContextKeyIdentifierClause.cs diff --git a/mcs/class/System.IdentityModel/Test/System.IdentityModel.Tokens/BootstrapContextTest.cs b/mcs/class/System.IdentityModel/Test/System.IdentityModel.Tokens/BootstrapContextTest.cs index 1d5090748c..d55b6a0692 100644 --- a/mcs/class/System.IdentityModel/Test/System.IdentityModel.Tokens/BootstrapContextTest.cs +++ b/mcs/class/System.IdentityModel/Test/System.IdentityModel.Tokens/BootstrapContextTest.cs @@ -2,7 +2,6 @@ // BootstrapContextTest.cs - NUnit Test Cases for System.IdentityModel.Tokens.BootstrapContext // -#if NET_4_5 using System; using System.IO; using System.IdentityModel.Tokens; @@ -248,4 +247,3 @@ namespace MonoTests.System.IdentityModel.Tokens.net_4_5 { } } } -#endif diff --git a/mcs/class/System.IdentityModel/net_4_x_System.IdentityModel.dll.sources b/mcs/class/System.IdentityModel/net_4_x_System.IdentityModel.dll.sources index 4d705d24d5..c6ab55fe8d 100755 --- a/mcs/class/System.IdentityModel/net_4_x_System.IdentityModel.dll.sources +++ b/mcs/class/System.IdentityModel/net_4_x_System.IdentityModel.dll.sources @@ -128,4 +128,10 @@ System.IdentityModel.Tokens/X509SubjectKeyIdentifierClause.cs System.IdentityModel.Tokens/X509ThumbprintKeyIdentifierClause.cs System.IdentityModel.Tokens/X509WindowsSecurityToken.cs System.Security.Claims/AuthenticationTypes.cs +System.ServiceModel.Security/BinarySecretKeyIdentifierClause.cs +System.ServiceModel.Security/KeyNameIdentifierClause.cs +System.ServiceModel.Security/SecurityContextKeyIdentifierClause.cs System.ServiceModel.Security/X509CertificateValidationMode.cs +System.ServiceModel.Security.Tokens/BinarySecretSecurityToken.cs +System.ServiceModel.Security.Tokens/InternalEncryptedKeyIdentifierClause.cs +System.ServiceModel.Security.Tokens/WrappedKeySecurityToken.cs diff --git a/mcs/class/System.Json.Microsoft/Makefile b/mcs/class/System.Json.Microsoft/Makefile index 4c2329392d..56c51c6330 100644 --- a/mcs/class/System.Json.Microsoft/Makefile +++ b/mcs/class/System.Json.Microsoft/Makefile @@ -2,14 +2,11 @@ thisdir = class/System.Json.Microsoft SUBDIRS = include ../../build/rules.make -System.Json.Properties.Resources.resources: System.Json/Properties/Resources.resx - $(RESGEN) "$<" "$@" +RESOURCE_DEFS = System.Json.Properties.Resources,System.Json/Properties/Resources.resx LIBRARY = System.Json.Microsoft.dll LIB_REFS = System System.Xml System.Core System.Runtime.Serialization -LIB_MCS_FLAGS = /d:ASPNETMVC -keyfile:../winfx.pub -delaysign \ - /resource:System.Json.Properties.Resources.resources - +LIB_MCS_FLAGS = /d:ASPNETMVC -keyfile:../winfx.pub -delaysign EXTRA_DISTFILES = System.Json/Properties/Resources.resx ifeq (4, $(FRAMEWORK_VERSION_MAJOR)) @@ -24,5 +21,3 @@ endif TEST_MCS_FLAGS = $(LIB_MCS_FLAGS) include ../../build/library.make - -$(the_lib): System.Json.Properties.Resources.resources diff --git a/mcs/class/System.Net.Http.Formatting/Makefile b/mcs/class/System.Net.Http.Formatting/Makefile index e6bee285bd..43895c07c8 100644 --- a/mcs/class/System.Net.Http.Formatting/Makefile +++ b/mcs/class/System.Net.Http.Formatting/Makefile @@ -4,19 +4,12 @@ include ../../build/rules.make LIBRARY = System.Net.Http.Formatting.dll -System.Net.Http.Properties.CommonWebApiResources.resources: ../../../external/aspnetwebstack/src/Common/CommonWebApiResources.resx - $(RESGEN) "$<" "$@" +RESOURCE_DEFS = \ + System.Net.Http.Properties.CommonWebApiResources,../../../external/aspnetwebstack/src/Common/CommonWebApiResources.resx \ + System.Net.Http.Properties.Resources,../../../external/aspnetwebstack/src/System.Net.Http.Formatting/Properties/Resources.resx -System.Net.Http.Properties.Resources.resources: ../../../external/aspnetwebstack/src/System.Net.Http.Formatting/Properties/Resources.resx - $(RESGEN) "$<" "$@" LIB_REFS = System.Core System System.Net.Http System.Xml System.Runtime.Serialization System.Xml.Linq System.Data System.Configuration -LIB_MCS_FLAGS = \ - -d:ASPNETMVC -keyfile:../winfx.pub -delaysign \ - -resource:System.Net.Http.Properties.CommonWebApiResources.resources \ - -resource:System.Net.Http.Properties.Resources.resources +LIB_MCS_FLAGS = -d:ASPNETMVC -keyfile:../winfx.pub -delaysign include ../../build/library.make - -$(the_lib): System.Net.Http.Properties.CommonWebApiResources.resources \ - System.Net.Http.Properties.Resources.resources diff --git a/mcs/class/System.Net.Http/System.Net.Http.Headers/ContentRangeHeaderValue.cs b/mcs/class/System.Net.Http/System.Net.Http.Headers/ContentRangeHeaderValue.cs index ee2dbe74b6..e90cc29f82 100644 --- a/mcs/class/System.Net.Http/System.Net.Http.Headers/ContentRangeHeaderValue.cs +++ b/mcs/class/System.Net.Http/System.Net.Http.Headers/ContentRangeHeaderValue.cs @@ -147,7 +147,7 @@ namespace System.Net.Http.Headers if (t != Token.Type.Token) return false; - int nvalue; + long nvalue; if (!lexer.IsStarStringValue (t)) { if (!lexer.TryGetNumericValue (t, out nvalue)) { var s = lexer.GetStringValue (t); @@ -158,12 +158,12 @@ namespace System.Net.Http.Headers if (sep.Length != 2) return false; - if (!int.TryParse (sep[0], NumberStyles.None, CultureInfo.InvariantCulture, out nvalue)) + if (!long.TryParse (sep[0], NumberStyles.None, CultureInfo.InvariantCulture, out nvalue)) return false; value.From = nvalue; - if (!int.TryParse (sep[1], NumberStyles.None, CultureInfo.InvariantCulture, out nvalue)) + if (!long.TryParse (sep[1], NumberStyles.None, CultureInfo.InvariantCulture, out nvalue)) return false; value.To = nvalue; diff --git a/mcs/class/System.Net.Http/System.Net.Http.Headers/HeaderInfo.cs b/mcs/class/System.Net.Http/System.Net.Http.Headers/HeaderInfo.cs index 9ca277dbbc..3da8be8c43 100644 --- a/mcs/class/System.Net.Http/System.Net.Http.Headers/HeaderInfo.cs +++ b/mcs/class/System.Net.Http/System.Net.Http.Headers/HeaderInfo.cs @@ -70,14 +70,21 @@ namespace System.Net.Http.Headers return null; var c = (HttpHeaderValueCollection) collection; - if (c.Count == 0) - return null; + if (c.Count == 0) { + if (c.InvalidValues == null) + return null; + + return new List (c.InvalidValues); + } var list = new List (); foreach (var item in c) { list.Add (item.ToString ()); } + if (c.InvalidValues != null) + list.AddRange (c.InvalidValues); + return list; } diff --git a/mcs/class/System.Net.Http/System.Net.Http.Headers/HttpHeaderValueCollection.cs b/mcs/class/System.Net.Http/System.Net.Http.Headers/HttpHeaderValueCollection.cs index 72c4299e64..35f8556bdc 100644 --- a/mcs/class/System.Net.Http/System.Net.Http.Headers/HttpHeaderValueCollection.cs +++ b/mcs/class/System.Net.Http/System.Net.Http.Headers/HttpHeaderValueCollection.cs @@ -36,6 +36,7 @@ namespace System.Net.Http.Headers readonly List list; readonly HttpHeaders headers; readonly HeaderInfo headerInfo; + List invalidValues; internal HttpHeaderValueCollection (HttpHeaders headers, HeaderInfo headerInfo) { @@ -50,6 +51,12 @@ namespace System.Net.Http.Headers } } + internal List InvalidValues { + get { + return invalidValues; + } + } + public bool IsReadOnly { get { return false; @@ -66,9 +73,18 @@ namespace System.Net.Http.Headers list.AddRange (values); } + internal void AddInvalidValue (string invalidValue) + { + if (invalidValues == null) + invalidValues = new List (); + + invalidValues.Add (invalidValue); + } + public void Clear () { list.Clear (); + invalidValues = null; } public bool Contains (T item) @@ -93,11 +109,12 @@ namespace System.Net.Http.Headers public override string ToString () { - // This implementation prints different values than - // what .NET does when one of the values is invalid - // But it better represents what is actually hold by - // the collection - return string.Join (headerInfo.Separator, list); + var res = string.Join (headerInfo.Separator, list); + + if (invalidValues != null) + res += string.Join (headerInfo.Separator, invalidValues); + + return res; } public bool TryParseAdd (string input) diff --git a/mcs/class/System.Net.Http/System.Net.Http.Headers/HttpHeaders.cs b/mcs/class/System.Net.Http/System.Net.Http.Headers/HttpHeaders.cs index 05b5fe6268..c22a669559 100644 --- a/mcs/class/System.Net.Http/System.Net.Http.Headers/HttpHeaders.cs +++ b/mcs/class/System.Net.Http/System.Net.Http.Headers/HttpHeaders.cs @@ -481,23 +481,28 @@ namespace System.Net.Http.Headers headers.Add (name, value); } + var col = (HttpHeaderValueCollection) value.Parsed; + if (value.HasStringValues) { var hinfo = known_headers[name]; - if (value.Parsed == null) - value.Parsed = hinfo.CreateCollection (this); + if (col == null) { + value.Parsed = col = new HttpHeaderValueCollection (this, hinfo); + } object pvalue; for (int i = 0; i < value.Values.Count; ++i) { - if (!hinfo.TryParse (value.Values[i], out pvalue)) - continue; - - hinfo.AddToCollection (value.Parsed, pvalue); - value.Values.RemoveAt (i); - --i; + var svalue = value.Values[i]; + if (!hinfo.TryParse (svalue, out pvalue)) { + col.AddInvalidValue (svalue); + } else { + hinfo.AddToCollection (col, pvalue); + } } + + value.Values.Clear (); } - return (HttpHeaderValueCollection) value.Parsed; + return col; } internal void SetValue (string name, T value, Func toStringConverter = null) diff --git a/mcs/class/System.Net.Http/System.Net.Http/HttpClientHandler.cs b/mcs/class/System.Net.Http/System.Net.Http/HttpClientHandler.cs index 78f2fafcc8..a3335ea550 100644 --- a/mcs/class/System.Net.Http/System.Net.Http/HttpClientHandler.cs +++ b/mcs/class/System.Net.Http/System.Net.Http/HttpClientHandler.cs @@ -380,7 +380,9 @@ namespace System.Net.Http } } catch (WebException we) { if (we.Status != WebExceptionStatus.RequestCanceled) - throw; + throw new HttpRequestException ("An error occurred while sending the request", we); + } catch (System.IO.IOException ex) { + throw new HttpRequestException ("An error occurred while sending the request", ex); } if (cancellationToken.IsCancellationRequested) { diff --git a/mcs/class/System.Net.Http/System.Net.Http/HttpClientHandler.platformnotsupported.cs b/mcs/class/System.Net.Http/System.Net.Http/HttpClientHandler.platformnotsupported.cs new file mode 100644 index 0000000000..eb5b7ffa82 --- /dev/null +++ b/mcs/class/System.Net.Http/System.Net.Http/HttpClientHandler.platformnotsupported.cs @@ -0,0 +1,175 @@ +// +// System.Net.Http/HttpClientHandler.cs +// +// Author: +// Rolf Bjarne Kvinge +// +// Copyright (C) 2016 Xamarin Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System.Collections.Generic; +using System.Net.Security; +using System.Security.Authentication; +using System.Security.Cryptography.X509Certificates; +using System.Threading.Tasks; +using System.Threading; + +namespace System.Net.Http +{ + public class HttpClientHandler : HttpMessageHandler + { + const string EXCEPTION_MESSAGE = "System.Net.Http.HttpClientHandler is not supported on the current platform."; + + public HttpClientHandler () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public bool AllowAutoRedirect { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public DecompressionMethods AutomaticDecompression { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public ClientCertificateOption ClientCertificateOptions { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public CookieContainer CookieContainer { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public ICredentials Credentials { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public int MaxAutomaticRedirections { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public long MaxRequestContentBufferSize { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public bool PreAuthenticate { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public IWebProxy Proxy { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public virtual bool SupportsAutomaticDecompression { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public virtual bool SupportsProxy { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public virtual bool SupportsRedirectConfiguration { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public bool UseCookies { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public bool UseDefaultCredentials { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public bool UseProxy { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + protected override void Dispose (bool disposing) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + HttpResponseMessage CreateResponseMessage (HttpWebResponse wr, HttpRequestMessage requestMessage, CancellationToken cancellationToken) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + protected internal async override Task SendAsync (HttpRequestMessage request, CancellationToken cancellationToken) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + +#if NETSTANDARD + public bool CheckCertificateRevocationList { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public X509CertificateCollection ClientCertificates { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public ICredentials DefaultProxyCredentials { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public int MaxConnectionsPerServer { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public int MaxResponseHeadersLength { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public IDictionary Properties { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public Func ServerCertificateCustomValidationCallback { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public SslProtocols SslProtocols { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } +#endif + } +} diff --git a/mcs/class/System.Net.Http/Test/System.Net.Http.Headers/HttpHeaderValueCollection.cs b/mcs/class/System.Net.Http/Test/System.Net.Http.Headers/HttpHeaderValueCollection.cs index 50f8432f8e..0fd7560375 100644 --- a/mcs/class/System.Net.Http/Test/System.Net.Http.Headers/HttpHeaderValueCollection.cs +++ b/mcs/class/System.Net.Http/Test/System.Net.Http.Headers/HttpHeaderValueCollection.cs @@ -91,5 +91,42 @@ namespace MonoTests.System.Net.Http.Headers Assert.AreEqual ("kk, ttt", headers.Connection.ToString (), "#3"); } + + [Test] + public void AddInvalid () + { + HttpRequestMessage message = new HttpRequestMessage (); + HttpRequestHeaders headers = message.Headers; + + headers.TryAddWithoutValidation ("User-Agent", "user,agent/1.0"); + + Assert.AreEqual (0, headers.UserAgent.Count, "#1"); + Assert.AreEqual ("user,agent/1.0", headers.UserAgent.ToString (), "#2"); + + Assert.AreEqual ("User-Agent: user,agent/1.0\r\n", headers.ToString (), "#3"); + + headers.UserAgent.Clear (); + Assert.AreEqual ("", headers.UserAgent.ToString (), "#4"); + Assert.AreEqual ("", headers.ToString (), "#5"); + } + + [Test] + public void AddInvalidAndValid () + { + HttpRequestMessage message = new HttpRequestMessage (); + HttpRequestHeaders headers = message.Headers; + + headers.TryAddWithoutValidation ("User-Agent", "user,agent/1.0"); + headers.TryAddWithoutValidation("User-Agent", "agent2/2.0"); + + Assert.AreEqual (1, headers.UserAgent.Count, "#1"); + Assert.AreEqual ("agent2/2.0user,agent/1.0", headers.UserAgent.ToString (), "#2"); + + Assert.AreEqual ("User-Agent: agent2/2.0 user,agent/1.0\r\n", headers.ToString (), "#3"); + + headers.UserAgent.Clear (); + Assert.AreEqual ("", headers.UserAgent.ToString (), "#4"); + Assert.AreEqual ("", headers.ToString (), "#5"); + } } } diff --git a/mcs/class/System.Net.Http/Test/System.Net.Http/HttpClientHandlerTest.cs b/mcs/class/System.Net.Http/Test/System.Net.Http/HttpClientHandlerTest.cs index 78f8a0c225..3f06e1c316 100644 --- a/mcs/class/System.Net.Http/Test/System.Net.Http/HttpClientHandlerTest.cs +++ b/mcs/class/System.Net.Http/Test/System.Net.Http/HttpClientHandlerTest.cs @@ -61,6 +61,9 @@ namespace MonoTests.System.Net.Http } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Properties_Defaults () { var h = new HttpClientHandler (); @@ -83,6 +86,9 @@ namespace MonoTests.System.Net.Http } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Properties_Invalid () { var h = new HttpClientHandler (); @@ -107,6 +113,9 @@ namespace MonoTests.System.Net.Http } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Properties_AfterClientCreation () { var h = new HttpClientHandler (); @@ -119,6 +128,9 @@ namespace MonoTests.System.Net.Http } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Disposed () { var h = new HttpClientHandler (); diff --git a/mcs/class/System.Net.Http/Test/System.Net.Http/HttpClientTest.cs b/mcs/class/System.Net.Http/Test/System.Net.Http/HttpClientTest.cs index aa678a036e..d9aab417df 100644 --- a/mcs/class/System.Net.Http/Test/System.Net.Http/HttpClientTest.cs +++ b/mcs/class/System.Net.Http/Test/System.Net.Http/HttpClientTest.cs @@ -263,6 +263,10 @@ namespace MonoTests.System.Net.Http [Test] +#if FEATURE_NO_BSD_SOCKETS + // Using HttpClientHandler, which indirectly requires BSD sockets. + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void CancelRequestViaProxy () { var handler = new HttpClientHandler { @@ -321,6 +325,9 @@ namespace MonoTests.System.Net.Http } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Proxy_Disabled () { var pp = WebRequest.DefaultWebProxy; @@ -397,6 +404,9 @@ namespace MonoTests.System.Net.Http } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Send_Complete_Default () { bool? failed = null; @@ -441,6 +451,9 @@ namespace MonoTests.System.Net.Http } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Send_Complete_Version_1_0 () { bool? failed = null; @@ -488,6 +501,9 @@ namespace MonoTests.System.Net.Http } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Send_Complete_ClientHandlerSettings () { bool? failed = null; @@ -552,6 +568,9 @@ namespace MonoTests.System.Net.Http } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Send_Complete_CustomHeaders () { bool? failed = null; @@ -616,6 +635,9 @@ namespace MonoTests.System.Net.Http } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Send_Complete_CustomHeaders_SpecialSeparators () { bool? failed = null; @@ -650,6 +672,9 @@ namespace MonoTests.System.Net.Http } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Send_Complete_CustomHeaders_Host () { bool? failed = null; @@ -683,6 +708,9 @@ namespace MonoTests.System.Net.Http } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Send_Transfer_Encoding_Chunked () { bool? failed = null; @@ -712,6 +740,9 @@ namespace MonoTests.System.Net.Http } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Send_Transfer_Encoding_Custom () { bool? failed = null; @@ -740,6 +771,9 @@ namespace MonoTests.System.Net.Http } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Send_Complete_Content () { var listener = CreateListener (l => { @@ -767,6 +801,9 @@ namespace MonoTests.System.Net.Http } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Send_Complete_Content_MaxResponseContentBufferSize () { var listener = CreateListener (l => { @@ -789,6 +826,9 @@ namespace MonoTests.System.Net.Http } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Send_Complete_Content_MaxResponseContentBufferSize_Error () { var listener = CreateListener (l => { @@ -815,6 +855,9 @@ namespace MonoTests.System.Net.Http } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Send_Complete_NoContent () { foreach (var method in new HttpMethod[] { HttpMethod.Post, HttpMethod.Put, HttpMethod.Delete }) { @@ -847,6 +890,9 @@ namespace MonoTests.System.Net.Http } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Send_Complete_Error () { var listener = CreateListener (l => { @@ -867,6 +913,9 @@ namespace MonoTests.System.Net.Http } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Send_Content_Get () { var listener = CreateListener (l => { @@ -886,6 +935,9 @@ namespace MonoTests.System.Net.Http } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Send_Content_BomEncoding () { var listener = CreateListener (l => { @@ -910,6 +962,9 @@ namespace MonoTests.System.Net.Http } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Send_Content_Put () { bool passed = false; @@ -935,6 +990,9 @@ namespace MonoTests.System.Net.Http } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Send_Content_Put_CustomStream () { bool passed = false; @@ -1037,6 +1095,9 @@ namespace MonoTests.System.Net.Http [Test] [Category ("MobileNotWorking")] // Missing encoding +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void GetString_Many () { Action context = (HttpListenerContext l) => { @@ -1066,6 +1127,9 @@ namespace MonoTests.System.Net.Http } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void GetByteArray_ServerError () { var listener = CreateListener (l => { @@ -1088,6 +1152,9 @@ namespace MonoTests.System.Net.Http } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void DisallowAutoRedirect () { var listener = CreateListener (l => { @@ -1116,6 +1183,9 @@ namespace MonoTests.System.Net.Http } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void RequestUriAfterRedirect () { var listener = CreateListener (l => { @@ -1156,6 +1226,9 @@ namespace MonoTests.System.Net.Http } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif /* * Properties may only be modified before sending the first request. */ @@ -1186,6 +1259,10 @@ namespace MonoTests.System.Net.Http } [Test] +#if FEATURE_NO_BSD_SOCKETS + // Using HttpClientHandler, which indirectly requires BSD sockets. + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif /* * However, this policy is not enforced for custom handlers and there * is also no way a derived class could tell its HttpClientHandler parent diff --git a/mcs/class/System.Net.Http/monotouch_watch_System.Net.Http.dll.exclude.sources b/mcs/class/System.Net.Http/monotouch_watch_System.Net.Http.dll.exclude.sources new file mode 100644 index 0000000000..5c2ff8a54f --- /dev/null +++ b/mcs/class/System.Net.Http/monotouch_watch_System.Net.Http.dll.exclude.sources @@ -0,0 +1 @@ +System.Net.Http/HttpClientHandler.cs diff --git a/mcs/class/System.Net.Http/monotouch_watch_System.Net.Http.dll.sources b/mcs/class/System.Net.Http/monotouch_watch_System.Net.Http.dll.sources new file mode 100644 index 0000000000..a9d766e5ed --- /dev/null +++ b/mcs/class/System.Net.Http/monotouch_watch_System.Net.Http.dll.sources @@ -0,0 +1,2 @@ +#include System.Net.Http.dll.sources +System.Net.Http/HttpClientHandler.platformnotsupported.cs diff --git a/mcs/class/System.Net/Assembly/AssemblyInfo.cs b/mcs/class/System.Net/Assembly/AssemblyInfo.cs index 249f6ebf8f..600e5eb6c6 100644 --- a/mcs/class/System.Net/Assembly/AssemblyInfo.cs +++ b/mcs/class/System.Net/Assembly/AssemblyInfo.cs @@ -54,7 +54,7 @@ using System.Runtime.InteropServices; [assembly: NeutralResourcesLanguage ("en-US")] [assembly: CLSCompliant (true)] [assembly: AssemblyDelaySign (true)] -#if NET_2_1 +#if MOBILE [assembly: AssemblyKeyFile ("../silverlight.pub")] [assembly: InternalsVisibleTo ("System.Windows, PublicKey=00240000048000009400000006020000002400005253413100040000010001008D56C76F9E8649383049F383C44BE0EC204181822A6C31CF5EB7EF486944D032188EA1D3920763712CCB12D75FB77E9811149E6148E5D32FBAAB37611C1878DDC19E20EF135D0CB2CFF2BFEC3D115810C3D9069638FE4BE215DBF795861920E5AB6F7DB2E2CEEF136AC23D5DD2BF031700AEC232F6C6B1C785B4305C123B37AB")] [assembly: InternalsVisibleTo ("System.Windows.Browser, PublicKey=00240000048000009400000006020000002400005253413100040000010001008D56C76F9E8649383049F383C44BE0EC204181822A6C31CF5EB7EF486944D032188EA1D3920763712CCB12D75FB77E9811149E6148E5D32FBAAB37611C1878DDC19E20EF135D0CB2CFF2BFEC3D115810C3D9069638FE4BE215DBF795861920E5AB6F7DB2E2CEEF136AC23D5DD2BF031700AEC232F6C6B1C785B4305C123B37AB")] diff --git a/mcs/class/System.Runtime.Caching/ReferenceSources/SRef.cs b/mcs/class/System.Runtime.Caching/ReferenceSources/SRef.cs deleted file mode 100644 index 644a2fc0b2..0000000000 --- a/mcs/class/System.Runtime.Caching/ReferenceSources/SRef.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; -using System.Runtime.InteropServices; - -namespace System.Runtime.Caching { - /* - * This class is used to retrieve the size of an object graph. - * Although Mono has not a way of computing this. - * Known problems: - * - CacheMemoryMonitor does not trim the cache when it reaches its memory size limit. - * - IMemoryCacheManager.UpdateCacheSize is called with incorrect size. - */ - internal class SRef { - -// private Object _sizedRef; - - internal SRef (Object target) { -// _sizedRef = target; - } - - internal long ApproximateSize { - get { - // TODO: .net uses System.SizedReference which contains approximate size after Gen 2 collection - return 16; - } - } - - internal void Dispose() { - - } - } -} \ No newline at end of file diff --git a/mcs/class/System.Runtime.Caching/System.Runtime.Caching.dll.sources b/mcs/class/System.Runtime.Caching/System.Runtime.Caching.dll.sources index c10ee4fb40..46aa74c47c 100644 --- a/mcs/class/System.Runtime.Caching/System.Runtime.Caching.dll.sources +++ b/mcs/class/System.Runtime.Caching/System.Runtime.Caching.dll.sources @@ -8,7 +8,6 @@ ReferenceSources/CacheEntryCollection.cs ReferenceSources/CacheExpires.cs ReferenceSources/CacheUsage.cs ReferenceSources/R.Designer.cs -ReferenceSources/SRef.cs ../referencesource/System.Runtime.Caching/Resources/RH.cs ../referencesource/System.Runtime.Caching/System/Caching/CacheEntryChangeMonitor.cs ../referencesource/System.Runtime.Caching/System/Caching/CacheEntryRemovedArguments.cs @@ -51,3 +50,4 @@ ReferenceSources/SRef.cs ../referencesource/System.Runtime.Caching/System/Caching/SafeBitVector32.cs ../referencesource/System.Runtime.Caching/System/Caching/SafeRegistryHandle.cs ../referencesource/System.Runtime.Caching/System/Caching/SqlChangeMonitor.cs +../referencesource/System.Runtime.Caching/System/Caching/SRef.cs diff --git a/mcs/class/System.Runtime.DurableInstancing/Assembly/AssemblyInfo.cs b/mcs/class/System.Runtime.DurableInstancing/Assembly/AssemblyInfo.cs index 72f0502653..edeecbe4e5 100644 --- a/mcs/class/System.Runtime.DurableInstancing/Assembly/AssemblyInfo.cs +++ b/mcs/class/System.Runtime.DurableInstancing/Assembly/AssemblyInfo.cs @@ -55,7 +55,7 @@ using System.Runtime.InteropServices; [assembly: NeutralResourcesLanguage ("en-US")] [assembly: CLSCompliant (true)] [assembly: AssemblyDelaySign (true)] -#if NET_2_1 +#if MOBILE [assembly: AssemblyKeyFile ("../silverlight.pub")] #else [assembly: AssemblyKeyFile ("../winfx.pub")] diff --git a/mcs/class/System.Runtime.Serialization.Formatters.Soap/Test/InternalSoapValuesTest.cs b/mcs/class/System.Runtime.Serialization.Formatters.Soap/Test/InternalSoapValuesTest.cs index cbab4c217e..86b4617162 100644 --- a/mcs/class/System.Runtime.Serialization.Formatters.Soap/Test/InternalSoapValuesTest.cs +++ b/mcs/class/System.Runtime.Serialization.Formatters.Soap/Test/InternalSoapValuesTest.cs @@ -53,7 +53,7 @@ namespace SoapShared Serialize(obj, ms); ms.Position = 0; Object des = Deserialize(ms); - Assertion.AssertEquals(obj.GetType(), des.GetType()); + Assert.AreEqual (obj.GetType(), des.GetType()); } private void Serialize(object ob, Stream stream) diff --git a/mcs/class/System.Runtime.Serialization.Formatters.Soap/Test/SerializationTest.cs b/mcs/class/System.Runtime.Serialization.Formatters.Soap/Test/SerializationTest.cs index d3914d9b32..3aee88df4a 100644 --- a/mcs/class/System.Runtime.Serialization.Formatters.Soap/Test/SerializationTest.cs +++ b/mcs/class/System.Runtime.Serialization.Formatters.Soap/Test/SerializationTest.cs @@ -222,7 +222,7 @@ namespace MonoTests.System.Runtime.Serialization.Formatters.Soap if (expected != null && expected.GetType().IsArray) EqualsArray (message, (Array)expected, (Array)actual); else - Assertion.AssertEquals (message, expected, actual); + Assert.AreEqual (expected, actual, message); } public static void EqualsArray (string message, object oar1, object oar2) diff --git a/mcs/class/System.Runtime.Serialization.Formatters.Soap/Test/SoapFormatterTest.cs b/mcs/class/System.Runtime.Serialization.Formatters.Soap/Test/SoapFormatterTest.cs index 9735ce04b0..91fdd7857d 100644 --- a/mcs/class/System.Runtime.Serialization.Formatters.Soap/Test/SoapFormatterTest.cs +++ b/mcs/class/System.Runtime.Serialization.Formatters.Soap/Test/SoapFormatterTest.cs @@ -171,8 +171,8 @@ namespace MonoTests.System.Runtime.Serialization.Formatters.Soap { private object Serialize(object objGraph) { MemoryStream stream = new MemoryStream(); - Assertion.Assert(objGraph != null); - Assertion.Assert(stream != null); + Assert.IsTrue(objGraph != null); + Assert.IsTrue(stream != null); _soapFormatter.SurrogateSelector = _surrogate; _soapFormatter.Serialize(stream, objGraph); @@ -182,8 +182,8 @@ namespace MonoTests.System.Runtime.Serialization.Formatters.Soap { stream.Position = 0; object objReturn = _soapFormatterDeserializer.Deserialize(stream); - Assertion.Assert(objReturn != null); - Assertion.AssertEquals("#Tests "+objGraph.GetType(), objGraph.GetType(), objReturn.GetType()); + Assert.IsTrue(objReturn != null); + Assert.AreEqual(objGraph.GetType(), objReturn.GetType(), "#Tests "+objGraph.GetType()); stream = new MemoryStream(); _soapFormatter.Serialize(stream, objReturn); stream.Position = 0; @@ -209,19 +209,19 @@ namespace MonoTests.System.Runtime.Serialization.Formatters.Soap { public void TestValueTypes() { object objReturn; objReturn = Serialize((short)1); - Assertion.AssertEquals("#int16", objReturn, 1); + Assert.AreEqual(objReturn, 1, "#int16"); objReturn = Serialize(1); - Assertion.AssertEquals("#int32", objReturn, 1); + Assert.AreEqual(objReturn, 1, "#int32"); objReturn = Serialize((Single)0.1234); - Assertion.AssertEquals("#Single", objReturn, 0.123400003f); + Assert.AreEqual(objReturn, 0.123400003f, "#Single"); objReturn = Serialize((Double)1234567890.0987654321); - Assertion.AssertEquals("#iDouble", objReturn, 1234567890.0987654321); + Assert.AreEqual(objReturn, 1234567890.0987654321, "#iDouble"); objReturn = Serialize(true); - Assertion.AssertEquals("#Bool", objReturn, true); + Assert.AreEqual(objReturn, true, "#Bool"); objReturn = Serialize((Int64) 1234567890); - Assertion.AssertEquals("#Int64", objReturn, 1234567890); + Assert.AreEqual(objReturn, 1234567890, "#Int64"); objReturn = Serialize('c'); - Assertion.AssertEquals("#Char", objReturn, 'c'); + Assert.AreEqual(objReturn, 'c', "#Char"); } [Test] @@ -229,7 +229,7 @@ namespace MonoTests.System.Runtime.Serialization.Formatters.Soap { object objReturn; objReturn = Serialize(""); objReturn = Serialize("hello world!"); - Assertion.AssertEquals("#string", "hello world!", objReturn); + Assert.AreEqual("hello world!", objReturn, "#string"); SoapMessage soapMsg = new SoapMessage(); soapMsg.Headers = new Header[0]; soapMsg.MethodName = "Equals"; @@ -242,27 +242,27 @@ namespace MonoTests.System.Runtime.Serialization.Formatters.Soap { _soapFormatterDeserializer.TopObject = null; SimpleObject obj = new SimpleObject("simple object", 1); objReturn = Serialize(obj); - Assertion.AssertEquals("#SimpleObject", obj, objReturn); + Assert.AreEqual(obj, objReturn, "#SimpleObject"); objReturn = Serialize(typeof(SimpleObject)); - Assertion.AssertEquals("#Type", typeof(SimpleObject), (Type)objReturn); + Assert.AreEqual(typeof(SimpleObject), (Type)objReturn, "#Type"); objReturn = Serialize(obj.GetType().Assembly); - Assertion.AssertEquals("#Assembly", obj.GetType().Assembly, objReturn); + Assert.AreEqual(obj.GetType().Assembly, objReturn, "#Assembly"); } public static bool CheckArray(object objTest, object objReturn) { Array objTestAsArray = objTest as Array; Array objReturnAsArray = objReturn as Array; - Assertion.Assert("#Not an Array "+objTest, objReturnAsArray != null); - Assertion.AssertEquals("#Different lengths "+objTest, objTestAsArray.Length, objReturnAsArray.Length); - + Assert.IsTrue(objReturnAsArray != null, "#Not an Array "+objTest); + Assert.AreEqual(objTestAsArray.Length, objReturnAsArray.Length, "#Different lengths "+objTest); + IEnumerator iEnum = objReturnAsArray.GetEnumerator(); iEnum.Reset(); object obj2; foreach(object obj1 in objTestAsArray) { iEnum.MoveNext(); obj2 = iEnum.Current; - Assertion.AssertEquals("#The content of the 2 arrays is different", obj1, obj2); + Assert.AreEqual(obj1, obj2, "#The content of the 2 arrays is different"); } return true; @@ -315,9 +315,9 @@ namespace MonoTests.System.Runtime.Serialization.Formatters.Soap { MoreComplexObject objReturn; MoreComplexObject objTest = new MoreComplexObject(); objReturn = (MoreComplexObject) Serialize(objTest); - Assertion.AssertEquals("#Equals", objTest, objReturn); + Assert.AreEqual(objTest, objReturn, "#Equals"); objReturn.OnTrucEvent("bidule"); - Assertion.AssertEquals("#dlg", "bidule", objReturn.ObjString); + Assert.AreEqual("bidule", objReturn.ObjString, "#dlg"); } [Test] @@ -333,9 +333,9 @@ namespace MonoTests.System.Runtime.Serialization.Formatters.Soap { _soapFormatterDeserializer.Binder = new Version1ToVersion2Binder(); objReturn = _soapFormatterDeserializer.Deserialize(stream); - Assertion.AssertEquals("#Version1 Version2", "Version2", objReturn.GetType().Name); - Assertion.AssertEquals("#_value", 123, ((Version2) objReturn)._value); - Assertion.AssertEquals("#_foo", "Default value", ((Version2) objReturn)._foo); + Assert.AreEqual("Version2", objReturn.GetType().Name, "#Version1 Version2"); + Assert.AreEqual(123, ((Version2) objReturn)._value, "#_value"); + Assert.AreEqual("Default value", ((Version2) objReturn)._foo, "#_foo"); } [Test] @@ -360,17 +360,17 @@ namespace MonoTests.System.Runtime.Serialization.Formatters.Soap { sf.TopObject = t; t = (SoapMessage) sf.Deserialize (ms); - Assertion.AssertNotNull ("#1", t.Headers[0].Value); - Assertion.AssertEquals ("#2", t.Headers[0].Value.GetType (), typeof(Type[])); + Assert.IsNotNull (t.Headers[0].Value, "#1"); + Assert.AreEqual (t.Headers[0].Value.GetType (), typeof(Type[]), "#2"); Type[] ts = (Type[]) t.Headers[0].Value; - Assertion.AssertEquals ("#3", 2, ts.Length); - Assertion.AssertNotNull ("#4", ts[0]); - Assertion.AssertNotNull ("#5", ts[1]); + Assert.AreEqual (2, ts.Length, "#3"); + Assert.IsNotNull (ts[0], "#4"); + Assert.IsNotNull (ts[1], "#5"); Console.WriteLine ("PPP:" + ts[0].GetType()); - Assertion.AssertEquals ("#6", typeof(string), ts[0]); - Assertion.AssertEquals ("#7", typeof(SignatureTest[]), ts[1]); + Assert.AreEqual (typeof(string), ts[0], "#6"); + Assert.AreEqual (typeof(SignatureTest[]), ts[1], "#7"); } [Test] @@ -398,14 +398,14 @@ namespace MonoTests.System.Runtime.Serialization.Formatters.Soap { public void OnDeserialization (StreamingContext context) { var ci = Thread.CurrentThread.CurrentCulture; - Assertion.AssertEquals("#1", "German (Germany)", ci.EnglishName); + Assert.AreEqual("German (Germany)", ci.EnglishName, "#1"); } [OnSerialized] public void OnSerialized (StreamingContext context) { var ci = Thread.CurrentThread.CurrentCulture; - Assertion.AssertEquals("#2", "German (Germany)", ci.EnglishName); + Assert.AreEqual("German (Germany)", ci.EnglishName, "#2"); } } } diff --git a/mcs/class/System.Runtime.Serialization/Assembly/AssemblyInfo.cs b/mcs/class/System.Runtime.Serialization/Assembly/AssemblyInfo.cs index bc2dc31dae..5995195a22 100644 --- a/mcs/class/System.Runtime.Serialization/Assembly/AssemblyInfo.cs +++ b/mcs/class/System.Runtime.Serialization/Assembly/AssemblyInfo.cs @@ -55,7 +55,7 @@ using System.Runtime.InteropServices; [assembly: NeutralResourcesLanguage ("en-US")] [assembly: CLSCompliant (true)] [assembly: AssemblyDelaySign (true)] -#if NET_2_1 +#if MOBILE [assembly: AssemblyKeyFile ("../silverlight.pub")] #else [assembly: AssemblyKeyFile ("../ecma.pub")] diff --git a/mcs/class/System.Runtime.Serialization/Makefile b/mcs/class/System.Runtime.Serialization/Makefile index f95de7c2fe..07cd917a6a 100644 --- a/mcs/class/System.Runtime.Serialization/Makefile +++ b/mcs/class/System.Runtime.Serialization/Makefile @@ -5,7 +5,7 @@ include ../../build/rules.make RESOURCE_FILES = LIBRARY = System.Runtime.Serialization.dll -LIB_REFS = System System.Xml System.Core System.ServiceModel.Internals SMDiagnostics +LIB_REFS = System System.Xml System.Core System.ServiceModel.Internals LIB_MCS_FLAGS = \ -unsafe \ -d:NO_DYNAMIC_CODEGEN \ @@ -14,7 +14,7 @@ LIB_MCS_FLAGS = \ TXT_RESOURCE_STRINGS = ../referencesource/System.Runtime.Serialization/System.Runtime.Serialization.txt ifneq (2.1, $(FRAMEWORK_VERSION)) -LIB_REFS += System.Data System.Configuration +LIB_REFS += System.Data System.Configuration SMDiagnostics LIB_MCS_FLAGS += /d:NET_3_0 else LIB_MCS_FLAGS += /d:NO_CONFIGURATION /d:NO_SECURITY_ATTRIBUTES /d:NO_CODEDOM /d:NO_DESKTOP_SECURITY diff --git a/mcs/class/System.Runtime.Serialization/ReferenceSources/LocalAppContextSwitches.cs b/mcs/class/System.Runtime.Serialization/ReferenceSources/LocalAppContextSwitches.cs new file mode 100644 index 0000000000..ad8837615e --- /dev/null +++ b/mcs/class/System.Runtime.Serialization/ReferenceSources/LocalAppContextSwitches.cs @@ -0,0 +1,7 @@ +namespace System +{ + static class LocalAppContextSwitches + { + public static readonly bool DoNotUseTimeZoneInfo = false; + } +} \ No newline at end of file diff --git a/mcs/class/System.Runtime.Serialization/ReferenceSources/SchemaExporter_mobile.cs b/mcs/class/System.Runtime.Serialization/ReferenceSources/SchemaExporter_mobile.cs index aa55440219..19da4ee223 100644 --- a/mcs/class/System.Runtime.Serialization/ReferenceSources/SchemaExporter_mobile.cs +++ b/mcs/class/System.Runtime.Serialization/ReferenceSources/SchemaExporter_mobile.cs @@ -10,7 +10,6 @@ namespace System.Runtime.Serialization using System.IO; using System.Reflection; using System.Runtime.Diagnostics; - using System.ServiceModel.Diagnostics; using System.Security; using System.Xml; using System.Xml.Schema; @@ -56,6 +55,11 @@ namespace System.Runtime.Serialization return false; } + internal static void AddDefaultXmlType(XmlSchemaSet schemas, string localName, string ns) + { + throw new NotImplementedException(); + } + static bool InvokeSchemaProviderMethod(Type clrType, XmlSchemaSet schemas, out XmlQualifiedName stableName, out XmlSchemaType xsdType, out bool hasRoot) { xsdType = null; diff --git a/mcs/class/System.Runtime.Serialization/ReferenceSources/XsdDataContractExporter_mobile.cs b/mcs/class/System.Runtime.Serialization/ReferenceSources/XsdDataContractExporter_mobile.cs new file mode 100644 index 0000000000..bc1bf438e2 --- /dev/null +++ b/mcs/class/System.Runtime.Serialization/ReferenceSources/XsdDataContractExporter_mobile.cs @@ -0,0 +1,54 @@ +// +// XsdDataContractExporter_mobile.cs +// +// Authors: +// Alexander Köplinger +// +// Copyright (C) 2016 Xamarin Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Xml; +using System.Xml.Schema; + +namespace System.Runtime.Serialization +{ + public class XsdDataContractExporter + { + public XsdDataContractExporter () { throw new NotImplementedException (); } + public XsdDataContractExporter (XmlSchemaSet schemas) { throw new NotImplementedException (); } + public ExportOptions Options { get { throw new NotImplementedException (); } set { throw new NotImplementedException (); } } + public XmlSchemaSet Schemas { get { throw new NotImplementedException (); } } + public bool CanExport (ICollection assemblies) { throw new NotImplementedException ();} + public bool CanExport (ICollection types) { throw new NotImplementedException (); } + public bool CanExport (Type type) { throw new NotImplementedException (); } + public void Export (ICollection assemblies) { throw new NotImplementedException (); } + public void Export (ICollection types) { throw new NotImplementedException (); } + public void Export (Type type) { throw new NotImplementedException (); } + public XmlQualifiedName GetRootElementName (Type type) { throw new NotImplementedException (); } + public XmlSchemaType GetSchemaType (Type type) { throw new NotImplementedException (); } + public XmlQualifiedName GetSchemaTypeName (Type type) { throw new NotImplementedException (); } + } +} + diff --git a/mcs/class/System.Runtime.Serialization/System.Runtime.Serialization.dll.sources b/mcs/class/System.Runtime.Serialization/System.Runtime.Serialization.dll.sources index 9e790d522b..e889387651 100644 --- a/mcs/class/System.Runtime.Serialization/System.Runtime.Serialization.dll.sources +++ b/mcs/class/System.Runtime.Serialization/System.Runtime.Serialization.dll.sources @@ -4,6 +4,7 @@ Assembly/AssemblyInfo.cs ReferenceSources/DiagnosticUtility.cs ReferenceSources/FxTrace.cs +ReferenceSources/LocalAppContextSwitches.cs ReferenceSources/SR.cs ReferenceSources/SR.missing.cs ReferenceSources/XmlExceptionHelper.cs diff --git a/mcs/class/System.Runtime.Serialization/Test/System.Runtime.Serialization/DataContractResolverTest.cs b/mcs/class/System.Runtime.Serialization/Test/System.Runtime.Serialization/DataContractResolverTest.cs index 5ba3d4cd4b..cb12bd8d9c 100644 --- a/mcs/class/System.Runtime.Serialization/Test/System.Runtime.Serialization/DataContractResolverTest.cs +++ b/mcs/class/System.Runtime.Serialization/Test/System.Runtime.Serialization/DataContractResolverTest.cs @@ -33,7 +33,9 @@ using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; +#if !MOBILE_STATIC using System.Data; +#endif using System.IO; using System.Net; using System.Runtime.Serialization; diff --git a/mcs/class/System.Runtime.Serialization/Test/System.Runtime.Serialization/XmlObjectSerializerTest.cs b/mcs/class/System.Runtime.Serialization/Test/System.Runtime.Serialization/XmlObjectSerializerTest.cs index 03264c43f5..944b7f2eea 100755 --- a/mcs/class/System.Runtime.Serialization/Test/System.Runtime.Serialization/XmlObjectSerializerTest.cs +++ b/mcs/class/System.Runtime.Serialization/Test/System.Runtime.Serialization/XmlObjectSerializerTest.cs @@ -37,7 +37,9 @@ using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; +#if !MOBILE_STATIC using System.Data; +#endif using System.IO; using System.Linq; using System.Net; @@ -1475,6 +1477,7 @@ namespace MonoTests.System.Runtime.Serialization Assert.AreEqual (parent, parent.Child.Parent, "#2"); } +#if !MOBILE_STATIC [Test] public void IXmlSerializableCallConstructor () { @@ -1525,6 +1528,7 @@ namespace MonoTests.System.Runtime.Serialization var ds = (DataSet) x.ReadObject (r); } +#endif [Test] [ExpectedException (typeof (InvalidDataContractException))] // BaseConstraintType1 is neither DataContract nor Serializable. diff --git a/mcs/class/System.Runtime.Serialization/mobile_System.Runtime.Serialization.dll.sources b/mcs/class/System.Runtime.Serialization/mobile_System.Runtime.Serialization.dll.sources index c0c73b07ad..bc4259a994 100644 --- a/mcs/class/System.Runtime.Serialization/mobile_System.Runtime.Serialization.dll.sources +++ b/mcs/class/System.Runtime.Serialization/mobile_System.Runtime.Serialization.dll.sources @@ -2,4 +2,5 @@ #include ReferenceSource.common.sources ReferenceSources/SchemaExporter_mobile.cs +ReferenceSources/XsdDataContractExporter_mobile.cs ReferenceSources/SimplifiedCodeTypeReference.cs diff --git a/mcs/class/System.Security/Makefile b/mcs/class/System.Security/Makefile index 5c009acb56..145f30f4b6 100644 --- a/mcs/class/System.Security/Makefile +++ b/mcs/class/System.Security/Makefile @@ -2,8 +2,13 @@ thisdir = class/System.Security SUBDIRS = include ../../build/rules.make +ifndef NO_MONO_SECURITY +MONO_SECURITY_DLL=$(the_libdir_base)/Mono.Security.dll +MONO_SECURITY=Mono.Security +endif + LIBRARY = System.Security.dll -LIB_REFS = secxml/System bare/System.Xml Mono.Security +LIB_REFS = secxml/System bare/System.Xml $(MONO_SECURITY) LIB_MCS_FLAGS = -nowarn:618 \ -d:SECURITY_DEP \ -nowarn:414 @@ -22,7 +27,7 @@ EXTRA_DISTFILES = \ include ../../build/library.make -$(build_lib): $(secxml_libdir)/System.dll $(the_libdir_base)/Mono.Security.dll +$(build_lib): $(secxml_libdir)/System.dll $(MONO_SECURITY_DLL) $(secxml_libdir)/System.dll: (cd ../System; $(MAKE) $@) diff --git a/mcs/class/System.ServiceModel.Discovery/Assembly/AssemblyInfo.cs b/mcs/class/System.ServiceModel.Discovery/Assembly/AssemblyInfo.cs index f8ff5c399c..6a9d85f5c7 100644 --- a/mcs/class/System.ServiceModel.Discovery/Assembly/AssemblyInfo.cs +++ b/mcs/class/System.ServiceModel.Discovery/Assembly/AssemblyInfo.cs @@ -54,7 +54,7 @@ using System.Runtime.InteropServices; [assembly: ComVisible (false)] [assembly: AssemblyDelaySign (true)] -#if NET_2_1 +#if MOBILE [assembly: AssemblyKeyFile ("../silverlight.pub")] #else [assembly: AssemblyKeyFile("../winfx.pub")] diff --git a/mcs/class/System.ServiceModel.Internals/Assembly/AssemblyInfo.cs b/mcs/class/System.ServiceModel.Internals/Assembly/AssemblyInfo.cs index 80b1075ba7..a9f41b5c7f 100644 --- a/mcs/class/System.ServiceModel.Internals/Assembly/AssemblyInfo.cs +++ b/mcs/class/System.ServiceModel.Internals/Assembly/AssemblyInfo.cs @@ -40,7 +40,7 @@ using System.Runtime.InteropServices; [assembly: NeutralResourcesLanguage ("en-US")] [assembly: CLSCompliant (true)] [assembly: AssemblyDelaySign (true)] -#if NET_2_1 +#if MOBILE [assembly: AssemblyKeyFile ("../winfx.pub")] #else [assembly: AssemblyKeyFile ("../ecma.pub")] diff --git a/mcs/class/System.ServiceModel.Routing/Assembly/AssemblyInfo.cs b/mcs/class/System.ServiceModel.Routing/Assembly/AssemblyInfo.cs index 6dd4a86622..0202afecb9 100644 --- a/mcs/class/System.ServiceModel.Routing/Assembly/AssemblyInfo.cs +++ b/mcs/class/System.ServiceModel.Routing/Assembly/AssemblyInfo.cs @@ -54,7 +54,7 @@ using System.Runtime.InteropServices; [assembly: ComVisible (false)] [assembly: AssemblyDelaySign (true)] -#if NET_2_1 +#if MOBILE [assembly: AssemblyKeyFile ("../silverlight.pub")] #else [assembly: AssemblyKeyFile("../winfx.pub")] diff --git a/mcs/class/System.ServiceModel.Web/Assembly/AssemblyInfo.cs b/mcs/class/System.ServiceModel.Web/Assembly/AssemblyInfo.cs index a974b19de9..2e2baf595c 100644 --- a/mcs/class/System.ServiceModel.Web/Assembly/AssemblyInfo.cs +++ b/mcs/class/System.ServiceModel.Web/Assembly/AssemblyInfo.cs @@ -53,7 +53,7 @@ using System.Runtime.InteropServices; [assembly: ComVisible (false)] [assembly: AssemblyDelaySign (true)] -#if NET_2_1 +#if MOBILE [assembly: AssemblyInformationalVersion (Consts.FxFileVersion)] [assembly: AssemblyKeyFile ("../silverlight.pub")] #else @@ -61,7 +61,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyKeyFile("../winfx.pub")] #endif -#if NET_2_1 +#if MOBILE [assembly: InternalsVisibleTo ("System.Json, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] [assembly: InternalsVisibleTo ("System.ServiceModel.Web.Extensions, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] [assembly: InternalsVisibleTo ("System.Windows.Browser, PublicKey=00240000048000009400000006020000002400005253413100040000010001008D56C76F9E8649383049F383C44BE0EC204181822A6C31CF5EB7EF486944D032188EA1D3920763712CCB12D75FB77E9811149E6148E5D32FBAAB37611C1878DDC19E20EF135D0CB2CFF2BFEC3D115810C3D9069638FE4BE215DBF795861920E5AB6F7DB2E2CEEF136AC23D5DD2BF031700AEC232F6C6B1C785B4305C123B37AB")] diff --git a/mcs/class/System.ServiceModel.Web/System.ServiceModel.Channels/WebMessageEncoder.cs b/mcs/class/System.ServiceModel.Web/System.ServiceModel.Channels/WebMessageEncoder.cs index b438b10968..0cf2bc5778 100644 --- a/mcs/class/System.ServiceModel.Web/System.ServiceModel.Channels/WebMessageEncoder.cs +++ b/mcs/class/System.ServiceModel.Web/System.ServiceModel.Channels/WebMessageEncoder.cs @@ -47,7 +47,7 @@ namespace System.ServiceModel.Channels } public override string ContentType { -#if NET_2_1 +#if MOBILE get { return MediaType; } #else get { return MediaType + "; charset=" + source.WriteEncoding.HeaderName; } @@ -114,7 +114,7 @@ namespace System.ServiceModel.Channels break; case WebContentFormat.Json: // FIXME: is it safe/unsafe/required to keep XmlReader open? -#if NET_2_1 +#if MOBILE msg = Message.CreateMessage (MessageVersion.None, null, JsonReaderWriterFactory.CreateJsonReader (stream, source.ReaderQuotas)); #else msg = Message.CreateMessage (MessageVersion.None, null, JsonReaderWriterFactory.CreateJsonReader (stream, enc, source.ReaderQuotas, null)); @@ -174,7 +174,7 @@ namespace System.ServiceModel.Channels switch (GetContentFormat (message)) { case WebContentFormat.Xml: -#if NET_2_1 +#if MOBILE using (XmlWriter w = XmlDictionaryWriter.CreateDictionaryWriter (XmlWriter.Create (new StreamWriter (stream, source.WriteEncoding)))) message.WriteMessage (w); #else diff --git a/mcs/class/System.ServiceModel.Web/System.ServiceModel.Channels/WebMessageEncodingBindingElement.cs b/mcs/class/System.ServiceModel.Web/System.ServiceModel.Channels/WebMessageEncodingBindingElement.cs index 3049f2901e..c6a0b10755 100644 --- a/mcs/class/System.ServiceModel.Web/System.ServiceModel.Channels/WebMessageEncodingBindingElement.cs +++ b/mcs/class/System.ServiceModel.Web/System.ServiceModel.Channels/WebMessageEncodingBindingElement.cs @@ -34,7 +34,7 @@ using System.Xml; namespace System.ServiceModel.Channels { public sealed class WebMessageEncodingBindingElement -#if NET_2_1 +#if MOBILE : MessageEncodingBindingElement #else : MessageEncodingBindingElement, IWsdlExportExtension @@ -109,7 +109,7 @@ namespace System.ServiceModel.Channels return base.BuildChannelFactory (context); } -#if !NET_2_1 +#if !MOBILE [MonoTODO ("Why is it overriden?")] public override bool CanBuildChannelListener (BindingContext context) { @@ -146,7 +146,7 @@ namespace System.ServiceModel.Channels return context.GetInnerProperty (); } -#if !NET_2_1 && !XAMMAC_4_5 +#if !MOBILE && !XAMMAC_4_5 [MonoTODO] void IWsdlExportExtension.ExportContract (WsdlExporter exporter, WsdlContractConversionContext context) { diff --git a/mcs/class/System.ServiceModel.Web/System.ServiceModel.Description/WebHttpBehavior.cs b/mcs/class/System.ServiceModel.Web/System.ServiceModel.Description/WebHttpBehavior.cs index d207385c97..dc8915ff76 100644 --- a/mcs/class/System.ServiceModel.Web/System.ServiceModel.Description/WebHttpBehavior.cs +++ b/mcs/class/System.ServiceModel.Web/System.ServiceModel.Description/WebHttpBehavior.cs @@ -84,7 +84,7 @@ namespace System.ServiceModel.Description // clientRuntime.MessageInspectors.Add (something); } -#if !NET_2_1 && !XAMMAC_4_5 +#if !MOBILE && !XAMMAC_4_5 protected virtual void AddServerErrorHandlers (ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) { endpointDispatcher.ChannelDispatcher.ErrorHandlers.Add (new WebHttpErrorHandler ()); @@ -103,7 +103,7 @@ namespace System.ServiceModel.Description public virtual void ApplyDispatchBehavior (ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) { -#if NET_2_1 || XAMMAC_4_5 +#if MOBILE || XAMMAC_4_5 throw new NotImplementedException (); #else endpointDispatcher.DispatchRuntime.OperationSelector = GetOperationSelector (endpoint); @@ -146,7 +146,7 @@ namespace System.ServiceModel.Description } } -#if !NET_2_1 && !XAMMAC_4_5 +#if !MOBILE && !XAMMAC_4_5 internal class DispatchPairFormatter : IDispatchMessageFormatter { public DispatchPairFormatter (IDispatchMessageFormatter request, IDispatchMessageFormatter reply) @@ -185,7 +185,7 @@ namespace System.ServiceModel.Description return new WebMessageFormatter.ReplyClientFormatter (operationDescription, endpoint, GetQueryStringConverter (operationDescription), this); } -#if !NET_2_1 +#if !MOBILE protected virtual IDispatchMessageFormatter GetReplyDispatchFormatter (OperationDescription operationDescription, ServiceEndpoint endpoint) { return new WebMessageFormatter.ReplyDispatchFormatter (operationDescription, endpoint, GetQueryStringConverter (operationDescription), this); @@ -197,7 +197,7 @@ namespace System.ServiceModel.Description return new WebMessageFormatter.RequestClientFormatter (operationDescription, endpoint, GetQueryStringConverter (operationDescription), this); } -#if !NET_2_1 +#if !MOBILE protected virtual IDispatchMessageFormatter GetRequestDispatchFormatter (OperationDescription operationDescription, ServiceEndpoint endpoint) { return new WebMessageFormatter.RequestDispatchFormatter (operationDescription, endpoint, GetQueryStringConverter (operationDescription), this); @@ -287,7 +287,7 @@ namespace System.ServiceModel.Description throw new InvalidOperationException ("ManualAddressing in the transport binding element in the binding must be true for WebHttpBehavior"); } -#if !NET_2_1 +#if !MOBILE internal class WebHttpErrorHandler : IErrorHandler { public void ProvideFault (Exception error, MessageVersion version, ref Message fault) diff --git a/mcs/class/System.ServiceModel.Web/System.ServiceModel.Dispatcher/WebMessageFormatter.cs b/mcs/class/System.ServiceModel.Web/System.ServiceModel.Dispatcher/WebMessageFormatter.cs index 6fb3b86590..aa15907599 100644 --- a/mcs/class/System.ServiceModel.Web/System.ServiceModel.Dispatcher/WebMessageFormatter.cs +++ b/mcs/class/System.ServiceModel.Web/System.ServiceModel.Dispatcher/WebMessageFormatter.cs @@ -41,7 +41,7 @@ using System.ServiceModel.Web; using System.Text; using System.Xml; -#if NET_2_1 +#if MOBILE using XmlObjectSerializer = System.Object; #endif @@ -81,7 +81,7 @@ namespace System.ServiceModel.Dispatcher this.converter = converter; this.behavior = behavior; ApplyWebAttribute (); -#if !NET_2_1 +#if !MOBILE // This is a hack for WebScriptEnablingBehavior var jqc = converter as JsonQueryStringConverter; if (jqc != null) @@ -248,7 +248,7 @@ namespace System.ServiceModel.Dispatcher protected object ReadObjectBody (XmlObjectSerializer serializer, XmlReader reader) { -#if NET_2_1 +#if MOBILE return (serializer is DataContractJsonSerializer) ? ((DataContractJsonSerializer) serializer).ReadObject (reader) : ((DataContractSerializer) serializer).ReadObject (reader, true); @@ -283,7 +283,7 @@ namespace System.ServiceModel.Dispatcher } } -#if !NET_2_1 +#if !MOBILE internal class RequestDispatchFormatter : WebDispatchMessageFormatter { public RequestDispatchFormatter (OperationDescription operation, ServiceEndpoint endpoint, QueryStringConverter converter, WebHttpBehavior behavior) @@ -363,7 +363,7 @@ namespace System.ServiceModel.Dispatcher // FIXME: get encoding from somewhere hp.Headers ["Content-Type"] = mediaType + "; charset=utf-8"; -#if !NET_2_1 +#if !MOBILE if (WebOperationContext.Current != null) WebOperationContext.Current.OutgoingRequest.Apply (hp); #endif @@ -382,7 +382,7 @@ namespace System.ServiceModel.Dispatcher throw new ArgumentNullException ("parameters"); CheckMessageVersion (message.Version); -#if !NET_2_1 +#if !MOBILE if (OperationContext.Current != null) { // Set response in the context OperationContext.Current.IncomingMessage = message; @@ -423,7 +423,7 @@ namespace System.ServiceModel.Dispatcher object value; XmlObjectSerializer serializer; -#if !NET_2_1 +#if !MOBILE protected override BodyWriter OnCreateBufferedCopy (int maxBufferSize) { return new WrappedBodyWriter (value, serializer, name, ns, fmt); @@ -473,7 +473,7 @@ namespace System.ServiceModel.Dispatcher void WriteObject (XmlObjectSerializer serializer, XmlDictionaryWriter writer, object value) { if (serializer != null){ -#if NET_2_1 +#if MOBILE if (serializer is DataContractJsonSerializer) ((DataContractJsonSerializer) serializer).WriteObject (writer, value); else @@ -485,7 +485,7 @@ namespace System.ServiceModel.Dispatcher } } -#if !NET_2_1 +#if !MOBILE internal abstract class WebDispatchMessageFormatter : WebMessageFormatter, IDispatchMessageFormatter { protected WebDispatchMessageFormatter (OperationDescription operation, ServiceEndpoint endpoint, QueryStringConverter converter, WebHttpBehavior behavior) diff --git a/mcs/class/System.ServiceModel.Web/System.ServiceModel.Web/WebChannelFactory.cs b/mcs/class/System.ServiceModel.Web/System.ServiceModel.Web/WebChannelFactory.cs index bee02209a1..4a5289dd51 100644 --- a/mcs/class/System.ServiceModel.Web/System.ServiceModel.Web/WebChannelFactory.cs +++ b/mcs/class/System.ServiceModel.Web/System.ServiceModel.Web/WebChannelFactory.cs @@ -39,7 +39,7 @@ namespace System.ServiceModel.Web { public class WebChannelFactory : ChannelFactory { -#if !NET_2_1 +#if !MOBILE public WebChannelFactory () : base () { @@ -84,7 +84,7 @@ namespace System.ServiceModel.Web protected override void OnOpening () { -#if !NET_2_1 +#if !MOBILE if (Endpoint.Behaviors.Find () == null) Endpoint.Behaviors.Add (new WebHttpBehavior ()); #endif diff --git a/mcs/class/System.ServiceModel.Web/System.ServiceModel.Web/WebOperationContext.cs b/mcs/class/System.ServiceModel.Web/System.ServiceModel.Web/WebOperationContext.cs index dfec47afe0..a372b24c6b 100644 --- a/mcs/class/System.ServiceModel.Web/System.ServiceModel.Web/WebOperationContext.cs +++ b/mcs/class/System.ServiceModel.Web/System.ServiceModel.Web/WebOperationContext.cs @@ -31,7 +31,7 @@ using System.ServiceModel; using System.ServiceModel.Channels; using System.ServiceModel.Description; -#if NET_2_1 // Note that moonlight System.ServiceModel.Web.dll does not contain this class. +#if MOBILE // Note that moonlight System.ServiceModel.Web.dll does not contain this class. using IncomingWebRequestContext = System.Object; using OutgoingWebResponseContext = System.Object; #else @@ -44,11 +44,11 @@ using System.Xml.Serialization; namespace System.ServiceModel.Web { public class WebOperationContext -#if !NET_2_1 +#if !MOBILE : IExtension #endif { -#if !NET_2_1 +#if !MOBILE public static WebOperationContext Current { get { if (OperationContext.Current == null) @@ -75,13 +75,13 @@ namespace System.ServiceModel.Web outgoing_request = new OutgoingWebRequestContext (); incoming_response = new IncomingWebResponseContext (operation); -#if !NET_2_1 +#if !MOBILE incoming_request = new IncomingWebRequestContext (operation); outgoing_response = new OutgoingWebResponseContext (); #endif } -#if !NET_2_1 +#if !MOBILE public IncomingWebRequestContext IncomingRequest { get { return incoming_request; } } @@ -95,7 +95,7 @@ namespace System.ServiceModel.Web get { return outgoing_request; } } -#if !NET_2_1 +#if !MOBILE public OutgoingWebResponseContext OutgoingResponse { get { return outgoing_response; } } diff --git a/mcs/class/System.ServiceModel.Web/System.ServiceModel/WebHttpBinding.cs b/mcs/class/System.ServiceModel.Web/System.ServiceModel/WebHttpBinding.cs index 8eee88bb87..a182f4f519 100644 --- a/mcs/class/System.ServiceModel.Web/System.ServiceModel/WebHttpBinding.cs +++ b/mcs/class/System.ServiceModel.Web/System.ServiceModel/WebHttpBinding.cs @@ -31,7 +31,7 @@ using System.Linq; using System.ServiceModel.Channels; using System.Text; using System.Xml; -#if !NET_2_1 +#if !MOBILE using System.Configuration; using System.ServiceModel.Configuration; #endif @@ -52,7 +52,7 @@ namespace System.ServiceModel public WebHttpBinding (string configurationName) { -#if !NET_2_1 && !XAMMAC_4_5 +#if !MOBILE && !XAMMAC_4_5 BindingsSection bindingsSection = ConfigUtil.BindingsSection; WebHttpBindingElement el = (WebHttpBindingElement) bindingsSection ["webHttpBinding"].ConfiguredBindings.FirstOrDefault (c => c.Name == configurationName); if (el != null) { @@ -88,7 +88,7 @@ namespace System.ServiceModel get { return EnvelopeVersion.None; } } -#if !NET_2_1 && !XAMMAC_4_5 +#if !MOBILE && !XAMMAC_4_5 [DefaultValue (false)] public bool AllowCookies { get { return t.AllowCookies; } diff --git a/mcs/class/System.ServiceModel.Web/System.ServiceModel/WebHttpSecurity.cs b/mcs/class/System.ServiceModel.Web/System.ServiceModel/WebHttpSecurity.cs index 4effb2e71a..b7aefe52df 100644 --- a/mcs/class/System.ServiceModel.Web/System.ServiceModel/WebHttpSecurity.cs +++ b/mcs/class/System.ServiceModel.Web/System.ServiceModel/WebHttpSecurity.cs @@ -34,7 +34,7 @@ namespace System.ServiceModel public WebHttpSecurity () { // there is no public constructor for transport ... -#if !NET_2_1 +#if !MOBILE Transport = new BasicHttpBinding ().Security.Transport; #endif } diff --git a/mcs/class/System.ServiceModel/Assembly/AssemblyInfo.cs b/mcs/class/System.ServiceModel/Assembly/AssemblyInfo.cs index c13a103d20..f4779a1e60 100644 --- a/mcs/class/System.ServiceModel/Assembly/AssemblyInfo.cs +++ b/mcs/class/System.ServiceModel/Assembly/AssemblyInfo.cs @@ -54,7 +54,7 @@ using System.Runtime.InteropServices; [assembly: NeutralResourcesLanguage ("en-US")] [assembly: CLSCompliant (true)] [assembly: AssemblyDelaySign (true)] -#if NET_2_1 +#if MOBILE [assembly: AssemblyKeyFile ("../winfx.pub")] #else [assembly: AssemblyKeyFile ("../ecma.pub")] @@ -65,11 +65,11 @@ using System.Runtime.InteropServices; [assembly: ComVisible (false)] -#if NET_2_1 +#if MOBILE //[assembly: InternalsVisibleTo ("System.Xml.Serialization, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] #endif -#if !NET_2_1 +#if !MOBILE [assembly: InternalsVisibleTo ("System.ServiceModel.Web, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] [assembly: InternalsVisibleTo ("System.ServiceModel.Routing, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] [assembly: InternalsVisibleTo ("System.ServiceModel.Discovery, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] // AnnouncementChannelEndpointElementCollection requires it. @@ -82,4 +82,13 @@ using System.Runtime.InteropServices; #endif +#if !MOBILE +[assembly: TypeForwardedTo (typeof (System.ServiceModel.Security.BinarySecretKeyIdentifierClause))] +[assembly: TypeForwardedTo (typeof (System.ServiceModel.Security.KeyNameIdentifierClause))] +[assembly: TypeForwardedTo (typeof (System.ServiceModel.Security.SecurityContextKeyIdentifierClause))] +[assembly: TypeForwardedTo (typeof (System.ServiceModel.Security.X509CertificateValidationMode))] +[assembly: TypeForwardedTo (typeof (System.ServiceModel.Security.Tokens.BinarySecretSecurityToken))] +[assembly: TypeForwardedTo (typeof (System.ServiceModel.Security.Tokens.WrappedKeySecurityToken))] + +#endif diff --git a/mcs/class/System.ServiceModel/Mono.CodeGeneration/CodeModule.cs b/mcs/class/System.ServiceModel/Mono.CodeGeneration/CodeModule.cs index ff8251f181..f7031432d8 100644 --- a/mcs/class/System.ServiceModel/Mono.CodeGeneration/CodeModule.cs +++ b/mcs/class/System.ServiceModel/Mono.CodeGeneration/CodeModule.cs @@ -40,7 +40,7 @@ namespace Mono.CodeGeneration AppDomain myDomain = System.Threading.Thread.GetDomain(); AssemblyName myAsmName = new AssemblyName(); myAsmName.Name = name; -#if NET_2_1 +#if MOBILE AssemblyBuilder myAsmBuilder = myDomain.DefineDynamicAssembly (myAsmName, AssemblyBuilderAccess.Run); #else AssemblyBuilder myAsmBuilder = myDomain.DefineDynamicAssembly (myAsmName, AssemblyBuilderAccess.RunAndSave); diff --git a/mcs/class/System.ServiceModel/Mono.Security.Protocol.Tls/DebugHelper.cs b/mcs/class/System.ServiceModel/Mono.Security.Protocol.Tls/DebugHelper.cs index 70b25bd1d5..ff122878c9 100644 --- a/mcs/class/System.ServiceModel/Mono.Security.Protocol.Tls/DebugHelper.cs +++ b/mcs/class/System.ServiceModel/Mono.Security.Protocol.Tls/DebugHelper.cs @@ -36,7 +36,7 @@ namespace Mono.Security.Protocol.Tls { if (!isInitialized) { -#if !NET_2_1 +#if !MOBILE Debug.Listeners.Add(new TextWriterTraceListener(Console.Out)); // Debug.Listeners.Add(new TextWriterTraceListener(@"c:\ssl.log")); Debug.AutoFlush = true; diff --git a/mcs/class/System.ServiceModel/System.ServiceModel.Channels/BinaryMessageEncodingBindingElement.cs b/mcs/class/System.ServiceModel/System.ServiceModel.Channels/BinaryMessageEncodingBindingElement.cs index 32ab72a9cb..b89e21a552 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel.Channels/BinaryMessageEncodingBindingElement.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel.Channels/BinaryMessageEncodingBindingElement.cs @@ -94,7 +94,7 @@ namespace System.ServiceModel.Channels return base.BuildChannelFactory (context); } -#if !NET_2_1 +#if !MOBILE public override IChannelListener BuildChannelListener ( BindingContext context) { @@ -131,7 +131,7 @@ namespace System.ServiceModel.Channels return new BinaryMessageEncoderFactory (this); } -#if !NET_2_1 && !XAMMAC_4_5 +#if !MOBILE && !XAMMAC_4_5 [MonoTODO] void IWsdlExportExtension.ExportContract (WsdlExporter exporter, WsdlContractConversionContext context) diff --git a/mcs/class/System.ServiceModel/System.ServiceModel.Channels/Binding.cs b/mcs/class/System.ServiceModel/System.ServiceModel.Channels/Binding.cs index 12c8ed6af0..9e66babb71 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel.Channels/Binding.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel.Channels/Binding.cs @@ -133,7 +133,7 @@ namespace System.ServiceModel.Channels return CreateContext (parameters).BuildInnerChannelFactory (); } -#if !NET_2_1 +#if !MOBILE public virtual IChannelListener BuildChannelListener ( Uri listenUriBaseAddress, @@ -267,7 +267,7 @@ namespace System.ServiceModel.Channels return CreateContext (parameters).CanBuildInnerChannelFactory (); } -#if !NET_2_1 +#if !MOBILE public bool CanBuildChannelListener ( params object [] parameters) where TChannel : class, IChannel diff --git a/mcs/class/System.ServiceModel/System.ServiceModel.Channels/BindingContext.cs b/mcs/class/System.ServiceModel/System.ServiceModel.Channels/BindingContext.cs index 601c2c07d9..2fecf22646 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel.Channels/BindingContext.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel.Channels/BindingContext.cs @@ -149,7 +149,7 @@ namespace System.ServiceModel.Channels return ctx.DequeueBindingElement ().BuildChannelFactory (ctx); } -#if !NET_2_1 +#if !MOBILE public IChannelListener BuildInnerChannelListener () where TChannel : class, IChannel @@ -168,7 +168,7 @@ namespace System.ServiceModel.Channels return ctx.DequeueBindingElement ().CanBuildChannelFactory (ctx); } -#if !NET_2_1 +#if !MOBILE public bool CanBuildInnerChannelListener () where TChannel : class, IChannel { diff --git a/mcs/class/System.ServiceModel/System.ServiceModel.Channels/BindingElement.cs b/mcs/class/System.ServiceModel/System.ServiceModel.Channels/BindingElement.cs index d9808b0f30..be628e07cc 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel.Channels/BindingElement.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel.Channels/BindingElement.cs @@ -52,7 +52,7 @@ namespace System.ServiceModel.Channels return context.BuildInnerChannelFactory (); } -#if !NET_2_1 +#if !MOBILE public virtual IChannelListener BuildChannelListener ( BindingContext context) @@ -70,7 +70,7 @@ namespace System.ServiceModel.Channels return context.CanBuildInnerChannelFactory (); } -#if !NET_2_1 +#if !MOBILE public virtual bool CanBuildChannelListener ( BindingContext context) where TChannel : class, IChannel diff --git a/mcs/class/System.ServiceModel/System.ServiceModel.Channels/ChannelManagerBase.cs b/mcs/class/System.ServiceModel/System.ServiceModel.Channels/ChannelManagerBase.cs index 7541ca08a0..3be8fa8056 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel.Channels/ChannelManagerBase.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel.Channels/ChannelManagerBase.cs @@ -65,7 +65,7 @@ namespace System.ServiceModel.Channels var f = mbe.CreateMessageEncoderFactory (); var t = typeof (TChannel); if (t == typeof (IRequestSessionChannel) || -#if !NET_2_1 +#if !MOBILE t == typeof (IReplySessionChannel) || #endif t == typeof (IInputSessionChannel) || diff --git a/mcs/class/System.ServiceModel/System.ServiceModel.Channels/FaultConverter.cs b/mcs/class/System.ServiceModel/System.ServiceModel.Channels/FaultConverter.cs index b8c5b4d35d..a2918a06e6 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel.Channels/FaultConverter.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel.Channels/FaultConverter.cs @@ -137,7 +137,7 @@ namespace System.ServiceModel.Channels OperationContext ctx = OperationContext.Current; // FIXME: support more fault code depending on the exception type. -#if !NET_2_1 && !XAMMAC_4_5 +#if !MOBILE && !XAMMAC_4_5 // FIXME: set correct fault reason. if (ctx != null && ctx.EndpointDispatcher.ChannelDispatcher.IncludeExceptionDetailInFaults) { ExceptionDetail detail = new ExceptionDetail (error); diff --git a/mcs/class/System.ServiceModel/System.ServiceModel.Channels/HttpRequestChannel.cs b/mcs/class/System.ServiceModel/System.ServiceModel.Channels/HttpRequestChannel.cs index 19faf78c14..4e4d73f9fb 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel.Channels/HttpRequestChannel.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel.Channels/HttpRequestChannel.cs @@ -56,7 +56,7 @@ namespace System.ServiceModel.Channels get { return source.MessageEncoder; } } -#if NET_2_1 +#if MOBILE public override T GetProperty () { if (typeof (T) == typeof (IHttpCookieContainerManager)) @@ -126,6 +126,7 @@ namespace System.ServiceModel.Channels } web_request.Timeout = (int) timeout.TotalMilliseconds; + web_request.KeepAlive = httpbe.KeepAliveEnabled; // There is no SOAP Action/To header when AddressingVersion is None. if (message.Version.Envelope.Equals (EnvelopeVersion.Soap11) || @@ -189,7 +190,7 @@ namespace System.ServiceModel.Channels suppressEntityBody = true; } -#if !NET_2_1 +#if !MOBILE if (source.ClientCredentials != null) { var cred = source.ClientCredentials; if ((cred.ClientCertificate != null) && (cred.ClientCertificate.Certificate != null)) @@ -476,7 +477,7 @@ namespace System.ServiceModel.Channels // FIXME: Do we need to use the timeout? If so, what happens when the timeout is reached. // Is the current request cancelled and an exception thrown? If so we need to pass the // exception to the Complete () method and allow the result to complete 'normally'. -#if NET_2_1 +#if MOBILE // neither Moonlight nor MonoTouch supports contexts (WaitOne default to false) bool result = AsyncWaitHandle.WaitOne (Timeout); #else diff --git a/mcs/class/System.ServiceModel/System.ServiceModel.Channels/HttpTransportBindingElement.cs b/mcs/class/System.ServiceModel/System.ServiceModel.Channels/HttpTransportBindingElement.cs index f9778c782a..d3c70970ad 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel.Channels/HttpTransportBindingElement.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel.Channels/HttpTransportBindingElement.cs @@ -32,7 +32,7 @@ using System.Net; using System.Net.Security; using System.Security.Authentication.ExtendedProtection; using System.ServiceModel.Channels; -#if !NET_2_1 +#if !MOBILE using System.ServiceModel.Channels.Http; #endif using System.ServiceModel.Description; @@ -185,7 +185,7 @@ namespace System.ServiceModel.Channels return typeof (TChannel) == typeof (IRequestChannel); } -#if !NET_2_1 && !XAMMAC_4_5 +#if !MOBILE && !XAMMAC_4_5 public override bool CanBuildChannelListener ( BindingContext context) { @@ -201,7 +201,7 @@ namespace System.ServiceModel.Channels return new HttpChannelFactory (this, context); } -#if !NET_2_1 && !XAMMAC_4_5 +#if !MOBILE && !XAMMAC_4_5 internal static object ListenerBuildLock = new object (); public override IChannelListener BuildChannelListener ( @@ -242,7 +242,7 @@ namespace System.ServiceModel.Channels set { throw new NotImplementedException (); } } -#if !NET_2_1 && !XAMMAC_4_5 +#if !MOBILE && !XAMMAC_4_5 void IPolicyExportExtension.ExportPolicy ( MetadataExporter exporter, PolicyConversionContext context) diff --git a/mcs/class/System.ServiceModel/System.ServiceModel.Channels/HttpsTransportBindingElement.cs b/mcs/class/System.ServiceModel/System.ServiceModel.Channels/HttpsTransportBindingElement.cs index 38ae7b2c95..3d890b9514 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel.Channels/HttpsTransportBindingElement.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel.Channels/HttpsTransportBindingElement.cs @@ -68,7 +68,7 @@ namespace System.ServiceModel.Channels return base.BuildChannelFactory (context); } -#if !NET_2_1 && !XAMMAC_4_5 +#if !MOBILE && !XAMMAC_4_5 [MonoTODO] public override IChannelListener BuildChannelListener ( @@ -83,7 +83,7 @@ namespace System.ServiceModel.Channels return new HttpsTransportBindingElement (this); } -#if !NET_2_1 && !XAMMAC_4_5 +#if !MOBILE && !XAMMAC_4_5 public XmlElement GetTransportTokenAssertion () { var doc = new XmlDocument (); diff --git a/mcs/class/System.ServiceModel/System.ServiceModel.Channels/LocalClientSecuritySettings.cs b/mcs/class/System.ServiceModel/System.ServiceModel.Channels/LocalClientSecuritySettings.cs index ef58f946df..05fc00512b 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel.Channels/LocalClientSecuritySettings.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel.Channels/LocalClientSecuritySettings.cs @@ -33,7 +33,7 @@ namespace System.ServiceModel.Channels [MonoTODO] public sealed class LocalClientSecuritySettings { -#if !NET_2_1 +#if !MOBILE bool cache_cookies = true; int cookie_renewal = 60; bool detect_replays = true; @@ -56,7 +56,7 @@ namespace System.ServiceModel.Channels public TimeSpan ReplayWindow { get; set; } public TimeSpan TimestampValidityDuration { get; set; } -#if !NET_2_1 +#if !MOBILE public bool CacheCookies { get { return cache_cookies; } set { cache_cookies = value; } diff --git a/mcs/class/System.ServiceModel/System.ServiceModel.Channels/MessageBufferImpl.cs b/mcs/class/System.ServiceModel/System.ServiceModel.Channels/MessageBufferImpl.cs index 4f3d010088..caebb3a7eb 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel.Channels/MessageBufferImpl.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel.Channels/MessageBufferImpl.cs @@ -89,7 +89,7 @@ namespace System.ServiceModel.Channels } } -#if !NET_2_1 +#if !MOBILE internal class XPathMessageBuffer : MessageBuffer { IXPathNavigable source; diff --git a/mcs/class/System.ServiceModel/System.ServiceModel.Channels/MessageEncodingBindingElement.cs b/mcs/class/System.ServiceModel/System.ServiceModel.Channels/MessageEncodingBindingElement.cs index e9e8ddef3a..9a40e499eb 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel.Channels/MessageEncodingBindingElement.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel.Channels/MessageEncodingBindingElement.cs @@ -59,7 +59,7 @@ namespace System.ServiceModel.Channels return context.GetInnerProperty (); } -#if !NET_2_1 && !XAMMAC_4_5 +#if !MOBILE && !XAMMAC_4_5 [MonoTODO] protected virtual void OnImportPolicy (XmlElement assertion, MessageVersion messageVersion, diff --git a/mcs/class/System.ServiceModel/System.ServiceModel.Channels/MessageHeader.cs b/mcs/class/System.ServiceModel/System.ServiceModel.Channels/MessageHeader.cs index baf4d8b356..4769523848 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel.Channels/MessageHeader.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel.Channels/MessageHeader.cs @@ -209,7 +209,7 @@ namespace System.ServiceModel.Channels { bool is_ref, must_understand, relay; string actor; -#if NET_2_1 +#if MOBILE string body; #else // This is required to completely clone body xml that @@ -238,7 +238,7 @@ namespace System.ServiceModel.Channels local_name = reader.LocalName; namespace_uri = reader.NamespaceURI; -#if NET_2_1 +#if MOBILE body = reader.ReadOuterXml (); #else body = new XmlDocument (); @@ -250,7 +250,7 @@ namespace System.ServiceModel.Channels public XmlReader CreateReader () { -#if NET_2_1 +#if MOBILE var reader = XmlReader.Create (new StringReader (body)); #else var reader = new XmlNodeReader (body); diff --git a/mcs/class/System.ServiceModel/System.ServiceModel.Channels/MessageHeaders.cs b/mcs/class/System.ServiceModel/System.ServiceModel.Channels/MessageHeaders.cs index c813ff318e..c08ef8697d 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel.Channels/MessageHeaders.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel.Channels/MessageHeaders.cs @@ -327,7 +327,7 @@ namespace System.ServiceModel.Channels return; if (MessageVersion.Addressing.Equals (AddressingVersion.WSAddressing10)) Add (MessageHeader.CreateHeader (name, ns, EndpointAddress10.FromEndpointAddress (address))); -#if !NET_2_1 +#if !MOBILE else if (MessageVersion.Addressing.Equals (AddressingVersion.WSAddressingAugust2004)) Add (MessageHeader.CreateHeader (name, ns, EndpointAddressAugust2004.FromEndpointAddress (address))); #endif diff --git a/mcs/class/System.ServiceModel/System.ServiceModel.Channels/MessageProperties.cs b/mcs/class/System.ServiceModel/System.ServiceModel.Channels/MessageProperties.cs index db1c8fd46b..f46f2ffe2c 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel.Channels/MessageProperties.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel.Channels/MessageProperties.cs @@ -98,7 +98,7 @@ namespace System.ServiceModel.Channels } } -#if !NET_2_1 +#if !MOBILE public SecurityMessageProperty Security { get { return (SecurityMessageProperty) this ["Security"]; } set { this ["Security"] = value; } diff --git a/mcs/class/System.ServiceModel/System.ServiceModel.Channels/ReliableSessionBindingElement.cs b/mcs/class/System.ServiceModel/System.ServiceModel.Channels/ReliableSessionBindingElement.cs index 422e6e92c1..1e3bf6cbef 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel.Channels/ReliableSessionBindingElement.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel.Channels/ReliableSessionBindingElement.cs @@ -69,7 +69,7 @@ namespace System.ServiceModel.Channels throw new NotImplementedException (); } -#if !NET_2_1 +#if !MOBILE [MonoTODO] public override IChannelListener BuildChannelListener (BindingContext context) { diff --git a/mcs/class/System.ServiceModel/System.ServiceModel.Channels/SecurityBindingElement.cs b/mcs/class/System.ServiceModel/System.ServiceModel.Channels/SecurityBindingElement.cs index 22c56cb785..ffcc6110be 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel.Channels/SecurityBindingElement.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel.Channels/SecurityBindingElement.cs @@ -30,7 +30,7 @@ using System.Collections.ObjectModel; using System.ServiceModel.Description; using System.ServiceModel.Channels; using System.ServiceModel.Security; -#if !NET_2_1 && !XAMMAC_4_5 +#if !MOBILE && !XAMMAC_4_5 using System.ServiceModel.Channels.Security; using System.IdentityModel.Selectors; using System.IdentityModel.Tokens; @@ -46,7 +46,7 @@ namespace System.ServiceModel.Channels { MessageSecurityVersion = MessageSecurityVersion.Default; endpoint = new SupportingTokenParameters (); -#if !NET_2_1 && !XAMMAC_4_5 +#if !MOBILE && !XAMMAC_4_5 DefaultAlgorithmSuite = SecurityAlgorithmSuite.Default; KeyEntropyMode = SecurityKeyEntropyMode.CombinedEntropy; operation = new Dictionary (); @@ -63,7 +63,7 @@ namespace System.ServiceModel.Channels security_header_layout = other.security_header_layout; msg_security_version = other.msg_security_version; endpoint = other.endpoint.Clone (); -#if !NET_2_1 && !XAMMAC_4_5 +#if !MOBILE && !XAMMAC_4_5 alg_suite = other.alg_suite; key_entropy_mode = other.key_entropy_mode; opt_endpoint = other.opt_endpoint.Clone (); @@ -83,7 +83,7 @@ namespace System.ServiceModel.Channels MessageSecurityVersion msg_security_version; SupportingTokenParameters endpoint; -#if !NET_2_1 && !XAMMAC_4_5 +#if !MOBILE && !XAMMAC_4_5 SecurityAlgorithmSuite alg_suite; SecurityKeyEntropyMode key_entropy_mode; SupportingTokenParameters opt_endpoint; @@ -109,7 +109,7 @@ namespace System.ServiceModel.Channels get { return endpoint; } } -#if !NET_2_1 && !XAMMAC_4_5 +#if !MOBILE && !XAMMAC_4_5 public SecurityAlgorithmSuite DefaultAlgorithmSuite { get { return alg_suite; } set { alg_suite = value; } @@ -140,7 +140,7 @@ namespace System.ServiceModel.Channels [MonoTODO ("Implement for TransportSecurityBindingElement")] public override bool CanBuildChannelFactory (BindingContext context) { -#if NET_2_1 || XAMMAC_4_5 +#if MOBILE || XAMMAC_4_5 // not sure this should be like this, but there isn't Symmetric/Asymmetric elements in 2.1 anyways. return context.CanBuildInnerChannelFactory (); #else @@ -185,7 +185,7 @@ namespace System.ServiceModel.Channels protected abstract IChannelFactory BuildChannelFactoryCore (BindingContext context); -#if !NET_2_1 && !XAMMAC_4_5 +#if !MOBILE && !XAMMAC_4_5 [MonoTODO ("Implement for TransportSecurityBindingElement")] public override bool CanBuildChannelListener (BindingContext context) { @@ -272,7 +272,7 @@ namespace System.ServiceModel.Channels #endif #region Factory methods -#if !NET_2_1 && !XAMMAC_4_5 +#if !MOBILE && !XAMMAC_4_5 public static SymmetricSecurityBindingElement CreateAnonymousForCertificateBindingElement () { @@ -548,7 +548,7 @@ namespace System.ServiceModel.Channels SecurityBindingElement bootstrapSecurity, bool requireCancellation, ChannelProtectionRequirements bootstrapProtectionRequirements) { -#if !NET_2_1 && !XAMMAC_4_5 +#if !MOBILE && !XAMMAC_4_5 SymmetricSecurityBindingElement be = new SymmetricSecurityBindingElement (); be.ProtectionTokenParameters = @@ -565,14 +565,14 @@ namespace System.ServiceModel.Channels CreateUserNameOverTransportBindingElement () { var be = new TransportSecurityBindingElement (); -#if !NET_2_1 && !XAMMAC_4_5 // FIXME: there should be whatever else to do for 2.1 instead. +#if !MOBILE && !XAMMAC_4_5 // FIXME: there should be whatever else to do for 2.1 instead. be.EndpointSupportingTokenParameters.SignedEncrypted.Add (new UserNameSecurityTokenParameters ()); #endif return be; } #endregion -#if !NET_2_1 && !XAMMAC_4_5 +#if !MOBILE && !XAMMAC_4_5 // It seems almost internal, hardcoded like this (I tried // custom parameters that sets IssuedTokenSecurityTokenParameters // like below ones, but that didn't trigger this method). diff --git a/mcs/class/System.ServiceModel/System.ServiceModel.Channels/TextMessageEncodingBindingElement.cs b/mcs/class/System.ServiceModel/System.ServiceModel.Channels/TextMessageEncodingBindingElement.cs index 2330e8134c..2b27840eec 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel.Channels/TextMessageEncodingBindingElement.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel.Channels/TextMessageEncodingBindingElement.cs @@ -105,7 +105,7 @@ namespace System.ServiceModel.Channels return base.BuildChannelFactory (context); } -#if !NET_2_1 +#if !MOBILE public override IChannelListener BuildChannelListener ( BindingContext context) { @@ -143,7 +143,7 @@ namespace System.ServiceModel.Channels return new TextMessageEncoderFactory (this); } -#if !NET_2_1 && !XAMMAC_4_5 +#if !MOBILE && !XAMMAC_4_5 [MonoTODO] protected override void OnImportPolicy (XmlElement assertion, MessageVersion messageVersion, diff --git a/mcs/class/System.ServiceModel/System.ServiceModel.Channels/TransportBindingElement.cs b/mcs/class/System.ServiceModel/System.ServiceModel.Channels/TransportBindingElement.cs index c1326c7cf9..17f3a1c36d 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel.Channels/TransportBindingElement.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel.Channels/TransportBindingElement.cs @@ -81,7 +81,7 @@ namespace System.ServiceModel.Channels q.MaxStringContentLength = (int) MaxReceivedMessageSize; return (T) (object) q; } -#if !NET_2_1 +#if !MOBILE if (typeof (T) == typeof (ChannelProtectionRequirements)) // blank one, basically it should not be used // for any secure channels ( @@ -92,7 +92,7 @@ namespace System.ServiceModel.Channels return context.GetInnerProperty (); } -#if !NET_2_1 && !XAMMAC_4_5 +#if !MOBILE && !XAMMAC_4_5 internal static XmlElement CreateTransportBinding (XmlElement transportToken) { var doc = new XmlDocument (); diff --git a/mcs/class/System.ServiceModel/System.ServiceModel.Channels/TransportSecurityBindingElement.cs b/mcs/class/System.ServiceModel/System.ServiceModel.Channels/TransportSecurityBindingElement.cs index e29e6f0c55..60ff280d32 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel.Channels/TransportSecurityBindingElement.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel.Channels/TransportSecurityBindingElement.cs @@ -36,7 +36,7 @@ using System.ServiceModel.Security.Tokens; namespace System.ServiceModel.Channels { public sealed class TransportSecurityBindingElement -#if NET_2_1 +#if MOBILE : SecurityBindingElement #else : SecurityBindingElement, IPolicyExportExtension @@ -65,7 +65,7 @@ namespace System.ServiceModel.Channels throw new NotImplementedException (); } -#if !NET_2_1 && !XAMMAC_4_5 +#if !MOBILE && !XAMMAC_4_5 [MonoTODO] protected override IChannelListener BuildChannelListenerCore ( diff --git a/mcs/class/System.ServiceModel/System.ServiceModel.Description/ClientCredentials.cs b/mcs/class/System.ServiceModel/System.ServiceModel.Description/ClientCredentials.cs index ce4d6c4e37..db06df4e28 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel.Description/ClientCredentials.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel.Description/ClientCredentials.cs @@ -31,7 +31,7 @@ using System.ServiceModel.Channels; using System.ServiceModel.Description; using System.ServiceModel.Dispatcher; using System.ServiceModel.Security; -#if !NET_2_1 +#if !MOBILE using System.IdentityModel.Selectors; using System.IdentityModel.Tokens; using System.ServiceModel.Security.Tokens; @@ -40,7 +40,7 @@ using System.ServiceModel.Security.Tokens; namespace System.ServiceModel.Description { public class ClientCredentials -#if NET_2_1 || XAMMAC_4_5 +#if MOBILE || XAMMAC_4_5 : IEndpointBehavior #else : SecurityCredentialsManager, IEndpointBehavior @@ -58,7 +58,7 @@ namespace System.ServiceModel.Description initiator = other.initiator.Clone (); recipient = other.recipient.Clone (); windows = other.windows.Clone (); -#if !NET_2_1 +#if !MOBILE issued_token = other.issued_token.Clone (); peer = other.peer.Clone (); support_interactive = other.support_interactive; @@ -93,7 +93,7 @@ namespace System.ServiceModel.Description get { return windows; } } -#if !NET_2_1 +#if !MOBILE IssuedTokenClientCredential issued_token = new IssuedTokenClientCredential (); PeerCredential peer = new PeerCredential (); @@ -130,7 +130,7 @@ namespace System.ServiceModel.Description return new ClientCredentials (this); } -#if !NET_2_1 && !XAMMAC_4_5 +#if !MOBILE && !XAMMAC_4_5 public override SecurityTokenManager CreateSecurityTokenManager () { return new ClientCredentialsSecurityTokenManager (this); diff --git a/mcs/class/System.ServiceModel/System.ServiceModel.Description/ContractDescriptionGenerator.cs b/mcs/class/System.ServiceModel/System.ServiceModel.Description/ContractDescriptionGenerator.cs index 80238d41ff..50ea0a9058 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel.Description/ContractDescriptionGenerator.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel.Description/ContractDescriptionGenerator.cs @@ -373,7 +373,7 @@ namespace System.ServiceModel.Description var fname = a.Name ?? a.DetailType.Name + "Fault"; var fns = a.Namespace ?? cd.Namespace; var fd = new FaultDescription (a.Action ?? cd.Namespace + cd.Name + "/" + od.Name + fname) { DetailType = a.DetailType, Name = fname, Namespace = fns }; -#if !NET_2_1 +#if !MOBILE if (a.HasProtectionLevel) fd.ProtectionLevel = a.ProtectionLevel; #endif @@ -400,7 +400,7 @@ namespace System.ServiceModel.Description foreach (object obj in serviceMethod.GetCustomAttributes (typeof(IOperationBehavior),true)) od.Behaviors.Add ((IOperationBehavior) obj); } -#if !NET_2_1 +#if !MOBILE if (od.Behaviors.Find() == null) od.Behaviors.Add (new OperationBehaviorAttribute ()); #endif diff --git a/mcs/class/System.ServiceModel/System.ServiceModel.Description/DataContractSerializerOperationBehavior.cs b/mcs/class/System.ServiceModel/System.ServiceModel.Description/DataContractSerializerOperationBehavior.cs index dc25161d46..b763c15ca9 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel.Description/DataContractSerializerOperationBehavior.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel.Description/DataContractSerializerOperationBehavior.cs @@ -65,13 +65,13 @@ namespace System.ServiceModel.Description public int MaxItemsInObjectGraph { get; set; } -#if !NET_2_1 +#if !MOBILE public IDataContractSurrogate DataContractSurrogate { get; set; } #endif public virtual XmlObjectSerializer CreateSerializer (Type type, string name, string ns, IList knownTypes) { -#if NET_2_1 +#if MOBILE return new DataContractSerializer (type, name, ns, knownTypes); #else return new DataContractSerializer (type, name, ns, knownTypes, MaxItemsInObjectGraph, IgnoreExtensionDataObject, false, DataContractSurrogate); @@ -80,7 +80,7 @@ namespace System.ServiceModel.Description public virtual XmlObjectSerializer CreateSerializer (Type type, XmlDictionaryString name, XmlDictionaryString ns, IList knownTypes) { -#if NET_2_1 +#if MOBILE return new DataContractSerializer (type, name, ns, knownTypes); #else return new DataContractSerializer (type, name, ns, knownTypes, MaxItemsInObjectGraph, IgnoreExtensionDataObject, false, DataContractSurrogate); @@ -112,7 +112,7 @@ namespace System.ServiceModel.Description { } -#if !NET_2_1 && !XAMMAC_4_5 +#if !MOBILE && !XAMMAC_4_5 //IWsdlExportExtension void IWsdlExportExtension.ExportContract (WsdlExporter exporter, diff --git a/mcs/class/System.ServiceModel/System.ServiceModel.Description/MessagePartDescription.cs b/mcs/class/System.ServiceModel/System.ServiceModel.Description/MessagePartDescription.cs index 5e3924b26e..6dc65cc0d5 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel.Description/MessagePartDescription.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel.Description/MessagePartDescription.cs @@ -100,7 +100,7 @@ namespace System.ServiceModel.Description set { type = value; } } -#if !NET_2_1 && !XAMMAC_4_5 +#if !MOBILE && !XAMMAC_4_5 internal XsdDataContractImporter DataContractImporter { get; set; } internal XmlSerializerMessageContractImporterInternal XmlSerializationImporter { get; set; } internal System.CodeDom.CodeTypeReference CodeTypeReference { get; set; } diff --git a/mcs/class/System.ServiceModel/System.ServiceModel.Description/XmlSerializerOperationBehavior.cs b/mcs/class/System.ServiceModel/System.ServiceModel.Description/XmlSerializerOperationBehavior.cs index 1895c10e75..26ee9d753d 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel.Description/XmlSerializerOperationBehavior.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel.Description/XmlSerializerOperationBehavior.cs @@ -36,7 +36,7 @@ namespace System.ServiceModel.Description { public class XmlSerializerOperationBehavior : IOperationBehavior -#if !NET_2_1 +#if !MOBILE , IWsdlExportExtension #endif { @@ -104,7 +104,7 @@ namespace System.ServiceModel.Description { } -#if !NET_2_1 && !XAMMAC_4_5 +#if !MOBILE && !XAMMAC_4_5 void IWsdlExportExtension.ExportContract ( WsdlExporter exporter, WsdlContractConversionContext context) diff --git a/mcs/class/System.ServiceModel/System.ServiceModel.Diagnostics/MessageLoggingSettings.cs b/mcs/class/System.ServiceModel/System.ServiceModel.Diagnostics/MessageLoggingSettings.cs index db050b9067..435b7ef323 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel.Diagnostics/MessageLoggingSettings.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel.Diagnostics/MessageLoggingSettings.cs @@ -36,7 +36,7 @@ namespace System.ServiceModel.Diagnostics { public MessageLoggingSettings () { -#if !NET_2_1 && !XAMMAC_4_5 +#if !MOBILE && !XAMMAC_4_5 var e = ConfigUtil.DiagnosticSection.MessageLogging; LogEntireMessage = e.LogEntireMessage; LogKnownPii = e.LogKnownPii; diff --git a/mcs/class/System.ServiceModel/System.ServiceModel.Dispatcher/BaseMessagesFormatter.cs b/mcs/class/System.ServiceModel/System.ServiceModel.Dispatcher/BaseMessagesFormatter.cs index db1c49650c..dd50fedc3f 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel.Dispatcher/BaseMessagesFormatter.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel.Dispatcher/BaseMessagesFormatter.cs @@ -243,7 +243,7 @@ namespace System.ServiceModel.Dispatcher var headers = MessageToHeaderObjects (md, message); object [] parts = MessageToParts (md, message); if (md.MessageType != null) { -#if NET_2_1 +#if MOBILE parameters [0] = Activator.CreateInstance (md.MessageType); #else parameters [0] = Activator.CreateInstance (md.MessageType, true); @@ -271,7 +271,7 @@ namespace System.ServiceModel.Dispatcher var headers = MessageToHeaderObjects (md, message); object [] parts = MessageToParts (md, message); if (md.MessageType != null) { -#if NET_2_1 +#if MOBILE object msgObject = Activator.CreateInstance (md.MessageType); #else object msgObject = Activator.CreateInstance (md.MessageType, true); @@ -355,14 +355,14 @@ namespace System.ServiceModel.Dispatcher class DataContractMessagesFormatter : BaseMessagesFormatter { DataContractFormatAttribute attr; -#if !NET_2_1 +#if !MOBILE DataContractSerializerOperationBehavior serializerBehavior; #endif public DataContractMessagesFormatter (OperationDescription desc, DataContractFormatAttribute attr) : base (desc) { -#if !NET_2_1 +#if !MOBILE this.serializerBehavior = desc.Behaviors.Find(); #endif this.attr = attr; @@ -442,7 +442,7 @@ namespace System.ServiceModel.Dispatcher XmlObjectSerializer GetSerializer (MessagePartDescription partDesc) { if (!serializers.ContainsKey (partDesc)) -#if !NET_2_1 +#if !MOBILE if (serializerBehavior != null) serializers [partDesc] = serializerBehavior.CreateSerializer( partDesc.Type, partDesc.Name, partDesc.Namespace, OperationKnownTypes as IList); diff --git a/mcs/class/System.ServiceModel/System.ServiceModel.Dispatcher/ClientOperation.cs b/mcs/class/System.ServiceModel/System.ServiceModel.Dispatcher/ClientOperation.cs index 3f218beb72..1984a76985 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel.Dispatcher/ClientOperation.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel.Dispatcher/ClientOperation.cs @@ -39,7 +39,7 @@ namespace System.ServiceModel.Dispatcher public sealed class ClientOperation { internal class ClientOperationCollection : -#if NET_2_1 +#if MOBILE KeyedCollection #else SynchronizedKeyedCollection diff --git a/mcs/class/System.ServiceModel/System.ServiceModel.Dispatcher/ClientRuntime.cs b/mcs/class/System.ServiceModel/System.ServiceModel.Dispatcher/ClientRuntime.cs index 08f1839c4f..b23a6ef834 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel.Dispatcher/ClientRuntime.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel.Dispatcher/ClientRuntime.cs @@ -54,7 +54,7 @@ namespace System.ServiceModel.Dispatcher { contract_name = name; contract_ns = ns; -#if !NET_2_1 +#if !MOBILE CallbackDispatchRuntime = (DispatchRuntime) callbackDispatchRuntime ?? new DispatchRuntime (null, this); #endif } @@ -80,7 +80,7 @@ namespace System.ServiceModel.Dispatcher public Type ContractClientType { get; set; } -#if !NET_2_1 +#if !MOBILE public DispatchRuntime CallbackDispatchRuntime { get; internal set; } #endif @@ -88,7 +88,7 @@ namespace System.ServiceModel.Dispatcher get { return inspectors; } } -#if NET_2_1 +#if MOBILE public KeyedCollection Operations { get { return operations; } } diff --git a/mcs/class/System.ServiceModel/System.ServiceModel.Dispatcher/DispatchOperation.cs b/mcs/class/System.ServiceModel/System.ServiceModel.Dispatcher/DispatchOperation.cs index e9fb67f98e..0397c9bf3c 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel.Dispatcher/DispatchOperation.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel.Dispatcher/DispatchOperation.cs @@ -54,7 +54,7 @@ namespace System.ServiceModel.Dispatcher tx_auto_complete, tx_required, auto_dispose_params = true; IDispatchMessageFormatter formatter; -#if !NET_2_1 +#if !MOBILE ImpersonationOption impersonation; IOperationInvoker invoker; SynchronizedCollection inspectors @@ -93,7 +93,7 @@ namespace System.ServiceModel.Dispatcher get { return action; } } -#if !NET_2_1 +#if !MOBILE public SynchronizedCollection CallContextInitializers { get { return ctx_initializers; } } @@ -214,7 +214,7 @@ namespace System.ServiceModel.Dispatcher void ThrowIfOpened () { -#if !NET_2_1 && !XAMMAC_4_5 +#if !MOBILE && !XAMMAC_4_5 // FIXME: get callback client runtime status when ChannelDispatcher is not available. var state = Parent.ChannelDispatcher != null ? Parent.ChannelDispatcher.State : CommunicationState.Created; // Parent.CallbackClientRuntime.ChannelFactory.State; switch (state) { diff --git a/mcs/class/System.ServiceModel/System.ServiceModel.Dispatcher/DispatchRuntime.cs b/mcs/class/System.ServiceModel/System.ServiceModel.Dispatcher/DispatchRuntime.cs index f6660e1c19..8dc605443e 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel.Dispatcher/DispatchRuntime.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel.Dispatcher/DispatchRuntime.cs @@ -29,7 +29,7 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Reflection; -#if !NET_2_1 +#if !MOBILE using System.IdentityModel.Policy; #if !XAMMAC_4_5 using System.Web.Security; @@ -45,7 +45,7 @@ namespace System.ServiceModel.Dispatcher { public sealed class DispatchRuntime { -#if NET_2_1 || XAMMAC_4_5 +#if MOBILE || XAMMAC_4_5 internal DispatchRuntime (EndpointDispatcher dispatcher, ClientRuntime callbackClientRuntime) { UnhandledDispatchOperation = new DispatchOperation ( diff --git a/mcs/class/System.ServiceModel/System.ServiceModel.Security/X509CertificateInitiatorClientCredential.cs b/mcs/class/System.ServiceModel/System.ServiceModel.Security/X509CertificateInitiatorClientCredential.cs index 3a1da201c8..c823ce38e9 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel.Security/X509CertificateInitiatorClientCredential.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel.Security/X509CertificateInitiatorClientCredential.cs @@ -57,7 +57,7 @@ namespace System.ServiceModel.Security StoreName storeName, X509FindType findType, object findValue) { -#if !NET_2_1 +#if !MOBILE certificate = ConfigUtil.CreateCertificateFrom (storeLocation, storeName, findType, findValue); #else throw new NotImplementedException (); @@ -68,7 +68,7 @@ namespace System.ServiceModel.Security string subjectName, StoreLocation storeLocation, StoreName storeName) { -#if !NET_2_1 +#if !MOBILE certificate = ConfigUtil.CreateCertificateFrom (storeLocation, storeName, X509FindType.FindBySubjectName, subjectName); #else throw new NotImplementedException (); diff --git a/mcs/class/System.ServiceModel/System.ServiceModel.Security/X509CertificateRecipientClientCredential.cs b/mcs/class/System.ServiceModel/System.ServiceModel.Security/X509CertificateRecipientClientCredential.cs index c6aa5acfa9..93dc520054 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel.Security/X509CertificateRecipientClientCredential.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel.Security/X509CertificateRecipientClientCredential.cs @@ -27,7 +27,7 @@ // using System; using System.Collections.Generic; -#if !NET_2_1 +#if !MOBILE using System.IdentityModel.Selectors; #endif using System.Security.Cryptography.X509Certificates; @@ -49,7 +49,7 @@ namespace System.ServiceModel.Security X509Certificate2 certificate; Dictionary scoped = new Dictionary (); -#if !NET_2_1 +#if !MOBILE X509CertificateValidator validator; #endif X509RevocationMode revocation_mode; @@ -92,7 +92,7 @@ namespace System.ServiceModel.Security public void SetDefaultCertificate (StoreLocation storeLocation, StoreName storeName, X509FindType findType, Object findValue) { -#if !NET_2_1 +#if !MOBILE DefaultCertificate = ConfigUtil.CreateCertificateFrom (storeLocation, storeName, findType, findValue); #else throw new NotImplementedException (); @@ -110,7 +110,7 @@ namespace System.ServiceModel.Security StoreName storeName, X509FindType findType, Object findValue, Uri targetService) { -#if !NET_2_1 +#if !MOBILE ScopedCertificates [targetService] = ConfigUtil.CreateCertificateFrom (storeLocation, storeName, findType, findValue); #else throw new NotImplementedException (); diff --git a/mcs/class/System.ServiceModel/System.ServiceModel.dll.sources b/mcs/class/System.ServiceModel/System.ServiceModel.dll.sources index 8e54cb5c62..3f62fe4b03 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel.dll.sources +++ b/mcs/class/System.ServiceModel/System.ServiceModel.dll.sources @@ -726,7 +726,6 @@ System.ServiceModel.PeerResolvers/ServiceSettingsResponseInfo.cs System.ServiceModel.PeerResolvers/UnregisterInfo.cs System.ServiceModel.PeerResolvers/UpdateInfo.cs System.ServiceModel.Security.Tokens/AuthenticatorCommunicationObject.cs -System.ServiceModel.Security.Tokens/BinarySecretSecurityToken.cs System.ServiceModel.Security.Tokens/ClaimTypeRequirement.cs System.ServiceModel.Security.Tokens/CommunicationSecurityTokenAuthenticator.cs System.ServiceModel.Security.Tokens/CommunicationSecurityTokenProvider.cs @@ -734,7 +733,6 @@ System.ServiceModel.Security.Tokens/DerivedKeySecurityToken.cs System.ServiceModel.Security.Tokens/IIssuanceSecurityTokenAuthenticator.cs System.ServiceModel.Security.Tokens/ISecurityContextSecurityTokenCache.cs System.ServiceModel.Security.Tokens/InitiatorServiceModelSecurityTokenRequirement.cs -System.ServiceModel.Security.Tokens/InternalEncryptedKeyIdentifierClause.cs System.ServiceModel.Security.Tokens/IssuedSecurityTokenHandler.cs System.ServiceModel.Security.Tokens/IssuedSecurityTokenParameters.cs System.ServiceModel.Security.Tokens/IssuedSecurityTokenProvider.cs @@ -767,10 +765,8 @@ System.ServiceModel.Security.Tokens/SupportingTokenParameters.cs System.ServiceModel.Security.Tokens/TlsClientSession.cs System.ServiceModel.Security.Tokens/TlsServerSession.cs System.ServiceModel.Security.Tokens/UserNameSecurityTokenParameters.cs -System.ServiceModel.Security.Tokens/WrappedKeySecurityToken.cs System.ServiceModel.Security.Tokens/X509SecurityTokenParameters.cs System.ServiceModel.Security/BasicSecurityProfileVersion.cs -System.ServiceModel.Security/BinarySecretKeyIdentifierClause.cs System.ServiceModel.Security/ChannelProtectionRequirements.cs System.ServiceModel.Security/DataProtectionSecurityStateEncoder.cs System.ServiceModel.Security/ExpiredSecurityTokenException.cs @@ -783,7 +779,6 @@ System.ServiceModel.Security/InfocardInteractiveChannelInitializer.cs System.ServiceModel.Security/IssuedTokenClientCredential.cs System.ServiceModel.Security/IssuedTokenServiceCredential.cs System.ServiceModel.Security/KeyEntropyMode.cs -System.ServiceModel.Security/KeyNameIdentifierClause.cs System.ServiceModel.Security/MessagePartSpecification.cs System.ServiceModel.Security/MessageProtectionOrder.cs System.ServiceModel.Security/MessageSecurityException.cs @@ -793,7 +788,6 @@ System.ServiceModel.Security/SecureConversationServiceCredential.cs System.ServiceModel.Security/SecureConversationVersion.cs System.ServiceModel.Security/SecurityAccessDeniedException.cs System.ServiceModel.Security/SecurityAlgorithmSuite.cs -System.ServiceModel.Security/SecurityContextKeyIdentifierClause.cs System.ServiceModel.Security/SecurityCredentialsManager.cs System.ServiceModel.Security/SecurityMessageProperty.cs System.ServiceModel.Security/SecurityNegotiationException.cs diff --git a/mcs/class/System.ServiceModel/System.ServiceModel/BasicHttpBinding_4_5.cs b/mcs/class/System.ServiceModel/System.ServiceModel/BasicHttpBinding_4_5.cs index ef9715fb4b..49140b9f64 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel/BasicHttpBinding_4_5.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel/BasicHttpBinding_4_5.cs @@ -50,7 +50,7 @@ namespace System.ServiceModel { } -#if !NET_2_1 && !XAMMAC_4_5 +#if !MOBILE && !XAMMAC_4_5 public BasicHttpBinding (string configurationName) : this () { @@ -110,7 +110,7 @@ namespace System.ServiceModel SecurityBindingElement element; switch (Security.Mode) { case BasicHttpSecurityMode.Message: -#if NET_2_1 || XAMMAC_4_5 +#if MOBILE || XAMMAC_4_5 throw new NotImplementedException (); #else if (Security.Message.ClientCredentialType != BasicHttpMessageCredentialType.Certificate) @@ -121,7 +121,7 @@ namespace System.ServiceModel #endif case BasicHttpSecurityMode.TransportWithMessageCredential: -#if NET_2_1 || XAMMAC_4_5 +#if MOBILE || XAMMAC_4_5 throw new NotImplementedException (); #else if (Security.Message.ClientCredentialType != BasicHttpMessageCredentialType.Certificate) @@ -135,7 +135,7 @@ namespace System.ServiceModel return null; } -#if !NET_2_1 && !XAMMAC_4_5 +#if !MOBILE && !XAMMAC_4_5 element.SetKeyDerivation (false); element.SecurityHeaderLayout = SecurityHeaderLayout.Lax; #endif @@ -150,7 +150,7 @@ namespace System.ServiceModel ReaderQuotas.CopyTo (tm.ReaderQuotas); return tm; } else { -#if NET_2_1 || XAMMAC_4_5 +#if MOBILE || XAMMAC_4_5 throw new NotImplementedException (); #else return new MtomMessageEncodingBindingElement ( diff --git a/mcs/class/System.ServiceModel/System.ServiceModel/BasicHttpsBinding.cs b/mcs/class/System.ServiceModel/System.ServiceModel/BasicHttpsBinding.cs index 21e66a4f65..b328f91e14 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel/BasicHttpsBinding.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel/BasicHttpsBinding.cs @@ -50,7 +50,7 @@ namespace System.ServiceModel { } -#if !NET_2_1 && !XAMMAC_4_5 +#if !MOBILE && !XAMMAC_4_5 public BasicHttpsBinding (string configurationName) : this () { @@ -102,7 +102,7 @@ namespace System.ServiceModel SecurityBindingElement element; switch (Security.Mode) { case BasicHttpsSecurityMode.TransportWithMessageCredential: -#if NET_2_1 || XAMMAC_4_5 +#if MOBILE || XAMMAC_4_5 throw new NotImplementedException (); #else @@ -117,7 +117,7 @@ namespace System.ServiceModel return null; } -#if !NET_2_1 && !XAMMAC_4_5 +#if !MOBILE && !XAMMAC_4_5 element.SetKeyDerivation (false); element.SecurityHeaderLayout = SecurityHeaderLayout.Lax; #endif @@ -132,7 +132,7 @@ namespace System.ServiceModel ReaderQuotas.CopyTo (tm.ReaderQuotas); return tm; } else { -#if NET_2_1 || XAMMAC_4_5 +#if MOBILE || XAMMAC_4_5 throw new NotImplementedException (); #else return new MtomMessageEncodingBindingElement ( diff --git a/mcs/class/System.ServiceModel/System.ServiceModel/ChannelFactory.cs b/mcs/class/System.ServiceModel/System.ServiceModel/ChannelFactory.cs index d2ba82da51..84b8f96db8 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel/ChannelFactory.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel/ChannelFactory.cs @@ -90,7 +90,7 @@ namespace System.ServiceModel if (configurationName == null) return; -#if NET_2_1 || XAMMAC_4_5 +#if MOBILE || XAMMAC_4_5 try { // It should automatically use XmlXapResolver var cfg = new SilverlightClientConfigLoader ().Load (XmlReader.Create ("ServiceReferences.ClientConfig")); @@ -160,7 +160,7 @@ namespace System.ServiceModel #endif } -#if !NET_2_1 && !XAMMAC_4_5 +#if !MOBILE && !XAMMAC_4_5 private void ApplyBehavior (string behaviorConfig) { BehaviorsSection behaviorsSection = ConfigUtil.BehaviorsSection; @@ -260,7 +260,7 @@ namespace System.ServiceModel new BindingParameterCollection (); ContractDescription cd = Endpoint.Contract; -#if !NET_2_1 +#if !MOBILE pl.Add (ChannelProtectionRequirements.CreateFromContract (cd)); #endif diff --git a/mcs/class/System.ServiceModel/System.ServiceModel/ClientProxyGenerator.cs b/mcs/class/System.ServiceModel/System.ServiceModel/ClientProxyGenerator.cs index a7b5587abf..1e2724f954 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel/ClientProxyGenerator.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel/ClientProxyGenerator.cs @@ -79,7 +79,7 @@ namespace System.ServiceModel string modname = "dummy"; Type crtype = -#if !NET_2_1 +#if !MOBILE duplex ? typeof (DuplexClientRuntimeChannel) : #endif typeof (ClientRuntimeChannel); @@ -131,7 +131,7 @@ namespace System.ServiceModel BindingFlags bf = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance; foreach (OperationDescription od in cd.Operations) { // FIXME: handle properties and events. -#if !NET_2_1 +#if !MOBILE if (od.SyncMethod != null) GenerateMethodImpl (c, crtype.GetMethod ("Process", bf), od.Name, od.SyncMethod); #endif diff --git a/mcs/class/System.ServiceModel/System.ServiceModel/ClientRealProxy.cs b/mcs/class/System.ServiceModel/System.ServiceModel/ClientRealProxy.cs index 41d75e98f9..986fb69f1e 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel/ClientRealProxy.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel/ClientRealProxy.cs @@ -71,7 +71,7 @@ namespace System.ServiceModel { if (CanCastTo (t)) return true; -#if !NET_2_1 +#if !MOBILE if (isDuplex && CanCastTo (t)) return true; #endif diff --git a/mcs/class/System.ServiceModel/System.ServiceModel/DuplexClientRuntimeChannel.cs b/mcs/class/System.ServiceModel/System.ServiceModel/DuplexClientRuntimeChannel.cs index 4fa56e12a7..db6647c76f 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel/DuplexClientRuntimeChannel.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel/DuplexClientRuntimeChannel.cs @@ -192,10 +192,6 @@ namespace System.ServiceModel.MonoInternal } catch (Exception ex) { // FIXME: log it. Console.WriteLine (ex); - } finally { - // unless it is closed by session/call manager, move it back to the loop to receive the next message. - if (loop && input.State != CommunicationState.Closed) - ProcessRequestOrInput (input); } } diff --git a/mcs/class/System.ServiceModel/System.ServiceModel/EndpointAddress.cs b/mcs/class/System.ServiceModel/System.ServiceModel/EndpointAddress.cs index 153567710f..1740e4d990 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel/EndpointAddress.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel/EndpointAddress.cs @@ -37,7 +37,7 @@ using System.Xml.Schema; using System.Xml.Serialization; using System.ServiceModel.Channels; using System.ServiceModel.Description; -#if !NET_2_1 +#if !MOBILE using System.Security.Cryptography.Xml; #endif @@ -116,7 +116,7 @@ namespace System.ServiceModel get { return address; } } -#if !NET_2_1 +#if !MOBILE internal static XmlSchema Schema { get { if (schema == null) { @@ -187,7 +187,7 @@ namespace System.ServiceModel return ! (address1 == address2); } -//#if !NET_2_1 +//#if !MOBILE public static EndpointAddress ReadFrom ( XmlDictionaryReader reader) { @@ -296,7 +296,7 @@ namespace System.ServiceModel addressingVersion.Namespace, reader.LocalName, reader.NamespaceURI)); reader.MoveToContent (); -#if !NET_2_1 +#if !MOBILE MetadataSet metadata = null; if (reader.LocalName == "Metadata" && reader.NamespaceURI == addressingVersion.Namespace && @@ -317,7 +317,7 @@ namespace System.ServiceModel if (addressingVersion == AddressingVersion.WSAddressing10 && uri == w3c_anonymous) uri = anonymous_role; -#if NET_2_1 +#if MOBILE return new EndpointAddress (uri, identity); #else if (metadata == null) @@ -338,7 +338,7 @@ namespace System.ServiceModel { if (writer == null) throw new ArgumentNullException ("writer"); -#if NET_2_1 +#if MOBILE if (addressingVersion == AddressingVersion.None) { writer.WriteString (Uri.AbsoluteUri); } else { diff --git a/mcs/class/System.ServiceModel/System.ServiceModel/EndpointAddress10.cs b/mcs/class/System.ServiceModel/System.ServiceModel/EndpointAddress10.cs index 862830b0c7..d26293b0e7 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel/EndpointAddress10.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel/EndpointAddress10.cs @@ -42,7 +42,7 @@ namespace System.ServiceModel { [XmlSchemaProvider ("GetSchema")] [XmlRoot ("EndpointReference", Namespace = "http://www.w3.org/2005/08/addressing")] -#if NET_2_1 +#if MOBILE internal class EndpointAddress10 : IXmlSerializable #else public class EndpointAddress10 : IXmlSerializable diff --git a/mcs/class/System.ServiceModel/System.ServiceModel/EndpointAddressBuilder.cs b/mcs/class/System.ServiceModel/System.ServiceModel/EndpointAddressBuilder.cs index 7500d76322..f56bb33330 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel/EndpointAddressBuilder.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel/EndpointAddressBuilder.cs @@ -67,7 +67,7 @@ namespace System.ServiceModel set { identity = value; } } -#if !NET_2_1 +#if !MOBILE public XmlDictionaryReader GetReaderAtExtensions () { if (extension == null) diff --git a/mcs/class/System.ServiceModel/System.ServiceModel/Logger.cs b/mcs/class/System.ServiceModel/System.ServiceModel/Logger.cs index 79c743c48f..b00afa8203 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel/Logger.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel/Logger.cs @@ -50,7 +50,7 @@ namespace System.ServiceModel internal static class Logger { -#if NET_2_1 +#if MOBILE enum TraceEventType // dummy { Critical, @@ -71,7 +71,7 @@ namespace System.ServiceModel static int event_id; static TextWriter log_writer; static XmlWriter xml_writer; -#if !NET_2_1 +#if !MOBILE static readonly TraceSource source = new TraceSource ("System.ServiceModel"); static readonly TraceSource message_source = new TraceSource ("System.ServiceModel.MessageLogging"); #endif @@ -89,7 +89,7 @@ namespace System.ServiceModel case "stderr": log_writer = Console.Error; break; -#if !NET_2_1 +#if !MOBILE default: try { if (!String.IsNullOrEmpty (env)) @@ -104,7 +104,7 @@ namespace System.ServiceModel if (log_writer != null) xml_writer = XmlWriter.Create (log_writer, new XmlWriterSettings () { OmitXmlDeclaration = true }); -#if !NET_2_1 +#if !MOBILE message_source.Switch.Level = SourceLevels.Information; #endif } @@ -143,7 +143,7 @@ namespace System.ServiceModel if (log_writer != null) { lock (log_writer){ event_id++; -#if NET_2_1 +#if MOBILE log_writer.Write ("[{0}] ", event_id); #endif TraceCore (TraceEventType.Information, event_id, @@ -151,7 +151,7 @@ namespace System.ServiceModel message, args); log_writer.WriteLine (message, args); log_writer.Flush (); -#if !NET_2_1 +#if !MOBILE source.TraceEvent (eventType, event_id, message, args); #endif } @@ -179,7 +179,7 @@ namespace System.ServiceModel { if (log_writer != null) { var sw = new StringWriter (); -#if NET_2_1 +#if MOBILE var xw = XmlWriter.Create (sw, xws); #else var doc = new XmlDocument (); @@ -199,7 +199,7 @@ namespace System.ServiceModel event_id++; lock (log_writer){ -#if NET_2_1 +#if MOBILE log_writer.Write ("[{0}] ", event_id); TraceCore (TraceEventType.Information, event_id, /*FIXME*/false, /*FIXME*/Guid.Empty, sw); diff --git a/mcs/class/System.ServiceModel/System.ServiceModel/OperationContext.cs b/mcs/class/System.ServiceModel/System.ServiceModel/OperationContext.cs index 097e8cbfa4..7d64d43d63 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel/OperationContext.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel/OperationContext.cs @@ -45,7 +45,7 @@ namespace System.ServiceModel } Message incoming_message; -#if !NET_2_1 && !XAMMAC_4_5 +#if !MOBILE && !XAMMAC_4_5 EndpointDispatcher dispatcher; #endif IContextChannel channel; @@ -83,7 +83,7 @@ namespace System.ServiceModel } -#if !NET_2_1 && !XAMMAC_4_5 +#if !MOBILE && !XAMMAC_4_5 public EndpointDispatcher EndpointDispatcher { get { return dispatcher; } set { dispatcher = value; } @@ -146,7 +146,7 @@ namespace System.ServiceModel get { return Channel.SessionId; } } -#if !NET_2_1 +#if !MOBILE public ServiceSecurityContext ServiceSecurityContext { get { return IncomingMessageProperties != null ? IncomingMessageProperties.Security.ServiceSecurityContext : null; } } diff --git a/mcs/class/System.ServiceModel/System.ServiceModel/SilverlightClientConfigLoader.cs b/mcs/class/System.ServiceModel/System.ServiceModel/SilverlightClientConfigLoader.cs index 75d412d50c..eaf7d5ce2c 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel/SilverlightClientConfigLoader.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel/SilverlightClientConfigLoader.cs @@ -25,7 +25,7 @@ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -#if NET_2_1 || XAMMAC_4_5 +#if MOBILE || XAMMAC_4_5 using System; using System.Collections.Generic; diff --git a/mcs/class/System.ServiceModel/System.ServiceModel_test.dll.sources b/mcs/class/System.ServiceModel/System.ServiceModel_test.dll.sources index dd2dc7f1c7..d06cb33fe2 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel_test.dll.sources +++ b/mcs/class/System.ServiceModel/System.ServiceModel_test.dll.sources @@ -1,5 +1,4 @@ NUnitMoonHelper.cs -../../test-helpers/NetworkHelpers.cs FeatureBased/Features.Client/AsyncCallTesterProxy.cs FeatureBased/Features.Client/AsyncPatternServer.cs FeatureBased/Features.Client/DataContractTesterProxy.cs diff --git a/mcs/class/System.ServiceModel/Test/MetadataTests/ImportTests.cs b/mcs/class/System.ServiceModel/Test/MetadataTests/ImportTests.cs index 976dc6728e..f43655c573 100644 --- a/mcs/class/System.ServiceModel/Test/MetadataTests/ImportTests.cs +++ b/mcs/class/System.ServiceModel/Test/MetadataTests/ImportTests.cs @@ -129,7 +129,6 @@ namespace MonoTests.System.ServiceModel.MetadataTests { AuthenticationSchemes.Ntlm, label); } -#if NET_4_5 [Test] public virtual void BasicHttps () { @@ -179,7 +178,6 @@ namespace MonoTests.System.ServiceModel.MetadataTests { WSMessageEncoding.Text, HttpClientCredentialType.None, AuthenticationSchemes.Anonymous, label); } -#endif [Test] public virtual void NetTcp () diff --git a/mcs/class/System.ServiceModel/Test/MetadataTests/MetadataSamples.cs b/mcs/class/System.ServiceModel/Test/MetadataTests/MetadataSamples.cs index e04de3e589..ab336b3c05 100644 --- a/mcs/class/System.ServiceModel/Test/MetadataTests/MetadataSamples.cs +++ b/mcs/class/System.ServiceModel/Test/MetadataTests/MetadataSamples.cs @@ -136,7 +136,6 @@ namespace MonoTests.System.ServiceModel.MetadataTests { return exporter.GetGeneratedMetadata (); } -#if NET_4_5 [MetadataSample] public static MetadataSet BasicHttps () { @@ -197,7 +196,6 @@ namespace MonoTests.System.ServiceModel.MetadataTests { return exporter.GetGeneratedMetadata (); } -#endif [MetadataSample] public static MetadataSet NetTcp () diff --git a/mcs/class/System.ServiceModel/Test/System.ServiceModel.Channels/CommunicationObjectSyncTest.cs b/mcs/class/System.ServiceModel/Test/System.ServiceModel.Channels/CommunicationObjectSyncTest.cs index 798a77915f..6f448cb59a 100644 --- a/mcs/class/System.ServiceModel/Test/System.ServiceModel.Channels/CommunicationObjectSyncTest.cs +++ b/mcs/class/System.ServiceModel/Test/System.ServiceModel.Channels/CommunicationObjectSyncTest.cs @@ -168,7 +168,7 @@ namespace MonoTests.System.ServiceModel.Channels { } [TestMethod] -#if NET_2_1 +#if MOBILE [MoonlightBug] #else [NUnit.Framework.Ignore] @@ -237,7 +237,7 @@ namespace MonoTests.System.ServiceModel.Channels { } [TestMethod] -#if NET_2_1 +#if MOBILE [MoonlightBug] #else [NUnit.Framework.Ignore] @@ -340,7 +340,7 @@ namespace MonoTests.System.ServiceModel.Channels { } [TestMethod] -#if NET_2_1 +#if MOBILE [MoonlightBug] #else [NUnit.Framework.Ignore] @@ -361,7 +361,7 @@ namespace MonoTests.System.ServiceModel.Channels { } [TestMethod] -#if NET_2_1 +#if MOBILE [MoonlightBug] #else [NUnit.Framework.Ignore] @@ -453,7 +453,7 @@ namespace MonoTests.System.ServiceModel.Channels { } [TestMethod] -#if NET_2_1 +#if MOBILE [MoonlightBug] #else [NUnit.Framework.Ignore] @@ -546,7 +546,7 @@ namespace MonoTests.System.ServiceModel.Channels { } [TestMethod] -#if NET_2_1 +#if MOBILE [MoonlightBug] #else [NUnit.Framework.Ignore] @@ -641,7 +641,7 @@ namespace MonoTests.System.ServiceModel.Channels { } [TestMethod] -#if NET_2_1 +#if MOBILE [MoonlightBug] #else [NUnit.Framework.Ignore] @@ -733,7 +733,7 @@ namespace MonoTests.System.ServiceModel.Channels { } [TestMethod] -#if NET_2_1 +#if MOBILE [MoonlightBug] #else [NUnit.Framework.Ignore] @@ -777,7 +777,7 @@ namespace MonoTests.System.ServiceModel.Channels { // ThrowIfDisposed throws an exception if the state is Closing, Closed or Faulted. [TestMethod] -#if NET_2_1 +#if MOBILE [MoonlightBug] #else [NUnit.Framework.Ignore] @@ -843,7 +843,7 @@ namespace MonoTests.System.ServiceModel.Channels { [TestMethod] -#if NET_2_1 +#if MOBILE [MoonlightBug] #else [NUnit.Framework.Ignore] @@ -910,7 +910,7 @@ namespace MonoTests.System.ServiceModel.Channels { // ThrowIfDisposedOrImmutable throws an exception if the state is not Created. [TestMethod] -#if NET_2_1 +#if MOBILE [MoonlightBug] #else [NUnit.Framework.Ignore] @@ -979,7 +979,7 @@ namespace MonoTests.System.ServiceModel.Channels { } [TestMethod] -#if NET_2_1 +#if MOBILE [MoonlightBug] #else [NUnit.Framework.Ignore] @@ -1050,7 +1050,7 @@ namespace MonoTests.System.ServiceModel.Channels { // ThrowIfDisposedOrNotOpen throws an exception if the state is not Opened. [TestMethod] -#if NET_2_1 +#if MOBILE [MoonlightBug] #else [NUnit.Framework.Ignore] @@ -1119,7 +1119,7 @@ namespace MonoTests.System.ServiceModel.Channels { } [TestMethod] -#if NET_2_1 +#if MOBILE [MoonlightBug] #else [NUnit.Framework.Ignore] @@ -1196,7 +1196,7 @@ namespace MonoTests.System.ServiceModel.Channels { } [TestMethod] -#if NET_2_1 +#if MOBILE [MoonlightBug] #else [NUnit.Framework.Ignore] @@ -1223,7 +1223,7 @@ namespace MonoTests.System.ServiceModel.Channels { } [TestMethod] -#if NET_2_1 +#if MOBILE [MoonlightBug] #else [NUnit.Framework.Ignore] @@ -1239,7 +1239,7 @@ namespace MonoTests.System.ServiceModel.Channels { } [TestMethod] -#if NET_2_1 +#if MOBILE [MoonlightBug] #else [NUnit.Framework.Ignore] @@ -1267,7 +1267,7 @@ namespace MonoTests.System.ServiceModel.Channels { } [TestMethod] -#if NET_2_1 +#if MOBILE [MoonlightBug] #else [NUnit.Framework.Ignore] @@ -1303,7 +1303,7 @@ namespace MonoTests.System.ServiceModel.Channels { } [TestMethod] -#if NET_2_1 +#if MOBILE [MoonlightBug] #else [NUnit.Framework.Ignore] diff --git a/mcs/class/System.ServiceModel/xammac_net_4_5_System.ServiceModel.dll.sources b/mcs/class/System.ServiceModel/xammac_net_4_5_System.ServiceModel.dll.sources index f5b081aeda..ea92e69528 100644 --- a/mcs/class/System.ServiceModel/xammac_net_4_5_System.ServiceModel.dll.sources +++ b/mcs/class/System.ServiceModel/xammac_net_4_5_System.ServiceModel.dll.sources @@ -41,7 +41,6 @@ System.ServiceModel.Security/MessagePartSpecification.cs System.ServiceModel.Security/PeerCredential.cs System.ServiceModel.Security/ScopedMessagePartSpecification.cs System.ServiceModel.Security/SecurityAlgorithmSuite.cs -System.ServiceModel.Security/SecurityContextKeyIdentifierClause.cs System.ServiceModel.Security/SecurityMessageProperty.cs System.ServiceModel.Security/SecurityStateEncoder.cs System.ServiceModel.Security/SecurityTokenAttachmentMode.cs diff --git a/mcs/class/System.Threading.Tasks.Dataflow/Test/System.Threading.Tasks.Dataflow/TransformBlockTest.cs b/mcs/class/System.Threading.Tasks.Dataflow/Test/System.Threading.Tasks.Dataflow/TransformBlockTest.cs index 3901a55afc..b2193a91ba 100644 --- a/mcs/class/System.Threading.Tasks.Dataflow/Test/System.Threading.Tasks.Dataflow/TransformBlockTest.cs +++ b/mcs/class/System.Threading.Tasks.Dataflow/Test/System.Threading.Tasks.Dataflow/TransformBlockTest.cs @@ -68,9 +68,9 @@ namespace MonoTests.System.Threading.Tasks.Dataflow { for (int i = 0; i < array.Length; ++i) Assert.IsTrue (block.Post (i), "Not accepted"); - Thread.Sleep (300); + Thread.Sleep (600); block.LinkTo (action); - Thread.Sleep (100); + Thread.Sleep (300); CollectionAssert.AreEqual (new[] { 0, -1, -2, -3, -4, -5, -6, -7, -8, -9 }, array); } diff --git a/mcs/class/System.Web.Http.SelfHost/Makefile b/mcs/class/System.Web.Http.SelfHost/Makefile index f13d3b55f8..f4ff7d4664 100644 --- a/mcs/class/System.Web.Http.SelfHost/Makefile +++ b/mcs/class/System.Web.Http.SelfHost/Makefile @@ -4,17 +4,12 @@ include ../../build/rules.make LIBRARY = System.Web.Http.SelfHost.dll -System.Web.Http.SelfHost.Properties.CommonWebApiResources.resources: ../../../external/aspnetwebstack/src/Common/CommonWebApiResources.resx - $(RESGEN) "$<" "$@" - -System.Web.Http.SelfHost.Properties.SRResources.resources: ../../../external/aspnetwebstack/src/System.Web.Http.SelfHost/Properties/SRResources.resx - $(RESGEN) "$<" "$@" - +RESOURCE_DEFS = \ + System.Web.Http.SelfHost.Properties.CommonWebApiResources,../../../external/aspnetwebstack/src/Common/CommonWebApiResources.resx \ + System.Web.Http.SelfHost.Properties.SRResources,../../../external/aspnetwebstack/src/System.Web.Http.SelfHost/Properties/SRResources.resx LIB_REFS = System.Core System System.Xml System.Configuration System.Net.Http System.Runtime.Serialization System.ServiceModel System.IdentityModel System.Web.Http System.Net.Http.Formatting LIB_MCS_FLAGS = -d:ASPNETMVC -keyfile:../winfx.pub -delaysign include ../../build/library.make -$(the_lib): System.Web.Http.SelfHost.Properties.CommonWebApiResources.resources \ - System.Web.Http.SelfHost.Properties.SRResources.resources diff --git a/mcs/class/System.Web.Http.WebHost/Makefile b/mcs/class/System.Web.Http.WebHost/Makefile index e0606bdbaf..b022ea314c 100644 --- a/mcs/class/System.Web.Http.WebHost/Makefile +++ b/mcs/class/System.Web.Http.WebHost/Makefile @@ -4,17 +4,13 @@ include ../../build/rules.make LIBRARY = System.Web.Http.WebHost.dll -System.Web.Http.WebHost.Properties.CommonWebApiResources.resources: ../../../external/aspnetwebstack/src/Common/CommonWebApiResources.resx - $(RESGEN) "$<" "$@" - -System.Web.Http.WebHost.Properties.SRResources.resources: ../../../external/aspnetwebstack/src/System.Web.Http.WebHost/Properties/SRResources.resx - $(RESGEN) "$<" "$@" - +RESOURCE_DEFS = \ + System.Web.Http.WebHost.Properties.CommonWebApiResources,../../../external/aspnetwebstack/src/Common/CommonWebApiResources.resx \ + System.Web.Http.WebHost.Properties.SRResources,../../../external/aspnetwebstack/src/System.Web.Http.WebHost/Properties/SRResources.resx LIB_REFS = System.Core System System.Xml System.Configuration System.Net.Http System.Runtime.Serialization System.ServiceModel System.IdentityModel System.Web.Http System.Net.Http.Formatting System.Web.Routing System.Web Microsoft.Web.Infrastructure LIB_MCS_FLAGS = -d:ASPNETMVC -keyfile:../winfx.pub -delaysign include ../../build/library.make -$(the_lib): System.Web.Http.WebHost.Properties.CommonWebApiResources.resources \ - System.Web.Http.WebHost.Properties.SRResources.resources +$(the_lib): diff --git a/mcs/class/System.Web.Http/Makefile b/mcs/class/System.Web.Http/Makefile index fb50d52d2e..72afa046d2 100644 --- a/mcs/class/System.Web.Http/Makefile +++ b/mcs/class/System.Web.Http/Makefile @@ -4,20 +4,13 @@ include ../../build/rules.make LIBRARY = System.Web.Http.dll -System.Web.Http.Properties.CommonWebApiResources.resources: ../../../external/aspnetwebstack/src/Common/CommonWebApiResources.resx - $(RESGEN) "$<" "$@" - -System.Web.Http.Properties.SRResources.resources: ../../../external/aspnetwebstack/src/System.Web.Http/Properties/SRResources.resx - $(RESGEN) "$<" "$@" +RESOURCE_DEFS = \ + System.Web.Http.Properties.CommonWebApiResources,../../../external/aspnetwebstack/src/Common/CommonWebApiResources.resx \ + System.Web.Http.Properties.SRResources,../../../external/aspnetwebstack/src/System.Web.Http/Properties/SRResources.resx + LIB_REFS = System.Core System System.Xml System.Net.Http System.ComponentModel.DataAnnotations System.Net.Http.Formatting System.Runtime.Caching System.Runtime.Serialization System.Data.Linq -LIB_MCS_FLAGS = \ - -d:ASPNETMVC -keyfile:../winfx.pub -delaysign \ - -resource:System.Web.Http.Properties.CommonWebApiResources.resources \ - -resource:System.Web.Http.Properties.SRResources.resources +LIB_MCS_FLAGS = -d:ASPNETMVC -keyfile:../winfx.pub -delaysign include ../../build/library.make - -$(the_lib): System.Web.Http.Properties.CommonWebApiResources.resources \ - System.Web.Http.Properties.SRResources.resources diff --git a/mcs/class/System.Web.Mvc3/Makefile b/mcs/class/System.Web.Mvc3/Makefile index 024e52e89e..e5418545d9 100644 --- a/mcs/class/System.Web.Mvc3/Makefile +++ b/mcs/class/System.Web.Mvc3/Makefile @@ -5,6 +5,7 @@ include ../../build/rules.make LIBRARY = System.Web.Mvc3.dll LIBRARY_NAME = System.Web.Mvc.dll +RESOURCE_DEFS = System.Web.Mvc.Resources.MvcResources,Mvc/Resources/MvcResources.resx RESX_DIST = Mvc/Resources/MvcResources.resx LIB_REFS = Microsoft.Web.Infrastructure System System.Core System.Configuration System.Data System.Xml System.Web System.Web.Abstractions System.Web.Routing System.Web.Extensions System.ComponentModel.DataAnnotations System.Data.Linq System.Runtime.Caching System.Web.Razor System.Web.WebPages.Razor System.Web.WebPages @@ -12,14 +13,9 @@ LIB_MCS_FLAGS = \ /warn:1 \ /keyfile:../winfx.pub \ /d:MONO \ - /delaysign \ - $(foreach r, $(RESOURCES), /resource:$(r),System.Web.Mvc.Resources.$(notdir $(r))) + /delaysign EXTRA_DISTFILES = $(RESX_DIST) -RESOURCES = $(RESX_DIST:.resx=.resources) + include ../../build/library.make -$(build_lib): $(RESOURCES) - -$(RESOURCES): %.resources: %.resx - $(RESGEN) `echo $< | $(PLATFORM_CHANGE_SEPARATOR_CMD)` diff --git a/mcs/class/System.Web.Razor/Makefile b/mcs/class/System.Web.Razor/Makefile index 542360275c..e4472a96a0 100644 --- a/mcs/class/System.Web.Razor/Makefile +++ b/mcs/class/System.Web.Razor/Makefile @@ -5,21 +5,15 @@ include ../../build/rules.make LIBRARY = System.Web.Razor.dll LIBRARY_NAME = System.Web.Razor.dll -System.Web.Razor.Common.CommonResources.resources: ../../../external/aspnetwebstack/src/CommonResources.resx - $(RESGEN) "$<" "$@" - -System.Web.Razor.Resources.RazorResources.resources: ../../../external/aspnetwebstack/src/System.Web.Razor/Resources/RazorResources.resx - $(RESGEN) "$<" "$@" +RESOURCE_DEFS = \ + System.Web.Razor.Common.CommonResources,../../../external/aspnetwebstack/src/CommonResources.resx \ + System.Web.Razor.Resources.RazorResources,../../../external/aspnetwebstack/src/System.Web.Razor/Resources/RazorResources.resx LIB_REFS = System System.Core LIB_MCS_FLAGS = \ /warn:1 \ /keyfile:../winfx.pub -delaysign \ - /d:ASPNETWEBPAGES \ - /resource:System.Web.Razor.Resources.RazorResources.resources \ - /resource:System.Web.Razor.Common.CommonResources.resources + /d:ASPNETWEBPAGES include ../../build/library.make -$(build_lib): System.Web.Razor.Resources.RazorResources.resources \ - System.Web.Razor.Common.CommonResources.resources diff --git a/mcs/class/System.Web.WebPages.Deployment/Makefile b/mcs/class/System.Web.WebPages.Deployment/Makefile index 33d506be70..2e704de873 100644 --- a/mcs/class/System.Web.WebPages.Deployment/Makefile +++ b/mcs/class/System.Web.WebPages.Deployment/Makefile @@ -5,21 +5,15 @@ include ../../build/rules.make LIBRARY = System.Web.WebPages.Deployment.dll LIBRARY_NAME = System.Web.WebPages.Deployment.dll -System.Web.WebPages.Deployment.Common.CommonResources.resources: ../../../external/aspnetwebstack/src/CommonResources.resx - $(RESGEN) "$<" "$@" - -System.Web.WebPages.Deployment.Resources.ConfigurationResources.resources: ../../../external/aspnetwebstack/src/System.Web.WebPages.Deployment/Resources/ConfigurationResources.resx - $(RESGEN) "$<" "$@" +RESOURCE_DEFS = \ + System.Web.WebPages.Deployment.Common.CommonResources,../../../external/aspnetwebstack/src/CommonResources.resx \ + System.Web.WebPages.Deployment.Resources.ConfigurationResources,../../../external/aspnetwebstack/src/System.Web.WebPages.Deployment/Resources/ConfigurationResources.resx + LIB_REFS = System System.Core System.Configuration System.Web Microsoft.Web.Infrastructure LIB_MCS_FLAGS = \ /warn:1 \ /keyfile:../winfx.pub -delaysign \ - /d:ASPNETWEBPAGES \ - /resource:System.Web.WebPages.Deployment.Common.CommonResources.resources \ - /resource:System.Web.WebPages.Deployment.Resources.ConfigurationResources.resources + /d:ASPNETWEBPAGES include ../../build/library.make - -$(build_lib): System.Web.WebPages.Deployment.Common.CommonResources.resources \ - System.Web.WebPages.Deployment.Resources.ConfigurationResources.resources diff --git a/mcs/class/System.Web.WebPages.Razor/Makefile b/mcs/class/System.Web.WebPages.Razor/Makefile index cb0e52dc33..28b0f3f45c 100644 --- a/mcs/class/System.Web.WebPages.Razor/Makefile +++ b/mcs/class/System.Web.WebPages.Razor/Makefile @@ -5,24 +5,18 @@ include ../../build/rules.make LIBRARY = System.Web.WebPages.Razor.dll LIBRARY_NAME = System.Web.WebPages.Razor.dll -System.Web.WebPages.Razor.Common.CommonResources.resources: ../../../external/aspnetwebstack/src/CommonResources.resx - $(RESGEN) "$<" "$@" - -System.Web.WebPages.Razor.Resources.RazorWebResources.resources: ../../../external/aspnetwebstack/src/System.Web.WebPages.Razor/Resources/RazorWebResources.resx - $(RESGEN) "$<" "$@" +RESOURCE_DEFS = \ + System.Web.WebPages.Razor.Common.CommonResources,../../../external/aspnetwebstack/src/CommonResources.resx \ + System.Web.WebPages.Razor.Resources.RazorWebResources,../../../external/aspnetwebstack/src/System.Web.WebPages.Razor/Resources/RazorWebResources.resx LIB_REFS = System System.Core System.Configuration System.Web System.Web.WebPages System.Web.Razor LIB_MCS_FLAGS = \ /warn:1 \ /keyfile:../winfx.pub \ /delaysign \ - /d:ASPNETWEBPAGES \ - /resource:System.Web.WebPages.Razor.Resources.RazorWebResources.resources \ - /resource:System.Web.WebPages.Razor.Common.CommonResources.resources + /d:ASPNETWEBPAGES include ../../build/library.make -$(build_lib): System.Web.WebPages.Razor.Resources.RazorWebResources.resources \ - System.Web.WebPages.Razor.Common.CommonResources.resources diff --git a/mcs/class/System.Web.WebPages/Makefile b/mcs/class/System.Web.WebPages/Makefile index 394f2043a1..3e9641f079 100644 --- a/mcs/class/System.Web.WebPages/Makefile +++ b/mcs/class/System.Web.WebPages/Makefile @@ -5,24 +5,18 @@ include ../../build/rules.make LIBRARY = System.Web.WebPages.dll LIBRARY_NAME = System.Web.WebPages.dll -System.Web.WebPages.Common.CommonResources.resources: ../../../external/aspnetwebstack/src/CommonResources.resx - $(RESGEN) "$<" "$@" - -System.Web.WebPages.Resources.WebPageResources.resources: ../../../external/aspnetwebstack/src/System.Web.WebPages/Resources/WebPageResources.resx - $(RESGEN) "$<" "$@" +RESOURCE_DEFS = \ + System.Web.WebPages.Common.CommonResources,../../../external/aspnetwebstack/src/CommonResources.resx \ + System.Web.WebPages.Resources.WebPageResources,../../../external/aspnetwebstack/src/System.Web.WebPages/Resources/WebPageResources.resx LIB_REFS = Microsoft.CSharp Microsoft.Web.Infrastructure System System.ComponentModel.DataAnnotations System.Configuration System.Core System.Data.Linq System.Web System.Web.WebPages.Deployment System.Web.Razor System.Xml System.Xml.Linq + LIB_MCS_FLAGS = \ /warn:1 \ /keyfile:../winfx.pub \ /delaysign \ - /d:ASPNETWEBPAGES \ - /resource:System.Web.WebPages.Resources.WebPageResources.resources \ - /resource:System.Web.WebPages.Common.CommonResources.resources + /d:ASPNETWEBPAGES EXTRA_DISTFILES = $(RESX_DIST) include ../../build/library.make - -$(build_lib): System.Web.WebPages.Resources.WebPageResources.resources \ - System.Web.WebPages.Common.CommonResources.resources diff --git a/mcs/class/System.Web/Makefile b/mcs/class/System.Web/Makefile index 6098d30328..61ab3d54af 100644 --- a/mcs/class/System.Web/Makefile +++ b/mcs/class/System.Web/Makefile @@ -225,8 +225,8 @@ TEST_RESOURCE_FILES = \ Test/mainsoft/NunitWebResources/BoundField_Bug646505.aspx.cs \ Test/mainsoft/NunitWebResources/HtmlTitleCodeRender_Bug662918.aspx -RESX_DIST = resources/TranslationResources.resx -RESX_RES = $(RESX_DIST:.resx=.resources) +RESOURCE_DEFS = \ + TranslationResources,resources/TranslationResources.resx NUNIT_RESOURCE_FILES = $(TEST_RESOURCE_FILES) NUNIT_APP_CODE_FILES = $(TEST_APP_CODE_FILES) @@ -254,7 +254,7 @@ ifneq (plainweb/,$(intermediate)) LIB_REFS += System.Web.Services plaindesign/System.Design LIB_MCS_FLAGS += -define:WEBSERVICES_DEP -all-local: System.Web/UplevelHelper.cs resources/TranslationResources.resources +all-local: System.Web/UplevelHelper.cs endif @@ -272,7 +272,6 @@ EXTRA_DISTFILES = \ $(TEST_APP_CODE_FILES) \ $(TEST_APP_GLOBALRESOURCES_FILES) \ UplevelHelperDefinitions.xml \ - $(RESX_DIST) \ SQLiteProviders_DatabaseSchema.sql \ $(shell find Test/standalone-runner-support/ -name "*.cs" -type f -printf "'%p' ") \ $(shell find Test/standalone-tests/ -name "*.cs" -type f -printf "'%p' " -o -name "*.cs.in" -type f -printf "'%p' ") \ diff --git a/mcs/class/System.Web/System.Web.Security/FormsAuthentication.cs b/mcs/class/System.Web/System.Web.Security/FormsAuthentication.cs index 491d74f6c4..651d8bf4c8 100644 --- a/mcs/class/System.Web/System.Web.Security/FormsAuthentication.cs +++ b/mcs/class/System.Web/System.Web.Security/FormsAuthentication.cs @@ -212,21 +212,18 @@ namespace System.Web.Security strCookiePath = cookiePath; DateTime now = DateTime.Now; - DateTime then; - if (createPersistentCookie) - then = now.AddMinutes(timeout); - else - then = DateTime.MinValue; + DateTime ticketExpiry = now.AddMinutes(timeout); + DateTime cookieExpiry = createPersistentCookie ? ticketExpiry : DateTime.MinValue; FormsAuthenticationTicket ticket = new FormsAuthenticationTicket (1, userName, now, - createPersistentCookie?then:now.AddYears (50), + ticketExpiry, createPersistentCookie, String.Empty, cookiePath); - HttpCookie cookie = new HttpCookie (cookieName, Encrypt (ticket), strCookiePath, then); + HttpCookie cookie = new HttpCookie (cookieName, Encrypt (ticket), strCookiePath, cookieExpiry); if (requireSSL) cookie.Secure = true; if (!String.IsNullOrEmpty (cookie_domain)) diff --git a/mcs/class/System.Web/System.Web.dll.sources b/mcs/class/System.Web/System.Web.dll.sources index 5f47d1326e..248b80f353 100644 --- a/mcs/class/System.Web/System.Web.dll.sources +++ b/mcs/class/System.Web/System.Web.dll.sources @@ -1400,6 +1400,7 @@ ReferenceSources/SR.cs ../referencesource/System.Web/Hosting/IProcessHostSupportFunctions.cs ../referencesource/System.Web/Hosting/HTTP_COOKED_URL.cs ../referencesource/System.Web/Hosting/HostingEnvironmentException.cs +../referencesource/System.Web/Util/Debug.cs ../referencesource/System.Web/Util/SynchronizationContextMode.cs ../referencesource/System.Web/Util/ISyncContextLock.cs ../referencesource/System.Web/Util/DoNotResetAttribute.cs diff --git a/mcs/class/System.Web/System.Web/HttpCookie.cs b/mcs/class/System.Web/System.Web/HttpCookie.cs index 2b4e68cf8e..a413f1140d 100644 --- a/mcs/class/System.Web/System.Web/HttpCookie.cs +++ b/mcs/class/System.Web/System.Web/HttpCookie.cs @@ -3,6 +3,7 @@ // // Author: // Chris Toshok (toshok@novell.com) +// Katharina Bogad (bogad@cs.tum.edu) // // @@ -31,6 +32,7 @@ using System.Text; using System.Collections.Specialized; using System.Security.Permissions; +using System.Web.Configuration; namespace System.Web { @@ -66,6 +68,17 @@ namespace System.Web this.name = name; values = new CookieNVC(); Value = ""; + + HttpCookiesSection cookieConfig = (HttpCookiesSection) WebConfigurationManager.GetSection ("system.web/httpCookies"); + + if(!string.IsNullOrWhiteSpace(cookieConfig.Domain)) + domain = cookieConfig.Domain; + + if(cookieConfig.HttpOnlyCookies) + flags |= CookieFlags.HttpOnly; + + if(cookieConfig.RequireSSL) + flags |= CookieFlags.Secure; } public HttpCookie (string name, string value) diff --git a/mcs/class/System.Web/Test/System.Web.Security/MachineKeyTest.cs b/mcs/class/System.Web/Test/System.Web.Security/MachineKeyTest.cs index 06ee42a1a1..a88bfa88c0 100644 --- a/mcs/class/System.Web/Test/System.Web.Security/MachineKeyTest.cs +++ b/mcs/class/System.Web/Test/System.Web.Security/MachineKeyTest.cs @@ -169,7 +169,6 @@ namespace MonoTests.System.Web.Security } } -#if NET_4_5 [Test] public void Protect () { @@ -200,6 +199,5 @@ namespace MonoTests.System.Web.Security MachineKey.Unprotect (encryptedBytes, oneUsage), "Single purpose working when multiple supplied"); } -#endif } } diff --git a/mcs/class/System.Web/Test/System.Web.Security/MembershipPasswordAttributeTest.cs b/mcs/class/System.Web/Test/System.Web.Security/MembershipPasswordAttributeTest.cs index 4ace2ca1b3..b9900b94a5 100644 --- a/mcs/class/System.Web/Test/System.Web.Security/MembershipPasswordAttributeTest.cs +++ b/mcs/class/System.Web/Test/System.Web.Security/MembershipPasswordAttributeTest.cs @@ -1,4 +1,3 @@ -#if NET_4_5 using System.ComponentModel.DataAnnotations; using System.Linq; @@ -137,4 +136,3 @@ namespace MonoTests.System.Web.Security { } } } -#endif diff --git a/mcs/class/System.Web/Test/System.Web/EventHandlerTaskAsyncHelperTest.cs b/mcs/class/System.Web/Test/System.Web/EventHandlerTaskAsyncHelperTest.cs index 9ae8aae055..192623ce4c 100644 --- a/mcs/class/System.Web/Test/System.Web/EventHandlerTaskAsyncHelperTest.cs +++ b/mcs/class/System.Web/Test/System.Web/EventHandlerTaskAsyncHelperTest.cs @@ -26,7 +26,6 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -#if NET_4_5 using System; using System.Threading.Tasks; @@ -115,4 +114,3 @@ namespace MonoTests.System.Web } } -#endif diff --git a/mcs/class/System.Web/Test/System.Web/HttpTaskAsyncHandlerTest.cs b/mcs/class/System.Web/Test/System.Web/HttpTaskAsyncHandlerTest.cs index 50afda19bc..bfd5b21624 100644 --- a/mcs/class/System.Web/Test/System.Web/HttpTaskAsyncHandlerTest.cs +++ b/mcs/class/System.Web/Test/System.Web/HttpTaskAsyncHandlerTest.cs @@ -26,7 +26,6 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -#if NET_4_5 using System; using System.IO; @@ -129,4 +128,3 @@ namespace MonoTests.System.Web } } -#endif diff --git a/mcs/class/System.Web/Test/System.Web/TaskAsyncResultTest.cs b/mcs/class/System.Web/Test/System.Web/TaskAsyncResultTest.cs index 301a2988a3..05a67e4da0 100644 --- a/mcs/class/System.Web/Test/System.Web/TaskAsyncResultTest.cs +++ b/mcs/class/System.Web/Test/System.Web/TaskAsyncResultTest.cs @@ -26,7 +26,6 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -#if NET_4_5 using System; using System.Threading; @@ -331,4 +330,3 @@ namespace MonoTests.System.Web } } -#endif diff --git a/mcs/class/System.Windows.Forms/System.Windows.Forms/Application.cs b/mcs/class/System.Windows.Forms/System.Windows.Forms/Application.cs index 2c2d5bf931..e4f980e60d 100644 --- a/mcs/class/System.Windows.Forms/System.Windows.Forms/Application.cs +++ b/mcs/class/System.Windows.Forms/System.Windows.Forms/Application.cs @@ -969,8 +969,8 @@ namespace System.Windows.Forms EnableFormsForModalLoop (toplevels, context); - if (context.MainForm != null && context.MainForm.IsHandleCreated) { - XplatUI.SetModal (context.MainForm.Handle, false); + if (old != null && old.IsHandleCreated) { + XplatUI.SetModal (old.Handle, false); } #if DebugRunLoop Console.WriteLine (" Done with the SetModal"); diff --git a/mcs/class/System.Windows.Forms/Test/System.Windows.Forms/DateTimePickerTest.cs.REMOVED.git-id b/mcs/class/System.Windows.Forms/Test/System.Windows.Forms/DateTimePickerTest.cs.REMOVED.git-id index dea9b73de0..2f08b7399f 100644 --- a/mcs/class/System.Windows.Forms/Test/System.Windows.Forms/DateTimePickerTest.cs.REMOVED.git-id +++ b/mcs/class/System.Windows.Forms/Test/System.Windows.Forms/DateTimePickerTest.cs.REMOVED.git-id @@ -1 +1 @@ -17156b8b708bdef62e4659b9f104360ce575f311 \ No newline at end of file +7fc177f9851e5e48925bc4e9c97038948f047abf \ No newline at end of file diff --git a/mcs/class/System.XML/Assembly/AssemblyInfo.cs b/mcs/class/System.XML/Assembly/AssemblyInfo.cs index 3b61fe6384..cd45fc2ed3 100644 --- a/mcs/class/System.XML/Assembly/AssemblyInfo.cs +++ b/mcs/class/System.XML/Assembly/AssemblyInfo.cs @@ -55,13 +55,13 @@ using System.Runtime.InteropServices; [assembly: CLSCompliant (true)] [assembly: AssemblyDelaySign (true)] -#if NET_2_1 +#if MOBILE [assembly: AssemblyKeyFile ("../silverlight.pub")] #else [assembly: AssemblyKeyFile ("../ecma.pub")] #endif -#if NET_2_1 +#if MOBILE [assembly: InternalsVisibleTo ("System.ServiceModel.Web, PublicKey=00240000048000009400000006020000002400005253413100040000010001008D56C76F9E8649383049F383C44BE0EC204181822A6C31CF5EB7EF486944D032188EA1D3920763712CCB12D75FB77E9811149E6148E5D32FBAAB37611C1878DDC19E20EF135D0CB2CFF2BFEC3D115810C3D9069638FE4BE215DBF795861920E5AB6F7DB2E2CEEF136AC23D5DD2BF031700AEC232F6C6B1C785B4305C123B37AB")] #else [assembly: AllowPartiallyTrustedCallers] diff --git a/mcs/class/System.XML/Makefile b/mcs/class/System.XML/Makefile index 84a898e6ee..4c6d072bd6 100644 --- a/mcs/class/System.XML/Makefile +++ b/mcs/class/System.XML/Makefile @@ -20,7 +20,7 @@ TXT_RESOURCE_STRINGS = \ LIB_MCS_FLAGS = -nowarn:219,414,649,1717 -unsafe -d:ASYNC ifeq (2.1, $(FRAMEWORK_VERSION)) -LIB_MCS_FLAGS += -d:AGCLR -d:NET_2_1_HACK -d:DISABLE_XSLT_COMPILER -d:DISABLE_XSLT_SCRIPT,MONO_HYBRID_SYSTEM_XML -d:DISABLE_CAS_USE +LIB_MCS_FLAGS += -d:AGCLR -d:DISABLE_XSLT_COMPILER -d:DISABLE_XSLT_SCRIPT,MONO_HYBRID_SYSTEM_XML -d:DISABLE_CAS_USE endif TEST_LIB_REFS = System.Data System.Core diff --git a/mcs/class/System.XML/ReferenceSources/LocalAppContextSwitches.cs b/mcs/class/System.XML/ReferenceSources/LocalAppContextSwitches.cs index 9c961021fd..bc03e96bbd 100644 --- a/mcs/class/System.XML/ReferenceSources/LocalAppContextSwitches.cs +++ b/mcs/class/System.XML/ReferenceSources/LocalAppContextSwitches.cs @@ -1,7 +1,8 @@ namespace System { - static class LocalAppContextSwitches { - public const bool IgnoreEmptyKeySequences = false; - public const bool DontThrowOnInvalidSurrogatePairs = false; - } + static class LocalAppContextSwitches { + public static readonly bool IgnoreEmptyKeySequences = false; + public static readonly bool DontThrowOnInvalidSurrogatePairs = false; + public static readonly bool IgnoreKindInUtcTimeSerialization = false; + } } \ No newline at end of file diff --git a/mcs/class/System.XML/System.Xml.Serialization/XmlChoiceIdentifierAttribute.cs b/mcs/class/System.XML/System.Xml.Serialization/XmlChoiceIdentifierAttribute.cs index cf1434afff..fc4fefc966 100644 --- a/mcs/class/System.XML/System.Xml.Serialization/XmlChoiceIdentifierAttribute.cs +++ b/mcs/class/System.XML/System.Xml.Serialization/XmlChoiceIdentifierAttribute.cs @@ -60,7 +60,7 @@ namespace System.Xml.Serialization set { memberName = value; } } -#if NET_2_1 +#if MOBILE MemberInfo member; // It is used only in 2.1 S.X.Serialization.dll in MS SDK. internal MemberInfo MemberInfo { diff --git a/mcs/class/System.XML/System.Xml.Serialization/XmlCustomFormatter.cs b/mcs/class/System.XML/System.Xml.Serialization/XmlCustomFormatter.cs index a7343e0182..e27f99a0fb 100644 --- a/mcs/class/System.XML/System.Xml.Serialization/XmlCustomFormatter.cs +++ b/mcs/class/System.XML/System.Xml.Serialization/XmlCustomFormatter.cs @@ -243,6 +243,33 @@ namespace System.Xml.Serialization { } } + static string[] allTimeFormats = new string[] { + "HH:mm:ss.fffffffzzzzzz", + "HH:mm:ss", + "HH:mm:ss.f", + "HH:mm:ss.ff", + "HH:mm:ss.fff", + "HH:mm:ss.ffff", + "HH:mm:ss.fffff", + "HH:mm:ss.ffffff", + "HH:mm:ss.fffffff", + "HH:mm:ssZ", + "HH:mm:ss.fZ", + "HH:mm:ss.ffZ", + "HH:mm:ss.fffZ", + "HH:mm:ss.ffffZ", + "HH:mm:ss.fffffZ", + "HH:mm:ss.ffffffZ", + "HH:mm:ss.fffffffZ", + "HH:mm:sszzzzzz", + "HH:mm:ss.fzzzzzz", + "HH:mm:ss.ffzzzzzz", + "HH:mm:ss.fffzzzzzz", + "HH:mm:ss.ffffzzzzzz", + "HH:mm:ss.fffffzzzzzz", + "HH:mm:ss.ffffffzzzzzz", + }; + internal static object FromXmlString (TypeData type, string value) { if (value == null) return null; @@ -254,7 +281,7 @@ namespace System.Xml.Serialization { case "char": return (char)XmlConvert.ToInt32 (value); case "dateTime": return XmlConvert.ToDateTime (value, XmlDateTimeSerializationMode.RoundtripKind); case "date": return XmlConvert.ToDateTime (value).Date; - case "time": return DateTime.ParseExact (value, "HH:mm:ss.FFFFFFF", null); + case "time": return DateTime.ParseExact(value, allTimeFormats, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AllowLeadingWhite | DateTimeStyles.AllowTrailingWhite | DateTimeStyles.NoCurrentDateDefault | DateTimeStyles.RoundtripKind); case "decimal": return XmlConvert.ToDecimal (value); case "double": return XmlConvert.ToDouble (value); case "short": return XmlConvert.ToInt16 (value); diff --git a/mcs/class/System.XML/System.Xml.Serialization/XmlMemberMapping.cs b/mcs/class/System.XML/System.Xml.Serialization/XmlMemberMapping.cs index b68d33eec9..fc0a36035c 100644 --- a/mcs/class/System.XML/System.Xml.Serialization/XmlMemberMapping.cs +++ b/mcs/class/System.XML/System.Xml.Serialization/XmlMemberMapping.cs @@ -126,7 +126,7 @@ namespace System.Xml.Serialization { get { return _mapMember.Name; } } -#if !NET_2_1 +#if !MOBILE public string GenerateTypeName (System.CodeDom.Compiler.CodeDomProvider codeProvider) { string ret = codeProvider.CreateValidIdentifier (_mapMember.TypeData.FullTypeName); diff --git a/mcs/class/System.XML/System.Xml.Serialization/XmlReflectionImporter.cs b/mcs/class/System.XML/System.Xml.Serialization/XmlReflectionImporter.cs index 6338a8dc14..0c4e131b87 100644 --- a/mcs/class/System.XML/System.Xml.Serialization/XmlReflectionImporter.cs +++ b/mcs/class/System.XML/System.Xml.Serialization/XmlReflectionImporter.cs @@ -157,7 +157,7 @@ namespace System.Xml.Serialization { mps.RelatedMaps = relatedMaps; mps.Format = SerializationFormat.Literal; Type[] extraTypes = includedTypes != null ? (Type[])includedTypes.ToArray(typeof(Type)) : null; -#if !NET_2_1 +#if !MOBILE mps.Source = new MembersSerializationSource (elementName, hasWrapperElement, members, false, true, ns, extraTypes); if (allowPrivateTypes) mps.Source.CanBeGenerated = false; #endif @@ -226,7 +226,7 @@ namespace System.Xml.Serialization { map.RelatedMaps = relatedMaps; map.Format = SerializationFormat.Literal; Type[] extraTypes = includedTypes != null ? (Type[]) includedTypes.ToArray (typeof (Type)) : null; -#if !NET_2_1 +#if !MOBILE map.Source = new XmlTypeSerializationSource (typeData.Type, root, attributeOverrides, defaultNamespace, extraTypes); if (allowPrivateTypes) map.Source.CanBeGenerated = false; #endif diff --git a/mcs/class/System.XML/System.Xml.Serialization/XmlSerializationReader.cs b/mcs/class/System.XML/System.Xml.Serialization/XmlSerializationReader.cs index 32593bc4e0..de6710af0a 100644 --- a/mcs/class/System.XML/System.Xml.Serialization/XmlSerializationReader.cs +++ b/mcs/class/System.XML/System.Xml.Serialization/XmlSerializationReader.cs @@ -729,6 +729,29 @@ namespace System.Xml.Serialization return serializable; } + protected IXmlSerializable ReadSerializable (IXmlSerializable serializable, bool wrappedAny) + { + string name = null; + string ns = null; + + if (wrappedAny) { + name = reader.LocalName; + ns = reader.NamespaceURI; + reader.Read (); + reader.MoveToContent (); + } + serializable.ReadXml (reader); + + if (wrappedAny) { + while (reader.NodeType == XmlNodeType.Whitespace) reader.Skip (); + if (reader.NodeType == XmlNodeType.None) reader.Skip (); + if (reader.NodeType == XmlNodeType.EndElement && reader.LocalName == name && reader.NamespaceURI == ns) { + reader.Read (); + } + } + return serializable; + } + protected string ReadString (string value) { readCount++; diff --git a/mcs/class/System.XML/System.Xml.Serialization/XmlSerializer.cs b/mcs/class/System.XML/System.Xml.Serialization/XmlSerializer.cs index aa2852faf1..60bbc31669 100644 --- a/mcs/class/System.XML/System.Xml.Serialization/XmlSerializer.cs +++ b/mcs/class/System.XML/System.Xml.Serialization/XmlSerializer.cs @@ -37,7 +37,7 @@ using System.Reflection; using System.Xml; using System.Xml.Schema; using System.Text; -#if !NET_2_1 +#if !MOBILE using System.CodeDom; using System.CodeDom.Compiler; using Microsoft.CSharp; @@ -121,7 +121,7 @@ namespace System.Xml.Serialization // debugging pourposes by adding the "nofallback" option. // For example: MONO_XMLSERIALIZER_THS=0,nofallback -#if NET_2_1 +#if MOBILE string db = null; string th = null; generationThreshold = -1; @@ -150,7 +150,7 @@ namespace System.Xml.Serialization } #endif deleteTempFiles = (db == null || db == "no"); -#if !NET_2_1 && CONFIGURATION_DEP +#if !MOBILE && CONFIGURATION_DEP // DiagnosticsSection ConfigurationSection table = (ConfigurationSection) ConfigurationSettings.GetConfig("system.diagnostics"); var bf = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance; @@ -204,6 +204,11 @@ namespace System.Xml.Serialization { } + public XmlSerializer (Type type, XmlAttributeOverrides overrides, Type[] extraTypes, XmlRootAttribute root, string defaultNamespace, string location) + : this (type, overrides, extraTypes, root, defaultNamespace, location, null) + { + } + public XmlSerializer (Type type, XmlAttributeOverrides overrides) : this (type, overrides, null, null, null) { @@ -579,7 +584,7 @@ namespace System.Xml.Serialization } } -#if !NET_2_1 +#if !MOBILE if (!typeMapping.Source.CanBeGenerated || generationThreshold == -1) return new XmlSerializationWriterInterpreter (typeMapping); @@ -600,7 +605,7 @@ namespace System.Xml.Serialization XmlSerializationReader CreateReader (XmlMapping typeMapping) { -#if !NET_2_1 +#if !MOBILE XmlSerializationReader reader; lock (this) { @@ -630,7 +635,7 @@ namespace System.Xml.Serialization return new XmlSerializationReaderInterpreter (typeMapping); } -#if NET_2_1 +#if MOBILE void CheckGeneratedTypes (XmlMapping typeMapping) { throw new NotImplementedException(); diff --git a/mcs/class/System.XML/System.Xml.Serialization/XmlSerializerFactory.cs b/mcs/class/System.XML/System.Xml.Serialization/XmlSerializerFactory.cs index 204b67f71c..02c86fd7e6 100644 --- a/mcs/class/System.XML/System.Xml.Serialization/XmlSerializerFactory.cs +++ b/mcs/class/System.XML/System.Xml.Serialization/XmlSerializerFactory.cs @@ -61,6 +61,11 @@ namespace System.Xml.Serialization } } + public XmlSerializer CreateSerializer (Type type, XmlAttributeOverrides overrides, Type[] extraTypes, XmlRootAttribute root, string defaultNamespace, string location) + { + return CreateSerializer (type, overrides, extraTypes, root, defaultNamespace, location, null); + } + public XmlSerializer CreateSerializer (Type type, string defaultNamespace) { return CreateSerializer (type, null, null, null, defaultNamespace); diff --git a/mcs/class/System.XML/System.Xml.Xsl/XslCompiledTransform_Mobile.cs b/mcs/class/System.XML/System.Xml.Xsl/XslCompiledTransform_Mobile.cs index 94dcc0285b..e2b3432b0a 100644 --- a/mcs/class/System.XML/System.Xml.Xsl/XslCompiledTransform_Mobile.cs +++ b/mcs/class/System.XML/System.Xml.Xsl/XslCompiledTransform_Mobile.cs @@ -32,6 +32,7 @@ using System.CodeDom.Compiler; using System.Collections; using System.IO; using System.Text; +using System.Reflection; using System.Runtime.InteropServices; using System.Security; using System.Security.Policy; @@ -136,6 +137,11 @@ namespace System.Xml.Xsl Transform (input.CreateNavigator (), arguments, results, null); } + public void Transform (IXPathNavigable input, XsltArgumentList arguments, XmlWriter results, XmlResolver documentResolver) + { + Transform (input.CreateNavigator (), arguments, results, documentResolver); + } + public void Transform (XmlReader input, XsltArgumentList arguments, XmlWriter results, XmlResolver documentResolver) { Transform (new XPathDocument (input, XmlSpace.Preserve).CreateNavigator (), arguments, results, documentResolver); @@ -203,6 +209,15 @@ namespace System.Xml.Xsl Load (new XPathDocument (stylesheetUri, XmlSpace.Preserve).CreateNavigator (), settings, stylesheetResolver); } + public void Load (MethodInfo executeMethod, byte[] queryData, Type[] earlyBoundTypes) + { + throw new NotImplementedException (); + } + + public void Load (Type compiledStylesheet) + { + throw new NotImplementedException (); + } #endregion } diff --git a/mcs/class/System.XML/Test/System.Xml.Serialization/DeserializeTests.cs b/mcs/class/System.XML/Test/System.Xml.Serialization/DeserializeTests.cs index ec13691da1..1393c35420 100644 --- a/mcs/class/System.XML/Test/System.Xml.Serialization/DeserializeTests.cs +++ b/mcs/class/System.XML/Test/System.Xml.Serialization/DeserializeTests.cs @@ -1555,6 +1555,13 @@ namespace MonoTests.System.XmlSerialization Assert.AreEqual (new DateTime (2012,2,5,9,0,0,DateTimeKind.Utc), o.SomeDate.ToUniversalTime ()); } + [Test] + public void TimeWithUtc () + { + XmlSerializer xs = new XmlSerializer (typeof (UtcTimeClass)); + var o = (UtcTimeClass) xs.Deserialize (new StringReader ("12:34:56.0Z")); + Assert.AreEqual (new DateTime (1,1,1,12,34,56,DateTimeKind.Utc), o.DateTimeValue); + } public class Foo { diff --git a/mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializationWriterTests.cs b/mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializationWriterTests.cs index afa18715f2..4b81d7366f 100644 --- a/mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializationWriterTests.cs +++ b/mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializationWriterTests.cs @@ -1575,30 +1575,16 @@ namespace MonoTests.System.XmlSerialization ser.Serialize (sw, d); string str = sw.ToString (); - str = RemoveTZ (str, "MyTime"); - str = RemoveTZ (str, "MyTimeNullable"); - var expected = "" + Environment.NewLine + "" + Environment.NewLine + -" 10:00:00.0000000$TZ$" + Environment.NewLine + -" 10:00:00.0000000$TZ$" + Environment.NewLine + +" 10:00:00.0000000Z" + Environment.NewLine + +" 10:00:00.0000000Z" + Environment.NewLine + " 2012-01-03" + Environment.NewLine + " 2012-01-03" + Environment.NewLine + ""; Assert.AreEqual (expected, str); } - - static string RemoveTZ (string str, string tag) - { - var st = str.IndexOf ("<" + tag + ">"); - var et = str.IndexOf (""); - if (st < 0 || et < 0) - return str; - - var start = str.IndexOfAny (new [] { '+', '-' }, st, et - st); - return str.Substring (0, start) + "$TZ$" + str.Substring (et, str.Length - et); - } } } diff --git a/mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializerTestClasses.cs b/mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializerTestClasses.cs index 116bbe323a..4adcc11b20 100644 --- a/mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializerTestClasses.cs +++ b/mcs/class/System.XML/Test/System.Xml.Serialization/XmlSerializerTestClasses.cs @@ -1071,6 +1071,12 @@ namespace MonoTests.System.Xml.TestClasses public DateTime SomeDate; } + public class UtcTimeClass + { + [XmlElementAttribute (DataType = "time")] + public DateTime DateTimeValue; + } + public class Bug8468BaseClass { public string Base; diff --git a/mcs/class/System.XML/Test/System.Xml/XmlReaderCommonTests.cs b/mcs/class/System.XML/Test/System.Xml/XmlReaderCommonTests.cs index 16c46b496f..26f461aeb3 100644 --- a/mcs/class/System.XML/Test/System.Xml/XmlReaderCommonTests.cs +++ b/mcs/class/System.XML/Test/System.Xml/XmlReaderCommonTests.cs @@ -15,10 +15,8 @@ using System.Text; using System.Xml; using System.Xml.Schema; using System.Xml.XPath; -#if NET_4_5 using System.Threading; using System.Threading.Tasks; -#endif using NUnit.Framework; @@ -2298,7 +2296,6 @@ namespace MonoTests.System.Xml Assert.AreEqual ((UInt64) 1, xr.ReadContentAs (typeof (UInt64), null), "#8"); } -#if NET_4_5 [Test] [ExpectedException(typeof(InvalidOperationException))] public void MustSetAsyncFlag () @@ -2347,6 +2344,5 @@ namespace MonoTests.System.Xml if (task.Result != null) throw task.Result; } -#endif } } diff --git a/mcs/class/System.XML/Test/System.Xml/XmlReaderSettingsTests.cs b/mcs/class/System.XML/Test/System.Xml/XmlReaderSettingsTests.cs index effd9df94f..768cd5671d 100644 --- a/mcs/class/System.XML/Test/System.Xml/XmlReaderSettingsTests.cs +++ b/mcs/class/System.XML/Test/System.Xml/XmlReaderSettingsTests.cs @@ -419,7 +419,6 @@ namespace MonoTests.System.Xml Assert.AreEqual ("urn:foo", r.BaseURI); } -#if NET_4_5 [Test] [ExpectedException (typeof (XmlException))] public void ReadonlyAsync () @@ -444,6 +443,5 @@ namespace MonoTests.System.Xml var r2 = XmlReader.Create (r, c); Assert.IsTrue (r2.Settings.Async); } -#endif } } diff --git a/mcs/class/System.XML/Test/System.Xml/XmlResolverTest.cs b/mcs/class/System.XML/Test/System.Xml/XmlResolverTest.cs index df9756ee8f..15b2097448 100644 --- a/mcs/class/System.XML/Test/System.Xml/XmlResolverTest.cs +++ b/mcs/class/System.XML/Test/System.Xml/XmlResolverTest.cs @@ -103,7 +103,6 @@ namespace MonoTests.System.Xml { Assert.IsTrue (u2.IsAbsoluteUri, "null,absolute/file"); } -#if NET_4_5 class AsyncXmlResolver : XmlResolver { public override object GetEntity (Uri absoluteUri, string role, Type ofObjectToReturn) @@ -121,6 +120,5 @@ namespace MonoTests.System.Xml { var uri = new Uri ("http://www.mono-project.com"); ar.GetEntityAsync (uri, null, typeof(string)); } -#endif } } diff --git a/mcs/class/System.XML/Test/System.Xml/XmlSecureResolverTests.cs b/mcs/class/System.XML/Test/System.Xml/XmlSecureResolverTests.cs index 8f2de60a83..493bc6a8ad 100644 --- a/mcs/class/System.XML/Test/System.Xml/XmlSecureResolverTests.cs +++ b/mcs/class/System.XML/Test/System.Xml/XmlSecureResolverTests.cs @@ -124,7 +124,6 @@ namespace MonoTests.System.Xml Assert.IsTrue (site, "Site-2"); } -#if NET_4_5 [Test] [Category("Async")] public void TestAsync () @@ -139,7 +138,6 @@ namespace MonoTests.System.Xml Assert.That (task.Wait (3000)); Assert.IsInstanceOfType (typeof (Stream), task.Result); } -#endif } } diff --git a/mcs/class/System.XML/Test/System.Xml/XmlUrlResolverTests.cs b/mcs/class/System.XML/Test/System.Xml/XmlUrlResolverTests.cs index e62e8cebad..f637e8cc32 100644 --- a/mcs/class/System.XML/Test/System.Xml/XmlUrlResolverTests.cs +++ b/mcs/class/System.XML/Test/System.Xml/XmlUrlResolverTests.cs @@ -10,9 +10,7 @@ using System; using System.IO; using System.Xml; using NUnit.Framework; -#if NET_4_5 using System.Reflection; -#endif namespace MonoTests.System.Xml { @@ -98,7 +96,6 @@ namespace MonoTests.System.Xml Assert.AreEqual ("view:Standard.xslt", uri.AbsoluteUri, "#2"); } -#if NET_4_5 [Test] public void TestAsync () { @@ -126,6 +123,5 @@ namespace MonoTests.System.Xml Assert.IsTrue (ex is XmlException); } } -#endif } } diff --git a/mcs/class/System.XML/Test/System.Xml/XmlWriterSettingsTests.cs b/mcs/class/System.XML/Test/System.Xml/XmlWriterSettingsTests.cs index f70d43bd46..3ee725dff2 100644 --- a/mcs/class/System.XML/Test/System.Xml/XmlWriterSettingsTests.cs +++ b/mcs/class/System.XML/Test/System.Xml/XmlWriterSettingsTests.cs @@ -40,9 +40,7 @@ namespace MonoTests.System.Xml Assert.AreEqual (false, s.NewLineOnAttributes); Assert.AreEqual (false, s.OmitXmlDeclaration); Assert.AreEqual (NewLineHandling.Replace, s.NewLineHandling); -#if NET_4_5 Assert.IsFalse (s.Async); -#endif } [Test] @@ -381,7 +379,6 @@ namespace MonoTests.System.Xml Assert.AreEqual (xml, sw.ToString ()); } -#if NET_4_5 [Test] [ExpectedException (typeof (XmlException))] public void ReadonlyAsync () @@ -408,7 +405,6 @@ namespace MonoTests.System.Xml var w2 = XmlWriter.Create (w, c); Assert.IsTrue (w2.Settings.Async); } -#endif } } diff --git a/mcs/class/System.Xaml/Assembly/AssemblyInfo.cs b/mcs/class/System.Xaml/Assembly/AssemblyInfo.cs index 54cd847135..8581509e35 100644 --- a/mcs/class/System.Xaml/Assembly/AssemblyInfo.cs +++ b/mcs/class/System.Xaml/Assembly/AssemblyInfo.cs @@ -54,7 +54,7 @@ using System.Runtime.InteropServices; [assembly: NeutralResourcesLanguage ("en-US")] [assembly: CLSCompliant (true)] [assembly: AssemblyDelaySign (true)] -#if NET_2_1 +#if MOBILE [assembly: AssemblyKeyFile ("../silverlight.pub")] #else [assembly: AssemblyKeyFile ("../ecma.pub")] diff --git a/mcs/class/System.Xaml/System.Xaml/TypeExtensionMethods.cs b/mcs/class/System.Xaml/System.Xaml/TypeExtensionMethods.cs index c7002e5c8e..ccf8e0f703 100644 --- a/mcs/class/System.Xaml/System.Xaml/TypeExtensionMethods.cs +++ b/mcs/class/System.Xaml/System.Xaml/TypeExtensionMethods.cs @@ -124,7 +124,7 @@ namespace System.Xaml return TypeDescriptor.GetConverter (type); } - // FIXME: I want this to cover all the existing types and make it valid in both NET_2_1 and !NET_2_1. + // FIXME: I want this to cover all the existing types and make it valid in both MOBILE and !MOBILE. class ConvertibleTypeConverter : TypeConverter { Type type; diff --git a/mcs/class/System.Xml.Linq/Assembly/AssemblyInfo.cs b/mcs/class/System.Xml.Linq/Assembly/AssemblyInfo.cs index 169f6d1727..e6ac4809d4 100644 --- a/mcs/class/System.Xml.Linq/Assembly/AssemblyInfo.cs +++ b/mcs/class/System.Xml.Linq/Assembly/AssemblyInfo.cs @@ -54,7 +54,7 @@ using System.Runtime.InteropServices; [assembly: NeutralResourcesLanguage ("en-US")] [assembly: CLSCompliant (true)] [assembly: AssemblyDelaySign (true)] -#if NET_2_1 +#if MOBILE [assembly: AssemblyKeyFile ("../winfx.pub")] #else [assembly: AssemblyKeyFile ("../ecma.pub")] diff --git a/mcs/class/System.Xml.Linq/Test/System.Xml.Linq/XElementTest.cs.REMOVED.git-id b/mcs/class/System.Xml.Linq/Test/System.Xml.Linq/XElementTest.cs.REMOVED.git-id index 4f2944ce29..2d558c5525 100644 --- a/mcs/class/System.Xml.Linq/Test/System.Xml.Linq/XElementTest.cs.REMOVED.git-id +++ b/mcs/class/System.Xml.Linq/Test/System.Xml.Linq/XElementTest.cs.REMOVED.git-id @@ -1 +1 @@ -dc395b7d110e122b8dcf779cc8490f9e24ffb6e7 \ No newline at end of file +5415ff8e50a4beb760cc5825406fd6e49e7a3989 \ No newline at end of file diff --git a/mcs/class/System/Assembly/AssemblyInfo.cs b/mcs/class/System/Assembly/AssemblyInfo.cs index 69456085a2..6ed83d7c1e 100644 --- a/mcs/class/System/Assembly/AssemblyInfo.cs +++ b/mcs/class/System/Assembly/AssemblyInfo.cs @@ -55,33 +55,26 @@ using System.Runtime.InteropServices; [assembly: NeutralResourcesLanguage ("en-US")] [assembly: ComVisible (false)] -#if !NET_2_1 +#if !MOBILE [assembly: ComCompatibleVersion (1, 0, 3300, 0)] [assembly: AllowPartiallyTrustedCallers] #endif #if !BOOTSTRAP_WITH_OLDLIB [assembly: AssemblyDelaySign (true)] -#if NET_2_1 +#if MOBILE [assembly: AssemblyKeyFile ("../silverlight.pub")] #else [assembly: AssemblyKeyFile ("../ecma.pub")] #endif #endif -#if NET_2_1 && !MOBILE - [assembly: InternalsVisibleTo ("System.Net, PublicKey=00240000048000009400000006020000002400005253413100040000010001008D56C76F9E8649383049F383C44BE0EC204181822A6C31CF5EB7EF486944D032188EA1D3920763712CCB12D75FB77E9811149E6148E5D32FBAAB37611C1878DDC19E20EF135D0CB2CFF2BFEC3D115810C3D9069638FE4BE215DBF795861920E5AB6F7DB2E2CEEF136AC23D5DD2BF031700AEC232F6C6B1C785B4305C123B37AB")] -#else [assembly: InternalsVisibleTo ("System.ComponentModel.DataAnnotations, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] [assembly: InternalsVisibleTo ("System.Net.Http, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")] [assembly: StringFreezing] [assembly: DefaultDependency (LoadHint.Always)] -#endif - [assembly: InternalsVisibleTo ("Mono.Security.Providers.NewSystemSource, PublicKey=002400000480000094000000060200000024000052534131000400000100010079159977d2d03a8e6bea7a2e74e8d1afcc93e8851974952bb480a12c9134474d04062447c37e0e68c080536fcf3c3fbe2ff9c979ce998475e506e8ce82dd5b0f350dc10e93bf2eeecf874b24770c5081dbea7447fddafa277b22de47d6ffea449674a4f9fccf84d15069089380284dbdd35f46cdff12a1bd78e4ef0065d016df")] - [assembly: InternalsVisibleTo ("Mono.Security.Providers.OldTls, PublicKey=002400000480000094000000060200000024000052534131000400000100010079159977d2d03a8e6bea7a2e74e8d1afcc93e8851974952bb480a12c9134474d04062447c37e0e68c080536fcf3c3fbe2ff9c979ce998475e506e8ce82dd5b0f350dc10e93bf2eeecf874b24770c5081dbea7447fddafa277b22de47d6ffea449674a4f9fccf84d15069089380284dbdd35f46cdff12a1bd78e4ef0065d016df")] - [assembly: InternalsVisibleTo ("Mono.Security.Providers.NewTls, PublicKey=002400000480000094000000060200000024000052534131000400000100010079159977d2d03a8e6bea7a2e74e8d1afcc93e8851974952bb480a12c9134474d04062447c37e0e68c080536fcf3c3fbe2ff9c979ce998475e506e8ce82dd5b0f350dc10e93bf2eeecf874b24770c5081dbea7447fddafa277b22de47d6ffea449674a4f9fccf84d15069089380284dbdd35f46cdff12a1bd78e4ef0065d016df")] - [assembly: InternalsVisibleTo ("Mono.Security.Providers.DotNet, PublicKey=002400000480000094000000060200000024000052534131000400000100010079159977d2d03a8e6bea7a2e74e8d1afcc93e8851974952bb480a12c9134474d04062447c37e0e68c080536fcf3c3fbe2ff9c979ce998475e506e8ce82dd5b0f350dc10e93bf2eeecf874b24770c5081dbea7447fddafa277b22de47d6ffea449674a4f9fccf84d15069089380284dbdd35f46cdff12a1bd78e4ef0065d016df")] + [assembly: InternalsVisibleTo ("btls-cert-sync, PublicKey=002400000480000094000000060200000024000052534131000400000100010079159977d2d03a8e6bea7a2e74e8d1afcc93e8851974952bb480a12c9134474d04062447c37e0e68c080536fcf3c3fbe2ff9c979ce998475e506e8ce82dd5b0f350dc10e93bf2eeecf874b24770c5081dbea7447fddafa277b22de47d6ffea449674a4f9fccf84d15069089380284dbdd35f46cdff12a1bd78e4ef0065d016df")] + [assembly: InternalsVisibleTo ("Mono.Btls.Interface, PublicKey=002400000480000094000000060200000024000052534131000400000100010079159977d2d03a8e6bea7a2e74e8d1afcc93e8851974952bb480a12c9134474d04062447c37e0e68c080536fcf3c3fbe2ff9c979ce998475e506e8ce82dd5b0f350dc10e93bf2eeecf874b24770c5081dbea7447fddafa277b22de47d6ffea449674a4f9fccf84d15069089380284dbdd35f46cdff12a1bd78e4ef0065d016df")] [assembly: InternalsVisibleTo ("Mono.Security, PublicKey=002400000480000094000000060200000024000052534131000400000100010079159977d2d03a8e6bea7a2e74e8d1afcc93e8851974952bb480a12c9134474d04062447c37e0e68c080536fcf3c3fbe2ff9c979ce998475e506e8ce82dd5b0f350dc10e93bf2eeecf874b24770c5081dbea7447fddafa277b22de47d6ffea449674a4f9fccf84d15069089380284dbdd35f46cdff12a1bd78e4ef0065d016df")] - [assembly: InternalsVisibleTo ("Xamarin.BoringTls, PublicKey=002400000480000094000000060200000024000052534131000400001100000099dd12eda85767ae6f06023ee28e711c7e5a212462095c83868c29db75eddf6d8e296e03824c14fedd5f55553fed0b6173be3cc985a4b7f9fb7c83ccff8ba3938563b3d1f45a81122f12a1bcb73edcaad61a8456c7595a6da5184b4dd9d10f011b949ef1391fccfeab1ba62aa51c267ef8bd57ef1b6ba5a4c515d0badb81a78f")] diff --git a/mcs/class/System/Makefile b/mcs/class/System/Makefile index d4c83ee497..3b75713e6d 100644 --- a/mcs/class/System/Makefile +++ b/mcs/class/System/Makefile @@ -19,7 +19,17 @@ TEST_RESOURCES = \ Test/System/test-uri-props-manual.txt \ Test/System/test-uri-relative-props.txt -TEST_LIB_REFS = System.Drawing Mono.Security System.Data System.Xml System.Core System.Configuration +ifndef NO_MONO_SECURITY +MONO_SECURITY=Mono.Security +MONO_SECURITY_REF=MonoSecurity=Mono.Security +MONO_SECURITY_DLL=$(the_libdir_base)Mono.Security.dll +endif + +ifndef MOBILE_PROFILE +TEST_LIB_REFS = System.Drawing $(MONO_SECURITY) System.Data System.Xml System.Core System.Configuration +else +TEST_LIB_REFS = $(MONO_SECURITY) System.Data System.Xml System.Core +endif TEST_MCS_FLAGS = -nowarn:618,672,219,67,169,612 \ $(foreach f, $(TEST_RESOURCES), -resource:$(f),$(notdir $(f))) @@ -32,6 +42,18 @@ endif LIB_MCS_FLAGS = -nowarn:618 -d:CONFIGURATION_2_0 $(REFERENCE_SOURCES_FLAGS) -unsafe $(RESOURCE_FILES:%=-resource:%) +ifndef PROFILE_DISABLE_BTLS +ifdef HAVE_BTLS + +LIB_MCS_FLAGS += -d:MONO_FEATURE_BTLS + +ifdef HAVE_DYNAMIC_BTLS +LIB_MCS_FLAGS += -d:MONO_FEATURE_DYNAMIC_BTLS +endif + +endif +endif + ifndef NO_THREAD_ABORT REFERENCE_SOURCES_FLAGS += -d:MONO_FEATURE_THREAD_ABORT TEST_MCS_FLAGS += -d:MONO_FEATURE_THREAD_ABORT @@ -42,6 +64,11 @@ REFERENCE_SOURCES_FLAGS += -d:MONO_FEATURE_THREAD_SUSPEND_RESUME TEST_MCS_FLAGS += -d:MONO_FEATURE_THREAD_SUSPEND_RESUME endif +ifndef NO_MULTIPLE_APPDOMAINS +REFERENCE_SOURCES_FLAGS += -d:MONO_FEATURE_MULTIPLE_APPDOMAINS +TEST_MCS_FLAGS += -d:MONO_FEATURE_MULTIPLE_APPDOMAINS +endif + TXT_RESOURCE_STRINGS = ../referencesource/System/System.txt # @@ -58,7 +85,7 @@ endif # ifeq (secxml/, $(intermediate)) LOCAL_MCS_FLAGS = -LIB_REFS += bare/System.Xml MonoSecurity=Mono.Security +LIB_REFS += bare/System.Xml $(MONO_SECURITY_REF) LIB_MCS_FLAGS += -d:SECURITY_DEP -d:XML_DEP $(EXTERN_ALIAS_FLAGS) endif @@ -66,7 +93,7 @@ endif # Flags used to build the final version of System (when intermediate is not defined) # ifndef intermediate -LIB_REFS += System.Xml MonoSecurity=Mono.Security +LIB_REFS += System.Xml $(MONO_SECURITY_REF) LIB_MCS_FLAGS += -d:SECURITY_DEP -d:XML_DEP $(EXTERN_ALIAS_FLAGS) ifndef MOBILE_PROFILE @@ -90,7 +117,7 @@ include ../../build/library.make system_library_deps := \ $(secxml_libdir)/System.dll \ $(the_libdir_base)System.Xml.dll \ - $(the_libdir_base)Mono.Security.dll \ + $(MONO_SECURITY_DLL) \ $(bare_libdir)/System.dll ifndef MOBILE_PROFILE @@ -99,7 +126,7 @@ endif artifacts = $(system_library_deps) \ $(bare_libdir)/System.Xml.dll \ - $(the_libdir_base)Mono.Security.dll \ + $(MONO_SECURITY_DLL) \ $(the_libdir_base)System.Configuration.dll .NOTPARALLEL: $(system_library_deps) @@ -114,7 +141,7 @@ $(bare_libdir)/System.dll: endif ifneq (secxml/,$(intermediate)) -$(secxml_libdir)/System.dll: $(bare_libdir)/System.dll $(bare_libdir)/System.Xml.dll $(the_libdir_base)Mono.Security.dll $(bare_libdir)/System.dll +$(secxml_libdir)/System.dll: $(bare_libdir)/System.dll $(bare_libdir)/System.Xml.dll $(MONO_SECURITY_DLL) $(bare_libdir)/System.dll $(MAKE) intermediate=secxml/ $(secxml_libdir)/System.dll else build-sec: diff --git a/mcs/class/System/Microsoft.Win32.SafeHandles/SafeX509ChainHandle.cs b/mcs/class/System/Microsoft.Win32.SafeHandles/SafeX509ChainHandle.cs index f3091aa38b..9bad4ea25d 100644 --- a/mcs/class/System/Microsoft.Win32.SafeHandles/SafeX509ChainHandle.cs +++ b/mcs/class/System/Microsoft.Win32.SafeHandles/SafeX509ChainHandle.cs @@ -34,25 +34,16 @@ using System.Security; namespace Microsoft.Win32.SafeHandles { - public sealed class SafeX509ChainHandle : SafeHandle + public sealed class SafeX509ChainHandle : SafeHandleZeroOrMinusOneIsInvalid { - [MonoTODO] - public override bool IsInvalid - { - get - { - throw new NotImplementedException (); - } - } - - [MonoTODO] - internal SafeX509ChainHandle() : base ((IntPtr)0, false) + internal SafeX509ChainHandle (IntPtr handle) + : base (true) { throw new NotImplementedException (); } [MonoTODO] - protected override bool ReleaseHandle() + protected override bool ReleaseHandle () { throw new NotImplementedException (); } diff --git a/mcs/class/System/Mono.Btls/MonoBtlsBio.cs b/mcs/class/System/Mono.Btls/MonoBtlsBio.cs new file mode 100644 index 0000000000..204d167928 --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsBio.cs @@ -0,0 +1,449 @@ +// +// MonoBtlsBio.cs +// +// Author: +// Martin Baulig +// +// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +#if SECURITY_DEP && MONO_FEATURE_BTLS +using System; +using System.IO; +using System.Text; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +#if MONOTOUCH +using MonoTouch; +#endif + +namespace Mono.Btls +{ + class MonoBtlsBio : MonoBtlsObject + { + internal MonoBtlsBio (BoringBioHandle handle) + : base (handle) + { + } + + new protected internal BoringBioHandle Handle { + get { return (BoringBioHandle)base.Handle; } + } + + protected internal class BoringBioHandle : MonoBtlsHandle + { + public BoringBioHandle (IntPtr handle) + : base (handle, true) + { + } + + protected override bool ReleaseHandle () + { + if (handle != IntPtr.Zero) { + mono_btls_bio_free (handle); + handle = IntPtr.Zero; + } + return true; + } + + } + + public static MonoBtlsBio CreateMonoStream (Stream stream) + { + return MonoBtlsBioMono.CreateStream (stream, false); + } + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_bio_read (IntPtr bio, IntPtr data, int len); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_bio_write (IntPtr bio, IntPtr data, int len); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_bio_flush (IntPtr bio); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_bio_indent (IntPtr bio, uint indent, uint max_indent); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_bio_hexdump (IntPtr bio, IntPtr data, int len, uint indent); + + [DllImport (BTLS_DYLIB)] + extern static void mono_btls_bio_print_errors (IntPtr bio); + + [DllImport (BTLS_DYLIB)] + extern static void mono_btls_bio_free (IntPtr handle); + + public int Read (byte[] buffer, int offset, int size) + { + CheckThrow (); + var data = Marshal.AllocHGlobal (size); + if (data == IntPtr.Zero) + throw new OutOfMemoryException (); + + bool release = false; + try { + Handle.DangerousAddRef (ref release); + var ret = mono_btls_bio_read (Handle.DangerousGetHandle (), data, size); + if (ret > 0) + Marshal.Copy (data, buffer,offset, ret); + return ret; + } finally { + if (release) + Handle.DangerousRelease (); + Marshal.FreeHGlobal (data); + } + } + + public int Write (byte[] buffer, int offset, int size) + { + CheckThrow (); + var data = Marshal.AllocHGlobal (size); + if (data == IntPtr.Zero) + throw new OutOfMemoryException (); + + bool release = false; + try { + Handle.DangerousAddRef (ref release); + Marshal.Copy (buffer, offset, data, size); + return mono_btls_bio_write (Handle.DangerousGetHandle (), data, size); + } finally { + if (release) + Handle.DangerousRelease (); + Marshal.FreeHGlobal (data); + } + } + + public int Flush () + { + CheckThrow (); + bool release = false; + try { + Handle.DangerousAddRef (ref release); + return mono_btls_bio_flush (Handle.DangerousGetHandle ()); + } finally { + if (release) + Handle.DangerousRelease (); + } + } + + public int Indent (uint indent, uint max_indent) + { + CheckThrow (); + bool release = false; + try { + Handle.DangerousAddRef (ref release); + return mono_btls_bio_indent (Handle.DangerousGetHandle (), indent, max_indent); + } finally { + if (release) + Handle.DangerousRelease (); + } + } + + public int HexDump (byte[] buffer, uint indent) + { + CheckThrow (); + var data = Marshal.AllocHGlobal (buffer.Length); + if (data == IntPtr.Zero) + throw new OutOfMemoryException (); + + bool release = false; + try { + Handle.DangerousAddRef (ref release); + Marshal.Copy (buffer, 0, data, buffer.Length); + return mono_btls_bio_hexdump (Handle.DangerousGetHandle (), data, buffer.Length, indent); + } finally { + if (release) + Handle.DangerousRelease (); + Marshal.FreeHGlobal (data); + } + } + + public void PrintErrors () + { + CheckThrow (); + bool release = false; + try { + Handle.DangerousAddRef (ref release); + mono_btls_bio_print_errors (Handle.DangerousGetHandle ()); + } finally { + if (release) + Handle.DangerousRelease (); + } + } + } + + class MonoBtlsBioMemory : MonoBtlsBio + { + [DllImport (BTLS_DYLIB)] + extern static IntPtr mono_btls_bio_mem_new (); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_bio_mem_get_data (IntPtr handle, out IntPtr data); + + public MonoBtlsBioMemory () + : base (new BoringBioHandle (mono_btls_bio_mem_new ())) + { + } + + public byte[] GetData () + { + IntPtr data; + bool release = false; + try { + Handle.DangerousAddRef (ref release); + var size = mono_btls_bio_mem_get_data (Handle.DangerousGetHandle (), out data); + CheckError (size > 0); + var buffer = new byte[size]; + Marshal.Copy (data, buffer, 0, size); + return buffer; + } finally { + if (release) + Handle.DangerousRelease (); + } + } + } + + interface IMonoBtlsBioMono + { + int Read (byte[] buffer, int offset, int size, out bool wantMore); + + bool Write (byte[] buffer, int offset, int size); + + void Flush (); + + void Close (); + } + + class MonoBtlsBioMono : MonoBtlsBio + { + GCHandle handle; + IntPtr instance; + BioReadFunc readFunc; + BioWriteFunc writeFunc; + BioControlFunc controlFunc; + IntPtr readFuncPtr; + IntPtr writeFuncPtr; + IntPtr controlFuncPtr; + IMonoBtlsBioMono backend; + + public MonoBtlsBioMono (IMonoBtlsBioMono backend) + : base (new BoringBioHandle (mono_btls_bio_mono_new ())) + { + this.backend = backend; + handle = GCHandle.Alloc (this); + instance = GCHandle.ToIntPtr (handle); + readFunc = OnRead; + writeFunc = OnWrite; + controlFunc = Control; + readFuncPtr = Marshal.GetFunctionPointerForDelegate (readFunc); + writeFuncPtr = Marshal.GetFunctionPointerForDelegate (writeFunc); + controlFuncPtr = Marshal.GetFunctionPointerForDelegate (controlFunc); + mono_btls_bio_mono_initialize (Handle.DangerousGetHandle (), instance, readFuncPtr, writeFuncPtr, controlFuncPtr); + } + + public static MonoBtlsBioMono CreateStream (Stream stream, bool ownsStream) + { + return new MonoBtlsBioMono (new StreamBackend (stream, ownsStream)); + } + + public static MonoBtlsBioMono CreateString (StringWriter writer) + { + return new MonoBtlsBioMono (new StringBackend (writer)); + } + + enum ControlCommand + { + Flush = 1 + } + + delegate int BioReadFunc (IntPtr bio, IntPtr data, int dataLength, out int wantMore); + delegate int BioWriteFunc (IntPtr bio, IntPtr data, int dataLength); + delegate long BioControlFunc (IntPtr bio, ControlCommand command, long arg); + + [DllImport (BTLS_DYLIB)] + extern static IntPtr mono_btls_bio_mono_new (); + + [DllImport (BTLS_DYLIB)] + extern static void mono_btls_bio_mono_initialize (IntPtr handle, IntPtr instance, IntPtr readFunc, IntPtr writeFunc, IntPtr controlFunc); + + long Control (ControlCommand command, long arg) + { + switch (command) { + case ControlCommand.Flush: + backend.Flush (); + return 1; + + default: + throw new NotImplementedException (); + } + } + + int OnRead (IntPtr data, int dataLength, out int wantMore) + { + bool wantMoreBool; + var buffer = new byte[dataLength]; + var ret = backend.Read (buffer, 0, dataLength, out wantMoreBool); + wantMore = wantMoreBool ? 1 : 0; + if (ret <= 0) + return ret; + Marshal.Copy (buffer, 0, data, ret); + return ret; + } + +#if MONOTOUCH + [MonoPInvokeCallback (typeof (BioReadFunc))] +#endif + static int OnRead (IntPtr instance, IntPtr data, int dataLength, out int wantMore) + { + var c = (MonoBtlsBioMono)GCHandle.FromIntPtr (instance).Target; + try { + return c.OnRead (data, dataLength, out wantMore); + } catch (Exception ex) { + c.SetException (ex); + wantMore = 0; + return -1; + } + } + + int OnWrite (IntPtr data, int dataLength) + { + var buffer = new byte[dataLength]; + Marshal.Copy (data, buffer, 0, dataLength); + var ok = backend.Write (buffer, 0, dataLength); + return ok ? dataLength : -1; + } + +#if MONOTOUCH + [MonoPInvokeCallback (typeof (BioWriteFunc))] +#endif + static int OnWrite (IntPtr instance, IntPtr data, int dataLength) + { + var c = (MonoBtlsBioMono)GCHandle.FromIntPtr (instance).Target; + try { + return c.OnWrite (data, dataLength); + } catch (Exception ex) { + c.SetException (ex); + return -1; + } + } + +#if MONOTOUCH + [MonoPInvokeCallback (typeof (BioControlFunc))] +#endif + static long Control (IntPtr instance, ControlCommand command, long arg) + { + var c = (MonoBtlsBioMono)GCHandle.FromIntPtr (instance).Target; + try { + return c.Control (command, arg); + } catch (Exception ex) { + c.SetException (ex); + return -1; + } + } + + protected override void Close () + { + try { + if (backend != null) { + backend.Close (); + backend = null; + } + if (handle.IsAllocated) + handle.Free (); + } finally { + base.Close (); + } + } + + class StreamBackend : IMonoBtlsBioMono + { + Stream stream; + bool ownsStream; + + public Stream InnerStream { + get { return stream; } + } + + public StreamBackend (Stream stream, bool ownsStream) + { + this.stream = stream; + this.ownsStream = ownsStream; + } + + public int Read (byte[] buffer, int offset, int size, out bool wantMore) + { + wantMore = false; + return stream.Read (buffer, offset, size); + } + + public bool Write (byte[] buffer, int offset, int size) + { + stream.Write (buffer, offset, size); + return true; + } + + public void Flush () + { + stream.Flush (); + } + + public void Close () + { + if (ownsStream && stream != null) + stream.Dispose (); + stream = null; + } + } + + class StringBackend : IMonoBtlsBioMono + { + StringWriter writer; + Encoding encoding = new UTF8Encoding (); + + public StringBackend (StringWriter writer) + { + this.writer = writer; + } + + public int Read (byte[] buffer, int offset, int size, out bool wantMore) + { + wantMore = false; + return -1; + } + + public bool Write (byte[] buffer, int offset, int size) + { + var text = encoding.GetString (buffer, offset, size); + writer.Write (text); + return true; + } + + public void Flush () + { + } + + public void Close () + { + } + } + } +} +#endif diff --git a/mcs/class/System/Mono.Btls/MonoBtlsContext.cs b/mcs/class/System/Mono.Btls/MonoBtlsContext.cs new file mode 100644 index 0000000000..2df24d9793 --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsContext.cs @@ -0,0 +1,454 @@ +// +// MonoBtlsContext.cs +// +// Author: +// Martin Baulig +// +// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +#if SECURITY_DEP && MONO_FEATURE_BTLS +#if MONO_SECURITY_ALIAS +extern alias MonoSecurity; +#endif + +using System; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using System.Security.Cryptography.X509Certificates; +using System.Security.Authentication; +using System.Runtime.InteropServices; + +#if MONO_SECURITY_ALIAS +using MonoSecurity::Mono.Security.Interface; +#else +using Mono.Security.Interface; +#endif + +using MNS = Mono.Net.Security; + +namespace Mono.Btls +{ + class MonoBtlsContext : MNS.MobileTlsContext, IMonoBtlsBioMono + { + X509Certificate remoteCertificate; + X509Certificate clientCertificate; + X509CertificateImplBtls nativeServerCertificate; + X509CertificateImplBtls nativeClientCertificate; + MonoBtlsSslCtx ctx; + MonoBtlsSsl ssl; + MonoBtlsBio bio; + MonoBtlsBio errbio; + + MonoTlsConnectionInfo connectionInfo; + bool certificateValidated; + bool isAuthenticated; + bool connected; + + public MonoBtlsContext ( + MNS.MobileAuthenticatedStream parent, + bool serverMode, string targetHost, + SslProtocols enabledProtocols, X509Certificate serverCertificate, + X509CertificateCollection clientCertificates, bool askForClientCert) + : base (parent, serverMode, targetHost, enabledProtocols, + serverCertificate, clientCertificates, askForClientCert) + { + if (serverMode) + nativeServerCertificate = GetPrivateCertificate (serverCertificate); + } + + static X509CertificateImplBtls GetPrivateCertificate (X509Certificate certificate) + { + var impl = certificate.Impl as X509CertificateImplBtls; + if (impl != null) + return (X509CertificateImplBtls)impl.Clone (); + + var password = Guid.NewGuid ().ToString (); + var buffer = certificate.Export (X509ContentType.Pfx, password); + + impl = new X509CertificateImplBtls (); + impl.Import (buffer, password, X509KeyStorageFlags.DefaultKeySet); + return impl; + } + + new public MonoBtlsProvider Provider { + get { return (MonoBtlsProvider)base.Provider; } + } + + int VerifyCallback (MonoBtlsX509StoreCtx storeCtx) + { + using (var chainImpl = new X509ChainImplBtls (storeCtx)) + using (var managedChain = new X509Chain (chainImpl)) { + var leaf = managedChain.ChainElements[0].Certificate; + var result = ValidateCertificate (leaf, managedChain); + certificateValidated = true; + return result ? 1 : 0; + } + } + + int SelectCallback () + { + Debug ("SELECT CALLBACK!"); + + GetPeerCertificate (); + if (remoteCertificate == null) + throw new TlsException (AlertDescription.InternalError, "Cannot request client certificate before receiving one from the server."); + + var clientCert = SelectClientCertificate (remoteCertificate, null); + Debug ("SELECT CALLBACK #1: {0}", clientCert); + if (clientCert == null) + return 1; + + nativeClientCertificate = GetPrivateCertificate (clientCert); + Debug ("SELECT CALLBACK #2: {0}", nativeClientCertificate); + clientCertificate = new X509Certificate (nativeClientCertificate); + SetPrivateCertificate (nativeClientCertificate); + return 1; + } + + public override void StartHandshake () + { + InitializeConnection (); + + ssl = new MonoBtlsSsl (ctx); + + bio = new MonoBtlsBioMono (this); + ssl.SetBio (bio); + + if (IsServer) { + SetPrivateCertificate (nativeServerCertificate); + } else { + ssl.SetServerName (TargetHost); + } + } + + void SetPrivateCertificate (X509CertificateImplBtls privateCert) + { + Debug ("SetPrivateCertificate: {0}", privateCert); + ssl.SetCertificate (privateCert.X509); + ssl.SetPrivateKey (privateCert.NativePrivateKey); + var intermediate = privateCert.IntermediateCertificates; + if (intermediate == null) + return; + for (int i = 0; i < intermediate.Count; i++) { + var impl = (X509CertificateImplBtls)intermediate [i]; + Debug ("SetPrivateCertificate - add intermediate: {0}", impl); + ssl.AddIntermediateCertificate (impl.X509); + } + } + + Exception GetException (MonoBtlsSslError status) + { + var error = MonoBtlsError.GetError (); + if (error == null) + return new MonoBtlsException (status); + + var text = MonoBtlsError.GetErrorString (error); + return new MonoBtlsException ("{0} {1}", status, text); + } + + public override bool ProcessHandshake () + { + var done = false; + while (!done) { + Debug ("ProcessHandshake"); + MonoBtlsError.ClearError (); + var status = DoProcessHandshake (); + Debug ("ProcessHandshake #1: {0}", status); + + switch (status) { + case MonoBtlsSslError.None: + if (connected) + done = true; + else + connected = true; + break; + case MonoBtlsSslError.WantRead: + case MonoBtlsSslError.WantWrite: + return false; + default: + throw GetException (status); + } + } + + ssl.PrintErrors (); + + return true; + } + + MonoBtlsSslError DoProcessHandshake () + { + if (connected) + return ssl.Handshake (); + else if (IsServer) + return ssl.Accept (); + else + return ssl.Connect (); + } + + public override void FinishHandshake () + { + InitializeSession (); + + isAuthenticated = true; + } + + void SetupCertificateStore () + { + MonoBtlsProvider.SetupCertificateStore (ctx.CertificateStore); + + if (Settings != null && Settings.TrustAnchors != null) { + var trust = IsServer ? MonoBtlsX509TrustKind.TRUST_CLIENT : MonoBtlsX509TrustKind.TRUST_SERVER; + ctx.CertificateStore.AddCollection (Settings.TrustAnchors, trust); + } + } + + void InitializeConnection () + { + ctx = new MonoBtlsSslCtx (); + +#if MARTIN_DEBUG + errbio = MonoBtlsBio.CreateMonoStream (Console.OpenStandardError ()); + ctx.SetDebugBio (errbio); +#endif + + SetupCertificateStore (); + + if (!IsServer || AskForClientCertificate) + ctx.SetVerifyCallback (VerifyCallback, false); + if (!IsServer) + ctx.SetSelectCallback (SelectCallback); + + var host = TargetHost; + if (!string.IsNullOrEmpty (host)) { + var pos = TargetHost.IndexOf (':'); + if (pos > 0) + host = host.Substring (0, pos); + } + + ctx.SetVerifyParam (MonoBtlsProvider.GetVerifyParam (host, IsServer)); + + TlsProtocolCode minProtocol, maxProtocol; + GetProtocolVersions (out minProtocol, out maxProtocol); + + ctx.SetMinVersion ((int)minProtocol); + ctx.SetMaxVersion ((int)maxProtocol); + + if (Settings != null && Settings.EnabledCiphers != null) { + var ciphers = new short [Settings.EnabledCiphers.Length]; + for (int i = 0; i < ciphers.Length; i++) + ciphers [i] = (short)Settings.EnabledCiphers [i]; + ctx.SetCiphers (ciphers, true); + } + } + + void GetPeerCertificate () + { + if (remoteCertificate != null) + return; + using (var remoteCert = ssl.GetPeerCertificate ()) { + if (remoteCert != null) + remoteCertificate = MonoBtlsProvider.CreateCertificate (remoteCert); + } + } + + void InitializeSession () + { + GetPeerCertificate (); + + if (IsServer && AskForClientCertificate && !certificateValidated) { + if (!ValidateCertificate (null, null)) + throw new TlsException (AlertDescription.CertificateUnknown); + } + + var cipher = (CipherSuiteCode)ssl.GetCipher (); + var protocol = (TlsProtocolCode)ssl.GetVersion (); + Debug ("GET CONNECTION INFO: {0:x}:{0} {1:x}:{1} {2}", cipher, protocol, (TlsProtocolCode)protocol); + + connectionInfo = new MonoTlsConnectionInfo { + CipherSuiteCode = cipher, + ProtocolVersion = GetProtocol (protocol) + }; + } + + static TlsProtocols GetProtocol (TlsProtocolCode protocol) + { + switch (protocol) { + case TlsProtocolCode.Tls10: + return TlsProtocols.Tls10; + case TlsProtocolCode.Tls11: + return TlsProtocols.Tls11; + case TlsProtocolCode.Tls12: + return TlsProtocols.Tls12; + default: + throw new NotSupportedException (); + } + } + + public override void Flush () + { + throw new NotImplementedException (); + } + + public override int Read (byte[] buffer, int offset, int size, out bool wantMore) + { + Debug ("Read: {0} {1} {2}", buffer.Length, offset, size); + + var data = Marshal.AllocHGlobal (size); + if (data == IntPtr.Zero) + throw new OutOfMemoryException (); + + try { + MonoBtlsError.ClearError (); + var status = ssl.Read (data, ref size); + Debug ("Read done: {0} {1}", status, size); + + if (status == MonoBtlsSslError.WantRead) { + wantMore = true; + return 0; + } else if (status != MonoBtlsSslError.None) { + throw GetException (status); + } + + if (size > 0) + Marshal.Copy (data, buffer, offset, size); + + wantMore = false; + return size; + } finally { + Marshal.FreeHGlobal (data); + } + } + + public override int Write (byte[] buffer, int offset, int size, out bool wantMore) + { + Debug ("Write: {0} {1} {2}", buffer.Length, offset, size); + + var data = Marshal.AllocHGlobal (size); + if (data == IntPtr.Zero) + throw new OutOfMemoryException (); + + try { + MonoBtlsError.ClearError (); + Marshal.Copy (buffer, offset, data, size); + var status = ssl.Write (data, ref size); + Debug ("Write done: {0} {1}", status, size); + + if (status == MonoBtlsSslError.WantWrite) { + wantMore = true; + return 0; + } else if (status != MonoBtlsSslError.None) { + throw GetException (status); + } + + wantMore = false; + return size; + } finally { + Marshal.FreeHGlobal (data); + } + } + + public override void Close () + { + Debug ("Close!"); + ssl.Dispose (); + } + + void Dispose (ref T disposable) + where T : class, IDisposable + { + try { + if (disposable != null) + disposable.Dispose (); + } catch { + ; + } finally { + disposable = null; + } + } + + protected override void Dispose (bool disposing) + { + try { + if (disposing) { + Dispose (ref remoteCertificate); + Dispose (ref nativeServerCertificate); + Dispose (ref nativeClientCertificate); + Dispose (ref clientCertificate); + Dispose (ref ctx); + Dispose (ref ssl); + Dispose (ref bio); + Dispose (ref errbio); + } + } finally { + base.Dispose (disposing); + } + } + + int IMonoBtlsBioMono.Read (byte[] buffer, int offset, int size, out bool wantMore) + { + Debug ("InternalRead: {0} {1}", offset, size); + var ret = Parent.InternalRead (buffer, offset, size, out wantMore); + Debug ("InternalReadDone: {0} {1}", ret, wantMore); + return ret; + } + + bool IMonoBtlsBioMono.Write (byte[] buffer, int offset, int size) + { + Debug ("InternalWrite: {0} {1}", offset, size); + var ret = Parent.InternalWrite (buffer, offset, size); + Debug ("InternalWrite done: {0}", ret); + return ret; + } + + void IMonoBtlsBioMono.Flush () + { + ; + } + + void IMonoBtlsBioMono.Close () + { + ; + } + + public override bool HasContext { + get { return ssl != null && ssl.IsValid; } + } + public override bool IsAuthenticated { + get { return isAuthenticated; } + } + public override MonoTlsConnectionInfo ConnectionInfo { + get { return connectionInfo; } + } + internal override bool IsRemoteCertificateAvailable { + get { return remoteCertificate != null; } + } + internal override X509Certificate LocalClientCertificate { + get { return clientCertificate; } + } + public override X509Certificate RemoteCertificate { + get { return remoteCertificate; } + } + public override TlsProtocols NegotiatedProtocol { + get { return connectionInfo.ProtocolVersion; } + } + } +} +#endif diff --git a/mcs/class/System/Mono.Btls/MonoBtlsError.cs b/mcs/class/System/Mono.Btls/MonoBtlsError.cs new file mode 100644 index 0000000000..5e61bcf046 --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsError.cs @@ -0,0 +1,83 @@ +// +// MonoBtlsError.cs +// +// Author: +// Martin Baulig +// +// Copyright (c) 2015 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +#if SECURITY_DEP && MONO_FEATURE_BTLS +using System; +using System.IO; +using System.Text; +using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; + +#if MONOTOUCH +using MonoTouch; +#endif + +namespace Mono.Btls +{ + static class MonoBtlsError + { + [DllImport (MonoBtlsObject.BTLS_DYLIB)] + extern static int mono_btls_error_peek_error (); + + [DllImport (MonoBtlsObject.BTLS_DYLIB)] + extern static int mono_btls_error_get_error (); + + [DllImport (MonoBtlsObject.BTLS_DYLIB)] + extern static void mono_btls_error_clear_error (); + + [DllImport (MonoBtlsObject.BTLS_DYLIB)] + extern static void mono_btls_error_get_error_string_n (int error, IntPtr buf, int len); + + public static int PeekError () + { + return mono_btls_error_peek_error (); + } + + public static int GetError () + { + return mono_btls_error_get_error (); + } + + public static void ClearError () + { + mono_btls_error_clear_error (); + } + + public static string GetErrorString (int error) + { + var size = 1024; + var buffer = Marshal.AllocHGlobal (size); + if (buffer == IntPtr.Zero) + throw new OutOfMemoryException (); + try { + mono_btls_error_get_error_string_n (error, buffer, size); + return Marshal.PtrToStringAnsi (buffer); + } finally { + Marshal.FreeHGlobal (buffer); + } + } + } +} +#endif diff --git a/mcs/class/System/Mono.Btls/MonoBtlsException.cs b/mcs/class/System/Mono.Btls/MonoBtlsException.cs new file mode 100644 index 0000000000..44282c97ec --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsException.cs @@ -0,0 +1,53 @@ +// +// MonoBtlsException.cs +// +// Author: +// Martin Baulig +// +// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +#if SECURITY_DEP && MONO_FEATURE_BTLS +using System; + +namespace Mono.Btls +{ + class MonoBtlsException : Exception + { + public MonoBtlsException () + { + } + + public MonoBtlsException (MonoBtlsSslError error) + : base (error.ToString ()) + { + } + + public MonoBtlsException (string message) + : base (message) + { + } + + public MonoBtlsException (string format, params object[] args) + : base (string.Format (format, args)) + { + } + } +} +#endif diff --git a/mcs/class/System/Mono.Btls/MonoBtlsKey.cs b/mcs/class/System/Mono.Btls/MonoBtlsKey.cs new file mode 100644 index 0000000000..f0cc3764d6 --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsKey.cs @@ -0,0 +1,104 @@ +// +// MonoBtlsKey.cs +// +// Author: +// Martin Baulig +// +// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +#if SECURITY_DEP && MONO_FEATURE_BTLS +using System; +using System.IO; +using System.Text; +using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; + +namespace Mono.Btls +{ + class MonoBtlsKey : MonoBtlsObject + { + internal class BoringKeyHandle : MonoBtlsHandle + { + internal BoringKeyHandle (IntPtr handle) + : base (handle, true) + { + } + + protected override bool ReleaseHandle () + { + mono_btls_key_free (handle); + return true; + } + } + + [DllImport (BTLS_DYLIB)] + extern static void mono_btls_key_free (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static IntPtr mono_btls_key_up_ref (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_key_get_bytes (IntPtr handle, out IntPtr data, out int size, int include_private_bits); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_key_get_bits (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_key_is_rsa (IntPtr handle); + + new internal BoringKeyHandle Handle { + get { return (BoringKeyHandle)base.Handle; } + } + + internal MonoBtlsKey (BoringKeyHandle handle) + : base (handle) + { + } + + public byte[] GetBytes (bool include_private_bits) + { + int size; + IntPtr data; + + var ret = mono_btls_key_get_bytes (Handle.DangerousGetHandle (), out data, out size, include_private_bits ? 1 : 0); + CheckError (ret); + + var buffer = new byte [size]; + Marshal.Copy (data, buffer, 0, size); + FreeDataPtr (data); + return buffer; + } + + public bool IsRsa { + get { + return mono_btls_key_is_rsa (Handle.DangerousGetHandle ()) != 0; + } + } + + public MonoBtlsKey Copy () + { + CheckThrow (); + var copy = mono_btls_key_up_ref (Handle.DangerousGetHandle ()); + CheckError (copy != IntPtr.Zero); + return new MonoBtlsKey (new BoringKeyHandle (copy)); + } + } +} +#endif diff --git a/mcs/class/System/Mono.Btls/MonoBtlsObject.cs b/mcs/class/System/Mono.Btls/MonoBtlsObject.cs new file mode 100644 index 0000000000..fd267d49f6 --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsObject.cs @@ -0,0 +1,149 @@ +// +// MonoBtlsObject.cs +// +// Author: +// Martin Baulig +// +// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +#if SECURITY_DEP && MONO_FEATURE_BTLS +using System; +using System.Threading; +using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; + +namespace Mono.Btls +{ + abstract class MonoBtlsObject : IDisposable + { +#if MONO_FEATURE_DYNAMIC_BTLS + internal const string BTLS_DYLIB = "libmono-btls-shared"; +#else + internal const string BTLS_DYLIB = "__Internal"; +#endif + + internal MonoBtlsObject (MonoBtlsHandle handle) + { + this.handle = handle; + } + + protected internal abstract class MonoBtlsHandle : SafeHandle + { + internal MonoBtlsHandle () + : base (IntPtr.Zero, true) + { + } + + internal MonoBtlsHandle (IntPtr handle, bool ownsHandle) + : base (handle, ownsHandle) + { + } + + public override bool IsInvalid { + get { return handle == IntPtr.Zero; } + } + } + + internal MonoBtlsHandle Handle { + get { + CheckThrow (); + return handle; + } + } + + public bool IsValid { + get { return handle != null && !handle.IsInvalid; } + } + + MonoBtlsHandle handle; + Exception lastError; + + protected void CheckThrow () + { + if (lastError != null) + throw lastError; + if (handle == null || handle.IsInvalid) + throw new ObjectDisposedException ("MonoBtlsSsl"); + } + + protected Exception SetException (Exception ex) + { + if (lastError == null) + lastError = ex; + return ex; + } + + protected void CheckError (bool ok, [CallerMemberName] string callerName = null) + { + if (!ok) { + if (callerName != null) + throw new MonoBtlsException ("{0}.{1} failed.", GetType ().Name, callerName); + else + throw new MonoBtlsException (); + } + + } + + protected void CheckError (int ret, [CallerMemberName] string callerName = null) + { + CheckError (ret == 1, callerName); + } + + [DllImport (BTLS_DYLIB)] + extern static void mono_btls_free (IntPtr data); + + protected void FreeDataPtr (IntPtr data) + { + mono_btls_free (data); + } + + protected virtual void Close () + { + } + + protected void Dispose (bool disposing) + { + if (disposing) { + try { + if (handle != null) { + Close (); + handle.Dispose (); + handle = null; + } + } finally { + var disposedExc = new ObjectDisposedException (GetType ().Name); + Interlocked.CompareExchange (ref lastError, disposedExc, null); + } + } + } + + public void Dispose () + { + Dispose (true); + GC.SuppressFinalize (this); + } + + ~MonoBtlsObject () + { + Dispose (false); + } + } +} +#endif diff --git a/mcs/class/System/Mono.Btls/MonoBtlsPkcs12.cs b/mcs/class/System/Mono.Btls/MonoBtlsPkcs12.cs new file mode 100644 index 0000000000..92e432092b --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsPkcs12.cs @@ -0,0 +1,145 @@ +// +// MonoBtlsPkcs12.cs +// +// Author: +// Martin Baulig +// +// Copyright (c) 2015 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +#if SECURITY_DEP && MONO_FEATURE_BTLS +using System; +using System.IO; +using System.Security.Cryptography.X509Certificates; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace Mono.Btls +{ + class MonoBtlsPkcs12 : MonoBtlsObject + { + internal class BoringPkcs12Handle : MonoBtlsHandle + { + public BoringPkcs12Handle (IntPtr handle) + : base (handle, true) + { + } + + protected override bool ReleaseHandle () + { + mono_btls_pkcs12_free (handle); + return true; + } + } + + new internal BoringPkcs12Handle Handle { + get { return (BoringPkcs12Handle)base.Handle; } + } + + [DllImport (BTLS_DYLIB)] + extern static void mono_btls_pkcs12_free (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static IntPtr mono_btls_pkcs12_new (); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_pkcs12_get_count (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static IntPtr mono_btls_pkcs12_get_cert (IntPtr Handle, int index); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_pkcs12_add_cert (IntPtr chain, IntPtr x509); + + [DllImport (BTLS_DYLIB)] + extern unsafe static int mono_btls_pkcs12_import (IntPtr chain, void* data, int len, IntPtr password); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_pkcs12_has_private_key (IntPtr pkcs12); + + [DllImport (BTLS_DYLIB)] + extern static IntPtr mono_btls_pkcs12_get_private_key (IntPtr pkcs12); + + internal MonoBtlsPkcs12 () + : base (new BoringPkcs12Handle (mono_btls_pkcs12_new ())) + { + } + + internal MonoBtlsPkcs12 (BoringPkcs12Handle handle) + : base (handle) + { + } + + MonoBtlsKey privateKey; + + public int Count { + get { return mono_btls_pkcs12_get_count (Handle.DangerousGetHandle ()); } + } + + public MonoBtlsX509 GetCertificate (int index) + { + if (index >= Count) + throw new IndexOutOfRangeException (); + var handle = mono_btls_pkcs12_get_cert (Handle.DangerousGetHandle (), index); + CheckError (handle != IntPtr.Zero); + return new MonoBtlsX509 (new MonoBtlsX509.BoringX509Handle (handle)); + } + + public void AddCertificate (MonoBtlsX509 x509) + { + mono_btls_pkcs12_add_cert ( + Handle.DangerousGetHandle (), + x509.Handle.DangerousGetHandle ()); + } + + public unsafe void Import (byte[] buffer, string password) + { + var passptr = IntPtr.Zero; + fixed (void* ptr = buffer) + try { + if (password != null) + passptr = Marshal.StringToHGlobalAnsi (password); + var ret = mono_btls_pkcs12_import ( + Handle.DangerousGetHandle (), ptr, + buffer.Length, passptr); + CheckError (ret); + } finally { + if (passptr != IntPtr.Zero) + Marshal.FreeHGlobal (passptr); + } + } + + public bool HasPrivateKey { + get { return mono_btls_pkcs12_has_private_key (Handle.DangerousGetHandle ()) != 0; } + } + + public MonoBtlsKey GetPrivateKey () + { + if (!HasPrivateKey) + throw new InvalidOperationException (); + if (privateKey == null) { + var handle = mono_btls_pkcs12_get_private_key (Handle.DangerousGetHandle ()); + CheckError (handle != IntPtr.Zero); + privateKey = new MonoBtlsKey (new MonoBtlsKey.BoringKeyHandle (handle)); + } + return privateKey; + } + } +} +#endif diff --git a/mcs/class/System/Mono.Btls/MonoBtlsProvider.cs b/mcs/class/System/Mono.Btls/MonoBtlsProvider.cs new file mode 100644 index 0000000000..b300585863 --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsProvider.cs @@ -0,0 +1,295 @@ +// +// MonoBtlsProvider.cs +// +// Author: +// Martin Baulig +// +// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +#if SECURITY_DEP && MONO_FEATURE_BTLS +#if MONO_SECURITY_ALIAS +extern alias MonoSecurity; +#endif + +using System; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using System.Security.Cryptography.X509Certificates; +using System.Security.Authentication; + +#if MONO_SECURITY_ALIAS +using MonoSecurity::Mono.Security.Interface; +using MX = MonoSecurity::Mono.Security.X509; +#else +using Mono.Security.Interface; +using MX = Mono.Security.X509; +#endif + +using MNS = Mono.Net.Security; + +namespace Mono.Btls +{ + class MonoBtlsProvider : MonoTlsProvider + { + static readonly Guid id = new Guid ("432d18c9-9348-4b90-bfbf-9f2a10e1f15b"); + + public override Guid ID { + get { return id; } + } + public override string Name { + get { return "btls"; } + } + + internal MonoBtlsProvider () + { + if (!MNS.MonoTlsProviderFactory.IsBtlsSupported ()) + throw new NotSupportedException ("BTLS is not supported in this runtime."); + } + + public override bool SupportsSslStream { + get { return true; } + } + + public override bool SupportsMonoExtensions { + get { return true; } + } + + public override bool SupportsConnectionInfo { + get { return true; } + } + + public override SslProtocols SupportedProtocols { + get { return SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls; } + } + + public override IMonoSslStream CreateSslStream ( + Stream innerStream, bool leaveInnerStreamOpen, + MonoTlsSettings settings = null) + { + return new MonoBtlsStream ( + innerStream, leaveInnerStreamOpen, settings, this); + } + + internal override bool HasNativeCertificates { + get { return true; } + } + + internal override X509Certificate2Impl GetNativeCertificate ( + byte[] data, string password, X509KeyStorageFlags flags) + { + var impl = new X509CertificateImplBtls (false); + impl.Import (data, password, flags); + return impl; + } + + internal override X509Certificate2Impl GetNativeCertificate ( + X509Certificate certificate) + { + var impl = certificate.Impl as X509CertificateImplBtls; + if (impl != null) + return (X509Certificate2Impl)impl.Clone (); + + var data = certificate.GetRawCertData (); + return new X509CertificateImplBtls (data, MonoBtlsX509Format.DER, false); + } + + internal static MonoBtlsX509VerifyParam GetVerifyParam (string targetHost, bool serverMode) + { + MonoBtlsX509VerifyParam param; + if (serverMode) + param = MonoBtlsX509VerifyParam.GetSslClient (); + else + param = MonoBtlsX509VerifyParam.GetSslServer (); + + if (targetHost == null) + return param; + + try { + var copy = param.Copy (); + copy.SetHost (targetHost); + return copy; + } finally { + param.Dispose (); + } + } + + internal override bool ValidateCertificate ( + ICertificateValidator2 validator, string targetHost, bool serverMode, + X509CertificateCollection certificates, bool wantsChain, ref X509Chain chain, + ref MonoSslPolicyErrors errors, ref int status11) + { + if (chain != null) { + var chainImpl = (X509ChainImplBtls)chain.Impl; + var success = chainImpl.StoreCtx.VerifyResult == 1; + CheckValidationResult ( + validator, targetHost, serverMode, certificates, + wantsChain, chain, chainImpl.StoreCtx, + success, ref errors, ref status11); + return success; + } + + using (var store = new MonoBtlsX509Store ()) + using (var nativeChain = MonoBtlsProvider.GetNativeChain (certificates)) + using (var param = GetVerifyParam (targetHost, serverMode)) + using (var storeCtx = new MonoBtlsX509StoreCtx ()) { + SetupCertificateStore (store); + + storeCtx.Initialize (store, nativeChain); + + storeCtx.SetVerifyParam (param); + + var ret = storeCtx.Verify (); + + var success = ret == 1; + + if (wantsChain && chain == null) { + chain = GetManagedChain (nativeChain); + } + + CheckValidationResult ( + validator, targetHost, serverMode, certificates, + wantsChain, null, storeCtx, + success, ref errors, ref status11); + return success; + } + } + + internal static bool ValidateCertificate (MonoBtlsX509Chain chain, MonoBtlsX509VerifyParam param) + { + using (var store = new MonoBtlsX509Store ()) + using (var storeCtx = new MonoBtlsX509StoreCtx ()) { + SetupCertificateStore (store); + + storeCtx.Initialize (store, chain); + + if (param != null) + storeCtx.SetVerifyParam (param); + + var ret = storeCtx.Verify (); + + return ret == 1; + } + } + + void CheckValidationResult ( + ICertificateValidator validator, string targetHost, bool serverMode, + X509CertificateCollection certificates, bool wantsChain, + X509Chain chain, MonoBtlsX509StoreCtx storeCtx, + bool success, ref MonoSslPolicyErrors errors, ref int status11) + { + if (!success) { + errors = MonoSslPolicyErrors.RemoteCertificateChainErrors; + status11 = unchecked((int)0x800B010B); + } + } + + internal static void SetupCertificateStore (MonoBtlsX509Store store) + { +#if MONODROID + store.SetDefaultPaths (); + store.AddAndroidLookup (); +#else + var userPath = MonoBtlsX509StoreManager.GetStorePath (MonoBtlsX509StoreType.UserTrustedRoots); + if (Directory.Exists (userPath)) + store.AddDirectoryLookup (userPath, MonoBtlsX509FileType.PEM); + var machinePath = MonoBtlsX509StoreManager.GetStorePath (MonoBtlsX509StoreType.MachineTrustedRoots); + if (Directory.Exists (machinePath)) + store.AddDirectoryLookup (machinePath, MonoBtlsX509FileType.PEM); +#endif + } + + public static string GetSystemStoreLocation () + { +#if ANDROID + return "/system/etc/security/cacerts"; +#else + var appData = Environment.GetFolderPath (Environment.SpecialFolder.ApplicationData); + var path = Path.Combine (appData, ".mono", "certs", "NewTrust"); + return path; +#endif + } + + public static X509Certificate CreateCertificate (byte[] data, MonoBtlsX509Format format, bool disallowFallback = false) + { + using (var impl = new X509CertificateImplBtls (data, format, disallowFallback)) { + return new X509Certificate (impl); + } + } + + public static X509Certificate2 CreateCertificate2 (byte[] data, MonoBtlsX509Format format, bool disallowFallback = false) + { + using (var impl = new X509CertificateImplBtls (data, format, disallowFallback)) { + return new X509Certificate2 (impl); + } + } + + public static X509Certificate2 CreateCertificate2 (byte[] data, string password, bool disallowFallback = false) + { + using (var impl = new X509CertificateImplBtls (disallowFallback)) { + impl.Import (data, password, X509KeyStorageFlags.DefaultKeySet); + return new X509Certificate2 (impl); + } + } + + public static X509Certificate CreateCertificate (MonoBtlsX509 x509) + { + using (var impl = new X509CertificateImplBtls (x509, true)) + return new X509Certificate (impl); + } + + public static X509Chain CreateChain () + { + using (var impl = new X509ChainImplBtls ()) + return new X509Chain (impl); + } + + public static X509Chain GetManagedChain (MonoBtlsX509Chain chain) + { + var impl = new X509ChainImplBtls (chain); + return new X509Chain (impl); + } + + public static MonoBtlsX509 GetBtlsCertificate (X509Certificate certificate) + { + var impl = certificate.Impl as X509CertificateImplBtls; + if (impl != null) + return impl.X509.Copy (); + + return MonoBtlsX509.LoadFromData (certificate.GetRawCertData (), MonoBtlsX509Format.DER); + } + + public static MonoBtlsX509Chain GetNativeChain (X509CertificateCollection certificates) + { + var chain = new MonoBtlsX509Chain (); + try { + foreach (var cert in certificates) { + using (var x509 = GetBtlsCertificate (cert)) + chain.AddCertificate (x509); + } + return chain; + } catch { + chain.Dispose (); + throw; + } + } + } +} +#endif diff --git a/mcs/class/System/Mono.Btls/MonoBtlsSsl.cs b/mcs/class/System/Mono.Btls/MonoBtlsSsl.cs new file mode 100644 index 0000000000..d751090135 --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsSsl.cs @@ -0,0 +1,418 @@ +// +// MonoBtlsSsl.cs +// +// Author: +// Martin Baulig +// +// Copyright (c) 2015 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +#if SECURITY_DEP && MONO_FEATURE_BTLS +using System; +using System.IO; +using System.Text; +using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; + +#if MONOTOUCH +using MonoTouch; +#endif + +namespace Mono.Btls +{ + delegate int MonoBtlsVerifyCallback (MonoBtlsX509StoreCtx ctx); + delegate int MonoBtlsSelectCallback (); + + class MonoBtlsSsl : MonoBtlsObject + { + internal class BoringSslHandle : MonoBtlsHandle + { + public BoringSslHandle (IntPtr handle) + : base (handle, true) + { + } + + protected override bool ReleaseHandle () + { + mono_btls_ssl_destroy (handle); + return true; + } + } + + [DllImport (BTLS_DYLIB)] + extern static void mono_btls_ssl_destroy (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static IntPtr mono_btls_ssl_new (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_ssl_use_certificate (IntPtr handle, IntPtr x509); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_ssl_use_private_key (IntPtr handle, IntPtr key); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_ssl_add_chain_certificate (IntPtr handle, IntPtr x509); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_ssl_accept (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_ssl_connect (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_ssl_handshake (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static void mono_btls_ssl_close (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static void mono_btls_ssl_set_bio (IntPtr handle, IntPtr bio); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_ssl_read (IntPtr handle, IntPtr data, int len); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_ssl_write (IntPtr handle, IntPtr data, int len); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_ssl_get_error (IntPtr handle, int ret_code); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_ssl_get_version (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static void mono_btls_ssl_set_min_version (IntPtr handle, int version); + + [DllImport (BTLS_DYLIB)] + extern static void mono_btls_ssl_set_max_version (IntPtr handle, int version); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_ssl_get_cipher (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_ssl_get_ciphers (IntPtr handle, out IntPtr data); + + [DllImport (BTLS_DYLIB)] + extern static IntPtr mono_btls_ssl_get_peer_certificate (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_ssl_set_cipher_list (IntPtr handle, IntPtr str); + + [DllImport (BTLS_DYLIB)] + extern static void mono_btls_ssl_print_errors_cb (IntPtr func, IntPtr ctx); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_ssl_set_verify_param (IntPtr handle, IntPtr param); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_ssl_set_server_name (IntPtr handle, IntPtr name); + + static BoringSslHandle Create_internal (MonoBtlsSslCtx ctx) + { + var handle = mono_btls_ssl_new (ctx.Handle.DangerousGetHandle ()); + if (handle == IntPtr.Zero) + throw new MonoBtlsException (); + return new BoringSslHandle (handle); + } + + PrintErrorsCallbackFunc printErrorsFunc; + IntPtr printErrorsFuncPtr; + + public MonoBtlsSsl (MonoBtlsSslCtx ctx) + : base (Create_internal (ctx)) + { + printErrorsFunc = PrintErrorsCallback; + printErrorsFuncPtr = Marshal.GetFunctionPointerForDelegate (printErrorsFunc); + } + + new internal BoringSslHandle Handle { + get { return (BoringSslHandle)base.Handle; } + } + + public void SetBio (MonoBtlsBio bio) + { + CheckThrow (); + mono_btls_ssl_set_bio ( + Handle.DangerousGetHandle (), + bio.Handle.DangerousGetHandle ()); + } + + Exception ThrowError ([CallerMemberName] string callerName = null) + { + string errors; + try { + if (callerName == null) + callerName = GetType ().Name; + errors = GetErrors (); + } catch { + errors = null; + } + + if (errors != null) { + Console.Error.WriteLine ("ERROR: {0} failed: {1}", callerName, errors); + throw new MonoBtlsException ("{0} failed: {1}.", callerName, errors); + } else { + Console.Error.WriteLine ("ERROR: {0} failed.", callerName); + throw new MonoBtlsException ("{0} failed.", callerName); + } + } + + MonoBtlsSslError GetError (int ret_code) + { + CheckThrow (); + var error = mono_btls_ssl_get_error ( + Handle.DangerousGetHandle (), ret_code); + return (MonoBtlsSslError)error; + } + + public void SetCertificate (MonoBtlsX509 x509) + { + CheckThrow (); + + var ret = mono_btls_ssl_use_certificate ( + Handle.DangerousGetHandle (), + x509.Handle.DangerousGetHandle ()); + if (ret <= 0) + throw ThrowError (); + } + + public void SetPrivateKey (MonoBtlsKey key) + { + CheckThrow (); + + var ret = mono_btls_ssl_use_private_key ( + Handle.DangerousGetHandle (), + key.Handle.DangerousGetHandle ()); + if (ret <= 0) + throw ThrowError (); + } + + public void AddIntermediateCertificate (MonoBtlsX509 x509) + { + CheckThrow (); + + var ret = mono_btls_ssl_add_chain_certificate ( + Handle.DangerousGetHandle (), + x509.Handle.DangerousGetHandle ()); + if (ret <= 0) + throw ThrowError (); + } + + public MonoBtlsSslError Accept () + { + CheckThrow (); + + var ret = mono_btls_ssl_accept (Handle.DangerousGetHandle ()); + + var error = GetError (ret); + return error; + } + + public MonoBtlsSslError Connect () + { + CheckThrow (); + + var ret = mono_btls_ssl_connect (Handle.DangerousGetHandle ()); + + var error = GetError (ret); + return error; + } + + public MonoBtlsSslError Handshake () + { + CheckThrow (); + + var ret = mono_btls_ssl_handshake (Handle.DangerousGetHandle ()); + + var error = GetError (ret); + return error; + } + + delegate int PrintErrorsCallbackFunc (IntPtr str, IntPtr len, IntPtr ctx); + +#if MONOTOUCH + [MonoPInvokeCallback (typeof (PrintErrorsCallbackFunc))] +#endif + static int PrintErrorsCallback (IntPtr str, IntPtr len, IntPtr ctx) + { + var sb = (StringBuilder)GCHandle.FromIntPtr (ctx).Target; + try { + var text = Marshal.PtrToStringAnsi (str, (int)len); + sb.Append (text); + return 1; + } catch { + return 0; + } + } + + public string GetErrors () + { + var text = new StringBuilder (); + var handle = GCHandle.Alloc (text); + + try { + mono_btls_ssl_print_errors_cb (printErrorsFuncPtr, GCHandle.ToIntPtr (handle)); + return text.ToString (); + } finally { + if (handle.IsAllocated) + handle.Free (); + } + } + + public void PrintErrors () + { + var errors = GetErrors (); + if (string.IsNullOrEmpty (errors)) + return; + Console.Error.WriteLine (errors); + } + + public MonoBtlsSslError Read (IntPtr data, ref int dataSize) + { + CheckThrow (); + var ret = mono_btls_ssl_read ( + Handle.DangerousGetHandle (), data, dataSize); + + if (ret >= 0) { + dataSize = ret; + return MonoBtlsSslError.None; + } + + var error = mono_btls_ssl_get_error ( + Handle.DangerousGetHandle (), ret); + dataSize = 0; + return (MonoBtlsSslError)error; + } + + public MonoBtlsSslError Write (IntPtr data, ref int dataSize) + { + CheckThrow (); + var ret = mono_btls_ssl_write ( + Handle.DangerousGetHandle (), data, dataSize); + + if (ret >= 0) { + dataSize = ret; + return MonoBtlsSslError.None; + } + + var error = mono_btls_ssl_get_error ( + Handle.DangerousGetHandle (), ret); + dataSize = 0; + return (MonoBtlsSslError)error; + } + + public int GetVersion () + { + CheckThrow (); + return mono_btls_ssl_get_version (Handle.DangerousGetHandle ()); + } + + public void SetMinVersion (int version) + { + CheckThrow (); + mono_btls_ssl_set_min_version (Handle.DangerousGetHandle (), version); + } + + public void SetMaxVersion (int version) + { + CheckThrow (); + mono_btls_ssl_set_max_version (Handle.DangerousGetHandle (), version); + } + + public int GetCipher () + { + CheckThrow (); + var cipher = mono_btls_ssl_get_cipher (Handle.DangerousGetHandle ()); + CheckError (cipher > 0); + return cipher; + } + + public short[] GetCiphers () + { + CheckThrow (); + IntPtr data; + var count = mono_btls_ssl_get_ciphers ( + Handle.DangerousGetHandle (), out data); + CheckError (count > 0); + try { + short[] ciphers = new short[count]; + Marshal.Copy (data, ciphers, 0, count); + return ciphers; + } finally { + FreeDataPtr (data); + } + } + + public void SetCipherList (string str) + { + CheckThrow (); + IntPtr strPtr = IntPtr.Zero; + try { + strPtr = Marshal.StringToHGlobalAnsi (str); + var ret = mono_btls_ssl_set_cipher_list ( + Handle.DangerousGetHandle (), strPtr); + CheckError (ret); + } finally { + if (strPtr != IntPtr.Zero) + Marshal.FreeHGlobal (strPtr); + } + } + + public MonoBtlsX509 GetPeerCertificate () + { + CheckThrow (); + var x509 = mono_btls_ssl_get_peer_certificate ( + Handle.DangerousGetHandle ()); + if (x509 == IntPtr.Zero) + return null; + return new MonoBtlsX509 (new MonoBtlsX509.BoringX509Handle (x509)); + } + + public void SetVerifyParam (MonoBtlsX509VerifyParam param) + { + CheckThrow (); + var ret = mono_btls_ssl_set_verify_param ( + Handle.DangerousGetHandle (), + param.Handle.DangerousGetHandle ()); + CheckError (ret); + } + + public void SetServerName (string name) + { + CheckThrow (); + IntPtr namePtr = IntPtr.Zero; + try { + namePtr = Marshal.StringToHGlobalAnsi (name); + var ret = mono_btls_ssl_set_server_name ( + Handle.DangerousGetHandle (), namePtr); + CheckError (ret); + } finally { + if (namePtr != IntPtr.Zero) + Marshal.FreeHGlobal (namePtr); + } + } + + protected override void Close () + { + mono_btls_ssl_close (Handle.DangerousGetHandle ()); + } + } +} +#endif diff --git a/mcs/class/System/Mono.Btls/MonoBtlsSslCtx.cs b/mcs/class/System/Mono.Btls/MonoBtlsSslCtx.cs new file mode 100644 index 0000000000..fd9b6f1b62 --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsSslCtx.cs @@ -0,0 +1,260 @@ +// +// MonoBtlsSslCtx.cs +// +// Author: +// Martin Baulig +// +// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +#if SECURITY_DEP && MONO_FEATURE_BTLS +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +#if MONOTOUCH +using MonoTouch; +#endif + +namespace Mono.Btls +{ + class MonoBtlsSslCtx : MonoBtlsObject + { + internal class BoringSslCtxHandle : MonoBtlsHandle + { + public BoringSslCtxHandle (IntPtr handle) + : base (handle, true) + { + } + + protected override bool ReleaseHandle () + { + mono_btls_ssl_ctx_free (handle); + return true; + } + } + + new internal BoringSslCtxHandle Handle { + get { return (BoringSslCtxHandle)base.Handle; } + } + + [DllImport (BTLS_DYLIB)] + extern static IntPtr mono_btls_ssl_ctx_new (); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_ssl_ctx_free (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static IntPtr mono_btls_ssl_ctx_up_ref (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static void mono_btls_ssl_ctx_initialize (IntPtr handle, IntPtr instance); + + [DllImport (BTLS_DYLIB)] + extern static void mono_btls_ssl_ctx_set_debug_bio (IntPtr handle, IntPtr bio); + + [DllImport (BTLS_DYLIB)] + extern static void mono_btls_ssl_ctx_set_cert_verify_callback (IntPtr handle, IntPtr func, int cert_required); + + [DllImport (BTLS_DYLIB)] + extern static void mono_btls_ssl_ctx_set_cert_select_callback (IntPtr handle, IntPtr func); + + [DllImport (BTLS_DYLIB)] + extern static void mono_btls_ssl_ctx_set_min_version (IntPtr handle, int version); + + [DllImport (BTLS_DYLIB)] + extern static void mono_btls_ssl_ctx_set_max_version (IntPtr handle, int version); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_ssl_ctx_is_cipher_supported (IntPtr handle, short value); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_ssl_ctx_set_ciphers (IntPtr handle, int count, IntPtr data, int allow_unsupported); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_ssl_ctx_set_verify_param (IntPtr handle, IntPtr param); + + delegate int NativeVerifyFunc (IntPtr instance, int preverify_ok, IntPtr ctx); + delegate int NativeSelectFunc (IntPtr instance); + + NativeVerifyFunc verifyFunc; + NativeSelectFunc selectFunc; + IntPtr verifyFuncPtr; + IntPtr selectFuncPtr; + MonoBtlsVerifyCallback verifyCallback; + MonoBtlsSelectCallback selectCallback; + MonoBtlsX509Store store; + GCHandle instance; + IntPtr instancePtr; + + public MonoBtlsSslCtx () + : this (new BoringSslCtxHandle (mono_btls_ssl_ctx_new ())) + { + } + + internal MonoBtlsSslCtx (BoringSslCtxHandle handle) + : base (handle) + { + instance = GCHandle.Alloc (this); + instancePtr = GCHandle.ToIntPtr (instance); + mono_btls_ssl_ctx_initialize ( + handle.DangerousGetHandle (), instancePtr); + + verifyFunc = NativeVerifyCallback; + selectFunc = NativeSelectCallback; + verifyFuncPtr = Marshal.GetFunctionPointerForDelegate (verifyFunc); + selectFuncPtr = Marshal.GetFunctionPointerForDelegate (selectFunc); + + store = new MonoBtlsX509Store (Handle); + } + + internal MonoBtlsSslCtx Copy () + { + var copy = mono_btls_ssl_ctx_up_ref (Handle.DangerousGetHandle ()); + return new MonoBtlsSslCtx (new BoringSslCtxHandle (copy)); + } + + public MonoBtlsX509Store CertificateStore { + get { return store; } + } + + int VerifyCallback (bool preverify_ok, MonoBtlsX509StoreCtx ctx) + { + if (verifyCallback != null) + return verifyCallback (ctx); + return 0; + } + +#if MONOTOUCH + [MonoPInvokeCallback (typeof (NativeVerifyFunc))] +#endif + static int NativeVerifyCallback (IntPtr instance, int preverify_ok, IntPtr store_ctx) + { + var c = (MonoBtlsSslCtx)GCHandle.FromIntPtr (instance).Target; + using (var ctx = new MonoBtlsX509StoreCtx (preverify_ok, store_ctx)) { + try { + return c.VerifyCallback (preverify_ok != 0, ctx); + } catch (Exception ex) { + c.SetException (ex); + } + } + return 0; + } + + int SelectCallback () + { + if (selectCallback != null) + return selectCallback (); + return 1; + } + +#if MONOTOUCH + [MonoPInvokeCallback (typeof (NativeSelectFunc))] +#endif + static int NativeSelectCallback (IntPtr instance) + { + var c = (MonoBtlsSslCtx)GCHandle.FromIntPtr (instance).Target; + try { + return c.SelectCallback (); + } catch (Exception ex) { + c.SetException (ex); + return 0; + } + } + + public void SetDebugBio (MonoBtlsBio bio) + { + CheckThrow (); + mono_btls_ssl_ctx_set_debug_bio (Handle.DangerousGetHandle (), bio.Handle.DangerousGetHandle ()); + } + + public void SetVerifyCallback (MonoBtlsVerifyCallback callback, bool client_cert_required) + { + CheckThrow (); + + verifyCallback = callback; + mono_btls_ssl_ctx_set_cert_verify_callback ( + Handle.DangerousGetHandle (), verifyFuncPtr, + client_cert_required ? 1 : 0); + } + + public void SetSelectCallback (MonoBtlsSelectCallback callback) + { + CheckThrow (); + + selectCallback = callback; + mono_btls_ssl_ctx_set_cert_select_callback ( + Handle.DangerousGetHandle (), selectFuncPtr); + } + + public void SetMinVersion (int version) + { + CheckThrow (); + mono_btls_ssl_ctx_set_min_version (Handle.DangerousGetHandle (), version); + } + + public void SetMaxVersion (int version) + { + CheckThrow (); + mono_btls_ssl_ctx_set_max_version (Handle.DangerousGetHandle (), version); + } + + public bool IsCipherSupported (short value) + { + CheckThrow (); + return mono_btls_ssl_ctx_is_cipher_supported (Handle.DangerousGetHandle (), value) != 0; + } + + public void SetCiphers (short[] ciphers, bool allow_unsupported) + { + CheckThrow (); + var data = Marshal.AllocHGlobal (ciphers.Length * 2); + try { + Marshal.Copy (ciphers, 0, data, ciphers.Length); + var ret = mono_btls_ssl_ctx_set_ciphers ( + Handle.DangerousGetHandle (), + ciphers.Length, data, allow_unsupported ? 1 : 0); + CheckError (ret > 0); + } finally { + Marshal.FreeHGlobal (data); + } + } + + public void SetVerifyParam (MonoBtlsX509VerifyParam param) + { + CheckThrow (); + var ret = mono_btls_ssl_ctx_set_verify_param ( + Handle.DangerousGetHandle (), + param.Handle.DangerousGetHandle ()); + CheckError (ret); + } + + protected override void Close () + { + if (store != null) { + store.Dispose (); + store = null; + } + if (instance.IsAllocated) + instance.Free (); + base.Close (); + } + } +} +#endif diff --git a/mcs/class/System/ReferenceSources/SSPIConfiguration.cs b/mcs/class/System/Mono.Btls/MonoBtlsSslError.cs similarity index 74% rename from mcs/class/System/ReferenceSources/SSPIConfiguration.cs rename to mcs/class/System/Mono.Btls/MonoBtlsSslError.cs index 3ab41387ef..432ba5d036 100644 --- a/mcs/class/System/ReferenceSources/SSPIConfiguration.cs +++ b/mcs/class/System/Mono.Btls/MonoBtlsSslError.cs @@ -1,5 +1,5 @@ // -// SSPIConfiguration.cs +// MonoBtlsSslError.cs // // Author: // Martin Baulig @@ -23,31 +23,25 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. - -#if MONO_FEATURE_NEW_TLS && SECURITY_DEP -#if MONO_SECURITY_ALIAS -extern alias MonoSecurity; -using MonoSecurity::Mono.Security.Interface; -#else -using Mono.Security.Interface; -#endif -using Mono.Net.Security; - -namespace System.Net.Security +#if SECURITY_DEP && MONO_FEATURE_BTLS +namespace Mono.Btls { - internal interface SSPIConfiguration + // keep in sync with boringssl/include/ssl.h + enum MonoBtlsSslError { - IMonoTlsProvider Provider { - get; - } - - MonoTlsSettings Settings { - get; - } - - IMonoTlsEventSink EventSink { - get; - } + None = 0, + Ssl = 1, + WantRead = 2, + WantWrite = 3, + WantX509Lookup = 4, + Syscall = 5, + ZeroReturn = 6, + WantConnect = 7, + WantAccept = 8, + WantChannelIdLookup = 9, + PendingSession = 11, + PendingCertificate = 12, + WantPrivateKeyOperation = 13 } } #endif diff --git a/mcs/class/System/Mono.Btls/MonoBtlsStream.cs b/mcs/class/System/Mono.Btls/MonoBtlsStream.cs new file mode 100644 index 0000000000..38b6d83a4d --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsStream.cs @@ -0,0 +1,65 @@ +// +// MonoBtlsStream.cs +// +// Author: +// Martin Baulig +// +// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +#if SECURITY_DEP && MONO_FEATURE_BTLS +#if MONO_SECURITY_ALIAS +extern alias MonoSecurity; +#endif + +using System; +using System.IO; +using System.Security.Authentication; +using System.Security.Cryptography.X509Certificates; + +#if MONO_SECURITY_ALIAS +using MonoSecurity::Mono.Security.Interface; +#else +using Mono.Security.Interface; +#endif + +using MNS = Mono.Net.Security; + +namespace Mono.Btls +{ + class MonoBtlsStream : MNS.MobileAuthenticatedStream + { + public MonoBtlsStream (Stream innerStream, bool leaveInnerStreamOpen, MonoTlsSettings settings, MonoTlsProvider provider) + : base (innerStream, leaveInnerStreamOpen, settings, provider) + { + } + + protected override MNS.MobileTlsContext CreateContext ( + MNS.MobileAuthenticatedStream parent, bool serverMode, string targetHost, + SslProtocols enabledProtocols, X509Certificate serverCertificate, + X509CertificateCollection clientCertificates, bool askForClientCert) + { + return new MonoBtlsContext ( + parent, serverMode, targetHost, + enabledProtocols, serverCertificate, + clientCertificates, askForClientCert); + } + } +} +#endif diff --git a/mcs/class/System/Mono.Btls/MonoBtlsUtils.cs b/mcs/class/System/Mono.Btls/MonoBtlsUtils.cs new file mode 100644 index 0000000000..4175968195 --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsUtils.cs @@ -0,0 +1,187 @@ +// +// MonoBtlsUtils.cs +// +// Author: +// Martin Baulig +// +// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +#if SECURITY_DEP && MONO_FEATURE_BTLS +using System; +using System.Text; +using System.Security.Cryptography.X509Certificates; + +namespace Mono.Btls +{ + static class MonoBtlsUtils + { + static byte[] emailOid = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01 }; + + public static bool Compare (byte[] a, byte[] b) + { + if (a.Length != b.Length) + return false; + for (int i = 0; i < a.Length; i++) { + if (a[i] != b[i]) + return false; + } + return true; + } + + static bool AppendEntry (StringBuilder sb, MonoBtlsX509Name name, int index, string separator, bool quotes) + { + var type = name.GetEntryType (index); + if (type < 0) + return false; + else if (type == 0) { + var oidValue = name.GetEntryOidData (index); + if (Compare (oidValue, emailOid)) + type = MonoBtlsX509NameEntryType.Email; + } + int tag; + var text = name.GetEntryValue (index, out tag); + if (text == null) + return false; + var oid = name.GetEntryOid (index); + if (oid == null) + return false; + + if (sb.Length > 0) + sb.Append (separator); + + switch (type) { + case MonoBtlsX509NameEntryType.CountryName: + sb.Append ("C="); + break; + case MonoBtlsX509NameEntryType.OrganizationName: + sb.Append ("O="); + break; + case MonoBtlsX509NameEntryType.OrganizationalUnitName: + sb.Append ("OU="); + break; + case MonoBtlsX509NameEntryType.CommonName: + sb.Append ("CN="); + break; + case MonoBtlsX509NameEntryType.LocalityName: + sb.Append ("L="); + break; + case MonoBtlsX509NameEntryType.StateOrProvinceName: + sb.Append ("S="); // NOTE: RFC2253 uses ST= + break; + case MonoBtlsX509NameEntryType.StreetAddress: + sb.Append ("STREET="); + break; + case MonoBtlsX509NameEntryType.DomainComponent: + sb.Append ("DC="); + break; + case MonoBtlsX509NameEntryType.UserId: + sb.Append ("UID="); + break; + case MonoBtlsX509NameEntryType.Email: + sb.Append ("E="); // NOTE: Not part of RFC2253 + break; + case MonoBtlsX509NameEntryType.DnQualifier: + sb.Append ("dnQualifier="); + break; + case MonoBtlsX509NameEntryType.Title: + sb.Append ("T="); + break; + case MonoBtlsX509NameEntryType.Surname: + sb.Append ("SN="); + break; + case MonoBtlsX509NameEntryType.GivenName: + sb.Append ("G="); + break; + case MonoBtlsX509NameEntryType.Initial: + sb.Append ("I="); + break; + default: + // unknown OID + sb.Append ("OID."); // NOTE: Not present as RFC2253 + sb.Append (oid); + sb.Append ("="); + break; + } + + // 16bits or 8bits string ? TODO not complete (+special chars!) + char[] specials = { ',', '+', '"', '\\', '<', '>', ';' }; + if (quotes && tag != 0x1E) { + if ((text.IndexOfAny (specials, 0, text.Length) > 0) || + text.StartsWith (" ") || (text.EndsWith (" "))) + text = "\"" + text + "\""; + } + + sb.Append (text); + return true; + } + + const X500DistinguishedNameFlags AllFlags = X500DistinguishedNameFlags.Reversed | + X500DistinguishedNameFlags.UseSemicolons | X500DistinguishedNameFlags.DoNotUsePlusSign | + X500DistinguishedNameFlags.DoNotUseQuotes | X500DistinguishedNameFlags.UseCommas | + X500DistinguishedNameFlags.UseNewLines | X500DistinguishedNameFlags.UseUTF8Encoding | + X500DistinguishedNameFlags.UseT61Encoding | X500DistinguishedNameFlags.ForceUTF8Encoding; + + static string GetSeparator (X500DistinguishedNameFlags flag) + { + if ((flag & X500DistinguishedNameFlags.UseSemicolons) != 0) + return "; "; + if ((flag & X500DistinguishedNameFlags.UseCommas) != 0) + return ", "; + if ((flag & X500DistinguishedNameFlags.UseNewLines) != 0) + return Environment.NewLine; + return ", "; //default + } + + public static string FormatName (MonoBtlsX509Name name, X500DistinguishedNameFlags flag) + { + if ((flag != 0) && ((flag & AllFlags) == 0)) + throw new ArgumentException ("flag"); + + if (name.GetEntryCount () == 0) + return String.Empty; + + // Mono.Security reversed isn't the same as fx 2.0 (which is the reverse of 1.x) + bool reversed = ((flag & X500DistinguishedNameFlags.Reversed) != 0); + bool quotes = ((flag & X500DistinguishedNameFlags.DoNotUseQuotes) == 0); + string separator = GetSeparator (flag); + + return FormatName (name, reversed, separator, quotes); + } + + public static string FormatName (MonoBtlsX509Name name, bool reversed, string separator, bool quotes) + { + var count = name.GetEntryCount (); + StringBuilder sb = new StringBuilder (); + + if (reversed) { + for (int i = count - 1; i >= 0; i--) { + AppendEntry (sb, name, i, separator, quotes); + } + } else { + for (int i = 0; i < count; i++) { + AppendEntry (sb, name, i, separator, quotes); + } + } + + return sb.ToString (); + } + } +} +#endif diff --git a/mcs/class/System/Mono.Btls/MonoBtlsX509.cs b/mcs/class/System/Mono.Btls/MonoBtlsX509.cs new file mode 100644 index 0000000000..c722ad9fbf --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsX509.cs @@ -0,0 +1,465 @@ +// +// MonoBtlsX509.cs +// +// Author: +// Martin Baulig +// +// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +#if SECURITY_DEP && MONO_FEATURE_BTLS +using System; +using System.IO; +using System.Text; +using System.Threading; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Security.Cryptography.X509Certificates; +using System.Security.Cryptography; + +namespace Mono.Btls +{ + class MonoBtlsX509 : MonoBtlsObject + { + internal class BoringX509Handle : MonoBtlsHandle + { + public BoringX509Handle (IntPtr handle) + : base (handle, true) + { + } + + protected override bool ReleaseHandle () + { + if (handle != IntPtr.Zero) + mono_btls_x509_free (handle); + return true; + } + + public IntPtr StealHandle () + { + var retval = Interlocked.Exchange (ref handle, IntPtr.Zero); + return retval; + } + } + + new internal BoringX509Handle Handle { + get { return (BoringX509Handle)base.Handle; } + } + + internal MonoBtlsX509 (BoringX509Handle handle) + : base (handle) + { + } + + [DllImport (BTLS_DYLIB)] + extern static IntPtr mono_btls_x509_up_ref (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static IntPtr mono_btls_x509_from_data (IntPtr data, int len, MonoBtlsX509Format format); + + [DllImport (BTLS_DYLIB)] + extern static IntPtr mono_btls_x509_get_subject_name (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static IntPtr mono_btls_x509_get_issuer_name (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_x509_get_subject_name_string (IntPtr handle, IntPtr buffer, int size); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_x509_get_issuer_name_string (IntPtr handle, IntPtr buffer, int size); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_x509_get_raw_data (IntPtr handle, IntPtr bio, MonoBtlsX509Format format); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_x509_cmp (IntPtr a, IntPtr b); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_x509_get_hash (IntPtr handle, out IntPtr data); + + [DllImport (BTLS_DYLIB)] + extern static long mono_btls_x509_get_not_before (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static long mono_btls_x509_get_not_after (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_x509_get_public_key (IntPtr handle, IntPtr bio); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_x509_get_serial_number (IntPtr handle, IntPtr data, int size, int mono_style); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_x509_get_version (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_x509_get_signature_algorithm (IntPtr handle, IntPtr buffer, int size); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_x509_get_public_key_asn1 (IntPtr handle, IntPtr oid, int oid_size, out IntPtr data, out int size); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_x509_get_public_key_parameters (IntPtr handle, IntPtr oid, int oid_size, out IntPtr data, out int size); + + [DllImport (BTLS_DYLIB)] + extern static IntPtr mono_btls_x509_get_pubkey (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_x509_get_subject_key_identifier (IntPtr handle, out IntPtr data, out int size); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_x509_print (IntPtr handle, IntPtr bio); + + [DllImport (BTLS_DYLIB)] + extern static void mono_btls_x509_free (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static IntPtr mono_btls_x509_dup (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_x509_add_trust_object (IntPtr handle, MonoBtlsX509Purpose purpose); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_x509_add_reject_object (IntPtr handle, MonoBtlsX509Purpose purpose); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_x509_add_explicit_trust (IntPtr handle, MonoBtlsX509TrustKind kind); + + internal MonoBtlsX509 Copy () + { + var copy = mono_btls_x509_up_ref (Handle.DangerousGetHandle ()); + CheckError (copy != IntPtr.Zero); + return new MonoBtlsX509 (new BoringX509Handle (copy)); + } + + // This will actually duplicate the underlying 'X509 *' object instead of + // simply increasing the reference count. + internal MonoBtlsX509 Duplicate () + { + var copy = mono_btls_x509_dup (Handle.DangerousGetHandle ()); + CheckError (copy != IntPtr.Zero); + return new MonoBtlsX509 (new BoringX509Handle (copy)); + } + + public static MonoBtlsX509 LoadFromData (byte[] buffer, MonoBtlsX509Format format) + { + var data = Marshal.AllocHGlobal (buffer.Length); + if (data == IntPtr.Zero) + throw new OutOfMemoryException (); + + try { + Marshal.Copy (buffer, 0, data, buffer.Length); + var x509 = mono_btls_x509_from_data (data, buffer.Length, format); + if (x509 == IntPtr.Zero) + throw new MonoBtlsException ("Failed to read certificate from data."); + + return new MonoBtlsX509 (new BoringX509Handle (x509)); + } finally { + Marshal.FreeHGlobal (data); + } + } + + public MonoBtlsX509Name GetSubjectName () + { + var handle = mono_btls_x509_get_subject_name (Handle.DangerousGetHandle ()); + CheckError (handle != IntPtr.Zero); + return new MonoBtlsX509Name (new MonoBtlsX509Name.BoringX509NameHandle (handle, false)); + } + + public string GetSubjectNameString () + { + const int size = 4096; + var data = Marshal.AllocHGlobal (size); + try { + var ret = mono_btls_x509_get_subject_name_string ( + Handle.DangerousGetHandle (), data, size); + CheckError (ret); + return Marshal.PtrToStringAnsi (data); + } finally { + Marshal.FreeHGlobal (data); + } + } + + public long GetSubjectNameHash () + { + CheckThrow (); + using (var subject = GetSubjectName ()) + return subject.GetHash (); + } + + public MonoBtlsX509Name GetIssuerName () + { + var handle = mono_btls_x509_get_issuer_name (Handle.DangerousGetHandle ()); + CheckError (handle != IntPtr.Zero); + return new MonoBtlsX509Name (new MonoBtlsX509Name.BoringX509NameHandle (handle, false)); + } + + public string GetIssuerNameString () + { + const int size = 4096; + var data = Marshal.AllocHGlobal (size); + try { + var ret = mono_btls_x509_get_issuer_name_string ( + Handle.DangerousGetHandle (), data, size); + CheckError (ret); + return Marshal.PtrToStringAnsi (data); + } finally { + Marshal.FreeHGlobal (data); + } + } + + public byte[] GetRawData (MonoBtlsX509Format format) + { + using (var bio = new MonoBtlsBioMemory ()) { + var ret = mono_btls_x509_get_raw_data ( + Handle.DangerousGetHandle (), + bio.Handle.DangerousGetHandle (), + format); + CheckError (ret); + return bio.GetData (); + } + } + + public void GetRawData (MonoBtlsBio bio, MonoBtlsX509Format format) + { + CheckThrow (); + var ret = mono_btls_x509_get_raw_data ( + Handle.DangerousGetHandle (), + bio.Handle.DangerousGetHandle (), + format); + CheckError (ret); + } + + public static int Compare (MonoBtlsX509 a, MonoBtlsX509 b) + { + return mono_btls_x509_cmp ( + a.Handle.DangerousGetHandle (), + b.Handle.DangerousGetHandle ()); + } + + public byte[] GetCertHash () + { + IntPtr data; + var ret = mono_btls_x509_get_hash (Handle.DangerousGetHandle (), out data); + CheckError (ret > 0); + var buffer = new byte [ret]; + Marshal.Copy (data, buffer, 0, ret); + return buffer; + } + + public DateTime GetNotBefore () + { + var ticks = mono_btls_x509_get_not_before (Handle.DangerousGetHandle ()); + return new DateTime (1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds (ticks); + } + + public DateTime GetNotAfter () + { + var ticks = mono_btls_x509_get_not_after (Handle.DangerousGetHandle ()); + return new DateTime (1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds (ticks); + } + + public byte[] GetPublicKeyData () + { + using (var bio = new MonoBtlsBioMemory ()) { + var ret = mono_btls_x509_get_public_key ( + Handle.DangerousGetHandle (), + bio.Handle.DangerousGetHandle ()); + CheckError (ret > 0); + return bio.GetData (); + } + } + + public byte[] GetSerialNumber (bool mono_style) + { + int size = 256; + IntPtr data = Marshal.AllocHGlobal (size); + try { + var ret = mono_btls_x509_get_serial_number ( + Handle.DangerousGetHandle (), data, + size, mono_style ? 1 : 0); + CheckError (ret > 0); + var buffer = new byte [ret]; + Marshal.Copy (data, buffer, 0, ret); + return buffer; + } finally { + if (data != IntPtr.Zero) + Marshal.FreeHGlobal (data); + } + } + + public int GetVersion () + { + return mono_btls_x509_get_version (Handle.DangerousGetHandle ()); + } + + public Oid GetSignatureAlgorithm () + { + int size = 256; + IntPtr data = Marshal.AllocHGlobal (size); + try { + var ret = mono_btls_x509_get_signature_algorithm ( + Handle.DangerousGetHandle (), data, size); + CheckError (ret > 0); + return new Oid (Marshal.PtrToStringAnsi (data)); + } finally { + Marshal.FreeHGlobal (data); + } + } + + public AsnEncodedData GetPublicKeyAsn1 () + { + int size; + IntPtr data; + + int oidSize = 256; + var oidData = Marshal.AllocHGlobal (256); + string oid; + + try { + var ret = mono_btls_x509_get_public_key_asn1 ( + Handle.DangerousGetHandle (), oidData, oidSize, + out data, out size); + CheckError (ret); + oid = Marshal.PtrToStringAnsi (oidData); + } finally { + Marshal.FreeHGlobal (oidData); + } + + try { + var buffer = new byte[size]; + Marshal.Copy (data, buffer, 0, size); + return new AsnEncodedData (oid.ToString (), buffer); + } finally { + if (data != IntPtr.Zero) + FreeDataPtr (data); + } + } + + public AsnEncodedData GetPublicKeyParameters () + { + int size; + IntPtr data; + + int oidSize = 256; + var oidData = Marshal.AllocHGlobal (256); + string oid; + + try { + var ret = mono_btls_x509_get_public_key_parameters ( + Handle.DangerousGetHandle (), oidData, oidSize, + out data, out size); + CheckError (ret); + oid = Marshal.PtrToStringAnsi (oidData); + } finally { + Marshal.FreeHGlobal (oidData); + } + + try { + var buffer = new byte[size]; + Marshal.Copy (data, buffer, 0, size); + return new AsnEncodedData (oid.ToString (), buffer); + } finally { + if (data != IntPtr.Zero) + FreeDataPtr (data); + } + } + + public byte[] GetSubjectKeyIdentifier () + { + int size; + IntPtr data = IntPtr.Zero; + + try { + var ret = mono_btls_x509_get_subject_key_identifier ( + Handle.DangerousGetHandle (), out data, out size); + CheckError (ret); + var buffer = new byte[size]; + Marshal.Copy (data, buffer, 0, size); + return buffer; + } finally { + if (data != IntPtr.Zero) + FreeDataPtr (data); + } + } + + public MonoBtlsKey GetPublicKey () + { + var handle = mono_btls_x509_get_pubkey (Handle.DangerousGetHandle ()); + CheckError (handle != IntPtr.Zero); + return new MonoBtlsKey (new MonoBtlsKey.BoringKeyHandle (handle)); + } + + public void Print (MonoBtlsBio bio) + { + var ret = mono_btls_x509_print ( + Handle.DangerousGetHandle (), + bio.Handle.DangerousGetHandle ()); + CheckError (ret); + } + + public void ExportAsPEM (MonoBtlsBio bio, bool includeHumanReadableForm) + { + GetRawData (bio, MonoBtlsX509Format.PEM); + + if (!includeHumanReadableForm) + return; + + Print (bio); + + var hash = GetCertHash (); + var output = new StringBuilder (); + output.Append ("SHA1 Fingerprint="); + for (int i = 0; i < hash.Length; i++) { + if (i > 0) + output.Append (":"); + output.AppendFormat ("{0:X2}", hash [i]); + } + output.AppendLine (); + var outputData = Encoding.ASCII.GetBytes (output.ToString ()); + bio.Write (outputData, 0, outputData.Length); + } + + public void AddTrustObject (MonoBtlsX509Purpose purpose) + { + CheckThrow (); + var ret = mono_btls_x509_add_trust_object ( + Handle.DangerousGetHandle (), purpose); + CheckError (ret); + } + + public void AddRejectObject (MonoBtlsX509Purpose purpose) + { + CheckThrow (); + var ret = mono_btls_x509_add_reject_object ( + Handle.DangerousGetHandle (), purpose); + CheckError (ret); + } + + public void AddExplicitTrust (MonoBtlsX509TrustKind kind) + { + CheckThrow (); + var ret = mono_btls_x509_add_explicit_trust ( + Handle.DangerousGetHandle (), kind); + CheckError (ret); + } + } +} +#endif diff --git a/mcs/class/System/Mono.Btls/MonoBtlsX509Chain.cs b/mcs/class/System/Mono.Btls/MonoBtlsX509Chain.cs new file mode 100644 index 0000000000..7113d1f48f --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsX509Chain.cs @@ -0,0 +1,122 @@ +// +// MonoBtlsX509Chain.cs +// +// Author: +// Martin Baulig +// +// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +#if SECURITY_DEP && MONO_FEATURE_BTLS +using System; +using System.IO; +using System.Security.Cryptography.X509Certificates; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace Mono.Btls +{ + class MonoBtlsX509Chain : MonoBtlsObject + { + internal class BoringX509ChainHandle : MonoBtlsHandle + { + public BoringX509ChainHandle (IntPtr handle) + : base (handle, true) + { + } + + protected override bool ReleaseHandle () + { + mono_btls_x509_chain_free (handle); + return true; + } + } + + new internal BoringX509ChainHandle Handle { + get { return (BoringX509ChainHandle)base.Handle; } + } + + [DllImport (BTLS_DYLIB)] + extern static IntPtr mono_btls_x509_chain_new (); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_x509_chain_get_count (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static IntPtr mono_btls_x509_chain_get_cert (IntPtr Handle, int index); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_x509_chain_add_cert (IntPtr chain, IntPtr x509); + + [DllImport (BTLS_DYLIB)] + extern static IntPtr mono_btls_x509_chain_up_ref (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static void mono_btls_x509_chain_free (IntPtr handle); + + public MonoBtlsX509Chain () + : base (new BoringX509ChainHandle (mono_btls_x509_chain_new ())) + { + } + + internal MonoBtlsX509Chain (BoringX509ChainHandle handle) + : base (handle) + { + } + + public int Count { + get { return mono_btls_x509_chain_get_count (Handle.DangerousGetHandle ()); } + } + + public MonoBtlsX509 GetCertificate (int index) + { + if (index >= Count) + throw new IndexOutOfRangeException (); + var handle = mono_btls_x509_chain_get_cert ( + Handle.DangerousGetHandle (), index); + CheckError (handle != IntPtr.Zero); + return new MonoBtlsX509 (new MonoBtlsX509.BoringX509Handle (handle)); + } + + public void Dump () + { + Console.Error.WriteLine ("CHAIN: {0:x} {1}", Handle, Count); + for (int i = 0; i < Count; i++) { + using (var cert = GetCertificate (i)) { + Console.Error.WriteLine (" CERT #{0}: {1}", i, cert.GetSubjectNameString ()); + } + } + } + + public void AddCertificate (MonoBtlsX509 x509) + { + mono_btls_x509_chain_add_cert ( + Handle.DangerousGetHandle (), + x509.Handle.DangerousGetHandle ()); + } + + internal MonoBtlsX509Chain Copy () + { + var copy = mono_btls_x509_chain_up_ref (Handle.DangerousGetHandle ()); + CheckError (copy != IntPtr.Zero); + return new MonoBtlsX509Chain (new BoringX509ChainHandle (copy)); + } + } +} +#endif diff --git a/mcs/class/System/Mono.Btls/MonoBtlsX509Crl.cs b/mcs/class/System/Mono.Btls/MonoBtlsX509Crl.cs new file mode 100644 index 0000000000..6801b79b78 --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsX509Crl.cs @@ -0,0 +1,185 @@ +// +// MonoBtlsX509Crl.cs +// +// Author: +// Martin Baulig +// +// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +#if SECURITY_DEP && MONO_FEATURE_BTLS +using System; +using System.IO; +using System.Text; +using System.Threading; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Security.Cryptography.X509Certificates; +using System.Security.Cryptography; + +namespace Mono.Btls +{ + class MonoBtlsX509Crl : MonoBtlsObject + { + internal class BoringX509CrlHandle : MonoBtlsHandle + { + public BoringX509CrlHandle (IntPtr handle) + : base (handle, true) + { + } + + protected override bool ReleaseHandle () + { + if (handle != IntPtr.Zero) + mono_btls_x509_crl_free (handle); + return true; + } + + public IntPtr StealHandle () + { + var retval = Interlocked.Exchange (ref handle, IntPtr.Zero); + return retval; + } + } + + new internal BoringX509CrlHandle Handle { + get { return (BoringX509CrlHandle)base.Handle; } + } + + internal MonoBtlsX509Crl (BoringX509CrlHandle handle) + : base (handle) + { + } + + [DllImport (BTLS_DYLIB)] + extern static IntPtr mono_btls_x509_crl_ref (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static IntPtr mono_btls_x509_crl_from_data (IntPtr data, int len, MonoBtlsX509Format format); + + [DllImport (BTLS_DYLIB)] + extern static IntPtr mono_btls_x509_crl_get_by_cert (IntPtr handle, IntPtr x509); + + [DllImport (BTLS_DYLIB)] + unsafe extern static IntPtr mono_btls_x509_crl_get_by_serial (IntPtr handle, void *serial, int len); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_x509_crl_get_revoked_count (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static IntPtr mono_btls_x509_crl_get_revoked (IntPtr handle, int index); + + [DllImport (BTLS_DYLIB)] + extern static long mono_btls_x509_crl_get_last_update (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static long mono_btls_x509_crl_get_next_update (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static long mono_btls_x509_crl_get_version (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static IntPtr mono_btls_x509_crl_get_issuer (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static void mono_btls_x509_crl_free (IntPtr handle); + + public static MonoBtlsX509Crl LoadFromData (byte[] buffer, MonoBtlsX509Format format) + { + var data = Marshal.AllocHGlobal (buffer.Length); + if (data == IntPtr.Zero) + throw new OutOfMemoryException (); + + try { + Marshal.Copy (buffer, 0, data, buffer.Length); + var crl = mono_btls_x509_crl_from_data (data, buffer.Length, format); + if (crl == IntPtr.Zero) + throw new MonoBtlsException ("Failed to read CRL from data."); + + return new MonoBtlsX509Crl (new BoringX509CrlHandle (crl)); + } finally { + Marshal.FreeHGlobal (data); + } + } + + public MonoBtlsX509Revoked GetByCert (MonoBtlsX509 x509) + { + var revoked = mono_btls_x509_crl_get_by_cert ( + Handle.DangerousGetHandle (), + x509.Handle.DangerousGetHandle ()); + if (revoked == IntPtr.Zero) + return null; + return new MonoBtlsX509Revoked (new MonoBtlsX509Revoked.BoringX509RevokedHandle (revoked)); + } + + public unsafe MonoBtlsX509Revoked GetBySerial (byte[] serial) + { + fixed (void *ptr = serial) + { + var revoked = mono_btls_x509_crl_get_by_serial ( + Handle.DangerousGetHandle (), ptr, serial.Length); + if (revoked == IntPtr.Zero) + return null; + return new MonoBtlsX509Revoked (new MonoBtlsX509Revoked.BoringX509RevokedHandle (revoked)); + } + } + + public int GetRevokedCount () + { + return mono_btls_x509_crl_get_revoked_count (Handle.DangerousGetHandle ()); + } + + public MonoBtlsX509Revoked GetRevoked (int index) + { + if (index >= GetRevokedCount ()) + throw new ArgumentOutOfRangeException (); + + var revoked = mono_btls_x509_crl_get_revoked ( + Handle.DangerousGetHandle (), index); + if (revoked == IntPtr.Zero) + return null; + return new MonoBtlsX509Revoked (new MonoBtlsX509Revoked.BoringX509RevokedHandle (revoked)); + } + + public DateTime GetLastUpdate () + { + var ticks = mono_btls_x509_crl_get_last_update (Handle.DangerousGetHandle ()); + return new DateTime (1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds (ticks); + } + + public DateTime GetNextUpdate () + { + var ticks = mono_btls_x509_crl_get_next_update (Handle.DangerousGetHandle ()); + return new DateTime (1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds (ticks); + } + + public long GetVersion () + { + return mono_btls_x509_crl_get_version (Handle.DangerousGetHandle ()); + } + + public MonoBtlsX509Name GetIssuerName () + { + var handle = mono_btls_x509_crl_get_issuer (Handle.DangerousGetHandle ()); + CheckError (handle != IntPtr.Zero); + return new MonoBtlsX509Name (new MonoBtlsX509Name.BoringX509NameHandle (handle, false)); + } + } +} +#endif diff --git a/mcs/class/System/Mono.Btls/MonoBtlsX509Error.cs b/mcs/class/System/Mono.Btls/MonoBtlsX509Error.cs new file mode 100644 index 0000000000..bf40275b9f --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsX509Error.cs @@ -0,0 +1,111 @@ +// +// MonoBtlsX509Error.cs +// +// Author: +// Martin Baulig +// +// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +#if SECURITY_DEP && MONO_FEATURE_BTLS +using System; +namespace Mono.Btls +{ + // Keep in sync with x509_vfy.h + enum MonoBtlsX509Error + { + OK = 0, + /* illegal error (for uninitialized values, to avoid X509_V_OK): 1 */ + + UNABLE_TO_GET_ISSUER_CERT = 2, + UNABLE_TO_GET_CRL = 3, + UNABLE_TO_DECRYPT_CERT_SIGNATURE = 4, + UNABLE_TO_DECRYPT_CRL_SIGNATURE = 5, + UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY = 6, + CERT_SIGNATURE_FAILURE = 7, + CRL_SIGNATURE_FAILURE = 8, + CERT_NOT_YET_VALID = 9, + CERT_HAS_EXPIRED = 10, + CRL_NOT_YET_VALID = 11, + CRL_HAS_EXPIRED = 12, + ERROR_IN_CERT_NOT_BEFORE_FIELD = 13, + ERROR_IN_CERT_NOT_AFTER_FIELD = 14, + ERROR_IN_CRL_LAST_UPDATE_FIELD = 15, + ERROR_IN_CRL_NEXT_UPDATE_FIELD = 16, + OUT_OF_MEM = 17, + DEPTH_ZERO_SELF_SIGNED_CERT = 18, + SELF_SIGNED_CERT_IN_CHAIN = 19, + UNABLE_TO_GET_ISSUER_CERT_LOCALLY = 20, + UNABLE_TO_VERIFY_LEAF_SIGNATURE = 21, + CERT_CHAIN_TOO_LONG = 22, + CERT_REVOKED = 23, + INVALID_CA = 24, + PATH_LENGTH_EXCEEDED = 25, + INVALID_PURPOSE = 26, + CERT_UNTRUSTED = 27, + CERT_REJECTED = 28, + /* These are 'informational' when looking for issuer cert */ + SUBJECT_ISSUER_MISMATCH = 29, + AKID_SKID_MISMATCH = 30, + AKID_ISSUER_SERIAL_MISMATCH = 31, + KEYUSAGE_NO_CERTSIGN = 32, + + UNABLE_TO_GET_CRL_ISSUER = 33, + UNHANDLED_CRITICAL_EXTENSION = 34, + KEYUSAGE_NO_CRL_SIGN = 35, + UNHANDLED_CRITICAL_CRL_EXTENSION = 36, + INVALID_NON_CA = 37, + PROXY_PATH_LENGTH_EXCEEDED = 38, + KEYUSAGE_NO_DIGITAL_SIGNATURE = 39, + PROXY_CERTIFICATES_NOT_ALLOWED = 40, + + INVALID_EXTENSION = 41, + INVALID_POLICY_EXTENSION = 42, + NO_EXPLICIT_POLICY = 43, + DIFFERENT_CRL_SCOPE = 44, + UNSUPPORTED_EXTENSION_FEATURE = 45, + + UNNESTED_RESOURCE = 46, + + PERMITTED_VIOLATION = 47, + EXCLUDED_VIOLATION = 48, + SUBTREE_MINMAX = 49, + UNSUPPORTED_CONSTRAINT_TYPE = 51, + UNSUPPORTED_CONSTRAINT_SYNTAX = 52, + UNSUPPORTED_NAME_SYNTAX = 53, + CRL_PATH_VALIDATION_ERROR = 54, + + /* Suite B mode algorithm violation */ + SUITE_B_INVALID_VERSION = 56, + SUITE_B_INVALID_ALGORITHM = 57, + SUITE_B_INVALID_CURVE = 58, + SUITE_B_INVALID_SIGNATURE_ALGORITHM = 59, + SUITE_B_LOS_NOT_ALLOWED = 60, + SUITE_B_CANNOT_SIGN_P_384_WITH_P_256 = 61, + + /* Host, email and IP check errors */ + HOSTNAME_MISMATCH = 62, + EMAIL_MISMATCH = 63, + IP_ADDRESS_MISMATCH = 64, + + /* The application is not happy */ + APPLICATION_VERIFICATION = 50 + } +} +#endif diff --git a/mcs/class/System/Mono.Btls/MonoBtlsX509Exception.cs b/mcs/class/System/Mono.Btls/MonoBtlsX509Exception.cs new file mode 100644 index 0000000000..bb982bc0f4 --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsX509Exception.cs @@ -0,0 +1,56 @@ +// +// MonoBtlsX509Exception.cs +// +// Author: +// Martin Baulig +// +// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +#if SECURITY_DEP && MONO_FEATURE_BTLS +using System; + +namespace Mono.Btls +{ + class MonoBtlsX509Exception : Exception + { + public MonoBtlsX509Error ErrorCode { + get; + private set; + } + + public string ErrorMessage { + get; + private set; + } + + public MonoBtlsX509Exception (MonoBtlsX509Error code, string message) + : base (message) + { + ErrorCode = code; + ErrorMessage = message; + } + + public override string ToString () + { + return string.Format ("[MonoBtlsX509Exception: ErrorCode={0}, ErrorMessage={1}]", ErrorCode, ErrorMessage); + } + } +} +#endif diff --git a/mcs/class/System/Mono.Btls/MonoBtlsX509FileType.cs b/mcs/class/System/Mono.Btls/MonoBtlsX509FileType.cs new file mode 100644 index 0000000000..1475457507 --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsX509FileType.cs @@ -0,0 +1,37 @@ +// +// MonoBtlsX509FileType.cs +// +// Author: +// Martin Baulig +// +// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +#if SECURITY_DEP && MONO_FEATURE_BTLS +using System; +namespace Mono.Btls +{ + enum MonoBtlsX509FileType + { + PEM = 1, + ASN1 = 2, + DEFAULT = 3 + } +} +#endif diff --git a/mcs/class/System/Mono.Btls/MonoBtlsX509Format.cs b/mcs/class/System/Mono.Btls/MonoBtlsX509Format.cs new file mode 100644 index 0000000000..609d0c1f2a --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsX509Format.cs @@ -0,0 +1,36 @@ +// +// MonoBtlsX509Format.cs +// +// Author: +// Martin Baulig +// +// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +#if SECURITY_DEP && MONO_FEATURE_BTLS +using System; +namespace Mono.Btls +{ + enum MonoBtlsX509Format + { + DER = 1, + PEM = 2 + } +} +#endif diff --git a/mcs/class/System/Mono.Btls/MonoBtlsX509Lookup.cs b/mcs/class/System/Mono.Btls/MonoBtlsX509Lookup.cs new file mode 100644 index 0000000000..8a6bf30903 --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsX509Lookup.cs @@ -0,0 +1,213 @@ +// +// MonoBtlsX509Lookup.cs +// +// Author: +// Martin Baulig +// +// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +#if SECURITY_DEP && MONO_FEATURE_BTLS +using System; +using System.IO; +using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; +using System.Collections.Generic; + +namespace Mono.Btls +{ + class MonoBtlsX509Lookup : MonoBtlsObject + { + internal class BoringX509LookupHandle : MonoBtlsHandle + { + public BoringX509LookupHandle (IntPtr handle) + : base (handle, true) + { + } + + protected override bool ReleaseHandle () + { + mono_btls_x509_lookup_free (handle); + return true; + } + } + + new internal BoringX509LookupHandle Handle { + get { return (BoringX509LookupHandle)base.Handle; } + } + + [DllImport (BTLS_DYLIB)] + extern static IntPtr mono_btls_x509_lookup_new (IntPtr store, MonoBtlsX509LookupType type); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_x509_lookup_load_file (IntPtr handle, IntPtr file, MonoBtlsX509FileType type); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_x509_lookup_add_dir (IntPtr handle, IntPtr dir, MonoBtlsX509FileType type); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_x509_lookup_add_mono (IntPtr handle, IntPtr monoLookup); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_x509_lookup_init (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_x509_lookup_shutdown (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static IntPtr mono_btls_x509_lookup_by_subject (IntPtr handle, IntPtr name); + + [DllImport (BTLS_DYLIB)] + extern static IntPtr mono_btls_x509_lookup_by_fingerprint (IntPtr handle, IntPtr bytes, int len); + + [DllImport (BTLS_DYLIB)] + extern static void mono_btls_x509_lookup_free (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static IntPtr mono_btls_x509_lookup_peek_lookup (IntPtr handle); + + MonoBtlsX509LookupType type; + List monoLookups; + +#if FIXME + // Do we need this? + internal MonoBtlsX509Lookup (BoringX509LookupHandle handle) + : base (handle) + { + } +#endif + + static BoringX509LookupHandle Create_internal (MonoBtlsX509Store store, MonoBtlsX509LookupType type) + { + var handle = mono_btls_x509_lookup_new ( + store.Handle.DangerousGetHandle (), type); + if (handle == IntPtr.Zero) + throw new MonoBtlsException (); + return new BoringX509LookupHandle (handle); + } + + internal MonoBtlsX509Lookup (MonoBtlsX509Store store, MonoBtlsX509LookupType type) + : base (Create_internal (store, type)) + { + this.type = type; + } + + internal IntPtr GetNativeLookup () + { + return mono_btls_x509_lookup_peek_lookup (Handle.DangerousGetHandle ()); + } + + public void LoadFile (string file, MonoBtlsX509FileType type) + { + IntPtr filePtr = IntPtr.Zero; + try { + if (file != null) + filePtr = Marshal.StringToHGlobalAnsi (file); + var ret = mono_btls_x509_lookup_load_file ( + Handle.DangerousGetHandle (), filePtr, type); + CheckError (ret); + } finally { + if (filePtr != IntPtr.Zero) + Marshal.FreeHGlobal (filePtr); + } + } + + public void AddDirectory (string dir, MonoBtlsX509FileType type) + { + IntPtr dirPtr = IntPtr.Zero; + try { + if (dir != null) + dirPtr = Marshal.StringToHGlobalAnsi (dir); + var ret = mono_btls_x509_lookup_add_dir ( + Handle.DangerousGetHandle (), dirPtr, type); + CheckError (ret); + } finally { + if (dirPtr != IntPtr.Zero) + Marshal.FreeHGlobal (dirPtr); + } + } + + // Takes ownership of the 'monoLookup'. + internal void AddMono (MonoBtlsX509LookupMono monoLookup) + { + if (type != MonoBtlsX509LookupType.MONO) + throw new NotSupportedException (); + var ret = mono_btls_x509_lookup_add_mono ( + Handle.DangerousGetHandle (), monoLookup.Handle.DangerousGetHandle ()); + CheckError (ret); + + if (monoLookups == null) + monoLookups = new List (); + monoLookups.Add (monoLookup); + } + + public void Initialize () + { + var ret = mono_btls_x509_lookup_init (Handle.DangerousGetHandle ()); + CheckError (ret); + } + + public void Shutdown () + { + var ret = mono_btls_x509_lookup_shutdown (Handle.DangerousGetHandle ()); + CheckError (ret); + } + + public MonoBtlsX509 LookupBySubject (MonoBtlsX509Name name) + { + var handle = mono_btls_x509_lookup_by_subject ( + Handle.DangerousGetHandle (), + name.Handle.DangerousGetHandle ()); + if (handle == IntPtr.Zero) + return null; + return new MonoBtlsX509 (new MonoBtlsX509.BoringX509Handle (handle)); + } + + public MonoBtlsX509 LookupByFingerPrint (byte[] fingerprint) + { + var bytes = Marshal.AllocHGlobal (fingerprint.Length); + try { + Marshal.Copy (fingerprint, 0, bytes, fingerprint.Length); + var handle = mono_btls_x509_lookup_by_fingerprint ( + Handle.DangerousGetHandle (), + bytes, fingerprint.Length); + if (handle == IntPtr.Zero) + return null; + return new MonoBtlsX509 (new MonoBtlsX509.BoringX509Handle (handle)); + } finally { + if (bytes != IntPtr.Zero) + Marshal.FreeHGlobal (bytes); + } + } + + protected override void Close () + { + try { + if (monoLookups != null) { + foreach (var monoLookup in monoLookups) + monoLookup.Dispose (); + monoLookups = null; + } + } finally { + base.Close (); + } + } + } +} +#endif diff --git a/mcs/class/Mono.Security.Providers.OldTls/Properties/AssemblyInfo.cs b/mcs/class/System/Mono.Btls/MonoBtlsX509LookupAndroid.cs similarity index 65% rename from mcs/class/Mono.Security.Providers.OldTls/Properties/AssemblyInfo.cs rename to mcs/class/System/Mono.Btls/MonoBtlsX509LookupAndroid.cs index 923beca26c..db0151ac93 100644 --- a/mcs/class/Mono.Security.Providers.OldTls/Properties/AssemblyInfo.cs +++ b/mcs/class/System/Mono.Btls/MonoBtlsX509LookupAndroid.cs @@ -1,10 +1,10 @@ // -// AssemblyInfo.cs +// MonoBtlsX509LookupAndroid.cs // // Author: // Martin Baulig // -// Copyright (c) 2015 Xamarin, Inc. +// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -23,24 +23,21 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +#if SECURITY_DEP && MONO_FEATURE_BTLS && MONODROID using System; -using System.Reflection; -using System.Resources; -using System.Security; -using System.Security.Permissions; -using System.Runtime.CompilerServices; +using System.IO; using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; +using System.Security.Cryptography.X509Certificates; -// General Information about the system assembly - -[assembly: AssemblyVersion (Consts.FxVersion)] - -[assembly: AssemblyCompany ("MONO development team")] -[assembly: AssemblyCopyright ("(c) 2015 Xamarin")] -[assembly: AssemblyDescription ("Mono.Security.Providers.OldTls.dll")] -[assembly: AssemblyProduct ("MONO CLI")] -[assembly: AssemblyTitle ("Mono.Security.Providers.OldTls.dll")] -[assembly: CLSCompliant (true)] -[assembly: ComVisible (false)] -[assembly: NeutralResourcesLanguage ("en-US")] - +namespace Mono.Btls +{ + internal class MonoBtlsX509LookupAndroid : MonoBtlsX509LookupMono + { + protected override MonoBtlsX509 OnGetBySubject (MonoBtlsX509Name name) + { + return AndroidPlatform.CertStoreLookup (name); + } + } +} +#endif diff --git a/mcs/class/System/Mono.Btls/MonoBtlsX509LookupMono.cs b/mcs/class/System/Mono.Btls/MonoBtlsX509LookupMono.cs new file mode 100644 index 0000000000..cd86cde03a --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsX509LookupMono.cs @@ -0,0 +1,128 @@ +// +// MonoBtlsX509LookupMono.cs +// +// Author: +// Martin Baulig +// +// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +#if SECURITY_DEP && MONO_FEATURE_BTLS +using System; +using System.IO; +using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; + +namespace Mono.Btls +{ + abstract class MonoBtlsX509LookupMono : MonoBtlsObject + { + internal class BoringX509LookupMonoHandle : MonoBtlsHandle + { + public BoringX509LookupMonoHandle (IntPtr handle) + : base (handle, true) + { + } + + protected override bool ReleaseHandle () + { + mono_btls_x509_lookup_mono_free (handle); + return true; + } + } + + new internal BoringX509LookupMonoHandle Handle { + get { return (BoringX509LookupMonoHandle)base.Handle; } + } + + [DllImport (BTLS_DYLIB)] + extern static IntPtr mono_btls_x509_lookup_mono_new (); + + [DllImport (BTLS_DYLIB)] + extern static void mono_btls_x509_lookup_mono_init ( + IntPtr handle, IntPtr instance, IntPtr by_subject_func); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_x509_lookup_mono_free (IntPtr handle); + + delegate int BySubjectFunc (IntPtr instance, IntPtr name, out IntPtr x509_ptr); + + GCHandle gch; + IntPtr instance; + BySubjectFunc bySubjectFunc; + IntPtr bySubjectFuncPtr; + + internal MonoBtlsX509LookupMono () + : base (new BoringX509LookupMonoHandle (mono_btls_x509_lookup_mono_new ())) + { + gch = GCHandle.Alloc (this); + instance = GCHandle.ToIntPtr (gch); + bySubjectFunc = OnGetBySubject; + bySubjectFuncPtr = Marshal.GetFunctionPointerForDelegate (bySubjectFunc); + mono_btls_x509_lookup_mono_init (Handle.DangerousGetHandle (), instance, bySubjectFuncPtr); + } + + protected abstract MonoBtlsX509 OnGetBySubject (MonoBtlsX509Name name); + +#if MONOTOUCH + [MonoTouch.MonoPInvokeCallback (typeof (BySubjectFunc))] +#endif + static int OnGetBySubject (IntPtr instance, IntPtr name_ptr, out IntPtr x509_ptr) + { + try { + MonoBtlsX509LookupMono obj; + MonoBtlsX509Name.BoringX509NameHandle name_handle = null; + try { + obj = (MonoBtlsX509LookupMono)GCHandle.FromIntPtr (instance).Target; + name_handle = new MonoBtlsX509Name.BoringX509NameHandle (name_ptr, false); + MonoBtlsX509Name name_obj = new MonoBtlsX509Name (name_handle); + var x509 = obj.OnGetBySubject (name_obj); + if (x509 != null) { + x509_ptr = x509.Handle.StealHandle (); + return 1; + } else { + x509_ptr = IntPtr.Zero; + return 0; + } + } finally { + if (name_handle != null) + name_handle.Dispose (); + } + } catch (Exception ex) { + Console.WriteLine ("LOOKUP METHOD - GET BY SUBJECT EX: {0}", ex); + x509_ptr = IntPtr.Zero; + return 0; + } + } + + protected override void Close () + { + try { + if (gch.IsAllocated) + gch.Free (); + } finally { + instance = IntPtr.Zero; + bySubjectFunc = null; + bySubjectFuncPtr = IntPtr.Zero; + base.Close (); + } + } + } +} +#endif diff --git a/mcs/class/System/Mono.Btls/MonoBtlsX509LookupMonoCollection.cs b/mcs/class/System/Mono.Btls/MonoBtlsX509LookupMonoCollection.cs new file mode 100644 index 0000000000..139243e2a2 --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsX509LookupMonoCollection.cs @@ -0,0 +1,102 @@ +// +// MonoBtlsX509LookupMonoCollection.cs +// +// Author: +// Martin Baulig +// +// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +#if SECURITY_DEP && MONO_FEATURE_BTLS +using System; +using System.IO; +using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; +using System.Security.Cryptography.X509Certificates; + +#if MONOTOUCH +using MonoTouch; +#endif + +namespace Mono.Btls +{ + internal class MonoBtlsX509LookupMonoCollection : MonoBtlsX509LookupMono + { + long[] hashes; + MonoBtlsX509[] certificates; + X509CertificateCollection collection; + MonoBtlsX509TrustKind trust; + + internal MonoBtlsX509LookupMonoCollection (X509CertificateCollection collection, MonoBtlsX509TrustKind trust) + { + this.collection = collection; + this.trust = trust; + } + + void Initialize () + { + if (certificates != null) + return; + + hashes = new long [collection.Count]; + certificates = new MonoBtlsX509 [collection.Count]; + for (int i = 0; i < collection.Count; i++) { + // Create new 'X509 *' instance since we need to modify it to add the + // trust settings. + var data = collection [i].GetRawCertData (); + certificates [i] = MonoBtlsX509.LoadFromData (data, MonoBtlsX509Format.DER); + certificates [i].AddExplicitTrust (trust); + hashes [i] = certificates [i].GetSubjectNameHash (); + } + } + + protected override MonoBtlsX509 OnGetBySubject (MonoBtlsX509Name name) + { + Console.WriteLine ("COLLECTION LOOKUP: {0:x} - {1}", name.GetHash (), name.GetString ()); + Initialize (); + + var hash = name.GetHash (); + for (int i = 0; i < certificates.Length; i++) { + if (hashes [i] == hash) + return certificates [i]; + } + + return null; + } + + protected override void Close () + { + try { + if (certificates != null) { + for (int i = 0; i < certificates.Length; i++) { + if (certificates [i] != null) { + certificates [i].Dispose (); + certificates [i] = null; + } + } + certificates = null; + hashes = null; + } + } finally { + base.Close (); + } + } + } +} +#endif diff --git a/mcs/class/System/Mono.Btls/MonoBtlsX509LookupType.cs b/mcs/class/System/Mono.Btls/MonoBtlsX509LookupType.cs new file mode 100644 index 0000000000..6bb42d989f --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsX509LookupType.cs @@ -0,0 +1,39 @@ +// +// MonoBtlsX509LookupCollection.cs +// +// Author: +// Martin Baulig +// +// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +#if SECURITY_DEP && MONO_FEATURE_BTLS +using System; + +namespace Mono.Btls +{ + enum MonoBtlsX509LookupType + { + UNKNOWN = 0, + FILE, + HASH_DIR, + MONO + } +} +#endif diff --git a/mcs/class/System/Mono.Btls/MonoBtlsX509Name.cs b/mcs/class/System/Mono.Btls/MonoBtlsX509Name.cs new file mode 100644 index 0000000000..74e335a64c --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsX509Name.cs @@ -0,0 +1,216 @@ +// +// MonoBtlsX509Name.cs +// +// Author: +// Martin Baulig +// +// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +#if SECURITY_DEP && MONO_FEATURE_BTLS +using System; +using System.IO; +using System.Text; +using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; + +namespace Mono.Btls +{ + class MonoBtlsX509Name : MonoBtlsObject + { + internal class BoringX509NameHandle : MonoBtlsHandle + { + bool dontFree; + + internal BoringX509NameHandle (IntPtr handle, bool ownsHandle) + : base (handle, ownsHandle) + { + this.dontFree = !ownsHandle; + } + + protected override bool ReleaseHandle () + { + if (!dontFree) + mono_btls_x509_name_free (handle); + return true; + } + } + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_x509_name_print_bio (IntPtr handle, IntPtr bio); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_x509_name_print_string (IntPtr handle, IntPtr buffer, int size); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_x509_name_get_raw_data (IntPtr handle, out IntPtr buffer, int use_canon_enc); + + [DllImport (BTLS_DYLIB)] + extern static long mono_btls_x509_name_hash (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static long mono_btls_x509_name_hash_old (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_x509_name_get_entry_count (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static MonoBtlsX509NameEntryType mono_btls_x509_name_get_entry_type (IntPtr name, int index); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_x509_name_get_entry_oid (IntPtr name, int index, IntPtr buffer, int size); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_x509_name_get_entry_oid_data (IntPtr name, int index, out IntPtr data); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_x509_name_get_entry_value (IntPtr name, int index, out int tag, out IntPtr str); + + [DllImport (BTLS_DYLIB)] + extern unsafe static IntPtr mono_btls_x509_name_from_data (void* data, int len, int use_canon_enc); + + [DllImport (BTLS_DYLIB)] + extern static void mono_btls_x509_name_free (IntPtr handle); + + new internal BoringX509NameHandle Handle { + get { return (BoringX509NameHandle)base.Handle; } + } + + internal MonoBtlsX509Name (BoringX509NameHandle handle) + : base (handle) + { + } + + public string GetString () + { + const int size = 4096; + var data = Marshal.AllocHGlobal (size); + try { + var ret = mono_btls_x509_name_print_string ( + Handle.DangerousGetHandle (), data, size); + CheckError (ret); + return Marshal.PtrToStringAnsi (data); + } finally { + Marshal.FreeHGlobal (data); + } + } + + public void PrintBio (MonoBtlsBio bio) + { + var ret = mono_btls_x509_name_print_bio ( + Handle.DangerousGetHandle (), + bio.Handle.DangerousGetHandle ()); + CheckError (ret); + } + + public byte[] GetRawData (bool use_canon_enc) + { + IntPtr data; + var ret = mono_btls_x509_name_get_raw_data ( + Handle.DangerousGetHandle (), + out data, use_canon_enc ? 1 : 0); + CheckError (ret > 0); + var buffer = new byte [ret]; + Marshal.Copy (data, buffer, 0, ret); + FreeDataPtr (data); + return buffer; + } + + public long GetHash () + { + return mono_btls_x509_name_hash (Handle.DangerousGetHandle ()); + } + + public long GetHashOld () + { + return mono_btls_x509_name_hash_old (Handle.DangerousGetHandle ()); + } + + public int GetEntryCount () + { + return mono_btls_x509_name_get_entry_count (Handle.DangerousGetHandle ()); + } + + public MonoBtlsX509NameEntryType GetEntryType (int index) + { + if (index >= GetEntryCount ()) + throw new ArgumentOutOfRangeException (); + return mono_btls_x509_name_get_entry_type ( + Handle.DangerousGetHandle (), index); + } + + public string GetEntryOid (int index) + { + if (index >= GetEntryCount ()) + throw new ArgumentOutOfRangeException (); + + const int size = 4096; + var data = Marshal.AllocHGlobal (size); + try { + var ret = mono_btls_x509_name_get_entry_oid ( + Handle.DangerousGetHandle (), + index, data, size); + CheckError (ret > 0); + return Marshal.PtrToStringAnsi (data); + } finally { + Marshal.FreeHGlobal (data); + } + } + + public byte[] GetEntryOidData (int index) + { + IntPtr data; + var ret = mono_btls_x509_name_get_entry_oid_data ( + Handle.DangerousGetHandle (), index, out data); + CheckError (ret > 0); + + var bytes = new byte[ret]; + Marshal.Copy (data, bytes, 0, ret); + return bytes; + } + + public unsafe string GetEntryValue (int index, out int tag) + { + if (index >= GetEntryCount ()) + throw new ArgumentOutOfRangeException (); + IntPtr data; + var ret = mono_btls_x509_name_get_entry_value ( + Handle.DangerousGetHandle (), index, out tag, out data); + if (ret <= 0) + return null; + try { + return new UTF8Encoding ().GetString ((byte*)data, ret); + } finally { + if (data != IntPtr.Zero) + FreeDataPtr (data); + } + } + + public static unsafe MonoBtlsX509Name CreateFromData (byte[] data, bool use_canon_enc) + { + fixed (void *ptr = data) { + var handle = mono_btls_x509_name_from_data (ptr, data.Length, use_canon_enc ? 1 : 0); + if (handle == IntPtr.Zero) + throw new MonoBtlsException ("mono_btls_x509_name_from_data() failed."); + return new MonoBtlsX509Name (new BoringX509NameHandle (handle, false)); + } + } + } +} +#endif diff --git a/mcs/class/System/Mono.Btls/MonoBtlsX509NameEntryType.cs b/mcs/class/System/Mono.Btls/MonoBtlsX509NameEntryType.cs new file mode 100644 index 0000000000..1a4cdae673 --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsX509NameEntryType.cs @@ -0,0 +1,51 @@ +// +// MonoBtlsX509NameEntryType.cs +// +// Author: +// Martin Baulig +// +// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +#if SECURITY_DEP && MONO_FEATURE_BTLS +using System; +namespace Mono.Btls +{ + enum MonoBtlsX509NameEntryType : int + { + Unknown = 0, + CountryName, + OrganizationName, + OrganizationalUnitName, + CommonName, + LocalityName, + StateOrProvinceName, + StreetAddress, + SerialNumber, + DomainComponent, + UserId, + Email, + DnQualifier, + Title, + Surname, + GivenName, + Initial + } +} +#endif diff --git a/mcs/class/System/Mono.Btls/MonoBtlsX509Purpose.cs b/mcs/class/System/Mono.Btls/MonoBtlsX509Purpose.cs new file mode 100644 index 0000000000..b8b416330d --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsX509Purpose.cs @@ -0,0 +1,43 @@ +// +// MonoBtlsX509Purpose.cs +// +// Author: +// Martin Baulig +// +// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +#if SECURITY_DEP && MONO_FEATURE_BTLS +using System; +namespace Mono.Btls +{ + enum MonoBtlsX509Purpose + { + SSL_CLIENT = 1, + SSL_SERVER = 2, + NS_SSL_SERVER = 3, + SMIME_SIGN = 4, + SMIME_ENCRYPT = 5, + CRL_SIGN = 6, + ANY = 7, + OCSP_HELPER = 8, + TIMESTAMP_SIGN = 9, + } +} +#endif diff --git a/mcs/class/System/Mono.Btls/MonoBtlsX509Revoked.cs b/mcs/class/System/Mono.Btls/MonoBtlsX509Revoked.cs new file mode 100644 index 0000000000..1bb279a4ae --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsX509Revoked.cs @@ -0,0 +1,120 @@ +// +// MonoBtlsX509Revoked.cs +// +// Author: +// Martin Baulig +// +// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +#if SECURITY_DEP && MONO_FEATURE_BTLS +using System; +using System.IO; +using System.Text; +using System.Threading; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Security.Cryptography.X509Certificates; +using System.Security.Cryptography; + +namespace Mono.Btls +{ + class MonoBtlsX509Revoked : MonoBtlsObject + { + internal class BoringX509RevokedHandle : MonoBtlsHandle + { + public BoringX509RevokedHandle (IntPtr handle) + : base (handle, true) + { + } + + protected override bool ReleaseHandle () + { + if (handle != IntPtr.Zero) + mono_btls_x509_revoked_free (handle); + return true; + } + + public IntPtr StealHandle () + { + var retval = Interlocked.Exchange (ref handle, IntPtr.Zero); + return retval; + } + } + + new internal BoringX509RevokedHandle Handle { + get { return (BoringX509RevokedHandle)base.Handle; } + } + + internal MonoBtlsX509Revoked (BoringX509RevokedHandle handle) + : base (handle) + { + } + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_x509_revoked_get_serial_number (IntPtr handle, IntPtr data, int size); + + [DllImport (BTLS_DYLIB)] + extern static long mono_btls_x509_revoked_get_revocation_date (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_x509_revoked_get_reason (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_x509_revoked_get_sequence (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static void mono_btls_x509_revoked_free (IntPtr handle); + + public byte[] GetSerialNumber () + { + int size = 256; + IntPtr data = Marshal.AllocHGlobal (size); + try { + var ret = mono_btls_x509_revoked_get_serial_number ( + Handle.DangerousGetHandle (), data, size); + CheckError (ret > 0); + var buffer = new byte[ret]; + Marshal.Copy (data, buffer, 0, ret); + return buffer; + } finally { + if (data != IntPtr.Zero) + Marshal.FreeHGlobal (data); + } + } + + public DateTime GetRevocationDate () + { + var ticks = mono_btls_x509_revoked_get_revocation_date ( + Handle.DangerousGetHandle ()); + return new DateTime (1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds (ticks); + } + + public int GetReason () + { + return mono_btls_x509_revoked_get_reason (Handle.DangerousGetHandle ()); + } + + public int GetSequence () + { + return mono_btls_x509_revoked_get_sequence (Handle.DangerousGetHandle ()); + } + } +} +#endif diff --git a/mcs/class/System/Mono.Btls/MonoBtlsX509Store.cs b/mcs/class/System/Mono.Btls/MonoBtlsX509Store.cs new file mode 100644 index 0000000000..537993566e --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsX509Store.cs @@ -0,0 +1,230 @@ +// +// MonoBtlsX509Store.cs +// +// Author: +// Martin Baulig +// +// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +#if SECURITY_DEP && MONO_FEATURE_BTLS +using System; +using System.IO; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; +using System.Security.Cryptography.X509Certificates; + +namespace Mono.Btls +{ + class MonoBtlsX509Store : MonoBtlsObject + { + internal class BoringX509StoreHandle : MonoBtlsHandle + { + public BoringX509StoreHandle (IntPtr handle) + : base (handle, true) + { + } + + protected override bool ReleaseHandle () + { + mono_btls_x509_store_free (handle); + return true; + } + } + + new internal BoringX509StoreHandle Handle { + get { return (BoringX509StoreHandle)base.Handle; } + } + + [DllImport (BTLS_DYLIB)] + extern static IntPtr mono_btls_x509_store_new (); + + [DllImport (BTLS_DYLIB)] + extern static IntPtr mono_btls_x509_store_from_ctx (IntPtr ctx); + + [DllImport (BTLS_DYLIB)] + extern static IntPtr mono_btls_x509_store_from_ssl_ctx (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_x509_store_load_locations (IntPtr handle, IntPtr file, IntPtr path); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_x509_store_set_default_paths (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_x509_store_add_cert (IntPtr handle, IntPtr x509); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_x509_store_get_count (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static void mono_btls_x509_store_free (IntPtr handle); + + Dictionary lookupHash; + + public void LoadLocations (string file, string path) + { + IntPtr filePtr = IntPtr.Zero; + IntPtr pathPtr = IntPtr.Zero; + try { + if (file != null) + filePtr = Marshal.StringToHGlobalAnsi (file); + if (path != null) + pathPtr = Marshal.StringToHGlobalAnsi (path); + var ret = mono_btls_x509_store_load_locations ( + Handle.DangerousGetHandle (), filePtr, pathPtr); + CheckError (ret); + } finally { + if (filePtr != IntPtr.Zero) + Marshal.FreeHGlobal (filePtr); + if (pathPtr != IntPtr.Zero) + Marshal.FreeHGlobal (pathPtr); + } + } + + public void SetDefaultPaths () + { + var ret = mono_btls_x509_store_set_default_paths (Handle.DangerousGetHandle ()); + CheckError (ret); + } + + static BoringX509StoreHandle Create_internal () + { + var handle = mono_btls_x509_store_new (); + if (handle == IntPtr.Zero) + throw new MonoBtlsException (); + return new BoringX509StoreHandle (handle); + } + + static BoringX509StoreHandle Create_internal (IntPtr store_ctx) + { + var handle = mono_btls_x509_store_from_ssl_ctx (store_ctx); + if (handle == IntPtr.Zero) + throw new MonoBtlsException (); + return new BoringX509StoreHandle (handle); + } + + static BoringX509StoreHandle Create_internal (MonoBtlsSslCtx.BoringSslCtxHandle ctx) + { + var handle = mono_btls_x509_store_from_ssl_ctx (ctx.DangerousGetHandle ()); + if (handle == IntPtr.Zero) + throw new MonoBtlsException (); + return new BoringX509StoreHandle (handle); + } + + internal MonoBtlsX509Store () + : base (Create_internal ()) + { + } + + internal MonoBtlsX509Store (IntPtr store_ctx) + : base (Create_internal (store_ctx)) + { + } + + internal MonoBtlsX509Store (MonoBtlsSslCtx.BoringSslCtxHandle ctx) + : base (Create_internal (ctx)) + { + } + + public void AddCertificate (MonoBtlsX509 x509) + { + var ret = mono_btls_x509_store_add_cert ( + Handle.DangerousGetHandle (), + x509.Handle.DangerousGetHandle ()); + CheckError (ret); + } + + public int GetCount () + { + return mono_btls_x509_store_get_count (Handle.DangerousGetHandle ()); + } + + internal void AddTrustedRoots () + { + var systemRoot = MonoBtlsProvider.GetSystemStoreLocation (); + LoadLocations (null, systemRoot); + } + + public MonoBtlsX509Lookup AddLookup (MonoBtlsX509LookupType type) + { + if (lookupHash == null) + lookupHash = new Dictionary (); + + /* + * X509_STORE_add_lookup() returns the same 'X509_LOOKUP *' for each + * unique 'X509_LOOKUP_METHOD *' (which is supposed to be a static struct) + * and we want to use the same managed object for each unique 'X509_LOOKUP *'. + */ + var lookup = new MonoBtlsX509Lookup (this, type); + var nativeLookup = lookup.GetNativeLookup (); + if (lookupHash.ContainsKey (nativeLookup)) { + lookup.Dispose (); + lookup = lookupHash [nativeLookup]; + } else { + lookupHash.Add (nativeLookup, lookup); + } + + return lookup; + } + + public void AddDirectoryLookup (string dir, MonoBtlsX509FileType type) + { + var lookup = AddLookup (MonoBtlsX509LookupType.HASH_DIR); + lookup.AddDirectory (dir, type); + } + + public void AddFileLookup (string file, MonoBtlsX509FileType type) + { + var lookup = AddLookup (MonoBtlsX509LookupType.FILE); + lookup.LoadFile (file, type); + } + + public void AddCollection (X509CertificateCollection collection, MonoBtlsX509TrustKind trust) + { + var monoLookup = new MonoBtlsX509LookupMonoCollection (collection, trust); + var lookup = new MonoBtlsX509Lookup (this, MonoBtlsX509LookupType.MONO); + lookup.AddMono (monoLookup); + } + +#if MONODROID + public void AddAndroidLookup () + { + var androidLookup = new MonoBtlsX509LookupAndroid (); + var lookup = new MonoBtlsX509Lookup (this, MonoBtlsX509LookupType.MONO); + lookup.AddMono (androidLookup); + } +#endif + + protected override void Close () + { + try { + if (lookupHash != null) { + foreach (var lookup in lookupHash.Values) + lookup.Dispose (); + lookupHash = null; + } + } finally { + base.Close (); + } + } + } +} +#endif diff --git a/mcs/class/System/Mono.Btls/MonoBtlsX509StoreCtx.cs b/mcs/class/System/Mono.Btls/MonoBtlsX509StoreCtx.cs new file mode 100644 index 0000000000..9b8e82bb5e --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsX509StoreCtx.cs @@ -0,0 +1,244 @@ +// +// MonoBtlsX509StoreCtx.cs +// +// Author: +// Martin Baulig +// +// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +#if SECURITY_DEP && MONO_FEATURE_BTLS +using System; +using System.IO; +using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; + +namespace Mono.Btls +{ + class MonoBtlsX509StoreCtx : MonoBtlsObject + { + internal class BoringX509StoreCtxHandle : MonoBtlsHandle + { + bool dontFree; + + internal BoringX509StoreCtxHandle (IntPtr handle, bool ownsHandle = true) + : base (handle, ownsHandle) + { + dontFree = !ownsHandle; + } + + #if FIXME + internal BoringX509StoreCtxHandle (IntPtr handle) + : base () + { + base.handle = handle; + this.dontFree = true; + } + #endif + + protected override bool ReleaseHandle () + { + if (!dontFree) + mono_btls_x509_store_ctx_free (handle); + return true; + } + } + + int? verifyResult; + + new internal BoringX509StoreCtxHandle Handle { + get { return (BoringX509StoreCtxHandle)base.Handle; } + } + + [DllImport (BTLS_DYLIB)] + extern static IntPtr mono_btls_x509_store_ctx_new (); + + [DllImport (BTLS_DYLIB)] + extern static IntPtr mono_btls_x509_store_ctx_from_ptr (IntPtr ctx); + + [DllImport (BTLS_DYLIB)] + extern static MonoBtlsX509Error mono_btls_x509_store_ctx_get_error (IntPtr handle, out IntPtr error_string); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_x509_store_ctx_get_error_depth (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static IntPtr mono_btls_x509_store_ctx_get_chain (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_x509_store_ctx_init (IntPtr handle, IntPtr store, IntPtr chain); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_x509_store_ctx_set_param (IntPtr handle, IntPtr param); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_x509_store_ctx_verify_cert (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static IntPtr mono_btls_x509_store_ctx_get_by_subject (IntPtr handle, IntPtr name); + + [DllImport (BTLS_DYLIB)] + extern static IntPtr mono_btls_x509_store_ctx_get_current_cert (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static IntPtr mono_btls_x509_store_ctx_get_current_issuer (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static IntPtr mono_btls_x509_store_ctx_get_verify_param (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static IntPtr mono_btls_x509_store_ctx_get_untrusted (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static IntPtr mono_btls_x509_store_ctx_up_ref (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static void mono_btls_x509_store_ctx_free (IntPtr handle); + + internal MonoBtlsX509StoreCtx () + : base (new BoringX509StoreCtxHandle (mono_btls_x509_store_ctx_new ())) + { + } + + static BoringX509StoreCtxHandle Create_internal (IntPtr store_ctx) + { + var handle = mono_btls_x509_store_ctx_from_ptr (store_ctx); + if (handle == IntPtr.Zero) + throw new MonoBtlsException (); + return new BoringX509StoreCtxHandle (handle); + } + + internal MonoBtlsX509StoreCtx (int preverify_ok, IntPtr store_ctx) + : base (Create_internal (store_ctx)) + { + verifyResult = preverify_ok; + } + + internal MonoBtlsX509StoreCtx (BoringX509StoreCtxHandle ptr, int? verifyResult) + : base (ptr) + { + this.verifyResult = verifyResult; + } + + public MonoBtlsX509Error GetError () + { + IntPtr error_string_ptr; + return mono_btls_x509_store_ctx_get_error (Handle.DangerousGetHandle (), out error_string_ptr); + } + + public MonoBtlsX509Exception GetException () + { + IntPtr error_string_ptr; + var error = mono_btls_x509_store_ctx_get_error (Handle.DangerousGetHandle (), out error_string_ptr); + if (error == 0) + return null; + if (error_string_ptr != IntPtr.Zero) { + var error_string = Marshal.PtrToStringAnsi (error_string_ptr); + return new MonoBtlsX509Exception (error, error_string); + } + return new MonoBtlsX509Exception (error, "Unknown verify error."); + } + + public MonoBtlsX509Chain GetChain () + { + var chain = mono_btls_x509_store_ctx_get_chain (Handle.DangerousGetHandle ()); + CheckError (chain != IntPtr.Zero); + return new MonoBtlsX509Chain (new MonoBtlsX509Chain.BoringX509ChainHandle (chain)); + } + + public MonoBtlsX509Chain GetUntrusted () + { + var chain = mono_btls_x509_store_ctx_get_untrusted (Handle.DangerousGetHandle ()); + CheckError (chain != IntPtr.Zero); + return new MonoBtlsX509Chain (new MonoBtlsX509Chain.BoringX509ChainHandle (chain)); + } + + public void Initialize (MonoBtlsX509Store store, MonoBtlsX509Chain chain) + { + var ret = mono_btls_x509_store_ctx_init ( + Handle.DangerousGetHandle (), + store.Handle.DangerousGetHandle (), + chain.Handle.DangerousGetHandle ()); + CheckError (ret); + } + + public void SetVerifyParam (MonoBtlsX509VerifyParam param) + { + var ret = mono_btls_x509_store_ctx_set_param ( + Handle.DangerousGetHandle (), + param.Handle.DangerousGetHandle ()); + CheckError (ret); + } + + public int VerifyResult { + get { + if (verifyResult == null) + throw new InvalidOperationException (); + return verifyResult.Value; + } + } + + public int Verify () + { + verifyResult = mono_btls_x509_store_ctx_verify_cert (Handle.DangerousGetHandle ()); + return verifyResult.Value; + } + + public MonoBtlsX509 LookupBySubject (MonoBtlsX509Name name) + { + var handle = mono_btls_x509_store_ctx_get_by_subject ( + Handle.DangerousGetHandle (), name.Handle.DangerousGetHandle ()); + if (handle == IntPtr.Zero) + return null; + return new MonoBtlsX509 (new MonoBtlsX509.BoringX509Handle (handle)); + } + + public MonoBtlsX509 GetCurrentCertificate () + { + var x509 = mono_btls_x509_store_ctx_get_current_cert (Handle.DangerousGetHandle ()); + if (x509 == IntPtr.Zero) + return null; + return new MonoBtlsX509 (new MonoBtlsX509.BoringX509Handle (x509)); + } + + public MonoBtlsX509 GetCurrentIssuer () + { + var x509 = mono_btls_x509_store_ctx_get_current_issuer (Handle.DangerousGetHandle ()); + if (x509 == IntPtr.Zero) + return null; + return new MonoBtlsX509 (new MonoBtlsX509.BoringX509Handle (x509)); + } + + public MonoBtlsX509VerifyParam GetVerifyParam () + { + var param = mono_btls_x509_store_ctx_get_verify_param (Handle.DangerousGetHandle ()); + if (param == IntPtr.Zero) + return null; + return new MonoBtlsX509VerifyParam (new MonoBtlsX509VerifyParam.BoringX509VerifyParamHandle (param)); + } + + public MonoBtlsX509StoreCtx Copy () + { + var copy = mono_btls_x509_store_ctx_up_ref (Handle.DangerousGetHandle ()); + CheckError (copy != IntPtr.Zero); + return new MonoBtlsX509StoreCtx (new BoringX509StoreCtxHandle (copy), verifyResult); + } + } +} +#endif diff --git a/mcs/class/System/Mono.Btls/MonoBtlsX509StoreManager.cs b/mcs/class/System/Mono.Btls/MonoBtlsX509StoreManager.cs new file mode 100644 index 0000000000..9b67262aff --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsX509StoreManager.cs @@ -0,0 +1,120 @@ +// +// MonoBtlsX509StoreManager.cs +// +// Author: +// Martin Baulig +// +// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +#if SECURITY_DEP && MONO_FEATURE_BTLS +#if MONO_SECURITY_ALIAS +extern alias MonoSecurity; +#endif + +using System; +using System.IO; +using System.Security.Cryptography.X509Certificates; + +#if MONO_SECURITY_ALIAS +using MonoSecurity::Mono.Security.Interface; +using MX = MonoSecurity::Mono.Security.X509; +#else +using Mono.Security.Interface; +using MX = Mono.Security.X509; +#endif + +namespace Mono.Btls +{ + static class MonoBtlsX509StoreManager + { + static bool initialized; + static string machineTrustedRootPath; + static string machineIntermediateCAPath; + static string machineUntrustedPath; + static string userTrustedRootPath; + static string userIntermediateCAPath; + static string userUntrustedPath; + + static void Initialize () + { + if (initialized) + return; + + try { + DoInitialize (); + } catch (Exception ex) { + Console.Error.WriteLine ("MonoBtlsX509StoreManager.Initialize() threw exception: {0}", ex); + } finally { + initialized = true; + } + } + + static void DoInitialize () + { +#if !ANDROID + var userPath = MX.X509StoreManager.NewCurrentUserPath; + userTrustedRootPath = Path.Combine (userPath, MX.X509Stores.Names.TrustedRoot); + userIntermediateCAPath = Path.Combine (userPath, MX.X509Stores.Names.IntermediateCA); + userUntrustedPath = Path.Combine (userPath, MX.X509Stores.Names.Untrusted); + + var machinePath = MX.X509StoreManager.NewLocalMachinePath; + machineTrustedRootPath = Path.Combine (userPath, MX.X509Stores.Names.TrustedRoot); + machineIntermediateCAPath = Path.Combine (userPath, MX.X509Stores.Names.IntermediateCA); + machineUntrustedPath = Path.Combine (userPath, MX.X509Stores.Names.Untrusted); +#endif + } + + public static bool HasStore (MonoBtlsX509StoreType type) + { +#if ANDROID + return false; +#else + var path = GetStorePath (type); + return path != null && Directory.Exists (path); +#endif + } + + public static string GetStorePath (MonoBtlsX509StoreType type) + { +#if ANDROID + throw new NotSupportedException (); +#else + Initialize (); + switch (type) { + case MonoBtlsX509StoreType.MachineTrustedRoots: + return machineTrustedRootPath; + case MonoBtlsX509StoreType.MachineIntermediateCA: + return machineIntermediateCAPath; + case MonoBtlsX509StoreType.MachineUntrusted: + return machineUntrustedPath; + case MonoBtlsX509StoreType.UserTrustedRoots: + return userTrustedRootPath; + case MonoBtlsX509StoreType.UserIntermediateCA: + return userIntermediateCAPath; + case MonoBtlsX509StoreType.UserUntrusted: + return userUntrustedPath; + default: + throw new NotSupportedException (); + } +#endif + } + } +} +#endif diff --git a/mcs/class/System/Mono.Btls/MonoBtlsX509StoreType.cs b/mcs/class/System/Mono.Btls/MonoBtlsX509StoreType.cs new file mode 100644 index 0000000000..b4ac593005 --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsX509StoreType.cs @@ -0,0 +1,40 @@ +// +// MonoBtlsX509StoreType.cs +// +// Author: +// Martin Baulig +// +// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +#if SECURITY_DEP && MONO_FEATURE_BTLS +namespace Mono.Btls +{ + enum MonoBtlsX509StoreType + { + Custom, + MachineTrustedRoots, + MachineIntermediateCA, + MachineUntrusted, + UserTrustedRoots, + UserIntermediateCA, + UserUntrusted + } +} +#endif diff --git a/mcs/class/System/Mono.Btls/MonoBtlsX509TrustKind.cs b/mcs/class/System/Mono.Btls/MonoBtlsX509TrustKind.cs new file mode 100644 index 0000000000..4d85588704 --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsX509TrustKind.cs @@ -0,0 +1,42 @@ +// +// MonoBtlsX509TrustKind.cs +// +// Author: +// Martin Baulig +// +// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +#if SECURITY_DEP && MONO_FEATURE_BTLS +using System; +namespace Mono.Btls +{ + [Flags] + enum MonoBtlsX509TrustKind + { + DEFAULT = 0, + TRUST_CLIENT = 1, + TRUST_SERVER = 2, + TRUST_ALL = 4, + REJECT_CLIENT = 32, + REJECT_SERVER = 64, + REJECT_ALL = 128 + } +} +#endif diff --git a/mcs/class/System/Mono.Btls/MonoBtlsX509VerifyFlags.cs b/mcs/class/System/Mono.Btls/MonoBtlsX509VerifyFlags.cs new file mode 100644 index 0000000000..493fc9b1c3 --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsX509VerifyFlags.cs @@ -0,0 +1,39 @@ +// +// MonoBtlsX509VerifyFlags.cs +// +// Author: +// Martin Baulig +// +// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +#if SECURITY_DEP && MONO_FEATURE_BTLS +using System; +namespace Mono.Btls +{ + [Flags] + enum MonoBtlsX509VerifyFlags + { + DEFAULT = 0, + CRL_CHECK = 1, + CRL_CHECK_ALL = 2, + X509_STRIC = 4 + } +} +#endif diff --git a/mcs/class/System/Mono.Btls/MonoBtlsX509VerifyParam.cs b/mcs/class/System/Mono.Btls/MonoBtlsX509VerifyParam.cs new file mode 100644 index 0000000000..9029722a50 --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsX509VerifyParam.cs @@ -0,0 +1,277 @@ +// +// MonoBtlsX509VerifyParam.cs +// +// Author: +// Martin Baulig +// +// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +#if SECURITY_DEP && MONO_FEATURE_BTLS +using System; +using System.IO; +using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; + +namespace Mono.Btls +{ + class MonoBtlsX509VerifyParam : MonoBtlsObject + { + internal class BoringX509VerifyParamHandle : MonoBtlsHandle + { + public BoringX509VerifyParamHandle (IntPtr handle) + : base (handle, true) + { + } + + protected override bool ReleaseHandle () + { + mono_btls_x509_verify_param_free (handle); + return true; + } + } + + new internal BoringX509VerifyParamHandle Handle { + get { return (BoringX509VerifyParamHandle)base.Handle; } + } + + [DllImport (BTLS_DYLIB)] + extern static IntPtr mono_btls_x509_verify_param_new (); + + [DllImport (BTLS_DYLIB)] + extern static IntPtr mono_btls_x509_verify_param_copy (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static IntPtr mono_btls_x509_verify_param_lookup (IntPtr name); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_x509_verify_param_can_modify (IntPtr param); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_x509_verify_param_set_name (IntPtr handle, IntPtr name); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_x509_verify_param_set_host (IntPtr handle, IntPtr name, int namelen); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_x509_verify_param_add_host (IntPtr handle, IntPtr name, int namelen); + + [DllImport (BTLS_DYLIB)] + extern static ulong mono_btls_x509_verify_param_get_flags (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_x509_verify_param_set_flags (IntPtr handle, ulong flags); + + [DllImport (BTLS_DYLIB)] + extern static MonoBtlsX509VerifyFlags mono_btls_x509_verify_param_get_mono_flags (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_x509_verify_param_set_mono_flags (IntPtr handle, MonoBtlsX509VerifyFlags flags); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_x509_verify_param_set_purpose (IntPtr handle, MonoBtlsX509Purpose purpose); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_x509_verify_param_get_depth (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_x509_verify_param_set_depth (IntPtr handle, int depth); + + [DllImport (BTLS_DYLIB)] + extern static int mono_btls_x509_verify_param_set_time (IntPtr handle, long time); + + [DllImport (BTLS_DYLIB)] + extern static IntPtr mono_btls_x509_verify_param_get_peername (IntPtr handle); + + [DllImport (BTLS_DYLIB)] + extern static void mono_btls_x509_verify_param_free (IntPtr handle); + + internal MonoBtlsX509VerifyParam () + : base (new BoringX509VerifyParamHandle (mono_btls_x509_verify_param_new ())) + { + } + + internal MonoBtlsX509VerifyParam (BoringX509VerifyParamHandle handle) + : base (handle) + { + } + + public MonoBtlsX509VerifyParam Copy () + { + var copy = mono_btls_x509_verify_param_copy (Handle.DangerousGetHandle ()); + CheckError (copy != IntPtr.Zero); + return new MonoBtlsX509VerifyParam (new BoringX509VerifyParamHandle (copy)); + } + + public static MonoBtlsX509VerifyParam GetSslClient () + { + return Lookup ("ssl_client", true); + } + + public static MonoBtlsX509VerifyParam GetSslServer () + { + return Lookup ("ssl_server", true); + } + + public static MonoBtlsX509VerifyParam Lookup (string name, bool fail = false) + { + IntPtr namePtr = IntPtr.Zero; + IntPtr handle = IntPtr.Zero; + + try { + namePtr = Marshal.StringToHGlobalAnsi (name); + handle = mono_btls_x509_verify_param_lookup (namePtr); + if (handle == IntPtr.Zero) { + if (!fail) + return null; + throw new MonoBtlsException ("X509_VERIFY_PARAM_lookup() could not find '{0}'.", name); + } + + return new MonoBtlsX509VerifyParam (new BoringX509VerifyParamHandle (handle)); + } finally { + if (namePtr != IntPtr.Zero) + Marshal.FreeHGlobal (namePtr); + } + } + + public bool CanModify { + get { + return mono_btls_x509_verify_param_can_modify (Handle.DangerousGetHandle ()) != 0; + } + } + + void WantToModify () + { + if (!CanModify) + throw new MonoBtlsException ("Attempting to modify read-only MonoBtlsX509VerifyParam instance."); + } + + public void SetName (string name) + { + WantToModify (); + IntPtr namePtr = IntPtr.Zero; + try { + namePtr = Marshal.StringToHGlobalAnsi (name); + var ret = mono_btls_x509_verify_param_set_name ( + Handle.DangerousGetHandle (), namePtr); + CheckError (ret); + } finally { + if (namePtr != IntPtr.Zero) + Marshal.FreeHGlobal (namePtr); + } + } + + public void SetHost (string name) + { + WantToModify (); + IntPtr namePtr = IntPtr.Zero; + try { + namePtr = Marshal.StringToHGlobalAnsi (name); + var ret = mono_btls_x509_verify_param_set_host ( + Handle.DangerousGetHandle (), namePtr, name.Length); + CheckError (ret); + } finally { + if (namePtr != IntPtr.Zero) + Marshal.FreeHGlobal (namePtr); + } + } + + public void AddHost (string name) + { + WantToModify (); + IntPtr namePtr = IntPtr.Zero; + try { + namePtr = Marshal.StringToHGlobalAnsi (name); + var ret = mono_btls_x509_verify_param_add_host ( + Handle.DangerousGetHandle (), namePtr, name.Length); + CheckError (ret); + } finally { + if (namePtr != IntPtr.Zero) + Marshal.FreeHGlobal (namePtr); + } + } + + public ulong GetFlags () + { + return mono_btls_x509_verify_param_get_flags (Handle.DangerousGetHandle ()); + } + + public void SetFlags (ulong flags) + { + WantToModify (); + var ret = mono_btls_x509_verify_param_set_flags ( + Handle.DangerousGetHandle (), flags); + CheckError (ret); + } + + public MonoBtlsX509VerifyFlags GetMonoFlags () + { + return mono_btls_x509_verify_param_get_mono_flags ( + Handle.DangerousGetHandle ()); + } + + public void SetMonoFlags (MonoBtlsX509VerifyFlags flags) + { + WantToModify (); + var ret = mono_btls_x509_verify_param_set_mono_flags ( + Handle.DangerousGetHandle (), flags); + CheckError (ret); + } + + public void SetPurpose (MonoBtlsX509Purpose purpose) + { + WantToModify (); + var ret = mono_btls_x509_verify_param_set_purpose ( + Handle.DangerousGetHandle (), purpose); + CheckError (ret); + } + + public int GetDepth () + { + return mono_btls_x509_verify_param_get_depth (Handle.DangerousGetHandle ()); + } + + public void SetDepth (int depth) + { + WantToModify (); + var ret = mono_btls_x509_verify_param_set_depth ( + Handle.DangerousGetHandle (), depth); + CheckError (ret); + } + + public void SetTime (DateTime time) + { + WantToModify (); + var epoch = new DateTime (1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); + var ticks = (long)time.Subtract (epoch).TotalSeconds; + var ret = mono_btls_x509_verify_param_set_time ( + Handle.DangerousGetHandle (), ticks); + CheckError (ret); + } + + public string GetPeerName () + { + var peer = mono_btls_x509_verify_param_get_peername (Handle.DangerousGetHandle ()); + if (peer == IntPtr.Zero) + return null; + return Marshal.PtrToStringAnsi (peer); + } + } +} +#endif diff --git a/mcs/class/System/Mono.Btls/X509CertificateImplBtls.cs b/mcs/class/System/Mono.Btls/X509CertificateImplBtls.cs new file mode 100644 index 0000000000..f780812ce4 --- /dev/null +++ b/mcs/class/System/Mono.Btls/X509CertificateImplBtls.cs @@ -0,0 +1,495 @@ +// +// X509CertificateImplBtls.cs +// +// Author: +// Martin Baulig +// +// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +#if SECURITY_DEP && MONO_FEATURE_BTLS +#if MONO_SECURITY_ALIAS +extern alias MonoSecurity; +#endif + +#if MONO_SECURITY_ALIAS +using MX = MonoSecurity::Mono.Security.X509; +#else +using MX = Mono.Security.X509; +#endif + +using System; +using System.Text; +using System.Collections; +using System.Security; +using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; +using Mono.Security.Cryptography; + +namespace Mono.Btls +{ + class X509CertificateImplBtls : X509Certificate2Impl + { + MonoBtlsX509 x509; + MonoBtlsKey privateKey; + X500DistinguishedName subjectName; + X500DistinguishedName issuerName; + X509CertificateImplCollection intermediateCerts; + PublicKey publicKey; + bool archived; + bool disallowFallback; + + internal X509CertificateImplBtls (bool disallowFallback = false) + { + this.disallowFallback = disallowFallback; + } + + internal X509CertificateImplBtls (MonoBtlsX509 x509, bool disallowFallback = false) + { + this.disallowFallback = disallowFallback; + this.x509 = x509.Copy (); + } + + X509CertificateImplBtls (X509CertificateImplBtls other) + { + disallowFallback = other.disallowFallback; + x509 = other.x509 != null ? other.x509.Copy () : null; + privateKey = other.privateKey != null ? other.privateKey.Copy () : null; + if (other.intermediateCerts != null) + intermediateCerts = other.intermediateCerts.Clone (); + } + + internal X509CertificateImplBtls (byte[] data, MonoBtlsX509Format format, bool disallowFallback = false) + { + this.disallowFallback = disallowFallback; + x509 = MonoBtlsX509.LoadFromData (data, format); + } + + public override bool IsValid { + get { return x509 != null && x509.IsValid; } + } + + public override IntPtr Handle { + get { return x509.Handle.DangerousGetHandle (); } + } + + public override IntPtr GetNativeAppleCertificate () + { + return IntPtr.Zero; + } + + internal MonoBtlsX509 X509 { + get { + ThrowIfContextInvalid (); + return x509; + } + } + + internal MonoBtlsKey NativePrivateKey { + get { + ThrowIfContextInvalid (); + return privateKey; + } + } + + public override X509CertificateImpl Clone () + { + ThrowIfContextInvalid (); + return new X509CertificateImplBtls (this); + } + + public override bool Equals (X509CertificateImpl other, out bool result) + { + var otherBoringImpl = other as X509CertificateImplBtls; + if (otherBoringImpl == null) { + result = false; + return false; + } + + result = MonoBtlsX509.Compare (X509, otherBoringImpl.X509) == 0; + return true; + } + + protected override byte[] GetCertHash (bool lazy) + { + return X509.GetCertHash (); + } + + public override byte[] GetRawCertData () + { + return X509.GetRawData (MonoBtlsX509Format.DER); + } + + public override string GetSubjectName (bool legacyV1Mode) + { + if (legacyV1Mode) + return SubjectName.Decode (X500DistinguishedNameFlags.None); + return SubjectName.Name; + } + + public override string GetIssuerName (bool legacyV1Mode) + { + if (legacyV1Mode) + return IssuerName.Decode (X500DistinguishedNameFlags.None); + return IssuerName.Name; + } + + public override DateTime GetValidFrom () + { + return X509.GetNotBefore ().ToLocalTime (); + } + + public override DateTime GetValidUntil () + { + return X509.GetNotAfter ().ToLocalTime (); + } + + public override byte[] GetPublicKey () + { + return X509.GetPublicKeyData (); + } + + public override byte[] GetSerialNumber () + { + return X509.GetSerialNumber (true); + } + + public override string GetKeyAlgorithm () + { + return PublicKey.Oid.Value; + } + + public override byte[] GetKeyAlgorithmParameters () + { + return PublicKey.EncodedParameters.RawData; + } + + public override byte[] Export (X509ContentType contentType, byte[] password) + { + ThrowIfContextInvalid (); + + switch (contentType) { + case X509ContentType.Cert: + return GetRawCertData (); + case X509ContentType.Pfx: // this includes Pkcs12 + // TODO + throw new NotSupportedException (); + case X509ContentType.SerializedCert: + // TODO + throw new NotSupportedException (); + default: + string msg = Locale.GetText ("This certificate format '{0}' cannot be exported.", contentType); + throw new CryptographicException (msg); + } + } + + internal override X509CertificateImplCollection IntermediateCertificates { + get { return intermediateCerts; } + } + + public override string ToString (bool full) + { + ThrowIfContextInvalid (); + + if (!full) { + var summary = GetSubjectName (false); + return string.Format ("[X509Certificate: {0}]", summary); + } + + string nl = Environment.NewLine; + StringBuilder sb = new StringBuilder (); + sb.AppendFormat ("[Subject]{0} {1}{0}{0}", nl, GetSubjectName (false)); + + sb.AppendFormat ("[Issuer]{0} {1}{0}{0}", nl, GetIssuerName (false)); + sb.AppendFormat ("[Not Before]{0} {1}{0}{0}", nl, GetValidFrom ().ToLocalTime ()); + sb.AppendFormat ("[Not After]{0} {1}{0}{0}", nl, GetValidUntil ().ToLocalTime ()); + sb.AppendFormat ("[Thumbprint]{0} {1}{0}", nl, X509Helper.ToHexString (GetCertHash ())); + + sb.Append (nl); + return sb.ToString (); + } + + protected override void Dispose (bool disposing) + { + if (x509 != null) { + x509.Dispose (); + x509 = null; + } + } + +#region X509Certificate2Impl + + X509Certificate2Impl fallback; + + void MustFallback () + { + if (disallowFallback) + throw new InvalidOperationException (); + if (fallback != null) + return; + fallback = X509Helper2.Import (GetRawCertData (), null, X509KeyStorageFlags.DefaultKeySet, true); + } + + internal override X509Certificate2Impl FallbackImpl { + get { + MustFallback (); + return fallback; + } + } + + [MonoTODO] + public override bool Archived { + get { + ThrowIfContextInvalid (); + return archived; + } + set { + ThrowIfContextInvalid (); + archived = value; + } + } + + public override X509ExtensionCollection Extensions { + get { return FallbackImpl.Extensions; } + } + + public override bool HasPrivateKey { + get { return privateKey != null; } + } + + public override X500DistinguishedName IssuerName { + get { + ThrowIfContextInvalid (); + if (issuerName == null) { + using (var xname = x509.GetIssuerName ()) { + var encoding = xname.GetRawData (false); + var canonEncoding = xname.GetRawData (true); + var name = MonoBtlsUtils.FormatName (xname, true, ", ", true); + issuerName = new X500DistinguishedName (encoding, canonEncoding, name); + } + } + return issuerName; + } + } + + public override AsymmetricAlgorithm PrivateKey { + get { + if (privateKey == null || !privateKey.IsRsa) + return null; + var bytes = privateKey.GetBytes (true); + return PKCS8.PrivateKeyInfo.DecodeRSA (bytes); + } + set { FallbackImpl.PrivateKey = value; } + } + + public override PublicKey PublicKey { + get { + ThrowIfContextInvalid (); + if (publicKey == null) { + var keyAsn = X509.GetPublicKeyAsn1 (); + var keyParamAsn = X509.GetPublicKeyParameters (); + publicKey = new PublicKey (keyAsn.Oid, keyParamAsn, keyAsn); + } + return publicKey; + } + } + + public override Oid SignatureAlgorithm { + get { + ThrowIfContextInvalid (); + return X509.GetSignatureAlgorithm (); + } + } + + public override X500DistinguishedName SubjectName { + get { + ThrowIfContextInvalid (); + if (subjectName == null) { + using (var xname = x509.GetSubjectName ()) { + var encoding = xname.GetRawData (false); + var canonEncoding = xname.GetRawData (true); + var name = MonoBtlsUtils.FormatName (xname, true, ", ", true); + subjectName = new X500DistinguishedName (encoding, canonEncoding, name); + } + } + return subjectName; + } + } + + public override int Version { + get { return X509.GetVersion (); } + } + + public override string GetNameInfo (X509NameType nameType, bool forIssuer) + { + return FallbackImpl.GetNameInfo (nameType, forIssuer); + } + + public override void Import (byte[] data, string password, X509KeyStorageFlags keyStorageFlags) + { + if (password == null) { + try { + Import (data); + } catch (Exception e) { + try { + ImportPkcs12 (data, null); + } catch { + string msg = Locale.GetText ("Unable to decode certificate."); + // inner exception is the original (not second) exception + throw new CryptographicException (msg, e); + } + } + } else { + // try PKCS#12 + try { + ImportPkcs12 (data, password); + } catch (Exception e) { + try { + // it's possible to supply a (unrequired/unusued) password + // fix bug #79028 + Import (data); + } catch { + string msg = Locale.GetText ("Unable to decode certificate."); + // inner exception is the original (not second) exception + throw new CryptographicException (msg, e); + } + } + } + } + + void Import (byte[] data) + { + // Does it look like PEM? + if ((data.Length > 0) && (data [0] != 0x30)) + x509 = MonoBtlsX509.LoadFromData (data, MonoBtlsX509Format.PEM); + else + x509 = MonoBtlsX509.LoadFromData (data, MonoBtlsX509Format.DER); + } + + void ImportPkcs12 (byte[] data, string password) + { + using (var pkcs12 = new MonoBtlsPkcs12 ()) { + if (string.IsNullOrEmpty (password)) { + try { + // Support both unencrypted PKCS#12.. + pkcs12.Import (data, null); + } catch { + // ..and PKCS#12 encrypted with an empty password + pkcs12.Import (data, string.Empty); + } + } else { + pkcs12.Import (data, password); + } + + x509 = pkcs12.GetCertificate (0); + if (pkcs12.HasPrivateKey) + privateKey = pkcs12.GetPrivateKey (); + if (pkcs12.Count > 1) { + intermediateCerts = new X509CertificateImplCollection (); + for (int i = 0; i < pkcs12.Count; i++) { + using (var ic = pkcs12.GetCertificate (i)) { + if (MonoBtlsX509.Compare (ic, x509) == 0) + continue; + var impl = new X509CertificateImplBtls (ic, true); + intermediateCerts.Add (impl, true); + } + } + } + } + } + + public override byte[] Export (X509ContentType contentType, string password) + { + ThrowIfContextInvalid (); + + switch (contentType) { + case X509ContentType.Cert: + return GetRawCertData (); + case X509ContentType.Pfx: // this includes Pkcs12 + return ExportPkcs12 (password); + case X509ContentType.SerializedCert: + // TODO + throw new NotSupportedException (); + default: + string msg = Locale.GetText ("This certificate format '{0}' cannot be exported.", contentType); + throw new CryptographicException (msg); + } + } + + byte[] ExportPkcs12 (string password) + { + var pfx = new MX.PKCS12 (); + try { + var attrs = new Hashtable (); + var localKeyId = new ArrayList (); + localKeyId.Add (new byte[] { 1, 0, 0, 0 }); + attrs.Add (MX.PKCS9.localKeyId, localKeyId); + if (password != null) + pfx.Password = password; + pfx.AddCertificate (new MX.X509Certificate (GetRawCertData ()), attrs); + if (IntermediateCertificates != null) { + for (int i = 0; i < IntermediateCertificates.Count; i++) + pfx.AddCertificate (new MX.X509Certificate (IntermediateCertificates [i].GetRawCertData ())); + } + var privateKey = PrivateKey; + if (privateKey != null) + pfx.AddPkcs8ShroudedKeyBag (privateKey, attrs); + return pfx.GetBytes (); + } finally { + pfx.Password = null; + } + } + + public override bool Verify (X509Certificate2 thisCertificate) + { + using (var chain = new MonoBtlsX509Chain ()) { + chain.AddCertificate (x509.Copy ()); + if (intermediateCerts != null) { + for (int i = 0; i < intermediateCerts.Count; i++) { + var intermediate = (X509CertificateImplBtls)intermediateCerts [i]; + chain.AddCertificate (intermediate.x509.Copy ()); + } + } + return MonoBtlsProvider.ValidateCertificate (chain, null); + } + } + + public override void Reset () + { + if (x509 != null) { + x509.Dispose (); + x509 = null; + } + if (privateKey != null) { + privateKey = null; + privateKey = null; + } + subjectName = null; + issuerName = null; + archived = false; + publicKey = null; + intermediateCerts = null; + if (fallback != null) + fallback.Reset (); + } + +#endregion + } +} +#endif diff --git a/mcs/class/System/Mono.Btls/X509ChainImplBtls.cs b/mcs/class/System/Mono.Btls/X509ChainImplBtls.cs new file mode 100644 index 0000000000..13596686e8 --- /dev/null +++ b/mcs/class/System/Mono.Btls/X509ChainImplBtls.cs @@ -0,0 +1,178 @@ +// +// X509ChainImplBtls.cs +// +// Author: +// Martin Baulig +// +// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +#if SECURITY_DEP && MONO_FEATURE_BTLS +using System; +using System.Text; +using System.Security; +using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; +using MX = Mono.Security.X509; + +namespace Mono.Btls +{ + class X509ChainImplBtls : X509ChainImpl + { + MonoBtlsX509StoreCtx storeCtx; + MonoBtlsX509Chain chain; + MonoBtlsX509Chain untrustedChain; + X509ChainElementCollection elements; + X509Certificate2Collection untrusted; + X509Certificate2[] certificates; + X509ChainPolicy policy; + + internal X509ChainImplBtls (MonoBtlsX509Chain chain) + { + this.chain = chain.Copy (); + policy = new X509ChainPolicy (); + } + + internal X509ChainImplBtls (MonoBtlsX509StoreCtx storeCtx) + { + this.storeCtx = storeCtx.Copy (); + this.chain = storeCtx.GetChain (); + + policy = new X509ChainPolicy (); + + untrustedChain = storeCtx.GetUntrusted (); + + if (untrustedChain != null) { + untrusted = new X509Certificate2Collection (); + policy.ExtraStore = untrusted; + for (int i = 0; i < untrustedChain.Count; i++) { + var cert = untrustedChain.GetCertificate (i); + using (var impl = new X509CertificateImplBtls (cert)) + untrusted.Add (new X509Certificate2 (impl)); + } + } + } + + internal X509ChainImplBtls () + { + chain = new MonoBtlsX509Chain (); + elements = new X509ChainElementCollection (); + policy = new X509ChainPolicy (); + } + + public override bool IsValid { + get { return chain != null && chain.IsValid; } + } + + public override IntPtr Handle { + get { return chain.Handle.DangerousGetHandle (); } + } + + internal MonoBtlsX509Chain Chain { + get { + ThrowIfContextInvalid (); + return chain; + } + } + + internal MonoBtlsX509StoreCtx StoreCtx { + get { + ThrowIfContextInvalid (); + return storeCtx; + } + } + + public override X509ChainElementCollection ChainElements { + get { + ThrowIfContextInvalid (); + if (elements != null) + return elements; + + elements = new X509ChainElementCollection (); + certificates = new X509Certificate2 [chain.Count]; + + for (int i = 0; i < certificates.Length; i++) { + var cert = chain.GetCertificate (i); + using (var impl = new X509CertificateImplBtls (cert)) + certificates [i] = new X509Certificate2 (impl); + elements.Add (certificates [i]); + } + + return elements; + } + } + + public override X509ChainPolicy ChainPolicy { + get { return policy; } + set { policy = value; } + } + + public override X509ChainStatus[] ChainStatus { + get { throw new NotImplementedException (); } + } + + public override bool Build (X509Certificate2 certificate) + { + return false; + } + + public override void Reset () + { + if (certificates != null) { + foreach (var certificate in certificates) + certificate.Dispose (); + certificates = null; + } + if (elements != null) { + elements.Clear (); + elements = null; + } + } + + protected override void Dispose (bool disposing) + { + if (disposing) { + if (chain != null) { + chain.Dispose (); + chain = null; + } + if (storeCtx != null) { + storeCtx.Dispose (); + storeCtx = null; + } + if (untrustedChain != null) { + untrustedChain.Dispose (); + untrustedChain = null; + } + if (untrusted != null) { + foreach (var cert in untrusted) + cert.Dispose (); + untrusted = null; + } + if (certificates != null) { + foreach (var cert in certificates) + cert.Dispose (); + certificates = null; + } + } + base.Dispose (disposing); + } + } +} +#endif diff --git a/mcs/class/System/Mono.Net.Security/ChainValidationHelper.cs b/mcs/class/System/Mono.Net.Security/ChainValidationHelper.cs index 58d5c3865b..929e88e229 100644 --- a/mcs/class/System/Mono.Net.Security/ChainValidationHelper.cs +++ b/mcs/class/System/Mono.Net.Security/ChainValidationHelper.cs @@ -44,8 +44,6 @@ using Mono.Security.Interface; using MSX = Mono.Security.X509; using Mono.Security.X509.Extensions; #endif -using XX509CertificateCollection = System.Security.Cryptography.X509Certificates.X509CertificateCollection; -using XX509Chain = System.Security.Cryptography.X509Certificates.X509Chain; using System; using System.Net; @@ -77,7 +75,7 @@ namespace Mono.Net.Security readonly MonoTlsStream tlsStream; readonly HttpWebRequest request; - internal static ICertificateValidator GetDefaultValidator (MonoTlsProvider provider, MonoTlsSettings settings) + internal static ICertificateValidator GetInternalValidator (MonoTlsProvider provider, MonoTlsSettings settings) { if (settings == null) return new ChainValidationHelper (provider, null, false, null, null); @@ -86,6 +84,16 @@ namespace Mono.Net.Security return new ChainValidationHelper (provider, settings, false, null, null); } + internal static ICertificateValidator GetDefaultValidator (MonoTlsSettings settings) + { + var provider = MonoTlsProviderFactory.GetProvider (); + if (settings == null) + return new ChainValidationHelper (provider, null, false, null, null); + if (settings.CertificateValidator != null) + throw new NotSupportedException (); + return new ChainValidationHelper (provider, settings, false, null, null); + } + #region SslStream support /* @@ -138,6 +146,8 @@ namespace Mono.Net.Security settings = MonoTlsSettings.CopyDefaultSettings (); if (cloneSettings) settings = settings.CloneWithValidator (this); + if (provider == null) + provider = MonoTlsProviderFactory.GetProvider (); this.provider = provider; this.settings = settings; @@ -172,7 +182,7 @@ namespace Mono.Net.Security certValidationCallback = ServicePointManager.ServerCertValidationCallback; } - static X509Certificate DefaultSelectionCallback (string targetHost, XX509CertificateCollection localCertificates, X509Certificate remoteCertificate, string[] acceptableIssuers) + static X509Certificate DefaultSelectionCallback (string targetHost, X509CertificateCollection localCertificates, X509Certificate remoteCertificate, string[] acceptableIssuers) { X509Certificate clientCertificate; if (localCertificates == null || localCertificates.Count == 0) @@ -195,7 +205,7 @@ namespace Mono.Net.Security } public bool SelectClientCertificate ( - string targetHost, XX509CertificateCollection localCertificates, X509Certificate remoteCertificate, + string targetHost, X509CertificateCollection localCertificates, X509Certificate remoteCertificate, string[] acceptableIssuers, out X509Certificate clientCertificate) { if (certSelectionCallback == null) { @@ -207,7 +217,7 @@ namespace Mono.Net.Security } internal X509Certificate SelectClientCertificate ( - string targetHost, XX509CertificateCollection localCertificates, X509Certificate remoteCertificate, + string targetHost, X509CertificateCollection localCertificates, X509Certificate remoteCertificate, string[] acceptableIssuers) { if (certSelectionCallback == null) @@ -217,7 +227,7 @@ namespace Mono.Net.Security internal bool ValidateClientCertificate (X509Certificate certificate, MonoSslPolicyErrors errors) { - var certs = new XX509CertificateCollection (); + var certs = new X509CertificateCollection (); certs.Add (new X509Certificate2 (certificate.GetRawCertData ())); var result = ValidateChain (string.Empty, true, certificate, null, certs, (SslPolicyErrors)errors); @@ -227,7 +237,7 @@ namespace Mono.Net.Security return result.Trusted && !result.UserDenied; } - public ValidationResult ValidateCertificate (string host, bool serverMode, XX509CertificateCollection certs) + public ValidationResult ValidateCertificate (string host, bool serverMode, X509CertificateCollection certs) { try { X509Certificate leaf; @@ -246,10 +256,9 @@ namespace Mono.Net.Security } } - public ValidationResult ValidateCertificate (string host, bool serverMode, X509Certificate leaf, XX509Chain xchain) + public ValidationResult ValidateCertificate (string host, bool serverMode, X509Certificate leaf, X509Chain chain) { try { - var chain = xchain; var result = ValidateChain (host, serverMode, leaf, chain, null, 0); if (tlsStream != null) tlsStream.CertificateValidationFailed = result == null || !result.Trusted || result.UserDenied; @@ -262,7 +271,7 @@ namespace Mono.Net.Security } ValidationResult ValidateChain (string host, bool server, X509Certificate leaf, - X509Chain chain, XX509CertificateCollection certs, + X509Chain chain, X509CertificateCollection certs, SslPolicyErrors errors) { var oldChain = chain; @@ -281,7 +290,7 @@ namespace Mono.Net.Security } ValidationResult ValidateChain (string host, bool server, X509Certificate leaf, - ref X509Chain chain, XX509CertificateCollection certs, + ref X509Chain chain, X509CertificateCollection certs, SslPolicyErrors errors) { // user_denied is true if the user callback is called and returns false @@ -322,28 +331,19 @@ namespace Mono.Net.Security wantsChain = true; } - bool providerValidated = false; - if (provider != null && provider.HasCustomSystemCertificateValidator) { - var xerrors = (MonoSslPolicyErrors)errors; - var xchain = chain; - providerValidated = provider.InvokeSystemCertificateValidator (this, host, server, certs, wantsChain, ref xchain, out result, ref xerrors, ref status11); - chain = xchain; - errors = (SslPolicyErrors)xerrors; - } else if (wantsChain) { - chain = SystemCertificateValidator.CreateX509Chain (certs); - } + var xerrors = (MonoSslPolicyErrors)errors; + result = provider.ValidateCertificate (this, host, server, certs, wantsChain, ref chain, ref xerrors, ref status11); + errors = (SslPolicyErrors)xerrors; - if (!providerValidated) - result = SystemCertificateValidator.Evaluate (settings, host, certs, chain, ref errors, ref status11); + if (status11 == 0 && errors != 0) { + // TRUST_E_FAIL + status11 = unchecked ((int)0x800B010B); + } if (policy != null && (!(policy is DefaultCertificatePolicy) || certValidationCallback == null)) { ServicePoint sp = null; if (request != null) sp = request.ServicePointNoLock; - if (status11 == 0 && errors != 0) { - // TRUST_E_FAIL - status11 = unchecked ((int)0x800B010B); - } // pre 2.0 callback result = policy.CheckValidationResult (sp, leaf, request, status11); @@ -360,9 +360,8 @@ namespace Mono.Net.Security return new ValidationResult (result, user_denied, status11, (MonoSslPolicyErrors)errors); } - public bool InvokeSystemValidator (string targetHost, bool serverMode, XX509CertificateCollection certificates, XX509Chain xchain, ref MonoSslPolicyErrors xerrors, ref int status11) + bool InvokeSystemValidator (string targetHost, bool serverMode, X509CertificateCollection certificates, X509Chain chain, ref MonoSslPolicyErrors xerrors, ref int status11) { - X509Chain chain = xchain; var errors = (SslPolicyErrors)xerrors; var result = SystemCertificateValidator.Evaluate (settings, targetHost, certificates, chain, ref errors, ref status11); xerrors = (MonoSslPolicyErrors)errors; diff --git a/mcs/class/System/Mono.Net.Security/IMonoTlsProvider.cs b/mcs/class/System/Mono.Net.Security/IMonoTlsProvider.cs index 50b4cd9c8c..942b5065ce 100644 --- a/mcs/class/System/Mono.Net.Security/IMonoTlsProvider.cs +++ b/mcs/class/System/Mono.Net.Security/IMonoTlsProvider.cs @@ -34,7 +34,6 @@ using MonoSecurity::Mono.Security.Interface; #else using Mono.Security.Interface; #endif -using XX509CertificateCollection = System.Security.Cryptography.X509Certificates.X509CertificateCollection; #endif using System; @@ -70,12 +69,6 @@ namespace Mono.Net.Security IMonoSslStream CreateSslStream ( Stream innerStream, bool leaveInnerStreamOpen, MonoTlsSettings settings); - - IMonoTlsContext CreateTlsContext ( - string hostname, bool serverMode, TlsProtocols protocolFlags, - X509Certificate serverCertificate, XX509CertificateCollection clientCertificates, - bool remoteCertRequired, bool checkCertName, bool checkCertRevocationStatus, - MonoEncryptionPolicy encryptionPolicy, MonoTlsSettings settings); #endif } } diff --git a/mcs/class/System/Mono.Net.Security/LegacySslStream.cs b/mcs/class/System/Mono.Net.Security/LegacySslStream.cs index 1a6672f6c5..7ec9a86813 100644 --- a/mcs/class/System/Mono.Net.Security/LegacySslStream.cs +++ b/mcs/class/System/Mono.Net.Security/LegacySslStream.cs @@ -91,7 +91,7 @@ namespace Mono.Net.Security.Private : base (innerStream, leaveInnerStreamOpen) { this.provider = provider; - certificateValidator = ChainValidationHelper.GetDefaultValidator (provider, settings); + certificateValidator = ChainValidationHelper.GetInternalValidator (provider, settings); } #endregion // Constructors diff --git a/mcs/class/System/Mono.Net.Security/MonoLegacyTlsProvider.cs b/mcs/class/System/Mono.Net.Security/LegacyTlsProvider.cs similarity index 63% rename from mcs/class/System/Mono.Net.Security/MonoLegacyTlsProvider.cs rename to mcs/class/System/Mono.Net.Security/LegacyTlsProvider.cs index 9a97195e01..7048f44c7b 100644 --- a/mcs/class/System/Mono.Net.Security/MonoLegacyTlsProvider.cs +++ b/mcs/class/System/Mono.Net.Security/LegacyTlsProvider.cs @@ -1,5 +1,5 @@ // -// MonoLegacyTlsProvider.cs +// LegacyTlsProvider.cs // // Author: // Martin Baulig @@ -28,14 +28,10 @@ extern alias MonoSecurity; #endif -using XHttpWebRequest = System.Net.HttpWebRequest; -using XSslProtocols = System.Security.Authentication.SslProtocols; -using XX509CertificateCollection = System.Security.Cryptography.X509Certificates.X509CertificateCollection; - #if MONO_SECURITY_ALIAS -using MonoSecurity::Mono.Security.Interface; +using MSI = MonoSecurity::Mono.Security.Interface; #else -using Mono.Security.Interface; +using MSI = Mono.Security.Interface; #endif using System; @@ -43,13 +39,14 @@ using System.IO; using System.Net; using System.Net.Security; using System.Security.Cryptography.X509Certificates; +using System.Security.Authentication; -namespace Mono.Net.Security.Private +namespace Mono.Net.Security { /* * Strictly private - do not use outside the Mono.Net.Security directory. */ - class MonoLegacyTlsProvider : MonoTlsProviderImpl + class LegacyTlsProvider : MSI.MonoTlsProvider { static readonly Guid id = new Guid ("809e77d5-56cc-4da8-b9f0-45e65ba9cceb"); @@ -61,10 +58,6 @@ namespace Mono.Net.Security.Private get { return "legacy"; } } - public MonoTlsProvider Provider { - get { return this; } - } - public override bool SupportsSslStream { get { return true; } } @@ -77,28 +70,29 @@ namespace Mono.Net.Security.Private get { return false; } } - internal override bool SupportsTlsContext { - get { return false; } + public override SslProtocols SupportedProtocols { + get { return SslProtocols.Tls; } } - public override XSslProtocols SupportedProtocols { - get { return XSslProtocols.Ssl3 | XSslProtocols.Tls; } - } - - protected override IMonoSslStream CreateSslStreamImpl ( + public override MSI.IMonoSslStream CreateSslStream ( Stream innerStream, bool leaveInnerStreamOpen, - MonoTlsSettings settings) + MSI.MonoTlsSettings settings = null) { - return new LegacySslStream (innerStream, leaveInnerStreamOpen, this, settings); + var impl = new Private.LegacySslStream (innerStream, leaveInnerStreamOpen, this, settings); + return new Private.MonoSslStreamImpl (impl); } - protected override IMonoTlsContext CreateTlsContextImpl ( - string hostname, bool serverMode, TlsProtocols protocolFlags, - X509Certificate serverCertificate, X509CertificateCollection clientCertificates, - bool remoteCertRequired, MonoEncryptionPolicy encryptionPolicy, - MonoTlsSettings settings) + internal override bool ValidateCertificate ( + MSI.ICertificateValidator2 validator, string targetHost, bool serverMode, + X509CertificateCollection certificates, bool wantsChain, ref X509Chain chain, + ref MSI.MonoSslPolicyErrors errors, ref int status11) { - throw new NotSupportedException (); + if (wantsChain) + chain = SystemCertificateValidator.CreateX509Chain (certificates); + var xerrors = (SslPolicyErrors)errors; + var result = SystemCertificateValidator.Evaluate (validator.Settings, targetHost, certificates, chain, ref xerrors, ref status11); + errors = (MSI.MonoSslPolicyErrors)xerrors; + return result; } } } diff --git a/mcs/class/System/Mono.Net.Security/MobileTlsContext.cs b/mcs/class/System/Mono.Net.Security/MobileTlsContext.cs index 677a510769..f051a5fcbc 100644 --- a/mcs/class/System/Mono.Net.Security/MobileTlsContext.cs +++ b/mcs/class/System/Mono.Net.Security/MobileTlsContext.cs @@ -54,7 +54,7 @@ namespace Mono.Net.Security this.clientCertificates = clientCertificates; this.askForClientCert = askForClientCert; - certificateValidator = CertificateValidationHelper.GetDefaultValidator ( + certificateValidator = CertificateValidationHelper.GetInternalValidator ( parent.Settings, parent.Provider); } @@ -159,30 +159,35 @@ namespace Mono.Net.Security public abstract void Close (); - protected ValidationResult ValidateCertificate (X509Certificate leaf, X509Chain chain) + protected bool ValidateCertificate (X509Certificate leaf, X509Chain chain) { - return certificateValidator.ValidateCertificate ( - targetHost, serverMode, leaf, chain); + var result = certificateValidator.ValidateCertificate (TargetHost, IsServer, leaf, chain); + return result != null && result.Trusted && !result.UserDenied; } - protected X509Certificate SelectClientCertificate (string[] acceptableIssuers) - { - X509Certificate certificate; - var selected = certificateValidator.SelectClientCertificate ( - targetHost, clientCertificates, serverCertificate, - null, out certificate); - if (selected) - return certificate; + protected bool ValidateCertificate (X509CertificateCollection certificates) + { + var result = certificateValidator.ValidateCertificate (TargetHost, IsServer, certificates); + return result != null && result.Trusted && !result.UserDenied; + } - if (clientCertificates == null || clientCertificates.Count == 0) - return null; + protected X509Certificate SelectClientCertificate (X509Certificate serverCertificate, string[] acceptableIssuers) + { + X509Certificate certificate; + var selected = certificateValidator.SelectClientCertificate ( + TargetHost, ClientCertificates, serverCertificate, acceptableIssuers, out certificate); + if (selected) + return certificate; - if (clientCertificates.Count == 1) - return clientCertificates [0]; + if (clientCertificates == null || clientCertificates.Count == 0) + return null; - // FIXME: select one. - throw new NotImplementedException (); - } + if (clientCertificates.Count == 1) + return clientCertificates [0]; + + // FIXME: select onne. + throw new NotImplementedException (); + } public void Dispose () { diff --git a/mcs/class/System/Mono.Net.Security/MonoTlsProviderFactory.Droid.cs b/mcs/class/System/Mono.Net.Security/MonoTlsProviderFactory.Droid.cs index 72390bcdd1..f9bd47396e 100644 --- a/mcs/class/System/Mono.Net.Security/MonoTlsProviderFactory.Droid.cs +++ b/mcs/class/System/Mono.Net.Security/MonoTlsProviderFactory.Droid.cs @@ -2,7 +2,7 @@ #if SECURITY_DEP using System; using MSI = Mono.Security.Interface; -#if HAVE_BTLS +#if MONO_FEATURE_BTLS using Mono.Btls; #endif @@ -18,14 +18,12 @@ namespace Mono.Net.Security case null: case "default": case "legacy": - return new Private.MonoLegacyTlsProvider (); + return new LegacyTlsProvider (); +#if MONO_FEATURE_BTLS case "btls": -#if HAVE_BTLS - if (!MonoBtlsProvider.IsSupported ()) + if (!IsBtlsSupported ()) throw new NotSupportedException ("BTLS in not supported!"); return new MonoBtlsProvider (); -#else - throw new NotSupportedException ("BTLS in not supported!"); #endif default: throw new NotSupportedException (string.Format ("Invalid TLS Provider: `{0}'.", provider)); diff --git a/mcs/class/System/Mono.Net.Security/MonoTlsProviderFactory.cs b/mcs/class/System/Mono.Net.Security/MonoTlsProviderFactory.cs index e53b6eba4c..071535a5c4 100644 --- a/mcs/class/System/Mono.Net.Security/MonoTlsProviderFactory.cs +++ b/mcs/class/System/Mono.Net.Security/MonoTlsProviderFactory.cs @@ -39,6 +39,7 @@ using System.Security.Cryptography.X509Certificates; using System; using System.Net; using System.Collections.Generic; +using System.Runtime.CompilerServices; #if !MOBILE using System.Reflection; @@ -64,74 +65,61 @@ namespace Mono.Net.Security internal static IMonoTlsProvider GetProviderInternal () { + #if SECURITY_DEP lock (locker) { - if (currentProvider != null) - return currentProvider; - - try { - defaultProvider = GetDefaultProviderInternal (); - } catch (Exception ex) { - throw new NotSupportedException ("TLS Support not available.", ex); - } - - if (defaultProvider == null) - throw new NotSupportedException ("TLS Support not available."); - - currentProvider = defaultProvider; - return currentProvider; - } - } - - internal static IMonoTlsProvider GetDefaultProviderInternal () - { - lock (locker) { - if (defaultProvider != null) - return defaultProvider; - - try { - defaultProvider = CreateDefaultProvider (); - } catch (Exception ex) { - throw new NotSupportedException ("TLS Support not available.", ex); - } - - if (defaultProvider == null) - throw new NotSupportedException ("TLS Support not available."); - + InitializeInternal (); return defaultProvider; } + #else + throw new NotSupportedException ("TLS Support not available."); + #endif } - static IMonoTlsProvider CreateDefaultProvider () - { #if SECURITY_DEP - MSI.MonoTlsProvider provider = null; -#if MONO_FEATURE_NEW_SYSTEM_SOURCE - /* - * This is a hack, which is used in the Mono.Security.Providers.NewSystemSource - * assembly, which will provide a "fake" System.dll. Use the public Mono.Security - * API to get the "real" System.dll's provider via reflection, then wrap it with - * the "fake" version's perceived view. - * - * NewSystemSource needs to compile MonoTlsProviderFactory.cs, IMonoTlsProvider.cs, - * MonoTlsProviderWrapper.cs and CallbackHelpers.cs from this directory and only these. - */ - provider = MSI.MonoTlsProviderFactory.GetProvider (); -#else - provider = CreateDefaultProviderImpl (); -#endif - if (provider != null) - return new Private.MonoTlsProviderWrapper (provider); -#endif - return null; + internal static void InitializeInternal () + { + lock (locker) { + if (initialized) + return; + + MSI.MonoTlsProvider provider; + try { + provider = CreateDefaultProviderImpl (); + } catch (Exception ex) { + throw new NotSupportedException ("TLS Support not available.", ex); + } + + if (provider == null) + throw new NotSupportedException ("TLS Support not available."); + + defaultProvider = new Private.MonoTlsProviderWrapper (provider); + initialized = true; + } } + internal static void InitializeInternal (string provider) + { + lock (locker) { + if (initialized) + throw new NotSupportedException ("TLS Subsystem already initialized."); + + var msiProvider = LookupProvider (provider, true); + defaultProvider = new Private.MonoTlsProviderWrapper (msiProvider); + initialized = true; + } + } + + [MethodImpl (MethodImplOptions.InternalCall)] + internal extern static bool IsBtlsSupported (); +#endif + static object locker = new object (); + static bool initialized; static IMonoTlsProvider defaultProvider; - static IMonoTlsProvider currentProvider; #endregion -#if SECURITY_DEP && !MONO_FEATURE_NEW_SYSTEM_SOURCE +#if SECURITY_DEP static Dictionary providerRegistration; @@ -171,13 +159,10 @@ namespace Mono.Net.Security if (providerRegistration != null) return; providerRegistration = new Dictionary (); - providerRegistration.Add ("legacy", "Mono.Net.Security.Private.MonoLegacyTlsProvider"); - providerRegistration.Add ("newtls", "Mono.Security.Providers.NewTls.NewTlsProvider, Mono.Security.Providers.NewTls, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756"); - providerRegistration.Add ("oldtls", "Mono.Security.Providers.OldTls.OldTlsProvider, Mono.Security.Providers.OldTls, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756"); -#if HAVE_BTLS - if (Mono.Btls.MonoBtlsProvider.IsSupported ()) + providerRegistration.Add ("legacy", "Mono.Net.Security.LegacyTlsProvider"); + providerRegistration.Add ("default", "Mono.Net.Security.LegacyTlsProvider"); + if (IsBtlsSupported ()) providerRegistration.Add ("btls", "Mono.Btls.MonoBtlsProvider"); -#endif X509Helper2.Initialize (); } } @@ -186,11 +171,8 @@ namespace Mono.Net.Security static MSI.MonoTlsProvider TryDynamicLoad () { var variable = Environment.GetEnvironmentVariable ("MONO_TLS_PROVIDER"); - if (variable == null) - return null; - - if (string.Equals (variable, "default", StringComparison.OrdinalIgnoreCase)) - return null; + if (string.IsNullOrEmpty (variable)) + variable = "default"; return LookupProvider (variable, true); } @@ -201,7 +183,7 @@ namespace Mono.Net.Security if (provider != null) return provider; - return new Private.MonoLegacyTlsProvider (); + return new LegacyTlsProvider (); } #endif @@ -222,13 +204,9 @@ namespace Mono.Net.Security return provider.Provider; } - internal static MSI.MonoTlsProvider GetDefaultProvider () + internal static bool IsProviderSupported (string name) { - var provider = GetDefaultProviderInternal (); - if (provider == null) - throw new NotSupportedException ("No TLS Provider available."); - - return provider.Provider; + return LookupProvider (name, false) != null; } internal static MSI.MonoTlsProvider GetProvider (string name) @@ -236,20 +214,30 @@ namespace Mono.Net.Security return LookupProvider (name, false); } - internal static bool HasProvider { + internal static bool IsInitialized { get { lock (locker) { - return currentProvider != null; + return initialized; } } } - internal static void SetDefaultProvider (string name) + internal static void Initialize () { - lock (locker) { - var provider = LookupProvider (name, true); - currentProvider = new Private.MonoTlsProviderWrapper (provider); - } + #if SECURITY_DEP + InitializeInternal (); + #else + throw new NotSupportedException ("TLS Support not available."); + #endif + } + + internal static void Initialize (string provider) + { + #if SECURITY_DEP + InitializeInternal (provider); + #else + throw new NotSupportedException ("TLS Support not available."); + #endif } internal static HttpWebRequest CreateHttpsRequest (Uri requestUri, MSI.MonoTlsProvider provider, MSI.MonoTlsSettings settings) diff --git a/mcs/class/System/Mono.Net.Security/MonoTlsProviderImpl.cs b/mcs/class/System/Mono.Net.Security/MonoTlsProviderImpl.cs deleted file mode 100644 index 94f86ca7e7..0000000000 --- a/mcs/class/System/Mono.Net.Security/MonoTlsProviderImpl.cs +++ /dev/null @@ -1,108 +0,0 @@ -// -// MonoTlsProviderImpl.cs -// -// Author: -// Martin Baulig -// -// Copyright (c) 2015 Xamarin, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -#if SECURITY_DEP - -#if MONO_SECURITY_ALIAS -extern alias MonoSecurity; -#endif - -#if MONO_SECURITY_ALIAS -using MSI = MonoSecurity::Mono.Security.Interface; -#else -using MSI = Mono.Security.Interface; -#endif - -using System; -using System.IO; -using System.Net; -using System.Net.Security; -using System.Security.Cryptography.X509Certificates; - -namespace Mono.Net.Security.Private -{ - /* - * Strictly private - do not use outside the Mono.Net.Security directory. - */ - abstract class MonoTlsProviderImpl : MSI.MonoTlsProvider, IMonoTlsProvider - { - MSI.MonoTlsProvider IMonoTlsProvider.Provider { - get { return this; } - } - - IMonoSslStream IMonoTlsProvider.CreateSslStream ( - Stream innerStream, bool leaveInnerStreamOpen, - MSI.MonoTlsSettings settings) - { - return CreateSslStreamImpl (innerStream, leaveInnerStreamOpen, settings); - } - - protected abstract IMonoSslStream CreateSslStreamImpl ( - Stream innerStream, bool leaveInnerStreamOpen, - MSI.MonoTlsSettings settings); - - public override MSI.IMonoSslStream CreateSslStream ( - Stream innerStream, bool leaveInnerStreamOpen, - MSI.MonoTlsSettings settings = null) - { - var sslStream = CreateSslStreamImpl (innerStream, leaveInnerStreamOpen, settings); - return new MonoSslStreamImpl (sslStream); - } - - MSI.IMonoTlsContext IMonoTlsProvider.CreateTlsContext ( - string hostname, bool serverMode, MSI.TlsProtocols protocolFlags, - X509Certificate serverCertificate, X509CertificateCollection clientCertificates, - bool remoteCertRequired, bool checkCertName, bool checkCertRevocationStatus, - MSI.MonoEncryptionPolicy encryptionPolicy, MSI.MonoTlsSettings settings) - { - return CreateTlsContextImpl ( - hostname, serverMode, protocolFlags, - serverCertificate, clientCertificates, - remoteCertRequired, encryptionPolicy, settings); - } - - protected abstract MSI.IMonoTlsContext CreateTlsContextImpl ( - string hostname, bool serverMode, MSI.TlsProtocols protocolFlags, - X509Certificate serverCertificate, X509CertificateCollection clientCertificates, - bool remoteCertRequired, MSI.MonoEncryptionPolicy encryptionPolicy, - MSI.MonoTlsSettings settings); - - internal override MSI.IMonoTlsContext CreateTlsContext ( - string hostname, bool serverMode, MSI.TlsProtocols protocolFlags, - X509Certificate serverCertificate, X509CertificateCollection clientCertificates, - bool remoteCertRequired, MSI.MonoEncryptionPolicy encryptionPolicy, - MSI.MonoTlsSettings settings) - { - return CreateTlsContextImpl ( - hostname, serverMode, (MSI.TlsProtocols)protocolFlags, - serverCertificate, clientCertificates, - remoteCertRequired, (MSI.MonoEncryptionPolicy)encryptionPolicy, - settings); - } - } -} - -#endif diff --git a/mcs/class/System/Mono.Net.Security/MonoTlsProviderWrapper.cs b/mcs/class/System/Mono.Net.Security/MonoTlsProviderWrapper.cs index 1528320059..0a81f4ff93 100644 --- a/mcs/class/System/Mono.Net.Security/MonoTlsProviderWrapper.cs +++ b/mcs/class/System/Mono.Net.Security/MonoTlsProviderWrapper.cs @@ -73,19 +73,6 @@ namespace Mono.Net.Security.Private return monoSslStreamImpl.Impl; return new MonoSslStreamWrapper (sslStream); } - - public MSI.IMonoTlsContext CreateTlsContext ( - string hostname, bool serverMode, MSI.TlsProtocols protocolFlags, - X509Certificate serverCertificate, X509CertificateCollection clientCertificates, - bool remoteCertRequired, bool checkCertName, bool checkCertRevocationStatus, - MSI.MonoEncryptionPolicy encryptionPolicy, MSI.MonoTlsSettings settings) - { - return provider.CreateTlsContext ( - hostname, serverMode, protocolFlags, - serverCertificate, clientCertificates, - remoteCertRequired, (MSI.MonoEncryptionPolicy)encryptionPolicy, - settings); - } } } diff --git a/mcs/class/System/Mono.Net.Security/MonoTlsStream.cs b/mcs/class/System/Mono.Net.Security/MonoTlsStream.cs index 79e4fbf684..4e76cad89f 100644 --- a/mcs/class/System/Mono.Net.Security/MonoTlsStream.cs +++ b/mcs/class/System/Mono.Net.Security/MonoTlsStream.cs @@ -34,7 +34,6 @@ using MonoSecurity::Mono.Security.Interface; #else using Mono.Security.Interface; #endif -using XX509CertificateCollection = System.Security.Cryptography.X509Certificates.X509CertificateCollection; #endif using System; diff --git a/mcs/class/System/Mono.Net.Security/NoReflectionHelper.cs b/mcs/class/System/Mono.Net.Security/NoReflectionHelper.cs index 6de1cd2599..2787775d30 100644 --- a/mcs/class/System/Mono.Net.Security/NoReflectionHelper.cs +++ b/mcs/class/System/Mono.Net.Security/NoReflectionHelper.cs @@ -47,10 +47,19 @@ namespace Mono.Net.Security // internal static class NoReflectionHelper { - internal static object GetDefaultCertificateValidator (object provider, object settings) + internal static object GetInternalValidator (object provider, object settings) { #if SECURITY_DEP - return ChainValidationHelper.GetDefaultValidator ((MSI.MonoTlsProvider)provider, (MSI.MonoTlsSettings)settings); + return ChainValidationHelper.GetInternalValidator ((MSI.MonoTlsProvider)provider, (MSI.MonoTlsSettings)settings); + #else + throw new NotSupportedException (); + #endif + } + + internal static object GetDefaultValidator (object settings) + { + #if SECURITY_DEP + return ChainValidationHelper.GetDefaultValidator ((MSI.MonoTlsSettings)settings); #else throw new NotSupportedException (); #endif @@ -65,29 +74,29 @@ namespace Mono.Net.Security #endif } - internal static object GetDefaultProvider () - { - #if SECURITY_DEP - return MonoTlsProviderFactory.GetDefaultProvider (); - #else - throw new NotSupportedException (); - #endif - } - - internal static bool HasProvider { + internal static bool IsInitialized { get { #if SECURITY_DEP - return MonoTlsProviderFactory.HasProvider; + return MonoTlsProviderFactory.IsInitialized; #else throw new NotSupportedException (); #endif } } - internal static void SetDefaultProvider (string name) + internal static void Initialize () { #if SECURITY_DEP - MonoTlsProviderFactory.SetDefaultProvider (name); + MonoTlsProviderFactory.Initialize (); + #else + throw new NotSupportedException (); + #endif + } + + internal static void Initialize (string provider) + { + #if SECURITY_DEP + MonoTlsProviderFactory.Initialize (provider); #else throw new NotSupportedException (); #endif @@ -120,6 +129,15 @@ namespace Mono.Net.Security #endif } + internal static bool IsProviderSupported (string name) + { + #if SECURITY_DEP + return MonoTlsProviderFactory.IsProviderSupported (name); + #else + throw new NotSupportedException (); + #endif + } + internal static object GetProvider (string name) { #if SECURITY_DEP diff --git a/mcs/class/System/Mono.Net.Security/SystemCertificateValidator.cs b/mcs/class/System/Mono.Net.Security/SystemCertificateValidator.cs index e900c22bfe..42c17de3ce 100644 --- a/mcs/class/System/Mono.Net.Security/SystemCertificateValidator.cs +++ b/mcs/class/System/Mono.Net.Security/SystemCertificateValidator.cs @@ -13,8 +13,6 @@ using Mono.Security.Interface; using MSX = Mono.Security.X509; using Mono.Security.X509.Extensions; #endif -using XX509CertificateCollection = System.Security.Cryptography.X509Certificates.X509CertificateCollection; -using XX509Chain = System.Security.Cryptography.X509Certificates.X509Chain; using System; using System.Net; @@ -62,7 +60,7 @@ namespace Mono.Net.Security #endif } - public static X509Chain CreateX509Chain (XX509CertificateCollection certs) + public static X509Chain CreateX509Chain (X509CertificateCollection certs) { var chain = new X509Chain (); chain.ChainPolicy = new X509ChainPolicy ((X509CertificateCollection)(object)certs); @@ -74,7 +72,7 @@ namespace Mono.Net.Security return chain; } - static bool BuildX509Chain (XX509CertificateCollection certs, X509Chain chain, ref SslPolicyErrors errors, ref int status11) + static bool BuildX509Chain (X509CertificateCollection certs, X509Chain chain, ref SslPolicyErrors errors, ref int status11) { #if MOBILE return false; @@ -106,7 +104,7 @@ namespace Mono.Net.Security #endif } - static bool CheckUsage (XX509CertificateCollection certs, string host, ref SslPolicyErrors errors, ref int status11) + static bool CheckUsage (X509CertificateCollection certs, string host, ref SslPolicyErrors errors, ref int status11) { #if !MONOTOUCH var leaf = certs[0] as X509Certificate2; @@ -130,7 +128,7 @@ namespace Mono.Net.Security return true; } - static bool EvaluateSystem (XX509CertificateCollection certs, XX509CertificateCollection anchors, string host, X509Chain chain, ref SslPolicyErrors errors, ref int status11) + static bool EvaluateSystem (X509CertificateCollection certs, X509CertificateCollection anchors, string host, X509Chain chain, ref SslPolicyErrors errors, ref int status11) { var leaf = certs [0]; bool result; @@ -191,7 +189,7 @@ namespace Mono.Net.Security } public static bool Evaluate ( - MonoTlsSettings settings, string host, XX509CertificateCollection certs, + MonoTlsSettings settings, string host, X509CertificateCollection certs, X509Chain chain, ref SslPolicyErrors errors, ref int status11) { if (!CheckUsage (certs, host, ref errors, ref status11)) diff --git a/mcs/class/System/ReferenceSources/AutoWebProxyScriptEngine.cs b/mcs/class/System/ReferenceSources/AutoWebProxyScriptEngine.cs new file mode 100644 index 0000000000..f3b840e8f7 --- /dev/null +++ b/mcs/class/System/ReferenceSources/AutoWebProxyScriptEngine.cs @@ -0,0 +1,181 @@ +using System.Collections; +using System.Collections.Generic; +using System.Text.RegularExpressions; +#if !MONOTOUCH_WATCH +using Mono.Net; +#endif + +namespace System.Net +{ + class AutoWebProxyScriptEngine + { + public AutoWebProxyScriptEngine (WebProxy proxy, bool useRegistry) + { + } + + public Uri AutomaticConfigurationScript { get; set; } + public bool AutomaticallyDetectSettings { get; set; } + + public bool GetProxies (Uri destination, out IList proxyList) + { + int i = 0; + return GetProxies (destination, out proxyList, ref i); + } + + public bool GetProxies(Uri destination, out IList proxyList, ref int syncStatus) + { + proxyList = null; + return false; + } + + public void Close () + { + } + + public void Abort (ref int syncStatus) + { + } + + public void CheckForChanges () + { + } + +#if !MOBILE + public WebProxyData GetWebProxyData () + { + WebProxyData data; + + // TODO: Could re-use some pieces from _AutoWebProxyScriptEngine.cs + if (IsWindows ()) { + data = InitializeRegistryGlobalProxy (); + if (data != null) + return data; + } + + data = ReadEnvVariables (); + return data ?? new WebProxyData (); + } + + WebProxyData ReadEnvVariables () + { + string address = Environment.GetEnvironmentVariable ("http_proxy") ?? Environment.GetEnvironmentVariable ("HTTP_PROXY"); + + if (address != null) { + try { + if (!address.StartsWith ("http://")) + address = "http://" + address; + + Uri uri = new Uri (address); + IPAddress ip; + + if (IPAddress.TryParse (uri.Host, out ip)) { + if (IPAddress.Any.Equals (ip)) { + UriBuilder builder = new UriBuilder (uri); + builder.Host = "127.0.0.1"; + uri = builder.Uri; + } else if (IPAddress.IPv6Any.Equals (ip)) { + UriBuilder builder = new UriBuilder (uri); + builder.Host = "[::1]"; + uri = builder.Uri; + } + } + + bool bBypassOnLocal = false; + ArrayList al = new ArrayList (); + string bypass = Environment.GetEnvironmentVariable ("no_proxy") ?? Environment.GetEnvironmentVariable ("NO_PROXY"); + + if (bypass != null) { + string[] bypassList = bypass.Split (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); + + foreach (string str in bypassList) { + if (str != "*.local") + al.Add (str); + else + bBypassOnLocal = true; + } + } + + return new WebProxyData { + proxyAddress = uri, + bypassOnLocal = bBypassOnLocal, + bypassList = CreateBypassList (al) + }; + } catch (UriFormatException) { + } + } + + return null; + } + + static bool IsWindows () + { + return (int) Environment.OSVersion.Platform < 4; + } + + WebProxyData InitializeRegistryGlobalProxy () + { + int iProxyEnable = (int)Microsoft.Win32.Registry.GetValue ("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", "ProxyEnable", 0); + + if (iProxyEnable > 0) { + string strHttpProxy = ""; + bool bBypassOnLocal = false; + ArrayList al = new ArrayList (); + + string strProxyServer = (string)Microsoft.Win32.Registry.GetValue ("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", "ProxyServer", null); + string strProxyOverrride = (string)Microsoft.Win32.Registry.GetValue ("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", "ProxyOverride", null); + + if (strProxyServer.Contains ("=")) { + foreach (string strEntry in strProxyServer.Split (new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries)) + if (strEntry.StartsWith ("http=")) { + strHttpProxy = strEntry.Substring (5); + break; + } + } else strHttpProxy = strProxyServer; + + if (strProxyOverrride != null) { + string[] bypassList = strProxyOverrride.Split (new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries); + + foreach (string str in bypassList) { + if (str != "") + al.Add (str); + else + bBypassOnLocal = true; + } + } + + return new WebProxyData { + proxyAddress = ToUri (strHttpProxy), + bypassOnLocal = bBypassOnLocal, + bypassList = CreateBypassList (al) + }; + } + + return null; + } + + static Uri ToUri (string address) + { + if (address == null) + return null; + + if (address.IndexOf ("://", StringComparison.Ordinal) == -1) + address = "http://" + address; + + return new Uri (address); + } + + // Takes an ArrayList of fileglob-formatted strings and returns an array of Regex-formatted strings + static ArrayList CreateBypassList (ArrayList al) + { + string[] result = al.ToArray (typeof (string)) as string[]; + for (int c = 0; c < result.Length; c++) + { + result [c] = "^" + + Regex.Escape (result [c]).Replace (@"\*", ".*").Replace (@"\?", ".") + + "$"; + } + return new ArrayList (result); + } +#endif + } +} \ No newline at end of file diff --git a/mcs/class/System/ReferenceSources/HttpApi.cs b/mcs/class/System/ReferenceSources/HttpApi.cs index b7f3043a59..8d92f001d5 100644 --- a/mcs/class/System/ReferenceSources/HttpApi.cs +++ b/mcs/class/System/ReferenceSources/HttpApi.cs @@ -2,7 +2,7 @@ using System.Collections; namespace System.Net { - static class UnsafeNclNativeMethods + static partial class UnsafeNclNativeMethods { internal static unsafe class HttpApi { diff --git a/mcs/class/System/ReferenceSources/Internal.cs b/mcs/class/System/ReferenceSources/Internal.cs deleted file mode 100644 index 6c50450399..0000000000 --- a/mcs/class/System/ReferenceSources/Internal.cs +++ /dev/null @@ -1,80 +0,0 @@ -// -// Internal.cs -// -// Author: -// Martin Baulig -// -// Copyright (c) 2015 Xamarin Inc. (http://www.xamarin.com) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -using System.Runtime.InteropServices; -using System.Security.Cryptography.X509Certificates; - -namespace System.Net.Security -{ - //From Schannel.h - [Flags] - internal enum SchProtocols - { - Zero = 0, - PctClient = 0x00000002, - PctServer = 0x00000001, - Pct = (PctClient | PctServer), - Ssl2Client = 0x00000008, - Ssl2Server = 0x00000004, - Ssl2 = (Ssl2Client | Ssl2Server), - Ssl3Client = 0x00000020, - Ssl3Server = 0x00000010, - Ssl3 = (Ssl3Client | Ssl3Server), - Tls10Client = 0x00000080, - Tls10Server = 0x00000040, - Tls10 = (Tls10Client | Tls10Server), - Tls11Client = 0x00000200, - Tls11Server = 0x00000100, - Tls11 = (Tls11Client | Tls11Server), - Tls12Client = 0x00000800, - Tls12Server = 0x00000400, - Tls12 = (Tls12Client | Tls12Server), - Ssl3Tls = (Ssl3 | Tls10), - UniClient = unchecked((int)0x80000000), - UniServer = 0x40000000, - Unified = (UniClient | UniServer), - ClientMask = (PctClient | Ssl2Client | Ssl3Client | Tls10Client | Tls11Client | Tls12Client | UniClient), - ServerMask = (PctServer | Ssl2Server | Ssl3Server | Tls10Server | Tls11Server | Tls12Server | UniServer) - } - - //From Schannel.h - [StructLayout (LayoutKind.Sequential)] - internal class SslConnectionInfo - { - public readonly int Protocol; - public readonly int DataCipherAlg; - public readonly int DataKeySize; - public readonly int DataHashAlg; - public readonly int DataHashKeySize; - public readonly int KeyExchangeAlg; - public readonly int KeyExchKeySize; - - internal SslConnectionInfo (int protocol) - { - Protocol = protocol; - } - } -} diff --git a/mcs/class/System/ReferenceSources/LocalAppContextSwitches.cs b/mcs/class/System/ReferenceSources/LocalAppContextSwitches.cs new file mode 100644 index 0000000000..5df7130beb --- /dev/null +++ b/mcs/class/System/ReferenceSources/LocalAppContextSwitches.cs @@ -0,0 +1,7 @@ +namespace System +{ + static class LocalAppContextSwitches + { + public static readonly bool MemberDescriptorEqualsReturnsFalseIfEquivalent = false; + } +} \ No newline at end of file diff --git a/mcs/class/System/ReferenceSources/Logging.cs b/mcs/class/System/ReferenceSources/Logging.cs index 35474720e7..80c2bc9b80 100644 --- a/mcs/class/System/ReferenceSources/Logging.cs +++ b/mcs/class/System/ReferenceSources/Logging.cs @@ -1,4 +1,3 @@ -#if !MONO_FEATURE_NEW_TLS using System.Diagnostics; namespace System.Net { @@ -25,6 +24,10 @@ namespace System.Net { internal static void Enter(TraceSource traceSource, object obj, string method, object paramObject) { } + [Conditional ("TRACE")] + internal static void Enter(TraceSource traceSource, string msg) { + } + [Conditional ("TRACE")] internal static void Exception(TraceSource traceSource, object obj, string method, Exception e) { } @@ -33,10 +36,22 @@ namespace System.Net { internal static void Exit(TraceSource traceSource, object obj, string method, object retObject) { } + [Conditional ("TRACE")] + internal static void Exit(TraceSource traceSource, string msg) { + } + [Conditional ("TRACE")] internal static void PrintInfo(TraceSource traceSource, object obj, string method, string msg) { } + [Conditional ("TRACE")] + internal static void PrintInfo(TraceSource traceSource, object obj, string msg) { + } + + [Conditional ("TRACE")] + internal static void PrintInfo(TraceSource traceSource, string msg) { + } + [Conditional ("TRACE")] internal static void PrintWarning(TraceSource traceSource, object obj, string method, string msg) { } @@ -44,6 +59,10 @@ namespace System.Net { [Conditional ("TRACE")] internal static void PrintWarning(TraceSource traceSource, string msg) { } + + [Conditional ("TRACE")] + internal static void PrintError(TraceSource traceSource, string msg) { + } } #if MOBILE @@ -55,4 +74,3 @@ namespace System.Net { #endif } -#endif diff --git a/mcs/class/System/ReferenceSources/NativeMethods.cs b/mcs/class/System/ReferenceSources/NativeMethods.cs index ca41ea97ac..d2386472e0 100644 --- a/mcs/class/System/ReferenceSources/NativeMethods.cs +++ b/mcs/class/System/ReferenceSources/NativeMethods.cs @@ -38,6 +38,15 @@ namespace Microsoft.Win32 public const int WAIT_ABANDONED = 0x00000080; public const int WAIT_ABANDONED_0 = WAIT_ABANDONED; + public const int ERROR_FILE_NOT_FOUND = 2; + public const int ERROR_PATH_NOT_FOUND = 3; + public const int ERROR_ACCESS_DENIED = 5; + public const int ERROR_INVALID_HANDLE = 6; + public const int ERROR_SHARING_VIOLATION = 32; + public const int ERROR_INVALID_NAME = 0x7B; + public const int ERROR_ALREADY_EXISTS = 183; + public const int ERROR_FILENAME_EXCED_RANGE = 0xCE; + public static bool DuplicateHandle(HandleRef hSourceProcessHandle, SafeHandle hSourceHandle, HandleRef hTargetProcess, out SafeWaitHandle targetHandle, int dwDesiredAccess, bool bInheritHandle, int dwOptions) { diff --git a/mcs/class/System/ReferenceSources/RequestCacheProtocol.cs b/mcs/class/System/ReferenceSources/RequestCacheProtocol.cs new file mode 100644 index 0000000000..b9805f3d0c --- /dev/null +++ b/mcs/class/System/ReferenceSources/RequestCacheProtocol.cs @@ -0,0 +1,10 @@ +namespace System.Net.Cache +{ + class RequestCacheProtocol + { + public RequestCacheProtocol (object arg1, object arg2) + { + throw new NotImplementedException (); + } + } +} \ No newline at end of file diff --git a/mcs/class/System/ReferenceSources/SR2.cs b/mcs/class/System/ReferenceSources/SR2.cs index 35d8f634c0..cfcd038e9b 100644 --- a/mcs/class/System/ReferenceSources/SR2.cs +++ b/mcs/class/System/ReferenceSources/SR2.cs @@ -3,10 +3,14 @@ // // Copyright 2014 Xamarin Inc // -// Mono-specific additions, which are not in SR.cs. +// Mono-specific additions, which are not in SR.cs or missing in referencesource // partial class SR { public const string mono_net_io_shutdown = "mono_net_io_shutdown"; public const string mono_net_io_renegotiate = "mono_net_io_renegotiate"; + + public const string net_log_set_socketoption_reuseport_default_on = "net_log_set_socketoption_reuseport_default_on"; + public const string net_log_set_socketoption_reuseport_not_supported = "net_log_set_socketoption_reuseport_not_supported"; + public const string net_log_set_socketoption_reuseport = "net_log_set_socketoption_reuseport"; } diff --git a/mcs/class/System/ReferenceSources/SSPISafeHandles.cs b/mcs/class/System/ReferenceSources/SSPISafeHandles.cs deleted file mode 100644 index b7c1da7953..0000000000 --- a/mcs/class/System/ReferenceSources/SSPISafeHandles.cs +++ /dev/null @@ -1,208 +0,0 @@ -// -// SafeHandles.cs -// -// Author: -// Martin Baulig -// -// Copyright (c) 2015 Xamarin Inc. (http://www.xamarin.com) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -#if MONO_FEATURE_NEW_TLS && SECURITY_DEP -#if MONO_SECURITY_ALIAS -extern alias MonoSecurity; -using IMonoTlsContext = MonoSecurity::Mono.Security.Interface.IMonoTlsContext; -#else -using IMonoTlsContext = Mono.Security.Interface.IMonoTlsContext; -#endif - -using System.Runtime.InteropServices; -using System.Security.Cryptography.X509Certificates; - -namespace System.Net.Security -{ - class DummySafeHandle : SafeHandle - { - protected DummySafeHandle () - : base ((IntPtr)(-1), true) - { - } - - protected override bool ReleaseHandle () - { - return true; - } - - public override bool IsInvalid { - get { return handle == (IntPtr)(-1); } - } - } - - class SafeFreeCertContext : DummySafeHandle - { - } - - class SafeFreeCredentials : DummySafeHandle - { - SecureCredential credential; - - public X509Certificate2 Certificate { - get { - if (IsInvalid) - throw new ObjectDisposedException ("Certificate"); - return credential.certificate; - } - } - - public SafeFreeCredentials (SecureCredential credential) - { - this.credential = credential; - bool success = true; - DangerousAddRef (ref success); - } - - public override bool IsInvalid { - get { - return credential.certificate == null; - } - } - - protected override bool ReleaseHandle () - { - credential.Clear (); - return base.ReleaseHandle (); - } - } - - class SafeDeleteContext : DummySafeHandle - { - IMonoTlsContext context; - - public IMonoTlsContext Context { - get { - if (IsInvalid) - throw new ObjectDisposedException ("TlsContext"); - return context; - } - } - - public SafeDeleteContext (IMonoTlsContext context) - { - this.context = context; - } - - public override bool IsInvalid { - get { - return context == null || !context.IsValid; - } - } - - protected override bool ReleaseHandle () - { - context.Dispose (); - context = null; - return base.ReleaseHandle (); - } - } - - struct SecureCredential - { - public const int CurrentVersion = 0x4; - - [Flags] - public enum Flags - { - Zero = 0, - NoSystemMapper = 0x02, - NoNameCheck = 0x04, - ValidateManual = 0x08, - NoDefaultCred = 0x10, - ValidateAuto = 0x20, - UseStrongCrypto = 0x00400000 - } - - int version; - internal X509Certificate2 certificate; - SchProtocols protocols; - EncryptionPolicy policy; - - public SecureCredential (int version, X509Certificate2 certificate, SecureCredential.Flags flags, SchProtocols protocols, EncryptionPolicy policy) - { - this.version = version; - this.certificate = certificate; - this.protocols = protocols; - this.policy = policy; - } - - public void Clear () - { - certificate = null; - } - } - - internal class SafeCredentialReference : DummySafeHandle - { - // - // Static cache will return the target handle if found the reference in the table. - // - internal SafeFreeCredentials _Target; - - // - // - internal static SafeCredentialReference CreateReference (SafeFreeCredentials target) - { - SafeCredentialReference result = new SafeCredentialReference (target); - if (result.IsInvalid) - return null; - - return result; - } - - private SafeCredentialReference (SafeFreeCredentials target) - : base () - { - // Bumps up the refcount on Target to signify that target handle is statically cached so - // its dispose should be postponed - bool b = false; - try { - target.DangerousAddRef (ref b); - } catch { - if (b) { - target.DangerousRelease (); - b = false; - } - } finally { - if (b) { - _Target = target; - SetHandle (new IntPtr (0)); // make this handle valid - } - } - } - - override protected bool ReleaseHandle () - { - SafeFreeCredentials target = _Target; - if (target != null) - target.DangerousRelease (); - _Target = null; - return true; - } - } - -} -#endif diff --git a/mcs/class/System/ReferenceSources/SSPIWrapper.cs b/mcs/class/System/ReferenceSources/SSPIWrapper.cs deleted file mode 100644 index a0cb8d5019..0000000000 --- a/mcs/class/System/ReferenceSources/SSPIWrapper.cs +++ /dev/null @@ -1,303 +0,0 @@ -// -// SSPIWrapper.cs -// -// Author: -// Martin Baulig -// -// Copyright (c) 2015 Xamarin Inc. (http://www.xamarin.com) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -#if MONO_FEATURE_NEW_TLS && SECURITY_DEP -#if MONO_SECURITY_ALIAS -extern alias MonoSecurity; -#endif - -#if MONO_SECURITY_ALIAS -using MX = MonoSecurity::Mono.Security.X509; -using MonoSecurity::Mono.Security.Interface; -#else -using MX = Mono.Security.X509; -using Mono.Security.Interface; -#endif - -using System.Runtime.InteropServices; -using System.Security.Authentication.ExtendedProtection; -using System.Security.Cryptography.X509Certificates; -using MNS = Mono.Net.Security; - -namespace System.Net.Security -{ - internal class SSPIInterface - { - public IMonoTlsContext Context { - get; - private set; - } - - public IMonoTlsEventSink EventSink { - get; - private set; - } - - public SSPIInterface (IMonoTlsContext context, IMonoTlsEventSink eventSink) - { - Context = context; - EventSink = eventSink; - } - } - - internal static class GlobalSSPI - { - internal static SSPIInterface Create (string hostname, bool serverMode, SchProtocols protocolFlags, X509Certificate serverCertificate, X509CertificateCollection clientCertificates, - bool remoteCertRequired, bool checkCertName, bool checkCertRevocationStatus, EncryptionPolicy encryptionPolicy, - LocalCertSelectionCallback certSelectionDelegate, RemoteCertValidationCallback remoteValidationCallback, SSPIConfiguration userConfig) - { - if (userConfig.Settings != null && remoteValidationCallback != null) - throw new InvalidOperationException (); - var context = userConfig.Provider.CreateTlsContext ( - hostname, serverMode, (TlsProtocols)protocolFlags, serverCertificate, clientCertificates, - remoteCertRequired, checkCertName, checkCertRevocationStatus, - (MonoEncryptionPolicy)encryptionPolicy, userConfig.Settings); - return new SSPIInterface (context, userConfig.EventSink); - } - } - - /* - * SSPIWrapper _is a _class that provides a managed implementation of the equivalent - * _class _in Microsofts .NET Framework. - * - * The SSPIWrapper class is used by the TLS/SSL stack to implement both the - * protocol handshake as well as the encryption and decryption of messages. - * - * Microsoft's implementation of this class is merely a P/Invoke wrapper - * around the native SSPI APIs on Windows. This implementation instead, - * provides a managed implementation that uses the cross platform Mono.Security - * to provide the equivalent functionality. - * - * Ideally, this should be abstracted with a different name, and decouple - * the naming from the SSPIWrapper name, but this allows Mono to reuse - * the .NET code with minimal changes. - * - * The "internal" methods here are the API that is consumed by the class - * libraries. - */ - internal static class SSPIWrapper - { - static void SetCredentials (SSPIInterface secModule, SafeFreeCredentials credentials) - { - if (credentials != null && !credentials.IsInvalid) { - if (!secModule.Context.HasCredentials && credentials.Certificate != null) { - var cert = new X509Certificate2 (credentials.Certificate.RawData); - secModule.Context.SetCertificate (cert, credentials.Certificate.PrivateKey); - } - bool success = true; - credentials.DangerousAddRef (ref success); - } - } - - /* - * @safecontext is null on the first use, but it will become non-null for invocations - * where the connection is being re-negotiated. - * - */ - internal static int AcceptSecurityContext (SSPIInterface secModule, ref SafeFreeCredentials credentials, ref SafeDeleteContext safeContext, ContextFlags inFlags, Endianness endianness, SecurityBuffer inputBuffer, SecurityBuffer outputBuffer, ref ContextFlags outFlags) - { - if (endianness != Endianness.Native) - throw new NotSupportedException (); - - if (safeContext == null) { - if (credentials == null || credentials.IsInvalid) - return (int)SecurityStatus.CredentialsNeeded; - - secModule.Context.Initialize (secModule.EventSink); - safeContext = new SafeDeleteContext (secModule.Context); - } - - SetCredentials (secModule, credentials); - - var incoming = GetInputBuffer (inputBuffer); - IBufferOffsetSize outgoing; - - var retval = (int)safeContext.Context.GenerateNextToken (incoming, out outgoing); - UpdateOutput (outgoing, outputBuffer); - return retval; - } - - internal static int InitializeSecurityContext (SSPIInterface secModule, ref SafeFreeCredentials credentials, ref SafeDeleteContext safeContext, string targetName, ContextFlags inFlags, Endianness endianness, SecurityBuffer inputBuffer, SecurityBuffer outputBuffer, ref ContextFlags outFlags) - { - if (inputBuffer != null) - throw new InvalidOperationException (); - - if (safeContext == null) { - secModule.Context.Initialize (secModule.EventSink); - safeContext = new SafeDeleteContext (secModule.Context); - } - - return InitializeSecurityContext (secModule, credentials, ref safeContext, targetName, inFlags, endianness, null, outputBuffer, ref outFlags); - } - - internal static int InitializeSecurityContext (SSPIInterface secModule, SafeFreeCredentials credentials, ref SafeDeleteContext safeContext, string targetName, ContextFlags inFlags, Endianness endianness, SecurityBuffer[] inputBuffers, SecurityBuffer outputBuffer, ref ContextFlags outFlags) - { - if (endianness != Endianness.Native) - throw new NotSupportedException (); - - SetCredentials (secModule, credentials); - - SecurityBuffer inputBuffer = null; - if (inputBuffers != null) { - if (inputBuffers.Length != 2 || inputBuffers [1].type != BufferType.Empty) - throw new NotSupportedException (); - inputBuffer = inputBuffers [0]; - } - - var incoming = GetInputBuffer (inputBuffer); - IBufferOffsetSize outgoing = null; - - var retval = (int)safeContext.Context.GenerateNextToken (incoming, out outgoing); - UpdateOutput (outgoing, outputBuffer); - return retval; - } - - internal static int EncryptMessage (SSPIInterface secModule, SafeDeleteContext safeContext, SecurityBuffer securityBuffer, uint sequenceNumber) - { - var incoming = GetInputBuffer (securityBuffer); - var retval = (int)safeContext.Context.EncryptMessage (ref incoming); - UpdateOutput (incoming, securityBuffer); - return retval; - } - - internal static int DecryptMessage (SSPIInterface secModule, SafeDeleteContext safeContext, SecurityBuffer securityBuffer, uint sequenceNumber) - { - var incoming = GetInputBuffer (securityBuffer); - var retval = (int)safeContext.Context.DecryptMessage (ref incoming); - UpdateOutput (incoming, securityBuffer); - return retval; - } - - internal static byte[] CreateShutdownMessage (SSPIInterface secModule, SafeDeleteContext safeContext) - { - return safeContext.Context.CreateCloseNotify (); - } - - internal static byte[] CreateHelloRequestMessage (SSPIInterface secModule, SafeDeleteContext safeContext) - { - return safeContext.Context.CreateHelloRequest (); - } - - internal static bool IsClosed (SSPIInterface secModule, SafeDeleteContext safeContext) - { - return safeContext.Context.ReceivedCloseNotify; - } - - internal static SafeFreeCredentials AcquireCredentialsHandle (SSPIInterface SecModule, string package, CredentialUse intent, SecureCredential scc) - { - return new SafeFreeCredentials (scc); - } - - public static ChannelBinding QueryContextChannelBinding (SSPIInterface SecModule, SafeDeleteContext securityContext, ContextAttribute contextAttribute) - { - return null; - } - - internal static X509Certificate2 GetRemoteCertificate (SafeDeleteContext safeContext, out X509Certificate2Collection remoteCertificateStore) - { - X509CertificateCollection monoCollection; - if (safeContext == null || safeContext.IsInvalid) { - remoteCertificateStore = null; - return null; - } - var monoCert = safeContext.Context.GetRemoteCertificate (out monoCollection); - if (monoCert == null) { - remoteCertificateStore = null; - return null; - } - - remoteCertificateStore = new X509Certificate2Collection (); - foreach (var cert in monoCollection) { - remoteCertificateStore.Add (cert); - } - return (X509Certificate2)monoCert; - } - - internal static bool CheckRemoteCertificate (SafeDeleteContext safeContext) - { - return safeContext.Context.VerifyRemoteCertificate (); - } - - internal static MonoTlsConnectionInfo GetMonoConnectionInfo (SSPIInterface SecModule, SafeDeleteContext securityContext) - { - return securityContext.Context.GetConnectionInfo (); - } - - internal static SslConnectionInfo GetConnectionInfo (SSPIInterface SecModule, SafeDeleteContext securityContext) - { - var info = securityContext.Context.GetConnectionInfo (); - if (info == null) - return null; - - return new SslConnectionInfo ((int)info.ProtocolVersion); - } - - class InputBuffer : IBufferOffsetSize - { - public byte[] Buffer { - get; - private set; - } - - public int Offset { - get; - private set; - } - - public int Size { - get; - private set; - } - - public InputBuffer (byte[] buffer, int offset, int size) - { - Buffer = buffer; - Offset = offset; - Size = size; - } - } - - static IBufferOffsetSize GetInputBuffer (SecurityBuffer incoming) - { - return incoming != null ? new InputBuffer (incoming.token, incoming.offset, incoming.size) : null; - } - - static void UpdateOutput (IBufferOffsetSize buffer, SecurityBuffer outputBuffer) - { - if (buffer != null) { - outputBuffer.token = buffer.Buffer; - outputBuffer.offset = buffer.Offset; - outputBuffer.size = buffer.Size; - outputBuffer.type = BufferType.Token; - } else { - outputBuffer.token = null; - outputBuffer.size = outputBuffer.offset = 0; - outputBuffer.type = BufferType.Empty; - } - } - } -} -#endif diff --git a/mcs/class/System/ReferenceSources/SecureStringHelper.cs b/mcs/class/System/ReferenceSources/SecureStringHelper.cs new file mode 100644 index 0000000000..31372e2cc6 --- /dev/null +++ b/mcs/class/System/ReferenceSources/SecureStringHelper.cs @@ -0,0 +1,47 @@ +using System.Security; +using System.Runtime.InteropServices; + +namespace System.Net +{ + static partial class UnsafeNclNativeMethods + { + internal unsafe static class SecureStringHelper + { + internal static string CreateString(SecureString secureString) + { + string plainString; + IntPtr bstr = IntPtr.Zero; + + if (secureString == null || secureString.Length == 0) + return String.Empty; + + try + { + bstr = Marshal.SecureStringToBSTR(secureString); + plainString = Marshal.PtrToStringBSTR(bstr); + } + finally + { + if (bstr != IntPtr.Zero) + Marshal.ZeroFreeBSTR(bstr); + } + return plainString; + } + + internal static SecureString CreateSecureString(string plainString) + { + SecureString secureString; + + if (plainString == null || plainString.Length == 0) + return new SecureString(); + + fixed (char* pch = plainString) + { + secureString = new SecureString(pch, plainString.Length); + } + + return secureString; + } + } + } +} \ No newline at end of file diff --git a/mcs/class/System/ReferenceSources/SettingsSectionInternal.cs b/mcs/class/System/ReferenceSources/SettingsSectionInternal.cs index 595c569e6c..afe34459bb 100644 --- a/mcs/class/System/ReferenceSources/SettingsSectionInternal.cs +++ b/mcs/class/System/ReferenceSources/SettingsSectionInternal.cs @@ -1,3 +1,5 @@ +using System.Net.Security; + namespace System.Net.Configuration { sealed class SettingsSectionInternal { @@ -15,5 +17,14 @@ namespace System.Net.Configuration { #endif internal bool HttpListenerUnescapeRequestUrl = true; + + + internal bool UseNagleAlgorithm { get; set; } + internal bool Expect100Continue { get; set; } + internal bool CheckCertificateName { get; private set; } + internal int DnsRefreshTimeout { get; set; } + internal bool EnableDnsRoundRobin { get; set; } + internal bool CheckCertificateRevocationList { get; set; } + internal EncryptionPolicy EncryptionPolicy { get; private set; } } } diff --git a/mcs/class/System/ReferenceSources/Socket.cs b/mcs/class/System/ReferenceSources/Socket.cs index 8c1d12b8aa..a7f6f99f6b 100644 --- a/mcs/class/System/ReferenceSources/Socket.cs +++ b/mcs/class/System/ReferenceSources/Socket.cs @@ -100,5 +100,50 @@ namespace System.Net.Sockets if (!silent && error != 0) throw new SocketException (error); } + + internal bool CanTryAddressFamily (AddressFamily family) + { + return (family == address_family) || (family == AddressFamily.InterNetwork && IsDualMode); + } + + public static bool ConnectAsync(SocketType socketType, ProtocolType protocolType, SocketAsyncEventArgs e) { + + bool retval; + + // Throw if multiple buffers specified. + if (e.m_BufferList != null) { + throw new ArgumentException(SR.GetString(SR.net_multibuffernotsupported), "BufferList"); + } + + // Throw if RemoteEndPoint is null. + if (e.RemoteEndPoint == null) { + throw new ArgumentNullException("remoteEP"); + } + + EndPoint endPointSnapshot = e.RemoteEndPoint; + DnsEndPoint dnsEP = endPointSnapshot as DnsEndPoint; + + if (dnsEP != null) { + Socket attemptSocket = null; + MultipleConnectAsync multipleConnectAsync = null; + if (dnsEP.AddressFamily == AddressFamily.Unspecified) { + multipleConnectAsync = new MultipleSocketMultipleConnectAsync(socketType, protocolType); + } else { + attemptSocket = new Socket(dnsEP.AddressFamily, socketType, protocolType); + multipleConnectAsync = new SingleSocketMultipleConnectAsync(attemptSocket, false); + } + + e.StartOperationCommon(attemptSocket); + e.StartOperationWrapperConnect(multipleConnectAsync); + + retval = multipleConnectAsync.StartConnectAsync(e, dnsEP); + } else { + Socket attemptSocket = new Socket(endPointSnapshot.AddressFamily, socketType, protocolType); + retval = attemptSocket.ConnectAsync(e); + } + + return retval; + } + } } diff --git a/mcs/class/System/ReferenceSources/SslStream.cs b/mcs/class/System/ReferenceSources/SslStream.cs deleted file mode 100644 index fea8922f80..0000000000 --- a/mcs/class/System/ReferenceSources/SslStream.cs +++ /dev/null @@ -1,141 +0,0 @@ -// -// Mono-specific additions to Microsoft's SslStream.cs -// -#if MONO_FEATURE_NEW_TLS && SECURITY_DEP -#if MONO_SECURITY_ALIAS -extern alias MonoSecurity; -using MonoSecurity::Mono.Security.Interface; -#else -using Mono.Security.Interface; -#endif -using System.Threading; -using System.Security.Cryptography.X509Certificates; -using MNS = Mono.Net.Security; - -namespace System.Net.Security -{ - using System.Net.Sockets; - using System.IO; - - partial class SslStream : IMonoTlsEventSink - { - #if SECURITY_DEP - SSPIConfiguration _Configuration; - - internal SslStream (Stream innerStream, bool leaveInnerStreamOpen, EncryptionPolicy encryptionPolicy, MonoTlsProvider provider, MonoTlsSettings settings) - : base (innerStream, leaveInnerStreamOpen) - { - if (encryptionPolicy != EncryptionPolicy.RequireEncryption && encryptionPolicy != EncryptionPolicy.AllowNoEncryption && encryptionPolicy != EncryptionPolicy.NoEncryption) - throw new ArgumentException (SR.GetString (SR.net_invalid_enum, "EncryptionPolicy"), "encryptionPolicy"); - - var validationHelper = MNS.ChainValidationHelper.CloneWithCallbackWrapper (provider, ref settings, myUserCertValidationCallbackWrapper); - - LocalCertSelectionCallback selectionCallback = null; - if (validationHelper.HasCertificateSelectionCallback) - selectionCallback = validationHelper.SelectClientCertificate; - - var internalProvider = new MNS.Private.MonoTlsProviderWrapper (provider); - _Configuration = new MyConfiguration (internalProvider, settings, this); - _SslState = new SslState (innerStream, null, selectionCallback, encryptionPolicy, _Configuration); - } - - /* - * Mono-specific version of 'userCertValidationCallbackWrapper'; we're called from ChainValidationHelper.ValidateChain() here. - * - * Since we're built without the PrebuiltSystem alias, we can't use 'SslPolicyErrors' here. This prevents us from creating a subclass of 'ChainValidationHelper' - * as well as providing a custom 'ServerCertValidationCallback'. - */ - bool myUserCertValidationCallbackWrapper (ServerCertValidationCallback callback, X509Certificate certificate, X509Chain chain, MonoSslPolicyErrors sslPolicyErrors) - { - m_RemoteCertificateOrBytes = certificate == null ? null : certificate.GetRawCertData (); - if (callback == null) { - if (!_SslState.RemoteCertRequired) - sslPolicyErrors &= ~MonoSslPolicyErrors.RemoteCertificateNotAvailable; - - return (sslPolicyErrors == MonoSslPolicyErrors.None); - } - - return MNS.ChainValidationHelper.InvokeCallback (callback, this, certificate, chain, sslPolicyErrors); - } - - class MyConfiguration : SSPIConfiguration - { - MNS.IMonoTlsProvider provider; - MonoTlsSettings settings; - IMonoTlsEventSink eventSink; - - public MyConfiguration (MNS.IMonoTlsProvider provider, MonoTlsSettings settings, IMonoTlsEventSink eventSink) - { - this.provider = provider; - this.settings = settings; - this.eventSink = eventSink; - } - - public MNS.IMonoTlsProvider Provider { - get { return provider; } - } - - public MonoTlsSettings Settings { - get { return settings; } - } - - public IMonoTlsEventSink EventSink { - get { return eventSink; } - } - } - #endif - - internal bool IsClosed { - get { return _SslState.IsClosed; } - } - - internal Exception LastError { - get { return lastError; } - } - - #region IMonoTlsEventSink - - Exception lastError; - - void IMonoTlsEventSink.Error (Exception exception) - { - Interlocked.CompareExchange (ref lastError, exception, null); - } - - void IMonoTlsEventSink.ReceivedCloseNotify () - { - } - - #endregion - - internal IAsyncResult BeginShutdown (AsyncCallback asyncCallback, object asyncState) - { - return _SslState.BeginShutdown (asyncCallback, asyncState); - } - - internal void EndShutdown (IAsyncResult asyncResult) - { - _SslState.EndShutdown (asyncResult); - } - - internal IAsyncResult BeginRenegotiate (AsyncCallback asyncCallback, object asyncState) - { - return _SslState.BeginRenegotiate (asyncCallback, asyncState); - } - - internal void EndRenegotiate (IAsyncResult asyncResult) - { - _SslState.EndRenegotiate (asyncResult); - } - - internal X509Certificate InternalLocalCertificate { - get { return _SslState.InternalLocalCertificate; } - } - - internal MonoTlsConnectionInfo GetMonoConnectionInfo () - { - return _SslState.GetMonoConnectionInfo (); - } - } -} -#endif diff --git a/mcs/class/System/ReferenceSources/SystemNetworkCredential.cs b/mcs/class/System/ReferenceSources/SystemNetworkCredential.cs deleted file mode 100644 index 71f87c8899..0000000000 --- a/mcs/class/System/ReferenceSources/SystemNetworkCredential.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace System.Net { - // - // Object representing default credentials - // - internal class SystemNetworkCredential : NetworkCredential { - internal static readonly SystemNetworkCredential defaultCredential = new SystemNetworkCredential(); - - // We want reference equality to work. Making this private is a good way to guarantee that. - private SystemNetworkCredential() : - base(string.Empty, string.Empty, string.Empty) { - } - } -} \ No newline at end of file diff --git a/mcs/class/System/ReferenceSources/_SecureChannel.cs b/mcs/class/System/ReferenceSources/_SecureChannel.cs deleted file mode 100644 index f920353a09..0000000000 --- a/mcs/class/System/ReferenceSources/_SecureChannel.cs +++ /dev/null @@ -1,41 +0,0 @@ -// -// Mono-specific additions to Microsoft's _SecureChannel.cs -// -#if MONO_FEATURE_NEW_TLS && SECURITY_DEP -#if MONO_SECURITY_ALIAS -extern alias MonoSecurity; -using MonoSecurity::Mono.Security.Interface; -#else -using Mono.Security.Interface; -#endif -namespace System.Net.Security -{ - partial class SecureChannel - { - internal MonoTlsConnectionInfo GetMonoConnectionInfo () - { - return SSPIWrapper.GetMonoConnectionInfo (m_SecModule, m_SecurityContext); - } - - internal ProtocolToken CreateShutdownMessage () - { - var buffer = SSPIWrapper.CreateShutdownMessage (m_SecModule, m_SecurityContext); - return new ProtocolToken (buffer, SecurityStatus.ContinueNeeded); - } - - internal ProtocolToken CreateHelloRequestMessage () - { - var buffer = SSPIWrapper.CreateHelloRequestMessage (m_SecModule, m_SecurityContext); - return new ProtocolToken (buffer, SecurityStatus.ContinueNeeded); - } - - internal bool IsClosed { - get { - if (m_SecModule == null || m_SecurityContext == null || m_SecurityContext.IsClosed) - return true; - return SSPIWrapper.IsClosed (m_SecModule, m_SecurityContext); - } - } - } -} -#endif diff --git a/mcs/class/System/ReferenceSources/_SslState.cs b/mcs/class/System/ReferenceSources/_SslState.cs deleted file mode 100644 index 8d5ae3f310..0000000000 --- a/mcs/class/System/ReferenceSources/_SslState.cs +++ /dev/null @@ -1,141 +0,0 @@ -// -// Mono-specific additions to Microsoft's _SslState.cs -// -#if MONO_FEATURE_NEW_TLS && SECURITY_DEP -#if MONO_SECURITY_ALIAS -extern alias MonoSecurity; -using MonoSecurity::Mono.Security.Interface; -#else -using Mono.Security.Interface; -#endif -namespace System.Net.Security -{ - using System.IO; - using System.Threading; - using System.Net.Sockets; - - partial class SslState - { - int _SentShutdown; - - internal MonoTlsConnectionInfo GetMonoConnectionInfo () - { - return Context.GetMonoConnectionInfo (); - } - - internal bool IsClosed { - get { return Context.IsClosed; } - } - - internal ProtocolToken CreateShutdownMessage () - { - return Context.CreateShutdownMessage (); - } - - internal ProtocolToken CreateHelloRequestMessage () - { - return Context.CreateHelloRequestMessage (); - } - - internal IAsyncResult BeginShutdown (AsyncCallback asyncCallback, object asyncState) - { - var shutdownResult = new ShutdownAsyncResult (this, asyncState, asyncCallback); - - if (Interlocked.CompareExchange (ref _SentShutdown, 1, 0) == 1) { - shutdownResult.InvokeCallback (); - return shutdownResult; - } - - try - { - CheckThrow (false); - shutdownResult.SentShutdown = true; - SecureStream.BeginShutdown (shutdownResult); - return shutdownResult; - } catch (Exception e) { - if (e is IOException) - throw; - throw new IOException (SR.GetString (SR.mono_net_io_shutdown), e); - } - } - - internal void EndShutdown (IAsyncResult asyncResult) - { - if (asyncResult == null) - throw new ArgumentNullException ("asyncResult"); - - var shutdownResult = asyncResult as ShutdownAsyncResult; - if (shutdownResult == null) - throw new ArgumentException (SR.GetString (SR.net_io_async_result, asyncResult.GetType ().FullName), "asyncResult"); - - if (shutdownResult.SentShutdown) - SecureStream.EndShutdown (shutdownResult); - } - - internal IAsyncResult BeginRenegotiate (AsyncCallback asyncCallback, object asyncState) - { - var lazyResult = new LazyAsyncResult (this, asyncState, asyncCallback); - - if (Interlocked.Exchange (ref _NestedAuth, 1) == 1) - throw new InvalidOperationException (SR.GetString (SR.net_io_invalidnestedcall, "BeginRenegotiate", "renegotiate")); - if (Interlocked.CompareExchange (ref _PendingReHandshake, 1, 0) == 1) - throw new InvalidOperationException (SR.GetString (SR.net_io_invalidnestedcall, "BeginRenegotiate", "renegotiate")); - - try { - CheckThrow (false); - SecureStream.BeginRenegotiate (lazyResult); - return lazyResult; - } catch (Exception e) { - _NestedAuth = 0; - if (e is IOException) - throw; - throw new IOException (SR.GetString (SR.mono_net_io_renegotiate), e); - } - } - - internal void EndRenegotiate (IAsyncResult result) - { - if (result == null) - throw new ArgumentNullException ("asyncResult"); - - LazyAsyncResult lazyResult = result as LazyAsyncResult; - if (lazyResult == null) - throw new ArgumentException (SR.GetString (SR.net_io_async_result, result.GetType ().FullName), "asyncResult"); - - if (Interlocked.Exchange (ref _NestedAuth, 0) == 0) - throw new InvalidOperationException (SR.GetString (SR.net_io_invalidendcall, "EndRenegotiate")); - - SecureStream.EndRenegotiate (lazyResult); - } - - internal bool CheckEnqueueHandshakeWrite (byte[] buffer, AsyncProtocolRequest asyncRequest) - { - return CheckEnqueueHandshake (buffer, asyncRequest); - } - - internal void StartReHandshake (AsyncProtocolRequest asyncRequest) - { - if (IsServer) { - byte[] buffer = null; - if (CheckEnqueueHandshakeRead (ref buffer, asyncRequest)) - return; - - StartReceiveBlob (buffer, asyncRequest); - return; - } - - ForceAuthentication (false, null, asyncRequest); - } - - class ShutdownAsyncResult : LazyAsyncResult - { - public bool SentShutdown; - - internal ShutdownAsyncResult (SslState instance, object userState, AsyncCallback callback) - : base (instance, userState, callback) - { - } - } - } -} -#endif diff --git a/mcs/class/System/ReferenceSources/_SslStream.cs b/mcs/class/System/ReferenceSources/_SslStream.cs deleted file mode 100644 index 591b74abf6..0000000000 --- a/mcs/class/System/ReferenceSources/_SslStream.cs +++ /dev/null @@ -1,230 +0,0 @@ -// -// Mono-specific additions to Microsoft's _SslStream.cs -// -#if MONO_FEATURE_NEW_TLS && SECURITY_DEP -namespace System.Net.Security -{ - using System.IO; - using System.Threading; - using System.Net.Sockets; - - partial class _SslStream - { - static readonly AsyncCallback _HandshakeWriteCallback = new AsyncCallback (HandshakeWriteCallback); - static readonly HandshakeProtocolCallback _ResumeHandshakeWriteCallback = new HandshakeProtocolCallback (ResumeHandshakeWriteCallback); - - internal void BeginShutdown (LazyAsyncResult lazyResult) - { - HandshakeProtocolRequest asyncRequest = new HandshakeProtocolRequest (lazyResult); - - if (Interlocked.Exchange (ref _NestedWrite, 1) == 1) - throw new NotSupportedException (SR.GetString (SR.net_io_invalidnestedcall, (asyncRequest != null ? "BeginShutdown" : "Shutdown"), "shutdown")); - - bool failed = false; - try - { - ProtocolToken message = _SslState.CreateShutdownMessage (); - asyncRequest.SetNextRequest (HandshakeProtocolState.Shutdown, message, _ResumeHandshakeWriteCallback); - - StartHandshakeWrite (asyncRequest); - } catch (Exception e) { - _SslState.FinishWrite (); - failed = true; - throw; - } finally { - if (failed) - _NestedWrite = 0; - } - } - - internal void EndShutdown (LazyAsyncResult lazyResult) - { - if (Interlocked.Exchange (ref _NestedWrite, 0) == 0) - throw new InvalidOperationException (SR.GetString (SR.net_io_invalidendcall, "EndShutdown")); - - // No "artificial" timeouts implemented so far, InnerStream controls timeout. - lazyResult.InternalWaitForCompletion (); - - if (lazyResult.Result is Exception) { - if (lazyResult.Result is IOException) - throw (Exception)lazyResult.Result; - throw new IOException (SR.GetString (SR.mono_net_io_shutdown), (Exception)lazyResult.Result); - } - } - - internal void BeginRenegotiate (LazyAsyncResult lazyResult) - { - HandshakeProtocolRequest asyncRequest = new HandshakeProtocolRequest (lazyResult); - - if (Interlocked.Exchange (ref _NestedWrite, 1) == 1) - throw new NotSupportedException (SR.GetString (SR.net_io_invalidnestedcall, (asyncRequest != null ? "BeginRenegotiate" : "Renegotiate"), "renegotiate")); - - bool failed = false; - try - { - if (_SslState.IsServer) { - ProtocolToken message = _SslState.CreateHelloRequestMessage (); - asyncRequest.SetNextRequest (HandshakeProtocolState.SendHelloRequest, message, _ResumeHandshakeWriteCallback); - } else { - asyncRequest.SetNextRequest (HandshakeProtocolState.ClientRenegotiation, null, _ResumeHandshakeWriteCallback); - } - - StartHandshakeWrite (asyncRequest); - } catch (Exception e) { - _SslState.FinishWrite (); - failed = true; - throw; - } finally { - if (failed) - _NestedWrite = 0; - } - } - - internal void EndRenegotiate (LazyAsyncResult lazyResult) - { - if (Interlocked.Exchange (ref _NestedWrite, 0) == 0) - throw new InvalidOperationException (SR.GetString (SR.net_io_invalidendcall, "EndRenegotiate")); - - // No "artificial" timeouts implemented so far, InnerStream controls timeout. - lazyResult.InternalWaitForCompletion(); - - if (lazyResult.Result is Exception) { - if (lazyResult.Result is IOException) - throw (Exception)lazyResult.Result; - throw new IOException (SR.GetString (SR.mono_net_io_renegotiate), (Exception)lazyResult.Result); - } - } - - void StartHandshakeWrite (HandshakeProtocolRequest asyncRequest) - { - byte[] buffer = null; - if (asyncRequest.Message != null) { - buffer = asyncRequest.Message.Payload; - if (buffer.Length != asyncRequest.Message.Size) { - buffer = new byte [asyncRequest.Message.Size]; - Buffer.BlockCopy (asyncRequest.Message.Payload, 0, buffer, 0, buffer.Length); - } - } - - switch (asyncRequest.State) { - case HandshakeProtocolState.ClientRenegotiation: - case HandshakeProtocolState.ServerRenegotiation: - _SslState.StartReHandshake (asyncRequest); - return; - - case HandshakeProtocolState.SendHelloRequest: - if (_SslState.CheckEnqueueHandshakeWrite (buffer, asyncRequest)) { - // operation is async and has been queued, return. - return; - } - break; - - case HandshakeProtocolState.Shutdown: - if (_SslState.CheckEnqueueWrite (asyncRequest)) { - // operation is async and has been queued, return. - return; - } - break; - - default: - throw new InvalidOperationException (); - } - - if (_SslState.LastPayload != null) - throw new InvalidOperationException (); - - // prepare for the next request - IAsyncResult ar = ((NetworkStream)_SslState.InnerStream).BeginWrite (buffer, 0, buffer.Length, _HandshakeWriteCallback, asyncRequest); - if (!ar.CompletedSynchronously) - return; - - HandshakeWriteCallback (asyncRequest, ar); - } - - static void HandshakeWriteCallback (IAsyncResult transportResult) - { - if (transportResult.CompletedSynchronously) - return; - - HandshakeProtocolRequest asyncRequest = (HandshakeProtocolRequest)transportResult.AsyncState; - - SslState sslState = (SslState)asyncRequest.AsyncObject; - sslState.SecureStream.HandshakeWriteCallback (asyncRequest, transportResult); - } - - void HandshakeWriteCallback (HandshakeProtocolRequest asyncRequest, IAsyncResult transportResult) - { - try { - _SslState.InnerStream.EndWrite (transportResult); - } catch (Exception e) { - _SslState.FinishWrite (); - if (!asyncRequest.IsUserCompleted) { - asyncRequest.CompleteWithError (e); - return; - } - throw; - } - - if (asyncRequest.State == HandshakeProtocolState.SendHelloRequest) { - asyncRequest.SetNextRequest (HandshakeProtocolState.ServerRenegotiation, null, _ResumeHandshakeWriteCallback); - StartHandshakeWrite (asyncRequest); - return; - } - - try { - _SslState.FinishWrite (); - asyncRequest.CompleteUser (); - } catch (Exception e) { - if (!asyncRequest.IsUserCompleted) { - asyncRequest.CompleteWithError (e); - return; - } - throw; - } - } - - static void ResumeHandshakeWriteCallback (HandshakeProtocolRequest asyncRequest) - { - try { - ((_SslStream)asyncRequest.AsyncObject).StartHandshakeWrite (asyncRequest); - } catch (Exception e) { - if (asyncRequest.IsUserCompleted) { - // This will throw on a worker thread. - throw; - } - ((_SslStream)asyncRequest.AsyncObject)._SslState.FinishWrite (); - asyncRequest.CompleteWithError (e); - } - } - - delegate void HandshakeProtocolCallback (HandshakeProtocolRequest asyncRequest); - - enum HandshakeProtocolState { - None, - Shutdown, - SendHelloRequest, - ServerRenegotiation, - ClientRenegotiation - } - - class HandshakeProtocolRequest : AsyncProtocolRequest - { - public ProtocolToken Message; - public HandshakeProtocolState State; - - public HandshakeProtocolRequest (LazyAsyncResult userAsyncResult) - : base (userAsyncResult) - { - State = HandshakeProtocolState.None; - } - - public void SetNextRequest (HandshakeProtocolState state, ProtocolToken message, HandshakeProtocolCallback callback) - { - State = state; - Message = message; - SetNextRequest (null, 0, 0, (r) => callback ((HandshakeProtocolRequest)r)); - } - } - } -} -#endif diff --git a/mcs/class/System/System.Diagnostics/FileVersionInfo.cs b/mcs/class/System/System.Diagnostics/FileVersionInfo.cs index cf38a5e112..e59d0a89fa 100644 --- a/mcs/class/System/System.Diagnostics/FileVersionInfo.cs +++ b/mcs/class/System/System.Diagnostics/FileVersionInfo.cs @@ -144,7 +144,7 @@ namespace System.Diagnostics { public string FileName { get { -#if !NET_2_1 +#if !MOBILE if (SecurityManager.SecurityEnabled) { new FileIOPermission (FileIOPermissionAccess.PathDiscovery, filename).Demand (); } @@ -278,7 +278,7 @@ namespace System.Diagnostics { public static FileVersionInfo GetVersionInfo (string fileName) { -#if !NET_2_1 +#if !MOBILE if (SecurityManager.SecurityEnabled) { new FileIOPermission (FileIOPermissionAccess.Read, fileName).Demand (); } @@ -293,7 +293,7 @@ namespace System.Diagnostics { return fvi; } - // use our own AppendFormat because NET_2_1 have only this overload + // use our own AppendFormat because MOBILE have only this overload static void AppendFormat (StringBuilder sb, string format, params object [] args) { sb.AppendFormat (format, args); diff --git a/mcs/class/System/System.Diagnostics/ProcessThreadCollection.cs b/mcs/class/System/System.Diagnostics/ProcessThreadCollection.cs deleted file mode 100644 index b2fbdbfcb1..0000000000 --- a/mcs/class/System/System.Diagnostics/ProcessThreadCollection.cs +++ /dev/null @@ -1,113 +0,0 @@ -// -// System.Diagnostics.ProcessThreadCollection.cs -// -// Authors: -// Dick Porter (dick@ximian.com) -// Andreas Nahr (ClassDevelopment@A-SoftTech.com) -// -// (C) 2002 Ximian, Inc. http://www.ximian.com -// - -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// - -using System.Collections; - -namespace System.Diagnostics -{ -#if NET_2_1 - public class ProcessThreadCollectionBase : System.Collections.Generic.List - { - protected ProcessThreadCollectionBase InnerList { - get { return this; } - } - - public new int Add (ProcessThread thread) - { - base.Add (thread); - return Count - 1; - } - - public System.Collections.IEnumerator GetEnumerator () - { - return ((System.Collections.IEnumerable)InnerList).GetEnumerator (); - } - } -#endif - - public class ProcessThreadCollection : -#if !NET_2_1 - ReadOnlyCollectionBase -#else - ProcessThreadCollectionBase -#endif - { - protected ProcessThreadCollection() - { - } - - internal static ProcessThreadCollection GetEmpty () - { - return new ProcessThreadCollection (); - } - - public ProcessThreadCollection(ProcessThread[] processThreads) - { - InnerList.AddRange (processThreads); - } - - public ProcessThread this[int index] { - get { - return (ProcessThread)InnerList[index]; - } - } - - public int Add(ProcessThread thread) - { - return InnerList.Add (thread); - } - - public bool Contains(ProcessThread thread) - { - return InnerList.Contains (thread); - } - - public void CopyTo(ProcessThread[] array, int index) - { - InnerList.CopyTo (array, index); - } - - public int IndexOf(ProcessThread thread) - { - return InnerList.IndexOf (thread); - } - - public void Insert(int index, ProcessThread thread) - { - InnerList.Insert (index, thread); - } - - public void Remove(ProcessThread thread) - { - InnerList.Remove (thread); - } - } -} diff --git a/mcs/class/System/System.IO.Compression/DeflateStream.cs b/mcs/class/System/System.IO.Compression/DeflateStream.cs index 0eb6f62931..705cd5d020 100644 --- a/mcs/class/System/System.IO.Compression/DeflateStream.cs +++ b/mcs/class/System/System.IO.Compression/DeflateStream.cs @@ -35,7 +35,7 @@ using System.IO; using System.Runtime.InteropServices; using System.Runtime.Remoting.Messaging; -#if MONOTOUCH +#if MONOTOUCH || MOBILE_STATIC using MonoTouch; #endif @@ -383,7 +383,7 @@ namespace System.IO.Compression CheckResult (res, "WriteInternal"); } -#if MONOTOUCH +#if MONOTOUCH || MOBILE_STATIC [MonoPInvokeCallback (typeof (UnmanagedReadOrWrite))] #endif static int UnmanagedRead (IntPtr buffer, int length, IntPtr data) @@ -408,7 +408,7 @@ namespace System.IO.Compression return n; } -#if MONOTOUCH +#if MONOTOUCH || MOBILE_STATIC [MonoPInvokeCallback (typeof (UnmanagedReadOrWrite))] #endif static int UnmanagedWrite (IntPtr buffer, int length, IntPtr data) diff --git a/mcs/class/System/System.IO/FileSystemWatcher_mobile.cs b/mcs/class/System/System.IO/FileSystemWatcher_mobile.cs index 3b274e0599..04bd35a142 100644 --- a/mcs/class/System/System.IO/FileSystemWatcher_mobile.cs +++ b/mcs/class/System/System.IO/FileSystemWatcher_mobile.cs @@ -26,9 +26,11 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // +using System.ComponentModel; + namespace System.IO { - public class FileSystemWatcher : IDisposable + public class FileSystemWatcher : Component, IDisposable, ISupportInitialize { public FileSystemWatcher () { throw new NotImplementedException (); } public FileSystemWatcher (string path) { throw new NotImplementedException (); } @@ -39,11 +41,15 @@ namespace System.IO public int InternalBufferSize { get { throw new NotImplementedException (); } set { } } public NotifyFilters NotifyFilter { get { throw new NotImplementedException (); } set { } } public string Path { get { throw new NotImplementedException (); } set { } } + public override ISite Site { get { throw new NotImplementedException (); } set { } } + public ISynchronizeInvoke SynchronizingObject { get { throw new NotImplementedException (); } set { } } public event FileSystemEventHandler Changed; public event FileSystemEventHandler Created; public event FileSystemEventHandler Deleted; public event ErrorEventHandler Error; public event RenamedEventHandler Renamed; + public void BeginInit() { throw new NotImplementedException (); } + public void EndInit() { throw new NotImplementedException (); } protected void OnChanged (FileSystemEventArgs e) { throw new NotImplementedException (); } protected void OnCreated (FileSystemEventArgs e) { throw new NotImplementedException (); } protected void OnDeleted (System.IO.FileSystemEventArgs e) { throw new NotImplementedException (); } @@ -51,13 +57,7 @@ namespace System.IO protected void OnRenamed (RenamedEventArgs e) { throw new NotImplementedException (); } public WaitForChangedResult WaitForChanged (WatcherChangeTypes changeType) { throw new NotImplementedException (); } public WaitForChangedResult WaitForChanged (WatcherChangeTypes changeType, int timeout) { throw new NotImplementedException (); } - - public virtual void Dispose () - { - } - - protected virtual void Dispose (bool disposing) - { - } + public virtual void Dispose () { throw new NotImplementedException (); } + protected override void Dispose (bool disposing) { throw new NotImplementedException (); } } } \ No newline at end of file diff --git a/mcs/class/System/System.Net.Configuration/WebRequestModuleHandler.cs b/mcs/class/System/System.Net.Configuration/WebRequestModuleHandler.cs index ed53a83736..594803e2c2 100644 --- a/mcs/class/System/System.Net.Configuration/WebRequestModuleHandler.cs +++ b/mcs/class/System/System.Net.Configuration/WebRequestModuleHandler.cs @@ -42,7 +42,7 @@ namespace System.Net.Configuration { public virtual object Create (object parent, object configContext, XmlNode section) { -#if (XML_DEP) +#if XML_DEP if (section.Attributes != null && section.Attributes.Count != 0) HandlersUtil.ThrowException ("Unrecognized attribute", section); @@ -60,7 +60,7 @@ namespace System.Net.Configuration if (child.Attributes != null && child.Attributes.Count != 0) HandlersUtil.ThrowException ("Unrecognized attribute", child); - WebRequest.ClearPrefixes (); + WebRequest.PrefixList = new ArrayList (); continue; } @@ -70,16 +70,18 @@ namespace System.Net.Configuration if (child.Attributes != null && child.Attributes.Count != 0) HandlersUtil.ThrowException ("Unrecognized attribute", child); - WebRequest.AddPrefix (prefix, type); - continue; + throw new NotImplementedException (); + //WebRequest.PrefixList.Add (new WebRequestPrefixElement(prefix, type)); + //continue; } if (name == "remove") { if (child.Attributes != null && child.Attributes.Count != 0) HandlersUtil.ThrowException ("Unrecognized attribute", child); - WebRequest.RemovePrefix (prefix); - continue; + throw new NotImplementedException (); + // WebRequest.RemovePrefix (prefix); + // continue; } HandlersUtil.ThrowException ("Unexpected element", child); diff --git a/mcs/class/System/System.Net.Mail/MailMessage.cs b/mcs/class/System/System.Net.Mail/MailMessage.cs index 3b978ac32f..b5a58d86b8 100644 --- a/mcs/class/System/System.Net.Mail/MailMessage.cs +++ b/mcs/class/System/System.Net.Mail/MailMessage.cs @@ -153,6 +153,11 @@ namespace System.Net.Mail { set { bodyEncoding = value; } } + public TransferEncoding BodyTransferEncoding { + get { return GuessTransferEncoding (BodyEncoding); } + set { throw new NotImplementedException (); } + } + public MailAddressCollection CC { get { return cc; } } @@ -255,7 +260,7 @@ namespace System.Net.Mail { if (Encoding.ASCII.Equals (enc)) return TransferEncoding.SevenBit; else if (Encoding.UTF8.CodePage == enc.CodePage || -#if !NET_2_1 +#if !MOBILE Encoding.Unicode.CodePage == enc.CodePage || Encoding.UTF32.CodePage == enc.CodePage #else Encoding.Unicode.CodePage == enc.CodePage diff --git a/mcs/class/System/System.Net.Mail/SmtpClient.cs b/mcs/class/System/System.Net.Mail/SmtpClient.cs index ff881b00bc..ca658c23d7 100644 --- a/mcs/class/System/System.Net.Mail/SmtpClient.cs +++ b/mcs/class/System/System.Net.Mail/SmtpClient.cs @@ -71,6 +71,7 @@ namespace System.Net.Mail { ICredentialsByHost credentials; string pickupDirectoryLocation; SmtpDeliveryMethod deliveryMethod; + SmtpDeliveryFormat deliveryFormat; bool enableSsl; #if SECURITY_DEP X509CertificateCollection clientCertificates; @@ -223,7 +224,15 @@ namespace System.Net.Mail { port = value; } } - + + public SmtpDeliveryFormat DeliveryFormat { + get { return deliveryFormat; } + set { + CheckState (); + deliveryFormat = value; + } + } + [MonoTODO] public ServicePoint ServicePoint { get { throw new NotImplementedException (); } diff --git a/mcs/class/System/System.Net.Mail/SmtpClient.platformnotsupported.cs b/mcs/class/System/System.Net.Mail/SmtpClient.platformnotsupported.cs new file mode 100644 index 0000000000..92ef97d96e --- /dev/null +++ b/mcs/class/System/System.Net.Mail/SmtpClient.platformnotsupported.cs @@ -0,0 +1,167 @@ +// +// System.Net.Mail.SmtpClient.cs +// +// Author: +// Rolf Bjarne Kvinge +// +// Copyright (C) 2016 Xamarin Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System.ComponentModel; +using System.Security.Cryptography.X509Certificates; +using System.Threading.Tasks; + +namespace System.Net.Mail { + public class SmtpClient + : IDisposable + { + const string EXCEPTION_MESSAGE = "System.Net.Mail.SmtpClient is not supported on the current platform."; + + public SmtpClient () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public SmtpClient (string host) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public SmtpClient (string host, int port) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + +#if SECURITY_DEP + [MonoTODO("Client certificates not used")] + public X509CertificateCollection ClientCertificates { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } +#endif + + public string TargetName { get; set; } + + public ICredentialsByHost Credentials { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public SmtpDeliveryMethod DeliveryMethod { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public bool EnableSsl { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public string Host { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public string PickupDirectoryLocation { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public int Port { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public SmtpDeliveryFormat DeliveryFormat { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public ServicePoint ServicePoint { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public int Timeout { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public bool UseDefaultCredentials { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + +#pragma warning disable 0067 // The event `System.Net.Mail.SmtpClient.SendCompleted' is never used + public event SendCompletedEventHandler SendCompleted; +#pragma warning restore 0067 + + public void Dispose () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + protected virtual void Dispose (bool disposing) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + protected void OnSendCompleted (AsyncCompletedEventArgs e) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void Send (MailMessage message) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void Send (string from, string to, string subject, string body) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public Task SendMailAsync (MailMessage message) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public Task SendMailAsync (string from, string recipients, string subject, string body) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void SendAsync (MailMessage message, object userToken) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void SendAsync (string from, string to, string subject, string body, object userToken) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void SendAsyncCancel () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + } +} + diff --git a/mcs/class/System/System.Net.NetworkInformation/NetworkChange.cs b/mcs/class/System/System.Net.NetworkInformation/NetworkChange.cs index 50e9009741..861d710f77 100644 --- a/mcs/class/System/System.Net.NetworkInformation/NetworkChange.cs +++ b/mcs/class/System/System.Net.NetworkInformation/NetworkChange.cs @@ -299,7 +299,7 @@ namespace System.Net.NetworkInformation { } } -#if MONOTOUCH +#if MONOTOUCH || MOBILE_STATIC [MonoTouch.MonoPInvokeCallback (typeof (SCNetworkReachabilityCallback))] #endif static void HandleCallback (IntPtr reachability, NetworkReachabilityFlags flags, IntPtr info) diff --git a/mcs/class/System/System.Net.NetworkInformation/NetworkInterface.cs b/mcs/class/System/System.Net.NetworkInformation/NetworkInterface.cs index ece698af2b..6e2ecd0ee5 100644 --- a/mcs/class/System/System.Net.NetworkInformation/NetworkInterface.cs +++ b/mcs/class/System/System.Net.NetworkInformation/NetworkInterface.cs @@ -615,6 +615,19 @@ namespace System.Net.NetworkInformation { string iface_operstate_path; string iface_flags_path; +#if MONODROID + [DllImport ("__Internal")] + protected static extern int _monodroid_get_android_api_level (); + + [DllImport ("__Internal")] + protected static extern bool _monodroid_get_network_interface_up_state (string ifname, ref bool is_up); + + [DllImport ("__Internal")] + protected static extern bool _monodroid_get_network_interface_supports_multicast (string ifname, ref bool supports_multicast); + + bool android_use_java_api; +#endif + internal string IfacePath { get { return iface_path; } } @@ -625,6 +638,9 @@ namespace System.Net.NetworkInformation { iface_path = "/sys/class/net/" + name + "/"; iface_operstate_path = iface_path + "operstate"; iface_flags_path = iface_path + "flags"; +#if MONODROID + android_use_java_api = _monodroid_get_android_api_level () >= 24; +#endif } public override IPInterfaceProperties GetIPProperties () @@ -643,6 +659,23 @@ namespace System.Net.NetworkInformation { public override OperationalStatus OperationalStatus { get { +#if MONODROID + if (android_use_java_api) { + // Starting from API 24 (Android 7 "Nougat") Android restricts access to many + // files in the /sys filesystem (see https://code.google.com/p/android/issues/detail?id=205565 + // for more information) and therefore we are forced to call into Java API in + // order to get the information. Alas, what we can obtain in this way is quite + // limited. In the case of OperationalStatus we can only determine whether the + // interface is up or down. There is a way to get more detailed information but + // it requires an instance of the Android Context class which is not available + // to us here. + bool is_up = false; + if (_monodroid_get_network_interface_up_state (Name, ref is_up)) + return is_up ? OperationalStatus.Up : OperationalStatus.Down; + else + return OperationalStatus.Unknown; + } +#endif if (!Directory.Exists (iface_path)) return OperationalStatus.Unknown; @@ -679,6 +712,17 @@ namespace System.Net.NetworkInformation { public override bool SupportsMulticast { get { +#if MONODROID + if (android_use_java_api) { + // Starting from API 24 (Android 7 "Nougat") Android restricts access to many + // files in the /sys filesystem (see https://code.google.com/p/android/issues/detail?id=205565 + // for more information) and therefore we are forced to call into Java API in + // order to get the information. + bool supports_multicast = false; + _monodroid_get_network_interface_supports_multicast (Name, ref supports_multicast); + return supports_multicast; + } +#endif if (!Directory.Exists (iface_path)) return false; diff --git a/mcs/class/System/System.Net.Security/EncryptionPolicy.cs b/mcs/class/System/System.Net.Security/EncryptionPolicy.cs index 4db75cc965..d58a0e261f 100644 --- a/mcs/class/System/System.Net.Security/EncryptionPolicy.cs +++ b/mcs/class/System/System.Net.Security/EncryptionPolicy.cs @@ -25,7 +25,6 @@ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -#if SECURITY_DEP && !MONO_FEATURE_NEW_TLS namespace System.Net.Security { public enum EncryptionPolicy @@ -35,4 +34,3 @@ namespace System.Net.Security NoEncryption } } -#endif diff --git a/mcs/class/System/System.Net.Security/LocalCertificateSelectionCallback.cs b/mcs/class/System/System.Net.Security/LocalCertificateSelectionCallback.cs index 9b77646d7b..f71585c0f0 100644 --- a/mcs/class/System/System.Net.Security/LocalCertificateSelectionCallback.cs +++ b/mcs/class/System/System.Net.Security/LocalCertificateSelectionCallback.cs @@ -28,7 +28,7 @@ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -#if SECURITY_DEP && !MONO_FEATURE_NEW_TLS +#if SECURITY_DEP using System.Security.Cryptography.X509Certificates; diff --git a/mcs/class/System/System.Net.Security/NegotiateStream.cs b/mcs/class/System/System.Net.Security/NegotiateStream.cs index ad9e3526ff..0ee2c7b825 100644 --- a/mcs/class/System/System.Net.Security/NegotiateStream.cs +++ b/mcs/class/System/System.Net.Security/NegotiateStream.cs @@ -148,6 +148,12 @@ namespace System.Net.Security throw new NotImplementedException (); } + [MonoTODO] + public virtual IAsyncResult BeginAuthenticateAsClient (NetworkCredential credential, ChannelBinding binding, string targetName, AsyncCallback asyncCallback, object asyncState) + { + throw new NotImplementedException (); + } + [MonoTODO] public virtual IAsyncResult BeginAuthenticateAsClient (NetworkCredential credential, string targetName, AsyncCallback asyncCallback, object asyncState) { @@ -160,6 +166,12 @@ namespace System.Net.Security throw new NotImplementedException (); } + [MonoTODO] + public virtual IAsyncResult BeginAuthenticateAsClient (NetworkCredential credential, ChannelBinding binding, string targetName, ProtectionLevel requiredProtectionLevel, TokenImpersonationLevel allowedImpersonationLevel, AsyncCallback asyncCallback, object asyncState) + { + throw new NotImplementedException (); + } + [MonoTODO] public override IAsyncResult BeginRead (byte[] buffer, int offset, int count, AsyncCallback asyncCallback, object asyncState) { @@ -172,12 +184,24 @@ namespace System.Net.Security throw new NotImplementedException (); } + [MonoTODO] + public virtual IAsyncResult BeginAuthenticateAsServer (NetworkCredential credential, ExtendedProtectionPolicy policy, ProtectionLevel requiredProtectionLevel, TokenImpersonationLevel requiredImpersonationLevel, AsyncCallback asyncCallback, object asyncState) + { + throw new NotImplementedException (); + } + [MonoTODO] public virtual IAsyncResult BeginAuthenticateAsServer (NetworkCredential credential, ProtectionLevel requiredProtectionLevel, TokenImpersonationLevel requiredImpersonationLevel, AsyncCallback asyncCallback, object asyncState) { throw new NotImplementedException (); } + [MonoTODO] + public virtual IAsyncResult BeginAuthenticateAsServer (ExtendedProtectionPolicy policy, AsyncCallback asyncCallback, object asyncState) + { + throw new NotImplementedException (); + } + [MonoTODO] public override IAsyncResult BeginWrite (byte[] buffer, int offset, int count, AsyncCallback asyncCallback, object asyncState) { @@ -196,6 +220,18 @@ namespace System.Net.Security throw new NotImplementedException (); } + [MonoTODO] + public virtual void AuthenticateAsClient (NetworkCredential credential, ChannelBinding binding, string targetName) + { + throw new NotImplementedException (); + } + + [MonoTODO] + public virtual void AuthenticateAsClient (NetworkCredential credential, ChannelBinding binding, string targetName, ProtectionLevel requiredProtectionLevel, TokenImpersonationLevel allowedImpersonationLevel) + { + throw new NotImplementedException (); + } + [MonoTODO] public virtual void AuthenticateAsClient (NetworkCredential credential, string targetName, ProtectionLevel requiredProtectionLevel, TokenImpersonationLevel allowedImpersonationLevel) { @@ -208,6 +244,18 @@ namespace System.Net.Security throw new NotImplementedException (); } + [MonoTODO] + public virtual void AuthenticateAsServer (ExtendedProtectionPolicy policy) + { + throw new NotImplementedException (); + } + + [MonoTODO] + public virtual void AuthenticateAsServer (NetworkCredential credential, ExtendedProtectionPolicy policy, ProtectionLevel requiredProtectionLevel, TokenImpersonationLevel requiredImpersonationLevel) + { + throw new NotImplementedException (); + } + [MonoTODO] public virtual void AuthenticateAsServer (NetworkCredential credential, ProtectionLevel requiredProtectionLevel, TokenImpersonationLevel requiredImpersonationLevel) { diff --git a/mcs/class/System/System.Net.Security/RemoteCertificateValidationCallback.cs b/mcs/class/System/System.Net.Security/RemoteCertificateValidationCallback.cs index 9238428b1f..3db9e6b4ad 100644 --- a/mcs/class/System/System.Net.Security/RemoteCertificateValidationCallback.cs +++ b/mcs/class/System/System.Net.Security/RemoteCertificateValidationCallback.cs @@ -28,8 +28,6 @@ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -#if !MONO_FEATURE_NEW_TLS - using System.Security.Cryptography.X509Certificates; namespace System.Net.Security @@ -40,4 +38,3 @@ namespace System.Net.Security X509Chain chain, SslPolicyErrors sslPolicyErrors); } -#endif diff --git a/mcs/class/System/System.Net.Security/SslPolicyErrors.cs b/mcs/class/System/System.Net.Security/SslPolicyErrors.cs index 5a88d88e8b..0da167c71b 100644 --- a/mcs/class/System/System.Net.Security/SslPolicyErrors.cs +++ b/mcs/class/System/System.Net.Security/SslPolicyErrors.cs @@ -25,7 +25,6 @@ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -#if !MONO_FEATURE_NEW_TLS namespace System.Net.Security { [Flags] @@ -37,4 +36,3 @@ namespace System.Net.Security RemoteCertificateChainErrors = 4, } } -#endif diff --git a/mcs/class/System/System.Net.Security/SslStream.cs b/mcs/class/System/System.Net.Security/SslStream.cs index 3e7320e3cd..bf483016db 100644 --- a/mcs/class/System/System.Net.Security/SslStream.cs +++ b/mcs/class/System/System.Net.Security/SslStream.cs @@ -24,7 +24,6 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#if !MONO_FEATURE_NEW_TLS #if SECURITY_DEP #if MONO_SECURITY_ALIAS @@ -410,5 +409,3 @@ namespace System.Net.Security } } #endif - -#endif diff --git a/mcs/class/System/System.Net.Security/SslStream.platformnotsupported.cs b/mcs/class/System/System.Net.Security/SslStream.platformnotsupported.cs new file mode 100644 index 0000000000..1d3f040c08 --- /dev/null +++ b/mcs/class/System/System.Net.Security/SslStream.platformnotsupported.cs @@ -0,0 +1,287 @@ +// +// SslStream.cs +// +// Author: +// Rolf Bjarne Kvinge +// +// Copyright (c) 2016 Xamarin, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System.IO; +using System.Security.Authentication; +using System.Security.Cryptography.X509Certificates; +using System.Threading.Tasks; + +namespace System.Net.Security +{ + public class SslStream : AuthenticatedStream + { + const string EXCEPTION_MESSAGE = "System.Net.Security.SslStream is not supported on the current platform."; + + public SslStream (Stream innerStream) + : this (innerStream, false, null, null) + { + } + + public SslStream (Stream innerStream, bool leaveInnerStreamOpen) + : this (innerStream, leaveInnerStreamOpen, null, null) + { + } + + public SslStream (Stream innerStream, bool leaveInnerStreamOpen, RemoteCertificateValidationCallback userCertificateValidationCallback) + : this (innerStream, leaveInnerStreamOpen, userCertificateValidationCallback, null) + { + } + + public SslStream (Stream innerStream, bool leaveInnerStreamOpen, RemoteCertificateValidationCallback userCertificateValidationCallback, LocalCertificateSelectionCallback userCertificateSelectionCallback) + : base (innerStream, leaveInnerStreamOpen) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public SslStream (Stream innerStream, bool leaveInnerStreamOpen, RemoteCertificateValidationCallback userCertificateValidationCallback, LocalCertificateSelectionCallback userCertificateSelectionCallback, EncryptionPolicy encryptionPolicy) + : this (innerStream, leaveInnerStreamOpen, userCertificateValidationCallback, userCertificateSelectionCallback) + { + } + + public virtual void AuthenticateAsClient (string targetHost) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public virtual void AuthenticateAsClient (string targetHost, X509CertificateCollection clientCertificates, SslProtocols enabledSslProtocols, bool checkCertificateRevocation) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public virtual IAsyncResult BeginAuthenticateAsClient (string targetHost, AsyncCallback asyncCallback, object asyncState) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public virtual IAsyncResult BeginAuthenticateAsClient (string targetHost, X509CertificateCollection clientCertificates, SslProtocols enabledSslProtocols, bool checkCertificateRevocation, AsyncCallback asyncCallback, object asyncState) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public virtual void EndAuthenticateAsClient (IAsyncResult asyncResult) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public virtual void AuthenticateAsServer (X509Certificate serverCertificate) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public virtual void AuthenticateAsServer (X509Certificate serverCertificate, bool clientCertificateRequired, SslProtocols enabledSslProtocols, bool checkCertificateRevocation) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public virtual IAsyncResult BeginAuthenticateAsServer (X509Certificate serverCertificate, AsyncCallback asyncCallback, object asyncState) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public virtual IAsyncResult BeginAuthenticateAsServer (X509Certificate serverCertificate, bool clientCertificateRequired, SslProtocols enabledSslProtocols, bool checkCertificateRevocation, AsyncCallback asyncCallback, object asyncState) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public virtual void EndAuthenticateAsServer (IAsyncResult asyncResult) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public TransportContext TransportContext { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public virtual Task AuthenticateAsClientAsync (string targetHost) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public virtual Task AuthenticateAsClientAsync (string targetHost, X509CertificateCollection clientCertificates, SslProtocols enabledSslProtocols, bool checkCertificateRevocation) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public virtual Task AuthenticateAsServerAsync (X509Certificate serverCertificate) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public virtual Task AuthenticateAsServerAsync (X509Certificate serverCertificate, bool clientCertificateRequired, SslProtocols enabledSslProtocols, bool checkCertificateRevocation) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override bool IsAuthenticated { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override bool IsMutuallyAuthenticated { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override bool IsEncrypted { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override bool IsSigned { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override bool IsServer { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public virtual SslProtocols SslProtocol { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public virtual bool CheckCertRevocationStatus { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public virtual X509Certificate LocalCertificate { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public virtual X509Certificate RemoteCertificate { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public virtual CipherAlgorithmType CipherAlgorithm { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public virtual int CipherStrength { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public virtual HashAlgorithmType HashAlgorithm { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public virtual int HashStrength { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public virtual ExchangeAlgorithmType KeyExchangeAlgorithm { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public virtual int KeyExchangeStrength { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override bool CanSeek { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override bool CanRead { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override bool CanTimeout { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override bool CanWrite { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override int ReadTimeout { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override int WriteTimeout { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override long Length { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override long Position { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override void SetLength (long value) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override long Seek (long offset, SeekOrigin origin) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override void Flush () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + protected override void Dispose (bool disposing) + { + } + + public override int Read (byte[] buffer, int offset, int count) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void Write (byte[] buffer) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override void Write (byte[] buffer, int offset, int count) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override IAsyncResult BeginRead (byte[] buffer, int offset, int count, AsyncCallback asyncCallback, object asyncState) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override int EndRead (IAsyncResult asyncResult) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override IAsyncResult BeginWrite (byte[] buffer, int offset, int count, AsyncCallback asyncCallback, object asyncState) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override void EndWrite (IAsyncResult asyncResult) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + } +} diff --git a/mcs/class/System/System.Net.Sockets/Socket.cs.REMOVED.git-id b/mcs/class/System/System.Net.Sockets/Socket.cs.REMOVED.git-id index a17948af49..e9476f3afe 100644 --- a/mcs/class/System/System.Net.Sockets/Socket.cs.REMOVED.git-id +++ b/mcs/class/System/System.Net.Sockets/Socket.cs.REMOVED.git-id @@ -1 +1 @@ -999ca900d5443337a86927d0d2ef2add4422f2b4 \ No newline at end of file +64363911e4072d3b513ab012ba99c8b2a99ce860 \ No newline at end of file diff --git a/mcs/class/System/System.Net.Sockets/SocketAsyncEventArgs.cs b/mcs/class/System/System.Net.Sockets/SocketAsyncEventArgs.cs index 8a768b0d57..419035efe1 100644 --- a/mcs/class/System/System.Net.Sockets/SocketAsyncEventArgs.cs +++ b/mcs/class/System/System.Net.Sockets/SocketAsyncEventArgs.cs @@ -61,13 +61,13 @@ namespace System.Net.Sockets private set; } - IList > _bufferList; + internal IList> m_BufferList; public IList> BufferList { - get { return _bufferList; } + get { return m_BufferList; } set { if (Buffer != null && value != null) throw new ArgumentException ("Buffer and BufferList properties cannot both be non-null."); - _bufferList = value; + m_BufferList = value; } } @@ -111,12 +111,10 @@ namespace System.Net.Sockets set; } -#if !NET_2_1 public TransmitFileOptions SendPacketsFlags { get; set; } -#endif [MonoTODO ("unused property")] public int SendPacketsSendSize { @@ -236,5 +234,43 @@ namespace System.Net.Sockets Buffer = buffer; } + + internal void StartOperationCommon (Socket socket) + { + current_socket = socket; + } + + internal void StartOperationWrapperConnect (MultipleConnectAsync args) + { + SetLastOperation (SocketAsyncOperation.Connect); + + //m_MultipleConnect = args; + } + + internal void FinishConnectByNameSyncFailure (Exception exception, int bytesTransferred, SocketFlags flags) + { + throw new NotImplementedException (); + } + + internal void FinishOperationAsyncFailure (Exception exception, int bytesTransferred, SocketFlags flags) + { + throw new NotImplementedException (); + } + + internal void FinishWrapperConnectSuccess (Socket connectSocket, int bytesTransferred, SocketFlags flags) + { + SetResults(SocketError.Success, bytesTransferred, flags); + current_socket = connectSocket; + + Complete (); + OnCompleted (this); + } + + internal void SetResults (SocketError socketError, int bytesTransferred, SocketFlags flags) + { + SocketError = socketError; + BytesTransferred = bytesTransferred; + SocketFlags = flags; + } } } diff --git a/mcs/class/Facades/System.Net.Sockets/SocketReceiveFromResult.cs b/mcs/class/System/System.Net.Sockets/SocketReceiveFromResult.cs similarity index 98% rename from mcs/class/Facades/System.Net.Sockets/SocketReceiveFromResult.cs rename to mcs/class/System/System.Net.Sockets/SocketReceiveFromResult.cs index 2add0e6daf..605948300d 100644 --- a/mcs/class/Facades/System.Net.Sockets/SocketReceiveFromResult.cs +++ b/mcs/class/System/System.Net.Sockets/SocketReceiveFromResult.cs @@ -26,6 +26,8 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // +#if NETSTANDARD + namespace System.Net.Sockets { public struct SocketReceiveFromResult @@ -33,4 +35,6 @@ namespace System.Net.Sockets public int ReceivedBytes; public EndPoint RemoteEndPoint; } -} \ No newline at end of file +} + +#endif diff --git a/mcs/class/Facades/System.Net.Sockets/SocketReceiveMessageFromResult.cs b/mcs/class/System/System.Net.Sockets/SocketReceiveMessageFromResult.cs similarity index 98% rename from mcs/class/Facades/System.Net.Sockets/SocketReceiveMessageFromResult.cs rename to mcs/class/System/System.Net.Sockets/SocketReceiveMessageFromResult.cs index ab5ed1022f..f06b339949 100644 --- a/mcs/class/Facades/System.Net.Sockets/SocketReceiveMessageFromResult.cs +++ b/mcs/class/System/System.Net.Sockets/SocketReceiveMessageFromResult.cs @@ -26,6 +26,8 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // +#if NETSTANDARD + namespace System.Net.Sockets { public struct SocketReceiveMessageFromResult @@ -35,4 +37,6 @@ namespace System.Net.Sockets public EndPoint RemoteEndPoint; public IPPacketInformation PacketInformation; } -} \ No newline at end of file +} + +#endif diff --git a/mcs/class/Facades/System.Net.Sockets/SocketTaskExtensions.cs b/mcs/class/System/System.Net.Sockets/SocketTaskExtensions.cs similarity index 99% rename from mcs/class/Facades/System.Net.Sockets/SocketTaskExtensions.cs rename to mcs/class/System/System.Net.Sockets/SocketTaskExtensions.cs index c0665fc070..33bb55a7b0 100644 --- a/mcs/class/Facades/System.Net.Sockets/SocketTaskExtensions.cs +++ b/mcs/class/System/System.Net.Sockets/SocketTaskExtensions.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#if NETSTANDARD + using System.Collections.Generic; using System.Threading.Tasks; @@ -247,4 +249,6 @@ namespace System.Net.Sockets state: socket); } } -} \ No newline at end of file +} + +#endif diff --git a/mcs/class/System/System.Net.Sockets/TcpClient.platformnotsupported.cs b/mcs/class/System/System.Net.Sockets/TcpClient.platformnotsupported.cs new file mode 100644 index 0000000000..dd69a398fe --- /dev/null +++ b/mcs/class/System/System.Net.Sockets/TcpClient.platformnotsupported.cs @@ -0,0 +1,191 @@ +// +// System.Net.Sockets.TcpClient.cs +// +// Author: +// Rolf Bjarne Kvinge +// +// Copyright (C) 2016 Xamarin Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Net; +using System.Threading.Tasks; + +namespace System.Net.Sockets +{ + public class TcpClient : IDisposable + { + const string EXCEPTION_MESSAGE = "System.Net.Sockets.TcpClient is not supported on the current platform."; + + public TcpClient () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public TcpClient (AddressFamily family) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public TcpClient (IPEndPoint localEP) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public TcpClient (string hostname, int port) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + protected bool Active { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public Socket Client { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public int Available { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public bool Connected { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public bool ExclusiveAddressUse { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public LingerOption LingerState { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public bool NoDelay { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public int ReceiveBufferSize { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public int ReceiveTimeout { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public int SendBufferSize { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public int SendTimeout { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public void Close () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void Connect (IPEndPoint remoteEP) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void Connect (IPAddress address, int port) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void Connect (string hostname, int port) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void Connect (IPAddress[] ipAddresses, int port) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void EndConnect (IAsyncResult asyncResult) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public IAsyncResult BeginConnect (IPAddress address, int port, AsyncCallback requestCallback, object state) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public IAsyncResult BeginConnect (IPAddress[] addresses, int port, AsyncCallback requestCallback, object state) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public IAsyncResult BeginConnect (string host, int port, AsyncCallback requestCallback, object state) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void Dispose () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + protected virtual void Dispose (bool disposing) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + ~TcpClient () + { + } + + public NetworkStream GetStream() + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public Task ConnectAsync (IPAddress address, int port) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public Task ConnectAsync (IPAddress[] addresses, int port) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public Task ConnectAsync (string host, int port) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + } +} diff --git a/mcs/class/System/System.Net.Sockets/TcpListener.cs b/mcs/class/System/System.Net.Sockets/TcpListener.cs index 8ab582e554..e8b8ec40e0 100644 --- a/mcs/class/System/System.Net.Sockets/TcpListener.cs +++ b/mcs/class/System/System.Net.Sockets/TcpListener.cs @@ -200,7 +200,29 @@ namespace System.Net.Sockets return client; } - + + public void AllowNatTraversal (bool allowed) + { + if (active) + throw new InvalidOperationException (SR.GetString (SR.net_tcplistener_mustbestopped)); + + if (allowed) + server.SetIPProtectionLevel (IPProtectionLevel.Unrestricted); + else + server.SetIPProtectionLevel (IPProtectionLevel.EdgeRestricted); + } + + public static TcpListener Create (int port) + { + if (port < 0 || port > 65535) + throw new ArgumentOutOfRangeException ("port"); + + TcpListener listener = new TcpListener (IPAddress.IPv6Any, port); + listener.Server.DualMode = true; + + return listener; + } + /// /// Destructor - stops the listener listening /// diff --git a/mcs/class/System/System.Net.Sockets/TcpListener.platformnotsupported.cs b/mcs/class/System/System.Net.Sockets/TcpListener.platformnotsupported.cs new file mode 100644 index 0000000000..7b64967345 --- /dev/null +++ b/mcs/class/System/System.Net.Sockets/TcpListener.platformnotsupported.cs @@ -0,0 +1,135 @@ +// +// System.Net.Sockets.TcpListener.cs +// +// Author: +// Rolf Bjarne Kvinge +// +// Copyright (C) 2016 Xamarin Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Net; +using System.Threading.Tasks; + +namespace System.Net.Sockets +{ + public class TcpListener + { + const string EXCEPTION_MESSAGE = "System.Net.Sockets.TcpListener is not supported on the current platform."; + + public TcpListener (int port) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public TcpListener (IPEndPoint localEP) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public TcpListener (IPAddress localaddr, int port) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + protected bool Active { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public EndPoint LocalEndpoint { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public Socket Server { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public bool ExclusiveAddressUse { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public Socket AcceptSocket () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public TcpClient AcceptTcpClient () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + ~TcpListener () + { + } + + public bool Pending () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void Start () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void Start (int backlog) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public IAsyncResult BeginAcceptSocket (AsyncCallback callback, object state) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public IAsyncResult BeginAcceptTcpClient (AsyncCallback callback, object state) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public Socket EndAcceptSocket (IAsyncResult asyncResult) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public TcpClient EndAcceptTcpClient (IAsyncResult asyncResult) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void Stop () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public Task AcceptSocketAsync () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public Task AcceptTcpClientAsync () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + } +} diff --git a/mcs/class/System/System.Net.Sockets/UdpClient.cs b/mcs/class/System/System.Net.Sockets/UdpClient.cs index ad3c4117f5..c82529b32b 100644 --- a/mcs/class/System/System.Net.Sockets/UdpClient.cs +++ b/mcs/class/System/System.Net.Sockets/UdpClient.cs @@ -125,6 +125,14 @@ namespace System.Net.Sockets socket.Bind (localEP); } + public void AllowNatTraversal (bool allowed) + { + if (allowed) + socket.SetIPProtectionLevel (IPProtectionLevel.Unrestricted); + else + socket.SetIPProtectionLevel (IPProtectionLevel.EdgeRestricted); + } + public void Close () { Dispose (); diff --git a/mcs/class/System/System.Net.Sockets/UdpClient.platformnotsupported.cs b/mcs/class/System/System.Net.Sockets/UdpClient.platformnotsupported.cs new file mode 100644 index 0000000000..953350146d --- /dev/null +++ b/mcs/class/System/System.Net.Sockets/UdpClient.platformnotsupported.cs @@ -0,0 +1,241 @@ +// +// System.Net.Sockets.UdpClient.cs +// +// Author: +// Rolf Bjarne Kvinge +// +// Copyright (C) 2016 Xamarin Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Threading.Tasks; + +namespace System.Net.Sockets +{ + public class UdpClient : IDisposable + { + const string EXCEPTION_MESSAGE = "System.Net.Sockets.UdpClient is not supported on the current platform."; + + public UdpClient () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public UdpClient(AddressFamily family) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public UdpClient (int port) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public UdpClient (IPEndPoint localEP) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public UdpClient (int port, AddressFamily family) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public UdpClient (string hostname, int port) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void Close () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void Connect (IPEndPoint endPoint) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void Connect (IPAddress addr, int port) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void Connect (string hostname, int port) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void DropMulticastGroup (IPAddress multicastAddr) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void DropMulticastGroup (IPAddress multicastAddr, int ifindex) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void JoinMulticastGroup (IPAddress multicastAddr) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void JoinMulticastGroup (int ifindex, IPAddress multicastAddr) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void JoinMulticastGroup (IPAddress multicastAddr, int timeToLive) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void JoinMulticastGroup (IPAddress multicastAddr, IPAddress localAddress) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public byte [] Receive (ref IPEndPoint remoteEP) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public int Send (byte [] dgram, int bytes) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public int Send (byte [] dgram, int bytes, IPEndPoint endPoint) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public int Send (byte [] dgram, int bytes, string hostname, int port) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public IAsyncResult BeginSend (byte[] datagram, int bytes, AsyncCallback requestCallback, object state) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public IAsyncResult BeginSend (byte[] datagram, int bytes, IPEndPoint endPoint, AsyncCallback requestCallback, object state) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public IAsyncResult BeginSend (byte[] datagram, int bytes, string hostname, int port, AsyncCallback requestCallback, object state) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public int EndSend (IAsyncResult asyncResult) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public IAsyncResult BeginReceive (AsyncCallback requestCallback, object state) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public byte[] EndReceive (IAsyncResult asyncResult, ref IPEndPoint remoteEP) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + protected bool Active { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public Socket Client { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public int Available { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public bool DontFragment { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public bool EnableBroadcast { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public bool ExclusiveAddressUse { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public bool MulticastLoopback { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public short Ttl { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public void Dispose () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + protected virtual void Dispose (bool disposing) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + ~UdpClient () + { + } + + public Task ReceiveAsync () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public Task SendAsync (byte[] datagram, int bytes) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public Task SendAsync (byte[] datagram, int bytes, IPEndPoint endPoint) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public Task SendAsync (byte[] datagram, int bytes, string hostname, int port) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + } +} diff --git a/mcs/class/System/System.Net.WebSockets/ClientWebSocket.platformnotsupported.cs b/mcs/class/System/System.Net.WebSockets/ClientWebSocket.platformnotsupported.cs new file mode 100644 index 0000000000..324ae42112 --- /dev/null +++ b/mcs/class/System/System.Net.WebSockets/ClientWebSocket.platformnotsupported.cs @@ -0,0 +1,98 @@ +// +// ClientWebSocket.cs +// +// Author: +// Rolf Bjarne Kvinge +// +// Copyright (C) 2016 Xamarin Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System.Threading; +using System.Threading.Tasks; + +namespace System.Net.WebSockets +{ + public class ClientWebSocket : WebSocket, IDisposable + { + const string EXCEPTION_MESSAGE = "System.Net.WebSockets.ClientWebSocket is not supported on the current platform."; + + public ClientWebSocket () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override void Dispose () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override void Abort () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public ClientWebSocketOptions Options { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override WebSocketState State { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override WebSocketCloseStatus? CloseStatus { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override string CloseStatusDescription { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override string SubProtocol { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public Task ConnectAsync (Uri uri, CancellationToken cancellationToken) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override Task SendAsync (ArraySegment buffer, WebSocketMessageType messageType, bool endOfMessage, CancellationToken cancellationToken) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override Task ReceiveAsync (ArraySegment buffer, CancellationToken cancellationToken) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override Task CloseAsync (WebSocketCloseStatus closeStatus, string statusDescription, CancellationToken cancellationToken) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override Task CloseOutputAsync (WebSocketCloseStatus closeStatus, string statusDescription, CancellationToken cancellationToken) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + } +} diff --git a/mcs/class/System/System.Net/AuthenticationManager.cs b/mcs/class/System/System.Net/AuthenticationManager.cs index e987c5bd55..98200b45b4 100644 --- a/mcs/class/System/System.Net/AuthenticationManager.cs +++ b/mcs/class/System/System.Net/AuthenticationManager.cs @@ -51,7 +51,7 @@ namespace System.Net return; modules = new ArrayList (); -#if NET_2_1 +#if MOBILE modules.Add (new NtlmClient ()); modules.Add (new DigestClient ()); modules.Add (new BasicClient ()); @@ -106,6 +106,13 @@ namespace System.Net } } + [MonoTODO] + internal static bool OSSupportsExtendedProtection { + get { + return false; + } + } + internal static void Clear () { EnsureModules (); diff --git a/mcs/class/System/System.Net/AuthenticationManager.platformnotsupported.cs b/mcs/class/System/System.Net/AuthenticationManager.platformnotsupported.cs new file mode 100644 index 0000000000..1572ce7b57 --- /dev/null +++ b/mcs/class/System/System.Net/AuthenticationManager.platformnotsupported.cs @@ -0,0 +1,77 @@ +// +// AuthenticationManager.cs +// +// Author: +// Rolf Bjarne Kvinge +// +// Copyright (c) 2016 Xamarin, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System.Collections; +using System.Collections.Specialized; + +namespace System.Net +{ + public class AuthenticationManager { + const string EXCEPTION_MESSAGE = "System.Net.AuthenticationManager is not supported on the current platform."; + + private AuthenticationManager () + { + } + + public static ICredentialPolicy CredentialPolicy { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public static StringDictionary CustomTargetNameDictionary { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public static IEnumerator RegisteredModules { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public static Authorization Authenticate (string challenge, WebRequest request, ICredentials credentials) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public static Authorization PreAuthenticate (WebRequest request, ICredentials credentials) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public static void Register (IAuthenticationModule authenticationModule) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public static void Unregister (IAuthenticationModule authenticationModule) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public static void Unregister (string authenticationScheme) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + } +} diff --git a/mcs/class/System/System.Net/CredentialCache.cs b/mcs/class/System/System.Net/CredentialCache.cs deleted file mode 100644 index 9978daa46d..0000000000 --- a/mcs/class/System/System.Net/CredentialCache.cs +++ /dev/null @@ -1,282 +0,0 @@ -// -// System.Net.CredentialCache.cs -// -// Author: -// Lawrence Pit (loz@cable.a2000.nl) -// - -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// - -using System; -using System.Collections; -using System.Runtime.Serialization; - -namespace System.Net { - public class CredentialCache : ICredentials, IEnumerable, ICredentialsByHost - { - static NetworkCredential empty = new NetworkCredential (String.Empty, String.Empty, String.Empty); - Hashtable cache; - Hashtable cacheForHost; - - public CredentialCache () - { - cache = new Hashtable (); - cacheForHost = new Hashtable (); - } - - [MonoTODO ("Need EnvironmentPermission implementation first")] - public static ICredentials DefaultCredentials { - get { - // This is used for NTLM, Kerberos and Negotiate under MS - return empty; - } - } - - // MS does might return a special ICredentials which does not allow getting the - // username/password information out of it for non-internal classes. - public static NetworkCredential DefaultNetworkCredentials { - get { return empty; } - } - - public NetworkCredential GetCredential (Uri uriPrefix, string authType) - { - int longestPrefix = -1; - NetworkCredential result = null; - - if (uriPrefix == null || authType == null) - return null; - - string absPath = uriPrefix.AbsolutePath; - absPath = absPath.Substring (0, absPath.LastIndexOf ('/')); - - IDictionaryEnumerator e = cache.GetEnumerator (); - while (e.MoveNext ()) { - CredentialCacheKey key = e.Key as CredentialCacheKey; - - if (key.Length <= longestPrefix) - continue; - - if (String.Compare (key.AuthType, authType, true) != 0) - continue; - - Uri cachedUri = key.UriPrefix; - - if (cachedUri.Scheme != uriPrefix.Scheme) - continue; - - if (cachedUri.Port != uriPrefix.Port) - continue; - - if (cachedUri.Host != uriPrefix.Host) - continue; - - if (!absPath.StartsWith (key.AbsPath)) - continue; - - longestPrefix = key.Length; - result = (NetworkCredential) e.Value; - } - - return result; - } - - public IEnumerator GetEnumerator () - { - return cache.Values.GetEnumerator (); - } - - public void Add (Uri uriPrefix, string authType, NetworkCredential cred) - { - if (uriPrefix == null) - throw new ArgumentNullException ("uriPrefix"); - - if (authType == null) - throw new ArgumentNullException ("authType"); - - // throws ArgumentException when same key already exists. - cache.Add (new CredentialCacheKey (uriPrefix, authType), cred); - } - - public void Remove (Uri uriPrefix, string authType) - { - if (uriPrefix == null) - throw new ArgumentNullException ("uriPrefix"); - - if (authType == null) - throw new ArgumentNullException ("authType"); - - cache.Remove (new CredentialCacheKey (uriPrefix, authType)); - } - - public NetworkCredential GetCredential (string host, int port, string authenticationType) - { - NetworkCredential result = null; - - if (host == null || port < 0 || authenticationType == null) - return null; - - IDictionaryEnumerator e = cacheForHost.GetEnumerator (); - while (e.MoveNext ()) { - CredentialCacheForHostKey key = e.Key as CredentialCacheForHostKey; - - if (String.Compare (key.AuthType, authenticationType, true) != 0) - continue; - - if (key.Host != host) - continue; - - if (key.Port != port) - continue; - - result = (NetworkCredential) e.Value; - } - - return result; - } - - public void Add (string host, int port, string authenticationType, NetworkCredential credential) - { - if (host == null) - throw new ArgumentNullException("host"); - - if (port < 0) - throw new ArgumentOutOfRangeException("port"); - - if (authenticationType == null) - throw new ArgumentOutOfRangeException("authenticationType"); - - cacheForHost.Add (new CredentialCacheForHostKey (host, port, authenticationType), credential); - } - - public void Remove (string host, int port, string authenticationType) - { - if (host == null) - return; - - if (authenticationType == null) - return; - - cacheForHost.Remove (new CredentialCacheForHostKey (host, port, authenticationType)); - } - - class CredentialCacheKey { - Uri uriPrefix; - string authType; - string absPath; - int len; - int hash; - - internal CredentialCacheKey (Uri uriPrefix, string authType) - { - this.uriPrefix = uriPrefix; - this.authType = authType; - - this.absPath = uriPrefix.AbsolutePath; - this.absPath = absPath.Substring (0, absPath.LastIndexOf ('/')); - - this.len = uriPrefix.AbsoluteUri.Length; - this.hash = uriPrefix.GetHashCode () - + authType.GetHashCode (); - } - - public int Length { - get { return len; } - } - - public string AbsPath { - get { return absPath; } - } - - public Uri UriPrefix { - get { return uriPrefix; } - } - - public string AuthType { - get { return authType; } - } - - public override int GetHashCode () - { - return hash; - } - - public override bool Equals (object obj) - { - CredentialCacheKey key = obj as CredentialCacheKey; - return ((key != null) && (this.hash == key.hash)); - } - - public override string ToString () - { - return absPath + " : " + authType + " : len=" + len; - } - } - - class CredentialCacheForHostKey { - string host; - int port; - string authType; - int hash; - - internal CredentialCacheForHostKey (string host, int port, string authType) - { - this.host = host; - this.port = port; - this.authType = authType; - - this.hash = host.GetHashCode () - + port.GetHashCode () - + authType.GetHashCode (); - } - - public string Host { - get { return host; } - } - - public int Port { - get { return port; } - } - - public string AuthType { - get { return authType; } - } - - public override int GetHashCode () - { - return hash; - } - - public override bool Equals (object obj) - { - CredentialCacheForHostKey key = obj as CredentialCacheForHostKey; - return ((key != null) && (this.hash == key.hash)); - } - - public override string ToString () - { - return host + " : " + authType; - } - } -} -} - - diff --git a/mcs/class/System/System.Net/Dns.cs b/mcs/class/System/System.Net/Dns.cs index 9045052ccf..806bfc119d 100644 --- a/mcs/class/System/System.Net/Dns.cs +++ b/mcs/class/System/System.Net/Dns.cs @@ -130,6 +130,9 @@ namespace System.Net { [Obsolete ("Use BeginGetHostEntry instead")] public static IAsyncResult BeginGetHostByName (string hostName, AsyncCallback requestCallback, object stateObject) { +#if FEATURE_NO_BSD_SOCKETS + throw new PlatformNotSupportedException ("System.Net.Dns:BeginGetHostByName is not supported on this platform."); +#else if (hostName == null) throw new ArgumentNullException ("hostName"); @@ -140,11 +143,15 @@ namespace System.Net { GetHostByNameCallback c = new GetHostByNameCallback (GetHostByName); return c.BeginInvoke (hostName, requestCallback, stateObject); +#endif // FEATURE_NO_BSD_SOCKETS } [Obsolete ("Use BeginGetHostEntry instead")] public static IAsyncResult BeginResolve (string hostName, AsyncCallback requestCallback, object stateObject) { +#if FEATURE_NO_BSD_SOCKETS + throw new PlatformNotSupportedException ("System.Net.Dns:BeginResolve is not supported on this platform."); +#else if (hostName == null) throw new ArgumentNullException ("hostName"); @@ -155,6 +162,7 @@ namespace System.Net { ResolveCallback c = new ResolveCallback (Resolve); return c.BeginInvoke (hostName, requestCallback, stateObject); +#endif // FEATURE_NO_BSD_SOCKETS } public static IAsyncResult BeginGetHostAddresses (string hostNameOrAddress, AsyncCallback requestCallback, object state) @@ -178,6 +186,9 @@ namespace System.Net { public static IAsyncResult BeginGetHostEntry (string hostNameOrAddress, AsyncCallback requestCallback, object stateObject) { +#if FEATURE_NO_BSD_SOCKETS + throw new PlatformNotSupportedException ("System.Net.Dns:GetHostEntry is not supported on this platform."); +#else if (hostNameOrAddress == null) throw new ArgumentNullException ("hostName"); if (hostNameOrAddress == "0.0.0.0" || hostNameOrAddress == "::0") @@ -193,10 +204,14 @@ namespace System.Net { GetHostEntryNameCallback c = new GetHostEntryNameCallback (GetHostEntry); return c.BeginInvoke (hostNameOrAddress, requestCallback, stateObject); +#endif // FEATURE_NO_BSD_SOCKETS } public static IAsyncResult BeginGetHostEntry (IPAddress address, AsyncCallback requestCallback, object stateObject) { +#if FEATURE_NO_BSD_SOCKETS + throw new PlatformNotSupportedException ("System.Net.Dns:BeginGetHostEntry is not supported on this platform."); +#else if (address == null) throw new ArgumentNullException ("address"); @@ -207,6 +222,7 @@ namespace System.Net { GetHostEntryIPCallback c = new GetHostEntryIPCallback (GetHostEntry); return c.BeginInvoke (address, requestCallback, stateObject); +#endif // FEATURE_NO_BSD_SOCKETS } [Obsolete ("Use EndGetHostEntry instead")] @@ -409,6 +425,10 @@ namespace System.Net { [Obsolete ("Use GetHostEntry instead")] public static IPHostEntry GetHostByName (string hostName) { +#if FEATURE_NO_BSD_SOCKETS + if (!string.IsNullOrEmpty (hostName)) + throw new PlatformNotSupportedException ("System.Net.Dns:GetHostByName is not supported on this platform."); +#endif // FEATURE_NO_BSD_SOCKETS if (hostName == null) throw new ArgumentNullException ("hostName"); string h_name; @@ -436,6 +456,9 @@ namespace System.Net { [Obsolete ("Use GetHostEntry instead")] public static IPHostEntry Resolve(string hostName) { +#if FEATURE_NO_BSD_SOCKETS + throw new PlatformNotSupportedException ("System.Net.Dns:Resolve is not supported on this platform."); +#else if (hostName == null) throw new ArgumentNullException ("hostName"); @@ -450,6 +473,7 @@ namespace System.Net { ret = GetHostByName(hostName); return ret; +#endif // FEATURE_NO_BSD_SOCKETS } public static Task GetHostAddressesAsync (string hostNameOrAddress) diff --git a/mcs/class/corlib/System.Diagnostics.Tracing/EventSourceException.cs b/mcs/class/System/System.Net/FtpRequestCreator.platformnotsupported.cs similarity index 74% rename from mcs/class/corlib/System.Diagnostics.Tracing/EventSourceException.cs rename to mcs/class/System/System.Net/FtpRequestCreator.platformnotsupported.cs index 3602e29e8c..ae365c2815 100644 --- a/mcs/class/corlib/System.Diagnostics.Tracing/EventSourceException.cs +++ b/mcs/class/System/System.Net/FtpRequestCreator.platformnotsupported.cs @@ -1,8 +1,8 @@ // -// EventSourceException.cs +// System.Net.FtpbRequestCreator.cs // // Authors: -// Alexander Köplinger +// Rolf Bjarne Kvinge // // Copyright (C) 2016 Xamarin Inc (http://www.xamarin.com) // @@ -26,25 +26,14 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -using System; - -namespace System.Diagnostics.Tracing +namespace System.Net { - public class EventSourceException : Exception + class FtpRequestCreator : IWebRequestCreate { - [MonoTODO] - public EventSourceException () - { - } - - [MonoTODO] - public EventSourceException (string message) - { - } - - [MonoTODO] - public EventSourceException (string message, Exception innerException) + internal const string EXCEPTION_MESSAGE = "System.Net.FtpRequestCreator is not supported on the current platform."; + public WebRequest Create (Uri uri) { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } } } diff --git a/mcs/class/System/System.Net/FtpWebRequest.cs b/mcs/class/System/System.Net/FtpWebRequest.cs index 1fbf80dc7c..c0ea1b5511 100644 --- a/mcs/class/System/System.Net/FtpWebRequest.cs +++ b/mcs/class/System/System.Net/FtpWebRequest.cs @@ -17,6 +17,7 @@ using MSI = Mono.Security.Interface; #endif using System; +using System.Globalization; using System.IO; using System.Net.Sockets; using System.Text; @@ -42,6 +43,7 @@ namespace System.Net NetworkCredential credentials; IPHostEntry hostEntry; IPEndPoint localEndPoint; + IPEndPoint remoteEndPoint; IWebProxy proxy; int timeout = 100000; int rwTimeout = 300000; @@ -65,7 +67,9 @@ namespace System.Net const string PasswordCommand = "PASS"; const string TypeCommand = "TYPE"; const string PassiveCommand = "PASV"; + const string ExtendedPassiveCommand = "EPSV"; const string PortCommand = "PORT"; + const string ExtendedPortCommand = "EPRT"; const string AbortCommand = "ABOR"; const string AuthCommand = "AUTH"; const string RestCommand = "REST"; @@ -185,7 +189,7 @@ namespace System.Net } } -#if !NET_2_1 +#if !MOBILE [MonoTODO] public static new RequestCachePolicy DefaultCachePolicy { @@ -401,6 +405,7 @@ namespace System.Net State = RequestState.Scheduled; Thread thread = new Thread (ProcessRequest); + thread.IsBackground = true; thread.Start (); } } @@ -452,6 +457,7 @@ namespace System.Net asyncResult = new FtpAsyncResult (callback, state); Thread thread = new Thread (ProcessRequest); + thread.IsBackground = true; thread.Start (); return asyncResult; @@ -775,14 +781,14 @@ namespace System.Net foreach (IPAddress address in hostEntry.AddressList) { sock = new Socket (address.AddressFamily, SocketType.Stream, ProtocolType.Tcp); - IPEndPoint remote = new IPEndPoint (address, requestUri.Port); + remoteEndPoint = new IPEndPoint (address, requestUri.Port); - if (!ServicePoint.CallEndPointDelegate (sock, remote)) { + if (!ServicePoint.CallEndPointDelegate (sock, remoteEndPoint)) { sock.Close (); sock = null; } else { try { - sock.Connect (remote); + sock.Connect (remoteEndPoint); localEndPoint = (IPEndPoint) sock.LocalEndPoint; break; } catch (SocketException exc) { @@ -837,52 +843,19 @@ namespace System.Net } // Probably we could do better having here a regex - Socket SetupPassiveConnection (string statusDescription) + Socket SetupPassiveConnection (string statusDescription, bool ipv6) { // Current response string string response = statusDescription; if (response.Length < 4) throw new WebException ("Cannot open passive data connection"); - - // Look for first digit after code - int i; - for (i = 3; i < response.Length && !Char.IsDigit (response [i]); i++) - ; - if (i >= response.Length) - throw new WebException ("Cannot open passive data connection"); - // Get six elements - string [] digits = response.Substring (i).Split (new char [] {','}, 6); - if (digits.Length != 6) - throw new WebException ("Cannot open passive data connection"); + int port = ipv6 ? GetPortV6 (response) : GetPortV4 (response); - // Clean non-digits at the end of last element - int j; - for (j = digits [5].Length - 1; j >= 0 && !Char.IsDigit (digits [5][j]); j--) - ; - if (j < 0) - throw new WebException ("Cannot open passive data connection"); - - digits [5] = digits [5].Substring (0, j + 1); - - IPAddress ip; - try { - ip = IPAddress.Parse (String.Join (".", digits, 0, 4)); - } catch (FormatException) { - throw new WebException ("Cannot open passive data connection"); - } - - // Get the port - int p1, p2, port; - if (!Int32.TryParse (digits [4], out p1) || !Int32.TryParse (digits [5], out p2)) - throw new WebException ("Cannot open passive data connection"); - - port = (p1 << 8) + p2; // p1 * 256 + p2 - //port = p1 * 256 + p2; if (port < IPEndPoint.MinPort || port > IPEndPoint.MaxPort) throw new WebException ("Cannot open passive data connection"); - IPEndPoint ep = new IPEndPoint (ip, port); + IPEndPoint ep = new IPEndPoint (remoteEndPoint.Address, port); Socket sock = new Socket (ep.AddressFamily, SocketType.Stream, ProtocolType.Tcp); try { sock.Connect (ep); @@ -894,6 +867,87 @@ namespace System.Net return sock; } + // GetPortV4, GetPortV6, FormatAddress and FormatAddressV6 are copied from referencesource + // TODO: replace FtpWebRequest completely. + private int GetPortV4(string responseString) + { + string [] parsedList = responseString.Split(new char [] {' ', '(', ',', ')'}); + + // We need at least the status code and the port + if (parsedList.Length <= 7) { + throw new FormatException(SR.GetString(SR.net_ftp_response_invalid_format, responseString)); + } + + int index = parsedList.Length-1; + // skip the last non-number token (e.g. terminating '.') +#if MONO + // the MS code expects \r\n here in parsedList[index], + // but we're stripping the EOL off earlier so the array contains + // an empty string here which would make Char.IsNumber throw + // TODO: this can be removed once we switch FtpWebRequest to referencesource + if (parsedList[index] == "" || !Char.IsNumber(parsedList[index], 0)) +#else + if (!Char.IsNumber(parsedList[index], 0)) +#endif + index--; + + int port = Convert.ToByte(parsedList[index--], NumberFormatInfo.InvariantInfo); + port = port | + (Convert.ToByte(parsedList[index--], NumberFormatInfo.InvariantInfo) << 8); + + return port; + } + + private int GetPortV6(string responseString) + { + int pos1 = responseString.LastIndexOf("("); + int pos2 = responseString.LastIndexOf(")"); + if (pos1 == -1 || pos2 <= pos1) + throw new FormatException(SR.GetString(SR.net_ftp_response_invalid_format, responseString)); + + // addressInfo will contain a string of format "||||" + string addressInfo = responseString.Substring(pos1+1, pos2-pos1-1); + + // Although RFC2428 recommends using "|" as the delimiter, + // It allows ASCII characters in range 33-126 inclusive. + // We should consider allowing the full range. + + string [] parsedList = addressInfo.Split(new char [] {'|'}); + if (parsedList.Length < 4) + throw new FormatException(SR.GetString(SR.net_ftp_response_invalid_format, responseString)); + + return Convert.ToInt32(parsedList[3], NumberFormatInfo.InvariantInfo); + } + + private String FormatAddress(IPAddress address, int Port ) + { + byte [] localAddressInBytes = address.GetAddressBytes(); + + // produces a string in FTP IPAddress/Port encoding (a1, a2, a3, a4, p1, p2), for sending as a parameter + // to the port command. + StringBuilder sb = new StringBuilder(32); + foreach (byte element in localAddressInBytes) { + sb.Append(element); + sb.Append(','); + } + sb.Append(Port / 256 ); + sb.Append(','); + sb.Append(Port % 256 ); + return sb.ToString(); + } + + private string FormatAddressV6(IPAddress address, int port) { + StringBuilder sb = new StringBuilder(43); // based on max size of IPv6 address + port + seperators + String addressString = address.ToString(); + sb.Append("|2|"); + sb.Append(addressString); + sb.Append('|'); + sb.Append(port.ToString(NumberFormatInfo.InvariantInfo)); + sb.Append('|'); + return sb.ToString(); + } + // + Exception CreateExceptionFromResponse (FtpStatus status) { FtpWebResponse ftpResponse = new FtpWebResponse (this, requestUri, method, status); @@ -932,18 +986,19 @@ namespace System.Net Socket InitDataConnection () { FtpStatus status; - + bool ipv6 = remoteEndPoint.AddressFamily == AddressFamily.InterNetworkV6; + if (usePassive) { - status = SendCommand (PassiveCommand); - if (status.StatusCode != FtpStatusCode.EnteringPassive) { + status = SendCommand (ipv6 ? ExtendedPassiveCommand : PassiveCommand); + if (status.StatusCode != (ipv6 ? (FtpStatusCode)229 : FtpStatusCode.EnteringPassive)) { // FtpStatusCode doesn't contain code 229 for EPSV so we need to cast... throw CreateExceptionFromResponse (status); } - return SetupPassiveConnection (status.StatusDescription); + return SetupPassiveConnection (status.StatusDescription, ipv6); } // Open a socket to listen the server's connection - Socket sock = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + Socket sock = new Socket (remoteEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); try { sock.Bind (new IPEndPoint (localEndPoint.Address, 0)); sock.Listen (1); // We only expect a connection from server @@ -955,12 +1010,10 @@ namespace System.Net } IPEndPoint ep = (IPEndPoint) sock.LocalEndPoint; - string ipString = ep.Address.ToString ().Replace ('.', ','); - int h1 = ep.Port >> 8; // ep.Port / 256 - int h2 = ep.Port % 256; - string portParam = ipString + "," + h1 + "," + h2; - status = SendCommand (PortCommand, portParam); + var portParam = ipv6 ? FormatAddressV6 (ep.Address, ep.Port) : FormatAddress (ep.Address, ep.Port); + + status = SendCommand (ipv6 ? ExtendedPortCommand : PortCommand, portParam); if (status.StatusCode != FtpStatusCode.CommandOK) { sock.Close (); diff --git a/mcs/class/System/System.Net/FtpWebRequest.platformnotsupported.cs b/mcs/class/System/System.Net/FtpWebRequest.platformnotsupported.cs new file mode 100644 index 0000000000..2bb79d77c0 --- /dev/null +++ b/mcs/class/System/System.Net/FtpWebRequest.platformnotsupported.cs @@ -0,0 +1,182 @@ +// +// System.Net.FtpWebRequest.cs +// +// Author: +// Rolf Bjarne Kvinge +// +// Copyright (C) 2016 Xamarin Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System.IO; +using System.Security.Cryptography.X509Certificates; + +namespace System.Net +{ + public sealed class FtpWebRequest : WebRequest + { + const string EXCEPTION_MESSAGE = "System.Net.FtpWebRequest is not supported on the current platform."; + + FtpWebRequest () + { + } + + public X509CertificateCollection ClientCertificates { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override string ConnectionGroupName { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override string ContentType { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override long ContentLength { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public long ContentOffset { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override ICredentials Credentials { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + +#if !MOBILE + public static new RequestCachePolicy DefaultCachePolicy { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } +#endif + + public bool EnableSsl { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override WebHeaderCollection Headers { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public bool KeepAlive { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override string Method { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override bool PreAuthenticate { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override IWebProxy Proxy { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public int ReadWriteTimeout { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public string RenameTo { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override Uri RequestUri { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public ServicePoint ServicePoint { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public bool UsePassive { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override bool UseDefaultCredentials { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public bool UseBinary { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override int Timeout { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override void Abort () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override IAsyncResult BeginGetResponse (AsyncCallback callback, object state) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override WebResponse EndGetResponse (IAsyncResult asyncResult) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override WebResponse GetResponse () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override IAsyncResult BeginGetRequestStream (AsyncCallback callback, object state) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override Stream EndGetRequestStream (IAsyncResult asyncResult) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override Stream GetRequestStream () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + } +} diff --git a/mcs/class/System/System.Net/FtpWebResponse.platformnotsupported.cs b/mcs/class/System/System.Net/FtpWebResponse.platformnotsupported.cs new file mode 100644 index 0000000000..cd4fa71cee --- /dev/null +++ b/mcs/class/System/System.Net/FtpWebResponse.platformnotsupported.cs @@ -0,0 +1,91 @@ +// +// System.Net.FtpWebResponse.cs +// +// Author: +// Rolf Bjarne Kvinge +// +// Copyright (C) 2016 Xamarin Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System.IO; + +namespace System.Net +{ + public class FtpWebResponse : WebResponse + { + const string EXCEPTION_MESSAGE = "System.Net.FtpWebResponse is not supported on the current platform."; + + FtpWebResponse () + { + } + + public override long ContentLength { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override WebHeaderCollection Headers { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override Uri ResponseUri { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public DateTime LastModified { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public string BannerMessage { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public string WelcomeMessage { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public string ExitMessage { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public FtpStatusCode StatusCode { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override bool SupportsHeaders { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public string StatusDescription { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override void Close () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override Stream GetResponseStream () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + } +} diff --git a/mcs/class/System/System.Net/GlobalProxySelection.cs b/mcs/class/System/System.Net/GlobalProxySelection.cs deleted file mode 100644 index 049f61ccad..0000000000 --- a/mcs/class/System/System.Net/GlobalProxySelection.cs +++ /dev/null @@ -1,83 +0,0 @@ -// -// System.Net.GlobalProxySelection -// -// Author: -// Lawrence Pit (loz@cable.a2000.nl) -// - -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// - -using System; -using System.Collections; -using System.Configuration; -using System.IO; -using System.Runtime.Serialization; -using System.Net.Configuration; - -namespace System.Net -{ - [ObsoleteAttribute("Use WebRequest.DefaultProxy instead")] - public class GlobalProxySelection - { - // Constructors - public GlobalProxySelection() { } - - // Properties - - public static IWebProxy Select { - get { return WebRequest.DefaultWebProxy; } - set { WebRequest.DefaultWebProxy = value; } - } - - // Methods - - public static IWebProxy GetEmptyWebProxy() - { - // must return a new one each time, as the credentials - // can be set - return new EmptyWebProxy (); - } - - // Internal Classes - - internal class EmptyWebProxy : IWebProxy { - private ICredentials credentials = null; - - internal EmptyWebProxy () { } - - public ICredentials Credentials { - get { return credentials; } - set { credentials = value; } - } - - public Uri GetProxy (Uri destination) - { - return destination; - } - - public bool IsBypassed (Uri host) - { - return true; // pass directly to host - } - } - } -} diff --git a/mcs/class/System/System.Net/HttpListener.cs b/mcs/class/System/System.Net/HttpListener.cs index 29afc0fd84..716229d8b5 100644 --- a/mcs/class/System/System.Net/HttpListener.cs +++ b/mcs/class/System/System.Net/HttpListener.cs @@ -42,6 +42,7 @@ using System.IO; using System.Collections; using System.Threading; using System.Threading.Tasks; +using System.Security.Authentication.ExtendedProtection; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; @@ -69,6 +70,12 @@ namespace System.Net { ArrayList wait_queue; // List wait_queue; Hashtable connections; + ServiceNameStore defaultServiceNames; + ExtendedProtectionPolicy extendedProtectionPolicy; + ExtendedProtectionSelector extendedProtectionSelectorDelegate; + + public delegate ExtendedProtectionPolicy ExtendedProtectionSelector (HttpListenerRequest request); + public HttpListener () { prefixes = new HttpListenerPrefixCollection (this); @@ -77,6 +84,8 @@ namespace System.Net { ctx_queue = new ArrayList (); wait_queue = new ArrayList (); auth_schemes = AuthenticationSchemes.Anonymous; + defaultServiceNames = new ServiceNameStore (); + extendedProtectionPolicy = new ExtendedProtectionPolicy (PolicyEnforcement.Never); } internal HttpListener (X509Certificate certificate, IMonoTlsProvider tlsProvider, MSI.MonoTlsSettings tlsSettings) @@ -146,6 +155,21 @@ namespace System.Net { } } + public ExtendedProtectionSelector ExtendedProtectionSelectorDelegate + { + get { return extendedProtectionSelectorDelegate; } + set { + CheckDisposed(); + if (value == null) + throw new ArgumentNullException (); + + if (!AuthenticationManager.OSSupportsExtendedProtection) + throw new PlatformNotSupportedException (SR.GetString (SR.security_ExtendedProtection_NoOSSupport)); + + extendedProtectionSelectorDelegate = value; + } + } + public bool IgnoreWriteExceptions { get { return ignore_write_exceptions; } set { @@ -169,6 +193,42 @@ namespace System.Net { } } + [MonoTODO] + public HttpListenerTimeoutManager TimeoutManager { + get { + throw new NotImplementedException (); + } + } + + [MonoTODO ("not used anywhere in the implementation")] + public ExtendedProtectionPolicy ExtendedProtectionPolicy + { + get { + return extendedProtectionPolicy; + } + set { + CheckDisposed (); + + if (value == null) + throw new ArgumentNullException ("value"); + + if (!AuthenticationManager.OSSupportsExtendedProtection && value.PolicyEnforcement == PolicyEnforcement.Always) + throw new PlatformNotSupportedException (SR.GetString(SR.security_ExtendedProtection_NoOSSupport)); + + if (value.CustomChannelBinding != null) + throw new ArgumentException (SR.GetString (SR.net_listener_cannot_set_custom_cbt), "CustomChannelBinding"); + + extendedProtectionPolicy = value; + } + } + + public ServiceNameCollection DefaultServiceNames + { + get { + return defaultServiceNames.ServiceNames; + } + } + // TODO: use this public string Realm { get { return realm; } diff --git a/mcs/class/System/System.Net/HttpListener.platformnotsupported.cs b/mcs/class/System/System.Net/HttpListener.platformnotsupported.cs new file mode 100644 index 0000000000..bffdfbc701 --- /dev/null +++ b/mcs/class/System/System.Net/HttpListener.platformnotsupported.cs @@ -0,0 +1,123 @@ +// +// System.Net.HttpListener +// +// Author: +// Rolf Bjarne Kvinge +// +// Copyright (C) 2016 Xamarin Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System.Threading.Tasks; + +namespace System.Net { + public sealed class HttpListener : IDisposable + { + internal const string EXCEPTION_MESSAGE = "System.Net.HttpListener is not supported on the current platform."; + + public HttpListener () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public AuthenticationSchemes AuthenticationSchemes { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public AuthenticationSchemeSelector AuthenticationSchemeSelectorDelegate { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public bool IgnoreWriteExceptions { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public bool IsListening { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public static bool IsSupported { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public HttpListenerPrefixCollection Prefixes { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public string Realm { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public bool UnsafeConnectionNtlmAuthentication { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public void Abort () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void Close () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public IAsyncResult BeginGetContext (AsyncCallback callback, Object state) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public HttpListenerContext EndGetContext (IAsyncResult asyncResult) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public HttpListenerContext GetContext () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void Start () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void Stop () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + void IDisposable.Dispose () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public Task GetContextAsync () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + } +} diff --git a/mcs/class/System/System.Net/HttpListenerContext.cs b/mcs/class/System/System.Net/HttpListenerContext.cs index d495e4af58..5a3a2f0f44 100644 --- a/mcs/class/System/System.Net/HttpListenerContext.cs +++ b/mcs/class/System/System.Net/HttpListenerContext.cs @@ -137,16 +137,25 @@ namespace System.Net { } } + [MonoTODO] public Task AcceptWebSocketAsync (string subProtocol) { throw new NotImplementedException (); } + [MonoTODO] + public Task AcceptWebSocketAsync (string subProtocol, TimeSpan keepAliveInterval) + { + throw new NotImplementedException (); + } + + [MonoTODO] public Task AcceptWebSocketAsync (string subProtocol, int receiveBufferSize, TimeSpan keepAliveInterval) { throw new NotImplementedException (); } + [MonoTODO] public Task AcceptWebSocketAsync (string subProtocol, int receiveBufferSize, TimeSpan keepAliveInterval, ArraySegment internalBuffer) { throw new NotImplementedException (); diff --git a/mcs/class/System/System.Net/HttpListenerContext.platformnotsupported.cs b/mcs/class/System/System.Net/HttpListenerContext.platformnotsupported.cs new file mode 100644 index 0000000000..4c729de26c --- /dev/null +++ b/mcs/class/System/System.Net/HttpListenerContext.platformnotsupported.cs @@ -0,0 +1,68 @@ +// +// System.Net.HttpListenerContext +// +// Author: +// Rolf Bjarne Kvinge +// +// Copyright (C) 2016 Xamarin Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System.Security.Principal; +using System.Threading.Tasks; +using System.Net.WebSockets; + +namespace System.Net { + public sealed class HttpListenerContext { + const string EXCEPTION_MESSAGE = "System.Net.HttpListenerContext is not supported on the current platform."; + + HttpListenerContext () + { + } + + public HttpListenerRequest Request { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public HttpListenerResponse Response { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public IPrincipal User { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public Task AcceptWebSocketAsync (string subProtocol) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public Task AcceptWebSocketAsync (string subProtocol, int receiveBufferSize, TimeSpan keepAliveInterval) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public Task AcceptWebSocketAsync (string subProtocol, int receiveBufferSize, TimeSpan keepAliveInterval, ArraySegment internalBuffer) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + } +} diff --git a/mcs/class/System/System.Net/HttpListenerPrefixCollection.platformnotsupported.cs b/mcs/class/System/System.Net/HttpListenerPrefixCollection.platformnotsupported.cs new file mode 100644 index 0000000000..e3566c2d75 --- /dev/null +++ b/mcs/class/System/System.Net/HttpListenerPrefixCollection.platformnotsupported.cs @@ -0,0 +1,93 @@ +// +// System.Net.HttpListenerPrefixCollection.cs +// +// Author: +// Rolf Bjarne Kvinge +// +// Copyright (C) 2016 Xamarin Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System.Collections; +using System.Collections.Generic; + +namespace System.Net { + public class HttpListenerPrefixCollection : ICollection, IEnumerable, IEnumerable + { + const string EXCEPTION_MESSAGE = "System.Net.HttpListenerPrefixCollection is not supported on the current platform."; + + HttpListenerPrefixCollection () + { + } + + public int Count { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public bool IsReadOnly { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public bool IsSynchronized { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public void Add (string uriPrefix) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void Clear () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public bool Contains (string uriPrefix) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void CopyTo (string [] array, int offset) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void CopyTo (Array array, int offset) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public IEnumerator GetEnumerator () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + IEnumerator IEnumerable.GetEnumerator () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public bool Remove (string uriPrefix) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + } +} diff --git a/mcs/class/System/System.Net/HttpListenerRequest.platformnotsupported.cs b/mcs/class/System/System.Net/HttpListenerRequest.platformnotsupported.cs new file mode 100644 index 0000000000..32560d96e2 --- /dev/null +++ b/mcs/class/System/System.Net/HttpListenerRequest.platformnotsupported.cs @@ -0,0 +1,180 @@ +// +// System.Net.HttpListenerRequest +// +// Author: +// Rolf Bjarne Kvinge +// +// Copyright (C) 2016 Xamarin Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System.Collections.Specialized; +using System.IO; +using System.Security.Cryptography.X509Certificates; +using System.Text; +using System.Threading.Tasks; + +namespace System.Net { + public sealed class HttpListenerRequest + { + const string EXCEPTION_MESSAGE = "System.Net.HttpListenerRequest is not supported on the current platform."; + + HttpListenerRequest () + { + } + + public string [] AcceptTypes { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public int ClientCertificateError { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public Encoding ContentEncoding { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public long ContentLength64 { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public string ContentType { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public CookieCollection Cookies { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public bool HasEntityBody { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public NameValueCollection Headers { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public string HttpMethod { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public Stream InputStream { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public bool IsAuthenticated { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public bool IsLocal { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public bool IsSecureConnection { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public bool KeepAlive { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public IPEndPoint LocalEndPoint { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public Version ProtocolVersion { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public NameValueCollection QueryString { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public string RawUrl { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public IPEndPoint RemoteEndPoint { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public Guid RequestTraceIdentifier { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public Uri Url { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public Uri UrlReferrer { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public string UserAgent { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public string UserHostAddress { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public string UserHostName { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public string [] UserLanguages { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public IAsyncResult BeginGetClientCertificate (AsyncCallback requestCallback, object state) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public X509Certificate2 EndGetClientCertificate (IAsyncResult asyncResult) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public X509Certificate2 GetClientCertificate () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public string ServiceName { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public TransportContext TransportContext { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public bool IsWebSocketRequest { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public Task GetClientCertificateAsync () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + } +} diff --git a/mcs/class/System/System.Net/HttpListenerResponse.cs b/mcs/class/System/System.Net/HttpListenerResponse.cs index 329c4a2c19..73aa6396b5 100644 --- a/mcs/class/System/System.Net/HttpListenerResponse.cs +++ b/mcs/class/System/System.Net/HttpListenerResponse.cs @@ -427,10 +427,10 @@ namespace System.Net { StreamWriter writer = new StreamWriter (ms, encoding, 256); writer.Write ("HTTP/{0} {1} {2}\r\n", version, status_code, status_description); - string headers_str = headers.ToString (); + string headers_str = FormatHeaders (headers); writer.Write (headers_str); writer.Flush (); - int preamble = (encoding.CodePage == 65001) ? 3 : encoding.GetPreamble ().Length; + int preamble = encoding.GetPreamble ().Length; if (output_stream == null) output_stream = context.Connection.GetResponseStream (); @@ -439,6 +439,24 @@ namespace System.Net { HeadersSent = true; } + static string FormatHeaders (WebHeaderCollection headers) + { + var sb = new StringBuilder(); + + for (int i = 0; i < headers.Count ; i++) { + string key = headers.GetKey (i); + if (WebHeaderCollection.AllowMultiValues (key)) { + foreach (string v in headers.GetValues (i)) { + sb.Append (key).Append (": ").Append (v).Append ("\r\n"); + } + } else { + sb.Append (key).Append (": ").Append (headers.Get (i)).Append ("\r\n"); + } + } + + return sb.Append("\r\n").ToString(); + } + static string CookieToClientString (Cookie cookie) { if (cookie.Name.Length == 0) @@ -499,64 +517,6 @@ namespace System.Net { cookies.Add (cookie); } } - - // do not inline into HttpListenerResponse as this recursively brings everything that's - // reachable by IDisposable.Dispose (and that's quite a lot in this case). - static class HttpListenerResponseHelper { - - internal static string GetStatusDescription (int code) - { - switch (code){ - case 100: return "Continue"; - case 101: return "Switching Protocols"; - case 102: return "Processing"; - case 200: return "OK"; - case 201: return "Created"; - case 202: return "Accepted"; - case 203: return "Non-Authoritative Information"; - case 204: return "No Content"; - case 205: return "Reset Content"; - case 206: return "Partial Content"; - case 207: return "Multi-Status"; - case 300: return "Multiple Choices"; - case 301: return "Moved Permanently"; - case 302: return "Found"; - case 303: return "See Other"; - case 304: return "Not Modified"; - case 305: return "Use Proxy"; - case 307: return "Temporary Redirect"; - case 400: return "Bad Request"; - case 401: return "Unauthorized"; - case 402: return "Payment Required"; - case 403: return "Forbidden"; - case 404: return "Not Found"; - case 405: return "Method Not Allowed"; - case 406: return "Not Acceptable"; - case 407: return "Proxy Authentication Required"; - case 408: return "Request Timeout"; - case 409: return "Conflict"; - case 410: return "Gone"; - case 411: return "Length Required"; - case 412: return "Precondition Failed"; - case 413: return "Request Entity Too Large"; - case 414: return "Request-Uri Too Long"; - case 415: return "Unsupported Media Type"; - case 416: return "Requested Range Not Satisfiable"; - case 417: return "Expectation Failed"; - case 422: return "Unprocessable Entity"; - case 423: return "Locked"; - case 424: return "Failed Dependency"; - case 500: return "Internal Server Error"; - case 501: return "Not Implemented"; - case 502: return "Bad Gateway"; - case 503: return "Service Unavailable"; - case 504: return "Gateway Timeout"; - case 505: return "Http Version Not Supported"; - case 507: return "Insufficient Storage"; - } - return ""; - } - } } #endif diff --git a/mcs/class/System/System.Net/HttpListenerResponse.platformnotsupported.cs b/mcs/class/System/System.Net/HttpListenerResponse.platformnotsupported.cs new file mode 100644 index 0000000000..97661d6398 --- /dev/null +++ b/mcs/class/System/System.Net/HttpListenerResponse.platformnotsupported.cs @@ -0,0 +1,150 @@ +// +// System.Net.HttpListenerResponse +// +// Author: +// Rolf Bjarne Kvinge +// +// Copyright (C) 2016 Xamarin Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System.IO; +using System.Text; + +namespace System.Net { + public sealed class HttpListenerResponse : IDisposable + { + const string EXCEPTION_MESSAGE = "System.Net.HttpListenerResponse is not supported on the current platform."; + + HttpListenerResponse () + { + } + + public Encoding ContentEncoding { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public long ContentLength64 { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public string ContentType { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public CookieCollection Cookies { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public WebHeaderCollection Headers { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public bool KeepAlive { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public Stream OutputStream { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public Version ProtocolVersion { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public string RedirectLocation { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public bool SendChunked { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public int StatusCode { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public string StatusDescription { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + void IDisposable.Dispose () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void Abort () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void AddHeader (string name, string value) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void AppendCookie (Cookie cookie) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void AppendHeader (string name, string value) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void Close () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void Close (byte [] responseEntity, bool willBlock) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void CopyFrom (HttpListenerResponse templateResponse) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void Redirect (string url) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void SetCookie (Cookie cookie) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + } +} diff --git a/mcs/class/System/System.Net/HttpListenerResponseHelper.cs b/mcs/class/System/System.Net/HttpListenerResponseHelper.cs new file mode 100644 index 0000000000..7fc3c11bee --- /dev/null +++ b/mcs/class/System/System.Net/HttpListenerResponseHelper.cs @@ -0,0 +1,88 @@ +// +// System.Net.HttpListenerResponseHelper +// +// Author: +// Gonzalo Paniagua Javier (gonzalo@novell.com) +// +// Copyright (c) 2005 Novell, Inc. (http://www.novell.com) +// Copyright (C) 2016 Xamarin Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +namespace System.Net { + // do not inline into HttpListenerResponse as this recursively brings everything that's + // reachable by IDisposable.Dispose (and that's quite a lot in this case). + static class HttpListenerResponseHelper { + + internal static string GetStatusDescription (int code) + { + switch (code){ + case 100: return "Continue"; + case 101: return "Switching Protocols"; + case 102: return "Processing"; + case 200: return "OK"; + case 201: return "Created"; + case 202: return "Accepted"; + case 203: return "Non-Authoritative Information"; + case 204: return "No Content"; + case 205: return "Reset Content"; + case 206: return "Partial Content"; + case 207: return "Multi-Status"; + case 300: return "Multiple Choices"; + case 301: return "Moved Permanently"; + case 302: return "Found"; + case 303: return "See Other"; + case 304: return "Not Modified"; + case 305: return "Use Proxy"; + case 307: return "Temporary Redirect"; + case 400: return "Bad Request"; + case 401: return "Unauthorized"; + case 402: return "Payment Required"; + case 403: return "Forbidden"; + case 404: return "Not Found"; + case 405: return "Method Not Allowed"; + case 406: return "Not Acceptable"; + case 407: return "Proxy Authentication Required"; + case 408: return "Request Timeout"; + case 409: return "Conflict"; + case 410: return "Gone"; + case 411: return "Length Required"; + case 412: return "Precondition Failed"; + case 413: return "Request Entity Too Large"; + case 414: return "Request-Uri Too Long"; + case 415: return "Unsupported Media Type"; + case 416: return "Requested Range Not Satisfiable"; + case 417: return "Expectation Failed"; + case 422: return "Unprocessable Entity"; + case 423: return "Locked"; + case 424: return "Failed Dependency"; + case 500: return "Internal Server Error"; + case 501: return "Not Implemented"; + case 502: return "Bad Gateway"; + case 503: return "Service Unavailable"; + case 504: return "Gateway Timeout"; + case 505: return "Http Version Not Supported"; + case 507: return "Insufficient Storage"; + } + return ""; + } + } +} diff --git a/mcs/class/System/System.Net/HttpListenerTimeoutManager.cs b/mcs/class/System/System.Net/HttpListenerTimeoutManager.cs index d7e008baa0..3467357963 100644 --- a/mcs/class/System/System.Net/HttpListenerTimeoutManager.cs +++ b/mcs/class/System/System.Net/HttpListenerTimeoutManager.cs @@ -30,6 +30,46 @@ namespace System.Net { public class HttpListenerTimeoutManager { + [MonoTODO] + public TimeSpan EntityBody + { + get { throw new NotImplementedException (); } + set { throw new NotImplementedException (); } + } + [MonoTODO] + public TimeSpan DrainEntityBody + { + get { throw new NotImplementedException (); } + set { throw new NotImplementedException (); } + } + + [MonoTODO] + public TimeSpan RequestQueue + { + get { throw new NotImplementedException (); } + set { throw new NotImplementedException (); } + } + + [MonoTODO] + public TimeSpan IdleConnection + { + get { throw new NotImplementedException (); } + set { throw new NotImplementedException (); } + } + + [MonoTODO] + public TimeSpan HeaderWait + { + get { throw new NotImplementedException (); } + set { throw new NotImplementedException (); } + } + + [MonoTODO] + public long MinSendBytesPerSecond + { + get { throw new NotImplementedException (); } + set { throw new NotImplementedException (); } + } } } \ No newline at end of file diff --git a/mcs/class/System/System.Net/HttpWebRequest.cs b/mcs/class/System/System.Net/HttpWebRequest.cs index 676448649b..a57c579250 100644 --- a/mcs/class/System/System.Net/HttpWebRequest.cs +++ b/mcs/class/System/System.Net/HttpWebRequest.cs @@ -133,7 +133,7 @@ namespace System.Net static HttpWebRequest () { defaultMaxResponseHeadersLength = 64 * 1024; -#if !NET_2_1 +#if !MOBILE NetConfig config = ConfigurationSettings.GetConfig ("system.net/settings") as NetConfig; if (config != null) { int x = config.MaxResponseHeadersLength; @@ -145,7 +145,7 @@ namespace System.Net #endif } -#if NET_2_1 +#if MOBILE public #else internal @@ -154,7 +154,7 @@ namespace System.Net { this.requestUri = uri; this.actualUri = uri; - this.proxy = GlobalProxySelection.Select; + this.proxy = InternalDefaultWebProxy; this.webHeaders = new WebHeaderCollection (WebHeaderCollectionType.HttpWebRequest); ThrowOnError = true; ResetAuthorization (); @@ -226,12 +226,12 @@ namespace System.Net internal set { actualUri = value; } // Used by Ftp+proxy } - public bool AllowAutoRedirect { + public virtual bool AllowAutoRedirect { get { return allowAutoRedirect; } set { this.allowAutoRedirect = value; } } - public bool AllowWriteStreamBuffering { + public virtual bool AllowWriteStreamBuffering { get { return allowBuffering; } set { allowBuffering = value; } } @@ -382,7 +382,7 @@ namespace System.Net SetSpecialHeaders(headerName, HttpProtocolUtils.date2string(dateTime)); } -#if !NET_2_1 +#if !MOBILE [MonoTODO] public static new RequestCachePolicy DefaultCachePolicy { @@ -918,6 +918,12 @@ namespace System.Net return EndGetRequestStream (asyncResult); } + [MonoTODO] + public Stream GetRequestStream (out TransportContext context) + { + throw new NotImplementedException (); + } + bool CheckIfForceWrite (SimpleAsyncResult result) { if (writeStream == null || writeStream.RequestWritten || !InternalAllowBuffering) @@ -1314,8 +1320,11 @@ namespace System.Net msg = "Error: " + status; wex = new WebException (msg, status); } else { - msg = String.Format ("Error: {0} ({1})", status, exc.Message); - wex = new WebException (msg, status, WebExceptionInternalStatus.RequestFatal, exc); + wex = exc as WebException; + if (wex == null) { + msg = String.Format ("Error: {0} ({1})", status, exc.Message); + wex = new WebException (msg, status, WebExceptionInternalStatus.RequestFatal, exc); + } } r.SetCompleted (false, wex); r.DoCallback (); @@ -1474,7 +1483,7 @@ namespace System.Net if (wce != null) { WebConnection cnc = wce.Connection; cnc.PriorityRequest = this; - ICredentials creds = !isProxy ? credentials : proxy.Credentials; + ICredentials creds = (!isProxy || proxy == null) ? credentials : proxy.Credentials; if (creds != null) { cnc.NtlmCredential = creds.GetCredential (requestUri, "NTLM"); cnc.UnsafeAuthenticatedConnectionSharing = unsafe_auth_blah; @@ -1531,7 +1540,7 @@ namespace System.Net return; } - bool isProxy = ProxyQuery && !proxy.IsBypassed (actualUri); + bool isProxy = ProxyQuery && proxy != null && !proxy.IsBypassed (actualUri); bool redirected; try { @@ -1793,6 +1802,22 @@ namespace System.Net } internal WebConnection StoredConnection; + +#region referencesource + internal static StringBuilder GenerateConnectionGroup(string connectionGroupName, bool unsafeConnectionGroup, bool isInternalGroup) + { + StringBuilder connectionLine = new StringBuilder(connectionGroupName); + + connectionLine.Append(unsafeConnectionGroup ? "U>" : "S>"); + + if (isInternalGroup) + { + connectionLine.Append("I>"); + } + + return connectionLine; + } +#endregion } } diff --git a/mcs/class/System/System.Net/HttpWebRequest.platformnotsupported.cs b/mcs/class/System/System.Net/HttpWebRequest.platformnotsupported.cs new file mode 100644 index 0000000000..3977c7bad9 --- /dev/null +++ b/mcs/class/System/System.Net/HttpWebRequest.platformnotsupported.cs @@ -0,0 +1,422 @@ +// +// System.Net.HttpWebRequest +// +// Author: +// Rolf Bjarne Kvinge +// +// Copyright (C) 2016 Xamarin Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System.IO; +using System.Net.Security; +using System.Runtime.Serialization; +using System.Security.Cryptography.X509Certificates; + +namespace System.Net +{ + [Serializable] + public class HttpWebRequest : WebRequest, ISerializable + { + internal const string EXCEPTION_MESSAGE = "System.Net.HttpWebRequest is not supported on the current platform."; + +#if MOBILE + public +#else + internal +#endif + HttpWebRequest (Uri uri) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + internal HttpWebRequest (Uri uri, object /* IMonoTlsProvider */ tlsProvider, object /* MonoTlsSettings */ settings = null) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + protected HttpWebRequest (SerializationInfo serializationInfo, StreamingContext streamingContext) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public string Accept { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public Uri Address { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public bool AllowAutoRedirect { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public bool AllowWriteStreamBuffering { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public virtual bool AllowReadStreamBuffering { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public DecompressionMethods AutomaticDecompression { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + internal bool InternalAllowBuffering { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public X509CertificateCollection ClientCertificates { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public string Connection { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override string ConnectionGroupName { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override long ContentLength { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + internal long InternalContentLength { + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override string ContentType { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public HttpContinueDelegate ContinueDelegate { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public virtual CookieContainer CookieContainer { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override ICredentials Credentials { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public DateTime Date { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + +#if !MOBILE + public static new RequestCachePolicy DefaultCachePolicy { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } +#endif + + public static int DefaultMaximumErrorResponseLength { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public string Expect { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public virtual bool HaveResponse { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override WebHeaderCollection Headers { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public string Host { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public DateTime IfModifiedSince { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public bool KeepAlive { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public int MaximumAutomaticRedirections { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public int MaximumResponseHeadersLength { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public static int DefaultMaximumResponseHeadersLength { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public int ReadWriteTimeout { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public int ContinueTimeout { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public string MediaType { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override string Method { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public bool Pipelined { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override bool PreAuthenticate { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public Version ProtocolVersion { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override IWebProxy Proxy { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public string Referer { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override Uri RequestUri { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public bool SendChunked { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public ServicePoint ServicePoint { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + internal ServicePoint ServicePointNoLock { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public virtual bool SupportsCookieContainer { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override int Timeout { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public string TransferEncoding { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override bool UseDefaultCredentials { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public string UserAgent { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public bool UnsafeAuthenticatedConnectionSharing { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + internal bool ExpectContinue { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + internal ServerCertValidationCallback ServerCertValidationCallback { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + internal Uri AuthUri { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public RemoteCertificateValidationCallback ServerCertificateValidationCallback { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public void AddRange (int range) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void AddRange (int from, int to) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void AddRange (string rangeSpecifier, int range) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void AddRange (string rangeSpecifier, int from, int to) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void AddRange (long range) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void AddRange (long from, long to) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void AddRange (string rangeSpecifier, long range) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public void AddRange (string rangeSpecifier, long from, long to) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override IAsyncResult BeginGetRequestStream (AsyncCallback callback, object state) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override Stream EndGetRequestStream (IAsyncResult asyncResult) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override Stream GetRequestStream() + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override IAsyncResult BeginGetResponse (AsyncCallback callback, object state) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override WebResponse EndGetResponse (IAsyncResult asyncResult) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public Stream EndGetRequestStream (IAsyncResult asyncResult, out TransportContext transportContext) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override WebResponse GetResponse() + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + internal bool FinishedReading { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + internal bool Aborted { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override void Abort () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + void ISerializable.GetObjectData (SerializationInfo serializationInfo, StreamingContext streamingContext) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + protected override void GetObjectData (SerializationInfo serializationInfo, StreamingContext streamingContext) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + internal void DoContinueDelegate (int statusCode, WebHeaderCollection headers) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + internal void SetWriteStreamError (WebExceptionStatus status, Exception exc) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + internal byte[] GetRequestHeaders () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + } +} diff --git a/mcs/class/System/System.Net/HttpWebResponse.cs b/mcs/class/System/System.Net/HttpWebResponse.cs index 6a73ae0f16..9f7daa6c45 100644 --- a/mcs/class/System/System.Net/HttpWebResponse.cs +++ b/mcs/class/System/System.Net/HttpWebResponse.cs @@ -106,7 +106,7 @@ namespace System.Net version = (Version) info.GetValue ("version", typeof (Version)); statusCode = (HttpStatusCode) info.GetValue ("statusCode", typeof (HttpStatusCode)); } - + // Properties public string CharacterSet { diff --git a/mcs/class/System/System.Net/HttpWebResponse.platformnotsupported.cs b/mcs/class/System/System.Net/HttpWebResponse.platformnotsupported.cs new file mode 100644 index 0000000000..300d5d4f60 --- /dev/null +++ b/mcs/class/System/System.Net/HttpWebResponse.platformnotsupported.cs @@ -0,0 +1,147 @@ +// +// System.Net.HttpWebResponse +// +// Author: +// Rolf Bjarne Kvinge +// +// Copyright (C) 2016 Xamarin Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System.IO; +using System.Runtime.Serialization; + +namespace System.Net +{ + [Serializable] + public class HttpWebResponse : WebResponse, ISerializable, IDisposable + { + const string EXCEPTION_MESSAGE = "System.Net.HttpWebResponse is not supported on the current platform."; + + [Obsolete ("Serialization is obsoleted for this type", false)] + protected HttpWebResponse (SerializationInfo serializationInfo, StreamingContext streamingContext) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public string CharacterSet { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public string ContentEncoding { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override long ContentLength { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override string ContentType { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public virtual CookieCollection Cookies { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override WebHeaderCollection Headers { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + [MonoTODO] + public override bool IsMutuallyAuthenticated { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public DateTime LastModified { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public virtual string Method { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public Version ProtocolVersion { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override Uri ResponseUri { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public string Server { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public virtual HttpStatusCode StatusCode { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public virtual string StatusDescription { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public override bool SupportsHeaders { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public string GetResponseHeader (string headerName) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + internal void ReadAll () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override Stream GetResponseStream () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + void ISerializable.GetObjectData (SerializationInfo serializationInfo, StreamingContext streamingContext) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + protected override void GetObjectData (SerializationInfo serializationInfo, StreamingContext streamingContext) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public override void Close () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + void IDisposable.Dispose () + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + protected override void Dispose (bool disposing) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + } +} diff --git a/mcs/class/System/System.Net/NetworkCredential.cs b/mcs/class/System/System.Net/NetworkCredential.cs deleted file mode 100644 index faba55dd4f..0000000000 --- a/mcs/class/System/System.Net/NetworkCredential.cs +++ /dev/null @@ -1,112 +0,0 @@ -// -// System.Net.NetworkCredential.cs -// -// Authors: Duncan Mak (duncan@ximian.com) -// Rolf Bjarne KVinge (rolf@xamarin.com) -// Marek Safar (marek.safar@gmail.com) -// -// (C) Ximian, Inc. -// Copyright (C) 2010 Novell, Inc (http://www.novell.com) -// Copyright (C) 2011, 2014 Xamarin Inc (http://www.xamarin.com) -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// - -using System.Security; - -namespace System.Net -{ - public class NetworkCredential : ICredentials - , ICredentialsByHost - { - // Fields - string userName; - string password; - string domain; - - SecureString securePassword; - - // Constructors - public NetworkCredential () - { - } - - public NetworkCredential (string userName, string password) - { - this.userName = userName; - this.password = password; - } - - public NetworkCredential (string userName, string password, string domain) - : this (userName, password) - { - this.domain = domain; - } - - public NetworkCredential (string userName, SecureString password) - { - this.userName = userName; - SecurePassword = password; - } - - public NetworkCredential (string userName, SecureString password, string domain) - : this (userName, password) - { - this.domain = domain; - } - // Properties - - public string Domain { - get { return domain ?? String.Empty; } - set { domain = value; } - } - - public string UserName { - get { return userName ?? String.Empty; } - set { userName = value; } - } - - public string Password { - get { return password ?? String.Empty; } - set { password = value; } - } - - public SecureString SecurePassword { - get { return securePassword; } - set { - if (value == null) { - securePassword = new SecureString (); - } else { - securePassword = value; - } - } - } - - public NetworkCredential GetCredential (Uri uri, string authType) - { - return this; - } - - public NetworkCredential GetCredential (string host, int port, string authenticationType) - { - return this; - } - } -} diff --git a/mcs/class/System/System.Net/ServicePoint.cs b/mcs/class/System/System.Net/ServicePoint.cs index 2ee8b0c074..953da503f1 100644 --- a/mcs/class/System/System.Net/ServicePoint.cs +++ b/mcs/class/System/System.Net/ServicePoint.cs @@ -505,6 +505,11 @@ namespace System.Net return true; } } + + internal Socket GetConnection(PooledStream PooledStream, object owner, bool async, out IPAddress address, ref Socket abortSocket, ref Socket abortSocket6) + { + throw new NotImplementedException (); + } } } diff --git a/mcs/class/System/System.Net/ServicePoint.platformnotsupported.cs b/mcs/class/System/System.Net/ServicePoint.platformnotsupported.cs new file mode 100644 index 0000000000..d744a55644 --- /dev/null +++ b/mcs/class/System/System.Net/ServicePoint.platformnotsupported.cs @@ -0,0 +1,127 @@ +// +// ServicePoint.cs +// +// Author: +// Rolf Bjarne Kvinge +// +// Copyright (c) 2016 Xamarin, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System.Net.Sockets; +using System.Security.Cryptography.X509Certificates; + +namespace System.Net +{ + public class ServicePoint + { + const string EXCEPTION_MESSAGE = "System.Net.ServicePoint is not supported on the current platform."; + + ServicePoint () {} + + public Uri Address { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + static Exception GetMustImplement () + { + return new NotImplementedException (); + } + + public BindIPEndPoint BindIPEndPointDelegate + { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public int ConnectionLeaseTimeout { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public int ConnectionLimit { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public string ConnectionName { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public int CurrentConnections { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public DateTime IdleSince { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public int MaxIdleTime { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public virtual Version ProtocolVersion { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public int ReceiveBufferSize { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public bool SupportsPipelining { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public bool Expect100Continue { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public bool UseNagleAlgorithm { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public void SetTcpKeepAlive (bool enabled, int keepAliveTime, int keepAliveInterval) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public bool CloseConnectionGroup (string connectionGroupName) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public X509Certificate Certificate { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public X509Certificate ClientCertificate { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + // For reference source + internal Socket GetConnection(PooledStream PooledStream, object owner, bool async, out IPAddress address, ref Socket abortSocket, ref Socket abortSocket6) + { + throw new NotImplementedException (); + } + } +} diff --git a/mcs/class/System/System.Net/ServicePointManager.cs b/mcs/class/System/System.Net/ServicePointManager.cs index abd23e6727..d379526e80 100644 --- a/mcs/class/System/System.Net/ServicePointManager.cs +++ b/mcs/class/System/System.Net/ServicePointManager.cs @@ -132,20 +132,20 @@ namespace System.Net // Fields public const int DefaultNonPersistentConnectionLimit = 4; -#if MONOTOUCH +#if MOBILE public const int DefaultPersistentConnectionLimit = 10; #else public const int DefaultPersistentConnectionLimit = 2; #endif -#if !NET_2_1 +#if !MOBILE const string configKey = "system.net/connectionManagement"; static ConnectionManagementData manager; #endif static ServicePointManager () { -#if !NET_2_1 +#if !MOBILE #if CONFIGURATION_DEP object cfg = ConfigurationManager.GetSection (configKey); ConnectionManagementSection s = cfg as ConnectionManagementSection; @@ -200,7 +200,7 @@ namespace System.Net throw new ArgumentOutOfRangeException ("value"); defaultConnectionLimit = value; -#if !NET_2_1 +#if !MOBILE if (manager != null) manager.Add ("*", defaultConnectionLimit); #endif @@ -256,6 +256,12 @@ namespace System.Net } } + [MonoTODO] + public static bool ReusePort { + get { return false; } + set { throw new NotImplementedException (); } + } + public static SecurityProtocolType SecurityProtocol { get { return _securityProtocol; } set { _securityProtocol = value; } @@ -280,6 +286,13 @@ namespace System.Net } } + [MonoTODO ("Always returns EncryptionPolicy.RequireEncryption.")] + public static EncryptionPolicy EncryptionPolicy { + get { + return EncryptionPolicy.RequireEncryption; + } + } + public static bool Expect100Continue { get { return expectContinue; } set { expectContinue = value; } @@ -294,6 +307,10 @@ namespace System.Net get { return false; } } + internal static bool DisableSendAuxRecord { + get { return false; } + } + // Methods public static void SetTcpKeepAlive (bool enabled, int keepAliveTime, int keepAliveInterval) { @@ -311,7 +328,7 @@ namespace System.Net public static ServicePoint FindServicePoint (Uri address) { - return FindServicePoint (address, GlobalProxySelection.Select); + return FindServicePoint (address, null); } public static ServicePoint FindServicePoint (string uriString, IWebProxy proxy) @@ -352,7 +369,7 @@ namespace System.Net throw new InvalidOperationException ("maximum number of service points reached"); int limit; -#if NET_2_1 +#if MOBILE limit = defaultConnectionLimit; #else string addr = address.ToString (); diff --git a/mcs/class/System/System.Net/ServicePointManager.platformnotsupported.cs b/mcs/class/System/System.Net/ServicePointManager.platformnotsupported.cs new file mode 100644 index 0000000000..49c02e5a75 --- /dev/null +++ b/mcs/class/System/System.Net/ServicePointManager.platformnotsupported.cs @@ -0,0 +1,129 @@ +// +// ServicePointManager.cs +// +// Author: +// Rolf Bjarne Kvinge +// +// Copyright (c) 2016 Xamarin, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System.Net.Security; + +namespace System.Net +{ + public partial class ServicePointManager { + const string EXCEPTION_MESSAGE = "System.Net.ServicePointManager is not supported on the current platform."; + + public const int DefaultNonPersistentConnectionLimit = 4; +#if MOBILE + public const int DefaultPersistentConnectionLimit = 10; +#else + public const int DefaultPersistentConnectionLimit = 2; +#endif + + private ServicePointManager () + { + } + + public static ICertificatePolicy CertificatePolicy { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public static bool CheckCertificateRevocationList { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public static int DefaultConnectionLimit { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public static int DnsRefreshTimeout { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public static bool EnableDnsRoundRobin { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public static int MaxServicePointIdleTime { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public static int MaxServicePoints { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public static bool ReusePort { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public static SecurityProtocolType SecurityProtocol { + get; + set; + } = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12; + + public static RemoteCertificateValidationCallback ServerCertificateValidationCallback { + get; + set; + } + + public static EncryptionPolicy EncryptionPolicy { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public static bool Expect100Continue { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public static bool UseNagleAlgorithm { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public static void SetTcpKeepAlive (bool enabled, int keepAliveTime, int keepAliveInterval) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public static ServicePoint FindServicePoint (Uri address) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public static ServicePoint FindServicePoint (string uriString, IWebProxy proxy) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public static ServicePoint FindServicePoint (Uri address, IWebProxy proxy) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + } +} diff --git a/mcs/class/System/System.Net/WebConnection.cs b/mcs/class/System/System.Net/WebConnection.cs index 28d89a6065..83373052dd 100644 --- a/mcs/class/System/System.Net/WebConnection.cs +++ b/mcs/class/System/System.Net/WebConnection.cs @@ -257,14 +257,16 @@ namespace System.Net connect_request.Credentials = creds; } - for (int i = 0; i < challenge.Length; i++) { - var auth = AuthenticationManager.Authenticate (challenge [i], connect_request, creds); - if (auth == null) - continue; - ntlm = (auth.ModuleAuthenticationType == "NTLM"); - sb.Append ("\r\nProxy-Authorization: "); - sb.Append (auth.Message); - break; + if (creds != null) { + for (int i = 0; i < challenge.Length; i++) { + var auth = AuthenticationManager.Authenticate (challenge [i], connect_request, creds); + if (auth == null) + continue; + ntlm = (auth.ModuleAuthenticationType == "NTLM"); + sb.Append ("\r\nProxy-Authorization: "); + sb.Append (auth.Message); + break; + } } } @@ -292,11 +294,14 @@ namespace System.Net } Data.StatusCode = status; - Data.Challenge = result.GetValues ("Proxy-Authentic"); + Data.Challenge = result.GetValues ("Proxy-Authenticate"); + Data.Headers = result; return false; - } else if (status != 200) { - string msg = String.Format ("The remote server returned a {0} status code.", status); - HandleError (WebExceptionStatus.SecureChannelFailure, null, msg); + } + + if (status != 200) { + Data.StatusCode = status; + Data.Headers = result; return false; } @@ -368,6 +373,9 @@ namespace System.Net } status = (int)UInt32.Parse (parts [1]); + if (parts.Length >= 3) + Data.StatusDescription = String.Join (" ", parts, 2, parts.Length - 2); + gotStatus = true; } } @@ -670,7 +678,7 @@ namespace System.Net var value = s.Substring (pos_s + 1).Trim (); var h = data.Headers; - if (h.AllowMultiValues (header)) { + if (WebHeaderCollection.AllowMultiValues (header)) { h.AddInternal (header, value); } else { h.SetInternal (header, value); @@ -736,6 +744,15 @@ namespace System.Net goto retry; Exception cnc_exc = connect_exception; + if (cnc_exc == null && (Data.StatusCode == 401 || Data.StatusCode == 407)) { + st = WebExceptionStatus.ProtocolError; + if (Data.Headers == null) + Data.Headers = new WebHeaderCollection (); + + var webResponse = new HttpWebResponse (sPoint.Address, "CONNECT", Data, null); + cnc_exc = new WebException (Data.StatusCode == 407 ? "(407) Proxy Authentication Required" : "(401) Unauthorized", null, st, webResponse); + } + connect_exception = null; request.SetWriteStreamError (st, cnc_exc); Close (true); @@ -896,6 +913,8 @@ namespace System.Net { Stream s = null; lock (this) { + if (request.Aborted) + throw new WebException ("Request aborted", WebExceptionStatus.RequestCanceled); if (Data.request != request) throw new ObjectDisposedException (typeof (NetworkStream).FullName); if (nstream == null) diff --git a/mcs/class/System/System.Net/WebProxy.cs b/mcs/class/System/System.Net/WebProxy.cs deleted file mode 100644 index 365535a056..0000000000 --- a/mcs/class/System/System.Net/WebProxy.cs +++ /dev/null @@ -1,252 +0,0 @@ -// -// System.Net.WebProxy.cs -// -// Authors: -// Lawrence Pit (loz@cable.a2000.nl) -// Andreas Nahr (ClassDevelopment@A-SoftTech.com) -// - -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// - -using System; -using System.Collections; -using System.Globalization; -using System.Runtime.Serialization; -using System.Text.RegularExpressions; - -namespace System.Net -{ - [Serializable] - public class WebProxy : IWebProxy, ISerializable - { - Uri address; - bool bypassOnLocal; - ArrayList bypassList; - ICredentials credentials; - bool useDefaultCredentials; - - // Constructors - - public WebProxy () - : this ((Uri) null, false, null, null) {} - - public WebProxy (string address) - : this (ToUri (address), false, null, null) {} - - public WebProxy (Uri address) - : this (address, false, null, null) {} - - public WebProxy (string address, bool bypassOnLocal) - : this (ToUri (address), bypassOnLocal, null, null) {} - - public WebProxy (string host, int port) - : this (new Uri ("http://" + host + ":" + port)) {} - - public WebProxy (Uri address, bool bypassOnLocal) - : this (address, bypassOnLocal, null, null) {} - - public WebProxy (string address, bool bypassOnLocal, string [] bypassList) - : this (ToUri (address), bypassOnLocal, bypassList, null) {} - - public WebProxy (Uri address, bool bypassOnLocal, string [] bypassList) - : this (address, bypassOnLocal, bypassList, null) {} - - public WebProxy (string address, bool bypassOnLocal, string [] bypassList, - ICredentials credentials) - : this (ToUri (address), bypassOnLocal, bypassList, credentials) {} - - public WebProxy (Uri address, bool bypassOnLocal, - string[] bypassList, ICredentials credentials) - { - this.address = address; - this.bypassOnLocal = bypassOnLocal; - if (bypassList != null) - this.bypassList = new ArrayList (bypassList); - this.credentials = credentials; - CheckBypassList (); - } - - protected WebProxy (SerializationInfo serializationInfo, StreamingContext streamingContext) - { - this.address = (Uri) serializationInfo.GetValue ("_ProxyAddress", typeof (Uri)); - this.bypassOnLocal = serializationInfo.GetBoolean ("_BypassOnLocal"); - this.bypassList = (ArrayList) serializationInfo.GetValue ("_BypassList", typeof (ArrayList)); - this.useDefaultCredentials = serializationInfo.GetBoolean ("_UseDefaultCredentials"); - this.credentials = null; - CheckBypassList (); - } - - // Properties - public Uri Address { - get { return address; } - set { address = value; } - } - - public ArrayList BypassArrayList { - get { - if (bypassList == null) - bypassList = new ArrayList (); - return bypassList; - } - } - - public string [] BypassList { - get { return (string []) BypassArrayList.ToArray (typeof (string)); } - set { - if (value == null) - throw new ArgumentNullException (); - bypassList = new ArrayList (value); - CheckBypassList (); - } - } - - public bool BypassProxyOnLocal { - get { return bypassOnLocal; } - set { bypassOnLocal = value; } - } - - public ICredentials Credentials { - get { return credentials; } - set { credentials = value; } - } - - [MonoTODO ("Does not affect Credentials, since CredentialCache.DefaultCredentials is not implemented.")] - public bool UseDefaultCredentials { - get { return useDefaultCredentials; } - set { useDefaultCredentials = value; } - } - - // Methods - [Obsolete ("This method has been deprecated", false)] - [MonoTODO("Can we get this info under windows from the system?")] - public static WebProxy GetDefaultProxy () - { - // Select gets a WebProxy from config files, if available. - IWebProxy p = GlobalProxySelection.Select; - if (p is WebProxy) - return (WebProxy) p; - - return new WebProxy (); - } - - public Uri GetProxy (Uri destination) - { - if (IsBypassed (destination)) - return destination; - - return address; - } - - public bool IsBypassed (Uri host) - { - if (host == null) - throw new ArgumentNullException ("host"); - - if (host.IsLoopback && bypassOnLocal) - return true; - - if (address == null) - return true; - - string server = host.Host; - if (bypassOnLocal && server.IndexOf ('.') == -1) - return true; - - // LAMESPEC - if (!bypassOnLocal) { - if (String.Compare (server, "localhost", true, CultureInfo.InvariantCulture) == 0) - return true; - if (String.Compare (server, "loopback", true, CultureInfo.InvariantCulture) == 0) - return true; - - IPAddress addr = null; - if (IPAddress.TryParse (server, out addr) && IPAddress.IsLoopback (addr)) - return true; - } - - if (bypassList == null || bypassList.Count == 0) - return false; - - try { - string hostStr = host.Scheme + "://" + host.Authority; - int i = 0; - for (; i < bypassList.Count; i++) { - Regex regex = new Regex ((string) bypassList [i], - // TODO: RegexOptions.Compiled | // not implemented yet by Regex - RegexOptions.IgnoreCase | - RegexOptions.Singleline); - - if (regex.IsMatch (hostStr)) - break; - } - - if (i == bypassList.Count) - return false; - - // continue checking correctness of regular expressions.. - // will throw expression when an invalid one is found - for (; i < bypassList.Count; i++) - new Regex ((string) bypassList [i]); - - return true; - } catch (ArgumentException) { - return false; - } - } - - protected virtual void GetObjectData (SerializationInfo serializationInfo, StreamingContext streamingContext) - { - serializationInfo.AddValue ("_BypassOnLocal", bypassOnLocal); - serializationInfo.AddValue ("_ProxyAddress", address); - serializationInfo.AddValue ("_BypassList", bypassList); - serializationInfo.AddValue ("_UseDefaultCredentials", UseDefaultCredentials); - } - - void ISerializable.GetObjectData (SerializationInfo serializationInfo, - StreamingContext streamingContext) - { - GetObjectData (serializationInfo, streamingContext); - } - - // Private Methods - // this compiles the regular expressions, and will throw - // an exception when an invalid one is found. - void CheckBypassList () - { - if (bypassList == null) - return; - for (int i = 0; i < bypassList.Count; i++) - new Regex ((string) bypassList [i]); - } - - static Uri ToUri (string address) - { - if (address == null) - return null; - - if (address.IndexOf ("://", StringComparison.Ordinal) == -1) - address = "http://" + address; - - return new Uri (address); - } - } -} diff --git a/mcs/class/System/System.Net/WebRequest.cs b/mcs/class/System/System.Net/WebRequest.cs deleted file mode 100644 index fd450c8665..0000000000 --- a/mcs/class/System/System.Net/WebRequest.cs +++ /dev/null @@ -1,548 +0,0 @@ -// -// System.Net.WebRequest -// -// Authors: -// Lawrence Pit (loz@cable.a2000.nl) -// Marek Safar (marek.safar@gmail.com) -// -// Copyright 2011 Xamarin Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// - -using System; -using System.Collections; -using System.Collections.Specialized; -using System.Configuration; -using System.IO; -using System.Reflection; -using System.Runtime.Serialization; -using System.Globalization; -using System.Net.Configuration; -using System.Net.Security; -using System.Net.Cache; -using System.Security.Principal; -using System.Threading.Tasks; -using System.Text.RegularExpressions; -using Mono.Net; - -#if NET_2_1 -using ConfigurationException = System.ArgumentException; - -namespace System.Net.Configuration { - class Dummy {} -} -#endif - -namespace System.Net -{ - [Serializable] - public abstract class WebRequest : MarshalByRefObject, ISerializable { - static HybridDictionary prefixes = new HybridDictionary (); - static bool isDefaultWebProxySet; - static IWebProxy defaultWebProxy; - static RequestCachePolicy defaultCachePolicy; - - internal const int DefaultTimeout = 100000; - - static WebRequest () - { -#if MOBILE - IWebRequestCreate http = new HttpRequestCreator (); - RegisterPrefix ("http", http); - RegisterPrefix ("https", http); - RegisterPrefix ("file", new FileWebRequestCreator ()); - RegisterPrefix ("ftp", new FtpRequestCreator ()); -#else - #if CONFIGURATION_DEP - object cfg = ConfigurationManager.GetSection ("system.net/webRequestModules"); - WebRequestModulesSection s = cfg as WebRequestModulesSection; - if (s != null) { - foreach (WebRequestModuleElement el in - s.WebRequestModules) - AddPrefix (el.Prefix, el.Type); - return; - } - #endif - ConfigurationSettings.GetConfig ("system.net/webRequestModules"); -#endif - } - - protected WebRequest () - { - } - - protected WebRequest (SerializationInfo serializationInfo, StreamingContext streamingContext) - { - } - - static Exception GetMustImplement () - { - return new NotImplementedException ("This method must be implemented in derived classes"); - } - - // Properties - - private AuthenticationLevel authentication_level = AuthenticationLevel.MutualAuthRequested; - - public AuthenticationLevel AuthenticationLevel - { - get { - return(authentication_level); - } - set { - authentication_level = value; - } - } - - public virtual string ConnectionGroupName { - get { throw GetMustImplement (); } - set { throw GetMustImplement (); } - } - - public virtual long ContentLength { - get { throw GetMustImplement (); } - set { throw GetMustImplement (); } - } - - public virtual string ContentType { - get { throw GetMustImplement (); } - set { throw GetMustImplement (); } - } - - public virtual ICredentials Credentials { - get { throw GetMustImplement (); } - set { throw GetMustImplement (); } - } - - [MonoTODO ("Implement the caching system. Currently always returns a policy with the NoCacheNoStore level")] - public virtual RequestCachePolicy CachePolicy - { - get { return DefaultCachePolicy; } - set { - } - } - - public static RequestCachePolicy DefaultCachePolicy { - get { - return defaultCachePolicy ?? (defaultCachePolicy = new HttpRequestCachePolicy (HttpRequestCacheLevel.NoCacheNoStore)); - } - set { - throw GetMustImplement (); - } - } - - public virtual WebHeaderCollection Headers { - get { throw GetMustImplement (); } - set { throw GetMustImplement (); } - } - - - public virtual string Method { - get { throw GetMustImplement (); } - set { throw GetMustImplement (); } - } - - public virtual bool PreAuthenticate { - get { throw GetMustImplement (); } - set { throw GetMustImplement (); } - } - - public virtual IWebProxy Proxy { - get { throw GetMustImplement (); } - set { throw GetMustImplement (); } - } - - public virtual Uri RequestUri { - get { throw GetMustImplement (); } - } - - public virtual int Timeout { - get { throw GetMustImplement (); } - set { throw GetMustImplement (); } - } - - public virtual bool UseDefaultCredentials - { - get { - throw GetMustImplement (); - } - set { - throw GetMustImplement (); - } - } - - public TokenImpersonationLevel ImpersonationLevel { get; set; } - -// volatile static IWebProxy proxy; - static readonly object lockobj = new object (); - - public static IWebProxy DefaultWebProxy { - get { - if (!isDefaultWebProxySet) { - lock (lockobj) { - if (defaultWebProxy == null) - defaultWebProxy = GetDefaultWebProxy (); - } - } - return defaultWebProxy; - } - set { - /* MS documentation states that a null value would cause an ArgumentNullException - * but that's not the way it behaves: - * https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=304724 - */ - defaultWebProxy = value; - isDefaultWebProxySet = true; - } - } - - internal static IWebProxy InternalDefaultWebProxy { - get { - return DefaultWebProxy; - } - } - - - [MonoTODO("Needs to respect Module, Proxy.AutoDetect, and Proxy.ScriptLocation config settings")] - static IWebProxy GetDefaultWebProxy () - { -#if CONFIGURATION_DEP - DefaultProxySection sec = ConfigurationManager.GetSection ("system.net/defaultProxy") as DefaultProxySection; - WebProxy p; - - if (sec == null) - return GetSystemWebProxy (); - - ProxyElement pe = sec.Proxy; - - if ((pe.UseSystemDefault != ProxyElement.UseSystemDefaultValues.False) && (pe.ProxyAddress == null)) { - IWebProxy proxy = GetSystemWebProxy (); - - if (!(proxy is WebProxy)) - return proxy; - - p = (WebProxy) proxy; - } else - p = new WebProxy (); - - if (pe.ProxyAddress != null) - p.Address = pe.ProxyAddress; - - if (pe.BypassOnLocal != ProxyElement.BypassOnLocalValues.Unspecified) - p.BypassProxyOnLocal = (pe.BypassOnLocal == ProxyElement.BypassOnLocalValues.True); - - foreach(BypassElement elem in sec.BypassList) - p.BypassArrayList.Add(elem.Address); - - return p; -#else - return GetSystemWebProxy (); -#endif - } - - // Methods - - public virtual void Abort() - { - throw GetMustImplement (); - } - - public virtual IAsyncResult BeginGetRequestStream (AsyncCallback callback, object state) - { - throw GetMustImplement (); - } - - public virtual IAsyncResult BeginGetResponse (AsyncCallback callback, object state) - { - throw GetMustImplement (); - } - - public static WebRequest Create (string requestUriString) - { - if (requestUriString == null) - throw new ArgumentNullException ("requestUriString"); - return Create (new Uri (requestUriString)); - } - - public static WebRequest Create (Uri requestUri) - { - if (requestUri == null) - throw new ArgumentNullException ("requestUri"); - return GetCreator (requestUri.AbsoluteUri).Create (requestUri); - } - - public static WebRequest CreateDefault (Uri requestUri) - { - if (requestUri == null) - throw new ArgumentNullException ("requestUri"); - return GetCreator (requestUri.Scheme).Create (requestUri); - } - static HttpWebRequest SharedCreateHttp (Uri uri) - { - if (uri.Scheme != "http" && uri.Scheme != "https") - throw new NotSupportedException ("The uri should start with http or https"); - - return new HttpWebRequest (uri); - } - - public static HttpWebRequest CreateHttp (string requestUriString) - { - if (requestUriString == null) - throw new ArgumentNullException ("requestUriString"); - return SharedCreateHttp (new Uri (requestUriString)); - } - - public static HttpWebRequest CreateHttp (Uri requestUri) - { - if (requestUri == null) - throw new ArgumentNullException ("requestUri"); - return SharedCreateHttp (requestUri); - } - public virtual Stream EndGetRequestStream (IAsyncResult asyncResult) - { - throw GetMustImplement (); - } - - public virtual WebResponse EndGetResponse (IAsyncResult asyncResult) - { - throw GetMustImplement (); - } - - public virtual Stream GetRequestStream() - { - throw GetMustImplement (); - } - - public virtual WebResponse GetResponse() - { - throw GetMustImplement (); - } - - // Takes an ArrayList of fileglob-formatted strings and returns an array of Regex-formatted strings - private static string[] CreateBypassList (ArrayList al) - { - string[] result = al.ToArray (typeof (string)) as string[]; - for (int c = 0; c < result.Length; c++) - { - result [c] = "^" + - Regex.Escape (result [c]).Replace (@"\*", ".*").Replace (@"\?", ".") + - "$"; - } - return result; - } - - [MonoTODO("Look in other places for proxy config info")] - public static IWebProxy GetSystemWebProxy () - { -#if MONOTOUCH - return CFNetwork.GetDefaultProxy (); -#else -#if MONODROID - // Return the system web proxy. This only works for ICS+. - var androidProxy = AndroidPlatform.GetDefaultProxy (); - if (androidProxy != null) - return androidProxy; -#endif -#if !NET_2_1 - if (IsWindows ()) { - int iProxyEnable = (int)Microsoft.Win32.Registry.GetValue ("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", "ProxyEnable", 0); - - if (iProxyEnable > 0) { - string strHttpProxy = ""; - bool bBypassOnLocal = false; - ArrayList al = new ArrayList (); - - string strProxyServer = (string)Microsoft.Win32.Registry.GetValue ("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", "ProxyServer", null); - string strProxyOverrride = (string)Microsoft.Win32.Registry.GetValue ("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", "ProxyOverride", null); - - if (strProxyServer.Contains ("=")) { - foreach (string strEntry in strProxyServer.Split (new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries)) - if (strEntry.StartsWith ("http=")) { - strHttpProxy = strEntry.Substring (5); - break; - } - } else strHttpProxy = strProxyServer; - - if (strProxyOverrride != null) { - string[] bypassList = strProxyOverrride.Split (new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries); - - foreach (string str in bypassList) { - if (str != "") - al.Add (str); - else - bBypassOnLocal = true; - } - } - - return new WebProxy (strHttpProxy, bBypassOnLocal, CreateBypassList (al)); - } - } else { -#endif - if (Platform.IsMacOS) - return CFNetwork.GetDefaultProxy (); - - string address = Environment.GetEnvironmentVariable ("http_proxy"); - - if (address == null) - address = Environment.GetEnvironmentVariable ("HTTP_PROXY"); - - if (address != null) { - try { - if (!address.StartsWith ("http://")) - address = "http://" + address; - - Uri uri = new Uri (address); - IPAddress ip; - - if (IPAddress.TryParse (uri.Host, out ip)) { - if (IPAddress.Any.Equals (ip)) { - UriBuilder builder = new UriBuilder (uri); - builder.Host = "127.0.0.1"; - uri = builder.Uri; - } else if (IPAddress.IPv6Any.Equals (ip)) { - UriBuilder builder = new UriBuilder (uri); - builder.Host = "[::1]"; - uri = builder.Uri; - } - } - - bool bBypassOnLocal = false; - ArrayList al = new ArrayList (); - string bypass = Environment.GetEnvironmentVariable ("no_proxy"); - - if (bypass == null) - bypass = Environment.GetEnvironmentVariable ("NO_PROXY"); - - if (bypass != null) { - string[] bypassList = bypass.Split (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); - - foreach (string str in bypassList) { - if (str != "*.local") - al.Add (str); - else - bBypassOnLocal = true; - } - } - - return new WebProxy (uri, bBypassOnLocal, CreateBypassList (al)); - } catch (UriFormatException) { - } - } -#if !NET_2_1 - } -#endif - - return new WebProxy (); -#endif // MONOTOUCH - } - - void ISerializable.GetObjectData (SerializationInfo serializationInfo, StreamingContext streamingContext) - { - GetObjectData(serializationInfo, streamingContext); - } - - protected virtual void GetObjectData (SerializationInfo serializationInfo, StreamingContext streamingContext) - { - } - - public static bool RegisterPrefix (string prefix, IWebRequestCreate creator) - { - if (prefix == null) - throw new ArgumentNullException ("prefix"); - if (creator == null) - throw new ArgumentNullException ("creator"); - - lock (prefixes.SyncRoot) { - string lowerCasePrefix = prefix.ToLower (CultureInfo.InvariantCulture); - if (prefixes.Contains (lowerCasePrefix)) - return false; - prefixes.Add (lowerCasePrefix, creator); - } - return true; - } - - private static IWebRequestCreate GetCreator (string prefix) - { - int longestPrefix = -1; - IWebRequestCreate creator = null; - - prefix = prefix.ToLower (CultureInfo.InvariantCulture); - - IDictionaryEnumerator e = prefixes.GetEnumerator (); - while (e.MoveNext ()) { - string key = e.Key as string; - - if (key.Length <= longestPrefix) - continue; - - if (!prefix.StartsWith (key)) - continue; - - longestPrefix = key.Length; - creator = (IWebRequestCreate) e.Value; - } - - if (creator == null) - throw new NotSupportedException (prefix); - - return creator; - } - - internal static bool IsWindows () - { - return (int) Environment.OSVersion.Platform < 4; - } - - internal static void ClearPrefixes () - { - prefixes.Clear (); - } - - internal static void RemovePrefix (string prefix) - { - prefixes.Remove (prefix); - } - - internal static void AddPrefix (string prefix, string typeName) - { - Type type = Type.GetType (typeName); - if (type == null) - throw new ConfigurationException (String.Format ("Type {0} not found", typeName)); - AddPrefix (prefix, type); - } - - internal static void AddPrefix (string prefix, Type type) - { - object o = Activator.CreateInstance (type, true); - prefixes [prefix] = o; - } - - public virtual Task GetRequestStreamAsync () - { - return Task.Factory.FromAsync (BeginGetRequestStream, EndGetRequestStream, null); - } - - public virtual Task GetResponseAsync () - { - return Task.Factory.FromAsync (BeginGetResponse, EndGetResponse, null); - } - } -} diff --git a/mcs/class/System/System.Security.AccessControl/SemaphoreSecurity.cs b/mcs/class/System/System.Security.AccessControl/SemaphoreSecurity.cs index f0bdac661c..ac6db80037 100644 --- a/mcs/class/System/System.Security.AccessControl/SemaphoreSecurity.cs +++ b/mcs/class/System/System.Security.AccessControl/SemaphoreSecurity.cs @@ -133,7 +133,7 @@ namespace System.Security.AccessControl SetAuditRule((AuditRule)rule); } - internal new void PersistModifications (SafeHandle handle) + internal new void Persist (SafeHandle handle) { WriteLock(); try { diff --git a/mcs/class/System/System.Security.Cryptography.X509Certificates/OSX509Certificates.cs b/mcs/class/System/System.Security.Cryptography.X509Certificates/OSX509Certificates.cs index 98f5dfc4ab..6f5cf7042b 100644 --- a/mcs/class/System/System.Security.Cryptography.X509Certificates/OSX509Certificates.cs +++ b/mcs/class/System/System.Security.Cryptography.X509Certificates/OSX509Certificates.cs @@ -22,10 +22,9 @@ // #if SECURITY_DEP -using XX509CertificateCollection = System.Security.Cryptography.X509Certificates.X509CertificateCollection; - using System; using System.Runtime.InteropServices; +using System.Security.Cryptography.X509Certificates; namespace System.Security.Cryptography.X509Certificates { @@ -107,7 +106,7 @@ namespace System.Security.Cryptography.X509Certificates { return handle; } - public static SecTrustResult TrustEvaluateSsl (XX509CertificateCollection certificates, XX509CertificateCollection anchors, string host) + public static SecTrustResult TrustEvaluateSsl (X509CertificateCollection certificates, X509CertificateCollection anchors, string host) { if (certificates == null) return SecTrustResult.Deny; @@ -119,7 +118,7 @@ namespace System.Security.Cryptography.X509Certificates { } } - static SecTrustResult _TrustEvaluateSsl (XX509CertificateCollection certificates, XX509CertificateCollection anchors, string hostName) + static SecTrustResult _TrustEvaluateSsl (X509CertificateCollection certificates, X509CertificateCollection anchors, string hostName) { int certCount = certificates.Count; int anchorCount = anchors != null ? anchors.Count : 0; @@ -147,7 +146,7 @@ namespace System.Security.Cryptography.X509Certificates { certArray = FromIntPtrs (secCerts); - if (!string.IsNullOrEmpty (hostName)) + if (hostName != null) host = CFStringCreateWithCharacters (IntPtr.Zero, hostName, (IntPtr) hostName.Length); sslsecpolicy = SecPolicyCreateSSL (true, host); diff --git a/mcs/class/System/System.Security.Cryptography.X509Certificates/X500DistinguishedName.cs b/mcs/class/System/System.Security.Cryptography.X509Certificates/X500DistinguishedName.cs index 795f0d04b2..78a87057ce 100644 --- a/mcs/class/System/System.Security.Cryptography.X509Certificates/X500DistinguishedName.cs +++ b/mcs/class/System/System.Security.Cryptography.X509Certificates/X500DistinguishedName.cs @@ -124,7 +124,6 @@ namespace System.Security.Cryptography.X509Certificates { } internal X500DistinguishedName (byte[] encoded, byte[] canonEncoding, string name) - : this (encoded) { this.canonEncoding = canonEncoding; this.name = name; @@ -234,7 +233,7 @@ namespace System.Security.Cryptography.X509Certificates { if (name1.canonEncoding.Length != name2.canonEncoding.Length) return false; for (int i = 0; i < name1.canonEncoding.Length; i++) { - if (name1.canonEncoding[i] != name2.canonEncoding[2]) + if (name1.canonEncoding[i] != name2.canonEncoding[i]) return false; } return true; diff --git a/mcs/class/System/System.Security.Cryptography.X509Certificates/X509Certificate2.cs b/mcs/class/System/System.Security.Cryptography.X509Certificates/X509Certificate2.cs index 29decab439..ef10413f59 100644 --- a/mcs/class/System/System.Security.Cryptography.X509Certificates/X509Certificate2.cs +++ b/mcs/class/System/System.Security.Cryptography.X509Certificates/X509Certificate2.cs @@ -45,6 +45,7 @@ using MX = Mono.Security.X509; using System.IO; using System.Text; using System.Collections; +using System.Runtime.Serialization; namespace System.Security.Cryptography.X509Certificates { @@ -134,6 +135,10 @@ namespace System.Security.Cryptography.X509Certificates { { } + protected X509Certificate2 (SerializationInfo info, StreamingContext context) : base (info, context) + { + } + internal X509Certificate2 (X509Certificate2Impl impl) : base (impl) { @@ -394,13 +399,10 @@ namespace System.Security.Cryptography.X509Certificates { // internal stuff because X509Certificate2 isn't complete enough // (maybe X509Certificate3 will be better?) - [Obsolete ("KILL")] + [MonoTODO ("See comment in X509Helper2.GetMonoCertificate().")] internal MX.X509Certificate MonoCertificate { get { - var monoImpl = Impl as X509Certificate2ImplMono; - if (monoImpl == null) - throw new NotSupportedException (); - return monoImpl.MonoCertificate; + return X509Helper2.GetMonoCertificate (this); } } diff --git a/mcs/class/System/System.Security.Cryptography.X509Certificates/X509Certificate2Impl.cs b/mcs/class/System/System.Security.Cryptography.X509Certificates/X509Certificate2Impl.cs index 234d0907f2..38797d55fc 100644 --- a/mcs/class/System/System.Security.Cryptography.X509Certificates/X509Certificate2Impl.cs +++ b/mcs/class/System/System.Security.Cryptography.X509Certificates/X509Certificate2Impl.cs @@ -71,6 +71,10 @@ namespace System.Security.Cryptography.X509Certificates get; } + internal abstract X509Certificate2Impl FallbackImpl { + get; + } + public abstract string GetNameInfo (X509NameType nameType, bool forIssuer); public abstract void Import (byte[] rawData, string password, X509KeyStorageFlags keyStorageFlags); diff --git a/mcs/class/System/System.Security.Cryptography.X509Certificates/X509Certificate2ImplMono.cs b/mcs/class/System/System.Security.Cryptography.X509Certificates/X509Certificate2ImplMono.cs index cdc14c49eb..a16d6e0690 100644 --- a/mcs/class/System/System.Security.Cryptography.X509Certificates/X509Certificate2ImplMono.cs +++ b/mcs/class/System/System.Security.Cryptography.X509Certificates/X509Certificate2ImplMono.cs @@ -483,6 +483,7 @@ namespace System.Security.Cryptography.X509Certificates [MonoTODO ("missing KeyStorageFlags support")] public override void Import (byte[] rawData, string password, X509KeyStorageFlags keyStorageFlags) { + Reset (); MX.X509Certificate cert = null; if (password == null) { try { @@ -718,6 +719,10 @@ namespace System.Security.Cryptography.X509Certificates internal MX.X509Certificate MonoCertificate { get { return _cert; } } + + internal override X509Certificate2Impl FallbackImpl { + get { return this; } + } } } diff --git a/mcs/class/System/System.Security.Cryptography.X509Certificates/X509ChainPolicy.cs b/mcs/class/System/System.Security.Cryptography.X509Certificates/X509ChainPolicy.cs index 1dc234575b..2fcdd982f3 100644 --- a/mcs/class/System/System.Security.Cryptography.X509Certificates/X509ChainPolicy.cs +++ b/mcs/class/System/System.Security.Cryptography.X509Certificates/X509ChainPolicy.cs @@ -91,6 +91,9 @@ namespace System.Security.Cryptography.X509Certificates { } return store2; } + internal set { + store2 = value; + } } public X509RevocationFlag RevocationFlag { diff --git a/mcs/class/System/System.Security.Cryptography.X509Certificates/X509Helper2.cs b/mcs/class/System/System.Security.Cryptography.X509Certificates/X509Helper2.cs index 2a9163a346..7d0b3d1487 100644 --- a/mcs/class/System/System.Security.Cryptography.X509Certificates/X509Helper2.cs +++ b/mcs/class/System/System.Security.Cryptography.X509Certificates/X509Helper2.cs @@ -33,14 +33,57 @@ extern alias MonoSecurity; #if MONO_SECURITY_ALIAS using MonoSecurity::Mono.Security.Interface; +using MX = MonoSecurity::Mono.Security.X509; #else +#if MONO_FEATURE_BTLS using Mono.Security.Interface; #endif +using MX = Mono.Security.X509; +#endif + +#if MONO_FEATURE_BTLS +using Mono.Btls; +#endif +#endif + +using System.IO; +using System.Text; namespace System.Security.Cryptography.X509Certificates { internal static class X509Helper2 { + internal static long GetSubjectNameHash (X509Certificate certificate) + { + return GetSubjectNameHash (certificate.Impl); + } + + internal static long GetSubjectNameHash (X509CertificateImpl impl) + { +#if SECURITY_DEP + using (var x509 = GetNativeInstance (impl)) + return GetSubjectNameHash (x509); +#else + throw new NotSupportedException (); +#endif + } + + internal static void ExportAsPEM (X509Certificate certificate, Stream stream, bool includeHumanReadableForm) + { + ExportAsPEM (certificate.Impl, stream, includeHumanReadableForm); + } + + internal static void ExportAsPEM (X509CertificateImpl impl, Stream stream, bool includeHumanReadableForm) + { +#if SECURITY_DEP + using (var x509 = GetNativeInstance (impl)) + ExportAsPEM (x509, stream, includeHumanReadableForm); +#else + throw new NotSupportedException (); +#endif + } + +#if SECURITY_DEP internal static void Initialize () { X509Helper.InstallNativeHelper (new MyNativeHelper ()); @@ -51,32 +94,90 @@ namespace System.Security.Cryptography.X509Certificates X509Helper.ThrowIfContextInvalid (impl); } - internal static X509Certificate2Impl Import (byte[] rawData, string password, X509KeyStorageFlags keyStorageFlags) +#if !MONO_FEATURE_BTLS + static X509Certificate GetNativeInstance (X509CertificateImpl impl) { - var provider = MonoTlsProviderFactory.GetProvider (); - if (provider.HasNativeCertificates) { - var impl = provider.GetNativeCertificate (rawData, password, keyStorageFlags); - return impl; - } else { - var impl = new X509Certificate2ImplMono (); - impl.Import (rawData, password, keyStorageFlags); - return impl; - } + throw new PlatformNotSupportedException (); + } +#else + static MonoBtlsX509 GetNativeInstance (X509CertificateImpl impl) + { + ThrowIfContextInvalid (impl); + var btlsImpl = impl as X509CertificateImplBtls; + if (btlsImpl != null) + return btlsImpl.X509.Copy (); + else + return MonoBtlsX509.LoadFromData (impl.GetRawCertData (), MonoBtlsX509Format.DER); } - internal static X509Certificate2Impl Import (X509Certificate cert) + internal static long GetSubjectNameHash (MonoBtlsX509 x509) { - var provider = MonoTlsProviderFactory.GetProvider (); - if (provider.HasNativeCertificates) { - var impl = provider.GetNativeCertificate (cert); - return impl; + using (var subject = x509.GetSubjectName ()) + return subject.GetHash (); + } + + internal static void ExportAsPEM (MonoBtlsX509 x509, Stream stream, bool includeHumanReadableForm) + { + using (var bio = MonoBtlsBio.CreateMonoStream (stream)) { + x509.ExportAsPEM (bio, includeHumanReadableForm); } + } +#endif // !MONO_FEATURE_BTLS + + internal static X509Certificate2Impl Import (byte[] rawData, string password, X509KeyStorageFlags keyStorageFlags, bool disableProvider = false) + { +#if MONO_FEATURE_BTLS + if (!disableProvider) { + var provider = MonoTlsProviderFactory.GetProvider (); + if (provider.HasNativeCertificates) { + var impl = provider.GetNativeCertificate (rawData, password, keyStorageFlags); + return impl; + } + } +#endif // MONO_FEATURE_BTLS + var impl2 = new X509Certificate2ImplMono (); + impl2.Import (rawData, password, keyStorageFlags); + return impl2; + } + + internal static X509Certificate2Impl Import (X509Certificate cert, bool disableProvider = false) + { +#if MONO_FEATURE_BTLS + if (!disableProvider) { + var provider = MonoTlsProviderFactory.GetProvider (); + if (provider.HasNativeCertificates) { + var impl = provider.GetNativeCertificate (cert); + return impl; + } + } +#endif // MONO_FEATURE_BTLS var impl2 = cert.Impl as X509Certificate2Impl; if (impl2 != null) return (X509Certificate2Impl)impl2.Clone (); return Import (cert.GetRawCertData (), null, X509KeyStorageFlags.DefaultKeySet); } + /* + * This is used by X509ChainImplMono + * + * Some of the missing APIs such as X509v3 extensions can be added to the native + * BTLS implementation. + * + * We should also consider replacing X509ChainImplMono with a new X509ChainImplBtls + * at some point. + */ + [MonoTODO ("Investigate replacement; see comments in source.")] + internal static MX.X509Certificate GetMonoCertificate (X509Certificate2 certificate) + { + var impl2 = certificate.Impl as X509Certificate2Impl; + if (impl2 == null) + impl2 = Import (certificate, true); + var fallbackImpl = impl2.FallbackImpl as X509Certificate2ImplMono; + if (fallbackImpl == null) + throw new NotSupportedException (); + return fallbackImpl.MonoCertificate; + } + internal static X509ChainImpl CreateChainImpl (bool useMachineContext) { return new X509ChainImplMono (useMachineContext); @@ -111,6 +212,6 @@ namespace System.Security.Cryptography.X509Certificates return X509Helper2.Import (cert); } } +#endif } } -#endif diff --git a/mcs/class/System/System.Threading/Semaphore.cs b/mcs/class/System/System.Threading/Semaphore.cs deleted file mode 100644 index 2324fb9b52..0000000000 --- a/mcs/class/System/System.Threading/Semaphore.cs +++ /dev/null @@ -1,221 +0,0 @@ -// -// System.Threading.Semaphore.cs -// -// Author: -// Sebastien Pouliot -// -// Copyright (C) 2005 Novell, Inc (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// - -using System.Runtime.ConstrainedExecution; -using System.Runtime.InteropServices; -using System.Security.AccessControl; -using System.Security.Permissions; -using System.Runtime.CompilerServices; -using System.IO; - -namespace System.Threading { - - [ComVisible (false)] - public sealed class Semaphore : WaitHandle { - - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private static extern IntPtr CreateSemaphore_internal ( - int initialCount, int maximumCount, string name, - out bool createdNew); - - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private static extern int ReleaseSemaphore_internal ( - IntPtr handle, int releaseCount, out bool fail); - - [MethodImplAttribute (MethodImplOptions.InternalCall)] - private static extern IntPtr OpenSemaphore_internal (string name, SemaphoreRights rights, out MonoIOError error); - - private Semaphore (IntPtr handle) - { - Handle = handle; - } - - public Semaphore (int initialCount, int maximumCount) - : this (initialCount, maximumCount, null) - { - } - - public Semaphore (int initialCount, int maximumCount, string name) - { - if (initialCount < 0) - throw new ArgumentOutOfRangeException ("initialCount", "< 0"); - if (maximumCount < 1) - throw new ArgumentOutOfRangeException ("maximumCount", "< 1"); - if (initialCount > maximumCount) - throw new ArgumentException ("initialCount > maximumCount"); - - bool created; - - Handle = CreateSemaphore_internal (initialCount, - maximumCount, name, - out created); - } - - public Semaphore (int initialCount, int maximumCount, string name, out bool createdNew) - : this (initialCount, maximumCount, name, out createdNew, null) - { - } - - [MonoTODO ("CreateSemaphore_internal does not support access control, semaphoreSecurity is ignored")] - public Semaphore (int initialCount, int maximumCount, string name, out bool createdNew, - SemaphoreSecurity semaphoreSecurity) - { - if (initialCount < 0) - throw new ArgumentOutOfRangeException ("initialCount", "< 0"); - if (maximumCount < 1) - throw new ArgumentOutOfRangeException ("maximumCount", "< 1"); - if (initialCount > maximumCount) - throw new ArgumentException ("initialCount > maximumCount"); - - Handle = CreateSemaphore_internal (initialCount, - maximumCount, name, - out createdNew); - } - - public SemaphoreSecurity GetAccessControl () - { - return new SemaphoreSecurity (SafeWaitHandle, - AccessControlSections.Owner | - AccessControlSections.Group | - AccessControlSections.Access); - } - - [PrePrepareMethod] - [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)] - public int Release () - { - return (Release (1)); - } - - [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)] - public int Release (int releaseCount) - { - if (releaseCount < 1) - throw new ArgumentOutOfRangeException ("releaseCount"); - - int ret; - bool fail; - - ret = ReleaseSemaphore_internal (Handle, releaseCount, - out fail); - - if (fail) { - throw new SemaphoreFullException (); - } - - return (ret); - } - - public void SetAccessControl (SemaphoreSecurity semaphoreSecurity) - { - if (semaphoreSecurity == null) - throw new ArgumentNullException ("semaphoreSecurity"); - - semaphoreSecurity.PersistModifications (SafeWaitHandle); - } - - // static methods - -#if !MOBILE - public static Semaphore OpenExisting (string name) - { - return OpenExisting (name, SemaphoreRights.Synchronize | SemaphoreRights.Modify); - } - - public static Semaphore OpenExisting (string name, SemaphoreRights rights) - { - if (name == null) - throw new ArgumentNullException ("name"); - if ((name.Length ==0) || (name.Length > 260)) - throw new ArgumentException ("name", Locale.GetText ("Invalid length [1-260].")); - - MonoIOError error; - IntPtr handle = OpenSemaphore_internal (name, rights, - out error); - if (handle == (IntPtr)null) { - if (error == MonoIOError.ERROR_FILE_NOT_FOUND) { - throw new WaitHandleCannotBeOpenedException (Locale.GetText ("Named Semaphore handle does not exist: ") + name); - } else if (error == MonoIOError.ERROR_ACCESS_DENIED) { - throw new UnauthorizedAccessException (); - } else { - throw new IOException (Locale.GetText ("Win32 IO error: ") + error.ToString ()); - } - } - - return(new Semaphore (handle)); - } - - [SecurityPermissionAttribute (SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)] - public static bool TryOpenExisting (string name, out Semaphore result) - { - return TryOpenExisting (name, SemaphoreRights.Synchronize | SemaphoreRights.Modify, out result); - } - - [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)] - public static bool TryOpenExisting (string name, SemaphoreRights rights, out Semaphore result) - { - if (name == null) - throw new ArgumentNullException ("name"); - if ((name.Length == 0) || (name.Length > 260)) - throw new ArgumentException ("name", Locale.GetText ("Invalid length [1-260].")); - - MonoIOError error; - IntPtr handle = OpenSemaphore_internal (name, rights, out error); - - if (handle == (IntPtr)null) { - result = null; - return false; - } - - result = new Semaphore (handle); - return true; - } -#else - public static Semaphore OpenExisting (string name) - { - throw new NotSupportedException (); - } - - public static Semaphore OpenExisting (string name, SemaphoreRights rights) - { - throw new NotSupportedException (); - } - - public static bool TryOpenExisting (string name, out Semaphore result) - { - throw new NotSupportedException (); - } - - public static bool TryOpenExisting (string name, SemaphoreRights rights, out Semaphore result) - { - throw new NotSupportedException (); - } -#endif - } -} - diff --git a/mcs/class/System/System.dll.sources b/mcs/class/System/System.dll.sources index afde1b3a32..80ff90e346 100644 --- a/mcs/class/System/System.dll.sources +++ b/mcs/class/System/System.dll.sources @@ -148,11 +148,9 @@ System.Diagnostics/PerformanceCounterPermissionEntryCollection.cs System.Diagnostics/PerformanceCounterPermissionEntry.cs System.Diagnostics/PerformanceCounterType.cs System.Diagnostics/Process.cs -System.Diagnostics/ProcessModuleCollection.cs System.Diagnostics/ProcessModule.cs System.Diagnostics/ProcessPriorityClass.cs System.Diagnostics/ProcessStartInfo.cs -System.Diagnostics/ProcessThreadCollection.cs System.Diagnostics/ProcessThread.cs System.Diagnostics/ProcessWindowStyle.cs System.Diagnostics/Stopwatch.cs @@ -162,7 +160,6 @@ System.Diagnostics/ThreadWaitReason.cs System.Diagnostics/TraceImpl.cs System.Diagnostics/TraceSourceInfo.cs System.Diagnostics/Win32EventLog.cs -System.Diagnostics.CodeAnalysis/ExcludeFromCodeCoverageAttribute.cs System/Platform.cs System.IO.Compression/CompressionLevel.cs System.IO.Compression/CompressionMode.cs @@ -249,7 +246,6 @@ System.Net.Configuration/WebRequestModuleElementCollection.cs System.Net.Configuration/WebRequestModuleElement.cs System.Net.Configuration/WebRequestModuleHandler.cs System.Net.Configuration/WebRequestModulesSection.cs -System.Net/CredentialCache.cs System.Net/DecompressionMethods.cs System.Net/DefaultCertificatePolicy.cs System.Net/DigestClient.cs @@ -265,7 +261,6 @@ System.Net/FtpRequestCreator.cs System.Net/FtpWebRequest.cs System.Net/FtpStatus.cs System.Net/FtpWebResponse.cs -System.Net/GlobalProxySelection.cs System.Net/HttpConnection.cs System.Net/HttpListenerBasicIdentity.cs System.Net/HttpListenerContext.cs @@ -273,6 +268,7 @@ System.Net/HttpListener.cs System.Net/HttpListenerPrefixCollection.cs System.Net/HttpListenerRequest.cs System.Net/HttpListenerResponse.cs +System.Net/HttpListenerResponseHelper.cs System.Net/HttpListenerTimeoutManager.cs System.Net/HttpRequestCreator.cs System.Net/HttpStreamAsyncResult.cs @@ -340,7 +336,6 @@ System.Net.Mail/SmtpStatusCode.cs System.Net/MacProxy.cs System.Net/MonoHttpDate.cs System.Net/NetConfig.cs -System.Net/NetworkCredential.cs System.Net.NetworkInformation/IcmpV4Statistics.cs System.Net.NetworkInformation/IcmpV6Statistics.cs System.Net.NetworkInformation/IPAddressCollection.cs @@ -401,6 +396,9 @@ System.Net.Sockets/SocketOperation.cs ../referencesource/System/net/System/Net/Sockets/SocketOptionLevel.cs ../referencesource/System/net/System/Net/Sockets/SocketOptionName.cs ../referencesource/System/net/System/Net/Sockets/SocketShutdown.cs +System.Net.Sockets/SocketReceiveFromResult.cs +System.Net.Sockets/SocketReceiveMessageFromResult.cs +System.Net.Sockets/SocketTaskExtensions.cs ../referencesource/System/net/System/Net/Sockets/SocketType.cs System.Net.Sockets/TcpClient.cs System.Net.Sockets/TcpListener.cs @@ -412,8 +410,6 @@ System.Net/WebConnection.cs System.Net/WebConnectionData.cs System.Net/WebConnectionGroup.cs System.Net/WebConnectionStream.cs -System.Net/WebProxy.cs -System.Net/WebRequest.cs System.Net.WebSockets/ClientWebSocket.cs System.Net.WebSockets/ClientWebSocketOptions.cs System.Net.WebSockets/HttpListenerWebSocketContext.cs @@ -441,7 +437,6 @@ System.Security.Authentication.ExtendedProtection/ExtendedProtectionPolicy.cs System.Security.Authentication.ExtendedProtection/ExtendedProtectionPolicyTypeConverter.cs System.Security.Authentication.ExtendedProtection/PolicyEnforcement.cs System.Security.Authentication.ExtendedProtection/ProtectionScenario.cs -System.Security.Authentication.ExtendedProtection/ServiceNameCollection.cs System.Security.Authentication.ExtendedProtection.Configuration/ConfigUtil.cs System.Security.Authentication.ExtendedProtection.Configuration/ExtendedProtectionPolicyElement.cs System.Security.Authentication.ExtendedProtection.Configuration/ServiceNameElement.cs @@ -496,7 +491,6 @@ System.Security.Permissions/StorePermissionAttribute.cs System.Security.Permissions/StorePermission.cs System.Security.Permissions/StorePermissionFlags.cs System/SRDescriptionAttribute.cs -System.Threading/Semaphore.cs System.Threading/ThreadExceptionEventArgs.cs System.Threading/ThreadExceptionEventHandler.cs System.Timers/ElapsedEventArgs.cs @@ -544,6 +538,44 @@ System.Windows.Input/ICommand.cs System/IOSelector.cs +Mono.Btls/MonoBtlsBio.cs +Mono.Btls/MonoBtlsContext.cs +Mono.Btls/MonoBtlsError.cs +Mono.Btls/MonoBtlsException.cs +Mono.Btls/MonoBtlsKey.cs +Mono.Btls/MonoBtlsObject.cs +Mono.Btls/MonoBtlsPkcs12.cs +Mono.Btls/MonoBtlsProvider.cs +Mono.Btls/MonoBtlsSsl.cs +Mono.Btls/MonoBtlsSslCtx.cs +Mono.Btls/MonoBtlsSslError.cs +Mono.Btls/MonoBtlsStream.cs +Mono.Btls/MonoBtlsUtils.cs +Mono.Btls/MonoBtlsX509.cs +Mono.Btls/MonoBtlsX509Chain.cs +Mono.Btls/MonoBtlsX509Crl.cs +Mono.Btls/MonoBtlsX509Error.cs +Mono.Btls/MonoBtlsX509Exception.cs +Mono.Btls/MonoBtlsX509FileType.cs +Mono.Btls/MonoBtlsX509Format.cs +Mono.Btls/MonoBtlsX509Lookup.cs +Mono.Btls/MonoBtlsX509LookupMonoCollection.cs +Mono.Btls/MonoBtlsX509LookupMono.cs +Mono.Btls/MonoBtlsX509LookupType.cs +Mono.Btls/MonoBtlsX509Name.cs +Mono.Btls/MonoBtlsX509NameEntryType.cs +Mono.Btls/MonoBtlsX509Purpose.cs +Mono.Btls/MonoBtlsX509Revoked.cs +Mono.Btls/MonoBtlsX509Store.cs +Mono.Btls/MonoBtlsX509StoreCtx.cs +Mono.Btls/MonoBtlsX509StoreManager.cs +Mono.Btls/MonoBtlsX509StoreType.cs +Mono.Btls/MonoBtlsX509TrustKind.cs +Mono.Btls/MonoBtlsX509VerifyFlags.cs +Mono.Btls/MonoBtlsX509VerifyParam.cs +Mono.Btls/X509CertificateImplBtls.cs +Mono.Btls/X509ChainImplBtls.cs + Mono.Net.Security/AsyncProtocolRequest.cs Mono.Net.Security/CallbackHelpers.cs Mono.Net.Security/ChainValidationHelper.cs @@ -552,42 +584,35 @@ Mono.Net.Security/IMonoSslStream.cs Mono.Net.Security/LegacySslStream.cs Mono.Net.Security/MobileAuthenticatedStream.cs Mono.Net.Security/MobileTlsContext.cs -Mono.Net.Security/MonoLegacyTlsProvider.cs +Mono.Net.Security/LegacyTlsProvider.cs Mono.Net.Security/MonoSslStreamImpl.cs Mono.Net.Security/MonoSslStreamWrapper.cs Mono.Net.Security/MonoTlsProviderFactory.cs -Mono.Net.Security/MonoTlsProviderImpl.cs Mono.Net.Security/MonoTlsProviderWrapper.cs Mono.Net.Security/MonoTlsStream.cs Mono.Net.Security/NoReflectionHelper.cs Mono.Net.Security/SystemCertificateValidator.cs +ReferenceSources/AutoWebProxyScriptEngine.cs ReferenceSources/AssertWrapper.cs ReferenceSources/BinaryCompatibility.cs ReferenceSources/ConfigurationManagerInternalFactory.cs ReferenceSources/CAPI.cs ReferenceSources/EnvironmentHelpers.cs -ReferenceSources/Internal.cs ReferenceSources/HttpApi.cs ReferenceSources/HttpSysSettings.cs +ReferenceSources/LocalAppContextSwitches.cs ReferenceSources/Logging.cs ReferenceSources/NativeMethods.cs +ReferenceSources/RequestCacheProtocol.cs ReferenceSources/SettingsSectionInternal.cs +ReferenceSources/SecureStringHelper.cs ReferenceSources/Socket.cs ReferenceSources/SR.cs ReferenceSources/SR2.cs ReferenceSources/SRCategoryAttribute.cs -ReferenceSources/SystemNetworkCredential.cs ReferenceSources/Win32Exception.cs -ReferenceSources/SSPIConfiguration.cs -ReferenceSources/SSPISafeHandles.cs -ReferenceSources/SSPIWrapper.cs -ReferenceSources/SslStream.cs -ReferenceSources/_SecureChannel.cs -ReferenceSources/_SslState.cs -ReferenceSources/_SslStream.cs - ../referencesource/System/misc/PrivilegedConfigurationManager.cs ../referencesource/System/regex/system/text/regularexpressions/Regex.cs ../referencesource/System/regex/system/text/regularexpressions/RegexBoyerMoore.cs @@ -973,6 +998,7 @@ ReferenceSources/_SslStream.cs ../referencesource/System/net/System/Net/_BufferOffsetSize.cs ../referencesource/System/net/System/Net/_Connection.cs +../referencesource/System/net/System/Net/_emptywebproxy.cs ../referencesource/System/net/System/Net/_HeaderInfo.cs ../referencesource/System/net/System/Net/_HeaderInfoTable.cs ../referencesource/System/net/System/Net/_HTTPDateParse.cs @@ -980,19 +1006,28 @@ ReferenceSources/_SslStream.cs ../referencesource/System/net/System/Net/_NetRes.cs ../referencesource/System/net/System/Net/_LazyAsyncResult.cs ../referencesource/System/net/System/Net/_LoggingObject.cs +../referencesource/System/net/System/Net/_PooledStream.cs +../referencesource/System/net/System/Net/_ProxyChain.cs ../referencesource/System/net/System/Net/_ScatterGatherBuffers.cs +../referencesource/System/net/System/Net/_Semaphore.cs +../referencesource/System/net/System/Net/_ServiceNameStore.cs +../referencesource/System/net/System/Net/_TimerThread.cs +../referencesource/System/net/System/Net/_WebProxyDataBuilder.cs ../referencesource/System/net/System/Net/AuthenticationScheme.cs ../referencesource/System/net/System/Net/AuthenticationSchemeSelector.cs ../referencesource/System/net/System/Net/Authorization.cs +../referencesource/System/net/System/Net/CredentialCache.cs ../referencesource/System/net/System/Net/cookie.cs ../referencesource/System/net/System/Net/cookiecollection.cs ../referencesource/System/net/System/Net/cookiecontainer.cs ../referencesource/System/net/System/Net/cookieexception.cs +../referencesource/System/net/System/Net/connectionpool.cs ../referencesource/System/net/System/Net/DnsEndPoint.cs ../referencesource/System/net/System/Net/EndPoint.cs ../referencesource/System/net/System/Net/FtpStatusCode.cs ../referencesource/System/net/System/Net/filewebrequest.cs ../referencesource/System/net/System/Net/filewebresponse.cs +../referencesource/System/net/System/Net/GlobalProxySelection.cs ../referencesource/System/net/System/Net/HttpListenerException.cs ../referencesource/System/net/System/Net/HttpListenerRequestUriBuilder.cs ../referencesource/System/net/System/Net/HttpRequestHeader.cs @@ -1008,8 +1043,10 @@ ReferenceSources/_SslStream.cs ../referencesource/System/net/System/Net/IPEndPoint.cs ../referencesource/System/net/System/Net/IPHostEntry.cs ../referencesource/System/net/System/Net/iwebproxy.cs +../referencesource/System/net/System/Net/IWebProxyFinder.cs ../referencesource/System/net/System/Net/IWebRequestCreate.cs ../referencesource/System/net/System/Net/NetworkAccess.cs +../referencesource/System/net/System/Net/NetworkCredential.cs ../referencesource/System/net/System/Net/ProtocolViolationException.cs ../referencesource/System/net/System/Net/TransportContext.cs ../referencesource/System/net/System/Net/TransportType.cs @@ -1022,13 +1059,21 @@ ReferenceSources/_SslStream.cs ../referencesource/System/net/System/Net/WebExceptionStatus.cs ../referencesource/System/net/System/Net/WebHeaderCollection.cs ../referencesource/System/net/System/Net/WebPermission.cs +../referencesource/System/net/System/Net/webproxy.cs ../referencesource/System/net/System/Net/WebRequestMethods.cs +../referencesource/System/net/System/Net/WebRequest.cs ../referencesource/System/net/System/Net/WebResponse.cs ../referencesource/System/net/System/Net/WebUtility.cs ../referencesource/System/net/System/Net/WriteStreamClosedEventArgs.cs +../referencesource/System/net/System/Net/Cache/RequestCache.cs +../referencesource/System/net/System/Net/Cache/RequestCacheEntry.cs ../referencesource/System/net/System/Net/Cache/RequestCachePolicy.cs +../referencesource/System/net/System/Net/Cache/RequestCacheManager.cs +../referencesource/System/net/System/Net/Configuration/DefaultProxySection.cs + +../referencesource/System/net/System/Net/Sockets/_MultipleConnectAsync.cs ../referencesource/System/net/System/Net/Sockets/IPProtectionLevel.cs ../referencesource/System/net/System/Net/Sockets/NetworkStream.cs @@ -1076,15 +1121,22 @@ ReferenceSources/_SslStream.cs ../referencesource/System/net/System/Net/NetworkInformation/nodetype.cs ../referencesource/System/net/System/Net/NetworkInformation/pingexception.cs +../referencesource/System/sys/system/IO/ports/InternalResources.cs + +../referencesource/System/sys/system/Diagnostics/CodeAnalysis/ExcludeFromCodeCoverageAttribute.cs + ../referencesource/System/sys/system/runtime/interopservices/DefaultParameterValueAttribute.cs ../referencesource/System/sys/system/runtime/interopservices/handlecollector.cs ../referencesource/System/sys/system/runtime/versioning/FrameworkName.cs ../referencesource/System/sys/system/threading/Barrier.cs +../referencesource/System/sys/system/threading/semaphore.cs + ../referencesource/System/sys/system/windows/markup/ValueSerializerAttribute.cs ../referencesource/System/security/system/security/Authentication/ExtendedProtection/TokenBinding.cs +../referencesource/System/security/system/security/Authentication/ExtendedProtection/ServiceNameCollection.cs ../referencesource/System/security/system/security/cryptography/oid.cs @@ -1092,6 +1144,9 @@ ReferenceSources/_SslStream.cs ../referencesource/System/security/system/security/permissions/typedescriptorpermission.cs +../referencesource/System/services/monitoring/system/diagnosticts/ProcessModuleCollection.cs +../referencesource/System/services/monitoring/system/diagnosticts/ProcessThreadCollection.cs + ../referencesource/System/services/timers/system/timers/ElapsedEventHandler.cs ../referencesource/System/services/timers/system/timers/Timer.cs ../referencesource/System/services/timers/system/timers/TimersDescriptionAttribute.cs diff --git a/mcs/class/System/System/AndroidPlatform.cs b/mcs/class/System/System/AndroidPlatform.cs index 1f010668d7..dc4f4aaa54 100644 --- a/mcs/class/System/System/AndroidPlatform.cs +++ b/mcs/class/System/System/AndroidPlatform.cs @@ -33,6 +33,9 @@ using System.Net.Security; using System.Security.Cryptography.X509Certificates; #if SECURITY_DEP using MSX = Mono.Security.X509; +#if MONO_FEATURE_BTLS +using Mono.Btls; +#endif #endif namespace System { @@ -43,6 +46,7 @@ namespace System { #if SECURITY_DEP static readonly Converter, bool> trustEvaluateSsl; + static readonly Func certStoreLookup; #endif // SECURITY_DEP static readonly Func getDefaultProxy; static readonly GetInterfaceAddressesDelegate getInterfaceAddresses; @@ -58,6 +62,14 @@ namespace System { "TrustEvaluateSsl", ignoreCase:false, throwOnBindFailure:true); +#if MONO_FEATURE_BTLS + certStoreLookup = (Func) + Delegate.CreateDelegate (typeof (Func), + t, + "CertStoreLookup", + ignoreCase:false, + throwOnBindFailure:true); +#endif // MONO_FEATURE_BTLS #endif // SECURITY_DEP getDefaultProxy = (Func)Delegate.CreateDelegate ( typeof (Func), t, "GetDefaultProxy", @@ -83,6 +95,26 @@ namespace System { certsRawData.Add (cert.GetRawCertData ()); return trustEvaluateSsl (certsRawData); } + +#if MONO_FEATURE_BTLS + internal static MonoBtlsX509 CertStoreLookup (MonoBtlsX509Name name) + { + var hash = name.GetHash (); + var hashOld = name.GetHashOld (); + var result = certStoreLookup (hash, false); + if (result == null) + result = certStoreLookup (hashOld, false); + if (result == null) + result = certStoreLookup (hash, true); + if (result == null) + result = certStoreLookup (hashOld, true); + + if (result == null) + return null; + + return MonoBtlsX509.LoadFromData (result, MonoBtlsX509Format.DER); + } +#endif // MONO_FEATURE_BTLS #endif // SECURITY_DEP internal static IWebProxy GetDefaultProxy () diff --git a/mcs/class/System/System/UriTypeConverter.cs b/mcs/class/System/System/UriTypeConverter.cs index 2d7f9cf141..ea2fe62b6b 100644 --- a/mcs/class/System/System/UriTypeConverter.cs +++ b/mcs/class/System/System/UriTypeConverter.cs @@ -27,7 +27,7 @@ // using System.ComponentModel; -#if !NET_2_1 +#if !MOBILE using System.ComponentModel.Design.Serialization; #endif using System.Globalization; @@ -49,7 +49,7 @@ namespace System { return true; if (type == typeof (Uri)) return true; -#if NET_2_1 +#if MOBILE return false; #else return (type == typeof (InstanceDescriptor)); @@ -75,7 +75,7 @@ namespace System { public override object ConvertFrom (ITypeDescriptorContext context, CultureInfo culture, object value) { if (value == null) { -#if NET_2_1 +#if MOBILE throw new NotSupportedException (Locale.GetText ("Cannot convert from value.")); #else throw new ArgumentNullException ("value"); @@ -90,14 +90,14 @@ namespace System { string s = (value as string); if (s != null) { -#if NET_2_1 +#if MOBILE if (s == "") return null; #endif return new Uri (s, UriKind.RelativeOrAbsolute); } -#if !NET_2_1 +#if !MOBILE InstanceDescriptor id = (value as InstanceDescriptor); if (id != null) { return id.Invoke (); @@ -117,7 +117,7 @@ namespace System { return uri.ToString (); if (destinationType == typeof (Uri)) return uri; -#if !NET_2_1 +#if !MOBILE if (destinationType == typeof (InstanceDescriptor)) { ConstructorInfo ci = typeof (Uri).GetConstructor (new Type [2] { typeof (string), typeof (UriKind) }); return new InstanceDescriptor (ci , new object [] { uri.ToString (), uri.IsAbsoluteUri ? UriKind.Absolute : UriKind.Relative }); @@ -127,14 +127,14 @@ namespace System { #endif } -#if NET_2_1 +#if MOBILE throw new NotSupportedException (Locale.GetText ("Cannot convert to destination type.")); #else return base.ConvertTo (context, culture, value, destinationType); #endif } -#if !NET_2_1 +#if !MOBILE public override bool IsValid (ITypeDescriptorContext context, object value) { if (value == null) diff --git a/mcs/class/System/Test/System.ComponentModel.Design.Serialization/InstanceDescriptorTest.cs b/mcs/class/System/Test/System.ComponentModel.Design.Serialization/InstanceDescriptorTest.cs index dbc4110cb2..ec9d6b1bb0 100644 --- a/mcs/class/System/Test/System.ComponentModel.Design.Serialization/InstanceDescriptorTest.cs +++ b/mcs/class/System/Test/System.ComponentModel.Design.Serialization/InstanceDescriptorTest.cs @@ -190,7 +190,7 @@ namespace MonoTests.System.ComponentModel.Design.Serialization { { #if MOBILE // ensure the property is not linked out of the application since it make the test fails - Assert.NotNull (Thread.CurrentPrincipal, "pre-test"); + Assert.IsNotNull (Thread.CurrentPrincipal, "pre-test"); #endif PropertyInfo pi = typeof (Thread).GetProperty ("CurrentPrincipal"); @@ -213,7 +213,7 @@ namespace MonoTests.System.ComponentModel.Design.Serialization { { #if MOBILE // ensure the property is not linked out of the application since it make the test fails - Assert.NotNull (Thread.CurrentPrincipal, "pre-test"); + Assert.IsNotNull (Thread.CurrentPrincipal, "pre-test"); #endif PropertyInfo pi = typeof (Thread).GetProperty ("CurrentPrincipal"); diff --git a/mcs/class/System/Test/System.ComponentModel/CategoryAttributeTests.cs b/mcs/class/System/Test/System.ComponentModel/CategoryAttributeTests.cs index 1d5e4e6dbd..b9261cbe86 100644 --- a/mcs/class/System/Test/System.ComponentModel/CategoryAttributeTests.cs +++ b/mcs/class/System/Test/System.ComponentModel/CategoryAttributeTests.cs @@ -47,7 +47,7 @@ namespace MonoTests.System.ComponentModel { Assert.AreEqual(CM.CategoryAttribute.Key.Category, "Key", "#9"); Assert.AreEqual(CM.CategoryAttribute.Layout.Category, "Layout", "#10"); Assert.AreEqual(CM.CategoryAttribute.Mouse.Category, "Mouse", "#11"); -#if NET_2_1 +#if MOBILE Assert.AreEqual(CM.CategoryAttribute.Default.Category, "Default", "#12"); Assert.AreEqual(CM.CategoryAttribute.DragDrop.Category, "DragDrop", "#13"); Assert.AreEqual(CM.CategoryAttribute.WindowStyle.Category, "WindowStyle", "#14"); diff --git a/mcs/class/System/Test/System.Diagnostics/FileVersionInfoTest.cs.REMOVED.git-id b/mcs/class/System/Test/System.Diagnostics/FileVersionInfoTest.cs.REMOVED.git-id index 2b5697054c..250b5c2b2c 100644 --- a/mcs/class/System/Test/System.Diagnostics/FileVersionInfoTest.cs.REMOVED.git-id +++ b/mcs/class/System/Test/System.Diagnostics/FileVersionInfoTest.cs.REMOVED.git-id @@ -1 +1 @@ -668e863b5cc055feed1a132c8bc42e8fb00e586f \ No newline at end of file +b747e0dd0164e0fc6e98da731bc02b49911c94ef \ No newline at end of file diff --git a/mcs/class/System/Test/System.Diagnostics/ProcessTest.cs b/mcs/class/System/Test/System.Diagnostics/ProcessTest.cs index 75c4614ad2..2776042875 100644 --- a/mcs/class/System/Test/System.Diagnostics/ProcessTest.cs +++ b/mcs/class/System/Test/System.Diagnostics/ProcessTest.cs @@ -1084,6 +1084,27 @@ namespace MonoTests.System.Diagnostics Assert.Fail (); } } + + [Test] + [NUnit.Framework.Category ("MobileNotWorking")] + public void TestExitedRaisedTooSoon () + { + if (!RunningOnUnix) + Assert.Ignore ("using sleep command, only available on unix"); + + int sleeptime = 5; + + using (Process p = Process.Start("sleep", sleeptime.ToString ())) { + ManualResetEvent mre = new ManualResetEvent (false); + + p.EnableRaisingEvents = true; + p.Exited += (sender, e) => { + mre.Set (); + }; + + Assert.IsFalse (mre.WaitOne ((sleeptime - 2) * 1000), "Exited triggered before the process returned"); + } + } #endif // MONO_FEATURE_PROCESS_START } } diff --git a/mcs/class/System/Test/System.IO.Compression/DeflateStreamTest.cs b/mcs/class/System/Test/System.IO.Compression/DeflateStreamTest.cs index 2ae31073e5..1aa78a9d99 100644 --- a/mcs/class/System/Test/System.IO.Compression/DeflateStreamTest.cs +++ b/mcs/class/System/Test/System.IO.Compression/DeflateStreamTest.cs @@ -343,7 +343,6 @@ namespace MonoTests.System.IO.Compression return new MemoryStream (Encoding.UTF8.GetBytes (s)); } -#if NET_4_5 [Test] public void CheckNet45Overloads () // Xambug #21982 { @@ -361,7 +360,6 @@ namespace MonoTests.System.IO.Compression decompressing.Close(); backing.Close(); } -#endif [Test] [ExpectedException (typeof (ArgumentException))] @@ -412,6 +410,46 @@ namespace MonoTests.System.IO.Compression using (var unZippedStream = new StreamReader (gZipStream, Encoding.UTF8)) { unZipped = unZippedStream.ReadToEnd (); } + + Assert.AreEqual(1877, unZipped.Length); + } + + [Test] + public void Bug44994_Inflate() + { + var base64String = @"7cWxCQAgDACwpeBjgqsgXiHU0fd9QzBLErX1EQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADepcxcuU/atm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm37zy8="; + + byte[] byteArray = Convert.FromBase64String(base64String); + string unZipped = null; + + using (var zippedMemoryStream = new MemoryStream(byteArray)) + using (var gZipStream = new DeflateStream(zippedMemoryStream, CompressionMode.Decompress)) + using (var unzippedMemStream = new MemoryStream()) + using (var unZippedStream = new StreamReader(gZipStream, Encoding.UTF8)) + { + unZipped = unZippedStream.ReadToEnd(); + } + + Assert.AreEqual(81942, unZipped.Length); + } + + [Test] + [Category ("MobileNotWorking")] + public void Bug44994_InflateByteByByte() + { + int byteCount = 0; + using (var fileStream = File.OpenRead(Path.Combine("Test", "compressed.bin"))) + { + using (var deflateStream = new DeflateStream(fileStream, CompressionMode.Decompress, false)) + { + while (deflateStream.ReadByte() != -1) + { + byteCount++; + } + } + } + + Assert.AreEqual(125387, byteCount); } } } diff --git a/mcs/class/System/Test/System.IO.Compression/GzipStreamTest.cs b/mcs/class/System/Test/System.IO.Compression/GzipStreamTest.cs index a72ffc6ee0..47a740ca14 100644 --- a/mcs/class/System/Test/System.IO.Compression/GzipStreamTest.cs +++ b/mcs/class/System/Test/System.IO.Compression/GzipStreamTest.cs @@ -303,7 +303,6 @@ namespace MonoTests.System.IO.Compression return new MemoryStream (Encoding.UTF8.GetBytes (s)); } -#if NET_4_5 [Test] public void CheckNet45Overloads () // Xambug #21982 { @@ -321,7 +320,6 @@ namespace MonoTests.System.IO.Compression decompressing.Close(); backing.Close(); } -#endif } } diff --git a/mcs/class/System/Test/System.Net.Mail/SmtpClientTest.cs b/mcs/class/System/Test/System.Net.Mail/SmtpClientTest.cs index 8fa752a447..d3a39e4131 100644 --- a/mcs/class/System/Test/System.Net.Mail/SmtpClientTest.cs +++ b/mcs/class/System/Test/System.Net.Mail/SmtpClientTest.cs @@ -18,13 +18,13 @@ namespace MonoTests.System.Net.Mail [TestFixture] public class SmtpClientTest { - SmtpClient smtp; + SmtpClient _smtp; + SmtpClient smtp { get { return _smtp ?? (_smtp = new SmtpClient ()); } } string tempFolder; [SetUp] public void GetReady () { - smtp = new SmtpClient (); tempFolder = Path.Combine (Path.GetTempPath (), this.GetType ().FullName); if (Directory.Exists (tempFolder)) Directory.Delete (tempFolder, true); @@ -34,17 +34,24 @@ namespace MonoTests.System.Net.Mail [TearDown] public void TearDown () { + _smtp = null; if (Directory.Exists (tempFolder)) Directory.Delete (tempFolder, true); } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Credentials_Default () { Assert.IsNull (smtp.Credentials); } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void DeliveryMethod () { Assert.AreEqual (SmtpDeliveryMethod.Network, smtp.DeliveryMethod, "#1"); @@ -60,6 +67,9 @@ namespace MonoTests.System.Net.Mail } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void EnableSsl () { Assert.IsFalse (smtp.EnableSsl, "#1"); @@ -70,6 +80,9 @@ namespace MonoTests.System.Net.Mail } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Host () { smtp.Host = "127.0.0.1"; @@ -86,6 +99,9 @@ namespace MonoTests.System.Net.Mail } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Host_Value_Null () { try { @@ -100,6 +116,9 @@ namespace MonoTests.System.Net.Mail } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Host_Value_Empty () { try { @@ -115,6 +134,9 @@ namespace MonoTests.System.Net.Mail } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void PickupDirectoryLocation () { Assert.IsNull (smtp.PickupDirectoryLocation, "#1"); @@ -131,6 +153,9 @@ namespace MonoTests.System.Net.Mail } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Port () { Assert.AreEqual (25, smtp.Port, "#1"); @@ -141,6 +166,9 @@ namespace MonoTests.System.Net.Mail } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Port_Value_Invalid () { // zero @@ -167,6 +195,9 @@ namespace MonoTests.System.Net.Mail } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Send_Message_Null () { try { @@ -181,6 +212,9 @@ namespace MonoTests.System.Net.Mail } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Send_Network_Host_Null () { try { @@ -196,6 +230,9 @@ namespace MonoTests.System.Net.Mail } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Send_Network_Host_Whitespace () { smtp.Host = " \r\n "; @@ -212,6 +249,9 @@ namespace MonoTests.System.Net.Mail } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Send_SpecifiedPickupDirectory () { smtp.DeliveryMethod = SmtpDeliveryMethod.SpecifiedPickupDirectory; @@ -225,6 +265,9 @@ namespace MonoTests.System.Net.Mail } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Send_SpecifiedPickupDirectory_PickupDirectoryLocation_DirectoryNotFound () { Directory.Delete (tempFolder); @@ -252,6 +295,9 @@ namespace MonoTests.System.Net.Mail } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Send_SpecifiedPickupDirectory_PickupDirectoryLocation_Empty () { smtp.DeliveryMethod = SmtpDeliveryMethod.SpecifiedPickupDirectory; @@ -271,6 +317,9 @@ namespace MonoTests.System.Net.Mail } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Send_SpecifiedPickupDirectory_PickupDirectoryLocation_IllegalChars () { smtp.DeliveryMethod = SmtpDeliveryMethod.SpecifiedPickupDirectory; @@ -296,6 +345,9 @@ namespace MonoTests.System.Net.Mail } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Send_SpecifiedPickupDirectory_PickupDirectoryLocation_NotAbsolute () { smtp.DeliveryMethod = SmtpDeliveryMethod.SpecifiedPickupDirectory; @@ -315,6 +367,9 @@ namespace MonoTests.System.Net.Mail } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Send_SpecifiedPickupDirectory_PickupDirectoryLocation_Null () { smtp.DeliveryMethod = SmtpDeliveryMethod.SpecifiedPickupDirectory; @@ -333,6 +388,9 @@ namespace MonoTests.System.Net.Mail } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Timeout () { Assert.AreEqual (100000, smtp.Timeout, "#1"); @@ -343,19 +401,29 @@ namespace MonoTests.System.Net.Mail } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#else [ExpectedException (typeof (ArgumentOutOfRangeException))] +#endif public void Timeout_Value_Negative () { smtp.Timeout = -1; } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void UseDefaultCredentials_Default () { Assert.IsFalse (smtp.UseDefaultCredentials); } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Deliver () { var server = new SmtpServer (); @@ -372,6 +440,9 @@ namespace MonoTests.System.Net.Mail } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Deliver_Envelope () { var server = new SmtpServer (); @@ -390,6 +461,9 @@ namespace MonoTests.System.Net.Mail } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Deliver_Async () { // SmtpClient uses BackgroundWorker and listens for the RunWorkerCompleted diff --git a/mcs/class/System/Test/System.Net.Security/SslStreamTest.cs b/mcs/class/System/Test/System.Net.Security/SslStreamTest.cs index 68118776fb..e3542c34f3 100644 --- a/mcs/class/System/Test/System.Net.Security/SslStreamTest.cs +++ b/mcs/class/System/Test/System.Net.Security/SslStreamTest.cs @@ -59,6 +59,9 @@ public class SslStreamTest { } [Test] //bug https://bugzilla.novell.com/show_bug.cgi?id=457120 +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void AuthenticateClientAndServer_ClientSendsNoData () { AuthenticateClientAndServer (true, true); diff --git a/mcs/class/System/Test/System.Net.Sockets/NetworkStreamTest.cs b/mcs/class/System/Test/System.Net.Sockets/NetworkStreamTest.cs index 9c3765e2d5..0af239d238 100644 --- a/mcs/class/System/Test/System.Net.Sockets/NetworkStreamTest.cs +++ b/mcs/class/System/Test/System.Net.Sockets/NetworkStreamTest.cs @@ -20,7 +20,12 @@ namespace MonoTests.System.Net.Sockets { [Test] // See bug #371923 + +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#else [ExpectedException(typeof(IOException))] +#endif public void NetworkStreamConnection () { IPEndPoint ipe = new IPEndPoint(Dns.GetHostEntry ("www.google.com").AddressList [0], 80); @@ -30,6 +35,9 @@ namespace MonoTests.System.Net.Sockets } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ReadTimeout () { Socket sock = new Socket (AddressFamily.InterNetwork, diff --git a/mcs/class/System/Test/System.Net.Sockets/SocketAcceptAsyncTest.cs b/mcs/class/System/Test/System.Net.Sockets/SocketAcceptAsyncTest.cs index 3815b623c3..79e47a0af5 100644 --- a/mcs/class/System/Test/System.Net.Sockets/SocketAcceptAsyncTest.cs +++ b/mcs/class/System/Test/System.Net.Sockets/SocketAcceptAsyncTest.cs @@ -1,3 +1,4 @@ +using System; using System.Threading; using System.Net; using System.Net.Sockets; @@ -9,6 +10,9 @@ namespace MonoTests.System.Net.Sockets public class SocketAcceptAsyncTest { [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void AcceptAsyncShouldUseAcceptSocketFromEventArgs() { var readyEvent = new ManualResetEvent(false); @@ -18,27 +22,40 @@ namespace MonoTests.System.Net.Sockets var serverSocket = new Socket( AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); Socket acceptedSocket = null; - + Exception ex = null; ThreadPool.QueueUserWorkItem(_ => { - listenSocket.Bind(new IPEndPoint(IPAddress.Loopback, 0)); - listenSocket.Listen(1); + SocketAsyncEventArgs asyncEventArgs; + try { + listenSocket.Bind(new IPEndPoint(IPAddress.Loopback, 0)); + listenSocket.Listen(1); - var asyncEventArgs = new SocketAsyncEventArgs {AcceptSocket = serverSocket}; - asyncEventArgs.Completed += (s, e) => - { - acceptedSocket = e.AcceptSocket; - mainEvent.Set(); - }; + asyncEventArgs = new SocketAsyncEventArgs {AcceptSocket = serverSocket}; + asyncEventArgs.Completed += (s, e) => + { + acceptedSocket = e.AcceptSocket; + mainEvent.Set(); + }; - readyEvent.Set(); - - if (listenSocket.AcceptAsync(asyncEventArgs)) + } catch (Exception e) { + ex = e; return; - acceptedSocket = asyncEventArgs.AcceptSocket; - mainEvent.Set(); + } finally { + readyEvent.Set(); + } + + try { + if (listenSocket.AcceptAsync(asyncEventArgs)) + return; + acceptedSocket = asyncEventArgs.AcceptSocket; + mainEvent.Set(); + } catch (Exception e) { + ex = e; + } }); Assert.IsTrue(readyEvent.WaitOne(1500)); + if (ex != null) + throw ex; var clientSocket = new Socket( AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); diff --git a/mcs/class/System/Test/System.Net.Sockets/SocketAsyncTest.cs b/mcs/class/System/Test/System.Net.Sockets/SocketAsyncTest.cs index d59d39fad8..df31233d68 100644 --- a/mcs/class/System/Test/System.Net.Sockets/SocketAsyncTest.cs +++ b/mcs/class/System/Test/System.Net.Sockets/SocketAsyncTest.cs @@ -16,8 +16,7 @@ namespace MonoTests.System.Net.Sockets ManualResetEvent mainEvent; Exception error; - [TestFixtureSetUp] - public void SetUp () + void SetUp () { readyEvent = new ManualResetEvent (false); mainEvent = new ManualResetEvent (false); @@ -25,6 +24,9 @@ namespace MonoTests.System.Net.Sockets ThreadPool.QueueUserWorkItem (_ => DoWork ()); readyEvent.WaitOne (); + if (error != null) + throw error; + clientSocket = new Socket ( AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); clientSocket.Connect (serverSocket.LocalEndPoint); @@ -42,18 +44,22 @@ namespace MonoTests.System.Net.Sockets void DoWork () { - serverSocket = new Socket ( - AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); - serverSocket.Bind (new IPEndPoint (IPAddress.Loopback, 0)); - serverSocket.Listen (1); + try { + serverSocket = new Socket ( + AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + serverSocket.Bind (new IPEndPoint (IPAddress.Loopback, 0)); + serverSocket.Listen (1); - var async = new SocketAsyncEventArgs (); - async.Completed += (s,e) => OnAccepted (e); + var async = new SocketAsyncEventArgs (); + async.Completed += (s,e) => OnAccepted (e); - readyEvent.Set (); - - if (!serverSocket.AcceptAsync (async)) - OnAccepted (async); + if (!serverSocket.AcceptAsync (async)) + OnAccepted (async); + } catch (Exception e) { + error = e; + } finally { + readyEvent.Set (); + } } void OnAccepted (SocketAsyncEventArgs e) @@ -92,8 +98,12 @@ namespace MonoTests.System.Net.Sockets [Test] [Category("Test")] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void SendAsync () { + SetUp (); var buffer = new byte [] { 0x12, 0x34, 0x56, 0x78 }; var m = new ManualResetEvent (false); var e = new SocketAsyncEventArgs (); diff --git a/mcs/class/System/Test/System.Net.Sockets/SocketTest.cs.REMOVED.git-id b/mcs/class/System/Test/System.Net.Sockets/SocketTest.cs.REMOVED.git-id index de77c9a66c..3973ae747b 100644 --- a/mcs/class/System/Test/System.Net.Sockets/SocketTest.cs.REMOVED.git-id +++ b/mcs/class/System/Test/System.Net.Sockets/SocketTest.cs.REMOVED.git-id @@ -1 +1 @@ -7d024238d081e85b535a28cb160e824d94975df7 \ No newline at end of file +14ec2700869c289ee1159851c5402e07138b70a5 \ No newline at end of file diff --git a/mcs/class/System/Test/System.Net.Sockets/TcpClientTest.cs b/mcs/class/System/Test/System.Net.Sockets/TcpClientTest.cs index 91b461487e..5db3aadbc8 100644 --- a/mcs/class/System/Test/System.Net.Sockets/TcpClientTest.cs +++ b/mcs/class/System/Test/System.Net.Sockets/TcpClientTest.cs @@ -29,6 +29,9 @@ namespace MonoTests.System.Net.Sockets /// (from System.Net.Sockets) ///
[Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void TcpClient() { // set up a listening Socket @@ -76,6 +79,9 @@ namespace MonoTests.System.Net.Sockets } [Test] // bug #81105 +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void CloseTest () { var port = NetworkHelpers.FindFreePort (); @@ -139,7 +145,11 @@ namespace MonoTests.System.Net.Sockets } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#else [ExpectedException (typeof(ArgumentNullException))] +#endif public void ConnectMultiNull () { TcpClient client = new TcpClient (); @@ -149,6 +159,9 @@ namespace MonoTests.System.Net.Sockets } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ConnectMultiAny () { TcpClient client = new TcpClient (); @@ -167,6 +180,9 @@ namespace MonoTests.System.Net.Sockets } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ConnectMultiRefused () { TcpClient client = new TcpClient (); diff --git a/mcs/class/System/Test/System.Net.Sockets/TcpListenerTest.cs b/mcs/class/System/Test/System.Net.Sockets/TcpListenerTest.cs index b8594b8f11..25e8854ed6 100644 --- a/mcs/class/System/Test/System.Net.Sockets/TcpListenerTest.cs +++ b/mcs/class/System/Test/System.Net.Sockets/TcpListenerTest.cs @@ -23,6 +23,9 @@ namespace MonoTests.System.Net.Sockets public class TcpListenerTest { [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void TcpListener () { var port = NetworkHelpers.FindFreePort (); @@ -74,6 +77,9 @@ namespace MonoTests.System.Net.Sockets } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void CtorInt1 () { int nex = 0; @@ -86,21 +92,33 @@ namespace MonoTests.System.Net.Sockets } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#else [ExpectedException (typeof (ArgumentNullException))] +#endif public void CtorIPEndPoint () { new TcpListener (null); } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#else [ExpectedException (typeof (ArgumentNullException))] +#endif public void CtorIPAddressInt1 () { new TcpListener (null, 100000); } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#else [ExpectedException (typeof (ArgumentOutOfRangeException))] +#endif public void CtorIPAddressInt2 () { new TcpListener (IPAddress.Any, 100000); @@ -124,6 +142,9 @@ namespace MonoTests.System.Net.Sockets } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void PreStartStatus () { MyListener listener = new MyListener (); @@ -151,6 +172,9 @@ namespace MonoTests.System.Net.Sockets } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void PostStartStatus () { MyListener listener = new MyListener (); @@ -172,6 +196,9 @@ namespace MonoTests.System.Net.Sockets } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void StartListenMoreThan5 () { var port = NetworkHelpers.FindFreePort (); diff --git a/mcs/class/System/Test/System.Net.Sockets/UdpClientTest.cs b/mcs/class/System/Test/System.Net.Sockets/UdpClientTest.cs index b7a537f662..996da16f5c 100644 --- a/mcs/class/System/Test/System.Net.Sockets/UdpClientTest.cs +++ b/mcs/class/System/Test/System.Net.Sockets/UdpClientTest.cs @@ -17,6 +17,9 @@ namespace MonoTests.System.Net.Sockets { [TestFixture] public class UdpClientTest { [Test] // .ctor () +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Constructor1 () { MyUdpClient client; @@ -42,6 +45,9 @@ namespace MonoTests.System.Net.Sockets { } [Test] // .ctor (AddressFamily) +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Constructor2 () { MyUdpClient client; @@ -87,6 +93,9 @@ namespace MonoTests.System.Net.Sockets { } [Test] // .ctor (AddressFamily) +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Constructor2_Family_Invalid () { try { @@ -113,6 +122,9 @@ namespace MonoTests.System.Net.Sockets { } [Test] // .ctor (Int32) +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Constructor3 () { Socket s; @@ -162,6 +174,9 @@ namespace MonoTests.System.Net.Sockets { } [Test] // .ctor (Int32) +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Constructor3_Port_OutOfRange () { try { @@ -188,6 +203,9 @@ namespace MonoTests.System.Net.Sockets { } [Test] // .ctor (IPEndPoint) +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Constructor4 () { Socket s; @@ -220,6 +238,9 @@ namespace MonoTests.System.Net.Sockets { } [Test] // .ctor (IPEndPoint) +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Constructor4_LocalEP_Null () { try { @@ -234,6 +255,9 @@ namespace MonoTests.System.Net.Sockets { } [Test] // .ctor (Int32, AddressFamily) +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Constructor5 () { Socket s; @@ -287,6 +311,9 @@ namespace MonoTests.System.Net.Sockets { } [Test] // .ctor (Int32, AddressFamily) +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Constructor5_Family_Invalid () { try { @@ -317,6 +344,9 @@ namespace MonoTests.System.Net.Sockets { } [Test] // .ctor (Int32, AddressFamily) +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Constructor5_Port_OutOfRange () { try { @@ -343,6 +373,9 @@ namespace MonoTests.System.Net.Sockets { } [Test] // .ctor (String, Int32) +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Constructor6 () { Socket s; @@ -393,6 +426,9 @@ namespace MonoTests.System.Net.Sockets { } [Test] // .ctor (String, Int32) +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Constructor6_HostName_Null () { try { @@ -407,6 +443,9 @@ namespace MonoTests.System.Net.Sockets { } [Test] // .ctor (String, Int32) +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Constructor6_Port_OutOfRange () { try { @@ -433,6 +472,9 @@ namespace MonoTests.System.Net.Sockets { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void UdpClientBroadcastTest () { UdpClient client = new UdpClient (); @@ -446,6 +488,9 @@ namespace MonoTests.System.Net.Sockets { } [Test] // JoinMulticastGroup (IPAddress) +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void JoinMulticastGroup1_IPv4 () { IPAddress mcast_addr = IPAddress.Parse ("224.0.0.23"); @@ -456,6 +501,9 @@ namespace MonoTests.System.Net.Sockets { } [Test] // JoinMulticastGroup (IPAddress) +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void JoinMulticastGroup1_IPv6 () { if (!Socket.OSSupportsIPv6) @@ -469,6 +517,9 @@ namespace MonoTests.System.Net.Sockets { } [Test] // JoinMulticastGroup (IPAddress) +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void JoinMulticastGroup1_MulticastAddr_Null () { using (UdpClient client = new UdpClient (new IPEndPoint (IPAddress.Loopback, 1234))) { @@ -485,6 +536,9 @@ namespace MonoTests.System.Net.Sockets { } [Test] // JoinMulticastGroup (IPAddress) +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void JoinMulticastGroup1_Socket_Closed () { IPAddress mcast_addr = null; @@ -527,6 +581,9 @@ namespace MonoTests.System.Net.Sockets { } [Test] // JoinMulticastGroup (In32, IPAddress) +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void JoinMulticastGroup2_IPv4 () { IPAddress mcast_addr = IPAddress.Parse ("224.0.0.23"); @@ -549,6 +606,9 @@ namespace MonoTests.System.Net.Sockets { } [Test] // JoinMulticastGroup (In32, IPAddress) +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void JoinMulticastGroup2_IPv6 () { if (!Socket.OSSupportsIPv6) @@ -562,6 +622,9 @@ namespace MonoTests.System.Net.Sockets { } [Test] // JoinMulticastGroup (Int32, IPAddress) +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void JoinMulticastGroup2_MulticastAddr_Null () { using (UdpClient client = new UdpClient (new IPEndPoint (IPAddress.Loopback, 1234))) { @@ -578,6 +641,9 @@ namespace MonoTests.System.Net.Sockets { } [Test] // JoinMulticastGroup (Int32, IPAddress) +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void JoinMulticastGroup2_Socket_Closed () { if (!Socket.OSSupportsIPv6) @@ -623,6 +689,9 @@ namespace MonoTests.System.Net.Sockets { } [Test] // JoinMulticastGroup (IPAddress, Int32) +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void JoinMulticastGroup3_IPv4 () { IPAddress mcast_addr = IPAddress.Parse ("224.0.0.23"); @@ -637,6 +706,9 @@ namespace MonoTests.System.Net.Sockets { } [Test] // JoinMulticastGroup (IPAddress, Int32) +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void JoinMulticastGroup3_IPv6 () { if (!Socket.OSSupportsIPv6) @@ -654,6 +726,9 @@ namespace MonoTests.System.Net.Sockets { } [Test] // JoinMulticastGroup (IPAddress, Int32) +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void JoinMulticastGroup3_MulticastAddr_Null () { using (UdpClient client = new UdpClient (new IPEndPoint (IPAddress.Loopback, 1234))) { @@ -670,6 +745,9 @@ namespace MonoTests.System.Net.Sockets { } [Test] // JoinMulticastGroup (IPAddress, Int32) +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void JoinMulticastGroup3_Socket_Closed () { IPAddress mcast_addr = null; @@ -712,6 +790,9 @@ namespace MonoTests.System.Net.Sockets { } [Test] // JoinMulticastGroup (IPAddress, IPAddress) +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void JoinMulticastGroup4_IPv4 () { IPAddress mcast_addr = IPAddress.Parse ("224.0.0.23"); @@ -723,6 +804,9 @@ namespace MonoTests.System.Net.Sockets { } [Test] // JoinMulticastGroup (IPAddress, IPAddress) +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void JoinMulticastGroup4_IPv6 () { if (!Socket.OSSupportsIPv6) @@ -749,6 +833,9 @@ namespace MonoTests.System.Net.Sockets { } [Test] // JoinMulticastGroup (IPAddress, IPAddress) +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void JoinMulticastGroup4_LocalAddress_Null () { IPAddress mcast_addr = IPAddress.Parse ("224.0.0.23"); @@ -767,6 +854,9 @@ namespace MonoTests.System.Net.Sockets { } [Test] // JoinMulticastGroup (IPAddress, IPAddress) +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void JoinMulticastGroup4_MulticastAddr_Null () { using (UdpClient client = new UdpClient (new IPEndPoint (IPAddress.Loopback, 1234))) { @@ -783,6 +873,9 @@ namespace MonoTests.System.Net.Sockets { } [Test] // JoinMulticastGroup (IPAddress, IPAddress) +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void JoinMulticastGroup4_Socket_Closed () { IPAddress mcast_addr = null; @@ -827,6 +920,9 @@ namespace MonoTests.System.Net.Sockets { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void CloseInReceive () { UdpClient client = null; @@ -867,6 +963,9 @@ namespace MonoTests.System.Net.Sockets { // Test for bug 324033 [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void JoinMulticastGroupWithLocal () { UdpClient client = new UdpClient (9001); @@ -881,7 +980,11 @@ namespace MonoTests.System.Net.Sockets { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#else [ExpectedException (typeof(ArgumentNullException))] +#endif public void BeginSendNull () { UdpClient client = new UdpClient (); @@ -904,6 +1007,9 @@ namespace MonoTests.System.Net.Sockets { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void BeginSend () { UdpClient client = new UdpClient (); @@ -958,6 +1064,9 @@ namespace MonoTests.System.Net.Sockets { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void BeginReceive () { UdpClient client = new UdpClient (1237); @@ -983,6 +1092,9 @@ namespace MonoTests.System.Net.Sockets { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Available () { using (UdpClient client = new UdpClient (1238)) { @@ -1017,6 +1129,9 @@ namespace MonoTests.System.Net.Sockets { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void EnableBroadcastDefault () { UdpClient client = new UdpClient (); @@ -1056,6 +1171,9 @@ namespace MonoTests.System.Net.Sockets { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void MulticastLoopbackDefault () { UdpClient client = new UdpClient (); @@ -1066,6 +1184,9 @@ namespace MonoTests.System.Net.Sockets { } [Test] // #6057 +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ReceiveIPv6 () { if (!Socket.OSSupportsIPv6) diff --git a/mcs/class/System/Test/System.Net.WebSockets/ClientWebSocketTest.cs b/mcs/class/System/Test/System.Net.WebSockets/ClientWebSocketTest.cs index 0638cb720b..e3dd58188c 100644 --- a/mcs/class/System/Test/System.Net.WebSockets/ClientWebSocketTest.cs +++ b/mcs/class/System/Test/System.Net.WebSockets/ClientWebSocketTest.cs @@ -1,4 +1,3 @@ -#if NET_4_5 using System; using System.Net; using System.Threading; @@ -19,31 +18,33 @@ namespace MonoTests.System.Net.WebSockets { const string EchoServerUrl = "ws://corefx-net.cloudapp.net/WebSocket/EchoWebSocket.ashx"; int Port = NetworkHelpers.FindFreePort (); - HttpListener listener; - ClientWebSocket socket; - MethodInfo headerSetMethod; - - [SetUp] - public void Setup () - { - listener = new HttpListener (); - listener.Prefixes.Add ("http://localhost:" + Port + "/"); - listener.Start (); - socket = new ClientWebSocket (); + HttpListener _listener; + HttpListener listener { + get { + if (_listener != null) + return _listener; + var tmp = new HttpListener (); + tmp.Prefixes.Add ("http://localhost:" + Port + "/"); + tmp.Start (); + return _listener = tmp; + } } + ClientWebSocket _socket; + ClientWebSocket socket { get { return _socket ?? (_socket = new ClientWebSocket ()); } } + MethodInfo headerSetMethod; [TearDown] public void Teardown () { - if (listener != null) { - listener.Stop (); - listener = null; + if (_listener != null) { + _listener.Stop (); + _listener = null; } - if (socket != null) { - if (socket.State == WebSocketState.Open) - socket.CloseAsync (WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None).Wait (2000); - socket.Dispose (); - socket = null; + if (_socket != null) { + if (_socket.State == WebSocketState.Open) + _socket.CloseAsync (WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None).Wait (2000); + _socket.Dispose (); + _socket = null; } } @@ -297,4 +298,3 @@ namespace MonoTests.System.Net.WebSockets } } -#endif diff --git a/mcs/class/System/Test/System.Net/CookieParserTest.cs b/mcs/class/System/Test/System.Net/CookieParserTest.cs index da02abdd54..f3c4eceea7 100644 --- a/mcs/class/System/Test/System.Net/CookieParserTest.cs +++ b/mcs/class/System/Test/System.Net/CookieParserTest.cs @@ -71,6 +71,9 @@ namespace MonoTests.System.Net } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void TestExpires () { var cookies = DoRequest (A); @@ -81,6 +84,9 @@ namespace MonoTests.System.Net } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void TestInvalidCookie () { var cookies = DoRequest (B); @@ -91,6 +97,9 @@ namespace MonoTests.System.Net } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void TestLocalCulture () { var old = Thread.CurrentThread.CurrentCulture; @@ -108,6 +117,9 @@ namespace MonoTests.System.Net } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void TestMultiple () { var cookies = DoRequest (D); @@ -118,6 +130,9 @@ namespace MonoTests.System.Net } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void TestMultiple2 () { var cookies = DoRequest (E); @@ -127,6 +142,9 @@ namespace MonoTests.System.Net } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void TestQuotation () { var cookies = DoRequest (F); @@ -139,6 +157,7 @@ namespace MonoTests.System.Net { Socket socket; string[] headers; + Exception ex; public Listener (params string[] headers) { @@ -154,17 +173,28 @@ namespace MonoTests.System.Net socket.Bind (new IPEndPoint (IPAddress.Loopback, 0)); socket.Listen (1); socket.BeginAccept ((result) => { - var accepted = socket.EndAccept (result); - HandleRequest (accepted); + try { + var accepted = socket.EndAccept (result); + HandleRequest (accepted); + } catch (Exception e) { + ex = e; + } }, null); } + void ThrowIfException () + { + if (ex != null) + throw ex; + } + public void Dispose () { if (socket != null) { socket.Close (); socket = null; } + ThrowIfException (); } void HandleRequest (Socket accepted) @@ -182,11 +212,17 @@ namespace MonoTests.System.Net } public EndPoint EndPoint { - get { return socket.LocalEndPoint; } + get { + ThrowIfException (); + return socket.LocalEndPoint; + } } public string URI { - get { return string.Format ("http://{0}/", EndPoint); } + get { + ThrowIfException (); + return string.Format ("http://{0}/", EndPoint); + } } } } diff --git a/mcs/class/System/Test/System.Net/DnsTest.cs b/mcs/class/System/Test/System.Net/DnsTest.cs index a1b5f51cdd..fef0145418 100644 --- a/mcs/class/System/Test/System.Net/DnsTest.cs +++ b/mcs/class/System/Test/System.Net/DnsTest.cs @@ -29,41 +29,77 @@ namespace MonoTests.System.Net private uint site1IP = 134744072, site2IP = 134743044; // Big-Endian [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void AsyncGetHostByName () { - IAsyncResult r; - r = Dns.BeginGetHostByName (site1Name, new AsyncCallback (GetHostByNameCallback), null); - IAsyncResult async = Dns.BeginGetHostByName (site1Name, null, null); IPHostEntry entry = Dns.EndGetHostByName (async); SubTestValidIPHostEntry (entry); Assert.IsTrue (entry.HostName == "google-public-dns-a.google.com"); } - void GetHostByNameCallback (IAsyncResult ar) + [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif + public void AsyncGetHostByNameCallback () { - IPHostEntry h; - h = Dns.EndGetHostByName (ar); - SubTestValidIPHostEntry (h); + var evt = new ManualResetEvent (false); + Exception ex = null; + Dns.BeginGetHostByName (site1Name, new AsyncCallback ((IAsyncResult ar) => + { + try { + IPHostEntry h; + h = Dns.EndGetHostByName (ar); + SubTestValidIPHostEntry (h); + } catch (Exception e) { + ex = e; + } finally { + evt.Set (); + } + }), null); + + Assert.IsTrue (evt.WaitOne (TimeSpan.FromSeconds (60)), "Wait"); + Assert.IsNull (ex, "Exception"); } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void AsyncResolve () { - IAsyncResult r; - r = Dns.BeginResolve (site1Name, new AsyncCallback (ResolveCallback), null); - IAsyncResult async = Dns.BeginResolve (site1Dot, null, null); IPHostEntry entry = Dns.EndResolve (async); - SubTestValidIPHostEntry (entry); + SubTestValidIPHostEntry (entry); var ip = GetIPv4Address (entry); Assert.AreEqual (site1Dot, ip.ToString ()); } - void ResolveCallback (IAsyncResult ar) + [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif + public void AsyncResolveCallback () { - IPHostEntry h = Dns.EndResolve (ar); - SubTestValidIPHostEntry (h); + var evt = new ManualResetEvent (false); + Exception ex = null; + Dns.BeginResolve (site1Name, new AsyncCallback ((IAsyncResult ar) => + { + try { + IPHostEntry h = Dns.EndResolve (ar); + SubTestValidIPHostEntry (h); + } catch (Exception e) { + ex = e; + } finally { + evt.Set (); + } + }), null); + + Assert.IsTrue (evt.WaitOne (TimeSpan.FromSeconds (60)), "Wait"); + Assert.IsNull (ex, "Exception"); } [Test] @@ -72,7 +108,7 @@ namespace MonoTests.System.Net try { Dns.BeginGetHostAddresses ( (string) null, - new AsyncCallback (GetHostAddressesCallback), + new AsyncCallback (ShouldntBeCalled), null); Assert.Fail ("#1"); } catch (ArgumentNullException ex) { @@ -90,7 +126,7 @@ namespace MonoTests.System.Net try { Dns.BeginGetHostAddresses ( "0.0.0.0", - new AsyncCallback (GetHostAddressesCallback), + new AsyncCallback (ShouldntBeCalled), null); Assert.Fail ("#A1"); } catch (ArgumentException ex) { @@ -107,7 +143,7 @@ namespace MonoTests.System.Net try { Dns.BeginGetHostAddresses ( "::0", - new AsyncCallback (GetHostAddressesCallback), + new AsyncCallback (ShouldntBeCalled), null); Assert.Fail ("#B1"); } catch (ArgumentException ex) { @@ -121,10 +157,9 @@ namespace MonoTests.System.Net } } - void GetHostAddressesCallback (IAsyncResult ar) + void ShouldntBeCalled (IAsyncResult ar) { - IPAddress [] addresses = Dns.EndGetHostAddresses (ar); - Assert.IsNotNull (addresses); + Assert.Fail ("Should not be called"); } [Test] @@ -181,6 +216,9 @@ namespace MonoTests.System.Net } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void GetHostByName () { SubTestGetHostByName (site1Name, site1Dot); @@ -306,17 +344,20 @@ namespace MonoTests.System.Net { IPAddress addr = new IPAddress (IPAddress.NetworkToHostOrder ((int) site2IP)); IPHostEntry h = Dns.GetHostByAddress (addr); - SubTestValidIPHostEntry (h); + SubTestValidIPHostEntry (h); var ip = GetIPv4Address (h); Assert.AreEqual (addr.ToString (), ip.ToString ()); } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void BeginResolve_HostName_Null () { try { Dns.BeginResolve ((string) null, - new AsyncCallback (ResolveCallback), + new AsyncCallback (ShouldntBeCalled), null); Assert.Fail ("#1"); } catch (ArgumentNullException ex) { @@ -328,6 +369,9 @@ namespace MonoTests.System.Net } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Resolve () { SubTestResolve (site1Name); @@ -343,6 +387,9 @@ namespace MonoTests.System.Net } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Resolve_HostName_Null () { try { @@ -357,12 +404,15 @@ namespace MonoTests.System.Net } [Test] // BeginGetHostEntry (IPAddress, AsyncCallback, Object) +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void BeginGetHostEntry1_Address_Null () { try { Dns.BeginGetHostEntry ( (IPAddress) null, - new AsyncCallback (GetHostAddressesCallback), + new AsyncCallback (ShouldntBeCalled), null); Assert.Fail ("#1"); } catch (ArgumentNullException ex) { @@ -374,12 +424,15 @@ namespace MonoTests.System.Net } [Test] // BeginGetHostEntry (String, AsyncCallback, Object) +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void BeginGetHostEntry2_HostNameOrAddress_Null () { try { Dns.BeginGetHostEntry ( (string) null, - new AsyncCallback (GetHostAddressesCallback), + new AsyncCallback (ShouldntBeCalled), null); Assert.Fail ("#1"); } catch (ArgumentNullException ex) { @@ -391,6 +444,9 @@ namespace MonoTests.System.Net } [Test] // BeginGetHostEntry (String, AsyncCallback, Object) +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void BeginGetHostEntry2_HostNameOrAddress_UnspecifiedAddress () { // IPv4 @@ -449,6 +505,9 @@ namespace MonoTests.System.Net } [Test] // GetHostEntry (String) +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void GetHostEntry2 () { Dns.GetHostEntry (site1Name); // hostname diff --git a/mcs/class/System/Test/System.Net/FtpWebRequestTest.cs b/mcs/class/System/Test/System.Net/FtpWebRequestTest.cs index e740e1c67a..771d5d1fb6 100644 --- a/mcs/class/System/Test/System.Net/FtpWebRequestTest.cs +++ b/mcs/class/System/Test/System.Net/FtpWebRequestTest.cs @@ -21,7 +21,10 @@ namespace MonoTests.System.Net [TestFixture] public class FtpWebRequestTest { - FtpWebRequest defaultRequest; + FtpWebRequest _defaultRequest; + FtpWebRequest defaultRequest { + get { return _defaultRequest ?? (_defaultRequest = (FtpWebRequest) WebRequest.Create ("ftp://www.contoso.com")); } + } private string _tempDirectory; private string _tempFile; @@ -48,25 +51,31 @@ namespace MonoTests.System.Net Directory.Delete (_tempDirectory, true); } - [TestFixtureSetUp] - public void Init () - { - defaultRequest = (FtpWebRequest) WebRequest.Create ("ftp://www.contoso.com"); - } - [Test] public void ContentLength () { try { long l = defaultRequest.ContentLength; +#if FEATURE_NO_BSD_SOCKETS + Assert.Fail ("#1a"); + } catch (PlatformNotSupportedException) { + // OK. +#else } catch (NotSupportedException) { Assert.Fail ("#1"); // Not overriden +#endif } try { defaultRequest.ContentLength = 2; +#if FEATURE_NO_BSD_SOCKETS + Assert.Fail ("#2a"); + } catch (PlatformNotSupportedException) { + // OK. +#else } catch (NotSupportedException) { Assert.Fail ("#2"); // Not overriden +#endif } } @@ -87,6 +96,9 @@ namespace MonoTests.System.Net } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ContentOffset () { try { @@ -97,6 +109,9 @@ namespace MonoTests.System.Net } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Credentials () { try { @@ -108,6 +123,9 @@ namespace MonoTests.System.Net } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Method () { try { @@ -145,6 +163,9 @@ namespace MonoTests.System.Net } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ReadWriteTimeout () { try { @@ -155,6 +176,9 @@ namespace MonoTests.System.Net } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Timeout () { try { @@ -165,6 +189,9 @@ namespace MonoTests.System.Net } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void DefaultValues () { FtpWebRequest request = (FtpWebRequest) WebRequest.Create ("ftp://www.contoso.com"); @@ -182,6 +209,9 @@ namespace MonoTests.System.Net } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void RenameTo () { try { @@ -198,11 +228,31 @@ namespace MonoTests.System.Net } [Test] - public void UploadFile1 () +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif + public void UploadFile1_v4 () { - ServerPut sp = new ServerPut (); + UploadFile1 (false); + } + + [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif + public void UploadFile1_v6 () + { + if (!Socket.OSSupportsIPv6) + Assert.Ignore ("IPv6 not supported."); + + UploadFile1 (true); + } + + void UploadFile1 (bool ipv6) + { + ServerPut sp = new ServerPut (ipv6); sp.Start (); - string uri = String.Format ("ftp://{0}:{1}/uploads/file.txt", sp.IPAddress, sp.Port); + string uri = String.Format ("ftp://{0}:{1}/uploads/file.txt", EncloseIPv6 (sp.IPAddress), sp.Port); try { FtpWebRequest ftp = (FtpWebRequest) WebRequest.Create (uri); ftp.KeepAlive = false; @@ -228,15 +278,35 @@ namespace MonoTests.System.Net } [Test] - public void UploadFile_WebClient () +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif + public void UploadFile_WebClient_v4 () { - ServerPut sp = new ServerPut (); + UploadFile_WebClient (false); + } + + [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif + public void UploadFile_WebClient_v6 () + { + if (!Socket.OSSupportsIPv6) + Assert.Ignore ("IPv6 not supported."); + + UploadFile_WebClient (true); + } + + public void UploadFile_WebClient (bool ipv6) + { + ServerPut sp = new ServerPut (ipv6); File.WriteAllText (_tempFile, "0123456789"); sp.Start (); using (WebClient m_WebClient = new WebClient()) { - string uri = String.Format ("ftp://{0}:{1}/uploads/file.txt", sp.IPAddress, sp.Port); + string uri = String.Format ("ftp://{0}:{1}/uploads/file.txt", EncloseIPv6 (sp.IPAddress), sp.Port); m_WebClient.UploadFile(uri, _tempFile); } @@ -246,15 +316,30 @@ namespace MonoTests.System.Net } [Test] - public void DownloadFile1 () +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif + public void DownloadFile1_v4 () { - DownloadFile (new ServerDownload ()); + DownloadFile (new ServerDownload (false)); + } + + [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif + public void DownloadFile1_v6 () + { + if (!Socket.OSSupportsIPv6) + Assert.Ignore ("IPv6 not supported."); + + DownloadFile (new ServerDownload (true)); } void DownloadFile (ServerDownload sp) { sp.Start (); - string uri = String.Format ("ftp://{0}:{1}/file.txt", sp.IPAddress, sp.Port); + string uri = String.Format ("ftp://{0}:{1}/file.txt", EncloseIPv6 (sp.IPAddress), sp.Port); try { FtpWebRequest ftp = (FtpWebRequest) WebRequest.Create (uri); ftp.KeepAlive = false; @@ -278,19 +363,53 @@ namespace MonoTests.System.Net } [Test] - public void DownloadFile2 () +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif + public void DownloadFile2_v4 () { // Some embedded FTP servers in Industrial Automation Hardware report // the PWD using backslashes, but allow forward slashes for CWD. - DownloadFile (new ServerDownload (@"\Users\someuser", "/Users/someuser/")); + DownloadFile (new ServerDownload (@"\Users\someuser", "/Users/someuser/", false)); } [Test] - public void DeleteFile1 () +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif + public void DownloadFile2_v6 () { - ServerDeleteFile sp = new ServerDeleteFile (); + // Some embedded FTP servers in Industrial Automation Hardware report + // the PWD using backslashes, but allow forward slashes for CWD. + DownloadFile (new ServerDownload (@"\Users\someuser", "/Users/someuser/", true)); + } + + [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif + public void DeleteFile1_v4 () + { + DeleteFile1 (false); + } + + [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif + public void DeleteFile1_v6 () + { + if (!Socket.OSSupportsIPv6) + Assert.Ignore ("IPv6 not supported."); + + DeleteFile1 (true); + } + + void DeleteFile1 (bool ipv6) + { + ServerDeleteFile sp = new ServerDeleteFile (ipv6); sp.Start (); - string uri = String.Format ("ftp://{0}:{1}/file.txt", sp.IPAddress, sp.Port); + string uri = String.Format ("ftp://{0}:{1}/file.txt", EncloseIPv6 (sp.IPAddress), sp.Port); try { FtpWebRequest ftp = (FtpWebRequest) WebRequest.Create (uri); Console.WriteLine (ftp.RequestUri); @@ -312,11 +431,31 @@ namespace MonoTests.System.Net } [Test] - public void ListDirectory1 () +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif + public void ListDirectory1_v4 () { - ServerListDirectory sp = new ServerListDirectory (); + ListDirectory1 (false); + } + + [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif + public void ListDirectory1_v6 () + { + if (!Socket.OSSupportsIPv6) + Assert.Ignore ("IPv6 not supported."); + + ListDirectory1 (true); + } + + void ListDirectory1 (bool ipv6) + { + ServerListDirectory sp = new ServerListDirectory (ipv6); sp.Start (); - string uri = String.Format ("ftp://{0}:{1}/somedir/", sp.IPAddress, sp.Port); + string uri = String.Format ("ftp://{0}:{1}/somedir/", EncloseIPv6 (sp.IPAddress), sp.Port); try { FtpWebRequest ftp = (FtpWebRequest) WebRequest.Create (uri); Console.WriteLine (ftp.RequestUri); @@ -339,7 +478,20 @@ namespace MonoTests.System.Net } } + string EncloseIPv6 (IPAddress address) + { + if (address.AddressFamily == AddressFamily.InterNetwork) + return address.ToString (); + + return String.Format ("[{0}]", address.ToString ()); + } + class ServerListDirectory : FtpServer { + public ServerListDirectory (bool ipv6) + : base (ipv6) + { + } + protected override void Run () { Socket client = control.Accept (); @@ -357,24 +509,12 @@ namespace MonoTests.System.Net } string str = reader.ReadLine (); - if (str != "PASV") { - Where = "PASV"; + string resp = FormatPassiveResponse (str); + if (resp == null) { client.Close (); return; } - - IPEndPoint end_data = (IPEndPoint) data.LocalEndPoint; - byte [] addr_bytes = end_data.Address.GetAddressBytes (); - byte [] port = new byte [2]; - port[0] = (byte) ((end_data.Port >> 8) & 255); - port[1] = (byte) (end_data.Port & 255); - StringBuilder sb = new StringBuilder ("227 Passive ("); - foreach (byte b in addr_bytes) { - sb.AppendFormat ("{0},", b); - } - sb.AppendFormat ("{0},", port [0]); - sb.AppendFormat ("{0})", port [1]); - writer.WriteLine (sb.ToString ()); + writer.WriteLine (resp); writer.Flush (); str = reader.ReadLine (); @@ -401,6 +541,11 @@ namespace MonoTests.System.Net } class ServerDeleteFile : FtpServer { + public ServerDeleteFile (bool ipv6) + : base (ipv6) + { + } + protected override void Run () { Socket client = control.Accept (); @@ -437,12 +582,13 @@ namespace MonoTests.System.Net string Pwd, Cwd; - public ServerDownload () - : this (null, null) + public ServerDownload (bool ipv6) + : this (null, null, ipv6) { } - public ServerDownload (string pwd, string cwd) + public ServerDownload (string pwd, string cwd, bool ipv6) + : base (ipv6) { Pwd = pwd ?? "/home/someuser"; Cwd = cwd ?? "/home/someuser/"; @@ -465,24 +611,12 @@ namespace MonoTests.System.Net } string str = reader.ReadLine (); - if (str != "PASV") { - Where = "PASV"; + string resp = FormatPassiveResponse (str); + if (resp == null) { client.Close (); return; } - - IPEndPoint end_data = (IPEndPoint) data.LocalEndPoint; - byte [] addr_bytes = end_data.Address.GetAddressBytes (); - byte [] port = new byte [2]; - port[0] = (byte) ((end_data.Port >> 8) & 255); - port[1] = (byte) (end_data.Port & 255); - StringBuilder sb = new StringBuilder ("227 Passive ("); - foreach (byte b in addr_bytes) { - sb.AppendFormat ("{0},", b); - } - sb.AppendFormat ("{0},", port [0]); - sb.AppendFormat ("{0})", port [1]); - writer.WriteLine (sb.ToString ()); + writer.WriteLine (resp); writer.Flush (); str = reader.ReadLine (); @@ -511,6 +645,11 @@ namespace MonoTests.System.Net class ServerPut : FtpServer { public List result = new List (); + public ServerPut (bool ipv6) + : base (ipv6) + { + } + protected override void Run () { Socket client = control.Accept (); @@ -528,24 +667,12 @@ namespace MonoTests.System.Net } string str = reader.ReadLine (); - if (str != "PASV") { - Where = "PASV"; + string resp = FormatPassiveResponse (str); + if (resp == null) { client.Close (); return; } - - IPEndPoint end_data = (IPEndPoint) data.LocalEndPoint; - byte [] addr_bytes = end_data.Address.GetAddressBytes (); - byte [] port = new byte [2]; - port[0] = (byte) ((end_data.Port >> 8) & 255); - port[1] = (byte) (end_data.Port & 255); - StringBuilder sb = new StringBuilder ("227 Passive ("); - foreach (byte b in addr_bytes) { - sb.AppendFormat ("{0},", b); - } - sb.AppendFormat ("{0},", port [0]); - sb.AppendFormat ("{0})", port [1]); - writer.WriteLine (sb.ToString ()); + writer.WriteLine (resp); writer.Flush (); str = reader.ReadLine (); @@ -579,16 +706,18 @@ namespace MonoTests.System.Net protected Socket control; protected Socket data; protected ManualResetEvent evt; + protected bool ipv6; public string Where = ""; - public FtpServer () + public FtpServer (bool ipv6) { - control = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); - control.Bind (new IPEndPoint (IPAddress.Loopback, 0)); + control = new Socket (ipv6 ? AddressFamily.InterNetworkV6 : AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + control.Bind (new IPEndPoint (ipv6 ? IPAddress.IPv6Loopback : IPAddress.Loopback, 0)); control.Listen (1); - data = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); - data.Bind (new IPEndPoint (IPAddress.Loopback, 0)); + data = new Socket (ipv6 ? AddressFamily.InterNetworkV6 : AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + data.Bind (new IPEndPoint (ipv6 ? IPAddress.IPv6Loopback : IPAddress.Loopback, 0)); data.Listen (1); + this.ipv6 = ipv6; } public void Start () @@ -672,7 +801,39 @@ namespace MonoTests.System.Net writer.Flush (); return true; } - + + protected string FormatPassiveResponse (string request) + { + if (ipv6) { + if (request != "EPSV") { + Where = "EPSV"; + return null; + } + + IPEndPoint end_data = (IPEndPoint) data.LocalEndPoint; + return String.Format ("229 Extended Passive (|||{0}|)", end_data.Port); + } + else { + if (request != "PASV") { + Where = "PASV"; + return null; + } + + IPEndPoint end_data = (IPEndPoint) data.LocalEndPoint; + byte [] addr_bytes = end_data.Address.GetAddressBytes (); + byte [] port = new byte [2]; + port[0] = (byte) ((end_data.Port >> 8) & 255); + port[1] = (byte) (end_data.Port & 255); + StringBuilder sb = new StringBuilder ("227 Passive ("); + foreach (byte b in addr_bytes) { + sb.AppendFormat ("{0},", b); + } + sb.AppendFormat ("{0},", port [0]); + sb.AppendFormat ("{0})", port [1]); + return sb.ToString (); + } + } + public IPAddress IPAddress { get { return ((IPEndPoint) control.LocalEndPoint).Address; } } diff --git a/mcs/class/System/Test/System.Net/HttpListener2Test.cs b/mcs/class/System/Test/System.Net/HttpListener2Test.cs index 77fb73e3f0..51e2990c0d 100644 --- a/mcs/class/System/Test/System.Net/HttpListener2Test.cs +++ b/mcs/class/System/Test/System.Net/HttpListener2Test.cs @@ -146,6 +146,9 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Test1 () { var port = NetworkHelpers.FindFreePort (); @@ -154,10 +157,13 @@ namespace MonoTests.System.Net { Send (ns, "GET / HTTP/1.1\r\n\r\n"); // No host string response = Receive (ns, 512); ns.Close (); - StringAssert.StartsWith ("HTTP/1.1 400", response); + Assert.IsTrue(response.StartsWith ("HTTP/1.1 400")); } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Test2 () { var port = NetworkHelpers.FindFreePort (); @@ -166,10 +172,13 @@ namespace MonoTests.System.Net { Send (ns, "GET / HTTP/1.1\r\nHost: 127.0.0.1\r\n\r\n"); // no prefix string response = Receive (ns, 512); ns.Close (); - StringAssert.StartsWith ("HTTP/1.1 400", response); + Assert.IsTrue(response.StartsWith ("HTTP/1.1 400")); } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Test3 () { StringBuilder bad = new StringBuilder (); @@ -204,11 +213,14 @@ namespace MonoTests.System.Net { string response = Receive (ns, 512); ns.Close (); listener.Close (); - StringAssert.StartsWith ("HTTP/1.1 400", response, String.Format ("Failed on {0}", (int) b)); + Assert.IsTrue(response.StartsWith ("HTTP/1.1 400"), String.Format ("Failed on {0}", (int) b)); } } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Test4 () { var port = NetworkHelpers.FindFreePort (); @@ -217,10 +229,13 @@ namespace MonoTests.System.Net { Send (ns, "POST /test4/ HTTP/1.1\r\nHost: 127.0.0.1\r\n\r\n"); // length required string response = Receive (ns, 512); ns.Close (); - StringAssert.StartsWith ("HTTP/1.1 411", response); + Assert.IsTrue(response.StartsWith ("HTTP/1.1 411")); } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Test5 () { var port = NetworkHelpers.FindFreePort (); @@ -229,10 +244,13 @@ namespace MonoTests.System.Net { Send (ns, "POST / HTTP/1.1\r\nHost: 127.0.0.1\r\nTransfer-Encoding: pepe\r\n\r\n"); // not implemented string response = Receive (ns, 512); ns.Close (); - StringAssert.StartsWith ("HTTP/1.1 501", response); + Assert.IsTrue(response.StartsWith ("HTTP/1.1 501")); } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Test6 () { var port = NetworkHelpers.FindFreePort (); @@ -242,10 +260,13 @@ namespace MonoTests.System.Net { Send (ns, "POST /test6/ HTTP/1.1\r\nHost: 127.0.0.1\r\nTransfer-Encoding: identity\r\n\r\n"); string response = Receive (ns, 512); ns.Close (); - StringAssert.StartsWith ("HTTP/1.1 501", response); + Assert.IsTrue(response.StartsWith ("HTTP/1.1 501")); } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Test7 () { var port = NetworkHelpers.FindFreePort (); @@ -257,11 +278,14 @@ namespace MonoTests.System.Net { ctx.Response.Close (); string response = Receive (ns, 1024); ns.Close (); - StringAssert.StartsWith ("HTTP/1.1 200", response); - StringAssert.Contains ("Transfer-Encoding: chunked", response); + Assert.IsTrue(response.StartsWith ("HTTP/1.1 200")); + Assert.IsTrue(response.Contains ("Transfer-Encoding: chunked")); } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Test8 () { var port = NetworkHelpers.FindFreePort (); @@ -274,11 +298,14 @@ namespace MonoTests.System.Net { ctx.Response.Close (); string response = Receive (ns, 512); ns.Close (); - StringAssert.StartsWith ("HTTP/1.1 200", response); + Assert.IsTrue(response.StartsWith ("HTTP/1.1 200")); Assert.IsTrue (-1 == response.IndexOf ("Transfer-Encoding: chunked")); } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Test9 () { var port = NetworkHelpers.FindFreePort (); @@ -290,10 +317,13 @@ namespace MonoTests.System.Net { string response = ReceiveWithTimeout (ns, 512, 1000, out timeout); ns.Close (); Assert.IsFalse (timeout); - StringAssert.StartsWith ("HTTP/1.1 411", response); + Assert.IsTrue(response.StartsWith ("HTTP/1.1 411")); } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Test10 () { var port = NetworkHelpers.FindFreePort (); @@ -306,10 +336,13 @@ namespace MonoTests.System.Net { string response = ReceiveWithTimeout (ns, 512, 1000, out timeout); ns.Close (); Assert.IsFalse (timeout); - StringAssert.StartsWith ("HTTP/1.1 411", response); + Assert.IsTrue(response.StartsWith ("HTTP/1.1 411")); } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Test11 () { var port = NetworkHelpers.FindFreePort (); @@ -320,10 +353,13 @@ namespace MonoTests.System.Net { ns.GetSocket ().Shutdown (SocketShutdown.Send); string input = Receive (ns, 512); ns.Close (); - StringAssert.StartsWith ("HTTP/1.1 400", input); + Assert.IsTrue(input.StartsWith ("HTTP/1.1 400")); } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Test12 () { var port = NetworkHelpers.FindFreePort (); @@ -334,10 +370,13 @@ namespace MonoTests.System.Net { ns.GetSocket ().Shutdown (SocketShutdown.Send); string input = Receive (ns, 512); ns.Close (); - StringAssert.StartsWith ("HTTP/1.1 400", input); + Assert.IsTrue(input.StartsWith ("HTTP/1.1 400")); } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Test13 () { var port = NetworkHelpers.FindFreePort (); @@ -348,13 +387,16 @@ namespace MonoTests.System.Net { ns.GetSocket ().Shutdown (SocketShutdown.Send); string input = Receive (ns, 512); ns.Close (); - StringAssert.StartsWith ("HTTP/1.1 400", input); + Assert.IsTrue(input.StartsWith ("HTTP/1.1 400")); } HttpListenerRequest test14_request; ManualResetEvent test_evt; bool test14_error; [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Test14 () { var port = NetworkHelpers.FindFreePort (); @@ -391,6 +433,9 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Test15 () { var port = NetworkHelpers.FindFreePort (); @@ -413,6 +458,9 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Test16 () { var port = NetworkHelpers.FindFreePort (); @@ -437,6 +485,9 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Test17 () { var port = NetworkHelpers.FindFreePort (); @@ -448,11 +499,14 @@ namespace MonoTests.System.Net { ctx.Response.Close (); string response = Receive (ns, 1024); ns.Close (); - StringAssert.StartsWith ("HTTP/1.1 200", response); - StringAssert.Contains ("Transfer-Encoding: chunked", response); + Assert.IsTrue(response.StartsWith ("HTTP/1.1 200")); + Assert.IsTrue(response.Contains ("Transfer-Encoding: chunked")); } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Test_MultipleClosesOnOuputStreamAllowed () { var port = NetworkHelpers.FindFreePort (); @@ -483,6 +537,9 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ReceiveCookiesFromClient () { sendCookiePort = NetworkHelpers.FindFreePort (); @@ -529,6 +586,9 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void SendCookiestoClient () { receiveCookiePort = NetworkHelpers.FindFreePort (); @@ -580,6 +640,9 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void MultiResponses () { echoServerPort = NetworkHelpers.FindFreePort (); @@ -647,6 +710,9 @@ namespace MonoTests.System.Net { [TestFixture] public class HttpListenerBugs { [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void TestNonChunkedAsync () { var port = NetworkHelpers.FindFreePort (); @@ -701,6 +767,9 @@ namespace MonoTests.System.Net { // a documented pattern to close the connection // [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Test_MultipleConnections () { var port = NetworkHelpers.FindFreePort (); @@ -731,6 +800,9 @@ namespace MonoTests.System.Net { // Test case for bug 341443, an pretty old bug, filed on November of 2007. // [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Test_HostInUri () { var wait = new ManualResetEvent (false); @@ -760,6 +832,9 @@ namespace MonoTests.System.Net { } [Test] // bug #513849 +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ClosePort () { var port = NetworkHelpers.FindFreePort (); @@ -783,6 +858,9 @@ namespace MonoTests.System.Net { // does not also listen to another interface. // [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void BindToSingleInterface () { IPAddress [] machineAddress = null; @@ -809,6 +887,9 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void BindToAllInterfaces () { var h = new HttpListener (); @@ -821,6 +902,9 @@ namespace MonoTests.System.Net { // Test case for bug #31209 [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Test_EmptyLineAtStart () { var port = NetworkHelpers.FindFreePort (); diff --git a/mcs/class/System/Test/System.Net/HttpListenerPrefixCollectionTest.cs b/mcs/class/System/Test/System.Net/HttpListenerPrefixCollectionTest.cs index 873481cbc5..b09a8180ea 100644 --- a/mcs/class/System/Test/System.Net/HttpListenerPrefixCollectionTest.cs +++ b/mcs/class/System/Test/System.Net/HttpListenerPrefixCollectionTest.cs @@ -36,6 +36,9 @@ namespace MonoTests.System.Net { public class HttpListenerPrefixCollectionTest { // NL -> Not listening -> tests when listener.IsListening == false [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void NL_DefaultProperties () { HttpListener listener = new HttpListener (); @@ -46,6 +49,9 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void DefaultProperties () { HttpListener listener = new HttpListener (); @@ -57,6 +63,9 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void AddOne () { HttpListener listener = new HttpListener (); @@ -70,6 +79,9 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Duplicate () { HttpListener listener = new HttpListener (); @@ -84,6 +96,9 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void EndsWithSlash () { HttpListener listener = new HttpListener (); @@ -91,6 +106,9 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void DifferentPath () { HttpListener listener = new HttpListener (); @@ -100,6 +118,9 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void NL_Clear () { HttpListener listener = new HttpListener (); @@ -108,6 +129,9 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void NL_Remove () { HttpListener listener = new HttpListener (); @@ -116,6 +140,9 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void NL_RemoveBadUri () { HttpListener listener = new HttpListener (); @@ -124,7 +151,11 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#else [ExpectedException (typeof (ArgumentException))] +#endif public void NL_AddBadUri () { HttpListener listener = new HttpListener (); @@ -133,7 +164,11 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#else [ExpectedException (typeof (ArgumentException))] +#endif public void NoHostInUrl () { HttpListener listener = new HttpListener (); @@ -141,6 +176,9 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void MultipleSlashes () { // this one throws on Start(), not when adding it. @@ -154,6 +192,9 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void PercentSign () { HttpListener listener = new HttpListener (); @@ -167,6 +208,9 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Disposed1 () { HttpListener listener = new HttpListener (); @@ -178,7 +222,11 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#else [ExpectedException (typeof (ObjectDisposedException))] +#endif public void Disposed2 () { HttpListener listener = new HttpListener (); @@ -188,7 +236,11 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#else [ExpectedException (typeof (ObjectDisposedException))] +#endif public void Disposed3 () { HttpListener listener = new HttpListener (); @@ -198,7 +250,11 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#else [ExpectedException (typeof (ObjectDisposedException))] +#endif public void Disposed4 () { HttpListener listener = new HttpListener (); @@ -208,7 +264,11 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#else [ExpectedException (typeof (ObjectDisposedException))] +#endif public void Disposed5 () { HttpListener listener = new HttpListener (); @@ -219,6 +279,9 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Disposed6 () { HttpListener listener = new HttpListener (); @@ -232,6 +295,9 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Disposed7 () { HttpListener listener = new HttpListener (); diff --git a/mcs/class/System/Test/System.Net/HttpListenerRequestTest.cs b/mcs/class/System/Test/System.Net/HttpListenerRequestTest.cs index 6ff1b33260..d782103f33 100644 --- a/mcs/class/System/Test/System.Net/HttpListenerRequestTest.cs +++ b/mcs/class/System/Test/System.Net/HttpListenerRequestTest.cs @@ -150,6 +150,9 @@ namespace MonoTests.System.Net } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void HttpMethod () { var port = NetworkHelpers.FindFreePort (); @@ -164,6 +167,9 @@ namespace MonoTests.System.Net } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void HttpBasicAuthScheme () { var port = NetworkHelpers.FindFreePort (); @@ -179,6 +185,9 @@ namespace MonoTests.System.Net } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void HttpRequestUriIsNotDecoded () { var port = NetworkHelpers.FindFreePort (); @@ -193,6 +202,9 @@ namespace MonoTests.System.Net } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void HttpRequestIsLocal () { var port = NetworkHelpers.FindFreePort (); @@ -220,6 +232,9 @@ namespace MonoTests.System.Net } [Test] // #29927 +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void HttpRequestUriUnescape () { var prefix = "http://localhost:" + NetworkHelpers.FindFreePort () + "/"; diff --git a/mcs/class/System/Test/System.Net/HttpListenerTest.cs b/mcs/class/System/Test/System.Net/HttpListenerTest.cs index f2ae436d29..09d3cb0f3f 100644 --- a/mcs/class/System/Test/System.Net/HttpListenerTest.cs +++ b/mcs/class/System/Test/System.Net/HttpListenerTest.cs @@ -39,14 +39,21 @@ namespace MonoTests.System.Net { [TestFixture] public class HttpListenerTest { - int port; + int? _port; + int port { + get { return _port ?? (_port = NetworkHelpers.FindFreePort ()).Value; } + } - [SetUp] - public void SetUp () { - port = NetworkHelpers.FindFreePort (); + [TearDown] + public void Teardown () + { + _port = null; } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void DefaultProperties () { HttpListener listener = new HttpListener (); @@ -60,6 +67,9 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Start1 () { HttpListener listener = new HttpListener (); @@ -67,6 +77,9 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Stop1 () { HttpListener listener = new HttpListener (); @@ -74,7 +87,11 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#else [ExpectedException (typeof (InvalidOperationException))] +#endif public void GetContext1 () { HttpListener listener = new HttpListener (); @@ -83,7 +100,11 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#else [ExpectedException (typeof (InvalidOperationException))] +#endif public void GetContext2 () { HttpListener listener = new HttpListener (); @@ -93,7 +114,11 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#else [ExpectedException (typeof (InvalidOperationException))] +#endif public void BeginGetContext1 () { HttpListener listener = new HttpListener (); @@ -102,6 +127,9 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void BeginGetContext2 () { HttpListener listener = new HttpListener (); @@ -134,6 +162,9 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void DefaultHttpPort () { if (!CanOpenPort (80)) @@ -147,6 +178,9 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void DefaultHttpsPort () { if (!CanOpenPort (443)) @@ -160,6 +194,9 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void TwoListeners_SameAddress () { if (!CanOpenPort (port)) @@ -173,7 +210,11 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#else [ExpectedException (typeof (HttpListenerException))] +#endif public void TwoListeners_SameURL () { if (!CanOpenPort (port)) @@ -187,7 +228,11 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#else [ExpectedException (typeof (HttpListenerException))] +#endif public void MultipleSlashes () { if (!CanOpenPort (port)) @@ -199,7 +244,11 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#else [ExpectedException (typeof (HttpListenerException))] +#endif public void PercentSign () { if (!CanOpenPort (port)) @@ -211,6 +260,9 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void CloseBeforeStart () { HttpListener listener = new HttpListener (); @@ -218,6 +270,9 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void CloseTwice () { if (!CanOpenPort (port)) @@ -230,6 +285,9 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void StartStopStart () { if (!CanOpenPort (port)) @@ -243,6 +301,9 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void StartStopDispose () { if (!CanOpenPort (port)) @@ -255,6 +316,9 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void AbortBeforeStart () { HttpListener listener = new HttpListener (); @@ -262,6 +326,9 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void AbortTwice () { if (!CanOpenPort (port)) @@ -274,6 +341,9 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void PropertiesWhenClosed1 () { HttpListener listener = new HttpListener (); @@ -287,7 +357,11 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#else [ExpectedException (typeof (ObjectDisposedException))] +#endif public void PropertiesWhenClosed2 () { HttpListener listener = new HttpListener (); @@ -296,7 +370,11 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#else [ExpectedException (typeof (ObjectDisposedException))] +#endif public void PropertiesWhenClosedSet1 () { HttpListener listener = new HttpListener (); @@ -305,7 +383,11 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#else [ExpectedException (typeof (ObjectDisposedException))] +#endif public void PropertiesWhenClosedSet2 () { HttpListener listener = new HttpListener (); @@ -314,7 +396,11 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#else [ExpectedException (typeof (ObjectDisposedException))] +#endif public void PropertiesWhenClosedSet3 () { HttpListener listener = new HttpListener (); @@ -323,7 +409,11 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#else [ExpectedException (typeof (ObjectDisposedException))] +#endif public void PropertiesWhenClosedSet4 () { HttpListener listener = new HttpListener (); @@ -332,7 +422,11 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#else [ExpectedException (typeof (ObjectDisposedException))] +#endif public void PropertiesWhenClosedSet5 () { HttpListener listener = new HttpListener (); @@ -341,6 +435,9 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void PropertiesWhenClosed3 () { HttpListener listener = new HttpListener (); @@ -349,6 +446,9 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void CloseWhileBegin () { HttpListener listener = new HttpListener (); @@ -365,6 +465,9 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void AbortWhileBegin () { HttpListener listener = new HttpListener (); @@ -381,7 +484,11 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#else [ExpectedException (typeof (HttpListenerException))] +#endif public void CloseWhileGet () { // "System.Net.HttpListener Exception : The I/O operation has been aborted @@ -398,7 +505,11 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#else [ExpectedException (typeof (HttpListenerException))] +#endif public void AbortWhileGet () { // "System.Net.HttpListener Exception : The I/O operation has been aborted @@ -478,6 +589,9 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ConnectionReuse () { var uri = "http://localhost:" + NetworkHelpers.FindFreePort () + "/"; @@ -533,8 +647,41 @@ namespace MonoTests.System.Net { return clientEndPoint; } + + [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif + public void UserHeaderWithDoubleMultiValue () + { + string uri = "http://localhost:" + NetworkHelpers.FindFreePort () + "/"; + + var l = new HttpListener (); + l.Prefixes.Add (uri); + l.Start (); + l.BeginGetContext (ar => { + var ctx = l.EndGetContext (ar); + + var response = ctx.Response; + response.Headers.Add ("X-Custom-Header", "A"); + response.Headers.Add ("X-Custom-Header", "B"); + + response.Close (); + }, null); + + HttpWebRequest wr = HttpWebRequest.CreateHttp (uri); + var resp = wr.GetResponse (); + var vls = resp.Headers.GetValues ("X-Custom-Header"); + + Assert.AreEqual (2, vls.Length); + + l.Close (); + } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void HttpClientIsDisconnectedCheckForWriteException() { string uri = "http://localhost:" + NetworkHelpers.FindFreePort () + "/"; diff --git a/mcs/class/System/Test/System.Net/HttpWebRequestTest.cs.REMOVED.git-id b/mcs/class/System/Test/System.Net/HttpWebRequestTest.cs.REMOVED.git-id index 90b6422f0a..3058fe1f46 100644 --- a/mcs/class/System/Test/System.Net/HttpWebRequestTest.cs.REMOVED.git-id +++ b/mcs/class/System/Test/System.Net/HttpWebRequestTest.cs.REMOVED.git-id @@ -1 +1 @@ -a289a6b5e76e2ac19ac91ec28b641c358d2fcf10 \ No newline at end of file +a597b4cd0a240dd08b9f9f2e1722d4a28bcc6754 \ No newline at end of file diff --git a/mcs/class/System/Test/System.Net/HttpWebResponseTest.cs b/mcs/class/System/Test/System.Net/HttpWebResponseTest.cs index 580c548890..b2c8e90488 100644 --- a/mcs/class/System/Test/System.Net/HttpWebResponseTest.cs +++ b/mcs/class/System/Test/System.Net/HttpWebResponseTest.cs @@ -24,6 +24,9 @@ namespace MonoTests.System.Net public class HttpWebResponseTest { [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void CharacterSet_Disposed () { IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint(); @@ -52,6 +55,9 @@ namespace MonoTests.System.Net } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Close_Disposed () { IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint(); @@ -71,6 +77,9 @@ namespace MonoTests.System.Net } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ContentEncoding_Disposed () { IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint(); @@ -99,6 +108,9 @@ namespace MonoTests.System.Net } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ContentLength_Disposed () { IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint(); @@ -119,6 +131,9 @@ namespace MonoTests.System.Net } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ContentType_Disposed () { IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint(); @@ -147,6 +162,9 @@ namespace MonoTests.System.Net } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Cookies_Disposed () { IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint(); @@ -185,6 +203,9 @@ namespace MonoTests.System.Net } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void GetResponseHeader_Disposed () { IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint(); @@ -213,6 +234,9 @@ namespace MonoTests.System.Net } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void GetResponseStream_Disposed () { IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint(); @@ -241,6 +265,9 @@ namespace MonoTests.System.Net } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Headers_Disposed () { IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint(); @@ -268,6 +295,9 @@ namespace MonoTests.System.Net } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void LastModified_Disposed () { IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint(); @@ -296,6 +326,9 @@ namespace MonoTests.System.Net } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Method_Disposed () { IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint(); @@ -324,6 +357,9 @@ namespace MonoTests.System.Net } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ProtocolVersion_Disposed () { IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint(); @@ -352,6 +388,9 @@ namespace MonoTests.System.Net } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ResponseUri_Disposed () { IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint(); @@ -380,6 +419,9 @@ namespace MonoTests.System.Net } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Server_Disposed () { IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint(); @@ -408,6 +450,9 @@ namespace MonoTests.System.Net } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void StatusCode_Disposed () { IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint(); @@ -428,6 +473,9 @@ namespace MonoTests.System.Net } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void StatusDescription_Disposed () { IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint(); @@ -479,6 +527,9 @@ namespace MonoTests.System.Net public class HttpResponseStreamTest { [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void BeginRead_Buffer_Null () { IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint(); @@ -528,6 +579,9 @@ namespace MonoTests.System.Net } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void BeginWrite () { IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint(); @@ -588,6 +642,9 @@ namespace MonoTests.System.Net } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void CanSeek () { IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint(); @@ -615,6 +672,9 @@ namespace MonoTests.System.Net } [Test] // bug #324182 +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void CanTimeout () { IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint(); @@ -642,6 +702,9 @@ namespace MonoTests.System.Net } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void CanWrite () { IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint(); @@ -669,6 +732,9 @@ namespace MonoTests.System.Net } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Read () { IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint(); @@ -706,6 +772,9 @@ namespace MonoTests.System.Net } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Read_Buffer_Null () { IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint(); @@ -755,6 +824,9 @@ namespace MonoTests.System.Net } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Read_Count_Negative () { IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint(); @@ -805,6 +877,9 @@ namespace MonoTests.System.Net } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Read_Count_Overflow () { IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint(); @@ -855,6 +930,9 @@ namespace MonoTests.System.Net } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Read_Offset_Negative () { IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint(); @@ -905,6 +983,9 @@ namespace MonoTests.System.Net } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Read_Offset_Overflow () { IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint(); @@ -1019,6 +1100,9 @@ namespace MonoTests.System.Net } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void ReadTimeout () { IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint(); @@ -1046,6 +1130,9 @@ namespace MonoTests.System.Net } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void Write () { IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint(); @@ -1078,6 +1165,9 @@ namespace MonoTests.System.Net } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void WriteTimeout () { IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint(); diff --git a/mcs/class/System/Test/System.Net/NetworkCredentialTest.cs b/mcs/class/System/Test/System.Net/NetworkCredentialTest.cs index dbe3255cd6..e5c46f8f90 100644 --- a/mcs/class/System/Test/System.Net/NetworkCredentialTest.cs +++ b/mcs/class/System/Test/System.Net/NetworkCredentialTest.cs @@ -28,6 +28,7 @@ using System; using System.Net; +using System.Security; using NUnit.Framework; @@ -99,6 +100,21 @@ namespace MonoTests.System.Net { nc = new NetworkCredential ("user", "********", "dom"); CheckCustom (nc); } + + [Test] + public void DecipherSecureString () + { + // many code snippets suggest using the following to get the decrypted string from a SecureString + var ss = new SecureString (); + ss.AppendChar('h'); + ss.AppendChar('e'); + ss.AppendChar('l'); + ss.AppendChar('l'); + ss.AppendChar('o'); + + string plain = new NetworkCredential (string.Empty, ss).Password; + Assert.AreEqual ("hello", plain); + } } } diff --git a/mcs/class/System/Test/System.Net/ServicePointManagerTest.cs b/mcs/class/System/Test/System.Net/ServicePointManagerTest.cs index 6f763923cb..c252d21b18 100644 --- a/mcs/class/System/Test/System.Net/ServicePointManagerTest.cs +++ b/mcs/class/System/Test/System.Net/ServicePointManagerTest.cs @@ -29,8 +29,10 @@ public class ServicePointManagerTest [SetUp] public void GetReady () { +#if !FEATURE_NO_BSD_SOCKETS maxIdle = ServicePointManager.MaxServicePointIdleTime; ServicePointManager.MaxServicePointIdleTime = 10; +#endif googleUri = new Uri ("http://www.google.com"); yahooUri = new Uri ("http://www.yahoo.com"); apacheUri = new Uri ("http://www.apache.org"); @@ -39,7 +41,9 @@ public class ServicePointManagerTest [TearDown] public void Finish () { +#if !FEATURE_NO_BSD_SOCKETS ServicePointManager.MaxServicePointIdleTime = maxIdle; +#endif } [Test, ExpectedException (typeof (InvalidOperationException))] @@ -82,12 +86,15 @@ public class ServicePointManagerTest } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void FindServicePoint () { ServicePointManager.MaxServicePoints = 0; ServicePoint sp = ServicePointManager.FindServicePoint (googleUri, new WebProxy (apacheUri)); Assert.AreEqual (apacheUri, sp.Address, "#1"); -#if NET_2_1 && !MONODROID +#if MOBILE Assert.AreEqual (10, sp.ConnectionLimit, "#2"); #else Assert.AreEqual (2, sp.ConnectionLimit, "#2"); diff --git a/mcs/class/System/Test/System.Net/ServicePointTest.cs b/mcs/class/System/Test/System.Net/ServicePointTest.cs index 346f35bdea..6171a2fd25 100644 --- a/mcs/class/System/Test/System.Net/ServicePointTest.cs +++ b/mcs/class/System/Test/System.Net/ServicePointTest.cs @@ -13,7 +13,7 @@ using System; using System.Collections; using System.IO; using System.Net; -using System.Reflection; +using System.Reflection; using System.Threading; namespace MonoTests.System.Net @@ -23,6 +23,8 @@ namespace MonoTests.System.Net public class ServicePointTest { static private int max; + +#if !FEATURE_NO_BSD_SOCKETS [SetUp] public void SaveMax () { max = ServicePointManager.MaxServicePoints; @@ -33,6 +35,7 @@ public class ServicePointTest public void RestoreMax () { ServicePointManager.MaxServicePoints = max; } +#endif [Test] [Category ("InetAccess")] @@ -54,13 +57,13 @@ public class ServicePointTest HttpWebRequest req = (HttpWebRequest) WebRequest.Create ("http://www.google.com"); HttpWebResponse res = (HttpWebResponse) req.GetResponse (); -#if FOUND_SOME_OTHER_URL - // URL is no longer found, disabled the test until a more reliable URL is found :P +#if FOUND_SOME_OTHER_URL + // URL is no longer found, disabled the test until a more reliable URL is found :P //WriteServicePoint ("google after getting a response", google); ServicePoint google2 = ServicePointManager.FindServicePoint (new Uri ("http://www.google.com/dilbert.html")); Assert.AreEqual (google, google2, "#equals"); res.Close (); -#endif +#endif // in both instances property CurrentConnections is 0 according to ms.net. // let's see what it says when we do async operations... @@ -87,8 +90,8 @@ public class ServicePointTest //Console.WriteLine ("ContentLength: " + res2.ContentLength); res2.Close (); - ServicePoint sp2; -#if FOUND_SOME_OTHER_URL + ServicePoint sp2; +#if FOUND_SOME_OTHER_URL // unless of course some buffering is taking place.. let's check Uri uri2 = new Uri ("http://freedesktop.org/Software/pkgconfig/releases/pkgconfig-0.15.0.tar.gz"); sp2 = ServicePointManager.FindServicePoint (uri2); @@ -102,7 +105,7 @@ public class ServicePointTest // and so it shows //Console.WriteLine ("ContentLength: " + res2.ContentLength); res2.Close (); -#endif +#endif // what's the limit of the cache? @@ -154,7 +157,7 @@ public class ServicePointTest [Test] [Category ("InetAccess")] - [Category ("AndroidNotWorking")] // #A1 fails + [Category ("AndroidNotWorking")] // #A1 fails public void EndPointBind () { Uri uri = new Uri ("http://www.go-mono.com/"); @@ -189,6 +192,10 @@ public class ServicePointTest } [Test] //Covers #19823 +#if FEATURE_NO_BSD_SOCKETS + // This test uses HttpWebRequest + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void CloseConnectionGroupConcurency () { // Try with multiple service points @@ -206,36 +213,37 @@ public class ServicePointTest } } - - [Test] - public void DnsRefreshTimeout () - { - const int dnsRefreshTimeout = 2000; - - ServicePoint sp; - IPHostEntry host0, host1, host2; - Uri uri; - PropertyInfo hostEntryProperty; - - ServicePointManager.DnsRefreshTimeout = dnsRefreshTimeout; - - uri = new Uri ("http://localhost/"); - sp = ServicePointManager.FindServicePoint (uri); - - hostEntryProperty = typeof (ServicePoint).GetProperty ("HostEntry", BindingFlags.NonPublic | BindingFlags.Instance); - - host0 = hostEntryProperty.GetValue (sp, null) as IPHostEntry; - host1 = hostEntryProperty.GetValue (sp, null) as IPHostEntry; - - Assert.AreSame (host0, host1, "HostEntry should result in the same IPHostEntry object."); - - Thread.Sleep (dnsRefreshTimeout * 2); - host2 = hostEntryProperty.GetValue (sp, null) as IPHostEntry; - - Assert.AreNotSame(host0, host2, "HostEntry should result in a new IPHostEntry " + - "object when DnsRefreshTimeout is reached."); - } - + + [Test] + [Category ("RequiresBSDSockets")] // Tests internals, so it doesn't make sense to assert that PlatformNotSupportedExceptions are thrown. + public void DnsRefreshTimeout () + { + const int dnsRefreshTimeout = 2000; + + ServicePoint sp; + IPHostEntry host0, host1, host2; + Uri uri; + PropertyInfo hostEntryProperty; + + ServicePointManager.DnsRefreshTimeout = dnsRefreshTimeout; + + uri = new Uri ("http://localhost/"); + sp = ServicePointManager.FindServicePoint (uri); + + hostEntryProperty = typeof (ServicePoint).GetProperty ("HostEntry", BindingFlags.NonPublic | BindingFlags.Instance); + + host0 = hostEntryProperty.GetValue (sp, null) as IPHostEntry; + host1 = hostEntryProperty.GetValue (sp, null) as IPHostEntry; + + Assert.AreSame (host0, host1, "HostEntry should result in the same IPHostEntry object."); + + Thread.Sleep (dnsRefreshTimeout * 2); + host2 = hostEntryProperty.GetValue (sp, null) as IPHostEntry; + + Assert.AreNotSame(host0, host2, "HostEntry should result in a new IPHostEntry " + + "object when DnsRefreshTimeout is reached."); + } + // Debug code not used now, but could be useful later /* private void WriteServicePoint (string label, ServicePoint sp) diff --git a/mcs/class/System/Test/System.Net/WebClientTest.cs b/mcs/class/System/Test/System.Net/WebClientTest.cs index b671e9e923..30531be7e8 100644 --- a/mcs/class/System/Test/System.Net/WebClientTest.cs +++ b/mcs/class/System/Test/System.Net/WebClientTest.cs @@ -1418,6 +1418,9 @@ namespace MonoTests.System.Net [Test] [Category ("AndroidNotWorking")] // Fails when ran as part of the entire BCL test suite. Works when only this fixture is ran +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void UploadValues1 () { IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint (); @@ -1668,6 +1671,10 @@ namespace MonoTests.System.Net } [Test] +#if FEATURE_NO_BSD_SOCKETS + // We throw a PlatformNotSupportedException deeper, which is caught and re-thrown as WebException + [ExpectedException (typeof (WebException))] +#endif public void GetWebRequestOverriding () { GetWebRequestOverridingTestClass testObject = new GetWebRequestOverridingTestClass (); @@ -1771,6 +1778,9 @@ namespace MonoTests.System.Net } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void DefaultProxy () { WebClient wc = new WebClient (); @@ -1780,9 +1790,11 @@ namespace MonoTests.System.Net Assert.AreSame (wc.Proxy, WebRequest.DefaultWebProxy); } -#if NET_4_5 [Test] [Category ("AndroidNotWorking")] // Fails when ran as part of the entire BCL test suite. Works when only this fixture is ran +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void UploadStringAsyncCancelEvent () { UploadAsyncCancelEventTest (9301, (webClient, uri, cancelEvent) => @@ -1800,6 +1812,9 @@ namespace MonoTests.System.Net [Test] [Category ("AndroidNotWorking")] // Fails when ran as part of the entire BCL test suite. Works when only this fixture is ran +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void UploadDataAsyncCancelEvent () { UploadAsyncCancelEventTest (9302, (webClient, uri, cancelEvent) => @@ -1816,6 +1831,9 @@ namespace MonoTests.System.Net [Test] [Category ("AndroidNotWorking")] // Fails when ran as part of the entire BCL test suite. Works when only this fixture is ran +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void UploadValuesAsyncCancelEvent () { UploadAsyncCancelEventTest (9303, (webClient, uri, cancelEvent) => @@ -1832,6 +1850,9 @@ namespace MonoTests.System.Net [Test] [Category ("AndroidNotWorking")] // Fails when ran as part of the entire BCL test suite. Works when only this fixture is ran +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void UploadFileAsyncCancelEvent () { UploadAsyncCancelEventTest (9304,(webClient, uri, cancelEvent) => @@ -1851,6 +1872,9 @@ namespace MonoTests.System.Net [Test] [Category ("AndroidNotWorking")] // Test suite hangs if the tests runs as part of the entire BCL suite. Works when only this fixture is ran +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void UploadFileAsyncContentType () { var port = NetworkHelpers.FindFreePort (); @@ -1872,7 +1896,6 @@ namespace MonoTests.System.Net } listener.Close (); } -#endif public void UploadAsyncCancelEventTest (int port, Action uploadAction) { diff --git a/mcs/class/System/Test/System.Net/WebClientTestAsync.cs b/mcs/class/System/Test/System.Net/WebClientTestAsync.cs index aabaceb9f4..0b40458189 100644 --- a/mcs/class/System/Test/System.Net/WebClientTestAsync.cs +++ b/mcs/class/System/Test/System.Net/WebClientTestAsync.cs @@ -26,7 +26,6 @@ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -#if NET_4_5 using System; using System.IO; using System.Collections.Generic; @@ -276,4 +275,3 @@ namespace MonoTests.System.Net } } } -#endif diff --git a/mcs/class/System/Test/System.Net/WebHeaderCollectionTest.cs b/mcs/class/System/Test/System.Net/WebHeaderCollectionTest.cs index 1e21e43dc2..c2bdeba6ab 100644 --- a/mcs/class/System/Test/System.Net/WebHeaderCollectionTest.cs +++ b/mcs/class/System/Test/System.Net/WebHeaderCollectionTest.cs @@ -124,6 +124,9 @@ namespace MonoTests.System.Net } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void AddRestricted () { col = CreateRestrictedHeaders (); @@ -236,6 +239,9 @@ namespace MonoTests.System.Net } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void RemoveRestricted () { col = CreateRestrictedHeaders (); diff --git a/mcs/class/System/Test/System.Net/WebProxyTest.cs b/mcs/class/System/Test/System.Net/WebProxyTest.cs index d88c9864e2..0257ff50fe 100644 --- a/mcs/class/System/Test/System.Net/WebProxyTest.cs +++ b/mcs/class/System/Test/System.Net/WebProxyTest.cs @@ -123,11 +123,6 @@ namespace MonoTests.System.Net Assert.AreEqual (1, p.BypassList.Length, "#4"); } - [Test] - public void GetProxy () - { - } - [Test] public void IsByPassed () { diff --git a/mcs/class/System/Test/System.Net/WebRequestTest.cs b/mcs/class/System/Test/System.Net/WebRequestTest.cs index 908dadb35c..074c97d698 100644 --- a/mcs/class/System/Test/System.Net/WebRequestTest.cs +++ b/mcs/class/System/Test/System.Net/WebRequestTest.cs @@ -11,8 +11,10 @@ // using NUnit.Framework; +using MonoTests.Helpers; using System; using System.Net; +using System.Threading; using System.Collections; using System.Runtime.Serialization; using Socks = System.Net.Sockets; @@ -191,6 +193,9 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void All () { WebRequest req = WebRequest.Create ("http://www.contoso.com"); @@ -262,6 +267,9 @@ namespace MonoTests.System.Net { } [Test] +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif public void DefaultWebProxy () { WebProxy proxy = new WebProxy ("proxy.intern.com", 83); @@ -316,14 +324,18 @@ namespace MonoTests.System.Net { } [Test] //BNC#323452 - // Throws exception with Status == Timeout. The same code behaves as the test expects when run from a regular app. - // Might be an issue with the test suite. To investigate. - [Category("AndroidNotWorking")] + // Throws exception with Status == Timeout. The same code behaves as the test expects when run from a regular app. + // Might be an issue with the test suite. To investigate. + [Category("AndroidNotWorking")] public void TestFailedConnection () { try { WebRequest.Create ("http://127.0.0.1:0/non-existant.txt").GetResponse (); Assert.Fail ("Should have raised an exception"); +#if FEATURE_NO_BSD_SOCKETS + } catch (PlatformNotSupportedException) { + // Expected +#endif } catch (Exception e) { Assert.IsTrue (e is WebException, "Got " + e.GetType ().Name + ": " + e.Message); //#if NET_2_0 e.Message == "Unable to connect to the remote server" @@ -340,7 +352,7 @@ namespace MonoTests.System.Net { } [Test] //BNC#323452 - [Category ("AndroidNotWorking")] // Fails when ran as part of the entire BCL test suite. Works when only this fixture is ran + [Category ("AndroidNotWorking")] // Fails when ran as part of the entire BCL test suite. Works when only this fixture is ran public void TestFailedResolution () { try { @@ -357,6 +369,10 @@ namespace MonoTests.System.Net { Assert.Ignore ("Misbehaving DNS server."); Assert.Fail ("Should have raised an exception"); +#if FEATURE_NO_BSD_SOCKETS + } catch (PlatformNotSupportedException) { + // Expected +#endif } catch (Exception e) { Assert.IsTrue (e is WebException); //#if NET_2_0 e.Message == "The underlying connection was closed: The remote name could not be resolved." @@ -410,6 +426,55 @@ namespace MonoTests.System.Net { { internal TestWebRequest3 () { } } + + [Test] // Covers #41477 +#if FEATURE_NO_BSD_SOCKETS + [ExpectedException (typeof (PlatformNotSupportedException))] +#endif + public void TestReceiveCancelation () + { + var uri = "http://localhost:" + NetworkHelpers.FindFreePort () + "/"; + + HttpListener listener = new HttpListener (); + listener.Prefixes.Add (uri); + listener.Start (); + + try { + for (var i = 0; i < 10; i++) { + var request = WebRequest.CreateHttp (uri); + request.Method = "GET"; + + var tokenSource = new CancellationTokenSource (); + tokenSource.Token.Register(() => request.Abort ()); + + var responseTask = request.GetResponseAsync (); + + var context = listener.GetContext (); + byte[] outBuffer = new byte[8 * 1024]; + context.Response.OutputStream.WriteAsync (outBuffer, 0, outBuffer.Length); + + Assert.IsTrue (responseTask.Wait (1000), "Timeout #1"); + + WebResponse response = responseTask.Result; + var stream = response.GetResponseStream (); + + byte[] buffer = new byte[8 * 1024]; + var taskRead = stream.ReadAsync (buffer, 0, buffer.Length, tokenSource.Token); + + tokenSource.Cancel (); + + Assert.IsTrue (taskRead.Wait (1000), "Timeout #2"); + + var byteRead = taskRead.Result; + } + } catch (AggregateException ex) { + var webEx = ex.InnerException as WebException; + Assert.IsNotNull(webEx, "Inner exception is not a WebException"); + Assert.AreEqual (webEx.Status, WebExceptionStatus.RequestCanceled); + } + + listener.Close (); + } } } diff --git a/mcs/class/System/Test/System.Threading/SemaphoreTest.cs b/mcs/class/System/Test/System.Threading/SemaphoreTest.cs index e30968bf5a..db3a57adab 100644 --- a/mcs/class/System/Test/System.Threading/SemaphoreTest.cs +++ b/mcs/class/System/Test/System.Threading/SemaphoreTest.cs @@ -180,6 +180,15 @@ namespace MonoTests.System.Threading { Assert.IsTrue (created, "Created"); } + [Test] + public void Constructor_CreatedWithSameName () + { + var s1 = new Semaphore(1, 5, "name"); + bool created; + var s2 = new Semaphore(1, 5, "name", out created); + Assert.IsFalse (created); + } + [Test] [Category ("MobileNotWorking")] public void Constructor_IntIntStringBoolSecurity () diff --git a/mcs/class/System/Test/System/UriPermutationsTest.cs b/mcs/class/System/Test/System/UriPermutationsTest.cs index 7d9d24052f..308c3bdf39 100644 --- a/mcs/class/System/Test/System/UriPermutationsTest.cs +++ b/mcs/class/System/Test/System/UriPermutationsTest.cs @@ -62,11 +62,7 @@ namespace MonoTests.System { public void Setup() { StringTester.CreateMode = createMode; -#if NET_4_5 StringTester.Location = location + "NET_4_5"; -#else - StringTester.Location = location + "NET_4_0"; -#endif } [TearDown] diff --git a/mcs/class/System/Test/System/UriTest.cs b/mcs/class/System/Test/System/UriTest.cs index 32c3fb0459..6ebd708ee0 100644 --- a/mcs/class/System/Test/System/UriTest.cs +++ b/mcs/class/System/Test/System/UriTest.cs @@ -836,11 +836,7 @@ namespace MonoTests.System { Uri u = new Uri("http://localhost/index.asp#main#start", false); -#if NET_4_5 Assert.AreEqual (u.Fragment, "#main#start", "#1"); -#else - Assert.AreEqual (u.Fragment, "#main%23start", "#1"); -#endif u = new Uri("http://localhost/index.asp#main#start", true); Assert.AreEqual (u.Fragment, "#main#start", "#2"); @@ -849,11 +845,7 @@ namespace MonoTests.System Uri b = new Uri ("http://www.gnome.org"); Uri n = new Uri (b, "blah#main#start"); -#if NET_4_5 Assert.AreEqual (n.Fragment, "#main#start", "#3"); -#else - Assert.AreEqual (n.Fragment, "#main%23start", "#3"); -#endif n = new Uri (b, "blah#main#start", true); Assert.AreEqual (n.Fragment, "#main#start", "#4"); @@ -1071,13 +1063,8 @@ namespace MonoTests.System Uri ftp = new Uri ("FTP://[::ffFF:169.32.14.5]/"); Assert.AreEqual ("ftp", ftp.Scheme, "#7"); -#if NET_4_5 Assert.AreEqual ("[::ffff:169.32.14.5]", ftp.Host, "#8"); Assert.AreEqual ("ftp://[::ffff:169.32.14.5]/", ftp.ToString (), "#9"); -#else - Assert.AreEqual ("[0000:0000:0000:0000:0000:FFFF:A920:0E05]", ftp.Host, "#8"); - Assert.AreEqual ("ftp://[0000:0000:0000:0000:0000:FFFF:A920:0E05]/", ftp.ToString (), "#9"); -#endif } [Test] @@ -1484,15 +1471,9 @@ namespace MonoTests.System for (int i = 0; i < 128; i++) sb.Append ((char) i); -#if NET_4_5 Assert.AreEqual ( "%00%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%20%21%22%23%24%25%26%27%28%29%2A%2B%2C-.%2F0123456789%3A%3B%3C%3D%3E%3F%40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5D%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D~%7F", Uri.EscapeDataString (sb.ToString ())); -#else - Assert.AreEqual ( - "%00%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%20!%22%23%24%25%26'()*%2B%2C-.%2F0123456789%3A%3B%3C%3D%3E%3F%40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5D%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D~%7F", - Uri.EscapeDataString (sb.ToString ())); -#endif Assert.AreEqual ("%C3%A1", Uri.EscapeDataString ("á")); } @@ -1503,15 +1484,9 @@ namespace MonoTests.System for (int i = 0; i < 128; i++) sb.Append ((char) i); -#if NET_4_5 Assert.AreEqual ( "%00%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%20!%22#$%25&'()*+,-./0123456789:;%3C=%3E?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[%5C]%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D~%7F", Uri.EscapeUriString (sb.ToString ())); -#else - Assert.AreEqual ( - "%00%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%20!%22#$%25&'()*+,-./0123456789:;%3C=%3E?@ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5D%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D~%7F", - Uri.EscapeUriString (sb.ToString ())); -#endif Assert.AreEqual ("%C3%A1", Uri.EscapeDataString ("á")); } diff --git a/mcs/class/System/Test/System/UriTest3.cs b/mcs/class/System/Test/System/UriTest3.cs index 9b2e93b730..a39ac73d0a 100644 --- a/mcs/class/System/Test/System/UriTest3.cs +++ b/mcs/class/System/Test/System/UriTest3.cs @@ -312,6 +312,8 @@ namespace MonoTests.System Assert.IsFalse (Uri.IsWellFormedUriString (null, UriKind.Absolute), "null"); Assert.IsFalse (Uri.IsWellFormedUriString ("data", UriKind.Absolute), "data"); Assert.IsTrue (Uri.IsWellFormedUriString ("http://www.go-mono.com/Main_Page#1", UriKind.Absolute), "http/hex"); + Assert.IsTrue (Uri.IsWellFormedUriString ("test", UriKind.RelativeOrAbsolute), "rel1"); + Assert.IsTrue (Uri.IsWellFormedUriString ("/test", UriKind.RelativeOrAbsolute), "rel2"); } [Test] diff --git a/mcs/class/System/mobile_System.dll.sources b/mcs/class/System/mobile_System.dll.sources index ae15bf9c4b..8db8bb90d1 100644 --- a/mcs/class/System/mobile_System.dll.sources +++ b/mcs/class/System/mobile_System.dll.sources @@ -11,11 +11,9 @@ System.Diagnostics/FileVersionInfo.cs System.Diagnostics/MonitoringDescriptionAttribute.cs System.Diagnostics/Process.cs System.Diagnostics/ProcessModule.cs -System.Diagnostics/ProcessModuleCollection.cs System.Diagnostics/ProcessPriorityClass.cs System.Diagnostics/ProcessStartInfo.cs System.Diagnostics/ProcessThread.cs -System.Diagnostics/ProcessThreadCollection.cs System.Diagnostics/ProcessWindowStyle.cs System.Diagnostics/Stopwatch.cs System.Diagnostics/ThreadPriorityLevel.cs @@ -28,6 +26,7 @@ System.IO.Compression/DeflateStream.cs System.IO.Compression/GZipStream.cs System.IO/InternalBufferOverflowException.cs System.IO/InvalidDataException.cs +System.IO/IODescriptionAttribute.cs System.IO/ErrorEventArgs.cs System.IO/ErrorEventHandler.cs System.IO/FileSystemEventArgs.cs @@ -142,6 +141,9 @@ System.Net.Sockets/SocketOperation.cs ../referencesource/System/net/System/Net/Sockets/SocketOptionLevel.cs ../referencesource/System/net/System/Net/Sockets/SocketOptionName.cs ../referencesource/System/net/System/Net/Sockets/SocketShutdown.cs +System.Net.Sockets/SocketReceiveFromResult.cs +System.Net.Sockets/SocketReceiveMessageFromResult.cs +System.Net.Sockets/SocketTaskExtensions.cs ../referencesource/System/net/System/Net/Sockets/SocketType.cs System.Net.Sockets/TcpClient.cs System.Net.Sockets/TcpListener.cs @@ -153,7 +155,6 @@ System.Net/BasicClient.cs System.Net/BindIPEndPoint.cs System.Net/ChunkStream.cs System.Net/ChunkedInputStream.cs -System.Net/CredentialCache.cs System.Net/DecompressionMethods.cs System.Net/DefaultCertificatePolicy.cs System.Net/DigestClient.cs @@ -167,7 +168,6 @@ System.Net/FtpRequestCreator.cs System.Net/FtpStatus.cs System.Net/FtpWebRequest.cs System.Net/FtpWebResponse.cs -System.Net/GlobalProxySelection.cs System.Net/HttpConnection.cs System.Net/HttpListener.cs System.Net/HttpListenerBasicIdentity.cs @@ -175,6 +175,7 @@ System.Net/HttpListenerContext.cs System.Net/HttpListenerPrefixCollection.cs System.Net/HttpListenerRequest.cs System.Net/HttpListenerResponse.cs +System.Net/HttpListenerResponseHelper.cs System.Net/HttpListenerTimeoutManager.cs System.Net/HttpRequestCreator.cs System.Net/HttpStreamAsyncResult.cs @@ -182,7 +183,6 @@ System.Net/HttpWebRequest.cs System.Net/HttpWebResponse.cs System.Net/ICredentialPolicy.cs System.Net/IPv6Address.cs -System.Net/IPv6Address.cs System.Net/IWebConnectionState.cs System.Net/IWebProxyScript.cs System.Net/ListenerAsyncResult.cs @@ -190,7 +190,6 @@ System.Net/ListenerPrefix.cs System.Net/MacProxy.cs System.Net/MonoHttpDate.cs System.Net/NetConfig.cs -System.Net/NetworkCredential.cs System.Net/NtlmClient.cs System.Net/RequestStream.cs System.Net/ResponseStream.cs @@ -203,8 +202,6 @@ System.Net/WebConnection.cs System.Net/WebConnectionData.cs System.Net/WebConnectionGroup.cs System.Net/WebConnectionStream.cs -System.Net/WebProxy.cs -System.Net/WebRequest.cs System.Net.WebSockets/ClientWebSocket.cs System.Net.WebSockets/ClientWebSocketOptions.cs System.Net.WebSockets/HttpListenerWebSocketContext.cs @@ -232,7 +229,6 @@ System.Security.Authentication.ExtendedProtection/ExtendedProtectionPolicy.cs System.Security.Authentication.ExtendedProtection/ExtendedProtectionPolicyTypeConverter.cs System.Security.Authentication.ExtendedProtection/PolicyEnforcement.cs System.Security.Authentication.ExtendedProtection/ProtectionScenario.cs -System.Security.Authentication.ExtendedProtection/ServiceNameCollection.cs System.Security.Authentication.ExtendedProtection.Configuration/ConfigUtil.cs System.Security.Authentication.ExtendedProtection.Configuration/ExtendedProtectionPolicyElement.cs System.Security.Authentication.ExtendedProtection.Configuration/ServiceNameElement.cs @@ -280,7 +276,6 @@ System.Security.Cryptography.X509Certificates/X509VerificationFlags.cs System.Security.Cryptography/AsnEncodedData.cs System.Security.Cryptography/AsnEncodedDataCollection.cs System.Security.Cryptography/AsnEncodedDataEnumerator.cs -System.Threading/Semaphore.cs System.Threading/ThreadExceptionEventArgs.cs System.Threading/ThreadExceptionEventHandler.cs System.Timers/ElapsedEventArgs.cs @@ -299,29 +294,68 @@ Mono.Net.Security/IMonoSslStream.cs Mono.Net.Security/LegacySslStream.cs Mono.Net.Security/MobileAuthenticatedStream.cs Mono.Net.Security/MobileTlsContext.cs -Mono.Net.Security/MonoLegacyTlsProvider.cs +Mono.Net.Security/LegacyTlsProvider.cs Mono.Net.Security/MonoSslStreamImpl.cs Mono.Net.Security/MonoSslStreamWrapper.cs Mono.Net.Security/MonoTlsProviderFactory.cs -Mono.Net.Security/MonoTlsProviderImpl.cs Mono.Net.Security/MonoTlsProviderWrapper.cs Mono.Net.Security/MonoTlsStream.cs Mono.Net.Security/NoReflectionHelper.cs Mono.Net.Security/SystemCertificateValidator.cs +Mono.Btls/MonoBtlsBio.cs +Mono.Btls/MonoBtlsContext.cs +Mono.Btls/MonoBtlsError.cs +Mono.Btls/MonoBtlsException.cs +Mono.Btls/MonoBtlsKey.cs +Mono.Btls/MonoBtlsObject.cs +Mono.Btls/MonoBtlsPkcs12.cs +Mono.Btls/MonoBtlsProvider.cs +Mono.Btls/MonoBtlsSsl.cs +Mono.Btls/MonoBtlsSslCtx.cs +Mono.Btls/MonoBtlsSslError.cs +Mono.Btls/MonoBtlsStream.cs +Mono.Btls/MonoBtlsUtils.cs +Mono.Btls/MonoBtlsX509.cs +Mono.Btls/MonoBtlsX509Chain.cs +Mono.Btls/MonoBtlsX509Crl.cs +Mono.Btls/MonoBtlsX509Error.cs +Mono.Btls/MonoBtlsX509Exception.cs +Mono.Btls/MonoBtlsX509FileType.cs +Mono.Btls/MonoBtlsX509Format.cs +Mono.Btls/MonoBtlsX509Lookup.cs +Mono.Btls/MonoBtlsX509LookupMonoCollection.cs +Mono.Btls/MonoBtlsX509LookupMono.cs +Mono.Btls/MonoBtlsX509LookupType.cs +Mono.Btls/MonoBtlsX509Name.cs +Mono.Btls/MonoBtlsX509NameEntryType.cs +Mono.Btls/MonoBtlsX509Purpose.cs +Mono.Btls/MonoBtlsX509Revoked.cs +Mono.Btls/MonoBtlsX509Store.cs +Mono.Btls/MonoBtlsX509StoreCtx.cs +Mono.Btls/MonoBtlsX509StoreManager.cs +Mono.Btls/MonoBtlsX509StoreType.cs +Mono.Btls/MonoBtlsX509TrustKind.cs +Mono.Btls/MonoBtlsX509VerifyFlags.cs +Mono.Btls/MonoBtlsX509VerifyParam.cs +Mono.Btls/X509CertificateImplBtls.cs +Mono.Btls/X509ChainImplBtls.cs + +ReferenceSources/AutoWebProxyScriptEngine.cs ReferenceSources/AssertWrapper.cs ReferenceSources/CAPI.cs ReferenceSources/EnvironmentHelpers.cs ReferenceSources/HttpApi.cs -ReferenceSources/Internal.cs +ReferenceSources/LocalAppContextSwitches.cs ReferenceSources/HttpSysSettings.cs ReferenceSources/Logging.cs ReferenceSources/NativeMethods.cs +ReferenceSources/RequestCacheProtocol.cs ReferenceSources/SettingsSectionInternal.cs +ReferenceSources/SecureStringHelper.cs ReferenceSources/Socket.cs ReferenceSources/SR.cs ReferenceSources/SRCategoryAttribute.cs -ReferenceSources/SystemNetworkCredential.cs ReferenceSources/Win32Exception.cs ../referencesource/System/regex/system/text/regularexpressions/Regex.cs @@ -698,6 +732,7 @@ ReferenceSources/Win32Exception.cs ../referencesource/System/net/System/Net/_BufferOffsetSize.cs ../referencesource/System/net/System/Net/_Connection.cs +../referencesource/System/net/System/Net/_emptywebproxy.cs ../referencesource/System/net/System/Net/_HeaderInfo.cs ../referencesource/System/net/System/Net/_HeaderInfoTable.cs ../referencesource/System/net/System/Net/_HTTPDateParse.cs @@ -705,24 +740,33 @@ ReferenceSources/Win32Exception.cs ../referencesource/System/net/System/Net/_NetRes.cs ../referencesource/System/net/System/Net/_LazyAsyncResult.cs ../referencesource/System/net/System/Net/_LoggingObject.cs +../referencesource/System/net/System/Net/_PooledStream.cs +../referencesource/System/net/System/Net/_ProxyChain.cs ../referencesource/System/net/System/Net/_ScatterGatherBuffers.cs +../referencesource/System/net/System/Net/_Semaphore.cs +../referencesource/System/net/System/Net/_ServiceNameStore.cs +../referencesource/System/net/System/Net/_TimerThread.cs +../referencesource/System/net/System/Net/_WebProxyDataBuilder.cs ../referencesource/System/net/System/Net/AuthenticationScheme.cs ../referencesource/System/net/System/Net/AuthenticationSchemeSelector.cs ../referencesource/System/net/System/Net/Authorization.cs +../referencesource/System/net/System/Net/CredentialCache.cs ../referencesource/System/net/System/Net/cookie.cs ../referencesource/System/net/System/Net/cookiecollection.cs ../referencesource/System/net/System/Net/cookiecontainer.cs ../referencesource/System/net/System/Net/cookieexception.cs +../referencesource/System/net/System/Net/connectionpool.cs ../referencesource/System/net/System/Net/DnsEndPoint.cs ../referencesource/System/net/System/Net/EndPoint.cs ../referencesource/System/net/System/Net/FtpStatusCode.cs ../referencesource/System/net/System/Net/filewebrequest.cs ../referencesource/System/net/System/Net/filewebresponse.cs +../referencesource/System/net/System/Net/GlobalProxySelection.cs ../referencesource/System/net/System/Net/HttpListenerException.cs +../referencesource/System/net/System/Net/HttpListenerRequestUriBuilder.cs ../referencesource/System/net/System/Net/HttpRequestHeader.cs ../referencesource/System/net/System/Net/HttpResponseHeader.cs ../referencesource/System/net/System/Net/HttpStatusCode.cs -../referencesource/System/net/System/Net/HttpListenerRequestUriBuilder.cs ../referencesource/System/net/System/Net/HttpVersion.cs ../referencesource/System/net/System/Net/IAuthenticationModule.cs ../referencesource/System/net/System/Net/ICertificatePolicy.cs @@ -733,8 +777,10 @@ ReferenceSources/Win32Exception.cs ../referencesource/System/net/System/Net/IPEndPoint.cs ../referencesource/System/net/System/Net/IPHostEntry.cs ../referencesource/System/net/System/Net/iwebproxy.cs +../referencesource/System/net/System/Net/IWebProxyFinder.cs ../referencesource/System/net/System/Net/IWebRequestCreate.cs ../referencesource/System/net/System/Net/NetworkAccess.cs +../referencesource/System/net/System/Net/NetworkCredential.cs ../referencesource/System/net/System/Net/ProtocolViolationException.cs ../referencesource/System/net/System/Net/TransportContext.cs ../referencesource/System/net/System/Net/TransportType.cs @@ -747,13 +793,21 @@ ReferenceSources/Win32Exception.cs ../referencesource/System/net/System/Net/WebExceptionStatus.cs ../referencesource/System/net/System/Net/WebHeaderCollection.cs ../referencesource/System/net/System/Net/WebPermission.cs +../referencesource/System/net/System/Net/webproxy.cs ../referencesource/System/net/System/Net/WebRequestMethods.cs +../referencesource/System/net/System/Net/WebRequest.cs ../referencesource/System/net/System/Net/WebResponse.cs ../referencesource/System/net/System/Net/WebUtility.cs ../referencesource/System/net/System/Net/WriteStreamClosedEventArgs.cs +../referencesource/System/net/System/Net/Cache/RequestCache.cs +../referencesource/System/net/System/Net/Cache/RequestCacheEntry.cs ../referencesource/System/net/System/Net/Cache/RequestCachePolicy.cs +../referencesource/System/net/System/Net/Cache/RequestCacheManager.cs +../referencesource/System/net/System/Net/Configuration/DefaultProxySection.cs + +../referencesource/System/net/System/Net/Sockets/_MultipleConnectAsync.cs ../referencesource/System/net/System/Net/Sockets/IPProtectionLevel.cs ../referencesource/System/net/System/Net/Sockets/NetworkStream.cs @@ -801,14 +855,22 @@ ReferenceSources/Win32Exception.cs ../referencesource/System/net/System/Net/NetworkInformation/nodetype.cs ../referencesource/System/net/System/Net/NetworkInformation/pingexception.cs +../referencesource/System/sys/system/Diagnostics/CodeAnalysis/ExcludeFromCodeCoverageAttribute.cs + +../referencesource/System/sys/system/IO/ports/InternalResources.cs + ../referencesource/System/sys/system/runtime/interopservices/DefaultParameterValueAttribute.cs ../referencesource/System/sys/system/runtime/interopservices/handlecollector.cs ../referencesource/System/sys/system/runtime/versioning/FrameworkName.cs ../referencesource/System/sys/system/threading/Barrier.cs +../referencesource/System/sys/system/threading/semaphore.cs + +../referencesource/System/sys/system/windows/markup/ValueSerializerAttribute.cs ../referencesource/System/security/system/security/Authentication/ExtendedProtection/TokenBinding.cs +../referencesource/System/security/system/security/Authentication/ExtendedProtection/ServiceNameCollection.cs ../referencesource/System/security/system/security/cryptography/oid.cs @@ -816,6 +878,9 @@ ReferenceSources/Win32Exception.cs ../referencesource/System/security/system/security/permissions/typedescriptorpermission.cs +../referencesource/System/services/monitoring/system/diagnosticts/ProcessModuleCollection.cs +../referencesource/System/services/monitoring/system/diagnosticts/ProcessThreadCollection.cs + ../referencesource/System/services/timers/system/timers/ElapsedEventHandler.cs ../referencesource/System/services/timers/system/timers/Timer.cs ../referencesource/System/services/timers/system/timers/TimersDescriptionAttribute.cs @@ -918,7 +983,6 @@ ReferenceSources/Win32Exception.cs ../Mono.Security/Mono.Security.Interface/HashAlgorithmType.cs ../Mono.Security/Mono.Security.Interface/IBufferOffsetSize.cs ../Mono.Security/Mono.Security.Interface/IMonoTlsEventSink.cs -../Mono.Security/Mono.Security.Interface/IMonoTlsContext.cs ../Mono.Security/Mono.Security.Interface/IMonoSslStream.cs ../Mono.Security/Mono.Security.Interface/MonoTlsConnectionInfo.cs ../Mono.Security/Mono.Security.Interface/MonoTlsProvider.cs diff --git a/mcs/class/System/monodroid_System.dll.sources b/mcs/class/System/monodroid_System.dll.sources index 686004bd3b..c2950c536c 100644 --- a/mcs/class/System/monodroid_System.dll.sources +++ b/mcs/class/System/monodroid_System.dll.sources @@ -1,3 +1,4 @@ #include mobile_System.dll.sources System/AndroidPlatform.cs Mono.Net.Security/MonoTlsProviderFactory.Droid.cs +Mono.Btls/MonoBtlsX509LookupAndroid.cs diff --git a/mcs/class/Mono.Security.Providers.OldTls/Mono.Security.Providers.OldTls.dll.sources b/mcs/class/System/monotouch_watch_System.dll.exclude.sources similarity index 53% rename from mcs/class/Mono.Security.Providers.OldTls/Mono.Security.Providers.OldTls.dll.sources rename to mcs/class/System/monotouch_watch_System.dll.exclude.sources index 13653b8666..4bd39cc43b 100644 --- a/mcs/class/Mono.Security.Providers.OldTls/Mono.Security.Providers.OldTls.dll.sources +++ b/mcs/class/System/monotouch_watch_System.dll.exclude.sources @@ -1,13 +1,58 @@ -./Properties/AssemblyInfo.cs -../../build/common/Consts.cs -../../build/common/Locale.cs -../../build/common/MonoTODOAttribute.cs - -./Mono.Security.Providers.OldTls/OldTlsProvider.cs -../System/Mono.Net.Security/LegacySslStream.cs - +../Mono.Security/Mono.Security.Authenticode/PrivateKey.cs ../Mono.Security/Mono.Security.Cryptography/MD5SHA1.cs ../Mono.Security/Mono.Security.Cryptography/TlsHMAC.cs +../Mono.Security/Mono.Security.Interface/Alert.cs +../Mono.Security/Mono.Security.Interface/CertificateValidationHelper.cs +../Mono.Security/Mono.Security.Interface/CipherAlgorithmType.cs +../Mono.Security/Mono.Security.Interface/CipherSuiteCode.cs +../Mono.Security/Mono.Security.Interface/ExchangeAlgorithmType.cs +../Mono.Security/Mono.Security.Interface/HashAlgorithmType.cs +../Mono.Security/Mono.Security.Interface/IBufferOffsetSize.cs +../Mono.Security/Mono.Security.Interface/IMonoSslStream.cs +../Mono.Security/Mono.Security.Interface/IMonoTlsContext.cs +../Mono.Security/Mono.Security.Interface/IMonoTlsEventSink.cs +../Mono.Security/Mono.Security.Interface/MonoTlsConnectionInfo.cs +../Mono.Security/Mono.Security.Interface/MonoTlsProvider.cs +../Mono.Security/Mono.Security.Interface/MonoTlsProviderFactory.Apple.cs +../Mono.Security/Mono.Security.Interface/MonoTlsProviderFactory.cs +../Mono.Security/Mono.Security.Interface/MonoTlsSettings.cs +../Mono.Security/Mono.Security.Interface/TlsException.cs +../Mono.Security/Mono.Security.Interface/TlsProtocolCode.cs +../Mono.Security/Mono.Security.Interface/TlsProtocols.cs +../Mono.Security/Mono.Security.Protocol.Ntlm/ChallengeResponse.cs +../Mono.Security/Mono.Security.Protocol.Ntlm/ChallengeResponse2.cs +../Mono.Security/Mono.Security.Protocol.Ntlm/MessageBase.cs +../Mono.Security/Mono.Security.Protocol.Ntlm/NtlmAuthLevel.cs +../Mono.Security/Mono.Security.Protocol.Ntlm/NtlmFlags.cs +../Mono.Security/Mono.Security.Protocol.Ntlm/NtlmSettings.cs +../Mono.Security/Mono.Security.Protocol.Ntlm/Type1Message.cs +../Mono.Security/Mono.Security.Protocol.Ntlm/Type2Message.cs +../Mono.Security/Mono.Security.Protocol.Ntlm/Type3Message.cs +../Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsClientCertificate.cs +../Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsClientCertificateVerify.cs +../Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsClientFinished.cs +../Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsClientHello.cs +../Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsClientKeyExchange.cs +../Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsServerCertificate.cs +../Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsServerCertificateRequest.cs +../Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsServerFinished.cs +../Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsServerHello.cs +../Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsServerHelloDone.cs +../Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsServerKeyExchange.cs +../Mono.Security/Mono.Security.Protocol.Tls.Handshake.Server/TlsClientCertificate.cs +../Mono.Security/Mono.Security.Protocol.Tls.Handshake.Server/TlsClientCertificateVerify.cs +../Mono.Security/Mono.Security.Protocol.Tls.Handshake.Server/TlsClientFinished.cs +../Mono.Security/Mono.Security.Protocol.Tls.Handshake.Server/TlsClientHello.cs +../Mono.Security/Mono.Security.Protocol.Tls.Handshake.Server/TlsClientKeyExchange.cs +../Mono.Security/Mono.Security.Protocol.Tls.Handshake.Server/TlsServerCertificate.cs +../Mono.Security/Mono.Security.Protocol.Tls.Handshake.Server/TlsServerCertificateRequest.cs +../Mono.Security/Mono.Security.Protocol.Tls.Handshake.Server/TlsServerFinished.cs +../Mono.Security/Mono.Security.Protocol.Tls.Handshake.Server/TlsServerHello.cs +../Mono.Security/Mono.Security.Protocol.Tls.Handshake.Server/TlsServerHelloDone.cs +../Mono.Security/Mono.Security.Protocol.Tls.Handshake.Server/TlsServerKeyExchange.cs +../Mono.Security/Mono.Security.Protocol.Tls.Handshake/ClientCertificateType.cs +../Mono.Security/Mono.Security.Protocol.Tls.Handshake/HandshakeMessage.cs +../Mono.Security/Mono.Security.Protocol.Tls.Handshake/HandshakeType.cs ../Mono.Security/Mono.Security.Protocol.Tls/Alert.cs ../Mono.Security/Mono.Security.Protocol.Tls/CipherAlgorithmType.cs ../Mono.Security/Mono.Security.Protocol.Tls/CipherSuite.cs @@ -31,8 +76,8 @@ ../Mono.Security/Mono.Security.Protocol.Tls/SecurityProtocolType.cs ../Mono.Security/Mono.Security.Protocol.Tls/ServerContext.cs ../Mono.Security/Mono.Security.Protocol.Tls/ServerRecordProtocol.cs -../Mono.Security/Mono.Security.Protocol.Tls/SslClientStream.cs ../Mono.Security/Mono.Security.Protocol.Tls/SslCipherSuite.cs +../Mono.Security/Mono.Security.Protocol.Tls/SslClientStream.cs ../Mono.Security/Mono.Security.Protocol.Tls/SslHandshakeHash.cs ../Mono.Security/Mono.Security.Protocol.Tls/SslServerStream.cs ../Mono.Security/Mono.Security.Protocol.Tls/SslStreamBase.cs @@ -41,33 +86,60 @@ ../Mono.Security/Mono.Security.Protocol.Tls/TlsException.cs ../Mono.Security/Mono.Security.Protocol.Tls/TlsServerSettings.cs ../Mono.Security/Mono.Security.Protocol.Tls/TlsStream.cs -../Mono.Security/Mono.Security.Protocol.Tls.Handshake/ClientCertificateType.cs -../Mono.Security/Mono.Security.Protocol.Tls.Handshake/HandshakeMessage.cs -../Mono.Security/Mono.Security.Protocol.Tls.Handshake/HandshakeType.cs -../Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsClientCertificate.cs -../Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsClientCertificateVerify.cs -../Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsClientFinished.cs -../Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsClientHello.cs -../Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsClientKeyExchange.cs -../Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsServerCertificate.cs -../Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsServerCertificateRequest.cs -../Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsServerFinished.cs -../Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsServerHello.cs -../Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsServerHelloDone.cs -../Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsServerKeyExchange.cs -../Mono.Security/Mono.Security.Protocol.Tls.Handshake.Server/TlsClientCertificate.cs -../Mono.Security/Mono.Security.Protocol.Tls.Handshake.Server/TlsClientCertificateVerify.cs -../Mono.Security/Mono.Security.Protocol.Tls.Handshake.Server/TlsClientFinished.cs -../Mono.Security/Mono.Security.Protocol.Tls.Handshake.Server/TlsClientHello.cs -../Mono.Security/Mono.Security.Protocol.Tls.Handshake.Server/TlsClientKeyExchange.cs -../Mono.Security/Mono.Security.Protocol.Tls.Handshake.Server/TlsServerCertificate.cs -../Mono.Security/Mono.Security.Protocol.Tls.Handshake.Server/TlsServerCertificateRequest.cs -../Mono.Security/Mono.Security.Protocol.Tls.Handshake.Server/TlsServerFinished.cs -../Mono.Security/Mono.Security.Protocol.Tls.Handshake.Server/TlsServerHello.cs -../Mono.Security/Mono.Security.Protocol.Tls.Handshake.Server/TlsServerHelloDone.cs -../Mono.Security/Mono.Security.Protocol.Tls.Handshake.Server/TlsServerKeyExchange.cs -../Mono.Security/Mono.Security.X509.Extensions/AuthorityKeyIdentifierExtension.cs -../Mono.Security/Mono.Security.X509.Extensions/ExtendedKeyUsageExtension.cs -../Mono.Security/Mono.Security.X509.Extensions/GeneralNames.cs -../Mono.Security/Mono.Security.X509.Extensions/NetscapeCertTypeExtension.cs -../Mono.Security/Mono.Security.X509.Extensions/SubjectAltNameExtension.cs +Mono.Http/NtlmClient.cs +Mono.Net.Security/AsyncProtocolRequest.cs +Mono.Net.Security/CallbackHelpers.cs +Mono.Net.Security/ChainValidationHelper.cs +Mono.Net.Security/IMonoSslStream.cs +Mono.Net.Security/IMonoTlsProvider.cs +Mono.Net.Security/LegacySslStream.cs +Mono.Net.Security/LegacySslStream.cs +Mono.Net.Security/LegacyTlsProvider.cs +Mono.Net.Security/LegacyTlsProvider.cs +Mono.Net.Security/MobileAuthenticatedStream.cs +Mono.Net.Security/MobileTlsContext.cs +Mono.Net.Security/MonoSslStreamImpl.cs +Mono.Net.Security/MonoSslStreamWrapper.cs +Mono.Net.Security/MonoTlsProviderFactory.Apple.cs +Mono.Net.Security/MonoTlsProviderFactory.cs +Mono.Net.Security/MonoTlsProviderImpl.cs +Mono.Net.Security/MonoTlsProviderWrapper.cs +Mono.Net.Security/MonoTlsStream.cs +Mono.Net.Security/NoReflectionHelper.cs +Mono.Net.Security/SystemCertificateValidator.cs +System.Net/MacProxy.cs +System.Net.Mail/SmtpClient.cs +System.Net.Security/SslStream.cs +System.Net.Sockets/TcpClient.cs +System.Net.Sockets/TcpListener.cs +System.Net.Sockets/UdpClient.cs +System.Net.WebSockets/ClientWebSocket.cs +System.Net/AuthenticationManager.cs +System.Net/ChunkedInputStream.cs +System.Net/EndPointListener.cs +System.Net/EndPointManager.cs +System.Net/FtpAsyncResult.cs +System.Net/FtpDataStream.cs +System.Net/FtpRequestCreator.cs +System.Net/FtpRequestCreator.cs +System.Net/FtpStatus.cs +System.Net/FtpWebRequest.cs +System.Net/FtpWebResponse.cs +System.Net/HttpConnection.cs +System.Net/HttpListener.cs +System.Net/HttpListenerContext.cs +System.Net/HttpListenerPrefixCollection.cs +System.Net/HttpListenerRequest.cs +System.Net/HttpListenerResponse.cs +System.Net/HttpWebRequest.cs +System.Net/HttpWebResponse.cs +System.Net/IWebConnectionState.cs +System.Net/ListenerAsyncResult.cs +System.Net/NtlmClient.cs +System.Net/ResponseStream.cs +System.Net/ServicePoint.cs +System.Net/ServicePointManager.cs +System.Net/WebConnection.cs +System.Net/WebConnectionData.cs +System.Net/WebConnectionGroup.cs +System.Net/WebConnectionStream.cs diff --git a/mcs/class/System/monotouch_watch_System.dll.sources b/mcs/class/System/monotouch_watch_System.dll.sources index 7c0bd5983a..f7e73d81e3 100644 --- a/mcs/class/System/monotouch_watch_System.dll.sources +++ b/mcs/class/System/monotouch_watch_System.dll.sources @@ -1 +1,20 @@ #include monotouch_System.dll.sources +System.Net.Mail/SmtpClient.platformnotsupported.cs +System.Net.Security/SslStream.platformnotsupported.cs +System.Net.Sockets/TcpClient.platformnotsupported.cs +System.Net.Sockets/TcpListener.platformnotsupported.cs +System.Net.Sockets/UdpClient.platformnotsupported.cs +System.Net.WebSockets/ClientWebSocket.platformnotsupported.cs +System.Net/AuthenticationManager.platformnotsupported.cs +System.Net/FtpRequestCreator.platformnotsupported.cs +System.Net/FtpWebRequest.platformnotsupported.cs +System.Net/FtpWebResponse.platformnotsupported.cs +System.Net/HttpListener.platformnotsupported.cs +System.Net/HttpListenerContext.platformnotsupported.cs +System.Net/HttpListenerPrefixCollection.platformnotsupported.cs +System.Net/HttpListenerRequest.platformnotsupported.cs +System.Net/HttpListenerResponse.platformnotsupported.cs +System.Net/HttpWebRequest.platformnotsupported.cs +System.Net/HttpWebResponse.platformnotsupported.cs +System.Net/ServicePoint.platformnotsupported.cs +System.Net/ServicePointManager.platformnotsupported.cs diff --git a/mcs/class/System/monotouch_watch_runtime_System.dll.exclude.sources b/mcs/class/System/monotouch_watch_runtime_System.dll.exclude.sources new file mode 100644 index 0000000000..8869410435 --- /dev/null +++ b/mcs/class/System/monotouch_watch_runtime_System.dll.exclude.sources @@ -0,0 +1 @@ +#include monotouch_watch_System.dll.exclude.sources diff --git a/mcs/class/System/monotouch_watch_runtime_System.dll.sources b/mcs/class/System/monotouch_watch_runtime_System.dll.sources index 7c0bd5983a..c8c328c5ce 100644 --- a/mcs/class/System/monotouch_watch_runtime_System.dll.sources +++ b/mcs/class/System/monotouch_watch_runtime_System.dll.sources @@ -1 +1 @@ -#include monotouch_System.dll.sources +#include monotouch_watch_System.dll.sources diff --git a/mcs/class/corlib/Assembly/AssemblyInfo.cs b/mcs/class/corlib/Assembly/AssemblyInfo.cs index 3c68cceb82..6dc94160d1 100644 --- a/mcs/class/corlib/Assembly/AssemblyInfo.cs +++ b/mcs/class/corlib/Assembly/AssemblyInfo.cs @@ -59,7 +59,7 @@ using System.Runtime.InteropServices; [assembly: CLSCompliant (true)] [assembly: AssemblyDelaySign (true)] -#if NET_2_1 +#if MOBILE [assembly: AssemblyKeyFile ("../silverlight.pub")] #else [assembly: AssemblyKeyFile ("../ecma.pub")] @@ -83,6 +83,7 @@ using System.Runtime.InteropServices; [assembly: InternalsVisibleTo ("Xamarin.TVOS, PublicKey=0024000004800000940000000602000000240000525341310004000011000000438ac2a5acfbf16cbd2b2b47a62762f273df9cb2795ceccdf77d10bf508e69e7a362ea7a45455bbf3ac955e1f2e2814f144e5d817efc4c6502cc012df310783348304e3ae38573c6d658c234025821fda87a0be8a0d504df564e2c93b2b878925f42503e9d54dfef9f9586d9e6f38a305769587b1de01f6c0410328b2c9733db")] #elif MONOTOUCH_WATCH [assembly: InternalsVisibleTo ("Xamarin.WatchOS, PublicKey=0024000004800000940000000602000000240000525341310004000011000000438ac2a5acfbf16cbd2b2b47a62762f273df9cb2795ceccdf77d10bf508e69e7a362ea7a45455bbf3ac955e1f2e2814f144e5d817efc4c6502cc012df310783348304e3ae38573c6d658c234025821fda87a0be8a0d504df564e2c93b2b878925f42503e9d54dfef9f9586d9e6f38a305769587b1de01f6c0410328b2c9733db")] +[assembly: InternalsVisibleTo ("System.Security, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")] #else [assembly: InternalsVisibleTo ("monotouch, PublicKey=0024000004800000940000000602000000240000525341310004000011000000438ac2a5acfbf16cbd2b2b47a62762f273df9cb2795ceccdf77d10bf508e69e7a362ea7a45455bbf3ac955e1f2e2814f144e5d817efc4c6502cc012df310783348304e3ae38573c6d658c234025821fda87a0be8a0d504df564e2c93b2b878925f42503e9d54dfef9f9586d9e6f38a305769587b1de01f6c0410328b2c9733db")] [assembly: InternalsVisibleTo ("Xamarin.iOS, PublicKey=0024000004800000940000000602000000240000525341310004000011000000438ac2a5acfbf16cbd2b2b47a62762f273df9cb2795ceccdf77d10bf508e69e7a362ea7a45455bbf3ac955e1f2e2814f144e5d817efc4c6502cc012df310783348304e3ae38573c6d658c234025821fda87a0be8a0d504df564e2c93b2b878925f42503e9d54dfef9f9586d9e6f38a305769587b1de01f6c0410328b2c9733db")] @@ -94,5 +95,4 @@ using System.Runtime.InteropServices; [assembly: InternalsVisibleTo ("Xamarin.Mac, PublicKey=0024000004800000940000000602000000240000525341310004000011000000438ac2a5acfbf16cbd2b2b47a62762f273df9cb2795ceccdf77d10bf508e69e7a362ea7a45455bbf3ac955e1f2e2814f144e5d817efc4c6502cc012df310783348304e3ae38573c6d658c234025821fda87a0be8a0d504df564e2c93b2b878925f42503e9d54dfef9f9586d9e6f38a305769587b1de01f6c0410328b2c9733db")] #endif -[assembly: InternalsVisibleTo ("Xamarin.BoringTls, PublicKey=002400000480000094000000060200000024000052534131000400001100000099dd12eda85767ae6f06023ee28e711c7e5a212462095c83868c29db75eddf6d8e296e03824c14fedd5f55553fed0b6173be3cc985a4b7f9fb7c83ccff8ba3938563b3d1f45a81122f12a1bcb73edcaad61a8456c7595a6da5184b4dd9d10f011b949ef1391fccfeab1ba62aa51c267ef8bd57ef1b6ba5a4c515d0badb81a78f")] [assembly: Guid ("BED7F4EA-1A96-11D2-8F08-00A0C9A6186D")] diff --git a/mcs/class/corlib/CommonCrypto/SecRandom.cs b/mcs/class/corlib/CommonCrypto/SecRandom.cs index a112faf557..a35fe1dc66 100644 --- a/mcs/class/corlib/CommonCrypto/SecRandom.cs +++ b/mcs/class/corlib/CommonCrypto/SecRandom.cs @@ -39,6 +39,18 @@ namespace System.Security.Cryptography { { } + public RNGCryptoServiceProvider (byte[] rgb) + { + } + + public RNGCryptoServiceProvider (CspParameters cspParams) + { + } + + public RNGCryptoServiceProvider (string str) + { + } + ~RNGCryptoServiceProvider () { } diff --git a/mcs/class/corlib/Makefile b/mcs/class/corlib/Makefile index 1cd1a7af02..a0f17b0f19 100644 --- a/mcs/class/corlib/Makefile +++ b/mcs/class/corlib/Makefile @@ -203,7 +203,7 @@ tzi.exe:System/AndroidPlatform.cs $(wildcard System/TimeZone*.cs) ../../build/co trap "rm -f $(TMP_FILE1) $(TMP_FILE2)" EXIT INT QUIT TERM && \ sed 's/Environment\.GetResourceString/string.Format/g' ../referencesource/mscorlib/system/timezoneinfo.cs > $(TMP_FILE1) && \ sed 's/StringBuilder\.DefaultCapacity/100/g' ../referencesource/mscorlib/system/text/stringbuildercache.cs > $(TMP_FILE2) && \ - $(MCS) /debug+ /out:$@ -unsafe -nowarn:612,618 -d:INSIDE_CORLIB,MONO_CULTURE_DATA -d:LIBC $(REFERENCE_SOURCES_FLAGS) "/d:SELF_TEST;NET_1_1;NET_2_0;NET_2_1;NET_3_5;NET_4_0;NET_4_5;MONO;DISABLE_CAS_USE;MOBILE;MOBILE_DYNAMIC;MONODROID;ANDROID" $^ $(TMP_FILE1) $(TMP_FILE2) + $(MCS) /debug+ /out:$@ -unsafe -nowarn:612,618 -d:INSIDE_CORLIB,MONO_CULTURE_DATA -d:LIBC $(REFERENCE_SOURCES_FLAGS) "/d:SELF_TEST;NET_1_1;NET_2_0;MOBILE;NET_3_5;NET_4_0;NET_4_5;MONO;DISABLE_CAS_USE;MOBILE;MOBILE_DYNAMIC;MONODROID;ANDROID" $^ $(TMP_FILE1) $(TMP_FILE2) android-pull-tzdb: mkdir -p android/tzdb/usr/share/zoneinfo diff --git a/mcs/class/corlib/Microsoft.Win32/IRegistryApi.cs b/mcs/class/corlib/Microsoft.Win32/IRegistryApi.cs index b4ad9f294c..b7eeefe229 100644 --- a/mcs/class/corlib/Microsoft.Win32/IRegistryApi.cs +++ b/mcs/class/corlib/Microsoft.Win32/IRegistryApi.cs @@ -30,7 +30,7 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -#if !NET_2_1 +#if !MOBILE using System; using System.Text; @@ -67,5 +67,5 @@ namespace Microsoft.Win32 { } } -#endif // NET_2_1 +#endif // MOBILE diff --git a/mcs/class/corlib/Microsoft.Win32/RegistryKeyPermissionCheck.cs b/mcs/class/corlib/Microsoft.Win32/RegistryKeyPermissionCheck.cs index 7994839eda..a89a865de9 100644 --- a/mcs/class/corlib/Microsoft.Win32/RegistryKeyPermissionCheck.cs +++ b/mcs/class/corlib/Microsoft.Win32/RegistryKeyPermissionCheck.cs @@ -27,7 +27,7 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -#if !NET_2_1 +#if !MOBILE namespace Microsoft.Win32 { public enum RegistryKeyPermissionCheck diff --git a/mcs/class/corlib/Microsoft.Win32/UnixRegistryApi.cs b/mcs/class/corlib/Microsoft.Win32/UnixRegistryApi.cs index 757dc5eb21..30a035593a 100644 --- a/mcs/class/corlib/Microsoft.Win32/UnixRegistryApi.cs +++ b/mcs/class/corlib/Microsoft.Win32/UnixRegistryApi.cs @@ -37,7 +37,7 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -#if !NET_2_1 +#if !MOBILE using System; using System.Collections; @@ -1029,5 +1029,5 @@ namespace Microsoft.Win32 { } } -#endif // NET_2_1 +#endif // MOBILE diff --git a/mcs/class/corlib/Microsoft.Win32/Win32RegistryApi.cs b/mcs/class/corlib/Microsoft.Win32/Win32RegistryApi.cs index c5335ffd0e..220967e09e 100644 --- a/mcs/class/corlib/Microsoft.Win32/Win32RegistryApi.cs +++ b/mcs/class/corlib/Microsoft.Win32/Win32RegistryApi.cs @@ -33,7 +33,7 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -#if !NET_2_1 +#if !MOBILE using System; using System.Collections; @@ -241,48 +241,66 @@ namespace Microsoft.Win32 public void SetValue (RegistryKey rkey, string name, object value, RegistryValueKind valueKind) { Type type = value.GetType (); - int result; IntPtr handle = GetHandle (rkey); - if (valueKind == RegistryValueKind.QWord && type == typeof (long)) { - long rawValue = (long)value; - result = RegSetValueEx (handle, name, IntPtr.Zero, RegistryValueKind.QWord, ref rawValue, Int64ByteSize); - } else if (valueKind == RegistryValueKind.DWord && type == typeof (int)) { - int rawValue = (int)value; - result = RegSetValueEx (handle, name, IntPtr.Zero, RegistryValueKind.DWord, ref rawValue, Int32ByteSize); - } else if (valueKind == RegistryValueKind.Binary && type == typeof (byte[])) { - byte[] rawValue = (byte[]) value; - result = RegSetValueEx (handle, name, IntPtr.Zero, RegistryValueKind.Binary, rawValue, rawValue.Length); - } else if (valueKind == RegistryValueKind.MultiString && type == typeof (string[])) { - string[] vals = (string[]) value; - StringBuilder fullStringValue = new StringBuilder (); - foreach (string v in vals) - { - fullStringValue.Append (v); - fullStringValue.Append ('\0'); + switch (valueKind) { + case RegistryValueKind.QWord: + try { + long rawValue = Convert.ToInt64 (value); + CheckResult (RegSetValueEx (handle, name, IntPtr.Zero, RegistryValueKind.QWord, ref rawValue, Int64ByteSize)); + return; + } catch (OverflowException) { } - fullStringValue.Append ('\0'); + break; + case RegistryValueKind.DWord: + try { + int rawValue = Convert.ToInt32 (value); + CheckResult (RegSetValueEx (handle, name, IntPtr.Zero, RegistryValueKind.DWord, ref rawValue, Int32ByteSize)); + return; + } catch (OverflowException) { + } + break; + case RegistryValueKind.Binary: + if (type == typeof (byte[])) { + byte[] rawValue = (byte[]) value; + CheckResult (RegSetValueEx (handle, name, IntPtr.Zero, RegistryValueKind.Binary, rawValue, rawValue.Length)); + return; + } + break; + case RegistryValueKind.MultiString: + if (type == typeof (string[])) { + string[] vals = (string[]) value; + StringBuilder fullStringValue = new StringBuilder (); + foreach (string v in vals) + { + fullStringValue.Append (v); + fullStringValue.Append ('\0'); + } + fullStringValue.Append ('\0'); - byte[] rawValue = Encoding.Unicode.GetBytes (fullStringValue.ToString ()); + byte[] rawValue = Encoding.Unicode.GetBytes (fullStringValue.ToString ()); - result = RegSetValueEx (handle, name, IntPtr.Zero, RegistryValueKind.MultiString, rawValue, rawValue.Length); - } else if ((valueKind == RegistryValueKind.String || valueKind == RegistryValueKind.ExpandString) && - type == typeof (string)){ - string rawValue = String.Format ("{0}{1}", value, '\0'); - result = RegSetValueEx (handle, name, IntPtr.Zero, valueKind, rawValue, - rawValue.Length * NativeBytesPerCharacter); - - } else if (type.IsArray) { - throw new ArgumentException ("Only string and byte arrays can written as registry values"); - } else { - throw new ArgumentException ("Type does not match the valueKind"); + CheckResult (RegSetValueEx (handle, name, IntPtr.Zero, RegistryValueKind.MultiString, rawValue, rawValue.Length)); + return; + } + break; + case RegistryValueKind.String: + case RegistryValueKind.ExpandString: + if (type == typeof (string)) { + string rawValue = String.Format ("{0}{1}", value, '\0'); + CheckResult (RegSetValueEx (handle, name, IntPtr.Zero, valueKind, rawValue, + rawValue.Length * NativeBytesPerCharacter)); + return; + } + break; + default: + if (type.IsArray) { + throw new ArgumentException ("Only string and byte arrays can written as registry values"); + } + break; } - // handle the result codes - if (result != Win32ResultCode.Success) - { - GenerateException (result); - } + throw new ArgumentException ("Type does not match the valueKind"); } public void SetValue (RegistryKey rkey, string name, object value) @@ -318,9 +336,6 @@ namespace Microsoft.Win32 rawValue.Length * NativeBytesPerCharacter); } - if (result == Win32ResultCode.MarkedForDeletion) - throw RegistryKey.CreateMarkedForDeletionException (); - // handle the result codes if (result != Win32ResultCode.Success) { @@ -356,9 +371,6 @@ namespace Microsoft.Win32 int result = RegEnumKey (handle, index, stringBuffer, stringBuffer.Capacity); - if (result == Win32ResultCode.MarkedForDeletion) - throw RegistryKey.CreateMarkedForDeletionException (); - if (result == Win32ResultCode.Success) continue; @@ -386,9 +398,6 @@ namespace Microsoft.Win32 IntPtr.Zero, ref type, IntPtr.Zero, IntPtr.Zero); - if (result == Win32ResultCode.MarkedForDeletion) - throw RegistryKey.CreateMarkedForDeletionException (); - if (result == Win32ResultCode.Success || result == Win32ResultCode.MoreData) continue; @@ -470,9 +479,6 @@ namespace Microsoft.Win32 RegOptionsNonVolatile, OpenRegKeyRead | OpenRegKeyWrite, IntPtr.Zero, out subKeyHandle, out disposition); - if (result == Win32ResultCode.MarkedForDeletion) - throw RegistryKey.CreateMarkedForDeletionException (); - if (result != Win32ResultCode.Success) { GenerateException (result); } @@ -490,9 +496,6 @@ namespace Microsoft.Win32 options == RegistryOptions.Volatile ? RegOptionsVolatile : RegOptionsNonVolatile, OpenRegKeyRead | OpenRegKeyWrite, IntPtr.Zero, out subKeyHandle, out disposition); - if (result == Win32ResultCode.MarkedForDeletion) - throw RegistryKey.CreateMarkedForDeletionException (); - if (result != Win32ResultCode.Success) GenerateException (result); @@ -580,15 +583,19 @@ namespace Microsoft.Win32 if (result == Win32ResultCode.NoMoreEntries) break; - if (result == Win32ResultCode.MarkedForDeletion) - throw RegistryKey.CreateMarkedForDeletionException (); - GenerateException (result); } return values.ToArray (); } + private void CheckResult (int result) + { + if (result != Win32ResultCode.Success) { + GenerateException (result); + } + } + /// /// convert a win32 error code into an appropriate exception. /// @@ -604,6 +611,10 @@ namespace Microsoft.Win32 throw new IOException ("The network path was not found."); case Win32ResultCode.InvalidHandle: throw new IOException ("Invalid handle."); + case Win32ResultCode.MarkedForDeletion: + throw RegistryKey.CreateMarkedForDeletionException (); + case Win32ResultCode.ChildMustBeVolatile: + throw new IOException ("Cannot create a stable subkey under a volatile parent key."); default: // unidentified system exception throw new SystemException (); @@ -626,5 +637,5 @@ namespace Microsoft.Win32 } } -#endif // NET_2_1 +#endif // MOBILE diff --git a/mcs/class/corlib/Microsoft.Win32/Win32ResultCode.cs b/mcs/class/corlib/Microsoft.Win32/Win32ResultCode.cs index 1d0cbdaa85..4e8e85d0e8 100644 --- a/mcs/class/corlib/Microsoft.Win32/Win32ResultCode.cs +++ b/mcs/class/corlib/Microsoft.Win32/Win32ResultCode.cs @@ -30,7 +30,7 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -#if !NET_2_1 +#if !MOBILE using System; using System.Runtime.InteropServices; @@ -58,8 +58,9 @@ namespace Microsoft.Win32 public const int NetworkPathNotFound = 53; public const int NoMoreEntries = 259; public const int MarkedForDeletion = 1018; + public const int ChildMustBeVolatile = 1021; } } -#endif // NET_2_1 +#endif // MOBILE diff --git a/mcs/class/corlib/Mono.Security/Uri.cs b/mcs/class/corlib/Mono.Security/Uri.cs index 104516c3e9..9be2deb9e2 100644 --- a/mcs/class/corlib/Mono.Security/Uri.cs +++ b/mcs/class/corlib/Mono.Security/Uri.cs @@ -1015,7 +1015,7 @@ namespace Mono.Security { } // 5 path - pos = uriString.IndexOfAny (new char[] {'/'}); + pos = uriString.IndexOfAny (new char[] {'/', '\\'}); if (unixAbsPath) pos = -1; if (pos == -1) { @@ -1042,6 +1042,8 @@ namespace Mono.Security { pos = uriString.LastIndexOf (":"); if (unixAbsPath) pos = -1; + if (pos == 1 && scheme == Uri.UriSchemeFile && Char.IsLetter (uriString [0])) + pos = -1; if (pos != -1 && pos != (uriString.Length - 1)) { string portStr = uriString.Remove (0, pos + 1); if (portStr.Length > 1 && portStr [portStr.Length - 1] != ']') { diff --git a/mcs/class/corlib/Mono/Runtime.cs b/mcs/class/corlib/Mono/Runtime.cs index 7a5f9887c6..12148ed85d 100644 --- a/mcs/class/corlib/Mono/Runtime.cs +++ b/mcs/class/corlib/Mono/Runtime.cs @@ -31,7 +31,7 @@ using System.Runtime.CompilerServices; namespace Mono { -#if MOBILE +#if MOBILE || XAMMAC_4_5 public #endif static class Runtime @@ -40,16 +40,31 @@ namespace Mono { [MethodImplAttribute (MethodImplOptions.InternalCall)] private static extern void mono_runtime_install_handlers (); - static internal void InstallSignalHandlers () +#if MOBILE || XAMMAC_4_5 + public +#else + internal +#endif + static void InstallSignalHandlers () { mono_runtime_install_handlers (); } +#if MOBILE || XAMMAC_4_5 + [MethodImplAttribute (MethodImplOptions.InternalCall)] + static extern void mono_runtime_cleanup_handlers (); + + public static void RemoveSignalHandlers () + { + mono_runtime_cleanup_handlers (); + } +#endif + // Should not be removed intended for external use // Safe to be called using reflection // Format is undefined only for use as a string for reporting [MethodImplAttribute (MethodImplOptions.InternalCall)] -#if MOBILE +#if MOBILE || XAMMAC_4_5 public #else internal diff --git a/mcs/class/corlib/Mono/RuntimeHandles.cs b/mcs/class/corlib/Mono/RuntimeHandles.cs new file mode 100644 index 0000000000..68db33f394 --- /dev/null +++ b/mcs/class/corlib/Mono/RuntimeHandles.cs @@ -0,0 +1,274 @@ +// +// Wrapper handles for Mono Runtime internal structs +// +// Authors: +// Aleksey Kliger +// Rodrigo Kumpera +// +// Copyright 2016 Dot net foundation. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System; +using System.Reflection; +using System.Runtime.CompilerServices; + +namespace Mono { + + internal struct RuntimeClassHandle { + unsafe RuntimeStructs.MonoClass* value; + + internal unsafe RuntimeClassHandle (RuntimeStructs.MonoClass* value) { + this.value = value; + } + + internal unsafe RuntimeClassHandle (IntPtr ptr) { + this.value = (RuntimeStructs.MonoClass*) ptr; + } + + internal unsafe RuntimeStructs.MonoClass* Value { + get { return value; } + } + + public override bool Equals (object obj) + { + if (obj == null || GetType () != obj.GetType ()) + return false; + + unsafe { return value == ((RuntimeClassHandle)obj).Value; } + } + + public override int GetHashCode () + { + unsafe { return ((IntPtr)value).GetHashCode (); } + } + + public bool Equals (RuntimeClassHandle handle) + { + unsafe { return value == handle.Value; } + } + + public static bool operator == (RuntimeClassHandle left, Object right) + { + return (right != null) && (right is RuntimeClassHandle) && left.Equals ((RuntimeClassHandle)right); + } + + public static bool operator != (RuntimeClassHandle left, Object right) + { + return (right == null) || !(right is RuntimeClassHandle) || !left.Equals ((RuntimeClassHandle)right); + } + + public static bool operator == (Object left, RuntimeClassHandle right) + { + return (left != null) && (left is RuntimeClassHandle) && ((RuntimeClassHandle)left).Equals (right); + } + + public static bool operator != (Object left, RuntimeClassHandle right) + { + return (left == null) || !(left is RuntimeClassHandle) || !((RuntimeClassHandle)left).Equals (right); + } + + [MethodImpl(MethodImplOptions.InternalCall)] + internal unsafe extern static IntPtr GetTypeFromClass (RuntimeStructs.MonoClass *klass); + + internal RuntimeTypeHandle GetTypeHandle () + { + unsafe { return new RuntimeTypeHandle (GetTypeFromClass (value)); } + } + } + + internal struct RuntimeRemoteClassHandle { + unsafe RuntimeStructs.RemoteClass* value; + + internal unsafe RuntimeRemoteClassHandle (RuntimeStructs.RemoteClass* value) + { + this.value = value; + } + + internal RuntimeClassHandle ProxyClass { + get { + unsafe { + return new RuntimeClassHandle (value->proxy_class); + } + } + } + } + + internal struct RuntimeGenericParamInfoHandle { + unsafe RuntimeStructs.GenericParamInfo* value; + + internal unsafe RuntimeGenericParamInfoHandle (RuntimeStructs.GenericParamInfo* value) + { + this.value = value; + } + + internal unsafe RuntimeGenericParamInfoHandle (IntPtr ptr) + { + this.value = (RuntimeStructs.GenericParamInfo*) ptr; + } + + + internal Type[] Constraints { get { return GetConstraints (); } } + + internal GenericParameterAttributes Attributes { + get { + unsafe { + return (GenericParameterAttributes) value->flags; + } + } + } + + Type[] GetConstraints () { + int n = GetConstraintsCount (); + var a = new Type[n]; + for (int i = 0; i < n; i++) { + unsafe { + RuntimeClassHandle c = new RuntimeClassHandle (value->constraints[i]); + a[i] = Type.GetTypeFromHandle (c.GetTypeHandle ()); + } + } + return a; + } + + int GetConstraintsCount () { + int i = 0; + unsafe { + RuntimeStructs.MonoClass** p = value->constraints; + while (p != null && *p != null) { + p++; i++; + } + } + return i; + } + } + + internal struct RuntimeEventHandle { + IntPtr value; + + internal RuntimeEventHandle (IntPtr v) + { + value = v; + } + + public IntPtr Value { + get { + return value; + } + } + + public override bool Equals (object obj) + { + if (obj == null || GetType () != obj.GetType ()) + return false; + + return value == ((RuntimeEventHandle)obj).Value; + } + + public bool Equals (RuntimeEventHandle handle) + { + return value == handle.Value; + } + + public override int GetHashCode () + { + return value.GetHashCode (); + } + + public static bool operator == (RuntimeEventHandle left, RuntimeEventHandle right) + { + return left.Equals (right); + } + + public static bool operator != (RuntimeEventHandle left, RuntimeEventHandle right) + { + return !left.Equals (right); + } + } + + internal struct RuntimePropertyHandle { + IntPtr value; + + internal RuntimePropertyHandle (IntPtr v) + { + value = v; + } + + public IntPtr Value { + get { + return value; + } + } + + public override bool Equals (object obj) + { + if (obj == null || GetType () != obj.GetType ()) + return false; + + return value == ((RuntimePropertyHandle)obj).Value; + } + + public bool Equals (RuntimePropertyHandle handle) + { + return value == handle.Value; + } + + public override int GetHashCode () + { + return value.GetHashCode (); + } + + public static bool operator == (RuntimePropertyHandle left, RuntimePropertyHandle right) + { + return left.Equals (right); + } + + public static bool operator != (RuntimePropertyHandle left, RuntimePropertyHandle right) + { + return !left.Equals (right); + } + } + + internal struct RuntimeGPtrArrayHandle { + unsafe RuntimeStructs.GPtrArray* value; + + internal unsafe RuntimeGPtrArrayHandle (RuntimeStructs.GPtrArray* value) + { + this.value = value; + } + + internal unsafe RuntimeGPtrArrayHandle (IntPtr ptr) + { + this.value = (RuntimeStructs.GPtrArray*) ptr; + } + + internal int Length { + get { + unsafe { + return value->len; + } + } + } + + internal IntPtr this[int i] => Lookup (i); + + internal IntPtr Lookup (int i) + { + if (i >= 0 && i < Length) { + unsafe { + return value->data[i]; + } + } else + throw new IndexOutOfRangeException (); + } + + [MethodImpl(MethodImplOptions.InternalCall)] + unsafe extern static void GPtrArrayFree (RuntimeStructs.GPtrArray* value); + + internal static void DestroyAndFree (ref RuntimeGPtrArrayHandle h) { + unsafe { + GPtrArrayFree (h.value); + h.value = null; + } + } + } +} diff --git a/mcs/class/corlib/Mono/RuntimeMarshal.cs b/mcs/class/corlib/Mono/RuntimeMarshal.cs new file mode 100644 index 0000000000..38da4e2201 --- /dev/null +++ b/mcs/class/corlib/Mono/RuntimeMarshal.cs @@ -0,0 +1,65 @@ +using System; +using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; + +namespace Mono { + internal static class RuntimeMarshal { + internal static string PtrToUtf8String (IntPtr ptr) + { + unsafe { + return new String ((sbyte*)ptr); + } + } + + internal static SafeStringMarshal MarshalString (string str) + { + return new SafeStringMarshal (str); + } + + static int DecodeBlobSize (IntPtr in_ptr, out IntPtr out_ptr) + { + uint size; + unsafe { + byte *ptr = (byte*)in_ptr; + + if ((*ptr & 0x80) == 0) { + size = (uint)(ptr [0] & 0x7f); + ptr++; + } else if ((*ptr & 0x40) == 0){ + size = (uint)(((ptr [0] & 0x3f) << 8) + ptr [1]); + ptr += 2; + } else { + size = (uint)(((ptr [0] & 0x1f) << 24) + + (ptr [1] << 16) + + (ptr [2] << 8) + + ptr [3]); + ptr += 4; + } + out_ptr = (IntPtr)ptr; + } + + return (int)size; + } + + internal static byte[] DecodeBlobArray (IntPtr ptr) + { + IntPtr out_ptr; + int size = DecodeBlobSize (ptr, out out_ptr); + byte[] res = new byte [size]; + Marshal.Copy (out_ptr, res, 0, size); + return res; + } + + internal static int AsciHexDigitValue (int c) + { + if (c >= '0' && c <= '9') + return c - '0'; + if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + return c - 'A' + 10; + } + + [MethodImpl (MethodImplOptions.InternalCall)] + internal static extern void FreeAssemblyName (ref MonoAssemblyName name); + } +} diff --git a/mcs/class/corlib/Mono/RuntimeStructs.cs b/mcs/class/corlib/Mono/RuntimeStructs.cs new file mode 100644 index 0000000000..f70ee556ac --- /dev/null +++ b/mcs/class/corlib/Mono/RuntimeStructs.cs @@ -0,0 +1,83 @@ +// +// Mono runtime native structs surfaced to managed code. +// +// Authors: +// Aleksey Kliger +// Rodrigo Kumpera +// +// Copyright 2016 Dot net foundation. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System; +using System.Runtime.InteropServices; + +#pragma warning disable 169 + +namespace Mono { + // + // Managed representations of mono runtime types + // + internal static class RuntimeStructs { + // class-internals.h MonoRemoteClass + [StructLayout(LayoutKind.Sequential)] + internal unsafe struct RemoteClass { + internal IntPtr default_vtable; + internal IntPtr xdomain_vtable; + internal MonoClass* proxy_class; + internal IntPtr proxy_class_name; + internal uint interface_count; + // FIXME: How to represent variable-length array struct member? + // MonoClass* interfaces []; + } + + internal struct MonoClass { + } + + // class-internals.h MonoGenericParamInfo + internal unsafe struct GenericParamInfo { + internal MonoClass* pklass; + internal IntPtr name; + internal ushort flags; + internal uint token; + internal MonoClass** constraints; /* NULL terminated */ + } + + // glib.h GPtrArray + internal unsafe struct GPtrArray { + internal IntPtr* data; + internal int len; + } + + // handle.h HandleStackMark + struct HandleStackMark { + int size; + IntPtr chunk; + } + + // mono-error.h MonoError + struct MonoError { + ushort error_code; + ushort hidden_0; + IntPtr hidden_1, hidden_2, hidden_3, hidden_4, hidden_5, hidden_6, hidden_7, hidden_8; + IntPtr hidden_11, hidden_12, hidden_13, hidden_14, hidden_15, hidden_16, hidden_17, hidden_18; + } + } + + //Maps to metadata-internals.h:: MonoAssemblyName + internal unsafe struct MonoAssemblyName + { + const int MONO_PUBLIC_KEY_TOKEN_LENGTH = 17; + + internal IntPtr name; + internal IntPtr culture; + internal IntPtr hash_value; + internal IntPtr public_key; + internal fixed byte public_key_token [MONO_PUBLIC_KEY_TOKEN_LENGTH]; + internal uint hash_alg; + internal uint hash_len; + internal uint flags; + internal ushort major, minor, build, revision; + internal ushort arch; + } +} diff --git a/mcs/class/corlib/Mono/SafeGPtrArrayHandle.cs b/mcs/class/corlib/Mono/SafeGPtrArrayHandle.cs new file mode 100644 index 0000000000..0441c9b8bd --- /dev/null +++ b/mcs/class/corlib/Mono/SafeGPtrArrayHandle.cs @@ -0,0 +1,38 @@ +// +// Safe handle class for Mono.RuntimeGPtrArrayHandle +// +// Authors: +// Aleksey Kliger +// Rodrigo Kumpera +// +// Copyright 2016 Dot net foundation. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System; +using System.Runtime.CompilerServices; + +namespace Mono { + internal struct SafeGPtrArrayHandle : IDisposable { + RuntimeGPtrArrayHandle handle; + + internal SafeGPtrArrayHandle (IntPtr ptr) + { + handle = new RuntimeGPtrArrayHandle (ptr); + } + + public void Dispose () { + RuntimeGPtrArrayHandle.DestroyAndFree (ref handle); + } + + internal int Length { + get { + return handle.Length; + } + } + + internal IntPtr this[int i] => handle[i]; + } + + +} diff --git a/mcs/class/corlib/Mono/SafeStringMarshal.cs b/mcs/class/corlib/Mono/SafeStringMarshal.cs new file mode 100644 index 0000000000..c18f0d388a --- /dev/null +++ b/mcs/class/corlib/Mono/SafeStringMarshal.cs @@ -0,0 +1,46 @@ +// +// Safe wrapper for a string and its UTF8 encoding +// +// Authors: +// Aleksey Kliger +// Rodrigo Kumpera +// +// Copyright 2016 Dot net foundation. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System; +using System.Runtime.CompilerServices; + +namespace Mono { + internal struct SafeStringMarshal : IDisposable { + readonly string str; + IntPtr marshaled_string; + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public extern static IntPtr StringToUtf8 (string str); + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public extern static void GFree (IntPtr ptr); + + public SafeStringMarshal (string str) { + this.str = str; + this.marshaled_string = IntPtr.Zero; + } + + public IntPtr Value { + get { + if (marshaled_string == IntPtr.Zero && str != null) + marshaled_string = StringToUtf8 (str); + return marshaled_string; + } + } + + public void Dispose () { + if (marshaled_string != IntPtr.Zero) { + GFree (marshaled_string); + marshaled_string = IntPtr.Zero; + } + } + } +} diff --git a/mcs/class/corlib/ReferenceSources/AppContextSwitches.cs b/mcs/class/corlib/ReferenceSources/AppContextSwitches.cs index bf8c82427e..8874423d84 100644 --- a/mcs/class/corlib/ReferenceSources/AppContextSwitches.cs +++ b/mcs/class/corlib/ReferenceSources/AppContextSwitches.cs @@ -1,5 +1,7 @@ namespace System { static class AppContextSwitches { - public const bool ThrowExceptionIfDisposedCancellationTokenSource = true; + public static readonly bool ThrowExceptionIfDisposedCancellationTokenSource = true; + public static readonly bool SetActorAsReferenceWhenCopyingClaimsIdentity = false; + public static readonly bool NoAsyncCurrentCulture = false; } } \ No newline at end of file diff --git a/mcs/class/corlib/ReferenceSources/MethodBase.cs b/mcs/class/corlib/ReferenceSources/MethodBase.cs index 2fb847a6ef..8cd0005632 100644 --- a/mcs/class/corlib/ReferenceSources/MethodBase.cs +++ b/mcs/class/corlib/ReferenceSources/MethodBase.cs @@ -46,7 +46,12 @@ namespace System.Reflection internal static MethodBase GetMethodFromHandleNoGenericCheck (RuntimeMethodHandle handle) { - return GetMethodFromHandleInternalType (handle.Value, IntPtr.Zero); + return GetMethodFromHandleInternalType_native (handle.Value, IntPtr.Zero, false); + } + + internal static MethodBase GetMethodFromHandleNoGenericCheck (RuntimeMethodHandle handle, RuntimeTypeHandle reflectedType) + { + return GetMethodFromHandleInternalType_native (handle.Value, reflectedType.Value, false); } [MethodImplAttribute (MethodImplOptions.InternalCall)] @@ -57,7 +62,12 @@ namespace System.Reflection return GetMethodBodyInternal (handle); } + static MethodBase GetMethodFromHandleInternalType (IntPtr method_handle, IntPtr type_handle) { + return GetMethodFromHandleInternalType_native (method_handle, type_handle, true); + } + [MethodImplAttribute (MethodImplOptions.InternalCall)] - extern static MethodBase GetMethodFromHandleInternalType (IntPtr method_handle, IntPtr type_handle); + internal extern static MethodBase GetMethodFromHandleInternalType_native (IntPtr method_handle, IntPtr type_handle, bool genericCheck); + } -} \ No newline at end of file +} diff --git a/mcs/class/corlib/ReferenceSources/PathInternal.cs b/mcs/class/corlib/ReferenceSources/PathInternal.cs new file mode 100644 index 0000000000..828a080bb4 --- /dev/null +++ b/mcs/class/corlib/ReferenceSources/PathInternal.cs @@ -0,0 +1,10 @@ +namespace System.IO +{ + static class PathInternal + { + public static bool IsPartiallyQualified (string path) + { + return false; + } + } +} \ No newline at end of file diff --git a/mcs/class/corlib/ReferenceSources/RuntimeType.cs b/mcs/class/corlib/ReferenceSources/RuntimeType.cs index f577efcd5c..8a49451936 100644 --- a/mcs/class/corlib/ReferenceSources/RuntimeType.cs +++ b/mcs/class/corlib/ReferenceSources/RuntimeType.cs @@ -452,7 +452,8 @@ namespace System throw new InvalidOperationException(Environment.GetResourceString("Arg_NotGenericParameter")); Contract.EndContractBlock(); - Type[] constraints = GetGenericParameterConstraints_impl (); + var paramInfo = new Mono.RuntimeGenericParamInfoHandle (RuntimeTypeHandle.GetGenericParameterInfo (this)); + Type[] constraints = paramInfo.Constraints; if (constraints == null) constraints = EmptyArray.Value; @@ -471,13 +472,57 @@ namespace System static extern Type MakeGenericType (Type gt, Type [] types); [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal extern RuntimeMethodInfo[] GetMethodsByName (string name, BindingFlags bindingAttr, bool ignoreCase, Type reflected_type); + internal extern IntPtr GetMethodsByName_native (IntPtr namePtr, BindingFlags bindingAttr, bool ignoreCase); + + internal RuntimeMethodInfo[] GetMethodsByName (string name, BindingFlags bindingAttr, bool ignoreCase, RuntimeType reflectedType) + { + var refh = new RuntimeTypeHandle (reflectedType); + using (var namePtr = new Mono.SafeStringMarshal (name)) + using (var h = new Mono.SafeGPtrArrayHandle (GetMethodsByName_native (namePtr.Value, bindingAttr, ignoreCase))) { + var n = h.Length; + var a = new RuntimeMethodInfo [n]; + for (int i = 0; i < n; i++) { + var mh = new RuntimeMethodHandle (h[i]); + a[i] = (RuntimeMethodInfo) MethodBase.GetMethodFromHandleNoGenericCheck (mh, refh); + } + return a; + } + } [MethodImplAttribute(MethodImplOptions.InternalCall)] - extern RuntimePropertyInfo[] GetPropertiesByName (string name, BindingFlags bindingAttr, bool icase, Type reflected_type); + extern IntPtr GetPropertiesByName_native (IntPtr name, BindingFlags bindingAttr, bool icase); [MethodImplAttribute(MethodImplOptions.InternalCall)] - extern RuntimeConstructorInfo[] GetConstructors_internal (BindingFlags bindingAttr, Type reflected_type); + extern IntPtr GetConstructors_native (BindingFlags bindingAttr); + + RuntimeConstructorInfo[] GetConstructors_internal (BindingFlags bindingAttr, RuntimeType reflectedType) + { + var refh = new RuntimeTypeHandle (reflectedType); + using (var h = new Mono.SafeGPtrArrayHandle (GetConstructors_native (bindingAttr))) { + var n = h.Length; + var a = new RuntimeConstructorInfo [n]; + for (int i = 0; i < n; i++) { + var mh = new RuntimeMethodHandle (h[i]); + a[i] = (RuntimeConstructorInfo) MethodBase.GetMethodFromHandleNoGenericCheck (mh, refh); + } + return a; + } + } + + RuntimePropertyInfo[] GetPropertiesByName (string name, BindingFlags bindingAttr, bool icase, RuntimeType reflectedType) + { + var refh = new RuntimeTypeHandle (reflectedType); + using (var namePtr = new Mono.SafeStringMarshal (name)) + using (var h = new Mono.SafeGPtrArrayHandle (GetPropertiesByName_native (namePtr.Value, bindingAttr, icase))) { + var n = h.Length; + var a = new RuntimePropertyInfo [n]; + for (int i = 0; i < n; i++) { + var ph = new Mono.RuntimePropertyHandle (h[i]); + a[i] = (RuntimePropertyInfo) PropertyInfo.GetPropertyFromHandle (ph, refh); + } + return a; + } + } public override InterfaceMapping GetInterfaceMap (Type ifaceType) { @@ -618,26 +663,71 @@ namespace System [MethodImplAttribute(MethodImplOptions.InternalCall)] extern Type[] GetGenericArgumentsInternal (bool runtimeArray); - [MethodImplAttribute(MethodImplOptions.InternalCall)] - extern GenericParameterAttributes GetGenericParameterAttributes (); - - [MethodImplAttribute(MethodImplOptions.InternalCall)] - extern Type[] GetGenericParameterConstraints_impl (); + GenericParameterAttributes GetGenericParameterAttributes () { + return (new Mono.RuntimeGenericParamInfoHandle (RuntimeTypeHandle.GetGenericParameterInfo (this))).Attributes; + } [MethodImplAttribute(MethodImplOptions.InternalCall)] extern int GetGenericParameterPosition (); [MethodImplAttribute(MethodImplOptions.InternalCall)] - extern RuntimeEventInfo[] GetEvents_internal (string name, BindingFlags bindingAttr, Type reflected_type); + extern IntPtr GetEvents_native (IntPtr name, BindingFlags bindingAttr); [MethodImplAttribute(MethodImplOptions.InternalCall)] - extern RuntimeFieldInfo[] GetFields_internal (string name, BindingFlags bindingAttr, Type reflected_type); + extern IntPtr GetFields_native (IntPtr name, BindingFlags bindingAttr); + + RuntimeFieldInfo[] GetFields_internal (string name, BindingFlags bindingAttr, RuntimeType reflectedType) + { + var refh = new RuntimeTypeHandle (reflectedType); + using (var namePtr = new Mono.SafeStringMarshal (name)) + using (var h = new Mono.SafeGPtrArrayHandle (GetFields_native (namePtr.Value, bindingAttr))) { + int n = h.Length; + var a = new RuntimeFieldInfo[n]; + for (int i = 0; i < n; i++) { + var fh = new RuntimeFieldHandle (h[i]); + a[i] = (RuntimeFieldInfo) FieldInfo.GetFieldFromHandle (fh, refh); + } + return a; + } + } + + RuntimeEventInfo[] GetEvents_internal (string name, BindingFlags bindingAttr, RuntimeType reflectedType) + { + var refh = new RuntimeTypeHandle (reflectedType); + using (var namePtr = new Mono.SafeStringMarshal (name)) + using (var h = new Mono.SafeGPtrArrayHandle (GetEvents_native (namePtr.Value, bindingAttr))) { + int n = h.Length; + var a = new RuntimeEventInfo[n]; + for (int i = 0; i < n; i++) { + var eh = new Mono.RuntimeEventHandle (h[i]); + a[i] = (RuntimeEventInfo) EventInfo.GetEventFromHandle (eh, refh); + } + return a; + } + } [MethodImplAttribute(MethodImplOptions.InternalCall)] public extern override Type[] GetInterfaces(); [MethodImplAttribute(MethodImplOptions.InternalCall)] - extern RuntimeType[] GetNestedTypes_internal (string name, BindingFlags bindingAttr); + extern IntPtr GetNestedTypes_native (IntPtr name, BindingFlags bindingAttr); + + RuntimeType[] GetNestedTypes_internal (string displayName, BindingFlags bindingAttr) + { + string internalName = null; + if (displayName != null) + internalName = TypeIdentifiers.FromDisplay (displayName).InternalName; + using (var namePtr = new Mono.SafeStringMarshal (internalName)) + using (var h = new Mono.SafeGPtrArrayHandle (GetNestedTypes_native (namePtr.Value, bindingAttr))) { + int n = h.Length; + var a = new RuntimeType [n]; + for (int i = 0; i < n; i++) { + var th = new RuntimeTypeHandle (h[i]); + a[i] = (RuntimeType) Type.GetTypeFromHandle (th); + } + return a; + } + } public override string AssemblyQualifiedName { get { diff --git a/mcs/class/corlib/ReferenceSources/SharedStatics.cs b/mcs/class/corlib/ReferenceSources/SharedStatics.cs deleted file mode 100644 index 01252ccc2f..0000000000 --- a/mcs/class/corlib/ReferenceSources/SharedStatics.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System.Threading; -using StringMaker = System.Security.Util.Tokenizer.StringMaker; - -namespace System -{ - static class SharedStatics - { - static StringMaker shared; - static public StringMaker GetSharedStringMaker () - { - if (shared == null) - Interlocked.CompareExchange (ref shared, new StringMaker (), null); - - return shared; - } - - static public void ReleaseSharedStringMaker (ref StringMaker maker) - { - - } - } -} \ No newline at end of file diff --git a/mcs/class/Facades/System.Diagnostics.Tracing/EventCounter.cs b/mcs/class/corlib/System.Diagnostics.Tracing/EventCounter.cs similarity index 98% rename from mcs/class/Facades/System.Diagnostics.Tracing/EventCounter.cs rename to mcs/class/corlib/System.Diagnostics.Tracing/EventCounter.cs index 7fedc40688..4cb362578f 100644 --- a/mcs/class/Facades/System.Diagnostics.Tracing/EventCounter.cs +++ b/mcs/class/corlib/System.Diagnostics.Tracing/EventCounter.cs @@ -26,6 +26,8 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // +#if NETSTANDARD + namespace System.Diagnostics.Tracing { public class EventCounter @@ -38,4 +40,6 @@ namespace System.Diagnostics.Tracing { } } -} \ No newline at end of file +} + +#endif diff --git a/mcs/class/corlib/System.Diagnostics.Tracing/EventSource.cs b/mcs/class/corlib/System.Diagnostics.Tracing/EventSource.cs index 312f0ccb16..8397f4c2d2 100644 --- a/mcs/class/corlib/System.Diagnostics.Tracing/EventSource.cs +++ b/mcs/class/corlib/System.Diagnostics.Tracing/EventSource.cs @@ -256,6 +256,7 @@ namespace System.Diagnostics.Tracing WriteEvent (eventId, new object[] { arg1, arg2, arg3 } ); } + [CLSCompliant (false)] protected unsafe void WriteEventCore (int eventId, int eventDataCount, EventData* data) { } @@ -264,6 +265,7 @@ namespace System.Diagnostics.Tracing { } + [CLSCompliant (false)] protected unsafe void WriteEventWithRelatedActivityIdCore (int eventId, Guid* relatedActivityId, int eventDataCount, EventSource.EventData* data) { } diff --git a/mcs/class/corlib/System.Diagnostics/StackFrame.cs b/mcs/class/corlib/System.Diagnostics/StackFrame.cs index 702cd540d9..7de9ccce09 100644 --- a/mcs/class/corlib/System.Diagnostics/StackFrame.cs +++ b/mcs/class/corlib/System.Diagnostics/StackFrame.cs @@ -71,22 +71,25 @@ namespace System.Diagnostics { out nativeOffset, out fileName, out lineNumber, out columnNumber); } - + + [MethodImplAttribute (MethodImplOptions.NoInlining)] public StackFrame (bool fNeedFileInfo) { get_frame_info (2, fNeedFileInfo, out methodBase, out ilOffset, out nativeOffset, out fileName, out lineNumber, out columnNumber); } - - public StackFrame (int skipFrames) + + [MethodImplAttribute (MethodImplOptions.NoInlining)] + public StackFrame (int skipFrames) { get_frame_info (skipFrames + 2, false, out methodBase, out ilOffset, out nativeOffset, out fileName, out lineNumber, out columnNumber); } - public StackFrame (int skipFrames, bool fNeedFileInfo) + [MethodImplAttribute (MethodImplOptions.NoInlining)] + public StackFrame (int skipFrames, bool fNeedFileInfo) { get_frame_info (skipFrames + 2, fNeedFileInfo, out methodBase, out ilOffset, out nativeOffset, out fileName, out lineNumber, @@ -95,7 +98,8 @@ namespace System.Diagnostics { // LAMESPEC: According to the MSDN docs, this creates a frame with _only_ // the filename and lineNumber, but MS fills out the frame info as well. - public StackFrame (string fileName, int lineNumber) + [MethodImplAttribute (MethodImplOptions.NoInlining)] + public StackFrame (string fileName, int lineNumber) { get_frame_info (2, false, out methodBase, out ilOffset, out nativeOffset, out fileName, out lineNumber, @@ -107,7 +111,8 @@ namespace System.Diagnostics { // LAMESPEC: According to the MSDN docs, this creates a frame with _only_ // the filename, lineNumber and colNumber, but MS fills out the frame info as well. - public StackFrame (string fileName, int lineNumber, int colNumber) + [MethodImplAttribute (MethodImplOptions.NoInlining)] + public StackFrame (string fileName, int lineNumber, int colNumber) { get_frame_info (2, false, out methodBase, out ilOffset, out nativeOffset, out fileName, out lineNumber, @@ -129,7 +134,7 @@ namespace System.Diagnostics { public virtual string GetFileName() { -#if !NET_2_1 +#if !MOBILE if (SecurityManager.SecurityEnabled && (fileName != null) && (fileName.Length > 0)) { string fn = Path.GetFullPath (fileName); new FileIOPermission (FileIOPermissionAccess.PathDiscovery, fn).Demand (); diff --git a/mcs/class/corlib/System.Diagnostics/StackTrace.cs b/mcs/class/corlib/System.Diagnostics/StackTrace.cs index c8d8cdf0f8..b93808b89c 100644 --- a/mcs/class/corlib/System.Diagnostics/StackTrace.cs +++ b/mcs/class/corlib/System.Diagnostics/StackTrace.cs @@ -69,21 +69,25 @@ namespace System.Diagnostics { init_frames (METHODS_TO_SKIP, false); } + [MethodImplAttribute (MethodImplOptions.NoInlining)] public StackTrace (bool fNeedFileInfo) { init_frames (METHODS_TO_SKIP, fNeedFileInfo); } + [MethodImplAttribute (MethodImplOptions.NoInlining)] public StackTrace (int skipFrames) { init_frames (skipFrames, false); } + [MethodImplAttribute (MethodImplOptions.NoInlining)] public StackTrace (int skipFrames, bool fNeedFileInfo) { init_frames (skipFrames, fNeedFileInfo); } + [MethodImplAttribute (MethodImplOptions.NoInlining)] void init_frames (int skipFrames, bool fNeedFileInfo) { if (skipFrames < 0) diff --git a/mcs/class/corlib/System.Globalization/CultureInfo.cs b/mcs/class/corlib/System.Globalization/CultureInfo.cs index f2602702c4..63c0c01597 100644 --- a/mcs/class/corlib/System.Globalization/CultureInfo.cs +++ b/mcs/class/corlib/System.Globalization/CultureInfo.cs @@ -116,6 +116,9 @@ namespace System.Globalization const int CalendarTypeBits = 8; const string MSG_READONLY = "This instance is read only"; + + static volatile CultureInfo s_DefaultThreadCurrentUICulture; + static volatile CultureInfo s_DefaultThreadCurrentCulture; public static CultureInfo InvariantCulture { get { @@ -128,7 +131,7 @@ namespace System.Globalization return Thread.CurrentThread.CurrentCulture; } set { - throw new NotImplementedException (); + Thread.CurrentThread.CurrentCulture = value; } } @@ -137,7 +140,7 @@ namespace System.Globalization return Thread.CurrentThread.CurrentUICulture; } set { - throw new NotImplementedException (); + Thread.CurrentThread.CurrentUICulture = value; } } @@ -177,7 +180,6 @@ namespace System.Globalization get { return territory; } } -#if !NET_2_1 // FIXME: It is implemented, but would be hell slow. [ComVisible (false)] public CultureTypes CultureTypes { @@ -263,7 +265,6 @@ namespace System.Globalization } } } -#endif public virtual int LCID { get { @@ -511,7 +512,7 @@ namespace System.Globalization } } - internal void CheckNeutral () + void CheckNeutral () { } @@ -1070,19 +1071,19 @@ namespace System.Globalization public static CultureInfo DefaultThreadCurrentCulture { get { - return Thread.default_culture; + return s_DefaultThreadCurrentCulture; } set { - Thread.default_culture = value; + s_DefaultThreadCurrentCulture = value; } } public static CultureInfo DefaultThreadCurrentUICulture { get { - return Thread.default_ui_culture; + return s_DefaultThreadCurrentUICulture; } set { - Thread.default_ui_culture = value; + s_DefaultThreadCurrentUICulture = value; } } @@ -1092,6 +1093,19 @@ namespace System.Globalization } } + internal static CultureInfo UserDefaultUICulture { + get { + return ConstructCurrentUICulture (); + } + } + + internal static CultureInfo UserDefaultCulture { + get { + return ConstructCurrentCulture (); + } + } + + #region reference sources // TODO: internal static readonly bool IsTaiwanSku; @@ -1144,6 +1158,19 @@ namespace System.Globalization return true; } + internal static bool VerifyCultureName(CultureInfo culture, bool throwException) { + Contract.Assert(culture!=null, "[CultureInfo.VerifyCultureName]culture!=null"); + + //If we have an instance of one of our CultureInfos, the user can't have changed the + //name and we know that all names are valid in files. + if (!culture.m_isInherited) { + return true; + } + + return VerifyCultureName(culture.Name, throwException); + + } + #endregion } } diff --git a/mcs/class/corlib/System.IO/Directory.cs b/mcs/class/corlib/System.IO/Directory.cs index ed773f6ca6..522f305e42 100644 --- a/mcs/class/corlib/System.IO/Directory.cs +++ b/mcs/class/corlib/System.IO/Directory.cs @@ -86,7 +86,7 @@ namespace System.IO static DirectoryInfo CreateDirectoriesInternal (string path) { -#if !NET_2_1 +#if !MOBILE if (SecurityManager.SecurityEnabled) { new FileIOPermission (FileIOPermissionAccess.Read | FileIOPermissionAccess.Write, path).Demand (); } @@ -232,7 +232,7 @@ namespace System.IO SecurityManager.EnsureElevatedPermissions (); // this is a no-op outside moonlight string result = InsecureGetCurrentDirectory(); -#if !NET_2_1 +#if !MOBILE if ((result != null) && (result.Length > 0) && SecurityManager.SecurityEnabled) { new FileIOPermission (FileIOPermissionAccess.PathDiscovery, result).Demand (); } diff --git a/mcs/class/corlib/System.IO/DirectoryInfo.cs b/mcs/class/corlib/System.IO/DirectoryInfo.cs index d25432dcac..205fadc002 100644 --- a/mcs/class/corlib/System.IO/DirectoryInfo.cs +++ b/mcs/class/corlib/System.IO/DirectoryInfo.cs @@ -427,20 +427,20 @@ namespace System.IO { static internal IEnumerable EnumerateFileSystemInfos (string full, string searchPattern, SearchOption searchOption) { string path_with_pattern = Path.Combine (full, searchPattern); - IntPtr handle; + IntPtr handle = IntPtr.Zero; MonoIOError error; FileAttributes rattr; bool subdirs = searchOption == SearchOption.AllDirectories; Path.Validate (full); - string s = MonoIO.FindFirst (full, path_with_pattern, out rattr, out error, out handle); - if (s == null) - yield break; - if (error != 0) - throw MonoIO.GetException (Path.GetDirectoryName (path_with_pattern), (MonoIOError) error); - try { + string s = MonoIO.FindFirst (full, path_with_pattern, out rattr, out error, out handle); + if (s == null) + yield break; + if (error != 0) + throw MonoIO.GetException (Path.GetDirectoryName (path_with_pattern), (MonoIOError) error); + do { if (((rattr & FileAttributes.ReparsePoint) == 0)){ if ((rattr & FileAttributes.Directory) != 0) @@ -455,7 +455,8 @@ namespace System.IO { } while ((s = MonoIO.FindNext (handle, out rattr, out error)) != null); } finally { - MonoIO.FindClose (handle); + if (handle != IntPtr.Zero) + MonoIO.FindClose (handle); } } diff --git a/mcs/class/corlib/System.IO/File.cs b/mcs/class/corlib/System.IO/File.cs index 92389257c5..d3eebc4410 100644 --- a/mcs/class/corlib/System.IO/File.cs +++ b/mcs/class/corlib/System.IO/File.cs @@ -38,10 +38,7 @@ using System.Diagnostics; using System.Security; using System.Text; using System.Runtime.InteropServices; - -#if !NET_2_1 using System.Security.AccessControl; -#endif namespace System.IO { @@ -147,7 +144,6 @@ namespace System.IO FileShare.None, bufferSize, options); } -#if !NET_2_1 [MonoLimitation ("FileOptions and FileSecurity are ignored")] public static FileStream Create (string path, int bufferSize, FileOptions options, @@ -156,7 +152,6 @@ namespace System.IO return new FileStream (path, FileMode.Create, FileAccess.ReadWrite, FileShare.None, bufferSize, options); } -#endif public static StreamWriter CreateText (string path) { @@ -201,7 +196,6 @@ namespace System.IO return MonoIO.ExistsFile (path, out error); } -#if !NET_2_1 public static FileSecurity GetAccessControl (string path) { // AccessControlSections.Audit requires special permissions. @@ -215,7 +209,6 @@ namespace System.IO { return new FileSecurity (path, includeSections); } -#endif public static FileAttributes GetAttributes (string path) { @@ -434,7 +427,6 @@ namespace System.IO } } -#if !NET_2_1 public static void SetAccessControl (string path, FileSecurity fileSecurity) { @@ -443,7 +435,6 @@ namespace System.IO fileSecurity.PersistModifications (path); } -#endif public static void SetAttributes (string path, FileAttributes fileAttributes) diff --git a/mcs/class/corlib/System.IO/FileStream.cs b/mcs/class/corlib/System.IO/FileStream.cs index 0e20810547..db13468d36 100644 --- a/mcs/class/corlib/System.IO/FileStream.cs +++ b/mcs/class/corlib/System.IO/FileStream.cs @@ -37,17 +37,11 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Remoting.Messaging; using System.Security; +using System.Security.AccessControl; using System.Security.Permissions; using System.Threading; -using Microsoft.Win32.SafeHandles; - -#if NET_2_1 -using System.IO.IsolatedStorage; -#else -using System.Security.AccessControl; -#endif - using System.Threading.Tasks; +using Microsoft.Win32.SafeHandles; namespace System.IO { @@ -129,7 +123,6 @@ namespace System.IO Init (handle, access, false, bufferSize, isAsync, false); } -#if !MOBILE [MonoLimitation ("This ignores the rights parameter")] public FileStream (string path, FileMode mode, FileSystemRights rights, FileShare share, @@ -146,7 +139,6 @@ namespace System.IO : this (path, mode, (mode == FileMode.Append ? FileAccess.Write : FileAccess.ReadWrite), share, bufferSize, false, options) { } -#endif internal FileStream (string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options, string msgPath, bool bFromProxy, bool useLongPath = false, bool checkHost = false) : this (path, mode, access, share, bufferSize, false, options) @@ -176,7 +168,7 @@ namespace System.IO throw new ArgumentOutOfRangeException ("bufferSize", "Positive number required."); if (mode < FileMode.CreateNew || mode > FileMode.Append) { -#if NET_2_1 +#if MOBILE if (anonymous) throw new ArgumentException ("mode", "Enum value was out of legal range."); else @@ -942,7 +934,6 @@ namespace System.IO throw exc; } -#if !NET_2_1 public FileSecurity GetAccessControl () { if (safeHandle.IsClosed) @@ -964,7 +955,6 @@ namespace System.IO fileSecurity.PersistModifications (SafeFileHandle); } -#endif public override Task FlushAsync (CancellationToken cancellationToken) { diff --git a/mcs/class/corlib/System.IO/MonoIO.cs b/mcs/class/corlib/System.IO/MonoIO.cs index 994358c86b..35a81c5e44 100644 --- a/mcs/class/corlib/System.IO/MonoIO.cs +++ b/mcs/class/corlib/System.IO/MonoIO.cs @@ -36,7 +36,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Threading; using Microsoft.Win32.SafeHandles; -#if NET_2_1 +#if MOBILE using System.IO.IsolatedStorage; #endif @@ -108,7 +108,7 @@ namespace System.IO return new IOException (message, unchecked((int)0x80070000) | (int)error); case MonoIOError.ERROR_INVALID_DRIVE: message = String.Format ("Could not find the drive '{0}'. The drive might not be ready or might not be mapped.", path); -#if !NET_2_1 +#if !MOBILE return new DriveNotFoundException (message); #else return new IOException (message, unchecked((int)0x80070000) | (int)error); @@ -155,6 +155,10 @@ namespace System.IO case MonoIOError.ERROR_NOT_SAME_DEVICE: message = "Source and destination are not on the same device"; return new IOException (message, unchecked((int)0x80070000) | (int)error); + + case MonoIOError.ERROR_DIRECTORY: + message = "The directory name is invalid"; + return new IOException (message, unchecked((int)0x80070000) | (int)error); default: message = String.Format ("Win32 IO returned {0}. Path: {1}", error, path); diff --git a/mcs/class/corlib/System.IO/MonoIOError.cs b/mcs/class/corlib/System.IO/MonoIOError.cs index 63756d1901..2a78687ef3 100644 --- a/mcs/class/corlib/System.IO/MonoIOError.cs +++ b/mcs/class/corlib/System.IO/MonoIOError.cs @@ -217,8 +217,8 @@ namespace System.IO WAIT_TIMEOUT = 258, ERROR_NO_MORE_ITEMS = 259, ERROR_CANNOT_COPY = 266, - ERROR_DIRECTORY = 267, - ERROR_EAS_DIDNT_FIT = 275, + */ ERROR_DIRECTORY = 267, + /* ERROR_EAS_DIDNT_FIT = 275, ERROR_EA_FILE_CORRUPT = 276, ERROR_EA_TABLE_FULL = 277, ERROR_INVALID_EA_HANDLE = 278, diff --git a/mcs/class/corlib/System.IO/Path.cs b/mcs/class/corlib/System.IO/Path.cs index fc62a4db6e..138163779f 100644 --- a/mcs/class/corlib/System.IO/Path.cs +++ b/mcs/class/corlib/System.IO/Path.cs @@ -140,6 +140,7 @@ namespace System.IO { { int l = s.Length; int sub = 0; + int alt = 0; int start = 0; // Host prefix? @@ -158,6 +159,8 @@ namespace System.IO { if (c != DirectorySeparatorChar && c != AltDirectorySeparatorChar) continue; + if (DirectorySeparatorChar != AltDirectorySeparatorChar && c == AltDirectorySeparatorChar) + alt++; if (i+1 == l) sub++; else { @@ -167,7 +170,7 @@ namespace System.IO { } } - if (sub == 0) + if (sub == 0 && alt == 0) return s; char [] copy = new char [l-sub]; @@ -281,7 +284,7 @@ namespace System.IO { SecurityManager.EnsureElevatedPermissions (); // this is a no-op outside moonlight -#if !NET_2_1 +#if !MOBILE if (SecurityManager.SecurityEnabled) { new FileIOPermission (FileIOPermissionAccess.PathDiscovery, fullpath).Demand (); } @@ -320,9 +323,12 @@ namespace System.IO { internal static string WindowsDriveAdjustment (string path) { - // two special cases to consider when a drive is specified - if (path.Length < 2) + // three special cases to consider when a drive is specified + if (path.Length < 2) { + if (path.Length == 1 && (path[0] == '\\' || path[0] == '/')) + return Path.GetPathRoot(Directory.GetCurrentDirectory()); return path; + } if ((path [1] != ':') || !Char.IsLetter (path [0])) return path; @@ -882,5 +888,7 @@ namespace System.IO { return DirectorySeparatorStr; } } + + internal const int MAX_PATH = 260; // From WinDef.h } } diff --git a/mcs/class/corlib/System.Reflection.Emit/AssemblyBuilder.cs b/mcs/class/corlib/System.Reflection.Emit/AssemblyBuilder.cs index 6acc3c4ec7..9c257cb9a8 100644 --- a/mcs/class/corlib/System.Reflection.Emit/AssemblyBuilder.cs +++ b/mcs/class/corlib/System.Reflection.Emit/AssemblyBuilder.cs @@ -384,7 +384,7 @@ namespace System.Reflection.Emit internal void AddPermissionRequests (PermissionSet required, PermissionSet optional, PermissionSet refused) { -#if !NET_2_1 +#if !MOBILE if (created) throw new InvalidOperationException ("Assembly was already saved."); @@ -466,6 +466,11 @@ namespace System.Reflection.Emit return new AssemblyBuilder (name, null, access, false); } + public static AssemblyBuilder DefineDynamicAssembly (AssemblyName name, AssemblyBuilderAccess access, IEnumerable assemblyAttributes) + { + throw new NotImplementedException (); + } + public ModuleBuilder DefineDynamicModule (string name) { return DefineDynamicModule (name, name, false, true); @@ -1038,16 +1043,6 @@ namespace System.Reflection.Emit return (str == "neutral" ? String.Empty : str); } - internal override AssemblyName UnprotectedGetName () - { - AssemblyName an = base.UnprotectedGetName (); - if (sn != null) { - an.SetPublicKey (sn.PublicKey); - an.SetPublicKeyToken (sn.PublicKeyToken); - } - return an; - } - /*Warning, @typeArguments must be a mscorlib internal array. So make a copy before passing it in*/ internal Type MakeGenericType (Type gtd, Type[] typeArguments) { @@ -1124,7 +1119,14 @@ namespace System.Reflection.Emit public override AssemblyName GetName (bool copiedName) { - return base.GetName (copiedName); + var aname = AssemblyName.Create (this, false); + + if (sn != null) { + aname.SetPublicKey (sn.PublicKey); + aname.SetPublicKeyToken (sn.PublicKeyToken); + } + return aname; + } [MonoTODO ("This always returns an empty array")] diff --git a/mcs/class/corlib/System.Reflection.Emit/AssemblyBuilder.pns.cs b/mcs/class/corlib/System.Reflection.Emit/AssemblyBuilder.pns.cs new file mode 100644 index 0000000000..e10784c39f --- /dev/null +++ b/mcs/class/corlib/System.Reflection.Emit/AssemblyBuilder.pns.cs @@ -0,0 +1,69 @@ +// +// AssemblyBuilder.pns.cs +// +// Authors: +// Marek Safar (marek.safar@gmail.com) +// +// Copyright (C) 2016 Xamarin Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +#if FULL_AOT_RUNTIME + +namespace System.Reflection.Emit +{ + public class AssemblyBuilder : Assembly + { + public static AssemblyBuilder DefineDynamicAssembly (AssemblyName name, AssemblyBuilderAccess access) + { + throw new PlatformNotSupportedException (); + } + + public static AssemblyBuilder DefineDynamicAssembly (AssemblyName name, AssemblyBuilderAccess access, System.Collections.Generic.IEnumerable assemblyAttributes) + { + throw new PlatformNotSupportedException (); + } + + public ModuleBuilder DefineDynamicModule (string name) + { + throw new PlatformNotSupportedException (); + } + + public ModuleBuilder GetDynamicModule (string name) + { + throw new PlatformNotSupportedException (); + } + + public void SetCustomAttribute (CustomAttributeBuilder customBuilder) + { + throw new PlatformNotSupportedException (); + } + + + public void SetCustomAttribute (ConstructorInfo con, byte[] binaryAttribute) + { + throw new PlatformNotSupportedException (); + } + + } +} + +#endif \ No newline at end of file diff --git a/mcs/class/corlib/System.Reflection.Emit/AssemblyBuilderAccess.cs b/mcs/class/corlib/System.Reflection.Emit/AssemblyBuilderAccess.cs index 3d1bdf1528..d9d588bdac 100644 --- a/mcs/class/corlib/System.Reflection.Emit/AssemblyBuilderAccess.cs +++ b/mcs/class/corlib/System.Reflection.Emit/AssemblyBuilderAccess.cs @@ -28,7 +28,6 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -#if !FULL_AOT_RUNTIME || IOS_REFLECTION using System.Runtime.InteropServices; namespace System.Reflection.Emit @@ -44,4 +43,3 @@ namespace System.Reflection.Emit RunAndCollect = 9 } } -#endif diff --git a/mcs/class/corlib/System.Reflection.Emit/ConstructorBuilder.cs b/mcs/class/corlib/System.Reflection.Emit/ConstructorBuilder.cs index d74a09a1ce..793e36fd2a 100644 --- a/mcs/class/corlib/System.Reflection.Emit/ConstructorBuilder.cs +++ b/mcs/class/corlib/System.Reflection.Emit/ConstructorBuilder.cs @@ -201,7 +201,7 @@ namespace System.Reflection.Emit { public void AddDeclarativeSecurity (SecurityAction action, PermissionSet pset) { -#if !NET_2_1 +#if !MOBILE if (pset == null) throw new ArgumentNullException ("pset"); if ((action == SecurityAction.RequestMinimum) || @@ -360,6 +360,18 @@ namespace System.Reflection.Emit { if (ilgen != null) ilgen.label_fixup (this); } + + internal void ResolveUserTypes () { + TypeBuilder.ResolveUserTypes (parameters); + if (paramModReq != null) { + foreach (var types in paramModReq) + TypeBuilder.ResolveUserTypes (types); + } + if (paramModOpt != null) { + foreach (var types in paramModOpt) + TypeBuilder.ResolveUserTypes (types); + } + } internal void GenerateDebugInfo (ISymbolWriter symbolWriter) { diff --git a/mcs/class/corlib/System.Reflection.Emit/ConstructorBuilder.pns.cs b/mcs/class/corlib/System.Reflection.Emit/ConstructorBuilder.pns.cs new file mode 100644 index 0000000000..2432a643d6 --- /dev/null +++ b/mcs/class/corlib/System.Reflection.Emit/ConstructorBuilder.pns.cs @@ -0,0 +1,92 @@ +// +// ConstructorBuilder.pns.cs +// +// Authors: +// Marek Safar (marek.safar@gmail.com) +// +// Copyright (C) 2016 Xamarin Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +#if FULL_AOT_RUNTIME + +namespace System.Reflection.Emit +{ + public abstract class ConstructorBuilder : ConstructorInfo + { + public bool InitLocals { get; set; } + + public override MethodAttributes Attributes { + get { + throw new PlatformNotSupportedException (); + } + } + + public override Type DeclaringType { + get { + throw new PlatformNotSupportedException (); + } + } + + public override string Name { + get { + throw new PlatformNotSupportedException (); + } + } + + public ParameterBuilder DefineParameter (int iSequence, ParameterAttributes attributes, string strParamName) + { + throw new PlatformNotSupportedException (); + } + + public ILGenerator GetILGenerator () + { + throw new PlatformNotSupportedException (); + } + + public ILGenerator GetILGenerator (int streamSize) + { + throw new PlatformNotSupportedException (); + } + + public override ParameterInfo[] GetParameters () + { + throw new PlatformNotSupportedException (); + } + + public void SetCustomAttribute (CustomAttributeBuilder customBuilder) + { + throw new PlatformNotSupportedException (); + } + + public void SetCustomAttribute (ConstructorInfo con, byte[] binaryAttribute) + { + throw new PlatformNotSupportedException (); + } + + public void SetImplementationFlags (MethodImplAttributes attributes) + { + throw new PlatformNotSupportedException (); + } + } +} + +#endif \ No newline at end of file diff --git a/mcs/class/corlib/System.Reflection/TargetParameterCountException.cs b/mcs/class/corlib/System.Reflection.Emit/CustomAttributeBuilder.pns.cs similarity index 53% rename from mcs/class/corlib/System.Reflection/TargetParameterCountException.cs rename to mcs/class/corlib/System.Reflection.Emit/CustomAttributeBuilder.pns.cs index deb5344e15..fe74950935 100644 --- a/mcs/class/corlib/System.Reflection/TargetParameterCountException.cs +++ b/mcs/class/corlib/System.Reflection.Emit/CustomAttributeBuilder.pns.cs @@ -1,13 +1,10 @@ // -// System.Reflection.TargetParameterCountException.cs +// CustomAttributeBuilder.pns.cs // -// Author: Duncan Mak (duncan@ximian.com) +// Authors: +// Marek Safar (marek.safar@gmail.com) // -// (C) Ximian, Inc. http://www.ximian.com -// - -// -// Copyright (C) 2004 Novell, Inc (http://www.novell.com) +// Copyright (C) 2016 Xamarin Inc (http://www.xamarin.com) // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the @@ -29,38 +26,32 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -using System.Runtime.Serialization; -using System.Globalization; -using System.Runtime.InteropServices; +#if FULL_AOT_RUNTIME -namespace System.Reflection +namespace System.Reflection.Emit { - [ComVisible (true)] - [Serializable] -#if NET_2_1 - public sealed class TargetParameterCountException : Exception { -#else - public sealed class TargetParameterCountException : ApplicationException { -#endif - public TargetParameterCountException () - : base (Locale.GetText ("Number of parameter does not match expected count.")) + public class CustomAttributeBuilder + { + public CustomAttributeBuilder (ConstructorInfo con, object[] constructorArgs) { + throw new PlatformNotSupportedException (); } - public TargetParameterCountException (string message) - : base (message) + public CustomAttributeBuilder (ConstructorInfo con, object[] constructorArgs, FieldInfo[] namedFields, object[] fieldValues) { + throw new PlatformNotSupportedException (); } - public TargetParameterCountException (string message, Exception inner) - : base (message, inner) + public CustomAttributeBuilder (ConstructorInfo con, object[] constructorArgs, PropertyInfo[] namedProperties, object[] propertyValues) { + throw new PlatformNotSupportedException (); } - internal TargetParameterCountException (SerializationInfo info, - StreamingContext context) - : base (info, context) + public CustomAttributeBuilder (ConstructorInfo con, object[] constructorArgs, PropertyInfo[] namedProperties, object[] propertyValues, FieldInfo[] namedFields, object[] fieldValues) { + throw new PlatformNotSupportedException (); } } } + +#endif \ No newline at end of file diff --git a/mcs/class/corlib/System.Reflection.Emit/EnumBuilder.cs b/mcs/class/corlib/System.Reflection.Emit/EnumBuilder.cs index b5baac27ea..cba66c1184 100644 --- a/mcs/class/corlib/System.Reflection.Emit/EnumBuilder.cs +++ b/mcs/class/corlib/System.Reflection.Emit/EnumBuilder.cs @@ -162,6 +162,11 @@ namespace System.Reflection.Emit { return res; } + public TypeInfo CreateTypeInfo() + { + return _tb.CreateTypeInfo (); + } + public override Type GetEnumUnderlyingType () { return _underlyingType; diff --git a/mcs/class/corlib/System.Reflection.Emit/EnumBuilder.pns.cs b/mcs/class/corlib/System.Reflection.Emit/EnumBuilder.pns.cs new file mode 100644 index 0000000000..e518bc4ab6 --- /dev/null +++ b/mcs/class/corlib/System.Reflection.Emit/EnumBuilder.pns.cs @@ -0,0 +1,117 @@ +// +// EnumBuilder.pns.cs +// +// Authors: +// Marek Safar (marek.safar@gmail.com) +// +// Copyright (C) 2016 Xamarin Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +#if FULL_AOT_RUNTIME + +namespace System.Reflection.Emit +{ + public abstract class EnumBuilder : TypeInfo + { + public FieldBuilder UnderlyingField { + get { + throw new PlatformNotSupportedException (); + } + } + + public override Assembly Assembly { + get { + throw new PlatformNotSupportedException (); + } + } + + public override string AssemblyQualifiedName { + get { + throw new PlatformNotSupportedException (); + } + } + + public override Type BaseType { + get { + throw new PlatformNotSupportedException (); + } + } + + public override string FullName { + get { + throw new PlatformNotSupportedException (); + } + } + + public override Guid GUID { + get { + throw new PlatformNotSupportedException (); + } + } + + public override Module Module { + get { + throw new PlatformNotSupportedException (); + } + } + + public override string Name { + get { + throw new PlatformNotSupportedException (); + } + } + + public override string Namespace { + get { + throw new PlatformNotSupportedException (); + } + } + + public TypeInfo CreateTypeInfo () + { + throw new PlatformNotSupportedException (); + } + + public FieldBuilder DefineLiteral (string literalName, object literalValue) + { + throw new PlatformNotSupportedException (); + } + + public override System.Type GetElementType () + { + throw new PlatformNotSupportedException (); + } + + public void SetCustomAttribute (CustomAttributeBuilder customBuilder) + { + throw new PlatformNotSupportedException (); + } + + public void SetCustomAttribute (ConstructorInfo con, byte[] binaryAttribute) + { + throw new PlatformNotSupportedException (); + } + + } +} + +#endif \ No newline at end of file diff --git a/mcs/class/corlib/System.Reflection/TargetException.cs b/mcs/class/corlib/System.Reflection.Emit/EventBuilder.pns.cs similarity index 55% rename from mcs/class/corlib/System.Reflection/TargetException.cs rename to mcs/class/corlib/System.Reflection.Emit/EventBuilder.pns.cs index bd5e9010c2..159585c6b8 100644 --- a/mcs/class/corlib/System.Reflection/TargetException.cs +++ b/mcs/class/corlib/System.Reflection.Emit/EventBuilder.pns.cs @@ -1,13 +1,10 @@ // -// System.Reflection.TargetException.cs +// EventBuilder.pns.cs // -// Author: Duncan Mak (duncan@ximian.com) +// Authors: +// Marek Safar (marek.safar@gmail.com) // -// (C) Ximian, Inc. http://www.ximian.com -// - -// -// Copyright (C) 2004 Novell, Inc (http://www.novell.com) +// Copyright (C) 2016 Xamarin Inc (http://www.xamarin.com) // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the @@ -29,37 +26,42 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -using System.Globalization; -using System.Runtime.Serialization; -using System.Runtime.InteropServices; +#if FULL_AOT_RUNTIME -namespace System.Reflection +namespace System.Reflection.Emit { - [ComVisible (true)] - [Serializable] -#if NET_2_1 - public class TargetException : Exception { -#else - public class TargetException : ApplicationException { -#endif - public TargetException () - : base (Locale.GetText ("Unable to invoke an invalid target.")) + public class EventBuilder + { + public void AddOtherMethod (MethodBuilder mdBuilder) { + throw new PlatformNotSupportedException (); } - public TargetException (string message) - : base (message) + public void SetAddOnMethod (MethodBuilder mdBuilder) { + throw new PlatformNotSupportedException (); } - public TargetException (string message, Exception inner) - : base (message, inner) + public void SetCustomAttribute (CustomAttributeBuilder customBuilder) { + throw new PlatformNotSupportedException (); } - protected TargetException (SerializationInfo info, StreamingContext context) - : base (info, context) + public void SetCustomAttribute (ConstructorInfo con, byte[] binaryAttribute) { + throw new PlatformNotSupportedException (); + } + + public void SetRaiseMethod (MethodBuilder mdBuilder) + { + throw new PlatformNotSupportedException (); + } + + public void SetRemoveOnMethod (MethodBuilder mdBuilder) + { + throw new PlatformNotSupportedException (); } } } + +#endif \ No newline at end of file diff --git a/mcs/class/corlib/System.Reflection.Emit/FieldBuilder.cs b/mcs/class/corlib/System.Reflection.Emit/FieldBuilder.cs index 053d8c831e..f2fff7d7aa 100644 --- a/mcs/class/corlib/System.Reflection.Emit/FieldBuilder.cs +++ b/mcs/class/corlib/System.Reflection.Emit/FieldBuilder.cs @@ -220,6 +220,14 @@ namespace System.Reflection.Emit { throw new InvalidOperationException ("Unable to change after type has been created."); } + internal void ResolveUserTypes () { + type = TypeBuilder.ResolveUserType (type); + TypeBuilder.ResolveUserTypes (modReq); + TypeBuilder.ResolveUserTypes (modOpt); + if (marshal_info != null) + marshal_info.marshaltyperef = TypeBuilder.ResolveUserType (marshal_info.marshaltyperef); + } + public override Module Module { get { return base.Module; diff --git a/mcs/class/System/System.Diagnostics/ProcessModuleCollection.cs b/mcs/class/corlib/System.Reflection.Emit/FieldBuilder.pns.cs similarity index 50% rename from mcs/class/System/System.Diagnostics/ProcessModuleCollection.cs rename to mcs/class/corlib/System.Reflection.Emit/FieldBuilder.pns.cs index bd1ea619ba..c25a5e34ed 100644 --- a/mcs/class/System/System.Diagnostics/ProcessModuleCollection.cs +++ b/mcs/class/corlib/System.Reflection.Emit/FieldBuilder.pns.cs @@ -1,13 +1,10 @@ // -// System.Diagnostics.ProcessModuleCollection.cs +// FieldBuilder.pns.cs // // Authors: -// Dick Porter (dick@ximian.com) -// Andreas Nahr (ClassDevelopment@A-SoftTech.com) +// Marek Safar (marek.safar@gmail.com) // -// (C) 2002 Ximian, Inc. http://www.ximian.com -// - +// Copyright (C) 2016 Xamarin Inc (http://www.xamarin.com) // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the @@ -29,59 +26,61 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -using System.Collections; +#if FULL_AOT_RUNTIME -namespace System.Diagnostics +namespace System.Reflection.Emit { -#if NET_2_1 - public class ProcessModuleCollectionBase : System.Collections.Generic.List + public abstract class FieldBuilder : FieldInfo { - protected ProcessModuleCollectionBase InnerList { - get { return this; } - } - - public System.Collections.IEnumerator GetEnumerator () - { - return ((System.Collections.IEnumerable)InnerList).GetEnumerator (); - } - } -#endif - - public class ProcessModuleCollection : -#if !NET_2_1 - ReadOnlyCollectionBase -#else - ProcessModuleCollectionBase -#endif - { - protected ProcessModuleCollection() - { - } - - public ProcessModuleCollection(ProcessModule[] processModules) - { - InnerList.AddRange (processModules); - } - - public ProcessModule this[int index] { + public override FieldAttributes Attributes { get { - return (ProcessModule)InnerList[index]; + throw new PlatformNotSupportedException (); } } - public bool Contains(ProcessModule module) - { - return InnerList.Contains (module); + public override Type DeclaringType { + get { + throw new PlatformNotSupportedException (); + } } - public void CopyTo(ProcessModule[] array, int index) - { - InnerList.CopyTo (array, index); + public override Type FieldType { + get { + throw new PlatformNotSupportedException (); + } } - public int IndexOf(ProcessModule module) - { - return InnerList.IndexOf (module); + public override string Name { + get { + throw new PlatformNotSupportedException (); + } } + + public override object GetValue (object obj) + { + throw new PlatformNotSupportedException (); + } + + public void SetConstant (object defaultValue) + { + throw new PlatformNotSupportedException (); + } + + public void SetCustomAttribute (CustomAttributeBuilder customBuilder) + { + throw new PlatformNotSupportedException (); + } + + public void SetCustomAttribute (ConstructorInfo con, byte[] binaryAttribute) + { + throw new PlatformNotSupportedException (); + } + + public void SetOffset (int iOffset) + { + throw new PlatformNotSupportedException (); + } } } + +#endif \ No newline at end of file diff --git a/mcs/class/corlib/System.Reflection.Emit/GenericTypeParameterBuilder.pns.cs b/mcs/class/corlib/System.Reflection.Emit/GenericTypeParameterBuilder.pns.cs new file mode 100644 index 0000000000..7729596740 --- /dev/null +++ b/mcs/class/corlib/System.Reflection.Emit/GenericTypeParameterBuilder.pns.cs @@ -0,0 +1,115 @@ +// +// GenericTypeParameterBuilder.pns.cs +// +// Authors: +// Marek Safar (marek.safar@gmail.com) +// +// Copyright (C) 2016 Xamarin Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +#if FULL_AOT_RUNTIME + +namespace System.Reflection.Emit +{ + public abstract class GenericTypeParameterBuilder : TypeInfo + { + public override Assembly Assembly { + get { + throw new PlatformNotSupportedException (); + } + } + + public override string AssemblyQualifiedName { + get { + throw new PlatformNotSupportedException (); + } + } + + public override Type BaseType { + get { + throw new PlatformNotSupportedException (); + } + } + + public override string FullName { + get { + throw new PlatformNotSupportedException (); + } + } + + public override Guid GUID { + get { + throw new PlatformNotSupportedException (); + } + } + + public override Module Module { + get { + throw new PlatformNotSupportedException (); + } + } + + public override string Name { + get { + throw new PlatformNotSupportedException (); + } + } + + public override string Namespace { + get { + throw new PlatformNotSupportedException (); + } + } + + public override Type GetElementType () + { + throw new PlatformNotSupportedException (); + } + + public void SetBaseTypeConstraint (Type baseTypeConstraint) + { + throw new PlatformNotSupportedException (); + } + + public void SetCustomAttribute (CustomAttributeBuilder customBuilder) + { + throw new PlatformNotSupportedException (); + } + + public void SetCustomAttribute (ConstructorInfo con, byte[] binaryAttribute) + { + throw new PlatformNotSupportedException (); + } + + public void SetGenericParameterAttributes (GenericParameterAttributes genericParameterAttributes) + { + throw new PlatformNotSupportedException (); + } + + public void SetInterfaceConstraints (Type[] interfaceConstraints) + { + throw new PlatformNotSupportedException (); + } + } +} + +#endif \ No newline at end of file diff --git a/mcs/class/corlib/System.Reflection.Emit/ILGenerator.pns.cs b/mcs/class/corlib/System.Reflection.Emit/ILGenerator.pns.cs new file mode 100644 index 0000000000..3be336f320 --- /dev/null +++ b/mcs/class/corlib/System.Reflection.Emit/ILGenerator.pns.cs @@ -0,0 +1,229 @@ +// +// ILGenerator.pns.cs +// +// Authors: +// Marek Safar (marek.safar@gmail.com) +// +// Copyright (C) 2016 Xamarin Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +#if FULL_AOT_RUNTIME + +namespace System.Reflection.Emit +{ + public class ILGenerator + { + ILGenerator () + { + } + + public int ILOffset { + get { + throw new PlatformNotSupportedException (); + } + } + + public virtual void BeginCatchBlock (Type exceptionType) + { + throw new PlatformNotSupportedException (); + } + + public virtual void BeginExceptFilterBlock () + { + throw new PlatformNotSupportedException (); + } + + public virtual Label BeginExceptionBlock () + { + throw new PlatformNotSupportedException (); + } + + public virtual void BeginFaultBlock () + { + throw new PlatformNotSupportedException (); + } + + public virtual void BeginFinallyBlock () + { + throw new PlatformNotSupportedException (); + } + + public virtual void BeginScope () + { + throw new PlatformNotSupportedException (); + } + + public virtual LocalBuilder DeclareLocal (Type localType) + { + throw new PlatformNotSupportedException (); + } + + public virtual LocalBuilder DeclareLocal (Type localType, bool pinned) + { + throw new PlatformNotSupportedException (); + } + + public virtual Label DefineLabel () + { + throw new PlatformNotSupportedException (); + } + + public virtual void Emit (OpCode opcode) + { + throw new PlatformNotSupportedException (); + } + + public virtual void Emit (OpCode opcode, byte arg) + { + throw new PlatformNotSupportedException (); + } + + public virtual void Emit (OpCode opcode, double arg) + { + throw new PlatformNotSupportedException (); + } + + public virtual void Emit (OpCode opcode, short arg) + { + throw new PlatformNotSupportedException (); + } + + public virtual void Emit (OpCode opcode, int arg) + { + throw new PlatformNotSupportedException (); + } + + public virtual void Emit (OpCode opcode, long arg) + { + throw new PlatformNotSupportedException (); + } + + public virtual void Emit (OpCode opcode, ConstructorInfo con) + { + throw new PlatformNotSupportedException (); + } + + public virtual void Emit (OpCode opcode, Label label) + { + throw new PlatformNotSupportedException (); + } + + public virtual void Emit (OpCode opcode, Label[] labels) + { + throw new PlatformNotSupportedException (); + } + + public virtual void Emit (OpCode opcode, LocalBuilder local) + { + throw new PlatformNotSupportedException (); + } + + public virtual void Emit (OpCode opcode, SignatureHelper signature) + { + throw new PlatformNotSupportedException (); + } + + public virtual void Emit (OpCode opcode, FieldInfo field) + { + throw new PlatformNotSupportedException (); + } + + public virtual void Emit (OpCode opcode, MethodInfo meth) + { + throw new PlatformNotSupportedException (); + } + + [CLSCompliant (false)] + public void Emit (OpCode opcode, sbyte arg) + { + throw new PlatformNotSupportedException (); + } + + public virtual void Emit (OpCode opcode, float arg) + { + throw new PlatformNotSupportedException (); + } + + public virtual void Emit (OpCode opcode, string str) + { + throw new PlatformNotSupportedException (); + } + + public virtual void Emit (OpCode opcode, Type cls) + { + throw new PlatformNotSupportedException (); + } + + public virtual void EmitCall (OpCode opcode, MethodInfo methodInfo, Type[] optionalParameterTypes) + { + throw new PlatformNotSupportedException (); + } + + public virtual void EmitCalli (OpCode opcode, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, Type[] optionalParameterTypes) + { + throw new PlatformNotSupportedException (); + } + + public virtual void EmitWriteLine (LocalBuilder localBuilder) + { + throw new PlatformNotSupportedException (); + } + + public virtual void EmitWriteLine (FieldInfo fld) + { + throw new PlatformNotSupportedException (); + } + + public virtual void EmitWriteLine (string value) + { + throw new PlatformNotSupportedException (); + } + + public virtual void EndExceptionBlock () + { + throw new PlatformNotSupportedException (); + } + + public virtual void EndScope () + { + throw new PlatformNotSupportedException (); + } + + public virtual void MarkLabel (Label loc) + { + throw new PlatformNotSupportedException (); + } + + public virtual void ThrowException (Type excType) + { + throw new PlatformNotSupportedException (); + } + + public virtual void UsingNamespace (string usingNamespace) + { + throw new PlatformNotSupportedException (); + } + + } +} + +#endif \ No newline at end of file diff --git a/mcs/class/corlib/System.Reflection.Emit/Label.cs b/mcs/class/corlib/System.Reflection.Emit/Label.cs index 427b93d98d..4834aa2cf2 100644 --- a/mcs/class/corlib/System.Reflection.Emit/Label.cs +++ b/mcs/class/corlib/System.Reflection.Emit/Label.cs @@ -30,7 +30,6 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -#if !FULL_AOT_RUNTIME || IOS_REFLECTION using System.Runtime.InteropServices; namespace System.Reflection.Emit { @@ -73,4 +72,3 @@ namespace System.Reflection.Emit { } } } -#endif diff --git a/mcs/class/corlib/System.Reflection.Emit/LocalBuilder.cs b/mcs/class/corlib/System.Reflection.Emit/LocalBuilder.cs index 98c9addf50..0c56edfb36 100644 --- a/mcs/class/corlib/System.Reflection.Emit/LocalBuilder.cs +++ b/mcs/class/corlib/System.Reflection.Emit/LocalBuilder.cs @@ -33,10 +33,8 @@ // (C) 2001, 2002 Ximian, Inc. http://www.ximian.com // -#if !FULL_AOT_RUNTIME using System; using System.Reflection; -using System.Reflection.Emit; using System.Globalization; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -44,10 +42,16 @@ using System.Diagnostics.SymbolStore; namespace System.Reflection.Emit { [ComVisible (true)] +#if !FULL_AOT_RUNTIME [ComDefaultInterface (typeof (_LocalBuilder))] +#endif [ClassInterface (ClassInterfaceType.None)] [StructLayout (LayoutKind.Sequential)] - public sealed class LocalBuilder : LocalVariableInfo, _LocalBuilder { + public sealed class LocalBuilder : LocalVariableInfo +#if !FULL_AOT_RUNTIME + , _LocalBuilder +#endif + { // Some fields are already defined in LocalVariableInfo #region Sync with reflection.h @@ -108,7 +112,7 @@ namespace System.Reflection.Emit { internal int EndOffset { get { return endOffset; } } - +#if !FULL_AOT_RUNTIME void _LocalBuilder.GetIDsOfNames ([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId) { throw new NotImplementedException (); @@ -128,6 +132,6 @@ namespace System.Reflection.Emit { { throw new NotImplementedException (); } +#endif } } -#endif diff --git a/mcs/class/corlib/System.Reflection.Emit/MethodBuilder.cs b/mcs/class/corlib/System.Reflection.Emit/MethodBuilder.cs index 3772d98b82..5545adca27 100644 --- a/mcs/class/corlib/System.Reflection.Emit/MethodBuilder.cs +++ b/mcs/class/corlib/System.Reflection.Emit/MethodBuilder.cs @@ -364,7 +364,22 @@ namespace System.Reflection.Emit if (ilgen != null) ilgen.label_fixup (this); } - + + internal void ResolveUserTypes () { + rtype = TypeBuilder.ResolveUserType (rtype); + TypeBuilder.ResolveUserTypes (parameters); + TypeBuilder.ResolveUserTypes (returnModReq); + TypeBuilder.ResolveUserTypes (returnModOpt); + if (paramModReq != null) { + foreach (var types in paramModReq) + TypeBuilder.ResolveUserTypes (types); + } + if (paramModOpt != null) { + foreach (var types in paramModOpt) + TypeBuilder.ResolveUserTypes (types); + } + } + internal void GenerateDebugInfo (ISymbolWriter symbolWriter) { if (ilgen != null && ilgen.HasDebugInfo) { @@ -478,7 +493,7 @@ namespace System.Reflection.Emit public void AddDeclarativeSecurity (SecurityAction action, PermissionSet pset) { -#if !NET_2_1 +#if !MOBILE if (pset == null) throw new ArgumentNullException ("pset"); if ((action == SecurityAction.RequestMinimum) || diff --git a/mcs/class/corlib/System.Reflection.Emit/MethodBuilder.pns.cs b/mcs/class/corlib/System.Reflection.Emit/MethodBuilder.pns.cs new file mode 100644 index 0000000000..49ef26bd6f --- /dev/null +++ b/mcs/class/corlib/System.Reflection.Emit/MethodBuilder.pns.cs @@ -0,0 +1,112 @@ +// +// MethodBuilder.pns.cs +// +// Authors: +// Marek Safar (marek.safar@gmail.com) +// +// Copyright (C) 2016 Xamarin Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +#if FULL_AOT_RUNTIME + +namespace System.Reflection.Emit +{ + public abstract class MethodBuilder : MethodInfo + { + public bool InitLocals { get; set; } + + public override MethodAttributes Attributes { + get { + throw new PlatformNotSupportedException (); + } + } + + public override Type DeclaringType { + get { + throw new PlatformNotSupportedException (); + } + } + + public override string Name { + get { + throw new PlatformNotSupportedException (); + } + } + + public GenericTypeParameterBuilder[] DefineGenericParameters (string[] names) + { + throw new PlatformNotSupportedException (); + } + + public ParameterBuilder DefineParameter (int position, ParameterAttributes attributes, string strParamName) + { + throw new PlatformNotSupportedException (); + } + + public ILGenerator GetILGenerator () + { + throw new PlatformNotSupportedException (); + } + + public ILGenerator GetILGenerator (int size) + { + throw new PlatformNotSupportedException (); + } + + public override System.Reflection.ParameterInfo[] GetParameters () + { + throw new PlatformNotSupportedException (); + } + + public void SetCustomAttribute (CustomAttributeBuilder customBuilder) + { + throw new PlatformNotSupportedException (); + } + + public void SetCustomAttribute (ConstructorInfo con, byte[] binaryAttribute) + { + throw new PlatformNotSupportedException (); + } + + public void SetImplementationFlags (MethodImplAttributes attributes) + { + throw new PlatformNotSupportedException (); + } + + public void SetParameters (Type[] parameterTypes) + { + throw new PlatformNotSupportedException (); + } + + public void SetReturnType (Type returnType) + { + throw new PlatformNotSupportedException (); + } + + public void SetSignature (Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers, Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers) + { + throw new PlatformNotSupportedException (); + } + } +} + +#endif \ No newline at end of file diff --git a/mcs/class/corlib/System.Reflection.Emit/ModuleBuilder.pns.cs b/mcs/class/corlib/System.Reflection.Emit/ModuleBuilder.pns.cs new file mode 100644 index 0000000000..88d741d873 --- /dev/null +++ b/mcs/class/corlib/System.Reflection.Emit/ModuleBuilder.pns.cs @@ -0,0 +1,122 @@ +// +// ModuleBuilder.pns.cs +// +// Authors: +// Marek Safar (marek.safar@gmail.com) +// +// Copyright (C) 2016 Xamarin Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +#if FULL_AOT_RUNTIME + +namespace System.Reflection.Emit +{ + public abstract class ModuleBuilder : Module + { + public void CreateGlobalFunctions () + { + throw new PlatformNotSupportedException (); + } + + public EnumBuilder DefineEnum (string name, TypeAttributes visibility, Type underlyingType) + { + throw new PlatformNotSupportedException (); + } + + public MethodBuilder DefineGlobalMethod (string name, MethodAttributes attributes, Type returnType, Type[] parameterTypes) + { + throw new PlatformNotSupportedException (); + } + + public MethodBuilder DefineGlobalMethod (string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes) + { + throw new PlatformNotSupportedException (); + } + + public MethodBuilder DefineGlobalMethod (string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] requiredReturnTypeCustomModifiers, Type[] optionalReturnTypeCustomModifiers, Type[] parameterTypes, Type[][] requiredParameterTypeCustomModifiers, Type[][] optionalParameterTypeCustomModifiers) + { + throw new PlatformNotSupportedException (); + } + + public FieldBuilder DefineInitializedData (string name, byte[] data, FieldAttributes attributes) + { + throw new PlatformNotSupportedException (); + } + + public TypeBuilder DefineType (string name) + { + throw new PlatformNotSupportedException (); + } + + public TypeBuilder DefineType (string name, TypeAttributes attr) + { + throw new PlatformNotSupportedException (); + } + + public TypeBuilder DefineType (string name, TypeAttributes attr, Type parent) + { + throw new PlatformNotSupportedException (); + } + + public TypeBuilder DefineType (string name, TypeAttributes attr, Type parent, int typesize) + { + throw new PlatformNotSupportedException (); + } + + public TypeBuilder DefineType (string name, TypeAttributes attr, Type parent, PackingSize packsize) + { + throw new PlatformNotSupportedException (); + } + + public TypeBuilder DefineType (string name, TypeAttributes attr, Type parent, Type[] interfaces) + { + throw new PlatformNotSupportedException (); + } + + public TypeBuilder DefineType (string name, TypeAttributes attr, Type parent, PackingSize packingSize, int typesize) + { + throw new PlatformNotSupportedException (); + } + + public FieldBuilder DefineUninitializedData (string name, int size, FieldAttributes attributes) + { + throw new PlatformNotSupportedException (); + } + + public MethodInfo GetArrayMethod (Type arrayClass, string methodName, CallingConventions callingConvention, Type returnType, Type[] parameterTypes) + { + throw new PlatformNotSupportedException (); + } + + public void SetCustomAttribute (CustomAttributeBuilder customBuilder) + { + throw new PlatformNotSupportedException (); + } + + public void SetCustomAttribute (ConstructorInfo con, byte[] binaryAttribute) + { + throw new PlatformNotSupportedException (); + } + } +} + +#endif \ No newline at end of file diff --git a/mcs/class/corlib/System.Reflection.Emit/ParameterBuilder.pns.cs b/mcs/class/corlib/System.Reflection.Emit/ParameterBuilder.pns.cs new file mode 100644 index 0000000000..d9b1bab1e5 --- /dev/null +++ b/mcs/class/corlib/System.Reflection.Emit/ParameterBuilder.pns.cs @@ -0,0 +1,92 @@ +// +// ParameterBuilder.cs +// +// Authors: +// Marek Safar (marek.safar@gmail.com) +// +// Copyright (C) 2016 Xamarin Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +#if FULL_AOT_RUNTIME + +namespace System.Reflection.Emit +{ + public class ParameterBuilder + { + ParameterBuilder () + { + } + + public int Attributes { + get { + throw new PlatformNotSupportedException (); + } + } + + public bool IsIn { + get { + throw new PlatformNotSupportedException (); + } + } + + public bool IsOptional { + get { + throw new PlatformNotSupportedException (); + } + } + + public bool IsOut { + get { + throw new PlatformNotSupportedException (); + } + } + + public string Name { + get { + throw new PlatformNotSupportedException (); + } + } + + public int Position { + get { + throw new PlatformNotSupportedException (); + } + } + + public virtual void SetConstant (object defaultValue) + { + throw new PlatformNotSupportedException (); + } + + public void SetCustomAttribute (CustomAttributeBuilder customBuilder) + { + throw new PlatformNotSupportedException (); + } + + public void SetCustomAttribute (ConstructorInfo con, byte[] binaryAttribute) + { + throw new PlatformNotSupportedException (); + } + } +} + +#endif \ No newline at end of file diff --git a/mcs/class/corlib/System.Reflection.Emit/PropertyBuilder.pns.cs b/mcs/class/corlib/System.Reflection.Emit/PropertyBuilder.pns.cs new file mode 100644 index 0000000000..f0e709d53f --- /dev/null +++ b/mcs/class/corlib/System.Reflection.Emit/PropertyBuilder.pns.cs @@ -0,0 +1,108 @@ +// +// PropertyBuilder.pns.cs +// +// Authors: +// Marek Safar (marek.safar@gmail.com) +// +// Copyright (C) 2016 Xamarin Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +#if FULL_AOT_RUNTIME + +namespace System.Reflection.Emit +{ + public abstract class PropertyBuilder : PropertyInfo + { + public override PropertyAttributes Attributes { + get { + throw new PlatformNotSupportedException (); + } + } + + public override bool CanRead { + get { + throw new PlatformNotSupportedException (); + } + } + + public override bool CanWrite { + get { + throw new PlatformNotSupportedException (); + } + } + + public override Type DeclaringType { + get { + throw new PlatformNotSupportedException (); + } + } + + public override string Name { + get { + throw new PlatformNotSupportedException (); + } + } + + public override Type PropertyType { + get { + throw new PlatformNotSupportedException (); + } + } + + public void AddOtherMethod (MethodBuilder mdBuilder) + { + throw new PlatformNotSupportedException (); + } + + public void SetConstant (object defaultValue) + { + throw new PlatformNotSupportedException (); + } + + public void SetCustomAttribute (CustomAttributeBuilder customBuilder) + { + throw new PlatformNotSupportedException (); + } + + public void SetCustomAttribute (ConstructorInfo con, byte[] binaryAttribute) + { + throw new PlatformNotSupportedException (); + } + + public void SetGetMethod (MethodBuilder mdBuilder) + { + throw new PlatformNotSupportedException (); + } + + public void SetSetMethod (MethodBuilder mdBuilder) + { + throw new PlatformNotSupportedException (); + } + + public override ParameterInfo[] GetIndexParameters () + { + throw new PlatformNotSupportedException (); + } + } +} + +#endif \ No newline at end of file diff --git a/mcs/class/corlib/System.Reflection.Emit/SignatureHelper.cs b/mcs/class/corlib/System.Reflection.Emit/SignatureHelper.cs index 924eb674e1..f921be2218 100644 --- a/mcs/class/corlib/System.Reflection.Emit/SignatureHelper.cs +++ b/mcs/class/corlib/System.Reflection.Emit/SignatureHelper.cs @@ -361,6 +361,8 @@ namespace System.Reflection.Emit { public byte[] GetSignature () { + TypeBuilder.ResolveUserTypes (arguments); + switch (type) { case SignatureHelperType.HELPER_LOCAL: return get_signature_local (); diff --git a/mcs/class/corlib/System.Reflection.Emit/SignatureHelper.pns.cs b/mcs/class/corlib/System.Reflection.Emit/SignatureHelper.pns.cs new file mode 100644 index 0000000000..7aa0a27150 --- /dev/null +++ b/mcs/class/corlib/System.Reflection.Emit/SignatureHelper.pns.cs @@ -0,0 +1,116 @@ +// +// SignatureHelper.pns.cs +// +// Authors: +// Marek Safar (marek.safar@gmail.com) +// +// Copyright (C) 2016 Xamarin Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +#if FULL_AOT_RUNTIME + +namespace System.Reflection.Emit +{ + public class SignatureHelper + { + SignatureHelper () + { + } + + public void AddArgument (Type clsArgument) + { + throw new PlatformNotSupportedException (); + } + + public void AddArgument (Type argument, bool pinned) + { + throw new PlatformNotSupportedException (); + } + + public void AddArgument (Type argument, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers) + { + throw new PlatformNotSupportedException (); + } + + public void AddArguments (Type[] arguments, Type[][] requiredCustomModifiers, Type[][] optionalCustomModifiers) + { + throw new PlatformNotSupportedException (); + } + + public void AddSentinel () + { + throw new PlatformNotSupportedException (); + } + + public static SignatureHelper GetFieldSigHelper (Module mod) + { + throw new PlatformNotSupportedException (); + } + + public static SignatureHelper GetLocalVarSigHelper () + { + throw new PlatformNotSupportedException (); + } + + public static SignatureHelper GetLocalVarSigHelper (Module mod) + { + throw new PlatformNotSupportedException (); + } + + public static SignatureHelper GetMethodSigHelper (CallingConventions callingConvention, Type returnType) + { + throw new PlatformNotSupportedException (); + } + + public static SignatureHelper GetMethodSigHelper (Module mod, CallingConventions callingConvention, Type returnType) + { + throw new PlatformNotSupportedException (); + } + + public static SignatureHelper GetMethodSigHelper (Module mod, Type returnType, Type[] parameterTypes) + { + throw new PlatformNotSupportedException (); + } + + public static SignatureHelper GetPropertySigHelper (Module mod, Type returnType, Type[] parameterTypes) + { + throw new PlatformNotSupportedException (); + } + + public static SignatureHelper GetPropertySigHelper (Module mod, Type returnType, Type[] requiredReturnTypeCustomModifiers, Type[] optionalReturnTypeCustomModifiers, Type[] parameterTypes, Type[][] requiredParameterTypeCustomModifiers, Type[][] optionalParameterTypeCustomModifiers) + { + throw new PlatformNotSupportedException (); + } + + public static SignatureHelper GetPropertySigHelper (Module mod, CallingConventions callingConvention, Type returnType, Type[] requiredReturnTypeCustomModifiers, Type[] optionalReturnTypeCustomModifiers, Type[] parameterTypes, Type[][] requiredParameterTypeCustomModifiers, Type[][] optionalParameterTypeCustomModifiers) + { + throw new PlatformNotSupportedException (); + } + + public byte[] GetSignature () + { + throw new PlatformNotSupportedException (); + } + } +} + +#endif \ No newline at end of file diff --git a/mcs/class/corlib/System.Reflection.Emit/TypeBuilder.cs b/mcs/class/corlib/System.Reflection.Emit/TypeBuilder.cs index 7216a169e4..3972192308 100644 --- a/mcs/class/corlib/System.Reflection.Emit/TypeBuilder.cs +++ b/mcs/class/corlib/System.Reflection.Emit/TypeBuilder.cs @@ -93,14 +93,8 @@ namespace System.Reflection.Emit } [MethodImplAttribute(MethodImplOptions.InternalCall)] - private extern void setup_internal_class (TypeBuilder tb); + private extern void setup_internal_class (); - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private extern void create_internal_class (TypeBuilder tb); - - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private extern void setup_generic_class (); - [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern void create_generic_class (); @@ -117,13 +111,13 @@ namespace System.Reflection.Emit this.nspace = String.Empty; this.fullname = TypeIdentifiers.WithoutEscape(this.tname); pmodule = mb; - setup_internal_class (this); + setup_internal_class (); } internal TypeBuilder (ModuleBuilder mb, string name, TypeAttributes attr, Type parent, Type[] interfaces, PackingSize packing_size, int type_size, Type nesting_type) { int sep_index; - this.parent = parent; + this.parent = ResolveUserType (parent); this.attrs = attr; this.class_size = type_size; this.packing_size = packing_size; @@ -153,7 +147,7 @@ namespace System.Reflection.Emit // skip . ? table_idx = mb.get_next_table_index (this, 0x02, true); - setup_internal_class (this); + setup_internal_class (); fullname = GetFullName (); } @@ -259,7 +253,7 @@ namespace System.Reflection.Emit public void AddDeclarativeSecurity (SecurityAction action, PermissionSet pset) { -#if !NET_2_1 +#if !MOBILE if (pset == null) throw new ArgumentNullException ("pset"); if ((action == SecurityAction.RequestMinimum) || @@ -672,7 +666,6 @@ namespace System.Reflection.Emit fields = new FieldBuilder [1]; fields [0] = res; num_fields ++; - create_internal_class (this); } if (IsEnum) { @@ -728,7 +721,7 @@ namespace System.Reflection.Emit } [MethodImplAttribute(MethodImplOptions.InternalCall)] - private extern TypeInfo create_runtime_class (TypeBuilder tb); + private extern TypeInfo create_runtime_class (); private bool is_nested_in (Type t) { @@ -832,12 +825,54 @@ namespace System.Reflection.Emit ctor.fixup (); } - created = create_runtime_class (this); + ResolveUserTypes (); + + created = create_runtime_class (); if (created != null) return created; return this; } + void ResolveUserTypes () { + parent = ResolveUserType (parent); + ResolveUserTypes (interfaces); + if (fields != null) { + foreach (var fb in fields) { + if (fb != null) + fb.ResolveUserTypes (); + } + } + if (methods != null) { + foreach (var mb in methods) { + if (mb != null) + mb.ResolveUserTypes (); + } + } + if (ctors != null) { + foreach (var cb in ctors) { + if (cb != null) + cb.ResolveUserTypes (); + } + } + } + + static internal void ResolveUserTypes (Type[] types) { + if (types != null) + for (int i = 0; i < types.Length; ++i) + types [i] = ResolveUserType (types [i]); + } + + static internal Type ResolveUserType (Type t) { + if (t != null && ((t.GetType ().Assembly != typeof (int).Assembly) || (t is TypeDelegator))) { + t = t.UnderlyingSystemType; + if (t != null && ((t.GetType ().Assembly != typeof (int).Assembly) || (t is TypeDelegator))) + throw new NotSupportedException ("User defined subclasses of System.Type are not yet supported."); + return t; + } else { + return t; + } + } + internal void GenerateDebugInfo (ISymbolWriter symbolWriter) { symbolWriter.OpenNamespace (this.Namespace); @@ -1606,9 +1641,10 @@ namespace System.Reflection.Emit } else { this.parent = parent; } + this.parent = ResolveUserType (this.parent); // will just set the parent-related bits if called a second time - setup_internal_class (this); + setup_internal_class (); } internal int get_next_table_index (object obj, int table, bool inc) { @@ -1767,8 +1803,6 @@ namespace System.Reflection.Emit if (names.Length == 0) throw new ArgumentException ("names"); - setup_generic_class (); - generic_params = new GenericTypeParameterBuilder [names.Length]; for (int i = 0; i < names.Length; i++) { string item = names [i]; diff --git a/mcs/class/corlib/System.Reflection.Emit/TypeBuilder.pns.cs b/mcs/class/corlib/System.Reflection.Emit/TypeBuilder.pns.cs new file mode 100644 index 0000000000..ba97e01bef --- /dev/null +++ b/mcs/class/corlib/System.Reflection.Emit/TypeBuilder.pns.cs @@ -0,0 +1,284 @@ +// +// TypeBuilder.pns.cs +// +// Authors: +// Marek Safar (marek.safar@gmail.com) +// +// Copyright (C) 2016 Xamarin Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +#if FULL_AOT_RUNTIME + +namespace System.Reflection.Emit +{ + public abstract class TypeBuilder : TypeInfo + { + public const int UnspecifiedTypeSize = 0; + + public PackingSize PackingSize { + get { + throw new PlatformNotSupportedException (); + } + } + + public int Size { + get { + throw new PlatformNotSupportedException (); + } + } + + public override Assembly Assembly { + get { + throw new PlatformNotSupportedException (); + } + } + + public override string AssemblyQualifiedName { + get { + throw new PlatformNotSupportedException (); + } + } + + public override Type BaseType { + get { + throw new PlatformNotSupportedException (); + } + } + + public override string FullName { + get { + throw new PlatformNotSupportedException (); + } + } + + public override Guid GUID { + get { + throw new PlatformNotSupportedException (); + } + } + + public override Module Module { + get { + throw new PlatformNotSupportedException (); + } + } + + public override string Name { + get { + throw new PlatformNotSupportedException (); + } + } + + public override string Namespace { + get { + throw new PlatformNotSupportedException (); + } + } + + public void AddInterfaceImplementation (Type interfaceType) + { + throw new PlatformNotSupportedException (); + } + + public TypeInfo CreateTypeInfo () + { + throw new PlatformNotSupportedException (); + } + + public ConstructorBuilder DefineConstructor (MethodAttributes attributes, CallingConventions callingConvention, Type[] parameterTypes) + { + throw new PlatformNotSupportedException (); + } + + public ConstructorBuilder DefineConstructor (MethodAttributes attributes, CallingConventions callingConvention, Type[] parameterTypes, Type[][] requiredCustomModifiers, Type[][] optionalCustomModifiers) + { + throw new PlatformNotSupportedException (); + } + + public ConstructorBuilder DefineDefaultConstructor (MethodAttributes attributes) + { + throw new PlatformNotSupportedException (); + } + + public EventBuilder DefineEvent (string name, EventAttributes attributes, Type eventtype) + { + throw new PlatformNotSupportedException (); + } + + public FieldBuilder DefineField (string fieldName, Type type, FieldAttributes attributes) + { + throw new PlatformNotSupportedException (); + } + + public FieldBuilder DefineField (string fieldName, Type type, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers, FieldAttributes attributes) + { + throw new PlatformNotSupportedException (); + } + + public GenericTypeParameterBuilder[] DefineGenericParameters (string[] names) + { + throw new PlatformNotSupportedException (); + } + + public FieldBuilder DefineInitializedData (string name, byte[] data, FieldAttributes attributes) + { + throw new PlatformNotSupportedException (); + } + + public MethodBuilder DefineMethod (string name, MethodAttributes attributes) + { + throw new PlatformNotSupportedException (); + } + + public MethodBuilder DefineMethod (string name, MethodAttributes attributes, CallingConventions callingConvention) + { + throw new PlatformNotSupportedException (); + } + + public MethodBuilder DefineMethod (string name, MethodAttributes attributes, Type returnType, Type[] parameterTypes) + { + throw new PlatformNotSupportedException (); + } + + public MethodBuilder DefineMethod (string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes) + { + throw new PlatformNotSupportedException (); + } + + public MethodBuilder DefineMethod (string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers, Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers) + { + throw new PlatformNotSupportedException (); + } + + public void DefineMethodOverride (MethodInfo methodInfoBody, MethodInfo methodInfoDeclaration) + { + throw new PlatformNotSupportedException (); + } + + public TypeBuilder DefineNestedType (string name) + { + throw new PlatformNotSupportedException (); + } + + public TypeBuilder DefineNestedType (string name, TypeAttributes attr) + { + throw new PlatformNotSupportedException (); + } + + public TypeBuilder DefineNestedType (string name, TypeAttributes attr, Type parent) + { + throw new PlatformNotSupportedException (); + } + + public TypeBuilder DefineNestedType (string name, TypeAttributes attr, Type parent, int typeSize) + { + throw new PlatformNotSupportedException (); + } + + public TypeBuilder DefineNestedType (string name, TypeAttributes attr, Type parent, PackingSize packSize) + { + throw new PlatformNotSupportedException (); + } + + public TypeBuilder DefineNestedType (string name, TypeAttributes attr, Type parent, Type[] interfaces) + { + throw new PlatformNotSupportedException (); + } + + public TypeBuilder DefineNestedType (string name, TypeAttributes attr, Type parent, PackingSize packSize, int typeSize) + { + throw new PlatformNotSupportedException (); + } + + public PropertyBuilder DefineProperty (string name, PropertyAttributes attributes, Type returnType, Type[] parameterTypes) + { + throw new PlatformNotSupportedException (); + } + + public PropertyBuilder DefineProperty (string name, PropertyAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes) + { + throw new PlatformNotSupportedException (); + } + + public PropertyBuilder DefineProperty (string name, PropertyAttributes attributes, Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers, Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers) + { + throw new PlatformNotSupportedException (); + } + + public PropertyBuilder DefineProperty (string name, PropertyAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers, Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers) + { + throw new PlatformNotSupportedException (); + } + + public ConstructorBuilder DefineTypeInitializer () + { + throw new PlatformNotSupportedException (); + } + + public FieldBuilder DefineUninitializedData (string name, int size, FieldAttributes attributes) + { + throw new PlatformNotSupportedException (); + } + + public static ConstructorInfo GetConstructor (Type type, ConstructorInfo constructor) + { + throw new PlatformNotSupportedException (); + } + + public static FieldInfo GetField (Type type, FieldInfo field) + { + throw new PlatformNotSupportedException (); + } + + public static MethodInfo GetMethod (Type type, MethodInfo method) + { + throw new PlatformNotSupportedException (); + } + + public bool IsCreated () + { + throw new PlatformNotSupportedException (); + } + + public void SetCustomAttribute (CustomAttributeBuilder customBuilder) + { + throw new PlatformNotSupportedException (); + } + + public void SetCustomAttribute (ConstructorInfo con, byte[] binaryAttribute) + { + throw new PlatformNotSupportedException (); + } + + public void SetParent (Type parent) + { + throw new PlatformNotSupportedException (); + } + + public override Type GetElementType () + { + throw new PlatformNotSupportedException (); + } + } +} + +#endif \ No newline at end of file diff --git a/mcs/class/corlib/System.Reflection.Emit/UnmanagedMarshal.cs b/mcs/class/corlib/System.Reflection.Emit/UnmanagedMarshal.cs index 45b9a2caef..8772be59da 100644 --- a/mcs/class/corlib/System.Reflection.Emit/UnmanagedMarshal.cs +++ b/mcs/class/corlib/System.Reflection.Emit/UnmanagedMarshal.cs @@ -50,7 +50,7 @@ namespace System.Reflection.Emit { string guid; string mcookie; string marshaltype; - Type marshaltyperef; + internal Type marshaltyperef; private int param_num; private bool has_size; #pragma warning restore 169, 414 diff --git a/mcs/class/corlib/System.Reflection/Assembly.cs b/mcs/class/corlib/System.Reflection/Assembly.cs index 9b94a66cef..6b175b54b6 100644 --- a/mcs/class/corlib/System.Reflection/Assembly.cs +++ b/mcs/class/corlib/System.Reflection/Assembly.cs @@ -53,11 +53,12 @@ namespace System.Reflection { [ClassInterface(ClassInterfaceType.None)] [StructLayout (LayoutKind.Sequential)] #if MOBILE - public partial class Assembly : ICustomAttributeProvider { + public partial class Assembly : ICustomAttributeProvider, ISerializable #else - public abstract class Assembly : ICustomAttributeProvider, _Assembly, IEvidenceFactory, ISerializable { + public abstract class Assembly : ICustomAttributeProvider, _Assembly, IEvidenceFactory, ISerializable #endif - internal class ResolveEventHolder { + { + internal class ResolveEventHolder { public event ModuleResolveEventHandler ModuleResolve; } @@ -88,7 +89,7 @@ namespace System.Reflection { // Note: changes to fields must be reflected in _MonoReflectionAssembly struct (object-internals.h) #pragma warning disable 649 - private IntPtr _mono_assembly; + internal IntPtr _mono_assembly; #pragma warning restore 649 private ResolveEventHolder resolve_event_holder; @@ -115,7 +116,7 @@ namespace System.Reflection { // We can't store the event directly in this class, since the // compiler would silently insert the fields before _mono_assembly // - public event ModuleResolveEventHandler ModuleResolve { + public virtual event ModuleResolveEventHandler ModuleResolve { [SecurityPermission (SecurityAction.LinkDemand, ControlAppDomain = true)] add { resolve_event_holder.ModuleResolve += value; @@ -145,7 +146,7 @@ namespace System.Reflection { private string GetCodeBase (bool escaped) { string cb = get_code_base (escaped); -#if !NET_2_1 +#if !MOBILE if (SecurityManager.SecurityEnabled) { // we cannot divulge local file informations if (String.Compare ("FILE://", 0, cb, 0, 7, true, CultureInfo.InvariantCulture) == 0) { @@ -215,7 +216,7 @@ namespace System.Reflection { return String.Empty; string loc = get_location (); -#if !NET_2_1 +#if !MOBILE if ((loc != String.Empty) && SecurityManager.SecurityEnabled) { // we cannot divulge local file informations new FileIOPermission (FileIOPermissionAccess.PathDiscovery, loc).Demand (); @@ -425,19 +426,9 @@ namespace System.Reflection { [MethodImplAttribute (MethodImplOptions.InternalCall)] internal extern static void InternalGetAssemblyName (string assemblyFile, AssemblyName aname); - [MethodImplAttribute (MethodImplOptions.InternalCall)] - static extern void FillName (Assembly ass, AssemblyName aname); - - [MonoTODO ("copiedName == true is not supported")] public virtual AssemblyName GetName (Boolean copiedName) { -#if !MOBILE - // CodeBase, which is restricted, will be copied into the AssemblyName object so... - if (SecurityManager.SecurityEnabled) { - GetCodeBase (true); // this will ensure the Demand is made - } -#endif - return UnprotectedGetName (); + throw new NotImplementedException (); } public virtual AssemblyName GetName () @@ -445,14 +436,6 @@ namespace System.Reflection { return GetName (false); } - // the security runtime requires access to the assemblyname (e.g. to get the strongname) - internal virtual AssemblyName UnprotectedGetName () - { - AssemblyName aname = new AssemblyName (); - FillName (this, aname); - return aname; - } - public override string ToString () { // note: ToString work without requiring CodeBase (so no checks are needed) @@ -523,10 +506,14 @@ namespace System.Reflection { // Try the assembly directory string location = Path.GetDirectoryName (Location); string fullName = Path.Combine (location, Path.Combine (culture.Name, an.Name + ".dll")); - if (!throwOnFileNotFound && !File.Exists (fullName)) - return null; - return (RuntimeAssembly)LoadFrom (fullName); + try { + return (RuntimeAssembly)LoadFrom (fullName); + } catch { + if (!throwOnFileNotFound && !File.Exists (fullName)) + return null; + throw; + } } #if !MOBILE @@ -549,7 +536,7 @@ namespace System.Reflection { public static Assembly LoadFrom (String assemblyFile, Evidence securityEvidence) { Assembly a = LoadFrom (assemblyFile, false); -#if !NET_2_1 +#if !MOBILE if ((a != null) && (securityEvidence != null)) { // merge evidence (i.e. replace defaults with provided evidences) a.Evidence.Merge (securityEvidence); @@ -821,7 +808,7 @@ namespace System.Reflection { return other._mono_assembly == _mono_assembly; } -#if !NET_2_1 +#if !MOBILE // Code Access Security internal void Resolve () @@ -906,13 +893,12 @@ namespace System.Reflection { public virtual PermissionSet PermissionSet { get { return this.GrantedPermissionSet; } } - +#endif + public virtual SecurityRuleSet SecurityRuleSet { get { throw CreateNIE (); } } -#endif - static Exception CreateNIE () { return new NotImplementedException ("Derived classes must implement it"); diff --git a/mcs/class/corlib/System.Reflection/AssemblyName.cs b/mcs/class/corlib/System.Reflection/AssemblyName.cs index ca5f436a3c..86241d82d2 100644 --- a/mcs/class/corlib/System.Reflection/AssemblyName.cs +++ b/mcs/class/corlib/System.Reflection/AssemblyName.cs @@ -40,6 +40,7 @@ using System.Runtime.InteropServices; using System.Runtime.CompilerServices; using System.IO; +using Mono; using Mono.Security; using Mono.Security.Cryptography; @@ -84,17 +85,29 @@ namespace System.Reflection { } [MethodImpl (MethodImplOptions.InternalCall)] - static extern bool ParseName (AssemblyName aname, string assemblyName); - + static extern bool ParseAssemblyName (IntPtr name, out MonoAssemblyName aname, out bool is_version_definited, out bool is_token_defined); + public AssemblyName (string assemblyName) { if (assemblyName == null) throw new ArgumentNullException ("assemblyName"); if (assemblyName.Length < 1) throw new ArgumentException ("assemblyName cannot have zero length."); - - if (!ParseName (this, assemblyName)) - throw new FileLoadException ("The assembly name is invalid."); + + using (var name = RuntimeMarshal.MarshalString (assemblyName)) { + MonoAssemblyName nativeName; + bool isVersionDefined, isTokenDefined; + //ParseName free the name if it fails. + if (!ParseAssemblyName (name.Value, out nativeName, out isVersionDefined, out isTokenDefined)) + throw new FileLoadException ("The assembly name is invalid."); + try { + unsafe { + this.FillName (&nativeName, null, isVersionDefined, false, isTokenDefined); + } + } finally { + RuntimeMarshal.FreeAssemblyName (ref nativeName); + } + } } [MonoLimitation ("Not used, as the values are too limited; Mono supports more")] @@ -447,5 +460,63 @@ namespace System.Reflection { contentType = value; } } + + [MethodImplAttribute (MethodImplOptions.InternalCall)] + static extern unsafe MonoAssemblyName* GetNativeName (IntPtr assembly_ptr); + + internal unsafe void FillName (MonoAssemblyName *native, string codeBase, bool addVersion, bool addPublickey, bool defaultToken) + { + this.name = RuntimeMarshal.PtrToUtf8String (native->name); + + this.major = native->major; + this.minor = native->minor; + this.build = native->build; + this.revision = native->revision; + + this.flags = (AssemblyNameFlags)native->flags; + + this.hashalg = (AssemblyHashAlgorithm)native->hash_alg; + + this.versioncompat = AssemblyVersionCompatibility.SameMachine; + this.processor_architecture = (ProcessorArchitecture)native->arch; + + if (addVersion) + this.version = new Version (this.major, this.minor, this.build, this.revision); + + this.codebase = codeBase; + + if (native->culture != IntPtr.Zero) + this.cultureinfo = CultureInfo.CreateCulture ( RuntimeMarshal.PtrToUtf8String (native->culture), false); + + if (native->public_key != IntPtr.Zero) { + this.publicKey = RuntimeMarshal.DecodeBlobArray (native->public_key); + this.flags |= AssemblyNameFlags.PublicKey; + } else if (addPublickey) { + this.publicKey = EmptyArray.Value; + this.flags |= AssemblyNameFlags.PublicKey; + } + + // MonoAssemblyName keeps the public key token as an hexadecimal string + if (native->public_key_token [0] != 0) { + byte[] keyToken = new byte [8]; + for (int i = 0, j = 0; i < 8; ++i) { + keyToken [i] = (byte)(RuntimeMarshal.AsciHexDigitValue (native->public_key_token [j++]) << 4); + keyToken [i] |= (byte)RuntimeMarshal.AsciHexDigitValue (native->public_key_token [j++]); + } + this.keyToken = keyToken; + } else if (defaultToken) { + this.keyToken = EmptyArray.Value; + } + } + + internal static AssemblyName Create (Assembly assembly, bool fillCodebase) + { + AssemblyName aname = new AssemblyName (); + unsafe { + MonoAssemblyName *native = GetNativeName (assembly._mono_assembly); + aname.FillName (native, fillCodebase ? assembly.CodeBase : null, true, true, true); + } + return aname; + } } } diff --git a/mcs/class/corlib/System.Reflection/EventInfo.cs b/mcs/class/corlib/System.Reflection/EventInfo.cs index 040fe38bea..28a727924c 100644 --- a/mcs/class/corlib/System.Reflection/EventInfo.cs +++ b/mcs/class/corlib/System.Reflection/EventInfo.cs @@ -28,6 +28,7 @@ // using System.Diagnostics; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; namespace System.Reflection { @@ -252,7 +253,7 @@ namespace System.Reflection { } addHandlerType = addHandlerDelegateType.MakeGenericType (typeVector); -#if NET_2_1 +#if MOBILE // with Silverlight a coreclr failure (e.g. Transparent caller creating a delegate on a Critical method) // would normally throw an ArgumentException, so we set throwOnBindFailure to false and check for a null // delegate that we can transform into a MethodAccessException @@ -277,5 +278,25 @@ namespace System.Reflection { public virtual MethodInfo RemoveMethod { get { return GetRemoveMethod (true); } } + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + private static extern EventInfo internal_from_handle_type (IntPtr event_handle, IntPtr type_handle); + + internal static EventInfo GetEventFromHandle (Mono.RuntimeEventHandle handle) + { + if (handle.Value == IntPtr.Zero) + throw new ArgumentException ("The handle is invalid."); + return internal_from_handle_type (handle.Value, IntPtr.Zero); + } + + internal static EventInfo GetEventFromHandle (Mono.RuntimeEventHandle handle, RuntimeTypeHandle reflectedType) + { + if (handle.Value == IntPtr.Zero) + throw new ArgumentException ("The handle is invalid."); + EventInfo ei = internal_from_handle_type (handle.Value, reflectedType.Value); + if (ei == null) + throw new ArgumentException ("The event handle and the type handle are incompatible."); + return ei; + } } } diff --git a/mcs/class/corlib/System.Reflection/MonoAssembly.cs b/mcs/class/corlib/System.Reflection/MonoAssembly.cs index 7a03629457..a62b86a63e 100644 --- a/mcs/class/corlib/System.Reflection/MonoAssembly.cs +++ b/mcs/class/corlib/System.Reflection/MonoAssembly.cs @@ -37,9 +37,12 @@ using System.Collections.Generic; using System.Runtime.Serialization; using System.Threading; using System.Diagnostics.Contracts; +using System.Security; using System.Security.Policy; using System.Security.Permissions; +using Mono; + namespace System.Reflection { abstract class RuntimeAssembly : Assembly @@ -151,6 +154,18 @@ namespace System.Reflection { return LoadWithPartialNameInternal (an.ToString (), securityEvidence, ref stackMark); } + // the security runtime requires access to the assemblyname (e.g. to get the strongname) + public override AssemblyName GetName (bool copiedName) + { + +#if !MOBILE + // CodeBase, which is restricted, will be copied into the AssemblyName object so... + if (SecurityManager.SecurityEnabled) { + var _ = CodeBase; // this will ensure the Demand is made + } +#endif + return AssemblyName.Create (this, true); + } } [ComVisible (true)] diff --git a/mcs/class/corlib/System.Reflection/MonoMethod.cs b/mcs/class/corlib/System.Reflection/MonoMethod.cs index c93233dfff..9e5197df13 100644 --- a/mcs/class/corlib/System.Reflection/MonoMethod.cs +++ b/mcs/class/corlib/System.Reflection/MonoMethod.cs @@ -305,7 +305,7 @@ namespace System.Reflection { o = InternalInvoke (obj, parameters, out exc); } catch (ThreadAbortException) { throw; -#if NET_2_1 +#if MOBILE } catch (MethodAccessException) { throw; #endif @@ -659,7 +659,7 @@ namespace System.Reflection { try { o = InternalInvoke (obj, parameters, out exc); -#if NET_2_1 +#if MOBILE } catch (MethodAccessException) { throw; #endif diff --git a/mcs/class/corlib/System.Reflection/MonoModule.cs b/mcs/class/corlib/System.Reflection/MonoModule.cs index 6edaf0de37..25bde841e9 100644 --- a/mcs/class/corlib/System.Reflection/MonoModule.cs +++ b/mcs/class/corlib/System.Reflection/MonoModule.cs @@ -90,7 +90,7 @@ namespace System.Reflection { public override string FullyQualifiedName { get { -#if !NET_2_1 +#if !MOBILE if (SecurityManager.SecurityEnabled) { new FileIOPermission (FileIOPermissionAccess.PathDiscovery, fqname).Demand (); } @@ -283,7 +283,7 @@ namespace System.Reflection { UnitySerializationHolder.GetUnitySerializationInfo (info, UnitySerializationHolder.ModuleUnity, this.ScopeName, this.GetRuntimeAssembly ()); } -#if !NET_2_1 +#if !MOBILE public override diff --git a/mcs/class/corlib/System.Reflection/MonoProperty.cs b/mcs/class/corlib/System.Reflection/MonoProperty.cs index 87310b19e2..16f44ec583 100644 --- a/mcs/class/corlib/System.Reflection/MonoProperty.cs +++ b/mcs/class/corlib/System.Reflection/MonoProperty.cs @@ -359,7 +359,7 @@ namespace System.Reflection { } getterType = getterDelegateType.MakeGenericType (typeVector); -#if NET_2_1 +#if MOBILE // with Silverlight a coreclr failure (e.g. Transparent caller creating a delegate on a Critical method) // would normally throw an ArgumentException, so we set throwOnBindFailure to false and check for a null // delegate that we can transform into a MethodAccessException diff --git a/mcs/class/corlib/System.Reflection/PropertyInfo.cs b/mcs/class/corlib/System.Reflection/PropertyInfo.cs index 68a62f74a6..9eeb9cc917 100644 --- a/mcs/class/corlib/System.Reflection/PropertyInfo.cs +++ b/mcs/class/corlib/System.Reflection/PropertyInfo.cs @@ -196,5 +196,18 @@ namespace System.Reflection { throw new NotImplementedException (); } #endif + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + private static extern PropertyInfo internal_from_handle_type (IntPtr event_handle, IntPtr type_handle); + + internal static PropertyInfo GetPropertyFromHandle (Mono.RuntimePropertyHandle handle, RuntimeTypeHandle reflectedType) + { + if (handle.Value == IntPtr.Zero) + throw new ArgumentException ("The handle is invalid."); + PropertyInfo pi = internal_from_handle_type (handle.Value, reflectedType.Value); + if (pi == null) + throw new ArgumentException ("The property handle and the type handle are incompatible."); + return pi; + } } } diff --git a/mcs/class/corlib/System.Reflection/StrongNameKeyPair.cs b/mcs/class/corlib/System.Reflection/StrongNameKeyPair.cs index aff2ae187e..bfa10d8b9c 100644 --- a/mcs/class/corlib/System.Reflection/StrongNameKeyPair.cs +++ b/mcs/class/corlib/System.Reflection/StrongNameKeyPair.cs @@ -121,7 +121,7 @@ public class StrongNameKeyPair : ISerializable, IDeserializationCallback _keyPairArray = null; } } -#if !NET_2_1 +#if !MOBILE else if (_keyPairContainer != null) { CspParameters csp = new CspParameters (); csp.KeyContainerName = _keyPairContainer; diff --git a/mcs/class/corlib/System.Runtime.InteropServices/Marshal.cs b/mcs/class/corlib/System.Runtime.InteropServices/Marshal.cs index 1f3919573e..d7128abc33 100644 --- a/mcs/class/corlib/System.Runtime.InteropServices/Marshal.cs +++ b/mcs/class/corlib/System.Runtime.InteropServices/Marshal.cs @@ -1107,25 +1107,21 @@ namespace System.Runtime.InteropServices { if (s == null) throw new ArgumentNullException ("s"); - int len = s.Length; - IntPtr ctm = AllocCoTaskMem ((len+1) * 2 + 4); - byte [] buffer = null; - WriteInt32 (ctm, 0, len*2); - try { - buffer = s.GetBuffer (); - for (int i = 0; i < len; i++) - WriteInt16 (ctm, 4 + (i * 2), (short) ((buffer [(i*2)] << 8) | (buffer [i*2+1]))); - WriteInt16 (ctm, 4 + buffer.Length, 0); - } finally { - if (buffer != null) - for (int i = buffer.Length; i > 0; ){ - i--; - buffer [i] = 0; - } + byte[] buffer = s.GetBuffer (); + int len = s.Length; + + // SecureString doesn't take endian-ness into account. + // Therefore swap bytes here before we send it to c-side if little-endian. + if (BitConverter.IsLittleEndian) { + for (int i = 0; i < buffer.Length; i += 2) { + byte b = buffer[i]; + buffer[i] = buffer[i + 1]; + buffer[i + 1] = b; + } } - return (IntPtr) ((long)ctm + 4); - } + return BufferToBSTR (buffer, len); + } public static IntPtr SecureStringToCoTaskMemAnsi (SecureString s) { @@ -1212,6 +1208,10 @@ namespace System.Runtime.InteropServices throw ex; } + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public extern static IntPtr BufferToBSTR (Array ptr, int slen); + [MethodImplAttribute(MethodImplOptions.InternalCall)] public extern static IntPtr UnsafeAddrOfPinnedArrayElement (Array arr, int index); diff --git a/mcs/class/corlib/System.Runtime.InteropServices/SafeHandle.cs b/mcs/class/corlib/System.Runtime.InteropServices/SafeHandle.cs index b5b59a1ae8..a01d526ff2 100644 --- a/mcs/class/corlib/System.Runtime.InteropServices/SafeHandle.cs +++ b/mcs/class/corlib/System.Runtime.InteropServices/SafeHandle.cs @@ -122,7 +122,7 @@ namespace System.Runtime.InteropServices old_state = _state; if ((old_state & (int) State.Closed) != 0) - throw new ObjectDisposedException ("handle"); + throw new ObjectDisposedException (null, "Safe handle has been closed"); new_state = old_state + RefCount_One; } while (Interlocked.CompareExchange (ref _state, new_state, old_state) != old_state); @@ -198,7 +198,7 @@ namespace System.Runtime.InteropServices * hitting zero though -- that can happen if SetHandleAsInvalid is * used). */ if ((old_state & RefCount_Mask) == 0) - throw new ObjectDisposedException ("handle"); + throw new ObjectDisposedException (null, "Safe handle has been closed"); if ((old_state & RefCount_Mask) != RefCount_One) perform_release = false; diff --git a/mcs/class/corlib/System.Runtime.InteropServices/_Assembly.cs b/mcs/class/corlib/System.Runtime.InteropServices/_Assembly.cs index a30e29ce22..c8b640e10b 100644 --- a/mcs/class/corlib/System.Runtime.InteropServices/_Assembly.cs +++ b/mcs/class/corlib/System.Runtime.InteropServices/_Assembly.cs @@ -87,7 +87,7 @@ namespace System.Runtime.InteropServices string Location { get; } -#if !NET_2_1 +#if !MOBILE Evidence Evidence { get; } #endif @@ -129,7 +129,7 @@ namespace System.Runtime.InteropServices AssemblyName[] GetReferencedAssemblies (); -#if !NET_2_1 +#if !MOBILE bool GlobalAssemblyCache { get; } #endif diff --git a/mcs/class/corlib/System.Runtime.Remoting.Activation/ActivationServices.cs b/mcs/class/corlib/System.Runtime.Remoting.Activation/ActivationServices.cs index 71f1269b28..57094710db 100644 --- a/mcs/class/corlib/System.Runtime.Remoting.Activation/ActivationServices.cs +++ b/mcs/class/corlib/System.Runtime.Remoting.Activation/ActivationServices.cs @@ -213,7 +213,7 @@ namespace System.Runtime.Remoting.Activation if (type.IsContextful) return RemotingServices.CreateClientProxyForContextBound (type, null); -#if !NET_2_1 +#if !MOBILE if (type.IsCOMObject) { return RemotingServices.CreateClientProxyForComInterop (type); } diff --git a/mcs/class/corlib/System.Runtime.Remoting.Messaging/MonoMethodMessage.cs b/mcs/class/corlib/System.Runtime.Remoting.Messaging/MonoMethodMessage.cs index 3b324d1eab..3640f72859 100644 --- a/mcs/class/corlib/System.Runtime.Remoting.Messaging/MonoMethodMessage.cs +++ b/mcs/class/corlib/System.Runtime.Remoting.Messaging/MonoMethodMessage.cs @@ -68,8 +68,38 @@ namespace System.Runtime.Remoting.Messaging { internal static String CallContextKey = "__CallContext"; internal static String UriKey = "__Uri"; - [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal extern void InitMessage (MonoMethod method, object [] out_args); + internal void InitMessage (MonoMethod method, object [] out_args) + { + this.method = method; + ParameterInfo[] paramInfo = method.GetParametersInternal (); + int param_count = paramInfo.Length; + args = new object[param_count]; + arg_types = new byte[param_count]; + asyncResult = null; + call_type = CallType.Sync; + names = new string[param_count]; + for (int i = 0; i < param_count; i++) { + names[i] = paramInfo[i].Name; + } + bool hasOutArgs = out_args != null; + int j = 0; + for (int i = 0; i < param_count; i++) { + byte arg_type; + bool isOut = paramInfo[i].IsOut; + if (paramInfo[i].ParameterType.IsByRef) { + if (hasOutArgs) + args[i] = out_args[j++]; + arg_type = 2; // OUT + if (!isOut) + arg_type |= 1; // INOUT + } else { + arg_type = 1; // IN + if (isOut) + arg_type |= 4; // IN, COPY OUT + } + arg_types[i] = arg_type; + } + } public MonoMethodMessage (MethodBase method, object [] out_args) { @@ -79,19 +109,30 @@ namespace System.Runtime.Remoting.Messaging { args = null; } - public MonoMethodMessage (Type type, string method_name, object [] in_args) + internal MonoMethodMessage (MethodInfo minfo, object [] in_args, object [] out_args) { - // fixme: consider arg types - MethodInfo minfo = type.GetMethod (method_name); - - InitMessage ((MonoMethod)minfo, null); + InitMessage ((MonoMethod)minfo, out_args); int len = in_args.Length; for (int i = 0; i < len; i++) { args [i] = in_args [i]; } } + + private static MethodInfo GetMethodInfo (Type type, string methodName) + { + // fixme: consider arg types + MethodInfo minfo = type.GetMethod(methodName); + if (minfo == null) + throw new ArgumentException (String.Format("Could not find '{0}' in {1}", methodName, type), "methodName"); + return minfo; + } + public MonoMethodMessage (Type type, string methodName, object [] in_args) + : this (GetMethodInfo (type, methodName), in_args, null) + { + } + public IDictionary Properties { get { if (properties == null) properties = new MCMDictionary (this); diff --git a/mcs/class/corlib/System.Runtime.Remoting.Proxies/RealProxy.cs b/mcs/class/corlib/System.Runtime.Remoting.Proxies/RealProxy.cs index de4b921cff..74b8b65b3f 100644 --- a/mcs/class/corlib/System.Runtime.Remoting.Proxies/RealProxy.cs +++ b/mcs/class/corlib/System.Runtime.Remoting.Proxies/RealProxy.cs @@ -49,8 +49,84 @@ namespace System.Runtime.Remoting.Proxies [StructLayout (LayoutKind.Sequential)] internal class TransparentProxy { public RealProxy _rp; - IntPtr _class; + Mono.RuntimeRemoteClassHandle _class; bool _custom_type_info; + + unsafe internal RuntimeType GetProxyType () { + RuntimeTypeHandle h = _class.ProxyClass.GetTypeHandle (); + return (RuntimeType)Type.GetTypeFromHandle (h); + } + + bool IsContextBoundObject { + get { return GetProxyType ().IsContextful; } + } + + Context TargetContext { + get { return _rp._targetContext; } + } + + bool InCurrentContext () { + return IsContextBoundObject && Object.ReferenceEquals (TargetContext, Thread.CurrentContext); + } + + internal object LoadRemoteFieldNew (IntPtr classPtr, IntPtr fieldPtr) { + Mono.RuntimeClassHandle classHandle = new Mono.RuntimeClassHandle (classPtr); + RuntimeFieldHandle fieldHandle = new RuntimeFieldHandle (fieldPtr); + RuntimeTypeHandle typeHandle = classHandle.GetTypeHandle (); + + FieldInfo field = FieldInfo.GetFieldFromHandle (fieldHandle); + + if (InCurrentContext ()) { + object o = _rp._server; + return field.GetValue(o); + } + + string typeName = Type.GetTypeFromHandle(typeHandle).FullName; + string fieldName = field.Name; + object[] inArgs = new object[] { typeName, + fieldName }; + object[] outArgsMsg = new object[1]; + MethodInfo minfo = typeof(object).GetMethod("FieldGetter", BindingFlags.NonPublic | BindingFlags.Instance); + if (minfo == null) + throw new MissingMethodException ("System.Object", "FieldGetter"); + MonoMethodMessage msg = new MonoMethodMessage (minfo, inArgs, outArgsMsg); + object[] outArgs; + Exception exc; + RealProxy.PrivateInvoke (_rp, msg, out exc, out outArgs); + if (exc != null) + throw exc; + return outArgs[0]; + } + + internal void StoreRemoteField (IntPtr classPtr, IntPtr fieldPtr, object arg) { + Mono.RuntimeClassHandle classHandle = new Mono.RuntimeClassHandle (classPtr); + RuntimeFieldHandle fieldHandle = new RuntimeFieldHandle (fieldPtr); + RuntimeTypeHandle typeHandle = classHandle.GetTypeHandle (); + FieldInfo field = FieldInfo.GetFieldFromHandle (fieldHandle); + + if (InCurrentContext ()) { + object o = _rp._server; + field.SetValue (o, arg); + return; + } + + string typeName = Type.GetTypeFromHandle (typeHandle).FullName; + string fieldName = field.Name; + object [] inArgs = new object[] { typeName, + fieldName, + arg }; + MethodInfo minfo = typeof(object).GetMethod ("FieldSetter", BindingFlags.NonPublic | BindingFlags.Instance); + if (minfo == null) + throw new MissingMethodException ("System.Object", "FieldSetter"); + + MonoMethodMessage msg = new MonoMethodMessage (minfo, inArgs, null); + object [] outArgs; + Exception exc; + RealProxy.PrivateInvoke (_rp, msg, out exc, out outArgs); + if (exc != null) + throw exc; + } + } #pragma warning restore 169, 649 @@ -66,7 +142,7 @@ namespace System.Runtime.Remoting.Proxies #region Sync with object-internals.h Type class_to_proxy; internal Context _targetContext; - MarshalByRefObject _server; + internal MarshalByRefObject _server; int _targetDomainId = -1; internal string _targetUri; internal Identity _objectIdentity; diff --git a/mcs/class/corlib/System.Runtime.Remoting/RemotingConfiguration.cs b/mcs/class/corlib/System.Runtime.Remoting/RemotingConfiguration.cs index 33fef7a0a8..eb45ced822 100644 --- a/mcs/class/corlib/System.Runtime.Remoting/RemotingConfiguration.cs +++ b/mcs/class/corlib/System.Runtime.Remoting/RemotingConfiguration.cs @@ -106,7 +106,12 @@ namespace System.Runtime.Remoting { lock (channelTemplates) { if (!defaultConfigRead) { - ReadConfigFile (Environment.GetMachineConfigPath ()); + var bundled = Environment.GetBundledMachineConfig (); + if (bundled != null) + ReadConfigString (bundled); + + if (File.Exists (Environment.GetMachineConfigPath ())) + ReadConfigFile (Environment.GetMachineConfigPath ()); defaultConfigRead = true; } @@ -121,6 +126,22 @@ namespace System.Runtime.Remoting Configure (filename, false); } + private static void ReadConfigString (string filename) + { + try + { + SmallXmlParser parser = new SmallXmlParser (); + using (TextReader rreader = new StringReader (filename)) { + ConfigHandler handler = new ConfigHandler (false); + parser.Parse (rreader, handler); + } + } + catch (Exception ex) + { + throw new RemotingException ("Configuration string could not be loaded: " + ex.Message, ex); + } + } + private static void ReadConfigFile (string filename) { try diff --git a/mcs/class/corlib/System.Runtime.Remoting/RemotingServices.cs b/mcs/class/corlib/System.Runtime.Remoting/RemotingServices.cs index 1b35fe1ee9..d2b99281c3 100644 --- a/mcs/class/corlib/System.Runtime.Remoting/RemotingServices.cs +++ b/mcs/class/corlib/System.Runtime.Remoting/RemotingServices.cs @@ -581,7 +581,7 @@ namespace System.Runtime.Remoting RemotingProxy proxy = new RemotingProxy (type, ChannelServices.CrossContextUrl, activationAttributes); return proxy.GetTransparentProxy(); } -#if !NET_2_1 +#if !MOBILE internal static object CreateClientProxyForComInterop (Type type) { Mono.Interop.ComInteropProxy proxy = Mono.Interop.ComInteropProxy.CreateProxy (type); diff --git a/mcs/class/corlib/System.Runtime/GCLatencyMode.cs b/mcs/class/corlib/System.Runtime/GCLatencyMode.cs index 2bb0fd9f6c..7c9f393da2 100644 --- a/mcs/class/corlib/System.Runtime/GCLatencyMode.cs +++ b/mcs/class/corlib/System.Runtime/GCLatencyMode.cs @@ -35,6 +35,7 @@ namespace System.Runtime Batch = 0, Interactive = 1, LowLatency = 2, - SustainedLowLatency = 3 + SustainedLowLatency = 3, + NoGCRegion = 4 } } diff --git a/mcs/class/corlib/System.Security.AccessControl/NativeObjectSecurity.cs b/mcs/class/corlib/System.Security.AccessControl/NativeObjectSecurity.cs index 7e83a6cacf..b951a8141d 100644 --- a/mcs/class/corlib/System.Security.AccessControl/NativeObjectSecurity.cs +++ b/mcs/class/corlib/System.Security.AccessControl/NativeObjectSecurity.cs @@ -129,6 +129,11 @@ namespace System.Security.AccessControl { Persist (name, includeSections, null); } + + internal void Persist (SafeHandle handle) + { + PersistModifications (handle); + } internal void PersistModifications (SafeHandle handle) { diff --git a/mcs/class/corlib/System.Security.Cryptography.X509Certificates/X509Certificate.cs b/mcs/class/corlib/System.Security.Cryptography.X509Certificates/X509Certificate.cs index 135b270e50..46398d8561 100644 --- a/mcs/class/corlib/System.Security.Cryptography.X509Certificates/X509Certificate.cs +++ b/mcs/class/corlib/System.Security.Cryptography.X509Certificates/X509Certificate.cs @@ -48,7 +48,7 @@ namespace System.Security.Cryptography.X509Certificates { // and/or Authenticode certs. However this class works with older // X509v1 certificates and non-authenticode (code signing) certs. [Serializable] -#if NET_2_1 +#if MOBILE public partial class X509Certificate { #else public partial class X509Certificate : IDeserializationCallback, ISerializable { diff --git a/mcs/class/corlib/System.Security.Cryptography.X509Certificates/X509ContentType.cs b/mcs/class/corlib/System.Security.Cryptography.X509Certificates/X509ContentType.cs index 42fca5acad..3467dc8038 100644 --- a/mcs/class/corlib/System.Security.Cryptography.X509Certificates/X509ContentType.cs +++ b/mcs/class/corlib/System.Security.Cryptography.X509Certificates/X509ContentType.cs @@ -37,7 +37,7 @@ namespace System.Security.Cryptography.X509Certificates { enum X509ContentType { Unknown, Cert, - // not supported by Silverlight 2.0 (NET_2_1) + // not supported by Silverlight 2.0 (MOBILE) SerializedCert, Pfx, SerializedStore, diff --git a/mcs/class/corlib/System.Security.Cryptography.X509Certificates/X509Helper.cs b/mcs/class/corlib/System.Security.Cryptography.X509Certificates/X509Helper.cs index c12fa6229c..8bdd3db4da 100644 --- a/mcs/class/corlib/System.Security.Cryptography.X509Certificates/X509Helper.cs +++ b/mcs/class/corlib/System.Security.Cryptography.X509Certificates/X509Helper.cs @@ -32,7 +32,7 @@ using System; using System.Text; using System.Threading; using System.Runtime.InteropServices; -#if !NET_2_1 +#if !MOBILE using System.Security.Permissions; #endif using MX = Mono.Security.X509; @@ -49,7 +49,7 @@ namespace System.Security.Cryptography.X509Certificates Interlocked.CompareExchange (ref nativeHelper, helper, null); } -#if !NET_2_1 +#if !MOBILE // typedef struct _CERT_CONTEXT { // DWORD dwCertEncodingType; // BYTE *pbCertEncoded; diff --git a/mcs/class/corlib/System.Security.Cryptography.X509Certificates/X509KeyStorageFlags.cs b/mcs/class/corlib/System.Security.Cryptography.X509Certificates/X509KeyStorageFlags.cs index ce375c2aea..9d4c286415 100644 --- a/mcs/class/corlib/System.Security.Cryptography.X509Certificates/X509KeyStorageFlags.cs +++ b/mcs/class/corlib/System.Security.Cryptography.X509Certificates/X509KeyStorageFlags.cs @@ -35,7 +35,7 @@ namespace System.Security.Cryptography.X509Certificates { [ComVisible (true)] public enum X509KeyStorageFlags { DefaultKeySet = 0, - // not supported by Silverlight 2.0 (NET_2_1) + // not supported by Silverlight 2.0 (MOBILE) UserKeySet = 1, MachineKeySet = 2, Exportable = 4, diff --git a/mcs/class/corlib/System.Security.Cryptography/CryptoConfig_2_1.cs b/mcs/class/corlib/System.Security.Cryptography/CryptoConfig.common.cs similarity index 100% rename from mcs/class/corlib/System.Security.Cryptography/CryptoConfig_2_1.cs rename to mcs/class/corlib/System.Security.Cryptography/CryptoConfig.common.cs diff --git a/mcs/class/corlib/System.Security.Cryptography/CryptoConfig.cs b/mcs/class/corlib/System.Security.Cryptography/CryptoConfig.cs index 35a574660c..4f20771c40 100644 --- a/mcs/class/corlib/System.Security.Cryptography/CryptoConfig.cs +++ b/mcs/class/corlib/System.Security.Cryptography/CryptoConfig.cs @@ -73,7 +73,10 @@ public partial class CryptoConfig { static Type defaultMAC3DES = typeof (MACTripleDES); // LAMESPEC: undocumented classes (also undocumented in CryptoConfig ;-) static Type defaultDSASigDesc = typeof (DSASignatureDescription); - static Type defaultRSASigDesc = typeof (RSAPKCS1SHA1SignatureDescription); + static Type defaultRSAPKCS1SHA1SigDesc = typeof (RSAPKCS1SHA1SignatureDescription); + static Type defaultRSAPKCS1SHA256SigDesc = typeof (RSAPKCS1SHA256SignatureDescription); + static Type defaultRSAPKCS1SHA384SigDesc = typeof (RSAPKCS1SHA384SignatureDescription); + static Type defaultRSAPKCS1SHA512SigDesc = typeof (RSAPKCS1SHA512SignatureDescription); static Type defaultRIPEMD160 = typeof (RIPEMD160Managed); static Type defaultHMACMD5 = typeof (HMACMD5); static Type defaultHMACRIPEMD160 = typeof (HMACRIPEMD160); @@ -185,6 +188,9 @@ public partial class CryptoConfig { // LAMESPEC: undocumented URLs in CryptoConfig private const string urlDSASHA1 = urlXmlDsig + "dsa-sha1"; // no space private const string urlRSASHA1 = urlXmlDsig + "rsa-sha1"; // no space + private const string urlRSASHA256 = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"; // no space + private const string urlRSASHA384 = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha384"; // no space + private const string urlRSASHA512 = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512"; // no space private const string urlSHA1 = urlXmlDsig + "sha1"; // no space private const string urlC14N = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315"; private const string urlC14NWithComments = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"; @@ -196,6 +202,7 @@ public partial class CryptoConfig { private const string urlExcC14NWithComments = "http://www.w3.org/2001/10/xml-exc-c14n#WithComments"; private const string urlExcC14N = "http://www.w3.org/2001/10/xml-exc-c14n#"; private const string urlSHA256 = "http://www.w3.org/2001/04/xmlenc#sha256"; + private const string urlSHA384 = "http://www.w3.org/2001/04/xmldsig-more#sha384"; private const string urlSHA512 = "http://www.w3.org/2001/04/xmlenc#sha512"; private const string urlHMACSHA256 = "http://www.w3.org/2001/04/xmldsig-more#hmac-sha256"; private const string urlHMACSHA384 = "http://www.w3.org/2001/04/xmldsig-more#hmac-sha384"; @@ -360,7 +367,10 @@ public partial class CryptoConfig { // add some of the XMLDSIG urls into machine.config (and they make a LOT // of sense for implementing XMLDSIG in System.Security.Cryptography.Xml) algorithms.Add (urlDSASHA1, defaultDSASigDesc); - algorithms.Add (urlRSASHA1, defaultRSASigDesc); + algorithms.Add (urlRSASHA1, defaultRSAPKCS1SHA1SigDesc); + algorithms.Add (urlRSASHA256, defaultRSAPKCS1SHA256SigDesc); + algorithms.Add (urlRSASHA384, defaultRSAPKCS1SHA384SigDesc); + algorithms.Add (urlRSASHA512, defaultRSAPKCS1SHA512SigDesc); algorithms.Add (urlSHA1, defaultSHA1); unresolved_algorithms.Add (urlC14N, defaultC14N); unresolved_algorithms.Add (urlC14NWithComments, defaultC14NWithComments); @@ -372,7 +382,7 @@ public partial class CryptoConfig { unresolved_algorithms.Add (urlExcC14NWithComments, defaultExcC14NWithComments); unresolved_algorithms.Add (urlXmlDecryption, defaultXmlDecryption); algorithms.Add (urlSHA256, defaultSHA256); - // xmlenc does not include a definition for SHA384 + algorithms.Add (urlSHA384, defaultSHA384); algorithms.Add (urlSHA512, defaultSHA512); algorithms.Add (urlHMACSHA256, defaultHMACSHA256); algorithms.Add (urlHMACSHA384, defaultHMACSHA384); @@ -406,6 +416,15 @@ public partial class CryptoConfig { unresolved_algorithms.Add (nameECDsa_2, defaultECDsa); unresolved_algorithms.Add (nameECDsa_3, defaultECDsa); +#if MONODROID + algorithms.Add (nameSHA1Cng, defaultSHA1); + algorithms.Add (nameSHA256Cng, defaultSHA256); + algorithms.Add (nameSHA256Provider, defaultSHA256); + algorithms.Add (nameSHA384Cng, defaultSHA384); + algorithms.Add (nameSHA384Provider, defaultSHA384); + algorithms.Add (nameSHA512Cng, defaultSHA512); + algorithms.Add (nameSHA512Provider, defaultSHA512); +#else unresolved_algorithms.Add (nameSHA1Cng, defaultSHA1Cng); unresolved_algorithms.Add (nameSHA256Cng, defaultSHA256Cng); unresolved_algorithms.Add (nameSHA256Provider, defaultSHA256Provider); @@ -413,6 +432,7 @@ public partial class CryptoConfig { unresolved_algorithms.Add (nameSHA384Provider, defaultSHA384Provider); unresolved_algorithms.Add (nameSHA512Cng, defaultSHA512Cng); unresolved_algorithms.Add (nameSHA512Provider, defaultSHA512Provider); +#endif Dictionary oid = new Dictionary (StringComparer.OrdinalIgnoreCase); // comments here are to match with MS implementation (but not with doc) @@ -421,6 +441,7 @@ public partial class CryptoConfig { oid.Add (managedSHA1, oidSHA1); oid.Add (nameSHA1b, oidSHA1); oid.Add (nameSHA1c, oidSHA1); + oid.Add (nameSHA1Cng, oidSHA1); oid.Add (nameMD5, oidMD5); oid.Add (nameMD5a, oidMD5); @@ -429,14 +450,20 @@ public partial class CryptoConfig { oid.Add (nameSHA256, oidSHA256); oid.Add (nameSHA256a, oidSHA256); oid.Add (nameSHA256c, oidSHA256); + oid.Add (nameSHA256Cng, oidSHA256); + oid.Add (nameSHA256Provider, oidSHA256); oid.Add (nameSHA384, oidSHA384); oid.Add (nameSHA384a, oidSHA384); oid.Add (nameSHA384c, oidSHA384); + oid.Add (nameSHA384Cng, oidSHA384); + oid.Add (nameSHA384Provider, oidSHA384); oid.Add (nameSHA512, oidSHA512); oid.Add (nameSHA512a, oidSHA512); oid.Add (nameSHA512c, oidSHA512); + oid.Add (nameSHA512Cng, oidSHA512); + oid.Add (nameSHA512Provider, oidSHA512); oid.Add (nameRIPEMD160, oidRIPEMD160); oid.Add (nameRIPEMD160a, oidRIPEMD160); diff --git a/mcs/class/corlib/System.Security.Cryptography/CryptoConfig.fullaot.cs b/mcs/class/corlib/System.Security.Cryptography/CryptoConfig.fullaot.cs index 9282679690..9ae2a61b75 100755 --- a/mcs/class/corlib/System.Security.Cryptography/CryptoConfig.fullaot.cs +++ b/mcs/class/corlib/System.Security.Cryptography/CryptoConfig.fullaot.cs @@ -44,6 +44,16 @@ namespace System.Security.Cryptography { [ComVisible (true)] public partial class CryptoConfig { + public static void AddAlgorithm (Type algorithm, params string[] names) + { + throw new PlatformNotSupportedException (); + } + + public static void AddOID (string oid, params string[] names) + { + throw new PlatformNotSupportedException (); + } + // try to avoid hitting the CreateFromName overloads to help the linker public static object CreateFromName (string name) @@ -133,9 +143,19 @@ namespace System.Security.Cryptography { case "system.security.cryptography.rsapkcs1sha1signaturedescription": case "http://www.w3.org/2000/09/xmldsig#rsa-sha1": return new RSAPKCS1SHA1SignatureDescription (); + case "system.security.cryptography.rsapkcs1sha256signaturedescription": + case "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256": + return new RSAPKCS1SHA256SignatureDescription (); + case "system.security.cryptography.rsapkcs1sha384signaturedescription": + case "http://www.w3.org/2001/04/xmldsig-more#rsa-sha384": + return new RSAPKCS1SHA384SignatureDescription (); + case "system.security.cryptography.rsapkcs1sha512signaturedescription": + case "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512": + return new RSAPKCS1SHA512SignatureDescription (); case "system.security.cryptography.hashalgorithm": case "system.security.cryptography.sha1": case "system.security.cryptography.sha1cryptoserviceprovider": + case "system.security.cryptography.sha1cng": case "sha1": case "sha": case "http://www.w3.org/2000/09/xmldsig#sha1": @@ -144,17 +164,24 @@ namespace System.Security.Cryptography { return new SHA1Managed (); case "system.security.cryptography.sha256managed": case "system.security.cryptography.sha256": + case "system.security.cryptography.sha256cryptoserviceprovider": + case "system.security.cryptography.sha256cng": case "sha256": case "sha-256": case "http://www.w3.org/2001/04/xmlenc#sha256": return new SHA256Managed (); case "system.security.cryptography.sha384managed": case "system.security.cryptography.sha384": + case "system.security.cryptography.sha384cryptoserviceprovider": + case "system.security.cryptography.sha384cng": case "sha384": case "sha-384": + case "http://www.w3.org/2001/04/xmldsig-more#sha384": return new SHA384Managed (); case "system.security.cryptography.sha512managed": case "system.security.cryptography.sha512": + case "system.security.cryptography.sha512cryptoserviceprovider": + case "system.security.cryptography.sha512cng": case "sha512": case "sha-512": case "http://www.w3.org/2001/04/xmlenc#sha512": @@ -201,6 +228,7 @@ namespace System.Security.Cryptography { switch (name.ToLowerInvariant ()) { case "system.security.cryptography.sha1cryptoserviceprovider": + case "system.security.cryptography.sha1cng": case "system.security.cryptography.sha1managed": case "system.security.cryptography.sha1": case "sha1": @@ -209,14 +237,20 @@ namespace System.Security.Cryptography { case "system.security.cryptography.md5": case "md5": return "1.2.840.113549.2.5"; + case "system.security.cryptography.sha256cryptoserviceprovider": + case "system.security.cryptography.sha256cng": case "system.security.cryptography.sha256managed": case "system.security.cryptography.sha256": case "sha256": return "2.16.840.1.101.3.4.2.1"; + case "system.security.cryptography.sha384cryptoserviceprovider": + case "system.security.cryptography.sha384cng": case "system.security.cryptography.sha384managed": case "system.security.cryptography.sha384": case "sha384": return "2.16.840.1.101.3.4.2.2"; + case "system.security.cryptography.sha512cryptoserviceprovider": + case "system.security.cryptography.sha512cng": case "system.security.cryptography.sha512managed": case "system.security.cryptography.sha512": case "sha512": diff --git a/mcs/class/System.Core/System.Security.Cryptography/IncrementalHash.cs b/mcs/class/corlib/System.Security.Cryptography/IncrementalHash.cs similarity index 98% rename from mcs/class/System.Core/System.Security.Cryptography/IncrementalHash.cs rename to mcs/class/corlib/System.Security.Cryptography/IncrementalHash.cs index 14c895e597..d52ed93fac 100644 --- a/mcs/class/System.Core/System.Security.Cryptography/IncrementalHash.cs +++ b/mcs/class/corlib/System.Security.Cryptography/IncrementalHash.cs @@ -32,7 +32,7 @@ namespace System.Security.Cryptography { public sealed class IncrementalHash : IDisposable { - private IncrementalHash () { } + public IncrementalHash () { } public HashAlgorithmName AlgorithmName { get { throw new NotImplementedException (); } } public void AppendData (byte[] data) { } public void AppendData (byte[] data, int offset, int count) { } diff --git a/mcs/class/corlib/System.Security.Cryptography/RNGCryptoServiceProvider.cs b/mcs/class/corlib/System.Security.Cryptography/RNGCryptoServiceProvider.cs index 29e40efbad..7abdbecd11 100644 --- a/mcs/class/corlib/System.Security.Cryptography/RNGCryptoServiceProvider.cs +++ b/mcs/class/corlib/System.Security.Cryptography/RNGCryptoServiceProvider.cs @@ -40,7 +40,7 @@ using System.Text; namespace System.Security.Cryptography { -#if !NET_2_1 +#if !MOBILE [ComVisible (true)] #endif public sealed class RNGCryptoServiceProvider : RandomNumberGenerator { @@ -58,7 +58,7 @@ namespace System.Security.Cryptography { _handle = RngInitialize (null); Check (); } -#if !NET_2_1 + public RNGCryptoServiceProvider (byte[] rgb) { _handle = RngInitialize (rgb); @@ -81,7 +81,7 @@ namespace System.Security.Cryptography { _handle = RngInitialize (Encoding.UTF8.GetBytes (str)); Check (); } -#endif + private void Check () { if (_handle == IntPtr.Zero) { diff --git a/mcs/class/corlib/System.Security.Cryptography/RSACryptoServiceProvider.cs b/mcs/class/corlib/System.Security.Cryptography/RSACryptoServiceProvider.cs index 53667fb87d..a8ebc812da 100644 --- a/mcs/class/corlib/System.Security.Cryptography/RSACryptoServiceProvider.cs +++ b/mcs/class/corlib/System.Security.Cryptography/RSACryptoServiceProvider.cs @@ -36,8 +36,7 @@ using Mono.Security.Cryptography; namespace System.Security.Cryptography { - [ComVisible (true)] - public sealed class RSACryptoServiceProvider : RSA, ICspAsymmetricAlgorithm { + public partial class RSACryptoServiceProvider { private const int PROV_RSA_FULL = 1; // from WinCrypt.h private const int AT_KEYEXCHANGE = 1; private const int AT_SIGNATURE = 2; @@ -102,7 +101,7 @@ namespace System.Security.Cryptography { // no need to load - it cannot exists var p = new CspParameters (PROV_RSA_FULL); - if (useMachineKeyStore) + if (UseMachineKeyStore) p.Flags |= CspProviderFlags.UseMachineKeyStore; store = new KeyPairPersistence (p); } @@ -121,13 +120,6 @@ namespace System.Security.Cryptography { FromXmlString (store.KeyValue); } } - - private static bool useMachineKeyStore; - - public static bool UseMachineKeyStore { - get { return useMachineKeyStore; } - set { useMachineKeyStore = value; } - } ~RSACryptoServiceProvider () { @@ -161,11 +153,7 @@ namespace System.Security.Cryptography { public bool PublicOnly { get { return rsa.PublicOnly; } } - - public override string SignatureAlgorithm { - get { return "http://www.w3.org/2000/09/xmldsig#rsa-sha1"; } - } - + public byte[] Decrypt (byte[] rgb, bool fOAEP) { if (rgb == null) @@ -339,6 +327,29 @@ namespace System.Security.Cryptography { return PKCS1.Sign_v15 (this, hash, rgbHash); } + byte[] SignHash(byte[] rgbHash, int calgHash) + { + return PKCS1.Sign_v15 (this, InternalHashToHashAlgorithm (calgHash), rgbHash); + } + + static HashAlgorithm InternalHashToHashAlgorithm (int calgHash) + { + switch (calgHash) { + case Constants.CALG_MD5: + return MD5.Create (); + case Constants.CALG_SHA1: + return SHA1.Create (); + case Constants.CALG_SHA_256: + return SHA256.Create (); + case Constants.CALG_SHA_384: + return SHA384.Create (); + case Constants.CALG_SHA_512: + return SHA512.Create (); + } + + throw new NotImplementedException (calgHash.ToString ()); + } + // NOTE: this method can work with ANY configured (OID in machine.config) // HashAlgorithm descendant public bool VerifyData (byte[] buffer, object halg, byte[] signature) @@ -364,6 +375,11 @@ namespace System.Security.Cryptography { HashAlgorithm hash = HashAlgorithm.Create (hashName); return PKCS1.Verify_v15 (this, hash, rgbHash, rgbSignature); } + + bool VerifyHash(byte[] rgbHash, int calgHash, byte[] rgbSignature) + { + return PKCS1.Verify_v15 (this, InternalHashToHashAlgorithm (calgHash), rgbHash, rgbSignature); + } protected override void Dispose (bool disposing) { @@ -444,7 +460,7 @@ namespace System.Security.Cryptography { var p = new CspParameters (PROV_RSA_FULL); p.KeyNumber = keyBlob [5] == 0x24 ? AT_SIGNATURE : AT_KEYEXCHANGE; - if (useMachineKeyStore) + if (UseMachineKeyStore) p.Flags |= CspProviderFlags.UseMachineKeyStore; store = new KeyPairPersistence (p); } diff --git a/mcs/class/corlib/System.Security.Permissions/CodeAccessSecurityAttribute.cs b/mcs/class/corlib/System.Security.Permissions/CodeAccessSecurityAttribute.cs index 5714862cbd..05f56decf4 100644 --- a/mcs/class/corlib/System.Security.Permissions/CodeAccessSecurityAttribute.cs +++ b/mcs/class/corlib/System.Security.Permissions/CodeAccessSecurityAttribute.cs @@ -31,7 +31,7 @@ using System.Runtime.InteropServices; namespace System.Security.Permissions { -#if NET_2_1 && !MONOTOUCH +#if MOBILE && !MONOTOUCH [Obsolete ("CAS support is not available with Silverlight applications.")] #endif [ComVisible (true)] diff --git a/mcs/class/corlib/System.Security.Permissions/EnvironmentPermissionAttribute.cs b/mcs/class/corlib/System.Security.Permissions/EnvironmentPermissionAttribute.cs index 3e1c714e37..d943508a99 100644 --- a/mcs/class/corlib/System.Security.Permissions/EnvironmentPermissionAttribute.cs +++ b/mcs/class/corlib/System.Security.Permissions/EnvironmentPermissionAttribute.cs @@ -71,7 +71,7 @@ namespace System.Security.Permissions { // Methods public override IPermission CreatePermission () { -#if NET_2_1 +#if MOBILE return null; #else EnvironmentPermission perm = null; diff --git a/mcs/class/corlib/System.Security.Permissions/FileIOPermissionAttribute.cs b/mcs/class/corlib/System.Security.Permissions/FileIOPermissionAttribute.cs index 5f7fbff2d8..3a3250d47d 100644 --- a/mcs/class/corlib/System.Security.Permissions/FileIOPermissionAttribute.cs +++ b/mcs/class/corlib/System.Security.Permissions/FileIOPermissionAttribute.cs @@ -120,7 +120,7 @@ namespace System.Security.Permissions { // Methods public override IPermission CreatePermission () { -#if NET_2_1 +#if MOBILE return null; #else FileIOPermission perm = null; diff --git a/mcs/class/corlib/System.Security.Permissions/HostProtectionAttribute.cs b/mcs/class/corlib/System.Security.Permissions/HostProtectionAttribute.cs index dd7aa04d3d..3afcb62ede 100644 --- a/mcs/class/corlib/System.Security.Permissions/HostProtectionAttribute.cs +++ b/mcs/class/corlib/System.Security.Permissions/HostProtectionAttribute.cs @@ -175,7 +175,7 @@ namespace System.Security.Permissions { public override IPermission CreatePermission () { -#if NET_2_1 +#if MOBILE return null; #else // looks like permission is internal diff --git a/mcs/class/corlib/System.Security.Permissions/PermissionSetAttribute.cs b/mcs/class/corlib/System.Security.Permissions/PermissionSetAttribute.cs index 3e8381721b..aa6999b8a2 100644 --- a/mcs/class/corlib/System.Security.Permissions/PermissionSetAttribute.cs +++ b/mcs/class/corlib/System.Security.Permissions/PermissionSetAttribute.cs @@ -90,7 +90,7 @@ namespace System.Security.Permissions { private PermissionSet CreateFromXml (string xml) { -#if !NET_2_1 +#if !MOBILE SecurityParser sp = new SecurityParser (); try { sp.LoadXml (xml); @@ -125,7 +125,7 @@ namespace System.Security.Permissions { public PermissionSet CreatePermissionSet () { PermissionSet pset = null; -#if !NET_2_1 +#if !MOBILE if (this.Unrestricted) pset = new PermissionSet (PermissionState.Unrestricted); else { diff --git a/mcs/class/corlib/System.Security.Permissions/ReflectionPermissionAttribute.cs b/mcs/class/corlib/System.Security.Permissions/ReflectionPermissionAttribute.cs index 68d85e8106..8680139527 100644 --- a/mcs/class/corlib/System.Security.Permissions/ReflectionPermissionAttribute.cs +++ b/mcs/class/corlib/System.Security.Permissions/ReflectionPermissionAttribute.cs @@ -113,7 +113,7 @@ namespace System.Security.Permissions { // Methods public override IPermission CreatePermission () { -#if NET_2_1 +#if MOBILE return null; #else ReflectionPermission perm = null; diff --git a/mcs/class/corlib/System.Security.Permissions/SecurityAction.cs b/mcs/class/corlib/System.Security.Permissions/SecurityAction.cs index 94d14df749..2af0d262ae 100644 --- a/mcs/class/corlib/System.Security.Permissions/SecurityAction.cs +++ b/mcs/class/corlib/System.Security.Permissions/SecurityAction.cs @@ -35,7 +35,7 @@ using System.Runtime.InteropServices; namespace System.Security.Permissions { -#if NET_2_1 && !MONOTOUCH +#if MOBILE && !MONOTOUCH [Obsolete ("CAS support is not available with Silverlight applications.")] #endif [ComVisible (true)] diff --git a/mcs/class/corlib/System.Security.Permissions/SecurityAttribute.cs b/mcs/class/corlib/System.Security.Permissions/SecurityAttribute.cs index f871175e42..276a914439 100644 --- a/mcs/class/corlib/System.Security.Permissions/SecurityAttribute.cs +++ b/mcs/class/corlib/System.Security.Permissions/SecurityAttribute.cs @@ -31,7 +31,7 @@ using System.Runtime.InteropServices; namespace System.Security.Permissions { -#if NET_2_1 && !MONOTOUCH +#if MOBILE && !MONOTOUCH [Obsolete ("CAS support is not available with Silverlight applications.")] #endif [ComVisible (true)] diff --git a/mcs/class/corlib/System.Security.Permissions/SecurityPermissionAttribute.cs b/mcs/class/corlib/System.Security.Permissions/SecurityPermissionAttribute.cs index cf37722731..3cdc150e8d 100644 --- a/mcs/class/corlib/System.Security.Permissions/SecurityPermissionAttribute.cs +++ b/mcs/class/corlib/System.Security.Permissions/SecurityPermissionAttribute.cs @@ -31,7 +31,7 @@ using System.Runtime.InteropServices; namespace System.Security.Permissions { -#if NET_2_1 && !MONOTOUCH +#if MOBILE && !MONOTOUCH [Obsolete ("CAS support is not available with Silverlight applications.")] #endif [ComVisible (true)] @@ -251,7 +251,7 @@ namespace System.Security.Permissions { public override IPermission CreatePermission () { -#if NET_2_1 +#if MOBILE return null; #else SecurityPermission perm = null; diff --git a/mcs/class/corlib/System.Security.Permissions/SecurityPermissionFlag.cs b/mcs/class/corlib/System.Security.Permissions/SecurityPermissionFlag.cs index 9e5517bd40..f5c246e6b0 100644 --- a/mcs/class/corlib/System.Security.Permissions/SecurityPermissionFlag.cs +++ b/mcs/class/corlib/System.Security.Permissions/SecurityPermissionFlag.cs @@ -34,7 +34,7 @@ using System.Runtime.InteropServices; namespace System.Security.Permissions { -#if NET_2_1 && !MONOTOUCH +#if MOBILE && !MONOTOUCH [Obsolete ("CAS support is not available with Silverlight applications.")] #endif [ComVisible (true)] diff --git a/mcs/class/corlib/System.Security.Permissions/StrongNamePermissionAttribute.cs b/mcs/class/corlib/System.Security.Permissions/StrongNamePermissionAttribute.cs index c710c3d764..52a120d490 100644 --- a/mcs/class/corlib/System.Security.Permissions/StrongNamePermissionAttribute.cs +++ b/mcs/class/corlib/System.Security.Permissions/StrongNamePermissionAttribute.cs @@ -70,7 +70,7 @@ namespace System.Security.Permissions { // Methods public override IPermission CreatePermission () { -#if NET_2_1 +#if MOBILE return null; #else if (this.Unrestricted) diff --git a/mcs/class/corlib/System.Security.Policy/Evidence.cs b/mcs/class/corlib/System.Security.Policy/Evidence.cs index f8653aad20..66e6bec14e 100644 --- a/mcs/class/corlib/System.Security.Policy/Evidence.cs +++ b/mcs/class/corlib/System.Security.Policy/Evidence.cs @@ -225,7 +225,7 @@ namespace System.Security.Policy { // "possible" presence of an Authenticode signature [MethodImplAttribute (MethodImplOptions.InternalCall)] static extern bool IsAuthenticodePresent (Assembly a); -#if NET_2_1 +#if MOBILE static internal Evidence GetDefaultHostEvidence (Assembly a) { return new Evidence (); @@ -251,7 +251,7 @@ namespace System.Security.Policy { } // strongnamed assemblies gets a StrongName evidence - AssemblyName an = a.UnprotectedGetName (); + AssemblyName an = a.GetName (); byte[] pk = an.GetPublicKey (); if ((pk != null) && (pk.Length > 0)) { StrongNamePublicKeyBlob blob = new StrongNamePublicKeyBlob (pk); @@ -287,7 +287,7 @@ namespace System.Security.Policy { return e; } -#endif // NET_2_1 +#endif // MOBILE private class EvidenceEnumerator : IEnumerator { diff --git a/mcs/class/corlib/System.Security.Policy/PolicyLevel.cs b/mcs/class/corlib/System.Security.Policy/PolicyLevel.cs index d78fe55eb0..4e1427fe1b 100644 --- a/mcs/class/corlib/System.Security.Policy/PolicyLevel.cs +++ b/mcs/class/corlib/System.Security.Policy/PolicyLevel.cs @@ -582,7 +582,7 @@ namespace System.Security.Policy { internal bool IsFullTrustAssembly (Assembly a) { - AssemblyName an = a.UnprotectedGetName (); + AssemblyName an = a.GetName (); StrongNamePublicKeyBlob snpkb = new StrongNamePublicKeyBlob (an.GetPublicKey ()); StrongNameMembershipCondition snMC = new StrongNameMembershipCondition (snpkb, an.Name, an.Version); foreach (StrongNameMembershipCondition sn in full_trust_assemblies) { diff --git a/mcs/class/corlib/System.Security.Policy/Zone.cs b/mcs/class/corlib/System.Security.Policy/Zone.cs index b65d55460d..64826f938e 100644 --- a/mcs/class/corlib/System.Security.Policy/Zone.cs +++ b/mcs/class/corlib/System.Security.Policy/Zone.cs @@ -83,7 +83,13 @@ namespace System.Security.Policy { if (url.Length == 0) return new Zone (z); - Uri uri = new Uri (url); + Uri uri = null; + try { + uri = new Uri (url); + } + catch { + return new Zone (z); + } // TODO: apply zone configuration // this is the only way to use the Trusted and Untrusted zones diff --git a/mcs/class/corlib/System.Security/SecurityManager.cs b/mcs/class/corlib/System.Security/SecurityManager.cs index 376e69998c..c933e5e46b 100644 --- a/mcs/class/corlib/System.Security/SecurityManager.cs +++ b/mcs/class/corlib/System.Security/SecurityManager.cs @@ -29,7 +29,7 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -#if !NET_2_1 +#if !MOBILE using System.Collections; using System.Diagnostics; diff --git a/mcs/class/corlib/System.Threading/EventWaitHandle.cs b/mcs/class/corlib/System.Threading/EventWaitHandle.cs deleted file mode 100644 index fba21dc3ce..0000000000 --- a/mcs/class/corlib/System.Threading/EventWaitHandle.cs +++ /dev/null @@ -1,235 +0,0 @@ -// -// System.Threading.EventWaitHandle.cs -// -// Author: -// Dick Porter (dick@ximian.com) -// -// (C) Ximian, Inc. (http://www.ximian.com) -// Copyright (C) 2005 Novell, Inc (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// - -using System.IO; -using System.Runtime.InteropServices; -using System.Security.AccessControl; - -namespace System.Threading -{ - [ComVisible (true)] - public class EventWaitHandle : WaitHandle - { - private EventWaitHandle (IntPtr handle) - { - Handle = handle; - } - - static bool IsManualReset (EventResetMode mode) - { - if ((mode < EventResetMode.AutoReset) || (mode > EventResetMode.ManualReset)) - throw new ArgumentException ("mode"); - return (mode == EventResetMode.ManualReset); - } - - public EventWaitHandle (bool initialState, EventResetMode mode) - { - bool created; - bool manual = IsManualReset (mode); - Handle = NativeEventCalls.CreateEvent_internal (manual, initialState, null, out created); - } - -#if !MOBILE - - public EventWaitHandle (bool initialState, EventResetMode mode, - string name) - { - bool created; - bool manual = IsManualReset (mode); - Handle = NativeEventCalls.CreateEvent_internal (manual, initialState, name, out created); - } - - public EventWaitHandle (bool initialState, EventResetMode mode, - string name, out bool createdNew) - { - bool manual = IsManualReset (mode); - Handle = NativeEventCalls.CreateEvent_internal (manual, initialState, name, out createdNew); - } - - - [MonoTODO ("Use access control in CreateEvent_internal")] - public EventWaitHandle (bool initialState, EventResetMode mode, - string name, out bool createdNew, - EventWaitHandleSecurity eventSecurity) - { - bool manual = IsManualReset (mode); - Handle = NativeEventCalls.CreateEvent_internal (manual, initialState, name, out createdNew); - } - - public EventWaitHandleSecurity GetAccessControl () - { - return new EventWaitHandleSecurity (SafeWaitHandle, - AccessControlSections.Owner | - AccessControlSections.Group | - AccessControlSections.Access); - - } - - public static EventWaitHandle OpenExisting (string name) - { - return(OpenExisting (name, EventWaitHandleRights.Synchronize | EventWaitHandleRights.Modify)); - } - - public static EventWaitHandle OpenExisting (string name, EventWaitHandleRights rights) - { - if (name == null) { - throw new ArgumentNullException ("name"); - } - if ((name.Length == 0) || - (name.Length > 260)) { - throw new ArgumentException ("name", Locale.GetText ("Invalid length [1-260].")); - } - - MonoIOError error; - IntPtr handle = NativeEventCalls.OpenEvent_internal (name, rights, out error); - if (handle == (IntPtr)null) { - if (error == MonoIOError.ERROR_FILE_NOT_FOUND) { - throw new WaitHandleCannotBeOpenedException (Locale.GetText ("Named Event handle does not exist: ") + name); - } else if (error == MonoIOError.ERROR_ACCESS_DENIED) { - throw new UnauthorizedAccessException (); - } else { - throw new IOException (Locale.GetText ("Win32 IO error: ") + error.ToString ()); - } - } - - return(new EventWaitHandle (handle)); - } - - public static bool TryOpenExisting (string name, out EventWaitHandle result) - { - return TryOpenExisting ( - name, EventWaitHandleRights.Synchronize | EventWaitHandleRights.Modify, out result); - } - - public static bool TryOpenExisting (string name, EventWaitHandleRights rights, - out EventWaitHandle result) - { - if (name == null) { - throw new ArgumentNullException ("name"); - } - if ((name.Length == 0) || (name.Length > 260)) { - throw new ArgumentException ("name", Locale.GetText ("Invalid length [1-260].")); - } - - MonoIOError error; - IntPtr handle = NativeEventCalls.OpenEvent_internal (name, rights, out error); - if (handle == (IntPtr)null) { - result = null; - return false; - } - - result = new EventWaitHandle (handle); - return true; - } -#else - public EventWaitHandle (bool initialState, EventResetMode mode, string name) - { - throw new NotSupportedException (); - } - - public EventWaitHandle (bool initialState, EventResetMode mode, - string name, out bool createdNew) - { - throw new NotSupportedException (); - } - - - public EventWaitHandle (bool initialState, EventResetMode mode, - string name, out bool createdNew, - EventWaitHandleSecurity eventSecurity) - { - throw new NotSupportedException (); - } - - public static EventWaitHandle OpenExisting (string name) - { - throw new NotSupportedException (); - } - - public static EventWaitHandle OpenExisting (string name, EventWaitHandleRights rights) - { - throw new NotSupportedException (); - } - - public static bool TryOpenExisting (string name, out EventWaitHandle result) - { - throw new NotSupportedException (); - } - - public static bool TryOpenExisting (string name, EventWaitHandleRights rights, - out EventWaitHandle result) - { - throw new NotSupportedException (); - } -#endif - - public bool Reset () - { - /* This needs locking since another thread could dispose the handle */ - lock (this) { - CheckDisposed (); - - return NativeEventCalls.ResetEvent (SafeWaitHandle); - } - } - - public bool Set () - { - lock (this) { - CheckDisposed (); - - return NativeEventCalls.SetEvent (SafeWaitHandle); - } - } - - internal void CheckDisposed () - { - if (disposed) - throw new ObjectDisposedException (GetType ().FullName); - } - - bool disposed; - protected override void Dispose(bool explicitDisposing) - { - base.Dispose (explicitDisposing); - disposed = true; - } - -#if !NET_2_1 - public void SetAccessControl (EventWaitHandleSecurity eventSecurity) - { - if (null == eventSecurity) - throw new ArgumentNullException ("eventSecurity"); - - eventSecurity.PersistModifications (SafeWaitHandle); - - } -#endif - } -} diff --git a/mcs/class/corlib/System.Threading/Mutex.cs b/mcs/class/corlib/System.Threading/Mutex.cs index 6216e31013..9c88bce4d9 100644 --- a/mcs/class/corlib/System.Threading/Mutex.cs +++ b/mcs/class/corlib/System.Threading/Mutex.cs @@ -206,7 +206,7 @@ namespace System.Threading } } -#if !NET_2_1 +#if !MOBILE public void SetAccessControl (MutexSecurity mutexSecurity) { if (null == mutexSecurity) diff --git a/mcs/class/corlib/System.Threading/NativeEventCalls.cs b/mcs/class/corlib/System.Threading/NativeEventCalls.cs index b0320579bf..fc5a9f59ba 100644 --- a/mcs/class/corlib/System.Threading/NativeEventCalls.cs +++ b/mcs/class/corlib/System.Threading/NativeEventCalls.cs @@ -45,7 +45,7 @@ namespace System.Threading internal static class NativeEventCalls { [MethodImplAttribute(MethodImplOptions.InternalCall)] - public static extern IntPtr CreateEvent_internal(bool manual,bool initial,string name, out bool created); + public static extern IntPtr CreateEvent_internal (bool manual, bool initial, string name, out int errorCode); public static bool SetEvent (SafeWaitHandle handle) { @@ -82,7 +82,7 @@ namespace System.Threading #if !MOBILE [MethodImplAttribute (MethodImplOptions.InternalCall)] - public static extern IntPtr OpenEvent_internal (string name, EventWaitHandleRights rights, out MonoIOError error); + public static extern IntPtr OpenEvent_internal (string name, EventWaitHandleRights rights, out int errorCode); #endif } } diff --git a/mcs/class/corlib/System.Threading/Thread.cs b/mcs/class/corlib/System.Threading/Thread.cs index e10918121d..4a7fca93bc 100644 --- a/mcs/class/corlib/System.Threading/Thread.cs +++ b/mcs/class/corlib/System.Threading/Thread.cs @@ -65,7 +65,6 @@ namespace System.Threading { /* start_notify is used by the runtime to signal that Start() * is ok to return */ - private IntPtr start_notify; private IntPtr stack_ptr; private UIntPtr static_data; /* GC-tracked */ private IntPtr runtime_thread_info; @@ -90,12 +89,19 @@ namespace System.Threading { private IntPtr interrupt_on_stop; private IntPtr flags; private IntPtr thread_pinning_ref; + private IntPtr abort_protected_block_count; /* * These fields are used to avoid having to increment corlib versions * when a new field is added to the unmanaged MonoThread structure. */ private IntPtr unused1; private IntPtr unused2; + + /* This is used only to check that we are in sync between the representation + * of MonoInternalThread in native and InternalThread in managed + * + * DO NOT RENAME! DO NOT ADD FIELDS AFTER! */ + private IntPtr last; #endregion #pragma warning restore 169, 414, 649 @@ -116,15 +122,12 @@ namespace System.Threading { private InternalThread internal_thread; object m_ThreadStartArg; object pending_exception; + int priority = (int) ThreadPriority.Normal; #endregion #pragma warning restore 414 IPrincipal principal; int principal_version; - bool current_culture_set; - bool current_ui_culture_set; - CultureInfo current_culture; - CultureInfo current_ui_culture; // the name of current_thread is // important because they are used by the runtime. @@ -132,9 +135,6 @@ namespace System.Threading { [ThreadStatic] static Thread current_thread; - static internal CultureInfo default_culture; - static internal CultureInfo default_ui_culture; - // can be both a ThreadStart and a ParameterizedThreadStart private MulticastDelegate m_Delegate; @@ -339,54 +339,6 @@ namespace System.Threading { } } - //[MethodImplAttribute (MethodImplOptions.InternalCall)] - //private static extern int current_lcid (); - - public CultureInfo CurrentCulture { - get { - CultureInfo culture = current_culture; - if (current_culture_set && culture != null) - return culture; - - if (default_culture != null) - return default_culture; - - current_culture = culture = CultureInfo.ConstructCurrentCulture (); - return culture; - } - - [SecurityPermission (SecurityAction.Demand, ControlThread=true)] - set { - if (value == null) - throw new ArgumentNullException ("value"); - - value.CheckNeutral (); - current_culture = value; - current_culture_set = true; - } - } - - public CultureInfo CurrentUICulture { - get { - CultureInfo culture = current_ui_culture; - if (current_ui_culture_set && culture != null) - return culture; - - if (default_ui_culture != null) - return default_ui_culture; - - current_ui_culture = culture = CultureInfo.ConstructCurrentUICulture (); - return culture; - } - - set { - if (value == null) - throw new ArgumentNullException ("value"); - current_ui_culture = value; - current_ui_culture_set = true; - } - } - public bool IsThreadPoolThread { get { return IsThreadPoolThreadInternal; @@ -507,6 +459,12 @@ namespace System.Threading { { throw new PlatformNotSupportedException ("Thread.ResetAbort is not supported on the current platform."); } + + internal object AbortReason { + get { + throw new PlatformNotSupportedException ("Thread.ResetAbort is not supported on the current platform."); + } + } #endif // MONO_FEATURE_THREAD_ABORT [MethodImplAttribute (MethodImplOptions.InternalCall)] @@ -722,11 +680,6 @@ namespace System.Threading { return ManagedThreadId; } - internal CultureInfo GetCurrentUICultureNoAppX () - { - return CultureInfo.CurrentUICulture; - } - [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern void GetStackTraces (out Thread[] threads, out object[] stack_frames); @@ -756,5 +709,10 @@ namespace System.Threading { throw new PlatformNotSupportedException ("Thread.Resume is not supported on the current platform."); } #endif + + public void DisableComObjectEagerCleanup () + { + throw new PlatformNotSupportedException (); + } } } diff --git a/mcs/class/corlib/System/AppDomain.cs b/mcs/class/corlib/System/AppDomain.cs index 13cc078e57..ea12a7f346 100644 --- a/mcs/class/corlib/System/AppDomain.cs +++ b/mcs/class/corlib/System/AppDomain.cs @@ -116,7 +116,7 @@ namespace System { [MethodImplAttribute (MethodImplOptions.InternalCall)] private extern AppDomainSetup getSetup (); -#if NET_2_1 +#if MOBILE internal #endif AppDomainSetup SetupInformationNoCopy { @@ -130,7 +130,7 @@ namespace System { } } -#if !NET_2_1 +#if !MOBILE [MonoTODO] public ApplicationTrust ApplicationTrust { get { throw new NotImplementedException (); } @@ -139,7 +139,7 @@ namespace System { public string BaseDirectory { get { string path = SetupInformationNoCopy.ApplicationBase; -#if !NET_2_1 +#if !MOBILE if (SecurityManager.SecurityEnabled && (path != null) && (path.Length > 0)) { // we cannot divulge local file informations new FileIOPermission (FileIOPermissionAccess.PathDiscovery, path).Demand (); @@ -152,7 +152,7 @@ namespace System { public string RelativeSearchPath { get { string path = SetupInformationNoCopy.PrivateBinPath; -#if !NET_2_1 +#if !MOBILE if (SecurityManager.SecurityEnabled && (path != null) && (path.Length > 0)) { // we cannot divulge local file informations new FileIOPermission (FileIOPermissionAccess.PathDiscovery, path).Demand (); @@ -169,7 +169,7 @@ namespace System { return null; string path = Path.Combine (setup.DynamicBase, setup.ApplicationName); -#if !NET_2_1 +#if !MOBILE if (SecurityManager.SecurityEnabled && (path != null) && (path.Length > 0)) { // we cannot divulge local file informations new FileIOPermission (FileIOPermissionAccess.PathDiscovery, path).Demand (); @@ -311,7 +311,7 @@ namespace System { SetupInformationNoCopy.ShadowCopyDirectories = String.Empty; } -#if !NET_2_1 +#if !MOBILE public ObjectHandle CreateComInstanceFrom (string assemblyName, string typeName) { return Activator.CreateComInstanceFrom (assemblyName, typeName); @@ -1027,7 +1027,7 @@ namespace System { } else if (info.ConfigurationFile == null) info.ConfigurationFile = "[I don't have a config file]"; -#if !NET_2_1 +#if !MOBILE if (info.AppDomainInitializer != null) { if (!info.AppDomainInitializer.Method.IsStatic) throw new ArgumentException ("Non-static methods cannot be invoked as an appdomain initializer"); @@ -1047,7 +1047,7 @@ namespace System { else ad._evidence = new Evidence (securityInfo); // copy -#if !NET_2_1 +#if !MOBILE if (info.AppDomainInitializer != null) { Loader loader = new Loader ( info.AppDomainInitializer.Method.DeclaringType.Assembly.Location); @@ -1082,7 +1082,7 @@ namespace System { } #endif // MONO_FEATURE_MULTIPLE_APPDOMAINS -#if !NET_2_1 +#if !MOBILE [Serializable] class Loader { @@ -1133,7 +1133,7 @@ namespace System { } #endif // MONO_FEATURE_MULTIPLE_APPDOMAINS -#if !NET_2_1 +#if !MOBILE #if MONO_FEATURE_MULTIPLE_APPDOMAINS public static AppDomain CreateDomain (string friendlyName, Evidence securityInfo, AppDomainSetup info, PermissionSet grantSet, params StrongName [] fullTrustAssemblies) @@ -1217,14 +1217,16 @@ namespace System { SetData (name, data); } -#if !NET_2_1 [Obsolete ("Use AppDomainSetup.DynamicBase")] [SecurityPermission (SecurityAction.LinkDemand, ControlAppDomain = true)] public void SetDynamicBase (string path) { +#if MOBILE + throw new PlatformNotSupportedException (); +#else SetupInformationNoCopy.DynamicBase = path; +#endif // MOBILE } -#endif // !NET_2_1 [Obsolete ("AppDomain.GetCurrentThreadId has been deprecated" + " because it does not provide a stable Id when managed" @@ -1286,14 +1288,11 @@ namespace System { private Assembly DoAssemblyResolve (string name, Assembly requestingAssembly, bool refonly) { ResolveEventHandler del; -#if !NET_2_1 if (refonly) del = ReflectionOnlyAssemblyResolve; else del = AssemblyResolve; -#else - del = AssemblyResolve; -#endif + if (del == null) return null; @@ -1490,9 +1489,7 @@ namespace System { } #endif // MONO_FEATURE_MULTIPLE_APPDOMAINS -#if !MOBILE public event ResolveEventHandler ReflectionOnlyAssemblyResolve; -#endif #pragma warning disable 649 #if MOBILE diff --git a/mcs/class/corlib/System/AppDomainSetup.cs b/mcs/class/corlib/System/AppDomainSetup.cs index b3e2d51013..ded3fb527c 100644 --- a/mcs/class/corlib/System/AppDomainSetup.cs +++ b/mcs/class/corlib/System/AppDomainSetup.cs @@ -36,6 +36,7 @@ using System.IO; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Security; +using System.Security.Permissions; using System.Runtime.Serialization.Formatters.Binary; using System.Runtime.Hosting; @@ -47,7 +48,7 @@ namespace System [ClassInterface (ClassInterfaceType.None)] [ComVisible (true)] [StructLayout (LayoutKind.Sequential)] -#if NET_2_1 +#if MOBILE public sealed class AppDomainSetup #else public sealed class AppDomainSetup : IAppDomainSetup @@ -139,12 +140,27 @@ namespace System appBase = appBase.Substring (7); if (Path.DirectorySeparatorChar != '/') appBase = appBase.Replace ('/', Path.DirectorySeparatorChar); - if (Environment.IsRunningOnWindows) { - // Under Windows prepend "//" to indicate it's a local file - appBase = "//" + appBase; + } + appBase = Path.GetFullPath (appBase); + + if (Path.DirectorySeparatorChar != '/') { + bool isExtendedPath = appBase.StartsWith (@"\\?\", StringComparison.Ordinal); + if (appBase.IndexOf (':', isExtendedPath ? 6 : 2) != -1) { + throw new NotSupportedException ("The given path's format is not supported."); } - } else { - appBase = Path.GetFullPath (appBase); + } + + // validate the path + string dir = Path.GetDirectoryName (appBase); + if ((dir != null) && (dir.LastIndexOfAny (Path.GetInvalidPathChars ()) >= 0)) { + string msg = String.Format (Locale.GetText ("Invalid path characters in path: '{0}'"), appBase); + throw new ArgumentException (msg, "appBase"); + } + + string fname = Path.GetFileName (appBase); + if ((fname != null) && (fname.LastIndexOfAny (Path.GetInvalidFileNameChars ()) >= 0)) { + string msg = String.Format (Locale.GetText ("Invalid filename characters in path: '{0}'"), appBase); + throw new ArgumentException (msg, "appBase"); } return appBase; diff --git a/mcs/class/corlib/System/CStreamReader.cs b/mcs/class/corlib/System/CStreamReader.cs index 730b67a73f..8e51aed836 100644 --- a/mcs/class/corlib/System/CStreamReader.cs +++ b/mcs/class/corlib/System/CStreamReader.cs @@ -29,7 +29,7 @@ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -#if !NET_2_1 +#if !MOBILE using System.Text; using System.Runtime.InteropServices; diff --git a/mcs/class/corlib/System/CStreamWriter.cs b/mcs/class/corlib/System/CStreamWriter.cs index 5eaa353dc6..ff6fc63a25 100644 --- a/mcs/class/corlib/System/CStreamWriter.cs +++ b/mcs/class/corlib/System/CStreamWriter.cs @@ -31,7 +31,7 @@ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -#if !NET_2_1 +#if !MOBILE using System; using System.Text; diff --git a/mcs/class/corlib/System/Console.cs b/mcs/class/corlib/System/Console.cs index 2e7c4f4531..6a43f9cd80 100644 --- a/mcs/class/corlib/System/Console.cs +++ b/mcs/class/corlib/System/Console.cs @@ -41,7 +41,7 @@ namespace System { public static partial class Console { -#if !NET_2_1 +#if !MOBILE private class WindowsConsole { public static bool ctrlHandlerAdded = false; @@ -100,7 +100,7 @@ namespace System // // On Windows, follow the Windows tradition // -#if NET_2_1 +#if MOBILE // should never happen since Moonlight does not run on windows inputEncoding = outputEncoding = Encoding.Default; #else @@ -134,7 +134,7 @@ namespace System static void SetupStreams (Encoding inputEncoding, Encoding outputEncoding) { -#if !NET_2_1 +#if !MOBILE if (!Environment.IsRunningOnWindows && ConsoleDriver.IsConsole) { stdin = new CStreamReader (OpenStandardInput (0), inputEncoding); stdout = TextWriter.Synchronized (new CStreamWriter (OpenStandardOutput (0), outputEncoding, true) { AutoFlush = true }); @@ -488,7 +488,7 @@ namespace System stdout.WriteLine (String.Format (format, args)); } -#if !NET_2_1 +#if !MOBILE public static int Read () { if ((stdin is CStreamReader) && ConsoleDriver.IsConsole) { @@ -539,7 +539,7 @@ namespace System } } -#if !NET_2_1 +#if !MOBILE public static ConsoleColor BackgroundColor { get { return ConsoleDriver.BackgroundColor; } set { ConsoleDriver.BackgroundColor = value; } diff --git a/mcs/class/corlib/System/ConsoleDriver.cs b/mcs/class/corlib/System/ConsoleDriver.cs index cf1faa8da1..07354a9aeb 100644 --- a/mcs/class/corlib/System/ConsoleDriver.cs +++ b/mcs/class/corlib/System/ConsoleDriver.cs @@ -27,7 +27,7 @@ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -#if !NET_2_1 +#if !MOBILE using System.IO; using System.Runtime.CompilerServices; diff --git a/mcs/class/corlib/System/Environment.cs b/mcs/class/corlib/System/Environment.cs index ebef8e6ca4..f7f323681e 100644 --- a/mcs/class/corlib/System/Environment.cs +++ b/mcs/class/corlib/System/Environment.cs @@ -57,7 +57,7 @@ namespace System { * of icalls, do not require an increment. */ #pragma warning disable 169 - private const int mono_corlib_version = 149; + private const int mono_corlib_version = 156; #pragma warning restore 169 [ComVisible (true)] @@ -322,7 +322,7 @@ namespace System { return trace.ToString (); } } -#if !NET_2_1 + /// /// Get a fully qualified path to the system directory /// @@ -331,7 +331,7 @@ namespace System { return GetFolderPath (SpecialFolder.System); } } -#endif + /// /// Get the number of milliseconds that have elapsed since the system was booted /// @@ -472,7 +472,15 @@ namespace System { public extern static string[] GetCommandLineArgs (); [MethodImplAttribute (MethodImplOptions.InternalCall)] - internal extern static string internalGetEnvironmentVariable (string variable); + internal extern static string internalGetEnvironmentVariable_native (IntPtr variable); + + internal static string internalGetEnvironmentVariable (string variable) { + if (variable == null) + return null; + using (var h = Mono.RuntimeMarshal.MarshalString (variable)) { + return internalGetEnvironmentVariable_native (h.Value); + } + } /// /// Return a string containing the value of the environment @@ -480,7 +488,7 @@ namespace System { /// public static string GetEnvironmentVariable (string variable) { -#if !NET_2_1 +#if !MOBILE if (SecurityManager.SecurityEnabled) { new EnvironmentPermission (EnvironmentPermissionAccess.Read, variable).Demand (); } @@ -503,7 +511,7 @@ namespace System { /// /// Return a set of all environment variables and their values /// -#if !NET_2_1 +#if !MOBILE public static IDictionary GetEnvironmentVariables () { StringBuilder sb = null; @@ -565,7 +573,7 @@ namespace System { else dir = UnixGetFolderPath (folder, option); -#if !NET_2_1 +#if !MOBILE if ((dir != null) && (dir.Length > 0) && SecurityManager.SecurityEnabled) { new FileIOPermission (FileIOPermissionAccess.PathDiscovery, dir).Demand (); } @@ -917,7 +925,9 @@ namespace System { [SecurityCritical] public static void FailFast (string message, Exception exception) { - throw new NotImplementedException (); +#pragma warning disable 618 + throw new ExecutionEngineException (message, exception); +#pragma warning restore } [MethodImplAttribute (MethodImplOptions.InternalCall)] @@ -951,7 +961,7 @@ namespace System { } #endif -#if !NET_2_1 +#if !MOBILE // // Used by gacutil.exe // @@ -986,6 +996,14 @@ namespace System { [MethodImplAttribute (MethodImplOptions.InternalCall)] internal extern static int GetPageSize (); + [MethodImplAttribute(MethodImplOptions.InternalCall)] + extern private static string get_bundled_machine_config (); + + internal static string GetBundledMachineConfig () + { + return get_bundled_machine_config (); + } + static internal bool IsUnix { get { int platform = (int) Environment.Platform; diff --git a/mcs/class/corlib/System/GC.cs b/mcs/class/corlib/System/GC.cs deleted file mode 100644 index a673419bcf..0000000000 --- a/mcs/class/corlib/System/GC.cs +++ /dev/null @@ -1,159 +0,0 @@ -// -// System.GC.cs -// -// Author: -// Paolo Molaro (lupus@ximian.com) -// -// (C) 2001 Ximian, Inc. http://www.ximian.com -// - -// -// Copyright (C) 2004 Novell, Inc (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// - -using System.Runtime.CompilerServices; -using System.Runtime.ConstrainedExecution; -using System.Security.Permissions; - -namespace System -{ - public static class GC - { - - public extern static int MaxGeneration { - [MethodImplAttribute(MethodImplOptions.InternalCall)] - get; - } - - [MethodImplAttribute (MethodImplOptions.InternalCall)] - extern static void InternalCollect (int generation); - - public static void Collect () { - InternalCollect (MaxGeneration); - } - - public static void Collect (int generation) { - if (generation < 0) - throw new ArgumentOutOfRangeException ("generation"); - InternalCollect (generation); - } - - [MonoDocumentationNote ("mode parameter ignored")] - public static void Collect (int generation, GCCollectionMode mode) { - Collect (generation); - } - - [MonoDocumentationNote ("mode and blocking parameters ignored")] - public static void Collect (int generation, GCCollectionMode mode, bool blocking) { - Collect (generation); - } - - [MethodImplAttribute (MethodImplOptions.InternalCall)] - public extern static int GetGeneration (object obj); - - public static int GetGeneration (WeakReference wo) { - object obj = wo.Target; - if (obj == null) - throw new ArgumentException (); - return GetGeneration (obj); - } - - [MethodImplAttribute (MethodImplOptions.InternalCall)] - public extern static long GetTotalMemory (bool forceFullCollection); - - /* this icall has weird semantics check the docs... */ - [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)] - [MethodImplAttribute (MethodImplOptions.InternalCall)] - public extern static void KeepAlive (object obj); - - [MethodImplAttribute (MethodImplOptions.InternalCall)] - public extern static void ReRegisterForFinalize (object obj); - - [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)] - [MethodImplAttribute (MethodImplOptions.InternalCall)] - public extern static void SuppressFinalize (object obj); - - [MethodImplAttribute (MethodImplOptions.InternalCall)] - public extern static void WaitForPendingFinalizers (); - - [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)] - [MethodImplAttribute (MethodImplOptions.InternalCall)] - public extern static int CollectionCount (int generation); - - [MethodImplAttribute (MethodImplOptions.InternalCall)] - private extern static void RecordPressure (long bytesAllocated); - - public static void AddMemoryPressure (long bytesAllocated) { - RecordPressure (bytesAllocated); - } - - public static void RemoveMemoryPressure (long bytesAllocated) { - RecordPressure (-bytesAllocated); - } - - [PermissionSetAttribute (SecurityAction.LinkDemand, Name = "FullTrust")] - [MonoTODO] - public static GCNotificationStatus WaitForFullGCApproach () { - throw new NotImplementedException (); - } - - [PermissionSetAttribute (SecurityAction.LinkDemand, Name = "FullTrust")] - [MonoTODO] - public static GCNotificationStatus WaitForFullGCApproach (int millisecondsTimeout) { - throw new NotImplementedException (); - } - - [PermissionSetAttribute (SecurityAction.LinkDemand, Name = "FullTrust")] - [MonoTODO] - public static GCNotificationStatus WaitForFullGCComplete () { - throw new NotImplementedException (); - } - - [PermissionSetAttribute (SecurityAction.LinkDemand, Name = "FullTrust")] - [MonoTODO] - public static GCNotificationStatus WaitForFullGCComplete (int millisecondsTimeout) { - throw new NotImplementedException (); - } - - [PermissionSetAttribute (SecurityAction.LinkDemand, Name = "FullTrust")] - public static void RegisterForFullGCNotification (int maxGenerationThreshold, int largeObjectHeapThreshold) { - if (maxGenerationThreshold < 1 || maxGenerationThreshold > 99) - throw new ArgumentOutOfRangeException ("maxGenerationThreshold", maxGenerationThreshold, "maxGenerationThreshold must be between 1 and 99 inclusive"); - if (largeObjectHeapThreshold < 1 || largeObjectHeapThreshold > 99) - throw new ArgumentOutOfRangeException ("largeObjectHeapThreshold", largeObjectHeapThreshold, "largeObjectHeapThreshold must be between 1 and 99 inclusive"); - throw new NotImplementedException (); - } - - [PermissionSetAttribute (SecurityAction.LinkDemand, Name = "FullTrust")] - public static void CancelFullGCNotification () { - throw new NotImplementedException (); - } - - [MethodImplAttribute (MethodImplOptions.InternalCall)] - internal extern static void register_ephemeron_array (Ephemeron[] array); - - [MethodImplAttribute (MethodImplOptions.InternalCall)] - extern static object get_ephemeron_tombstone (); - - internal static readonly object EPHEMERON_TOMBSTONE = get_ephemeron_tombstone (); - } -} diff --git a/mcs/class/corlib/System/NullConsoleDriver.cs b/mcs/class/corlib/System/NullConsoleDriver.cs index ecec3b508b..09cba85976 100644 --- a/mcs/class/corlib/System/NullConsoleDriver.cs +++ b/mcs/class/corlib/System/NullConsoleDriver.cs @@ -26,7 +26,7 @@ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -#if !NET_2_1 +#if !MOBILE using System.Runtime.InteropServices; using System.Text; namespace System { diff --git a/mcs/class/corlib/System/Nullable.cs b/mcs/class/corlib/System/Nullable.cs index 11f6c67dbd..32c4aa0885 100644 --- a/mcs/class/corlib/System/Nullable.cs +++ b/mcs/class/corlib/System/Nullable.cs @@ -41,7 +41,7 @@ namespace System [ComVisible (true)] public static class Nullable { -#if NET_2_1 +#if MOBILE [ComVisible (false)] #endif public static int Compare (T? n1, T? n2) where T: struct @@ -56,7 +56,7 @@ namespace System return n2.has_value ? -1 : 0; } -#if NET_2_1 +#if MOBILE [ComVisible (false)] #endif public static bool Equals (T? n1, T? n2) where T: struct diff --git a/mcs/class/corlib/System/RuntimeTypeHandle.cs b/mcs/class/corlib/System/RuntimeTypeHandle.cs index eb6c42f097..cd51c87a2a 100644 --- a/mcs/class/corlib/System/RuntimeTypeHandle.cs +++ b/mcs/class/corlib/System/RuntimeTypeHandle.cs @@ -243,5 +243,9 @@ namespace System [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern static bool IsGenericTypeDefinition (RuntimeType type); + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + internal extern static IntPtr GetGenericParameterInfo (RuntimeType type); + } } diff --git a/mcs/class/corlib/System/TermInfoDriver.cs b/mcs/class/corlib/System/TermInfoDriver.cs index 5ab662ab06..ff6cc88a80 100644 --- a/mcs/class/corlib/System/TermInfoDriver.cs +++ b/mcs/class/corlib/System/TermInfoDriver.cs @@ -33,7 +33,7 @@ // https://github.com/dotnet/corefx // src/System.Console/src/System/ConsolePal.Unix.cs // -#if !NET_2_1 +#if !MOBILE // // Defining this writes the output to console.log diff --git a/mcs/class/corlib/System/TermInfoNumbers.cs b/mcs/class/corlib/System/TermInfoNumbers.cs index fb547d4f58..b0b89f225c 100644 --- a/mcs/class/corlib/System/TermInfoNumbers.cs +++ b/mcs/class/corlib/System/TermInfoNumbers.cs @@ -27,7 +27,7 @@ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -#if !NET_2_1 +#if !MOBILE // These values are taken from 'man 5 terminfo' and /usr/include/term.h. // They are the indexes for the numeric capabilities in a terminfo file. diff --git a/mcs/class/corlib/System/TermInfoReader.cs b/mcs/class/corlib/System/TermInfoReader.cs index 6424d4fb79..1a1ec6a942 100644 --- a/mcs/class/corlib/System/TermInfoReader.cs +++ b/mcs/class/corlib/System/TermInfoReader.cs @@ -27,7 +27,7 @@ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -#if !NET_2_1 +#if !MOBILE using System.IO; using System.Text; namespace System { diff --git a/mcs/class/corlib/System/TermInfoStrings.cs b/mcs/class/corlib/System/TermInfoStrings.cs index 4baa2793d8..d795ef91ad 100644 --- a/mcs/class/corlib/System/TermInfoStrings.cs +++ b/mcs/class/corlib/System/TermInfoStrings.cs @@ -27,7 +27,7 @@ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -#if !NET_2_1 +#if !MOBILE // These values are taken from 'man 5 terminfo' and /usr/include/term.h. // They are the indexes for the string capabilities in a terminfo file. diff --git a/mcs/class/corlib/System/TimeZoneInfo.cs b/mcs/class/corlib/System/TimeZoneInfo.cs index 6226f5b224..592f1d2f30 100644 --- a/mcs/class/corlib/System/TimeZoneInfo.cs +++ b/mcs/class/corlib/System/TimeZoneInfo.cs @@ -273,7 +273,7 @@ namespace System #endif private AdjustmentRule [] adjustmentRules; -#if !NET_2_1 || MOBILE_STATIC +#if !MOBILE || MOBILE_STATIC /// /// Determine whether windows of not (taken Stephane Delcroix's code) /// @@ -538,7 +538,7 @@ namespace System //FIXME: this method should check for cached values in systemTimeZones if (id == null) throw new ArgumentNullException ("id"); -#if !NET_2_1 +#if !MOBILE if (TimeZoneKey != null) { if (id == "Coordinated Universal Time") @@ -568,7 +568,7 @@ namespace System } #endif -#if !NET_2_1 +#if !MOBILE private static TimeZoneInfo FromRegistryKey (string id, RegistryKey key) { byte [] reg_tzi = (byte []) key.GetValue ("TZI"); @@ -919,7 +919,7 @@ namespace System public bool IsDaylightSavingTime (DateTimeOffset dateTimeOffset) { - throw new NotImplementedException (); + return IsDaylightSavingTime (dateTimeOffset.DateTime); } internal DaylightTime GetDaylightChanges (int year) diff --git a/mcs/class/corlib/System/WeakReference.cs b/mcs/class/corlib/System/WeakReference.cs index 7ba2a7abd4..cfbb19afb3 100644 --- a/mcs/class/corlib/System/WeakReference.cs +++ b/mcs/class/corlib/System/WeakReference.cs @@ -54,7 +54,7 @@ namespace System } //Constructors -#if NET_2_1 +#if MOBILE protected WeakReference () { } diff --git a/mcs/class/corlib/System/WindowsConsoleDriver.cs b/mcs/class/corlib/System/WindowsConsoleDriver.cs index 2e8b643e33..10ba8db45e 100755 --- a/mcs/class/corlib/System/WindowsConsoleDriver.cs +++ b/mcs/class/corlib/System/WindowsConsoleDriver.cs @@ -26,7 +26,7 @@ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -#if !NET_2_1 +#if !MOBILE using System.Runtime.InteropServices; using System.Text; namespace System { diff --git a/mcs/class/corlib/Test/Microsoft.Win32/RegistryKeyTest.cs.REMOVED.git-id b/mcs/class/corlib/Test/Microsoft.Win32/RegistryKeyTest.cs.REMOVED.git-id index 138815a2ce..4d2a18872d 100644 --- a/mcs/class/corlib/Test/Microsoft.Win32/RegistryKeyTest.cs.REMOVED.git-id +++ b/mcs/class/corlib/Test/Microsoft.Win32/RegistryKeyTest.cs.REMOVED.git-id @@ -1 +1 @@ -7479bc775b28da65130781710df3ce18d64e9e33 \ No newline at end of file +7054084409dab3c72f7be13a1ddc4df6b7c49d9f \ No newline at end of file diff --git a/mcs/class/corlib/Test/System.Collections.Generic/ComparerTest.cs b/mcs/class/corlib/Test/System.Collections.Generic/ComparerTest.cs index b5d78b7571..d347fb6196 100644 --- a/mcs/class/corlib/Test/System.Collections.Generic/ComparerTest.cs +++ b/mcs/class/corlib/Test/System.Collections.Generic/ComparerTest.cs @@ -53,7 +53,6 @@ namespace MonoTests.System.Collections.Generic } } -#if NET_4_5 [Test] public void Create () { @@ -70,7 +69,6 @@ namespace MonoTests.System.Collections.Generic } catch (ArgumentNullException) { } } -#endif [Test] public void DefaultComparer_UserComparable () diff --git a/mcs/class/corlib/Test/System.Collections/SortedListTest.cs b/mcs/class/corlib/Test/System.Collections/SortedListTest.cs index 4b4b3b3a80..ce4f22174b 100644 --- a/mcs/class/corlib/Test/System.Collections/SortedListTest.cs +++ b/mcs/class/corlib/Test/System.Collections/SortedListTest.cs @@ -770,7 +770,7 @@ namespace MonoTests.System.Collections for (int i = 0; i < 20; i++) sl1.RemoveAt (9); - Assert.AreEqual (30, sl1.Count, 30, "#C1"); + Assert.AreEqual (30, (double) sl1.Count, 30, "#C1"); for (int i = 0; i < 9; i++) Assert.AreEqual (i, sl1 ["kala " + string.Format ("{0:D2}", i)], "#C2:" + i); for (int i = 9; i < 29; i++) diff --git a/mcs/class/corlib/Test/System.Globalization/CultureInfoTest.cs b/mcs/class/corlib/Test/System.Globalization/CultureInfoTest.cs index 364a8b3f95..b2a720650f 100644 --- a/mcs/class/corlib/Test/System.Globalization/CultureInfoTest.cs +++ b/mcs/class/corlib/Test/System.Globalization/CultureInfoTest.cs @@ -12,6 +12,7 @@ using System.Globalization; using System.IO; using System.Runtime.Serialization.Formatters.Binary; using System.Threading; +using System.Threading.Tasks; using NUnit.Framework; @@ -623,7 +624,6 @@ namespace MonoTests.System.Globalization Assert.IsFalse (zh2.Equals (zh1), "#2"); } -#if NET_4_5 CountdownEvent barrier = new CountdownEvent (3); AutoResetEvent[] evt = new AutoResetEvent [] { new AutoResetEvent (false), new AutoResetEvent (false), new AutoResetEvent (false), new AutoResetEvent (false)}; @@ -728,21 +728,42 @@ namespace MonoTests.System.Globalization } [Test] - public void DefaultThreadCurrentCultureAndNumberFormaters () { + public void DefaultThreadCurrentCultureIsIgnoredWhenCultureFlowsToThread () + { string us_str = null; string br_str = null; + var thread = new Thread (() => { CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("en-US"); us_str = 100000.ToString ("C"); CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("pt-BR"); br_str = 100000.ToString ("C"); }); + + var expected = 100000.ToString ("C"); + thread.Start (); - thread.Join (); + Assert.IsTrue (thread.Join (5000), "#0"); CultureInfo.DefaultThreadCurrentCulture = null; - Assert.AreEqual ("$100,000.00", us_str, "#1"); - Assert.AreEqual ("R$ 100.000,00", br_str, "#2"); + Assert.AreEqual (expected, us_str, "#1"); + Assert.AreEqual (expected, br_str, "#2"); + } + + [Test] + public void FlowCultureInfoFromParentThreadSinceNet46 () + { + if (SynchronizationContext.Current != null) { + Assert.Ignore (); + return; + } + + Func f = async () => { + Thread.CurrentThread.CurrentUICulture = new CultureInfo ("pt-BR"); + await Task.Yield (); + Assert.AreEqual ("pt-BR", Thread.CurrentThread.CurrentUICulture.Name); + }; + + Assert.IsTrue (f ().Wait (5 * 1000), "#1"); } -#endif } } diff --git a/mcs/class/corlib/Test/System.IO.IsolatedStorage/IsolatedStorageFileTest.cs b/mcs/class/corlib/Test/System.IO.IsolatedStorage/IsolatedStorageFileTest.cs index 66eb27ed32..474a3bba20 100644 --- a/mcs/class/corlib/Test/System.IO.IsolatedStorage/IsolatedStorageFileTest.cs +++ b/mcs/class/corlib/Test/System.IO.IsolatedStorage/IsolatedStorageFileTest.cs @@ -124,7 +124,7 @@ namespace MonoTests.System.IO.IsolatedStorageTest { IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForAssembly (); Assert.AreEqual (Int64.MaxValue, isf.MaximumSize, "MaximumSize"); Assert.AreEqual (IsolatedStorageScope.User | IsolatedStorageScope.Assembly, isf.Scope, "Scope"); -#if !NET_2_1 +#if !MOBILE Assert.IsTrue ((isf.AssemblyIdentity is Url), "AssemblyIdentity"); // note: mono transforms the CodeBase into uppercase // for net 1.1 which uses file:// and not file:/// @@ -157,7 +157,7 @@ namespace MonoTests.System.IO.IsolatedStorageTest { IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForDomain (); Assert.AreEqual (Int64.MaxValue, isf.MaximumSize, "MaximumSize"); Assert.AreEqual (IsolatedStorageScope.User | IsolatedStorageScope.Domain | IsolatedStorageScope.Assembly, isf.Scope, "Scope"); -#if !NET_2_1 +#if !MOBILE Assert.IsTrue ((isf.AssemblyIdentity is Url), "AssemblyIdentity"); // note: mono transforms the CodeBase into uppercase // for net 1.1 which uses file:// and not file:/// @@ -198,7 +198,7 @@ namespace MonoTests.System.IO.IsolatedStorageTest { { IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication (); Assert.AreEqual (Int64.MaxValue, isf.MaximumSize, "MaximumSize"); -#if !NET_2_1 +#if !MOBILE Assert.AreEqual (IsolatedStorageScope.User | IsolatedStorageScope.Assembly, isf.Scope, "Scope"); Assert.IsTrue ((isf.AssemblyIdentity is Url), "AssemblyIdentity"); Assert.IsTrue ((isf.AssemblyIdentity.ToString ().IndexOf (Assembly.GetExecutingAssembly ().CodeBase) > 0), "Url"); @@ -206,7 +206,7 @@ namespace MonoTests.System.IO.IsolatedStorageTest { Assert.IsTrue ((isf.CurrentSize >= 0), "CurrentSize"); } -#if !NET_2_1 +#if !MOBILE [Test] [ExpectedException (typeof (IsolatedStorageException))] public void GetUserStoreForApplication_AssemblyIdentity () @@ -238,7 +238,7 @@ namespace MonoTests.System.IO.IsolatedStorageTest { IsolatedStorageScope scope = IsolatedStorageScope.User | IsolatedStorageScope.Domain | IsolatedStorageScope.Assembly; IsolatedStorageFile isf = IsolatedStorageFile.GetStore (scope, typeof (Zone), typeof (Zone)); Assert.AreEqual (Int64.MaxValue, isf.MaximumSize, "MaximumSize"); -#if !NET_2_1 +#if !MOBILE Assert.AreEqual (IsolatedStorageScope.User | IsolatedStorageScope.Domain | IsolatedStorageScope.Assembly, isf.Scope, "Scope"); Assert.IsTrue ((isf.AssemblyIdentity is Zone), "AssemblyIdentity"); Assert.IsTrue ((isf.AssemblyIdentity.ToString ().IndexOf ("MyComputer") > 0), "Zone - Assembly"); @@ -265,7 +265,7 @@ namespace MonoTests.System.IO.IsolatedStorageTest { IsolatedStorageFile isf = IsolatedStorageFile.GetStore (scope, typeof (StrongName), typeof (Url)); Assert.AreEqual (Int64.MaxValue, isf.MaximumSize, "MaximumSize"); Assert.AreEqual (scope, isf.Scope, "Scope"); -#if !NET_2_1 +#if !MOBILE Assert.IsTrue ((isf.AssemblyIdentity is Url), "AssemblyIdentity"); // note: mono transforms the CodeBase into uppercase // for net 1.1 which uses file:// and not file:/// @@ -361,7 +361,7 @@ namespace MonoTests.System.IO.IsolatedStorageTest { // Maximum size for Internet isn't (by default) Int64.MaxValue Assert.AreEqual (scope, isf.Scope, "Scope"); -#if !NET_2_1 +#if !MOBILE Assert.IsTrue ((isf.AssemblyIdentity is Zone), "AssemblyIdentity"); Assert.IsTrue ((isf.AssemblyIdentity.ToString ().IndexOf ("Intranet") > 0), "Zone - Assembly"); Assert.IsTrue ((isf.DomainIdentity is Zone), "DomainIdentity"); @@ -577,7 +577,7 @@ namespace MonoTests.System.IO.IsolatedStorageTest { { IsolatedStorageScope scope = IsolatedStorageScope.User | IsolatedStorageScope.Roaming | IsolatedStorageScope.Assembly | IsolatedStorageScope.Domain; IsolatedStorageFile isf = IsolatedStorageFile.GetStore (scope, null, null); -#if !NET_2_1 +#if !MOBILE Assert.AreEqual (typeof (Url), isf.AssemblyIdentity.GetType (), "AssemblyIdentity"); Assert.AreEqual (typeof (Url), isf.DomainIdentity.GetType (), "DomainIdentity"); #endif diff --git a/mcs/class/corlib/Test/System.IO/DirectoryInfoTest.cs b/mcs/class/corlib/Test/System.IO/DirectoryInfoTest.cs index d6aacac5dc..34a431aabd 100644 --- a/mcs/class/corlib/Test/System.IO/DirectoryInfoTest.cs +++ b/mcs/class/corlib/Test/System.IO/DirectoryInfoTest.cs @@ -168,6 +168,8 @@ namespace MonoTests.System.IO info = new DirectoryInfo ("/test/"); Assert.AreEqual ("test", info.Name, "#4"); } else { + Directory.SetCurrentDirectory (@"C:\"); + info = new DirectoryInfo (@"c:"); Assert.AreEqual (@"C:\", info.Name, "#4"); @@ -217,6 +219,8 @@ namespace MonoTests.System.IO Assert.IsNotNull (info.Parent, "#7a"); Assert.AreEqual ("/", info.Parent.FullName, "#7b"); } else { + Directory.SetCurrentDirectory (@"C:\"); + info = new DirectoryInfo (@"c:"); Assert.IsNull (info.Parent, "#4"); @@ -418,6 +422,8 @@ namespace MonoTests.System.IO di = new DirectoryInfo ("/test/"); Assert.AreEqual ("/test/", di.FullName, "#D4"); } else { + Directory.SetCurrentDirectory (@"C:\"); + di = new DirectoryInfo (@"c:"); Assert.AreEqual (@"C:\", di.FullName, "#D1"); diff --git a/mcs/class/corlib/Test/System.IO/FileInfoTest.cs b/mcs/class/corlib/Test/System.IO/FileInfoTest.cs index 50755fa0dc..e4000ea33d 100644 --- a/mcs/class/corlib/Test/System.IO/FileInfoTest.cs +++ b/mcs/class/corlib/Test/System.IO/FileInfoTest.cs @@ -758,9 +758,9 @@ namespace MonoTests.System.IO try { info.MoveTo (destFile); Assert.Fail ("#1"); - } catch (FileNotFoundException ex) { + } catch (DirectoryNotFoundException ex) { // Could not find a part of the path - Assert.AreEqual (typeof (FileNotFoundException), ex.GetType (), "#2"); + Assert.AreEqual (typeof (DirectoryNotFoundException), ex.GetType (), "#2"); Assert.IsNull (ex.InnerException, "#3"); Assert.IsNotNull (ex.Message, "#4"); } diff --git a/mcs/class/corlib/Test/System.IO/FileStreamSafeHandleTest.cs b/mcs/class/corlib/Test/System.IO/FileStreamSafeHandleTest.cs index bd114bb5fb..3800701e32 100644 --- a/mcs/class/corlib/Test/System.IO/FileStreamSafeHandleTest.cs +++ b/mcs/class/corlib/Test/System.IO/FileStreamSafeHandleTest.cs @@ -17,7 +17,7 @@ namespace MonoTests.System.IO [TestFixture] public class FileStreamWithClosedSafeHandleTests { -#if !NET_2_1 +#if !MOBILE private FileStream GetFileStreamWithClosedHandle () { var fs1 = new FileStream ("test2", FileMode.OpenOrCreate); diff --git a/mcs/class/corlib/Test/System.IO/FileStreamTest.cs b/mcs/class/corlib/Test/System.IO/FileStreamTest.cs index 008930061e..b07955903f 100644 --- a/mcs/class/corlib/Test/System.IO/FileStreamTest.cs +++ b/mcs/class/corlib/Test/System.IO/FileStreamTest.cs @@ -25,10 +25,6 @@ namespace MonoTests.System.IO { string TempFolder = Path.Combine (Path.GetTempPath (), "MonoTests.System.IO.Tests"); static readonly char DSC = Path.DirectorySeparatorChar; - static bool MacOSX = false; - - [DllImport ("libc")] - static extern int uname (IntPtr buf); [TearDown] public void TearDown () @@ -44,13 +40,6 @@ namespace MonoTests.System.IO Directory.Delete (TempFolder, true); Directory.CreateDirectory (TempFolder); -#if !MOBILE - // from XplatUI.cs - IntPtr buf = Marshal.AllocHGlobal (8192); - if (uname (buf) == 0) - MacOSX = Marshal.PtrToStringAnsi (buf) == "Darwin"; - Marshal.FreeHGlobal (buf); -#endif } public void TestCtr () diff --git a/mcs/class/corlib/Test/System.IO/MemoryStreamTest.cs b/mcs/class/corlib/Test/System.IO/MemoryStreamTest.cs index f552e933a6..b7c472b4fd 100644 --- a/mcs/class/corlib/Test/System.IO/MemoryStreamTest.cs +++ b/mcs/class/corlib/Test/System.IO/MemoryStreamTest.cs @@ -17,9 +17,7 @@ using System.IO; using System.Runtime.Serialization.Formatters.Binary; using System.Text; using System.Threading; -#if NET_4_5 using System.Threading.Tasks; -#endif using NUnit.Framework; @@ -1119,7 +1117,6 @@ namespace MonoTests.System.IO Assert.IsTrue (ms.DisposedCalled, "After"); } -#if NET_4_5 [Test] public void ReadAsync () { @@ -1323,6 +1320,5 @@ namespace MonoTests.System.IO return true; } } -#endif } } diff --git a/mcs/class/corlib/Test/System.IO/PathTest.cs b/mcs/class/corlib/Test/System.IO/PathTest.cs index 897342eba7..7b83492b99 100644 --- a/mcs/class/corlib/Test/System.IO/PathTest.cs +++ b/mcs/class/corlib/Test/System.IO/PathTest.cs @@ -37,6 +37,7 @@ namespace MonoTests.System.IO static string path3; static OsType OS; static char DSC = Path.DirectorySeparatorChar; + static char ADSC = Path.AltDirectorySeparatorChar; [SetUp] public void SetUp () @@ -359,6 +360,12 @@ namespace MonoTests.System.IO } } + [Test] + public void GetDirectoryName_Replaces_AltDirectorySeparatorChar () + { + Assert.AreEqual ($"foo{DSC}bar", Path.GetDirectoryName ($"foo{ADSC}bar{ADSC}dingus"), "#1"); + } + [Test] public void GetExtension () { @@ -688,6 +695,11 @@ namespace MonoTests.System.IO i, root + test [i, 0], ex.GetType ())); } } + + // These cases require that we don't pass a root to GetFullPath - it should return the proper drive root. + string root4 = Path.GetPathRoot(Directory.GetCurrentDirectory()); + Assert.AreEqual(root4, Path.GetFullPath(@"\")); + Assert.AreEqual(root4, Path.GetFullPath("/")); } [Test] diff --git a/mcs/class/corlib/Test/System.IO/StreamReaderTest.cs b/mcs/class/corlib/Test/System.IO/StreamReaderTest.cs index 54e5e04243..eb29cfa9e4 100644 --- a/mcs/class/corlib/Test/System.IO/StreamReaderTest.cs +++ b/mcs/class/corlib/Test/System.IO/StreamReaderTest.cs @@ -9,9 +9,7 @@ using System; using System.IO; using System.Text; -#if NET_4_5 using System.Threading.Tasks; -#endif using NUnit.Framework; @@ -845,7 +843,6 @@ public class StreamReaderTest Assert.AreEqual (0, StreamReader.Null.ReadBlock (buffer, 0, buffer.Length)); } -#if NET_4_5 [Test] public void ReadLineAsync () { @@ -866,7 +863,6 @@ public class StreamReaderTest Assert.IsTrue (result.Wait (3000), "#1"); Assert.AreEqual ("ab" + Environment.NewLine, result.Result); } -#endif } class MyStream : Stream { diff --git a/mcs/class/corlib/Test/System.IO/StreamTest.cs b/mcs/class/corlib/Test/System.IO/StreamTest.cs index e22a13736f..a7ad4ea65e 100644 --- a/mcs/class/corlib/Test/System.IO/StreamTest.cs +++ b/mcs/class/corlib/Test/System.IO/StreamTest.cs @@ -120,7 +120,6 @@ namespace MonoTests.System.IO Assert.IsFalse (s.CanRead, "#1"); } -#if NET_4_5 [Test] public void CopyAsync () { @@ -211,6 +210,5 @@ namespace MonoTests.System.IO } catch (AggregateException) { } } -#endif } } diff --git a/mcs/class/corlib/Test/System.IO/StreamWriterTest.cs b/mcs/class/corlib/Test/System.IO/StreamWriterTest.cs index 661cffc18c..a0afe23178 100644 --- a/mcs/class/corlib/Test/System.IO/StreamWriterTest.cs +++ b/mcs/class/corlib/Test/System.IO/StreamWriterTest.cs @@ -1051,7 +1051,6 @@ namespace MonoTests.System.IO Assert.AreEqual (5, ms.Position, "#2"); } -#if NET_4_5 [Test] public void FlushAsync () { @@ -1098,7 +1097,6 @@ namespace MonoTests.System.IO Assert.IsTrue (t.Wait (1000), "#5"); } -#endif // TODO - Write - test errors, functionality tested in TestFlush. } diff --git a/mcs/class/corlib/Test/System.Reflection.Emit/MethodBuilderTest.cs b/mcs/class/corlib/Test/System.Reflection.Emit/MethodBuilderTest.cs index c14a6c388f..e40d8ef72d 100644 --- a/mcs/class/corlib/Test/System.Reflection.Emit/MethodBuilderTest.cs +++ b/mcs/class/corlib/Test/System.Reflection.Emit/MethodBuilderTest.cs @@ -656,7 +656,7 @@ namespace MonoTests.System.Reflection.Emit Assert.AreEqual ("FOO", ((ObsoleteAttribute) attrs [0]).Message, "#B3"); } } -#if !NET_2_1 +#if !MOBILE [Test] [ExpectedException (typeof (InvalidOperationException))] public void TestAddDeclarativeSecurityAlreadyCreated () diff --git a/mcs/class/corlib/Test/System.Reflection/AssemblyNameTest.cs b/mcs/class/corlib/Test/System.Reflection/AssemblyNameTest.cs index 4d8f1bf0dd..b707567f1d 100644 --- a/mcs/class/corlib/Test/System.Reflection/AssemblyNameTest.cs +++ b/mcs/class/corlib/Test/System.Reflection/AssemblyNameTest.cs @@ -1152,10 +1152,8 @@ public class AssemblyNameTest { Assert.IsNull (an.GetPublicKey (), "GetPublicKey"); Assert.IsNull (an.GetPublicKeyToken (), "GetPublicKeyToken"); Assert.AreEqual ("TestAssembly", an.ToString (), "ToString"); -#if NET_4_5 Assert.IsNull (an.CultureName, "CultureName"); Assert.AreEqual (AssemblyContentType.Default, an.ContentType, "ContentType"); -#endif } [Test] // ctor (String) diff --git a/mcs/class/corlib/Test/System.Reflection/AssemblyTest.cs b/mcs/class/corlib/Test/System.Reflection/AssemblyTest.cs index f0ccd30b71..e82d81fba6 100644 --- a/mcs/class/corlib/Test/System.Reflection/AssemblyTest.cs +++ b/mcs/class/corlib/Test/System.Reflection/AssemblyTest.cs @@ -55,14 +55,27 @@ namespace MonoTests.System.Reflection [TestFixture] public class AssemblyTest { - static string TempFolder = Path.Combine (Path.GetTempPath (), + static string BaseTempFolder = Path.Combine (Path.GetTempPath (), "MonoTests.System.Reflection.AssemblyTest"); + static string TempFolder; + + [TestFixtureSetUp] + public void FixtureSetUp () + { + try { + // Try to cleanup from any previous NUnit run. + Directory.Delete (BaseTempFolder, true); + } catch (Exception) { + } + } [SetUp] public void SetUp () { - while (Directory.Exists (TempFolder)) - TempFolder = Path.Combine (TempFolder, "2"); + int i = 0; + do { + TempFolder = Path.Combine (BaseTempFolder, (++i).ToString()); + } while (Directory.Exists (TempFolder)); Directory.CreateDirectory (TempFolder); } @@ -70,8 +83,8 @@ namespace MonoTests.System.Reflection public void TearDown () { try { - // This throws an exception under MS.NET, since the directory contains loaded - // assemblies. + // This throws an exception under MS.NET and Mono on Windows, + // since the directory contains loaded assemblies. Directory.Delete (TempFolder, true); } catch (Exception) { } @@ -410,22 +423,21 @@ namespace MonoTests.System.Reflection [Test] // bug #78517 public void LoadFrom_Empty_Assembly () { - string tempFile = Path.GetTempFileName (); + string tempFile = Path.Combine (TempFolder, Path.GetRandomFileName ()); + File.CreateText (tempFile).Close (); try { Assembly.LoadFrom (tempFile); Assert.Fail ("#1"); } catch (BadImageFormatException ex) { Assert.IsNull (ex.InnerException, "#2"); - } finally { - File.Delete (tempFile); } } [Test] // bug #78517 public void LoadFrom_Invalid_Assembly () { - string tempFile = Path.GetTempFileName (); + string tempFile = Path.Combine (TempFolder, Path.GetRandomFileName ()); using (StreamWriter sw = File.CreateText (tempFile)) { sw.WriteLine ("foo"); sw.Close (); @@ -436,24 +448,19 @@ namespace MonoTests.System.Reflection Assert.Fail ("#1"); } catch (BadImageFormatException ex) { Assert.IsNull (ex.InnerException, "#2"); - } finally { - File.Delete (tempFile); } } [Test] public void LoadFrom_NonExisting_Assembly () { - string tempFile = Path.GetTempFileName (); - File.Delete (tempFile); + string tempFile = Path.Combine (TempFolder, Path.GetRandomFileName ()); try { Assembly.LoadFrom (tempFile); Assert.Fail ("#1"); } catch (FileNotFoundException ex) { Assert.IsNull (ex.InnerException, "#2"); - } finally { - File.Delete (tempFile); } } @@ -520,28 +527,24 @@ namespace MonoTests.System.Reflection [Test] public void Location_Empty() { string assemblyFileName = Path.Combine ( - Path.GetTempPath (), "AssemblyLocation.dll"); + TempFolder, "AssemblyLocation.dll"); - try { - AssemblyName assemblyName = new AssemblyName (); - assemblyName.Name = "AssemblyLocation"; + AssemblyName assemblyName = new AssemblyName (); + assemblyName.Name = "AssemblyLocation"; - AssemblyBuilder ab = AppDomain.CurrentDomain - .DefineDynamicAssembly (assemblyName, - AssemblyBuilderAccess.Save, - Path.GetTempPath (), - AppDomain.CurrentDomain.Evidence); - ab.Save (Path.GetFileName (assemblyFileName)); + AssemblyBuilder ab = AppDomain.CurrentDomain + .DefineDynamicAssembly (assemblyName, + AssemblyBuilderAccess.Save, + TempFolder, + AppDomain.CurrentDomain.Evidence); + ab.Save (Path.GetFileName (assemblyFileName)); - using (FileStream fs = File.OpenRead (assemblyFileName)) { - byte[] buffer = new byte[fs.Length]; - fs.Read (buffer, 0, buffer.Length); - Assembly assembly = Assembly.Load (buffer); - Assert.AreEqual (string.Empty, assembly.Location); - fs.Close (); - } - } finally { - File.Delete (assemblyFileName); + using (FileStream fs = File.OpenRead (assemblyFileName)) { + byte[] buffer = new byte[fs.Length]; + fs.Read (buffer, 0, buffer.Length); + Assembly assembly = Assembly.Load (buffer); + Assert.AreEqual (string.Empty, assembly.Location); + fs.Close (); } } @@ -549,56 +552,52 @@ namespace MonoTests.System.Reflection public void SateliteAssemblyForInMemoryAssembly () { string assemblyFileName = Path.Combine ( - Path.GetTempPath (), "AssemblyLocation1.dll"); + TempFolder, "AssemblyLocation1.dll"); - try { - AssemblyName assemblyName = new AssemblyName (); - assemblyName.Name = "AssemblyLocation1"; + AssemblyName assemblyName = new AssemblyName (); + assemblyName.Name = "AssemblyLocation1"; - AssemblyBuilder ab = AppDomain.CurrentDomain - .DefineDynamicAssembly (assemblyName, - AssemblyBuilderAccess.Save, - Path.GetTempPath ()); + AssemblyBuilder ab = AppDomain.CurrentDomain + .DefineDynamicAssembly (assemblyName, + AssemblyBuilderAccess.Save, + TempFolder); - ModuleBuilder moduleBuilder = ab.DefineDynamicModule (assemblyName.Name, assemblyName.Name + ".dll"); - TypeBuilder typeBuilder = moduleBuilder.DefineType ("Program", TypeAttributes.Public); + ModuleBuilder moduleBuilder = ab.DefineDynamicModule (assemblyName.Name, assemblyName.Name + ".dll"); + TypeBuilder typeBuilder = moduleBuilder.DefineType ("Program", TypeAttributes.Public); - MethodBuilder methodBuilder = typeBuilder.DefineMethod ("TestCall", MethodAttributes.Public | MethodAttributes.Static, typeof(void), Type.EmptyTypes); - ILGenerator gen = methodBuilder.GetILGenerator (); + MethodBuilder methodBuilder = typeBuilder.DefineMethod ("TestCall", MethodAttributes.Public | MethodAttributes.Static, typeof(void), Type.EmptyTypes); + ILGenerator gen = methodBuilder.GetILGenerator (); - // - // var resourceManager = new ResourceManager (typeof (Program)); - // resourceManager.GetString ("test"); - // - gen.Emit (OpCodes.Ldtoken, typeBuilder); - gen.Emit (OpCodes.Call, typeof(Type).GetMethod ("GetTypeFromHandle")); - gen.Emit (OpCodes.Newobj, typeof(ResourceManager).GetConstructor (new Type[] { typeof(Type) })); - gen.Emit (OpCodes.Ldstr, "test"); - gen.Emit (OpCodes.Callvirt, typeof(ResourceManager).GetMethod ("GetString", new Type[] { typeof(string) })); - gen.Emit (OpCodes.Pop); - gen.Emit (OpCodes.Ret); + // + // var resourceManager = new ResourceManager (typeof (Program)); + // resourceManager.GetString ("test"); + // + gen.Emit (OpCodes.Ldtoken, typeBuilder); + gen.Emit (OpCodes.Call, typeof(Type).GetMethod ("GetTypeFromHandle")); + gen.Emit (OpCodes.Newobj, typeof(ResourceManager).GetConstructor (new Type[] { typeof(Type) })); + gen.Emit (OpCodes.Ldstr, "test"); + gen.Emit (OpCodes.Callvirt, typeof(ResourceManager).GetMethod ("GetString", new Type[] { typeof(string) })); + gen.Emit (OpCodes.Pop); + gen.Emit (OpCodes.Ret); - typeBuilder.CreateType (); + typeBuilder.CreateType (); - ab.Save (Path.GetFileName (assemblyFileName)); + ab.Save (Path.GetFileName (assemblyFileName)); - using (FileStream fs = File.OpenRead (assemblyFileName)) { - byte[] buffer = new byte[fs.Length]; - fs.Read (buffer, 0, buffer.Length); - Assembly assembly = Assembly.Load (buffer); + using (FileStream fs = File.OpenRead (assemblyFileName)) { + byte[] buffer = new byte[fs.Length]; + fs.Read (buffer, 0, buffer.Length); + Assembly assembly = Assembly.Load (buffer); - var mm = assembly.GetType ("Program").GetMethod ("TestCall"); - try { - mm.Invoke (null, null); - Assert.Fail (); - } catch (TargetInvocationException e) { - Assert.IsTrue (e.InnerException is MissingManifestResourceException); - } - - fs.Close (); + var mm = assembly.GetType ("Program").GetMethod ("TestCall"); + try { + mm.Invoke (null, null); + Assert.Fail (); + } catch (TargetInvocationException e) { + Assert.IsTrue (e.InnerException is MissingManifestResourceException); } - } finally { - File.Delete (assemblyFileName); + + fs.Close (); } } @@ -607,19 +606,15 @@ namespace MonoTests.System.Reflection public void bug78464 () { string assemblyFileName = Path.Combine ( - Path.GetTempPath (), "bug78464.dll"); + TempFolder, "bug78464.dll"); + // execute test in separate appdomain to allow assembly to be unloaded + AppDomain testDomain = CreateTestDomain (AppDomain.CurrentDomain.BaseDirectory, false); + CrossDomainTester crossDomainTester = CreateCrossDomainTester (testDomain); try { - // execute test in separate appdomain to allow assembly to be unloaded - AppDomain testDomain = CreateTestDomain (AppDomain.CurrentDomain.BaseDirectory, false); - CrossDomainTester crossDomainTester = CreateCrossDomainTester (testDomain); - try { - crossDomainTester.bug78464 (assemblyFileName); - } finally { - AppDomain.Unload (testDomain); - } + crossDomainTester.bug78464 (assemblyFileName); } finally { - File.Delete (assemblyFileName); + AppDomain.Unload (testDomain); } } @@ -628,36 +623,32 @@ namespace MonoTests.System.Reflection public void bug78465 () { string assemblyFileName = Path.Combine ( - Path.GetTempPath (), "bug78465.dll"); + TempFolder, "bug78465.dll"); + AssemblyName assemblyName = new AssemblyName (); + assemblyName.Name = "bug78465"; + + AssemblyBuilder ab = AppDomain.CurrentDomain + .DefineDynamicAssembly (assemblyName, + AssemblyBuilderAccess.Save, + Path.GetDirectoryName (assemblyFileName), + AppDomain.CurrentDomain.Evidence); + ab.Save (Path.GetFileName (assemblyFileName)); + + using (FileStream fs = File.OpenRead (assemblyFileName)) { + byte[] buffer = new byte[fs.Length]; + fs.Read (buffer, 0, buffer.Length); + Assembly assembly = Assembly.Load (buffer); + Assert.AreEqual (string.Empty, assembly.Location, "#1"); + fs.Close (); + } + + AppDomain testDomain = CreateTestDomain (AppDomain.CurrentDomain.BaseDirectory, false); + CrossDomainTester crossDomainTester = CreateCrossDomainTester (testDomain); try { - AssemblyName assemblyName = new AssemblyName (); - assemblyName.Name = "bug78465"; - - AssemblyBuilder ab = AppDomain.CurrentDomain - .DefineDynamicAssembly (assemblyName, - AssemblyBuilderAccess.Save, - Path.GetDirectoryName (assemblyFileName), - AppDomain.CurrentDomain.Evidence); - ab.Save (Path.GetFileName (assemblyFileName)); - - using (FileStream fs = File.OpenRead (assemblyFileName)) { - byte[] buffer = new byte[fs.Length]; - fs.Read (buffer, 0, buffer.Length); - Assembly assembly = Assembly.Load (buffer); - Assert.AreEqual (string.Empty, assembly.Location, "#1"); - fs.Close (); - } - - AppDomain testDomain = CreateTestDomain (AppDomain.CurrentDomain.BaseDirectory, false); - CrossDomainTester crossDomainTester = CreateCrossDomainTester (testDomain); - try { - crossDomainTester.bug78465 (assemblyFileName); - } finally { - AppDomain.Unload (testDomain); - } + crossDomainTester.bug78465 (assemblyFileName); } finally { - File.Delete (assemblyFileName); + AppDomain.Unload (testDomain); } } @@ -665,9 +656,9 @@ namespace MonoTests.System.Reflection [Category("MobileNotWorking")] public void bug78468 () { - string assemblyFileNameA = Path.Combine (Path.GetTempPath (), + string assemblyFileNameA = Path.Combine (TempFolder, "bug78468a.dll"); - string resourceFileName = Path.Combine (Path.GetTempPath (), + string resourceFileName = Path.Combine (TempFolder, "readme.txt"); using (StreamWriter sw = File.CreateText (resourceFileName)) { @@ -675,62 +666,56 @@ namespace MonoTests.System.Reflection sw.Close (); } + AssemblyName assemblyName = new AssemblyName (); + assemblyName.Name = "bug78468a"; + + AssemblyBuilder ab = AppDomain.CurrentDomain + .DefineDynamicAssembly (assemblyName, + AssemblyBuilderAccess.Save, + TempFolder, + AppDomain.CurrentDomain.Evidence); + ab.AddResourceFile ("read", "readme.txt"); + ab.Save (Path.GetFileName (assemblyFileNameA)); + + Assembly assembly; + + using (FileStream fs = File.OpenRead (assemblyFileNameA)) { + byte[] buffer = new byte[fs.Length]; + fs.Read (buffer, 0, buffer.Length); + assembly = Assembly.Load (buffer); + fs.Close (); + } + + Assert.AreEqual (string.Empty, assembly.Location, "#A1"); + string[] resNames = assembly.GetManifestResourceNames (); + Assert.IsNotNull (resNames, "#A2"); + Assert.AreEqual (1, resNames.Length, "#A3"); + Assert.AreEqual ("read", resNames[0], "#A4"); + ManifestResourceInfo resInfo = assembly.GetManifestResourceInfo ("read"); + Assert.IsNotNull (resInfo, "#A5"); + Assert.AreEqual ("readme.txt", resInfo.FileName, "#A6"); + Assert.IsNull (resInfo.ReferencedAssembly, "#A7"); + Assert.AreEqual ((ResourceLocation) 0, resInfo.ResourceLocation, "#A8"); try { - AssemblyName assemblyName = new AssemblyName (); - assemblyName.Name = "bug78468a"; + assembly.GetManifestResourceStream ("read"); + Assert.Fail ("#A9"); + } catch (FileNotFoundException) { + } + try { + assembly.GetFile ("readme.txt"); + Assert.Fail ("#A10"); + } catch (FileNotFoundException) { + } - AssemblyBuilder ab = AppDomain.CurrentDomain - .DefineDynamicAssembly (assemblyName, - AssemblyBuilderAccess.Save, - Path.GetTempPath (), - AppDomain.CurrentDomain.Evidence); - ab.AddResourceFile ("read", "readme.txt"); - ab.Save (Path.GetFileName (assemblyFileNameA)); + string assemblyFileNameB = Path.Combine (TempFolder, + "bug78468b.dll"); - Assembly assembly; - - using (FileStream fs = File.OpenRead (assemblyFileNameA)) { - byte[] buffer = new byte[fs.Length]; - fs.Read (buffer, 0, buffer.Length); - assembly = Assembly.Load (buffer); - fs.Close (); - } - - Assert.AreEqual (string.Empty, assembly.Location, "#A1"); - string[] resNames = assembly.GetManifestResourceNames (); - Assert.IsNotNull (resNames, "#A2"); - Assert.AreEqual (1, resNames.Length, "#A3"); - Assert.AreEqual ("read", resNames[0], "#A4"); - ManifestResourceInfo resInfo = assembly.GetManifestResourceInfo ("read"); - Assert.IsNotNull (resInfo, "#A5"); - Assert.AreEqual ("readme.txt", resInfo.FileName, "#A6"); - Assert.IsNull (resInfo.ReferencedAssembly, "#A7"); - Assert.AreEqual ((ResourceLocation) 0, resInfo.ResourceLocation, "#A8"); - try { - assembly.GetManifestResourceStream ("read"); - Assert.Fail ("#A9"); - } catch (FileNotFoundException) { - } - try { - assembly.GetFile ("readme.txt"); - Assert.Fail ("#A10"); - } catch (FileNotFoundException) { - } - - string assemblyFileNameB = Path.Combine (Path.GetTempPath (), - "bug78468b.dll"); - - AppDomain testDomain = CreateTestDomain (AppDomain.CurrentDomain.BaseDirectory, false); - CrossDomainTester crossDomainTester = CreateCrossDomainTester (testDomain); - try { - crossDomainTester.bug78468 (assemblyFileNameB); - } finally { - AppDomain.Unload (testDomain); - File.Delete (assemblyFileNameB); - } + AppDomain testDomain = CreateTestDomain (AppDomain.CurrentDomain.BaseDirectory, false); + CrossDomainTester crossDomainTester = CreateCrossDomainTester (testDomain); + try { + crossDomainTester.bug78468 (assemblyFileNameB); } finally { - File.Delete (assemblyFileNameA); - File.Delete (resourceFileName); + AppDomain.Unload (testDomain); } } @@ -768,8 +753,7 @@ namespace MonoTests.System.Reflection [Category ("NotWorking")] // patch for bug #79720 must be committed first public void Load_Culture () { - string tempDir = Path.Combine (Path.GetTempPath (), - "MonoTests.System.Reflection.AssemblyTest"); + string tempDir = TempFolder; string cultureTempDir = Path.Combine (tempDir, "nl-BE"); if (!Directory.Exists (cultureTempDir)) Directory.CreateDirectory (cultureTempDir); @@ -866,8 +850,6 @@ namespace MonoTests.System.Reflection Assert.IsTrue (cdt.AssertFileNotFoundException (aname), "#D3"); } finally { AppDomain.Unload (ad); - if (Directory.Exists (tempDir)) - Directory.Delete (tempDir, true); } } @@ -875,8 +857,7 @@ namespace MonoTests.System.Reflection [Category ("NotWorking")] // in non-default domain, MS throws FileNotFoundException public void Load_Culture_Mismatch () { - string tempDir = Path.Combine (Path.GetTempPath (), - "MonoTests.System.Reflection.AssemblyTest"); + string tempDir = TempFolder; string cultureTempDir = Path.Combine (tempDir, "en-US"); if (!Directory.Exists (cultureTempDir)) Directory.CreateDirectory (cultureTempDir); @@ -910,8 +891,6 @@ namespace MonoTests.System.Reflection Assert.IsTrue (cdt.AssertFileNotFoundException (aname), "#B1"); } finally { AppDomain.Unload (ad); - if (Directory.Exists (tempDir)) - Directory.Delete (tempDir, true); } } @@ -920,10 +899,7 @@ namespace MonoTests.System.Reflection [Category("MobileNotWorking")] public void Load_PartialVersion () { - string tempDir = Path.Combine (Path.GetTempPath (), - "MonoTests.System.Reflection.AssemblyTest"); - if (!Directory.Exists (tempDir)) - Directory.CreateDirectory (tempDir); + string tempDir = TempFolder; AppDomain ad = CreateTestDomain (tempDir, true); try { @@ -953,8 +929,6 @@ namespace MonoTests.System.Reflection Assert.IsTrue (cdt.AssertLoad (aname.FullName), "#C2"); } finally { AppDomain.Unload (ad); - if (Directory.Exists (tempDir)) - Directory.Delete (tempDir, true); } } @@ -1128,22 +1102,7 @@ namespace MonoTests.System.Reflection [Test] public void bug79872 () { - Random rnd = new Random (); - string outdir; - int tries = 0; - - retry: - outdir = Path.Combine (Path.GetTempPath (), "bug79872-" + rnd.Next (10000, 99999)); - if (Directory.Exists (outdir)) { - try { - Directory.Delete (outdir, true); - } catch { - if (++tries <= 100) - goto retry; - } - } - - Directory.CreateDirectory (outdir); + string outdir = TempFolder; AssemblyName an = new AssemblyName (); an.Name = "bug79872"; @@ -1175,8 +1134,6 @@ namespace MonoTests.System.Reflection // swallow the rest } Assert.IsTrue (ok, "Complain on loading a .NET metadata file without an assembly manifest"); - - Directory.Delete (outdir, true); } #endif @@ -1320,7 +1277,6 @@ namespace MonoTests.System.Reflection Assert.AreEqual (GetType().Assembly, a); } -#if NET_4_5 [Test] public void DefinedTypes_Equality () { @@ -1329,7 +1285,19 @@ namespace MonoTests.System.Reflection Assert.AreSame (x1, x2, "#1"); } -#endif + + class MyAssembly : Assembly { } + + [Test] + public void CustomAssemblyImplThrows () + { + var ma = new MyAssembly(); + try { + ma.GetName (); + Assert.Fail ("must throw"); + } catch (NotImplementedException){ + } + } } public class TestDefinedTypes diff --git a/mcs/class/corlib/Test/System.Reflection/IntrospectionExtensionsTest.cs b/mcs/class/corlib/Test/System.Reflection/IntrospectionExtensionsTest.cs index f16d9a2a0f..a2d0f7cfac 100644 --- a/mcs/class/corlib/Test/System.Reflection/IntrospectionExtensionsTest.cs +++ b/mcs/class/corlib/Test/System.Reflection/IntrospectionExtensionsTest.cs @@ -26,7 +26,6 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -#if NET_4_5 using System; using System.Reflection; @@ -54,4 +53,3 @@ namespace MonoTests.System.Reflection } } -#endif \ No newline at end of file diff --git a/mcs/class/corlib/Test/System.Reflection/ModuleTest.cs b/mcs/class/corlib/Test/System.Reflection/ModuleTest.cs index c93fecfa42..d40ff368bc 100644 --- a/mcs/class/corlib/Test/System.Reflection/ModuleTest.cs +++ b/mcs/class/corlib/Test/System.Reflection/ModuleTest.cs @@ -24,13 +24,26 @@ namespace MonoTests.System.Reflection [TestFixture] public class ModuleTest { - static string TempFolder = Path.Combine (Path.GetTempPath (), "MonoTests.System.Reflection.ModuleTest"); + static string BaseTempFolder = Path.Combine (Path.GetTempPath (), "MonoTests.System.Reflection.ModuleTest"); + static string TempFolder; + + [TestFixtureSetUp] + public void FixtureSetUp () + { + try { + // Try to cleanup from any previous NUnit run. + Directory.Delete (BaseTempFolder, true); + } catch (Exception) { + } + } [SetUp] public void SetUp () { - while (Directory.Exists (TempFolder)) - TempFolder = Path.Combine (TempFolder, "2"); + int i = 0; + do { + TempFolder = Path.Combine (BaseTempFolder, (++i).ToString()); + } while (Directory.Exists (TempFolder)); Directory.CreateDirectory (TempFolder); } @@ -38,8 +51,8 @@ public class ModuleTest public void TearDown () { try { - // This throws an exception under MS.NET, since the directory contains loaded - // assemblies. + // This throws an exception under MS.NET and Mono on Windows, + // since the directory contains loaded assemblies. Directory.Delete (TempFolder, true); } catch (Exception) { } diff --git a/mcs/class/corlib/Test/System.Reflection/MonoGenericClassTest.cs b/mcs/class/corlib/Test/System.Reflection/MonoGenericClassTest.cs index d31b99fa49..c645120744 100644 --- a/mcs/class/corlib/Test/System.Reflection/MonoGenericClassTest.cs +++ b/mcs/class/corlib/Test/System.Reflection/MonoGenericClassTest.cs @@ -71,7 +71,7 @@ namespace MonoTests.System.Reflection.Emit #if !MOBILE Assert.AreEqual ("foo.type[[System.Double, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]", inst.FullName, "#3"); Assert.AreEqual ("foo.type[[System.Double, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], MonoTests.System.Reflection.Emit.MonoGenericClassTest, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", inst.AssemblyQualifiedName, "#4"); -#elif NET_2_1 || MOBILE +#elif MOBILE || MOBILE Assert.AreEqual ("foo.type[[System.Double, mscorlib, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.String, mscorlib, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]", inst.FullName, "#3"); Assert.AreEqual ("foo.type[[System.Double, mscorlib, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.String, mscorlib, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], MonoTests.System.Reflection.Emit.MonoGenericClassTest, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", inst.AssemblyQualifiedName, "#4"); Assert.AreEqual ("foo.type[System.Double,System.String]", inst.ToString (), "#5"); diff --git a/mcs/class/corlib/Test/System.Reflection/ParameterInfoTest.cs b/mcs/class/corlib/Test/System.Reflection/ParameterInfoTest.cs index 8d5fc3a921..fb2706d575 100644 --- a/mcs/class/corlib/Test/System.Reflection/ParameterInfoTest.cs +++ b/mcs/class/corlib/Test/System.Reflection/ParameterInfoTest.cs @@ -73,7 +73,7 @@ namespace MonoTests.System.Reflection } } -#if !NET_2_1 +#if !MOBILE public enum ParamEnum { None = 0, Foo = 1, @@ -97,14 +97,12 @@ namespace MonoTests.System.Reflection Assert.AreEqual (ParamEnum.Foo, info [5].DefaultValue, "#2"); } -#if NET_4_5 [Test] public void HasDefaultValueEnum () { ParameterInfo[] info = typeof (ParameterInfoTest).GetMethod ("paramMethod").GetParameters (); Assert.IsTrue (info [5].HasDefaultValue); } -#endif public static void Sample2 ([DecimalConstantAttribute(2,2,2,2,2)] decimal a, [DateTimeConstantAttribute(123456)] DateTime b) {} @@ -125,7 +123,6 @@ namespace MonoTests.System.Reflection Assert.AreEqual (pi [1].DefaultValue.GetType (), typeof (Missing), "#2"); } -#if NET_4_5 [Test] public void TestHasDefaultValues () { @@ -135,7 +132,6 @@ namespace MonoTests.System.Reflection Assert.IsFalse (pi [1].HasDefaultValue, "#2"); Assert.IsTrue (pi [2].HasDefaultValue, "#3"); } -#endif public void Sample (int a, [Optional] int b, object c = null) { @@ -252,13 +248,11 @@ namespace MonoTests.System.Reflection Assert.AreEqual (decimal.MaxValue, info [0].DefaultValue); } -#if NET_4_5 [Test] public void HasDefaultValueDecimal () { var info = typeof (ParameterInfoTest).GetMethod ("TestC").GetParameters (); Assert.IsTrue (info [0].HasDefaultValue); } -#endif class TestParamAttribute : Attribute { @@ -344,13 +338,11 @@ namespace MonoTests.System.Reflection Assert.AreEqual (0, p.GetCustomAttributes (typeof (FlagsAttribute), false).Length, "#3"); Assert.AreEqual (0, p.GetOptionalCustomModifiers ().Length, "#4"); Assert.AreEqual (0, p.GetRequiredCustomModifiers ().Length, "#5"); -#if NET_4_5 try { var ign = p.HasDefaultValue; Assert.Fail ("#6"); } catch (NotImplementedException) { } -#endif Assert.IsFalse (p.IsIn, "#7"); #if FEATURE_USE_LCID Assert.IsFalse (p.IsLcid, "#8"); @@ -358,13 +350,11 @@ namespace MonoTests.System.Reflection Assert.IsFalse (p.IsOptional, "#9"); Assert.IsFalse (p.IsOut, "#10"); Assert.IsFalse (p.IsRetval, "#10"); -#if NET_4_5 try { var ign = p.CustomAttributes; Assert.Fail ("#11"); } catch (NotImplementedException) { } -#endif try { p.GetCustomAttributesData (); Assert.Fail ("#12"); @@ -446,9 +436,7 @@ namespace MonoTests.System.Reflection Assert.IsFalse (p2.IsIn, "#1"); p2.MyAttrsImpl = ParameterAttributes.In; Assert.IsTrue (p2.IsIn, "#2"); -#if NET_4_5 Assert.AreEqual (p2.myList, p2.CustomAttributes, "#3"); -#endif } } } diff --git a/mcs/class/corlib/Test/System.Reflection/PropertyInfoTest.cs b/mcs/class/corlib/Test/System.Reflection/PropertyInfoTest.cs index 2fe870111c..4c4388ec8b 100644 --- a/mcs/class/corlib/Test/System.Reflection/PropertyInfoTest.cs +++ b/mcs/class/corlib/Test/System.Reflection/PropertyInfoTest.cs @@ -391,7 +391,12 @@ namespace MonoTests.System.Reflection var p = t.GetProperty ("Prop"); Assert.AreEqual ("test", p.GetConstantValue (), "#1"); - File.Delete (Path.Combine (Path.GetTempPath (), an)); + try { + // This throws an exception under MS.NET and Mono on Windows, + // open files cannot be deleted. That's fine. + File.Delete (Path.Combine (Path.GetTempPath (), an)); + } catch (Exception) { + } var pa = typeof (TestE).GetProperty ("PropE"); try { diff --git a/mcs/class/corlib/Test/System.Resources/ResourceReaderTest.cs b/mcs/class/corlib/Test/System.Resources/ResourceReaderTest.cs index 88690944df..55f00dd8be 100644 --- a/mcs/class/corlib/Test/System.Resources/ResourceReaderTest.cs +++ b/mcs/class/corlib/Test/System.Resources/ResourceReaderTest.cs @@ -28,15 +28,9 @@ namespace MonoTests.System.Resources [TestFixtureSetUp] public void FixtureSetUp () { - char ds = Path.DirectorySeparatorChar; - if (ds == '/') { - string base_path = Path.Combine (Directory.GetCurrentDirectory (), Path.Combine ("Test", "resources")); - m_ResourceFile = Path.Combine (base_path, "MyResources.resources"); - m_BadResourceFile = Path.Combine (base_path, "Empty.resources"); - } else { - m_ResourceFile = Path.Combine ("Test", Path.Combine ("resources", "MyResources.resources")); - m_BadResourceFile = "resources" + ds + "Empty.resources"; - } + string base_path = Path.Combine (Directory.GetCurrentDirectory (), Path.Combine ("Test", "resources")); + m_ResourceFile = Path.Combine (base_path, "MyResources.resources"); + m_BadResourceFile = Path.Combine (base_path, "Empty.resources"); } [SetUp] diff --git a/mcs/class/corlib/Test/System.Runtime.CompilerServices/AsyncVoidMethodBuilderTest.cs b/mcs/class/corlib/Test/System.Runtime.CompilerServices/AsyncVoidMethodBuilderTest.cs index 5edb1274e3..c442b3c7b8 100644 --- a/mcs/class/corlib/Test/System.Runtime.CompilerServices/AsyncVoidMethodBuilderTest.cs +++ b/mcs/class/corlib/Test/System.Runtime.CompilerServices/AsyncVoidMethodBuilderTest.cs @@ -26,7 +26,6 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -#if NET_4_5 using System; using System.Threading; @@ -117,4 +116,3 @@ namespace MonoTests.System.Runtime.CompilerServices } } -#endif \ No newline at end of file diff --git a/mcs/class/corlib/Test/System.Runtime.CompilerServices/TaskAwaiterTest.cs b/mcs/class/corlib/Test/System.Runtime.CompilerServices/TaskAwaiterTest.cs index 57b1d2c276..c9d7aca855 100644 --- a/mcs/class/corlib/Test/System.Runtime.CompilerServices/TaskAwaiterTest.cs +++ b/mcs/class/corlib/Test/System.Runtime.CompilerServices/TaskAwaiterTest.cs @@ -26,7 +26,6 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -#if NET_4_5 using System; using System.Threading; @@ -396,4 +395,3 @@ namespace MonoTests.System.Runtime.CompilerServices } } -#endif diff --git a/mcs/class/corlib/Test/System.Runtime.CompilerServices/TaskAwaiterTest_T.cs b/mcs/class/corlib/Test/System.Runtime.CompilerServices/TaskAwaiterTest_T.cs index 31242816cd..867a06cabc 100644 --- a/mcs/class/corlib/Test/System.Runtime.CompilerServices/TaskAwaiterTest_T.cs +++ b/mcs/class/corlib/Test/System.Runtime.CompilerServices/TaskAwaiterTest_T.cs @@ -26,7 +26,6 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -#if NET_4_5 using System; using System.Threading; @@ -173,4 +172,3 @@ namespace MonoTests.System.Runtime.CompilerServices } } -#endif \ No newline at end of file diff --git a/mcs/class/corlib/Test/System.Runtime.CompilerServices/YieldAwaitableTest.cs b/mcs/class/corlib/Test/System.Runtime.CompilerServices/YieldAwaitableTest.cs index cc53f6a8d9..fbb1d82115 100644 --- a/mcs/class/corlib/Test/System.Runtime.CompilerServices/YieldAwaitableTest.cs +++ b/mcs/class/corlib/Test/System.Runtime.CompilerServices/YieldAwaitableTest.cs @@ -26,7 +26,6 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -#if NET_4_5 using System; using System.Collections.Generic; @@ -183,4 +182,3 @@ namespace MonoTests.System.Runtime.CompilerServices } } -#endif \ No newline at end of file diff --git a/mcs/class/corlib/Test/System.Runtime.InteropServices/MarshalTest.cs b/mcs/class/corlib/Test/System.Runtime.InteropServices/MarshalTest.cs index bde7be3fd1..d4ca72dc0a 100644 --- a/mcs/class/corlib/Test/System.Runtime.InteropServices/MarshalTest.cs +++ b/mcs/class/corlib/Test/System.Runtime.InteropServices/MarshalTest.cs @@ -208,8 +208,8 @@ namespace MonoTests.System.Runtime.InteropServices [Test] public void GetHINSTANCE () { - if (RunningOnUnix) - Assert.Ignore ("GetHINSTANCE only applies to Windows."); + if (RunningOnMono) + Assert.Ignore ("GetHINSTANCE only applies to .NET on Windows."); Assembly a; IntPtr hinstance; @@ -307,9 +307,7 @@ namespace MonoTests.System.Runtime.InteropServices Assert.AreEqual (0x1234, Marshal.ReadInt16 (ptr)); Assert.AreEqual (0x1234, Marshal.ReadInt16 (ptr, 0)); Assert.AreEqual (0x4567, Marshal.ReadInt16 (ptr, 2)); -#if NET_4_5 Assert.AreEqual (0x4567, Marshal.ReadInt16 ((ptr + 5))); -#endif Assert.AreEqual (0x4567, Marshal.ReadInt16 (ptr, 5)); } finally { Marshal.FreeHGlobal (ptr); @@ -327,9 +325,7 @@ namespace MonoTests.System.Runtime.InteropServices Assert.AreEqual (0x12345678, Marshal.ReadInt32 (ptr)); Assert.AreEqual (0x12345678, Marshal.ReadInt32 (ptr, 0)); Assert.AreEqual (0x77654321, Marshal.ReadInt32 (ptr, 4)); -#if NET_4_5 Assert.AreEqual (0x77654321, Marshal.ReadInt32 ((ptr + 10))); -#endif Assert.AreEqual (0x77654321, Marshal.ReadInt32 (ptr, 10)); } finally { Marshal.FreeHGlobal (ptr); @@ -680,7 +676,7 @@ namespace MonoTests.System.Runtime.InteropServices } } -#if !NET_2_1 +#if !MOBILE [Test] public void TestGetComSlotForMethodInfo () { @@ -807,10 +803,9 @@ namespace MonoTests.System.Runtime.InteropServices ex = Marshal.GetExceptionForHR (E_INVALIDARG); Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "E_INVALIDARG"); } - bool RunningOnUnix { + bool RunningOnMono { get { - int p = (int) Environment.OSVersion.Platform; - return ((p == 4) || (p == 128) || (p == 6)); + return (Type.GetType ("System.MonoType", false) != null); } } @@ -827,8 +822,153 @@ namespace MonoTests.System.Runtime.InteropServices int nSize ); #endif + + [StructLayout( LayoutKind.Sequential, Pack = 1 )] + public class FourByteStruct + { + public UInt16 value1; + public UInt16 value2; + } + + [StructLayout( LayoutKind.Sequential, Pack = 1 )] + public class ByteArrayFourByteStruct : FourByteStruct + { + [MarshalAs( UnmanagedType.ByValArray, SizeConst = 5 )] + public byte[] array; + } + + [StructLayout( LayoutKind.Sequential, Pack = 1 )] + public class SingleByteStruct + { + public byte value1; + } + + [StructLayout( LayoutKind.Sequential, Pack = 1 )] + public class ByteArraySingleByteStruct : SingleByteStruct + { + [MarshalAs( UnmanagedType.ByValArray, SizeConst = 5 )] + public byte[] array1; + public byte value2; + } + + [StructLayout( LayoutKind.Sequential, Pack = 1 )] + public class ByteArraySingleByteChildStruct : ByteArraySingleByteStruct + { + [MarshalAs( UnmanagedType.ByValArray, SizeConst = 5 )] + public byte[] array2; + } + + [Test] + public void CheckByteArrayFourByteStruct() + { + ByteArrayFourByteStruct myStruct = new ByteArrayFourByteStruct + { value1 = 42, value2 = 53, array = Encoding.UTF8.GetBytes( "Hello" ) }; + + byte[] buffer = Serialize (myStruct); + + UInt16 value1 = BitConverter.ToUInt16 (buffer, 0); + UInt16 value2 = BitConverter.ToUInt16 (buffer, 2); + string array = Encoding.UTF8.GetString (buffer, 4, 5); + + Assert.AreEqual((UInt16)42, value1); + Assert.AreEqual((UInt16)53, value2); + Assert.AreEqual ("Hello", array); + } + + [Test] + public void CheckByteArraySingleByteChildStruct() + { + ByteArraySingleByteChildStruct myStruct = new ByteArraySingleByteChildStruct + { value1 = 42, array1 = Encoding.UTF8.GetBytes( "Hello" ), value2 = 53, array2 = Encoding.UTF8.GetBytes( "World" ) }; + + byte[] array = Serialize (myStruct); + + byte value1 = array [0]; + string array1 = Encoding.UTF8.GetString (array, 1, 5); + byte value2 = array [6]; + string array2 = Encoding.UTF8.GetString (array, 7, 5); + + Assert.AreEqual((byte)42, value1); + Assert.AreEqual ("Hello", array1); + Assert.AreEqual((byte)53, value2); + Assert.AreEqual ("World", array2); + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct FiveByteStruct + { + public uint uIntField; + public byte byteField; + }; + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public class Base + { + public ushort firstUShortField; + public ushort secondUShortField; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public class Derived : Base + { + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] + public FiveByteStruct[] arrayField; + } + + [Test] + public void CheckPtrToStructureWithFixedArrayAndBaseClassFields() + { + const int arraySize = 6; + var derived = new Derived + { + arrayField = new FiveByteStruct[arraySize], + firstUShortField = 42, + secondUShortField = 43 + }; + + for (var i = 0; i < arraySize; ++i) + { + derived.arrayField[i].byteField = (byte)i; + derived.arrayField[i].uIntField = (uint)i * 10; + } + + var array = Serialize(derived); + var deserializedDerived = Deserialize(array); + + Assert.AreEqual(derived.firstUShortField, deserializedDerived.firstUShortField, "The firstUShortField differs, which is not expected."); + Assert.AreEqual(derived.secondUShortField, deserializedDerived.secondUShortField, "The secondUShortField differs, which is not expected."); + + for (var i = 0; i < arraySize; ++i) + { + Assert.AreEqual(derived.arrayField[i].byteField, deserializedDerived.arrayField[i].byteField, string.Format("The byteField at index {0} differs, which is not expected.", i)); + Assert.AreEqual(derived.arrayField[i].uIntField, deserializedDerived.arrayField[i].uIntField, string.Format("The uIntField at index {0} differs, which is not expected.", i)); + } + } + + public static byte[] Serialize( object obj ) + { + int nTypeSize = Marshal.SizeOf( obj ); + byte[] arrBuffer = new byte[nTypeSize]; + + GCHandle hGCHandle = GCHandle.Alloc( arrBuffer, GCHandleType.Pinned ); + IntPtr pBuffer = hGCHandle.AddrOfPinnedObject(); + Marshal.StructureToPtr( obj, pBuffer, false ); + hGCHandle.Free(); + + return arrBuffer; + } + + public static T Deserialize(byte[] buffer) + { + var handle = GCHandle.Alloc(buffer, GCHandleType.Pinned); + var pBuffer = handle.AddrOfPinnedObject(); + var objResult = (T)Marshal.PtrToStructure(pBuffer, typeof(T)); + handle.Free(); + + return objResult; + } } -#if !NET_2_1 +#if !MOBILE [ComImport()] [Guid("AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA")] interface ITestDefault diff --git a/mcs/class/corlib/Test/System.Runtime.InteropServices/RuntimeEnvironmentTest.cs b/mcs/class/corlib/Test/System.Runtime.InteropServices/RuntimeEnvironmentTest.cs index 660a556c18..832ac6fc1c 100644 --- a/mcs/class/corlib/Test/System.Runtime.InteropServices/RuntimeEnvironmentTest.cs +++ b/mcs/class/corlib/Test/System.Runtime.InteropServices/RuntimeEnvironmentTest.cs @@ -58,7 +58,7 @@ namespace MonoTests.System.Runtime.InteropServices { [Test] #if MOBILE - [Ignore ("There's no GAC for the NET_2_1 based profiles (Moonlight, MonoTouch and Mono for Android")] + [Ignore ("There's no GAC for the MOBILE based profiles (Moonlight, MonoTouch and Mono for Android")] #endif public void FromGlobalAccessCache () { diff --git a/mcs/class/corlib/Test/System.Security.Claims/ClaimsIdentityTest.cs b/mcs/class/corlib/Test/System.Security.Claims/ClaimsIdentityTest.cs index 0456cbcdd1..7eb43817eb 100644 --- a/mcs/class/corlib/Test/System.Security.Claims/ClaimsIdentityTest.cs +++ b/mcs/class/corlib/Test/System.Security.Claims/ClaimsIdentityTest.cs @@ -2,7 +2,6 @@ // ClaimsIdentityTest.cs - NUnit Test Cases for System.Security.Claims.ClaimsIdentity // -#if NET_4_5 using NUnit.Framework; using System; @@ -561,4 +560,3 @@ namespace MonoTests.System.Security.Claims } } -#endif diff --git a/mcs/class/corlib/Test/System.Security.Claims/ClaimsPrincipalTest.cs b/mcs/class/corlib/Test/System.Security.Claims/ClaimsPrincipalTest.cs index 3d5660d256..35734b76b0 100644 --- a/mcs/class/corlib/Test/System.Security.Claims/ClaimsPrincipalTest.cs +++ b/mcs/class/corlib/Test/System.Security.Claims/ClaimsPrincipalTest.cs @@ -3,7 +3,6 @@ // ClaimsPrincipalTest.cs - NUnit Test Cases for System.Security.Claims.ClaimsPrincipal // -#if NET_4_5 using NUnit.Framework; using System; @@ -253,4 +252,3 @@ namespace MonoTests.System.Security.Claims } } -#endif diff --git a/mcs/class/corlib/Test/System.Security.Cryptography.X509Certificates/X509CapiTest.cs b/mcs/class/corlib/Test/System.Security.Cryptography.X509Certificates/X509CapiTest.cs index 328bbb54a5..efbc57018e 100644 --- a/mcs/class/corlib/Test/System.Security.Cryptography.X509Certificates/X509CapiTest.cs +++ b/mcs/class/corlib/Test/System.Security.Cryptography.X509Certificates/X509CapiTest.cs @@ -104,8 +104,8 @@ namespace MonoTests.System.Security.Cryptography.X509Certificates { } [Test] -#if NET_2_1 - [Ignore ("This constructor always throw a NotSupportedException under NET_2_1 and is useless without CryptoAPI (i.e. outside Windows)")] +#if MOBILE + [Ignore ("This constructor always throw a NotSupportedException under MOBILE and is useless without CryptoAPI (i.e. outside Windows)")] #endif public void ConstructorIntPtr () { diff --git a/mcs/class/corlib/Test/System.Security.Cryptography/CryptoConfigTest.cs b/mcs/class/corlib/Test/System.Security.Cryptography/CryptoConfigTest.cs index e141fa9e90..a3e95c65a6 100644 --- a/mcs/class/corlib/Test/System.Security.Cryptography/CryptoConfigTest.cs +++ b/mcs/class/corlib/Test/System.Security.Cryptography/CryptoConfigTest.cs @@ -137,7 +137,7 @@ public class CryptoConfigTest { // additional names (URL) used for XMLDSIG (System.Security.Cryptography.Xml) // URL taken from http://www.w3.org/TR/2002/REC-xmldsig-core-20020212/ [Test] -#if NET_2_1 +#if MOBILE [Ignore ("System.Security.dll is not part of Moonlight, MonoTouch and Mono for Android")] #endif public void CreateFromURL () @@ -145,6 +145,9 @@ public class CryptoConfigTest { // URL used in SignatureMethod element CreateFromName ("http://www.w3.org/2000/09/xmldsig#dsa-sha1", "System.Security.Cryptography.DSASignatureDescription"); CreateFromName ("http://www.w3.org/2000/09/xmldsig#rsa-sha1", "System.Security.Cryptography.RSAPKCS1SHA1SignatureDescription"); + CreateFromName ("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", "System.Security.Cryptography.RSAPKCS1SHA256SignatureDescription"); + CreateFromName ("http://www.w3.org/2001/04/xmldsig-more#rsa-sha384", "System.Security.Cryptography.RSAPKCS1SHA384SignatureDescription"); + CreateFromName ("http://www.w3.org/2001/04/xmldsig-more#rsa-sha512", "System.Security.Cryptography.RSAPKCS1SHA512SignatureDescription"); CreateFromName ("http://www.w3.org/2000/09/xmldsig#hmac-sha1", null); // URL used in DigestMethod element CreateFromName ("http://www.w3.org/2000/09/xmldsig#sha1", "System.Security.Cryptography.SHA1CryptoServiceProvider"); @@ -303,17 +306,24 @@ public class CryptoConfigTest { MapNameToOID ("System.Security.Cryptography.SHA1", "1.3.14.3.2.26"); // MapNameToOID ("System.Security.Cryptography.HashAlgorithm", "1.3.14.3.2.26"); MapNameToOID ("System.Security.Cryptography.SHA1CryptoServiceProvider", "1.3.14.3.2.26"); + MapNameToOID ("System.Security.Cryptography.SHA1Cng", "1.3.14.3.2.26"); MapNameToOID ("System.Security.Cryptography.SHA1Managed", "1.3.14.3.2.26"); MapNameToOID ("MD5", "1.2.840.113549.2.5"); MapNameToOID ("System.Security.Cryptography.MD5", "1.2.840.113549.2.5"); MapNameToOID ("System.Security.Cryptography.MD5CryptoServiceProvider", "1.2.840.113549.2.5"); MapNameToOID ("SHA256", "2.16.840.1.101.3.4.2.1"); + MapNameToOID ("System.Security.Cryptography.SHA256CryptoServiceProvider", "2.16.840.1.101.3.4.2.1"); + MapNameToOID ("System.Security.Cryptography.SHA256Cng", "2.16.840.1.101.3.4.2.1"); MapNameToOID ("System.Security.Cryptography.SHA256", "2.16.840.1.101.3.4.2.1"); MapNameToOID ("System.Security.Cryptography.SHA256Managed", "2.16.840.1.101.3.4.2.1"); MapNameToOID ("SHA384", "2.16.840.1.101.3.4.2.2"); + MapNameToOID ("System.Security.Cryptography.SHA384CryptoServiceProvider", "2.16.840.1.101.3.4.2.2"); + MapNameToOID ("System.Security.Cryptography.SHA384Cng", "2.16.840.1.101.3.4.2.2"); MapNameToOID ("System.Security.Cryptography.SHA384", "2.16.840.1.101.3.4.2.2"); MapNameToOID ("System.Security.Cryptography.SHA384Managed", "2.16.840.1.101.3.4.2.2"); MapNameToOID ("SHA512", "2.16.840.1.101.3.4.2.3"); + MapNameToOID ("System.Security.Cryptography.SHA512CryptoServiceProvider", "2.16.840.1.101.3.4.2.3"); + MapNameToOID ("System.Security.Cryptography.SHA512Cng", "2.16.840.1.101.3.4.2.3"); MapNameToOID ("System.Security.Cryptography.SHA512", "2.16.840.1.101.3.4.2.3"); MapNameToOID ("System.Security.Cryptography.SHA512Managed", "2.16.840.1.101.3.4.2.3"); MapNameToOID ("RIPEMD160", "1.3.36.3.2.1"); diff --git a/mcs/class/corlib/Test/System.Security.Cryptography/CryptoStreamTest.cs b/mcs/class/corlib/Test/System.Security.Cryptography/CryptoStreamTest.cs index 7f3320e9c9..7f3790421f 100644 --- a/mcs/class/corlib/Test/System.Security.Cryptography/CryptoStreamTest.cs +++ b/mcs/class/corlib/Test/System.Security.Cryptography/CryptoStreamTest.cs @@ -324,7 +324,7 @@ namespace MonoTests.System.Security.Cryptography { } } -#if !NET_2_1 +#if !MOBILE [Test] [ExpectedException (typeof (NotSupportedException))] public void Read_Disposed_Break () diff --git a/mcs/class/corlib/Test/System.Security.Cryptography/DSACryptoServiceProviderTest.cs b/mcs/class/corlib/Test/System.Security.Cryptography/DSACryptoServiceProviderTest.cs index a609ce74e2..e56a20c75c 100644 --- a/mcs/class/corlib/Test/System.Security.Cryptography/DSACryptoServiceProviderTest.cs +++ b/mcs/class/corlib/Test/System.Security.Cryptography/DSACryptoServiceProviderTest.cs @@ -857,7 +857,7 @@ public class DSACryptoServiceProviderTest { } } -#if !NET_2_1 +#if !MOBILE [Test] [Category ("NotWorking")] public void CspKeyContainerInfo_NewKeypair () diff --git a/mcs/class/corlib/Test/System.Security.Cryptography/HashAlgorithmTest.cs b/mcs/class/corlib/Test/System.Security.Cryptography/HashAlgorithmTest.cs index cb689ea25e..f5ba3ecf91 100644 --- a/mcs/class/corlib/Test/System.Security.Cryptography/HashAlgorithmTest.cs +++ b/mcs/class/corlib/Test/System.Security.Cryptography/HashAlgorithmTest.cs @@ -345,7 +345,7 @@ public class HashAlgorithmTest { public virtual bool ManagedHashImplementation { get { return false; } } -#if !NET_2_1 +#if !MOBILE [Test] [Category ("NotWorking")] // Mono nevers throws an exception (and we're all managed ;-) public void TransformFinalBlock_Twice () @@ -424,7 +424,7 @@ public class HashAlgorithmTest { { Assert.AreEqual (HashBuffer (false), HashBuffer (true), "Intersect"); } -#if !NET_2_1 +#if !MOBILE [Test] [ExpectedException (typeof (NullReferenceException))] [Category ("NotWorking")] // initialization problem ? fx2.0 only ? diff --git a/mcs/class/corlib/Test/System.Security.Cryptography/PasswordDeriveBytesTest.cs b/mcs/class/corlib/Test/System.Security.Cryptography/PasswordDeriveBytesTest.cs index 31401da3fe..375512ecd5 100644 --- a/mcs/class/corlib/Test/System.Security.Cryptography/PasswordDeriveBytesTest.cs +++ b/mcs/class/corlib/Test/System.Security.Cryptography/PasswordDeriveBytesTest.cs @@ -79,7 +79,7 @@ public class PasswordDeriveBytesTest { PasswordDeriveBytes pdb = new PasswordDeriveBytes (pwd, salt, new CspParameters ()); } -#if !NET_2_1 +#if !MOBILE [Test] [Category ("NotWorking")] // CspParameters aren't supported by Mono (requires CryptoAPI) public void Ctor_PasswordSaltNullCspParameters () @@ -100,7 +100,7 @@ public class PasswordDeriveBytesTest { Assert.AreEqual (ssalt, BitConverter.ToString (pdb.Salt), "Salt"); } -#if !NET_2_1 +#if !MOBILE [Test] [Category ("NotWorking")] // CspParameters aren't supported by Mono (requires CryptoAPI) public void Ctor_PasswordSaltCspParameters () @@ -176,7 +176,7 @@ public class PasswordDeriveBytesTest { PasswordDeriveBytes pdb = new PasswordDeriveBytes (pwd, salt, "SHA1", 1, new CspParameters ()); } -#if !NET_2_1 +#if !MOBILE [Test] [Category ("NotWorking")] // CspParameters aren't supported by Mono (requires CryptoAPI) public void Ctor_PasswordSaltNullHashIterationCspParameters () @@ -209,7 +209,7 @@ public class PasswordDeriveBytesTest { PasswordDeriveBytes pdb = new PasswordDeriveBytes ("s3kr3t", salt, "SHA1", 0, new CspParameters ()); } -#if !NET_2_1 +#if !MOBILE [Test] [Category ("NotWorking")] // CspParameters aren't supported by Mono (requires CryptoAPI) public void Ctor_PasswordSaltHashIterationMaxValueCspParameters () @@ -230,7 +230,7 @@ public class PasswordDeriveBytesTest { Assert.AreEqual (ssalt, BitConverter.ToString (pdb.Salt), "Salt"); } -#if !NET_2_1 +#if !MOBILE [Test] [Category ("NotWorking")] // CspParameters aren't supported by Mono (requires CryptoAPI) public void Ctor_PasswordSaltHashIterationCspParameters () @@ -669,7 +669,7 @@ public class PasswordDeriveBytesTest { pd.CryptDeriveKey ("AlgName", "MD5", -256, new byte [8]); } -#if !NET_2_1 +#if !MOBILE [Test] [Category ("NotWorking")] // bug #79499 public void LongMultipleGetBytes () diff --git a/mcs/class/corlib/Test/System.Security.Cryptography/RNGCryptoServiceProviderTest.cs b/mcs/class/corlib/Test/System.Security.Cryptography/RNGCryptoServiceProviderTest.cs index 6f351c4edd..2ebcad4a36 100644 --- a/mcs/class/corlib/Test/System.Security.Cryptography/RNGCryptoServiceProviderTest.cs +++ b/mcs/class/corlib/Test/System.Security.Cryptography/RNGCryptoServiceProviderTest.cs @@ -25,7 +25,7 @@ namespace MonoTests.System.Security.Cryptography { { _algo = new RNGCryptoServiceProvider (); } -#if !NET_2_1 +#if !MOBILE [Test] public void ConstructorByteArray () { diff --git a/mcs/class/corlib/Test/System.Security.Cryptography/RSACryptoServiceProviderTest.cs.REMOVED.git-id b/mcs/class/corlib/Test/System.Security.Cryptography/RSACryptoServiceProviderTest.cs.REMOVED.git-id index 2092582245..48194a331a 100644 --- a/mcs/class/corlib/Test/System.Security.Cryptography/RSACryptoServiceProviderTest.cs.REMOVED.git-id +++ b/mcs/class/corlib/Test/System.Security.Cryptography/RSACryptoServiceProviderTest.cs.REMOVED.git-id @@ -1 +1 @@ -8a20b9add458b2d2ed9ff7c097f7a140479c7215 \ No newline at end of file +6e44e3235b24061c7626bc48311a4cacbf686184 \ No newline at end of file diff --git a/mcs/class/corlib/Test/System.Security.Cryptography/RijndaelManagedTest.cs b/mcs/class/corlib/Test/System.Security.Cryptography/RijndaelManagedTest.cs index b7bf46057a..5a200bbfa3 100644 --- a/mcs/class/corlib/Test/System.Security.Cryptography/RijndaelManagedTest.cs +++ b/mcs/class/corlib/Test/System.Security.Cryptography/RijndaelManagedTest.cs @@ -277,7 +277,7 @@ namespace MonoTests.System.Security.Cryptography { CreateEncryptor_IV (size); } -#if !NET_2_1 +#if !MOBILE [Test] [ExpectedException (typeof (CryptographicException))] // Rijndael is the only implementation that has @@ -324,7 +324,7 @@ namespace MonoTests.System.Security.Cryptography { int size = (aes.BlockSize >> 3); CreateDecryptor_IV (size); } -#if !NET_2_1 +#if !MOBILE [Test] [ExpectedException (typeof (CryptographicException))] // Rijndael is the only implementation that has diff --git a/mcs/class/corlib/Test/System.Security.Cryptography/SignatureDescriptionTest.cs b/mcs/class/corlib/Test/System.Security.Cryptography/SignatureDescriptionTest.cs index 38a4aa7faf..46fbe94a6d 100644 --- a/mcs/class/corlib/Test/System.Security.Cryptography/SignatureDescriptionTest.cs +++ b/mcs/class/corlib/Test/System.Security.Cryptography/SignatureDescriptionTest.cs @@ -307,19 +307,35 @@ public class SignatureDescriptionTest { } [Test] - public void RSASignatureDescription () + public void RSASignatureDescription () + { +// TODO: this would be cleaner with NUnit TestCase'es but they're NUnit 2.5+ :( +#if FULL_AOT_RUNTIME || MONOTOUCH || MONODROID + RSASignatureDescriptionCore ("http://www.w3.org/2000/09/xmldsig#rsa-sha1", "System.Security.Cryptography.SHA1Cng", "System.Security.Cryptography.SHA1CryptoServiceProvider"); + RSASignatureDescriptionCore ("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", "System.Security.Cryptography.SHA256Cng", "System.Security.Cryptography.SHA256Managed"); + RSASignatureDescriptionCore ("http://www.w3.org/2001/04/xmldsig-more#rsa-sha384", "System.Security.Cryptography.SHA384Cng", "System.Security.Cryptography.SHA384Managed"); + RSASignatureDescriptionCore ("http://www.w3.org/2001/04/xmldsig-more#rsa-sha512", "System.Security.Cryptography.SHA512Cng", "System.Security.Cryptography.SHA512Managed"); +#else + RSASignatureDescriptionCore ("http://www.w3.org/2000/09/xmldsig#rsa-sha1", "System.Security.Cryptography.SHA1Cng", "System.Security.Cryptography.SHA1Cng"); + RSASignatureDescriptionCore ("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", "System.Security.Cryptography.SHA256Cng", "System.Security.Cryptography.SHA256Cng"); + RSASignatureDescriptionCore ("http://www.w3.org/2001/04/xmldsig-more#rsa-sha384", "System.Security.Cryptography.SHA384Cng", "System.Security.Cryptography.SHA384Cng"); + RSASignatureDescriptionCore ("http://www.w3.org/2001/04/xmldsig-more#rsa-sha512", "System.Security.Cryptography.SHA512Cng", "System.Security.Cryptography.SHA512Cng"); +#endif + } + + void RSASignatureDescriptionCore (string name, string expectedDigestAlgorithm, string expectedSelectedDigestAlgorithm) { // internal class - we cannot create one without CryptoConfig - SignatureDescription sd = (SignatureDescription) CryptoConfig.CreateFromName ("http://www.w3.org/2000/09/xmldsig#rsa-sha1"); - Assert.AreEqual ("System.Security.Cryptography.SHA1CryptoServiceProvider", sd.DigestAlgorithm); + SignatureDescription sd = (SignatureDescription) CryptoConfig.CreateFromName (name); + Assert.AreEqual (expectedDigestAlgorithm, sd.DigestAlgorithm); Assert.AreEqual ("System.Security.Cryptography.RSAPKCS1SignatureDeformatter", sd.DeformatterAlgorithm); Assert.AreEqual ("System.Security.Cryptography.RSAPKCS1SignatureFormatter", sd.FormatterAlgorithm); - Assert.AreEqual ("System.Security.Cryptography.RSACryptoServiceProvider", sd.KeyAlgorithm); + Assert.AreEqual ("System.Security.Cryptography.RSA", sd.KeyAlgorithm); HashAlgorithm hash = sd.CreateDigest(); - Assert.AreEqual ("System.Security.Cryptography.SHA1CryptoServiceProvider", hash.ToString ()); + Assert.AreEqual (expectedSelectedDigestAlgorithm, hash.ToString ()); - Assert.AreEqual (rsa.ToString (), sd.KeyAlgorithm); + Assert.AreEqual ("System.Security.Cryptography.RSA", sd.KeyAlgorithm); AsymmetricSignatureDeformatter asd = sd.CreateDeformatter (rsa); Assert.AreEqual ("System.Security.Cryptography.RSAPKCS1SignatureDeformatter", asd.ToString ()); @@ -329,4 +345,4 @@ public class SignatureDescriptionTest { } } -} \ No newline at end of file +} diff --git a/mcs/class/corlib/Test/System.Security.Policy/ZoneTest.cs b/mcs/class/corlib/Test/System.Security.Policy/ZoneTest.cs index 00aa374348..f75b723ff4 100644 --- a/mcs/class/corlib/Test/System.Security.Policy/ZoneTest.cs +++ b/mcs/class/corlib/Test/System.Security.Policy/ZoneTest.cs @@ -229,7 +229,7 @@ namespace MonoTests.System.Security.Policy { "http://*.go-mono.com", "http://www.go-mono.com:8080/index.html", "mono://unknown/protocol", - Path.DirectorySeparatorChar + "mono" + Path.DirectorySeparatorChar + "index.html", + "/mono/index.html", }; [Test] diff --git a/mcs/class/corlib/Test/System.Security/HostSecurityManagerTest.cs b/mcs/class/corlib/Test/System.Security/HostSecurityManagerTest.cs index 80336afc64..a420ffb560 100644 --- a/mcs/class/corlib/Test/System.Security/HostSecurityManagerTest.cs +++ b/mcs/class/corlib/Test/System.Security/HostSecurityManagerTest.cs @@ -27,8 +27,8 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -// NET_2_1 profile lacks some (of the few) CAS features required to execute those tests -#if !NET_2_1 +// MOBILE profile lacks some (of the few) CAS features required to execute those tests +#if !MOBILE using NUnit.Framework; using System; diff --git a/mcs/class/corlib/Test/System.Threading.Tasks/ConcurrentExclusiveSchedulerPairTest.cs b/mcs/class/corlib/Test/System.Threading.Tasks/ConcurrentExclusiveSchedulerPairTest.cs index a02ffe9698..264095d8b3 100644 --- a/mcs/class/corlib/Test/System.Threading.Tasks/ConcurrentExclusiveSchedulerPairTest.cs +++ b/mcs/class/corlib/Test/System.Threading.Tasks/ConcurrentExclusiveSchedulerPairTest.cs @@ -24,7 +24,6 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#if NET_4_5 using System; using System.Threading; @@ -176,4 +175,3 @@ namespace MonoTests.System.Threading.Tasks } } -#endif \ No newline at end of file diff --git a/mcs/class/corlib/Test/System.Threading.Tasks/TaskTest.cs b/mcs/class/corlib/Test/System.Threading.Tasks/TaskTest.cs index 15ee9bfbdc..f4e8a9705f 100644 --- a/mcs/class/corlib/Test/System.Threading.Tasks/TaskTest.cs +++ b/mcs/class/corlib/Test/System.Threading.Tasks/TaskTest.cs @@ -409,7 +409,6 @@ namespace MonoTests.System.Threading.Tasks Assert.IsTrue (tasks[1].IsCanceled, "#4"); } -#if NET_4_5 [Test] public void WaitAll_CancelledAndTimeout () { @@ -418,7 +417,6 @@ namespace MonoTests.System.Threading.Tasks var t2 = Task.Delay (3000); Assert.IsFalse (Task.WaitAll (new[] { t1, t2 }, 10)); } -#endif [Test] public void WaitAllExceptionThenCancelled () @@ -1216,7 +1214,6 @@ namespace MonoTests.System.Threading.Tasks } } -#if NET_4_5 [Test] public void ContinuationOnBrokenScheduler () { @@ -2111,6 +2108,5 @@ namespace MonoTests.System.Threading.Tasks } } -#endif } } diff --git a/mcs/class/corlib/Test/System.Threading/CancellationTokenSourceTest.cs b/mcs/class/corlib/Test/System.Threading/CancellationTokenSourceTest.cs index 3a80f5ae0d..f5b4dd9a3b 100644 --- a/mcs/class/corlib/Test/System.Threading/CancellationTokenSourceTest.cs +++ b/mcs/class/corlib/Test/System.Threading/CancellationTokenSourceTest.cs @@ -38,7 +38,6 @@ namespace MonoTests.System.Threading [TestFixture] public class CancellationTokenSourceTest { -#if NET_4_5 [Test] public void Ctor_Invalid () @@ -100,7 +99,6 @@ namespace MonoTests.System.Threading Assert.AreEqual (0, called, "#1"); } -#endif [Test] public void Token () @@ -345,13 +343,11 @@ namespace MonoTests.System.Threading } catch (ObjectDisposedException) { } -#if NET_4_5 try { cts.CancelAfter (1); Assert.Fail ("#6"); } catch (ObjectDisposedException) { } -#endif } [Test] @@ -478,7 +474,6 @@ namespace MonoTests.System.Threading } } -#if NET_4_5 [Test] public void DisposeRace () { @@ -490,7 +485,6 @@ namespace MonoTests.System.Threading c1.Dispose (); } } -#endif } } diff --git a/mcs/class/corlib/Test/System.Threading/EventWaitHandleTest.cs b/mcs/class/corlib/Test/System.Threading/EventWaitHandleTest.cs index c0e50b9cb8..005a9d8688 100644 --- a/mcs/class/corlib/Test/System.Threading/EventWaitHandleTest.cs +++ b/mcs/class/corlib/Test/System.Threading/EventWaitHandleTest.cs @@ -43,6 +43,18 @@ namespace MonoTests.System.Threading { { new EventWaitHandle (true, (EventResetMode) Int32.MinValue); } + + [Test] + public void Disposed_Set () + { + var ewh = new EventWaitHandle (false, EventResetMode.ManualReset); + ewh.Dispose(); + try { + ewh.Set(); + Assert.Fail (); + } catch (ObjectDisposedException) { + } + } } } diff --git a/mcs/class/corlib/Test/System.Threading/ThreadTest.cs b/mcs/class/corlib/Test/System.Threading/ThreadTest.cs index a869f7191f..4c6694f1e1 100644 --- a/mcs/class/corlib/Test/System.Threading/ThreadTest.cs +++ b/mcs/class/corlib/Test/System.Threading/ThreadTest.cs @@ -94,25 +94,6 @@ namespace MonoTests.System.Threading //TimeSpan MaxValue = TimeSpan.FromMilliseconds ((long) Int32.MaxValue); TimeSpan TooLarge = TimeSpan.FromMilliseconds ((long) Int32.MaxValue + 1); - static bool is_win32; - static bool is_mono; - - static ThreadTest () - { - switch (Environment.OSVersion.Platform) { - case PlatformID.Win32NT: - case PlatformID.Win32S: - case PlatformID.Win32Windows: - case PlatformID.WinCE: - is_win32 = true; - break; - } - - // check a class in mscorlib to determine if we're running on Mono - if (Type.GetType ("Mono.Runtime", false) != null) - is_mono = true; - } - //Some Classes to test as threads private class C1Test { @@ -327,8 +308,6 @@ namespace MonoTests.System.Threading [Category ("NotDotNet")] // it hangs. public void TestStart() { - if (is_win32 && is_mono) - Assert.Fail ("This test fails on Win32. The test should be fixed."); { C1Test test1 = new C1Test(); Thread TestThread = new Thread(new ThreadStart(test1.TestMethod)); @@ -370,9 +349,6 @@ namespace MonoTests.System.Threading [Test] public void TestApartmentState () { - if (is_win32 && is_mono) - Assert.Fail ("This test fails on mono on win32. Our runtime should be fixed."); - C2Test test1 = new C2Test(); Thread TestThread = new Thread(new ThreadStart(test1.TestMethod)); Assert.AreEqual (ApartmentState.Unknown, TestThread.ApartmentState, "#1"); @@ -390,9 +366,6 @@ namespace MonoTests.System.Threading [Category ("NotWorking")] // setting the priority of a Thread before it is started isn't implemented in Mono yet public void TestPriority1() { - if (is_win32 && is_mono) - Assert.Fail ("This test fails on mono on Win32. Our runtime should be fixed."); - C2Test test1 = new C2Test(); Thread TestThread = new Thread(new ThreadStart(test1.TestMethod)); try { @@ -487,9 +460,6 @@ namespace MonoTests.System.Threading [Test] public void TestIsBackground1 () { - if (is_win32 && is_mono) - Assert.Fail ("This test fails on mono on Win32. Our runtime should be fixed."); - C2Test test1 = new C2Test(); Thread TestThread = new Thread(new ThreadStart(test1.TestMethod)); try { @@ -534,9 +504,6 @@ namespace MonoTests.System.Threading [Test] public void TestName() { - if (is_win32 && is_mono) - Assert.Fail ("This test fails on mono on Win32. Our runtime should be fixed."); - C2Test test1 = new C2Test(); Thread TestThread = new Thread(new ThreadStart(test1.TestMethod)); try { @@ -696,9 +663,6 @@ namespace MonoTests.System.Threading [Test] public void TestThreadState () { - if (is_win32 && is_mono) - Assert.Fail ("This test fails on mono on Win32. Our runtime should be fixed."); - //TODO: Test The rest of the possible transitions C2Test test1 = new C2Test(); Thread TestThread = new Thread(new ThreadStart(test1.TestMethod)); @@ -830,9 +794,6 @@ namespace MonoTests.System.Threading [Category("NotDotNet")] // On MS, ThreadStateException is thrown on Abort: "Thread is suspended; attempting to abort" public void TestSuspendAbort () { - if (is_win32 && is_mono) - Assert.Fail ("This test fails on Win32. The test should be fixed."); - Thread t = new Thread (new ThreadStart (DoCount)); t.IsBackground = true; t.Start (); @@ -898,7 +859,6 @@ namespace MonoTests.System.Threading } [Test] - [Category ("NotDotNet")] // it crashes nunit. public void Test_InterruptCurrentThread () { ManualResetEvent mre = new ManualResetEvent (false); @@ -937,6 +897,7 @@ namespace MonoTests.System.Threading #if MONO_FEATURE_MULTIPLE_APPDOMAINS [Test] + [Category ("NotDotNet")] public void CurrentThread_Domains () { AppDomain ad = AppDomain.CreateDomain ("foo"); diff --git a/mcs/class/corlib/Test/System.Threading/VolatileTest.cs b/mcs/class/corlib/Test/System.Threading/VolatileTest.cs index 3743ea2b30..c3b37a9940 100644 --- a/mcs/class/corlib/Test/System.Threading/VolatileTest.cs +++ b/mcs/class/corlib/Test/System.Threading/VolatileTest.cs @@ -26,7 +26,6 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -#if NET_4_5 using System; using System.Threading; @@ -146,5 +145,4 @@ namespace MonoTests.System.Threading } } -#endif diff --git a/mcs/class/corlib/Test/System/AppDomainSetupTest.cs b/mcs/class/corlib/Test/System/AppDomainSetupTest.cs index 121d1c45f1..387d0318a3 100644 --- a/mcs/class/corlib/Test/System/AppDomainSetupTest.cs +++ b/mcs/class/corlib/Test/System/AppDomainSetupTest.cs @@ -23,8 +23,12 @@ namespace MonoTests.System private bool RunningOnWindows { get { - int os = (int)Environment.OSVersion.Platform; - return (os != 4); + return Path.DirectorySeparatorChar == '\\'; + } + } + private bool RunningOnMono { + get { + return (Type.GetType ("System.MonoType", false) != null); } } @@ -72,22 +76,18 @@ namespace MonoTests.System [Test] public void ApplicationBase1 () { - string expected_path = tmpPath.Replace(@"\", @"/"); + string expected_path = tmpPath; AppDomainSetup setup = new AppDomainSetup (); - string fileUri = "file://" + expected_path; + string fileUri = "file://" + tmpPath.Replace(@"\", @"/"); setup.ApplicationBase = fileUri; - // with MS 1.1 SP1 the expected_path starts with "//" but this make - // sense only under Windows (i.e. reversed \\ for local files) - if (RunningOnWindows) - expected_path = "//" + expected_path; try { - // under 2.0 the NotSupportedException is throw when getting + // under .NET the NotSupportedException is throw when getting // (and not setting) the ApplicationBase property Assert.AreEqual (expected_path, setup.ApplicationBase); } catch (NotSupportedException) { - // however the path is invalid only on Windows - if (!RunningOnWindows) + // however the path is invalid only on .NET + if (RunningOnMono) throw; } } @@ -114,16 +114,17 @@ namespace MonoTests.System { AppDomainSetup setup = new AppDomainSetup (); setup.ApplicationBase = "lala:la"; - try { - // under 2.0 the NotSupportedException is throw when getting - // (and not setting) the ApplicationBase property + if (!RunningOnWindows) { Assert.AreEqual (Path.GetFullPath ("lala:la"), setup.ApplicationBase); - } - catch (NotSupportedException) { - // however the path is invalid only on Windows - // (same exceptions as Path.GetFullPath) - if (!RunningOnWindows) - throw; + } else { + // On Windows we expect a NotSupportedException to be thrown because + // of the illegal character (:) in the path + try { + Assert.Fail ("NotSupportedException expected but setup.ApplicationBase returned:" + setup.ApplicationBase); + } + catch (NotSupportedException) { + // Expected + } } } @@ -133,16 +134,18 @@ namespace MonoTests.System // This is failing because of (probably) a windows-ism, so don't worry AppDomainSetup setup = new AppDomainSetup (); setup.ApplicationBase = "file:///lala:la"; - try { - // under 2.0 the NotSupportedException is throw when getting - // (and not setting) the ApplicationBase property - Assert.AreEqual ("/lala:la", setup.ApplicationBase); - } - catch (NotSupportedException) { - // however the path is invalid only on Windows - // (same exceptions as Path.GetFullPath) - if (!RunningOnWindows) - throw; + string expected = "/lala:la"; + if (!RunningOnWindows) { + Assert.AreEqual (expected, setup.ApplicationBase); + } else { + // On Windows we expect a NotSupportedException to be thrown because + // of the illegal character (:) in the path + try { + Assert.Fail ("NotSupportedException expected but setup.ApplicationBase returned:" + setup.ApplicationBase); + } + catch (NotSupportedException) { + // Expected + } } } @@ -153,19 +156,45 @@ namespace MonoTests.System setup.ApplicationBase = "la?lala"; // paths containing "?" are *always* bad on Windows // but are legal for linux so we return a full path - if (RunningOnWindows) { + if (!RunningOnWindows) { + Assert.AreEqual (Path.GetFullPath ("la?lala"), setup.ApplicationBase); + } else { + // On Windows we expect a ArgumentException to be thrown because + // of the illegal character (?) in the path try { - // ArgumentException is throw when getting - // (and not setting) the ApplicationBase property - Assert.Fail ("setup.ApplicationBase returned :" + setup.ApplicationBase); + Assert.Fail ("ArgumentException expected but setup.ApplicationBase returned:" + setup.ApplicationBase); } catch (ArgumentException) { + // Expected } - catch (Exception e) { - Assert.Fail ("Unexpected exception: " + e.ToString ()); + } + } + + [Test] + public void ApplicationBase7 () + { + if (RunningOnWindows) { + // Extended paths are Windows only + AppDomainSetup setup = new AppDomainSetup (); + string expected = @"\\?\" + curDir; + setup.ApplicationBase = expected; + Assert.AreEqual (expected, setup.ApplicationBase); + } + } + + [Test] + public void ApplicationBase8 () + { + if (RunningOnWindows) { + // Extended paths are Windows only + AppDomainSetup setup = new AppDomainSetup (); + setup.ApplicationBase = @"\\?\C:\lala:la"; + try { + Assert.Fail ("NotSupportedException expected but setup.ApplicationBase returned:" + setup.ApplicationBase); + } + catch (NotSupportedException) { + // Expected } - } else { - Assert.AreEqual (Path.GetFullPath ("la?lala"), setup.ApplicationBase); } } diff --git a/mcs/class/corlib/Test/System/AppDomainTest.cs.REMOVED.git-id b/mcs/class/corlib/Test/System/AppDomainTest.cs.REMOVED.git-id index 9d86f517a5..0ec07d938a 100644 --- a/mcs/class/corlib/Test/System/AppDomainTest.cs.REMOVED.git-id +++ b/mcs/class/corlib/Test/System/AppDomainTest.cs.REMOVED.git-id @@ -1 +1 @@ -03de187af3d953521b3b78452e6eff523b6be07a \ No newline at end of file +34874b1f81f0bae8977486ef067eec0eceac7e71 \ No newline at end of file diff --git a/mcs/class/corlib/Test/System/ArraySegmentTest.cs b/mcs/class/corlib/Test/System/ArraySegmentTest.cs index 28588f8e00..7fa93e8fcf 100644 --- a/mcs/class/corlib/Test/System/ArraySegmentTest.cs +++ b/mcs/class/corlib/Test/System/ArraySegmentTest.cs @@ -156,7 +156,6 @@ namespace MonoTests.System Assert.AreEqual (myArrSeg_1 != myArrSeg_2, true); } -#if NET_4_5 [Test] public void IList_NotSupported () { @@ -278,6 +277,5 @@ namespace MonoTests.System IList seg = new ArraySegment (arr); seg[4] = 3; } -#endif } } diff --git a/mcs/class/corlib/Test/System/AttributeTest.cs b/mcs/class/corlib/Test/System/AttributeTest.cs index d609c18883..dd66b8c7a2 100644 --- a/mcs/class/corlib/Test/System/AttributeTest.cs +++ b/mcs/class/corlib/Test/System/AttributeTest.cs @@ -903,7 +903,13 @@ namespace MonoTests.System Assert.AreEqual (1, res.Length, "#1"); } - abstract class Abs + abstract class Root + { + [MyAttribute] + public abstract void Foo (); + } + + abstract class Abs : Root { public abstract string Name { get; set; } } @@ -915,6 +921,8 @@ namespace MonoTests.System get { return ""; } set {} } + + public override void Foo () { } } class Sub: Base @@ -1032,6 +1040,27 @@ namespace MonoTests.System a.GetHashCode (); } + + [Test] + public void DerivedClassOverrideHasInhertedAttributeFromAbstractRoot () + { + // regression test for #44010 + // we have + // abstract class Root { + // [MyAttribute] + // public abstract void Foo (); + // } + // abstract class Abs : Root { } + // class Base : Abs { + // public override void Foo () { } + // } + // note that Abs does not itself override Foo. + var bt = typeof(Base); + var m = bt.GetMethod ("Foo"); + var attribute = Attribute.GetCustomAttribute (m, typeof (MyAttribute), true); + Assert.IsNotNull (attribute); + } + class ArrayAttribute : Attribute { #pragma warning disable 414 diff --git a/mcs/class/corlib/Test/System/BitConverterTest.cs b/mcs/class/corlib/Test/System/BitConverterTest.cs index 75775d3aa7..b69d81d535 100644 --- a/mcs/class/corlib/Test/System/BitConverterTest.cs +++ b/mcs/class/corlib/Test/System/BitConverterTest.cs @@ -790,7 +790,7 @@ namespace MonoTests.System Assert.IsNull (ex.InnerException, "#C3"); Assert.IsNotNull (ex.Message, "#C4"); Assert.IsNotNull (ex.ParamName, "#C5"); - Assert.AreEqual ("byteArray", ex.ParamName, "#C6"); + Assert.AreEqual ("value", ex.ParamName, "#C6"); } } diff --git a/mcs/class/corlib/Test/System/ConsoleTest.cs b/mcs/class/corlib/Test/System/ConsoleTest.cs index 1d9f1a10bc..93676f9dd0 100644 --- a/mcs/class/corlib/Test/System/ConsoleTest.cs +++ b/mcs/class/corlib/Test/System/ConsoleTest.cs @@ -332,7 +332,6 @@ public class ConsoleTest #if !MOBILE -#if NET_4_5 [Test] public void RedirectedTest () { @@ -343,7 +342,6 @@ public class ConsoleTest Console.SetError (TextWriter.Null); Assert.IsFalse (Console.IsErrorRedirected); } -#endif // Bug 678357 [Test] diff --git a/mcs/class/corlib/Test/System/ConvertTest.cs.REMOVED.git-id b/mcs/class/corlib/Test/System/ConvertTest.cs.REMOVED.git-id index cc2d20875f..48dc1b6986 100644 --- a/mcs/class/corlib/Test/System/ConvertTest.cs.REMOVED.git-id +++ b/mcs/class/corlib/Test/System/ConvertTest.cs.REMOVED.git-id @@ -1 +1 @@ -2124aa85733b05943c15d6c00f8c006ed856713e \ No newline at end of file +2391dbb65071a4f0a313703b9e3aac16d322de59 \ No newline at end of file diff --git a/mcs/class/corlib/Test/System/DelegateTest.cs b/mcs/class/corlib/Test/System/DelegateTest.cs index ae5a82908c..ba664353ab 100644 --- a/mcs/class/corlib/Test/System/DelegateTest.cs +++ b/mcs/class/corlib/Test/System/DelegateTest.cs @@ -1251,7 +1251,7 @@ namespace MonoTests.System } } - delegate int IntNoArgs (); + public delegate int IntNoArgs (); [Test] public void CreateDelegateWithAbstractMethods () @@ -1445,6 +1445,18 @@ namespace MonoTests.System var del = Delegate.Remove (del1, del2); } + [Test] + [ExpectedException (typeof (ArgumentException))] + public void CreateDelegateThrowsAnArgumentExceptionWhenCalledWithAnOpenGeneric() + { + var m = GetType().GetMethod("AnyGenericMethod"); + Delegate.CreateDelegate(typeof(Action), this, m); + } + + public void AnyGenericMethod() + { + } + static bool Int32D2 (int x, int y) { return (x & y) == y; diff --git a/mcs/class/corlib/Test/System/DoubleTest.cs b/mcs/class/corlib/Test/System/DoubleTest.cs index 30fe1dce81..45d7ee1105 100644 --- a/mcs/class/corlib/Test/System/DoubleTest.cs +++ b/mcs/class/corlib/Test/System/DoubleTest.cs @@ -147,6 +147,7 @@ namespace MonoTests.System } [Test] + [Culture ("en-US")] public void Parse () { int i = 0; diff --git a/mcs/class/corlib/Test/System/EnvironmentTest.cs b/mcs/class/corlib/Test/System/EnvironmentTest.cs index fed370974e..fb547931b2 100644 --- a/mcs/class/corlib/Test/System/EnvironmentTest.cs +++ b/mcs/class/corlib/Test/System/EnvironmentTest.cs @@ -138,7 +138,7 @@ namespace MonoTests.System Assert.IsFalse (d.IsSynchronized, "IsSynchronized"); } -#if !NET_2_1 +#if !MOBILE [Test] // bug #333740 public void GetEnvironmentVariables_NewlySet () { @@ -165,7 +165,7 @@ namespace MonoTests.System #endif } -#if !NET_2_1 +#if !MOBILE [Test] [ExpectedException (typeof (ArgumentException))] public void GetEnvironmentVariable_Target_Invalid () diff --git a/mcs/class/corlib/Test/System/GCTest.cs b/mcs/class/corlib/Test/System/GCTest.cs new file mode 100644 index 0000000000..6ce65b4b43 --- /dev/null +++ b/mcs/class/corlib/Test/System/GCTest.cs @@ -0,0 +1,72 @@ +// +// GCTest.cs - NUnit Test Cases for GC +// +// Authors: +// Marek Safar +// +// Copyright (C) 2016 Xamarin Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Threading.Tasks; + +using NUnit.Framework; + +namespace MonoTests.System { + + [TestFixture] + public class GCTest { + + class MyFinalizeObject + { + public volatile static int finalized; + + ~MyFinalizeObject () + { + if (finalized++ == 0) { + GC.ReRegisterForFinalize (this); + } + } + } + + static void Run_ReRegisterForFinalizeTest () + { + var m = new WeakReference (new MyFinalizeObject ()); + m.SetTarget (null); + } + + [Test] + public void ReRegisterForFinalizeTest () + { + Run_ReRegisterForFinalizeTest (); + var t = Task.Factory.StartNew (() => { + do { + GC.Collect (); + GC.WaitForPendingFinalizers (); + Task.Yield (); + } while (MyFinalizeObject.finalized != 2); + }); + + Assert.IsTrue (t.Wait (5000)); + } + } +} \ No newline at end of file diff --git a/mcs/class/corlib/Test/System/TimeZoneInfoTest.cs b/mcs/class/corlib/Test/System/TimeZoneInfoTest.cs index 505ac04cfa..5e3811bca0 100644 --- a/mcs/class/corlib/Test/System/TimeZoneInfoTest.cs +++ b/mcs/class/corlib/Test/System/TimeZoneInfoTest.cs @@ -359,6 +359,21 @@ namespace MonoTests.System Assert.IsFalse (tzi.IsDaylightSavingTime (date)); Assert.AreEqual (new TimeSpan (2,0,0), tzi.GetUtcOffset (date)); } + + [Test] //Covers #41349 + public void TestIsDST_DateTimeOffset () + { + TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById ("Europe/Athens"); + var date = new DateTime (2014, 3, 30 , 2, 0, 0); + var offset = tzi.GetUtcOffset (date); + var dateOffset = new DateTimeOffset (date, offset); + Assert.IsFalse (tzi.IsDaylightSavingTime (dateOffset)); + + date = new DateTime (2014, 3, 30 , 3, 0, 0); + offset = tzi.GetUtcOffset (date); + dateOffset = new DateTimeOffset (date, offset); + Assert.IsTrue (tzi.IsDaylightSavingTime (dateOffset)); + } } [TestFixture] diff --git a/mcs/class/corlib/Test/System/TypeTest.cs.REMOVED.git-id b/mcs/class/corlib/Test/System/TypeTest.cs.REMOVED.git-id index 2ac4b49adc..cfabe9c21a 100644 --- a/mcs/class/corlib/Test/System/TypeTest.cs.REMOVED.git-id +++ b/mcs/class/corlib/Test/System/TypeTest.cs.REMOVED.git-id @@ -1 +1 @@ -1e38f069af2b809045fa4e4cb2b686d035553a3f \ No newline at end of file +d9eea5672d519baa2abbb431cd364b9620888b26 \ No newline at end of file diff --git a/mcs/class/corlib/Test/System/WeakReferenceTest.cs b/mcs/class/corlib/Test/System/WeakReferenceTest.cs index 717a99b6e1..b94afe1013 100644 --- a/mcs/class/corlib/Test/System/WeakReferenceTest.cs +++ b/mcs/class/corlib/Test/System/WeakReferenceTest.cs @@ -124,7 +124,6 @@ namespace MonoTests.System { Assert.IsFalse (Foo.failed); } -#if NET_4_5 [Test] public void WeakReferenceT_TryGetTarget_NullTarget () { @@ -132,7 +131,6 @@ namespace MonoTests.System { object obj; Assert.IsFalse (r.TryGetTarget (out obj), "#1"); } -#endif } } diff --git a/mcs/class/corlib/coreclr/AsyncLocal.cs b/mcs/class/corlib/coreclr/AsyncLocal.cs deleted file mode 100644 index 38035bd922..0000000000 --- a/mcs/class/corlib/coreclr/AsyncLocal.cs +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using System; -using System.Collections.Generic; -using System.Diagnostics.Contracts; -using System.Security; - -namespace System.Threading -{ - // - // AsyncLocal represents "ambient" data that is local to a given asynchronous control flow, such as an - // async method. For example, say you want to associate a culture with a given async flow: - // - // static AsyncLocal s_currentCulture = new AsyncLocal(); - // - // static async Task SomeOperationAsync(Culture culture) - // { - // s_currentCulture.Value = culture; - // - // await FooAsync(); - // } - // - // static async Task FooAsync() - // { - // PrintStringWithCulture(s_currentCulture.Value); - // } - // - // AsyncLocal also provides optional notifications when the value associated with the current thread - // changes, either because it was explicitly changed by setting the Value property, or implicitly changed - // when the thread encountered an "await" or other context transition. For example, we might want our - // current culture to be communicated to the OS as well: - // - // static AsyncLocal s_currentCulture = new AsyncLocal( - // args => - // { - // NativeMethods.SetThreadCulture(args.CurrentValue.LCID); - // }); - // - public sealed class AsyncLocal : IAsyncLocal - { - [SecurityCritical] // critical because this action will terminate the process if it throws. - private readonly Action> m_valueChangedHandler; - - // - // Constructs an AsyncLocal that does not receive change notifications. - // - public AsyncLocal() - { - } - - // - // Constructs an AsyncLocal with a delegate that is called whenever the current value changes - // on any thread. - // - [SecurityCritical] - public AsyncLocal(Action> valueChangedHandler) - { - m_valueChangedHandler = valueChangedHandler; - } - - public T Value - { - [SecuritySafeCritical] - get - { - object obj = ExecutionContext.GetLocalValue(this); - return (obj == null) ? default(T) : (T)obj; - } - [SecuritySafeCritical] - set - { - ExecutionContext.SetLocalValue(this, value, m_valueChangedHandler != null); - } - } - - [SecurityCritical] - void IAsyncLocal.OnValueChanged(object previousValueObj, object currentValueObj, bool contextChanged) - { - Contract.Assert(m_valueChangedHandler != null); - T previousValue = previousValueObj == null ? default(T) : (T)previousValueObj; - T currentValue = currentValueObj == null ? default(T) : (T)currentValueObj; - m_valueChangedHandler(new AsyncLocalValueChangedArgs(previousValue, currentValue, contextChanged)); - } - } - - // - // Interface to allow non-generic code in ExecutionContext to call into the generic AsyncLocal type. - // - internal interface IAsyncLocal - { - [SecurityCritical] - void OnValueChanged(object previousValue, object currentValue, bool contextChanged); - } - - public struct AsyncLocalValueChangedArgs - { - public T PreviousValue { get; private set; } - public T CurrentValue { get; private set; } - - // - // If the value changed because we changed to a different ExecutionContext, this is true. If it changed - // because someone set the Value property, this is false. - // - public bool ThreadContextChanged { get; private set; } - - internal AsyncLocalValueChangedArgs(T previousValue, T currentValue, bool contextChanged) - : this() - { - PreviousValue = previousValue; - CurrentValue = currentValue; - ThreadContextChanged = contextChanged; - } - } -} \ No newline at end of file diff --git a/mcs/class/corlib/coreclr/DisablePrivateReflectionAttribute.cs b/mcs/class/corlib/coreclr/DisablePrivateReflectionAttribute.cs deleted file mode 100644 index c510478b94..0000000000 --- a/mcs/class/corlib/coreclr/DisablePrivateReflectionAttribute.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ - -namespace System.Runtime.CompilerServices -{ - using System; - - [AttributeUsage(AttributeTargets.Assembly, AllowMultiple=false, Inherited=false)] - public sealed class DisablePrivateReflectionAttribute : Attribute - { - public DisablePrivateReflectionAttribute() {} - } -} - diff --git a/mcs/class/corlib/coreclr/EncodingProvider.cs b/mcs/class/corlib/coreclr/EncodingProvider.cs deleted file mode 100644 index 82024ced56..0000000000 --- a/mcs/class/corlib/coreclr/EncodingProvider.cs +++ /dev/null @@ -1,136 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -namespace System.Text -{ - using System; - using System.Collections; - using System.Collections.Generic; - - [System.Runtime.InteropServices.ComVisible(true)] - public abstract class EncodingProvider - { - public EncodingProvider() { } - public abstract Encoding GetEncoding(string name); - public abstract Encoding GetEncoding(int codepage); - - // GetEncoding should return either valid encoding or null. shouldn't throw any exception except on null name - public virtual Encoding GetEncoding(string name, EncoderFallback encoderFallback, DecoderFallback decoderFallback) - { - Encoding enc = GetEncoding(name); - if (enc != null) - { - enc = (Encoding)GetEncoding(name).Clone(); - enc.EncoderFallback = encoderFallback; - enc.DecoderFallback = decoderFallback; - } - - return enc; - } - - public virtual Encoding GetEncoding(int codepage, EncoderFallback encoderFallback, DecoderFallback decoderFallback) - { - Encoding enc = GetEncoding(codepage); - if (enc != null) - { - enc = (Encoding)GetEncoding(codepage).Clone(); - enc.EncoderFallback = encoderFallback; - enc.DecoderFallback = decoderFallback; - } - - return enc; - } - - internal static void AddProvider(EncodingProvider provider) - { - if (provider == null) - throw new ArgumentNullException("provider"); - - lock (s_InternalSyncObject) - { - if (s_providers == null) - { - s_providers = new EncodingProvider[1] { provider }; - return; - } - - if (Array.IndexOf(s_providers, provider) >= 0) - { - return; - } - - var providers = new EncodingProvider[s_providers.Length + 1]; - Array.Copy(s_providers, providers, s_providers.Length); - providers[providers.Length - 1] = provider; - s_providers = providers; - } - } - - internal static Encoding GetEncodingFromProvider(int codepage) - { - if (s_providers == null) - return null; - - var providers = s_providers; - foreach (EncodingProvider provider in providers) - { - Encoding enc = provider.GetEncoding(codepage); - if (enc != null) - return enc; - } - - return null; - } - - internal static Encoding GetEncodingFromProvider(string encodingName) - { - if (s_providers == null) - return null; - - var providers = s_providers; - foreach (EncodingProvider provider in providers) - { - Encoding enc = provider.GetEncoding(encodingName); - if (enc != null) - return enc; - } - - return null; - } - - internal static Encoding GetEncodingFromProvider(int codepage, EncoderFallback enc, DecoderFallback dec) - { - if (s_providers == null) - return null; - - var providers = s_providers; - foreach (EncodingProvider provider in providers) - { - Encoding encing = provider.GetEncoding(codepage, enc, dec); - if (encing != null) - return encing; - } - - return null; - } - - internal static Encoding GetEncodingFromProvider(string encodingName, EncoderFallback enc, DecoderFallback dec) - { - if (s_providers == null) - return null; - - var providers = s_providers; - foreach (EncodingProvider provider in providers) - { - Encoding encoding = provider.GetEncoding(encodingName, enc, dec); - if (encoding != null) - return encoding; - } - - return null; - } - - private static Object s_InternalSyncObject = new Object(); - private static volatile EncodingProvider[] s_providers; - } -} diff --git a/mcs/class/corlib/coreclr/FormattableString.cs b/mcs/class/corlib/coreclr/FormattableString.cs deleted file mode 100644 index 420421b44a..0000000000 --- a/mcs/class/corlib/coreclr/FormattableString.cs +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -/*============================================================ -** -** Class: FormattableString -** -** -** Purpose: implementation of the FormattableString -** class. -** -===========================================================*/ -namespace System -{ - /// - /// A composite format string along with the arguments to be formatted. An instance of this - /// type may result from the use of the C# or VB language primitive "interpolated string". - /// - public abstract class FormattableString : IFormattable - { - /// - /// The composite format string. - /// - public abstract string Format { get; } - - /// - /// Returns an object array that contains zero or more objects to format. Clients should not - /// mutate the contents of the array. - /// - public abstract object[] GetArguments(); - - /// - /// The number of arguments to be formatted. - /// - public abstract int ArgumentCount { get; } - - /// - /// Returns one argument to be formatted from argument position . - /// - public abstract object GetArgument(int index); - - /// - /// Format to a string using the given culture. - /// - public abstract string ToString(IFormatProvider formatProvider); - - string IFormattable.ToString(string ignored, IFormatProvider formatProvider) - { - return ToString(formatProvider); - } - - /// - /// Format the given object in the invariant culture. This static method may be - /// imported in C# by - /// - /// using static System.FormattableString; - /// . - /// Within the scope - /// of that import directive an interpolated string may be formatted in the - /// invariant culture by writing, for example, - /// - /// Invariant($"{{ lat = {latitude}; lon = {longitude} }}") - /// - /// - public static string Invariant(FormattableString formattable) - { - if (formattable == null) - { - throw new ArgumentNullException("formattable"); - } - - return formattable.ToString(Globalization.CultureInfo.InvariantCulture); - } - - public override string ToString() - { - return ToString(Globalization.CultureInfo.CurrentCulture); - } - } -} diff --git a/mcs/class/corlib/coreclr/FormattableStringFactory.cs b/mcs/class/corlib/coreclr/FormattableStringFactory.cs deleted file mode 100644 index 990204cbc0..0000000000 --- a/mcs/class/corlib/coreclr/FormattableStringFactory.cs +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -/*============================================================ -** -** Class: FormattableStringFactory -** -** -** Purpose: implementation of the FormattableStringFactory -** class. -** -===========================================================*/ -namespace System.Runtime.CompilerServices -{ - /// - /// A factory type used by compilers to create instances of the type . - /// - public static class FormattableStringFactory - { - /// - /// Create a from a composite format string and object - /// array containing zero or more objects to format. - /// - public static FormattableString Create(string format, params object[] arguments) - { - if (format == null) - { - throw new ArgumentNullException("format"); - } - - if (arguments == null) - { - throw new ArgumentNullException("arguments"); - } - - return new ConcreteFormattableString(format, arguments); - } - - private sealed class ConcreteFormattableString : FormattableString - { - private readonly string _format; - private readonly object[] _arguments; - - internal ConcreteFormattableString(string format, object[] arguments) - { - _format = format; - _arguments = arguments; - } - - public override string Format { get { return _format; } } - public override object[] GetArguments() { return _arguments; } - public override int ArgumentCount { get { return _arguments.Length; } } - public override object GetArgument(int index) { return _arguments[index]; } - public override string ToString(IFormatProvider formatProvider) { return string.Format(formatProvider, _format, _arguments); } - } - } -} diff --git a/mcs/class/corlib/coreclr/WaitHandleExtensions.cs b/mcs/class/corlib/coreclr/WaitHandleExtensions.cs deleted file mode 100644 index 93dbc6f92e..0000000000 --- a/mcs/class/corlib/coreclr/WaitHandleExtensions.cs +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -// - -using Microsoft.Win32.SafeHandles; -using System.Security; - -namespace System.Threading -{ - public static class WaitHandleExtensions - { - /// - /// Gets the native operating system handle. - /// - /// The to operate on. - /// A representing the native operating system handle. - [SecurityCritical] - public static SafeWaitHandle GetSafeWaitHandle(this WaitHandle waitHandle) - { - if (waitHandle == null) - { - throw new ArgumentNullException("waitHandle"); - } - - return waitHandle.SafeWaitHandle; - } - - /// - /// Sets the native operating system handle - /// - /// The to operate on. - /// A representing the native operating system handle. - [SecurityCritical] - public static void SetSafeWaitHandle(this WaitHandle waitHandle, SafeWaitHandle value) - { - if (waitHandle == null) - { - throw new ArgumentNullException("waitHandle"); - } - - waitHandle.SafeWaitHandle = value; - } - } -} \ No newline at end of file diff --git a/mcs/class/corlib/corlib.dll.sources b/mcs/class/corlib/corlib.dll.sources index f6eef5aa1a..18d6b1f4ed 100644 --- a/mcs/class/corlib/corlib.dll.sources +++ b/mcs/class/corlib/corlib.dll.sources @@ -23,6 +23,11 @@ Mono.Globalization.Unicode/SortKeyBuffer.cs Mono.Globalization.Unicode/Normalization.cs Mono.Globalization.Unicode/NormalizationTableUtil.cs Mono/Runtime.cs +Mono/RuntimeHandles.cs +Mono/RuntimeMarshal.cs +Mono/RuntimeStructs.cs +Mono/SafeGPtrArrayHandle.cs +Mono/SafeStringMarshal.cs Mono/DataConverter.cs Mono.Interop/ComInteropProxy.cs Mono.Interop/IDispatch.cs @@ -100,9 +105,6 @@ System/DomainManagerInitializationFlags.cs System/EmptyArray.cs System/Environment.cs System/EnvironmentVariableTarget.cs -System/GC.cs -System/GCCollectionMode.cs -System/GCNotificationStatus.cs System/Guid.cs System/IConsoleDriver.cs System/IntPtr.cs @@ -162,6 +164,7 @@ System.Diagnostics/StackFrame.cs System.Diagnostics/StackTrace.cs System.Diagnostics.Tracing/EventAttribute.cs System.Diagnostics.Tracing/EventCommand.cs +System.Diagnostics.Tracing/EventCounter.cs System.Diagnostics.Tracing/EventSource.cs System.Diagnostics.Tracing/EventSourceAttribute.cs System.Diagnostics.Tracing/EventSourceSettings.cs @@ -175,7 +178,6 @@ System.Diagnostics.Tracing/EventFieldFormat.cs System.Diagnostics.Tracing/EventFieldTags.cs System.Diagnostics.Tracing/EventIgnoreAttribute.cs System.Diagnostics.Tracing/EventManifestOptions.cs -System.Diagnostics.Tracing/EventSourceException.cs System.Diagnostics.SymbolStore/ISymbolBinder.cs System.Diagnostics.SymbolStore/ISymbolBinder1.cs System.Diagnostics.SymbolStore/ISymbolDocument.cs @@ -257,14 +259,12 @@ System.Reflection/PortableExecutableKinds.cs System.Reflection/PropertyInfo.cs System.Reflection/ReflectionTypeLoadException.cs System.Reflection/StrongNameKeyPair.cs -System.Reflection/TargetException.cs -System.Reflection/TargetInvocationException.cs -System.Reflection/TargetParameterCountException.cs System.Reflection.Emit/AssemblyBuilder.cs System.Reflection.Emit/AssemblyBuilderAccess.cs System.Reflection.Emit/ConstructorBuilder.cs System.Reflection.Emit/ConstructorOnTypeBuilderInst.cs System.Reflection.Emit/CustomAttributeBuilder.cs +System.Reflection.Emit/CustomAttributeBuilder.pns.cs System.Reflection.Emit/DerivedTypes.cs System.Reflection.Emit/DynamicILInfo.cs System.Reflection.Emit/DynamicMethod.cs @@ -278,6 +278,7 @@ System.Reflection.Emit/FieldToken.cs System.Reflection.Emit/FlowControl.cs System.Reflection.Emit/GenericTypeParameterBuilder.cs System.Reflection.Emit/ILGenerator.cs +System.Reflection.Emit/ILGenerator.pns.cs System.Reflection.Emit/Label.cs System.Reflection.Emit/LocalBuilder.cs System.Reflection.Emit/MethodBuilder.cs @@ -293,18 +294,34 @@ System.Reflection.Emit/OpCodeType.cs System.Reflection.Emit/OperandType.cs System.Reflection.Emit/PackingSize.cs System.Reflection.Emit/ParameterBuilder.cs +System.Reflection.Emit/ParameterBuilder.pns.cs System.Reflection.Emit/ParameterToken.cs System.Reflection.Emit/PEFileKinds.cs System.Reflection.Emit/PropertyBuilder.cs System.Reflection.Emit/PropertyOnTypeBuilderInst.cs System.Reflection.Emit/PropertyToken.cs System.Reflection.Emit/SignatureHelper.cs +System.Reflection.Emit/SignatureHelper.pns.cs System.Reflection.Emit/SignatureToken.cs System.Reflection.Emit/StackBehaviour.cs System.Reflection.Emit/StringToken.cs System.Reflection.Emit/TypeBuilder.cs System.Reflection.Emit/TypeToken.cs System.Reflection.Emit/UnmanagedMarshal.cs +System.Reflection.Emit/AssemblyBuilder.pns.cs +System.Reflection.Emit/ConstructorBuilder.pns.cs +System.Reflection.Emit/CustomAttributeBuilder.pns.cs +System.Reflection.Emit/EnumBuilder.pns.cs +System.Reflection.Emit/EventBuilder.pns.cs +System.Reflection.Emit/FieldBuilder.pns.cs +System.Reflection.Emit/GenericTypeParameterBuilder.pns.cs +System.Reflection.Emit/ILGenerator.pns.cs +System.Reflection.Emit/MethodBuilder.pns.cs +System.Reflection.Emit/ModuleBuilder.pns.cs +System.Reflection.Emit/ParameterBuilder.pns.cs +System.Reflection.Emit/PropertyBuilder.pns.cs +System.Reflection.Emit/SignatureHelper.pns.cs +System.Reflection.Emit/TypeBuilder.pns.cs System.Reflection.Metadata/AssemblyExtensions.cs System.Resources/Win32Resources.cs System.Runtime/GCLargeObjectHeapCompactionMode.cs @@ -695,12 +712,13 @@ System.Security.AccessControl/SecurityInfos.cs System.Security.AccessControl/SystemAcl.cs System.Security.Cryptography/CryptoAPITransform.cs System.Security.Cryptography/CryptoConfig.cs -System.Security.Cryptography/CryptoConfig_2_1.cs +System.Security.Cryptography/CryptoConfig.common.cs System.Security.Cryptography/CryptoConfig.fullaot.cs System.Security.Cryptography/CspKeyContainerInfo.cs System.Security.Cryptography/DESCryptoServiceProvider.cs System.Security.Cryptography/DSACryptoServiceProvider.cs System.Security.Cryptography/ICspAsymmetricAlgorithm.cs +System.Security.Cryptography/IncrementalHash.cs System.Security.Cryptography/KeyNumber.cs System.Security.Cryptography/MD5CryptoServiceProvider.cs System.Security.Cryptography/RC2CryptoServiceProvider.cs @@ -844,7 +862,6 @@ System.Text/EncodingHelper.cs System.Text/NormalizationForm.cs System.Text/Latin1Encoding.cs System.Threading/CompressedStack.cs -System.Threading/EventWaitHandle.cs System.Threading/HostExecutionContext.cs System.Threading/HostExecutionContextManager.cs System.Threading/Interlocked.cs @@ -893,8 +910,8 @@ ReferenceSources/TypeBuilderInstantiation.cs ReferenceSources/Buffer.cs ReferenceSources/TextInfo.cs ReferenceSources/win32native.cs -ReferenceSources/SharedStatics.cs ReferenceSources/SecurityContext.cs +ReferenceSources/PathInternal.cs ../referencesource/mscorlib/system/__filters.cs ../referencesource/mscorlib/system/__hresults.cs @@ -959,6 +976,8 @@ ReferenceSources/SecurityContext.cs ../referencesource/mscorlib/system/fieldaccessexception.cs ../referencesource/mscorlib/system/flagsattribute.cs ../referencesource/mscorlib/system/formatexception.cs +../referencesource/mscorlib/system/FormattableString.cs +../referencesource/mscorlib/system/gc.cs ../referencesource/mscorlib/system/guid.cs ../referencesource/mscorlib/system/iappdomain.cs ../referencesource/mscorlib/system/iappdomainsetup.cs @@ -1015,6 +1034,7 @@ ReferenceSources/SecurityContext.cs ../referencesource/mscorlib/system/rttype.cs ../referencesource/mscorlib/system/sbyte.cs ../referencesource/mscorlib/system/serializableattribute.cs +../referencesource/mscorlib/system/sharedstatics.cs ../referencesource/mscorlib/system/stackoverflowexception.cs ../referencesource/mscorlib/system/single.cs ../referencesource/mscorlib/system/string.cs @@ -1119,6 +1139,7 @@ ReferenceSources/SecurityContext.cs ../referencesource/mscorlib/system/diagnostics/contracts/contractsbcl.cs ../referencesource/mscorlib/system/diagnostics/eventing/eventactivityoptions.cs +../referencesource/mscorlib/system/diagnostics/eventing/eventsourceexception.cs ../referencesource/mscorlib/system/diagnostics/eventing/winmeta.cs ../referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/EventSourceOptions.cs @@ -1236,6 +1257,9 @@ ReferenceSources/SecurityContext.cs ../referencesource/mscorlib/system/reflection/reflectioncontext.cs ../referencesource/mscorlib/system/reflection/resourceattributes.cs ../referencesource/mscorlib/system/reflection/RuntimeReflectionExtensions.cs +../referencesource/mscorlib/system/reflection/targetexception.cs +../referencesource/mscorlib/system/reflection/targetinvocationexception.cs +../referencesource/mscorlib/system/reflection/targetparametercountexception.cs ../referencesource/mscorlib/system/reflection/typeattributes.cs ../referencesource/mscorlib/system/reflection/typedelegator.cs ../referencesource/mscorlib/system/reflection/typefilter.cs @@ -1348,12 +1372,15 @@ ReferenceSources/SecurityContext.cs ../referencesource/mscorlib/system/runtime/compilerservices/datetimeconstantattribute.cs ../referencesource/mscorlib/system/runtime/compilerservices/decimalconstantattribute.cs ../referencesource/mscorlib/system/runtime/compilerservices/decoratednameattribute.cs +../referencesource/mscorlib/system/runtime/compilerservices/disableprivatereflectionattribute.cs ../referencesource/mscorlib/system/runtime/compilerservices/discardableattribute.cs ../referencesource/mscorlib/system/runtime/compilerservices/extensionattribute.cs ../referencesource/mscorlib/system/runtime/compilerservices/fixedaddressvaluetypeattribute.cs ../referencesource/mscorlib/system/runtime/compilerservices/fixedbufferattribute.cs +../referencesource/mscorlib/system/runtime/compilerservices/FormattableStringFactory.cs ../referencesource/mscorlib/system/runtime/compilerservices/hascopysemanticsattribute.cs ../referencesource/mscorlib/system/runtime/compilerservices/IAsyncStateMachine.cs +../referencesource/mscorlib/system/runtime/compilerservices/idispatchconstantattribute.cs ../referencesource/mscorlib/system/runtime/compilerservices/indexernameattribute.cs ../referencesource/mscorlib/system/runtime/compilerservices/INotifyCompletion.cs ../referencesource/mscorlib/system/runtime/compilerservices/internalsvisibletoattribute.cs @@ -1443,6 +1470,7 @@ ReferenceSources/SecurityContext.cs ../referencesource/mscorlib/system/security/cryptography/ripemd160.cs ../referencesource/mscorlib/system/security/cryptography/ripemd160managed.cs ../referencesource/mscorlib/system/security/cryptography/rsa.cs +../referencesource/mscorlib/system/security/cryptography/rsacryptoserviceprovider.cs ../referencesource/mscorlib/system/security/cryptography/rsaoaepkeyexchangedeformatter.cs ../referencesource/mscorlib/system/security/cryptography/rsaoaepkeyexchangeformatter.cs ../referencesource/mscorlib/system/security/cryptography/rsapkcs1keyexchangedeformatter.cs @@ -1489,6 +1517,7 @@ ReferenceSources/SecurityContext.cs ../referencesource/mscorlib/system/text/encoderreplacementfallback.cs ../referencesource/mscorlib/system/text/encoding.cs ../referencesource/mscorlib/system/text/encodinginfo.cs +../referencesource/mscorlib/system/text/encodingprovider.cs ../referencesource/mscorlib/system/text/mlangcodepageencoding.cs ../referencesource/mscorlib/system/text/surrogateencoder.cs ../referencesource/mscorlib/system/text/unicodeencoding.cs @@ -1557,12 +1586,14 @@ ReferenceSources/SecurityContext.cs ../referencesource/mscorlib/system/threading/abandonedmutexexception.cs ../referencesource/mscorlib/system/threading/apartmentstate.cs +../referencesource/mscorlib/system/threading/asynclocal.cs ../referencesource/mscorlib/system/threading/autoresetevent.cs ../referencesource/mscorlib/system/threading/CancellationToken.cs ../referencesource/mscorlib/system/threading/CancellationTokenRegistration.cs ../referencesource/mscorlib/system/threading/CancellationTokenSource.cs ../referencesource/mscorlib/system/threading/CountdownEvent.cs ../referencesource/mscorlib/system/threading/eventresetmode.cs +../referencesource/mscorlib/system/threading/eventwaithandle.cs ../referencesource/mscorlib/system/threading/executioncontext.cs ../referencesource/mscorlib/system/threading/LazyInitializer.cs ../referencesource/mscorlib/system/threading/lockrecursionexception.cs @@ -1590,6 +1621,7 @@ ReferenceSources/SecurityContext.cs ../referencesource/mscorlib/system/threading/waithandlecannotbeopenedexception.cs ../referencesource/mscorlib/system/threading/threadpool.cs ../referencesource/mscorlib/system/threading/waithandle.cs +../referencesource/mscorlib/system/threading/waithandleExtensions.cs ../referencesource/mscorlib/system/threading/Tasks/AsyncCausalityTracer.cs ../referencesource/mscorlib/system/threading/Tasks/BeginEndAwaitableAdapter.cs @@ -1618,10 +1650,3 @@ ReferenceSources/SecurityContext.cs ReferenceSources/String.cs ReferenceSources/Type.cs - -coreclr/AsyncLocal.cs -coreclr/DisablePrivateReflectionAttribute.cs -coreclr/EncodingProvider.cs -coreclr/FormattableString.cs -coreclr/FormattableStringFactory.cs -coreclr/WaitHandleExtensions.cs diff --git a/mcs/class/corlib/corlib_test.dll.sources b/mcs/class/corlib/corlib_test.dll.sources index 46f4d2752e..bc43d92b92 100644 --- a/mcs/class/corlib/corlib_test.dll.sources +++ b/mcs/class/corlib/corlib_test.dll.sources @@ -22,6 +22,7 @@ System/CharCategoryTest.cs System/CharEnumeratorTest.cs System/CharTest.cs System/DelegateTest.cs +System/GCTest.cs System/ModuleHandleTest.cs System/NullableTest.cs System/ObsoleteAttributeTest.cs @@ -514,4 +515,4 @@ System.Threading/CountdownEventTests.cs System/AggregateExceptionTests.cs System.Threading/ThreadLocalTests.cs System.Threading/SpinLockTests.cs -../../test-helpers/TestHelpers.cs +../../../../mono/mini/TestHelpers.cs diff --git a/mcs/class/corlib/monotouch_runtime_corlib.dll.sources b/mcs/class/corlib/monotouch_runtime_corlib.dll.sources index 6acc765c09..9d688d51c5 100644 --- a/mcs/class/corlib/monotouch_runtime_corlib.dll.sources +++ b/mcs/class/corlib/monotouch_runtime_corlib.dll.sources @@ -1,15 +1 @@ -#include corlib.dll.sources -CommonCrypto/CommonCrypto.cs -CommonCrypto/CryptorTransform.cs -CommonCrypto/FastCryptorTransform.cs -CommonCrypto/CorlibExtras.cs -CommonCrypto/RijndaelManaged.cs -CommonCrypto/SecRandom.cs -CommonCrypto/RC4CommonCrypto.cs -System/Environment.iOS.cs -System/Guid.MonoTouch.cs -System/NotSupportedException.iOS.cs -CoreFoundation/CFHelpers.cs -System.Security.Cryptography.X509Certificates/X509CertificateImplApple.cs -System.Security.Cryptography.X509Certificates/X509Helper.Apple.cs -System.Text/EncodingHelper.MonoTouch.cs +#include monotouch_corlib.dll.sources diff --git a/mcs/class/corlib/monotouch_tv_corlib.dll.sources b/mcs/class/corlib/monotouch_tv_corlib.dll.sources index 6acc765c09..9d688d51c5 100644 --- a/mcs/class/corlib/monotouch_tv_corlib.dll.sources +++ b/mcs/class/corlib/monotouch_tv_corlib.dll.sources @@ -1,15 +1 @@ -#include corlib.dll.sources -CommonCrypto/CommonCrypto.cs -CommonCrypto/CryptorTransform.cs -CommonCrypto/FastCryptorTransform.cs -CommonCrypto/CorlibExtras.cs -CommonCrypto/RijndaelManaged.cs -CommonCrypto/SecRandom.cs -CommonCrypto/RC4CommonCrypto.cs -System/Environment.iOS.cs -System/Guid.MonoTouch.cs -System/NotSupportedException.iOS.cs -CoreFoundation/CFHelpers.cs -System.Security.Cryptography.X509Certificates/X509CertificateImplApple.cs -System.Security.Cryptography.X509Certificates/X509Helper.Apple.cs -System.Text/EncodingHelper.MonoTouch.cs +#include monotouch_corlib.dll.sources diff --git a/mcs/class/corlib/monotouch_tv_runtime_corlib.dll.sources b/mcs/class/corlib/monotouch_tv_runtime_corlib.dll.sources index 6acc765c09..9d688d51c5 100644 --- a/mcs/class/corlib/monotouch_tv_runtime_corlib.dll.sources +++ b/mcs/class/corlib/monotouch_tv_runtime_corlib.dll.sources @@ -1,15 +1 @@ -#include corlib.dll.sources -CommonCrypto/CommonCrypto.cs -CommonCrypto/CryptorTransform.cs -CommonCrypto/FastCryptorTransform.cs -CommonCrypto/CorlibExtras.cs -CommonCrypto/RijndaelManaged.cs -CommonCrypto/SecRandom.cs -CommonCrypto/RC4CommonCrypto.cs -System/Environment.iOS.cs -System/Guid.MonoTouch.cs -System/NotSupportedException.iOS.cs -CoreFoundation/CFHelpers.cs -System.Security.Cryptography.X509Certificates/X509CertificateImplApple.cs -System.Security.Cryptography.X509Certificates/X509Helper.Apple.cs -System.Text/EncodingHelper.MonoTouch.cs +#include monotouch_corlib.dll.sources diff --git a/mcs/class/corlib/monotouch_watch_corlib.dll.sources b/mcs/class/corlib/monotouch_watch_corlib.dll.sources index 6acc765c09..9d688d51c5 100644 --- a/mcs/class/corlib/monotouch_watch_corlib.dll.sources +++ b/mcs/class/corlib/monotouch_watch_corlib.dll.sources @@ -1,15 +1 @@ -#include corlib.dll.sources -CommonCrypto/CommonCrypto.cs -CommonCrypto/CryptorTransform.cs -CommonCrypto/FastCryptorTransform.cs -CommonCrypto/CorlibExtras.cs -CommonCrypto/RijndaelManaged.cs -CommonCrypto/SecRandom.cs -CommonCrypto/RC4CommonCrypto.cs -System/Environment.iOS.cs -System/Guid.MonoTouch.cs -System/NotSupportedException.iOS.cs -CoreFoundation/CFHelpers.cs -System.Security.Cryptography.X509Certificates/X509CertificateImplApple.cs -System.Security.Cryptography.X509Certificates/X509Helper.Apple.cs -System.Text/EncodingHelper.MonoTouch.cs +#include monotouch_corlib.dll.sources diff --git a/mcs/class/corlib/monotouch_watch_runtime_corlib.dll.sources b/mcs/class/corlib/monotouch_watch_runtime_corlib.dll.sources index 6acc765c09..9d688d51c5 100644 --- a/mcs/class/corlib/monotouch_watch_runtime_corlib.dll.sources +++ b/mcs/class/corlib/monotouch_watch_runtime_corlib.dll.sources @@ -1,15 +1 @@ -#include corlib.dll.sources -CommonCrypto/CommonCrypto.cs -CommonCrypto/CryptorTransform.cs -CommonCrypto/FastCryptorTransform.cs -CommonCrypto/CorlibExtras.cs -CommonCrypto/RijndaelManaged.cs -CommonCrypto/SecRandom.cs -CommonCrypto/RC4CommonCrypto.cs -System/Environment.iOS.cs -System/Guid.MonoTouch.cs -System/NotSupportedException.iOS.cs -CoreFoundation/CFHelpers.cs -System.Security.Cryptography.X509Certificates/X509CertificateImplApple.cs -System.Security.Cryptography.X509Certificates/X509Helper.Apple.cs -System.Text/EncodingHelper.MonoTouch.cs +#include monotouch_corlib.dll.sources diff --git a/mcs/class/corlib/net_4_x_corlib.dll.sources b/mcs/class/corlib/net_4_x_corlib.dll.sources index 2ea5c40c16..da77893bcc 100644 --- a/mcs/class/corlib/net_4_x_corlib.dll.sources +++ b/mcs/class/corlib/net_4_x_corlib.dll.sources @@ -1,2 +1 @@ #include corlib.dll.sources -../referencesource/mscorlib/system/runtime/compilerservices/idispatchconstantattribute.cs diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/DebugInfoGenerator.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/DebugInfoGenerator.cs index 329928fd80..b87eecde4e 100644 --- a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/DebugInfoGenerator.cs +++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/DebugInfoGenerator.cs @@ -48,6 +48,10 @@ namespace System.Runtime.CompilerServices { public static DebugInfoGenerator CreatePdbGenerator() { return new SymbolDocumentGenerator(); } +#else + public static DebugInfoGenerator CreatePdbGenerator() { + throw new PlatformNotSupportedException(); + } #endif /// /// Marks a sequence point. diff --git a/mcs/class/doc/NUnitGuidelines b/mcs/class/doc/NUnitGuidelines index 5b7b87f5d9..191d5dd7ac 100644 --- a/mcs/class/doc/NUnitGuidelines +++ b/mcs/class/doc/NUnitGuidelines @@ -45,45 +45,45 @@ build and the tests will be run along with all the others. * Tips --- Provide an unique error message for Assertion.Assert () +-- Provide an unique error message for Assert.IsTrue () -Include an unique message for each Assertion.Assert () so that when the assert +Include an unique message for each Assert.IsTrue () so that when the assert fails, it is trivial to locate the failing one. Otherwise, it may be difficult to determine which part of the test is failing. A good way to ensure unique messages is to use something like #A01, #A02 etc. Bad: - Assertion.AssertEquals ("array match", compare[0], i1[0]); - Assertion.AssertEquals ("array match", compare[1], i1[1]); - Assertion.AssertEquals ("array match", compare[2], i1[2]); - Assertion.AssertEquals ("array match", compare[3], i1[3]); + Assert.AreEqual (compare[0], i1[0], "array match"); + Assert.AreEqual (compare[1], i1[1], "array match"); + Assert.AreEqual (compare[2], i1[2], "array match"); + Assert.AreEqual (compare[3], i1[3], "array match"); Good: - Assertion.AssertEquals ("#A01", compare[0], i1[0]); - Assertion.AssertEquals ("#A02", compare[1], i1[1]); - Assertion.AssertEquals ("#A03", compare[2], i1[2]); - Assertion.AssertEquals ("#A04", compare[3], i1[3]); + Assert.AreEqual (compare[0], i1[0], "#A01"); + Assert.AreEqual (compare[1], i1[1], "#A02"); + Assert.AreEqual (compare[2], i1[2], "#A03"); + Assert.AreEqual (compare[3], i1[3], "#A04"); -Once you used such a number in an Assertion.Assert (), don't change it later on - +Once you used such a number in an Assert.IsTrue (), don't change it later on - people might use it it identify the test in bug reports or in mailing lists. --- Use Assertion.AssertEquals () to compare things, not Assertion.Assert (). +-- Use Assert.AreEqual () to compare things, not Assert.IsTrue (). -Never compare two values with Assertion.Assert () - if the test fails, people -have no idea what went wrong while Assertion.AssertEquals () reports the failed +Never compare two values with Assert.IsTrue () - if the test fails, people +have no idea what went wrong while Assert.AreEqual () reports the failed value. Also, make sure the second paramter is the expected value, and the third parameter is the actual value. Bad: - Assertion.Assert ("A01", myTicks[0] == t1.Ticks); + Assert.IsTrue (myTicks[0] == t1.Ticks, "A01"); Good: - Assertion.AssertEquals ("A01", myTicks[0], t1.Ticks); + Assert.AreEqual (myTicks[0], t1.Ticks, "A01"); -- Namespace diff --git a/mcs/class/legacy/Mono.Cecil/Makefile b/mcs/class/legacy/Mono.Cecil/Makefile new file mode 100644 index 0000000000..8128987f33 --- /dev/null +++ b/mcs/class/legacy/Mono.Cecil/Makefile @@ -0,0 +1,14 @@ +thisdir = class/legacy/Mono.Cecil +include ../../../build/rules.make + +LIBRARY = Mono.Cecil.dll +LIBRARY_SNK = ../../mono.snk +LIBRARY_PACKAGE = none +LIBRARY_SUBDIR = legacy + +LIB_REFS = System.Core +LIB_MCS_FLAGS = -keyfile:$(LIBRARY_SNK) -d:NET_3_5 /publicsign + +NO_TEST = yes + +include ../../../build/library.make diff --git a/mcs/class/legacy/Mono.Cecil/Mono.Cecil.dll.sources b/mcs/class/legacy/Mono.Cecil/Mono.Cecil.dll.sources new file mode 100644 index 0000000000..c993b3a502 --- /dev/null +++ b/mcs/class/legacy/Mono.Cecil/Mono.Cecil.dll.sources @@ -0,0 +1,127 @@ +../../../../external/cecil-legacy/Mono.Collections.Generic/Collection.cs +../../../../external/cecil-legacy/Mono.Collections.Generic/ReadOnlyCollection.cs +../../../../external/cecil-legacy/Mono.Cecil.PE/ImageWriter.cs +../../../../external/cecil-legacy/Mono.Cecil.PE/BinaryStreamWriter.cs +../../../../external/cecil-legacy/Mono.Cecil.PE/BinaryStreamReader.cs +../../../../external/cecil-legacy/Mono.Cecil.PE/DataDirectory.cs +../../../../external/cecil-legacy/Mono.Cecil.PE/ByteBuffer.cs +../../../../external/cecil-legacy/Mono.Cecil.PE/ByteBufferEqualityComparer.cs +../../../../external/cecil-legacy/Mono.Cecil.PE/TextMap.cs +../../../../external/cecil-legacy/Mono.Cecil.PE/Section.cs +../../../../external/cecil-legacy/Mono.Cecil.PE/Image.cs +../../../../external/cecil-legacy/Mono.Cecil.PE/ImageReader.cs +../../../../external/cecil-legacy/Mono.Cecil.Metadata/TableHeap.cs +../../../../external/cecil-legacy/Mono.Cecil.Metadata/GuidHeap.cs +../../../../external/cecil-legacy/Mono.Cecil.Metadata/Heap.cs +../../../../external/cecil-legacy/Mono.Cecil.Metadata/TokenType.cs +../../../../external/cecil-legacy/Mono.Cecil.Metadata/CodedIndex.cs +../../../../external/cecil-legacy/Mono.Cecil.Metadata/ElementType.cs +../../../../external/cecil-legacy/Mono.Cecil.Metadata/BlobHeap.cs +../../../../external/cecil-legacy/Mono.Cecil.Metadata/Row.cs +../../../../external/cecil-legacy/Mono.Cecil.Metadata/MetadataToken.cs +../../../../external/cecil-legacy/Mono.Cecil.Metadata/UserStringHeap.cs +../../../../external/cecil-legacy/Mono.Cecil.Metadata/Utilities.cs +../../../../external/cecil-legacy/Mono.Cecil.Metadata/StringHeap.cs +../../../../external/cecil-legacy/Mono.Cecil.Metadata/Buffers.cs +../../../../external/cecil-legacy/System.Runtime.CompilerServices/ExtensionAttribute.cs +../../../../external/cecil-legacy/Mono.Security.Cryptography/CryptoService.cs +../../../../external/cecil-legacy/Mono.Security.Cryptography/CryptoConvert.cs +../../../../external/cecil-legacy/Mono/Empty.cs +../../../../external/cecil-legacy/Mono/Funcs.cs +../../../../external/cecil-legacy/Mono/Actions.cs +../../../../external/cecil-legacy/Mono.Cecil.Cil/ILProcessor.cs +../../../../external/cecil-legacy/Mono.Cecil.Cil/VariableReference.cs +../../../../external/cecil-legacy/Mono.Cecil.Cil/OpCodes.cs +../../../../external/cecil-legacy/Mono.Cecil.Cil/MethodBody.cs +../../../../external/cecil-legacy/Mono.Cecil.Cil/Instruction.cs +../../../../external/cecil-legacy/Mono.Cecil.Cil/Code.cs +../../../../external/cecil-legacy/Mono.Cecil.Cil/Symbols.cs +../../../../external/cecil-legacy/Mono.Cecil.Cil/CodeWriter.cs +../../../../external/cecil-legacy/Mono.Cecil.Cil/CodeReader.cs +../../../../external/cecil-legacy/Mono.Cecil.Cil/SequencePoint.cs +../../../../external/cecil-legacy/Mono.Cecil.Cil/Document.cs +../../../../external/cecil-legacy/Mono.Cecil.Cil/OpCode.cs +../../../../external/cecil-legacy/Mono.Cecil.Cil/ExceptionHandler.cs +../../../../external/cecil-legacy/Mono.Cecil.Cil/VariableDefinition.cs +../../../../external/cecil-legacy/Mono.Cecil/ModuleReference.cs +../../../../external/cecil-legacy/Mono.Cecil/TypeParser.cs +../../../../external/cecil-legacy/Mono.Cecil/LinkedResource.cs +../../../../external/cecil-legacy/Mono.Cecil/IMemberDefinition.cs +../../../../external/cecil-legacy/Mono.Cecil/Resource.cs +../../../../external/cecil-legacy/Mono.Cecil/ICustomAttributeProvider.cs +../../../../external/cecil-legacy/Mono.Cecil/MethodReference.cs +../../../../external/cecil-legacy/Mono.Cecil/EventAttributes.cs +../../../../external/cecil-legacy/Mono.Cecil/FieldReference.cs +../../../../external/cecil-legacy/Mono.Cecil/SentinelType.cs +../../../../external/cecil-legacy/Mono.Cecil/MemberReference.cs +../../../../external/cecil-legacy/Mono.Cecil/AssemblyReader.cs +../../../../external/cecil-legacy/Mono.Cecil/TargetRuntime.cs +../../../../external/cecil-legacy/Mono.Cecil/TypeAttributes.cs +../../../../external/cecil-legacy/Mono.Cecil/GenericParameter.cs +../../../../external/cecil-legacy/Mono.Cecil/MethodImplAttributes.cs +../../../../external/cecil-legacy/Mono.Cecil/FileAttributes.cs +../../../../external/cecil-legacy/Mono.Cecil/ManifestResourceAttributes.cs +../../../../external/cecil-legacy/Mono.Cecil/SecurityDeclaration.cs +../../../../external/cecil-legacy/Mono.Cecil/NativeType.cs +../../../../external/cecil-legacy/Mono.Cecil/EventReference.cs +../../../../external/cecil-legacy/Mono.Cecil/AssemblyWriter.cs +../../../../external/cecil-legacy/Mono.Cecil/Modifiers.cs +../../../../external/cecil-legacy/Mono.Cecil/IGenericParameterProvider.cs +../../../../external/cecil-legacy/Mono.Cecil/ParameterDefinition.cs +../../../../external/cecil-legacy/Mono.Cecil/IMetadataScope.cs +../../../../external/cecil-legacy/Mono.Cecil/AssemblyNameReference.cs +../../../../external/cecil-legacy/Mono.Cecil/ParameterAttributes.cs +../../../../external/cecil-legacy/Mono.Cecil/TypeSpecification.cs +../../../../external/cecil-legacy/Mono.Cecil/IMetadataTokenProvider.cs +../../../../external/cecil-legacy/Mono.Cecil/MethodAttributes.cs +../../../../external/cecil-legacy/Mono.Cecil/AssemblyInfo.cs +../../../../external/cecil-legacy/Mono.Cecil/IMarshalInfoProvider.cs +../../../../external/cecil-legacy/Mono.Cecil/PointerType.cs +../../../../external/cecil-legacy/Mono.Cecil/ArrayType.cs +../../../../external/cecil-legacy/Mono.Cecil/TypeDefinition.cs +../../../../external/cecil-legacy/Mono.Cecil/FunctionPointerType.cs +../../../../external/cecil-legacy/Mono.Cecil/MetadataResolver.cs +../../../../external/cecil-legacy/Mono.Cecil/Import.cs +../../../../external/cecil-legacy/Mono.Cecil/IGenericInstance.cs +../../../../external/cecil-legacy/Mono.Cecil/ExportedType.cs +../../../../external/cecil-legacy/Mono.Cecil/PInvokeAttributes.cs +../../../../external/cecil-legacy/Mono.Cecil/AssemblyHashAlgorithm.cs +../../../../external/cecil-legacy/Mono.Cecil/MethodReturnType.cs +../../../../external/cecil-legacy/Mono.Cecil/ParameterReference.cs +../../../../external/cecil-legacy/Mono.Cecil/AssemblyLinkedResource.cs +../../../../external/cecil-legacy/Mono.Cecil/EventDefinition.cs +../../../../external/cecil-legacy/Mono.Cecil/FieldAttributes.cs +../../../../external/cecil-legacy/Mono.Cecil/AssemblyNameDefinition.cs +../../../../external/cecil-legacy/Mono.Cecil/ParameterDefinitionCollection.cs +../../../../external/cecil-legacy/Mono.Cecil/ModuleDefinition.cs +../../../../external/cecil-legacy/Mono.Cecil/MetadataSystem.cs +../../../../external/cecil-legacy/Mono.Cecil/AssemblyFlags.cs +../../../../external/cecil-legacy/Mono.Cecil/TypeDefinitionCollection.cs +../../../../external/cecil-legacy/Mono.Cecil/CustomAttribute.cs +../../../../external/cecil-legacy/Mono.Cecil/MemberDefinitionCollection.cs +../../../../external/cecil-legacy/Mono.Cecil/PropertyDefinition.cs +../../../../external/cecil-legacy/Mono.Cecil/GenericInstanceType.cs +../../../../external/cecil-legacy/Mono.Cecil/ModuleKind.cs +../../../../external/cecil-legacy/Mono.Cecil/DefaultAssemblyResolver.cs +../../../../external/cecil-legacy/Mono.Cecil/MethodSemanticsAttributes.cs +../../../../external/cecil-legacy/Mono.Cecil/EmbeddedResource.cs +../../../../external/cecil-legacy/Mono.Cecil/PropertyAttributes.cs +../../../../external/cecil-legacy/Mono.Cecil/MethodSpecification.cs +../../../../external/cecil-legacy/Mono.Cecil/TypeReference.cs +../../../../external/cecil-legacy/Mono.Cecil/IConstantProvider.cs +../../../../external/cecil-legacy/Mono.Cecil/MethodDefinition.cs +../../../../external/cecil-legacy/Mono.Cecil/PinnedType.cs +../../../../external/cecil-legacy/Mono.Cecil/VariantType.cs +../../../../external/cecil-legacy/Mono.Cecil/MethodCallingConvention.cs +../../../../external/cecil-legacy/Mono.Cecil/TypeSystem.cs +../../../../external/cecil-legacy/Mono.Cecil/IMethodSignature.cs +../../../../external/cecil-legacy/Mono.Cecil/FieldDefinition.cs +../../../../external/cecil-legacy/Mono.Cecil/BaseAssemblyResolver.cs +../../../../external/cecil-legacy/Mono.Cecil/PropertyReference.cs +../../../../external/cecil-legacy/Mono.Cecil/MarshalInfo.cs +../../../../external/cecil-legacy/Mono.Cecil/GenericInstanceMethod.cs +../../../../external/cecil-legacy/Mono.Cecil/ReferenceType.cs +../../../../external/cecil-legacy/Mono.Cecil/PInvokeInfo.cs +../../../../external/cecil-legacy/Mono.Cecil/CallSite.cs +../../../../external/cecil-legacy/Mono.Cecil/AssemblyDefinition.cs +../../../../external/cecil-legacy/Mono.Cecil/GenericParameterAttributes.cs diff --git a/mcs/class/lib/monolite/Mono.Security.dll.REMOVED.git-id b/mcs/class/lib/monolite/Mono.Security.dll.REMOVED.git-id index 7b5a39c753..0cb2314230 100644 --- a/mcs/class/lib/monolite/Mono.Security.dll.REMOVED.git-id +++ b/mcs/class/lib/monolite/Mono.Security.dll.REMOVED.git-id @@ -1 +1 @@ -00b036beeecec41027d32261f93ef4afcded2671 \ No newline at end of file +888a60f83ef20a418c92152c4aa04334e35ca797 \ No newline at end of file diff --git a/mcs/class/lib/monolite/System.Configuration.dll.REMOVED.git-id b/mcs/class/lib/monolite/System.Configuration.dll.REMOVED.git-id index 802174ee41..8855a044a1 100644 --- a/mcs/class/lib/monolite/System.Configuration.dll.REMOVED.git-id +++ b/mcs/class/lib/monolite/System.Configuration.dll.REMOVED.git-id @@ -1 +1 @@ -bcbe83f41aabb1ad3e9a1b1d2db8b1a232d1a926 \ No newline at end of file +a1437f73aa93b512e6b12d6a52339d1d4d2abd5d \ No newline at end of file diff --git a/mcs/class/lib/monolite/System.Core.dll.REMOVED.git-id b/mcs/class/lib/monolite/System.Core.dll.REMOVED.git-id index 9c2dbecc7d..443bfbe699 100644 --- a/mcs/class/lib/monolite/System.Core.dll.REMOVED.git-id +++ b/mcs/class/lib/monolite/System.Core.dll.REMOVED.git-id @@ -1 +1 @@ -c490c7433c000c0ca9ff7be0753080941738fdbc \ No newline at end of file +b5880ee73621284b7237031d8d27fb8a5747a797 \ No newline at end of file diff --git a/mcs/class/lib/monolite/System.Security.dll.REMOVED.git-id b/mcs/class/lib/monolite/System.Security.dll.REMOVED.git-id index 714009bd29..26bec16875 100644 --- a/mcs/class/lib/monolite/System.Security.dll.REMOVED.git-id +++ b/mcs/class/lib/monolite/System.Security.dll.REMOVED.git-id @@ -1 +1 @@ -3750501024a83aeecb9eae17568c1ce449e4a5ee \ No newline at end of file +4290723c3f54f5143abed47828651d8f424b95f3 \ No newline at end of file diff --git a/mcs/class/lib/monolite/System.Xml.dll.REMOVED.git-id b/mcs/class/lib/monolite/System.Xml.dll.REMOVED.git-id index cf68b6611c..61403184e0 100644 --- a/mcs/class/lib/monolite/System.Xml.dll.REMOVED.git-id +++ b/mcs/class/lib/monolite/System.Xml.dll.REMOVED.git-id @@ -1 +1 @@ -902c79a57b8ba29447b9a30239452ab2187b2890 \ No newline at end of file +0314861ee197046bdbbaf9680511292bbde83c39 \ No newline at end of file diff --git a/mcs/class/lib/monolite/System.dll.REMOVED.git-id b/mcs/class/lib/monolite/System.dll.REMOVED.git-id index e98a025474..386249ad7e 100644 --- a/mcs/class/lib/monolite/System.dll.REMOVED.git-id +++ b/mcs/class/lib/monolite/System.dll.REMOVED.git-id @@ -1 +1 @@ -5356d88f5d4b5d16d5017ef1fa1c4716dc7a2c99 \ No newline at end of file +4300ee601c5a3c592bf6808619b626189da4347f \ No newline at end of file diff --git a/mcs/class/lib/monolite/basic.exe.REMOVED.git-id b/mcs/class/lib/monolite/basic.exe.REMOVED.git-id index 8c2dab7ae7..b97165616b 100644 --- a/mcs/class/lib/monolite/basic.exe.REMOVED.git-id +++ b/mcs/class/lib/monolite/basic.exe.REMOVED.git-id @@ -1 +1 @@ -957872a1e4c1a244c061e75175fedabe66254f81 \ No newline at end of file +e2b3d103722a7d6c1da86715c5858c14afefa8af \ No newline at end of file diff --git a/mcs/class/lib/monolite/mscorlib.dll.REMOVED.git-id b/mcs/class/lib/monolite/mscorlib.dll.REMOVED.git-id index 5d925f7c90..c75cc51845 100644 --- a/mcs/class/lib/monolite/mscorlib.dll.REMOVED.git-id +++ b/mcs/class/lib/monolite/mscorlib.dll.REMOVED.git-id @@ -1 +1 @@ -9494bf7798aee9c87600048b7a9fef4caf09d396 \ No newline at end of file +4a5d937cf3124b7461317b6d951a881da4f0a453 \ No newline at end of file diff --git a/mcs/class/referencesource/System.Activities.Core.Presentation/System/Activities/Core/Presentation/FlowchartConnectionPointsAdorner.cs b/mcs/class/referencesource/System.Activities.Core.Presentation/System/Activities/Core/Presentation/FlowchartConnectionPointsAdorner.cs index d1b3abc1da..2debe1f357 100644 --- a/mcs/class/referencesource/System.Activities.Core.Presentation/System/Activities/Core/Presentation/FlowchartConnectionPointsAdorner.cs +++ b/mcs/class/referencesource/System.Activities.Core.Presentation/System/Activities/Core/Presentation/FlowchartConnectionPointsAdorner.cs @@ -63,10 +63,11 @@ namespace System.Activities.Core.Presentation trueLabelText = (string)virtualizingContainer.ModelItem.Properties["TrueLabel"].ComputedValue; } + double pixelsPerDip = VisualTreeHelper.GetDpi(trueConnectionPoint).PixelsPerDip; actualPoint = new Point(trueConnectionPoint.Location.X - origin.X, trueConnectionPoint.Location.Y - origin.Y); FormattedText trueMarkerFormattedText = new FormattedText(trueLabelText, new System.Globalization.CultureInfo(textCulture), this.FlowDirection, FlowchartDesigner.FlowElementCaptionTypeface, FlowchartDesigner.FlowNodeCaptionFontSize, - new SolidColorBrush(WorkflowDesignerColors.WorkflowViewElementCaptionColor)); + new SolidColorBrush(WorkflowDesignerColors.WorkflowViewElementCaptionColor), pixelsPerDip); actualPoint.Y += ConnectionPoint.DrawingLargeSide / 2; actualPoint.X -= trueMarkerFormattedText.WidthIncludingTrailingWhitespace; @@ -94,9 +95,10 @@ namespace System.Activities.Core.Presentation actualPoint = new Point(falseConnectionPoint.Location.X - origin.X, falseConnectionPoint.Location.Y - origin.Y); actualPoint.Y += ConnectionPoint.DrawingLargeSide / 2; + double pixelsPerDip = VisualTreeHelper.GetDpi(falseConnectionPoint).PixelsPerDip; FormattedText falseMarkerFormattedText = new FormattedText(falseLabelText, new System.Globalization.CultureInfo(textCulture), this.FlowDirection, FlowchartDesigner.FlowElementCaptionTypeface, FlowchartDesigner.FlowNodeCaptionFontSize, - new SolidColorBrush(WorkflowDesignerColors.WorkflowViewElementCaptionColor)); + new SolidColorBrush(WorkflowDesignerColors.WorkflowViewElementCaptionColor), pixelsPerDip); DrawtWithTransform( drawingContext, diff --git a/mcs/class/referencesource/System.Activities.Presentation/Microsoft.Tools.Common/Microsoft/Activities/Presentation/Xaml/ViewStateXamlHelper.cs b/mcs/class/referencesource/System.Activities.Presentation/Microsoft.Tools.Common/Microsoft/Activities/Presentation/Xaml/ViewStateXamlHelper.cs index 08bf6c294f..fb5266eb13 100644 --- a/mcs/class/referencesource/System.Activities.Presentation/Microsoft.Tools.Common/Microsoft/Activities/Presentation/Xaml/ViewStateXamlHelper.cs +++ b/mcs/class/referencesource/System.Activities.Presentation/Microsoft.Tools.Common/Microsoft/Activities/Presentation/Xaml/ViewStateXamlHelper.cs @@ -7,6 +7,7 @@ namespace Microsoft.Activities.Presentation.Xaml using System; using System.Activities; using System.Activities.Debugger; + using System.Activities.DynamicUpdate; using System.Activities.Presentation.View; using System.Activities.Presentation.ViewState; using System.Collections.Generic; @@ -30,6 +31,18 @@ namespace Microsoft.Activities.Presentation.Xaml XamlDebuggerXmlReader.EndColumnName.MemberName }; + // These are used to discover that we have found a DynamicUpdateInfo.OriginalDefintion or OriginalActivityBuilder + // attached property member. We have "hardcoded" the *MemberName" here because DynamicUpdateInfo has the + // AttachableMemberIdentifier properties marked as private. But the DynamicUpdateInfo class itself is public, + // as are the Get and Set methods. + static readonly string DynamicUpdateOriginalDefinitionMemberName = "OriginalDefinition"; + static readonly MethodInfo GetOriginalDefinition = typeof(DynamicUpdateInfo).GetMethod("GetOriginalDefinition"); + static readonly MethodInfo SetOriginalDefinition = typeof(DynamicUpdateInfo).GetMethod("SetOriginalDefinition"); + + static readonly string DynamicUpdateOriginalActivityBuilderMemberName = "OriginalActivityBuilder"; + static readonly MethodInfo GetOriginalActivityBuilder = typeof(DynamicUpdateInfo).GetMethod("GetOriginalActivityBuilder"); + static readonly MethodInfo SetOriginalActivityBuilder = typeof(DynamicUpdateInfo).GetMethod("SetOriginalActivityBuilder"); + // This method collects view state attached properties and generates a Xaml node stream // with all view state information appearing within the ViewStateManager node. // It is called when workflow definition is being serialized to string. @@ -279,6 +292,22 @@ namespace Microsoft.Activities.Presentation.Xaml // Xaml member definition for IdRef. Used to identify existing IdRef properties in the input nodestream. XamlMember idRefMember = new XamlMember(IdRef, GetIdRef, SetIdRef, inputReader.SchemaContext); + // These are used to ignore the IdRef members that are inside a DynamicUpdateInfo.OriginalDefinition/OriginalActivityBuilder attached property. + // We need to ignore these because if we don't, the IdRef values for the objects in the actual workflow defintion will be ignored because of the + // duplicate IdRef value. This causes problems with activity designers that depend on the ViewStateManager data to correctly display the workflow + // on the WorkflowDesigner canvas. + XamlMember originalDefinitionMember = new XamlMember(DynamicUpdateOriginalDefinitionMemberName, GetOriginalDefinition, SetOriginalDefinition, inputReader.SchemaContext); + XamlMember originalActivityBuilderMember = new XamlMember(DynamicUpdateOriginalActivityBuilderMemberName, GetOriginalActivityBuilder, SetOriginalActivityBuilder, inputReader.SchemaContext); + + // insideOriginalDefintion gets set to true when we find a "StartMember" node for either of the above two attached properties. + // originalDefintionMemberCount gets incremented if we find any "StartMember" and insideOriginalDefinition is true. + // originalDefintionMemberCount gets decremented if we find any "EndMember" and insideOriginalDefintion is true. + // insideOriginalDefintion gets set to false when we find an "EndMember" and originalDefinitionMemberCount gets decremented to 0. + // If insideOriginalDefintion is true when we find an "IdRef" member, we do NOT add that IdRef to the idRefsSeen HashSet to avoid + // duplicates being defined by the IdRefs inside of the OriginalDefinition attached properties. + bool insideOriginalDefinition = false; + int originalDefinitionMemberCount = 0; + // Dictionary containing Ids and corresponding viewstate related // attached property nodes. Populated by StripViewStateElement method. Dictionary viewStateInfo = null; @@ -323,9 +352,21 @@ namespace Microsoft.Activities.Presentation.Xaml break; case XamlNodeType.StartMember: + // If we find a StartMember for DynamicUpdateInfo.OriginalDefinition or OriginalActivityBuilder, remember that we are + // inside one of those. We don't want to "remember" IdRef values in the idRefsSeen HashSet while inside these attached properties. + if (workflowDefinition.Member.Equals(originalDefinitionMember) || workflowDefinition.Member.Equals(originalActivityBuilderMember)) + { + insideOriginalDefinition = true; + } + + if (insideOriginalDefinition) + { + originalDefinitionMemberCount++; + } + // Track when the reader enters IdRef. Skip writing the start // node to the output nodelist until we check for duplicates. - if (workflowDefinition.Member.Equals(idRefMember)) + else if (workflowDefinition.Member.Equals(idRefMember)) { inIdRefMember = true; skipWritingWorkflowDefinition = true; @@ -341,38 +382,43 @@ namespace Microsoft.Activities.Presentation.Xaml case XamlNodeType.Value: if (inIdRefMember) { - string idRef = workflowDefinition.Value as string; - if (!string.IsNullOrWhiteSpace(idRef)) + // We don't want to deal with the IdRef if we are inside a DynamicUpdateInfo.OriginalDefinition/OriginalActivityBuilder + // attached property. + if (!insideOriginalDefinition) { - // If IdRef value is a duplicate then do not associate it with - // the stack frame (top of stack == activity node with IdRef member on it). - if (idRefsSeen.Contains(idRef)) + string idRef = workflowDefinition.Value as string; + if (!string.IsNullOrWhiteSpace(idRef)) { - stack.Peek().IdRef = null; - } - // If the IdRef value is unique then associate it with the - // stack frame and also write its value into the output nodestream. - else - { - stack.Peek().IdRef = idRef; - idManager.UpdateMap(idRef); - idRefsSeen.Add(idRef); - - if (shouldPassLineInfo) + // If IdRef value is a duplicate then do not associate it with + // the stack frame (top of stack == activity node with IdRef member on it). + if (idRefsSeen.Contains(idRef)) { - lineInfoComsumer.SetLineInfo(idRefLineNumber, idRefLinePosition); + stack.Peek().IdRef = null; } - - mergedNodeWriter.WriteStartMember(idRefMember); - - if (shouldPassLineInfo) + // If the IdRef value is unique then associate it with the + // stack frame and also write its value into the output nodestream. + else { - lineInfoComsumer.SetLineInfo(lineInfo.LineNumber, lineInfo.LinePosition); + stack.Peek().IdRef = idRef; + idManager.UpdateMap(idRef); + idRefsSeen.Add(idRef); + + if (shouldPassLineInfo) + { + lineInfoComsumer.SetLineInfo(idRefLineNumber, idRefLinePosition); + } + + mergedNodeWriter.WriteStartMember(idRefMember); + + if (shouldPassLineInfo) + { + lineInfoComsumer.SetLineInfo(lineInfo.LineNumber, lineInfo.LinePosition); + } + + mergedNodeWriter.WriteValue(idRef); + + shouldWriteIdRefEndMember = true; } - - mergedNodeWriter.WriteValue(idRef); - - shouldWriteIdRefEndMember = true; } } // Don't need to write IdRef value into the output @@ -382,9 +428,21 @@ namespace Microsoft.Activities.Presentation.Xaml break; case XamlNodeType.EndMember: + // If we are inside an OriginalDefinition/OriginalActivityBuilder attached property, + // decrement the count and if it goes to zero, set insideOriginalDefintion to false + // because we just encountered the EndMember for it. + if (insideOriginalDefinition) + { + originalDefinitionMemberCount--; + if (originalDefinitionMemberCount == 0) + { + insideOriginalDefinition = false; + } + } + // Exit IdRef node. Skip writing the EndMember node, we would have done // it as part of reading the IdRef value. - if (inIdRefMember) + if (inIdRefMember && !insideOriginalDefinition) { inIdRefMember = false; skipWritingWorkflowDefinition = true; @@ -401,6 +459,7 @@ namespace Microsoft.Activities.Presentation.Xaml mergedNodeWriter.WriteEndMember(); } } + break; case XamlNodeType.EndObject: @@ -592,6 +651,7 @@ namespace Microsoft.Activities.Presentation.Xaml viewStateSourceLocationMap = null; XamlNodeList strippedNodeList = new XamlNodeList(inputReader.SchemaContext); XamlMember viewStateManager = new XamlMember(ViewStateManager, GetViewStateManager, SetViewStateManager, inputReader.SchemaContext); + using (XamlWriter strippedWriter = strippedNodeList.Writer) { IXamlLineInfo lineInfo = inputReader as IXamlLineInfo; @@ -618,7 +678,7 @@ namespace Microsoft.Activities.Presentation.Xaml return strippedNodeList.GetReader(); } - + // This method reads ViewStateManager nodes from the xaml nodestream and outputs that in the // viewStateInfo dictionary. The input reader is positioned on the ViewStateManagerNode in the nodestream. static void ReadViewStateInfo(XamlReader inputReader, out Dictionary viewStateInfo, out Dictionary viewStateSourceLocationMap) @@ -700,7 +760,11 @@ namespace Microsoft.Activities.Presentation.Xaml } } } - else if (globalMemberLevel == 1 && !IsAttachablePropertyForConvert(xamlReader)) + // The xamlReader.ReadSubtree and subsequent while loop to get the Id member + // has moved the xamlReader forward to the next member. We need to check to see + // if it is an Attached Property that we care about. If it isn't then we need to + // skip it and not put it in the resulting XamlNodeList. + if (globalMemberLevel == 1 && !IsAttachablePropertyForConvert(xamlReader)) { skippingUnexpectedAttachedProperty = true; } diff --git a/mcs/class/referencesource/System.Activities/System/Activities/Hosting/WorkflowInstance.cs b/mcs/class/referencesource/System.Activities/System/Activities/Hosting/WorkflowInstance.cs index 6b24f0ea52..c4cd899b81 100644 --- a/mcs/class/referencesource/System.Activities/System/Activities/Hosting/WorkflowInstance.cs +++ b/mcs/class/referencesource/System.Activities/System/Activities/Hosting/WorkflowInstance.cs @@ -48,6 +48,20 @@ namespace System.Activities.Hosting StackTrace abortStack; #endif + static WorkflowInstance() + { + try + { + using (TelemetryEventSource eventSource = new TelemetryEventSource()) + { + eventSource.V2Runtime(); + } + } + catch + { + } + } + protected WorkflowInstance(Activity workflowDefinition) : this(workflowDefinition, null) { diff --git a/mcs/class/referencesource/System.Activities/System/Activities/WorkflowApplication.cs.REMOVED.git-id b/mcs/class/referencesource/System.Activities/System/Activities/WorkflowApplication.cs.REMOVED.git-id index 22bd6090f8..d8ebf04f9c 100644 --- a/mcs/class/referencesource/System.Activities/System/Activities/WorkflowApplication.cs.REMOVED.git-id +++ b/mcs/class/referencesource/System.Activities/System/Activities/WorkflowApplication.cs.REMOVED.git-id @@ -1 +1 @@ -2090063250746eae0b7a6eaec193aac86984b785 \ No newline at end of file +ff9b74d7295d3a52cf91057ee647d184edec0c5e \ No newline at end of file diff --git a/mcs/class/referencesource/System.ComponentModel.DataAnnotations/DataAnnotations/LocalAppContextSwitches.cs b/mcs/class/referencesource/System.ComponentModel.DataAnnotations/DataAnnotations/LocalAppContextSwitches.cs index 20b80cfdef..799f49541b 100644 --- a/mcs/class/referencesource/System.ComponentModel.DataAnnotations/DataAnnotations/LocalAppContextSwitches.cs +++ b/mcs/class/referencesource/System.ComponentModel.DataAnnotations/DataAnnotations/LocalAppContextSwitches.cs @@ -21,8 +21,10 @@ namespace System.ComponentModel.DataAnnotations { } public static void SetDefaultsLessOrEqual_46() { +#pragma warning disable BCL0012 //disable warning about AppContextDefaults not following the recommended pattern // Define the switches that should be true for 4.6 or less, false for 4.6.1+. LocalAppContext.DefineSwitchDefault(UseLegacyRegExTimeoutString, true); +#pragma warning restore BCL0012 } } } diff --git a/mcs/class/referencesource/System.ComponentModel.DataAnnotations/DataAnnotations/RegularExpressionAttribute.cs b/mcs/class/referencesource/System.ComponentModel.DataAnnotations/DataAnnotations/RegularExpressionAttribute.cs index cd4ac2683e..0b0f4b3047 100644 --- a/mcs/class/referencesource/System.ComponentModel.DataAnnotations/DataAnnotations/RegularExpressionAttribute.cs +++ b/mcs/class/referencesource/System.ComponentModel.DataAnnotations/DataAnnotations/RegularExpressionAttribute.cs @@ -1,4 +1,4 @@ -using System.ComponentModel.DataAnnotations.Resources; +using System.ComponentModel.DataAnnotations.Resources; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Text.RegularExpressions; @@ -19,7 +19,18 @@ namespace System.ComponentModel.DataAnnotations { /// Gets or sets the timeout to use when matching the regular expression pattern (in milliseconds) /// (-1 means never timeout). /// - public int MatchTimeoutInMilliseconds { get; set; } = GetDefaultTimeout(); + public int MatchTimeoutInMilliseconds { + get { + return _matchTimeoutInMilliseconds; + } + set { + _matchTimeoutInMilliseconds = value; + _matchTimeoutSet = true; + } + } + + private int _matchTimeoutInMilliseconds; + private bool _matchTimeoutSet; private Regex Regex { get; set; } @@ -90,6 +101,11 @@ namespace System.ComponentModel.DataAnnotations { if (string.IsNullOrEmpty(this.Pattern)) { throw new InvalidOperationException(DataAnnotationsResources.RegularExpressionAttribute_Empty_Pattern); } + + if (!_matchTimeoutSet) { + MatchTimeoutInMilliseconds = GetDefaultTimeout(); + } + Regex = MatchTimeoutInMilliseconds == -1 ? new Regex(Pattern) : Regex = new Regex(Pattern, default(RegexOptions), TimeSpan.FromMilliseconds((double)MatchTimeoutInMilliseconds)); diff --git a/mcs/class/referencesource/System.ComponentModel.DataAnnotations/InternalApis/Clr/inc/AppContextDefaultValues.cs b/mcs/class/referencesource/System.ComponentModel.DataAnnotations/InternalApis/Clr/inc/AppContextDefaultValues.cs index 8a130a0f34..9224bf8b8f 100644 --- a/mcs/class/referencesource/System.ComponentModel.DataAnnotations/InternalApis/Clr/inc/AppContextDefaultValues.cs +++ b/mcs/class/referencesource/System.ComponentModel.DataAnnotations/InternalApis/Clr/inc/AppContextDefaultValues.cs @@ -3,6 +3,15 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== + +// There are cases where we have multiple assemblies that are going to import this file and +// if they are going to also have InternalsVisibleTo between them, there will be a compiler warning +// that the type is found both in the source and in a referenced assembly. The compiler will prefer +// the version of the type defined in the source +// +// In order to disable the warning for this type we are disabling this warning for this entire file. +#pragma warning disable 436 + using System; using System.Collections.Generic; @@ -167,3 +176,5 @@ namespace System static partial void PopulateDefaultValuesPartial(string platformIdentifier, string profile, int version); } } + +#pragma warning restore 436 diff --git a/mcs/class/referencesource/System.ComponentModel.DataAnnotations/InternalApis/Clr/inc/LocalAppContext.cs b/mcs/class/referencesource/System.ComponentModel.DataAnnotations/InternalApis/Clr/inc/LocalAppContext.cs index f05b599ed3..33662b5428 100644 --- a/mcs/class/referencesource/System.ComponentModel.DataAnnotations/InternalApis/Clr/inc/LocalAppContext.cs +++ b/mcs/class/referencesource/System.ComponentModel.DataAnnotations/InternalApis/Clr/inc/LocalAppContext.cs @@ -4,6 +4,14 @@ // // ==--== +// There are cases where we have multiple assemblies that are going to import this file and +// if they are going to also have InternalsVisibleTo between them, there will be a compiler warning +// that the type is found both in the source and in a referenced assembly. The compiler will prefer +// the version of the type defined in the source +// +// In order to disable the warning for this type we are disabling this warning for this entire file. +#pragma warning disable 436 + // NOTE: This file should not be included in mscorlib. This should only be included in FX libraries that need to provide switches using System; using System.Collections.Generic; @@ -126,3 +134,5 @@ namespace System } } } + +#pragma warning restore 436 diff --git a/mcs/class/referencesource/System.Configuration/System/Configuration/ClientConfigPaths.cs b/mcs/class/referencesource/System.Configuration/System/Configuration/ClientConfigPaths.cs index 4e46c61716..5ee50f1adc 100644 --- a/mcs/class/referencesource/System.Configuration/System/Configuration/ClientConfigPaths.cs +++ b/mcs/class/referencesource/System.Configuration/System/Configuration/ClientConfigPaths.cs @@ -26,6 +26,8 @@ namespace System.Configuration { const string ClickOnceDataDirectory = "DataDirectory"; const string ConfigExtension = ".config"; const int MAX_PATH = 260; + const int MAX_UNICODESTRING_LEN = short.MaxValue; + const int ERROR_INSUFFICIENT_BUFFER = 122; //https://msdn.microsoft.com/en-us/library/windows/desktop/ms681382(v=vs.85).aspx const int MAX_LENGTH_TO_USE = 25; const string FILE_URI_LOCAL = "file:///"; const string FILE_URI_UNC = "file://"; @@ -108,7 +110,18 @@ namespace System.Configuration { } else { StringBuilder sb = new StringBuilder(MAX_PATH); - UnsafeNativeMethods.GetModuleFileName(new HandleRef(null, IntPtr.Zero), sb, sb.Capacity); + int noOfTimes = 1; + int length = 0; + // Iterating by allocating chunk of memory each time we find the length is not sufficient. + // Performance should not be an issue for current MAX_PATH length due to this change. + while (((length = UnsafeNativeMethods.GetModuleFileName(new HandleRef(null, IntPtr.Zero), sb, sb.Capacity)) == sb.Capacity) + && Marshal.GetLastWin32Error() == ERROR_INSUFFICIENT_BUFFER + && sb.Capacity < MAX_UNICODESTRING_LEN) { + noOfTimes += 2; // increasing buffer size by 520 in each iteration - perf. + int capacity = noOfTimes * MAX_PATH < MAX_UNICODESTRING_LEN ? noOfTimes * MAX_PATH : MAX_UNICODESTRING_LEN; + sb.EnsureCapacity(capacity); + } + sb.Length = length; applicationUri = Path.GetFullPath(sb.ToString()); applicationFilename = applicationUri; } diff --git a/mcs/class/referencesource/System.Core/Microsoft/Win32/SafeHandles/CapiSafeHandles.cs b/mcs/class/referencesource/System.Core/Microsoft/Win32/SafeHandles/CapiSafeHandles.cs index 16669900dc..acda796288 100644 --- a/mcs/class/referencesource/System.Core/Microsoft/Win32/SafeHandles/CapiSafeHandles.cs +++ b/mcs/class/referencesource/System.Core/Microsoft/Win32/SafeHandles/CapiSafeHandles.cs @@ -186,6 +186,8 @@ namespace Microsoft.Win32.SafeHandles { #pragma warning restore 618 #endif internal sealed class SafeCapiHashHandle : SafeCapiHandleBase { + private static volatile SafeCapiHashHandle s_invalidHandle; + #if FEATURE_CORESYSTEM [System.Security.SecurityCritical] #endif @@ -197,9 +199,17 @@ namespace Microsoft.Win32.SafeHandles { /// public static SafeCapiHashHandle InvalidHandle { get { - SafeCapiHashHandle handle = new SafeCapiHashHandle(); - handle.SetHandle(IntPtr.Zero); - return handle; + if (s_invalidHandle == null) { + // More than one of these might get created in parallel, but that's okay. + // Saving one to the field saves on GC tracking, but by SuppressingFinalize on + // any instance returned there's already less finalization pressure. + SafeCapiHashHandle handle = new SafeCapiHashHandle(); + handle.SetHandle(IntPtr.Zero); + GC.SuppressFinalize(handle); + s_invalidHandle = handle; + } + + return s_invalidHandle; } } @@ -233,6 +243,8 @@ namespace Microsoft.Win32.SafeHandles { #pragma warning restore 618 #endif internal sealed class SafeCapiKeyHandle : SafeCapiHandleBase { + private static volatile SafeCapiKeyHandle s_invalidHandle; + #if FEATURE_CORESYSTEM [System.Security.SecurityCritical] #endif @@ -245,9 +257,17 @@ namespace Microsoft.Win32.SafeHandles { internal static SafeCapiKeyHandle InvalidHandle { [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")] get { - SafeCapiKeyHandle handle = new SafeCapiKeyHandle(); - handle.SetHandle(IntPtr.Zero); - return handle; + if (s_invalidHandle == null) { + // More than one of these might get created in parallel, but that's okay. + // Saving one to the field saves on GC tracking, but by SuppressingFinalize on + // any instance returned there's already less finalization pressure. + SafeCapiKeyHandle handle = new SafeCapiKeyHandle(); + handle.SetHandle(IntPtr.Zero); + GC.SuppressFinalize(handle); + s_invalidHandle = handle; + } + + return s_invalidHandle; } } diff --git a/mcs/class/referencesource/System.Core/System/Security/Cryptography/BCryptNative.cs b/mcs/class/referencesource/System.Core/System/Security/Cryptography/BCryptNative.cs index b0586886a1..f4d5ebecbc 100644 --- a/mcs/class/referencesource/System.Core/System/Security/Cryptography/BCryptNative.cs +++ b/mcs/class/referencesource/System.Core/System/Security/Cryptography/BCryptNative.cs @@ -38,6 +38,35 @@ namespace System.Security.Cryptography { /// Pss = 8 // BCRYPT_PAD_PSS } +#if !MONO + [StructLayout(LayoutKind.Sequential)] + internal struct BCRYPT_DSA_KEY_BLOB_V2 + { + public BCryptNative.KeyBlobMagicNumber dwMagic; // BCRYPT_DSA_PUBLIC_MAGIC_V2 or BCRYPT_DSA_PRIVATE_MAGIC_V2 + public int cbKey; // key lengths in BYTES (e.g. for a 3072-bit key, cbKey = 3072/8 = 384) + public HASHALGORITHM_ENUM hashAlgorithm; + public DSAFIPSVERSION_ENUM standardVersion; + public int cbSeedLength; // size (in bytes) of the seed value + public int cbGroupSize; // size (in bytes) of the Q value + public byte Count3; // # of iterations used to generate Q. In big-endian format. + public byte Count2; + public byte Count1; + public byte Count0; + } +#endif + internal enum HASHALGORITHM_ENUM : int + { + DSA_HASH_ALGORITHM_SHA1 = 0, + DSA_HASH_ALGORITHM_SHA256 = 1, + DSA_HASH_ALGORITHM_SHA512 = 2, + } + + internal enum DSAFIPSVERSION_ENUM : int + { + DSA_FIPS186_2 = 0, + DSA_FIPS186_3 = 1, + } + /// /// Native interop with CNG's BCrypt layer. Native definitions can be found in bcrypt.h /// @@ -102,6 +131,10 @@ namespace System.Security.Cryptography { /// Magic numbers identifying blob types /// internal enum KeyBlobMagicNumber { + DsaPublic = 0x42505344, // BCRYPT_DSA_PUBLIC_MAGIC for key lengths <= 1024 bits + DsaPublicV2 = 0x32425044, // BCRYPT_DSA_PUBLIC_MAGIC_V2 for key lengths > 1024 bits + DsaPrivate = 0x56505344, // BCRYPT_DSA_PRIVATE_MAGIC for key lengths <= 1024 bits + DsaPrivateV2 = 0x32565044, // BCRYPT_DSA_PRIVATE_MAGIC_V2 for key lengths > 1024 bits ECDHPublicP256 = 0x314B4345, // BCRYPT_ECDH_PUBLIC_P256_MAGIC ECDHPublicP384 = 0x334B4345, // BCRYPT_ECDH_PUBLIC_P384_MAGIC ECDHPublicP521 = 0x354B4345, // BCRYPT_ECDH_PUBLIC_P521_MAGIC diff --git a/mcs/class/referencesource/System.Core/System/Security/Cryptography/CapiNative.cs b/mcs/class/referencesource/System.Core/System/Security/Cryptography/CapiNative.cs index b9f7080aff..cbf1971793 100644 --- a/mcs/class/referencesource/System.Core/System/Security/Cryptography/CapiNative.cs +++ b/mcs/class/referencesource/System.Core/System/Security/Cryptography/CapiNative.cs @@ -168,6 +168,14 @@ namespace System.Security.Cryptography { public IntPtr pbData; } + [StructLayout(LayoutKind.Sequential)] + internal struct CERT_DSS_PARAMETERS + { + public CRYPTOAPI_BLOB p; + public CRYPTOAPI_BLOB q; + public CRYPTOAPI_BLOB g; + } + [StructLayout(LayoutKind.Sequential)] internal unsafe struct PROV_ENUMALGS { public AlgorithmId aiAlgId; @@ -187,6 +195,8 @@ namespace System.Security.Cryptography { internal const uint CALG_DSS_SIGN = (ALG_CLASS_SIGNATURE | ALG_TYPE_DSS | ALG_SID_DSS_ANY); internal const uint CALG_RSA_KEYX = (ALG_CLASS_KEY_EXCHANGE | ALG_TYPE_RSA | ALG_SID_RSA_ANY); internal const uint CNG_RSA_PUBLIC_KEY_BLOB = 72; + internal const uint X509_DSS_PUBLICKEY = 38; + internal const uint X509_DSS_PARAMETERS = 39; internal const uint X509_ASN_ENCODING = 0x00000001; internal const uint PKCS_7_ASN_ENCODING = 0x00010000; diff --git a/mcs/class/referencesource/System.Core/System/Security/Cryptography/CapiSymmetricAlgorithm.cs b/mcs/class/referencesource/System.Core/System/Security/Cryptography/CapiSymmetricAlgorithm.cs index 490e61651f..c1c5bdc3d7 100644 --- a/mcs/class/referencesource/System.Core/System/Security/Cryptography/CapiSymmetricAlgorithm.cs +++ b/mcs/class/referencesource/System.Core/System/Security/Cryptography/CapiSymmetricAlgorithm.cs @@ -447,6 +447,9 @@ namespace System.Security.Cryptography { buffer.Length); } else { + if (!LocalAppContextSwitches.AesCryptoServiceProviderDontCorrectlyResetDecryptor) { + resetSize = buffer.Length; + } CapiNative.UnsafeNativeMethods.CryptDecrypt(m_key, SafeCapiHashHandle.InvalidHandle, true, diff --git a/mcs/class/referencesource/System.Core/System/Security/Cryptography/ECDiffieHellman.cs b/mcs/class/referencesource/System.Core/System/Security/Cryptography/ECDiffieHellman.cs index efb002c581..39a279372b 100644 --- a/mcs/class/referencesource/System.Core/System/Security/Cryptography/ECDiffieHellman.cs +++ b/mcs/class/referencesource/System.Core/System/Security/Cryptography/ECDiffieHellman.cs @@ -46,6 +46,101 @@ namespace System.Security.Cryptography { // public abstract ECDiffieHellmanPublicKey PublicKey { get; } - public abstract byte[] DeriveKeyMaterial(ECDiffieHellmanPublicKey otherPartyPublicKey); + + // This method must be implemented by derived classes. In order to conform to the contract, it cannot be abstract. + public virtual byte[] DeriveKeyMaterial(ECDiffieHellmanPublicKey otherPartyPublicKey) + { + throw DerivedClassMustOverride(); + } + + /// + /// Derive key material using the formula HASH(x) where x is the computed result of the EC Diffie-Hellman algorithm. + /// + /// The public key of the party with which to derive a mutual secret. + /// The identifier for the hash algorithm to use. + /// A hashed output suitable for key material + /// is over a different curve than this key + public byte[] DeriveKeyFromHash(ECDiffieHellmanPublicKey otherPartyPublicKey, HashAlgorithmName hashAlgorithm) + { + return DeriveKeyFromHash(otherPartyPublicKey, hashAlgorithm, null, null); + } + + /// + /// Derive key material using the formula HASH(secretPrepend || x || secretAppend) where x is the computed + /// result of the EC Diffie-Hellman algorithm. + /// + /// The public key of the party with which to derive a mutual secret. + /// The identifier for the hash algorithm to use. + /// A value to prepend to the derived secret before hashing. A null value is treated as an empty array. + /// A value to append to the derived secret before hashing. A null value is treated as an empty array. + /// A hashed output suitable for key material + /// is over a different curve than this key + public virtual byte[] DeriveKeyFromHash( + ECDiffieHellmanPublicKey otherPartyPublicKey, + HashAlgorithmName hashAlgorithm, + byte[] secretPrepend, + byte[] secretAppend) + { + throw DerivedClassMustOverride(); + } + + /// + /// Derive key material using the formula HMAC(hmacKey, x) where x is the computed + /// result of the EC Diffie-Hellman algorithm. + /// + /// The public key of the party with which to derive a mutual secret. + /// The identifier for the hash algorithm to use. + /// The key to use in the HMAC. A null value indicates that the result of the EC Diffie-Hellman algorithm should be used as the HMAC key. + /// A hashed output suitable for key material + /// is over a different curve than this key + public byte[] DeriveKeyFromHmac( + ECDiffieHellmanPublicKey otherPartyPublicKey, + HashAlgorithmName hashAlgorithm, + byte[] hmacKey) + { + return DeriveKeyFromHmac(otherPartyPublicKey, hashAlgorithm, hmacKey, null, null); + } + + /// + /// Derive key material using the formula HMAC(hmacKey, secretPrepend || x || secretAppend) where x is the computed + /// result of the EC Diffie-Hellman algorithm. + /// + /// The public key of the party with which to derive a mutual secret. + /// The identifier for the hash algorithm to use. + /// The key to use in the HMAC. A null value indicates that the result of the EC Diffie-Hellman algorithm should be used as the HMAC key. + /// A value to prepend to the derived secret before hashing. A null value is treated as an empty array. + /// A value to append to the derived secret before hashing. A null value is treated as an empty array. + /// A hashed output suitable for key material + /// is over a different curve than this key + public virtual byte[] DeriveKeyFromHmac( + ECDiffieHellmanPublicKey otherPartyPublicKey, + HashAlgorithmName hashAlgorithm, + byte[] hmacKey, + byte[] secretPrepend, + byte[] secretAppend) + { + throw DerivedClassMustOverride(); + } + + /// + /// Derive key material using the TLS pseudo-random function (PRF) derivation algorithm. + /// + /// The public key of the party with which to derive a mutual secret. + /// The ASCII encoded PRF label. + /// The 64-byte PRF seed. + /// A 48-byte output of the TLS pseudo-random function. + /// is over a different curve than this key + /// is null + /// is null + /// is not exactly 64 bytes in length + public virtual byte[] DeriveKeyTls(ECDiffieHellmanPublicKey otherPartyPublicKey, byte[] prfLabel, byte[] prfSeed) + { + throw DerivedClassMustOverride(); + } + + private static Exception DerivedClassMustOverride() + { + return new NotImplementedException(SR.GetString(SR.NotSupported_SubclassOverride)); + } } } diff --git a/mcs/class/referencesource/System.Core/System/Security/Cryptography/ECDiffieHellmanCng.cs b/mcs/class/referencesource/System.Core/System/Security/Cryptography/ECDiffieHellmanCng.cs index ada0c1ac58..4a555dae54 100644 --- a/mcs/class/referencesource/System.Core/System/Security/Cryptography/ECDiffieHellmanCng.cs +++ b/mcs/class/referencesource/System.Core/System/Security/Cryptography/ECDiffieHellmanCng.cs @@ -93,7 +93,21 @@ namespace System.Security.Cryptography { } CodeAccessPermission.RevertAssert(); - KeySize = m_key.KeySize; + // Our LegalKeySizes value stores the values that we encoded as being the correct + // legal key size limitations for this algorithm, as documented on MSDN. + // + // But on a new OS version we might not question if our limit is accurate, or MSDN + // could have been innacurate to start with. + // + // Since the key is already loaded, we know that Windows thought it to be valid; + // therefore we should set KeySizeValue directly to bypass the LegalKeySizes conformance + // check. + // + // For RSA there are known cases where this change matters. RSACryptoServiceProvider can + // create a 384-bit RSA key, which we consider too small to be legal. It can also create + // a 1032-bit RSA key, which we consider illegal because it doesn't match our 64-bit + // alignment requirement. (In both cases Windows loads it just fine) + KeySizeValue = m_key.KeySize; } /// @@ -247,7 +261,22 @@ namespace System.Security.Cryptography { // m_key = value; - KeySize = m_key.KeySize; + + // Our LegalKeySizes value stores the values that we encoded as being the correct + // legal key size limitations for this algorithm, as documented on MSDN. + // + // But on a new OS version we might not question if our limit is accurate, or MSDN + // could have been innacurate to start with. + // + // Since the key is already loaded, we know that Windows thought it to be valid; + // therefore we should set KeySizeValue directly to bypass the LegalKeySizes conformance + // check. + // + // For RSA there are known cases where this change matters. RSACryptoServiceProvider can + // create a 384-bit RSA key, which we consider too small to be legal. It can also create + // a 1032-bit RSA key, which we consider illegal because it doesn't match our 64-bit + // alignment requirement. (In both cases Windows loads it just fine) + KeySizeValue = m_key.KeySize; } } @@ -369,6 +398,84 @@ namespace System.Security.Cryptography { } } + [SecuritySafeCritical] + public override byte[] DeriveKeyFromHash( + ECDiffieHellmanPublicKey otherPartyPublicKey, + HashAlgorithmName hashAlgorithm, + byte[] secretPrepend, + byte[] secretAppend) + { + Contract.Ensures(Contract.Result() != null); + + if (otherPartyPublicKey == null) + throw new ArgumentNullException("otherPartyPublicKey"); + if (string.IsNullOrEmpty(hashAlgorithm.Name)) + throw new ArgumentException(SR.GetString(SR.Cryptography_HashAlgorithmNameNullOrEmpty), "hashAlgorithm"); + + using (SafeNCryptSecretHandle secretAgreement = DeriveSecretAgreementHandle(otherPartyPublicKey)) + { + return NCryptNative.DeriveKeyMaterialHash( + secretAgreement, + hashAlgorithm.Name, + secretPrepend, + secretAppend, + NCryptNative.SecretAgreementFlags.None); + } + } + + [SecuritySafeCritical] + public override byte[] DeriveKeyFromHmac( + ECDiffieHellmanPublicKey otherPartyPublicKey, + HashAlgorithmName hashAlgorithm, + byte[] hmacKey, + byte[] secretPrepend, + byte[] secretAppend) + { + Contract.Ensures(Contract.Result() != null); + + if (otherPartyPublicKey == null) + throw new ArgumentNullException("otherPartyPublicKey"); + if (string.IsNullOrEmpty(hashAlgorithm.Name)) + throw new ArgumentException(SR.GetString(SR.Cryptography_HashAlgorithmNameNullOrEmpty), "hashAlgorithm"); + + using (SafeNCryptSecretHandle secretAgreement = DeriveSecretAgreementHandle(otherPartyPublicKey)) + { + NCryptNative.SecretAgreementFlags flags = hmacKey == null ? + NCryptNative.SecretAgreementFlags.UseSecretAsHmacKey : + NCryptNative.SecretAgreementFlags.None; + + return NCryptNative.DeriveKeyMaterialHmac( + secretAgreement, + hashAlgorithm.Name, + hmacKey, + secretPrepend, + secretAppend, + flags); + } + } + + [SecuritySafeCritical] + public override byte[] DeriveKeyTls(ECDiffieHellmanPublicKey otherPartyPublicKey, byte[] prfLabel, byte[] prfSeed) + { + Contract.Ensures(Contract.Result() != null); + + if (otherPartyPublicKey == null) + throw new ArgumentNullException("otherPartyPublicKey"); + if (prfLabel == null) + throw new ArgumentNullException("prfLabel"); + if (prfSeed == null) + throw new ArgumentNullException("prfSeed"); + + using (SafeNCryptSecretHandle secretAgreement = DeriveSecretAgreementHandle(otherPartyPublicKey)) + { + return NCryptNative.DeriveKeyMaterialTls( + secretAgreement, + prfLabel, + prfSeed, + NCryptNative.SecretAgreementFlags.None); + } + } + /// /// Get a handle to the secret agreement generated between two parties /// diff --git a/mcs/class/referencesource/System.Core/System/Security/Cryptography/ECDiffieHellmanPublicKey.cs b/mcs/class/referencesource/System.Core/System/Security/Cryptography/ECDiffieHellmanPublicKey.cs index 3099a3a77e..91e89d8be9 100644 --- a/mcs/class/referencesource/System.Core/System/Security/Cryptography/ECDiffieHellmanPublicKey.cs +++ b/mcs/class/referencesource/System.Core/System/Security/Cryptography/ECDiffieHellmanPublicKey.cs @@ -40,6 +40,10 @@ namespace System.Security.Cryptography { return m_keyBlob.Clone() as byte[]; } - public abstract string ToXmlString(); + // This method must be implemented by derived classes. In order to conform to the contract, it cannot be abstract. + public virtual string ToXmlString() + { + throw new NotImplementedException(SR.GetString(SR.NotSupported_SubclassOverride)); + } } } diff --git a/mcs/class/referencesource/System.Core/System/Security/Cryptography/ECDsaCng.cs b/mcs/class/referencesource/System.Core/System/Security/Cryptography/ECDsaCng.cs index 0dea9c70ed..ec51a5c665 100644 --- a/mcs/class/referencesource/System.Core/System/Security/Cryptography/ECDsaCng.cs +++ b/mcs/class/referencesource/System.Core/System/Security/Cryptography/ECDsaCng.cs @@ -82,12 +82,12 @@ namespace System.Security.Cryptography { [SecuritySafeCritical] public ECDsaCng(CngKey key) { Contract.Ensures(LegalKeySizesValue != null); - Contract.Ensures(m_key != null && m_key.AlgorithmGroup == CngAlgorithmGroup.ECDsa); + Contract.Ensures(m_key != null && IsEccAlgorithmGroup(m_key.AlgorithmGroup)); if (key == null) { throw new ArgumentNullException("key"); } - if (key.AlgorithmGroup != CngAlgorithmGroup.ECDsa) { + if (!IsEccAlgorithmGroup(key.AlgorithmGroup)) { throw new ArgumentException(SR.GetString(SR.Cryptography_ArgECDsaRequiresECDsaKey), "key"); } @@ -111,7 +111,21 @@ namespace System.Security.Cryptography { } CodeAccessPermission.RevertAssert(); - KeySize = m_key.KeySize; + // Our LegalKeySizes value stores the values that we encoded as being the correct + // legal key size limitations for this algorithm, as documented on MSDN. + // + // But on a new OS version we might not question if our limit is accurate, or MSDN + // could have been innacurate to start with. + // + // Since the key is already loaded, we know that Windows thought it to be valid; + // therefore we should set KeySizeValue directly to bypass the LegalKeySizes conformance + // check. + // + // For RSA there are known cases where this change matters. RSACryptoServiceProvider can + // create a 384-bit RSA key, which we consider too small to be legal. It can also create + // a 1032-bit RSA key, which we consider illegal because it doesn't match our 64-bit + // alignment requirement. (In both cases Windows loads it just fine) + KeySizeValue = m_key.KeySize; } /// @@ -140,8 +154,8 @@ namespace System.Security.Cryptography { public CngKey Key { get { Contract.Ensures(Contract.Result() != null); - Contract.Ensures(Contract.Result().AlgorithmGroup == CngAlgorithmGroup.ECDsa); - Contract.Ensures(m_key != null && m_key.AlgorithmGroup == CngAlgorithmGroup.ECDsa); + Contract.Ensures(IsEccAlgorithmGroup(Contract.Result().AlgorithmGroup)); + Contract.Ensures(m_key != null && IsEccAlgorithmGroup(m_key.AlgorithmGroup)); // If the size of the key no longer matches our stored value, then we need to replace it with // a new key of the correct size. @@ -179,9 +193,9 @@ namespace System.Security.Cryptography { private set { Contract.Requires(value != null); - Contract.Ensures(m_key != null && m_key.AlgorithmGroup == CngAlgorithmGroup.ECDsa); + Contract.Ensures(m_key != null && IsEccAlgorithmGroup(m_key.AlgorithmGroup)); - if (value.AlgorithmGroup != CngAlgorithmGroup.ECDsa) { + if (!IsEccAlgorithmGroup(value.AlgorithmGroup)) { throw new ArgumentException(SR.GetString(SR.Cryptography_ArgECDsaRequiresECDsaKey)); } @@ -196,7 +210,22 @@ namespace System.Security.Cryptography { // m_key = value; - KeySize = m_key.KeySize; + + // Our LegalKeySizes value stores the values that we encoded as being the correct + // legal key size limitations for this algorithm, as documented on MSDN. + // + // But on a new OS version we might not question if our limit is accurate, or MSDN + // could have been innacurate to start with. + // + // Since the key is already loaded, we know that Windows thought it to be valid; + // therefore we should set KeySizeValue directly to bypass the LegalKeySizes conformance + // check. + // + // For RSA there are known cases where this change matters. RSACryptoServiceProvider can + // create a 384-bit RSA key, which we consider too small to be legal. It can also create + // a 1032-bit RSA key, which we consider illegal because it doesn't match our 64-bit + // alignment requirement. (In both cases Windows loads it just fine) + KeySizeValue = m_key.KeySize; } } @@ -444,6 +473,16 @@ namespace System.Security.Cryptography { return hasher.HashFinal(); } } - #endif + + private static bool IsEccAlgorithmGroup(CngAlgorithmGroup algorithmGroup) + { + // Sometimes, when reading from certificates, ECDSA keys get identified as ECDH. + // Windows allows the ECDH keys to perform both key exchange (ECDH) and signing (ECDSA), + // so either value is acceptable for the ECDSA wrapper object. + // + // It is worth noting, however, that ECDSA-identified keys cannot be used for key exchange (ECDH) in CNG. + return algorithmGroup == CngAlgorithmGroup.ECDsa || algorithmGroup == CngAlgorithmGroup.ECDiffieHellman; + } +#endif } } diff --git a/mcs/class/referencesource/System.Core/System/Security/Cryptography/NCryptNative.cs b/mcs/class/referencesource/System.Core/System/Security/Cryptography/NCryptNative.cs index 8807a43424..9faf5ee01b 100644 --- a/mcs/class/referencesource/System.Core/System/Security/Cryptography/NCryptNative.cs +++ b/mcs/class/referencesource/System.Core/System/Security/Cryptography/NCryptNative.cs @@ -796,10 +796,6 @@ namespace System.Security.Cryptography { signature, signature.Length, paddingMode); - if (error != ErrorCode.Success && error != ErrorCode.BadSignature) { - throw new CryptographicException((int)error); - } - return error == ErrorCode.Success; } @@ -1694,6 +1690,55 @@ namespace System.Security.Cryptography { return signature; } + /// + /// Sign a hash using no padding + /// + [System.Security.SecurityCritical] + internal static byte[] SignHash(SafeNCryptKeyHandle key, byte[] hash, int expectedSize) + { + Contract.Requires(key != null); + Contract.Requires(hash != null); + Contract.Ensures(Contract.Result() != null); + +#if DEBUG + expectedSize = 1; +#endif + + // Figure out how big the signature is + byte[] signature = new byte[expectedSize]; + int signatureSize = 0; + ErrorCode error = UnsafeNativeMethods.NCryptSignHash(key, + IntPtr.Zero, + hash, + hash.Length, + signature, + signature.Length, + out signatureSize, + 0); + + if (error == ErrorCode.BufferTooSmall) + { + signature = new byte[signatureSize]; + + error = UnsafeNativeMethods.NCryptSignHash(key, + IntPtr.Zero, + hash, + hash.Length, + signature, + signature.Length, + out signatureSize, + 0); + } + + if (error != ErrorCode.Success) + { + throw new CryptographicException((int)error); + } + + Array.Resize(ref signature, signatureSize); + return signature; + } + /// /// Unpack a key blob in ECC public blob format into its X and Y parameters /// @@ -1736,10 +1781,6 @@ namespace System.Security.Cryptography { signature.Length, 0); - if (error != ErrorCode.Success && error != ErrorCode.BadSignature) { - throw new CryptographicException((int)error); - } - return error == ErrorCode.Success; } } diff --git a/mcs/class/referencesource/System.Core/System/Security/Cryptography/RsaCng.cs b/mcs/class/referencesource/System.Core/System/Security/Cryptography/RsaCng.cs index ca5ec3694d..78764bb468 100644 --- a/mcs/class/referencesource/System.Core/System/Security/Cryptography/RsaCng.cs +++ b/mcs/class/referencesource/System.Core/System/Security/Cryptography/RsaCng.cs @@ -129,7 +129,11 @@ namespace System.Security.Cryptography // If we don't have a key yet, we need to generate a random one now if (_key == null) { - CngKeyCreationParameters creationParameters = new CngKeyCreationParameters(); + CngKeyCreationParameters creationParameters = new CngKeyCreationParameters() + { + ExportPolicy = CngExportPolicies.AllowPlaintextExport, + }; + CngProperty keySizeProperty = new CngProperty(NCryptNative.KeyPropertyName.Length, BitConverter.GetBytes(KeySize), CngPropertyOptions.None); @@ -154,7 +158,22 @@ namespace System.Security.Cryptography } _key = value; - KeySize = _key.KeySize; + + // Our LegalKeySizes value stores the values that we encoded as being the correct + // legal key size limitations for this algorithm, as documented on MSDN. + // + // But on a new OS version we might not question if our limit is accurate, or MSDN + // could have been innacurate to start with. + // + // Since the key is already loaded, we know that Windows thought it to be valid; + // therefore we should set KeySizeValue directly to bypass the LegalKeySizes conformance + // check. + // + // For RSA there are known cases where this change matters. RSACryptoServiceProvider can + // create a 384-bit RSA key, which we consider too small to be legal. It can also create + // a 1032-bit RSA key, which we consider illegal because it doesn't match our 64-bit + // alignment requirement. (In both cases Windows loads it just fine) + KeySizeValue = _key.KeySize; } } @@ -544,6 +563,25 @@ namespace System.Security.Cryptography throw new CryptographicException(SR.GetString(SR.Cryptography_UnsupportedPaddingMode)); } } + + /* + * The members + * DecryptValue + * EncryptValue + * get_KeyExchangeAlgorithm + * get_SignatureAlgorithm + * are all implemented on RSA as of net46. + * + * But in servicing situations, System.Core.dll can get patched onto a machine which has mscorlib < net46, meaning + * these abstract members have no implementation. + * + * To keep servicing simple, we'll redefine the overrides here. Since this type is sealed it only affects reflection, + * as there are no derived types to mis-target base.-invocations. + */ + public override byte[] DecryptValue(byte[] rgb) { throw new NotSupportedException(SR.NotSupported_Method); } + public override byte[] EncryptValue(byte[] rgb) { throw new NotSupportedException(SR.NotSupported_Method); } + public override string KeyExchangeAlgorithm { get { return "RSA"; } } + public override string SignatureAlgorithm { get { return "RSA"; } } #endif } } diff --git a/mcs/class/referencesource/System.Core/System/Security/Cryptography/X509Certificates/RSACertificateExtensions.cs b/mcs/class/referencesource/System.Core/System/Security/Cryptography/X509Certificates/RSACertificateExtensions.cs index e4ef01d3e6..a69b7ed8aa 100644 --- a/mcs/class/referencesource/System.Core/System/Security/Cryptography/X509Certificates/RSACertificateExtensions.cs +++ b/mcs/class/referencesource/System.Core/System/Security/Cryptography/X509Certificates/RSACertificateExtensions.cs @@ -71,8 +71,14 @@ namespace System.Security.Cryptography.X509Certificates { if (privateKeyHandle == null) { + if (LocalAppContextSwitches.DontReliablyClonePrivateKey) + return (RSA)certificate.PrivateKey; + // fall back to CAPI if we cannot acquire the key using CNG. - return (RSA)certificate.PrivateKey; + RSACryptoServiceProvider rsaCsp = (RSACryptoServiceProvider)certificate.PrivateKey; + CspParameters cspParameters = DSACertificateExtensions.CopyCspParameters(rsaCsp); + RSACryptoServiceProvider clone = new RSACryptoServiceProvider(cspParameters); + return clone; } CngKey key = CngKey.Open(privateKeyHandle, CngKeyHandleOpenOptions.None); diff --git a/mcs/class/referencesource/System.Core/System/threading/ReaderWriterLockSlim/ReaderWriterLockSlim.cs b/mcs/class/referencesource/System.Core/System/threading/ReaderWriterLockSlim/ReaderWriterLockSlim.cs index 19db1acb0a..aeff48d004 100644 --- a/mcs/class/referencesource/System.Core/System/threading/ReaderWriterLockSlim/ReaderWriterLockSlim.cs +++ b/mcs/class/referencesource/System.Core/System/threading/ReaderWriterLockSlim/ReaderWriterLockSlim.cs @@ -155,9 +155,7 @@ namespace System.Threading lockID = Interlocked.Increment(ref s_nextLockID); } -#if NET_4_5 [MethodImpl(MethodImplOptions.AggressiveInlining)] -#endif private static bool IsRWEntryEmpty(ReaderWriterCount rwc) { if (rwc.lockID == 0) @@ -181,9 +179,7 @@ namespace System.Threading /// entry for this thread, but doesn't want to add one if an existing one /// could not be found. /// -#if NET_4_5 [MethodImpl(MethodImplOptions.AggressiveInlining)] -#endif private ReaderWriterCount GetThreadRWCount(bool dontAllocate) { ReaderWriterCount rwc = t_rwc; @@ -1117,9 +1113,7 @@ namespace System.Threading return owners & READER_MASK; } -#if NET_4_5 [MethodImpl(MethodImplOptions.AggressiveInlining)] -#endif private void EnterMyLock() { if (Interlocked.CompareExchange(ref myLock, 1, 0) != 0) diff --git a/mcs/class/referencesource/System.Data.Entity/System/Data/Common/Utils/MetadataHelper.cs b/mcs/class/referencesource/System.Data.Entity/System/Data/Common/Utils/MetadataHelper.cs index 1ab0fb9122..8d7a31911c 100644 --- a/mcs/class/referencesource/System.Data.Entity/System/Data/Common/Utils/MetadataHelper.cs +++ b/mcs/class/referencesource/System.Data.Entity/System/Data/Common/Utils/MetadataHelper.cs @@ -833,6 +833,8 @@ namespace System.Data.Common.Utils [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Cryptographic.Standard", "CA5350:Microsoft.Cryptographic.Standard", Justification = "MD5CryptoServiceProvider is not used for cryptography/security purposes and we do it only for v1 and v1.1 for compatibility reasons.")] + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security.Cryptography", "CA5350:Microsoft.Cryptographic.Standard", + Justification = "MD5CryptoServiceProvider is not used for cryptography/security purposes and we do it only for v1 and v1.1 for compatibility reasons.")] internal static HashAlgorithm CreateMetadataHashAlgorithm(double schemaVersion) { HashAlgorithm hashAlgorithm; diff --git a/mcs/class/referencesource/System.Data.Entity/System/Data/EntityModel/SchemaObjectModel/Schema.cs b/mcs/class/referencesource/System.Data.Entity/System/Data/EntityModel/SchemaObjectModel/Schema.cs index a0388683aa..adb7b34c74 100644 --- a/mcs/class/referencesource/System.Data.Entity/System/Data/EntityModel/SchemaObjectModel/Schema.cs +++ b/mcs/class/referencesource/System.Data.Entity/System/Data/EntityModel/SchemaObjectModel/Schema.cs @@ -1253,6 +1253,7 @@ namespace System.Data.EntityModel.SchemaObjectModel return schemaSet; } + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security.Xml", "CA3060:UseXmlReaderForSchemaRead", Justification = "The schema files are embedded in the product assembly as resources")] private static void AddXmlSchemaToSet(XmlSchemaSet schemaSet, XmlSchemaResource schemaResource, HashSet schemasAlreadyAdded) { // loop through the children to do a depth first load diff --git a/mcs/class/referencesource/System.Data.SqlXml/System/Xml/Xsl/IlGen/XmlILOptimizerVisitor.cs.REMOVED.git-id b/mcs/class/referencesource/System.Data.SqlXml/System/Xml/Xsl/IlGen/XmlILOptimizerVisitor.cs.REMOVED.git-id index b4987ec7dc..88433c5c3a 100644 --- a/mcs/class/referencesource/System.Data.SqlXml/System/Xml/Xsl/IlGen/XmlILOptimizerVisitor.cs.REMOVED.git-id +++ b/mcs/class/referencesource/System.Data.SqlXml/System/Xml/Xsl/IlGen/XmlILOptimizerVisitor.cs.REMOVED.git-id @@ -1 +1 @@ -e1c869221fa43552e2ba4aeda158583a553d307c \ No newline at end of file +f671178fc0c4bde44e8228f097fdf8007979ec69 \ No newline at end of file diff --git a/mcs/class/referencesource/System.Data/System/Data/Common/DbConnectionStringCommon.cs b/mcs/class/referencesource/System.Data/System/Data/Common/DbConnectionStringCommon.cs index e1981b6b9d..24be05dfc2 100644 --- a/mcs/class/referencesource/System.Data/System/Data/Common/DbConnectionStringCommon.cs +++ b/mcs/class/referencesource/System.Data/System/Data/Common/DbConnectionStringCommon.cs @@ -323,6 +323,143 @@ namespace System.Data.Common { } } + #region <> + const string PoolBlockingPeriodAutoString = "Auto"; + const string PoolBlockingPeriodAlwaysBlockString = "AlwaysBlock"; + const string PoolBlockingPeriodNeverBlockString = "NeverBlock"; + + internal static bool TryConvertToPoolBlockingPeriod(string value, out PoolBlockingPeriod result) + { + Debug.Assert(Enum.GetNames(typeof(PoolBlockingPeriod)).Length == 3, "PoolBlockingPeriod enum has changed, update needed"); + Debug.Assert(null != value, "TryConvertToPoolBlockingPeriod(null,...)"); + + if (StringComparer.OrdinalIgnoreCase.Equals(value, PoolBlockingPeriodAutoString)) + { + result = PoolBlockingPeriod.Auto; + return true; + } + else if (StringComparer.OrdinalIgnoreCase.Equals(value, PoolBlockingPeriodAlwaysBlockString)) + { + result = PoolBlockingPeriod.AlwaysBlock; + return true; + } + else if (StringComparer.OrdinalIgnoreCase.Equals(value, PoolBlockingPeriodNeverBlockString)) + { + result = PoolBlockingPeriod.NeverBlock; + return true; + } + else + { + result = DbConnectionStringDefaults.PoolBlockingPeriod; + return false; + } + } + + internal static bool IsValidPoolBlockingPeriodValue(PoolBlockingPeriod value) + { + Debug.Assert(Enum.GetNames(typeof(PoolBlockingPeriod)).Length == 3, "PoolBlockingPeriod enum has changed, update needed"); + return value == PoolBlockingPeriod.Auto || value == PoolBlockingPeriod.AlwaysBlock || value == PoolBlockingPeriod.NeverBlock; + } + + internal static string PoolBlockingPeriodToString(PoolBlockingPeriod value) + { + Debug.Assert(IsValidPoolBlockingPeriodValue(value)); + + if (value == PoolBlockingPeriod.AlwaysBlock) + { + return PoolBlockingPeriodAlwaysBlockString; + } + if (value == PoolBlockingPeriod.NeverBlock) + { + return PoolBlockingPeriodNeverBlockString; + } + else + { + return PoolBlockingPeriodAutoString; + } + } + + /// + /// This method attempts to convert the given value to a PoolBlockingPeriod enum. The algorithm is: + /// * if the value is from type string, it will be matched against PoolBlockingPeriod enum names only, using ordinal, case-insensitive comparer + /// * if the value is from type PoolBlockingPeriod, it will be used as is + /// * if the value is from integral type (SByte, Int16, Int32, Int64, Byte, UInt16, UInt32, or UInt64), it will be converted to enum + /// * if the value is another enum or any other type, it will be blocked with an appropriate ArgumentException + /// + /// in any case above, if the conerted value is out of valid range, the method raises ArgumentOutOfRangeException. + /// + /// PoolBlockingPeriod value in the valid range + internal static PoolBlockingPeriod ConvertToPoolBlockingPeriod(string keyword, object value) + { + Debug.Assert(null != value, "ConvertToPoolBlockingPeriod(null)"); + string sValue = (value as string); + PoolBlockingPeriod result; + if (null != sValue) + { + // We could use Enum.TryParse here, but it accepts value combinations like + // "ReadOnly, ReadWrite" which are unwelcome here + // Also, Enum.TryParse is 100x slower than plain StringComparer.OrdinalIgnoreCase.Equals method. + + if (TryConvertToPoolBlockingPeriod(sValue, out result)) + { + return result; + } + + // try again after remove leading & trailing whitespaces. + sValue = sValue.Trim(); + if (TryConvertToPoolBlockingPeriod(sValue, out result)) + { + return result; + } + + // string values must be valid + throw ADP.InvalidConnectionOptionValue(keyword); + } + else + { + // the value is not string, try other options + PoolBlockingPeriod eValue; + + if (value is PoolBlockingPeriod) + { + // quick path for the most common case + eValue = (PoolBlockingPeriod)value; + } + else if (value.GetType().IsEnum) + { + // explicitly block scenarios in which user tries to use wrong enum types, like: + // builder["PoolBlockingPeriod"] = EnvironmentVariableTarget.Process; + // workaround: explicitly cast non-PoolBlockingPeriod enums to int + throw ADP.ConvertFailed(value.GetType(), typeof(PoolBlockingPeriod), null); + } + else + { + try + { + // Enum.ToObject allows only integral and enum values (enums are blocked above), rasing ArgumentException for the rest + eValue = (PoolBlockingPeriod)Enum.ToObject(typeof(PoolBlockingPeriod), value); + } + catch (ArgumentException e) + { + // to be consistent with the messages we send in case of wrong type usage, replace + // the error with our exception, and keep the original one as inner one for troubleshooting + throw ADP.ConvertFailed(value.GetType(), typeof(PoolBlockingPeriod), e); + } + } + + // ensure value is in valid range + if (IsValidPoolBlockingPeriodValue(eValue)) + { + return eValue; + } + else + { + throw ADP.InvalidEnumerationValue(typeof(ApplicationIntent), (int)eValue); + } + } + } + #endregion + const string ApplicationIntentReadWriteString = "ReadWrite"; const string ApplicationIntentReadOnlyString = "ReadOnly"; @@ -752,6 +889,7 @@ namespace System.Data.Common { internal const int ConnectRetryInterval = 10; internal static readonly SqlAuthenticationMethod Authentication = SqlAuthenticationMethod.NotSpecified; internal static readonly SqlConnectionColumnEncryptionSetting ColumnEncryptionSetting = SqlConnectionColumnEncryptionSetting.Disabled; + internal const PoolBlockingPeriod PoolBlockingPeriod = SqlClient.PoolBlockingPeriod.Auto; } internal static class DbConnectionOptionKeywords { @@ -819,6 +957,7 @@ namespace System.Data.Common { internal const string Authentication = "Authentication"; internal const string Certificate = "Certificate"; internal const string ColumnEncryptionSetting = "Column Encryption Setting"; + internal const string PoolBlockingPeriod = "PoolBlockingPeriod"; // common keywords (OleDb, OracleClient, SqlClient) internal const string DataSource = "Data Source"; diff --git a/mcs/class/referencesource/System.Data/System/Data/DataSet.cs.REMOVED.git-id b/mcs/class/referencesource/System.Data/System/Data/DataSet.cs.REMOVED.git-id index 8c025a0796..6b32fbdf95 100644 --- a/mcs/class/referencesource/System.Data/System/Data/DataSet.cs.REMOVED.git-id +++ b/mcs/class/referencesource/System.Data/System/Data/DataSet.cs.REMOVED.git-id @@ -1 +1 @@ -cb0c072a6596823dda1c71424cf7f7567719a28b \ No newline at end of file +44d81f07e1ef51520c0677f750ff35d1e6774efc \ No newline at end of file diff --git a/mcs/class/referencesource/System.Data/System/Data/DataTable.cs.REMOVED.git-id b/mcs/class/referencesource/System.Data/System/Data/DataTable.cs.REMOVED.git-id index 5f894cc55d..61043bd9a7 100644 --- a/mcs/class/referencesource/System.Data/System/Data/DataTable.cs.REMOVED.git-id +++ b/mcs/class/referencesource/System.Data/System/Data/DataTable.cs.REMOVED.git-id @@ -1 +1 @@ -637816ef0c379f684e5e1133aca1e168b9896e41 \ No newline at end of file +24673fa5c5120d868cf61c9ab74da5abe2261022 \ No newline at end of file diff --git a/mcs/class/referencesource/System.Data/System/Data/ProviderBase/DbConnectionPool.cs b/mcs/class/referencesource/System.Data/System/Data/ProviderBase/DbConnectionPool.cs index 5b5743725f..dd0b6ad4bb 100644 --- a/mcs/class/referencesource/System.Data/System/Data/ProviderBase/DbConnectionPool.cs +++ b/mcs/class/referencesource/System.Data/System/Data/ProviderBase/DbConnectionPool.cs @@ -12,6 +12,7 @@ namespace System.Data.ProviderBase { using System.Collections; using System.Collections.Generic; using System.Data.Common; + using System.Data.SqlClient; using System.Diagnostics; using System.Globalization; using System.Runtime.CompilerServices; @@ -756,7 +757,81 @@ namespace System.Data.ProviderBase { private Timer CreateCleanupTimer() { return (new Timer(new TimerCallback(this.CleanupCallback), null, _cleanupWait, _cleanupWait)); } - + + private static readonly string[] AzureSqlServerEndpoints = {Res.GetString(Res.AZURESQL_GenericEndpoint), + Res.GetString(Res.AZURESQL_GermanEndpoint), + Res.GetString(Res.AZURESQL_UsGovEndpoint), + Res.GetString(Res.AZURESQL_ChinaEndpoint) }; + private static bool IsAzureSqlServerEndpoint(string dataSource) + { + // remove server port + var i = dataSource.LastIndexOf(','); + if (i >= 0) + { + dataSource = dataSource.Substring(0, i); + } + + // check for the instance name + i = dataSource.LastIndexOf('\\'); + if (i >= 0) + { + dataSource = dataSource.Substring(0, i); + } + + // trim redundant whitespaces + dataSource = dataSource.Trim(); + + // check if servername end with any azure endpoints + for (i = 0; i < AzureSqlServerEndpoints.Length; i++) + { + if (dataSource.EndsWith(AzureSqlServerEndpoints[i], StringComparison.OrdinalIgnoreCase)) + { + return true; + } + } + return false; + } + + private bool IsBlockingPeriodEnabled() + { + var poolGroupConnectionOptions = _connectionPoolGroup.ConnectionOptions as SqlConnectionString; + if (poolGroupConnectionOptions == null) + { + return true; + } + + var policy = poolGroupConnectionOptions.PoolBlockingPeriod; + + switch (policy) + { + case PoolBlockingPeriod.Auto: + { + if (IsAzureSqlServerEndpoint(poolGroupConnectionOptions.DataSource)) + { + return false; // in Azure it will be Disabled + } + else + { + return true; // in Non Azure, it will be Enabled + } + } + case PoolBlockingPeriod.AlwaysBlock: + { + return true; //Enabled + } + case PoolBlockingPeriod.NeverBlock: + { + return false; //Disabled + } + default: + { + //we should never get into this path. + Debug.Fail("Unknown PoolBlockingPeriod. Please specify explicit results in above switch case statement."); + return true; + } + } + } + private DbConnectionInternal CreateObject(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection) { DbConnectionInternal newObj = null; @@ -797,7 +872,7 @@ namespace System.Data.ProviderBase { // Reset the error wait: _errorWait = ERROR_WAIT_DEFAULT; } - catch(Exception e) { + catch(Exception e) { // if (!ADP.IsCatchableExceptionType(e)) { throw; @@ -805,6 +880,11 @@ namespace System.Data.ProviderBase { ADP.TraceExceptionForCapture(e); + if (!IsBlockingPeriodEnabled()) + { + throw; + } + newObj = null; // set to null, so we do not return bad new object // Failed to create instance _resError = e; diff --git a/mcs/class/referencesource/System.Data/System/Data/SqlClient/SqlClientSymmetricKey.cs b/mcs/class/referencesource/System.Data/System/Data/SqlClient/SqlClientSymmetricKey.cs index 112108ae14..501ed7c915 100644 --- a/mcs/class/referencesource/System.Data/System/Data/SqlClient/SqlClientSymmetricKey.cs +++ b/mcs/class/referencesource/System.Data/System/Data/SqlClient/SqlClientSymmetricKey.cs @@ -15,10 +15,9 @@ namespace System.Data.SqlClient /// Base class containing raw key bytes for symmetric key algorithms. Some encryption algorithms can use the key directly while others derive sub keys from this. /// If an algorithm needs to derive more keys, have a derived class from this and use it in the corresponding encryption algorithm. /// - internal class SqlClientSymmetricKey - { + internal class SqlClientSymmetricKey { /// - /// DPAPI protected key + /// The underlying key material /// protected readonly byte[] _rootKey; @@ -26,8 +25,7 @@ namespace System.Data.SqlClient /// Constructor that initializes the root key. /// /// root key - internal SqlClientSymmetricKey(byte[] rootKey) - { + internal SqlClientSymmetricKey(byte[] rootKey) { // Key validation if (rootKey == null || rootKey.Length == 0) { throw SQL.NullColumnEncryptionKeySysErr(); @@ -36,14 +34,24 @@ namespace System.Data.SqlClient _rootKey = rootKey; } + /// + /// Destructor that cleans up the key material. + /// This is a best effort approach since there are no guarantees around GC. + /// + ~SqlClientSymmetricKey() { + if (_rootKey != null) { + for (int i = 0; i < _rootKey.Length; i++) { + _rootKey[i] = 0; + } + } + } + /// /// Returns a copy of the plain text key /// This is needed for actual encryption/decryption. /// - internal virtual byte[] RootKey - { - get - { + internal virtual byte[] RootKey { + get { return _rootKey; } } @@ -52,8 +60,7 @@ namespace System.Data.SqlClient /// Computes SHA256 value of the plain text key bytes /// /// A string containing SHA256 hash of the root key - internal virtual string GetKeyHash() - { + internal virtual string GetKeyHash() { return SqlSecurityUtility.GetSHA256Hash(RootKey); } @@ -63,10 +70,7 @@ namespace System.Data.SqlClient /// /// Returns the length of the root key /// - internal virtual int Length() - { - // Note: DPAPI preserves the original byte length - // so for now, this is as same as returning the length of the raw key. + internal virtual int Length() { return _rootKey.Length; } } diff --git a/mcs/class/referencesource/System.Data/System/Data/SqlClient/SqlCommand.cs.REMOVED.git-id b/mcs/class/referencesource/System.Data/System/Data/SqlClient/SqlCommand.cs.REMOVED.git-id index cb4f707c15..770a4f1713 100644 --- a/mcs/class/referencesource/System.Data/System/Data/SqlClient/SqlCommand.cs.REMOVED.git-id +++ b/mcs/class/referencesource/System.Data/System/Data/SqlClient/SqlCommand.cs.REMOVED.git-id @@ -1 +1 @@ -2e560dbf344a2a5ef4577863f3342dc13d2498de \ No newline at end of file +46a53537089cdd872b7c8964bfc4fc8718f9c782 \ No newline at end of file diff --git a/mcs/class/referencesource/System.Data/System/Data/SqlClient/SqlConnection.cs.REMOVED.git-id b/mcs/class/referencesource/System.Data/System/Data/SqlClient/SqlConnection.cs.REMOVED.git-id index a6658837b0..b65cdf9379 100644 --- a/mcs/class/referencesource/System.Data/System/Data/SqlClient/SqlConnection.cs.REMOVED.git-id +++ b/mcs/class/referencesource/System.Data/System/Data/SqlClient/SqlConnection.cs.REMOVED.git-id @@ -1 +1 @@ -0ce4dbb08763054308721ed6139b428134b0cb54 \ No newline at end of file +306a42079800e4f74776c8f8f967a9df88f0c8f5 \ No newline at end of file diff --git a/mcs/class/referencesource/System.Data/System/Data/SqlClient/SqlConnectionString.cs b/mcs/class/referencesource/System.Data/System/Data/SqlClient/SqlConnectionString.cs index 85ed1b7bbf..1dd74aec96 100644 --- a/mcs/class/referencesource/System.Data/System/Data/SqlClient/SqlConnectionString.cs +++ b/mcs/class/referencesource/System.Data/System/Data/SqlClient/SqlConnectionString.cs @@ -30,6 +30,7 @@ namespace System.Data.SqlClient { internal const string Application_Name = TdsEnums.SQL_PROVIDER_NAME; internal const bool Asynchronous = false; internal const string AttachDBFilename = ""; + internal const PoolBlockingPeriod PoolBlockingPeriod = DbConnectionStringDefaults.PoolBlockingPeriod; internal const int Connect_Timeout = ADP.DefaultConnectionTimeout; internal const bool Connection_Reset = true; internal const bool Context_Connection = false; @@ -69,6 +70,7 @@ namespace System.Data.SqlClient { internal const string Application_Name = "application name"; internal const string AsynchronousProcessing = "asynchronous processing"; internal const string AttachDBFilename = "attachdbfilename"; + internal const string PoolBlockingPeriod = "poolblockingperiod"; internal const string ColumnEncryptionSetting = "column encryption setting"; internal const string Connect_Timeout = "connect timeout"; internal const string Connection_Reset = "connection reset"; @@ -190,6 +192,7 @@ namespace System.Data.SqlClient { private readonly bool _integratedSecurity; + private readonly PoolBlockingPeriod _poolBlockingPeriod; private readonly bool _connectionReset; private readonly bool _contextConnection; private readonly bool _encrypt; @@ -247,6 +250,7 @@ namespace System.Data.SqlClient { ConvertValueToBoolean(KEY.AsynchronousProcessing, DEFAULT.Asynchronous); // while we don't use it anymore, we still need to verify it is true/false // SQLPT 41700: Ignore ResetConnection=False (still validate the keyword/value) + _poolBlockingPeriod = ConvertValueToPoolBlockingPeriod(); _connectionReset = ConvertValueToBoolean(KEY.Connection_Reset, DEFAULT.Connection_Reset); _contextConnection = ConvertValueToBoolean(KEY.Context_Connection, DEFAULT.Context_Connection); _encrypt = ConvertValueToEncrypt(); @@ -490,6 +494,7 @@ namespace System.Data.SqlClient { _userInstance = userInstance; _connectTimeout = connectionOptions._connectTimeout; _loadBalanceTimeout = connectionOptions._loadBalanceTimeout; + _poolBlockingPeriod = connectionOptions._poolBlockingPeriod; _maxPoolSize = connectionOptions._maxPoolSize; _minPoolSize = connectionOptions._minPoolSize; _multiSubnetFailover = connectionOptions._multiSubnetFailover; @@ -525,6 +530,8 @@ namespace System.Data.SqlClient { // will work. In the future we can deprecate the keyword entirely. internal bool Asynchronous { get { return true; } } + internal PoolBlockingPeriod PoolBlockingPeriod { get { return _poolBlockingPeriod; } } + // SQLPT 41700: Ignore ResetConnection=False, always reset the connection for security internal bool ConnectionReset { get { return true; } } internal bool ContextConnection { get { return _contextConnection; } } @@ -620,6 +627,7 @@ namespace System.Data.SqlClient { hash.Add(KEY.Application_Name, KEY.Application_Name); hash.Add(KEY.AsynchronousProcessing, KEY.AsynchronousProcessing); hash.Add(KEY.AttachDBFilename, KEY.AttachDBFilename); + hash.Add(KEY.PoolBlockingPeriod, KEY.PoolBlockingPeriod); hash.Add(KEY.Connect_Timeout, KEY.Connect_Timeout); hash.Add(KEY.Connection_Reset, KEY.Connection_Reset); hash.Add(KEY.Context_Connection, KEY.Context_Connection); @@ -779,6 +787,28 @@ namespace System.Data.SqlClient { // ArgumentException and other types are raised as is (no wrapping) } + internal System.Data.SqlClient.PoolBlockingPeriod ConvertValueToPoolBlockingPeriod() + { + object value = base.Parsetable[KEY.PoolBlockingPeriod]; + if (value == null) + { + return DEFAULT.PoolBlockingPeriod; + } + + try + { + return DbConnectionStringBuilderUtil.ConvertToPoolBlockingPeriod(KEY.PoolBlockingPeriod, value); + } + catch (FormatException e) + { + throw ADP.InvalidConnectionOptionValue(KEY.PoolBlockingPeriod, e); + } + catch (OverflowException e) + { + throw ADP.InvalidConnectionOptionValue(KEY.PoolBlockingPeriod, e); + } + } + internal SqlAuthenticationMethod ConvertValueToAuthenticationType() { object value = base.Parsetable[KEY.Authentication]; diff --git a/mcs/class/referencesource/System.Data/System/Data/SqlClient/SqlConnectionStringBuilder.cs b/mcs/class/referencesource/System.Data/System/Data/SqlClient/SqlConnectionStringBuilder.cs index 8e7714341c..ae3c2b1e67 100644 --- a/mcs/class/referencesource/System.Data/System/Data/SqlClient/SqlConnectionStringBuilder.cs +++ b/mcs/class/referencesource/System.Data/System/Data/SqlClient/SqlConnectionStringBuilder.cs @@ -41,6 +41,7 @@ namespace System.Data.SqlClient { Pooling, MinPoolSize, MaxPoolSize, + PoolBlockingPeriod, AsynchronousProcessing, ConnectionReset, @@ -127,6 +128,7 @@ namespace System.Data.SqlClient { private bool _userInstance = DbConnectionStringDefaults.UserInstance; private SqlAuthenticationMethod _authentication = DbConnectionStringDefaults.Authentication; private SqlConnectionColumnEncryptionSetting _columnEncryptionSetting = DbConnectionStringDefaults.ColumnEncryptionSetting; + private PoolBlockingPeriod _poolBlockingPeriod = DbConnectionStringDefaults.PoolBlockingPeriod; static SqlConnectionStringBuilder() { string[] validKeywords = new string[KeywordsCount]; @@ -134,6 +136,7 @@ namespace System.Data.SqlClient { validKeywords[(int)Keywords.ApplicationName] = DbConnectionStringKeywords.ApplicationName; validKeywords[(int)Keywords.AsynchronousProcessing] = DbConnectionStringKeywords.AsynchronousProcessing; validKeywords[(int)Keywords.AttachDBFilename] = DbConnectionStringKeywords.AttachDBFilename; + validKeywords[(int)Keywords.PoolBlockingPeriod] = DbConnectionStringKeywords.PoolBlockingPeriod; validKeywords[(int)Keywords.ConnectionReset] = DbConnectionStringKeywords.ConnectionReset; validKeywords[(int)Keywords.ContextConnection] = DbConnectionStringKeywords.ContextConnection; validKeywords[(int)Keywords.ConnectTimeout] = DbConnectionStringKeywords.ConnectTimeout; @@ -174,6 +177,7 @@ namespace System.Data.SqlClient { hash.Add(DbConnectionStringKeywords.ApplicationName, Keywords.ApplicationName); hash.Add(DbConnectionStringKeywords.AsynchronousProcessing, Keywords.AsynchronousProcessing); hash.Add(DbConnectionStringKeywords.AttachDBFilename, Keywords.AttachDBFilename); + hash.Add(DbConnectionStringKeywords.PoolBlockingPeriod, Keywords.PoolBlockingPeriod); hash.Add(DbConnectionStringKeywords.ConnectTimeout, Keywords.ConnectTimeout); hash.Add(DbConnectionStringKeywords.ConnectionReset, Keywords.ConnectionReset); hash.Add(DbConnectionStringKeywords.ContextConnection, Keywords.ContextConnection); @@ -278,6 +282,7 @@ namespace System.Data.SqlClient { case Keywords.Authentication: Authentication = ConvertToAuthenticationType(keyword, value); break; case Keywords.ColumnEncryptionSetting: ColumnEncryptionSetting = ConvertToColumnEncryptionSetting(keyword, value); break; case Keywords.AsynchronousProcessing: AsynchronousProcessing = ConvertToBoolean(value); break; + case Keywords.PoolBlockingPeriod: PoolBlockingPeriod = ConvertToPoolBlockingPeriod(keyword, value); break; #pragma warning disable 618 // Obsolete ConnectionReset case Keywords.ConnectionReset: ConnectionReset = ConvertToBoolean(value); break; #pragma warning restore 618 @@ -360,6 +365,25 @@ namespace System.Data.SqlClient { } } + [DisplayName(DbConnectionStringKeywords.PoolBlockingPeriod)] + [ResCategoryAttribute(Res.DataCategory_Pooling)] + [ResDescriptionAttribute(Res.DbConnectionString_PoolBlockingPeriod)] + [RefreshPropertiesAttribute(RefreshProperties.All)] + public PoolBlockingPeriod PoolBlockingPeriod + { + get { return _poolBlockingPeriod; } + set + { + if (!DbConnectionStringBuilderUtil.IsValidPoolBlockingPeriodValue(value)) + { + throw ADP.InvalidEnumerationValue(typeof(PoolBlockingPeriod), (int)value); + } + + SetPoolBlockingPeriodValue(value); + _poolBlockingPeriod = value; + } + } + [Browsable(false)] [DisplayName(DbConnectionStringKeywords.ConnectionReset)] [Obsolete("ConnectionReset has been deprecated. SqlConnection will ignore the 'connection reset' keyword and always reset the connection")] // SQLPT 41700 @@ -881,6 +905,10 @@ namespace System.Data.SqlClient { private static SqlAuthenticationMethod ConvertToAuthenticationType(string keyword, object value) { return DbConnectionStringBuilderUtil.ConvertToAuthenticationType(keyword, value); } + private static PoolBlockingPeriod ConvertToPoolBlockingPeriod(string keyword, object value) + { + return DbConnectionStringBuilderUtil.ConvertToPoolBlockingPeriod(keyword, value); + } /// /// Convert to SqlConnectionColumnEncryptionSetting. @@ -906,6 +934,7 @@ namespace System.Data.SqlClient { case Keywords.ApplicationName: return ApplicationName; case Keywords.AsynchronousProcessing: return AsynchronousProcessing; case Keywords.AttachDBFilename: return AttachDBFilename; + case Keywords.PoolBlockingPeriod: return PoolBlockingPeriod; case Keywords.ConnectTimeout: return ConnectTimeout; #pragma warning disable 618 // Obsolete ConnectionReset case Keywords.ConnectionReset: return ConnectionReset; @@ -1012,6 +1041,10 @@ namespace System.Data.SqlClient { case Keywords.Authentication: _authentication = DbConnectionStringDefaults.Authentication; break; + case Keywords.PoolBlockingPeriod: + _poolBlockingPeriod = DbConnectionStringDefaults.PoolBlockingPeriod; + break; + case Keywords.ConnectTimeout: _connectTimeout = DbConnectionStringDefaults.ConnectTimeout; break; @@ -1128,6 +1161,11 @@ namespace System.Data.SqlClient { Debug.Assert(DbConnectionStringBuilderUtil.IsValidApplicationIntentValue(value), "Invalid value for ApplicationIntent"); base[DbConnectionStringKeywords.ApplicationIntent] = DbConnectionStringBuilderUtil.ApplicationIntentToString(value); } + private void SetPoolBlockingPeriodValue(PoolBlockingPeriod value) + { + Debug.Assert(DbConnectionStringBuilderUtil.IsValidPoolBlockingPeriodValue(value), "Invalid value for PoolBlockingPeriod"); + base[DbConnectionStringKeywords.PoolBlockingPeriod] = DbConnectionStringBuilderUtil.PoolBlockingPeriodToString(value); + } private void SetAuthenticationValue(SqlAuthenticationMethod value) { Debug.Assert(DbConnectionStringBuilderUtil.IsValidAuthenticationTypeValue(value), "Invalid value for AuthenticationType"); base[DbConnectionStringKeywords.Authentication] = DbConnectionStringBuilderUtil.AuthenticationTypeToString(value); diff --git a/mcs/class/referencesource/System.Data/System/Data/SqlClient/SqlConnectionTimeoutErrorInternal.cs b/mcs/class/referencesource/System.Data/System/Data/SqlClient/SqlConnectionTimeoutErrorInternal.cs index 879a86d61a..0e799476ba 100644 --- a/mcs/class/referencesource/System.Data/System/Data/SqlClient/SqlConnectionTimeoutErrorInternal.cs +++ b/mcs/class/referencesource/System.Data/System/Data/SqlClient/SqlConnectionTimeoutErrorInternal.cs @@ -207,10 +207,10 @@ namespace System.Data.SqlClient durationString = null; break; } - + // This message is to be added only when within the various stages of a connection. // In all other cases, it will default to the original error message. - if ((currentPhase != SqlConnectionTimeoutErrorPhase.Undefined) || (currentPhase != SqlConnectionTimeoutErrorPhase.Complete)) + if ((currentPhase != SqlConnectionTimeoutErrorPhase.Undefined) && (currentPhase != SqlConnectionTimeoutErrorPhase.Complete)) { // NOTE: In case of a failover scenario, add a string that this failure occured as part of the primary or secondary server if (isFailoverScenario) @@ -229,13 +229,13 @@ namespace System.Data.SqlClient originalPhaseDurations[(int)SqlConnectionTimeoutErrorPhase.ProcessConnectionAuth].GetMilliSecondDuration(), originalPhaseDurations[(int)SqlConnectionTimeoutErrorPhase.PostLogin].GetMilliSecondDuration()); } + } - // NOTE: To display duration in each phase. - if (durationString != null) - { - errorBuilder.Append(" "); - errorBuilder.Append(durationString); - } + // NOTE: To display duration in each phase. + if (durationString != null) + { + errorBuilder.Append(" "); + errorBuilder.Append(durationString); } return errorBuilder.ToString(); diff --git a/mcs/class/referencesource/System.Data/System/Data/SqlClient/SqlInternalConnectionTds.cs.REMOVED.git-id b/mcs/class/referencesource/System.Data/System/Data/SqlClient/SqlInternalConnectionTds.cs.REMOVED.git-id index 760d57829a..ac1aeb10c0 100644 --- a/mcs/class/referencesource/System.Data/System/Data/SqlClient/SqlInternalConnectionTds.cs.REMOVED.git-id +++ b/mcs/class/referencesource/System.Data/System/Data/SqlClient/SqlInternalConnectionTds.cs.REMOVED.git-id @@ -1 +1 @@ -c07b195ac1ba68e64a6342f0c03bbc6e4bc32456 \ No newline at end of file +376909b9abd7bd6b626018dfbe5b83b5a12940c2 \ No newline at end of file diff --git a/mcs/class/referencesource/System.Data/System/Data/SqlClient/SqlParameter.cs b/mcs/class/referencesource/System.Data/System/Data/SqlClient/SqlParameter.cs index 9b238a4706..81274a6b84 100644 --- a/mcs/class/referencesource/System.Data/System/Data/SqlClient/SqlParameter.cs +++ b/mcs/class/referencesource/System.Data/System/Data/SqlClient/SqlParameter.cs @@ -99,9 +99,6 @@ namespace System.Data.SqlClient { } set { - Debug.Assert(_columnEncryptionCipherMetadata == null || value == null, - "_columnEncryptionCipherMetadata should be set to a non-null value only once."); - _columnEncryptionCipherMetadata = value; } } diff --git a/mcs/class/referencesource/System.Data/System/Data/SqlClient/SqlSymmetricKeyCache.cs b/mcs/class/referencesource/System.Data/System/Data/SqlClient/SqlSymmetricKeyCache.cs index fa371fb722..8df0617428 100644 --- a/mcs/class/referencesource/System.Data/System/Data/SqlClient/SqlSymmetricKeyCache.cs +++ b/mcs/class/referencesource/System.Data/System/Data/SqlClient/SqlSymmetricKeyCache.cs @@ -13,18 +13,19 @@ namespace System.Data.SqlClient { using System.Diagnostics; using System.Globalization; using System.Linq; + using System.Runtime.Caching; using System.Text; /// /// Implements a cache of Symmetric Keys (once they are decrypted).Useful for rapidly decrypting multiple data values. /// sealed internal class SqlSymmetricKeyCache { - private readonly ConcurrentDictionary _cache; + private readonly MemoryCache _cache; private static readonly SqlSymmetricKeyCache _singletonInstance = new SqlSymmetricKeyCache(); private SqlSymmetricKeyCache () { - _cache = new ConcurrentDictionary(concurrencyLevel: 4 * Environment.ProcessorCount /* default value in ConcurrentDictionary*/, capacity: 2); + _cache = new MemoryCache("ColumnEncryptionKeyCache"); } internal static SqlSymmetricKeyCache GetInstance () { @@ -54,10 +55,10 @@ namespace System.Data.SqlClient { Debug.Assert(cacheLookupKey.Length <= capacity, "We needed to allocate a larger array"); #endif //DEBUG - encryptionKey = null; - // Lookup the key in cache - if (!_cache.TryGetValue(cacheLookupKey, out encryptionKey)) { + encryptionKey = _cache.Get(cacheLookupKey) as SqlClientSymmetricKey; + + if (encryptionKey == null) { Debug.Assert(SqlConnection.ColumnEncryptionTrustedMasterKeyPaths != null, @"SqlConnection.ColumnEncryptionTrustedMasterKeyPaths should not be null"); // Check against the trusted key paths @@ -96,9 +97,13 @@ namespace System.Data.SqlClient { encryptionKey = new SqlClientSymmetricKey (plaintextKey); - // In case multiple threads reach here at the same time, the first one wins. - // The allocated memory will be reclaimed by Garbage Collector. - _cache.TryAdd(cacheLookupKey, encryptionKey); + // If the cache TTL is zero, don't even bother inserting to the cache. + if (SqlConnection.ColumnEncryptionKeyCacheTtl != TimeSpan.Zero) { + // In case multiple threads reach here at the same time, the first one wins. + // The allocated memory will be reclaimed by Garbage Collector. + DateTimeOffset expirationTime = DateTimeOffset.UtcNow.Add(SqlConnection.ColumnEncryptionKeyCacheTtl); + _cache.Add(cacheLookupKey, encryptionKey, expirationTime); + } } return true; diff --git a/mcs/class/referencesource/System.Data/System/Data/SqlClient/SqlUtil.cs b/mcs/class/referencesource/System.Data/System/Data/SqlClient/SqlUtil.cs index ae7086f0a0..a15b189376 100644 --- a/mcs/class/referencesource/System.Data/System/Data/SqlClient/SqlUtil.cs +++ b/mcs/class/referencesource/System.Data/System/Data/SqlClient/SqlUtil.cs @@ -1543,7 +1543,7 @@ namespace System.Data.SqlClient { return Res.GetString(Res.SQL_SSPIGenerateError); } static internal string Timeout() { - return Res.GetString(Res.SQL_Timeout); + return Res.GetString(Res.SQL_Timeout_Execution); } static internal string Timeout_PreLogin_Begin() { return Res.GetString(Res.SQL_Timeout_PreLogin_Begin); diff --git a/mcs/class/referencesource/System.Data/System/Data/SqlClient/TdsEnums.cs b/mcs/class/referencesource/System.Data/System/Data/SqlClient/TdsEnums.cs index 319e252b21..11e3cdd98e 100644 --- a/mcs/class/referencesource/System.Data/System/Data/SqlClient/TdsEnums.cs +++ b/mcs/class/referencesource/System.Data/System/Data/SqlClient/TdsEnums.cs @@ -544,6 +544,9 @@ namespace System.Data.SqlClient { public const int IMPERSONATION_FAILED = 1346; public const int P_TOKENTOOLONG = 103; + // SQL error that indicates retry for Always Encrypted + public const int TCE_CONVERSION_ERROR_CLIENT_RETRY = 33514; + // SNI\Win32 error values // NOTE: these are simply windows system error codes, not SNI specific public const uint SNI_UNINITIALIZED = unchecked((uint)-1); diff --git a/mcs/class/referencesource/System.Data/System/NewXml/XPathNodePointer.cs b/mcs/class/referencesource/System.Data/System/NewXml/XPathNodePointer.cs index f8f3d1d95c..1af6e149ac 100644 --- a/mcs/class/referencesource/System.Data/System/NewXml/XPathNodePointer.cs +++ b/mcs/class/referencesource/System.Data/System/NewXml/XPathNodePointer.cs @@ -883,7 +883,6 @@ namespace System.Xml { RealFoliate(); AssertValid(); if ( NodeType == XPathNodeType.Namespace ) { - Debug.Assert( _parentOfNS != null ); MoveTo( _parentOfNS ); return true; } diff --git a/mcs/class/referencesource/System.IdentityModel/InternalApis/Clr/inc/AppContextDefaultValues.cs b/mcs/class/referencesource/System.IdentityModel/InternalApis/Clr/inc/AppContextDefaultValues.cs index 8a130a0f34..9224bf8b8f 100644 --- a/mcs/class/referencesource/System.IdentityModel/InternalApis/Clr/inc/AppContextDefaultValues.cs +++ b/mcs/class/referencesource/System.IdentityModel/InternalApis/Clr/inc/AppContextDefaultValues.cs @@ -3,6 +3,15 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== + +// There are cases where we have multiple assemblies that are going to import this file and +// if they are going to also have InternalsVisibleTo between them, there will be a compiler warning +// that the type is found both in the source and in a referenced assembly. The compiler will prefer +// the version of the type defined in the source +// +// In order to disable the warning for this type we are disabling this warning for this entire file. +#pragma warning disable 436 + using System; using System.Collections.Generic; @@ -167,3 +176,5 @@ namespace System static partial void PopulateDefaultValuesPartial(string platformIdentifier, string profile, int version); } } + +#pragma warning restore 436 diff --git a/mcs/class/referencesource/System.IdentityModel/InternalApis/Clr/inc/LocalAppContext.cs b/mcs/class/referencesource/System.IdentityModel/InternalApis/Clr/inc/LocalAppContext.cs index f05b599ed3..33662b5428 100644 --- a/mcs/class/referencesource/System.IdentityModel/InternalApis/Clr/inc/LocalAppContext.cs +++ b/mcs/class/referencesource/System.IdentityModel/InternalApis/Clr/inc/LocalAppContext.cs @@ -4,6 +4,14 @@ // // ==--== +// There are cases where we have multiple assemblies that are going to import this file and +// if they are going to also have InternalsVisibleTo between them, there will be a compiler warning +// that the type is found both in the source and in a referenced assembly. The compiler will prefer +// the version of the type defined in the source +// +// In order to disable the warning for this type we are disabling this warning for this entire file. +#pragma warning disable 436 + // NOTE: This file should not be included in mscorlib. This should only be included in FX libraries that need to provide switches using System; using System.Collections.Generic; @@ -126,3 +134,5 @@ namespace System } } } + +#pragma warning restore 436 diff --git a/mcs/class/referencesource/System.IdentityModel/System/IdentityModel/Claims/X509CertificateClaimSet.cs b/mcs/class/referencesource/System.IdentityModel/System/IdentityModel/Claims/X509CertificateClaimSet.cs index 4113bd328c..7561fffb97 100644 --- a/mcs/class/referencesource/System.IdentityModel/System/IdentityModel/Claims/X509CertificateClaimSet.cs +++ b/mcs/class/referencesource/System.IdentityModel/System/IdentityModel/Claims/X509CertificateClaimSet.cs @@ -5,12 +5,14 @@ namespace System.IdentityModel.Claims { using System.Collections.Generic; + using System.Diagnostics; using System.IdentityModel.Policy; using System.Net.Mail; using System.Security.Claims; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using System.Security.Principal; + using Globalization; public class X509CertificateClaimSet : ClaimSet, IIdentityInfo, IDisposable { @@ -172,24 +174,7 @@ namespace System.IdentityModel.Claims if (!string.IsNullOrEmpty(value)) claims.Add(Claim.CreateX500DistinguishedNameClaim(this.certificate.SubjectName)); - // App context switch for disabling support for multiple dns entries in a SAN certificate - if (LocalAppContextSwitches.DisableMultipleDNSEntriesInSANCertificate) - { - // old behavior, default for <= 4.6 - value = this.certificate.GetNameInfo(X509NameType.DnsName, false); - if (!string.IsNullOrEmpty(value)) - claims.Add(Claim.CreateDnsClaim(value)); - } - else - { - // new behavior as this is the default long term behavior - // Since a SAN can have multiple DNS entries - string[] entries = GetDnsFromExtensions(this.certificate); - for (int i = 0; i < entries.Length; ++i) - { - claims.Add(Claim.CreateDnsClaim(entries[i])); - } - } + claims.AddRange(GetDnsClaims(this.certificate)); value = this.certificate.GetNameInfo(X509NameType.SimpleName, false); if (!string.IsNullOrEmpty(value)) @@ -258,25 +243,8 @@ namespace System.IdentityModel.Claims { if (right == null || Rights.PossessProperty.Equals(right)) { - // App context switch for disabling support for multiple dns entries in a SAN certificate - if (LocalAppContextSwitches.DisableMultipleDNSEntriesInSANCertificate) - { - // old behavior, default for <= 4.6 - string value = this.certificate.GetNameInfo(X509NameType.DnsName, false); - if (!string.IsNullOrEmpty(value)) - { - yield return Claim.CreateDnsClaim(value); - } - } - else - { - // new behavior since this is the default long term behavior - string[] entries = GetDnsFromExtensions(certificate); - for (int i = 0; i < entries.Length; ++i) - { - yield return Claim.CreateDnsClaim(entries[i]); - } - } + foreach (var claim in GetDnsClaims(certificate)) + yield return claim; } } else @@ -299,31 +267,44 @@ namespace System.IdentityModel.Claims } } - // Fixing Bug 795660: SAN having multiple DNS entries - private static string[] GetDnsFromExtensions(X509Certificate2 cert) + private static List GetDnsClaims(X509Certificate2 cert) { - foreach (X509Extension ext in cert.Extensions) - { - // Extension is SAN or SAN2 - if (ext.Oid.Value == "2.5.29.7" || ext.Oid.Value == "2.5.29.17") - { - string asnString = ext.Format(true); - if (string.IsNullOrEmpty(asnString)) - { - return new string[0]; - } + List dnsClaimEntries = new List(); - string[] rawDnsEntries = asnString.Split(new string[1] { "\n" }, StringSplitOptions.RemoveEmptyEntries); - string[] dnsEntries = new string[rawDnsEntries.Length]; - for (int i = 0; i < rawDnsEntries.Length; ++i) + // old behavior, default for <= 4.6 + string value = cert.GetNameInfo(X509NameType.DnsName, false); + if (!string.IsNullOrEmpty(value)) + dnsClaimEntries.Add(Claim.CreateDnsClaim(value)); + + // App context switch for disabling support for multiple dns entries in a SAN certificate + // If we can't dynamically parse the alt subject names, we will not add any dns claims ONLY for the alt subject names. + // In this way, if the X509NameType.DnsName was enough to succeed for the out-bound-message. We would have a success. + if (!LocalAppContextSwitches.DisableMultipleDNSEntriesInSANCertificate && X509SubjectAlternativeNameConstants.SuccessfullyInitialized) + { + foreach (X509Extension ext in cert.Extensions) + { + // Extension is SAN or SAN2 + if (ext.Oid.Value == X509SubjectAlternativeNameConstants.SanOid || ext.Oid.Value == X509SubjectAlternativeNameConstants.San2Oid) { - int equalSignIndex = rawDnsEntries[i].IndexOf('='); - dnsEntries[i] = rawDnsEntries[i].Substring(equalSignIndex + 1).Trim(); + string asnString = ext.Format(false); + if (string.IsNullOrWhiteSpace(asnString)) + break; + + // SubjectAlternativeNames might contain something other than a dNSName, + // so we have to parse through and only use the dNSNames + // + string[] rawDnsEntries = asnString.Split(X509SubjectAlternativeNameConstants.SeparatorArray, StringSplitOptions.RemoveEmptyEntries); + for (int i = 0; i < rawDnsEntries.Length; i++) + { + string[] keyval = rawDnsEntries[i].Split(X509SubjectAlternativeNameConstants.Delimiter); + if (string.Equals(keyval[0], X509SubjectAlternativeNameConstants.Identifier)) + dnsClaimEntries.Add(Claim.CreateDnsClaim(keyval[1])); + } } - return dnsEntries; } } - return new string[0]; + + return dnsClaimEntries; } public override IEnumerator GetEnumerator() @@ -367,6 +348,107 @@ namespace System.IdentityModel.Claims get { return this.identity; } } } + + // We don't have a strongly typed extension to parse Subject Alt Names, so we have to do a workaround + // to figure out what the identifier, delimiter, and separator is by using a well-known extension + private static class X509SubjectAlternativeNameConstants + { + public const string SanOid = "2.5.29.7"; + public const string San2Oid = "2.5.29.17"; + + public static string Identifier + { + get; + private set; + } + + public static char Delimiter + { + get; + private set; + } + + public static string Separator + { + get; + private set; + } + + public static string[] SeparatorArray + { + get; + private set; + } + + public static bool SuccessfullyInitialized + { + get; + private set; + } + + // static initializer will run before properties are accessed + static X509SubjectAlternativeNameConstants() + { + // Extracted a well-known X509Extension + byte[] x509ExtensionBytes = new byte[] { + 48, 36, 130, 21, 110, 111, 116, 45, 114, 101, 97, 108, 45, 115, 117, 98, 106, 101, 99, + 116, 45, 110, 97, 109, 101, 130, 11, 101, 120, 97, 109, 112, 108, 101, 46, 99, 111, 109 + }; + const string subjectName = "not-real-subject-name"; + string x509ExtensionFormattedString = string.Empty; + try + { + X509Extension x509Extension = new X509Extension(SanOid, x509ExtensionBytes, true); + x509ExtensionFormattedString = x509Extension.Format(false); + + // Each OS has a different dNSName identifier and delimiter + // On Windows, dNSName == "DNS Name" (localizable), on Linux, dNSName == "DNS" + // e.g., + // Windows: x509ExtensionFormattedString is: "DNS Name=not-real-subject-name, DNS Name=example.com" + // Linux: x509ExtensionFormattedString is: "DNS:not-real-subject-name, DNS:example.com" + // Parse: + + int delimiterIndex = x509ExtensionFormattedString.IndexOf(subjectName) - 1; + Delimiter = x509ExtensionFormattedString[delimiterIndex]; + + // Make an assumption that all characters from the the start of string to the delimiter + // are part of the identifier + Identifier = x509ExtensionFormattedString.Substring(0, delimiterIndex); + + int separatorFirstChar = delimiterIndex + subjectName.Length + 1; + int separatorLength = 1; + for (int i = separatorFirstChar + 1; i < x509ExtensionFormattedString.Length; i++) + { + // We advance until the first character of the identifier to determine what the + // separator is. This assumes that the identifier assumption above is correct + if (x509ExtensionFormattedString[i] == Identifier[0]) + { + break; + } + + separatorLength++; + } + + Separator = x509ExtensionFormattedString.Substring(separatorFirstChar, separatorLength); + SeparatorArray = new string[1] { Separator }; + SuccessfullyInitialized = true; + } + catch (Exception ex) + { + SuccessfullyInitialized = false; + DiagnosticUtility.TraceHandledException( + new FormatException(string.Format(CultureInfo.InvariantCulture, + "There was an error parsing the SubjectAlternativeNames: '{0}'. See inner exception for more details.{1}Detected values were: Identifier: '{2}'; Delimiter:'{3}'; Separator:'{4}'", + x509ExtensionFormattedString, + Environment.NewLine, + Identifier, + Delimiter, + Separator), + ex), + TraceEventType.Warning); + } + } + } } class X509Identity : GenericIdentity, IDisposable diff --git a/mcs/class/referencesource/System.IdentityModel/System/IdentityModel/LocalAppContextSwitches.cs b/mcs/class/referencesource/System.IdentityModel/System/IdentityModel/LocalAppContextSwitches.cs index f18ab5dd58..b6bc822248 100644 --- a/mcs/class/referencesource/System.IdentityModel/System/IdentityModel/LocalAppContextSwitches.cs +++ b/mcs/class/referencesource/System.IdentityModel/System/IdentityModel/LocalAppContextSwitches.cs @@ -15,9 +15,11 @@ namespace System.IdentityModel { private const string EnableCachedEmptyDefaultAuthorizationContextString = "Switch.System.IdentityModel.EnableCachedEmptyDefaultAuthorizationContext"; private const string DisableMultipleDNSEntriesInSANCertificateString = "Switch.System.IdentityModel.DisableMultipleDNSEntriesInSANCertificate"; + private const string DisableUpdatingRsaProviderTypeString = "Switch.System.IdentityModel.DisableUpdatingRsaProviderType"; private static int enableCachedEmptyDefaultAuthorizationContext; private static int disableMultipleDNSEntriesInSANCertificate; + private static int disableUpdatingRsaProviderType; public static bool EnableCachedEmptyDefaultAuthorizationContext { @@ -37,16 +39,29 @@ namespace System.IdentityModel } } + public static bool DisableUpdatingRsaProviderType + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return LocalAppContext.GetCachedSwitchValue(DisableUpdatingRsaProviderTypeString, ref disableUpdatingRsaProviderType); + } + } + public static void SetDefaultsLessOrEqual_452() { +#pragma warning disable BCL0012 // Define the switches that should be true for 4.5.2 or less, false for 4.6+. LocalAppContext.DefineSwitchDefault(EnableCachedEmptyDefaultAuthorizationContextString, true); +#pragma warning restore BCL0012 } public static void SetDefaultsLessOrEqual_46() { +#pragma warning disable BCL0012 // Define the switches that should be true for 4.6 or less, false for 4.6.1+. LocalAppContext.DefineSwitchDefault(DisableMultipleDNSEntriesInSANCertificateString, true); +#pragma warning restore BCL0012 } } } diff --git a/mcs/class/referencesource/System.IdentityModel/System/IdentityModel/Tokens/X509AsymmetricSecurityKey.cs b/mcs/class/referencesource/System.IdentityModel/System/IdentityModel/Tokens/X509AsymmetricSecurityKey.cs index 397194f644..fb1918c6ca 100644 --- a/mcs/class/referencesource/System.IdentityModel/System/IdentityModel/Tokens/X509AsymmetricSecurityKey.cs +++ b/mcs/class/referencesource/System.IdentityModel/System/IdentityModel/Tokens/X509AsymmetricSecurityKey.cs @@ -309,22 +309,26 @@ namespace System.IdentityModel.Tokens { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(algorithm, SR.GetString(SR.EmptyOrNullArgumentString, "algorithm")); } - // We support one of the two algoritms, but not both. + + // We support: // XmlDsigDSAUrl = "http://www.w3.org/2000/09/xmldsig#dsa-sha1"; // XmlDsigRSASHA1Url = "http://www.w3.org/2000/09/xmldsig#rsa-sha1"; + // RsaSha256Signature = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"; + AsymmetricAlgorithm privateKey = LevelUpRsa(this.PrivateKey, algorithm); + object algorithmObject = CryptoHelper.GetAlgorithmFromConfig(algorithm); if (algorithmObject != null) { SignatureDescription description = algorithmObject as SignatureDescription; if (description != null) - return description.CreateFormatter(this.PrivateKey); + return description.CreateFormatter(privateKey); try { AsymmetricSignatureFormatter asymmetricSignatureFormatter = algorithmObject as AsymmetricSignatureFormatter; if (asymmetricSignatureFormatter != null) { - asymmetricSignatureFormatter.SetKey(this.PrivateKey); + asymmetricSignatureFormatter.SetKey(privateKey); return asymmetricSignatureFormatter; } } @@ -356,19 +360,10 @@ namespace System.IdentityModel.Tokens case SecurityAlgorithms.RsaSha256Signature: // Ensure that we have an RSA algorithm object. - RSACryptoServiceProvider rsa_prov_full = (this.PrivateKey as RSACryptoServiceProvider); - if (rsa_prov_full == null) + RSA rsaSha256 = (privateKey as RSA); + if (rsaSha256 == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.PrivateKeyNotRSA))); - CspParameters csp = new CspParameters(); - csp.ProviderType = 24; - csp.KeyContainerName = rsa_prov_full.CspKeyContainerInfo.KeyContainerName; - csp.KeyNumber = (int)rsa_prov_full.CspKeyContainerInfo.KeyNumber; - if (rsa_prov_full.CspKeyContainerInfo.MachineKeyStore) - csp.Flags = CspProviderFlags.UseMachineKeyStore; - - csp.Flags |= CspProviderFlags.UseExistingKey; - - return new RSAPKCS1SignatureFormatter(new RSACryptoServiceProvider(csp)); + return new RSAPKCS1SignatureFormatter(rsaSha256); default: throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.UnsupportedCryptoAlgorithm, algorithm))); @@ -376,6 +371,45 @@ namespace System.IdentityModel.Tokens } + private static AsymmetricAlgorithm LevelUpRsa(AsymmetricAlgorithm asymmetricAlgorithm, string algorithm) + { + // If user turned off leveling up at app level, return + if (LocalAppContextSwitches.DisableUpdatingRsaProviderType) + return asymmetricAlgorithm; + + if (asymmetricAlgorithm == null) + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("asymmetricAlgorithm")); + + if (string.IsNullOrEmpty(algorithm)) + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(algorithm, SR.GetString(SR.EmptyOrNullArgumentString, "algorithm")); + + // only level up if alg is sha256 + if (!string.Equals(algorithm, SecurityAlgorithms.RsaSha256Signature)) + return asymmetricAlgorithm; + + RSACryptoServiceProvider rsaCsp = asymmetricAlgorithm as RSACryptoServiceProvider; + if (rsaCsp == null) + return asymmetricAlgorithm; + + // ProviderType == 1(PROV_RSA_FULL) and providerType == 12(PROV_RSA_SCHANNEL) are provider types that only support SHA1. Change them to PROV_RSA_AES=24 that supports SHA2 also. + // Only levels up if the associated key is not a hardware key. + // Another provider type related to rsa, PROV_RSA_SIG == 2 that only supports Sha1 is no longer supported + if ((rsaCsp.CspKeyContainerInfo.ProviderType == 1 || rsaCsp.CspKeyContainerInfo.ProviderType == 12) && !rsaCsp.CspKeyContainerInfo.HardwareDevice) + { + CspParameters csp = new CspParameters(); + csp.ProviderType = 24; + csp.KeyContainerName = rsaCsp.CspKeyContainerInfo.KeyContainerName; + csp.KeyNumber = (int)rsaCsp.CspKeyContainerInfo.KeyNumber; + if (rsaCsp.CspKeyContainerInfo.MachineKeyStore) + csp.Flags = CspProviderFlags.UseMachineKeyStore; + + csp.Flags |= CspProviderFlags.UseExistingKey; + return new RSACryptoServiceProvider(csp); + } + + return rsaCsp; + } + public override bool HasPrivateKey() { return (this.PrivateKey != null); diff --git a/mcs/class/referencesource/System.Runtime.Caching/System/Caching/CacheMemoryMonitor.cs b/mcs/class/referencesource/System.Runtime.Caching/System/Caching/CacheMemoryMonitor.cs index 8b32bedf74..05af143599 100644 --- a/mcs/class/referencesource/System.Runtime.Caching/System/Caching/CacheMemoryMonitor.cs +++ b/mcs/class/referencesource/System.Runtime.Caching/System/Caching/CacheMemoryMonitor.cs @@ -27,7 +27,7 @@ namespace System.Runtime.Caching { private long[] _cacheSizeSamples; private DateTime[] _cacheSizeSampleTimes; private int _idx; - private SRef _sizedRef; + private SRefMultiple _sizedRefMultiple; private int _gen2Count; private long _memoryLimit; @@ -51,7 +51,7 @@ namespace System.Runtime.Caching { private void InitDisposableMembers(int cacheMemoryLimitMegabytes) { bool dispose = true; try { - _sizedRef = new SRef(_memoryCache); + _sizedRefMultiple = new SRefMultiple(_memoryCache.AllSRefTargets); SetLimit(cacheMemoryLimitMegabytes); InitHistory(); dispose = false; @@ -112,8 +112,8 @@ namespace System.Runtime.Caching { } public void Dispose() { - SRef sref = _sizedRef; - if (sref != null && Interlocked.CompareExchange(ref _sizedRef, null, sref) == sref) { + SRefMultiple sref = _sizedRefMultiple; + if (sref != null && Interlocked.CompareExchange(ref _sizedRefMultiple, null, sref) == sref) { sref.Dispose(); } IMemoryCacheManager memoryCacheManager = s_memoryCacheManager; @@ -139,7 +139,7 @@ namespace System.Runtime.Caching { // This update must happen, otherwise the CacheManager won't // know the total cache size. int gen2Count = GC.CollectionCount(2); - SRef sref = _sizedRef; + SRefMultiple sref = _sizedRefMultiple; if (gen2Count != _gen2Count && sref != null) { // update _gen2Count _gen2Count = gen2Count; diff --git a/mcs/class/referencesource/System.Runtime.Caching/System/Caching/MemoryCache.cs b/mcs/class/referencesource/System.Runtime.Caching/System/Caching/MemoryCache.cs index 816319755c..f74996a20e 100644 --- a/mcs/class/referencesource/System.Runtime.Caching/System/Caching/MemoryCache.cs +++ b/mcs/class/referencesource/System.Runtime.Caching/System/Caching/MemoryCache.cs @@ -27,9 +27,8 @@ namespace System.Runtime.Caching { private static object s_initLock = new object(); private static MemoryCache s_defaultCache; private static CacheEntryRemovedCallback s_sentinelRemovedCallback = new CacheEntryRemovedCallback(SentinelEntry.OnCacheEntryRemovedCallback); - private MemoryCacheStore[] _stores; + private GCHandleRef[] _storeRefs; private int _storeCount; - private int _storeMask; private int _disposed; private MemoryCacheStatistics _stats; private string _name; @@ -150,8 +149,18 @@ namespace System.Runtime.Caching { if (hashCode < 0) { hashCode = (hashCode == Int32.MinValue) ? 0 : -hashCode; } - int idx = hashCode & _storeMask; - return _stores[idx]; + int idx = hashCode % _storeCount; + return _storeRefs[idx].Target; + } + + internal object[] AllSRefTargets { + get { + var allStores = new MemoryCacheStore[_storeCount]; + for (int i = 0; i < _storeCount; i++) { + allStores[i] = _storeRefs[i].Target; + } + return allStores; + } } [SecuritySafeCritical] @@ -166,8 +175,8 @@ namespace System.Runtime.Caching { catch { // ignore exceptions from perf counters } - for (int i = 0; i < _stores.Length; i++) { - _stores[i] = new MemoryCacheStore(this, _perfCounters); + for (int i = 0; i < _storeCount; i++) { + _storeRefs[i] = new GCHandleRef (new MemoryCacheStore(this, _perfCounters)); } _stats = new MemoryCacheStatistics(this, config); AppDomain appDomain = Thread.GetDomain(); @@ -321,8 +330,7 @@ namespace System.Runtime.Caching { } } #endif - _storeMask = _storeCount - 1; - _stores = new MemoryCacheStore[_storeCount]; + _storeRefs = new GCHandleRef[_storeCount]; InitDisposableMembers(config); } @@ -392,10 +400,10 @@ namespace System.Runtime.Caching { if (_stats != null) { _stats.Dispose(); } - if (_stores != null) { - foreach (MemoryCacheStore store in _stores) { - if (store != null) { - store.Dispose(); + if (_storeRefs != null) { + foreach (var storeRef in _storeRefs) { + if (storeRef != null) { + storeRef.Dispose(); } } } @@ -442,8 +450,8 @@ namespace System.Runtime.Caching { IEnumerator IEnumerable.GetEnumerator() { Hashtable h = new Hashtable(); if (!IsDisposed) { - foreach (MemoryCacheStore store in _stores) { - store.CopyTo(h); + foreach (var storeRef in _storeRefs) { + storeRef.Target.CopyTo(h); } } return h.GetEnumerator(); @@ -452,8 +460,8 @@ namespace System.Runtime.Caching { protected override IEnumerator> GetEnumerator() { Dictionary h = new Dictionary(); if (!IsDisposed) { - foreach (MemoryCacheStore store in _stores) { - store.CopyTo(h); + foreach (var storeRef in _storeRefs) { + storeRef.Target.CopyTo(h); } } return h.GetEnumerator(); @@ -471,8 +479,8 @@ namespace System.Runtime.Caching { } long trimmed = 0; if (_disposed == 0) { - foreach (MemoryCacheStore store in _stores) { - trimmed += store.TrimInternal(percent); + foreach (var storeRef in _storeRefs) { + trimmed += storeRef.Target.TrimInternal(percent); } } return trimmed; @@ -680,8 +688,8 @@ namespace System.Runtime.Caching { } long count = 0; if (!IsDisposed) { - foreach (MemoryCacheStore store in _stores) { - count += store.Count; + foreach (var storeRef in _storeRefs) { + count += storeRef.Target.Count; } } return count; diff --git a/mcs/class/referencesource/System.Runtime.Caching/System/Caching/MemoryCacheStatistics.cs b/mcs/class/referencesource/System.Runtime.Caching/System/Caching/MemoryCacheStatistics.cs index 61d3ce3ace..99196c05f5 100644 --- a/mcs/class/referencesource/System.Runtime.Caching/System/Caching/MemoryCacheStatistics.cs +++ b/mcs/class/referencesource/System.Runtime.Caching/System/Caching/MemoryCacheStatistics.cs @@ -27,7 +27,7 @@ namespace System.Runtime.Caching { private int _lastTrimPercent; private DateTime _lastTrimTime; private int _pollingInterval; - private Timer _timer; + private GCHandleRef _timerHandleRef; private Object _timerLock; private long _totalCountBeforeTrim; @@ -44,16 +44,18 @@ namespace System.Runtime.Caching { private void AdjustTimer() { lock (_timerLock) { - if (_timer == null) + if (_timerHandleRef == null) return; + Timer timer = _timerHandleRef.Target; + // the order of these if statements is important // When above the high pressure mark, interval should be 5 seconds or less if (_physicalMemoryMonitor.IsAboveHighPressure() || _cacheMemoryMonitor.IsAboveHighPressure()) { if (_pollingInterval > MEMORYSTATUS_INTERVAL_5_SECONDS) { _pollingInterval = MEMORYSTATUS_INTERVAL_5_SECONDS; - _timer.Change(_pollingInterval, _pollingInterval); + timer.Change(_pollingInterval, _pollingInterval); } return; } @@ -65,7 +67,7 @@ namespace System.Runtime.Caching { int newPollingInterval = Math.Min(_configPollingInterval, MEMORYSTATUS_INTERVAL_30_SECONDS); if (_pollingInterval != newPollingInterval) { _pollingInterval = newPollingInterval; - _timer.Change(_pollingInterval, _pollingInterval); + timer.Change(_pollingInterval, _pollingInterval); } return; } @@ -73,7 +75,7 @@ namespace System.Runtime.Caching { // there is no pressure, interval should be the value from config if (_pollingInterval != _configPollingInterval) { _pollingInterval = _configPollingInterval; - _timer.Change(_pollingInterval, _pollingInterval); + timer.Change(_pollingInterval, _pollingInterval); } } } @@ -126,7 +128,8 @@ namespace System.Runtime.Caching { bool dispose = true; try { _cacheMemoryMonitor = new CacheMemoryMonitor(_memoryCache, _configCacheMemoryLimitMegabytes); - _timer = new Timer(new TimerCallback(CacheManagerTimerCallback), null, _configPollingInterval, _configPollingInterval); + Timer timer = new Timer(new TimerCallback(CacheManagerTimerCallback), null, _configPollingInterval, _configPollingInterval); + _timerHandleRef = new GCHandleRef(timer); dispose = false; } finally { @@ -246,9 +249,9 @@ namespace System.Runtime.Caching { public void Dispose() { if (Interlocked.Exchange(ref _disposed, 1) == 0) { lock (_timerLock) { - Timer timer = _timer; - if (timer != null && Interlocked.CompareExchange(ref _timer, null, timer) == timer) { - timer.Dispose(); + GCHandleRef timerHandleRef = _timerHandleRef; + if (timerHandleRef != null && Interlocked.CompareExchange(ref _timerHandleRef, null, timerHandleRef) == timerHandleRef) { + timerHandleRef.Dispose(); Dbg.Trace("MemoryCacheStats", "Stopped CacheMemoryTimers"); } } diff --git a/mcs/class/referencesource/System.Runtime.Caching/System/Caching/SRef.cs b/mcs/class/referencesource/System.Runtime.Caching/System/Caching/SRef.cs index 27ee134e46..50374308ba 100644 --- a/mcs/class/referencesource/System.Runtime.Caching/System/Caching/SRef.cs +++ b/mcs/class/referencesource/System.Runtime.Caching/System/Caching/SRef.cs @@ -7,24 +7,33 @@ using System.Reflection; using System.Security; using System.Security.Permissions; using System.Diagnostics.CodeAnalysis; +using System.Runtime.InteropServices; namespace System.Runtime.Caching { internal class SRef { +#if !MONO private static Type s_type = Type.GetType("System.SizedReference", true, false); private Object _sizedRef; +#endif internal SRef(Object target) { +#if !MONO _sizedRef = Activator.CreateInstance(s_type, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.CreateInstance, null, new object[] { target }, null); +#endif } internal long ApproximateSize { [SecuritySafeCritical] [PermissionSet(SecurityAction.Assert, Unrestricted = true)] get { +#if MONO + // TODO: .net uses System.SizedReference which contains approximate size after Gen 2 collection + return 16; +#else object o = s_type.InvokeMember("ApproximateSize", BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty, null, // binder @@ -32,6 +41,7 @@ namespace System.Runtime.Caching { null, // args CultureInfo.InvariantCulture); return (long)o; +#endif } } @@ -40,12 +50,87 @@ namespace System.Runtime.Caching { [SecuritySafeCritical] [PermissionSet(SecurityAction.Assert, Unrestricted = true)] internal void Dispose() { +#if !MONO s_type.InvokeMember("Dispose", BindingFlags.Public | BindingFlags.Instance | BindingFlags.InvokeMethod, null, // binder _sizedRef, // target null, // args CultureInfo.InvariantCulture); +#endif + } + } + + internal class SRefMultiple { + private SRef[] _srefs; + private long[] _sizes; // Getting SRef size in the debugger is extremely tedious so we keep the last read value here + + internal SRefMultiple(object[] targets) { + _srefs = new SRef[targets.Length]; + _sizes = new long[targets.Length]; + for (int i = 0; i < targets.Length; i++) { + _srefs[i] = new SRef(targets[i]); + } + } + + internal long ApproximateSize { + get { + long size = 0; + for (int i = 0; i < _srefs.Length; i++) { + size += (_sizes[i] = _srefs[i].ApproximateSize); + } + return size; + } + } + + internal void Dispose() { + foreach (SRef s in _srefs) { + s.Dispose(); + } + } + } + + internal class GCHandleRef : IDisposable + where T : class, IDisposable { + GCHandle _handle; + T _t; + + [SecuritySafeCritical] + [PermissionSet(SecurityAction.Assert, Unrestricted = true)] + public GCHandleRef(T t) { + _handle = GCHandle.Alloc(t); + } + + public T Target { + [SecuritySafeCritical] + [PermissionSet(SecurityAction.Assert, Unrestricted = true)] + get { + try { + T t = (T)_handle.Target; + if (t != null) { + return t; + } + } + catch (InvalidOperationException) { + // use the normal reference instead of throwing an exception when _handle is already freed + } + return _t; + } + } + + [SecuritySafeCritical] + [PermissionSet(SecurityAction.Assert, Unrestricted = true)] + public void Dispose() { + Target.Dispose(); + // Safe to call Dispose more than once but not thread-safe + if (_handle.IsAllocated) { + // We must free the GC handle to avoid leaks. + // However after _handle is freed we no longer have access to its Target + // which will cause AVs and various race conditions under stress. + // We revert to using normal references after disposing the GC handle + _t = (T)_handle.Target; + _handle.Free(); + } } } } diff --git a/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/DataContract.cs.REMOVED.git-id b/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/DataContract.cs.REMOVED.git-id index 8f3536459d..e8ef82a586 100644 --- a/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/DataContract.cs.REMOVED.git-id +++ b/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/DataContract.cs.REMOVED.git-id @@ -1 +1 @@ -c63c76f91537ad23db1f24fb585d429c313200cd \ No newline at end of file +2ed1d48643d071051cbb40b991b398d60b8f2f8f \ No newline at end of file diff --git a/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/Diagnostics/TraceUtility.cs b/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/Diagnostics/TraceUtility.cs index 9b49ef0a45..aca78cb6ef 100644 --- a/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/Diagnostics/TraceUtility.cs +++ b/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/Diagnostics/TraceUtility.cs @@ -9,7 +9,9 @@ namespace System.Runtime.Serialization.Diagnostics using System.Globalization; using System.Runtime; using System.Runtime.Diagnostics; +#if !MONO using System.ServiceModel.Diagnostics; +#endif static class TraceUtility { diff --git a/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/Json/DataContractJsonSerializer.cs b/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/Json/DataContractJsonSerializer.cs index b190b0487f..66a49e25c1 100644 --- a/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/Json/DataContractJsonSerializer.cs +++ b/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/Json/DataContractJsonSerializer.cs @@ -11,7 +11,9 @@ namespace System.Runtime.Serialization.Json using System.IO; using System.Text; using System.Xml; +#if !MONO using System.ServiceModel; +#endif using System.Collections; using DataContractDictionary = System.Collections.Generic.Dictionary; using System.Runtime.CompilerServices; diff --git a/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/Json/JsonClassDataContract.cs b/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/Json/JsonClassDataContract.cs index 5441be39a0..cea778e8ca 100644 --- a/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/Json/JsonClassDataContract.cs +++ b/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/Json/JsonClassDataContract.cs @@ -7,7 +7,9 @@ namespace System.Runtime.Serialization.Json using System.Threading; using System.Xml; using System.Diagnostics; +#if !MONO using System.ServiceModel; +#endif using System.Collections.Generic; using System.Security; diff --git a/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/Json/JsonDataContract.cs b/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/Json/JsonDataContract.cs index c595fce062..35811e93f0 100644 --- a/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/Json/JsonDataContract.cs +++ b/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/Json/JsonDataContract.cs @@ -9,7 +9,9 @@ namespace System.Runtime.Serialization.Json using System.Runtime.Serialization; using System.Security; using System.Reflection; +#if !MONO using System.ServiceModel; +#endif using System.Xml; #if USE_REFEMIT diff --git a/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/Json/JsonEncodingStreamWrapper.cs b/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/Json/JsonEncodingStreamWrapper.cs index 3f756c1dcd..d3f2b39d19 100644 --- a/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/Json/JsonEncodingStreamWrapper.cs +++ b/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/Json/JsonEncodingStreamWrapper.cs @@ -7,7 +7,9 @@ namespace System.Runtime.Serialization.Json { using System.IO; +#if !MONO using System.ServiceModel; +#endif using System.Text; using System.Xml; using System.Security; diff --git a/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/Json/JsonObjectDataContract.cs b/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/Json/JsonObjectDataContract.cs index 3104947e45..06f8c9dc5e 100644 --- a/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/Json/JsonObjectDataContract.cs +++ b/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/Json/JsonObjectDataContract.cs @@ -5,7 +5,9 @@ namespace System.Runtime.Serialization.Json { using System.Xml; +#if !MONO using System.ServiceModel; +#endif using System.Runtime.Serialization; using System.Globalization; diff --git a/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/Json/JsonReaderDelegator.cs b/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/Json/JsonReaderDelegator.cs index bb496121d1..36925108ca 100644 --- a/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/Json/JsonReaderDelegator.cs +++ b/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/Json/JsonReaderDelegator.cs @@ -5,7 +5,9 @@ namespace System.Runtime.Serialization.Json { using System.Xml; +#if !MONO using System.ServiceModel; +#endif using System.Runtime.Serialization; using System.Globalization; diff --git a/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/Json/JsonReaderWriterFactory.cs b/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/Json/JsonReaderWriterFactory.cs index befa224840..79387fe488 100644 --- a/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/Json/JsonReaderWriterFactory.cs +++ b/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/Json/JsonReaderWriterFactory.cs @@ -9,7 +9,9 @@ namespace System.Runtime.Serialization.Json using System.Text; using System.Xml; using System.IO; +#if !MONO using System.ServiceModel; +#endif using System.Runtime.Serialization.Json; using System.Runtime.CompilerServices; diff --git a/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/Json/JsonWriterDelegator.cs b/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/Json/JsonWriterDelegator.cs index dc71490b99..6e0e98201f 100644 --- a/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/Json/JsonWriterDelegator.cs +++ b/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/Json/JsonWriterDelegator.cs @@ -6,7 +6,9 @@ namespace System.Runtime.Serialization.Json { using System.Xml; using System.Globalization; +#if !MONO using System.ServiceModel; +#endif #if USE_REFEMIT public class JsonWriterDelegator : XmlWriterDelegator @@ -202,7 +204,15 @@ namespace System.Runtime.Serialization.Json // This will break round-tripping of these dates (see bug 9690 in CSD Developer Framework) if (value.Kind != DateTimeKind.Utc) { - long tickCount = value.Ticks - TimeZone.CurrentTimeZone.GetUtcOffset(value).Ticks; + long tickCount; + if (!LocalAppContextSwitches.DoNotUseTimeZoneInfo) + { + tickCount = value.Ticks - TimeZoneInfo.Local.GetUtcOffset(value).Ticks; + } + else + { + tickCount = value.Ticks - TimeZone.CurrentTimeZone.GetUtcOffset(value).Ticks; + } if ((tickCount > DateTime.MaxValue.Ticks) || (tickCount < DateTime.MinValue.Ticks)) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( @@ -218,7 +228,15 @@ namespace System.Runtime.Serialization.Json case DateTimeKind.Unspecified: case DateTimeKind.Local: // +"zzzz"; - TimeSpan ts = TimeZone.CurrentTimeZone.GetUtcOffset(value.ToLocalTime()); + TimeSpan ts; + if (!LocalAppContextSwitches.DoNotUseTimeZoneInfo) + { + ts = TimeZoneInfo.Local.GetUtcOffset(value.ToLocalTime()); + } + else + { + ts = TimeZone.CurrentTimeZone.GetUtcOffset(value.ToLocalTime()); + } if (ts.Ticks < 0) { writer.WriteString("-"); diff --git a/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/Json/XmlJsonReader.cs b/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/Json/XmlJsonReader.cs index 1ff02aed67..ccaca2af39 100644 --- a/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/Json/XmlJsonReader.cs +++ b/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/Json/XmlJsonReader.cs @@ -6,7 +6,9 @@ namespace System.Runtime.Serialization.Json { using System.Globalization; using System.IO; +#if !MONO using System.ServiceModel; +#endif using System.Text; using System.Runtime.Serialization; using System.Collections.Generic; diff --git a/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/Json/XmlJsonWriter.cs b/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/Json/XmlJsonWriter.cs index 581e40aee0..c87639bee1 100644 --- a/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/Json/XmlJsonWriter.cs +++ b/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/Json/XmlJsonWriter.cs @@ -10,7 +10,9 @@ namespace System.Runtime.Serialization.Json using System.Runtime; using System.Runtime.Serialization; using System.Security; +#if !MONO using System.ServiceModel; +#endif using System.Text; using System.Xml; diff --git a/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/Json/XmlObjectSerializerReadContextComplexJson.cs b/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/Json/XmlObjectSerializerReadContextComplexJson.cs index 75e4a6b640..4e3e602ace 100644 --- a/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/Json/XmlObjectSerializerReadContextComplexJson.cs +++ b/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/Json/XmlObjectSerializerReadContextComplexJson.cs @@ -8,7 +8,9 @@ namespace System.Runtime.Serialization.Json using System.Collections.Generic; using System.Runtime; using System.Security; +#if !MONO using System.ServiceModel; +#endif using System.Text; using System.Xml; diff --git a/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/Json/XmlObjectSerializerWriteContextComplexJson.cs b/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/Json/XmlObjectSerializerWriteContextComplexJson.cs index 841bde9461..bdf35e3a6a 100644 --- a/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/Json/XmlObjectSerializerWriteContextComplexJson.cs +++ b/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/Json/XmlObjectSerializerWriteContextComplexJson.cs @@ -3,7 +3,9 @@ using System.Collections.Generic; using System.Text; using System.Xml; using System.Reflection; +#if !MONO using System.ServiceModel; +#endif using System.Collections; namespace System.Runtime.Serialization.Json diff --git a/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/SchemaExporter.cs b/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/SchemaExporter.cs index b2c4586e3b..ff5704a55d 100644 --- a/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/SchemaExporter.cs +++ b/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/SchemaExporter.cs @@ -75,7 +75,7 @@ namespace System.Runtime.Serialization if (!Schemas.Contains(Globals.SerializationNamespace)) { StringReader reader = new StringReader(Globals.SerializationSchema); - XmlSchema schema = XmlSchema.Read(reader, null); + XmlSchema schema = XmlSchema.Read(new XmlTextReader(reader) { DtdProcessing = DtdProcessing.Prohibit }, null); if (schema == null) throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.CouldNotReadSerializationSchema, Globals.SerializationNamespace))); Schemas.Add(schema); diff --git a/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/SchemaImporter.cs b/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/SchemaImporter.cs index 32d06e427d..29885641ac 100644 --- a/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/SchemaImporter.cs +++ b/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/SchemaImporter.cs @@ -51,7 +51,7 @@ namespace System.Runtime.Serialization if (!schemaSet.Contains(Globals.SerializationNamespace)) { StringReader reader = new StringReader(Globals.SerializationSchema); - XmlSchema schema = XmlSchema.Read(reader, null); + XmlSchema schema = XmlSchema.Read(new XmlTextReader(reader) { DtdProcessing = DtdProcessing.Prohibit }, null); if (schema == null) throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.CouldNotReadSerializationSchema, Globals.SerializationNamespace))); schemaSet.Add(schema); diff --git a/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/XmlObjectSerializerReadContext.cs b/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/XmlObjectSerializerReadContext.cs index 96abfad874..38a78ece46 100644 --- a/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/XmlObjectSerializerReadContext.cs +++ b/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/XmlObjectSerializerReadContext.cs @@ -9,7 +9,9 @@ namespace System.Runtime.Serialization using System.Collections.Generic; using System.Diagnostics; using System.Runtime.Diagnostics; +#if !MONO using System.ServiceModel.Diagnostics; +#endif using System.Text; using System.Xml; using System.Xml.Serialization; diff --git a/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/XmlObjectSerializerWriteContext.cs b/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/XmlObjectSerializerWriteContext.cs index a61836fc14..acd6282a73 100644 --- a/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/XmlObjectSerializerWriteContext.cs +++ b/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/XmlObjectSerializerWriteContext.cs @@ -14,7 +14,9 @@ namespace System.Runtime.Serialization using System.Xml; using System.Collections.Generic; using System.Xml.Serialization; +#if !MONO using System.ServiceModel.Diagnostics; +#endif using System.Security; using System.Security.Permissions; using System.Runtime.CompilerServices; diff --git a/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/XmlSerializableServices.cs b/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/XmlSerializableServices.cs index c36cb152e9..bf5a3cb3e5 100644 --- a/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/XmlSerializableServices.cs +++ b/mcs/class/referencesource/System.Runtime.Serialization/System/Runtime/Serialization/XmlSerializableServices.cs @@ -67,7 +67,6 @@ namespace System.Runtime.Serialization nodes[i].WriteTo(xmlWriter); } -#if !MOBILE internal static string AddDefaultSchemaMethodName = "AddDefaultSchema"; public static void AddDefaultSchema(XmlSchemaSet schemas, XmlQualifiedName typeQName) { @@ -77,6 +76,5 @@ namespace System.Runtime.Serialization throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("typeQName"); SchemaExporter.AddDefaultXmlType(schemas, typeQName.Name, typeQName.Namespace); } -#endif } } diff --git a/mcs/class/referencesource/System.ServiceModel.Activation/System/ServiceModel/Activation/HostedAspNetEnvironment.cs b/mcs/class/referencesource/System.ServiceModel.Activation/System/ServiceModel/Activation/HostedAspNetEnvironment.cs index c0dc0f3292..4e785e5b1f 100644 --- a/mcs/class/referencesource/System.ServiceModel.Activation/System/ServiceModel/Activation/HostedAspNetEnvironment.cs +++ b/mcs/class/referencesource/System.ServiceModel.Activation/System/ServiceModel/Activation/HostedAspNetEnvironment.cs @@ -101,20 +101,13 @@ namespace System.ServiceModel.Activation } } - // Provides the version of the WebSocket protocol supported by IIS. Throws an exception if called before we determined the value. + // Provides the version of the WebSocket protocol supported by IIS. // Returns null if WebSockets are not supported (because the IIS WebSocketModule is not installed or enabled). public override string WebSocketVersion { get { - if (isWebSocketVersionSet) - { - return webSocketVersion; - } - else - { - throw Fx.AssertAndFailFast("The supported WebSocket protocol version is not determined at this time."); - } + return isWebSocketVersionSet ? webSocketVersion : null; } } @@ -136,8 +129,6 @@ namespace System.ServiceModel.Activation /// public static void TrySetWebSocketVersion(HttpApplication application) { - Fx.Assert(application != null, "Invalid argument."); - if (!isWebSocketVersionSet) { webSocketVersion = application.Request.ServerVariables[WebSocketVersionServerProperty]; diff --git a/mcs/class/referencesource/System.ServiceModel.Internals/System/Runtime/Diagnostics/EtwDiagnosticTrace.cs b/mcs/class/referencesource/System.ServiceModel.Internals/System/Runtime/Diagnostics/EtwDiagnosticTrace.cs index 4a81f353ca..c84160682a 100644 --- a/mcs/class/referencesource/System.ServiceModel.Internals/System/Runtime/Diagnostics/EtwDiagnosticTrace.cs +++ b/mcs/class/referencesource/System.ServiceModel.Internals/System/Runtime/Diagnostics/EtwDiagnosticTrace.cs @@ -288,6 +288,7 @@ namespace System.Runtime.Diagnostics [Fx.Tag.SecurityNote(Critical = "Usage of EventDescriptor, which is protected by a LinkDemand")] [SecurityCritical] + [SuppressMessage("Microsoft.Security.Xml", "CA3057:DoNotUseLoadXml", Justification = "It is internal code. No security concern.")] public void WriteTraceSource(ref EventDescriptor eventDescriptor, string description, TracePayload payload) { if (this.TracingEnabled) diff --git a/mcs/class/referencesource/System.ServiceModel/InternalApis/Clr/inc/AppContextDefaultValues.cs b/mcs/class/referencesource/System.ServiceModel/InternalApis/Clr/inc/AppContextDefaultValues.cs index 8a130a0f34..9224bf8b8f 100644 --- a/mcs/class/referencesource/System.ServiceModel/InternalApis/Clr/inc/AppContextDefaultValues.cs +++ b/mcs/class/referencesource/System.ServiceModel/InternalApis/Clr/inc/AppContextDefaultValues.cs @@ -3,6 +3,15 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== + +// There are cases where we have multiple assemblies that are going to import this file and +// if they are going to also have InternalsVisibleTo between them, there will be a compiler warning +// that the type is found both in the source and in a referenced assembly. The compiler will prefer +// the version of the type defined in the source +// +// In order to disable the warning for this type we are disabling this warning for this entire file. +#pragma warning disable 436 + using System; using System.Collections.Generic; @@ -167,3 +176,5 @@ namespace System static partial void PopulateDefaultValuesPartial(string platformIdentifier, string profile, int version); } } + +#pragma warning restore 436 diff --git a/mcs/class/referencesource/System.ServiceModel/InternalApis/Clr/inc/LocalAppContext.cs b/mcs/class/referencesource/System.ServiceModel/InternalApis/Clr/inc/LocalAppContext.cs index f05b599ed3..33662b5428 100644 --- a/mcs/class/referencesource/System.ServiceModel/InternalApis/Clr/inc/LocalAppContext.cs +++ b/mcs/class/referencesource/System.ServiceModel/InternalApis/Clr/inc/LocalAppContext.cs @@ -4,6 +4,14 @@ // // ==--== +// There are cases where we have multiple assemblies that are going to import this file and +// if they are going to also have InternalsVisibleTo between them, there will be a compiler warning +// that the type is found both in the source and in a referenced assembly. The compiler will prefer +// the version of the type defined in the source +// +// In order to disable the warning for this type we are disabling this warning for this entire file. +#pragma warning disable 436 + // NOTE: This file should not be included in mscorlib. This should only be included in FX libraries that need to provide switches using System; using System.Collections.Generic; @@ -126,3 +134,5 @@ namespace System } } } + +#pragma warning restore 436 diff --git a/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/AppContextDefaultValues.Default.cs b/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/AppContextDefaultValues.Default.cs index 5f591137e3..e086fad276 100644 --- a/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/AppContextDefaultValues.Default.cs +++ b/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/AppContextDefaultValues.Default.cs @@ -27,6 +27,11 @@ namespace System LocalAppContextSwitches.SetDefaultsLessOrEqual_452(); } + if (version <= 40601) + { + LocalAppContextSwitches.SetDefaultsLessOrEqual_461(); + } + break; } } diff --git a/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Channels/HttpChannelListener.cs b/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Channels/HttpChannelListener.cs index 785a9c0595..5dac93babe 100644 --- a/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Channels/HttpChannelListener.cs +++ b/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Channels/HttpChannelListener.cs @@ -839,17 +839,11 @@ namespace System.ServiceModel.Channels { AspNetEnvironment env = AspNetEnvironment.Current; - // When IIS hosted, WebSockets can be used if the pipeline mode is integrated and the WebSocketModule is loaded. - // Otherwise, the client requests will not be upgraded to web sockets (see the code in HostedHttpTransportManager.HttpContextReceived(..)). - // We do the checks below (and fail the service activation), to avoid starting a WebSockets listener that won't get called. + // When IIS hosted, WebSockets can be used if the pipeline mode is integrated if (!env.UsingIntegratedPipeline) { throw FxTrace.Exception.AsError(new NotSupportedException(SR.GetString(SR.WebSocketsNotSupportedInClassicPipeline))); } - else if (!env.IsWebSocketModuleLoaded) - { - throw FxTrace.Exception.AsError(new NotSupportedException(SR.GetString(SR.WebSocketModuleNotLoaded))); - } } else if (!WebSocketHelper.OSSupportsWebSockets()) { diff --git a/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Channels/PipeConnection.cs.REMOVED.git-id b/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Channels/PipeConnection.cs.REMOVED.git-id index ccf5a09a5a..8c57a59224 100644 --- a/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Channels/PipeConnection.cs.REMOVED.git-id +++ b/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Channels/PipeConnection.cs.REMOVED.git-id @@ -1 +1 @@ -f50e3667174e51a9ed111f895086c89240f0296c \ No newline at end of file +ee3fbc127a7fcb92e6aa44345193357a75edc7ee \ No newline at end of file diff --git a/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Channels/TransportDefaults.cs b/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Channels/TransportDefaults.cs index 4de327474f..d2c0f72a51 100644 --- a/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Channels/TransportDefaults.cs +++ b/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Channels/TransportDefaults.cs @@ -202,8 +202,8 @@ namespace System.ServiceModel.Channels internal const bool RequireClientCertificate = false; internal const int MaxFaultSize = MaxBufferSize; internal const int MaxSecurityFaultSize = 16384; - internal const SslProtocols SslProtocols = System.Security.Authentication.SslProtocols.Ssl3 | - System.Security.Authentication.SslProtocols.Tls | + + internal const SslProtocols SslProtocols = System.Security.Authentication.SslProtocols.Tls | System.Security.Authentication.SslProtocols.Tls11 | System.Security.Authentication.SslProtocols.Tls12; diff --git a/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Channels/UnsafeNativeMethods.cs b/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Channels/UnsafeNativeMethods.cs index bade3dab69..275270b401 100644 --- a/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Channels/UnsafeNativeMethods.cs +++ b/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Channels/UnsafeNativeMethods.cs @@ -1101,31 +1101,82 @@ namespace System.ServiceModel.Channels #if !FEATURE_CORECLR - // On CoreCLR this is not the way to determine if a process is a tailored application (which means APPX). - // On CoreCLR AppX is determined by a flag past to the host which is exposed by AppDomain.IsAppXProcess in mscorlib. - // The reason for this if-def is to ensure nobody takes a dependency on this on CoreCLR. - + private static IntPtr GetCurrentProcessToken() { return new IntPtr(-4); } + + enum AppPolicyClrCompat + { + AppPolicyClrCompat_Others = 0, + AppPolicyClrCompat_ClassicDesktop = 1, + AppPolicyClrCompat_Universal = 2, + AppPolicyClrCompat_PackagedDesktop = 3 + }; + + [DllImport(KERNEL32, CharSet = CharSet.None, EntryPoint = "AppPolicyGetClrCompat")] + [System.Security.SecuritySafeCritical] + [return: MarshalAs(UnmanagedType.I4)] + private static extern Int32 _AppPolicyGetClrCompat(IntPtr processToken, out AppPolicyClrCompat appPolicyClrCompat); + // AppModel.h functions (Win8+) [DllImport(KERNEL32, CharSet = CharSet.None, EntryPoint = "GetCurrentPackageId")] - [SecurityCritical] + [System.Security.SecuritySafeCritical] [return: MarshalAs(UnmanagedType.I4)] - private static extern Int32 GetCurrentPackageId(ref Int32 pBufferLength, Byte[] pBuffer); + private static extern Int32 _GetCurrentPackageId(ref Int32 pBufferLength, Byte[] pBuffer); - [Fx.Tag.SecurityNote( - Critical = "Critical because it calls the native function GetCurrentPackageId.", - Safe = "Safe because it takes no user input and it doesn't leak security sensitive information.")] - [SecuritySafeCritical] + [DllImport(KERNEL32, CharSet=System.Runtime.InteropServices.CharSet.Auto, BestFitMapping=false)] + [ResourceExposure(ResourceScope.Machine)] + private static extern IntPtr GetModuleHandle(string modName); + + // Copied from Win32Native.cs + // Note - do NOT use this to call methods. Use P/Invoke, which will + // do much better things w.r.t. marshaling, pinning memory, security + // stuff, better interactions with thread aborts, etc. This is used + // solely by DoesWin32MethodExist for avoiding try/catch EntryPointNotFoundException + // in scenarios where an OS Version check is insufficient + [DllImport(KERNEL32, CharSet=CharSet.Ansi, BestFitMapping=false, SetLastError=true, ExactSpelling=true)] + [ResourceExposure(ResourceScope.None)] + private static extern IntPtr GetProcAddress(IntPtr hModule, String methodName); + + [System.Security.SecurityCritical] // auto-generated + private static bool DoesWin32MethodExist(String moduleName, String methodName) + { + // GetModuleHandle does not increment the module's ref count, so we don't need to call FreeLibrary. + IntPtr hModule = GetModuleHandle(moduleName); + if (hModule == IntPtr.Zero) { + System.Diagnostics.Debug.Assert(hModule != IntPtr.Zero, "GetModuleHandle failed. Dll isn't loaded?"); + return false; + } + IntPtr functionPointer = GetProcAddress(hModule, methodName); + return (functionPointer != IntPtr.Zero); + } + + // On CoreCLR this is not the way to determine if a process is a tailored application (which means APPX). + // On CoreCLR AppX is determined by a flag past to the host which is exposed by AppDomain.IsAppXProcess in mscorlib. + // The reason for this if-def is to ensure nobody takes a dependency on this on CoreCLR. + [System.Security.SecuritySafeCritical] private static bool _IsTailoredApplication() { - if (OSEnvironmentHelper.IsAtLeast(OSVersion.Win8)) + Version windows8Version = new Version(6, 2, 0, 0); + OperatingSystem os = Environment.OSVersion; + bool osSupportsPackagedProcesses = os.Platform == PlatformID.Win32NT && os.Version >= windows8Version; + + if (osSupportsPackagedProcesses && DoesWin32MethodExist(KERNEL32, "AppPolicyGetClrCompat")) { - int bufLen = 0; - // Will return ERROR_INSUFFICIENT_BUFFER when running within a tailored application, + // Use AppPolicyGetClrCompat if it is available. Return true if and only if this is a UWA which means if + // this is packaged desktop app this method will return false. This may cause some confusion however + // this is necessary to make the behavior of packaged desktop apps identical to desktop apps. + AppPolicyClrCompat appPolicyClrCompat; + return _AppPolicyGetClrCompat(GetCurrentProcessToken(), out appPolicyClrCompat) == ERROR_SUCCESS && + appPolicyClrCompat == AppPolicyClrCompat.AppPolicyClrCompat_Universal; + } + else if(osSupportsPackagedProcesses && DoesWin32MethodExist(KERNEL32, "GetCurrentPackageId")) + { + Int32 bufLen = 0; + // Will return ERROR_INSUFFICIENT_BUFFER when running within a packaged application, // and will return ERROR_NO_PACKAGE_IDENTITY otherwise. - return GetCurrentPackageId(ref bufLen, null) == ERROR_INSUFFICIENT_BUFFER; + return _GetCurrentPackageId(ref bufLen, null) == ERROR_INSUFFICIENT_BUFFER; } else - { + { // We must be running on a downlevel OS. return false; } } diff --git a/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Channels/WebSocketHelper.cs b/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Channels/WebSocketHelper.cs index 928d9be8f3..b99db25d12 100644 --- a/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Channels/WebSocketHelper.cs +++ b/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Channels/WebSocketHelper.cs @@ -6,6 +6,7 @@ namespace System.ServiceModel.Channels { using System; using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Linq; using System.Net; @@ -44,6 +45,7 @@ namespace System.ServiceModel.Channels static readonly HashSet InvalidSeparatorSet = new HashSet(new char[] { '(', ')', '<', '>', '@', ',', ';', ':', '\\', '"', '/', '[', ']', '?', '=', '{', '}', ' ' }); static string currentWebSocketVersion; + [SuppressMessage("Microsoft.Security.Cryptography", "CA5354:DoNotUseSHA1", Justification = "Cannot change. Usage of SHA1 is part of WebSocket spec. Justification in RFC6455 section 10.8")] internal static string ComputeAcceptHeader(string webSocketKey) { Fx.Assert(webSocketKey != null, "webSocketKey should not be null."); diff --git a/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Configuration/Properties.cs.REMOVED.git-id b/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Configuration/Properties.cs.REMOVED.git-id index 574f59fed7..4ea19d726e 100644 --- a/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Configuration/Properties.cs.REMOVED.git-id +++ b/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Configuration/Properties.cs.REMOVED.git-id @@ -1 +1 @@ -35c78297859f7342bb6f1137a045ea1bf79b932c \ No newline at end of file +a457268b0cec838769a3f3a1db5bc2d6a67d31c1 \ No newline at end of file diff --git a/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Description/MessageContractExporter.cs b/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Description/MessageContractExporter.cs index dbef91c127..e4a23bcc00 100644 --- a/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Description/MessageContractExporter.cs +++ b/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Description/MessageContractExporter.cs @@ -1347,31 +1347,38 @@ namespace System.ServiceModel.Description internal static XmlSchema CreateWsdl() { - return XmlSchema.Read(new StringReader(wsdl), null); + StringReader reader = new StringReader(wsdl); + return XmlSchema.Read(new XmlTextReader(reader) { DtdProcessing = DtdProcessing.Prohibit }, null); } + internal static XmlSchema CreateSoap() { - return XmlSchema.Read(new StringReader(soap), null); + StringReader reader = new StringReader(soap); + return XmlSchema.Read(new XmlTextReader(reader) { DtdProcessing = DtdProcessing.Prohibit }, null); } internal static XmlSchema CreateSoapEncoding() { - return XmlSchema.Read(new StringReader(soapEncoding), null); + StringReader reader = new StringReader(soapEncoding); + return XmlSchema.Read(new XmlTextReader(reader) { DtdProcessing = DtdProcessing.Prohibit }, null); } internal static XmlSchema CreateFakeSoapEncoding() { - return XmlSchema.Read(new StringReader(fakeSoapEncoding), null); + StringReader reader = new StringReader(fakeSoapEncoding); + return XmlSchema.Read(new XmlTextReader(reader) { DtdProcessing = DtdProcessing.Prohibit }, null); } internal static XmlSchema CreateFakeXsdSchema() { - return XmlSchema.Read(new StringReader(fakeXsd), null); + StringReader reader = new StringReader(fakeXsd); + return XmlSchema.Read(new XmlTextReader(reader) { DtdProcessing = DtdProcessing.Prohibit }, null); } internal static XmlSchema CreateFakeXmlSchema() { - return XmlSchema.Read(new StringReader(fakeXmlSchema), null); + StringReader reader = new StringReader(fakeXmlSchema); + return XmlSchema.Read(new XmlTextReader(reader) { DtdProcessing = DtdProcessing.Prohibit }, null); } internal static bool IsKnownSchema(string ns) diff --git a/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Description/WsdlHelper.cs b/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Description/WsdlHelper.cs index c056108dd6..f8674ce614 100644 --- a/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Description/WsdlHelper.cs +++ b/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Description/WsdlHelper.cs @@ -5,6 +5,7 @@ namespace System.ServiceModel.Description { using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.Linq; @@ -313,6 +314,8 @@ namespace System.ServiceModel.Description return newWsdl; } + [SuppressMessage("Microsoft.Security.Xml", "CA3054:DoNotAllowDtdOnXmlTextReader")] + [SuppressMessage("Microsoft.Security.Xml", "CA3069:ReviewDtdProcessingAssignment", Justification = "This is trusted server code from the application only. We should allow the customer add dtd.")] private static XmlSchema CloneXsd(XmlSchema originalXsd) { Fx.Assert(originalXsd != null, "originalXsd must not be null"); @@ -321,7 +324,7 @@ namespace System.ServiceModel.Description { originalXsd.Write(memoryStream); memoryStream.Seek(0, SeekOrigin.Begin); - newXsd = XmlSchema.Read(memoryStream, null); + newXsd = XmlSchema.Read(new XmlTextReader(memoryStream) { DtdProcessing = DtdProcessing.Parse }, null); } return newXsd; diff --git a/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Dispatcher/QueryMatcher.cs b/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Dispatcher/QueryMatcher.cs index d34430b873..c7fb348721 100644 --- a/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Dispatcher/QueryMatcher.cs +++ b/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Dispatcher/QueryMatcher.cs @@ -7,6 +7,7 @@ namespace System.ServiceModel.Dispatcher using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; + using System.Diagnostics.CodeAnalysis; using System.Runtime; using System.ServiceModel.Channels; using System.ServiceModel.Diagnostics; @@ -262,6 +263,7 @@ namespace System.ServiceModel.Dispatcher } } + [SuppressMessage("Microsoft.Security.Xml", "CA3057:DoNotUseLoadXml")] static QueryMatcher() { QueryMatcher.defaultFunctionLibs = new IFunctionLibrary[] { new XPathFunctionLibrary() }; diff --git a/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Dispatcher/TaskMethodInvoker.cs b/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Dispatcher/TaskMethodInvoker.cs index 9bf6328b82..2b9ff6aeda 100644 --- a/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Dispatcher/TaskMethodInvoker.cs +++ b/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Dispatcher/TaskMethodInvoker.cs @@ -8,12 +8,11 @@ namespace System.ServiceModel.Dispatcher using System.Diagnostics; using System.Reflection; using System.Runtime; - using System.Runtime.Diagnostics; using System.Security; using System.ServiceModel.Description; using System.ServiceModel.Diagnostics; - using System.ServiceModel.Diagnostics.Application; using System.Threading.Tasks; + using Threading; /// /// An invoker used when some operation contract has a return value of Task or its generic counterpart (Task of T) @@ -21,14 +20,12 @@ namespace System.ServiceModel.Dispatcher internal class TaskMethodInvoker : IOperationInvoker { private const string ResultMethodName = "Result"; - private MethodInfo taskMethod; - private bool isGenericTask; + private readonly MethodInfo taskMethod; private InvokeDelegate invokeDelegate; private int inputParameterCount; private int outputParameterCount; - private object[] outputs; - private MethodInfo toAsyncMethodInfo; private MethodInfo taskTResultGetMethod; + private bool isGenericTask; public TaskMethodInvoker(MethodInfo taskMethod, Type taskType) { @@ -41,7 +38,6 @@ namespace System.ServiceModel.Dispatcher if (taskType != ServiceReflector.VoidType) { - this.toAsyncMethodInfo = TaskExtensions.MakeGenericMethod(taskType); this.taskTResultGetMethod = ((PropertyInfo)taskMethod.ReturnType.GetMember(ResultMethodName)[0]).GetGetMethod(); this.isGenericTask = true; } @@ -57,36 +53,11 @@ namespace System.ServiceModel.Dispatcher get { return this.taskMethod; } } - private InvokeDelegate InvokeDelegate - { - get - { - this.EnsureIsInitialized(); - return this.invokeDelegate; - } - } - - private int InputParameterCount - { - get - { - this.EnsureIsInitialized(); - return this.inputParameterCount; - } - } - - private int OutputParameterCount - { - get - { - this.EnsureIsInitialized(); - return this.outputParameterCount; - } - } - public object[] AllocateInputs() { - return EmptyArray.Allocate(this.InputParameterCount); + EnsureIsInitialized(); + + return EmptyArray.Allocate(this.inputParameterCount); } public object Invoke(object instance, object[] inputs, out object[] outputs) @@ -96,6 +67,114 @@ namespace System.ServiceModel.Dispatcher public IAsyncResult InvokeBegin(object instance, object[] inputs, AsyncCallback callback, object state) { + return ToApm(InvokeAsync(instance, inputs), callback, state); + } + + public object InvokeEnd(object instance, out object[] outputs, IAsyncResult result) + { + if (instance == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxNoServiceObject))); + } + + object returnVal = null; + bool callFailed = true; + bool callFaulted = false; + ServiceModelActivity activity = null; + Activity boundOperation = null; + + try + { + AsyncMethodInvoker.GetActivityInfo(ref activity, ref boundOperation); + + Task> invokeTask = result as Task>; + + if (invokeTask == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.SFxInvalidCallbackIAsyncResult)); + } + + AggregateException ae = null; + Tuple tuple = null; + Task task = null; + + if (invokeTask.IsFaulted) + { + Fx.Assert(invokeTask.Exception != null, "Task.IsFaulted guarantees non-null exception."); + ae = invokeTask.Exception; + } + else + { + Fx.Assert(invokeTask.IsCompleted, "Task.Result is expected to be completed"); + + tuple = invokeTask.Result; + task = tuple.Item1 as Task; + + if (task == null) + { + outputs = tuple.Item2; + return null; + } + + if (task.IsFaulted) + { + Fx.Assert(task.Exception != null, "Task.IsFaulted guarantees non-null exception."); + ae = task.Exception; + } + } + + if (ae != null && ae.InnerException != null) + { + if (ae.InnerException is FaultException) + { + // If invokeTask.IsFaulted we produce the 'callFaulted' behavior below. + // Any other exception will retain 'callFailed' behavior. + callFaulted = true; + callFailed = false; + } + + if (ae.InnerException is SecurityException) + { + DiagnosticUtility.TraceHandledException(ae.InnerException, TraceEventType.Warning); + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(AuthorizationBehavior.CreateAccessDeniedFaultException()); + } + + invokeTask.GetAwaiter().GetResult(); + } + + // Task cancellation without an exception indicates failure but we have no + // additional information to provide. Accessing Task.Result will throw a + // TaskCanceledException. For consistency between void Tasks and Task, + // we detect and throw here. + if (task.IsCanceled) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new TaskCanceledException(task)); + } + + outputs = tuple.Item2; + + returnVal = this.isGenericTask ? this.taskTResultGetMethod.Invoke(task, Type.EmptyTypes) : null; + callFailed = false; + + return returnVal; + } + finally + { + if (boundOperation != null) + { + ((IDisposable)boundOperation).Dispose(); + } + + ServiceModelActivity.Stop(activity); + AsyncMethodInvoker.StopOperationInvokeTrace(callFailed, callFaulted, this.TaskMethod.Name); + AsyncMethodInvoker.StopOperationInvokePerformanceCounters(callFailed, callFaulted, this.TaskMethod.Name); + } + } + + private async Task> InvokeAsync(object instance, object[] inputs) + { + EnsureIsInitialized(); + if (instance == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxNoServiceObject))); @@ -103,59 +182,55 @@ namespace System.ServiceModel.Dispatcher if (inputs == null) { - if (this.InputParameterCount > 0) + if (this.inputParameterCount > 0) { - throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxInputParametersToServiceNull, this.InputParameterCount))); + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxInputParametersToServiceNull, this.inputParameterCount))); } } - else if (inputs.Length != this.InputParameterCount) + else if (inputs.Length != this.inputParameterCount) { - throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxInputParametersToServiceInvalid, this.InputParameterCount, inputs.Length))); + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxInputParametersToServiceInvalid, this.inputParameterCount, inputs.Length))); } - this.outputs = EmptyArray.Allocate(this.OutputParameterCount); + object[] outputs = EmptyArray.Allocate(this.outputParameterCount); AsyncMethodInvoker.StartOperationInvokePerformanceCounters(this.taskMethod.Name); - IAsyncResult returnValue; - bool callFailed = true; - bool callFaulted = false; + object returnValue; ServiceModelActivity activity = null; + Activity boundActivity = null; try { - Activity boundActivity = null; AsyncMethodInvoker.CreateActivityInfo(ref activity, ref boundActivity); - AsyncMethodInvoker.StartOperationInvokeTrace(this.taskMethod.Name); - - using (boundActivity) + + if (DiagnosticUtility.ShouldUseActivity) { - if (DiagnosticUtility.ShouldUseActivity) - { - string activityName = SR.GetString(SR.ActivityExecuteMethod, this.taskMethod.DeclaringType.FullName, this.taskMethod.Name); - ServiceModelActivity.Start(activity, activityName, ActivityType.ExecuteUserCode); - } - - object taskReturnValue = this.InvokeDelegate(instance, inputs, this.outputs); - - if (taskReturnValue == null) - { - throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("task"); - } - else if (this.isGenericTask) - { - returnValue = (IAsyncResult)this.toAsyncMethodInfo.Invoke(null, new object[] { taskReturnValue, callback, state }); - } - else - { - returnValue = ((Task)taskReturnValue).AsAsyncResult(callback, state); - } - - callFailed = false; + string activityName = SR.GetString(SR.ActivityExecuteMethod, this.taskMethod.DeclaringType.FullName, this.taskMethod.Name); + ServiceModelActivity.Start(activity, activityName, ActivityType.ExecuteUserCode); } + + OperationContext.EnableAsyncFlow(); + + returnValue = this.invokeDelegate(instance, inputs, outputs); + + if (returnValue == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("task"); + } + + var returnValueTask = returnValue as Task; + + if (returnValueTask != null) + { + // Only return once the task has completed + await returnValueTask; + } + + return Tuple.Create(returnValue, outputs); } - catch (System.Security.SecurityException e) + catch (SecurityException e) { DiagnosticUtility.TraceHandledException(e, TraceEventType.Warning); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(AuthorizationBehavior.CreateAccessDeniedFaultException()); @@ -163,101 +238,77 @@ namespace System.ServiceModel.Dispatcher catch (Exception e) { TraceUtility.TraceUserCodeException(e, this.taskMethod); - if (e is FaultException) - { - callFaulted = true; - callFailed = false; - } - throw; } finally { - ServiceModelActivity.Stop(activity); + OperationContext.DisableAsyncFlow(); - // Any exception above means InvokeEnd will not be called, so complete it here. - if (callFailed || callFaulted) + if (boundActivity != null) { - AsyncMethodInvoker.StopOperationInvokeTrace(callFailed, callFaulted, this.TaskMethod.Name); - AsyncMethodInvoker.StopOperationInvokePerformanceCounters(callFailed, callFaulted, this.TaskMethod.Name); + ((IDisposable)boundActivity).Dispose(); } - } - return returnValue; + ServiceModelActivity.Stop(activity); + } } - public object InvokeEnd(object instance, out object[] outputs, IAsyncResult result) + // Helper method when implementing an APM wrapper around a Task based async method which returns a result. + // In the BeginMethod method, you would call use ToApm to wrap a call to MethodAsync: + // return MethodAsync(params).ToApm(callback, state); + // In the EndMethod, you would use ToApmEnd to ensure the correct exception handling + // This will handle throwing exceptions in the correct place and ensure the IAsyncResult contains the provided + // state object + private static Task ToApm(Task task, AsyncCallback callback, object state) { - object returnVal; - bool callFailed = true; - bool callFaulted = false; - ServiceModelActivity activity = null; - - if (instance == null) + // When using APM, the returned IAsyncResult must have the passed in state object stored in AsyncState. This + // is so the callback can regain state. If the incoming task already holds the state object, there's no need + // to create a TaskCompletionSource to ensure the returned (IAsyncResult)Task has the right state object. + // This is a performance optimization for this special case. + if (task.AsyncState == state) { - throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxNoServiceObject))); - } - - try - { - Activity boundOperation = null; - AsyncMethodInvoker.GetActivityInfo(ref activity, ref boundOperation); - - using (boundOperation) + if (callback != null) { - Task task = result as Task; - - Fx.Assert(task != null, "InvokeEnd needs to be called with the result returned from InvokeBegin."); - if (task.IsFaulted) + task.ContinueWith((antecedent, obj) => { - Fx.Assert(task.Exception != null, "Task.IsFaulted guarantees non-null exception."); - - // If FaultException is thrown, we will get 'callFaulted' behavior below. - // Any other exception will retain 'callFailed' behavior. - throw FxTrace.Exception.AsError(task.Exception); - } - - // Task cancellation without an exception indicates failure but we have no - // additional information to provide. Accessing Task.Result will throw a - // TaskCanceledException. For consistency between void Tasks and Task, - // we detect and throw here. - if (task.IsCanceled) - { - throw FxTrace.Exception.AsError(new TaskCanceledException(task)); - } - - outputs = this.outputs; - if (this.isGenericTask) - { - returnVal = this.taskTResultGetMethod.Invoke(result, Type.EmptyTypes); - } - else - { - returnVal = null; - } - - callFailed = false; + AsyncCallback callbackObj = (AsyncCallback)obj; + callbackObj(antecedent); + }, callback, CancellationToken.None, TaskContinuationOptions.HideScheduler, TaskScheduler.Default); } - } - catch (SecurityException e) - { - DiagnosticUtility.TraceHandledException(e, TraceEventType.Warning); - throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(AuthorizationBehavior.CreateAccessDeniedFaultException()); - } - catch (FaultException) - { - callFaulted = true; - callFailed = false; - throw; - } - finally - { - ServiceModelActivity.Stop(activity); - AsyncMethodInvoker.StopOperationInvokeTrace(callFailed, callFaulted, this.TaskMethod.Name); - AsyncMethodInvoker.StopOperationInvokePerformanceCounters(callFailed, callFaulted, this.TaskMethod.Name); + + return task; } - return returnVal; + // Need to create a TaskCompletionSource so that the returned Task object has the correct AsyncState value. + var tcs = new TaskCompletionSource(state); + var continuationState = Tuple.Create(tcs, callback); + + task.ContinueWith((antecedent, obj) => + { + Tuple, AsyncCallback> tuple = (Tuple, AsyncCallback>)obj; + TaskCompletionSource tcsObj = tuple.Item1; + AsyncCallback callbackObj = tuple.Item2; + + if (antecedent.IsFaulted) + { + tcsObj.TrySetException(antecedent.Exception.InnerException); + } + else if (antecedent.IsCanceled) + { + tcsObj.TrySetCanceled(); + } + else + { + tcsObj.TrySetResult(antecedent.Result); + } + + if (callbackObj != null) + { + callbackObj(tcsObj.Task); + } + }, continuationState, CancellationToken.None, TaskContinuationOptions.HideScheduler, TaskScheduler.Default); + + return tcs.Task; } private void EnsureIsInitialized() diff --git a/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Dispatcher/XmlSerializerOperationFormatter.cs b/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Dispatcher/XmlSerializerOperationFormatter.cs index 5d826dfb48..0072f122b8 100644 --- a/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Dispatcher/XmlSerializerOperationFormatter.cs +++ b/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Dispatcher/XmlSerializerOperationFormatter.cs @@ -92,7 +92,7 @@ namespace System.ServiceModel.Dispatcher bufferWriter.Flush(); XmlDocument doc = new XmlDocument(); memoryStream.Position = 0; - doc.Load(memoryStream); + doc.Load(new XmlTextReader(memoryStream) { DtdProcessing = DtdProcessing.Prohibit }); //doc.Save(Console.Out); foreach (XmlElement element in doc.DocumentElement.ChildNodes) { diff --git a/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/EndpointAddress10.cs b/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/EndpointAddress10.cs index dd5b3ef343..d7e24e00a8 100644 --- a/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/EndpointAddress10.cs +++ b/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/EndpointAddress10.cs @@ -67,7 +67,7 @@ namespace System.ServiceModel static XmlSchema GetEprSchema() { - using (XmlTextReader reader = new XmlTextReader(new StringReader(Schema))) + using (XmlTextReader reader = new XmlTextReader(new StringReader(Schema)) { DtdProcessing = DtdProcessing.Prohibit }) { return XmlSchema.Read(reader, null); } diff --git a/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/EndpointAddressAugust2004.cs b/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/EndpointAddressAugust2004.cs index b60cc2b287..d74bdeb89c 100644 --- a/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/EndpointAddressAugust2004.cs +++ b/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/EndpointAddressAugust2004.cs @@ -67,7 +67,7 @@ namespace System.ServiceModel static XmlSchema GetEprSchema() { - using (XmlTextReader reader = new XmlTextReader(new StringReader(Schema))) + using (XmlTextReader reader = new XmlTextReader(new StringReader(Schema)) { DtdProcessing = DtdProcessing.Prohibit }) { return XmlSchema.Read(reader, null); } diff --git a/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/LocalAppContextSwitches.cs b/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/LocalAppContextSwitches.cs index 616b1feddc..323304ff6b 100644 --- a/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/LocalAppContextSwitches.cs +++ b/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/LocalAppContextSwitches.cs @@ -14,9 +14,11 @@ namespace System.ServiceModel { private const string DisableExplicitConnectionCloseHeaderString = "Switch.System.ServiceModel.DisableExplicitConnectionCloseHeader"; private const string AllowUnsignedToHeaderString = "Switch.System.ServiceModel.AllowUnsignedToHeader"; + private const string DisableCngCertificatesString = "Switch.System.ServiceModel.DisableCngCertificates"; private static int disableExplicitConnectionCloseHeader; private static int allowUnsignedToHeader; + private static int disableCngCertificates; public static bool DisableExplicitConnectionCloseHeader { @@ -36,10 +38,29 @@ namespace System.ServiceModel } } + public static bool DisableCngCertificates + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return LocalAppContext.GetCachedSwitchValue(DisableCngCertificatesString, ref disableCngCertificates); + } + } + public static void SetDefaultsLessOrEqual_452() { +#pragma warning disable BCL0012 // Define the switches that should be true for 4.5.2 or less, false for 4.6+. LocalAppContext.DefineSwitchDefault(DisableExplicitConnectionCloseHeaderString, true); +#pragma warning restore BCL0012 + } + + public static void SetDefaultsLessOrEqual_461() + { +#pragma warning disable BCL0012 + // Define the switches that should be true for 4.6.1 or less, false for 4.6.2+. + LocalAppContext.DefineSwitchDefault(DisableCngCertificatesString, true); +#pragma warning restore BCL0012 } } } diff --git a/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/OperationContext.cs b/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/OperationContext.cs index 0879498672..c08a1200cb 100644 --- a/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/OperationContext.cs +++ b/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/OperationContext.cs @@ -5,19 +5,21 @@ namespace System.ServiceModel { using System.Collections.Generic; - using System.ComponentModel; using System.Runtime; using System.Security.Claims; using System.Security.Principal; using System.ServiceModel.Channels; using System.ServiceModel.Dispatcher; using System.ServiceModel.Security; + using System.Threading; public sealed class OperationContext : IExtensibleObject { [ThreadStatic] static Holder currentContext; + static AsyncLocal currentAsyncLocalContext = new AsyncLocal(); + ServiceChannel channel; Message clientReply; bool closeClientReply; @@ -33,6 +35,7 @@ namespace System.ServiceModel MessageHeaders outgoingMessageHeaders; MessageVersion outgoingMessageVersion; EndpointDispatcher endpointDispatcher; + bool isAsyncFlowEnabled; public event EventHandler OperationCompleted; @@ -92,12 +95,19 @@ namespace System.ServiceModel { get { - return CurrentHolder.Context; + return ShouldUseAsyncLocalContext ? OperationContext.currentAsyncLocalContext.Value : CurrentHolder.Context; } set { - CurrentHolder.Context = value; + if (ShouldUseAsyncLocalContext) + { + OperationContext.currentAsyncLocalContext.Value = value; + } + else + { + CurrentHolder.Context = value; + } } } @@ -115,6 +125,14 @@ namespace System.ServiceModel } } + private static bool ShouldUseAsyncLocalContext + { + get + { + return CurrentHolder.Context == null && OperationContext.currentAsyncLocalContext.Value != null && OperationContext.currentAsyncLocalContext.Value.isAsyncFlowEnabled; + } + } + public EndpointDispatcher EndpointDispatcher { get @@ -339,6 +357,21 @@ namespace System.ServiceModel this.clientReply = null; } + internal static void EnableAsyncFlow() + { + CurrentHolder.Context.isAsyncFlowEnabled = true; + currentAsyncLocalContext.Value = CurrentHolder.Context; + } + + internal static void DisableAsyncFlow() + { + if (OperationContext.Current != null && OperationContext.Current.isAsyncFlowEnabled) + { + OperationContext.Current.isAsyncFlowEnabled = false; + currentAsyncLocalContext.Value = null; + } + } + internal void FireOperationCompleted() { try diff --git a/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/OperationContextScope.cs b/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/OperationContextScope.cs index 17da631e14..3d12f54c86 100644 --- a/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/OperationContextScope.cs +++ b/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/OperationContextScope.cs @@ -10,14 +10,12 @@ namespace System.ServiceModel public sealed class OperationContextScope : IDisposable { - [ThreadStatic] - static OperationContextScope currentScope; + static AsyncLocal currentScope = new AsyncLocal(); OperationContext currentContext; bool disposed; readonly OperationContext originalContext = OperationContext.Current; - readonly OperationContextScope originalScope = OperationContextScope.currentScope; - readonly Thread thread = Thread.CurrentThread; + readonly OperationContextScope originalScope = OperationContextScope.currentScope.Value; public OperationContextScope(IContextChannel channel) { @@ -41,22 +39,19 @@ namespace System.ServiceModel void PushContext(OperationContext context) { this.currentContext = context; - OperationContextScope.currentScope = this; + OperationContextScope.currentScope.Value = this; OperationContext.Current = this.currentContext; } void PopContext() { - if (this.thread != Thread.CurrentThread) - throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxInvalidContextScopeThread0))); - - if (OperationContextScope.currentScope != this) + if (OperationContextScope.currentScope.Value != this) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxInterleavedContextScopes0))); if (OperationContext.Current != this.currentContext) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxContextModifiedInsideScope0))); - OperationContextScope.currentScope = this.originalScope; + OperationContextScope.currentScope.Value = this.originalScope; OperationContext.Current = this.originalContext; if (this.currentContext != null) diff --git a/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Security/CryptoHelper.cs b/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Security/CryptoHelper.cs index ff0d508ecb..7c0b7a8cb2 100644 --- a/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Security/CryptoHelper.cs +++ b/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Security/CryptoHelper.cs @@ -17,6 +17,7 @@ namespace System.ServiceModel.Security using System.Text; using System.Xml; using System.Diagnostics; + using System.Diagnostics.CodeAnalysis; using System.Security.Cryptography; using Psha1DerivedKeyGenerator = System.IdentityModel.Psha1DerivedKeyGenerator; @@ -57,6 +58,7 @@ namespace System.ServiceModel.Security return CryptoHelper.CreateHashAlgorithm(SecurityAlgorithms.Sha256Digest); } + [SuppressMessage("Microsoft.Security.Cryptography", "CA5354:DoNotUseSHA1", Justification = "Cannot change. Required as SOAP spec requires supporting SHA1.")] internal static HashAlgorithm CreateHashAlgorithm(string digestMethod) { object algorithmObject = CryptoAlgorithms.GetAlgorithmFromConfig(digestMethod); @@ -86,6 +88,7 @@ namespace System.ServiceModel.Security } } + [SuppressMessage("Microsoft.Security.Cryptography", "CA5354:DoNotUseSHA1", Justification = "Cannot change. Required as SOAP spec requires supporting SHA1.")] internal static HashAlgorithm CreateHashForAsymmetricSignature(string signatureMethod) { object algorithmObject = CryptoAlgorithms.GetAlgorithmFromConfig(signatureMethod); diff --git a/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Security/SecurityUtils.cs b/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Security/SecurityUtils.cs deleted file mode 100644 index 913840d035..0000000000 --- a/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Security/SecurityUtils.cs +++ /dev/null @@ -1,2393 +0,0 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace System.ServiceModel.Security -{ - using System.Collections.Generic; - using System.Collections.ObjectModel; - using System.ComponentModel; - using System.Diagnostics; - using System.DirectoryServices.ActiveDirectory; - using System.Globalization; - using System.IdentityModel.Claims; - using System.IdentityModel.Policy; - using System.IdentityModel.Selectors; - using System.IdentityModel.Tokens; - using System.Net; - using System.Net.Security; - using System.Runtime; - using System.Security; - using System.Security.Authentication; - using System.Security.Authentication.ExtendedProtection; - using System.Security.Cryptography; - using System.Security.Cryptography.X509Certificates; - using System.Security.Permissions; - using System.Security.Principal; - using System.ServiceModel; - using System.ServiceModel.Channels; - using System.ServiceModel.Description; - using System.ServiceModel.Diagnostics; - using System.ServiceModel.Dispatcher; - using System.ServiceModel.Security.Tokens; - using System.Text; - using System.Threading; - using System.Xml; - using Microsoft.Win32; - using AuthIdentityEx = System.IdentityModel.AuthIdentityEx; - using CredentialUse = System.IdentityModel.CredentialUse; - using DictionaryManager = System.IdentityModel.DictionaryManager; - using SafeFreeCredentials = System.IdentityModel.SafeFreeCredentials; - using SspiWrapper = System.IdentityModel.SspiWrapper; - - static class StoreLocationHelper - { - internal static bool IsDefined(StoreLocation value) - { - return (value == StoreLocation.CurrentUser - || value == StoreLocation.LocalMachine); - } - } - - static class ProtectionLevelHelper - { - internal static bool IsDefined(ProtectionLevel value) - { - return (value == ProtectionLevel.None - || value == ProtectionLevel.Sign - || value == ProtectionLevel.EncryptAndSign); - } - - internal static void Validate(ProtectionLevel value) - { - if (!IsDefined(value)) - { - throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidEnumArgumentException("value", (int)value, - typeof(ProtectionLevel))); - } - } - - internal static bool IsStronger(ProtectionLevel v1, ProtectionLevel v2) - { - return ((v1 == ProtectionLevel.EncryptAndSign && v2 != ProtectionLevel.EncryptAndSign) - || (v1 == ProtectionLevel.Sign && v2 == ProtectionLevel.None)); - } - - internal static bool IsStrongerOrEqual(ProtectionLevel v1, ProtectionLevel v2) - { - return (v1 == ProtectionLevel.EncryptAndSign - || (v1 == ProtectionLevel.Sign && v2 != ProtectionLevel.EncryptAndSign)); - } - - internal static ProtectionLevel Max(ProtectionLevel v1, ProtectionLevel v2) - { - return IsStronger(v1, v2) ? v1 : v2; - } - - internal static int GetOrdinal(Nullable p) - { - if (p.HasValue) - { - switch ((ProtectionLevel)p) - { - default: - throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidEnumArgumentException("p", (int)p, - typeof(ProtectionLevel))); - case ProtectionLevel.None: - return 2; - case ProtectionLevel.Sign: - return 3; - case ProtectionLevel.EncryptAndSign: - return 4; - } - } - else - return 1; - } - } - - static class SslProtocolsHelper - { - internal static bool IsDefined(SslProtocols value) - { - SslProtocols allValues = SslProtocols.None; - foreach (var protocol in Enum.GetValues(typeof(SslProtocols))) - { - allValues |= (SslProtocols)protocol; - } - return (value & allValues) == value; - } - - internal static void Validate(SslProtocols value) - { - if (!IsDefined(value)) - { - throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidEnumArgumentException("value", (int)value, - typeof(SslProtocols))); - } - } - } - - static class TokenImpersonationLevelHelper - { - internal static bool IsDefined(TokenImpersonationLevel value) - { - return (value == TokenImpersonationLevel.None - || value == TokenImpersonationLevel.Anonymous - || value == TokenImpersonationLevel.Identification - || value == TokenImpersonationLevel.Impersonation - || value == TokenImpersonationLevel.Delegation); - } - - internal static void Validate(TokenImpersonationLevel value) - { - if (!IsDefined(value)) - { - throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidEnumArgumentException("value", (int)value, - typeof(TokenImpersonationLevel))); - } - } - - static TokenImpersonationLevel[] TokenImpersonationLevelOrder = new TokenImpersonationLevel[] - { - TokenImpersonationLevel.None, - TokenImpersonationLevel.Anonymous, - TokenImpersonationLevel.Identification, - TokenImpersonationLevel.Impersonation, - TokenImpersonationLevel.Delegation - }; - - internal static string ToString(TokenImpersonationLevel impersonationLevel) - { - if (impersonationLevel == TokenImpersonationLevel.Identification) - { - return "identification"; - } - else if (impersonationLevel == TokenImpersonationLevel.None) - { - return "none"; - } - else if (impersonationLevel == TokenImpersonationLevel.Anonymous) - { - return "anonymous"; - } - else if (impersonationLevel == TokenImpersonationLevel.Impersonation) - { - return "impersonation"; - } - else if (impersonationLevel == TokenImpersonationLevel.Delegation) - { - return "delegation"; - } - - Fx.Assert("unknown token impersonation level"); - throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidEnumArgumentException("impersonationLevel", (int)impersonationLevel, - typeof(TokenImpersonationLevel))); - } - - internal static bool IsGreaterOrEqual(TokenImpersonationLevel x, TokenImpersonationLevel y) - { - TokenImpersonationLevelHelper.Validate(x); - TokenImpersonationLevelHelper.Validate(y); - - if (x == y) - return true; - - int px = 0; - int py = 0; - for (int i = 0; i < TokenImpersonationLevelOrder.Length; i++) - { - if (x == TokenImpersonationLevelOrder[i]) - px = i; - if (y == TokenImpersonationLevelOrder[i]) - py = i; - } - - return (px > py); - } - - internal static int Compare(TokenImpersonationLevel x, TokenImpersonationLevel y) - { - int result = 0; - - if (x != y) - { - switch (x) - { - case TokenImpersonationLevel.Identification: - result = -1; - break; - case TokenImpersonationLevel.Impersonation: - switch (y) - { - case TokenImpersonationLevel.Identification: - result = 1; - break; - case TokenImpersonationLevel.Delegation: - result = -1; - break; - default: - throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidEnumArgumentException("y", (int)y, - typeof(TokenImpersonationLevel))); - - } - break; - case TokenImpersonationLevel.Delegation: - result = 1; - break; - default: - throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidEnumArgumentException("x", (int)x, - typeof(TokenImpersonationLevel))); - - } - } - - return result; - } - } - - internal class ServiceModelDictionaryManager - { - static DictionaryManager dictionaryManager; - - public static DictionaryManager Instance - { - get - { - if (dictionaryManager == null) - dictionaryManager = new DictionaryManager(BinaryMessageEncoderFactory.XmlDictionary); - - return dictionaryManager; - } - } - } - - static class SecurityUtils - { - public const string Principal = "Principal"; - public const string Identities = "Identities"; - static bool computedDomain; - static string currentDomain; - static byte[] combinedHashLabel; - static IIdentity anonymousIdentity; - static NetworkCredential dummyNetworkCredential; - static object dummyNetworkCredentialLock = new object(); - static X509SecurityTokenAuthenticator nonValidatingX509Authenticator; - static SecurityIdentifier administratorsSid; - const int WindowsServerMajorNumber = 5; - const int WindowsServerMinorNumber = 2; - const int XPMajorNumber = 5; - const int XPMinorNumber = 1; - const string ServicePack1 = "Service Pack 1"; - const string ServicePack2 = "Service Pack 2"; - volatile static bool shouldValidateSslCipherStrength; - volatile static bool isSslValidationRequirementDetermined = false; - static readonly int MinimumSslCipherStrength = 128; - - // these are kept in [....] with IIS70 - public const string AuthTypeNTLM = "NTLM"; - public const string AuthTypeNegotiate = "Negotiate"; - public const string AuthTypeKerberos = "Kerberos"; - public const string AuthTypeAnonymous = ""; - public const string AuthTypeCertMap = "SSL/PCT"; // mapped from a cert - public const string AuthTypeBasic = "Basic"; //LogonUser - - public static ChannelBinding GetChannelBindingFromMessage(Message message) - { - if (message == null) - { - return null; - } - - ChannelBindingMessageProperty channelBindingMessageProperty = null; - ChannelBindingMessageProperty.TryGet(message, out channelBindingMessageProperty); - ChannelBinding channelBinding = null; - - if (channelBindingMessageProperty != null) - { - channelBinding = channelBindingMessageProperty.ChannelBinding; - } - - return channelBinding; - } - - internal static bool IsOsGreaterThanXP() - { - return ((Environment.OSVersion.Version.Major >= SecurityUtils.XPMajorNumber && Environment.OSVersion.Version.Minor > SecurityUtils.XPMinorNumber) || - Environment.OSVersion.Version.Major > SecurityUtils.XPMajorNumber); - } - - internal static bool IsOSGreaterThanOrEqualToWin7() - { - Version windows7Version = new Version(6, 1, 0, 0); - return (Environment.OSVersion.Version.Major >= windows7Version.Major && Environment.OSVersion.Version.Minor >= windows7Version.Minor); - } - - internal static bool IsCurrentlyTimeEffective(DateTime effectiveTime, DateTime expirationTime, TimeSpan maxClockSkew) - { - DateTime curEffectiveTime = (effectiveTime < DateTime.MinValue.Add(maxClockSkew)) ? effectiveTime : effectiveTime.Subtract(maxClockSkew); - DateTime curExpirationTime = (expirationTime > DateTime.MaxValue.Subtract(maxClockSkew)) ? expirationTime : expirationTime.Add(maxClockSkew); - DateTime curTime = DateTime.UtcNow; - - return (curEffectiveTime.ToUniversalTime() <= curTime) && (curTime < curExpirationTime.ToUniversalTime()); - } - - internal static X509SecurityTokenAuthenticator NonValidatingX509Authenticator - { - get - { - if (nonValidatingX509Authenticator == null) - { - nonValidatingX509Authenticator = new X509SecurityTokenAuthenticator(X509CertificateValidator.None); - } - return nonValidatingX509Authenticator; - } - } - - public static SecurityIdentifier AdministratorsSid - { - get - { - if (administratorsSid == null) - administratorsSid = new SecurityIdentifier(WellKnownSidType.BuiltinAdministratorsSid, null); - return administratorsSid; - } - } - - internal static IIdentity AnonymousIdentity - { - get - { - if (anonymousIdentity == null) - { - anonymousIdentity = SecurityUtils.CreateIdentity(String.Empty); - } - return anonymousIdentity; - } - } - - public static DateTime MaxUtcDateTime - { - get - { - // + and - TimeSpan.TicksPerDay is to compensate the DateTime.ParseExact (to localtime) overflow. - return new DateTime(DateTime.MaxValue.Ticks - TimeSpan.TicksPerDay, DateTimeKind.Utc); - } - } - - public static DateTime MinUtcDateTime - { - get - { - // + and - TimeSpan.TicksPerDay is to compensate the DateTime.ParseExact (to localtime) overflow. - return new DateTime(DateTime.MinValue.Ticks + TimeSpan.TicksPerDay, DateTimeKind.Utc); - } - } - - internal static IIdentity CreateIdentity(string name, string authenticationType) - { - return new GenericIdentity(name, authenticationType); - } - - internal static IIdentity CreateIdentity(string name) - { - return new GenericIdentity(name); - } - - internal static EndpointIdentity CreateWindowsIdentity() - { - return CreateWindowsIdentity(false); - } - - internal static EndpointIdentity CreateWindowsIdentity(NetworkCredential serverCredential) - { - if (serverCredential != null && !NetworkCredentialHelper.IsDefault(serverCredential)) - { - string upn; - if (serverCredential.Domain != null && serverCredential.Domain.Length > 0) - { - upn = serverCredential.UserName + "@" + serverCredential.Domain; - } - else - { - upn = serverCredential.UserName; - } - return EndpointIdentity.CreateUpnIdentity(upn); - } - else - { - return SecurityUtils.CreateWindowsIdentity(); - } - } - - static bool IsSystemAccount(WindowsIdentity self) - { - SecurityIdentifier sid = self.User; - if (sid == null) - { - return false; - } - // S-1-5-82 is the prefix for the sid that represents the identity that IIS 7.5 Apppool thread runs under. - return (sid.IsWellKnown(WellKnownSidType.LocalSystemSid) - || sid.IsWellKnown(WellKnownSidType.NetworkServiceSid) - || sid.IsWellKnown(WellKnownSidType.LocalServiceSid) - || self.User.Value.StartsWith("S-1-5-82", StringComparison.OrdinalIgnoreCase)); - } - - internal static EndpointIdentity CreateWindowsIdentity(bool spnOnly) - { - EndpointIdentity identity = null; - using (WindowsIdentity self = WindowsIdentity.GetCurrent()) - { - bool isSystemAccount = IsSystemAccount(self); - if (spnOnly || isSystemAccount) - { - identity = EndpointIdentity.CreateSpnIdentity(String.Format(CultureInfo.InvariantCulture, "host/{0}", DnsCache.MachineName)); - } - else - { - // Save windowsIdentity for delay lookup - identity = new UpnEndpointIdentity(CloneWindowsIdentityIfNecessary(self)); - } - } - - return identity; - } - - [Fx.Tag.SecurityNote(Critical = "Calls two critical methods: UnsafeGetWindowsIdentityToken and UnsafeCreateWindowsIdentityFromToken.", - Safe = "'Clone' operation is considered safe despite using WindowsIdentity IntPtr token. Must not let IntPtr token leak in or out.")] - [SecuritySafeCritical] - internal static WindowsIdentity CloneWindowsIdentityIfNecessary(WindowsIdentity wid) - { - return SecurityUtils.CloneWindowsIdentityIfNecessary(wid, null); - } - - [Fx.Tag.SecurityNote(Critical = "Calls two critical methods: UnsafeGetWindowsIdentityToken and UnsafeCreateWindowsIdentityFromToken.", - Safe = "'Clone' operation is considered safe despite using WindowsIdentity IntPtr token. Must not let IntPtr token leak in or out.")] - [SecuritySafeCritical] - internal static WindowsIdentity CloneWindowsIdentityIfNecessary(WindowsIdentity wid, string authType) - { - if (wid != null) - { - IntPtr token = UnsafeGetWindowsIdentityToken(wid); - if (token != IntPtr.Zero) - { - return UnsafeCreateWindowsIdentityFromToken(token, authType); - } - } - return wid; - } - - [Fx.Tag.SecurityNote(Critical = "Elevates in order to return the WindowsIdentity.Token property, caller must protect return value.")] - [SecurityCritical] - [SecurityPermission(SecurityAction.Assert, UnmanagedCode = true)] - static IntPtr UnsafeGetWindowsIdentityToken(WindowsIdentity wid) - { - return wid.Token; - } - - [Fx.Tag.SecurityNote(Critical = "Elevates in order to return the SecurityIdentifier of the current user as a string, caller must protect return value.")] - [SecurityCritical] - [SecurityPermission(SecurityAction.Assert, Flags = SecurityPermissionFlag.ControlPrincipal)] - static string UnsafeGetCurrentUserSidAsString() - { - using (WindowsIdentity self = WindowsIdentity.GetCurrent()) - { - return self.User.Value; - } - } - - [Fx.Tag.SecurityNote(Critical = "Elevates in order to return the WindowsIdentity.Token property, caller must protect return value.")] - [SecurityCritical] - [SecurityPermission(SecurityAction.Assert, ControlPrincipal = true, UnmanagedCode = true)] - static WindowsIdentity UnsafeCreateWindowsIdentityFromToken(IntPtr token, string authType) - { - if (authType != null) - return new WindowsIdentity(token, authType); - else - return new WindowsIdentity(token); - } - - internal static bool AllowsImpersonation(WindowsIdentity windowsIdentity, TokenImpersonationLevel impersonationLevel) - { - if (windowsIdentity == null) - throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("windowsIdentity"); - - TokenImpersonationLevelHelper.Validate(impersonationLevel); - - if (impersonationLevel == TokenImpersonationLevel.Identification) - throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("impersonationLevel")); - - bool result = true; - - switch (windowsIdentity.ImpersonationLevel) - { - case TokenImpersonationLevel.None: - case TokenImpersonationLevel.Anonymous: - case TokenImpersonationLevel.Identification: - result = false; break; - case TokenImpersonationLevel.Impersonation: - if (impersonationLevel == TokenImpersonationLevel.Delegation) - result = false; - break; - case TokenImpersonationLevel.Delegation: - break; - default: - result = false; - break; - } - - return result; - } - - internal static byte[] CombinedHashLabel - { - get - { - if (combinedHashLabel == null) - combinedHashLabel = Encoding.UTF8.GetBytes(TrustApr2004Strings.CombinedHashLabel); - return combinedHashLabel; - } - } - - internal static T GetSecurityKey(SecurityToken token) - where T : SecurityKey - { - T result = null; - if (token.SecurityKeys != null) - { - for (int i = 0; i < token.SecurityKeys.Count; ++i) - { - T temp = (token.SecurityKeys[i] as T); - if (temp != null) - { - if (result != null) - { - throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new MessageSecurityException(SR.GetString(SR.MultipleMatchingCryptosFound, typeof(T).ToString()))); - } - else - { - result = temp; - } - } - } - } - return result; - } - - internal static bool HasSymmetricSecurityKey(SecurityToken token) - { - return GetSecurityKey(token) != null; - } - - internal static void EnsureExpectedSymmetricMatch(SecurityToken t1, SecurityToken t2, Message message) - { - // nulls are not mismatches - if (t1 == null || t2 == null || ReferenceEquals(t1, t2)) - { - return; - } - // check for interop flexibility - SymmetricSecurityKey c1 = SecurityUtils.GetSecurityKey(t1); - SymmetricSecurityKey c2 = SecurityUtils.GetSecurityKey(t2); - if (c1 == null || c2 == null || !CryptoHelper.IsEqual(c1.GetSymmetricKey(), c2.GetSymmetricKey())) - { - throw System.ServiceModel.Diagnostics.TraceUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.TokenNotExpectedInSecurityHeader, t2)), message); - } - } - - internal static SymmetricAlgorithm GetSymmetricAlgorithm(string algorithm, SecurityToken token) - { - SymmetricSecurityKey securityKey = SecurityUtils.GetSecurityKey(token); - if (securityKey != null && securityKey.IsSupportedAlgorithm(algorithm)) - { - return securityKey.GetSymmetricAlgorithm(algorithm); - } - else - { - return null; - } - } - - internal static KeyedHashAlgorithm GetKeyedHashAlgorithm(string algorithm, SecurityToken token) - { - SymmetricSecurityKey securityKey = SecurityUtils.GetSecurityKey(token); - if (securityKey != null && securityKey.IsSupportedAlgorithm(algorithm)) - { - return securityKey.GetKeyedHashAlgorithm(algorithm); - } - else - { - return null; - } - } - - internal static ReadOnlyCollection CreateSymmetricSecurityKeys(byte[] key) - { - List temp = new List(1); - temp.Add(new InMemorySymmetricSecurityKey(key)); - return temp.AsReadOnly(); - } - - internal static byte[] DecryptKey(SecurityToken unwrappingToken, string encryptionMethod, byte[] wrappedKey, out SecurityKey unwrappingSecurityKey) - { - unwrappingSecurityKey = null; - if (unwrappingToken.SecurityKeys != null) - { - for (int i = 0; i < unwrappingToken.SecurityKeys.Count; ++i) - { - if (unwrappingToken.SecurityKeys[i].IsSupportedAlgorithm(encryptionMethod)) - { - unwrappingSecurityKey = unwrappingToken.SecurityKeys[i]; - break; - } - } - } - if (unwrappingSecurityKey == null) - { - throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new MessageSecurityException(SR.GetString(SR.CannotFindMatchingCrypto, encryptionMethod))); - } - return unwrappingSecurityKey.DecryptKey(encryptionMethod, wrappedKey); - } - - internal static byte[] EncryptKey(SecurityToken wrappingToken, string encryptionMethod, byte[] keyToWrap) - { - SecurityKey wrappingSecurityKey = null; - if (wrappingToken.SecurityKeys != null) - { - for (int i = 0; i < wrappingToken.SecurityKeys.Count; ++i) - { - if (wrappingToken.SecurityKeys[i].IsSupportedAlgorithm(encryptionMethod)) - { - wrappingSecurityKey = wrappingToken.SecurityKeys[i]; - break; - } - } - } - if (wrappingSecurityKey == null) - { - throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(SR.GetString(SR.CannotFindMatchingCrypto, encryptionMethod)); - } - return wrappingSecurityKey.EncryptKey(encryptionMethod, keyToWrap); - } - - internal static byte[] ReadContentAsBase64(XmlDictionaryReader reader, long maxBufferSize) - { - if (reader == null) - throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader"); - - // Code cloned from System.Xml.XmlDictionaryReder. - byte[][] buffers = new byte[32][]; - byte[] buffer; - // Its best to read in buffers that are a multiple of 3 so we don't break base64 boundaries when converting text - int count = 384; - int bufferCount = 0; - int totalRead = 0; - while (true) - { - buffer = new byte[count]; - buffers[bufferCount++] = buffer; - int read = 0; - while (read < buffer.Length) - { - int actual = reader.ReadContentAsBase64(buffer, read, buffer.Length - read); - if (actual == 0) - break; - read += actual; - } - if (totalRead > maxBufferSize - read) - throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new QuotaExceededException(SR.GetString(SR.BufferQuotaExceededReadingBase64, maxBufferSize))); - totalRead += read; - if (read < buffer.Length) - break; - count = count * 2; - } - buffer = new byte[totalRead]; - int offset = 0; - for (int i = 0; i < bufferCount - 1; i++) - { - Buffer.BlockCopy(buffers[i], 0, buffer, offset, buffers[i].Length); - offset += buffers[i].Length; - } - Buffer.BlockCopy(buffers[bufferCount - 1], 0, buffer, offset, totalRead - offset); - return buffer; - } - - internal static byte[] GenerateDerivedKey(SecurityToken tokenToDerive, string derivationAlgorithm, byte[] label, byte[] nonce, - int keySize, int offset) - { - SymmetricSecurityKey symmetricSecurityKey = SecurityUtils.GetSecurityKey(tokenToDerive); - if (symmetricSecurityKey == null || !symmetricSecurityKey.IsSupportedAlgorithm(derivationAlgorithm)) - { - throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new MessageSecurityException(SR.GetString(SR.CannotFindMatchingCrypto, derivationAlgorithm))); - } - return symmetricSecurityKey.GenerateDerivedKey(derivationAlgorithm, label, nonce, keySize, offset); - } - - internal static string GetSpnFromIdentity(EndpointIdentity identity, EndpointAddress target) - { - bool foundSpn = false; - string spn = null; - if (identity != null) - { - if (ClaimTypes.Spn.Equals(identity.IdentityClaim.ClaimType)) - { - spn = (string)identity.IdentityClaim.Resource; - foundSpn = true; - } - else if (ClaimTypes.Upn.Equals(identity.IdentityClaim.ClaimType)) - { - spn = (string)identity.IdentityClaim.Resource; - foundSpn = true; - } - else if (ClaimTypes.Dns.Equals(identity.IdentityClaim.ClaimType)) - { - spn = String.Format(CultureInfo.InvariantCulture, "host/{0}", (string)identity.IdentityClaim.Resource); - foundSpn = true; - } - } - if (!foundSpn) - { - throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.CannotDetermineSPNBasedOnAddress, target))); - } - return spn; - } - - internal static string GetSpnFromTarget(EndpointAddress target) - { - if (target == null) - { - throw Fx.AssertAndThrow("target should not be null - expecting an EndpointAddress"); - } - - return string.Format(CultureInfo.InvariantCulture, "host/{0}", target.Uri.DnsSafeHost); - } - - internal static bool IsSupportedAlgorithm(string algorithm, SecurityToken token) - { - if (token.SecurityKeys == null) - { - return false; - } - for (int i = 0; i < token.SecurityKeys.Count; ++i) - { - if (token.SecurityKeys[i].IsSupportedAlgorithm(algorithm)) - { - return true; - } - } - return false; - } - - internal static Claim GetPrimaryIdentityClaim(ReadOnlyCollection authorizationPolicies) - { - return GetPrimaryIdentityClaim(AuthorizationContext.CreateDefaultAuthorizationContext(authorizationPolicies)); - } - - internal static Claim GetPrimaryIdentityClaim(AuthorizationContext authContext) - { - if (authContext != null) - { - for (int i = 0; i < authContext.ClaimSets.Count; ++i) - { - ClaimSet claimSet = authContext.ClaimSets[i]; - foreach (Claim claim in claimSet.FindClaims(null, Rights.Identity)) - { - return claim; - } - } - } - return null; - } - - internal static int GetServiceAddressAndViaHash(EndpointAddress sr) - { - if (sr == null) - { - throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("sr"); - } - return sr.GetHashCode(); - } - - internal static string GenerateId() - { - return SecurityUniqueId.Create().Value; - } - - internal static string GenerateIdWithPrefix(string prefix) - { - return SecurityUniqueId.Create(prefix).Value; - } - - internal static UniqueId GenerateUniqueId() - { - return new UniqueId(); - } - - internal static string GetPrimaryDomain() - { - using (WindowsIdentity wid = WindowsIdentity.GetCurrent()) - { - return GetPrimaryDomain(IsSystemAccount(wid)); - } - } - - internal static string GetPrimaryDomain(bool isSystemAccount) - { - if (computedDomain == false) - { - try - { - if (isSystemAccount) - { - currentDomain = Domain.GetComputerDomain().Name; - } - else - { - currentDomain = Domain.GetCurrentDomain().Name; - } - } -#pragma warning suppress 56500 // covered by FxCOP - catch (Exception e) - { - if (Fx.IsFatal(e)) - { - throw; - } - DiagnosticUtility.TraceHandledException(e, TraceEventType.Warning); - } - finally - { - computedDomain = true; - } - } - return currentDomain; - } - - internal static void EnsureCertificateCanDoKeyExchange(X509Certificate2 certificate) - { - if (certificate == null) - { - throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("certificate"); - } - bool canDoKeyExchange = false; - Exception innerException = null; - if (certificate.HasPrivateKey) - { - try - { - canDoKeyExchange = CanKeyDoKeyExchange(certificate); - } - // exceptions can be due to ACLs on the key etc - catch (System.Security.SecurityException e) - { - innerException = e; - } - catch (CryptographicException e) - { - innerException = e; - } - } - if (!canDoKeyExchange) - { - throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.SslCertMayNotDoKeyExchange, certificate.SubjectName.Name), innerException)); - } - } - - [Fx.Tag.SecurityNote(Critical = "Calls critical method GetKeyContainerInfo.", - Safe = "Info is not leaked.")] - [SecuritySafeCritical] - static bool CanKeyDoKeyExchange(X509Certificate2 certificate) - { - CspKeyContainerInfo info = GetKeyContainerInfo(certificate); - return info != null && info.KeyNumber == KeyNumber.Exchange; - } - - [Fx.Tag.SecurityNote(Critical = "Elevates to call properties: X509Certificate2.PrivateKey and CspKeyContainerInfo. Caller must protect the return value.")] - [SecurityCritical] - [KeyContainerPermission(SecurityAction.Assert, Flags = KeyContainerPermissionFlags.Open)] - static CspKeyContainerInfo GetKeyContainerInfo(X509Certificate2 certificate) - { - RSACryptoServiceProvider rsa = certificate.PrivateKey as RSACryptoServiceProvider; - if (rsa != null) - { - return rsa.CspKeyContainerInfo; - } - - return null; - } - - internal static string GetCertificateId(X509Certificate2 certificate) - { - StringBuilder str = new StringBuilder(256); - AppendCertificateIdentityName(str, certificate); - return str.ToString(); - } - - internal static ReadOnlyCollection CreatePrincipalNameAuthorizationPolicies(string principalName) - { - if (principalName == null) - throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("principalName"); - - Claim identityClaim; - Claim primaryPrincipal; - if (principalName.Contains("@") || principalName.Contains(@"\")) - { - identityClaim = new Claim(ClaimTypes.Upn, principalName, Rights.Identity); - primaryPrincipal = Claim.CreateUpnClaim(principalName); - } - else - { - identityClaim = new Claim(ClaimTypes.Spn, principalName, Rights.Identity); - primaryPrincipal = Claim.CreateSpnClaim(principalName); - } - - List claims = new List(2); - claims.Add(identityClaim); - claims.Add(primaryPrincipal); - - List policies = new List(1); - policies.Add(new UnconditionalPolicy(SecurityUtils.CreateIdentity(principalName), new DefaultClaimSet(ClaimSet.Anonymous, claims))); - return policies.AsReadOnly(); - } - - internal static string GetIdentityNamesFromPolicies(IList authPolicies) - { - return GetIdentityNamesFromContext(AuthorizationContext.CreateDefaultAuthorizationContext(authPolicies)); - } - - internal static string GetIdentityNamesFromContext(AuthorizationContext authContext) - { - if (authContext == null) - return String.Empty; - - StringBuilder str = new StringBuilder(256); - for (int i = 0; i < authContext.ClaimSets.Count; ++i) - { - ClaimSet claimSet = authContext.ClaimSets[i]; - - // Windows - WindowsClaimSet windows = claimSet as WindowsClaimSet; - if (windows != null) - { - if (str.Length > 0) - str.Append(", "); - - AppendIdentityName(str, windows.WindowsIdentity); - } - else - { - // X509 - X509CertificateClaimSet x509 = claimSet as X509CertificateClaimSet; - if (x509 != null) - { - if (str.Length > 0) - str.Append(", "); - - AppendCertificateIdentityName(str, x509.X509Certificate); - } - } - } - - if (str.Length <= 0) - { - List identities = null; - object obj; - if (authContext.Properties.TryGetValue(SecurityUtils.Identities, out obj)) - { - identities = obj as List; - } - if (identities != null) - { - for (int i = 0; i < identities.Count; ++i) - { - IIdentity identity = identities[i]; - if (identity != null) - { - if (str.Length > 0) - str.Append(", "); - - AppendIdentityName(str, identity); - } - } - } - } - return str.Length <= 0 ? String.Empty : str.ToString(); - } - - internal static void AppendCertificateIdentityName(StringBuilder str, X509Certificate2 certificate) - { - string value = certificate.SubjectName.Name; - if (String.IsNullOrEmpty(value)) - { - value = certificate.GetNameInfo(X509NameType.DnsName, false); - if (String.IsNullOrEmpty(value)) - { - value = certificate.GetNameInfo(X509NameType.SimpleName, false); - if (String.IsNullOrEmpty(value)) - { - value = certificate.GetNameInfo(X509NameType.EmailName, false); - if (String.IsNullOrEmpty(value)) - { - value = certificate.GetNameInfo(X509NameType.UpnName, false); - } - } - } - } - // Same format as X509Identity - str.Append(String.IsNullOrEmpty(value) ? "" : value); - str.Append("; "); - str.Append(certificate.Thumbprint); - } - - internal static void AppendIdentityName(StringBuilder str, IIdentity identity) - { - string name = null; - try - { - name = identity.Name; - } -#pragma warning suppress 56500 - catch (Exception e) - { - if (Fx.IsFatal(e)) - { - throw; - } - // suppress exception, this is just info. - } - - str.Append(String.IsNullOrEmpty(name) ? "" : name); - - WindowsIdentity windows = identity as WindowsIdentity; - if (windows != null) - { - if (windows.User != null) - { - str.Append("; "); - str.Append(windows.User.ToString()); - } - } - else - { - WindowsSidIdentity sid = identity as WindowsSidIdentity; - if (sid != null) - { - str.Append("; "); - str.Append(sid.SecurityIdentifier.ToString()); - } - } - } - - [Fx.Tag.SecurityNote(Critical = "Calls critical methods UnsafeGetDomain, UnsafeGetUserName, UnsafeGetPassword and UnsafeGetCurrentUserSidAsString.")] - [SecurityCritical] - internal static string AppendWindowsAuthenticationInfo(string inputString, NetworkCredential credential, - AuthenticationLevel authenticationLevel, TokenImpersonationLevel impersonationLevel) - { - const string delimiter = "\0"; // nonprintable characters are invalid for SSPI Domain/UserName/Password - - if (IsDefaultNetworkCredential(credential)) - { - string sid = UnsafeGetCurrentUserSidAsString(); - return string.Concat(inputString, delimiter, - sid, delimiter, - AuthenticationLevelHelper.ToString(authenticationLevel), delimiter, - TokenImpersonationLevelHelper.ToString(impersonationLevel)); - } - else - { - return string.Concat(inputString, delimiter, - NetworkCredentialHelper.UnsafeGetDomain(credential), delimiter, - NetworkCredentialHelper.UnsafeGetUsername(credential), delimiter, - NetworkCredentialHelper.UnsafeGetPassword(credential), delimiter, - AuthenticationLevelHelper.ToString(authenticationLevel), delimiter, - TokenImpersonationLevelHelper.ToString(impersonationLevel)); - } - } - - internal static string GetIdentityName(IIdentity identity) - { - StringBuilder str = new StringBuilder(256); - AppendIdentityName(str, identity); - return str.ToString(); - } - - /// - /// Critical - Calls an UnsafeNativeMethod and a Critical method (GetFipsAlgorithmPolicyKeyFromRegistry) - /// Safe - processes the return and just returns a bool, which is safe - /// - internal static bool IsChannelBindingDisabled - { - [SecuritySafeCritical] - get - { - return ((GetSuppressChannelBindingValue() & 0x1) != 0); - } - } - - const string suppressChannelBindingRegistryKey = @"System\CurrentControlSet\Control\Lsa"; - - /// - /// Critical - Asserts to get a value from the registry - /// - [SecurityCritical] - [RegistryPermission(SecurityAction.Assert, Read = @"HKEY_LOCAL_MACHINE\" + suppressChannelBindingRegistryKey)] - internal static int GetSuppressChannelBindingValue() - { - int channelBindingPolicyKeyValue = 0; - - try - { - using (RegistryKey channelBindingPolicyKey = Registry.LocalMachine.OpenSubKey(suppressChannelBindingRegistryKey, false)) - { - if (channelBindingPolicyKey != null) - { - object data = channelBindingPolicyKey.GetValue("SuppressChannelBindingInfo"); - if (data != null) - channelBindingPolicyKeyValue = (int)data; - } - } - } -#pragma warning suppress 56500 - catch (Exception e) - { - if (Fx.IsFatal(e)) - throw; - } - - return channelBindingPolicyKeyValue; - } - - internal static bool IsSecurityBindingSuitableForChannelBinding(TransportSecurityBindingElement securityBindingElement) - { - if (securityBindingElement == null) - { - return false; - } - - // channel binding of OperationSupportingTokenParameters, OptionalEndpointSupportingTokenParameters, or OptionalOperationSupportingTokenParameters - // is not supported in Win7 - if (AreSecurityTokenParametersSuitableForChannelBinding(securityBindingElement.EndpointSupportingTokenParameters.Endorsing)) - { - return true; - } - - if (AreSecurityTokenParametersSuitableForChannelBinding(securityBindingElement.EndpointSupportingTokenParameters.Signed)) - { - return true; - } - - if (AreSecurityTokenParametersSuitableForChannelBinding(securityBindingElement.EndpointSupportingTokenParameters.SignedEncrypted)) - { - return true; - } - - if (AreSecurityTokenParametersSuitableForChannelBinding(securityBindingElement.EndpointSupportingTokenParameters.SignedEndorsing)) - { - return true; - } - - return false; - } - - internal static bool AreSecurityTokenParametersSuitableForChannelBinding(Collection tokenParameters) - { - if (tokenParameters == null) - { - return false; - } - - foreach (SecurityTokenParameters stp in tokenParameters) - { - if (stp is SspiSecurityTokenParameters || stp is KerberosSecurityTokenParameters) - { - return true; - } - - SecureConversationSecurityTokenParameters scstp = stp as SecureConversationSecurityTokenParameters; - if (scstp != null) - { - return IsSecurityBindingSuitableForChannelBinding(scstp.BootstrapSecurityBindingElement as TransportSecurityBindingElement); - } - } - - return false; - } - - internal static void ThrowIfNegotiationFault(Message message, EndpointAddress target) - { - if (message.IsFault) - { - MessageFault fault = MessageFault.CreateFault(message, TransportDefaults.MaxSecurityFaultSize); - Exception faultException = new FaultException(fault, message.Headers.Action); - if (fault.Code != null && fault.Code.IsReceiverFault && fault.Code.SubCode != null) - { - FaultCode subCode = fault.Code.SubCode; - if (subCode.Name == DotNetSecurityStrings.SecurityServerTooBusyFault && subCode.Namespace == DotNetSecurityStrings.Namespace) - { - throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ServerTooBusyException(SR.GetString(SR.SecurityServerTooBusy, target), faultException)); - } - else if (subCode.Name == AddressingStrings.EndpointUnavailable && subCode.Namespace == message.Version.Addressing.Namespace) - { - throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new EndpointNotFoundException(SR.GetString(SR.SecurityEndpointNotFound, target), faultException)); - } - } - throw TraceUtility.ThrowHelperError(faultException, message); - } - } - - internal static bool IsSecurityFault(MessageFault fault, SecurityStandardsManager standardsManager) - { - if (fault.Code.IsSenderFault) - { - FaultCode subCode = fault.Code.SubCode; - if (subCode != null) - { - return (subCode.Namespace == standardsManager.SecurityVersion.HeaderNamespace.Value - || subCode.Namespace == standardsManager.SecureConversationDriver.Namespace.Value - || subCode.Namespace == standardsManager.TrustDriver.Namespace.Value - || subCode.Namespace == DotNetSecurityStrings.Namespace); - } - } - return false; - } - - internal static Exception CreateSecurityFaultException(Message unverifiedMessage) - { - MessageFault fault = MessageFault.CreateFault(unverifiedMessage, TransportDefaults.MaxSecurityFaultSize); - return CreateSecurityFaultException(fault); - } - - internal static Exception CreateSecurityFaultException(MessageFault fault) - { - FaultException faultException = FaultException.CreateFault(fault, typeof(string), typeof(object)); - return new MessageSecurityException(SR.GetString(SR.UnsecuredMessageFaultReceived), faultException); - } - - internal static MessageFault CreateSecurityContextNotFoundFault(SecurityStandardsManager standardsManager, string action) - { - SecureConversationDriver scDriver = standardsManager.SecureConversationDriver; - FaultCode subCode = new FaultCode(scDriver.BadContextTokenFaultCode.Value, scDriver.Namespace.Value); - FaultReason reason; - if (action != null) - { - reason = new FaultReason(SR.GetString(SR.BadContextTokenOrActionFaultReason, action), CultureInfo.CurrentCulture); - } - else - { - reason = new FaultReason(SR.GetString(SR.BadContextTokenFaultReason), CultureInfo.CurrentCulture); - } - FaultCode senderCode = FaultCode.CreateSenderFaultCode(subCode); - return MessageFault.CreateFault(senderCode, reason); - } - - internal static MessageFault CreateSecurityMessageFault(Exception e, SecurityStandardsManager standardsManager) - { - bool isSecurityError = false; - bool isTokenValidationError = false; - bool isGenericTokenError = false; - FaultException faultException = null; - while (e != null) - { - if (e is SecurityTokenValidationException) - { - if (e is SecurityContextTokenValidationException) - { - return CreateSecurityContextNotFoundFault(SecurityStandardsManager.DefaultInstance, null); - } - isSecurityError = true; - isTokenValidationError = true; - break; - } - else if (e is SecurityTokenException) - { - isSecurityError = true; - isGenericTokenError = true; - break; - } - else if (e is MessageSecurityException) - { - MessageSecurityException ms = (MessageSecurityException)e; - if (ms.Fault != null) - { - return ms.Fault; - } - isSecurityError = true; - } - else if (e is FaultException) - { - faultException = (FaultException)e; - break; - } - e = e.InnerException; - } - if (!isSecurityError && faultException == null) - { - return null; - } - FaultCode subCode; - FaultReason reason; - SecurityVersion wss = standardsManager.SecurityVersion; - if (isTokenValidationError) - { - subCode = new FaultCode(wss.FailedAuthenticationFaultCode.Value, wss.HeaderNamespace.Value); - reason = new FaultReason(SR.GetString(SR.FailedAuthenticationFaultReason), CultureInfo.CurrentCulture); - } - else if (isGenericTokenError) - { - subCode = new FaultCode(wss.InvalidSecurityTokenFaultCode.Value, wss.HeaderNamespace.Value); - reason = new FaultReason(SR.GetString(SR.InvalidSecurityTokenFaultReason), CultureInfo.CurrentCulture); - } - else if (faultException != null) - { - // Only support Code and Reason. No detail or action customization. - return MessageFault.CreateFault(faultException.Code, faultException.Reason); - } - else - { - subCode = new FaultCode(wss.InvalidSecurityFaultCode.Value, wss.HeaderNamespace.Value); - reason = new FaultReason(SR.GetString(SR.InvalidSecurityFaultReason), CultureInfo.CurrentCulture); - } - FaultCode senderCode = FaultCode.CreateSenderFaultCode(subCode); - return MessageFault.CreateFault(senderCode, reason); - } - - internal static bool IsCompositeDuplexBinding(BindingContext context) - { - return ((context.Binding.Elements.Find() != null) - || (context.Binding.Elements.Find() != null)); - } - - // The method checks TransportToken, ProtectionToken and all SupportingTokens to find a - // UserNameSecurityToken. If found, it sets the password of the UserNameSecurityToken to null. - // Custom UserNameSecurityToken are skipped. - internal static void ErasePasswordInUsernameTokenIfPresent(SecurityMessageProperty messageProperty) - { - if (messageProperty == null) - { - // Nothing to fix. - return; - } - - if (messageProperty.TransportToken != null) - { - UserNameSecurityToken token = messageProperty.TransportToken.SecurityToken as UserNameSecurityToken; - if ((token != null) && !messageProperty.TransportToken.SecurityToken.GetType().IsSubclassOf(typeof(UserNameSecurityToken))) - { - messageProperty.TransportToken = new SecurityTokenSpecification(new UserNameSecurityToken(token.UserName, null, token.Id), messageProperty.TransportToken.SecurityTokenPolicies); - } - } - - if (messageProperty.ProtectionToken != null) - { - UserNameSecurityToken token = messageProperty.ProtectionToken.SecurityToken as UserNameSecurityToken; - if ((token != null) && !messageProperty.ProtectionToken.SecurityToken.GetType().IsSubclassOf(typeof(UserNameSecurityToken))) - { - messageProperty.ProtectionToken = new SecurityTokenSpecification(new UserNameSecurityToken(token.UserName, null, token.Id), messageProperty.ProtectionToken.SecurityTokenPolicies); - } - } - - if (messageProperty.HasIncomingSupportingTokens) - { - for (int i = 0; i < messageProperty.IncomingSupportingTokens.Count; ++i) - { - SupportingTokenSpecification supportingTokenSpecification = messageProperty.IncomingSupportingTokens[i]; - UserNameSecurityToken token = supportingTokenSpecification.SecurityToken as UserNameSecurityToken; - if ((token != null) && !supportingTokenSpecification.SecurityToken.GetType().IsSubclassOf(typeof(UserNameSecurityToken))) - { - messageProperty.IncomingSupportingTokens[i] = new SupportingTokenSpecification(new UserNameSecurityToken(token.UserName, null, token.Id), supportingTokenSpecification.SecurityTokenPolicies, supportingTokenSpecification.SecurityTokenAttachmentMode, supportingTokenSpecification.SecurityTokenParameters); - } - } - } - } - - // work-around to Windows SE Bug 141614 - [Fx.Tag.SecurityNote(Critical = "Uses unsafe critical method UnsafeGetPassword to access the credential password without a Demand.", - Safe = "Only uses the password to construct a cloned NetworkCredential instance, does not leak password value.")] - [SecuritySafeCritical] - internal static void FixNetworkCredential(ref NetworkCredential credential) - { - if (credential == null) - { - return; - } - string username = NetworkCredentialHelper.UnsafeGetUsername(credential); - string domain = NetworkCredentialHelper.UnsafeGetDomain(credential); - if (!string.IsNullOrEmpty(username) && string.IsNullOrEmpty(domain)) - { - // do the splitting only if there is exactly 1 \ or exactly 1 @ - string[] partsWithSlashDelimiter = username.Split('\\'); - string[] partsWithAtDelimiter = username.Split('@'); - if (partsWithSlashDelimiter.Length == 2 && partsWithAtDelimiter.Length == 1) - { - if (!string.IsNullOrEmpty(partsWithSlashDelimiter[0]) && !string.IsNullOrEmpty(partsWithSlashDelimiter[1])) - { - credential = new NetworkCredential(partsWithSlashDelimiter[1], NetworkCredentialHelper.UnsafeGetPassword(credential), partsWithSlashDelimiter[0]); - } - } - else if (partsWithSlashDelimiter.Length == 1 && partsWithAtDelimiter.Length == 2) - { - if (!string.IsNullOrEmpty(partsWithAtDelimiter[0]) && !string.IsNullOrEmpty(partsWithAtDelimiter[1])) - { - credential = new NetworkCredential(partsWithAtDelimiter[0], NetworkCredentialHelper.UnsafeGetPassword(credential), partsWithAtDelimiter[1]); - } - } - } - } - - // WORKAROUND, [....], VSWhidbey 561276: The first NetworkCredential must be created in a lock. - internal static void PrepareNetworkCredential() - { - if (dummyNetworkCredential == null) - { - PrepareNetworkCredentialWorker(); - } - } - - // Since this takes a lock, it probably won't be inlined, but the typical case will be. - static void PrepareNetworkCredentialWorker() - { - lock (dummyNetworkCredentialLock) - { - dummyNetworkCredential = new NetworkCredential("dummy", "dummy"); - } - } - - // This is the workaround, Since store.Certificates returns a full collection - // of certs in store. These are holding native resources. - internal static void ResetAllCertificates(X509Certificate2Collection certificates) - { - if (certificates != null) - { - for (int i = 0; i < certificates.Count; ++i) - { - ResetCertificate(certificates[i]); - } - } - } - - [Fx.Tag.SecurityNote(Critical = "Calls critical method X509Certificate2.Reset.", - Safe = "Per review from CLR security team, this method does nothing unsafe.")] - [SecuritySafeCritical] - internal static void ResetCertificate(X509Certificate2 certificate) - { - certificate.Reset(); - } - - internal static bool IsDefaultNetworkCredential(NetworkCredential credential) - { - return NetworkCredentialHelper.IsDefault(credential); - } - - internal static void OpenTokenProviderIfRequired(SecurityTokenProvider tokenProvider, TimeSpan timeout) - { - OpenCommunicationObject(tokenProvider as ICommunicationObject, timeout); - } - - internal static IAsyncResult BeginOpenTokenProviderIfRequired(SecurityTokenProvider tokenProvider, TimeSpan timeout, - AsyncCallback callback, object state) - { - return new OpenCommunicationObjectAsyncResult(tokenProvider, timeout, callback, state); - } - - internal static void EndOpenTokenProviderIfRequired(IAsyncResult result) - { - OpenCommunicationObjectAsyncResult.End(result); - } - - internal static IAsyncResult BeginCloseTokenProviderIfRequired(SecurityTokenProvider tokenProvider, TimeSpan timeout, - AsyncCallback callback, object state) - { - return new CloseCommunicationObjectAsyncResult(tokenProvider, timeout, callback, state); - } - - internal static void EndCloseTokenProviderIfRequired(IAsyncResult result) - { - CloseCommunicationObjectAsyncResult.End(result); - } - - internal static void CloseTokenProviderIfRequired(SecurityTokenProvider tokenProvider, TimeSpan timeout) - { - CloseCommunicationObject(tokenProvider, false, timeout); - } - - internal static void CloseTokenProviderIfRequired(SecurityTokenProvider tokenProvider, bool aborted, TimeSpan timeout) - { - CloseCommunicationObject(tokenProvider, aborted, timeout); - } - - internal static void AbortTokenProviderIfRequired(SecurityTokenProvider tokenProvider) - { - CloseCommunicationObject(tokenProvider, true, TimeSpan.Zero); - } - - internal static void OpenTokenAuthenticatorIfRequired(SecurityTokenAuthenticator tokenAuthenticator, TimeSpan timeout) - { - OpenCommunicationObject(tokenAuthenticator as ICommunicationObject, timeout); - } - - internal static void CloseTokenAuthenticatorIfRequired(SecurityTokenAuthenticator tokenAuthenticator, TimeSpan timeout) - { - CloseTokenAuthenticatorIfRequired(tokenAuthenticator, false, timeout); - } - - internal static void CloseTokenAuthenticatorIfRequired(SecurityTokenAuthenticator tokenAuthenticator, bool aborted, TimeSpan timeout) - { - CloseCommunicationObject(tokenAuthenticator, aborted, timeout); - } - - internal static IAsyncResult BeginOpenTokenAuthenticatorIfRequired(SecurityTokenAuthenticator tokenAuthenticator, TimeSpan timeout, - AsyncCallback callback, object state) - { - return new OpenCommunicationObjectAsyncResult(tokenAuthenticator, timeout, callback, state); - } - - internal static void EndOpenTokenAuthenticatorIfRequired(IAsyncResult result) - { - OpenCommunicationObjectAsyncResult.End(result); - } - - internal static IAsyncResult BeginCloseTokenAuthenticatorIfRequired(SecurityTokenAuthenticator tokenAuthenticator, TimeSpan timeout, - AsyncCallback callback, object state) - { - return new CloseCommunicationObjectAsyncResult(tokenAuthenticator, timeout, callback, state); - } - - internal static void EndCloseTokenAuthenticatorIfRequired(IAsyncResult result) - { - CloseCommunicationObjectAsyncResult.End(result); - } - - internal static void AbortTokenAuthenticatorIfRequired(SecurityTokenAuthenticator tokenAuthenticator) - { - CloseCommunicationObject(tokenAuthenticator, true, TimeSpan.Zero); - } - - static void OpenCommunicationObject(ICommunicationObject obj, TimeSpan timeout) - { - if (obj != null) - obj.Open(timeout); - } - - static void CloseCommunicationObject(Object obj, bool aborted, TimeSpan timeout) - { - if (obj != null) - { - ICommunicationObject co = obj as ICommunicationObject; - if (co != null) - { - if (aborted) - { - try - { - co.Abort(); - } - catch (CommunicationException e) - { - DiagnosticUtility.TraceHandledException(e, TraceEventType.Information); - } - } - else - { - co.Close(timeout); - } - } - else if (obj is IDisposable) - { - ((IDisposable)obj).Dispose(); - } - } - } - - class OpenCommunicationObjectAsyncResult : AsyncResult - { - ICommunicationObject communicationObject; - static AsyncCallback onOpen; - - public OpenCommunicationObjectAsyncResult(object obj, TimeSpan timeout, AsyncCallback callback, object state) - : base(callback, state) - { - this.communicationObject = obj as ICommunicationObject; - - bool completeSelf = false; - if (this.communicationObject == null) - { - completeSelf = true; - } - else - { - if (onOpen == null) - { - onOpen = Fx.ThunkCallback(new AsyncCallback(OnOpen)); - } - - IAsyncResult result = this.communicationObject.BeginOpen(timeout, onOpen, this); - if (result.CompletedSynchronously) - { - this.communicationObject.EndOpen(result); - completeSelf = true; - } - } - - if (completeSelf) - { - base.Complete(true); - } - } - - public static void End(IAsyncResult result) - { - AsyncResult.End(result); - } - - static void OnOpen(IAsyncResult result) - { - if (result.CompletedSynchronously) - { - return; - } - - OpenCommunicationObjectAsyncResult thisPtr = - (OpenCommunicationObjectAsyncResult)result.AsyncState; - - Exception completionException = null; - try - { - thisPtr.communicationObject.EndOpen(result); - } -#pragma warning suppress 56500 // [....], transferring exception to another thread - catch (Exception e) - { - if (Fx.IsFatal(e)) - { - throw; - } - - completionException = e; - } - thisPtr.Complete(false, completionException); - } - } - - class CloseCommunicationObjectAsyncResult : AsyncResult - { - ICommunicationObject communicationObject; - static AsyncCallback onClose; - - public CloseCommunicationObjectAsyncResult(object obj, TimeSpan timeout, AsyncCallback callback, object state) - : base(callback, state) - { - this.communicationObject = obj as ICommunicationObject; - - bool completeSelf = false; - if (this.communicationObject == null) - { - IDisposable disposable = obj as IDisposable; - if (disposable != null) - { - disposable.Dispose(); - } - completeSelf = true; - } - else - { - if (onClose == null) - { - onClose = Fx.ThunkCallback(new AsyncCallback(OnClose)); - } - - IAsyncResult result = this.communicationObject.BeginClose(timeout, onClose, this); - if (result.CompletedSynchronously) - { - this.communicationObject.EndClose(result); - completeSelf = true; - } - } - - if (completeSelf) - { - base.Complete(true); - } - } - - public static void End(IAsyncResult result) - { - AsyncResult.End(result); - } - - static void OnClose(IAsyncResult result) - { - if (result.CompletedSynchronously) - { - return; - } - - CloseCommunicationObjectAsyncResult thisPtr = - (CloseCommunicationObjectAsyncResult)result.AsyncState; - - Exception completionException = null; - try - { - thisPtr.communicationObject.EndClose(result); - } -#pragma warning suppress 56500 // [....], transferring exception to another thread - catch (Exception e) - { - if (Fx.IsFatal(e)) - { - throw; - } - - completionException = e; - } - thisPtr.Complete(false, completionException); - } - } - - internal static void MatchRstWithEndpointFilter(Message rst, IMessageFilterTable endpointFilterTable, Uri listenUri) - { - if (endpointFilterTable == null) - { - return; - } - Collection result = new Collection(); - if (!endpointFilterTable.GetMatchingValues(rst, result)) - { - throw TraceUtility.ThrowHelperWarning(new SecurityNegotiationException(SR.GetString(SR.RequestSecurityTokenDoesNotMatchEndpointFilters, listenUri)), rst); - } - } - - // match the RST with the endpoint filters in case there is at least 1 asymmetric signature in the message - internal static bool ShouldMatchRstWithEndpointFilter(SecurityBindingElement sbe) - { - foreach (SecurityTokenParameters parameters in new SecurityTokenParametersEnumerable(sbe, true)) - { - if (parameters.HasAsymmetricKey) - { - return true; - } - } - return false; - } - - internal static SecurityStandardsManager CreateSecurityStandardsManager(MessageSecurityVersion securityVersion, SecurityTokenManager tokenManager) - { - SecurityTokenSerializer tokenSerializer = tokenManager.CreateSecurityTokenSerializer(securityVersion.SecurityTokenVersion); - return new SecurityStandardsManager(securityVersion, tokenSerializer); - } - - internal static SecurityStandardsManager CreateSecurityStandardsManager(SecurityTokenRequirement requirement, SecurityTokenManager tokenManager) - { - MessageSecurityTokenVersion securityVersion = (MessageSecurityTokenVersion)requirement.GetProperty(ServiceModelSecurityTokenRequirement.MessageSecurityVersionProperty); - if (securityVersion == MessageSecurityTokenVersion.WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005BasicSecurityProfile10) - return CreateSecurityStandardsManager(MessageSecurityVersion.WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10, tokenManager); - else if (securityVersion == MessageSecurityTokenVersion.WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005) - return CreateSecurityStandardsManager(MessageSecurityVersion.WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11, tokenManager); - else if (securityVersion == MessageSecurityTokenVersion.WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005BasicSecurityProfile10) - return CreateSecurityStandardsManager(MessageSecurityVersion.WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10, tokenManager); - else if (securityVersion == MessageSecurityTokenVersion.WSSecurity10WSTrust13WSSecureConversation13BasicSecurityProfile10) - return CreateSecurityStandardsManager(MessageSecurityVersion.WSSecurity10WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10, tokenManager); - else if (securityVersion == MessageSecurityTokenVersion.WSSecurity11WSTrust13WSSecureConversation13) - return CreateSecurityStandardsManager(MessageSecurityVersion.WSSecurity11WSTrust13WSSecureConversation13WSSecurityPolicy12, tokenManager); - else if (securityVersion == MessageSecurityTokenVersion.WSSecurity11WSTrust13WSSecureConversation13BasicSecurityProfile10) - return CreateSecurityStandardsManager(MessageSecurityVersion.WSSecurity11WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10, tokenManager); - else - throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException()); - } - - internal static SecurityStandardsManager CreateSecurityStandardsManager(MessageSecurityVersion securityVersion, SecurityTokenSerializer securityTokenSerializer) - { - if (securityVersion == null) - { - throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("securityVersion")); - } - if (securityTokenSerializer == null) - { - throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("securityTokenSerializer"); - } - return new SecurityStandardsManager(securityVersion, securityTokenSerializer); - } - - static bool TryCreateIdentity(ClaimSet claimSet, string claimType, out EndpointIdentity identity) - { - identity = null; - foreach (Claim claim in claimSet.FindClaims(claimType, null)) - { - identity = EndpointIdentity.CreateIdentity(claim); - return true; - } - return false; - } - - internal static EndpointIdentity GetServiceCertificateIdentity(X509Certificate2 certificate) - { - using (X509CertificateClaimSet claimSet = new X509CertificateClaimSet(certificate)) - { - EndpointIdentity identity; - if (!TryCreateIdentity(claimSet, ClaimTypes.Dns, out identity)) - { - TryCreateIdentity(claimSet, ClaimTypes.Rsa, out identity); - } - return identity; - } - } - - [Fx.Tag.SecurityNote(Critical = "Uses unsafe critical method UnsafeGetPassword to access the credential password without a Demand.", - Safe = "Only uses the password to construct a new NetworkCredential which will then protect access, password does not leak from this method.")] - [SecuritySafeCritical] - internal static NetworkCredential GetNetworkCredentialsCopy(NetworkCredential networkCredential) - { - NetworkCredential result; - if (networkCredential != null && !NetworkCredentialHelper.IsDefault(networkCredential)) - { - result = new NetworkCredential(NetworkCredentialHelper.UnsafeGetUsername(networkCredential), NetworkCredentialHelper.UnsafeGetPassword(networkCredential), NetworkCredentialHelper.UnsafeGetDomain(networkCredential)); - } - else - { - result = networkCredential; - } - return result; - } - - internal static NetworkCredential GetNetworkCredentialOrDefault(NetworkCredential credential) - { - // because of VSW 564452, we dont use CredentialCache.DefaultNetworkCredentials in our OM. Instead we - // use an empty NetworkCredential to denote the default credentials - if (NetworkCredentialHelper.IsNullOrEmpty(credential)) - { - // FYI: this will fail with SecurityException in PT due to Demand for EnvironmentPermission. - // Typically a PT app should not have access to DefaultNetworkCredentials. If there is a valid reason, - // see UnsafeGetDefaultNetworkCredentials. - return CredentialCache.DefaultNetworkCredentials; - } - else - { - return credential; - } - } - - static class NetworkCredentialHelper - { - [Fx.Tag.SecurityNote(Critical = "Uses unsafe critical methods UnsafeGetUsername, UnsafeGetPassword, and UnsafeGetDomain to access the credential details without a Demand.", - Safe = "Only uses the protected values to test for null/empty. Does not leak.")] - [SecuritySafeCritical] - static internal bool IsNullOrEmpty(NetworkCredential credential) - { - return credential == null || - ( - String.IsNullOrEmpty(UnsafeGetUsername(credential)) && - String.IsNullOrEmpty(UnsafeGetDomain(credential)) && - String.IsNullOrEmpty(UnsafeGetPassword(credential)) - ); - } - - [Fx.Tag.SecurityNote(Critical = "Uses unsafe critical method UnsafeGetDefaultNetworkCredentials to access the default network credentials without a Demand.", - Safe = "Only uses the default credentials to test for equality and uses the system credential's .Equals, not the caller's.")] - [SecuritySafeCritical] - static internal bool IsDefault(NetworkCredential credential) - { - return UnsafeGetDefaultNetworkCredentials().Equals(credential); - } - - [Fx.Tag.SecurityNote(Critical = "Asserts SecurityPermission(UnmanagedCode) in order to get the NetworkCredential password." - + "This is used for example to test for empty/null or to construct a cloned NetworkCredential." - + "Callers absolutely must not leak the return value.")] - [SecurityCritical] - [EnvironmentPermission(SecurityAction.Assert, Read = "USERNAME")] - static internal string UnsafeGetUsername(NetworkCredential credential) - { - return credential.UserName; - } - - [Fx.Tag.SecurityNote(Critical = "Asserts SecurityPermission(UnmanagedCode) in order to get the NetworkCredential password." - + "This is used for example to test for empty/null or to construct a cloned NetworkCredential." - + "Callers absolutely must not leak the return value.")] - [SecurityCritical] - [SecurityPermission(SecurityAction.Assert, UnmanagedCode = true)] - static internal string UnsafeGetPassword(NetworkCredential credential) - { - return credential.Password; - } - - [Fx.Tag.SecurityNote(Critical = "Asserts SecurityPermission(UnmanagedCode) in order to get the NetworkCredential password." - + "This is used for example to test for empty/null or to construct a cloned NetworkCredential." - + "Callers absolutely must not leak the return value.")] - [SecurityCritical] - [EnvironmentPermission(SecurityAction.Assert, Read = "USERDOMAIN")] - static internal string UnsafeGetDomain(NetworkCredential credential) - { - return credential.Domain; - } - - [Fx.Tag.SecurityNote(Critical = "Asserts EnvironmentPermission(Read='USERNAME') in order to get the DefaultNetworkCredentials in PT." - + "This is used for example to test for instance equality with a specific NetworkCredential." - + "Callers absolutely must not leak the return value.")] - [SecurityCritical] - [EnvironmentPermission(SecurityAction.Assert, Read = "USERNAME")] - static NetworkCredential UnsafeGetDefaultNetworkCredentials() - { - return CredentialCache.DefaultNetworkCredentials; - } - } - - internal static SafeFreeCredentials GetCredentialsHandle(string package, NetworkCredential credential, bool isServer, params string[] additionalPackages) - { - SafeFreeCredentials credentialsHandle; - CredentialUse credentialUse = isServer ? CredentialUse.Inbound : CredentialUse.Outbound; - if (credential == null || NetworkCredentialHelper.IsDefault(credential)) - { - AuthIdentityEx authIdentity = new AuthIdentityEx(null, null, null, additionalPackages); - credentialsHandle = SspiWrapper.AcquireCredentialsHandle(package, credentialUse, ref authIdentity); - } - else - { - SecurityUtils.FixNetworkCredential(ref credential); - - // we're not using DefaultCredentials, we need a - // AuthIdentity struct to contain credentials - AuthIdentityEx authIdentity = new AuthIdentityEx(credential.UserName, credential.Password, credential.Domain); - credentialsHandle = SspiWrapper.AcquireCredentialsHandle(package, credentialUse, ref authIdentity); - } - return credentialsHandle; - } - - internal static SafeFreeCredentials GetCredentialsHandle(Binding binding, KeyedByTypeCollection behaviors) - { - ClientCredentials clientCredentials = (behaviors == null) ? null : behaviors.Find(); - return GetCredentialsHandle(binding, clientCredentials); - } - - internal static SafeFreeCredentials GetCredentialsHandle(Binding binding, ClientCredentials clientCredentials) - { - SecurityBindingElement sbe = (binding == null) ? null : binding.CreateBindingElements().Find(); - return GetCredentialsHandle(sbe, clientCredentials); - } - - internal static SafeFreeCredentials GetCredentialsHandle(SecurityBindingElement sbe, BindingContext context) - { - ClientCredentials clientCredentials = (context == null) ? null : context.BindingParameters.Find(); - return GetCredentialsHandle(sbe, clientCredentials); - } - - internal static SafeFreeCredentials GetCredentialsHandle(SecurityBindingElement sbe, ClientCredentials clientCredentials) - { - if (sbe == null) - { - return null; - } - - bool isSspi = false; - bool isKerberos = false; - foreach (SecurityTokenParameters stp in new SecurityTokenParametersEnumerable(sbe, true)) - { - if (stp is SecureConversationSecurityTokenParameters) - { - SafeFreeCredentials result = GetCredentialsHandle(((SecureConversationSecurityTokenParameters)stp).BootstrapSecurityBindingElement, clientCredentials); - if (result != null) - { - return result; - } - continue; - } - else if (stp is IssuedSecurityTokenParameters) - { - SafeFreeCredentials result = GetCredentialsHandle(((IssuedSecurityTokenParameters)stp).IssuerBinding, clientCredentials); - if (result != null) - { - return result; - } - continue; - } - else if (stp is SspiSecurityTokenParameters) - { - isSspi = true; - break; - } - else if (stp is KerberosSecurityTokenParameters) - { - isKerberos = true; - break; - } - } - if (!isSspi && !isKerberos) - { - return null; - } - - NetworkCredential credential = null; - if (clientCredentials != null) - { - credential = SecurityUtils.GetNetworkCredentialOrDefault(clientCredentials.Windows.ClientCredential); - } - - if (isKerberos) - { - return SecurityUtils.GetCredentialsHandle("Kerberos", credential, false); - } - // if OS is less that Vista cannot use !NTLM, Windows SE 142400 - -// To disable AllowNtlm warning. -#pragma warning disable 618 - - else if (clientCredentials != null && !clientCredentials.Windows.AllowNtlm) - { - if (SecurityUtils.IsOsGreaterThanXP()) - { - return SecurityUtils.GetCredentialsHandle("Negotiate", credential, false, "!NTLM"); - } - else - { - return SecurityUtils.GetCredentialsHandle("Kerberos", credential, false); - } - } - -#pragma warning restore 618 - - return SecurityUtils.GetCredentialsHandle("Negotiate", credential, false); - } - - internal static byte[] CloneBuffer(byte[] buffer) - { - byte[] copy = DiagnosticUtility.Utility.AllocateByteArray(buffer.Length); - Buffer.BlockCopy(buffer, 0, copy, 0, buffer.Length); - return copy; - } - - internal static X509Certificate2 GetCertificateFromStore(StoreName storeName, StoreLocation storeLocation, - X509FindType findType, object findValue, EndpointAddress target) - { - X509Certificate2 certificate = GetCertificateFromStoreCore(storeName, storeLocation, findType, findValue, target, true); - if (certificate == null) - throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.CannotFindCert, storeName, storeLocation, findType, findValue))); - - return certificate; - } - - internal static bool TryGetCertificateFromStore(StoreName storeName, StoreLocation storeLocation, - X509FindType findType, object findValue, EndpointAddress target, out X509Certificate2 certificate) - { - certificate = GetCertificateFromStoreCore(storeName, storeLocation, findType, findValue, target, false); - return (certificate != null); - } - - static X509Certificate2 GetCertificateFromStoreCore(StoreName storeName, StoreLocation storeLocation, - X509FindType findType, object findValue, EndpointAddress target, bool throwIfMultipleOrNoMatch) - { - if (findValue == null) - { - throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("findValue"); - } - X509CertificateStore store = new X509CertificateStore(storeName, storeLocation); - X509Certificate2Collection certs = null; - try - { - store.Open(OpenFlags.ReadOnly); - certs = store.Find(findType, findValue, false); - if (certs.Count == 1) - { - return new X509Certificate2(certs[0]); - } - if (throwIfMultipleOrNoMatch) - { - throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateCertificateLoadException( - storeName, storeLocation, findType, findValue, target, certs.Count)); - } - else - { - return null; - } - } - finally - { - SecurityUtils.ResetAllCertificates(certs); - store.Close(); - } - } - - static Exception CreateCertificateLoadException(StoreName storeName, StoreLocation storeLocation, - X509FindType findType, object findValue, EndpointAddress target, int certCount) - { - if (certCount == 0) - { - if (target == null) - { - return new InvalidOperationException(SR.GetString(SR.CannotFindCert, storeName, storeLocation, findType, findValue)); - } - else - { - return new InvalidOperationException(SR.GetString(SR.CannotFindCertForTarget, storeName, storeLocation, findType, findValue, target)); - } - } - else - { - if (target == null) - { - return new InvalidOperationException(SR.GetString(SR.FoundMultipleCerts, storeName, storeLocation, findType, findValue)); - } - else - { - return new InvalidOperationException(SR.GetString(SR.FoundMultipleCertsForTarget, storeName, storeLocation, findType, findValue, target)); - } - } - } - - public static SecurityBindingElement GetIssuerSecurityBindingElement(ServiceModelSecurityTokenRequirement requirement) - { - SecurityBindingElement bindingElement = requirement.SecureConversationSecurityBindingElement; - if (bindingElement != null) - { - return bindingElement; - } - - Binding binding = requirement.IssuerBinding; - if (binding == null) - { - throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(SR.GetString(SR.IssuerBindingNotPresentInTokenRequirement, requirement)); - } - BindingElementCollection bindingElements = binding.CreateBindingElements(); - return bindingElements.Find(); - } - - public static int GetMaxNegotiationBufferSize(BindingContext bindingContext) - { - TransportBindingElement transport = bindingContext.RemainingBindingElements.Find(); - Fx.Assert(transport != null, "TransportBindingElement is null!"); - int maxNegoMessageSize; - if (transport is ConnectionOrientedTransportBindingElement) - { - maxNegoMessageSize = ((ConnectionOrientedTransportBindingElement)transport).MaxBufferSize; - } - else if (transport is HttpTransportBindingElement) - { - maxNegoMessageSize = ((HttpTransportBindingElement)transport).MaxBufferSize; - } - else - { - maxNegoMessageSize = TransportDefaults.MaxBufferSize; - } - return maxNegoMessageSize; - } - - public static bool TryCreateKeyFromIntrinsicKeyClause(SecurityKeyIdentifierClause keyIdentifierClause, SecurityTokenResolver resolver, out SecurityKey key) - { - key = null; - if (keyIdentifierClause.CanCreateKey) - { - key = keyIdentifierClause.CreateKey(); - return true; - } - if (keyIdentifierClause is EncryptedKeyIdentifierClause) - { - EncryptedKeyIdentifierClause keyClause = (EncryptedKeyIdentifierClause)keyIdentifierClause; - // PreSharp Bug: Parameter 'keyClause' to this public method must be validated: A null-dereference can occur here. -#pragma warning suppress 56506 // keyClause will not be null due to the if condition above. - for (int i = 0; i < keyClause.EncryptingKeyIdentifier.Count; i++) - { - SecurityKey unwrappingSecurityKey = null; - if (resolver.TryResolveSecurityKey(keyClause.EncryptingKeyIdentifier[i], out unwrappingSecurityKey)) - { - byte[] wrappedKey = keyClause.GetEncryptedKey(); - string wrappingAlgorithm = keyClause.EncryptionMethod; - byte[] unwrappedKey = unwrappingSecurityKey.DecryptKey(wrappingAlgorithm, wrappedKey); - key = new InMemorySymmetricSecurityKey(unwrappedKey, false); - return true; - } - } - } - return false; - } - - public static WrappedKeySecurityToken CreateTokenFromEncryptedKeyClause(EncryptedKeyIdentifierClause keyClause, SecurityToken unwrappingToken) - { - SecurityKeyIdentifier wrappingTokenReference = keyClause.EncryptingKeyIdentifier; - byte[] wrappedKey = keyClause.GetEncryptedKey(); - SecurityKey unwrappingSecurityKey = unwrappingToken.SecurityKeys[0]; - string wrappingAlgorithm = keyClause.EncryptionMethod; - byte[] unwrappedKey = unwrappingSecurityKey.DecryptKey(wrappingAlgorithm, wrappedKey); - return new WrappedKeySecurityToken(SecurityUtils.GenerateId(), unwrappedKey, wrappingAlgorithm, - unwrappingToken, wrappingTokenReference, wrappedKey, unwrappingSecurityKey - ); - } - - public static void ValidateAnonymityConstraint(WindowsIdentity identity, bool allowUnauthenticatedCallers) - { - if (!allowUnauthenticatedCallers && identity.User.IsWellKnown(WellKnownSidType.AnonymousSid)) - { - throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning( - new SecurityTokenValidationException(SR.GetString(SR.AnonymousLogonsAreNotAllowed))); - } - } - - static bool ComputeSslCipherStrengthRequirementFlag() - { - // validate only for XP versions < XP SP3 and windows server versions < Win2K3 SP2 - if ((Environment.OSVersion.Version.Major > WindowsServerMajorNumber) - || (Environment.OSVersion.Version.Major == WindowsServerMajorNumber && Environment.OSVersion.Version.Minor > WindowsServerMinorNumber)) - { - return false; - } - // version <= Win2K3 - if (Environment.OSVersion.Version.Major == XPMajorNumber && Environment.OSVersion.Version.Minor == XPMinorNumber) - { - if ((Environment.OSVersion.ServicePack == string.Empty) || String.Equals(Environment.OSVersion.ServicePack, ServicePack1, StringComparison.OrdinalIgnoreCase) || String.Equals(Environment.OSVersion.ServicePack, ServicePack2, StringComparison.OrdinalIgnoreCase)) - { - return true; - } - else - { - // the OS is XP SP3 or higher - return false; - } - } - else if (Environment.OSVersion.Version.Major == WindowsServerMajorNumber && Environment.OSVersion.Version.Minor == WindowsServerMinorNumber) - { - if (Environment.OSVersion.ServicePack == string.Empty || String.Equals(Environment.OSVersion.ServicePack, ServicePack1, StringComparison.OrdinalIgnoreCase)) - { - return true; - } - else - { - // the OS is Win2K3 SP2 or higher - return false; - } - } - else - { - // this is <= XP. We should never get here but if we do validate SSL strength - return true; - } - } - - public static bool ShouldValidateSslCipherStrength() - { - if (!isSslValidationRequirementDetermined) - { - shouldValidateSslCipherStrength = ComputeSslCipherStrengthRequirementFlag(); - Thread.MemoryBarrier(); - isSslValidationRequirementDetermined = true; - } - return shouldValidateSslCipherStrength; - } - - public static void ValidateSslCipherStrength(int keySizeInBits) - { - if (ShouldValidateSslCipherStrength() && keySizeInBits < MinimumSslCipherStrength) - { - throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new SecurityNegotiationException(SR.GetString(SR.SslCipherKeyTooSmall, keySizeInBits, MinimumSslCipherStrength))); - } - } - - public static bool TryCreateX509CertificateFromRawData(byte[] rawData, out X509Certificate2 certificate) - { - certificate = (rawData == null || rawData.Length == 0) ? null : new X509Certificate2(rawData); - return certificate != null && certificate.Handle != IntPtr.Zero; - } - - internal static string GetKeyDerivationAlgorithm(SecureConversationVersion version) - { - string derivationAlgorithm = null; - if (version == SecureConversationVersion.WSSecureConversationFeb2005) - { - derivationAlgorithm = SecurityAlgorithms.Psha1KeyDerivation; - } - else if (version == SecureConversationVersion.WSSecureConversation13) - { - derivationAlgorithm = SecurityAlgorithms.Psha1KeyDerivationDec2005; - } - else - { - throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException()); - } - - return derivationAlgorithm; - } - - } - - struct SecurityUniqueId - { - static long nextId = 0; - static string commonPrefix = "uuid-" + Guid.NewGuid().ToString() + "-"; - - long id; - string prefix; - string val; - - SecurityUniqueId(string prefix, long id) - { - this.id = id; - this.prefix = prefix; - this.val = null; - } - - public static SecurityUniqueId Create() - { - return SecurityUniqueId.Create(commonPrefix); - } - - public static SecurityUniqueId Create(string prefix) - { - return new SecurityUniqueId(prefix, Interlocked.Increment(ref nextId)); - } - - public string Value - { - get - { - if (this.val == null) - this.val = this.prefix + this.id.ToString(CultureInfo.InvariantCulture); - - return this.val; - } - } - } - - static class EmptyReadOnlyCollection - { - public static ReadOnlyCollection Instance = new ReadOnlyCollection(new List()); - } - - class OperationWithTimeoutAsyncResult : TraceAsyncResult - { - static readonly Action scheduledCallback = new Action(OnScheduled); - TimeoutHelper timeoutHelper; - OperationWithTimeoutCallback operationWithTimeout; - - public OperationWithTimeoutAsyncResult(OperationWithTimeoutCallback operationWithTimeout, TimeSpan timeout, AsyncCallback callback, object state) - : base(callback, state) - { - this.operationWithTimeout = operationWithTimeout; - this.timeoutHelper = new TimeoutHelper(timeout); - ActionItem.Schedule(scheduledCallback, this); - } - - static void OnScheduled(object state) - { - OperationWithTimeoutAsyncResult thisResult = (OperationWithTimeoutAsyncResult)state; - Exception completionException = null; - try - { - using (thisResult.CallbackActivity == null ? null : ServiceModelActivity.BoundOperation(thisResult.CallbackActivity)) - { - thisResult.operationWithTimeout(thisResult.timeoutHelper.RemainingTime()); - } - } -#pragma warning suppress 56500 // covered by FxCOP - catch (Exception e) - { - if (Fx.IsFatal(e)) - { - throw; - } - - completionException = e; - } - thisResult.Complete(false, completionException); - } - - public static void End(IAsyncResult result) - { - AsyncResult.End(result); - } - } -} diff --git a/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Security/SecurityUtils.cs.REMOVED.git-id b/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Security/SecurityUtils.cs.REMOVED.git-id new file mode 100644 index 0000000000..5a2304d180 --- /dev/null +++ b/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Security/SecurityUtils.cs.REMOVED.git-id @@ -0,0 +1 @@ +b62aceefcff29d0061ab33c65db191ab5faee7c8 \ No newline at end of file diff --git a/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Security/TlsSspiNegotiation.cs b/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Security/TlsSspiNegotiation.cs index 0032edc9ea..5972289343 100644 --- a/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Security/TlsSspiNegotiation.cs +++ b/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Security/TlsSspiNegotiation.cs @@ -543,7 +543,14 @@ namespace System.ServiceModel.Security bool hasPrivateKey = false; try { - hasPrivateKey = certificate != null && certificate.PrivateKey != null; + if (System.ServiceModel.LocalAppContextSwitches.DisableCngCertificates) + { + hasPrivateKey = certificate != null && certificate.PrivateKey != null; + } + else + { + hasPrivateKey = certificate.HasPrivateKey && SecurityUtils.CanReadPrivateKey(certificate); + } } catch (SecurityException e) { diff --git a/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Security/Tokens/IssuedSecurityTokenProvider.cs b/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Security/Tokens/IssuedSecurityTokenProvider.cs index b9f10c42f5..5641522d6e 100644 --- a/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Security/Tokens/IssuedSecurityTokenProvider.cs +++ b/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Security/Tokens/IssuedSecurityTokenProvider.cs @@ -461,7 +461,7 @@ namespace System.ServiceModel.Security.Tokens XmlDocument dom = new XmlDocument(); dom.PreserveWhitespace = true; - dom.Load(stream); + dom.Load(new XmlTextReader(stream) { DtdProcessing = DtdProcessing.Prohibit }); stream.Close(); return dom.DocumentElement; diff --git a/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Security/WSSecurityPolicy.cs.REMOVED.git-id b/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Security/WSSecurityPolicy.cs.REMOVED.git-id index b2d712e04c..031c0c4415 100644 --- a/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Security/WSSecurityPolicy.cs.REMOVED.git-id +++ b/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Security/WSSecurityPolicy.cs.REMOVED.git-id @@ -1 +1 @@ -e3d7cf18cc07d587f1e980a4e513774963b751e3 \ No newline at end of file +417886dd3eba68ef6d147d84828ba4cd1efa0ae1 \ No newline at end of file diff --git a/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Security/WSTrust.cs b/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Security/WSTrust.cs index 2795cd2b3e..2b65cc9326 100644 --- a/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Security/WSTrust.cs +++ b/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Security/WSTrust.cs @@ -1417,7 +1417,7 @@ namespace System.ServiceModel.Security writer.Flush(); stream.Seek(0, SeekOrigin.Begin); XmlNode skiNode; - using (XmlDictionaryReader reader = XmlDictionaryReader.CreateDictionaryReader(new XmlTextReader(stream))) + using (XmlDictionaryReader reader = XmlDictionaryReader.CreateDictionaryReader(new XmlTextReader(stream) { DtdProcessing = DtdProcessing.Prohibit })) { reader.MoveToContent(); skiNode = doc.ReadNode(reader); diff --git a/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Security/WSTrustServiceContract.cs.REMOVED.git-id b/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Security/WSTrustServiceContract.cs.REMOVED.git-id index 1deb63abf3..32bbae10b9 100644 --- a/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Security/WSTrustServiceContract.cs.REMOVED.git-id +++ b/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Security/WSTrustServiceContract.cs.REMOVED.git-id @@ -1 +1 @@ -81df58a3069e5ff171d11fed73dc25d5fab47202 \ No newline at end of file +1bd584b2806af9a18b3a131b41a8151545fe09e1 \ No newline at end of file diff --git a/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/ServiceHost.cs b/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/ServiceHost.cs index 47a80aaf77..37ca8e48b9 100644 --- a/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/ServiceHost.cs +++ b/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/ServiceHost.cs @@ -1,4 +1,4 @@ - //----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- // Copyright (c) Microsoft Corporation. All rights reserved. //----------------------------------------------------------------------------- @@ -1076,6 +1076,9 @@ namespace System.ServiceModel { ManagementExtension.OnServiceOpened(this); } + + // log telemetry data for the current WCF service. + TelemetryTraceLogging.LogSeriveKPIData(this.Description); } base.OnOpened(); diff --git a/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/ServiceModelAppSettings.cs b/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/ServiceModelAppSettings.cs index b7c7db2a42..19fba5c99a 100644 --- a/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/ServiceModelAppSettings.cs +++ b/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/ServiceModelAppSettings.cs @@ -15,12 +15,15 @@ namespace System.ServiceModel internal const string HttpTransportPerFactoryConnectionPoolString = "wcf:httpTransportBinding:useUniqueConnectionPoolPerFactory"; internal const string EnsureUniquePerformanceCounterInstanceNamesString = "wcf:ensureUniquePerformanceCounterInstanceNames"; internal const string UseConfiguredTransportSecurityHeaderLayoutString = "wcf:useConfiguredTransportSecurityHeaderLayout"; + internal const string UseBestMatchNamedPipeUriString = "wcf:useBestMatchNamedPipeUri"; const bool DefaultHttpTransportPerFactoryConnectionPool = false; const bool DefaultEnsureUniquePerformanceCounterInstanceNames = false; const bool DefaultUseConfiguredTransportSecurityHeaderLayout = false; + const bool DefaultUseBestMatchNamedPipeUri = false; static bool httpTransportPerFactoryConnectionPool; static bool ensureUniquePerformanceCounterInstanceNames; static bool useConfiguredTransportSecurityHeaderLayout; + static bool useBestMatchNamedPipeUri; static volatile bool settingsInitalized = false; static object appSettingsLock = new object(); @@ -54,6 +57,16 @@ namespace System.ServiceModel } } + internal static bool UseBestMatchNamedPipeUri + { + get + { + EnsureSettingsLoaded(); + + return useBestMatchNamedPipeUri; + } + } + [SuppressMessage(FxCop.Category.ReliabilityBasic, "Reliability104:CaughtAndHandledExceptionsRule", Justification = "Handle the configuration exceptions here to avoid regressions on customer's existing scenarios")] static void EnsureSettingsLoaded() @@ -89,6 +102,11 @@ namespace System.ServiceModel useConfiguredTransportSecurityHeaderLayout = DefaultUseConfiguredTransportSecurityHeaderLayout; } + if ((appSettingsSection == null) || !bool.TryParse(appSettingsSection[UseBestMatchNamedPipeUriString], out useBestMatchNamedPipeUri)) + { + useBestMatchNamedPipeUri = DefaultUseBestMatchNamedPipeUri; + } + settingsInitalized = true; } } diff --git a/mcs/class/referencesource/System.ServiceModel/System/UriTemplate.cs b/mcs/class/referencesource/System.ServiceModel/System/UriTemplate.cs index 969772454c..a62d82e0b9 100644 --- a/mcs/class/referencesource/System.ServiceModel/System/UriTemplate.cs +++ b/mcs/class/referencesource/System.ServiceModel/System/UriTemplate.cs @@ -4,6 +4,7 @@ namespace System { + using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Collections.Specialized; @@ -11,6 +12,7 @@ namespace System using System.ServiceModel; using System.ServiceModel.Channels; using System.Text; + using System.Threading; using System.Runtime.CompilerServices; using System.Globalization; @@ -31,7 +33,7 @@ namespace System const string NullableDefault = "null"; readonly WildcardInfo wildcard; IDictionary defaults; - Dictionary unescapedDefaults; + ConcurrentDictionary unescapedDefaults; VariablesCollection variables; @@ -263,7 +265,7 @@ namespace System { if (this.defaults == null) { - this.defaults = new UriTemplateDefaults(this); + Interlocked.CompareExchange>(ref this.defaults, new UriTemplateDefaults(this), null); } return this.defaults; } @@ -943,16 +945,10 @@ namespace System } if (this.unescapedDefaults == null) { - this.unescapedDefaults = new Dictionary(StringComparer.Ordinal); - } - string unescapedValue; - if (!this.unescapedDefaults.TryGetValue(escapedValue, out unescapedValue)) - { - unescapedValue = Uri.UnescapeDataString(escapedValue); - this.unescapedDefaults.Add(escapedValue, unescapedValue); + this.unescapedDefaults = new ConcurrentDictionary(StringComparer.Ordinal); } - return unescapedValue; + return this.unescapedDefaults.GetOrAdd(escapedValue, Uri.UnescapeDataString); } struct BindInformation @@ -1181,8 +1177,8 @@ namespace System { if (this.pathSegmentVariableNamesSnapshot == null) { - this.pathSegmentVariableNamesSnapshot = new ReadOnlyCollection( - this.pathSegmentVariableNames); + Interlocked.CompareExchange>(ref this.pathSegmentVariableNamesSnapshot, new ReadOnlyCollection( + this.pathSegmentVariableNames), null); } return this.pathSegmentVariableNamesSnapshot; } @@ -1193,8 +1189,8 @@ namespace System { if (this.queryValueVariableNamesSnapshot == null) { - this.queryValueVariableNamesSnapshot = new ReadOnlyCollection( - this.queryValueVariableNames); + Interlocked.CompareExchange>(ref this.queryValueVariableNamesSnapshot, new ReadOnlyCollection( + this.queryValueVariableNames), null); } return this.queryValueVariableNamesSnapshot; } diff --git a/mcs/class/referencesource/System.Web.DynamicData/DynamicData/DynamicValidator.cs b/mcs/class/referencesource/System.Web.DynamicData/DynamicData/DynamicValidator.cs index 7e89f129e7..51d5a3c922 100644 --- a/mcs/class/referencesource/System.Web.DynamicData/DynamicData/DynamicValidator.cs +++ b/mcs/class/referencesource/System.Web.DynamicData/DynamicData/DynamicValidator.cs @@ -11,6 +11,7 @@ using System.Web.Resources; using System.Web.UI; using System.Web.UI.WebControls; + using System.Web.DynamicData.Util; /// /// Validator that enforces model validation. It can be used either at the field level or the entity level @@ -163,7 +164,7 @@ } if (!attrib.IsValid(value)) { - ErrorMessage = HttpUtility.HtmlEncode(attrib.FormatErrorMessage(Column.DisplayName)); + ErrorMessage = HttpUtility.HtmlEncode(StringLocalizerUtil.GetLocalizedString(attrib, Column.DisplayName)); return false; } } diff --git a/mcs/class/referencesource/System.Web.DynamicData/DynamicData/FieldTemplateUserControl.cs b/mcs/class/referencesource/System.Web.DynamicData/DynamicData/FieldTemplateUserControl.cs index 33381499ec..324ddf3a0a 100644 --- a/mcs/class/referencesource/System.Web.DynamicData/DynamicData/FieldTemplateUserControl.cs +++ b/mcs/class/referencesource/System.Web.DynamicData/DynamicData/FieldTemplateUserControl.cs @@ -516,7 +516,8 @@ namespace System.Web.DynamicData { validator.MaximumValue = converter(rangeAttribute.Maximum); if (String.IsNullOrEmpty(validator.ErrorMessage)) { - validator.ErrorMessage = HttpUtility.HtmlEncode(rangeAttribute.FormatErrorMessage(column.DisplayName)); + validator.ErrorMessage = HttpUtility.HtmlEncode( + StringLocalizerUtil.GetLocalizedString(rangeAttribute, column.DisplayName)); } } @@ -533,7 +534,8 @@ namespace System.Web.DynamicData { validator.ValidationExpression = regexAttribute.Pattern; if (String.IsNullOrEmpty(validator.ErrorMessage)) { - validator.ErrorMessage = HttpUtility.HtmlEncode(regexAttribute.FormatErrorMessage(column.DisplayName)); + validator.ErrorMessage = HttpUtility.HtmlEncode( + StringLocalizerUtil.GetLocalizedString(regexAttribute, column.DisplayName)); } } diff --git a/mcs/class/referencesource/System.Web.DynamicData/DynamicData/MetaColumn.cs b/mcs/class/referencesource/System.Web.DynamicData/DynamicData/MetaColumn.cs index 41ce63ba26..74fb8fb0fe 100644 --- a/mcs/class/referencesource/System.Web.DynamicData/DynamicData/MetaColumn.cs +++ b/mcs/class/referencesource/System.Web.DynamicData/DynamicData/MetaColumn.cs @@ -250,7 +250,8 @@ namespace System.Web.DynamicData { public string RequiredErrorMessage { get { var requiredAttribute = Metadata.RequiredAttribute; - return requiredAttribute != null ? requiredAttribute.FormatErrorMessage(DisplayName) : String.Empty; + return requiredAttribute != null ? + StringLocalizerUtil.GetLocalizedString(requiredAttribute, DisplayName) : String.Empty; } } @@ -590,7 +591,7 @@ namespace System.Web.DynamicData { public string Description { get { - return DisplayAttribute.GetPropertyValue(a => a.GetDescription(), null) ?? + return DisplayAttribute.GetLocalizedDescription() ?? DescriptionAttribute.GetPropertyValue(a => a.Description, null); } } @@ -599,14 +600,14 @@ namespace System.Web.DynamicData { public string DisplayName { get { - return DisplayAttribute.GetPropertyValue(a => a.GetName(), null) ?? + return DisplayAttribute.GetLocalizedName() ?? DisplayNameAttribute.GetPropertyValue(a => a.DisplayName, null); } } public string ShortDisplayName { get { - return DisplayAttribute.GetPropertyValue(a => a.GetShortName(), null); + return DisplayAttribute.GetLocalizedShortName(); } } @@ -622,7 +623,7 @@ namespace System.Web.DynamicData { public string Prompt { get { - return DisplayAttribute.GetPropertyValue(a => a.GetPrompt(), null); + return DisplayAttribute.GetLocalizedPrompt(); } } diff --git a/mcs/class/referencesource/System.Web.Extensions/Compilation/WCFModel/DataSvcMapFileLoader.cs b/mcs/class/referencesource/System.Web.Extensions/Compilation/WCFModel/DataSvcMapFileLoader.cs index e0c957977b..b7a62e03ad 100644 --- a/mcs/class/referencesource/System.Web.Extensions/Compilation/WCFModel/DataSvcMapFileLoader.cs +++ b/mcs/class/referencesource/System.Web.Extensions/Compilation/WCFModel/DataSvcMapFileLoader.cs @@ -6,6 +6,7 @@ #endregion using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Xml.Schema; using System.Xml.Serialization; @@ -50,6 +51,7 @@ namespace Microsoft.VSDesigner.WCFModel return mapFile is DataSvcMapFile ? ((DataSvcMapFile)mapFile).Impl : null; } + [SuppressMessage("Microsoft.Security.Xml", "CA3060:UseXmlReaderForSchemaRead", Justification = "asp.net controls this .xsd file")] protected override XmlSchemaSet GetMapFileSchemaSet() { if (_mapFileSchemaSet == null) diff --git a/mcs/class/referencesource/System.Web.Extensions/Compilation/WCFModel/MetadataFile.cs b/mcs/class/referencesource/System.Web.Extensions/Compilation/WCFModel/MetadataFile.cs index 9aea425a73..d05896f212 100644 --- a/mcs/class/referencesource/System.Web.Extensions/Compilation/WCFModel/MetadataFile.cs +++ b/mcs/class/referencesource/System.Web.Extensions/Compilation/WCFModel/MetadataFile.cs @@ -17,6 +17,7 @@ using XmlSerialization = System.Xml.Serialization; #if WEB_EXTENSIONS_CODE using System.Web.Resources; +using System.Diagnostics.CodeAnalysis; #else using Microsoft.VSDesigner.WCF.Resources; #endif @@ -551,6 +552,7 @@ namespace Microsoft.VSDesigner.WCFModel /// /// /// + [SuppressMessage("Microsoft.Security.Xml", "CA3054:DoNotAllowDtdOnXmlTextReader", Justification = "Legacy code that trusts our developer-controlled input.")] private void LoadContentFromTextReader(TextReader contentReader) { if (contentReader == null) @@ -597,6 +599,7 @@ namespace Microsoft.VSDesigner.WCFModel /// /// /// + [SuppressMessage("Microsoft.Security.Xml", "CA3054:DoNotAllowDtdOnXmlTextReader", Justification = "Legacy code that trusts our developer-controlled input.")] private MetadataContent LoadMetadataContent(MetadataType fileType) { if (ErrorInLoading != null) diff --git a/mcs/class/referencesource/System.Web.Extensions/Compilation/WCFModel/SvcMapFileLoader.cs b/mcs/class/referencesource/System.Web.Extensions/Compilation/WCFModel/SvcMapFileLoader.cs index d820af9e04..8b9e1ea290 100644 --- a/mcs/class/referencesource/System.Web.Extensions/Compilation/WCFModel/SvcMapFileLoader.cs +++ b/mcs/class/referencesource/System.Web.Extensions/Compilation/WCFModel/SvcMapFileLoader.cs @@ -6,6 +6,7 @@ #endregion using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Xml.Schema; using System.Xml.Serialization; @@ -50,6 +51,7 @@ namespace Microsoft.VSDesigner.WCFModel return mapFile is SvcMapFile ? ((SvcMapFile)mapFile).Impl : null; } + [SuppressMessage("Microsoft.Security.Xml", "CA3060:UseXmlReaderForSchemaRead", Justification = "asp.net controls this .xsd file")] protected override XmlSchemaSet GetMapFileSchemaSet() { if (_mapFileSchemaSet == null) diff --git a/mcs/class/referencesource/System.Web.Mobile/UI/MobileControls/Adapters/ChtmlCalendarAdapter.cs b/mcs/class/referencesource/System.Web.Mobile/UI/MobileControls/Adapters/ChtmlCalendarAdapter.cs index 91b5f5e706..a68af5f0a0 100644 --- a/mcs/class/referencesource/System.Web.Mobile/UI/MobileControls/Adapters/ChtmlCalendarAdapter.cs +++ b/mcs/class/referencesource/System.Web.Mobile/UI/MobileControls/Adapters/ChtmlCalendarAdapter.cs @@ -59,7 +59,7 @@ namespace System.Web.UI.MobileControls.Adapters // This member variable is set each time when calendar info needs to // be accessed and be shared for other helper functions. - private Globalization.Calendar _threadCalendar; + private System.Globalization.Calendar _threadCalendar; private String _textBoxErrorMessage; diff --git a/mcs/class/referencesource/System.Web.Mobile/UI/MobileControls/Adapters/WmlCalendarAdapter.cs b/mcs/class/referencesource/System.Web.Mobile/UI/MobileControls/Adapters/WmlCalendarAdapter.cs index ad6d1c2ff5..c71652d11f 100644 --- a/mcs/class/referencesource/System.Web.Mobile/UI/MobileControls/Adapters/WmlCalendarAdapter.cs +++ b/mcs/class/referencesource/System.Web.Mobile/UI/MobileControls/Adapters/WmlCalendarAdapter.cs @@ -57,7 +57,7 @@ namespace System.Web.UI.MobileControls.Adapters // This member variable is set each time when calendar info needs to // be accessed and be shared for other helper functions. - private Globalization.Calendar _threadCalendar; + private System.Globalization.Calendar _threadCalendar; private String _textBoxErrorMessage; diff --git a/mcs/class/referencesource/System.Web/AspNetEventSource.cs b/mcs/class/referencesource/System.Web/AspNetEventSource.cs index 47ceee67bd..13648d0bf6 100644 --- a/mcs/class/referencesource/System.Web/AspNetEventSource.cs +++ b/mcs/class/referencesource/System.Web/AspNetEventSource.cs @@ -140,6 +140,10 @@ namespace System.Web { // Event signals that ASP.NET has started processing a request. // Overload used only for deducing ETW parameters; use the public entry point instead. // + // Visual Studio Online #222067 - This event is hardcoded to opt-out of EventSource activityID tracking. + // This would normally be done by setting ActivityOptions = EventActivityOptions.Disable in the + // Event attribute, but this causes a dependency between System.Web and mscorlib that breaks servicing. + // // !! WARNING !! // The logic in RequestStartedImpl must be kept in [....] with these parameters, otherwise // type safety violations could occur. @@ -150,6 +154,10 @@ namespace System.Web { } // Event signals that ASP.NET has completed processing a request. + // + // Visual Studio Online #222067 - This event is hardcoded to opt-out of EventSource activityID tracking. + // This would normally be done by setting ActivityOptions = EventActivityOptions.Disable in the + // Event attribute, but this causes a dependency between System.Web and mscorlib that breaks servicing. [Event((int)Events.RequestCompleted, Level = EventLevel.Informational, Task = (EventTask)Tasks.Request, Opcode = EventOpcode.Stop, Version = 1)] [MethodImpl(MethodImplOptions.AggressiveInlining)] public void RequestCompleted() { diff --git a/mcs/class/referencesource/System.Web/Cache/CacheDependency.cs b/mcs/class/referencesource/System.Web/Cache/CacheDependency.cs index 60d00f6e84..9e137fd5fc 100644 --- a/mcs/class/referencesource/System.Web/Cache/CacheDependency.cs +++ b/mcs/class/referencesource/System.Web/Cache/CacheDependency.cs @@ -909,10 +909,11 @@ namespace System.Web.Caching { return false; } - // - // This method will return only the file dependencies from this dependency - // - internal virtual string[] GetFileDependencies() + /// + /// This method will return only the file dependencies from this dependency + /// + /// + public virtual string[] GetFileDependencies() { #if USE_MEMORY_CACHE if (CacheInternal.UseMemoryCache) { @@ -1121,11 +1122,12 @@ namespace System.Web.Caching { return true; } - - // - // This method will return only the file dependencies from this dependency - // - internal override string[] GetFileDependencies() + + /// + /// This method will return only the file dependencies from this dependency + /// + /// + public override string[] GetFileDependencies() { ArrayList fileNames = null; CacheDependency[] dependencies = null; diff --git a/mcs/class/referencesource/System.Web/Cache/SRef.cs b/mcs/class/referencesource/System.Web/Cache/SRef.cs index 993569bd85..4ecdaa4301 100644 --- a/mcs/class/referencesource/System.Web/Cache/SRef.cs +++ b/mcs/class/referencesource/System.Web/Cache/SRef.cs @@ -10,6 +10,7 @@ namespace System.Web.Caching { internal class SRef { private static Type s_type = Type.GetType("System.SizedReference", true, false); private Object _sizedRef; + private long _lastReportedSize; // This helps tremendously when looking at large dumps internal SRef(Object target) { _sizedRef = HttpRuntime.CreateNonPublicInstance(s_type, new object[] {target}); @@ -24,7 +25,7 @@ namespace System.Web.Caching { _sizedRef, // target null, // args CultureInfo.InvariantCulture); - return (long) o; + return _lastReportedSize = (long) o; } } diff --git a/mcs/class/referencesource/System.Web/Cache/cache.cs b/mcs/class/referencesource/System.Web/Cache/cache.cs index 811f6e7da2..0dd2f027e6 100644 --- a/mcs/class/referencesource/System.Web/Cache/cache.cs +++ b/mcs/class/referencesource/System.Web/Cache/cache.cs @@ -519,13 +519,14 @@ namespace System.Web.Caching { internal Cache _cachePublic; internal protected CacheMemoryStats _cacheMemoryStats; private object _timerLock = new object(); - private Timer _timer; + private DisposableGCHandleRef _timerHandleRef; private int _currentPollInterval = MEMORYSTATUS_INTERVAL_30_SECONDS; internal int _inCacheManagerThread; internal bool _enableMemoryCollection; internal bool _enableExpiration; internal bool _internalConfigRead; internal SRefMultiple _srefMultiple; + private int _disposed = 0; internal CacheCommon() { _cachePublic = new Cache(0); @@ -537,13 +538,16 @@ namespace System.Web.Caching { internal void Dispose(bool disposing) { if (disposing) { - EnableCacheMemoryTimer(false); - _cacheMemoryStats.Dispose(); + // This method must be tolerant to multiple calls to Dispose on the same instance + if (Interlocked.Exchange(ref _disposed, 1) == 0) { + EnableCacheMemoryTimer(false); + _cacheMemoryStats.Dispose(); + } } } - internal void AddSRefTarget(CacheInternal c) { - _srefMultiple.AddSRefTarget(c); + internal void AddSRefTarget(object o) { + _srefMultiple.AddSRefTarget(o); } internal void SetCacheInternal(CacheInternal cacheInternal) { @@ -591,19 +595,20 @@ namespace System.Web.Caching { if (enable) { - if (_timer == null) { + if (_timerHandleRef == null) { // has not been read yet - _timer = new Timer(new TimerCallback(this.CacheManagerTimerCallback), null, _currentPollInterval, _currentPollInterval); + Timer timer = new Timer(new TimerCallback(this.CacheManagerTimerCallback), null, _currentPollInterval, _currentPollInterval); + _timerHandleRef = new DisposableGCHandleRef(timer); Debug.Trace("Cache", "Started CacheMemoryTimers"); } else { - _timer.Change(_currentPollInterval, _currentPollInterval); + _timerHandleRef.Target.Change(_currentPollInterval, _currentPollInterval); } } else { - Timer timer = _timer; - if (timer != null && Interlocked.CompareExchange(ref _timer, null, timer) == timer) { - timer.Dispose(); + var timerHandleRef = _timerHandleRef; + if (timerHandleRef != null && Interlocked.CompareExchange(ref _timerHandleRef, null, timerHandleRef) == timerHandleRef) { + timerHandleRef.Dispose(); Debug.Trace("Cache", "Stopped CacheMemoryTimers"); } } @@ -620,7 +625,7 @@ namespace System.Web.Caching { void AdjustTimer() { lock (_timerLock) { - if (_timer == null) + if (_timerHandleRef == null) return; // the order of these if statements is important @@ -629,7 +634,7 @@ namespace System.Web.Caching { if (_cacheMemoryStats.IsAboveHighPressure()) { if (_currentPollInterval > MEMORYSTATUS_INTERVAL_5_SECONDS) { _currentPollInterval = MEMORYSTATUS_INTERVAL_5_SECONDS; - _timer.Change(_currentPollInterval, _currentPollInterval); + _timerHandleRef.Target.Change(_currentPollInterval, _currentPollInterval); } return; } @@ -641,7 +646,7 @@ namespace System.Web.Caching { int newPollInterval = Math.Min(CacheMemorySizePressure.PollInterval, MEMORYSTATUS_INTERVAL_30_SECONDS); if (_currentPollInterval != newPollInterval) { _currentPollInterval = newPollInterval; - _timer.Change(_currentPollInterval, _currentPollInterval); + _timerHandleRef.Target.Change(_currentPollInterval, _currentPollInterval); } return; } @@ -649,7 +654,7 @@ namespace System.Web.Caching { // there is no pressure, interval should be the value from config if (_currentPollInterval != CacheMemorySizePressure.PollInterval) { _currentPollInterval = CacheMemorySizePressure.PollInterval; - _timer.Change(_currentPollInterval, _currentPollInterval); + _timerHandleRef.Target.Change(_currentPollInterval, _currentPollInterval); } } } @@ -666,7 +671,7 @@ namespace System.Web.Caching { #endif try { // Dev10 633335: if the timer has been disposed, return without doing anything - if (_timer == null) + if (_timerHandleRef == null) return 0; // The timer thread must always call Update so that the CacheManager @@ -1188,7 +1193,7 @@ namespace System.Web.Caching { _usage = new CacheUsage(this); _lock = new object(); _insertBlock = new ManualResetEvent(true); - cacheCommon.AddSRefTarget(this); + cacheCommon.AddSRefTarget(new { _entries, _expires, _usage }); } /* @@ -1880,24 +1885,32 @@ namespace System.Web.Caching { class CacheMultiple : CacheInternal { int _disposed; - CacheSingle[] _caches; + DisposableGCHandleRef[] _cachesRefs; int _cacheIndexMask; internal CacheMultiple(CacheCommon cacheCommon, int numSingleCaches) : base(cacheCommon) { Debug.Assert(numSingleCaches > 1, "numSingleCaches is not greater than 1"); Debug.Assert((numSingleCaches & (numSingleCaches - 1)) == 0, "numSingleCaches is not a power of 2"); _cacheIndexMask = numSingleCaches - 1; - _caches = new CacheSingle[numSingleCaches]; + + // Each CacheSingle will have its own SRef reporting the size of the data it references. + // Objects in this CacheSingle may have refs to the root Cache and therefore reference other instances of CacheSingle. + // This leads to an unbalanced tree of SRefs and makes GC less efficient while calculating multiple SRefs on multiple cores. + // Using DisposableGCHandleRef here prevents SRefs from calculating data that does not belong to other CacheSingle instances. + _cachesRefs = new DisposableGCHandleRef[numSingleCaches]; for (int i = 0; i < numSingleCaches; i++) { - _caches[i] = new CacheSingle(cacheCommon, this, i); + _cachesRefs[i] = new DisposableGCHandleRef(new CacheSingle(cacheCommon, this, i)); } } protected override void Dispose(bool disposing) { if (disposing) { if (Interlocked.Exchange(ref _disposed, 1) == 0) { - foreach (CacheSingle cacheSingle in _caches) { - cacheSingle.Dispose(); + foreach (var cacheSingleRef in _cachesRefs) { + // Unfortunately the application shutdown logic allows user to access cache even after its disposal. + // We'll keep the GCHandle inside cacheSingleRef until it gets reclaimed during appdomain shutdown. + // And we'll only dispose the Target to preserve the old behavior. + cacheSingleRef.Target.Dispose(); } } } @@ -1908,8 +1921,8 @@ namespace System.Web.Caching { internal override int PublicCount { get { int count = 0; - foreach (CacheSingle cacheSingle in _caches) { - count += cacheSingle.PublicCount; + foreach (var cacheSingleRef in _cachesRefs) { + count += cacheSingleRef.Target.PublicCount; } return count; @@ -1919,8 +1932,8 @@ namespace System.Web.Caching { internal override long TotalCount { get { long count = 0; - foreach (CacheSingle cacheSingle in _caches) { - count += cacheSingle.TotalCount; + foreach (var cacheSingleRef in _cachesRefs) { + count += cacheSingleRef.Target.TotalCount; } return count; @@ -1928,22 +1941,23 @@ namespace System.Web.Caching { } internal override IDictionaryEnumerator CreateEnumerator() { - IDictionaryEnumerator[] enumerators = new IDictionaryEnumerator[_caches.Length]; - for (int i = 0, c = _caches.Length; i < c; i++) { - enumerators[i] = _caches[i].CreateEnumerator(); + IDictionaryEnumerator[] enumerators = new IDictionaryEnumerator[_cachesRefs.Length]; + for (int i = 0, c = _cachesRefs.Length; i < c; i++) { + enumerators[i] = _cachesRefs[i].Target.CreateEnumerator(); } return new AggregateEnumerator(enumerators); } internal CacheSingle GetCacheSingle(int hashCode) { - Debug.Assert(_caches != null && _caches.Length != 0); + Debug.Assert(_cachesRefs != null && _cachesRefs.Length != 0); // Dev10 865907: Math.Abs throws OverflowException for Int32.MinValue if (hashCode < 0) { hashCode = (hashCode == Int32.MinValue) ? 0 : -hashCode; } int index = (hashCode & _cacheIndexMask); - return _caches[index]; + Debug.Assert(_cachesRefs[index].Target != null); + return _cachesRefs[index].Target; } internal override CacheEntry UpdateCache( @@ -1960,15 +1974,15 @@ namespace System.Web.Caching { internal override long TrimIfNecessary(int percent) { long count = 0; - foreach (CacheSingle cacheSingle in _caches) { - count += cacheSingle.TrimIfNecessary(percent); + foreach (var cacheSingleRef in _cachesRefs) { + count += cacheSingleRef.Target.TrimIfNecessary(percent); } return count; } internal override void EnableExpirationTimer(bool enable) { - foreach (CacheSingle cacheSingle in _caches) { - cacheSingle.EnableExpirationTimer(enable); + foreach (var cacheSingleRef in _cachesRefs) { + cacheSingleRef.Target.EnableExpirationTimer(enable); } } } diff --git a/mcs/class/referencesource/System.Web/Compilation/BuildManager.cs.REMOVED.git-id b/mcs/class/referencesource/System.Web/Compilation/BuildManager.cs.REMOVED.git-id index 461977d79e..f5481cead2 100644 --- a/mcs/class/referencesource/System.Web/Compilation/BuildManager.cs.REMOVED.git-id +++ b/mcs/class/referencesource/System.Web/Compilation/BuildManager.cs.REMOVED.git-id @@ -1 +1 @@ -9f26b6ed449d60e2c96baeff70f3bf474eaf9ecf \ No newline at end of file +65f0272002f410cb2fa2a9ac6d2b7c2ef979c154 \ No newline at end of file diff --git a/mcs/class/referencesource/System.Web/Compilation/PreservationFileReader.cs b/mcs/class/referencesource/System.Web/Compilation/PreservationFileReader.cs index ebcce1503c..b190341670 100644 --- a/mcs/class/referencesource/System.Web/Compilation/PreservationFileReader.cs +++ b/mcs/class/referencesource/System.Web/Compilation/PreservationFileReader.cs @@ -61,6 +61,7 @@ internal class PreservationFileReader { } [SuppressMessage("Microsoft.Security", "MSEC1207:UseXmlReaderForLoad", Justification = "Xml file is created by us and only accessible to admins.")] + [SuppressMessage("Microsoft.Security.Xml", "CA3056:UseXmlReaderForLoad", Justification = "Xml file is created by us and only accessible to admins.")] private BuildResult ReadFileInternal(VirtualPath virtualPath, string preservationFile, long hashCode, bool ensureIsUpToDate) { XmlDocument doc = new XmlDocument(); diff --git a/mcs/class/referencesource/System.Web/Compilation/XsdBuildProvider.cs b/mcs/class/referencesource/System.Web/Compilation/XsdBuildProvider.cs index 7802a250b5..9498833059 100644 --- a/mcs/class/referencesource/System.Web/Compilation/XsdBuildProvider.cs +++ b/mcs/class/referencesource/System.Web/Compilation/XsdBuildProvider.cs @@ -30,6 +30,7 @@ using TypedDataSetGenerator=System.Data.Design.TypedDataSetGenerator; internal class XsdBuildProvider: BuildProvider { [SuppressMessage("Microsoft.Security", "MSEC1207:UseXmlReaderForLoad", Justification = "Developer-controlled .xsd files in application directory are implicitly trusted by ASP.Net.")] + [SuppressMessage("Microsoft.Security.Xml", "CA3056:UseXmlReaderForLoad", Justification = "Developer-controlled .xml files in application directory are implicitly trusted by ASP.Net.")] public override void GenerateCode(AssemblyBuilder assemblyBuilder) { #if !FEATURE_PAL // FEATURE_PAL does not support System.Data.Design // Get the namespace that we will use diff --git a/mcs/class/referencesource/System.Web/Configuration/BrowserCapabilitiesCodeGenerator.cs b/mcs/class/referencesource/System.Web/Configuration/BrowserCapabilitiesCodeGenerator.cs index 5dd5d4b54f..01ef95f8af 100644 --- a/mcs/class/referencesource/System.Web/Configuration/BrowserCapabilitiesCodeGenerator.cs +++ b/mcs/class/referencesource/System.Web/Configuration/BrowserCapabilitiesCodeGenerator.cs @@ -32,6 +32,7 @@ namespace System.Web.Configuration { using Microsoft.Build.Utilities; using Microsoft.CSharp; + using System.Diagnostics.CodeAnalysis; [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)] [PermissionSet(SecurityAction.InheritanceDemand, Unrestricted = true)] @@ -400,6 +401,7 @@ namespace System.Web.Configuration { return false; } + [SuppressMessage("Microsoft.Security.Xml", "CA3056:UseXmlReaderForLoad", Justification = "Developer-controlled .xml files in application directory are implicitly trusted by ASP.Net.")] protected void ProcessBrowserFiles(bool useVirtualPath, string virtualDir) { _browserTree = new BrowserTree(); _defaultTree = new BrowserTree(); @@ -507,6 +509,7 @@ namespace System.Web.Configuration { ProcessCustomBrowserFiles(false, String.Empty); } + [SuppressMessage("Microsoft.Security.Xml", "CA3056:UseXmlReaderForLoad", Justification = "Developer-controlled .xml files in application directory are implicitly trusted by ASP.Net.")] internal void ProcessCustomBrowserFiles(bool useVirtualPath, string virtualDir) { //get all custom browser files and put them in the "tree" DirectoryInfo browserDirInfo = null; diff --git a/mcs/class/referencesource/System.Web/Configuration/HttpCapabilitiesSectionHandler.cs b/mcs/class/referencesource/System.Web/Configuration/HttpCapabilitiesSectionHandler.cs index cddc9f294a..2bd04aa4ba 100644 --- a/mcs/class/referencesource/System.Web/Configuration/HttpCapabilitiesSectionHandler.cs +++ b/mcs/class/referencesource/System.Web/Configuration/HttpCapabilitiesSectionHandler.cs @@ -8,6 +8,7 @@ namespace System.Web.Configuration { using System.Collections; using System.Configuration; + using System.Diagnostics.CodeAnalysis; using System.IO; using System.Security; using System.Security.Permissions; @@ -15,7 +16,6 @@ namespace System.Web.Configuration { using System.Web.Configuration; using System.Web.Util; using System.Xml; - using Pair = System.Web.UI.Pair; // @@ -276,6 +276,7 @@ namespace System.Web.Configuration { // // ResolveFiles - parse files referenced with // + [SuppressMessage("Microsoft.Security.Xml", "CA3056:UseXmlReaderForLoad", Justification = "Developer-controlled .xml files in application directory are implicitly trusted by ASP.Net.")] static void ResolveFiles(ParseState parseState, object configurationContext) { // diff --git a/mcs/class/referencesource/System.Web/Configuration/RemoteWebConfigurationHostServer.cs b/mcs/class/referencesource/System.Web/Configuration/RemoteWebConfigurationHostServer.cs index 8100d46591..e40ceb29e5 100644 --- a/mcs/class/referencesource/System.Web/Configuration/RemoteWebConfigurationHostServer.cs +++ b/mcs/class/referencesource/System.Web/Configuration/RemoteWebConfigurationHostServer.cs @@ -21,6 +21,7 @@ namespace System.Web.Configuration { using System.Security.AccessControl; #endif // !FEATURE_PAL using System.Security.Permissions; + using System.Diagnostics.CodeAnalysis; #if !FEATURE_PAL // FEATURE_PAL does not enable COM @@ -215,6 +216,7 @@ namespace System.Web.Configuration { return sb.ToString(); } + [SuppressMessage("Microsoft.Security.Xml", "CA3057:DoNotUseLoadXml", Justification = "Developer-controlled xml contents are implicitly trusted by ASP.Net.")] public string DoEncryptOrDecrypt(bool doEncrypt, string xmlString, string protectionProviderName, string protectionProviderType, string[] paramKeys, string[] paramValues) { Type t = Type.GetType(protectionProviderType, true); diff --git a/mcs/class/referencesource/System.Web/Handlers/TransferRequestHandler.cs b/mcs/class/referencesource/System.Web/Handlers/TransferRequestHandler.cs index 5c74438c23..0534ff1c51 100644 --- a/mcs/class/referencesource/System.Web/Handlers/TransferRequestHandler.cs +++ b/mcs/class/referencesource/System.Web/Handlers/TransferRequestHandler.cs @@ -6,11 +6,21 @@ namespace System.Web.Handlers { using System; + using System.Threading.Tasks; using System.Web.Hosting; - - internal class TransferRequestHandler : IHttpHandler { - - public void ProcessRequest(HttpContext context) { + + internal class TransferRequestHandler : IHttpAsyncHandler { + public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData) + { + return TaskAsyncHelper.BeginTask(() => ProcessRequestAsync(context), cb, extraData); + } + + public void EndProcessRequest(IAsyncResult result) + { + TaskAsyncHelper.EndTask(result); + } + + private Task ProcessRequestAsync(HttpContext context) { IIS7WorkerRequest wr = context.WorkerRequest as IIS7WorkerRequest; if (wr == null) { throw new PlatformNotSupportedException(SR.GetString(SR.Requires_Iis_Integrated_Mode)); @@ -24,14 +34,26 @@ namespace System.Web.Handlers { context.Request.EntityBody, null, preserveUser: false); - + // force the completion of the current request so that the // child execution can be performed immediately after unwind - context.ApplicationInstance.EnsureReleaseState(); + var releaseStateTask = context.ApplicationInstance.EnsureReleaseStateAsync(); // DevDiv Bugs 162750: IIS7 Integrated Mode: TransferRequest performance issue // Instead of calling Response.End we call HttpApplication.CompleteRequest() - context.ApplicationInstance.CompleteRequest(); + if (releaseStateTask.IsCompleted) { + context.ApplicationInstance.CompleteRequest(); + return TaskAsyncHelper.CompletedTask; + } + else { + return releaseStateTask.ContinueWith((_) => context.ApplicationInstance.CompleteRequest()); + } + } + + public void ProcessRequest(HttpContext context) + { + string errorMessage = SR.GetString(SR.HttpTaskAsyncHandler_CannotExecuteSynchronously, GetType()); + throw new NotSupportedException(errorMessage); } public bool IsReusable { diff --git a/mcs/class/referencesource/System.Web/Hosting/ApplicationManager.cs b/mcs/class/referencesource/System.Web/Hosting/ApplicationManager.cs index e02ad7fb55..9a24a5b37f 100644 --- a/mcs/class/referencesource/System.Web/Hosting/ApplicationManager.cs +++ b/mcs/class/referencesource/System.Web/Hosting/ApplicationManager.cs @@ -82,6 +82,9 @@ namespace System.Web.Hosting { // delegate OnRespondToPing private WaitCallback _onRespondToPingWaitCallback; + // flag indicates whether any fatal exception has been recorded + private bool _fatalExceptionRecorded = false; + // single instance of app manager private static ApplicationManager _theAppManager; @@ -154,6 +157,16 @@ namespace System.Web.Hosting { } } + private bool FatalExceptionRecorded + { + get { + return _fatalExceptionRecorded; + } + set { + _fatalExceptionRecorded = value; + } + } + internal static void RecordFatalException(Exception e) { RecordFatalException(AppDomain.CurrentDomain, e); } @@ -168,7 +181,7 @@ namespace System.Web.Hosting { } } - private static void OnUnhandledException(Object sender, UnhandledExceptionEventArgs eventArgs) { + internal static void OnUnhandledException(Object sender, UnhandledExceptionEventArgs eventArgs) { // if the CLR is not terminating, ignore the notification if (!eventArgs.IsTerminating) { return; @@ -184,6 +197,15 @@ namespace System.Web.Hosting { return; } + // If any fatal exception was recorded in applicaiton AppDomains, + // we wouldn't record exceptions in the default AppDomain. + var appManager = GetApplicationManager(); + if (AppDomain.CurrentDomain.IsDefaultAppDomain() && appManager.FatalExceptionRecorded) { + return; + } + + appManager.FatalExceptionRecorded = true; + RecordFatalException(appDomain, exception); } diff --git a/mcs/class/referencesource/System.Web/Hosting/HostingEnvironment.cs b/mcs/class/referencesource/System.Web/Hosting/HostingEnvironment.cs index d5d2c15e35..27ce613025 100644 --- a/mcs/class/referencesource/System.Web/Hosting/HostingEnvironment.cs +++ b/mcs/class/referencesource/System.Web/Hosting/HostingEnvironment.cs @@ -184,6 +184,11 @@ namespace System.Web.Hosting { // start watching for app domain unloading _onAppDomainUnload = new EventHandler(OnAppDomainUnload); Thread.GetDomain().DomainUnload += _onAppDomainUnload; + + // VSO 160528: We used to listen to the default AppDomain's UnhandledException only. + // However, non-serializable exceptions cannot be passed to the default domain. Therefore + // we should try to log exceptions in application AppDomains. + Thread.GetDomain().UnhandledException += new UnhandledExceptionEventHandler(ApplicationManager.OnUnhandledException); } internal long TrimCache(int percent) { diff --git a/mcs/class/referencesource/System.Web/HttpApplication.cs.REMOVED.git-id b/mcs/class/referencesource/System.Web/HttpApplication.cs.REMOVED.git-id index ff673950e1..1a38596fba 100644 --- a/mcs/class/referencesource/System.Web/HttpApplication.cs.REMOVED.git-id +++ b/mcs/class/referencesource/System.Web/HttpApplication.cs.REMOVED.git-id @@ -1 +1 @@ -eff422558e332b96b845c2f140b46d0117076596 \ No newline at end of file +41564928cced4f99e96ceacbe00249c8cc3066cd \ No newline at end of file diff --git a/mcs/class/referencesource/System.Web/HttpCacheParams.cs b/mcs/class/referencesource/System.Web/HttpCacheParams.cs index 6d4bae316f..f54da48a4a 100644 --- a/mcs/class/referencesource/System.Web/HttpCacheParams.cs +++ b/mcs/class/referencesource/System.Web/HttpCacheParams.cs @@ -39,10 +39,11 @@ namespace System.Web { _ignoreParams = -1; } - /* - * Reset based on the cached vary headers. - */ - internal void ResetFromParams(String[] parameters) { + /// + /// Set the Parameters in Cache Vary + /// + /// + public void SetParams(string[] parameters) { int i, n; Reset(); @@ -75,16 +76,20 @@ namespace System.Web { return _ignoreParams == 1 || _paramsStar || _parameters != null; } - internal String[] GetParams() { - String[] s = null; + /// + /// Get the Parameters in Cache Vary + /// + /// + public string[] GetParams() { + string[] s = null; Object item; int i, j, c, n; if (_ignoreParams == 1) { - s = new String[1] {String.Empty}; + s = new string[1] {string.Empty}; } else if (_paramsStar) { - s = new String[1] {"*"}; + s = new string[1] {"*"}; } else if (_parameters != null) { n = _parameters.Size; @@ -102,7 +107,7 @@ namespace System.Web { for (i = 0; i < n; i++) { item = _parameters.GetValue(i); if (item != null) { - s[j] = (String) item; + s[j] = (string) item; j++; } } @@ -116,7 +121,7 @@ namespace System.Web { // // Public methods and properties - // + // /// diff --git a/mcs/class/referencesource/System.Web/HttpCachePolicy.cs b/mcs/class/referencesource/System.Web/HttpCachePolicy.cs index 5cdde5d300..0e5efebd84 100644 --- a/mcs/class/referencesource/System.Web/HttpCachePolicy.cs +++ b/mcs/class/referencesource/System.Web/HttpCachePolicy.cs @@ -30,7 +30,7 @@ namespace System.Web { // // Public constants for cache-control // - + /// /// @@ -573,12 +573,10 @@ namespace System.Web { int i, n; string[] fields; - - _utcTimestampRequest = utcTimestampRequest; - - _varyByContentEncodings.ResetFromContentEncodings(settings.VaryByContentEncodings); - _varyByHeaders.ResetFromHeaders(settings.VaryByHeaders); - _varyByParams.ResetFromParams(settings.VaryByParams); + + _varyByContentEncodings.SetContentEncodings(settings.VaryByContentEncodings); + _varyByHeaders.SetHeaders(settings.VaryByHeaders); + _varyByParams.SetParams(settings.VaryByParams); _isModified = settings.IsModified; _hasSetCookieHeader = settings.hasSetCookieHeader; @@ -645,7 +643,11 @@ namespace System.Web { } } - internal bool IsModified() { + /// + /// Return true if the CachePolicy has been modified + /// + /// + public bool IsModified() { return _isModified || _varyByContentEncodings.IsModified() || _varyByHeaders.IsModified() || _varyByParams.IsModified(); } @@ -771,20 +773,18 @@ namespace System.Web { return; } - Debug.Assert((_utcTimestampCreated == DateTime.MinValue && _utcTimestampRequest == DateTime.MinValue) || - (_utcTimestampCreated != DateTime.MinValue && _utcTimestampRequest != DateTime.MinValue), - "_utcTimestampCreated and _utcTimestampRequest are out of [....] in UpdateCachedHeaders"); - + //To enable Out of Band OutputCache Module support, we will always refresh the UtcTimestampRequest. if (_utcTimestampCreated == DateTime.MinValue) { - _utcTimestampCreated = _utcTimestampRequest = response.Context.UtcTimestamp; + _utcTimestampCreated = response.Context.UtcTimestamp; } + _utcTimestampRequest = response.Context.UtcTimestamp; if (_slidingExpiration != 1) { _slidingDelta = TimeSpan.Zero; } else if (_isMaxAgeSet) { _slidingDelta = _maxAge; - } + } else if (_isExpiresSet) { _slidingDelta = _utcExpires - _utcTimestampCreated; } @@ -840,7 +840,7 @@ namespace System.Web { } sb.Append('\"'); - } + } if (_noStore) { AppendValueToHeader(sb, "no-store"); @@ -1056,10 +1056,10 @@ namespace System.Web { headers.Add(_headerVaryBy); } } - + /* - * Public methods - */ + * Public methods + */ internal HttpCachePolicySettings GetCurrentSettings(HttpResponse response) { String[] varyByContentEncodings; @@ -1191,6 +1191,16 @@ namespace System.Web { return absoluteExpiration; } + // Expose this property to OutputCacheUtility class + // In order to enable Out of Band output cache module to access the Validation Callback Info + internal IEnumerable GetValidationCallbacks() { + if (_validationCallbackInfo == null) { + return new ArrayList(); + } + + return _validationCallbackInfo; + } + /* * Cache at server? */ @@ -1203,7 +1213,11 @@ namespace System.Web { _noServerCaching = true; } - internal bool GetNoServerCaching() { + /// + /// Return True if we should stops all server caching for current response + /// + /// + public bool GetNoServerCaching() { return _noServerCaching; } @@ -1229,6 +1243,13 @@ namespace System.Web { _varyByCustom = custom; } + /// + /// Get the Vary by Custom Value + /// + /// + public string GetVaryByCustom() { + return _varyByCustom; + } /* * Cache-Control: extension */ @@ -1250,6 +1271,14 @@ namespace System.Web { } } + /// + /// Get Cache Extensions Value + /// + /// + public string GetCacheExtensions() { + return _cacheExtension; + } + /* * Cache-Control: no-transform */ @@ -1263,11 +1292,27 @@ namespace System.Web { _noTransforms = true; } + /// + /// Return true if No-transform directive, enables the sending of the CacheControl + /// + /// + public bool GetNoTransforms() { + return _noTransforms; + } + internal void SetIgnoreRangeRequests() { Dirtied(); _ignoreRangeRequests = true; } + /// + /// Return true if ignore range request + /// + /// + public bool GetIgnoreRangeRequests() { + return _ignoreRangeRequests; + } + /// /// Contains policy for the Vary: header. /// @@ -1320,11 +1365,15 @@ namespace System.Web { } } - internal HttpCacheability GetCacheability() { + /// + /// Get the Cache-control (public, private and no-cache) directive + /// + /// + public HttpCacheability GetCacheability() { return _cacheability; } - - + + /// /// Sets the Cache-Control header to one of the values of HttpCacheability in /// conjunction with a field-level exclusion directive. @@ -1376,6 +1425,14 @@ namespace System.Web { Dirtied(); _hasUserProvidedDependencies = hasUserProvidedDependencies; } + + /// + /// return true if no store is set + /// + /// + public bool GetNoStore() { + return _noStore; + } /* * Expiration policy. @@ -1405,6 +1462,14 @@ namespace System.Web { } } + /// + /// Return the expire header as absolute expire datetime + /// + /// + public DateTime GetExpires() { + return _utcExpires; + } + /* * Cache-Control: max-age=delta-seconds */ @@ -1428,6 +1493,14 @@ namespace System.Web { } } + /// + /// Get the Cache-Control Max Age + /// + /// + public TimeSpan GetMaxAge() { + return _maxAge; + } + // Suppress max-age and s-maxage in cache-control header (required for IIS6 kernel mode cache) internal void SetNoMaxAgeInCacheControl() { _noMaxAgeInCacheControl = true; @@ -1452,6 +1525,14 @@ namespace System.Web { } } + /// + /// Get the Cache-Control: Proxy Max Age Value + /// + /// + public TimeSpan GetProxyMaxAge() { + return _proxyMaxAge; + } + /* * Sliding Expiration */ @@ -1470,6 +1551,17 @@ namespace System.Web { } } + /// + /// Return true if to make expiration sliding. that is, if cached, it should be renewed with each + /// response. This feature is identical in spirit to the IIS + /// configuration option to add an expiration header relative to the current response + /// time. This feature is identical in spirit to the IIS configuration option to add + /// an expiration header relative to the current response time. + /// + /// + public bool HasSlidingExpiration() { + return _slidingExpiration == 1; + } public void SetValidUntilExpires(bool validUntilExpires) { if (_validUntilExpires == -1 || _validUntilExpires == 1) { @@ -1478,6 +1570,13 @@ namespace System.Web { } } + /// + /// Return true if valid until expires + /// + /// + public bool IsValidUntilExpires() { + return _validUntilExpires == 1; + } public void SetAllowResponseInBrowserHistory(bool allow) { if (_allowInHistory == -1 || _allowInHistory == 1) { @@ -1512,7 +1611,17 @@ namespace System.Web { } } - /* + /// + /// Get the Cache-Control: header to reflect either the must-revalidate or + /// proxy-revalidate directives. + /// The default is to not send either of these directives unless explicitly enabled using this method. + /// + /// + public HttpCacheRevalidation GetRevalidation() { + return _revalidation; + } + + /* * Etag */ @@ -1537,6 +1646,16 @@ namespace System.Web { _etag = etag; } + /// + /// Get the ETag header. Once an ETag is set, + /// subsequent attempts to set it will fail and an exception will be thrown. + /// + /// + public string GetETag() { + return _etag; + } + + /* * Last-Modified: RFC Date */ @@ -1577,6 +1696,14 @@ namespace System.Web { } } + /// + /// Get the Last-Modified header. + /// + /// + public DateTime GetUtcLastModified() { + return _utcLastModified; + } + /// /// Sets the Last-Modified: header based on the timestamps of the @@ -1587,6 +1714,15 @@ namespace System.Web { _generateLastModifiedFromFiles = true; } + /// + /// Return true if the Last-Modified header is set to base on the timestamps of the + /// file dependencies of the handler. + /// + /// + public bool GetLastModifiedFromFileDependencies() { + return _generateLastModifiedFromFiles; + } + /// /// Sets the Etag header based on the timestamps of the file @@ -1601,6 +1737,14 @@ namespace System.Web { _generateEtagFromFiles = true; } + /// + /// Return true if the Etag header has been set to base on the timestamps of the file + /// dependencies of the handler + /// + /// + public bool GetETagFromFileDependencies() { + return _generateEtagFromFiles; + } public void SetOmitVaryStar(bool omit) { Dirtied(); @@ -1610,6 +1754,13 @@ namespace System.Web { } } + /// + /// Return true if to omit Vary Star + /// + /// + public int GetOmitVaryStar() { + return _omitVaryStar; + } /// /// Registers a validation callback for the current response. @@ -1628,5 +1779,16 @@ namespace System.Web { _validationCallbackInfo.Add(new ValidationCallbackInfo(handler, data)); } + /// + /// Utc Timestamp Created + /// + public DateTime UtcTimestampCreated { + get { + return _utcTimestampCreated; + } + set { + _utcTimestampCreated = value; + } + } } } diff --git a/mcs/class/referencesource/System.Web/HttpCacheVary.cs b/mcs/class/referencesource/System.Web/HttpCacheVary.cs index e55c71d051..7f8a952f00 100644 --- a/mcs/class/referencesource/System.Web/HttpCacheVary.cs +++ b/mcs/class/referencesource/System.Web/HttpCacheVary.cs @@ -37,10 +37,12 @@ namespace System.Web { _headers = null; } - /* - * Reset based on the cached vary headers. - */ - internal void ResetFromHeaders(String[] headers) { + /// + /// Set the Headers in Cache Vary + /// + /// + public void SetHeaders(string[] headers) { + int i, n; if (headers == null) { @@ -48,7 +50,7 @@ namespace System.Web { _varyStar = false; _headers = null; } - else { + else { _isModified = true; if (headers[0].Equals("*")) { Debug.Assert(headers.Length == 1, "headers.Length == 1"); @@ -97,19 +99,19 @@ namespace System.Web { return null; } + + /// + /// Get the Headers in Cache Vary + /// + /// + public string[] GetHeaders() { + string[] s = null; - /* - * Returns the headers, for package access only. - * - * @return the headers. - */ - internal String[] GetHeaders() { - String[] s = null; Object item; int i, j, c, n; if (_varyStar) { - return new String[1] {"*"}; + return new string[1] {"*"}; } else if (_headers != null) { n = _headers.Size; @@ -127,7 +129,7 @@ namespace System.Web { for (i = 0; i < n; i++) { item = _headers.GetValue(i); if (item != null) { - s[j] = (String) item; + s[j] = (string) item; j++; } } @@ -138,7 +140,7 @@ namespace System.Web { return s; } - + // // Public methods and properties // diff --git a/mcs/class/referencesource/System.Web/HttpCacheVaryByContentEncodings.cs b/mcs/class/referencesource/System.Web/HttpCacheVaryByContentEncodings.cs index fe1e6d355f..236adffa9a 100644 --- a/mcs/class/referencesource/System.Web/HttpCacheVaryByContentEncodings.cs +++ b/mcs/class/referencesource/System.Web/HttpCacheVaryByContentEncodings.cs @@ -32,11 +32,13 @@ namespace System.Web { _isModified = false; _contentEncodings = null; } + + /// + /// Set the Content Encodings in Cache Vary + /// + /// + public void SetContentEncodings(string[] contentEncodings) { - /* - * Reset based on content encodings. - */ - internal void ResetFromContentEncodings(String[] contentEncodings) { Reset(); if (contentEncodings != null) { _isModified = true; @@ -75,9 +77,18 @@ namespace System.Web { internal bool IsModified() { return _isModified; } - - internal String[] GetContentEncodings() { - return _contentEncodings; + + /// + /// Get the Content Encodings in Cache Vary + /// + /// + public string[] GetContentEncodings() { + if (_contentEncodings != null) { + string[] contentEncodings = new string[_contentEncodings.Length]; + _contentEncodings.CopyTo(contentEncodings, 0); + return contentEncodings; + } + return null; } // diff --git a/mcs/class/referencesource/System.Web/HttpContext.cs b/mcs/class/referencesource/System.Web/HttpContext.cs index 4d02a0a8a8..812c779064 100644 --- a/mcs/class/referencesource/System.Web/HttpContext.cs +++ b/mcs/class/referencesource/System.Web/HttpContext.cs @@ -22,6 +22,7 @@ namespace System.Web { using System.Linq; using System.Net; using System.Reflection; + using System.Runtime.CompilerServices; using System.Runtime.Remoting.Messaging; using System.Security.Permissions; using System.Security.Principal; @@ -1009,6 +1010,8 @@ namespace System.Web { if (_delayedSessionState) { lock (this) { if (_delayedSessionState) { + Debug.Assert(_sessionStateModule != null, "_sessionStateModule != null"); + // If it's not null, it means we have a delayed session state item _sessionStateModule.InitStateStoreItem(true); _delayedSessionState = false; @@ -1020,8 +1023,21 @@ namespace System.Web { } } + [MethodImpl(MethodImplOptions.NoInlining)] internal void EnsureSessionStateIfNecessary() { - Debug.Assert(_sessionStateModule != null, "_sessionStateModule != null"); + if (_sessionStateModule == null) + { + // If _sessionStateModule is null, we wouldn't be able to call + // _sessionStateModule.EnsureStateStoreItemLocked(), so we return here. + // _sessionStateModule could be null in the following cases, + // 1. No session state acquired. + // 2. HttpResponse.Flush() happens after session state being released. + // 3. The session state module in use is not System.Web.SessionState.SessionStateModule. + // + // This method is for the in-framework SessionStateModule only. + // OOB SessionStateModule can achieve this by using HttpResponse.AddOnSendingHeaders. + return; + } HttpSessionState session = (HttpSessionState)Items[SessionStateUtility.SESSION_KEY]; @@ -1042,7 +1058,6 @@ namespace System.Web { } internal void RemoveHttpSessionStateModule() { - Debug.Assert(_sessionStateModule != null, "_sessionStateModule != null"); _delayedSessionState = false; _sessionStateModule = null; } diff --git a/mcs/class/referencesource/System.Web/HttpResponse.cs.REMOVED.git-id b/mcs/class/referencesource/System.Web/HttpResponse.cs.REMOVED.git-id index 7fbe9fa049..d5c9be1b34 100644 --- a/mcs/class/referencesource/System.Web/HttpResponse.cs.REMOVED.git-id +++ b/mcs/class/referencesource/System.Web/HttpResponse.cs.REMOVED.git-id @@ -1 +1 @@ -b92ce62520ba19dc4df09601e85545381237d6a8 \ No newline at end of file +db4f721437c45c7d9fe7606f9d2221e0256a32a8 \ No newline at end of file diff --git a/mcs/class/referencesource/System.Web/ModelBinding/DataAnnotationsModelMetadataProvider.cs b/mcs/class/referencesource/System.Web/ModelBinding/DataAnnotationsModelMetadataProvider.cs index aa91b33062..3c0296df9e 100644 --- a/mcs/class/referencesource/System.Web/ModelBinding/DataAnnotationsModelMetadataProvider.cs +++ b/mcs/class/referencesource/System.Web/ModelBinding/DataAnnotationsModelMetadataProvider.cs @@ -4,6 +4,7 @@ using System.ComponentModel; using System.ComponentModel.DataAnnotations; using System.Linq; + using System.Web.Globalization; public class DataAnnotationsModelMetadataProvider : AssociatedMetadataProvider { @@ -11,7 +12,7 @@ List attributeList = new List(attributes); DisplayColumnAttribute displayColumnAttribute = attributeList.OfType().FirstOrDefault(); DataAnnotationsModelMetadata result = new DataAnnotationsModelMetadata(this, containerType, modelAccessor, modelType, propertyName, displayColumnAttribute); - + #if UNDEF // Do [HiddenInput] before [UIHint], so you can override the template hint HiddenInputAttribute hiddenInputAttribute = attributeList.OfType().FirstOrDefault(); @@ -71,12 +72,13 @@ DisplayAttribute display = attributes.OfType().FirstOrDefault(); string name = null; if (display != null) { - result.Description = display.GetDescription(); - result.ShortDisplayName = display.GetShortName(); - result.Watermark = display.GetPrompt(); - result.Order = display.GetOrder() ?? ModelMetadata.DefaultOrder; + var displayAdapter = new DisplayAttributeAdapter(display); + result.Description = displayAdapter.GetDescription(); + result.ShortDisplayName = displayAdapter.GetShortName(); + result.Watermark = displayAdapter.GetPrompt(); + result.Order = displayAdapter.GetOrder() ?? ModelMetadata.DefaultOrder; - name = display.GetName(); + name = displayAdapter.GetName(); } if (name != null) { diff --git a/mcs/class/referencesource/System.Web/ModelBinding/DataAnnotationsModelValidator.cs b/mcs/class/referencesource/System.Web/ModelBinding/DataAnnotationsModelValidator.cs index cff887cbb5..79bf561a2a 100644 --- a/mcs/class/referencesource/System.Web/ModelBinding/DataAnnotationsModelValidator.cs +++ b/mcs/class/referencesource/System.Web/ModelBinding/DataAnnotationsModelValidator.cs @@ -2,8 +2,10 @@ using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; + using System.Threading; + using System.Web.Globalization; - public class DataAnnotationsModelValidator : ModelValidator { + public class DataAnnotationsModelValidator : ModelValidator { public DataAnnotationsModelValidator(ModelMetadata metadata, ModelBindingExecutionContext context, ValidationAttribute attribute) : base(metadata, context) { @@ -18,7 +20,24 @@ protected internal string ErrorMessage { get { - return Attribute.FormatErrorMessage(Metadata.GetDisplayName()); + if (UseStringLocalizerProvider) { + var errorMsg = GetLocalizedString(Attribute.ErrorMessage); + + return errorMsg ?? Attribute.FormatErrorMessage(Metadata.GetDisplayName()); + } + else { + return Attribute.FormatErrorMessage(Metadata.GetDisplayName()); + } + } + } + + protected string GetLocalizedString(string name, params object[] arguments) { + if (StringLocalizerProviders.DataAnnotationStringLocalizerProvider != null) { + return StringLocalizerProviders.DataAnnotationStringLocalizerProvider + .GetLocalizedString(Thread.CurrentThread.CurrentUICulture, name, arguments); + } + else { + return null; } } @@ -55,9 +74,37 @@ ValidationResult result = Attribute.GetValidationResult(Metadata.Model, context); if (result != ValidationResult.Success) { yield return new ModelValidationResult { - Message = result.ErrorMessage + Message = GetValidationErrorMessage(result) }; } } + + protected virtual string GetLocalizedErrorMessage(string errorMessage) { + return GetLocalizedString(errorMessage, Metadata.GetDisplayName()); + } + + private string GetValidationErrorMessage(ValidationResult result) { + string errorMsg; + + if (UseStringLocalizerProvider) { + errorMsg = GetLocalizedErrorMessage(Attribute.ErrorMessage); + + errorMsg = errorMsg ?? result.ErrorMessage; + } + else { + errorMsg = result.ErrorMessage; + } + return errorMsg; + } + + private bool UseStringLocalizerProvider { + get { + // if developer already uses existing localization feature, + // then we don't opt in the new localization feature. + return (!string.IsNullOrEmpty(Attribute.ErrorMessage) && + string.IsNullOrEmpty(Attribute.ErrorMessageResourceName) && + Attribute.ErrorMessageResourceType == null); + } + } } } diff --git a/mcs/class/referencesource/System.Web/ModelBinding/DataAnnotationsModelValidatorProvider.cs b/mcs/class/referencesource/System.Web/ModelBinding/DataAnnotationsModelValidatorProvider.cs index 11cce2416e..ae952e12a8 100644 --- a/mcs/class/referencesource/System.Web/ModelBinding/DataAnnotationsModelValidatorProvider.cs +++ b/mcs/class/referencesource/System.Web/ModelBinding/DataAnnotationsModelValidatorProvider.cs @@ -1,5 +1,5 @@ namespace System.Web.ModelBinding { - using System; +using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Diagnostics.CodeAnalysis; @@ -7,6 +7,7 @@ using System.Globalization; using System.Linq; using System.Reflection; using System.Threading; +using System.Web.Globalization; // A factory for validators based on ValidationAttribute public delegate ModelValidator DataAnnotationsModelValidationFactory(ModelMetadata metadata, ModelBindingExecutionContext context, ValidationAttribute attribute); @@ -26,7 +27,7 @@ using System.Threading; public class DataAnnotationsModelValidatorProvider : AssociatedValidatorProvider { private static bool _addImplicitRequiredAttributeForValueTypes = true; private static ReaderWriterLockSlim _adaptersLock = new ReaderWriterLockSlim(); - + // Factories for validation attributes internal static DataAnnotationsModelValidationFactory DefaultAttributeFactory = @@ -49,6 +50,14 @@ using System.Threading; typeof(StringLengthAttribute), (metadata, context, attribute) => new StringLengthAttributeAdapter(metadata, context, (StringLengthAttribute)attribute) }, + { + typeof(MinLengthAttribute), + (metadata, context, attribute) => new MinLengthAttributeAdapter(metadata, context, (MinLengthAttribute)attribute) + }, + { + typeof(MaxLengthAttribute), + (metadata, context, attribute) => new MaxLengthAttributeAdapter(metadata, context, (MaxLengthAttribute)attribute) + }, }; // Factories for IValidatableObject models @@ -66,7 +75,7 @@ using System.Threading; _addImplicitRequiredAttributeForValueTypes = value; } } - + protected override IEnumerable GetValidators(ModelMetadata metadata, ModelBindingExecutionContext context, IEnumerable attributes) { _adaptersLock.EnterReadLock(); diff --git a/mcs/class/referencesource/System.Web/ModelBinding/RangeAttributeAdapter.cs b/mcs/class/referencesource/System.Web/ModelBinding/RangeAttributeAdapter.cs index 2c5acf046f..28858643c1 100644 --- a/mcs/class/referencesource/System.Web/ModelBinding/RangeAttributeAdapter.cs +++ b/mcs/class/referencesource/System.Web/ModelBinding/RangeAttributeAdapter.cs @@ -6,6 +6,11 @@ : base(metadata, context, attribute) { } + protected override string GetLocalizedErrorMessage(string errorMessage) { + return GetLocalizedString(errorMessage, Metadata.GetDisplayName(), Attribute.Minimum, Attribute.Maximum); + + } + #if UNDEF public override IEnumerable GetClientValidationRules() { string errorMessage = ErrorMessage; // Per Dev10 Bug #923283, need to make sure ErrorMessage is called before Minimum/Maximum diff --git a/mcs/class/referencesource/System.Web/ModelBinding/RegularExpressionAttributeAdapter.cs b/mcs/class/referencesource/System.Web/ModelBinding/RegularExpressionAttributeAdapter.cs index c5c0f0d527..2a49853c2f 100644 --- a/mcs/class/referencesource/System.Web/ModelBinding/RegularExpressionAttributeAdapter.cs +++ b/mcs/class/referencesource/System.Web/ModelBinding/RegularExpressionAttributeAdapter.cs @@ -6,6 +6,10 @@ : base(metadata, context, attribute) { } + protected override string GetLocalizedErrorMessage(string errorMessage) { + return GetLocalizedString(errorMessage, Metadata.GetDisplayName(), Attribute.Pattern); + } + #if UNDEF public override IEnumerable GetClientValidationRules() { return new[] { new ModelClientValidationRegexRule(ErrorMessage, Attribute.Pattern) }; diff --git a/mcs/class/referencesource/System.Web/ModelBinding/StringLengthAttributeAdapter.cs b/mcs/class/referencesource/System.Web/ModelBinding/StringLengthAttributeAdapter.cs index 354cc3a861..a27cba17df 100644 --- a/mcs/class/referencesource/System.Web/ModelBinding/StringLengthAttributeAdapter.cs +++ b/mcs/class/referencesource/System.Web/ModelBinding/StringLengthAttributeAdapter.cs @@ -6,6 +6,10 @@ : base(metadata, context, attribute) { } + protected override string GetLocalizedErrorMessage(string errorMessage) { + return GetLocalizedString(errorMessage, Metadata.GetDisplayName(), Attribute.MinimumLength, Attribute.MaximumLength); + } + #if UNDEF public override IEnumerable GetClientValidationRules() { return new[] { new ModelClientValidationStringLengthRule(ErrorMessage, Attribute.MinimumLength, Attribute.MaximumLength) }; diff --git a/mcs/class/referencesource/System.Web/Security/Cryptography/CryptoAlgorithms.cs b/mcs/class/referencesource/System.Web/Security/Cryptography/CryptoAlgorithms.cs index a4fcc08f63..a4147901f2 100644 --- a/mcs/class/referencesource/System.Web/Security/Cryptography/CryptoAlgorithms.cs +++ b/mcs/class/referencesource/System.Web/Security/Cryptography/CryptoAlgorithms.cs @@ -44,6 +44,7 @@ namespace System.Web.Security.Cryptography { return new DESCryptoServiceProvider(); } + [SuppressMessage("Microsoft.Security.Cryptography", "CA5354:SHA1CannotBeUsed", Justification = @"This is only used by legacy code; new features do not use this algorithm.")] internal static HMACSHA1 CreateHMACSHA1() { return new HMACSHA1(); } diff --git a/mcs/class/referencesource/System.Web/Security/FormsIdentity.cs b/mcs/class/referencesource/System.Web/Security/FormsIdentity.cs index 2fba9c4592..a07c223408 100644 --- a/mcs/class/referencesource/System.Web/Security/FormsIdentity.cs +++ b/mcs/class/referencesource/System.Web/Security/FormsIdentity.cs @@ -17,6 +17,7 @@ namespace System.Web.Security { using System.Security; using System.Security.Claims; using System.Security.Permissions; + using System.Security.Principal; /// /// This class is an IIdentity derived class @@ -77,7 +78,7 @@ namespace System.Web.Security { /// Constructor. /// protected FormsIdentity(FormsIdentity identity) - : base(identity) + : base((IIdentity)identity) { _Ticket = identity._Ticket; } diff --git a/mcs/class/referencesource/System.Web/State/SessionStateModule.cs b/mcs/class/referencesource/System.Web/State/SessionStateModule.cs index 2e9144cceb..84b3d55a8a 100644 --- a/mcs/class/referencesource/System.Web/State/SessionStateModule.cs +++ b/mcs/class/referencesource/System.Web/State/SessionStateModule.cs @@ -27,6 +27,7 @@ namespace System.Web.SessionState { using System.Globalization; using System.Security.Permissions; using System.Text; + using System.Threading.Tasks; using System.Web.Hosting; using System.Web.Management; using Microsoft.Win32; @@ -111,7 +112,7 @@ namespace System.Web.SessionState { /// /// [To be supplied.] /// - public sealed class SessionStateModule : IHttpModule { + public sealed class SessionStateModule : ISessionStateModule { internal const string SQL_CONNECTION_STRING_DEFAULT = "data source=localhost;Integrated Security=SSPI"; internal const string STATE_CONNECTION_STRING_DEFAULT = "tcpip=loopback:42424"; @@ -1446,15 +1447,19 @@ namespace System.Web.SessionState { } } } - - // DevDiv Bugs 151914: Release session state before executing child request - internal void EnsureReleaseState(HttpApplication app) { + + public void ReleaseSessionState(HttpContext context) { if (HttpRuntime.UseIntegratedPipeline && _acquireCalled && !_releaseCalled) { try { - OnReleaseState(app, null); + OnReleaseState(context.ApplicationInstance, null); } catch { } } } + + public Task ReleaseSessionStateAsync(HttpContext context) { + ReleaseSessionState(context); + return TaskAsyncHelper.CompletedTask; + } } } diff --git a/mcs/class/referencesource/System.Web/State/SessionStateUtil.cs b/mcs/class/referencesource/System.Web/State/SessionStateUtil.cs index 8116fbc271..19c6d73938 100644 --- a/mcs/class/referencesource/System.Web/State/SessionStateUtil.cs +++ b/mcs/class/referencesource/System.Web/State/SessionStateUtil.cs @@ -73,6 +73,24 @@ namespace System.Web.SessionState { return context.Application.SessionStaticObjects.Clone(); } + /// + /// Gets a value that indicates whether session state is required by the context. + /// + /// The HttpContext. + /// A value that indicates whether session state is required by the context. + static public bool IsSessionStateRequired(HttpContext context) { + return context.RequiresSessionState; + } + + /// + /// Gets a value that indicates whether session state is read-only in the context. + /// + /// The HttpContext. + /// A value that indicates whether session state is read-only in the context. + static public bool IsSessionStateReadOnly(HttpContext context) { + return context.ReadOnlySessionState; + } + internal static SessionStateStoreData CreateLegitStoreData(HttpContext context, ISessionStateItemCollection sessionItems, HttpStaticObjectsCollection staticObjects, diff --git a/mcs/class/referencesource/System.Web/TaskAsyncHelper.cs b/mcs/class/referencesource/System.Web/TaskAsyncHelper.cs index 2558f75a0d..85e2bef8a0 100644 --- a/mcs/class/referencesource/System.Web/TaskAsyncHelper.cs +++ b/mcs/class/referencesource/System.Web/TaskAsyncHelper.cs @@ -16,6 +16,8 @@ namespace System.Web { internal static class TaskAsyncHelper { + private static readonly Task s_completedTask = Task.FromResult(null); + internal static IAsyncResult BeginTask(Func taskFunc, AsyncCallback callback, object state) { Task task = taskFunc(); if (task == null) { @@ -76,5 +78,10 @@ namespace System.Web { taskWrapper.Task.GetAwaiter().GetResult(); } + internal static Task CompletedTask { + get { + return s_completedTask; + } + } } } diff --git a/mcs/class/referencesource/System.Web/UI/PartialCachingControl.cs b/mcs/class/referencesource/System.Web/UI/PartialCachingControl.cs index 9efc13a587..e70f02a264 100644 --- a/mcs/class/referencesource/System.Web/UI/PartialCachingControl.cs +++ b/mcs/class/referencesource/System.Web/UI/PartialCachingControl.cs @@ -6,27 +6,27 @@ namespace System.Web.UI { -using System; -using System.IO; -using System.Text; -using System.Collections; -using System.Collections.Specialized; -using System.ComponentModel; -using System.ComponentModel.Design; -using System.Globalization; -using System.Web; -using System.Web.Util; -using System.Web.UI.HtmlControls; -using System.Web.UI.WebControls; -using System.Web.Caching; -using System.Web.Compilation; -using System.Web.Configuration; -using System.Security.Permissions; + using System; + using System.IO; + using System.Text; + using System.Collections; + using System.Collections.Specialized; + using System.ComponentModel; + using System.ComponentModel.Design; + using System.Globalization; + using System.Web; + using System.Web.Util; + using System.Web.UI.HtmlControls; + using System.Web.UI.WebControls; + using System.Web.Caching; + using System.Web.Compilation; + using System.Web.Configuration; + using System.Security.Permissions; -// Keeps track of one call to Page Register* API -// The semantics of the fields depends to the call type -[Serializable] + // Keeps track of one call to Page Register* API + // The semantics of the fields depends to the call type + [Serializable] internal class RegisterCallData { internal ClientAPIRegisterType Type; internal ScriptKey Key; @@ -406,8 +406,8 @@ public abstract class BasePartialCachingControl : Control { } else { string[] varyByParams = null; - if (_varyByParamsCollection != null) - varyByParams = _varyByParamsCollection.GetParams(); + if (_varyByParamsCollection != null) + varyByParams = _varyByParamsCollection.GetParams(); cachedVary = new ControlCachedVary(varyByParams, _varyByControlsCollection, _varyByCustom); @@ -576,7 +576,7 @@ public abstract class BasePartialCachingControl : Control { string[] varyByParamsStrings = varyByParams.Split(varySeparator); _varyByParamsCollection = new HttpCacheVaryByParams(); - _varyByParamsCollection.ResetFromParams(varyByParamsStrings); + _varyByParamsCollection.SetParams(varyByParamsStrings); } internal void RegisterPostBackScript() { diff --git a/mcs/class/referencesource/System.Web/UI/WebControls/Calendar.cs b/mcs/class/referencesource/System.Web/UI/WebControls/Calendar.cs index ce3d85949f..ea3c1e08be 100644 --- a/mcs/class/referencesource/System.Web/UI/WebControls/Calendar.cs +++ b/mcs/class/referencesource/System.Web/UI/WebControls/Calendar.cs @@ -56,7 +56,7 @@ namespace System.Web.UI.WebControls { private ArrayList dateList; private SelectedDatesCollection selectedDates; - private Globalization.Calendar threadCalendar; + private System.Globalization.Calendar threadCalendar; private DateTime minSupportedDate; private DateTime maxSupportedDate; #if DEBUG diff --git a/mcs/class/referencesource/System.Web/UI/WebControls/QueryExtensions.cs b/mcs/class/referencesource/System.Web/UI/WebControls/QueryExtensions.cs index ac1bbae574..3657d75cca 100644 --- a/mcs/class/referencesource/System.Web/UI/WebControls/QueryExtensions.cs +++ b/mcs/class/referencesource/System.Web/UI/WebControls/QueryExtensions.cs @@ -32,7 +32,17 @@ namespace System.Web.UI.WebControls { } ParameterExpression parameter = Expression.Parameter(source.ElementType, String.Empty); - MemberExpression property = Expression.Property(parameter, sortExpression); + //VSO bug 173528-- Add support for sorting by nested property names + MemberExpression property = null; + string[] sortExpressionFields = sortExpression.Split('.'); + foreach (string sortExpressionField in sortExpressionFields) { + if (property == null) { + property = Expression.Property(parameter, sortExpressionField); + } + else { + property = Expression.Property(property, sortExpressionField); + } + } LambdaExpression lambda = Expression.Lambda(property, parameter); string methodName = (isDescending) ? "OrderByDescending" : "OrderBy" ; diff --git a/mcs/class/referencesource/System.Web/UI/WebControls/xml.cs b/mcs/class/referencesource/System.Web/UI/WebControls/xml.cs index bb97a7c282..93ec3e60d0 100644 --- a/mcs/class/referencesource/System.Web/UI/WebControls/xml.cs +++ b/mcs/class/referencesource/System.Web/UI/WebControls/xml.cs @@ -41,6 +41,7 @@ namespace System.Web.UI.WebControls { [SuppressMessage("Microsoft.Security", "MSEC1220:ReviewDtdProcessingAssignment", Justification = "Dtd processing is needed for back-compat, but is being done as safely as possible.")] + [SuppressMessage("Microsoft.Security.Xml", "CA3069:ReviewDtdProcessingAssignment", Justification = "Dtd processing is needed for back-compat, but is being done as safely as possible.")] public override void SetTagInnerText(string text) { if (!Util.IsWhiteSpaceString(text)) { @@ -114,7 +115,9 @@ namespace System.Web.UI.WebControls { #pragma warning restore 0618 [SuppressMessage("Microsoft.Security", "MSEC1201:DoNotUseXslTransform", Justification = "_identityTransform contents are trusted hard-coded string.")] + [SuppressMessage("Microsoft.Security.Xml", "CA3050:DoNotUseXslTransform", Justification = "_identityTransform contents are trusted hard-coded string.")] [SuppressMessage("Microsoft.Security", "MSEC1205:DoNotAllowDtdOnXmlTextReader", Justification = "_identityTransform contents are trusted hard-coded string.")] + [SuppressMessage("Microsoft.Security.Xml", "CA3054:DoNotAllowDtdOnXmlTextReader", Justification = "_identityTransform contents are trusted hard-coded string.")] [PermissionSet(SecurityAction.Assert, Unrestricted = true)] static Xml() { @@ -332,6 +335,7 @@ namespace System.Web.UI.WebControls { [SuppressMessage("Microsoft.Security", "MSEC1218:ReviewWebControlForSet_DocumentContent", Justification = "Legacy code that trusts our developer input. Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")] + [SuppressMessage("Microsoft.Security.Xml", "CA3067:ReviewWebControlForSet_DocumentContent", Justification = "Legacy code that trusts our developer input. Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")] protected override void AddParsedSubObject(object obj) { if (obj is LiteralControl) { // Trim the initial whitespaces since XML is very picky (related to ASURT 58100) diff --git a/mcs/class/referencesource/System.Web/Util/GCUtil.cs b/mcs/class/referencesource/System.Web/Util/GCUtil.cs index 0e48e6d162..f6c84a2177 100644 --- a/mcs/class/referencesource/System.Web/Util/GCUtil.cs +++ b/mcs/class/referencesource/System.Web/Util/GCUtil.cs @@ -36,4 +36,33 @@ namespace System.Web.Util { } } + + // This wrapper around a managed object is opaque to SizedReference GC handle + // and therefore helps with calculating size of only relevant graph of objects + internal class DisposableGCHandleRef : IDisposable + where T : class, IDisposable { + GCHandle _handle; + [PermissionSet(SecurityAction.Assert, Unrestricted = true)] + public DisposableGCHandleRef(T t) { + Debug.Assert(t != null); + _handle = GCHandle.Alloc(t); + } + + public T Target { + [PermissionSet(SecurityAction.Assert, Unrestricted = true)] + get { + Debug.Assert(_handle.IsAllocated); + return (T)_handle.Target; + } + } + + [PermissionSet(SecurityAction.Assert, Unrestricted = true)] + public void Dispose() { + Target.Dispose(); + Debug.Assert(_handle.IsAllocated); + if (_handle.IsAllocated) { + _handle.Free(); + } + } + } } diff --git a/mcs/class/referencesource/System.Web/Util/StringUtil.cs b/mcs/class/referencesource/System.Web/Util/StringUtil.cs index 545023b7a2..94ef87f029 100644 --- a/mcs/class/referencesource/System.Web/Util/StringUtil.cs +++ b/mcs/class/referencesource/System.Web/Util/StringUtil.cs @@ -15,6 +15,7 @@ using System.Text; using System.Globalization; using System.Runtime.InteropServices; using System.Web.Hosting; +using System.Diagnostics.CodeAnalysis; /* * Various string handling utilities @@ -294,6 +295,7 @@ internal static class StringUtil { // Instead use the default AppDomain, because it doesn't have string hash randomization enabled. // Marshal the call to reuse the default StringComparer behavior. // PERF isn't optimal, so apply consideration! + [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Justification = "We carefully control the callers.")] internal static int GetNonRandomizedStringComparerHashCode(string s) { // Preserve the default behavior when string hash randomization is off if (!AppSettings.UseRandomizedStringHashAlgorithm) { diff --git a/mcs/class/referencesource/System.Web/Util/SynchronizationHelper.cs b/mcs/class/referencesource/System.Web/Util/SynchronizationHelper.cs index d442f0cc89..64a86b6811 100644 --- a/mcs/class/referencesource/System.Web/Util/SynchronizationHelper.cs +++ b/mcs/class/referencesource/System.Web/Util/SynchronizationHelper.cs @@ -105,7 +105,7 @@ namespace System.Web.Util { // This method only schedules work; it doesn't itself do any work. The lock is held for a very // short period of time. lock (_lockObj) { - Task newTask = _lastScheduledTask.ContinueWith(_ => SafeWrapCallback(action)); + Task newTask = _lastScheduledTask.ContinueWith(_ => SafeWrapCallback(action), TaskScheduler.Default); _lastScheduledTask = newTask; // the newly-created task is now the last one } } diff --git a/mcs/class/referencesource/System.Web/Util/XmlUtils.cs b/mcs/class/referencesource/System.Web/Util/XmlUtils.cs index eb237040da..a07e9df58d 100644 --- a/mcs/class/referencesource/System.Web/Util/XmlUtils.cs +++ b/mcs/class/referencesource/System.Web/Util/XmlUtils.cs @@ -17,6 +17,7 @@ namespace System.Web.Util { public static readonly long MaxEntityExpansion = 1024 * 1024; [SuppressMessage("Microsoft.Security", "MSEC1208:DoNotUseLoadXml", Justification = "Handles developer-controlled input xml. Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")] + [SuppressMessage("Microsoft.Security.Xml", "CA3057:DoNotUseLoadXml", Justification = "Handles developer-controlled input xml. Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")] public static XmlDocument CreateXmlDocumentFromContent(string content) { XmlDocument doc = new XmlDocument(); @@ -35,6 +36,7 @@ namespace System.Web.Util { } [SuppressMessage("Microsoft.Security", "MSEC1210:UseXmlReaderForXPathDocument", Justification = "Handles developer-controlled input xml. Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")] + [SuppressMessage("Microsoft.Security.Xml", "CA3059:UseXmlReaderForXPathDocument", Justification = "Handles developer-controlled input xml. Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")] public static XPathDocument CreateXPathDocumentFromContent(string content) { StringReader reader = new StringReader(content); @@ -47,6 +49,7 @@ namespace System.Web.Util { } [SuppressMessage("Microsoft.Security", "MSEC1220:ReviewDtdProcessingAssignment", Justification = "Dtd processing is needed for back-compat, but is being done as safely as possible.")] + [SuppressMessage("Microsoft.Security.Xml", "CA3069:ReviewDtdProcessingAssignment", Justification = "Dtd processing is needed for back-compat, but is being done as safely as possible.")] public static XmlReaderSettings CreateXmlReaderSettings() { XmlReaderSettings settings = new XmlReaderSettings(); @@ -68,7 +71,9 @@ namespace System.Web.Util { // try to guess at how to set matching defaults with XmlReader.Create(). // (E.g. DtdProcessing is Parse by default using XmlTextReader directly. It's Prohibit in default XmlReaderSettings.) [SuppressMessage("Microsoft.Security", "MSEC1205:DoNotAllowDtdOnXmlTextReader", Justification = "Handles trusted or developer-controlled input xml. Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")] + [SuppressMessage("Microsoft.Security.Xml", "CA3054:DoNotAllowDtdOnXmlTextReader", Justification = "Handles trusted or developer-controlled input xml. Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")] [SuppressMessage("Microsoft.Security", "MSEC1225:ReviewClassesDerivedFromXmlTextReader", Justification = "NoEntitiesXmlReader is our internal mechanism for using XmlTextReaders in a reasonably safe manner.")] + [SuppressMessage("Microsoft.Security.Xml", "CA3074:ReviewClassesDerivedFromXmlTextReader", Justification = "NoEntitiesXmlReader is our internal mechanism for using XmlTextReaders in a reasonably safe manner.")] public static XmlReader CreateXmlReader(string filepath) { if (AppSettings.RestrictXmlControls) @@ -84,7 +89,9 @@ namespace System.Web.Util { } [SuppressMessage("Microsoft.Security", "MSEC1205:DoNotAllowDtdOnXmlTextReader", Justification = "Handles trusted or developer-controlled input xml. Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")] + [SuppressMessage("Microsoft.Security.Xml", "CA3054:DoNotAllowDtdOnXmlTextReader", Justification = "Handles trusted or developer-controlled input xml. Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")] [SuppressMessage("Microsoft.Security", "MSEC1225:ReviewClassesDerivedFromXmlTextReader", Justification = "NoEntitiesXmlReader is our internal mechanism for using XmlTextReaders in a reasonably safe manner.")] + [SuppressMessage("Microsoft.Security.Xml", "CA3074:ReviewClassesDerivedFromXmlTextReader", Justification = "NoEntitiesXmlReader is our internal mechanism for using XmlTextReaders in a reasonably safe manner.")] public static XmlReader CreateXmlReader(Stream datastream) { if (AppSettings.RestrictXmlControls) @@ -100,7 +107,9 @@ namespace System.Web.Util { } [SuppressMessage("Microsoft.Security", "MSEC1205:DoNotAllowDtdOnXmlTextReader", Justification = "Handles trusted or developer-controlled input xml. Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")] + [SuppressMessage("Microsoft.Security.Xml", "CA3054:DoNotAllowDtdOnXmlTextReader", Justification = "Handles trusted or developer-controlled input xml. Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")] [SuppressMessage("Microsoft.Security", "MSEC1225:ReviewClassesDerivedFromXmlTextReader", Justification = "NoEntitiesXmlReader is our internal mechanism for using XmlTextReaders in a reasonably safe manner.")] + [SuppressMessage("Microsoft.Security.Xml", "CA3074:ReviewClassesDerivedFromXmlTextReader", Justification = "NoEntitiesXmlReader is our internal mechanism for using XmlTextReaders in a reasonably safe manner.")] public static XmlReader CreateXmlReader(TextReader reader) { if (AppSettings.RestrictXmlControls) @@ -116,7 +125,9 @@ namespace System.Web.Util { } [SuppressMessage("Microsoft.Security", "MSEC1205:DoNotAllowDtdOnXmlTextReader", Justification = "Handles trusted or developer-controlled input xml. Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")] + [SuppressMessage("Microsoft.Security.Xml", "CA3054:DoNotAllowDtdOnXmlTextReader", Justification = "Handles trusted or developer-controlled input xml. Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")] [SuppressMessage("Microsoft.Security", "MSEC1225:ReviewClassesDerivedFromXmlTextReader", Justification = "NoEntitiesXmlReader is our internal mechanism for using XmlTextReaders in a reasonably safe manner.")] + [SuppressMessage("Microsoft.Security.Xml", "CA3074:ReviewClassesDerivedFromXmlTextReader", Justification = "NoEntitiesXmlReader is our internal mechanism for using XmlTextReaders in a reasonably safe manner.")] public static XmlReader CreateXmlReader(Stream contentStream, string baseURI) { if (AppSettings.RestrictXmlControls) @@ -179,6 +190,7 @@ namespace System.Web.Util { #pragma warning disable 0618 // To avoid deprecation warning [SuppressMessage("Microsoft.Security", "MSEC1201:DoNotUseXslTransform", Justification = "Handles developer-controlled input xsl. Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")] + [SuppressMessage("Microsoft.Security.Xml", "CA3050:DoNotUseXslTransform", Justification = "Handles developer-controlled input xsl. Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")] public static XslTransform CreateXslTransform(XmlReader reader) { if (!AppSettings.RestrictXmlControls) @@ -191,6 +203,7 @@ namespace System.Web.Util { } [SuppressMessage("Microsoft.Security", "MSEC1201:DoNotUseXslTransform", Justification = "Handles developer-controlled input xsl. Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")] + [SuppressMessage("Microsoft.Security.Xml", "CA3050:DoNotUseXslTransform", Justification = "Handles developer-controlled input xsl. Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")] public static XslTransform CreateXslTransform(XmlReader reader, XmlResolver resolver) { if (!AppSettings.RestrictXmlControls) diff --git a/mcs/class/referencesource/System.Web/XmlSiteMapProvider.cs b/mcs/class/referencesource/System.Web/XmlSiteMapProvider.cs index 736c8f48b8..917aeea915 100644 --- a/mcs/class/referencesource/System.Web/XmlSiteMapProvider.cs +++ b/mcs/class/referencesource/System.Web/XmlSiteMapProvider.cs @@ -232,6 +232,7 @@ namespace System.Web { [SuppressMessage("Microsoft.Security", "MSEC1205:DoNotAllowDtdOnXmlTextReader", Justification = "Legacy code that trusts our developer-controlled input.")] + [SuppressMessage("Microsoft.Security.Xml", "CA3054:DoNotAllowDtdOnXmlTextReader", Justification = "Legacy code that trusts our developer-controlled input.")] public override SiteMapNode BuildSiteMap() { SiteMapNode tempNode = _siteMapNode; diff --git a/mcs/class/referencesource/System.Workflow.ComponentModel/AuthoringOM/Compiler/CompileXomlTask.cs b/mcs/class/referencesource/System.Workflow.ComponentModel/AuthoringOM/Compiler/CompileXomlTask.cs index 5290f57da1..d1a7668ea7 100644 --- a/mcs/class/referencesource/System.Workflow.ComponentModel/AuthoringOM/Compiler/CompileXomlTask.cs +++ b/mcs/class/referencesource/System.Workflow.ComponentModel/AuthoringOM/Compiler/CompileXomlTask.cs @@ -6,6 +6,7 @@ namespace System.Workflow.ComponentModel.Compiler using System.Diagnostics; using System.Globalization; using System.IO; + using System.Xml; using System.Text; using System.Collections; using System.Collections.Specialized; @@ -1142,7 +1143,7 @@ namespace System.Workflow.ComponentModel.Compiler string name = null; try { - Xml.XmlTextReader reader = new Xml.XmlTextReader(binaryStream); + Xml.XmlTextReader reader = new Xml.XmlTextReader(binaryStream) { DtdProcessing = DtdProcessing.Prohibit }; if (reader.MoveToContent() == System.Xml.XmlNodeType.Element) { if (reader.MoveToAttribute("Class", StandardXomlKeys.Definitions_XmlNs)) diff --git a/mcs/class/referencesource/System.Workflow.ComponentModel/AuthoringOM/Design/ComponentSerializationService.cs b/mcs/class/referencesource/System.Workflow.ComponentModel/AuthoringOM/Design/ComponentSerializationService.cs index 1e658c689b..5488a93ae6 100644 --- a/mcs/class/referencesource/System.Workflow.ComponentModel/AuthoringOM/Design/ComponentSerializationService.cs +++ b/mcs/class/referencesource/System.Workflow.ComponentModel/AuthoringOM/Design/ComponentSerializationService.cs @@ -193,7 +193,7 @@ namespace System.Workflow.ComponentModel.Design { ArrayList objects = new ArrayList(); WorkflowMarkupSerializationManager xomlSerializationManager = new WorkflowMarkupSerializationManager(serializationManager); - XmlTextReader reader = new XmlTextReader(this.serializedXmlString, XmlNodeType.Element, null); + XmlTextReader reader = new XmlTextReader(this.serializedXmlString, XmlNodeType.Element, null) { DtdProcessing = DtdProcessing.Prohibit }; reader.MoveToElement(); do { @@ -235,7 +235,7 @@ namespace System.Workflow.ComponentModel.Design xomlSerializationManager.AddSerializationProvider(propertySegmentSerializationProvider); StringReader stringReader = new StringReader(this.serializedXmlString); - using (XmlTextReader reader = new XmlTextReader(stringReader)) + using (XmlTextReader reader = new XmlTextReader(stringReader) { DtdProcessing = DtdProcessing.Prohibit }) { while (reader.NodeType != XmlNodeType.Element && reader.NodeType != XmlNodeType.ProcessingInstruction && reader.Read()); diff --git a/mcs/class/referencesource/System.Workflow.Runtime/Tracking.cs b/mcs/class/referencesource/System.Workflow.Runtime/Tracking.cs index 55ef70d719..df277deaef 100644 --- a/mcs/class/referencesource/System.Workflow.Runtime/Tracking.cs +++ b/mcs/class/referencesource/System.Workflow.Runtime/Tracking.cs @@ -1837,18 +1837,25 @@ namespace System.Workflow.Runtime return HashServiceType(serviceType.AssemblyQualifiedName); } - [SuppressMessage("Microsoft.Cryptographic.Standard", "CA5350:MD5CannotBeUsed", + [SuppressMessage("Microsoft.Cryptographic.Standard", "CA5350:MD5CannotBeUsed", Justification = "Design has been approved. We are not using MD5 for any security or cryptography purposes but rather as a hash.")] internal static Guid HashServiceType(String serviceFullTypeName) { - MD5 md5 = new MD5CryptoServiceProvider(); byte[] data; byte[] result; UnicodeEncoding ue = new UnicodeEncoding(); data = ue.GetBytes(serviceFullTypeName); - result = md5.ComputeHash(data); + if (AppSettings.FIPSRequired) + { + result = MD5PInvokeHelper.CalculateHash(data); + } + else + { + MD5 md5 = new MD5CryptoServiceProvider(); + result = md5.ComputeHash(data); + } return new Guid(result); } diff --git a/mcs/class/referencesource/System.Workflow.Runtime/Tracking/TrackingProfileSerializer.cs b/mcs/class/referencesource/System.Workflow.Runtime/Tracking/TrackingProfileSerializer.cs index 79d95e3450..7c6905f92b 100644 --- a/mcs/class/referencesource/System.Workflow.Runtime/Tracking/TrackingProfileSerializer.cs +++ b/mcs/class/referencesource/System.Workflow.Runtime/Tracking/TrackingProfileSerializer.cs @@ -28,7 +28,8 @@ namespace System.Workflow.Runtime.Tracking { public TrackingProfileSerializer() { - _schema = XmlSchema.Read(new StringReader(_xsd), null); + StringReader reader = new StringReader(_xsd); + _schema = XmlSchema.Read(new XmlTextReader(reader) { DtdProcessing = DtdProcessing.Prohibit }, null); _schema.Namespaces.Add("", _ns); } diff --git a/mcs/class/referencesource/System.Workflow.Runtime/WorkflowRuntime.cs b/mcs/class/referencesource/System.Workflow.Runtime/WorkflowRuntime.cs index 718b7556e4..1697c08565 100644 --- a/mcs/class/referencesource/System.Workflow.Runtime/WorkflowRuntime.cs +++ b/mcs/class/referencesource/System.Workflow.Runtime/WorkflowRuntime.cs @@ -129,6 +129,17 @@ namespace System.Workflow.Runtime // listen to activity definition resolve events Activity.ActivityResolve += OnActivityDefinitionResolve; Activity.WorkflowChangeActionsResolve += OnWorkflowChangeActionsResolve; + + try + { + using (TelemetryEventSource eventSource = new TelemetryEventSource()) + { + eventSource.V1Runtime(); + } + } + catch + { + } } public WorkflowRuntime() diff --git a/mcs/class/referencesource/System.Xml/InternalApis/Clr/inc/AppContextDefaultValues.cs b/mcs/class/referencesource/System.Xml/InternalApis/Clr/inc/AppContextDefaultValues.cs index 8a130a0f34..9224bf8b8f 100644 --- a/mcs/class/referencesource/System.Xml/InternalApis/Clr/inc/AppContextDefaultValues.cs +++ b/mcs/class/referencesource/System.Xml/InternalApis/Clr/inc/AppContextDefaultValues.cs @@ -3,6 +3,15 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== + +// There are cases where we have multiple assemblies that are going to import this file and +// if they are going to also have InternalsVisibleTo between them, there will be a compiler warning +// that the type is found both in the source and in a referenced assembly. The compiler will prefer +// the version of the type defined in the source +// +// In order to disable the warning for this type we are disabling this warning for this entire file. +#pragma warning disable 436 + using System; using System.Collections.Generic; @@ -167,3 +176,5 @@ namespace System static partial void PopulateDefaultValuesPartial(string platformIdentifier, string profile, int version); } } + +#pragma warning restore 436 diff --git a/mcs/class/referencesource/System.Xml/InternalApis/Clr/inc/LocalAppContext.cs b/mcs/class/referencesource/System.Xml/InternalApis/Clr/inc/LocalAppContext.cs index f05b599ed3..33662b5428 100644 --- a/mcs/class/referencesource/System.Xml/InternalApis/Clr/inc/LocalAppContext.cs +++ b/mcs/class/referencesource/System.Xml/InternalApis/Clr/inc/LocalAppContext.cs @@ -4,6 +4,14 @@ // // ==--== +// There are cases where we have multiple assemblies that are going to import this file and +// if they are going to also have InternalsVisibleTo between them, there will be a compiler warning +// that the type is found both in the source and in a referenced assembly. The compiler will prefer +// the version of the type defined in the source +// +// In order to disable the warning for this type we are disabling this warning for this entire file. +#pragma warning disable 436 + // NOTE: This file should not be included in mscorlib. This should only be included in FX libraries that need to provide switches using System; using System.Collections.Generic; @@ -126,3 +134,5 @@ namespace System } } } + +#pragma warning restore 436 diff --git a/mcs/class/referencesource/System.Xml/System/Xml/Core/AppContextDefaultValues.Defaults.cs b/mcs/class/referencesource/System.Xml/System/Xml/Core/AppContextDefaultValues.Defaults.cs index 01ac463e47..ac29b89384 100644 --- a/mcs/class/referencesource/System.Xml/System/Xml/Core/AppContextDefaultValues.Defaults.cs +++ b/mcs/class/referencesource/System.Xml/System/Xml/Core/AppContextDefaultValues.Defaults.cs @@ -28,6 +28,10 @@ namespace System LocalAppContext.DefineSwitchDefault("Switch.System.Xml.DontThrowOnInvalidSurrogatePairs", true); LocalAppContext.DefineSwitchDefault("Switch.System.Xml.IgnoreEmptyKeySequences", true); } + if (version <= 40601) + { + LocalAppContext.DefineSwitchDefault("Switch.System.Xml.IgnoreKindInUtcTimeSerialization", true); + } break; } case "WindowsPhone": @@ -37,6 +41,7 @@ namespace System { LocalAppContext.DefineSwitchDefault("Switch.System.Xml.DontThrowOnInvalidSurrogatePairs", true); LocalAppContext.DefineSwitchDefault("Switch.System.Xml.IgnoreEmptyKeySequences", true); + LocalAppContext.DefineSwitchDefault("Switch.System.Xml.IgnoreKindInUtcTimeSerialization", true); } break; } diff --git a/mcs/class/referencesource/System.Xml/System/Xml/Core/LocalAppContextSwitches.cs b/mcs/class/referencesource/System.Xml/System/Xml/Core/LocalAppContextSwitches.cs index c744ba1c0d..ddc3323413 100644 --- a/mcs/class/referencesource/System.Xml/System/Xml/Core/LocalAppContextSwitches.cs +++ b/mcs/class/referencesource/System.Xml/System/Xml/Core/LocalAppContextSwitches.cs @@ -29,5 +29,15 @@ namespace System return LocalAppContext.GetCachedSwitchValue(@"Switch.System.Xml.IgnoreEmptyKeySequences", ref _ignoreEmptyKeySequences); } } + + private static int _ignoreKindInUtcTimeSerialization; + public static bool IgnoreKindInUtcTimeSerialization + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return LocalAppContext.GetCachedSwitchValue(@"Switch.System.Xml.IgnoreKindInUtcTimeSerialization", ref _ignoreKindInUtcTimeSerialization); + } + } } } diff --git a/mcs/class/referencesource/System.Xml/System/Xml/Serialization/Xmlcustomformatter.cs b/mcs/class/referencesource/System.Xml/System/Xml/Serialization/Xmlcustomformatter.cs index d186daa2aa..9803815594 100644 --- a/mcs/class/referencesource/System.Xml/System/Xml/Serialization/Xmlcustomformatter.cs +++ b/mcs/class/referencesource/System.Xml/System/Xml/Serialization/Xmlcustomformatter.cs @@ -77,7 +77,14 @@ namespace System.Xml.Serialization { } internal static string FromTime(DateTime value) { - return XmlConvert.ToString(DateTime.MinValue + value.TimeOfDay, "HH:mm:ss.fffffffzzzzzz"); + if (!LocalAppContextSwitches.IgnoreKindInUtcTimeSerialization && value.Kind == DateTimeKind.Utc) + { + return XmlConvert.ToString(DateTime.MinValue + value.TimeOfDay, "HH:mm:ss.fffffffZ"); + } + else + { + return XmlConvert.ToString(DateTime.MinValue + value.TimeOfDay, "HH:mm:ss.fffffffzzzzzz"); + } } internal static string FromDateTime(DateTime value) { @@ -337,7 +344,14 @@ namespace System.Xml.Serialization { } internal static DateTime ToTime(string value) { - return DateTime.ParseExact(value, allTimeFormats, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AllowLeadingWhite|DateTimeStyles.AllowTrailingWhite|DateTimeStyles.NoCurrentDateDefault); + if (!LocalAppContextSwitches.IgnoreKindInUtcTimeSerialization) + { + return DateTime.ParseExact(value, allTimeFormats, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AllowLeadingWhite | DateTimeStyles.AllowTrailingWhite | DateTimeStyles.NoCurrentDateDefault | DateTimeStyles.RoundtripKind); + } + else + { + return DateTime.ParseExact(value, allTimeFormats, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AllowLeadingWhite | DateTimeStyles.AllowTrailingWhite | DateTimeStyles.NoCurrentDateDefault); + } } internal static char ToChar(string value) { diff --git a/mcs/class/referencesource/System/InternalApis/Clr/inc/AppContextDefaultValues.cs b/mcs/class/referencesource/System/InternalApis/Clr/inc/AppContextDefaultValues.cs index 8a130a0f34..9224bf8b8f 100644 --- a/mcs/class/referencesource/System/InternalApis/Clr/inc/AppContextDefaultValues.cs +++ b/mcs/class/referencesource/System/InternalApis/Clr/inc/AppContextDefaultValues.cs @@ -3,6 +3,15 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== + +// There are cases where we have multiple assemblies that are going to import this file and +// if they are going to also have InternalsVisibleTo between them, there will be a compiler warning +// that the type is found both in the source and in a referenced assembly. The compiler will prefer +// the version of the type defined in the source +// +// In order to disable the warning for this type we are disabling this warning for this entire file. +#pragma warning disable 436 + using System; using System.Collections.Generic; @@ -167,3 +176,5 @@ namespace System static partial void PopulateDefaultValuesPartial(string platformIdentifier, string profile, int version); } } + +#pragma warning restore 436 diff --git a/mcs/class/referencesource/System/InternalApis/Clr/inc/LocalAppContext.cs b/mcs/class/referencesource/System/InternalApis/Clr/inc/LocalAppContext.cs index f05b599ed3..33662b5428 100644 --- a/mcs/class/referencesource/System/InternalApis/Clr/inc/LocalAppContext.cs +++ b/mcs/class/referencesource/System/InternalApis/Clr/inc/LocalAppContext.cs @@ -4,6 +4,14 @@ // // ==--== +// There are cases where we have multiple assemblies that are going to import this file and +// if they are going to also have InternalsVisibleTo between them, there will be a compiler warning +// that the type is found both in the source and in a referenced assembly. The compiler will prefer +// the version of the type defined in the source +// +// In order to disable the warning for this type we are disabling this warning for this entire file. +#pragma warning disable 436 + // NOTE: This file should not be included in mscorlib. This should only be included in FX libraries that need to provide switches using System; using System.Collections.Generic; @@ -126,3 +134,5 @@ namespace System } } } + +#pragma warning restore 436 diff --git a/mcs/class/referencesource/System/InternalApis/NDP_Common/inc/PinnableBufferCache.cs b/mcs/class/referencesource/System/InternalApis/NDP_Common/inc/PinnableBufferCache.cs index 872cfa80dd..19ec1053a3 100644 --- a/mcs/class/referencesource/System/InternalApis/NDP_Common/inc/PinnableBufferCache.cs +++ b/mcs/class/referencesource/System/InternalApis/NDP_Common/inc/PinnableBufferCache.cs @@ -155,7 +155,14 @@ namespace System if (PinnableBufferCacheEventSource.Log.IsEnabled()) PinnableBufferCacheEventSource.Log.FreeBuffer(m_CacheName, PinnableBufferCacheEventSource.AddressOf(buffer), buffer.GetHashCode(), m_FreeList.Count); - + if(buffer == null) + { + if (PinnableBufferCacheEventSource.Log.IsEnabled()) + PinnableBufferCacheEventSource.Log.FreeBufferNull(m_CacheName, m_FreeList.Count); + + return; + } + // After we've done 3 gen1 GCs, assume that all buffers have aged into gen2 on the free path. if ((m_gen1CountAtLastRestock + 3) > GC.CollectionCount(GC.MaxGeneration - 1)) { @@ -567,6 +574,7 @@ namespace System public void AllocateBufferAged(string cacheName, int agedCount) {} public void AllocateBufferFreeListEmpty(string cacheName, int notGen2CountBefore) {} public void FreeBuffer(string cacheName, ulong objectId, int objectHash, int freeCountBefore) {} + public void FreeBufferNull(string cacheName, int freeCountBefore) { } public void FreeBufferStillTooYoung(string cacheName, int notGen2CountBefore) {} public void TrimCheck(string cacheName, int totalBuffs, bool neededMoreThanFreeList, int deltaMSec) {} public void TrimFree(string cacheName, int totalBuffs, int freeListCount, int toBeFreed) {} @@ -643,6 +651,8 @@ namespace System public void AgePendingBuffersResults(string cacheName, int promotedToFreeListCount, int heldBackCount) { if (IsEnabled()) WriteEvent(20, cacheName, promotedToFreeListCount, heldBackCount); } [Event(21)] public void WalkFreeListResult(string cacheName, int freeListCount, int gen0BuffersInFreeList) { if (IsEnabled()) WriteEvent(21, cacheName, freeListCount, gen0BuffersInFreeList); } + [Event(22)] + public void FreeBufferNull(string cacheName, int freeCountBefore) { if(IsEnabled()) WriteEvent(22, cacheName, freeCountBefore); } static internal ulong AddressOf(object obj) diff --git a/mcs/class/referencesource/System/compmod/microsoft/win32/UnsafeNativeMethods.cs b/mcs/class/referencesource/System/compmod/microsoft/win32/UnsafeNativeMethods.cs index a1911293b0..9587402297 100644 --- a/mcs/class/referencesource/System/compmod/microsoft/win32/UnsafeNativeMethods.cs +++ b/mcs/class/referencesource/System/compmod/microsoft/win32/UnsafeNativeMethods.cs @@ -169,6 +169,23 @@ namespace Microsoft.Win32 { [ResourceExposure(ResourceScope.None)] public static extern bool WTSUnRegisterSessionNotification(HandleRef hWnd); + private static IntPtr GetCurrentProcessToken() { return new IntPtr(-4); } + + private const int ERROR_SUCCESS = 0; + + enum AppPolicyClrCompat + { + AppPolicyClrCompat_Others = 0, + AppPolicyClrCompat_ClassicDesktop = 1, + AppPolicyClrCompat_Universal = 2, + AppPolicyClrCompat_PackagedDesktop = 3 + }; + + [DllImport(ExternDll.Kernel32, CharSet = CharSet.None, EntryPoint = "AppPolicyGetClrCompat")] + [System.Security.SecuritySafeCritical] + [return: MarshalAs(UnmanagedType.I4)] + private static extern Int32 _AppPolicyGetClrCompat(IntPtr processToken, out AppPolicyClrCompat appPolicyClrCompat); + private const int ERROR_INSUFFICIENT_BUFFER = 0x007A; private const int ERROR_NO_PACKAGE_IDENTITY = 0x3d54; @@ -204,8 +221,20 @@ namespace Microsoft.Win32 { [System.Security.SecuritySafeCritical] private static bool _IsPackagedProcess() { + Version windows8Version = new Version(6, 2, 0, 0); OperatingSystem os = Environment.OSVersion; - if(os.Platform == PlatformID.Win32NT && os.Version >= new Version(6,2,0,0) && DoesWin32MethodExist(ExternDll.Kernel32, "GetCurrentPackageId")) + bool osSupportsPackagedProcesses = os.Platform == PlatformID.Win32NT && os.Version >= windows8Version; + + if (osSupportsPackagedProcesses && DoesWin32MethodExist(ExternDll.Kernel32, "AppPolicyGetClrCompat")) + { + // Use AppPolicyGetClrCompat if it is available. Return true if and only if this is a UWA which means if + // this is packaged desktop app this method will return false. This may cause some confusion however + // this is necessary to make the behavior of packaged desktop apps identical to desktop apps. + AppPolicyClrCompat appPolicyClrCompat; + return _AppPolicyGetClrCompat(GetCurrentProcessToken(), out appPolicyClrCompat) == ERROR_SUCCESS && + appPolicyClrCompat == AppPolicyClrCompat.AppPolicyClrCompat_Universal; + } + else if(osSupportsPackagedProcesses && DoesWin32MethodExist(ExternDll.Kernel32, "GetCurrentPackageId")) { Int32 bufLen = 0; // Will return ERROR_INSUFFICIENT_BUFFER when running within a packaged application, diff --git a/mcs/class/referencesource/System/compmod/system/componentmodel/MemberDescriptor.cs b/mcs/class/referencesource/System/compmod/system/componentmodel/MemberDescriptor.cs index c16486800a..ebc36a83d4 100644 --- a/mcs/class/referencesource/System/compmod/system/componentmodel/MemberDescriptor.cs +++ b/mcs/class/referencesource/System/compmod/system/componentmodel/MemberDescriptor.cs @@ -326,9 +326,19 @@ namespace System.ComponentModel { return false; } - if ((mdObj.description == null) != (description == null) || - (description != null && !mdObj.category.Equals(description))) { - return false; + // VSO 149471 - Technically fixing this could cause a behavior change, so we are + // adding a quirk in case anyone is bit by this and needs the old, buggy behavior. + if (!LocalAppContextSwitches.MemberDescriptorEqualsReturnsFalseIfEquivalent) { + if ((mdObj.description == null) != (description == null) || + (description != null && !mdObj.description.Equals(description))) { + return false; + } + } + else { + if ((mdObj.description == null) != (description == null) || + (description != null && !mdObj.category.Equals(description))) { + return false; + } } if ((mdObj.attributes == null) != (attributes == null)) { diff --git a/mcs/class/referencesource/System/net/System/Net/Cache/RequestCacheManager.cs b/mcs/class/referencesource/System/net/System/Net/Cache/RequestCacheManager.cs index d1927650d7..198f982db9 100644 --- a/mcs/class/referencesource/System/net/System/Net/Cache/RequestCacheManager.cs +++ b/mcs/class/referencesource/System/net/System/Net/Cache/RequestCacheManager.cs @@ -101,11 +101,15 @@ using System.Configuration; { if (s_CacheConfigSettings == null) { +#if MONO + var settings = new RequestCachingSectionInternal(); +#else RequestCachingSectionInternal settings = RequestCachingSectionInternal.GetSection(); s_DefaultGlobalBinding = new RequestCacheBinding (settings.DefaultCache, settings.DefaultHttpValidator, settings.DefaultCachePolicy); s_DefaultHttpBinding = new RequestCacheBinding (settings.DefaultCache, settings.DefaultHttpValidator, settings.DefaultHttpCachePolicy); s_DefaultFtpBinding = new RequestCacheBinding (settings.DefaultCache, settings.DefaultFtpValidator, settings.DefaultFtpCachePolicy); +#endif s_CacheConfigSettings = settings; } @@ -113,6 +117,22 @@ using System.Configuration; } } +#if MONO + class RequestCacheValidator + { + public object CreateValidator () + { + throw new NotImplementedException (); + } + } + + class RequestCachingSectionInternal + { + // TODO: Implement + public readonly bool DisableAllCaching = true; + } +#endif + // // internal class RequestCacheBinding { diff --git a/mcs/class/referencesource/System/net/System/Net/Configuration/DefaultProxySection.cs b/mcs/class/referencesource/System/net/System/Net/Configuration/DefaultProxySection.cs index 13b735ef54..cee3b6b2eb 100644 --- a/mcs/class/referencesource/System/net/System/Net/Configuration/DefaultProxySection.cs +++ b/mcs/class/referencesource/System/net/System/Net/Configuration/DefaultProxySection.cs @@ -17,7 +17,7 @@ namespace System.Net.Configuration using System.Security.Principal; using System.ComponentModel; - +#if !MONO public sealed class DefaultProxySection : ConfigurationSection { public DefaultProxySection() @@ -134,9 +134,10 @@ namespace System.Net.Configuration base.Reset(defaultElement); } } - +#endif internal sealed class DefaultProxySectionInternal { +#if !MONO [SecurityPermission(SecurityAction.Assert, Flags=SecurityPermissionFlag.ControlPrincipal)] internal DefaultProxySectionInternal(DefaultProxySection section) { @@ -274,6 +275,50 @@ namespace System.Net.Configuration this.webProxy.Credentials = SystemNetworkCredential.defaultCredential; } } +#else + + static IWebProxy GetDefaultProxy_UsingOldMonoCode() + { +#if CONFIGURATION_DEP + DefaultProxySection sec = ConfigurationManager.GetSection ("system.net/defaultProxy") as DefaultProxySection; + WebProxy p; + + if (sec == null) + return GetSystemWebProxy (); + + ProxyElement pe = sec.Proxy; + + if ((pe.UseSystemDefault != ProxyElement.UseSystemDefaultValues.False) && (pe.ProxyAddress == null)) { + IWebProxy proxy = GetSystemWebProxy (); + + if (!(proxy is WebProxy)) + return proxy; + + p = (WebProxy) proxy; + } else + p = new WebProxy (); + + if (pe.ProxyAddress != null) + p.Address = pe.ProxyAddress; + + if (pe.BypassOnLocal != ProxyElement.BypassOnLocalValues.Unspecified) + p.BypassProxyOnLocal = (pe.BypassOnLocal == ProxyElement.BypassOnLocalValues.True); + + foreach(BypassElement elem in sec.BypassList) + p.BypassArrayList.Add(elem.Address); + + return p; +#else + return GetSystemWebProxy (); +#endif + } + + static IWebProxy GetSystemWebProxy() + { + return System.Net.WebProxy.CreateDefaultProxy (); + } + +#endif internal static object ClassSyncObject { @@ -292,6 +337,11 @@ namespace System.Net.Configuration { lock (DefaultProxySectionInternal.ClassSyncObject) { +#if MONO + var res = new DefaultProxySectionInternal(); + res.webProxy = GetDefaultProxy_UsingOldMonoCode (); + return res; +#else DefaultProxySection section = PrivilegedConfigurationManager.GetSection(ConfigurationStrings.DefaultProxySectionPath) as DefaultProxySection; if (section == null) return null; @@ -306,6 +356,7 @@ namespace System.Net.Configuration throw new ConfigurationErrorsException(SR.GetString(SR.net_config_proxy), exception); } +#endif } } diff --git a/mcs/class/referencesource/System/net/System/Net/HttpListenerRequest.cs b/mcs/class/referencesource/System/net/System/Net/HttpListenerRequest.cs index 320e1d69ff..a789a6ea2b 100644 --- a/mcs/class/referencesource/System/net/System/Net/HttpListenerRequest.cs +++ b/mcs/class/referencesource/System/net/System/Net/HttpListenerRequest.cs @@ -300,6 +300,9 @@ namespace System.Net { } } + // Note: RequestBuffer may get moved in memory. If you dereference a pointer from inside the RequestBuffer, + // you must use 'OriginalBlobAddress' below to adjust the location of the pointer to match the location of + // RequestBuffer. internal byte[] RequestBuffer { get @@ -1061,7 +1064,7 @@ namespace System.Net { m_TokenBindings = new List(); - UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST_TOKEN_BINDING_INFO* pTokenBindingInfo = GetTlsTokenBindingRequestInfo(); + UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST_TOKEN_BINDING_INFO* pTokenBindingInfo = UnsafeNclNativeMethods.HttpApi.GetTlsTokenBindingRequestInfo(RequestBuffer, OriginalBlobAddress); if (pTokenBindingInfo == null) { @@ -1116,23 +1119,6 @@ namespace System.Net { } } - private UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST_TOKEN_BINDING_INFO* GetTlsTokenBindingRequestInfo() { - fixed (byte* pMemoryBlob = RequestBuffer) - { - UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST_V2* request = (UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST_V2*)pMemoryBlob; - - for (int i = 0; i < request->RequestInfoCount; i++) - { - UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST_INFO* pThisInfo = &request->pRequestInfo[i]; - if (pThisInfo != null && pThisInfo->InfoType == UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST_INFO_TYPE.HttpRequestInfoTypeSslTokenBinding) - { - return (UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST_TOKEN_BINDING_INFO*)pThisInfo->pInfo; - } - } - } - return null; - } - internal void CheckDisposed() { if (m_IsDisposed) { throw new ObjectDisposedException(this.GetType().FullName); diff --git a/mcs/class/referencesource/System/net/System/Net/Internal.cs b/mcs/class/referencesource/System/net/System/Net/Internal.cs index 79e75caf3d..05732c28d3 100644 --- a/mcs/class/referencesource/System/net/System/Net/Internal.cs +++ b/mcs/class/referencesource/System/net/System/Net/Internal.cs @@ -24,6 +24,7 @@ namespace System.Net { using System.Net.NetworkInformation; using System.Runtime.Serialization; using Microsoft.Win32; + using System.Collections.Generic; internal static class IntPtrHelper { /* @@ -174,7 +175,6 @@ namespace System.Net { private static volatile IPAddress[] _LocalAddresses; private static object _LocalAddressesLock; -#if MONO_NOT_IMPLEMENTED #if !FEATURE_PAL private static volatile NetworkAddressChangePolled s_AddressChange; @@ -287,6 +287,19 @@ namespace System.Net { } #else // !FEATURE_PAL + + internal static bool IsAddressLocal(IPAddress ipAddress) { + IPAddress[] localAddresses = NclUtilities.LocalAddresses; + for (int i = 0; i < localAddresses.Length; i++) + { + if (ipAddress.Equals(localAddresses[i], false)) + { + return true; + } + } + return false; + } + private const int HostNameBufferLength = 256; internal static string _LocalDomainName; @@ -295,6 +308,9 @@ namespace System.Net { // private static IPHostEntry GetLocalHost() { +#if MONO + return Dns.GetHostByName (Dns.GetHostName ()); +#else // // IPv6 Changes: If IPv6 is enabled, we can't simply use the // old IPv4 gethostbyname(null). Instead we need @@ -337,6 +353,7 @@ namespace System.Net { return Dns.NativeToHostEntry(nativePointer); } +#endif } // GetLocalHost @@ -402,7 +419,6 @@ namespace System.Net { } } #endif // !FEATURE_PAL -#endif private static object LocalAddressesLock { @@ -1390,6 +1406,7 @@ typedef struct _SCHANNEL_CRED ValidateManual = 0x08, NoDefaultCred = 0x10, ValidateAuto = 0x20, + SendAuxRecord = 0x00200000, UseStrongCrypto = 0x00400000, } diff --git a/mcs/class/referencesource/System/net/System/Net/NetworkCredential.cs b/mcs/class/referencesource/System/net/System/Net/NetworkCredential.cs index 06aa93aa15..3f9b4d7c8c 100644 --- a/mcs/class/referencesource/System/net/System/Net/NetworkCredential.cs +++ b/mcs/class/referencesource/System/net/System/Net/NetworkCredential.cs @@ -4,6 +4,10 @@ // //------------------------------------------------------------------------------ +#if MONO +#undef FEATURE_PAL +#endif + namespace System.Net { using System.IO; @@ -22,9 +26,11 @@ namespace System.Net { /// public class NetworkCredential : ICredentials,ICredentialsByHost { +#if FEATURE_MONO_CAS private static volatile EnvironmentPermission m_environmentUserNamePermission; private static volatile EnvironmentPermission m_environmentDomainNamePermission; private static readonly object lockingObject = new object(); +#endif private string m_domain; private string m_userName; #if !FEATURE_PAL @@ -85,6 +91,7 @@ namespace System.Net { } #endif //!FEATURE_PAL +#if FEATURE_MONO_CAS void InitializePart1() { if (m_environmentUserNamePermission == null) { lock(lockingObject) { @@ -95,7 +102,7 @@ namespace System.Net { } } } - +#endif /// /// @@ -104,8 +111,10 @@ namespace System.Net { /// public string UserName { get { +#if FEATURE_MONO_CAS InitializePart1(); m_environmentUserNamePermission.Demand(); +#endif return InternalGetUserName(); } set { @@ -124,7 +133,9 @@ namespace System.Net { /// public string Password { get { +#if FEATURE_MONO_CAS ExceptionHelper.UnmanagedPermission.Demand(); +#endif return InternalGetPassword(); } set { @@ -151,7 +162,9 @@ namespace System.Net { /// public SecureString SecurePassword { get { +#if FEATURE_MONO_CAS ExceptionHelper.UnmanagedPermission.Demand(); +#endif return InternalGetSecurePassword().Copy(); } set { @@ -171,8 +184,10 @@ namespace System.Net { /// public string Domain { get { +#if FEATURE_MONO_CAS InitializePart1(); m_environmentDomainNamePermission.Demand(); +#endif return InternalGetDomain(); } set { diff --git a/mcs/class/referencesource/System/net/System/Net/SecureProtocols/_SslState.cs b/mcs/class/referencesource/System/net/System/Net/SecureProtocols/_SslState.cs index 01776e420d..b5488d4a29 100644 --- a/mcs/class/referencesource/System/net/System/Net/SecureProtocols/_SslState.cs +++ b/mcs/class/referencesource/System/net/System/Net/SecureProtocols/_SslState.cs @@ -592,9 +592,17 @@ namespace System.Net.Security { KeyExchangeStrength)); } } + catch (Exception) + { + // If an exception emerges synchronously, the asynchronous operation was not + // initiated, so no operation is in progress. + _NestedAuth = 0; + + throw; + } finally { - if (lazyResult == null || _Exception != null) + if (lazyResult == null) { _NestedAuth = 0; } diff --git a/mcs/class/referencesource/System/net/System/Net/ServicePoint.cs b/mcs/class/referencesource/System/net/System/Net/ServicePoint.cs index 7f71c4ba8a..2995de9113 100644 --- a/mcs/class/referencesource/System/net/System/Net/ServicePoint.cs +++ b/mcs/class/referencesource/System/net/System/Net/ServicePoint.cs @@ -93,7 +93,9 @@ namespace System.Net { return m_BindIPEndPointDelegate; } set { +#if FEATURE_MONO_CAS ExceptionHelper.InfrastructurePermission.Demand(); +#endif m_BindIPEndPointDelegate = value; } } @@ -458,11 +460,13 @@ namespace System.Net { throw new NotSupportedException(SR.GetString(SR.net_servicePointAddressNotSupportedInHostMode)); } +#if FEATURE_MONO_CAS // Don't let low-trust apps discover the proxy information. if (m_ProxyServicePoint) { ExceptionHelper.WebPermissionUnrestricted.Demand(); } +#endif return m_Address; } diff --git a/mcs/class/referencesource/System/net/System/Net/ServicePointManager.cs b/mcs/class/referencesource/System/net/System/Net/ServicePointManager.cs index 48bb45802f..3de63c914d 100644 --- a/mcs/class/referencesource/System/net/System/Net/ServicePointManager.cs +++ b/mcs/class/referencesource/System/net/System/Net/ServicePointManager.cs @@ -247,12 +247,15 @@ namespace System.Net { private static volatile CertPolicyValidationCallback s_CertPolicyValidationCallback = new CertPolicyValidationCallback(); private static volatile ServerCertValidationCallback s_ServerCertValidationCallback = null; + private const string sendAuxRecordValueName = "SchSendAuxRecord"; + private const string sendAuxRecordAppSetting = "System.Net.ServicePointManager.SchSendAuxRecord"; private const string strongCryptoValueName = "SchUseStrongCrypto"; private const string secureProtocolAppSetting = "System.Net.ServicePointManager.SecurityProtocol"; - private static object disableStrongCryptoLock = new object(); - private static volatile bool disableStrongCryptoInitialized = false; + private static object configurationLoadedLock = new object(); + private static volatile bool configurationLoaded = false; private static bool disableStrongCrypto = false; + private static bool disableSendAuxRecord = false; private static SecurityProtocolType s_SecurityProtocolType = SecurityProtocolType.Tls | SecurityProtocolType.Ssl3; @@ -427,11 +430,11 @@ namespace System.Net { [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "Reviewed for thread-safety")] public static SecurityProtocolType SecurityProtocol { get { - EnsureStrongCryptoSettingsInitialized(); + EnsureConfigurationLoaded(); return s_SecurityProtocolType; } set { - EnsureStrongCryptoSettingsInitialized(); + EnsureConfigurationLoaded(); ValidateSecurityProtocol(value); s_SecurityProtocolType = value; } @@ -640,77 +643,118 @@ namespace System.Net { internal static bool DisableStrongCrypto { get { - EnsureStrongCryptoSettingsInitialized(); - return (bool)disableStrongCrypto; + EnsureConfigurationLoaded(); + return disableStrongCrypto; } } - private static void EnsureStrongCryptoSettingsInitialized() { - - if (disableStrongCryptoInitialized) { + internal static bool DisableSendAuxRecord { + get { + EnsureConfigurationLoaded(); + return disableSendAuxRecord; + } + } + + private static void EnsureConfigurationLoaded() { + if (configurationLoaded) { return; } - lock (disableStrongCryptoLock) { - if (disableStrongCryptoInitialized) { + lock (configurationLoadedLock) { + if (configurationLoaded) { return; } - try { - bool disableStrongCryptoInternal = false; - int schUseStrongCryptoKeyValue = 0; + LoadDisableStrongCryptoConfiguration(); + LoadDisableSendAuxRecordConfiguration(); - if (LocalAppContextSwitches.DontEnableSchUseStrongCrypto) - { - //.Net 4.5.2 and below will default to false unless the registry key is specifically set to 1. - schUseStrongCryptoKeyValue = - RegistryConfiguration.GlobalConfigReadInt(strongCryptoValueName, 0); + configurationLoaded = true; + } + } - disableStrongCryptoInternal = schUseStrongCryptoKeyValue != 1; - } - else - { - // .Net 4.6 and above will default to true unless the registry key is specifically set to 0. - schUseStrongCryptoKeyValue = - RegistryConfiguration.GlobalConfigReadInt(strongCryptoValueName, 1); + private static void LoadDisableStrongCryptoConfiguration() { + try { + bool disableStrongCryptoInternal = false; + int schUseStrongCryptoKeyValue = 0; - disableStrongCryptoInternal = schUseStrongCryptoKeyValue == 0; - } - - if (disableStrongCryptoInternal) { - // Revert the SecurityProtocol selection to the legacy combination. - s_SecurityProtocolType = SecurityProtocolType.Tls | SecurityProtocolType.Ssl3; - } - else { - s_SecurityProtocolType = - SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls; + if (LocalAppContextSwitches.DontEnableSchUseStrongCrypto) { + //.Net 4.5.2 and below will default to false unless the registry key is specifically set to 1. + schUseStrongCryptoKeyValue = + RegistryConfiguration.GlobalConfigReadInt(strongCryptoValueName, 0); - string appSetting = RegistryConfiguration.AppConfigReadString(secureProtocolAppSetting, null); - - SecurityProtocolType value; - try { - value = (SecurityProtocolType)Enum.Parse(typeof(SecurityProtocolType), appSetting); - ValidateSecurityProtocol(value); - s_SecurityProtocolType = value; - } - // Ignore all potential exceptions caused by Enum.Parse. - catch (ArgumentNullException) { } - catch (ArgumentException) { } - catch (NotSupportedException) { } - catch (OverflowException) { } - } - - disableStrongCrypto = disableStrongCryptoInternal; - disableStrongCryptoInitialized = true; + disableStrongCryptoInternal = schUseStrongCryptoKeyValue != 1; } - catch (Exception e) { - if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) { - throw; + else { + // .Net 4.6 and above will default to true unless the registry key is specifically set to 0. + schUseStrongCryptoKeyValue = + RegistryConfiguration.GlobalConfigReadInt(strongCryptoValueName, 1); + + disableStrongCryptoInternal = schUseStrongCryptoKeyValue == 0; + } + + if (disableStrongCryptoInternal) { + // Revert the SecurityProtocol selection to the legacy combination. + s_SecurityProtocolType = SecurityProtocolType.Tls | SecurityProtocolType.Ssl3; + } + else { + s_SecurityProtocolType = + SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls; + + string appSetting = RegistryConfiguration.AppConfigReadString(secureProtocolAppSetting, null); + + SecurityProtocolType value; + try { + value = (SecurityProtocolType)Enum.Parse(typeof(SecurityProtocolType), appSetting); + ValidateSecurityProtocol(value); + s_SecurityProtocolType = value; } + // Ignore all potential exceptions caused by Enum.Parse. + catch (ArgumentNullException) { } + catch (ArgumentException) { } + catch (NotSupportedException) { } + catch (OverflowException) { } + } + + disableStrongCrypto = disableStrongCryptoInternal; + } + catch (Exception e) + { + if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) + { + throw; } } } - + + private static void LoadDisableSendAuxRecordConfiguration() { + try { + if (LocalAppContextSwitches.DontEnableSchSendAuxRecord) { + disableSendAuxRecord = true; + return; + } + + int schSendAuxRecordKeyValue = 1; + schSendAuxRecordKeyValue = RegistryConfiguration.AppConfigReadInt(sendAuxRecordAppSetting, 1); + if (schSendAuxRecordKeyValue == 0) { + disableSendAuxRecord = true; + return; + } + + schSendAuxRecordKeyValue = RegistryConfiguration.GlobalConfigReadInt(sendAuxRecordValueName, 1); + if (schSendAuxRecordKeyValue == 0) { + disableSendAuxRecord = true; + return; + } + } + catch (Exception e) + { + if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) + { + throw; + } + } + } + public static bool ReusePort { get { EnsureReusePortSettingsInitialized(); diff --git a/mcs/class/referencesource/System/net/System/Net/Sockets/Socket.cs.REMOVED.git-id b/mcs/class/referencesource/System/net/System/Net/Sockets/Socket.cs.REMOVED.git-id index 5497e3907d..d4960689d8 100644 --- a/mcs/class/referencesource/System/net/System/Net/Sockets/Socket.cs.REMOVED.git-id +++ b/mcs/class/referencesource/System/net/System/Net/Sockets/Socket.cs.REMOVED.git-id @@ -1 +1 @@ -1d92faa541f6a2d6c5a5700a11dc0113895d3e89 \ No newline at end of file +c8a3da853476918de06973dfe4cb78058a0e20d4 \ No newline at end of file diff --git a/mcs/class/referencesource/System/net/System/Net/UnsafeNativeMethods.cs.REMOVED.git-id b/mcs/class/referencesource/System/net/System/Net/UnsafeNativeMethods.cs.REMOVED.git-id index e95ecbb9a3..ff0a744a6d 100644 --- a/mcs/class/referencesource/System/net/System/Net/UnsafeNativeMethods.cs.REMOVED.git-id +++ b/mcs/class/referencesource/System/net/System/Net/UnsafeNativeMethods.cs.REMOVED.git-id @@ -1 +1 @@ -7cf970ed013f48125de2c07a4a866a49c4cbd648 \ No newline at end of file +680ea9813968ee030704b14352a20cc2eaaede54 \ No newline at end of file diff --git a/mcs/class/referencesource/System/net/System/Net/WebHeaderCollection.cs b/mcs/class/referencesource/System/net/System/Net/WebHeaderCollection.cs index 42743232cf..49e6c040ee 100644 --- a/mcs/class/referencesource/System/net/System/Net/WebHeaderCollection.cs +++ b/mcs/class/referencesource/System/net/System/Net/WebHeaderCollection.cs @@ -247,7 +247,7 @@ namespace System.Net { private WebHeaderCollectionType m_Type; #if MONO - internal bool AllowMultiValues (string name) + internal static bool AllowMultiValues (string name) { var hinfo = HInfo[name]; // Is common header which supports multi value or it's unknown header diff --git a/mcs/class/referencesource/System/net/System/Net/WebRequest.cs b/mcs/class/referencesource/System/net/System/Net/WebRequest.cs index 1135be0891..a9be75be0a 100644 --- a/mcs/class/referencesource/System/net/System/Net/WebRequest.cs +++ b/mcs/class/referencesource/System/net/System/Net/WebRequest.cs @@ -4,6 +4,9 @@ // //------------------------------------------------------------------------------ +#if MONO +#undef FEATURE_PAL +#endif namespace System.Net { using System.Collections; using System.Collections.Generic; @@ -53,6 +56,7 @@ namespace System.Net { private AuthenticationLevel m_AuthenticationLevel; private TokenImpersonationLevel m_ImpersonationLevel; #endif + private RequestCachePolicy m_CachePolicy; private RequestCacheProtocol m_CacheProtocol; private RequestCacheBinding m_CacheBinding; @@ -361,7 +365,9 @@ namespace System.Net { throw new ArgumentNullException("creator"); } +#if FEATURE_MONO_CAS ExceptionHelper.WebPermissionUnrestricted.Demand(); +#endif // Lock this object, then walk down PrefixList looking for a place to // to insert this prefix. @@ -523,7 +529,11 @@ namespace System.Net { lock (InternalSyncObject) { if (s_PrefixList == null) { GlobalLog.Print("WebRequest::Initialize(): calling ConfigurationManager.GetSection()"); +#if MONO + s_PrefixList = PopulatePrefixList (); +#else s_PrefixList = WebRequestModulesSectionInternal.GetSection().WebRequestModules; +#endif } } } @@ -535,6 +545,30 @@ namespace System.Net { } } +#if MONO + static ArrayList PopulatePrefixList () + { + var res = new ArrayList(); + +#if MOBILE || !CONFIGURATION_DEP + IWebRequestCreate http = new HttpRequestCreator (); + res.Add(new WebRequestPrefixElement("http", http)); + res.Add(new WebRequestPrefixElement("https", http)); + res.Add(new WebRequestPrefixElement("file", new FileWebRequestCreator ())); + res.Add(new WebRequestPrefixElement("ftp", new FtpRequestCreator ())); +#else + object cfg = ConfigurationManager.GetSection ("system.net/webRequestModules"); + WebRequestModulesSection s = cfg as WebRequestModulesSection; + if (s != null) { + foreach (WebRequestModuleElement el in s.WebRequestModules) + res.Add (new WebRequestPrefixElement(el.Prefix, el.Type)); + } +#endif + return res; + } +#endif + + // constructors /// @@ -588,8 +622,10 @@ namespace System.Net { return RequestCacheManager.GetBinding(string.Empty).Policy; } set { +#if FEATURE_MONO_CAS // This is a replacement of RequestCachePermission demand since we are not including the latest in the product. ExceptionHelper.WebPermissionUnrestricted.Demand(); +#endif RequestCacheBinding binding = RequestCacheManager.GetBinding(string.Empty); RequestCacheManager.SetBinding(string.Empty, new RequestCacheBinding(binding.Cache, binding.Validator, value)); @@ -975,7 +1011,7 @@ namespace System.Net { } } - +#if !MONO // Methods to retrieve the context of the "reading phase" and of the "writing phase" of the request. // Each request type can define what goes into what phase. Typically, the writing phase corresponds to // GetRequestStream() and the reading phase to GetResponse(), but if there's no request body, both phases @@ -996,7 +1032,7 @@ namespace System.Net { { throw ExceptionHelper.MethodNotImplementedException; } - +#endif // // @@ -1072,13 +1108,17 @@ namespace System.Net { { get { +#if FEATURE_MONO_CAS ExceptionHelper.WebPermissionUnrestricted.Demand(); +#endif return InternalDefaultWebProxy; } set { +#if FEATURE_MONO_CAS ExceptionHelper.WebPermissionUnrestricted.Demand(); +#endif InternalDefaultWebProxy = value; } } @@ -1088,13 +1128,20 @@ namespace System.Net { // public static IWebProxy GetSystemWebProxy() { +#if FEATURE_MONO_CAS ExceptionHelper.WebPermissionUnrestricted.Demand(); +#endif return InternalGetSystemWebProxy(); } internal static IWebProxy InternalGetSystemWebProxy() { +#if MONO + // FIXME: Need to break mobile internal API + return WebProxy.CreateDefaultProxy(); +#else return new WebProxyWrapperOpaque(new WebProxy(true)); +#endif } // @@ -1162,7 +1209,7 @@ namespace System.Net { } } - +#if !MONO // internal void SetupCacheProtocol(Uri uri) { @@ -1242,5 +1289,6 @@ namespace System.Net { s_EtwFireEndGetRequestStream(this, success, synchronous); } } +#endif } // class WebRequest } // namespace System.Net diff --git a/mcs/class/referencesource/System/net/System/Net/_SecureChannel.cs b/mcs/class/referencesource/System/net/System/Net/_SecureChannel.cs index 9f04a33e0b..58400b2b26 100644 --- a/mcs/class/referencesource/System/net/System/Net/_SecureChannel.cs +++ b/mcs/class/referencesource/System/net/System/Net/_SecureChannel.cs @@ -393,7 +393,7 @@ namespace System.Net.Security { if (store != null) { collectionEx = store.Certificates.Find(X509FindType.FindByThumbprint, certHash, false); - if (collectionEx.Count > 0 && collectionEx[0].PrivateKey != null) + if (collectionEx.Count > 0 && collectionEx[0].HasPrivateKey) { if (Logging.On) Logging.PrintInfo(Logging.Web, this, SR.GetString(SR.net_log_found_cert_in_store, (m_ServerMode ? "LocalMachine" : "CurrentUser"))); return collectionEx[0]; @@ -404,7 +404,7 @@ namespace System.Net.Security { if (store != null) { collectionEx = store.Certificates.Find(X509FindType.FindByThumbprint, certHash, false); - if (collectionEx.Count > 0 && collectionEx[0].PrivateKey != null) + if (collectionEx.Count > 0 && collectionEx[0].HasPrivateKey) { if (Logging.On) Logging.PrintInfo(Logging.Web, this, SR.GetString(SR.net_log_found_cert_in_store, (m_ServerMode ? "CurrentUser" : "LocalMachine"))); return collectionEx[0]; @@ -791,6 +791,12 @@ namespace System.Net.Security { else { SecureCredential.Flags flags = SecureCredential.Flags.ValidateManual | SecureCredential.Flags.NoDefaultCred; + + if (!ServicePointManager.DisableSendAuxRecord) + { + flags |= SecureCredential.Flags.SendAuxRecord; + } + if (!ServicePointManager.DisableStrongCrypto && ((m_ProtocolFlags & (SchProtocols.Tls10 | SchProtocols.Tls11 | SchProtocols.Tls12)) != 0) && (m_EncryptionPolicy != EncryptionPolicy.AllowNoEncryption) && (m_EncryptionPolicy != EncryptionPolicy.NoEncryption)) @@ -876,7 +882,14 @@ namespace System.Net.Security { } else { - SecureCredential secureCredential = new SecureCredential(SecureCredential.CurrentVersion, selectedCert, SecureCredential.Flags.Zero, m_ProtocolFlags, m_EncryptionPolicy); + SecureCredential.Flags flags = SecureCredential.Flags.Zero; + + if (!ServicePointManager.DisableSendAuxRecord) + { + flags |= SecureCredential.Flags.SendAuxRecord; + } + + SecureCredential secureCredential = new SecureCredential(SecureCredential.CurrentVersion, selectedCert, flags, m_ProtocolFlags, m_EncryptionPolicy); m_CredentialsHandle = AcquireCredentialsHandle(CredentialUse.Inbound, ref secureCredential); thumbPrint = guessedThumbPrint; m_ServerCertificate = localCertificate; diff --git a/mcs/class/referencesource/System/net/System/Net/_Semaphore.cs b/mcs/class/referencesource/System/net/System/Net/_Semaphore.cs index 4d289ac7bc..0365206cf5 100644 --- a/mcs/class/referencesource/System/net/System/Net/_Semaphore.cs +++ b/mcs/class/referencesource/System/net/System/Net/_Semaphore.cs @@ -20,8 +20,13 @@ namespace System.Net { internal Semaphore(int initialCount, int maxCount) : base() { lock (this) { +#if MONO + int errorCode; + Handle = System.Threading.Semaphore.CreateSemaphore_internal(initialCount, maxCount, null, out errorCode); +#else // Handle = UnsafeNclNativeMethods.CreateSemaphore(IntPtr.Zero, initialCount, maxCount, IntPtr.Zero); +#endif } } @@ -36,14 +41,19 @@ namespace System.Net */ internal bool ReleaseSemaphore() { -#if DEBUG +#if MONO + int previousCount; + return System.Threading.Semaphore.ReleaseSemaphore_internal (Handle, 1, out previousCount); +#else +#if DEBUG int previousCount; bool success = UnsafeNclNativeMethods.ReleaseSemaphore(Handle, 1, out previousCount); GlobalLog.Print("ReleaseSemaphore#"+ValidationHelper.HashString(this)+" success:"+success+" previousCount:"+previousCount.ToString()); return success; #else return UnsafeNclNativeMethods.ReleaseSemaphore(Handle, 1, IntPtr.Zero); -#endif +#endif +#endif } /* diff --git a/mcs/class/referencesource/System/net/System/Net/_TimerThread.cs b/mcs/class/referencesource/System/net/System/Net/_TimerThread.cs index 059e88d5bc..c75a713669 100644 --- a/mcs/class/referencesource/System/net/System/Net/_TimerThread.cs +++ b/mcs/class/referencesource/System/net/System/Net/_TimerThread.cs @@ -182,7 +182,9 @@ namespace System.Net { static TimerThread() { s_ThreadEvents = new WaitHandle[] { s_ThreadShutdownEvent, s_ThreadReadyEvent }; +#if MONO_FEATURE_MULTIPLE_APPDOMAINS AppDomain.CurrentDomain.DomainUnload += new EventHandler(OnDomainUnload); +#endif } /// diff --git a/mcs/class/referencesource/System/net/System/Net/webproxy.cs b/mcs/class/referencesource/System/net/System/Net/webproxy.cs index ca05e1355e..15840cd702 100644 --- a/mcs/class/referencesource/System/net/System/Net/webproxy.cs +++ b/mcs/class/referencesource/System/net/System/Net/webproxy.cs @@ -414,7 +414,9 @@ namespace System.Net { /// [Obsolete("This method has been deprecated. Please use the proxy selected for you by default. http://go.microsoft.com/fwlink/?linkid=14202")] public static WebProxy GetDefaultProxy() { +#if FEATURE_MONO_CAS ExceptionHelper.WebPermissionUnrestricted.Demand(); +#endif return new WebProxy(true); } @@ -435,7 +437,9 @@ namespace System.Net { if (useRegistry) { // just make the proxy advanced, don't populate with any settings // note - this will happen in the context of the user performing the deserialization (their proxy settings get read) +#if FEATURE_MONO_CAS ExceptionHelper.WebPermissionUnrestricted.Demand(); +#endif UnsafeUpdateFromRegistry(); return; } @@ -497,6 +501,30 @@ namespace System.Net { } } +#if MONO + public static IWebProxy CreateDefaultProxy () + { +#if FEATURE_NO_BSD_SOCKETS + throw new PlatformNotSupportedException (); +#elif MONOTOUCH + return Mono.Net.CFNetwork.GetDefaultProxy (); +#elif MONODROID + // Return the system web proxy. This only works for ICS+. + var data = AndroidPlatform.GetDefaultProxy (); + if (data != null) + return data; +#else + if (Platform.IsMacOS) { + var data = Mono.Net.CFNetwork.GetDefaultProxy (); + if (data != null) + return data; + } +#endif + + return new WebProxy (true); + } +#endif + // This constructor is used internally to make WebProxies that read their state from the registry. // internal WebProxy(bool enableAutoproxy) @@ -515,7 +543,7 @@ namespace System.Net { internal void UnsafeUpdateFromRegistry() { GlobalLog.Assert(!_UseRegistry, "WebProxy#{0}::UnsafeUpdateFromRegistry()|_UseRegistry ScriptEngine#{1}", ValidationHelper.HashString(this), ValidationHelper.HashString(m_ScriptEngine)); _UseRegistry = true; -#if !FEATURE_PAL +#if !FEATURE_PAL || !MOBILE ScriptEngine = new AutoWebProxyScriptEngine(this, true); WebProxyData webProxyData = ScriptEngine.GetWebProxyData(); diff --git a/mcs/class/referencesource/System/net/System/UriExt.cs b/mcs/class/referencesource/System/net/System/UriExt.cs index 9f55631246..1a587adf4e 100644 --- a/mcs/class/referencesource/System/net/System/UriExt.cs +++ b/mcs/class/referencesource/System/net/System/UriExt.cs @@ -443,6 +443,11 @@ namespace System { { Uri result; +#if MONO + if (uriKind == UriKind.RelativeOrAbsolute) + uriKind = DotNetRelativeOrAbsolute; +#endif + if (!Uri.TryCreate(uriString, uriKind, out result)) return false; diff --git a/mcs/class/referencesource/System/regex/system/text/regularexpressions/Regex.cs b/mcs/class/referencesource/System/regex/system/text/regularexpressions/Regex.cs index 7b9b1e1911..4675771138 100644 --- a/mcs/class/referencesource/System/regex/system/text/regularexpressions/Regex.cs +++ b/mcs/class/referencesource/System/regex/system/text/regularexpressions/Regex.cs @@ -473,6 +473,7 @@ namespace System.Text.RegularExpressions { } #if NETSTANDARD + [CLSCompliant (false)] protected IDictionary Caps { get @@ -500,6 +501,7 @@ namespace System.Text.RegularExpressions { } } + [CLSCompliant (false)] protected IDictionary CapNames { get @@ -1398,7 +1400,7 @@ namespace System.Text.RegularExpressions { return newcached; } -#if !(SILVERLIGHT||FULL_AOT_RUNTIME) +#if !SILVERLIGHT /* * True if the O option was set */ @@ -1408,7 +1410,11 @@ namespace System.Text.RegularExpressions { protected bool UseOptionC() { /* Mono: Set to false until we investigate https://bugzilla.xamarin.com/show_bug.cgi?id=25671 */ return false; +#if FULL_AOT_RUNTIME + return false; +#else return(roptions & RegexOptions.Compiled) != 0; +#endif } #endif diff --git a/mcs/class/referencesource/System/services/io/system/io/FileSystemWatcher.cs b/mcs/class/referencesource/System/services/io/system/io/FileSystemWatcher.cs index ed0965d382..500280aed3 100644 --- a/mcs/class/referencesource/System/services/io/system/io/FileSystemWatcher.cs +++ b/mcs/class/referencesource/System/services/io/system/io/FileSystemWatcher.cs @@ -586,9 +586,6 @@ namespace System.IO { } else { if (oldName != null) { - Debug.Assert(false, "FileSystemWatcher: FILE_ACTION_RENAMED_OLD_NAME with no" + - "new name! [" + oldName + "]"); - NotifyRenameEventArgs(WatcherChangeTypes.Renamed, null, oldName); oldName = null; } diff --git a/mcs/class/referencesource/System/services/monitoring/system/diagnosticts/AsyncStreamReader.cs b/mcs/class/referencesource/System/services/monitoring/system/diagnosticts/AsyncStreamReader.cs index f5fabc69b6..d9236f7836 100644 --- a/mcs/class/referencesource/System/services/monitoring/system/diagnosticts/AsyncStreamReader.cs +++ b/mcs/class/referencesource/System/services/monitoring/system/diagnosticts/AsyncStreamReader.cs @@ -57,6 +57,11 @@ namespace System.Diagnostics { // Cache the last position scanned in sb when searching for lines. private int currentLinePos; +#if MONO + //users to coordinate between Dispose and BeginReadLine + private object syncObject = new Object (); +#endif + internal AsyncStreamReader(Process process, Stream stream, UserCallBack callback, Encoding encoding) : this(process, stream, callback, encoding, DefaultBufferSize) { } @@ -104,6 +109,9 @@ namespace System.Diagnostics { protected virtual void Dispose(bool disposing) { +#if MONO + lock (syncObject) { +#endif if (disposing) { if (stream != null) stream.Close(); @@ -120,6 +128,9 @@ namespace System.Diagnostics { eofEvent.Close(); eofEvent = null; } +#if MONO + } +#endif } public virtual Encoding CurrentEncoding { @@ -155,6 +166,12 @@ namespace System.Diagnostics { int byteLen; try { +#if MONO + var stream = this.stream; + if (stream == null) + byteLen = 0; + else +#endif byteLen = stream.EndRead(ar); } catch (IOException ) { @@ -171,6 +188,9 @@ namespace System.Diagnostics { byteLen = 0; // Treat this as EOF } +#if MONO +retry_dispose: +#endif if (byteLen == 0) { // We're at EOF, we won't call this function again from here on. lock(messageQueue) { @@ -186,13 +206,45 @@ namespace System.Diagnostics { FlushMessageQueue(); } finally { +#if MONO + lock (syncObject) { + if (eofEvent != null) { + try { + eofEvent.Set (); + } catch (System.ObjectDisposedException) { + // This races with Dispose, it's safe to ignore the error as it comes from a SafeHandle doing its job + } + } + } +#else eofEvent.Set(); +#endif } } else { +#if MONO + lock (syncObject) { + if (decoder == null) { //we got disposed after the EndRead, retry as Diposed + byteLen = 0; + goto retry_dispose; + } +#endif int charLen = decoder.GetChars(byteBuffer, 0, byteLen, charBuffer, 0); sb.Append(charBuffer, 0, charLen); +#if MONO + } +#endif GetLinesFromStringBuilder(); +#if MONO + lock (syncObject) { + if (stream == null) { //we got disposed after the EndRead, retry as Diposed + byteLen = 0; + goto retry_dispose; + } +#endif stream.BeginRead(byteBuffer, 0 , byteBuffer.Length, new AsyncCallback(ReadBuffer), null); +#if MONO + } +#endif } } diff --git a/mcs/class/referencesource/System/services/monitoring/system/diagnosticts/Process.cs.REMOVED.git-id b/mcs/class/referencesource/System/services/monitoring/system/diagnosticts/Process.cs.REMOVED.git-id index 3bbce20bc9..9d409463ae 100644 --- a/mcs/class/referencesource/System/services/monitoring/system/diagnosticts/Process.cs.REMOVED.git-id +++ b/mcs/class/referencesource/System/services/monitoring/system/diagnosticts/Process.cs.REMOVED.git-id @@ -1 +1 @@ -cbd2456ab966dcad784e6055e16ea4b2a7964721 \ No newline at end of file +6fbeb99f020d1dbe0c11bf3f34f0a6002307c13e \ No newline at end of file diff --git a/mcs/class/referencesource/System/services/monitoring/system/diagnosticts/ProcessModuleCollection.cs b/mcs/class/referencesource/System/services/monitoring/system/diagnosticts/ProcessModuleCollection.cs index ef960754ba..85d996b827 100644 --- a/mcs/class/referencesource/System/services/monitoring/system/diagnosticts/ProcessModuleCollection.cs +++ b/mcs/class/referencesource/System/services/monitoring/system/diagnosticts/ProcessModuleCollection.cs @@ -53,6 +53,270 @@ namespace System.Diagnostics { public void CopyTo(ProcessModule[] array, int index) { InnerList.CopyTo(array, index); } + +#if MOBILE + [Obsolete ("This API is no longer available", true)] + public int Capacity { + get { + throw new NotSupportedException (); + } + set { + throw new NotSupportedException (); + } + } + + [Obsolete ("This API is no longer available", true)] + public void Add (ProcessModule item) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public void AddRange (System.Collections.Generic.IEnumerable collection) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public System.Collections.ObjectModel.ReadOnlyCollection AsReadOnly() + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public int BinarySearch(int index, int count, ProcessModule item, System.Collections.Generic.IComparer comparer) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public int BinarySearch(ProcessModule item) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public int BinarySearch(ProcessModule item, System.Collections.Generic.IComparer comparer) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public void Clear() + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public System.Collections.Generic.List ConvertAll(Converter converter) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public void CopyTo(ProcessModule[] array) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public void CopyTo(int index, ProcessModule[] array, int arrayIndex, int count) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public bool Exists(Predicate match) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public ProcessModule Find(Predicate match) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public System.Collections.Generic.List FindAll(Predicate match) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public int FindIndex(Predicate match) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public int FindIndex(int startIndex, Predicate match) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public int FindIndex(int startIndex, int count, Predicate match) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public ProcessModule FindLast(Predicate match) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public int FindLastIndex(Predicate match) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public int FindLastIndex(int startIndex, Predicate match) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public int FindLastIndex(int startIndex, int count, Predicate match) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public void ForEach(Action action) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public System.Collections.Generic.List GetRange(int index, int count) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public int IndexOf(ProcessModule item, int index) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public int IndexOf(ProcessModule item, int index, int count) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public void Insert(int index, ProcessModule item) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public void InsertRange(int index, System.Collections.Generic.IEnumerable collection) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public int LastIndexOf(ProcessModule item) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public int LastIndexOf(ProcessModule item, int index) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public int LastIndexOf(ProcessModule item, int index, int count) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public bool Remove(ProcessModule item) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public int RemoveAll(Predicate match) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public void RemoveAt(int index) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public void RemoveRange(int index, int count) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public void Reverse() + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public void Reverse(int index, int count) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public void Sort() + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public void Sort(System.Collections.Generic.IComparer comparer) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public void Sort(int index, int count, System.Collections.Generic.IComparer comparer) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public void Sort(Comparison comparison) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public ProcessModule[] ToArray() + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public void TrimExcess() + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public bool TrueForAll(Predicate match) + { + throw new NotSupportedException (); + } +#endif } } diff --git a/mcs/class/referencesource/System/services/monitoring/system/diagnosticts/ProcessThreadCollection.cs b/mcs/class/referencesource/System/services/monitoring/system/diagnosticts/ProcessThreadCollection.cs index 127c1d4319..94fa2f43bb 100644 --- a/mcs/class/referencesource/System/services/monitoring/system/diagnosticts/ProcessThreadCollection.cs +++ b/mcs/class/referencesource/System/services/monitoring/system/diagnosticts/ProcessThreadCollection.cs @@ -77,6 +77,252 @@ namespace System.Diagnostics { public void CopyTo(ProcessThread[] array, int index) { InnerList.CopyTo(array, index); } + +#if MOBILE + [Obsolete ("This API is no longer available", true)] + public int Capacity { + get { + throw new NotSupportedException (); + } + set { + throw new NotSupportedException (); + } + } + + [Obsolete ("This API is no longer available", true)] + public void AddRange (System.Collections.Generic.IEnumerable collection) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public System.Collections.ObjectModel.ReadOnlyCollection AsReadOnly() + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public int BinarySearch(int index, int count, ProcessThread item, System.Collections.Generic.IComparer comparer) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public int BinarySearch(ProcessThread item) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public int BinarySearch(ProcessThread item, System.Collections.Generic.IComparer comparer) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public void Clear() + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public System.Collections.Generic.List ConvertAll(Converter converter) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public void CopyTo(ProcessThread[] array) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public void CopyTo(int index, ProcessThread[] array, int arrayIndex, int count) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public bool Exists(Predicate match) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public ProcessThread Find(Predicate match) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public System.Collections.Generic.List FindAll(Predicate match) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public int FindIndex(Predicate match) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public int FindIndex(int startIndex, Predicate match) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public int FindIndex(int startIndex, int count, Predicate match) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public ProcessThread FindLast(Predicate match) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public int FindLastIndex(Predicate match) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public int FindLastIndex(int startIndex, Predicate match) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public int FindLastIndex(int startIndex, int count, Predicate match) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public void ForEach(Action action) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public System.Collections.Generic.List GetRange(int index, int count) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public int IndexOf(ProcessThread item, int index) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public int IndexOf(ProcessThread item, int index, int count) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public void InsertRange(int index, System.Collections.Generic.IEnumerable collection) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public int LastIndexOf(ProcessThread item) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public int LastIndexOf(ProcessThread item, int index) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public int LastIndexOf(ProcessThread item, int index, int count) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public int RemoveAll(Predicate match) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public void RemoveAt(int index) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public void RemoveRange(int index, int count) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public void Reverse() + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public void Reverse(int index, int count) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public void Sort() + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public void Sort(System.Collections.Generic.IComparer comparer) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public void Sort(int index, int count, System.Collections.Generic.IComparer comparer) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public void Sort(Comparison comparison) + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public ProcessThread[] ToArray() + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public void TrimExcess() + { + throw new NotSupportedException (); + } + + [Obsolete ("This API is no longer available", true)] + public bool TrueForAll(Predicate match) + { + throw new NotSupportedException (); + } +#endif } } diff --git a/mcs/class/referencesource/System/sys/AppContextDefaultValues.Defaults.cs b/mcs/class/referencesource/System/sys/AppContextDefaultValues.Defaults.cs index a084bb5dc8..da13e19302 100644 --- a/mcs/class/referencesource/System/sys/AppContextDefaultValues.Defaults.cs +++ b/mcs/class/referencesource/System/sys/AppContextDefaultValues.Defaults.cs @@ -27,6 +27,11 @@ namespace System { LocalAppContext.DefineSwitchDefault(LocalAppContextSwitches.DontEnableSchUseStrongCryptoName, true); } + + if (version <= 40601) + { + LocalAppContext.DefineSwitchDefault(LocalAppContextSwitches.MemberDescriptorEqualsReturnsFalseIfEquivalentName, true); + } break; } case "WindowsPhone": @@ -34,7 +39,7 @@ namespace System { if (version <= 80100) { - LocalAppContext.DefineSwitchDefault(LocalAppContextSwitches.DontEnableSchUseStrongCryptoName, true); + LocalAppContext.DefineSwitchDefault(LocalAppContextSwitches.DontEnableSchUseStrongCryptoName, true); } break; } diff --git a/mcs/class/referencesource/System/sys/LocalAppContextSwitches.cs b/mcs/class/referencesource/System/sys/LocalAppContextSwitches.cs index 50f2bac56d..0d28af1593 100644 --- a/mcs/class/referencesource/System/sys/LocalAppContextSwitches.cs +++ b/mcs/class/referencesource/System/sys/LocalAppContextSwitches.cs @@ -11,7 +11,21 @@ namespace System internal static class LocalAppContextSwitches { -#region System.Net quirks + #region System quirks + private static int _memberDescriptorEqualsReturnsFalseIfEquivalent; + internal const string MemberDescriptorEqualsReturnsFalseIfEquivalentName = @"Switch.System.MemberDescriptorEqualsReturnsFalseIfEquivalent"; + + public static bool MemberDescriptorEqualsReturnsFalseIfEquivalent + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return LocalAppContext.GetCachedSwitchValue(MemberDescriptorEqualsReturnsFalseIfEquivalentName, ref _memberDescriptorEqualsReturnsFalseIfEquivalent); + } + } + #endregion + + #region System.Net quirks private static int _dontEnableSchUseStrongCrypto; internal const string DontEnableSchUseStrongCryptoName = @"Switch.System.Net.DontEnableSchUseStrongCrypto"; @@ -23,9 +37,7 @@ namespace System return LocalAppContext.GetCachedSwitchValue(DontEnableSchUseStrongCryptoName, ref _dontEnableSchUseStrongCrypto); } } -#endregion -#region System.Net.WebSockets.HttpListenerAsyncEventArgs private static int _allocateOverlappedOnDemand; internal const string AllocateOverlappedOnDemandName = @"Switch.System.Net.WebSockets.HttpListenerAsyncEventArgs.AllocateOverlappedOnDemand"; @@ -37,7 +49,18 @@ namespace System return LocalAppContext.GetCachedSwitchValue(AllocateOverlappedOnDemandName, ref _allocateOverlappedOnDemand); } } -#endregion + private static int _dontEnableSchSendAuxRecord; + internal const string DontEnableSchSendAuxRecordName = @"Switch.System.Net.DontEnableSchSendAuxRecord"; + + public static bool DontEnableSchSendAuxRecord + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return LocalAppContext.GetCachedSwitchValue(DontEnableSchSendAuxRecordName, ref _dontEnableSchSendAuxRecord); + } + } + #endregion } } diff --git a/mcs/class/referencesource/System/sys/system/IO/ports/InternalResources.cs b/mcs/class/referencesource/System/sys/system/IO/ports/InternalResources.cs index 4d181e8c22..5a68cc4744 100644 --- a/mcs/class/referencesource/System/sys/system/IO/ports/InternalResources.cs +++ b/mcs/class/referencesource/System/sys/system/IO/ports/InternalResources.cs @@ -34,6 +34,7 @@ namespace System.IO.Ports #endif internal static String GetMessage(int errorCode) { +#if !MONO StringBuilder sb = new StringBuilder(512); int result = SafeNativeMethods.FormatMessage(NativeMethods.FORMAT_MESSAGE_IGNORE_INSERTS | NativeMethods.FORMAT_MESSAGE_FROM_SYSTEM | NativeMethods.FORMAT_MESSAGE_ARGUMENT_ARRAY, @@ -47,6 +48,7 @@ namespace System.IO.Ports return s; } else +#endif { return SR.GetString(SR.IO_UnknownError, errorCode); } @@ -76,6 +78,7 @@ namespace System.IO.Ports } #endif +#if !MONO #if FEATURE_NETCORE [SecuritySafeCritical] #endif @@ -93,6 +96,7 @@ namespace System.IO.Ports int errorCode = Marshal.GetLastWin32Error(); WinIOError(errorCode, str); } +#endif // After calling GetLastWin32Error(), it clears the last error field, // so you must save the HResult and pass it to this method. This method diff --git a/mcs/class/referencesource/System/sys/system/threading/semaphore.cs b/mcs/class/referencesource/System/sys/system/threading/semaphore.cs index 9a77cc0a64..eae169c364 100644 --- a/mcs/class/referencesource/System/sys/system/threading/semaphore.cs +++ b/mcs/class/referencesource/System/sys/system/threading/semaphore.cs @@ -1,3 +1,6 @@ +#if MONO +#undef FEATURE_PAL +#endif // ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. @@ -21,6 +24,7 @@ namespace System.Threading #endif using System.Runtime.Versioning; using System.Runtime.ConstrainedExecution; + using System.Runtime.CompilerServices; [HostProtection(Synchronization=true, ExternalThreading=true)] @@ -66,16 +70,28 @@ namespace System.Threading { throw new ArgumentException(SR.GetString(SR.Argument_WaitHandleNameTooLong)); } + +#if MONO + int errorCode; + var myHandle = new SafeWaitHandle (CreateSemaphore_internal (initialCount, maximumCount, name, out errorCode), true); +#else SafeWaitHandle myHandle = SafeNativeMethods.CreateSemaphore(null, initialCount, maximumCount, name); +#endif if (myHandle.IsInvalid) { +#if !MONO int errorCode = Marshal.GetLastWin32Error(); +#endif if(null != name && 0 != name.Length && NativeMethods.ERROR_INVALID_HANDLE == errorCode) throw new WaitHandleCannotBeOpenedException(SR.GetString(SR.WaitHandleCannotBeOpenedException_InvalidHandle,name)); +#if MONO + InternalResources.WinIOError(errorCode, ""); +#else InternalResources.WinIOError(); +#endif } this.SafeWaitHandle = myHandle; } @@ -119,6 +135,11 @@ namespace System.Threading throw new ArgumentException(SR.GetString(SR.Argument_WaitHandleNameTooLong)); } SafeWaitHandle myHandle; + +#if MONO + int errorCode; + myHandle = new SafeWaitHandle (CreateSemaphore_internal (initialCount, maximumCount, name, out errorCode), true); +#else #if !FEATURE_PAL && !FEATURE_NETCORE // For ACL's, get the security descriptor from the SemaphoreSecurity. if (semaphoreSecurity != null) { @@ -137,12 +158,19 @@ namespace System.Threading #if !FEATURE_PAL && !FEATURE_NETCORE } #endif + int errorCode = Marshal.GetLastWin32Error(); +#endif if (myHandle.IsInvalid) { if(null != name && 0 != name.Length && NativeMethods.ERROR_INVALID_HANDLE == errorCode) throw new WaitHandleCannotBeOpenedException(SR.GetString(SR.WaitHandleCannotBeOpenedException_InvalidHandle,name)); + +#if MONO + InternalResources.WinIOError(errorCode, ""); +#else InternalResources.WinIOError(); +#endif } createdNew = errorCode != NativeMethods.ERROR_ALREADY_EXISTS; this.SafeWaitHandle = myHandle; @@ -259,7 +287,14 @@ namespace System.Threading } result = null; +#if MOBILE + throw new NotSupportedException (); +#else +#if MONO + int errorCode; + var myHandle = new SafeWaitHandle (OpenSemaphore_internal (name, rights, out errorCode), true); +#else //Pass false to OpenSemaphore to prevent inheritedHandles #if FEATURE_PAL || FEATURE_NETCORE const int SYNCHRONIZE = 0x00100000; @@ -268,11 +303,14 @@ namespace System.Threading SafeWaitHandle myHandle = SafeNativeMethods.OpenSemaphore(SEMAPHORE_MODIFY_STATE | SYNCHRONIZE, false, name); #else SafeWaitHandle myHandle = SafeNativeMethods.OpenSemaphore((int) rights, false, name); +#endif #endif if (myHandle.IsInvalid) { +#if !MONO int errorCode = Marshal.GetLastWin32Error(); +#endif if (NativeMethods.ERROR_FILE_NOT_FOUND == errorCode || NativeMethods.ERROR_INVALID_NAME == errorCode) return OpenExistingResult.NameNotFound; @@ -281,10 +319,15 @@ namespace System.Threading if (null != name && 0 != name.Length && NativeMethods.ERROR_INVALID_HANDLE == errorCode) return OpenExistingResult.NameInvalid; //this is for passed through NativeMethods Errors +#if MONO + InternalResources.WinIOError(errorCode, ""); +#else InternalResources.WinIOError(); +#endif } result = new Semaphore(myHandle); return OpenExistingResult.Success; +#endif } @@ -318,7 +361,11 @@ namespace System.Threading // the semaphore's count to exceed the maximum count set when Semaphore was created //Non-Zero return +#if MONO + if (!ReleaseSemaphore_internal(Handle, releaseCount, out previousCount)) +#else if (!SafeNativeMethods.ReleaseSemaphore(SafeWaitHandle, releaseCount, out previousCount)) +#endif { throw new SemaphoreFullException(); } @@ -342,6 +389,19 @@ namespace System.Threading semaphoreSecurity.Persist(SafeWaitHandle); } #endif + +#if MONO + [MethodImplAttribute(MethodImplOptions.InternalCall)] + internal static extern IntPtr CreateSemaphore_internal ( + int initialCount, int maximumCount, string name, out int errorCode); + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + internal static extern bool ReleaseSemaphore_internal ( + IntPtr handle, int releaseCount, out int previousCount); + + [MethodImplAttribute (MethodImplOptions.InternalCall)] + private static extern IntPtr OpenSemaphore_internal (string name, SemaphoreRights rights, out int errorCode); +#endif } } diff --git a/mcs/class/referencesource/System/sys/system/windows/markup/ValueSerializerAttribute.cs b/mcs/class/referencesource/System/sys/system/windows/markup/ValueSerializerAttribute.cs index 2a0102e8c5..37f19b3aa8 100644 --- a/mcs/class/referencesource/System/sys/system/windows/markup/ValueSerializerAttribute.cs +++ b/mcs/class/referencesource/System/sys/system/windows/markup/ValueSerializerAttribute.cs @@ -26,7 +26,9 @@ namespace System.Windows.Markup /// attached property. /// [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Property | AttributeTargets.Method, AllowMultiple = false, Inherited = true)] +#if !MOBILE [TypeForwardedFrom("WindowsBase, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")] +#endif public sealed class ValueSerializerAttribute : Attribute { /// diff --git a/mcs/class/referencesource/XamlBuildTask/Microsoft/Build/Tasks/Xaml/PartialClassGenerationTask.cs b/mcs/class/referencesource/XamlBuildTask/Microsoft/Build/Tasks/Xaml/PartialClassGenerationTask.cs index 30a681e707..fb57cc3cba 100644 --- a/mcs/class/referencesource/XamlBuildTask/Microsoft/Build/Tasks/Xaml/PartialClassGenerationTask.cs +++ b/mcs/class/referencesource/XamlBuildTask/Microsoft/Build/Tasks/Xaml/PartialClassGenerationTask.cs @@ -198,8 +198,11 @@ namespace Microsoft.Build.Tasks.Xaml } else { - AppDomain.Unload(inProcessAppDomain); - inProcessAppDomain = null; + if (inProcessAppDomain != null) + { + AppDomain.Unload(inProcessAppDomain); + inProcessAppDomain = null; + } return GetAppDomainAndExecute(); } } diff --git a/mcs/class/referencesource/XamlBuildTask/Microsoft/Build/Tasks/Xaml/XamlBuildTaskServices.cs b/mcs/class/referencesource/XamlBuildTask/Microsoft/Build/Tasks/Xaml/XamlBuildTaskServices.cs index 03a90fba66..a21ac391e5 100644 --- a/mcs/class/referencesource/XamlBuildTask/Microsoft/Build/Tasks/Xaml/XamlBuildTaskServices.cs +++ b/mcs/class/referencesource/XamlBuildTask/Microsoft/Build/Tasks/Xaml/XamlBuildTaskServices.cs @@ -215,6 +215,12 @@ namespace Microsoft.Build.Tasks.Xaml appDomainSetup.ApplicationBase = buildTaskPath; appDomainSetup.LoaderOptimization = LoaderOptimization.MultiDomainHost; + // Set the AppDomainManager class name and assembly name to the empty string. We don't want the AppDomain to try to load the + // Microsoft.VisualStudio.Platform.AppDomainManager.dll because it is no longer in the GAC, so it won't be found + // by the AppDomain that is created for the in-process build to support Intellisense in Visual Studio. + appDomainSetup.AppDomainManagerType = ""; + appDomainSetup.AppDomainManagerAssembly = ""; + // Create appdomain with fulltrust. return AppDomain.CreateDomain( friendlyName, diff --git a/mcs/class/referencesource/mscorlib/InternalApis/NDP_Common/inc/PinnableBufferCache.cs b/mcs/class/referencesource/mscorlib/InternalApis/NDP_Common/inc/PinnableBufferCache.cs index 872cfa80dd..19ec1053a3 100644 --- a/mcs/class/referencesource/mscorlib/InternalApis/NDP_Common/inc/PinnableBufferCache.cs +++ b/mcs/class/referencesource/mscorlib/InternalApis/NDP_Common/inc/PinnableBufferCache.cs @@ -155,7 +155,14 @@ namespace System if (PinnableBufferCacheEventSource.Log.IsEnabled()) PinnableBufferCacheEventSource.Log.FreeBuffer(m_CacheName, PinnableBufferCacheEventSource.AddressOf(buffer), buffer.GetHashCode(), m_FreeList.Count); - + if(buffer == null) + { + if (PinnableBufferCacheEventSource.Log.IsEnabled()) + PinnableBufferCacheEventSource.Log.FreeBufferNull(m_CacheName, m_FreeList.Count); + + return; + } + // After we've done 3 gen1 GCs, assume that all buffers have aged into gen2 on the free path. if ((m_gen1CountAtLastRestock + 3) > GC.CollectionCount(GC.MaxGeneration - 1)) { @@ -567,6 +574,7 @@ namespace System public void AllocateBufferAged(string cacheName, int agedCount) {} public void AllocateBufferFreeListEmpty(string cacheName, int notGen2CountBefore) {} public void FreeBuffer(string cacheName, ulong objectId, int objectHash, int freeCountBefore) {} + public void FreeBufferNull(string cacheName, int freeCountBefore) { } public void FreeBufferStillTooYoung(string cacheName, int notGen2CountBefore) {} public void TrimCheck(string cacheName, int totalBuffs, bool neededMoreThanFreeList, int deltaMSec) {} public void TrimFree(string cacheName, int totalBuffs, int freeListCount, int toBeFreed) {} @@ -643,6 +651,8 @@ namespace System public void AgePendingBuffersResults(string cacheName, int promotedToFreeListCount, int heldBackCount) { if (IsEnabled()) WriteEvent(20, cacheName, promotedToFreeListCount, heldBackCount); } [Event(21)] public void WalkFreeListResult(string cacheName, int freeListCount, int gen0BuffersInFreeList) { if (IsEnabled()) WriteEvent(21, cacheName, freeListCount, gen0BuffersInFreeList); } + [Event(22)] + public void FreeBufferNull(string cacheName, int freeCountBefore) { if(IsEnabled()) WriteEvent(22, cacheName, freeCountBefore); } static internal ulong AddressOf(object obj) diff --git a/mcs/class/referencesource/mscorlib/microsoft/win32/win32native.cs.REMOVED.git-id b/mcs/class/referencesource/mscorlib/microsoft/win32/win32native.cs.REMOVED.git-id index 4bed25f392..a90fb94ae5 100644 --- a/mcs/class/referencesource/mscorlib/microsoft/win32/win32native.cs.REMOVED.git-id +++ b/mcs/class/referencesource/mscorlib/microsoft/win32/win32native.cs.REMOVED.git-id @@ -1 +1 @@ -9c2df18a2daf5d191612169f1bcc5d0cb9f10b82 \ No newline at end of file +1bf3586fe471a184fd2979557e4ed976454224d7 \ No newline at end of file diff --git a/mcs/class/referencesource/mscorlib/system/AppContext/AppContext.cs b/mcs/class/referencesource/mscorlib/system/AppContext/AppContext.cs index 7eaddbf117..48b508d50d 100644 --- a/mcs/class/referencesource/mscorlib/system/AppContext/AppContext.cs +++ b/mcs/class/referencesource/mscorlib/system/AppContext/AppContext.cs @@ -18,8 +18,7 @@ namespace System HasLookedForOverride = 0x4, UnknownValue = 0x8 // Has no default and could not find an override } - private static Dictionary s_switchMap = new Dictionary(); - private static readonly object s_syncLock = new object(); + private static readonly Dictionary s_switchMap = new Dictionary(); public static string BaseDirectory { @@ -166,11 +165,12 @@ namespace System if (switchName.Length == 0) throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "switchName"); - lock (s_syncLock) + SwitchValueState switchValue = (isEnabled ? SwitchValueState.HasTrueValue : SwitchValueState.HasFalseValue) + | SwitchValueState.HasLookedForOverride; + lock (s_switchMap) { // Store the new value and the fact that we checked in the dictionary - s_switchMap[switchName] = (isEnabled ? SwitchValueState.HasTrueValue : SwitchValueState.HasFalseValue) - | SwitchValueState.HasLookedForOverride; + s_switchMap[switchName] = switchValue; } } diff --git a/mcs/class/referencesource/mscorlib/system/AppContext/AppContextDefaultValues.Defaults.cs b/mcs/class/referencesource/mscorlib/system/AppContext/AppContextDefaultValues.Defaults.cs index bc1f347abb..d934f6ac18 100644 --- a/mcs/class/referencesource/mscorlib/system/AppContext/AppContextDefaultValues.Defaults.cs +++ b/mcs/class/referencesource/mscorlib/system/AppContext/AppContextDefaultValues.Defaults.cs @@ -1,4 +1,4 @@ -// ==++== +// ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // @@ -13,8 +13,11 @@ namespace System internal static readonly string SwitchNoAsyncCurrentCulture = "Switch.System.Globalization.NoAsyncCurrentCulture"; internal static readonly string SwitchThrowExceptionIfDisposedCancellationTokenSource = "Switch.System.Threading.ThrowExceptionIfDisposedCancellationTokenSource"; internal static readonly string SwitchPreserveEventListnerObjectIdentity = "Switch.System.Diagnostics.EventSource.PreserveEventListnerObjectIdentity"; + internal static readonly string SwitchUseLegacyPathHandling = "Switch.System.IO.UseLegacyPathHandling"; + internal static readonly string SwitchBlockLongPaths = "Switch.System.IO.BlockLongPaths"; + internal static readonly string SwitchSetActorAsReferenceWhenCopyingClaimsIdentity = "Switch.System.Security.ClaimsIdentity.SetActorAsReferenceWhenCopyingClaimsIdentity"; + - // This is a partial method. Platforms can provide an implementation of it that will set override values // from whatever mechanism is available on that platform. If no implementation is provided, the compiler is going to remove the calls // to it from the code @@ -41,6 +44,14 @@ namespace System AppContext.DefineSwitchDefault(SwitchNoAsyncCurrentCulture, true); AppContext.DefineSwitchDefault(SwitchThrowExceptionIfDisposedCancellationTokenSource, true); } + + if (version <= 40601) + { + AppContext.DefineSwitchDefault(SwitchUseLegacyPathHandling, true); + AppContext.DefineSwitchDefault(SwitchBlockLongPaths, true); + AppContext.DefineSwitchDefault(SwitchSetActorAsReferenceWhenCopyingClaimsIdentity, true); + } + break; } case "WindowsPhone": @@ -50,6 +61,8 @@ namespace System { AppContext.DefineSwitchDefault(SwitchNoAsyncCurrentCulture, true); AppContext.DefineSwitchDefault(SwitchThrowExceptionIfDisposedCancellationTokenSource, true); + AppContext.DefineSwitchDefault(SwitchUseLegacyPathHandling, true); + AppContext.DefineSwitchDefault(SwitchBlockLongPaths, true); } break; } diff --git a/mcs/class/referencesource/mscorlib/system/AppContext/AppContextDefaultValues.cs b/mcs/class/referencesource/mscorlib/system/AppContext/AppContextDefaultValues.cs index 8a130a0f34..9224bf8b8f 100644 --- a/mcs/class/referencesource/mscorlib/system/AppContext/AppContextDefaultValues.cs +++ b/mcs/class/referencesource/mscorlib/system/AppContext/AppContextDefaultValues.cs @@ -3,6 +3,15 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== + +// There are cases where we have multiple assemblies that are going to import this file and +// if they are going to also have InternalsVisibleTo between them, there will be a compiler warning +// that the type is found both in the source and in a referenced assembly. The compiler will prefer +// the version of the type defined in the source +// +// In order to disable the warning for this type we are disabling this warning for this entire file. +#pragma warning disable 436 + using System; using System.Collections.Generic; @@ -167,3 +176,5 @@ namespace System static partial void PopulateDefaultValuesPartial(string platformIdentifier, string profile, int version); } } + +#pragma warning restore 436 diff --git a/mcs/class/referencesource/mscorlib/system/AppContext/AppContextSwitches.cs b/mcs/class/referencesource/mscorlib/system/AppContext/AppContextSwitches.cs index 539e877016..72eb1cccb1 100644 --- a/mcs/class/referencesource/mscorlib/system/AppContext/AppContextSwitches.cs +++ b/mcs/class/referencesource/mscorlib/system/AppContext/AppContextSwitches.cs @@ -41,6 +41,48 @@ namespace System } } + private static int _useLegacyPathHandling; + + /// + /// Use legacy path normalization logic and blocking of extended syntax. + /// + public static bool UseLegacyPathHandling + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return GetCachedSwitchValue(AppContextDefaultValues.SwitchUseLegacyPathHandling, ref _useLegacyPathHandling); + } + } + + private static int _blockLongPaths; + + /// + /// Throw PathTooLongException for paths greater than MAX_PATH or directories greater than 248 (as per CreateDirectory Win32 limitations) + /// + public static bool BlockLongPaths + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return GetCachedSwitchValue(AppContextDefaultValues.SwitchBlockLongPaths, ref _blockLongPaths); + } + } + + private static int _cloneActor; + + /// + /// When copying a ClaimsIdentity.Actor this switch controls whether ClaimsIdentity.Actor should be set as a reference or the result of Actor.Clone() + /// + public static bool SetActorAsReferenceWhenCopyingClaimsIdentity + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return GetCachedSwitchValue(AppContextDefaultValues.SwitchSetActorAsReferenceWhenCopyingClaimsIdentity, ref _cloneActor); + } + } + // // Implementation details // diff --git a/mcs/class/referencesource/mscorlib/system/AppDomainSetup.cs b/mcs/class/referencesource/mscorlib/system/AppDomainSetup.cs index fb850445ce..5509b40250 100644 --- a/mcs/class/referencesource/mscorlib/system/AppDomainSetup.cs +++ b/mcs/class/referencesource/mscorlib/system/AppDomainSetup.cs @@ -318,17 +318,23 @@ namespace System { } } - [ResourceExposure(ResourceScope.Machine)] - [ResourceConsumption(ResourceScope.Machine)] - private String NormalizePath(String path, bool useAppBase) + [System.Security.SecuritySafeCritical] + private string NormalizePath(string path, bool useAppBase) { if(path == null) return null; // If we add very long file name support ("\\?\") to the Path class then this is unnecesary, // but we do not plan on doing this for now. + + // Long path checks can be quirked, and as loading default quirks too early in the setup of an AppDomain is risky + // we'll avoid checking path lengths- we'll still fail at MAX_PATH later if we're !useAppBase when we call Path's + // NormalizePath. if (!useAppBase) - path = System.Security.Util.URLString.PreProcessForExtendedPathRemoval(path, false); + path = System.Security.Util.URLString.PreProcessForExtendedPathRemoval( + checkPathLength: false, + url: path, + isFileUrl: false); int len = path.Length; if (len == 0) @@ -417,10 +423,10 @@ namespace System { if (localPath) { - if (useAppBase && - ( (len == 1) || (path[1] != ':') )) { - String appBase = Value[(int) LoaderInformation.ApplicationBaseValue]; + ((len == 1) || (path[1] != ':'))) + { + String appBase = Value[(int)LoaderInformation.ApplicationBaseValue]; if ((appBase == null) || (appBase.Length == 0)) throw new MemberAccessException(Environment.GetResourceString("AppDomain_AppBaseNotSet")); @@ -429,7 +435,9 @@ namespace System { bool slash = false; if ((path[0] == '/') || (path[0] == '\\')) { - String pathRoot = Path.GetPathRoot(appBase); + // Emulate Path.GetPathRoot without hitting code paths that check quirks + string pathRoot = AppDomain.NormalizePath(appBase, fullCheck: false); + pathRoot = pathRoot.Substring(0, System.IO.PathInternal.GetRootLength(pathRoot)); if (pathRoot.Length == 0) { // URL int index = appBase.IndexOf(":/", StringComparison.Ordinal); if (index == -1) @@ -439,11 +447,11 @@ namespace System { int urlLen = appBase.Length; for (index += 1; (index < urlLen) && ((appBase[index] == '/') || (appBase[index] == '\\')); - index++); + index++) ; // Now find the next slash to get domain name - for(; (index < urlLen) && (appBase[index] != '/') && (appBase[index] != '\\'); - index++); + for (; (index < urlLen) && (appBase[index] != '/') && (appBase[index] != '\\'); + index++) ; pathRoot = appBase.Substring(0, index); } @@ -472,7 +480,9 @@ namespace System { path = StringBuilderCache.GetStringAndRelease(result); } else - path = Path.GetFullPathInternal(path); + { + path = AppDomain.NormalizePath(path, fullCheck: true); + } } return path; @@ -792,20 +802,32 @@ namespace System { [ResourceConsumption(ResourceScope.Machine)] private String VerifyDir(String dir, bool normalize) { - if (dir != null) { + if (dir != null) + { if (dir.Length == 0) + { dir = null; - else { + } + else + { if (normalize) dir = NormalizePath(dir, true); - // The only way AppDomainSetup is exposed in coreclr is through the AppDomainManager - // and the AppDomainManager is a SecurityCritical type. Also, all callers of callstacks - // leading from VerifyDir are SecurityCritical. So we can remove the Demand because - // we have validated that all callers are SecurityCritical + // The only way AppDomainSetup is exposed in coreclr is through the AppDomainManager + // and the AppDomainManager is a SecurityCritical type. Also, all callers of callstacks + // leading from VerifyDir are SecurityCritical. So we can remove the Demand because + // we have validated that all callers are SecurityCritical #if !FEATURE_CORECLR if (IsFilePath(dir)) - new FileIOPermission( FileIOPermissionAccess.PathDiscovery, dir ).Demand(); + { + // If we've already normalized we don't need to do it again, and can avoid hitting + // quirks in FileIOPermission. + new FileIOPermission( + access: FileIOPermissionAccess.PathDiscovery, + pathList: new string[] { dir }, + checkForDuplicates: false, + needFullPath: false).Demand(); + } #endif // !FEATURE_CORECLR } } diff --git a/mcs/class/referencesource/mscorlib/system/appdomain.cs.REMOVED.git-id b/mcs/class/referencesource/mscorlib/system/appdomain.cs.REMOVED.git-id index c212c3ab56..a4fa38e3a3 100644 --- a/mcs/class/referencesource/mscorlib/system/appdomain.cs.REMOVED.git-id +++ b/mcs/class/referencesource/mscorlib/system/appdomain.cs.REMOVED.git-id @@ -1 +1 @@ -0d7719d224a5cc564d4059a538c91201946c6082 \ No newline at end of file +2a704e83006fa15410f41e5e15bbe8ae7ddd0a4f \ No newline at end of file diff --git a/mcs/class/referencesource/mscorlib/system/bitconverter.cs b/mcs/class/referencesource/mscorlib/system/bitconverter.cs index a8a864ac12..49d20cd669 100644 --- a/mcs/class/referencesource/mscorlib/system/bitconverter.cs +++ b/mcs/class/referencesource/mscorlib/system/bitconverter.cs @@ -372,7 +372,7 @@ namespace System { // Converts an array of bytes into a String. public static String ToString (byte[] value, int startIndex, int length) { if (value == null) { - throw new ArgumentNullException("byteArray"); + throw new ArgumentNullException("value"); } if (startIndex < 0 || startIndex >= value.Length && startIndex > 0) { // Don't throw for a 0 length array. diff --git a/mcs/class/referencesource/mscorlib/system/contextboundobject.cs b/mcs/class/referencesource/mscorlib/system/contextboundobject.cs index b0290241aa..f7298b8d11 100644 --- a/mcs/class/referencesource/mscorlib/system/contextboundobject.cs +++ b/mcs/class/referencesource/mscorlib/system/contextboundobject.cs @@ -20,7 +20,7 @@ namespace System { using System.Security.Permissions; [Serializable] [System.Runtime.InteropServices.ComVisible(true)] -#if FEATURE_REMOTING +#if FEATURE_REMOTING || MONO public abstract class ContextBoundObject : MarshalByRefObject { #else // FEATURE_REMOTING public abstract class ContextBoundObject { diff --git a/mcs/class/referencesource/mscorlib/system/deployment/cmsutils.cs b/mcs/class/referencesource/mscorlib/system/deployment/cmsutils.cs index 1c0fb31377..247c7dfe28 100644 --- a/mcs/class/referencesource/mscorlib/system/deployment/cmsutils.cs +++ b/mcs/class/referencesource/mscorlib/system/deployment/cmsutils.cs @@ -79,18 +79,18 @@ namespace System.Deployment.Internal.Isolation.Manifest { [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] - internal static string GetEntryPointFullPath (ActivationContext activationContext) { + internal static string GetEntryPointFullPath (ActivationContext activationContext) + { string file, parameters; GetEntryPoint(activationContext, out file, out parameters); - if (!String.IsNullOrEmpty(file)) { + if (!string.IsNullOrEmpty(file)) + { string directoryName = activationContext.ApplicationDirectory; - if (directoryName == null || directoryName.Length == 0) { + if (directoryName == null || directoryName.Length == 0) + { // If we were passed a relative path, assume the app base is the current working directory - StringBuilder sb = new StringBuilder(Path.MAX_PATH + 1); - if (Win32Native.GetCurrentDirectory(sb.Capacity, sb) == 0) - System.IO.__Error.WinIOError(); - directoryName = sb.ToString(); + directoryName = Directory.UnsafeGetCurrentDirectory(); } file = Path.Combine(directoryName, file); diff --git a/mcs/class/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/SimpleTypeInfos.cs b/mcs/class/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/SimpleTypeInfos.cs index cd70bfb23e..08844d397a 100644 --- a/mcs/class/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/SimpleTypeInfos.cs +++ b/mcs/class/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/SimpleTypeInfos.cs @@ -833,6 +833,15 @@ namespace System.Diagnostics.Tracing { collector.AddBinary(value); } + + public override object GetData(object value) + { + object val = base.GetData(value); + if (null == val) + val = ""; + + return val; + } } /// diff --git a/mcs/class/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/TraceLoggingEventSource.cs b/mcs/class/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/TraceLoggingEventSource.cs index d620ff9635..ae38d4fde5 100644 --- a/mcs/class/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/TraceLoggingEventSource.cs +++ b/mcs/class/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/TraceLoggingEventSource.cs @@ -460,6 +460,7 @@ namespace System.Diagnostics.Tracing } this.WriteEventRaw( + eventName, ref descriptor, activityID, childActivityID, @@ -564,6 +565,7 @@ namespace System.Diagnostics.Tracing } this.WriteEventRaw( + eventName, ref descriptor, activityID, childActivityID, @@ -646,6 +648,7 @@ namespace System.Diagnostics.Tracing eventTypes.typeInfo.WriteData(TraceLoggingDataCollector.Instance, ref data); this.WriteEventRaw( + eventName, ref descriptor, pActivityId, pRelatedActivityId, @@ -665,7 +668,7 @@ namespace System.Diagnostics.Tracing if (ex is EventSourceException) throw; else - ThrowEventSourceException(ex); + ThrowEventSourceException(eventName, ex); } finally { @@ -679,7 +682,7 @@ namespace System.Diagnostics.Tracing if (ex is EventSourceException) throw; else - ThrowEventSourceException(ex); + ThrowEventSourceException(eventName, ex); } } @@ -703,7 +706,7 @@ namespace System.Diagnostics.Tracing eventCallbackArgs.PayloadNames = new ReadOnlyCollection((IList)payload.Keys); } - DisptachToAllListeners(-1, pActivityId, eventCallbackArgs); + DispatchToAllListeners(-1, pActivityId, eventCallbackArgs); } #if !ES_BUILD_PCL diff --git a/mcs/class/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/TraceLoggingMetadataCollector.cs b/mcs/class/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/TraceLoggingMetadataCollector.cs index 1d1f1e708f..ed5ffeca90 100644 --- a/mcs/class/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/TraceLoggingMetadataCollector.cs +++ b/mcs/class/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/TraceLoggingMetadataCollector.cs @@ -99,7 +99,7 @@ namespace System.Diagnostics.Tracing var newGroup = new FieldMetadata( name, TraceLoggingDataType.Struct, - 0, + this.Tags, this.BeginningBufferedArray); this.AddField(newGroup); result = new TraceLoggingMetadataCollector(this, newGroup); diff --git a/mcs/class/referencesource/mscorlib/system/diagnostics/eventing/activitytracker.cs b/mcs/class/referencesource/mscorlib/system/diagnostics/eventing/activitytracker.cs index 633183d941..bdfa364fe1 100644 --- a/mcs/class/referencesource/mscorlib/system/diagnostics/eventing/activitytracker.cs +++ b/mcs/class/referencesource/mscorlib/system/diagnostics/eventing/activitytracker.cs @@ -1,8 +1,6 @@ using System; using System.Diagnostics; using System.Threading; -using System.Threading.Tasks; - #if !ES_BUILD_AGAINST_DOTNET_V35 using Contract = System.Diagnostics.Contracts.Contract; #else @@ -11,15 +9,16 @@ using Contract = Microsoft.Diagnostics.Contracts.Internal.Contract; #if ES_BUILD_STANDALONE namespace Microsoft.Diagnostics.Tracing -#else +#else +using System.Threading.Tasks; namespace System.Diagnostics.Tracing #endif { /// - /// Tracks activities. This is meant to be a singledon (accessed by the ActivityTracer.Instance static property) + /// Tracks activities. This is meant to be a singleton (accessed by the ActivityTracer.Instance static property) /// /// Logically this is simply holds the m_current variable that holds the async local that holds the current ActivityInfo - /// An ActivityInfo is represents a actvity (which knows its creator and thus knows its path). + /// An ActivityInfo is represents a activity (which knows its creator and thus knows its path). /// /// Most of the magic is in the async local (it gets copied to new tasks) /// @@ -39,7 +38,7 @@ namespace System.Diagnostics.Tracing /// On any normal event log the event with activityTracker.CurrentActivityId /// internal class ActivityTracker - { + { /// /// Called on work item begins. The activity name = providerName + activityName without 'Start' suffix. @@ -55,15 +54,32 @@ namespace System.Diagnostics.Tracing public void OnStart(string providerName, string activityName, int task, ref Guid activityId, ref Guid relatedActivityId, EventActivityOptions options) { if (m_current == null) // We are not enabled - return; + { + // We used to rely on the TPL provider turning us on, but that has the disadvantage that you don't get Start-Stop tracking + // until you use Tasks for the first time (which you may never do). Thus we change it to pull rather tan push for whether + // we are enabled. + if (m_checkedForEnable) + return; + m_checkedForEnable = true; +#if ES_BUILD_STANDALONE + Enable(); // Enable it unconditionally. +#else + if (System.Threading.Tasks.TplEtwProvider.Log.IsEnabled(EventLevel.Informational, System.Threading.Tasks.TplEtwProvider.Keywords.TasksFlowActivityIds)) + Enable(); +#endif + if(m_current == null) + { + return; + } + } Contract.Assert((options & EventActivityOptions.Disable) == 0); var currentActivity = m_current.Value; var fullActivityName = NormalizeActivityName(providerName, activityName, task); - + var etwLog = TplEtwProvider.Log; - if (etwLog.Debug) + if (etwLog.Debug) { etwLog.DebugFacilityMessage("OnStartEnter", fullActivityName); etwLog.DebugFacilityMessage("OnStartEnterActivityState", ActivityInfo.LiveActivities(currentActivity)); @@ -100,17 +116,17 @@ namespace System.Diagnostics.Tracing else id = Interlocked.Increment(ref currentActivity.m_lastChildID); - // Remember the previous ID so we can log it - relatedActivityId = currentActivity != null ? currentActivity.ActivityId : Guid.Empty; + // The previous ID is my 'causer' and becomes my related activity ID + relatedActivityId = EventSource.CurrentThreadActivityId; // Add to the list of started but not stopped activities. - ActivityInfo newActivity = new ActivityInfo(fullActivityName, id, currentActivity, options); + ActivityInfo newActivity = new ActivityInfo(fullActivityName, id, currentActivity, relatedActivityId, options); m_current.Value = newActivity; // Remember the current ID so we can log it activityId = newActivity.ActivityId; - if (etwLog.Debug) + if (etwLog.Debug) { etwLog.DebugFacilityMessage("OnStartRetActivityState", ActivityInfo.LiveActivities(newActivity)); etwLog.DebugFacilityMessage1("OnStartRet", activityId.ToString(), relatedActivityId.ToString()); @@ -119,7 +135,7 @@ namespace System.Diagnostics.Tracing /// /// Called when a work item stops. The activity name = providerName + activityName without 'Stop' suffix. - /// It updates CurrentActivityId to track this fact. The Stop event associated with stop should log the ActivityID associated with the event. + /// It updates m_current variable to track this fact. The Stop event associated with stop should log the ActivityID associated with the event. /// /// If activity tracing is not on, then activityId and relatedActivityId are not set /// @@ -131,13 +147,13 @@ namespace System.Diagnostics.Tracing var fullActivityName = NormalizeActivityName(providerName, activityName, task); var etwLog = TplEtwProvider.Log; - if (etwLog.Debug) + if (etwLog.Debug) { etwLog.DebugFacilityMessage("OnStopEnter", fullActivityName); etwLog.DebugFacilityMessage("OnStopEnterActivityState", ActivityInfo.LiveActivities(m_current.Value)); } - for (; ;) // This is a retry loop. + for (; ; ) // This is a retry loop. { ActivityInfo currentActivity = m_current.Value; ActivityInfo newCurrentActivity = null; // if we have seen any live activities (orphans), at he first one we have seen. @@ -193,7 +209,7 @@ namespace System.Diagnostics.Tracing m_current.Value = newCurrentActivity; - if (etwLog.Debug) + if (etwLog.Debug) { etwLog.DebugFacilityMessage("OnStopRetActivityState", ActivityInfo.LiveActivities(newCurrentActivity)); etwLog.DebugFacilityMessage("OnStopRet", activityId.ToString()); @@ -210,12 +226,12 @@ namespace System.Diagnostics.Tracing [System.Security.SecuritySafeCritical] public void Enable() { - if (m_current == null) + if (m_current == null) { m_current = new AsyncLocal(ActivityChanging); } } - + /// /// An activity tracker is a singleton, this is how you get the one and only instance. /// @@ -263,24 +279,25 @@ namespace System.Diagnostics.Tracing // ******************************************************************************* /// - /// An ActivityInfo repesents a particular activity. It is almost read-only the only + /// An ActivityInfo represents a particular activity. It is almost read-only. The only /// fields that change after creation are /// m_lastChildID - used to generate unique IDs for the children activities and for the most part can be ignored. /// m_stopped - indicates that this activity is dead - /// This read-only ness is important because an activity's m_creator chain forms the + /// This read-only-ness is important because an activity's m_creator chain forms the /// 'Path of creation' for the activity (which is also its unique ID) but is also used as /// the 'list of live parents' which indicate of those ancestors, which are alive (if they /// are not marked dead they are alive). /// private class ActivityInfo { - public ActivityInfo(string name, long uniqueId, ActivityInfo creator, EventActivityOptions options) + public ActivityInfo(string name, long uniqueId, ActivityInfo creator, Guid activityIDToRestore, EventActivityOptions options) { m_name = name; m_eventOptions = options; m_creator = creator; m_uniqueId = uniqueId; m_level = creator != null ? creator.m_level + 1 : 0; + m_activityIdToRestore = activityIDToRestore; // Create a nice GUID that encodes the chain of activities that started this one. CreateActivityPathGuid(out m_guid, out m_activityPathGuidOffset); @@ -294,19 +311,19 @@ namespace System.Diagnostics.Tracing } } - public static string Path(ActivityInfo activityInfo) + public static string Path(ActivityInfo activityInfo) { if (activityInfo == null) - return(""); + return (""); return Path(activityInfo.m_creator) + "/" + activityInfo.m_uniqueId; } - public override string ToString() + public override string ToString() { string dead = ""; if (m_stopped != 0) - dead = ",DEAD"; - return m_name + "(" + Path(this) + dead + ")"; + dead = ",DEAD"; + return m_name + "(" + Path(this) + dead + ")"; } public static string LiveActivities(ActivityInfo list) @@ -331,10 +348,10 @@ namespace System.Diagnostics.Tracing /// (rooted in an activity that predates activity tracking. /// /// We wish to encode this path in the Guid to the extent that we can. Many of the paths have - /// many small numbers in them and we take advatage of this in the encoding to output as long + /// many small numbers in them and we take advantage of this in the encoding to output as long /// a path in the GUID as possible. /// - /// Because of the possiblility of GUID collistion, we only use 96 of the 128 bits of the GUID + /// Because of the possibility of GUID collision, we only use 96 of the 128 bits of the GUID /// for encoding the path. The last 32 bits are a simple checksum (and random number) that /// identifies this as using the convention defined here. /// @@ -347,7 +364,7 @@ namespace System.Diagnostics.Tracing [System.Security.SecuritySafeCritical] private unsafe void CreateActivityPathGuid(out Guid idRet, out int activityPathGuidOffset) { - fixed (Guid* outPtr = &idRet) + fixed (Guid* outPtr = &idRet) { int activityPathGuidOffsetStart = 0; if (m_creator != null) @@ -355,13 +372,18 @@ namespace System.Diagnostics.Tracing activityPathGuidOffsetStart = m_creator.m_activityPathGuidOffset; idRet = m_creator.m_guid; } - else + else { - // We start with the appdomain number to make this unique among appdomains. - activityPathGuidOffsetStart = AddIdToGuid(outPtr, activityPathGuidOffsetStart, (uint) System.Threading.Thread.GetDomainID()); + // + int appDomainID = 0; +#if !ES_BUILD_PCL + appDomainID = System.Threading.Thread.GetDomainID(); +#endif + // We start with the appdomain number to make this unique among appdomains. + activityPathGuidOffsetStart = AddIdToGuid(outPtr, activityPathGuidOffsetStart, (uint)appDomainID); } - activityPathGuidOffset = AddIdToGuid(outPtr, activityPathGuidOffsetStart, (uint) m_uniqueId); + activityPathGuidOffset = AddIdToGuid(outPtr, activityPathGuidOffsetStart, (uint)m_uniqueId); // If the path does not fit, Make a GUID by incrementing rather than as a path, keeping as much of the path as possible @@ -372,19 +394,19 @@ namespace System.Diagnostics.Tracing /// /// If we can't fit the activity Path into the GUID we come here. What we do is simply - /// generate a 4 byte number (s_nextOverflowId). Then look for an anscesor that has + /// generate a 4 byte number (s_nextOverflowId). Then look for an ancestor that has /// sufficient space for this ID. By doing this, we preserve the fact that this activity /// is a child (of unknown depth) from that ancestor. /// [System.Security.SecurityCritical] private unsafe void CreateOverflowGuid(Guid* outPtr) { - // Seach backwards for an ancestor that has sufficient space to put the ID. - for(ActivityInfo ancestor = m_creator; ancestor != null; ancestor = ancestor.m_creator) + // Search backwards for an ancestor that has sufficient space to put the ID. + for (ActivityInfo ancestor = m_creator; ancestor != null; ancestor = ancestor.m_creator) { if (ancestor.m_activityPathGuidOffset <= 10) // we need at least 2 bytes. { - uint id = (uint) Interlocked.Increment(ref ancestor.m_lastChildID); // Get a unique ID + uint id = unchecked((uint)Interlocked.Increment(ref ancestor.m_lastChildID)); // Get a unique ID // Try to put the ID into the GUID *outPtr = ancestor.m_guid; int endId = AddIdToGuid(outPtr, ancestor.m_activityPathGuidOffset, id, true); @@ -397,8 +419,8 @@ namespace System.Diagnostics.Tracing } /// - /// The encoding for a list of numbers used to make Activity Guids. Basically - /// we operate on nibbles (which are nice becase they show up as hex digits). The + /// The encoding for a list of numbers used to make Activity GUIDs. Basically + /// we operate on nibbles (which are nice because they show up as hex digits). The /// list is ended with a end nibble (0) and depending on the nibble value (Below) /// the value is either encoded into nibble itself or it can spill over into the /// bytes that follow. @@ -409,18 +431,18 @@ namespace System.Diagnostics.Tracing LastImmediateValue = 0xA, PrefixCode = 0xB, // all the 'long' encodings go here. If the next nibble is MultiByte1-4 - // than this is a 'overflow' id. Unlike the hierarchitcal IDs these are - // allocated densly but don't tell you anything about nesting. we use - // these when we run out of space in the GUID to store the path. + // than this is a 'overflow' id. Unlike the hierarchical IDs these are + // allocated densely but don't tell you anything about nesting. we use + // these when we run out of space in the GUID to store the path. MultiByte1 = 0xC, // 1 byte follows. If this Nibble is in the high bits, it the high bits of the number are stored in the low nibble. // commented out because the code does not explicitly reference the names (but they are logically defined). - // MultiByte2 = 0xD, // 2 bytes follow (we don't bother with the nibble optimzation) - // MultiByte3 = 0xE, // 3 bytes follow (we don't bother with the nibble optimzation) - // MultiByte4 = 0xF, // 4 bytes follow (we don't bother with the nibble optimzation) + // MultiByte2 = 0xD, // 2 bytes follow (we don't bother with the nibble optimization) + // MultiByte3 = 0xE, // 3 bytes follow (we don't bother with the nibble optimization) + // MultiByte4 = 0xF, // 4 bytes follow (we don't bother with the nibble optimization) } - /// Add the acivity id 'id' to the output Guid 'outPtr' starting at the offset 'whereToAddId' + /// Add the activity id 'id' to the output Guid 'outPtr' starting at the offset 'whereToAddId' /// Thus if this number is 6 that is where 'id' will be added. This will return 13 (12 /// is the maximum number of bytes that fit in a GUID) if the path did not fit. /// If 'overflow' is true, then the number is encoded as an 'overflow number (which has a @@ -450,9 +472,9 @@ namespace System.Diagnostics.Tracing { if (endPtr <= ptr + 2) // I need at least 2 bytes return 13; - + // Write out the prefix code nibble and the length nibble - WriteNibble(ref ptr, endPtr, (uint) NumberListCodes.PrefixCode); + WriteNibble(ref ptr, endPtr, (uint)NumberListCodes.PrefixCode); } // The rest is the same for overflow and non-overflow case WriteNibble(ref ptr, endPtr, (uint)NumberListCodes.MultiByte1 + (len - 1)); @@ -460,7 +482,7 @@ namespace System.Diagnostics.Tracing // Do we have an odd nibble? If so flush it or use it for the 12 byte case. if (ptr < endPtr && *ptr != 0) { - // If the value < 4096 we can use the nibble we are otherwise just outputing as padding. + // If the value < 4096 we can use the nibble we are otherwise just outputting as padding. if (id < 4096) { // Indicate this is a 1 byte multicode with 4 high order bits in the lower nibble. @@ -471,7 +493,7 @@ namespace System.Diagnostics.Tracing } // Write out the bytes. - while(0 < len) + while (0 < len) { if (endPtr <= ptr) { @@ -514,14 +536,15 @@ namespace System.Diagnostics.Tracing #endregion // CreateGuidForActivityPath readonly internal string m_name; // The name used in the 'start' and 'stop' APIs to help match up - readonly long m_uniqueId; // a small number that makes this activity unique among its siblings - internal readonly Guid m_guid; // Activity Guid, it is bascially an encoding of the Path() (see CreateActivityPathGuid) + readonly long m_uniqueId; // a small number that makes this activity unique among its siblings + internal readonly Guid m_guid; // Activity Guid, it is basically an encoding of the Path() (see CreateActivityPathGuid) internal readonly int m_activityPathGuidOffset; // Keeps track of where in m_guid the causality path stops (used to generated child GUIDs) internal readonly int m_level; // current depth of the Path() of the activity (used to keep recursion under control) readonly internal EventActivityOptions m_eventOptions; // Options passed to start. internal long m_lastChildID; // used to create a unique ID for my children activities internal int m_stopped; // This work item has stopped readonly internal ActivityInfo m_creator; // My parent (creator). Forms the Path() for the activity. + readonly internal Guid m_activityIdToRestore; // The Guid to restore after a stop. #endregion } @@ -530,26 +553,50 @@ namespace System.Diagnostics.Tracing // with m_current.ActivityID void ActivityChanging(AsyncLocalValueChangedArgs args) { - if (args.PreviousValue == args.CurrentValue) - return; + ActivityInfo cur = args.CurrentValue; + ActivityInfo prev = args.PreviousValue; - if (args.CurrentValue != null) + // Are we popping off a value? (we have a prev, and it creator is cur) + // Then check if we should use the GUID at the time of the start event + if (prev != null && prev.m_creator == cur) { - // Allow subsequent activities inside this thread to automatically get the current activity ID. - EventSource.SetCurrentThreadActivityId(args.CurrentValue.ActivityId); + // If the saved activity ID is not the same as the creator activity + // that takes precedence (it means someone explicitly did a SetActivityID) + // Set it to that and get out + if (cur == null || prev.m_activityIdToRestore != cur.ActivityId) + { + EventSource.SetCurrentThreadActivityId(prev.m_activityIdToRestore); + return; + } } - else - EventSource.SetCurrentThreadActivityId(Guid.Empty); + + // OK we did not have an explicit SetActivityID set. Then we should be + // setting the activity to current ActivityInfo. However that activity + // might be dead, in which case we should skip it, so we never set + // the ID to dead things. + while(cur != null) + { + // We found a live activity (typically the first time), set it to that. + if (cur.m_stopped == 0) + { + EventSource.SetCurrentThreadActivityId(cur.ActivityId); + return; + } + cur = cur.m_creator; + } + // we can get here if there is no information on our activity stack (everything is dead) + // currently we do nothing, as that seems better than setting to Guid.Emtpy. } /// - /// Async local variables have the propery that the are automatically copied whenever a task is created and used + /// Async local variables have the properly that the are automatically copied whenever a task is created and used /// while that task is running. Thus m_current 'flows' to any task that is caused by the current thread that /// last set it. /// /// This variable points a a linked list that represents all Activities that have started but have not stopped. /// AsyncLocal m_current; + bool m_checkedForEnable; // Singleton private static ActivityTracker s_activityTrackerInstance = new ActivityTracker(); @@ -557,8 +604,74 @@ namespace System.Diagnostics.Tracing // Used to create unique IDs at the top level. Not used for nested Ids (each activity has its own id generator) static long m_nextId = 0; private const ushort MAX_ACTIVITY_DEPTH = 100; // Limit maximum depth of activities to be tracked at 100. - // This will avoid leaking memory in case of activities that are never stopped. + // This will avoid leaking memory in case of activities that are never stopped. #endregion } + +#if ES_BUILD_STANDALONE + /******************************** SUPPORT *****************************/ + /// + /// This is supplied by the framework. It is has the semantics that the value is copied to any new Tasks that is created + /// by the current task. Thus all causally related code gets this value. Note that reads and writes to this VARIABLE + /// (not what it points it) to this does not need to be protected by locks because it is inherently thread local (you always + /// only get your thread local copy which means that you never have ----s. + /// + /// + [EventSource(Name="Microsoft.Tasks.Nuget")] + internal class TplEtwProvider : EventSource + { + public class Keywords + { + public const EventKeywords Debug = (EventKeywords) 1; + } + + public static TplEtwProvider Log = new TplEtwProvider(); + public bool Debug { get { return IsEnabled(EventLevel.Verbose, Keywords.Debug); } } + + public void DebugFacilityMessage(string Facility, string Message) { WriteEvent(1, Facility, Message); } + public void DebugFacilityMessage1(string Facility, string Message, string Arg) { WriteEvent(2, Facility, Message, Arg); } + public void SetActivityId(Guid Id) { WriteEvent(3, Id); } + } +#endif + +#if ES_BUILD_AGAINST_DOTNET_V35 || ES_BUILD_PCL || NO_ASYNC_LOCAL + + internal sealed class AsyncLocalValueChangedArgs + { + public AsyncLocalValueChangedArgs() + { + } + + public T PreviousValue { get { return default(T); } } + public T CurrentValue { get { return default(T); } } + + } + + internal sealed class AsyncLocal + { + public AsyncLocal() + { + } + + public AsyncLocal(Action> valueChangedHandler) + { + + } + + public T Value + { + get + { + object obj = null; // + return (obj == null) ? default(T) : (T)obj; + } + set + { + // + } + } + } +#endif + } diff --git a/mcs/class/referencesource/mscorlib/system/diagnostics/eventing/eventprovider.cs b/mcs/class/referencesource/mscorlib/system/diagnostics/eventing/eventprovider.cs index 8a3fec6e6f..939d15ee52 100644 --- a/mcs/class/referencesource/mscorlib/system/diagnostics/eventing/eventprovider.cs +++ b/mcs/class/referencesource/mscorlib/system/diagnostics/eventing/eventprovider.cs @@ -91,7 +91,7 @@ namespace System.Diagnostics.Tracing private static WriteEventErrorCode s_returnCode; // The last return code private const int s_basicTypeAllocationBufferSize = 16; - private const int s_etwMaxNumberArguments = 32; + private const int s_etwMaxNumberArguments = 128; private const int s_etwAPIMaxRefObjCount = 8; private const int s_maxEventDataDescriptors = 128; private const int s_traceEventMaximumSize = 65482; diff --git a/mcs/class/referencesource/mscorlib/system/diagnostics/eventing/eventsource.cs.REMOVED.git-id b/mcs/class/referencesource/mscorlib/system/diagnostics/eventing/eventsource.cs.REMOVED.git-id index 89291cc60d..553e7158ad 100644 --- a/mcs/class/referencesource/mscorlib/system/diagnostics/eventing/eventsource.cs.REMOVED.git-id +++ b/mcs/class/referencesource/mscorlib/system/diagnostics/eventing/eventsource.cs.REMOVED.git-id @@ -1 +1 @@ -a1b51851218d5fc20ec8ab7c6933e742e0f6a94b \ No newline at end of file +9ae566937256255d1b55dcc7c0b259983dc54595 \ No newline at end of file diff --git a/mcs/class/referencesource/mscorlib/system/environment.cs b/mcs/class/referencesource/mscorlib/system/environment.cs index 5e9b986bd7..d5feefac38 100644 --- a/mcs/class/referencesource/mscorlib/system/environment.cs +++ b/mcs/class/referencesource/mscorlib/system/environment.cs @@ -416,7 +416,7 @@ namespace System { #if !FEATURE_CORECLR // Do security check - new FileIOPermission(FileIOPermissionAccess.PathDiscovery, path).Demand(); + FileIOPermission.QuickDemand(FileIOPermissionAccess.PathDiscovery, path); #endif return path; diff --git a/mcs/class/referencesource/mscorlib/system/exception.cs b/mcs/class/referencesource/mscorlib/system/exception.cs index b20d663dc8..8bab365089 100644 --- a/mcs/class/referencesource/mscorlib/system/exception.cs +++ b/mcs/class/referencesource/mscorlib/system/exception.cs @@ -429,7 +429,7 @@ namespace System { #if MONO if (method != null) { // source can be null - _source = method.DeclaringType.Assembly.UnprotectedGetName ().Name; + _source = method.DeclaringType.Assembly.GetName ().Name; } #else Module module = method.Module; diff --git a/mcs/class/referencesource/mscorlib/system/gc.cs b/mcs/class/referencesource/mscorlib/system/gc.cs index a4d5858e9e..dcc15f55ed 100644 --- a/mcs/class/referencesource/mscorlib/system/gc.cs +++ b/mcs/class/referencesource/mscorlib/system/gc.cs @@ -65,6 +65,28 @@ namespace System { public static class GC { +#if MONO + [MethodImplAttribute (MethodImplOptions.InternalCall)] + extern static int GetCollectionCount (int generation); + + [MethodImplAttribute (MethodImplOptions.InternalCall)] + extern static int GetMaxGeneration (); + + [MethodImplAttribute (MethodImplOptions.InternalCall)] + extern static void InternalCollect (int generation); + + [MethodImplAttribute (MethodImplOptions.InternalCall)] + extern static void RecordPressure (long bytesAllocated); + + // TODO: Move following to ConditionalWeakTable + [MethodImplAttribute (MethodImplOptions.InternalCall)] + internal extern static void register_ephemeron_array (Ephemeron[] array); + + [MethodImplAttribute (MethodImplOptions.InternalCall)] + extern static object get_ephemeron_tombstone (); + + internal static readonly object EPHEMERON_TOMBSTONE = get_ephemeron_tombstone (); +#else [System.Security.SecurityCritical] // auto-generated [ResourceExposure(ResourceScope.None)] [MethodImplAttribute(MethodImplOptions.InternalCall)] @@ -139,6 +161,7 @@ namespace System { [ResourceExposure(ResourceScope.None)] [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity] private static extern void _RemoveMemoryPressure(UInt64 bytesAllocated); +#endif [System.Security.SecurityCritical] // auto-generated_required public static void AddMemoryPressure (long bytesAllocated) { @@ -153,7 +176,11 @@ namespace System { } Contract.EndContractBlock(); +#if MONO + RecordPressure (bytesAllocated); +#else _AddMemoryPressure((ulong)bytesAllocated); +#endif } [System.Security.SecurityCritical] // auto-generated_required @@ -169,7 +196,11 @@ namespace System { } Contract.EndContractBlock(); +#if MONO + RecordPressure (-bytesAllocated); +#else _RemoveMemoryPressure((ulong) bytesAllocated); +#endif } @@ -198,8 +229,12 @@ namespace System { // [System.Security.SecuritySafeCritical] // auto-generated public static void Collect() { +#if MONO + InternalCollect (MaxGeneration); +#else //-1 says to GC all generations. _Collect(-1, (int)InternalGCCollectionMode.Blocking); +#endif } [System.Security.SecuritySafeCritical] // auto-generated @@ -248,7 +283,11 @@ namespace System { iInternalModes |= (int)InternalGCCollectionMode.NonBlocking; } +#if MONO + InternalCollect (generation); +#else _Collect(generation, iInternalModes); +#endif } [System.Security.SecuritySafeCritical] // auto-generated @@ -260,9 +299,15 @@ namespace System { throw new ArgumentOutOfRangeException("generation", Environment.GetResourceString("ArgumentOutOfRange_GenericPositive")); } Contract.EndContractBlock(); + +#if MONO + return GetCollectionCount(generation); +#else return _CollectionCount(generation, 0); +#endif } +#if !MONO // pass in true to get the BGC or FGC count. [System.Security.SecuritySafeCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] @@ -275,6 +320,7 @@ namespace System { Contract.EndContractBlock(); return _CollectionCount(generation, (getSpecialGCCount ? 1 : 0)); } +#endif // This method DOES NOT DO ANYTHING in and of itself. It's used to // prevent a finalizable object from losing any outstanding references @@ -318,9 +364,16 @@ namespace System { // [System.Security.SecuritySafeCritical] // auto-generated public static int GetGeneration(WeakReference wo) { +#if MONO + object obj = wo.Target; + if (obj == null) + throw new ArgumentException (); + return GetGeneration (obj); +#else int result = GetGenerationWR(wo.m_handle); KeepAlive(wo); return result; +#endif } // Returns the maximum GC generation. Currently assumes only 1 heap. @@ -330,17 +383,23 @@ namespace System { get { return GetMaxGeneration(); } } +#if MONO + [MethodImplAttribute (MethodImplOptions.InternalCall)] + public extern static void WaitForPendingFinalizers (); +#else [System.Security.SecurityCritical] // auto-generated [ResourceExposure(ResourceScope.None)] [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern void _WaitForPendingFinalizers(); + [System.Security.SecuritySafeCritical] // auto-generated public static void WaitForPendingFinalizers() { // QCalls can not be exposed from mscorlib directly, need to wrap it. _WaitForPendingFinalizers(); } +#endif // Indicates that the system should not call the Finalize() method on // an object that would normally require this call. @@ -380,6 +439,31 @@ namespace System { // the GC heap. This does not return the total size of the GC heap, but // only the live objects in the GC heap. // +#if MONO + [MethodImplAttribute (MethodImplOptions.InternalCall)] + public extern static long GetTotalMemory (bool forceFullCollection); + + static bool _RegisterForFullGCNotification(int maxGenerationPercentage, int largeObjectHeapPercentage) + { + throw new NotImplementedException (); + } + + static bool _CancelFullGCNotification () + { + throw new NotImplementedException (); + } + + static int _WaitForFullGCApproach (int millisecondsTimeout) + { + throw new NotImplementedException (); + } + + static int _WaitForFullGCComplete (int millisecondsTimeout) + { + throw new NotImplementedException (); + } + +#else [System.Security.SecuritySafeCritical] // auto-generated public static long GetTotalMemory(bool forceFullCollection) { long size = GetTotalMemory(); @@ -416,6 +500,7 @@ namespace System { [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern int _WaitForFullGCComplete(int millisecondsTimeout); +#endif [SecurityCritical] public static void RegisterForFullGCNotification(int maxGenerationThreshold, int largeObjectHeapThreshold) @@ -503,6 +588,9 @@ namespace System { [SecurityCritical] static bool StartNoGCRegionWorker(long totalSize, bool hasLohSize, long lohSize, bool disallowFullBlockingGC) { +#if MONO + throw new NotImplementedException (); +#else StartNoGCRegionStatus status = (StartNoGCRegionStatus)_StartNoGCRegion(totalSize, hasLohSize, lohSize, disallowFullBlockingGC); if (status == StartNoGCRegionStatus.AmountTooLarge) throw new ArgumentOutOfRangeException("totalSize", @@ -512,6 +600,7 @@ namespace System { else if (status == StartNoGCRegionStatus.NotEnoughMemory) return false; return true; +#endif } [SecurityCritical] @@ -541,6 +630,9 @@ namespace System { [SecurityCritical] static EndNoGCRegionStatus EndNoGCRegionWorker() { +#if MONO + throw new NotImplementedException (); +#else EndNoGCRegionStatus status = (EndNoGCRegionStatus)_EndNoGCRegion(); if (status == EndNoGCRegionStatus.NotInProgress) throw new InvalidOperationException("NoGCRegion mode must be set"); @@ -550,6 +642,7 @@ namespace System { throw new InvalidOperationException("Allocated memory exceeds specified memory for NoGCRegion mode"); return EndNoGCRegionStatus.Succeeded; +#endif } [SecurityCritical] diff --git a/mcs/class/referencesource/mscorlib/system/globalization/compareinfo.cs b/mcs/class/referencesource/mscorlib/system/globalization/compareinfo.cs index 29c4cd43de..75a4bddc77 100644 --- a/mcs/class/referencesource/mscorlib/system/globalization/compareinfo.cs +++ b/mcs/class/referencesource/mscorlib/system/globalization/compareinfo.cs @@ -1348,8 +1348,9 @@ namespace System.Globalization { { return NativeInternalInitSortHandle(localeName, out handleOrigin); } +#endif -#if !FEATURE_CORECLR +#if !FEATURE_CORECLR || MONO private const int SORT_VERSION_WHIDBEY = 0x00001000; private const int SORT_VERSION_V4 = 0x00060101; @@ -1366,7 +1367,11 @@ namespace System.Globalization { [System.Security.SecuritySafeCritical] get { +#if MONO + return SORT_VERSION_V4; +#else return InternalGetSortVersion(); +#endif } } @@ -1380,16 +1385,21 @@ namespace System.Globalization { { if(m_SortVersion == null) { +#if MONO + m_SortVersion = new SortVersion(SORT_VERSION_V4, new Guid("00000001-57ee-1e5c-00b4-d0000bb1e11e")); // Guid returned by corefx and .NET 4.6 +#else Win32Native.NlsVersionInfoEx v = new Win32Native.NlsVersionInfoEx(); v.dwNLSVersionInfoSize = Marshal.SizeOf(typeof(Win32Native.NlsVersionInfoEx)); InternalGetNlsVersionEx(m_dataHandle, m_handleOrigin, m_sortName, ref v); m_SortVersion = new SortVersion(v.dwNLSVersion, (v.dwEffectiveId != 0) ? v.dwEffectiveId : LCID, v.guidCustomVersion); +#endif } return m_SortVersion; } } - + +#if !MONO [System.Security.SecurityCritical] [ResourceExposure(ResourceScope.None)] [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] @@ -1403,7 +1413,6 @@ namespace System.Globalization { [SuppressUnmanagedCodeSecurity] private static extern uint InternalGetSortVersion(); -#endif [System.Security.SecurityCritical] [ResourceExposure(ResourceScope.None)] [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] @@ -1447,6 +1456,8 @@ namespace System.Globalization { [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern int InternalGetSortKey(IntPtr handle, IntPtr handleOrigin, String localeName, int flags, String source, int sourceCount, byte[] target, int targetCount); +#endif + #endif } } diff --git a/mcs/class/referencesource/mscorlib/system/globalization/taiwancalendar.cs b/mcs/class/referencesource/mscorlib/system/globalization/taiwancalendar.cs index 45b0322f8c..e2f2f3055e 100644 --- a/mcs/class/referencesource/mscorlib/system/globalization/taiwancalendar.cs +++ b/mcs/class/referencesource/mscorlib/system/globalization/taiwancalendar.cs @@ -21,7 +21,7 @@ namespace System.Globalization { ** Gregorian 1912/01/01 9999/12/31 ** Taiwan 01/01/01 8088/12/31 ============================================================================*/ - + [System.Runtime.InteropServices.ComVisible(true)] [Serializable] public class TaiwanCalendar: Calendar { diff --git a/mcs/class/referencesource/mscorlib/system/io/__error.cs b/mcs/class/referencesource/mscorlib/system/io/__error.cs index e318533937..a7a35c642d 100644 --- a/mcs/class/referencesource/mscorlib/system/io/__error.cs +++ b/mcs/class/referencesource/mscorlib/system/io/__error.cs @@ -79,29 +79,21 @@ namespace System.IO { [System.Security.SecurityCritical] // auto-generated internal static String GetDisplayablePath(String path, bool isInvalidPath) { - if (String.IsNullOrEmpty(path)) return String.Empty; - // Is it a fully qualified path? - bool isFullyQualified = false; if (path.Length < 2) return path; - if (Path.IsDirectorySeparator(path[0]) && Path.IsDirectorySeparator(path[1])) - isFullyQualified = true; - else if (path[1] == Path.VolumeSeparatorChar) { - isFullyQualified = true; - } - if (!isFullyQualified && !isInvalidPath) + // Return the path as is if we're relative (not fully qualified) and not a bad path + if (PathInternal.IsPartiallyQualified(path) && !isInvalidPath) return path; -#if FEATURE_MONO_CAS bool safeToReturn = false; try { if (!isInvalidPath) { -#if !FEATURE_CORECLR - new FileIOPermission(FileIOPermissionAccess.PathDiscovery, new String[] { path }, false, false).Demand(); +#if !FEATURE_CORECLR && FEATURE_MONO_CAS + FileIOPermission.QuickDemand(FileIOPermissionAccess.PathDiscovery, path, false, false); #endif safeToReturn = true; } @@ -117,9 +109,7 @@ namespace System.IO { // from Security.Util.StringExpressionSet.CanonicalizePath when ':' is found in the path // beyond string index position 1. } -#else - bool safeToReturn = !isInvalidPath; -#endif // FEATURE_MONO_CAS + if (!safeToReturn) { if (Path.IsDirectorySeparator(path[path.Length - 1])) path = Environment.GetResourceString("IO.IO_NoPermissionToDirectoryName"); diff --git a/mcs/class/referencesource/mscorlib/system/io/binaryreader.cs b/mcs/class/referencesource/mscorlib/system/io/binaryreader.cs index 409b35c377..3357589278 100644 --- a/mcs/class/referencesource/mscorlib/system/io/binaryreader.cs +++ b/mcs/class/referencesource/mscorlib/system/io/binaryreader.cs @@ -382,10 +382,23 @@ namespace System.IO { } Contract.Assert(byteBuffer != null, "expected byteBuffer to be non-null"); - unsafe { - fixed (byte* pBytes = byteBuffer) - fixed (char* pChars = buffer) { - charsRead = m_decoder.GetChars(pBytes + position, numBytes, pChars + index, charsRemaining, false); + + checked { + + if (position < 0 || numBytes < 0 || position + numBytes > byteBuffer.Length) { + throw new ArgumentOutOfRangeException("byteCount"); + } + + if (index < 0 || charsRemaining < 0 || index + charsRemaining > buffer.Length) { + throw new ArgumentOutOfRangeException("charsRemaining"); + } + + unsafe { + fixed (byte* pBytes = byteBuffer) { + fixed (char* pChars = buffer) { + charsRead = m_decoder.GetChars(pBytes + position, numBytes, pChars + index, charsRemaining, false); + } + } } } diff --git a/mcs/class/referencesource/mscorlib/system/io/binarywriter.cs b/mcs/class/referencesource/mscorlib/system/io/binarywriter.cs index ad11daa8bd..c6f81955e4 100644 --- a/mcs/class/referencesource/mscorlib/system/io/binarywriter.cs +++ b/mcs/class/referencesource/mscorlib/system/io/binarywriter.cs @@ -196,7 +196,7 @@ namespace System.IO { Contract.Assert(_encoding.GetMaxByteCount(1) <= 16, "_encoding.GetMaxByteCount(1) <= 16)"); int numBytes = 0; fixed(byte * pBytes = _buffer) { - numBytes = _encoder.GetBytes(&ch, 1, pBytes, 16, true); + numBytes = _encoder.GetBytes(&ch, 1, pBytes, _buffer.Length, true); } OutStream.Write(_buffer, 0, numBytes); } @@ -371,10 +371,10 @@ namespace System.IO { if (_largeByteBuffer == null) { _largeByteBuffer = new byte[LargeByteBufferSize]; - _maxChars = LargeByteBufferSize / _encoding.GetMaxByteCount(1); + _maxChars = _largeByteBuffer.Length / _encoding.GetMaxByteCount(1); } - if (len <= LargeByteBufferSize) { + if (len <= _largeByteBuffer.Length) { //Contract.Assert(len == _encoding.GetBytes(chars, 0, chars.Length, _largeByteBuffer, 0), "encoding's GetByteCount & GetBytes gave different answers! encoding type: "+_encoding.GetType().Name); _encoding.GetBytes(value, 0, value.Length, _largeByteBuffer, 0); OutStream.Write(_largeByteBuffer, 0, len); @@ -393,14 +393,21 @@ namespace System.IO { // Figure out how many chars to process this round. int charCount = (numLeft > _maxChars) ? _maxChars : numLeft; int byteLen; - fixed(char* pChars = value) { - fixed(byte* pBytes = _largeByteBuffer) { - byteLen = _encoder.GetBytes(pChars + charStart, charCount, pBytes, LargeByteBufferSize, charCount == numLeft); + + checked { + if (charStart < 0 || charCount < 0 || charStart + charCount > value.Length) { + throw new ArgumentOutOfRangeException("charCount"); + } + + fixed(char* pChars = value) { + fixed(byte* pBytes = _largeByteBuffer) { + byteLen = _encoder.GetBytes(pChars + charStart, charCount, pBytes, _largeByteBuffer.Length, charCount == numLeft); + } } } #if _DEBUG totalBytes += byteLen; - Contract.Assert (totalBytes <= len && byteLen <= LargeByteBufferSize, "BinaryWriter::Write(String) - More bytes encoded than expected!"); + Contract.Assert (totalBytes <= len && byteLen <= _largeByteBuffer.Length, "BinaryWriter::Write(String) - More bytes encoded than expected!"); #endif OutStream.Write(_largeByteBuffer, 0, byteLen); charStart += charCount; diff --git a/mcs/class/referencesource/mscorlib/system/io/directory.cs b/mcs/class/referencesource/mscorlib/system/io/directory.cs index da6f5ab57e..943e8ff52b 100644 --- a/mcs/class/referencesource/mscorlib/system/io/directory.cs +++ b/mcs/class/referencesource/mscorlib/system/io/directory.cs @@ -248,17 +248,25 @@ namespace System.IO { int count = stackDir.Count; - if (stackDir.Count != 0) + if (stackDir.Count != 0 +#if FEATURE_CAS_POLICY + // All demands in full trust domains are no-ops, so skip + // + // The full path went through validity checks by being passed through FileIOPermissions already. + // As a sub string of the full path can't fail the checks if the full path passes. + && !CodeAccessSecurityEngine.QuickCheckForAllDemands() +#endif + ) { - String [] securityList = new String[stackDir.Count]; + String[] securityList = new String[stackDir.Count]; stackDir.CopyTo(securityList, 0); for (int j = 0 ; j < securityList.Length; j++) securityList[j] += "\\."; // leaf will never have a slash at the end // Security check for all directories not present only. -#if !FEATURE_PAL && FEATURE_MACL +#if !FEATURE_PAL && FEATURE_MACL AccessControlActions control = (dirSecurity == null) ? AccessControlActions.None : AccessControlActions.Change; - new FileIOPermission(FileIOPermissionAccess.Write, control, securityList, false, false ).Demand(); + FileIOPermission.QuickDemand(FileIOPermissionAccess.Write, control, securityList, false, false); #else #if FEATURE_CORECLR if (checkHost) @@ -270,7 +278,7 @@ namespace System.IO { } } #else - new FileIOPermission(FileIOPermissionAccess.Write, securityList, false, false ).Demand(); + FileIOPermission.QuickDemand(FileIOPermissionAccess.Write, securityList, false, false ); #endif #endif //!FEATURE_PAL && FEATURE_MACL } @@ -298,8 +306,9 @@ namespace System.IO { while (stackDir.Count > 0) { String name = stackDir[stackDir.Count - 1]; stackDir.RemoveAt(stackDir.Count - 1); - if (name.Length >= Path.MAX_DIRECTORY_PATH) + if (PathInternal.IsDirectoryTooLong(name)) throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong")); + r = Win32Native.CreateDirectory(name, secAttrs); if (!r && (firstError == 0)) { int currentError = Marshal.GetLastWin32Error(); @@ -326,7 +335,7 @@ namespace System.IO { state.EnsureState(); } #else - new FileIOPermission(FileIOPermissionAccess.PathDiscovery, GetDemandDir(name, true)).Demand(); + FileIOPermission.QuickDemand(FileIOPermissionAccess.PathDiscovery, GetDemandDir(name, true)); #endif // FEATURE_CORECLR errorString = name; } @@ -1085,36 +1094,14 @@ namespace System.IO { return InternalGetCurrentDirectory(false); } - [System.Security.SecurityCritical] + [System.Security.SecuritySafeCritical] [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] - private static String InternalGetCurrentDirectory(bool checkHost) + private static string InternalGetCurrentDirectory(bool checkHost) { - StringBuilder sb = StringBuilderCache.Acquire(Path.MAX_PATH + 1); - if (Win32Native.GetCurrentDirectory(sb.Capacity, sb) == 0) - __Error.WinIOError(); - String currentDirectory = sb.ToString(); - // Note that if we have somehow put our command prompt into short - // file name mode (ie, by running edlin or a DOS grep, etc), then - // this will return a short file name. - if (currentDirectory.IndexOf('~') >= 0) { - int r = Win32Native.GetLongPathName(currentDirectory, sb, sb.Capacity); - if (r == 0 || r >= Path.MAX_PATH) { - int errorCode = Marshal.GetLastWin32Error(); - if (r >= Path.MAX_PATH) - errorCode = Win32Native.ERROR_FILENAME_EXCED_RANGE; - if (errorCode != Win32Native.ERROR_FILE_NOT_FOUND && - errorCode != Win32Native.ERROR_PATH_NOT_FOUND && - errorCode != Win32Native.ERROR_INVALID_FUNCTION && // by design - enough said. - errorCode != Win32Native.ERROR_ACCESS_DENIED) - __Error.WinIOError(errorCode, String.Empty); - } - currentDirectory = sb.ToString(); - } - StringBuilderCache.Release(sb); - String demandPath = GetDemandDir(currentDirectory, true); + string currentDirectory = AppContextSwitches.UseLegacyPathHandling ? LegacyGetCurrentDirectory() : NewGetCurrentDirectory(); + string demandPath = GetDemandDir(currentDirectory, true); - #if FEATURE_CORECLR if (checkHost) { @@ -1122,11 +1109,72 @@ namespace System.IO { state.EnsureState(); } #else - new FileIOPermission( FileIOPermissionAccess.PathDiscovery, new String[] { demandPath }, false, false ).Demand(); + FileIOPermission.QuickDemand(FileIOPermissionAccess.PathDiscovery, demandPath, false, false); #endif return currentDirectory; } + [System.Security.SecurityCritical] + [ResourceExposure(ResourceScope.Machine)] + [ResourceConsumption(ResourceScope.Machine)] + private static string LegacyGetCurrentDirectory() + { + StringBuilder sb = StringBuilderCache.Acquire(PathInternal.MaxShortPath + 1); + if (Win32Native.GetCurrentDirectory(sb.Capacity, sb) == 0) + __Error.WinIOError(); + string currentDirectory = sb.ToString(); + // Note that if we have somehow put our command prompt into short + // file name mode (ie, by running edlin or a DOS grep, etc), then + // this will return a short file name. + if (currentDirectory.IndexOf('~') >= 0) + { + int r = Win32Native.GetLongPathName(currentDirectory, sb, sb.Capacity); + if (r == 0 || r >= PathInternal.MaxShortPath) + { + int errorCode = Marshal.GetLastWin32Error(); + if (r >= PathInternal.MaxShortPath) + errorCode = Win32Native.ERROR_FILENAME_EXCED_RANGE; + if (errorCode != Win32Native.ERROR_FILE_NOT_FOUND && + errorCode != Win32Native.ERROR_PATH_NOT_FOUND && + errorCode != Win32Native.ERROR_INVALID_FUNCTION && // by design - enough said. + errorCode != Win32Native.ERROR_ACCESS_DENIED) + __Error.WinIOError(errorCode, string.Empty); + } + currentDirectory = sb.ToString(); + } + StringBuilderCache.Release(sb); + return currentDirectory; + } + + [System.Security.SecurityCritical] + [ResourceExposure(ResourceScope.Machine)] + [ResourceConsumption(ResourceScope.Machine)] + private static string NewGetCurrentDirectory() + { + using (StringBuffer buffer = new StringBuffer(PathInternal.MaxShortPath)) + { + uint result = 0; + while ((result = Win32Native.GetCurrentDirectoryW(buffer.CharCapacity, buffer.GetHandle())) > buffer.CharCapacity) + { + // Reported size is greater than the buffer size. Increase the capacity. + // The size returned includes the null only if more space is needed (this case). + buffer.EnsureCharCapacity(result); + } + + if (result == 0) + { + __Error.WinIOError(); + } + + buffer.Length = result; + if (buffer.Contains('~')) + { + return LongPathHelper.GetLongPathName(buffer); + } + + return buffer.ToString(); + } + } #if FEATURE_CORECLR [System.Security.SecurityCritical] // auto-generated @@ -1136,15 +1184,16 @@ namespace System.IO { [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] public static void SetCurrentDirectory(String path) - { + { if (path==null) throw new ArgumentNullException("value"); if (path.Length==0) throw new ArgumentException(Environment.GetResourceString("Argument_PathEmpty")); Contract.EndContractBlock(); - if (path.Length >= Path.MAX_PATH) + + if (PathInternal.IsPathTooLong(path)) throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong")); - + // This will have some large effects on the rest of the runtime // and other appdomains in this process. Demand unmanaged code. #pragma warning disable 618 @@ -1174,19 +1223,19 @@ namespace System.IO { [System.Security.SecurityCritical] [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] - internal static void UnsafeMove(String sourceDirName,String destDirName) { + internal static void UnsafeMove(String sourceDirName, String destDirName) { InternalMove(sourceDirName, destDirName, false); } [System.Security.SecurityCritical] [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] - private static void InternalMove(String sourceDirName,String destDirName,bool checkHost) { + private static void InternalMove(String sourceDirName, String destDirName, bool checkHost) { if (sourceDirName==null) throw new ArgumentNullException("sourceDirName"); if (sourceDirName.Length==0) throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), "sourceDirName"); - + if (destDirName==null) throw new ArgumentNullException("destDirName"); if (destDirName.Length==0) @@ -1195,16 +1244,16 @@ namespace System.IO { String fullsourceDirName = Path.GetFullPathInternal(sourceDirName); String sourcePath = GetDemandDir(fullsourceDirName, false); - - if (sourcePath.Length >= Path.MAX_DIRECTORY_PATH) + + if (PathInternal.IsDirectoryTooLong(sourcePath)) throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong")); String fulldestDirName = Path.GetFullPathInternal(destDirName); String destPath = GetDemandDir(fulldestDirName, false); - if (destPath.Length >= Path.MAX_DIRECTORY_PATH) + if (PathInternal.IsDirectoryTooLong(sourcePath)) throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong")); - + #if FEATURE_CORECLR if (checkHost) { FileSecurityState sourceState = new FileSecurityState(FileSecurityStateAccess.Write | FileSecurityStateAccess.Read, sourceDirName, sourcePath); @@ -1288,7 +1337,7 @@ namespace System.IO { } #else // Make sure we have write permission to this directory - new FileIOPermission(FileIOPermissionAccess.Write, new String[] { demandPath }, false, false ).Demand(); + FileIOPermission.QuickDemand(FileIOPermissionAccess.Write, demandPath, false, false); #endif // Do not recursively delete through reparse points. Perhaps in a diff --git a/mcs/class/referencesource/mscorlib/system/io/directoryinfo.cs b/mcs/class/referencesource/mscorlib/system/io/directoryinfo.cs index 5d88346dd3..4a5d733a5f 100644 --- a/mcs/class/referencesource/mscorlib/system/io/directoryinfo.cs +++ b/mcs/class/referencesource/mscorlib/system/io/directoryinfo.cs @@ -102,7 +102,7 @@ namespace System.IO { state.EnsureState(); } #else - new FileIOPermission(FileIOPermissionAccess.Read, demandDir, false, false ).Demand(); + FileIOPermission.QuickDemand(FileIOPermissionAccess.Read, demandDir, false, false); #endif FullPath = fullPath; @@ -130,7 +130,7 @@ namespace System.IO { { #if !FEATURE_CORECLR demandDir = new String[] {Directory.GetDemandDir(FullPath, true)}; - new FileIOPermission(FileIOPermissionAccess.Read, demandDir, false, false ).Demand(); + FileIOPermission.QuickDemand(FileIOPermissionAccess.Read, demandDir, false, false ); #endif DisplayPath = GetDisplayName(OriginalPath, FullPath); } @@ -169,7 +169,7 @@ namespace System.IO { FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.PathDiscovery | FileSecurityStateAccess.Read, String.Empty, dir.demandDir[0]); state.EnsureState(); #else - new FileIOPermission(FileIOPermissionAccess.PathDiscovery | FileIOPermissionAccess.Read, dir.demandDir, false, false).Demand(); + FileIOPermission.QuickDemand(FileIOPermissionAccess.PathDiscovery | FileIOPermissionAccess.Read, dir.demandDir, false, false); #endif return dir; } @@ -234,7 +234,7 @@ namespace System.IO { FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Write, OriginalPath, demandDirForCreation); state.EnsureState(); #else - new FileIOPermission(FileIOPermissionAccess.Write, new String[] { demandDirForCreation }, false, false).Demand(); + FileIOPermission.QuickDemand(FileIOPermissionAccess.Write, demandDirForCreation, false, false); #endif Directory.InternalCreateDirectory(fullPath, path, directorySecurity); @@ -609,7 +609,7 @@ namespace System.IO { FileSecurityState sourceState = new FileSecurityState(FileSecurityStateAccess.PathDiscovery, String.Empty, demandPath); sourceState.EnsureState(); #else - new FileIOPermission(FileIOPermissionAccess.PathDiscovery, new String[] { demandPath }, false, false).Demand(); + FileIOPermission.QuickDemand(FileIOPermissionAccess.PathDiscovery, demandPath, false, false); #endif return new DirectoryInfo(rootPath); } @@ -629,7 +629,7 @@ namespace System.IO { FileSecurityState sourceState = new FileSecurityState(FileSecurityStateAccess.Write | FileSecurityStateAccess.Read, DisplayPath, Directory.GetDemandDir(FullPath, true)); sourceState.EnsureState(); #else - new FileIOPermission(FileIOPermissionAccess.Write | FileIOPermissionAccess.Read, demandDir, false, false).Demand(); + FileIOPermission.QuickDemand(FileIOPermissionAccess.Write | FileIOPermissionAccess.Read, demandDir, false, false); #endif String fullDestDirName = Path.GetFullPathInternal(destDirName); String demandPath; @@ -648,9 +648,9 @@ namespace System.IO { FileSecurityState destState = new FileSecurityState(FileSecurityStateAccess.Write, destDirName, demandPath); destState.EnsureState(); #else - new FileIOPermission(FileIOPermissionAccess.Write | FileIOPermissionAccess.Read, demandPath).Demand(); + FileIOPermission.QuickDemand(FileIOPermissionAccess.Write | FileIOPermissionAccess.Read, demandPath); #endif - + String fullSourcePath; if (FullPath.EndsWith(Path.DirectorySeparatorChar)) fullSourcePath = FullPath; diff --git a/mcs/class/referencesource/mscorlib/system/io/file.cs b/mcs/class/referencesource/mscorlib/system/io/file.cs index d8a7146e01..8a36be7ee7 100644 --- a/mcs/class/referencesource/mscorlib/system/io/file.cs +++ b/mcs/class/referencesource/mscorlib/system/io/file.cs @@ -1322,10 +1322,23 @@ namespace System.IO { destState.EnsureState(); backupState.EnsureState(); #else - FileIOPermission perm = new FileIOPermission(FileIOPermissionAccess.Read | FileIOPermissionAccess.Write, new String[] { fullSrcPath, fullDestPath}); - if (destinationBackupFileName != null) - perm.AddPathList(FileIOPermissionAccess.Write, fullBackupPath); - perm.Demand(); +#if FEATURE_CAS_POLICY + // All demands in full trust domains are no-ops, just do additional checks + if (CodeAccessSecurityEngine.QuickCheckForAllDemands()) + { + FileIOPermission.EmulateFileIOPermissionChecks(fullSrcPath); + FileIOPermission.EmulateFileIOPermissionChecks(fullDestPath); + if (fullBackupPath != null) + FileIOPermission.EmulateFileIOPermissionChecks(fullBackupPath); + } + else +#endif + { + FileIOPermission perm = new FileIOPermission(FileIOPermissionAccess.Read | FileIOPermissionAccess.Write, new String[] { fullSrcPath, fullDestPath }); + if (fullBackupPath != null) + perm.AddPathList(FileIOPermissionAccess.Write, fullBackupPath); + perm.Demand(); + } #endif int flags = Win32Native.REPLACEFILE_WRITE_THROUGH; diff --git a/mcs/class/referencesource/mscorlib/system/io/fileinfo.cs b/mcs/class/referencesource/mscorlib/system/io/fileinfo.cs index f3da2cbd41..cb2f144af2 100644 --- a/mcs/class/referencesource/mscorlib/system/io/fileinfo.cs +++ b/mcs/class/referencesource/mscorlib/system/io/fileinfo.cs @@ -17,7 +17,7 @@ ===========================================================*/ using System; -#if FEATURE_MACL +#if FEATURE_MACL || MONO using System.Security.AccessControl; #endif using System.Security.Permissions; @@ -132,7 +132,7 @@ namespace System.IO { { #if FEATURE_MONO_CAS #if !FEATURE_CORECLR - new FileIOPermission(FileIOPermissionAccess.Read, new String[] { FullPath }, false, false).Demand(); + FileIOPermission.QuickDemand(FileIOPermissionAccess.Read, FullPath, false, false); #endif #endif _name = Path.GetFileName(OriginalPath); @@ -192,7 +192,7 @@ namespace System.IO { FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Read, DisplayPath, FullPath); state.EnsureState(); #else - new FileIOPermission(FileIOPermissionAccess.PathDiscovery, new String[] { directoryName }, false, false).Demand(); + FileIOPermission.QuickDemand(FileIOPermissionAccess.PathDiscovery, directoryName, false, false); #endif #endif } @@ -226,7 +226,7 @@ namespace System.IO { } } -#if FEATURE_MACL +#if FEATURE_MACL || MONO [ResourceExposure(ResourceScope.None)] [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] public FileSecurity GetAccessControl() @@ -344,7 +344,7 @@ namespace System.IO { state.EnsureState(); #else // For security check, path should be resolved to an absolute path. - new FileIOPermission(FileIOPermissionAccess.Write, new String[] { FullPath }, false, false).Demand(); + FileIOPermission.QuickDemand(FileIOPermissionAccess.Write, FullPath, false, false); #endif #endif @@ -483,7 +483,7 @@ namespace System.IO { sourceState.EnsureState(); destState.EnsureState(); #else - new FileIOPermission(FileIOPermissionAccess.Write | FileIOPermissionAccess.Read, new String[] { FullPath }, false, false).Demand(); + FileIOPermission.QuickDemand(FileIOPermissionAccess.Write | FileIOPermissionAccess.Read, FullPath, false, false); FileIOPermission.QuickDemand(FileIOPermissionAccess.Write, fullDestFileName, false, false); #endif #endif diff --git a/mcs/class/referencesource/mscorlib/system/io/filestream.cs.REMOVED.git-id b/mcs/class/referencesource/mscorlib/system/io/filestream.cs.REMOVED.git-id index d5d927c046..704593ff44 100644 --- a/mcs/class/referencesource/mscorlib/system/io/filestream.cs.REMOVED.git-id +++ b/mcs/class/referencesource/mscorlib/system/io/filestream.cs.REMOVED.git-id @@ -1 +1 @@ -38b86735241ea07f3ab33268fed4980d92d915dd \ No newline at end of file +7e47b8bedeccb5022eb808e71cc10b40a7e730eb \ No newline at end of file diff --git a/mcs/class/referencesource/mscorlib/system/io/filesystemenumerable.cs b/mcs/class/referencesource/mscorlib/system/io/filesystemenumerable.cs index ec69c33afb..5acaf13e86 100644 --- a/mcs/class/referencesource/mscorlib/system/io/filesystemenumerable.cs +++ b/mcs/class/referencesource/mscorlib/system/io/filesystemenumerable.cs @@ -234,7 +234,7 @@ namespace System.IO state2.EnsureState(); } #else - new FileIOPermission(FileIOPermissionAccess.PathDiscovery, demandPaths, false, false).Demand(); + FileIOPermission.QuickDemand(FileIOPermissionAccess.PathDiscovery, demandPaths, false, false); #endif // normalize search criteria @@ -340,7 +340,7 @@ namespace System.IO state2.EnsureState(); } #else - new FileIOPermission(FileIOPermissionAccess.PathDiscovery, demandPaths, false, false).Demand(); + FileIOPermission.QuickDemand(FileIOPermissionAccess.PathDiscovery, demandPaths, false, false); #endif searchData = new Directory.SearchData(normalizedSearchPath, userPath, searchOption); CommonInit(); @@ -591,8 +591,7 @@ namespace System.IO } #else String demandDir = Directory.GetDemandDir(fullPathToDemand, true); - String[] demandPaths = new String[] { demandDir }; - new FileIOPermission(FileIOPermissionAccess.PathDiscovery, demandPaths, false, false).Demand(); + FileIOPermission.QuickDemand(FileIOPermissionAccess.PathDiscovery, demandDir, false, false); #endif } @@ -706,8 +705,7 @@ namespace System.IO FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Read, String.Empty, name); state.EnsureState(); #else - String[] names = new String[] { name }; - new FileIOPermission(FileIOPermissionAccess.Read, names, false, false).Demand(); + FileIOPermission.QuickDemand(FileIOPermissionAccess.Read, name, false, false); #endif FileInfo fi = new FileInfo(name, false); fi.InitializeFrom(result.FindData); @@ -733,8 +731,7 @@ namespace System.IO FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Read, String.Empty, permissionName); state.EnsureState(); #else - String[] permissionNames = new String[] { permissionName }; - new FileIOPermission(FileIOPermissionAccess.Read, permissionNames, false, false).Demand(); + FileIOPermission.QuickDemand(FileIOPermissionAccess.Read, permissionName, false, false); #endif DirectoryInfo di = new DirectoryInfo(name, false); di.InitializeFrom(result.FindData); @@ -770,8 +767,7 @@ namespace System.IO FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Read, String.Empty, permissionName); state.EnsureState(); #else - String[] permissionNames = new String[] { permissionName }; - new FileIOPermission(FileIOPermissionAccess.Read, permissionNames, false, false).Demand(); + FileIOPermission.QuickDemand(FileIOPermissionAccess.Read, permissionName, false, false); #endif DirectoryInfo di = new DirectoryInfo(name, false); di.InitializeFrom(result.FindData); @@ -786,8 +782,7 @@ namespace System.IO FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Read, String.Empty, name); state.EnsureState(); #else - String[] names = new String[] { name }; - new FileIOPermission(FileIOPermissionAccess.Read, names, false, false).Demand(); + FileIOPermission.QuickDemand(FileIOPermissionAccess.Read, name, false, false); #endif FileInfo fi = new FileInfo(name, false); fi.InitializeFrom(result.FindData); diff --git a/mcs/class/referencesource/mscorlib/system/io/filesysteminfo.cs b/mcs/class/referencesource/mscorlib/system/io/filesysteminfo.cs index c551e66159..433d756664 100644 --- a/mcs/class/referencesource/mscorlib/system/io/filesysteminfo.cs +++ b/mcs/class/referencesource/mscorlib/system/io/filesysteminfo.cs @@ -34,7 +34,7 @@ namespace System.IO { [FileIOPermissionAttribute(SecurityAction.InheritanceDemand,Unrestricted=true)] #endif [ComVisible(true)] -#if FEATURE_REMOTING +#if FEATURE_REMOTING || MONO public abstract class FileSystemInfo : MarshalByRefObject, ISerializable { #else // FEATURE_REMOTING public abstract class FileSystemInfo : ISerializable { @@ -107,7 +107,7 @@ namespace System.IO { FileSecurityState sourceState = new FileSecurityState(FileSecurityStateAccess.PathDiscovery, String.Empty, demandDir); sourceState.EnsureState(); #else - new FileIOPermission(FileIOPermissionAccess.PathDiscovery, demandDir).Demand(); + FileIOPermission.QuickDemand(FileIOPermissionAccess.PathDiscovery, demandDir); #endif #endif return FullPath; @@ -126,7 +126,7 @@ namespace System.IO { demandDir = FullPath; #if FEATURE_MONO_CAS #if !FEATURE_CORECLR - new FileIOPermission(FileIOPermissionAccess.PathDiscovery, demandDir).Demand(); + FileIOPermission.QuickDemand(FileIOPermissionAccess.PathDiscovery, demandDir); #endif #endif return FullPath; @@ -353,7 +353,7 @@ namespace System.IO { set { #if FEATURE_MONO_CAS #if !FEATURE_CORECLR - new FileIOPermission(FileIOPermissionAccess.Write, FullPath).Demand(); + FileIOPermission.QuickDemand(FileIOPermissionAccess.Write, FullPath); #endif #endif #if MONO @@ -386,7 +386,7 @@ namespace System.IO { { #if FEATURE_MONO_CAS #if !FEATURE_CORECLR - new FileIOPermission(FileIOPermissionAccess.PathDiscovery, FullPath).Demand(); + FileIOPermission.QuickDemand(FileIOPermissionAccess.PathDiscovery, FullPath); #endif #endif diff --git a/mcs/class/referencesource/mscorlib/system/io/longpath.cs b/mcs/class/referencesource/mscorlib/system/io/longpath.cs index 2240ba9e1a..7b863b95c8 100644 --- a/mcs/class/referencesource/mscorlib/system/io/longpath.cs +++ b/mcs/class/referencesource/mscorlib/system/io/longpath.cs @@ -195,9 +195,9 @@ namespace System.IO { Contract.Requires(destFileName.Length > 0); String fullSourceFileName = LongPath.NormalizePath(sourceFileName); - new FileIOPermission(FileIOPermissionAccess.Read, new String[] { fullSourceFileName }, false, false).Demand(); + FileIOPermission.QuickDemand(FileIOPermissionAccess.Read, fullSourceFileName, false, false); String fullDestFileName = LongPath.NormalizePath(destFileName); - new FileIOPermission(FileIOPermissionAccess.Write, new String[] { fullDestFileName }, false, false).Demand(); + FileIOPermission.QuickDemand(FileIOPermissionAccess.Write, fullDestFileName, false, false); InternalCopy(fullSourceFileName, fullDestFileName, sourceFileName, destFileName, overwrite); } @@ -258,7 +258,7 @@ namespace System.IO { String fullPath = LongPath.NormalizePath(path); // For security check, path should be resolved to an absolute path. - new FileIOPermission(FileIOPermissionAccess.Write, new String[] { fullPath }, false, false ).Demand(); + FileIOPermission.QuickDemand(FileIOPermissionAccess.Write, fullPath, false, false); String tempPath = Path.AddLongPathPrefix(fullPath); bool r = Win32Native.DeleteFile(tempPath); @@ -297,8 +297,8 @@ namespace System.IO { if (path.Length > 0 && Path.IsDirectorySeparator(path[path.Length - 1])) { return false; } - - new FileIOPermission(FileIOPermissionAccess.Read, new String[] { path }, false, false ).Demand(); + + FileIOPermission.QuickDemand(FileIOPermissionAccess.Read, path, false, false ); return InternalExists(path); } @@ -326,7 +326,7 @@ namespace System.IO { Contract.Requires(path != null); String fullPath = LongPath.NormalizePath(path); - new FileIOPermission(FileIOPermissionAccess.Read, new String[] { fullPath }, false, false ).Demand(); + FileIOPermission.QuickDemand(FileIOPermissionAccess.Read, fullPath, false, false); String tempPath = Path.AddLongPathPrefix(fullPath); @@ -348,7 +348,7 @@ namespace System.IO { Contract.Requires(path != null); String fullPath = LongPath.NormalizePath(path); - new FileIOPermission(FileIOPermissionAccess.Read, new String[] { fullPath }, false, false ).Demand(); + FileIOPermission.QuickDemand(FileIOPermissionAccess.Read, fullPath, false, false); String tempPath = Path.AddLongPathPrefix(fullPath); Win32Native.WIN32_FILE_ATTRIBUTE_DATA data = new Win32Native.WIN32_FILE_ATTRIBUTE_DATA(); @@ -369,7 +369,7 @@ namespace System.IO { Contract.Requires(path != null); String fullPath = LongPath.NormalizePath(path); - new FileIOPermission(FileIOPermissionAccess.Read, new String[] { fullPath }, false, false ).Demand(); + FileIOPermission.QuickDemand(FileIOPermissionAccess.Read, fullPath, false, false); String tempPath = Path.AddLongPathPrefix(fullPath); Win32Native.WIN32_FILE_ATTRIBUTE_DATA data = new Win32Native.WIN32_FILE_ATTRIBUTE_DATA(); @@ -400,9 +400,9 @@ namespace System.IO { Contract.Requires(destFileName.Length > 0); String fullSourceFileName = LongPath.NormalizePath(sourceFileName); - new FileIOPermission(FileIOPermissionAccess.Write | FileIOPermissionAccess.Read, new String[] { fullSourceFileName }, false, false).Demand(); + FileIOPermission.QuickDemand(FileIOPermissionAccess.Write | FileIOPermissionAccess.Read, fullSourceFileName, false, false); String fullDestFileName = LongPath.NormalizePath(destFileName); - new FileIOPermission(FileIOPermissionAccess.Write, new String[] { fullDestFileName }, false, false).Demand(); + FileIOPermission.QuickDemand(FileIOPermissionAccess.Write, fullDestFileName, false, false); if (!LongPathFile.InternalExists(fullSourceFileName)) __Error.WinIOError(Win32Native.ERROR_FILE_NOT_FOUND, fullSourceFileName); @@ -423,7 +423,7 @@ namespace System.IO { Contract.Requires(path != null); String fullPath = LongPath.NormalizePath(path); - new FileIOPermission(FileIOPermissionAccess.Read, new String[] { fullPath }, false, false ).Demand(); + FileIOPermission.QuickDemand(FileIOPermissionAccess.Read, fullPath, false, false); String tempPath = Path.AddLongPathPrefix(fullPath); Win32Native.WIN32_FILE_ATTRIBUTE_DATA data = new Win32Native.WIN32_FILE_ATTRIBUTE_DATA(); @@ -435,7 +435,6 @@ namespace System.IO { __Error.WinIOError(Win32Native.ERROR_FILE_NOT_FOUND, path); return ((long)data.fileSizeHigh) << 32 | ((long)data.fileSizeLow & 0xFFFFFFFFL); - } // Defined in WinError.h @@ -460,7 +459,7 @@ namespace System.IO { // We attempt to create directories only after all the security checks have passed. This is avoid doing // a demand at every level. String demandDir = GetDemandDir(fullPath, true); - new FileIOPermission(FileIOPermissionAccess.Read, new String[] { demandDir }, false, false).Demand(); + FileIOPermission.QuickDemand(FileIOPermissionAccess.Read, demandDir, false, false); InternalCreateDirectory(fullPath, path, null); } @@ -514,7 +513,15 @@ namespace System.IO { int count = stackDir.Count; - if (stackDir.Count != 0) + if (stackDir.Count != 0 +#if FEATURE_CAS_POLICY + // All demands in full trust domains are no-ops, so skip + // + // The full path went through validity checks by being passed through FileIOPermissions already. + // As a sub string of the full path can't fail the checks if the full path passes. + && !CodeAccessSecurityEngine.QuickCheckForAllDemands() +#endif + ) { String[] securityList = new String[stackDir.Count]; stackDir.CopyTo(securityList, 0); @@ -524,9 +531,9 @@ namespace System.IO { // Security check for all directories not present only. #if !FEATURE_PAL && FEATURE_MACL AccessControlActions control = (dirSecurity == null) ? AccessControlActions.None : AccessControlActions.Change; - new FileIOPermission(FileIOPermissionAccess.Write, control, securityList, false, false ).Demand(); + FileIOPermission.QuickDemand(FileIOPermissionAccess.Write, control, securityList, false, false); #else - new FileIOPermission(FileIOPermissionAccess.Write, securityList, false, false).Demand(); + FileIOPermission.QuickDemand(FileIOPermissionAccess.Write, securityList, false, false); #endif } @@ -554,9 +561,11 @@ namespace System.IO { { String name = stackDir[stackDir.Count - 1]; stackDir.RemoveAt(stackDir.Count - 1); + if (name.Length >= Path.MaxLongPath) throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong")); - r = Win32Native.CreateDirectory(Path.AddLongPathPrefix(name), secAttrs); + + r = Win32Native.CreateDirectory(PathInternal.EnsureExtendedPrefix(name), secAttrs); if (!r && (firstError == 0)) { int currentError = Marshal.GetLastWin32Error(); @@ -579,7 +588,7 @@ namespace System.IO { // Give the user a nice error message, but don't leak path information. try { - new FileIOPermission(FileIOPermissionAccess.PathDiscovery, new String[] { GetDemandDir(name, true) }, false, false).Demand(); + FileIOPermission.QuickDemand(FileIOPermissionAccess.PathDiscovery, GetDemandDir(name, true), false, false); errorString = name; } catch (SecurityException) { } @@ -631,8 +640,8 @@ namespace System.IO { if (destPath.Length >= Path.MaxLongPath) throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong")); - new FileIOPermission(FileIOPermissionAccess.Write | FileIOPermissionAccess.Read, new String[] { sourcePath }, false, false).Demand(); - new FileIOPermission(FileIOPermissionAccess.Write, new String[] { destPath }, false, false).Demand(); + FileIOPermission.QuickDemand(FileIOPermissionAccess.Write | FileIOPermissionAccess.Read, sourcePath, false, false); + FileIOPermission.QuickDemand(FileIOPermissionAccess.Write, destPath, false, false); if (String.Compare(sourcePath, destPath, StringComparison.OrdinalIgnoreCase) == 0) throw new IOException(Environment.GetResourceString("IO.IO_SourceDestMustBeDifferent")); @@ -643,8 +652,8 @@ namespace System.IO { throw new IOException(Environment.GetResourceString("IO.IO_SourceDestMustHaveSameRoot")); - String tempSourceDirName = Path.AddLongPathPrefix(sourceDirName); - String tempDestDirName = Path.AddLongPathPrefix(destDirName); + String tempSourceDirName = PathInternal.EnsureExtendedPrefix(sourceDirName); + String tempDestDirName = PathInternal.EnsureExtendedPrefix(destDirName); if (!Win32Native.MoveFile(tempSourceDirName, tempDestDirName)) { @@ -683,7 +692,7 @@ namespace System.IO { demandPath = GetDemandDir(fullPath, !recursive); // Make sure we have write permission to this directory - new FileIOPermission(FileIOPermissionAccess.Write, new String[] { demandPath }, false, false).Demand(); + FileIOPermission.QuickDemand(FileIOPermissionAccess.Write, demandPath, false, false); String longPath = Path.AddLongPathPrefix(fullPath); // Do not recursively delete through reparse points. Perhaps in a @@ -904,7 +913,7 @@ namespace System.IO { String fullPath = LongPath.NormalizePath(path); String demandPath = GetDemandDir(fullPath, true); - new FileIOPermission(FileIOPermissionAccess.Read, new String[] { demandPath }, false, false).Demand(); + FileIOPermission.QuickDemand(FileIOPermissionAccess.Read, demandPath, false, false); return InternalExists(fullPath); } diff --git a/mcs/class/referencesource/mscorlib/system/io/path.cs b/mcs/class/referencesource/mscorlib/system/io/path.cs index b4cb0ab7e3..3927d52da0 100644 --- a/mcs/class/referencesource/mscorlib/system/io/path.cs +++ b/mcs/class/referencesource/mscorlib/system/io/path.cs @@ -55,19 +55,19 @@ namespace System.IO { // public static readonly char DirectorySeparatorChar = '\\'; internal const string DirectorySeparatorCharAsString = "\\"; - + // Platform specific alternate directory separator character. // This is backslash ('\') on Unix, and slash ('/') on Windows // and MacOS. // public static readonly char AltDirectorySeparatorChar = '/'; - + // Platform specific volume separator character. This is colon (':') // on Windows and MacOS, and slash ('/') on Unix. This is mostly - // useful for parsing paths like "c:\windows" or "MacVolume:System Folder". + // useful for parsing paths like "c:\windows" or "MacVolume:System Folder". // public static readonly char VolumeSeparatorChar = ':'; - + // Platform specific invalid list of characters in a path. // See the "Naming a File" MSDN conceptual docs for more details on // what is valid in a file name (which is slightly different from what @@ -77,10 +77,10 @@ namespace System.IO { public static readonly char[] InvalidPathChars = { '\"', '<', '>', '|', '\0', (Char)1, (Char)2, (Char)3, (Char)4, (Char)5, (Char)6, (Char)7, (Char)8, (Char)9, (Char)10, (Char)11, (Char)12, (Char)13, (Char)14, (Char)15, (Char)16, (Char)17, (Char)18, (Char)19, (Char)20, (Char)21, (Char)22, (Char)23, (Char)24, (Char)25, (Char)26, (Char)27, (Char)28, (Char)29, (Char)30, (Char)31 }; // Trim trailing white spaces, tabs etc but don't be aggressive in removing everything that has UnicodeCategory of trailing space. - // String.WhitespaceChars will trim aggressively than what the underlying FS does (for ex, NTFS, FAT). - internal static readonly char[] TrimEndChars = { (char) 0x9, (char) 0xA, (char) 0xB, (char) 0xC, (char) 0xD, (char) 0x20, (char) 0x85, (char) 0xA0}; - - private static readonly char[] RealInvalidPathChars = { '\"', '<', '>', '|', '\0', (Char)1, (Char)2, (Char)3, (Char)4, (Char)5, (Char)6, (Char)7, (Char)8, (Char)9, (Char)10, (Char)11, (Char)12, (Char)13, (Char)14, (Char)15, (Char)16, (Char)17, (Char)18, (Char)19, (Char)20, (Char)21, (Char)22, (Char)23, (Char)24, (Char)25, (Char)26, (Char)27, (Char)28, (Char)29, (Char)30, (Char)31 }; + // String.WhitespaceChars will trim aggressively than what the underlying FS does (for ex, NTFS, FAT). + internal static readonly char[] TrimEndChars = LongPathHelper.s_trimEndChars; + + private static readonly char[] RealInvalidPathChars = PathInternal.InvalidPathChars; // This is used by HasIllegalCharacters private static readonly char[] InvalidPathCharsWithAdditionalChecks = { '\"', '<', '>', '|', '\0', (Char)1, (Char)2, (Char)3, (Char)4, (Char)5, (Char)6, (Char)7, (Char)8, (Char)9, (Char)10, (Char)11, (Char)12, (Char)13, (Char)14, (Char)15, (Char)16, (Char)17, (Char)18, (Char)19, (Char)20, (Char)21, (Char)22, (Char)23, (Char)24, (Char)25, (Char)26, (Char)27, (Char)28, (Char)29, (Char)30, (Char)31, '*', '?' }; @@ -89,16 +89,15 @@ namespace System.IO { public static readonly char PathSeparator = ';'; - // Make this public sometime. // The max total path is 260, and the max individual component length is 255. // For example, D:\<256 char file name> isn't legal, even though it's under 260 chars. - internal static readonly int MaxPath = 260; - private static readonly int MaxDirectoryLength = 255; + internal static readonly int MaxPath = PathInternal.MaxShortPath; + private static readonly int MaxDirectoryLength = PathInternal.MaxComponentLength; // Windows API definitions - internal const int MAX_PATH = 260; // From WinDef.h - internal const int MAX_DIRECTORY_PATH = 248; // cannot create directories greater than 248 characters + internal const int MAX_PATH = PathInternal.MaxShortPath; // From WinDef.h + internal const int MAX_DIRECTORY_PATH = PathInternal.MaxShortDirectoryPath; // cannot create directories greater than 248 characters // Changes the extension of a file path. The path parameter // specifies a file path, and the extension parameter @@ -136,7 +135,6 @@ namespace System.IO { return null; } - // Returns the directory path of a file path. This method effectively // removes the last element of the given file path, i.e. it returns a // string consisting of all characters up to but not including the last @@ -146,7 +144,17 @@ namespace System.IO { // [ResourceExposure(ResourceScope.None)] [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] - public static String GetDirectoryName(String path) { + public static string GetDirectoryName(string path) + { + return InternalGetDirectoryName(path); + } + + [ResourceExposure(ResourceScope.None)] + [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] + [System.Security.SecuritySafeCritical] + + private static string InternalGetDirectoryName(string path) + { if (path != null) { CheckInvalidPathChars(path); @@ -154,16 +162,29 @@ namespace System.IO { if (!CompatibilitySwitches.IsAppEarlierThanWindowsPhone8) { #endif - string normalizedPath = NormalizePath(path, false); + // Expanding short paths is dangerous in this case as the results will change with the current directory. + // + // Suppose you have a path called "PICTUR~1\Foo". Now suppose you have two folders on disk "C:\Mine\Pictures Of Me" + // and "C:\Yours\Pictures of You". If the current directory is neither you'll get back "PICTUR~1". If it is "C:\Mine" + // get back "Pictures Of Me". "C:\Yours" would give back "Pictures of You". + // + // Because of this and as it isn't documented that short paths are expanded we will not expand short names unless + // we're in legacy mode. + string normalizedPath = NormalizePath(path, fullCheck: false, expandShortPaths: AppContextSwitches.UseLegacyPathHandling); // If there are no permissions for PathDiscovery to this path, we should NOT expand the short paths // as this would leak information about paths to which the user would not have access to. - if (path.Length > 0) + if (path.Length > 0 +#if FEATURE_CAS_POLICY + // Only do the extra logic if we're not in full trust + && !CodeAccessSecurityEngine.QuickCheckForAllDemands() +#endif + ) { try { // If we were passed in a path with \\?\ we need to remove it as FileIOPermission does not like it. - string tempPath = Path.RemoveLongPathPrefix(path); + string tempPath = RemoveLongPathPrefix(path); // FileIOPermission cannot handle paths that contain ? or * // So we only pass to FileIOPermission the text up to them. @@ -176,14 +197,14 @@ namespace System.IO { // While we don't use the result of this call we are using it as a consistent way of // doing the security checks. if (pos > 0) - Path.GetFullPath(tempPath.Substring(0, pos)); + GetFullPath(tempPath.Substring(0, pos)); } catch (SecurityException) { // If the user did not have permissions to the path, make sure that we don't leak expanded short paths // Only re-normalize if the original path had a ~ in it. if (path.IndexOf("~", StringComparison.Ordinal) != -1) { - normalizedPath = NormalizePath(path, /*fullCheck*/ false, /*expandShortPaths*/ false); + normalizedPath = NormalizePath(path, fullCheck: false, expandShortPaths: false); } } catch (PathTooLongException) { } @@ -203,13 +224,13 @@ namespace System.IO { if (i > root) { i = path.Length; if (i == root) return null; - while (i > root && path[--i] != DirectorySeparatorChar && path[i] != AltDirectorySeparatorChar); + while (i > root && path[--i] != DirectorySeparatorChar && path[i] != AltDirectorySeparatorChar); String dir = path.Substring(0, i); #if FEATURE_LEGACYNETCF - if (CompatibilitySwitches.IsAppEarlierThanWindowsPhone8) { + if (CompatibilitySwitches.IsAppEarlierThanWindowsPhone8) { if (dir.Length >= MAX_PATH - 1) throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong")); - } + } #endif return dir; } @@ -220,9 +241,22 @@ namespace System.IO { // Gets the length of the root DirectoryInfo or whatever DirectoryInfo markers // are specified for the first part of the DirectoryInfo name. // - internal static int GetRootLength(String path) { + internal static int GetRootLength(string path) + { CheckInvalidPathChars(path); - + + if (AppContextSwitches.UseLegacyPathHandling) + { + return LegacyGetRootLength(path); + } + else + { + return PathInternal.GetRootLength(path); + } + } + + private static int LegacyGetRootLength(string path) + { int i = 0; int length = path.Length; @@ -247,7 +281,6 @@ namespace System.IO { return (c==DirectorySeparatorChar || c == AltDirectorySeparatorChar); } - public static char[] GetInvalidPathChars() { return (char[]) RealInvalidPathChars.Clone(); @@ -330,7 +363,7 @@ namespace System.IO { throw new ArgumentNullException("path"); Contract.EndContractBlock(); - String newPath = NormalizePath(path, true); + string newPath = NormalizePath(path, fullCheck: true); return newPath; } @@ -338,8 +371,9 @@ namespace System.IO { [System.Security.SecuritySafeCritical] // auto-generated [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] - internal unsafe static String NormalizePath(String path, bool fullCheck) { - return NormalizePath(path, fullCheck, MaxPath); + internal unsafe static String NormalizePath(String path, bool fullCheck) + { + return NormalizePath(path, fullCheck, AppContextSwitches.BlockLongPaths ? PathInternal.MaxShortPath : PathInternal.MaxLongPath); } [System.Security.SecuritySafeCritical] // auto-generated @@ -347,31 +381,127 @@ namespace System.IO { [ResourceConsumption(ResourceScope.Machine)] internal unsafe static String NormalizePath(String path, bool fullCheck, bool expandShortPaths) { - return NormalizePath(path, fullCheck, MaxPath, expandShortPaths); + return NormalizePath(path, fullCheck, MaxPath, expandShortPaths: expandShortPaths); } [System.Security.SecuritySafeCritical] // auto-generated [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] internal unsafe static String NormalizePath(String path, bool fullCheck, int maxPathLength) { - return NormalizePath(path, fullCheck, maxPathLength, true); + return NormalizePath(path, fullCheck, maxPathLength, expandShortPaths: true); + } + + [System.Security.SecuritySafeCritical] + [ResourceExposure(ResourceScope.Machine)] + [ResourceConsumption(ResourceScope.Machine)] + internal static string NormalizePath(string path, bool fullCheck, int maxPathLength, bool expandShortPaths) + { + if (AppContextSwitches.UseLegacyPathHandling) + { + return LegacyNormalizePath(path, fullCheck, maxPathLength, expandShortPaths); + } + else + { + if (PathInternal.IsExtended(path)) + { + // We can't really know what is valid for all cases of extended paths. + // + // - object names can include other characters as well (':', '/', etc.) + // - even file objects have different rules (pipe names can contain most characters) + // + // As such we will do no further analysis of extended paths to avoid blocking known and unknown + // scenarios as well as minimizing compat breaks should we block now and need to unblock later. + return path; + } + + string normalizedPath = null; + + if (fullCheck == false) + { + // Disabled fullCheck is only called by GetDirectoryName and GetPathRoot. + // Avoid adding addtional callers and try going direct to lighter weight NormalizeDirectorySeparators. + normalizedPath = NewNormalizePathLimitedChecks(path, maxPathLength, expandShortPaths); + } + else + { + normalizedPath = NewNormalizePath(path, maxPathLength, expandShortPaths: true); + } + + if (string.IsNullOrWhiteSpace(normalizedPath)) + throw new ArgumentException(Environment.GetResourceString("Arg_PathIllegal")); + return normalizedPath; + } + } + + [System.Security.SecuritySafeCritical] + private static string NewNormalizePathLimitedChecks(string path, int maxPathLength, bool expandShortPaths) + { + string normalized = PathInternal.NormalizeDirectorySeparators(path); + + if (PathInternal.IsPathTooLong(normalized) || PathInternal.AreSegmentsTooLong(normalized)) + throw new PathTooLongException(); + + if (!PathInternal.IsDevice(normalized) && PathInternal.HasInvalidVolumeSeparator(path)) + throw new ArgumentException(Environment.GetResourceString("Arg_PathIllegal")); + + if (expandShortPaths && normalized.IndexOf('~') != -1) + { + try + { + return LongPathHelper.GetLongPathName(normalized); + } + catch + { + // Don't care if we can't get the long path- might not exist, etc. + } + } + + return normalized; + } + + /// + /// Normalize the path and check for bad characters or other invalid syntax. + /// + [System.Security.SecuritySafeCritical] + [ResourceExposure(ResourceScope.Machine)] + [ResourceConsumption(ResourceScope.Machine)] + private static string NewNormalizePath(string path, int maxPathLength, bool expandShortPaths) + { + Contract.Requires(path != null, "path can't be null"); + + // Embedded null characters are the only invalid character case we want to check up front. + // This is because the nulls will signal the end of the string to Win32 and therefore have + // unpredictable results. Other invalid characters we give a chance to be normalized out. + if (path.IndexOf('\0') != -1) + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidPathChars")); + + // Note that colon and wildcard checks happen in FileIOPermissions + + // Technically this doesn't matter but we used to throw for this case + if (string.IsNullOrWhiteSpace(path)) + throw new ArgumentException(Environment.GetResourceString("Arg_PathIllegal")); + + // We don't want to check invalid characters for device format- see comments for extended above + return LongPathHelper.Normalize(path, (uint)maxPathLength, checkInvalidCharacters: !PathInternal.IsDevice(path), expandShortPaths: expandShortPaths); } [System.Security.SecurityCritical] // auto-generated [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] - internal unsafe static String NormalizePath(String path, bool fullCheck, int maxPathLength, bool expandShortPaths) { - + internal unsafe static string LegacyNormalizePath(string path, bool fullCheck, int maxPathLength, bool expandShortPaths) + { Contract.Requires(path != null, "path can't be null"); - // If we're doing a full path check, trim whitespace and look for - // illegal path characters. - if (fullCheck) { + + // If we're doing a full path check, trim whitespace and look for illegal path characters. + if (fullCheck) + { // Trim whitespace off the end of the string. // Win32 normalization trims only U+0020. path = path.TrimEnd(TrimEndChars); // Look for illegal path characters. - CheckInvalidPathChars(path); + if (PathInternal.AnyPathHasIllegalCharacters(path)) + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidPathChars")); } int index = 0; @@ -777,50 +907,75 @@ namespace System.IO { return returnVal; } - internal const int MaxLongPath = 32000; - private const string LongPathPrefix = @"\\?\"; - private const string UNCPathPrefix = @"\\"; - private const string UNCLongPathPrefixToInsert = @"?\UNC\"; - private const string UNCLongPathPrefix = @"\\?\UNC\"; + internal const int MaxLongPath = PathInternal.MaxLongPath; - internal unsafe static bool HasLongPathPrefix(String path) + private const string LongPathPrefix = PathInternal.ExtendedPathPrefix; + private const string UNCPathPrefix = PathInternal.UncPathPrefix; + private const string UNCLongPathPrefixToInsert = PathInternal.UncExtendedPrefixToInsert; + private const string UNCLongPathPrefix = PathInternal.UncExtendedPathPrefix; + + internal static bool HasLongPathPrefix(string path) { - return path.StartsWith(LongPathPrefix, StringComparison.Ordinal); + if (AppContextSwitches.UseLegacyPathHandling) + return path.StartsWith(LongPathPrefix, StringComparison.Ordinal); + else + return PathInternal.IsExtended(path); } - internal unsafe static String AddLongPathPrefix(String path) + internal static string AddLongPathPrefix(string path) { - if (path.StartsWith(LongPathPrefix, StringComparison.Ordinal)) - return path; + if (AppContextSwitches.UseLegacyPathHandling) + { + if (path.StartsWith(LongPathPrefix, StringComparison.Ordinal)) + return path; - if (path.StartsWith(UNCPathPrefix, StringComparison.Ordinal)) - return path.Insert(2, UNCLongPathPrefixToInsert); // Given \\server\share in longpath becomes \\?\UNC\server\share => UNCLongPathPrefix + path.SubString(2); => The actual command simply reduces the operation cost. + if (path.StartsWith(UNCPathPrefix, StringComparison.Ordinal)) + return path.Insert(2, UNCLongPathPrefixToInsert); // Given \\server\share in longpath becomes \\?\UNC\server\share => UNCLongPathPrefix + path.SubString(2); => The actual command simply reduces the operation cost. - return LongPathPrefix + path; + return LongPathPrefix + path; + } + else + { + return PathInternal.EnsureExtendedPrefix(path); + } } - internal unsafe static String RemoveLongPathPrefix(String path) + internal static string RemoveLongPathPrefix(string path) { - if (!path.StartsWith(LongPathPrefix, StringComparison.Ordinal)) - return path; + if (AppContextSwitches.UseLegacyPathHandling) + { + if (!path.StartsWith(LongPathPrefix, StringComparison.Ordinal)) + return path; - if (path.StartsWith(UNCLongPathPrefix, StringComparison.OrdinalIgnoreCase)) - return path.Remove(2, 6); // Given \\?\UNC\server\share we return \\server\share => @'\\' + path.SubString(UNCLongPathPrefix.Length) => The actual command simply reduces the operation cost. + if (path.StartsWith(UNCLongPathPrefix, StringComparison.OrdinalIgnoreCase)) + return path.Remove(2, 6); // Given \\?\UNC\server\share we return \\server\share => @'\\' + path.SubString(UNCLongPathPrefix.Length) => The actual command simply reduces the operation cost. - return path.Substring(4); + return path.Substring(4); + } + else + { + return PathInternal.RemoveExtendedPrefix(path); + } } - internal unsafe static StringBuilder RemoveLongPathPrefix(StringBuilder pathSB) + internal static StringBuilder RemoveLongPathPrefix(StringBuilder pathSB) { - string path = pathSB.ToString(); - if (!path.StartsWith(LongPathPrefix, StringComparison.Ordinal)) - return pathSB; + if (AppContextSwitches.UseLegacyPathHandling) + { + if (!PathInternal.StartsWithOrdinal(pathSB, LongPathPrefix)) + return pathSB; - if (path.StartsWith(UNCLongPathPrefix, StringComparison.OrdinalIgnoreCase)) - return pathSB.Remove(2, 6); // Given \\?\UNC\server\share we return \\server\share => @'\\' + path.SubString(UNCLongPathPrefix.Length) => The actual command simply reduces the operation cost. + // Given \\?\UNC\server\share we return \\server\share => @'\\' + path.SubString(UNCLongPathPrefix.Length) => The actual command simply reduces the operation cost. + if (PathInternal.StartsWithOrdinal(pathSB, UNCLongPathPrefix, ignoreCase: true)) + return pathSB.Remove(2, 6); - return pathSB.Remove(0, 4); + return pathSB.Remove(0, 4); + } + else + { + return PathInternal.RemoveExtendedPrefix(pathSB); + } } // Returns the name and extension parts of the given path. The resulting @@ -860,8 +1015,6 @@ namespace System.IO { return null; } - - // Returns the root portion of the given path. The resulting string // consists of those rightmost characters of the path that constitute the // root of the path. Possible patterns for the resulting string are: An @@ -876,7 +1029,10 @@ namespace System.IO { [ResourceConsumption(ResourceScope.Machine)] public static String GetPathRoot(String path) { if (path == null) return null; - path = NormalizePath(path, false); + + // Expanding short paths has no impact on the path root- there is no such thing as an + // 8.3 volume or server/share name. + path = NormalizePath(path, fullCheck: false, expandShortPaths: false); return path.Substring(0, GetRootLength(path)); } @@ -903,15 +1059,9 @@ namespace System.IO { internal static bool IsRelative(string path) { Contract.Assert(path != null, "path can't be null"); - if ((path.Length >= 3 && path[1] == VolumeSeparatorChar && path[2] == DirectorySeparatorChar && - ((path[0] >= 'a' && path[0] <= 'z') || (path[0] >= 'A' && path[0] <= 'Z'))) || - (path.Length >= 2 && path[0] == '\\' && path[1] == '\\')) - return false; - else - return true; - + return PathInternal.IsPartiallyQualified(path); } - + // Returns a cryptographically strong random 8.3 string that can be // used as either a folder name or a file name. public static String GetRandomFileName() @@ -978,7 +1128,7 @@ namespace System.IO { state.EnsureState(); } #else - new FileIOPermission(FileIOPermissionAccess.Write, path).Demand(); + FileIOPermission.QuickDemand(FileIOPermissionAccess.Write, path); #endif StringBuilder sb = new StringBuilder(MAX_PATH); uint r = Win32Native.GetTempFileName(path, "tmp", 0, sb); @@ -1214,31 +1364,17 @@ namespace System.IO { searchPattern = searchPattern.Substring(index + 2); } - } - internal static bool HasIllegalCharacters(String path, bool checkAdditional) - { - Contract.Requires(path != null); - - if (checkAdditional) - { - return path.IndexOfAny(InvalidPathCharsWithAdditionalChecks) >= 0; - } - - return path.IndexOfAny(RealInvalidPathChars) >= 0; - } - - internal static void CheckInvalidPathChars(String path, bool checkAdditional = false) + internal static void CheckInvalidPathChars(string path, bool checkAdditional = false) { if (path == null) throw new ArgumentNullException("path"); - if (Path.HasIllegalCharacters(path, checkAdditional)) + if (PathInternal.HasIllegalCharacters(path, checkAdditional)) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidPathChars")); } - internal static String InternalCombine(String path1, String path2) { if (path1==null || path2==null) throw new ArgumentNullException((path1==null) ? "path1" : "path2"); diff --git a/mcs/class/referencesource/mscorlib/system/io/stream.cs b/mcs/class/referencesource/mscorlib/system/io/stream.cs index 007745c7ab..fa022e96e5 100644 --- a/mcs/class/referencesource/mscorlib/system/io/stream.cs +++ b/mcs/class/referencesource/mscorlib/system/io/stream.cs @@ -39,7 +39,7 @@ namespace System.IO { #if CONTRACTS_FULL [ContractClass(typeof(StreamContract))] #endif -#if FEATURE_REMOTING +#if FEATURE_REMOTING || MONO public abstract class Stream : MarshalByRefObject, IDisposable { #else // FEATURE_REMOTING public abstract class Stream : IDisposable { diff --git a/mcs/class/referencesource/mscorlib/system/io/textreader.cs b/mcs/class/referencesource/mscorlib/system/io/textreader.cs index 5f8e7b98a7..9023902cbf 100644 --- a/mcs/class/referencesource/mscorlib/system/io/textreader.cs +++ b/mcs/class/referencesource/mscorlib/system/io/textreader.cs @@ -39,7 +39,7 @@ namespace System.IO { // There are methods on the Stream class for reading bytes. [Serializable] [ComVisible(true)] -#if FEATURE_REMOTING +#if FEATURE_REMOTING || MONO public abstract class TextReader : MarshalByRefObject, IDisposable { #else // FEATURE_REMOTING public abstract class TextReader : IDisposable { diff --git a/mcs/class/referencesource/mscorlib/system/io/textwriter.cs b/mcs/class/referencesource/mscorlib/system/io/textwriter.cs index 2afe3a6cbf..3f484ffadd 100644 --- a/mcs/class/referencesource/mscorlib/system/io/textwriter.cs +++ b/mcs/class/referencesource/mscorlib/system/io/textwriter.cs @@ -39,7 +39,7 @@ namespace System.IO { // There are methods on the Stream class for writing bytes. [Serializable] [ComVisible(true)] -#if FEATURE_REMOTING +#if FEATURE_REMOTING || MONO public abstract class TextWriter : MarshalByRefObject, IDisposable { #else // FEATURE_REMOTING public abstract class TextWriter : IDisposable { diff --git a/mcs/class/referencesource/mscorlib/system/resources/resourcereader.cs b/mcs/class/referencesource/mscorlib/system/resources/resourcereader.cs index a67ee8c29f..33c341eb4f 100644 --- a/mcs/class/referencesource/mscorlib/system/resources/resourcereader.cs +++ b/mcs/class/referencesource/mscorlib/system/resources/resourcereader.cs @@ -1014,10 +1014,15 @@ namespace System.Resources { } } else { - int seekPos = unchecked(4 * _numResources); - if (seekPos < 0) { + // The hexadecimal E translates to binary 1110 + // So, with this & condition we are checking that none of the highest 3 bits are + // set before multiplying, as that would cause an overflow. + if ((_numResources & 0xE0000000) != 0){ + throw new BadImageFormatException(Environment.GetResourceString("BadImageFormat_ResourcesHeaderCorrupted")); } + + int seekPos = unchecked(4 * _numResources); unsafe { _nameHashesPtr = (int*)_ums.PositionPointer; // Skip over the array of nameHashes. @@ -1046,10 +1051,14 @@ namespace System.Resources { } } else { - int seekPos = unchecked(4 * _numResources); - if (seekPos < 0) { + // The hexadecimal E translates to binary 1110 + // So, with this & condition we are checking that none of the highest 3 bits are + // set before multiplying, as that would cause an overflow. + if ((_numResources & 0xE0000000) != 0){ throw new BadImageFormatException(Environment.GetResourceString("BadImageFormat_ResourcesHeaderCorrupted")); } + + int seekPos = unchecked(4 * _numResources); unsafe { _namePositionsPtr = (int*)_ums.PositionPointer; // Skip over the array of namePositions. diff --git a/mcs/class/referencesource/mscorlib/system/runtime/interopservices/runtimeenvironment.cs b/mcs/class/referencesource/mscorlib/system/runtime/interopservices/runtimeenvironment.cs index b74e4d606b..dd983a383e 100644 --- a/mcs/class/referencesource/mscorlib/system/runtime/interopservices/runtimeenvironment.cs +++ b/mcs/class/referencesource/mscorlib/system/runtime/interopservices/runtimeenvironment.cs @@ -151,7 +151,13 @@ namespace System.Runtime.InteropServices { } } -#if FEATURE_COMINTEROP && !MONO +#if FEATURE_COMINTEROP || MONO +#if MONO + private static IntPtr GetRuntimeInterfaceImpl(Guid clsid, Guid riid) + { + throw new NotSupportedException(); + } +#else [System.Security.SecurityCritical] [ResourceExposure(ResourceScope.Process)] [ResourceConsumption(ResourceScope.Process)] @@ -160,6 +166,7 @@ namespace System.Runtime.InteropServices { private static extern IntPtr GetRuntimeInterfaceImpl( [In, MarshalAs(UnmanagedType.LPStruct)] Guid clsid, [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid); +#endif // // This function does the equivalent of calling GetInterface(clsid, riid) on the diff --git a/mcs/class/referencesource/mscorlib/system/runtime/interopservices/windowsruntime/nativemethods.cs b/mcs/class/referencesource/mscorlib/system/runtime/interopservices/windowsruntime/nativemethods.cs index f9cec78699..893340d673 100644 --- a/mcs/class/referencesource/mscorlib/system/runtime/interopservices/windowsruntime/nativemethods.cs +++ b/mcs/class/referencesource/mscorlib/system/runtime/interopservices/windowsruntime/nativemethods.cs @@ -28,22 +28,26 @@ namespace System.Runtime.InteropServices.WindowsRuntime [DllImport("api-ms-win-core-winrt-error-l1-1-1.dll", PreserveSig = false)] [SecurityCritical] [SuppressUnmanagedCodeSecurity] + [DefaultDllImportSearchPaths(DllImportSearchPath.System32)] internal static extern IRestrictedErrorInfo GetRestrictedErrorInfo(); [DllImport("api-ms-win-core-winrt-error-l1-1-1.dll")] [SecurityCritical] [SuppressUnmanagedCodeSecurity] [return: MarshalAs(UnmanagedType.Bool)] + [DefaultDllImportSearchPaths(DllImportSearchPath.System32)] internal static extern bool RoOriginateLanguageException(int error, [MarshalAs(UnmanagedType.HString)]string message, IntPtr languageException); [DllImport("api-ms-win-core-winrt-error-l1-1-1.dll", PreserveSig = false)] [SecurityCritical] [SuppressUnmanagedCodeSecurity] + [DefaultDllImportSearchPaths(DllImportSearchPath.System32)] internal static extern void RoReportUnhandledError(IRestrictedErrorInfo error); [DllImport("api-ms-win-core-winrt-string-l1-1-0.dll", CallingConvention = CallingConvention.StdCall)] [SecurityCritical] [SuppressUnmanagedCodeSecurity] + [DefaultDllImportSearchPaths(DllImportSearchPath.System32)] internal static unsafe extern int WindowsCreateString([MarshalAs(UnmanagedType.LPWStr)] string sourceString, int length, [Out] IntPtr *hstring); @@ -51,6 +55,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime [DllImport("api-ms-win-core-winrt-string-l1-1-0.dll", CallingConvention = CallingConvention.StdCall)] [SecurityCritical] [SuppressUnmanagedCodeSecurity] + [DefaultDllImportSearchPaths(DllImportSearchPath.System32)] internal static unsafe extern int WindowsCreateStringReference(char *sourceString, int length, [Out] HSTRING_HEADER *hstringHeader, @@ -59,11 +64,13 @@ namespace System.Runtime.InteropServices.WindowsRuntime [DllImport("api-ms-win-core-winrt-string-l1-1-0.dll", CallingConvention = CallingConvention.StdCall)] [SecurityCritical] [SuppressUnmanagedCodeSecurity] + [DefaultDllImportSearchPaths(DllImportSearchPath.System32)] internal static extern int WindowsDeleteString(IntPtr hstring); [DllImport("api-ms-win-core-winrt-string-l1-1-0.dll", CallingConvention = CallingConvention.StdCall)] [SecurityCritical] [SuppressUnmanagedCodeSecurity] + [DefaultDllImportSearchPaths(DllImportSearchPath.System32)] internal static unsafe extern char* WindowsGetStringRawBuffer(IntPtr hstring, [Out] uint *length); } } diff --git a/mcs/class/referencesource/mscorlib/system/runtime/serialization/formatters/binary/binaryformatter.cs b/mcs/class/referencesource/mscorlib/system/runtime/serialization/formatters/binary/binaryformatter.cs index 0e7bfafaf9..b82294c787 100644 --- a/mcs/class/referencesource/mscorlib/system/runtime/serialization/formatters/binary/binaryformatter.cs +++ b/mcs/class/referencesource/mscorlib/system/runtime/serialization/formatters/binary/binaryformatter.cs @@ -34,7 +34,7 @@ namespace System.Runtime.Serialization.Formatters.Binary { [System.Runtime.InteropServices.ComVisible(true)] sealed public class BinaryFormatter : -#if !FEATURE_REMOTING +#if !FEATURE_REMOTING && !MONO IFormatter #else IRemotingFormatter diff --git a/mcs/class/referencesource/mscorlib/system/security/accesscontrol/filesecurity.cs b/mcs/class/referencesource/mscorlib/system/security/accesscontrol/filesecurity.cs index 59c44820f3..fad7beb385 100644 --- a/mcs/class/referencesource/mscorlib/system/security/accesscontrol/filesecurity.cs +++ b/mcs/class/referencesource/mscorlib/system/security/accesscontrol/filesecurity.cs @@ -435,9 +435,9 @@ namespace System.Security.AccessControl [SecurityPermission(SecurityAction.Assert, UnmanagedCode=true)] [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] - internal void Persist( String fullPath ) + internal void Persist(string fullPath) { - new FileIOPermission( FileIOPermissionAccess.NoAccess, AccessControlActions.Change, fullPath ).Demand(); + FileIOPermission.QuickDemand(FileIOPermissionAccess.NoAccess, AccessControlActions.Change, fullPath); WriteLock(); @@ -455,12 +455,12 @@ namespace System.Security.AccessControl [System.Security.SecuritySafeCritical] // auto-generated [SecurityPermission(SecurityAction.Assert, UnmanagedCode=true)] - internal void Persist( SafeFileHandle handle, String fullPath ) + internal void Persist(SafeFileHandle handle, string fullPath) { - if ( fullPath != null ) - new FileIOPermission( FileIOPermissionAccess.NoAccess, AccessControlActions.Change, fullPath ).Demand(); + if (fullPath != null) + FileIOPermission.QuickDemand(FileIOPermissionAccess.NoAccess, AccessControlActions.Change, fullPath); else - new FileIOPermission( PermissionState.Unrestricted ).Demand(); + FileIOPermission.QuickDemand(PermissionState.Unrestricted); WriteLock(); @@ -627,11 +627,9 @@ namespace System.Security.AccessControl public sealed class FileSecurity : FileSystemSecurity { - #region Constructors - [System.Security.SecuritySafeCritical] // auto-generated public FileSecurity() - : base( false ) + : base(false) { } @@ -639,11 +637,11 @@ namespace System.Security.AccessControl [SecurityPermission(SecurityAction.Assert, UnmanagedCode=true)] [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] - public FileSecurity( String fileName, AccessControlSections includeSections ) + public FileSecurity(string fileName, AccessControlSections includeSections) : base(false, fileName, includeSections, false) { - String fullPath = Path.GetFullPathInternal(fileName); - new FileIOPermission(FileIOPermissionAccess.NoAccess, AccessControlActions.View, fullPath).Demand(); + string fullPath = Path.GetFullPathInternal(fileName); + FileIOPermission.QuickDemand(FileIOPermissionAccess.NoAccess, AccessControlActions.View, fullPath, checkForDuplicates: false, needFullPath: false); } // Warning! Be exceedingly careful with this constructor. Do not make @@ -654,26 +652,21 @@ namespace System.Security.AccessControl [SecurityPermission(SecurityAction.Assert, UnmanagedCode=true)] [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] - internal FileSecurity( SafeFileHandle handle, String fullPath, AccessControlSections includeSections ) - : base( false, handle, includeSections, false ) + internal FileSecurity(SafeFileHandle handle, string fullPath, AccessControlSections includeSections) + : base(false, handle, includeSections, false) { if (fullPath != null) - new FileIOPermission(FileIOPermissionAccess.NoAccess, AccessControlActions.View, fullPath).Demand(); + FileIOPermission.QuickDemand(FileIOPermissionAccess.NoAccess, AccessControlActions.View, fullPath); else - new FileIOPermission(PermissionState.Unrestricted).Demand(); + FileIOPermission.QuickDemand(PermissionState.Unrestricted); } - - #endregion } - public sealed class DirectorySecurity : FileSystemSecurity { - #region Constructors - [System.Security.SecuritySafeCritical] // auto-generated public DirectorySecurity() - : base( true ) + : base(true) { } @@ -681,14 +674,12 @@ namespace System.Security.AccessControl [SecurityPermission(SecurityAction.Assert, UnmanagedCode=true)] [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] - public DirectorySecurity( String name, AccessControlSections includeSections ) - : base( true, name, includeSections, true ) + public DirectorySecurity(string name, AccessControlSections includeSections) + : base(true, name, includeSections, true) { - String fullPath = Path.GetFullPathInternal(name); - new FileIOPermission(FileIOPermissionAccess.NoAccess, AccessControlActions.View, fullPath).Demand(); + string fullPath = Path.GetFullPathInternal(name); + FileIOPermission.QuickDemand(FileIOPermissionAccess.NoAccess, AccessControlActions.View, fullPath, checkForDuplicates: false, needFullPath: false); } - - #endregion } } diff --git a/mcs/class/referencesource/mscorlib/system/security/attributes.cs b/mcs/class/referencesource/mscorlib/system/security/attributes.cs index cd8b165baa..090998e0a5 100644 --- a/mcs/class/referencesource/mscorlib/system/security/attributes.cs +++ b/mcs/class/referencesource/mscorlib/system/security/attributes.cs @@ -86,12 +86,12 @@ namespace System.Security { #pragma warning disable 618 // We still use SecurityCriticalScope for v2 compat -#if !FEATURE_CORECLR && !MOBILE +#if !FEATURE_CORECLR private SecurityCriticalScope _val; #endif // FEATURE_CORECLR public SecurityCriticalAttribute () {} -#if !FEATURE_CORECLR && !MOBILE +#if !FEATURE_CORECLR public SecurityCriticalAttribute(SecurityCriticalScope scope) { _val = scope; diff --git a/mcs/class/referencesource/mscorlib/system/security/claims/ClaimsIdentity.cs b/mcs/class/referencesource/mscorlib/system/security/claims/ClaimsIdentity.cs index 5b8627cd9b..5f3a25e79b 100644 --- a/mcs/class/referencesource/mscorlib/system/security/claims/ClaimsIdentity.cs +++ b/mcs/class/referencesource/mscorlib/system/security/claims/ClaimsIdentity.cs @@ -315,7 +315,14 @@ namespace System.Security.Claims // if(!IsCircular(claimsIdentity.Actor)) { - m_actor = claimsIdentity.Actor; + if (!AppContextSwitches.SetActorAsReferenceWhenCopyingClaimsIdentity) + { + m_actor = claimsIdentity.Actor.Clone(); + } + else + { + m_actor = claimsIdentity.Actor; + } } else { @@ -334,6 +341,10 @@ namespace System.Security.Claims else SafeAddClaims(claimsIdentity.m_instanceClaims); + if (claimsIdentity.m_userSerializationData != null) + { + m_userSerializationData = claimsIdentity.m_userSerializationData.Clone() as byte[]; + } } else { @@ -594,7 +605,14 @@ namespace System.Security.Claims // the Actor property and so not really needed here. But checking just for sanity sake if(!IsCircular(this.Actor)) { - newIdentity.Actor = this.Actor; + if (!AppContextSwitches.SetActorAsReferenceWhenCopyingClaimsIdentity) + { + newIdentity.Actor = this.Actor.Clone(); + } + else + { + newIdentity.Actor = this.Actor; + } } else { @@ -945,6 +963,7 @@ namespace System.Security.Claims return; m_instanceClaims = new List(); + m_externalClaims = new Collection>(); } diff --git a/mcs/class/referencesource/mscorlib/system/security/cryptography/cryptoconfig.cs b/mcs/class/referencesource/mscorlib/system/security/cryptography/cryptoconfig.cs index 7d3eb777e4..667369d2dd 100644 --- a/mcs/class/referencesource/mscorlib/system/security/cryptography/cryptoconfig.cs +++ b/mcs/class/referencesource/mscorlib/system/security/cryptography/cryptoconfig.cs @@ -122,6 +122,7 @@ namespace System.Security.Cryptography { #endif //FEATURE_CRYPTO || FEATURE_LEGACYNETCFCRYPTO #if FEATURE_CRYPTO ht.Add("System.Security.Cryptography.SHA1CryptoServiceProvider", Constants.OID_OIWSEC_SHA1); + ht.Add("System.Security.Cryptography.SHA1Cng", Constants.OID_OIWSEC_SHA1); #endif //FEATURE_CRYPTO #if FEATURE_CRYPTO || FEATURE_LEGACYNETCFCRYPTO ht.Add("System.Security.Cryptography.SHA1Managed", Constants.OID_OIWSEC_SHA1); @@ -174,13 +175,6 @@ namespace System.Security.Cryptography { #if FEATURE_CRYPTO Type SHA1CryptoServiceProviderType = typeof(System.Security.Cryptography.SHA1CryptoServiceProvider); Type MD5CryptoServiceProviderType = typeof(System.Security.Cryptography.MD5CryptoServiceProvider); -#endif //FEATURE_CRYPTO -#if FEATURE_CRYPTO || FEATURE_LEGACYNETCFCRYPTO - Type SHA256ManagedType = typeof(SHA256Managed); -#endif //FEATURE_CRYPTO || FEATURE_LEGACYNETCFCRYPTO -#if FEATURE_CRYPTO - Type SHA384ManagedType = typeof(SHA384Managed); - Type SHA512ManagedType = typeof(SHA512Managed); Type RIPEMD160ManagedType = typeof(System.Security.Cryptography.RIPEMD160Managed); Type HMACMD5Type = typeof(System.Security.Cryptography.HMACMD5); Type HMACRIPEMD160Type = typeof(System.Security.Cryptography.HMACRIPEMD160); @@ -209,6 +203,9 @@ namespace System.Security.Cryptography { #if FEATURE_CRYPTO Type DSASignatureDescriptionType = typeof(System.Security.Cryptography.DSASignatureDescription); Type RSAPKCS1SHA1SignatureDescriptionType = typeof(System.Security.Cryptography.RSAPKCS1SHA1SignatureDescription); + Type RSAPKCS1SHA256SignatureDescriptionType = typeof(System.Security.Cryptography.RSAPKCS1SHA256SignatureDescription); + Type RSAPKCS1SHA384SignatureDescriptionType = typeof(System.Security.Cryptography.RSAPKCS1SHA384SignatureDescription); + Type RSAPKCS1SHA512SignatureDescriptionType = typeof(System.Security.Cryptography.RSAPKCS1SHA512SignatureDescription); #endif //FEATURE_CRYPTO #if FEATURE_CRYPTO || FEATURE_LEGACYNETCFCRYPTO Type RNGCryptoServiceProviderType = typeof(System.Security.Cryptography.RNGCryptoServiceProvider); @@ -233,11 +230,26 @@ namespace System.Security.Cryptography { string SHA384CryptoSerivceProviderType = "System.Security.Cryptography.SHA384CryptoServiceProvider, " + AssemblyRef.SystemCore; string SHA512CngType = "System.Security.Cryptography.SHA512Cng, " + AssemblyRef.SystemCore; string SHA512CryptoServiceProviderType = "System.Security.Cryptography.SHA512CryptoServiceProvider, " + AssemblyRef.SystemCore; +#endif //FEATURE_CRYPTO + + +#if FEATURE_CRYPTO || FEATURE_LEGACYNETCFCRYPTO + bool fipsOnly = AllowOnlyFipsAlgorithms; + object SHA256DefaultType = typeof(SHA256Managed); +#endif //FEATURE_CRYPTO || FEATURE_LEGACYNETCFCRYPTO + +#if FEATURE_CRYPTO + if (fipsOnly) + { + SHA256DefaultType = SHA256CngType; + } + object SHA384DefaultType = fipsOnly ? (object)SHA384CngType : (object)typeof(SHA384Managed); + object SHA512DefaultType = fipsOnly ? (object)SHA512CngType : (object)typeof(SHA512Managed); // Cryptography algorithms in System.Security string DpapiDataProtectorType = "System.Security.Cryptography.DpapiDataProtector, " + AssemblyRef.SystemSecurity; - #endif //FEATURE_CRYPTO + #if FEATURE_CRYPTO || FEATURE_LEGACYNETCFCRYPTO // Random number generator ht.Add("RandomNumberGenerator", RNGCryptoServiceProviderType); @@ -256,21 +268,21 @@ namespace System.Security.Cryptography { ht.Add("System.Security.Cryptography.MD5Cng", MD5CngType); #endif //FEATURE_CRYPTO #if FEATURE_CRYPTO || FEATURE_LEGACYNETCFCRYPTO - ht.Add("SHA256", SHA256ManagedType); - ht.Add("SHA-256", SHA256ManagedType); - ht.Add("System.Security.Cryptography.SHA256", SHA256ManagedType); + ht.Add("SHA256", SHA256DefaultType); + ht.Add("SHA-256", SHA256DefaultType); + ht.Add("System.Security.Cryptography.SHA256", SHA256DefaultType); #endif //FEATURE_CRYPTO || FEATURE_LEGACYNETCFCRYPTO #if FEATURE_CRYPTO ht.Add("System.Security.Cryptography.SHA256Cng", SHA256CngType); ht.Add("System.Security.Cryptography.SHA256CryptoServiceProvider", SHA256CryptoServiceProviderType); - ht.Add("SHA384", SHA384ManagedType); - ht.Add("SHA-384", SHA384ManagedType); - ht.Add("System.Security.Cryptography.SHA384", SHA384ManagedType); + ht.Add("SHA384", SHA384DefaultType); + ht.Add("SHA-384", SHA384DefaultType); + ht.Add("System.Security.Cryptography.SHA384", SHA384DefaultType); ht.Add("System.Security.Cryptography.SHA384Cng", SHA384CngType); ht.Add("System.Security.Cryptography.SHA384CryptoServiceProvider", SHA384CryptoSerivceProviderType); - ht.Add("SHA512", SHA512ManagedType); - ht.Add("SHA-512", SHA512ManagedType); - ht.Add("System.Security.Cryptography.SHA512", SHA512ManagedType); + ht.Add("SHA512", SHA512DefaultType); + ht.Add("SHA-512", SHA512DefaultType); + ht.Add("System.Security.Cryptography.SHA512", SHA512DefaultType); ht.Add("System.Security.Cryptography.SHA512Cng", SHA512CngType); ht.Add("System.Security.Cryptography.SHA512CryptoServiceProvider", SHA512CryptoServiceProviderType); ht.Add("RIPEMD160", RIPEMD160ManagedType); @@ -357,16 +369,19 @@ namespace System.Security.Cryptography { ht.Add("System.Security.Cryptography.DSASignatureDescription", DSASignatureDescriptionType); ht.Add("http://www.w3.org/2000/09/xmldsig#rsa-sha1", RSAPKCS1SHA1SignatureDescriptionType); ht.Add("System.Security.Cryptography.RSASignatureDescription", RSAPKCS1SHA1SignatureDescriptionType); + ht.Add("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", RSAPKCS1SHA256SignatureDescriptionType); + ht.Add("http://www.w3.org/2001/04/xmldsig-more#rsa-sha384", RSAPKCS1SHA384SignatureDescriptionType); + ht.Add("http://www.w3.org/2001/04/xmldsig-more#rsa-sha512", RSAPKCS1SHA512SignatureDescriptionType); // Xml Dsig/Enc Hash algorithms ht.Add("http://www.w3.org/2000/09/xmldsig#sha1", SHA1CryptoServiceProviderType); // Add the other hash algorithms introduced with XML Encryption #endif //FEATURE_CRYPTO #if FEATURE_CRYPTO || FEATURE_LEGACYNETCFCRYPTO - ht.Add("http://www.w3.org/2001/04/xmlenc#sha256", SHA256ManagedType); + ht.Add("http://www.w3.org/2001/04/xmlenc#sha256", SHA256DefaultType); #endif //FEATURE_CRYPTO || FEATURE_LEGACYNETCFCRYPTO #if FEATURE_CRYPTO && !FEATURE_CORECLR - ht.Add("http://www.w3.org/2001/04/xmlenc#sha512", SHA512ManagedType); + ht.Add("http://www.w3.org/2001/04/xmlenc#sha512", SHA512DefaultType); ht.Add("http://www.w3.org/2001/04/xmlenc#ripemd160", RIPEMD160ManagedType); // Xml Encryption symmetric keys @@ -421,7 +436,7 @@ namespace System.Security.Cryptography { // Xml Dsig-more Uri's as defined in http://www.ietf.org/rfc/rfc4051.txt ht.Add("http://www.w3.org/2001/04/xmldsig-more#md5", MD5CryptoServiceProviderType); - ht.Add("http://www.w3.org/2001/04/xmldsig-more#sha384", SHA384ManagedType); + ht.Add("http://www.w3.org/2001/04/xmldsig-more#sha384", SHA384DefaultType); ht.Add("http://www.w3.org/2001/04/xmldsig-more#hmac-md5", HMACMD5Type); ht.Add("http://www.w3.org/2001/04/xmldsig-more#hmac-ripemd160", HMACRIPEMD160Type); #endif //FEATURE_CRYPTO diff --git a/mcs/class/referencesource/mscorlib/system/security/cryptography/dsa.cs b/mcs/class/referencesource/mscorlib/system/security/cryptography/dsa.cs index 51f9a9ae4c..af2db6e530 100644 --- a/mcs/class/referencesource/mscorlib/system/security/cryptography/dsa.cs +++ b/mcs/class/referencesource/mscorlib/system/security/cryptography/dsa.cs @@ -15,6 +15,7 @@ namespace System.Security.Cryptography { using System.Runtime.Serialization; using System.Security.Util; using System.Globalization; + using System.IO; using System.Diagnostics.Contracts; // DSAParameters is serializable so that one could pass the public parameters @@ -63,10 +64,78 @@ namespace System.Security.Cryptography { return (DSA) CryptoConfig.CreateFromName(algName); } + // DSA does not encode the algorithm identifier into the signature blob, therefore CreateSignature and + // VerifySignature do not need the HashAlgorithmName value, only SignData and VerifyData do. abstract public byte[] CreateSignature(byte[] rgbHash); abstract public bool VerifySignature(byte[] rgbHash, byte[] rgbSignature); + protected virtual byte[] HashData(byte[] data, int offset, int count, HashAlgorithmName hashAlgorithm) + { + throw DerivedClassMustOverride(); + } + + protected virtual byte[] HashData(Stream data, HashAlgorithmName hashAlgorithm) + { + throw DerivedClassMustOverride(); + } + + public byte[] SignData(byte[] data, HashAlgorithmName hashAlgorithm) + { + if (data == null) { throw new ArgumentNullException("data"); } + + return SignData(data, 0, data.Length, hashAlgorithm); + } + + public virtual byte[] SignData(byte[] data, int offset, int count, HashAlgorithmName hashAlgorithm) + { + if (data == null) { throw new ArgumentNullException("data"); } + if (offset < 0 || offset > data.Length) { throw new ArgumentOutOfRangeException("offset"); } + if (count < 0 || count > data.Length - offset) { throw new ArgumentOutOfRangeException("count"); } + if (String.IsNullOrEmpty(hashAlgorithm.Name)) { throw HashAlgorithmNameNullOrEmpty(); } + + byte[] hash = HashData(data, offset, count, hashAlgorithm); + return CreateSignature(hash); + } + + public virtual byte[] SignData(Stream data, HashAlgorithmName hashAlgorithm) + { + if (data == null) { throw new ArgumentNullException("data"); } + if (String.IsNullOrEmpty(hashAlgorithm.Name)) { throw HashAlgorithmNameNullOrEmpty(); } + + byte[] hash = HashData(data, hashAlgorithm); + return CreateSignature(hash); + } + + public bool VerifyData(byte[] data, byte[] signature, HashAlgorithmName hashAlgorithm) + { + if (data == null) { throw new ArgumentNullException("data"); } + + return VerifyData(data, 0, data.Length, signature, hashAlgorithm); + } + + public virtual bool VerifyData(byte[] data, int offset, int count, byte[] signature, HashAlgorithmName hashAlgorithm) + { + if (data == null) { throw new ArgumentNullException("data"); } + if (offset < 0 || offset > data.Length) { throw new ArgumentOutOfRangeException("offset"); } + if (count < 0 || count > data.Length - offset) { throw new ArgumentOutOfRangeException("count"); } + if (signature == null) { throw new ArgumentNullException("signature"); } + if (String.IsNullOrEmpty(hashAlgorithm.Name)) { throw HashAlgorithmNameNullOrEmpty(); } + + byte[] hash = HashData(data, offset, count, hashAlgorithm); + return VerifySignature(hash, signature); + } + + public virtual bool VerifyData(Stream data, byte[] signature, HashAlgorithmName hashAlgorithm) + { + if (data == null) { throw new ArgumentNullException("data"); } + if (signature == null) { throw new ArgumentNullException("signature"); } + if (String.IsNullOrEmpty(hashAlgorithm.Name)) { throw HashAlgorithmNameNullOrEmpty(); } + + byte[] hash = HashData(data, hashAlgorithm); + return VerifySignature(hash, signature); + } + // We can provide a default implementation of FromXmlString because we require // every DSA implementation to implement ImportParameters // All we have to do here is parse the XML. @@ -187,5 +256,15 @@ namespace System.Security.Cryptography { abstract public DSAParameters ExportParameters(bool includePrivateParameters); abstract public void ImportParameters(DSAParameters parameters); + + private static Exception DerivedClassMustOverride() + { + return new NotImplementedException(Environment.GetResourceString("NotSupported_SubclassOverride")); + } + + internal static Exception HashAlgorithmNameNullOrEmpty() + { + return new ArgumentException(Environment.GetResourceString("Cryptography_HashAlgorithmNameNullOrEmpty"), "hashAlgorithm"); + } } } diff --git a/mcs/class/referencesource/mscorlib/system/security/cryptography/dsacryptoserviceprovider.cs b/mcs/class/referencesource/mscorlib/system/security/cryptography/dsacryptoserviceprovider.cs index 318b09813a..df23a26af1 100644 --- a/mcs/class/referencesource/mscorlib/system/security/cryptography/dsacryptoserviceprovider.cs +++ b/mcs/class/referencesource/mscorlib/system/security/cryptography/dsacryptoserviceprovider.cs @@ -268,6 +268,36 @@ namespace System.Security.Cryptography { return VerifyHash(rgbHash, null, rgbSignature); } + protected override byte[] HashData(byte[] data, int offset, int count, HashAlgorithmName hashAlgorithm) + { + // we're sealed and the base should have checked this before calling us + Contract.Assert(data != null); + Contract.Assert(offset >= 0 && offset <= data.Length); + Contract.Assert(count >= 0 && count <= data.Length - offset); + Contract.Assert(!String.IsNullOrEmpty(hashAlgorithm.Name)); + + if (hashAlgorithm != HashAlgorithmName.SHA1) + { + throw new CryptographicException(Environment.GetResourceString("Cryptography_UnknownHashAlgorithm", hashAlgorithm.Name)); + } + + return _sha1.ComputeHash(data, offset, count); + } + + protected override byte[] HashData(Stream data, HashAlgorithmName hashAlgorithm) + { + // we're sealed and the base should have checked this before calling us + Contract.Assert(data != null); + Contract.Assert(!String.IsNullOrEmpty(hashAlgorithm.Name)); + + if (hashAlgorithm != HashAlgorithmName.SHA1) + { + throw new CryptographicException(Environment.GetResourceString("Cryptography_UnknownHashAlgorithm", hashAlgorithm.Name)); + } + + return _sha1.ComputeHash(data); + } + [System.Security.SecuritySafeCritical] // auto-generated public byte[] SignHash(byte[] rgbHash, string str) { if (rgbHash == null) diff --git a/mcs/class/referencesource/mscorlib/system/security/cryptography/rc2cryptoserviceprovider.cs b/mcs/class/referencesource/mscorlib/system/security/cryptography/rc2cryptoserviceprovider.cs index c97acf8e60..89877e0add 100644 --- a/mcs/class/referencesource/mscorlib/system/security/cryptography/rc2cryptoserviceprovider.cs +++ b/mcs/class/referencesource/mscorlib/system/security/cryptography/rc2cryptoserviceprovider.cs @@ -70,6 +70,9 @@ namespace System.Security.Cryptography { [System.Security.SecuritySafeCritical] // auto-generated public override ICryptoTransform CreateEncryptor (byte[] rgbKey, byte[] rgbIV) { #if MONO + if (m_use40bitSalt) + throw new NotImplementedException ("UseSalt=true is not implemented on Mono yet"); + return new RC2Transform (this, true, rgbKey, rgbIV); #else return _NewEncryptor(rgbKey, ModeValue, rgbIV, EffectiveKeySizeValue, @@ -80,6 +83,9 @@ namespace System.Security.Cryptography { [System.Security.SecuritySafeCritical] // auto-generated public override ICryptoTransform CreateDecryptor (byte[] rgbKey, byte[] rgbIV) { #if MONO + if (m_use40bitSalt) + throw new NotImplementedException ("UseSalt=true is not implemented on Mono yet"); + return new RC2Transform (this, false, rgbKey, rgbIV); #else return _NewEncryptor(rgbKey, ModeValue, rgbIV, EffectiveKeySizeValue, diff --git a/mcs/class/referencesource/mscorlib/system/security/cryptography/rfc2898derivebytes.cs b/mcs/class/referencesource/mscorlib/system/security/cryptography/rfc2898derivebytes.cs index 84d4a66edc..d71d881007 100644 --- a/mcs/class/referencesource/mscorlib/system/security/cryptography/rfc2898derivebytes.cs +++ b/mcs/class/referencesource/mscorlib/system/security/cryptography/rfc2898derivebytes.cs @@ -207,13 +207,15 @@ namespace System.Security.Cryptography { m_block++; return ret; } -#if !MONO [System.Security.SecuritySafeCritical] // auto-generated public byte[] CryptDeriveKey(string algname, string alghashname, int keySize, byte[] rgbIV) { if (keySize < 0) throw new CryptographicException(Environment.GetResourceString("Cryptography_InvalidKeySize")); +#if MONO + throw new NotSupportedException ("CspParameters are not supported by Mono"); +#else int algidhash = X509Utils.NameOrOidToAlgId(alghashname, OidGroup.HashAlgorithm); if (algidhash == 0) throw new CryptographicException(Environment.GetResourceString("Cryptography_PasswordDerivedBytes_InvalidAlgorithm")); @@ -231,8 +233,10 @@ namespace System.Security.Cryptography { m_password, m_password.Length, keySize << 16, rgbIV, rgbIV.Length, JitHelpers.GetObjectHandleOnStack(ref key)); return key; +#endif } +#if !MONO [System.Security.SecurityCritical] // auto-generated private SafeProvHandle _safeProvHandle = null; private SafeProvHandle ProvHandle diff --git a/mcs/class/referencesource/mscorlib/system/security/cryptography/rsacryptoserviceprovider.cs b/mcs/class/referencesource/mscorlib/system/security/cryptography/rsacryptoserviceprovider.cs index 0bf87db770..d3f4e98ade 100644 --- a/mcs/class/referencesource/mscorlib/system/security/cryptography/rsacryptoserviceprovider.cs +++ b/mcs/class/referencesource/mscorlib/system/security/cryptography/rsacryptoserviceprovider.cs @@ -37,9 +37,10 @@ namespace System.Security.Cryptography { } [System.Runtime.InteropServices.ComVisible(true)] - public sealed class RSACryptoServiceProvider : RSA + public sealed partial class RSACryptoServiceProvider : RSA , ICspAsymmetricAlgorithm { +#if !MONO private int _dwKeySize; private CspParameters _parameters; private bool _randomKeyContainer; @@ -47,13 +48,13 @@ namespace System.Security.Cryptography { private SafeProvHandle _safeProvHandle; [System.Security.SecurityCritical] // auto-generated private SafeKeyHandle _safeKeyHandle; - +#endif private static volatile CspProviderFlags s_UseMachineKeyStore = 0; // // QCalls // - +#if !MONO [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [ResourceExposure(ResourceScope.None)] @@ -194,7 +195,7 @@ namespace System.Security.Cryptography { return null; } } - +#endif public override string SignatureAlgorithm { get { return "http://www.w3.org/2000/09/xmldsig#rsa-sha1"; } } @@ -203,7 +204,7 @@ namespace System.Security.Cryptography { get { return (s_UseMachineKeyStore == CspProviderFlags.UseMachineKeyStore); } set { s_UseMachineKeyStore = (value ? CspProviderFlags.UseMachineKeyStore : 0); } } - +#if !MONO public bool PersistKeyInCsp { [System.Security.SecuritySafeCritical] // auto-generated get { @@ -502,7 +503,7 @@ namespace System.Security.Cryptography { private static bool IsPublic(RSAParameters rsaParams) { return (rsaParams.P == null); } - +#endif // // Adapt new RSA abstraction to legacy RSACryptoServiceProvider surface area. // @@ -524,10 +525,15 @@ namespace System.Security.Cryptography { Contract.Assert(count >= 0 && count <= data.Length); Contract.Assert(!String.IsNullOrEmpty(hashAlgorithm.Name)); +#if MONO + var hash = HashAlgorithm.Create (hashAlgorithm.Name); + return hash.ComputeHash (data, offset, count); +#else using (SafeHashHandle hashHandle = Utils.CreateHash(Utils.StaticProvHandle, GetAlgorithmId(hashAlgorithm))) { Utils.HashData(hashHandle, data, offset, count); return Utils.EndHash(hashHandle); } +#endif } [SecuritySafeCritical] @@ -536,6 +542,10 @@ namespace System.Security.Cryptography { Contract.Assert(data != null); Contract.Assert(!String.IsNullOrEmpty(hashAlgorithm.Name)); +#if MONO + var hash = HashAlgorithm.Create (hashAlgorithm.Name); + return hash.ComputeHash (data); +#else using (SafeHashHandle hashHandle = Utils.CreateHash(Utils.StaticProvHandle, GetAlgorithmId(hashAlgorithm))) { // Read the data 4KB at a time, providing similar read characteristics to a standard HashAlgorithm byte[] buffer = new byte[4096]; @@ -549,6 +559,7 @@ namespace System.Security.Cryptography { return Utils.EndHash(hashHandle); } +#endif } private static int GetAlgorithmId(HashAlgorithmName hashAlgorithm) { diff --git a/mcs/class/referencesource/mscorlib/system/security/cryptography/rsaoaepkeyexchangedeformatter.cs b/mcs/class/referencesource/mscorlib/system/security/cryptography/rsaoaepkeyexchangedeformatter.cs index 416b29f507..674cdf23f6 100644 --- a/mcs/class/referencesource/mscorlib/system/security/cryptography/rsaoaepkeyexchangedeformatter.cs +++ b/mcs/class/referencesource/mscorlib/system/security/cryptography/rsaoaepkeyexchangedeformatter.cs @@ -11,6 +11,7 @@ namespace System.Security.Cryptography { [System.Runtime.InteropServices.ComVisible(true)] public class RSAOAEPKeyExchangeDeformatter : AsymmetricKeyExchangeDeformatter { private RSA _rsaKey; // RSA Key value to do decrypt operation + private bool? _rsaOverridesDecrypt; // // public constructors @@ -42,8 +43,8 @@ namespace System.Security.Cryptography { if (_rsaKey == null) throw new CryptographicUnexpectedOperationException(Environment.GetResourceString("Cryptography_MissingKey")); - if (_rsaKey is RSACryptoServiceProvider) { - return ((RSACryptoServiceProvider) _rsaKey).Decrypt(rgbData, true); + if (OverridesDecrypt) { + return _rsaKey.Decrypt(rgbData, RSAEncryptionPadding.OaepSHA1); } else { return Utils.RsaOaepDecrypt(_rsaKey, SHA1.Create(), new PKCS1MaskGenerationMethod(), rgbData); } @@ -54,6 +55,16 @@ namespace System.Security.Cryptography { throw new ArgumentNullException("key"); Contract.EndContractBlock(); _rsaKey = (RSA) key; + _rsaOverridesDecrypt = default(bool?); + } + + private bool OverridesDecrypt { + get { + if (!_rsaOverridesDecrypt.HasValue) { + _rsaOverridesDecrypt = Utils.DoesRsaKeyOverride(_rsaKey, "Decrypt", new Type[] { typeof(byte[]), typeof(RSAEncryptionPadding) }); + } + return _rsaOverridesDecrypt.Value; + } } } } diff --git a/mcs/class/referencesource/mscorlib/system/security/cryptography/rsaoaepkeyexchangeformatter.cs b/mcs/class/referencesource/mscorlib/system/security/cryptography/rsaoaepkeyexchangeformatter.cs index 68746fe177..a931c154cd 100644 --- a/mcs/class/referencesource/mscorlib/system/security/cryptography/rsaoaepkeyexchangeformatter.cs +++ b/mcs/class/referencesource/mscorlib/system/security/cryptography/rsaoaepkeyexchangeformatter.cs @@ -12,6 +12,7 @@ namespace System.Security.Cryptography { public class RSAOAEPKeyExchangeFormatter : AsymmetricKeyExchangeFormatter { private byte[] ParameterValue; private RSA _rsaKey; + private bool? _rsaOverridesEncrypt; private RandomNumberGenerator RngValue; // @@ -64,6 +65,7 @@ namespace System.Security.Cryptography { throw new ArgumentNullException("key"); Contract.EndContractBlock(); _rsaKey = (RSA) key; + _rsaOverridesEncrypt = default(bool?); } [System.Security.SecuritySafeCritical] // auto-generated @@ -71,8 +73,8 @@ namespace System.Security.Cryptography { if (_rsaKey == null) throw new CryptographicUnexpectedOperationException(Environment.GetResourceString("Cryptography_MissingKey")); - if (_rsaKey is RSACryptoServiceProvider) { - return ((RSACryptoServiceProvider) _rsaKey).Encrypt(rgbData, true); + if (OverridesEncrypt) { + return _rsaKey.Encrypt(rgbData, RSAEncryptionPadding.OaepSHA1); } else { return Utils.RsaOaepEncrypt(_rsaKey, SHA1.Create(), new PKCS1MaskGenerationMethod(), RandomNumberGenerator.Create(), rgbData); } @@ -81,5 +83,14 @@ namespace System.Security.Cryptography { public override byte[] CreateKeyExchange(byte[] rgbData, Type symAlgType) { return CreateKeyExchange(rgbData); } + + private bool OverridesEncrypt { + get { + if (!_rsaOverridesEncrypt.HasValue) { + _rsaOverridesEncrypt = Utils.DoesRsaKeyOverride(_rsaKey, "Encrypt", new Type[] { typeof(byte[]), typeof(RSAEncryptionPadding) }); + } + return _rsaOverridesEncrypt.Value; + } + } } } diff --git a/mcs/class/referencesource/mscorlib/system/security/cryptography/rsapkcs1keyexchangedeformatter.cs b/mcs/class/referencesource/mscorlib/system/security/cryptography/rsapkcs1keyexchangedeformatter.cs index ed412c64db..ccd8570ada 100644 --- a/mcs/class/referencesource/mscorlib/system/security/cryptography/rsapkcs1keyexchangedeformatter.cs +++ b/mcs/class/referencesource/mscorlib/system/security/cryptography/rsapkcs1keyexchangedeformatter.cs @@ -11,6 +11,7 @@ namespace System.Security.Cryptography { [System.Runtime.InteropServices.ComVisible(true)] public class RSAPKCS1KeyExchangeDeformatter : AsymmetricKeyExchangeDeformatter { RSA _rsaKey; + bool? _rsaOverridesDecrypt; RandomNumberGenerator RngValue; // Constructors @@ -47,8 +48,8 @@ namespace System.Security.Cryptography { throw new CryptographicUnexpectedOperationException(Environment.GetResourceString("Cryptography_MissingKey")); byte[] rgbOut; - if (_rsaKey is RSACryptoServiceProvider) { - rgbOut = ((RSACryptoServiceProvider) _rsaKey).Decrypt(rgbIn, false); + if (OverridesDecrypt) { + rgbOut = _rsaKey.Decrypt(rgbIn, RSAEncryptionPadding.Pkcs1); } else { int i; @@ -83,6 +84,16 @@ namespace System.Security.Cryptography { throw new ArgumentNullException("key"); Contract.EndContractBlock(); _rsaKey = (RSA) key; + _rsaOverridesDecrypt = default(bool?); + } + + private bool OverridesDecrypt { + get { + if (!_rsaOverridesDecrypt.HasValue) { + _rsaOverridesDecrypt = Utils.DoesRsaKeyOverride(_rsaKey, "Decrypt", new Type[] { typeof(byte[]), typeof(RSAEncryptionPadding) }); + } + return _rsaOverridesDecrypt.Value; + } } } } diff --git a/mcs/class/referencesource/mscorlib/system/security/cryptography/rsapkcs1keyexchangeformatter.cs b/mcs/class/referencesource/mscorlib/system/security/cryptography/rsapkcs1keyexchangeformatter.cs index 19f34b6d6f..188e55ce1c 100644 --- a/mcs/class/referencesource/mscorlib/system/security/cryptography/rsapkcs1keyexchangeformatter.cs +++ b/mcs/class/referencesource/mscorlib/system/security/cryptography/rsapkcs1keyexchangeformatter.cs @@ -14,6 +14,7 @@ namespace System.Security.Cryptography { public class RSAPKCS1KeyExchangeFormatter : AsymmetricKeyExchangeFormatter { RandomNumberGenerator RngValue; RSA _rsaKey; + bool? _rsaOverridesEncrypt; // // public constructors @@ -50,6 +51,7 @@ namespace System.Security.Cryptography { throw new ArgumentNullException("key"); Contract.EndContractBlock(); _rsaKey = (RSA) key; + _rsaOverridesEncrypt = default(bool?); } public override byte[] CreateKeyExchange(byte[] rgbData) { @@ -62,8 +64,8 @@ namespace System.Security.Cryptography { throw new CryptographicUnexpectedOperationException(Environment.GetResourceString("Cryptography_MissingKey")); byte[] rgbKeyEx; - if (_rsaKey is RSACryptoServiceProvider) { - rgbKeyEx = ((RSACryptoServiceProvider) _rsaKey).Encrypt(rgbData, false); + if (OverridesEncrypt) { + rgbKeyEx = _rsaKey.Encrypt(rgbData, RSAEncryptionPadding.Pkcs1); } else { int cb = _rsaKey.KeySize/8; @@ -101,5 +103,14 @@ namespace System.Security.Cryptography { public override byte[] CreateKeyExchange(byte[] rgbData, Type symAlgType) { return CreateKeyExchange(rgbData); } + + private bool OverridesEncrypt { + get { + if (!_rsaOverridesEncrypt.HasValue) { + _rsaOverridesEncrypt = Utils.DoesRsaKeyOverride(_rsaKey, "Encrypt", new Type[] { typeof(byte[]), typeof(RSAEncryptionPadding) }); + } + return _rsaOverridesEncrypt.Value; + } + } } } diff --git a/mcs/class/referencesource/mscorlib/system/security/cryptography/rsapkcs1signaturedeformatter.cs b/mcs/class/referencesource/mscorlib/system/security/cryptography/rsapkcs1signaturedeformatter.cs index 01363fefbd..28ee873863 100644 --- a/mcs/class/referencesource/mscorlib/system/security/cryptography/rsapkcs1signaturedeformatter.cs +++ b/mcs/class/referencesource/mscorlib/system/security/cryptography/rsapkcs1signaturedeformatter.cs @@ -27,6 +27,7 @@ namespace System.Security.Cryptography { private RSA _rsaKey; // RSA Key value to do decrypt operation private String _strOID; // OID value for the HASH algorithm + private bool? _rsaOverridesVerifyHash; // // public constructors @@ -49,6 +50,7 @@ namespace System.Security.Cryptography { throw new ArgumentNullException("key"); Contract.EndContractBlock(); _rsaKey = (RSA) key; + _rsaOverridesVerifyHash = default(bool?); } public override void SetHashAlgorithm(String strName) { @@ -70,15 +72,32 @@ namespace System.Security.Cryptography { // Two cases here -- if we are talking to the CSP version or if we are talking to some other RSA provider. if (_rsaKey is RSACryptoServiceProvider) { + // This path is kept around for desktop compat: in case someone is using this with a hash algorithm that's known to GetAlgIdFromOid but + // not from OidToHashAlgorithmName. int calgHash = X509Utils.GetAlgIdFromOid(_strOID, OidGroup.HashAlgorithm); return ((RSACryptoServiceProvider)_rsaKey).VerifyHash(rgbHash, calgHash, rgbSignature); } + else if (OverridesVerifyHash) { + HashAlgorithmName hashAlgorithmName = Utils.OidToHashAlgorithmName(_strOID); + return _rsaKey.VerifyHash(rgbHash, rgbSignature, hashAlgorithmName, RSASignaturePadding.Pkcs1); + } else { + // Fallback compat path for 3rd-party RSA classes that don't override VerifyHash() + byte[] pad = Utils.RsaPkcs1Padding(_rsaKey, CryptoConfig.EncodeOID(_strOID), rgbHash); // Apply the public key to the signature data to get back the padded buffer actually signed. // Compare the two buffers to see if they match; ignoring any leading zeros return Utils.CompareBigIntArrays(_rsaKey.EncryptValue(rgbSignature), pad); } } + + private bool OverridesVerifyHash { + get { + if (!_rsaOverridesVerifyHash.HasValue) { + _rsaOverridesVerifyHash = Utils.DoesRsaKeyOverride(_rsaKey, "VerifyHash", new Type[] { typeof(byte[]), typeof(byte[]), typeof(HashAlgorithmName), typeof(RSASignaturePadding) }); + } + return _rsaOverridesVerifyHash.Value; + } + } } } diff --git a/mcs/class/referencesource/mscorlib/system/security/cryptography/rsapkcs1signatureformatter.cs b/mcs/class/referencesource/mscorlib/system/security/cryptography/rsapkcs1signatureformatter.cs index 249ea4b072..9791242561 100644 --- a/mcs/class/referencesource/mscorlib/system/security/cryptography/rsapkcs1signatureformatter.cs +++ b/mcs/class/referencesource/mscorlib/system/security/cryptography/rsapkcs1signatureformatter.cs @@ -19,6 +19,7 @@ namespace System.Security.Cryptography { public class RSAPKCS1SignatureFormatter : AsymmetricSignatureFormatter { private RSA _rsaKey; private String _strOID; + private bool? _rsaOverridesSignHash; // // public constructors @@ -42,6 +43,7 @@ namespace System.Security.Cryptography { throw new ArgumentNullException("key"); Contract.EndContractBlock(); _rsaKey = (RSA) key; + _rsaOverridesSignHash = default(bool?); } public override void SetHashAlgorithm(String strName) { @@ -61,14 +63,31 @@ namespace System.Security.Cryptography { // Two cases here -- if we are talking to the CSP version or if we are talking to some other RSA provider. if (_rsaKey is RSACryptoServiceProvider) { + // This path is kept around for desktop compat: in case someone is using this with a hash algorithm that's known to GetAlgIdFromOid but + // not from OidToHashAlgorithmName. int calgHash = X509Utils.GetAlgIdFromOid(_strOID, OidGroup.HashAlgorithm); return ((RSACryptoServiceProvider)_rsaKey).SignHash(rgbHash, calgHash); } + else if (OverridesSignHash) { + HashAlgorithmName hashAlgorithmName = Utils.OidToHashAlgorithmName(_strOID); + return _rsaKey.SignHash(rgbHash, hashAlgorithmName, RSASignaturePadding.Pkcs1); + } else { + // Fallback compat path for 3rd-party RSA classes that don't override SignHash() + byte[] pad = Utils.RsaPkcs1Padding(_rsaKey, CryptoConfig.EncodeOID(_strOID), rgbHash); // Create the signature by applying the private key to the padded buffer we just created. return _rsaKey.DecryptValue(pad); } } + + private bool OverridesSignHash { + get { + if (!_rsaOverridesSignHash.HasValue) { + _rsaOverridesSignHash = Utils.DoesRsaKeyOverride(_rsaKey, "SignHash", new Type[] { typeof(byte[]), typeof(HashAlgorithmName), typeof(RSASignaturePadding) }); + } + return _rsaOverridesSignHash.Value; + } + } } } diff --git a/mcs/class/referencesource/mscorlib/system/security/cryptography/signaturedescription.cs b/mcs/class/referencesource/mscorlib/system/security/cryptography/signaturedescription.cs index f115e8afc3..330a0222f0 100644 --- a/mcs/class/referencesource/mscorlib/system/security/cryptography/signaturedescription.cs +++ b/mcs/class/referencesource/mscorlib/system/security/cryptography/signaturedescription.cs @@ -83,20 +83,52 @@ namespace System.Security.Cryptography { } } - internal class RSAPKCS1SHA1SignatureDescription : SignatureDescription { - public RSAPKCS1SHA1SignatureDescription() { - KeyAlgorithm = "System.Security.Cryptography.RSACryptoServiceProvider"; - DigestAlgorithm = "System.Security.Cryptography.SHA1CryptoServiceProvider"; + internal abstract class RSAPKCS1SignatureDescription : SignatureDescription { + protected RSAPKCS1SignatureDescription(string hashAlgorithm, string digestAlgorithm) { + KeyAlgorithm = "System.Security.Cryptography.RSA"; + DigestAlgorithm = digestAlgorithm; FormatterAlgorithm = "System.Security.Cryptography.RSAPKCS1SignatureFormatter"; DeformatterAlgorithm = "System.Security.Cryptography.RSAPKCS1SignatureDeformatter"; + _hashAlgorithm = hashAlgorithm; + } + + public sealed override AsymmetricSignatureDeformatter CreateDeformatter(AsymmetricAlgorithm key) { + AsymmetricSignatureDeformatter item = base.CreateDeformatter(key); + item.SetHashAlgorithm(_hashAlgorithm); + return item; } - public override AsymmetricSignatureDeformatter CreateDeformatter(AsymmetricAlgorithm key) { - AsymmetricSignatureDeformatter item = (AsymmetricSignatureDeformatter) CryptoConfig.CreateFromName(DeformatterAlgorithm); - item.SetKey(key); - item.SetHashAlgorithm("SHA1"); + public sealed override AsymmetricSignatureFormatter CreateFormatter(AsymmetricAlgorithm key) { + AsymmetricSignatureFormatter item = base.CreateFormatter(key); + item.SetHashAlgorithm(_hashAlgorithm); return item; } + + private string _hashAlgorithm; + } + + internal class RSAPKCS1SHA1SignatureDescription : RSAPKCS1SignatureDescription { + public RSAPKCS1SHA1SignatureDescription() + : base("SHA1", "System.Security.Cryptography.SHA1Cng") { + } + } + + internal class RSAPKCS1SHA256SignatureDescription : RSAPKCS1SignatureDescription { + public RSAPKCS1SHA256SignatureDescription() + : base("SHA256", "System.Security.Cryptography.SHA256Cng") { + } + } + + internal class RSAPKCS1SHA384SignatureDescription : RSAPKCS1SignatureDescription { + public RSAPKCS1SHA384SignatureDescription() + : base("SHA384", "System.Security.Cryptography.SHA384Cng") { + } + } + + internal class RSAPKCS1SHA512SignatureDescription : RSAPKCS1SignatureDescription { + public RSAPKCS1SHA512SignatureDescription() + : base("SHA512", "System.Security.Cryptography.SHA512Cng") { + } } internal class DSASignatureDescription : SignatureDescription { diff --git a/mcs/class/referencesource/mscorlib/system/security/cryptography/utils.cs b/mcs/class/referencesource/mscorlib/system/security/cryptography/utils.cs index e8a95fc3be..cc08a62a05 100644 --- a/mcs/class/referencesource/mscorlib/system/security/cryptography/utils.cs +++ b/mcs/class/referencesource/mscorlib/system/security/cryptography/utils.cs @@ -16,6 +16,7 @@ namespace System.Security.Cryptography { using Microsoft.Win32; using System.IO; + using System.Reflection; using System.Globalization; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -1017,7 +1018,74 @@ namespace System.Security.Cryptography [ResourceExposure(ResourceScope.None)] // Creates a process resource, but it can't be scoped. [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity] internal static extern SafeHashHandle CreateHash(SafeProvHandle hProv, int algid); +#endif + internal static HashAlgorithmName OidToHashAlgorithmName(string oid) + { + switch (oid) + { + case Constants.OID_OIWSEC_SHA1: + return HashAlgorithmName.SHA1; + case Constants.OID_OIWSEC_SHA256: + return HashAlgorithmName.SHA256; + + case Constants.OID_OIWSEC_SHA384: + return HashAlgorithmName.SHA384; + + case Constants.OID_OIWSEC_SHA512: + return HashAlgorithmName.SHA512; + + default: + throw new NotSupportedException(); + } + } + + // + // Backward-compat hack for third-party RSA-derived classes: + // + // Because the SignHash()/VerifyHash()/Encrypt()/Decrypt() methods are new on RSA, we may + // encounter older third-party RSA-derived classes that don't override them + // (and if they don't override them, these methods will throw since they are effectively abstract methods that had to declared non-abstract + // for backward compat reasons.) + // + internal static bool DoesRsaKeyOverride(RSA rsaKey, string methodName, Type[] parameterTypes) + { + // A fast-path check for the common cases where we know we implemented the overrides. + Type t = rsaKey.GetType(); + if (rsaKey is RSACryptoServiceProvider) + { +#if DEBUG + // On checked builds, do the slow-path check anyway so it gets exercised. + bool foundOverride = DoesRsaKeyOverrideSlowPath(t, methodName, parameterTypes); + BCLDebug.Assert(foundOverride, "RSACryptoServiceProvider expected to override " + methodName); +#endif + return true; + } + + string fullName = t.FullName; + if (fullName == "System.Security.Cryptography.RSACng") + { +#if DEBUG + // On checked builds, do the slow-path check anyway so it gets exercised. + bool foundOverride = DoesRsaKeyOverrideSlowPath(t, methodName, parameterTypes); + BCLDebug.Assert(foundOverride, "RSACng expected to override " + methodName); +#endif + return true; + } + return DoesRsaKeyOverrideSlowPath(t, methodName, parameterTypes); + } + + private static bool DoesRsaKeyOverrideSlowPath(Type t, string methodName, Type[] parameterTypes) + { + MethodInfo method = t.GetMethod(methodName, BindingFlags.Public | BindingFlags.Instance, null, parameterTypes, null); + BCLDebug.Assert(method != null, "method != null"); + Type declaringType = method.DeclaringType; + if (declaringType == typeof(RSA)) + return false; + + return true; + } +#if !MONO [System.Security.SecurityCritical] // auto-generated [ResourceExposure(ResourceScope.None)] [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity] diff --git a/mcs/class/referencesource/mscorlib/system/security/cryptography/x509certificates/x509utils.cs b/mcs/class/referencesource/mscorlib/system/security/cryptography/x509certificates/x509utils.cs index 23f747c042..e730084e19 100644 --- a/mcs/class/referencesource/mscorlib/system/security/cryptography/x509certificates/x509utils.cs +++ b/mcs/class/referencesource/mscorlib/system/security/cryptography/x509certificates/x509utils.cs @@ -159,7 +159,7 @@ namespace System.Security.Cryptography.X509Certificates if (group != OidGroup.AllGroups) { IntPtr allGroupOidInfo = CryptFindOIDInfo(keyType, rawKey, OidGroup.AllGroups); if (allGroupOidInfo != IntPtr.Zero) { - return (CRYPT_OID_INFO)Marshal.PtrToStructure(fullOidInfo, typeof(CRYPT_OID_INFO)); + return (CRYPT_OID_INFO)Marshal.PtrToStructure(allGroupOidInfo, typeof(CRYPT_OID_INFO)); } } diff --git a/mcs/class/referencesource/mscorlib/system/security/permissions/fileiopermission.cs b/mcs/class/referencesource/mscorlib/system/security/permissions/fileiopermission.cs index 02ef088b5e..db35ac502b 100644 --- a/mcs/class/referencesource/mscorlib/system/security/permissions/fileiopermission.cs +++ b/mcs/class/referencesource/mscorlib/system/security/permissions/fileiopermission.cs @@ -24,9 +24,9 @@ namespace System.Security.Permissions { using System.Runtime.Versioning; using System.Diagnostics.Contracts; -[Serializable] + [Serializable] [Flags] -[System.Runtime.InteropServices.ComVisible(true)] + [System.Runtime.InteropServices.ComVisible(true)] public enum FileIOPermissionAccess { NoAccess = 0x00, @@ -36,9 +36,8 @@ namespace System.Security.Permissions { PathDiscovery = 0x08, AllAccess = 0x0F, } - - -[System.Runtime.InteropServices.ComVisible(true)] + + [System.Runtime.InteropServices.ComVisible(true)] [Serializable] sealed public class FileIOPermission : CodeAccessPermission, IUnrestrictedPermission, IBuiltInPermission { @@ -51,7 +50,7 @@ namespace System.Security.Permissions { [OptionalField(VersionAdded = 2)] private FileIOAccess m_changeAcl; private bool m_unrestricted; - + public FileIOPermission(PermissionState state) { if (state == PermissionState.Unrestricted) @@ -67,91 +66,91 @@ namespace System.Security.Permissions { throw new ArgumentException(Environment.GetResourceString("Argument_InvalidPermissionState")); } } - + [System.Security.SecuritySafeCritical] // auto-generated - public FileIOPermission( FileIOPermissionAccess access, String path ) + public FileIOPermission(FileIOPermissionAccess access, String path) { - VerifyAccess( access ); - + VerifyAccess(access); + String[] pathList = new String[] { path }; - AddPathList( access, pathList, false, true, false ); + AddPathList(access, pathList, false, true, false); } - + [System.Security.SecuritySafeCritical] // auto-generated - public FileIOPermission( FileIOPermissionAccess access, String[] pathList ) + public FileIOPermission(FileIOPermissionAccess access, String[] pathList) { - VerifyAccess( access ); - - AddPathList( access, pathList, false, true, false ); + VerifyAccess(access); + + AddPathList(access, pathList, false, true, false); } #if FEATURE_MACL [System.Security.SecuritySafeCritical] // auto-generated - public FileIOPermission( FileIOPermissionAccess access, AccessControlActions control, String path ) + public FileIOPermission(FileIOPermissionAccess access, AccessControlActions control, String path) { - VerifyAccess( access ); - + VerifyAccess(access); + String[] pathList = new String[] { path }; - AddPathList( access, control, pathList, false, true, false ); + AddPathList(access, control, pathList, false, true, false); } - + [System.Security.SecuritySafeCritical] // auto-generated - public FileIOPermission( FileIOPermissionAccess access, AccessControlActions control, String[] pathList ) - : this( access, control, pathList, true, true ) + public FileIOPermission(FileIOPermissionAccess access, AccessControlActions control, String[] pathList) + : this(access, control, pathList, true, true) { } #endif [System.Security.SecurityCritical] // auto-generated - internal FileIOPermission( FileIOPermissionAccess access, String[] pathList, bool checkForDuplicates, bool needFullPath ) + internal FileIOPermission(FileIOPermissionAccess access, String[] pathList, bool checkForDuplicates, bool needFullPath) { - VerifyAccess( access ); - - AddPathList( access, pathList, checkForDuplicates, needFullPath, true ); + VerifyAccess(access); + + AddPathList(access, pathList, checkForDuplicates, needFullPath, true); } #if FEATURE_MACL [System.Security.SecurityCritical] // auto-generated - internal FileIOPermission( FileIOPermissionAccess access, AccessControlActions control, String[] pathList, bool checkForDuplicates, bool needFullPath ) + internal FileIOPermission(FileIOPermissionAccess access, AccessControlActions control, String[] pathList, bool checkForDuplicates, bool needFullPath) { - VerifyAccess( access ); - - AddPathList( access, control, pathList, checkForDuplicates, needFullPath, true ); + VerifyAccess(access); + + AddPathList(access, control, pathList, checkForDuplicates, needFullPath, true); } #endif - public void SetPathList( FileIOPermissionAccess access, String path ) + public void SetPathList(FileIOPermissionAccess access, String path) { String[] pathList; - if(path == null) - pathList = new String[] {}; + if (path == null) + pathList = new String[] { }; else pathList = new String[] { path }; - SetPathList( access, pathList, false ); - } - - public void SetPathList( FileIOPermissionAccess access, String[] pathList ) - { - SetPathList( access, pathList, true ); + SetPathList(access, pathList, false); } - internal void SetPathList( FileIOPermissionAccess access, - String[] pathList, bool checkForDuplicates ) + public void SetPathList(FileIOPermissionAccess access, String[] pathList) { - SetPathList( access, AccessControlActions.None, pathList, checkForDuplicates ); + SetPathList(access, pathList, true); + } + + internal void SetPathList(FileIOPermissionAccess access, + String[] pathList, bool checkForDuplicates) + { + SetPathList(access, AccessControlActions.None, pathList, checkForDuplicates); } [System.Security.SecuritySafeCritical] // auto-generated - internal void SetPathList( FileIOPermissionAccess access, AccessControlActions control, String[] pathList, bool checkForDuplicates ) + internal void SetPathList(FileIOPermissionAccess access, AccessControlActions control, String[] pathList, bool checkForDuplicates) { - VerifyAccess( access ); - + VerifyAccess(access); + if ((access & FileIOPermissionAccess.Read) != 0) m_read = null; - + if ((access & FileIOPermissionAccess.Write) != 0) m_write = null; - + if ((access & FileIOPermissionAccess.Append) != 0) m_append = null; @@ -168,36 +167,36 @@ namespace System.Security.Permissions { m_viewAcl = null; m_changeAcl = null; #endif - + m_unrestricted = false; #if FEATURE_MACL - AddPathList( access, control, pathList, checkForDuplicates, true, true ); + AddPathList(access, control, pathList, checkForDuplicates, true, true); #else AddPathList( access, pathList, checkForDuplicates, true, true ); #endif } [System.Security.SecuritySafeCritical] // auto-generated - public void AddPathList( FileIOPermissionAccess access, String path ) + public void AddPathList(FileIOPermissionAccess access, String path) { String[] pathList; - if(path == null) - pathList = new String[] {}; + if (path == null) + pathList = new String[] { }; else pathList = new String[] { path }; - AddPathList( access, pathList, false, true, false ); + AddPathList(access, pathList, false, true, false); } [System.Security.SecuritySafeCritical] // auto-generated - public void AddPathList( FileIOPermissionAccess access, String[] pathList ) + public void AddPathList(FileIOPermissionAccess access, String[] pathList) { - AddPathList( access, pathList, true, true, true ); + AddPathList(access, pathList, true, true, true); } [System.Security.SecurityCritical] // auto-generated - internal void AddPathList( FileIOPermissionAccess access, String[] pathListOrig, bool checkForDuplicates, bool needFullPath, bool copyPathList ) + internal void AddPathList(FileIOPermissionAccess access, String[] pathListOrig, bool checkForDuplicates, bool needFullPath, bool copyPathList) { - AddPathList( access, AccessControlActions.None, pathListOrig, checkForDuplicates, needFullPath, copyPathList ); + AddPathList(access, AccessControlActions.None, pathListOrig, checkForDuplicates, needFullPath, copyPathList); } [System.Security.SecurityCritical] // auto-generated @@ -205,65 +204,73 @@ namespace System.Security.Permissions { { if (pathListOrig == null) { - throw new ArgumentNullException( "pathList" ); + throw new ArgumentNullException("pathList"); } if (pathListOrig.Length == 0) { - throw new ArgumentException( Environment.GetResourceString("Argument_EmptyPath" )); + throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath")); } Contract.EndContractBlock(); // @ VerifyAccess(access); - + if (m_unrestricted) return; String[] pathList = pathListOrig; - if(copyPathList) + if (copyPathList) { // Make a copy of pathList (in case its value changes after we check for illegal chars) pathList = new String[pathListOrig.Length]; Array.Copy(pathListOrig, pathList, pathListOrig.Length); } - CheckIllegalCharacters( pathList ); + // If we need the full path the standard illegal characters will be checked in StringExpressionSet. + CheckIllegalCharacters(pathList, onlyCheckExtras: needFullPath); + + // StringExpressionSet will do minor normalization, trimming spaces and replacing alternate + // directory separators. It will make an attemt to expand short file names and will check + // for standard colon placement. + // + // If needFullPath is true it will call NormalizePath- which performs short name expansion + // and does the normal validity checks. ArrayList pathArrayList = StringExpressionSet.CreateListFromExpressions(pathList, needFullPath); - + if ((access & FileIOPermissionAccess.Read) != 0) { if (m_read == null) { m_read = new FileIOAccess(); } - m_read.AddExpressions( pathArrayList, checkForDuplicates); + m_read.AddExpressions(pathArrayList, checkForDuplicates); } - + if ((access & FileIOPermissionAccess.Write) != 0) { if (m_write == null) { m_write = new FileIOAccess(); } - m_write.AddExpressions( pathArrayList, checkForDuplicates); + m_write.AddExpressions(pathArrayList, checkForDuplicates); } - + if ((access & FileIOPermissionAccess.Append) != 0) { if (m_append == null) { m_append = new FileIOAccess(); } - m_append.AddExpressions( pathArrayList, checkForDuplicates); + m_append.AddExpressions(pathArrayList, checkForDuplicates); } if ((access & FileIOPermissionAccess.PathDiscovery) != 0) { if (m_pathDiscovery == null) { - m_pathDiscovery = new FileIOAccess( true ); + m_pathDiscovery = new FileIOAccess(true); } - m_pathDiscovery.AddExpressions( pathArrayList, checkForDuplicates); + m_pathDiscovery.AddExpressions(pathArrayList, checkForDuplicates); } #if FEATURE_MACL @@ -273,7 +280,7 @@ namespace System.Security.Permissions { { m_viewAcl = new FileIOAccess(); } - m_viewAcl.AddExpressions( pathArrayList, checkForDuplicates); + m_viewAcl.AddExpressions(pathArrayList, checkForDuplicates); } if ((control & AccessControlActions.Change) != 0) @@ -282,18 +289,18 @@ namespace System.Security.Permissions { { m_changeAcl = new FileIOAccess(); } - m_changeAcl.AddExpressions( pathArrayList, checkForDuplicates); + m_changeAcl.AddExpressions(pathArrayList, checkForDuplicates); } #endif } - + [SecuritySafeCritical] - public String[] GetPathList( FileIOPermissionAccess access ) + public String[] GetPathList(FileIOPermissionAccess access) { - VerifyAccess( access ); - ExclusiveAccess( access ); - - if (AccessIsSet( access, FileIOPermissionAccess.Read )) + VerifyAccess(access); + ExclusiveAccess(access); + + if (AccessIsSet(access, FileIOPermissionAccess.Read)) { if (m_read == null) { @@ -301,8 +308,8 @@ namespace System.Security.Permissions { } return m_read.ToStringArray(); } - - if (AccessIsSet( access, FileIOPermissionAccess.Write )) + + if (AccessIsSet(access, FileIOPermissionAccess.Write)) { if (m_write == null) { @@ -310,8 +317,8 @@ namespace System.Security.Permissions { } return m_write.ToStringArray(); } - - if (AccessIsSet( access, FileIOPermissionAccess.Append )) + + if (AccessIsSet(access, FileIOPermissionAccess.Append)) { if (m_append == null) { @@ -319,8 +326,8 @@ namespace System.Security.Permissions { } return m_append.ToStringArray(); } - - if (AccessIsSet( access, FileIOPermissionAccess.PathDiscovery )) + + if (AccessIsSet(access, FileIOPermissionAccess.PathDiscovery)) { if (m_pathDiscovery == null) { @@ -330,10 +337,10 @@ namespace System.Security.Permissions { } // not reached - + return null; } - + public FileIOPermissionAccess AllLocalFiles { @@ -341,19 +348,19 @@ namespace System.Security.Permissions { { if (m_unrestricted) return FileIOPermissionAccess.AllAccess; - + FileIOPermissionAccess access = FileIOPermissionAccess.NoAccess; - + if (m_read != null && m_read.AllLocalFiles) { access |= FileIOPermissionAccess.Read; } - + if (m_write != null && m_write.AllLocalFiles) { access |= FileIOPermissionAccess.Write; } - + if (m_append != null && m_append.AllLocalFiles) { access |= FileIOPermissionAccess.Append; @@ -363,17 +370,17 @@ namespace System.Security.Permissions { { access |= FileIOPermissionAccess.PathDiscovery; } - + return access; } - + set { if ((value & FileIOPermissionAccess.Read) != 0) { if (m_read == null) m_read = new FileIOAccess(); - + m_read.AllLocalFiles = true; } else @@ -381,12 +388,12 @@ namespace System.Security.Permissions { if (m_read != null) m_read.AllLocalFiles = false; } - + if ((value & FileIOPermissionAccess.Write) != 0) { if (m_write == null) m_write = new FileIOAccess(); - + m_write.AllLocalFiles = true; } else @@ -394,12 +401,12 @@ namespace System.Security.Permissions { if (m_write != null) m_write.AllLocalFiles = false; } - + if ((value & FileIOPermissionAccess.Append) != 0) { if (m_append == null) m_append = new FileIOAccess(); - + m_append.AllLocalFiles = true; } else @@ -411,8 +418,8 @@ namespace System.Security.Permissions { if ((value & FileIOPermissionAccess.PathDiscovery) != 0) { if (m_pathDiscovery == null) - m_pathDiscovery = new FileIOAccess( true ); - + m_pathDiscovery = new FileIOAccess(true); + m_pathDiscovery.AllLocalFiles = true; } else @@ -423,31 +430,31 @@ namespace System.Security.Permissions { } } - + public FileIOPermissionAccess AllFiles { get { if (m_unrestricted) return FileIOPermissionAccess.AllAccess; - + FileIOPermissionAccess access = FileIOPermissionAccess.NoAccess; - + if (m_read != null && m_read.AllFiles) { access |= FileIOPermissionAccess.Read; } - + if (m_write != null && m_write.AllFiles) { access |= FileIOPermissionAccess.Write; } - + if (m_append != null && m_append.AllFiles) { access |= FileIOPermissionAccess.Append; } - + if (m_pathDiscovery != null && m_pathDiscovery.AllFiles) { access |= FileIOPermissionAccess.PathDiscovery; @@ -455,7 +462,7 @@ namespace System.Security.Permissions { return access; } - + set { if (value == FileIOPermissionAccess.AllAccess) @@ -463,12 +470,12 @@ namespace System.Security.Permissions { m_unrestricted = true; return; } - + if ((value & FileIOPermissionAccess.Read) != 0) { if (m_read == null) m_read = new FileIOAccess(); - + m_read.AllFiles = true; } else @@ -476,12 +483,12 @@ namespace System.Security.Permissions { if (m_read != null) m_read.AllFiles = false; } - + if ((value & FileIOPermissionAccess.Write) != 0) { if (m_write == null) m_write = new FileIOAccess(); - + m_write.AllFiles = true; } else @@ -489,12 +496,12 @@ namespace System.Security.Permissions { if (m_write != null) m_write.AllFiles = false; } - + if ((value & FileIOPermissionAccess.Append) != 0) { if (m_append == null) m_append = new FileIOAccess(); - + m_append.AllFiles = true; } else @@ -506,8 +513,8 @@ namespace System.Security.Permissions { if ((value & FileIOPermissionAccess.PathDiscovery) != 0) { if (m_pathDiscovery == null) - m_pathDiscovery = new FileIOAccess( true ); - + m_pathDiscovery = new FileIOAccess(true); + m_pathDiscovery.AllFiles = true; } else @@ -517,42 +524,70 @@ namespace System.Security.Permissions { } } - } - + } + [Pure] - private static void VerifyAccess( FileIOPermissionAccess access ) + private static void VerifyAccess(FileIOPermissionAccess access) { if ((access & ~FileIOPermissionAccess.AllAccess) != 0) throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)access)); } - + [Pure] - private static void ExclusiveAccess( FileIOPermissionAccess access ) + private static void ExclusiveAccess(FileIOPermissionAccess access) { if (access == FileIOPermissionAccess.NoAccess) { - throw new ArgumentException( Environment.GetResourceString("Arg_EnumNotSingleFlag") ); + throw new ArgumentException(Environment.GetResourceString("Arg_EnumNotSingleFlag")); } - - if (((int) access & ((int)access-1)) != 0) + + if (((int)access & ((int)access - 1)) != 0) { - throw new ArgumentException( Environment.GetResourceString("Arg_EnumNotSingleFlag") ); + throw new ArgumentException(Environment.GetResourceString("Arg_EnumNotSingleFlag")); } } - private static void CheckIllegalCharacters( String[] str ) + private static void CheckIllegalCharacters(String[] str, bool onlyCheckExtras) { for (int i = 0; i < str.Length; ++i) { - Path.CheckInvalidPathChars(str[i], true); + // FileIOPermission doesn't allow for normalizing across various volume names. This means "C:\" and + // "\\?\C:\" won't be considered correctly. In addition there are many other aliases for the volume + // besides "C:" such as (in one concrete example) "\\?\Harddisk0Partition2\", "\\?\HarddiskVolume6\", + // "\\?\Volume{d1655348-0000-0000-0000-f01500000000}\", etc. + // + // We'll continue to explicitly block extended syntax here by disallowing wildcards no matter where + // they occur in the string (e.g. \\?\ isn't ok) + if (CheckExtraPathCharacters(str[i])) + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidPathChars")); + + if (!onlyCheckExtras) + Path.CheckInvalidPathChars(str[i]); } } - private static bool AccessIsSet( FileIOPermissionAccess access, FileIOPermissionAccess question ) + /// + /// Check for ?,* and null, ignoring extended syntax. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private unsafe static bool CheckExtraPathCharacters(string path) + { + char currentChar; + for (int i = 0; i < path.Length; i++) + { + currentChar = path[i]; + + // We also check for null here as StringExpressionSet will trim it out. (Ensuring we still throw as we always have.) + if (currentChar == '*' || currentChar == '?' || currentChar == '\0') return true; + } + return false; + } + + private static bool AccessIsSet(FileIOPermissionAccess access, FileIOPermissionAccess question) { return (access & question) != 0; } - + private bool IsEmpty() { return (!m_unrestricted && @@ -563,24 +598,24 @@ namespace System.Security.Permissions { (this.m_viewAcl == null || this.m_viewAcl.IsEmpty()) && (this.m_changeAcl == null || this.m_changeAcl.IsEmpty())); } - + //------------------------------------------------------ // // CODEACCESSPERMISSION IMPLEMENTATION // //------------------------------------------------------ - + public bool IsUnrestricted() { return m_unrestricted; } - + //------------------------------------------------------ // // IPERMISSION IMPLEMENTATION // //------------------------------------------------------ - + public override bool IsSubsetOf(IPermission target) { if (target == null) @@ -597,14 +632,14 @@ namespace System.Security.Permissions { else if (this.IsUnrestricted()) return false; else - return ((this.m_read == null || this.m_read.IsSubsetOf( operand.m_read )) && - (this.m_write == null || this.m_write.IsSubsetOf( operand.m_write )) && - (this.m_append == null || this.m_append.IsSubsetOf( operand.m_append )) && - (this.m_pathDiscovery == null || this.m_pathDiscovery.IsSubsetOf( operand.m_pathDiscovery )) && - (this.m_viewAcl == null || this.m_viewAcl.IsSubsetOf( operand.m_viewAcl )) && - (this.m_changeAcl == null || this.m_changeAcl.IsSubsetOf( operand.m_changeAcl ))); + return ((this.m_read == null || this.m_read.IsSubsetOf(operand.m_read)) && + (this.m_write == null || this.m_write.IsSubsetOf(operand.m_write)) && + (this.m_append == null || this.m_append.IsSubsetOf(operand.m_append)) && + (this.m_pathDiscovery == null || this.m_pathDiscovery.IsSubsetOf(operand.m_pathDiscovery)) && + (this.m_viewAcl == null || this.m_viewAcl.IsSubsetOf(operand.m_viewAcl)) && + (this.m_changeAcl == null || this.m_changeAcl.IsSubsetOf(operand.m_changeAcl))); } - + public override IPermission Intersect(IPermission target) { if (target == null) @@ -622,18 +657,18 @@ namespace System.Security.Permissions { { return target.Copy(); } - + if (operand.IsUnrestricted()) { return this.Copy(); } - - FileIOAccess intersectRead = this.m_read == null ? null : this.m_read.Intersect( operand.m_read ); - FileIOAccess intersectWrite = this.m_write == null ? null : this.m_write.Intersect( operand.m_write ); - FileIOAccess intersectAppend = this.m_append == null ? null : this.m_append.Intersect( operand.m_append ); - FileIOAccess intersectPathDiscovery = this.m_pathDiscovery == null ? null : this.m_pathDiscovery.Intersect( operand.m_pathDiscovery ); - FileIOAccess intersectViewAcl = this.m_viewAcl == null ? null : this.m_viewAcl.Intersect( operand.m_viewAcl ); - FileIOAccess intersectChangeAcl = this.m_changeAcl == null ? null : this.m_changeAcl.Intersect( operand.m_changeAcl ); + + FileIOAccess intersectRead = this.m_read == null ? null : this.m_read.Intersect(operand.m_read); + FileIOAccess intersectWrite = this.m_write == null ? null : this.m_write.Intersect(operand.m_write); + FileIOAccess intersectAppend = this.m_append == null ? null : this.m_append.Intersect(operand.m_append); + FileIOAccess intersectPathDiscovery = this.m_pathDiscovery == null ? null : this.m_pathDiscovery.Intersect(operand.m_pathDiscovery); + FileIOAccess intersectViewAcl = this.m_viewAcl == null ? null : this.m_viewAcl.Intersect(operand.m_viewAcl); + FileIOAccess intersectChangeAcl = this.m_changeAcl == null ? null : this.m_changeAcl.Intersect(operand.m_changeAcl); if ((intersectRead == null || intersectRead.IsEmpty()) && (intersectWrite == null || intersectWrite.IsEmpty()) && @@ -644,7 +679,7 @@ namespace System.Security.Permissions { { return null; } - + FileIOPermission intersectPermission = new FileIOPermission(PermissionState.None); intersectPermission.m_unrestricted = false; intersectPermission.m_read = intersectRead; @@ -653,10 +688,10 @@ namespace System.Security.Permissions { intersectPermission.m_pathDiscovery = intersectPathDiscovery; intersectPermission.m_viewAcl = intersectViewAcl; intersectPermission.m_changeAcl = intersectChangeAcl; - + return intersectPermission; } - + public override IPermission Union(IPermission other) { if (other == null) @@ -670,19 +705,19 @@ namespace System.Security.Permissions { { throw new ArgumentException(Environment.GetResourceString("Argument_WrongType", this.GetType().FullName)); } - + if (this.IsUnrestricted() || operand.IsUnrestricted()) { - return new FileIOPermission( PermissionState.Unrestricted ); + return new FileIOPermission(PermissionState.Unrestricted); } - - FileIOAccess unionRead = this.m_read == null ? operand.m_read : this.m_read.Union( operand.m_read ); - FileIOAccess unionWrite = this.m_write == null ? operand.m_write : this.m_write.Union( operand.m_write ); - FileIOAccess unionAppend = this.m_append == null ? operand.m_append : this.m_append.Union( operand.m_append ); - FileIOAccess unionPathDiscovery = this.m_pathDiscovery == null ? operand.m_pathDiscovery : this.m_pathDiscovery.Union( operand.m_pathDiscovery ); - FileIOAccess unionViewAcl = this.m_viewAcl == null ? operand.m_viewAcl : this.m_viewAcl.Union( operand.m_viewAcl ); - FileIOAccess unionChangeAcl = this.m_changeAcl == null ? operand.m_changeAcl : this.m_changeAcl.Union( operand.m_changeAcl ); - + + FileIOAccess unionRead = this.m_read == null ? operand.m_read : this.m_read.Union(operand.m_read); + FileIOAccess unionWrite = this.m_write == null ? operand.m_write : this.m_write.Union(operand.m_write); + FileIOAccess unionAppend = this.m_append == null ? operand.m_append : this.m_append.Union(operand.m_append); + FileIOAccess unionPathDiscovery = this.m_pathDiscovery == null ? operand.m_pathDiscovery : this.m_pathDiscovery.Union(operand.m_pathDiscovery); + FileIOAccess unionViewAcl = this.m_viewAcl == null ? operand.m_viewAcl : this.m_viewAcl.Union(operand.m_viewAcl); + FileIOAccess unionChangeAcl = this.m_changeAcl == null ? operand.m_changeAcl : this.m_changeAcl.Union(operand.m_changeAcl); + if ((unionRead == null || unionRead.IsEmpty()) && (unionWrite == null || unionWrite.IsEmpty()) && (unionAppend == null || unionAppend.IsEmpty()) && @@ -692,7 +727,7 @@ namespace System.Security.Permissions { { return null; } - + FileIOPermission unionPermission = new FileIOPermission(PermissionState.None); unionPermission.m_unrestricted = false; unionPermission.m_read = unionRead; @@ -702,9 +737,9 @@ namespace System.Security.Permissions { unionPermission.m_viewAcl = unionViewAcl; unionPermission.m_changeAcl = unionChangeAcl; - return unionPermission; + return unionPermission; } - + public override IPermission Copy() { FileIOPermission copy = new FileIOPermission(PermissionState.None); @@ -740,97 +775,97 @@ namespace System.Security.Permissions { copy.m_changeAcl = this.m_changeAcl.Copy(); } } - return copy; + return copy; } - + #if FEATURE_CAS_POLICY public override SecurityElement ToXml() { - SecurityElement esd = CodeAccessPermission.CreatePermissionElement( this, "System.Security.Permissions.FileIOPermission" ); + SecurityElement esd = CodeAccessPermission.CreatePermissionElement(this, "System.Security.Permissions.FileIOPermission"); if (!IsUnrestricted()) { if (this.m_read != null && !this.m_read.IsEmpty()) { - esd.AddAttribute( "Read", SecurityElement.Escape( m_read.ToString() ) ); + esd.AddAttribute("Read", SecurityElement.Escape(m_read.ToString())); } if (this.m_write != null && !this.m_write.IsEmpty()) { - esd.AddAttribute( "Write", SecurityElement.Escape( m_write.ToString() ) ); + esd.AddAttribute("Write", SecurityElement.Escape(m_write.ToString())); } if (this.m_append != null && !this.m_append.IsEmpty()) { - esd.AddAttribute( "Append", SecurityElement.Escape( m_append.ToString() ) ); + esd.AddAttribute("Append", SecurityElement.Escape(m_append.ToString())); } if (this.m_pathDiscovery != null && !this.m_pathDiscovery.IsEmpty()) { - esd.AddAttribute( "PathDiscovery", SecurityElement.Escape( m_pathDiscovery.ToString() ) ); + esd.AddAttribute("PathDiscovery", SecurityElement.Escape(m_pathDiscovery.ToString())); } if (this.m_viewAcl != null && !this.m_viewAcl.IsEmpty()) { - esd.AddAttribute( "ViewAcl", SecurityElement.Escape( m_viewAcl.ToString() ) ); + esd.AddAttribute("ViewAcl", SecurityElement.Escape(m_viewAcl.ToString())); } if (this.m_changeAcl != null && !this.m_changeAcl.IsEmpty()) { - esd.AddAttribute( "ChangeAcl", SecurityElement.Escape( m_changeAcl.ToString() ) ); + esd.AddAttribute("ChangeAcl", SecurityElement.Escape(m_changeAcl.ToString())); } } else { - esd.AddAttribute( "Unrestricted", "true" ); + esd.AddAttribute("Unrestricted", "true"); } return esd; } - + [System.Security.SecuritySafeCritical] // auto-generated public override void FromXml(SecurityElement esd) { - CodeAccessPermission.ValidateElement( esd, this ); + CodeAccessPermission.ValidateElement(esd, this); String et; - + if (XMLUtil.IsUnrestricted(esd)) { m_unrestricted = true; return; } - - + + m_unrestricted = false; - - et = esd.Attribute( "Read" ); + + et = esd.Attribute("Read"); if (et != null) { - m_read = new FileIOAccess( et ); + m_read = new FileIOAccess(et); } else { m_read = null; } - - et = esd.Attribute( "Write" ); + + et = esd.Attribute("Write"); if (et != null) { - m_write = new FileIOAccess( et ); + m_write = new FileIOAccess(et); } else { m_write = null; } - - et = esd.Attribute( "Append" ); + + et = esd.Attribute("Append"); if (et != null) { - m_append = new FileIOAccess( et ); + m_append = new FileIOAccess(et); } else { m_append = null; } - et = esd.Attribute( "PathDiscovery" ); + et = esd.Attribute("PathDiscovery"); if (et != null) { - m_pathDiscovery = new FileIOAccess( et ); + m_pathDiscovery = new FileIOAccess(et); m_pathDiscovery.PathDiscovery = true; } else @@ -838,20 +873,20 @@ namespace System.Security.Permissions { m_pathDiscovery = null; } - et = esd.Attribute( "ViewAcl" ); + et = esd.Attribute("ViewAcl"); if (et != null) { - m_viewAcl = new FileIOAccess( et ); + m_viewAcl = new FileIOAccess(et); } else { m_viewAcl = null; } - et = esd.Attribute( "ChangeAcl" ); + et = esd.Attribute("ChangeAcl"); if (et != null) { - m_changeAcl = new FileIOAccess( et ); + m_changeAcl = new FileIOAccess(et); } else { @@ -875,60 +910,60 @@ namespace System.Security.Permissions { public override bool Equals(Object obj) { FileIOPermission perm = obj as FileIOPermission; - if(perm == null) + if (perm == null) return false; - if(m_unrestricted && perm.m_unrestricted) + if (m_unrestricted && perm.m_unrestricted) return true; - if(m_unrestricted != perm.m_unrestricted) + if (m_unrestricted != perm.m_unrestricted) return false; - if(m_read == null) + if (m_read == null) { - if(perm.m_read != null && !perm.m_read.IsEmpty()) + if (perm.m_read != null && !perm.m_read.IsEmpty()) return false; } - else if(!m_read.Equals(perm.m_read)) + else if (!m_read.Equals(perm.m_read)) return false; - if(m_write == null) + if (m_write == null) { - if(perm.m_write != null && !perm.m_write.IsEmpty()) - return false; + if (perm.m_write != null && !perm.m_write.IsEmpty()) + return false; } - else if(!m_write.Equals(perm.m_write)) + else if (!m_write.Equals(perm.m_write)) return false; - if(m_append == null) + if (m_append == null) { - if(perm.m_append != null && !perm.m_append.IsEmpty()) - return false; + if (perm.m_append != null && !perm.m_append.IsEmpty()) + return false; } - else if(!m_append.Equals(perm.m_append)) + else if (!m_append.Equals(perm.m_append)) return false; - if(m_pathDiscovery == null) + if (m_pathDiscovery == null) { - if(perm.m_pathDiscovery != null && !perm.m_pathDiscovery.IsEmpty()) - return false; + if (perm.m_pathDiscovery != null && !perm.m_pathDiscovery.IsEmpty()) + return false; } - else if(!m_pathDiscovery.Equals(perm.m_pathDiscovery)) + else if (!m_pathDiscovery.Equals(perm.m_pathDiscovery)) return false; - if(m_viewAcl == null) + if (m_viewAcl == null) { - if(perm.m_viewAcl != null && !perm.m_viewAcl.IsEmpty()) - return false; + if (perm.m_viewAcl != null && !perm.m_viewAcl.IsEmpty()) + return false; } - else if(!m_viewAcl.Equals(perm.m_viewAcl)) + else if (!m_viewAcl.Equals(perm.m_viewAcl)) return false; - if(m_changeAcl == null) + if (m_changeAcl == null) { - if(perm.m_changeAcl != null && !perm.m_changeAcl.IsEmpty()) - return false; + if (perm.m_changeAcl != null && !perm.m_changeAcl.IsEmpty()) + return false; } - else if(!m_changeAcl.Equals(perm.m_changeAcl)) + else if (!m_changeAcl.Equals(perm.m_changeAcl)) return false; return true; @@ -951,12 +986,8 @@ namespace System.Security.Permissions { /// IMPORTANT: This method should only be used after calling GetFullPath on the path to verify /// /// - /// - /// - /// - /// [System.Security.SecuritySafeCritical] - internal static void QuickDemand(FileIOPermissionAccess access, string fullPath, bool checkForDuplicates, bool needFullPath) + internal static void QuickDemand(FileIOPermissionAccess access, string fullPath, bool checkForDuplicates = false, bool needFullPath = true) { if (!CodeAccessSecurityEngine.QuickCheckForAllDemands()) { @@ -964,18 +995,109 @@ namespace System.Security.Permissions { } else { - //Emulate FileIOPermission checks - Path.CheckInvalidPathChars(fullPath, true); + EmulateFileIOPermissionChecks(fullPath); + } + } - if (fullPath.Length > 2 && fullPath.IndexOf(':', 2) != -1) + /// + /// Call this method if you don't need a the FileIOPermission for anything other than calling Demand() once. + /// + /// This method tries to verify full access before allocating a FileIOPermission object. + /// If full access is there, then we still have to emulate the checks that creating the + /// FileIOPermission object would have performed. + /// + /// IMPORTANT: This method should only be used after calling GetFullPath on the path to verify + /// + /// + [System.Security.SecuritySafeCritical] + internal static void QuickDemand(FileIOPermissionAccess access, string[] fullPathList, bool checkForDuplicates = false, bool needFullPath = true) + { + if (!CodeAccessSecurityEngine.QuickCheckForAllDemands()) + { + new FileIOPermission(access, fullPathList, checkForDuplicates, needFullPath).Demand(); + } + else + { + foreach (string fullPath in fullPathList) + { + EmulateFileIOPermissionChecks(fullPath); + } + } + } + + [System.Security.SecuritySafeCritical] + internal static void QuickDemand(PermissionState state) + { + if (!CodeAccessSecurityEngine.QuickCheckForAllDemands()) + { + new FileIOPermission(state).Demand(); + } + } + +#if FEATURE_MACL + [System.Security.SecuritySafeCritical] + internal static void QuickDemand(FileIOPermissionAccess access, AccessControlActions control, string fullPath, bool checkForDuplicates = false, bool needFullPath = true) + { + if (!CodeAccessSecurityEngine.QuickCheckForAllDemands()) + { + new FileIOPermission(access, control, new string[] { fullPath }, checkForDuplicates, needFullPath).Demand(); + } + else + { + EmulateFileIOPermissionChecks(fullPath); + } + } + + [System.Security.SecuritySafeCritical] + internal static void QuickDemand(FileIOPermissionAccess access, AccessControlActions control, string[] fullPathList, bool checkForDuplicates = true, bool needFullPath = true) + { + if (!CodeAccessSecurityEngine.QuickCheckForAllDemands()) + { + new FileIOPermission(access, control, fullPathList, checkForDuplicates, needFullPath).Demand(); + } + else + { + foreach (string fullPath in fullPathList) + { + EmulateFileIOPermissionChecks(fullPath); + } + } + } +#endif + + /// + /// Perform the additional path checks that would normally happen when creating a FileIOPermission object. + /// + /// A path that has already gone through GetFullPath or Normalize + internal static void EmulateFileIOPermissionChecks(string fullPath) + { + // Callers should have already made checks for invalid path format via normalization. This method will only make the + // additional checks needed to throw the same exceptions that would normally throw when using FileIOPermission. + // These checks are done via CheckIllegalCharacters() and StringExpressionSet in AddPathList() above. + // + // We have to check the beginning as some paths may be passed in as path + @"\.", which will be normalized away. + BCLDebug.Assert( + fullPath.StartsWith(Path.NormalizePath(fullPath, fullCheck: false), StringComparison.OrdinalIgnoreCase), + string.Format("path isn't normalized: {0}", fullPath)); + + // Checking for colon / invalid characters on device paths blocks legitimate access to objects such as named pipes. + if (AppContextSwitches.UseLegacyPathHandling || !PathInternal.IsDevice(fullPath)) + { + // GetFullPath already checks normal invalid path characters. We need to just check additional (wildcard) characters here. + // (By calling the standard helper we can allow extended paths \\?\ through when the support is enabled.) + if (PathInternal.HasWildCardCharacters(fullPath)) + { + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidPathChars")); + } + + if (PathInternal.HasInvalidVolumeSeparator(fullPath)) { throw new NotSupportedException(Environment.GetResourceString("Argument_PathFormatNotSupported")); } } } - } - + [Serializable] internal sealed class FileIOAccess { diff --git a/mcs/class/referencesource/mscorlib/system/security/principal/windowsidentity.cs b/mcs/class/referencesource/mscorlib/system/security/principal/windowsidentity.cs index 93cb255587..e045de8e25 100644 --- a/mcs/class/referencesource/mscorlib/system/security/principal/windowsidentity.cs +++ b/mcs/class/referencesource/mscorlib/system/security/principal/windowsidentity.cs @@ -609,6 +609,8 @@ namespace System.Security.Principal // Public methods. // [SecuritySafeCritical] + [DynamicSecurityMethodAttribute()] + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public static void RunImpersonated(SafeAccessTokenHandle safeAccessTokenHandle, Action action) { if (action == null) @@ -627,6 +629,8 @@ namespace System.Security.Principal } [SecuritySafeCritical] + [DynamicSecurityMethodAttribute()] + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public static T RunImpersonated(SafeAccessTokenHandle safeAccessTokenHandle, Func func) { if (func == null) diff --git a/mcs/class/referencesource/mscorlib/system/security/util/stringexpressionset.cs b/mcs/class/referencesource/mscorlib/system/security/util/stringexpressionset.cs index 101d15ee58..698f76f02e 100644 --- a/mcs/class/referencesource/mscorlib/system/security/util/stringexpressionset.cs +++ b/mcs/class/referencesource/mscorlib/system/security/util/stringexpressionset.cs @@ -219,33 +219,35 @@ namespace System.Security.Util { throw new ArgumentNullException( "str" ); } Contract.EndContractBlock(); + ArrayList retArrayList = new ArrayList(); for (int index = 0; index < str.Length; ++index) { if (str[index] == null) throw new ArgumentNullException( "str" ); + // Replace alternate directory separators String oneString = StaticProcessWholeString( str[index] ); if (oneString != null && oneString.Length != 0) { - String temp = StaticProcessSingleString( oneString); + // Trim leading and trailing spaces + String temp = StaticProcessSingleString(oneString); - int indexOfNull = temp.IndexOf( '\0' ); + int indexOfNull = temp.IndexOf('\0'); if (indexOfNull != -1) - temp = temp.Substring( 0, indexOfNull ); + temp = temp.Substring(0, indexOfNull); if (temp != null && temp.Length != 0) { - if (Path.IsRelative(temp)) + if (PathInternal.IsPartiallyQualified(temp)) { - throw new ArgumentException( Environment.GetResourceString( "Argument_AbsolutePathRequired" ) ); + throw new ArgumentException(Environment.GetResourceString("Argument_AbsolutePathRequired")); } temp = CanonicalizePath( temp, needFullPath ); - retArrayList.Add( temp ); } } @@ -746,24 +748,14 @@ namespace System.Security.Util { [System.Security.SecurityCritical] // auto-generated [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] - internal static String CanonicalizePath( String path, bool needFullPath ) + internal static string CanonicalizePath(string path, bool needFullPath) { - if (path.IndexOf( '~' ) != -1) - { - string longPath = null; - GetLongPathName(path, JitHelpers.GetStringHandleOnStack(ref longPath)); - path = (longPath != null) ? longPath : path; - } - - if (path.IndexOf( ':', 2 ) != -1) - throw new NotSupportedException( Environment.GetResourceString( "Argument_PathFormatNotSupported" ) ); - if (needFullPath) { - String newPath = System.IO.Path.GetFullPathInternal( path ); - if (path.EndsWith( m_directorySeparator + ".", StringComparison.Ordinal )) + string newPath = Path.GetFullPathInternal(path); + if (path.EndsWith(m_directorySeparator + ".", StringComparison.Ordinal)) { - if (newPath.EndsWith( m_directorySeparator )) + if (newPath.EndsWith(m_directorySeparator)) { newPath += "."; } @@ -771,11 +763,23 @@ namespace System.Security.Util { { newPath += m_directorySeparator + "."; } - } - return newPath; + } + path = newPath; } - else - return path; + else if (path.IndexOf('~') != -1) + { + // GetFullPathInternal() will expand 8.3 file names + string longPath = null; + GetLongPathName(path, JitHelpers.GetStringHandleOnStack(ref longPath)); + path = (longPath != null) ? longPath : path; + } + + // This blocks usage of alternate data streams and some extended syntax paths (\\?\C:\). Checking after + // normalization allows valid paths such as " C:\" to be considered ok (as it will become "C:\"). + if (path.IndexOf(':', 2) != -1) + throw new NotSupportedException(Environment.GetResourceString("Argument_PathFormatNotSupported")); + + return path; } } } diff --git a/mcs/class/referencesource/mscorlib/system/security/util/urlstring.cs b/mcs/class/referencesource/mscorlib/system/security/util/urlstring.cs index b009ff0a8e..c629fb4f69 100644 --- a/mcs/class/referencesource/mscorlib/system/security/util/urlstring.cs +++ b/mcs/class/referencesource/mscorlib/system/security/util/urlstring.cs @@ -354,13 +354,24 @@ namespace System.Security.Util { // 3. Throws a PathTooLongException if the length of the resulting URL is >= MAX_PATH. // This is done to prevent security issues due to canonicalization truncations. // Remove this method when the Path class supports "\\?\" - internal static String PreProcessForExtendedPathRemoval(String url, bool isFileUrl) + internal static string PreProcessForExtendedPathRemoval(string url, bool isFileUrl) { - bool uncShare = false; - return PreProcessForExtendedPathRemoval(url, isFileUrl, ref uncShare); + return PreProcessForExtendedPathRemoval(checkPathLength: true, url: url, isFileUrl: isFileUrl); } - private static String PreProcessForExtendedPathRemoval(String url, bool isFileUrl, ref bool isUncShare) + internal static string PreProcessForExtendedPathRemoval(bool checkPathLength, string url, bool isFileUrl) + { + bool isUncShare = false; + return PreProcessForExtendedPathRemoval(checkPathLength: checkPathLength, url: url, isFileUrl: isFileUrl, isUncShare: ref isUncShare); + } + + // Keeping this signature to avoid reflection breaks + private static string PreProcessForExtendedPathRemoval(string url, bool isFileUrl, ref bool isUncShare) + { + return PreProcessForExtendedPathRemoval(checkPathLength: true, url: url, isFileUrl: isFileUrl, isUncShare: ref isUncShare); + } + + private static string PreProcessForExtendedPathRemoval(bool checkPathLength, string url, bool isFileUrl, ref bool isUncShare) { // This is the modified URL that we will return StringBuilder modifiedUrl = new StringBuilder(url); @@ -434,15 +445,24 @@ namespace System.Security.Util { } // ITEM 3 - If the path is greater than or equal (due to terminating NULL in windows) MAX_PATH, we throw. - if (modifiedUrl.Length >= Path.MAX_PATH) + if (checkPathLength) { - throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong")); + // This needs to be a separate method to avoid hitting the static constructor on AppContextSwitches + CheckPathTooLong(modifiedUrl); } // Create the result string from the StringBuilder return modifiedUrl.ToString(); } + [MethodImpl(MethodImplOptions.NoInlining)] + private static void CheckPathTooLong(StringBuilder path) + { + if (path.Length >= (AppContextSwitches.BlockLongPaths ? PathInternal.MaxShortPath : PathInternal.MaxLongPath)) + { + throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong")); + } + } // Do any misc massaging of data in the URL private String PreProcessURL(String url, bool isFileURL) diff --git a/mcs/class/referencesource/mscorlib/system/sharedstatics.cs b/mcs/class/referencesource/mscorlib/system/sharedstatics.cs index 87f99a67da..d455031e76 100644 --- a/mcs/class/referencesource/mscorlib/system/sharedstatics.cs +++ b/mcs/class/referencesource/mscorlib/system/sharedstatics.cs @@ -28,6 +28,15 @@ namespace System { internal sealed class SharedStatics { +#if MONO + // TODO: We are using only GetSharedStringMaker for now which is + // ok to be AppDomain static + static readonly SharedStatics _sharedStatics = new SharedStatics(); + + private SharedStatics() + { + } +#else // this is declared static but is actually forced to be the same object // for each AppDomain at AppDomain create time. private static SharedStatics _sharedStatics; @@ -38,6 +47,7 @@ namespace System { { BCLDebug.Assert(false, "SharedStatics..ctor() is never called."); } +#endif private volatile String _Remoting_Identity_IDGuid; public static String Remoting_Identity_IDGuid diff --git a/mcs/class/referencesource/mscorlib/system/text/stringbuilder.cs b/mcs/class/referencesource/mscorlib/system/text/stringbuilder.cs index 357bfe6c6a..46c377bdeb 100644 --- a/mcs/class/referencesource/mscorlib/system/text/stringbuilder.cs +++ b/mcs/class/referencesource/mscorlib/system/text/stringbuilder.cs @@ -1968,7 +1968,7 @@ namespace System.Text { VerifyClassInvariant(); - if ((minBlockCharCount + Length) > m_MaxCapacity) + if (minBlockCharCount + Length < minBlockCharCount || (minBlockCharCount + Length) > m_MaxCapacity) throw new ArgumentOutOfRangeException("requiredLength", Environment.GetResourceString("ArgumentOutOfRange_SmallCapacity")); // Compute the length of the new block we need @@ -2028,7 +2028,8 @@ namespace System.Text { VerifyClassInvariant(); Contract.Assert(count > 0, "Count must be strictly positive"); Contract.Assert(index >= 0, "Index can't be negative"); - if (count + Length > m_MaxCapacity) + + if (count + Length < count || count + Length > m_MaxCapacity) throw new ArgumentOutOfRangeException("requiredLength", Environment.GetResourceString("ArgumentOutOfRange_SmallCapacity")); chunk = this; diff --git a/mcs/class/referencesource/mscorlib/system/threading/Tasks/Task.cs.REMOVED.git-id b/mcs/class/referencesource/mscorlib/system/threading/Tasks/Task.cs.REMOVED.git-id index 7a95d85312..f1df9a014f 100644 --- a/mcs/class/referencesource/mscorlib/system/threading/Tasks/Task.cs.REMOVED.git-id +++ b/mcs/class/referencesource/mscorlib/system/threading/Tasks/Task.cs.REMOVED.git-id @@ -1 +1 @@ -1e3f9293f7c31efdabd588b569ba8cd587752795 \ No newline at end of file +6ee970a08efe8a6db1ba7d82b85a2d685c96bd2b \ No newline at end of file diff --git a/mcs/class/referencesource/mscorlib/system/threading/eventwaithandle.cs b/mcs/class/referencesource/mscorlib/system/threading/eventwaithandle.cs index 08426b2327..cf9bdf17b1 100644 --- a/mcs/class/referencesource/mscorlib/system/threading/eventwaithandle.cs +++ b/mcs/class/referencesource/mscorlib/system/threading/eventwaithandle.cs @@ -16,6 +16,7 @@ =============================================================================*/ +#if !MOBILE #if !FEATURE_MACL namespace System.Security.AccessControl { @@ -27,6 +28,7 @@ namespace System.Security.AccessControl } } #endif +#endif namespace System.Threading { @@ -63,13 +65,24 @@ namespace System.Threading Contract.EndContractBlock(); SafeWaitHandle _handle = null; +#if MONO + int errorCode; +#endif switch(mode) { case EventResetMode.ManualReset: +#if MONO + _handle = new SafeWaitHandle (NativeEventCalls.CreateEvent_internal (true, initialState, name, out errorCode), true); +#else _handle = Win32Native.CreateEvent(null, true, initialState, name); +#endif break; case EventResetMode.AutoReset: +#if MONO + _handle = new SafeWaitHandle (NativeEventCalls.CreateEvent_internal (false, initialState, name, out errorCode), true); +#else _handle = Win32Native.CreateEvent(null, false, initialState, name); +#endif break; default: @@ -78,7 +91,9 @@ namespace System.Threading if (_handle.IsInvalid) { +#if !MONO int errorCode = Marshal.GetLastWin32Error(); +#endif _handle.SetHandleAsInvalid(); if(null != name && 0 != name.Length && Win32Native.ERROR_INVALID_HANDLE == errorCode) @@ -108,6 +123,7 @@ namespace System.Threading } Contract.EndContractBlock(); Win32Native.SECURITY_ATTRIBUTES secAttrs = null; +#if !MONO #if FEATURE_MACL // For ACL's, get the security descriptor from the EventWaitHandleSecurity. if (eventSecurity != null) { @@ -119,6 +135,7 @@ namespace System.Threading Buffer.Memcpy(pSecDescriptor, 0, sd, 0, sd.Length); secAttrs.pSecurityDescriptor = pSecDescriptor; } +#endif #endif SafeWaitHandle _handle = null; @@ -136,8 +153,13 @@ namespace System.Threading throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag",name)); }; +#if MONO + int errorCode; + _handle = new SafeWaitHandle (NativeEventCalls.CreateEvent_internal (isManualReset, initialState, name, out errorCode), true); +#else _handle = Win32Native.CreateEvent(secAttrs, isManualReset, initialState, name); int errorCode = Marshal.GetLastWin32Error(); +#endif if (_handle.IsInvalid) { @@ -239,15 +261,26 @@ namespace System.Threading result = null; +#if MOBILE + throw new NotSupportedException (); +#else + +#if MONO + int errorCode; + var myHandle = new SafeWaitHandle (NativeEventCalls.OpenEvent_internal (name, rights, out errorCode), true); +#else #if FEATURE_MACL SafeWaitHandle myHandle = Win32Native.OpenEvent((int) rights, false, name); #else SafeWaitHandle myHandle = Win32Native.OpenEvent(Win32Native.EVENT_MODIFY_STATE | Win32Native.SYNCHRONIZE, false, name); +#endif #endif if (myHandle.IsInvalid) { +#if !MONO int errorCode = Marshal.GetLastWin32Error(); +#endif if(Win32Native.ERROR_FILE_NOT_FOUND == errorCode || Win32Native.ERROR_INVALID_NAME == errorCode) return OpenExistingResult.NameNotFound; @@ -260,33 +293,52 @@ namespace System.Threading } result = new EventWaitHandle(myHandle); return OpenExistingResult.Success; +#endif } [System.Security.SecuritySafeCritical] // auto-generated public bool Reset() { +#if MONO + var res = NativeEventCalls.ResetEvent(safeWaitHandle); +#else bool res = Win32Native.ResetEvent(safeWaitHandle); +#endif if (!res) +#if MONO + throw new IOException (); +#else __Error.WinIOError(); +#endif return res; } [System.Security.SecuritySafeCritical] // auto-generated public bool Set() { +#if MONO + var res = NativeEventCalls.SetEvent(safeWaitHandle); +#else bool res = Win32Native.SetEvent(safeWaitHandle); +#endif if (!res) +#if MONO + throw new IOException (); +#else __Error.WinIOError(); +#endif return res; } -#if FEATURE_MACL +#if FEATURE_MACL || MOBILE [System.Security.SecuritySafeCritical] // auto-generated public EventWaitHandleSecurity GetAccessControl() { return new EventWaitHandleSecurity(safeWaitHandle, AccessControlSections.Access | AccessControlSections.Owner | AccessControlSections.Group); } +#endif +#if FEATURE_MACL [System.Security.SecuritySafeCritical] // auto-generated public void SetAccessControl(EventWaitHandleSecurity eventSecurity) { diff --git a/mcs/class/referencesource/mscorlib/system/threading/thread.cs b/mcs/class/referencesource/mscorlib/system/threading/thread.cs index b477f7bb68..d85cf9fb97 100644 --- a/mcs/class/referencesource/mscorlib/system/threading/thread.cs +++ b/mcs/class/referencesource/mscorlib/system/threading/thread.cs @@ -1081,7 +1081,6 @@ namespace System.Threading { dls.Store.SetData(slot, data); } -#if !MONO // #threadCultureInfo // @@ -1337,12 +1336,23 @@ namespace System.Threading { } #if! FEATURE_LEAK_CULTURE_INFO + +#if MONO + static void nativeInitCultureAccessors() + { + m_CurrentCulture = CultureInfo.ConstructCurrentCulture (); + m_CurrentUICulture = CultureInfo.ConstructCurrentUICulture (); + } +#else [System.Security.SecurityCritical] // auto-generated [ResourceExposure(ResourceScope.None)] [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern void nativeInitCultureAccessors(); #endif +#endif + +#if !MONO /*=============================================================*/ diff --git a/mcs/class/referencesource/mscorlib/system/threading/threadabortexception.cs b/mcs/class/referencesource/mscorlib/system/threading/threadabortexception.cs index 60046c7dba..3063b06aed 100644 --- a/mcs/class/referencesource/mscorlib/system/threading/threadabortexception.cs +++ b/mcs/class/referencesource/mscorlib/system/threading/threadabortexception.cs @@ -39,12 +39,11 @@ namespace System.Threading : base(info, context) { } -#if !MOBILE + public Object ExceptionState { [System.Security.SecuritySafeCritical] // auto-generated get {return Thread.CurrentThread.AbortReason;} } -#endif } } diff --git a/mcs/errors/cs0029-37.cs b/mcs/errors/cs0029-37.cs new file mode 100644 index 0000000000..80f8e8c800 --- /dev/null +++ b/mcs/errors/cs0029-37.cs @@ -0,0 +1,24 @@ +// CS0029: Cannot implicitly convert type `string' to `int' +// Line: 8 + +class A where T : CB, IA +{ + void Foo (T t) + { + t.Prop = "3"; + } +} + +class CB : CA +{ +} + +class CA +{ + public int Prop { get; set; } +} + +interface IA +{ + string Prop { get; set; } +} \ No newline at end of file diff --git a/mcs/errors/cs0122-39.cs b/mcs/errors/cs0122-39.cs new file mode 100644 index 0000000000..f7da1f94bf --- /dev/null +++ b/mcs/errors/cs0122-39.cs @@ -0,0 +1,15 @@ +// CS0122: `A.Y' is inaccessible due to its protection level +// Line: 8 + +public class Test +{ + public static void Main () + { + var x = nameof (A.Y); + } +} + +public class A +{ + private int Y { get; set; } +} \ No newline at end of file diff --git a/mcs/errors/cs0177-15.cs b/mcs/errors/cs0177-15.cs new file mode 100644 index 0000000000..310f40523b --- /dev/null +++ b/mcs/errors/cs0177-15.cs @@ -0,0 +1,21 @@ +// CS0177: The out parameter `x' must be assigned to before control leaves the current method +// Line: 6 + +public class GotoWithOut +{ + public static void Test (bool cond, out int x) + { + if (cond) + { + goto Label2; + } + else + { + goto Label; + } + Label: + x = 0; + Label2: + return; + } +} \ No newline at end of file diff --git a/mcs/errors/cs0619-59.cs b/mcs/errors/cs0619-59.cs new file mode 100644 index 0000000000..b703b0e44b --- /dev/null +++ b/mcs/errors/cs0619-59.cs @@ -0,0 +1,18 @@ +// CS0619: `A.X' is obsolete: `' +// Line: 10 + +using System; + +public class Test +{ + public static void Main() + { + var m = nameof (A.X); + } +} + +public class A +{ + [Obsolete ("", true)] + public int X; +} diff --git a/mcs/errors/cs1070-3.cs b/mcs/errors/cs1070-3.cs new file mode 100644 index 0000000000..18811dc53d --- /dev/null +++ b/mcs/errors/cs1070-3.cs @@ -0,0 +1,11 @@ +// CS1070: The type `C' has been forwarded to an assembly that is not referenced. Consider adding a reference to assembly `CS1070-lib-missing, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' +// Line: 5 +// Compiler options: -r:CS1070-lib.dll + +public class D +{ + static void Main () + { + new C (); + } +} \ No newline at end of file diff --git a/mcs/errors/cs1501-19.cs b/mcs/errors/cs1501-19.cs new file mode 100644 index 0000000000..68095c11bc --- /dev/null +++ b/mcs/errors/cs1501-19.cs @@ -0,0 +1,26 @@ +// CS1501: No overload for method `Call' takes `0' arguments +// Line: 8 + +class A where T : CB, IA +{ + void Foo (T t) + { + t.Call (); + } +} + +class CB : CA +{ +} + +class CA +{ + public void Call (int arg) + { + } +} + +interface IA +{ + void Call (bool arg, int arg2); +} diff --git a/mcs/errors/cs1691-2.cs b/mcs/errors/cs1691-2.cs deleted file mode 100644 index 8c096991a7..0000000000 --- a/mcs/errors/cs1691-2.cs +++ /dev/null @@ -1,4 +0,0 @@ -// CS1691: `2' is not a valid warning number -// Line: 0 -// Compiler options: -warnaserror -warnaserror:1691,2 - diff --git a/mcs/errors/cs1691-3.cs b/mcs/errors/cs1691-3.cs deleted file mode 100644 index c423ebf4f3..0000000000 --- a/mcs/errors/cs1691-3.cs +++ /dev/null @@ -1,4 +0,0 @@ -// CS1691: `20' is not a valid warning number -// Line: 0 -// Compiler options: -warnaserror -warnaserror-:20 - diff --git a/mcs/errors/cs1691-4.cs b/mcs/errors/cs1691-4.cs deleted file mode 100644 index cd9ce646a4..0000000000 --- a/mcs/errors/cs1691-4.cs +++ /dev/null @@ -1,4 +0,0 @@ -// CS1691: `20' is not a valid warning number -// Line: 0 -// Compiler options: -warnaserror -nowarn:20 - diff --git a/mcs/errors/cs1691.cs b/mcs/errors/cs1691.cs deleted file mode 100644 index bd3e169f4b..0000000000 --- a/mcs/errors/cs1691.cs +++ /dev/null @@ -1,6 +0,0 @@ -// CS1691: `1' is not a valid warning number -// Line: 5 -// Compiler options: -warnaserror - -#pragma warning disable 1 - diff --git a/mcs/errors/cs1744-3.cs b/mcs/errors/cs1744-3.cs new file mode 100644 index 0000000000..b899816d21 --- /dev/null +++ b/mcs/errors/cs1744-3.cs @@ -0,0 +1,18 @@ +// CS1744: Named argument `p1' cannot be used for a parameter which has positional argument specified +// Line: 8 + +internal class Program +{ + public static void Main () + { + Method (1, 2, p1: 3); + } + + static void Method (int p1, int paramNamed, int p2) + { + } + + static void Method (int p1, int p2, object paramNamed) + { + } +} diff --git a/mcs/errors/cs1904.cs b/mcs/errors/cs1904.cs deleted file mode 100644 index 441753793d..0000000000 --- a/mcs/errors/cs1904.cs +++ /dev/null @@ -1,8 +0,0 @@ -// CS1904: `4013' is not a valid warning number -// Line: 0 -// Compiler options: -nowarn:4014,4013 - -class ClassMain { - public static void Main () {} -} - diff --git a/mcs/ilasm/codegen/TypeDef.cs b/mcs/ilasm/codegen/TypeDef.cs index 793e47c8a2..74200cddf4 100644 --- a/mcs/ilasm/codegen/TypeDef.cs +++ b/mcs/ilasm/codegen/TypeDef.cs @@ -348,8 +348,10 @@ namespace Mono.ILASM { if (IsValueType (parent.PeapiClass.nameSpace, parent.PeapiClass.name)) is_value_class = true; - else if (IsEnumType (parent.PeapiClass.nameSpace, parent.PeapiClass.name)) + else if (IsEnumType (parent.PeapiClass.nameSpace, parent.PeapiClass.name)) { is_enum_class = true; + is_value_class = false; + } if (!IsValueType (name_space, name) && !IsEnumType (name_space, name) && is_value_class && (attr & PEAPI.TypeAttr.Sealed) == 0) { diff --git a/mcs/ilasm/scanner/InstrToken.cs b/mcs/ilasm/scanner/InstrToken.cs index edd6db3739..bc78f97fd1 100644 --- a/mcs/ilasm/scanner/InstrToken.cs +++ b/mcs/ilasm/scanner/InstrToken.cs @@ -1,6 +1,8 @@ // InstrToken.cs // Author: Sergey Chaban (serge@wildwestsoftware.com) +#if !MOBILE + using System; using System.Reflection.Emit; @@ -103,3 +105,5 @@ namespace Mono.ILASM { } } + +#endif diff --git a/mcs/jay/jay.vcxproj b/mcs/jay/jay.vcxproj index 7e97652e02..3d6f8c0d4f 100644 --- a/mcs/jay/jay.vcxproj +++ b/mcs/jay/jay.vcxproj @@ -1,5 +1,5 @@  - + Debug @@ -14,17 +14,18 @@ {5D485D32-3B9F-4287-AB24-C8DA5B89F537} jay Win32Proj + 8.1 Application MultiByte - v120 + v140 Application MultiByte - v120 + v140 @@ -38,11 +39,11 @@ <_ProjectFileVersion>10.0.30319.1 - Debug\ - Debug\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ true - Release\ - Release\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ false @@ -51,11 +52,10 @@ SKEL_DIRECTORY=".";%(PreprocessorDefinitions) true EnableFastChecks - MultiThreadedDebug Level3 - EditAndContinue + ProgramDatabase true @@ -69,7 +69,6 @@ SKEL_DIRECTORY=".";%(PreprocessorDefinitions) - MultiThreaded Level3 diff --git a/mcs/mcs/Makefile b/mcs/mcs/Makefile index 01285712a2..9c4b6a172a 100644 --- a/mcs/mcs/Makefile +++ b/mcs/mcs/Makefile @@ -68,10 +68,10 @@ btest: mcs2.exe mcs3.exe ls -l mcs2.exe mcs3.exe mcs2.exe: $(PROGRAM) - $(TIME) $(RUNTIME) $(RUNTIME_FLAGS) $(PROGRAM) $(USE_MCS_FLAGS) -target:exe -out:$@ $(BUILT_SOURCES) @$(response) + $(TIME) $(RUNTIME) $(RUNTIME_FLAGS) $(PROGRAM) $(USE_MCS_FLAGS) $(MCS_REFERENCES) -target:exe -out:$@ $(BUILT_SOURCES) $(EXTRA_SOURCES) @$(response) mcs3.exe: mcs2.exe - $(TIME) $(RUNTIME) $(RUNTIME_FLAGS) ./mcs2.exe $(USE_MCS_FLAGS) -target:exe -out:$@ $(BUILT_SOURCES) @$(response) + $(TIME) $(RUNTIME) $(RUNTIME_FLAGS) ./mcs2.exe $(USE_MCS_FLAGS) $(MCS_REFERENCES) -target:exe -out:$@ $(BUILT_SOURCES) $(EXTRA_SOURCES) @$(response) wc: wc -l $(BUILT_SOURCES) `cat $(sourcefile)` diff --git a/mcs/mcs/assembly.cs b/mcs/mcs/assembly.cs index 53ec6e22c5..318d040985 100644 --- a/mcs/mcs/assembly.cs +++ b/mcs/mcs/assembly.cs @@ -1215,7 +1215,7 @@ namespace Mono.CSharp paths.AddRange (compiler.Settings.ReferencesLookupPaths); } - public abstract bool HasObjectType (T assembly); + public abstract T HasObjectType (T assembly); protected abstract string[] GetDefaultReferences (); public abstract T LoadAssemblyFile (string fileName, bool isImplicitReference); public abstract void LoadReferences (ModuleContainer module); @@ -1282,8 +1282,13 @@ namespace Mono.CSharp // // corlib assembly is the first referenced assembly which contains System.Object // - if (HasObjectType (assembly.Item2)) { - corlib_assembly = assembly.Item2; + corlib_assembly = HasObjectType (assembly.Item2); + if (corlib_assembly != null) { + if (corlib_assembly != assembly.Item2) { + var ca = corlib_assembly; + i = loaded.FindIndex (l => l.Item2 == ca); + } + loaded.RemoveAt (i); break; } diff --git a/mcs/mcs/class.cs.REMOVED.git-id b/mcs/mcs/class.cs.REMOVED.git-id index 79fa8c3acd..2acdf00878 100644 --- a/mcs/mcs/class.cs.REMOVED.git-id +++ b/mcs/mcs/class.cs.REMOVED.git-id @@ -1 +1 @@ -0f7ea925d9e3382fab323c3950fb1a16c48a47b5 \ No newline at end of file +e5d0b1f173584fe1676d1379efa1df8a35346731 \ No newline at end of file diff --git a/mcs/mcs/constant.cs b/mcs/mcs/constant.cs index a0ae78cdf5..acec3be358 100644 --- a/mcs/mcs/constant.cs +++ b/mcs/mcs/constant.cs @@ -2149,11 +2149,6 @@ namespace Mono.CSharp { this.name = name; } - static void Error_MethodGroupWithTypeArguments (ResolveContext rc, Location loc) - { - rc.Report.Error (8084, loc, "An argument to nameof operator cannot be method group with type arguments"); - } - protected override Expression DoResolve (ResolveContext rc) { throw new NotSupportedException (); @@ -2169,9 +2164,9 @@ namespace Mono.CSharp { rc.Report.FeatureIsNotAvailable (rc.Module.Compiler, Location, "nameof operator"); var res = sn.LookupNameExpression (rc, MemberLookupRestrictions.IgnoreAmbiguity | MemberLookupRestrictions.NameOfExcluded); - if (sn.HasTypeArguments && res is MethodGroupExpr) { - Error_MethodGroupWithTypeArguments (rc, expr.Location); - } + var me = res as MemberExpr; + if (me != null) + me.ResolveNameOf (rc, sn); return true; } @@ -2197,20 +2192,9 @@ namespace Mono.CSharp { return false; } - var mg = res as MethodGroupExpr; - if (mg != null) { - var emg = res as ExtensionMethodGroupExpr; - if (emg != null && !emg.ResolveNameOf (rc, ma)) { - return true; - } - - if (!mg.HasAccessibleCandidate (rc)) { - ErrorIsInaccesible (rc, ma.GetSignatureForError (), loc); - } - - if (ma.HasTypeArguments) { - Error_MethodGroupWithTypeArguments (rc, ma.Location); - } + var me = res as MemberExpr; + if (me != null) { + me.ResolveNameOf (rc, ma); } // diff --git a/mcs/mcs/context.cs b/mcs/mcs/context.cs index b2399c8bd8..33b05ff809 100644 --- a/mcs/mcs/context.cs +++ b/mcs/mcs/context.cs @@ -526,6 +526,19 @@ namespace Mono.CSharp return da; } + public Dictionary> CopyLabelStack () + { + if (LabelStack == null) + return null; + + var dest = new Dictionary> (); + foreach (var entry in LabelStack) { + dest.Add (entry.Key, new List (entry.Value)); + } + + return dest; + } + public bool IsDefinitelyAssigned (VariableInfo variable) { return variable.IsAssigned (DefiniteAssignment); @@ -536,6 +549,11 @@ namespace Mono.CSharp return variable.IsStructFieldAssigned (DefiniteAssignment, name); } + public void SetLabelStack (Dictionary> labelStack) + { + LabelStack = labelStack; + } + public void SetVariableAssigned (VariableInfo variable, bool generatedAssignment = false) { variable.SetAssigned (DefiniteAssignment, generatedAssignment); diff --git a/mcs/mcs/cs-tokenizer.cs b/mcs/mcs/cs-tokenizer.cs index 1915a07240..e6a95fe816 100644 --- a/mcs/mcs/cs-tokenizer.cs +++ b/mcs/mcs/cs-tokenizer.cs @@ -2465,6 +2465,12 @@ namespace Mono.CSharp case '\"': ++str_quote; break; + case '\\': + // Skip escaped " character + c = reader.Read (); + if (c == -1) + res = false; + break; case -1: res = false; break; diff --git a/mcs/mcs/decl.cs b/mcs/mcs/decl.cs index 3f88a5935c..340eb488ab 100644 --- a/mcs/mcs/decl.cs +++ b/mcs/mcs/decl.cs @@ -18,7 +18,7 @@ using System.Diagnostics; using System.Text; using Mono.CompilerServices.SymbolWriter; -#if NET_2_1 +#if MOBILE using XmlElement = System.Object; #else using System.Xml; diff --git a/mcs/mcs/ecore.cs.REMOVED.git-id b/mcs/mcs/ecore.cs.REMOVED.git-id index 5b09343adb..5906c6fa32 100644 --- a/mcs/mcs/ecore.cs.REMOVED.git-id +++ b/mcs/mcs/ecore.cs.REMOVED.git-id @@ -1 +1 @@ -020166ddf94f9f86b0a2c64c968df999e14695e3 \ No newline at end of file +39ee29f1c5df056194e1d3f7e14c8e2577c863cd \ No newline at end of file diff --git a/mcs/mcs/eval.cs b/mcs/mcs/eval.cs index 62c02b1fd5..d4e83a506a 100644 --- a/mcs/mcs/eval.cs +++ b/mcs/mcs/eval.cs @@ -1134,7 +1134,7 @@ namespace Mono.CSharp QuitRequested = true; } -#if !NET_2_1 +#if !MOBILE /// /// Describes an object or a type. /// diff --git a/mcs/mcs/expression.cs.REMOVED.git-id b/mcs/mcs/expression.cs.REMOVED.git-id index 2711680215..69415769ea 100644 --- a/mcs/mcs/expression.cs.REMOVED.git-id +++ b/mcs/mcs/expression.cs.REMOVED.git-id @@ -1 +1 @@ -2a9aa97fed0e62be46728b7c4dccb871de0ff0cc \ No newline at end of file +2968ee08584f544f7869efba43e4007b9f259888 \ No newline at end of file diff --git a/mcs/mcs/generic.cs b/mcs/mcs/generic.cs index b34f2dc1ec..48d2dc01b9 100644 --- a/mcs/mcs/generic.cs +++ b/mcs/mcs/generic.cs @@ -773,6 +773,7 @@ namespace Mono.CSharp { TypeSpec[] targs; TypeSpec[] ifaces_defined; TypeSpec effective_base; + MemberCache interface_cache; // // Creates type owned type parameter @@ -882,6 +883,12 @@ namespace Mono.CSharp { } } + public MemberCache InterfaceCache { + get { + return interface_cache; + } + } + // // Unexpanded interfaces list // @@ -1351,13 +1358,27 @@ namespace Mono.CSharp { // For a type parameter the membercache is the union of the sets of members of the types // specified as a primary constraint or secondary constraint // + bool has_user_base_type = false; if (BaseType.BuiltinType != BuiltinTypeSpec.Type.Object && BaseType.BuiltinType != BuiltinTypeSpec.Type.ValueType) { cache.AddBaseType (BaseType); + has_user_base_type = true; } if (InterfacesDefined != null) { + var icache = cache; + if (has_user_base_type) { + // + // type-parameter lookup rules are more complicated that other types lookup rules. + // Effective base class and its base types member have priority over interface + // constraints which means we cannot lookup interface members before class members + // hence we setup secondary cache for such cases. + // + interface_cache = new MemberCache (); + icache = interface_cache; + } + foreach (var iface_type in InterfacesDefined) { - cache.AddInterface (iface_type); + icache.AddInterface (iface_type); } } @@ -1370,8 +1391,14 @@ namespace Mono.CSharp { var ifaces = tps == null ? ta.Interfaces : tps.InterfacesDefined; if (ifaces != null) { + var icache = cache; + if (has_user_base_type) { + interface_cache = new MemberCache (); + icache = interface_cache; + } + foreach (var iface_type in ifaces) { - cache.AddInterface (iface_type); + icache.AddInterface (iface_type); } } } diff --git a/mcs/mcs/ikvm.cs b/mcs/mcs/ikvm.cs index a7a0cc5e12..14824d136b 100644 --- a/mcs/mcs/ikvm.cs +++ b/mcs/mcs/ikvm.cs @@ -239,6 +239,7 @@ namespace Mono.CSharp readonly List> loaded_names; static readonly Dictionary sdk_directory; Dictionary> resolved_version_mismatches; + static readonly TypeName objectTypeName = new TypeName ("System", "Object"); static StaticLoader () { @@ -257,7 +258,7 @@ namespace Mono.CSharp this.importer = importer; domain = new Universe (UniverseOptions.MetadataOnly | UniverseOptions.ResolveMissingMembers | UniverseOptions.DisableFusion | UniverseOptions.DecodeVersionInfoAttributeBlobs | - UniverseOptions.DeterministicOutput); + UniverseOptions.DeterministicOutput | UniverseOptions.DisableDefaultAssembliesLookup); domain.AssemblyResolve += AssemblyReferenceResolver; loaded_names = new List> (); @@ -355,26 +356,23 @@ namespace Mono.CSharp } if (version_mismatch != null) { - if (version_mismatch is AssemblyBuilder) + if (is_fx_assembly || version_mismatch is AssemblyBuilder) return version_mismatch; var ref_an = new AssemblyName (refname); var v1 = ref_an.Version; var v2 = version_mismatch.GetName ().Version; + AssemblyReferenceMessageInfo messageInfo; if (v1 > v2) { - var messageInfo = new AssemblyReferenceMessageInfo (ref_an, report => { + messageInfo = new AssemblyReferenceMessageInfo (ref_an, report => { report.SymbolRelatedToPreviousError (args.RequestingAssembly.Location); report.Error (1705, string.Format ("Assembly `{0}' depends on `{1}' which has a higher version number than referenced assembly `{2}'", args.RequestingAssembly.FullName, refname, version_mismatch.GetName ().FullName)); }); - AddReferenceVersionMismatch (args.RequestingAssembly.GetName (), messageInfo); - return version_mismatch; - } - - if (!is_fx_assembly) { - var messageInfo = new AssemblyReferenceMessageInfo (ref_an, report => { + } else { + messageInfo = new AssemblyReferenceMessageInfo (ref_an, report => { if (v1.Major != v2.Major || v1.Minor != v2.Minor) { report.Warning (1701, 2, "Assuming assembly reference `{0}' matches assembly `{1}'. You may need to supply runtime policy", @@ -385,10 +383,10 @@ namespace Mono.CSharp refname, version_mismatch.GetName ().FullName); } }); - - AddReferenceVersionMismatch (args.RequestingAssembly.GetName (), messageInfo); } + AddReferenceVersionMismatch (args.RequestingAssembly.GetName (), messageInfo); + return version_mismatch; } @@ -452,10 +450,15 @@ namespace Mono.CSharp return list; } - public override bool HasObjectType (Assembly assembly) + public override Assembly HasObjectType (Assembly assembly) { try { - return assembly.GetType (compiler.BuiltinTypes.Object.FullName) != null; + // System.Object can be forwarded and ikvm + // transparently finds it in target assembly therefore + // need to return actual obj assembly becauase in such + // case it's different to assembly parameter + var obj = assembly.FindType (objectTypeName); + return obj == null ? null : obj.Assembly; } catch (Exception e) { throw new InternalErrorException (e, "Failed to load assembly `{0}'", assembly.FullName); } diff --git a/mcs/mcs/import.cs b/mcs/mcs/import.cs index 60073b9f4c..9518427e1a 100644 --- a/mcs/mcs/import.cs +++ b/mcs/mcs/import.cs @@ -142,6 +142,7 @@ namespace Mono.CSharp compiled_types = new Dictionary (40, ReferenceEquality.Default); assembly_2_definition = new Dictionary (ReferenceEquality.Default); IgnorePrivateMembers = true; + IgnoreCompilerGeneratedField = true; } #region Properties @@ -154,6 +155,8 @@ namespace Mono.CSharp public bool IgnorePrivateMembers { get; set; } + public bool IgnoreCompilerGeneratedField { get; set; } + #endregion public abstract void AddCompiledType (TypeBuilder builder, TypeSpec spec); @@ -179,8 +182,10 @@ namespace Mono.CSharp break; default: // Ignore private fields (even for error reporting) to not require extra dependencies - if ((IgnorePrivateMembers && !declaringType.IsStruct) || - HasAttribute (CustomAttributeData.GetCustomAttributes (fi), "CompilerGeneratedAttribute", CompilerServicesNamespace)) + if (IgnorePrivateMembers && !declaringType.IsStruct) + return null; + + if (IgnoreCompilerGeneratedField && HasAttribute (CustomAttributeData.GetCustomAttributes (fi), "CompilerGeneratedAttribute", CompilerServicesNamespace)) return null; mod = Modifiers.PRIVATE; diff --git a/mcs/mcs/iterators.cs b/mcs/mcs/iterators.cs index 47919ec8ce..0b6fc1abf7 100644 --- a/mcs/mcs/iterators.cs +++ b/mcs/mcs/iterators.cs @@ -254,7 +254,7 @@ namespace Mono.CSharp // Special format which encodes original variable name and // it's scope to support lifted variables debugging. This // is same what csc does and allows to correctly set fields - // scope information (like ambiguity, our of scope, etc). + // scope information (like ambiguity, out of scope, etc). // var id = rc.CurrentBlock.Explicit.GetDebugSymbolScopeIndex (); return "<" + local_info.Name + ">__" + id; @@ -1067,6 +1067,7 @@ namespace Mono.CSharp method.Block = new ToplevelBlock (method.Compiler, method.ParameterInfo, loc, ToplevelBlock.Flags.CompilerGenerated | ToplevelBlock.Flags.NoFlowAnalysis); + method.Block.AddStatement (new TryFinallyBlockProxyStatement (this, block)); // Cannot it add to storey because it'd be emitted before nested diff --git a/mcs/mcs/mcs.csproj b/mcs/mcs/mcs.csproj index 812652f925..74a217c4eb 100644 --- a/mcs/mcs/mcs.csproj +++ b/mcs/mcs/mcs.csproj @@ -22,7 +22,7 @@ prompt 4 false - y.cs + pdbonly diff --git a/mcs/mcs/membercache.cs b/mcs/mcs/membercache.cs index 8ada0a9707..27b7f58693 100644 --- a/mcs/mcs/membercache.cs +++ b/mcs/mcs/membercache.cs @@ -406,8 +406,13 @@ namespace Mono.CSharp { public static MemberSpec FindMember (TypeSpec container, MemberFilter filter, BindingRestriction restrictions) { + if (filter.Kind == MemberKind.Method && container.Kind == MemberKind.TypeParameter && filter.Parameters == null) + throw new NotSupportedException ("type parameters methods cannot be lookup up due to two stage setup"); + + IList applicable; + var top_container = container; + do { - IList applicable; if (container.MemberCache.member_hash.TryGetValue (filter.Name, out applicable)) { // Start from the end because interface members are in reverse order for (int i = applicable.Count - 1; i >= 0; i--) { @@ -438,6 +443,26 @@ namespace Mono.CSharp { container = container.BaseType; } while (container != null); + var tps = top_container as TypeParameterSpec; + if (tps != null && tps.InterfaceCache != null) { + if (tps.InterfaceCache.member_hash.TryGetValue (filter.Name, out applicable)) { + for (int i = applicable.Count - 1; i >= 0; i--) { + var entry = applicable [i]; + + if ((restrictions & BindingRestriction.NoAccessors) != 0 && entry.IsAccessor) + continue; + + if ((restrictions & BindingRestriction.OverrideOnly) != 0 && (entry.Modifiers & Modifiers.OVERRIDE) == 0) + continue; + + if (!filter.Equals (entry)) + continue; + + return entry; + } + } + } + return null; } @@ -450,9 +475,9 @@ namespace Mono.CSharp { // public static IList FindMembers (TypeSpec container, string name, bool declaredOnlyClass) { - IList applicable; - do { + IList applicable; + if (container.MemberCache.member_hash.TryGetValue (name, out applicable) || declaredOnlyClass) return applicable; @@ -462,6 +487,17 @@ namespace Mono.CSharp { return null; } + public static IList FindInterfaceMembers (TypeParameterSpec typeParameter, string name) + { + if (typeParameter.InterfaceCache != null) { + IList applicable; + typeParameter.InterfaceCache.member_hash.TryGetValue (name, out applicable); + return applicable; + } + + return null; + } + // // Finds the nested type in container // diff --git a/mcs/mcs/method.cs b/mcs/mcs/method.cs index e6213c7e43..3adb36f327 100644 --- a/mcs/mcs/method.cs +++ b/mcs/mcs/method.cs @@ -21,7 +21,7 @@ using System.Linq; using Mono.CompilerServices.SymbolWriter; using System.Runtime.CompilerServices; -#if NET_2_1 +#if MOBILE using XmlElement = System.Object; #else using System.Xml; diff --git a/mcs/mcs/property.cs b/mcs/mcs/property.cs index 94e9b6baf0..6b1990e1f0 100644 --- a/mcs/mcs/property.cs +++ b/mcs/mcs/property.cs @@ -17,7 +17,7 @@ using System.Collections.Generic; using System.Text; using Mono.CompilerServices.SymbolWriter; -#if NET_2_1 +#if MOBILE using XmlElement = System.Object; #endif @@ -1210,12 +1210,11 @@ namespace Mono.CSharp backing_field = new Field (Parent, new TypeExpression (MemberType, Location), - Modifiers.BACKING_FIELD | Modifiers.COMPILER_GENERATED | Modifiers.PRIVATE | (ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE)), + Modifiers.BACKING_FIELD | Modifiers.COMPILER_GENERATED | Modifiers.DEBUGGER_HIDDEN | Modifiers.PRIVATE | (ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE)), MemberName, null); Parent.PartialContainer.Members.Add (backing_field); backing_field.Initializer = Initializer; - backing_field.ModFlags &= ~Modifiers.COMPILER_GENERATED; // Call define because we passed fields definition backing_field.Define (); diff --git a/mcs/mcs/reflection.cs b/mcs/mcs/reflection.cs index b233b9439c..c7bcb479db 100644 --- a/mcs/mcs/reflection.cs +++ b/mcs/mcs/reflection.cs @@ -418,7 +418,7 @@ namespace Mono.CSharp default_references.Add ("System"); default_references.Add ("System.Xml"); -#if NET_2_1 +#if MOBILE default_references.Add ("System.Net"); default_references.Add ("System.Windows"); default_references.Add ("System.Windows.Browser"); @@ -440,9 +440,9 @@ namespace Mono.CSharp return Path.GetDirectoryName (typeof (object).Assembly.Location); } - public override bool HasObjectType (Assembly assembly) + public override Assembly HasObjectType (Assembly assembly) { - return assembly.GetType (compiler.BuiltinTypes.Object.FullName) != null; + return assembly.GetType (compiler.BuiltinTypes.Object.FullName) == null ? null : assembly; } public override Assembly LoadAssemblyFile (string assembly, bool isImplicitReference) diff --git a/mcs/mcs/report.cs b/mcs/mcs/report.cs index 74bbb46c64..afa4f75bd8 100644 --- a/mcs/mcs/report.cs +++ b/mcs/mcs/report.cs @@ -61,12 +61,10 @@ namespace Mono.CSharp { 8009, 8094 }; - static HashSet AllWarningsHashSet; - public Report (CompilerContext context, ReportPrinter printer) { if (context == null) - throw new ArgumentNullException ("settings"); + throw new ArgumentNullException ("context"); if (printer == null) throw new ArgumentNullException ("printer"); @@ -175,18 +173,6 @@ namespace Mono.CSharp { extra_information.Add (msg); } - public bool CheckWarningCode (int code, Location loc) - { - if (AllWarningsHashSet == null) - AllWarningsHashSet = new HashSet (AllWarnings); - - if (AllWarningsHashSet.Contains (code)) - return true; - - Warning (1691, 1, loc, "`{0}' is not a valid warning number", code); - return false; - } - public void ExtraInformation (Location loc, string msg) { extra_information.Add (String.Format ("{0} {1}", loc, msg)); @@ -1109,8 +1095,7 @@ namespace Mono.CSharp { public void WarningDisable (Location location, int code, Report Report) { - if (Report.CheckWarningCode (code, location)) - regions.Add (new Disable (location.Row, code)); + regions.Add (new Disable (location.Row, code)); } public void WarningEnable (int line) @@ -1120,9 +1105,6 @@ namespace Mono.CSharp { public void WarningEnable (Location location, int code, CompilerContext context) { - if (!context.Report.CheckWarningCode (code, location)) - return; - if (context.Settings.IsWarningDisabledGlobally (code)) context.Report.Warning (1635, 1, location, "Cannot restore warning `CS{0:0000}' because it was disabled globally", code); diff --git a/mcs/mcs/settings.cs b/mcs/mcs/settings.cs index 0c199017af..cb9365d14d 100644 --- a/mcs/mcs/settings.cs +++ b/mcs/mcs/settings.cs @@ -581,7 +581,6 @@ namespace Mono.CSharp { public bool ProcessWarningsList (string text, Action action) { - bool valid = true; foreach (string wid in text.Split (numeric_value_separator, StringSplitOptions.RemoveEmptyEntries)) { var warning = wid; if (warning.Length == 6 && warning [0] == 'C' && warning [1] == 'S') @@ -592,15 +591,10 @@ namespace Mono.CSharp { continue; } - if (report.CheckWarningCode (id, Location.Null)) { - action (id); - } else { - report.Error (1904, "`{0}' is not a valid warning number", wid); - valid = false; - } + action (id); } - return valid; + return true; } void Error_RequiresArgument (string option) @@ -1215,6 +1209,8 @@ namespace Mono.CSharp { case "/appconfig": case "/baseaddress": case "/deterministic": + case "/deterministic+": + case "/deterministic-": case "/errorendlocation": case "/errorlog": case "/features": @@ -1228,6 +1224,8 @@ namespace Mono.CSharp { case "/pdb": case "/preferreduilang": case "/publicsign": + case "/publicsign+": + case "/publicsign-": case "/reportanalyzer": case "/ruleset": case "/sqmsessionguid": diff --git a/mcs/mcs/statement.cs.REMOVED.git-id b/mcs/mcs/statement.cs.REMOVED.git-id index 8efe91f778..19c1bc8805 100644 --- a/mcs/mcs/statement.cs.REMOVED.git-id +++ b/mcs/mcs/statement.cs.REMOVED.git-id @@ -1 +1 @@ -7f54b33eeb599c16146c7adfcc0c2e12b3d5beaf \ No newline at end of file +75f2b8ed1eb8e49031e9eb5ff5c370c01a61e4e9 \ No newline at end of file diff --git a/mcs/tests/gtest-638.cs b/mcs/tests/gtest-638.cs new file mode 100644 index 0000000000..cadf2725eb --- /dev/null +++ b/mcs/tests/gtest-638.cs @@ -0,0 +1,17 @@ +class X + where T1 : class, T2 + where T2 : class + where U : A, T1 +{ +} + +class A +{ +} + +class F +{ + public static void Main () + { + } +} \ No newline at end of file diff --git a/mcs/tests/gtest-639.cs b/mcs/tests/gtest-639.cs new file mode 100644 index 0000000000..afc0b2004a --- /dev/null +++ b/mcs/tests/gtest-639.cs @@ -0,0 +1,47 @@ +class A where T : CB, IA +{ + void Foo (T t) + { + t.Prop = 3; + long l = t.Prop2; + t["1"] = "2"; + } +} + +class A2 + where T : CB, U + where U : IA +{ + void Foo (T t) + { + t.Prop = 3; + long l = t.Prop2; + t["1"] = "2"; + } +} + +class CB : CA +{ +} + +class CA +{ + public int Prop { get; set; } + + public string this [byte b] { get { return ""; } } +} + +interface IA +{ + string Prop { get; set; } + long Prop2 { get; } + + string this [string b] { get; set; } +} + +class X +{ + public static void Main () + { + } +} \ No newline at end of file diff --git a/mcs/tests/test-254.cs b/mcs/tests/test-254.cs index 1971d2f4e4..36453ea86b 100644 --- a/mcs/tests/test-254.cs +++ b/mcs/tests/test-254.cs @@ -1,5 +1,6 @@ using System; using System.Reflection; +using System.Runtime.CompilerServices; [assembly: Test] @@ -130,7 +131,8 @@ public class ClassMain Assert (ei.GetRemoveMethod ().GetCustomAttributes (true), false, 44); Assert (ei.GetRemoveMethod ().ReturnTypeCustomAttributes.GetCustomAttributes (true), false, 45); FieldInfo fi = typeof(Test_3).GetField ("e_1", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); - Assert (fi.GetCustomAttributes (true), true, 46); + Assert (fi.GetCustomAttributes (typeof (CompilerGeneratedAttribute), true), true, 46); + Assert (fi.GetCustomAttributes (typeof (TestAttribute), true), true, 47); ei = typeof(Test_3).GetEvent ("e_2"); Assert (ei.GetCustomAttributes (true), false, 51); @@ -139,7 +141,8 @@ public class ClassMain Assert (ei.GetRemoveMethod ().GetCustomAttributes (true), true, 54); Assert (ei.GetRemoveMethod ().ReturnTypeCustomAttributes.GetCustomAttributes (true), false, 55); fi = typeof(Test_3).GetField ("e_2", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); - Assert (fi.GetCustomAttributes (true), false, 56); + Assert (fi.GetCustomAttributes (typeof (CompilerGeneratedAttribute), true), true, 56); + Assert (fi.GetCustomAttributes (typeof (TestAttribute), true), false, 57); ei = typeof(Test_4).GetEvent ("e_2"); Assert (ei.GetCustomAttributes (true), false, 71); @@ -148,7 +151,8 @@ public class ClassMain Assert (ei.GetRemoveMethod ().GetCustomAttributes (true), false, 74); Assert (ei.GetRemoveMethod ().ReturnTypeCustomAttributes.GetCustomAttributes (true), true, 75); fi = typeof(Test_3).GetField ("e_2", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); - Assert (fi.GetCustomAttributes (true), false, 76); + Assert (fi.GetCustomAttributes (typeof (CompilerGeneratedAttribute), true), true, 76); + Assert (fi.GetCustomAttributes (typeof (TestAttribute), true), false, 77); ei = typeof(Test_4).GetEvent ("e_3"); Assert (ei.GetCustomAttributes (true), false, 81); @@ -159,7 +163,8 @@ public class ClassMain Assert (ei.GetRemoveMethod ().ReturnTypeCustomAttributes.GetCustomAttributes (true), false, 86); Assert (ei.GetRemoveMethod ().GetParameters ()[0].GetCustomAttributes (true), true, 87); fi = typeof(Test_3).GetField ("e_2", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); - Assert (fi.GetCustomAttributes (true), false, 88); + Assert (fi.GetCustomAttributes (typeof (CompilerGeneratedAttribute), true), true, 86); + Assert (fi.GetCustomAttributes (typeof (TestAttribute), true), false, 87); return failed ? 1 : 0; } diff --git a/mcs/tests/test-937.cs b/mcs/tests/test-937.cs new file mode 100644 index 0000000000..b577d34e7f --- /dev/null +++ b/mcs/tests/test-937.cs @@ -0,0 +1,15 @@ +// Compiler options: /noconfig /nostdlib -r:../class/lib/net_4_x/Facades/System.Runtime.dll -r:../class/lib/net_4_x/mscorlib.dll + +using System; + +class TypeForwarderOfSystemObject +{ + void TestAttributeReadDoesNotCrash () + { + System.Runtime.InteropServices.Marshal.ReadByte (IntPtr.Zero, 0); + } + + static void Main () + { + } +} diff --git a/mcs/tests/test-940.cs b/mcs/tests/test-940.cs new file mode 100644 index 0000000000..d7c68f0e34 --- /dev/null +++ b/mcs/tests/test-940.cs @@ -0,0 +1,31 @@ +// Compiler options: -unsafe + +using System; + +struct nint +{ + public static nint operator * (nint a, nint b) + { + return a; + } + + public static implicit operator long (nint v) + { + return 0; + } +} + +class X +{ + public static void Main () + { + nint width; + nint bytesPerRow; + + unsafe { + var da = (uint*)0; + var dp1 = da + width * bytesPerRow; + var dp2 = width * bytesPerRow + da; + } + } +} \ No newline at end of file diff --git a/mcs/tests/test-941.cs b/mcs/tests/test-941.cs new file mode 100644 index 0000000000..f5d90c046f --- /dev/null +++ b/mcs/tests/test-941.cs @@ -0,0 +1,30 @@ +public class GotoCodeFlowBug +{ + public static void Test (bool cond, out int x) + { + if (cond) + { + goto Label; + } + Label: + x = 0; + } + + public static void Test2 (bool cond, out int x) + { + if (cond) + { + goto Label; + } + else + { + goto Label; + } + Label: + x = 0; + } + + public static void Main () + { + } +} \ No newline at end of file diff --git a/mcs/tests/test-debug-11-ref.xml b/mcs/tests/test-debug-11-ref.xml index db740c2456..d14a377f00 100644 --- a/mcs/tests/test-debug-11-ref.xml +++ b/mcs/tests/test-debug-11-ref.xml @@ -378,8 +378,7 @@ - - + @@ -401,8 +400,7 @@ - - + @@ -423,8 +421,7 @@ - - + @@ -446,8 +443,7 @@ - - + diff --git a/mcs/tests/test-debug-21-ref.xml b/mcs/tests/test-debug-21-ref.xml index 3958eb589f..41445be8ce 100644 --- a/mcs/tests/test-debug-21-ref.xml +++ b/mcs/tests/test-debug-21-ref.xml @@ -83,7 +83,8 @@ - + + diff --git a/mcs/tests/test-debug-28-ref.xml b/mcs/tests/test-debug-28-ref.xml index 1038be00dd..c823a34e29 100644 --- a/mcs/tests/test-debug-28-ref.xml +++ b/mcs/tests/test-debug-28-ref.xml @@ -28,9 +28,7 @@ - - - + diff --git a/mcs/tests/test-debug-31-ref.xml b/mcs/tests/test-debug-31-ref.xml new file mode 100644 index 0000000000..1a77894386 --- /dev/null +++ b/mcs/tests/test-debug-31-ref.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/mcs/tests/test-debug-31.cs b/mcs/tests/test-debug-31.cs new file mode 100644 index 0000000000..5a3d55de82 --- /dev/null +++ b/mcs/tests/test-debug-31.cs @@ -0,0 +1,25 @@ +using System; + +namespace cp534534 +{ + class MainClass + { + public static void Main () + { + var array = new string[] { "a", "b", "c" }; + + foreach (var item in array) + { + Console.WriteLine (item); + } + + foreach (var item1 in array) { + Console.WriteLine (item1); + } + + foreach (var item2 in array) { + Console.WriteLine (item2); + } + } + } +} \ No newline at end of file diff --git a/mcs/tests/test-debug-32-ref.xml b/mcs/tests/test-debug-32-ref.xml new file mode 100644 index 0000000000..acabcfb38a --- /dev/null +++ b/mcs/tests/test-debug-32-ref.xml @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/mcs/tests/test-debug-32.cs b/mcs/tests/test-debug-32.cs new file mode 100644 index 0000000000..ba52a104c1 --- /dev/null +++ b/mcs/tests/test-debug-32.cs @@ -0,0 +1,21 @@ +using System.Collections.Generic; + +class X +{ + internal static IEnumerable EnumerateKind () + { + yield return 1; + + int h = 3; + try { + yield return h; + } finally { + if (h != 1) { + } + } + } + + public static void Main () + { + } +} \ No newline at end of file diff --git a/mcs/tests/test-interpolation-05.cs b/mcs/tests/test-interpolation-05.cs index 3dd99f5f27..4cf2e64196 100644 --- a/mcs/tests/test-interpolation-05.cs +++ b/mcs/tests/test-interpolation-05.cs @@ -13,6 +13,13 @@ public class ParserTest Console.WriteLine($"This should work but the compiler explodes if the string is too long!"); } + void Test3 () + { + string field = ""; + var l1 = $"\"{field.Replace("\"", "gg")}\""; + var l2 = $@"""{field.Replace("\"", "gg")}"""; + } + public static void Main() { } diff --git a/mcs/tests/test-iter-23.cs b/mcs/tests/test-iter-23.cs index cf1b181359..3dd524c496 100644 --- a/mcs/tests/test-iter-23.cs +++ b/mcs/tests/test-iter-23.cs @@ -5,6 +5,7 @@ using System.Threading; class X { static ManualResetEvent dispose = new ManualResetEvent (false); + static ManualResetEvent wait = new ManualResetEvent (false); static IEnumerable GetIt2 () { @@ -15,7 +16,7 @@ class X static int Delay () { dispose.Set (); - Thread.Sleep (10); + wait.WaitOne (); return 1; } @@ -25,6 +26,7 @@ class X ThreadPool.QueueUserWorkItem (l => { dispose.WaitOne (); ((IDisposable) e).Dispose (); + wait.Set (); }); if (!e.MoveNext ()) diff --git a/mcs/tests/test-named-10.cs b/mcs/tests/test-named-10.cs new file mode 100644 index 0000000000..6434c83661 --- /dev/null +++ b/mcs/tests/test-named-10.cs @@ -0,0 +1,18 @@ +using System; + +internal class Program +{ + public static void Main () + { + Method (1, 2, paramNamed: 3); + } + + static void Method (int p1, int paramNamed, int p2) + { + throw new ApplicationException (); + } + + static void Method (int p1, int p2, object paramNamed) + { + } +} diff --git a/mcs/tests/test-partial-35.cs b/mcs/tests/test-partial-35.cs new file mode 100644 index 0000000000..ba512452fe --- /dev/null +++ b/mcs/tests/test-partial-35.cs @@ -0,0 +1,19 @@ +partial class A +{ +} + +partial class A +{ + enum E + { + None = 0, + All = 1 + } +} + +class X +{ + public static void Main () + { + } +} \ No newline at end of file diff --git a/mcs/tests/ver-il-net_4_x.xml.REMOVED.git-id b/mcs/tests/ver-il-net_4_x.xml.REMOVED.git-id index 52d7c901c4..1711680d46 100644 --- a/mcs/tests/ver-il-net_4_x.xml.REMOVED.git-id +++ b/mcs/tests/ver-il-net_4_x.xml.REMOVED.git-id @@ -1 +1 @@ -216a310da0866d4efac81f4c8a3bcdc849ad8891 \ No newline at end of file +f9c8f8b2465c7c00ddc1831c311422c9785ad594 \ No newline at end of file diff --git a/mcs/tools/Makefile b/mcs/tools/Makefile index 693318cbea..af120d403e 100644 --- a/mcs/tools/Makefile +++ b/mcs/tools/Makefile @@ -47,7 +47,8 @@ net_4_5_dirs := \ mdbrebase \ ikdasm \ mono-symbolicate \ - linker-analyzer + linker-analyzer \ + btls build_SUBDIRS = gacutil security culevel cil-stringreplacer commoncryptogenerator net_4_5_SUBDIRS = gacutil diff --git a/mcs/tools/al/Al.cs b/mcs/tools/al/Al.cs index bdc741144e..3670d2f2eb 100644 --- a/mcs/tools/al/Al.cs +++ b/mcs/tools/al/Al.cs @@ -13,14 +13,13 @@ using System.Globalization; using System.IO; using System.Collections; using System.Collections.Generic; -using System.Reflection; -using System.Reflection.Emit; using System.Security.Cryptography; using System.Text; using System.Configuration.Assemblies; +using IKVM.Reflection; +using IKVM.Reflection.Emit; using Mono.Security.Cryptography; -using IKR = IKVM.Reflection; namespace Mono.AssemblyLinker { @@ -49,6 +48,15 @@ namespace Mono.AssemblyLinker No } + public enum Platform { + AnyCPU, + AnyCPU32Preferred, + Arm, + X86, + X64, + IA64 + } + public class AssemblyLinker { ArrayList inputFiles = new ArrayList (); @@ -59,24 +67,35 @@ namespace Mono.AssemblyLinker string entryPoint; string win32IconFile; string win32ResFile; + string title; + string description; + string company; + string product; + string copyright; + string trademark; string templateFile; bool isTemplateFile = false; Target target = Target.Dll; + Platform platform = Platform.AnyCPU; DelaySign delaysign = DelaySign.NotSet; string keyfile; string keyname; string culture; + Universe universe; public static int Main (String[] args) { return new AssemblyLinker ().DynMain (args); } private int DynMain (String[] args) { - ParseArgs (args); + using (universe = new Universe (UniverseOptions.MetadataOnly)) { + universe.LoadFile (typeof (object).Assembly.Location); + ParseArgs (args); - DoIt (); + DoIt (); - return 0; + return 0; + } } private void ParseArgs (string[] args) @@ -211,7 +230,7 @@ namespace Mono.AssemblyLinker if (realArg.StartsWith ("0x")) realArg = realArg.Substring (2); uint val = Convert.ToUInt32 (realArg, 16); - AddCattr (typeof (AssemblyAlgorithmIdAttribute), typeof (uint), val); + AddCattr (typeof (System.Reflection.AssemblyAlgorithmIdAttribute), typeof (uint), val); } catch (Exception) { ReportInvalidArgument (opt, arg); } @@ -233,21 +252,21 @@ namespace Mono.AssemblyLinker case "company": if (arg == null) ReportMissingText (opt); - AddCattr (typeof (AssemblyCompanyAttribute), arg); + company = arg; return true; case "config": case "configuration": if (arg == null) ReportMissingText (opt); - AddCattr (typeof (AssemblyConfigurationAttribute), arg); + AddCattr (typeof (System.Reflection.AssemblyConfigurationAttribute), arg); return true; case "copy": case "copyright": if (arg == null) ReportMissingText (opt); - AddCattr (typeof (AssemblyCopyrightAttribute), arg); + copyright = arg; return true; case "c": @@ -273,7 +292,7 @@ namespace Mono.AssemblyLinker case "description": if (arg == null) ReportMissingText (opt); - AddCattr (typeof (AssemblyDescriptionAttribute), arg); + description = arg; return true; case "e": @@ -292,7 +311,7 @@ namespace Mono.AssemblyLinker if (arg == null) ReportMissingText (opt); - AddCattr (typeof (AssemblyFileVersionAttribute), arg); + AddCattr (typeof (System.Reflection.AssemblyFileVersionAttribute), arg); return true; case "flags": @@ -303,7 +322,7 @@ namespace Mono.AssemblyLinker if (realArg.StartsWith ("0x")) realArg = realArg.Substring (2); uint val = Convert.ToUInt32 (realArg, 16); - AddCattr (typeof (AssemblyFlagsAttribute), typeof (uint), val); + AddCattr (typeof (System.Reflection.AssemblyFlagsAttribute), typeof (uint), val); } catch (Exception) { ReportInvalidArgument (opt, arg); } @@ -342,18 +361,46 @@ namespace Mono.AssemblyLinker outFile = arg; return true; + case "platform": + if (arg == null) + ReportMissingText (opt); + switch (arg.ToLowerInvariant ()) { + case "arm": + platform = Platform.Arm; + break; + case "anycpu": + platform = Platform.AnyCPU; + break; + case "x86": + platform = Platform.X86; + break; + case "x64": + platform = Platform.X64; + break; + case "itanium": + platform = Platform.IA64; + break; + case "anycpu32bitpreferred": + platform = Platform.AnyCPU32Preferred; + break; + default: + ReportInvalidArgument (opt, arg); + break; + } + return true; + case "prod": case "product": if (arg == null) ReportMissingText (opt); - AddCattr (typeof (AssemblyProductAttribute), arg); + product = arg; return true; case "productv": case "productversion": if (arg == null) ReportMissingText (opt); - AddCattr (typeof (AssemblyInformationalVersionAttribute), arg); + AddCattr (typeof (System.Reflection.AssemblyInformationalVersionAttribute), arg); return true; case "t": @@ -388,14 +435,14 @@ namespace Mono.AssemblyLinker case "title": if (arg == null) ReportMissingText (opt); - AddCattr (typeof (AssemblyTitleAttribute), arg); + title = arg; return true; case "trade": case "trademark": if (arg == null) ReportMissingText (opt); - AddCattr (typeof (AssemblyTrademarkAttribute), arg); + trademark = arg; return true; case "v": @@ -405,7 +452,7 @@ namespace Mono.AssemblyLinker Version (); break; } - AddCattr (typeof (AssemblyVersionAttribute), arg); + AddCattr (typeof (System.Reflection.AssemblyVersionAttribute), arg); return true; case "win32icon": @@ -461,11 +508,14 @@ namespace Mono.AssemblyLinker return command.ToLower (); } - private void AddCattr (Type attrType, Type arg, object value) { - cattrs.Add (new CustomAttributeBuilder (attrType.GetConstructor (new Type [] { arg }), new object [] { value })); + private void AddCattr (System.Type attrType, System.Type arg, object value) { + var importedAttrType = universe.Import(attrType); + var importedArg = universe.Import(arg); + + cattrs.Add (new CustomAttributeBuilder (importedAttrType.GetConstructor (new [] { importedArg }), new [] { value })); } - private void AddCattr (Type attrType, object value) { + private void AddCattr (System.Type attrType, object value) { AddCattr (attrType, typeof (string), value); } @@ -596,12 +646,25 @@ namespace Mono.AssemblyLinker if (isTemplateFile) aname = ReadCustomAttributesFromTemplateFile (templateFile, aname); + if (!String.IsNullOrEmpty (title)) + AddCattr (typeof (System.Reflection.AssemblyTitleAttribute), title); + if (!String.IsNullOrEmpty (description)) + AddCattr (typeof (System.Reflection.AssemblyDescriptionAttribute), description); + if (!String.IsNullOrEmpty (company)) + AddCattr (typeof (System.Reflection.AssemblyCompanyAttribute), company); + if (!String.IsNullOrEmpty (product)) + AddCattr (typeof (System.Reflection.AssemblyProductAttribute), product); + if (!String.IsNullOrEmpty (copyright)) + AddCattr (typeof (System.Reflection.AssemblyCopyrightAttribute), copyright); + if (!String.IsNullOrEmpty (trademark)) + AddCattr (typeof (System.Reflection.AssemblyTrademarkAttribute), trademark); + SetKeyPair (aname); if (fileName != outFile) - ab = AppDomain.CurrentDomain.DefineDynamicAssembly (aname, AssemblyBuilderAccess.Save, Path.GetDirectoryName (outFile)); + ab = universe.DefineDynamicAssembly (aname, AssemblyBuilderAccess.Save, Path.GetDirectoryName (outFile)); else - ab = AppDomain.CurrentDomain.DefineDynamicAssembly (aname, AssemblyBuilderAccess.Save); + ab = universe.DefineDynamicAssembly (aname, AssemblyBuilderAccess.Save); foreach (CustomAttributeBuilder cb in cattrs) ab.SetCustomAttribute (cb); @@ -611,10 +674,6 @@ namespace Mono.AssemblyLinker */ foreach (ModuleInfo mod in inputFiles) { - MethodInfo mi = typeof (AssemblyBuilder).GetMethod ("AddModule", BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic); - if (mi == null) - Report (0, "Cannot add modules on this runtime: try the Mono runtime instead."); - if (mod.target != null) { File.Copy (mod.fileName, mod.target, true); mod.fileName = mod.target; @@ -631,7 +690,7 @@ namespace Mono.AssemblyLinker if (isAssembly) ReportWarning (1020, "Ignoring included assembly '" + mod.fileName + "'"); else - mi.Invoke (ab, new object [] { mod.fileName }); + ab.__AddModule (universe.OpenRawModule(mod.fileName)); } /* @@ -645,7 +704,7 @@ namespace Mono.AssemblyLinker MethodInfo mainMethodInfo = null; try { - Type mainType = ab.GetType (mainClass); + IKVM.Reflection.Type mainType = ab.GetType (mainClass); if (mainType != null) mainMethodInfo = mainType.GetMethod (mainMethod); } @@ -666,10 +725,7 @@ namespace Mono.AssemblyLinker if (win32IconFile != null) { try { - MethodInfo mi = typeof (AssemblyBuilder).GetMethod ("DefineIconResource", BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic); - if (mi == null) - Report (0, "Cannot embed win32 icons on this runtime: try the Mono runtime instead."); - mi.Invoke (ab, new object [] { win32IconFile }); + ab.__DefineIconResource (File.ReadAllBytes (win32IconFile)); } catch (Exception ex) { Report (1031, "Error reading icon '" + win32IconFile + "' --" + ex); @@ -685,6 +741,8 @@ namespace Mono.AssemblyLinker } } + ModuleBuilder mainModule = null; + foreach (ResourceInfo res in resources) { if (res.name == null) res.name = Path.GetFileName (res.fileName); @@ -694,11 +752,13 @@ namespace Mono.AssemblyLinker Report (1046, String.Format ("Resource identifier '{0}' has already been used in this assembly", res.name)); if (res.isEmbedded) { - MethodInfo mi = typeof (AssemblyBuilder).GetMethod ("EmbedResourceFile", BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic, - null, CallingConventions.Any, new Type [] { typeof (string), typeof (string) }, null); - if (mi == null) - Report (0, "Cannot embed resources on this runtime: try the Mono runtime instead."); - mi.Invoke (ab, new object [] { res.name, res.fileName }); + if (mainModule == null) { + mainModule = ab.DefineDynamicModule (fileName, fileName, false); + } + + Stream stream = new MemoryStream (File.ReadAllBytes (res.fileName)); + + mainModule.DefineManifestResource (res.name, stream, res.isPrivate ? ResourceAttributes.Private : ResourceAttributes.Public); } else { if (res.target != null) { @@ -721,8 +781,36 @@ namespace Mono.AssemblyLinker } } + PortableExecutableKinds pekind = PortableExecutableKinds.ILOnly; + ImageFileMachine machine; + + switch (platform) { + case Platform.X86: + pekind |= PortableExecutableKinds.Required32Bit; + machine = ImageFileMachine.I386; + break; + case Platform.X64: + pekind |= PortableExecutableKinds.PE32Plus; + machine = ImageFileMachine.AMD64; + break; + case Platform.IA64: + machine = ImageFileMachine.IA64; + break; + case Platform.AnyCPU32Preferred: + pekind |= PortableExecutableKinds.Preferred32Bit; + machine = ImageFileMachine.I386; + break; + case Platform.Arm: + machine = ImageFileMachine.ARM; + break; + case Platform.AnyCPU: + default: + machine = ImageFileMachine.I386; + break; + } + try { - ab.Save (fileName); + ab.Save (fileName, pekind, machine); } catch (Exception ex) { Report (1019, "Metadata failure creating assembly -- " + ex); @@ -733,17 +821,14 @@ namespace Mono.AssemblyLinker { // LAMESPEC: according to MSDN, the template assembly must have a // strong name but this is not enforced - const IKR.UniverseOptions options = IKR.UniverseOptions.MetadataOnly; - - var universe = new IKR.Universe (options); var asm = universe.LoadFile (templateFile); // Create missing assemblies, we don't want to load them! // Code taken from ikdasm var names = new HashSet (); - IKR.AssemblyName[] assembly_refs = asm.ManifestModule.__GetReferencedAssemblies (); + AssemblyName[] assembly_refs = asm.ManifestModule.__GetReferencedAssemblies (); - var resolved_assemblies = new IKR.Assembly [assembly_refs.Length]; + var resolved_assemblies = new Assembly [assembly_refs.Length]; for (int i = 0; i < resolved_assemblies.Length; i++) { string name = assembly_refs [i].Name; @@ -798,6 +883,85 @@ namespace Mono.AssemblyLinker keyname = key_name_value; } break; + + case "System.Reflection.AssemblyTitleAttribute": { + if (title != null) + // ignore if specified on command line + continue; + + // AssemblyTitleAttribute .ctor(string title) + string title_value = (string) attr_data.ConstructorArguments [0].Value; + + if (!String.IsNullOrEmpty (title_value)) + title = title_value; + } + break; + + case "System.Reflection.AssemblyDescriptionAttribute": { + if (description != null) + // ignore if specified on command line + continue; + + // AssemblyDescriptionAttribute .ctor(string description) + string description_value = (string) attr_data.ConstructorArguments [0].Value; + + if (!String.IsNullOrEmpty (description_value)) + description = description_value; + } + break; + + case "System.Reflection.AssemblyProductAttribute": { + if (product != null) + // ignore if specified on command line + continue; + + // AssemblyProductAttribute .ctor(string product) + string product_value = (string) attr_data.ConstructorArguments [0].Value; + + if (!String.IsNullOrEmpty (product_value)) + product = product_value; + } + break; + + case "System.Reflection.AssemblyCompanyAttribute": { + if (company != null) + // ignore if specified on command line + continue; + + // AssemblyCompanyAttribute .ctor(string company) + string company_value = (string) attr_data.ConstructorArguments [0].Value; + + if (!String.IsNullOrEmpty (company_value)) + company = company_value; + + } + break; + + case "System.Reflection.AssemblyCopyrightAttribute": { + if (copyright != null) + // ignore if specified on command line + continue; + + // AssemblyCopyrightAttribute .ctor(string copyright) + string copyright_value = (string) attr_data.ConstructorArguments [0].Value; + + if (!String.IsNullOrEmpty (copyright_value)) + copyright = copyright_value; + } + break; + + case "System.Reflection.AssemblyTrademarkAttribute": { + if (trademark != null) + // ignore if specified on command line + continue; + + // AssemblyTrademarkAttribute .ctor(string trademark) + string trademark_value = (string) attr_data.ConstructorArguments [0].Value; + + if (!String.IsNullOrEmpty (trademark_value)) + trademark = trademark_value; + } + break; } } @@ -877,6 +1041,9 @@ namespace Mono.AssemblyLinker " /main: Specifies the method name of the entry point", " /nologo Suppress the startup banner and copyright message", " /out: Output file name for the assembly manifest", + " /platform: Limit which platforms this code can run on; must be", + " one of x86, Itanium, x64, arm, anycpu32bitpreferred,", + " or anycpu (the default)", " /prod[uct]: Product name", " /productv[ersion]: Product version", " /t[arget]:lib[rary] Create a library", diff --git a/mcs/tools/btls/AssemblyInfo.cs b/mcs/tools/btls/AssemblyInfo.cs new file mode 100644 index 0000000000..06f8d61c8d --- /dev/null +++ b/mcs/tools/btls/AssemblyInfo.cs @@ -0,0 +1,26 @@ +using System; +using System.Diagnostics; +using System.Reflection; +using System.Resources; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle ("btls-cert-sync")] +[assembly: AssemblyDescription ("btls-cert-sync")] +[assembly: AssemblyDefaultAlias ("btls-cert-sync")] + +[assembly: AssemblyCompany (Consts.MonoCompany)] +[assembly: AssemblyProduct (Consts.MonoProduct)] +[assembly: AssemblyCopyright (Consts.MonoCopyright)] +[assembly: AssemblyVersion (Consts.FxVersion)] +[assembly: AssemblyFileVersion (Consts.FxFileVersion)] +[assembly: SatelliteContractVersion (Consts.FxVersion)] +[assembly: AssemblyInformationalVersion (Consts.FxFileVersion)] + +[assembly: CLSCompliant (true)] +[assembly: NeutralResourcesLanguage ("en-US")] + +[assembly: ComVisible (false)] + +[assembly: AssemblyDelaySign (true)] +[assembly: AssemblyKeyFile ("../../class/mono.pub")] diff --git a/mcs/tools/btls/Makefile b/mcs/tools/btls/Makefile new file mode 100644 index 0000000000..b551fa782c --- /dev/null +++ b/mcs/tools/btls/Makefile @@ -0,0 +1,17 @@ +thisdir = tools/btls +SUBDIRS = +include ../../build/rules.make + +LOCAL_MCS_FLAGS = +LIB_REFS = System Mono.Security Mono.Btls.Interface +PROGRAM = btls-cert-sync.exe + +ifndef HAVE_BTLS +PROGRAM_NAME = dummy-btls-cert-sync.exe +NO_INSTALL = yes +NO_SIGN_ASSEMBLY = yes +NO_TEST = yes +NO_BUILD = yes +endif + +include ../../build/executable.make diff --git a/mcs/tools/btls/btls-cert-sync.cs b/mcs/tools/btls/btls-cert-sync.cs new file mode 100644 index 0000000000..fcdc708e0a --- /dev/null +++ b/mcs/tools/btls/btls-cert-sync.cs @@ -0,0 +1,61 @@ +using System; +using System.IO; +using System.Text; +using System.Security.Cryptography.X509Certificates; +using MNS = Mono.Net.Security; + +namespace Mono.Btls +{ + static class BtlsCertSync + { + static void Main (string[] args) + { + if (!MNS.MonoTlsProviderFactory.IsBtlsSupported ()) { + Console.Error.WriteLine ("BTLS is not supported in this runtime!"); + Environment.Exit (255); + } + + var configPath = Environment.GetFolderPath (Environment.SpecialFolder.ApplicationData); + configPath = Path.Combine (configPath, ".mono"); + + var oldStorePath = Path.Combine (configPath, "certs", "Trust"); + var newStorePath = MonoBtlsX509StoreManager.GetStorePath (MonoBtlsX509StoreType.UserTrustedRoots); + + if (!Directory.Exists (oldStorePath)) { + Console.WriteLine ("Old trust store {0} does not exist."); + Environment.Exit (255); + } + + if (Directory.Exists (newStorePath)) + Directory.Delete (newStorePath, true); + Directory.CreateDirectory (newStorePath); + + var oldfiles = Directory.GetFiles (oldStorePath, "*.cer"); + Console.WriteLine ("Found {0} files in the old store.", oldfiles.Length); + + foreach (var file in oldfiles) { + Console.WriteLine ("Converting {0}.", file); + var data = File.ReadAllBytes (file); + using (var x509 = MonoBtlsX509.LoadFromData (data, MonoBtlsX509Format.DER)) { + ConvertToNewFormat (newStorePath, x509); + } + } + } + + static void ConvertToNewFormat (string root, MonoBtlsX509 x509) + { + long hash = x509.GetSubjectNameHash (); + + string newName; + int index = 0; + do { + newName = Path.Combine (root, string.Format ("{0:x8}.{1}", hash, index++)); + } while (File.Exists (newName)); + Console.WriteLine (" new name: {0}", newName); + + using (var stream = new FileStream (newName, FileMode.Create)) + using (var bio = MonoBtlsBio.CreateMonoStream (stream)) + x509.ExportAsPEM (bio, true); + } + } +} diff --git a/mcs/tools/btls/btls-cert-sync.exe.sources b/mcs/tools/btls/btls-cert-sync.exe.sources new file mode 100644 index 0000000000..706d78f894 --- /dev/null +++ b/mcs/tools/btls/btls-cert-sync.exe.sources @@ -0,0 +1,4 @@ +../../build/common/SR.cs +../../build/common/Consts.cs +AssemblyInfo.cs +btls-cert-sync.cs diff --git a/mcs/tools/cil-stringreplacer/cil-stringreplacer.cs b/mcs/tools/cil-stringreplacer/cil-stringreplacer.cs index 2414206c69..a7803c0ea1 100644 --- a/mcs/tools/cil-stringreplacer/cil-stringreplacer.cs +++ b/mcs/tools/cil-stringreplacer/cil-stringreplacer.cs @@ -100,33 +100,34 @@ public class Program static void RewriteAssembly (string assemblyLocation, Dictionary resourcesStrings, CmdOptions options) { - var readerParameters = new ReaderParameters { ReadSymbols = true }; - var assembly = AssemblyDefinition.ReadAssembly (assemblyLocation, readerParameters); - foreach (var module in assembly.Modules) { - foreach (var type in module.GetTypes ()) { - foreach (var method in type.Methods) { - if (!method.HasBody) - continue; - - foreach (var instr in method.Body.Instructions) { - if (instr.OpCode != OpCodes.Ldstr) + var readerParameters = new ReaderParameters { ReadSymbols = true, ReadWrite = true }; + using (var assembly = AssemblyDefinition.ReadAssembly (assemblyLocation, readerParameters)) { + foreach (var module in assembly.Modules) { + foreach (var type in module.GetTypes ()) { + foreach (var method in type.Methods) { + if (!method.HasBody) continue; + + foreach (var instr in method.Body.Instructions) { + if (instr.OpCode != OpCodes.Ldstr) + continue; - string value; - if (resourcesStrings.TryGetValue ((string)instr.Operand, out value)) { - if (options.Verbose) { - Console.WriteLine ($"Replacing '{instr.Operand}' with '{value}'"); + string value; + if (resourcesStrings.TryGetValue ((string)instr.Operand, out value)) { + if (options.Verbose) { + Console.WriteLine ($"Replacing '{instr.Operand}' with '{value}'"); + } + + instr.Operand = value; } - - instr.Operand = value; } } } } - } - var writerParameters = new WriterParameters { WriteSymbols = true }; - assembly.Write (assemblyLocation, writerParameters); + var writerParameters = new WriterParameters { WriteSymbols = true }; + assembly.Write (writerParameters); + } } static bool LoadGetResourceStrings (Dictionary resourcesStrings, CmdOptions options) diff --git a/mcs/tools/commoncryptogenerator/CommonCryptorGenerator.cs b/mcs/tools/commoncryptogenerator/CommonCryptorGenerator.cs index f177c17ef3..b9262adae0 100644 --- a/mcs/tools/commoncryptogenerator/CommonCryptorGenerator.cs +++ b/mcs/tools/commoncryptogenerator/CommonCryptorGenerator.cs @@ -14,7 +14,7 @@ namespace Xamarin { public static class CommonCryptor { - static public void Generate (string namespaceName, string typeName, string baseTypeName, string ccAlgorithmName, string feedbackSize = "8", string ctorInitializers = null) + static public void Generate (string namespaceName, string typeName, string baseTypeName, string ccAlgorithmName, string feedbackSize = "8", string ctorInitializers = null, string decryptorInitializers = null, string encryptorInitializers = null, string properties = null) { string template = @"// Generated file to bind CommonCrypto cipher algorithms - DO NOT EDIT // @@ -38,7 +38,9 @@ namespace %NAMESPACE% { FeedbackSizeValue = %FEEDBACKSIZE%; %CTOR_INIT% } - + + %PROPERTIES% + public override void GenerateIV () { IVValue = KeyBuilder.IV (BlockSizeValue >> 3); @@ -51,6 +53,8 @@ namespace %NAMESPACE% { public override ICryptoTransform CreateDecryptor (byte[] rgbKey, byte[] rgbIV) { + %CREATEDECRYPTOR_INIT% + IntPtr decryptor = IntPtr.Zero; switch (Mode) { case CipherMode.CBC: @@ -74,6 +78,8 @@ namespace %NAMESPACE% { public override ICryptoTransform CreateEncryptor (byte[] rgbKey, byte[] rgbIV) { + %CREATEENCRYPTOR_INIT% + IntPtr encryptor = IntPtr.Zero; switch (Mode) { case CipherMode.CBC: @@ -98,6 +104,9 @@ namespace %NAMESPACE% { File.WriteAllText (typeName + ".g.cs", template.Replace ("%NAMESPACE%", namespaceName). Replace ("%TYPE%", typeName).Replace ("%BASE%", baseTypeName).Replace("%FEEDBACKSIZE%", feedbackSize).Replace ("%CTOR_INIT%", ctorInitializers). + Replace ("%CREATEDECRYPTOR_INIT%", decryptorInitializers). + Replace ("%CREATEENCRYPTOR_INIT%", encryptorInitializers). + Replace ("%PROPERTIES%", properties). Replace ("%CCALGORITHM%", ccAlgorithmName.ToString ())); } } diff --git a/mcs/tools/commoncryptogenerator/generator.cs b/mcs/tools/commoncryptogenerator/generator.cs index a7d13c8cb8..4fb846fe8f 100644 --- a/mcs/tools/commoncryptogenerator/generator.cs +++ b/mcs/tools/commoncryptogenerator/generator.cs @@ -42,7 +42,13 @@ namespace Xamarin { // mscorlib replacements CommonCryptor.Generate ("System.Security.Cryptography", "DESCryptoServiceProvider", "DES", "DES"); CommonCryptor.Generate ("System.Security.Cryptography", "TripleDESCryptoServiceProvider", "TripleDES", "TripleDES"); - CommonCryptor.Generate ("System.Security.Cryptography", "RC2CryptoServiceProvider", "RC2", "RC2", ctorInitializers: "LegalKeySizesValue = new[] { new KeySizes(40, 128, 8) };"); + + const string checkUseSalt = "if (UseSalt) throw new NotImplementedException (\"UseSalt=true is not implemented on Mono yet\");"; + CommonCryptor.Generate ("System.Security.Cryptography", "RC2CryptoServiceProvider", "RC2", "RC2", + ctorInitializers: "LegalKeySizesValue = new[] { new KeySizes(40, 128, 8) };", + decryptorInitializers: checkUseSalt, + encryptorInitializers: checkUseSalt, + properties: "public bool UseSalt { get; set; }"); // Rijndael supports block sizes that are not available in AES - as such it does not use the same generated code // but has it's own version, using AES (128 bits block size) and falling back to managed (192/256 bits block size) diff --git a/mcs/tools/compiler-tester/compiler-tester.cs b/mcs/tools/compiler-tester/compiler-tester.cs index ec7e9dfc25..265f702ab6 100644 --- a/mcs/tools/compiler-tester/compiler-tester.cs +++ b/mcs/tools/compiler-tester/compiler-tester.cs @@ -91,7 +91,7 @@ namespace TestRunner { } } -#if !NET_2_1 +#if !MOBILE class ProcessTester: ITester { ProcessStartInfo pi; @@ -734,7 +734,7 @@ namespace TestRunner { bool update_verif_file; Hashtable verif_data; -#if !NET_2_1 +#if !MOBILE ProcessStartInfo pi; #endif readonly string mono; @@ -756,7 +756,7 @@ namespace TestRunner { files_folder = Directory.GetCurrentDirectory (); this.verif_file = verif_file; -#if !NET_2_1 +#if !MOBILE pi = new ProcessStartInfo (); pi.CreateNoWindow = true; pi.WindowStyle = ProcessWindowStyle.Hidden; @@ -965,7 +965,7 @@ namespace TestRunner { string filename = test.FileName; AppDomain domain = null; -#if !NET_2_1 +#if !MOBILE if (safe_execution) { // Create a new AppDomain, with the current directory as the base. AppDomainSetup setupInfo = new AppDomainSetup (); @@ -977,7 +977,7 @@ namespace TestRunner { try { DomainTester tester; try { -#if !NET_2_1 +#if !MOBILE if (domain != null) tester = (DomainTester) domain.CreateInstanceAndUnwrap (typeof (PositiveChecker).Assembly.FullName, typeof (DomainTester).FullName); else @@ -998,7 +998,7 @@ namespace TestRunner { if (doc_output != null) { string ref_file = filename.Replace (".cs", "-ref.xml"); try { -#if !NET_2_1 +#if !MOBILE new XmlComparer ("doc").Compare (ref_file, doc_output); #endif } catch (Exception e) { diff --git a/mcs/tools/compiler-tester/xmldocdiff.cs b/mcs/tools/compiler-tester/xmldocdiff.cs index bd9ade3603..ddcb6a70c0 100644 --- a/mcs/tools/compiler-tester/xmldocdiff.cs +++ b/mcs/tools/compiler-tester/xmldocdiff.cs @@ -24,9 +24,9 @@ // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// +// -#if !NET_2_1 +#if !MOBILE using System; using System.Collections; @@ -137,4 +137,4 @@ public class XmlComparer } } -#endif +#endif diff --git a/mcs/tools/corcompare/Util.cs b/mcs/tools/corcompare/Util.cs index fa643ed20f..660e859ca2 100644 --- a/mcs/tools/corcompare/Util.cs +++ b/mcs/tools/corcompare/Util.cs @@ -55,8 +55,8 @@ namespace CorCompare { var ifaces = new Dictionary (); foreach (var def in WalkHierarchy (type)) - foreach (TypeReference iface in def.Interfaces) - ifaces [iface.FullName] = iface; + foreach (var iface in def.Interfaces) + ifaces [iface.InterfaceType.FullName] = iface.InterfaceType; return ifaces.Values; } diff --git a/mcs/tools/corcompare/mono-api-info.cs b/mcs/tools/corcompare/mono-api-info.cs index 55c2aeb428..cf6b177710 100644 --- a/mcs/tools/corcompare/mono-api-info.cs +++ b/mcs/tools/corcompare/mono-api-info.cs @@ -59,6 +59,9 @@ namespace CorCompare { "h|?|help", "Show this message and exit.", v => showHelp = v != null }, + { "contract-api", + "Produces contract API with all members at each level of inheritance hierarchy", + v => FullAPISet = v != null }, }; var asms = options.Parse (args); @@ -116,6 +119,7 @@ namespace CorCompare internal static bool AbiMode { get; private set; } internal static bool FollowForwarders { get; private set; } + internal static bool FullAPISet { get; set; } } public class Utils { @@ -538,7 +542,7 @@ namespace CorCompare members.Add (new ConstructorData (writer, ctors)); } - PropertyDefinition[] properties = GetProperties (type); + PropertyDefinition[] properties = GetProperties (type, Driver.FullAPISet); if (properties.Length > 0) { Array.Sort (properties, PropertyDefinitionComparer.Default); members.Add (new PropertyData (writer, properties)); @@ -550,7 +554,7 @@ namespace CorCompare members.Add (new EventData (writer, events)); } - MethodDefinition [] methods = GetMethods (type); + MethodDefinition [] methods = GetMethods (type, Driver.FullAPISet); if (methods.Length > 0) { Array.Sort (methods, MethodDefinitionComparer.Default); members.Add (new MethodData (writer, methods)); @@ -693,53 +697,104 @@ namespace CorCompare } - internal static PropertyDefinition [] GetProperties (TypeDefinition type) { - ArrayList list = new ArrayList (); + internal static PropertyDefinition [] GetProperties (TypeDefinition type, bool fullAPI) { + var list = new List (); - var properties = type.Properties;//type.GetProperties (flags); - foreach (PropertyDefinition property in properties) { - MethodDefinition getMethod = property.GetMethod; - MethodDefinition setMethod = property.SetMethod; + var t = type; + do { + var properties = t.Properties;//type.GetProperties (flags); + foreach (PropertyDefinition property in properties) { + MethodDefinition getMethod = property.GetMethod; + MethodDefinition setMethod = property.SetMethod; - bool hasGetter = (getMethod != null) && MustDocumentMethod (getMethod); - bool hasSetter = (setMethod != null) && MustDocumentMethod (setMethod); + bool hasGetter = (getMethod != null) && MustDocumentMethod (getMethod); + bool hasSetter = (setMethod != null) && MustDocumentMethod (setMethod); - // if neither the getter or setter should be documented, then - // skip the property - if (hasGetter || hasSetter) { - list.Add (property); + // if neither the getter or setter should be documented, then + // skip the property + if (hasGetter || hasSetter) { + + if (t != type && list.Any (l => l.Name == property.Name)) + continue; + + list.Add (property); + } } - } - return (PropertyDefinition []) list.ToArray (typeof (PropertyDefinition)); + if (!fullAPI) + break; + + if (t.IsInterface || t.IsEnum) + break; + + if (t.BaseType == null || t.BaseType.FullName == "System.Object") + t = null; + else + t = t.BaseType.Resolve (); + + } while (t != null); + + return list.ToArray (); } - private MethodDefinition[] GetMethods (TypeDefinition type) + private MethodDefinition[] GetMethods (TypeDefinition type, bool fullAPI) { - ArrayList list = new ArrayList (); + var list = new List (); - var methods = type.Methods;//type.GetMethods (flags); - foreach (MethodDefinition method in methods) { - if (method.IsSpecialName && !method.Name.StartsWith ("op_", StringComparison.Ordinal)) - continue; + var t = type; + do { + var methods = t.Methods;//type.GetMethods (flags); + foreach (MethodDefinition method in methods) { + if (method.IsSpecialName && !method.Name.StartsWith ("op_", StringComparison.Ordinal)) + continue; - // we're only interested in public or protected members - if (!MustDocumentMethod(method)) - continue; + // we're only interested in public or protected members + if (!MustDocumentMethod (method)) + continue; - if (IsFinalizer (method)) { - string name = method.DeclaringType.Name; - int arity = name.IndexOf ('`'); - if (arity > 0) - name = name.Substring (0, arity); + if (t == type && IsFinalizer (method)) { + string name = method.DeclaringType.Name; + int arity = name.IndexOf ('`'); + if (arity > 0) + name = name.Substring (0, arity); - method.Name = "~" + name; + method.Name = "~" + name; + } + + if (t != type && list.Any (l => l.DeclaringType != method.DeclaringType && l.Name == method.Name && l.Parameters.Count == method.Parameters.Count && + l.Parameters.SequenceEqual (method.Parameters, new ParameterComparer ()))) + continue; + + list.Add (method); } - list.Add (method); + if (!fullAPI) + break; + + if (t.IsInterface || t.IsEnum) + break; + + if (t.BaseType == null || t.BaseType.FullName == "System.Object") + t = null; + else + t = t.BaseType.Resolve (); + + } while (t != null); + + return list.ToArray (); + } + + sealed class ParameterComparer : IEqualityComparer + { + public bool Equals (ParameterDefinition x, ParameterDefinition y) + { + return x.ParameterType.Name == y.ParameterType.Name; } - return (MethodDefinition []) list.ToArray (typeof (MethodDefinition)); + public int GetHashCode (ParameterDefinition obj) + { + return obj.ParameterType.Name.GetHashCode (); + } } static bool IsFinalizer (MethodDefinition method) @@ -1034,9 +1089,12 @@ namespace CorCompare if (!(memberDefenition is MethodDefinition)) return; - MethodDefinition mbase = (MethodDefinition) memberDefenition; + MethodDefinition mbase = (MethodDefinition)memberDefenition; + + ParameterData parms = new ParameterData (writer, mbase.Parameters) { + HasExtensionParameter = mbase.CustomAttributes.Any (l => l.AttributeType.FullName == "System.Runtime.CompilerServices.ExtensionAttribute") + }; - ParameterData parms = new ParameterData (writer, mbase.Parameters); parms.DoOutput (); MemberData.OutputGenericParameters (writer, mbase); @@ -1082,8 +1140,11 @@ namespace CorCompare this.parameters = parameters; } + public bool HasExtensionParameter { get; set; } + public override void DoOutput () { + bool first = true; writer.WriteStartElement ("parameters"); foreach (ParameterDefinition parameter in parameters) { writer.WriteStartElement ("parameter"); @@ -1091,13 +1152,17 @@ namespace CorCompare AddAttribute ("position", parameter.Method.Parameters.IndexOf(parameter).ToString(CultureInfo.InvariantCulture)); AddAttribute ("attrib", ((int) parameter.Attributes).ToString()); - string direction = "in"; + string direction = first && HasExtensionParameter ? "this" : "in"; + first = false; - if (parameter.ParameterType is ByReferenceType) + var pt = parameter.ParameterType; + var brt = pt as ByReferenceType; + if (brt != null) { direction = parameter.IsOut ? "out" : "ref"; + pt = brt.ElementType; + } - TypeReference t = parameter.ParameterType; - AddAttribute ("type", Utils.CleanupTypeName (t)); + AddAttribute ("type", Utils.CleanupTypeName (pt)); if (parameter.IsOptional) { AddAttribute ("optional", "true"); @@ -1476,13 +1541,13 @@ namespace CorCompare ParameterDefinition info = infos [i]; - string modifier; - if ((info.Attributes & ParameterAttributes.In) != 0) - modifier = "in"; - else if ((info.Attributes & ParameterAttributes.Out) != 0) - modifier = "out"; - else - modifier = string.Empty; + string modifier = string.Empty; + if (info.ParameterType.IsByReference) { + if ((info.Attributes & ParameterAttributes.In) != 0) + modifier = "in"; + else if ((info.Attributes & ParameterAttributes.Out) != 0) + modifier = "out"; + } if (modifier.Length > 0) { signature.Append (modifier); diff --git a/mcs/tools/linker/Descriptors/mscorlib.xml b/mcs/tools/linker/Descriptors/mscorlib.xml index 6e07617be3..396acc5a69 100644 --- a/mcs/tools/linker/Descriptors/mscorlib.xml +++ b/mcs/tools/linker/Descriptors/mscorlib.xml @@ -55,6 +55,11 @@ + + + + + @@ -111,8 +116,18 @@ + + + + + + + + + + @@ -130,7 +145,9 @@ - + + + @@ -177,7 +194,9 @@ - + + + @@ -210,6 +229,9 @@ + + + @@ -262,6 +284,9 @@ --> + + + @@ -290,12 +315,17 @@ - + + + - + + + + @@ -317,6 +347,7 @@ + + + + + diff --git a/mcs/tools/linker/Mono.Linker.Steps/MarkStep.cs b/mcs/tools/linker/Mono.Linker.Steps/MarkStep.cs index 74e61e3541..9bf293d7f1 100644 --- a/mcs/tools/linker/Mono.Linker.Steps/MarkStep.cs +++ b/mcs/tools/linker/Mono.Linker.Steps/MarkStep.cs @@ -69,29 +69,27 @@ namespace Mono.Linker.Steps { protected virtual void InitializeAssembly (AssemblyDefinition assembly) { MarkAssembly (assembly); - foreach (TypeDefinition type in assembly.MainModule.Types) { - if (!Annotations.IsMarked (type)) - continue; + foreach (TypeDefinition type in assembly.MainModule.Types) InitializeType (type); - } } void InitializeType (TypeDefinition type) { + if (type.HasNestedTypes) { + foreach (var nested in type.NestedTypes) + InitializeType (nested); + } + + if (!Annotations.IsMarked (type)) + return; + MarkType (type); if (type.HasFields) InitializeFields (type); if (type.HasMethods) InitializeMethods (type.Methods); - - if (type.HasNestedTypes) { - foreach (var nested in type.NestedTypes) { - if (Annotations.IsMarked (nested)) - InitializeType (nested); - } - } } void InitializeFields (TypeDefinition type) @@ -520,8 +518,8 @@ namespace Mono.Linker.Steps { MarkFields (type, type.IsEnum); if (type.HasInterfaces) { - foreach (TypeReference iface in type.Interfaces) - MarkType (iface); + foreach (var iface in type.Interfaces) + MarkType (iface.InterfaceType); } if (type.HasMethods) { diff --git a/mcs/tools/linker/Mono.Linker.Steps/OutputStep.cs b/mcs/tools/linker/Mono.Linker.Steps/OutputStep.cs index 0260c892e9..0ae94deef2 100644 --- a/mcs/tools/linker/Mono.Linker.Steps/OutputStep.cs +++ b/mcs/tools/linker/Mono.Linker.Steps/OutputStep.cs @@ -129,7 +129,7 @@ namespace Mono.Linker.Steps { static FileInfo GetOriginalAssemblyFileInfo (AssemblyDefinition assembly) { - return new FileInfo (assembly.MainModule.FullyQualifiedName); + return new FileInfo (assembly.MainModule.FileName); } static void CopyAssembly (FileInfo fi, string directory, bool symbols) diff --git a/mcs/tools/linker/Mono.Linker.Steps/ResolveFromXmlStep.cs b/mcs/tools/linker/Mono.Linker.Steps/ResolveFromXmlStep.cs index 5e9f681fd1..aa4f6afc76 100644 --- a/mcs/tools/linker/Mono.Linker.Steps/ResolveFromXmlStep.cs +++ b/mcs/tools/linker/Mono.Linker.Steps/ResolveFromXmlStep.cs @@ -174,6 +174,14 @@ namespace Mono.Linker.Steps { Annotations.Mark (type); + if (type.IsNested) { + var parent = type; + while (parent.IsNested) { + parent = parent.DeclaringType; + Annotations.Mark (parent); + } + } + switch (preserve) { case TypePreserve.Nothing: if (!nav.HasChildren) diff --git a/mcs/tools/linker/Mono.Linker.Steps/SweepStep.cs b/mcs/tools/linker/Mono.Linker.Steps/SweepStep.cs index e463ff9cde..73c89cc799 100644 --- a/mcs/tools/linker/Mono.Linker.Steps/SweepStep.cs +++ b/mcs/tools/linker/Mono.Linker.Steps/SweepStep.cs @@ -152,7 +152,7 @@ namespace Mono.Linker.Steps { // at this stage reference might include things that can't be resolved // and if it is (resolved) it needs to be kept only if marked (#16213) if ((td != null) && Annotations.IsMarked (td)) { - scope = assembly.MainModule.Import (td).Scope; + scope = assembly.MainModule.ImportReference (td).Scope; if (tr.Scope != scope) changes = true; hash.Add (tr, scope); @@ -163,7 +163,7 @@ namespace Mono.Linker.Steps { var td = et.Resolve (); IMetadataScope scope = et.Scope; if ((td != null) && Annotations.IsMarked (td)) { - scope = assembly.MainModule.Import (td).Scope; + scope = assembly.MainModule.ImportReference (td).Scope; hash.Add (td, scope); } } diff --git a/mcs/tools/linker/Mono.Linker.Steps/TypeMapStep.cs b/mcs/tools/linker/Mono.Linker.Steps/TypeMapStep.cs index 4f0e2eeaae..3fe12ae667 100644 --- a/mcs/tools/linker/Mono.Linker.Steps/TypeMapStep.cs +++ b/mcs/tools/linker/Mono.Linker.Steps/TypeMapStep.cs @@ -59,8 +59,8 @@ namespace Mono.Linker.Steps { if (!type.HasInterfaces) return; - foreach (TypeReference @interface in type.Interfaces) { - var iface = @interface.Resolve (); + foreach (var @interface in type.Interfaces) { + var iface = @interface.InterfaceType.Resolve (); if (iface == null || !iface.HasMethods) continue; @@ -160,8 +160,8 @@ namespace Mono.Linker.Steps { if (!type.HasInterfaces) yield break; - foreach (TypeReference interface_ref in type.Interfaces) { - TypeDefinition @interface = interface_ref.Resolve (); + foreach (var interface_ref in type.Interfaces) { + TypeDefinition @interface = interface_ref.InterfaceType.Resolve (); if (@interface == null) continue; diff --git a/mcs/tools/linker/Mono.Linker/AssemblyResolver.cs b/mcs/tools/linker/Mono.Linker/AssemblyResolver.cs index 23aca21a84..cb0646c687 100644 --- a/mcs/tools/linker/Mono.Linker/AssemblyResolver.cs +++ b/mcs/tools/linker/Mono.Linker/AssemblyResolver.cs @@ -65,7 +65,7 @@ namespace Mono.Linker { public void CacheAssembly (AssemblyDefinition assembly) { _assemblies [assembly.Name.Name] = assembly; - base.AddSearchDirectory (Path.GetDirectoryName (assembly.MainModule.FullyQualifiedName)); + base.AddSearchDirectory (Path.GetDirectoryName (assembly.MainModule.FileName)); } } } diff --git a/mcs/tools/linker/Mono.Linker/LinkContext.cs b/mcs/tools/linker/Mono.Linker/LinkContext.cs index 417206ce07..7d7908f2ec 100644 --- a/mcs/tools/linker/Mono.Linker/LinkContext.cs +++ b/mcs/tools/linker/Mono.Linker/LinkContext.cs @@ -178,7 +178,7 @@ namespace Mono.Linker { if (_symbolReaderProvider != null) { var symbolReader = _symbolReaderProvider.GetSymbolReader ( assembly.MainModule, - assembly.MainModule.FullyQualifiedName); + assembly.MainModule.FileName); _annotations.AddSymbolReader (assembly, symbolReader); assembly.MainModule.ReadSymbols (symbolReader); diff --git a/mcs/tools/mconfig/Makefile b/mcs/tools/mconfig/Makefile index 92fc95c91f..48b315986d 100644 --- a/mcs/tools/mconfig/Makefile +++ b/mcs/tools/mconfig/Makefile @@ -6,17 +6,12 @@ LOCAL_MCS_FLAGS = LIB_REFS = System.Xml System PROGRAM = mconfig.exe -BUILT_SOURCES=Mono.MonoConfig/consts.cs - -Mono.MonoConfig/consts.cs: Mono.MonoConfig/consts.cs.in - sed -e "s;@MONO_SYSCONFDIR@;$(sysconfdir);g" < $< > $@ - install-local: install-local-data install-local-data: $(MKINSTALLDIRS) $(DESTDIR)$(sysconfdir)/mono/mconfig/ $(INSTALL_DATA) data/config.xml $(DESTDIR)$(sysconfdir)/mono/mconfig -EXTRA_DISTFILES = TODO data/config.xml Mono.MonoConfig/consts.cs.in +EXTRA_DISTFILES = TODO data/config.xml include ../../build/executable.make diff --git a/mcs/tools/mconfig/mconfig.cs b/mcs/tools/mconfig/mconfig.cs index 5887f739db..7fc9f0bc97 100644 --- a/mcs/tools/mconfig/mconfig.cs +++ b/mcs/tools/mconfig/mconfig.cs @@ -270,7 +270,7 @@ namespace Mono.MonoConfig class MConfig { static string[] configPaths = { - Constants.GlobalConfigPath, + Path.GetFullPath (Path.Combine (Environment.CommandLine, "..", "..", "..","..", "etc", "mono", "mconfig", "config.xml")), Path.Combine (ConfigPath, "config.xml"), Path.Combine (".", "mconfig.xml"), null diff --git a/mcs/tools/mdoc/Makefile b/mcs/tools/mdoc/Makefile index efb76cbf9e..f707436102 100644 --- a/mcs/tools/mdoc/Makefile +++ b/mcs/tools/mdoc/Makefile @@ -16,7 +16,7 @@ MDOC_COMMON_FLAGS = \ LIB_REFS = monodoc System System.Xml System.Core Mono.Cecil ICSharpCode.SharpZipLib System.Xml.Linq System.Web LOCAL_MCS_FLAGS = $(MDOC_COMMON_FLAGS) -PROGRAM = mdoc.exe +PROGRAM = $(topdir)/class/lib/$(PROFILE)/mdoc.exe PROGRAM_DEPS = $(topdir)/class/lib/$(PROFILE)/monodoc.dll ifdef NET @@ -66,11 +66,6 @@ PROGRAM_COMPILE = $(CSCOMPILE) -platform:x86 include ../../build/executable.make -$(PROGRAM) : $(build_lib) - cp $< $@ - -$(PROGRAM) : Makefile - MONO = \ MONO_PATH="$(topdir)/class/lib/$(PROFILE)$(PLATFORM_PATH_SEPARATOR)$$MONO_PATH" \ $(RUNTIME) $(RUNTIME_FLAGS) @@ -165,7 +160,7 @@ check-monodocer-addNonGeneric: $(PROGRAM) $(MONO) $(PROGRAM) update --exceptions=all -o Test/en.actual Test/DocTest-addNonGeneric-v2.dll $(MONO) $(PROGRAM) update --exceptions=all -o Test/en.actual Test/DocTest-addNonGeneric-v2.dll $(MONO) $(PROGRAM) update --exceptions=all -o Test/en.actual Test/DocTest-addNonGeneric-v2.dll - diff --exclude=.svn -rup Test/en.expected-addNonGeneric Test/en.actual + diff -rup Test/en.expected-addNonGeneric Test/en.actual check-monodocer-dropns-classic: $(PROGRAM) # tests the simplest --dropns case, a single class where the root namespace was dropped. @@ -173,7 +168,7 @@ check-monodocer-dropns-classic: $(PROGRAM) $(MAKE) Test/DocTest-DropNS-classic.dll $(MONO) $(PROGRAM) update --exceptions=all -o Test/en.actual Test/DocTest-DropNS-classic.dll --api-style=classic $(MAKE) update-monodocer-dropns-unified - diff --exclude=.svn -rup Test/en.expected-dropns-classic-v1 Test/en.actual + diff -rup Test/en.expected-dropns-classic-v1 Test/en.actual check-monodocer-dropns-multi: $(PROGRAM) -rm -Rf Test/en.actual @@ -183,14 +178,14 @@ check-monodocer-dropns-multi: $(PROGRAM) $(MAKE) Test/DocTest-DropNS-unified-multitest.dll # mdoc update for both classic and unified - $(MONO) $(PROGRAM) update --exceptions=all -o Test/en.actual $(MULTI-CLASSIC) --api-style=classic -multiassembly - $(MONO) $(PROGRAM) update --exceptions=all -o Test/en.actual $(MULTI-UNIFIED) --api-style=unified --dropns Test/DocTest-DropNS-unified.dll=MyFramework --dropns Test/DocTest-DropNS-unified-multitest.dll=MyFramework -multiassembly + $(MONO) $(PROGRAM) update --exceptions=all -o Test/en.actual $(MULTI-CLASSIC) --api-style=classic + $(MONO) $(PROGRAM) update --exceptions=all -o Test/en.actual $(MULTI-UNIFIED) --api-style=unified --dropns Test/DocTest-DropNS-unified.dll=MyFramework --dropns Test/DocTest-DropNS-unified-multitest.dll=MyFramework # now run it again to verify idempotency - $(MONO) $(PROGRAM) update --exceptions=all -o Test/en.actual $(MULTI-CLASSIC) --api-style=classic -multiassembly - $(MONO) $(PROGRAM) update --exceptions=all -o Test/en.actual $(MULTI-UNIFIED) --api-style=unified --dropns Test/DocTest-DropNS-unified.dll=MyFramework --dropns Test/DocTest-DropNS-unified-multitest.dll=MyFramework -multiassembly + $(MONO) $(PROGRAM) update --exceptions=all -o Test/en.actual $(MULTI-CLASSIC) --api-style=classic + $(MONO) $(PROGRAM) update --exceptions=all -o Test/en.actual $(MULTI-UNIFIED) --api-style=unified --dropns Test/DocTest-DropNS-unified.dll=MyFramework --dropns Test/DocTest-DropNS-unified-multitest.dll=MyFramework - diff --exclude=.svn -rup Test/en.expected-dropns-multi Test/en.actual + diff -rup Test/en.expected-dropns-multi Test/en.actual check-monodocer-dropns-multi-withexisting: $(PROGRAM) @@ -205,10 +200,10 @@ check-monodocer-dropns-multi-withexisting: $(PROGRAM) $(MONO) $(PROGRAM) update --exceptions=all -o Test/en.actual Test/DocTest-DropNS-unified.dll --api-style=unified --dropns Test/DocTest-DropNS-unified.dll=MyFramework # mdoc update for both classic and unified - $(MONO) $(PROGRAM) update --exceptions=all -o Test/en.actual $(MULTI-CLASSIC) --api-style=classic -multiassembly - $(MONO) $(PROGRAM) update --exceptions=all -o Test/en.actual $(MULTI-UNIFIED) --api-style=unified --dropns Test/DocTest-DropNS-unified.dll=MyFramework --dropns Test/DocTest-DropNS-unified-multitest.dll=MyFramework -multiassembly + $(MONO) $(PROGRAM) update --exceptions=all -o Test/en.actual $(MULTI-CLASSIC) --api-style=classic + $(MONO) $(PROGRAM) update --exceptions=all -o Test/en.actual $(MULTI-UNIFIED) --api-style=unified --dropns Test/DocTest-DropNS-unified.dll=MyFramework --dropns Test/DocTest-DropNS-unified-multitest.dll=MyFramework - diff --exclude=.svn -rup Test/en.expected-dropns-multi-withexisting Test/en.actual + diff -rup Test/en.expected-dropns-multi-withexisting Test/en.actual check-monodocer-dropns-delete: $(PROGRAM) -rm -Rf Test/en.actual @@ -222,7 +217,7 @@ check-monodocer-dropns-delete: $(PROGRAM) $(MONO) $(PROGRAM) update --delete --exceptions=all -o Test/en.actual Test/DocTest-DropNS-classic-deletetest.dll --api-style=classic $(MAKE) Test/DocTest-DropNS-unified-deletetest-V2.dll $(MONO) $(PROGRAM) update --delete --exceptions=all -o Test/en.actual Test/DocTest-DropNS-unified-deletetest.dll --api-style=unified --dropns Test/DocTest-DropNS-unified-deletetest.dll=MyFramework - diff --exclude=.dvn -rup Test/en.expected-dropns-delete Test/en.actual + diff -rup Test/en.expected-dropns-delete Test/en.actual check-monodocer-dropns-classic-withsecondary: $(PROGRAM) # tests case where a secondary assembly is included with a --dropns parameter @@ -231,7 +226,7 @@ check-monodocer-dropns-classic-withsecondary: $(PROGRAM) $(MAKE) Test/DocTest-DropNS-classic-secondary.dll $(MONO) $(PROGRAM) update --exceptions=all -o Test/en.actual Test/DocTest-DropNS-classic.dll Test/DocTest-DropNS-classic-secondary.dll --api-style=classic $(MAKE) update-monodocer-dropns-unified-withsecondary - diff --exclude=.svn -rup Test/en.expected-dropns-classic-withsecondary Test/en.actual + diff -rup Test/en.expected-dropns-classic-withsecondary Test/en.actual update-monodocer-dropns-unified: $(PROGRAM) $(MAKE) Test/DocTest-DropNS-unified.dll @@ -250,13 +245,13 @@ check-monodocer-internal-interface: $(PROGRAM) -rm -Rf Test/en.actual $(MAKE) Test/DocTest-InternalInterface.dll $(MONO) $(PROGRAM) update --exceptions=all -o Test/en.actual Test/DocTest-InternalInterface.dll - diff --exclude=.svn -rup Test/en.expected-internal-interface Test/en.actual + diff -rup Test/en.expected-internal-interface Test/en.actual check-monodocer-enumerations: $(PROGRAM) -rm -Rf Test/en.actual $(MAKE) Test/DocTest-enumerations.dll $(MONO) $(PROGRAM) update --exceptions=all -o Test/en.actual Test/DocTest-enumerations.dll - diff --exclude=.svn -rup Test/en.expected-enumerations Test/en.actual + diff -rup Test/en.expected-enumerations Test/en.actual check-monodocer-update: $(PROGRAM) find Test/en.expected -name \*.xml -exec rm "{}" \; @@ -267,9 +262,9 @@ check-monodocer: $(PROGRAM) -rm -Rf Test/en.actual $(MAKE) Test/DocTest.dll-v1 $(MONO) $(PROGRAM) update --debug --exceptions=all -o Test/en.actual Test/DocTest.dll - diff --exclude=.svn -rup Test/en.expected Test/en.actual + diff -rup Test/en.expected Test/en.actual $(MONO) $(PROGRAM) update --debug --exceptions=all -o Test/en.actual Test/DocTest.dll - diff --exclude=.svn -rup Test/en.expected Test/en.actual + diff -rup Test/en.expected Test/en.actual check-monodocer-since-update: $(PROGRAM) find Test/en.expected.since -name \*.xml -exec rm "{}" \; @@ -286,7 +281,7 @@ check-monodocer-since: $(PROGRAM) $(MAKE) Test/DocTest.dll-v2 $(MONO) $(PROGRAM) --debug update --exceptions=all --since="Version 2.0" \ -o Test/en.actual Test/DocTest.dll - diff --exclude=.svn -rup Test/en.expected.since Test/en.actual + diff -rup Test/en.expected.since Test/en.actual check-monodocer-delete-update: $(PROGRAM) find Test/en.expected.delete -type f -exec rm "{}" \; @@ -306,7 +301,7 @@ check-monodocer-delete: $(PROGRAM) $(MONO) $(PROGRAM) --debug update --exceptions=all -o Test/en.actual Test/DocTest.dll $(MAKE) Test/DocTest.dll-v1 $(MONO) $(PROGRAM) --debug update -fno-assembly-versions --delete --exceptions=all -o Test/en.actual Test/DocTest.dll - diff --exclude=.svn -rup Test/en.expected.delete Test/en.actual + diff -rup Test/en.expected.delete Test/en.actual check-monodocer-importslashdoc-update: $(PROGRAM) find Test/en.expected.importslashdoc -name \*.xml -exec rm "{}" \; @@ -319,7 +314,7 @@ check-monodocer-importslashdoc: $(PROGRAM) $(MAKE) Test/DocTest.dll-v1 TEST_CSCFLAGS=-doc:Test/DocTest.xml $(MONO) $(PROGRAM) --debug update --exceptions=all -i Test/DocTest.xml \ -o Test/en.actual Test/DocTest.dll - diff --exclude=.svn -rup Test/en.expected.importslashdoc Test/en.actual + diff -rup Test/en.expected.importslashdoc Test/en.actual check-monodocer-importecmadoc-update: $(PROGRAM) find Test/en.expected.importecmadoc -name \*.xml -exec rm "{}" \; @@ -336,7 +331,7 @@ check-monodocer-importecmadoc: $(PROGRAM) '--type=System.Action`1' --type=System.AsyncCallback \ --type=System.Environment --type=System.Array \ -o Test/en.actual Test/DocTest.dll - diff --exclude=.svn -rup Test/en.expected.importecmadoc Test/en.actual + diff -rup Test/en.expected.importecmadoc Test/en.actual check-mdoc-export-html-update: $(PROGRAM) find Test/html.expected -name \*.html -exec rm "{}" \; @@ -347,7 +342,7 @@ check-mdoc-export-html: check-monodocer $(PROGRAM) rm -Rf Test/html.actual $(MONO) $(PROGRAM) export-html -o Test/html.actual \ Test/en.expected.importslashdoc - diff --exclude=.svn -rup Test/html.expected Test/html.actual + diff -rup Test/html.expected Test/html.actual check-mdoc-export-html-with-version: $(PROGRAM) rm -Rf Test/html.actual.v0 Test/html.actual.since-with-v0 .v0.txt .v2.txt @@ -362,7 +357,7 @@ check-mdoc-export-html-with-version: $(PROGRAM) check-md-html-dir: $(PROGRAM) rm -Rf Test/html.actual $(MONO) $(PROGRAM) export-html -dest:Test/html.actual $(DIR) - diff --exclude=.svn -rup Test/html.expected Test/html.actual + diff -rup Test/html.expected Test/html.actual check-mdoc-export-msxdoc-update: $(MONO) $(PROGRAM) export-msxdoc -o - Test/en.expected.importslashdoc \ diff --git a/mcs/tools/mdoc/Mono.Documentation/exceptions.cs b/mcs/tools/mdoc/Mono.Documentation/exceptions.cs index 5919870876..23b6762a65 100644 --- a/mcs/tools/mdoc/Mono.Documentation/exceptions.cs +++ b/mcs/tools/mdoc/Mono.Documentation/exceptions.cs @@ -74,7 +74,8 @@ namespace Mono.Documentation { get { if (member == null) throw new ArgumentNullException ("member"); - MemberReference memberDef = member.Resolve (); + + var memberDef = member.Resolve (); if (memberDef == null) { ArrayType array = member.DeclaringType as ArrayType; if (array != null && array.Rank > 1) { @@ -87,7 +88,7 @@ namespace Mono.Documentation { "Unable to resolve member {0}::{1}.", member.DeclaringType.FullName, member.Name)); } - string memberDecl = xdoc.GetDeclaration (member.Resolve ()); + string memberDecl = xdoc.GetDeclaration (member); Dictionary e; if (!db.TryGetValue (memberDecl, out e)) { e = new Dictionary (); diff --git a/mcs/tools/mdoc/Mono.Documentation/monodocer.cs.REMOVED.git-id b/mcs/tools/mdoc/Mono.Documentation/monodocer.cs.REMOVED.git-id index 6956f66131..78eead062f 100644 --- a/mcs/tools/mdoc/Mono.Documentation/monodocer.cs.REMOVED.git-id +++ b/mcs/tools/mdoc/Mono.Documentation/monodocer.cs.REMOVED.git-id @@ -1 +1 @@ -a8f1ccc50290aeeeb70422e0aec4a93274f6528b \ No newline at end of file +8b5b5ab08e4d440f58d3dd88d1b732cbd5ccc449 \ No newline at end of file diff --git a/mcs/tools/mdoc/Test/en.expected-dropns-classic-v1/MyFramework.MyNamespace/MyClass.xml b/mcs/tools/mdoc/Test/en.expected-dropns-classic-v1/MyFramework.MyNamespace/MyClass.xml index 77388be881..317b6a6184 100644 --- a/mcs/tools/mdoc/Test/en.expected-dropns-classic-v1/MyFramework.MyNamespace/MyClass.xml +++ b/mcs/tools/mdoc/Test/en.expected-dropns-classic-v1/MyFramework.MyNamespace/MyClass.xml @@ -23,9 +23,11 @@ Constructor + DocTest-DropNS-classic 0.0.0.0 + DocTest-DropNS-unified 0.0.0.0 @@ -39,9 +41,11 @@ Method + DocTest-DropNS-classic 0.0.0.0 + DocTest-DropNS-unified 0.0.0.0 @@ -62,9 +66,11 @@ Property + DocTest-DropNS-classic 0.0.0.0 + DocTest-DropNS-unified 0.0.0.0 @@ -81,6 +87,7 @@ Property + DocTest-DropNS-classic 0.0.0.0 @@ -97,6 +104,7 @@ Property + DocTest-DropNS-unified 0.0.0.0 diff --git a/mcs/tools/mdoc/Test/en.expected-dropns-classic-v1/MyFramework.MyNamespace/MyClassExtensions.xml b/mcs/tools/mdoc/Test/en.expected-dropns-classic-v1/MyFramework.MyNamespace/MyClassExtensions.xml new file mode 100644 index 0000000000..a11fafef69 --- /dev/null +++ b/mcs/tools/mdoc/Test/en.expected-dropns-classic-v1/MyFramework.MyNamespace/MyClassExtensions.xml @@ -0,0 +1,47 @@ + + + + + DocTest-DropNS-classic + 0.0.0.0 + + + DocTest-DropNS-unified + 0.0.0.0 + + + System.Object + + + + To be added. + To be added. + + + + + + Method + + DocTest-DropNS-classic + 0.0.0.0 + + + DocTest-DropNS-unified + 0.0.0.0 + + + System.Boolean + + + + + + To be added. + To be added. + To be added. + To be added. + + + + diff --git a/mcs/tools/mdoc/Test/en.expected-dropns-classic-v1/index.xml b/mcs/tools/mdoc/Test/en.expected-dropns-classic-v1/index.xml index edacc723f5..330a3895e2 100644 --- a/mcs/tools/mdoc/Test/en.expected-dropns-classic-v1/index.xml +++ b/mcs/tools/mdoc/Test/en.expected-dropns-classic-v1/index.xml @@ -1,5 +1,15 @@ + + + + System.Diagnostics.Debuggable(System.Diagnostics.DebuggableAttribute+DebuggingModes.IgnoreSymbolStoreSequencePoints) + + + System.Runtime.CompilerServices.RuntimeCompatibility(WrapNonExceptionThrows=true) + + + @@ -16,7 +26,31 @@ + DocTest-DropNS-classic + + + + + + + + + ExtensionMethod + + System.Boolean + + + + + + To be added. + To be added. + + + + + diff --git a/mcs/tools/mdoc/Test/en.expected-dropns-classic-withsecondary/MyFramework.MyNamespace/MyClass.xml b/mcs/tools/mdoc/Test/en.expected-dropns-classic-withsecondary/MyFramework.MyNamespace/MyClass.xml index 77388be881..317b6a6184 100644 --- a/mcs/tools/mdoc/Test/en.expected-dropns-classic-withsecondary/MyFramework.MyNamespace/MyClass.xml +++ b/mcs/tools/mdoc/Test/en.expected-dropns-classic-withsecondary/MyFramework.MyNamespace/MyClass.xml @@ -23,9 +23,11 @@ Constructor + DocTest-DropNS-classic 0.0.0.0 + DocTest-DropNS-unified 0.0.0.0 @@ -39,9 +41,11 @@ Method + DocTest-DropNS-classic 0.0.0.0 + DocTest-DropNS-unified 0.0.0.0 @@ -62,9 +66,11 @@ Property + DocTest-DropNS-classic 0.0.0.0 + DocTest-DropNS-unified 0.0.0.0 @@ -81,6 +87,7 @@ Property + DocTest-DropNS-classic 0.0.0.0 @@ -97,6 +104,7 @@ Property + DocTest-DropNS-unified 0.0.0.0 diff --git a/mcs/tools/mdoc/Test/en.expected-dropns-classic-withsecondary/MyFramework.MyNamespace/MyClassExtensions.xml b/mcs/tools/mdoc/Test/en.expected-dropns-classic-withsecondary/MyFramework.MyNamespace/MyClassExtensions.xml new file mode 100644 index 0000000000..a11fafef69 --- /dev/null +++ b/mcs/tools/mdoc/Test/en.expected-dropns-classic-withsecondary/MyFramework.MyNamespace/MyClassExtensions.xml @@ -0,0 +1,47 @@ + + + + + DocTest-DropNS-classic + 0.0.0.0 + + + DocTest-DropNS-unified + 0.0.0.0 + + + System.Object + + + + To be added. + To be added. + + + + + + Method + + DocTest-DropNS-classic + 0.0.0.0 + + + DocTest-DropNS-unified + 0.0.0.0 + + + System.Boolean + + + + + + To be added. + To be added. + To be added. + To be added. + + + + diff --git a/mcs/tools/mdoc/Test/en.expected-dropns-classic-withsecondary/MyFramework.MyOtherNamespace/MyOtherClass.xml b/mcs/tools/mdoc/Test/en.expected-dropns-classic-withsecondary/MyFramework.MyOtherNamespace/MyOtherClass.xml index a920ce2f49..0e02038a02 100644 --- a/mcs/tools/mdoc/Test/en.expected-dropns-classic-withsecondary/MyFramework.MyOtherNamespace/MyOtherClass.xml +++ b/mcs/tools/mdoc/Test/en.expected-dropns-classic-withsecondary/MyFramework.MyOtherNamespace/MyOtherClass.xml @@ -14,11 +14,12 @@ To be added. - + Constructor - + + DocTest-DropNS-classic-secondary 0.0.0.0 @@ -27,11 +28,12 @@ To be added. - + Method - + + DocTest-DropNS-classic-secondary 0.0.0.0 @@ -47,11 +49,12 @@ To be added. - + Property - + + DocTest-DropNS-classic-secondary 0.0.0.0 diff --git a/mcs/tools/mdoc/Test/en.expected-dropns-classic-withsecondary/index.xml b/mcs/tools/mdoc/Test/en.expected-dropns-classic-withsecondary/index.xml index d0fb593627..3620aa8d0a 100644 --- a/mcs/tools/mdoc/Test/en.expected-dropns-classic-withsecondary/index.xml +++ b/mcs/tools/mdoc/Test/en.expected-dropns-classic-withsecondary/index.xml @@ -1,5 +1,15 @@ + + + + System.Diagnostics.Debuggable(System.Diagnostics.DebuggableAttribute+DebuggingModes.IgnoreSymbolStoreSequencePoints) + + + System.Runtime.CompilerServices.RuntimeCompatibility(WrapNonExceptionThrows=true) + + + @@ -26,10 +36,34 @@ + Untitled + + + + + + + + + ExtensionMethod + + System.Boolean + + + + + + To be added. + To be added. + + + + + diff --git a/mcs/tools/mdoc/Test/en.expected-dropns-delete/MyFramework.MyNamespace/MyClass.xml b/mcs/tools/mdoc/Test/en.expected-dropns-delete/MyFramework.MyNamespace/MyClass.xml index 1ff3447bab..13e6364a07 100644 --- a/mcs/tools/mdoc/Test/en.expected-dropns-delete/MyFramework.MyNamespace/MyClass.xml +++ b/mcs/tools/mdoc/Test/en.expected-dropns-delete/MyFramework.MyNamespace/MyClass.xml @@ -23,9 +23,11 @@ Constructor + DocTest-DropNS-classic-deletetest 0.0.0.0 + DocTest-DropNS-unified-deletetest 0.0.0.0 @@ -39,9 +41,11 @@ Property + DocTest-DropNS-classic-deletetest 0.0.0.0 + DocTest-DropNS-unified-deletetest 0.0.0.0 @@ -58,6 +62,7 @@ Property + DocTest-DropNS-classic-deletetest 0.0.0.0 @@ -74,6 +79,7 @@ Property + DocTest-DropNS-unified-deletetest 0.0.0.0 @@ -90,9 +96,11 @@ Method + DocTest-DropNS-classic-deletetest 0.0.0.0 + DocTest-DropNS-unified-deletetest 0.0.0.0 @@ -113,9 +121,11 @@ Property + DocTest-DropNS-classic-deletetest 0.0.0.0 + DocTest-DropNS-unified-deletetest 0.0.0.0 @@ -132,6 +142,7 @@ Property + DocTest-DropNS-classic-deletetest 0.0.0.0 @@ -150,9 +161,11 @@ Property + DocTest-DropNS-classic-deletetest 0.0.0.0 + DocTest-DropNS-unified-deletetest 0.0.0.0 @@ -170,6 +183,7 @@ Property + DocTest-DropNS-unified-deletetest 0.0.0.0 @@ -186,9 +200,11 @@ Property + DocTest-DropNS-classic-deletetest 0.0.0.0 + DocTest-DropNS-unified-deletetest 0.0.0.0 @@ -205,6 +221,7 @@ Property + DocTest-DropNS-classic-deletetest 0.0.0.0 @@ -221,6 +238,7 @@ Property + DocTest-DropNS-unified-deletetest 0.0.0.0 diff --git a/mcs/tools/mdoc/Test/en.expected-dropns-delete/MyFramework.MyNamespace/MyClassExtensions.xml b/mcs/tools/mdoc/Test/en.expected-dropns-delete/MyFramework.MyNamespace/MyClassExtensions.xml new file mode 100644 index 0000000000..3edb15b4cb --- /dev/null +++ b/mcs/tools/mdoc/Test/en.expected-dropns-delete/MyFramework.MyNamespace/MyClassExtensions.xml @@ -0,0 +1,47 @@ + + + + + DocTest-DropNS-classic-deletetest + 0.0.0.0 + + + DocTest-DropNS-unified-deletetest + 0.0.0.0 + + + System.Object + + + + To be added. + To be added. + + + + + + Method + + DocTest-DropNS-classic-deletetest + 0.0.0.0 + + + DocTest-DropNS-unified-deletetest + 0.0.0.0 + + + System.Boolean + + + + + + To be added. + To be added. + To be added. + To be added. + + + + diff --git a/mcs/tools/mdoc/Test/en.expected-dropns-delete/MyFramework.MyNamespace/TypeOnlyInClassic.xml b/mcs/tools/mdoc/Test/en.expected-dropns-delete/MyFramework.MyNamespace/TypeOnlyInClassic.xml index 7e6adf24eb..442a2d7c54 100644 --- a/mcs/tools/mdoc/Test/en.expected-dropns-delete/MyFramework.MyNamespace/TypeOnlyInClassic.xml +++ b/mcs/tools/mdoc/Test/en.expected-dropns-delete/MyFramework.MyNamespace/TypeOnlyInClassic.xml @@ -14,11 +14,12 @@ To be added. - + Constructor - + + DocTest-DropNS-classic-deletetest 0.0.0.0 diff --git a/mcs/tools/mdoc/Test/en.expected-dropns-delete/index.xml b/mcs/tools/mdoc/Test/en.expected-dropns-delete/index.xml index 0988450d77..02836fe971 100644 --- a/mcs/tools/mdoc/Test/en.expected-dropns-delete/index.xml +++ b/mcs/tools/mdoc/Test/en.expected-dropns-delete/index.xml @@ -1,5 +1,15 @@ + + + + System.Diagnostics.Debuggable(System.Diagnostics.DebuggableAttribute+DebuggingModes.IgnoreSymbolStoreSequencePoints) + + + System.Runtime.CompilerServices.RuntimeCompatibility(WrapNonExceptionThrows=true) + + + @@ -16,8 +26,32 @@ + DocTest-DropNS-classic-deletetest + + + + + + + + + ExtensionMethod + + System.Boolean + + + + + + To be added. + To be added. + + + + + diff --git a/mcs/tools/mdoc/Test/en.expected-dropns-multi-withexisting/MyFramework.MyNamespace/MyClass.xml b/mcs/tools/mdoc/Test/en.expected-dropns-multi-withexisting/MyFramework.MyNamespace/MyClass.xml index e73f7d55ff..a88b428a94 100644 --- a/mcs/tools/mdoc/Test/en.expected-dropns-multi-withexisting/MyFramework.MyNamespace/MyClass.xml +++ b/mcs/tools/mdoc/Test/en.expected-dropns-multi-withexisting/MyFramework.MyNamespace/MyClass.xml @@ -31,12 +31,12 @@ Constructor - 0.0.0.0 DocTest-DropNS-classic + 0.0.0.0 - 0.0.0.0 DocTest-DropNS-unified + 0.0.0.0 DocTest-DropNS-classic-multitest @@ -57,12 +57,12 @@ Method - 0.0.0.0 DocTest-DropNS-classic + 0.0.0.0 - 0.0.0.0 DocTest-DropNS-unified + 0.0.0.0 DocTest-DropNS-classic-multitest @@ -90,12 +90,12 @@ Property - 0.0.0.0 DocTest-DropNS-classic + 0.0.0.0 - 0.0.0.0 DocTest-DropNS-unified + 0.0.0.0 DocTest-DropNS-classic-multitest @@ -119,8 +119,8 @@ Property - 0.0.0.0 DocTest-DropNS-classic + 0.0.0.0 DocTest-DropNS-classic-multitest @@ -140,8 +140,8 @@ Property - 0.0.0.0 DocTest-DropNS-unified + 0.0.0.0 DocTest-DropNS-unified-multitest diff --git a/mcs/tools/mdoc/Test/en.expected-dropns-multi-withexisting/MyFramework.MyNamespace/MyClassExtensions.xml b/mcs/tools/mdoc/Test/en.expected-dropns-multi-withexisting/MyFramework.MyNamespace/MyClassExtensions.xml new file mode 100644 index 0000000000..7a504e29c7 --- /dev/null +++ b/mcs/tools/mdoc/Test/en.expected-dropns-multi-withexisting/MyFramework.MyNamespace/MyClassExtensions.xml @@ -0,0 +1,63 @@ + + + + + DocTest-DropNS-classic + 0.0.0.0 + + + DocTest-DropNS-unified + 0.0.0.0 + + + DocTest-DropNS-classic-multitest + 0.0.0.0 + + + DocTest-DropNS-unified-multitest + 0.0.0.0 + + + System.Object + + + + To be added. + To be added. + + + + + + Method + + DocTest-DropNS-classic + 0.0.0.0 + + + DocTest-DropNS-unified + 0.0.0.0 + + + DocTest-DropNS-classic-multitest + 0.0.0.0 + + + DocTest-DropNS-unified-multitest + 0.0.0.0 + + + System.Boolean + + + + + + To be added. + To be added. + To be added. + To be added. + + + + diff --git a/mcs/tools/mdoc/Test/en.expected-dropns-multi-withexisting/index.xml b/mcs/tools/mdoc/Test/en.expected-dropns-multi-withexisting/index.xml index 6b5124ac28..734bd3da1a 100644 --- a/mcs/tools/mdoc/Test/en.expected-dropns-multi-withexisting/index.xml +++ b/mcs/tools/mdoc/Test/en.expected-dropns-multi-withexisting/index.xml @@ -46,8 +46,32 @@ + DocTest-DropNS-classic + + + + + + + + + ExtensionMethod + + System.Boolean + + + + + + To be added. + To be added. + + + + + diff --git a/mcs/tools/mdoc/Test/en.expected-dropns-multi/MyFramework.MyNamespace/MyClassExtensions.xml b/mcs/tools/mdoc/Test/en.expected-dropns-multi/MyFramework.MyNamespace/MyClassExtensions.xml new file mode 100644 index 0000000000..c3e0ca736f --- /dev/null +++ b/mcs/tools/mdoc/Test/en.expected-dropns-multi/MyFramework.MyNamespace/MyClassExtensions.xml @@ -0,0 +1,63 @@ + + + + + DocTest-DropNS-classic + 0.0.0.0 + + + DocTest-DropNS-classic-multitest + 0.0.0.0 + + + DocTest-DropNS-unified + 0.0.0.0 + + + DocTest-DropNS-unified-multitest + 0.0.0.0 + + + System.Object + + + + To be added. + To be added. + + + + + + Method + + DocTest-DropNS-classic + 0.0.0.0 + + + DocTest-DropNS-classic-multitest + 0.0.0.0 + + + DocTest-DropNS-unified + 0.0.0.0 + + + DocTest-DropNS-unified-multitest + 0.0.0.0 + + + System.Boolean + + + + + + To be added. + To be added. + To be added. + To be added. + + + + diff --git a/mcs/tools/mdoc/Test/en.expected-dropns-multi/index.xml b/mcs/tools/mdoc/Test/en.expected-dropns-multi/index.xml index 3baf401ce5..b8345d0216 100644 --- a/mcs/tools/mdoc/Test/en.expected-dropns-multi/index.xml +++ b/mcs/tools/mdoc/Test/en.expected-dropns-multi/index.xml @@ -46,8 +46,32 @@ + Untitled + + + + + + + + + ExtensionMethod + + System.Boolean + + + + + + To be added. + To be added. + + + + + diff --git a/mcs/tools/mkbundle/Makefile b/mcs/tools/mkbundle/Makefile index 05faf5e8c6..64a1b9cbf9 100644 --- a/mcs/tools/mkbundle/Makefile +++ b/mcs/tools/mkbundle/Makefile @@ -11,10 +11,23 @@ RESOURCE_FILES = $(OTHER_RES) LOCAL_MCS_FLAGS= $(OTHER_RES:%=-resource:%) LOCAL_MCS_FLAGS += -d:STATIC,NO_SYMBOL_WRITER,NO_AUTHENTICODE -LIB_REFS = System.Xml System System.Core +LIB_REFS = System.Xml System System.Core System.IO.Compression.FileSystem EXTRA_DISTFILES = $(RESOURCE_FILES) include ../../build/executable.make mkbundle.exe: $(RESOURCE_FILES) + +test-simple: simple.exe + mono --debug $(the_lib) --simple simple.exe -o foo && ./foo + mono --debug $(the_lib) --cross default simple.exe -o foo && ./foo + mono --debug $(the_lib) --sdk `dirname \`which mono\``/.. simple.exe -o foo && ./foo + -rm DEMO.zip + mono-package-runtime `dirname \`which mono\``/.. DEMO + mkdir -p ~/.mono/targets/DEMO + unzip -d ~/.mono/targets/DEMO DEMO.zip + mono --debug $(the_lib) --cross DEMO simple.exe -o foo && ./foo + +simple.exe: Makefile + echo 'class X { static void Main () { System.Console.WriteLine ("OK");}}' > simple.cs && mcs simple.cs diff --git a/mcs/tools/mkbundle/mkbundle.cs b/mcs/tools/mkbundle/mkbundle.cs index 86a7132bbc..1ea1d74024 100755 --- a/mcs/tools/mkbundle/mkbundle.cs +++ b/mcs/tools/mkbundle/mkbundle.cs @@ -3,6 +3,16 @@ // // Based on the `make-bundle' Perl script written by Paolo Molaro (lupus@debian.org) // +// TODO: +// [x] Rename the paths for the zip file that is downloaded +// [x] Update documentation with new flag +// [x] Load internationalized assemblies +// [x] Dependencies - if System.dll -> include Mono.Security.* (not needed, automatic) +// [x] --list-targets should download from a different url +// [x] --fetch-target should unpack zip file +// [x] Update --cross to use not a runtime, but an SDK +// [x] Update --local-targets to show the downloaded SDKs +// // Author: // Miguel de Icaza // @@ -23,7 +33,6 @@ using System.Runtime.InteropServices; using System.Text; using IKVM.Reflection; using System.Linq; -using System.Diagnostics; using System.Net; using System.Threading.Tasks; @@ -31,6 +40,7 @@ class MakeBundle { static string output = "a.out"; static string object_out = null; static List link_paths = new List (); + static Dictionary libraries = new Dictionary (); static bool autodeps = false; static bool keeptemp = false; static bool compile_only = false; @@ -46,12 +56,27 @@ class MakeBundle { static bool? use_dos2unix = null; static bool skip_scan; static string ctor_func; - static bool quiet; + static bool quiet = true; static string cross_target = null; static string fetch_target = null; static bool custom_mode = true; static string embedded_options = null; static string runtime = null; + static string sdk_path = null; + static string lib_path = null; + static Dictionary environment = new Dictionary(); + static string [] i18n = new string [] { + "West", + "" + }; + static string [] i18n_all = new string [] { + "CJK", + "MidEast", + "Other", + "Rare", + "West", + "" + }; static string target_server = "https://download.mono-project.com/runtimes/raw/"; static int Main (string [] args) @@ -61,7 +86,7 @@ class MakeBundle { link_paths.Add ("."); DetectOS (); - + for (int i = 0; i < top; i++){ switch (args [i]){ case "--help": case "-h": case "-?": @@ -72,6 +97,24 @@ class MakeBundle { custom_mode = false; autodeps = true; break; + + case "-v": + quiet = false; + break; + + case "--i18n": + if (i+1 == top){ + Help (); + return 1; + } + var iarg = args [++i]; + if (iarg == "all") + i18n = i18n_all; + else if (iarg == "none") + i18n = new string [0]; + else + i18n = iarg.Split (','); + break; case "--custom": custom_mode = true; @@ -90,11 +133,38 @@ class MakeBundle { Help (); return 1; } + if (sdk_path != null || runtime != null) + Error ("You can not specify one of --runtime, --sdk or --cross"); custom_mode = false; autodeps = true; cross_target = args [++i]; break; + case "--library": + if (i+1 == top){ + Help (); + return 1; + } + if (custom_mode){ + Console.Error.WriteLine ("--library can only be used with --simple/--runtime/--cross mode"); + Help (); + return 1; + } + var lspec = args [++i]; + var p = lspec.IndexOf (","); + string alias, path; + if (p == -1){ + alias = Path.GetFileName (lspec); + path = lspec; + } else { + alias = lspec.Substring (0, p); + path = lspec.Substring (p+1); + } + if (!File.Exists (path)) + Error ($"The specified library file {path} does not exist"); + libraries [alias] = path; + break; + case "--fetch-target": if (i+1 == top){ Help (); @@ -104,10 +174,10 @@ class MakeBundle { break; case "--list-targets": + CommandLocalTargets (); var wc = new WebClient (); - var s = wc.DownloadString (new Uri (target_server + "target-list.txt")); - Console.WriteLine ("Cross-compilation targets available:\n" + s); - + var s = wc.DownloadString (new Uri (target_server + "target-sdks.txt")); + Console.WriteLine ("Targets available for download with --fetch-target:\n" + s); return 0; case "--target-server": @@ -133,11 +203,26 @@ class MakeBundle { } embedded_options = args [++i]; break; + case "--sdk": + if (i + 1 == top) { + Help (); + return 1; + } + custom_mode = false; + autodeps = true; + sdk_path = args [++i]; + if (cross_target != null || runtime != null) + Error ("You can not specify one of --runtime, --sdk or --cross"); + break; case "--runtime": if (i+1 == top){ Help (); return 1; } + if (sdk_path != null || cross_target != null) + Error ("You can only specify one of --runtime, --sdk or --cross"); + custom_mode = false; + autodeps = true; runtime = args [++i]; break; case "-oo": @@ -223,7 +308,7 @@ class MakeBundle { case "linux": break; default: - Console.Error.WriteLine ("Invalid style '{0}' - only 'windows', 'mac' and 'linux' are supported for --style argument", style); + Error ("Invalid style '{0}' - only 'windows', 'mac' and 'linux' are supported for --style argument", style); return 1; } @@ -249,27 +334,58 @@ class MakeBundle { case "--quiet": quiet = true; break; + case "-e": + case "--env": + if (i+1 == top) { + Help (); + return 1; + } + var env = args [++i]; + p = env.IndexOf ('='); + if (p == -1) + environment.Add (env, ""); + else + environment.Add (env.Substring (0, p), env.Substring (p+1)); + break; default: sources.Add (args [i]); break; } } + // Modern bundling starts here + if (!custom_mode){ + if (runtime != null){ + // Nothing to do here, the user has chosen to manually specify --runtime nad libraries + } else if (sdk_path != null) { + VerifySdk (sdk_path); + } else if (cross_target == "default" || cross_target == null){ + sdk_path = Path.GetFullPath (Path.Combine (Process.GetCurrentProcess().MainModule.FileName, "..", "..")); + VerifySdk (sdk_path); + } else { + sdk_path = Path.Combine (targets_dir, cross_target); + Console.WriteLine ("From: " + sdk_path); + VerifySdk (sdk_path); + } + } if (fetch_target != null){ - var truntime = Path.Combine (targets_dir, fetch_target, "mono"); - Directory.CreateDirectory (Path.GetDirectoryName (truntime)); + var directory = Path.Combine (targets_dir, fetch_target); + var zip_download = Path.Combine (directory, "sdk.zip"); + Directory.CreateDirectory (Path.GetDirectoryName (directory)); var wc = new WebClient (); var uri = new Uri ($"{target_server}{fetch_target}"); try { if (!quiet){ - Console.WriteLine ($"Downloading runtime {uri} to {truntime}"); + Console.WriteLine ($"Downloading runtime {uri} to {zip_download}"); } - wc.DownloadFile (uri, truntime); + wc.DownloadFile (uri, zip_download); + ZipFile.ExtractToDirectory(zip_download, directory); + File.Delete (zip_download); } catch { Console.Error.WriteLine ($"Failure to download the specified runtime from {uri}"); - File.Delete (truntime); + File.Delete (zip_download); return 1; } return 0; @@ -286,49 +402,41 @@ class MakeBundle { } List assemblies = LoadAssemblies (sources); + LoadLocalizedAssemblies (assemblies); List files = new List (); foreach (string file in assemblies) if (!QueueAssembly (files, file)) return 1; - if (custom_mode) GenerateBundles (files); - else { - if (cross_target == "default") - runtime = null; - else { - if (runtime == null){ - if (cross_target == null){ - Console.Error.WriteLine ("you should specify either a --runtime or a --cross compilation target"); - Environment.Exit (1); - } - runtime = Path.Combine (targets_dir, cross_target, "mono"); - if (!File.Exists (runtime)){ - Console.Error.WriteLine ($"The runtime for the {cross_target} does not exist, use --fetch-target {cross_target} to download first"); - return 1; - } - } else { - if (!File.Exists (runtime)){ - Console.Error.WriteLine ($"The Mono runtime specified with --runtime does not exist"); - return 1; - } - } - - Console.WriteLine ("Using runtime {0}", runtime); - } + else GeneratePackage (files); - } - + + Console.WriteLine ("Generated {0}", output); + return 0; } + static void VerifySdk (string path) + { + if (!Directory.Exists (path)) + Error ($"The specified SDK path does not exist: {path}"); + runtime = Path.Combine (sdk_path, "bin", "mono"); + if (!File.Exists (runtime)) + Error ($"The SDK location does not contain a {path}/bin/mono runtime"); + lib_path = Path.Combine (path, "lib", "mono", "4.5"); + if (!Directory.Exists (lib_path)) + Error ($"The SDK location does not contain a {path}/lib/mono/4.5 directory"); + link_paths.Add (lib_path); + } + static string targets_dir = Path.Combine (Environment.GetFolderPath (Environment.SpecialFolder.Personal), ".mono", "targets"); static void CommandLocalTargets () { string [] targets; - Console.WriteLine ("Available targets:"); + Console.WriteLine ("Available targets locally:"); Console.WriteLine ("\tdefault\t- Current System Mono"); try { targets = Directory.GetDirectories (targets_dir); @@ -336,7 +444,7 @@ class MakeBundle { return; } foreach (var target in targets){ - var p = Path.Combine (target, "mono"); + var p = Path.Combine (target, "bin", "mono"); if (File.Exists (p)) Console.WriteLine ("\t{0}", Path.GetFileName (target)); } @@ -420,8 +528,9 @@ class MakeBundle { { using (Stream fileStream = File.OpenRead (fname)){ var ret = fileStream.Length; - - Console.WriteLine ("At {0:x} with input {1}", package.Position, fileStream.Length); + + if (!quiet) + Console.WriteLine ("At {0:x} with input {1}", package.Position, fileStream.Length); fileStream.CopyTo (package); package.Position = package.Position + (align - (package.Position % align)); @@ -445,8 +554,30 @@ class MakeBundle { package.Position = package.Position + (align - (package.Position % align)); } + public void AddStringPair (string entry, string key, string value) + { + var kbytes = Encoding.UTF8.GetBytes (key); + var vbytes = Encoding.UTF8.GetBytes (value); + + Console.WriteLine ("ADDING {0} to {1}", key, value); + if (kbytes.Length > 255){ + Console.WriteLine ("The key value can not exceed 255 characters: " + key); + Environment.Exit (1); + } + + locations [entry] = Tuple.Create (package.Position, kbytes.Length+vbytes.Length+3); + package.WriteByte ((byte)kbytes.Length); + package.Write (kbytes, 0, kbytes.Length); + package.WriteByte (0); + package.Write (vbytes, 0, vbytes.Length); + package.WriteByte (0); + package.Position = package.Position + (align - (package.Position % align)); + } + public void Dump () { + if (quiet) + return; foreach (var floc in locations.Keys){ Console.WriteLine ($"{floc} at {locations[floc]:x}"); } @@ -485,7 +616,7 @@ class MakeBundle { return true; if (!File.Exists (file)){ - Console.Error.WriteLine ("The file {0} does not exist", file); + Error ("The file {0} does not exist", file); return false; } maker.Add (code, file); @@ -498,31 +629,36 @@ class MakeBundle { if (IsUnix) runtime = Process.GetCurrentProcess().MainModule.FileName; else { - Console.Error.WriteLine ("You must specify at least one runtime with --runtime or --cross"); + Error ("You must specify at least one runtime with --runtime or --cross"); Environment.Exit (1); } } if (!File.Exists (runtime)){ - Console.Error.WriteLine ($"The specified runtime at {runtime} does not exist"); + Error ($"The specified runtime at {runtime} does not exist"); Environment.Exit (1); } if (ctor_func != null){ - Console.Error.WriteLine ("--static-ctor not supported with package bundling, you must use native compilation for this"); + Error ("--static-ctor not supported with package bundling, you must use native compilation for this"); return false; } var maker = new PackageMaker (output); + Console.WriteLine ("Using runtime: " + runtime); maker.AddFile (runtime); foreach (var url in files){ string fname = LocateFile (new Uri (url).LocalPath); - string aname = Path.GetFileName (fname); + string aname = MakeBundle.GetAssemblyName (fname); maker.Add ("assembly:" + aname, fname); - if (File.Exists (fname + ".config")) + Console.WriteLine (" Assembly: " + fname); + if (File.Exists (fname + ".config")){ maker.Add ("config:" + aname, fname + ".config"); + Console.WriteLine (" Config: " + runtime); + } } + if (!MaybeAddFile (maker, "systemconfig:", config_file) || !MaybeAddFile (maker, "machineconfig:", machine_config_file)) return false; @@ -530,6 +666,16 @@ class MakeBundle { maker.Add ("config_dir:", config_dir); if (embedded_options != null) maker.AddString ("options:", embedded_options); + if (environment.Count > 0){ + foreach (var key in environment.Keys) + maker.AddStringPair ("env:" + key, key, environment [key]); + } + if (libraries.Count > 0){ + foreach (var alias_and_path in libraries){ + Console.WriteLine (" Library: " + alias_and_path.Value); + maker.Add ("library:" + alias_and_path.Key, alias_and_path.Value); + } + } maker.Dump (); maker.Close (); return true; @@ -623,7 +769,7 @@ void mono_register_config_for_assembly (const char* assembly_name, cons var symbolEscapeRE = new System.Text.RegularExpressions.Regex ("[^\\w_]"); foreach (var url in files) { string fname = LocateFile (new Uri (url).LocalPath); - string aname = Path.GetFileName (fname); + string aname = MakeBundle.GetAssemblyName (fname); string encoded = symbolEscapeRE.Replace (aname, "_"); if (prog == null) @@ -676,7 +822,7 @@ void mono_register_config_for_assembly (const char* assembly_name, cons try { conf = File.OpenRead (config_file); } catch { - Error (String.Format ("Failure to open {0}", config_file)); + Error ("Failure to open {0}", config_file); return; } if (!quiet) @@ -695,7 +841,7 @@ void mono_register_config_for_assembly (const char* assembly_name, cons try { conf = File.OpenRead (machine_config_file); } catch { - Error (String.Format ("Failure to open {0}", machine_config_file)); + Error ("Failure to open {0}", machine_config_file); return; } if (!quiet) @@ -782,7 +928,7 @@ void mono_register_config_for_assembly (const char* assembly_name, cons string monoPath = GetEnv("MONOPREFIX", @"C:\Program Files (x86)\Mono"); string[] includes = new string[] {winsdkPath + @"\Include\um", winsdkPath + @"\Include\shared", vsPath + @"\include", monoPath + @"\include\mono-2.0", "." }; - string[] libs = new string[] { winsdkPath + @"\Lib\winv6.3\um\x86" , vsPath + @"\lib" }; + // string[] libs = new string[] { winsdkPath + @"\Lib\winv6.3\um\x86" , vsPath + @"\lib" }; var linkLibraries = new string[] { "kernel32.lib", "version.lib", "Ws2_32.lib", @@ -903,10 +1049,10 @@ void mono_register_config_for_assembly (const char* assembly_name, cons { List assemblies = new List (); bool error = false; - + foreach (string name in sources){ try { - Assembly a = LoadAssembly (name); + Assembly a = LoadAssemblyFile (name); if (a == null){ error = true; @@ -927,24 +1073,75 @@ void mono_register_config_for_assembly (const char* assembly_name, cons if (error) Environment.Exit (1); - + return assemblies; } + + static void LoadLocalizedAssemblies (List assemblies) + { + var other = i18n.Select (x => "I18N." + x + (x.Length > 0 ? "." : "") + "dll"); + bool error = false; + + foreach (string name in other) { + try { + Assembly a = LoadAssembly (name); + + if (a == null) { + error = true; + continue; + } + + assemblies.Add (a.CodeBase); + } catch (Exception) { + if (skip_scan) { + if (!quiet) + Console.WriteLine ("File will not be scanned: {0}", name); + assemblies.Add (new Uri (new FileInfo (name).FullName).ToString ()); + } else { + throw; + } + } + } + + if (error) + Environment.Exit (1); + } + static readonly Universe universe = new Universe (); static readonly Dictionary loaded_assemblies = new Dictionary (); - + + public static string GetAssemblyName (string path) + { + string name = Path.GetFileName (path); + + // A bit of a hack to support satellite assemblies. They all share the same name but + // are placed in subdirectories named after the locale they implement. Also, all of + // them end in .resources.dll, therefore we can use that to detect the circumstances. + if (name.EndsWith (".resources.dll", StringComparison.OrdinalIgnoreCase)) { + string dir = Path.GetDirectoryName (path); + int idx = dir.LastIndexOf (Path.DirectorySeparatorChar); + if (idx >= 0) { + name = dir.Substring (idx + 1) + Path.DirectorySeparatorChar + name; + Console.WriteLine ($"Storing satellite assembly '{path}' with name '{name}'"); + } else if (!quiet) + Console.WriteLine ($"Warning: satellite assembly {path} doesn't have locale path prefix, name conflicts possible"); + } + + return name; + } + static bool QueueAssembly (List files, string codebase) { - // Console.WriteLine ("CODE BASE IS {0}", codebase); + //Console.WriteLine ("CODE BASE IS {0}", codebase); if (files.Contains (codebase)) return true; var path = new Uri(codebase).LocalPath; - var name = Path.GetFileName (path); + var name = GetAssemblyName (path); string found; if (loaded_assemblies.TryGetValue (name, out found)) { - Error (string.Format ("Duplicate assembly name `{0}'. Both `{1}' and `{2}' use same assembly name.", name, path, found)); + Error ("Duplicate assembly name `{0}'. Both `{1}' and `{2}' use same assembly name.", name, path, found); return false; } @@ -957,7 +1154,7 @@ void mono_register_config_for_assembly (const char* assembly_name, cons Assembly a = universe.LoadFile (path); foreach (AssemblyName an in a.GetReferencedAssemblies ()) { - a = universe.Load (an.FullName); + LoadAssembly (an.FullName); if (!QueueAssembly (files, a.CodeBase)) return false; } @@ -969,56 +1166,57 @@ void mono_register_config_for_assembly (const char* assembly_name, cons return true; } - static Assembly LoadAssembly (string assembly) + // + // Loads an assembly from a specific path + // + static Assembly LoadAssemblyFile (string assembly) { - Assembly a; + Assembly a = null; try { - char[] path_chars = { '/', '\\' }; - - if (assembly.IndexOfAny (path_chars) != -1) { - a = universe.LoadFile (assembly); - } else { - string ass = assembly; - if (ass.EndsWith (".dll")) - ass = assembly.Substring (0, assembly.Length - 4); - a = universe.Load (ass); - } - return a; + a = universe.LoadFile (assembly); } catch (FileNotFoundException){ - string total_log = ""; - - foreach (string dir in link_paths){ - string full_path = Path.Combine (dir, assembly); - if (!assembly.EndsWith (".dll") && !assembly.EndsWith (".exe")) - full_path += ".dll"; - - try { - a = universe.LoadFile (full_path); - return a; - } catch (FileNotFoundException ff) { - total_log += ff.FusionLog; - continue; - } - } - Error ("Cannot find assembly `" + assembly + "'" ); - if (!quiet) - Console.WriteLine ("Log: \n" + total_log); + Error ($"Cannot find assembly `{assembly}'"); } catch (IKVM.Reflection.BadImageFormatException f) { if (skip_scan) throw; - Error ("Cannot load assembly (bad file format) " + f.Message); + Error ($"Cannot load assembly (bad file format) " + f.Message); } catch (FileLoadException f){ - Error ("Cannot load assembly " + f.Message); + Error ($"Cannot load assembly " + f.Message); } catch (ArgumentNullException){ - Error("Cannot load assembly (null argument)"); + Error( $"Cannot load assembly (null argument)"); } - return null; + return a; } - static void Error (string msg) + // + // Loads an assembly from any of the link directories provided + // + static Assembly LoadAssembly (string assembly) { - Console.Error.WriteLine ("ERROR: " + msg); + string total_log = ""; + foreach (string dir in link_paths){ + string full_path = Path.Combine (dir, assembly); + if (!assembly.EndsWith (".dll") && !assembly.EndsWith (".exe")) + full_path += ".dll"; + + try { + var a = universe.LoadFile (full_path); + return a; + } catch (FileNotFoundException ff) { + total_log += ff.FusionLog; + continue; + } + } + if (!quiet) + Console.WriteLine ("Log: \n" + total_log); + return null; + } + + static void Error (string msg, params object [] args) + { + Console.Error.WriteLine ("ERROR: {0}", string.Format (msg, args)); + throw new Exception (); Environment.Exit (1); } @@ -1026,37 +1224,44 @@ void mono_register_config_for_assembly (const char* assembly_name, cons { Console.WriteLine ("Usage is: mkbundle [options] assembly1 [assembly2...]\n\n" + "Options:\n" + - " --config F Bundle system config file `F'\n" + - " --config-dir D Set MONO_CFG_DIR to `D'\n" + - " --deps Turns on automatic dependency embedding (default on simple)\n" + - " -L path Adds `path' to the search path for assemblies\n" + - " --machine-config F Use the given file as the machine.config for the application.\n" + - " -o out Specifies output filename\n" + - " --nodeps Turns off automatic dependency embedding (default on custom)\n" + - " --skip-scan Skip scanning assemblies that could not be loaded (but still embed them).\n" + + " --config F Bundle system config file `F'\n" + + " --config-dir D Set MONO_CFG_DIR to `D'\n" + + " --deps Turns on automatic dependency embedding (default on simple)\n" + + " -L path Adds `path' to the search path for assemblies\n" + + " --machine-config F Use the given file as the machine.config for the application.\n" + + " -o out Specifies output filename\n" + + " --nodeps Turns off automatic dependency embedding (default on custom)\n" + + " --skip-scan Skip scanning assemblies that could not be loaded (but still embed them).\n" + + " --i18n ENCODING none, all or comma separated list of CJK, MidWest, Other, Rare, West.\n" + + " -v Verbose output\n" + "\n" + "--simple Simple mode does not require a C toolchain and can cross compile\n" + - " --cross TARGET Generates a binary for the given TARGET\n"+ - " --local-targets Lists locally available targets\n" + - " --list-targets Lists available targets on the remote server\n" + - " --options OPTIONS Embed the specified Mono command line options on target\n" + - " --runtime RUNTIME Manually specifies the Mono runtime to use\n" + - " --target-server URL Specified a server to download targets from, default is " + target_server + "\n" + + " --cross TARGET Generates a binary for the given TARGET\n"+ + " --env KEY=VALUE Hardcodes an environment variable for the target\n" + + " --fetch-target NAME Downloads the target SDK from the remote server\n" + + " --library [LIB,]PATH Bundles the specified dynamic library to be used at runtime\n" + + " LIB is optional shortname for file located at PATH\n" + + " --list-targets Lists available targets on the remote server\n" + + " --local-targets Lists locally available targets\n" + + " --options OPTIONS Embed the specified Mono command line options on target\n" + + " --runtime RUNTIME Manually specifies the Mono runtime to use\n" + + " --sdk PATH Use a Mono SDK root location instead of a target\n" + + " --target-server URL Specified a server to download targets from, default is " + target_server + "\n" + "\n" + "--custom Builds a custom launcher, options for --custom\n" + - " -c Produce stub only, do not compile\n" + - " -oo obj Specifies output filename for helper object file\n" + + " -c Produce stub only, do not compile\n" + + " -oo obj Specifies output filename for helper object file\n" + " --dos2unix[=true|false]\n" + - " When no value provided, or when `true` specified\n" + - " `dos2unix` will be invoked to convert paths on Windows.\n" + - " When `--dos2unix=false` used, dos2unix is NEVER used.\n" + - " --keeptemp Keeps the temporary files\n" + - " --static Statically link to mono libs\n" + - " --nomain Don't include a main() function, for libraries\n" + - " --custom-main C Link the specified compilation unit (.c or .obj) with entry point/init code\n" + - " -z Compress the assemblies before embedding.\n" + - " --static-ctor ctor Add a constructor call to the supplied function.\n" + - " You need zlib development headers and libraries.\n"); + " When no value provided, or when `true` specified\n" + + " `dos2unix` will be invoked to convert paths on Windows.\n" + + " When `--dos2unix=false` used, dos2unix is NEVER used.\n" + + " --keeptemp Keeps the temporary files\n" + + " --static Statically link to mono libs\n" + + " --nomain Don't include a main() function, for libraries\n" + + " --custom-main C Link the specified compilation unit (.c or .obj) with entry point/init code\n" + + " -z Compress the assemblies before embedding.\n" + + " --static-ctor ctor Add a constructor call to the supplied function.\n" + + " You need zlib development headers and libraries.\n"); } [DllImport ("libc")] @@ -1171,7 +1376,7 @@ void mono_register_config_for_assembly (const char* assembly_name, cons p.WaitForExit (); int ret = p.ExitCode; if (ret != 0){ - Error (String.Format("[Fail] {0}", ret)); + Error ("[Fail] {0}", ret); } } } diff --git a/mcs/tools/mono-api-html/ApiDiff.cs b/mcs/tools/mono-api-html/ApiDiff.cs index 8fe2784485..0f4cd7c2d9 100644 --- a/mcs/tools/mono-api-html/ApiDiff.cs +++ b/mcs/tools/mono-api-html/ApiDiff.cs @@ -78,10 +78,11 @@ namespace Xamarin.ApiDiff { public static bool IgnoreVirtualChanges { get; set; } public static bool IgnoreAddedPropertySetters { get; set; } + public static bool IgnoreNonbreaking { get; set; } + public static bool Lax; public static bool Colorize = true; } - class Program { public static int Main (string[] args) @@ -120,7 +121,8 @@ namespace Xamarin.ApiDiff { v => State.IgnoreVirtualChanges = v != null }, { "c|colorize:", "Colorize HTML output", v => State.Colorize = string.IsNullOrEmpty (v) ? true : bool.Parse (v) }, - { "x|lax", "Ignore duplicate XML entries", v => State.Lax = true } + { "x|lax", "Ignore duplicate XML entries", v => State.Lax = true }, + { "ignore-nonbreaking", "Ignore all nonbreaking changes", v => State.IgnoreNonbreaking = true } }; try { @@ -130,6 +132,13 @@ namespace Xamarin.ApiDiff { showHelp = true; } + if (State.IgnoreNonbreaking) { + State.IgnoreAddedPropertySetters = true; + State.IgnoreVirtualChanges = true; + State.IgnoreNew.Add (new Regex (".*")); + State.IgnoreAdded.Add (new Regex (".*")); + } + if (showHelp || extra == null || extra.Count < 2 || extra.Count > 3) { Console.WriteLine (@"Usage: mono-api-html [options] [diff.html]"); Console.WriteLine (); @@ -253,9 +262,11 @@ namespace Xamarin.ApiDiff { } else { file.WriteLine ("

{0}.dll vs {1}.dll

", ac.SourceAssembly, ac.TargetAssembly); } - file.WriteLine ("Hide non-breaking changes"); - file.WriteLine (""); - file.WriteLine ("
"); + if (!State.IgnoreNonbreaking) { + file.WriteLine ("Hide non-breaking changes"); + file.WriteLine (""); + file.WriteLine ("
"); + } file.WriteLine ("
"); file.Write (diffHtml); file.WriteLine ("
"); diff --git a/mcs/tools/mono-api-html/AssemblyComparer.cs b/mcs/tools/mono-api-html/AssemblyComparer.cs index adbd862eb9..f09ab497ee 100644 --- a/mcs/tools/mono-api-html/AssemblyComparer.cs +++ b/mcs/tools/mono-api-html/AssemblyComparer.cs @@ -66,7 +66,13 @@ namespace Xamarin.ApiDiff { { SourceAssembly = source.GetAttribute ("name"); TargetAssembly = target.GetAttribute ("name"); - // TODO: version + + var sb = source.GetAttribute ("version"); + var tb = target.GetAttribute ("version"); + if (sb != tb) { + Output.WriteLine ("

Assembly Version Changed: {0} vs {1}

", tb, sb); + } + // ? custom attributes ? comparer.Compare (source, target); } diff --git a/mcs/tools/mono-api-html/ClassComparer.cs b/mcs/tools/mono-api-html/ClassComparer.cs index a3399fbef0..f6cf940c9e 100644 --- a/mcs/tools/mono-api-html/ClassComparer.cs +++ b/mcs/tools/mono-api-html/ClassComparer.cs @@ -198,6 +198,20 @@ namespace Xamarin.ApiDiff { Indent ().WriteLine ("}"); } + //HACK: we don't have hierarchy information here so just check some basic heuristics for now + bool IsBaseChangeCompatible (string source, string target) + { + if (source == "System.Object") + return true; + if (source == "System.Exception" && target.EndsWith ("Exception", StringComparison.Ordinal)) + return true; + if (source == "System.EventArgs" && target.EndsWith ("EventArgs", StringComparison.Ordinal)) + return true; + if (source == "System.Runtime.InteropServices.SafeHandle" && target.StartsWith ("Microsoft.Win32.SafeHandles.SafeHandle", StringComparison.Ordinal)) + return true; + return false; + } + public override void Modified (XElement source, XElement target, ApiChanges diff) { // hack - there could be changes that we're not monitoring (e.g. attributes properties) @@ -206,7 +220,7 @@ namespace Xamarin.ApiDiff { var sb = source.GetAttribute ("base"); var tb = target.GetAttribute ("base"); - if (sb != tb) { + if (sb != tb && !(State.IgnoreNonbreaking && IsBaseChangeCompatible (sb, tb))) { Output.Write ("Modified base type: "); Output.WriteLine (new ApiChange ().AppendModified (sb, tb, true).Member.ToString ()); } diff --git a/mcs/tools/mono-api-html/FieldComparer.cs b/mcs/tools/mono-api-html/FieldComparer.cs index a2b0225b44..f292eee22d 100644 --- a/mcs/tools/mono-api-html/FieldComparer.cs +++ b/mcs/tools/mono-api-html/FieldComparer.cs @@ -45,14 +45,16 @@ namespace Xamarin.ApiDiff { void RenderFieldAttributes (FieldAttributes source, FieldAttributes target, ApiChange change) { - var srcNotSerialized = (source & FieldAttributes.NotSerialized) == FieldAttributes.NotSerialized; - var tgtNotSerialized = (target & FieldAttributes.NotSerialized) == FieldAttributes.NotSerialized; - if (srcNotSerialized != tgtNotSerialized) { - // this is not a breaking change, so only render it if it changed. - if (srcNotSerialized) { - change.AppendRemoved ("[NonSerialized]\n"); - } else { - change.AppendAdded ("[NonSerialized]\n"); + if (!State.IgnoreNonbreaking) { + var srcNotSerialized = (source & FieldAttributes.NotSerialized) == FieldAttributes.NotSerialized; + var tgtNotSerialized = (target & FieldAttributes.NotSerialized) == FieldAttributes.NotSerialized; + if (srcNotSerialized != tgtNotSerialized) { + // this is not a breaking change, so only render it if it changed. + if (srcNotSerialized) { + change.AppendRemoved ("[NonSerialized]\n"); + } else { + change.AppendAdded ("[NonSerialized]\n"); + } } } diff --git a/mcs/tools/mono-api-html/MemberComparer.cs b/mcs/tools/mono-api-html/MemberComparer.cs index d12d86625c..2acb5ca3f5 100644 --- a/mcs/tools/mono-api-html/MemberComparer.cs +++ b/mcs/tools/mono-api-html/MemberComparer.cs @@ -138,9 +138,13 @@ namespace Xamarin.ApiDiff { void Modify (ApiChanges modified) { foreach (var changes in modified) { + if (State.IgnoreNonbreaking && changes.Value.All (c => !c.Breaking)) + continue; Output.WriteLine ("

{0}:

", changes.Key); Output.WriteLine ("
");
 				foreach (var element in changes.Value) {
+					if (State.IgnoreNonbreaking && !element.Breaking)
+						continue;
 					Output.Write ("
", element.Breaking ? "data-is-breaking" : "data-is-non-breaking"); foreach (var line in element.Member.ToString ().Split ('\n')) Output.WriteLine ("\t{0}", line); @@ -158,6 +162,8 @@ namespace Xamarin.ApiDiff { if (State.IgnoreRemoved.Any (re => re.IsMatch (GetDescription (item)))) continue; SetContext (item); + if (State.IgnoreNonbreaking && !IsBreakingRemoval (item)) + continue; if (!r) { BeforeRemoving (elements); r = true; @@ -336,10 +342,19 @@ namespace Xamarin.ApiDiff { if (i > 0) change.Append (", "); + string mods_tgt = tgt [i].GetAttribute ("direction") ?? ""; + string mods_src = src [i].GetAttribute ("direction") ?? ""; + + if (mods_tgt.Length > 0) + mods_tgt = mods_tgt + " "; + + if (mods_src.Length > 0) + mods_src = mods_src + " "; + if (i >= srcCount) { - change.AppendAdded (tgt [i].GetTypeName ("type") + " " + tgt [i].GetAttribute ("name"), true); + change.AppendAdded (mods_tgt + tgt [i].GetTypeName ("type") + " " + tgt [i].GetAttribute ("name"), true); } else if (i >= tgtCount) { - change.AppendRemoved (src [i].GetTypeName ("type") + " " + src [i].GetAttribute ("name"), true); + change.AppendRemoved (mods_src + src [i].GetTypeName ("type") + " " + src [i].GetAttribute ("name"), true); } else { var paramSourceType = src [i].GetTypeName ("type"); var paramTargetType = tgt [i].GetTypeName ("type"); @@ -347,6 +362,12 @@ namespace Xamarin.ApiDiff { var paramSourceName = src [i].GetAttribute ("name"); var paramTargetName = tgt [i].GetAttribute ("name"); + if (mods_src != mods_tgt) { + change.AppendModified (mods_src, mods_tgt, true); + } else { + change.Append (mods_src); + } + if (paramSourceType != paramTargetType) { change.AppendModified (paramSourceType, paramTargetType, true); } else { @@ -354,7 +375,7 @@ namespace Xamarin.ApiDiff { } change.Append (" "); if (paramSourceName != paramTargetName) { - change.AppendModified (paramSourceName, paramTargetName, false); + change.AppendModified (paramSourceName, paramTargetName, true); } else { change.Append (paramSourceName); } @@ -418,8 +439,13 @@ namespace Xamarin.ApiDiff { if (tgtAbstract) { change.AppendAdded ("abstract", true).Append (" "); } else if (srcWord != tgtWord) { - if (!tgtFinal) - change.AppendModified (srcWord, tgtWord, breaking).Append (" "); + if (!tgtFinal) { + if (State.IgnoreVirtualChanges) { + change.HasIgnoredChanges = true; + } else { + change.AppendModified (srcWord, tgtWord, breaking).Append (" "); + } + } } else if (tgtWord.Length > 0) { change.Append (tgtWord).Append (" "); } else if (srcWord.Length > 0) { @@ -431,7 +457,11 @@ namespace Xamarin.ApiDiff { if (tgtFinal) { change.Append ("final "); } else { - change.AppendRemoved ("final", false).Append (" "); // removing 'final' is not a breaking change. + if (srcVirtual && !tgtVirtual && State.IgnoreVirtualChanges) { + change.HasIgnoredChanges = true; + } else { + change.AppendRemoved ("final", false).Append (" "); // removing 'final' is not a breaking change. + } } } else { if (tgtFinal && srcVirtual) { diff --git a/mcs/tools/mono-symbolicate/LocationProvider.cs b/mcs/tools/mono-symbolicate/LocationProvider.cs index c3a97993c6..68387807a5 100644 --- a/mcs/tools/mono-symbolicate/LocationProvider.cs +++ b/mcs/tools/mono-symbolicate/LocationProvider.cs @@ -72,15 +72,22 @@ namespace Mono if (ilOffset < 0) return false; - SequencePoint sp = null; - foreach (var instr in method.Body.Instructions) { - if (instr.SequencePoint != null) - sp = instr.SequencePoint; - - if (instr.Offset >= ilOffset) { + if (!method.DebugInformation.HasSequencePoints) + return false; + + SequencePoint prev = null; + foreach (var sp in method.DebugInformation.SequencePoints.OrderBy (l => l.Offset)) { + if (sp.Offset >= ilOffset) { sfData.SetLocation (sp.Document.Url, sp.StartLine); return true; } + + prev = sp; + } + + if (prev != null) { + sfData.SetLocation (prev.Document.Url, prev.StartLine); + return true; } return false; diff --git a/mcs/tools/mono-symbolicate/Makefile b/mcs/tools/mono-symbolicate/Makefile index 67c98b7dd1..884bea5a11 100644 --- a/mcs/tools/mono-symbolicate/Makefile +++ b/mcs/tools/mono-symbolicate/Makefile @@ -27,7 +27,7 @@ CHECK_DIFF = @\ $(MONO) $(TEST_EXE) > $(STACKTRACE_FILE); \ $(MONO) $(LIB_PATH)/$(PROGRAM) $(MSYM_DIR) $(STACKTRACE_FILE) > $(SYMBOLICATE_RAW_FILE); \ sed "s/) .* in .*\/mcs\//) in mcs\//" $(SYMBOLICATE_RAW_FILE) | sed '/\[MVID\]/d' | sed '/\[AOTID\]/d' > $(SYMBOLICATE_RESULT_FILE); \ - DIFF=$$(diff $(SYMBOLICATE_RESULT_FILE) $(SYMBOLICATE_EXPECTED_FILE)); \ + DIFF=$$(diff -up $(SYMBOLICATE_EXPECTED_FILE) $(SYMBOLICATE_RESULT_FILE)); \ if [ ! -z "$$DIFF" ]; then \ echo "Symbolicate tests failed."; \ echo "If $(SYMBOLICATE_RESULT_FILE) is correct copy it to $(SYMBOLICATE_EXPECTED_FILE)."; \ diff --git a/mcs/tools/mono-symbolicate/SymbolManager.cs b/mcs/tools/mono-symbolicate/SymbolManager.cs index 734aa3a166..a204788306 100644 --- a/mcs/tools/mono-symbolicate/SymbolManager.cs +++ b/mcs/tools/mono-symbolicate/SymbolManager.cs @@ -57,7 +57,7 @@ namespace Mono return null; } - assemblyPath = (exeFiles.Length > 0)? exeFiles[0] : dllFiles[0]; + assemblyPath = exeFiles.Length > 0 ? exeFiles[0] : dllFiles[0]; var locProvider = new AssemblyLocationProvider (assemblyPath, logger); @@ -97,10 +97,13 @@ namespace Mono var dllFiles = Directory.GetFiles (dir, "*.dll"); var assemblies = exeFiles.Concat (dllFiles); foreach (var assemblyPath in assemblies) { - var mdbPath = assemblyPath + ".mdb"; - if (!File.Exists (mdbPath)) { - logger.LogWarning ("Directory {0} contains {1} but no mdb {2}.", dir, Path.GetFileName (assemblyPath), Path.GetFileName (mdbPath)); - // assemblies without mdb files are useless + + // TODO: Ignore embedded pdb + var symbolFile = GetSymbolFile (assemblyPath); + + if (symbolFile == null) { + logger.LogWarning ("Directory {0} contains {1} but no debug symbols file was found.", dir, Path.GetFileName (assemblyPath)); + // assemblies without debug symbols are useless continue; } @@ -112,7 +115,7 @@ namespace Mono if (Directory.Exists (mvidDir)) { try { Directory.Delete (mvidDir, true); - } catch (DirectoryNotFoundException e) {} + } catch (DirectoryNotFoundException) {} } Directory.CreateDirectory (mvidDir); @@ -120,12 +123,26 @@ namespace Mono var mvidAssemblyPath = Path.Combine (mvidDir, Path.GetFileName (assemblyPath)); File.Copy (assemblyPath, mvidAssemblyPath); - var mvidMdbPath = Path.Combine (mvidDir, Path.GetFileName (mdbPath)); - File.Copy (mdbPath, mvidMdbPath); + var mvidDebugPath = Path.Combine (mvidDir, Path.GetFileName (symbolFile)); + File.Copy (symbolFile, mvidDebugPath); // TODO create MVID dir for non main modules with links to main module MVID } } } + + static string GetSymbolFile (string assembly) + { + var pdbName = Path.ChangeExtension (assembly, "pdb"); + if (File.Exists (pdbName)) + return pdbName; + + var mdbName = assembly + ".mdb"; + + if (File.Exists (mdbName)) + return mdbName; + + return null; + } } } diff --git a/mcs/tools/security/cert-sync.cs b/mcs/tools/security/cert-sync.cs index ac2c2ef82c..56797562e5 100644 --- a/mcs/tools/security/cert-sync.cs +++ b/mcs/tools/security/cert-sync.cs @@ -50,6 +50,7 @@ namespace Mono.Tools static string inputFile; static bool quiet; static bool userStore; + static bool btlsStore = false; static X509Certificate DecodeCertificate (string s) { @@ -116,14 +117,19 @@ namespace Mono.Tools return 0; } - X509Stores stores = userStore ? X509StoreManager.CurrentUser : X509StoreManager.LocalMachine; - X509CertificateCollection trusted = stores.TrustedRoot.Certificates; + X509Stores stores; + if (userStore) + stores = btlsStore ? X509StoreManager.NewCurrentUser : X509StoreManager.CurrentUser; + else + stores = btlsStore ? X509StoreManager.NewLocalMachine : X509StoreManager.LocalMachine; + X509Store store = stores.TrustedRoot; + X509CertificateCollection trusted = store.Certificates; int additions = 0; WriteLine ("I already trust {0}, your new list has {1}", trusted.Count, roots.Count); foreach (X509Certificate root in roots) { if (!trusted.Contains (root)) { try { - stores.TrustedRoot.Import (root); + store.Import (root); WriteLine ("Certificate added: {0}", root.SubjectName); additions++; } catch (Exception e) { @@ -145,7 +151,7 @@ namespace Mono.Tools WriteLine ("{0} previously trusted certificates were removed.", removed.Count); foreach (X509Certificate old in removed) { - stores.TrustedRoot.Remove (old); + store.Remove (old); WriteLine ("Certificate removed: {0}", old.SubjectName); } } @@ -173,6 +179,9 @@ namespace Mono.Tools case "--user": userStore = true; break; + case "--btls": + btlsStore = true; + break; default: WriteLine ("Unknown option '{0}'.", args[i]); return false; @@ -228,4 +237,4 @@ namespace Mono.Tools } } } -} \ No newline at end of file +} diff --git a/mcs/tools/tuner/Mono.Tuner/CheckVisibility.cs b/mcs/tools/tuner/Mono.Tuner/CheckVisibility.cs index 144702556a..df553db5ab 100644 --- a/mcs/tools/tuner/Mono.Tuner/CheckVisibility.cs +++ b/mcs/tools/tuner/Mono.Tuner/CheckVisibility.cs @@ -86,8 +86,8 @@ namespace Mono.Tuner { void CheckInterfaces (TypeDefinition type) { - foreach (TypeReference iface in type.Interfaces) { - if (!IsVisibleFrom (type, iface)) { + foreach (var iface in type.Interfaces) { + if (!IsVisibleFrom (type, iface.InterfaceType)) { ReportError ("Interface `{0}` implemented by `{1}` is not visible", iface, type); } diff --git a/mcs/tools/tuner/Mono.Tuner/MoonlightA11yProcessor.cs b/mcs/tools/tuner/Mono.Tuner/MoonlightA11yProcessor.cs index d8d9e54bea..2971b11ad5 100644 --- a/mcs/tools/tuner/Mono.Tuner/MoonlightA11yProcessor.cs +++ b/mcs/tools/tuner/Mono.Tuner/MoonlightA11yProcessor.cs @@ -149,8 +149,8 @@ namespace Mono.Tuner { TypeDefinition baseType = finalType; while (baseType != null) { if (baseType.HasInterfaces) - foreach (TypeReference @interface in baseType.Interfaces) - foreach (MethodDefinition method in @interface.Resolve ().Methods) + foreach (var @interface in baseType.Interfaces) + foreach (MethodDefinition method in @interface.InterfaceType.Resolve ().Methods) if (method.Name == final.Name && HasSameSignature (method, final)) return method; diff --git a/mcs/tools/tuner/Mono.Tuner/RemoveSerialization.cs b/mcs/tools/tuner/Mono.Tuner/RemoveSerialization.cs index 1266c9d31a..d38aef196c 100644 --- a/mcs/tools/tuner/Mono.Tuner/RemoveSerialization.cs +++ b/mcs/tools/tuner/Mono.Tuner/RemoveSerialization.cs @@ -68,7 +68,7 @@ namespace Mono.Tuner { static void RemoveInterface (TypeDefinition type, string name) { for (int i = 0; i < type.Interfaces.Count; i++) { - TypeReference iface = type.Interfaces [i]; + TypeReference iface = type.Interfaces [i].InterfaceType; if (iface.FullName == name) { type.Interfaces.RemoveAt (i); return; diff --git a/mono/Makefile.am b/mono/Makefile.am index 7bf7b5c3de..651271c25f 100644 --- a/mono/Makefile.am +++ b/mono/Makefile.am @@ -2,11 +2,15 @@ if SUPPORT_SGEN sgen_dirs = sgen endif +if BTLS +btls_dirs = btls +endif + if CROSS_COMPILING -SUBDIRS = arch utils io-layer cil metadata $(sgen_dirs) mini dis profiler +SUBDIRS = $(btls_dirs) arch utils io-layer cil metadata $(sgen_dirs) mini dis profiler else if INSTALL_MONOTOUCH -SUBDIRS = arch utils io-layer metadata $(sgen_dirs) mini profiler +SUBDIRS = $(btls_dirs) arch utils io-layer metadata $(sgen_dirs) mini profiler monotouch-do-build: @list='$(SUBDIRS)'; for subdir in $$list; do \ @@ -30,7 +34,7 @@ monotouch-do-clean: (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$target); \ done; else -SUBDIRS = arch utils io-layer cil metadata $(sgen_dirs) mini dis tests unit-tests benchmark profiler +SUBDIRS = $(btls_dirs) arch utils io-layer cil metadata $(sgen_dirs) mini dis tests unit-tests benchmark profiler endif endif -DIST_SUBDIRS = arch utils io-layer cil metadata $(sgen_dirs) mini dis tests unit-tests benchmark profiler +DIST_SUBDIRS = btls arch utils io-layer cil metadata $(sgen_dirs) mini dis tests unit-tests benchmark profiler diff --git a/mono/Makefile.in b/mono/Makefile.in index 65867b67ed..8cdfe8e041 100644 --- a/mono/Makefile.in +++ b/mono/Makefile.in @@ -179,6 +179,8 @@ am__relativize = \ ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AOT_BUILD_FLAGS = @AOT_BUILD_FLAGS@ +AOT_RUN_FLAGS = @AOT_RUN_FLAGS@ API_VER = @API_VER@ AR = @AR@ AS = @AS@ @@ -187,6 +189,11 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOEHM_DEFINES = @BOEHM_DEFINES@ +BTLS_ARCH = @BTLS_ARCH@ +BTLS_CFLAGS = @BTLS_CFLAGS@ +BTLS_CMAKE_ARGS = @BTLS_CMAKE_ARGS@ +BTLS_PLATFORM = @BTLS_PLATFORM@ +BTLS_ROOT = @BTLS_ROOT@ BUILD_EXEEXT = @BUILD_EXEEXT@ CC = @CC@ CCAS = @CCAS@ @@ -196,6 +203,7 @@ CCDEPMODE = @CCDEPMODE@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMAKE = @CMAKE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ @@ -216,7 +224,6 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_PERF_EVENTS = @ENABLE_PERF_EVENTS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDKX11 = @GDKX11@ @@ -231,10 +238,12 @@ HAVE_MSGFMT = @HAVE_MSGFMT@ HOST_CC = @HOST_CC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MOBILE_STATIC = @INSTALL_MOBILE_STATIC@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTL = @INTL@ +INVARIANT_AOT_OPTIONS = @INVARIANT_AOT_OPTIONS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBC = @LIBC@ @@ -281,6 +290,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ +PLATFORM_AOT_SUFFIX = @PLATFORM_AOT_SUFFIX@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -290,6 +300,7 @@ SHELL = @SHELL@ SQLITE = @SQLITE@ SQLITE3 = @SQLITE3@ STRIP = @STRIP@ +TEST_PROFILE = @TEST_PROFILE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VTUNE_CFLAGS = @VTUNE_CFLAGS@ @@ -379,10 +390,11 @@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ @SUPPORT_SGEN_TRUE@sgen_dirs = sgen -@CROSS_COMPILING_FALSE@@INSTALL_MONOTOUCH_FALSE@SUBDIRS = arch utils io-layer cil metadata $(sgen_dirs) mini dis tests unit-tests benchmark profiler -@CROSS_COMPILING_FALSE@@INSTALL_MONOTOUCH_TRUE@SUBDIRS = arch utils io-layer metadata $(sgen_dirs) mini profiler -@CROSS_COMPILING_TRUE@SUBDIRS = arch utils io-layer cil metadata $(sgen_dirs) mini dis profiler -DIST_SUBDIRS = arch utils io-layer cil metadata $(sgen_dirs) mini dis tests unit-tests benchmark profiler +@BTLS_TRUE@btls_dirs = btls +@CROSS_COMPILING_FALSE@@INSTALL_MONOTOUCH_FALSE@SUBDIRS = $(btls_dirs) arch utils io-layer cil metadata $(sgen_dirs) mini dis tests unit-tests benchmark profiler +@CROSS_COMPILING_FALSE@@INSTALL_MONOTOUCH_TRUE@SUBDIRS = $(btls_dirs) arch utils io-layer metadata $(sgen_dirs) mini profiler +@CROSS_COMPILING_TRUE@SUBDIRS = $(btls_dirs) arch utils io-layer cil metadata $(sgen_dirs) mini dis profiler +DIST_SUBDIRS = btls arch utils io-layer cil metadata $(sgen_dirs) mini dis tests unit-tests benchmark profiler all: all-recursive .SUFFIXES: diff --git a/mono/arch/Makefile.in b/mono/arch/Makefile.in index 3eeffdeb84..318e037ef6 100644 --- a/mono/arch/Makefile.in +++ b/mono/arch/Makefile.in @@ -179,6 +179,8 @@ am__relativize = \ ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AOT_BUILD_FLAGS = @AOT_BUILD_FLAGS@ +AOT_RUN_FLAGS = @AOT_RUN_FLAGS@ API_VER = @API_VER@ AR = @AR@ AS = @AS@ @@ -187,6 +189,11 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOEHM_DEFINES = @BOEHM_DEFINES@ +BTLS_ARCH = @BTLS_ARCH@ +BTLS_CFLAGS = @BTLS_CFLAGS@ +BTLS_CMAKE_ARGS = @BTLS_CMAKE_ARGS@ +BTLS_PLATFORM = @BTLS_PLATFORM@ +BTLS_ROOT = @BTLS_ROOT@ BUILD_EXEEXT = @BUILD_EXEEXT@ CC = @CC@ CCAS = @CCAS@ @@ -196,6 +203,7 @@ CCDEPMODE = @CCDEPMODE@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMAKE = @CMAKE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ @@ -216,7 +224,6 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_PERF_EVENTS = @ENABLE_PERF_EVENTS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDKX11 = @GDKX11@ @@ -231,10 +238,12 @@ HAVE_MSGFMT = @HAVE_MSGFMT@ HOST_CC = @HOST_CC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MOBILE_STATIC = @INSTALL_MOBILE_STATIC@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTL = @INTL@ +INVARIANT_AOT_OPTIONS = @INVARIANT_AOT_OPTIONS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBC = @LIBC@ @@ -281,6 +290,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ +PLATFORM_AOT_SUFFIX = @PLATFORM_AOT_SUFFIX@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -290,6 +300,7 @@ SHELL = @SHELL@ SQLITE = @SQLITE@ SQLITE3 = @SQLITE3@ STRIP = @STRIP@ +TEST_PROFILE = @TEST_PROFILE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VTUNE_CFLAGS = @VTUNE_CFLAGS@ diff --git a/mono/arch/amd64/Makefile.in b/mono/arch/amd64/Makefile.in index a8c45ddcaa..38270497ed 100644 --- a/mono/arch/amd64/Makefile.in +++ b/mono/arch/amd64/Makefile.in @@ -120,6 +120,8 @@ DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AOT_BUILD_FLAGS = @AOT_BUILD_FLAGS@ +AOT_RUN_FLAGS = @AOT_RUN_FLAGS@ API_VER = @API_VER@ AR = @AR@ AS = @AS@ @@ -128,6 +130,11 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOEHM_DEFINES = @BOEHM_DEFINES@ +BTLS_ARCH = @BTLS_ARCH@ +BTLS_CFLAGS = @BTLS_CFLAGS@ +BTLS_CMAKE_ARGS = @BTLS_CMAKE_ARGS@ +BTLS_PLATFORM = @BTLS_PLATFORM@ +BTLS_ROOT = @BTLS_ROOT@ BUILD_EXEEXT = @BUILD_EXEEXT@ CC = @CC@ CCAS = @CCAS@ @@ -137,6 +144,7 @@ CCDEPMODE = @CCDEPMODE@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMAKE = @CMAKE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ @@ -157,7 +165,6 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_PERF_EVENTS = @ENABLE_PERF_EVENTS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDKX11 = @GDKX11@ @@ -172,10 +179,12 @@ HAVE_MSGFMT = @HAVE_MSGFMT@ HOST_CC = @HOST_CC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MOBILE_STATIC = @INSTALL_MOBILE_STATIC@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTL = @INTL@ +INVARIANT_AOT_OPTIONS = @INVARIANT_AOT_OPTIONS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBC = @LIBC@ @@ -222,6 +231,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ +PLATFORM_AOT_SUFFIX = @PLATFORM_AOT_SUFFIX@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -231,6 +241,7 @@ SHELL = @SHELL@ SQLITE = @SQLITE@ SQLITE3 = @SQLITE3@ STRIP = @STRIP@ +TEST_PROFILE = @TEST_PROFILE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VTUNE_CFLAGS = @VTUNE_CFLAGS@ diff --git a/mono/arch/arm/Makefile.in b/mono/arch/arm/Makefile.in index b8139f1538..9ab54681a1 100644 --- a/mono/arch/arm/Makefile.in +++ b/mono/arch/arm/Makefile.in @@ -120,6 +120,8 @@ DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AOT_BUILD_FLAGS = @AOT_BUILD_FLAGS@ +AOT_RUN_FLAGS = @AOT_RUN_FLAGS@ API_VER = @API_VER@ AR = @AR@ AS = @AS@ @@ -128,6 +130,11 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOEHM_DEFINES = @BOEHM_DEFINES@ +BTLS_ARCH = @BTLS_ARCH@ +BTLS_CFLAGS = @BTLS_CFLAGS@ +BTLS_CMAKE_ARGS = @BTLS_CMAKE_ARGS@ +BTLS_PLATFORM = @BTLS_PLATFORM@ +BTLS_ROOT = @BTLS_ROOT@ BUILD_EXEEXT = @BUILD_EXEEXT@ CC = @CC@ CCAS = @CCAS@ @@ -137,6 +144,7 @@ CCDEPMODE = @CCDEPMODE@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMAKE = @CMAKE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ @@ -157,7 +165,6 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_PERF_EVENTS = @ENABLE_PERF_EVENTS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDKX11 = @GDKX11@ @@ -172,10 +179,12 @@ HAVE_MSGFMT = @HAVE_MSGFMT@ HOST_CC = @HOST_CC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MOBILE_STATIC = @INSTALL_MOBILE_STATIC@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTL = @INTL@ +INVARIANT_AOT_OPTIONS = @INVARIANT_AOT_OPTIONS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBC = @LIBC@ @@ -222,6 +231,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ +PLATFORM_AOT_SUFFIX = @PLATFORM_AOT_SUFFIX@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -231,6 +241,7 @@ SHELL = @SHELL@ SQLITE = @SQLITE@ SQLITE3 = @SQLITE3@ STRIP = @STRIP@ +TEST_PROFILE = @TEST_PROFILE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VTUNE_CFLAGS = @VTUNE_CFLAGS@ diff --git a/mono/arch/arm/arm-codegen.h b/mono/arch/arm/arm-codegen.h index 9f89a91d5f..4cde34937b 100644 --- a/mono/arch/arm/arm-codegen.h +++ b/mono/arch/arm/arm-codegen.h @@ -500,14 +500,24 @@ typedef struct { /* Rd := (Rm * Rs)[31:0]; 32 x 32 -> 32 */ #define ARM_MUL_COND(p, rd, rm, rs, cond) \ ARM_EMIT(p, ARM_DEF_MUL_COND(ARMOP_MUL, rd, rm, rs, 0, 0, cond)) +#define ARM_UMULL_COND(p, rdhi, rdlo, rm, rs, cond) \ + ARM_EMIT(p, ARM_DEF_MUL_COND(ARMOP_UMULL, rdhi, rm, rs, rdlo, 0, cond)) +#define ARM_SMULL_COND(p, rdhi, rdlo, rm, rs, cond) \ + ARM_EMIT(p, ARM_DEF_MUL_COND(ARMOP_SMULL, rdhi, rm, rs, rdlo, 0, cond)) #define ARM_MUL(p, rd, rm, rs) \ ARM_MUL_COND(p, rd, rm, rs, ARMCOND_AL) +#define ARM_UMULL(p, rdhi, rdlo, rm, rs) \ + ARM_UMULL_COND(p, rdhi, rdlo, rm, rs, ARMCOND_AL) +#define ARM_SMULL(p, rdhi, rdlo, rm, rs) \ + ARM_SMULL_COND(p, rdhi, rdlo, rm, rs, ARMCOND_AL) #define ARM_MULS_COND(p, rd, rm, rs, cond) \ ARM_EMIT(p, ARM_DEF_MUL_COND(ARMOP_MUL, rd, rm, rs, 0, 1, cond)) #define ARM_MULS(p, rd, rm, rs) \ ARM_MULS_COND(p, rd, rm, rs, ARMCOND_AL) #define ARM_MUL_REG_REG(p, rd, rm, rs) ARM_MUL(p, rd, rm, rs) #define ARM_MULS_REG_REG(p, rd, rm, rs) ARM_MULS(p, rd, rm, rs) +#define ARM_UMULL_REG_REG(p, rdhi, rdlo, rm, rs) ARM_UMULL(p, rdhi, rdlo, rm, rs) +#define ARM_SMULL_REG_REG(p, rdhi, rdlo, rm, rs) ARM_SMULL(p, rdhi, rdlo, rm, rs) /* inline */ #define ARM_IASM_MUL_COND(rd, rm, rs, cond) \ diff --git a/mono/arch/arm64/Makefile.in b/mono/arch/arm64/Makefile.in index fee418e191..e1841c1027 100644 --- a/mono/arch/arm64/Makefile.in +++ b/mono/arch/arm64/Makefile.in @@ -120,6 +120,8 @@ DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AOT_BUILD_FLAGS = @AOT_BUILD_FLAGS@ +AOT_RUN_FLAGS = @AOT_RUN_FLAGS@ API_VER = @API_VER@ AR = @AR@ AS = @AS@ @@ -128,6 +130,11 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOEHM_DEFINES = @BOEHM_DEFINES@ +BTLS_ARCH = @BTLS_ARCH@ +BTLS_CFLAGS = @BTLS_CFLAGS@ +BTLS_CMAKE_ARGS = @BTLS_CMAKE_ARGS@ +BTLS_PLATFORM = @BTLS_PLATFORM@ +BTLS_ROOT = @BTLS_ROOT@ BUILD_EXEEXT = @BUILD_EXEEXT@ CC = @CC@ CCAS = @CCAS@ @@ -137,6 +144,7 @@ CCDEPMODE = @CCDEPMODE@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMAKE = @CMAKE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ @@ -157,7 +165,6 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_PERF_EVENTS = @ENABLE_PERF_EVENTS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDKX11 = @GDKX11@ @@ -172,10 +179,12 @@ HAVE_MSGFMT = @HAVE_MSGFMT@ HOST_CC = @HOST_CC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MOBILE_STATIC = @INSTALL_MOBILE_STATIC@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTL = @INTL@ +INVARIANT_AOT_OPTIONS = @INVARIANT_AOT_OPTIONS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBC = @LIBC@ @@ -222,6 +231,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ +PLATFORM_AOT_SUFFIX = @PLATFORM_AOT_SUFFIX@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -231,6 +241,7 @@ SHELL = @SHELL@ SQLITE = @SQLITE@ SQLITE3 = @SQLITE3@ STRIP = @STRIP@ +TEST_PROFILE = @TEST_PROFILE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VTUNE_CFLAGS = @VTUNE_CFLAGS@ diff --git a/mono/arch/ia64/Makefile.in b/mono/arch/ia64/Makefile.in index be0851e386..5d7fd2f759 100644 --- a/mono/arch/ia64/Makefile.in +++ b/mono/arch/ia64/Makefile.in @@ -120,6 +120,8 @@ DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AOT_BUILD_FLAGS = @AOT_BUILD_FLAGS@ +AOT_RUN_FLAGS = @AOT_RUN_FLAGS@ API_VER = @API_VER@ AR = @AR@ AS = @AS@ @@ -128,6 +130,11 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOEHM_DEFINES = @BOEHM_DEFINES@ +BTLS_ARCH = @BTLS_ARCH@ +BTLS_CFLAGS = @BTLS_CFLAGS@ +BTLS_CMAKE_ARGS = @BTLS_CMAKE_ARGS@ +BTLS_PLATFORM = @BTLS_PLATFORM@ +BTLS_ROOT = @BTLS_ROOT@ BUILD_EXEEXT = @BUILD_EXEEXT@ CC = @CC@ CCAS = @CCAS@ @@ -137,6 +144,7 @@ CCDEPMODE = @CCDEPMODE@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMAKE = @CMAKE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ @@ -157,7 +165,6 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_PERF_EVENTS = @ENABLE_PERF_EVENTS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDKX11 = @GDKX11@ @@ -172,10 +179,12 @@ HAVE_MSGFMT = @HAVE_MSGFMT@ HOST_CC = @HOST_CC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MOBILE_STATIC = @INSTALL_MOBILE_STATIC@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTL = @INTL@ +INVARIANT_AOT_OPTIONS = @INVARIANT_AOT_OPTIONS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBC = @LIBC@ @@ -222,6 +231,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ +PLATFORM_AOT_SUFFIX = @PLATFORM_AOT_SUFFIX@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -231,6 +241,7 @@ SHELL = @SHELL@ SQLITE = @SQLITE@ SQLITE3 = @SQLITE3@ STRIP = @STRIP@ +TEST_PROFILE = @TEST_PROFILE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VTUNE_CFLAGS = @VTUNE_CFLAGS@ diff --git a/mono/arch/mips/Makefile.in b/mono/arch/mips/Makefile.in index ddec8ea722..c76b10cc9a 100644 --- a/mono/arch/mips/Makefile.in +++ b/mono/arch/mips/Makefile.in @@ -171,6 +171,8 @@ DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AOT_BUILD_FLAGS = @AOT_BUILD_FLAGS@ +AOT_RUN_FLAGS = @AOT_RUN_FLAGS@ API_VER = @API_VER@ AR = @AR@ AS = @AS@ @@ -179,6 +181,11 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOEHM_DEFINES = @BOEHM_DEFINES@ +BTLS_ARCH = @BTLS_ARCH@ +BTLS_CFLAGS = @BTLS_CFLAGS@ +BTLS_CMAKE_ARGS = @BTLS_CMAKE_ARGS@ +BTLS_PLATFORM = @BTLS_PLATFORM@ +BTLS_ROOT = @BTLS_ROOT@ BUILD_EXEEXT = @BUILD_EXEEXT@ CC = @CC@ CCAS = @CCAS@ @@ -188,6 +195,7 @@ CCDEPMODE = @CCDEPMODE@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMAKE = @CMAKE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ @@ -208,7 +216,6 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_PERF_EVENTS = @ENABLE_PERF_EVENTS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDKX11 = @GDKX11@ @@ -223,10 +230,12 @@ HAVE_MSGFMT = @HAVE_MSGFMT@ HOST_CC = @HOST_CC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MOBILE_STATIC = @INSTALL_MOBILE_STATIC@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTL = @INTL@ +INVARIANT_AOT_OPTIONS = @INVARIANT_AOT_OPTIONS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBC = @LIBC@ @@ -273,6 +282,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ +PLATFORM_AOT_SUFFIX = @PLATFORM_AOT_SUFFIX@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -282,6 +292,7 @@ SHELL = @SHELL@ SQLITE = @SQLITE@ SQLITE3 = @SQLITE3@ STRIP = @STRIP@ +TEST_PROFILE = @TEST_PROFILE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VTUNE_CFLAGS = @VTUNE_CFLAGS@ diff --git a/mono/arch/ppc/Makefile.in b/mono/arch/ppc/Makefile.in index a4babb91e3..410440b829 100644 --- a/mono/arch/ppc/Makefile.in +++ b/mono/arch/ppc/Makefile.in @@ -120,6 +120,8 @@ DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AOT_BUILD_FLAGS = @AOT_BUILD_FLAGS@ +AOT_RUN_FLAGS = @AOT_RUN_FLAGS@ API_VER = @API_VER@ AR = @AR@ AS = @AS@ @@ -128,6 +130,11 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOEHM_DEFINES = @BOEHM_DEFINES@ +BTLS_ARCH = @BTLS_ARCH@ +BTLS_CFLAGS = @BTLS_CFLAGS@ +BTLS_CMAKE_ARGS = @BTLS_CMAKE_ARGS@ +BTLS_PLATFORM = @BTLS_PLATFORM@ +BTLS_ROOT = @BTLS_ROOT@ BUILD_EXEEXT = @BUILD_EXEEXT@ CC = @CC@ CCAS = @CCAS@ @@ -137,6 +144,7 @@ CCDEPMODE = @CCDEPMODE@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMAKE = @CMAKE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ @@ -157,7 +165,6 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_PERF_EVENTS = @ENABLE_PERF_EVENTS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDKX11 = @GDKX11@ @@ -172,10 +179,12 @@ HAVE_MSGFMT = @HAVE_MSGFMT@ HOST_CC = @HOST_CC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MOBILE_STATIC = @INSTALL_MOBILE_STATIC@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTL = @INTL@ +INVARIANT_AOT_OPTIONS = @INVARIANT_AOT_OPTIONS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBC = @LIBC@ @@ -222,6 +231,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ +PLATFORM_AOT_SUFFIX = @PLATFORM_AOT_SUFFIX@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -231,6 +241,7 @@ SHELL = @SHELL@ SQLITE = @SQLITE@ SQLITE3 = @SQLITE3@ STRIP = @STRIP@ +TEST_PROFILE = @TEST_PROFILE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VTUNE_CFLAGS = @VTUNE_CFLAGS@ diff --git a/mono/arch/s390x/Makefile.in b/mono/arch/s390x/Makefile.in index 0c20d30fd4..967faa313b 100644 --- a/mono/arch/s390x/Makefile.in +++ b/mono/arch/s390x/Makefile.in @@ -165,6 +165,8 @@ DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AOT_BUILD_FLAGS = @AOT_BUILD_FLAGS@ +AOT_RUN_FLAGS = @AOT_RUN_FLAGS@ API_VER = @API_VER@ AR = @AR@ AS = @AS@ @@ -173,6 +175,11 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOEHM_DEFINES = @BOEHM_DEFINES@ +BTLS_ARCH = @BTLS_ARCH@ +BTLS_CFLAGS = @BTLS_CFLAGS@ +BTLS_CMAKE_ARGS = @BTLS_CMAKE_ARGS@ +BTLS_PLATFORM = @BTLS_PLATFORM@ +BTLS_ROOT = @BTLS_ROOT@ BUILD_EXEEXT = @BUILD_EXEEXT@ CC = @CC@ CCAS = @CCAS@ @@ -182,6 +189,7 @@ CCDEPMODE = @CCDEPMODE@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMAKE = @CMAKE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ @@ -202,7 +210,6 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_PERF_EVENTS = @ENABLE_PERF_EVENTS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDKX11 = @GDKX11@ @@ -217,10 +224,12 @@ HAVE_MSGFMT = @HAVE_MSGFMT@ HOST_CC = @HOST_CC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MOBILE_STATIC = @INSTALL_MOBILE_STATIC@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTL = @INTL@ +INVARIANT_AOT_OPTIONS = @INVARIANT_AOT_OPTIONS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBC = @LIBC@ @@ -267,6 +276,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ +PLATFORM_AOT_SUFFIX = @PLATFORM_AOT_SUFFIX@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -276,6 +286,7 @@ SHELL = @SHELL@ SQLITE = @SQLITE@ SQLITE3 = @SQLITE3@ STRIP = @STRIP@ +TEST_PROFILE = @TEST_PROFILE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VTUNE_CFLAGS = @VTUNE_CFLAGS@ diff --git a/mono/arch/sparc/Makefile.in b/mono/arch/sparc/Makefile.in index 908408cfa5..83d8d479af 100644 --- a/mono/arch/sparc/Makefile.in +++ b/mono/arch/sparc/Makefile.in @@ -120,6 +120,8 @@ DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AOT_BUILD_FLAGS = @AOT_BUILD_FLAGS@ +AOT_RUN_FLAGS = @AOT_RUN_FLAGS@ API_VER = @API_VER@ AR = @AR@ AS = @AS@ @@ -128,6 +130,11 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOEHM_DEFINES = @BOEHM_DEFINES@ +BTLS_ARCH = @BTLS_ARCH@ +BTLS_CFLAGS = @BTLS_CFLAGS@ +BTLS_CMAKE_ARGS = @BTLS_CMAKE_ARGS@ +BTLS_PLATFORM = @BTLS_PLATFORM@ +BTLS_ROOT = @BTLS_ROOT@ BUILD_EXEEXT = @BUILD_EXEEXT@ CC = @CC@ CCAS = @CCAS@ @@ -137,6 +144,7 @@ CCDEPMODE = @CCDEPMODE@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMAKE = @CMAKE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ @@ -157,7 +165,6 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_PERF_EVENTS = @ENABLE_PERF_EVENTS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDKX11 = @GDKX11@ @@ -172,10 +179,12 @@ HAVE_MSGFMT = @HAVE_MSGFMT@ HOST_CC = @HOST_CC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MOBILE_STATIC = @INSTALL_MOBILE_STATIC@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTL = @INTL@ +INVARIANT_AOT_OPTIONS = @INVARIANT_AOT_OPTIONS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBC = @LIBC@ @@ -222,6 +231,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ +PLATFORM_AOT_SUFFIX = @PLATFORM_AOT_SUFFIX@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -231,6 +241,7 @@ SHELL = @SHELL@ SQLITE = @SQLITE@ SQLITE3 = @SQLITE3@ STRIP = @STRIP@ +TEST_PROFILE = @TEST_PROFILE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VTUNE_CFLAGS = @VTUNE_CFLAGS@ diff --git a/mono/arch/x86/Makefile.in b/mono/arch/x86/Makefile.in index 633bde5ce1..1e13da829d 100644 --- a/mono/arch/x86/Makefile.in +++ b/mono/arch/x86/Makefile.in @@ -120,6 +120,8 @@ DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AOT_BUILD_FLAGS = @AOT_BUILD_FLAGS@ +AOT_RUN_FLAGS = @AOT_RUN_FLAGS@ API_VER = @API_VER@ AR = @AR@ AS = @AS@ @@ -128,6 +130,11 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOEHM_DEFINES = @BOEHM_DEFINES@ +BTLS_ARCH = @BTLS_ARCH@ +BTLS_CFLAGS = @BTLS_CFLAGS@ +BTLS_CMAKE_ARGS = @BTLS_CMAKE_ARGS@ +BTLS_PLATFORM = @BTLS_PLATFORM@ +BTLS_ROOT = @BTLS_ROOT@ BUILD_EXEEXT = @BUILD_EXEEXT@ CC = @CC@ CCAS = @CCAS@ @@ -137,6 +144,7 @@ CCDEPMODE = @CCDEPMODE@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMAKE = @CMAKE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ @@ -157,7 +165,6 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_PERF_EVENTS = @ENABLE_PERF_EVENTS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDKX11 = @GDKX11@ @@ -172,10 +179,12 @@ HAVE_MSGFMT = @HAVE_MSGFMT@ HOST_CC = @HOST_CC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MOBILE_STATIC = @INSTALL_MOBILE_STATIC@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTL = @INTL@ +INVARIANT_AOT_OPTIONS = @INVARIANT_AOT_OPTIONS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBC = @LIBC@ @@ -222,6 +231,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ +PLATFORM_AOT_SUFFIX = @PLATFORM_AOT_SUFFIX@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -231,6 +241,7 @@ SHELL = @SHELL@ SQLITE = @SQLITE@ SQLITE3 = @SQLITE3@ STRIP = @STRIP@ +TEST_PROFILE = @TEST_PROFILE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VTUNE_CFLAGS = @VTUNE_CFLAGS@ diff --git a/mono/benchmark/Makefile.in b/mono/benchmark/Makefile.in index dab85a0156..38f4440628 100644 --- a/mono/benchmark/Makefile.in +++ b/mono/benchmark/Makefile.in @@ -120,6 +120,8 @@ DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AOT_BUILD_FLAGS = @AOT_BUILD_FLAGS@ +AOT_RUN_FLAGS = @AOT_RUN_FLAGS@ API_VER = @API_VER@ AR = @AR@ AS = @AS@ @@ -128,6 +130,11 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOEHM_DEFINES = @BOEHM_DEFINES@ +BTLS_ARCH = @BTLS_ARCH@ +BTLS_CFLAGS = @BTLS_CFLAGS@ +BTLS_CMAKE_ARGS = @BTLS_CMAKE_ARGS@ +BTLS_PLATFORM = @BTLS_PLATFORM@ +BTLS_ROOT = @BTLS_ROOT@ BUILD_EXEEXT = @BUILD_EXEEXT@ CC = @CC@ CCAS = @CCAS@ @@ -137,6 +144,7 @@ CCDEPMODE = @CCDEPMODE@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMAKE = @CMAKE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ @@ -157,7 +165,6 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_PERF_EVENTS = @ENABLE_PERF_EVENTS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDKX11 = @GDKX11@ @@ -172,10 +179,12 @@ HAVE_MSGFMT = @HAVE_MSGFMT@ HOST_CC = @HOST_CC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MOBILE_STATIC = @INSTALL_MOBILE_STATIC@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTL = @INTL@ +INVARIANT_AOT_OPTIONS = @INVARIANT_AOT_OPTIONS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBC = @LIBC@ @@ -222,6 +231,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ +PLATFORM_AOT_SUFFIX = @PLATFORM_AOT_SUFFIX@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -231,6 +241,7 @@ SHELL = @SHELL@ SQLITE = @SQLITE@ SQLITE3 = @SQLITE3@ STRIP = @STRIP@ +TEST_PROFILE = @TEST_PROFILE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VTUNE_CFLAGS = @VTUNE_CFLAGS@ diff --git a/mono/btls/Makefile.am b/mono/btls/Makefile.am new file mode 100644 index 0000000000..fa4a949b5f --- /dev/null +++ b/mono/btls/Makefile.am @@ -0,0 +1,41 @@ +BTLS_STATIC_LIST = build-static/mono-btls-static-lo.txt +BTLS_SHARED_LIST = build-shared/mono-btls-shared-lo.txt + +BTLS_DEPS = $(BTLS_LIBS) build-shared/Makefile build-static/Makefile + +CMAKE_VERBOSE=$(if $(V),VERBOSE=1,) + +CMAKE_ARGS = -D CMAKE_INSTALL_PREFIX:PATH=$(prefix) -D BTLS_ROOT:PATH=$(BTLS_ROOT) \ + -D SRC_DIR:PATH=$(abs_top_srcdir)/mono/btls -D BTLS_CFLAGS:STRING="$(BTLS_CFLAGS)" + +all-local: $(BTLS_STATIC_LIST) $(BTLS_SHARED_LIST) + +if DYNAMIC_BTLS +build-shared/Makefile: + -mkdir -p build-shared + (cd build-shared && $(CMAKE) $(CMAKE_ARGS) $(BTLS_CMAKE_ARGS) -DBUILD_DYNAMIC_BTLS=1 $(abs_top_srcdir)/mono/btls) +else +build-shared/Makefile: + -mkdir -p build-shared + (cd build-shared && $(CMAKE) $(CMAKE_ARGS) $(BTLS_CMAKE_ARGS) -DBUILD_SHARED_LIBS=1 $(abs_top_srcdir)/mono/btls) +endif + +build-static/Makefile: + -mkdir -p build-static + (cd build-static && $(CMAKE) $(CMAKE_ARGS) $(BTLS_CMAKE_ARGS) $(abs_top_srcdir)/mono/btls) + +$(BTLS_STATIC_LIST): build-static/Makefile + $(MAKE) -C build-static $(CMAKE_VERBOSE) + +$(BTLS_SHARED_LIST): build-shared/Makefile + $(MAKE) -C build-shared $(CMAKE_VERBOSE) + +clean-local: + -rm -rf build-static + -rm -rf build-shared + +if DYNAMIC_BTLS +install-exec-local: + $(mkinstalldirs) "$(DESTDIR)$(libdir)" + $(install_sh) build-shared/libmono-btls-shared.* "$(DESTDIR)$(libdir)" +endif diff --git a/mono/btls/Makefile.in b/mono/btls/Makefile.in new file mode 100644 index 0000000000..72ffa1eaea --- /dev/null +++ b/mono/btls/Makefile.in @@ -0,0 +1,562 @@ +# Makefile.in generated by automake 1.14.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = mono/btls +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(top_srcdir)/mkinstalldirs +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/iconv.m4 \ + $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ + $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AOT_BUILD_FLAGS = @AOT_BUILD_FLAGS@ +AOT_RUN_FLAGS = @AOT_RUN_FLAGS@ +API_VER = @API_VER@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BOEHM_DEFINES = @BOEHM_DEFINES@ +BTLS_ARCH = @BTLS_ARCH@ +BTLS_CFLAGS = @BTLS_CFLAGS@ +BTLS_CMAKE_ARGS = @BTLS_CMAKE_ARGS@ +BTLS_PLATFORM = @BTLS_PLATFORM@ +BTLS_ROOT = @BTLS_ROOT@ +BUILD_EXEEXT = @BUILD_EXEEXT@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CC_FOR_BUILD = @CC_FOR_BUILD@ +CFLAGS = @CFLAGS@ +CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMAKE = @CMAKE@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFAULT_PROFILE = @DEFAULT_PROFILE@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOLT_BASH = @DOLT_BASH@ +DSYMUTIL = @DSYMUTIL@ +DTRACE = @DTRACE@ +DTRACEFLAGS = @DTRACEFLAGS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GDKX11 = @GDKX11@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_LIBS = @GLIB_LIBS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +GTKX11 = @GTKX11@ +HAVE_MSGFMT = @HAVE_MSGFMT@ +HOST_CC = @HOST_CC@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MOBILE_STATIC = @INSTALL_MOBILE_STATIC@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTL = @INTL@ +INVARIANT_AOT_OPTIONS = @INVARIANT_AOT_OPTIONS@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBC = @LIBC@ +LIBGC_CPPFLAGS = @LIBGC_CPPFLAGS@ +LIBGC_LIBS = @LIBGC_LIBS@ +LIBGC_STATIC_LIBS = @LIBGC_STATIC_LIBS@ +LIBICONV = @LIBICONV@ +LIBMONO_LA = @LIBMONO_LA@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LLVM_CFLAGS = @LLVM_CFLAGS@ +LLVM_CONFIG = @LLVM_CONFIG@ +LLVM_CXXFLAGS = @LLVM_CXXFLAGS@ +LLVM_LDFLAGS = @LLVM_LDFLAGS@ +LLVM_LIBS = @LLVM_LIBS@ +LN_S = @LN_S@ +LTCOMPILE = @LTCOMPILE@ +LTCXXCOMPILE = @LTCXXCOMPILE@ +LTLIBICONV = @LTLIBICONV@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MONO_DL_NEED_USCORE = @MONO_DL_NEED_USCORE@ +MONO_NACL_ALIGN_MASK_OFF = @MONO_NACL_ALIGN_MASK_OFF@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PLATFORM_AOT_SUFFIX = @PLATFORM_AOT_SUFFIX@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SGEN_DEFINES = @SGEN_DEFINES@ +SHARED_CFLAGS = @SHARED_CFLAGS@ +SHELL = @SHELL@ +SQLITE = @SQLITE@ +SQLITE3 = @SQLITE3@ +STRIP = @STRIP@ +TEST_PROFILE = @TEST_PROFILE@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +VTUNE_CFLAGS = @VTUNE_CFLAGS@ +VTUNE_LIBS = @VTUNE_LIBS@ +WERROR_CFLAGS = @WERROR_CFLAGS@ +X11 = @X11@ +XATTR_LIB = @XATTR_LIB@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +XINERAMA = @XINERAMA@ +XMKMF = @XMKMF@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +arch_target = @arch_target@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +docs_dir = @docs_dir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +export_ldflags = @export_ldflags@ +extra_runtime_ldflags = @extra_runtime_ldflags@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +ikvm_native_dir = @ikvm_native_dir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +libgc_dir = @libgc_dir@ +libgdiplus_install_loc = @libgdiplus_install_loc@ +libgdiplus_loc = @libgdiplus_loc@ +libmono_cflags = @libmono_cflags@ +libmono_ldflags = @libmono_ldflags@ +libsuffix = @libsuffix@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mcs_topdir = @mcs_topdir@ +mcs_topdir_from_srcdir = @mcs_topdir_from_srcdir@ +mkdir_p = @mkdir_p@ +mono_build_root = @mono_build_root@ +mono_cfg_dir = @mono_cfg_dir@ +mono_runtime = @mono_runtime@ +nacl_self_host = @nacl_self_host@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +reloc_libdir = @reloc_libdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +BTLS_STATIC_LIST = build-static/mono-btls-static-lo.txt +BTLS_SHARED_LIST = build-shared/mono-btls-shared-lo.txt +BTLS_DEPS = $(BTLS_LIBS) build-shared/Makefile build-static/Makefile +CMAKE_VERBOSE = $(if $(V),VERBOSE=1,) +CMAKE_ARGS = -D CMAKE_INSTALL_PREFIX:PATH=$(prefix) -D BTLS_ROOT:PATH=$(BTLS_ROOT) \ + -D SRC_DIR:PATH=$(abs_top_srcdir)/mono/btls -D BTLS_CFLAGS:STRING="$(BTLS_CFLAGS)" + +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign mono/btls/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign mono/btls/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: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile all-local +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +@DYNAMIC_BTLS_FALSE@install-exec-local: +clean: clean-am + +clean-am: clean-generic clean-libtool clean-local mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-exec-local + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: all all-am all-local check check-am clean clean-generic \ + clean-libtool clean-local cscopelist-am ctags-am distclean \ + distclean-generic distclean-libtool 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-exec-local install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags-am uninstall uninstall-am + + +all-local: $(BTLS_STATIC_LIST) $(BTLS_SHARED_LIST) + +@DYNAMIC_BTLS_TRUE@build-shared/Makefile: +@DYNAMIC_BTLS_TRUE@ -mkdir -p build-shared +@DYNAMIC_BTLS_TRUE@ (cd build-shared && $(CMAKE) $(CMAKE_ARGS) $(BTLS_CMAKE_ARGS) -DBUILD_DYNAMIC_BTLS=1 $(abs_top_srcdir)/mono/btls) +@DYNAMIC_BTLS_FALSE@build-shared/Makefile: +@DYNAMIC_BTLS_FALSE@ -mkdir -p build-shared +@DYNAMIC_BTLS_FALSE@ (cd build-shared && $(CMAKE) $(CMAKE_ARGS) $(BTLS_CMAKE_ARGS) -DBUILD_SHARED_LIBS=1 $(abs_top_srcdir)/mono/btls) + +build-static/Makefile: + -mkdir -p build-static + (cd build-static && $(CMAKE) $(CMAKE_ARGS) $(BTLS_CMAKE_ARGS) $(abs_top_srcdir)/mono/btls) + +$(BTLS_STATIC_LIST): build-static/Makefile + $(MAKE) -C build-static $(CMAKE_VERBOSE) + +$(BTLS_SHARED_LIST): build-shared/Makefile + $(MAKE) -C build-shared $(CMAKE_VERBOSE) + +clean-local: + -rm -rf build-static + -rm -rf build-shared + +@DYNAMIC_BTLS_TRUE@install-exec-local: +@DYNAMIC_BTLS_TRUE@ $(mkinstalldirs) "$(DESTDIR)$(libdir)" +@DYNAMIC_BTLS_TRUE@ $(install_sh) build-shared/libmono-btls-shared.* "$(DESTDIR)$(libdir)" + +# 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/mono/cil/Makefile.in b/mono/cil/Makefile.in index 29d6144849..709a6e154b 100644 --- a/mono/cil/Makefile.in +++ b/mono/cil/Makefile.in @@ -150,6 +150,8 @@ DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AOT_BUILD_FLAGS = @AOT_BUILD_FLAGS@ +AOT_RUN_FLAGS = @AOT_RUN_FLAGS@ API_VER = @API_VER@ AR = @AR@ AS = @AS@ @@ -158,6 +160,11 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOEHM_DEFINES = @BOEHM_DEFINES@ +BTLS_ARCH = @BTLS_ARCH@ +BTLS_CFLAGS = @BTLS_CFLAGS@ +BTLS_CMAKE_ARGS = @BTLS_CMAKE_ARGS@ +BTLS_PLATFORM = @BTLS_PLATFORM@ +BTLS_ROOT = @BTLS_ROOT@ BUILD_EXEEXT = @BUILD_EXEEXT@ CC = @CC@ CCAS = @CCAS@ @@ -167,6 +174,7 @@ CCDEPMODE = @CCDEPMODE@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMAKE = @CMAKE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ @@ -187,7 +195,6 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_PERF_EVENTS = @ENABLE_PERF_EVENTS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDKX11 = @GDKX11@ @@ -202,10 +209,12 @@ HAVE_MSGFMT = @HAVE_MSGFMT@ HOST_CC = @HOST_CC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MOBILE_STATIC = @INSTALL_MOBILE_STATIC@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTL = @INTL@ +INVARIANT_AOT_OPTIONS = @INVARIANT_AOT_OPTIONS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBC = @LIBC@ @@ -252,6 +261,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ +PLATFORM_AOT_SUFFIX = @PLATFORM_AOT_SUFFIX@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -261,6 +271,7 @@ SHELL = @SHELL@ SQLITE = @SQLITE@ SQLITE3 = @SQLITE3@ STRIP = @STRIP@ +TEST_PROFILE = @TEST_PROFILE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VTUNE_CFLAGS = @VTUNE_CFLAGS@ diff --git a/mono/cil/cil-opcodes.xml b/mono/cil/cil-opcodes.xml index 087e3f3008..c8ef14eaee 100644 --- a/mono/cil/cil-opcodes.xml +++ b/mono/cil/cil-opcodes.xml @@ -319,4 +319,5 @@ + diff --git a/mono/cil/opcode.def b/mono/cil/opcode.def index ee69b699ba..fca2448151 100644 --- a/mono/cil/opcode.def +++ b/mono/cil/opcode.def @@ -319,6 +319,7 @@ OPDEF(CEE_MONO_LDPTR_NURSERY_BITS, "mono_ldptr_nursery_bits", Pop0, PushI, Inlin OPDEF(CEE_MONO_CALLI_EXTRA_ARG, "mono_calli_extra_arg", VarPop, VarPush, InlineSig, X, 2, 0xF0, 0x18, CALL) OPDEF(CEE_MONO_LDDOMAIN, "mono_lddomain", Pop0, PushI, InlineNone, X, 2, 0xF0, 0x19, NEXT) OPDEF(CEE_MONO_ATOMIC_STORE_I4, "mono_atomic_store_i4", PopI+PopI, Push0, InlineI, X, 2, 0xF0, 0x1A, NEXT) +OPDEF(CEE_MONO_GET_LAST_ERROR, "mono_get_last_error", Pop0, PushI, InlineNone, X, 2, 0xF0, 0x1B, NEXT) #ifndef OPALIAS #define _MONO_CIL_OPALIAS_DEFINED_ #define OPALIAS(a,s,r) diff --git a/mono/dis/Makefile.in b/mono/dis/Makefile.in index c7eb0481b3..11c63b8f25 100644 --- a/mono/dis/Makefile.in +++ b/mono/dis/Makefile.in @@ -221,6 +221,8 @@ DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AOT_BUILD_FLAGS = @AOT_BUILD_FLAGS@ +AOT_RUN_FLAGS = @AOT_RUN_FLAGS@ API_VER = @API_VER@ AR = @AR@ AS = @AS@ @@ -229,6 +231,11 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOEHM_DEFINES = @BOEHM_DEFINES@ +BTLS_ARCH = @BTLS_ARCH@ +BTLS_CFLAGS = @BTLS_CFLAGS@ +BTLS_CMAKE_ARGS = @BTLS_CMAKE_ARGS@ +BTLS_PLATFORM = @BTLS_PLATFORM@ +BTLS_ROOT = @BTLS_ROOT@ BUILD_EXEEXT = @BUILD_EXEEXT@ CC = @CC@ CCAS = @CCAS@ @@ -238,6 +245,7 @@ CCDEPMODE = @CCDEPMODE@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMAKE = @CMAKE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ @@ -258,7 +266,6 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_PERF_EVENTS = @ENABLE_PERF_EVENTS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDKX11 = @GDKX11@ @@ -273,10 +280,12 @@ HAVE_MSGFMT = @HAVE_MSGFMT@ HOST_CC = @HOST_CC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MOBILE_STATIC = @INSTALL_MOBILE_STATIC@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTL = @INTL@ +INVARIANT_AOT_OPTIONS = @INVARIANT_AOT_OPTIONS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBC = @LIBC@ @@ -323,6 +332,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ +PLATFORM_AOT_SUFFIX = @PLATFORM_AOT_SUFFIX@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -332,6 +342,7 @@ SHELL = @SHELL@ SQLITE = @SQLITE@ SQLITE3 = @SQLITE3@ STRIP = @STRIP@ +TEST_PROFILE = @TEST_PROFILE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VTUNE_CFLAGS = @VTUNE_CFLAGS@ diff --git a/mono/dis/main.c b/mono/dis/main.c index d1b85c5509..1af061c383 100644 --- a/mono/dis/main.c +++ b/mono/dis/main.c @@ -1617,7 +1617,7 @@ struct { * * Disassembles the @file file. */ -static void +static int disassemble_file (const char *file) { MonoImageOpenStatus status; @@ -1626,7 +1626,7 @@ disassemble_file (const char *file) img = mono_image_open (file, &status); if (!img) { fprintf (stderr, "Error while trying to process %s\n", file); - return; + return 1; } else { /* FIXME: is this call necessary? */ mono_assembly_load_from_full (img, file, &status, FALSE); @@ -1659,6 +1659,7 @@ disassemble_file (const char *file) } mono_image_close (img); + return 0; } typedef struct { @@ -2028,12 +2029,14 @@ main (int argc, char *argv []) mono_install_assembly_preload_hook (monodis_preload, GUINT_TO_POINTER (FALSE)); - disassemble_file (filename); + return disassemble_file (filename); } else { mono_init (argv [0]); + i = 0; for (l = input_files; l; l = l->next) - disassemble_file ((const char *)l->data); + if (disassemble_file ((const char *)l->data) == 1) i = 1; + return i; } return 0; diff --git a/mono/io-layer/Makefile.am b/mono/io-layer/Makefile.am index fd81942497..0eb885e055 100644 --- a/mono/io-layer/Makefile.am +++ b/mono/io-layer/Makefile.am @@ -15,7 +15,6 @@ OTHER_H = \ context.h \ error.h \ events.h \ - handles.h \ io.h \ io-trace.h \ io-layer.h \ @@ -28,7 +27,6 @@ OTHER_H = \ semaphores.h \ sockets.h \ status.h \ - threads.h \ timefuncs.h \ types.h \ uglify.h \ @@ -46,9 +44,6 @@ OTHER_SRC = \ events.c \ events.h \ event-private.h \ - handles.c \ - handles.h \ - handles-private.h \ io.c \ io.h \ io-portability.c \ @@ -78,8 +73,6 @@ OTHER_SRC = \ socket-private.h \ socket-wrappers.h \ status.h \ - threads.h \ - thread-private.h \ timefuncs.c \ timefuncs.h \ timefuncs-private.h \ @@ -93,7 +86,7 @@ OTHER_SRC = \ wapi_glob.c \ wapi.h \ wapi-private.h \ - wthreads.c + wapi.c WINDOWS_H = \ diff --git a/mono/io-layer/Makefile.in b/mono/io-layer/Makefile.in index da36ac7465..36d33d9b67 100644 --- a/mono/io-layer/Makefile.in +++ b/mono/io-layer/Makefile.in @@ -100,22 +100,21 @@ CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libwapi_la_DEPENDENCIES = am__libwapi_la_SOURCES_DIST = access.h context.c context.h error.c \ - error.h events.c events.h event-private.h handles.c handles.h \ - handles-private.h io.c io.h io-portability.c io-portability.h \ - io-private.h io-layer.h locking.c macros.h messages.c \ - messages.h mutexes.c mutexes.h mutex-private.h posix.c \ - processes.c processes.h process-private.h security.c \ - security.h semaphores.c semaphores.h semaphore-private.h \ - shared.c shared.h sockets.c sockets.h socket-private.h \ - socket-wrappers.h status.h threads.h thread-private.h \ + error.h events.c events.h event-private.h io.c io.h \ + io-portability.c io-portability.h io-private.h io-layer.h \ + locking.c macros.h messages.c messages.h mutexes.c mutexes.h \ + mutex-private.h posix.c processes.c processes.h \ + process-private.h security.c security.h semaphores.c \ + semaphores.h semaphore-private.h shared.c shared.h sockets.c \ + sockets.h socket-private.h socket-wrappers.h status.h \ timefuncs.c timefuncs.h timefuncs-private.h types.h uglify.h \ versioninfo.c versioninfo.h wait.c wait.h wapi_glob.h \ - wapi_glob.c wapi.h wapi-private.h wthreads.c io-trace.h \ + wapi_glob.c wapi.h wapi-private.h wapi.c io-trace.h \ wapi-remap.h io-layer-dummy.c -am__objects_1 = context.lo error.lo events.lo handles.lo io.lo \ - io-portability.lo locking.lo messages.lo mutexes.lo posix.lo \ - processes.lo security.lo semaphores.lo shared.lo sockets.lo \ - timefuncs.lo versioninfo.lo wait.lo wapi_glob.lo wthreads.lo +am__objects_1 = context.lo error.lo events.lo io.lo io-portability.lo \ + locking.lo messages.lo mutexes.lo posix.lo processes.lo \ + security.lo semaphores.lo shared.lo sockets.lo timefuncs.lo \ + versioninfo.lo wait.lo wapi_glob.lo wapi.lo am__objects_2 = am__objects_3 = io-layer-dummy.lo @HOST_WIN32_FALSE@am_libwapi_la_OBJECTS = $(am__objects_1) \ @@ -187,6 +186,8 @@ DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AOT_BUILD_FLAGS = @AOT_BUILD_FLAGS@ +AOT_RUN_FLAGS = @AOT_RUN_FLAGS@ API_VER = @API_VER@ AR = @AR@ AS = @AS@ @@ -195,6 +196,11 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOEHM_DEFINES = @BOEHM_DEFINES@ +BTLS_ARCH = @BTLS_ARCH@ +BTLS_CFLAGS = @BTLS_CFLAGS@ +BTLS_CMAKE_ARGS = @BTLS_CMAKE_ARGS@ +BTLS_PLATFORM = @BTLS_PLATFORM@ +BTLS_ROOT = @BTLS_ROOT@ BUILD_EXEEXT = @BUILD_EXEEXT@ CC = @CC@ CCAS = @CCAS@ @@ -204,6 +210,7 @@ CCDEPMODE = @CCDEPMODE@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMAKE = @CMAKE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ @@ -224,7 +231,6 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_PERF_EVENTS = @ENABLE_PERF_EVENTS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDKX11 = @GDKX11@ @@ -239,10 +245,12 @@ HAVE_MSGFMT = @HAVE_MSGFMT@ HOST_CC = @HOST_CC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MOBILE_STATIC = @INSTALL_MOBILE_STATIC@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTL = @INTL@ +INVARIANT_AOT_OPTIONS = @INVARIANT_AOT_OPTIONS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBC = @LIBC@ @@ -289,6 +297,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ +PLATFORM_AOT_SUFFIX = @PLATFORM_AOT_SUFFIX@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -298,6 +307,7 @@ SHELL = @SHELL@ SQLITE = @SQLITE@ SQLITE3 = @SQLITE3@ STRIP = @STRIP@ +TEST_PROFILE = @TEST_PROFILE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VTUNE_CFLAGS = @VTUNE_CFLAGS@ @@ -400,7 +410,6 @@ OTHER_H = \ context.h \ error.h \ events.h \ - handles.h \ io.h \ io-trace.h \ io-layer.h \ @@ -413,7 +422,6 @@ OTHER_H = \ semaphores.h \ sockets.h \ status.h \ - threads.h \ timefuncs.h \ types.h \ uglify.h \ @@ -431,9 +439,6 @@ OTHER_SRC = \ events.c \ events.h \ event-private.h \ - handles.c \ - handles.h \ - handles-private.h \ io.c \ io.h \ io-portability.c \ @@ -463,8 +468,6 @@ OTHER_SRC = \ socket-private.h \ socket-wrappers.h \ status.h \ - threads.h \ - thread-private.h \ timefuncs.c \ timefuncs.h \ timefuncs-private.h \ @@ -478,7 +481,7 @@ OTHER_SRC = \ wapi_glob.c \ wapi.h \ wapi-private.h \ - wthreads.c + wapi.c WINDOWS_H = \ io-layer.h @@ -551,7 +554,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/context.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/error.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/events.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/handles.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/io-layer-dummy.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/io-portability.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/io.Plo@am__quote@ @@ -567,8 +569,8 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/timefuncs.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/versioninfo.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wait.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wapi.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wapi_glob.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wthreads.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ diff --git a/mono/io-layer/error.c b/mono/io-layer/error.c index 6d40dd3b5c..db128be5c7 100644 --- a/mono/io-layer/error.c +++ b/mono/io-layer/error.c @@ -14,11 +14,11 @@ #include #include "mono/io-layer/wapi.h" +#include "mono/io-layer/wapi-private.h" #include "mono/utils/mono-once.h" static pthread_key_t error_key; static mono_once_t error_key_once=MONO_ONCE_INIT; -extern gboolean _wapi_has_shut_down; static void error_init(void) { diff --git a/mono/io-layer/event-private.h b/mono/io-layer/event-private.h index 25df911165..07b35e0c2f 100644 --- a/mono/io-layer/event-private.h +++ b/mono/io-layer/event-private.h @@ -14,10 +14,7 @@ #include #include -extern struct _WapiHandleOps _wapi_event_ops; -extern struct _WapiHandleOps _wapi_namedevent_ops; - -extern void _wapi_event_details (gpointer handle_info); +#include "wapi-private.h" struct _WapiHandle_event { @@ -27,9 +24,11 @@ struct _WapiHandle_event struct _WapiHandle_namedevent { + struct _WapiHandle_event e; WapiSharedNamespace sharedns; - gboolean manual; - guint32 set_count; }; +void +_wapi_event_init (void); + #endif /* _WAPI_EVENT_PRIVATE_H_ */ diff --git a/mono/io-layer/events.c b/mono/io-layer/events.c index 723982cc39..8e3fa4a039 100644 --- a/mono/io-layer/events.c +++ b/mono/io-layer/events.c @@ -14,79 +14,94 @@ #include #include -#include #include #include #include #include +#include static void event_signal(gpointer handle); static gboolean event_own (gpointer handle); +static void event_details (gpointer data); +static const gchar* event_typename (void); +static gsize event_typesize (void); static void namedevent_signal (gpointer handle); static gboolean namedevent_own (gpointer handle); +static void namedevent_details (gpointer data); +static const gchar* namedevent_typename (void); +static gsize namedevent_typesize (void); -struct _WapiHandleOps _wapi_event_ops = { +static MonoW32HandleOps _wapi_event_ops = { NULL, /* close */ event_signal, /* signal */ event_own, /* own */ NULL, /* is_owned */ NULL, /* special_wait */ - NULL /* prewait */ + NULL, /* prewait */ + event_details, /* details */ + event_typename, /* typename */ + event_typesize, /* typesize */ }; -struct _WapiHandleOps _wapi_namedevent_ops = { +static MonoW32HandleOps _wapi_namedevent_ops = { NULL, /* close */ namedevent_signal, /* signal */ namedevent_own, /* own */ NULL, /* is_owned */ + NULL, /* special_wait */ + NULL, /* prewait */ + namedevent_details, /* details */ + namedevent_typename, /* typename */ + namedevent_typesize, /* typesize */ }; -static gboolean event_pulse (gpointer handle); -static gboolean event_reset (gpointer handle); -static gboolean event_set (gpointer handle); - -static gboolean namedevent_pulse (gpointer handle); -static gboolean namedevent_reset (gpointer handle); -static gboolean namedevent_set (gpointer handle); - -static struct +void +_wapi_event_init (void) { - gboolean (*pulse)(gpointer handle); - gboolean (*reset)(gpointer handle); - gboolean (*set)(gpointer handle); -} event_ops[WAPI_HANDLE_COUNT] = { - {NULL}, - {NULL}, - {NULL}, - {NULL}, - {NULL}, - {NULL}, - {event_pulse, event_reset, event_set}, - {NULL}, - {NULL}, - {NULL}, - {NULL}, - {NULL}, - {NULL}, - {namedevent_pulse, namedevent_reset, namedevent_set}, -}; + mono_w32handle_register_ops (MONO_W32HANDLE_EVENT, &_wapi_event_ops); + mono_w32handle_register_ops (MONO_W32HANDLE_NAMEDEVENT, &_wapi_namedevent_ops); -void _wapi_event_details (gpointer handle_info) -{ - struct _WapiHandle_event *event = (struct _WapiHandle_event *)handle_info; - - g_print ("manual: %s", event->manual?"TRUE":"FALSE"); + mono_w32handle_register_capabilities (MONO_W32HANDLE_EVENT, + (MonoW32HandleCapability)(MONO_W32HANDLE_CAP_WAIT | MONO_W32HANDLE_CAP_SIGNAL)); + mono_w32handle_register_capabilities (MONO_W32HANDLE_NAMEDEVENT, + (MonoW32HandleCapability)(MONO_W32HANDLE_CAP_WAIT | MONO_W32HANDLE_CAP_SIGNAL)); } -static mono_once_t event_ops_once=MONO_ONCE_INIT; - -static void event_ops_init (void) +static const char* event_handle_type_to_string (MonoW32HandleType type) { - _wapi_handle_register_capabilities (WAPI_HANDLE_EVENT, - (WapiHandleCapability)(WAPI_HANDLE_CAP_WAIT | WAPI_HANDLE_CAP_SIGNAL)); - _wapi_handle_register_capabilities (WAPI_HANDLE_NAMEDEVENT, - (WapiHandleCapability)(WAPI_HANDLE_CAP_WAIT | WAPI_HANDLE_CAP_SIGNAL)); + switch (type) { + case MONO_W32HANDLE_EVENT: return "event"; + case MONO_W32HANDLE_NAMEDEVENT: return "named event"; + default: + g_assert_not_reached (); + } +} + +static gboolean event_handle_own (gpointer handle, MonoW32HandleType type) +{ + struct _WapiHandle_event *event_handle; + gboolean ok; + + ok = mono_w32handle_lookup (handle, type, (gpointer *)&event_handle); + if (!ok) { + g_warning ("%s: error looking up %s handle %p", + __func__, event_handle_type_to_string (type), handle); + return FALSE; + } + + MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: owning %s handle %p", + __func__, event_handle_type_to_string (type), handle); + + if (!event_handle->manual) { + g_assert (event_handle->set_count > 0); + event_handle->set_count --; + + if (event_handle->set_count == 0) + mono_w32handle_set_signal_state (handle, FALSE, FALSE); + } + + return TRUE; } static void event_signal(gpointer handle) @@ -96,28 +111,7 @@ static void event_signal(gpointer handle) static gboolean event_own (gpointer handle) { - struct _WapiHandle_event *event_handle; - gboolean ok; - - ok=_wapi_lookup_handle (handle, WAPI_HANDLE_EVENT, - (gpointer *)&event_handle); - if(ok==FALSE) { - g_warning ("%s: error looking up event handle %p", __func__, - handle); - return (FALSE); - } - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: owning event handle %p", __func__, handle); - - if(event_handle->manual==FALSE) { - g_assert (event_handle->set_count > 0); - - if (--event_handle->set_count == 0) { - _wapi_handle_set_signal_state (handle, FALSE, FALSE); - } - } - - return(TRUE); + return event_handle_own (handle, MONO_W32HANDLE_EVENT); } static void namedevent_signal (gpointer handle) @@ -128,181 +122,124 @@ static void namedevent_signal (gpointer handle) /* NB, always called with the shared handle lock held */ static gboolean namedevent_own (gpointer handle) { - struct _WapiHandle_namedevent *namedevent_handle; - gboolean ok; - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: owning named event handle %p", __func__, handle); - - ok = _wapi_lookup_handle (handle, WAPI_HANDLE_NAMEDEVENT, - (gpointer *)&namedevent_handle); - if (ok == FALSE) { - g_warning ("%s: error looking up named event handle %p", - __func__, handle); - return(FALSE); - } - - if (namedevent_handle->manual == FALSE) { - g_assert (namedevent_handle->set_count > 0); - - if (--namedevent_handle->set_count == 0) { - _wapi_shared_handle_set_signal_state (handle, FALSE); - } - } - - return (TRUE); + return event_handle_own (handle, MONO_W32HANDLE_NAMEDEVENT); } -static gpointer event_create (WapiSecurityAttributes *security G_GNUC_UNUSED, - gboolean manual, gboolean initial) + +static void event_details (gpointer data) +{ + struct _WapiHandle_event *event = (struct _WapiHandle_event *)data; + g_print ("manual: %s, set_count: %d", + event->manual ? "TRUE" : "FALSE", event->set_count); +} + +static void namedevent_details (gpointer data) +{ + struct _WapiHandle_namedevent *namedevent = (struct _WapiHandle_namedevent *)data; + g_print ("manual: %s, set_count: %d, name: \"%s\"", + namedevent->e.manual ? "TRUE" : "FALSE", namedevent->e.set_count, namedevent->sharedns.name); +} + +static const gchar* event_typename (void) +{ + return "Event"; +} + +static gsize event_typesize (void) +{ + return sizeof (struct _WapiHandle_event); +} + +static const gchar* namedevent_typename (void) +{ + return "N.Event"; +} + +static gsize namedevent_typesize (void) +{ + return sizeof (struct _WapiHandle_namedevent); +} + +static gpointer event_handle_create (struct _WapiHandle_event *event_handle, MonoW32HandleType type, gboolean manual, gboolean initial) { - struct _WapiHandle_event event_handle = {0}; gpointer handle; int thr_ret; - - /* Need to blow away any old errors here, because code tests - * for ERROR_ALREADY_EXISTS on success (!) to see if an event - * was freshly created - */ - SetLastError (ERROR_SUCCESS); - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Creating unnamed event", __func__); - - event_handle.manual = manual; - event_handle.set_count = 0; + event_handle->manual = manual; + event_handle->set_count = (initial && !manual) ? 1 : 0; - if (initial == TRUE) { - if (manual == FALSE) { - event_handle.set_count = 1; - } - } - - handle = _wapi_handle_new (WAPI_HANDLE_EVENT, &event_handle); - if (handle == _WAPI_HANDLE_INVALID) { - g_warning ("%s: error creating event handle", __func__); + handle = mono_w32handle_new (type, event_handle); + if (handle == INVALID_HANDLE_VALUE) { + g_warning ("%s: error creating %s handle", + __func__, event_handle_type_to_string (type)); SetLastError (ERROR_GEN_FAILURE); - return(NULL); + return NULL; } - thr_ret = _wapi_handle_lock_handle (handle); - g_assert (thr_ret == 0); - - if (initial == TRUE) { - _wapi_handle_set_signal_state (handle, TRUE, FALSE); - } - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: created new event handle %p", __func__, handle); - - thr_ret = _wapi_handle_unlock_handle (handle); + thr_ret = mono_w32handle_lock_handle (handle); g_assert (thr_ret == 0); - return(handle); + if (initial) + mono_w32handle_set_signal_state (handle, TRUE, FALSE); + + thr_ret = mono_w32handle_unlock_handle (handle); + g_assert (thr_ret == 0); + + MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: created %s handle %p", + __func__, event_handle_type_to_string (type), handle); + + return handle; } -static gpointer namedevent_create (WapiSecurityAttributes *security G_GNUC_UNUSED, - gboolean manual, gboolean initial, - const gunichar2 *name G_GNUC_UNUSED) +static gpointer event_create (gboolean manual, gboolean initial) +{ + struct _WapiHandle_event event_handle; + MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: creating %s handle", + __func__, event_handle_type_to_string (MONO_W32HANDLE_EVENT)); + return event_handle_create (&event_handle, MONO_W32HANDLE_EVENT, manual, initial); +} + +static gpointer namedevent_create (gboolean manual, gboolean initial, const gunichar2 *name G_GNUC_UNUSED) { - struct _WapiHandle_namedevent namedevent_handle = {{{0}}, 0}; gpointer handle; gchar *utf8_name; int thr_ret; - gpointer ret = NULL; - guint32 namelen; - gint32 offset; - - /* w32 seems to guarantee that opening named objects can't - * race each other - */ + + MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: creating %s handle", + __func__, event_handle_type_to_string (MONO_W32HANDLE_NAMEDEVENT)); + + /* w32 seems to guarantee that opening named objects can't race each other */ thr_ret = _wapi_namespace_lock (); g_assert (thr_ret == 0); - /* Need to blow away any old errors here, because code tests - * for ERROR_ALREADY_EXISTS on success (!) to see if an event - * was freshly created - */ - SetLastError (ERROR_SUCCESS); - utf8_name = g_utf16_to_utf8 (name, -1, NULL, NULL, NULL); - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Creating named event [%s]", __func__, utf8_name); - - offset = _wapi_search_handle_namespace (WAPI_HANDLE_NAMEDEVENT, - utf8_name); - if (offset == -1) { - /* The name has already been used for a different - * object. - */ + + handle = _wapi_search_handle_namespace (MONO_W32HANDLE_NAMEDEVENT, utf8_name); + if (handle == INVALID_HANDLE_VALUE) { + /* The name has already been used for a different object. */ + handle = NULL; SetLastError (ERROR_INVALID_HANDLE); - goto cleanup; - } else if (offset != 0) { - /* Not an error, but this is how the caller is - * informed that the event wasn't freshly created - */ + } else if (handle) { + /* Not an error, but this is how the caller is informed that the event wasn't freshly created */ SetLastError (ERROR_ALREADY_EXISTS); - } - /* Fall through to create the event handle. */ - if (offset == 0) { - /* A new named event, so create both the private and - * shared parts - */ - - if (strlen (utf8_name) < MAX_PATH) { - namelen = strlen (utf8_name); - } else { - namelen = MAX_PATH; - } - - memcpy (&namedevent_handle.sharedns.name, utf8_name, namelen); - - namedevent_handle.manual = manual; - namedevent_handle.set_count = 0; - - if (initial == TRUE) { - if (manual == FALSE) { - namedevent_handle.set_count = 1; - } - } - - handle = _wapi_handle_new (WAPI_HANDLE_NAMEDEVENT, - &namedevent_handle); + /* this is used as creating a new handle */ + mono_w32handle_ref (handle); } else { - /* A new reference to an existing named event, so just - * create the private part - */ - handle = _wapi_handle_new_from_offset (WAPI_HANDLE_NAMEDEVENT, - offset, TRUE); - } - - if (handle == _WAPI_HANDLE_INVALID) { - g_warning ("%s: error creating event handle", __func__); - SetLastError (ERROR_GEN_FAILURE); - goto cleanup; - } - ret = handle; + /* A new named event */ + struct _WapiHandle_namedevent namedevent_handle; - if (offset == 0) { - /* Set the initial state, as this is a completely new - * handle - */ - thr_ret = _wapi_handle_lock_shared_handles (); - g_assert (thr_ret == 0); - - if (initial == TRUE) { - _wapi_shared_handle_set_signal_state (handle, TRUE); - } + strncpy (&namedevent_handle.sharedns.name [0], utf8_name, MAX_PATH); + namedevent_handle.sharedns.name [MAX_PATH] = '\0'; - _wapi_handle_unlock_shared_handles (); + handle = event_handle_create ((struct _WapiHandle_event*) &namedevent_handle, MONO_W32HANDLE_NAMEDEVENT, manual, initial); } - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning event handle %p", __func__, handle); -cleanup: g_free (utf8_name); - _wapi_namespace_unlock (NULL); - - return(ret); + thr_ret = _wapi_namespace_unlock (NULL); + g_assert (thr_ret == 0); + return handle; } @@ -330,125 +267,13 @@ gpointer CreateEvent(WapiSecurityAttributes *security G_GNUC_UNUSED, gboolean manual, gboolean initial, const gunichar2 *name G_GNUC_UNUSED) { - mono_once (&event_ops_once, event_ops_init); + /* Need to blow away any old errors here, because code tests + * for ERROR_ALREADY_EXISTS on success (!) to see if an event + * was freshly created + */ + SetLastError (ERROR_SUCCESS); - if (name == NULL) { - return(event_create (security, manual, initial)); - } else { - return(namedevent_create (security, manual, initial, name)); - } -} - -static gboolean event_pulse (gpointer handle) -{ - struct _WapiHandle_event *event_handle; - gboolean ok; - int thr_ret; - - ok = _wapi_lookup_handle (handle, WAPI_HANDLE_EVENT, - (gpointer *)&event_handle); - if (ok == FALSE) { - g_warning ("%s: error looking up event handle %p", __func__, - handle); - return(FALSE); - } - - thr_ret = _wapi_handle_lock_handle (handle); - g_assert (thr_ret == 0); - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Pulsing event handle %p", __func__, handle); - - if (event_handle->manual == TRUE) { - _wapi_handle_set_signal_state (handle, TRUE, TRUE); - } else { - event_handle->set_count = 1; - _wapi_handle_set_signal_state (handle, TRUE, FALSE); - } - - thr_ret = _wapi_handle_unlock_handle (handle); - g_assert (thr_ret == 0); - - if (event_handle->manual == TRUE) { - /* For a manual-reset event, we're about to try and - * get the handle lock again, so give other threads a - * chance - */ - sched_yield (); - - /* Reset the handle signal state */ - /* I'm not sure whether or not we need a barrier here - * to make sure that all threads waiting on the event - * have proceeded. Currently we rely on broadcasting - * a condition. - */ - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Obtained write lock on event handle %p", - __func__, handle); - - thr_ret = _wapi_handle_lock_handle (handle); - g_assert (thr_ret == 0); - - _wapi_handle_set_signal_state (handle, FALSE, FALSE); - - thr_ret = _wapi_handle_unlock_handle (handle); - g_assert (thr_ret == 0); - } - - return(TRUE); -} - -static gboolean namedevent_pulse (gpointer handle) -{ - struct _WapiHandle_namedevent *namedevent_handle; - gboolean ok; - int thr_ret; - - ok = _wapi_lookup_handle (handle, WAPI_HANDLE_NAMEDEVENT, - (gpointer *)&namedevent_handle); - if (ok == FALSE) { - g_warning ("%s: error looking up named event handle %p", - __func__, handle); - return(FALSE); - } - - thr_ret = _wapi_handle_lock_shared_handles (); - g_assert (thr_ret == 0); - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Pulsing named event handle %p", __func__, handle); - - if (namedevent_handle->manual == TRUE) { - _wapi_shared_handle_set_signal_state (handle, TRUE); - } else { - namedevent_handle->set_count = 1; - _wapi_shared_handle_set_signal_state (handle, TRUE); - } - - _wapi_handle_unlock_shared_handles (); - - if (namedevent_handle->manual == TRUE) { - /* For a manual-reset event, we're about to try and - * get the handle lock again, so give other processes - * a chance - */ - _wapi_handle_spin (200); - - /* Reset the handle signal state */ - /* I'm not sure whether or not we need a barrier here - * to make sure that all threads waiting on the event - * have proceeded. Currently we rely on waiting for - * twice the shared handle poll interval. - */ - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Obtained write lock on event handle %p", - __func__, handle); - - thr_ret = _wapi_handle_lock_shared_handles (); - g_assert (thr_ret == 0); - - _wapi_shared_handle_set_signal_state (handle, FALSE); - - _wapi_handle_unlock_shared_handles (); - } - - return(TRUE); + return name ? namedevent_create (manual, initial, name) : event_create (manual, initial); } /** @@ -468,94 +293,65 @@ static gboolean namedevent_pulse (gpointer handle) */ gboolean PulseEvent(gpointer handle) { - WapiHandleType type; - + MonoW32HandleType type; + struct _WapiHandle_event *event_handle; + int thr_ret; + if (handle == NULL) { SetLastError (ERROR_INVALID_HANDLE); return(FALSE); } - - type = _wapi_handle_type (handle); - - if (event_ops[type].pulse == NULL) { + + switch (type = mono_w32handle_get_type (handle)) { + case MONO_W32HANDLE_EVENT: + case MONO_W32HANDLE_NAMEDEVENT: + break; + default: SetLastError (ERROR_INVALID_HANDLE); - return(FALSE); - } - - return(event_ops[type].pulse (handle)); -} - -static gboolean event_reset (gpointer handle) -{ - struct _WapiHandle_event *event_handle; - gboolean ok; - int thr_ret; - - ok = _wapi_lookup_handle (handle, WAPI_HANDLE_EVENT, - (gpointer *)&event_handle); - if (ok == FALSE) { - g_warning ("%s: error looking up event handle %p", - __func__, handle); - return(FALSE); + return FALSE; } - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Resetting event handle %p", __func__, handle); + if (!mono_w32handle_lookup (handle, type, (gpointer *)&event_handle)) { + g_warning ("%s: error looking up %s handle %p", + __func__, event_handle_type_to_string (type), handle); + return FALSE; + } - thr_ret = _wapi_handle_lock_handle (handle); + MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: pulsing %s handle %p", + __func__, event_handle_type_to_string (type), handle); + + thr_ret = mono_w32handle_lock_handle (handle); g_assert (thr_ret == 0); - - if (_wapi_handle_issignalled (handle) == FALSE) { - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: No need to reset event handle %p", __func__, - handle); + + if (!event_handle->manual) { + event_handle->set_count = 1; + mono_w32handle_set_signal_state (handle, TRUE, FALSE); } else { - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Obtained write lock on event handle %p", - __func__, handle); + mono_w32handle_set_signal_state (handle, TRUE, TRUE); - _wapi_handle_set_signal_state (handle, FALSE, FALSE); + thr_ret = mono_w32handle_unlock_handle (handle); + g_assert (thr_ret == 0); + + /* For a manual-reset event, we're about to try and get the handle + * lock again, so give other threads a chance */ + sched_yield (); + + /* Reset the handle signal state */ + + /* I'm not sure whether or not we need a barrier here to make sure + * that all threads waiting on the event have proceeded. Currently + * we rely on broadcasting a condition. */ + + thr_ret = mono_w32handle_lock_handle (handle); + g_assert (thr_ret == 0); + + mono_w32handle_set_signal_state (handle, FALSE, FALSE); } - - event_handle->set_count = 0; - - thr_ret = _wapi_handle_unlock_handle (handle); + + thr_ret = mono_w32handle_unlock_handle (handle); g_assert (thr_ret == 0); - - return(TRUE); -} -static gboolean namedevent_reset (gpointer handle) -{ - struct _WapiHandle_namedevent *namedevent_handle; - gboolean ok; - int thr_ret; - - ok = _wapi_lookup_handle (handle, WAPI_HANDLE_NAMEDEVENT, - (gpointer *)&namedevent_handle); - if (ok == FALSE) { - g_warning ("%s: error looking up named event handle %p", - __func__, handle); - return(FALSE); - } - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Resetting named event handle %p", __func__, handle); - - thr_ret = _wapi_handle_lock_shared_handles (); - g_assert (thr_ret == 0); - - if (_wapi_handle_issignalled (handle) == FALSE) { - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: No need to reset named event handle %p", - __func__, handle); - } else { - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Obtained write lock on named event handle %p", - __func__, handle); - - _wapi_shared_handle_set_signal_state (handle, FALSE); - } - - namedevent_handle->set_count = 0; - - _wapi_handle_unlock_shared_handles (); - - return(TRUE); + return TRUE; } /** @@ -569,84 +365,54 @@ static gboolean namedevent_reset (gpointer handle) */ gboolean ResetEvent(gpointer handle) { - WapiHandleType type; + MonoW32HandleType type; + struct _WapiHandle_event *event_handle; + int thr_ret; + + SetLastError (ERROR_SUCCESS); if (handle == NULL) { SetLastError (ERROR_INVALID_HANDLE); return(FALSE); } - type = _wapi_handle_type (handle); - - if (event_ops[type].reset == NULL) { + switch (type = mono_w32handle_get_type (handle)) { + case MONO_W32HANDLE_EVENT: + case MONO_W32HANDLE_NAMEDEVENT: + break; + default: SetLastError (ERROR_INVALID_HANDLE); - return(FALSE); + return FALSE; } - - return(event_ops[type].reset (handle)); -} -static gboolean event_set (gpointer handle) -{ - struct _WapiHandle_event *event_handle; - gboolean ok; - int thr_ret; - - ok = _wapi_lookup_handle (handle, WAPI_HANDLE_EVENT, - (gpointer *)&event_handle); - if (ok == FALSE) { - g_warning ("%s: error looking up event handle %p", __func__, - handle); - return(FALSE); + if (!mono_w32handle_lookup (handle, type, (gpointer *)&event_handle)) { + g_warning ("%s: error looking up %s handle %p", + __func__, event_handle_type_to_string (type), handle); + return FALSE; } - - thr_ret = _wapi_handle_lock_handle (handle); + + MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: resetting %s handle %p", + __func__, event_handle_type_to_string (type), handle); + + thr_ret = mono_w32handle_lock_handle (handle); g_assert (thr_ret == 0); - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Setting event handle %p", __func__, handle); - - if (event_handle->manual == TRUE) { - _wapi_handle_set_signal_state (handle, TRUE, TRUE); + if (!mono_w32handle_issignalled (handle)) { + MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: no need to reset %s handle %p", + __func__, event_handle_type_to_string (type), handle); } else { - event_handle->set_count = 1; - _wapi_handle_set_signal_state (handle, TRUE, FALSE); + MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: obtained write lock on %s handle %p", + __func__, event_handle_type_to_string (type), handle); + + mono_w32handle_set_signal_state (handle, FALSE, FALSE); } - thr_ret = _wapi_handle_unlock_handle (handle); - g_assert (thr_ret == 0); - - return(TRUE); -} + event_handle->set_count = 0; -static gboolean namedevent_set (gpointer handle) -{ - struct _WapiHandle_namedevent *namedevent_handle; - gboolean ok; - int thr_ret; - - ok = _wapi_lookup_handle (handle, WAPI_HANDLE_NAMEDEVENT, - (gpointer *)&namedevent_handle); - if (ok == FALSE) { - g_warning ("%s: error looking up named event handle %p", - __func__, handle); - return(FALSE); - } - - thr_ret = _wapi_handle_lock_shared_handles (); + thr_ret = mono_w32handle_unlock_handle (handle); g_assert (thr_ret == 0); - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Setting named event handle %p", __func__, handle); - - if (namedevent_handle->manual == TRUE) { - _wapi_shared_handle_set_signal_state (handle, TRUE); - } else { - namedevent_handle->set_count = 1; - _wapi_shared_handle_set_signal_state (handle, TRUE); - } - - _wapi_handle_unlock_shared_handles (); - - return(TRUE); + return TRUE; } /** @@ -665,21 +431,47 @@ static gboolean namedevent_set (gpointer handle) */ gboolean SetEvent(gpointer handle) { - WapiHandleType type; + MonoW32HandleType type; + struct _WapiHandle_event *event_handle; + int thr_ret; if (handle == NULL) { SetLastError (ERROR_INVALID_HANDLE); return(FALSE); } - type = _wapi_handle_type (handle); - - if (event_ops[type].set == NULL) { + switch (type = mono_w32handle_get_type (handle)) { + case MONO_W32HANDLE_EVENT: + case MONO_W32HANDLE_NAMEDEVENT: + break; + default: SetLastError (ERROR_INVALID_HANDLE); - return(FALSE); + return FALSE; } - - return(event_ops[type].set (handle)); + + if (!mono_w32handle_lookup (handle, type, (gpointer *)&event_handle)) { + g_warning ("%s: error looking up %s handle %p", + __func__, event_handle_type_to_string (type), handle); + return FALSE; + } + + MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: setting %s handle %p", + __func__, event_handle_type_to_string (type), handle); + + thr_ret = mono_w32handle_lock_handle (handle); + g_assert (thr_ret == 0); + + if (!event_handle->manual) { + event_handle->set_count = 1; + mono_w32handle_set_signal_state (handle, TRUE, FALSE); + } else { + mono_w32handle_set_signal_state (handle, TRUE, TRUE); + } + + thr_ret = mono_w32handle_unlock_handle (handle); + g_assert (thr_ret == 0); + + return TRUE; } gpointer OpenEvent (guint32 access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED, const gunichar2 *name) @@ -687,10 +479,6 @@ gpointer OpenEvent (guint32 access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED gpointer handle; gchar *utf8_name; int thr_ret; - gpointer ret = NULL; - gint32 offset; - - mono_once (&event_ops_once, event_ops_init); /* w32 seems to guarantee that opening named objects can't * race each other @@ -702,33 +490,20 @@ gpointer OpenEvent (guint32 access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Opening named event [%s]", __func__, utf8_name); - offset = _wapi_search_handle_namespace (WAPI_HANDLE_NAMEDEVENT, + handle = _wapi_search_handle_namespace (MONO_W32HANDLE_NAMEDEVENT, utf8_name); - if (offset == -1) { + if (handle == INVALID_HANDLE_VALUE) { /* The name has already been used for a different * object. */ SetLastError (ERROR_INVALID_HANDLE); goto cleanup; - } else if (offset == 0) { + } else if (!handle) { /* This name doesn't exist */ SetLastError (ERROR_FILE_NOT_FOUND); /* yes, really */ goto cleanup; } - /* A new reference to an existing named event, so just create - * the private part - */ - handle = _wapi_handle_new_from_offset (WAPI_HANDLE_NAMEDEVENT, offset, - TRUE); - - if (handle == _WAPI_HANDLE_INVALID) { - g_warning ("%s: error opening named event handle", __func__); - SetLastError (ERROR_GEN_FAILURE); - goto cleanup; - } - ret = handle; - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning named event handle %p", __func__, handle); cleanup: @@ -736,6 +511,6 @@ cleanup: _wapi_namespace_unlock (NULL); - return(ret); + return handle; } diff --git a/mono/io-layer/handles-private.h b/mono/io-layer/handles-private.h deleted file mode 100644 index 4f20de02d4..0000000000 --- a/mono/io-layer/handles-private.h +++ /dev/null @@ -1,367 +0,0 @@ -/* - * handles-private.h: Internal operations on handles - * - * Author: - * Dick Porter (dick@ximian.com) - * - * (C) 2002-2006 Novell, Inc. - */ - -#ifndef _WAPI_HANDLES_PRIVATE_H_ -#define _WAPI_HANDLES_PRIVATE_H_ - -#include -#include -#include -#include -#include - -#include -#include -#include - -#define _WAPI_PRIVATE_MAX_SLOTS (1024 * 16) -#define _WAPI_PRIVATE_HANDLES(x) (_wapi_private_handles [x / _WAPI_HANDLE_INITIAL_COUNT][x % _WAPI_HANDLE_INITIAL_COUNT]) -#define _WAPI_PRIVATE_HAVE_SLOT(x) ((GPOINTER_TO_UINT (x) / _WAPI_PRIVATE_MAX_SLOTS) < _WAPI_PRIVATE_MAX_SLOTS && \ - _wapi_private_handles [GPOINTER_TO_UINT (x) / _WAPI_HANDLE_INITIAL_COUNT] != NULL) -#define _WAPI_PRIVATE_VALID_SLOT(x) (((x) / _WAPI_HANDLE_INITIAL_COUNT) < _WAPI_PRIVATE_MAX_SLOTS) - -#undef DEBUG - -extern struct _WapiHandleUnshared *_wapi_private_handles []; -extern struct _WapiHandleSharedLayout *_wapi_shared_layout; - -extern guint32 _wapi_fd_reserve; -extern mono_mutex_t *_wapi_global_signal_mutex; -extern pthread_cond_t *_wapi_global_signal_cond; -extern int _wapi_sem_id; -extern gboolean _wapi_has_shut_down; - -extern pid_t _wapi_getpid (void); -extern gpointer _wapi_handle_new (WapiHandleType type, - gpointer handle_specific); -extern gpointer _wapi_handle_new_fd (WapiHandleType type, int fd, - gpointer handle_specific); -extern gpointer _wapi_handle_new_from_offset (WapiHandleType type, - guint32 offset, - gboolean timestamp); -extern gboolean _wapi_lookup_handle (gpointer handle, WapiHandleType type, - gpointer *handle_specific); -extern gpointer _wapi_search_handle (WapiHandleType type, - gboolean (*check)(gpointer, gpointer), - gpointer user_data, - gpointer *handle_specific, - gboolean search_shared); -extern gint32 _wapi_search_handle_namespace (WapiHandleType type, - gchar *utf8_name); -extern void _wapi_handle_ref (gpointer handle); -extern void _wapi_handle_unref (gpointer handle); -extern void _wapi_handle_register_capabilities (WapiHandleType type, - WapiHandleCapability caps); -extern gboolean _wapi_handle_test_capabilities (gpointer handle, - WapiHandleCapability caps); -extern void _wapi_handle_ops_close (gpointer handle, gpointer data); -extern void _wapi_handle_ops_signal (gpointer handle); -extern gboolean _wapi_handle_ops_own (gpointer handle); -extern gboolean _wapi_handle_ops_isowned (gpointer handle); -extern guint32 _wapi_handle_ops_special_wait (gpointer handle, - guint32 timeout, - gboolean alertable); -extern void _wapi_handle_ops_prewait (gpointer handle); - -extern gboolean _wapi_handle_count_signalled_handles (guint32 numhandles, - gpointer *handles, - gboolean waitall, - guint32 *retcount, - guint32 *lowest); -extern void _wapi_handle_unlock_handles (guint32 numhandles, - gpointer *handles); -extern int _wapi_handle_timedwait_signal (guint32 timeout, gboolean poll, gboolean *alerted); -extern int _wapi_handle_timedwait_signal_handle (gpointer handle, guint32 timeout, gboolean alertable, gboolean poll, gboolean *alerted); -extern gboolean _wapi_handle_get_or_set_share (guint64 device, guint64 inode, - guint32 new_sharemode, - guint32 new_access, - guint32 *old_sharemode, - guint32 *old_access, - struct _WapiFileShare **info); -extern void _wapi_handle_check_share (struct _WapiFileShare *share_info, - int fd); -extern void _wapi_handle_dump (void); -extern void _wapi_handle_foreach (WapiHandleType type, - gboolean (*on_each)(gpointer test, gpointer user), - gpointer user_data); -void _wapi_free_share_info (_WapiFileShare *share_info); - -/* This is OK to use for atomic writes of individual struct members, as they - * are independent - */ -#define WAPI_SHARED_HANDLE_DATA(handle) _wapi_shared_layout->handles[_WAPI_PRIVATE_HANDLES(GPOINTER_TO_UINT((handle))).u.shared.offset] - -#define WAPI_SHARED_HANDLE_TYPED_DATA(handle, type) _wapi_shared_layout->handles[_WAPI_PRIVATE_HANDLES(GPOINTER_TO_UINT((handle))).u.shared.offset].u.type - -static inline WapiHandleType _wapi_handle_type (gpointer handle) -{ - guint32 idx = GPOINTER_TO_UINT(handle); - - if (!_WAPI_PRIVATE_VALID_SLOT (idx) || !_WAPI_PRIVATE_HAVE_SLOT (idx)) { - return(WAPI_HANDLE_UNUSED); /* An impossible type */ - } - - return(_WAPI_PRIVATE_HANDLES(idx).type); -} - -static inline void _wapi_handle_set_signal_state (gpointer handle, - gboolean state, - gboolean broadcast) -{ - guint32 idx = GPOINTER_TO_UINT(handle); - struct _WapiHandleUnshared *handle_data; - int thr_ret; - - if (!_WAPI_PRIVATE_VALID_SLOT (idx)) { - return; - } - - g_assert (!_WAPI_SHARED_HANDLE(_wapi_handle_type (handle))); - - handle_data = &_WAPI_PRIVATE_HANDLES(idx); - -#ifdef DEBUG - g_message ("%s: setting state of %p to %s (broadcast %s)", __func__, - handle, state?"TRUE":"FALSE", broadcast?"TRUE":"FALSE"); -#endif - - if (state == TRUE) { - /* Tell everyone blocking on a single handle */ - - /* The condition the global signal cond is waiting on is the signalling of - * _any_ handle. So lock it before setting the signalled state. - */ - thr_ret = mono_os_mutex_lock (_wapi_global_signal_mutex); - if (thr_ret != 0) - g_warning ("Bad call to mono_os_mutex_lock result %d for global signal mutex", thr_ret); - g_assert (thr_ret == 0); - - /* This function _must_ be called with - * handle->signal_mutex locked - */ - handle_data->signalled=state; - - if (broadcast == TRUE) { - thr_ret = pthread_cond_broadcast (&handle_data->signal_cond); - if (thr_ret != 0) - g_warning ("Bad call to pthread_cond_broadcast result %d for handle %p", thr_ret, handle); - g_assert (thr_ret == 0); - } else { - thr_ret = pthread_cond_signal (&handle_data->signal_cond); - if (thr_ret != 0) - g_warning ("Bad call to pthread_cond_signal result %d for handle %p", thr_ret, handle); - g_assert (thr_ret == 0); - } - - /* Tell everyone blocking on multiple handles that something - * was signalled - */ - thr_ret = pthread_cond_broadcast (_wapi_global_signal_cond); - if (thr_ret != 0) - g_warning ("Bad call to pthread_cond_broadcast result %d for handle %p", thr_ret, handle); - g_assert (thr_ret == 0); - - thr_ret = mono_os_mutex_unlock (_wapi_global_signal_mutex); - if (thr_ret != 0) - g_warning ("Bad call to mono_os_mutex_unlock result %d for global signal mutex", thr_ret); - g_assert (thr_ret == 0); - } else { - handle_data->signalled=state; - } -} - -static inline void _wapi_shared_handle_set_signal_state (gpointer handle, - gboolean state) -{ - guint32 idx = GPOINTER_TO_UINT(handle); - struct _WapiHandleUnshared *handle_data; - struct _WapiHandle_shared_ref *ref; - struct _WapiHandleShared *shared_data; - - if (!_WAPI_PRIVATE_VALID_SLOT (idx)) { - return; - } - - g_assert (_WAPI_SHARED_HANDLE(_wapi_handle_type (handle))); - - handle_data = &_WAPI_PRIVATE_HANDLES(idx); - - ref = &handle_data->u.shared; - shared_data = &_wapi_shared_layout->handles[ref->offset]; - shared_data->signalled = state; - -#ifdef DEBUG - g_message ("%s: signalled shared handle offset 0x%x", __func__, - ref->offset); -#endif -} - -static inline gboolean _wapi_handle_issignalled (gpointer handle) -{ - guint32 idx = GPOINTER_TO_UINT(handle); - - if (!_WAPI_PRIVATE_VALID_SLOT (idx)) { - return(FALSE); - } - - if (_WAPI_SHARED_HANDLE(_wapi_handle_type (handle))) { - return(WAPI_SHARED_HANDLE_DATA(handle).signalled); - } else { - return(_WAPI_PRIVATE_HANDLES(idx).signalled); - } -} - -static inline int _wapi_handle_lock_signal_mutex (void) -{ -#ifdef DEBUG - g_message ("%s: lock global signal mutex", __func__); -#endif - - return(mono_os_mutex_lock (_wapi_global_signal_mutex)); -} - -/* the parameter makes it easier to call from a pthread cleanup handler */ -static inline int _wapi_handle_unlock_signal_mutex (void *unused) -{ -#ifdef DEBUG - g_message ("%s: unlock global signal mutex", __func__); -#endif - - return(mono_os_mutex_unlock (_wapi_global_signal_mutex)); -} - -static inline int _wapi_handle_lock_handle (gpointer handle) -{ - guint32 idx = GPOINTER_TO_UINT(handle); - -#ifdef DEBUG - g_message ("%s: locking handle %p", __func__, handle); -#endif - - if (!_WAPI_PRIVATE_VALID_SLOT (idx)) { - return(0); - } - - _wapi_handle_ref (handle); - - if (_WAPI_SHARED_HANDLE (_wapi_handle_type (handle))) { - return(0); - } - - return(mono_os_mutex_lock (&_WAPI_PRIVATE_HANDLES(idx).signal_mutex)); -} - -static inline int _wapi_handle_trylock_handle (gpointer handle) -{ - guint32 idx = GPOINTER_TO_UINT(handle); - int ret; - -#ifdef DEBUG - g_message ("%s: locking handle %p", __func__, handle); -#endif - - if (!_WAPI_PRIVATE_VALID_SLOT (idx)) { - return(0); - } - - _wapi_handle_ref (handle); - - if (_WAPI_SHARED_HANDLE (_wapi_handle_type (handle))) { - return(0); - } - - ret = mono_os_mutex_trylock (&_WAPI_PRIVATE_HANDLES(idx).signal_mutex); - if (ret != 0) { - _wapi_handle_unref (handle); - } - - return(ret); -} - -static inline int _wapi_handle_unlock_handle (gpointer handle) -{ - guint32 idx = GPOINTER_TO_UINT(handle); - int ret; - -#ifdef DEBUG - g_message ("%s: unlocking handle %p", __func__, handle); -#endif - - if (!_WAPI_PRIVATE_VALID_SLOT (idx)) { - return(0); - } - - if (_WAPI_SHARED_HANDLE (_wapi_handle_type (handle))) { - _wapi_handle_unref (handle); - return(0); - } - - ret = mono_os_mutex_unlock (&_WAPI_PRIVATE_HANDLES(idx).signal_mutex); - - _wapi_handle_unref (handle); - - return(ret); -} - -static inline void _wapi_handle_spin (guint32 ms) -{ - struct timespec sleepytime; - - g_assert (ms < 1000); - - sleepytime.tv_sec = 0; - sleepytime.tv_nsec = ms * 1000000; - - nanosleep (&sleepytime, NULL); -} - -static inline int _wapi_handle_lock_shared_handles (void) -{ - return(_wapi_shm_sem_lock (_WAPI_SHARED_SEM_SHARED_HANDLES)); -} - -static inline int _wapi_handle_trylock_shared_handles (void) -{ - return(_wapi_shm_sem_trylock (_WAPI_SHARED_SEM_SHARED_HANDLES)); -} - -static inline int _wapi_handle_unlock_shared_handles (void) -{ - return(_wapi_shm_sem_unlock (_WAPI_SHARED_SEM_SHARED_HANDLES)); -} - -static inline int _wapi_namespace_lock (void) -{ - return(_wapi_shm_sem_lock (_WAPI_SHARED_SEM_NAMESPACE)); -} - -/* This signature makes it easier to use in pthread cleanup handlers */ -static inline int _wapi_namespace_unlock (gpointer data G_GNUC_UNUSED) -{ - return(_wapi_shm_sem_unlock (_WAPI_SHARED_SEM_NAMESPACE)); -} - -static inline void _wapi_handle_share_release (struct _WapiFileShare *info) -{ - int thr_ret; - - g_assert (info->handle_refs > 0); - - /* Prevent new entries racing with us */ - thr_ret = _wapi_shm_sem_lock (_WAPI_SHARED_SEM_FILESHARE); - g_assert(thr_ret == 0); - - if (InterlockedDecrement ((gint32 *)&info->handle_refs) == 0) { - _wapi_free_share_info (info); - } - - thr_ret = _wapi_shm_sem_unlock (_WAPI_SHARED_SEM_FILESHARE); -} - -#endif /* _WAPI_HANDLES_PRIVATE_H_ */ diff --git a/mono/io-layer/handles.c b/mono/io-layer/handles.c deleted file mode 100644 index 814d216fe5..0000000000 --- a/mono/io-layer/handles.c +++ /dev/null @@ -1,1840 +0,0 @@ -/* - * handles.c: Generic and internal operations on handles - * - * Author: - * Dick Porter (dick@ximian.com) - * - * (C) 2002-2011 Novell, Inc. - * Copyright 2011 Xamarin Inc - * Licensed under the MIT license. See LICENSE file in the project root for full license information. - */ - -#include -#include -#include -#include -#include -#ifdef HAVE_SIGNAL_H -#include -#endif -#include -#include -#ifdef HAVE_SYS_SOCKET_H -# include -#endif -#ifdef HAVE_SYS_UN_H -# include -#endif -#ifdef HAVE_SYS_MMAN_H -# include -#endif -#ifdef HAVE_DIRENT_H -# include -#endif -#include -#ifdef HAVE_SYS_RESOURCE_H -# include -#endif - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#undef DEBUG_REFS - -static void (*_wapi_handle_ops_get_close_func (WapiHandleType type))(gpointer, gpointer); - -static WapiHandleCapability handle_caps[WAPI_HANDLE_COUNT] = { (WapiHandleCapability)0 }; -static struct _WapiHandleOps *handle_ops[WAPI_HANDLE_COUNT]={ - NULL, - &_wapi_file_ops, - &_wapi_console_ops, - &_wapi_thread_ops, - &_wapi_sem_ops, - &_wapi_mutex_ops, - &_wapi_event_ops, -#ifndef DISABLE_SOCKETS - &_wapi_socket_ops, -#endif - &_wapi_find_ops, - &_wapi_process_ops, - &_wapi_pipe_ops, - &_wapi_namedmutex_ops, - &_wapi_namedsem_ops, - &_wapi_namedevent_ops, -}; - -static void _wapi_shared_details (gpointer handle_info); - -static void (*handle_details[WAPI_HANDLE_COUNT])(gpointer) = { - NULL, - _wapi_file_details, - _wapi_console_details, - _wapi_shared_details, /* thread */ - _wapi_sem_details, - _wapi_mutex_details, - _wapi_event_details, - NULL, /* Nothing useful to see in a socket handle */ - NULL, /* Nothing useful to see in a find handle */ - _wapi_shared_details, /* process */ - _wapi_pipe_details, - _wapi_shared_details, /* namedmutex */ - _wapi_shared_details, /* namedsem */ - _wapi_shared_details, /* namedevent */ -}; - -const char *_wapi_handle_typename[] = { - "Unused", - "File", - "Console", - "Thread", - "Sem", - "Mutex", - "Event", - "Socket", - "Find", - "Process", - "Pipe", - "N.Mutex", - "N.Sem", - "N.Event", - "Error!!" -}; - -/* - * We can hold _WAPI_PRIVATE_MAX_SLOTS * _WAPI_HANDLE_INITIAL_COUNT handles. - * If 4M handles are not enough... Oh, well... we will crash. - */ -#define SLOT_INDEX(x) (x / _WAPI_HANDLE_INITIAL_COUNT) -#define SLOT_OFFSET(x) (x % _WAPI_HANDLE_INITIAL_COUNT) - -struct _WapiHandleUnshared *_wapi_private_handles [_WAPI_PRIVATE_MAX_SLOTS]; -static guint32 _wapi_private_handle_count = 0; -static guint32 _wapi_private_handle_slot_count = 0; - -struct _WapiHandleSharedLayout *_wapi_shared_layout = NULL; - -/* - * If SHM is disabled, this will point to a hash of _WapiFileShare structures, otherwise - * it will be NULL. We use this instead of _wapi_fileshare_layout to avoid allocating a - * 4MB array. - */ -static GHashTable *file_share_hash; -static mono_mutex_t file_share_hash_mutex; - -#define file_share_hash_lock() mono_os_mutex_lock (&file_share_hash_mutex) -#define file_share_hash_unlock() mono_os_mutex_unlock (&file_share_hash_mutex) - -guint32 _wapi_fd_reserve; - -/* - * This is an internal handle which is used for handling waiting for multiple handles. - * Threads which wait for multiple handles wait on this one handle, and when a handle - * is signalled, this handle is signalled too. - */ -static gpointer _wapi_global_signal_handle; - -/* Point to the mutex/cond inside _wapi_global_signal_handle */ -mono_mutex_t *_wapi_global_signal_mutex; -pthread_cond_t *_wapi_global_signal_cond; - -int _wapi_sem_id; -gboolean _wapi_has_shut_down = FALSE; - -/* Use this instead of getpid(), to cope with linuxthreads. It's a - * function rather than a variable lookup because we need to get at - * this before share_init() might have been called. - */ -static pid_t _wapi_pid; -static mono_once_t pid_init_once = MONO_ONCE_INIT; - -static void _wapi_handle_unref_full (gpointer handle, gboolean ignore_private_busy_handles); - -static void pid_init (void) -{ - _wapi_pid = getpid (); -} - -pid_t _wapi_getpid (void) -{ - mono_once (&pid_init_once, pid_init); - - return(_wapi_pid); -} - - -static mono_mutex_t scan_mutex; - -static void handle_cleanup (void) -{ - int i, j, k; - - /* Every shared handle we were using ought really to be closed - * by now, but to make sure just blow them all away. The - * exiting finalizer thread in particular races us to the - * program exit and doesn't always win, so it can be left - * cluttering up the shared file. Anything else left over is - * really a bug. - */ - for(i = SLOT_INDEX (0); _wapi_private_handles[i] != NULL; i++) { - for(j = SLOT_OFFSET (0); j < _WAPI_HANDLE_INITIAL_COUNT; j++) { - struct _WapiHandleUnshared *handle_data = &_wapi_private_handles[i][j]; - gpointer handle = GINT_TO_POINTER (i*_WAPI_HANDLE_INITIAL_COUNT+j); - - for(k = handle_data->ref; k > 0; k--) { - _wapi_handle_unref_full (handle, TRUE); - } - } - } - - _wapi_shm_semaphores_remove (); - - g_free (_wapi_shared_layout); - - if (file_share_hash) { - g_hash_table_destroy (file_share_hash); - mono_os_mutex_destroy (&file_share_hash_mutex); - } - - for (i = 0; i < _WAPI_PRIVATE_MAX_SLOTS; ++i) - g_free (_wapi_private_handles [i]); -} - -int -wapi_getdtablesize (void) -{ - return eg_getdtablesize (); -} - -/* - * wapi_init: - * - * Initialize the io-layer. - */ -void -wapi_init (void) -{ - g_assert ((sizeof (handle_ops) / sizeof (handle_ops[0])) - == WAPI_HANDLE_COUNT); - - _wapi_fd_reserve = wapi_getdtablesize (); - - /* This is needed by the code in _wapi_handle_new_internal */ - _wapi_fd_reserve = (_wapi_fd_reserve + (_WAPI_HANDLE_INITIAL_COUNT - 1)) & ~(_WAPI_HANDLE_INITIAL_COUNT - 1); - - do { - /* - * The entries in _wapi_private_handles reserved for fds are allocated lazily to - * save memory. - */ - /* - _wapi_private_handles [idx++] = g_new0 (struct _WapiHandleUnshared, - _WAPI_HANDLE_INITIAL_COUNT); - */ - - _wapi_private_handle_count += _WAPI_HANDLE_INITIAL_COUNT; - _wapi_private_handle_slot_count ++; - } while(_wapi_fd_reserve > _wapi_private_handle_count); - - _wapi_shm_semaphores_init (); - - _wapi_shared_layout = (_WapiHandleSharedLayout *)g_malloc0 (sizeof (_WapiHandleSharedLayout)); - g_assert (_wapi_shared_layout != NULL); - - _wapi_io_init (); - mono_os_mutex_init (&scan_mutex); - - _wapi_global_signal_handle = _wapi_handle_new (WAPI_HANDLE_EVENT, NULL); - - _wapi_global_signal_cond = &_WAPI_PRIVATE_HANDLES (GPOINTER_TO_UINT (_wapi_global_signal_handle)).signal_cond; - _wapi_global_signal_mutex = &_WAPI_PRIVATE_HANDLES (GPOINTER_TO_UINT (_wapi_global_signal_handle)).signal_mutex; - - wapi_processes_init (); -} - -void -wapi_cleanup (void) -{ - g_assert (_wapi_has_shut_down == FALSE); - - _wapi_has_shut_down = TRUE; - - _wapi_error_cleanup (); - _wapi_thread_cleanup (); - wapi_processes_cleanup (); - handle_cleanup (); -} - -static void _wapi_handle_init_shared (struct _WapiHandleShared *handle, - WapiHandleType type, - gpointer handle_specific) -{ - g_assert (_wapi_has_shut_down == FALSE); - - handle->type = type; - handle->timestamp = (guint32)(time (NULL) & 0xFFFFFFFF); - handle->signalled = FALSE; - handle->handle_refs = 1; - - if (handle_specific != NULL) { - memcpy (&handle->u, handle_specific, sizeof (handle->u)); - } -} - -static size_t _wapi_handle_struct_size (WapiHandleType type) -{ - size_t type_size; - - switch (type) { - case WAPI_HANDLE_FILE: case WAPI_HANDLE_CONSOLE: case WAPI_HANDLE_PIPE: - type_size = sizeof (struct _WapiHandle_file); - break; - case WAPI_HANDLE_THREAD: - type_size = sizeof (struct _WapiHandle_thread); - break; - case WAPI_HANDLE_SEM: - type_size = sizeof (struct _WapiHandle_sem); - break; - case WAPI_HANDLE_MUTEX: - type_size = sizeof (struct _WapiHandle_mutex); - break; - case WAPI_HANDLE_EVENT: - type_size = sizeof (struct _WapiHandle_event); - break; - case WAPI_HANDLE_SOCKET: - type_size = sizeof (struct _WapiHandle_socket); - break; - case WAPI_HANDLE_FIND: - type_size = sizeof (struct _WapiHandle_find); - break; - case WAPI_HANDLE_PROCESS: - type_size = sizeof (struct _WapiHandle_process); - break; - case WAPI_HANDLE_NAMEDMUTEX: - type_size = sizeof (struct _WapiHandle_namedmutex); - break; - case WAPI_HANDLE_NAMEDSEM: - type_size = sizeof (struct _WapiHandle_namedsem); - break; - case WAPI_HANDLE_NAMEDEVENT: - type_size = sizeof (struct _WapiHandle_namedevent); - break; - - default: - g_error ("Unknown WapiHandleType: %d\n", type); - } - - return type_size; -} - -static void _wapi_handle_init (struct _WapiHandleUnshared *handle, - WapiHandleType type, gpointer handle_specific) -{ - int thr_ret; - int type_size; - - g_assert (_wapi_has_shut_down == FALSE); - - handle->type = type; - handle->signalled = FALSE; - handle->ref = 1; - - if (!_WAPI_SHARED_HANDLE(type)) { - thr_ret = pthread_cond_init (&handle->signal_cond, NULL); - g_assert (thr_ret == 0); - - thr_ret = mono_os_mutex_init (&handle->signal_mutex); - g_assert (thr_ret == 0); - - if (handle_specific != NULL) { - type_size = _wapi_handle_struct_size (type); - memcpy (&handle->u, handle_specific, - type_size); - } - } -} - -static guint32 _wapi_handle_new_shared (WapiHandleType type, - gpointer handle_specific) -{ - guint32 offset; - static guint32 last = 1; - int thr_ret; - - g_assert (_wapi_has_shut_down == FALSE); - - /* Leave the first slot empty as a guard */ -again: - /* FIXME: expandable array */ - for(offset = last; offset <_WAPI_HANDLE_INITIAL_COUNT; offset++) { - struct _WapiHandleShared *handle = &_wapi_shared_layout->handles[offset]; - - if(handle->type == WAPI_HANDLE_UNUSED) { - thr_ret = _wapi_handle_lock_shared_handles (); - g_assert (thr_ret == 0); - - if (InterlockedCompareExchange ((gint32 *)&handle->type, type, WAPI_HANDLE_UNUSED) == WAPI_HANDLE_UNUSED) { - last = offset + 1; - - _wapi_handle_init_shared (handle, type, - handle_specific); - - _wapi_handle_unlock_shared_handles (); - - return(offset); - } else { - /* Someone else beat us to it, just - * continue looking - */ - } - - _wapi_handle_unlock_shared_handles (); - } - } - - if(last > 1) { - /* Try again from the beginning */ - last = 1; - goto again; - } - - /* Will need to expand the array. The caller will sort it out */ - - return(0); -} - -/* - * _wapi_handle_new_internal: - * @type: Init handle to this type - * - * Search for a free handle and initialize it. Return the handle on - * success and 0 on failure. This is only called from - * _wapi_handle_new, and scan_mutex must be held. - */ -static guint32 _wapi_handle_new_internal (WapiHandleType type, - gpointer handle_specific) -{ - guint32 i, k, count; - static guint32 last = 0; - gboolean retry = FALSE; - - g_assert (_wapi_has_shut_down == FALSE); - - /* A linear scan should be fast enough. Start from the last - * allocation, assuming that handles are allocated more often - * than they're freed. Leave the space reserved for file - * descriptors - */ - - if (last < _wapi_fd_reserve) { - last = _wapi_fd_reserve; - } else { - retry = TRUE; - } - -again: - count = last; - for(i = SLOT_INDEX (count); i < _wapi_private_handle_slot_count; i++) { - if (_wapi_private_handles [i]) { - for (k = SLOT_OFFSET (count); k < _WAPI_HANDLE_INITIAL_COUNT; k++) { - struct _WapiHandleUnshared *handle = &_wapi_private_handles [i][k]; - - if(handle->type == WAPI_HANDLE_UNUSED) { - last = count + 1; - - _wapi_handle_init (handle, type, handle_specific); - return (count); - } - count++; - } - } - } - - if(retry && last > _wapi_fd_reserve) { - /* Try again from the beginning */ - last = _wapi_fd_reserve; - goto again; - } - - /* Will need to expand the array. The caller will sort it out */ - - return(0); -} - -gpointer -_wapi_handle_new (WapiHandleType type, gpointer handle_specific) -{ - guint32 handle_idx = 0; - gpointer handle; - int thr_ret; - - g_assert (_wapi_has_shut_down == FALSE); - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Creating new handle of type %s", __func__, - _wapi_handle_typename[type]); - - g_assert(!_WAPI_FD_HANDLE(type)); - - thr_ret = mono_os_mutex_lock (&scan_mutex); - g_assert (thr_ret == 0); - - while ((handle_idx = _wapi_handle_new_internal (type, handle_specific)) == 0) { - /* Try and expand the array, and have another go */ - int idx = SLOT_INDEX (_wapi_private_handle_count); - if (idx >= _WAPI_PRIVATE_MAX_SLOTS) { - break; - } - - _wapi_private_handles [idx] = g_new0 (struct _WapiHandleUnshared, - _WAPI_HANDLE_INITIAL_COUNT); - - _wapi_private_handle_count += _WAPI_HANDLE_INITIAL_COUNT; - _wapi_private_handle_slot_count ++; - } - - thr_ret = mono_os_mutex_unlock (&scan_mutex); - g_assert (thr_ret == 0); - - if (handle_idx == 0) { - /* We ran out of slots */ - handle = _WAPI_HANDLE_INVALID; - goto done; - } - - /* Make sure we left the space for fd mappings */ - g_assert (handle_idx >= _wapi_fd_reserve); - - handle = GUINT_TO_POINTER (handle_idx); - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Allocated new handle %p", __func__, handle); - - if (_WAPI_SHARED_HANDLE(type)) { - /* Add the shared section too */ - guint32 ref; - - ref = _wapi_handle_new_shared (type, handle_specific); - if (ref == 0) { - ref = _wapi_handle_new_shared (type, handle_specific); - if (ref == 0) { - /* FIXME: grow the arrays */ - handle = _WAPI_HANDLE_INVALID; - goto done; - } - } - - _WAPI_PRIVATE_HANDLES(handle_idx).u.shared.offset = ref; - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: New shared handle at offset 0x%x", __func__, - ref); - } - -done: - return(handle); -} - -gpointer _wapi_handle_new_from_offset (WapiHandleType type, guint32 offset, - gboolean timestamp) -{ - guint32 handle_idx = 0; - gpointer handle = INVALID_HANDLE_VALUE; - int thr_ret, i, k; - struct _WapiHandleShared *shared; - - g_assert (_wapi_has_shut_down == FALSE); - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Creating new handle of type %s to offset %d", __func__, - _wapi_handle_typename[type], offset); - - g_assert(!_WAPI_FD_HANDLE(type)); - g_assert(_WAPI_SHARED_HANDLE(type)); - g_assert(offset != 0); - - shared = &_wapi_shared_layout->handles[offset]; - if (timestamp) { - guint32 now = (guint32)(time (NULL) & 0xFFFFFFFF); - /* Bump up the timestamp for this offset */ - InterlockedExchange ((gint32 *)&shared->timestamp, now); - } - - thr_ret = mono_os_mutex_lock (&scan_mutex); - g_assert (thr_ret == 0); - - for (i = SLOT_INDEX (0); i < _wapi_private_handle_slot_count; i++) { - if (_wapi_private_handles [i]) { - for (k = SLOT_OFFSET (0); k < _WAPI_HANDLE_INITIAL_COUNT; k++) { - struct _WapiHandleUnshared *handle_data = &_wapi_private_handles [i][k]; - - if (handle_data->type == type && - handle_data->u.shared.offset == offset) { - handle = GUINT_TO_POINTER (i * _WAPI_HANDLE_INITIAL_COUNT + k); - goto first_pass_done; - } - } - } - } - -first_pass_done: - thr_ret = mono_os_mutex_unlock (&scan_mutex); - g_assert (thr_ret == 0); - - if (handle != INVALID_HANDLE_VALUE) { - _wapi_handle_ref (handle); - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Returning old handle %p referencing 0x%x", - __func__, handle, offset); - return (handle); - } - - /* Prevent entries expiring under us as we search */ - thr_ret = _wapi_handle_lock_shared_handles (); - g_assert (thr_ret == 0); - - if (shared->type == WAPI_HANDLE_UNUSED) { - /* Someone deleted this handle while we were working */ - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Handle at 0x%x unused", __func__, offset); - goto done; - } - - if (shared->type != type) { - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Wrong type at %d 0x%x! Found %s wanted %s", - __func__, offset, offset, - _wapi_handle_typename[shared->type], - _wapi_handle_typename[type]); - goto done; - } - - thr_ret = mono_os_mutex_lock (&scan_mutex); - g_assert (thr_ret == 0); - - while ((handle_idx = _wapi_handle_new_internal (type, NULL)) == 0) { - /* Try and expand the array, and have another go */ - int idx = SLOT_INDEX (_wapi_private_handle_count); - _wapi_private_handles [idx] = g_new0 (struct _WapiHandleUnshared, - _WAPI_HANDLE_INITIAL_COUNT); - - _wapi_private_handle_count += _WAPI_HANDLE_INITIAL_COUNT; - _wapi_private_handle_slot_count ++; - } - - thr_ret = mono_os_mutex_unlock (&scan_mutex); - g_assert (thr_ret == 0); - - /* Make sure we left the space for fd mappings */ - g_assert (handle_idx >= _wapi_fd_reserve); - - handle = GUINT_TO_POINTER (handle_idx); - - _WAPI_PRIVATE_HANDLES(handle_idx).u.shared.offset = offset; - InterlockedIncrement ((gint32 *)&shared->handle_refs); - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Allocated new handle %p referencing 0x%x (shared refs %d)", __func__, handle, offset, shared->handle_refs); - -done: - _wapi_handle_unlock_shared_handles (); - - return(handle); -} - -static void -init_handles_slot (int idx) -{ - int thr_ret; - - thr_ret = mono_os_mutex_lock (&scan_mutex); - g_assert (thr_ret == 0); - - if (_wapi_private_handles [idx] == NULL) { - _wapi_private_handles [idx] = g_new0 (struct _WapiHandleUnshared, - _WAPI_HANDLE_INITIAL_COUNT); - g_assert (_wapi_private_handles [idx]); - } - - thr_ret = mono_os_mutex_unlock (&scan_mutex); - g_assert (thr_ret == 0); -} - -gpointer _wapi_handle_new_fd (WapiHandleType type, int fd, - gpointer handle_specific) -{ - struct _WapiHandleUnshared *handle; - int thr_ret; - - g_assert (_wapi_has_shut_down == FALSE); - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Creating new handle of type %s", __func__, - _wapi_handle_typename[type]); - - g_assert(_WAPI_FD_HANDLE(type)); - g_assert(!_WAPI_SHARED_HANDLE(type)); - - if (fd >= _wapi_fd_reserve) { - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d is too big", __func__, fd); - - return(GUINT_TO_POINTER (_WAPI_HANDLE_INVALID)); - } - - /* Initialize the array entries on demand */ - if (_wapi_private_handles [SLOT_INDEX (fd)] == NULL) - init_handles_slot (SLOT_INDEX (fd)); - - handle = &_WAPI_PRIVATE_HANDLES(fd); - - if (handle->type != WAPI_HANDLE_UNUSED) { - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d is already in use!", __func__, fd); - /* FIXME: clean up this handle? We can't do anything - * with the fd, cos thats the new one - */ - } - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Assigning new fd handle %d", __func__, fd); - - /* Prevent file share entries racing with us, when the file - * handle is only half initialised - */ - thr_ret = _wapi_shm_sem_lock (_WAPI_SHARED_SEM_FILESHARE); - g_assert(thr_ret == 0); - - _wapi_handle_init (handle, type, handle_specific); - - thr_ret = _wapi_shm_sem_unlock (_WAPI_SHARED_SEM_FILESHARE); - - return(GUINT_TO_POINTER(fd)); -} - -gboolean _wapi_lookup_handle (gpointer handle, WapiHandleType type, - gpointer *handle_specific) -{ - struct _WapiHandleUnshared *handle_data; - guint32 handle_idx = GPOINTER_TO_UINT(handle); - - if (!_WAPI_PRIVATE_VALID_SLOT (handle_idx)) { - return(FALSE); - } - - /* Initialize the array entries on demand */ - if (_wapi_private_handles [SLOT_INDEX (handle_idx)] == NULL) - init_handles_slot (SLOT_INDEX (handle_idx)); - - handle_data = &_WAPI_PRIVATE_HANDLES(handle_idx); - - if (handle_data->type != type) { - return(FALSE); - } - - if (handle_specific == NULL) { - return(FALSE); - } - - if (_WAPI_SHARED_HANDLE(type)) { - struct _WapiHandle_shared_ref *ref; - struct _WapiHandleShared *shared_handle_data; - - ref = &handle_data->u.shared; - shared_handle_data = &_wapi_shared_layout->handles[ref->offset]; - - if (shared_handle_data->type != type) { - /* The handle must have been deleted on us - */ - return (FALSE); - } - - *handle_specific = &shared_handle_data->u; - } else { - *handle_specific = &handle_data->u; - } - - return(TRUE); -} - -void -_wapi_handle_foreach (WapiHandleType type, - gboolean (*on_each)(gpointer test, gpointer user), - gpointer user_data) -{ - struct _WapiHandleUnshared *handle_data = NULL; - gpointer ret = NULL; - guint32 i, k; - int thr_ret; - - thr_ret = mono_os_mutex_lock (&scan_mutex); - g_assert (thr_ret == 0); - - for (i = SLOT_INDEX (0); i < _wapi_private_handle_slot_count; i++) { - if (_wapi_private_handles [i]) { - for (k = SLOT_OFFSET (0); k < _WAPI_HANDLE_INITIAL_COUNT; k++) { - handle_data = &_wapi_private_handles [i][k]; - - if (handle_data->type == type) { - ret = GUINT_TO_POINTER (i * _WAPI_HANDLE_INITIAL_COUNT + k); - if (on_each (ret, user_data) == TRUE) - break; - } - } - } - } - - thr_ret = mono_os_mutex_unlock (&scan_mutex); - g_assert (thr_ret == 0); -} - -/* This might list some shared handles twice if they are already - * opened by this process, and the check function returns FALSE the - * first time. Shared handles that are created during the search are - * unreffed if the check function returns FALSE, so callers must not - * rely on the handle persisting (unless the check function returns - * TRUE) - * The caller owns the returned handle. - */ -gpointer _wapi_search_handle (WapiHandleType type, - gboolean (*check)(gpointer test, gpointer user), - gpointer user_data, - gpointer *handle_specific, - gboolean search_shared) -{ - struct _WapiHandleUnshared *handle_data = NULL; - struct _WapiHandleShared *shared = NULL; - gpointer ret = NULL; - guint32 i, k; - gboolean found = FALSE; - int thr_ret; - - thr_ret = mono_os_mutex_lock (&scan_mutex); - g_assert (thr_ret == 0); - - for (i = SLOT_INDEX (0); !found && i < _wapi_private_handle_slot_count; i++) { - if (_wapi_private_handles [i]) { - for (k = SLOT_OFFSET (0); k < _WAPI_HANDLE_INITIAL_COUNT; k++) { - handle_data = &_wapi_private_handles [i][k]; - - if (handle_data->type == type) { - ret = GUINT_TO_POINTER (i * _WAPI_HANDLE_INITIAL_COUNT + k); - if (check (ret, user_data) == TRUE) { - _wapi_handle_ref (ret); - found = TRUE; - - if (_WAPI_SHARED_HANDLE (type)) { - shared = &_wapi_shared_layout->handles[i]; - } - - break; - } - } - } - } - } - - thr_ret = mono_os_mutex_unlock (&scan_mutex); - g_assert (thr_ret == 0); - - if (!found && search_shared && _WAPI_SHARED_HANDLE (type)) { - /* Not found yet, so search the shared memory too */ - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Looking at other shared handles...", __func__); - - for (i = 0; i < _WAPI_HANDLE_INITIAL_COUNT; i++) { - shared = &_wapi_shared_layout->handles[i]; - - if (shared->type == type) { - /* Tell new_from_offset to not - * timestamp this handle, because - * otherwise it will ping every handle - * in the list and they will never - * expire - */ - ret = _wapi_handle_new_from_offset (type, i, - FALSE); - if (ret == INVALID_HANDLE_VALUE) { - /* This handle was deleted - * while we were looking at it - */ - continue; - } - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Opened tmp handle %p (type %s) from offset %d", __func__, ret, _wapi_handle_typename[type], i); - - /* It's possible that the shared part - * of this handle has now been blown - * away (after new_from_offset - * successfully opened it,) if its - * timestamp is too old. The check - * function needs to be aware of this, - * and cope if the handle has - * vanished. - */ - if (check (ret, user_data) == TRUE) { - /* Timestamp this handle, but make - * sure it still exists first - */ - thr_ret = _wapi_handle_lock_shared_handles (); - g_assert (thr_ret == 0); - - if (shared->type == type) { - guint32 now = (guint32)(time (NULL) & 0xFFFFFFFF); - InterlockedExchange ((gint32 *)&shared->timestamp, now); - - found = TRUE; - handle_data = &_WAPI_PRIVATE_HANDLES(GPOINTER_TO_UINT(ret)); - - _wapi_handle_unlock_shared_handles (); - break; - } else { - /* It's been deleted, - * so just keep - * looking - */ - _wapi_handle_unlock_shared_handles (); - } - } - - /* This isn't the handle we're looking - * for, so drop the reference we took - * in _wapi_handle_new_from_offset () - */ - _wapi_handle_unref (ret); - } - } - } - - if (!found) { - ret = NULL; - goto done; - } - - if(handle_specific != NULL) { - if (_WAPI_SHARED_HANDLE(type)) { - g_assert(shared->type == type); - - *handle_specific = &shared->u; - } else { - *handle_specific = &handle_data->u; - } - } - -done: - return(ret); -} - -/* Returns the offset of the metadata array, or -1 on error, or 0 for - * not found (0 is not a valid offset) - */ -gint32 _wapi_search_handle_namespace (WapiHandleType type, - gchar *utf8_name) -{ - struct _WapiHandleShared *shared_handle_data; - guint32 i; - gint32 ret = 0; - int thr_ret; - - g_assert(_WAPI_SHARED_HANDLE(type)); - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Lookup for handle named [%s] type %s", __func__, - utf8_name, _wapi_handle_typename[type]); - - thr_ret = _wapi_handle_lock_shared_handles (); - g_assert (thr_ret == 0); - - for(i = 1; i < _WAPI_HANDLE_INITIAL_COUNT; i++) { - WapiSharedNamespace *sharedns; - - shared_handle_data = &_wapi_shared_layout->handles[i]; - - /* Check mutex, event, semaphore, timer, job and - * file-mapping object names. So far only mutex, - * semaphore and event are implemented. - */ - if (!_WAPI_SHARED_NAMESPACE (shared_handle_data->type)) { - continue; - } - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: found a shared namespace handle at 0x%x (type %s)", __func__, i, _wapi_handle_typename[shared_handle_data->type]); - - sharedns=(WapiSharedNamespace *)&shared_handle_data->u; - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: name is [%s]", __func__, sharedns->name); - - if (strcmp (sharedns->name, utf8_name) == 0) { - if (shared_handle_data->type != type) { - /* Its the wrong type, so fail now */ - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle 0x%x matches name but is wrong type: %s", __func__, i, _wapi_handle_typename[shared_handle_data->type]); - ret = -1; - goto done; - } else { - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle 0x%x matches name and type", __func__, i); - ret = i; - goto done; - } - } - } - -done: - _wapi_handle_unlock_shared_handles (); - - return(ret); -} - -void _wapi_handle_ref (gpointer handle) -{ - guint32 idx = GPOINTER_TO_UINT(handle); - struct _WapiHandleUnshared *handle_data; - - if (!_WAPI_PRIVATE_VALID_SLOT (idx)) { - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Attempting to ref invalid private handle %p", __func__, handle); - return; - } - - if (_wapi_handle_type (handle) == WAPI_HANDLE_UNUSED) { - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Attempting to ref unused handle %p", __func__, handle); - return; - } - - handle_data = &_WAPI_PRIVATE_HANDLES(idx); - - InterlockedIncrement ((gint32 *)&handle_data->ref); - - /* It's possible for processes to exit before getting around - * to updating timestamps in the collection thread, so if a - * shared handle is reffed do the timestamp here as well just - * to make sure. - */ - if (_WAPI_SHARED_HANDLE(handle_data->type)) { - struct _WapiHandleShared *shared_data = &_wapi_shared_layout->handles[handle_data->u.shared.offset]; - guint32 now = (guint32)(time (NULL) & 0xFFFFFFFF); - InterlockedExchange ((gint32 *)&shared_data->timestamp, now); - } - -#ifdef DEBUG_REFS - g_message ("%s: %s handle %p ref now %d", __func__, - _wapi_handle_typename[_WAPI_PRIVATE_HANDLES (idx).type], - handle, - _WAPI_PRIVATE_HANDLES(idx).ref); -#endif -} - -/* The handle must not be locked on entry to this function */ -static void _wapi_handle_unref_full (gpointer handle, gboolean ignore_private_busy_handles) -{ - guint32 idx = GPOINTER_TO_UINT(handle); - gboolean destroy = FALSE, early_exit = FALSE; - int thr_ret; - - if (!_WAPI_PRIVATE_VALID_SLOT (idx)) { - return; - } - - if (_wapi_handle_type (handle) == WAPI_HANDLE_UNUSED) { - g_warning ("%s: Attempting to unref unused handle %p", - __func__, handle); - return; - } - - /* Possible race condition here if another thread refs the - * handle between here and setting the type to UNUSED. I - * could lock a mutex, but I'm not sure that allowing a handle - * reference to reach 0 isn't an application bug anyway. - */ - destroy = (InterlockedDecrement ((gint32 *)&_WAPI_PRIVATE_HANDLES(idx).ref) ==0); - -#ifdef DEBUG_REFS - g_message ("%s: %s handle %p ref now %d (destroy %s)", __func__, - _wapi_handle_typename[_WAPI_PRIVATE_HANDLES (idx).type], - handle, - _WAPI_PRIVATE_HANDLES(idx).ref, destroy?"TRUE":"FALSE"); -#endif - - if(destroy==TRUE) { - /* Need to copy the handle info, reset the slot in the - * array, and _only then_ call the close function to - * avoid race conditions (eg file descriptors being - * closed, and another file being opened getting the - * same fd racing the memset()) - */ - struct _WapiHandleUnshared handle_data; - struct _WapiHandleShared shared_handle_data; - WapiHandleType type = _WAPI_PRIVATE_HANDLES(idx).type; - void (*close_func)(gpointer, gpointer) = _wapi_handle_ops_get_close_func (type); - gboolean is_shared = _WAPI_SHARED_HANDLE(type); - - if (is_shared) { - /* If this is a shared handle we need to take - * the shared lock outside of the scan_mutex - * lock to avoid deadlocks - */ - thr_ret = _wapi_handle_lock_shared_handles (); - g_assert (thr_ret == 0); - } - - thr_ret = mono_os_mutex_lock (&scan_mutex); - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Destroying handle %p", __func__, handle); - - memcpy (&handle_data, &_WAPI_PRIVATE_HANDLES(idx), - sizeof (struct _WapiHandleUnshared)); - - memset (&_WAPI_PRIVATE_HANDLES(idx).u, '\0', - sizeof(_WAPI_PRIVATE_HANDLES(idx).u)); - - _WAPI_PRIVATE_HANDLES(idx).type = WAPI_HANDLE_UNUSED; - - if (!is_shared) { - /* Destroy the mutex and cond var. We hope nobody - * tried to grab them between the handle unlock and - * now, but pthreads doesn't have a - * "unlock_and_destroy" atomic function. - */ - thr_ret = mono_os_mutex_destroy (&_WAPI_PRIVATE_HANDLES(idx).signal_mutex); - /*WARNING gross hack to make cleanup not crash when exiting without the whole runtime teardown.*/ - if (thr_ret == EBUSY && ignore_private_busy_handles) { - early_exit = TRUE; - } else { - if (thr_ret != 0) - g_error ("Error destroying handle %p mutex due to %d\n", handle, thr_ret); - - thr_ret = pthread_cond_destroy (&_WAPI_PRIVATE_HANDLES(idx).signal_cond); - if (thr_ret == EBUSY && ignore_private_busy_handles) - early_exit = TRUE; - else if (thr_ret != 0) - g_error ("Error destroying handle %p cond var due to %d\n", handle, thr_ret); - } - } else { - struct _WapiHandleShared *shared = &_wapi_shared_layout->handles[handle_data.u.shared.offset]; - - memcpy (&shared_handle_data, shared, - sizeof (struct _WapiHandleShared)); - - /* It's possible that this handle is already - * pointing at a deleted shared section - */ -#ifdef DEBUG_REFS - g_message ("%s: %s handle %p shared refs before dec %d", __func__, _wapi_handle_typename[type], handle, shared->handle_refs); -#endif - - if (shared->handle_refs > 0) { - shared->handle_refs--; - if (shared->handle_refs == 0) { - memset (shared, '\0', sizeof (struct _WapiHandleShared)); - } - } - } - - thr_ret = mono_os_mutex_unlock (&scan_mutex); - g_assert (thr_ret == 0); - - if (early_exit) - return; - if (is_shared) { - _wapi_handle_unlock_shared_handles (); - } - - if (close_func != NULL) { - if (is_shared) { - close_func (handle, &shared_handle_data.u); - } else { - close_func (handle, &handle_data.u); - } - } - } -} - -void _wapi_handle_unref (gpointer handle) -{ - _wapi_handle_unref_full (handle, FALSE); -} - -void _wapi_handle_register_capabilities (WapiHandleType type, - WapiHandleCapability caps) -{ - handle_caps[type] = caps; -} - -gboolean _wapi_handle_test_capabilities (gpointer handle, - WapiHandleCapability caps) -{ - guint32 idx = GPOINTER_TO_UINT(handle); - WapiHandleType type; - - if (!_WAPI_PRIVATE_VALID_SLOT (idx)) { - return(FALSE); - } - - type = _WAPI_PRIVATE_HANDLES(idx).type; - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: testing 0x%x against 0x%x (%d)", __func__, - handle_caps[type], caps, handle_caps[type] & caps); - - return((handle_caps[type] & caps) != 0); -} - -static void (*_wapi_handle_ops_get_close_func (WapiHandleType type))(gpointer, gpointer) -{ - if (handle_ops[type] != NULL && - handle_ops[type]->close != NULL) { - return (handle_ops[type]->close); - } - - return (NULL); -} - -void _wapi_handle_ops_close (gpointer handle, gpointer data) -{ - guint32 idx = GPOINTER_TO_UINT(handle); - WapiHandleType type; - - if (!_WAPI_PRIVATE_VALID_SLOT (idx)) { - return; - } - - type = _WAPI_PRIVATE_HANDLES(idx).type; - - if (handle_ops[type] != NULL && - handle_ops[type]->close != NULL) { - handle_ops[type]->close (handle, data); - } -} - -void _wapi_handle_ops_signal (gpointer handle) -{ - guint32 idx = GPOINTER_TO_UINT(handle); - WapiHandleType type; - - if (!_WAPI_PRIVATE_VALID_SLOT (idx)) { - return; - } - - type = _WAPI_PRIVATE_HANDLES(idx).type; - - if (handle_ops[type] != NULL && handle_ops[type]->signal != NULL) { - handle_ops[type]->signal (handle); - } -} - -gboolean _wapi_handle_ops_own (gpointer handle) -{ - guint32 idx = GPOINTER_TO_UINT(handle); - WapiHandleType type; - - if (!_WAPI_PRIVATE_VALID_SLOT (idx)) { - return(FALSE); - } - - type = _WAPI_PRIVATE_HANDLES(idx).type; - - if (handle_ops[type] != NULL && handle_ops[type]->own_handle != NULL) { - return(handle_ops[type]->own_handle (handle)); - } else { - return(FALSE); - } -} - -gboolean _wapi_handle_ops_isowned (gpointer handle) -{ - guint32 idx = GPOINTER_TO_UINT(handle); - WapiHandleType type; - - if (!_WAPI_PRIVATE_VALID_SLOT (idx)) { - return(FALSE); - } - - type = _WAPI_PRIVATE_HANDLES(idx).type; - - if (handle_ops[type] != NULL && handle_ops[type]->is_owned != NULL) { - return(handle_ops[type]->is_owned (handle)); - } else { - return(FALSE); - } -} - -guint32 _wapi_handle_ops_special_wait (gpointer handle, guint32 timeout, gboolean alertable) -{ - guint32 idx = GPOINTER_TO_UINT(handle); - WapiHandleType type; - - if (!_WAPI_PRIVATE_VALID_SLOT (idx)) { - return(WAIT_FAILED); - } - - type = _WAPI_PRIVATE_HANDLES(idx).type; - - if (handle_ops[type] != NULL && - handle_ops[type]->special_wait != NULL) { - return(handle_ops[type]->special_wait (handle, timeout, alertable)); - } else { - return(WAIT_FAILED); - } -} - -void _wapi_handle_ops_prewait (gpointer handle) -{ - guint32 idx = GPOINTER_TO_UINT (handle); - WapiHandleType type; - - if (!_WAPI_PRIVATE_VALID_SLOT (idx)) { - return; - } - - type = _WAPI_PRIVATE_HANDLES (idx).type; - - if (handle_ops[type] != NULL && - handle_ops[type]->prewait != NULL) { - handle_ops[type]->prewait (handle); - } -} - - -/** - * CloseHandle: - * @handle: The handle to release - * - * Closes and invalidates @handle, releasing any resources it - * consumes. When the last handle to a temporary or non-persistent - * object is closed, that object can be deleted. Closing the same - * handle twice is an error. - * - * Return value: %TRUE on success, %FALSE otherwise. - */ -gboolean CloseHandle(gpointer handle) -{ - if (handle == NULL) { - /* Problem: because we map file descriptors to the - * same-numbered handle we can't tell the difference - * between a bogus handle and the handle to stdin. - * Assume that it's the console handle if that handle - * exists... - */ - if (_WAPI_PRIVATE_HANDLES (0).type != WAPI_HANDLE_CONSOLE) { - SetLastError (ERROR_INVALID_PARAMETER); - return(FALSE); - } - } - if (handle == _WAPI_HANDLE_INVALID){ - SetLastError (ERROR_INVALID_PARAMETER); - return(FALSE); - } - - _wapi_handle_unref (handle); - - return(TRUE); -} - -/* Lots more to implement here, but this is all we need at the moment */ -gboolean DuplicateHandle (gpointer srcprocess, gpointer src, - gpointer targetprocess, gpointer *target, - guint32 access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED, guint32 options G_GNUC_UNUSED) -{ - if (srcprocess != _WAPI_PROCESS_CURRENT || - targetprocess != _WAPI_PROCESS_CURRENT) { - /* Duplicating other process's handles is not supported */ - SetLastError (ERROR_INVALID_HANDLE); - return(FALSE); - } - - if (src == _WAPI_PROCESS_CURRENT) { - *target = _wapi_process_duplicate (); - } else if (src == _WAPI_THREAD_CURRENT) { - g_assert_not_reached (); - } else { - _wapi_handle_ref (src); - *target = src; - } - - return(TRUE); -} - -gboolean _wapi_handle_count_signalled_handles (guint32 numhandles, - gpointer *handles, - gboolean waitall, - guint32 *retcount, - guint32 *lowest) -{ - guint32 count, i, iter=0; - gboolean ret; - int thr_ret; - WapiHandleType type; - - /* Lock all the handles, with backoff */ -again: - thr_ret = _wapi_handle_lock_shared_handles (); - g_assert (thr_ret == 0); - - for(i=0; ii) { - *lowest=i; - } - } - } - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: %d event handles signalled", __func__, count); - - if ((waitall == TRUE && count == numhandles) || - (waitall == FALSE && count > 0)) { - ret=TRUE; - } else { - ret=FALSE; - } - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Returning %d", __func__, ret); - - *retcount=count; - - return(ret); -} - -void _wapi_handle_unlock_handles (guint32 numhandles, gpointer *handles) -{ - guint32 i; - int thr_ret; - - thr_ret = _wapi_handle_unlock_shared_handles (); - g_assert (thr_ret == 0); - - for(i=0; idevice == s2->device && s1->inode == s2->inode) ? 1 : 0; -} - -static guint -wapi_share_info_hash (gconstpointer data) -{ - const _WapiFileShare *s = (const _WapiFileShare *)data; - - return s->inode; -} - -gboolean _wapi_handle_get_or_set_share (guint64 device, guint64 inode, - guint32 new_sharemode, - guint32 new_access, - guint32 *old_sharemode, - guint32 *old_access, - struct _WapiFileShare **share_info) -{ - struct _WapiFileShare *file_share; - int thr_ret; - gboolean exists = FALSE; - - /* Prevents entries from expiring under us as we search - */ - thr_ret = _wapi_handle_lock_shared_handles (); - g_assert (thr_ret == 0); - - /* Prevent new entries racing with us */ - thr_ret = _wapi_shm_sem_lock (_WAPI_SHARED_SEM_FILESHARE); - g_assert (thr_ret == 0); - - _WapiFileShare tmp; - - /* - * Instead of allocating a 4MB array, we use a hash table to keep track of this - * info. This is needed even if SHM is disabled, to track sharing inside - * the current process. - */ - if (!file_share_hash) { - file_share_hash = g_hash_table_new_full (wapi_share_info_hash, wapi_share_info_equal, NULL, g_free); - mono_os_mutex_init_recursive (&file_share_hash_mutex); - } - - tmp.device = device; - tmp.inode = inode; - - file_share_hash_lock (); - - file_share = (_WapiFileShare *)g_hash_table_lookup (file_share_hash, &tmp); - if (file_share) { - *old_sharemode = file_share->sharemode; - *old_access = file_share->access; - *share_info = file_share; - - InterlockedIncrement ((gint32 *)&file_share->handle_refs); - exists = TRUE; - } else { - file_share = g_new0 (_WapiFileShare, 1); - - file_share->device = device; - file_share->inode = inode; - file_share->opened_by_pid = _wapi_getpid (); - file_share->sharemode = new_sharemode; - file_share->access = new_access; - file_share->handle_refs = 1; - *share_info = file_share; - - g_hash_table_insert (file_share_hash, file_share, file_share); - } - - file_share_hash_unlock (); - - thr_ret = _wapi_shm_sem_unlock (_WAPI_SHARED_SEM_FILESHARE); - - _wapi_handle_unlock_shared_handles (); - - return(exists); -} - -/* If we don't have the info in /proc, check if the process that - * opened this share info is still there (it's not a perfect method, - * due to pid reuse) - */ -static void _wapi_handle_check_share_by_pid (struct _WapiFileShare *share_info) -{ -#if defined(__native_client__) - g_assert_not_reached (); -#elif defined(HAVE_KILL) - if (kill (share_info->opened_by_pid, 0) == -1 && - (errno == ESRCH || - errno == EPERM)) { - /* It's gone completely (or there's a new process - * owned by someone else) so mark this share info as - * dead - */ - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Didn't find it, destroying entry", __func__); - - _wapi_free_share_info (share_info); - } -#endif -} - -#ifdef __linux__ -/* Scan /proc//fd/ for open file descriptors to the file in - * question. If there are none, reset the share info. - * - * This implementation is Linux-specific; legacy systems will have to - * implement their own ways of finding out if a particular file is - * open by a process. - */ -void _wapi_handle_check_share (struct _WapiFileShare *share_info, int fd) -{ - gboolean found = FALSE, proc_fds = FALSE; - int thr_ret, i; - - /* Prevents entries from expiring under us if we remove this - * one - */ - thr_ret = _wapi_handle_lock_shared_handles (); - g_assert (thr_ret == 0); - - /* Prevent new entries racing with us */ - thr_ret = _wapi_shm_sem_lock (_WAPI_SHARED_SEM_FILESHARE); - g_assert (thr_ret == 0); - - /* If there is no /proc, there's nothing more we can do here */ - if (access ("/proc", F_OK) == -1) { - _wapi_handle_check_share_by_pid (share_info); - goto done; - } - - /* If there's another handle that thinks it owns this fd, then even - * if the fd has been closed behind our back consider it still owned. - * See bugs 75764 and 75891 - */ - for (i = 0; i < _wapi_fd_reserve; i++) { - if (_wapi_private_handles [SLOT_INDEX (i)]) { - struct _WapiHandleUnshared *handle = &_WAPI_PRIVATE_HANDLES(i); - - if (i != fd && - handle->type == WAPI_HANDLE_FILE) { - struct _WapiHandle_file *file_handle = &handle->u.file; - - if (file_handle->share_info == share_info) { - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle 0x%x has this file open!", - __func__, i); - - goto done; - } - } - } - } - - if (proc_fds == FALSE) { - _wapi_handle_check_share_by_pid (share_info); - } else if (found == FALSE) { - /* Blank out this entry, as it is stale */ - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Didn't find it, destroying entry", __func__); - - _wapi_free_share_info (share_info); - } - -done: - thr_ret = _wapi_shm_sem_unlock (_WAPI_SHARED_SEM_FILESHARE); - - _wapi_handle_unlock_shared_handles (); -} -#else -// -// Other implementations (non-Linux) -// -void _wapi_handle_check_share (struct _WapiFileShare *share_info, int fd) -{ - int thr_ret; - - /* Prevents entries from expiring under us if we remove this - * one */ - thr_ret = _wapi_handle_lock_shared_handles (); - g_assert (thr_ret == 0); - - /* Prevent new entries racing with us */ - thr_ret = _wapi_shm_sem_lock (_WAPI_SHARED_SEM_FILESHARE); - g_assert (thr_ret == 0); - - _wapi_handle_check_share_by_pid (share_info); - - thr_ret = _wapi_shm_sem_unlock (_WAPI_SHARED_SEM_FILESHARE); - _wapi_handle_unlock_shared_handles (); -} -#endif - -void _wapi_handle_dump (void) -{ - struct _WapiHandleUnshared *handle_data; - guint32 i, k; - int thr_ret; - - thr_ret = mono_os_mutex_lock (&scan_mutex); - g_assert (thr_ret == 0); - - for(i = SLOT_INDEX (0); i < _wapi_private_handle_slot_count; i++) { - if (_wapi_private_handles [i]) { - for (k = SLOT_OFFSET (0); k < _WAPI_HANDLE_INITIAL_COUNT; k++) { - handle_data = &_wapi_private_handles [i][k]; - - if (handle_data->type == WAPI_HANDLE_UNUSED) { - continue; - } - - g_print ("%3x [%7s] %s %d ", - i * _WAPI_HANDLE_INITIAL_COUNT + k, - _wapi_handle_typename[handle_data->type], - handle_data->signalled?"Sg":"Un", - handle_data->ref); - if (handle_details[handle_data->type]) - handle_details[handle_data->type](&handle_data->u); - g_print ("\n"); - } - } - } - - thr_ret = mono_os_mutex_unlock (&scan_mutex); - g_assert (thr_ret == 0); -} - -static void _wapi_shared_details (gpointer handle_info) -{ - struct _WapiHandle_shared_ref *shared = (struct _WapiHandle_shared_ref *)handle_info; - - g_print ("offset: 0x%x", shared->offset); -} diff --git a/mono/io-layer/handles.h b/mono/io-layer/handles.h deleted file mode 100644 index 31cab7bdb9..0000000000 --- a/mono/io-layer/handles.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * handles.h: Generic operations on handles - * - * Author: - * Dick Porter (dick@ximian.com) - * - * (C) 2002 Ximian, Inc. - */ - -#ifndef _WAPI_HANDLES_H_ -#define _WAPI_HANDLES_H_ - -#define INVALID_HANDLE_VALUE (gpointer)-1 - -G_BEGIN_DECLS - -extern gboolean CloseHandle (gpointer handle); -extern gboolean DuplicateHandle (gpointer srcprocess, gpointer src, gpointer targetprocess, gpointer *target, guint32 access, gboolean inherit, guint32 options); - -extern void wapi_init (void); -extern void wapi_cleanup (void); - -int wapi_getdtablesize (void); - -G_END_DECLS - -#endif /* _WAPI_HANDLES_H_ */ diff --git a/mono/io-layer/io-private.h b/mono/io-layer/io-private.h index 9af4b1f0a1..392b081ca7 100644 --- a/mono/io-layer/io-private.h +++ b/mono/io-layer/io-private.h @@ -21,16 +21,8 @@ #include #include -extern struct _WapiHandleOps _wapi_file_ops; -extern struct _WapiHandleOps _wapi_console_ops; -extern struct _WapiHandleOps _wapi_find_ops; -extern struct _WapiHandleOps _wapi_pipe_ops; - extern gboolean _wapi_lock_file_region (int fd, off_t offset, off_t length); extern gboolean _wapi_unlock_file_region (int fd, off_t offset, off_t length); -extern void _wapi_file_details (gpointer handle_info); -extern void _wapi_console_details (gpointer handle_info); -extern void _wapi_pipe_details (gpointer handle_info); extern gpointer _wapi_stdhandle_create (int fd, const gchar *name); /* Currently used for both FILE, CONSOLE and PIPE handle types. This may diff --git a/mono/io-layer/io-trace.h b/mono/io-layer/io-trace.h index f67ff65f84..e65fdc345a 100644 --- a/mono/io-layer/io-trace.h +++ b/mono/io-layer/io-trace.h @@ -13,6 +13,7 @@ #ifdef DISABLE_IO_LAYER_TRACE #define MONO_TRACE(...) #else +#include "mono/utils/mono-logger-internals.h" #define MONO_TRACE(...) mono_trace (__VA_ARGS__) #endif diff --git a/mono/io-layer/io.c.REMOVED.git-id b/mono/io-layer/io.c.REMOVED.git-id index 8db19e0a4b..8e264fae64 100644 --- a/mono/io-layer/io.c.REMOVED.git-id +++ b/mono/io-layer/io.c.REMOVED.git-id @@ -1 +1 @@ -5d10b370a9c8309a629414a236804a9d1a7962c6 \ No newline at end of file +baf297ae7450123d50878ba4869eaf1df5e66ea0 \ No newline at end of file diff --git a/mono/io-layer/io.h b/mono/io-layer/io.h index 4c5a492b95..5321bcd7c4 100644 --- a/mono/io-layer/io.h +++ b/mono/io-layer/io.h @@ -225,6 +225,7 @@ extern gboolean GetVolumeInformation (const gunichar2 *path, gunichar2 *volumena extern void _wapi_io_init (void); +extern void _wapi_io_cleanup (void); G_END_DECLS diff --git a/mono/io-layer/locking.c b/mono/io-layer/locking.c index c014a2d3dc..001df9bef7 100644 --- a/mono/io-layer/locking.c +++ b/mono/io-layer/locking.c @@ -15,10 +15,10 @@ #include #include #include -#include #include #include #include +#include gboolean _wapi_lock_file_region (int fd, off_t offset, off_t length) @@ -125,7 +125,7 @@ LockFile (gpointer handle, guint32 offset_low, guint32 offset_high, off_t offset, length; int fd = GPOINTER_TO_UINT(handle); - ok = _wapi_lookup_handle (handle, WAPI_HANDLE_FILE, + ok = mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE, (gpointer *)&file_handle); if (ok == FALSE) { g_warning ("%s: error looking up file handle %p", __func__, @@ -172,7 +172,7 @@ UnlockFile (gpointer handle, guint32 offset_low, off_t offset, length; int fd = GPOINTER_TO_UINT(handle); - ok = _wapi_lookup_handle (handle, WAPI_HANDLE_FILE, + ok = mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE, (gpointer *)&file_handle); if (ok == FALSE) { g_warning ("%s: error looking up file handle %p", __func__, diff --git a/mono/io-layer/mutex-private.h b/mono/io-layer/mutex-private.h index 4faa3b7202..50e5b14e06 100644 --- a/mono/io-layer/mutex-private.h +++ b/mono/io-layer/mutex-private.h @@ -15,26 +15,21 @@ #include #include -extern struct _WapiHandleOps _wapi_mutex_ops; -extern struct _WapiHandleOps _wapi_namedmutex_ops; - -extern void _wapi_mutex_details (gpointer handle_info); +#include "wapi-private.h" struct _WapiHandle_mutex { - pid_t pid; pthread_t tid; guint32 recursion; }; struct _WapiHandle_namedmutex { + struct _WapiHandle_mutex m; WapiSharedNamespace sharedns; - pid_t pid; - pthread_t tid; - guint32 recursion; }; -extern void _wapi_mutex_abandon (gpointer data, pid_t pid, pthread_t tid); +void +_wapi_mutex_init (void); #endif /* _WAPI_MUTEX_PRIVATE_H_ */ diff --git a/mono/io-layer/mutexes.c b/mono/io-layer/mutexes.c index 730363e630..dbfe8b1697 100644 --- a/mono/io-layer/mutexes.c +++ b/mono/io-layer/mutexes.c @@ -15,81 +15,119 @@ #include #include -#include #include #include #include #include +#include static void mutex_signal(gpointer handle); static gboolean mutex_own (gpointer handle); static gboolean mutex_is_owned (gpointer handle); +static void mutex_prewait (gpointer handle); +static void mutex_details (gpointer data); +static const gchar* mutex_typename (void); +static gsize mutex_typesize (void); static void namedmutex_signal (gpointer handle); static gboolean namedmutex_own (gpointer handle); static gboolean namedmutex_is_owned (gpointer handle); static void namedmutex_prewait (gpointer handle); +static void namedmutex_details (gpointer data); +static const gchar* namedmutex_typename (void); +static gsize namedmutex_typesize (void); -struct _WapiHandleOps _wapi_mutex_ops = { +static MonoW32HandleOps _wapi_mutex_ops = { NULL, /* close */ mutex_signal, /* signal */ mutex_own, /* own */ mutex_is_owned, /* is_owned */ NULL, /* special_wait */ - NULL /* prewait */ + mutex_prewait, /* prewait */ + mutex_details, /* details */ + mutex_typename, /* typename */ + mutex_typesize, /* typesize */ }; -void _wapi_mutex_details (gpointer handle_info) -{ - struct _WapiHandle_mutex *mut = (struct _WapiHandle_mutex *)handle_info; - -#ifdef PTHREAD_POINTER_ID - g_print ("own: %5d:%5p, count: %5u", mut->pid, mut->tid, - mut->recursion); -#else - g_print ("own: %5d:%5ld, count: %5u", mut->pid, mut->tid, - mut->recursion); -#endif -} - -struct _WapiHandleOps _wapi_namedmutex_ops = { +static MonoW32HandleOps _wapi_namedmutex_ops = { NULL, /* close */ namedmutex_signal, /* signal */ namedmutex_own, /* own */ namedmutex_is_owned, /* is_owned */ NULL, /* special_wait */ - namedmutex_prewait /* prewait */ + namedmutex_prewait, /* prewait */ + namedmutex_details, /* details */ + namedmutex_typename, /* typename */ + namedmutex_typesize, /* typesize */ }; -static gboolean mutex_release (gpointer handle); -static gboolean namedmutex_release (gpointer handle); - -static struct +void +_wapi_mutex_init (void) { - gboolean (*release)(gpointer handle); -} mutex_ops[WAPI_HANDLE_COUNT] = { - {NULL}, - {NULL}, - {NULL}, - {NULL}, - {NULL}, - {mutex_release}, - {NULL}, - {NULL}, - {NULL}, - {NULL}, - {NULL}, - {namedmutex_release}, -}; + mono_w32handle_register_ops (MONO_W32HANDLE_MUTEX, &_wapi_mutex_ops); + mono_w32handle_register_ops (MONO_W32HANDLE_NAMEDMUTEX, &_wapi_namedmutex_ops); -static mono_once_t mutex_ops_once=MONO_ONCE_INIT; + mono_w32handle_register_capabilities (MONO_W32HANDLE_MUTEX, + (MonoW32HandleCapability)(MONO_W32HANDLE_CAP_WAIT | MONO_W32HANDLE_CAP_SIGNAL | MONO_W32HANDLE_CAP_OWN)); + mono_w32handle_register_capabilities (MONO_W32HANDLE_NAMEDMUTEX, + (MonoW32HandleCapability)(MONO_W32HANDLE_CAP_WAIT | MONO_W32HANDLE_CAP_SIGNAL | MONO_W32HANDLE_CAP_OWN)); +} -static void mutex_ops_init (void) +static const char* mutex_handle_type_to_string (MonoW32HandleType type) { - _wapi_handle_register_capabilities (WAPI_HANDLE_MUTEX, - (WapiHandleCapability)(WAPI_HANDLE_CAP_WAIT | WAPI_HANDLE_CAP_SIGNAL | WAPI_HANDLE_CAP_OWN)); - _wapi_handle_register_capabilities (WAPI_HANDLE_NAMEDMUTEX, - (WapiHandleCapability)(WAPI_HANDLE_CAP_WAIT | WAPI_HANDLE_CAP_SIGNAL | WAPI_HANDLE_CAP_OWN)); + switch (type) { + case MONO_W32HANDLE_MUTEX: return "mutex"; + case MONO_W32HANDLE_NAMEDMUTEX: return "named mutex"; + default: + g_assert_not_reached (); + } +} + +static gboolean +mutex_handle_own (gpointer handle, MonoW32HandleType type) +{ + struct _WapiHandle_mutex *mutex_handle; + + if (!mono_w32handle_lookup (handle, type, (gpointer *)&mutex_handle)) { + g_warning ("%s: error looking up %s handle %p", __func__, mutex_handle_type_to_string (type), handle); + return FALSE; + } + + MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: owning %s handle %p, tid %p, recursion %u", + __func__, mutex_handle_type_to_string (type), handle, (gpointer) mutex_handle->tid, mutex_handle->recursion); + + mono_thread_info_own_mutex (mono_thread_info_current (), handle); + + mutex_handle->tid = pthread_self (); + mutex_handle->recursion++; + + mono_w32handle_set_signal_state (handle, FALSE, FALSE); + + return TRUE; +} + +static gboolean +mutex_handle_is_owned (gpointer handle, MonoW32HandleType type) +{ + struct _WapiHandle_mutex *mutex_handle; + + if (!mono_w32handle_lookup (handle, type, (gpointer *)&mutex_handle)) { + g_warning ("%s: error looking up %s handle %p", __func__, mutex_handle_type_to_string (type), handle); + return FALSE; + } + + MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: testing ownership %s handle %p", + __func__, mutex_handle_type_to_string (type), handle); + + if (mutex_handle->recursion > 0 && pthread_equal (mutex_handle->tid, pthread_self ())) { + MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: %s handle %p owned by %p", + __func__, mutex_handle_type_to_string (type), handle, (gpointer) pthread_self ()); + return TRUE; + } else { + MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: %s handle %p not owned by %p, but locked %d times by %p", + __func__, mutex_handle_type_to_string (type), handle, (gpointer) pthread_self (), mutex_handle->recursion, (gpointer) mutex_handle->tid); + return FALSE; + } } static void mutex_signal(gpointer handle) @@ -99,61 +137,13 @@ static void mutex_signal(gpointer handle) static gboolean mutex_own (gpointer handle) { - struct _WapiHandle_mutex *mutex_handle; - gboolean ok; - - ok = _wapi_lookup_handle (handle, WAPI_HANDLE_MUTEX, - (gpointer *)&mutex_handle); - if (ok == FALSE) { - g_warning ("%s: error looking up mutex handle %p", __func__, - handle); - return(FALSE); - } - - _wapi_thread_own_mutex (handle); - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: owning mutex handle %p", __func__, handle); - - _wapi_handle_set_signal_state (handle, FALSE, FALSE); - - mutex_handle->pid = _wapi_getpid (); - mutex_handle->tid = pthread_self (); - mutex_handle->recursion++; - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: mutex handle %p locked %d times by %d:%ld", __func__, - handle, mutex_handle->recursion, mutex_handle->pid, - mutex_handle->tid); - - return(TRUE); + return mutex_handle_own (handle, MONO_W32HANDLE_MUTEX); } static gboolean mutex_is_owned (gpointer handle) { - struct _WapiHandle_mutex *mutex_handle; - gboolean ok; - ok=_wapi_lookup_handle (handle, WAPI_HANDLE_MUTEX, - (gpointer *)&mutex_handle); - if(ok==FALSE) { - g_warning ("%s: error looking up mutex handle %p", __func__, - handle); - return(FALSE); - } - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: testing ownership mutex handle %p", __func__, handle); - - if (mutex_handle->recursion > 0 && - mutex_handle->pid == _wapi_getpid () && - pthread_equal (mutex_handle->tid, pthread_self ())) { - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: mutex handle %p owned by %d:%ld", __func__, - handle, _wapi_getpid (), pthread_self ()); - - return(TRUE); - } else { - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: mutex handle %p not owned by %d:%ld, but locked %d times by %d:%ld", __func__, handle, _wapi_getpid (), pthread_self (), mutex_handle->recursion, mutex_handle->pid, mutex_handle->tid); - - return(FALSE); - } + return mutex_handle_is_owned (handle, MONO_W32HANDLE_MUTEX); } static void namedmutex_signal (gpointer handle) @@ -164,65 +154,15 @@ static void namedmutex_signal (gpointer handle) /* NB, always called with the shared handle lock held */ static gboolean namedmutex_own (gpointer handle) { - struct _WapiHandle_namedmutex *namedmutex_handle; - gboolean ok; - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: owning named mutex handle %p", __func__, handle); - - ok = _wapi_lookup_handle (handle, WAPI_HANDLE_NAMEDMUTEX, - (gpointer *)&namedmutex_handle); - if (ok == FALSE) { - g_warning ("%s: error looking up named mutex handle %p", - __func__, handle); - return(FALSE); - } - - _wapi_thread_own_mutex (handle); - - namedmutex_handle->pid = _wapi_getpid (); - namedmutex_handle->tid = pthread_self (); - namedmutex_handle->recursion++; - - _wapi_shared_handle_set_signal_state (handle, FALSE); - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: mutex handle %p locked %d times by %d:%ld", __func__, - handle, namedmutex_handle->recursion, - namedmutex_handle->pid, namedmutex_handle->tid); - - return(TRUE); + return mutex_handle_own (handle, MONO_W32HANDLE_NAMEDMUTEX); } static gboolean namedmutex_is_owned (gpointer handle) { - struct _WapiHandle_namedmutex *namedmutex_handle; - gboolean ok; - - ok = _wapi_lookup_handle (handle, WAPI_HANDLE_NAMEDMUTEX, - (gpointer *)&namedmutex_handle); - if (ok == FALSE) { - g_warning ("%s: error looking up mutex handle %p", __func__, - handle); - return(FALSE); - } - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: testing ownership mutex handle %p", __func__, handle); - - if (namedmutex_handle->recursion > 0 && - namedmutex_handle->pid == _wapi_getpid () && - pthread_equal (namedmutex_handle->tid, pthread_self ())) { - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: mutex handle %p owned by %d:%ld", __func__, - handle, _wapi_getpid (), pthread_self ()); - - return(TRUE); - } else { - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: mutex handle %p not owned by %d:%ld, but locked %d times by %d:%ld", __func__, handle, _wapi_getpid (), pthread_self (), namedmutex_handle->recursion, namedmutex_handle->pid, namedmutex_handle->tid); - - return(FALSE); - } + return mutex_handle_is_owned (handle, MONO_W32HANDLE_NAMEDMUTEX); } -/* The shared state is not locked when prewait methods are called */ -static void namedmutex_prewait (gpointer handle) +static void mutex_handle_prewait (gpointer handle, MonoW32HandleType type) { /* If the mutex is not currently owned, do nothing and let the * usual wait carry on. If it is owned, check that the owner @@ -230,270 +170,198 @@ static void namedmutex_prewait (gpointer handle) * and assume that process exited abnormally and failed to * clean up. */ - struct _WapiHandle_namedmutex *namedmutex_handle; - gboolean ok; - - ok = _wapi_lookup_handle (handle, WAPI_HANDLE_NAMEDMUTEX, - (gpointer *)&namedmutex_handle); - if (ok == FALSE) { - g_warning ("%s: error looking up named mutex handle %p", - __func__, handle); - return; - } - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Checking ownership of named mutex handle %p", __func__, - handle); - - if (namedmutex_handle->recursion == 0) { - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Named mutex handle %p not owned", __func__, - handle); - } else if (namedmutex_handle->pid == _wapi_getpid ()) { - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Named mutex handle %p owned by this process", - __func__, handle); - } else { - int thr_ret; - gpointer proc_handle; - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Named mutex handle %p owned by another process", __func__, handle); - proc_handle = OpenProcess (0, 0, namedmutex_handle->pid); - if (proc_handle == NULL) { - /* Didn't find the process that this handle - * was owned by, overriding it - */ - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: overriding old owner of named mutex handle %p", __func__, handle); - thr_ret = _wapi_handle_lock_shared_handles (); - g_assert (thr_ret == 0); - - namedmutex_handle->pid = 0; - namedmutex_handle->tid = 0; - namedmutex_handle->recursion = 0; - - _wapi_shared_handle_set_signal_state (handle, TRUE); - _wapi_handle_unlock_shared_handles (); - } else { - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Found active pid %d for named mutex handle %p", __func__, namedmutex_handle->pid, handle); - } - if (proc_handle != NULL) - CloseProcess (proc_handle); - } -} - -static void mutex_abandon (gpointer handle, pid_t pid, pthread_t tid) -{ struct _WapiHandle_mutex *mutex_handle; - gboolean ok; - int thr_ret; - - ok = _wapi_lookup_handle (handle, WAPI_HANDLE_MUTEX, - (gpointer *)&mutex_handle); - if (ok == FALSE) { - g_warning ("%s: error looking up mutex handle %p", __func__, - handle); + + if (!mono_w32handle_lookup (handle, type, (gpointer *)&mutex_handle)) { + g_warning ("%s: error looking up %s handle %p", + __func__, mutex_handle_type_to_string (type), handle); return; } - thr_ret = _wapi_handle_lock_handle (handle); - g_assert (thr_ret == 0); - - if (mutex_handle->pid == pid && - pthread_equal (mutex_handle->tid, tid)) { - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Mutex handle %p abandoned!", __func__, handle); - - mutex_handle->recursion = 0; - mutex_handle->pid = 0; - mutex_handle->tid = 0; - - _wapi_handle_set_signal_state (handle, TRUE, FALSE); - } - - thr_ret = _wapi_handle_unlock_handle (handle); - g_assert (thr_ret == 0); + MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: pre-waiting %s handle %p, owned? %s", + __func__, mutex_handle_type_to_string (type), handle, mutex_handle->recursion != 0 ? "true" : "false"); } -static void namedmutex_abandon (gpointer handle, pid_t pid, pthread_t tid) +/* The shared state is not locked when prewait methods are called */ +static void mutex_prewait (gpointer handle) { - struct _WapiHandle_namedmutex *mutex_handle; - gboolean ok; + mutex_handle_prewait (handle, MONO_W32HANDLE_MUTEX); +} + +/* The shared state is not locked when prewait methods are called */ +static void namedmutex_prewait (gpointer handle) +{ + mutex_handle_prewait (handle, MONO_W32HANDLE_NAMEDMUTEX); +} + +static void mutex_details (gpointer data) +{ + struct _WapiHandle_mutex *mut = (struct _WapiHandle_mutex *)data; + +#ifdef PTHREAD_POINTER_ID + g_print ("own: %5p, count: %5u", mut->tid, mut->recursion); +#else + g_print ("own: %5ld, count: %5u", mut->tid, mut->recursion); +#endif +} + +static void namedmutex_details (gpointer data) +{ + struct _WapiHandle_namedmutex *namedmut = (struct _WapiHandle_namedmutex *)data; + +#ifdef PTHREAD_POINTER_ID + g_print ("own: %5p, count: %5u, name: \"%s\"", + namedmut->m.tid, namedmut->m.recursion, namedmut->sharedns.name); +#else + g_print ("own: %5ld, count: %5u, name: \"%s\"", + namedmut->m.tid, namedmut->m.recursion, namedmut->sharedns.name); +#endif +} + +static const gchar* mutex_typename (void) +{ + return "Mutex"; +} + +static gsize mutex_typesize (void) +{ + return sizeof (struct _WapiHandle_mutex); +} + +static const gchar* namedmutex_typename (void) +{ + return "N.Mutex"; +} + +static gsize namedmutex_typesize (void) +{ + return sizeof (struct _WapiHandle_namedmutex); +} + +/* When a thread exits, any mutexes it still holds need to be signalled. */ +void wapi_mutex_abandon (gpointer handle, pid_t pid, pthread_t tid) +{ + MonoW32HandleType type; + struct _WapiHandle_mutex *mutex_handle; int thr_ret; - - ok = _wapi_lookup_handle (handle, WAPI_HANDLE_NAMEDMUTEX, - (gpointer *)&mutex_handle); - if (ok == FALSE) { - g_warning ("%s: error looking up named mutex handle %p", - __func__, handle); - return; - } - thr_ret = _wapi_handle_lock_shared_handles (); - g_assert (thr_ret == 0); - - if (mutex_handle->pid == pid && - pthread_equal (mutex_handle->tid, tid)) { - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Mutex handle %p abandoned!", __func__, handle); - - mutex_handle->recursion = 0; - mutex_handle->pid = 0; - mutex_handle->tid = 0; - - _wapi_shared_handle_set_signal_state (handle, TRUE); - } - - _wapi_handle_unlock_shared_handles (); -} - -/* When a thread exits, any mutexes it still holds need to be - * signalled. This function must not be called with the shared handle - * lock held, as namedmutex_abandon () will try to acquire it - */ -void _wapi_mutex_abandon (gpointer data, pid_t pid, pthread_t tid) -{ - WapiHandleType type = _wapi_handle_type (data); - - if (type == WAPI_HANDLE_MUTEX) { - mutex_abandon (data, pid, tid); - } else if (type == WAPI_HANDLE_NAMEDMUTEX) { - namedmutex_abandon (data, pid, tid); - } else { + switch (type = mono_w32handle_get_type (handle)) { + case MONO_W32HANDLE_MUTEX: + case MONO_W32HANDLE_NAMEDMUTEX: + break; + default: g_assert_not_reached (); } + + if (!mono_w32handle_lookup (handle, type, (gpointer *)&mutex_handle)) { + g_warning ("%s: error looking up %s handle %p", + __func__, mutex_handle_type_to_string (type), handle); + return; + } + + MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: abandon %s handle %p", + __func__, mutex_handle_type_to_string (type), handle); + + thr_ret = mono_w32handle_lock_handle (handle); + g_assert (thr_ret == 0); + + if (pthread_equal (mutex_handle->tid, tid)) { + mutex_handle->recursion = 0; + mutex_handle->tid = 0; + + mono_w32handle_set_signal_state (handle, TRUE, FALSE); + + MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: abandoned %s handle %p", + __func__, mutex_handle_type_to_string (type), handle); + } + + thr_ret = mono_w32handle_unlock_handle (handle); + g_assert (thr_ret == 0); } -static gpointer mutex_create (WapiSecurityAttributes *security G_GNUC_UNUSED, - gboolean owned) +static gpointer mutex_handle_create (struct _WapiHandle_mutex *mutex_handle, MonoW32HandleType type, gboolean owned) { - struct _WapiHandle_mutex mutex_handle = {0}; gpointer handle; int thr_ret; - - /* Need to blow away any old errors here, because code tests - * for ERROR_ALREADY_EXISTS on success (!) to see if a mutex - * was freshly created - */ - SetLastError (ERROR_SUCCESS); - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Creating unnamed mutex", __func__); - - handle = _wapi_handle_new (WAPI_HANDLE_MUTEX, &mutex_handle); - if (handle == _WAPI_HANDLE_INVALID) { - g_warning ("%s: error creating mutex handle", __func__); + + mutex_handle->tid = 0; + mutex_handle->recursion = 0; + + handle = mono_w32handle_new (type, mutex_handle); + if (handle == INVALID_HANDLE_VALUE) { + g_warning ("%s: error creating %s handle", + __func__, mutex_handle_type_to_string (type)); SetLastError (ERROR_GEN_FAILURE); - return(NULL); + return NULL; } - thr_ret = _wapi_handle_lock_handle (handle); + thr_ret = mono_w32handle_lock_handle (handle); g_assert (thr_ret == 0); - - if(owned==TRUE) { - mutex_own (handle); - } else { - _wapi_handle_set_signal_state (handle, TRUE, FALSE); - } - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning mutex handle %p", __func__, handle); - thr_ret = _wapi_handle_unlock_handle (handle); + if (owned) + mutex_handle_own (handle, type); + else + mono_w32handle_set_signal_state (handle, TRUE, FALSE); + + thr_ret = mono_w32handle_unlock_handle (handle); g_assert (thr_ret == 0); - - return(handle); + + MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: created %s handle %p", + __func__, mutex_handle_type_to_string (type), handle); + + return handle; } -static gpointer namedmutex_create (WapiSecurityAttributes *security G_GNUC_UNUSED, gboolean owned, - const gunichar2 *name) +static gpointer mutex_create (gboolean owned) +{ + struct _WapiHandle_mutex mutex_handle; + MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: creating %s handle", + __func__, mutex_handle_type_to_string (MONO_W32HANDLE_MUTEX)); + return mutex_handle_create (&mutex_handle, MONO_W32HANDLE_MUTEX, owned); +} + +static gpointer namedmutex_create (gboolean owned, const gunichar2 *name) { - struct _WapiHandle_namedmutex namedmutex_handle = {{{0}}, 0}; gpointer handle; gchar *utf8_name; int thr_ret; - gpointer ret = NULL; - guint32 namelen; - gint32 offset; - /* w32 seems to guarantee that opening named objects can't - * race each other - */ + MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: creating %s handle", + __func__, mutex_handle_type_to_string (MONO_W32HANDLE_NAMEDMUTEX)); + + /* w32 seems to guarantee that opening named objects can't race each other */ thr_ret = _wapi_namespace_lock (); g_assert (thr_ret == 0); - /* Need to blow away any old errors here, because code tests - * for ERROR_ALREADY_EXISTS on success (!) to see if a mutex - * was freshly created - */ - SetLastError (ERROR_SUCCESS); - utf8_name = g_utf16_to_utf8 (name, -1, NULL, NULL, NULL); - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Creating named mutex [%s]", __func__, utf8_name); - - offset = _wapi_search_handle_namespace (WAPI_HANDLE_NAMEDMUTEX, - utf8_name); - if (offset == -1) { - /* The name has already been used for a different - * object. - */ + + handle = _wapi_search_handle_namespace (MONO_W32HANDLE_NAMEDMUTEX, utf8_name); + if (handle == INVALID_HANDLE_VALUE) { + /* The name has already been used for a different object. */ + handle = NULL; SetLastError (ERROR_INVALID_HANDLE); - goto cleanup; - } else if (offset != 0) { - /* Not an error, but this is how the caller is - * informed that the mutex wasn't freshly created - */ + } else if (handle) { + /* Not an error, but this is how the caller is informed that the mutex wasn't freshly created */ SetLastError (ERROR_ALREADY_EXISTS); - } - /* Fall through to create the mutex handle. */ - if (offset == 0) { - /* A new named mutex, so create both the private and - * shared parts - */ - - if (strlen (utf8_name) < MAX_PATH) { - namelen = strlen (utf8_name); - } else { - namelen = MAX_PATH; - } - - memcpy (&namedmutex_handle.sharedns.name, utf8_name, namelen); - - handle = _wapi_handle_new (WAPI_HANDLE_NAMEDMUTEX, - &namedmutex_handle); + /* this is used as creating a new handle */ + mono_w32handle_ref (handle); } else { - /* A new reference to an existing named mutex, so just - * create the private part - */ - handle = _wapi_handle_new_from_offset (WAPI_HANDLE_NAMEDMUTEX, - offset, TRUE); - } - - if (handle == _WAPI_HANDLE_INVALID) { - g_warning ("%s: error creating mutex handle", __func__); - SetLastError (ERROR_GEN_FAILURE); - goto cleanup; - } - ret = handle; + /* A new named mutex */ + struct _WapiHandle_namedmutex namedmutex_handle; - if (offset == 0) { - /* Set the initial state, as this is a completely new - * handle - */ - thr_ret = _wapi_handle_lock_shared_handles (); - g_assert (thr_ret == 0); - - if (owned == TRUE) { - namedmutex_own (handle); - } else { - _wapi_shared_handle_set_signal_state (handle, TRUE); - } + strncpy (&namedmutex_handle.sharedns.name [0], utf8_name, MAX_PATH); + namedmutex_handle.sharedns.name [MAX_PATH] = '\0'; - _wapi_handle_unlock_shared_handles (); + handle = mutex_handle_create ((struct _WapiHandle_mutex*) &namedmutex_handle, MONO_W32HANDLE_NAMEDMUTEX, owned); } - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning mutex handle %p", __func__, handle); -cleanup: g_free (utf8_name); - _wapi_namespace_unlock (NULL); - - return(ret); + thr_ret = _wapi_namespace_unlock (NULL); + g_assert (thr_ret == 0); + + return handle; } /** @@ -515,115 +383,14 @@ cleanup: * * Return value: A new handle, or %NULL on error. */ -gpointer CreateMutex(WapiSecurityAttributes *security G_GNUC_UNUSED, gboolean owned, - const gunichar2 *name) +gpointer CreateMutex(WapiSecurityAttributes *security G_GNUC_UNUSED, gboolean owned, const gunichar2 *name) { - mono_once (&mutex_ops_once, mutex_ops_init); + /* Need to blow away any old errors here, because code tests + * for ERROR_ALREADY_EXISTS on success (!) to see if a mutex + * was freshly created */ + SetLastError (ERROR_SUCCESS); - if (name == NULL) { - return(mutex_create (security, owned)); - } else { - return(namedmutex_create (security, owned, name)); - } -} - -static gboolean mutex_release (gpointer handle) -{ - struct _WapiHandle_mutex *mutex_handle; - gboolean ok; - pthread_t tid = pthread_self (); - pid_t pid = _wapi_getpid (); - int thr_ret; - gboolean ret = FALSE; - - ok = _wapi_lookup_handle (handle, WAPI_HANDLE_MUTEX, - (gpointer *)&mutex_handle); - if (ok == FALSE) { - g_warning ("%s: error looking up mutex handle %p", __func__, - handle); - return(FALSE); - } - - thr_ret = _wapi_handle_lock_handle (handle); - g_assert (thr_ret == 0); - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Releasing mutex handle %p", __func__, handle); - - if (!pthread_equal (mutex_handle->tid, tid) || - mutex_handle->pid != pid) { - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: We don't own mutex handle %p (owned by %d:%ld, me %d:%ld)", __func__, handle, mutex_handle->pid, mutex_handle->tid, _wapi_getpid (), tid); - - goto cleanup; - } - ret = TRUE; - - /* OK, we own this mutex */ - mutex_handle->recursion--; - - if(mutex_handle->recursion==0) { - _wapi_thread_disown_mutex (handle); - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Unlocking mutex handle %p", __func__, handle); - - mutex_handle->pid=0; - mutex_handle->tid=0; - _wapi_handle_set_signal_state (handle, TRUE, FALSE); - } - -cleanup: - thr_ret = _wapi_handle_unlock_handle (handle); - g_assert (thr_ret == 0); - - return(ret); -} - -static gboolean namedmutex_release (gpointer handle) -{ - struct _WapiHandle_namedmutex *mutex_handle; - gboolean ok; - pthread_t tid = pthread_self (); - pid_t pid = _wapi_getpid (); - int thr_ret; - gboolean ret = FALSE; - - ok=_wapi_lookup_handle (handle, WAPI_HANDLE_NAMEDMUTEX, - (gpointer *)&mutex_handle); - if(ok==FALSE) { - g_warning ("%s: error looking up named mutex handle %p", - __func__, handle); - return(FALSE); - } - - thr_ret = _wapi_handle_lock_shared_handles (); - g_assert (thr_ret == 0); - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Releasing mutex handle %p", __func__, handle); - - if (!pthread_equal (mutex_handle->tid, tid) || - mutex_handle->pid != pid) { - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: We don't own mutex handle %p (owned by %d:%ld, me %d:%ld)", __func__, handle, mutex_handle->pid, mutex_handle->tid, _wapi_getpid (), tid); - - goto cleanup; - } - ret = TRUE; - - /* OK, we own this mutex */ - mutex_handle->recursion--; - - if(mutex_handle->recursion==0) { - _wapi_thread_disown_mutex (handle); - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Unlocking mutex handle %p", __func__, handle); - - mutex_handle->pid=0; - mutex_handle->tid=0; - _wapi_shared_handle_set_signal_state (handle, TRUE); - } - -cleanup: - _wapi_handle_unlock_shared_handles (); - - return(ret); + return name ? namedmutex_create (owned, name) : mutex_create (owned); } /** @@ -637,21 +404,66 @@ cleanup: */ gboolean ReleaseMutex(gpointer handle) { - WapiHandleType type; + MonoW32HandleType type; + struct _WapiHandle_mutex *mutex_handle; + pthread_t tid; + int thr_ret; + gboolean ret; if (handle == NULL) { SetLastError (ERROR_INVALID_HANDLE); - return(FALSE); + return FALSE; } - - type = _wapi_handle_type (handle); - - if (mutex_ops[type].release == NULL) { + + switch (type = mono_w32handle_get_type (handle)) { + case MONO_W32HANDLE_MUTEX: + case MONO_W32HANDLE_NAMEDMUTEX: + break; + default: SetLastError (ERROR_INVALID_HANDLE); - return(FALSE); + return FALSE; } - - return(mutex_ops[type].release (handle)); + + if (!mono_w32handle_lookup (handle, type, (gpointer *)&mutex_handle)) { + g_warning ("%s: error looking up %s handle %p", + __func__, mutex_handle_type_to_string (type), handle); + return FALSE; + } + + MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: releasing %s handle %p", + __func__, mutex_handle_type_to_string (type), handle); + + thr_ret = mono_w32handle_lock_handle (handle); + g_assert (thr_ret == 0); + + tid = pthread_self (); + + if (!pthread_equal (mutex_handle->tid, tid)) { + ret = FALSE; + + MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: we don't own %s handle %p (owned by %ld, me %ld)", + __func__, mutex_handle_type_to_string (type), handle, mutex_handle->tid, tid); + } else { + ret = TRUE; + + /* OK, we own this mutex */ + mutex_handle->recursion--; + + if (mutex_handle->recursion == 0) { + mono_thread_info_disown_mutex (mono_thread_info_current (), handle); + + MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unlocking %s handle %p", + __func__, mutex_handle_type_to_string (type), handle); + + mutex_handle->tid = 0; + mono_w32handle_set_signal_state (handle, TRUE, FALSE); + } + } + + thr_ret = mono_w32handle_unlock_handle (handle); + g_assert (thr_ret == 0); + + return ret; } gpointer OpenMutex (guint32 access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED, const gunichar2 *name) @@ -659,10 +471,6 @@ gpointer OpenMutex (guint32 access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED gpointer handle; gchar *utf8_name; int thr_ret; - gpointer ret = NULL; - gint32 offset; - - mono_once (&mutex_ops_once, mutex_ops_init); /* w32 seems to guarantee that opening named objects can't * race each other @@ -674,33 +482,20 @@ gpointer OpenMutex (guint32 access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Opening named mutex [%s]", __func__, utf8_name); - offset = _wapi_search_handle_namespace (WAPI_HANDLE_NAMEDMUTEX, + handle = _wapi_search_handle_namespace (MONO_W32HANDLE_NAMEDMUTEX, utf8_name); - if (offset == -1) { + if (handle == INVALID_HANDLE_VALUE) { /* The name has already been used for a different * object. */ SetLastError (ERROR_INVALID_HANDLE); goto cleanup; - } else if (offset == 0) { + } else if (!handle) { /* This name doesn't exist */ SetLastError (ERROR_FILE_NOT_FOUND); /* yes, really */ goto cleanup; } - /* A new reference to an existing named mutex, so just create - * the private part - */ - handle = _wapi_handle_new_from_offset (WAPI_HANDLE_NAMEDMUTEX, offset, - TRUE); - - if (handle == _WAPI_HANDLE_INVALID) { - g_warning ("%s: error opening named mutex handle", __func__); - SetLastError (ERROR_GEN_FAILURE); - goto cleanup; - } - ret = handle; - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning named mutex handle %p", __func__, handle); cleanup: @@ -708,5 +503,5 @@ cleanup: _wapi_namespace_unlock (NULL); - return(ret); + return handle; } diff --git a/mono/io-layer/mutexes.h b/mono/io-layer/mutexes.h index ef9e46d9e9..d1b7a68d67 100644 --- a/mono/io-layer/mutexes.h +++ b/mono/io-layer/mutexes.h @@ -12,6 +12,8 @@ #include +#include + G_BEGIN_DECLS extern gpointer CreateMutex (WapiSecurityAttributes *security, gboolean owned, @@ -20,6 +22,9 @@ extern gboolean ReleaseMutex (gpointer handle); extern gpointer OpenMutex (guint32 access, gboolean inherit, const gunichar2 *name); +void +wapi_mutex_abandon (gpointer data, pid_t pid, pthread_t tid); + G_END_DECLS #endif /* _WAPI_MUTEXES_H_ */ diff --git a/mono/io-layer/posix.c b/mono/io-layer/posix.c index 2856d4fcd6..fe350c8b86 100644 --- a/mono/io-layer/posix.c +++ b/mono/io-layer/posix.c @@ -22,10 +22,10 @@ #include #include -#include #include #include #include +#include static guint32 convert_from_flags(int flags) @@ -101,8 +101,8 @@ gpointer _wapi_stdhandle_create (int fd, const gchar *name) file_handle.sharemode=0; file_handle.attrs=0; - handle = _wapi_handle_new_fd (WAPI_HANDLE_CONSOLE, fd, &file_handle); - if (handle == _WAPI_HANDLE_INVALID) { + handle = mono_w32handle_new_fd (MONO_W32HANDLE_CONSOLE, fd, &file_handle); + if (handle == INVALID_HANDLE_VALUE) { g_warning ("%s: error creating file handle", __func__); SetLastError (ERROR_GEN_FAILURE); return(INVALID_HANDLE_VALUE); diff --git a/mono/io-layer/process-private.h b/mono/io-layer/process-private.h index ddd6e863f3..a17de8a3ad 100644 --- a/mono/io-layer/process-private.h +++ b/mono/io-layer/process-private.h @@ -30,12 +30,10 @@ #define WAPI_PID_TO_HANDLE(pid) GINT_TO_POINTER (_WAPI_PROCESS_UNHANDLED + (pid)) #define WAPI_HANDLE_TO_PID(handle) (GPOINTER_TO_UINT ((handle)) - _WAPI_PROCESS_UNHANDLED) -void wapi_processes_init (void); +void _wapi_processes_init (void); extern gpointer _wapi_process_duplicate (void); extern void wapi_processes_cleanup (void); -extern struct _WapiHandleOps _wapi_process_ops; - /* * MonoProcess describes processes we create. * It contains a semaphore that can be waited on in order to wait diff --git a/mono/io-layer/processes.c b/mono/io-layer/processes.c index 2120793460..53c271a449 100644 --- a/mono/io-layer/processes.c +++ b/mono/io-layer/processes.c @@ -95,9 +95,7 @@ #include #include -#include #include -#include #include #include #include @@ -109,6 +107,9 @@ #include #include #include +#include + +#define STILL_ACTIVE STATUS_PENDING /* The process' environment strings */ #if defined(__APPLE__) @@ -127,8 +128,11 @@ static char *mono_environ[1] = { NULL }; extern char **environ; #endif -static guint32 process_wait (gpointer handle, guint32 timeout, gboolean alertable); +static guint32 process_wait (gpointer handle, guint32 timeout, gboolean *alerted); static void process_close (gpointer handle, gpointer data); +static void process_details (gpointer data); +static const gchar* process_typename (void); +static gsize process_typesize (void); static gboolean is_pid_valid (pid_t pid); #if !(defined(USE_OSX_LOADER) || defined(USE_BSD_LOADER) || defined(USE_HAIKU_LOADER)) @@ -136,13 +140,16 @@ static FILE * open_process_map (int pid, const char *mode); #endif -struct _WapiHandleOps _wapi_process_ops = { +static MonoW32HandleOps _wapi_process_ops = { process_close, /* close_shared */ NULL, /* signal */ NULL, /* own */ NULL, /* is_owned */ process_wait, /* special_wait */ - NULL /* prewait */ + NULL, /* prewait */ + process_details, /* details */ + process_typename, /* typename */ + process_typesize, /* typesize */ }; #if HAVE_SIGACTION @@ -178,7 +185,7 @@ lookup_process_handle (gpointer handle) WapiHandle_process *process_data; gboolean ret; - ret = _wapi_lookup_handle (handle, WAPI_HANDLE_PROCESS, + ret = mono_w32handle_lookup (handle, MONO_W32HANDLE_PROCESS, (gpointer *)&process_data); if (!ret) return NULL; @@ -405,10 +412,10 @@ is_managed_binary (const char *filename) off_t new_offset; unsigned char buffer[8]; off_t file_size, optional_header_offset; - off_t pe_header_offset; + off_t pe_header_offset, clr_header_offset; gboolean managed = FALSE; int num_read; - guint32 first_word, second_word; + guint32 first_word, second_word, magic_number; /* If we are unable to open the file, then we definitely * can't say that it is managed. The child mono process @@ -473,13 +480,34 @@ is_managed_binary (const char *filename) if ((num_read != 2) || ((buffer[0] | (buffer[1] << 8)) < 216)) goto leave; + optional_header_offset = pe_header_offset + 24; + + /* Read the PE magic number */ + new_offset = lseek (file, optional_header_offset, SEEK_SET); + + if (new_offset != optional_header_offset) + goto leave; + + num_read = read (file, buffer, 2); + + if (num_read != 2) + goto leave; + + magic_number = (buffer[0] | (buffer[1] << 8)); + + if (magic_number == 0x10B) // PE32 + clr_header_offset = 208; + else if (magic_number == 0x20B) // PE32+ + clr_header_offset = 224; + else + goto leave; + /* Read the CLR header address and size fields. These will be * zero if the binary is not managed. */ - optional_header_offset = pe_header_offset + 24; - new_offset = lseek (file, optional_header_offset + 208, SEEK_SET); + new_offset = lseek (file, optional_header_offset + clr_header_offset, SEEK_SET); - if (new_offset != optional_header_offset + 208) + if (new_offset != optional_header_offset + clr_header_offset) goto leave; num_read = read (file, buffer, 8); @@ -577,7 +605,6 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline, GError *gerr = NULL; int in_fd, out_fd, err_fd; pid_t pid = 0; - int thr_ret; int startup_pipe [2] = {-1, -1}; int dummy; struct MonoProcess *mono_process; @@ -895,8 +922,8 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline, process_set_defaults (&process_handle); - handle = _wapi_handle_new (WAPI_HANDLE_PROCESS, &process_handle); - if (handle == _WAPI_HANDLE_INVALID) { + handle = mono_w32handle_new (MONO_W32HANDLE_PROCESS, &process_handle); + if (handle == INVALID_HANDLE_VALUE) { g_warning ("%s: error creating process handle", __func__); ret = FALSE; @@ -999,7 +1026,7 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline, } /* Close all file descriptors */ - for (i = wapi_getdtablesize () - 1; i > 2; i--) + for (i = mono_w32handle_fd_reserve - 1; i > 2; i--) close (i); #ifdef DEBUG_ENABLED @@ -1027,13 +1054,10 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline, break; } default: /* Parent */ { - thr_ret = _wapi_handle_lock_shared_handles (); - g_assert (thr_ret == 0); - process_handle_data = lookup_process_handle (handle); if (!process_handle_data) { g_warning ("%s: error looking up process handle %p", __func__, handle); - _wapi_handle_unref (handle); + mono_w32handle_unref (handle); } else { process_handle_data->id = pid; @@ -1041,25 +1065,19 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline, mono_process = (struct MonoProcess *) g_malloc0 (sizeof (struct MonoProcess)); mono_process->pid = pid; mono_process->handle_count = 1; - if (mono_os_sem_init (&mono_process->exit_sem, 0) != 0) { - /* If we can't create the exit semaphore, we just don't add anything - * to our list of mono processes. Waiting on the process will return - * immediately. */ - g_warning ("%s: could not create exit semaphore for process.", strerror (errno)); - g_free (mono_process); - } else { - /* Keep the process handle artificially alive until the process - * exits so that the information in the handle isn't lost. */ - _wapi_handle_ref (handle); - mono_process->handle = handle; + mono_os_sem_init (&mono_process->exit_sem, 0); - process_handle_data->mono_process = mono_process; + /* Keep the process handle artificially alive until the process + * exits so that the information in the handle isn't lost. */ + mono_w32handle_ref (handle); + mono_process->handle = handle; - mono_os_mutex_lock (&mono_processes_mutex); - mono_process->next = mono_processes; - mono_processes = mono_process; - mono_os_mutex_unlock (&mono_processes_mutex); - } + process_handle_data->mono_process = mono_process; + + mono_os_mutex_lock (&mono_processes_mutex); + mono_process->next = mono_processes; + mono_processes = mono_process; + mono_os_mutex_unlock (&mono_processes_mutex); if (process_info != NULL) { process_info->hProcess = handle; @@ -1071,14 +1089,12 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline, } } - _wapi_handle_unlock_shared_handles (); - break; } } if (fork_failed) - _wapi_handle_unref (handle); + mono_w32handle_unref (handle); if (startup_pipe [1] != -1) { /* Write 1 byte, doesn't matter what */ @@ -1136,20 +1152,22 @@ process_set_name (WapiHandle_process *process_handle) } void -wapi_processes_init (void) +_wapi_processes_init (void) { - pid_t pid = _wapi_getpid (); + pid_t pid = wapi_getpid (); WapiHandle_process process_handle = {0}; - _wapi_handle_register_capabilities (WAPI_HANDLE_PROCESS, - (WapiHandleCapability)(WAPI_HANDLE_CAP_WAIT | WAPI_HANDLE_CAP_SPECIAL_WAIT)); + mono_w32handle_register_ops (MONO_W32HANDLE_PROCESS, &_wapi_process_ops); + + mono_w32handle_register_capabilities (MONO_W32HANDLE_PROCESS, + (MonoW32HandleCapability)(MONO_W32HANDLE_CAP_WAIT | MONO_W32HANDLE_CAP_SPECIAL_WAIT)); process_handle.id = pid; process_set_defaults (&process_handle); process_set_name (&process_handle); - current_process = _wapi_handle_new (WAPI_HANDLE_PROCESS, + current_process = mono_w32handle_new (MONO_W32HANDLE_PROCESS, &process_handle); g_assert (current_process); @@ -1159,7 +1177,7 @@ wapi_processes_init (void) gpointer _wapi_process_duplicate (void) { - _wapi_handle_ref (current_process); + mono_w32handle_ref (current_process); return current_process; } @@ -1215,9 +1233,9 @@ process_open_compare (gpointer handle, gpointer user_data) * unsignalled */ if (checking_pid == wanted_pid && - !_wapi_handle_issignalled (handle)) { + !mono_w32handle_issignalled (handle)) { /* If the handle is blown away in the window between - * returning TRUE here and _wapi_search_handle pinging + * returning TRUE here and mono_w32handle_search pinging * the timestamp, the search will continue */ return TRUE; @@ -1245,7 +1263,7 @@ OpenProcess (guint32 req_access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED, g MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: looking for process %d", __func__, pid); - handle = _wapi_search_handle (WAPI_HANDLE_PROCESS, + handle = mono_w32handle_search (MONO_W32HANDLE_PROCESS, process_open_compare, GUINT_TO_POINTER (pid), NULL, TRUE); if (handle == 0) { @@ -1263,7 +1281,7 @@ OpenProcess (guint32 req_access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED, g } } - /* _wapi_search_handle () already added a ref */ + /* mono_w32handle_search () already added a ref */ return handle; } @@ -1272,6 +1290,7 @@ GetExitCodeProcess (gpointer process, guint32 *code) { WapiHandle_process *process_handle; guint32 pid = -1; + gboolean alerted; if (!code) return FALSE; @@ -1297,7 +1316,7 @@ GetExitCodeProcess (gpointer process, guint32 *code) return FALSE; } - if (process_handle->id == _wapi_getpid ()) { + if (process_handle->id == wapi_getpid ()) { *code = STILL_ACTIVE; return TRUE; } @@ -1308,9 +1327,9 @@ GetExitCodeProcess (gpointer process, guint32 *code) /* Make sure any process exit has been noticed, before * checking if the process is signalled. Fixes bug 325463. */ - process_wait (process, 0, TRUE); + process_wait (process, 0, &alerted); - if (_wapi_handle_issignalled (process)) + if (mono_w32handle_issignalled (process)) *code = process_handle->exitstatus; else *code = STILL_ACTIVE; @@ -1356,7 +1375,7 @@ GetProcessTimes (gpointer process, WapiFileTime *create_time, /* A process handle is only signalled if the process has * exited. Otherwise exit_time isn't set */ - if (_wapi_handle_issignalled (process)) + if (mono_w32handle_issignalled (process)) *exit_time = process_handle->exit_time; #ifdef HAVE_GETRUSAGE @@ -1478,7 +1497,7 @@ static int load_modules_callback (struct dl_phdr_info *info, size_t size, void * + sizeof (info->dlpi_phnum)) return (-1); - struct dl_phdr_info *cpy = calloc(1, sizeof(struct dl_phdr_info)); + struct dl_phdr_info *cpy = g_calloc (1, sizeof(struct dl_phdr_info)); if (!cpy) return (-1); @@ -1514,7 +1533,7 @@ static GSList *load_modules (void) MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: inode=%d, filename=%s, address_start=%p, address_end=%p", __func__, mod->inode, mod->filename, mod->address_start, mod->address_end); - free(info); + g_free (info); if (g_slist_find_custom (ret, mod, find_procmodule) == NULL) { ret = g_slist_prepend (ret, mod); @@ -1913,12 +1932,12 @@ get_process_name_from_proc (pid_t pid) if (sysctl(mib, 4, NULL, &size, NULL, 0) < 0) return(ret); - if ((pi = malloc(size)) == NULL) + if ((pi = g_malloc (size)) == NULL) return(ret); if (sysctl (mib, 4, pi, &size, NULL, 0) < 0) { if (errno == ENOMEM) { - free(pi); + g_free (pi); MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Didn't allocate enough memory for kproc info", __func__); } return(ret); @@ -1927,7 +1946,7 @@ get_process_name_from_proc (pid_t pid) if (strlen (pi->kp_proc.p_comm) > 0) ret = g_strdup (pi->kp_proc.p_comm); - free(pi); + g_free (pi); #endif #elif defined(USE_BSD_LOADER) #if defined(__FreeBSD__) @@ -1940,12 +1959,12 @@ get_process_name_from_proc (pid_t pid) return(ret); } - if ((pi = malloc(size)) == NULL) + if ((pi = g_malloc (size)) == NULL) return(ret); if (sysctl (mib, 4, pi, &size, NULL, 0) < 0) { if (errno == ENOMEM) { - free(pi); + g_free (pi); MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Didn't allocate enough memory for kproc info", __func__); } return(ret); @@ -1953,7 +1972,7 @@ get_process_name_from_proc (pid_t pid) if (strlen (pi->ki_comm) > 0) ret = g_strdup (pi->ki_comm); - free(pi); + g_free (pi); #elif defined(__OpenBSD__) mib [0] = CTL_KERN; mib [1] = KERN_PROC; @@ -1968,7 +1987,7 @@ retry: return(ret); } - if ((pi = malloc(size)) == NULL) + if ((pi = g_malloc (size)) == NULL) return(ret); mib[5] = (int)(size / sizeof(struct kinfo_proc)); @@ -1976,7 +1995,7 @@ retry: if ((sysctl (mib, 6, pi, &size, NULL, 0) < 0) || (size != sizeof (struct kinfo_proc))) { if (errno == ENOMEM) { - free(pi); + g_free (pi); goto retry; } return(ret); @@ -1985,7 +2004,7 @@ retry: if (strlen (pi->p_comm) > 0) ret = g_strdup (pi->p_comm); - free(pi); + g_free (pi); #endif #elif defined(USE_HAIKU_LOADER) image_info imageInfo; @@ -2594,7 +2613,7 @@ mono_processes_cleanup (void) mp->handle = NULL; mono_os_mutex_unlock (&mono_processes_mutex); if (unref_handle) - _wapi_handle_unref (unref_handle); + mono_w32handle_unref (unref_handle); } } @@ -2663,6 +2682,23 @@ process_close (gpointer handle, gpointer data) mono_processes_cleanup (); } +static void process_details (gpointer data) +{ + WapiHandle_process *process_handle = (WapiHandle_process *) data; + g_print ("id: %d, exited: %s, exitstatus: %d", + process_handle->id, process_handle->exited ? "true" : "false", process_handle->exitstatus); +} + +static const gchar* process_typename (void) +{ + return "Process"; +} + +static gsize process_typesize (void) +{ + return sizeof (WapiHandle_process); +} + #if HAVE_SIGACTION MONO_SIGNAL_HANDLER_FUNC (static, mono_sigchld_signal_handler, (int _dummy, siginfo_t *info, void *context)) { @@ -2670,8 +2706,6 @@ MONO_SIGNAL_HANDLER_FUNC (static, mono_sigchld_signal_handler, (int _dummy, sigi int pid; struct MonoProcess *p; - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "SIG CHILD handler for pid: %i\n", info->si_pid); - do { do { pid = waitpid (-1, &status, WNOHANG); @@ -2680,8 +2714,6 @@ MONO_SIGNAL_HANDLER_FUNC (static, mono_sigchld_signal_handler, (int _dummy, sigi if (pid <= 0) break; - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "child ended: %i", pid); - /* * This can run concurrently with the code in the rest of this module. */ @@ -2699,8 +2731,6 @@ MONO_SIGNAL_HANDLER_FUNC (static, mono_sigchld_signal_handler, (int _dummy, sigi p->freeable = TRUE; } } while (1); - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "SIG CHILD handler: done looping."); } #endif @@ -2720,7 +2750,7 @@ process_add_sigchld_handler (void) } static guint32 -process_wait (gpointer handle, guint32 timeout, gboolean alertable) +process_wait (gpointer handle, guint32 timeout, gboolean *alerted) { WapiHandle_process *process_handle; pid_t pid G_GNUC_UNUSED, ret; @@ -2734,6 +2764,9 @@ process_wait (gpointer handle, guint32 timeout, gboolean alertable) MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u)", __func__, handle, timeout); + if (alerted) + *alerted = FALSE; + process_handle = lookup_process_handle (handle); if (!process_handle) { g_warning ("%s: error looking up process handle %p", __func__, handle); @@ -2789,26 +2822,20 @@ process_wait (gpointer handle, guint32 timeout, gboolean alertable) if (timeout != INFINITE) { MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): waiting on semaphore for %li ms...", __func__, handle, timeout, (timeout - (now - start))); - ret = mono_os_sem_timedwait (&mp->exit_sem, (timeout - (now - start)), alertable ? MONO_SEM_FLAGS_ALERTABLE : MONO_SEM_FLAGS_NONE); + ret = mono_os_sem_timedwait (&mp->exit_sem, (timeout - (now - start)), alerted ? MONO_SEM_FLAGS_ALERTABLE : MONO_SEM_FLAGS_NONE); } else { MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): waiting on semaphore forever...", __func__, handle, timeout); - ret = mono_os_sem_wait (&mp->exit_sem, alertable ? MONO_SEM_FLAGS_ALERTABLE : MONO_SEM_FLAGS_NONE); + ret = mono_os_sem_wait (&mp->exit_sem, alerted ? MONO_SEM_FLAGS_ALERTABLE : MONO_SEM_FLAGS_NONE); } - if (ret == -1 && errno != EINTR && errno != ETIMEDOUT) { - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): sem_timedwait failure: %s", - __func__, handle, timeout, g_strerror (errno)); - /* Should we return a failure here? */ - } - - if (ret == 0) { + if (ret == MONO_SEM_TIMEDWAIT_RET_SUCCESS) { /* Success, process has exited */ mono_os_sem_post (&mp->exit_sem); break; } - if (timeout == 0) { + if (ret == MONO_SEM_TIMEDWAIT_RET_TIMEDOUT) { MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): WAIT_TIMEOUT (timeout = 0)", __func__, handle, timeout); return WAIT_TIMEOUT; } @@ -2819,8 +2846,9 @@ process_wait (gpointer handle, guint32 timeout, gboolean alertable) return WAIT_TIMEOUT; } - if (alertable && _wapi_thread_cur_apc_pending ()) { + if (alerted && ret == MONO_SEM_TIMEDWAIT_RET_ALERTED) { MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): WAIT_IO_COMPLETION", __func__, handle, timeout); + *alerted = TRUE; return WAIT_IO_COMPLETION; } } @@ -2828,9 +2856,6 @@ process_wait (gpointer handle, guint32 timeout, gboolean alertable) /* Process must have exited */ MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): Waited successfully", __func__, handle, timeout); - ret = _wapi_handle_lock_shared_handles (); - g_assert (ret == 0); - status = mp ? mp->status : 0; if (WIFSIGNALED (status)) process_handle->exitstatus = 128 + WTERMSIG (status); @@ -2843,9 +2868,7 @@ process_wait (gpointer handle, guint32 timeout, gboolean alertable) MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): Setting pid %d signalled, exit status %d", __func__, handle, timeout, process_handle->id, process_handle->exitstatus); - _wapi_handle_set_signal_state (handle, TRUE, TRUE); - - _wapi_handle_unlock_shared_handles (); + mono_w32handle_set_signal_state (handle, TRUE, TRUE); return WAIT_OBJECT_0; } diff --git a/mono/io-layer/processes.h b/mono/io-layer/processes.h index a5ff917f4d..c4da3eceee 100644 --- a/mono/io-layer/processes.h +++ b/mono/io-layer/processes.h @@ -10,12 +10,12 @@ #ifndef _WAPI_PROCESSES_H_ #define _WAPI_PROCESSES_H_ +#include #ifdef HAVE_UNISTD_H #include #endif #include -#include #include #include @@ -130,7 +130,6 @@ struct _WapiShellExecuteInfo #define DEBUG_PROCESS 0x00000001 #define DEBUG_ONLY_THIS_PROCESS 0x00000002 -#define CREATE_SUSPENDED 0x00000004 #define DETACHED_PROCESS 0x00000008 #define CREATE_NEW_CONSOLE 0x00000010 #define NORMAL_PRIORITY_CLASS 0x00000020 diff --git a/mono/io-layer/semaphore-private.h b/mono/io-layer/semaphore-private.h index 8414f4e920..3c27eef989 100644 --- a/mono/io-layer/semaphore-private.h +++ b/mono/io-layer/semaphore-private.h @@ -13,10 +13,7 @@ #include #include -extern struct _WapiHandleOps _wapi_sem_ops; -extern struct _WapiHandleOps _wapi_namedsem_ops; - -extern void _wapi_sem_details (gpointer handle_info); +#include "wapi-private.h" /* emulate sem_t, so that we can prod the internal state more easily */ struct _WapiHandle_sem @@ -27,9 +24,11 @@ struct _WapiHandle_sem struct _WapiHandle_namedsem { + struct _WapiHandle_sem s; WapiSharedNamespace sharedns; - guint32 val; - gint32 max; }; +void +_wapi_semaphore_init (void); + #endif /* _WAPI_SEMAPHORE_PRIVATE_H_ */ diff --git a/mono/io-layer/semaphores.c b/mono/io-layer/semaphores.c index a8131fa97f..c473f4dc00 100644 --- a/mono/io-layer/semaphores.c +++ b/mono/io-layer/semaphores.c @@ -19,73 +19,89 @@ #include #include -#include #include #include #include #include +#include static void sema_signal(gpointer handle); static gboolean sema_own (gpointer handle); +static void sema_details (gpointer data); +static const gchar* sema_typename (void); +static gsize sema_typesize (void); static void namedsema_signal (gpointer handle); static gboolean namedsema_own (gpointer handle); +static void namedsema_details (gpointer data); +static const gchar* namedsema_typename (void); +static gsize namedsema_typesize (void); -struct _WapiHandleOps _wapi_sem_ops = { +static MonoW32HandleOps _wapi_sem_ops = { NULL, /* close */ sema_signal, /* signal */ sema_own, /* own */ NULL, /* is_owned */ NULL, /* special_wait */ - NULL /* prewait */ + NULL, /* prewait */ + sema_details, /* details */ + sema_typename, /* typename */ + sema_typesize, /* typesize */ }; -void _wapi_sem_details (gpointer handle_info) -{ - struct _WapiHandle_sem *sem = (struct _WapiHandle_sem *)handle_info; - - g_print ("val: %5u, max: %5d", sem->val, sem->max); -} - -struct _WapiHandleOps _wapi_namedsem_ops = { +static MonoW32HandleOps _wapi_namedsem_ops = { NULL, /* close */ namedsema_signal, /* signal */ namedsema_own, /* own */ NULL, /* is_owned */ NULL, /* special_wait */ - NULL /* prewait */ + NULL, /* prewait */ + namedsema_details, /* details */ + namedsema_typename, /* typename */ + namedsema_typesize, /* typesize */ }; -static gboolean sem_release (gpointer handle, gint32 count, gint32 *prev); -static gboolean namedsem_release (gpointer handle, gint32 count, gint32 *prev); - -static struct +void +_wapi_semaphore_init (void) { - gboolean (*release)(gpointer handle, gint32 count, gint32 *prev); -} sem_ops[WAPI_HANDLE_COUNT] = { - {NULL}, - {NULL}, - {NULL}, - {NULL}, - {sem_release}, - {NULL}, - {NULL}, - {NULL}, - {NULL}, - {NULL}, - {NULL}, - {NULL}, - {namedsem_release}, -}; + mono_w32handle_register_ops (MONO_W32HANDLE_SEM, &_wapi_sem_ops); + mono_w32handle_register_ops (MONO_W32HANDLE_NAMEDSEM, &_wapi_namedsem_ops); -static mono_once_t sem_ops_once=MONO_ONCE_INIT; + mono_w32handle_register_capabilities (MONO_W32HANDLE_SEM, + (MonoW32HandleCapability)(MONO_W32HANDLE_CAP_WAIT | MONO_W32HANDLE_CAP_SIGNAL)); + mono_w32handle_register_capabilities (MONO_W32HANDLE_NAMEDSEM, + (MonoW32HandleCapability)(MONO_W32HANDLE_CAP_WAIT | MONO_W32HANDLE_CAP_SIGNAL)); +} -static void sem_ops_init (void) +static const char* sem_handle_type_to_string (MonoW32HandleType type) { - _wapi_handle_register_capabilities (WAPI_HANDLE_SEM, - (WapiHandleCapability)(WAPI_HANDLE_CAP_WAIT | WAPI_HANDLE_CAP_SIGNAL)); - _wapi_handle_register_capabilities (WAPI_HANDLE_NAMEDSEM, - (WapiHandleCapability)(WAPI_HANDLE_CAP_WAIT | WAPI_HANDLE_CAP_SIGNAL)); + switch (type) { + case MONO_W32HANDLE_SEM: return "sem"; + case MONO_W32HANDLE_NAMEDSEM: return "named sem"; + default: + g_assert_not_reached (); + } +} + +static gboolean sem_handle_own (gpointer handle, MonoW32HandleType type) +{ + struct _WapiHandle_sem *sem_handle; + + if (!mono_w32handle_lookup (handle, type, (gpointer *)&sem_handle)) { + g_warning ("%s: error looking up %s handle %p", + __func__, sem_handle_type_to_string (type), handle); + return FALSE; + } + + MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: owning %s handle %p", + __func__, sem_handle_type_to_string (type), handle); + + sem_handle->val--; + + if (sem_handle->val == 0) + mono_w32handle_set_signal_state (handle, FALSE, FALSE); + + return TRUE; } static void sema_signal(gpointer handle) @@ -95,28 +111,7 @@ static void sema_signal(gpointer handle) static gboolean sema_own (gpointer handle) { - struct _WapiHandle_sem *sem_handle; - gboolean ok; - - ok=_wapi_lookup_handle (handle, WAPI_HANDLE_SEM, - (gpointer *)&sem_handle); - if(ok==FALSE) { - g_warning ("%s: error looking up sem handle %p", __func__, - handle); - return(FALSE); - } - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: owning sem handle %p", __func__, handle); - - sem_handle->val--; - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: sem %p val now %d", __func__, handle, sem_handle->val); - - if(sem_handle->val==0) { - _wapi_handle_set_signal_state (handle, FALSE, FALSE); - } - - return(TRUE); + return sem_handle_own (handle, MONO_W32HANDLE_SEM); } static void namedsema_signal (gpointer handle) @@ -127,165 +122,124 @@ static void namedsema_signal (gpointer handle) /* NB, always called with the shared handle lock held */ static gboolean namedsema_own (gpointer handle) { - struct _WapiHandle_namedsem *namedsem_handle; - gboolean ok; - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: owning named sem handle %p", __func__, handle); - - ok = _wapi_lookup_handle (handle, WAPI_HANDLE_NAMEDSEM, - (gpointer *)&namedsem_handle); - if (ok == FALSE) { - g_warning ("%s: error looking up named sem handle %p", - __func__, handle); - return (FALSE); - } - - namedsem_handle->val--; - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: named sem %p val now %d", __func__, handle, - namedsem_handle->val); - - if (namedsem_handle->val == 0) { - _wapi_shared_handle_set_signal_state (handle, FALSE); - } - - return (TRUE); + return sem_handle_own (handle, MONO_W32HANDLE_NAMEDSEM); } -static gpointer sem_create (WapiSecurityAttributes *security G_GNUC_UNUSED, - gint32 initial, gint32 max) + +static void sema_details (gpointer data) +{ + struct _WapiHandle_sem *sem = (struct _WapiHandle_sem *)data; + g_print ("val: %5u, max: %5d", sem->val, sem->max); +} + +static void namedsema_details (gpointer data) +{ + struct _WapiHandle_namedsem *namedsem = (struct _WapiHandle_namedsem *)data; + g_print ("val: %5u, max: %5d, name: \"%s\"", namedsem->s.val, namedsem->s.max, namedsem->sharedns.name); +} + +static const gchar* sema_typename (void) +{ + return "Semaphore"; +} + +static gsize sema_typesize (void) +{ + return sizeof (struct _WapiHandle_sem); +} + +static const gchar* namedsema_typename (void) +{ + return "N.Semaphore"; +} + +static gsize namedsema_typesize (void) +{ + return sizeof (struct _WapiHandle_namedsem); +} + +static gpointer sem_handle_create (struct _WapiHandle_sem *sem_handle, MonoW32HandleType type, gint32 initial, gint32 max) { - struct _WapiHandle_sem sem_handle = {0}; gpointer handle; int thr_ret; - - /* Need to blow away any old errors here, because code tests - * for ERROR_ALREADY_EXISTS on success (!) to see if a - * semaphore was freshly created - */ - SetLastError (ERROR_SUCCESS); - - sem_handle.val = initial; - sem_handle.max = max; - handle = _wapi_handle_new (WAPI_HANDLE_SEM, &sem_handle); - if (handle == _WAPI_HANDLE_INVALID) { - g_warning ("%s: error creating semaphore handle", __func__); + sem_handle->val = initial; + sem_handle->max = max; + + handle = mono_w32handle_new (type, sem_handle); + if (handle == INVALID_HANDLE_VALUE) { + g_warning ("%s: error creating %s handle", + __func__, sem_handle_type_to_string (type)); SetLastError (ERROR_GEN_FAILURE); - return(NULL); + return NULL; } - thr_ret = _wapi_handle_lock_handle (handle); - g_assert (thr_ret == 0); - - if (initial != 0) { - _wapi_handle_set_signal_state (handle, TRUE, FALSE); - } - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Created semaphore handle %p initial %d max %d", - __func__, handle, initial, max); - - thr_ret = _wapi_handle_unlock_handle (handle); + thr_ret = mono_w32handle_lock_handle (handle); g_assert (thr_ret == 0); - return(handle); + if (initial != 0) + mono_w32handle_set_signal_state (handle, TRUE, FALSE); + + thr_ret = mono_w32handle_unlock_handle (handle); + g_assert (thr_ret == 0); + + MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: created %s handle %p", + __func__, sem_handle_type_to_string (type), handle); + + return handle; } -static gpointer namedsem_create (WapiSecurityAttributes *security G_GNUC_UNUSED, gint32 initial, gint32 max, const gunichar2 *name G_GNUC_UNUSED) +static gpointer sem_create (gint32 initial, gint32 max) +{ + struct _WapiHandle_sem sem_handle; + MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: creating %s handle, initial %d max %d", + __func__, sem_handle_type_to_string (MONO_W32HANDLE_SEM), initial, max); + return sem_handle_create (&sem_handle, MONO_W32HANDLE_SEM, initial, max); +} + +static gpointer namedsem_create (gint32 initial, gint32 max, const gunichar2 *name) { - struct _WapiHandle_namedsem namedsem_handle = {{{0}}, 0}; gpointer handle; gchar *utf8_name; int thr_ret; - gpointer ret = NULL; - guint32 namelen; - gint32 offset; - - /* w32 seems to guarantee that opening named objects can't - * race each other - */ + + MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: creating %s handle, initial %d max %d name \"%s\"", + __func__, sem_handle_type_to_string (MONO_W32HANDLE_NAMEDSEM), initial, max, name); + + /* w32 seems to guarantee that opening named objects can't race each other */ thr_ret = _wapi_namespace_lock (); g_assert (thr_ret == 0); - - /* Need to blow away any old errors here, because code tests - * for ERROR_ALREADY_EXISTS on success (!) to see if a - * semaphore was freshly created - */ - SetLastError (ERROR_SUCCESS); utf8_name = g_utf16_to_utf8 (name, -1, NULL, NULL, NULL); - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Creating named sem [%s]", __func__, utf8_name); - offset = _wapi_search_handle_namespace (WAPI_HANDLE_NAMEDSEM, - utf8_name); - if (offset == -1) { - /* The name has already been used for a different - * object. - */ + MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Creating named sem name [%s] initial %d max %d", __func__, utf8_name, initial, max); + + handle = _wapi_search_handle_namespace (MONO_W32HANDLE_NAMEDSEM, utf8_name); + if (handle == INVALID_HANDLE_VALUE) { + /* The name has already been used for a different object. */ + handle = NULL; SetLastError (ERROR_INVALID_HANDLE); - goto cleanup; - } else if (offset != 0) { - /* Not an error, but this is how the caller is - * informed that the semaphore wasn't freshly created - */ + } else if (handle) { + /* Not an error, but this is how the caller is informed that the semaphore wasn't freshly created */ SetLastError (ERROR_ALREADY_EXISTS); - } - /* Fall through to create the semaphore handle */ - if (offset == 0) { - /* A new named semaphore, so create both the private - * and shared parts - */ - if (strlen (utf8_name) < MAX_PATH) { - namelen = strlen (utf8_name); - } else { - namelen = MAX_PATH; - } - - memcpy (&namedsem_handle.sharedns.name, utf8_name, namelen); - - namedsem_handle.val = initial; - namedsem_handle.max = max; - - handle = _wapi_handle_new (WAPI_HANDLE_NAMEDSEM, - &namedsem_handle); + /* this is used as creating a new handle */ + mono_w32handle_ref (handle); } else { - /* A new reference to an existing named semaphore, so - * just create the private part - */ - handle = _wapi_handle_new_from_offset (WAPI_HANDLE_NAMEDSEM, - offset, TRUE); - } - - if (handle == _WAPI_HANDLE_INVALID) { - g_warning ("%s: error creating named sem handle", __func__); - SetLastError (ERROR_GEN_FAILURE); - goto cleanup; - } - ret = handle; - - if (offset == 0) { - /* Set the initial state, as this is a completely new - * handle - */ - thr_ret = _wapi_handle_lock_shared_handles (); - g_assert (thr_ret == 0); - - if (initial != 0) { - _wapi_shared_handle_set_signal_state (handle, TRUE); - } - - _wapi_handle_unlock_shared_handles (); - } - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning named sem handle %p", __func__, handle); + /* A new named semaphore */ + struct _WapiHandle_namedsem namedsem_handle; + + strncpy (&namedsem_handle.sharedns.name [0], utf8_name, MAX_PATH); + namedsem_handle.sharedns.name [MAX_PATH] = '\0'; + + handle = sem_handle_create ((struct _WapiHandle_sem*) &namedsem_handle, MONO_W32HANDLE_NAMEDSEM, initial, max); + } -cleanup: g_free (utf8_name); - - _wapi_namespace_unlock (NULL); - - return (ret); + + thr_ret = _wapi_namespace_unlock (NULL); + g_assert (thr_ret == 0); + + return handle; } @@ -309,8 +263,6 @@ cleanup: */ gpointer CreateSemaphore(WapiSecurityAttributes *security G_GNUC_UNUSED, gint32 initial, gint32 max, const gunichar2 *name) { - mono_once (&sem_ops_once, sem_ops_init); - if (max <= 0) { MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: max <= 0", __func__); @@ -325,110 +277,13 @@ gpointer CreateSemaphore(WapiSecurityAttributes *security G_GNUC_UNUSED, gint32 return(NULL); } - if (name == NULL) { - return (sem_create (security, initial, max)); - } else { - return (namedsem_create (security, initial, max, name)); - } -} - -static gboolean sem_release (gpointer handle, gint32 count, gint32 *prevcount) -{ - struct _WapiHandle_sem *sem_handle; - gboolean ok; - gboolean ret=FALSE; - int thr_ret; - - ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SEM, - (gpointer *)&sem_handle); - if (ok == FALSE) { - g_warning ("%s: error looking up sem handle %p", __func__, - handle); - return(FALSE); - } - - thr_ret = _wapi_handle_lock_handle (handle); - g_assert (thr_ret == 0); - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: sem %p val %d count %d", __func__, handle, - sem_handle->val, count); - - /* Do this before checking for count overflow, because overflowing max - * is a listed technique for finding the current value + /* Need to blow away any old errors here, because code tests + * for ERROR_ALREADY_EXISTS on success (!) to see if a + * semaphore was freshly created */ - if (prevcount != NULL) { - *prevcount = sem_handle->val; - } - - /* No idea why max is signed, but thats the spec :-( */ - if (sem_handle->val + count > (guint32)sem_handle->max) { - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: sem %p max value would be exceeded: max %d current %d count %d", __func__, handle, sem_handle->max, sem_handle->val, count); + SetLastError (ERROR_SUCCESS); - goto end; - } - - sem_handle->val += count; - _wapi_handle_set_signal_state (handle, TRUE, TRUE); - - ret = TRUE; - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: sem %p val now %d", __func__, handle, sem_handle->val); - -end: - thr_ret = _wapi_handle_unlock_handle (handle); - g_assert (thr_ret == 0); - - return(ret); -} - -static gboolean namedsem_release (gpointer handle, gint32 count, - gint32 *prevcount) -{ - struct _WapiHandle_namedsem *sem_handle; - gboolean ok; - gboolean ret=FALSE; - int thr_ret; - - ok = _wapi_lookup_handle (handle, WAPI_HANDLE_NAMEDSEM, - (gpointer *)&sem_handle); - if (ok == FALSE) { - g_warning ("%s: error looking up sem handle %p", __func__, - handle); - return(FALSE); - } - - thr_ret = _wapi_handle_lock_shared_handles (); - g_assert (thr_ret == 0); - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: named sem %p val %d count %d", __func__, handle, - sem_handle->val, count); - - /* Do this before checking for count overflow, because overflowing max - * is a listed technique for finding the current value - */ - if (prevcount != NULL) { - *prevcount = sem_handle->val; - } - - /* No idea why max is signed, but thats the spec :-( */ - if (sem_handle->val + count > (guint32)sem_handle->max) { - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: named sem %p max value would be exceeded: max %d current %d count %d", __func__, handle, sem_handle->max, sem_handle->val, count); - - goto end; - } - - sem_handle->val += count; - _wapi_shared_handle_set_signal_state (handle, TRUE); - - ret = TRUE; - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: named sem %p val now %d", __func__, handle, - sem_handle->val); - -end: - _wapi_handle_unlock_shared_handles (); - - return(ret); + return name ? namedsem_create (initial, max, name) : sem_create (initial, max); } /** @@ -445,21 +300,61 @@ end: */ gboolean ReleaseSemaphore(gpointer handle, gint32 count, gint32 *prevcount) { - WapiHandleType type; - - if (handle == NULL) { + MonoW32HandleType type; + struct _WapiHandle_sem *sem_handle; + int thr_ret; + gboolean ret; + + if (!handle) { SetLastError (ERROR_INVALID_HANDLE); - return (FALSE); + return FALSE; } - - type = _wapi_handle_type (handle); - - if (sem_ops[type].release == NULL) { + + switch (type = mono_w32handle_get_type (handle)) { + case MONO_W32HANDLE_SEM: + case MONO_W32HANDLE_NAMEDSEM: + break; + default: SetLastError (ERROR_INVALID_HANDLE); - return (FALSE); + return FALSE; } - - return (sem_ops[type].release (handle, count, prevcount)); + + if (!mono_w32handle_lookup (handle, type, (gpointer *)&sem_handle)) { + g_warning ("%s: error looking up sem handle %p", __func__, handle); + return FALSE; + } + + MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: releasing %s handle %p", + __func__, sem_handle_type_to_string (type), handle); + + thr_ret = mono_w32handle_lock_handle (handle); + g_assert (thr_ret == 0); + + /* Do this before checking for count overflow, because overflowing + * max is a listed technique for finding the current value */ + if (prevcount) + *prevcount = sem_handle->val; + + /* No idea why max is signed, but thats the spec :-( */ + if (sem_handle->val + count > (guint32)sem_handle->max) { + MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: %s handle %p val %d count %d max %d, max value would be exceeded", + __func__, sem_handle_type_to_string (type), handle, sem_handle->val, count, sem_handle->max, count); + + ret = FALSE; + } else { + MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: %s handle %p val %d count %d max %d", + __func__, sem_handle_type_to_string (type), handle, sem_handle->val, count, sem_handle->max, count); + + sem_handle->val += count; + mono_w32handle_set_signal_state (handle, TRUE, TRUE); + + ret = TRUE; + } + + thr_ret = mono_w32handle_unlock_handle (handle); + g_assert (thr_ret == 0); + + return ret; } gpointer OpenSemaphore (guint32 access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED, @@ -468,11 +363,7 @@ gpointer OpenSemaphore (guint32 access G_GNUC_UNUSED, gboolean inherit G_GNUC_UN gpointer handle; gchar *utf8_name; int thr_ret; - gpointer ret = NULL; - gint32 offset; - mono_once (&sem_ops_once, sem_ops_init); - /* w32 seems to guarantee that opening named objects can't * race each other */ @@ -483,33 +374,20 @@ gpointer OpenSemaphore (guint32 access G_GNUC_UNUSED, gboolean inherit G_GNUC_UN MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Opening named sem [%s]", __func__, utf8_name); - offset = _wapi_search_handle_namespace (WAPI_HANDLE_NAMEDSEM, + handle = _wapi_search_handle_namespace (MONO_W32HANDLE_NAMEDSEM, utf8_name); - if (offset == -1) { + if (handle == INVALID_HANDLE_VALUE) { /* The name has already been used for a different * object. */ SetLastError (ERROR_INVALID_HANDLE); goto cleanup; - } else if (offset == 0) { + } else if (!handle) { /* This name doesn't exist */ SetLastError (ERROR_FILE_NOT_FOUND); /* yes, really */ goto cleanup; } - /* A new reference to an existing named semaphore, so just - * create the private part - */ - handle = _wapi_handle_new_from_offset (WAPI_HANDLE_NAMEDSEM, offset, - TRUE); - - if (handle == _WAPI_HANDLE_INVALID) { - g_warning ("%s: error opening named sem handle", __func__); - SetLastError (ERROR_GEN_FAILURE); - goto cleanup; - } - ret = handle; - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning named sem handle %p", __func__, handle); cleanup: @@ -517,5 +395,5 @@ cleanup: _wapi_namespace_unlock (NULL); - return (ret); + return handle; } diff --git a/mono/io-layer/shared.c b/mono/io-layer/shared.c index 64a8b330d4..8fb0e2703b 100644 --- a/mono/io-layer/shared.c +++ b/mono/io-layer/shared.c @@ -27,17 +27,12 @@ _wapi_shm_semaphores_init (void) mono_os_mutex_init (&noshm_sems [i]); } -void -_wapi_shm_semaphores_remove (void) -{ - /* Nothing */ -} - int _wapi_shm_sem_lock (int sem) { DEBUGLOG ("%s: locking nosem %d", __func__, sem); - return mono_os_mutex_lock (&noshm_sems[sem]); + mono_os_mutex_lock (&noshm_sems[sem]); + return 0; } int @@ -51,5 +46,6 @@ int _wapi_shm_sem_unlock (int sem) { DEBUGLOG ("%s: unlocking nosem %d", __func__, sem); - return mono_os_mutex_unlock (&noshm_sems[sem]); + mono_os_mutex_unlock (&noshm_sems[sem]); + return 0; } diff --git a/mono/io-layer/shared.h b/mono/io-layer/shared.h index 4807adc5a8..204f50661f 100644 --- a/mono/io-layer/shared.h +++ b/mono/io-layer/shared.h @@ -11,7 +11,6 @@ #define _WAPI_SHARED_H_ extern void _wapi_shm_semaphores_init (void); -extern void _wapi_shm_semaphores_remove (void); extern int _wapi_shm_sem_lock (int sem); extern int _wapi_shm_sem_trylock (int sem); extern int _wapi_shm_sem_unlock (int sem); diff --git a/mono/io-layer/socket-private.h b/mono/io-layer/socket-private.h index db210e2356..31bbfe33c8 100644 --- a/mono/io-layer/socket-private.h +++ b/mono/io-layer/socket-private.h @@ -13,7 +13,7 @@ #include #include -extern struct _WapiHandleOps _wapi_socket_ops; +#include "wapi-private.h" struct _WapiHandle_socket { @@ -24,4 +24,7 @@ struct _WapiHandle_socket int still_readable; }; +void +_wapi_socket_init (void); + #endif /* _WAPI_SOCKET_PRIVATE_H_ */ diff --git a/mono/io-layer/sockets.c b/mono/io-layer/sockets.c index 4785e1504e..05012d26fb 100644 --- a/mono/io-layer/sockets.c +++ b/mono/io-layer/sockets.c @@ -39,12 +39,12 @@ #include #include #include -#include #include #include #include #include #include +#include #include #include @@ -59,27 +59,33 @@ static guint32 in_cleanup = 0; static void socket_close (gpointer handle, gpointer data); +static void socket_details (gpointer data); +static const gchar* socket_typename (void); +static gsize socket_typesize (void); -struct _WapiHandleOps _wapi_socket_ops = { +static MonoW32HandleOps _wapi_socket_ops = { socket_close, /* close */ NULL, /* signal */ NULL, /* own */ NULL, /* is_owned */ NULL, /* special_wait */ - NULL /* prewait */ + NULL, /* prewait */ + socket_details, /* details */ + socket_typename, /* typename */ + socket_typesize, /* typesize */ }; -static mono_once_t socket_ops_once=MONO_ONCE_INIT; - -static void socket_ops_init (void) +void +_wapi_socket_init (void) { - /* No capabilities to register */ + mono_w32handle_register_ops (MONO_W32HANDLE_SOCKET, &_wapi_socket_ops); } static void socket_close (gpointer handle, gpointer data) { int ret; struct _WapiHandle_socket *socket_handle = (struct _WapiHandle_socket *)data; + MonoThreadInfo *info = mono_thread_info_current (); MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: closing socket handle %p", __func__, handle); @@ -91,7 +97,7 @@ static void socket_close (gpointer handle, gpointer data) do { ret = close (GPOINTER_TO_UINT(handle)); } while (ret == -1 && errno == EINTR && - !_wapi_thread_cur_apc_pending ()); + !mono_thread_info_is_interrupt_state (info)); if (ret == -1) { gint errnum = errno; @@ -105,11 +111,28 @@ static void socket_close (gpointer handle, gpointer data) socket_handle->saved_error = 0; } -static gboolean -cleanup_close (gpointer handle, gpointer data) +static void socket_details (gpointer data) { - _wapi_handle_ops_close (handle, NULL); - return TRUE; + /* FIXME: do something */ +} + +static const gchar* socket_typename (void) +{ + return "Socket"; +} + +static gsize socket_typesize (void) +{ + return sizeof (struct _WapiHandle_socket); +} + +static gboolean +cleanup_close (gpointer handle, gpointer data, gpointer user_data) +{ + if (mono_w32handle_get_type (handle) == MONO_W32HANDLE_SOCKET) + mono_w32handle_ops_close (handle, data); + + return FALSE; } void _wapi_cleanup_networking(void) @@ -117,7 +140,7 @@ void _wapi_cleanup_networking(void) MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: cleaning up", __func__); in_cleanup = 1; - _wapi_handle_foreach (WAPI_HANDLE_SOCKET, cleanup_close, NULL); + mono_w32handle_foreach (cleanup_close, NULL); in_cleanup = 0; } @@ -135,12 +158,12 @@ int closesocket(guint32 fd) { gpointer handle = GUINT_TO_POINTER (fd); - if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { + if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { WSASetLastError (WSAENOTSOCK); return(0); } - _wapi_handle_unref (handle); + mono_w32handle_unref (handle); return(0); } @@ -152,18 +175,19 @@ guint32 _wapi_accept(guint32 fd, struct sockaddr *addr, socklen_t *addrlen) struct _WapiHandle_socket new_socket_handle = {0}; gboolean ok; int new_fd; + MonoThreadInfo *info = mono_thread_info_current (); if (addr != NULL && *addrlen < sizeof(struct sockaddr)) { WSASetLastError (WSAEFAULT); return(INVALID_SOCKET); } - if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { + if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { WSASetLastError (WSAENOTSOCK); return(INVALID_SOCKET); } - ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET, + ok = mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, (gpointer *)&socket_handle); if (ok == FALSE) { g_warning ("%s: error looking up socket handle %p", @@ -175,7 +199,7 @@ guint32 _wapi_accept(guint32 fd, struct sockaddr *addr, socklen_t *addrlen) do { new_fd = accept (fd, addr, addrlen); } while (new_fd == -1 && errno == EINTR && - !_wapi_thread_cur_apc_pending()); + !mono_thread_info_is_interrupt_state (info)); if (new_fd == -1) { gint errnum = errno; @@ -187,7 +211,7 @@ guint32 _wapi_accept(guint32 fd, struct sockaddr *addr, socklen_t *addrlen) return(INVALID_SOCKET); } - if (new_fd >= _wapi_fd_reserve) { + if (new_fd >= mono_w32handle_fd_reserve) { MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: File descriptor is too big", __func__); WSASetLastError (WSASYSCALLFAILURE); @@ -202,9 +226,9 @@ guint32 _wapi_accept(guint32 fd, struct sockaddr *addr, socklen_t *addrlen) new_socket_handle.protocol = socket_handle->protocol; new_socket_handle.still_readable = 1; - new_handle = _wapi_handle_new_fd (WAPI_HANDLE_SOCKET, new_fd, + new_handle = mono_w32handle_new_fd (MONO_W32HANDLE_SOCKET, new_fd, &new_socket_handle); - if(new_handle == _WAPI_HANDLE_INVALID) { + if(new_handle == INVALID_HANDLE_VALUE) { g_warning ("%s: error creating socket handle", __func__); WSASetLastError (ERROR_GEN_FAILURE); return(INVALID_SOCKET); @@ -221,7 +245,7 @@ int _wapi_bind(guint32 fd, struct sockaddr *my_addr, socklen_t addrlen) gpointer handle = GUINT_TO_POINTER (fd); int ret; - if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { + if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { WSASetLastError (WSAENOTSOCK); return(SOCKET_ERROR); } @@ -245,8 +269,9 @@ int _wapi_connect(guint32 fd, const struct sockaddr *serv_addr, struct _WapiHandle_socket *socket_handle; gboolean ok; gint errnum; - - if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { + MonoThreadInfo *info = mono_thread_info_current (); + + if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { WSASetLastError (WSAENOTSOCK); return(SOCKET_ERROR); } @@ -275,8 +300,8 @@ int _wapi_connect(guint32 fd, const struct sockaddr *serv_addr, * But don't do this for EWOULDBLOCK (bug 317315) */ if (errnum != WSAEWOULDBLOCK) { - ok = _wapi_lookup_handle (handle, - WAPI_HANDLE_SOCKET, + ok = mono_w32handle_lookup (handle, + MONO_W32HANDLE_SOCKET, (gpointer *)&socket_handle); if (ok == FALSE) { /* ECONNRESET means the socket was closed by another thread */ @@ -293,7 +318,7 @@ int _wapi_connect(guint32 fd, const struct sockaddr *serv_addr, fds.fd = fd; fds.events = MONO_POLLOUT; while (mono_poll (&fds, 1, -1) == -1 && - !_wapi_thread_cur_apc_pending ()) { + !mono_thread_info_is_interrupt_state (info)) { if (errno != EINTR) { errnum = errno_to_WSA (errno, __func__); @@ -321,7 +346,7 @@ int _wapi_connect(guint32 fd, const struct sockaddr *serv_addr, errnum = errno_to_WSA (so_error, __func__); /* Need to save this socket error */ - ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET, + ok = mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, (gpointer *)&socket_handle); if (ok == FALSE) { g_warning ("%s: error looking up socket handle %p", __func__, handle); @@ -345,7 +370,7 @@ int _wapi_getpeername(guint32 fd, struct sockaddr *name, socklen_t *namelen) gpointer handle = GUINT_TO_POINTER (fd); int ret; - if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { + if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { WSASetLastError (WSAENOTSOCK); return(SOCKET_ERROR); } @@ -370,7 +395,7 @@ int _wapi_getsockname(guint32 fd, struct sockaddr *name, socklen_t *namelen) gpointer handle = GUINT_TO_POINTER (fd); int ret; - if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { + if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { WSASetLastError (WSAENOTSOCK); return(SOCKET_ERROR); } @@ -400,7 +425,7 @@ int _wapi_getsockopt(guint32 fd, int level, int optname, void *optval, struct _WapiHandle_socket *socket_handle; gboolean ok; - if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { + if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { WSASetLastError (WSAENOTSOCK); return(SOCKET_ERROR); } @@ -431,7 +456,7 @@ int _wapi_getsockopt(guint32 fd, int level, int optname, void *optval, } if (optname == SO_ERROR) { - ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET, + ok = mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, (gpointer *)&socket_handle); if (ok == FALSE) { g_warning ("%s: error looking up socket handle %p", @@ -459,7 +484,7 @@ int _wapi_listen(guint32 fd, int backlog) gpointer handle = GUINT_TO_POINTER (fd); int ret; - if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { + if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { WSASetLastError (WSAENOTSOCK); return(SOCKET_ERROR); } @@ -490,8 +515,9 @@ int _wapi_recvfrom(guint32 fd, void *buf, size_t len, int recv_flags, struct _WapiHandle_socket *socket_handle; gboolean ok; int ret; + MonoThreadInfo *info = mono_thread_info_current (); - if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { + if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { WSASetLastError (WSAENOTSOCK); return(SOCKET_ERROR); } @@ -499,7 +525,7 @@ int _wapi_recvfrom(guint32 fd, void *buf, size_t len, int recv_flags, do { ret = recvfrom (fd, buf, len, recv_flags, from, fromlen); } while (ret == -1 && errno == EINTR && - !_wapi_thread_cur_apc_pending ()); + !mono_thread_info_is_interrupt_state (info)); if (ret == 0 && len > 0) { /* According to the Linux man page, recvfrom only @@ -520,7 +546,7 @@ int _wapi_recvfrom(guint32 fd, void *buf, size_t len, int recv_flags, * still_readable != 1 then shutdown * (SHUT_RD|SHUT_RDWR) has been called locally. */ - ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET, + ok = mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, (gpointer *)&socket_handle); if (ok == FALSE || socket_handle->still_readable != 1) { ret = -1; @@ -547,8 +573,9 @@ _wapi_recvmsg(guint32 fd, struct msghdr *msg, int recv_flags) struct _WapiHandle_socket *socket_handle; gboolean ok; int ret; + MonoThreadInfo *info = mono_thread_info_current (); - if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { + if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { WSASetLastError (WSAENOTSOCK); return(SOCKET_ERROR); } @@ -556,11 +583,11 @@ _wapi_recvmsg(guint32 fd, struct msghdr *msg, int recv_flags) do { ret = recvmsg (fd, msg, recv_flags); } while (ret == -1 && errno == EINTR && - !_wapi_thread_cur_apc_pending ()); + !mono_thread_info_is_interrupt_state (info)); if (ret == 0) { /* see _wapi_recvfrom */ - ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET, + ok = mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, (gpointer *)&socket_handle); if (ok == FALSE || socket_handle->still_readable != 1) { ret = -1; @@ -584,8 +611,9 @@ int _wapi_send(guint32 fd, const void *msg, size_t len, int send_flags) { gpointer handle = GUINT_TO_POINTER (fd); int ret; + MonoThreadInfo *info = mono_thread_info_current (); - if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { + if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { WSASetLastError (WSAENOTSOCK); return(SOCKET_ERROR); } @@ -593,7 +621,7 @@ int _wapi_send(guint32 fd, const void *msg, size_t len, int send_flags) do { ret = send (fd, msg, len, send_flags); } while (ret == -1 && errno == EINTR && - !_wapi_thread_cur_apc_pending ()); + !mono_thread_info_is_interrupt_state (info)); if (ret == -1) { gint errnum = errno; @@ -621,8 +649,9 @@ int _wapi_sendto(guint32 fd, const void *msg, size_t len, int send_flags, { gpointer handle = GUINT_TO_POINTER (fd); int ret; + MonoThreadInfo *info = mono_thread_info_current (); - if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { + if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { WSASetLastError (WSAENOTSOCK); return(SOCKET_ERROR); } @@ -630,7 +659,7 @@ int _wapi_sendto(guint32 fd, const void *msg, size_t len, int send_flags, do { ret = sendto (fd, msg, len, send_flags, to, tolen); } while (ret == -1 && errno == EINTR && - !_wapi_thread_cur_apc_pending ()); + !mono_thread_info_is_interrupt_state (info)); if (ret == -1) { gint errnum = errno; @@ -649,8 +678,9 @@ _wapi_sendmsg(guint32 fd, const struct msghdr *msg, int send_flags) { gpointer handle = GUINT_TO_POINTER (fd); int ret; + MonoThreadInfo *info = mono_thread_info_current (); - if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { + if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { WSASetLastError (WSAENOTSOCK); return(SOCKET_ERROR); } @@ -658,7 +688,7 @@ _wapi_sendmsg(guint32 fd, const struct msghdr *msg, int send_flags) do { ret = sendmsg (fd, msg, send_flags); } while (ret == -1 && errno == EINTR && - !_wapi_thread_cur_apc_pending ()); + !mono_thread_info_is_interrupt_state (info)); if (ret == -1) { gint errnum = errno; @@ -684,7 +714,7 @@ int _wapi_setsockopt(guint32 fd, int level, int optname, #endif struct timeval tv; - if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { + if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { WSASetLastError (WSAENOTSOCK); return(SOCKET_ERROR); } @@ -747,14 +777,14 @@ int _wapi_shutdown(guint32 fd, int how) gpointer handle = GUINT_TO_POINTER (fd); int ret; - if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { + if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { WSASetLastError (WSAENOTSOCK); return(SOCKET_ERROR); } if (how == SHUT_RD || how == SHUT_RDWR) { - ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET, + ok = mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, (gpointer *)&socket_handle); if (ok == FALSE) { g_warning ("%s: error looking up socket handle %p", @@ -811,9 +841,9 @@ guint32 _wapi_socket(int domain, int type, int protocol, void *unused, return(INVALID_SOCKET); } - if (fd >= _wapi_fd_reserve) { + if (fd >= mono_w32handle_fd_reserve) { MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: File descriptor is too big (%d >= %d)", - __func__, fd, _wapi_fd_reserve); + __func__, fd, mono_w32handle_fd_reserve); WSASetLastError (WSASYSCALLFAILURE); close (fd); @@ -856,10 +886,8 @@ guint32 _wapi_socket(int domain, int type, int protocol, void *unused, } - mono_once (&socket_ops_once, socket_ops_init); - - handle = _wapi_handle_new_fd (WAPI_HANDLE_SOCKET, fd, &socket_handle); - if (handle == _WAPI_HANDLE_INVALID) { + handle = mono_w32handle_new_fd (MONO_W32HANDLE_SOCKET, fd, &socket_handle); + if (handle == INVALID_HANDLE_VALUE) { g_warning ("%s: error creating socket handle", __func__); WSASetLastError (WSASYSCALLFAILURE); close (fd); @@ -878,7 +906,7 @@ static gboolean socket_disconnect (guint32 fd) gpointer handle = GUINT_TO_POINTER (fd); int newsock, ret; - ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET, + ok = mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, (gpointer *)&socket_handle); if (ok == FALSE) { g_warning ("%s: error looking up socket handle %p", __func__, @@ -947,6 +975,7 @@ static gboolean wapi_disconnectex (guint32 fd, WapiOverlapped *overlapped, static gint wapi_sendfile (guint32 socket, gpointer fd, guint32 bytes_to_write, guint32 bytes_per_send, guint32 flags) { + MonoThreadInfo *info = mono_thread_info_current (); #if defined(HAVE_SENDFILE) && (defined(__linux__) || defined(DARWIN)) gint file = GPOINTER_TO_INT (fd); gint n; @@ -969,7 +998,7 @@ wapi_sendfile (guint32 socket, gpointer fd, guint32 bytes_to_write, guint32 byte /* TODO: Might not send the entire file for non-blocking sockets */ res = sendfile (file, socket, 0, &statbuf.st_size, NULL, 0); #endif - } while (res != -1 && errno == EINTR && !_wapi_thread_cur_apc_pending ()); + } while (res != -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); if (res == -1) { errnum = errno; errnum = errno_to_WSA (errnum, __func__); @@ -986,7 +1015,7 @@ wapi_sendfile (guint32 socket, gpointer fd, guint32 bytes_to_write, guint32 byte do { do { n = read (file, buffer, SF_BUFFER_SIZE); - } while (n == -1 && errno == EINTR && !_wapi_thread_cur_apc_pending ()); + } while (n == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); if (n == -1) break; if (n == 0) { @@ -995,8 +1024,8 @@ wapi_sendfile (guint32 socket, gpointer fd, guint32 bytes_to_write, guint32 byte } do { n = send (socket, buffer, n, 0); /* short sends? enclose this in a loop? */ - } while (n == -1 && errno == EINTR && !_wapi_thread_cur_apc_pending ()); - } while (n != -1 && errno == EINTR && !_wapi_thread_cur_apc_pending ()); + } while (n == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); + } while (n != -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); if (n == -1) { gint errnum = errno; @@ -1017,7 +1046,7 @@ TransmitFile (guint32 socket, gpointer file, guint32 bytes_to_write, guint32 byt gpointer sock = GUINT_TO_POINTER (socket); gint ret; - if (_wapi_handle_type (sock) != WAPI_HANDLE_SOCKET) { + if (mono_w32handle_get_type (sock) != MONO_W32HANDLE_SOCKET) { WSASetLastError (WSAENOTSOCK); return FALSE; } @@ -1066,7 +1095,7 @@ WSAIoctl (guint32 fd, gint32 command, int ret; gchar *buffer = NULL; - if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { + if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { WSASetLastError (WSAENOTSOCK); return SOCKET_ERROR; } @@ -1204,7 +1233,7 @@ int ioctlsocket(guint32 fd, unsigned long command, gpointer arg) gpointer handle = GUINT_TO_POINTER (fd); int ret; - if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { + if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { WSASetLastError (WSAENOTSOCK); return(SOCKET_ERROR); } @@ -1275,6 +1304,7 @@ int _wapi_select(int nfds G_GNUC_UNUSED, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) { int ret, maxfd; + MonoThreadInfo *info = mono_thread_info_current (); for (maxfd = FD_SETSIZE-1; maxfd >= 0; maxfd--) { if ((readfds && FD_ISSET (maxfd, readfds)) || @@ -1293,7 +1323,7 @@ int _wapi_select(int nfds G_GNUC_UNUSED, fd_set *readfds, fd_set *writefds, ret = select(maxfd + 1, readfds, writefds, exceptfds, timeout); } while (ret == -1 && errno == EINTR && - !_wapi_thread_cur_apc_pending ()); + !mono_thread_info_is_interrupt_state (info)); if (ret == -1) { gint errnum = errno; @@ -1316,7 +1346,7 @@ void _wapi_FD_CLR(guint32 fd, fd_set *set) return; } - if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { + if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { WSASetLastError (WSAENOTSOCK); return; } @@ -1333,7 +1363,7 @@ int _wapi_FD_ISSET(guint32 fd, fd_set *set) return(0); } - if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { + if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { WSASetLastError (WSAENOTSOCK); return(0); } @@ -1350,7 +1380,7 @@ void _wapi_FD_SET(guint32 fd, fd_set *set) return; } - if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { + if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { WSASetLastError (WSAENOTSOCK); return; } diff --git a/mono/io-layer/thread-private.h b/mono/io-layer/thread-private.h deleted file mode 100644 index 3cf5535c5b..0000000000 --- a/mono/io-layer/thread-private.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * thread-private.h: Private definitions for thread handles - * - * Author: - * Dick Porter (dick@ximian.com) - * - * (C) 2002 Ximian, Inc. - */ - -#ifndef _WAPI_THREAD_PRIVATE_H_ -#define _WAPI_THREAD_PRIVATE_H_ - -#include -#include -#include - -/* There doesn't seem to be a defined symbol for this */ -#define _WAPI_THREAD_CURRENT (gpointer)0xFFFFFFFE - -extern struct _WapiHandleOps _wapi_thread_ops; - -struct _WapiHandle_thread -{ - pthread_t id; - GPtrArray *owned_mutexes; -}; - -typedef struct _WapiHandle_thread WapiHandle_thread; - -extern gboolean _wapi_thread_cur_apc_pending (void); -extern void _wapi_thread_own_mutex (gpointer mutex); -extern void _wapi_thread_disown_mutex (gpointer mutex); -extern void _wapi_thread_cleanup (void); - -#endif /* _WAPI_THREAD_PRIVATE_H_ */ diff --git a/mono/io-layer/threads.h b/mono/io-layer/threads.h deleted file mode 100644 index a00569d1a9..0000000000 --- a/mono/io-layer/threads.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * threads.h: Thread handles - * - * Author: - * Dick Porter (dick@ximian.com) - * - * (C) 2002 Ximian, Inc. - */ - -#ifndef _WAPI_THREADS_H_ -#define _WAPI_THREADS_H_ - -#include - -#include -#include -#include -#include -#include - -G_BEGIN_DECLS - -#define STILL_ACTIVE STATUS_PENDING - -#define THREAD_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|0x3ff) - -typedef guint32 (*WapiThreadStart)(gpointer); - -gpointer wapi_create_thread_handle (void); -void wapi_thread_handle_set_exited (gpointer handle, guint32 exitstatus); -void wapi_ref_thread_handle (gpointer handle); -gpointer wapi_get_current_thread_handle (void); - -char* wapi_current_thread_desc (void); - -extern gint32 GetThreadPriority (gpointer handle); -extern gboolean SetThreadPriority (gpointer handle, gint32 priority); - -G_END_DECLS -#endif /* _WAPI_THREADS_H_ */ diff --git a/mono/io-layer/uglify.h b/mono/io-layer/uglify.h index aa847569cb..5176da07ea 100644 --- a/mono/io-layer/uglify.h +++ b/mono/io-layer/uglify.h @@ -50,7 +50,6 @@ typedef WapiSecurityAttributes SECURITY_ATTRIBUTES; typedef WapiSecurityAttributes *LPSECURITY_ATTRIBUTES; typedef WapiOverlapped *LPOVERLAPPED; typedef WapiOverlappedCB LPOVERLAPPED_COMPLETION_ROUTINE; -typedef WapiThreadStart LPTHREAD_START_ROUTINE; typedef WapiFileTime FILETIME; typedef WapiFileTime *LPFILETIME; typedef WapiSystemTime SYSTEMTIME; diff --git a/mono/io-layer/wait.c b/mono/io-layer/wait.c index 149412902f..448232dff9 100644 --- a/mono/io-layer/wait.c +++ b/mono/io-layer/wait.c @@ -13,55 +13,8 @@ #include #include -#include #include -#include -#include -#include - -static gboolean own_if_signalled(gpointer handle) -{ - gboolean ret = FALSE; - - if (_WAPI_SHARED_HANDLE (_wapi_handle_type (handle))) { - if (_wapi_handle_trylock_shared_handles () == EBUSY) { - return (FALSE); - } - } - - if (_wapi_handle_issignalled (handle)) { - _wapi_handle_ops_own (handle); - ret = TRUE; - } - - if (_WAPI_SHARED_HANDLE (_wapi_handle_type (handle))) { - _wapi_handle_unlock_shared_handles (); - } - - return(ret); -} - -static gboolean own_if_owned(gpointer handle) -{ - gboolean ret = FALSE; - - if (_WAPI_SHARED_HANDLE (_wapi_handle_type (handle))) { - if (_wapi_handle_trylock_shared_handles () == EBUSY) { - return (FALSE); - } - } - - if (_wapi_handle_ops_isowned (handle)) { - _wapi_handle_ops_own (handle); - ret = TRUE; - } - - if (_WAPI_SHARED_HANDLE (_wapi_handle_type (handle))) { - _wapi_handle_unlock_shared_handles (); - } - - return(ret); -} +#include /** * WaitForSingleObjectEx: @@ -82,149 +35,21 @@ static gboolean own_if_owned(gpointer handle) * @handle's state is still not signalled. %WAIT_FAILED - an error * occurred. %WAIT_IO_COMPLETION - the wait was ended by an APC. */ -guint32 WaitForSingleObjectEx(gpointer handle, guint32 timeout, - gboolean alertable) +guint32 WaitForSingleObjectEx(gpointer handle, guint32 timeout, gboolean alertable) { - guint32 ret, waited; - int thr_ret; - gboolean apc_pending = FALSE; - gpointer current_thread = wapi_get_current_thread_handle (); - gint64 wait_start, timeout_in_ticks; - - if (current_thread == NULL) { - SetLastError (ERROR_INVALID_HANDLE); - return(WAIT_FAILED); - } + MonoW32HandleWaitRet ret; - if (handle == _WAPI_THREAD_CURRENT) { - handle = wapi_get_current_thread_handle (); - if (handle == NULL) { - SetLastError (ERROR_INVALID_HANDLE); - return(WAIT_FAILED); - } - } - - if ((GPOINTER_TO_UINT (handle) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) { - SetLastError (ERROR_INVALID_HANDLE); - return(WAIT_FAILED); - } - - if (_wapi_handle_test_capabilities (handle, - WAPI_HANDLE_CAP_WAIT) == FALSE) { - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p can't be waited for", __func__, - handle); - - return(WAIT_FAILED); - } - - _wapi_handle_ops_prewait (handle); - - if (_wapi_handle_test_capabilities (handle, WAPI_HANDLE_CAP_SPECIAL_WAIT) == TRUE) { - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p has special wait", __func__, handle); - - ret = _wapi_handle_ops_special_wait (handle, timeout, alertable); - - if (alertable && _wapi_thread_cur_apc_pending ()) - ret = WAIT_IO_COMPLETION; - - return ret; - } - - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: locking handle %p", __func__, handle); - - thr_ret = _wapi_handle_lock_handle (handle); - g_assert (thr_ret == 0); - - if (_wapi_handle_test_capabilities (handle, - WAPI_HANDLE_CAP_OWN) == TRUE) { - if (own_if_owned (handle) == TRUE) { - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p already owned", __func__, - handle); - ret = WAIT_OBJECT_0; - goto done; - } - } - - if (own_if_signalled (handle) == TRUE) { - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p already signalled", __func__, - handle); - - ret=WAIT_OBJECT_0; - goto done; - } - - if (timeout == 0) { - ret = WAIT_TIMEOUT; - goto done; - } - - if (timeout != INFINITE) { - wait_start = mono_100ns_ticks (); - timeout_in_ticks = (gint64)timeout * 10 * 1000; //can't overflow as timeout is 32bits - } - - do { - /* Check before waiting on the condition, just in case - */ - _wapi_handle_ops_prewait (handle); - - if (own_if_signalled (handle)) { - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p signalled", __func__, - handle); - - ret = WAIT_OBJECT_0; - goto done; - } - - if (timeout == INFINITE) { - waited = _wapi_handle_timedwait_signal_handle (handle, INFINITE, alertable, FALSE, &apc_pending); - } else { - gint64 elapsed = mono_100ns_ticks () - wait_start; - if (elapsed >= timeout_in_ticks) { - ret = WAIT_TIMEOUT; - goto done; - } - - waited = _wapi_handle_timedwait_signal_handle (handle, (timeout_in_ticks - elapsed) / 10 / 1000, alertable, FALSE, &apc_pending); - } - - if(waited==0 && !apc_pending) { - /* Condition was signalled, so hopefully - * handle is signalled now. (It might not be - * if someone else got in before us.) - */ - if (own_if_signalled (handle)) { - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p signalled", __func__, - handle); - - ret=WAIT_OBJECT_0; - goto done; - } - - /* Better luck next time */ - } - } while(waited == 0 && !apc_pending); - - /* Timeout or other error */ - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: wait on handle %p error: %s", __func__, handle, - strerror (waited)); - - ret = apc_pending ? WAIT_IO_COMPLETION : WAIT_TIMEOUT; - -done: - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unlocking handle %p", __func__, handle); - - thr_ret = _wapi_handle_unlock_handle (handle); - g_assert (thr_ret == 0); - - return(ret); -} - -guint32 WaitForSingleObject(gpointer handle, guint32 timeout) -{ - return WaitForSingleObjectEx (handle, timeout, FALSE); + ret = mono_w32handle_wait_one (handle, timeout, alertable); + if (ret == MONO_W32HANDLE_WAIT_RET_SUCCESS_0) + return WAIT_OBJECT_0; + else if (ret == MONO_W32HANDLE_WAIT_RET_ALERTED) + return WAIT_IO_COMPLETION; + else if (ret == MONO_W32HANDLE_WAIT_RET_TIMEOUT) + return WAIT_TIMEOUT; + else if (ret == MONO_W32HANDLE_WAIT_RET_FAILED) + return WAIT_FAILED; + else + g_error ("%s: unknown ret value %d", __func__, ret); } @@ -266,171 +91,19 @@ guint32 WaitForSingleObject(gpointer handle, guint32 timeout) guint32 SignalObjectAndWait(gpointer signal_handle, gpointer wait, guint32 timeout, gboolean alertable) { - guint32 ret = 0, waited; - int thr_ret; - gboolean apc_pending = FALSE; - gpointer current_thread = wapi_get_current_thread_handle (); - gint64 wait_start, timeout_in_ticks; - - if (current_thread == NULL) { - SetLastError (ERROR_INVALID_HANDLE); - return(WAIT_FAILED); - } + MonoW32HandleWaitRet ret; - if (signal_handle == _WAPI_THREAD_CURRENT) { - signal_handle = wapi_get_current_thread_handle (); - if (signal_handle == NULL) { - SetLastError (ERROR_INVALID_HANDLE); - return(WAIT_FAILED); - } - } - - if (wait == _WAPI_THREAD_CURRENT) { - wait = wapi_get_current_thread_handle (); - if (wait == NULL) { - SetLastError (ERROR_INVALID_HANDLE); - return(WAIT_FAILED); - } - } - - if ((GPOINTER_TO_UINT (signal_handle) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) { - SetLastError (ERROR_INVALID_HANDLE); - return(WAIT_FAILED); - } - - if ((GPOINTER_TO_UINT (wait) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) { - SetLastError (ERROR_INVALID_HANDLE); - return(WAIT_FAILED); - } - - if (_wapi_handle_test_capabilities (signal_handle, - WAPI_HANDLE_CAP_SIGNAL)==FALSE) { - return(WAIT_FAILED); - } - - if (_wapi_handle_test_capabilities (wait, - WAPI_HANDLE_CAP_WAIT)==FALSE) { - return(WAIT_FAILED); - } - - _wapi_handle_ops_prewait (wait); - - if (_wapi_handle_test_capabilities (wait, WAPI_HANDLE_CAP_SPECIAL_WAIT) == TRUE) { - g_warning ("%s: handle %p has special wait, implement me!!", - __func__, wait); - - return (WAIT_FAILED); - } - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: locking handle %p", __func__, wait); - - thr_ret = _wapi_handle_lock_handle (wait); - g_assert (thr_ret == 0); - - _wapi_handle_ops_signal (signal_handle); - - if (_wapi_handle_test_capabilities (wait, WAPI_HANDLE_CAP_OWN)==TRUE) { - if (own_if_owned (wait)) { - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p already owned", __func__, - wait); - ret = WAIT_OBJECT_0; - goto done; - } - } - - if (own_if_signalled (wait)) { - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p already signalled", __func__, wait); - - ret = WAIT_OBJECT_0; - goto done; - } - - if (timeout != INFINITE) { - wait_start = mono_100ns_ticks (); - timeout_in_ticks = (gint64)timeout * 10 * 1000; //can't overflow as timeout is 32bits - } - do { - /* Check before waiting on the condition, just in case - */ - _wapi_handle_ops_prewait (wait); - - if (own_if_signalled (wait)) { - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p signalled", __func__, wait); - - ret = WAIT_OBJECT_0; - goto done; - } - - if (timeout == INFINITE) { - waited = _wapi_handle_timedwait_signal_handle (wait, INFINITE, alertable, FALSE, &apc_pending); - } else { - gint64 elapsed = mono_100ns_ticks () - wait_start; - if (elapsed >= timeout_in_ticks) { - ret = WAIT_TIMEOUT; - goto done; - } - - waited = _wapi_handle_timedwait_signal_handle (wait, (timeout_in_ticks - elapsed) / 10 / 1000, alertable, FALSE, &apc_pending); - } - - if (waited==0 && !apc_pending) { - /* Condition was signalled, so hopefully - * handle is signalled now. (It might not be - * if someone else got in before us.) - */ - if (own_if_signalled (wait)) { - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p signalled", __func__, - wait); - - ret = WAIT_OBJECT_0; - goto done; - } - - /* Better luck next time */ - } - } while(waited == 0 && !apc_pending); - - /* Timeout or other error */ - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: wait on handle %p error: %s", __func__, wait, strerror (ret)); - - ret = apc_pending ? WAIT_IO_COMPLETION : WAIT_TIMEOUT; - -done: - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unlocking handle %p", __func__, wait); - - thr_ret = _wapi_handle_unlock_handle (wait); - g_assert (thr_ret == 0); - - return(ret); -} - -static gboolean test_and_own (guint32 numobjects, gpointer *handles, - gboolean waitall, guint32 *count, - guint32 *lowest) -{ - gboolean done; - int i; - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: locking handles", __func__); - - done = _wapi_handle_count_signalled_handles (numobjects, handles, - waitall, count, lowest); - if (done == TRUE) { - if (waitall == TRUE) { - for (i = 0; i < numobjects; i++) { - own_if_signalled (handles[i]); - } - } else { - own_if_signalled (handles[*lowest]); - } - } - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unlocking handles", __func__); - - _wapi_handle_unlock_handles (numobjects, handles); - - return(done); + ret = mono_w32handle_signal_and_wait (signal_handle, wait, timeout, alertable); + if (ret == MONO_W32HANDLE_WAIT_RET_SUCCESS_0) + return WAIT_OBJECT_0; + else if (ret == MONO_W32HANDLE_WAIT_RET_ALERTED) + return WAIT_IO_COMPLETION; + else if (ret == MONO_W32HANDLE_WAIT_RET_TIMEOUT) + return WAIT_TIMEOUT; + else if (ret == MONO_W32HANDLE_WAIT_RET_FAILED) + return WAIT_FAILED; + else + g_error ("%s: unknown ret value %d", __func__, ret); } /** @@ -467,231 +140,18 @@ guint32 WaitForMultipleObjectsEx(guint32 numobjects, gpointer *handles, gboolean waitall, guint32 timeout, gboolean alertable) { - gboolean duplicate = FALSE, bogustype = FALSE, done; - guint32 count, lowest; - guint i; - guint32 ret; - int thr_ret; - gpointer current_thread = wapi_get_current_thread_handle (); - guint32 retval; - gboolean poll; - gpointer sorted_handles [MAXIMUM_WAIT_OBJECTS]; - gboolean apc_pending = FALSE; - gint64 wait_start, timeout_in_ticks; - - if (current_thread == NULL) { - SetLastError (ERROR_INVALID_HANDLE); - return(WAIT_FAILED); - } - - if (numobjects > MAXIMUM_WAIT_OBJECTS) { - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Too many handles: %d", __func__, numobjects); + MonoW32HandleWaitRet ret; - return(WAIT_FAILED); - } - - if (numobjects == 1) { - return WaitForSingleObjectEx (handles [0], timeout, alertable); - } - - /* Check for duplicates */ - for (i = 0; i < numobjects; i++) { - if (handles[i] == _WAPI_THREAD_CURRENT) { - handles[i] = wapi_get_current_thread_handle (); - - if (handles[i] == NULL) { - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Handle %d bogus", __func__, i); - - bogustype = TRUE; - break; - } - } - - if ((GPOINTER_TO_UINT (handles[i]) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) { - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Handle %d pseudo process", __func__, - i); - - bogustype = TRUE; - break; - } - - if (_wapi_handle_test_capabilities (handles[i], WAPI_HANDLE_CAP_WAIT) == FALSE) { - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Handle %p can't be waited for", - __func__, handles[i]); - - bogustype = TRUE; - break; - } - - sorted_handles [i] = handles [i]; - _wapi_handle_ops_prewait (handles[i]); - } - - qsort (sorted_handles, numobjects, sizeof (gpointer), g_direct_equal); - for (i = 1; i < numobjects; i++) { - if (sorted_handles [i - 1] == sorted_handles [i]) { - duplicate = TRUE; - break; - } - } - - if (duplicate == TRUE) { - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Returning due to duplicates", __func__); - - return(WAIT_FAILED); - } - - if (bogustype == TRUE) { - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Returning due to bogus type", __func__); - - return(WAIT_FAILED); - } - - poll = FALSE; - for (i = 0; i < numobjects; ++i) - if (_wapi_handle_type (handles [i]) == WAPI_HANDLE_PROCESS || _WAPI_SHARED_HANDLE (_wapi_handle_type (handles[i]))) - /* Can't wait for a process handle + another handle without polling */ - poll = TRUE; - - done = test_and_own (numobjects, handles, waitall, &count, &lowest); - if (done == TRUE) { - return(WAIT_OBJECT_0+lowest); - } - - if (timeout == 0) { + ret = mono_w32handle_wait_multiple (handles, numobjects, waitall, timeout, alertable); + if (ret >= MONO_W32HANDLE_WAIT_RET_SUCCESS_0) + return WAIT_OBJECT_0 + (ret - MONO_W32HANDLE_WAIT_RET_SUCCESS_0); + else if (ret == MONO_W32HANDLE_WAIT_RET_ALERTED) + return WAIT_IO_COMPLETION; + else if (ret == MONO_W32HANDLE_WAIT_RET_TIMEOUT) return WAIT_TIMEOUT; - } - - if (timeout != INFINITE) { - wait_start = mono_100ns_ticks (); - timeout_in_ticks = (gint64)timeout * 10 * 1000; //can't overflow as timeout is 32bits - } - - /* Have to wait for some or all handles to become signalled - */ - - for (i = 0; i < numobjects; i++) { - /* Add a reference, as we need to ensure the handle wont - * disappear from under us while we're waiting in the loop - * (not lock, as we don't want exclusive access here) - */ - _wapi_handle_ref (handles[i]); - } - - while(1) { - /* Prod all handles with prewait methods and - * special-wait handles that aren't already signalled - */ - for (i = 0; i < numobjects; i++) { - _wapi_handle_ops_prewait (handles[i]); - - if (_wapi_handle_test_capabilities (handles[i], WAPI_HANDLE_CAP_SPECIAL_WAIT) == TRUE && _wapi_handle_issignalled (handles[i]) == FALSE) { - _wapi_handle_ops_special_wait (handles[i], 0, alertable); - } - } - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: locking signal mutex", __func__); - - thr_ret = _wapi_handle_lock_signal_mutex (); - g_assert (thr_ret == 0); - - /* Check the signalled state of handles inside the critical section */ - if (waitall) { - done = TRUE; - for (i = 0; i < numobjects; i++) - if (!_wapi_handle_issignalled (handles [i])) - done = FALSE; - } else { - done = FALSE; - for (i = 0; i < numobjects; i++) - if (_wapi_handle_issignalled (handles [i])) - done = TRUE; - } - - if (!done) { - /* Enter the wait */ - if (timeout == INFINITE) { - ret = _wapi_handle_timedwait_signal (INFINITE, poll, &apc_pending); - } else { - gint64 elapsed = mono_100ns_ticks () - wait_start; - if (elapsed >= timeout_in_ticks) { - ret = WAIT_TIMEOUT; - } else { - ret = _wapi_handle_timedwait_signal ((timeout_in_ticks - elapsed) / 10 / 1000, poll, &apc_pending); - } - } - } else { - /* No need to wait */ - ret = 0; - } - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unlocking signal mutex", __func__); - - thr_ret = _wapi_handle_unlock_signal_mutex (NULL); - g_assert (thr_ret == 0); - - if (alertable && apc_pending) { - retval = WAIT_IO_COMPLETION; - break; - } - - /* Check if everything is signalled, as we can't - * guarantee to notice a shared signal even if the - * wait timed out - */ - done = test_and_own (numobjects, handles, waitall, - &count, &lowest); - if (done == TRUE) { - retval = WAIT_OBJECT_0+lowest; - break; - } else if (ret != 0) { - /* Didn't get all handles, and there was a - * timeout or other error - */ - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: wait returned error: %s", __func__, - strerror (ret)); - - if(ret==ETIMEDOUT) { - retval = WAIT_TIMEOUT; - } else { - retval = WAIT_FAILED; - } - break; - } - } - - for (i = 0; i < numobjects; i++) { - /* Unref everything we reffed above */ - _wapi_handle_unref (handles[i]); - } - - return retval; -} - -guint32 WaitForMultipleObjects(guint32 numobjects, gpointer *handles, - gboolean waitall, guint32 timeout) -{ - return WaitForMultipleObjectsEx(numobjects, handles, waitall, timeout, FALSE); -} - -/** - * WaitForInputIdle: - * @handle: a handle to the process to wait for - * @timeout: the maximum time in milliseconds to wait for - * - * This function returns when either @handle process is waiting - * for input, or @timeout ms elapses. If @timeout is zero, the - * process state is tested and the function returns immediately. - * If @timeout is %INFINITE, the function waits forever. - * - * Return value: 0 - @handle process is waiting for input. - * %WAIT_TIMEOUT - The @timeout interval elapsed and - * @handle process is not waiting for input. %WAIT_FAILED - an error - * occurred. - */ -guint32 WaitForInputIdle(gpointer handle, guint32 timeout) -{ - /*TODO: Not implemented*/ - return WAIT_TIMEOUT; + else if (ret == MONO_W32HANDLE_WAIT_RET_FAILED) + return WAIT_FAILED; + else + g_error ("%s: unknown ret value %d", __func__, ret); } diff --git a/mono/io-layer/wait.h b/mono/io-layer/wait.h index a4ff149147..b1fef4b147 100644 --- a/mono/io-layer/wait.h +++ b/mono/io-layer/wait.h @@ -11,11 +11,10 @@ #define _WAPI_WAIT_H_ #include "mono/io-layer/status.h" +#include "mono/utils/w32handle.h" G_BEGIN_DECLS -#define MAXIMUM_WAIT_OBJECTS 64 - #define INFINITE 0xFFFFFFFF #define WAIT_FAILED 0xFFFFFFFF @@ -27,16 +26,12 @@ G_BEGIN_DECLS #define WAIT_TIMEOUT STATUS_TIMEOUT #define WAIT_IO_COMPLETION STATUS_USER_APC -extern guint32 WaitForSingleObject(gpointer handle, guint32 timeout); extern guint32 WaitForSingleObjectEx(gpointer handle, guint32 timeout, gboolean alertable); extern guint32 SignalObjectAndWait(gpointer signal_handle, gpointer wait, guint32 timeout, gboolean alertable); -extern guint32 WaitForMultipleObjects(guint32 numobjects, gpointer *handles, - gboolean waitall, guint32 timeout); extern guint32 WaitForMultipleObjectsEx(guint32 numobjects, gpointer *handles, gboolean waitall, guint32 timeout, gboolean alertable); -extern guint32 WaitForInputIdle(gpointer handle, guint32 timeout); G_END_DECLS #endif /* _WAPI_WAIT_H_ */ diff --git a/mono/io-layer/wapi-private.h b/mono/io-layer/wapi-private.h index e01cdf6804..ee961002d9 100644 --- a/mono/io-layer/wapi-private.h +++ b/mono/io-layer/wapi-private.h @@ -15,101 +15,28 @@ #include #include -#include #include +#include #include -/* Increment this whenever an incompatible change is made to the - * shared handle structure. - */ -#define _WAPI_HANDLE_VERSION 12 +/* There doesn't seem to be a defined symbol for this */ +#define _WAPI_THREAD_CURRENT (gpointer)0xFFFFFFFE -typedef enum { - WAPI_HANDLE_UNUSED=0, - WAPI_HANDLE_FILE, - WAPI_HANDLE_CONSOLE, - WAPI_HANDLE_THREAD, - WAPI_HANDLE_SEM, - WAPI_HANDLE_MUTEX, - WAPI_HANDLE_EVENT, - WAPI_HANDLE_SOCKET, - WAPI_HANDLE_FIND, - WAPI_HANDLE_PROCESS, - WAPI_HANDLE_PIPE, - WAPI_HANDLE_NAMEDMUTEX, - WAPI_HANDLE_NAMEDSEM, - WAPI_HANDLE_NAMEDEVENT, - WAPI_HANDLE_COUNT -} WapiHandleType; - -extern const char *_wapi_handle_typename[]; - -#define _WAPI_SHARED_HANDLE(type) (type == WAPI_HANDLE_NAMEDMUTEX || \ - type == WAPI_HANDLE_NAMEDSEM || \ - type == WAPI_HANDLE_NAMEDEVENT) - -#define _WAPI_FD_HANDLE(type) (type == WAPI_HANDLE_FILE || \ - type == WAPI_HANDLE_CONSOLE || \ - type == WAPI_HANDLE_SOCKET || \ - type == WAPI_HANDLE_PIPE) - -#define _WAPI_SHARED_NAMESPACE(type) (type == WAPI_HANDLE_NAMEDMUTEX || \ - type == WAPI_HANDLE_NAMEDSEM || \ - type == WAPI_HANDLE_NAMEDEVENT) +extern gboolean _wapi_has_shut_down; typedef struct { gchar name[MAX_PATH + 1]; } WapiSharedNamespace; -typedef enum { - WAPI_HANDLE_CAP_WAIT=0x01, - WAPI_HANDLE_CAP_SIGNAL=0x02, - WAPI_HANDLE_CAP_OWN=0x04, - WAPI_HANDLE_CAP_SPECIAL_WAIT=0x08 -} WapiHandleCapability; - -struct _WapiHandleOps -{ - void (*close)(gpointer handle, gpointer data); - - /* SignalObjectAndWait */ - void (*signal)(gpointer signal); - - /* Called by WaitForSingleObject and WaitForMultipleObjects, - * with the handle locked (shared handles aren't locked.) - * Returns TRUE if ownership was established, false otherwise. - */ - gboolean (*own_handle)(gpointer handle); - - /* Called by WaitForSingleObject and WaitForMultipleObjects, if the - * handle in question is "ownable" (ie mutexes), to see if the current - * thread already owns this handle - */ - gboolean (*is_owned)(gpointer handle); - - /* Called by WaitForSingleObject and WaitForMultipleObjects, - * if the handle in question needs a special wait function - * instead of using the normal handle signal mechanism. - * Returns the WaitForSingleObject return code. - */ - guint32 (*special_wait)(gpointer handle, guint32 timeout, gboolean alertable); - - /* Called by WaitForSingleObject and WaitForMultipleObjects, - * if the handle in question needs some preprocessing before the - * signal wait. - */ - void (*prewait)(gpointer handle); -}; - #include #include #include #include #include -#include #include +#include struct _WapiHandle_shared_ref { @@ -119,63 +46,13 @@ struct _WapiHandle_shared_ref guint32 offset; }; -#define _WAPI_HANDLE_INITIAL_COUNT 256 - -struct _WapiHandleUnshared -{ - WapiHandleType type; - guint ref; - gboolean signalled; - mono_mutex_t signal_mutex; - pthread_cond_t signal_cond; - - union - { - struct _WapiHandle_event event; - struct _WapiHandle_file file; - struct _WapiHandle_find find; - struct _WapiHandle_mutex mutex; - struct _WapiHandle_sem sem; - struct _WapiHandle_socket sock; - struct _WapiHandle_thread thread; - struct _WapiHandle_process process; - struct _WapiHandle_shared_ref shared; - } u; -}; - -struct _WapiHandleShared -{ - WapiHandleType type; - guint32 timestamp; - guint32 handle_refs; - volatile gboolean signalled; - - union - { - struct _WapiHandle_namedmutex namedmutex; - struct _WapiHandle_namedsem namedsem; - struct _WapiHandle_namedevent namedevent; - } u; -}; - #define _WAPI_SHARED_SEM_NAMESPACE 0 /*#define _WAPI_SHARED_SEM_COLLECTION 1*/ #define _WAPI_SHARED_SEM_FILESHARE 2 -#define _WAPI_SHARED_SEM_SHARED_HANDLES 3 #define _WAPI_SHARED_SEM_PROCESS_COUNT_LOCK 6 #define _WAPI_SHARED_SEM_PROCESS_COUNT 7 #define _WAPI_SHARED_SEM_COUNT 8 /* Leave some future expansion space */ -struct _WapiHandleSharedLayout -{ - volatile guint32 collection_count; - volatile key_t sem_key; - - struct _WapiHandleShared handles[_WAPI_HANDLE_INITIAL_COUNT]; -}; - -typedef struct _WapiHandleSharedLayout _WapiHandleSharedLayout; - struct _WapiFileShare { #ifdef WAPI_FILE_SHARE_PLATFORM_EXTRA_DATA @@ -192,6 +69,18 @@ struct _WapiFileShare typedef struct _WapiFileShare _WapiFileShare; -#define _WAPI_HANDLE_INVALID (gpointer)-1 +gpointer +_wapi_search_handle_namespace (MonoW32HandleType type, gchar *utf8_name); + +static inline int _wapi_namespace_lock (void) +{ + return(_wapi_shm_sem_lock (_WAPI_SHARED_SEM_NAMESPACE)); +} + +/* This signature makes it easier to use in pthread cleanup handlers */ +static inline int _wapi_namespace_unlock (gpointer data G_GNUC_UNUSED) +{ + return(_wapi_shm_sem_unlock (_WAPI_SHARED_SEM_NAMESPACE)); +} #endif /* _WAPI_PRIVATE_H_ */ diff --git a/mono/io-layer/wapi-remap.h b/mono/io-layer/wapi-remap.h index d8c4aaccb0..8f8b4ff549 100644 --- a/mono/io-layer/wapi-remap.h +++ b/mono/io-layer/wapi-remap.h @@ -93,13 +93,8 @@ #define GetFileVersionInfo wapi_GetFileVersionInfo #define VerQueryValue wapi_VerQueryValue #define VerLanguageName wapi_VerLanguageName -#define WaitForSingleObject wapi_WaitForSingleObject #define WaitForSingleObjectEx wapi_WaitForSingleObjectEx #define SignalObjectAndWait wapi_SignalObjectAndWait -#define WaitForMultipleObjects wapi_WaitForMultipleObjects #define WaitForMultipleObjectsEx wapi_WaitForMultipleObjectsEx -#define WaitForInputIdle wapi_WaitForInputIdle -#define GetThreadPriority wapi_GetThreadPriority -#define SetThreadPriority wapi_SetThreadPriority #endif /* __WAPI_REMAP_H__ */ diff --git a/mono/io-layer/wapi.c b/mono/io-layer/wapi.c new file mode 100644 index 0000000000..a9f9369240 --- /dev/null +++ b/mono/io-layer/wapi.c @@ -0,0 +1,187 @@ + +#include "wapi.h" + +#include "event-private.h" +#include "io-trace.h" +#include "io.h" +#include "mutex-private.h" +#include "process-private.h" +#include "semaphore-private.h" +#include "shared.h" +#include "socket-private.h" + +#include "mono/utils/mono-lazy-init.h" +#include "mono/utils/w32handle.h" + +gboolean _wapi_has_shut_down = FALSE; + +void +wapi_init (void) +{ + _wapi_shm_semaphores_init (); + _wapi_io_init (); + _wapi_processes_init (); + _wapi_semaphore_init (); + _wapi_mutex_init (); + _wapi_event_init (); + _wapi_socket_init (); +} + +void +wapi_cleanup (void) +{ + g_assert (_wapi_has_shut_down == FALSE); + _wapi_has_shut_down = TRUE; + + _wapi_error_cleanup (); + wapi_processes_cleanup (); + _wapi_io_cleanup (); +} + +/* Use this instead of getpid(), to cope with linuxthreads. It's a + * function rather than a variable lookup because we need to get at + * this before share_init() might have been called. */ +static mono_lazy_init_t _wapi_pid_init_lazy = MONO_LAZY_INIT_STATUS_NOT_INITIALIZED; +static pid_t _wapi_pid; + +static void +_wapi_pid_init (void) +{ + _wapi_pid = getpid (); +} + +pid_t +wapi_getpid (void) +{ + mono_lazy_initialize (&_wapi_pid_init_lazy, _wapi_pid_init); + return _wapi_pid; +} + +static gboolean +_WAPI_SHARED_NAMESPACE (MonoW32HandleType type) +{ + switch (type) { + case MONO_W32HANDLE_NAMEDMUTEX: + case MONO_W32HANDLE_NAMEDSEM: + case MONO_W32HANDLE_NAMEDEVENT: + return TRUE; + default: + return FALSE; + } +} + +typedef struct { + gpointer ret; + MonoW32HandleType type; + gchar *utf8_name; +} _WapiSearchHandleNamespaceData; + +static gboolean mono_w32handle_search_namespace_callback (gpointer handle, gpointer data, gpointer user_data) +{ + _WapiSearchHandleNamespaceData *search_data; + MonoW32HandleType type; + WapiSharedNamespace *sharedns; + + type = mono_w32handle_get_type (handle); + if (!_WAPI_SHARED_NAMESPACE (type)) + return FALSE; + + search_data = (_WapiSearchHandleNamespaceData*) user_data; + + switch (type) { + case MONO_W32HANDLE_NAMEDMUTEX: sharedns = &((struct _WapiHandle_namedmutex*) data)->sharedns; break; + case MONO_W32HANDLE_NAMEDSEM: sharedns = &((struct _WapiHandle_namedsem*) data)->sharedns; break; + case MONO_W32HANDLE_NAMEDEVENT: sharedns = &((struct _WapiHandle_namedevent*) data)->sharedns; break; + default: + g_assert_not_reached (); + } + + if (strcmp (sharedns->name, search_data->utf8_name) == 0) { + if (type != search_data->type) { + /* Its the wrong type, so fail now */ + MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p matches name but is wrong type: %s", + __func__, handle, mono_w32handle_ops_typename (type)); + search_data->ret = INVALID_HANDLE_VALUE; + } else { + MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p matches name and type", + __func__, handle); + search_data->ret = handle; + } + + return TRUE; + } + + return FALSE; +} + +/* Returns the offset of the metadata array, or INVALID_HANDLE_VALUE on error, or NULL for + * not found + */ +gpointer _wapi_search_handle_namespace (MonoW32HandleType type, gchar *utf8_name) +{ + _WapiSearchHandleNamespaceData search_data; + + g_assert(_WAPI_SHARED_NAMESPACE(type)); + + MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Lookup for handle named [%s] type %s", + __func__, utf8_name, mono_w32handle_ops_typename (type)); + + search_data.ret = NULL; + search_data.type = type; + search_data.utf8_name = utf8_name; + mono_w32handle_foreach (mono_w32handle_search_namespace_callback, &search_data); + return search_data.ret; +} + +/* Lots more to implement here, but this is all we need at the moment */ +gboolean +DuplicateHandle (gpointer srcprocess, gpointer src, gpointer targetprocess, gpointer *target, + guint32 access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED, guint32 options G_GNUC_UNUSED) +{ + if (srcprocess != _WAPI_PROCESS_CURRENT || targetprocess != _WAPI_PROCESS_CURRENT) { + /* Duplicating other process's handles is not supported */ + SetLastError (ERROR_INVALID_HANDLE); + return FALSE; + } + + if (src == _WAPI_PROCESS_CURRENT) { + *target = _wapi_process_duplicate (); + } else { + mono_w32handle_ref (src); + *target = src; + } + + return TRUE; +} + +/** + * CloseHandle: + * @handle: The handle to release + * + * Closes and invalidates @handle, releasing any resources it + * consumes. When the last handle to a temporary or non-persistent + * object is closed, that object can be deleted. Closing the same + * handle twice is an error. + * + * Return value: %TRUE on success, %FALSE otherwise. + */ +gboolean CloseHandle(gpointer handle) +{ + if (handle == INVALID_HANDLE_VALUE){ + SetLastError (ERROR_INVALID_PARAMETER); + return FALSE; + } + if (handle == (gpointer)0 && mono_w32handle_get_type (handle) != MONO_W32HANDLE_CONSOLE) { + /* Problem: because we map file descriptors to the + * same-numbered handle we can't tell the difference + * between a bogus handle and the handle to stdin. + * Assume that it's the console handle if that handle + * exists... + */ + SetLastError (ERROR_INVALID_PARAMETER); + return FALSE; + } + + mono_w32handle_unref (handle); + return TRUE; +} diff --git a/mono/io-layer/wapi.h b/mono/io-layer/wapi.h index c6cbecd49c..4e0a688063 100644 --- a/mono/io-layer/wapi.h +++ b/mono/io-layer/wapi.h @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include @@ -26,9 +25,24 @@ #include #include #include -#include #include #include #include +void +wapi_init (void); + +void +wapi_cleanup (void); + +gboolean +CloseHandle (gpointer handle); + +gboolean +DuplicateHandle (gpointer srcprocess, gpointer src, gpointer targetprocess, gpointer *target, + guint32 access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED, guint32 options G_GNUC_UNUSED); + +pid_t +wapi_getpid (void); + #endif /* _WAPI_WAPI_H_ */ diff --git a/mono/io-layer/wapi_glob.c b/mono/io-layer/wapi_glob.c index 88864821be..013b778a86 100644 --- a/mono/io-layer/wapi_glob.c +++ b/mono/io-layer/wapi_glob.c @@ -267,11 +267,11 @@ globextend(const gchar *path, wapi_glob_t *pglob, size_t *limitp) newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs); /* FIXME: Can just use realloc(). */ - pathv = (char **)(pglob->gl_pathv ? realloc((char *)pglob->gl_pathv, newsize) : - malloc(newsize)); + pathv = (char **)(pglob->gl_pathv ? g_realloc ((char *)pglob->gl_pathv, newsize) : + g_malloc (newsize)); if (pathv == NULL) { if (pglob->gl_pathv) { - free(pglob->gl_pathv); + g_free (pglob->gl_pathv); pglob->gl_pathv = NULL; } return(WAPI_GLOB_NOSPACE); @@ -291,7 +291,7 @@ globextend(const gchar *path, wapi_glob_t *pglob, size_t *limitp) *limitp += len; if ((copy = (char *)malloc(len)) != NULL) { if (g_Ctoc(path, copy, len)) { - free(copy); + g_free (copy); return(WAPI_GLOB_NOSPACE); } pathv[pglob->gl_offs + pglob->gl_pathc++] = copy; @@ -361,8 +361,8 @@ _wapi_globfree(wapi_glob_t *pglob) pp = pglob->gl_pathv + pglob->gl_offs; for (i = pglob->gl_pathc; i--; ++pp) if (*pp) - free(*pp); - free(pglob->gl_pathv); + g_free (*pp); + g_free (pglob->gl_pathv); pglob->gl_pathv = NULL; } } diff --git a/mono/io-layer/wthreads.c b/mono/io-layer/wthreads.c deleted file mode 100644 index 304fd35adf..0000000000 --- a/mono/io-layer/wthreads.c +++ /dev/null @@ -1,451 +0,0 @@ -/* - * threads.c: Thread handles - * - * Author: - * Dick Porter (dick@ximian.com) - * - * (C) 2002-2006 Ximian, Inc. - * Copyright 2003-2011 Novell, Inc (http://www.novell.com) - * Copyright 2011 Xamarin, Inc (http://www.xamarin.com) - * Licensed under the MIT license. See LICENSE file in the project root for full license information. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#ifdef HAVE_VALGRIND_MEMCHECK_H -#include -#endif - -struct _WapiHandleOps _wapi_thread_ops = { - NULL, /* close */ - NULL, /* signal */ - NULL, /* own */ - NULL, /* is_owned */ - NULL, /* special_wait */ - NULL /* prewait */ -}; - -typedef enum { - THREAD_PRIORITY_LOWEST = -2, - THREAD_PRIORITY_BELOW_NORMAL = -1, - THREAD_PRIORITY_NORMAL = 0, - THREAD_PRIORITY_ABOVE_NORMAL = 1, - THREAD_PRIORITY_HIGHEST = 2 -} WapiThreadPriority; - -static mono_once_t thread_ops_once = MONO_ONCE_INIT; - -static void -thread_ops_init (void) -{ - _wapi_handle_register_capabilities (WAPI_HANDLE_THREAD, - WAPI_HANDLE_CAP_WAIT); -} - -void -_wapi_thread_cleanup (void) -{ -} - -static gpointer -get_current_thread_handle (void) -{ - MonoThreadInfo *info; - - info = mono_thread_info_current (); - g_assert (info); - g_assert (info->handle); - return info->handle; -} - -static WapiHandle_thread* -lookup_thread (HANDLE handle) -{ - WapiHandle_thread *thread; - gboolean ok; - - ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD, - (gpointer *)&thread); - g_assert (ok); - return thread; -} - -static WapiHandle_thread* -get_current_thread (void) -{ - gpointer handle; - - handle = get_current_thread_handle (); - return lookup_thread (handle); -} - -void -wapi_thread_handle_set_exited (gpointer handle, guint32 exitstatus) -{ - WapiHandle_thread *thread_handle; - int i, thr_ret; - pid_t pid = _wapi_getpid (); - pthread_t tid = pthread_self (); - - if (_wapi_handle_issignalled (handle) || - _wapi_handle_type (handle) == WAPI_HANDLE_UNUSED) { - /* We must have already deliberately finished with - * this thread, so don't do any more now - */ - return; - } - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Thread %p terminating", __func__, handle); - - thread_handle = lookup_thread (handle); - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Thread %p abandoning held mutexes", __func__, handle); - - for (i = 0; i < thread_handle->owned_mutexes->len; i++) { - gpointer mutex = g_ptr_array_index (thread_handle->owned_mutexes, i); - - _wapi_mutex_abandon (mutex, pid, tid); - _wapi_thread_disown_mutex (mutex); - } - g_ptr_array_free (thread_handle->owned_mutexes, TRUE); - - thr_ret = _wapi_handle_lock_handle (handle); - g_assert (thr_ret == 0); - - _wapi_handle_set_signal_state (handle, TRUE, TRUE); - - thr_ret = _wapi_handle_unlock_handle (handle); - g_assert (thr_ret == 0); - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Recording thread handle %p id %ld status as %d", - __func__, handle, thread_handle->id, exitstatus); - - /* The thread is no longer active, so unref it */ - _wapi_handle_unref (handle); -} - -/* - * wapi_create_thread_handle: - * - * Create a thread handle for the current thread. - */ -gpointer -wapi_create_thread_handle (void) -{ - WapiHandle_thread thread_handle = {0}, *thread; - gpointer handle; - - mono_once (&thread_ops_once, thread_ops_init); - - thread_handle.owned_mutexes = g_ptr_array_new (); - - handle = _wapi_handle_new (WAPI_HANDLE_THREAD, &thread_handle); - if (handle == _WAPI_HANDLE_INVALID) { - g_warning ("%s: error creating thread handle", __func__); - SetLastError (ERROR_GEN_FAILURE); - - return NULL; - } - - thread = lookup_thread (handle); - - thread->id = pthread_self (); - - /* - * Hold a reference while the thread is active, because we use - * the handle to store thread exit information - */ - _wapi_handle_ref (handle); - - MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: started thread id %ld", __func__, thread->id); - - return handle; -} - -void -wapi_ref_thread_handle (gpointer handle) -{ - _wapi_handle_ref (handle); -} - -gpointer -wapi_get_current_thread_handle (void) -{ - return get_current_thread_handle (); -} - -gboolean -_wapi_thread_cur_apc_pending (void) -{ - return mono_thread_info_is_interrupt_state (mono_thread_info_current ()); -} - -void -_wapi_thread_own_mutex (gpointer mutex) -{ - WapiHandle_thread *thread; - - thread = get_current_thread (); - - _wapi_handle_ref (mutex); - - g_ptr_array_add (thread->owned_mutexes, mutex); -} - -void -_wapi_thread_disown_mutex (gpointer mutex) -{ - WapiHandle_thread *thread; - - thread = get_current_thread (); - - _wapi_handle_unref (mutex); - - g_ptr_array_remove (thread->owned_mutexes, mutex); -} - -/** - * _wapi_thread_posix_priority_to_priority: - * - * Convert a POSIX priority to a WapiThreadPriority. - * sched_priority is a POSIX priority, - * policy is the current scheduling policy - */ -static WapiThreadPriority -_wapi_thread_posix_priority_to_priority (int sched_priority, int policy) -{ -/* Necessary to get valid priority range */ -#ifdef _POSIX_PRIORITY_SCHEDULING - int max, - min, - i, - priority, - chunk; - WapiThreadPriority priorities[] = { - THREAD_PRIORITY_LOWEST, - THREAD_PRIORITY_LOWEST, - THREAD_PRIORITY_BELOW_NORMAL, - THREAD_PRIORITY_NORMAL, - THREAD_PRIORITY_ABOVE_NORMAL, - THREAD_PRIORITY_HIGHEST, - THREAD_PRIORITY_HIGHEST - }; - - max = sched_get_priority_max (policy); - min = sched_get_priority_min (policy); - - /* Partition priority range linearly, - assign each partition a thread priority */ - if (max != min && 0 <= max && 0 <= min) { - for (i=1, priority=min, chunk=(max-min)/7; - i<6 && sched_priority > priority; - ++i) { - priority += chunk; - } - - if (max <= priority) - { - return (THREAD_PRIORITY_HIGHEST); - } - else - { - return (priorities[i-1]); - } - } -#endif - - return (THREAD_PRIORITY_NORMAL); -} - -/** - * _wapi_thread_priority_to_posix_priority: - * - * Convert a WapiThreadPriority to a POSIX priority. - * priority is a WapiThreadPriority, - * policy is the current scheduling policy - */ -static int -_wapi_thread_priority_to_posix_priority (WapiThreadPriority priority, int policy) -{ -/* Necessary to get valid priority range */ -#ifdef _POSIX_PRIORITY_SCHEDULING - int max, - min, - posix_priority, - i; - WapiThreadPriority priorities[] = { - THREAD_PRIORITY_LOWEST, - THREAD_PRIORITY_LOWEST, - THREAD_PRIORITY_BELOW_NORMAL, - THREAD_PRIORITY_NORMAL, - THREAD_PRIORITY_ABOVE_NORMAL, - THREAD_PRIORITY_HIGHEST, - THREAD_PRIORITY_HIGHEST - }; - - max = sched_get_priority_max (policy); - min = sched_get_priority_min (policy); - - /* Partition priority range linearly, - numerically approximate matching ThreadPriority */ - if (max != min && 0 <= max && 0 <= min) { - for (i=0; i<7; ++i) { - if (priorities[i] == priority) { - posix_priority = min + ((max-min)/7) * i; - if (max < posix_priority) - { - return max; - } - else { - return posix_priority; - } - } - } - } -#endif - - switch (policy) { - case SCHED_FIFO: - case SCHED_RR: - return 50; -#ifdef SCHED_BATCH - case SCHED_BATCH: -#endif - case SCHED_OTHER: - return 0; - default: - return -1; - } -} - -/** - * GetThreadPriority: - * @param handle: The thread handle to query. - * - * Gets the priority of the given thread. - * @return: A MonoThreadPriority approximating the current POSIX - * thread priority, or THREAD_PRIORITY_NORMAL on error. - */ -gint32 -GetThreadPriority (gpointer handle) -{ - struct _WapiHandle_thread *thread_handle; - int policy; - struct sched_param param; - gboolean ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD, - (gpointer *)&thread_handle); - - if (ok == FALSE) { - return (THREAD_PRIORITY_NORMAL); - } - - switch (pthread_getschedparam (thread_handle->id, &policy, ¶m)) { - case 0: - return (_wapi_thread_posix_priority_to_priority (param.sched_priority, policy)); - case ESRCH: - g_warning ("pthread_getschedparam: error looking up thread id %x", (gsize)thread_handle->id); - } - - return (THREAD_PRIORITY_NORMAL); -} - -/** - * SetThreadPriority: - * @param handle: The thread handle to query. - * @param priority: The priority to give to the thread. - * - * Sets the priority of the given thread. - * @return: TRUE on success, FALSE on failure or error. - */ -gboolean -SetThreadPriority (gpointer handle, gint32 priority) -{ - struct _WapiHandle_thread *thread_handle; - int policy, - posix_priority, - rv; - struct sched_param param; - gboolean ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD, - (gpointer *)&thread_handle); - - if (ok == FALSE) { - return ok; - } - - rv = pthread_getschedparam (thread_handle->id, &policy, ¶m); - if (rv) { - if (ESRCH == rv) - g_warning ("pthread_getschedparam: error looking up thread id %x", (gsize)thread_handle->id); - return FALSE; - } - - posix_priority = _wapi_thread_priority_to_posix_priority (priority, policy); - if (0 > posix_priority) - return FALSE; - - param.sched_priority = posix_priority; - switch (pthread_setschedparam (thread_handle->id, policy, ¶m)) { - case 0: - return TRUE; - case ESRCH: - g_warning ("pthread_setschedparam: error looking up thread id %x", (gsize)thread_handle->id); - break; - case ENOTSUP: - g_warning ("%s: priority %d not supported", __func__, priority); - break; - case EPERM: - g_warning ("%s: permission denied", __func__); - break; - } - - return FALSE; -} - -char* -wapi_current_thread_desc (void) -{ - WapiHandle_thread *thread; - gpointer thread_handle; - int i; - GString* text; - char *res; - - thread_handle = get_current_thread_handle (); - thread = lookup_thread (thread_handle); - - text = g_string_new (0); - g_string_append_printf (text, "thread handle %p state : ", thread_handle); - - mono_thread_info_describe_interrupt_token (mono_thread_info_current (), text); - - g_string_append_printf (text, " owns ("); - for (i = 0; i < thread->owned_mutexes->len; i++) - g_string_append_printf (text, i > 0 ? ", %p" : "%p", g_ptr_array_index (thread->owned_mutexes, i)); - g_string_append_printf (text, ")"); - - res = text->str; - g_string_free (text, FALSE); - return res; -} diff --git a/mono/metadata/Makefile.am b/mono/metadata/Makefile.am index cdf42e498d..16575ecc67 100644 --- a/mono/metadata/Makefile.am +++ b/mono/metadata/Makefile.am @@ -32,9 +32,13 @@ if PLATFORM_ANDROID platform_sources += ../../support/libm/complex.c endif -if SHARED_MONO -if SUPPORT_BOEHM -bin_PROGRAMS = pedump +if !DYNAMIC_BTLS +if BTLS +btls_file_list := $(shell cat ../btls/build-shared/mono-btls-shared-lo.txt) +btls_static_file_list := $(shell cat ../btls/build-static/mono-btls-static-lo.txt) +btls_libs = $(btls_file_list) +btls_static_libs = $(btls_static_file_list) +btls_cflags = -I$(top_srcdir)/external/boringssl/include -I$(top_srcdir)/mono/btls endif endif @@ -70,7 +74,7 @@ else noinst_LTLIBRARIES = libmonoruntime-config.la $(boehm_libraries) $(sgen_libraries) endif -AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/mono $(LIBGC_CPPFLAGS) $(GLIB_CFLAGS) $(SHARED_CFLAGS) +AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/mono $(LIBGC_CPPFLAGS) $(GLIB_CFLAGS) $(SHARED_CFLAGS) $(btls_cflags) # # Make sure any prefix changes are updated in the binaries too. @@ -207,6 +211,12 @@ common_sources = \ verify.c \ verify-internals.h \ wrapper-types.h \ + dynamic-image-internals.h \ + dynamic-stream.c \ + dynamic-stream-internals.h \ + reflection-cache.h \ + custom-attrs-internals.h \ + sre-internals.h \ reflection-internals.h \ file-mmap-posix.c \ file-mmap-windows.c \ @@ -229,8 +239,14 @@ gc_dependent_sources = \ monitor.c \ mono-hash.c \ object.c \ + dynamic-image.c \ + sre.c \ + sre-encode.c \ + sre-save.c \ + custom-attrs.c \ reflection.c + boehm_sources = \ boehm-gc.c @@ -253,21 +269,21 @@ sgen_sources = \ libmonoruntime_la_SOURCES = $(common_sources) $(gc_dependent_sources) $(null_gc_sources) $(boehm_sources) libmonoruntime_la_CFLAGS = $(BOEHM_DEFINES) -libmonoruntime_la_LIBADD = libmonoruntime-config.la +libmonoruntime_la_LIBADD = libmonoruntime-config.la $(btls_libs) libmonoruntimesgen_la_SOURCES = $(common_sources) $(gc_dependent_sources) $(sgen_sources) libmonoruntimesgen_la_CFLAGS = $(SGEN_DEFINES) -libmonoruntimesgen_la_LIBADD = libmonoruntime-config.la +libmonoruntimesgen_la_LIBADD = libmonoruntime-config.la $(btls_libs) libmonoruntime_static_la_SOURCES = $(libmonoruntime_la_SOURCES) libmonoruntime_static_la_LDFLAGS = -static libmonoruntime_static_la_CFLAGS = $(BOEHM_DEFINES) -libmonoruntime_static_la_LIBADD = $(bundle_obj) $(libmonoruntime_la_LIBADD) +libmonoruntime_static_la_LIBADD = $(bundle_obj) libmonoruntime-config.la $(btls_static_libs) libmonoruntimesgen_static_la_SOURCES = $(libmonoruntimesgen_la_SOURCES) libmonoruntimesgen_static_la_LDFLAGS = -static libmonoruntimesgen_static_la_CFLAGS = $(SGEN_DEFINES) -libmonoruntimesgen_static_la_LIBADD = $(libmonoruntimesgen_la_LIBADD) +libmonoruntimesgen_static_la_LIBADD = libmonoruntime-config.la $(btls_static_libs) libmonoruntimeincludedir = $(includedir)/mono-$(API_VER)/mono/metadata @@ -297,31 +313,5 @@ libmonoruntimeinclude_HEADERS = \ tokentype.h \ verify.h -if DTRACE_G_REQUIRED - -PEDUMP_DTRACE_OBJECT = pedump-dtrace.$(OBJEXT) - -pedump-dtrace.$(OBJEXT): $(top_srcdir)/data/mono.d libmonoruntime.la ../io-layer/libwapi.la ../utils/libmonoutils.la - DTRACE="$(DTRACE)" DTRACEFLAGS="$(DTRACEFLAGS)" AR="$(AR)" $(SHELL) $(top_srcdir)/data/dtrace-prelink.sh \ - --pic pedump-dtrace.$(OBJEXT) $(top_srcdir)/data/mono.d libmonoruntime.la ../io-layer/libwapi.la ../utils/libmonoutils.la - -else -PEDUMP_DTRACE_OBJECT = -endif - -if SHARED_MONO -if SUPPORT_BOEHM -pedump_SOURCES = \ - pedump.c - -pedump_LDADD = libmonoruntime.la ../io-layer/libwapi.la ../utils/libmonoutils.la \ - $(LIBGC_LIBS) $(GLIB_LIBS) -lm $(LIBICONV) $(PEDUMP_DTRACE_OBJECT) - -if PLATFORM_DARWIN -pedump_LDFLAGS=-framework CoreFoundation -framework Foundation -endif -endif -endif - EXTRA_DIST = $(win32_sources) $(unix_sources) $(null_sources) runtime.h \ - threadpool-ms-io-poll.c threadpool-ms-io-epoll.c threadpool-ms-io-kqueue.c + threadpool-ms-io-poll.c threadpool-ms-io-epoll.c threadpool-ms-io-kqueue.c sgen-dynarray.h diff --git a/mono/metadata/Makefile.in.REMOVED.git-id b/mono/metadata/Makefile.in.REMOVED.git-id index b91726f6a6..1bf25d434b 100644 --- a/mono/metadata/Makefile.in.REMOVED.git-id +++ b/mono/metadata/Makefile.in.REMOVED.git-id @@ -1 +1 @@ -979067eee8f63e1d49368e906fa57f0d9e3d4c78 \ No newline at end of file +e5365ceab10db097e26594b511bae0ad84084843 \ No newline at end of file diff --git a/mono/metadata/appdomain.c b/mono/metadata/appdomain.c index 579b93afc1..2c13387cc0 100644 --- a/mono/metadata/appdomain.c +++ b/mono/metadata/appdomain.c @@ -39,6 +39,7 @@ #include "mono/metadata/metadata-internals.h" #include #include +#include #include #include #include @@ -66,6 +67,7 @@ #include #include #include +#include #ifdef HOST_WIN32 #include #endif @@ -81,7 +83,7 @@ * Changes which are already detected at runtime, like the addition * of icalls, do not require an increment. */ -#define MONO_CORLIB_VERSION 149 +#define MONO_CORLIB_VERSION 156 typedef struct { @@ -189,16 +191,19 @@ create_domain_objects (MonoDomain *domain) * Create an instance early since we can't do it when there is no memory. */ arg = mono_string_new (domain, "Out of memory"); - domain->out_of_memory_ex = mono_exception_from_name_two_strings (mono_defaults.corlib, "System", "OutOfMemoryException", arg, NULL); + domain->out_of_memory_ex = mono_exception_from_name_two_strings_checked (mono_defaults.corlib, "System", "OutOfMemoryException", arg, NULL, &error); + mono_error_assert_ok (&error); /* * These two are needed because the signal handlers might be executing on * an alternate stack, and Boehm GC can't handle that. */ arg = mono_string_new (domain, "A null value was found where an object instance was required"); - domain->null_reference_ex = mono_exception_from_name_two_strings (mono_defaults.corlib, "System", "NullReferenceException", arg, NULL); + domain->null_reference_ex = mono_exception_from_name_two_strings_checked (mono_defaults.corlib, "System", "NullReferenceException", arg, NULL, &error); + mono_error_assert_ok (&error); arg = mono_string_new (domain, "The requested operation caused a stack overflow."); - domain->stack_overflow_ex = mono_exception_from_name_two_strings (mono_defaults.corlib, "System", "StackOverflowException", arg, NULL); + domain->stack_overflow_ex = mono_exception_from_name_two_strings_checked (mono_defaults.corlib, "System", "StackOverflowException", arg, NULL, &error); + mono_error_assert_ok (&error); /*The ephemeron tombstone i*/ domain->ephemeron_tombstone = mono_object_new_checked (domain, mono_defaults.object_class, &error); @@ -957,7 +962,9 @@ ves_icall_System_AppDomain_createDomain (MonoString *friendly_name, MonoAppDomai { MonoError error; MonoAppDomain *ad = NULL; + #ifdef DISABLE_APPDOMAINS + mono_error_init (&error); mono_error_set_not_supported (&error, "AppDomain creation is not supported on this runtime."); #else char *fname; @@ -1757,13 +1764,13 @@ mono_make_shadow_copy (const char *filename, MonoError *oerror) sibling_target_len = strlen (sibling_target); copy_result = shadow_copy_sibling (sibling_source, sibling_source_len, ".mdb", sibling_target, sibling_target_len, 7); - if (copy_result == TRUE) + if (copy_result) copy_result = shadow_copy_sibling (sibling_source, sibling_source_len, ".config", sibling_target, sibling_target_len, 7); g_free (sibling_source); g_free (sibling_target); - if (copy_result == FALSE) { + if (!copy_result) { g_free (shadow); mono_error_set_execution_engine (oerror, "Failed to create shadow copy of sibling data (CopyFile)."); return NULL; @@ -1935,37 +1942,37 @@ ves_icall_System_Reflection_Assembly_LoadFrom (MonoString *fname, MonoBoolean re MonoDomain *domain = mono_domain_get (); char *name, *filename; MonoImageOpenStatus status = MONO_IMAGE_OK; - MonoAssembly *ass; + MonoAssembly *ass = NULL; + + name = NULL; + result = NULL; + + mono_error_init (&error); if (fname == NULL) { - MonoException *exc = mono_get_exception_argument_null ("assemblyFile"); - mono_set_pending_exception (exc); - return NULL; + mono_error_set_argument_null (&error, "assemblyFile", ""); + goto leave; } name = filename = mono_string_to_utf8_checked (fname, &error); - if (mono_error_set_pending_exception (&error)) - return NULL; + if (!is_ok (&error)) + goto leave; ass = mono_assembly_open_full (filename, &status, refOnly); if (!ass) { - MonoException *exc; - if (status == MONO_IMAGE_IMAGE_INVALID) - exc = mono_get_exception_bad_image_format2 (NULL, fname); + mono_error_set_bad_image_name (&error, name, ""); else - exc = mono_get_exception_file_not_found2 (NULL, fname); - g_free (name); - mono_set_pending_exception (exc); - return NULL; + mono_error_set_exception_instance (&error, mono_get_exception_file_not_found2 (NULL, fname)); + goto leave; } - g_free (name); - result = mono_assembly_get_object_checked (domain, ass, &error); - if (!result) - mono_error_set_pending_exception (&error); + +leave: + mono_error_set_pending_exception (&error); + g_free (name); return result; } @@ -2017,7 +2024,7 @@ ves_icall_System_AppDomain_LoadAssembly (MonoAppDomain *ad, MonoString *assRef, MonoAssembly *ass; MonoAssemblyName aname; MonoReflectionAssembly *refass = NULL; - gchar *name; + gchar *name = NULL; gboolean parsed; g_assert (assRef); @@ -2026,16 +2033,13 @@ ves_icall_System_AppDomain_LoadAssembly (MonoAppDomain *ad, MonoString *assRef, if (mono_error_set_pending_exception (&error)) return NULL; parsed = mono_assembly_name_parse (name, &aname); - g_free (name); if (!parsed) { /* This is a parse error... */ if (!refOnly) { refass = mono_try_assembly_resolve (domain, assRef, NULL, refOnly, &error); - if (!mono_error_ok (&error)) { - mono_error_set_pending_exception (&error); - return NULL; - } + if (!is_ok (&error)) + goto leave; } return refass; } @@ -2047,25 +2051,28 @@ ves_icall_System_AppDomain_LoadAssembly (MonoAppDomain *ad, MonoString *assRef, /* MS.NET doesn't seem to call the assembly resolve handler for refonly assemblies */ if (!refOnly) { refass = mono_try_assembly_resolve (domain, assRef, NULL, refOnly, &error); - if (!mono_error_ok (&error)) { - mono_error_set_pending_exception (&error); - return NULL; - } + if (!is_ok (&error)) + goto leave; } else refass = NULL; - if (!refass) { - return NULL; - } + if (!refass) + goto leave; + ass = refass->assembly; } - if (refass == NULL) + g_assert (ass); + if (refass == NULL) { refass = mono_assembly_get_object_checked (domain, ass, &error); + if (!is_ok (&error)) + goto leave; + } - if (refass == NULL) - mono_error_set_pending_exception (&error); - else - MONO_OBJECT_SETREF (refass, evidence, evidence); + MONO_OBJECT_SETREF (refass, evidence, evidence); + +leave: + g_free (name); + mono_error_set_pending_exception (&error); return refass; } @@ -2140,7 +2147,9 @@ ves_icall_System_AppDomain_ExecuteAssembly (MonoAppDomain *ad, mono_error_assert_ok (&error); } - return mono_runtime_exec_main (method, (MonoArray *)args, NULL); + int res = mono_runtime_exec_main_checked (method, (MonoArray *)args, &error); + mono_error_set_pending_exception (&error); + return res; } gint32 @@ -2346,7 +2355,7 @@ deregister_reflection_info_roots (MonoDomain *domain) mono_domain_assemblies_unlock (domain); } -static guint32 WINAPI +static gsize WINAPI unload_thread_main (void *arg) { MonoError error; @@ -2496,6 +2505,7 @@ mono_domain_try_unload (MonoDomain *domain, MonoObject **exc) unload_data *thread_data; MonoNativeThreadId tid; MonoDomain *caller_domain = mono_domain_get (); + MonoThreadParm tp; /* printf ("UNLOAD STARTING FOR %s (%p) IN THREAD 0x%x.\n", domain->friendly_name, domain, mono_native_thread_id_get ()); */ @@ -2552,22 +2562,25 @@ mono_domain_try_unload (MonoDomain *domain, MonoObject **exc) * First we create a separate thread for unloading, since * we might have to abort some threads, including the current one. */ - thread_handle = mono_threads_create_thread ((LPTHREAD_START_ROUTINE)unload_thread_main, thread_data, 0, CREATE_SUSPENDED, &tid); + tp.priority = MONO_THREAD_PRIORITY_NORMAL; + tp.stack_size = 0; + tp.creation_flags = 0; + thread_handle = mono_threads_create_thread (unload_thread_main, thread_data, &tp, &tid); if (thread_handle == NULL) return; - mono_thread_info_resume (tid); /* Wait for the thread */ while (!thread_data->done && guarded_wait (thread_handle, INFINITE, TRUE) == WAIT_IO_COMPLETION) { if (mono_thread_internal_has_appdomain_ref (mono_thread_internal_current (), domain) && (mono_thread_interruption_requested ())) { /* The unload thread tries to abort us */ /* The icall wrapper will execute the abort */ - CloseHandle (thread_handle); + mono_threads_close_thread_handle (thread_handle); unload_data_unref (thread_data); return; } } - CloseHandle (thread_handle); + + mono_threads_close_thread_handle (thread_handle); if (thread_data->failure_reason) { /* Roll back the state change */ diff --git a/mono/metadata/assembly.c b/mono/metadata/assembly.c deleted file mode 100644 index 57ce86ba71..0000000000 --- a/mono/metadata/assembly.c +++ /dev/null @@ -1,3653 +0,0 @@ -/* - * assembly.c: Routines for loading assemblies. - * - * Author: - * Miguel de Icaza (miguel@ximian.com) - * - * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com) - * Copyright 2004-2009 Novell, Inc (http://www.novell.com) - * Copyright 2011 Xamarin, Inc (http://www.xamarin.com) - * Licensed under the MIT license. See LICENSE file in the project root for full license information. - */ -#include -#include -#include -#include -#include -#include -#include "assembly.h" -#include "image.h" -#include "object-internals.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef HOST_WIN32 -#include -#include -#include -#endif - -#ifdef PLATFORM_MACOSX -#include -#endif - -/* AssemblyVersionMap: an assembly name, the assembly version set on which it is based, the assembly name it is replaced with and whether only versions lower than the current runtime version should be remapped */ -typedef struct { - const char* assembly_name; - guint8 version_set_index; - const char* new_assembly_name; - gboolean only_lower_versions; -} AssemblyVersionMap; - -/* the default search path is empty, the first slot is replaced with the computed value */ -static const char* -default_path [] = { - NULL, - NULL, - NULL -}; - -/* Contains the list of directories to be searched for assemblies (MONO_PATH) */ -static char **assemblies_path = NULL; - -/* Contains the list of directories that point to auxiliary GACs */ -static char **extra_gac_paths = NULL; - -#ifndef DISABLE_ASSEMBLY_REMAPPING -/* The list of system assemblies what will be remapped to the running - * runtime version. WARNING: this list must be sorted. - * The integer number is an index in the MonoRuntimeInfo structure, whose - * values can be found in domain.c - supported_runtimes. Look there - * to understand what remapping will be made. - * - * .NET version can be found at https://github.com/dotnet/coreclr/blob/master/src/inc/fxretarget.h#L99 - * - */ -static const AssemblyVersionMap framework_assemblies [] = { - {"Accessibility", 0}, - {"Commons.Xml.Relaxng", 0}, - {"I18N", 0}, - {"I18N.CJK", 0}, - {"I18N.MidEast", 0}, - {"I18N.Other", 0}, - {"I18N.Rare", 0}, - {"I18N.West", 0}, - {"Microsoft.Build.Engine", 2, NULL, TRUE}, - {"Microsoft.Build.Framework", 2, NULL, TRUE}, - {"Microsoft.Build.Tasks", 2, "Microsoft.Build.Tasks.v4.0"}, - {"Microsoft.Build.Tasks.v3.5", 2, "Microsoft.Build.Tasks.v4.0"}, - {"Microsoft.Build.Utilities", 2, "Microsoft.Build.Utilities.v4.0"}, - {"Microsoft.Build.Utilities.v3.5", 2, "Microsoft.Build.Utilities.v4.0"}, - {"Microsoft.VisualBasic", 1}, - {"Microsoft.VisualC", 1}, - {"Mono.Cairo", 0}, - {"Mono.CompilerServices.SymbolWriter", 0}, - {"Mono.Data", 0}, - {"Mono.Data.SybaseClient", 0}, - {"Mono.Data.Tds", 0}, - {"Mono.Data.TdsClient", 0}, - {"Mono.GetOptions", 0}, - {"Mono.Http", 0}, - {"Mono.Posix", 0}, - {"Mono.Security", 0}, - {"Mono.Security.Win32", 0}, - {"Mono.Xml.Ext", 0}, - {"Novell.Directory.Ldap", 0}, - {"PEAPI", 0}, - {"System", 0}, - {"System.ComponentModel.Composition", 2}, - {"System.ComponentModel.DataAnnotations", 2}, - {"System.Configuration", 0}, - {"System.Configuration.Install", 0}, - {"System.Core", 2}, - {"System.Data", 0}, - {"System.Data.Linq", 2}, - {"System.Data.OracleClient", 0}, - {"System.Data.Services", 2}, - {"System.Data.Services.Client", 2}, - {"System.Data.SqlXml", 0}, - {"System.Design", 0}, - {"System.DirectoryServices", 0}, - {"System.Drawing", 0}, - {"System.Drawing.Design", 0}, - {"System.EnterpriseServices", 0}, - {"System.IdentityModel", 3}, - {"System.IdentityModel.Selectors", 3}, - {"System.Management", 0}, - {"System.Messaging", 0}, - {"System.Net", 2}, - {"System.Runtime.Remoting", 0}, - {"System.Runtime.Serialization", 3}, - {"System.Runtime.Serialization.Formatters.Soap", 0}, - {"System.Security", 0}, - {"System.ServiceModel", 3}, - {"System.ServiceModel.Web", 2}, - {"System.ServiceProcess", 0}, - {"System.Transactions", 0}, - {"System.Web", 0}, - {"System.Web.Abstractions", 2}, - {"System.Web.DynamicData", 2}, - {"System.Web.Extensions", 2}, - {"System.Web.Mobile", 0}, - {"System.Web.Routing", 2}, - {"System.Web.Services", 0}, - {"System.Windows.Forms", 0}, - {"System.Xml", 0}, - {"System.Xml.Linq", 2}, - {"WindowsBase", 3}, - {"mscorlib", 0} -}; -#endif - -/* - * keeps track of loaded assemblies - */ -static GList *loaded_assemblies = NULL; -static MonoAssembly *corlib; - -#if defined(__native_client__) - -/* On Native Client, allow mscorlib to be loaded from memory */ -/* instead of loaded off disk. If these are not set, default */ -/* mscorlib loading will take place */ - -/* NOTE: If mscorlib data is passed to mono in this way then */ -/* it needs to remain allocated during the use of mono. */ - -static void *corlibData = NULL; -static size_t corlibSize = 0; - -void -mono_set_corlib_data (void *data, size_t size) -{ - corlibData = data; - corlibSize = size; -} - -#endif - -static char* unquote (const char *str); - -/* This protects loaded_assemblies and image->references */ -#define mono_assemblies_lock() mono_os_mutex_lock (&assemblies_mutex) -#define mono_assemblies_unlock() mono_os_mutex_unlock (&assemblies_mutex) -static mono_mutex_t assemblies_mutex; - -/* If defined, points to the bundled assembly information */ -const MonoBundledAssembly **bundles; - -static mono_mutex_t assembly_binding_mutex; - -/* Loaded assembly binding info */ -static GSList *loaded_assembly_bindings = NULL; - -/* Class lazy loading functions */ -static GENERATE_TRY_GET_CLASS_WITH_CACHE (internals_visible, System.Runtime.CompilerServices, InternalsVisibleToAttribute) - -static MonoAssembly* -mono_assembly_invoke_search_hook_internal (MonoAssemblyName *aname, MonoAssembly *requesting, gboolean refonly, gboolean postload); -static MonoAssembly* -mono_assembly_load_full_internal (MonoAssemblyName *aname, MonoAssembly *requesting, const char *basedir, MonoImageOpenStatus *status, gboolean refonly); -static MonoBoolean -mono_assembly_is_in_gac (const gchar *filanem); - -static gchar* -encode_public_tok (const guchar *token, gint32 len) -{ - const static gchar allowed [] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; - gchar *res; - int i; - - res = (gchar *)g_malloc (len * 2 + 1); - for (i = 0; i < len; i++) { - res [i * 2] = allowed [token [i] >> 4]; - res [i * 2 + 1] = allowed [token [i] & 0xF]; - } - res [len * 2] = 0; - return res; -} - -/** - * mono_public_tokens_are_equal: - * @pubt1: first public key token - * @pubt2: second public key token - * - * Compare two public key tokens and return #TRUE is they are equal and #FALSE - * otherwise. - */ -gboolean -mono_public_tokens_are_equal (const unsigned char *pubt1, const unsigned char *pubt2) -{ - return memcmp (pubt1, pubt2, 16) == 0; -} - -/** - * mono_set_assemblies_path: - * @path: list of paths that contain directories where Mono will look for assemblies - * - * Use this method to override the standard assembly lookup system and - * override any assemblies coming from the GAC. This is the method - * that supports the MONO_PATH variable. - * - * Notice that MONO_PATH and this method are really a very bad idea as - * it prevents the GAC from working and it prevents the standard - * resolution mechanisms from working. Nonetheless, for some debugging - * situations and bootstrapping setups, this is useful to have. - */ -void -mono_set_assemblies_path (const char* path) -{ - char **splitted, **dest; - - splitted = g_strsplit (path, G_SEARCHPATH_SEPARATOR_S, 1000); - if (assemblies_path) - g_strfreev (assemblies_path); - assemblies_path = dest = splitted; - while (*splitted) { - char *tmp = *splitted; - if (*tmp) - *dest++ = mono_path_canonicalize (tmp); - g_free (tmp); - splitted++; - } - *dest = *splitted; - - if (g_getenv ("MONO_DEBUG") == NULL) - return; - - splitted = assemblies_path; - while (*splitted) { - if (**splitted && !g_file_test (*splitted, G_FILE_TEST_IS_DIR)) - g_warning ("'%s' in MONO_PATH doesn't exist or has wrong permissions.", *splitted); - - splitted++; - } -} - -/* Native Client can't get this info from an environment variable so */ -/* it's passed in to the runtime, or set manually by embedding code. */ -#ifdef __native_client__ -char* nacl_mono_path = NULL; -#endif - -static void -check_path_env (void) -{ - const char* path; - path = g_getenv ("MONO_PATH"); -#ifdef __native_client__ - if (!path) - path = nacl_mono_path; -#endif - if (!path || assemblies_path != NULL) - return; - - mono_set_assemblies_path(path); -} - -static void -check_extra_gac_path_env (void) { - const char *path; - char **splitted, **dest; - - path = g_getenv ("MONO_GAC_PREFIX"); - if (!path) - return; - - splitted = g_strsplit (path, G_SEARCHPATH_SEPARATOR_S, 1000); - if (extra_gac_paths) - g_strfreev (extra_gac_paths); - extra_gac_paths = dest = splitted; - while (*splitted){ - if (**splitted) - *dest++ = *splitted; - splitted++; - } - *dest = *splitted; - - if (g_getenv ("MONO_DEBUG") == NULL) - return; - - while (*splitted) { - if (**splitted && !g_file_test (*splitted, G_FILE_TEST_IS_DIR)) - g_warning ("'%s' in MONO_GAC_PREFIX doesn't exist or has wrong permissions.", *splitted); - - splitted++; - } -} - -static gboolean -assembly_binding_maps_name (MonoAssemblyBindingInfo *info, MonoAssemblyName *aname) -{ - if (!info || !info->name) - return FALSE; - - if (strcmp (info->name, aname->name)) - return FALSE; - - if (info->major != aname->major || info->minor != aname->minor) - return FALSE; - - if ((info->culture != NULL && info->culture [0]) != (aname->culture != NULL && aname->culture [0])) - return FALSE; - - if (info->culture && aname->culture && strcmp (info->culture, aname->culture)) - return FALSE; - - if (!mono_public_tokens_are_equal (info->public_key_token, aname->public_key_token)) - return FALSE; - - return TRUE; -} - -static void -mono_assembly_binding_info_free (MonoAssemblyBindingInfo *info) -{ - if (!info) - return; - - g_free (info->name); - g_free (info->culture); -} - -static void -get_publisher_policy_info (MonoImage *image, MonoAssemblyName *aname, MonoAssemblyBindingInfo *binding_info) -{ - MonoTableInfo *t; - guint32 cols [MONO_MANIFEST_SIZE]; - const gchar *filename; - gchar *subpath, *fullpath; - - t = &image->tables [MONO_TABLE_MANIFESTRESOURCE]; - /* MS Impl. accepts policy assemblies with more than - * one manifest resource, and only takes the first one */ - if (t->rows < 1) { - binding_info->is_valid = FALSE; - return; - } - - mono_metadata_decode_row (t, 0, cols, MONO_MANIFEST_SIZE); - if ((cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) != MONO_IMPLEMENTATION_FILE) { - binding_info->is_valid = FALSE; - return; - } - - filename = mono_metadata_string_heap (image, cols [MONO_MANIFEST_NAME]); - g_assert (filename != NULL); - - subpath = g_path_get_dirname (image->name); - fullpath = g_build_path (G_DIR_SEPARATOR_S, subpath, filename, NULL); - mono_config_parse_publisher_policy (fullpath, binding_info); - g_free (subpath); - g_free (fullpath); - - /* Define the optional elements/attributes before checking */ - if (!binding_info->culture) - binding_info->culture = g_strdup (""); - - /* Check that the most important elements/attributes exist */ - if (!binding_info->name || !binding_info->public_key_token [0] || !binding_info->has_old_version_bottom || - !binding_info->has_new_version || !assembly_binding_maps_name (binding_info, aname)) { - mono_assembly_binding_info_free (binding_info); - binding_info->is_valid = FALSE; - return; - } - - binding_info->is_valid = TRUE; -} - -static int -compare_versions (AssemblyVersionSet *v, MonoAssemblyName *aname) -{ - if (v->major > aname->major) - return 1; - else if (v->major < aname->major) - return -1; - - if (v->minor > aname->minor) - return 1; - else if (v->minor < aname->minor) - return -1; - - if (v->build > aname->build) - return 1; - else if (v->build < aname->build) - return -1; - - if (v->revision > aname->revision) - return 1; - else if (v->revision < aname->revision) - return -1; - - return 0; -} - -static gboolean -check_policy_versions (MonoAssemblyBindingInfo *info, MonoAssemblyName *name) -{ - if (!info->is_valid) - return FALSE; - - /* If has_old_version_top doesn't exist, we don't have an interval */ - if (!info->has_old_version_top) { - if (compare_versions (&info->old_version_bottom, name) == 0) - return TRUE; - - return FALSE; - } - - /* Check that the version defined by name is valid for the interval */ - if (compare_versions (&info->old_version_top, name) < 0) - return FALSE; - - /* We should be greater or equal than the small version */ - if (compare_versions (&info->old_version_bottom, name) > 0) - return FALSE; - - return TRUE; -} - -/** - * mono_assembly_names_equal: - * @l: first assembly - * @r: second assembly. - * - * Compares two MonoAssemblyNames and returns whether they are equal. - * - * This compares the names, the cultures, the release version and their - * public tokens. - * - * Returns: TRUE if both assembly names are equal. - */ -gboolean -mono_assembly_names_equal (MonoAssemblyName *l, MonoAssemblyName *r) -{ - if (!l->name || !r->name) - return FALSE; - - if (strcmp (l->name, r->name)) - return FALSE; - - if (l->culture && r->culture && strcmp (l->culture, r->culture)) - return FALSE; - - if (l->major != r->major || l->minor != r->minor || - l->build != r->build || l->revision != r->revision) - if (! ((l->major == 0 && l->minor == 0 && l->build == 0 && l->revision == 0) || (r->major == 0 && r->minor == 0 && r->build == 0 && r->revision == 0))) - return FALSE; - - if (!l->public_key_token [0] || !r->public_key_token [0]) - return TRUE; - - if (!mono_public_tokens_are_equal (l->public_key_token, r->public_key_token)) - return FALSE; - - return TRUE; -} - -static MonoAssembly * -load_in_path (const char *basename, const char** search_path, MonoImageOpenStatus *status, MonoBoolean refonly) -{ - int i; - char *fullpath; - MonoAssembly *result; - - for (i = 0; search_path [i]; ++i) { - fullpath = g_build_filename (search_path [i], basename, NULL); - result = mono_assembly_open_full (fullpath, status, refonly); - g_free (fullpath); - if (result) - return result; - } - return NULL; -} - -/** - * mono_assembly_setrootdir: - * @root_dir: The pathname of the root directory where we will locate assemblies - * - * This routine sets the internal default root directory for looking up - * assemblies. - * - * This is used by Windows installations to compute dynamically the - * place where the Mono assemblies are located. - * - */ -void -mono_assembly_setrootdir (const char *root_dir) -{ - /* - * Override the MONO_ASSEMBLIES directory configured at compile time. - */ - /* Leak if called more than once */ - default_path [0] = g_strdup (root_dir); -} - -/** - * mono_assembly_getrootdir: - * - * Obtains the root directory used for looking up assemblies. - * - * Returns: a string with the directory, this string should not be freed. - */ -G_CONST_RETURN gchar * -mono_assembly_getrootdir (void) -{ - return default_path [0]; -} - -/** - * mono_set_dirs: - * @assembly_dir: the base directory for assemblies - * @config_dir: the base directory for configuration files - * - * This routine is used internally and by developers embedding - * the runtime into their own applications. - * - * There are a number of cases to consider: Mono as a system-installed - * package that is available on the location preconfigured or Mono in - * a relocated location. - * - * If you are using a system-installed Mono, you can pass NULL - * to both parameters. If you are not, you should compute both - * directory values and call this routine. - * - * The values for a given PREFIX are: - * - * assembly_dir: PREFIX/lib - * config_dir: PREFIX/etc - * - * Notice that embedders that use Mono in a relocated way must - * compute the location at runtime, as they will be in control - * of where Mono is installed. - */ -void -mono_set_dirs (const char *assembly_dir, const char *config_dir) -{ - if (assembly_dir == NULL) - assembly_dir = mono_config_get_assemblies_dir (); - if (config_dir == NULL) - config_dir = mono_config_get_cfg_dir (); - mono_assembly_setrootdir (assembly_dir); - mono_set_config_dir (config_dir); -} - -#ifndef HOST_WIN32 - -static char * -compute_base (char *path) -{ - char *p = strrchr (path, '/'); - if (p == NULL) - return NULL; - - /* Not a well known Mono executable, we are embedded, cant guess the base */ - if (strcmp (p, "/mono") && strcmp (p, "/mono-boehm") && strcmp (p, "/mono-sgen") && strcmp (p, "/pedump") && strcmp (p, "/monodis")) - return NULL; - - *p = 0; - p = strrchr (path, '/'); - if (p == NULL) - return NULL; - - if (strcmp (p, "/bin") != 0) - return NULL; - *p = 0; - return path; -} - -static void -fallback (void) -{ - mono_set_dirs (mono_config_get_assemblies_dir (), mono_config_get_cfg_dir ()); -} - -static G_GNUC_UNUSED void -set_dirs (char *exe) -{ - char *base; - char *config, *lib, *mono; - struct stat buf; - const char *bindir; - - /* - * Only /usr prefix is treated specially - */ - bindir = mono_config_get_bin_dir (); - g_assert (bindir); - if (strncmp (exe, bindir, strlen (bindir)) == 0 || (base = compute_base (exe)) == NULL){ - fallback (); - return; - } - - config = g_build_filename (base, "etc", NULL); - lib = g_build_filename (base, "lib", NULL); - mono = g_build_filename (lib, "mono/4.5", NULL); // FIXME: stop hardcoding 4.5 here - if (stat (mono, &buf) == -1) - fallback (); - else { - mono_set_dirs (lib, config); - } - - g_free (config); - g_free (lib); - g_free (mono); -} - -#endif /* HOST_WIN32 */ - -/** - * mono_set_rootdir: - * - * Registers the root directory for the Mono runtime, for Linux and Solaris 10, - * this auto-detects the prefix where Mono was installed. - */ -void -mono_set_rootdir (void) -{ -#if defined(HOST_WIN32) || (defined(PLATFORM_MACOSX) && !defined(TARGET_ARM)) - gchar *bindir, *installdir, *root, *name, *resolvedname, *config; - -#ifdef HOST_WIN32 - name = mono_get_module_file_name ((HMODULE) &__ImageBase); -#else - { - /* - * _NSGetExecutablePath may return -1 to indicate buf is not large - * enough, but we ignore that case to avoid having to do extra dynamic - * allocation for the path and hope that 4096 is enough - this is - * ok in the Linux/Solaris case below at least... - */ - - gchar buf[4096]; - guint buf_size = sizeof (buf); - - name = NULL; - if (_NSGetExecutablePath (buf, &buf_size) == 0) - name = g_strdup (buf); - - if (name == NULL) { - fallback (); - return; - } - } -#endif - - resolvedname = mono_path_resolve_symlinks (name); - - bindir = g_path_get_dirname (resolvedname); - installdir = g_path_get_dirname (bindir); - root = g_build_path (G_DIR_SEPARATOR_S, installdir, "lib", NULL); - - config = g_build_filename (root, "..", "etc", NULL); -#ifdef HOST_WIN32 - mono_set_dirs (root, config); -#else - if (g_file_test (root, G_FILE_TEST_EXISTS) && g_file_test (config, G_FILE_TEST_EXISTS)) - mono_set_dirs (root, config); - else - fallback (); -#endif - - g_free (config); - g_free (root); - g_free (installdir); - g_free (bindir); - g_free (name); - g_free (resolvedname); -#elif defined(DISABLE_MONO_AUTODETECTION) - fallback (); -#else - char buf [4096]; - int s; - char *str; - - /* Linux style */ - s = readlink ("/proc/self/exe", buf, sizeof (buf)-1); - - if (s != -1){ - buf [s] = 0; - set_dirs (buf); - return; - } - - /* Solaris 10 style */ - str = g_strdup_printf ("/proc/%d/path/a.out", getpid ()); - s = readlink (str, buf, sizeof (buf)-1); - g_free (str); - if (s != -1){ - buf [s] = 0; - set_dirs (buf); - return; - } - fallback (); -#endif -} - -/** - * mono_assemblies_init: - * - * Initialize global variables used by this module. - */ -void -mono_assemblies_init (void) -{ - /* - * Initialize our internal paths if we have not been initialized yet. - * This happens when embedders use Mono. - */ - if (mono_assembly_getrootdir () == NULL) - mono_set_rootdir (); - - check_path_env (); - check_extra_gac_path_env (); - - mono_os_mutex_init_recursive (&assemblies_mutex); - mono_os_mutex_init (&assembly_binding_mutex); -} - -static void -mono_assembly_binding_lock (void) -{ - mono_locks_os_acquire (&assembly_binding_mutex, AssemblyBindingLock); -} - -static void -mono_assembly_binding_unlock (void) -{ - mono_locks_os_release (&assembly_binding_mutex, AssemblyBindingLock); -} - -gboolean -mono_assembly_fill_assembly_name (MonoImage *image, MonoAssemblyName *aname) -{ - MonoTableInfo *t = &image->tables [MONO_TABLE_ASSEMBLY]; - guint32 cols [MONO_ASSEMBLY_SIZE]; - gint32 machine, flags; - - if (!t->rows) - return FALSE; - - mono_metadata_decode_row (t, 0, cols, MONO_ASSEMBLY_SIZE); - - aname->hash_len = 0; - aname->hash_value = NULL; - aname->name = mono_metadata_string_heap (image, cols [MONO_ASSEMBLY_NAME]); - aname->culture = mono_metadata_string_heap (image, cols [MONO_ASSEMBLY_CULTURE]); - aname->flags = cols [MONO_ASSEMBLY_FLAGS]; - aname->major = cols [MONO_ASSEMBLY_MAJOR_VERSION]; - aname->minor = cols [MONO_ASSEMBLY_MINOR_VERSION]; - aname->build = cols [MONO_ASSEMBLY_BUILD_NUMBER]; - aname->revision = cols [MONO_ASSEMBLY_REV_NUMBER]; - aname->hash_alg = cols [MONO_ASSEMBLY_HASH_ALG]; - if (cols [MONO_ASSEMBLY_PUBLIC_KEY]) { - guchar* token = (guchar *)g_malloc (8); - gchar* encoded; - const gchar* pkey; - int len; - - pkey = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLY_PUBLIC_KEY]); - len = mono_metadata_decode_blob_size (pkey, &pkey); - aname->public_key = (guchar*)pkey; - - mono_digest_get_public_token (token, aname->public_key, len); - encoded = encode_public_tok (token, 8); - g_strlcpy ((char*)aname->public_key_token, encoded, MONO_PUBLIC_KEY_TOKEN_LENGTH); - - g_free (encoded); - g_free (token); - } - else { - aname->public_key = NULL; - memset (aname->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH); - } - - if (cols [MONO_ASSEMBLY_PUBLIC_KEY]) { - aname->public_key = (guchar*)mono_metadata_blob_heap (image, cols [MONO_ASSEMBLY_PUBLIC_KEY]); - } - else - aname->public_key = 0; - - machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine; - flags = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags; - switch (machine) { - case COFF_MACHINE_I386: - /* https://bugzilla.xamarin.com/show_bug.cgi?id=17632 */ - if (flags & (CLI_FLAGS_32BITREQUIRED|CLI_FLAGS_PREFERRED32BIT)) - aname->arch = MONO_PROCESSOR_ARCHITECTURE_X86; - else if ((flags & 0x70) == 0x70) - aname->arch = MONO_PROCESSOR_ARCHITECTURE_NONE; - else - aname->arch = MONO_PROCESSOR_ARCHITECTURE_MSIL; - break; - case COFF_MACHINE_IA64: - aname->arch = MONO_PROCESSOR_ARCHITECTURE_IA64; - break; - case COFF_MACHINE_AMD64: - aname->arch = MONO_PROCESSOR_ARCHITECTURE_AMD64; - break; - case COFF_MACHINE_ARM: - aname->arch = MONO_PROCESSOR_ARCHITECTURE_ARM; - break; - default: - break; - } - - return TRUE; -} - -/** - * mono_stringify_assembly_name: - * @aname: the assembly name. - * - * Convert @aname into its string format. The returned string is dynamically - * allocated and should be freed by the caller. - * - * Returns: a newly allocated string with a string representation of - * the assembly name. - */ -char* -mono_stringify_assembly_name (MonoAssemblyName *aname) -{ - const char *quote = (aname->name && g_ascii_isspace (aname->name [0])) ? "\"" : ""; - - return g_strdup_printf ( - "%s%s%s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s%s", - quote, aname->name, quote, - aname->major, aname->minor, aname->build, aname->revision, - aname->culture && *aname->culture? aname->culture: "neutral", - aname->public_key_token [0] ? (char *)aname->public_key_token : "null", - (aname->flags & ASSEMBLYREF_RETARGETABLE_FLAG) ? ", Retargetable=Yes" : ""); -} - -static gchar* -assemblyref_public_tok (MonoImage *image, guint32 key_index, guint32 flags) -{ - const gchar *public_tok; - int len; - - public_tok = mono_metadata_blob_heap (image, key_index); - len = mono_metadata_decode_blob_size (public_tok, &public_tok); - - if (flags & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG) { - guchar token [8]; - mono_digest_get_public_token (token, (guchar*)public_tok, len); - return encode_public_tok (token, 8); - } - - return encode_public_tok ((guchar*)public_tok, len); -} - -/** - * mono_assembly_addref: - * @assemnly: the assembly to reference - * - * This routine increments the reference count on a MonoAssembly. - * The reference count is reduced every time the method mono_assembly_close() is - * invoked. - */ -void -mono_assembly_addref (MonoAssembly *assembly) -{ - InterlockedIncrement (&assembly->ref_count); -} - -/* - * CAUTION: This table must be kept in sync with - * ivkm/reflect/Fusion.cs - */ - -#define SILVERLIGHT_KEY "7cec85d7bea7798e" -#define WINFX_KEY "31bf3856ad364e35" -#define ECMA_KEY "b77a5c561934e089" -#define MSFINAL_KEY "b03f5f7f11d50a3a" - -typedef struct { - const char *name; - const char *from; - const char *to; -} KeyRemapEntry; - -static KeyRemapEntry key_remap_table[] = { - { "Microsoft.CSharp", WINFX_KEY, MSFINAL_KEY }, - { "System", SILVERLIGHT_KEY, ECMA_KEY }, - { "System.ComponentModel.Composition", WINFX_KEY, ECMA_KEY }, - { "System.ComponentModel.DataAnnotations", "ddd0da4d3e678217", WINFX_KEY }, - { "System.Core", SILVERLIGHT_KEY, ECMA_KEY }, - // FIXME: MS uses MSFINAL_KEY for .NET 4.5 - { "System.Net", SILVERLIGHT_KEY, MSFINAL_KEY }, - { "System.Numerics", WINFX_KEY, ECMA_KEY }, - { "System.Runtime.Serialization", SILVERLIGHT_KEY, ECMA_KEY }, - { "System.ServiceModel", WINFX_KEY, ECMA_KEY }, - { "System.ServiceModel.Web", SILVERLIGHT_KEY, WINFX_KEY }, - { "System.Windows", SILVERLIGHT_KEY, MSFINAL_KEY }, - { "System.Xml", SILVERLIGHT_KEY, ECMA_KEY }, - { "System.Xml.Linq", WINFX_KEY, ECMA_KEY }, - { "System.Xml.Serialization", WINFX_KEY, ECMA_KEY } -}; - -static void -remap_keys (MonoAssemblyName *aname) -{ - int i; - for (i = 0; i < G_N_ELEMENTS (key_remap_table); i++) { - const KeyRemapEntry *entry = &key_remap_table [i]; - - if (strcmp (aname->name, entry->name) || - !mono_public_tokens_are_equal (aname->public_key_token, (const unsigned char*) entry->from)) - continue; - - memcpy (aname->public_key_token, entry->to, MONO_PUBLIC_KEY_TOKEN_LENGTH); - - mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, - "Remapped public key token of retargetable assembly %s from %s to %s", - aname->name, entry->from, entry->to); - return; - } -} - -static MonoAssemblyName * -mono_assembly_remap_version (MonoAssemblyName *aname, MonoAssemblyName *dest_aname) -{ - const MonoRuntimeInfo *current_runtime; - int pos, first, last; - - if (aname->name == NULL) return aname; - - current_runtime = mono_get_runtime_info (); - - if (aname->flags & ASSEMBLYREF_RETARGETABLE_FLAG) { - const AssemblyVersionSet* vset; - - /* Remap to current runtime */ - vset = ¤t_runtime->version_sets [0]; - - memcpy (dest_aname, aname, sizeof(MonoAssemblyName)); - dest_aname->major = vset->major; - dest_aname->minor = vset->minor; - dest_aname->build = vset->build; - dest_aname->revision = vset->revision; - dest_aname->flags &= ~ASSEMBLYREF_RETARGETABLE_FLAG; - - /* Remap assembly name */ - if (!strcmp (aname->name, "System.Net")) - dest_aname->name = g_strdup ("System"); - - remap_keys (dest_aname); - - mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, - "The request to load the retargetable assembly %s v%d.%d.%d.%d was remapped to %s v%d.%d.%d.%d", - aname->name, - aname->major, aname->minor, aname->build, aname->revision, - dest_aname->name, - vset->major, vset->minor, vset->build, vset->revision - ); - - return dest_aname; - } - -#ifndef DISABLE_ASSEMBLY_REMAPPING - first = 0; - last = G_N_ELEMENTS (framework_assemblies) - 1; - - while (first <= last) { - int res; - pos = first + (last - first) / 2; - res = strcmp (aname->name, framework_assemblies[pos].assembly_name); - if (res == 0) { - const AssemblyVersionSet* vset; - int index = framework_assemblies[pos].version_set_index; - g_assert (index < G_N_ELEMENTS (current_runtime->version_sets)); - vset = ¤t_runtime->version_sets [index]; - - if (aname->major == vset->major && aname->minor == vset->minor && - aname->build == vset->build && aname->revision == vset->revision) - return aname; - - if (framework_assemblies[pos].only_lower_versions && compare_versions ((AssemblyVersionSet*)vset, aname) < 0) - return aname; - - if ((aname->major | aname->minor | aname->build | aname->revision) != 0) - mono_trace (G_LOG_LEVEL_WARNING, MONO_TRACE_ASSEMBLY, - "The request to load the assembly %s v%d.%d.%d.%d was remapped to v%d.%d.%d.%d", - aname->name, - aname->major, aname->minor, aname->build, aname->revision, - vset->major, vset->minor, vset->build, vset->revision - ); - - memcpy (dest_aname, aname, sizeof(MonoAssemblyName)); - dest_aname->major = vset->major; - dest_aname->minor = vset->minor; - dest_aname->build = vset->build; - dest_aname->revision = vset->revision; - if (framework_assemblies[pos].new_assembly_name != NULL) { - dest_aname->name = framework_assemblies[pos].new_assembly_name; - mono_trace (G_LOG_LEVEL_WARNING, MONO_TRACE_ASSEMBLY, - "The assembly name %s was remapped to %s", - aname->name, - dest_aname->name); - } - return dest_aname; - } else if (res < 0) { - last = pos - 1; - } else { - first = pos + 1; - } - } -#endif - - return aname; -} - -/** - * mono_assembly_get_assemblyref: - * @image: pointer to the MonoImage to extract the information from. - * @index: index to the assembly reference in the image. - * @aname: pointer to a `MonoAssemblyName` that will hold the returned value. - * - * Fills out the @aname with the assembly name of the @index assembly reference in @image. - */ -void -mono_assembly_get_assemblyref (MonoImage *image, int index, MonoAssemblyName *aname) -{ - MonoTableInfo *t; - guint32 cols [MONO_ASSEMBLYREF_SIZE]; - const char *hash; - - t = &image->tables [MONO_TABLE_ASSEMBLYREF]; - - mono_metadata_decode_row (t, index, cols, MONO_ASSEMBLYREF_SIZE); - - hash = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_HASH_VALUE]); - aname->hash_len = mono_metadata_decode_blob_size (hash, &hash); - aname->hash_value = hash; - aname->name = mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME]); - aname->culture = mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]); - aname->flags = cols [MONO_ASSEMBLYREF_FLAGS]; - aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION]; - aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION]; - aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER]; - aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER]; - - if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) { - gchar *token = assemblyref_public_tok (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY], aname->flags); - g_strlcpy ((char*)aname->public_key_token, token, MONO_PUBLIC_KEY_TOKEN_LENGTH); - g_free (token); - } else { - memset (aname->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH); - } -} - -void -mono_assembly_load_reference (MonoImage *image, int index) -{ - MonoAssembly *reference; - MonoAssemblyName aname; - MonoImageOpenStatus status; - - /* - * image->references is shared between threads, so we need to access - * it inside a critical section. - */ - mono_assemblies_lock (); - if (!image->references) { - MonoTableInfo *t = &image->tables [MONO_TABLE_ASSEMBLYREF]; - - image->references = g_new0 (MonoAssembly *, t->rows + 1); - image->nreferences = t->rows; - } - reference = image->references [index]; - mono_assemblies_unlock (); - if (reference) - return; - - mono_assembly_get_assemblyref (image, index, &aname); - - if (image->assembly && image->assembly->ref_only) { - /* We use the loaded corlib */ - if (!strcmp (aname.name, "mscorlib")) - reference = mono_assembly_load_full_internal (&aname, image->assembly, image->assembly->basedir, &status, FALSE); - else { - reference = mono_assembly_loaded_full (&aname, TRUE); - if (!reference) - /* Try a postload search hook */ - reference = mono_assembly_invoke_search_hook_internal (&aname, image->assembly, TRUE, TRUE); - } - - /* - * Here we must advice that the error was due to - * a non loaded reference using the ReflectionOnly api - */ - if (!reference) - reference = (MonoAssembly *)REFERENCE_MISSING; - } else { - /* we first try without setting the basedir: this can eventually result in a ResolveAssembly - * event which is the MS .net compatible behaviour (the assemblyresolve_event3.cs test has been fixed - * accordingly, it would fail on the MS runtime before). - * The second load attempt has the basedir set to keep compatibility with the old mono behavior, for - * example bug-349190.2.cs and who knows how much more code in the wild. - */ - reference = mono_assembly_load_full_internal (&aname, image->assembly, NULL, &status, FALSE); - if (!reference && image->assembly) - reference = mono_assembly_load_full_internal (&aname, image->assembly, image->assembly->basedir, &status, FALSE); - } - - if (reference == NULL){ - char *extra_msg; - - if (status == MONO_IMAGE_ERROR_ERRNO && errno == ENOENT) { - extra_msg = g_strdup_printf ("The assembly was not found in the Global Assembly Cache, a path listed in the MONO_PATH environment variable, or in the location of the executing assembly (%s).\n", image->assembly != NULL ? image->assembly->basedir : "" ); - } else if (status == MONO_IMAGE_ERROR_ERRNO) { - extra_msg = g_strdup_printf ("System error: %s\n", strerror (errno)); - } else if (status == MONO_IMAGE_MISSING_ASSEMBLYREF) { - extra_msg = g_strdup ("Cannot find an assembly referenced from this one.\n"); - } else if (status == MONO_IMAGE_IMAGE_INVALID) { - extra_msg = g_strdup ("The file exists but is not a valid assembly.\n"); - } else { - extra_msg = g_strdup (""); - } - - mono_trace (G_LOG_LEVEL_WARNING, MONO_TRACE_ASSEMBLY, "The following assembly referenced from %s could not be loaded:\n" - " Assembly: %s (assemblyref_index=%d)\n" - " Version: %d.%d.%d.%d\n" - " Public Key: %s\n%s", - image->name, aname.name, index, - aname.major, aname.minor, aname.build, aname.revision, - strlen ((char*)aname.public_key_token) == 0 ? "(none)" : (char*)aname.public_key_token, extra_msg); - g_free (extra_msg); - } - - mono_assemblies_lock (); - if (reference == NULL) { - /* Flag as not found */ - reference = (MonoAssembly *)REFERENCE_MISSING; - } - - if (!image->references [index]) { - if (reference != REFERENCE_MISSING){ - mono_assembly_addref (reference); - if (image->assembly) - mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Assembly Ref addref %s[%p] -> %s[%p]: %d", - image->assembly->aname.name, image->assembly, reference->aname.name, reference, reference->ref_count); - } else { - if (image->assembly) - mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Failed to load assembly %s[%p]\n", - image->assembly->aname.name, image->assembly); - } - - image->references [index] = reference; - } - mono_assemblies_unlock (); - - if (image->references [index] != reference) { - /* Somebody loaded it before us */ - mono_assembly_close (reference); - } -} - -/** - * mono_assembly_load_references: - * @image: - * @status: - * @deprecated: There is no reason to use this method anymore, it does nothing - * - * This method is now a no-op, it does nothing other than setting the @status to #MONO_IMAGE_OK - */ -void -mono_assembly_load_references (MonoImage *image, MonoImageOpenStatus *status) -{ - /* This is a no-op now but it is part of the embedding API so we can't remove it */ - *status = MONO_IMAGE_OK; -} - -typedef struct AssemblyLoadHook AssemblyLoadHook; -struct AssemblyLoadHook { - AssemblyLoadHook *next; - MonoAssemblyLoadFunc func; - gpointer user_data; -}; - -AssemblyLoadHook *assembly_load_hook = NULL; - -void -mono_assembly_invoke_load_hook (MonoAssembly *ass) -{ - AssemblyLoadHook *hook; - - for (hook = assembly_load_hook; hook; hook = hook->next) { - hook->func (ass, hook->user_data); - } -} - -void -mono_install_assembly_load_hook (MonoAssemblyLoadFunc func, gpointer user_data) -{ - AssemblyLoadHook *hook; - - g_return_if_fail (func != NULL); - - hook = g_new0 (AssemblyLoadHook, 1); - hook->func = func; - hook->user_data = user_data; - hook->next = assembly_load_hook; - assembly_load_hook = hook; -} - -static void -free_assembly_load_hooks (void) -{ - AssemblyLoadHook *hook, *next; - - for (hook = assembly_load_hook; hook; hook = next) { - next = hook->next; - g_free (hook); - } -} - -typedef struct AssemblySearchHook AssemblySearchHook; -struct AssemblySearchHook { - AssemblySearchHook *next; - MonoAssemblySearchFunc func; - gboolean refonly; - gboolean postload; - gpointer user_data; -}; - -AssemblySearchHook *assembly_search_hook = NULL; - -static MonoAssembly* -mono_assembly_invoke_search_hook_internal (MonoAssemblyName *aname, MonoAssembly *requesting, gboolean refonly, gboolean postload) -{ - AssemblySearchHook *hook; - - for (hook = assembly_search_hook; hook; hook = hook->next) { - if ((hook->refonly == refonly) && (hook->postload == postload)) { - MonoAssembly *ass; - /** - * A little explanation is in order here. - * - * The default postload search hook needs to know the requesting assembly to report it to managed code. - * The embedding API exposes a search hook that doesn't take such argument. - * - * The original fix would call the default search hook before all the registered ones and pass - * the requesting assembly to it. It works but broke a very suddle embedding API aspect that some users - * rely on. Which is the ordering between user hooks and the default runtime hook. - * - * Registering the hook after mono_jit_init would let your hook run before the default one and - * when using it to handle non standard app layouts this could save your app from a massive amount - * of syscalls that the default hook does when probing all sorts of places. Slow targets with horrible IO - * are all using this trick and if we broke this assumption they would be very disapointed at us. - * - * So what's the fix? We register the default hook using regular means and special case it when iterating - * over the registered hooks. This preserves ordering and enables managed resolve hooks to get the requesting - * assembly. - */ - if (hook->func == (void*)mono_domain_assembly_postload_search) - ass = mono_domain_assembly_postload_search (aname, requesting, refonly); - else - ass = hook->func (aname, hook->user_data); - if (ass) - return ass; - } - } - - return NULL; -} - -MonoAssembly* -mono_assembly_invoke_search_hook (MonoAssemblyName *aname) -{ - return mono_assembly_invoke_search_hook_internal (aname, NULL, FALSE, FALSE); -} - -static void -mono_install_assembly_search_hook_internal (MonoAssemblySearchFunc func, gpointer user_data, gboolean refonly, gboolean postload) -{ - AssemblySearchHook *hook; - - g_return_if_fail (func != NULL); - - hook = g_new0 (AssemblySearchHook, 1); - hook->func = func; - hook->user_data = user_data; - hook->refonly = refonly; - hook->postload = postload; - hook->next = assembly_search_hook; - assembly_search_hook = hook; -} - -void -mono_install_assembly_search_hook (MonoAssemblySearchFunc func, gpointer user_data) -{ - mono_install_assembly_search_hook_internal (func, user_data, FALSE, FALSE); -} - -static void -free_assembly_search_hooks (void) -{ - AssemblySearchHook *hook, *next; - - for (hook = assembly_search_hook; hook; hook = next) { - next = hook->next; - g_free (hook); - } -} - -void -mono_install_assembly_refonly_search_hook (MonoAssemblySearchFunc func, gpointer user_data) -{ - mono_install_assembly_search_hook_internal (func, user_data, TRUE, FALSE); -} - -void -mono_install_assembly_postload_search_hook (MonoAssemblySearchFunc func, gpointer user_data) -{ - mono_install_assembly_search_hook_internal (func, user_data, FALSE, TRUE); -} - -void -mono_install_assembly_postload_refonly_search_hook (MonoAssemblySearchFunc func, gpointer user_data) -{ - mono_install_assembly_search_hook_internal (func, user_data, TRUE, TRUE); -} - -typedef struct AssemblyPreLoadHook AssemblyPreLoadHook; -struct AssemblyPreLoadHook { - AssemblyPreLoadHook *next; - MonoAssemblyPreLoadFunc func; - gpointer user_data; -}; - -static AssemblyPreLoadHook *assembly_preload_hook = NULL; -static AssemblyPreLoadHook *assembly_refonly_preload_hook = NULL; - -static MonoAssembly * -invoke_assembly_preload_hook (MonoAssemblyName *aname, gchar **assemblies_path) -{ - AssemblyPreLoadHook *hook; - MonoAssembly *assembly; - - for (hook = assembly_preload_hook; hook; hook = hook->next) { - assembly = hook->func (aname, assemblies_path, hook->user_data); - if (assembly != NULL) - return assembly; - } - - return NULL; -} - -static MonoAssembly * -invoke_assembly_refonly_preload_hook (MonoAssemblyName *aname, gchar **assemblies_path) -{ - AssemblyPreLoadHook *hook; - MonoAssembly *assembly; - - for (hook = assembly_refonly_preload_hook; hook; hook = hook->next) { - assembly = hook->func (aname, assemblies_path, hook->user_data); - if (assembly != NULL) - return assembly; - } - - return NULL; -} - -void -mono_install_assembly_preload_hook (MonoAssemblyPreLoadFunc func, gpointer user_data) -{ - AssemblyPreLoadHook *hook; - - g_return_if_fail (func != NULL); - - hook = g_new0 (AssemblyPreLoadHook, 1); - hook->func = func; - hook->user_data = user_data; - hook->next = assembly_preload_hook; - assembly_preload_hook = hook; -} - -void -mono_install_assembly_refonly_preload_hook (MonoAssemblyPreLoadFunc func, gpointer user_data) -{ - AssemblyPreLoadHook *hook; - - g_return_if_fail (func != NULL); - - hook = g_new0 (AssemblyPreLoadHook, 1); - hook->func = func; - hook->user_data = user_data; - hook->next = assembly_refonly_preload_hook; - assembly_refonly_preload_hook = hook; -} - -static void -free_assembly_preload_hooks (void) -{ - AssemblyPreLoadHook *hook, *next; - - for (hook = assembly_preload_hook; hook; hook = next) { - next = hook->next; - g_free (hook); - } - - for (hook = assembly_refonly_preload_hook; hook; hook = next) { - next = hook->next; - g_free (hook); - } -} - -static gchar * -absolute_dir (const gchar *filename) -{ - gchar *cwd; - gchar *mixed; - gchar **parts; - gchar *part; - GList *list, *tmp; - GString *result; - gchar *res; - gint i; - - if (g_path_is_absolute (filename)) { - part = g_path_get_dirname (filename); - res = g_strconcat (part, G_DIR_SEPARATOR_S, NULL); - g_free (part); - return res; - } - - cwd = g_get_current_dir (); - mixed = g_build_filename (cwd, filename, NULL); - parts = g_strsplit (mixed, G_DIR_SEPARATOR_S, 0); - g_free (mixed); - g_free (cwd); - - list = NULL; - for (i = 0; (part = parts [i]) != NULL; i++) { - if (!strcmp (part, ".")) - continue; - - if (!strcmp (part, "..")) { - if (list && list->next) /* Don't remove root */ - list = g_list_delete_link (list, list); - } else { - list = g_list_prepend (list, part); - } - } - - result = g_string_new (""); - list = g_list_reverse (list); - - /* Ignores last data pointer, which should be the filename */ - for (tmp = list; tmp && tmp->next != NULL; tmp = tmp->next){ - if (tmp->data) - g_string_append_printf (result, "%s%c", (char *) tmp->data, - G_DIR_SEPARATOR); - } - - res = result->str; - g_string_free (result, FALSE); - g_list_free (list); - g_strfreev (parts); - if (*res == '\0') { - g_free (res); - return g_strdup ("."); - } - - return res; -} - -/** - * mono_assembly_open_from_bundle: - * @filename: Filename requested - * @status: return status code - * - * This routine tries to open the assembly specified by `filename' from the - * defined bundles, if found, returns the MonoImage for it, if not found - * returns NULL - */ -MonoImage * -mono_assembly_open_from_bundle (const char *filename, MonoImageOpenStatus *status, gboolean refonly) -{ - int i; - char *name; - MonoImage *image = NULL; - - /* - * we do a very simple search for bundled assemblies: it's not a general - * purpose assembly loading mechanism. - */ - - if (!bundles) - return NULL; - - name = g_path_get_basename (filename); - - mono_assemblies_lock (); - for (i = 0; !image && bundles [i]; ++i) { - if (strcmp (bundles [i]->name, name) == 0) { - image = mono_image_open_from_data_with_name ((char*)bundles [i]->data, bundles [i]->size, FALSE, status, refonly, name); - break; - } - } - mono_assemblies_unlock (); - if (image) { - mono_image_addref (image); - mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Assembly Loader loaded assembly from bundle: '%s'.", name); - g_free (name); - return image; - } - g_free (name); - return NULL; -} - -/** - * mono_assemblies_open_full: - * @filename: the file to load - * @status: return status code - * @refonly: Whether this assembly is being opened in "reflection-only" mode. -* - * This loads an assembly from the specified @filename. The @filename allows - * a local URL (starting with a file:// prefix). If a file prefix is used, the - * filename is interpreted as a URL, and the filename is URL-decoded. Otherwise the file - * is treated as a local path. - * - * First, an attempt is made to load the assembly from the bundled executable (for those - * deployments that have been done with the `mkbundle` tool or for scenarios where the - * assembly has been registered as an embedded assembly). If this is not the case, then - * the assembly is loaded from disk using `api:mono_image_open_full`. - * - * If the pointed assembly does not live in the Global Assembly Cache, a shadow copy of - * the assembly is made. - * - * If @refonly is set to true, then the assembly is loaded purely for inspection with - * the `System.Reflection` API. - * - * Returns: NULL on error, with the @status set to an error code, or a pointer - * to the assembly. - */ -MonoAssembly * -mono_assembly_open_full (const char *filename, MonoImageOpenStatus *status, gboolean refonly) -{ - MonoImage *image; - MonoAssembly *ass; - MonoImageOpenStatus def_status; - gchar *fname; - gchar *new_fname; - gboolean loaded_from_bundle; - - g_return_val_if_fail (filename != NULL, NULL); - - if (!status) - status = &def_status; - *status = MONO_IMAGE_OK; - - if (strncmp (filename, "file://", 7) == 0) { - GError *error = NULL; - gchar *uri = (gchar *) filename; - gchar *tmpuri; - - /* - * MS allows file://c:/... and fails on file://localhost/c:/... - * They also throw an IndexOutOfRangeException if "file://" - */ - if (uri [7] != '/') - uri = g_strdup_printf ("file:///%s", uri + 7); - - tmpuri = uri; - uri = mono_escape_uri_string (tmpuri); - fname = g_filename_from_uri (uri, NULL, &error); - g_free (uri); - - if (tmpuri != filename) - g_free (tmpuri); - - if (error != NULL) { - g_warning ("%s\n", error->message); - g_error_free (error); - fname = g_strdup (filename); - } - } else { - fname = g_strdup (filename); - } - - mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, - "Assembly Loader probing location: '%s'.", fname); - - new_fname = NULL; - if (!mono_assembly_is_in_gac (fname)) { - MonoError error; - new_fname = mono_make_shadow_copy (fname, &error); - if (!is_ok (&error)) { - mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, - "Assembly Loader shadow copy error: %s.", mono_error_get_message (&error)); - mono_error_cleanup (&error); - *status = MONO_IMAGE_IMAGE_INVALID; - g_free (fname); - return NULL; - } - } - if (new_fname && new_fname != fname) { - g_free (fname); - fname = new_fname; - mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, - "Assembly Loader shadow-copied assembly to: '%s'.", fname); - } - - image = NULL; - - // If VM built with mkbundle - loaded_from_bundle = FALSE; - if (bundles != NULL) { - image = mono_assembly_open_from_bundle (fname, status, refonly); - loaded_from_bundle = image != NULL; - } - - if (!image) - image = mono_image_open_full (fname, status, refonly); - - if (!image){ - if (*status == MONO_IMAGE_OK) - *status = MONO_IMAGE_ERROR_ERRNO; - g_free (fname); - return NULL; - } - - if (image->assembly) { - /* Already loaded by another appdomain */ - mono_assembly_invoke_load_hook (image->assembly); - mono_image_close (image); - g_free (fname); - return image->assembly; - } - - ass = mono_assembly_load_from_full (image, fname, status, refonly); - - if (ass) { - if (!loaded_from_bundle) - mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, - "Assembly Loader loaded assembly from location: '%s'.", filename); - if (!refonly) - mono_config_for_assembly (ass->image); - } - - /* Clear the reference added by mono_image_open */ - mono_image_close (image); - - g_free (fname); - - return ass; -} - -static void -free_item (gpointer val, gpointer user_data) -{ - g_free (val); -} - -/** - * mono_assembly_load_friends: - * @ass: an assembly - * - * Load the list of friend assemblies that are allowed to access - * the assembly's internal types and members. They are stored as assembly - * names in custom attributes. - * - * This is an internal method, we need this because when we load mscorlib - * we do not have the internals visible cattr loaded yet, - * so we need to load these after we initialize the runtime. - * - * LOCKING: Acquires the assemblies lock plus the loader lock. - */ -void -mono_assembly_load_friends (MonoAssembly* ass) -{ - MonoError error; - int i; - MonoCustomAttrInfo* attrs; - GSList *list; - - if (ass->friend_assembly_names_inited) - return; - - attrs = mono_custom_attrs_from_assembly_checked (ass, &error); - mono_error_assert_ok (&error); - if (!attrs) { - mono_assemblies_lock (); - ass->friend_assembly_names_inited = TRUE; - mono_assemblies_unlock (); - return; - } - - mono_assemblies_lock (); - if (ass->friend_assembly_names_inited) { - mono_assemblies_unlock (); - return; - } - mono_assemblies_unlock (); - - list = NULL; - /* - * We build the list outside the assemblies lock, the worse that can happen - * is that we'll need to free the allocated list. - */ - for (i = 0; i < attrs->num_attrs; ++i) { - MonoCustomAttrEntry *attr = &attrs->attrs [i]; - MonoAssemblyName *aname; - const gchar *data; - /* Do some sanity checking */ - if (!attr->ctor || attr->ctor->klass != mono_class_try_get_internals_visible_class ()) - continue; - if (attr->data_size < 4) - continue; - data = (const char*)attr->data; - /* 0xFF means null string, see custom attr format */ - if (data [0] != 1 || data [1] != 0 || (data [2] & 0xFF) == 0xFF) - continue; - mono_metadata_decode_value (data + 2, &data); - aname = g_new0 (MonoAssemblyName, 1); - /*g_print ("friend ass: %s\n", data);*/ - if (mono_assembly_name_parse_full (data, aname, TRUE, NULL, NULL)) { - list = g_slist_prepend (list, aname); - } else { - g_free (aname); - } - } - mono_custom_attrs_free (attrs); - - mono_assemblies_lock (); - if (ass->friend_assembly_names_inited) { - mono_assemblies_unlock (); - g_slist_foreach (list, free_item, NULL); - g_slist_free (list); - return; - } - ass->friend_assembly_names = list; - - /* Because of the double checked locking pattern above */ - mono_memory_barrier (); - ass->friend_assembly_names_inited = TRUE; - mono_assemblies_unlock (); -} - -/** - * mono_assembly_open: - * @filename: Opens the assembly pointed out by this name - * @status: return status code - * - * This loads an assembly from the specified @filename. The @filename allows - * a local URL (starting with a file:// prefix). If a file prefix is used, the - * filename is interpreted as a URL, and the filename is URL-decoded. Otherwise the file - * is treated as a local path. - * - * First, an attempt is made to load the assembly from the bundled executable (for those - * deployments that have been done with the `mkbundle` tool or for scenarios where the - * assembly has been registered as an embedded assembly). If this is not the case, then - * the assembly is loaded from disk using `api:mono_image_open_full`. - * - * If the pointed assembly does not live in the Global Assembly Cache, a shadow copy of - * the assembly is made. - * - * Return: a pointer to the MonoAssembly if @filename contains a valid - * assembly or NULL on error. Details about the error are stored in the - * @status variable. - */ -MonoAssembly * -mono_assembly_open (const char *filename, MonoImageOpenStatus *status) -{ - return mono_assembly_open_full (filename, status, FALSE); -} - -/** - * mono_assembly_load_from_full: - * @image: Image to load the assembly from - * @fname: assembly name to associate with the assembly - * @status: returns the status condition - * @refonly: Whether this assembly is being opened in "reflection-only" mode. - * - * If the provided @image has an assembly reference, it will process the given - * image as an assembly with the given name. - * - * Most likely you want to use the `api:mono_assembly_load_full` method instead. - * - * Returns: A valid pointer to a `MonoAssembly*` on success and the @status will be - * set to #MONO_IMAGE_OK; or NULL on error. - * - * If there is an error loading the assembly the @status will indicate the - * reason with @status being set to `MONO_IMAGE_INVALID` if the - * image did not contain an assembly reference table. - */ -MonoAssembly * -mono_assembly_load_from_full (MonoImage *image, const char*fname, - MonoImageOpenStatus *status, gboolean refonly) -{ - MonoAssembly *ass, *ass2; - char *base_dir; - - if (!image->tables [MONO_TABLE_ASSEMBLY].rows) { - /* 'image' doesn't have a manifest -- maybe someone is trying to Assembly.Load a .netmodule */ - *status = MONO_IMAGE_IMAGE_INVALID; - return NULL; - } - -#if defined (HOST_WIN32) - { - gchar *tmp_fn; - int i; - - tmp_fn = g_strdup (fname); - for (i = strlen (tmp_fn) - 1; i >= 0; i--) { - if (tmp_fn [i] == '/') - tmp_fn [i] = '\\'; - } - - base_dir = absolute_dir (tmp_fn); - g_free (tmp_fn); - } -#else - base_dir = absolute_dir (fname); -#endif - - /* - * Create assembly struct, and enter it into the assembly cache - */ - ass = g_new0 (MonoAssembly, 1); - ass->basedir = base_dir; - ass->ref_only = refonly; - ass->image = image; - - mono_profiler_assembly_event (ass, MONO_PROFILE_START_LOAD); - - mono_assembly_fill_assembly_name (image, &ass->aname); - - if (mono_defaults.corlib && strcmp (ass->aname.name, "mscorlib") == 0) { - // MS.NET doesn't support loading other mscorlibs - g_free (ass); - g_free (base_dir); - mono_image_addref (mono_defaults.corlib); - *status = MONO_IMAGE_OK; - return mono_defaults.corlib->assembly; - } - - /* Add a non-temporary reference because of ass->image */ - mono_image_addref (image); - - mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Image addref %s[%p] -> %s[%p]: %d", ass->aname.name, ass, image->name, image, image->ref_count); - - /* - * The load hooks might take locks so we can't call them while holding the - * assemblies lock. - */ - if (ass->aname.name) { - ass2 = mono_assembly_invoke_search_hook_internal (&ass->aname, NULL, refonly, FALSE); - if (ass2) { - g_free (ass); - g_free (base_dir); - mono_image_close (image); - *status = MONO_IMAGE_OK; - return ass2; - } - } - - mono_assemblies_lock (); - - if (image->assembly) { - /* - * This means another thread has already loaded the assembly, but not yet - * called the load hooks so the search hook can't find the assembly. - */ - mono_assemblies_unlock (); - ass2 = image->assembly; - g_free (ass); - g_free (base_dir); - mono_image_close (image); - *status = MONO_IMAGE_OK; - return ass2; - } - - image->assembly = ass; - - loaded_assemblies = g_list_prepend (loaded_assemblies, ass); - mono_assemblies_unlock (); - -#ifdef HOST_WIN32 - if (image->is_module_handle) - mono_image_fixup_vtable (image); -#endif - - mono_assembly_invoke_load_hook (ass); - - mono_profiler_assembly_loaded (ass, MONO_PROFILE_OK); - - return ass; -} - -/** - * mono_assembly_load_from: - * @image: Image to load the assembly from - * @fname: assembly name to associate with the assembly - * @status: return status code - * - * If the provided @image has an assembly reference, it will process the given - * image as an assembly with the given name. - * - * Most likely you want to use the `api:mono_assembly_load_full` method instead. - * - * This is equivalent to calling `api:mono_assembly_load_from_full` with the - * @refonly parameter set to FALSE. - * Returns: A valid pointer to a `MonoAssembly*` on success and the @status will be - * set to #MONO_IMAGE_OK; or NULL on error. - * - * If there is an error loading the assembly the @status will indicate the - * reason with @status being set to `MONO_IMAGE_INVALID` if the - * image did not contain an assembly reference table. - - */ -MonoAssembly * -mono_assembly_load_from (MonoImage *image, const char *fname, - MonoImageOpenStatus *status) -{ - return mono_assembly_load_from_full (image, fname, status, FALSE); -} - -/** - * mono_assembly_name_free: - * @aname: assembly name to free - * - * Frees the provided assembly name object. - * (it does not frees the object itself, only the name members). - */ -void -mono_assembly_name_free (MonoAssemblyName *aname) -{ - if (aname == NULL) - return; - - g_free ((void *) aname->name); - g_free ((void *) aname->culture); - g_free ((void *) aname->hash_value); -} - -static gboolean -parse_public_key (const gchar *key, gchar** pubkey, gboolean *is_ecma) -{ - const gchar *pkey; - gchar header [16], val, *arr; - gint i, j, offset, bitlen, keylen, pkeylen; - - keylen = strlen (key) >> 1; - if (keylen < 1) - return FALSE; - - /* allow the ECMA standard key */ - if (strcmp (key, "00000000000000000400000000000000") == 0) { - if (pubkey) { - *pubkey = g_strdup (key); - *is_ecma = TRUE; - } - return TRUE; - } - *is_ecma = FALSE; - val = g_ascii_xdigit_value (key [0]) << 4; - val |= g_ascii_xdigit_value (key [1]); - switch (val) { - case 0x00: - if (keylen < 13) - return FALSE; - val = g_ascii_xdigit_value (key [24]); - val |= g_ascii_xdigit_value (key [25]); - if (val != 0x06) - return FALSE; - pkey = key + 24; - break; - case 0x06: - pkey = key; - break; - default: - return FALSE; - } - - /* We need the first 16 bytes - * to check whether this key is valid or not */ - pkeylen = strlen (pkey) >> 1; - if (pkeylen < 16) - return FALSE; - - for (i = 0, j = 0; i < 16; i++) { - header [i] = g_ascii_xdigit_value (pkey [j++]) << 4; - header [i] |= g_ascii_xdigit_value (pkey [j++]); - } - - if (header [0] != 0x06 || /* PUBLICKEYBLOB (0x06) */ - header [1] != 0x02 || /* Version (0x02) */ - header [2] != 0x00 || /* Reserved (word) */ - header [3] != 0x00 || - (guint)(read32 (header + 8)) != 0x31415352) /* DWORD magic = RSA1 */ - return FALSE; - - /* Based on this length, we _should_ be able to know if the length is right */ - bitlen = read32 (header + 12) >> 3; - if ((bitlen + 16 + 4) != pkeylen) - return FALSE; - - /* parsing is OK and the public key itself is not requested back */ - if (!pubkey) - return TRUE; - - /* Encode the size of the blob */ - offset = 0; - if (keylen <= 127) { - arr = (gchar *)g_malloc (keylen + 1); - arr [offset++] = keylen; - } else { - arr = (gchar *)g_malloc (keylen + 2); - arr [offset++] = 0x80; /* 10bs */ - arr [offset++] = keylen; - } - - for (i = offset, j = 0; i < keylen + offset; i++) { - arr [i] = g_ascii_xdigit_value (key [j++]) << 4; - arr [i] |= g_ascii_xdigit_value (key [j++]); - } - - *pubkey = arr; - - return TRUE; -} - -static gboolean -build_assembly_name (const char *name, const char *version, const char *culture, const char *token, const char *key, guint32 flags, guint32 arch, MonoAssemblyName *aname, gboolean save_public_key) -{ - gint major, minor, build, revision; - gint len; - gint version_parts; - gchar *pkey, *pkeyptr, *encoded, tok [8]; - - memset (aname, 0, sizeof (MonoAssemblyName)); - - if (version) { - version_parts = sscanf (version, "%u.%u.%u.%u", &major, &minor, &build, &revision); - if (version_parts < 2 || version_parts > 4) - return FALSE; - - /* FIXME: we should set build & revision to -1 (instead of 0) - if these are not set in the version string. That way, later on, - we can still determine if these were specified. */ - aname->major = major; - aname->minor = minor; - if (version_parts >= 3) - aname->build = build; - else - aname->build = 0; - if (version_parts == 4) - aname->revision = revision; - else - aname->revision = 0; - } - - aname->flags = flags; - aname->arch = arch; - aname->name = g_strdup (name); - - if (culture) { - if (g_ascii_strcasecmp (culture, "neutral") == 0) - aname->culture = g_strdup (""); - else - aname->culture = g_strdup (culture); - } - - if (token && strncmp (token, "null", 4) != 0) { - char *lower; - - /* the constant includes the ending NULL, hence the -1 */ - if (strlen (token) != (MONO_PUBLIC_KEY_TOKEN_LENGTH - 1)) { - mono_assembly_name_free (aname); - return FALSE; - } - lower = g_ascii_strdown (token, MONO_PUBLIC_KEY_TOKEN_LENGTH); - g_strlcpy ((char*)aname->public_key_token, lower, MONO_PUBLIC_KEY_TOKEN_LENGTH); - g_free (lower); - } - - if (key) { - gboolean is_ecma; - if (strcmp (key, "null") == 0 || !parse_public_key (key, &pkey, &is_ecma)) { - mono_assembly_name_free (aname); - return FALSE; - } - - if (is_ecma) { - if (save_public_key) - aname->public_key = (guint8*)pkey; - else - g_free (pkey); - g_strlcpy ((gchar*)aname->public_key_token, "b77a5c561934e089", MONO_PUBLIC_KEY_TOKEN_LENGTH); - return TRUE; - } - - len = mono_metadata_decode_blob_size ((const gchar *) pkey, (const gchar **) &pkeyptr); - // We also need to generate the key token - mono_digest_get_public_token ((guchar*) tok, (guint8*) pkeyptr, len); - encoded = encode_public_tok ((guchar*) tok, 8); - g_strlcpy ((gchar*)aname->public_key_token, encoded, MONO_PUBLIC_KEY_TOKEN_LENGTH); - g_free (encoded); - - if (save_public_key) - aname->public_key = (guint8*) pkey; - else - g_free (pkey); - } - - return TRUE; -} - -static gboolean -parse_assembly_directory_name (const char *name, const char *dirname, MonoAssemblyName *aname) -{ - gchar **parts; - gboolean res; - - parts = g_strsplit (dirname, "_", 3); - if (!parts || !parts[0] || !parts[1] || !parts[2]) { - g_strfreev (parts); - return FALSE; - } - - res = build_assembly_name (name, parts[0], parts[1], parts[2], NULL, 0, 0, aname, FALSE); - g_strfreev (parts); - return res; -} - -static gboolean -split_key_value (const gchar *pair, gchar **key, guint32 *keylen, gchar **value) -{ - char *eqsign = strchr (pair, '='); - if (!eqsign) { - *key = NULL; - *keylen = 0; - *value = NULL; - return FALSE; - } - - *key = (gchar*)pair; - *keylen = eqsign - *key; - while (*keylen > 0 && g_ascii_isspace ((*key) [*keylen - 1])) - (*keylen)--; - *value = g_strstrip (eqsign + 1); - return TRUE; -} - -gboolean -mono_assembly_name_parse_full (const char *name, MonoAssemblyName *aname, gboolean save_public_key, gboolean *is_version_defined, gboolean *is_token_defined) -{ - gchar *dllname; - gchar *dllname_uq; - gchar *version = NULL; - gchar *version_uq; - gchar *culture = NULL; - gchar *culture_uq; - gchar *token = NULL; - gchar *token_uq; - gchar *key = NULL; - gchar *key_uq; - gchar *retargetable = NULL; - gchar *retargetable_uq; - gchar *procarch; - gchar *procarch_uq; - gboolean res; - gchar *value, *part_name; - guint32 part_name_len; - gchar **parts; - gchar **tmp; - gboolean version_defined; - gboolean token_defined; - guint32 flags = 0; - guint32 arch = MONO_PROCESSOR_ARCHITECTURE_NONE; - - if (!is_version_defined) - is_version_defined = &version_defined; - *is_version_defined = FALSE; - if (!is_token_defined) - is_token_defined = &token_defined; - *is_token_defined = FALSE; - - parts = tmp = g_strsplit (name, ",", 6); - if (!tmp || !*tmp) { - g_strfreev (tmp); - return FALSE; - } - - dllname = g_strstrip (*tmp); - - tmp++; - - while (*tmp) { - if (!split_key_value (g_strstrip (*tmp), &part_name, &part_name_len, &value)) - goto cleanup_and_fail; - - if (part_name_len == 7 && !g_ascii_strncasecmp (part_name, "Version", part_name_len)) { - *is_version_defined = TRUE; - version = value; - if (strlen (version) == 0) { - goto cleanup_and_fail; - } - tmp++; - continue; - } - - if (part_name_len == 7 && !g_ascii_strncasecmp (part_name, "Culture", part_name_len)) { - culture = value; - if (strlen (culture) == 0) { - goto cleanup_and_fail; - } - tmp++; - continue; - } - - if (part_name_len == 14 && !g_ascii_strncasecmp (part_name, "PublicKeyToken", part_name_len)) { - *is_token_defined = TRUE; - token = value; - if (strlen (token) == 0) { - goto cleanup_and_fail; - } - tmp++; - continue; - } - - if (part_name_len == 9 && !g_ascii_strncasecmp (part_name, "PublicKey", part_name_len)) { - key = value; - if (strlen (key) == 0) { - goto cleanup_and_fail; - } - tmp++; - continue; - } - - if (part_name_len == 12 && !g_ascii_strncasecmp (part_name, "Retargetable", part_name_len)) { - retargetable = value; - retargetable_uq = unquote (retargetable); - if (retargetable_uq != NULL) - retargetable = retargetable_uq; - - if (!g_ascii_strcasecmp (retargetable, "yes")) { - flags |= ASSEMBLYREF_RETARGETABLE_FLAG; - } else if (g_ascii_strcasecmp (retargetable, "no")) { - free (retargetable_uq); - goto cleanup_and_fail; - } - - free (retargetable_uq); - tmp++; - continue; - } - - if (part_name_len == 21 && !g_ascii_strncasecmp (part_name, "ProcessorArchitecture", part_name_len)) { - procarch = value; - procarch_uq = unquote (procarch); - if (procarch_uq != NULL) - procarch = procarch_uq; - - if (!g_ascii_strcasecmp (procarch, "MSIL")) - arch = MONO_PROCESSOR_ARCHITECTURE_MSIL; - else if (!g_ascii_strcasecmp (procarch, "X86")) - arch = MONO_PROCESSOR_ARCHITECTURE_X86; - else if (!g_ascii_strcasecmp (procarch, "IA64")) - arch = MONO_PROCESSOR_ARCHITECTURE_IA64; - else if (!g_ascii_strcasecmp (procarch, "AMD64")) - arch = MONO_PROCESSOR_ARCHITECTURE_AMD64; - else { - free (procarch_uq); - goto cleanup_and_fail; - } - - free (procarch_uq); - tmp++; - continue; - } - - g_strfreev (parts); - return FALSE; - } - - /* if retargetable flag is set, then we must have a fully qualified name */ - if (retargetable != NULL && (version == NULL || culture == NULL || (key == NULL && token == NULL))) { - goto cleanup_and_fail; - } - - dllname_uq = unquote (dllname); - version_uq = unquote (version); - culture_uq = unquote (culture); - token_uq = unquote (token); - key_uq = unquote (key); - - res = build_assembly_name ( - dllname_uq == NULL ? dllname : dllname_uq, - version_uq == NULL ? version : version_uq, - culture_uq == NULL ? culture : culture_uq, - token_uq == NULL ? token : token_uq, - key_uq == NULL ? key : key_uq, - flags, arch, aname, save_public_key); - - free (dllname_uq); - free (version_uq); - free (culture_uq); - free (token_uq); - free (key_uq); - - g_strfreev (parts); - return res; - -cleanup_and_fail: - g_strfreev (parts); - return FALSE; -} - -static char* -unquote (const char *str) -{ - gint slen; - const char *end; - - if (str == NULL) - return NULL; - - slen = strlen (str); - if (slen < 2) - return NULL; - - if (*str != '\'' && *str != '\"') - return NULL; - - end = str + slen - 1; - if (*str != *end) - return NULL; - - return g_strndup (str + 1, slen - 2); -} - -/** - * mono_assembly_name_parse: - * @name: name to parse - * @aname: the destination assembly name - * - * Parses an assembly qualified type name and assigns the name, - * version, culture and token to the provided assembly name object. - * - * Returns: TRUE if the name could be parsed. - */ -gboolean -mono_assembly_name_parse (const char *name, MonoAssemblyName *aname) -{ - return mono_assembly_name_parse_full (name, aname, FALSE, NULL, NULL); -} - -/** - * mono_assembly_name_new: - * @name: name to parse - * - * Allocate a new MonoAssemblyName and fill its values from the - * passed @name. - * - * Returns: a newly allocated structure or NULL if there was any failure. - */ -MonoAssemblyName* -mono_assembly_name_new (const char *name) -{ - MonoAssemblyName *aname = g_new0 (MonoAssemblyName, 1); - if (mono_assembly_name_parse (name, aname)) - return aname; - g_free (aname); - return NULL; -} - -const char* -mono_assembly_name_get_name (MonoAssemblyName *aname) -{ - return aname->name; -} - -const char* -mono_assembly_name_get_culture (MonoAssemblyName *aname) -{ - return aname->culture; -} - -mono_byte* -mono_assembly_name_get_pubkeytoken (MonoAssemblyName *aname) -{ - if (aname->public_key_token [0]) - return aname->public_key_token; - return NULL; -} - -uint16_t -mono_assembly_name_get_version (MonoAssemblyName *aname, uint16_t *minor, uint16_t *build, uint16_t *revision) -{ - if (minor) - *minor = aname->minor; - if (build) - *build = aname->build; - if (revision) - *revision = aname->revision; - return aname->major; -} - -static MonoAssembly* -probe_for_partial_name (const char *basepath, const char *fullname, MonoAssemblyName *aname, MonoImageOpenStatus *status) -{ - gchar *fullpath = NULL; - GDir *dirhandle; - const char* direntry; - MonoAssemblyName gac_aname; - gint major=-1, minor=0, build=0, revision=0; - gboolean exact_version; - - dirhandle = g_dir_open (basepath, 0, NULL); - if (!dirhandle) - return NULL; - - exact_version = (aname->major | aname->minor | aname->build | aname->revision) != 0; - - while ((direntry = g_dir_read_name (dirhandle))) { - gboolean match = TRUE; - - if(!parse_assembly_directory_name (aname->name, direntry, &gac_aname)) - continue; - - if (aname->culture != NULL && strcmp (aname->culture, gac_aname.culture) != 0) - match = FALSE; - - if (match && strlen ((char*)aname->public_key_token) > 0 && - !mono_public_tokens_are_equal (aname->public_key_token, gac_aname.public_key_token)) - match = FALSE; - - if (match) { - if (exact_version) { - match = (aname->major == gac_aname.major && aname->minor == gac_aname.minor && - aname->build == gac_aname.build && aname->revision == gac_aname.revision); - } - else if (gac_aname.major < major) - match = FALSE; - else if (gac_aname.major == major) { - if (gac_aname.minor < minor) - match = FALSE; - else if (gac_aname.minor == minor) { - if (gac_aname.build < build) - match = FALSE; - else if (gac_aname.build == build && gac_aname.revision <= revision) - match = FALSE; - } - } - } - - if (match) { - major = gac_aname.major; - minor = gac_aname.minor; - build = gac_aname.build; - revision = gac_aname.revision; - g_free (fullpath); - fullpath = g_build_path (G_DIR_SEPARATOR_S, basepath, direntry, fullname, NULL); - } - - mono_assembly_name_free (&gac_aname); - } - - g_dir_close (dirhandle); - - if (fullpath == NULL) - return NULL; - else { - MonoAssembly *res = mono_assembly_open (fullpath, status); - g_free (fullpath); - return res; - } -} - -/** - * mono_assembly_load_with_partial_name: - * @name: an assembly name that is then parsed by `api:mono_assembly_name_parse`. - * @status: return status code - * - * Loads a Mono Assembly from a name. The name is parsed using `api:mono_assembly_name_parse`, - * so it might contain a qualified type name, version, culture and token. - * - * This will load the assembly from the file whose name is derived from the assembly name - * by appending the .dll extension. - * - * The assembly is loaded from either one of the extra Global Assembly Caches specified - * by the extra GAC paths (specified by the `MONO_GAC_PREFIX` environment variable) or - * if that fails from the GAC. - * - * Returns: NULL on failure, or a pointer to a MonoAssembly on success. - */ -MonoAssembly* -mono_assembly_load_with_partial_name (const char *name, MonoImageOpenStatus *status) -{ - MonoError error; - MonoAssembly *res; - MonoAssemblyName *aname, base_name; - MonoAssemblyName mapped_aname; - gchar *fullname, *gacpath; - gchar **paths; - - memset (&base_name, 0, sizeof (MonoAssemblyName)); - aname = &base_name; - - if (!mono_assembly_name_parse (name, aname)) - return NULL; - - /* - * If no specific version has been requested, make sure we load the - * correct version for system assemblies. - */ - if ((aname->major | aname->minor | aname->build | aname->revision) == 0) - aname = mono_assembly_remap_version (aname, &mapped_aname); - - res = mono_assembly_loaded (aname); - if (res) { - mono_assembly_name_free (aname); - return res; - } - - res = invoke_assembly_preload_hook (aname, assemblies_path); - if (res) { - res->in_gac = FALSE; - mono_assembly_name_free (aname); - return res; - } - - fullname = g_strdup_printf ("%s.dll", aname->name); - - if (extra_gac_paths) { - paths = extra_gac_paths; - while (!res && *paths) { - gacpath = g_build_path (G_DIR_SEPARATOR_S, *paths, "lib", "mono", "gac", aname->name, NULL); - res = probe_for_partial_name (gacpath, fullname, aname, status); - g_free (gacpath); - paths++; - } - } - - if (res) { - res->in_gac = TRUE; - g_free (fullname); - mono_assembly_name_free (aname); - return res; - } - - gacpath = g_build_path (G_DIR_SEPARATOR_S, mono_assembly_getrootdir (), "mono", "gac", aname->name, NULL); - res = probe_for_partial_name (gacpath, fullname, aname, status); - g_free (gacpath); - - if (res) - res->in_gac = TRUE; - else { - MonoDomain *domain = mono_domain_get (); - MonoReflectionAssembly *refasm; - - refasm = mono_try_assembly_resolve (domain, mono_string_new (domain, name), NULL, FALSE, &error); - if (!is_ok (&error)) { - g_free (fullname); - mono_assembly_name_free (aname); - mono_error_cleanup (&error); - if (*status == MONO_IMAGE_OK) - *status = MONO_IMAGE_IMAGE_INVALID; - } - - if (refasm) - res = refasm->assembly; - } - - g_free (fullname); - mono_assembly_name_free (aname); - - return res; -} - -static MonoBoolean -mono_assembly_is_in_gac (const gchar *filename) -{ - const gchar *rootdir; - gchar *gp; - gchar **paths; - - if (filename == NULL) - return FALSE; - - for (paths = extra_gac_paths; paths && *paths; paths++) { - if (strstr (*paths, filename) != *paths) - continue; - - gp = (gchar *) (filename + strlen (*paths)); - if (*gp != G_DIR_SEPARATOR) - continue; - gp++; - if (strncmp (gp, "lib", 3)) - continue; - gp += 3; - if (*gp != G_DIR_SEPARATOR) - continue; - gp++; - if (strncmp (gp, "mono", 4)) - continue; - gp += 4; - if (*gp != G_DIR_SEPARATOR) - continue; - gp++; - if (strncmp (gp, "gac", 3)) - continue; - gp += 3; - if (*gp != G_DIR_SEPARATOR) - continue; - - return TRUE; - } - - rootdir = mono_assembly_getrootdir (); - if (strstr (filename, rootdir) != filename) - return FALSE; - - gp = (gchar *) (filename + strlen (rootdir)); - if (*gp != G_DIR_SEPARATOR) - return FALSE; - gp++; - if (strncmp (gp, "mono", 4)) - return FALSE; - gp += 4; - if (*gp != G_DIR_SEPARATOR) - return FALSE; - gp++; - if (strncmp (gp, "gac", 3)) - return FALSE; - gp += 3; - if (*gp != G_DIR_SEPARATOR) - return FALSE; - return TRUE; -} - -static MonoImage* -mono_assembly_load_publisher_policy (MonoAssemblyName *aname) -{ - MonoImage *image; - gchar *filename, *pname, *name, *culture, *version, *fullpath, *subpath; - gchar **paths; - gint32 len; - - if (strstr (aname->name, ".dll")) { - len = strlen (aname->name) - 4; - name = (gchar *)g_malloc (len + 1); - strncpy (name, aname->name, len); - name[len] = 0; - } else - name = g_strdup (aname->name); - - if (aname->culture) - culture = g_utf8_strdown (aname->culture, -1); - else - culture = g_strdup (""); - - pname = g_strdup_printf ("policy.%d.%d.%s", aname->major, aname->minor, name); - version = g_strdup_printf ("0.0.0.0_%s_%s", culture, aname->public_key_token); - g_free (name); - g_free (culture); - - filename = g_strconcat (pname, ".dll", NULL); - subpath = g_build_path (G_DIR_SEPARATOR_S, pname, version, filename, NULL); - g_free (pname); - g_free (version); - g_free (filename); - - image = NULL; - if (extra_gac_paths) { - paths = extra_gac_paths; - while (!image && *paths) { - fullpath = g_build_path (G_DIR_SEPARATOR_S, *paths, - "lib", "mono", "gac", subpath, NULL); - image = mono_image_open (fullpath, NULL); - g_free (fullpath); - paths++; - } - } - - if (image) { - g_free (subpath); - return image; - } - - fullpath = g_build_path (G_DIR_SEPARATOR_S, mono_assembly_getrootdir (), - "mono", "gac", subpath, NULL); - image = mono_image_open (fullpath, NULL); - g_free (subpath); - g_free (fullpath); - - return image; -} - -static MonoAssemblyName* -mono_assembly_bind_version (MonoAssemblyBindingInfo *info, MonoAssemblyName *aname, MonoAssemblyName *dest_name) -{ - memcpy (dest_name, aname, sizeof (MonoAssemblyName)); - dest_name->major = info->new_version.major; - dest_name->minor = info->new_version.minor; - dest_name->build = info->new_version.build; - dest_name->revision = info->new_version.revision; - - return dest_name; -} - -/* LOCKING: assembly_binding lock must be held */ -static MonoAssemblyBindingInfo* -search_binding_loaded (MonoAssemblyName *aname) -{ - GSList *tmp; - - for (tmp = loaded_assembly_bindings; tmp; tmp = tmp->next) { - MonoAssemblyBindingInfo *info = (MonoAssemblyBindingInfo *)tmp->data; - if (assembly_binding_maps_name (info, aname)) - return info; - } - - return NULL; -} - -static inline gboolean -info_compare_versions (AssemblyVersionSet *left, AssemblyVersionSet *right) -{ - if (left->major != right->major || left->minor != right->minor || - left->build != right->build || left->revision != right->revision) - return FALSE; - - return TRUE; -} - -static inline gboolean -info_versions_equal (MonoAssemblyBindingInfo *left, MonoAssemblyBindingInfo *right) -{ - if (left->has_old_version_bottom != right->has_old_version_bottom) - return FALSE; - - if (left->has_old_version_top != right->has_old_version_top) - return FALSE; - - if (left->has_new_version != right->has_new_version) - return FALSE; - - if (left->has_old_version_bottom && !info_compare_versions (&left->old_version_bottom, &right->old_version_bottom)) - return FALSE; - - if (left->has_old_version_top && !info_compare_versions (&left->old_version_top, &right->old_version_top)) - return FALSE; - - if (left->has_new_version && !info_compare_versions (&left->new_version, &right->new_version)) - return FALSE; - - return TRUE; -} - -/* LOCKING: assumes all the necessary locks are held */ -static void -assembly_binding_info_parsed (MonoAssemblyBindingInfo *info, void *user_data) -{ - MonoAssemblyBindingInfo *info_copy; - GSList *tmp; - MonoAssemblyBindingInfo *info_tmp; - MonoDomain *domain = (MonoDomain*)user_data; - - if (!domain) - return; - - for (tmp = domain->assembly_bindings; tmp; tmp = tmp->next) { - info_tmp = (MonoAssemblyBindingInfo *)tmp->data; - if (strcmp (info->name, info_tmp->name) == 0 && info_versions_equal (info, info_tmp)) - return; - } - - info_copy = (MonoAssemblyBindingInfo *)mono_mempool_alloc0 (domain->mp, sizeof (MonoAssemblyBindingInfo)); - memcpy (info_copy, info, sizeof (MonoAssemblyBindingInfo)); - if (info->name) - info_copy->name = mono_mempool_strdup (domain->mp, info->name); - if (info->culture) - info_copy->culture = mono_mempool_strdup (domain->mp, info->culture); - - domain->assembly_bindings = g_slist_append_mempool (domain->mp, domain->assembly_bindings, info_copy); -} - -static int -get_version_number (int major, int minor) -{ - return major * 256 + minor; -} - -static inline gboolean -info_major_minor_in_range (MonoAssemblyBindingInfo *info, MonoAssemblyName *aname) -{ - int aname_version_number = get_version_number (aname->major, aname->minor); - if (!info->has_old_version_bottom) - return FALSE; - - if (get_version_number (info->old_version_bottom.major, info->old_version_bottom.minor) > aname_version_number) - return FALSE; - - if (info->has_old_version_top && get_version_number (info->old_version_top.major, info->old_version_top.minor) < aname_version_number) - return FALSE; - - /* This is not the nicest way to do it, but it's a by-product of the way parsing is done */ - info->major = aname->major; - info->minor = aname->minor; - - return TRUE; -} - -/* LOCKING: Assumes that we are already locked - both loader and domain locks */ -static MonoAssemblyBindingInfo* -get_per_domain_assembly_binding_info (MonoDomain *domain, MonoAssemblyName *aname) -{ - MonoAssemblyBindingInfo *info; - GSList *list; - - if (!domain->assembly_bindings) - return NULL; - - info = NULL; - for (list = domain->assembly_bindings; list; list = list->next) { - info = (MonoAssemblyBindingInfo *)list->data; - if (info && !strcmp (aname->name, info->name) && info_major_minor_in_range (info, aname)) - break; - info = NULL; - } - - if (info) { - if (info->name && info->public_key_token [0] && info->has_old_version_bottom && - info->has_new_version && assembly_binding_maps_name (info, aname)) - info->is_valid = TRUE; - else - info->is_valid = FALSE; - } - - return info; -} - -static MonoAssemblyName* -mono_assembly_apply_binding (MonoAssemblyName *aname, MonoAssemblyName *dest_name) -{ - MonoError error; - MonoAssemblyBindingInfo *info, *info2; - MonoImage *ppimage; - MonoDomain *domain; - - if (aname->public_key_token [0] == 0) - return aname; - - domain = mono_domain_get (); - - mono_assembly_binding_lock (); - info = search_binding_loaded (aname); - mono_assembly_binding_unlock (); - - if (!info) { - mono_domain_lock (domain); - info = get_per_domain_assembly_binding_info (domain, aname); - mono_domain_unlock (domain); - } - - if (info) { - if (!check_policy_versions (info, aname)) - return aname; - - mono_assembly_bind_version (info, aname, dest_name); - return dest_name; - } - - if (domain && domain->setup && domain->setup->configuration_file) { - mono_domain_lock (domain); - if (!domain->assembly_bindings_parsed) { - gchar *domain_config_file_name = mono_string_to_utf8_checked (domain->setup->configuration_file, &error); - mono_error_raise_exception (&error); /* FIXME don't raise here */ - - gchar *domain_config_file_path = mono_portability_find_file (domain_config_file_name, TRUE); - - if (!domain_config_file_path) - domain_config_file_path = domain_config_file_name; - - mono_config_parse_assembly_bindings (domain_config_file_path, aname->major, aname->minor, domain, assembly_binding_info_parsed); - domain->assembly_bindings_parsed = TRUE; - if (domain_config_file_name != domain_config_file_path) - g_free (domain_config_file_name); - g_free (domain_config_file_path); - } - - info2 = get_per_domain_assembly_binding_info (domain, aname); - - if (info2) { - info = (MonoAssemblyBindingInfo *)g_memdup (info2, sizeof (MonoAssemblyBindingInfo)); - info->name = g_strdup (info2->name); - info->culture = g_strdup (info2->culture); - info->domain_id = domain->domain_id; - } - - mono_domain_unlock (domain); - } - - if (!info) { - info = g_new0 (MonoAssemblyBindingInfo, 1); - info->major = aname->major; - info->minor = aname->minor; - } - - if (!info->is_valid) { - ppimage = mono_assembly_load_publisher_policy (aname); - if (ppimage) { - get_publisher_policy_info (ppimage, aname, info); - mono_image_close (ppimage); - } - } - - /* Define default error value if needed */ - if (!info->is_valid) { - info->name = g_strdup (aname->name); - info->culture = g_strdup (aname->culture); - g_strlcpy ((char *)info->public_key_token, (const char *)aname->public_key_token, MONO_PUBLIC_KEY_TOKEN_LENGTH); - } - - mono_assembly_binding_lock (); - info2 = search_binding_loaded (aname); - if (info2) { - /* This binding was added by another thread - * before us */ - mono_assembly_binding_info_free (info); - g_free (info); - - info = info2; - } else - loaded_assembly_bindings = g_slist_prepend (loaded_assembly_bindings, info); - - mono_assembly_binding_unlock (); - - if (!info->is_valid || !check_policy_versions (info, aname)) - return aname; - - mono_assembly_bind_version (info, aname, dest_name); - return dest_name; -} - -/** - * mono_assembly_load_from_gac - * - * @aname: The assembly name object - */ -static MonoAssembly* -mono_assembly_load_from_gac (MonoAssemblyName *aname, gchar *filename, MonoImageOpenStatus *status, MonoBoolean refonly) -{ - MonoAssembly *result = NULL; - gchar *name, *version, *culture, *fullpath, *subpath; - gint32 len; - gchar **paths; - char *pubtok; - - if (aname->public_key_token [0] == 0) { - return NULL; - } - - if (strstr (aname->name, ".dll")) { - len = strlen (filename) - 4; - name = (gchar *)g_malloc (len + 1); - strncpy (name, aname->name, len); - name[len] = 0; - } else { - name = g_strdup (aname->name); - } - - if (aname->culture) { - culture = g_utf8_strdown (aname->culture, -1); - } else { - culture = g_strdup (""); - } - - pubtok = g_ascii_strdown ((char*)aname->public_key_token, MONO_PUBLIC_KEY_TOKEN_LENGTH); - version = g_strdup_printf ("%d.%d.%d.%d_%s_%s", aname->major, - aname->minor, aname->build, aname->revision, - culture, pubtok); - g_free (pubtok); - - subpath = g_build_path (G_DIR_SEPARATOR_S, name, version, filename, NULL); - g_free (name); - g_free (version); - g_free (culture); - - if (extra_gac_paths) { - paths = extra_gac_paths; - while (!result && *paths) { - fullpath = g_build_path (G_DIR_SEPARATOR_S, *paths, "lib", "mono", "gac", subpath, NULL); - result = mono_assembly_open_full (fullpath, status, refonly); - g_free (fullpath); - paths++; - } - } - - if (result) { - result->in_gac = TRUE; - g_free (subpath); - return result; - } - - fullpath = g_build_path (G_DIR_SEPARATOR_S, mono_assembly_getrootdir (), - "mono", "gac", subpath, NULL); - result = mono_assembly_open_full (fullpath, status, refonly); - g_free (fullpath); - - if (result) - result->in_gac = TRUE; - - g_free (subpath); - - return result; -} - -MonoAssembly* -mono_assembly_load_corlib (const MonoRuntimeInfo *runtime, MonoImageOpenStatus *status) -{ - char *corlib_file; - MonoAssemblyName *aname; - - if (corlib) { - /* g_print ("corlib already loaded\n"); */ - return corlib; - } - - // In native client, Corlib is embedded in the executable as static variable corlibData -#if defined(__native_client__) - if (corlibData != NULL && corlibSize != 0) { - int status = 0; - /* First "FALSE" instructs mono not to make a copy. */ - /* Second "FALSE" says this is not just a ref. */ - MonoImage* image = mono_image_open_from_data_full (corlibData, corlibSize, FALSE, &status, FALSE); - if (image == NULL || status != 0) - g_print("mono_image_open_from_data_full failed: %d\n", status); - corlib = mono_assembly_load_from_full (image, "mscorlib", &status, FALSE); - if (corlib == NULL || status != 0) - g_print ("mono_assembly_load_from_full failed: %d\n", status); - if (corlib) - return corlib; - } -#endif - - // A nonstandard preload hook may provide a special mscorlib assembly - aname = mono_assembly_name_new ("mscorlib.dll"); - corlib = invoke_assembly_preload_hook (aname, assemblies_path); - mono_assembly_name_free (aname); - g_free (aname); - if (corlib != NULL) - goto return_corlib_and_facades; - - // This unusual directory layout can occur if mono is being built and run out of its own source repo - if (assemblies_path) { // Custom assemblies path set via MONO_PATH or mono_set_assemblies_path - corlib = load_in_path ("mscorlib.dll", (const char**)assemblies_path, status, FALSE); - if (corlib) - goto return_corlib_and_facades; - } - - /* Normal case: Load corlib from mono/ */ - corlib_file = g_build_filename ("mono", runtime->framework_version, "mscorlib.dll", NULL); - if (assemblies_path) { // Custom assemblies path - corlib = load_in_path (corlib_file, (const char**)assemblies_path, status, FALSE); - if (corlib) { - g_free (corlib_file); - goto return_corlib_and_facades; - } - } - corlib = load_in_path (corlib_file, default_path, status, FALSE); - g_free (corlib_file); - -return_corlib_and_facades: - if (corlib && !strcmp (runtime->framework_version, "4.5")) // FIXME: stop hardcoding 4.5 here - default_path [1] = g_strdup_printf ("%s/Facades", corlib->basedir); - - return corlib; -} - -MonoAssembly* -mono_assembly_load_full_nosearch (MonoAssemblyName *aname, - const char *basedir, - MonoImageOpenStatus *status, - gboolean refonly) -{ - MonoAssembly *result; - char *fullpath, *filename; - MonoAssemblyName maped_aname; - MonoAssemblyName maped_name_pp; - int ext_index; - const char *ext; - int len; - - aname = mono_assembly_remap_version (aname, &maped_aname); - - /* Reflection only assemblies don't get assembly binding */ - if (!refonly) - aname = mono_assembly_apply_binding (aname, &maped_name_pp); - - result = mono_assembly_loaded_full (aname, refonly); - if (result) - return result; - - result = refonly ? invoke_assembly_refonly_preload_hook (aname, assemblies_path) : invoke_assembly_preload_hook (aname, assemblies_path); - if (result) { - result->in_gac = FALSE; - return result; - } - - /* Currently we retrieve the loaded corlib for reflection - * only requests, like a common reflection only assembly - */ - if (strcmp (aname->name, "mscorlib") == 0 || strcmp (aname->name, "mscorlib.dll") == 0) { - return mono_assembly_load_corlib (mono_get_runtime_info (), status); - } - - len = strlen (aname->name); - for (ext_index = 0; ext_index < 2; ext_index ++) { - ext = ext_index == 0 ? ".dll" : ".exe"; - if (len > 4 && (!strcmp (aname->name + len - 4, ".dll") || !strcmp (aname->name + len - 4, ".exe"))) { - filename = g_strdup (aname->name); - /* Don't try appending .dll/.exe if it already has one of those extensions */ - ext_index++; - } else { - filename = g_strconcat (aname->name, ext, NULL); - } - - result = mono_assembly_load_from_gac (aname, filename, status, refonly); - if (result) { - g_free (filename); - return result; - } - - if (basedir) { - fullpath = g_build_filename (basedir, filename, NULL); - result = mono_assembly_open_full (fullpath, status, refonly); - g_free (fullpath); - if (result) { - result->in_gac = FALSE; - g_free (filename); - return result; - } - } - - result = load_in_path (filename, default_path, status, refonly); - if (result) - result->in_gac = FALSE; - g_free (filename); - if (result) - return result; - } - - return result; -} - -MonoAssembly* -mono_assembly_load_full_internal (MonoAssemblyName *aname, MonoAssembly *requesting, const char *basedir, MonoImageOpenStatus *status, gboolean refonly) -{ - MonoAssembly *result = mono_assembly_load_full_nosearch (aname, basedir, status, refonly); - - if (!result) - /* Try a postload search hook */ - result = mono_assembly_invoke_search_hook_internal (aname, requesting, refonly, TRUE); - return result; -} - -/** - * mono_assembly_load_full: - * @aname: A MonoAssemblyName with the assembly name to load. - * @basedir: A directory to look up the assembly at. - * @status: a pointer to a MonoImageOpenStatus to return the status of the load operation - * @refonly: Whether this assembly is being opened in "reflection-only" mode. - * - * Loads the assembly referenced by @aname, if the value of @basedir is not NULL, it - * attempts to load the assembly from that directory before probing the standard locations. - * - * If the assembly is being opened in reflection-only mode (@refonly set to TRUE) then no - * assembly binding takes place. - * - * Returns: the assembly referenced by @aname loaded or NULL on error. On error the - * value pointed by status is updated with an error code. - */ -MonoAssembly* -mono_assembly_load_full (MonoAssemblyName *aname, const char *basedir, MonoImageOpenStatus *status, gboolean refonly) -{ - return mono_assembly_load_full_internal (aname, NULL, basedir, status, refonly); -} - -/** - * mono_assembly_load: - * @aname: A MonoAssemblyName with the assembly name to load. - * @basedir: A directory to look up the assembly at. - * @status: a pointer to a MonoImageOpenStatus to return the status of the load operation - * - * Loads the assembly referenced by @aname, if the value of @basedir is not NULL, it - * attempts to load the assembly from that directory before probing the standard locations. - * - * Returns: the assembly referenced by @aname loaded or NULL on error. On error the - * value pointed by status is updated with an error code. - */ -MonoAssembly* -mono_assembly_load (MonoAssemblyName *aname, const char *basedir, MonoImageOpenStatus *status) -{ - return mono_assembly_load_full_internal (aname, NULL, basedir, status, FALSE); -} - -/** - * mono_assembly_loaded_full: - * @aname: an assembly to look for. - * @refonly: Whether this assembly is being opened in "reflection-only" mode. - * - * This is used to determine if the specified assembly has been loaded - * Returns: NULL If the given @aname assembly has not been loaded, or a pointer to - * a `MonoAssembly` that matches the `MonoAssemblyName` specified. - */ -MonoAssembly* -mono_assembly_loaded_full (MonoAssemblyName *aname, gboolean refonly) -{ - MonoAssembly *res; - MonoAssemblyName maped_aname; - - aname = mono_assembly_remap_version (aname, &maped_aname); - - res = mono_assembly_invoke_search_hook_internal (aname, NULL, refonly, FALSE); - - return res; -} - -/** - * mono_assembly_loaded: - * @aname: an assembly to look for. - * - * This is used to determine if the specified assembly has been loaded - - * Returns: NULL If the given @aname assembly has not been loaded, or a pointer to - * a `MonoAssembly` that matches the `MonoAssemblyName` specified. - */ -MonoAssembly* -mono_assembly_loaded (MonoAssemblyName *aname) -{ - return mono_assembly_loaded_full (aname, FALSE); -} - -void -mono_assembly_release_gc_roots (MonoAssembly *assembly) -{ - if (assembly == NULL || assembly == REFERENCE_MISSING) - return; - - if (assembly_is_dynamic (assembly)) { - int i; - MonoDynamicImage *dynimg = (MonoDynamicImage *)assembly->image; - for (i = 0; i < dynimg->image.module_count; ++i) - mono_dynamic_image_release_gc_roots ((MonoDynamicImage *)dynimg->image.modules [i]); - mono_dynamic_image_release_gc_roots (dynimg); - } -} - -/* - * Returns whether mono_assembly_close_finish() must be called as - * well. See comment for mono_image_close_except_pools() for why we - * unload in two steps. - */ -gboolean -mono_assembly_close_except_image_pools (MonoAssembly *assembly) -{ - GSList *tmp; - g_return_val_if_fail (assembly != NULL, FALSE); - - if (assembly == REFERENCE_MISSING) - return FALSE; - - /* Might be 0 already */ - if (InterlockedDecrement (&assembly->ref_count) > 0) - return FALSE; - - mono_profiler_assembly_event (assembly, MONO_PROFILE_START_UNLOAD); - - mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Unloading assembly %s [%p].", assembly->aname.name, assembly); - - mono_debug_close_image (assembly->image); - - mono_assemblies_lock (); - loaded_assemblies = g_list_remove (loaded_assemblies, assembly); - mono_assemblies_unlock (); - - assembly->image->assembly = NULL; - - if (!mono_image_close_except_pools (assembly->image)) - assembly->image = NULL; - - for (tmp = assembly->friend_assembly_names; tmp; tmp = tmp->next) { - MonoAssemblyName *fname = (MonoAssemblyName *)tmp->data; - mono_assembly_name_free (fname); - g_free (fname); - } - g_slist_free (assembly->friend_assembly_names); - g_free (assembly->basedir); - - mono_profiler_assembly_event (assembly, MONO_PROFILE_END_UNLOAD); - - return TRUE; -} - -void -mono_assembly_close_finish (MonoAssembly *assembly) -{ - g_assert (assembly && assembly != REFERENCE_MISSING); - - if (assembly->image) - mono_image_close_finish (assembly->image); - - if (assembly_is_dynamic (assembly)) { - g_free ((char*)assembly->aname.culture); - } else { - g_free (assembly); - } -} - -/** - * mono_assembly_close: - * @assembly: the assembly to release. - * - * This method releases a reference to the @assembly. The assembly is - * only released when all the outstanding references to it are released. - */ -void -mono_assembly_close (MonoAssembly *assembly) -{ - if (mono_assembly_close_except_image_pools (assembly)) - mono_assembly_close_finish (assembly); -} - -MonoImage* -mono_assembly_load_module (MonoAssembly *assembly, guint32 idx) -{ - return mono_image_load_file_for_image (assembly->image, idx); -} - -/** - * mono_assembly_foreach: - * @func: function to invoke for each assembly loaded - * @user_data: data passed to the callback - * - * Invokes the provided @func callback for each assembly loaded into - * the runtime. The first parameter passed to the callback is the - * `MonoAssembly*`, and the second parameter is the @user_data. - * - * This is done for all assemblies loaded in the runtime, not just - * those loaded in the current application domain. - */ -void -mono_assembly_foreach (GFunc func, gpointer user_data) -{ - GList *copy; - - /* - * We make a copy of the list to avoid calling the callback inside the - * lock, which could lead to deadlocks. - */ - mono_assemblies_lock (); - copy = g_list_copy (loaded_assemblies); - mono_assemblies_unlock (); - - g_list_foreach (loaded_assemblies, func, user_data); - - g_list_free (copy); -} - -/** - * mono_assemblies_cleanup: - * - * Free all resources used by this module. - */ -void -mono_assemblies_cleanup (void) -{ - GSList *l; - - mono_os_mutex_destroy (&assemblies_mutex); - mono_os_mutex_destroy (&assembly_binding_mutex); - - for (l = loaded_assembly_bindings; l; l = l->next) { - MonoAssemblyBindingInfo *info = (MonoAssemblyBindingInfo *)l->data; - - mono_assembly_binding_info_free (info); - g_free (info); - } - g_slist_free (loaded_assembly_bindings); - - free_assembly_load_hooks (); - free_assembly_search_hooks (); - free_assembly_preload_hooks (); -} - -/*LOCKING takes the assembly_binding lock*/ -void -mono_assembly_cleanup_domain_bindings (guint32 domain_id) -{ - GSList **iter; - - mono_assembly_binding_lock (); - iter = &loaded_assembly_bindings; - while (*iter) { - GSList *l = *iter; - MonoAssemblyBindingInfo *info = (MonoAssemblyBindingInfo *)l->data; - - if (info->domain_id == domain_id) { - *iter = l->next; - mono_assembly_binding_info_free (info); - g_free (info); - g_slist_free_1 (l); - } else { - iter = &l->next; - } - } - mono_assembly_binding_unlock (); -} - -/* - * Holds the assembly of the application, for - * System.Diagnostics.Process::MainModule - */ -static MonoAssembly *main_assembly=NULL; - -void -mono_assembly_set_main (MonoAssembly *assembly) -{ - main_assembly = assembly; -} - -/** - * mono_assembly_get_main: - * - * Returns: the assembly for the application, the first assembly that is loaded by the VM - */ -MonoAssembly * -mono_assembly_get_main (void) -{ - return (main_assembly); -} - -/** - * mono_assembly_get_image: - * @assembly: The assembly to retrieve the image from - * - * Returns: the MonoImage associated with this assembly. - */ -MonoImage* -mono_assembly_get_image (MonoAssembly *assembly) -{ - return assembly->image; -} - -/** - * mono_assembly_get_name: - * @assembly: The assembly to retrieve the name from - * - * The returned name's lifetime is the same as @assembly's. - * - * Returns: the MonoAssemblyName associated with this assembly. - */ -MonoAssemblyName * -mono_assembly_get_name (MonoAssembly *assembly) -{ - return &assembly->aname; -} - -void -mono_register_bundled_assemblies (const MonoBundledAssembly **assemblies) -{ - bundles = assemblies; -} - -#define MONO_DECLSEC_FORMAT_10 0x3C -#define MONO_DECLSEC_FORMAT_20 0x2E -#define MONO_DECLSEC_FIELD 0x53 -#define MONO_DECLSEC_PROPERTY 0x54 - -#define SKIP_VISIBILITY_XML_ATTRIBUTE ("\"SkipVerification\"") -#define SKIP_VISIBILITY_ATTRIBUTE_NAME ("System.Security.Permissions.SecurityPermissionAttribute") -#define SKIP_VISIBILITY_ATTRIBUTE_SIZE (sizeof (SKIP_VISIBILITY_ATTRIBUTE_NAME) - 1) -#define SKIP_VISIBILITY_PROPERTY_NAME ("SkipVerification") -#define SKIP_VISIBILITY_PROPERTY_SIZE (sizeof (SKIP_VISIBILITY_PROPERTY_NAME) - 1) - -static gboolean -mono_assembly_try_decode_skip_verification_param (const char *p, const char **resp, gboolean *abort_decoding) -{ - int len; - switch (*p++) { - case MONO_DECLSEC_PROPERTY: - break; - case MONO_DECLSEC_FIELD: - default: - *abort_decoding = TRUE; - return FALSE; - break; - } - - if (*p++ != MONO_TYPE_BOOLEAN) { - *abort_decoding = TRUE; - return FALSE; - } - - /* property name length */ - len = mono_metadata_decode_value (p, &p); - - if (len >= SKIP_VISIBILITY_PROPERTY_SIZE && !memcmp (p, SKIP_VISIBILITY_PROPERTY_NAME, SKIP_VISIBILITY_PROPERTY_SIZE)) { - p += len; - return *p; - } - p += len + 1; - - *resp = p; - return FALSE; -} - -static gboolean -mono_assembly_try_decode_skip_verification (const char *p, const char *endn) -{ - int i, j, num, len, params_len; - - if (*p == MONO_DECLSEC_FORMAT_10) { - gsize read, written; - char *res = g_convert (p, endn - p, "UTF-8", "UTF-16LE", &read, &written, NULL); - if (res) { - gboolean found = strstr (res, SKIP_VISIBILITY_XML_ATTRIBUTE) != NULL; - g_free (res); - return found; - } - return FALSE; - } - if (*p++ != MONO_DECLSEC_FORMAT_20) - return FALSE; - - /* number of encoded permission attributes */ - num = mono_metadata_decode_value (p, &p); - for (i = 0; i < num; ++i) { - gboolean is_valid = FALSE; - gboolean abort_decoding = FALSE; - - /* attribute name length */ - len = mono_metadata_decode_value (p, &p); - - /* We don't really need to fully decode the type. Comparing the name is enough */ - is_valid = len >= SKIP_VISIBILITY_ATTRIBUTE_SIZE && !memcmp (p, SKIP_VISIBILITY_ATTRIBUTE_NAME, SKIP_VISIBILITY_ATTRIBUTE_SIZE); - - p += len; - - /*size of the params table*/ - params_len = mono_metadata_decode_value (p, &p); - if (is_valid) { - const char *params_end = p + params_len; - - /* number of parameters */ - len = mono_metadata_decode_value (p, &p); - - for (j = 0; j < len; ++j) { - if (mono_assembly_try_decode_skip_verification_param (p, &p, &abort_decoding)) - return TRUE; - if (abort_decoding) - break; - } - p = params_end; - } else { - p += params_len; - } - } - - return FALSE; -} - - -gboolean -mono_assembly_has_skip_verification (MonoAssembly *assembly) -{ - MonoTableInfo *t; - guint32 cols [MONO_DECL_SECURITY_SIZE]; - const char *blob; - int i, len; - - if (MONO_SECMAN_FLAG_INIT (assembly->skipverification)) - return MONO_SECMAN_FLAG_GET_VALUE (assembly->skipverification); - - t = &assembly->image->tables [MONO_TABLE_DECLSECURITY]; - - for (i = 0; i < t->rows; ++i) { - mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE); - if ((cols [MONO_DECL_SECURITY_PARENT] & MONO_HAS_DECL_SECURITY_MASK) != MONO_HAS_DECL_SECURITY_ASSEMBLY) - continue; - if (cols [MONO_DECL_SECURITY_ACTION] != SECURITY_ACTION_REQMIN) - continue; - - blob = mono_metadata_blob_heap (assembly->image, cols [MONO_DECL_SECURITY_PERMISSIONSET]); - len = mono_metadata_decode_blob_size (blob, &blob); - if (!len) - continue; - - if (mono_assembly_try_decode_skip_verification (blob, blob + len)) { - MONO_SECMAN_FLAG_SET_VALUE (assembly->skipverification, TRUE); - return TRUE; - } - } - - MONO_SECMAN_FLAG_SET_VALUE (assembly->skipverification, FALSE); - return FALSE; -} diff --git a/mono/metadata/assembly.c.REMOVED.git-id b/mono/metadata/assembly.c.REMOVED.git-id new file mode 100644 index 0000000000..7892bef234 --- /dev/null +++ b/mono/metadata/assembly.c.REMOVED.git-id @@ -0,0 +1 @@ +f3feda4554cd8067c41f9d7baacaaf0d00bb7b02 \ No newline at end of file diff --git a/mono/metadata/assembly.h b/mono/metadata/assembly.h index bdf3d75f62..556981f493 100644 --- a/mono/metadata/assembly.h +++ b/mono/metadata/assembly.h @@ -36,7 +36,7 @@ MONO_API MonoImage* mono_assembly_load_module (MonoAssembly *assembly, uint32 MONO_API void mono_assembly_close (MonoAssembly *assembly); MONO_API void mono_assembly_setrootdir (const char *root_dir); MONO_API MONO_CONST_RETURN char *mono_assembly_getrootdir (void); -MONO_API void mono_assembly_foreach (MonoFunc func, void* user_data); +MONO_API void mono_assembly_foreach (MonoFunc func, void* user_data); MONO_API void mono_assembly_set_main (MonoAssembly *assembly); MONO_API MonoAssembly *mono_assembly_get_main (void); MONO_API MonoImage *mono_assembly_get_image (MonoAssembly *assembly); diff --git a/mono/metadata/attach.c b/mono/metadata/attach.c index 9f6f1e6a83..4372397aa5 100644 --- a/mono/metadata/attach.c +++ b/mono/metadata/attach.c @@ -102,7 +102,7 @@ static gboolean needs_to_start, started; static void transport_connect (void); -static guint32 WINAPI receiver_thread (void *arg); +static gsize WINAPI receiver_thread (void *arg); static void transport_start_receive (void); @@ -475,16 +475,21 @@ transport_send (int fd, guint8 *data, int len) static void transport_start_receive (void) { + MonoThreadParm tp; + transport_connect (); if (!listen_fd) return; - receiver_thread_handle = mono_threads_create_thread (receiver_thread, NULL, 0, 0, NULL); + tp.priority = MONO_THREAD_PRIORITY_NORMAL; + tp.stack_size = 0; + tp.creation_flags = 0; + receiver_thread_handle = mono_threads_create_thread (receiver_thread, NULL, &tp, NULL); g_assert (receiver_thread_handle); } -static guint32 WINAPI +static gsize WINAPI receiver_thread (void *arg) { MonoError error; diff --git a/mono/metadata/boehm-gc.c b/mono/metadata/boehm-gc.c index 71f8fa92ca..d2465ce650 100644 --- a/mono/metadata/boehm-gc.c +++ b/mono/metadata/boehm-gc.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -96,6 +97,9 @@ mono_gc_warning (char *msg, GC_word arg) mono_trace (G_LOG_LEVEL_WARNING, MONO_TRACE_GC, msg, (unsigned long)arg); } +static void on_gc_notification (GC_EventType event); +static void on_gc_heap_resize (size_t new_size); + void mono_gc_base_init (void) { @@ -108,6 +112,10 @@ mono_gc_base_init (void) mono_counters_init (); +#ifndef HOST_WIN32 + mono_w32handle_init (); +#endif + /* * Handle the case when we are called from a thread different from the main thread, * confusing libgc. @@ -243,7 +251,8 @@ mono_gc_base_init (void) mono_thread_info_attach (&dummy); - mono_gc_enable_events (); + GC_set_on_collection_event (on_gc_notification); + GC_on_heap_resize = on_gc_heap_resize; MONO_GC_REGISTER_ROOT_FIXED (gc_handles [HANDLE_NORMAL].entries, MONO_ROOT_SOURCE_GC_HANDLE, "gc handles table"); MONO_GC_REGISTER_ROOT_FIXED (gc_handles [HANDLE_PINNED].entries, MONO_ROOT_SOURCE_GC_HANDLE, "gc handles table"); @@ -388,6 +397,9 @@ boehm_thread_register (MonoThreadInfo* info, void *baseptr) res = GC_register_my_thread (&sb); if (res == GC_UNIMPLEMENTED) return NULL; /* Cannot happen with GC v7+. */ + + info->handle_stack = mono_handle_stack_alloc (); + return info; } @@ -505,21 +517,6 @@ on_gc_heap_resize (size_t new_size) mono_profiler_gc_heap_resize (new_size); } -void -mono_gc_enable_events (void) -{ - GC_set_on_collection_event (on_gc_notification); - GC_on_heap_resize = on_gc_heap_resize; -} - -static gboolean alloc_events = FALSE; - -void -mono_gc_enable_alloc_events (void) -{ - alloc_events = TRUE; -} - int mono_gc_register_root (char *start, size_t size, void *descr, MonoGCRootSource source, const char *msg) { @@ -661,7 +658,7 @@ mono_gc_alloc_obj (MonoVTable *vtable, size_t size) obj->vtable = vtable; } - if (G_UNLIKELY (alloc_events)) + if (G_UNLIKELY (mono_profiler_events & MONO_PROFILE_ALLOCATIONS)) mono_profiler_allocation (obj); return obj; @@ -695,7 +692,7 @@ mono_gc_alloc_vector (MonoVTable *vtable, size_t size, uintptr_t max_length) obj->max_length = max_length; - if (G_UNLIKELY (alloc_events)) + if (G_UNLIKELY (mono_profiler_events & MONO_PROFILE_ALLOCATIONS)) mono_profiler_allocation (&obj->obj); return obj; @@ -732,7 +729,7 @@ mono_gc_alloc_array (MonoVTable *vtable, size_t size, uintptr_t max_length, uint if (bounds_size) obj->bounds = (MonoArrayBounds *) ((char *) obj + size - bounds_size); - if (G_UNLIKELY (alloc_events)) + if (G_UNLIKELY (mono_profiler_events & MONO_PROFILE_ALLOCATIONS)) mono_profiler_allocation (&obj->obj); return obj; @@ -750,7 +747,7 @@ mono_gc_alloc_string (MonoVTable *vtable, size_t size, gint32 len) obj->length = len; obj->chars [len] = 0; - if (G_UNLIKELY (alloc_events)) + if (G_UNLIKELY (mono_profiler_events & MONO_PROFILE_ALLOCATIONS)) mono_profiler_allocation (&obj->object); return obj; @@ -1924,5 +1921,9 @@ mono_gchandle_free_domain (MonoDomain *domain) } } - +#else + #ifdef _MSC_VER + // Quiet Visual Studio linker warning, LNK4221, in cases when this source file intentional ends up empty. + void __mono_win32_boehm_gc_quiet_lnk4221(void) {} + #endif #endif /* no Boehm GC */ diff --git a/mono/metadata/class-internals.h b/mono/metadata/class-internals.h index b8f4aca8f8..de54bd07a4 100644 --- a/mono/metadata/class-internals.h +++ b/mono/metadata/class-internals.h @@ -529,8 +529,9 @@ struct _MonoMethodInflated { struct _MonoGenericClass { MonoClass *container_class; /* the generic type definition */ MonoGenericContext context; /* a context that contains the type instantiation doesn't contain any method instantiation */ /* FIXME: Only the class_inst member of "context" is ever used, so this field could be replaced with just a monogenericinst */ - guint is_dynamic : 1; /* We're a MonoDynamicGenericClass */ + guint is_dynamic : 1; /* Contains dynamic types */ guint is_tb_open : 1; /* This is the fully open instantiation for a type_builder. Quite ugly, but it's temporary.*/ + guint need_sync : 1; /* Only if dynamic. Need to be synchronized with its container class after its finished. */ MonoClass *cached_class; /* if present, the MonoClass corresponding to the instantiation. */ /* @@ -541,21 +542,6 @@ struct _MonoGenericClass { MonoImageSet *owner; }; -/* - * This is used when instantiating a generic type definition which is - * a TypeBuilder. - */ -struct _MonoDynamicGenericClass { - MonoGenericClass generic_class; - int count_fields; - MonoClassField *fields; - guint initialized; - /* The non-inflated types of the fields */ - MonoType **field_generic_types; - /* The managed objects representing the fields */ - MonoObject **field_objects; -}; - /* * A type parameter. */ @@ -573,6 +559,7 @@ struct _MonoGenericParam { }; /* Additional details about a MonoGenericParam */ +/* Keep in sync with managed Mono.RuntimeStructs.GenericParamInfo */ typedef struct { MonoClass *pklass; /* The corresponding `MonoClass'. */ const char *name; @@ -1402,7 +1389,7 @@ void mono_unload_interface_id (MonoClass *klass); GPtrArray* -mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex); +mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoError *error); char* mono_class_full_name (MonoClass *klass); @@ -1443,6 +1430,9 @@ mono_class_load_from_name (MonoImage *image, const char* name_space, const char MonoClass* mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name); +void +mono_error_set_for_class_failure (MonoError *orerror, MonoClass *klass); + static inline guint8 mono_class_get_failure (MonoClass *klass) { diff --git a/mono/metadata/class.c.REMOVED.git-id b/mono/metadata/class.c.REMOVED.git-id index aeea9c5019..59c8d39be7 100644 --- a/mono/metadata/class.c.REMOVED.git-id +++ b/mono/metadata/class.c.REMOVED.git-id @@ -1 +1 @@ -17da478b5e9c1f089d76de0bc275da6ab5e21077 \ No newline at end of file +f1718591e4aa1f373e41b0fa4038d606cc9f72ba \ No newline at end of file diff --git a/mono/metadata/cominterop.c.REMOVED.git-id b/mono/metadata/cominterop.c.REMOVED.git-id index c77e9ada8f..ad33f793b3 100644 --- a/mono/metadata/cominterop.c.REMOVED.git-id +++ b/mono/metadata/cominterop.c.REMOVED.git-id @@ -1 +1 @@ -889c19ece4f786221a020fc365cebe41983b7734 \ No newline at end of file +bedd740079bfdc160e07c76ae65b67134f7af777 \ No newline at end of file diff --git a/mono/metadata/coree.c b/mono/metadata/coree.c index 326251cc14..4436229376 100644 --- a/mono/metadata/coree.c +++ b/mono/metadata/coree.c @@ -23,6 +23,7 @@ #include "domain-internals.h" #include "appdomain.h" #include "object.h" +#include "object-internals.h" #include "loader.h" #include "threads.h" #include "environment.h" @@ -197,7 +198,8 @@ __int32 STDMETHODCALLTYPE _CorExeMain(void) argv [i] = g_utf16_to_utf8 (argvw [i], -1, NULL, NULL, NULL); LocalFree (argvw); - mono_runtime_run_main (method, argc, argv, NULL); + mono_runtime_run_main_checked (method, argc, argv, &error); + mono_error_raise_exception (&error); /* OK, triggers unhandled exn handler */ mono_thread_manage (); mono_runtime_quit (); diff --git a/mono/metadata/custom-attrs-internals.h b/mono/metadata/custom-attrs-internals.h new file mode 100644 index 0000000000..76bd1c21d8 --- /dev/null +++ b/mono/metadata/custom-attrs-internals.h @@ -0,0 +1,15 @@ +#ifndef __MONO_METADATA_CUSTOM_ATTRS_INTERNALS_H__ +#define __MONO_METADATA_CUSTOM_ATTRS_INTERNALS_H__ + +#include +#include + +MonoCustomAttrInfo* +mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs); + +typedef gboolean (*MonoAssemblyMetadataCustomAttrIterFunc) (MonoImage *image, guint32 typeref_scope_token, const gchar* nspace, const gchar* name, guint32 method_token, gpointer user_data); + +void +mono_assembly_metadata_foreach_custom_attr (MonoAssembly *assembly, MonoAssemblyMetadataCustomAttrIterFunc func, gpointer user_data); + +#endif /* __MONO_METADATA_REFLECTION_CUSTOM_ATTRS_INTERNALS_H__ */ diff --git a/mono/metadata/custom-attrs.c b/mono/metadata/custom-attrs.c new file mode 100644 index 0000000000..1b0c152eb3 --- /dev/null +++ b/mono/metadata/custom-attrs.c @@ -0,0 +1,1899 @@ +/* + * custom-attrs.c: Custom attributes. + * + * Author: + * Paolo Molaro (lupus@ximian.com) + * + * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com) + * Copyright 2004-2009 Novell, Inc (http://www.novell.com) + * Copyright 2011 Rodrigo Kumpera + * Copyright 2016 Microsoft + * + * Licensed under the MIT license. See LICENSE file in the project root for full license information. + */ +#include +#include "mono/metadata/assembly.h" +#include "mono/metadata/gc-internals.h" +#include "mono/metadata/mono-endian.h" +#include "mono/metadata/object-internals.h" +#include "mono/metadata/reflection-cache.h" +#include "mono/metadata/custom-attrs-internals.h" +#include "mono/metadata/sre-internals.h" +#include "mono/metadata/reflection-internals.h" +#include "mono/metadata/tabledefs.h" +#include "mono/metadata/tokentype.h" +#include "mono/metadata/verify-internals.h" +#include "mono/utils/checked-build.h" + + +#define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a)) +#define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a)) + +#if SIZEOF_VOID_P == 4 +#define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b) +#else +#define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b) +#endif + +#define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b)) +#define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b)) + +static gboolean type_is_reference (MonoType *type); + +static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_typed_argument, System.Reflection, CustomAttributeTypedArgument); +static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_named_argument, System.Reflection, CustomAttributeNamedArgument); + +/* + * LOCKING: Acquires the loader lock. + */ +static MonoCustomAttrInfo* +lookup_custom_attr (MonoImage *image, gpointer member) +{ + MONO_REQ_GC_NEUTRAL_MODE; + + MonoCustomAttrInfo* res; + + res = (MonoCustomAttrInfo *)mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR); + + if (!res) + return NULL; + + res = (MonoCustomAttrInfo *)g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs); + res->cached = 0; + return res; +} + +static gboolean +custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr) +{ + MONO_REQ_GC_UNSAFE_MODE; + + /* FIXME: Need to do more checks */ + if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) { + int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK; + + if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)) + return FALSE; + } + + return TRUE; +} + +static gboolean +type_is_reference (MonoType *type) +{ + switch (type->type) { + case MONO_TYPE_BOOLEAN: + case MONO_TYPE_CHAR: + case MONO_TYPE_U: + case MONO_TYPE_I: + case MONO_TYPE_U1: + case MONO_TYPE_I1: + case MONO_TYPE_U2: + case MONO_TYPE_I2: + case MONO_TYPE_U4: + case MONO_TYPE_I4: + case MONO_TYPE_U8: + case MONO_TYPE_I8: + case MONO_TYPE_R8: + case MONO_TYPE_R4: + case MONO_TYPE_VALUETYPE: + return FALSE; + default: + return TRUE; + } +} + +static void +free_param_data (MonoMethodSignature *sig, void **params) { + int i; + for (i = 0; i < sig->param_count; ++i) { + if (!type_is_reference (sig->params [i])) + g_free (params [i]); + } +} + +/* + * Find the field index in the metadata FieldDef table. + */ +static guint32 +find_field_index (MonoClass *klass, MonoClassField *field) { + int i; + + for (i = 0; i < klass->field.count; ++i) { + if (field == &klass->fields [i]) + return klass->field.first + 1 + i; + } + return 0; +} + +/* + * Find the property index in the metadata Property table. + */ +static guint32 +find_property_index (MonoClass *klass, MonoProperty *property) { + int i; + + for (i = 0; i < klass->ext->property.count; ++i) { + if (property == &klass->ext->properties [i]) + return klass->ext->property.first + 1 + i; + } + return 0; +} + +/* + * Find the event index in the metadata Event table. + */ +static guint32 +find_event_index (MonoClass *klass, MonoEvent *event) { + int i; + + for (i = 0; i < klass->ext->event.count; ++i) { + if (event == &klass->ext->events [i]) + return klass->ext->event.first + 1 + i; + } + return 0; +} + +/* + * Load the type with name @n on behalf of image @image. On failure sets @error and returns NULL. + * The @is_enum flag only affects the error message that's displayed on failure. + */ +static MonoType* +cattr_type_from_name (char *n, MonoImage *image, gboolean is_enum, MonoError *error) +{ + MonoError inner_error; + MonoType *t = mono_reflection_type_from_name_checked (n, image, &inner_error); + if (!t) { + mono_error_set_type_load_name (error, g_strdup(n), NULL, + "Could not load %s %s while decoding custom attribute: %s", + is_enum ? "enum type": "type", + n, + mono_error_get_message (&inner_error)); + mono_error_cleanup (&inner_error); + return NULL; + } + return t; +} + +static MonoClass* +load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error) +{ + char *n; + MonoType *t; + int slen = mono_metadata_decode_value (p, &p); + + mono_error_init (error); + + n = (char *)g_memdup (p, slen + 1); + n [slen] = 0; + t = cattr_type_from_name (n, image, TRUE, error); + g_free (n); + return_val_if_nok (error, NULL); + p += slen; + *end = p; + return mono_class_from_mono_type (t); +} + +static void* +load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error) +{ + int slen, type = t->type; + MonoClass *tklass = t->data.klass; + + mono_error_init (error); + +handle_enum: + switch (type) { + case MONO_TYPE_U1: + case MONO_TYPE_I1: + case MONO_TYPE_BOOLEAN: { + MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean)); + *bval = *p; + *end = p + 1; + return bval; + } + case MONO_TYPE_CHAR: + case MONO_TYPE_U2: + case MONO_TYPE_I2: { + guint16 *val = (guint16 *)g_malloc (sizeof (guint16)); + *val = read16 (p); + *end = p + 2; + return val; + } +#if SIZEOF_VOID_P == 4 + case MONO_TYPE_U: + case MONO_TYPE_I: +#endif + case MONO_TYPE_R4: + case MONO_TYPE_U4: + case MONO_TYPE_I4: { + guint32 *val = (guint32 *)g_malloc (sizeof (guint32)); + *val = read32 (p); + *end = p + 4; + return val; + } +#if SIZEOF_VOID_P == 8 + case MONO_TYPE_U: /* error out instead? this should probably not happen */ + case MONO_TYPE_I: +#endif + case MONO_TYPE_U8: + case MONO_TYPE_I8: { + guint64 *val = (guint64 *)g_malloc (sizeof (guint64)); + *val = read64 (p); + *end = p + 8; + return val; + } + case MONO_TYPE_R8: { + double *val = (double *)g_malloc (sizeof (double)); + readr8 (p, val); + *end = p + 8; + return val; + } + case MONO_TYPE_VALUETYPE: + if (t->data.klass->enumtype) { + type = mono_class_enum_basetype (t->data.klass)->type; + goto handle_enum; + } else { + MonoClass *k = t->data.klass; + + if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){ + guint64 *val = (guint64 *)g_malloc (sizeof (guint64)); + *val = read64 (p); + *end = p + 8; + return val; + } + } + g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name); + break; + + case MONO_TYPE_STRING: + if (*p == (char)0xFF) { + *end = p + 1; + return NULL; + } + slen = mono_metadata_decode_value (p, &p); + *end = p + slen; + return mono_string_new_len_checked (mono_domain_get (), p, slen, error); + case MONO_TYPE_CLASS: { + MonoReflectionType *rt; + char *n; + MonoType *t; + if (*p == (char)0xFF) { + *end = p + 1; + return NULL; + } +handle_type: + slen = mono_metadata_decode_value (p, &p); + n = (char *)g_memdup (p, slen + 1); + n [slen] = 0; + t = cattr_type_from_name (n, image, FALSE, error); + g_free (n); + return_val_if_nok (error, NULL); + *end = p + slen; + + rt = mono_type_get_object_checked (mono_domain_get (), t, error); + if (!mono_error_ok (error)) + return NULL; + + return rt; + } + case MONO_TYPE_OBJECT: { + char subt = *p++; + MonoObject *obj; + MonoClass *subc = NULL; + void *val; + + if (subt == 0x50) { + goto handle_type; + } else if (subt == 0x0E) { + type = MONO_TYPE_STRING; + goto handle_enum; + } else if (subt == 0x1D) { + MonoType simple_type = {{0}}; + int etype = *p; + p ++; + + type = MONO_TYPE_SZARRAY; + if (etype == 0x50) { + tklass = mono_defaults.systemtype_class; + } else if (etype == 0x55) { + tklass = load_cattr_enum_type (image, p, &p, error); + if (!mono_error_ok (error)) + return NULL; + } else { + if (etype == 0x51) + /* See Partition II, Appendix B3 */ + etype = MONO_TYPE_OBJECT; + simple_type.type = (MonoTypeEnum)etype; + tklass = mono_class_from_mono_type (&simple_type); + } + goto handle_enum; + } else if (subt == 0x55) { + char *n; + MonoType *t; + slen = mono_metadata_decode_value (p, &p); + n = (char *)g_memdup (p, slen + 1); + n [slen] = 0; + t = cattr_type_from_name (n, image, FALSE, error); + g_free (n); + return_val_if_nok (error, NULL); + p += slen; + subc = mono_class_from_mono_type (t); + } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) { + MonoType simple_type = {{0}}; + simple_type.type = (MonoTypeEnum)subt; + subc = mono_class_from_mono_type (&simple_type); + } else { + g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt); + } + val = load_cattr_value (image, &subc->byval_arg, p, end, error); + obj = NULL; + if (mono_error_ok (error)) { + obj = mono_object_new_checked (mono_domain_get (), subc, error); + g_assert (!subc->has_references); + if (mono_error_ok (error)) + mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL)); + } + + g_free (val); + return obj; + } + case MONO_TYPE_SZARRAY: { + MonoArray *arr; + guint32 i, alen, basetype; + alen = read32 (p); + p += 4; + if (alen == 0xffffffff) { + *end = p; + return NULL; + } + arr = mono_array_new_checked (mono_domain_get(), tklass, alen, error); + return_val_if_nok (error, NULL); + basetype = tklass->byval_arg.type; + if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype) + basetype = mono_class_enum_basetype (tklass)->type; + switch (basetype) + { + case MONO_TYPE_U1: + case MONO_TYPE_I1: + case MONO_TYPE_BOOLEAN: + for (i = 0; i < alen; i++) { + MonoBoolean val = *p++; + mono_array_set (arr, MonoBoolean, i, val); + } + break; + case MONO_TYPE_CHAR: + case MONO_TYPE_U2: + case MONO_TYPE_I2: + for (i = 0; i < alen; i++) { + guint16 val = read16 (p); + mono_array_set (arr, guint16, i, val); + p += 2; + } + break; + case MONO_TYPE_R4: + case MONO_TYPE_U4: + case MONO_TYPE_I4: + for (i = 0; i < alen; i++) { + guint32 val = read32 (p); + mono_array_set (arr, guint32, i, val); + p += 4; + } + break; + case MONO_TYPE_R8: + for (i = 0; i < alen; i++) { + double val; + readr8 (p, &val); + mono_array_set (arr, double, i, val); + p += 8; + } + break; + case MONO_TYPE_U8: + case MONO_TYPE_I8: + for (i = 0; i < alen; i++) { + guint64 val = read64 (p); + mono_array_set (arr, guint64, i, val); + p += 8; + } + break; + case MONO_TYPE_CLASS: + case MONO_TYPE_OBJECT: + case MONO_TYPE_STRING: + case MONO_TYPE_SZARRAY: + for (i = 0; i < alen; i++) { + MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error); + if (!mono_error_ok (error)) + return NULL; + mono_array_setref (arr, i, item); + } + break; + default: + g_error ("Type 0x%02x not handled in custom attr array decoding", basetype); + } + *end=p; + return arr; + } + default: + g_error ("Type 0x%02x not handled in custom attr value decoding", type); + } + return NULL; +} + +static MonoObject* +load_cattr_value_boxed (MonoDomain *domain, MonoImage *image, MonoType *t, const char* p, const char** end, MonoError *error) +{ + mono_error_init (error); + + gboolean is_ref = type_is_reference (t); + + void *val = load_cattr_value (image, t, p, end, error); + if (!is_ok (error)) { + if (is_ref) + g_free (val); + return NULL; + } + + if (is_ref) + return (MonoObject*)val; + + MonoObject *boxed = mono_value_box_checked (domain, mono_class_from_mono_type (t), val, error); + g_free (val); + return boxed; +} + +static MonoObject* +create_cattr_typed_arg (MonoType *t, MonoObject *val, MonoError *error) +{ + static MonoMethod *ctor; + MonoObject *retval; + void *params [2], *unboxed; + + mono_error_init (error); + + if (!ctor) + ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_typed_argument_class (), ".ctor", 2); + + params [0] = mono_type_get_object_checked (mono_domain_get (), t, error); + return_val_if_nok (error, NULL); + + params [1] = val; + retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_typed_argument_class (), error); + return_val_if_nok (error, NULL); + unboxed = mono_object_unbox (retval); + + mono_runtime_invoke_checked (ctor, unboxed, params, error); + return_val_if_nok (error, NULL); + + return retval; +} + +static MonoObject* +create_cattr_named_arg (void *minfo, MonoObject *typedarg, MonoError *error) +{ + static MonoMethod *ctor; + MonoObject *retval; + void *unboxed, *params [2]; + + mono_error_init (error); + + if (!ctor) + ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_named_argument_class (), ".ctor", 2); + + params [0] = minfo; + params [1] = typedarg; + retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_named_argument_class (), error); + return_val_if_nok (error, NULL); + + unboxed = mono_object_unbox (retval); + + mono_runtime_invoke_checked (ctor, unboxed, params, error); + return_val_if_nok (error, NULL); + + return retval; +} + + +MonoCustomAttrInfo* +mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs) +{ + MONO_REQ_GC_UNSAFE_MODE; + + int i, index, count, not_visible; + MonoCustomAttrInfo *ainfo; + MonoReflectionCustomAttr *cattr; + + if (!cattrs) + return NULL; + /* FIXME: check in assembly the Run flag is set */ + + count = mono_array_length (cattrs); + + /* Skip nonpublic attributes since MS.NET seems to do the same */ + /* FIXME: This needs to be done more globally */ + not_visible = 0; + for (i = 0; i < count; ++i) { + cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i); + if (!custom_attr_visible (image, cattr)) + not_visible ++; + } + + int num_attrs = count - not_visible; + ainfo = (MonoCustomAttrInfo *)mono_image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * num_attrs); + + ainfo->image = image; + ainfo->num_attrs = num_attrs; + ainfo->cached = alloc_img != NULL; + index = 0; + for (i = 0; i < count; ++i) { + cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i); + if (custom_attr_visible (image, cattr)) { + unsigned char *saved = (unsigned char *)mono_image_alloc (image, mono_array_length (cattr->data)); + memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data)); + ainfo->attrs [index].ctor = cattr->ctor->method; + g_assert (cattr->ctor->method); + ainfo->attrs [index].data = saved; + ainfo->attrs [index].data_size = mono_array_length (cattr->data); + index ++; + } + } + g_assert (index == num_attrs && count == num_attrs + not_visible); + + return ainfo; +} + + +static MonoObject* +create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error) +{ + const char *p = (const char*)data; + const char *named; + guint32 i, j, num_named; + MonoObject *attr; + void *params_buf [32]; + void **params = NULL; + MonoMethodSignature *sig; + + mono_error_init (error); + + mono_class_init (method->klass); + + if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) { + mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid."); + return NULL; + } + + if (len == 0) { + attr = mono_object_new_checked (mono_domain_get (), method->klass, error); + if (!mono_error_ok (error)) return NULL; + + mono_runtime_invoke_checked (method, attr, NULL, error); + if (!mono_error_ok (error)) + return NULL; + + return attr; + } + + if (len < 2 || read16 (p) != 0x0001) /* Prolog */ + return NULL; + + /*g_print ("got attr %s\n", method->klass->name);*/ + + sig = mono_method_signature (method); + if (sig->param_count < 32) { + params = params_buf; + memset (params, 0, sizeof (void*) * sig->param_count); + } else { + /* Allocate using GC so it gets GC tracking */ + params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters"); + } + + /* skip prolog */ + p += 2; + for (i = 0; i < mono_method_signature (method)->param_count; ++i) { + params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error); + if (!mono_error_ok (error)) + goto fail; + } + + named = p; + attr = mono_object_new_checked (mono_domain_get (), method->klass, error); + if (!mono_error_ok (error)) goto fail; + + MonoObject *exc = NULL; + mono_runtime_try_invoke (method, attr, params, &exc, error); + if (!mono_error_ok (error)) + goto fail; + if (exc) { + mono_error_set_exception_instance (error, (MonoException*)exc); + goto fail; + } + + num_named = read16 (named); + named += 2; + for (j = 0; j < num_named; j++) { + gint name_len; + char *name, named_type, data_type; + named_type = *named++; + data_type = *named++; /* type of data */ + if (data_type == MONO_TYPE_SZARRAY) + data_type = *named++; + if (data_type == MONO_TYPE_ENUM) { + gint type_len; + char *type_name; + type_len = mono_metadata_decode_blob_size (named, &named); + type_name = (char *)g_malloc (type_len + 1); + memcpy (type_name, named, type_len); + type_name [type_len] = 0; + named += type_len; + /* FIXME: lookup the type and check type consistency */ + g_free (type_name); + } + name_len = mono_metadata_decode_blob_size (named, &named); + name = (char *)g_malloc (name_len + 1); + memcpy (name, named, name_len); + name [name_len] = 0; + named += name_len; + if (named_type == 0x53) { + MonoClassField *field; + void *val; + + /* how this fail is a blackbox */ + field = mono_class_get_field_from_name (mono_object_class (attr), name); + if (!field) { + mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name); + g_free (name); + goto fail; + } + + val = load_cattr_value (image, field->type, named, &named, error); + if (!mono_error_ok (error)) { + g_free (name); + if (!type_is_reference (field->type)) + g_free (val); + goto fail; + } + + mono_field_set_value (attr, field, val); + if (!type_is_reference (field->type)) + g_free (val); + } else if (named_type == 0x54) { + MonoProperty *prop; + void *pparams [1]; + MonoType *prop_type; + + prop = mono_class_get_property_from_name (mono_object_class (attr), name); + + if (!prop) { + mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name); + g_free (name); + goto fail; + } + + if (!prop->set) { + mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name); + g_free (name); + goto fail; + } + + /* can we have more that 1 arg in a custom attr named property? */ + prop_type = prop->get? mono_method_signature (prop->get)->ret : + mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1]; + + pparams [0] = load_cattr_value (image, prop_type, named, &named, error); + if (!mono_error_ok (error)) { + g_free (name); + if (!type_is_reference (prop_type)) + g_free (pparams [0]); + goto fail; + } + + + mono_property_set_value_checked (prop, attr, pparams, error); + if (!type_is_reference (prop_type)) + g_free (pparams [0]); + if (!is_ok (error)) { + g_free (name); + goto fail; + } + } + g_free (name); + } + + free_param_data (method->signature, params); + if (params != params_buf) + mono_gc_free_fixed (params); + + return attr; + +fail: + free_param_data (method->signature, params); + if (params != params_buf) + mono_gc_free_fixed (params); + return NULL; +} + +/* + * mono_reflection_create_custom_attr_data_args: + * + * Create an array of typed and named arguments from the cattr blob given by DATA. + * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments, + * NAMED_ARG_INFO will contain information about the named arguments. + */ +void +mono_reflection_create_custom_attr_data_args (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoArray **typed_args, MonoArray **named_args, CattrNamedArg **named_arg_info, MonoError *error) +{ + MonoArray *typedargs, *namedargs; + MonoClass *attrklass; + MonoDomain *domain; + const char *p = (const char*)data; + const char *named; + guint32 i, j, num_named; + CattrNamedArg *arginfo = NULL; + + *typed_args = NULL; + *named_args = NULL; + *named_arg_info = NULL; + + mono_error_init (error); + + if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) { + mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid."); + return; + } + + mono_class_init (method->klass); + + domain = mono_domain_get (); + + if (len < 2 || read16 (p) != 0x0001) /* Prolog */ + return; + + typedargs = mono_array_new_checked (domain, mono_get_object_class (), mono_method_signature (method)->param_count, error); + return_if_nok (error); + + /* skip prolog */ + p += 2; + for (i = 0; i < mono_method_signature (method)->param_count; ++i) { + MonoObject *obj; + + obj = load_cattr_value_boxed (domain, image, mono_method_signature (method)->params [i], p, &p, error); + return_if_nok (error); + mono_array_setref (typedargs, i, obj); + } + + named = p; + num_named = read16 (named); + namedargs = mono_array_new_checked (domain, mono_get_object_class (), num_named, error); + return_if_nok (error); + named += 2; + attrklass = method->klass; + + arginfo = g_new0 (CattrNamedArg, num_named); + *named_arg_info = arginfo; + + for (j = 0; j < num_named; j++) { + gint name_len; + char *name, named_type, data_type; + named_type = *named++; + data_type = *named++; /* type of data */ + if (data_type == MONO_TYPE_SZARRAY) + data_type = *named++; + if (data_type == MONO_TYPE_ENUM) { + gint type_len; + char *type_name; + type_len = mono_metadata_decode_blob_size (named, &named); + if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len)) + goto fail; + + type_name = (char *)g_malloc (type_len + 1); + memcpy (type_name, named, type_len); + type_name [type_len] = 0; + named += type_len; + /* FIXME: lookup the type and check type consistency */ + g_free (type_name); + } + name_len = mono_metadata_decode_blob_size (named, &named); + if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len)) + goto fail; + name = (char *)g_malloc (name_len + 1); + memcpy (name, named, name_len); + name [name_len] = 0; + named += name_len; + if (named_type == 0x53) { + MonoObject *obj; + MonoClassField *field = mono_class_get_field_from_name (attrklass, name); + + if (!field) { + g_free (name); + goto fail; + } + + arginfo [j].type = field->type; + arginfo [j].field = field; + + obj = load_cattr_value_boxed (domain, image, field->type, named, &named, error); + if (!is_ok (error)) { + g_free (name); + return; + } + mono_array_setref (namedargs, j, obj); + + } else if (named_type == 0x54) { + MonoObject *obj; + MonoType *prop_type; + MonoProperty *prop = mono_class_get_property_from_name (attrklass, name); + + if (!prop || !prop->set) { + g_free (name); + goto fail; + } + + prop_type = prop->get? mono_method_signature (prop->get)->ret : + mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1]; + + arginfo [j].type = prop_type; + arginfo [j].prop = prop; + + obj = load_cattr_value_boxed (domain, image, prop_type, named, &named, error); + if (!is_ok (error)) { + g_free (name); + return; + } + mono_array_setref (namedargs, j, obj); + } + g_free (name); + } + + *typed_args = typedargs; + *named_args = namedargs; + return; +fail: + mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid."); + g_free (arginfo); + *named_arg_info = NULL; +} + +static gboolean +reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args, MonoError *error) +{ + MonoDomain *domain; + MonoArray *typedargs, *namedargs; + MonoImage *image; + MonoMethod *method; + CattrNamedArg *arginfo = NULL; + int i; + + mono_error_init (error); + + *ctor_args = NULL; + *named_args = NULL; + + if (len == 0) + return TRUE; + + image = assembly->assembly->image; + method = ref_method->method; + domain = mono_object_domain (ref_method); + + if (!mono_class_init (method->klass)) { + mono_error_set_for_class_failure (error, method->klass); + goto leave; + } + + mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, error); + if (!is_ok (error)) + goto leave; + + if (!typedargs || !namedargs) + goto leave; + + for (i = 0; i < mono_method_signature (method)->param_count; ++i) { + MonoObject *obj = mono_array_get (typedargs, MonoObject*, i); + MonoObject *typedarg; + + typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj, error); + if (!is_ok (error)) + goto leave; + mono_array_setref (typedargs, i, typedarg); + } + + for (i = 0; i < mono_array_length (namedargs); ++i) { + MonoObject *obj = mono_array_get (namedargs, MonoObject*, i); + MonoObject *typedarg, *namedarg, *minfo; + + if (arginfo [i].prop) { + minfo = (MonoObject*)mono_property_get_object_checked (domain, NULL, arginfo [i].prop, error); + if (!minfo) + goto leave; + } else { + minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, error); + if (!is_ok (error)) + goto leave; + } + + typedarg = create_cattr_typed_arg (arginfo [i].type, obj, error); + if (!is_ok (error)) + goto leave; + namedarg = create_cattr_named_arg (minfo, typedarg, error); + if (!is_ok (error)) + goto leave; + + mono_array_setref (namedargs, i, namedarg); + } + + *ctor_args = typedargs; + *named_args = namedargs; + +leave: + g_free (arginfo); + return mono_error_ok (error); +} + +void +ves_icall_System_Reflection_CustomAttributeData_ResolveArgumentsInternal (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args) +{ + MonoError error; + (void) reflection_resolve_custom_attribute_data (ref_method, assembly, data, len, ctor_args, named_args, &error); + mono_error_set_pending_exception (&error); +} + +static MonoObject* +create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr, MonoError *error) +{ + static MonoMethod *ctor; + + MonoDomain *domain; + MonoObject *attr; + void *params [4]; + + mono_error_init (error); + + g_assert (image->assembly); + + if (!ctor) + ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4); + + domain = mono_domain_get (); + attr = mono_object_new_checked (domain, mono_defaults.customattribute_data_class, error); + return_val_if_nok (error, NULL); + params [0] = mono_method_get_object_checked (domain, cattr->ctor, NULL, error); + return_val_if_nok (error, NULL); + params [1] = mono_assembly_get_object_checked (domain, image->assembly, error); + return_val_if_nok (error, NULL); + params [2] = (gpointer)&cattr->data; + params [3] = &cattr->data_size; + + mono_runtime_invoke_checked (ctor, attr, params, error); + return_val_if_nok (error, NULL); + return attr; +} + +static MonoArray* +mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error) +{ + MonoArray *result; + MonoObject *attr; + int i, n; + + mono_error_init (error); + + for (i = 0; i < cinfo->num_attrs; ++i) { + MonoCustomAttrEntry *centry = &cinfo->attrs[i]; + if (!centry->ctor) { + /* The cattr type is not finished yet */ + /* We should include the type name but cinfo doesn't contain it */ + mono_error_set_type_load_name (error, NULL, NULL, "Custom attribute constructor is null because the custom attribute type is not finished yet."); + return NULL; + } + } + + n = 0; + if (attr_klass) { + for (i = 0; i < cinfo->num_attrs; ++i) { + MonoMethod *ctor = cinfo->attrs[i].ctor; + g_assert (ctor); + if (mono_class_is_assignable_from (attr_klass, ctor->klass)) + n++; + } + } else { + n = cinfo->num_attrs; + } + + result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n, error); + return_val_if_nok (error, NULL); + n = 0; + for (i = 0; i < cinfo->num_attrs; ++i) { + MonoCustomAttrEntry *centry = &cinfo->attrs [i]; + if (!attr_klass || mono_class_is_assignable_from (attr_klass, centry->ctor->klass)) { + attr = create_custom_attr (cinfo->image, centry->ctor, centry->data, centry->data_size, error); + if (!mono_error_ok (error)) + return result; + mono_array_setref (result, n, attr); + n ++; + } + } + return result; +} + +MonoArray* +mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo) +{ + MonoError error; + MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error); + mono_error_assert_ok (&error); /*FIXME proper error handling*/ + + return result; +} + +static MonoArray* +mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo, MonoError *error) +{ + MonoArray *result; + MonoObject *attr; + int i; + + mono_error_init (error); + result = mono_array_new_checked (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs, error); + return_val_if_nok (error, NULL); + for (i = 0; i < cinfo->num_attrs; ++i) { + attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i], error); + return_val_if_nok (error, NULL); + mono_array_setref (result, i, attr); + } + return result; +} + +/** + * mono_custom_attrs_from_index: + * + * Returns: NULL if no attributes are found or if a loading error occurs. + */ +MonoCustomAttrInfo* +mono_custom_attrs_from_index (MonoImage *image, guint32 idx) +{ + MonoError error; + MonoCustomAttrInfo *result = mono_custom_attrs_from_index_checked (image, idx, FALSE, &error); + mono_error_cleanup (&error); + return result; +} +/** + * mono_custom_attrs_from_index_checked: + * + * Returns: NULL if no attributes are found. On error returns NULL and sets @error. + */ +MonoCustomAttrInfo* +mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, gboolean ignore_missing, MonoError *error) +{ + guint32 mtoken, i, len; + guint32 cols [MONO_CUSTOM_ATTR_SIZE]; + MonoTableInfo *ca; + MonoCustomAttrInfo *ainfo; + GList *tmp, *list = NULL; + const char *data; + MonoCustomAttrEntry* attr; + + mono_error_init (error); + + ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE]; + + i = mono_metadata_custom_attrs_from_index (image, idx); + if (!i) + return NULL; + i --; + while (i < ca->rows) { + if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx) + break; + list = g_list_prepend (list, GUINT_TO_POINTER (i)); + ++i; + } + len = g_list_length (list); + if (!len) + return NULL; + ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len); + ainfo->num_attrs = len; + ainfo->image = image; + for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) { + mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE); + mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS; + switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) { + case MONO_CUSTOM_ATTR_TYPE_METHODDEF: + mtoken |= MONO_TOKEN_METHOD_DEF; + break; + case MONO_CUSTOM_ATTR_TYPE_MEMBERREF: + mtoken |= MONO_TOKEN_MEMBER_REF; + break; + default: + g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]); + break; + } + attr = &ainfo->attrs [i - 1]; + attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, error); + if (!attr->ctor) { + g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to: %s", image->name, mtoken, mono_error_get_message (error)); + if (ignore_missing) { + mono_error_cleanup (error); + mono_error_init (error); + } else { + g_list_free (list); + g_free (ainfo); + return NULL; + } + } + + if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) { + /*FIXME raising an exception here doesn't make any sense*/ + g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx); + g_list_free (list); + g_free (ainfo); + return NULL; + } + data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]); + attr->data_size = mono_metadata_decode_value (data, &data); + attr->data = (guchar*)data; + } + g_list_free (list); + + return ainfo; +} + +MonoCustomAttrInfo* +mono_custom_attrs_from_method (MonoMethod *method) +{ + MonoError error; + MonoCustomAttrInfo* result = mono_custom_attrs_from_method_checked (method, &error); + mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */ + return result; +} + +MonoCustomAttrInfo* +mono_custom_attrs_from_method_checked (MonoMethod *method, MonoError *error) +{ + guint32 idx; + + mono_error_init (error); + + /* + * An instantiated method has the same cattrs as the generic method definition. + * + * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders + * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization + */ + if (method->is_inflated) + method = ((MonoMethodInflated *) method)->declaring; + + if (method_is_dynamic (method) || image_is_dynamic (method->klass->image)) + return lookup_custom_attr (method->klass->image, method); + + if (!method->token) + /* Synthetic methods */ + return NULL; + + idx = mono_method_get_index (method); + idx <<= MONO_CUSTOM_ATTR_BITS; + idx |= MONO_CUSTOM_ATTR_METHODDEF; + return mono_custom_attrs_from_index_checked (method->klass->image, idx, FALSE, error); +} + +MonoCustomAttrInfo* +mono_custom_attrs_from_class (MonoClass *klass) +{ + MonoError error; + MonoCustomAttrInfo *result = mono_custom_attrs_from_class_checked (klass, &error); + mono_error_cleanup (&error); + return result; +} + +MonoCustomAttrInfo* +mono_custom_attrs_from_class_checked (MonoClass *klass, MonoError *error) +{ + guint32 idx; + + mono_error_init (error); + + if (klass->generic_class) + klass = klass->generic_class->container_class; + + if (image_is_dynamic (klass->image)) + return lookup_custom_attr (klass->image, klass); + + if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) { + idx = mono_metadata_token_index (klass->sizes.generic_param_token); + idx <<= MONO_CUSTOM_ATTR_BITS; + idx |= MONO_CUSTOM_ATTR_GENERICPAR; + } else { + idx = mono_metadata_token_index (klass->type_token); + idx <<= MONO_CUSTOM_ATTR_BITS; + idx |= MONO_CUSTOM_ATTR_TYPEDEF; + } + return mono_custom_attrs_from_index_checked (klass->image, idx, FALSE, error); +} + +MonoCustomAttrInfo* +mono_custom_attrs_from_assembly (MonoAssembly *assembly) +{ + MonoError error; + MonoCustomAttrInfo *result = mono_custom_attrs_from_assembly_checked (assembly, FALSE, &error); + mono_error_cleanup (&error); + return result; +} + +MonoCustomAttrInfo* +mono_custom_attrs_from_assembly_checked (MonoAssembly *assembly, gboolean ignore_missing, MonoError *error) +{ + guint32 idx; + + mono_error_init (error); + + if (image_is_dynamic (assembly->image)) + return lookup_custom_attr (assembly->image, assembly); + idx = 1; /* there is only one assembly */ + idx <<= MONO_CUSTOM_ATTR_BITS; + idx |= MONO_CUSTOM_ATTR_ASSEMBLY; + return mono_custom_attrs_from_index_checked (assembly->image, idx, ignore_missing, error); +} + +static MonoCustomAttrInfo* +mono_custom_attrs_from_module (MonoImage *image, MonoError *error) +{ + guint32 idx; + + if (image_is_dynamic (image)) + return lookup_custom_attr (image, image); + idx = 1; /* there is only one module */ + idx <<= MONO_CUSTOM_ATTR_BITS; + idx |= MONO_CUSTOM_ATTR_MODULE; + return mono_custom_attrs_from_index_checked (image, idx, FALSE, error); +} + +MonoCustomAttrInfo* +mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property) +{ + MonoError error; + MonoCustomAttrInfo * result = mono_custom_attrs_from_property_checked (klass, property, &error); + mono_error_cleanup (&error); + return result; +} + +MonoCustomAttrInfo* +mono_custom_attrs_from_property_checked (MonoClass *klass, MonoProperty *property, MonoError *error) +{ + guint32 idx; + + if (image_is_dynamic (klass->image)) { + property = mono_metadata_get_corresponding_property_from_generic_type_definition (property); + return lookup_custom_attr (klass->image, property); + } + idx = find_property_index (klass, property); + idx <<= MONO_CUSTOM_ATTR_BITS; + idx |= MONO_CUSTOM_ATTR_PROPERTY; + return mono_custom_attrs_from_index_checked (klass->image, idx, FALSE, error); +} + +MonoCustomAttrInfo* +mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event) +{ + MonoError error; + MonoCustomAttrInfo * result = mono_custom_attrs_from_event_checked (klass, event, &error); + mono_error_cleanup (&error); + return result; +} + +MonoCustomAttrInfo* +mono_custom_attrs_from_event_checked (MonoClass *klass, MonoEvent *event, MonoError *error) +{ + guint32 idx; + + if (image_is_dynamic (klass->image)) { + event = mono_metadata_get_corresponding_event_from_generic_type_definition (event); + return lookup_custom_attr (klass->image, event); + } + idx = find_event_index (klass, event); + idx <<= MONO_CUSTOM_ATTR_BITS; + idx |= MONO_CUSTOM_ATTR_EVENT; + return mono_custom_attrs_from_index_checked (klass->image, idx, FALSE, error); +} + +MonoCustomAttrInfo* +mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field) +{ + MonoError error; + MonoCustomAttrInfo * result = mono_custom_attrs_from_field_checked (klass, field, &error); + mono_error_cleanup (&error); + return result; +} + +MonoCustomAttrInfo* +mono_custom_attrs_from_field_checked (MonoClass *klass, MonoClassField *field, MonoError *error) +{ + guint32 idx; + mono_error_init (error); + + if (image_is_dynamic (klass->image)) { + field = mono_metadata_get_corresponding_field_from_generic_type_definition (field); + return lookup_custom_attr (klass->image, field); + } + idx = find_field_index (klass, field); + idx <<= MONO_CUSTOM_ATTR_BITS; + idx |= MONO_CUSTOM_ATTR_FIELDDEF; + return mono_custom_attrs_from_index_checked (klass->image, idx, FALSE, error); +} + +/** + * mono_custom_attrs_from_param: + * @method: handle to the method that we want to retrieve custom parameter information from + * @param: parameter number, where zero represent the return value, and one is the first parameter in the method + * + * The result must be released with mono_custom_attrs_free(). + * + * Returns: the custom attribute object for the specified parameter, or NULL if there are none. + */ +MonoCustomAttrInfo* +mono_custom_attrs_from_param (MonoMethod *method, guint32 param) +{ + MonoError error; + MonoCustomAttrInfo *result = mono_custom_attrs_from_param_checked (method, param, &error); + mono_error_cleanup (&error); + return result; +} + +/** + * mono_custom_attrs_from_param_checked: + * @method: handle to the method that we want to retrieve custom parameter information from + * @param: parameter number, where zero represent the return value, and one is the first parameter in the method + * @error: set on error + * + * The result must be released with mono_custom_attrs_free(). + * + * Returns: the custom attribute object for the specified parameter, or NULL if there are none. On failure returns NULL and sets @error. + */ +MonoCustomAttrInfo* +mono_custom_attrs_from_param_checked (MonoMethod *method, guint32 param, MonoError *error) +{ + MonoTableInfo *ca; + guint32 i, idx, method_index; + guint32 param_list, param_last, param_pos, found; + MonoImage *image; + MonoReflectionMethodAux *aux; + + mono_error_init (error); + + /* + * An instantiated method has the same cattrs as the generic method definition. + * + * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders + * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization + */ + if (method->is_inflated) + method = ((MonoMethodInflated *) method)->declaring; + + if (image_is_dynamic (method->klass->image)) { + MonoCustomAttrInfo *res, *ainfo; + int size; + + aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method); + if (!aux || !aux->param_cattr) + return NULL; + + /* Need to copy since it will be freed later */ + ainfo = aux->param_cattr [param]; + if (!ainfo) + return NULL; + size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs; + res = (MonoCustomAttrInfo *)g_malloc0 (size); + memcpy (res, ainfo, size); + return res; + } + + image = method->klass->image; + method_index = mono_method_get_index (method); + if (!method_index) + return NULL; + ca = &image->tables [MONO_TABLE_METHOD]; + + param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST); + if (method_index == ca->rows) { + ca = &image->tables [MONO_TABLE_PARAM]; + param_last = ca->rows + 1; + } else { + param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST); + ca = &image->tables [MONO_TABLE_PARAM]; + } + found = FALSE; + for (i = param_list; i < param_last; ++i) { + param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE); + if (param_pos == param) { + found = TRUE; + break; + } + } + if (!found) + return NULL; + idx = i; + idx <<= MONO_CUSTOM_ATTR_BITS; + idx |= MONO_CUSTOM_ATTR_PARAMDEF; + return mono_custom_attrs_from_index_checked (image, idx, FALSE, error); +} + +gboolean +mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass) +{ + int i; + for (i = 0; i < ainfo->num_attrs; ++i) { + MonoCustomAttrEntry *centry = &ainfo->attrs[i]; + if (centry->ctor == NULL) + continue; + MonoClass *klass = centry->ctor->klass; + if (klass == attr_klass || mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass))) + return TRUE; + } + return FALSE; +} + +MonoObject* +mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass) +{ + MonoError error; + MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error); + mono_error_assert_ok (&error); /*FIXME proper error handling*/ + return res; +} + +MonoObject* +mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error) +{ + int i; + MonoCustomAttrEntry *centry = NULL; + + g_assert (attr_klass != NULL); + + mono_error_init (error); + + for (i = 0; i < ainfo->num_attrs; ++i) { + centry = &ainfo->attrs[i]; + if (centry->ctor == NULL) + continue; + MonoClass *klass = centry->ctor->klass; + if (attr_klass == klass || mono_class_is_assignable_from (attr_klass, klass)) + break; + } + if (centry == NULL) + return NULL; + + return create_custom_attr (ainfo->image, centry->ctor, centry->data, centry->data_size, error); +} + +/* + * mono_reflection_get_custom_attrs_info: + * @obj: a reflection object handle + * + * Return the custom attribute info for attributes defined for the + * reflection handle @obj. The objects. + * + * FIXME this function leaks like a sieve for SRE objects. + */ +MonoCustomAttrInfo* +mono_reflection_get_custom_attrs_info (MonoObject *obj) +{ + MonoError error; + MonoCustomAttrInfo *result = mono_reflection_get_custom_attrs_info_checked (obj, &error); + mono_error_assert_ok (&error); + return result; +} + +/** + * mono_reflection_get_custom_attrs_info_checked: + * @obj: a reflection object handle + * @error: set on error + * + * Return the custom attribute info for attributes defined for the + * reflection handle @obj. The objects. + * + * On failure returns NULL and sets @error. + * + * FIXME this function leaks like a sieve for SRE objects. + */ +MonoCustomAttrInfo* +mono_reflection_get_custom_attrs_info_checked (MonoObject *obj, MonoError *error) +{ + MonoClass *klass; + MonoCustomAttrInfo *cinfo = NULL; + + mono_error_init (error); + + klass = obj->vtable->klass; + if (klass == mono_defaults.runtimetype_class) { + MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error); + return_val_if_nok (error, NULL); + klass = mono_class_from_mono_type (type); + /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/ + cinfo = mono_custom_attrs_from_class_checked (klass, error); + return_val_if_nok (error, NULL); + } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) { + MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj; + cinfo = mono_custom_attrs_from_assembly_checked (rassembly->assembly, FALSE, error); + return_val_if_nok (error, NULL); + } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) { + MonoReflectionModule *module = (MonoReflectionModule*)obj; + cinfo = mono_custom_attrs_from_module (module->image, error); + return_val_if_nok (error, NULL); + } else if (strcmp ("MonoProperty", klass->name) == 0) { + MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj; + cinfo = mono_custom_attrs_from_property_checked (rprop->property->parent, rprop->property, error); + return_val_if_nok (error, NULL); + } else if (strcmp ("MonoEvent", klass->name) == 0) { + MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj; + cinfo = mono_custom_attrs_from_event_checked (revent->event->parent, revent->event, error); + return_val_if_nok (error, NULL); + } else if (strcmp ("MonoField", klass->name) == 0) { + MonoReflectionField *rfield = (MonoReflectionField*)obj; + cinfo = mono_custom_attrs_from_field_checked (rfield->field->parent, rfield->field, error); + return_val_if_nok (error, NULL); + } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) { + MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj; + cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error); + return_val_if_nok (error, NULL); + } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) { + MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj; + cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error); + return_val_if_nok (error, NULL); + } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) { + MonoReflectionParameter *param = (MonoReflectionParameter*)obj; + MonoClass *member_class = mono_object_class (param->MemberImpl); + if (mono_class_is_reflection_method_or_constructor (member_class)) { + MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl; + cinfo = mono_custom_attrs_from_param_checked (rmethod->method, param->PositionImpl + 1, error); + return_val_if_nok (error, NULL); + } else if (mono_is_sr_mono_property (member_class)) { + MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl; + MonoMethod *method; + if (!(method = prop->property->get)) + method = prop->property->set; + g_assert (method); + + cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error); + return_val_if_nok (error, NULL); + } +#ifndef DISABLE_REFLECTION_EMIT + else if (mono_is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/ + MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl, error); + return_val_if_nok (error, NULL); + cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error); + return_val_if_nok (error, NULL); + } else if (mono_is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/ + MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl; + MonoMethod *method = NULL; + if (mono_is_sre_ctor_builder (mono_object_class (c->cb))) + method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle; + else if (mono_is_sr_mono_cmethod (mono_object_class (c->cb))) + method = ((MonoReflectionMethod *)c->cb)->method; + else + g_error ("mono_reflection_get_custom_attrs_info:: can't handle a CTBI with base_method of type %s", mono_type_get_full_name (member_class)); + + cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error); + return_val_if_nok (error, NULL); + } +#endif + else { + char *type_name = mono_type_get_full_name (member_class); + mono_error_set_not_supported (error, + "Custom attributes on a ParamInfo with member %s are not supported", + type_name); + g_free (type_name); + return NULL; + } + } else if (strcmp ("AssemblyBuilder", klass->name) == 0) { + MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj; + cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs); + } else if (strcmp ("TypeBuilder", klass->name) == 0) { + MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj; + cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs); + } else if (strcmp ("ModuleBuilder", klass->name) == 0) { + MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj; + cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs); + } else if (strcmp ("ConstructorBuilder", klass->name) == 0) { + MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj; + cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs); + } else if (strcmp ("MethodBuilder", klass->name) == 0) { + MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj; + cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs); + } else if (strcmp ("FieldBuilder", klass->name) == 0) { + MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj; + cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs); + } else if (strcmp ("MonoGenericClass", klass->name) == 0) { + MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj; + cinfo = mono_reflection_get_custom_attrs_info_checked ((MonoObject*)gclass->generic_type, error); + return_val_if_nok (error, NULL); + } else { /* handle other types here... */ + g_error ("get custom attrs not yet supported for %s", klass->name); + } + + return cinfo; +} + +/* + * mono_reflection_get_custom_attrs_by_type: + * @obj: a reflection object handle + * + * Return an array with all the custom attributes defined of the + * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes + * of that type are returned. The objects are fully build. Return NULL if a loading error + * occurs. + */ +MonoArray* +mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error) +{ + MonoArray *result; + MonoCustomAttrInfo *cinfo; + + mono_error_init (error); + + cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error); + return_val_if_nok (error, NULL); + if (cinfo) { + result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error); + if (!cinfo->cached) + mono_custom_attrs_free (cinfo); + if (!result) + return NULL; + } else { + result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0, error); + } + + return result; +} + +/* + * mono_reflection_get_custom_attrs: + * @obj: a reflection object handle + * + * Return an array with all the custom attributes defined of the + * reflection handle @obj. The objects are fully build. Return NULL if a loading error + * occurs. + */ +MonoArray* +mono_reflection_get_custom_attrs (MonoObject *obj) +{ + MonoError error; + + return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error); +} + +/* + * mono_reflection_get_custom_attrs_data: + * @obj: a reflection obj handle + * + * Returns an array of System.Reflection.CustomAttributeData, + * which include information about attributes reflected on + * types loaded using the Reflection Only methods + */ +MonoArray* +mono_reflection_get_custom_attrs_data (MonoObject *obj) +{ + MonoError error; + MonoArray* result; + result = mono_reflection_get_custom_attrs_data_checked (obj, &error); + mono_error_cleanup (&error); + return result; +} + +/* + * mono_reflection_get_custom_attrs_data_checked: + * @obj: a reflection obj handle + * @error: set on error + * + * Returns an array of System.Reflection.CustomAttributeData, + * which include information about attributes reflected on + * types loaded using the Reflection Only methods + */ +MonoArray* +mono_reflection_get_custom_attrs_data_checked (MonoObject *obj, MonoError *error) +{ + MonoArray *result; + MonoCustomAttrInfo *cinfo; + + mono_error_init (error); + + cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error); + return_val_if_nok (error, NULL); + if (cinfo) { + result = mono_custom_attrs_data_construct (cinfo, error); + if (!cinfo->cached) + mono_custom_attrs_free (cinfo); + return_val_if_nok (error, NULL); + } else + result = mono_array_new_checked (mono_domain_get (), mono_defaults.customattribute_data_class, 0, error); + + return result; +} + +static gboolean +custom_attr_class_name_from_methoddef (MonoImage *image, guint32 method_token, const gchar **nspace, const gchar **class_name) +{ + /* mono_get_method_from_token () */ + g_assert (mono_metadata_token_table (method_token) == MONO_TABLE_METHOD); + guint32 type_token = mono_metadata_typedef_from_method (image, method_token); + if (!type_token) { + /* Bad method token (could not find corresponding typedef) */ + return FALSE; + } + type_token |= MONO_TOKEN_TYPE_DEF; + { + /* mono_class_create_from_typedef () */ + MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF]; + guint32 cols [MONO_TYPEDEF_SIZE]; + guint tidx = mono_metadata_token_index (type_token); + + if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) { + /* "Invalid typedef token %x", type_token */ + return FALSE; + } + + mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE); + + if (class_name) + *class_name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]); + if (nspace) + *nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]); + return TRUE; + } +} + + +/** + * custom_attr_class_name_from_method_token: + * @image: The MonoImage + * @method_token: a token for a custom attr constructor in @image + * @assembly_token: out argment set to the assembly ref token of the custom attr + * @nspace: out argument set to namespace (a string in the string heap of @image) of the custom attr + * @class_name: out argument set to the class name of the custom attr. + * + * Given an @image and a @method_token (which is assumed to be a + * constructor), fills in the out arguments with the assembly ref (if + * a methodref) and the namespace and class name of the custom + * attribute. + * + * Returns: TRUE on success, FALSE otherwise. + * + * LOCKING: does not take locks + */ +static gboolean +custom_attr_class_name_from_method_token (MonoImage *image, guint32 method_token, guint32 *assembly_token, const gchar **nspace, const gchar **class_name) +{ + /* This only works with method tokens constructed from a + * custom attr token, which can only be methoddef or + * memberref */ + g_assert (mono_metadata_token_table (method_token) == MONO_TABLE_METHOD + || mono_metadata_token_table (method_token) == MONO_TABLE_MEMBERREF); + + if (mono_metadata_token_table (method_token) == MONO_TABLE_MEMBERREF) { + /* method_from_memberref () */ + guint32 cols[6]; + guint32 nindex, class_index; + + int idx = mono_metadata_token_index (method_token); + + mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], idx-1, cols, 3); + nindex = cols [MONO_MEMBERREF_CLASS] >> MONO_MEMBERREF_PARENT_BITS; + class_index = cols [MONO_MEMBERREF_CLASS] & MONO_MEMBERREF_PARENT_MASK; + if (class_index == MONO_MEMBERREF_PARENT_TYPEREF) { + guint32 type_token = MONO_TOKEN_TYPE_REF | nindex; + /* mono_class_from_typeref_checked () */ + { + guint32 cols [MONO_TYPEREF_SIZE]; + MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF]; + + mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE); + + if (class_name) + *class_name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]); + if (nspace) + *nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]); + if (assembly_token) + *assembly_token = cols [MONO_TYPEREF_SCOPE]; + return TRUE; + } + } else if (class_index == MONO_MEMBERREF_PARENT_METHODDEF) { + guint32 methoddef_token = MONO_TOKEN_METHOD_DEF | nindex; + if (assembly_token) + *assembly_token = 0; + return custom_attr_class_name_from_methoddef (image, methoddef_token, nspace, class_name); + } else { + /* Attributes can't be generic, so it won't be + * a typespec, and they're always + * constructors, so it won't be a moduleref */ + g_assert_not_reached (); + } + } else { + /* must be MONO_TABLE_METHOD */ + if (assembly_token) + *assembly_token = 0; + return custom_attr_class_name_from_methoddef (image, method_token, nspace, class_name); + } +} + +/** + * mono_assembly_metadata_foreach_custom_attr: + * @assembly: the assembly to iterate over + * @func: the function to call for each custom attribute + * @user_data: passed to @func + * + * Calls @func for each custom attribute type on the given assembly until @func returns TRUE. + * Everything is done using low-level metadata APIs, so it is safe to use during assembly loading. + * + */ +void +mono_assembly_metadata_foreach_custom_attr (MonoAssembly *assembly, MonoAssemblyMetadataCustomAttrIterFunc func, gpointer user_data) +{ + MonoImage *image; + guint32 mtoken, i; + guint32 cols [MONO_CUSTOM_ATTR_SIZE]; + MonoTableInfo *ca; + guint32 idx; + + /* + * This might be called during assembly loading, so do everything using the low-level + * metadata APIs. + */ + + image = assembly->image; + g_assert (!image_is_dynamic (image)); + idx = 1; /* there is only one assembly */ + idx <<= MONO_CUSTOM_ATTR_BITS; + idx |= MONO_CUSTOM_ATTR_ASSEMBLY; + + /* Inlined from mono_custom_attrs_from_index_checked () */ + ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE]; + i = mono_metadata_custom_attrs_from_index (image, idx); + if (!i) + return; + i --; + gboolean stop_iterating = FALSE; + while (!stop_iterating && i < ca->rows) { + if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx) + break; + mono_metadata_decode_row (ca, i, cols, MONO_CUSTOM_ATTR_SIZE); + i ++; + mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS; + switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) { + case MONO_CUSTOM_ATTR_TYPE_METHODDEF: + mtoken |= MONO_TOKEN_METHOD_DEF; + break; + case MONO_CUSTOM_ATTR_TYPE_MEMBERREF: + mtoken |= MONO_TOKEN_MEMBER_REF; + break; + default: + g_warning ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]); + continue; + } + + const char *nspace = NULL; + const char *name = NULL; + guint32 assembly_token = 0; + + if (!custom_attr_class_name_from_method_token (image, mtoken, &assembly_token, &nspace, &name)) + continue; + + stop_iterating = func (image, assembly_token, nspace, name, mtoken, user_data); + } +} diff --git a/mono/metadata/debug-helpers.c b/mono/metadata/debug-helpers.c index 9e933a64bb..449895a561 100644 --- a/mono/metadata/debug-helpers.c +++ b/mono/metadata/debug-helpers.c @@ -928,14 +928,18 @@ mono_object_describe (MonoObject *obj) klass = mono_object_class (obj); if (klass == mono_defaults.string_class) { char *utf8 = mono_string_to_utf8_checked ((MonoString*)obj, &error); - mono_error_raise_exception (&error); /* FIXME don't raise here */ - if (strlen (utf8) > 60) { + mono_error_cleanup (&error); /* FIXME don't swallow the error */ + if (utf8 && strlen (utf8) > 60) { utf8 [57] = '.'; utf8 [58] = '.'; utf8 [59] = '.'; utf8 [60] = 0; } - g_print ("String at %p, length: %d, '%s'\n", obj, mono_string_length ((MonoString*) obj), utf8); + if (utf8) { + g_print ("String at %p, length: %d, '%s'\n", obj, mono_string_length ((MonoString*) obj), utf8); + } else { + g_print ("String at %p, length: %d, unable to decode UTF16\n", obj, mono_string_length ((MonoString*) obj)); + } g_free (utf8); } else if (klass->rank) { MonoArray *array = (MonoArray*)obj; diff --git a/mono/metadata/domain-internals.h b/mono/metadata/domain-internals.h index d4d20ab25a..4966badd21 100644 --- a/mono/metadata/domain-internals.h +++ b/mono/metadata/domain-internals.h @@ -325,7 +325,10 @@ struct _MonoDomain { /* hashtables for Reflection handles */ MonoGHashTable *type_hash; MonoGHashTable *refobject_hash; - /* a GC-tracked array to keep references to the static fields of types */ + /* + * A GC-tracked array to keep references to the static fields of types. + * See note [Domain Static Data Array]. + */ gpointer *static_data_array; /* maps class -> type initialization exception object */ MonoGHashTable *type_init_exception_hash; @@ -386,7 +389,7 @@ struct _MonoDomain { /*thread pool jobs, used to coordinate shutdown.*/ volatile int threadpool_jobs; - HANDLE cleanup_semaphore; + gpointer cleanup_semaphore; /* Contains the compiled runtime invoke wrapper used by finalizers */ gpointer finalize_runtime_invoke; @@ -439,8 +442,8 @@ typedef struct { typedef MonoDomain* (*MonoLoadFunc) (const char *filename, const char *runtime_version); -void mono_domain_lock (MonoDomain *domain); -void mono_domain_unlock (MonoDomain *domain); +void mono_domain_lock (MonoDomain *domain) MONO_LLVM_INTERNAL; +void mono_domain_unlock (MonoDomain *domain) MONO_LLVM_INTERNAL; void mono_install_runtime_load (MonoLoadFunc func); @@ -694,4 +697,8 @@ mono_runtime_init_checked (MonoDomain *domain, MonoThreadStartCB start_cb, MonoT void mono_context_init_checked (MonoDomain *domain, MonoError *error); +gboolean +mono_assembly_has_reference_assembly_attribute (MonoAssembly *assembly, MonoError *error); + + #endif /* __MONO_METADATA_DOMAIN_INTERNALS_H__ */ diff --git a/mono/metadata/domain.c b/mono/metadata/domain.c index f18f9b0d0d..315858b14d 100644 --- a/mono/metadata/domain.c +++ b/mono/metadata/domain.c @@ -525,6 +525,7 @@ mono_init_internal (const char *filename, const char *exe_filename, const char * #endif #ifndef HOST_WIN32 + mono_w32handle_init (); wapi_init (); #endif @@ -1166,6 +1167,12 @@ mono_domain_free (MonoDomain *domain, gboolean force) g_slist_free (domain->domain_assemblies); domain->domain_assemblies = NULL; + /* + * Send this after the assemblies have been unloaded and the domain is still in a + * usable state. + */ + mono_profiler_appdomain_event (domain, MONO_PROFILE_END_UNLOAD); + if (free_domain_hook) free_domain_hook (domain); @@ -1479,8 +1486,10 @@ mono_context_get_domain_id (MonoAppContext *context) void mono_domain_add_class_static_data (MonoDomain *domain, MonoClass *klass, gpointer data, guint32 *bitmap) { - /* The first entry in the array is the index of the next free slot - * and the total size of the array + /* Note [Domain Static Data Array]: + * + * Entry 0 in the array is the index of the next free slot. + * Entry 1 is the total size of the array. */ int next; if (domain->static_data_array) { diff --git a/mono/metadata/dynamic-image-internals.h b/mono/metadata/dynamic-image-internals.h new file mode 100644 index 0000000000..e01216867b --- /dev/null +++ b/mono/metadata/dynamic-image-internals.h @@ -0,0 +1,44 @@ +/* + * Copyright 2016 Microsoft + * Licensed under the MIT license. See LICENSE file in the project root for full license information. + */ +#ifndef __MONO_METADATA_DYNAMIC_IMAGE_INTERNALS_H__ +#define __MONO_METADATA_DYNAMIC_IMAGE_INTERNALS_H__ + +#include +#include + +typedef struct { + guint32 import_lookup_table; + guint32 timestamp; + guint32 forwarder; + guint32 name_rva; + guint32 import_address_table_rva; +} MonoIDT; + +typedef struct { + guint32 name_rva; + guint32 flags; +} MonoILT; + + +void +mono_dynamic_images_init (void); + +void +mono_dynamic_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj); + +gboolean +mono_dynamic_image_is_valid_token (MonoDynamicImage *image, guint32 token); + +MonoDynamicImage* +mono_dynamic_image_create (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name); + +guint32 +mono_dynamic_image_add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2); + +void +mono_dynimage_alloc_table (MonoDynamicTable *table, guint nrows); + +#endif /* __MONO_METADATA_DYNAMIC_IMAGE_INTERNALS_H__ */ + diff --git a/mono/metadata/dynamic-image.c b/mono/metadata/dynamic-image.c new file mode 100644 index 0000000000..17f0f8e82f --- /dev/null +++ b/mono/metadata/dynamic-image.c @@ -0,0 +1,562 @@ +/* + * dynamic-image.c: Images created at runtime. + * + * + * Author: + * Paolo Molaro (lupus@ximian.com) + * + * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com) + * Copyright 2004-2009 Novell, Inc (http://www.novell.com) + * Copyright 2011 Rodrigo Kumpera + * Copyright 2016 Microsoft + * + * Licensed under the MIT license. See LICENSE file in the project root for full license information. + */ + +#include +#include +#include "mono/metadata/object.h" +#include "mono/metadata/dynamic-image-internals.h" +#include "mono/metadata/dynamic-stream-internals.h" +#include "mono/metadata/gc-internals.h" +#include "mono/metadata/metadata-internals.h" +#include "mono/metadata/profiler-private.h" +#include "mono/metadata/reflection-internals.h" +#include "mono/metadata/sre-internals.h" +#include "mono/utils/checked-build.h" +#include "mono/utils/mono-error-internals.h" +#include "mono/utils/mono-os-mutex.h" + +const unsigned char table_sizes [MONO_TABLE_NUM] = { + MONO_MODULE_SIZE, + MONO_TYPEREF_SIZE, + MONO_TYPEDEF_SIZE, + 0, + MONO_FIELD_SIZE, + 0, + MONO_METHOD_SIZE, + 0, + MONO_PARAM_SIZE, + MONO_INTERFACEIMPL_SIZE, + MONO_MEMBERREF_SIZE, /* 0x0A */ + MONO_CONSTANT_SIZE, + MONO_CUSTOM_ATTR_SIZE, + MONO_FIELD_MARSHAL_SIZE, + MONO_DECL_SECURITY_SIZE, + MONO_CLASS_LAYOUT_SIZE, + MONO_FIELD_LAYOUT_SIZE, /* 0x10 */ + MONO_STAND_ALONE_SIGNATURE_SIZE, + MONO_EVENT_MAP_SIZE, + 0, + MONO_EVENT_SIZE, + MONO_PROPERTY_MAP_SIZE, + 0, + MONO_PROPERTY_SIZE, + MONO_METHOD_SEMA_SIZE, + MONO_METHODIMPL_SIZE, + MONO_MODULEREF_SIZE, /* 0x1A */ + MONO_TYPESPEC_SIZE, + MONO_IMPLMAP_SIZE, + MONO_FIELD_RVA_SIZE, + 0, + 0, + MONO_ASSEMBLY_SIZE, /* 0x20 */ + MONO_ASSEMBLY_PROCESSOR_SIZE, + MONO_ASSEMBLYOS_SIZE, + MONO_ASSEMBLYREF_SIZE, + MONO_ASSEMBLYREFPROC_SIZE, + MONO_ASSEMBLYREFOS_SIZE, + MONO_FILE_SIZE, + MONO_EXP_TYPE_SIZE, + MONO_MANIFEST_SIZE, + MONO_NESTED_CLASS_SIZE, + + MONO_GENERICPARAM_SIZE, /* 0x2A */ + MONO_METHODSPEC_SIZE, + MONO_GENPARCONSTRAINT_SIZE + +}; + +// The dynamic images list is only needed to support the mempool reference tracking feature in checked-build. +static GPtrArray *dynamic_images; +static mono_mutex_t dynamic_images_mutex; + +static inline void +dynamic_images_lock (void) +{ + mono_os_mutex_lock (&dynamic_images_mutex); +} + +static inline void +dynamic_images_unlock (void) +{ + mono_os_mutex_unlock (&dynamic_images_mutex); +} + +void +mono_dynamic_images_init (void) +{ + mono_os_mutex_init (&dynamic_images_mutex); +} + +#ifndef DISABLE_REFLECTION_EMIT +static void +string_heap_init (MonoDynamicStream *sh) +{ + mono_dynstream_init (sh); +} +#endif + +#ifndef DISABLE_REFLECTION_EMIT +static int +mono_blob_entry_hash (const char* str) +{ + MONO_REQ_GC_NEUTRAL_MODE; + + guint len, h; + const char *end; + len = mono_metadata_decode_blob_size (str, &str); + if (len > 0) { + end = str + len; + h = *str; + for (str += 1; str < end; str++) + h = (h << 5) - h + *str; + return h; + } else { + return 0; + } +} + +static gboolean +mono_blob_entry_equal (const char *str1, const char *str2) { + MONO_REQ_GC_NEUTRAL_MODE; + + int len, len2; + const char *end1; + const char *end2; + len = mono_metadata_decode_blob_size (str1, &end1); + len2 = mono_metadata_decode_blob_size (str2, &end2); + if (len != len2) + return 0; + return memcmp (end1, end2, len) == 0; +} +#endif + + +/** + * mono_find_dynamic_image_owner: + * + * Find the dynamic image, if any, which a given pointer is located in the memory of. + */ +MonoImage * +mono_find_dynamic_image_owner (void *ptr) +{ + MonoImage *owner = NULL; + int i; + + dynamic_images_lock (); + + if (dynamic_images) + { + for (i = 0; !owner && i < dynamic_images->len; ++i) { + MonoImage *image = (MonoImage *)g_ptr_array_index (dynamic_images, i); + if (mono_mempool_contains_addr (image->mempool, ptr)) + owner = image; + } + } + + dynamic_images_unlock (); + + return owner; +} + +static inline void +dynamic_image_lock (MonoDynamicImage *image) +{ + MONO_ENTER_GC_SAFE; + mono_image_lock ((MonoImage*)image); + MONO_EXIT_GC_SAFE; +} + +static inline void +dynamic_image_unlock (MonoDynamicImage *image) +{ + mono_image_unlock ((MonoImage*)image); +} + +void +mono_dynamic_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj) +{ + MONO_REQ_GC_UNSAFE_MODE; + + dynamic_image_lock (assembly); + mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj); + dynamic_image_unlock (assembly); +} + +static MonoObject* +lookup_dyn_token (MonoDynamicImage *assembly, guint32 token) +{ + MONO_REQ_GC_UNSAFE_MODE; + + MonoObject *obj; + + dynamic_image_lock (assembly); + obj = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token)); + dynamic_image_unlock (assembly); + + return obj; +} + +/** + * + * mono_dynamic_image_is_valid_token: + * + * Returns TRUE if token is valid in the given image. + * + */ +gboolean +mono_dynamic_image_is_valid_token (MonoDynamicImage *image, guint32 token) +{ + return lookup_dyn_token (image, token) != NULL; +} + +#ifndef DISABLE_REFLECTION_EMIT + +#endif /* DISABLE_REFLECTION_EMIT */ + +#ifndef DISABLE_REFLECTION_EMIT +/** + * mono_reflection_lookup_dynamic_token: + * + * Finish the Builder object pointed to by TOKEN and return the corresponding + * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by + * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object + * mapping table. + * + * LOCKING: Take the loader lock + */ +gpointer +mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error) +{ + MonoDynamicImage *assembly = (MonoDynamicImage*)image; + MonoObject *obj; + MonoClass *klass; + + mono_error_init (error); + + obj = lookup_dyn_token (assembly, token); + if (!obj) { + if (valid_token) + g_error ("Could not find required dynamic token 0x%08x", token); + else { + mono_error_set_execution_engine (error, "Could not find dynamic token 0x%08x", token); + return NULL; + } + } + + if (!handle_class) + handle_class = &klass; + gpointer result = mono_reflection_resolve_object (image, obj, handle_class, context, error); + return result; +} + +/* + * mono_image_register_token: + * + * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for + * the Module.ResolveXXXToken () methods to work. + */ +void +mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj) +{ + MonoObject *prev; + + dynamic_image_lock (assembly); + prev = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token)); + if (prev) { + /* There could be multiple MethodInfo objects with the same token */ + //g_assert (prev == obj); + } else { + mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj); + } + dynamic_image_unlock (assembly); +} + +#else /* DISABLE_REFLECTION_EMIT */ + +gpointer +mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error) +{ + mono_error_init (error); + return NULL; +} + +void +mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj) +{ +} + +#endif /* DISABLE_REFLECTION_EMIT */ + +#ifndef DISABLE_REFLECTION_EMIT +MonoDynamicImage* +mono_dynamic_image_create (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name) +{ + static const guchar entrycode [16] = {0xff, 0x25, 0}; + MonoDynamicImage *image; + int i; + + const char *version; + + if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1")) + version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */ + else + version = mono_get_runtime_info ()->runtime_version; + +#if HAVE_BOEHM_GC + /* The MonoGHashTable's need GC tracking */ + image = (MonoDynamicImage *)GC_MALLOC (sizeof (MonoDynamicImage)); +#else + image = g_new0 (MonoDynamicImage, 1); +#endif + + mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD); + + /*g_print ("created image %p\n", image);*/ + /* keep in sync with image.c */ + image->image.name = assembly_name; + image->image.assembly_name = image->image.name; /* they may be different */ + image->image.module_name = module_name; + image->image.version = g_strdup (version); + image->image.md_version_major = 1; + image->image.md_version_minor = 1; + image->image.dynamic = TRUE; + + image->image.references = g_new0 (MonoAssembly*, 1); + image->image.references [0] = NULL; + + mono_image_init (&image->image); + + image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module token fixups table"); + image->method_to_table_idx = g_hash_table_new (NULL, NULL); + image->field_to_table_idx = g_hash_table_new (NULL, NULL); + image->method_aux_hash = g_hash_table_new (NULL, NULL); + image->vararg_aux_hash = g_hash_table_new (NULL, NULL); + image->handleref = g_hash_table_new (NULL, NULL); + image->handleref_managed = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module reference-to-token table"); + image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table"); + image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module generic definitions table"); + image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module method specifications table"); + image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal); + image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal); + image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal); + image->gen_params = g_ptr_array_new (); + image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table"); + + /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/ + string_heap_init (&image->sheap); + mono_dynstream_add_data (&image->us, "", 1); + mono_dynamic_image_add_to_blob_cached (image, (char*) "", 1, NULL, 0); + /* import tables... */ + mono_dynstream_add_data (&image->code, (char*)entrycode, sizeof (entrycode)); + image->iat_offset = mono_dynstream_add_zero (&image->code, 8); /* two IAT entries */ + image->idt_offset = mono_dynstream_add_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */ + image->imp_names_offset = mono_dynstream_add_zero (&image->code, 2); /* flags for name entry */ + mono_dynstream_add_data (&image->code, "_CorExeMain", 12); + mono_dynstream_add_data (&image->code, "mscoree.dll", 12); + image->ilt_offset = mono_dynstream_add_zero (&image->code, 8); /* two ILT entries */ + mono_dynstream_data_align (&image->code); + + image->cli_header_offset = mono_dynstream_add_zero (&image->code, sizeof (MonoCLIHeader)); + + for (i=0; i < MONO_TABLE_NUM; ++i) { + image->tables [i].next_idx = 1; + image->tables [i].columns = table_sizes [i]; + } + + image->image.assembly = (MonoAssembly*)assembly; + image->run = assembly->run; + image->save = assembly->save; + image->pe_kind = 0x1; /* ILOnly */ + image->machine = 0x14c; /* I386 */ + + mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK); + + dynamic_images_lock (); + + if (!dynamic_images) + dynamic_images = g_ptr_array_new (); + + g_ptr_array_add (dynamic_images, image); + + dynamic_images_unlock (); + + return image; +} +#else /* DISABLE_REFLECTION_EMIT */ +MonoDynamicImage* +mono_dynamic_image_create (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name) +{ + g_assert_not_reached (); + return NULL; +} +#endif /* DISABLE_REFLECTION_EMIT */ + +guint32 +mono_dynamic_image_add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2) +{ + MONO_REQ_GC_NEUTRAL_MODE; + + guint32 idx; + char *copy; + gpointer oldkey, oldval; + + copy = (char *)g_malloc (s1+s2); + memcpy (copy, b1, s1); + memcpy (copy + s1, b2, s2); + if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) { + g_free (copy); + idx = GPOINTER_TO_UINT (oldval); + } else { + idx = mono_dynstream_add_data (&assembly->blob, b1, s1); + mono_dynstream_add_data (&assembly->blob, b2, s2); + g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx)); + } + return idx; +} + +void +mono_dynimage_alloc_table (MonoDynamicTable *table, guint nrows) +{ + MONO_REQ_GC_NEUTRAL_MODE; + + table->rows = nrows; + g_assert (table->columns); + if (nrows + 1 >= table->alloc_rows) { + while (nrows + 1 >= table->alloc_rows) { + if (table->alloc_rows == 0) + table->alloc_rows = 16; + else + table->alloc_rows *= 2; + } + + table->values = (guint32 *)g_renew (guint32, table->values, (table->alloc_rows) * table->columns); + } +} + + +static void +free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data) +{ + g_free (key); +} + +static void +release_hashtable (MonoGHashTable **hash) +{ + if (*hash) { + mono_g_hash_table_destroy (*hash); + *hash = NULL; + } +} + +void +mono_dynamic_image_release_gc_roots (MonoDynamicImage *image) +{ + release_hashtable (&image->token_fixups); + release_hashtable (&image->handleref_managed); + release_hashtable (&image->tokens); + release_hashtable (&image->remapped_tokens); + release_hashtable (&image->generic_def_objects); + release_hashtable (&image->methodspec); +} + +// Free dynamic image pass one: Free resources but not image itself +void +mono_dynamic_image_free (MonoDynamicImage *image) +{ + MonoDynamicImage *di = image; + GList *list; + int i; + + if (di->methodspec) + mono_g_hash_table_destroy (di->methodspec); + if (di->typespec) + g_hash_table_destroy (di->typespec); + if (di->typeref) + g_hash_table_destroy (di->typeref); + if (di->handleref) + g_hash_table_destroy (di->handleref); + if (di->handleref_managed) + mono_g_hash_table_destroy (di->handleref_managed); + if (di->tokens) + mono_g_hash_table_destroy (di->tokens); + if (di->remapped_tokens) + mono_g_hash_table_destroy (di->remapped_tokens); + if (di->generic_def_objects) + mono_g_hash_table_destroy (di->generic_def_objects); + if (di->blob_cache) { + g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL); + g_hash_table_destroy (di->blob_cache); + } + if (di->standalonesig_cache) + g_hash_table_destroy (di->standalonesig_cache); + for (list = di->array_methods; list; list = list->next) { + ArrayMethod *am = (ArrayMethod *)list->data; + mono_sre_array_method_free (am); + } + g_list_free (di->array_methods); + if (di->gen_params) { + for (i = 0; i < di->gen_params->len; i++) { + GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (di->gen_params, i); + mono_sre_generic_param_table_entry_free (entry); + } + g_ptr_array_free (di->gen_params, TRUE); + } + if (di->token_fixups) + mono_g_hash_table_destroy (di->token_fixups); + if (di->method_to_table_idx) + g_hash_table_destroy (di->method_to_table_idx); + if (di->field_to_table_idx) + g_hash_table_destroy (di->field_to_table_idx); + if (di->method_aux_hash) + g_hash_table_destroy (di->method_aux_hash); + if (di->vararg_aux_hash) + g_hash_table_destroy (di->vararg_aux_hash); + g_free (di->strong_name); + g_free (di->win32_res); + if (di->public_key) + g_free (di->public_key); + + /*g_print ("string heap destroy for image %p\n", di);*/ + mono_dynamic_stream_reset (&di->sheap); + mono_dynamic_stream_reset (&di->code); + mono_dynamic_stream_reset (&di->resources); + mono_dynamic_stream_reset (&di->us); + mono_dynamic_stream_reset (&di->blob); + mono_dynamic_stream_reset (&di->tstream); + mono_dynamic_stream_reset (&di->guid); + for (i = 0; i < MONO_TABLE_NUM; ++i) { + g_free (di->tables [i].values); + } + + dynamic_images_lock (); + + if (dynamic_images) + g_ptr_array_remove (dynamic_images, di); + + dynamic_images_unlock (); +} + +// Free dynamic image pass two: Free image itself (might never get called in some debug modes) +void +mono_dynamic_image_free_image (MonoDynamicImage *image) +{ + /* See create_dynamic_mono_image () */ +#if HAVE_BOEHM_GC + /* Allocated using GC_MALLOC */ +#else + g_free (image); +#endif +} diff --git a/mono/metadata/dynamic-stream-internals.h b/mono/metadata/dynamic-stream-internals.h new file mode 100644 index 0000000000..454f350cf8 --- /dev/null +++ b/mono/metadata/dynamic-stream-internals.h @@ -0,0 +1,30 @@ +/* + * Copyright 2016 Microsoft + * Licensed under the MIT license. See LICENSE file in the project root for full license information. + */ +#ifndef __MONO_METADATA_DYNAMIC_STREAM_INTERNALS_H__ +#define __MONO_METADATA_DYNAMIC_STREAM_INTERNALS_H__ + +#include +#include + +void +mono_dynstream_init (MonoDynamicStream *stream); + +guint32 +mono_dynstream_insert_string (MonoDynamicStream *sh, const char *str); + +guint32 +mono_dynstream_insert_mstring (MonoDynamicStream *sh, MonoString *str, MonoError *error); + +guint32 +mono_dynstream_add_data (MonoDynamicStream *stream, const char *data, guint32 len); + +guint32 +mono_dynstream_add_zero (MonoDynamicStream *stream, guint32 len); + +void +mono_dynstream_data_align (MonoDynamicStream *stream); + +#endif /* __MONO_METADATA_DYNAMIC_STREAM_INTERNALS_H__ */ + diff --git a/mono/metadata/dynamic-stream.c b/mono/metadata/dynamic-stream.c new file mode 100644 index 0000000000..6cf6370e04 --- /dev/null +++ b/mono/metadata/dynamic-stream.c @@ -0,0 +1,131 @@ +/* + * dynamic-stream.c: MonoDynamicStream + * Copyright 2016 Microsoft + * + * Licensed under the MIT license. See LICENSE file in the project root for full license information. + */ + +#include +#include + +#include "mono/metadata/dynamic-stream-internals.h" +#include "mono/metadata/metadata-internals.h" +#include "mono/utils/checked-build.h" +#include "mono/utils/mono-error-internals.h" + +void +mono_dynstream_init (MonoDynamicStream *sh) +{ + MONO_REQ_GC_NEUTRAL_MODE; + + sh->index = 0; + sh->alloc_size = 4096; + sh->data = (char *)g_malloc (4096); + sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + mono_dynstream_insert_string (sh, ""); +} + +static void +make_room_in_stream (MonoDynamicStream *stream, int size) +{ + MONO_REQ_GC_NEUTRAL_MODE; + + if (size <= stream->alloc_size) + return; + + while (stream->alloc_size <= size) { + if (stream->alloc_size < 4096) + stream->alloc_size = 4096; + else + stream->alloc_size *= 2; + } + + stream->data = (char *)g_realloc (stream->data, stream->alloc_size); +} + +guint32 +mono_dynstream_insert_string (MonoDynamicStream *sh, const char *str) +{ + MONO_REQ_GC_NEUTRAL_MODE; + + guint32 idx; + guint32 len; + gpointer oldkey, oldval; + + if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval)) + return GPOINTER_TO_UINT (oldval); + + len = strlen (str) + 1; + idx = sh->index; + + make_room_in_stream (sh, idx + len); + + /* + * We strdup the string even if we already copy them in sh->data + * so that the string pointers in the hash remain valid even if + * we need to realloc sh->data. We may want to avoid that later. + */ + g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx)); + memcpy (sh->data + idx, str, len); + sh->index += len; + return idx; +} + +guint32 +mono_dynstream_insert_mstring (MonoDynamicStream *sh, MonoString *str, MonoError *error) +{ + MONO_REQ_GC_UNSAFE_MODE; + + mono_error_init (error); + char *name = mono_string_to_utf8_checked (str, error); + return_val_if_nok (error, -1); + guint32 idx; + idx = mono_dynstream_insert_string (sh, name); + g_free (name); + return idx; +} + +guint32 +mono_dynstream_add_data (MonoDynamicStream *stream, const char *data, guint32 len) +{ + MONO_REQ_GC_NEUTRAL_MODE; + + guint32 idx; + + make_room_in_stream (stream, stream->index + len); + memcpy (stream->data + stream->index, data, len); + idx = stream->index; + stream->index += len; + /* + * align index? Not without adding an additional param that controls it since + * we may store a blob value in pieces. + */ + return idx; +} + +guint32 +mono_dynstream_add_zero (MonoDynamicStream *stream, guint32 len) +{ + MONO_REQ_GC_NEUTRAL_MODE; + + guint32 idx; + + make_room_in_stream (stream, stream->index + len); + memset (stream->data + stream->index, 0, len); + idx = stream->index; + stream->index += len; + return idx; +} + +void +mono_dynstream_data_align (MonoDynamicStream *stream) +{ + MONO_REQ_GC_NEUTRAL_MODE; + + guint32 count = stream->index % 4; + + /* we assume the stream data will be aligned */ + if (count) + mono_dynstream_add_zero (stream, 4 - count); +} + diff --git a/mono/metadata/exception-internals.h b/mono/metadata/exception-internals.h index 60c2ae0bd1..4a9ad50579 100644 --- a/mono/metadata/exception-internals.h +++ b/mono/metadata/exception-internals.h @@ -15,4 +15,14 @@ mono_get_exception_reflection_type_load_checked (MonoArray *types, MonoArray *ex MonoException * mono_get_exception_runtime_wrapped_checked (MonoObject *wrapped_exception, MonoError *error); -#endif \ No newline at end of file +MonoException * +mono_exception_from_name_two_strings_checked (MonoImage *image, const char *name_space, + const char *name, MonoString *a1, MonoString *a2, + MonoError *error); + +MonoException * +mono_exception_from_token_two_strings_checked (MonoImage *image, uint32_t token, + MonoString *a1, MonoString *a2, + MonoError *error); + +#endif diff --git a/mono/metadata/exception.c b/mono/metadata/exception.c index e2e162f702..b4be09844a 100644 --- a/mono/metadata/exception.c +++ b/mono/metadata/exception.c @@ -13,6 +13,8 @@ */ #include +#include +#include #include #include @@ -21,12 +23,16 @@ #include #include #include +#include #include #ifdef HAVE_EXECINFO_H #include #endif +static MonoUnhandledExceptionFunc unhandled_exception_hook = NULL; +static gpointer unhandled_exception_hook_data = NULL; + /** * mono_exception_from_name: * @image: the Mono image where to look for the class @@ -173,15 +179,39 @@ mono_exception_from_name_two_strings (MonoImage *image, const char *name_space, const char *name, MonoString *a1, MonoString *a2) { MonoError error; - MonoClass *klass; MonoException *ret; + ret = mono_exception_from_name_two_strings_checked (image, name_space, name, a1, a2, &error); + mono_error_cleanup (&error); + return ret; +} + +/** + * mono_exception_from_name_two_strings_checked: + * @image: the Mono image where to look for the class + * @name_space: the namespace for the class + * @name: class name + * @a1: first string argument to pass + * @a2: second string argument to pass + * @error: set on error + * + * Creates an exception from a constructor that takes two string + * arguments. + * + * Returns: the initialized exception instance. On failure returns + * NULL and sets @error. + */ +MonoException * +mono_exception_from_name_two_strings_checked (MonoImage *image, const char *name_space, + const char *name, MonoString *a1, MonoString *a2, + MonoError *error) +{ + MonoClass *klass; + + mono_error_init (error); klass = mono_class_load_from_name (image, name_space, name); - ret = create_exception_two_strings (klass, a1, a2, &error); - mono_error_raise_exception (&error); /* FIXME don't raise here */ - - return ret; + return create_exception_two_strings (klass, a1, a2, error); } /** @@ -220,18 +250,33 @@ mono_exception_from_token_two_strings (MonoImage *image, guint32 token, MonoString *a1, MonoString *a2) { MonoError error; - MonoClass *klass; MonoException *ret; - - klass = mono_class_get_checked (image, token, &error); - mono_error_assert_ok (&error); /* FIXME handle the error. */ - - ret = create_exception_two_strings (klass, a1, a2, &error); - mono_error_raise_exception (&error); /* FIXME don't raise here */ - + ret = mono_exception_from_token_two_strings_checked (image, token, a1, a2, &error); + mono_error_cleanup (&error); return ret; } +/** + * mono_exception_from_token_two_strings_checked: + * + * Same as mono_exception_from_name_two_strings, but lookup the exception class using + * IMAGE and TOKEN. + */ +MonoException * +mono_exception_from_token_two_strings_checked (MonoImage *image, guint32 token, + MonoString *a1, MonoString *a2, + MonoError *error) +{ + MonoClass *klass; + + mono_error_init (error); + + klass = mono_class_get_checked (image, token, error); + mono_error_assert_ok (error); /* FIXME handle the error. */ + + return create_exception_two_strings (klass, a1, a2, error); +} + /** * mono_get_exception_divide_by_zero: * @@ -400,8 +445,11 @@ mono_get_exception_type_load (MonoString *class_name, char *assembly_name) { MonoString *s = assembly_name ? mono_string_new (mono_domain_get (), assembly_name) : mono_string_new (mono_domain_get (), ""); - return mono_exception_from_name_two_strings (mono_get_corlib (), "System", - "TypeLoadException", class_name, s); + MonoError error; + MonoException *ret = mono_exception_from_name_two_strings_checked (mono_get_corlib (), "System", + "TypeLoadException", class_name, s, &error); + mono_error_assert_ok (&error); + return ret; } /** @@ -441,8 +489,11 @@ mono_get_exception_missing_method (const char *class_name, const char *member_na MonoString *s1 = mono_string_new (mono_domain_get (), class_name); MonoString *s2 = mono_string_new (mono_domain_get (), member_name); - return mono_exception_from_name_two_strings (mono_get_corlib (), "System", - "MissingMethodException", s1, s2); + MonoError error; + MonoException *ret = mono_exception_from_name_two_strings_checked (mono_get_corlib (), "System", + "MissingMethodException", s1, s2, &error); + mono_error_assert_ok (&error); + return ret; } /** @@ -458,8 +509,11 @@ mono_get_exception_missing_field (const char *class_name, const char *member_nam MonoString *s1 = mono_string_new (mono_domain_get (), class_name); MonoString *s2 = mono_string_new (mono_domain_get (), member_name); - return mono_exception_from_name_two_strings (mono_get_corlib (), "System", - "MissingFieldException", s1, s2); + MonoError error; + MonoException *ret = mono_exception_from_name_two_strings_checked (mono_get_corlib (), "System", + "MissingFieldException", s1, s2, &error); + mono_error_assert_ok (&error); + return ret; } /** @@ -563,8 +617,11 @@ mono_get_exception_io (const char *msg) MonoException * mono_get_exception_file_not_found (MonoString *fname) { - return mono_exception_from_name_two_strings ( - mono_get_corlib (), "System.IO", "FileNotFoundException", fname, fname); + MonoError error; + MonoException *ret = mono_exception_from_name_two_strings_checked ( + mono_get_corlib (), "System.IO", "FileNotFoundException", fname, fname, &error); + mono_error_assert_ok (&error); + return ret; } /** @@ -579,8 +636,11 @@ mono_get_exception_file_not_found2 (const char *msg, MonoString *fname) { MonoString *s = msg ? mono_string_new (mono_domain_get (), msg) : NULL; - return mono_exception_from_name_two_strings ( - mono_get_corlib (), "System.IO", "FileNotFoundException", s, fname); + MonoError error; + MonoException *ret = mono_exception_from_name_two_strings_checked ( + mono_get_corlib (), "System.IO", "FileNotFoundException", s, fname, &error); + mono_error_assert_ok (&error); + return ret; } /** @@ -699,8 +759,11 @@ mono_get_exception_bad_image_format2 (const char *msg, MonoString *fname) { MonoString *s = msg ? mono_string_new (mono_domain_get (), msg) : NULL; - return mono_exception_from_name_two_strings ( - mono_get_corlib (), "System", "BadImageFormatException", s, fname); + MonoError error; + MonoException *ret = mono_exception_from_name_two_strings_checked ( + mono_get_corlib (), "System", "BadImageFormatException", s, fname, &error); + mono_error_assert_ok (&error); + return ret; } /** @@ -913,8 +976,12 @@ mono_exception_get_native_backtrace (MonoException *exc) domain = mono_domain_get (); len = mono_array_length (arr); text = g_string_new_len (NULL, len * 20); - messages = backtrace_symbols (mono_array_addr (arr, gpointer, 0), len); - + uint32_t gchandle = mono_gchandle_new (&arr->obj, TRUE); /* pinned */ + void* addr = mono_array_addr (arr, gpointer, 0); + MONO_ENTER_GC_SAFE; + messages = backtrace_symbols (addr, len); + MONO_EXIT_GC_SAFE; + mono_gchandle_free (gchandle); for (i = 0; i < len; ++i) { gpointer ip = mono_array_get (arr, gpointer, i); @@ -928,7 +995,7 @@ mono_exception_get_native_backtrace (MonoException *exc) } } - free (messages); + g_free (messages); return g_string_free (text, FALSE); #else return g_strdup (""); @@ -993,3 +1060,50 @@ mono_error_set_pending_exception (MonoError *error) } } +void +mono_install_unhandled_exception_hook (MonoUnhandledExceptionFunc func, gpointer user_data) +{ + unhandled_exception_hook = func; + unhandled_exception_hook_data = user_data; +} + +void +mono_invoke_unhandled_exception_hook (MonoObject *exc) +{ + if (unhandled_exception_hook) { + unhandled_exception_hook (exc, unhandled_exception_hook_data); + } else { + MonoError inner_error; + MonoObject *other = NULL; + MonoString *str = mono_object_try_to_string (exc, &other, &inner_error); + char *msg = NULL; + + if (str && is_ok (&inner_error)) { + msg = mono_string_to_utf8_checked (str, &inner_error); + if (!is_ok (&inner_error)) { + msg = g_strdup_printf ("Nested exception while formatting original exception"); + mono_error_cleanup (&inner_error); + } + } else if (other) { + char *original_backtrace = mono_exception_get_managed_backtrace ((MonoException*)exc); + char *nested_backtrace = mono_exception_get_managed_backtrace ((MonoException*)other); + + msg = g_strdup_printf ("Nested exception detected.\nOriginal Exception: %s\nNested exception:%s\n", + original_backtrace, nested_backtrace); + + g_free (original_backtrace); + g_free (nested_backtrace); + } else { + msg = g_strdup ("Nested exception trying to figure out what went wrong"); + } + mono_runtime_printf_err ("[ERROR] FATAL UNHANDLED EXCEPTION: %s", msg); + g_free (msg); +#if defined(HOST_IOS) + g_assertion_message ("Terminating runtime due to unhandled exception"); +#else + exit (mono_environment_exitcode_get ()); +#endif + } + + g_assert_not_reached (); +} diff --git a/mono/metadata/exception.h b/mono/metadata/exception.h index b9b82dd742..895a67795f 100644 --- a/mono/metadata/exception.h +++ b/mono/metadata/exception.h @@ -1,6 +1,7 @@ #ifndef _MONO_METADATA_EXCEPTION_H_ #define _MONO_METADATA_EXCEPTION_H_ +#include #include #include @@ -14,6 +15,7 @@ mono_exception_from_name (MonoImage *image, MONO_API MonoException * mono_exception_from_token (MonoImage *image, uint32_t token); +MONO_RT_EXTERNAL_ONLY MONO_API MonoException * mono_exception_from_name_two_strings (MonoImage *image, const char *name_space, const char *name, MonoString *a1, MonoString *a2); @@ -22,6 +24,7 @@ MONO_API MonoException * mono_exception_from_name_msg (MonoImage *image, const char *name_space, const char *name, const char *msg); +MONO_RT_EXTERNAL_ONLY MONO_API MonoException * mono_exception_from_token_two_strings (MonoImage *image, uint32_t token, MonoString *a1, MonoString *a2); @@ -145,6 +148,14 @@ MONO_RT_EXTERNAL_ONLY MONO_API MonoException * mono_get_exception_runtime_wrapped (MonoObject *wrapped_exception); +/* Installs a function which is called when the runtime encounters an unhandled exception. + * This hook isn't expected to return. + * If no hook has been installed, the runtime will print a message before aborting. + */ +typedef void (*MonoUnhandledExceptionFunc) (MonoObject *exc, gpointer user_data); +MONO_API void mono_install_unhandled_exception_hook (MonoUnhandledExceptionFunc func, gpointer user_data); +void mono_invoke_unhandled_exception_hook (MonoObject *exc); + MONO_END_DECLS #endif /* _MONO_METADATA_EXCEPTION_H_ */ diff --git a/mono/metadata/file-io.c b/mono/metadata/file-io.c index df5cbe2acf..1e0422e35f 100644 --- a/mono/metadata/file-io.c +++ b/mono/metadata/file-io.c @@ -34,6 +34,7 @@ #include #include #include +#include #undef DEBUG @@ -488,8 +489,13 @@ ves_icall_System_IO_MonoIO_FindFirst (MonoString *path, ifh = g_new (IncrementalFind, 1); ifh->find_handle = find_handle; ifh->utf8_path = mono_string_to_utf8_checked (path, &error); - if (mono_error_set_pending_exception (&error)) + if (mono_error_set_pending_exception (&error)) { + MONO_ENTER_GC_SAFE; + FindClose (find_handle); + MONO_EXIT_GC_SAFE; + g_free (ifh); return NULL; + } ifh->domain = mono_domain_get (); *handle = ifh; @@ -799,10 +805,6 @@ ves_icall_System_IO_MonoIO_Open (MonoString *filename, gint32 mode, if (options & FileOptions_Temporary) attributes |= FILE_ATTRIBUTE_TEMPORARY; - /* Not sure if we should set FILE_FLAG_OVERLAPPED, how does this mix with the "Async" bool here? */ - if (options & FileOptions_Asynchronous) - attributes |= FILE_FLAG_OVERLAPPED; - if (options & FileOptions_WriteThrough) attributes |= FILE_FLAG_WRITE_THROUGH; } else @@ -1240,7 +1242,7 @@ mono_filesize_from_path (MonoString *string) struct stat buf; gint64 res; char *path = mono_string_to_utf8_checked (string, &error); - mono_error_raise_exception (&error); /* FIXME don't raise here */ + mono_error_raise_exception (&error); /* OK to throw, external only without a good alternative */ MONO_ENTER_GC_SAFE; if (stat (path, &buf) == -1) @@ -1272,11 +1274,11 @@ mono_filesize_from_fd (int fd) #endif -void _wapi_handle_dump (void); +void mono_w32handle_dump (void); void ves_icall_System_IO_MonoIO_DumpHandles (void) { #ifndef HOST_WIN32 - _wapi_handle_dump (); + mono_w32handle_dump (); #endif } diff --git a/mono/metadata/file-io.h b/mono/metadata/file-io.h index ab10f92917..0d798ed6a0 100644 --- a/mono/metadata/file-io.h +++ b/mono/metadata/file-io.h @@ -248,6 +248,7 @@ ves_icall_System_IO_MonoIO_ReplaceFile (MonoString *sourceFileName, MonoString * MonoString *destinationBackupFileName, MonoBoolean ignoreMetadataErrors, gint32 *error); +MONO_RT_EXTERNAL_ONLY extern gint64 mono_filesize_from_path (MonoString *path); diff --git a/mono/metadata/file-mmap-posix.c b/mono/metadata/file-mmap-posix.c index 201c724a8f..84e3b4aa68 100644 --- a/mono/metadata/file-mmap-posix.c +++ b/mono/metadata/file-mmap-posix.c @@ -227,20 +227,13 @@ is_special_zero_size_file (struct stat *buf) XXX implement options */ static void* -open_file_map (MonoString *path, int input_fd, int mode, gint64 *capacity, int access, int options, int *ioerror) +open_file_map (const char *c_path, int input_fd, int mode, gint64 *capacity, int access, int options, int *ioerror) { - MonoError error; struct stat buf; - char *c_path = NULL; MmapHandle *handle = NULL; int result, fd; - if (path) { - c_path = mono_string_to_utf8_checked (path, &error); - mono_error_raise_exception (&error); /* FIXME don't raise here */ - } - - if (path) + if (c_path) result = stat (c_path, &buf); else result = fstat (input_fd, &buf); @@ -279,7 +272,7 @@ open_file_map (MonoString *path, int input_fd, int mode, gint64 *capacity, int a } } - if (path) //FIXME use io portability? + if (c_path) //FIXME use io portability? fd = open (c_path, file_mode_to_unix (mode) | access_mode_to_unix (access), DEFAULT_FILEMODE); else fd = dup (input_fd); @@ -299,16 +292,13 @@ open_file_map (MonoString *path, int input_fd, int mode, gint64 *capacity, int a handle->fd = fd; done: - g_free (c_path); return (void*)handle; } #define MONO_ANON_FILE_TEMPLATE "/mono.anonmap.XXXXXXXXX" static void* -open_memory_map (MonoString *mapName, int mode, gint64 *capacity, int access, int options, int *ioerror) +open_memory_map (const char *c_mapName, int mode, gint64 *capacity, int access, int options, int *ioerror) { - MonoError error; - char *c_mapName; MmapHandle *handle; if (*capacity <= 1) { *ioerror = CAPACITY_MUST_BE_POSITIVE; @@ -320,9 +310,6 @@ open_memory_map (MonoString *mapName, int mode, gint64 *capacity, int access, in return NULL; } - c_mapName = mono_string_to_utf8_checked (mapName, &error); - mono_error_raise_exception (&error); /* FIXME don't raise here */ - named_regions_lock (); handle = (MmapHandle*)g_hash_table_lookup (named_regions, c_mapName); if (handle) { @@ -377,46 +364,59 @@ open_memory_map (MonoString *mapName, int mode, gint64 *capacity, int access, in done: named_regions_unlock (); - g_free (c_mapName); return handle; } +/* This is an icall */ void * mono_mmap_open_file (MonoString *path, int mode, MonoString *mapName, gint64 *capacity, int access, int options, int *ioerror) { MonoError error; + MmapHandle *handle = NULL; g_assert (path || mapName); - if (!mapName) - return open_file_map (path, -1, mode, capacity, access, options, ioerror); + if (!mapName) { + char * c_path = mono_string_to_utf8_checked (path, &error); + if (mono_error_set_pending_exception (&error)) + return NULL; + handle = open_file_map (c_path, -1, mode, capacity, access, options, ioerror); + g_free (c_path); + return handle; + } + + char *c_mapName = mono_string_to_utf8_checked (mapName, &error); + if (mono_error_set_pending_exception (&error)) + return NULL; if (path) { - MmapHandle *handle; - char *c_mapName = mono_string_to_utf8_checked (mapName, &error); - mono_error_raise_exception (&error); /* FIXME don't raise here */ - named_regions_lock (); handle = (MmapHandle*)g_hash_table_lookup (named_regions, c_mapName); if (handle) { *ioerror = FILE_ALREADY_EXISTS; handle = NULL; } else { - handle = (MmapHandle *)open_file_map (path, -1, mode, capacity, access, options, ioerror); - if (handle) { - handle->name = g_strdup (c_mapName); - g_hash_table_insert (named_regions, handle->name, handle); + char *c_path = mono_string_to_utf8_checked (path, &error); + if (is_ok (&error)) { + handle = (MmapHandle *)open_file_map (c_path, -1, mode, capacity, access, options, ioerror); + if (handle) { + handle->name = g_strdup (c_mapName); + g_hash_table_insert (named_regions, handle->name, handle); + } + } else { + handle = NULL; } + g_free (c_path); } named_regions_unlock (); + } else + handle = open_memory_map (c_mapName, mode, capacity, access, options, ioerror); - g_free (c_mapName); - return handle; - } - - return open_memory_map (mapName, mode, capacity, access, options, ioerror); + g_free (c_mapName); + return handle; } +/* this is an icall */ void * mono_mmap_open_handle (void *input_fd, MonoString *mapName, gint64 *capacity, int access, int options, int *ioerror) { @@ -426,7 +426,8 @@ mono_mmap_open_handle (void *input_fd, MonoString *mapName, gint64 *capacity, in handle = (MmapHandle *)open_file_map (NULL, GPOINTER_TO_INT (input_fd), FILE_MODE_OPEN, capacity, access, options, ioerror); } else { char *c_mapName = mono_string_to_utf8_checked (mapName, &error); - mono_error_raise_exception (&error); /* FIXME don't raise here */ + if (mono_error_set_pending_exception (&error)) + return NULL; named_regions_lock (); handle = (MmapHandle*)g_hash_table_lookup (named_regions, c_mapName); diff --git a/mono/metadata/gc-internals.h b/mono/metadata/gc-internals.h index cd9408df98..d3d81f272a 100644 --- a/mono/metadata/gc-internals.h +++ b/mono/metadata/gc-internals.h @@ -103,8 +103,6 @@ extern void mono_gc_set_stack_end (void *stack_end); gboolean mono_object_is_alive (MonoObject* obj); gboolean mono_gc_is_finalizer_thread (MonoThread *thread); gpointer mono_gc_out_of_memory (size_t size); -void mono_gc_enable_events (void); -void mono_gc_enable_alloc_events (void); void mono_gchandle_set_target (guint32 gchandle, MonoObject *obj); diff --git a/mono/metadata/gc.c b/mono/metadata/gc.c index a027969e61..ae4329be66 100644 --- a/mono/metadata/gc.c +++ b/mono/metadata/gc.c @@ -48,26 +48,27 @@ #endif typedef struct DomainFinalizationReq { + gint32 ref; MonoDomain *domain; - HANDLE done_event; + MonoCoopSem done; } DomainFinalizationReq; -static gboolean gc_disabled = FALSE; +static gboolean gc_disabled; -static gboolean finalizing_root_domain = FALSE; +static gboolean finalizing_root_domain; -gboolean log_finalizers = FALSE; -gboolean mono_do_not_finalize = FALSE; -volatile gboolean suspend_finalizers = FALSE; -gchar **mono_do_not_finalize_class_names = NULL; +gboolean log_finalizers; +gboolean mono_do_not_finalize; +volatile gboolean suspend_finalizers; +gchar **mono_do_not_finalize_class_names ; #define mono_finalizer_lock() mono_coop_mutex_lock (&finalizer_mutex) #define mono_finalizer_unlock() mono_coop_mutex_unlock (&finalizer_mutex) static MonoCoopMutex finalizer_mutex; static MonoCoopMutex reference_queue_mutex; -static GSList *domains_to_finalize= NULL; -static MonoMList *threads_to_finalize = NULL; +static GSList *domains_to_finalize; +static MonoMList *threads_to_finalize; static gboolean finalizer_thread_exited; /* Uses finalizer_mutex */ @@ -75,12 +76,20 @@ static MonoCoopCond exited_cond; static MonoInternalThread *gc_thread; +#ifdef TARGET_WIN32 +static HANDLE pending_done_event; +#else +static gboolean pending_done; +static MonoCoopCond pending_done_cond; +static MonoCoopMutex pending_done_mutex; +#endif + static void object_register_finalizer (MonoObject *obj, void (*callback)(void *, void*)); static void reference_queue_proccess_all (void); static void mono_reference_queue_cleanup (void); static void reference_queue_clear_for_domain (MonoDomain *domain); -static HANDLE pending_done_event; + static guint32 guarded_wait (HANDLE handle, guint32 timeout, gboolean alertable) @@ -94,6 +103,60 @@ guarded_wait (HANDLE handle, guint32 timeout, gboolean alertable) return result; } +typedef struct { + MonoCoopCond *cond; + MonoCoopMutex *mutex; +} BreakCoopAlertableWaitUD; + +static inline void +break_coop_alertable_wait (gpointer user_data) +{ + BreakCoopAlertableWaitUD *ud = (BreakCoopAlertableWaitUD*)user_data; + + mono_coop_mutex_lock (ud->mutex); + mono_coop_cond_signal (ud->cond); + mono_coop_mutex_unlock (ud->mutex); + + g_free (ud); +} + +/* + * coop_cond_timedwait_alertable: + * + * Wait on COND/MUTEX. If ALERTABLE is non-null, the wait can be interrupted. + * In that case, *ALERTABLE will be set to TRUE, and 0 is returned. + */ +static inline gint +coop_cond_timedwait_alertable (MonoCoopCond *cond, MonoCoopMutex *mutex, guint32 timeout_ms, gboolean *alertable) +{ + BreakCoopAlertableWaitUD *ud; + int res; + + if (alertable) { + ud = g_new0 (BreakCoopAlertableWaitUD, 1); + ud->cond = cond; + ud->mutex = mutex; + + mono_thread_info_install_interrupt (break_coop_alertable_wait, ud, alertable); + if (*alertable) { + g_free (ud); + return 0; + } + } + res = mono_coop_cond_timedwait (cond, mutex, timeout_ms); + if (alertable) { + mono_thread_info_uninstall_interrupt (alertable); + if (*alertable) + return 0; + else { + /* the interrupt token has not been taken by another + * thread, so it's our responsability to free it up. */ + g_free (ud); + } + } + return res; +} + static gboolean add_thread_to_finalize (MonoInternalThread *thread, MonoError *error) { @@ -386,9 +449,10 @@ gboolean mono_domain_finalize (MonoDomain *domain, guint32 timeout) { DomainFinalizationReq *req; - guint32 res; - HANDLE done_event; MonoInternalThread *thread = mono_thread_internal_current (); + gint res; + gboolean ret; + gint64 start; #if defined(__native_client__) return FALSE; @@ -412,14 +476,10 @@ mono_domain_finalize (MonoDomain *domain, guint32 timeout) mono_gc_collect (mono_gc_max_generation ()); - done_event = CreateEvent (NULL, TRUE, FALSE, NULL); - if (done_event == NULL) { - return FALSE; - } - req = g_new0 (DomainFinalizationReq, 1); + req->ref = 2; req->domain = domain; - req->done_event = done_event; + mono_coop_sem_init (&req->done, 0); if (domain == mono_get_root_domain ()) finalizing_root_domain = TRUE; @@ -435,32 +495,78 @@ mono_domain_finalize (MonoDomain *domain, guint32 timeout) if (timeout == -1) timeout = INFINITE; + if (timeout != INFINITE) + start = mono_msec_ticks (); - while (TRUE) { - res = guarded_wait (done_event, timeout, TRUE); - /* printf ("WAIT RES: %d.\n", res); */ + ret = TRUE; - if (res == WAIT_IO_COMPLETION) { - if ((thread->state & (ThreadState_StopRequested | ThreadState_SuspendRequested)) != 0) - return FALSE; - } else if (res == WAIT_TIMEOUT) { - /* We leak the handle here */ - return FALSE; + for (;;) { + if (timeout == INFINITE) { + res = mono_coop_sem_wait (&req->done, MONO_SEM_FLAGS_ALERTABLE); } else { + gint64 elapsed = mono_msec_ticks () - start; + if (elapsed >= timeout) { + ret = FALSE; + break; + } + + res = mono_coop_sem_timedwait (&req->done, timeout - elapsed, MONO_SEM_FLAGS_ALERTABLE); + } + + if (res == MONO_SEM_TIMEDWAIT_RET_SUCCESS) { break; + } else if (res == MONO_SEM_TIMEDWAIT_RET_ALERTED) { + if ((thread->state & (ThreadState_StopRequested | ThreadState_SuspendRequested)) != 0) { + ret = FALSE; + break; + } + } else if (res == MONO_SEM_TIMEDWAIT_RET_TIMEDOUT) { + ret = FALSE; + break; + } else { + g_error ("%s: unknown result %d", __func__, res); } } - CloseHandle (done_event); + if (!ret) { + /* Try removing the req from domains_to_finalize: + * - if it's not found: the domain is being finalized, + * so we the ref count is already decremented + * - if it's found: the domain is not yet being finalized, + * so we can safely decrement the ref */ + + gboolean found; + + mono_finalizer_lock (); + + found = g_slist_index (domains_to_finalize, req) != -1; + if (found) + domains_to_finalize = g_slist_remove (domains_to_finalize, req); + + mono_finalizer_unlock (); + + if (found) { + /* We have to decrement it wherever we + * remove it from domains_to_finalize */ + if (InterlockedDecrement (&req->ref) != 1) + g_error ("%s: req->ref should be 1, as we are the first one to decrement it", __func__); + } + + goto done; + } if (domain == mono_get_root_domain ()) { mono_threadpool_ms_cleanup (); mono_gc_finalize_threadpool_threads (); } - mono_profiler_appdomain_event (domain, MONO_PROFILE_END_UNLOAD); +done: + if (InterlockedDecrement (&req->ref) == 0) { + mono_coop_sem_destroy (&req->done); + g_free (req); + } - return TRUE; + return ret; } void @@ -532,11 +638,24 @@ ves_icall_System_GC_WaitForPendingFinalizers (void) if (gc_thread == NULL) return; +#ifdef TARGET_WIN32 ResetEvent (pending_done_event); mono_gc_finalize_notify (); /* g_print ("Waiting for pending finalizers....\n"); */ guarded_wait (pending_done_event, INFINITE, TRUE); /* g_print ("Done pending....\n"); */ +#else + gboolean alerted = FALSE; + mono_coop_mutex_lock (&pending_done_mutex); + pending_done = FALSE; + mono_gc_finalize_notify (); + while (!pending_done) { + coop_cond_timedwait_alertable (&pending_done_cond, &pending_done_mutex, INFINITE, &alerted); + if (alerted) + break; + } + mono_coop_mutex_unlock (&pending_done_mutex); +#endif } void @@ -626,8 +745,14 @@ mono_gc_GCHandle_CheckCurrentDomain (guint32 gchandle) } static MonoCoopSem finalizer_sem; -static volatile gboolean finished=FALSE; +static volatile gboolean finished; +/* + * mono_gc_finalize_notify: + * + * Notify the finalizer thread that finalizers etc. + * are available to be processed. + */ void mono_gc_finalize_notify (void) { @@ -693,9 +818,24 @@ collect_objects (gpointer key, gpointer value, gpointer user_data) * Run the finalizers of all finalizable objects in req->domain. */ static void -finalize_domain_objects (DomainFinalizationReq *req) +finalize_domain_objects (void) { - MonoDomain *domain = req->domain; + DomainFinalizationReq *req = NULL; + MonoDomain *domain; + + if (domains_to_finalize) { + mono_finalizer_lock (); + if (domains_to_finalize) { + req = (DomainFinalizationReq *)domains_to_finalize->data; + domains_to_finalize = g_slist_remove (domains_to_finalize, req); + } + mono_finalizer_unlock (); + } + + if (!req) + return; + + domain = req->domain; /* Process finalizers which are already in the queue */ mono_gc_invoke_finalizers (); @@ -730,21 +870,25 @@ finalize_domain_objects (DomainFinalizationReq *req) reference_queue_clear_for_domain (domain); /* printf ("DONE.\n"); */ - SetEvent (req->done_event); + mono_coop_sem_post (&req->done); - /* The event is closed in mono_domain_finalize if we get here */ - g_free (req); + if (InterlockedDecrement (&req->ref) == 0) { + /* mono_domain_finalize already returned, and + * doesn't hold a reference to req anymore. */ + mono_coop_sem_destroy (&req->done); + g_free (req); + } } static guint32 finalizer_thread (gpointer unused) { MonoError error; + gboolean wait = TRUE; + mono_thread_set_name_internal (mono_thread_internal_current (), mono_string_new (mono_get_root_domain (), "Finalizer"), FALSE, &error); mono_error_assert_ok (&error); - gboolean wait = TRUE; - /* Register a hazard free queue pump callback */ mono_hazard_pointer_install_free_queue_size_callback (hazard_free_queue_is_too_big); @@ -770,18 +914,7 @@ finalizer_thread (gpointer unused) mono_attach_maybe_start (); - if (domains_to_finalize) { - mono_finalizer_lock (); - if (domains_to_finalize) { - DomainFinalizationReq *req = (DomainFinalizationReq *)domains_to_finalize->data; - domains_to_finalize = g_slist_remove (domains_to_finalize, req); - mono_finalizer_unlock (); - - finalize_domain_objects (req); - } else { - mono_finalizer_unlock (); - } - } + finalize_domain_objects (); mono_profiler_gc_finalize_begin (); @@ -799,11 +932,18 @@ finalizer_thread (gpointer unused) hazard_free_queue_pump (); /* Avoid posting the pending done event until there are pending finalizers */ - if (mono_coop_sem_timedwait (&finalizer_sem, 0, MONO_SEM_FLAGS_NONE) == 0) { + if (mono_coop_sem_timedwait (&finalizer_sem, 0, MONO_SEM_FLAGS_NONE) == MONO_SEM_TIMEDWAIT_RET_SUCCESS) { /* Don't wait again at the start of the loop */ wait = FALSE; } else { +#ifdef TARGET_WIN32 SetEvent (pending_done_event); +#else + mono_coop_mutex_lock (&pending_done_mutex); + pending_done = TRUE; + mono_coop_cond_signal (&pending_done_cond); + mono_coop_mutex_unlock (&pending_done_mutex); +#endif } } @@ -845,8 +985,14 @@ mono_gc_init (void) return; } +#ifdef TARGET_WIN32 pending_done_event = CreateEvent (NULL, TRUE, FALSE, NULL); g_assert (pending_done_event); +#else + mono_coop_cond_init (&pending_done_cond); + mono_coop_mutex_init (&pending_done_mutex); +#endif + mono_coop_cond_init (&exited_cond); mono_coop_sem_init (&finalizer_sem, 0); diff --git a/mono/metadata/handle.c b/mono/metadata/handle.c index 6c26625950..e201b38c68 100644 --- a/mono/metadata/handle.c +++ b/mono/metadata/handle.c @@ -3,8 +3,10 @@ * * Authors: * - Ludovic Henry + * - Aleksey Klieger + * - Rodrigo Kumpera * - * Copyright 2015 Xamarin, Inc. (www.xamarin.com) + * Copyright 2016 Dot net foundation. * Licensed under the MIT license. See LICENSE file in the project root for full license information. */ @@ -17,204 +19,207 @@ #include #include #include +/* TODO (missing pieces) -#define HANDLES_PER_CHUNK (16 - 2) +Add counters for: + number of stack marks + stack marks per icall + mix/max/avg size of stack marks + handle stack wastage -typedef struct _MonoHandleArenaChunk MonoHandleArenaChunk; -struct _MonoHandleArenaChunk { - /* if next is NULL, this is the first chunk. - * - * The first chunk is special - it was allocated together with - * its owning arena and must not be deallocated unless the - * arena is being deallocated. N.B: Arenas are - * stack-allocated. - */ - MonoHandleArenaChunk *next; - gsize handles_size; - MonoHandleStorage handles [HANDLES_PER_CHUNK]; -}; +Actually do something in mono_handle_verify -struct _MonoHandleArena { - MonoHandleArenaChunk *chunk; - MonoHandleArena *prev; -}; +Shrink the handles stack in mono_handle_stack_scan +Properly report it to the profiler. +Add a boehm implementation -static mono_lazy_init_t arena_status = MONO_LAZY_INIT_STATUS_NOT_INITIALIZED; +TODO (things to explore): -static MonoGCDescriptor arena_desc = MONO_GC_DESCRIPTOR_NULL; +There's no convenient way to wrap the object allocation function. +Right now we do this: + MonoCultureInfoHandle culture = MONO_HANDLE_NEW (MonoCultureInfo, mono_object_new_checked (domain, klass, &error)); -static MonoHandleArenaChunk *chunk_free_list = NULL; +Maybe what we need is a round of cleanup around all exposed types in the runtime to unify all helpers under the same hoof. +Combine: MonoDefaults, GENERATE_GET_CLASS_WITH_CACHE, TYPED_HANDLE_DECL and friends. + This would solve the age old issue of making it clear which types are optional and tell that to the linker. + We could then generate neat type safe wrappers. +*/ -static inline MonoHandleArenaChunk* -chunk_alloc (void) +/* + * NOTE: Async suspend + * + * If we are running with cooperative GC, all the handle stack + * manipulation will complete before a GC thread scans the handle + * stack. If we are using async suspend, however, a thread may be + * trying to allocate a new handle, or unwind the handle stack when + * the GC stops the world. + * + * In particular, we need to ensure that if the mutator thread is + * suspended while manipulating the handle stack, the stack is in a + * good enough state to be scanned. In particular, the size of each + * chunk should be updated before an object is written into the + * handle, and chunks to be scanned (between bottom and top) should + * always be valid. + * + * Note that the handle stack is scanned PRECISELY (see + * sgen_client_scan_thread_data ()). That means there should not be + * stale objects scanned. So when we manipulate the size of a chunk, + * wemust ensure that the newly scannable slot is either null or + * points to a valid value. + */ + +const MonoObjectHandle mono_null_value_handle = NULL; + +#define THIS_IS_AN_OK_NUMBER_OF_HANDLES 100 + +/* Actual handles implementation */ +MonoRawHandle +mono_handle_new (MonoObject *object) { - MonoHandleArenaChunk *old, *new; + MonoThreadInfo *info = mono_thread_info_current (); + HandleStack *handles = (HandleStack *)info->handle_stack; + HandleChunk *top = handles->top; - do { - old = chunk_free_list; - if (!old) { - MonoHandleArenaChunk *chunk; - - chunk = g_malloc0 (sizeof (MonoHandleArenaChunk)); - g_assert (chunk); - - return chunk; - } - - new = old->next; - } while (InterlockedCompareExchangePointer ((gpointer*) &chunk_free_list, new, old) != old); - - memset (old, 0, sizeof (MonoHandleArenaChunk)); - return old; +retry: + if (G_LIKELY (top->size < OBJECTS_PER_HANDLES_CHUNK)) { + int idx = top->size; + /* can be interrupted anywhere here, so: + * 1. make sure the new slot is null + * 2. make the new slot scannable (increment size) + * 3. put a valid object in there + * + * (have to do 1 then 3 so that if we're interrupted + * between 1 and 2, the object is still live) + */ + top->objects [idx] = NULL; + mono_memory_write_barrier (); + top->size++; + mono_memory_write_barrier (); + MonoObject **h = &top->objects [idx]; + *h = object; + return h; + } + if (G_LIKELY (top->next)) { + top->next->size = 0; + /* make sure size == 0 is visible to a GC thread before it sees the new top */ + mono_memory_write_barrier (); + top = top->next; + handles->top = top; + goto retry; + } + HandleChunk *new_chunk = g_new (HandleChunk, 1); + new_chunk->size = 0; + new_chunk->prev = top; + new_chunk->next = NULL; + /* make sure size == 0 before new chunk is visible */ + mono_memory_write_barrier (); + top->next = new_chunk; + handles->top = new_chunk; + goto retry; } -static inline void -chunk_free (MonoHandleArenaChunk *chunk) + + +HandleStack* +mono_handle_stack_alloc (void) { - if (chunk == NULL) + HandleStack *stack = g_new (HandleStack, 1); + HandleChunk *chunk = g_new (HandleChunk, 1); + + chunk->size = 0; + chunk->prev = chunk->next = NULL; + mono_memory_write_barrier (); + stack->top = stack->bottom = chunk; + return stack; +} + +void +mono_handle_stack_free (HandleStack *stack) +{ + if (!stack) return; - while (chunk->next != NULL) { - MonoHandleArenaChunk *next = chunk->next; - chunk->next = NULL; - do { - chunk->next = chunk_free_list; - } while (InterlockedCompareExchangePointer ((gpointer*) &chunk_free_list, chunk, chunk->next) != chunk->next); - chunk = next; + HandleChunk *c = stack->bottom; + stack->top = stack->bottom = NULL; + mono_memory_write_barrier (); + while (c) { + HandleChunk *next = c->next; + g_free (c); + c = next; + } + g_free (c); + g_free (stack); +} + +void +mono_handle_stack_scan (HandleStack *stack, GcScanFunc func, gpointer gc_data) +{ + /* if we're running, we know the world is stopped. + */ + HandleChunk *cur = stack->bottom; + HandleChunk *last = stack->top; + + if (!cur) + return; + + while (cur) { + int i; + for (i = 0; i < cur->size; ++i) { + if (cur->objects [i] != NULL) + func ((gpointer*)&cur->objects [i], gc_data); + } + if (cur == last) + break; + cur = cur->next; } } -static MonoHandle -handle_new (MonoHandleArena *arena, MonoObject *obj) +void +mono_stack_mark_record_size (MonoThreadInfo *info, HandleStackMark *stackmark, const char *func_name) { - MonoHandleArenaChunk *chunk; - - g_assert (arena->chunk); - - chunk = arena->chunk; - - if (chunk->handles_size < HANDLES_PER_CHUNK) { - chunk->handles [chunk->handles_size].__private_obj = obj; - chunk->handles_size += 1; - - return &chunk->handles [chunk->handles_size - 1]; - } else { - - MonoHandleArenaChunk *new_chunk = chunk_alloc (); - new_chunk->next = chunk; - arena->chunk = chunk = new_chunk; - - chunk->handles [0].__private_obj = obj; - chunk->handles_size = 1; - - return &chunk->handles [0]; + HandleStack *handles = (HandleStack *)info->handle_stack; + HandleChunk *cur = stackmark->chunk; + int size = -stackmark->size; //discard the starting point of the stack + while (cur) { + size += cur->size; + if (cur == handles->top) + break; + cur = cur->next; } -} -MonoHandle -mono_handle_arena_new (MonoHandleArena *arena, MonoObject *obj) -{ - g_assert (arena); - return handle_new (arena, obj); + if (size > THIS_IS_AN_OK_NUMBER_OF_HANDLES) + g_warning ("%s USED %d handles\n", func_name, size); } /* - * Elevate the handle to the parent arena + * Pop the stack until @stackmark and make @value the top value. + * + * @return the new handle for what @value points to */ -MonoHandle -mono_handle_arena_elevate (MonoHandleArena *arena, MonoHandle handle) +MonoRawHandle +mono_stack_mark_pop_value (MonoThreadInfo *info, HandleStackMark *stackmark, MonoRawHandle value) { - g_assert (handle); - g_assert (arena); - g_assert (arena->prev); - - return handle_new (arena->prev, handle->__private_obj); + g_error ("impl me"); } -gsize -mono_handle_arena_size (void) +/* Temporary place for some of the handle enabled wrapper functions*/ + +MonoStringHandle +mono_string_new_handle (MonoDomain *domain, const char *data, MonoError *error) { - return sizeof (MonoHandleArena) + sizeof (MonoHandleArenaChunk); + return MONO_HANDLE_NEW (MonoString, mono_string_new_checked (domain, data, error)); } +MonoArrayHandle +mono_array_new_handle (MonoDomain *domain, MonoClass *eclass, uintptr_t n, MonoError *error) +{ + return MONO_HANDLE_NEW (MonoArray, mono_array_new_checked (domain, eclass, n, error)); +} + +#ifdef ENABLE_CHECKED_BUILD +/* Checked build helpers */ void -mono_handle_arena_stack_push(MonoHandleArena **arena_stack, MonoHandleArena *arena) +mono_handle_verify (MonoRawHandle raw_handle) { - g_assert (arena_stack); - g_assert (arena); - - arena->prev = *arena_stack; - arena->chunk = (MonoHandleArenaChunk*) (((char*) arena) + sizeof (MonoHandleArena)); - - arena->chunk->next = NULL; - arena->chunk->handles_size = 0; - memset (&arena->chunk->handles [0], 0, sizeof (MonoHandleStorage) * HANDLES_PER_CHUNK); - - *arena_stack = arena; -} - -void -mono_handle_arena_stack_pop(MonoHandleArena **arena_stack, MonoHandleArena *arena) -{ - MonoHandleArenaChunk *chunk, *next; - - g_assert (arena); - g_assert (arena->chunk); - g_assert (arena_stack); - - *arena_stack = arena->prev; - - for (chunk = arena->chunk; chunk; chunk = next) { - next = chunk->next; - memset (&chunk->handles [0], 0, sizeof (MonoHandleStorage) * HANDLES_PER_CHUNK); - if (next != NULL) - chunk_free (chunk); - } -} - -static void -arena_scan (gpointer addr, MonoGCMarkFunc mark_func, gpointer gc_data) -{ - MonoHandleArena *arena; - MonoHandleArenaChunk *chunk; - int i; - - for (arena = *(MonoHandleArena**) addr; arena; arena = arena->prev) { - for (chunk = arena->chunk; chunk; chunk = chunk->next) { - for (i = 0; i < chunk->handles_size; ++i) { - if (chunk->handles [i].__private_obj != NULL) - mark_func (&chunk->handles [i].__private_obj, gc_data); - } - } - } -} - -static void -initialize (void) -{ - arena_desc = mono_gc_make_root_descr_user (arena_scan); -} - -void -mono_handle_arena_init (MonoHandleArena **arena_stack) -{ - mono_lazy_initialize (&arena_status, initialize); - mono_gc_register_root ((char*) arena_stack, sizeof (MonoHandleArena*), arena_desc, MONO_ROOT_SOURCE_HANDLE, "runtime threads handle arena"); -} - -void -mono_handle_arena_cleanup (MonoHandleArena **arena_stack) -{ - mono_gc_deregister_root ((char*) arena_stack); -} - -MonoHandleArena* -mono_handle_arena_current (void) -{ - return (MonoHandleArena*) mono_thread_info_current ()->handle_arena; -} - -MonoHandleArena** -mono_handle_arena_current_addr (void) -{ - return (MonoHandleArena**) &mono_thread_info_current ()->handle_arena; + } +#endif diff --git a/mono/metadata/handle.h b/mono/metadata/handle.h index 99a0428290..76a43969eb 100644 --- a/mono/metadata/handle.h +++ b/mono/metadata/handle.h @@ -3,8 +3,10 @@ * * Authors: * - Ludovic Henry + * - Aleksey Klieger + * - Rodrigo Kumpera * - * Copyright 2015 Xamarin, Inc. (www.xamarin.com) + * Copyright 2016 Dot net foundation. * Licensed under the MIT license. See LICENSE file in the project root for full license information. */ @@ -16,183 +18,260 @@ #include #include -#include +#include +#include #include G_BEGIN_DECLS + /* - * DO NOT ACCESS DIRECTLY - * USE mono_handle_obj BELOW TO ACCESS OBJ - * - * The field obj is not private as there is no way to do that - * in C, but using a C++ template would simplify that a lot - */ -typedef struct { - MonoObject *__private_obj; -} MonoHandleStorage; +Handle stack. -typedef MonoHandleStorage* MonoHandle; +The handle stack is designed so it's efficient to pop a large amount of entries at once. +The stack is made out of a series of fixed size segments. -typedef struct _MonoHandleArena MonoHandleArena; +To do bulk operations you use a stack mark. + +*/ -gsize -mono_handle_arena_size (void); - -MonoHandle -mono_handle_arena_new (MonoHandleArena *arena, MonoObject *obj); - -MonoHandle -mono_handle_arena_elevate (MonoHandleArena *arena, MonoHandle handle); - -void -mono_handle_arena_stack_push (MonoHandleArena **arena_stack, MonoHandleArena *arena); - -void -mono_handle_arena_stack_pop (MonoHandleArena **arena_stack, MonoHandleArena *arena); - -void -mono_handle_arena_init (MonoHandleArena **arena_stack); - -void -mono_handle_arena_cleanup (MonoHandleArena **arena_stack); - -MonoHandleArena* -mono_handle_arena_current (void); - -MonoHandleArena** -mono_handle_arena_current_addr (void); - -#define MONO_HANDLE_ARENA_PUSH() \ - do { \ - MonoHandleArena **__arena_stack = mono_handle_arena_current_addr (); \ - MonoHandleArena *__arena = (MonoHandleArena*) g_alloca (mono_handle_arena_size ()); \ - mono_handle_arena_stack_push (__arena_stack, __arena) - -#define MONO_HANDLE_ARENA_POP() \ - mono_handle_arena_stack_pop (__arena_stack, __arena); \ - } while (0) - -#define MONO_HANDLE_ARENA_POP_RETURN_UNSAFE(handle,ret) \ - (ret) = (handle)->__private_obj; \ - mono_handle_arena_stack_pop (__arena_stack, __arena); \ - } while (0) - -#define MONO_HANDLE_ARENA_POP_RETURN(handle,ret_handle) \ - *((MonoHandle**)(&(ret_handle))) = mono_handle_elevate ((MonoHandle*)(handle)); \ - mono_handle_arena_stack_pop(__arena_stack, __arena); \ - } while (0) - -static inline MonoHandle -mono_handle_new (MonoObject *obj) -{ - return mono_handle_arena_new (mono_handle_arena_current (), obj); -} - -static inline MonoHandle -mono_handle_elevate (MonoHandle handle) -{ - return mono_handle_arena_elevate (mono_handle_arena_current (), handle); -} - -#ifndef ENABLE_CHECKED_BUILD - -#define mono_handle_obj(handle) ((handle)->__private_obj) - -#define mono_handle_assign(handle,rawptr) do { (handle)->__private_obj = (rawptr); } while(0) - -#else - -static inline void -mono_handle_check_in_critical_section () -{ - MONO_REQ_GC_CRITICAL; -} - -#define mono_handle_obj(handle) (mono_handle_check_in_critical_section (), (handle)->__private_obj) - -#define mono_handle_assign(handle,rawptr) do { mono_handle_check_in_critical_section (); (handle)->__private_obj = (rawptr); } while (0) +/* +3 is the number of fields besides the data in the struct; +128 words makes each chunk 512 or 1024 bytes each +*/ +#define OBJECTS_PER_HANDLES_CHUNK (128 - 3) +/* +Whether this config needs stack watermark recording to know where to start scanning from. +*/ +#ifdef HOST_WATCHOS +#define MONO_NEEDS_STACK_WATERMARK 1 #endif -static inline MonoClass* -mono_handle_class (MonoHandle handle) +typedef struct _HandleChunk HandleChunk; + +struct _HandleChunk { + int size; //number of bytes + HandleChunk *prev, *next; + MonoObject *objects [OBJECTS_PER_HANDLES_CHUNK]; +}; + +typedef struct { + HandleChunk *top; //alloc from here + HandleChunk *bottom; //scan from here +} HandleStack; + +typedef struct { + int size; + HandleChunk *chunk; +} HandleStackMark; + +typedef void *MonoRawHandle; + +typedef void (*GcScanFunc) (gpointer*, gpointer); + + +MonoRawHandle mono_handle_new (MonoObject *object); + +void mono_handle_stack_scan (HandleStack *stack, GcScanFunc func, gpointer gc_data); +HandleStack* mono_handle_stack_alloc (void); +void mono_handle_stack_free (HandleStack *handlestack); +MonoRawHandle mono_stack_mark_pop_value (MonoThreadInfo *info, HandleStackMark *stackmark, MonoRawHandle value); +void mono_stack_mark_record_size (MonoThreadInfo *info, HandleStackMark *stackmark, const char *func_name); + +static inline void +mono_stack_mark_init (MonoThreadInfo *info, HandleStackMark *stackmark) { - return mono_object_get_class (handle->__private_obj); + HandleStack *handles = (HandleStack *)info->handle_stack; + stackmark->size = handles->top->size; + stackmark->chunk = handles->top; } -static inline MonoDomain* -mono_handle_domain (MonoHandle handle) +static inline void +mono_stack_mark_pop (MonoThreadInfo *info, HandleStackMark *stackmark) { - return mono_object_get_domain (handle->__private_obj); + HandleStack *handles = (HandleStack *)info->handle_stack; + handles->top->size = stackmark->size; + mono_memory_write_barrier (); + handles->top = stackmark->chunk; } -#define mono_handle_obj_is_null(handle) ((handle)->__private_obj == NULL) +/* +Icall macros +*/ +#define SETUP_ICALL_COMMON \ + do { \ + MonoError error; \ + MonoThreadInfo *__info = mono_thread_info_current (); \ + error_init (&error); \ -#define MONO_HANDLE_TYPE_DECL(type) typedef struct { type *__private_obj; } type ## HandleStorage ; \ - typedef type ## HandleStorage * type ## Handle -#define MONO_HANDLE_TYPE(type) type ## Handle -#define MONO_HANDLE_NEW(type,obj) ((type ## Handle) mono_handle_new ((MonoObject*) (obj))) -#define MONO_HANDLE_ELEVATE(type,handle) ((type ## Handle) mono_handle_elevate ((MonoObject*) (handle)->__private_obj)) +#define CLEAR_ICALL_COMMON \ + mono_error_set_pending_exception (&error); -#define MONO_HANDLE_ASSIGN(handle,rawptr) \ +#define SETUP_ICALL_FRAME \ + HandleStackMark __mark; \ + mono_stack_mark_init (__info, &__mark); + +#define CLEAR_ICALL_FRAME \ + mono_stack_mark_record_size (__info, &__mark, __FUNCTION__); \ + mono_stack_mark_pop (__info, &__mark); + +#ifdef MONO_NEEDS_STACK_WATERMARK + +static void +mono_thread_info_pop_stack_mark (MonoThreadInfo *info, void *old_mark) +{ + info->stack_mark = old_mark; +} + +static void* +mono_thread_info_push_stack_mark (MonoThreadInfo *info, void *mark) +{ + void *old = info->stack_mark; + info->stack_mark = mark; + return old; +} + +#define SETUP_STACK_WATERMARK \ + int __dummy; \ + __builtin_unwind_init (); \ + void *__old_stack_mark = mono_thread_info_push_stack_mark (__info, &__dummy); + +#define CLEAR_STACK_WATERMARK \ + mono_thread_info_pop_stack_mark (__info, __old_stack_mark); + +#else +#define SETUP_STACK_WATERMARK +#define CLEAR_STACK_WATERMARK +#endif + +#define ICALL_ENTRY() \ + SETUP_ICALL_COMMON \ + SETUP_ICALL_FRAME \ + SETUP_STACK_WATERMARK + +#define ICALL_RETURN() \ do { \ - mono_handle_assign ((handle), (rawptr)); \ - } while (0) + CLEAR_STACK_WATERMARK \ + CLEAR_ICALL_COMMON \ + CLEAR_ICALL_FRAME \ + return; \ + } while (0); } while (0) -#define MONO_HANDLE_SETREF(handle,fieldname,value) \ - do { \ - MonoHandle __value = (MonoHandle) (value); \ - MONO_PREPARE_GC_CRITICAL_REGION; \ - MONO_OBJECT_SETREF (mono_handle_obj ((handle)), fieldname, mono_handle_obj (__value)); \ - MONO_FINISH_GC_CRITICAL_REGION; \ - } while (0) - -#define MONO_HANDLE_SETREF_NULL(handle,fieldname) \ - do { \ - MONO_PREPARE_GC_CRITICAL_REGION; \ - MONO_OBJECT_SETREF (mono_handle_obj ((handle)), fieldname, NULL); \ - MONO_FINISH_GC_CRITICAL_REGION; \ - } while (0) - - -#define MONO_HANDLE_SET(handle,fieldname,value) \ +#define ICALL_RETURN_VAL(VAL) \ do { \ - MONO_PREPARE_GC_CRITICAL_REGION; \ - mono_handle_obj ((handle))->fieldname = (value); \ - MONO_FINISH_GC_CRITICAL_REGION; \ - } while (0) + CLEAR_STACK_WATERMARK \ + CLEAR_ICALL_COMMON \ + CLEAR_ICALL_FRAME \ + return VAL; \ + } while (0); } while (0) -#define MONO_HANDLE_ARRAY_SETREF(handle,index,value) \ - do { \ - MonoHandle __value = (MonoHandle) (value); \ - MONO_PREPARE_GC_CRITICAL_REGION; \ - mono_array_setref (mono_handle_obj ((handle)), (index), mono_handle_obj (__value)); \ - MONO_FINISH_GC_CRITICAL_REGION; \ - } while (0) - -#define MONO_HANDLE_ARRAY_SETREF_NULL(handle,index) \ - do { \ - MONO_PREPARE_GC_CRITICAL_REGION; \ - mono_array_setref (mono_handle_obj ((handle)), (index), NULL); \ - MONO_FINISH_GC_CRITICAL_REGION; \ - } while (0) - - -#define MONO_HANDLE_ARRAY_SET(handle,type,index,value) \ +#define ICALL_RETURN_OBJ(HANDLE) \ do { \ - MONO_PREPARE_GC_CRITICAL_REGION; \ - mono_array_set (mono_handle_obj ((handle)), type, (index), (value)); \ - MONO_FINISH_GC_CRITICAL_REGION; \ + CLEAR_STACK_WATERMARK \ + CLEAR_ICALL_COMMON \ + void* __ret = MONO_HANDLE_RAW (HANDLE); \ + CLEAR_ICALL_FRAME \ + return __ret; \ + } while (0); } while (0) + +/* +Handle macros/functions +*/ + +#ifdef ENABLE_CHECKED_BUILD +void mono_handle_verify (MonoRawHandle handle); +#define HANDLE_INVARIANTS(H) mono_handle_verify((void*)(H)) +#else +#define HANDLE_INVARIANTS(H) (0) +#endif + +#define TYPED_HANDLE_PAYLOAD_NAME(TYPE) TYPE ## HandlePayload +#define TYPED_HANDLE_NAME(TYPE) TYPE ## Handle + +/* + * TYPED_HANDLE_DECL(SomeType): + * Expands to a decl for handles to SomeType and to an internal payload struct. + * + * For example, TYPED_HANDLE_DECL(MonoObject) (see below) expands to: + * + * typedef struct { + * MonoObject *__obj; + * } MonoObjectHandlePayload; + * + * typedef MonoObjectHandlePayload* MonoObjectHandle; + */ +#define TYPED_HANDLE_DECL(TYPE) typedef struct { TYPE *__obj; } TYPED_HANDLE_PAYLOAD_NAME (TYPE) ; typedef TYPED_HANDLE_PAYLOAD_NAME (TYPE) * TYPED_HANDLE_NAME (TYPE) +/* Have to double expand because MONO_STRUCT_OFFSET is doing token pasting on cross-compilers. */ +#define MONO_HANDLE_PAYLOAD_OFFSET_(PayloadType) MONO_STRUCT_OFFSET(PayloadType, __obj) +#define MONO_HANDLE_PAYLOAD_OFFSET(TYPE) MONO_HANDLE_PAYLOAD_OFFSET_(TYPED_HANDLE_PAYLOAD_NAME (TYPE)) + +#define MONO_HANDLE_INIT ((void*) mono_null_value_handle) +#define NULL_HANDLE mono_null_value_handle + +//XXX add functions to get/set raw, set field, set field to null, set array, set array to null +#define MONO_HANDLE_RAW(HANDLE) (HANDLE_INVARIANTS (HANDLE), ((HANDLE)->__obj)) +#define MONO_HANDLE_DCL(TYPE, NAME) TYPED_HANDLE_NAME(TYPE) NAME = (TYPED_HANDLE_NAME(TYPE))(mono_handle_new ((MonoObject*)(NAME ## _raw))) +#define MONO_HANDLE_NEW(TYPE, VALUE) (TYPED_HANDLE_NAME(TYPE))( mono_handle_new ((MonoObject*)(VALUE)) ) +#define MONO_HANDLE_CAST(TYPE, VALUE) (TYPED_HANDLE_NAME(TYPE))( VALUE ) + +/* +WARNING WARNING WARNING + +The following functions require a particular evaluation ordering to ensure correctness. +We must not have exposed handles while any sort of evaluation is happening as that very evaluation might trigger +a safepoint and break us. + +This is why we evaluate index and value before any call to MONO_HANDLE_RAW or other functions that deal with naked objects. +*/ +#define MONO_HANDLE_SETRAW(HANDLE, FIELD, VALUE) do { \ + MonoObject *__val = (MonoObject*)(VALUE); \ + MONO_OBJECT_SETREF (MONO_HANDLE_RAW (HANDLE), FIELD, __val); \ + } while (0); + +#define MONO_HANDLE_SET(HANDLE, FIELD, VALUE) do { \ + MonoObjectHandle __val = MONO_HANDLE_CAST (MonoObject, VALUE); \ + MONO_OBJECT_SETREF (MONO_HANDLE_RAW (HANDLE), FIELD, MONO_HANDLE_RAW (__val)); \ + } while (0); + +/* VS doesn't support typeof :( :( :( */ +#define MONO_HANDLE_SETVAL(HANDLE, FIELD, TYPE, VALUE) do { \ + TYPE __val = (VALUE); \ + MONO_HANDLE_RAW (HANDLE)->FIELD = __val; \ + } while (0) + +#define MONO_HANDLE_ARRAY_SETREF(HANDLE, IDX, VALUE) do { \ + int __idx = (IDX); \ + MonoObjectHandle __val = MONO_HANDLE_CAST (MonoObject, VALUE); \ + mono_array_setref_fast (MONO_HANDLE_RAW (HANDLE), __idx, MONO_HANDLE_RAW (__val)); \ + } while (0) + +#define MONO_HANDLE_ARRAY_SETRAW(HANDLE, IDX, VALUE) do { \ + int __idx = (IDX); \ + MonoObject *__val = (MonoObject*)(VALUE); \ + mono_array_setref_fast (MONO_HANDLE_RAW (HANDLE), __idx, __val); \ } while (0) +#define MONO_HANDLE_DOMAIN(HANDLE) (mono_object_domain (MONO_HANDLE_RAW (MONO_HANDLE_CAST (MonoObject, HANDLE)))) + +/* Baked typed handles we all want */ +TYPED_HANDLE_DECL (MonoString); +TYPED_HANDLE_DECL (MonoArray); +TYPED_HANDLE_DECL (MonoObject); + +#define NULL_HANDLE_STRING MONO_HANDLE_CAST(MonoString, NULL_HANDLE) + +/* +This is the constant for a handle that points nowhere. +Init values to it. +*/ +extern const MonoObjectHandle mono_null_value_handle; -/* Some common handle types */ - -MONO_HANDLE_TYPE_DECL (MonoArray); -MONO_HANDLE_TYPE_DECL (MonoString); +//FIXME this should go somewhere else +MonoStringHandle mono_string_new_handle (MonoDomain *domain, const char *data, MonoError *error); +MonoArrayHandle mono_array_new_handle (MonoDomain *domain, MonoClass *eclass, uintptr_t n, MonoError *error); G_END_DECLS diff --git a/mono/metadata/icall-def.h b/mono/metadata/icall-def.h index 71495d2bc8..92cb607993 100644 --- a/mono/metadata/icall-def.h +++ b/mono/metadata/icall-def.h @@ -35,6 +35,32 @@ * you need to insert a method in the middle, don't bother renaming all the symbols. * Remember to change also the first_icall_id argument in the ICALL_TYPE * declaration if you add a new icall at the beginning of a type's icall list. + * + * + * *** (Experimental) Cooperative GC support via Handles and MonoError *** + * An icall can use the coop GC handles infrastructure from handles.h to avoid some + * boilerplate when manipulating managed objects from runtime code and to use MonoError for + * threading exceptions out to managed callerrs: + * + * HANDLES(ICALL(icallid, methodname, cfuncptr)) + * + * An icall with a HANDLES() declaration wrapped around it will have a generated wrapper + * that: + * (1) Updates the coop handle stack on entry and exit + * (2) Call the cfuncptr with a new signature: + * (a) All managed object reference in arguments will be wrapped in a handle + * (ie, MonoString* becomes MonoStringHandle) + * (b) the same for the return value (MonoObject* return becomes MonoObjectHandle) + * (c) An additional final argument is added of type MonoError* + * example: class object { + * [MethodImplOptions(InternalCall)] + * String some_icall (object[] x); + * } + * should be implemented as: + * MonoStringHandle some_icall (MonoObjectHandle this_handle, MonoArrayHandle x_handle, MonoError *error); + * (3) The wrapper will automatically call mono_error_set_pending_exception (error) and raise the resulting exception. + * Note: valuetypes use the same calling convention as normal. + * Limitations: "out" and "ref" arguments are not supported yet. */ #ifndef DISABLE_PROCESS_HANDLING @@ -52,16 +78,267 @@ ICALL(NATIVEMETHODS_10, "TerminateProcess", ves_icall_Microsoft_Win32_NativeMeth ICALL(NATIVEMETHODS_11, "WaitForInputIdle", ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle) #endif /* !DISABLE_PROCESS_HANDLING */ +#if defined(HAVE_BTLS) && !defined(HAVE_DYNAMIC_BTLS) +ICALL_TYPE(BTLS_BIO, "Mono.Btls.MonoBtlsBio", BTLS_BIO_1) +ICALL(BTLS_BIO_1, "mono_btls_bio_flush", mono_btls_bio_flush) +ICALL(BTLS_BIO_2, "mono_btls_bio_free", mono_btls_bio_free) +ICALL(BTLS_BIO_3, "mono_btls_bio_hexdump", mono_btls_bio_hexdump) +ICALL(BTLS_BIO_4, "mono_btls_bio_indent", mono_btls_bio_indent) +ICALL(BTLS_BIO_5, "mono_btls_bio_print_errors", mono_btls_bio_print_errors) +ICALL(BTLS_BIO_6, "mono_btls_bio_read", mono_btls_bio_read) +ICALL(BTLS_BIO_7, "mono_btls_bio_write", mono_btls_bio_write) + +ICALL_TYPE(BTLS_BIO_MEM, "Mono.Btls.MonoBtlsBioMemory", BTLS_BIO_MEM_1) +ICALL(BTLS_BIO_MEM_1, "mono_btls_bio_mem_get_data", mono_btls_bio_mem_get_data) +ICALL(BTLS_BIO_MEM_2, "mono_btls_bio_mem_new", mono_btls_bio_mem_new) + +ICALL_TYPE(BTLS_BIO_MONO, "Mono.Btls.MonoBtlsBioMono", BTLS_BIO_MONO_1) +ICALL(BTLS_BIO_MONO_1, "mono_btls_bio_mono_initialize", mono_btls_bio_mono_initialize) +ICALL(BTLS_BIO_MONO_2, "mono_btls_bio_mono_new", mono_btls_bio_mono_new) + +ICALL_TYPE(BTLS_ERROR, "Mono.Btls.MonoBtlsError", BTLS_ERROR_1) +ICALL(BTLS_ERROR_1, "mono_btls_error_clear_error", mono_btls_error_clear_error) +ICALL(BTLS_ERROR_2, "mono_btls_error_get_error", mono_btls_error_get_error) +ICALL(BTLS_ERROR_3, "mono_btls_error_get_error_string_n", mono_btls_error_get_error_string_n) +ICALL(BTLS_ERROR_4, "mono_btls_error_peek_error", mono_btls_error_peek_error) + +ICALL_TYPE(BTLS_KEY, "Mono.Btls.MonoBtlsKey", BTLS_KEY_1) +ICALL(BTLS_KEY_1, "mono_btls_key_free", mono_btls_key_free) +ICALL(BTLS_KEY_2, "mono_btls_key_get_bits", mono_btls_key_get_bits) +ICALL(BTLS_KEY_3, "mono_btls_key_get_bytes", mono_btls_key_get_bytes) +ICALL(BTLS_KEY_4, "mono_btls_key_is_rsa", mono_btls_key_is_rsa) +ICALL(BTLS_KEY_5, "mono_btls_key_up_ref", mono_btls_key_up_ref) + +ICALL_TYPE(BTLS_OBJECT, "Mono.Btls.MonoBtlsObject", BTLS_OBJECT_1) +ICALL(BTLS_OBJECT_1, "mono_btls_free", mono_btls_free) + +ICALL_TYPE(BTLS_PKCS12, "Mono.Btls.MonoBtlsPkcs12", BTLS_PKCS12_1) +ICALL(BTLS_PKCS12_1, "mono_btls_pkcs12_add_cert", mono_btls_pkcs12_add_cert) +ICALL(BTLS_PKCS12_2, "mono_btls_pkcs12_free", mono_btls_pkcs12_free) +ICALL(BTLS_PKCS12_3, "mono_btls_pkcs12_get_cert", mono_btls_pkcs12_get_cert) +ICALL(BTLS_PKCS12_4, "mono_btls_pkcs12_get_certs", mono_btls_pkcs12_get_certs) +ICALL(BTLS_PKCS12_5, "mono_btls_pkcs12_get_count", mono_btls_pkcs12_get_count) +ICALL(BTLS_PKCS12_6, "mono_btls_pkcs12_get_private_key", mono_btls_pkcs12_get_private_key) +ICALL(BTLS_PKCS12_7, "mono_btls_pkcs12_has_private_key", mono_btls_pkcs12_has_private_key) +ICALL(BTLS_PKCS12_8, "mono_btls_pkcs12_import", mono_btls_pkcs12_import) +ICALL(BTLS_PKCS12_9, "mono_btls_pkcs12_new", mono_btls_pkcs12_new) +ICALL(BTLS_PKCS12_10, "mono_btls_pkcs12_up_ref", mono_btls_pkcs12_up_ref) + +ICALL_TYPE(BTLS_SSL, "Mono.Btls.MonoBtlsSsl", BTLS_SSL_1) +ICALL(BTLS_SSL_1, "mono_btls_ssl_accept", mono_btls_ssl_accept) +ICALL(BTLS_SSL_2, "mono_btls_ssl_add_chain_certificate", mono_btls_ssl_add_chain_certificate) +ICALL(BTLS_SSL_3, "mono_btls_ssl_close", mono_btls_ssl_close) +ICALL(BTLS_SSL_4, "mono_btls_ssl_connect", mono_btls_ssl_connect) +ICALL(BTLS_SSL_5, "mono_btls_ssl_destroy", mono_btls_ssl_destroy) +ICALL(BTLS_SSL_6, "mono_btls_ssl_get_cipher", mono_btls_ssl_get_cipher) +ICALL(BTLS_SSL_7, "mono_btls_ssl_get_ciphers", mono_btls_ssl_get_ciphers) +ICALL(BTLS_SSL_8, "mono_btls_ssl_get_error", mono_btls_ssl_get_error) +ICALL(BTLS_SSL_9, "mono_btls_ssl_get_peer_certificate", mono_btls_ssl_get_peer_certificate) +ICALL(BTLS_SSL_10, "mono_btls_ssl_get_version", mono_btls_ssl_get_version) +ICALL(BTLS_SSL_11, "mono_btls_ssl_handshake", mono_btls_ssl_handshake) +ICALL(BTLS_SSL_12, "mono_btls_ssl_new", mono_btls_ssl_new) +ICALL(BTLS_SSL_13, "mono_btls_ssl_print_errors_cb", mono_btls_ssl_print_errors_cb) +ICALL(BTLS_SSL_14, "mono_btls_ssl_read", mono_btls_ssl_read) +ICALL(BTLS_SSL_15, "mono_btls_ssl_set_bio", mono_btls_ssl_set_bio) +ICALL(BTLS_SSL_16, "mono_btls_ssl_set_cipher_list", mono_btls_ssl_set_cipher_list) +ICALL(BTLS_SSL_17, "mono_btls_ssl_set_max_version", mono_btls_ssl_set_max_version) +ICALL(BTLS_SSL_18, "mono_btls_ssl_set_min_version", mono_btls_ssl_set_min_version) +ICALL(BTLS_SSL_19, "mono_btls_ssl_set_server_name", mono_btls_ssl_set_server_name) +ICALL(BTLS_SSL_20, "mono_btls_ssl_set_verify_param", mono_btls_ssl_set_verify_param) +ICALL(BTLS_SSL_21, "mono_btls_ssl_use_certificate", mono_btls_ssl_use_certificate) +ICALL(BTLS_SSL_22, "mono_btls_ssl_use_private_key", mono_btls_ssl_use_private_key) +ICALL(BTLS_SSL_23, "mono_btls_ssl_write", mono_btls_ssl_write) + +ICALL_TYPE(BTLS_SSL_CTX, "Mono.Btls.MonoBtlsSslCtx", BTLS_SSL_CTX_1) +ICALL(BTLS_SSL_CTX_1, "mono_btls_ssl_ctx_debug_printf", mono_btls_ssl_ctx_debug_printf) +ICALL(BTLS_SSL_CTX_2, "mono_btls_ssl_ctx_free", mono_btls_ssl_ctx_free) +ICALL(BTLS_SSL_CTX_3, "mono_btls_ssl_ctx_get_ctx", mono_btls_ssl_ctx_get_ctx) +ICALL(BTLS_SSL_CTX_4, "mono_btls_ssl_ctx_initialize", mono_btls_ssl_ctx_initialize) +ICALL(BTLS_SSL_CTX_5, "mono_btls_ssl_ctx_is_cipher_supported", mono_btls_ssl_ctx_is_cipher_supported) +ICALL(BTLS_SSL_CTX_6, "mono_btls_ssl_ctx_is_debug_enabled", mono_btls_ssl_ctx_is_debug_enabled) +ICALL(BTLS_SSL_CTX_7, "mono_btls_ssl_ctx_new", mono_btls_ssl_ctx_new) +ICALL(BTLS_SSL_CTX_8, "mono_btls_ssl_ctx_peek_store", mono_btls_ssl_ctx_peek_store) +ICALL(BTLS_SSL_CTX_9, "mono_btls_ssl_ctx_set_cert_select_callback", mono_btls_ssl_ctx_set_cert_select_callback) +ICALL(BTLS_SSL_CTX_10, "mono_btls_ssl_ctx_set_cert_verify_callback", mono_btls_ssl_ctx_set_cert_verify_callback) +ICALL(BTLS_SSL_CTX_11, "mono_btls_ssl_ctx_set_ciphers", mono_btls_ssl_ctx_set_ciphers) +ICALL(BTLS_SSL_CTX_12, "mono_btls_ssl_ctx_set_debug_bio", mono_btls_ssl_ctx_set_debug_bio) +ICALL(BTLS_SSL_CTX_13, "mono_btls_ssl_ctx_set_max_version", mono_btls_ssl_ctx_set_max_version) +ICALL(BTLS_SSL_CTX_14, "mono_btls_ssl_ctx_set_min_version", mono_btls_ssl_ctx_set_min_version) +ICALL(BTLS_SSL_CTX_15, "mono_btls_ssl_ctx_set_verify_param", mono_btls_ssl_ctx_set_verify_param) +ICALL(BTLS_SSL_CTX_16, "mono_btls_ssl_ctx_up_ref", mono_btls_ssl_ctx_up_ref) + +ICALL_TYPE(BTLS_X509, "Mono.Btls.MonoBtlsX509", BTLS_X509_1) +ICALL(BTLS_X509_1, "mono_btls_x509_add_explicit_trust", mono_btls_x509_add_explicit_trust) +ICALL(BTLS_X509_2, "mono_btls_x509_add_reject_object", mono_btls_x509_add_reject_object) +ICALL(BTLS_X509_3, "mono_btls_x509_add_trust_object", mono_btls_x509_add_trust_object) +ICALL(BTLS_X509_4, "mono_btls_x509_cmp", mono_btls_x509_cmp) +ICALL(BTLS_X509_5, "mono_btls_x509_dup", mono_btls_x509_dup) +ICALL(BTLS_X509_6, "mono_btls_x509_free", mono_btls_x509_free) +ICALL(BTLS_X509_7, "mono_btls_x509_from_data", mono_btls_x509_from_data) +ICALL(BTLS_X509_8, "mono_btls_x509_get_hash", mono_btls_x509_get_hash) +ICALL(BTLS_X509_9, "mono_btls_x509_get_issuer_name", mono_btls_x509_get_issuer_name) +ICALL(BTLS_X509_10, "mono_btls_x509_get_issuer_name_string", mono_btls_x509_get_issuer_name_string) +ICALL(BTLS_X509_11, "mono_btls_x509_get_not_after", mono_btls_x509_get_not_after) +ICALL(BTLS_X509_12, "mono_btls_x509_get_not_before", mono_btls_x509_get_not_before) +ICALL(BTLS_X509_13, "mono_btls_x509_get_pubkey", mono_btls_x509_get_pubkey) +ICALL(BTLS_X509_14, "mono_btls_x509_get_public_key", mono_btls_x509_get_public_key) +ICALL(BTLS_X509_15, "mono_btls_x509_get_public_key_algorithm", mono_btls_x509_get_public_key_algorithm) +ICALL(BTLS_X509_16, "mono_btls_x509_get_public_key_asn1", mono_btls_x509_get_public_key_asn1) +ICALL(BTLS_X509_17, "mono_btls_x509_get_public_key_parameters", mono_btls_x509_get_public_key_parameters) +ICALL(BTLS_X509_18, "mono_btls_x509_get_raw_data", mono_btls_x509_get_raw_data) +ICALL(BTLS_X509_19, "mono_btls_x509_get_serial_number", mono_btls_x509_get_serial_number) +ICALL(BTLS_X509_20, "mono_btls_x509_get_signature_algorithm", mono_btls_x509_get_signature_algorithm) +ICALL(BTLS_X509_21, "mono_btls_x509_get_subject_key_identifier", mono_btls_x509_get_subject_key_identifier) +ICALL(BTLS_X509_22, "mono_btls_x509_get_subject_name", mono_btls_x509_get_subject_name) +ICALL(BTLS_X509_23, "mono_btls_x509_get_subject_name_string", mono_btls_x509_get_subject_name_string) +ICALL(BTLS_X509_24, "mono_btls_x509_get_version", mono_btls_x509_get_version) +ICALL(BTLS_X509_25, "mono_btls_x509_print", mono_btls_x509_print) +ICALL(BTLS_X509_26, "mono_btls_x509_up_ref", mono_btls_x509_up_ref) + +ICALL_TYPE(BTLS_X509_CHAIN, "Mono.Btls.MonoBtlsX509Chain", BTLS_X509_CHAIN_1) +ICALL(BTLS_X509_CHAIN_1, "mono_btls_x509_chain_add_cert", mono_btls_x509_chain_add_cert) +ICALL(BTLS_X509_CHAIN_2, "mono_btls_x509_chain_free", mono_btls_x509_chain_free) +ICALL(BTLS_X509_CHAIN_3, "mono_btls_x509_chain_from_certs", mono_btls_x509_chain_from_certs) +ICALL(BTLS_X509_CHAIN_4, "mono_btls_x509_chain_get_cert", mono_btls_x509_chain_get_cert) +ICALL(BTLS_X509_CHAIN_5, "mono_btls_x509_chain_get_count", mono_btls_x509_chain_get_count) +ICALL(BTLS_X509_CHAIN_6, "mono_btls_x509_chain_new", mono_btls_x509_chain_new) +ICALL(BTLS_X509_CHAIN_7, "mono_btls_x509_chain_peek_certs", mono_btls_x509_chain_peek_certs) +ICALL(BTLS_X509_CHAIN_8, "mono_btls_x509_chain_up_ref", mono_btls_x509_chain_up_ref) + +ICALL_TYPE(BTLS_X509_CRL, "Mono.Btls.MonoBtlsX509Crl", BTLS_X509_CRL_1) +ICALL(BTLS_X509_CRL_1, "mono_btls_x509_crl_free", mono_btls_x509_crl_free) +ICALL(BTLS_X509_CRL_2, "mono_btls_x509_crl_from_data", mono_btls_x509_crl_from_data) +ICALL(BTLS_X509_CRL_3, "mono_btls_x509_crl_get_by_cert", mono_btls_x509_crl_get_by_cert) +ICALL(BTLS_X509_CRL_4, "mono_btls_x509_crl_get_by_serial", mono_btls_x509_crl_get_by_serial) +ICALL(BTLS_X509_CRL_5, "mono_btls_x509_crl_get_issuer", mono_btls_x509_crl_get_issuer) +ICALL(BTLS_X509_CRL_6, "mono_btls_x509_crl_get_last_update", mono_btls_x509_crl_get_last_update) +ICALL(BTLS_X509_CRL_7, "mono_btls_x509_crl_get_next_update", mono_btls_x509_crl_get_next_update) +ICALL(BTLS_X509_CRL_8, "mono_btls_x509_crl_get_revoked", mono_btls_x509_crl_get_revoked) +ICALL(BTLS_X509_CRL_9, "mono_btls_x509_crl_get_revoked_count", mono_btls_x509_crl_get_revoked_count) +ICALL(BTLS_X509_CRL_10, "mono_btls_x509_crl_get_version", mono_btls_x509_crl_get_version) +ICALL(BTLS_X509_CRL_11, "mono_btls_x509_crl_ref", mono_btls_x509_crl_ref) + +ICALL_TYPE(BTLS_X509_LOOKUP, "Mono.Btls.MonoBtlsX509Lookup", BTLS_X509_LOOKUP_1) +ICALL(BTLS_X509_LOOKUP_1, "mono_btls_x509_lookup_add_dir", mono_btls_x509_lookup_add_dir) +ICALL(BTLS_X509_LOOKUP_2, "mono_btls_x509_lookup_add_mono", mono_btls_x509_lookup_add_mono) +ICALL(BTLS_X509_LOOKUP_3, "mono_btls_x509_lookup_by_fingerprint", mono_btls_x509_lookup_by_fingerprint) +ICALL(BTLS_X509_LOOKUP_4, "mono_btls_x509_lookup_by_subject", mono_btls_x509_lookup_by_subject) +ICALL(BTLS_X509_LOOKUP_5, "mono_btls_x509_lookup_free", mono_btls_x509_lookup_free) +ICALL(BTLS_X509_LOOKUP_6, "mono_btls_x509_lookup_init", mono_btls_x509_lookup_init) +ICALL(BTLS_X509_LOOKUP_7, "mono_btls_x509_lookup_load_file", mono_btls_x509_lookup_load_file) +ICALL(BTLS_X509_LOOKUP_8, "mono_btls_x509_lookup_mono_init", mono_btls_x509_lookup_mono_init) +ICALL(BTLS_X509_LOOKUP_9, "mono_btls_x509_lookup_new", mono_btls_x509_lookup_new) +ICALL(BTLS_X509_LOOKUP_10, "mono_btls_x509_lookup_peek_lookup", mono_btls_x509_lookup_peek_lookup) +ICALL(BTLS_X509_LOOKUP_11, "mono_btls_x509_lookup_shutdown", mono_btls_x509_lookup_shutdown) +ICALL(BTLS_X509_LOOKUP_12, "mono_btls_x509_lookup_up_ref", mono_btls_x509_lookup_up_ref) + +ICALL_TYPE(BTLS_X509_LOOKUP_MONO, "Mono.Btls.MonoBtlsX509LookupMono", BTLS_X509_LOOKUP_MONO_1) +ICALL(BTLS_X509_LOOKUP_MONO_1, "mono_btls_x509_lookup_mono_free", mono_btls_x509_lookup_mono_free) +ICALL(BTLS_X509_LOOKUP_MONO_2, "mono_btls_x509_lookup_mono_init", mono_btls_x509_lookup_mono_init) +ICALL(BTLS_X509_LOOKUP_MONO_3, "mono_btls_x509_lookup_mono_new", mono_btls_x509_lookup_mono_new) + +ICALL_TYPE(BTLS_X509_NAME, "Mono.Btls.MonoBtlsX509Name", BTLS_X509_NAME_1) +ICALL(BTLS_X509_NAME_1, "mono_btls_x509_name_copy", mono_btls_x509_name_copy) +ICALL(BTLS_X509_NAME_2, "mono_btls_x509_name_free", mono_btls_x509_name_free) +ICALL(BTLS_X509_NAME_3, "mono_btls_x509_name_from_data", mono_btls_x509_name_from_data) +ICALL(BTLS_X509_NAME_4, "mono_btls_x509_name_from_name", mono_btls_x509_name_from_name) +ICALL(BTLS_X509_NAME_5, "mono_btls_x509_name_get_entry_count", mono_btls_x509_name_get_entry_count) +ICALL(BTLS_X509_NAME_6, "mono_btls_x509_name_get_entry_oid", mono_btls_x509_name_get_entry_oid) +ICALL(BTLS_X509_NAME_7, "mono_btls_x509_name_get_entry_oid_data", mono_btls_x509_name_get_entry_oid_data) +ICALL(BTLS_X509_NAME_8, "mono_btls_x509_name_get_entry_type", mono_btls_x509_name_get_entry_type) +ICALL(BTLS_X509_NAME_9, "mono_btls_x509_name_get_entry_value", mono_btls_x509_name_get_entry_value) +ICALL(BTLS_X509_NAME_10, "mono_btls_x509_name_get_raw_data", mono_btls_x509_name_get_raw_data) +ICALL(BTLS_X509_NAME_11, "mono_btls_x509_name_hash", mono_btls_x509_name_hash) +ICALL(BTLS_X509_NAME_12, "mono_btls_x509_name_hash_old", mono_btls_x509_name_hash_old) +ICALL(BTLS_X509_NAME_13, "mono_btls_x509_name_peek_name", mono_btls_x509_name_peek_name) +ICALL(BTLS_X509_NAME_14, "mono_btls_x509_name_print_bio", mono_btls_x509_name_print_bio) +ICALL(BTLS_X509_NAME_15, "mono_btls_x509_name_print_string", mono_btls_x509_name_print_string) + +ICALL_TYPE(BTLS_X509_REVOKED, "Mono.Btls.MonoBtlsX509Revoked", BTLS_X509_REVOKED_1) +ICALL(BTLS_X509_REVOKED_1, "mono_btls_x509_revoked_free", mono_btls_x509_revoked_free) +ICALL(BTLS_X509_REVOKED_2, "mono_btls_x509_revoked_get_reason", mono_btls_x509_revoked_get_reason) +ICALL(BTLS_X509_REVOKED_2a, "mono_btls_x509_revoked_get_revocation_date", mono_btls_x509_revoked_get_revocation_date) +ICALL(BTLS_X509_REVOKED_3, "mono_btls_x509_revoked_get_sequence", mono_btls_x509_revoked_get_sequence) +ICALL(BTLS_X509_REVOKED_4, "mono_btls_x509_revoked_get_serial_number", mono_btls_x509_revoked_get_serial_number) +ICALL(BTLS_X509_REVOKED_5, "mono_btls_x509_revoked_new", mono_btls_x509_revoked_new) + +ICALL_TYPE(BTLS_X509_STORE, "Mono.Btls.MonoBtlsX509Store", BTLS_X509_STORE_1) +ICALL(BTLS_X509_STORE_1, "mono_btls_x509_store_add_cert", mono_btls_x509_store_add_cert) +ICALL(BTLS_X509_STORE_2, "mono_btls_x509_store_free", mono_btls_x509_store_free) +ICALL(BTLS_X509_STORE_3, "mono_btls_x509_store_from_ctx", mono_btls_x509_store_from_ctx) +ICALL(BTLS_X509_STORE_4, "mono_btls_x509_store_from_ssl_ctx", mono_btls_x509_store_from_ssl_ctx) +ICALL(BTLS_X509_STORE_5, "mono_btls_x509_store_get_count", mono_btls_x509_store_get_count) +ICALL(BTLS_X509_STORE_6, "mono_btls_x509_store_load_locations", mono_btls_x509_store_load_locations) +ICALL(BTLS_X509_STORE_7, "mono_btls_x509_store_new", mono_btls_x509_store_new) +ICALL(BTLS_X509_STORE_8, "mono_btls_x509_store_peek_store", mono_btls_x509_store_peek_store) +ICALL(BTLS_X509_STORE_9, "mono_btls_x509_store_set_default_paths", mono_btls_x509_store_set_default_paths) +ICALL(BTLS_X509_STORE_10, "mono_btls_x509_store_up_ref", mono_btls_x509_store_up_ref) + +ICALL_TYPE(BTLS_X509_STORE_CTX, "Mono.Btls.MonoBtlsX509StoreCtx", BTLS_X509_STORE_CTX_1) +ICALL(BTLS_X509_STORE_CTX_1, "mono_btls_x509_store_ctx_free", mono_btls_x509_store_ctx_free) +ICALL(BTLS_X509_STORE_CTX_2, "mono_btls_x509_store_ctx_from_ptr", mono_btls_x509_store_ctx_from_ptr) +ICALL(BTLS_X509_STORE_CTX_3, "mono_btls_x509_store_ctx_get_by_subject", mono_btls_x509_store_ctx_get_by_subject) +ICALL(BTLS_X509_STORE_CTX_4, "mono_btls_x509_store_ctx_get_chain", mono_btls_x509_store_ctx_get_chain) +ICALL(BTLS_X509_STORE_CTX_5, "mono_btls_x509_store_ctx_get_current_cert", mono_btls_x509_store_ctx_get_current_cert) +ICALL(BTLS_X509_STORE_CTX_6, "mono_btls_x509_store_ctx_get_current_issuer", mono_btls_x509_store_ctx_get_current_issuer) +ICALL(BTLS_X509_STORE_CTX_7, "mono_btls_x509_store_ctx_get_error", mono_btls_x509_store_ctx_get_error) +ICALL(BTLS_X509_STORE_CTX_8, "mono_btls_x509_store_ctx_get_error_depth", mono_btls_x509_store_ctx_get_error_depth) +ICALL(BTLS_X509_STORE_CTX_9, "mono_btls_x509_store_ctx_get_untrusted", mono_btls_x509_store_ctx_get_untrusted) +ICALL(BTLS_X509_STORE_CTX_10, "mono_btls_x509_store_ctx_get_verify_param", mono_btls_x509_store_ctx_get_verify_param) +ICALL(BTLS_X509_STORE_CTX_11, "mono_btls_x509_store_ctx_init", mono_btls_x509_store_ctx_init) +ICALL(BTLS_X509_STORE_CTX_12, "mono_btls_x509_store_ctx_new", mono_btls_x509_store_ctx_new) +ICALL(BTLS_X509_STORE_CTX_13, "mono_btls_x509_store_ctx_set_param", mono_btls_x509_store_ctx_set_param) +ICALL(BTLS_X509_STORE_CTX_15, "mono_btls_x509_store_ctx_up_ref", mono_btls_x509_store_ctx_up_ref) +ICALL(BTLS_X509_STORE_CTX_16, "mono_btls_x509_store_ctx_verify_cert", mono_btls_x509_store_ctx_verify_cert) + +ICALL_TYPE(BTLS_X509_VERIFY_PARAM, "Mono.Btls.MonoBtlsX509VerifyParam", BTLS_X509_VERIFY_PARAM_1) +ICALL(BTLS_X509_VERIFY_PARAM_1, "mono_btls_x509_verify_param_add_host", mono_btls_x509_verify_param_add_host) +ICALL(BTLS_X509_VERIFY_PARAM_2, "mono_btls_x509_verify_param_can_modify", mono_btls_x509_verify_param_can_modify) +ICALL(BTLS_X509_VERIFY_PARAM_3, "mono_btls_x509_verify_param_copy", mono_btls_x509_verify_param_copy) +ICALL(BTLS_X509_VERIFY_PARAM_4, "mono_btls_x509_verify_param_free", mono_btls_x509_verify_param_free) +ICALL(BTLS_X509_VERIFY_PARAM_5, "mono_btls_x509_verify_param_from_store_ctx", mono_btls_x509_verify_param_from_store_ctx) +ICALL(BTLS_X509_VERIFY_PARAM_6, "mono_btls_x509_verify_param_get_depth", mono_btls_x509_verify_param_get_depth) +ICALL(BTLS_X509_VERIFY_PARAM_7, "mono_btls_x509_verify_param_get_flags", mono_btls_x509_verify_param_get_flags) +ICALL(BTLS_X509_VERIFY_PARAM_8, "mono_btls_x509_verify_param_get_mono_flags", mono_btls_x509_verify_param_get_mono_flags) +ICALL(BTLS_X509_VERIFY_PARAM_9, "mono_btls_x509_verify_param_get_peername", mono_btls_x509_verify_param_get_peername) +ICALL(BTLS_X509_VERIFY_PARAM_10, "mono_btls_x509_verify_param_lookup", mono_btls_x509_verify_param_lookup) +ICALL(BTLS_X509_VERIFY_PARAM_11, "mono_btls_x509_verify_param_new", mono_btls_x509_verify_param_new) +ICALL(BTLS_X509_VERIFY_PARAM_12, "mono_btls_x509_verify_param_peek_param", mono_btls_x509_verify_param_peek_param) +ICALL(BTLS_X509_VERIFY_PARAM_13, "mono_btls_x509_verify_param_set_depth", mono_btls_x509_verify_param_set_depth) +ICALL(BTLS_X509_VERIFY_PARAM_14, "mono_btls_x509_verify_param_set_flags", mono_btls_x509_verify_param_set_flags) +ICALL(BTLS_X509_VERIFY_PARAM_15, "mono_btls_x509_verify_param_set_host", mono_btls_x509_verify_param_set_host) +ICALL(BTLS_X509_VERIFY_PARAM_16, "mono_btls_x509_verify_param_set_mono_flags", mono_btls_x509_verify_param_set_mono_flags) +ICALL(BTLS_X509_VERIFY_PARAM_17, "mono_btls_x509_verify_param_set_name", mono_btls_x509_verify_param_set_name) +ICALL(BTLS_X509_VERIFY_PARAM_18, "mono_btls_x509_verify_param_set_purpose", mono_btls_x509_verify_param_set_purpose) +ICALL(BTLS_X509_VERIFY_PARAM_19, "mono_btls_x509_verify_param_set_time", mono_btls_x509_verify_param_set_time) +#endif + #ifndef DISABLE_COM ICALL_TYPE(COMPROX, "Mono.Interop.ComInteropProxy", COMPROX_1) ICALL(COMPROX_1, "AddProxy", ves_icall_Mono_Interop_ComInteropProxy_AddProxy) ICALL(COMPROX_2, "FindProxy", ves_icall_Mono_Interop_ComInteropProxy_FindProxy) #endif +ICALL_TYPE(TLS_PROVIDER_FACTORY, "Mono.Net.Security.MonoTlsProviderFactory", TLS_PROVIDER_FACTORY_1) +ICALL(TLS_PROVIDER_FACTORY_1, "IsBtlsSupported", ves_icall_Mono_TlsProviderFactory_IsBtlsSupported) + ICALL_TYPE(RUNTIME, "Mono.Runtime", RUNTIME_1) ICALL(RUNTIME_1, "GetDisplayName", ves_icall_Mono_Runtime_GetDisplayName) ICALL(RUNTIME_12, "GetNativeStackTrace", ves_icall_Mono_Runtime_GetNativeStackTrace) +ICALL_TYPE(RTCLASS, "Mono.RuntimeClassHandle", RTCLASS_1) +ICALL(RTCLASS_1, "GetTypeFromClass", ves_icall_Mono_RuntimeClassHandle_GetTypeFromClass) + +ICALL_TYPE(RTPTRARRAY, "Mono.RuntimeGPtrArrayHandle", RTPTRARRAY_1) +ICALL(RTPTRARRAY_1, "GPtrArrayFree", ves_icall_Mono_RuntimeGPtrArrayHandle_GPtrArrayFree) + +ICALL_TYPE(RTMARSHAL, "Mono.RuntimeMarshal", RTMARSHAL_1) +ICALL(RTMARSHAL_1, "FreeAssemblyName", ves_icall_Mono_RuntimeMarshal_FreeAssemblyName) + +ICALL_TYPE(SAFESTRMARSHAL, "Mono.SafeStringMarshal", SAFESTRMARSHAL_1) +ICALL(SAFESTRMARSHAL_1, "GFree", ves_icall_Mono_SafeStringMarshal_GFree) +ICALL(SAFESTRMARSHAL_2, "StringToUtf8", ves_icall_Mono_SafeStringMarshal_StringToUtf8) + #ifndef PLATFORM_RO_FS ICALL_TYPE(KPAIR, "Mono.Security.Cryptography.KeyPairPersistence", KPAIR_1) ICALL(KPAIR_1, "_CanSecure", ves_icall_Mono_Security_Cryptography_KeyPairPersistence_CanSecure) @@ -132,13 +409,13 @@ ICALL_TYPE (COMPO_W, "System.ComponentModel.Win32Exception", COMPO_W_1) ICALL (COMPO_W_1, "W32ErrorMessage", ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage) ICALL_TYPE(DEFAULTC, "System.Configuration.DefaultConfig", DEFAULTC_1) -ICALL(DEFAULTC_1, "get_bundled_machine_config", get_bundled_machine_config) +HANDLES(ICALL(DEFAULTC_1, "get_bundled_machine_config", get_bundled_machine_config)) ICALL(DEFAULTC_2, "get_machine_config_path", ves_icall_System_Configuration_DefaultConfig_get_machine_config_path) /* Note that the below icall shares the same function as DefaultConfig uses */ ICALL_TYPE(INTCFGHOST, "System.Configuration.InternalConfigurationHost", INTCFGHOST_1) ICALL(INTCFGHOST_1, "get_bundled_app_config", get_bundled_app_config) -ICALL(INTCFGHOST_2, "get_bundled_machine_config", get_bundled_machine_config) +HANDLES(ICALL(INTCFGHOST_2, "get_bundled_machine_config", get_bundled_machine_config)) ICALL_TYPE(CONSOLE, "System.ConsoleDriver", CONSOLE_1) ICALL(CONSOLE_1, "InternalKeyAvailable", ves_icall_System_ConsoleDriver_InternalKeyAvailable ) @@ -241,23 +518,24 @@ ICALL(ENV_13, "get_Platform", ves_icall_System_Environment_get_Platform) ICALL(ENV_14, "get_ProcessorCount", mono_cpu_count) ICALL(ENV_15, "get_TickCount", ves_icall_System_Environment_get_TickCount) ICALL(ENV_16, "get_UserName", ves_icall_System_Environment_get_UserName) +HANDLES(ICALL(ENV_16b, "get_bundled_machine_config", get_bundled_machine_config)) ICALL(ENV_16m, "internalBroadcastSettingChange", ves_icall_System_Environment_BroadcastSettingChange) -ICALL(ENV_17, "internalGetEnvironmentVariable", ves_icall_System_Environment_GetEnvironmentVariable) -ICALL(ENV_18, "internalGetGacPath", ves_icall_System_Environment_GetGacPath) -ICALL(ENV_19, "internalGetHome", ves_icall_System_Environment_InternalGetHome) +HANDLES(ICALL(ENV_17, "internalGetEnvironmentVariable_native", ves_icall_System_Environment_GetEnvironmentVariable_native)) +HANDLES(ICALL(ENV_18, "internalGetGacPath", ves_icall_System_Environment_GetGacPath)) +HANDLES(ICALL(ENV_19, "internalGetHome", ves_icall_System_Environment_InternalGetHome)) ICALL(ENV_20, "set_ExitCode", mono_environment_exitcode_set) ICALL_TYPE(GC, "System.GC", GC_0) -ICALL(GC_0, "CollectionCount", mono_gc_collection_count) +ICALL(GC_0, "GetCollectionCount", mono_gc_collection_count) ICALL(GC_0a, "GetGeneration", mono_gc_get_generation) +ICALL(GC_0b, "GetMaxGeneration", mono_gc_max_generation) ICALL(GC_1, "GetTotalMemory", ves_icall_System_GC_GetTotalMemory) ICALL(GC_2, "InternalCollect", ves_icall_System_GC_InternalCollect) ICALL(GC_3, "KeepAlive", ves_icall_System_GC_KeepAlive) -ICALL(GC_4, "ReRegisterForFinalize", ves_icall_System_GC_ReRegisterForFinalize) ICALL(GC_4a, "RecordPressure", mono_gc_add_memory_pressure) -ICALL(GC_5, "SuppressFinalize", ves_icall_System_GC_SuppressFinalize) ICALL(GC_6, "WaitForPendingFinalizers", ves_icall_System_GC_WaitForPendingFinalizers) -ICALL(GC_7, "get_MaxGeneration", mono_gc_max_generation) +ICALL(GC_6b, "_ReRegisterForFinalize", ves_icall_System_GC_ReRegisterForFinalize) +ICALL(GC_7, "_SuppressFinalize", ves_icall_System_GC_SuppressFinalize) ICALL(GC_9, "get_ephemeron_tombstone", ves_icall_System_GC_get_ephemeron_tombstone) ICALL(GC_8, "register_ephemeron_array", ves_icall_System_GC_register_ephemeron_array) @@ -364,7 +642,7 @@ ICALL(MONOIO_32, "get_PathSeparator", ves_icall_System_IO_MonoIO_get_PathSeparat ICALL(MONOIO_33, "get_VolumeSeparatorChar", ves_icall_System_IO_MonoIO_get_VolumeSeparatorChar) ICALL_TYPE(IOPATH, "System.IO.Path", IOPATH_1) -ICALL(IOPATH_1, "get_temp_path", ves_icall_System_IO_get_temp_path) +HANDLES(ICALL(IOPATH_1, "get_temp_path", ves_icall_System_IO_get_temp_path)) ICALL_TYPE(IOSELECTOR, "System.IOSelector", IOSELECTOR_1) ICALL(IOSELECTOR_1, "Add", ves_icall_System_IOSelector_Add) @@ -454,9 +732,8 @@ ICALL(OBJ_1, "GetType", ves_icall_System_Object_GetType) ICALL(OBJ_2, "InternalGetHashCode", mono_object_hash) ICALL(OBJ_3, "MemberwiseClone", ves_icall_System_Object_MemberwiseClone) -ICALL_TYPE(ASSEM, "System.Reflection.Assembly", ASSEM_1) -ICALL(ASSEM_1, "FillName", ves_icall_System_Reflection_Assembly_FillName) -ICALL(ASSEM_1a, "GetAotId", ves_icall_System_Reflection_Assembly_GetAotId) +ICALL_TYPE(ASSEM, "System.Reflection.Assembly", ASSEM_1a) +HANDLES(ICALL(ASSEM_1a, "GetAotId", ves_icall_System_Reflection_Assembly_GetAotId)) ICALL(ASSEM_2, "GetCallingAssembly", ves_icall_System_Reflection_Assembly_GetCallingAssembly) ICALL(ASSEM_3, "GetEntryAssembly", ves_icall_System_Reflection_Assembly_GetEntryAssembly) ICALL(ASSEM_4, "GetExecutingAssembly", ves_icall_System_Reflection_Assembly_GetExecutingAssembly) @@ -471,7 +748,7 @@ ICALL(ASSEM_12, "GetReferencedAssemblies", ves_icall_System_Reflection_Assembly_ ICALL(ASSEM_13, "GetTypes", ves_icall_System_Reflection_Assembly_GetTypes) ICALL(ASSEM_14, "InternalGetAssemblyName", ves_icall_System_Reflection_Assembly_InternalGetAssemblyName) ICALL(ASSEM_15, "InternalGetType", ves_icall_System_Reflection_Assembly_InternalGetType) -ICALL(ASSEM_16, "InternalImageRuntimeVersion", ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion) +HANDLES(ICALL(ASSEM_16, "InternalImageRuntimeVersion", ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion)) ICALL(ASSEM_17, "LoadFrom", ves_icall_System_Reflection_Assembly_LoadFrom) ICALL(ASSEM_18, "LoadPermissions", ves_icall_System_Reflection_Assembly_LoadPermissions) @@ -481,66 +758,67 @@ ICALL(ASSEM_21, "get_ReflectionOnly", ves_icall_System_Reflection_Assembly_get_R ICALL(ASSEM_22, "get_code_base", ves_icall_System_Reflection_Assembly_get_code_base) ICALL(ASSEM_23, "get_fullname", ves_icall_System_Reflection_Assembly_get_fullName) ICALL(ASSEM_24, "get_global_assembly_cache", ves_icall_System_Reflection_Assembly_get_global_assembly_cache) -ICALL(ASSEM_25, "get_location", ves_icall_System_Reflection_Assembly_get_location) +HANDLES(ICALL(ASSEM_25, "get_location", ves_icall_System_Reflection_Assembly_get_location)) ICALL(ASSEM_26, "load_with_partial_name", ves_icall_System_Reflection_Assembly_load_with_partial_name) -ICALL_TYPE(ASSEMN, "System.Reflection.AssemblyName", ASSEMN_1) -ICALL(ASSEMN_1, "ParseName", ves_icall_System_Reflection_AssemblyName_ParseName) +ICALL_TYPE(ASSEMN, "System.Reflection.AssemblyName", ASSEMN_0) +ICALL(ASSEMN_0, "GetNativeName", ves_icall_System_Reflection_AssemblyName_GetNativeName) +ICALL(ASSEMN_3, "ParseAssemblyName", ves_icall_System_Reflection_AssemblyName_ParseAssemblyName) ICALL(ASSEMN_2, "get_public_token", mono_digest_get_public_token) ICALL_TYPE(CATTR_DATA, "System.Reflection.CustomAttributeData", CATTR_DATA_1) ICALL(CATTR_DATA_1, "ResolveArgumentsInternal", ves_icall_System_Reflection_CustomAttributeData_ResolveArgumentsInternal) -ICALL_TYPE(ASSEMB, "System.Reflection.Emit.AssemblyBuilder", ASSEMB_1) -ICALL(ASSEMB_1, "InternalAddModule", ves_icall_System_Reflection_Emit_AssemblyBuilder_InternalAddModule) -ICALL(ASSEMB_2, "basic_init", mono_image_basic_init) +ICALL_TYPE(ASSEMB, "System.Reflection.Emit.AssemblyBuilder", ASSEMB_2) +ICALL(ASSEMB_2, "basic_init", ves_icall_AssemblyBuilder_basic_init) #ifndef DISABLE_REFLECTION_EMIT ICALL_TYPE(CATTRB, "System.Reflection.Emit.CustomAttributeBuilder", CATTRB_1) -ICALL(CATTRB_1, "GetBlob", ves_icall_System_Reflection_Emit_CustomAttributeBuilder_GetBlob) +ICALL(CATTRB_1, "GetBlob", ves_icall_CustomAttributeBuilder_GetBlob) #endif ICALL_TYPE(DYNM, "System.Reflection.Emit.DynamicMethod", DYNM_1) -ICALL(DYNM_1, "create_dynamic_method", mono_reflection_create_dynamic_method) +ICALL(DYNM_1, "create_dynamic_method", ves_icall_DynamicMethod_create_dynamic_method) ICALL_TYPE(ENUMB, "System.Reflection.Emit.EnumBuilder", ENUMB_1) ICALL(ENUMB_1, "setup_enum_type", ves_icall_EnumBuilder_setup_enum_type) ICALL_TYPE(GPARB, "System.Reflection.Emit.GenericTypeParameterBuilder", GPARB_1) -ICALL(GPARB_1, "initialize", mono_reflection_initialize_generic_parameter) +ICALL(GPARB_1, "initialize", ves_icall_GenericTypeParameterBuilder_initialize_generic_parameter) ICALL_TYPE(METHODB, "System.Reflection.Emit.MethodBuilder", METHODB_1) -ICALL(METHODB_1, "MakeGenericMethod", mono_reflection_bind_generic_method_parameters) +ICALL(METHODB_1, "MakeGenericMethod", ves_icall_MethodBuilder_MakeGenericMethod) ICALL_TYPE(MODULEB, "System.Reflection.Emit.ModuleBuilder", MODULEB_10) ICALL(MODULEB_10, "GetRegisteredToken", ves_icall_ModuleBuilder_GetRegisteredToken) ICALL(MODULEB_8, "RegisterToken", ves_icall_ModuleBuilder_RegisterToken) ICALL(MODULEB_1, "WriteToFile", ves_icall_ModuleBuilder_WriteToFile) -ICALL(MODULEB_2, "basic_init", mono_image_module_basic_init) +ICALL(MODULEB_2, "basic_init", ves_icall_ModuleBuilder_basic_init) ICALL(MODULEB_3, "build_metadata", ves_icall_ModuleBuilder_build_metadata) ICALL(MODULEB_4, "create_modified_type", ves_icall_ModuleBuilder_create_modified_type) ICALL(MODULEB_5, "getMethodToken", ves_icall_ModuleBuilder_getMethodToken) ICALL(MODULEB_6, "getToken", ves_icall_ModuleBuilder_getToken) -ICALL(MODULEB_7, "getUSIndex", mono_image_insert_string) -ICALL(MODULEB_9, "set_wrappers_type", mono_image_set_wrappers_type) +ICALL(MODULEB_7, "getUSIndex", ves_icall_ModuleBuilder_getUSIndex) +ICALL(MODULEB_9, "set_wrappers_type", ves_icall_ModuleBuilder_set_wrappers_type) ICALL_TYPE(SIGH, "System.Reflection.Emit.SignatureHelper", SIGH_1) -ICALL(SIGH_1, "get_signature_field", mono_reflection_sighelper_get_signature_field) -ICALL(SIGH_2, "get_signature_local", mono_reflection_sighelper_get_signature_local) +ICALL(SIGH_1, "get_signature_field", ves_icall_SignatureHelper_get_signature_field) +ICALL(SIGH_2, "get_signature_local", ves_icall_SignatureHelper_get_signature_local) #ifndef DISABLE_REFLECTION_EMIT ICALL_TYPE(SYMBOLTYPE, "System.Reflection.Emit.SymbolType", SYMBOLTYPE_1) -ICALL(SYMBOLTYPE_1, "create_unmanaged_type", mono_reflection_create_unmanaged_type) +ICALL(SYMBOLTYPE_1, "create_unmanaged_type", ves_icall_SymbolType_create_unmanaged_type) #endif ICALL_TYPE(TYPEB, "System.Reflection.Emit.TypeBuilder", TYPEB_1) -ICALL(TYPEB_1, "create_generic_class", ves_icall_System_Reflection_Emit_TypeBuilder_create_generic_class) -ICALL(TYPEB_2, "create_internal_class", mono_reflection_create_internal_class) -ICALL(TYPEB_3, "create_runtime_class", mono_reflection_create_runtime_class) +ICALL(TYPEB_1, "create_generic_class", ves_icall_TypeBuilder_create_generic_class) +ICALL(TYPEB_3, "create_runtime_class", ves_icall_TypeBuilder_create_runtime_class) ICALL(TYPEB_4, "get_IsGenericParameter", ves_icall_TypeBuilder_get_IsGenericParameter) -ICALL(TYPEB_5, "get_event_info", mono_reflection_event_builder_get_event_info) -ICALL(TYPEB_6, "setup_generic_class", mono_reflection_setup_generic_class) -ICALL(TYPEB_7, "setup_internal_class", mono_reflection_setup_internal_class) +ICALL(TYPEB_5, "get_event_info", ves_icall_TypeBuilder_get_event_info) +ICALL(TYPEB_7, "setup_internal_class", ves_icall_TypeBuilder_setup_internal_class) + +ICALL_TYPE(EVENTI, "System.Reflection.EventInfo", EVENTI_1) +ICALL(EVENTI_1, "internal_from_handle_type", ves_icall_System_Reflection_EventInfo_internal_from_handle_type) ICALL_TYPE(FIELDI, "System.Reflection.FieldInfo", FILEDI_1) ICALL(FILEDI_1, "GetTypeModifiers", ves_icall_System_Reflection_FieldInfo_GetTypeModifiers) @@ -553,12 +831,12 @@ ICALL(MEMBERI_1, "get_MetadataToken", ves_icall_reflection_get_token) ICALL_TYPE(MBASE, "System.Reflection.MethodBase", MBASE_1) ICALL(MBASE_1, "GetCurrentMethod", ves_icall_GetCurrentMethod) ICALL(MBASE_2, "GetMethodBodyInternal", ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal) -ICALL(MBASE_4, "GetMethodFromHandleInternalType", ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType) +ICALL(MBASE_4, "GetMethodFromHandleInternalType_native", ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType_native) ICALL_TYPE(MODULE, "System.Reflection.Module", MODULE_1) ICALL(MODULE_1, "Close", ves_icall_System_Reflection_Module_Close) ICALL(MODULE_2, "GetGlobalType", ves_icall_System_Reflection_Module_GetGlobalType) -ICALL(MODULE_3, "GetGuidInternal", ves_icall_System_Reflection_Module_GetGuidInternal) +HANDLES(ICALL(MODULE_3, "GetGuidInternal", ves_icall_System_Reflection_Module_GetGuidInternal)) ICALL(MODULE_14, "GetHINSTANCE", ves_icall_System_Reflection_Module_GetHINSTANCE) ICALL(MODULE_4, "GetMDStreamVersion", ves_icall_System_Reflection_Module_GetMDStreamVersion) ICALL(MODULE_5, "GetPEKind", ves_icall_System_Reflection_Module_GetPEKind) @@ -597,7 +875,7 @@ ICALL(MMETH_2, "GetGenericArguments", ves_icall_MonoMethod_GetGenericArguments) ICALL(MMETH_3, "GetGenericMethodDefinition_impl", ves_icall_MonoMethod_GetGenericMethodDefinition) ICALL(MMETH_11, "GetPInvoke", ves_icall_MonoMethod_GetPInvoke) ICALL(MMETH_4, "InternalInvoke", ves_icall_InternalInvoke) -ICALL(MMETH_5, "MakeGenericMethod_impl", mono_reflection_bind_generic_method_parameters) +ICALL(MMETH_5, "MakeGenericMethod_impl", ves_icall_MonoMethod_MakeGenericMethod_impl) ICALL(MMETH_6, "get_IsGenericMethod", ves_icall_MonoMethod_get_IsGenericMethod) ICALL(MMETH_7, "get_IsGenericMethodDefinition", ves_icall_MonoMethod_get_IsGenericMethodDefinition) ICALL(MMETH_8, "get_base_method", ves_icall_MonoMethod_get_base_method) @@ -619,6 +897,9 @@ ICALL_TYPE(PARAMI, "System.Reflection.ParameterInfo", PARAMI_1) ICALL(PARAMI_1, "GetMetadataToken", ves_icall_reflection_get_token) ICALL(PARAMI_2, "GetTypeModifiers", ves_icall_ParameterInfo_GetTypeModifiers) +ICALL_TYPE(PROPI, "System.Reflection.PropertyInfo", PROPI_1) +ICALL(PROPI_1, "internal_from_handle_type", ves_icall_System_Reflection_PropertyInfo_internal_from_handle_type) + ICALL_TYPE(RTFIELD, "System.Reflection.RtFieldInfo", RTFIELD_1) ICALL(RTFIELD_1, "UnsafeGetValue", ves_icall_MonoField_GetValueInternal) @@ -647,6 +928,7 @@ ICALL_TYPE(MARSHAL, "System.Runtime.InteropServices.Marshal", MARSHAL_2) #endif ICALL(MARSHAL_2, "AllocCoTaskMem", ves_icall_System_Runtime_InteropServices_Marshal_AllocCoTaskMem) ICALL(MARSHAL_3, "AllocHGlobal", ves_icall_System_Runtime_InteropServices_Marshal_AllocHGlobal) +ICALL(MARSHAL_50, "BufferToBSTR", ves_icall_System_Runtime_InteropServices_Marshal_BufferToBSTR) ICALL(MARSHAL_4, "DestroyStructure", ves_icall_System_Runtime_InteropServices_Marshal_DestroyStructure) ICALL(MARSHAL_5, "FreeBSTR", ves_icall_System_Runtime_InteropServices_Marshal_FreeBSTR) ICALL(MARSHAL_6, "FreeCoTaskMem", ves_icall_System_Runtime_InteropServices_Marshal_FreeCoTaskMem) @@ -693,6 +975,7 @@ ICALL(MARSHAL_32, "StringToHGlobalAnsi", ves_icall_System_Runtime_InteropService ICALL(MARSHAL_33, "StringToHGlobalUni", ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalUni) ICALL(MARSHAL_34, "StructureToPtr", ves_icall_System_Runtime_InteropServices_Marshal_StructureToPtr) ICALL(MARSHAL_35, "UnsafeAddrOfPinnedArrayElement", ves_icall_System_Runtime_InteropServices_Marshal_UnsafeAddrOfPinnedArrayElement) + ICALL(MARSHAL_41, "copy_from_unmanaged", ves_icall_System_Runtime_InteropServices_Marshal_copy_from_unmanaged) ICALL(MARSHAL_42, "copy_to_unmanaged", ves_icall_System_Runtime_InteropServices_Marshal_copy_to_unmanaged) @@ -707,9 +990,6 @@ ICALL(CONTEXT_2, "ReleaseContext", ves_icall_System_Runtime_Remoting_Contexts_Co ICALL_TYPE(ARES, "System.Runtime.Remoting.Messaging.AsyncResult", ARES_1) ICALL(ARES_1, "Invoke", ves_icall_System_Runtime_Remoting_Messaging_AsyncResult_Invoke) -ICALL_TYPE(MONOMM, "System.Runtime.Remoting.Messaging.MonoMethodMessage", MONOMM_1) -ICALL(MONOMM_1, "InitMessage", ves_icall_MonoMethodMessage_InitMessage) - #ifndef DISABLE_REMOTING ICALL_TYPE(REALP, "System.Runtime.Remoting.Proxies.RealProxy", REALP_1) ICALL(REALP_1, "InternalGetProxyType", ves_icall_Remoting_RealProxy_InternalGetProxyType) @@ -733,31 +1013,29 @@ ICALL(MHAN_1, "GetFunctionPointer", ves_icall_RuntimeMethodHandle_GetFunctionPoi ICALL_TYPE(RT, "System.RuntimeType", RT_1) ICALL(RT_1, "CreateInstanceInternal", ves_icall_System_Activator_CreateInstanceInternal) -ICALL(RT_2, "GetConstructors_internal", ves_icall_RuntimeType_GetConstructors_internal) +ICALL(RT_2, "GetConstructors_native", ves_icall_RuntimeType_GetConstructors_native) ICALL(RT_30, "GetCorrespondingInflatedConstructor", ves_icall_RuntimeType_GetCorrespondingInflatedMethod) ICALL(RT_31, "GetCorrespondingInflatedMethod", ves_icall_RuntimeType_GetCorrespondingInflatedMethod) -ICALL(RT_3, "GetEvents_internal", ves_icall_RuntimeType_GetEvents_internal) -ICALL(RT_5, "GetFields_internal", ves_icall_RuntimeType_GetFields_internal) +ICALL(RT_3, "GetEvents_native", ves_icall_RuntimeType_GetEvents_native) +ICALL(RT_5, "GetFields_native", ves_icall_RuntimeType_GetFields_native) ICALL(RT_6, "GetGenericArgumentsInternal", ves_icall_RuntimeType_GetGenericArguments) -ICALL(RT_7, "GetGenericParameterAttributes", ves_icall_RuntimeType_GetGenericParameterAttributes) -ICALL(RT_8, "GetGenericParameterConstraints_impl", ves_icall_RuntimeType_GetGenericParameterConstraints) ICALL(RT_9, "GetGenericParameterPosition", ves_icall_RuntimeType_GetGenericParameterPosition) ICALL(RT_10, "GetInterfaceMapData", ves_icall_RuntimeType_GetInterfaceMapData) ICALL(RT_11, "GetInterfaces", ves_icall_RuntimeType_GetInterfaces) -ICALL(RT_12, "GetMethodsByName", ves_icall_RuntimeType_GetMethodsByName) -ICALL(RT_13, "GetNestedTypes_internal", ves_icall_RuntimeType_GetNestedTypes) +ICALL(RT_12, "GetMethodsByName_native", ves_icall_RuntimeType_GetMethodsByName_native) +ICALL(RT_13, "GetNestedTypes_native", ves_icall_RuntimeType_GetNestedTypes_native) ICALL(RT_14, "GetPacking", ves_icall_RuntimeType_GetPacking) -ICALL(RT_15, "GetPropertiesByName", ves_icall_RuntimeType_GetPropertiesByName) +ICALL(RT_15, "GetPropertiesByName_native", ves_icall_RuntimeType_GetPropertiesByName_native) ICALL(RT_16, "GetTypeCodeImplInternal", ves_icall_type_GetTypeCodeInternal) ICALL(RT_28, "IsTypeExportedToWindowsRuntime", ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime) ICALL(RT_29, "IsWindowsRuntimeObjectType", ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType) ICALL(RT_17, "MakeGenericType", ves_icall_RuntimeType_MakeGenericType) ICALL(RT_18, "MakePointerType", ves_icall_RuntimeType_MakePointerType) -ICALL(RT_19, "getFullName", ves_icall_System_MonoType_getFullName) +HANDLES(ICALL(RT_19, "getFullName", ves_icall_System_RuntimeType_getFullName)) ICALL(RT_21, "get_DeclaringMethod", ves_icall_RuntimeType_get_DeclaringMethod) ICALL(RT_22, "get_DeclaringType", ves_icall_RuntimeType_get_DeclaringType) -ICALL(RT_23, "get_Name", ves_icall_RuntimeType_get_Name) -ICALL(RT_24, "get_Namespace", ves_icall_RuntimeType_get_Namespace) +HANDLES(ICALL(RT_23, "get_Name", ves_icall_RuntimeType_get_Name)) +HANDLES(ICALL(RT_24, "get_Namespace", ves_icall_RuntimeType_get_Namespace)) ICALL(RT_25, "get_core_clr_security_level", vell_icall_RuntimeType_get_core_clr_security_level) ICALL(RT_26, "make_array_type", ves_icall_RuntimeType_make_array_type) ICALL(RT_27, "make_byref_type", ves_icall_RuntimeType_make_byref_type) @@ -768,6 +1046,7 @@ ICALL(RTH_2, "GetAssembly", ves_icall_RuntimeTypeHandle_GetAssembly) ICALL(RTH_3, "GetAttributes", ves_icall_RuntimeTypeHandle_GetAttributes) ICALL(RTH_4, "GetBaseType", ves_icall_RuntimeTypeHandle_GetBaseType) ICALL(RTH_5, "GetElementType", ves_icall_RuntimeTypeHandle_GetElementType) +ICALL(RTH_19, "GetGenericParameterInfo", ves_icall_RuntimeTypeHandle_GetGenericParameterInfo) ICALL(RTH_6, "GetGenericTypeDefinition_impl", ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl) ICALL(RTH_7, "GetMetadataToken", ves_icall_reflection_get_token) ICALL(RTH_8, "GetModule", ves_icall_RuntimeTypeHandle_GetModule) @@ -881,15 +1160,15 @@ ICALL(MUTEX_3, "ReleaseMutex_internal(intptr)", ves_icall_System_Threading_Mutex ICALL_TYPE(NATIVEC, "System.Threading.NativeEventCalls", NATIVEC_1) ICALL(NATIVEC_1, "CloseEvent_internal", ves_icall_System_Threading_Events_CloseEvent_internal) -ICALL(NATIVEC_2, "CreateEvent_internal(bool,bool,string,bool&)", ves_icall_System_Threading_Events_CreateEvent_internal) -ICALL(NATIVEC_3, "OpenEvent_internal(string,System.Security.AccessControl.EventWaitHandleRights,System.IO.MonoIOError&)", ves_icall_System_Threading_Events_OpenEvent_internal) +ICALL(NATIVEC_2, "CreateEvent_internal(bool,bool,string,int&)", ves_icall_System_Threading_Events_CreateEvent_internal) +ICALL(NATIVEC_3, "OpenEvent_internal(string,System.Security.AccessControl.EventWaitHandleRights,int&)", ves_icall_System_Threading_Events_OpenEvent_internal) ICALL(NATIVEC_4, "ResetEvent_internal", ves_icall_System_Threading_Events_ResetEvent_internal) ICALL(NATIVEC_5, "SetEvent_internal", ves_icall_System_Threading_Events_SetEvent_internal) ICALL_TYPE(SEMA, "System.Threading.Semaphore", SEMA_1) -ICALL(SEMA_1, "CreateSemaphore_internal(int,int,string,bool&)", ves_icall_System_Threading_Semaphore_CreateSemaphore_internal) -ICALL(SEMA_2, "OpenSemaphore_internal(string,System.Security.AccessControl.SemaphoreRights,System.IO.MonoIOError&)", ves_icall_System_Threading_Semaphore_OpenSemaphore_internal) -ICALL(SEMA_3, "ReleaseSemaphore_internal(intptr,int,bool&)", ves_icall_System_Threading_Semaphore_ReleaseSemaphore_internal) +ICALL(SEMA_1, "CreateSemaphore_internal(int,int,string,int&)", ves_icall_System_Threading_Semaphore_CreateSemaphore_internal) +ICALL(SEMA_2, "OpenSemaphore_internal(string,System.Security.AccessControl.SemaphoreRights,int&)", ves_icall_System_Threading_Semaphore_OpenSemaphore_internal) +ICALL(SEMA_3, "ReleaseSemaphore_internal(intptr,int,int&)", ves_icall_System_Threading_Semaphore_ReleaseSemaphore_internal) ICALL_TYPE(THREAD, "System.Threading.Thread", THREAD_1) ICALL(THREAD_1, "Abort_internal(System.Threading.InternalThread,object)", ves_icall_System_Threading_Thread_Abort) diff --git a/mono/metadata/icall.c.REMOVED.git-id b/mono/metadata/icall.c.REMOVED.git-id index de43ff9e2a..27f45a1d26 100644 --- a/mono/metadata/icall.c.REMOVED.git-id +++ b/mono/metadata/icall.c.REMOVED.git-id @@ -1 +1 @@ -5b650df80f8220cc82e4d7da358c5fad1ec45a62 \ No newline at end of file +deecd47028339a9eccb62c62fcbb37e6f7ab5357 \ No newline at end of file diff --git a/mono/metadata/image.c b/mono/metadata/image.c index 7b1b427831..50eaded2e3 100644 --- a/mono/metadata/image.c +++ b/mono/metadata/image.c @@ -1300,6 +1300,7 @@ mono_image_open_from_data_internal (char *data, guint32 data_len, gboolean need_ image->image_info = iinfo; image->ref_only = refonly; image->metadata_only = metadata_only; + image->ref_count = 1; image = do_mono_image_load (image, status, TRUE, TRUE); if (image == NULL) @@ -1801,6 +1802,7 @@ mono_image_close_except_pools (MonoImage *image) free_hash (image->stfld_wrapper_cache); free_hash (image->isinst_cache); free_hash (image->castclass_cache); + free_hash (image->icall_wrapper_cache); free_hash (image->proxy_isinst_cache); free_hash (image->var_cache_slow); free_hash (image->mvar_cache_slow); @@ -1991,13 +1993,13 @@ mono_image_walk_resource_tree (MonoCLIImageInfo *info, guint32 res_id, } #endif } else if (level==2) { - if (is_string == TRUE || (is_string == FALSE && lang_id != 0 && name_offset != lang_id)) + if (is_string || (lang_id != 0 && name_offset != lang_id)) return NULL; } else { g_assert_not_reached (); } - if(is_dir==TRUE) { + if (is_dir) { MonoPEResourceDir *res_dir=(MonoPEResourceDir *)(((char *)root)+dir_offset); MonoPEResourceDirEntry *sub_entries=(MonoPEResourceDirEntry *)(res_dir+1); guint32 entries, i; diff --git a/mono/metadata/loader.c b/mono/metadata/loader.c index 2922234965..70e371aa66 100644 --- a/mono/metadata/loader.c +++ b/mono/metadata/loader.c @@ -994,6 +994,7 @@ mono_dllmap_lookup_list (MonoDllMap *dll_map, const char *dll, const char* func, */ } if (dll_map->func && strcmp (dll_map->func, func) == 0) { + *rdll = dll_map->target; *rfunc = dll_map->target_func; break; } @@ -1021,7 +1022,7 @@ mono_dllmap_lookup (MonoImage *assembly, const char *dll, const char* func, cons * @dll: The name of the external library, as it would be found in the DllImport declaration. If prefixed with 'i:' the matching of the library name is done without case sensitivity * @func: if not null, the mapping will only applied to the named function (the value of EntryPoint) * @tdll: The name of the library to map the specified @dll if it matches. - * @tfunc: if func is not NULL, the name of the function that replaces the invocation + * @tfunc: The name of the function that replaces the invocation. If NULL, it is replaced with a copy of @func. * * LOCKING: Acquires the loader lock. * @@ -1056,7 +1057,7 @@ mono_dllmap_insert (MonoImage *assembly, const char *dll, const char *func, cons entry->dll = dll? g_strdup (dll): NULL; entry->target = tdll? g_strdup (tdll): NULL; entry->func = func? g_strdup (func): NULL; - entry->target_func = tfunc? g_strdup (tfunc): NULL; + entry->target_func = tfunc? g_strdup (tfunc): (func? g_strdup (func): NULL); global_loader_data_lock (); entry->next = global_dll_map; @@ -1067,7 +1068,7 @@ mono_dllmap_insert (MonoImage *assembly, const char *dll, const char *func, cons entry->dll = dll? mono_image_strdup (assembly, dll): NULL; entry->target = tdll? mono_image_strdup (assembly, tdll): NULL; entry->func = func? mono_image_strdup (assembly, func): NULL; - entry->target_func = tfunc? mono_image_strdup (assembly, tfunc): NULL; + entry->target_func = tfunc? mono_image_strdup (assembly, tfunc): (func? mono_image_strdup (assembly, func): NULL); mono_image_lock (assembly); entry->next = assembly->dll_map; @@ -1122,6 +1123,14 @@ cached_module_load (const char *name, int flags, char **err) return res; } +void +mono_loader_register_module (const char *name, MonoDl *module) +{ + if (!global_module_map) + global_module_map = g_hash_table_new (g_str_hash, g_str_equal); + g_hash_table_insert (global_module_map, g_strdup (name), module); +} + static MonoDl *internal_module; static gboolean @@ -2223,7 +2232,7 @@ mono_stack_walk_async_safe (MonoStackWalkAsyncSafe func, void *initial_sig_conte AsyncStackWalkUserData ud = { func, user_data }; mono_sigctx_to_monoctx (initial_sig_context, &ctx); - mono_get_eh_callbacks ()->mono_walk_stack_with_ctx (async_stack_walk_adapter, NULL, MONO_UNWIND_SIGNAL_SAFE, &ud); + mono_get_eh_callbacks ()->mono_walk_stack_with_ctx (async_stack_walk_adapter, &ctx, MONO_UNWIND_SIGNAL_SAFE, &ud); } static gboolean diff --git a/mono/metadata/loader.h b/mono/metadata/loader.h index 774c9b8a47..6382c774ae 100644 --- a/mono/metadata/loader.h +++ b/mono/metadata/loader.h @@ -4,6 +4,7 @@ #include #include #include +#include MONO_BEGIN_DECLS @@ -60,6 +61,12 @@ mono_add_internal_call (const char *name, const void* method); MONO_API void* mono_lookup_internal_call (MonoMethod *method); +void* +mono_lookup_internal_call_full (MonoMethod *method, mono_bool *uses_handles); + +void +mono_loader_register_module (const char *name, MonoDl *module); + MONO_API const char* mono_lookup_icall_symbol (MonoMethod *m); diff --git a/mono/metadata/locales.c b/mono/metadata/locales.c index bcb0dc3c01..783b528339 100644 --- a/mono/metadata/locales.c +++ b/mono/metadata/locales.c @@ -434,7 +434,7 @@ get_darwin_locale (void) len += bytes_converted + 1; } - darwin_locale = (char *) malloc (len + 1); + darwin_locale = (char *) g_malloc (len + 1); CFStringGetBytes (locale_language, CFRangeMake (0, CFStringGetLength (locale_language)), kCFStringEncodingMacRoman, 0, FALSE, (UInt8 *) darwin_locale, len, &bytes_converted); darwin_locale[bytes_converted] = '-'; @@ -454,9 +454,9 @@ get_darwin_locale (void) if (locale_cfstr) { len = CFStringGetMaximumSizeForEncoding (CFStringGetLength (locale_cfstr), kCFStringEncodingMacRoman) + 1; - darwin_locale = (char *) malloc (len); + darwin_locale = (char *) g_malloc (len); if (!CFStringGetCString (locale_cfstr, darwin_locale, len, kCFStringEncodingMacRoman)) { - free (darwin_locale); + g_free (darwin_locale); CFRelease (locale); darwin_locale = NULL; return NULL; diff --git a/mono/metadata/lock-tracer.c b/mono/metadata/lock-tracer.c index f0d2bca6ed..66f7d6b560 100644 --- a/mono/metadata/lock-tracer.c +++ b/mono/metadata/lock-tracer.c @@ -24,7 +24,6 @@ #include "lock-tracer.h" - /* * This is a very simple lock trace implementation. It can be used to verify that the runtime is * correctly following all locking rules. @@ -141,5 +140,9 @@ mono_locks_lock_released (RuntimeLocks kind, gpointer lock) { add_record (RECORD_LOCK_RELEASED, kind, lock); } - -#endif +#else + #ifdef _MSC_VER + // Quiet Visual Studio linker warning, LNK4221, in cases when this source file intentional ends up empty. + void __mono_win32_lock_tracer_quiet_lnk4221(void) {} + #endif +#endif /* LOCK_TRACER */ diff --git a/mono/metadata/marshal.c.REMOVED.git-id b/mono/metadata/marshal.c.REMOVED.git-id index b165715c97..56bb4012f1 100644 --- a/mono/metadata/marshal.c.REMOVED.git-id +++ b/mono/metadata/marshal.c.REMOVED.git-id @@ -1 +1 @@ -86e66ece626ce9a7560ea03a47cf58d44222bf69 \ No newline at end of file +9957328e2c001b4e47ce410362f38f810f481a26 \ No newline at end of file diff --git a/mono/metadata/marshal.h b/mono/metadata/marshal.h index d3c0a2b051..166db1478c 100644 --- a/mono/metadata/marshal.h +++ b/mono/metadata/marshal.h @@ -191,6 +191,10 @@ typedef struct { MonoMethodSignature *sig; } GsharedvtWrapperInfo; +typedef struct { + MonoMethod *method; +} DelegateInvokeWrapperInfo; + /* * This structure contains additional information to uniquely identify a given wrapper * method. It can be retrieved by mono_marshal_get_wrapper_info () for certain types @@ -231,6 +235,8 @@ typedef struct { RemotingWrapperInfo remoting; /* GSHAREDVT_IN_SIG/GSHAREDVT_OUT_SIG */ GsharedvtWrapperInfo gsharedvt; + /* DELEGATE_INVOKE */ + DelegateInvokeWrapperInfo delegate_invoke; } d; } WrapperInfo; @@ -269,7 +275,10 @@ gpointer mono_string_to_ansibstr (MonoString *string_obj); gpointer -mono_string_to_bstr (MonoString *string_obj); +mono_ptr_to_bstr (gpointer ptr, int slen); + +gpointer +mono_string_to_bstr(MonoString* str); void mono_delegate_free_ftnptr (MonoDelegate *delegate); @@ -466,6 +475,9 @@ ves_icall_System_Runtime_InteropServices_Marshal_OffsetOf (MonoReflectionType *t gpointer ves_icall_System_Runtime_InteropServices_Marshal_StringToBSTR (MonoString *string); +gpointer +ves_icall_System_Runtime_InteropServices_Marshal_BufferToBSTR (MonoArray *ptr, int len); + gpointer ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalAnsi (MonoString *string); diff --git a/mono/metadata/mempool.c b/mono/metadata/mempool.c index 60d36ae2ad..9a3254b058 100644 --- a/mono/metadata/mempool.c +++ b/mono/metadata/mempool.c @@ -172,7 +172,7 @@ mono_mempool_stats (MonoMemPool *pool) { MonoMemPool *p; int count = 0; - guint32 still_free = pool->end - pool->pos; + guint32 still_free; p = pool; while (p) { @@ -180,6 +180,7 @@ mono_mempool_stats (MonoMemPool *pool) count++; } if (pool) { + still_free = pool->end - pool->pos; g_print ("Mempool %p stats:\n", pool); g_print ("Total mem allocated: %d\n", pool->d.allocated); g_print ("Num chunks: %d\n", count); @@ -197,25 +198,27 @@ static mono_mutex_t mempool_tracing_lock; static void mono_backtrace (int size) { - void *array[BACKTRACE_DEPTH]; - char **names; - int i, symbols; - static gboolean inited; + void *array[BACKTRACE_DEPTH]; + char **names; + int i, symbols; + static gboolean inited; - if (!inited) { - mono_os_mutex_init_recursive (&mempool_tracing_lock); - inited = TRUE; - } + if (!inited) { + mono_os_mutex_init_recursive (&mempool_tracing_lock); + inited = TRUE; + } - mono_os_mutex_lock (&mempool_tracing_lock); - g_print ("Allocating %d bytes\n", size); - symbols = backtrace (array, BACKTRACE_DEPTH); - names = backtrace_symbols (array, symbols); - for (i = 1; i < symbols; ++i) { - g_print ("\t%s\n", names [i]); - } - free (names); - mono_os_mutex_unlock (&mempool_tracing_lock); + mono_os_mutex_lock (&mempool_tracing_lock); + g_print ("Allocating %d bytes\n", size); + MONO_ENTER_GC_SAFE; + symbols = backtrace (array, BACKTRACE_DEPTH); + names = backtrace_symbols (array, symbols); + MONO_EXIT_GC_SAFE; + for (i = 1; i < symbols; ++i) { + g_print ("\t%s\n", names [i]); + } + g_free (names); + mono_os_mutex_unlock (&mempool_tracing_lock); } #endif diff --git a/mono/metadata/metadata-cross-helpers.c b/mono/metadata/metadata-cross-helpers.c index 90a4d332bd..561e996883 100644 --- a/mono/metadata/metadata-cross-helpers.c +++ b/mono/metadata/metadata-cross-helpers.c @@ -6,6 +6,7 @@ #include #include #include +#include #ifdef HAVE_SGEN_GC #include #endif diff --git a/mono/metadata/metadata-internals.h b/mono/metadata/metadata-internals.h index d80475c03e..a1b9eb8417 100644 --- a/mono/metadata/metadata-internals.h +++ b/mono/metadata/metadata-internals.h @@ -336,6 +336,8 @@ struct _MonoImage { GHashTable *ldflda_wrapper_cache; GHashTable *stfld_wrapper_cache; GHashTable *isinst_cache; + + GHashTable *icall_wrapper_cache; GHashTable *castclass_cache; GHashTable *proxy_isinst_cache; GHashTable *rgctx_template_hash; /* LOCKING: templates lock */ diff --git a/mono/metadata/metadata-verify.c.REMOVED.git-id b/mono/metadata/metadata-verify.c.REMOVED.git-id index 42684f2df6..99826e80a5 100644 --- a/mono/metadata/metadata-verify.c.REMOVED.git-id +++ b/mono/metadata/metadata-verify.c.REMOVED.git-id @@ -1 +1 @@ -2c5612c2a1d6a4f30c2da778f08d6998505904ff \ No newline at end of file +c3beaa4553795cf7d9285b3b0f68c5d3c88abf7e \ No newline at end of file diff --git a/mono/metadata/metadata.c.REMOVED.git-id b/mono/metadata/metadata.c.REMOVED.git-id index f106a46f87..a248df3cd0 100644 --- a/mono/metadata/metadata.c.REMOVED.git-id +++ b/mono/metadata/metadata.c.REMOVED.git-id @@ -1 +1 @@ -2df6db21ec67febd81d791c9663007b2d3660c01 \ No newline at end of file +27115ccc9c1b1e384c9245ff8e976882159a9ed1 \ No newline at end of file diff --git a/mono/metadata/metadata.h b/mono/metadata/metadata.h index 37c91f1ae8..046491943d 100644 --- a/mono/metadata/metadata.h +++ b/mono/metadata/metadata.h @@ -284,7 +284,6 @@ typedef struct { typedef struct _MonoType MonoType; typedef struct _MonoGenericInst MonoGenericInst; typedef struct _MonoGenericClass MonoGenericClass; -typedef struct _MonoDynamicGenericClass MonoDynamicGenericClass; typedef struct _MonoGenericContext MonoGenericContext; typedef struct _MonoGenericContainer MonoGenericContainer; typedef struct _MonoGenericParam MonoGenericParam; @@ -301,7 +300,10 @@ typedef struct { struct _MonoArrayType { MonoClass *eklass; + // Number of dimensions of the array uint8_t rank; + + // Arrays recording known upper and lower index bounds for each dimension uint8_t numsizes; uint8_t numlobounds; int *sizes; @@ -347,6 +349,7 @@ MONO_API mono_bool mono_type_is_struct (MonoType *type); MONO_API mono_bool mono_type_is_void (MonoType *type); MONO_API mono_bool mono_type_is_pointer (MonoType *type); MONO_API mono_bool mono_type_is_reference (MonoType *type); +mono_bool mono_type_is_generic_parameter (MonoType *type); MONO_API MonoType* mono_signature_get_return_type (MonoMethodSignature *sig); diff --git a/mono/metadata/monitor.c b/mono/metadata/monitor.c index b9a3051216..ef01f3d530 100644 --- a/mono/metadata/monitor.c +++ b/mono/metadata/monitor.c @@ -357,7 +357,8 @@ mon_finalize (MonoThreadsSync *mon) LOCK_DEBUG (g_message ("%s: Finalizing sync %p", __func__, mon)); if (mon->entry_sem != NULL) { - CloseHandle (mon->entry_sem); + mono_coop_sem_destroy (mon->entry_sem); + g_free (mon->entry_sem); mon->entry_sem = NULL; } /* If this isn't empty then something is seriously broken - it @@ -679,7 +680,7 @@ mono_monitor_exit_inflated (MonoObject *obj) tmp_status = InterlockedCompareExchange ((gint32*)&mon->status, new_status, old_status); if (tmp_status == old_status) { if (have_waiters) - ReleaseSemaphore (mon->entry_sem, 1, NULL); + mono_coop_sem_post (mon->entry_sem); break; } old_status = tmp_status; @@ -745,8 +746,8 @@ mono_monitor_try_enter_inflated (MonoObject *obj, guint32 ms, gboolean allow_int HANDLE sem; gint64 then = 0, now, delta; guint32 waitms; - guint32 ret; guint32 new_status, old_status, tmp_status; + MonoSemTimedwaitRet wait_ret; MonoInternalThread *thread; gboolean interrupted = FALSE; @@ -838,11 +839,12 @@ retry_contended: */ if (mon->entry_sem == NULL) { /* Create the semaphore */ - sem = CreateSemaphore (NULL, 0, 0x7fffffff, NULL); - g_assert (sem != NULL); + sem = g_new0 (MonoCoopSem, 1); + mono_coop_sem_init (sem, 0); if (InterlockedCompareExchangePointer ((gpointer*)&mon->entry_sem, sem, NULL) != NULL) { /* Someone else just put a handle here */ - CloseHandle (sem); + mono_coop_sem_destroy (sem); + g_free (sem); } } @@ -878,12 +880,10 @@ retry_contended: mono_thread_set_state (thread, ThreadState_WaitSleepJoin); /* - * We pass TRUE instead of allow_interruption since we have to check for the + * We pass ALERTABLE instead of allow_interruption since we have to check for the * StopRequested case below. */ - MONO_ENTER_GC_SAFE; - ret = WaitForSingleObjectEx (mon->entry_sem, waitms, TRUE); - MONO_EXIT_GC_SAFE; + wait_ret = mono_coop_sem_timedwait (mon->entry_sem, waitms, MONO_SEM_FLAGS_ALERTABLE); mono_thread_clr_state (thread, ThreadState_WaitSleepJoin); @@ -891,7 +891,7 @@ retry_contended: mono_perfcounters->thread_queue_len--; #endif - if (ret == WAIT_IO_COMPLETION && !allow_interruption) { + if (wait_ret == MONO_SEM_TIMEDWAIT_RET_ALERTED && !allow_interruption) { interrupted = TRUE; /* * We have to obey a stop/suspend request even if @@ -914,11 +914,11 @@ retry_contended: /* retry from the top */ goto retry_contended; } - } else if (ret == WAIT_OBJECT_0) { + } else if (wait_ret == MONO_SEM_TIMEDWAIT_RET_SUCCESS) { interrupted = FALSE; /* retry from the top */ goto retry_contended; - } else if (ret == WAIT_TIMEOUT) { + } else if (wait_ret == MONO_SEM_TIMEDWAIT_RET_TIMEDOUT) { /* we're done */ } @@ -927,10 +927,10 @@ retry_contended: mono_profiler_monitor_event (obj, MONO_PROFILER_MONITOR_FAIL); - if (ret == WAIT_IO_COMPLETION) { + if (wait_ret == MONO_SEM_TIMEDWAIT_RET_ALERTED) { LOCK_DEBUG (g_message ("%s: (%d) interrupted waiting, returning -1", __func__, id)); return -1; - } else if (ret == WAIT_TIMEOUT) { + } else if (wait_ret == MONO_SEM_TIMEDWAIT_RET_TIMEDOUT) { LOCK_DEBUG (g_message ("%s: (%d) timed out waiting, returning FALSE", __func__, id)); return 0; } else { @@ -951,11 +951,6 @@ mono_monitor_try_enter_internal (MonoObject *obj, guint32 ms, gboolean allow_int LOCK_DEBUG (g_message("%s: (%d) Trying to lock object %p (%d ms)", __func__, id, obj, ms)); - if (G_UNLIKELY (!obj)) { - mono_set_pending_exception (mono_get_exception_argument_null ("obj")); - return FALSE; - } - lw.sync = obj->synchronisation; if (G_LIKELY (lock_word_is_free (lw))) { @@ -1001,18 +996,31 @@ mono_monitor_try_enter_internal (MonoObject *obj, guint32 ms, gboolean allow_int gboolean mono_monitor_enter (MonoObject *obj) { + if (G_UNLIKELY (!obj)) { + mono_set_pending_exception (mono_get_exception_argument_null ("obj")); + return FALSE; + } return mono_monitor_try_enter_internal (obj, INFINITE, FALSE) == 1; } gboolean mono_monitor_enter_fast (MonoObject *obj) { + if (G_UNLIKELY (!obj)) { + /* don't set pending exn on the fast path, just return + * FALSE and let the slow path take care of it. */ + return FALSE; + } return mono_monitor_try_enter_internal (obj, 0, FALSE) == 1; } gboolean mono_monitor_try_enter (MonoObject *obj, guint32 ms) { + if (G_UNLIKELY (!obj)) { + mono_set_pending_exception (mono_get_exception_argument_null ("obj")); + return FALSE; + } return mono_monitor_try_enter_internal (obj, ms, FALSE) == 1; } @@ -1075,6 +1083,10 @@ void ves_icall_System_Threading_Monitor_Monitor_try_enter_with_atomic_var (MonoObject *obj, guint32 ms, char *lockTaken) { gint32 res; + if (G_UNLIKELY (!obj)) { + mono_set_pending_exception (mono_get_exception_argument_null ("obj")); + return; + } do { res = mono_monitor_try_enter_internal (obj, ms, TRUE); /*This means we got interrupted during the wait and didn't got the monitor.*/ diff --git a/mono/metadata/monitor.h b/mono/metadata/monitor.h index f43e08caec..39afe1b69a 100644 --- a/mono/metadata/monitor.h +++ b/mono/metadata/monitor.h @@ -13,7 +13,8 @@ #include #include #include -#include "mono/utils/mono-compiler.h" +#include +#include G_BEGIN_DECLS @@ -39,9 +40,9 @@ struct _MonoThreadsSync #ifdef HAVE_MOVING_COLLECTOR gint32 hash_code; #endif - HANDLE entry_sem; GSList *wait_list; void *data; + MonoCoopSem *entry_sem; }; /* diff --git a/mono/metadata/mono-config.c b/mono/metadata/mono-config.c index 39ef20082c..2bedf12cd8 100644 --- a/mono/metadata/mono-config.c +++ b/mono/metadata/mono-config.c @@ -735,7 +735,7 @@ publisher_policy_start (gpointer user_data, memset (&info->old_version_bottom, 0, sizeof (info->old_version_bottom)); memset (&info->old_version_top, 0, sizeof (info->old_version_top)); memset (&info->new_version, 0, sizeof (info->new_version)); - } if (!strcmp (element_name, "assemblyIdentity")) { + } else if (!strcmp (element_name, "assemblyIdentity")) { for (n = 0; attribute_names [n]; n++) { const gchar *attribute_name = attribute_names [n]; diff --git a/mono/metadata/mono-perfcounters.c b/mono/metadata/mono-perfcounters.c index 44872a4dcf..cd2c622a89 100644 --- a/mono/metadata/mono-perfcounters.c +++ b/mono/metadata/mono-perfcounters.c @@ -30,10 +30,13 @@ #include #include #include -#endif -#if defined (__NetBSD__) || defined (__APPLE__) #include #endif +#if defined (__NetBSD__) +#include +#include +#include +#endif #include "metadata/mono-perfcounters.h" #include "metadata/appdomain.h" #include "metadata/object-internals.h" @@ -425,7 +428,7 @@ mono_determine_physical_ram_size (void) int mib[2] = { CTL_HW, #ifdef __NetBSD__ - HW_PHYSMEM + HW_PHYSMEM64 #else HW_MEMSIZE #endif @@ -474,29 +477,22 @@ mono_determine_physical_ram_available_size (void) #elif defined (__NetBSD__) struct vmtotal vm_total; guint64 page_size; - int mib [2]; + int mib[2]; size_t len; + mib[0] = CTL_VM; + mib[1] = VM_METER; - mib = { - CTL_VM, -#if defined (VM_METER) - VM_METER -#else - VM_TOTAL -#endif - }; len = sizeof (vm_total); sysctl (mib, 2, &vm_total, &len, NULL, 0); - mib = { - CTL_HW, - HW_PAGESIZE - }; - len = sizeof (page_size); - sysctl (mib, 2, &page_size, &len, NULL, 0 + mib[0] = CTL_HW; + mib[1] = HW_PAGESIZE; - return ((guint64) value.t_free * page_size) / 1024; + len = sizeof (page_size); + sysctl (mib, 2, &page_size, &len, NULL, 0); + + return ((guint64) vm_total.t_free * page_size) / 1024; #elif defined (__APPLE__) mach_msg_type_number_t count = HOST_VM_INFO_COUNT; mach_port_t host = mach_host_self(); @@ -802,18 +798,14 @@ fill_sample (MonoCounterSample *sample) } static int -id_from_string (MonoString *instance, gboolean is_process) +id_from_string (const gchar *id_str, gboolean is_process) { - MonoError error; int id = -1; - if (mono_string_length (instance)) { - char *id_str = mono_string_to_utf8_checked (instance, &error); - mono_error_raise_exception (&error); /* FIXME don't raise here */ + if (strcmp("", id_str) != 0) { char *end; id = strtol (id_str, &end, 0); if (end == id_str && !is_process) id = -1; - g_free (id_str); } return id; } @@ -851,7 +843,7 @@ get_cpu_counter (ImplVtable *vtable, MonoBoolean only_value, MonoCounterSample * } static void* -cpu_get_impl (MonoString* counter, MonoString* instance, int *type, MonoBoolean *custom) +cpu_get_impl (MonoString* counter, const gchar* instance, int *type, MonoBoolean *custom) { int id = id_from_string (instance, FALSE) << 5; const CounterDesc *cdesc; @@ -912,9 +904,8 @@ network_cleanup (ImplVtable *vtable) } static void* -network_get_impl (MonoString* counter, MonoString* instance, int *type, MonoBoolean *custom) +network_get_impl (MonoString* counter, const gchar* instance, int *type, MonoBoolean *custom) { - MonoError error; const CounterDesc *cdesc; NetworkVtableArg *narg; ImplVtable *vtable; @@ -922,8 +913,7 @@ network_get_impl (MonoString* counter, MonoString* instance, int *type, MonoBool *custom = FALSE; if ((cdesc = get_counter_in_category (&predef_categories [CATEGORY_NETWORK], counter))) { - instance_name = mono_string_to_utf8_checked (instance, &error); - mono_error_raise_exception (&error); /* FIXME don't raise here */ + instance_name = g_strdup (instance); narg = g_new0 (NetworkVtableArg, 1); narg->id = cdesc->id; narg->name = instance_name; @@ -975,7 +965,7 @@ get_process_counter (ImplVtable *vtable, MonoBoolean only_value, MonoCounterSamp } static void* -process_get_impl (MonoString* counter, MonoString* instance, int *type, MonoBoolean *custom) +process_get_impl (MonoString* counter, const gchar* instance, int *type, MonoBoolean *custom) { int id = id_from_string (instance, TRUE) << 5; const CounterDesc *cdesc; @@ -1013,7 +1003,7 @@ mono_mem_counter (ImplVtable *vtable, MonoBoolean only_value, MonoCounterSample } static void* -mono_mem_get_impl (MonoString* counter, MonoString* instance, int *type, MonoBoolean *custom) +mono_mem_get_impl (MonoString* counter, const gchar* instance, int *type, MonoBoolean *custom) { const CounterDesc *cdesc; *custom = FALSE; @@ -1045,17 +1035,13 @@ predef_readonly_counter (ImplVtable *vtable, MonoBoolean only_value, MonoCounter } static ImplVtable* -predef_vtable (void *arg, MonoString *instance) +predef_vtable (void *arg, const gchar *pids) { - MonoError error; MonoSharedArea *area; PredefVtable *vtable; - char *pids = mono_string_to_utf8_checked (instance, &error); - mono_error_raise_exception (&error); /* FIXME don't raise here */ int pid; pid = atoi (pids); - g_free (pids); area = load_sarea_for_pid (pid); if (!area) return NULL; @@ -1200,13 +1186,13 @@ predef_writable_update (ImplVtable *vtable, MonoBoolean do_incr, gint64 value) } static void* -predef_writable_get_impl (int cat, MonoString* counter, MonoString* instance, int *type, MonoBoolean *custom) +predef_writable_get_impl (int cat, MonoString* counter, const gchar *instance, int *type, MonoBoolean *custom) { const CounterDesc *cdesc; *custom = TRUE; if ((cdesc = get_counter_in_category (&predef_categories [cat], counter))) { *type = cdesc->type; - if (instance == NULL || mono_string_compare_ascii (instance, "") == 0) + if (instance == NULL || strcmp (instance, "") == 0) return create_vtable (GINT_TO_POINTER ((cdesc->id << 16) | cat), predef_writable_counter, predef_writable_update); else return predef_vtable (GINT_TO_POINTER ((cdesc->id << 16) | cat), instance); @@ -1304,19 +1290,19 @@ custom_get_value_address (SharedCounter *scounter, SharedInstance* sinst) } static void* -custom_get_impl (SharedCategory *cat, MonoString* counter, MonoString* instance, int *type) +custom_get_impl (SharedCategory *cat, MonoString *counter, MonoString* instance, int *type, MonoError *error) { - MonoError error; SharedCounter *scounter; SharedInstance* inst; char *name; + mono_error_init (error); scounter = find_custom_counter (cat, counter); if (!scounter) return NULL; + name = mono_string_to_utf8_checked (counter, error); + return_val_if_nok (error, NULL); *type = simple_type_to_type [scounter->type]; - name = mono_string_to_utf8_checked (counter, &error); - mono_error_raise_exception (&error); /* FIXME don't raise here */ inst = custom_get_instance (cat, scounter, name); g_free (name); if (!inst) @@ -1339,7 +1325,9 @@ void* mono_perfcounter_get_impl (MonoString* category, MonoString* counter, MonoString* instance, MonoString* machine, int *type, MonoBoolean *custom) { + MonoError error; const CategoryDesc *cdesc; + void *result = NULL; /* no support for counters on other machines */ if (mono_string_compare_ascii (machine, ".")) return NULL; @@ -1349,17 +1337,27 @@ mono_perfcounter_get_impl (MonoString* category, MonoString* counter, MonoString if (!scat) return NULL; *custom = TRUE; - return custom_get_impl (scat, counter, instance, type); + result = custom_get_impl (scat, counter, instance, type, &error); + if (mono_error_set_pending_exception (&error)) + return NULL; + return result; } + gchar *c_instance = mono_string_to_utf8_checked (instance, &error); + if (mono_error_set_pending_exception (&error)) + return NULL; switch (cdesc->id) { case CATEGORY_CPU: - return cpu_get_impl (counter, instance, type, custom); + result = cpu_get_impl (counter, c_instance, type, custom); + break; case CATEGORY_PROC: - return process_get_impl (counter, instance, type, custom); + result = process_get_impl (counter, c_instance, type, custom); + break; case CATEGORY_MONO_MEM: - return mono_mem_get_impl (counter, instance, type, custom); + result = mono_mem_get_impl (counter, c_instance, type, custom); + break; case CATEGORY_NETWORK: - return network_get_impl (counter, instance, type, custom); + result = network_get_impl (counter, c_instance, type, custom); + break; case CATEGORY_JIT: case CATEGORY_EXC: case CATEGORY_GC: @@ -1370,9 +1368,11 @@ mono_perfcounter_get_impl (MonoString* category, MonoString* counter, MonoString case CATEGORY_SECURITY: case CATEGORY_ASPNET: case CATEGORY_THREADPOOL: - return predef_writable_get_impl (cdesc->id, counter, instance, type, custom); + result = predef_writable_get_impl (cdesc->id, counter, c_instance, type, custom); + break; } - return NULL; + g_free (c_instance); + return result; } MonoBoolean @@ -1585,7 +1585,8 @@ mono_perfcounter_instance_exists (MonoString *instance, MonoString *category, Mo if (!scat) return FALSE; name = mono_string_to_utf8_checked (instance, &error); - mono_error_raise_exception (&error); /* FIXME don't raise here */ + if (mono_error_set_pending_exception (&error)) + return FALSE; sinst = find_custom_instance (scat, name); g_free (name); if (sinst) diff --git a/mono/metadata/mono-route.c b/mono/metadata/mono-route.c index d651b0e5b0..5f3ecb93ea 100644 --- a/mono/metadata/mono-route.c +++ b/mono/metadata/mono-route.c @@ -53,7 +53,7 @@ extern MonoBoolean ves_icall_System_Net_NetworkInformation_MacOsIPInterfacePrope return FALSE; // Allocate suffcient memory for available data based on the previous sysctl call - if ((buf = malloc(needed)) == NULL) + if ((buf = g_malloc (needed)) == NULL) return FALSE; // Second sysctl call to retrieve data into appropriately sized buffer @@ -102,7 +102,7 @@ extern MonoBoolean ves_icall_System_Net_NetworkInformation_MacOsIPInterfacePrope mono_array_setref (*gw_addr_list, gwnum, addr_string); gwnum++; } - free(buf); + g_free (buf); return TRUE; } diff --git a/mono/metadata/mono-security.c b/mono/metadata/mono-security.c index b27da35857..865b9ca1e0 100644 --- a/mono/metadata/mono-security.c +++ b/mono/metadata/mono-security.c @@ -276,9 +276,9 @@ ves_icall_System_Security_Principal_WindowsIdentity_GetCurrentToken (void) */ /* thread may be impersonating somebody */ - if (OpenThreadToken (GetCurrentThread (), TOKEN_QUERY, 1, &token) == 0) { + if (OpenThreadToken (GetCurrentThread (), MAXIMUM_ALLOWED, 1, &token) == 0) { /* if not take the process identity */ - OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &token); + OpenProcessToken (GetCurrentProcess (), MAXIMUM_ALLOWED, &token); } #else token = GINT_TO_POINTER (geteuid ()); @@ -660,9 +660,10 @@ IsMachineProtected (gunichar2 *path) { gboolean success = FALSE; PACL pDACL = NULL; + PSECURITY_DESCRIPTOR pSD = NULL; PSID pEveryoneSid = NULL; - DWORD dwRes = GetNamedSecurityInfoW (path, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, &pDACL, NULL, NULL); + DWORD dwRes = GetNamedSecurityInfoW (path, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, &pDACL, NULL, &pSD); if (dwRes != ERROR_SUCCESS) return FALSE; @@ -679,8 +680,8 @@ IsMachineProtected (gunichar2 *path) /* Note: we don't need to check our own access - we'll know soon enough when reading the file */ - if (pDACL) - LocalFree (pDACL); + if (pSD) + LocalFree (pSD); return success; } diff --git a/mono/metadata/null-gc.c b/mono/metadata/null-gc.c index c1a531c0dc..aa8bc0259b 100644 --- a/mono/metadata/null-gc.c +++ b/mono/metadata/null-gc.c @@ -26,6 +26,10 @@ mono_gc_base_init (void) mono_counters_init (); +#ifndef HOST_WIN32 + mono_w32handle_init (); +#endif + memset (&cb, 0, sizeof (cb)); /* TODO: This casts away an incompatible pointer type warning in the same manner that boehm-gc does it. This is probably worth investigating @@ -107,16 +111,6 @@ mono_object_is_alive (MonoObject* o) return TRUE; } -void -mono_gc_enable_events (void) -{ -} - -void -mono_gc_enable_alloc_events (void) -{ -} - int mono_gc_register_root (char *start, size_t size, void *descr, MonoGCRootSource source, const char *msg) { @@ -191,7 +185,7 @@ mono_gc_free_fixed (void* addr) void * mono_gc_alloc_obj (MonoVTable *vtable, size_t size) { - MonoObject *obj = calloc (1, size); + MonoObject *obj = g_calloc (1, size); obj->vtable = vtable; @@ -201,7 +195,7 @@ mono_gc_alloc_obj (MonoVTable *vtable, size_t size) void * mono_gc_alloc_vector (MonoVTable *vtable, size_t size, uintptr_t max_length) { - MonoArray *obj = calloc (1, size); + MonoArray *obj = g_calloc (1, size); obj->obj.vtable = vtable; obj->max_length = max_length; @@ -212,7 +206,7 @@ mono_gc_alloc_vector (MonoVTable *vtable, size_t size, uintptr_t max_length) void * mono_gc_alloc_array (MonoVTable *vtable, size_t size, uintptr_t max_length, uintptr_t bounds_size) { - MonoArray *obj = calloc (1, size); + MonoArray *obj = g_calloc (1, size); obj->obj.vtable = vtable; obj->max_length = max_length; @@ -226,7 +220,7 @@ mono_gc_alloc_array (MonoVTable *vtable, size_t size, uintptr_t max_length, uint void * mono_gc_alloc_string (MonoVTable *vtable, size_t size, gint32 len) { - MonoString *obj = calloc (1, size); + MonoString *obj = g_calloc (1, size); obj->object.vtable = vtable; obj->length = len; @@ -551,5 +545,9 @@ mono_gc_is_null (void) { return TRUE; } - -#endif +#else + #ifdef _MSC_VER + // Quiet Visual Studio linker warning, LNK4221, in cases when this source file intentional ends up empty. + void __mono_win32_null_gc_quiet_lnk4221(void) {} + #endif +#endif /* HAVE_NULL_GC */ diff --git a/mono/metadata/object-internals.h b/mono/metadata/object-internals.h index 20af8c4ac1..2be3719a19 100644 --- a/mono/metadata/object-internals.h +++ b/mono/metadata/object-internals.h @@ -263,6 +263,9 @@ struct _MonoReflectionType { MonoType *type; }; +/* Safely access System.Type from native code */ +TYPED_HANDLE_DECL (MonoReflectionType); + /* This corresponds to System.RuntimeType */ typedef struct { MonoReflectionType type; @@ -354,7 +357,6 @@ struct _MonoInternalThread { MonoException *abort_exc; int abort_state_handle; guint64 tid; /* This is accessed as a gsize in the code (so it can hold a 64bit pointer on systems that need it), but needs to reserve 64 bits of space on all machines as it corresponds to a field in managed code */ - HANDLE start_notify; gpointer stack_ptr; gpointer *static_data; void *thread_info; /*This is MonoThreadInfo*, but to simplify dependencies, let's make it a void* here. */ @@ -377,14 +379,21 @@ struct _MonoInternalThread { gpointer interrupt_on_stop; gsize flags; gpointer thread_pinning_ref; + gsize abort_protected_block_count; /* * These fields are used to avoid having to increment corlib versions * when a new field is added to this structure. * Please synchronize any changes with InternalThread in Thread.cs, i.e. add the * same field there. */ - gpointer unused1; - gpointer unused2; + gsize unused1; + gsize unused2; + + /* This is used only to check that we are in sync between the representation + * of MonoInternalThread in native and InternalThread in managed + * + * DO NOT RENAME! DO NOT ADD FIELDS AFTER! */ + gpointer last; }; struct _MonoThread { @@ -392,6 +401,7 @@ struct _MonoThread { struct _MonoInternalThread *internal_thread; MonoObject *start_obj; MonoException *pending_exception; + gint32 priority; }; typedef struct { @@ -584,6 +594,7 @@ typedef struct { void (*mono_raise_exception_with_ctx) (MonoException *ex, MonoContext *ctx); gboolean (*mono_exception_walk_trace) (MonoException *ex, MonoInternalExceptionFrameWalk func, gpointer user_data); gboolean (*mono_install_handler_block_guard) (MonoThreadUnwindState *unwind_state); + gboolean (*mono_current_thread_has_handle_block_guard) (void); } MonoRuntimeExceptionHandlingCallbacks; /* used to free a dynamic method */ @@ -808,6 +819,9 @@ struct _MonoReflectionAssembly { MonoString *name; }; +/* Safely access System.Reflection.Assembly from native code */ +TYPED_HANDLE_DECL (MonoReflectionAssembly); + typedef struct { MonoReflectionType *utype; MonoArray *values; @@ -1097,6 +1111,9 @@ struct _MonoReflectionModule { guint32 token; }; +/* Safely access System.Reflection.Module from native code */ +TYPED_HANDLE_DECL (MonoReflectionModule); + typedef struct { MonoReflectionModule module; MonoDynamicImage *dynamic_image; @@ -1329,35 +1346,29 @@ typedef struct { } CattrNamedArg; gboolean mono_image_create_pefile (MonoReflectionModuleBuilder *module, HANDLE file, MonoError *error); -void mono_image_basic_init (MonoReflectionAssemblyBuilder *assembly); -MonoReflectionModule * mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *assembly, MonoString *file_name, MonoError *error); guint32 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str); guint32 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, gboolean create_methodspec, gboolean register_token, MonoError *error); guint32 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error); -void mono_image_module_basic_init (MonoReflectionModuleBuilder *module); void mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj); void mono_dynamic_image_free (MonoDynamicImage *image); void mono_dynamic_image_free_image (MonoDynamicImage *image); -void mono_image_set_wrappers_type (MonoReflectionModuleBuilder *mb, MonoReflectionType *type); void mono_dynamic_image_release_gc_roots (MonoDynamicImage *image); void mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb); -void mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb); +MonoReflectionType* +ves_icall_TypeBuilder_create_runtime_class (MonoReflectionTypeBuilder *tb); -void mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb); - -gboolean mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb, MonoError *error); - -MonoReflectionType* mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb); +void +ves_icall_TypeBuilder_setup_internal_class (MonoReflectionTypeBuilder *tb); void mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error); -void mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *m); void mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb); -void mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam); -void mono_reflection_create_unmanaged_type (MonoReflectionType *type); +void +ves_icall_SymbolType_create_unmanaged_type (MonoReflectionType *type); + void mono_reflection_register_with_runtime (MonoReflectionType *type); void mono_reflection_create_custom_attr_data_args (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoArray **typed_args, MonoArray **named_args, CattrNamedArg **named_arg_info, MonoError *error); @@ -1369,16 +1380,17 @@ MonoClass* mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic); MonoType* mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types, MonoError *error); -MonoReflectionMethod* -mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *method, MonoArray *types); void mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields); + MonoReflectionEvent * -mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb); +ves_icall_TypeBuilder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb); -MonoArray *mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig); +MonoArray * +ves_icall_SignatureHelper_get_signature_local (MonoReflectionSigHelper *sig); -MonoArray *mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig); +MonoArray * +ves_icall_SignatureHelper_get_signature_field (MonoReflectionSigHelper *sig); MonoReflectionMarshalAsAttribute* mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass, MonoMarshalSpec *spec, MonoError *error); @@ -1388,18 +1400,12 @@ mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean gboolean mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass, MonoError *error); -gboolean -mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token); - void ves_icall_System_Reflection_CustomAttributeData_ResolveArgumentsInternal (MonoReflectionMethod *method, MonoReflectionAssembly *assembly, gpointer data, guint32 data_length, MonoArray **ctor_args, MonoArray ** named_args); MonoType* mono_reflection_type_get_handle (MonoReflectionType *ref, MonoError *error); -void -mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass); - gboolean mono_image_build_metadata (MonoReflectionModuleBuilder *module, MonoError *error); @@ -1456,18 +1462,12 @@ mono_upgrade_remote_class (MonoDomain *domain, MonoObject *tproxy, MonoClass *kl void* mono_load_remote_field_checked (MonoObject *this_obj, MonoClass *klass, MonoClassField *field, void **res, MonoError *error); -MonoObject * -mono_load_remote_field_new_icall (MonoObject *this_obj, MonoClass *klass, MonoClassField *field); - MonoObject * mono_load_remote_field_new_checked (MonoObject *this_obj, MonoClass *klass, MonoClassField *field, MonoError *error); gboolean mono_store_remote_field_checked (MonoObject *this_obj, MonoClass *klass, MonoClassField *field, void* val, MonoError *error); -void -mono_store_remote_field_new_icall (MonoObject *this_obj, MonoClass *klass, MonoClassField *field, MonoObject *arg); - gboolean mono_store_remote_field_new_checked (MonoObject *this_obj, MonoClass *klass, MonoClassField *field, MonoObject *arg, MonoError *error); @@ -1623,6 +1623,12 @@ mono_property_set_value_checked (MonoProperty *prop, void *obj, void **params, M MonoObject* mono_property_get_value_checked (MonoProperty *prop, void *obj, void **params, MonoError *error); +MonoString* +mono_object_to_string_checked (MonoObject *obj, MonoError *error); + +MonoString* +mono_object_try_to_string (MonoObject *obj, MonoObject **exc, MonoError *error); + char * mono_string_to_utf8_ignore (MonoString *s); @@ -1735,6 +1741,81 @@ mono_runtime_delegate_invoke_checked (MonoObject *delegate, void **params, MonoArray* mono_runtime_get_main_args_checked (MonoError *error); +int +mono_runtime_run_main_checked (MonoMethod *method, int argc, char* argv[], + MonoError *error); + +int +mono_runtime_try_run_main (MonoMethod *method, int argc, char* argv[], + MonoObject **exc); + +int +mono_runtime_exec_main_checked (MonoMethod *method, MonoArray *args, MonoError *error); + +int +mono_runtime_try_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc); + +MonoReflectionMethod* +ves_icall_MonoMethod_MakeGenericMethod_impl (MonoReflectionMethod *rmethod, MonoArray *types); + +gint32 +ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance); + +gint32 +ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb, + MonoReflectionMethod *method, + MonoArray *opt_param_types); + +void +ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file); + +void +ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb); + +void +ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token); + +MonoObject* +ves_icall_ModuleBuilder_GetRegisteredToken (MonoReflectionModuleBuilder *mb, guint32 token); + +void +ves_icall_AssemblyBuilder_basic_init (MonoReflectionAssemblyBuilder *assemblyb); + +MonoReflectionModule* +ves_icall_AssemblyBuilder_InternalAddModule (MonoReflectionAssemblyBuilder *ab, MonoString *fileName); + +void +ves_icall_TypeBuilder_create_generic_class (MonoReflectionTypeBuilder *tb); + +MonoArray* +ves_icall_CustomAttributeBuilder_GetBlob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues); + +void +ves_icall_DynamicMethod_create_dynamic_method (MonoReflectionDynamicMethod *mb); + +MonoBoolean +ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb); + +void +ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype, + MonoReflectionType *t); + +MonoReflectionType* +ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers); + +void +ves_icall_ModuleBuilder_basic_init (MonoReflectionModuleBuilder *moduleb); + +guint32 +ves_icall_ModuleBuilder_getUSIndex (MonoReflectionModuleBuilder *module, MonoString *str); + +void +ves_icall_ModuleBuilder_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type); + +void +ves_icall_GenericTypeParameterBuilder_initialize_generic_parameter (MonoReflectionGenericParam *gparam); + +MonoReflectionMethod* +ves_icall_MethodBuilder_MakeGenericMethod (MonoReflectionMethod *rmethod, MonoArray *types); + #endif /* __MONO_OBJECT_INTERNALS_H__ */ - - diff --git a/mono/metadata/object-offsets.h b/mono/metadata/object-offsets.h index 26fae81fb8..e4965a512a 100644 --- a/mono/metadata/object-offsets.h +++ b/mono/metadata/object-offsets.h @@ -56,6 +56,8 @@ DECL_SIZE(gpointer) DECL_OFFSET(MonoObject, vtable) DECL_OFFSET(MonoObject, synchronisation) +DECL_OFFSET(MonoObjectHandlePayload, __obj) + DECL_OFFSET(MonoClass, interface_bitmap) DECL_OFFSET(MonoClass, byval_arg) DECL_OFFSET(MonoClass, cast_class) @@ -90,6 +92,7 @@ DECL_OFFSET(MonoDelegate, extra_arg) DECL_OFFSET(MonoInternalThread, tid) DECL_OFFSET(MonoInternalThread, small_id) DECL_OFFSET(MonoInternalThread, static_data) +DECL_OFFSET(MonoInternalThread, last) DECL_OFFSET(MonoMulticastDelegate, delegates) diff --git a/mono/metadata/object.c.REMOVED.git-id b/mono/metadata/object.c.REMOVED.git-id index ce6c50526e..7034aeecf9 100644 --- a/mono/metadata/object.c.REMOVED.git-id +++ b/mono/metadata/object.c.REMOVED.git-id @@ -1 +1 @@ -d5b8dd5db52f5b2af9fca12c6c39209d7f1e8cfc \ No newline at end of file +83d80c89e28835b80aac9c19bc28d3588b51ac32 \ No newline at end of file diff --git a/mono/metadata/object.h b/mono/metadata/object.h index 6f31d12191..24f7284e8e 100644 --- a/mono/metadata/object.h +++ b/mono/metadata/object.h @@ -175,6 +175,7 @@ mono_string_hash (MonoString *s); MONO_API int mono_object_hash (MonoObject* obj); +MONO_RT_EXTERNAL_ONLY MONO_API MonoString * mono_object_to_string (MonoObject *obj, MonoObject **exc); @@ -278,10 +279,12 @@ mono_runtime_exec_managed_code (MonoDomain *domain, MonoMainThreadFunc main_func, void* main_args); +MONO_RT_EXTERNAL_ONLY MONO_API int mono_runtime_run_main (MonoMethod *method, int argc, char* argv[], MonoObject **exc); +MONO_RT_EXTERNAL_ONLY MONO_API int mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc); diff --git a/mono/metadata/opcodes.h b/mono/metadata/opcodes.h index 71b4cb4958..d70d6f07be 100644 --- a/mono/metadata/opcodes.h +++ b/mono/metadata/opcodes.h @@ -62,7 +62,7 @@ typedef struct { unsigned short opval; } MonoOpcode; -extern const MonoOpcode mono_opcodes []; +MONO_API extern const MonoOpcode mono_opcodes []; MONO_API const char* mono_opcode_name (int opcode); diff --git a/mono/metadata/process.c b/mono/metadata/process.c index 138bd98553..8178d28382 100644 --- a/mono/metadata/process.c +++ b/mono/metadata/process.c @@ -27,6 +27,7 @@ #include /* FIXME: fix this code to not depend so much on the internals */ #include +#include #define LOGDEBUG(...) /* define LOGDEBUG(...) g_message(__VA_ARGS__) */ diff --git a/mono/metadata/profiler.c b/mono/metadata/profiler.c index fb4cdeca08..0fd162dd98 100644 --- a/mono/metadata/profiler.c +++ b/mono/metadata/profiler.c @@ -273,7 +273,6 @@ mono_profiler_install_transition (MonoProfileMethodResult callback) void mono_profiler_install_allocation (MonoProfileAllocFunc callback) { - mono_gc_enable_alloc_events (); if (!prof_list) return; prof_list->allocation_cb = callback; @@ -876,7 +875,6 @@ mono_profiler_gc_roots (int num, void **objects, int *root_types, uintptr_t *ext void mono_profiler_install_gc (MonoProfileGCFunc callback, MonoProfileGCResizeFunc heap_resize_callback) { - mono_gc_enable_events (); if (!prof_list) return; prof_list->gc_event = callback; @@ -970,7 +968,7 @@ mono_profiler_install_gc_finalize (MonoProfileGCFinalizeFunc begin, MonoProfileG prof_list->gc_finalize_begin = begin; prof_list->gc_finalize_object_begin = begin_obj; - prof_list->gc_finalize_object_begin = end_obj; + prof_list->gc_finalize_object_end = end_obj; prof_list->gc_finalize_end = end; } diff --git a/mono/metadata/reflection-cache.h b/mono/metadata/reflection-cache.h new file mode 100644 index 0000000000..ec4d722fb8 --- /dev/null +++ b/mono/metadata/reflection-cache.h @@ -0,0 +1,80 @@ +/* + * Copyright 2016 Microsoft + * Licensed under the MIT license. See LICENSE file in the project root for full license information. + */ +#ifndef __MONO_METADATA_REFLECTION_CACHE_H__ +#define __MONO_METADATA_REFLECTION_CACHE_H__ + +#include +#include +#include +#include + +/* + * We need to return always the same object for MethodInfo, FieldInfo etc.. + * but we need to consider the reflected type. + * type uses a different hash, since it uses custom hash/equal functions. + */ + +typedef struct { + gpointer item; + MonoClass *refclass; +} ReflectedEntry; + +gboolean +reflected_equal (gconstpointer a, gconstpointer b); + +guint +reflected_hash (gconstpointer a); + +#ifdef HAVE_BOEHM_GC +/* ReflectedEntry doesn't need to be GC tracked */ +#define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1) +#define FREE_REFENTRY(entry) g_free ((entry)) +#define REFENTRY_REQUIRES_CLEANUP +#else +#define ALLOC_REFENTRY (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry)) +/* FIXME: */ +#define FREE_REFENTRY(entry) +#endif + + +#define CACHE_OBJECT(t,p,o,k) \ + do { \ + t _obj; \ + ReflectedEntry pe; \ + pe.item = (p); \ + pe.refclass = (k); \ + mono_domain_lock (domain); \ + if (!domain->refobject_hash) \ + domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection objects table"); \ + _obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &pe); \ + if (!_obj) { \ + ReflectedEntry *e = ALLOC_REFENTRY; \ + e->item = (p); \ + e->refclass = (k); \ + mono_g_hash_table_insert (domain->refobject_hash, e,o); \ + _obj = o; \ + } \ + mono_domain_unlock (domain); \ + return _obj; \ + } while (0) + +#define CHECK_OBJECT(t,p,k) \ + do { \ + t _obj; \ + ReflectedEntry e; \ + e.item = (p); \ + e.refclass = (k); \ + mono_domain_lock (domain); \ + if (!domain->refobject_hash) \ + domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection objects table"); \ + if ((_obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \ + mono_domain_unlock (domain); \ + return _obj; \ + } \ + mono_domain_unlock (domain); \ + } while (0) + + +#endif /*__MONO_METADATA_REFLECTION_CACHE_H__*/ diff --git a/mono/metadata/reflection-internals.h b/mono/metadata/reflection-internals.h index 327bb93142..85e757fbf5 100644 --- a/mono/metadata/reflection-internals.h +++ b/mono/metadata/reflection-internals.h @@ -1,14 +1,23 @@ /* * Copyright 2014 Xamarin Inc + * Copyright 2016 Microsoft * Licensed under the MIT license. See LICENSE file in the project root for full license information. */ #ifndef __MONO_METADATA_REFLECTION_INTERNALS_H__ #define __MONO_METADATA_REFLECTION_INTERNALS_H__ +#include #include +#include #include #include +gboolean +mono_reflection_is_usertype (MonoReflectionType *ref); + +MonoReflectionType* +mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error); + MonoType* mono_reflection_get_type_checked (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, mono_bool ignorecase, mono_bool *type_resolve, MonoError *error); @@ -32,13 +41,13 @@ MonoArray* mono_reflection_get_custom_attrs_blob_checked (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues, MonoError *error); MonoCustomAttrInfo* -mono_custom_attrs_from_index_checked (MonoImage *image, uint32_t idx, MonoError *error); +mono_custom_attrs_from_index_checked (MonoImage *image, uint32_t idx, gboolean ignore_missing, MonoError *error); MonoCustomAttrInfo* mono_custom_attrs_from_method_checked (MonoMethod *method, MonoError *error); MonoCustomAttrInfo* mono_custom_attrs_from_class_checked (MonoClass *klass, MonoError *error); MonoCustomAttrInfo* -mono_custom_attrs_from_assembly_checked (MonoAssembly *assembly, MonoError *error); +mono_custom_attrs_from_assembly_checked (MonoAssembly *assembly, gboolean ignore_missing, MonoError *error); MonoCustomAttrInfo* mono_custom_attrs_from_property_checked (MonoClass *klass, MonoProperty *property, MonoError *error); MonoCustomAttrInfo* @@ -82,5 +91,8 @@ mono_module_file_get_object_checked (MonoDomain *domain, MonoImage *image, int t MonoReflectionMethodBody* mono_method_body_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoError *error); +MonoClass * +mono_class_from_mono_type_handle (MonoReflectionTypeHandle h); + #endif /* __MONO_METADATA_REFLECTION_INTERNALS_H__ */ diff --git a/mono/metadata/reflection.c b/mono/metadata/reflection.c new file mode 100644 index 0000000000..0a5ea615a0 --- /dev/null +++ b/mono/metadata/reflection.c @@ -0,0 +1,2876 @@ +/* + * reflection.c: System.Type icalls and related reflection queries. + * + * Author: + * Paolo Molaro (lupus@ximian.com) + * + * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com) + * Copyright 2004-2009 Novell, Inc (http://www.novell.com) + * Copyright 2011 Rodrigo Kumpera + * Copyright 2016 Microsoft + * + * Licensed under the MIT license. See LICENSE file in the project root for full license information. + */ +#include +#include "mono/utils/mono-membar.h" +#include "mono/metadata/reflection-internals.h" +#include "mono/metadata/tabledefs.h" +#include "mono/metadata/metadata-internals.h" +#include +#include "mono/metadata/class-internals.h" +#include "mono/metadata/gc-internals.h" +#include "mono/metadata/domain-internals.h" +#include "mono/metadata/opcodes.h" +#include "mono/metadata/assembly.h" +#include "mono/metadata/object-internals.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "image.h" +#include "cil-coff.h" +#include "mono-endian.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types); +static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error); + +/* Class lazy loading functions */ +static GENERATE_GET_CLASS_WITH_CACHE (mono_assembly, System.Reflection, MonoAssembly) +static GENERATE_GET_CLASS_WITH_CACHE (mono_module, System.Reflection, MonoModule) +static GENERATE_GET_CLASS_WITH_CACHE (mono_generic_method, System.Reflection, MonoGenericMethod); +static GENERATE_GET_CLASS_WITH_CACHE (mono_generic_cmethod, System.Reflection, MonoGenericCMethod); +static GENERATE_GET_CLASS_WITH_CACHE (mono_method, System.Reflection, MonoMethod); +static GENERATE_GET_CLASS_WITH_CACHE (mono_cmethod, System.Reflection, MonoCMethod); +static GENERATE_GET_CLASS_WITH_CACHE (mono_field, System.Reflection, MonoField); +static GENERATE_GET_CLASS_WITH_CACHE (mono_event, System.Reflection, MonoEvent); +static GENERATE_GET_CLASS_WITH_CACHE (mono_property, System.Reflection, MonoProperty); +static GENERATE_GET_CLASS_WITH_CACHE (mono_parameter_info, System.Reflection, MonoParameterInfo); +static GENERATE_GET_CLASS_WITH_CACHE (missing, System.Reflection, Missing); +static GENERATE_GET_CLASS_WITH_CACHE (method_body, System.Reflection, MethodBody); +static GENERATE_GET_CLASS_WITH_CACHE (local_variable_info, System.Reflection, LocalVariableInfo); +static GENERATE_GET_CLASS_WITH_CACHE (exception_handling_clause, System.Reflection, ExceptionHandlingClause); +static GENERATE_GET_CLASS_WITH_CACHE (type_builder, System.Reflection.Emit, TypeBuilder); +static GENERATE_GET_CLASS_WITH_CACHE (dbnull, System, DBNull); + +void +mono_reflection_init (void) +{ + mono_reflection_emit_init (); +} + +/* + * mono_class_get_ref_info: + * + * Return the type builder/generic param builder corresponding to KLASS, if it exists. + */ +gpointer +mono_class_get_ref_info (MonoClass *klass) +{ + MONO_REQ_GC_UNSAFE_MODE; + + if (klass->ref_info_handle == 0) + return NULL; + else + return mono_gchandle_get_target (klass->ref_info_handle); +} + +void +mono_class_set_ref_info (MonoClass *klass, gpointer obj) +{ + MONO_REQ_GC_UNSAFE_MODE; + + klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE); + g_assert (klass->ref_info_handle != 0); +} + +void +mono_class_free_ref_info (MonoClass *klass) +{ + MONO_REQ_GC_NEUTRAL_MODE; + + if (klass->ref_info_handle) { + mono_gchandle_free (klass->ref_info_handle); + klass->ref_info_handle = 0; + } +} + + +void +mono_custom_attrs_free (MonoCustomAttrInfo *ainfo) +{ + MONO_REQ_GC_NEUTRAL_MODE; + + if (ainfo && !ainfo->cached) + g_free (ainfo); +} + + +gboolean +reflected_equal (gconstpointer a, gconstpointer b) +{ + const ReflectedEntry *ea = (const ReflectedEntry *)a; + const ReflectedEntry *eb = (const ReflectedEntry *)b; + + return (ea->item == eb->item) && (ea->refclass == eb->refclass); +} + +guint +reflected_hash (gconstpointer a) { + const ReflectedEntry *ea = (const ReflectedEntry *)a; + return mono_aligned_addr_hash (ea->item); +} + + +static void +clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass) +{ + mono_domain_lock (domain); + if (domain->refobject_hash) { + ReflectedEntry pe; + gpointer orig_pe, orig_value; + + pe.item = o; + pe.refclass = klass; + if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) { + mono_g_hash_table_remove (domain->refobject_hash, &pe); + FREE_REFENTRY (orig_pe); + } + } + mono_domain_unlock (domain); +} + +#ifdef REFENTRY_REQUIRES_CLEANUP +static void +cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data) +{ + FREE_REFENTRY (key); +} +#endif + +void +mono_reflection_cleanup_domain (MonoDomain *domain) +{ + if (domain->refobject_hash) { +/*let's avoid scanning the whole hashtable if not needed*/ +#ifdef REFENTRY_REQUIRES_CLEANUP + mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL); +#endif + mono_g_hash_table_destroy (domain->refobject_hash); + domain->refobject_hash = NULL; + } +} + + +/* + * mono_assembly_get_object: + * @domain: an app domain + * @assembly: an assembly + * + * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly. + */ +MonoReflectionAssembly* +mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly) +{ + MonoError error; + MonoReflectionAssembly *result; + result = mono_assembly_get_object_checked (domain, assembly, &error); + mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */ + return result; +} +/* + * mono_assembly_get_object_checked: + * @domain: an app domain + * @assembly: an assembly + * + * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly. + */ +MonoReflectionAssembly* +mono_assembly_get_object_checked (MonoDomain *domain, MonoAssembly *assembly, MonoError *error) +{ + MonoReflectionAssembly *res; + + mono_error_init (error); + + CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL); + res = (MonoReflectionAssembly *)mono_object_new_checked (domain, mono_class_get_mono_assembly_class (), error); + if (!res) + return NULL; + res->assembly = assembly; + + CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL); +} + + + +MonoReflectionModule* +mono_module_get_object (MonoDomain *domain, MonoImage *image) +{ + MonoError error; + MonoReflectionModule *result; + result = mono_module_get_object_checked (domain, image, &error); + mono_error_cleanup (&error); + return result; +} + +MonoReflectionModule* +mono_module_get_object_checked (MonoDomain *domain, MonoImage *image, MonoError *error) +{ + MonoReflectionModule *res; + char* basename; + + mono_error_init (error); + CHECK_OBJECT (MonoReflectionModule *, image, NULL); + res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error); + if (!res) + return NULL; + + res->image = image; + MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error); + if (!assm_obj) + return NULL; + MONO_OBJECT_SETREF (res, assembly, assm_obj); + + MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name)); + basename = g_path_get_basename (image->name); + MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename)); + MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name)); + + g_free (basename); + + if (image->assembly->image == image) { + res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1); + } else { + int i; + res->token = 0; + if (image->assembly->image->modules) { + for (i = 0; i < image->assembly->image->module_count; i++) { + if (image->assembly->image->modules [i] == image) + res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1); + } + g_assert (res->token); + } + } + + CACHE_OBJECT (MonoReflectionModule *, image, res, NULL); +} + +MonoReflectionModule* +mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index) +{ + MonoError error; + MonoReflectionModule *result; + result = mono_module_file_get_object_checked (domain, image, table_index, &error); + mono_error_cleanup (&error); + return result; +} + +MonoReflectionModule* +mono_module_file_get_object_checked (MonoDomain *domain, MonoImage *image, int table_index, MonoError *error) +{ + MonoReflectionModule *res; + MonoTableInfo *table; + guint32 cols [MONO_FILE_SIZE]; + const char *name; + guint32 i, name_idx; + const char *val; + + mono_error_init (error); + + res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error); + if (!res) + return NULL; + + table = &image->tables [MONO_TABLE_FILE]; + g_assert (table_index < table->rows); + mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE); + + res->image = NULL; + MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error); + if (!assm_obj) + return NULL; + MONO_OBJECT_SETREF (res, assembly, assm_obj); + name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]); + + /* Check whenever the row has a corresponding row in the moduleref table */ + table = &image->tables [MONO_TABLE_MODULEREF]; + for (i = 0; i < table->rows; ++i) { + name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME); + val = mono_metadata_string_heap (image, name_idx); + if (strcmp (val, name) == 0) + res->image = image->modules [i]; + } + + MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name)); + MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name)); + MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name)); + res->is_resource = cols [MONO_FILE_FLAGS] & FILE_CONTAINS_NO_METADATA; + res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1); + + return res; +} + +static gboolean +verify_safe_for_managed_space (MonoType *type) +{ + switch (type->type) { +#ifdef DEBUG_HARDER + case MONO_TYPE_ARRAY: + return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg); + case MONO_TYPE_PTR: + return verify_safe_for_managed_space (type->data.type); + case MONO_TYPE_SZARRAY: + return verify_safe_for_managed_space (&type->data.klass->byval_arg); + case MONO_TYPE_GENERICINST: { + MonoGenericInst *inst = type->data.generic_class->inst; + int i; + if (!inst->is_open) + break; + for (i = 0; i < inst->type_argc; ++i) + if (!verify_safe_for_managed_space (inst->type_argv [i])) + return FALSE; + return TRUE; + } +#endif + case MONO_TYPE_VAR: + case MONO_TYPE_MVAR: + return TRUE; + default: + return TRUE; + } +} + +static MonoType* +mono_type_normalize (MonoType *type) +{ + int i; + MonoGenericClass *gclass; + MonoGenericInst *ginst; + MonoClass *gtd; + MonoGenericContainer *gcontainer; + MonoType **argv = NULL; + gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE; + + if (type->type != MONO_TYPE_GENERICINST) + return type; + + gclass = type->data.generic_class; + ginst = gclass->context.class_inst; + if (!ginst->is_open) + return type; + + gtd = gclass->container_class; + gcontainer = gtd->generic_container; + argv = g_newa (MonoType*, ginst->type_argc); + + for (i = 0; i < ginst->type_argc; ++i) { + MonoType *t = ginst->type_argv [i], *norm; + if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer) + is_denorm_gtd = FALSE; + norm = mono_type_normalize (t); + argv [i] = norm; + if (norm != t) + requires_rebind = TRUE; + } + + if (is_denorm_gtd) + return type->byref == gtd->byval_arg.byref ? >d->byval_arg : >d->this_arg; + + if (requires_rebind) { + MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic); + return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg; + } + + return type; +} +/* + * mono_type_get_object: + * @domain: an app domain + * @type: a type + * + * Return an System.MonoType object representing the type @type. + */ +MonoReflectionType* +mono_type_get_object (MonoDomain *domain, MonoType *type) +{ + MonoError error; + MonoReflectionType *ret = mono_type_get_object_checked (domain, type, &error); + mono_error_cleanup (&error); + + return ret; +} + +MonoReflectionType* +mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error) +{ + MonoType *norm_type; + MonoReflectionType *res; + MonoClass *klass; + + mono_error_init (error); + + klass = mono_class_from_mono_type (type); + + /*we must avoid using @type as it might have come + * from a mono_metadata_type_dup and the caller + * expects that is can be freed. + * Using the right type from + */ + type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg; + + /* void is very common */ + if (type->type == MONO_TYPE_VOID && domain->typeof_void) + return (MonoReflectionType*)domain->typeof_void; + + /* + * If the vtable of the given class was already created, we can use + * the MonoType from there and avoid all locking and hash table lookups. + * + * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects + * that the resulting object is different. + */ + if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) { + MonoVTable *vtable = mono_class_try_get_vtable (domain, klass); + if (vtable && vtable->type) + return (MonoReflectionType *)vtable->type; + } + + mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/ + mono_domain_lock (domain); + if (!domain->type_hash) + domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, + (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table"); + if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) { + mono_domain_unlock (domain); + mono_loader_unlock (); + return res; + } + + /*Types must be normalized so a generic instance of the GTD get's the same inner type. + * For example in: Foo; Bar : Foo> + * The second Bar will be encoded a generic instance of Bar with as parameter. + * On all other places, Bar will be encoded as the GTD itself. This is an implementation + * artifact of how generics are encoded and should be transparent to managed code so we + * need to weed out this diference when retrieving managed System.Type objects. + */ + norm_type = mono_type_normalize (type); + if (norm_type != type) { + res = mono_type_get_object_checked (domain, norm_type, error); + if (!mono_error_ok (error)) + return NULL; + mono_g_hash_table_insert (domain->type_hash, type, res); + mono_domain_unlock (domain); + mono_loader_unlock (); + return res; + } + + /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/ + if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder) + g_assert (0); + + if (!verify_safe_for_managed_space (type)) { + mono_domain_unlock (domain); + mono_loader_unlock (); + mono_error_set_generic_error (error, "System", "InvalidOperationException", "This type cannot be propagated to managed space"); + return NULL; + } + + if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) { + gboolean is_type_done = TRUE; + /* Generic parameters have reflection_info set but they are not finished together with their enclosing type. + * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder. + * We can't simply close the types as this will interfere with other parts of the generics machinery. + */ + if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) { + MonoGenericParam *gparam = klass->byval_arg.data.generic_param; + + if (gparam->owner && gparam->owner->is_method) { + MonoMethod *method = gparam->owner->owner.method; + if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder) + is_type_done = FALSE; + } else if (gparam->owner && !gparam->owner->is_method) { + MonoClass *klass = gparam->owner->owner.klass; + if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder) + is_type_done = FALSE; + } + } + + /* g_assert_not_reached (); */ + /* should this be considered an error condition? */ + if (is_type_done && !type->byref) { + mono_domain_unlock (domain); + mono_loader_unlock (); + return (MonoReflectionType *)mono_class_get_ref_info (klass); + } + } + /* This is stored in vtables/JITted code so it has to be pinned */ + res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.runtimetype_class, error); + if (!mono_error_ok (error)) + return NULL; + + res->type = type; + mono_g_hash_table_insert (domain->type_hash, type, res); + + if (type->type == MONO_TYPE_VOID) + domain->typeof_void = (MonoObject*)res; + + mono_domain_unlock (domain); + mono_loader_unlock (); + return res; +} + +/* + * mono_method_get_object: + * @domain: an app domain + * @method: a method + * @refclass: the reflected type (can be NULL) + * + * Return an System.Reflection.MonoMethod object representing the method @method. + */ +MonoReflectionMethod* +mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass) +{ + MonoError error; + MonoReflectionMethod *ret = NULL; + ret = mono_method_get_object_checked (domain, method, refclass, &error); + mono_error_cleanup (&error); + return ret; +} + +/* + * mono_method_get_object_checked: + * @domain: an app domain + * @method: a method + * @refclass: the reflected type (can be NULL) + * @error: set on error. + * + * Return an System.Reflection.MonoMethod object representing the method @method. + * Returns NULL and sets @error on error. + */ +MonoReflectionMethod* +mono_method_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error) +{ + /* + * We use the same C representation for methods and constructors, but the type + * name in C# is different. + */ + MonoReflectionType *rt; + MonoClass *klass; + MonoReflectionMethod *ret; + + mono_error_init (error); + + if (method->is_inflated) { + MonoReflectionGenericMethod *gret; + + if (!refclass) + refclass = method->klass; + CHECK_OBJECT (MonoReflectionMethod *, method, refclass); + if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) { + klass = mono_class_get_mono_generic_cmethod_class (); + } else { + klass = mono_class_get_mono_generic_method_class (); + } + gret = (MonoReflectionGenericMethod*)mono_object_new_checked (domain, klass, error); + if (!mono_error_ok (error)) + goto leave; + gret->method.method = method; + + MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name)); + + rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error); + if (!mono_error_ok (error)) + goto leave; + + MONO_OBJECT_SETREF (gret, method.reftype, rt); + + CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass); + } + + if (!refclass) + refclass = method->klass; + + CHECK_OBJECT (MonoReflectionMethod *, method, refclass); + if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) { + klass = mono_class_get_mono_cmethod_class (); + } + else { + klass = mono_class_get_mono_method_class (); + } + ret = (MonoReflectionMethod*)mono_object_new_checked (domain, klass, error); + if (!mono_error_ok (error)) + goto leave; + ret->method = method; + + rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error); + if (!mono_error_ok (error)) + goto leave; + + MONO_OBJECT_SETREF (ret, reftype, rt); + + CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass); + +leave: + g_assert (!mono_error_ok (error)); + return NULL; +} + +/* + * mono_method_clear_object: + * + * Clear the cached reflection objects for the dynamic method METHOD. + */ +void +mono_method_clear_object (MonoDomain *domain, MonoMethod *method) +{ + MonoClass *klass; + g_assert (method_is_dynamic (method)); + + klass = method->klass; + while (klass) { + clear_cached_object (domain, method, klass); + klass = klass->parent; + } + /* Added by mono_param_get_objects () */ + clear_cached_object (domain, &(method->signature), NULL); + klass = method->klass; + while (klass) { + clear_cached_object (domain, &(method->signature), klass); + klass = klass->parent; + } +} + +/* + * mono_field_get_object: + * @domain: an app domain + * @klass: a type + * @field: a field + * + * Return an System.Reflection.MonoField object representing the field @field + * in class @klass. + */ +MonoReflectionField* +mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field) +{ + MonoError error; + MonoReflectionField *result; + result = mono_field_get_object_checked (domain, klass, field, &error); + mono_error_cleanup (&error); + return result; +} + +/* + * mono_field_get_object_checked: + * @domain: an app domain + * @klass: a type + * @field: a field + * @error: set on error + * + * Return an System.Reflection.MonoField object representing the field @field + * in class @klass. On error, returns NULL and sets @error. + */ +MonoReflectionField* +mono_field_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoClassField *field, MonoError *error) +{ + MonoReflectionType *rt; + MonoReflectionField *res; + + mono_error_init (error); + + CHECK_OBJECT (MonoReflectionField *, field, klass); + res = (MonoReflectionField *)mono_object_new_checked (domain, mono_class_get_mono_field_class (), error); + if (!res) + return NULL; + res->klass = klass; + res->field = field; + MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field))); + + if (field->type) { + rt = mono_type_get_object_checked (domain, field->type, error); + if (!mono_error_ok (error)) + return NULL; + + MONO_OBJECT_SETREF (res, type, rt); + } + res->attrs = mono_field_get_flags (field); + CACHE_OBJECT (MonoReflectionField *, field, res, klass); +} + +/* + * mono_property_get_object: + * @domain: an app domain + * @klass: a type + * @property: a property + * + * Return an System.Reflection.MonoProperty object representing the property @property + * in class @klass. + */ +MonoReflectionProperty* +mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property) +{ + MonoError error; + MonoReflectionProperty *result; + result = mono_property_get_object_checked (domain, klass, property, &error); + mono_error_cleanup (&error); + return result; +} + +/** + * mono_property_get_object: + * @domain: an app domain + * @klass: a type + * @property: a property + * @error: set on error + * + * Return an System.Reflection.MonoProperty object representing the property @property + * in class @klass. On error returns NULL and sets @error. + */ +MonoReflectionProperty* +mono_property_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoProperty *property, MonoError *error) +{ + MonoReflectionProperty *res; + + mono_error_init (error); + + CHECK_OBJECT (MonoReflectionProperty *, property, klass); + res = (MonoReflectionProperty *)mono_object_new_checked (domain, mono_class_get_mono_property_class (), error); + if (!res) + return NULL; + res->klass = klass; + res->property = property; + CACHE_OBJECT (MonoReflectionProperty *, property, res, klass); +} + +/* + * mono_event_get_object: + * @domain: an app domain + * @klass: a type + * @event: a event + * + * Return an System.Reflection.MonoEvent object representing the event @event + * in class @klass. + */ +MonoReflectionEvent* +mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event) +{ + MonoError error; + MonoReflectionEvent *result; + result = mono_event_get_object_checked (domain, klass, event, &error); + mono_error_cleanup (&error); + return result; +} + +/** + * mono_event_get_object_checked: + * @domain: an app domain + * @klass: a type + * @event: a event + * @error: set on error + * + * Return an System.Reflection.MonoEvent object representing the event @event + * in class @klass. On failure sets @error and returns NULL + */ +MonoReflectionEvent* +mono_event_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoEvent *event, MonoError *error) +{ + MonoReflectionEvent *res; + MonoReflectionMonoEvent *mono_event; + + mono_error_init (error); + CHECK_OBJECT (MonoReflectionEvent *, event, klass); + mono_event = (MonoReflectionMonoEvent *)mono_object_new_checked (domain, mono_class_get_mono_event_class (), error); + if (!mono_event) + return NULL; + mono_event->klass = klass; + mono_event->event = event; + res = (MonoReflectionEvent*)mono_event; + CACHE_OBJECT (MonoReflectionEvent *, event, res, klass); +} + +/** + * mono_get_reflection_missing_object: + * @domain: Domain where the object lives + * + * Returns the System.Reflection.Missing.Value singleton object + * (of type System.Reflection.Missing). + * + * Used as the value for ParameterInfo.DefaultValue when Optional + * is present + */ +static MonoObject * +mono_get_reflection_missing_object (MonoDomain *domain) +{ + MonoError error; + MonoObject *obj; + static MonoClassField *missing_value_field = NULL; + + if (!missing_value_field) { + MonoClass *missing_klass; + missing_klass = mono_class_get_missing_class (); + mono_class_init (missing_klass); + missing_value_field = mono_class_get_field_from_name (missing_klass, "Value"); + g_assert (missing_value_field); + } + obj = mono_field_get_value_object_checked (domain, missing_value_field, NULL, &error); + mono_error_assert_ok (&error); + return obj; +} + +static MonoObject* +get_dbnull (MonoDomain *domain, MonoObject **dbnull) +{ + if (!*dbnull) + *dbnull = mono_get_dbnull_object (domain); + return *dbnull; +} + +static MonoObject* +get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing) +{ + if (!*reflection_missing) + *reflection_missing = mono_get_reflection_missing_object (domain); + return *reflection_missing; +} + +/* + * mono_param_get_objects: + * @domain: an app domain + * @method: a method + * + * Return an System.Reflection.ParameterInfo array object representing the parameters + * in the method @method. + */ +MonoArray* +mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error) +{ + static MonoClass *System_Reflection_ParameterInfo; + static MonoClass *System_Reflection_ParameterInfo_array; + MonoArray *res = NULL; + MonoReflectionMethod *member = NULL; + MonoReflectionParameter *param = NULL; + char **names = NULL, **blobs = NULL; + guint32 *types = NULL; + MonoType *type = NULL; + MonoObject *dbnull = NULL; + MonoObject *missing = NULL; + MonoMarshalSpec **mspecs = NULL; + MonoMethodSignature *sig = NULL; + MonoVTable *pinfo_vtable; + MonoReflectionType *rt; + int i; + + mono_error_init (error); + + if (!System_Reflection_ParameterInfo_array) { + MonoClass *klass; + + klass = mono_class_get_mono_parameter_info_class (); + + mono_memory_barrier (); + System_Reflection_ParameterInfo = klass; + + + klass = mono_array_class_get (klass, 1); + mono_memory_barrier (); + System_Reflection_ParameterInfo_array = klass; + } + + sig = mono_method_signature_checked (method, error); + if (!mono_error_ok (error)) + goto leave; + + if (!sig->param_count) { + res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, error); + if (!res) + goto leave; + + return res; + } + + /* Note: the cache is based on the address of the signature into the method + * since we already cache MethodInfos with the method as keys. + */ + CHECK_OBJECT (MonoArray*, &(method->signature), refclass); + + member = mono_method_get_object_checked (domain, method, refclass, error); + if (!member) + goto leave; + names = g_new (char *, sig->param_count); + mono_method_get_param_names (method, (const char **) names); + + mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1); + mono_method_get_marshal_info (method, mspecs); + + res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, error); + if (!res) + goto leave; + + pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo); + for (i = 0; i < sig->param_count; ++i) { + param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, error); + if (!param) + goto leave; + + rt = mono_type_get_object_checked (domain, sig->params [i], error); + if (!rt) + goto leave; + + MONO_OBJECT_SETREF (param, ClassImpl, rt); + + MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member); + + MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i])); + + param->PositionImpl = i; + param->AttrsImpl = sig->params [i]->attrs; + + if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) { + if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL) + MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing)); + else + MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull)); + } else { + + if (!blobs) { + blobs = g_new0 (char *, sig->param_count); + types = g_new0 (guint32, sig->param_count); + get_default_param_value_blobs (method, blobs, types); + } + + /* Build MonoType for the type from the Constant Table */ + if (!type) + type = g_new0 (MonoType, 1); + type->type = (MonoTypeEnum)types [i]; + type->data.klass = NULL; + if (types [i] == MONO_TYPE_CLASS) + type->data.klass = mono_defaults.object_class; + else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) { + /* For enums, types [i] contains the base type */ + + type->type = MONO_TYPE_VALUETYPE; + type->data.klass = mono_class_from_mono_type (sig->params [i]); + } else + type->data.klass = mono_class_from_mono_type (type); + + MonoObject *default_val_obj = mono_get_object_from_blob (domain, type, blobs [i], error); + if (!is_ok (error)) + goto leave; + MONO_OBJECT_SETREF (param, DefaultValueImpl, default_val_obj); + + /* Type in the Constant table is MONO_TYPE_CLASS for nulls */ + if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) { + if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL) + MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing)); + else + MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull)); + } + + } + + if (mspecs [i + 1]) { + MonoReflectionMarshalAsAttribute* mobj; + mobj = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1], error); + if (!mobj) + goto leave; + MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mobj); + } + + mono_array_setref (res, i, param); + } + +leave: + g_free (names); + g_free (blobs); + g_free (types); + g_free (type); + + if (sig) { + for (i = sig->param_count; i >= 0; i--) { + if (mspecs [i]) + mono_metadata_free_marshal_spec (mspecs [i]); + } + } + g_free (mspecs); + + if (!is_ok (error)) + return NULL; + + CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass); +} + +MonoArray* +mono_param_get_objects (MonoDomain *domain, MonoMethod *method) +{ + MonoError error; + MonoArray *result = mono_param_get_objects_internal (domain, method, NULL, &error); + mono_error_assert_ok (&error); + return result; +} + +/* + * mono_method_body_get_object: + * @domain: an app domain + * @method: a method + * + * Return an System.Reflection.MethodBody object representing the method @method. + */ +MonoReflectionMethodBody* +mono_method_body_get_object (MonoDomain *domain, MonoMethod *method) +{ + MonoError error; + MonoReflectionMethodBody *result = mono_method_body_get_object_checked (domain, method, &error); + mono_error_cleanup (&error); + return result; +} + +/** + * mono_method_body_get_object_checked: + * @domain: an app domain + * @method: a method + * @error: set on error + * + * Return an System.Reflection.MethodBody object representing the + * method @method. On failure, returns NULL and sets @error. + */ +MonoReflectionMethodBody* +mono_method_body_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoError *error) +{ + MonoReflectionMethodBody *ret; + MonoMethodHeader *header; + MonoImage *image; + MonoReflectionType *rt; + guint32 method_rva, local_var_sig_token; + char *ptr; + unsigned char format, flags; + int i; + + mono_error_init (error); + + /* for compatibility with .net */ + if (method_is_dynamic (method)) { + mono_error_set_generic_error (error, "System", "InvalidOperationException", ""); + return NULL; + } + + CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL); + + if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) || + (method->flags & METHOD_ATTRIBUTE_ABSTRACT) || + (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) || + (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') || + (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) + return NULL; + + image = method->klass->image; + header = mono_method_get_header_checked (method, error); + return_val_if_nok (error, NULL); + + if (!image_is_dynamic (image)) { + /* Obtain local vars signature token */ + method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA); + ptr = mono_image_rva_map (image, method_rva); + flags = *(const unsigned char *) ptr; + format = flags & METHOD_HEADER_FORMAT_MASK; + switch (format){ + case METHOD_HEADER_TINY_FORMAT: + local_var_sig_token = 0; + break; + case METHOD_HEADER_FAT_FORMAT: + ptr += 2; + ptr += 2; + ptr += 4; + local_var_sig_token = read32 (ptr); + break; + default: + g_assert_not_reached (); + } + } else + local_var_sig_token = 0; //FIXME + + ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, mono_class_get_method_body_class (), error); + if (!is_ok (error)) + goto fail; + + ret->init_locals = header->init_locals; + ret->max_stack = header->max_stack; + ret->local_var_sig_token = local_var_sig_token; + MonoArray *il_arr = mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size, error); + if (!is_ok (error)) + goto fail; + MONO_OBJECT_SETREF (ret, il, il_arr); + memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size); + + /* Locals */ + MonoArray *locals_arr = mono_array_new_cached (domain, mono_class_get_local_variable_info_class (), header->num_locals, error); + if (!is_ok (error)) + goto fail; + MONO_OBJECT_SETREF (ret, locals, locals_arr); + for (i = 0; i < header->num_locals; ++i) { + MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, mono_class_get_local_variable_info_class (), error); + if (!is_ok (error)) + goto fail; + + rt = mono_type_get_object_checked (domain, header->locals [i], error); + if (!is_ok (error)) + goto fail; + + MONO_OBJECT_SETREF (info, local_type, rt); + + info->is_pinned = header->locals [i]->pinned; + info->local_index = i; + mono_array_setref (ret->locals, i, info); + } + + /* Exceptions */ + MonoArray *exn_clauses = mono_array_new_cached (domain, mono_class_get_exception_handling_clause_class (), header->num_clauses, error); + if (!is_ok (error)) + goto fail; + MONO_OBJECT_SETREF (ret, clauses, exn_clauses); + for (i = 0; i < header->num_clauses; ++i) { + MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, mono_class_get_exception_handling_clause_class (), error); + if (!is_ok (error)) + goto fail; + MonoExceptionClause *clause = &header->clauses [i]; + + info->flags = clause->flags; + info->try_offset = clause->try_offset; + info->try_length = clause->try_len; + info->handler_offset = clause->handler_offset; + info->handler_length = clause->handler_len; + if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER) + info->filter_offset = clause->data.filter_offset; + else if (clause->data.catch_class) { + rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, error); + if (!is_ok (error)) + goto fail; + + MONO_OBJECT_SETREF (info, catch_type, rt); + } + + mono_array_setref (ret->clauses, i, info); + } + + mono_metadata_free_mh (header); + CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL); + return ret; + +fail: + mono_metadata_free_mh (header); + return NULL; +} + +/** + * mono_get_dbnull_object: + * @domain: Domain where the object lives + * + * Returns the System.DBNull.Value singleton object + * + * Used as the value for ParameterInfo.DefaultValue + */ +MonoObject * +mono_get_dbnull_object (MonoDomain *domain) +{ + MonoError error; + MonoObject *obj; + static MonoClassField *dbnull_value_field = NULL; + + if (!dbnull_value_field) { + MonoClass *dbnull_klass; + dbnull_klass = mono_class_get_dbnull_class (); + dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value"); + g_assert (dbnull_value_field); + } + obj = mono_field_get_value_object_checked (domain, dbnull_value_field, NULL, &error); + mono_error_assert_ok (&error); + return obj; +} + +static void +get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types) +{ + guint32 param_index, i, lastp, crow = 0; + guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE]; + gint32 idx; + + MonoClass *klass = method->klass; + MonoImage *image = klass->image; + MonoMethodSignature *methodsig = mono_method_signature (method); + + MonoTableInfo *constt; + MonoTableInfo *methodt; + MonoTableInfo *paramt; + + if (!methodsig->param_count) + return; + + mono_class_init (klass); + + if (image_is_dynamic (klass->image)) { + MonoReflectionMethodAux *aux; + if (method->is_inflated) + method = ((MonoMethodInflated*)method)->declaring; + aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method); + if (aux && aux->param_defaults) { + memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*)); + memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32)); + } + return; + } + + methodt = &klass->image->tables [MONO_TABLE_METHOD]; + paramt = &klass->image->tables [MONO_TABLE_PARAM]; + constt = &image->tables [MONO_TABLE_CONSTANT]; + + idx = mono_method_get_index (method) - 1; + g_assert (idx != -1); + + param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST); + if (idx + 1 < methodt->rows) + lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST); + else + lastp = paramt->rows + 1; + + for (i = param_index; i < lastp; ++i) { + guint32 paramseq; + + mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE); + paramseq = param_cols [MONO_PARAM_SEQUENCE]; + + if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)) + continue; + + crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1); + if (!crow) { + continue; + } + + mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE); + blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]); + types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE]; + } + + return; +} + +MonoObject * +mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob, MonoError *error) +{ + void *retval; + MonoClass *klass; + MonoObject *object; + MonoType *basetype = type; + + mono_error_init (error); + + if (!blob) + return NULL; + + klass = mono_class_from_mono_type (type); + if (klass->valuetype) { + object = mono_object_new_checked (domain, klass, error); + return_val_if_nok (error, NULL); + retval = ((gchar *) object + sizeof (MonoObject)); + if (klass->enumtype) + basetype = mono_class_enum_basetype (klass); + } else { + retval = &object; + } + + if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval, error)) + return object; + else + return NULL; +} + +static int +assembly_name_to_aname (MonoAssemblyName *assembly, char *p) { + int found_sep; + char *s; + gboolean quoted = FALSE; + + memset (assembly, 0, sizeof (MonoAssemblyName)); + assembly->culture = ""; + memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH); + + if (*p == '"') { + quoted = TRUE; + p++; + } + assembly->name = p; + while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p))) + p++; + if (quoted) { + if (*p != '"') + return 1; + *p = 0; + p++; + } + if (*p != ',') + return 1; + *p = 0; + /* Remove trailing whitespace */ + s = p - 1; + while (*s && g_ascii_isspace (*s)) + *s-- = 0; + p ++; + while (g_ascii_isspace (*p)) + p++; + while (*p) { + if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) { + p += 8; + assembly->major = strtoul (p, &s, 10); + if (s == p || *s != '.') + return 1; + p = ++s; + assembly->minor = strtoul (p, &s, 10); + if (s == p || *s != '.') + return 1; + p = ++s; + assembly->build = strtoul (p, &s, 10); + if (s == p || *s != '.') + return 1; + p = ++s; + assembly->revision = strtoul (p, &s, 10); + if (s == p) + return 1; + p = s; + } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) { + p += 8; + if (g_ascii_strncasecmp (p, "neutral", 7) == 0) { + assembly->culture = ""; + p += 7; + } else { + assembly->culture = p; + while (*p && *p != ',') { + p++; + } + } + } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) { + p += 15; + if (strncmp (p, "null", 4) == 0) { + p += 4; + } else { + int len; + gchar *start = p; + while (*p && *p != ',') { + p++; + } + len = (p - start + 1); + if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH) + len = MONO_PUBLIC_KEY_TOKEN_LENGTH; + g_strlcpy ((char*)assembly->public_key_token, start, len); + } + } else { + while (*p && *p != ',') + p++; + } + found_sep = 0; + while (g_ascii_isspace (*p) || *p == ',') { + *p++ = 0; + found_sep = 1; + continue; + } + /* failed */ + if (!found_sep) + return 1; + } + + return 0; +} + +/* + * mono_reflection_parse_type: + * @name: type name + * + * Parse a type name as accepted by the GetType () method and output the info + * extracted in the info structure. + * the name param will be mangled, so, make a copy before passing it to this function. + * The fields in info will be valid until the memory pointed to by name is valid. + * + * See also mono_type_get_name () below. + * + * Returns: 0 on parse error. + */ +static int +_mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed, + MonoTypeNameParse *info) +{ + char *start, *p, *w, *last_point, *startn; + int in_modifiers = 0; + int isbyref = 0, rank = 0, isptr = 0; + + start = p = w = name; + + //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse)) + memset (&info->assembly, 0, sizeof (MonoAssemblyName)); + info->name = info->name_space = NULL; + info->nested = NULL; + info->modifiers = NULL; + info->type_arguments = NULL; + + /* last_point separates the namespace from the name */ + last_point = NULL; + /* Skips spaces */ + while (*p == ' ') p++, start++, w++, name++; + + while (*p) { + switch (*p) { + case '+': + *p = 0; /* NULL terminate the name */ + startn = p + 1; + info->nested = g_list_append (info->nested, startn); + /* we have parsed the nesting namespace + name */ + if (info->name) + break; + if (last_point) { + info->name_space = start; + *last_point = 0; + info->name = last_point + 1; + } else { + info->name_space = (char *)""; + info->name = start; + } + break; + case '.': + last_point = p; + break; + case '\\': + ++p; + break; + case '&': + case '*': + case '[': + case ',': + case ']': + in_modifiers = 1; + break; + default: + break; + } + if (in_modifiers) + break; + // *w++ = *p++; + p++; + } + + if (!info->name) { + if (last_point) { + info->name_space = start; + *last_point = 0; + info->name = last_point + 1; + } else { + info->name_space = (char *)""; + info->name = start; + } + } + while (*p) { + switch (*p) { + case '&': + if (isbyref) /* only one level allowed by the spec */ + return 0; + isbyref = 1; + isptr = 0; + info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0)); + *p++ = 0; + break; + case '*': + if (isbyref) /* pointer to ref not okay */ + return 0; + info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1)); + isptr = 1; + *p++ = 0; + break; + case '[': + if (isbyref) /* array of ref and generic ref are not okay */ + return 0; + //Decide if it's an array of a generic argument list + *p++ = 0; + + if (!*p) //XXX test + return 0; + if (*p == ',' || *p == '*' || *p == ']') { //array + isptr = 0; + rank = 1; + while (*p) { + if (*p == ']') + break; + if (*p == ',') + rank++; + else if (*p == '*') /* '*' means unknown lower bound */ + info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2)); + else + return 0; + ++p; + } + if (*p++ != ']') + return 0; + info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank)); + } else { + if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test + return 0; + isptr = 0; + info->type_arguments = g_ptr_array_new (); + while (*p) { + MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1); + gboolean fqname = FALSE; + + g_ptr_array_add (info->type_arguments, subinfo); + + while (*p == ' ') p++; + if (*p == '[') { + p++; + fqname = TRUE; + } + + if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo)) + return 0; + + /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/ + if (fqname && (*p != ']')) { + char *aname; + + if (*p != ',') + return 0; + *p++ = 0; + + aname = p; + while (*p && (*p != ']')) + p++; + + if (*p != ']') + return 0; + + *p++ = 0; + while (*aname) { + if (g_ascii_isspace (*aname)) { + ++aname; + continue; + } + break; + } + if (!*aname || + !assembly_name_to_aname (&subinfo->assembly, aname)) + return 0; + } else if (fqname && (*p == ']')) { + *p++ = 0; + } + if (*p == ']') { + *p++ = 0; + break; + } else if (!*p) { + return 0; + } + *p++ = 0; + } + } + break; + case ']': + if (is_recursed) + goto end; + return 0; + case ',': + if (is_recursed) + goto end; + *p++ = 0; + while (*p) { + if (g_ascii_isspace (*p)) { + ++p; + continue; + } + break; + } + if (!*p) + return 0; /* missing assembly name */ + if (!assembly_name_to_aname (&info->assembly, p)) + return 0; + break; + default: + return 0; + } + if (info->assembly.name) + break; + } + // *w = 0; /* terminate class name */ + end: + if (!info->name || !*info->name) + return 0; + if (endptr) + *endptr = p; + /* add other consistency checks */ + return 1; +} + + +/** + * mono_identifier_unescape_type_name_chars: + * @identifier: the display name of a mono type + * + * Returns: + * The name in internal form, that is without escaping backslashes. + * + * The string is modified in place! + */ +char* +mono_identifier_unescape_type_name_chars(char* identifier) +{ + char *w, *r; + if (!identifier) + return NULL; + for (w = r = identifier; *r != 0; r++) + { + char c = *r; + if (c == '\\') { + r++; + if (*r == 0) + break; + c = *r; + } + *w = c; + w++; + } + if (w != r) + *w = 0; + return identifier; +} + +void +mono_identifier_unescape_info (MonoTypeNameParse* info); + +static void +unescape_each_type_argument(void* data, void* user_data) +{ + MonoTypeNameParse* info = (MonoTypeNameParse*)data; + mono_identifier_unescape_info (info); +} + +static void +unescape_each_nested_name (void* data, void* user_data) +{ + char* nested_name = (char*) data; + mono_identifier_unescape_type_name_chars(nested_name); +} + +/** + * mono_identifier_unescape_info: + * + * @info: a parsed display form of an (optionally assembly qualified) full type name. + * + * Returns: nothing. + * + * Destructively updates the info by unescaping the identifiers that + * comprise the type namespace, name, nested types (if any) and + * generic type arguments (if any). + * + * The resulting info has the names in internal form. + * + */ +void +mono_identifier_unescape_info (MonoTypeNameParse *info) +{ + if (!info) + return; + mono_identifier_unescape_type_name_chars(info->name_space); + mono_identifier_unescape_type_name_chars(info->name); + // but don't escape info->assembly + if (info->type_arguments) + g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL); + if (info->nested) + g_list_foreach(info->nested, &unescape_each_nested_name, NULL); +} + +int +mono_reflection_parse_type (char *name, MonoTypeNameParse *info) +{ + int ok = _mono_reflection_parse_type (name, NULL, FALSE, info); + if (ok) { + mono_identifier_unescape_info (info); + } + return ok; +} + +static MonoType* +_mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase, MonoError *error) +{ + gboolean type_resolve = FALSE; + MonoType *type; + MonoImage *rootimage = image; + + mono_error_init (error); + + if (info->assembly.name) { + MonoAssembly *assembly = mono_assembly_loaded (&info->assembly); + if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname)) + /* + * This could happen in the AOT compiler case when the search hook is not + * installed. + */ + assembly = image->assembly; + if (!assembly) { + /* then we must load the assembly ourselve - see #60439 */ + assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL); + if (!assembly) + return NULL; + } + image = assembly->image; + } else if (!image) { + image = mono_defaults.corlib; + } + + type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error); + if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) { + /* ignore the error and try again */ + mono_error_cleanup (error); + mono_error_init (error); + image = mono_defaults.corlib; + type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error); + } + + return type; +} + +/** + * mono_reflection_get_type_internal: + * + * Returns: may return NULL on success, sets error on failure. + */ +static MonoType* +mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error) +{ + MonoClass *klass; + GList *mod; + int modval; + gboolean bounded = FALSE; + + mono_error_init (error); + if (!image) + image = mono_defaults.corlib; + + if (!rootimage) + rootimage = mono_defaults.corlib; + + if (ignorecase) + klass = mono_class_from_name_case_checked (image, info->name_space, info->name, error); + else + klass = mono_class_from_name_checked (image, info->name_space, info->name, error); + + if (!klass) + return NULL; + + for (mod = info->nested; mod; mod = mod->next) { + gpointer iter = NULL; + MonoClass *parent; + + parent = klass; + mono_class_init (parent); + + while ((klass = mono_class_get_nested_types (parent, &iter))) { + char *lastp; + char *nested_name, *nested_nspace; + gboolean match = TRUE; + + lastp = strrchr ((const char *)mod->data, '.'); + if (lastp) { + /* Nested classes can have namespaces */ + int nspace_len; + + nested_name = g_strdup (lastp + 1); + nspace_len = lastp - (char*)mod->data; + nested_nspace = (char *)g_malloc (nspace_len + 1); + memcpy (nested_nspace, mod->data, nspace_len); + nested_nspace [nspace_len] = '\0'; + + } else { + nested_name = (char *)mod->data; + nested_nspace = NULL; + } + + if (nested_nspace) { + if (ignorecase) { + if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0)) + match = FALSE; + } else { + if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0)) + match = FALSE; + } + } + if (match) { + if (ignorecase) { + if (mono_utf8_strcasecmp (klass->name, nested_name) != 0) + match = FALSE; + } else { + if (strcmp (klass->name, nested_name) != 0) + match = FALSE; + } + } + if (lastp) { + g_free (nested_name); + g_free (nested_nspace); + } + if (match) + break; + } + + if (!klass) + break; + } + if (!klass) + return NULL; + + if (info->type_arguments) { + MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len); + MonoReflectionType *the_type; + MonoType *instance; + int i; + + for (i = 0; i < info->type_arguments->len; i++) { + MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i); + + type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase, error); + if (!type_args [i]) { + g_free (type_args); + return NULL; + } + } + + the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error); + if (!the_type) + return NULL; + + instance = mono_reflection_bind_generic_parameters ( + the_type, info->type_arguments->len, type_args, error); + + g_free (type_args); + if (!instance) + return NULL; + + klass = mono_class_from_mono_type (instance); + } + + for (mod = info->modifiers; mod; mod = mod->next) { + modval = GPOINTER_TO_UINT (mod->data); + if (!modval) { /* byref: must be last modifier */ + return &klass->this_arg; + } else if (modval == -1) { + klass = mono_ptr_class_get (&klass->byval_arg); + } else if (modval == -2) { + bounded = TRUE; + } else { /* array rank */ + klass = mono_bounded_array_class_get (klass, modval, bounded); + } + } + + return &klass->byval_arg; +} + +/* + * mono_reflection_get_type: + * @image: a metadata context + * @info: type description structure + * @ignorecase: flag for case-insensitive string compares + * @type_resolve: whenever type resolve was already tried + * + * Build a MonoType from the type description in @info. + * + */ + +MonoType* +mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) { + MonoError error; + MonoType *result = mono_reflection_get_type_with_rootimage (image, image, info, ignorecase, type_resolve, &error); + mono_error_cleanup (&error); + return result; +} + +/** + * mono_reflection_get_type_checked: + * @rootimage: the image of the currently active managed caller + * @image: a metadata context + * @info: type description structure + * @ignorecase: flag for case-insensitive string compares + * @type_resolve: whenever type resolve was already tried + * @error: set on error. + * + * Build a MonoType from the type description in @info. On failure returns NULL and sets @error. + * + */ +MonoType* +mono_reflection_get_type_checked (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error) { + mono_error_init (error); + return mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, type_resolve, error); +} + + +static MonoType* +mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error) +{ + MonoReflectionAssemblyBuilder *abuilder; + MonoType *type; + int i; + + mono_error_init (error); + g_assert (assembly_is_dynamic (assembly)); + abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object_checked (((MonoDynamicAssembly*)assembly)->domain, assembly, error); + if (!abuilder) + return NULL; + + /* Enumerate all modules */ + + type = NULL; + if (abuilder->modules) { + for (i = 0; i < mono_array_length (abuilder->modules); ++i) { + MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i); + type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase, error); + if (type) + break; + if (!mono_error_ok (error)) + return NULL; + } + } + + if (!type && abuilder->loaded_modules) { + for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) { + MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i); + type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase, error); + if (type) + break; + if (!mono_error_ok (error)) + return NULL; + } + } + + return type; +} + +MonoType* +mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error) +{ + MonoType *type; + MonoReflectionAssembly *assembly; + GString *fullName; + GList *mod; + + mono_error_init (error); + + if (image && image_is_dynamic (image)) + type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase, error); + else { + type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase, error); + } + return_val_if_nok (error, NULL); + + if (type) + return type; + if (!mono_domain_has_type_resolve (mono_domain_get ())) + return NULL; + + if (type_resolve) { + if (*type_resolve) + return NULL; + else + *type_resolve = TRUE; + } + + /* Reconstruct the type name */ + fullName = g_string_new (""); + if (info->name_space && (info->name_space [0] != '\0')) + g_string_printf (fullName, "%s.%s", info->name_space, info->name); + else + g_string_printf (fullName, "%s", info->name); + for (mod = info->nested; mod; mod = mod->next) + g_string_append_printf (fullName, "+%s", (char*)mod->data); + + assembly = mono_domain_try_type_resolve_checked ( mono_domain_get (), fullName->str, NULL, error); + if (!is_ok (error)) { + g_string_free (fullName, TRUE); + return NULL; + } + + if (assembly) { + if (assembly_is_dynamic (assembly->assembly)) + type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, + info, ignorecase, error); + else + type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, + info, ignorecase, error); + } + g_string_free (fullName, TRUE); + return_val_if_nok (error, NULL); + return type; +} + +void +mono_reflection_free_type_info (MonoTypeNameParse *info) +{ + g_list_free (info->modifiers); + g_list_free (info->nested); + + if (info->type_arguments) { + int i; + + for (i = 0; i < info->type_arguments->len; i++) { + MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i); + + mono_reflection_free_type_info (subinfo); + /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/ + g_free (subinfo); + } + + g_ptr_array_free (info->type_arguments, TRUE); + } +} + +/* + * mono_reflection_type_from_name: + * @name: type name. + * @image: a metadata context (can be NULL). + * + * Retrieves a MonoType from its @name. If the name is not fully qualified, + * it defaults to get the type from @image or, if @image is NULL or loading + * from it fails, uses corlib. + * + */ +MonoType* +mono_reflection_type_from_name (char *name, MonoImage *image) +{ + MonoError error; + MonoType *result = mono_reflection_type_from_name_checked (name, image, &error); + mono_error_cleanup (&error); + return result; +} + +/** + * mono_reflection_type_from_name_checked: + * @name: type name. + * @image: a metadata context (can be NULL). + * @error: set on errror. + * + * Retrieves a MonoType from its @name. If the name is not fully qualified, + * it defaults to get the type from @image or, if @image is NULL or loading + * from it fails, uses corlib. On failure returns NULL and sets @error. + * + */ +MonoType* +mono_reflection_type_from_name_checked (char *name, MonoImage *image, MonoError *error) +{ + MonoType *type = NULL; + MonoTypeNameParse info; + char *tmp; + + mono_error_init (error); + /* Make a copy since parse_type modifies its argument */ + tmp = g_strdup (name); + + /*g_print ("requested type %s\n", str);*/ + if (mono_reflection_parse_type (tmp, &info)) { + type = _mono_reflection_get_type_from_info (&info, image, FALSE, error); + if (!is_ok (error)) { + g_free (tmp); + mono_reflection_free_type_info (&info); + return NULL; + } + } + + g_free (tmp); + mono_reflection_free_type_info (&info); + return type; +} + +/* + * mono_reflection_get_token: + * + * Return the metadata token of OBJ which should be an object + * representing a metadata element. + */ +guint32 +mono_reflection_get_token (MonoObject *obj) +{ + MonoError error; + guint32 result = mono_reflection_get_token_checked (obj, &error); + mono_error_assert_ok (&error); + return result; +} + +/** + * mono_reflection_get_token_checked: + * @obj: the object + * @error: set on error + * + * Return the metadata token of @obj which should be an object + * representing a metadata element. On failure sets @error. + */ +guint32 +mono_reflection_get_token_checked (MonoObject *obj, MonoError *error) +{ + MonoClass *klass; + guint32 token = 0; + + mono_error_init (error); + + klass = obj->vtable->klass; + + if (strcmp (klass->name, "MethodBuilder") == 0) { + MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj; + + token = mb->table_idx | MONO_TOKEN_METHOD_DEF; + } else if (strcmp (klass->name, "ConstructorBuilder") == 0) { + MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj; + + token = mb->table_idx | MONO_TOKEN_METHOD_DEF; + } else if (strcmp (klass->name, "FieldBuilder") == 0) { + MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj; + + token = fb->table_idx | MONO_TOKEN_FIELD_DEF; + } else if (strcmp (klass->name, "TypeBuilder") == 0) { + MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj; + token = tb->table_idx | MONO_TOKEN_TYPE_DEF; + } else if (strcmp (klass->name, "RuntimeType") == 0) { + MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error); + return_val_if_nok (error, 0); + MonoClass *mc = mono_class_from_mono_type (type); + if (!mono_class_init (mc)) { + mono_error_set_for_class_failure (error, mc); + return 0; + } + + token = mc->type_token; + } else if (strcmp (klass->name, "MonoCMethod") == 0 || + strcmp (klass->name, "MonoMethod") == 0 || + strcmp (klass->name, "MonoGenericMethod") == 0 || + strcmp (klass->name, "MonoGenericCMethod") == 0) { + MonoReflectionMethod *m = (MonoReflectionMethod *)obj; + if (m->method->is_inflated) { + MonoMethodInflated *inflated = (MonoMethodInflated *) m->method; + return inflated->declaring->token; + } else { + token = m->method->token; + } + } else if (strcmp (klass->name, "MonoField") == 0) { + MonoReflectionField *f = (MonoReflectionField*)obj; + + token = mono_class_get_field_token (f->field); + } else if (strcmp (klass->name, "MonoProperty") == 0) { + MonoReflectionProperty *p = (MonoReflectionProperty*)obj; + + token = mono_class_get_property_token (p->property); + } else if (strcmp (klass->name, "MonoEvent") == 0) { + MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj; + + token = mono_class_get_event_token (p->event); + } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) { + MonoReflectionParameter *p = (MonoReflectionParameter*)obj; + MonoClass *member_class = mono_object_class (p->MemberImpl); + g_assert (mono_class_is_reflection_method_or_constructor (member_class)); + + token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl); + } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) { + MonoReflectionModule *m = (MonoReflectionModule*)obj; + + token = m->token; + } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) { + token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1); + } else { + mono_error_set_not_implemented (error, "MetadataToken is not supported for type '%s.%s'", + klass->name_space, klass->name); + return 0; + } + + return token; +} + + +gboolean +mono_reflection_is_usertype (MonoReflectionType *ref) +{ + MonoClass *klass = mono_object_class (ref); + return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0; +} + +/** + * mono_reflection_bind_generic_parameters: + * @type: a managed type object (which should be some kind of generic (instance? definition?)) + * @type_args: the number of type arguments to bind + * @types: array of type arguments + * @error: set on error + * + * Given a managed type object for a generic type instance, binds each of its arguments to the specified types. + * Returns the MonoType* for the resulting type instantiation. On failure returns NULL and sets @error. + */ +MonoType* +mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types, MonoError *error) +{ + MonoClass *klass; + MonoReflectionTypeBuilder *tb = NULL; + gboolean is_dynamic = FALSE; + MonoClass *geninst; + + mono_error_init (error); + + mono_loader_lock (); + + if (mono_is_sre_type_builder (mono_object_class (type))) { + tb = (MonoReflectionTypeBuilder *) type; + + is_dynamic = TRUE; + } else if (mono_is_sre_generic_instance (mono_object_class (type))) { + MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type; + MonoReflectionType *gtd = rgi->generic_type; + + if (mono_is_sre_type_builder (mono_object_class (gtd))) { + tb = (MonoReflectionTypeBuilder *)gtd; + is_dynamic = TRUE; + } + } + + /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */ + if (tb && tb->generic_container) { + if (!mono_reflection_create_generic_class (tb, error)) { + mono_loader_unlock (); + return NULL; + } + } + + MonoType *t = mono_reflection_type_get_handle (type, error); + if (!is_ok (error)) { + mono_loader_unlock (); + return NULL; + } + + klass = mono_class_from_mono_type (t); + if (!klass->generic_container) { + mono_loader_unlock (); + mono_error_set_type_load_class (error, klass, "Cannot bind generic parameters of a non-generic type"); + return NULL; + } + + if (klass->wastypebuilder) { + tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass); + + is_dynamic = TRUE; + } + + mono_loader_unlock (); + + geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic); + + return &geninst->byval_arg; +} + +MonoClass* +mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic) +{ + MonoGenericClass *gclass; + MonoGenericInst *inst; + + g_assert (klass->generic_container); + + inst = mono_metadata_get_generic_inst (type_argc, types); + gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic); + + return mono_generic_class_get_class (gclass); +} + +static MonoReflectionMethod* +reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types, MonoError *error) +{ + MonoClass *klass; + MonoMethod *method, *inflated; + MonoMethodInflated *imethod; + MonoGenericContext tmp_context; + MonoGenericInst *ginst; + MonoType **type_argv; + int count, i; + + mono_error_init (error); + + /*FIXME but this no longer should happen*/ + if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) { + method = mono_reflection_method_builder_to_mono_method ((MonoReflectionMethodBuilder*)rmethod, error); + return_val_if_nok (error, NULL); + } else { + method = rmethod->method; + } + + klass = method->klass; + + if (method->is_inflated) + method = ((MonoMethodInflated *) method)->declaring; + + count = mono_method_signature (method)->generic_param_count; + if (count != mono_array_length (types)) + return NULL; + + type_argv = g_new0 (MonoType *, count); + for (i = 0; i < count; i++) { + MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i); + type_argv [i] = mono_reflection_type_get_handle (garg, error); + if (!is_ok (error)) { + g_free (type_argv); + return NULL; + } + } + ginst = mono_metadata_get_generic_inst (count, type_argv); + g_free (type_argv); + + tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL; + tmp_context.method_inst = ginst; + + inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error); + mono_error_assert_ok (error); + imethod = (MonoMethodInflated *) inflated; + + /*FIXME but I think this is no longer necessary*/ + if (image_is_dynamic (method->klass->image)) { + MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image; + /* + * This table maps metadata structures representing inflated methods/fields + * to the reflection objects representing their generic definitions. + */ + mono_image_lock ((MonoImage*)image); + mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod); + mono_image_unlock ((MonoImage*)image); + } + + if (!mono_verifier_is_method_valid_generic_instantiation (inflated)) { + mono_error_set_argument (error, "typeArguments", "Invalid generic arguments"); + return NULL; + } + + MonoReflectionMethod *ret = mono_method_get_object_checked (mono_object_domain (rmethod), inflated, NULL, error); + return ret; +} + +MonoReflectionMethod* +ves_icall_MethodBuilder_MakeGenericMethod (MonoReflectionMethod *rmethod, MonoArray *types) +{ + MonoError error; + MonoReflectionMethod *result = reflection_bind_generic_method_parameters (rmethod, types, &error); + mono_error_set_pending_exception (&error); + return result; +} + +MonoReflectionMethod* +ves_icall_MonoMethod_MakeGenericMethod_impl (MonoReflectionMethod *rmethod, MonoArray *types) +{ + MonoError error; + MonoReflectionMethod *result = reflection_bind_generic_method_parameters (rmethod, types, &error); + mono_error_set_pending_exception (&error); + return result; +} + + +/* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */ +const static guint32 declsec_flags_map[] = { + 0x00000000, /* empty */ + MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */ + MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */ + MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */ + MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */ + MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */ + MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */ + MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */ + MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */ + MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */ + MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */ + MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */ + MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */ + MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */ + MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */ + MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */ + MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */ + MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */ + MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */ +}; + +/* + * Returns flags that includes all available security action associated to the handle. + * @token: metadata token (either for a class or a method) + * @image: image where resides the metadata. + */ +static guint32 +mono_declsec_get_flags (MonoImage *image, guint32 token) +{ + int index = mono_metadata_declsec_from_index (image, token); + MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY]; + guint32 result = 0; + guint32 action; + int i; + + /* HasSecurity can be present for other, not specially encoded, attributes, + e.g. SuppressUnmanagedCodeSecurityAttribute */ + if (index < 0) + return 0; + + for (i = index; i < t->rows; i++) { + guint32 cols [MONO_DECL_SECURITY_SIZE]; + + mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE); + if (cols [MONO_DECL_SECURITY_PARENT] != token) + break; + + action = cols [MONO_DECL_SECURITY_ACTION]; + if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) { + result |= declsec_flags_map [action]; + } else { + g_assert_not_reached (); + } + } + return result; +} + +/* + * Get the security actions (in the form of flags) associated with the specified method. + * + * @method: The method for which we want the declarative security flags. + * Return the declarative security flags for the method (only). + * + * Note: To keep MonoMethod size down we do not cache the declarative security flags + * (except for the stack modifiers which are kept in the MonoJitInfo structure) + */ +guint32 +mono_declsec_flags_from_method (MonoMethod *method) +{ + if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) { + /* FIXME: No cache (for the moment) */ + guint32 idx = mono_method_get_index (method); + idx <<= MONO_HAS_DECL_SECURITY_BITS; + idx |= MONO_HAS_DECL_SECURITY_METHODDEF; + return mono_declsec_get_flags (method->klass->image, idx); + } + return 0; +} + +/* + * Get the security actions (in the form of flags) associated with the specified class. + * + * @klass: The class for which we want the declarative security flags. + * Return the declarative security flags for the class. + * + * Note: We cache the flags inside the MonoClass structure as this will get + * called very often (at least for each method). + */ +guint32 +mono_declsec_flags_from_class (MonoClass *klass) +{ + if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) { + if (!klass->ext || !klass->ext->declsec_flags) { + guint32 idx; + + idx = mono_metadata_token_index (klass->type_token); + idx <<= MONO_HAS_DECL_SECURITY_BITS; + idx |= MONO_HAS_DECL_SECURITY_TYPEDEF; + mono_loader_lock (); + mono_class_alloc_ext (klass); + mono_loader_unlock (); + /* we cache the flags on classes */ + klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx); + } + return klass->ext->declsec_flags; + } + return 0; +} + +/* + * Get the security actions (in the form of flags) associated with the specified assembly. + * + * @assembly: The assembly for which we want the declarative security flags. + * Return the declarative security flags for the assembly. + */ +guint32 +mono_declsec_flags_from_assembly (MonoAssembly *assembly) +{ + guint32 idx = 1; /* there is only one assembly */ + idx <<= MONO_HAS_DECL_SECURITY_BITS; + idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY; + return mono_declsec_get_flags (assembly->image, idx); +} + + +/* + * Fill actions for the specific index (which may either be an encoded class token or + * an encoded method token) from the metadata image. + * Returns TRUE if some actions requiring code generation are present, FALSE otherwise. + */ +static MonoBoolean +fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions, + guint32 id_std, guint32 id_noncas, guint32 id_choice) +{ + MonoBoolean result = FALSE; + MonoTableInfo *t; + guint32 cols [MONO_DECL_SECURITY_SIZE]; + int index = mono_metadata_declsec_from_index (image, token); + int i; + + t = &image->tables [MONO_TABLE_DECLSECURITY]; + for (i = index; i < t->rows; i++) { + mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE); + + if (cols [MONO_DECL_SECURITY_PARENT] != token) + return result; + + /* if present only replace (class) permissions with method permissions */ + /* if empty accept either class or method permissions */ + if (cols [MONO_DECL_SECURITY_ACTION] == id_std) { + if (!actions->demand.blob) { + const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]); + actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET]; + actions->demand.blob = (char*) (blob + 2); + actions->demand.size = mono_metadata_decode_blob_size (blob, &blob); + result = TRUE; + } + } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) { + if (!actions->noncasdemand.blob) { + const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]); + actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET]; + actions->noncasdemand.blob = (char*) (blob + 2); + actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob); + result = TRUE; + } + } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) { + if (!actions->demandchoice.blob) { + const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]); + actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET]; + actions->demandchoice.blob = (char*) (blob + 2); + actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob); + result = TRUE; + } + } + } + + return result; +} + +static MonoBoolean +mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, + guint32 id_std, guint32 id_noncas, guint32 id_choice) +{ + guint32 idx = mono_metadata_token_index (klass->type_token); + idx <<= MONO_HAS_DECL_SECURITY_BITS; + idx |= MONO_HAS_DECL_SECURITY_TYPEDEF; + return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice); +} + +static MonoBoolean +mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, + guint32 id_std, guint32 id_noncas, guint32 id_choice) +{ + guint32 idx = mono_method_get_index (method); + idx <<= MONO_HAS_DECL_SECURITY_BITS; + idx |= MONO_HAS_DECL_SECURITY_METHODDEF; + return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice); +} + +/* + * Collect all actions (that requires to generate code in mini) assigned for + * the specified method. + * Note: Don't use the content of actions if the function return FALSE. + */ +MonoBoolean +mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands) +{ + guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | + MONO_DECLSEC_FLAG_DEMAND_CHOICE; + MonoBoolean result = FALSE; + guint32 flags; + + /* quick exit if no declarative security is present in the metadata */ + if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows) + return FALSE; + + /* we want the original as the wrapper is "free" of the security informations */ + if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) { + method = mono_marshal_method_from_wrapper (method); + if (!method) + return FALSE; + } + + /* First we look for method-level attributes */ + if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) { + mono_class_init (method->klass); + memset (demands, 0, sizeof (MonoDeclSecurityActions)); + + result = mono_declsec_get_method_demands_params (method, demands, + SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE); + } + + /* Here we use (or create) the class declarative cache to look for demands */ + flags = mono_declsec_flags_from_class (method->klass); + if (flags & mask) { + if (!result) { + mono_class_init (method->klass); + memset (demands, 0, sizeof (MonoDeclSecurityActions)); + } + result |= mono_declsec_get_class_demands_params (method->klass, demands, + SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE); + } + + /* The boolean return value is used as a shortcut in case nothing needs to + be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */ + return result; +} + + +/* + * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0). + * + * Note: Don't use the content of actions if the function return FALSE. + */ +MonoBoolean +mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod) +{ + MonoBoolean result = FALSE; + guint32 flags; + + /* quick exit if no declarative security is present in the metadata */ + if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows) + return FALSE; + + /* we want the original as the wrapper is "free" of the security informations */ + if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) { + method = mono_marshal_method_from_wrapper (method); + if (!method) + return FALSE; + } + + /* results are independant - zeroize both */ + memset (cmethod, 0, sizeof (MonoDeclSecurityActions)); + memset (klass, 0, sizeof (MonoDeclSecurityActions)); + + /* First we look for method-level attributes */ + if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) { + mono_class_init (method->klass); + + result = mono_declsec_get_method_demands_params (method, cmethod, + SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE); + } + + /* Here we use (or create) the class declarative cache to look for demands */ + flags = mono_declsec_flags_from_class (method->klass); + if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) { + mono_class_init (method->klass); + + result |= mono_declsec_get_class_demands_params (method->klass, klass, + SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE); + } + + return result; +} + +/* + * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0). + * + * @klass The inherited class - this is the class that provides the security check (attributes) + * @demans + * return TRUE if inheritance demands (any kind) are present, FALSE otherwise. + * + * Note: Don't use the content of actions if the function return FALSE. + */ +MonoBoolean +mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands) +{ + MonoBoolean result = FALSE; + guint32 flags; + + /* quick exit if no declarative security is present in the metadata */ + if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows) + return FALSE; + + /* Here we use (or create) the class declarative cache to look for demands */ + flags = mono_declsec_flags_from_class (klass); + if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) { + mono_class_init (klass); + memset (demands, 0, sizeof (MonoDeclSecurityActions)); + + result |= mono_declsec_get_class_demands_params (klass, demands, + SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE); + } + + return result; +} + +/* + * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0). + * + * Note: Don't use the content of actions if the function return FALSE. + */ +MonoBoolean +mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands) +{ + /* quick exit if no declarative security is present in the metadata */ + if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows) + return FALSE; + + /* we want the original as the wrapper is "free" of the security informations */ + if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) { + method = mono_marshal_method_from_wrapper (method); + if (!method) + return FALSE; + } + + if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) { + mono_class_init (method->klass); + memset (demands, 0, sizeof (MonoDeclSecurityActions)); + + return mono_declsec_get_method_demands_params (method, demands, + SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE); + } + return FALSE; +} + + +static MonoBoolean +get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry) +{ + guint32 cols [MONO_DECL_SECURITY_SIZE]; + MonoTableInfo *t; + int i; + + int index = mono_metadata_declsec_from_index (image, token); + if (index == -1) + return FALSE; + + t = &image->tables [MONO_TABLE_DECLSECURITY]; + for (i = index; i < t->rows; i++) { + mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE); + + /* shortcut - index are ordered */ + if (token != cols [MONO_DECL_SECURITY_PARENT]) + return FALSE; + + if (cols [MONO_DECL_SECURITY_ACTION] == action) { + const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]); + entry->blob = (char*) (metadata + 2); + entry->size = mono_metadata_decode_blob_size (metadata, &metadata); + return TRUE; + } + } + + return FALSE; +} + +MonoBoolean +mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry) +{ + if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) { + guint32 idx = mono_method_get_index (method); + idx <<= MONO_HAS_DECL_SECURITY_BITS; + idx |= MONO_HAS_DECL_SECURITY_METHODDEF; + return get_declsec_action (method->klass->image, idx, action, entry); + } + return FALSE; +} + +MonoBoolean +mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry) +{ + /* use cache */ + guint32 flags = mono_declsec_flags_from_class (klass); + if (declsec_flags_map [action] & flags) { + guint32 idx = mono_metadata_token_index (klass->type_token); + idx <<= MONO_HAS_DECL_SECURITY_BITS; + idx |= MONO_HAS_DECL_SECURITY_TYPEDEF; + return get_declsec_action (klass->image, idx, action, entry); + } + return FALSE; +} + +MonoBoolean +mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry) +{ + guint32 idx = 1; /* there is only one assembly */ + idx <<= MONO_HAS_DECL_SECURITY_BITS; + idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY; + + return get_declsec_action (assembly->image, idx, action, entry); +} + +gboolean +mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass, MonoError *error) +{ + MonoObject *res, *exc; + void *params [1]; + static MonoMethod *method = NULL; + + mono_error_init (error); + + if (method == NULL) { + method = mono_class_get_method_from_name (mono_class_get_type_builder_class (), "IsAssignableTo", 1); + g_assert (method); + } + + /* + * The result of mono_type_get_object_checked () might be a System.MonoType but we + * need a TypeBuilder so use mono_class_get_ref_info (klass). + */ + g_assert (mono_class_get_ref_info (klass)); + g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder")); + + params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, error); + return_val_if_nok (error, FALSE); + + MonoError inner_error; + res = mono_runtime_try_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc, &inner_error); + + if (exc || !is_ok (&inner_error)) { + mono_error_cleanup (&inner_error); + return FALSE; + } else + return *(MonoBoolean*)mono_object_unbox (res); +} + +/** + * mono_reflection_type_get_type: + * @reftype: the System.Type object + * + * Returns the MonoType* associated with the C# System.Type object @reftype. + */ +MonoType* +mono_reflection_type_get_type (MonoReflectionType *reftype) +{ + g_assert (reftype); + + MonoError error; + MonoType *result = mono_reflection_type_get_handle (reftype, &error); + mono_error_assert_ok (&error); + return result; +} + +/** + * mono_reflection_assembly_get_assembly: + * @refassembly: the System.Reflection.Assembly object + * + * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly. + */ +MonoAssembly* +mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly) +{ + g_assert (refassembly); + + return refassembly->assembly; +} + +/** + * mono_class_from_mono_type_handle: + * @reftype: the System.Type handle + * + * Returns the MonoClass* corresponding to the given type. + */ +MonoClass* +mono_class_from_mono_type_handle (MonoReflectionTypeHandle reftype) +{ + return mono_class_from_mono_type (MONO_HANDLE_RAW (reftype)->type); +} diff --git a/mono/metadata/reflection.c.REMOVED.git-id b/mono/metadata/reflection.c.REMOVED.git-id deleted file mode 100644 index b1c2ea89ff..0000000000 --- a/mono/metadata/reflection.c.REMOVED.git-id +++ /dev/null @@ -1 +0,0 @@ -9fbac024ad6e85933d31c735232b407130f89f93 \ No newline at end of file diff --git a/mono/metadata/reflection.h b/mono/metadata/reflection.h index 7484759db5..80e334ed34 100644 --- a/mono/metadata/reflection.h +++ b/mono/metadata/reflection.h @@ -102,6 +102,7 @@ MONO_API MonoCustomAttrInfo* mono_custom_attrs_from_field (MonoClass *klass, MONO_RT_EXTERNAL_ONLY MONO_API MonoCustomAttrInfo* mono_custom_attrs_from_param (MonoMethod *method, uint32_t param); MONO_API mono_bool mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass); +MONO_RT_EXTERNAL_ONLY MONO_API MonoObject* mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass); MONO_API void mono_custom_attrs_free (MonoCustomAttrInfo *ainfo); diff --git a/mono/metadata/remoting.c b/mono/metadata/remoting.c index 0afdec6960..30595ee541 100644 --- a/mono/metadata/remoting.c +++ b/mono/metadata/remoting.c @@ -198,8 +198,6 @@ mono_remoting_marshal_init (void) register_icall (mono_remoting_wrapper, "mono_remoting_wrapper", "object ptr ptr", FALSE); register_icall (mono_upgrade_remote_class_wrapper, "mono_upgrade_remote_class_wrapper", "void object object", FALSE); register_icall (mono_compile_method_icall, "mono_compile_method_icall", "ptr ptr", FALSE); - /* mono_load_remote_field_new_icall registered by mini-runtime.c */ - /* mono_store_remote_field_new_icall registered by mini-runtime.c */ } @@ -426,7 +424,7 @@ fail: * is_running_protected_wrapper () in threads.c and * mono_marshal_get_remoting_invoke () in remoting.c) */ - mono_error_raise_exception (&error); + mono_error_raise_exception (&error); /* OK to throw, see note */ return NULL; } @@ -1327,72 +1325,6 @@ mono_marshal_get_remoting_invoke_with_check (MonoMethod *method) return res; } -/* - * mono_marshal_get_ldfld_remote_wrapper: - * @klass: The return type - * - * This method generates a wrapper for calling mono_load_remote_field_new. - * The return type is ignored for now, as mono_load_remote_field_new () always - * returns an object. In the future, to optimize some codepaths, we might - * call a different function that takes a pointer to a valuetype, instead. - */ -MonoMethod * -mono_marshal_get_ldfld_remote_wrapper (MonoClass *klass) -{ - MonoMethodSignature *sig; - MonoMethodBuilder *mb; - MonoMethod *res; - static MonoMethod* cached = NULL; - - mono_marshal_lock_internal (); - if (cached) { - mono_marshal_unlock_internal (); - return cached; - } - mono_marshal_unlock_internal (); - - mb = mono_mb_new_no_dup_name (mono_defaults.object_class, "__mono_load_remote_field_new_wrapper", MONO_WRAPPER_LDFLD_REMOTE); - - mb->method->save_lmf = 1; - - sig = mono_metadata_signature_alloc (mono_defaults.corlib, 3); - sig->params [0] = &mono_defaults.object_class->byval_arg; - sig->params [1] = &mono_defaults.int_class->byval_arg; - sig->params [2] = &mono_defaults.int_class->byval_arg; - sig->ret = &mono_defaults.object_class->byval_arg; - -#ifndef DISABLE_JIT - mono_mb_emit_ldarg (mb, 0); - mono_mb_emit_ldarg (mb, 1); - mono_mb_emit_ldarg (mb, 2); - - mono_mb_emit_icall (mb, mono_load_remote_field_new_icall); - - mono_mb_emit_byte (mb, CEE_RET); -#endif - - mono_marshal_lock_internal (); - res = cached; - mono_marshal_unlock_internal (); - if (!res) { - MonoMethod *newm; - newm = mono_mb_create (mb, sig, 4, NULL); - mono_marshal_lock_internal (); - res = cached; - if (!res) { - res = newm; - cached = res; - mono_marshal_unlock_internal (); - } else { - mono_marshal_unlock_internal (); - mono_free_method (newm); - } - } - mono_mb_free (mb); - - return res; -} - /* * mono_marshal_get_ldfld_wrapper: * @type: the type of the field @@ -1412,6 +1344,7 @@ mono_marshal_get_ldfld_wrapper (MonoType *type) WrapperInfo *info; char *name; int t, pos0, pos1 = 0; + static MonoMethod* tp_load = NULL; type = mono_type_get_underlying_type (type); @@ -1442,6 +1375,13 @@ mono_marshal_get_ldfld_wrapper (MonoType *type) if ((res = mono_marshal_find_in_cache (cache, klass))) return res; +#ifndef DISABLE_REMOTING + if (!tp_load) { + tp_load = mono_class_get_method_from_name (mono_defaults.transparent_proxy_class, "LoadRemoteFieldNew", -1); + g_assert (tp_load != NULL); + } +#endif + /* we add the %p pointer value of klass because class names are not unique */ name = g_strdup_printf ("__ldfld_wrapper_%p_%s.%s", klass, klass->name_space, klass->name); mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_LDFLD); @@ -1458,11 +1398,12 @@ mono_marshal_get_ldfld_wrapper (MonoType *type) mono_mb_emit_ldarg (mb, 0); pos0 = mono_mb_emit_proxy_check (mb, CEE_BNE_UN); +#ifndef DISABLE_REMOTING mono_mb_emit_ldarg (mb, 0); mono_mb_emit_ldarg (mb, 1); mono_mb_emit_ldarg (mb, 2); - mono_mb_emit_managed_call (mb, mono_marshal_get_ldfld_remote_wrapper (klass), NULL); + mono_mb_emit_managed_call (mb, tp_load, NULL); /* csig = mono_metadata_signature_alloc (mono_defaults.corlib, 3); @@ -1482,6 +1423,7 @@ mono_marshal_get_ldfld_wrapper (MonoType *type) } else { mono_mb_emit_byte (mb, CEE_RET); } +#endif mono_mb_patch_branch (mb, pos0); @@ -1578,8 +1520,7 @@ mono_marshal_get_ldflda_wrapper (MonoType *type) klass = mono_defaults.array_class; } else if (type->type == MONO_TYPE_VALUETYPE) { klass = type->data.klass; - } else if (t == MONO_TYPE_OBJECT || t == MONO_TYPE_CLASS || t == MONO_TYPE_STRING || - t == MONO_TYPE_CLASS) { + } else if (t == MONO_TYPE_OBJECT || t == MONO_TYPE_CLASS || t == MONO_TYPE_STRING) { klass = mono_defaults.object_class; } else if (t == MONO_TYPE_PTR || t == MONO_TYPE_FNPTR) { klass = mono_defaults.int_class; @@ -1677,73 +1618,6 @@ mono_marshal_get_ldflda_wrapper (MonoType *type) return res; } -/* - * mono_marshal_get_stfld_remote_wrapper: - * klass: The type of the field - * - * This function generates a wrapper for calling mono_store_remote_field_new - * with the appropriate signature. - * Similarly to mono_marshal_get_ldfld_remote_wrapper () this doesn't depend on the - * klass argument anymore. - */ -MonoMethod * -mono_marshal_get_stfld_remote_wrapper (MonoClass *klass) -{ - MonoMethodSignature *sig; - MonoMethodBuilder *mb; - MonoMethod *res; - static MonoMethod *cached = NULL; - - mono_marshal_lock_internal (); - if (cached) { - mono_marshal_unlock_internal (); - return cached; - } - mono_marshal_unlock_internal (); - - mb = mono_mb_new_no_dup_name (mono_defaults.object_class, "__mono_store_remote_field_new_wrapper", MONO_WRAPPER_STFLD_REMOTE); - - mb->method->save_lmf = 1; - - sig = mono_metadata_signature_alloc (mono_defaults.corlib, 4); - sig->params [0] = &mono_defaults.object_class->byval_arg; - sig->params [1] = &mono_defaults.int_class->byval_arg; - sig->params [2] = &mono_defaults.int_class->byval_arg; - sig->params [3] = &mono_defaults.object_class->byval_arg; - sig->ret = &mono_defaults.void_class->byval_arg; - -#ifndef DISABLE_JIT - mono_mb_emit_ldarg (mb, 0); - mono_mb_emit_ldarg (mb, 1); - mono_mb_emit_ldarg (mb, 2); - mono_mb_emit_ldarg (mb, 3); - - mono_mb_emit_icall (mb, mono_store_remote_field_new_icall); - - mono_mb_emit_byte (mb, CEE_RET); -#endif - - mono_marshal_lock_internal (); - res = cached; - mono_marshal_unlock_internal (); - if (!res) { - MonoMethod *newm; - newm = mono_mb_create (mb, sig, 6, NULL); - mono_marshal_lock_internal (); - res = cached; - if (!res) { - res = newm; - cached = res; - mono_marshal_unlock_internal (); - } else { - mono_marshal_unlock_internal (); - mono_free_method (newm); - } - } - mono_mb_free (mb); - - return res; -} /* * mono_marshal_get_stfld_wrapper: @@ -1764,6 +1638,7 @@ mono_marshal_get_stfld_wrapper (MonoType *type) WrapperInfo *info; char *name; int t, pos; + static MonoMethod *tp_store = NULL; type = mono_type_get_underlying_type (type); t = type->type; @@ -1793,6 +1668,13 @@ mono_marshal_get_stfld_wrapper (MonoType *type) if ((res = mono_marshal_find_in_cache (cache, klass))) return res; +#ifndef DISABLE_REMOTING + if (!tp_store) { + tp_store = mono_class_get_method_from_name (mono_defaults.transparent_proxy_class, "StoreRemoteField", -1); + g_assert (tp_store != NULL); + } +#endif + /* we add the %p pointer value of klass because class names are not unique */ name = g_strdup_printf ("__stfld_wrapper_%p_%s.%s", klass, klass->name_space, klass->name); mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_STFLD); @@ -1810,6 +1692,7 @@ mono_marshal_get_stfld_wrapper (MonoType *type) mono_mb_emit_ldarg (mb, 0); pos = mono_mb_emit_proxy_check (mb, CEE_BNE_UN); +#ifndef DISABLE_REMOTING mono_mb_emit_ldarg (mb, 0); mono_mb_emit_ldarg (mb, 1); mono_mb_emit_ldarg (mb, 2); @@ -1817,9 +1700,10 @@ mono_marshal_get_stfld_wrapper (MonoType *type) if (klass->valuetype) mono_mb_emit_op (mb, CEE_BOX, klass); - mono_mb_emit_managed_call (mb, mono_marshal_get_stfld_remote_wrapper (klass), NULL); + mono_mb_emit_managed_call (mb, tp_store, NULL); mono_mb_emit_byte (mb, CEE_RET); +#endif mono_mb_patch_branch (mb, pos); diff --git a/mono/metadata/remoting.h b/mono/metadata/remoting.h index 9b495b2fb5..b0307aed93 100644 --- a/mono/metadata/remoting.h +++ b/mono/metadata/remoting.h @@ -38,12 +38,6 @@ mono_marshal_get_ldfld_wrapper (MonoType *type); MonoMethod * mono_marshal_get_ldflda_wrapper (MonoType *type); -MonoMethod * -mono_marshal_get_ldfld_remote_wrapper (MonoClass *klass); - -MonoMethod * -mono_marshal_get_stfld_remote_wrapper (MonoClass *klass); - MonoMethod * mono_marshal_get_proxy_cancast (MonoClass *klass); diff --git a/mono/metadata/sgen-bridge-internals.h b/mono/metadata/sgen-bridge-internals.h index c5ad090b6c..09224b2f15 100644 --- a/mono/metadata/sgen-bridge-internals.h +++ b/mono/metadata/sgen-bridge-internals.h @@ -33,9 +33,16 @@ void sgen_bridge_describe_pointer (GCObject *object); gboolean sgen_is_bridge_object (GCObject *obj); void sgen_mark_bridge_object (GCObject *obj); +gboolean sgen_bridge_handle_gc_param (const char *opt); gboolean sgen_bridge_handle_gc_debug (const char *opt); void sgen_bridge_print_gc_debug_usage (void); +typedef struct { + char *dump_prefix; + gboolean accounting; + gboolean scc_precise_merge; // Used by Tarjan +} SgenBridgeProcessorConfig; + typedef struct { void (*reset_data) (void); void (*processing_stw_step) (void); @@ -44,8 +51,9 @@ typedef struct { MonoGCBridgeObjectKind (*class_kind) (MonoClass *klass); void (*register_finalized_object) (GCObject *object); void (*describe_pointer) (GCObject *object); - void (*enable_accounting) (void); - void (*set_dump_prefix) (const char *prefix); + + /* Should be called once, immediately after init */ + void (*set_config) (const SgenBridgeProcessorConfig *); /* * These are set by processing_build_callback_data(). diff --git a/mono/metadata/sgen-bridge.c b/mono/metadata/sgen-bridge.c index 006e68c501..7ec2d4386d 100644 --- a/mono/metadata/sgen-bridge.c +++ b/mono/metadata/sgen-bridge.c @@ -33,6 +33,8 @@ typedef enum { static BridgeProcessorSelection bridge_processor_selection = BRIDGE_PROCESSOR_DEFAULT; // Most recently requested callbacks static MonoGCBridgeCallbacks pending_bridge_callbacks; +// Configuration to be passed to bridge processor after init +static SgenBridgeProcessorConfig bridge_processor_config; // Currently-in-use callbacks MonoGCBridgeCallbacks bridge_callbacks; @@ -84,6 +86,12 @@ bridge_processor_name (const char *name) } } +static gboolean +bridge_processor_started () +{ + return bridge_processor.reset_data != NULL; +} + // Initialize a single bridge processor static void init_bridge_processor (SgenBridgeProcessor *processor, BridgeProcessorSelection selection) @@ -133,9 +141,17 @@ sgen_init_bridge () bridge_callbacks = pending_bridge_callbacks; // If a bridge was registered but there is no bridge processor yet - if (bridge_callbacks.cross_references && !bridge_processor.reset_data) + if (bridge_callbacks.cross_references && !bridge_processor_started ()) { init_bridge_processor (&bridge_processor, bridge_processor_selection); + if (bridge_processor.set_config) + bridge_processor.set_config (&bridge_processor_config); + + // Config is no longer needed so free its memory + free (bridge_processor_config.dump_prefix); + bridge_processor_config.dump_prefix = NULL; + } + sgen_gc_unlock (); } } @@ -147,7 +163,7 @@ sgen_set_bridge_implementation (const char *name) if (selection == BRIDGE_PROCESSOR_INVALID) g_warning ("Invalid value for bridge processor implementation, valid values are: 'new', 'old' and 'tarjan'."); - else if (bridge_processor.reset_data) + else if (bridge_processor_started ()) g_warning ("Cannot set bridge processor implementation once bridge has already started"); else bridge_processor_selection = selection; @@ -480,12 +496,9 @@ sgen_bridge_describe_pointer (GCObject *obj) static void set_dump_prefix (const char *prefix) { - if (!bridge_processor.set_dump_prefix) { - fprintf (stderr, "Warning: Bridge implementation does not support dumping - ignoring.\n"); - return; - } - - bridge_processor.set_dump_prefix (prefix); + if (bridge_processor_config.dump_prefix) + free (bridge_processor_config.dump_prefix); + bridge_processor_config.dump_prefix = strdup (prefix); } /* Test support code */ @@ -652,22 +665,39 @@ register_test_bridge_callbacks (const char *bridge_class_name) mono_gc_register_bridge_callbacks (&callbacks); } +gboolean +sgen_bridge_handle_gc_param (const char *opt) +{ + g_assert (!bridge_processor_started ()); + + if (!strcmp (opt, "bridge-require-precise-merge")) { + bridge_processor_config.scc_precise_merge = TRUE; + } else { + return FALSE; + } + + return TRUE; +} + gboolean sgen_bridge_handle_gc_debug (const char *opt) { + g_assert (!bridge_processor_started ()); + if (g_str_has_prefix (opt, "bridge=")) { opt = strchr (opt, '=') + 1; register_test_bridge_callbacks (g_strdup (opt)); } else if (!strcmp (opt, "enable-bridge-accounting")) { - bridge_processor.enable_accounting (); + bridge_processor_config.accounting = TRUE; } else if (g_str_has_prefix (opt, "bridge-dump=")) { char *prefix = strchr (opt, '=') + 1; - set_dump_prefix (prefix); + set_dump_prefix(prefix); } else if (g_str_has_prefix (opt, "bridge-compare-to=")) { const char *name = strchr (opt, '=') + 1; BridgeProcessorSelection selection = bridge_processor_name (name); if (selection != BRIDGE_PROCESSOR_INVALID) { + // Compare processor doesn't get config init_bridge_processor (&compare_to_bridge_processor, selection); } else { g_warning ("Invalid bridge implementation to compare against - ignoring."); diff --git a/mono/metadata/sgen-bridge.h b/mono/metadata/sgen-bridge.h index ea952efe10..a03b0a81bf 100644 --- a/mono/metadata/sgen-bridge.h +++ b/mono/metadata/sgen-bridge.h @@ -9,20 +9,23 @@ * unreachable objects. We use it in monodroid to do garbage collection across * the Mono and Java heaps. * - * The client can designate some objects as "bridged", which means that they - * participate in the bridge processing step once SGen considers them + * The client (Monodroid) can designate some objects as "bridged", which means + * that they participate in the bridge processing step once SGen considers them * unreachable, i.e., dead. Bridged objects must be registered for * finalization. * * When SGen is done marking, it puts together a list of all dead bridged - * objects and then does a strongly connected component analysis over their - * object graph. That graph will usually contain non-bridged objects, too. + * objects. This is passed to the bridge processor, which does an analysis to + * simplify the graph: It replaces strongly-connected components with single + * nodes, and may remove nodes corresponding to components which do not contain + * bridged objects. * - * The output of the SCC analysis is passed to the `cross_references()` - * callback. It is expected to set the `is_alive` flag on those strongly - * connected components that it wishes to be kept alive. Only bridged objects - * will be reported to the callback, i.e., non-bridged objects are removed from - * the callback graph. + * The output of the SCC analysis is passed to the client's `cross_references()` + * callback. This consists of 2 arrays, an array of SCCs (MonoGCBridgeSCC), + * and an array of "xrefs" (edges between SCCs, MonoGCBridgeXRef). Edges are + * encoded as pairs of "API indices", ie indexes in the SCC array. The client + * is expected to set the `is_alive` flag on those strongly connected components + * that it wishes to be kept alive. * * In monodroid each bridged object has a corresponding Java mirror object. In * the bridge callback it reifies the Mono object graph in the Java heap so that @@ -37,6 +40,10 @@ * point all links to bridged objects that don't have `is_alive` set are nulled. * Note that weak links to non-bridged objects reachable from bridged objects * are not nulled. This might be considered a bug. + * + * There are three different implementations of the bridge processor, each of + * which implements 8 callbacks (see SgenBridgeProcessor). The implementations + * differ in the algorithm they use to compute the "simplified" SCC graph. */ #ifndef _MONO_SGEN_BRIDGE_H_ @@ -47,7 +54,7 @@ MONO_BEGIN_DECLS enum { - SGEN_BRIDGE_VERSION = 4 + SGEN_BRIDGE_VERSION = 5 }; typedef enum { diff --git a/mono/metadata/sgen-client-mono.h b/mono/metadata/sgen-client-mono.h index 0c36133e1c..eee26b7060 100644 --- a/mono/metadata/sgen-client-mono.h +++ b/mono/metadata/sgen-client-mono.h @@ -84,6 +84,7 @@ extern void mono_sgen_init_stw (void); enum { INTERNAL_MEM_EPHEMERON_LINK = INTERNAL_MEM_FIRST_CLIENT, + INTERNAL_MEM_MOVED_OBJECT, INTERNAL_MEM_MAX }; @@ -694,6 +695,11 @@ sgen_client_binary_protocol_header (long long check, int version, int ptr_size, { } +static void G_GNUC_UNUSED +sgen_client_binary_protocol_pin_stats (int objects_pinned_in_nursery, size_t bytes_pinned_in_nursery, int objects_pinned_in_major, size_t bytes_pinned_in_major) +{ +} + int sgen_thread_handshake (BOOL suspend); gboolean sgen_suspend_thread (SgenThreadInfo *info); gboolean sgen_resume_thread (SgenThreadInfo *info); diff --git a/mono/metadata/sgen-dynarray.h b/mono/metadata/sgen-dynarray.h new file mode 100644 index 0000000000..f5a6a61be6 --- /dev/null +++ b/mono/metadata/sgen-dynarray.h @@ -0,0 +1,346 @@ +/* + * Copyright 2016 Xamarin, Inc. + * + * Licensed under the MIT license. See LICENSE file in the project root for full license information. + */ + + // Growable array implementation used by sgen-new-bridge and sgen-tarjan-bridge. + +typedef struct { + int size; + int capacity; /* if negative, data points to another DynArray's data */ + char *data; +} DynArray; + +/*Specializations*/ + +// IntArray supports an optimization (in sgen-new-bridge.c): If capacity is less than 0 it is a "copy" and does not own its buffer. +typedef struct { + DynArray array; +} DynIntArray; + +// PtrArray supports an optimization: If size is equal to 1 it is a "singleton" and data points to the single held item, not to a buffer. +typedef struct { + DynArray array; +} DynPtrArray; + +typedef struct { + DynArray array; +} DynSCCArray; + +static void +dyn_array_init (DynArray *da) +{ + da->size = 0; + da->capacity = 0; + da->data = NULL; +} + +static void +dyn_array_uninit (DynArray *da, int elem_size) +{ + if (da->capacity < 0) { + dyn_array_init (da); + return; + } + + if (da->capacity == 0) + return; + + sgen_free_internal_dynamic (da->data, elem_size * da->capacity, INTERNAL_MEM_BRIDGE_DATA); + da->data = NULL; +} + +static void +dyn_array_empty (DynArray *da) +{ + if (da->capacity < 0) + dyn_array_init (da); + else + da->size = 0; +} + +static char * +dyn_array_ensure_capacity_internal (DynArray *da, int capacity, int elem_size) +{ + if (da->capacity <= 0) + da->capacity = 2; + while (capacity > da->capacity) + da->capacity *= 2; + + return (char *)sgen_alloc_internal_dynamic (elem_size * da->capacity, INTERNAL_MEM_BRIDGE_DATA, TRUE); +} + +static void +dyn_array_ensure_capacity (DynArray *da, int capacity, int elem_size) +{ + int old_capacity = da->capacity; + char *new_data; + + g_assert (capacity > 0); + + if (capacity <= old_capacity) + return; + + new_data = dyn_array_ensure_capacity_internal (da, capacity, elem_size); + memcpy (new_data, da->data, elem_size * da->size); + if (old_capacity > 0) + sgen_free_internal_dynamic (da->data, elem_size * old_capacity, INTERNAL_MEM_BRIDGE_DATA); + da->data = new_data; +} + +static gboolean +dyn_array_is_copy (DynArray *da) +{ + return da->capacity < 0; +} + +static void +dyn_array_ensure_independent (DynArray *da, int elem_size) +{ + if (!dyn_array_is_copy (da)) + return; + dyn_array_ensure_capacity (da, da->size, elem_size); + g_assert (da->capacity > 0); +} + +static void* +dyn_array_add (DynArray *da, int elem_size) +{ + void *p; + + dyn_array_ensure_capacity (da, da->size + 1, elem_size); + + p = da->data + da->size * elem_size; + ++da->size; + return p; +} + +static void +dyn_array_copy (DynArray *dst, DynArray *src, int elem_size) +{ + dyn_array_uninit (dst, elem_size); + + if (src->size == 0) + return; + + dst->size = src->size; + dst->capacity = -1; + dst->data = src->data; +} + +/* int */ +static void +dyn_array_int_init (DynIntArray *da) +{ + dyn_array_init (&da->array); +} + +static void +dyn_array_int_uninit (DynIntArray *da) +{ + dyn_array_uninit (&da->array, sizeof (int)); +} + +static int +dyn_array_int_size (DynIntArray *da) +{ + return da->array.size; +} + +#ifdef NEW_XREFS +static void +dyn_array_int_empty (DynIntArray *da) +{ + dyn_array_empty (&da->array); +} +#endif + +static void +dyn_array_int_add (DynIntArray *da, int x) +{ + int *p = (int *)dyn_array_add (&da->array, sizeof (int)); + *p = x; +} + +static int +dyn_array_int_get (DynIntArray *da, int x) +{ + return ((int*)da->array.data)[x]; +} + +#ifdef NEW_XREFS +static void +dyn_array_int_set (DynIntArray *da, int idx, int val) +{ + ((int*)da->array.data)[idx] = val; +} +#endif + +static void +dyn_array_int_ensure_independent (DynIntArray *da) +{ + dyn_array_ensure_independent (&da->array, sizeof (int)); +} + +static void +dyn_array_int_copy (DynIntArray *dst, DynIntArray *src) +{ + dyn_array_copy (&dst->array, &src->array, sizeof (int)); +} + +static gboolean +dyn_array_int_is_copy (DynIntArray *da) +{ + return dyn_array_is_copy (&da->array); +} + +/* ptr */ + +static void +dyn_array_ptr_init (DynPtrArray *da) +{ + dyn_array_init (&da->array); +} + +static void +dyn_array_ptr_uninit (DynPtrArray *da) +{ +#ifdef OPTIMIZATION_SINGLETON_DYN_ARRAY + if (da->array.capacity == 1) + dyn_array_ptr_init (da); + else +#endif + dyn_array_uninit (&da->array, sizeof (void*)); +} + +static int +dyn_array_ptr_size (DynPtrArray *da) +{ + return da->array.size; +} + +static void +dyn_array_ptr_empty (DynPtrArray *da) +{ +#ifdef OPTIMIZATION_SINGLETON_DYN_ARRAY + if (da->array.capacity == 1) + dyn_array_ptr_init (da); + else +#endif + dyn_array_empty (&da->array); +} + +static void* +dyn_array_ptr_get (DynPtrArray *da, int x) +{ +#ifdef OPTIMIZATION_SINGLETON_DYN_ARRAY + if (da->array.capacity == 1) { + g_assert (x == 0); + return da->array.data; + } +#endif + return ((void**)da->array.data)[x]; +} + +static void +dyn_array_ptr_set (DynPtrArray *da, int x, void *ptr) +{ +#ifdef OPTIMIZATION_SINGLETON_DYN_ARRAY + if (da->array.capacity == 1) { + g_assert (x == 0); + da->array.data = ptr; + } else +#endif + { + ((void**)da->array.data)[x] = ptr; + } +} + +static void +dyn_array_ptr_add (DynPtrArray *da, void *ptr) +{ + void **p; + +#ifdef OPTIMIZATION_SINGLETON_DYN_ARRAY + if (da->array.capacity == 0) { + da->array.capacity = 1; + da->array.size = 1; + p = (void**)&da->array.data; + } else if (da->array.capacity == 1) { + void *ptr0 = da->array.data; + void **p0; + dyn_array_init (&da->array); + p0 = (void **)dyn_array_add (&da->array, sizeof (void*)); + *p0 = ptr0; + p = (void **)dyn_array_add (&da->array, sizeof (void*)); + } else +#endif + { + p = (void **)dyn_array_add (&da->array, sizeof (void*)); + } + *p = ptr; +} + +#define dyn_array_ptr_push dyn_array_ptr_add + +static void* +dyn_array_ptr_pop (DynPtrArray *da) +{ + int size = da->array.size; + void *p; + g_assert (size > 0); +#ifdef OPTIMIZATION_SINGLETON_DYN_ARRAY + if (da->array.capacity == 1) { + p = dyn_array_ptr_get (da, 0); + dyn_array_init (&da->array); + } else +#endif + { + g_assert (da->array.capacity > 1); + dyn_array_ensure_independent (&da->array, sizeof (void*)); + p = dyn_array_ptr_get (da, size - 1); + --da->array.size; + } + return p; +} + +static void +dyn_array_ptr_ensure_capacity (DynPtrArray *da, int capacity) +{ +#ifdef OPTIMIZATION_SINGLETON_DYN_ARRAY + if (capacity == 1 && da->array.capacity < 1) { + da->array.capacity = 1; + } else if (da->array.capacity == 1) // TODO size==1 + { + if (capacity > 1) + { + void *ptr = dyn_array_ptr_get (da, 0); + da->array.data = dyn_array_ensure_capacity_internal(&da->array, capacity, sizeof (void*)); + dyn_array_ptr_set (da, 0, ptr); + } + } +#endif + { + dyn_array_ensure_capacity (&da->array, capacity, sizeof (void*)); + } +} + +static void +dyn_array_ptr_set_all (DynPtrArray *dst, DynPtrArray *src) +{ + const int copysize = src->array.size; + if (copysize > 0) { + dyn_array_ptr_ensure_capacity (dst, copysize); + +#ifdef OPTIMIZATION_SINGLETON_DYN_ARRAY + if (copysize == 1) { + dyn_array_ptr_set (dst, 0, dyn_array_ptr_get (src, 0)); + } else +#endif + { + memcpy (dst->array.data, src->array.data, copysize * sizeof (void*)); + } + } + dst->array.size = src->array.size; +} diff --git a/mono/metadata/sgen-mono.c b/mono/metadata/sgen-mono.c index 7bfe3c4e60..6b53cc35f2 100644 --- a/mono/metadata/sgen-mono.c +++ b/mono/metadata/sgen-mono.c @@ -16,6 +16,7 @@ #include "sgen/sgen-client.h" #include "sgen/sgen-cardtable.h" #include "sgen/sgen-pinning.h" +#include "sgen/sgen-thread-pool.h" #include "metadata/marshal.h" #include "metadata/method-builder.h" #include "metadata/abi-details.h" @@ -140,7 +141,8 @@ mono_gc_wbarrier_object_copy (MonoObject* obj, MonoObject *src) HEAVY_STAT (++stat_wbarrier_object_copy); - if (sgen_ptr_in_nursery (obj) || ptr_on_stack (obj) || !SGEN_OBJECT_HAS_REFERENCES (src)) { + SGEN_ASSERT (6, !ptr_on_stack (obj), "Why is this called for a non-reference type?"); + if (sgen_ptr_in_nursery (obj) || !SGEN_OBJECT_HAS_REFERENCES (src)) { size = mono_object_class (obj)->instance_size; mono_gc_memmove_aligned ((char*)obj + sizeof (MonoObject), (char*)src + sizeof (MonoObject), size - sizeof (MonoObject)); @@ -188,13 +190,13 @@ static MonoMethod *write_barrier_noconc_method; gboolean sgen_is_critical_method (MonoMethod *method) { - return (method == write_barrier_conc_method || method == write_barrier_noconc_method || sgen_is_managed_allocator (method)); + return sgen_is_managed_allocator (method); } gboolean sgen_has_critical_method (void) { - return write_barrier_conc_method || write_barrier_noconc_method || sgen_has_managed_allocator (); + return sgen_has_managed_allocator (); } #ifndef DISABLE_JIT @@ -900,7 +902,7 @@ mono_gc_clear_domain (MonoDomain * domain) major_collector.iterate_objects (ITERATE_OBJECTS_SWEEP_PINNED, (IterateObjectCallbackFunc)clear_domain_free_major_pinned_object_callback, domain); if (domain == mono_get_root_domain ()) { - sgen_pin_stats_print_class_stats (); + sgen_pin_stats_report (); sgen_object_layout_dump (stdout); } @@ -916,20 +918,12 @@ mono_gc_clear_domain (MonoDomain * domain) * Allocation */ -static gboolean alloc_events = FALSE; - -void -mono_gc_enable_alloc_events (void) -{ - alloc_events = TRUE; -} - void* mono_gc_alloc_obj (MonoVTable *vtable, size_t size) { MonoObject *obj = sgen_alloc_obj (vtable, size); - if (G_UNLIKELY (alloc_events)) { + if (G_UNLIKELY (mono_profiler_events & MONO_PROFILE_ALLOCATIONS)) { if (obj) mono_profiler_allocation (obj); } @@ -942,7 +936,7 @@ mono_gc_alloc_pinned_obj (MonoVTable *vtable, size_t size) { MonoObject *obj = sgen_alloc_obj_pinned (vtable, size); - if (G_UNLIKELY (alloc_events)) { + if (G_UNLIKELY (mono_profiler_events & MONO_PROFILE_ALLOCATIONS)) { if (obj) mono_profiler_allocation (obj); } @@ -955,7 +949,7 @@ mono_gc_alloc_mature (MonoVTable *vtable, size_t size) { MonoObject *obj = sgen_alloc_obj_mature (vtable, size); - if (G_UNLIKELY (alloc_events)) { + if (G_UNLIKELY (mono_profiler_events & MONO_PROFILE_ALLOCATIONS)) { if (obj) mono_profiler_allocation (obj); } @@ -967,11 +961,11 @@ void* mono_gc_alloc_fixed (size_t size, MonoGCDescriptor descr, MonoGCRootSource source, const char *msg) { /* FIXME: do a single allocation */ - void *res = calloc (1, size); + void *res = g_calloc (1, size); if (!res) return NULL; if (!mono_gc_register_root ((char *)res, size, descr, source, msg)) { - free (res); + g_free (res); res = NULL; } return res; @@ -981,7 +975,7 @@ void mono_gc_free_fixed (void* addr) { mono_gc_deregister_root ((char *)addr); - free (addr); + g_free (addr); } /* @@ -1124,14 +1118,6 @@ create_allocator (int atype, ManagedAllocatorVariant variant) */ EMIT_TLS_ACCESS_VAR (mb, thread_var); -#ifdef MANAGED_ALLOCATOR_CAN_USE_CRITICAL_REGION - EMIT_TLS_ACCESS_IN_CRITICAL_REGION_ADDR (mb, thread_var); - mono_mb_emit_byte (mb, CEE_LDC_I4_1); - mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX); - mono_mb_emit_byte (mb, CEE_MONO_ATOMIC_STORE_I4); - mono_mb_emit_i4 (mb, MONO_MEMORY_BARRIER_NONE); -#endif - size_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg); if (atype == ATYPE_SMALL) { /* size_var = size_arg */ @@ -1258,6 +1244,14 @@ create_allocator (int atype, ManagedAllocatorVariant variant) g_assert_not_reached (); } +#ifdef MANAGED_ALLOCATOR_CAN_USE_CRITICAL_REGION + EMIT_TLS_ACCESS_IN_CRITICAL_REGION_ADDR (mb, thread_var); + mono_mb_emit_byte (mb, CEE_LDC_I4_1); + mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX); + mono_mb_emit_byte (mb, CEE_MONO_ATOMIC_STORE_I4); + mono_mb_emit_i4 (mb, MONO_MEMORY_BARRIER_NONE); +#endif + /* size += ALLOC_ALIGN - 1; */ mono_mb_emit_ldloc (mb, size_var); mono_mb_emit_icon (mb, SGEN_ALLOC_ALIGN - 1); @@ -1752,7 +1746,7 @@ mono_gc_alloc_vector (MonoVTable *vtable, size_t size, uintptr_t max_length) UNLOCK_GC; done: - if (G_UNLIKELY (alloc_events)) + if (G_UNLIKELY (mono_profiler_events & MONO_PROFILE_ALLOCATIONS)) mono_profiler_allocation (&arr->obj); SGEN_ASSERT (6, SGEN_ALIGN_UP (size) == SGEN_ALIGN_UP (sgen_client_par_object_get_size (vtable, (GCObject*)arr)), "Vector has incorrect size."); @@ -1800,7 +1794,7 @@ mono_gc_alloc_array (MonoVTable *vtable, size_t size, uintptr_t max_length, uint UNLOCK_GC; done: - if (G_UNLIKELY (alloc_events)) + if (G_UNLIKELY (mono_profiler_events & MONO_PROFILE_ALLOCATIONS)) mono_profiler_allocation (&arr->obj); SGEN_ASSERT (6, SGEN_ALIGN_UP (size) == SGEN_ALIGN_UP (sgen_client_par_object_get_size (vtable, (GCObject*)arr)), "Array has incorrect size."); @@ -1841,7 +1835,7 @@ mono_gc_alloc_string (MonoVTable *vtable, size_t size, gint32 len) UNLOCK_GC; done: - if (G_UNLIKELY (alloc_events)) + if (G_UNLIKELY (mono_profiler_events & MONO_PROFILE_ALLOCATIONS)) mono_profiler_allocation (&str->object); return str; @@ -2060,22 +2054,45 @@ sgen_client_collecting_major_3 (SgenPointerQueue *fin_ready_queue, SgenPointerQu static void *moved_objects [MOVED_OBJECTS_NUM]; static int moved_objects_idx = 0; +static SgenPointerQueue moved_objects_queue = SGEN_POINTER_QUEUE_INIT (INTERNAL_MEM_MOVED_OBJECT); + void mono_sgen_register_moved_object (void *obj, void *destination) { - g_assert (mono_profiler_events & MONO_PROFILE_GC_MOVES); + /* + * This function can be called from SGen's worker threads. We want to try + * and avoid exposing those threads to the profiler API, so queue up move + * events and send them later when the main GC thread calls + * mono_sgen_gc_event_moves (). + * + * TODO: Once SGen has multiple worker threads, we need to switch to a + * lock-free data structure for the queue as multiple threads will be + * adding to it at the same time. + */ + if (sgen_thread_pool_is_thread_pool_thread (mono_native_thread_id_get ())) { + sgen_pointer_queue_add (&moved_objects_queue, obj); + sgen_pointer_queue_add (&moved_objects_queue, destination); + } else { + if (moved_objects_idx == MOVED_OBJECTS_NUM) { + mono_profiler_gc_moves (moved_objects, moved_objects_idx); + moved_objects_idx = 0; + } - if (moved_objects_idx == MOVED_OBJECTS_NUM) { - mono_profiler_gc_moves (moved_objects, moved_objects_idx); - moved_objects_idx = 0; + moved_objects [moved_objects_idx++] = obj; + moved_objects [moved_objects_idx++] = destination; } - moved_objects [moved_objects_idx++] = obj; - moved_objects [moved_objects_idx++] = destination; } void mono_sgen_gc_event_moves (void) { + while (!sgen_pointer_queue_is_empty (&moved_objects_queue)) { + void *dst = sgen_pointer_queue_pop (&moved_objects_queue); + void *src = sgen_pointer_queue_pop (&moved_objects_queue); + + mono_sgen_register_moved_object (src, dst); + } + if (moved_objects_idx) { mono_profiler_gc_moves (moved_objects, moved_objects_idx); moved_objects_idx = 0; @@ -2229,6 +2246,8 @@ sgen_client_thread_register (SgenThreadInfo* info, void *stack_bottom_fallback) binary_protocol_thread_register ((gpointer)mono_thread_info_get_tid (info)); SGEN_LOG (3, "registered thread %p (%p) stack end %p", info, (gpointer)mono_thread_info_get_tid (info), info->client_info.stack_end); + + info->client_info.info.handle_stack = mono_handle_stack_alloc (); } void @@ -2254,6 +2273,10 @@ sgen_client_thread_unregister (SgenThreadInfo *p) binary_protocol_thread_unregister ((gpointer)tid); SGEN_LOG (3, "unregister thread %p (%p)", p, (gpointer)tid); + + HandleStack *handles = (HandleStack*) p->client_info.info.handle_stack; + p->client_info.info.handle_stack = NULL; + mono_handle_stack_free (handles); } void @@ -2281,8 +2304,6 @@ thread_in_critical_region (SgenThreadInfo *info) static void sgen_thread_attach (SgenThreadInfo *info) { - mono_handle_arena_init ((MonoHandleArena**) &info->client_info.info.handle_arena); - if (mono_gc_get_gc_callbacks ()->thread_attach_func && !info->client_info.runtime_data) info->client_info.runtime_data = mono_gc_get_gc_callbacks ()->thread_attach_func (); } @@ -2298,8 +2319,6 @@ sgen_thread_detach (SgenThreadInfo *p) */ if (mono_domain_get ()) mono_thread_detach_internal (mono_thread_internal_current ()); - - mono_handle_arena_cleanup ((MonoHandleArena**) &p->client_info.info.handle_arena); } gboolean @@ -2378,6 +2397,21 @@ sgen_client_scan_thread_data (void *start_nursery, void *end_nursery, gboolean p g_assert (info->client_info.stack_end); aligned_stack_start = (void*)(mword) ALIGN_TO ((mword)info->client_info.stack_start, SIZEOF_VOID_P); +#ifdef HOST_WIN32 + /* Windows uses a guard page before the committed stack memory pages to detect when the + stack needs to be grown. If we suspend a thread just after a function prolog has + decremented the stack pointer to point into the guard page but before the thread has + been able to read or write to that page, starting the stack scan at aligned_stack_start + will raise a STATUS_GUARD_PAGE_VIOLATION and the process will crash. This code uses + VirtualQuery() to determine whether stack_start points into the guard page and then + updates aligned_stack_start to point at the next non-guard page. */ + MEMORY_BASIC_INFORMATION mem_info; + SIZE_T result = VirtualQuery(info->client_info.stack_start, &mem_info, sizeof(mem_info)); + g_assert (result != 0); + if (mem_info.Protect & PAGE_GUARD) { + aligned_stack_start = ((char*) mem_info.BaseAddress) + mem_info.RegionSize; + } +#endif g_assert (info->client_info.suspend_done); SGEN_LOG (3, "Scanning thread %p, range: %p-%p, size: %zd, pinned=%zd", info, info->client_info.stack_start, info->client_info.stack_end, (char*)info->client_info.stack_end - (char*)info->client_info.stack_start, sgen_get_pinned_count ()); @@ -2388,6 +2422,7 @@ sgen_client_scan_thread_data (void *start_nursery, void *end_nursery, gboolean p fprintf (stderr, "Precise stack mark not supported - disabling.\n"); conservative_stack_mark = TRUE; } + //FIXME we should eventually use the new stack_mark from coop sgen_conservatively_pin_objects_from ((void **)aligned_stack_start, (void **)info->client_info.stack_end, start_nursery, end_nursery, PIN_TYPE_STACK); } @@ -2398,6 +2433,7 @@ sgen_client_scan_thread_data (void *start_nursery, void *end_nursery, gboolean p { // This is used on Coop GC for platforms where we cannot get the data for individual registers. // We force a spill of all registers into the stack and pass a chunk of data into sgen. + //FIXME under coop, for now, what we need to ensure is that we scan any extra memory from info->client_info.stack_end to stack_mark MonoThreadUnwindState *state = &info->client_info.info.thread_saved_state [SELF_SUSPEND_STATE_INDEX]; if (state && state->gc_stackdata) { sgen_conservatively_pin_objects_from ((void **)state->gc_stackdata, (void**)((char*)state->gc_stackdata + state->gc_stackdata_size), @@ -2405,6 +2441,9 @@ sgen_client_scan_thread_data (void *start_nursery, void *end_nursery, gboolean p } } } + if (precise && info->client_info.info.handle_stack) { + mono_handle_stack_scan ((HandleStack*)info->client_info.info.handle_stack, (GcScanFunc)ctx.ops->copy_or_mark_object, ctx.queue); + } } FOREACH_THREAD_END } @@ -2492,11 +2531,6 @@ mono_gc_get_generation (MonoObject *obj) return 1; } -void -mono_gc_enable_events (void) -{ -} - const char * mono_gc_get_gc_name (void) { @@ -2768,6 +2802,7 @@ sgen_client_description_for_internal_mem_type (int type) { switch (type) { case INTERNAL_MEM_EPHEMERON_LINK: return "ephemeron-link"; + case INTERNAL_MEM_MOVED_OBJECT: return "moved-object"; default: return NULL; } @@ -2873,7 +2908,7 @@ sgen_client_handle_gc_param (const char *opt) } else if (g_str_has_prefix (opt, "toggleref-test")) { /* FIXME: This should probably in MONO_GC_DEBUG */ sgen_register_test_toggleref_callback (); - } else { + } else if (!sgen_bridge_handle_gc_param (opt)) { return FALSE; } return TRUE; @@ -2950,6 +2985,10 @@ mono_gc_base_init (void) mono_counters_init (); +#ifndef HOST_WIN32 + mono_w32handle_init (); +#endif + #ifdef HEAVY_STATISTICS mono_counters_register ("los marked cards", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &los_marked_cards); mono_counters_register ("los array cards scanned ", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &los_array_cards); @@ -2978,6 +3017,9 @@ void mono_gc_base_cleanup (void) { sgen_thread_pool_shutdown (); + + // We should have consumed any outstanding moves. + g_assert (sgen_pointer_queue_is_empty (&moved_objects_queue)); } gboolean diff --git a/mono/metadata/sgen-new-bridge.c b/mono/metadata/sgen-new-bridge.c index a1eb82a714..501ceb76d5 100644 --- a/mono/metadata/sgen-new-bridge.c +++ b/mono/metadata/sgen-new-bridge.c @@ -24,6 +24,11 @@ #include "tabledefs.h" #include "utils/mono-logger-internals.h" +#define OPTIMIZATION_COPY +#define OPTIMIZATION_FORWARD +#define OPTIMIZATION_SINGLETON_DYN_ARRAY +#include "sgen-dynarray.h" + //#define NEW_XREFS #ifdef NEW_XREFS //#define TEST_NEW_XREFS @@ -39,31 +44,6 @@ #define XREFS old_xrefs #endif -#define OPTIMIZATION_COPY -#define OPTIMIZATION_FORWARD -#define OPTIMIZATION_SINGLETON_DYN_ARRAY - -typedef struct { - int size; - int capacity; /* if negative, data points to another DynArray's data */ - char *data; -} DynArray; - -/*Specializations*/ - -typedef struct { - DynArray array; -} DynIntArray; - -typedef struct { - DynArray array; -} DynPtrArray; - -typedef struct { - DynArray array; -} DynSCCArray; - - /* * Bridge data for a single managed object * @@ -121,6 +101,8 @@ typedef struct _SCC { #endif } SCC; +static char *dump_prefix = NULL; + // Maps managed objects to corresponding HashEntry stricts static SgenHashTable hash_table = SGEN_HASH_TABLE_INIT (INTERNAL_MEM_BRIDGE_HASH_TABLE, INTERNAL_MEM_BRIDGE_HASH_TABLE_ENTRY, sizeof (HashEntry), mono_aligned_addr_hash, NULL); @@ -131,266 +113,6 @@ static gboolean bridge_accounting_enabled = FALSE; static SgenBridgeProcessor *bridge_processor; /* Core functions */ -/* public */ - -/* private */ - -static void -dyn_array_init (DynArray *da) -{ - da->size = 0; - da->capacity = 0; - da->data = NULL; -} - -static void -dyn_array_uninit (DynArray *da, int elem_size) -{ - if (da->capacity < 0) { - dyn_array_init (da); - return; - } - - if (da->capacity == 0) - return; - - sgen_free_internal_dynamic (da->data, elem_size * da->capacity, INTERNAL_MEM_BRIDGE_DATA); - da->data = NULL; -} - -static void -dyn_array_empty (DynArray *da) -{ - if (da->capacity < 0) - dyn_array_init (da); - else - da->size = 0; -} - -static void -dyn_array_ensure_capacity (DynArray *da, int capacity, int elem_size) -{ - int old_capacity = da->capacity; - char *new_data; - - g_assert (capacity > 0); - - if (capacity <= old_capacity) - return; - - if (old_capacity <= 0) - da->capacity = 2; - while (capacity > da->capacity) - da->capacity *= 2; - - new_data = (char *)sgen_alloc_internal_dynamic (elem_size * da->capacity, INTERNAL_MEM_BRIDGE_DATA, TRUE); - memcpy (new_data, da->data, elem_size * da->size); - if (old_capacity > 0) - sgen_free_internal_dynamic (da->data, elem_size * old_capacity, INTERNAL_MEM_BRIDGE_DATA); - da->data = new_data; -} - -static gboolean -dyn_array_is_copy (DynArray *da) -{ - return da->capacity < 0; -} - -static void -dyn_array_ensure_independent (DynArray *da, int elem_size) -{ - if (!dyn_array_is_copy (da)) - return; - dyn_array_ensure_capacity (da, da->size, elem_size); - g_assert (da->capacity > 0); -} - -static void* -dyn_array_add (DynArray *da, int elem_size) -{ - void *p; - - dyn_array_ensure_capacity (da, da->size + 1, elem_size); - - p = da->data + da->size * elem_size; - ++da->size; - return p; -} - -static void -dyn_array_copy (DynArray *dst, DynArray *src, int elem_size) -{ - dyn_array_uninit (dst, elem_size); - - if (src->size == 0) - return; - - dst->size = src->size; - dst->capacity = -1; - dst->data = src->data; -} - -/* int */ -static void -dyn_array_int_init (DynIntArray *da) -{ - dyn_array_init (&da->array); -} - -static void -dyn_array_int_uninit (DynIntArray *da) -{ - dyn_array_uninit (&da->array, sizeof (int)); -} - -static int -dyn_array_int_size (DynIntArray *da) -{ - return da->array.size; -} - -#ifdef NEW_XREFS -static void -dyn_array_int_empty (DynIntArray *da) -{ - dyn_array_empty (&da->array); -} -#endif - -static void -dyn_array_int_add (DynIntArray *da, int x) -{ - int *p = (int *)dyn_array_add (&da->array, sizeof (int)); - *p = x; -} - -static int -dyn_array_int_get (DynIntArray *da, int x) -{ - return ((int*)da->array.data)[x]; -} - -#ifdef NEW_XREFS -static void -dyn_array_int_set (DynIntArray *da, int idx, int val) -{ - ((int*)da->array.data)[idx] = val; -} -#endif - -static void -dyn_array_int_ensure_independent (DynIntArray *da) -{ - dyn_array_ensure_independent (&da->array, sizeof (int)); -} - -static void -dyn_array_int_copy (DynIntArray *dst, DynIntArray *src) -{ - dyn_array_copy (&dst->array, &src->array, sizeof (int)); -} - -static gboolean -dyn_array_int_is_copy (DynIntArray *da) -{ - return dyn_array_is_copy (&da->array); -} - -/* ptr */ - -static void -dyn_array_ptr_init (DynPtrArray *da) -{ - dyn_array_init (&da->array); -} - -static void -dyn_array_ptr_uninit (DynPtrArray *da) -{ -#ifdef OPTIMIZATION_SINGLETON_DYN_ARRAY - if (da->array.capacity == 1) - dyn_array_ptr_init (da); - else -#endif - dyn_array_uninit (&da->array, sizeof (void*)); -} - -static int -dyn_array_ptr_size (DynPtrArray *da) -{ - return da->array.size; -} - -static void -dyn_array_ptr_empty (DynPtrArray *da) -{ -#ifdef OPTIMIZATION_SINGLETON_DYN_ARRAY - if (da->array.capacity == 1) - dyn_array_ptr_init (da); - else -#endif - dyn_array_empty (&da->array); -} - -static void* -dyn_array_ptr_get (DynPtrArray *da, int x) -{ -#ifdef OPTIMIZATION_SINGLETON_DYN_ARRAY - if (da->array.capacity == 1) { - g_assert (x == 0); - return da->array.data; - } -#endif - return ((void**)da->array.data)[x]; -} - -static void -dyn_array_ptr_add (DynPtrArray *da, void *ptr) -{ - void **p; - -#ifdef OPTIMIZATION_SINGLETON_DYN_ARRAY - if (da->array.capacity == 0) { - da->array.capacity = 1; - da->array.size = 1; - p = (void**)&da->array.data; - } else if (da->array.capacity == 1) { - void *ptr0 = da->array.data; - void **p0; - dyn_array_init (&da->array); - p0 = (void **)dyn_array_add (&da->array, sizeof (void*)); - *p0 = ptr0; - p = (void **)dyn_array_add (&da->array, sizeof (void*)); - } else -#endif - { - p = (void **)dyn_array_add (&da->array, sizeof (void*)); - } - *p = ptr; -} - -#define dyn_array_ptr_push dyn_array_ptr_add - -static void* -dyn_array_ptr_pop (DynPtrArray *da) -{ - int size = da->array.size; - void *p; - g_assert (size > 0); -#ifdef OPTIMIZATION_SINGLETON_DYN_ARRAY - if (da->array.capacity == 1) { - p = dyn_array_ptr_get (da, 0); - dyn_array_init (&da->array); - } else -#endif - { - g_assert (da->array.capacity > 1); - dyn_array_ensure_independent (&da->array, sizeof (void*)); - p = dyn_array_ptr_get (da, size - 1); - --da->array.size; - } - return p; -} /*SCC */ @@ -441,11 +163,16 @@ dyn_array_int_contains (DynIntArray *da, int x) #endif static void -enable_accounting (void) +set_config (const SgenBridgeProcessorConfig *config) { - SgenHashTable table = SGEN_HASH_TABLE_INIT (INTERNAL_MEM_BRIDGE_HASH_TABLE, INTERNAL_MEM_BRIDGE_HASH_TABLE_ENTRY, sizeof (HashEntryWithAccounting), mono_aligned_addr_hash, NULL); - bridge_accounting_enabled = TRUE; - hash_table = table; + if (config->accounting) { + SgenHashTable table = SGEN_HASH_TABLE_INIT (INTERNAL_MEM_BRIDGE_HASH_TABLE, INTERNAL_MEM_BRIDGE_HASH_TABLE_ENTRY, sizeof (HashEntryWithAccounting), mono_aligned_addr_hash, NULL); + bridge_accounting_enabled = TRUE; + hash_table = table; + } + if (config->dump_prefix) { + dump_prefix = strdup (config->dump_prefix); + } } static MonoGCBridgeObjectKind @@ -884,8 +611,6 @@ reset_flags (SCC *scc) } #endif -static char *dump_prefix = NULL; - static void dump_graph (void) { @@ -937,12 +662,6 @@ dump_graph (void) fclose (file); } -static void -set_dump_prefix (const char *prefix) -{ - dump_prefix = strdup (prefix); -} - static int compare_hash_entries (const HashEntry *e1, const HashEntry *e2) { @@ -1367,8 +1086,7 @@ sgen_new_bridge_init (SgenBridgeProcessor *collector) collector->class_kind = class_kind; collector->register_finalized_object = register_finalized_object; collector->describe_pointer = describe_pointer; - collector->enable_accounting = enable_accounting; - collector->set_dump_prefix = set_dump_prefix; + collector->set_config = set_config; bridge_processor = collector; } diff --git a/mono/metadata/sgen-old-bridge.c b/mono/metadata/sgen-old-bridge.c index d33d5d8681..346e4b0aeb 100644 --- a/mono/metadata/sgen-old-bridge.c +++ b/mono/metadata/sgen-old-bridge.c @@ -372,11 +372,13 @@ dyn_array_int_merge_one (DynIntArray *array, int value) static void -enable_accounting (void) +set_config (const SgenBridgeProcessorConfig *config) { - SgenHashTable table = SGEN_HASH_TABLE_INIT (INTERNAL_MEM_BRIDGE_HASH_TABLE, INTERNAL_MEM_BRIDGE_HASH_TABLE_ENTRY, sizeof (HashEntryWithAccounting), mono_aligned_addr_hash, NULL); - bridge_accounting_enabled = TRUE; - hash_table = table; + if (config->accounting) { + SgenHashTable table = SGEN_HASH_TABLE_INIT (INTERNAL_MEM_BRIDGE_HASH_TABLE, INTERNAL_MEM_BRIDGE_HASH_TABLE_ENTRY, sizeof (HashEntryWithAccounting), mono_aligned_addr_hash, NULL); + bridge_accounting_enabled = TRUE; + hash_table = table; + } } static MonoGCBridgeObjectKind @@ -922,7 +924,7 @@ sgen_old_bridge_init (SgenBridgeProcessor *collector) collector->class_kind = class_kind; collector->register_finalized_object = register_finalized_object; collector->describe_pointer = describe_pointer; - collector->enable_accounting = enable_accounting; + collector->set_config = set_config; bridge_processor = collector; } diff --git a/mono/metadata/sgen-os-coop.c b/mono/metadata/sgen-os-coop.c index 90c8266b34..32bab7ebcb 100644 --- a/mono/metadata/sgen-os-coop.c +++ b/mono/metadata/sgen-os-coop.c @@ -9,6 +9,7 @@ */ #include "config.h" + #ifdef HAVE_SGEN_GC @@ -65,6 +66,10 @@ mono_gc_get_restart_signal (void) { return -1; } - -#endif +#else + #ifdef _MSC_VER + // Quiet Visual Studio linker warning, LNK4221, in cases when this source file intentional ends up empty. + void __mono_win32_sgen_os_coop_quiet_lnk4221(void) {} + #endif +#endif /* USE_COOP_GC */ #endif diff --git a/mono/metadata/sgen-os-posix.c b/mono/metadata/sgen-os-posix.c index 5a9bae85b6..1016841f53 100644 --- a/mono/metadata/sgen-os-posix.c +++ b/mono/metadata/sgen-os-posix.c @@ -46,6 +46,7 @@ suspend_thread (SgenThreadInfo *info, void *context) gpointer stack_start; info->client_info.stopped_domain = mono_domain_get (); + info->client_info.stack_start = NULL; info->client_info.signal = 0; stop_count = sgen_global_stop_count; /* duplicate signal */ diff --git a/mono/metadata/sgen-tarjan-bridge.c b/mono/metadata/sgen-tarjan-bridge.c index 66dff8d1d1..daa983e64a 100644 --- a/mono/metadata/sgen-tarjan-bridge.c +++ b/mono/metadata/sgen-tarjan-bridge.c @@ -19,139 +19,28 @@ #include "sgen/sgen-gc.h" #include "sgen-bridge-internals.h" -#include "sgen/sgen-hash-table.h" -#include "sgen/sgen-qsort.h" #include "tabledefs.h" #include "utils/mono-logger-internals.h" -typedef struct { - int size; - int capacity; - char *data; -} DynArray; +#include "sgen-dynarray.h" -/*Specializations*/ - -typedef struct { - DynArray array; -} DynPtrArray; - -/* private */ - -static void -dyn_array_uninit (DynArray *da, int elem_size) -{ - if (da->capacity <= 0) - return; - - sgen_free_internal_dynamic (da->data, elem_size * da->capacity, INTERNAL_MEM_BRIDGE_DATA); - da->data = NULL; -} - -static void -dyn_array_ensure_capacity (DynArray *da, int capacity, int elem_size) -{ - int old_capacity = da->capacity; - char *new_data; - - if (capacity <= old_capacity) - return; - - if (da->capacity == 0) - da->capacity = 2; - while (capacity > da->capacity) - da->capacity *= 2; - - new_data = (char *)sgen_alloc_internal_dynamic (elem_size * da->capacity, INTERNAL_MEM_BRIDGE_DATA, TRUE); - if (da->data) { - memcpy (new_data, da->data, elem_size * da->size); - sgen_free_internal_dynamic (da->data, elem_size * old_capacity, INTERNAL_MEM_BRIDGE_DATA); - } - da->data = new_data; -} - -static void* -dyn_array_add (DynArray *da, int elem_size) -{ - void *p; - - dyn_array_ensure_capacity (da, da->size + 1, elem_size); - - p = da->data + da->size * elem_size; - ++da->size; - return p; -} - -/* ptr */ - -static void -dyn_array_ptr_uninit (DynPtrArray *da) -{ - dyn_array_uninit (&da->array, sizeof (void*)); -} - -static int -dyn_array_ptr_size (DynPtrArray *da) -{ - return da->array.size; -} - -static void -dyn_array_ptr_set_size (DynPtrArray *da, int size) -{ - da->array.size = size; -} - -static void* -dyn_array_ptr_get (DynPtrArray *da, int x) -{ - return ((void**)da->array.data)[x]; -} - -static void -dyn_array_ptr_add (DynPtrArray *da, void *ptr) -{ - void **p = (void **)dyn_array_add (&da->array, sizeof (void*)); - *p = ptr; -} - -#define dyn_array_ptr_push dyn_array_ptr_add - -static void* -dyn_array_ptr_pop (DynPtrArray *da) -{ - void *p; - int size = da->array.size; - g_assert (size > 0); - p = dyn_array_ptr_get (da, size - 1); - --da->array.size; - return p; -} - -static void -dyn_array_ptr_ensure_capacity (DynPtrArray *da, int capacity) -{ - dyn_array_ensure_capacity (&da->array, capacity, sizeof (void*)); -} - - -static void -dyn_array_ptr_set_all (DynPtrArray *dst, DynPtrArray *src) -{ - if (src->array.size > 0) { - dyn_array_ptr_ensure_capacity (dst, src->array.size); - memcpy (dst->array.data, src->array.data, src->array.size * sizeof (void*)); - } - dst->array.size = src->array.size; -} - -static void -enable_accounting (void) -{ - // bridge_accounting_enabled = TRUE; - // hash_table = (SgenHashTable)SGEN_HASH_TABLE_INIT (INTERNAL_MEM_BRIDGE_HASH_TABLE, INTERNAL_MEM_BRIDGE_HASH_TABLE_ENTRY, sizeof (HashEntryWithAccounting), mono_aligned_addr_hash, NULL); -} +/* + * See comments in sgen-bridge.h + * + * This bridge implementation is based on the tarjan algorithm for strongly + * connected components. It has two elements: + * + * - Standard tarjan SCC algorithm to convert graph to SCC forest + * + * - "Colors": We reduce the SCC forest to bridged-SCCs-only by using a + * "color" algorithm devised by Kumpera. Consider the set of bridged SCCs + * which is reachable from a given object. We call each such unique set a + * "color". We compute the set of colors and which colors contain links to + * which colors. The color graph then becomes the reduced SCC graph. + */ +// Is this class bridged or not, and should its dependencies be scanned or not? +// The result of this callback will be cached for use by is_opaque_object later. static MonoGCBridgeObjectKind class_kind (MonoClass *klass) { @@ -182,9 +71,40 @@ class_kind (MonoClass *klass) return GC_BRIDGE_TRANSPARENT_CLASS; } -//enable unsage logging +//enable usage logging // #define DUMP_GRAPH 1 +/* Used in bridgeless_color_is_heavy: + * The idea here is as long as the reference fanin and fanout on a node are both 2 or greater, then + * removing that node will result in a net increase in edge count. So the question is which node + * removals are counterproductive (i.e., how many edges saved balances out one node added). + * The number of edges saved by preserving a node is (fanin*fanout - fanin - fanout). + * + * With all that in mind: + * + * - HEAVY_REFS_MIN is the number that *both* fanin and fanout must meet to preserve the node. + * - HEAVY_COMBINED_REFS_MIN is the number (fanin*fanout) must meet to preserve the node. + * + * Note HEAVY_COMBINED_REFS_MIN must be <= 2*INCOMING_COLORS_MAX, or we won't know the true fanin. + */ + +#define HEAVY_REFS_MIN 2 +#define HEAVY_COMBINED_REFS_MIN 60 + +/* Used in ColorData: + * The higher INCOMING_COLORS_BITS is the higher HEAVY_COMBINED_REFS_MIN can be (see above). + * However, API_INDEX_BITS + INCOMING_COLORS_BITS must be equal to 31, and if API_INDEX_BITS is too + * low then terrible things will happen if too many colors are generated. (The number of colors we + * will ever attempt to generate is currently naturally limited by the JNI GREF limit.) + */ + +#define API_INDEX_BITS 26 +#define INCOMING_COLORS_BITS 5 + +#define API_INDEX_MAX ((1<incoming_colors; + int fanout = dyn_array_ptr_size (&data->other_colors); + return fanin > HEAVY_REFS_MIN && fanout > HEAVY_REFS_MIN + && fanin*fanout >= HEAVY_COMBINED_REFS_MIN; +} +// Should color be made visible to client? +static inline gboolean +color_visible_to_client (ColorData *data) { + return dyn_array_ptr_size (&data->bridges) || bridgeless_color_is_heavy (data); +} +// Stacks of ScanData objects used for tarjan algorithm. +// The Tarjan algorithm is normally defined recursively; here scan_stack simulates the call stack of a recursive algorithm, +// and loop_stack is the stack structure used by the algorithm itself. +static DynPtrArray scan_stack, loop_stack; -static DynPtrArray scan_stack, loop_stack, registered_bridges; +// GCObjects on which register_finalized_object has been called +static DynPtrArray registered_bridges; + +// As we traverse the graph, which ColorData objects are accessible from our current position? static DynPtrArray color_merge_array; +// Running hash of the contents of the color_merge_array. +static unsigned int color_merge_array_hash; + +static void color_merge_array_empty () +{ + dyn_array_ptr_empty (&color_merge_array); + color_merge_array_hash = 0; +} static int ignored_objects; static int object_index; static int num_colors_with_bridges; +static int num_sccs; static int xref_count; static size_t setup_time, tarjan_time, scc_setup_time, gather_xref_time, xref_setup_time, cleanup_time; @@ -247,6 +210,7 @@ static ObjectBucket *root_object_bucket; static ObjectBucket *cur_object_bucket; static int object_data_count; +// Arenas to allocate ScanData from static ObjectBucket* new_object_bucket (void) { @@ -299,6 +263,7 @@ free_object_buckets (void) //ColorData buckets #define NUM_COLOR_ENTRIES ((BUCKET_SIZE - SIZEOF_VOID_P * 2) / sizeof (ColorData)) +// Arenas for ColorDatas, same as ObjectBucket except items-per-bucket differs typedef struct _ColorBucket ColorBucket; struct _ColorBucket { ColorBucket *next; @@ -372,6 +337,8 @@ create_data (GCObject *obj) res->obj = obj; res->color = NULL; res->index = res->low_index = -1; + res->state = INITIAL; + res->is_bridge = FALSE; res->obj_state = o [0] & SGEN_VTABLE_BITS_MASK; res->lock_word = o [1]; @@ -439,11 +406,13 @@ find_or_create_data (GCObject *obj) //---------- typedef struct { ColorData *color; - int hash; + unsigned int hash; } HashEntry; /* -We tried 2/32, 2/128, 4/32, 4/128, 6/128 and 8/128. +The merge cache maps an ordered list of ColorDatas [the color_merge_array] to a single ColorData. + +About cache bucket tuning: We tried 2/32, 2/128, 4/32, 4/128, 6/128 and 8/128. The performance cost between 4/128 and 8/128 is so small since cache movement happens completely in the same cacheline, making the extra space pretty much free. @@ -456,17 +425,39 @@ Memory wise, 4/32 takes 512 and 8/128 takes 8k, so it's quite reasonable. #define ELEMENTS_PER_BUCKET 8 #define COLOR_CACHE_SIZE 128 static HashEntry merge_cache [COLOR_CACHE_SIZE][ELEMENTS_PER_BUCKET]; +static unsigned int hash_perturb; -static int -mix_hash (size_t hash) +// If true, disable an optimization where sometimes SCC nodes are merged without a perfect check +static gboolean scc_precise_merge; + +static unsigned int +mix_hash (uintptr_t source) { - return (int)(((hash * 215497) >> 16) ^ ((hash * 1823231) + hash)); + unsigned int hash = source; + + // The full hash determines whether two colors can be merged-- sometimes exclusively. + // This value changes every GC, so XORing it in before performing the hash will make the + // chance that two different colors will produce the same hash on successive GCs very low. + hash = hash ^ hash_perturb; + + // Actual hash + hash = (((hash * 215497) >> 16) ^ ((hash * 1823231) + hash)); + + // Mix in highest bits on 64-bit systems only + if (sizeof (source) > 4) + hash = hash ^ (source >> 32); + + return hash; } static void reset_cache (void) { memset (merge_cache, 0, sizeof (merge_cache)); + + // When using the precise merge debug option, we do not want the inconsistency caused by hash_perturb. + if (!scc_precise_merge) + ++hash_perturb; } @@ -480,6 +471,13 @@ dyn_array_ptr_contains (DynPtrArray *da, void *x) return FALSE; } +static gboolean +match_colors_estimate (DynPtrArray *a, DynPtrArray *b) +{ + return dyn_array_ptr_size (a) == dyn_array_ptr_size (b); +} + + static gboolean match_colors (DynPtrArray *a, DynPtrArray *b) { @@ -494,23 +492,36 @@ match_colors (DynPtrArray *a, DynPtrArray *b) return TRUE; } -static int cache_hits, cache_misses; +// If scc_precise_merge, "semihits" refers to find_in_cache calls aborted because the merge array was too large. +// Otherwise "semihits" refers to cache hits where the match was only estimated. +static int cache_hits, cache_semihits, cache_misses; +// The cache contains only non-bridged colors. static ColorData* find_in_cache (int *insert_index) { HashEntry *bucket; - int i, hash, size, index; + int i, size, index; size = dyn_array_ptr_size (&color_merge_array); - /* Cache checking is very ineficient with a lot of elements*/ - if (size > 3) - return NULL; - hash = 0; - for (i = 0 ; i < size; ++i) - hash += mix_hash ((size_t)dyn_array_ptr_get (&color_merge_array, i)); - if (!hash) + /* Color equality checking is very expensive with a lot of elements, so when there are many + * elements we switch to a cheap comparison method which allows false positives. When false + * positives occur the worst that can happen is two items will be inappropriately merged + * and memory will be retained longer than it should be. We assume that will correct itself + * on the next GC (the hash_perturb mechanism increases the probability of this). + * + * Because this has *some* potential to create problems, if the user set the debug option + * 'enable-tarjan-precise-merge' we bail out early (and never merge SCCs with >3 colors). + */ + gboolean color_merge_array_large = size > 3; + if (scc_precise_merge && color_merge_array_large) { + ++cache_semihits; + return NULL; + } + + unsigned int hash = color_merge_array_hash; + if (!hash) // 0 is used to indicate an empty bucket entry hash = 1; index = hash & (COLOR_CACHE_SIZE - 1); @@ -518,9 +529,17 @@ find_in_cache (int *insert_index) for (i = 0; i < ELEMENTS_PER_BUCKET; ++i) { if (bucket [i].hash != hash) continue; - if (match_colors (&bucket [i].color->other_colors, &color_merge_array)) { - ++cache_hits; - return bucket [i].color; + + if (color_merge_array_large) { + if (match_colors_estimate (&bucket [i].color->other_colors, &color_merge_array)) { + ++cache_semihits; + return bucket [i].color; + } + } else { + if (match_colors (&bucket [i].color->other_colors, &color_merge_array)) { + ++cache_hits; + return bucket [i].color; + } } } @@ -533,14 +552,16 @@ find_in_cache (int *insert_index) return NULL; } +// A color is needed for an SCC. If the SCC has bridges, the color MUST be newly allocated. +// If the SCC lacks bridges, the allocator MAY use the cache to merge it with an existing one. static ColorData* -new_color (gboolean force_new) +new_color (gboolean has_bridges) { - int i = -1; + int cacheSlot = -1; ColorData *cd; /* XXX Try to find an equal one and return it */ - if (!force_new) { - cd = find_in_cache (&i); + if (!has_bridges) { + cd = find_in_cache (&cacheSlot); if (cd) return cd; } @@ -548,9 +569,16 @@ new_color (gboolean force_new) cd = alloc_color_data (); cd->api_index = -1; dyn_array_ptr_set_all (&cd->other_colors, &color_merge_array); - /* if i >= 0, it means we prepared a given slot to receive the new color */ - if (i >= 0) - merge_cache [i][0].color = cd; + + // Inform targets + for (int i = 0; i < dyn_array_ptr_size (&color_merge_array); ++i) { + ColorData *points_to = (ColorData *)dyn_array_ptr_get (&color_merge_array, i); + points_to->incoming_colors = MIN (points_to->incoming_colors + 1, INCOMING_COLORS_MAX); + } + + /* if cacheSlot >= 0, it means we prepared a given slot to receive the new color */ + if (cacheSlot >= 0) + merge_cache [cacheSlot][0].color = cd; return cd; } @@ -574,6 +602,7 @@ is_opaque_object (GCObject *obj) return FALSE; } +// Called during DFS; visits one child. If it is a candidate to be scanned, pushes it to the stacks. static void push_object (GCObject *obj) { @@ -627,6 +656,7 @@ push_object (GCObject *obj) if (dst) push_object (dst); \ } while (0) +// dfs () function's queue-children-of-object operation. static void push_all (ScanData *data) { @@ -635,7 +665,7 @@ push_all (ScanData *data) mword desc = sgen_obj_get_descriptor_safe (obj); #if DUMP_GRAPH - printf ("**scanning %p %s\n", obj, safe_name_bridge (obj)); + printf ("+scanning %s (%p) index %d color %p\n", safe_name_bridge (data->obj), data->obj, data->index, data->color); #endif #include "sgen/sgen-scan-object.h" @@ -647,8 +677,8 @@ compute_low_index (ScanData *data, GCObject *obj) { ScanData *other; ColorData *cd; - obj = bridge_object_forward (obj); + obj = bridge_object_forward (obj); other = find_data (obj); #if DUMP_GRAPH @@ -668,6 +698,7 @@ compute_low_index (ScanData *data, GCObject *obj) cd = other->color; if (!cd->visited) { + color_merge_array_hash += mix_hash ((uintptr_t) other->color); dyn_array_ptr_add (&color_merge_array, other->color); cd->visited = TRUE; } @@ -689,16 +720,24 @@ compute_low (ScanData *data) #include "sgen/sgen-scan-object.h" } +// A non-bridged object needs a single color describing the current merge array. static ColorData* reduce_color (void) { ColorData *color = NULL; int size = dyn_array_ptr_size (&color_merge_array); + // Merge array is empty-- this SCC points to no bridged colors. + // This SCC can be ignored completely. if (size == 0) color = NULL; + + // Merge array has one item-- this SCC points to a single bridged color. + // This SCC can be forwarded to the pointed-to color. else if (size == 1) { color = (ColorData *)dyn_array_ptr_get (&color_merge_array, 0); + + // This SCC gets to talk to the color allocator. } else color = new_color (FALSE); @@ -723,12 +762,12 @@ create_scc (ScanData *data) #if DUMP_GRAPH printf ("|SCC rooted in %s (%p) has bridge %d\n", safe_name_bridge (data->obj), data->obj, found_bridge); printf ("\tpoints-to-colors: "); - for (i = 0; i < dyn_array_ptr_size (&color_merge_array); ++i) + for (int i = 0; i < dyn_array_ptr_size (&color_merge_array); ++i) printf ("%p ", dyn_array_ptr_get (&color_merge_array, i)); printf ("\n"); printf ("loop stack: "); - for (i = 0; i < dyn_array_ptr_size (&loop_stack); ++i) { + for (int i = 0; i < dyn_array_ptr_size (&loop_stack); ++i) { ScanData *other = dyn_array_ptr_get (&loop_stack, i); printf ("(%d/%d)", other->index, other->low_index); } @@ -775,7 +814,7 @@ create_scc (ScanData *data) g_assert (cd->visited); cd->visited = FALSE; } - dyn_array_ptr_set_size (&color_merge_array, 0); + color_merge_array_empty (); found_bridge = FALSE; } @@ -785,7 +824,7 @@ dfs (void) g_assert (dyn_array_ptr_size (&scan_stack) == 1); g_assert (dyn_array_ptr_size (&loop_stack) == 0); - dyn_array_ptr_set_size (&color_merge_array, 0); + color_merge_array_empty (); while (dyn_array_ptr_size (&scan_stack) > 0) { ScanData *data = (ScanData *)dyn_array_ptr_pop (&scan_stack); @@ -852,15 +891,15 @@ register_finalized_object (GCObject *obj) static void reset_data (void) { - dyn_array_ptr_set_size (®istered_bridges, 0); + dyn_array_ptr_empty (®istered_bridges); } static void cleanup (void) { - dyn_array_ptr_set_size (&scan_stack, 0); - dyn_array_ptr_set_size (&loop_stack, 0); - dyn_array_ptr_set_size (®istered_bridges, 0); + dyn_array_ptr_empty (&scan_stack); + dyn_array_ptr_empty (&loop_stack); + dyn_array_ptr_empty (®istered_bridges); free_object_buckets (); free_color_buckets (); reset_cache (); @@ -951,7 +990,7 @@ processing_stw_step (void) #if defined (DUMP_GRAPH) printf ("----summary----\n"); printf ("bridges:\n"); - for (i = 0; i < bridge_count; ++i) { + for (int i = 0; i < bridge_count; ++i) { ScanData *sd = find_data (dyn_array_ptr_get (®istered_bridges, i)); printf ("\t%s (%p) index %d color %p\n", safe_name_bridge (sd->obj), sd->obj, sd->index, sd->color); } @@ -972,7 +1011,7 @@ gather_xrefs (ColorData *color) if (src->visited) continue; src->visited = TRUE; - if (dyn_array_ptr_size (&src->bridges)) + if (color_visible_to_client (src)) dyn_array_ptr_add (&color_merge_array, src); else gather_xrefs (src); @@ -988,7 +1027,7 @@ reset_xrefs (ColorData *color) if (!src->visited) continue; src->visited = FALSE; - if (!dyn_array_ptr_size (&src->bridges)) + if (!color_visible_to_client (src)) reset_xrefs (src); } } @@ -996,9 +1035,7 @@ reset_xrefs (ColorData *color) static void processing_build_callback_data (int generation) { - int j, api_index; - MonoGCBridgeSCC **api_sccs; - MonoGCBridgeXRef *api_xrefs; + int j; gint64 curtime; ColorBucket *cur; @@ -1017,15 +1054,27 @@ processing_build_callback_data (int generation) printf ("number of SCCs %d\n", num_colors_with_bridges); #endif - /* This is a straightforward translation from colors to the bridge callback format. */ - api_sccs = (MonoGCBridgeSCC **)sgen_alloc_internal_dynamic (sizeof (MonoGCBridgeSCC*) * num_colors_with_bridges, INTERNAL_MEM_BRIDGE_DATA, TRUE); - api_index = xref_count = 0; + // Count the number of SCCs visible to the client + num_sccs = 0; + for (cur = root_color_bucket; cur; cur = cur->next) { + ColorData *cd; + for (cd = &cur->data [0]; cd < cur->next_data; ++cd) { + if (color_visible_to_client (cd)) + num_sccs++; + } + } + /* This is a straightforward translation from colors to the bridge callback format. */ + MonoGCBridgeSCC **api_sccs = (MonoGCBridgeSCC **)sgen_alloc_internal_dynamic (sizeof (MonoGCBridgeSCC*) * num_sccs, INTERNAL_MEM_BRIDGE_DATA, TRUE); + int api_index = 0; + xref_count = 0; + + // Convert visible SCCs, along with their bridged object list, to MonoGCBridgeSCCs in the client's SCC list for (cur = root_color_bucket; cur; cur = cur->next) { ColorData *cd; for (cd = &cur->data [0]; cd < cur->next_data; ++cd) { int bridges = dyn_array_ptr_size (&cd->bridges); - if (!bridges) + if (!(bridges || bridgeless_color_is_heavy (cd))) continue; api_sccs [api_index] = (MonoGCBridgeSCC *)sgen_alloc_internal_dynamic (sizeof (MonoGCBridgeSCC) + sizeof (MonoObject*) * bridges, INTERNAL_MEM_BRIDGE_DATA, TRUE); @@ -1036,20 +1085,22 @@ processing_build_callback_data (int generation) for (j = 0; j < bridges; ++j) api_sccs [api_index]->objs [j] = (MonoObject *)dyn_array_ptr_get (&cd->bridges, j); + + g_assert(api_index < API_INDEX_MAX); api_index++; } } scc_setup_time = step_timer (&curtime); + // Eliminate non-visible SCCs from the SCC list and redistribute xrefs for (cur = root_color_bucket; cur; cur = cur->next) { ColorData *cd; for (cd = &cur->data [0]; cd < cur->next_data; ++cd) { - int bridges = dyn_array_ptr_size (&cd->bridges); - if (!bridges) + if (!color_visible_to_client (cd)) continue; - dyn_array_ptr_set_size (&color_merge_array, 0); + color_merge_array_empty (); gather_xrefs (cd); reset_xrefs (cd); dyn_array_ptr_set_all (&cd->other_colors, &color_merge_array); @@ -1064,37 +1115,38 @@ processing_build_callback_data (int generation) dump_color_table (" after xref pass", TRUE); #endif - api_xrefs = (MonoGCBridgeXRef *)sgen_alloc_internal_dynamic (sizeof (MonoGCBridgeXRef) * xref_count, INTERNAL_MEM_BRIDGE_DATA, TRUE); - api_index = 0; + // Write out xrefs array + MonoGCBridgeXRef *api_xrefs = (MonoGCBridgeXRef *)sgen_alloc_internal_dynamic (sizeof (MonoGCBridgeXRef) * xref_count, INTERNAL_MEM_BRIDGE_DATA, TRUE); + int xref_index = 0; for (cur = root_color_bucket; cur; cur = cur->next) { ColorData *src; for (src = &cur->data [0]; src < cur->next_data; ++src) { - int bridges = dyn_array_ptr_size (&src->bridges); - if (!bridges) + if (!color_visible_to_client (src)) continue; for (j = 0; j < dyn_array_ptr_size (&src->other_colors); ++j) { ColorData *dest = (ColorData *)dyn_array_ptr_get (&src->other_colors, j); - g_assert (dyn_array_ptr_size (&dest->bridges)); /* We flattened the color graph, so this must never happen. */ + g_assert (color_visible_to_client (dest)); /* Supposedly we already eliminated all xrefs to non-visible objects. */ - api_xrefs [api_index].src_scc_index = src->api_index; - api_xrefs [api_index].dst_scc_index = dest->api_index; - ++api_index; + api_xrefs [xref_index].src_scc_index = src->api_index; + api_xrefs [xref_index].dst_scc_index = dest->api_index; + + ++xref_index; } } } - g_assert (xref_count == api_index); + g_assert (xref_count == xref_index); xref_setup_time = step_timer (&curtime); #if defined (DUMP_GRAPH) printf ("---xrefs:\n"); - for (i = 0; i < xref_count; ++i) + for (int i = 0; i < xref_count; ++i) printf ("\t%d -> %d\n", api_xrefs [i].src_scc_index, api_xrefs [i].dst_scc_index); #endif //FIXME move half of the cleanup to before the bridge callback? - bridge_processor->num_sccs = num_colors_with_bridges; + bridge_processor->num_sccs = num_sccs; bridge_processor->api_sccs = api_sccs; bridge_processor->num_xrefs = xref_count; bridge_processor->api_xrefs = api_xrefs; @@ -1107,7 +1159,7 @@ processing_after_callback (int generation) int bridge_count = dyn_array_ptr_size (®istered_bridges); int object_count = object_data_count; int color_count = color_data_count; - int scc_count = num_colors_with_bridges; + int colors_with_bridges_count = num_colors_with_bridges; SGEN_TV_GETTIME (curtime); @@ -1116,10 +1168,10 @@ processing_after_callback (int generation) cleanup_time = step_timer (&curtime); - mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_GC, "GC_TAR_BRIDGE bridges %d objects %d colors %d ignored %d sccs %d xref %d cache %d/%d setup %.2fms tarjan %.2fms scc-setup %.2fms gather-xref %.2fms xref-setup %.2fms cleanup %.2fms", - bridge_count, object_count, color_count, - ignored_objects, scc_count, xref_count, - cache_hits, cache_misses, + mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_GC, "GC_TAR_BRIDGE bridges %d objects %d opaque %d colors %d colors-bridged %d colors-visible %d xref %d cache-hit %d cache-%s %d cache-miss %d setup %.2fms tarjan %.2fms scc-setup %.2fms gather-xref %.2fms xref-setup %.2fms cleanup %.2fms", + bridge_count, object_count, ignored_objects, + color_count, colors_with_bridges_count, num_sccs, xref_count, + cache_hits, (scc_precise_merge ? "abstain" : "semihit"), cache_semihits, cache_misses, setup_time / 10000.0f, tarjan_time / 10000.0f, scc_setup_time / 10000.0f, @@ -1127,7 +1179,7 @@ processing_after_callback (int generation) xref_setup_time / 10000.0f, cleanup_time / 10000.0f); - cache_hits = cache_misses = 0; + cache_hits = cache_semihits = cache_misses = 0; ignored_objects = 0; } @@ -1153,6 +1205,15 @@ describe_pointer (GCObject *obj) // printf (" is visited: %d\n", (int)entry->is_visited); } +static void +set_config (const SgenBridgeProcessorConfig *config) +{ + if (config->scc_precise_merge) { + hash_perturb = 0; + scc_precise_merge = TRUE; + } +} + void sgen_tarjan_bridge_init (SgenBridgeProcessor *collector) { @@ -1163,12 +1224,12 @@ sgen_tarjan_bridge_init (SgenBridgeProcessor *collector) collector->class_kind = class_kind; collector->register_finalized_object = register_finalized_object; collector->describe_pointer = describe_pointer; - collector->enable_accounting = enable_accounting; - // collector->set_dump_prefix = set_dump_prefix; + collector->set_config = set_config; sgen_register_fixed_internal_mem_type (INTERNAL_MEM_TARJAN_OBJ_BUCKET, BUCKET_SIZE); g_assert (sizeof (ObjectBucket) <= BUCKET_SIZE); g_assert (sizeof (ColorBucket) <= BUCKET_SIZE); + g_assert (API_INDEX_BITS + INCOMING_COLORS_BITS <= 31); bridge_processor = collector; } diff --git a/mono/metadata/socket-io.c b/mono/metadata/socket-io.c index 95bac2301b..d4d168da76 100644 --- a/mono/metadata/socket-io.c +++ b/mono/metadata/socket-io.c @@ -62,6 +62,7 @@ #include #include #include +#include #include #ifdef HAVE_SYS_TIME_H @@ -773,16 +774,15 @@ ves_icall_System_Net_Sockets_Socket_Accept_internal (SOCKET sock, gint32 *werror MONO_EXIT_GC_SAFE; - mono_thread_info_uninstall_interrupt (&interrupted); - if (interrupted) { - *werror = WSAEINTR; - return NULL; - } - - if (newsock == INVALID_SOCKET) { + if (newsock == INVALID_SOCKET) *werror = WSAGetLastError (); + + mono_thread_info_uninstall_interrupt (&interrupted); + if (interrupted) + *werror = WSAEINTR; + + if (*werror) return NULL; - } return GUINT_TO_POINTER (newsock); } @@ -1335,15 +1335,13 @@ ves_icall_System_Net_Sockets_Socket_Connect_internal (SOCKET sock, MonoObject *s MONO_EXIT_GC_SAFE; - mono_thread_info_uninstall_interrupt (&interrupted); - if (interrupted) { - *werror = WSAEINTR; - return; - } - if (ret == SOCKET_ERROR) *werror = WSAGetLastError (); + mono_thread_info_uninstall_interrupt (&interrupted); + if (interrupted) + *werror = WSAEINTR; + g_free (sa); } @@ -1422,10 +1420,10 @@ ves_icall_System_Net_Sockets_Socket_Disconnect_internal (SOCKET sock, MonoBoolea MONO_ENTER_GC_SAFE; if (_wapi_disconnectex != NULL) { - if (!_wapi_disconnectex (sock, NULL, TF_REUSE_SOCKET, 0)) + if (!_wapi_disconnectex (sock, NULL, reuse ? TF_REUSE_SOCKET : 0, 0)) *werror = WSAGetLastError (); } else if (_wapi_transmitfile != NULL) { - if (!_wapi_transmitfile (sock, NULL, 0, 0, NULL, NULL, TF_DISCONNECT | TF_REUSE_SOCKET)) + if (!_wapi_transmitfile (sock, NULL, 0, 0, NULL, NULL, TF_DISCONNECT | (reuse ? TF_REUSE_SOCKET : 0))) *werror = WSAGetLastError (); } else { *werror = ERROR_NOT_SUPPORTED; @@ -1480,16 +1478,15 @@ ves_icall_System_Net_Sockets_Socket_Receive_internal (SOCKET sock, MonoArray *bu MONO_EXIT_GC_SAFE; - mono_thread_info_uninstall_interrupt (&interrupted); - if (interrupted) { - *werror = WSAEINTR; - return 0; - } - - if (ret == SOCKET_ERROR) { + if (ret == SOCKET_ERROR) *werror = WSAGetLastError (); + + mono_thread_info_uninstall_interrupt (&interrupted); + if (interrupted) + *werror = WSAEINTR; + + if (*werror) return 0; - } return ret; } @@ -1526,16 +1523,15 @@ ves_icall_System_Net_Sockets_Socket_Receive_array_internal (SOCKET sock, MonoArr MONO_EXIT_GC_SAFE; - mono_thread_info_uninstall_interrupt (&interrupted); - if (interrupted) { - *werror = WSAEINTR; - return 0; - } - - if (ret == SOCKET_ERROR) { + if (ret == SOCKET_ERROR) *werror = WSAGetLastError (); + + mono_thread_info_uninstall_interrupt (&interrupted); + if (interrupted) + *werror = WSAEINTR; + + if (*werror) return 0; - } return recv; } @@ -1587,16 +1583,16 @@ ves_icall_System_Net_Sockets_Socket_ReceiveFrom_internal (SOCKET sock, MonoArray MONO_EXIT_GC_SAFE; - mono_thread_info_uninstall_interrupt (&interrupted); - if (interrupted) { - g_free (sa); - *werror = WSAEINTR; - return 0; - } - - if (ret==SOCKET_ERROR) { - g_free (sa); + if (ret == SOCKET_ERROR) *werror = WSAGetLastError (); + + mono_thread_info_uninstall_interrupt (&interrupted); + + if (interrupted) + *werror = WSAEINTR; + + if (*werror) { + g_free(sa); return 0; } @@ -1659,16 +1655,15 @@ ves_icall_System_Net_Sockets_Socket_Send_internal (SOCKET sock, MonoArray *buffe MONO_EXIT_GC_SAFE; - mono_thread_info_uninstall_interrupt (&interrupted); - if (interrupted) { - *werror = WSAEINTR; - return 0; - } - - if (ret == SOCKET_ERROR) { + if (ret == SOCKET_ERROR) *werror = WSAGetLastError (); + + mono_thread_info_uninstall_interrupt (&interrupted); + if (interrupted) + *werror = WSAEINTR; + + if (*werror) return 0; - } return ret; } @@ -1705,17 +1700,16 @@ ves_icall_System_Net_Sockets_Socket_Send_array_internal (SOCKET sock, MonoArray MONO_EXIT_GC_SAFE; - mono_thread_info_uninstall_interrupt (&interrupted); - if (interrupted) { - *werror = WSAEINTR; - return 0; - } - - if (ret == SOCKET_ERROR) { + if (ret == SOCKET_ERROR) *werror = WSAGetLastError (); + + mono_thread_info_uninstall_interrupt (&interrupted); + if (interrupted) + *werror = WSAEINTR; + + if (*werror) return 0; - } - + return sent; } @@ -1772,18 +1766,18 @@ ves_icall_System_Net_Sockets_Socket_SendTo_internal (SOCKET sock, MonoArray *buf MONO_EXIT_GC_SAFE; - mono_thread_info_uninstall_interrupt (&interrupted); - if (interrupted) { - g_free (sa); - *werror = WSAEINTR; - return 0; - } - if (ret == SOCKET_ERROR) *werror = WSAGetLastError (); - g_free (sa); - + mono_thread_info_uninstall_interrupt (&interrupted); + if (interrupted) + *werror = WSAEINTR; + + g_free(sa); + + if (*werror) + return 0; + return ret; } @@ -1960,7 +1954,7 @@ ves_icall_System_Net_Sockets_Socket_GetSocketOption_obj_internal (SOCKET sock, g int system_level = 0; int system_name = 0; int ret; - int val; + int val = 0; socklen_t valsize = sizeof (val); struct linger linger; socklen_t lingersize = sizeof (linger); @@ -2453,14 +2447,14 @@ ves_icall_System_Net_Sockets_Socket_Shutdown_internal (SOCKET sock, gint32 how, MONO_EXIT_GC_SAFE; + if (ret == SOCKET_ERROR) + *werror = WSAGetLastError (); + mono_thread_info_uninstall_interrupt (&interrupted); if (interrupted) { *werror = WSAEINTR; - return; } - if (ret == SOCKET_ERROR) - *werror = WSAGetLastError (); } gint @@ -2675,8 +2669,16 @@ ves_icall_System_Net_Dns_GetHostByName_internal (MonoString *host, MonoString ** } } +#ifdef HOST_WIN32 + // Win32 APIs already returns local interface addresses for empty hostname ("") + // so we never want to add them manually. + add_local_ips = FALSE; + if (mono_get_address_info(hostname, 0, MONO_HINT_CANONICAL_NAME | hint, &info)) + add_info_ok = FALSE; +#else if (*hostname && mono_get_address_info (hostname, 0, MONO_HINT_CANONICAL_NAME | hint, &info)) add_info_ok = FALSE; +#endif g_free(hostname); diff --git a/mono/metadata/sre-encode.c b/mono/metadata/sre-encode.c new file mode 100644 index 0000000000..ef91c85b0a --- /dev/null +++ b/mono/metadata/sre-encode.c @@ -0,0 +1,1303 @@ +/* + * sre-encode.c: Routines for encoding SRE builders into a + * MonoDynamicImage and generating tokens. + * + * + * Author: + * Paolo Molaro (lupus@ximian.com) + * + * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com) + * Copyright 2004-2009 Novell, Inc (http://www.novell.com) + * Copyright 2011 Rodrigo Kumpera + * Copyright 2016 Microsoft + * + * Licensed under the MIT license. See LICENSE file in the project root for full license information. + */ +#include +#include + +#include "mono/metadata/dynamic-image-internals.h" +#include "mono/metadata/dynamic-stream-internals.h" +#include "mono/metadata/object-internals.h" +#include "mono/metadata/sre-internals.h" +#include "mono/metadata/tabledefs.h" +#include "mono/metadata/tokentype.h" +#include "mono/utils/checked-build.h" + +typedef struct { + char *p; + char *buf; + char *end; +} SigBuffer; + +static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type); +static void encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf); +static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type); + +#define mono_type_array_get_and_resolve(array, index, error) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index), error) + +static guint32 +mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len) +{ + return mono_dynstream_add_data (stream, data, len); +} + +static void +alloc_table (MonoDynamicTable *table, guint nrows) +{ + mono_dynimage_alloc_table (table, nrows); +} + +static void +sigbuffer_init (SigBuffer *buf, int size) +{ + MONO_REQ_GC_NEUTRAL_MODE; + + buf->buf = (char *)g_malloc (size); + buf->p = buf->buf; + buf->end = buf->buf + size; +} + +static void +sigbuffer_make_room (SigBuffer *buf, int size) +{ + MONO_REQ_GC_NEUTRAL_MODE; + + if (buf->end - buf->p < size) { + int new_size = buf->end - buf->buf + size + 32; + char *p = (char *)g_realloc (buf->buf, new_size); + size = buf->p - buf->buf; + buf->buf = p; + buf->p = p + size; + buf->end = buf->buf + new_size; + } +} + +static void +sigbuffer_add_value (SigBuffer *buf, guint32 val) +{ + MONO_REQ_GC_NEUTRAL_MODE; + + sigbuffer_make_room (buf, 6); + mono_metadata_encode_value (val, buf->p, &buf->p); +} + +static void +sigbuffer_add_byte (SigBuffer *buf, guint8 val) +{ + MONO_REQ_GC_NEUTRAL_MODE; + + sigbuffer_make_room (buf, 1); + buf->p [0] = val; + buf->p++; +} + +static void +sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size) +{ + MONO_REQ_GC_NEUTRAL_MODE; + + sigbuffer_make_room (buf, size); + memcpy (buf->p, p, size); + buf->p += size; +} + +static void +sigbuffer_free (SigBuffer *buf) +{ + MONO_REQ_GC_NEUTRAL_MODE; + + g_free (buf->buf); +} + +static guint32 +sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf) +{ + MONO_REQ_GC_NEUTRAL_MODE; + + char blob_size [8]; + char *b = blob_size; + guint32 size = buf->p - buf->buf; + /* store length */ + g_assert (size <= (buf->end - buf->buf)); + mono_metadata_encode_value (size, b, &b); + return mono_dynamic_image_add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size); +} + + +static void +encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf) +{ + MONO_REQ_GC_NEUTRAL_MODE; + + int i; + MonoGenericInst *class_inst; + MonoClass *klass; + + g_assert (gclass); + + class_inst = gclass->context.class_inst; + + sigbuffer_add_value (buf, MONO_TYPE_GENERICINST); + klass = gclass->container_class; + sigbuffer_add_value (buf, klass->byval_arg.type); + sigbuffer_add_value (buf, mono_dynimage_encode_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE)); + + sigbuffer_add_value (buf, class_inst->type_argc); + for (i = 0; i < class_inst->type_argc; ++i) + encode_type (assembly, class_inst->type_argv [i], buf); + +} + +static void +encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf) +{ + MONO_REQ_GC_NEUTRAL_MODE; + + if (!type) { + g_assert_not_reached (); + return; + } + + if (type->byref) + sigbuffer_add_value (buf, MONO_TYPE_BYREF); + + switch (type->type){ + case MONO_TYPE_VOID: + case MONO_TYPE_BOOLEAN: + case MONO_TYPE_CHAR: + case MONO_TYPE_I1: + case MONO_TYPE_U1: + case MONO_TYPE_I2: + case MONO_TYPE_U2: + case MONO_TYPE_I4: + case MONO_TYPE_U4: + case MONO_TYPE_I8: + case MONO_TYPE_U8: + case MONO_TYPE_R4: + case MONO_TYPE_R8: + case MONO_TYPE_I: + case MONO_TYPE_U: + case MONO_TYPE_STRING: + case MONO_TYPE_OBJECT: + case MONO_TYPE_TYPEDBYREF: + sigbuffer_add_value (buf, type->type); + break; + case MONO_TYPE_PTR: + sigbuffer_add_value (buf, type->type); + encode_type (assembly, type->data.type, buf); + break; + case MONO_TYPE_SZARRAY: + sigbuffer_add_value (buf, type->type); + encode_type (assembly, &type->data.klass->byval_arg, buf); + break; + case MONO_TYPE_VALUETYPE: + case MONO_TYPE_CLASS: { + MonoClass *k = mono_class_from_mono_type (type); + + if (k->generic_container) { + MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE); + encode_generic_class (assembly, gclass, buf); + } else { + /* + * Make sure we use the correct type. + */ + sigbuffer_add_value (buf, k->byval_arg.type); + /* + * ensure only non-byref gets passed to mono_image_typedef_or_ref(), + * otherwise two typerefs could point to the same type, leading to + * verification errors. + */ + sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg)); + } + break; + } + case MONO_TYPE_ARRAY: + sigbuffer_add_value (buf, type->type); + encode_type (assembly, &type->data.array->eklass->byval_arg, buf); + sigbuffer_add_value (buf, type->data.array->rank); + sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */ + sigbuffer_add_value (buf, 0); + break; + case MONO_TYPE_GENERICINST: + encode_generic_class (assembly, type->data.generic_class, buf); + break; + case MONO_TYPE_VAR: + case MONO_TYPE_MVAR: + sigbuffer_add_value (buf, type->type); + sigbuffer_add_value (buf, mono_type_get_generic_param_num (type)); + break; + default: + g_error ("need to encode type %x", type->type); + } +} + +static void +encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf, MonoError *error) +{ + MONO_REQ_GC_UNSAFE_MODE; + + mono_error_init (error); + + if (!type) { + sigbuffer_add_value (buf, MONO_TYPE_VOID); + return; + } + + MonoType *t = mono_reflection_type_get_handle (type, error); + return_if_nok (error); + encode_type (assembly, t, buf); +} + +static void +encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf, MonoError *error) +{ + MONO_REQ_GC_UNSAFE_MODE; + + int i; + + mono_error_init (error); + + if (modreq) { + for (i = 0; i < mono_array_length (modreq); ++i) { + MonoType *mod = mono_type_array_get_and_resolve (modreq, i, error); + return_if_nok (error); + sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD); + sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod)); + } + } + if (modopt) { + for (i = 0; i < mono_array_length (modopt); ++i) { + MonoType *mod = mono_type_array_get_and_resolve (modopt, i, error); + return_if_nok (error); + sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT); + sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod)); + } + } +} + +#ifndef DISABLE_REFLECTION_EMIT +guint32 +mono_dynimage_encode_method_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig) +{ + MONO_REQ_GC_UNSAFE_MODE; + + SigBuffer buf; + int i; + guint32 nparams = sig->param_count; + guint32 idx; + + if (!assembly->save) + return 0; + + sigbuffer_init (&buf, 32); + /* + * FIXME: vararg, explicit_this, differenc call_conv values... + */ + idx = sig->call_convention; + if (sig->hasthis) + idx |= 0x20; /* hasthis */ + if (sig->generic_param_count) + idx |= 0x10; /* generic */ + sigbuffer_add_byte (&buf, idx); + if (sig->generic_param_count) + sigbuffer_add_value (&buf, sig->generic_param_count); + sigbuffer_add_value (&buf, nparams); + encode_type (assembly, sig->ret, &buf); + for (i = 0; i < nparams; ++i) { + if (i == sig->sentinelpos) + sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL); + encode_type (assembly, sig->params [i], &buf); + } + idx = sigbuffer_add_to_blob_cached (assembly, &buf); + sigbuffer_free (&buf); + return idx; +} +#else /* DISABLE_REFLECTION_EMIT */ +guint32 +mono_dynimage_encode_method_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig) +{ + g_assert_not_reached (); + return 0; +} +#endif + +guint32 +mono_dynimage_encode_method_builder_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error) +{ + MONO_REQ_GC_UNSAFE_MODE; + + mono_error_init (error); + + /* + * FIXME: reuse code from method_encode_signature(). + */ + SigBuffer buf; + int i; + guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0; + guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0; + guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0; + guint32 idx; + + sigbuffer_init (&buf, 32); + /* LAMESPEC: all the call conv spec is foobared */ + idx = mb->call_conv & 0x60; /* has-this, explicit-this */ + if (mb->call_conv & 2) + idx |= 0x5; /* vararg */ + if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC)) + idx |= 0x20; /* hasthis */ + if (ngparams) + idx |= 0x10; /* generic */ + sigbuffer_add_byte (&buf, idx); + if (ngparams) + sigbuffer_add_value (&buf, ngparams); + sigbuffer_add_value (&buf, nparams + notypes); + encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf, error); + if (!is_ok (error)) + goto leave; + encode_reflection_type (assembly, mb->rtype, &buf, error); + if (!is_ok (error)) + goto leave; + for (i = 0; i < nparams; ++i) { + MonoArray *modreq = NULL; + MonoArray *modopt = NULL; + MonoReflectionType *pt; + + if (mb->param_modreq && (i < mono_array_length (mb->param_modreq))) + modreq = mono_array_get (mb->param_modreq, MonoArray*, i); + if (mb->param_modopt && (i < mono_array_length (mb->param_modopt))) + modopt = mono_array_get (mb->param_modopt, MonoArray*, i); + encode_custom_modifiers (assembly, modreq, modopt, &buf, error); + if (!is_ok (error)) + goto leave; + pt = mono_array_get (mb->parameters, MonoReflectionType*, i); + encode_reflection_type (assembly, pt, &buf, error); + if (!is_ok (error)) + goto leave; + } + if (notypes) + sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL); + for (i = 0; i < notypes; ++i) { + MonoReflectionType *pt; + + pt = mono_array_get (mb->opt_types, MonoReflectionType*, i); + encode_reflection_type (assembly, pt, &buf, error); + if (!is_ok (error)) + goto leave; + } + + idx = sigbuffer_add_to_blob_cached (assembly, &buf); +leave: + sigbuffer_free (&buf); + return idx; +} + +guint32 +mono_dynimage_encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, MonoError *error) +{ + MONO_REQ_GC_UNSAFE_MODE; + + mono_error_init (error); + + MonoDynamicTable *table; + guint32 *values; + guint32 idx, sig_idx; + guint nl = mono_array_length (ilgen->locals); + SigBuffer buf; + int i; + + sigbuffer_init (&buf, 32); + sigbuffer_add_value (&buf, 0x07); + sigbuffer_add_value (&buf, nl); + for (i = 0; i < nl; ++i) { + MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i); + + if (lb->is_pinned) + sigbuffer_add_value (&buf, MONO_TYPE_PINNED); + + encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf, error); + if (!is_ok (error)) { + sigbuffer_free (&buf); + return 0; + } + } + sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf); + sigbuffer_free (&buf); + + if (assembly->standalonesig_cache == NULL) + assembly->standalonesig_cache = g_hash_table_new (NULL, NULL); + idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx))); + if (idx) + return idx; + + table = &assembly->tables [MONO_TABLE_STANDALONESIG]; + idx = table->next_idx ++; + table->rows ++; + alloc_table (table, table->rows); + values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE; + + values [MONO_STAND_ALONE_SIGNATURE] = sig_idx; + + g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx)); + + return idx; +} + + +/* + * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary. + * dest may be misaligned. + */ +static void +swap_with_size (char *dest, const char* val, int len, int nelem) { + MONO_REQ_GC_NEUTRAL_MODE; +#if G_BYTE_ORDER != G_LITTLE_ENDIAN + int elem; + + for (elem = 0; elem < nelem; ++elem) { + switch (len) { + case 1: + *dest = *val; + break; + case 2: + dest [0] = val [1]; + dest [1] = val [0]; + break; + case 4: + dest [0] = val [3]; + dest [1] = val [2]; + dest [2] = val [1]; + dest [3] = val [0]; + break; + case 8: + dest [0] = val [7]; + dest [1] = val [6]; + dest [2] = val [5]; + dest [3] = val [4]; + dest [4] = val [3]; + dest [5] = val [2]; + dest [6] = val [1]; + dest [7] = val [0]; + break; + default: + g_assert_not_reached (); + } + dest += len; + val += len; + } +#else + memcpy (dest, val, len * nelem); +#endif +} + + +guint32 +mono_dynimage_encode_constant (MonoDynamicImage *assembly, MonoObject *val, MonoTypeEnum *ret_type) +{ + MONO_REQ_GC_UNSAFE_MODE; + + char blob_size [64]; + char *b = blob_size; + char *box_val; + char* buf; + guint32 idx = 0, len = 0, dummy = 0; + + buf = (char *)g_malloc (64); + if (!val) { + *ret_type = MONO_TYPE_CLASS; + len = 4; + box_val = (char*)&dummy; + } else { + box_val = ((char*)val) + sizeof (MonoObject); + *ret_type = val->vtable->klass->byval_arg.type; + } +handle_enum: + switch (*ret_type) { + case MONO_TYPE_BOOLEAN: + case MONO_TYPE_U1: + case MONO_TYPE_I1: + len = 1; + break; + case MONO_TYPE_CHAR: + case MONO_TYPE_U2: + case MONO_TYPE_I2: + len = 2; + break; + case MONO_TYPE_U4: + case MONO_TYPE_I4: + case MONO_TYPE_R4: + len = 4; + break; + case MONO_TYPE_U8: + case MONO_TYPE_I8: + len = 8; + break; + case MONO_TYPE_R8: + len = 8; + break; + case MONO_TYPE_VALUETYPE: { + MonoClass *klass = val->vtable->klass; + + if (klass->enumtype) { + *ret_type = mono_class_enum_basetype (klass)->type; + goto handle_enum; + } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) { + len = 8; + } else + g_error ("we can't encode valuetypes, we should have never reached this line"); + break; + } + case MONO_TYPE_CLASS: + break; + case MONO_TYPE_STRING: { + MonoString *str = (MonoString*)val; + /* there is no signature */ + len = str->length * 2; + mono_metadata_encode_value (len, b, &b); +#if G_BYTE_ORDER != G_LITTLE_ENDIAN + { + char *swapped = g_malloc (2 * mono_string_length (str)); + const char *p = (const char*)mono_string_chars (str); + + swap_with_size (swapped, p, 2, mono_string_length (str)); + idx = mono_dynamic_image_add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len); + g_free (swapped); + } +#else + idx = mono_dynamic_image_add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len); +#endif + + g_free (buf); + return idx; + } + case MONO_TYPE_GENERICINST: + *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type; + goto handle_enum; + default: + g_error ("we don't encode constant type 0x%02x yet", *ret_type); + } + + /* there is no signature */ + mono_metadata_encode_value (len, b, &b); +#if G_BYTE_ORDER != G_LITTLE_ENDIAN + idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size); + swap_with_size (blob_size, box_val, len, 1); + mono_image_add_stream_data (&assembly->blob, blob_size, len); +#else + idx = mono_dynamic_image_add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len); +#endif + + g_free (buf); + return idx; +} + + +guint32 +mono_dynimage_encode_field_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error) +{ + MONO_REQ_GC_UNSAFE_MODE; + + mono_error_init (error); + + SigBuffer buf; + guint32 idx; + guint32 typespec = 0; + MonoType *type; + MonoClass *klass; + + mono_reflection_init_type_builder_generics (fb->type, error); + return_val_if_nok (error, 0); + + type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error); + return_val_if_nok (error, 0); + klass = mono_class_from_mono_type (type); + + sigbuffer_init (&buf, 32); + + sigbuffer_add_value (&buf, 0x06); + encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf, error); + if (!is_ok (error)) + goto fail; + /* encode custom attributes before the type */ + + if (klass->generic_container) + typespec = create_typespec (assembly, type); + + if (typespec) { + MonoGenericClass *gclass; + gclass = mono_metadata_lookup_generic_class (klass, klass->generic_container->context.class_inst, TRUE); + encode_generic_class (assembly, gclass, &buf); + } else { + encode_type (assembly, type, &buf); + } + idx = sigbuffer_add_to_blob_cached (assembly, &buf); + sigbuffer_free (&buf); + return idx; +fail: + sigbuffer_free (&buf); + return 0; +} + +#ifndef DISABLE_REFLECTION_EMIT +/*field_image is the image to which the eventual custom mods have been encoded against*/ +guint32 +mono_dynimage_encode_fieldref_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type) +{ + MONO_REQ_GC_NEUTRAL_MODE; + + SigBuffer buf; + guint32 idx, i, token; + + if (!assembly->save) + return 0; + + sigbuffer_init (&buf, 32); + + sigbuffer_add_value (&buf, 0x06); + /* encode custom attributes before the type */ + if (type->num_mods) { + for (i = 0; i < type->num_mods; ++i) { + if (field_image) { + MonoError error; + MonoClass *klass = mono_class_get_checked (field_image, type->modifiers [i].token, &error); + g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */ + + token = mono_image_typedef_or_ref (assembly, &klass->byval_arg); + } else { + token = type->modifiers [i].token; + } + + if (type->modifiers [i].required) + sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD); + else + sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT); + + sigbuffer_add_value (&buf, token); + } + } + encode_type (assembly, type, &buf); + idx = sigbuffer_add_to_blob_cached (assembly, &buf); + sigbuffer_free (&buf); + return idx; +} +#else /* DISABLE_REFLECTION_EMIT */ +guint32 +mono_dynimage_encode_fieldref_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type) +{ + g_assert_not_reached (); + return 0; +} +#endif /* DISABLE_REFLECTION_EMIT */ + +static guint32 +create_typespec (MonoDynamicImage *assembly, MonoType *type) +{ + MONO_REQ_GC_NEUTRAL_MODE; + + MonoDynamicTable *table; + guint32 *values; + guint32 token; + SigBuffer buf; + + if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type)))) + return token; + + sigbuffer_init (&buf, 32); + switch (type->type) { + case MONO_TYPE_FNPTR: + case MONO_TYPE_PTR: + case MONO_TYPE_SZARRAY: + case MONO_TYPE_ARRAY: + case MONO_TYPE_VAR: + case MONO_TYPE_MVAR: + case MONO_TYPE_GENERICINST: + encode_type (assembly, type, &buf); + break; + case MONO_TYPE_CLASS: + case MONO_TYPE_VALUETYPE: { + MonoClass *k = mono_class_from_mono_type (type); + if (!k || !k->generic_container) { + sigbuffer_free (&buf); + return 0; + } + encode_type (assembly, type, &buf); + break; + } + default: + sigbuffer_free (&buf); + return 0; + } + + table = &assembly->tables [MONO_TABLE_TYPESPEC]; + if (assembly->save) { + token = sigbuffer_add_to_blob_cached (assembly, &buf); + alloc_table (table, table->rows + 1); + values = table->values + table->next_idx * MONO_TYPESPEC_SIZE; + values [MONO_TYPESPEC_SIGNATURE] = token; + } + sigbuffer_free (&buf); + + token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS); + g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token)); + table->next_idx ++; + return token; +} + +guint32 +mono_dynimage_encode_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec) +{ + MONO_REQ_GC_UNSAFE_MODE; + + MonoDynamicTable *table; + guint32 *values; + guint32 token, scope, enclosing; + MonoClass *klass; + + /* if the type requires a typespec, we must try that first*/ + if (try_typespec && (token = create_typespec (assembly, type))) + return token; + token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type)); + if (token) + return token; + klass = mono_class_from_mono_type (type); + if (!klass) + klass = mono_class_from_mono_type (type); + + /* + * If it's in the same module and not a generic type parameter: + */ + if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) && + (type->type != MONO_TYPE_MVAR)) { + MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass); + token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS); + mono_dynamic_image_register_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass)); + return token; + } + + if (klass->nested_in) { + enclosing = mono_dynimage_encode_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE); + /* get the typeref idx of the enclosing type */ + enclosing >>= MONO_TYPEDEFORREF_BITS; + scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF; + } else { + scope = mono_reflection_resolution_scope_from_image (assembly, klass->image); + } + table = &assembly->tables [MONO_TABLE_TYPEREF]; + if (assembly->save) { + alloc_table (table, table->rows + 1); + values = table->values + table->next_idx * MONO_TYPEREF_SIZE; + values [MONO_TYPEREF_SCOPE] = scope; + values [MONO_TYPEREF_NAME] = mono_dynstream_insert_string (&assembly->sheap, klass->name); + values [MONO_TYPEREF_NAMESPACE] = mono_dynstream_insert_string (&assembly->sheap, klass->name_space); + } + token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */ + g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token)); + table->next_idx ++; + mono_dynamic_image_register_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass)); + return token; +} + +/* + * Despite the name, we handle also TypeSpec (with the above helper). + */ +static guint32 +mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type) +{ + return mono_dynimage_encode_typedef_or_ref_full (assembly, type, TRUE); +} + +guint32 +mono_dynimage_encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb) +{ + SigBuffer buf; + int i; + guint32 nparams = mono_array_length (mb->generic_params); + guint32 idx; + + if (!assembly->save) + return 0; + + sigbuffer_init (&buf, 32); + + sigbuffer_add_value (&buf, 0xa); + sigbuffer_add_value (&buf, nparams); + + for (i = 0; i < nparams; i++) { + sigbuffer_add_value (&buf, MONO_TYPE_MVAR); + sigbuffer_add_value (&buf, i); + } + + idx = sigbuffer_add_to_blob_cached (assembly, &buf); + sigbuffer_free (&buf); + return idx; +} + +guint32 +mono_dynimage_encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context) +{ + SigBuffer buf; + int i; + guint32 nparams = context->method_inst->type_argc; + guint32 idx; + + if (!assembly->save) + return 0; + + sigbuffer_init (&buf, 32); + /* + * FIXME: vararg, explicit_this, differenc call_conv values... + */ + sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */ + sigbuffer_add_value (&buf, nparams); + + for (i = 0; i < nparams; i++) + encode_type (assembly, context->method_inst->type_argv [i], &buf); + + idx = sigbuffer_add_to_blob_cached (assembly, &buf); + sigbuffer_free (&buf); + return idx; +} + +#ifndef DISABLE_REFLECTION_EMIT +guint32 +mono_dynimage_encode_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error) +{ + MonoDynamicTable *table; + MonoClass *klass; + MonoType *type; + guint32 *values; + guint32 token; + SigBuffer buf; + int count, i; + + /* + * We're creating a TypeSpec for the TypeBuilder of a generic type declaration, + * ie. what we'd normally use as the generic type in a TypeSpec signature. + * Because of this, we must not insert it into the `typeref' hash table. + */ + type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error); + return_val_if_nok (error, 0); + token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type)); + if (token) + return token; + + sigbuffer_init (&buf, 32); + + g_assert (tb->generic_params); + klass = mono_class_from_mono_type (type); + + if (tb->generic_container) { + if (!mono_reflection_create_generic_class (tb, error)) + goto fail; + } + + sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST); + g_assert (klass->generic_container); + sigbuffer_add_value (&buf, klass->byval_arg.type); + sigbuffer_add_value (&buf, mono_dynimage_encode_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE)); + + count = mono_array_length (tb->generic_params); + sigbuffer_add_value (&buf, count); + for (i = 0; i < count; i++) { + MonoReflectionGenericParam *gparam; + + gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i); + MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, error); + if (!is_ok (error)) + goto fail; + + encode_type (assembly, gparam_type, &buf); + } + + table = &assembly->tables [MONO_TABLE_TYPESPEC]; + + if (assembly->save) { + token = sigbuffer_add_to_blob_cached (assembly, &buf); + alloc_table (table, table->rows + 1); + values = table->values + table->next_idx * MONO_TYPESPEC_SIZE; + values [MONO_TYPESPEC_SIGNATURE] = token; + } + sigbuffer_free (&buf); + + token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS); + g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token)); + table->next_idx ++; + return token; +fail: + sigbuffer_free (&buf); + return 0; +} +#else /*DISABLE_REFLECTION_EMIT*/ +guint32 +mono_dynimage_encode_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error) +{ + g_assert_not_reached (); + return 0; +} +#endif /*DISABLE_REFLECTION_EMIT*/ + +#ifndef DISABLE_REFLECTION_EMIT +guint32 +mono_dynimage_encode_reflection_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error) +{ + SigBuffer buf; + guint32 nargs; + guint32 i, idx; + + mono_error_init (error); + + if (!assembly->save) + return 0; + + /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */ + g_assert (helper->type == 2); + + if (helper->arguments) + nargs = mono_array_length (helper->arguments); + else + nargs = 0; + + sigbuffer_init (&buf, 32); + + /* Encode calling convention */ + /* Change Any to Standard */ + if ((helper->call_conv & 0x03) == 0x03) + helper->call_conv = 0x01; + /* explicit_this implies has_this */ + if (helper->call_conv & 0x40) + helper->call_conv &= 0x20; + + if (helper->call_conv == 0) { /* Unmanaged */ + idx = helper->unmanaged_call_conv - 1; + } else { + /* Managed */ + idx = helper->call_conv & 0x60; /* has_this + explicit_this */ + if (helper->call_conv & 0x02) /* varargs */ + idx += 0x05; + } + + sigbuffer_add_byte (&buf, idx); + sigbuffer_add_value (&buf, nargs); + encode_reflection_type (assembly, helper->return_type, &buf, error); + if (!is_ok (error)) + goto fail; + for (i = 0; i < nargs; ++i) { + MonoArray *modreqs = NULL; + MonoArray *modopts = NULL; + MonoReflectionType *pt; + + if (helper->modreqs && (i < mono_array_length (helper->modreqs))) + modreqs = mono_array_get (helper->modreqs, MonoArray*, i); + if (helper->modopts && (i < mono_array_length (helper->modopts))) + modopts = mono_array_get (helper->modopts, MonoArray*, i); + + encode_custom_modifiers (assembly, modreqs, modopts, &buf, error); + if (!is_ok (error)) + goto fail; + pt = mono_array_get (helper->arguments, MonoReflectionType*, i); + encode_reflection_type (assembly, pt, &buf, error); + if (!is_ok (error)) + goto fail; + } + idx = sigbuffer_add_to_blob_cached (assembly, &buf); + sigbuffer_free (&buf); + + return idx; +fail: + sigbuffer_free (&buf); + return 0; +} +#else /* DISABLE_REFLECTION_EMIT */ +guint32 +mono_dynimage_encode_reflection_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error) +{ + g_assert_not_reached (); + return 0; +} +#endif /* DISABLE_REFLECTION_EMIT */ + +static MonoArray * +reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig, MonoError *error) +{ + MonoReflectionModuleBuilder *module = sig->module; + MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL; + guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0; + guint32 buflen, i; + MonoArray *result; + SigBuffer buf; + + mono_error_init (error); + + sigbuffer_init (&buf, 32); + + sigbuffer_add_value (&buf, 0x07); + sigbuffer_add_value (&buf, na); + if (assembly != NULL){ + for (i = 0; i < na; ++i) { + MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i); + encode_reflection_type (assembly, type, &buf, error); + if (!is_ok (error)) goto fail; + } + } + + buflen = buf.p - buf.buf; + result = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, buflen, error); + if (!is_ok (error)) goto fail; + memcpy (mono_array_addr (result, char, 0), buf.buf, buflen); + sigbuffer_free (&buf); + return result; +fail: + sigbuffer_free (&buf); + return NULL; +} + +static MonoArray * +reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig, MonoError *error) +{ + MonoDynamicImage *assembly = sig->module->dynamic_image; + guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0; + guint32 buflen, i; + MonoArray *result; + SigBuffer buf; + + mono_error_init (error); + + sigbuffer_init (&buf, 32); + + sigbuffer_add_value (&buf, 0x06); + for (i = 0; i < na; ++i) { + MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i); + encode_reflection_type (assembly, type, &buf, error); + if (!is_ok (error)) + goto fail; + } + + buflen = buf.p - buf.buf; + result = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, buflen, error); + if (!is_ok (error)) goto fail; + memcpy (mono_array_addr (result, char, 0), buf.buf, buflen); + sigbuffer_free (&buf); + + return result; +fail: + sigbuffer_free (&buf); + return NULL; +} + +static char* +type_get_fully_qualified_name (MonoType *type) +{ + MONO_REQ_GC_NEUTRAL_MODE; + + return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED); +} + +#ifndef DISABLE_REFLECTION_EMIT_SAVE +guint32 +mono_dynimage_save_encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error) +{ + MONO_REQ_GC_UNSAFE_MODE; + + mono_error_init (error); + + char *str; + SigBuffer buf; + guint32 idx, len; + + sigbuffer_init (&buf, 32); + + sigbuffer_add_value (&buf, minfo->type); + + switch (minfo->type) { + case MONO_NATIVE_BYVALTSTR: + case MONO_NATIVE_BYVALARRAY: + sigbuffer_add_value (&buf, minfo->count); + break; + case MONO_NATIVE_LPARRAY: + if (minfo->eltype || minfo->has_size) { + sigbuffer_add_value (&buf, minfo->eltype); + if (minfo->has_size) { + sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0); + sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0); + + /* LAMESPEC: ElemMult is undocumented */ + sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0); + } + } + break; + case MONO_NATIVE_SAFEARRAY: + if (minfo->eltype) + sigbuffer_add_value (&buf, minfo->eltype); + break; + case MONO_NATIVE_CUSTOM: + if (minfo->guid) { + str = mono_string_to_utf8_checked (minfo->guid, error); + if (!is_ok (error)) { + sigbuffer_free (&buf); + return 0; + } + len = strlen (str); + sigbuffer_add_value (&buf, len); + sigbuffer_add_mem (&buf, str, len); + g_free (str); + } else { + sigbuffer_add_value (&buf, 0); + } + /* native type name */ + sigbuffer_add_value (&buf, 0); + /* custom marshaler type name */ + if (minfo->marshaltype || minfo->marshaltyperef) { + if (minfo->marshaltyperef) { + MonoType *marshaltype = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error); + if (!is_ok (error)) { + sigbuffer_free (&buf); + return 0; + } + str = type_get_fully_qualified_name (marshaltype); + } else { + str = mono_string_to_utf8_checked (minfo->marshaltype, error); + if (!is_ok (error)) { + sigbuffer_free (&buf); + return 0; + } + } + len = strlen (str); + sigbuffer_add_value (&buf, len); + sigbuffer_add_mem (&buf, str, len); + g_free (str); + } else { + /* FIXME: Actually a bug, since this field is required. Punting for now ... */ + sigbuffer_add_value (&buf, 0); + } + if (minfo->mcookie) { + str = mono_string_to_utf8_checked (minfo->mcookie, error); + if (!is_ok (error)) { + sigbuffer_free (&buf); + return 0; + } + len = strlen (str); + sigbuffer_add_value (&buf, len); + sigbuffer_add_mem (&buf, str, len); + g_free (str); + } else { + sigbuffer_add_value (&buf, 0); + } + break; + default: + break; + } + idx = sigbuffer_add_to_blob_cached (assembly, &buf); + sigbuffer_free (&buf); + return idx; +} + +guint32 +mono_dynimage_save_encode_property_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb, MonoError *error) +{ + MONO_REQ_GC_UNSAFE_MODE; + + mono_error_init (error); + + SigBuffer buf; + guint32 nparams = 0; + MonoReflectionMethodBuilder *mb = fb->get_method; + MonoReflectionMethodBuilder *smb = fb->set_method; + guint32 idx, i; + + if (mb && mb->parameters) + nparams = mono_array_length (mb->parameters); + if (!mb && smb && smb->parameters) + nparams = mono_array_length (smb->parameters) - 1; + sigbuffer_init (&buf, 32); + if (fb->call_conv & 0x20) + sigbuffer_add_byte (&buf, 0x28); + else + sigbuffer_add_byte (&buf, 0x08); + sigbuffer_add_value (&buf, nparams); + if (mb) { + encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf, error); + if (!is_ok (error)) + goto fail; + for (i = 0; i < nparams; ++i) { + MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i); + encode_reflection_type (assembly, pt, &buf, error); + if (!is_ok (error)) + goto fail; + } + } else if (smb && smb->parameters) { + /* the property type is the last param */ + encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf, error); + if (!is_ok (error)) + goto fail; + + for (i = 0; i < nparams; ++i) { + MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i); + encode_reflection_type (assembly, pt, &buf, error); + if (!is_ok (error)) + goto fail; + } + } else { + encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf, error); + if (!is_ok (error)) + goto fail; + } + + idx = sigbuffer_add_to_blob_cached (assembly, &buf); + sigbuffer_free (&buf); + return idx; +fail: + sigbuffer_free (&buf); + return 0; +} + + +#else /*DISABLE_REFLECTION_EMIT_SAVE*/ +guint32 +mono_dynimage_save_encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error) +{ + g_assert_not_reached (); + return 0; +} + +guint32 +mono_dynimage_save_encode_property_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb, MonoError *error) +{ + g_assert_not_reached (); + return 0; +} +#endif /*DISABLE_REFLECTION_EMIT_SAVE*/ + +#ifndef DISABLE_REFLECTION_EMIT +MonoArray * +ves_icall_SignatureHelper_get_signature_local (MonoReflectionSigHelper *sig) +{ + MonoError error; + MonoArray *result = reflection_sighelper_get_signature_local (sig, &error); + mono_error_set_pending_exception (&error); + return result; +} + +MonoArray * +ves_icall_SignatureHelper_get_signature_field (MonoReflectionSigHelper *sig) +{ + MonoError error; + MonoArray *result = reflection_sighelper_get_signature_field (sig, &error); + mono_error_set_pending_exception (&error); + return result; +} +#else /* DISABLE_REFLECTION_EMIT */ +MonoArray * +ves_icall_SignatureHelper_get_signature_local (MonoReflectionSigHelper *sig) +{ + g_assert_not_reached (); + return NULL; +} + +MonoArray * +ves_icall_SignatureHelper_get_signature_field (MonoReflectionSigHelper *sig) +{ + g_assert_not_reached (); + return NULL; +} + +#endif /* DISABLE_REFLECTION_EMIT */ diff --git a/mono/metadata/sre-internals.h b/mono/metadata/sre-internals.h new file mode 100644 index 0000000000..87d823a22e --- /dev/null +++ b/mono/metadata/sre-internals.h @@ -0,0 +1,157 @@ +/* + * Copyright 2016 Microsoft + * Licensed under the MIT license. See LICENSE file in the project root for full license information. + */ +#ifndef __MONO_METADATA_SRE_INTERNALS_H__ +#define __MONO_METADATA_SRE_INTERNALS_H__ + +#include + +typedef struct _ArrayMethod ArrayMethod; + +typedef struct { + guint32 owner; + MonoReflectionGenericParam *gparam; +} GenericParamTableEntry; + +typedef struct { + MonoReflectionILGen *ilgen; + MonoReflectionType *rtype; + MonoArray *parameters; + MonoArray *generic_params; + MonoGenericContainer *generic_container; + MonoArray *pinfo; + MonoArray *opt_types; + guint32 attrs; + guint32 iattrs; + guint32 call_conv; + guint32 *table_idx; /* note: it's a pointer */ + MonoArray *code; + MonoObject *type; + MonoString *name; + MonoBoolean init_locals; + MonoBoolean skip_visibility; + MonoArray *return_modreq; + MonoArray *return_modopt; + MonoArray *param_modreq; + MonoArray *param_modopt; + MonoArray *permissions; + MonoMethod *mhandle; + guint32 nrefs; + gpointer *refs; + /* for PInvoke */ + int charset, extra_flags, native_cc; + MonoString *dll, *dllentry; +} ReflectionMethodBuilder; + +void +mono_reflection_emit_init (void); + +void +mono_reflection_dynimage_basic_init (MonoReflectionAssemblyBuilder *assemblyb); + +gpointer +mono_image_g_malloc0 (MonoImage *image, guint size); + +gboolean +mono_is_sre_type_builder (MonoClass *klass); + +gboolean +mono_is_sre_generic_instance (MonoClass *klass); + +gboolean +mono_is_sre_method_on_tb_inst (MonoClass *klass); + +gboolean +mono_is_sre_ctor_builder (MonoClass *klass); + +gboolean +mono_is_sre_ctor_on_tb_inst (MonoClass *klass); + +gboolean +mono_is_sr_mono_cmethod (MonoClass *klass); + +gboolean +mono_is_sr_mono_property (MonoClass *klass); + +gboolean +mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb, MonoError *error); + +MonoMethod* +mono_reflection_method_builder_to_mono_method (MonoReflectionMethodBuilder *mb, MonoError *error); + +MonoMethod* +mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m, MonoError *error); + +gpointer +mono_reflection_resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context, MonoError *error); + +void +mono_sre_array_method_free (ArrayMethod *am); + +void +mono_sre_generic_param_table_entry_free (GenericParamTableEntry *entry); + +gboolean +mono_reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, + MonoError *error); +gboolean +mono_reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, + MonoError *error); + +void +mono_reflection_init_type_builder_generics (MonoObject *type, MonoError *error); + +guint32 +mono_reflection_resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image); + +guint32 mono_reflection_method_count_clauses (MonoReflectionILGen *ilgen); + + +/* sre-encode */ + +guint32 +mono_dynimage_encode_field_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error); + +guint32 +mono_dynimage_encode_constant (MonoDynamicImage *assembly, MonoObject *val, MonoTypeEnum *ret_type); + +guint32 +mono_dynimage_encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, MonoError *error); + +guint32 +mono_dynimage_encode_fieldref_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type); + +guint32 +mono_dynimage_encode_method_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig); + +guint32 +mono_dynimage_encode_method_builder_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, + MonoError *error); + +guint32 +mono_dynimage_encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb); + +guint32 +mono_dynimage_encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context); + +guint32 +mono_dynimage_encode_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error); + +guint32 +mono_dynimage_encode_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec); + +guint32 +mono_dynimage_encode_reflection_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, + MonoError *error); + +/* sre-encode, without DISABLE_REFLECTION_EMIT_SAVE (o.w. g_assert_not_reached ()) */ + +guint32 +mono_dynimage_save_encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error); + +guint32 +mono_dynimage_save_encode_property_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb, MonoError *error); + +#endif /* __MONO_METADATA_SRE_INTERNALS_H__ */ + diff --git a/mono/metadata/sre-save.c.REMOVED.git-id b/mono/metadata/sre-save.c.REMOVED.git-id new file mode 100644 index 0000000000..5894391c66 --- /dev/null +++ b/mono/metadata/sre-save.c.REMOVED.git-id @@ -0,0 +1 @@ +ff2f93a767be1a8ef630b34a058a2fa076a48db5 \ No newline at end of file diff --git a/mono/metadata/sre.c.REMOVED.git-id b/mono/metadata/sre.c.REMOVED.git-id new file mode 100644 index 0000000000..fa0facd677 --- /dev/null +++ b/mono/metadata/sre.c.REMOVED.git-id @@ -0,0 +1 @@ +c15bd42b74aabd2b63709a831bcd20cc338e128d \ No newline at end of file diff --git a/mono/metadata/threadpool-ms-io.c b/mono/metadata/threadpool-ms-io.c index b78ca83b28..7cdaf5be68 100644 --- a/mono/metadata/threadpool-ms-io.c +++ b/mono/metadata/threadpool-ms-io.c @@ -565,7 +565,7 @@ ves_icall_System_IOSelector_Add (gpointer handle, MonoIOSelectorJob *job) { ThreadPoolIOUpdate *update; - g_assert (handle >= 0); + g_assert (handle); g_assert ((job->operation == EVENT_IN) ^ (job->operation == EVENT_OUT)); g_assert (job->callback); diff --git a/mono/metadata/threadpool-ms.c b/mono/metadata/threadpool-ms.c index 1f4a6cc605..3eaa48dc51 100644 --- a/mono/metadata/threadpool-ms.c +++ b/mono/metadata/threadpool-ms.c @@ -159,6 +159,11 @@ typedef struct { gboolean suspended; } ThreadPool; +typedef struct { + gint32 ref; + MonoCoopCond cond; +} ThreadPoolDomainCleanupSemaphore; + typedef enum { TRANSITION_WARMUP, TRANSITION_INITIALIZING, @@ -430,6 +435,14 @@ domain_get (MonoDomain *domain, gboolean create) } if (create) { + ThreadPoolDomainCleanupSemaphore *cleanup_semaphore; + cleanup_semaphore = g_new0 (ThreadPoolDomainCleanupSemaphore, 1); + cleanup_semaphore->ref = 2; + mono_coop_cond_init (&cleanup_semaphore->cond); + + g_assert(!domain->cleanup_semaphore); + domain->cleanup_semaphore = cleanup_semaphore; + tpdomain = g_new0 (ThreadPoolDomain, 1); tpdomain->domain = domain; domain_add (tpdomain); @@ -476,7 +489,7 @@ domain_get_next (ThreadPoolDomain *current) break; } } - g_assert (current_idx >= 0); + g_assert (current_idx != (guint)-1); } for (i = current_idx + 1; i < len + current_idx + 1; ++i) { ThreadPoolDomain *tmp = (ThreadPoolDomain *)g_ptr_array_index (threadpool->domains, i % len); @@ -635,6 +648,9 @@ worker_thread (gpointer data) if (retire) retire = FALSE; + /* The tpdomain->domain might have unloaded, while this thread was parked */ + previous_tpdomain = NULL; + continue; } @@ -678,10 +694,23 @@ worker_thread (gpointer data) g_assert (tpdomain->domain->threadpool_jobs >= 0); if (tpdomain->domain->threadpool_jobs == 0 && mono_domain_is_unloading (tpdomain->domain)) { - gboolean removed = domain_remove (tpdomain); + ThreadPoolDomainCleanupSemaphore *cleanup_semaphore; + gboolean removed; + + removed = domain_remove(tpdomain); g_assert (removed); - if (tpdomain->domain->cleanup_semaphore) - ReleaseSemaphore (tpdomain->domain->cleanup_semaphore, 1, NULL); + + cleanup_semaphore = (ThreadPoolDomainCleanupSemaphore*) tpdomain->domain->cleanup_semaphore; + g_assert (cleanup_semaphore); + + mono_coop_cond_signal (&cleanup_semaphore->cond); + + if (InterlockedDecrement (&cleanup_semaphore->ref) == 0) { + mono_coop_cond_destroy (&cleanup_semaphore->cond); + g_free (cleanup_semaphore); + tpdomain->domain->cleanup_semaphore = NULL; + } + domain_free (tpdomain); tpdomain = NULL; } @@ -1424,9 +1453,10 @@ mono_threadpool_ms_end_invoke (MonoAsyncResult *ares, MonoArray **out_args, Mono gboolean mono_threadpool_ms_remove_domain_jobs (MonoDomain *domain, int timeout) { - gboolean res = TRUE; gint64 end; - gpointer sem; + ThreadPoolDomain *tpdomain; + ThreadPoolDomainCleanupSemaphore *cleanup_semaphore; + gboolean ret; g_assert (domain); g_assert (timeout >= -1); @@ -1445,38 +1475,59 @@ mono_threadpool_ms_remove_domain_jobs (MonoDomain *domain, int timeout) #endif /* - * There might be some threads out that could be about to execute stuff from the given domain. - * We avoid that by setting up a semaphore to be pulsed by the thread that reaches zero. - */ - sem = domain->cleanup_semaphore = CreateSemaphore (NULL, 0, 1, NULL); + * There might be some threads out that could be about to execute stuff from the given domain. + * We avoid that by waiting on a semaphore to be pulsed by the thread that reaches zero. + * The semaphore is only created for domains which queued threadpool jobs. + * We always wait on the semaphore rather than ensuring domain->threadpool_jobs is 0. + * There may be pending outstanding requests which will create new jobs. + * The semaphore is signaled the threadpool domain has been removed from list + * and we know no more jobs for the domain will be processed. + */ - /* - * The memory barrier here is required to have global ordering between assigning to cleanup_semaphone - * and reading threadpool_jobs. Otherwise this thread could read a stale version of threadpool_jobs - * and wait forever. - */ - mono_memory_write_barrier (); + mono_lazy_initialize(&status, initialize); + mono_coop_mutex_lock(&threadpool->domains_lock); - while (domain->threadpool_jobs) { - gint64 now; + tpdomain = domain_get (domain, FALSE); + if (!tpdomain || tpdomain->outstanding_request == 0) { + mono_coop_mutex_unlock(&threadpool->domains_lock); + return TRUE; + } - if (timeout != -1) { - now = mono_msec_ticks (); + g_assert (domain->cleanup_semaphore); + cleanup_semaphore = (ThreadPoolDomainCleanupSemaphore*) domain->cleanup_semaphore; + + ret = TRUE; + + do { + if (timeout == -1) { + mono_coop_cond_wait (&cleanup_semaphore->cond, &threadpool->domains_lock); + } else { + gint64 now; + gint res; + + now = mono_msec_ticks(); if (now > end) { - res = FALSE; + ret = FALSE; + break; + } + + res = mono_coop_cond_timedwait (&cleanup_semaphore->cond, &threadpool->domains_lock, end - now); + if (res != 0) { + ret = FALSE; break; } } + } while (tpdomain->outstanding_request != 0); - MONO_ENTER_GC_SAFE; - WaitForSingleObject (sem, timeout != -1 ? end - now : timeout); - MONO_EXIT_GC_SAFE; + if (InterlockedDecrement (&cleanup_semaphore->ref) == 0) { + mono_coop_cond_destroy (&cleanup_semaphore->cond); + g_free (cleanup_semaphore); + domain->cleanup_semaphore = NULL; } - domain->cleanup_semaphore = NULL; - CloseHandle (sem); + mono_coop_mutex_unlock(&threadpool->domains_lock); - return res; + return ret; } void diff --git a/mono/metadata/threads-types.h b/mono/metadata/threads-types.h index 68f8ec7851..e27e89bb6f 100644 --- a/mono/metadata/threads-types.h +++ b/mono/metadata/threads-types.h @@ -42,21 +42,12 @@ typedef enum { ThreadApartmentState_Unknown = 0x00000002 } MonoThreadApartmentState; -typedef enum { - ThreadPriority_Lowest = 0, - ThreadPriority_BelowNormal = 1, - ThreadPriority_Normal = 2, - ThreadPriority_AboveNormal = 3, - ThreadPriority_Highest = 4 -} MonoThreadPriority; - #define SPECIAL_STATIC_NONE 0 #define SPECIAL_STATIC_THREAD 1 #define SPECIAL_STATIC_CONTEXT 2 #ifdef HOST_WIN32 typedef SECURITY_ATTRIBUTES WapiSecurityAttributes; -typedef LPTHREAD_START_ROUTINE WapiThreadStart; #endif typedef struct _MonoInternalThread MonoInternalThread; @@ -87,10 +78,10 @@ void ves_icall_System_Threading_Thread_SetCachedCurrentUICulture (MonoThread *th HANDLE ves_icall_System_Threading_Mutex_CreateMutex_internal(MonoBoolean owned, MonoString *name, MonoBoolean *created); MonoBoolean ves_icall_System_Threading_Mutex_ReleaseMutex_internal (HANDLE handle ); HANDLE ves_icall_System_Threading_Mutex_OpenMutex_internal (MonoString *name, gint32 rights, gint32 *error); -HANDLE ves_icall_System_Threading_Semaphore_CreateSemaphore_internal (gint32 initialCount, gint32 maximumCount, MonoString *name, MonoBoolean *created); -gint32 ves_icall_System_Threading_Semaphore_ReleaseSemaphore_internal (HANDLE handle, gint32 releaseCount, MonoBoolean *fail); +HANDLE ves_icall_System_Threading_Semaphore_CreateSemaphore_internal (gint32 initialCount, gint32 maximumCount, MonoString *name, gint32 *error); +MonoBoolean ves_icall_System_Threading_Semaphore_ReleaseSemaphore_internal (HANDLE handle, gint32 releaseCount, gint32 *prevcount); HANDLE ves_icall_System_Threading_Semaphore_OpenSemaphore_internal (MonoString *name, gint32 rights, gint32 *error); -HANDLE ves_icall_System_Threading_Events_CreateEvent_internal (MonoBoolean manual, MonoBoolean initial, MonoString *name, MonoBoolean *created); +HANDLE ves_icall_System_Threading_Events_CreateEvent_internal (MonoBoolean manual, MonoBoolean initial, MonoString *name, gint32 *error); gboolean ves_icall_System_Threading_Events_SetEvent_internal (HANDLE handle); gboolean ves_icall_System_Threading_Events_ResetEvent_internal (HANDLE handle); void ves_icall_System_Threading_Events_CloseEvent_internal (HANDLE handle); @@ -267,4 +258,8 @@ mono_threads_attach_coop (MonoDomain *domain, gpointer *dummy); MONO_API void mono_threads_detach_coop (gpointer cookie, gpointer *dummy); +void mono_threads_begin_abort_protected_block (void); +void mono_threads_end_abort_protected_block (void); +MonoException* mono_thread_try_resume_interruption (void); + #endif /* _MONO_METADATA_THREADS_TYPES_H_ */ diff --git a/mono/metadata/threads.c.REMOVED.git-id b/mono/metadata/threads.c.REMOVED.git-id index 6ac851a87d..046b6ab3e6 100644 --- a/mono/metadata/threads.c.REMOVED.git-id +++ b/mono/metadata/threads.c.REMOVED.git-id @@ -1 +1 @@ -3a30726881ed181de849a074ad338bb08f80e7e4 \ No newline at end of file +4640b4a486524167b883c296cbfb15f3ed049a00 \ No newline at end of file diff --git a/mono/metadata/verify.c.REMOVED.git-id b/mono/metadata/verify.c.REMOVED.git-id index 77782981c9..9913c5b68d 100644 --- a/mono/metadata/verify.c.REMOVED.git-id +++ b/mono/metadata/verify.c.REMOVED.git-id @@ -1 +1 @@ -c3da0227e3c78f729968ffa1e9c4391a47a84e51 \ No newline at end of file +7be7267baa5d7bdb303b6809640bb58b9f88c18b \ No newline at end of file diff --git a/mono/metadata/wrapper-types.h b/mono/metadata/wrapper-types.h index 72ca453eb8..fc2c895442 100644 --- a/mono/metadata/wrapper-types.h +++ b/mono/metadata/wrapper-types.h @@ -17,8 +17,6 @@ WRAPPER(XDOMAIN_INVOKE, "xdomain-invoke") WRAPPER(XDOMAIN_DISPATCH, "xdomain-dispatch") WRAPPER(LDFLD, "ldfld") WRAPPER(STFLD, "stfld") -WRAPPER(LDFLD_REMOTE, "ldfld-remote") -WRAPPER(STFLD_REMOTE, "stfld-remote") WRAPPER(SYNCHRONIZED, "synchronized") WRAPPER(DYNAMIC_METHOD, "dynamic-method") WRAPPER(ISINST, "isinst") diff --git a/mono/mini/Makefile.am b/mono/mini/Makefile.am index 3630a0de74..d745bb5dd4 100644 --- a/mono/mini/Makefile.am +++ b/mono/mini/Makefile.am @@ -372,7 +372,8 @@ darwin_sources = \ mini-darwin.c windows_sources = \ - mini-windows.c + mini-windows.c \ + mini-windows-dllmain.c posix_sources = \ mini-posix.c @@ -486,12 +487,24 @@ test_sources = \ gc-test.cs \ gshared.cs -regtests=basic.exe basic-float.exe basic-long.exe basic-calls.exe objects.exe arrays.exe basic-math.exe exceptions.exe iltests.exe devirtualization.exe generics.exe basic-simd.exe + +regtests_UNIVERSAL=basic.exe basic-float.exe basic-long.exe basic-calls.exe objects.exe arrays.exe basic-math.exe exceptions.exe iltests.exe devirtualization.exe generics.exe basic-simd.exe + +if INSTALL_MOBILE_STATIC +regtests= \ + $(regtests_UNIVERSAL) + if NACL_CODEGEN test_sources += nacl.cs regtests += nacl.exe endif +else +regtests= \ + $(regtests_UNIVERSAL) \ + $(regtests_MOBILE_STATIC_BLACKLIST) +endif + if X86 arch_sources = $(x86_sources) arch_built=cpu-x86.h @@ -502,7 +515,7 @@ if AMD64 arch_sources = $(amd64_sources) arch_built=cpu-amd64.h arch_define=__x86_64__ -ARCH_FULLAOT_EXCLUDE=--exclude DYNCALL +ARCH_FULLAOT_EXCLUDE= endif if POWERPC @@ -583,12 +596,12 @@ libmini_la_CFLAGS = $(mono_CFLAGS) libmonoboehm_2_0_la_SOURCES = libmonoboehm_2_0_la_CFLAGS = $(mono_boehm_CFLAGS) libmonoboehm_2_0_la_LIBADD = libmini.la $(boehm_libs) $(LIBMONO_DTRACE_OBJECT) $(LLVMMONOF) -libmonoboehm_2_0_la_LDFLAGS = $(libmonoldflags) +libmonoboehm_2_0_la_LDFLAGS = $(libmonoldflags) $(monobin_platform_ldflags) libmonosgen_2_0_la_SOURCES = libmonosgen_2_0_la_CFLAGS = $(mono_sgen_CFLAGS) libmonosgen_2_0_la_LIBADD = libmini.la $(sgen_libs) $(LIBMONO_DTRACE_OBJECT) $(LLVMMONOF) -libmonosgen_2_0_la_LDFLAGS = $(libmonoldflags) +libmonosgen_2_0_la_LDFLAGS = $(libmonoldflags) $(monobin_platform_ldflags) # # This library is shared between mono and mono-sgen, since the code in mini/ doesn't contain @@ -683,15 +696,19 @@ testi: mono test.exe checktests: $(regtests) for i in $(regtests); do $(MINI_RUNTIME) $$i; done -rcheck: mono $(regtests) -if NACL_CODEGEN - for i in $(regtests); do echo "running test $$i"; $(MINI_RUNTIME) $$i --exclude 'NaClDisable' || exit 1; done -else - -($(MINI_RUNTIME) --regression $(regtests); echo $$? > regressionexitcode.out) | $(srcdir)/emitnunit.pl - exit $$(cat regressionexitcode.out) -endif +rcheck-nunit: mono $(regtests) + $(MINI_RUNTIME) --regression $(regtests) > regressiontests.out 2>&1; cat regressiontests.out; \ + if grep -q "100% pass" regressiontests.out; then successbool=True; failurescount=0; else successbool=False; failurescount=1; fi; \ + echo "\ + \ + \ + " > TestResult-regression.xml; \ + if [ "$$successbool" = "False" ]; then echo "" >> TestResult-regression.xml; fi; \ + echo "\ + \ + " >> TestResult-regression.xml; exit $$failurescount -rcheck2: mono $(regtests) +rcheck: mono $(regtests) $(MINI_RUNTIME) --regression $(regtests) if ARM @@ -724,26 +741,43 @@ gsharedvtcheck: fullaot_regtests = $(regtests) aot-tests.exe $(if $(GSHAREDVT),gshared.exe) -FULLAOT_LIBS = \ +# Skip aoting the tests that aren't compiled +# on the mobile_static profile because they're skipped +# on mobile profiles +FULLAOT_LIBS_MOBILE_STATIC_BLACKLIST = \ + Mono.Posix.dll \ + System.Configuration.dll + +FULLAOT_LIBS_UNIVERSAL = \ mscorlib.dll \ System.Core.dll \ System.dll \ - Mono.Posix.dll \ - System.Configuration.dll \ - System.Security.dll \ System.Xml.dll \ - Mono.Security.dll \ - Mono.Simd.dll + System.Security.dll \ + Mono.Simd.dll \ + Mono.Security.dll + +if INSTALL_MOBILE_STATIC +FULLAOT_LIBS= \ + Mono.Dynamic.Interpreter.dll \ + $(FULLAOT_LIBS_UNIVERSAL) +else +FULLAOT_LIBS= \ + $(FULLAOT_LIBS_UNIVERSAL) \ + $(FULLAOT_LIBS_MOBILE_STATIC_BLACKLIST) +endif + +FULLAOT_TMP_DIR=$(top_builddir)/mono/mini/fullaot-tmp # This currently only works on amd64/arm fullaotcheck: $(mono) $(fullaot_regtests) - rm -rf fullaot-tmp - mkdir fullaot-tmp - $(MAKE) fullaot-libs AOT_FLAGS="full,$(MONO_FULLAOT_ADDITIONAL_ARGS)" GSHAREDVT=$(GSHAREDVT) - cp $(regtests) $(fullaot_regtests) generics-variant-types.dll TestDriver.dll fullaot-tmp/ - MONO_PATH=fullaot-tmp $(top_builddir)/runtime/mono-wrapper $(LLVM_AOT_RUNTIME_OPTS) $(GSHAREDVT_RUNTIME_OPTS) --aot="full,$(MONO_FULLAOT_ADDITIONAL_ARGS)" fullaot-tmp/{generics-variant-types.dll,TestDriver.dll,*.exe} || exit 1 - ln -s $(if $(MONO_EXECUTABLE),$(MONO_EXECUTABLE),$$PWD/mono) fullaot-tmp/ - for i in $(fullaot_regtests); do echo $$i; MONO_PATH=fullaot-tmp $(top_builddir)/runtime/mono-wrapper --full-aot fullaot-tmp/$$i --exclude '!FULLAOT' $(ARCH_FULLAOT_EXCLUDE) || exit 1; done + rm -rf $(FULLAOT_TMP_DIR) + mkdir $(FULLAOT_TMP_DIR) + $(MAKE) fullaot-libs AOT_FLAGS="full,$(MONO_FULLAOT_ADDITIONAL_ARGS)$(INVARIANT_AOT_OPTIONS)" GSHAREDVT=$(GSHAREDVT) + cp $(regtests) $(fullaot_regtests) generics-variant-types.dll TestDriver.dll $(FULLAOT_TMP_DIR)/ + MONO_PATH=$(FULLAOT_TMP_DIR) $(top_builddir)/runtime/mono-wrapper $(LLVM_AOT_RUNTIME_OPTS) $(GSHAREDVT_RUNTIME_OPTS) --aot="full,$(MONO_FULLAOT_ADDITIONAL_ARGS)$(INVARIANT_AOT_OPTIONS)" $(FULLAOT_TMP_DIR)/{generics-variant-types.dll,TestDriver.dll,*.exe} || exit 1 + ln -s $(if $(MONO_EXECUTABLE),$(MONO_EXECUTABLE),$$PWD/mono) $(FULLAOT_TMP_DIR)/ + for i in $(fullaot_regtests); do echo $$i; MONO_PATH=$(FULLAOT_TMP_DIR) $(top_builddir)/runtime/mono-wrapper --full-aot $(FULLAOT_TMP_DIR)/$$i --exclude '!FULLAOT' $(ARCH_FULLAOT_EXCLUDE) || exit 1; done # This can run in parallel fullaot-libs: $(patsubst %,fullaot-tmp/%.dylib,$(FULLAOT_LIBS)) @@ -762,7 +796,7 @@ llvmonly_regtests = $(fullaot_regtests) gshared.exe llvmonlycheck: mono $(llvmonly_regtests) rm -rf fullaot-tmp mkdir fullaot-tmp - $(MAKE) fullaot-libs AOT_FLAGS="llvmonly,$(MONO_FULLAOT_ADDITIONAL_ARGS)" + $(MAKE) fullaot-libs AOT_FLAGS="llvmonly,$(MONO_FULLAOT_ADDITIONAL_ARGS)$(INVARIANT_AOT_OPTIONS)" cp $(llvmonly_regtests) generics-variant-types.dll TestDriver.dll fullaot-tmp/ MONO_PATH=fullaot-tmp $(top_builddir)/runtime/mono-wrapper --aot=llvmonly fullaot-tmp/{generics-variant-types.dll,TestDriver.dll,*.exe} || exit 1 ln -s $$PWD/mono fullaot-tmp/ @@ -792,7 +826,10 @@ stat3: mono bench.exe docu: mini.sgm docbook2txt mini.sgm -check-local: rcheck check-seq-points +# We need these because automake can't process normal make conditionals +check_local_targets = $(if $(EMIT_NUNIT), rcheck-nunit, rcheck) + +check-local: $(check_local_targets) clean-local: rm -f mono a.out gmon.out *.o buildver-boehm.h buildver-sgen.h test.exe regressionexitcode.out TestResult-op_il_seq_point.xml* @@ -805,7 +842,6 @@ CLEANFILES= $(BUILT_SOURCES) *.exe *.dll EXTRA_DIST = TestDriver.cs \ TestHelpers.cs \ genmdesc.pl \ - emitnunit.pl \ $(test_sources) \ $(x86_sources) cpu-x86.md \ $(amd64_sources) cpu-amd64.md \ @@ -824,7 +860,7 @@ EXTRA_DIST = TestDriver.cs \ Makefile.am.in version.h: Makefile - echo "#define FULL_VERSION \"Stable 4.6.2.6/db69866\"" > version.h + echo "#define FULL_VERSION \"Stable 4.8.0.309/dea12ad\"" > version.h # Utility target for patching libtool to speed up linking patch-libtool: diff --git a/mono/mini/Makefile.am.in b/mono/mini/Makefile.am.in index 3630a0de74..d745bb5dd4 100755 --- a/mono/mini/Makefile.am.in +++ b/mono/mini/Makefile.am.in @@ -372,7 +372,8 @@ darwin_sources = \ mini-darwin.c windows_sources = \ - mini-windows.c + mini-windows.c \ + mini-windows-dllmain.c posix_sources = \ mini-posix.c @@ -486,12 +487,24 @@ test_sources = \ gc-test.cs \ gshared.cs -regtests=basic.exe basic-float.exe basic-long.exe basic-calls.exe objects.exe arrays.exe basic-math.exe exceptions.exe iltests.exe devirtualization.exe generics.exe basic-simd.exe + +regtests_UNIVERSAL=basic.exe basic-float.exe basic-long.exe basic-calls.exe objects.exe arrays.exe basic-math.exe exceptions.exe iltests.exe devirtualization.exe generics.exe basic-simd.exe + +if INSTALL_MOBILE_STATIC +regtests= \ + $(regtests_UNIVERSAL) + if NACL_CODEGEN test_sources += nacl.cs regtests += nacl.exe endif +else +regtests= \ + $(regtests_UNIVERSAL) \ + $(regtests_MOBILE_STATIC_BLACKLIST) +endif + if X86 arch_sources = $(x86_sources) arch_built=cpu-x86.h @@ -502,7 +515,7 @@ if AMD64 arch_sources = $(amd64_sources) arch_built=cpu-amd64.h arch_define=__x86_64__ -ARCH_FULLAOT_EXCLUDE=--exclude DYNCALL +ARCH_FULLAOT_EXCLUDE= endif if POWERPC @@ -583,12 +596,12 @@ libmini_la_CFLAGS = $(mono_CFLAGS) libmonoboehm_2_0_la_SOURCES = libmonoboehm_2_0_la_CFLAGS = $(mono_boehm_CFLAGS) libmonoboehm_2_0_la_LIBADD = libmini.la $(boehm_libs) $(LIBMONO_DTRACE_OBJECT) $(LLVMMONOF) -libmonoboehm_2_0_la_LDFLAGS = $(libmonoldflags) +libmonoboehm_2_0_la_LDFLAGS = $(libmonoldflags) $(monobin_platform_ldflags) libmonosgen_2_0_la_SOURCES = libmonosgen_2_0_la_CFLAGS = $(mono_sgen_CFLAGS) libmonosgen_2_0_la_LIBADD = libmini.la $(sgen_libs) $(LIBMONO_DTRACE_OBJECT) $(LLVMMONOF) -libmonosgen_2_0_la_LDFLAGS = $(libmonoldflags) +libmonosgen_2_0_la_LDFLAGS = $(libmonoldflags) $(monobin_platform_ldflags) # # This library is shared between mono and mono-sgen, since the code in mini/ doesn't contain @@ -683,15 +696,19 @@ testi: mono test.exe checktests: $(regtests) for i in $(regtests); do $(MINI_RUNTIME) $$i; done -rcheck: mono $(regtests) -if NACL_CODEGEN - for i in $(regtests); do echo "running test $$i"; $(MINI_RUNTIME) $$i --exclude 'NaClDisable' || exit 1; done -else - -($(MINI_RUNTIME) --regression $(regtests); echo $$? > regressionexitcode.out) | $(srcdir)/emitnunit.pl - exit $$(cat regressionexitcode.out) -endif +rcheck-nunit: mono $(regtests) + $(MINI_RUNTIME) --regression $(regtests) > regressiontests.out 2>&1; cat regressiontests.out; \ + if grep -q "100% pass" regressiontests.out; then successbool=True; failurescount=0; else successbool=False; failurescount=1; fi; \ + echo "\ + \ + \ + " > TestResult-regression.xml; \ + if [ "$$successbool" = "False" ]; then echo "" >> TestResult-regression.xml; fi; \ + echo "\ + \ + " >> TestResult-regression.xml; exit $$failurescount -rcheck2: mono $(regtests) +rcheck: mono $(regtests) $(MINI_RUNTIME) --regression $(regtests) if ARM @@ -724,26 +741,43 @@ gsharedvtcheck: fullaot_regtests = $(regtests) aot-tests.exe $(if $(GSHAREDVT),gshared.exe) -FULLAOT_LIBS = \ +# Skip aoting the tests that aren't compiled +# on the mobile_static profile because they're skipped +# on mobile profiles +FULLAOT_LIBS_MOBILE_STATIC_BLACKLIST = \ + Mono.Posix.dll \ + System.Configuration.dll + +FULLAOT_LIBS_UNIVERSAL = \ mscorlib.dll \ System.Core.dll \ System.dll \ - Mono.Posix.dll \ - System.Configuration.dll \ - System.Security.dll \ System.Xml.dll \ - Mono.Security.dll \ - Mono.Simd.dll + System.Security.dll \ + Mono.Simd.dll \ + Mono.Security.dll + +if INSTALL_MOBILE_STATIC +FULLAOT_LIBS= \ + Mono.Dynamic.Interpreter.dll \ + $(FULLAOT_LIBS_UNIVERSAL) +else +FULLAOT_LIBS= \ + $(FULLAOT_LIBS_UNIVERSAL) \ + $(FULLAOT_LIBS_MOBILE_STATIC_BLACKLIST) +endif + +FULLAOT_TMP_DIR=$(top_builddir)/mono/mini/fullaot-tmp # This currently only works on amd64/arm fullaotcheck: $(mono) $(fullaot_regtests) - rm -rf fullaot-tmp - mkdir fullaot-tmp - $(MAKE) fullaot-libs AOT_FLAGS="full,$(MONO_FULLAOT_ADDITIONAL_ARGS)" GSHAREDVT=$(GSHAREDVT) - cp $(regtests) $(fullaot_regtests) generics-variant-types.dll TestDriver.dll fullaot-tmp/ - MONO_PATH=fullaot-tmp $(top_builddir)/runtime/mono-wrapper $(LLVM_AOT_RUNTIME_OPTS) $(GSHAREDVT_RUNTIME_OPTS) --aot="full,$(MONO_FULLAOT_ADDITIONAL_ARGS)" fullaot-tmp/{generics-variant-types.dll,TestDriver.dll,*.exe} || exit 1 - ln -s $(if $(MONO_EXECUTABLE),$(MONO_EXECUTABLE),$$PWD/mono) fullaot-tmp/ - for i in $(fullaot_regtests); do echo $$i; MONO_PATH=fullaot-tmp $(top_builddir)/runtime/mono-wrapper --full-aot fullaot-tmp/$$i --exclude '!FULLAOT' $(ARCH_FULLAOT_EXCLUDE) || exit 1; done + rm -rf $(FULLAOT_TMP_DIR) + mkdir $(FULLAOT_TMP_DIR) + $(MAKE) fullaot-libs AOT_FLAGS="full,$(MONO_FULLAOT_ADDITIONAL_ARGS)$(INVARIANT_AOT_OPTIONS)" GSHAREDVT=$(GSHAREDVT) + cp $(regtests) $(fullaot_regtests) generics-variant-types.dll TestDriver.dll $(FULLAOT_TMP_DIR)/ + MONO_PATH=$(FULLAOT_TMP_DIR) $(top_builddir)/runtime/mono-wrapper $(LLVM_AOT_RUNTIME_OPTS) $(GSHAREDVT_RUNTIME_OPTS) --aot="full,$(MONO_FULLAOT_ADDITIONAL_ARGS)$(INVARIANT_AOT_OPTIONS)" $(FULLAOT_TMP_DIR)/{generics-variant-types.dll,TestDriver.dll,*.exe} || exit 1 + ln -s $(if $(MONO_EXECUTABLE),$(MONO_EXECUTABLE),$$PWD/mono) $(FULLAOT_TMP_DIR)/ + for i in $(fullaot_regtests); do echo $$i; MONO_PATH=$(FULLAOT_TMP_DIR) $(top_builddir)/runtime/mono-wrapper --full-aot $(FULLAOT_TMP_DIR)/$$i --exclude '!FULLAOT' $(ARCH_FULLAOT_EXCLUDE) || exit 1; done # This can run in parallel fullaot-libs: $(patsubst %,fullaot-tmp/%.dylib,$(FULLAOT_LIBS)) @@ -762,7 +796,7 @@ llvmonly_regtests = $(fullaot_regtests) gshared.exe llvmonlycheck: mono $(llvmonly_regtests) rm -rf fullaot-tmp mkdir fullaot-tmp - $(MAKE) fullaot-libs AOT_FLAGS="llvmonly,$(MONO_FULLAOT_ADDITIONAL_ARGS)" + $(MAKE) fullaot-libs AOT_FLAGS="llvmonly,$(MONO_FULLAOT_ADDITIONAL_ARGS)$(INVARIANT_AOT_OPTIONS)" cp $(llvmonly_regtests) generics-variant-types.dll TestDriver.dll fullaot-tmp/ MONO_PATH=fullaot-tmp $(top_builddir)/runtime/mono-wrapper --aot=llvmonly fullaot-tmp/{generics-variant-types.dll,TestDriver.dll,*.exe} || exit 1 ln -s $$PWD/mono fullaot-tmp/ @@ -792,7 +826,10 @@ stat3: mono bench.exe docu: mini.sgm docbook2txt mini.sgm -check-local: rcheck check-seq-points +# We need these because automake can't process normal make conditionals +check_local_targets = $(if $(EMIT_NUNIT), rcheck-nunit, rcheck) + +check-local: $(check_local_targets) clean-local: rm -f mono a.out gmon.out *.o buildver-boehm.h buildver-sgen.h test.exe regressionexitcode.out TestResult-op_il_seq_point.xml* @@ -805,7 +842,6 @@ CLEANFILES= $(BUILT_SOURCES) *.exe *.dll EXTRA_DIST = TestDriver.cs \ TestHelpers.cs \ genmdesc.pl \ - emitnunit.pl \ $(test_sources) \ $(x86_sources) cpu-x86.md \ $(amd64_sources) cpu-amd64.md \ @@ -824,7 +860,7 @@ EXTRA_DIST = TestDriver.cs \ Makefile.am.in version.h: Makefile - echo "#define FULL_VERSION \"Stable 4.6.2.6/db69866\"" > version.h + echo "#define FULL_VERSION \"Stable 4.8.0.309/dea12ad\"" > version.h # Utility target for patching libtool to speed up linking patch-libtool: diff --git a/mono/mini/Makefile.in.REMOVED.git-id b/mono/mini/Makefile.in.REMOVED.git-id index db459cdb8e..00e2abd56e 100644 --- a/mono/mini/Makefile.in.REMOVED.git-id +++ b/mono/mini/Makefile.in.REMOVED.git-id @@ -1 +1 @@ -f219af2692be7d8f8ddc330d4241f4fa99446213 \ No newline at end of file +758b7a9eb4e4abb105aa5381c4c9a16a34e8b4d6 \ No newline at end of file diff --git a/mono/mini/abcremoval.c b/mono/mini/abcremoval.c index fddbef9d9c..17a8e84d91 100644 --- a/mono/mini/abcremoval.c +++ b/mono/mini/abcremoval.c @@ -183,10 +183,9 @@ print_evaluation_context_ranges (MonoRelationsEvaluationRanges *ranges) { } static void -print_evaluation_context (MonoRelationsEvaluationContext *context) { - printf ("Context status: "); - print_evaluation_context_status (context->status); - if (context->status & (MONO_RELATIONS_EVALUATION_IN_PROGRESS|MONO_RELATIONS_EVALUATION_COMPLETED)) { +print_evaluation_context (MonoRelationsEvaluationContext *context, MonoRelationsEvaluationStatus status) { + print_evaluation_context_status (status); + if (status & (MONO_RELATIONS_EVALUATION_IN_PROGRESS|MONO_RELATIONS_EVALUATION_COMPLETED)) { print_evaluation_context_ranges (&(context->ranges)); } printf ("\n"); @@ -537,12 +536,9 @@ remove_change_from_evaluation_area (MonoAdditionalVariableRelation *change) static void -clean_contexts (MonoRelationsEvaluationContext *contexts, int number) +clean_contexts (MonoVariableRelationsEvaluationArea *area, int number) { - int i; - for (i = 0; i < number; i++) { - contexts [i].status = MONO_RELATIONS_EVALUATION_NOT_STARTED; - } + memset(area->statuses, MONO_RELATIONS_EVALUATION_NOT_STARTED, number * sizeof(MonoRelationsEvaluationStatus)); } @@ -655,13 +651,14 @@ intersect_ranges( MonoRelationsEvaluationRanges *ranges, MonoRelationsEvaluation * (or NULL for the first invocation) */ static void -evaluate_relation_with_target_variable (MonoVariableRelationsEvaluationArea *area, int variable, int target_variable, MonoRelationsEvaluationContext *father_context) +evaluate_relation_with_target_variable (MonoVariableRelationsEvaluationArea *area, const int variable, const int target_variable, MonoRelationsEvaluationContext *father_context) { - MonoRelationsEvaluationContext *context = &(area->contexts [variable]); + MonoRelationsEvaluationContext * const context = &(area->contexts [variable]); + MonoRelationsEvaluationStatus * const status = &(area->statuses [variable]); // First of all, we check the evaluation status // (what must be done is *very* different in each case) - switch (context->status) { + switch (*status) { case MONO_RELATIONS_EVALUATION_NOT_STARTED: { MonoSummarizedValueRelation *relation = &(area->relations [variable]); @@ -672,7 +669,7 @@ evaluate_relation_with_target_variable (MonoVariableRelationsEvaluationArea *are } // We properly inizialize the context - context->status = MONO_RELATIONS_EVALUATION_IN_PROGRESS; + *status = MONO_RELATIONS_EVALUATION_IN_PROGRESS; context->father = father_context; MONO_MAKE_RELATIONS_EVALUATION_RANGES_WEAK (context->ranges); @@ -714,24 +711,25 @@ evaluate_relation_with_target_variable (MonoVariableRelationsEvaluationArea *are if (relation->relation != MONO_ANY_RELATION) { int related_variable = relation->related_value.value.variable.variable; MonoRelationsEvaluationContext *related_context = &(area->contexts [related_variable]); + MonoRelationsEvaluationStatus related_status = area->statuses [related_variable]; // The second condition in the "or" avoids messing with "back edges" in the graph traversal // (they are simply ignored instead of triggering the handling of recursion) - if ( (related_context->status == MONO_RELATIONS_EVALUATION_NOT_STARTED) || ! + if ( (related_status == MONO_RELATIONS_EVALUATION_NOT_STARTED) || ! ((related_context->current_relation->related_value.type == MONO_VARIABLE_SUMMARIZED_VALUE) && (related_context->current_relation->related_value.value.variable.variable == variable))) { // Evaluate the related variable evaluate_relation_with_target_variable (area, related_variable, target_variable, context); // Check if we are part of a recursive loop - if (context->status & MONO_RELATIONS_EVALUATION_IS_RECURSIVE) { + if (*status & MONO_RELATIONS_EVALUATION_IS_RECURSIVE) { if (TRACE_ABC_REMOVAL) { printf ("Recursivity detected for variable %d (target variable %d), status ", variable, target_variable); - print_evaluation_context_status (context->status); + print_evaluation_context_status (*status); } // If we are, check if the evaluation of the related variable is complete - if (related_context->status == MONO_RELATIONS_EVALUATION_COMPLETED) { + if (related_status == MONO_RELATIONS_EVALUATION_COMPLETED) { // If it is complete, we are part of a recursive definition. // Since it is a *definition* (and definitions are evaluated *before* // conditions because they are first in the list), intersection is not @@ -739,7 +737,7 @@ evaluate_relation_with_target_variable (MonoVariableRelationsEvaluationArea *are context->ranges = related_context->ranges; /* Delta has already been checked for over/under-flow when evaluating values */ MONO_ADD_DELTA_SAFELY_TO_RANGES (context->ranges, relation->related_value.value.variable.delta); - context->status = MONO_RELATIONS_EVALUATION_COMPLETED; + *status = MONO_RELATIONS_EVALUATION_COMPLETED; if (TRACE_ABC_REMOVAL) { printf (", ranges already computed, result: \n"); print_evaluation_context_ranges (&(context->ranges)); @@ -777,25 +775,25 @@ evaluate_relation_with_target_variable (MonoVariableRelationsEvaluationArea *are evaluate_relation_with_target_variable (area, phi_alternative, target_variable, context); // This means we are part of a recursive loop - if (context->status & MONO_RELATIONS_EVALUATION_IS_RECURSIVE) { + if (*status & MONO_RELATIONS_EVALUATION_IS_RECURSIVE) { if (TRACE_ABC_REMOVAL) { printf ("Recursivity detected for variable %d (target variable %d), status ", variable, target_variable); - print_evaluation_context_status (context->status); + print_evaluation_context_status (*status); printf ("\n"); } - if (context->status & MONO_RELATIONS_EVALUATION_IS_RECURSIVELY_ASCENDING) { + if (*status & MONO_RELATIONS_EVALUATION_IS_RECURSIVELY_ASCENDING) { is_ascending = TRUE; } - if (context->status & MONO_RELATIONS_EVALUATION_IS_RECURSIVELY_DESCENDING) { + if (*status & MONO_RELATIONS_EVALUATION_IS_RECURSIVELY_DESCENDING) { is_descending = TRUE; } - if (context->status & MONO_RELATIONS_EVALUATION_IS_RECURSIVELY_INDEFINITE) { + if (*status & MONO_RELATIONS_EVALUATION_IS_RECURSIVELY_INDEFINITE) { is_ascending = TRUE; is_descending = TRUE; } // Clear "recursivity" bits in the status (recursion has been handled) - context->status = MONO_RELATIONS_EVALUATION_IN_PROGRESS; + *status = MONO_RELATIONS_EVALUATION_IN_PROGRESS; } else { MONO_RELATIONS_EVALUATION_RANGES_UNION (phi_ranges, area->contexts [phi_alternative].ranges); } @@ -824,16 +822,16 @@ evaluate_relation_with_target_variable (MonoVariableRelationsEvaluationArea *are } // Check if any recursivity bits are still in the status, and in any case clear them - if (context->status & MONO_RELATIONS_EVALUATION_IS_RECURSIVE) { + if (*status & MONO_RELATIONS_EVALUATION_IS_RECURSIVE) { if (TRACE_ABC_REMOVAL) { printf ("Recursivity for variable %d (target variable %d) discards computation, status ", variable, target_variable); - print_evaluation_context_status (context->status); + print_evaluation_context_status (*status); printf ("\n"); } // If yes, we did not have enough information (most likely we were evaluated inside a PHI, but we also // depended on the same PHI, which was still in evaluation...), so clear the status to "NOT_STARTED" // (if we will be evaluated again, the PHI will be already done, so our evaluation will succeed) - context->status = MONO_RELATIONS_EVALUATION_NOT_STARTED; + *status = MONO_RELATIONS_EVALUATION_NOT_STARTED; } else { if (TRACE_ABC_REMOVAL) { printf ("Ranges for variable %d (target variable %d) computed: ", variable, target_variable); @@ -841,7 +839,7 @@ evaluate_relation_with_target_variable (MonoVariableRelationsEvaluationArea *are printf ("\n"); } // If not (the common case) the evaluation is complete, and the result is in the context - context->status = MONO_RELATIONS_EVALUATION_COMPLETED; + *status = MONO_RELATIONS_EVALUATION_COMPLETED; } break; } @@ -855,7 +853,7 @@ evaluate_relation_with_target_variable (MonoVariableRelationsEvaluationArea *are if (TRACE_ABC_REMOVAL) { printf ("Evaluation of variable %d (target variable %d) already in progress\n", variable, target_variable); - print_evaluation_context (context); + print_evaluation_context (context, *status); print_summarized_value_relation (context->current_relation); printf ("\n"); } @@ -905,7 +903,9 @@ evaluate_relation_with_target_variable (MonoVariableRelationsEvaluationArea *are current_context = father_context; while (current_context != last_context) { - current_context->status = (MonoRelationsEvaluationStatus)(current_context->status | recursive_status); + int index = father_context - area->contexts; + MonoRelationsEvaluationStatus *current_status = &(area->statuses [index]); + *current_status = (MonoRelationsEvaluationStatus)(*current_status | recursive_status); current_context = current_context->father; } } else { @@ -921,7 +921,7 @@ evaluate_relation_with_target_variable (MonoVariableRelationsEvaluationArea *are default: if (TRACE_ABC_REMOVAL) { printf ("Variable %d (target variable %d) already in a recursive ring, skipping\n", variable, target_variable); - print_evaluation_context (context); + print_evaluation_context (context, *status); print_summarized_value_relation (context->current_relation); printf ("\n"); } @@ -986,7 +986,7 @@ remove_abc_from_inst (MonoInst *ins, MonoVariableRelationsEvaluationArea *area) MonoRelationsEvaluationContext *array_context = &(area->contexts [array_variable]); MonoRelationsEvaluationContext *index_context = &(area->contexts [index_variable]); - clean_contexts (area->contexts, area->cfg->next_vreg); + clean_contexts (area, area->cfg->next_vreg); evaluate_relation_with_target_variable (area, index_variable, array_variable, NULL); evaluate_relation_with_target_variable (area, array_variable, array_variable, NULL); @@ -1017,7 +1017,7 @@ eval_non_null (MonoVariableRelationsEvaluationArea *area, int reg) { MonoRelationsEvaluationContext *context = &(area->contexts [reg]); - clean_contexts (area->contexts, area->cfg->next_vreg); + clean_contexts (area, area->cfg->next_vreg); evaluate_relation_with_target_variable (area, reg, reg, NULL); return context->ranges.zero.lower > 0; @@ -1271,8 +1271,13 @@ mono_perform_abc_removal (MonoCompile *cfg) area.cfg = cfg; area.relations = (MonoSummarizedValueRelation *) mono_mempool_alloc (cfg->mempool, sizeof (MonoSummarizedValueRelation) * (cfg->next_vreg) * 2); + area.contexts = (MonoRelationsEvaluationContext *) - mono_mempool_alloc (cfg->mempool, sizeof (MonoRelationsEvaluationContext) * (cfg->next_vreg)); + mono_mempool_alloc0 (cfg->mempool, sizeof (MonoRelationsEvaluationContext) * (cfg->next_vreg)); + + area.statuses = (MonoRelationsEvaluationStatus *) + mono_mempool_alloc0 (cfg->mempool, sizeof (MonoRelationsEvaluationStatus) * (cfg->next_vreg)); + area.variable_value_kind = (MonoIntegerValueKind *) mono_mempool_alloc (cfg->mempool, sizeof (MonoIntegerValueKind) * (cfg->next_vreg)); area.defs = (MonoInst **)mono_mempool_alloc (cfg->mempool, sizeof (MonoInst*) * cfg->next_vreg); diff --git a/mono/mini/abcremoval.h b/mono/mini/abcremoval.h index c9896af403..0d00454a9d 100644 --- a/mono/mini/abcremoval.h +++ b/mono/mini/abcremoval.h @@ -179,14 +179,12 @@ typedef struct MonoRelationsEvaluationRanges { /** * The context of a variable evaluation. - * status: the evaluation status * current_relation: the relation that is currently evaluated. * ranges: the result of the evaluation. * father: the context of the evaluation that invoked this one (used to * perform the backtracking when loops are detected. */ typedef struct MonoRelationsEvaluationContext { - MonoRelationsEvaluationStatus status; MonoSummarizedValueRelation *current_relation; MonoRelationsEvaluationRanges ranges; struct MonoRelationsEvaluationContext *father; @@ -308,7 +306,17 @@ typedef struct MonoRelationsEvaluationContext { typedef struct MonoVariableRelationsEvaluationArea { MonoCompile *cfg; MonoSummarizedValueRelation *relations; + +/** + * statuses and contexts are parallel arrays. A given index into each refers to + * the same context. This is a performance optimization. Clean_context was + * coming to dominate the running time of abcremoval. By + * storing the statuses together, we can memset the entire + * region. + */ + MonoRelationsEvaluationStatus *statuses; MonoRelationsEvaluationContext *contexts; + MonoIntegerValueKind *variable_value_kind; MonoInst **defs; } MonoVariableRelationsEvaluationArea; diff --git a/mono/mini/alias-analysis.c b/mono/mini/alias-analysis.c index 2e61c0f523..82e3672ae1 100644 --- a/mono/mini/alias-analysis.c +++ b/mono/mini/alias-analysis.c @@ -230,7 +230,7 @@ handle_instruction: } } break; - + //FIXME missing storei1_membase_imm and storei2_membase_imm case OP_STORE_MEMBASE_IMM: case OP_STOREI4_MEMBASE_IMM: case OP_STOREI8_MEMBASE_IMM: diff --git a/mono/mini/aot-compiler.c.REMOVED.git-id b/mono/mini/aot-compiler.c.REMOVED.git-id index e10f0c6353..be9e5155b6 100644 --- a/mono/mini/aot-compiler.c.REMOVED.git-id +++ b/mono/mini/aot-compiler.c.REMOVED.git-id @@ -1 +1 @@ -270bce9d5a5e5d508a93d95ff2f49d0633752d03 \ No newline at end of file +bd6f925c87c7032d749d0524b3629b3d81a48d63 \ No newline at end of file diff --git a/mono/mini/aot-runtime.c.REMOVED.git-id b/mono/mini/aot-runtime.c.REMOVED.git-id index bbaf8b64a7..66a0c35eeb 100644 --- a/mono/mini/aot-runtime.c.REMOVED.git-id +++ b/mono/mini/aot-runtime.c.REMOVED.git-id @@ -1 +1 @@ -f1499dd86dfa96b2daff903a17b06f8d4f099923 \ No newline at end of file +71edbb64e2301688815b71c81fdcc47dabad3ec1 \ No newline at end of file diff --git a/mono/mini/aot-tests.cs b/mono/mini/aot-tests.cs index bd823f2b90..36c7a15a3e 100644 --- a/mono/mini/aot-tests.cs +++ b/mono/mini/aot-tests.cs @@ -84,6 +84,7 @@ class Tests } [Category ("DYNCALL")] + [Category ("!FULLAOT-AMD64")] static int test_0_arm64_dyncall_hfa_double () { double arg1 = 1.0f; // HFA with double members @@ -97,6 +98,7 @@ class Tests } [Category ("DYNCALL")] + [Category ("!FULLAOT-AMD64")] static int test_0_arm64_dyncall_hfa_float () { double arg1 = 1.0f; var s = new Struct2 (); @@ -110,6 +112,7 @@ class Tests [Category ("DYNCALL")] [Category ("GSHAREDVT")] + [Category ("!FULLAOT-AMD64")] static int test_0_arm64_dyncall_gsharedvt_out_hfa_double () { /* gsharedvt out trampoline with double hfa argument */ double arg1 = 1.0f; @@ -129,6 +132,7 @@ class Tests [Category ("DYNCALL")] [Category ("GSHAREDVT")] + [Category ("!FULLAOT-AMD64")] static int test_0_arm64_dyncall_gsharedvt_out_hfa_float () { /* gsharedvt out trampoline with double hfa argument */ double arg1 = 1.0f; @@ -190,6 +194,8 @@ class Tests } [Category ("DYNCALL")] + [Category ("GSHAREDVT")] + [Category ("!FULLAOT-AMD64")] static int test_0_arm64_dyncall_vtypebyref_ret () { var s = new VTypeByRefStruct () { o1 = 1, o2 = 2, o3 = 3 }; Type t = typeof (Foo5<>).MakeGenericType (new Type [] { typeof (VTypeByRefStruct) }); @@ -210,7 +216,8 @@ class Tests } } - [Category("DYNCALL")] + [Category ("DYNCALL")] + [Category ("GSHAREDVT")] static int test_0_arm_dyncall_reg_stack_split () { var m = typeof (Foo6).GetMethod ("reg_stack_split_inner").MakeGenericMethod (new Type[] { typeof (long) }); var o = new Foo6 (); @@ -251,6 +258,7 @@ class Tests } [Category ("DYNCALL")] + [Category ("!FULLAOT-AMD64")] public static int test_0_dyncall_nullable () { int? v; @@ -367,6 +375,7 @@ class Tests return 0; } + [Category ("DYNCALL")] public static int test_0_array_accessor_runtime_invoke_ref () { var t = typeof (string[]); var arr = Array.CreateInstance (typeof (string), 1); @@ -399,6 +408,7 @@ class Tests } [Category ("DYNCALL")] + [Category ("!FULLAOT-AMD64")] public static int test_0_large_nullable_invoke () { var s = new LargeStruct () { a = 1, b = 2, c = 3, d = 4 }; diff --git a/mono/mini/branch-opts.c b/mono/mini/branch-opts.c index ca8289b81c..cab90f84d3 100644 --- a/mono/mini/branch-opts.c +++ b/mono/mini/branch-opts.c @@ -209,9 +209,11 @@ mono_replace_ins (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *ins, MonoInst /* Multiple BBs */ - /* Set region */ - for (tmp = first_bb; tmp; tmp = tmp->next_bb) + /* Set region/real_offset */ + for (tmp = first_bb; tmp; tmp = tmp->next_bb) { tmp->region = bb->region; + tmp->real_offset = bb->real_offset; + } /* Split the original bb */ if (ins->next) diff --git a/mono/mini/cpu-amd64.md b/mono/mini/cpu-amd64.md index 99a6d9a18b..3eeae0fc0d 100755 --- a/mono/mini/cpu-amd64.md +++ b/mono/mini/cpu-amd64.md @@ -561,7 +561,7 @@ vcall2: len:64 clob:c vcall2_reg: src1:i len:64 clob:c vcall2_membase: src1:b len:64 clob:c -dyn_call: src1:i src2:i len:128 clob:c +dyn_call: src1:i src2:i len:192 clob:c localloc_imm: dest:i len:96 @@ -792,3 +792,4 @@ gc_spill_slot_liveness_def: len:0 gc_param_slot_liveness_def: len:0 generic_class_init: src1:A len:32 clob:c +get_last_error: dest:i len:32 diff --git a/mono/mini/debugger-agent.c.REMOVED.git-id b/mono/mini/debugger-agent.c.REMOVED.git-id index 8d0459dd31..f71b8e489a 100644 --- a/mono/mini/debugger-agent.c.REMOVED.git-id +++ b/mono/mini/debugger-agent.c.REMOVED.git-id @@ -1 +1 @@ -271ccab23ddd40f3397e22fe6fc7a38af88fd06e \ No newline at end of file +0a708d482293b4d8f1e47e5e967134b8878d3882 \ No newline at end of file diff --git a/mono/mini/driver.c b/mono/mini/driver.c index 1a7b15b6f5..82fece5fa9 100644 --- a/mono/mini/driver.c +++ b/mono/mini/driver.c @@ -52,6 +52,7 @@ #include "mono/utils/mono-counters.h" #include "mono/utils/mono-hwcap.h" #include "mono/utils/mono-logger-internals.h" +#include "mono/utils/w32handle.h" #include "mini.h" #include "jit.h" @@ -1026,18 +1027,27 @@ mono_jit_exec (MonoDomain *domain, MonoAssembly *assembly, int argc, char *argv[ } if (mono_llvm_only) { - MonoObject *exc; + MonoObject *exc = NULL; int res; - res = mono_runtime_run_main (method, argc, argv, &exc); + res = mono_runtime_try_run_main (method, argc, argv, &exc); if (exc) { mono_unhandled_exception (exc); mono_invoke_unhandled_exception_hook (exc); - return 1; + g_assert_not_reached (); } return res; } else { - return mono_runtime_run_main (method, argc, argv, NULL); + int res = mono_runtime_run_main_checked (method, argc, argv, &error); + if (!is_ok (&error)) { + MonoException *ex = mono_error_convert_to_exception (&error); + if (ex) { + mono_unhandled_exception (&ex->object); + mono_invoke_unhandled_exception_hook (&ex->object); + g_assert_not_reached (); + } + } + return res; } } @@ -1358,30 +1368,6 @@ static const char info[] = #define error_if_aot_unsupported() #endif -#ifdef HOST_WIN32 -BOOL APIENTRY DllMain (HMODULE module_handle, DWORD reason, LPVOID reserved) -{ - if (!mono_gc_dllmain (module_handle, reason, reserved)) - return FALSE; - - switch (reason) - { - case DLL_PROCESS_ATTACH: - mono_install_runtime_load (mini_init); - break; - case DLL_PROCESS_DETACH: - if (coree_module_handle) - FreeLibrary (coree_module_handle); - break; - case DLL_THREAD_DETACH: - mono_thread_info_detach (); - break; - - } - return TRUE; -} -#endif - static gboolean enable_debugging; /* @@ -1758,10 +1744,11 @@ mono_main (int argc, char* argv[]) } else if (strcmp (argv [i], "--verify-all") == 0) { mono_verifier_enable_verify_all (); } else if (strcmp (argv [i], "--full-aot") == 0) { - mono_aot_only = TRUE; + mono_jit_set_aot_mode (MONO_AOT_MODE_FULL); } else if (strcmp (argv [i], "--llvmonly") == 0) { - mono_aot_only = TRUE; - mono_llvm_only = TRUE; + mono_jit_set_aot_mode (MONO_AOT_MODE_LLVMONLY); + } else if (strcmp (argv [i], "--hybrid-aot") == 0) { + mono_jit_set_aot_mode (MONO_AOT_MODE_HYBRID); } else if (strcmp (argv [i], "--print-vtable") == 0) { mono_print_vtable = TRUE; } else if (strcmp (argv [i], "--stats") == 0) { @@ -1977,15 +1964,13 @@ mono_main (int argc, char* argv[]) mono_counters_init (); +#ifndef HOST_WIN32 + mono_w32handle_init (); +#endif + /* Set rootdir before loading config */ mono_set_rootdir (); - /* - * We only set the native name of the thread since MS.NET leaves the - * managed thread name for the main thread as null. - */ - mono_native_thread_set_name (mono_native_thread_id_get (), "Main"); - if (enable_profile) { mono_profiler_load (profile_options); mono_profiler_thread_name (MONO_NATIVE_THREAD_ID_TO_UINT (mono_native_thread_id_get ()), "Main"); @@ -2312,11 +2297,21 @@ mono_jit_set_aot_only (gboolean val) void mono_jit_set_aot_mode (MonoAotMode mode) { + /* we don't want to set mono_aot_mode twice */ + g_assert (mono_aot_mode == MONO_AOT_MODE_NONE); mono_aot_mode = mode; + if (mono_aot_mode == MONO_AOT_MODE_LLVMONLY) { mono_aot_only = TRUE; mono_llvm_only = TRUE; } + if (mono_aot_mode == MONO_AOT_MODE_FULL) { + mono_aot_only = TRUE; + } + if (mono_aot_mode == MONO_AOT_MODE_HYBRID) { + mono_set_generic_sharing_vt_supported (TRUE); + mono_set_partial_sharing_supported (TRUE); + } } /** diff --git a/mono/mini/emitnunit.pl b/mono/mini/emitnunit.pl deleted file mode 100755 index 63e667985f..0000000000 --- a/mono/mini/emitnunit.pl +++ /dev/null @@ -1,76 +0,0 @@ -#!/usr/bin/perl -use strict; -use warnings; -use Cwd; -use POSIX qw(strftime uname locale_h); -use Net::Domain qw(hostname hostfqdn); -use locale; - -my $line; -foreach $line () { - chomp ($line); - print "$line\n"; - if ($line =~ /^Overall results:/) { - # do magic nunit emission here - # failures look like: - # Overall results: tests: 19992, failed: 48, opt combinations: 24 (pass: 99.76%) - # passes look like: - # Overall results: tests: 20928, 100% pass, opt combinations: 24 - my @words = split (/ /, $line); - my $failed; - my $successbool; - my $total = $words[3]; - my $mylocale = setlocale (LC_CTYPE); - $mylocale = substr($mylocale, 0, index($mylocale, '.')); - $mylocale =~ s/_/-/; - if ($line =~ /failed:/) { - $failed = $words[5]; - } else { - $failed = "0,"; - } - chop ($failed); - chop ($total); - if ($failed > 0) { - $successbool = "False"; - } else { - $successbool = "True"; - } - open (my $nunitxml, '>', 'TestResult-regression.xml') or die "Could not write to 'TestResult-regression.xml' $!"; - print $nunitxml "\n"; - print $nunitxml "\n"; - print $nunitxml "\n"; - print $nunitxml " \n"; - print $nunitxml " \n"; - print $nunitxml " \n"; - print $nunitxml " \n"; - print $nunitxml " \n"; - print $nunitxml " \n"; - print $nunitxml " \n"; - print $nunitxml " \n"; - print $nunitxml " 0) { - print $nunitxml ">\n"; - print $nunitxml " \n"; - print $nunitxml " ) { - chomp ($line); - print "$line\n"; - } - print $nunitxml "]]>\n"; - print $nunitxml " \n"; - print $nunitxml " \n"; - print $nunitxml " \n"; - print $nunitxml " \n"; - } else { - print $nunitxml " />\n"; - } - print $nunitxml " \n"; - print $nunitxml " \n"; - print $nunitxml " \n"; - print $nunitxml " \n"; - print $nunitxml " \n"; - print $nunitxml " \n"; - print $nunitxml "\n"; - close $nunitxml; - } -} diff --git a/mono/mini/exceptions-amd64.c b/mono/mini/exceptions-amd64.c index b011872643..919682acca 100644 --- a/mono/mini/exceptions-amd64.c +++ b/mono/mini/exceptions-amd64.c @@ -1152,13 +1152,15 @@ mono_tasklets_arch_restore (void) amd64_movsl (code); /* now restore the registers from the LMF */ - NOT_IMPLEMENTED; amd64_mov_reg_membase (code, AMD64_RCX, cont_reg, MONO_STRUCT_OFFSET (MonoContinuation, lmf), 8); + amd64_mov_reg_membase (code, AMD64_RBP, AMD64_RCX, MONO_STRUCT_OFFSET (MonoLMF, rbp), 8); amd64_mov_reg_membase (code, AMD64_RSP, AMD64_RCX, MONO_STRUCT_OFFSET (MonoLMF, rsp), 8); - /* restore the lmf chain */ - /*x86_mov_reg_membase (code, X86_ECX, X86_ESP, 12, 4); - x86_mov_membase_reg (code, X86_ECX, 0, X86_EDX, 4);*/ +#ifdef WIN32 + amd64_mov_reg_reg (code, AMD64_R14, AMD64_ARG_REG3, 8); +#else + amd64_mov_reg_reg (code, AMD64_R12, AMD64_ARG_REG3, 8); +#endif /* state is already in rax */ amd64_jump_membase (code, cont_reg, MONO_STRUCT_OFFSET (MonoContinuation, return_ip)); diff --git a/mono/mini/exceptions-arm.c b/mono/mini/exceptions-arm.c index b036aa7a61..c7f01aab9f 100644 --- a/mono/mini/exceptions-arm.c +++ b/mono/mini/exceptions-arm.c @@ -14,9 +14,9 @@ #include #ifndef MONO_CROSS_COMPILE -#ifdef HAVE_ASM_SIGCONTEXT_H +#ifdef PLATFORM_ANDROID #include -#endif /* def HAVE_ASM_SIGCONTEXT_H */ +#endif /* def PLATFORM_ANDROID */ #endif #ifdef HAVE_UCONTEXT_H diff --git a/mono/mini/exceptions-x86.c b/mono/mini/exceptions-x86.c index 5811210cab..d737bc7f7f 100644 --- a/mono/mini/exceptions-x86.c +++ b/mono/mini/exceptions-x86.c @@ -1145,8 +1145,10 @@ mono_tasklets_arch_restore (void) /* the signature is: restore (MonoContinuation *cont, int state, MonoLMF **lmf_addr) */ /* put cont in edx */ x86_mov_reg_membase (code, X86_EDX, X86_ESP, 4, 4); - /* state in eax, so it's setup as the return value */ - x86_mov_reg_membase (code, X86_EAX, X86_ESP, 8, 4); + /* state in eax, so it's setup as the return value */ + x86_mov_reg_membase (code, X86_EAX, X86_ESP, 8, 4); + /* lmf_addr in ebx */ + x86_mov_reg_membase(code, X86_EBX, X86_ESP, 0x0C, 4); /* setup the copy of the stack */ x86_mov_reg_membase (code, X86_ECX, X86_EDX, MONO_STRUCT_OFFSET (MonoContinuation, stack_used_size), 4); @@ -1159,10 +1161,8 @@ mono_tasklets_arch_restore (void) /* now restore the registers from the LMF */ x86_mov_reg_membase (code, X86_ECX, X86_EDX, MONO_STRUCT_OFFSET (MonoContinuation, lmf), 4); - x86_mov_reg_membase (code, X86_EBX, X86_ECX, MONO_STRUCT_OFFSET (MonoLMF, ebx), 4); x86_mov_reg_membase (code, X86_EBP, X86_ECX, MONO_STRUCT_OFFSET (MonoLMF, ebp), 4); - x86_mov_reg_membase (code, X86_ESI, X86_ECX, MONO_STRUCT_OFFSET (MonoLMF, esi), 4); - x86_mov_reg_membase (code, X86_EDI, X86_ECX, MONO_STRUCT_OFFSET (MonoLMF, edi), 4); + x86_mov_reg_membase (code, X86_ESP, X86_ECX, MONO_STRUCT_OFFSET (MonoLMF, esp), 4); /* restore the lmf chain */ /*x86_mov_reg_membase (code, X86_ECX, X86_ESP, 12, 4); diff --git a/mono/mini/generics.cs b/mono/mini/generics.cs index 1284cb292a..0186194491 100644 --- a/mono/mini/generics.cs +++ b/mono/mini/generics.cs @@ -898,6 +898,7 @@ class Tests } [Category ("!FULLAOT")] + [Category ("!BITCODE")] public static int test_0_regress_668095_synchronized_gshared () { return DoSomething (new DefaultRetriever ()); } @@ -1271,7 +1272,6 @@ class Tests c.throw_catch_t (); return 0; } - } #if !__MOBILE__ diff --git a/mono/mini/gshared.cs b/mono/mini/gshared.cs index 88f8c2ebb2..65151b0702 100644 --- a/mono/mini/gshared.cs +++ b/mono/mini/gshared.cs @@ -1907,6 +1907,40 @@ public class Tests bool success = zz == 0xAAAAAAAAAAAAAAAA; return success ? 20 : 1; } + + void gsharedvt_try_at_offset_0 (ref T disposable) + where T : class, IDisposable { + try { + disposable.Dispose (); + } finally { + disposable = null; + } + } + + [MethodImplAttribute (MethodImplOptions.NoInlining)] + static DateTimeOffset gsharedvt_vphi_inner (T t) { + return DateTimeOffset.MinValue; + } + + static DateTimeOffset gsharedvt_vphi (T t) { + int[] arr = new int [10]; + + try { + DateTimeOffset v; + if (arr [0] == 0) + v = gsharedvt_vphi_inner (t); + else + v = gsharedvt_vphi_inner (t); + return v; + } catch { + return DateTimeOffset.MinValue; + } + } + + static int test_0_gsharedvt_vphi_volatile () { + gsharedvt_vphi (0); + return 0; + } } // #13191 diff --git a/mono/mini/jit-icalls.c b/mono/mini/jit-icalls.c index 2a12aecb6f..f8a328375b 100644 --- a/mono/mini/jit-icalls.c +++ b/mono/mini/jit-icalls.c @@ -19,6 +19,7 @@ #include "jit-icalls.h" #include +#include #include #include @@ -1189,13 +1190,21 @@ mono_create_corlib_exception_0 (guint32 token) MonoException * mono_create_corlib_exception_1 (guint32 token, MonoString *arg) { - return mono_exception_from_token_two_strings (mono_defaults.corlib, token, arg, NULL); + MonoError error; + MonoException *ret = mono_exception_from_token_two_strings_checked ( + mono_defaults.corlib, token, arg, NULL, &error); + mono_error_set_pending_exception (&error); + return ret; } MonoException * mono_create_corlib_exception_2 (guint32 token, MonoString *arg1, MonoString *arg2) { - return mono_exception_from_token_two_strings (mono_defaults.corlib, token, arg1, arg2); + MonoError error; + MonoException *ret = mono_exception_from_token_two_strings_checked ( + mono_defaults.corlib, token, arg1, arg2, &error); + mono_error_set_pending_exception (&error); + return ret; } MonoObject* @@ -1487,15 +1496,15 @@ mono_fill_method_rgctx (MonoMethodRuntimeGenericContext *mrgctx, int index) * out parameter. */ static gpointer -resolve_iface_call (MonoObject *this_obj, int imt_slot, MonoMethod *imt_method, gpointer *out_arg, gboolean caller_gsharedvt) +resolve_iface_call (MonoObject *this_obj, int imt_slot, MonoMethod *imt_method, gpointer *out_arg, gboolean caller_gsharedvt, MonoError *error) { - MonoError error; MonoVTable *vt; gpointer *imt, *vtable_slot; MonoMethod *impl_method, *generic_virtual = NULL, *variant_iface = NULL; gpointer addr, compiled_method, aot_addr; gboolean need_rgctx_tramp = FALSE, need_unbox_tramp = FALSE; + mono_error_init (error); if (!this_obj) /* The caller will handle it */ return NULL; @@ -1503,11 +1512,12 @@ resolve_iface_call (MonoObject *this_obj, int imt_slot, MonoMethod *imt_method, vt = this_obj->vtable; imt = (gpointer*)vt - MONO_IMT_SIZE; - vtable_slot = mini_resolve_imt_method (vt, imt + imt_slot, imt_method, &impl_method, &aot_addr, &need_rgctx_tramp, &variant_iface); + vtable_slot = mini_resolve_imt_method (vt, imt + imt_slot, imt_method, &impl_method, &aot_addr, &need_rgctx_tramp, &variant_iface, error); + return_val_if_nok (error, NULL); // FIXME: This can throw exceptions - addr = compiled_method = mono_compile_method_checked (impl_method, &error); - mono_error_assert_ok (&error); + addr = compiled_method = mono_compile_method_checked (impl_method, error); + mono_error_assert_ok (error); g_assert (addr); if (imt_method->is_inflated && ((MonoMethodInflated*)imt_method)->context.method_inst) @@ -1537,7 +1547,13 @@ resolve_iface_call (MonoObject *this_obj, int imt_slot, MonoMethod *imt_method, gpointer mono_resolve_iface_call_gsharedvt (MonoObject *this_obj, int imt_slot, MonoMethod *imt_method, gpointer *out_arg) { - return resolve_iface_call (this_obj, imt_slot, imt_method, out_arg, TRUE); + MonoError error; + gpointer res = resolve_iface_call (this_obj, imt_slot, imt_method, out_arg, TRUE, &error); + if (!is_ok (&error)) { + MonoException *ex = mono_error_convert_to_exception (&error); + mono_llvm_throw_exception ((MonoObject*)ex); + } + return res; } static gboolean @@ -1566,18 +1582,18 @@ is_generic_method_definition (MonoMethod *m) * out parameter. */ static gpointer -resolve_vcall (MonoVTable *vt, int slot, MonoMethod *imt_method, gpointer *out_arg, gboolean gsharedvt) +resolve_vcall (MonoVTable *vt, int slot, MonoMethod *imt_method, gpointer *out_arg, gboolean gsharedvt, MonoError *error) { - MonoError error; MonoMethod *m, *generic_virtual = NULL; gpointer addr, compiled_method; gboolean need_unbox_tramp = FALSE; + mono_error_init (error); /* Same as in common_call_trampoline () */ /* Avoid loading metadata or creating a generic vtable if possible */ - addr = mono_aot_get_method_from_vt_slot (mono_domain_get (), vt, slot, &error); - mono_error_raise_exception (&error); // FIXME: Don't raise here + addr = mono_aot_get_method_from_vt_slot (mono_domain_get (), vt, slot, error); + return_val_if_nok (error, NULL); if (addr && !vt->klass->valuetype) return mono_create_ftnptr (mono_domain_get (), addr); @@ -1602,8 +1618,8 @@ resolve_vcall (MonoVTable *vt, int slot, MonoMethod *imt_method, gpointer *out_a g_assert (generic_virtual->is_inflated); context.method_inst = ((MonoMethodInflated*)generic_virtual)->context.method_inst; - m = mono_class_inflate_generic_method_checked (declaring, &context, &error); - mono_error_assert_ok (&error); /* FIXME don't swallow the error */ + m = mono_class_inflate_generic_method_checked (declaring, &context, error); + mono_error_assert_ok (error); /* FIXME don't swallow the error */ } if (generic_virtual) { @@ -1614,9 +1630,12 @@ resolve_vcall (MonoVTable *vt, int slot, MonoMethod *imt_method, gpointer *out_a need_unbox_tramp = TRUE; } + if (m->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED) + m = mono_marshal_get_synchronized_wrapper (m); + // FIXME: This can throw exceptions - addr = compiled_method = mono_compile_method_checked (m, &error); - mono_error_assert_ok (&error); + addr = compiled_method = mono_compile_method_checked (m, error); + mono_error_assert_ok (error); g_assert (addr); addr = mini_add_method_wrappers_llvmonly (m, addr, gsharedvt, need_unbox_tramp, out_arg); @@ -1638,7 +1657,13 @@ mono_resolve_vcall_gsharedvt (MonoObject *this_obj, int slot, MonoMethod *imt_me { g_assert (this_obj); - return resolve_vcall (this_obj->vtable, slot, imt_method, out_arg, TRUE); + MonoError error; + gpointer result = resolve_vcall (this_obj->vtable, slot, imt_method, out_arg, TRUE, &error); + if (!is_ok (&error)) { + MonoException *ex = mono_error_convert_to_exception (&error); + mono_llvm_throw_exception ((MonoObject*)ex); + } + return result; } /* @@ -1720,14 +1745,20 @@ mono_resolve_generic_virtual_iface_call (MonoVTable *vt, int imt_slot, MonoMetho imt = (gpointer*)vt - MONO_IMT_SIZE; - mini_resolve_imt_method (vt, imt + imt_slot, generic_virtual, &m, &aot_addr, &need_rgctx_tramp, &variant_iface); + mini_resolve_imt_method (vt, imt + imt_slot, generic_virtual, &m, &aot_addr, &need_rgctx_tramp, &variant_iface, &error); + if (!is_ok (&error)) { + MonoException *ex = mono_error_convert_to_exception (&error); + mono_llvm_throw_exception ((MonoObject*)ex); + } if (vt->klass->valuetype) need_unbox_tramp = TRUE; - // FIXME: This can throw exceptions + if (m->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED) + m = mono_marshal_get_synchronized_wrapper (m); + addr = compiled_method = mono_compile_method_checked (m, &error); - mono_error_assert_ok (&error); + mono_error_raise_exception (&error); g_assert (addr); addr = mini_add_method_wrappers_llvmonly (m, addr, FALSE, need_unbox_tramp, &arg); @@ -1754,11 +1785,14 @@ mono_resolve_generic_virtual_iface_call (MonoVTable *vt, int imt_slot, MonoMetho gpointer mono_init_vtable_slot (MonoVTable *vtable, int slot) { + MonoError error; gpointer arg = NULL; gpointer addr; gpointer *ftnptr; - addr = resolve_vcall (vtable, slot, NULL, &arg, FALSE); + addr = resolve_vcall (vtable, slot, NULL, &arg, FALSE, &error); + if (mono_error_set_pending_exception (&error)) + return NULL; ftnptr = mono_domain_alloc0 (vtable->domain, 2 * sizeof (gpointer)); ftnptr [0] = addr; ftnptr [1] = arg; @@ -1787,12 +1821,16 @@ mono_llvmonly_init_delegate (MonoDelegate *del) * but we don't have a a structure which could own its memory. */ if (G_UNLIKELY (!ftndesc)) { - gpointer addr = mono_compile_method_checked (del->method, &error); + MonoMethod *m = del->method; + if (m->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED) + m = mono_marshal_get_synchronized_wrapper (m); + + gpointer addr = mono_compile_method_checked (m, &error); if (mono_error_set_pending_exception (&error)) return; - if (del->method->klass->valuetype && mono_method_signature (del->method)->hasthis) - addr = mono_aot_get_unbox_trampoline (del->method); + if (m->klass->valuetype && mono_method_signature (m)->hasthis) + addr = mono_aot_get_unbox_trampoline (m); gpointer arg = mini_get_delegate_arg (del->method, addr); @@ -1813,6 +1851,9 @@ mono_llvmonly_init_delegate_virtual (MonoDelegate *del, MonoObject *target, Mono method = mono_object_get_virtual_method (target, method); + if (method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED) + method = mono_marshal_get_synchronized_wrapper (method); + del->method = method; del->method_ptr = mono_compile_method_checked (method, &error); if (mono_error_set_pending_exception (&error)) diff --git a/mono/mini/linear-scan.c b/mono/mini/linear-scan.c index 6ee1e0ff79..287022daad 100644 --- a/mono/mini/linear-scan.c +++ b/mono/mini/linear-scan.c @@ -81,9 +81,11 @@ mono_linear_scan (MonoCompile *cfg, GList *vars, GList *regs, regmask_t *used_ma gboolean cost_driven; if (!cfg->disable_reuse_registers && vars && (((MonoMethodVar*)vars->data)->interval != NULL)) { - mono_linear_scan2 (cfg, vars, regs, used_mask); - return; - } + mono_linear_scan2 (cfg, vars, regs, used_mask); + g_list_free (regs); + g_list_free (vars); + return; + } cost_driven = TRUE; diff --git a/mono/mini/llvm-jit.cpp b/mono/mini/llvm-jit.cpp index 7fef6b85cb..2011fddafa 100644 --- a/mono/mini/llvm-jit.cpp +++ b/mono/mini/llvm-jit.cpp @@ -34,6 +34,8 @@ #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" #include "llvm/ExecutionEngine/Orc/OrcArchitectureSupport.h" +#include + extern "C" { #include } @@ -64,6 +66,58 @@ void bzero (void *to, size_t count) { memset (to, 0, count); } #endif +static AllocCodeMemoryCb *alloc_code_mem_cb; + +class MonoJitMemoryManager : public RTDyldMemoryManager +{ +public: + ~MonoJitMemoryManager() override; + + uint8_t *allocateDataSection(uintptr_t Size, + unsigned Alignment, + unsigned SectionID, + StringRef SectionName, + bool IsReadOnly) override; + + uint8_t *allocateCodeSection(uintptr_t Size, + unsigned Alignment, + unsigned SectionID, + StringRef SectionName) override; + + bool finalizeMemory(std::string *ErrMsg = nullptr) override; +}; + +MonoJitMemoryManager::~MonoJitMemoryManager() +{ +} + +uint8_t * +MonoJitMemoryManager::allocateDataSection(uintptr_t Size, + unsigned Alignment, + unsigned SectionID, + StringRef SectionName, + bool IsReadOnly) { + uint8_t *res = (uint8_t*)malloc (Size); + assert (res); + memset (res, 0, Size); + return res; +} + +uint8_t * +MonoJitMemoryManager::allocateCodeSection(uintptr_t Size, + unsigned Alignment, + unsigned SectionID, + StringRef SectionName) +{ + return alloc_code_mem_cb (NULL, Size); +} + +bool +MonoJitMemoryManager::finalizeMemory(std::string *ErrMsg) +{ + return false; +} + class MonoLLVMJIT { public: /* We use our own trampoline infrastructure instead of the Orc one */ @@ -105,7 +159,7 @@ public: } ); return CompileLayer.addModuleSet(singletonSet(M), - make_unique(), + make_unique(), std::move(Resolver)); } @@ -166,6 +220,8 @@ static MonoLLVMJIT *jit; MonoEERef mono_llvm_create_ee (LLVMModuleProviderRef MP, AllocCodeMemoryCb *alloc_cb, FunctionEmittedCb *emitted_cb, ExceptionTableCb *exception_cb, DlSymCb *dlsym_cb, LLVMExecutionEngineRef *ee) { + alloc_code_mem_cb = alloc_cb; + InitializeNativeTarget (); InitializeNativeTargetAsmPrinter(); @@ -760,6 +816,13 @@ mono_llvm_optimize_method (MonoEERef eeref, LLVMValueRef method) g_assert_not_reached (); } +gpointer +mono_llvm_compile_method (MonoEERef mono_ee, LLVMValueRef method, int nvars, LLVMValueRef *callee_vars, gpointer *callee_addrs, gpointer *eh_frame) +{ + g_assert_not_reached (); + return NULL; +} + void mono_llvm_dispose_ee (MonoEERef *eeref) { diff --git a/mono/mini/local-propagation.c b/mono/mini/local-propagation.c index a35a7a39f2..04373359fb 100644 --- a/mono/mini/local-propagation.c +++ b/mono/mini/local-propagation.c @@ -42,6 +42,257 @@ mono_bitset_mp_new_noinit (MonoMemPool *mp, guint32 max_size) return mono_bitset_mem_new (mem, max_size, MONO_BITSET_DONT_FREE); } +struct magic_unsigned { + guint32 magic_number; + gboolean addition; + int shift; +}; + +struct magic_signed { + gint32 magic_number; + int shift; +}; + +/* http://www.hackersdelight.org/hdcodetxt/magicu.c.txt */ +static struct magic_unsigned +compute_magic_unsigned (guint32 divisor) { + guint32 nc, delta, q1, r1, q2, r2; + struct magic_unsigned magu; + gboolean gt = FALSE; + int p; + + magu.addition = 0; + nc = -1 - (-divisor) % divisor; + p = 31; + q1 = 0x80000000 / nc; + r1 = 0x80000000 - q1 * nc; + q2 = 0x7FFFFFFF / divisor; + r2 = 0x7FFFFFFF - q2 * divisor; + do { + p = p + 1; + if (q1 >= 0x80000000) + gt = TRUE; + if (r1 >= nc - r1) { + q1 = 2 * q1 + 1; + r1 = 2 * r1 - nc; + } else { + q1 = 2 * q1; + r1 = 2 * r1; + } + if (r2 + 1 >= divisor - r2) { + if (q2 >= 0x7FFFFFFF) + magu.addition = 1; + q2 = 2 * q2 + 1; + r2 = 2 * r2 + 1 - divisor; + } else { + if (q2 >= 0x80000000) + magu.addition = 1; + q2 = 2 * q2; + r2 = 2 * r2 + 1; + } + delta = divisor - 1 - r2; + } while (!gt && (q1 < delta || (q1 == delta && r1 == 0))); + + magu.magic_number = q2 + 1; + magu.shift = p - 32; + return magu; +} + +/* http://www.hackersdelight.org/hdcodetxt/magic.c.txt */ +static struct magic_signed +compute_magic_signed (gint32 divisor) { + int p; + guint32 ad, anc, delta, q1, r1, q2, r2, t; + const guint32 two31 = 0x80000000; + struct magic_signed mag; + + ad = abs (divisor); + t = two31 + ((unsigned)divisor >> 31); + anc = t - 1 - t % ad; + p = 31; + q1 = two31 / anc; + r1 = two31 - q1 * anc; + q2 = two31 / ad; + r2 = two31 - q2 * ad; + do { + p++; + q1 *= 2; + r1 *= 2; + if (r1 >= anc) { + q1++; + r1 -= anc; + } + + q2 *= 2; + r2 *= 2; + + if (r2 >= ad) { + q2++; + r2 -= ad; + } + + delta = ad - r2; + } while (q1 < delta || (q1 == delta && r1 == 0)); + + mag.magic_number = q2 + 1; + if (divisor < 0) + mag.magic_number = -mag.magic_number; + mag.shift = p - 32; + return mag; +} + +static gboolean +mono_strength_reduction_division (MonoCompile *cfg, MonoInst *ins) +{ + gboolean allocated_vregs = FALSE; + /* + * We don't use it on 32bit systems because on those + * platforms we emulate long multiplication, driving the + * performance back down. + */ + switch (ins->opcode) { + case OP_IDIV_UN_IMM: { + guint32 tmp_regl; +#if SIZEOF_REGISTER == 8 + guint32 dividend_reg; +#else + guint32 tmp_regi; +#endif + struct magic_unsigned mag; + int power2 = mono_is_power_of_two (ins->inst_imm); + + /* The decomposition doesn't handle exception throwing */ + if (ins->inst_imm == 0) + break; + + if (power2 >= 0) { + ins->opcode = OP_ISHR_UN_IMM; + ins->sreg2 = -1; + ins->inst_imm = power2; + break; + } + allocated_vregs = TRUE; + /* + * Replacement of unsigned division with multiplication, + * shifts and additions Hacker's Delight, chapter 10-10. + */ + mag = compute_magic_unsigned (ins->inst_imm); + tmp_regl = alloc_lreg (cfg); +#if SIZEOF_REGISTER == 8 + dividend_reg = alloc_lreg (cfg); + MONO_EMIT_NEW_I8CONST (cfg, tmp_regl, mag.magic_number); + MONO_EMIT_NEW_UNALU (cfg, OP_ZEXT_I4, dividend_reg, ins->sreg1); + MONO_EMIT_NEW_BIALU (cfg, OP_LMUL, tmp_regl, dividend_reg, tmp_regl); + if (mag.addition) { + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_LSHR_UN_IMM, tmp_regl, tmp_regl, 32); + MONO_EMIT_NEW_BIALU (cfg, OP_LADD, tmp_regl, tmp_regl, dividend_reg); + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_LSHR_UN_IMM, ins->dreg, tmp_regl, mag.shift); + } else { + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_LSHR_UN_IMM, ins->dreg, tmp_regl, 32 + mag.shift); + } +#else + tmp_regi = alloc_ireg (cfg); + MONO_EMIT_NEW_ICONST (cfg, tmp_regi, mag.magic_number); + MONO_EMIT_NEW_BIALU (cfg, OP_BIGMUL_UN, tmp_regl, ins->sreg1, tmp_regi); + /* Long shifts below will be decomposed during cprop */ + if (mag.addition) { + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_LSHR_UN_IMM, tmp_regl, tmp_regl, 32); + MONO_EMIT_NEW_BIALU (cfg, OP_IADDCC, MONO_LVREG_LS (tmp_regl), MONO_LVREG_LS (tmp_regl), ins->sreg1); + /* MONO_LVREG_MS (tmp_reg) is 0, save in it the carry */ + MONO_EMIT_NEW_BIALU (cfg, OP_IADC, MONO_LVREG_MS (tmp_regl), MONO_LVREG_MS (tmp_regl), MONO_LVREG_MS (tmp_regl)); + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_LSHR_UN_IMM, tmp_regl, tmp_regl, mag.shift); + } else { + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_LSHR_UN_IMM, tmp_regl, tmp_regl, 32 + mag.shift); + } + MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, ins->dreg, MONO_LVREG_LS (tmp_regl)); +#endif + mono_jit_stats.optimized_divisions++; + break; + } + case OP_IDIV_IMM: { + guint32 tmp_regl; +#if SIZEOF_REGISTER == 8 + guint32 dividend_reg; +#else + guint32 tmp_regi; +#endif + struct magic_signed mag; + int power2 = mono_is_power_of_two (ins->inst_imm); + /* The decomposition doesn't handle exception throwing */ + /* Optimization with MUL does not apply for -1, 0 and 1 divisors */ + if (ins->inst_imm == 0 || ins->inst_imm == -1) { + break; + } else if (ins->inst_imm == 1) { + ins->opcode = OP_MOVE; + ins->inst_imm = 0; + break; + } + allocated_vregs = TRUE; + if (power2 == 1) { + guint32 r1 = alloc_ireg (cfg); + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ISHR_UN_IMM, r1, ins->sreg1, 31); + MONO_EMIT_NEW_BIALU (cfg, OP_IADD, r1, r1, ins->sreg1); + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ISHR_IMM, ins->dreg, r1, 1); + break; + } else if (power2 > 0 && power2 < 31) { + guint32 r1 = alloc_ireg (cfg); + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ISHR_IMM, r1, ins->sreg1, 31); + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ISHR_UN_IMM, r1, r1, (32 - power2)); + MONO_EMIT_NEW_BIALU (cfg, OP_IADD, r1, r1, ins->sreg1); + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ISHR_IMM, ins->dreg, r1, power2); + break; + } + + /* + * Replacement of signed division with multiplication, + * shifts and additions Hacker's Delight, chapter 10-6. + */ + mag = compute_magic_signed (ins->inst_imm); + tmp_regl = alloc_lreg (cfg); +#if SIZEOF_REGISTER == 8 + dividend_reg = alloc_lreg (cfg); + MONO_EMIT_NEW_I8CONST (cfg, tmp_regl, mag.magic_number); + MONO_EMIT_NEW_UNALU (cfg, OP_SEXT_I4, dividend_reg, ins->sreg1); + MONO_EMIT_NEW_BIALU (cfg, OP_LMUL, tmp_regl, dividend_reg, tmp_regl); + if ((ins->inst_imm > 0 && mag.magic_number < 0) || (ins->inst_imm < 0 && mag.magic_number > 0)) { + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_LSHR_IMM, tmp_regl, tmp_regl, 32); + if (ins->inst_imm > 0 && mag.magic_number < 0) { + MONO_EMIT_NEW_BIALU (cfg, OP_LADD, tmp_regl, tmp_regl, dividend_reg); + } else if (ins->inst_imm < 0 && mag.magic_number > 0) { + MONO_EMIT_NEW_BIALU (cfg, OP_LSUB, tmp_regl, tmp_regl, dividend_reg); + } + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_LSHR_IMM, tmp_regl, tmp_regl, mag.shift); + } else { + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_LSHR_IMM, tmp_regl, tmp_regl, 32 + mag.shift); + } + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_LSHR_UN_IMM, ins->dreg, tmp_regl, SIZEOF_REGISTER * 8 - 1); + MONO_EMIT_NEW_BIALU (cfg, OP_LADD, ins->dreg, ins->dreg, tmp_regl); +#else + tmp_regi = alloc_ireg (cfg); + MONO_EMIT_NEW_ICONST (cfg, tmp_regi, mag.magic_number); + MONO_EMIT_NEW_BIALU (cfg, OP_BIGMUL, tmp_regl, ins->sreg1, tmp_regi); + if ((ins->inst_imm > 0 && mag.magic_number < 0) || (ins->inst_imm < 0 && mag.magic_number > 0)) { + if (ins->inst_imm > 0 && mag.magic_number < 0) { + /* Opposite sign, cannot overflow */ + MONO_EMIT_NEW_BIALU (cfg, OP_IADD, tmp_regi, MONO_LVREG_MS (tmp_regl), ins->sreg1); + } else if (ins->inst_imm < 0 && mag.magic_number > 0) { + /* Same sign, cannot overflow */ + MONO_EMIT_NEW_BIALU (cfg, OP_ISUB, tmp_regi, MONO_LVREG_MS (tmp_regl), ins->sreg1); + } + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ISHR_IMM, tmp_regi, tmp_regi, mag.shift); + } else { + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ISHR_IMM, tmp_regi, MONO_LVREG_MS (tmp_regl), mag.shift); + } + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ISHR_UN_IMM, ins->dreg, tmp_regi, SIZEOF_REGISTER * 8 - 1); + MONO_EMIT_NEW_BIALU (cfg, OP_IADD, ins->dreg, ins->dreg, tmp_regi); +#endif + mono_jit_stats.optimized_divisions++; + break; + } + } + return allocated_vregs; +} + /* * Replaces ins with optimized opcodes. * @@ -99,46 +350,20 @@ mono_strength_reduction_ins (MonoCompile *cfg, MonoInst *ins, const char **spec) } } break; - case OP_IREM_UN_IMM: - case OP_IDIV_UN_IMM: { - int c = ins->inst_imm; - int power2 = mono_is_power_of_two (c); + case OP_IREM_UN_IMM: { + int power2 = mono_is_power_of_two (ins->inst_imm); if (power2 >= 0) { - if (ins->opcode == OP_IREM_UN_IMM) { - ins->opcode = OP_IAND_IMM; - ins->sreg2 = -1; - ins->inst_imm = (1 << power2) - 1; - } else if (ins->opcode == OP_IDIV_UN_IMM) { - ins->opcode = OP_ISHR_UN_IMM; - ins->sreg2 = -1; - ins->inst_imm = power2; - } + ins->opcode = OP_IAND_IMM; + ins->sreg2 = -1; + ins->inst_imm = (1 << power2) - 1; } break; } + case OP_IDIV_UN_IMM: case OP_IDIV_IMM: { - int c = ins->inst_imm; - int power2 = mono_is_power_of_two (c); - - if (power2 == 1) { - int r1 = mono_alloc_ireg (cfg); - - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ISHR_UN_IMM, r1, ins->sreg1, 31); - MONO_EMIT_NEW_BIALU (cfg, OP_IADD, r1, r1, ins->sreg1); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ISHR_IMM, ins->dreg, r1, 1); - - allocated_vregs = TRUE; - } else if (power2 > 0 && power2 < 31) { - int r1 = mono_alloc_ireg (cfg); - - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ISHR_IMM, r1, ins->sreg1, 31); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ISHR_UN_IMM, r1, r1, (32 - power2)); - MONO_EMIT_NEW_BIALU (cfg, OP_IADD, r1, r1, ins->sreg1); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ISHR_IMM, ins->dreg, r1, power2); - - allocated_vregs = TRUE; - } + if (!COMPILE_LLVM (cfg)) + allocated_vregs = mono_strength_reduction_division (cfg, ins); break; } #if SIZEOF_REGISTER == 8 diff --git a/mono/mini/main.c b/mono/mini/main.c index 241e6f57e5..80044897a8 100644 --- a/mono/mini/main.c +++ b/mono/mini/main.c @@ -1,7 +1,24 @@ +/* + * main.c: The main entry point for the mono executable + * + * The main entry point does a few things: + * + * * It probes whether the executable has a bundle appended + * at the end, and if so, registers the various bundled + * resources with Mono and executes the contained bundle + * + * * Parses the MONO_ENV_OPTIONS variable to treat the + * contents of the variable as command line arguments for + * the mono runtime + * + * * Launches Mono, by calling mono_main. + */ #include #include #include +#include #include +#include #include "mini.h" #ifdef HAVE_UNISTD_H @@ -28,8 +45,143 @@ mono_main_with_options (int argc, char *argv []) return mono_main (argc, argv); } -#define STREAM_INT(x) (*(uint32_t*)x) -#define STREAM_LONG(x) (*(uint64_t*)x) +/* + * The Mono executable can initialize itself from a payload attached + * at the end of the main program. The payload contains the + * main assembly, one or more managed assemblies, configuration + * files and other assets that are used instead of launching a + * program from the command line. + * + * The startup sequence probes for a magical signature at the end of + * the executable, if the 16 characters "xmonkeysloveplay" are found, + * the code expects the 64-bits just before it to contain an offset + * within the executable with a directory of assets. + * + * All pointers in the file format are encoded as little-endian values + * + * The format of the file is thus: + * + * Location Content + * -------- ------- + * lenght-16 Optional "xmonkeysloveplay", indicating that a + * bundled payload is contained in the executable. + * length-24 pointer to the directory in the file, address DIR + * + * DIR 32-bit value with the number of entries in the directory + * DIR+4 First directory entry. + * + * Each directory entry is made up of: + * 4-bytes uint32_t containing the size of a string (STR) + * STRING UTF8 encoded and \0 terminated string + * 8-bytes uint64_t offset in the file with the payload associated with STRING + * 4-bytes uint32_t size of the asset + * + * The following are the known directory entries, without the quotes: + * "assembly:NAME" An assembly with the name NAME, assembly is in the payload + * "config:NAME" A configuration file (usually file.dll.config) in the payload that is + * loaded as the config file for an assembly + * "systemconfig:" Treats as a Mono system configuration, payload contains the config file. + * "options:" The payload contains command line options to initialize Mono, as if you + had set them on MONO_ENV_OPTIONS + * "config_dir:DIR" Configures the MONO_PATH to point to point to DIR + * "machineconfig:" The payload contains the machine.config file to use at runtime + * "env:" Sets the environment variable to the value encoded in the payload + * payload contains: 1-byte lenght for the \0 terminated variable, + * followed by the value. + * "library:NAME" Bundled dynamic library NAME, payload contains the dynamic library + */ +#define STREAM_INT(x) GUINT32_TO_LE((*(uint32_t*)x)) +#define STREAM_LONG(x) GUINT64_TO_LE((*(uint64_t*)x)) + +/** + * Loads a chunk of data from the file pointed to by the + * @fd starting at the file offset @offset for @size bytes + * and returns an allocated version of that string, or NULL + * on error. + */ +static char * +load_from_region (int fd, uint64_t offset, uint64_t size) +{ + char *buffer; + off_t loc; + int status; + + do { + loc = lseek (fd, offset, SEEK_SET); + } while (loc == -1 && errno == EINTR); + if (loc == -1) + return NULL; + buffer = g_malloc (size + 1); + if (buffer == NULL) + return NULL; + buffer [size] = 0; + do { + status = read (fd, buffer, size); + } while (status == -1 && errno == EINTR); + if (status == -1){ + g_free (buffer); + return NULL; + } + return buffer; +} + +/* Did we initialize the temporary directory for dynamic libraries */ +static int bundle_save_library_initialized; + +/* List of bundled libraries we unpacked */ +static GSList *bundle_library_paths; + +/* Directory where we unpacked dynamic libraries */ +static char *bundled_dylibrary_directory; + +static void +delete_bundled_libraries () +{ + GSList *list; + + for (list = bundle_library_paths; list != NULL; list = list->next){ + unlink (list->data); + } + rmdir (bundled_dylibrary_directory); +} + +static void +bundle_save_library_initialize () +{ + bundle_save_library_initialized = 1; + char *path = g_build_filename (g_get_tmp_dir (), "mono-bundle-XXXXXX", NULL); + bundled_dylibrary_directory = g_mkdtemp (path); + g_free (path); + if (bundled_dylibrary_directory == NULL) + return; + atexit (delete_bundled_libraries); +} + +static void +save_library (int fd, uint64_t offset, uint64_t size, const char *destfname) +{ + MonoDl *lib; + char *file, *buffer, *err, *internal_path; + if (!bundle_save_library_initialized) + bundle_save_library_initialize (); + + file = g_build_filename (bundled_dylibrary_directory, destfname, NULL); + buffer = load_from_region (fd, offset, size); + g_file_set_contents (file, buffer, size, NULL); + + lib = mono_dl_open (file, MONO_DL_LAZY, &err); + if (lib == NULL){ + fprintf (stderr, "Error loading shared library: %s %s\n", file, err); + exit (1); + } + // Register the name with "." as this is how it will be found when embedded + internal_path = g_build_filename (".", destfname, NULL); + mono_loader_register_module (internal_path, lib); + g_free (internal_path); + bundle_library_paths = g_slist_append (bundle_library_paths, file); + + g_free (buffer); +} static gboolean probe_embedded (const char *program, int *ref_argc, char **ref_argv []) @@ -100,29 +252,38 @@ probe_embedded (const char *program, int *ref_argc, char **ref_argv []) if (entry_point == NULL) entry_point = aname; } else if (strncmp (kind, "config:", strlen ("config:")) == 0){ - printf ("c-Found: %s %llx\n", kind, (long long)offset); char *config = kind + strlen ("config:"); char *aname = g_strdup (config); aname [strlen(aname)-strlen(".config")] = 0; - mono_register_config_for_assembly (aname, config); - } else if (strncmp (kind, "system_config:", strlen ("system_config:")) == 0){ - printf ("TODO s-Found: %s %llx\n", kind, (long long)offset); + mono_register_config_for_assembly (aname, load_from_region (fd, offset, item_size)); + } else if (strncmp (kind, "systemconfig:", strlen ("systemconfig:")) == 0){ + mono_config_parse_memory (load_from_region (fd, offset, item_size)); } else if (strncmp (kind, "options:", strlen ("options:")) == 0){ - mono_parse_options_from (kind + strlen("options:"), ref_argc, ref_argv); + mono_parse_options_from (load_from_region (fd, offset, item_size), ref_argc, ref_argv); } else if (strncmp (kind, "config_dir:", strlen ("config_dir:")) == 0){ - printf ("TODO Found: %s %llx\n", kind, (long long)offset); + mono_set_dirs (getenv ("MONO_PATH"), load_from_region (fd, offset, item_size)); + } else if (strncmp (kind, "machineconfig:", strlen ("machineconfig:")) == 0) { + mono_register_machine_config (load_from_region (fd, offset, item_size)); + } else if (strncmp (kind, "env:", strlen ("env:")) == 0){ + char *data = load_from_region (fd, offset, item_size); + uint8_t count = *data++; + char *value = data + count + 1; + g_setenv (data, value, FALSE); + } else if (strncmp (kind, "library:", strlen ("library:")) == 0){ + save_library (fd, offset, item_size, kind + strlen ("library:")); } else { fprintf (stderr, "Unknown stream on embedded package: %s\n", kind); exit (1); } } g_array_append_val (assemblies, last); - + mono_register_bundled_assemblies ((const MonoBundledAssembly **) assemblies->data); new_argv = g_new (char *, (*ref_argc)+1); - for (j = 0; j < *ref_argc; j++) - new_argv [j] = (*ref_argv)[j]; - new_argv [j] = entry_point; + new_argv [0] = (*ref_argv)[0]; + new_argv [1] = entry_point; + for (j = 1; j < *ref_argc; j++) + new_argv [j+1] = (*ref_argv)[j]; *ref_argv = new_argv; (*ref_argc)++; diff --git a/mono/mini/method-to-ir.c.REMOVED.git-id b/mono/mini/method-to-ir.c.REMOVED.git-id index c5d05ee3f1..8df56c323d 100644 --- a/mono/mini/method-to-ir.c.REMOVED.git-id +++ b/mono/mini/method-to-ir.c.REMOVED.git-id @@ -1 +1 @@ -c997ed5af31cb98c0f5784fe9ae8fd20edb74fc5 \ No newline at end of file +965434138b99b82354a510e35de120461917ce05 \ No newline at end of file diff --git a/mono/mini/mini-amd64-gsharedvt.c b/mono/mini/mini-amd64-gsharedvt.c index 2930a31e58..6a4e7af9d4 100644 --- a/mono/mini/mini-amd64-gsharedvt.c +++ b/mono/mini/mini-amd64-gsharedvt.c @@ -5,6 +5,7 @@ * Zoltan Varga * Rodrigo Kumpera * Andi McClure + * Johan Lorensson * * Copyright 2015 Xamarin, Inc (http://www.xamarin.com) * Licensed under the MIT license. See LICENSE file in the project root for full license information. @@ -48,6 +49,7 @@ storage_name (ArgStorage st) case ArgOnStack: return "ArgOnStack"; case ArgValuetypeInReg: return "ArgValuetypeInReg"; case ArgValuetypeAddrInIReg: return "ArgValuetypeAddrInIReg"; + case ArgValuetypeAddrOnStack: return "ArgValuetypeAddrOnStack"; case ArgGSharedVtInReg: return "ArgGSharedVtInReg"; case ArgGSharedVtOnStack: return "ArgGSharedVtOnStack"; case ArgNone: return "ArgNone"; @@ -80,9 +82,17 @@ add_to_map (GPtrArray *map, int src, int dst) /* * Slot mapping: + * + * System V: * 0..5 - rdi, rsi, rdx, rcx, r8, r9 * 6..13 - xmm0..xmm7 * 14.. - stack slots + * + * Windows: + * 0..3 - rcx, rdx, r8, r9 + * 4..7 - xmm0..xmm3 + * 8.. - stack slots + * */ static inline int map_reg (int reg) @@ -158,6 +168,18 @@ get_arg_slots (ArgInfo *ainfo, int **out_slots, gboolean is_source_argument) src = g_malloc (nsrc * sizeof (int)); src [0] = map_freg (sreg); break; + case ArgValuetypeAddrInIReg: + nsrc = 1; + src = g_malloc (nsrc * sizeof (int)); + src [0] = map_reg (ainfo->pair_regs [0]); + break; + case ArgValuetypeAddrOnStack: + nsrc = 1; + src = g_malloc (nsrc * sizeof (int)); + // is_source_argument adds 2 because we're skipping over the old BBP and the return address + // XXX this is a very fragile setup as changes in alignment for the caller reg array can cause the magic number be 3 + src [0] = map_stack_slot (sslot + (is_source_argument ? 2 : 0)); + break; default: NOT_IMPLEMENTED; break; @@ -187,6 +209,11 @@ handle_marshal_when_src_gsharedvt (ArgInfo *dst_info, int *arg_marshal, int *arg *arg_marshal = GSHAREDVT_ARG_BYREF_TO_BYVAL; *arg_slots = dst_info->nregs; break; + case ArgValuetypeAddrInIReg: + case ArgValuetypeAddrOnStack: + *arg_marshal = GSHAREDVT_ARG_NONE; + *arg_slots = dst_info->nregs; + break; default: NOT_IMPLEMENTED; // Inappropriate value: if dst and src are gsharedvt at once, we shouldn't be here break; @@ -205,6 +232,10 @@ handle_marshal_when_dst_gsharedvt (ArgInfo *src_info, int *arg_marshal) case ArgOnStack: *arg_marshal = GSHAREDVT_ARG_BYVAL_TO_BYREF; break; + case ArgValuetypeAddrInIReg: + case ArgValuetypeAddrOnStack: + *arg_marshal = GSHAREDVT_ARG_NONE; + break; default: NOT_IMPLEMENTED; // See above break; @@ -316,6 +347,10 @@ mono_arch_get_gsharedvt_call_info (gpointer addr, MonoMethodSignature *normal_si handle_marshal_when_src_gsharedvt (dst_info, &arg_marshal, &arg_slots); handle_map_when_gsharedvt_on_stack (src_info, &nsrc, &src, TRUE); break; + case ArgValuetypeAddrInIReg: + case ArgValuetypeAddrOnStack: + nsrc = get_arg_slots (src_info, &src, TRUE); + break; default: g_error ("Gsharedvt can't handle source arg type %d", (int)src_info->storage); // Inappropriate value: ArgValuetypeAddrInIReg is for returns only } @@ -336,6 +371,10 @@ mono_arch_get_gsharedvt_call_info (gpointer addr, MonoMethodSignature *normal_si handle_marshal_when_dst_gsharedvt (src_info, &arg_marshal); handle_map_when_gsharedvt_on_stack (dst_info, &ndst, &dst, FALSE); break; + case ArgValuetypeAddrInIReg: + case ArgValuetypeAddrOnStack: + ndst = get_arg_slots (dst_info, &dst, FALSE); + break; default: g_error ("Gsharedvt can't handle dest arg type %d", (int)dst_info->storage); // See above } @@ -356,7 +395,7 @@ mono_arch_get_gsharedvt_call_info (gpointer addr, MonoMethodSignature *normal_si DEBUG_AMD64_GSHAREDVT_PRINT ("-- return in (%s) out (%s) var_ret %d\n", arg_info_desc (&caller_cinfo->ret), arg_info_desc (&callee_cinfo->ret), var_ret); if (cinfo->ret.storage == ArgValuetypeAddrInIReg) { - /* Both the caller and the callee pass the vtype ret address in r8 */ + /* Both the caller and the callee pass the vtype ret address in r8 (System V) and RCX or RDX (Windows) */ g_assert (gcinfo->ret.storage == ArgValuetypeAddrInIReg || gcinfo->ret.storage == ArgGsharedvtVariableInReg); add_to_map (map, map_reg (cinfo->ret.reg), map_reg (cinfo->ret.reg)); } @@ -474,6 +513,9 @@ mono_arch_get_gsharedvt_call_info (gpointer addr, MonoMethodSignature *normal_si info->stack_usage = ALIGN_TO (info->stack_usage, MONO_ARCH_FRAME_ALIGNMENT); + g_free (callee_cinfo); + g_free (caller_cinfo); + DEBUG_AMD64_GSHAREDVT_PRINT ("allocated an info at %p stack usage %d\n", info, info->stack_usage); return info; } diff --git a/mono/mini/mini-amd64-gsharedvt.h b/mono/mini/mini-amd64-gsharedvt.h index 3e3d56c54f..1bb14e5abd 100644 --- a/mono/mini/mini-amd64-gsharedvt.h +++ b/mono/mini/mini-amd64-gsharedvt.h @@ -5,6 +5,7 @@ * Zoltan Varga * Rodrigo Kumpera * Andi McClure + * Johan Lorensson * * Copyright 2015 Xamarin, Inc (http://www.xamarin.com) * Licensed under the MIT license. See LICENSE file in the project root for full license information. diff --git a/mono/mini/mini-amd64.c.REMOVED.git-id b/mono/mini/mini-amd64.c.REMOVED.git-id index 7b364b9eb5..aa59cf0caa 100644 --- a/mono/mini/mini-amd64.c.REMOVED.git-id +++ b/mono/mini/mini-amd64.c.REMOVED.git-id @@ -1 +1 @@ -3f41fb3fc226e85aa23b373990dd4e5738d6d28d \ No newline at end of file +3db3f59ac8a8d3be96d86874d46e4ac43a7e450a \ No newline at end of file diff --git a/mono/mini/mini-amd64.h b/mono/mini/mini-amd64.h index 753c091a3b..22e7413a6f 100644 --- a/mono/mini/mini-amd64.h +++ b/mono/mini/mini-amd64.h @@ -188,12 +188,20 @@ typedef struct MonoCompileArch { } MonoCompileArch; #ifdef TARGET_WIN32 -#define PARAM_REGS 4 -#define FLOAT_PARAM_REGS 4 static AMD64_Reg_No param_regs [] = { AMD64_RCX, AMD64_RDX, AMD64_R8, AMD64_R9 }; -static AMD64_Reg_No return_regs [] = { AMD64_RAX, AMD64_RDX }; +static AMD64_Reg_No float_param_regs [] = { AMD64_XMM0, AMD64_XMM1, AMD64_XMM2, AMD64_XMM3 }; + +static AMD64_Reg_No return_regs [] = { AMD64_RAX }; + +static AMD64_Reg_No float_return_regs [] = { AMD64_XMM0 }; + +#define PARAM_REGS G_N_ELEMENTS(param_regs) +#define FLOAT_PARAM_REGS G_N_ELEMENTS(float_param_regs) +#define RETURN_REGS G_N_ELEMENTS(return_regs) +#define FLOAT_RETURN_REGS G_N_ELEMENTS(float_return_regs) + #else #define PARAM_REGS 6 #define FLOAT_PARAM_REGS 8 @@ -230,8 +238,10 @@ typedef struct { gpointer bp_addrs [MONO_ZERO_LEN_ARRAY]; } SeqPointInfo; +#define DYN_CALL_STACK_ARGS 6 + typedef struct { - mgreg_t regs [PARAM_REGS]; + mgreg_t regs [PARAM_REGS + DYN_CALL_STACK_ARGS]; mgreg_t res; guint8 *ret; double fregs [8]; @@ -246,6 +256,7 @@ typedef enum { ArgOnStack, ArgValuetypeInReg, ArgValuetypeAddrInIReg, + ArgValuetypeAddrOnStack, /* gsharedvt argument passed by addr */ ArgGSharedVtInReg, ArgGSharedVtOnStack, @@ -267,6 +278,7 @@ typedef struct { int nregs; /* Only if storage == ArgOnStack */ int arg_size; // Bytes, will always be rounded up/aligned to 8 byte boundary + guint8 pass_empty_struct : 1; // Set in scenarios when empty structs needs to be represented as argument. } ArgInfo; typedef struct { @@ -386,10 +398,11 @@ typedef struct { #define MONO_ARCH_GSHARED_SUPPORTED 1 #define MONO_ARCH_DYN_CALL_SUPPORTED 1 -#define MONO_ARCH_DYN_CALL_PARAM_AREA 0 +#define MONO_ARCH_DYN_CALL_PARAM_AREA (DYN_CALL_STACK_ARGS * 8) #define MONO_ARCH_LLVM_SUPPORTED 1 #define MONO_ARCH_HAVE_HANDLER_BLOCK_GUARD 1 +#define MONO_ARCH_HAVE_HANDLER_BLOCK_GUARD_AOT 1 #define MONO_ARCH_HAVE_CARD_TABLE_WBARRIER 1 #define MONO_ARCH_HAVE_SETUP_RESUME_FROM_SIGNAL_HANDLER_CTX 1 #define MONO_ARCH_GC_MAPS_SUPPORTED 1 @@ -412,9 +425,7 @@ typedef struct { #define MONO_ARCH_HAVE_TLS_GET_REG 1 #endif -#if !defined (TARGET_WIN32) #define MONO_ARCH_GSHAREDVT_SUPPORTED 1 -#endif #if defined(TARGET_APPLETVOS) @@ -471,6 +482,9 @@ mono_amd64_get_exception_trampolines (gboolean aot); int mono_amd64_get_tls_gs_offset (void) MONO_LLVM_INTERNAL; +gpointer +mono_amd64_handler_block_trampoline_helper (void); + #ifdef TARGET_WIN32 void mono_arch_unwindinfo_add_push_nonvol (gpointer* monoui, gpointer codebegin, gpointer nextip, guchar reg ); diff --git a/mono/mini/mini-arm.c.REMOVED.git-id b/mono/mini/mini-arm.c.REMOVED.git-id index e996b06490..4089c73503 100644 --- a/mono/mini/mini-arm.c.REMOVED.git-id +++ b/mono/mini/mini-arm.c.REMOVED.git-id @@ -1 +1 @@ -2eac36939370f203a0ed0b3ea7e284bc90b21527 \ No newline at end of file +e249d1215b974ea22b97135efc8865641fd6e064 \ No newline at end of file diff --git a/mono/mini/mini-arm.h b/mono/mini/mini-arm.h index 046b8c543f..5df9de5bba 100644 --- a/mono/mini/mini-arm.h +++ b/mono/mini/mini-arm.h @@ -226,6 +226,7 @@ typedef struct { typedef struct { gpointer ss_trigger_page; gpointer bp_trigger_page; + gpointer ss_tramp_addr; guint8* bp_addrs [MONO_ZERO_LEN_ARRAY]; } SeqPointInfo; @@ -349,6 +350,7 @@ typedef struct MonoCompileArch { #define MONO_ARCH_HAVE_SDB_TRAMPOLINES 1 #define MONO_ARCH_HAVE_PATCH_CODE_NEW 1 #define MONO_ARCH_HAVE_OP_GENERIC_CLASS_INIT 1 +#define MONO_ARCH_HAVE_GET_TLS_TRAMP 1 #define MONO_ARCH_HAVE_TLS_GET (mono_arm_have_tls_get ()) #define MONO_ARCH_HAVE_TLS_GET_REG 1 diff --git a/mono/mini/mini-arm64.c.REMOVED.git-id b/mono/mini/mini-arm64.c.REMOVED.git-id index 8d62e892e3..6623c313a7 100644 --- a/mono/mini/mini-arm64.c.REMOVED.git-id +++ b/mono/mini/mini-arm64.c.REMOVED.git-id @@ -1 +1 @@ -995aea83d98094d62e65b814a85ba53c4744c5c1 \ No newline at end of file +b7652c94f218e0d67ed6ef9ae1bf0c0e4ff1493a \ No newline at end of file diff --git a/mono/mini/mini-arm64.h b/mono/mini/mini-arm64.h index e3e90eb6ea..9ae56a66e6 100644 --- a/mono/mini/mini-arm64.h +++ b/mono/mini/mini-arm64.h @@ -143,9 +143,7 @@ typedef struct { #define MONO_ARCH_DYN_CALL_SUPPORTED 1 #define MONO_ARCH_DYN_CALL_PARAM_AREA (DYN_CALL_STACK_ARGS * 8) #define MONO_ARCH_SOFT_DEBUG_SUPPORTED 1 -#ifndef TARGET_ANDROID #define MONO_ARCH_GSHAREDVT_SUPPORTED 1 -#endif #define MONO_ARCH_HAVE_SETUP_RESUME_FROM_SIGNAL_HANDLER_CTX 1 #define MONO_ARCH_HAVE_SETUP_ASYNC_CALLBACK 1 #define MONO_ARCH_HAVE_GENERAL_RGCTX_LAZY_FETCH_TRAMPOLINE 1 diff --git a/mono/mini/mini-codegen.c b/mono/mini/mini-codegen.c index 9cf772bad0..57a7a38dee 100644 --- a/mono/mini/mini-codegen.c +++ b/mono/mini/mini-codegen.c @@ -535,6 +535,10 @@ mono_print_ins_index_strbuf (int i, MonoInst *ins) case OP_GSHAREDVT_ARG_REGOFFSET: g_string_append_printf (sbuf, " + 0x%lx", (long)ins->inst_offset); break; + case OP_ISINST: + case OP_CASTCLASS: + g_string_append_printf (sbuf, " %s", ins->klass->name); + break; default: break; } diff --git a/mono/mini/mini-exceptions.c b/mono/mini/mini-exceptions.c index 4ddcffaf1f..8b666bfe70 100644 --- a/mono/mini/mini-exceptions.c +++ b/mono/mini/mini-exceptions.c @@ -89,14 +89,12 @@ static gpointer throw_corlib_exception_func; static gpointer try_more_restore_tramp = NULL; static gpointer restore_stack_protection_tramp = NULL; -static MonoUnhandledExceptionFunc unhandled_exception_hook = NULL; -static gpointer unhandled_exception_hook_data = NULL; - static void try_more_restore (void); static void restore_stack_protection (void); static void mono_walk_stack_full (MonoJitStackWalk func, MonoContext *start_ctx, MonoDomain *domain, MonoJitTlsData *jit_tls, MonoLMF *lmf, MonoUnwindOptions unwind_options, gpointer user_data); static void mono_raise_exception_with_ctx (MonoException *exc, MonoContext *ctx); static void mono_runtime_walk_stack_with_ctx (MonoJitStackWalk func, MonoContext *start_ctx, MonoUnwindOptions unwind_options, void *user_data); +static gboolean mono_current_thread_has_handle_block_guard (void); void mono_exceptions_init (void) @@ -139,6 +137,7 @@ mono_exceptions_init (void) cbs.mono_raise_exception_with_ctx = mono_raise_exception_with_ctx; cbs.mono_exception_walk_trace = mono_exception_walk_trace; cbs.mono_install_handler_block_guard = mono_install_handler_block_guard; + cbs.mono_current_thread_has_handle_block_guard = mono_current_thread_has_handle_block_guard; mono_install_eh_callbacks (&cbs); } @@ -1230,7 +1229,7 @@ wrap_non_exception_throws (MonoMethod *m) klass = mono_class_get_runtime_compat_attr_class (); - attrs = mono_custom_attrs_from_assembly_checked (ass, &error); + attrs = mono_custom_attrs_from_assembly_checked (ass, FALSE, &error); mono_error_cleanup (&error); /* FIXME don't swallow the error */ if (attrs) { for (i = 0; i < attrs->num_attrs; ++i) { @@ -1291,7 +1290,10 @@ build_native_trace (MonoError *error) #if defined (HAVE_BACKTRACE_SYMBOLS) && defined (TARGET_ARM) MonoArray *res; void *native_trace [MAX_UNMANAGED_BACKTRACE]; - int size = backtrace (native_trace, MAX_UNMANAGED_BACKTRACE); + int size = -1; + MONO_ENTER_GC_SAFE; + size = backtrace (native_trace, MAX_UNMANAGED_BACKTRACE); + MONO_EXIT_GC_SAFE; int i; if (!size) @@ -2390,7 +2392,7 @@ mono_handle_native_sigsegv (int signal, void *ctx, MONO_SIG_HANDLER_INFO_TYPE *i for (i =0; i < size; ++i) { mono_runtime_printf_err ("\t%s", names [i]); } - free (names); + g_free (names); /* Try to get more meaningful information using gdb */ @@ -2487,9 +2489,6 @@ mono_print_thread_dump_internal (void *sigctx, MonoContext *start_ctx) #endif GString* text; char *name; -#ifndef HOST_WIN32 - char *wapi_desc; -#endif GError *error = NULL; if (!thread) @@ -2507,11 +2506,9 @@ mono_print_thread_dump_internal (void *sigctx, MonoContext *start_ctx) else g_string_append (text, "\n\"\""); -#ifndef HOST_WIN32 - wapi_desc = wapi_current_thread_desc (); - g_string_append_printf (text, " tid=0x%p this=0x%p %s\n", (gpointer)(gsize)thread->tid, thread, wapi_desc); - free (wapi_desc); -#endif + g_string_append_printf (text, " tid=0x%p this=0x%p ", (gpointer)(gsize)thread->tid, thread); + mono_thread_info_describe ((MonoThreadInfo*) thread->thread_info, text); + g_string_append (text, "\n"); #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX if (start_ctx) { @@ -2645,7 +2642,6 @@ install_handler_block_guard (MonoJitInfo *ji, MonoContext *ctx) /* * Finds the bottom handler block running and install a block guard if needed. - * FIXME add full-aot support. */ gboolean mono_install_handler_block_guard (MonoThreadUnwindState *ctx) @@ -2654,9 +2650,10 @@ mono_install_handler_block_guard (MonoThreadUnwindState *ctx) MonoJitTlsData *jit_tls = (MonoJitTlsData *)ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS]; gpointer resume_ip; - /* FIXME */ +#ifndef MONO_ARCH_HAVE_HANDLER_BLOCK_GUARD_AOT if (mono_aot_only) return FALSE; +#endif /* Guard against a null MonoJitTlsData. This can happens if the thread receives the * interrupt signal before the JIT has time to initialize its TLS data for the given thread. @@ -2684,6 +2681,13 @@ mono_install_handler_block_guard (MonoThreadUnwindState *ctx) return TRUE; } +static gboolean +mono_current_thread_has_handle_block_guard (void) +{ + MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id); + return jit_tls && jit_tls->handler_block_return_address != NULL; +} + #else gboolean mono_install_handler_block_guard (MonoThreadUnwindState *ctx) @@ -2691,6 +2695,12 @@ mono_install_handler_block_guard (MonoThreadUnwindState *ctx) return FALSE; } +static gboolean +mono_current_thread_has_handle_block_guard (void) +{ + return FALSE; +} + #endif void @@ -2824,55 +2834,6 @@ mono_setup_async_callback (MonoContext *ctx, void (*async_cb)(void *fun), gpoint #endif } -void -mono_install_unhandled_exception_hook (MonoUnhandledExceptionFunc func, gpointer user_data) -{ - unhandled_exception_hook = func; - unhandled_exception_hook_data = user_data; -} - -void -mono_invoke_unhandled_exception_hook (MonoObject *exc) -{ - if (unhandled_exception_hook) { - unhandled_exception_hook (exc, unhandled_exception_hook_data); - } else { - MonoObject *other = NULL; - MonoString *str = mono_object_to_string (exc, &other); - char *msg = NULL; - - if (str) { - MonoError inner_error; - msg = mono_string_to_utf8_checked (str, &inner_error); - if (!is_ok (&inner_error)) { - msg = g_strdup_printf ("Nested exception while formatting original exception"); - mono_error_cleanup (&inner_error); - } - } - else if (other) { - char *original_backtrace = mono_exception_get_managed_backtrace ((MonoException*)exc); - char *nested_backtrace = mono_exception_get_managed_backtrace ((MonoException*)other); - - msg = g_strdup_printf ("Nested exception detected.\nOriginal Exception: %s\nNested exception:%s\n", - original_backtrace, nested_backtrace); - - g_free (original_backtrace); - g_free (nested_backtrace); - } else { - msg = g_strdup ("Nested exception trying to figure out what went wrong"); - } - mono_runtime_printf_err ("[ERROR] FATAL UNHANDLED EXCEPTION: %s", msg); - g_free (msg); -#if defined(HOST_IOS) - g_assertion_message ("Terminating runtime due to unhandled exception"); -#else - exit (mono_environment_exitcode_get ()); -#endif - } - - g_assert_not_reached (); -} - /* * mono_restore_context: * @@ -2931,6 +2892,7 @@ throw_exception (MonoObject *ex, gboolean rethrow) mono_error_assert_ok (&error); mono_ex = mono_get_exception_runtime_wrapped_checked (ex, &error); mono_error_assert_ok (&error); + jit_tls->thrown_non_exc = mono_gchandle_new (ex, FALSE); } else mono_ex = (MonoException*)ex; @@ -3010,7 +2972,7 @@ mono_llvm_resume_exception (void) MonoObject * mono_llvm_load_exception (void) { - MonoError error; + MonoError error; MonoJitTlsData *jit_tls = mono_get_jit_tls (); MonoException *mono_ex = (MonoException*)mono_gchandle_get_target (jit_tls->thrown_exc); @@ -3062,6 +3024,9 @@ mono_llvm_clear_exception (void) MonoJitTlsData *jit_tls = mono_get_jit_tls (); mono_gchandle_free (jit_tls->thrown_exc); jit_tls->thrown_exc = 0; + if (jit_tls->thrown_non_exc) + mono_gchandle_free (jit_tls->thrown_non_exc); + jit_tls->thrown_non_exc = 0; mono_memory_barrier (); } @@ -3075,13 +3040,22 @@ mono_llvm_clear_exception (void) gint32 mono_llvm_match_exception (MonoJitInfo *jinfo, guint32 region_start, guint32 region_end, gpointer rgctx, MonoObject *this_obj) { - MonoError error; + MonoError error; MonoJitTlsData *jit_tls = mono_get_jit_tls (); MonoObject *exc; gint32 index = -1; g_assert (jit_tls->thrown_exc); exc = mono_gchandle_get_target (jit_tls->thrown_exc); + if (jit_tls->thrown_non_exc) { + /* + * Have to unwrap RuntimeWrappedExceptions if the + * method's assembly doesn't have a RuntimeCompatibilityAttribute. + */ + if (!wrap_non_exception_throws (jinfo_get_method (jinfo))) + exc = mono_gchandle_get_target (jit_tls->thrown_non_exc); + } + for (int i = 0; i < jinfo->num_clauses; i++) { MonoJitExceptionInfo *ei = &jinfo->clauses [i]; MonoClass *catch_class; @@ -3090,7 +3064,7 @@ mono_llvm_match_exception (MonoJitInfo *jinfo, guint32 region_start, guint32 reg continue; catch_class = ei->data.catch_class; - if (catch_class->byval_arg.type == MONO_TYPE_VAR || catch_class->byval_arg.type == MONO_TYPE_MVAR || catch_class->byval_arg.type == MONO_TYPE_GENERICINST) { + if (mono_class_is_open_constructed_type (&catch_class->byval_arg)) { MonoGenericContext context; MonoType *inflated_type; diff --git a/mono/mini/mini-generic-sharing.c.REMOVED.git-id b/mono/mini/mini-generic-sharing.c.REMOVED.git-id index b0cf164d7a..572d53387f 100644 --- a/mono/mini/mini-generic-sharing.c.REMOVED.git-id +++ b/mono/mini/mini-generic-sharing.c.REMOVED.git-id @@ -1 +1 @@ -84c21c5890e9dfedf73e95a441857fc6875f370a \ No newline at end of file +aca368c9dba9e1ad8ef382fa8e7532a93981ffe5 \ No newline at end of file diff --git a/mono/mini/mini-llvm-cpp.cpp b/mono/mini/mini-llvm-cpp.cpp index e3219686ae..1bf14393db 100644 --- a/mono/mini/mini-llvm-cpp.cpp +++ b/mono/mini/mini-llvm-cpp.cpp @@ -54,10 +54,20 @@ mono_llvm_build_alloca (LLVMBuilderRef builder, LLVMTypeRef Ty, LLVMValueRef mono_llvm_build_load (LLVMBuilderRef builder, LLVMValueRef PointerVal, - const char *Name, gboolean is_volatile, BarrierKind barrier) + const char *Name, gboolean is_volatile) { LoadInst *ins = unwrap(builder)->CreateLoad(unwrap(PointerVal), is_volatile, Name); + return wrap(ins); +} + +LLVMValueRef +mono_llvm_build_atomic_load (LLVMBuilderRef builder, LLVMValueRef PointerVal, + const char *Name, gboolean is_volatile, int alignment, BarrierKind barrier) +{ + LoadInst *ins = unwrap(builder)->CreateLoad(unwrap(PointerVal), is_volatile, Name); + + ins->setAlignment (alignment); switch (barrier) { case LLVM_BARRIER_NONE: break; @@ -219,6 +229,14 @@ mono_llvm_set_call_preserveall_cc (LLVMValueRef func) unwrap(func)->setCallingConv (CallingConv::PreserveAll); } +void +mono_llvm_set_call_notail (LLVMValueRef func) +{ +#if LLVM_API_VERSION > 100 + //unwrap(func)->setTailCallKind (CallInst::TailCallKind::TCK_NoTail); +#endif +} + #if LLVM_API_VERSION > 100 void* @@ -236,16 +254,21 @@ mono_llvm_di_create_compile_unit (void *di_builder, const char *cu_name, const c } void* -mono_llvm_di_create_function (void *di_builder, void *cu, const char *name, const char *mangled_name, const char *dir, const char *file, int line) +mono_llvm_di_create_function (void *di_builder, void *cu, LLVMValueRef func, const char *name, const char *mangled_name, const char *dir, const char *file, int line) { DIBuilder *builder = (DIBuilder*)di_builder; DIFile *di_file; DISubroutineType *type; + DISubprogram *di_func; // FIXME: Share DIFile di_file = builder->createFile (file, dir); type = builder->createSubroutineType (builder->getOrCreateTypeArray (ArrayRef ())); - return builder->createFunction (di_file, name, mangled_name, di_file, line, type, true, true, 0); + di_func = builder->createFunction (di_file, name, mangled_name, di_file, line, type, true, true, 0); + + unwrap(func)->setMetadata ("dbg", di_func); + + return di_func; } void* diff --git a/mono/mini/mini-llvm-cpp.h b/mono/mini/mini-llvm-cpp.h index 06858713f4..f969274e4a 100644 --- a/mono/mini/mini-llvm-cpp.h +++ b/mono/mini/mini-llvm-cpp.h @@ -44,9 +44,13 @@ mono_llvm_build_alloca (LLVMBuilderRef builder, LLVMTypeRef Ty, LLVMValueRef mono_llvm_build_load (LLVMBuilderRef builder, LLVMValueRef PointerVal, - const char *Name, gboolean is_volatile, BarrierKind barrier); + const char *Name, gboolean is_volatile); LLVMValueRef +mono_llvm_build_atomic_load (LLVMBuilderRef builder, LLVMValueRef PointerVal, + const char *Name, gboolean is_volatile, int alignment, BarrierKind barrier); + +LLVMValueRef mono_llvm_build_aligned_load (LLVMBuilderRef builder, LLVMValueRef PointerVal, const char *Name, gboolean is_volatile, int alignment); @@ -85,6 +89,9 @@ mono_llvm_set_preserveall_cc (LLVMValueRef func); void mono_llvm_set_call_preserveall_cc (LLVMValueRef call); +void +mono_llvm_set_call_notail (LLVMValueRef call); + _Unwind_Reason_Code mono_debug_personality (int a, _Unwind_Action b, uint64_t c, struct _Unwind_Exception *d, struct _Unwind_Context *e); @@ -96,7 +103,7 @@ void* mono_llvm_create_di_builder (LLVMModuleRef module); void* -mono_llvm_di_create_function (void *di_builder, void *cu, const char *name, const char *mangled_name, const char *dir, const char *file, int line); +mono_llvm_di_create_function (void *di_builder, void *cu, LLVMValueRef func, const char *name, const char *mangled_name, const char *dir, const char *file, int line); void* mono_llvm_di_create_compile_unit (void *di_builder, const char *cu_name, const char *dir, const char *producer); diff --git a/mono/mini/mini-llvm.c.REMOVED.git-id b/mono/mini/mini-llvm.c.REMOVED.git-id index 3af216e208..3027178162 100644 --- a/mono/mini/mini-llvm.c.REMOVED.git-id +++ b/mono/mini/mini-llvm.c.REMOVED.git-id @@ -1 +1 @@ -33a4ca8d181b6ff7032ee475b3c355317dda43da \ No newline at end of file +b83c823acfb57b9c0df3e1d56790906fa106dae8 \ No newline at end of file diff --git a/mono/mini/mini-native-types.c b/mono/mini/mini-native-types.c index 5d66853ece..6e461b806b 100644 --- a/mono/mini/mini-native-types.c +++ b/mono/mini/mini-native-types.c @@ -406,6 +406,13 @@ mono_class_is_magic_float (MonoClass *klass) if (strcmp ("nfloat", klass->name) == 0) { magic_nfloat_class = klass; + + /* Assert that we are using the matching assembly */ + MonoClassField *value_field = mono_class_get_field_from_name (klass, "v"); + g_assert (value_field); + MonoType *t = mono_field_get_type (value_field); + g_assert (t->type == mini_native_type_replace_type (&klass->byval_arg)->type); + return TRUE; } return FALSE; diff --git a/mono/mini/mini-ops.h b/mono/mini/mini-ops.h index 883fc1af32..07dd0a4353 100644 --- a/mono/mini/mini-ops.h +++ b/mono/mini/mini-ops.h @@ -706,6 +706,9 @@ MINI_OP(OP_STRLEN, "strlen", IREG, IREG, NONE) MINI_OP(OP_NEWARR, "newarr", IREG, IREG, NONE) MINI_OP(OP_LDLEN, "ldlen", IREG, IREG, NONE) MINI_OP(OP_BOUNDS_CHECK, "bounds_check", NONE, IREG, IREG) +/* type checks */ +MINI_OP(OP_ISINST, "isinst", IREG, IREG, NONE) +MINI_OP(OP_CASTCLASS, "castclass", IREG, IREG, NONE) /* get adress of element in a 2D array */ MINI_OP(OP_LDELEMA2D, "getldelema2", NONE, NONE, NONE) /* inlined small memcpy with constant length */ @@ -1397,3 +1400,4 @@ MINI_OP(OP_OBJC_GET_SELECTOR, "objc_get_selector", IREG, NONE, NONE) MINI_OP(OP_GET_SP, "get_sp", IREG, NONE, NONE) MINI_OP(OP_SET_SP, "set_sp", NONE, IREG, NONE) +MINI_OP(OP_GET_LAST_ERROR, "get_last_error", IREG, NONE, NONE) diff --git a/mono/mini/mini-posix.c b/mono/mini/mini-posix.c index 6f6e266a3b..bdd3149c25 100644 --- a/mono/mini/mini-posix.c +++ b/mono/mini/mini-posix.c @@ -140,11 +140,15 @@ mono_gdb_render_native_backtraces (pid_t crashed_pid) static GHashTable *mono_saved_signal_handlers = NULL; static struct sigaction * -get_saved_signal_handler (int signo) +get_saved_signal_handler (int signo, gboolean remove) { - if (mono_saved_signal_handlers) + if (mono_saved_signal_handlers) { /* The hash is only modified during startup, so no need for locking */ - return (struct sigaction *)g_hash_table_lookup (mono_saved_signal_handlers, GINT_TO_POINTER (signo)); + struct sigaction *handler = g_hash_table_lookup (mono_saved_signal_handlers, GINT_TO_POINTER (signo)); + if (remove && handler) + g_hash_table_remove (mono_saved_signal_handlers, GINT_TO_POINTER (signo)); + return handler; + } return NULL; } @@ -167,21 +171,14 @@ save_old_signal_handler (int signo, struct sigaction *old_action) handler_to_save->sa_flags = old_action->sa_flags; if (!mono_saved_signal_handlers) - mono_saved_signal_handlers = g_hash_table_new (NULL, NULL); + mono_saved_signal_handlers = g_hash_table_new_full (NULL, NULL, NULL, g_free); g_hash_table_insert (mono_saved_signal_handlers, GINT_TO_POINTER (signo), handler_to_save); } -static void -free_saved_sig_handler_func (gpointer key, gpointer value, gpointer user_data) -{ - g_free (value); -} - static void free_saved_signal_handlers (void) { if (mono_saved_signal_handlers) { - g_hash_table_foreach (mono_saved_signal_handlers, free_saved_sig_handler_func, NULL); g_hash_table_destroy (mono_saved_signal_handlers); mono_saved_signal_handlers = NULL; } @@ -198,7 +195,7 @@ gboolean MONO_SIG_HANDLER_SIGNATURE (mono_chain_signal) { int signal = MONO_SIG_HANDLER_GET_SIGNO (); - struct sigaction *saved_handler = (struct sigaction *)get_saved_signal_handler (signal); + struct sigaction *saved_handler = (struct sigaction *)get_saved_signal_handler (signal, FALSE); if (saved_handler && saved_handler->sa_handler) { if (!(saved_handler->sa_flags & SA_SIGINFO)) { @@ -338,14 +335,8 @@ MONO_SIG_HANDLER_FUNC (static, profiler_signal_handler) /* See the comment in mono_runtime_shutdown_stat_profiler (). */ if (mono_native_thread_id_get () == sampling_thread) { -#ifdef HAVE_CLOCK_NANOSLEEP - if (mono_profiler_get_sampling_mode () == MONO_PROFILER_STAT_MODE_PROCESS) { - InterlockedIncrement (&profiler_interrupt_signals_received); - return; - } -#endif - - g_error ("%s: Unexpected profiler signal received by the sampler thread", __func__); + InterlockedIncrement (&profiler_interrupt_signals_received); + return; } InterlockedIncrement (&profiler_signals_received); @@ -453,7 +444,7 @@ static void remove_signal_handler (int signo) { struct sigaction sa; - struct sigaction *saved_action = get_saved_signal_handler (signo); + struct sigaction *saved_action = get_saved_signal_handler (signo, TRUE); if (!saved_action) { sa.sa_handler = SIG_DFL; @@ -764,7 +755,7 @@ mono_runtime_shutdown_stat_profiler (void) { InterlockedWrite (&sampling_thread_running, 0); -#ifdef HAVE_CLOCK_NANOSLEEP +#ifndef PLATFORM_MACOSX /* * There is a slight problem when we're using CLOCK_PROCESS_CPUTIME_ID: If * we're shutting down and there's largely no activity in the process other @@ -777,28 +768,22 @@ mono_runtime_shutdown_stat_profiler (void) * sampling_thread_running upon an interrupt and return immediately if it's * zero. profiler_signal_handler () has a special case to ignore the signal * for the sampler thread. - * - * We do not need to do this on platforms where we use a regular sleep - * based on a monotonic clock. The sleep will return in a reasonable amount - * of time in those cases. */ - if (mono_profiler_get_sampling_mode () == MONO_PROFILER_STAT_MODE_PROCESS) { - MonoThreadInfo *info; + MonoThreadInfo *info; - // Did it shut down already? - if ((info = mono_thread_info_lookup (sampling_thread))) { - while (!InterlockedRead (&sampling_thread_exiting)) { - mono_threads_pthread_kill (info, profiler_signal); - mono_thread_info_usleep (10 * 1000 /* 10ms */); - } - - // Make sure info can be freed. - mono_hazard_pointer_clear (mono_hazard_pointer_get (), 1); + // Did it shut down already? + if ((info = mono_thread_info_lookup (sampling_thread))) { + while (!InterlockedRead (&sampling_thread_exiting)) { + mono_threads_pthread_kill (info, profiler_signal); + mono_thread_info_usleep (10 * 1000 /* 10ms */); } + + // Make sure info can be freed. + mono_hazard_pointer_clear (mono_hazard_pointer_get (), 1); } #endif - pthread_join (sampling_thread, NULL); + mono_native_thread_join (sampling_thread); /* * We can't safely remove the signal handler because we have no guarantee diff --git a/mono/mini/mini-runtime.c.REMOVED.git-id b/mono/mini/mini-runtime.c.REMOVED.git-id index 7429fe535f..bcd768236b 100644 --- a/mono/mini/mini-runtime.c.REMOVED.git-id +++ b/mono/mini/mini-runtime.c.REMOVED.git-id @@ -1 +1 @@ -c4ae82e0cbcbda75f4f963ba3f352e7d90dc4c14 \ No newline at end of file +8222f550fb89866ac7929f17f2da8d18cf191f4d \ No newline at end of file diff --git a/mono/mini/mini-trampolines.c b/mono/mini/mini-trampolines.c index 12e0fd9775..97197fe946 100644 --- a/mono/mini/mini-trampolines.c +++ b/mono/mini/mini-trampolines.c @@ -154,7 +154,7 @@ mono_create_static_rgctx_trampoline (MonoMethod *m, gpointer addr) * Either IMPL_METHOD or OUT_AOT_ADDR will be set on return. */ gpointer* -mini_resolve_imt_method (MonoVTable *vt, gpointer *vtable_slot, MonoMethod *imt_method, MonoMethod **impl_method, gpointer *out_aot_addr, gboolean *out_need_rgctx_tramp, MonoMethod **variant_iface) +mini_resolve_imt_method (MonoVTable *vt, gpointer *vtable_slot, MonoMethod *imt_method, MonoMethod **impl_method, gpointer *out_aot_addr, gboolean *out_need_rgctx_tramp, MonoMethod **variant_iface, MonoError *error) { MonoMethod *impl = NULL, *generic_virtual = NULL; gboolean lookup_aot, variance_used = FALSE, need_rgctx_tramp = FALSE; @@ -166,6 +166,7 @@ mini_resolve_imt_method (MonoVTable *vt, gpointer *vtable_slot, MonoMethod *imt_ g_assert (imt_slot < MONO_IMT_SIZE); + mono_error_init (error); /* This has to be variance aware since imt_method can be from an interface that vt->klass doesn't directly implement */ interface_offset = mono_class_interface_offset_with_variance (vt->klass, imt_method->klass, &variance_used); if (interface_offset < 0) @@ -188,7 +189,6 @@ mini_resolve_imt_method (MonoVTable *vt, gpointer *vtable_slot, MonoMethod *imt_ mono_vtable_build_imt_slot (vt, mono_method_get_imt_slot (imt_method)); if (imt_method->is_inflated && ((MonoMethodInflated*)imt_method)->context.method_inst) { - MonoError error; MonoGenericContext context = { NULL, NULL }; /* @@ -201,15 +201,14 @@ mini_resolve_imt_method (MonoVTable *vt, gpointer *vtable_slot, MonoMethod *imt_ if (impl->klass->generic_class) context.class_inst = impl->klass->generic_class->context.class_inst; context.method_inst = ((MonoMethodInflated*)imt_method)->context.method_inst; - impl = mono_class_inflate_generic_method_checked (impl, &context, &error); - g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */ + impl = mono_class_inflate_generic_method_checked (impl, &context, error); + mono_error_assert_ok (error); } else { - MonoError error; /* Avoid loading metadata or creating a generic vtable if possible */ if (lookup_aot && !vt->klass->valuetype) { - aot_addr = (guint8 *)mono_aot_get_method_from_vt_slot (mono_domain_get (), vt, interface_offset + mono_method_get_vtable_slot (imt_method), &error); - mono_error_raise_exception (&error); // FIXME: Don't raise here + aot_addr = (guint8 *)mono_aot_get_method_from_vt_slot (mono_domain_get (), vt, interface_offset + mono_method_get_vtable_slot (imt_method), error); + return_val_if_nok (error, NULL); } else { aot_addr = NULL; } @@ -367,12 +366,9 @@ mini_add_method_trampoline (MonoMethod *m, gpointer compiled_method, gboolean ad if (callee_array_helper) { add_static_rgctx_tramp = FALSE; - /* FIXME: ji->from_aot is not set for llvm methods */ - if (ji && (ji->from_aot || mono_aot_only)) { - /* In AOT mode, compiled_method points to one of the InternalArray methods in Array. */ - if (!mono_llvm_only && mono_method_needs_static_rgctx_invoke (jinfo_get_method (ji), TRUE)) - add_static_rgctx_tramp = TRUE; - } + /* In AOT mode, compiled_method points to one of the InternalArray methods in Array. */ + if (ji && !mono_llvm_only && mono_method_needs_static_rgctx_invoke (jinfo_get_method (ji), TRUE)) + add_static_rgctx_tramp = TRUE; } if (mono_llvm_only) @@ -562,7 +558,9 @@ common_call_trampoline (mgreg_t *regs, guint8 *code, MonoMethod *m, MonoVTable * need_rgctx_tramp = TRUE; } - vtable_slot = mini_resolve_imt_method (vt, vtable_slot, imt_method, &impl_method, &addr, &need_rgctx_tramp, &variant_iface); + vtable_slot = mini_resolve_imt_method (vt, vtable_slot, imt_method, &impl_method, &addr, &need_rgctx_tramp, &variant_iface, error); + return_val_if_nok (error, NULL); + /* This is the vcall slot which gets called through the IMT thunk */ vtable_slot_to_patch = vtable_slot; @@ -585,7 +583,6 @@ common_call_trampoline (mgreg_t *regs, guint8 *code, MonoMethod *m, MonoVTable * * return TRUE for methods used in IMT calls too. */ if (virtual_ && is_generic_method_definition (m)) { - MonoError error; MonoGenericContext context = { NULL, NULL }; MonoMethod *declaring; @@ -604,8 +601,8 @@ common_call_trampoline (mgreg_t *regs, guint8 *code, MonoMethod *m, MonoVTable * g_assert (generic_virtual->is_inflated); context.method_inst = ((MonoMethodInflated*)generic_virtual)->context.method_inst; - m = mono_class_inflate_generic_method_checked (declaring, &context, &error); - g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */ + m = mono_class_inflate_generic_method_checked (declaring, &context, error); + mono_error_assert_ok (error); /* FIXME: only do this if the method is sharable */ need_rgctx_tramp = TRUE; } else if ((context_used = mono_method_check_context_used (m))) { @@ -658,7 +655,6 @@ common_call_trampoline (mgreg_t *regs, guint8 *code, MonoMethod *m, MonoVTable * } if (method_inst || m->wrapper_type) { - MonoError error; MonoGenericContext context = { NULL, NULL }; if (m->is_inflated) @@ -672,8 +668,8 @@ common_call_trampoline (mgreg_t *regs, guint8 *code, MonoMethod *m, MonoVTable * context.class_inst = klass->generic_container->context.class_inst; context.method_inst = method_inst; - actual_method = mono_class_inflate_generic_method_checked (declaring, &context, &error); - g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */ + actual_method = mono_class_inflate_generic_method_checked (declaring, &context, error); + mono_error_assert_ok (error); } else { actual_method = mono_class_get_method_generic (klass, m); } @@ -800,7 +796,11 @@ common_call_trampoline (mgreg_t *regs, guint8 *code, MonoMethod *m, MonoVTable * */ no_patch = TRUE; } - +#if LLVM_API_VERSION > 100 + /* LLVM code doesn't make direct calls */ + if (ji && ji->from_llvm) + no_patch = TRUE; +#endif if (!no_patch && mono_method_same_domain (ji, target_ji)) mono_arch_patch_callsite ((guint8 *)ji->code_start, code, (guint8 *)addr); } @@ -876,7 +876,8 @@ mono_vcall_trampoline (mgreg_t *regs, guint8 *code, int slot, guint8 *tramp) /* Avoid loading metadata or creating a generic vtable if possible */ addr = mono_aot_get_method_from_vt_slot (mono_domain_get (), vt, slot, &error); - mono_error_raise_exception (&error); /* FIXME don't raise here */ + if (!is_ok (&error)) + goto leave; if (addr && !vt->klass->valuetype) { if (mono_domain_owns_vtable_slot (mono_domain_get (), vtable_slot)) *vtable_slot = addr; @@ -906,6 +907,7 @@ mono_vcall_trampoline (mgreg_t *regs, guint8 *code, int slot, guint8 *tramp) } res = common_call_trampoline (regs, code, m, vt, vtable_slot, &error); +leave: if (!mono_error_ok (&error)) { mono_error_set_pending_exception (&error); return NULL; @@ -1299,15 +1301,19 @@ gpointer mono_create_handler_block_trampoline (void) { static gpointer code; - if (code) { + + if (code) + return code; + + if (mono_aot_only) { + gpointer tmp = mono_aot_get_trampoline ("handler_block_trampoline"); + g_assert (tmp); mono_memory_barrier (); + code = tmp; return code; } - g_assert (!mono_aot_only); - mono_trampolines_lock (); - if (!code) { MonoTrampInfo *info; gpointer tmp; @@ -1504,14 +1510,16 @@ mono_create_jit_trampoline (MonoDomain *domain, MonoMethod *method, MonoError *e mono_error_init (error); if (mono_aot_only) { + if (mono_llvm_only && method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED) + method = mono_marshal_get_synchronized_wrapper (method); + /* Avoid creating trampolines if possible */ gpointer code = mono_jit_find_compiled_method (domain, method); if (code) return code; if (mono_llvm_only) { - if (method->wrapper_type == MONO_WRAPPER_PROXY_ISINST || method->wrapper_type == MONO_WRAPPER_LDFLD_REMOTE || - method->wrapper_type == MONO_WRAPPER_STFLD_REMOTE) + if (method->wrapper_type == MONO_WRAPPER_PROXY_ISINST) /* These wrappers are not generated */ return method_not_found; /* Methods are lazily initialized on first call, so this can't lead recursion */ diff --git a/mono/mini/mini-unwind.h b/mono/mini/mini-unwind.h index ab690bf480..3d14e9cde7 100644 --- a/mono/mini/mini-unwind.h +++ b/mono/mini/mini-unwind.h @@ -182,7 +182,7 @@ typedef struct { } MonoLLVMFDEInfo; void -mono_unwind_decode_llvm_mono_fde (guint8 *fde, int fde_len, guint8 *cie, guint8 *code, MonoLLVMFDEInfo *res); +mono_unwind_decode_llvm_mono_fde (guint8 *fde, int fde_len, guint8 *cie, guint8 *code, MonoLLVMFDEInfo *res) MONO_LLVM_INTERNAL; GSList* mono_unwind_get_cie_program (void); diff --git a/mono/mini/mini-windows-dllmain.c b/mono/mini/mini-windows-dllmain.c new file mode 100644 index 0000000000..887a6a13b2 --- /dev/null +++ b/mono/mini/mini-windows-dllmain.c @@ -0,0 +1,40 @@ +/* + * mini-windows-dllmain.c: DllMain entry point. + * + * (C) 2002-2003 Ximian, Inc. + * (C) 2003-2006 Novell, Inc. + * Licensed under the MIT license. See LICENSE file in the project root for full license information. + */ + +#include +#include +#include +#include +#include "mini.h" + +#ifdef HOST_WIN32 +#include + +BOOL APIENTRY DllMain (HMODULE module_handle, DWORD reason, LPVOID reserved) +{ + if (!mono_gc_dllmain (module_handle, reason, reserved)) + return FALSE; + + switch (reason) + { + case DLL_PROCESS_ATTACH: + mono_install_runtime_load (mini_init); + break; + case DLL_PROCESS_DETACH: + if (coree_module_handle) + FreeLibrary (coree_module_handle); + break; + case DLL_THREAD_DETACH: + mono_thread_info_detach (); + break; + + } + return TRUE; +} +#endif + diff --git a/mono/mini/mini-x86.c.REMOVED.git-id b/mono/mini/mini-x86.c.REMOVED.git-id index 216bd0b682..74e6ffee02 100644 --- a/mono/mini/mini-x86.c.REMOVED.git-id +++ b/mono/mini/mini-x86.c.REMOVED.git-id @@ -1 +1 @@ -6a3a6c0aa4e1c0a792e0d4bcc355138b97d67f68 \ No newline at end of file +288af652434bf9ffc25e4ad0893d5087409de286 \ No newline at end of file diff --git a/mono/mini/mini-x86.h b/mono/mini/mini-x86.h index 4150cdf60d..b70d836c2a 100644 --- a/mono/mini/mini-x86.h +++ b/mono/mini/mini-x86.h @@ -315,6 +315,7 @@ typedef struct { /* Only if storage == ArgValuetypeInReg */ ArgStorage pair_storage [2]; gint8 pair_regs [2]; + guint8 pass_empty_struct : 1; // Set in scenarios when empty structs needs to be represented as argument. } ArgInfo; typedef struct { diff --git a/mono/mini/mini.c.REMOVED.git-id b/mono/mini/mini.c.REMOVED.git-id index c0be0d5631..5aa7ec09f7 100644 --- a/mono/mini/mini.c.REMOVED.git-id +++ b/mono/mini/mini.c.REMOVED.git-id @@ -1 +1 @@ -a76acc17e46cbc10c09f1cf6671e933495786600 \ No newline at end of file +750410441af8afda4ad292c84405f3e195b47c24 \ No newline at end of file diff --git a/mono/mini/mini.h.REMOVED.git-id b/mono/mini/mini.h.REMOVED.git-id index 27c5fdbcdf..5ad3353832 100644 --- a/mono/mini/mini.h.REMOVED.git-id +++ b/mono/mini/mini.h.REMOVED.git-id @@ -1 +1 @@ -d1f83c4641b21eb86ef3a9291f1af35cf6f78be4 \ No newline at end of file +7aef90d17eede287da97280c621552b83e8daa49 \ No newline at end of file diff --git a/mono/mini/patch-info.h b/mono/mini/patch-info.h index e6635a4b49..a557003557 100644 --- a/mono/mini/patch-info.h +++ b/mono/mini/patch-info.h @@ -57,3 +57,4 @@ PATCH_INFO(AOT_JIT_INFO, "aot_jit_info") PATCH_INFO(GC_NURSERY_BITS, "gc_nursery_bits") PATCH_INFO(GSHAREDVT_IN_WRAPPER, "gsharedvt_in_wrapper") PATCH_INFO(ICALL_ADDR_CALL, "icall_addr_call") +PATCH_INFO(GET_TLS_TRAMP, "get_tls_tramp") diff --git a/mono/mini/seq-points.c b/mono/mini/seq-points.c index fd9cc01200..8ff2e1e3ec 100644 --- a/mono/mini/seq-points.c +++ b/mono/mini/seq-points.c @@ -12,31 +12,88 @@ #include "seq-points.h" static void -collect_pred_seq_points (MonoBasicBlock *bb, MonoInst *ins, GSList **next, int depth) +insert_pred_seq_point (MonoInst *last_seq_ins, MonoInst *ins, GSList **next) { - int i; - MonoBasicBlock *in_bb; GSList *l; + int src_index = last_seq_ins->backend.size; + int dst_index = ins->backend.size; - for (i = 0; i < bb->in_count; ++i) { - in_bb = bb->in_bb [i]; + /* bb->in_bb might contain duplicates */ + for (l = next [src_index]; l; l = l->next) + if (GPOINTER_TO_UINT (l->data) == dst_index) + break; + if (!l) + next [src_index] = g_slist_append (next [src_index], GUINT_TO_POINTER (dst_index)); +} - if (in_bb->last_seq_point) { - int src_index = in_bb->last_seq_point->backend.size; - int dst_index = ins->backend.size; +static void +recursively_make_pred_seq_points (MonoCompile *cfg, MonoBasicBlock *bb) +{ + const gpointer MONO_SEQ_SEEN_LOOP = GINT_TO_POINTER(-1); - /* bb->in_bb might contain duplicates */ - for (l = next [src_index]; l; l = l->next) - if (GPOINTER_TO_UINT (l->data) == dst_index) - break; - if (!l) - next [src_index] = g_slist_append (next [src_index], GUINT_TO_POINTER (dst_index)); - } else { - /* Have to look at its predecessors */ - if (depth < 5) - collect_pred_seq_points (in_bb, ins, next, depth + 1); + GArray *predecessors = g_array_new (FALSE, TRUE, sizeof (gpointer)); + GHashTable *seen = g_hash_table_new_full (g_direct_hash, NULL, NULL, NULL); + + // Insert/remove sentinel into the memoize table to detect loops containing bb + bb->pred_seq_points = MONO_SEQ_SEEN_LOOP; + + for (int i = 0; i < bb->in_count; ++i) { + MonoBasicBlock *in_bb = bb->in_bb [i]; + + // This bb has the last seq point, append it and continue + if (in_bb->last_seq_point != NULL) { + predecessors = g_array_append_val (predecessors, in_bb->last_seq_point); + continue; } + + // We've looped or handled this before, exit early. + // No last sequence points to find. + if (in_bb->pred_seq_points == MONO_SEQ_SEEN_LOOP) + continue; + + // Take sequence points from incoming basic blocks + + if (in_bb == cfg->bb_entry) + continue; + + if (in_bb->pred_seq_points == NULL) + recursively_make_pred_seq_points (cfg, in_bb); + + // Union sequence points with incoming bb's + for (int i=0; i < in_bb->num_pred_seq_points; i++) { + if (!g_hash_table_lookup (seen, in_bb->pred_seq_points [i])) { + g_array_append_val (predecessors, in_bb->pred_seq_points [i]); + g_hash_table_insert (seen, in_bb->pred_seq_points [i], (gpointer)&MONO_SEQ_SEEN_LOOP); + } + } + // predecessors = g_array_append_vals (predecessors, in_bb->pred_seq_points, in_bb->num_pred_seq_points); } + + g_hash_table_destroy (seen); + + if (predecessors->len != 0) { + bb->pred_seq_points = (MonoInst **)mono_mempool_alloc0 (cfg->mempool, sizeof (MonoInst *) * predecessors->len); + bb->num_pred_seq_points = predecessors->len; + + for (int newer = 0; newer < bb->num_pred_seq_points; newer++) { + bb->pred_seq_points [newer] = g_array_index(predecessors, gpointer, newer); + } + } + + g_free (predecessors); +} + +static void +collect_pred_seq_points (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *ins, GSList **next) +{ + // Doesn't have a last sequence point, must find from incoming basic blocks + if (bb->pred_seq_points == NULL && bb != cfg->bb_entry) + recursively_make_pred_seq_points (cfg, bb); + + for (int i = 0; i < bb->num_pred_seq_points; i++) + insert_pred_seq_point (bb->pred_seq_points [i], ins, next); + + return; } void @@ -93,7 +150,7 @@ mono_save_seq_point_info (MonoCompile *cfg) next [last->backend.size] = g_slist_append (next [last->backend.size], GUINT_TO_POINTER (ins->backend.size)); } else { /* Link with the last bb in the previous bblocks */ - collect_pred_seq_points (bb, ins, next, 0); + collect_pred_seq_points (cfg, bb, ins, next); } last = ins; diff --git a/mono/mini/tasklets.c b/mono/mini/tasklets.c index 9457633baf..7d035aa3b2 100644 --- a/mono/mini/tasklets.c +++ b/mono/mini/tasklets.c @@ -54,6 +54,7 @@ continuation_mark_frame (MonoContinuation *cont) /* get to the frame that called Mark () */ memset (&rji, 0, sizeof (rji)); + memset (&ctx, 0, sizeof (ctx)); do { ji = mono_find_jit_info (cont->domain, jit_tls, &rji, NULL, &ctx, &new_ctx, NULL, &lmf, NULL, NULL); if (!ji || ji == (gpointer)-1) { @@ -149,6 +150,57 @@ void mono_tasklets_cleanup (void) { } +#else +static +void continuations_not_supported (void) +{ + mono_set_pending_exception (mono_get_exception_not_implemented ("Tasklets are not implemented on this platform.")); +} + +static void* +continuation_alloc (void) +{ + continuations_not_supported (); + return NULL; +} + +static void +continuation_free (MonoContinuation *cont) +{ + continuations_not_supported (); +} + +static MonoException* +continuation_mark_frame (MonoContinuation *cont) +{ + continuations_not_supported (); + return NULL; +} + +static int +continuation_store (MonoContinuation *cont, int state, MonoException **e) +{ + continuations_not_supported (); + return 0; +} + +static MonoException* +continuation_restore (MonoContinuation *cont, int state) +{ + continuations_not_supported (); + return NULL; +} + +void +mono_tasklets_init(void) +{ + mono_add_internal_call ("Mono.Tasklets.Continuation::alloc", continuation_alloc); + mono_add_internal_call ("Mono.Tasklets.Continuation::free", continuation_free); + mono_add_internal_call ("Mono.Tasklets.Continuation::mark", continuation_mark_frame); + mono_add_internal_call ("Mono.Tasklets.Continuation::store", continuation_store); + mono_add_internal_call ("Mono.Tasklets.Continuation::restore", continuation_restore); + +} #endif diff --git a/mono/mini/test_op_il_seq_point.sh b/mono/mini/test_op_il_seq_point.sh index b89cc887ff..ee235f5c73 100755 --- a/mono/mini/test_op_il_seq_point.sh +++ b/mono/mini/test_op_il_seq_point.sh @@ -1,7 +1,8 @@ #!/bin/bash -TEST_FILE=$1 -USE_AOT=$2 +DEFAULT_PROFILE=$1 +TEST_FILE=$2 +USE_AOT=$3 TMP_FILE_PREFIX=$(basename $0).tmp BASEDIR=$(dirname $0) @@ -11,13 +12,13 @@ case "$(uname -s)" in *) PLATFORM_PATH_SEPARATOR=':';; esac -MONO_PATH=$BASEDIR/../../mcs/class/lib/net_4_x$PLATFORM_PATH_SEPARATOR$BASEDIR +MONO_PATH=$BASEDIR/../../mcs/class/lib/$DEFAULT_PROFILE$PLATFORM_PATH_SEPARATOR$BASEDIR RUNTIME=$BASEDIR/../../runtime/mono-wrapper trap "rm -rf ${TMP_FILE_PREFIX}*" EXIT tmp_file () { - mktemp ./${TMP_FILE_PREFIX}XXXX + mktemp ./${TMP_FILE_PREFIX}XXXXXX } clean_aot () { diff --git a/mono/mini/tramp-amd64-gsharedvt.c b/mono/mini/tramp-amd64-gsharedvt.c index 94289f9d57..f5600adbde 100644 --- a/mono/mini/tramp-amd64-gsharedvt.c +++ b/mono/mini/tramp-amd64-gsharedvt.c @@ -5,6 +5,7 @@ * Zoltan Varga * Rodrigo Kumpera * Andi McClure + * Johan Lorensson * * Copyright 2015 Xamarin, Inc (http://www.xamarin.com) * Licensed under the MIT license. See LICENSE file in the project root for full license information. @@ -145,7 +146,6 @@ mono_arch_get_gsharedvt_arg_trampoline (MonoDomain *domain, gpointer arg, gpoint return start; } - gpointer mono_arch_get_gsharedvt_trampoline (MonoTrampInfo **info, gboolean aot) { @@ -245,8 +245,8 @@ mono_arch_get_gsharedvt_trampoline (MonoTrampInfo **info, gboolean aot) - - + + */ /* Call start_gsharedvt_call () */ @@ -263,7 +263,23 @@ mono_arch_get_gsharedvt_trampoline (MonoTrampInfo **info, gboolean aot) if (aot) { code = mono_arch_emit_load_aotconst (buf, code, &ji, MONO_PATCH_INFO_JIT_ICALL_ADDR, "mono_amd64_start_gsharedvt_call"); - amd64_call_reg (code, AMD64_R11); + #ifdef TARGET_WIN32 + /* Since we are doing a call as part of setting up stackframe, the reserved shadow stack used by Windows platform is allocated up in + the callee stack area but currently the callee reg area is in between. Windows calling convention dictates that room is made on stack where + callee can save any parameters passed in registers. Since Windows x64 calling convention + uses 4 registers for the first 4 parameters, stack needs to be adjusted before making the call. + NOTE, Windows calling convention assumes that space for all registers have been reserved, regardless + of the number of function parameters actually used. + */ + int shadow_reg_size = 0; + + shadow_reg_size = ALIGN_TO (PARAM_REGS * sizeof(gpointer), MONO_ARCH_FRAME_ALIGNMENT); + amd64_alu_reg_imm (code, X86_SUB, AMD64_RSP, shadow_reg_size); + amd64_call_reg (code, AMD64_R11); + amd64_alu_reg_imm (code, X86_ADD, AMD64_RSP, shadow_reg_size); + #else + amd64_call_reg (code, AMD64_R11); + #endif } else { g_error ("no aot"); } @@ -302,13 +318,14 @@ mono_arch_get_gsharedvt_trampoline (MonoTrampInfo **info, gboolean aot) */ /* Load vret_slot */ - amd64_mov_reg_membase (code, AMD64_RDI, AMD64_R10, MONO_STRUCT_OFFSET (GSharedVtCallInfo, vret_slot), 4); - amd64_alu_reg_imm (code, X86_SUB, AMD64_RDI, n_arg_regs + n_arg_fregs); - amd64_shift_reg_imm (code, X86_SHL, AMD64_RDI, 3); + /* Use first input parameter register as scratch since it is volatile on all platforms */ + amd64_mov_reg_membase (code, MONO_AMD64_ARG_REG1, AMD64_R10, MONO_STRUCT_OFFSET (GSharedVtCallInfo, vret_slot), 4); + amd64_alu_reg_imm (code, X86_SUB, MONO_AMD64_ARG_REG1, n_arg_regs + n_arg_fregs); + amd64_shift_reg_imm (code, X86_SHL, MONO_AMD64_ARG_REG1, 3); /* vret address is RBP - (framesize - caller_reg_area_offset) */ amd64_mov_reg_reg (code, AMD64_R11, AMD64_RSP, sizeof(mgreg_t)); - amd64_alu_reg_reg (code, X86_ADD, AMD64_R11, AMD64_RDI); + amd64_alu_reg_reg (code, X86_ADD, AMD64_R11, MONO_AMD64_ARG_REG1); /* Load ret marshal type */ /* Load vret address in R11 */ @@ -366,10 +383,10 @@ mono_arch_get_gsharedvt_trampoline (MonoTrampInfo **info, gboolean aot) /* Address to write return to is in the original value of the register specified by vret_arg_reg. - This will be either RSI or RDI depending on whether this is a static call. + This will be either RSI, RDI (System V) or RCX, RDX (Windows) depending on whether this is a static call. Its location: We alloc 'framesize' bytes below RBP to save regs, info and rgctx. RSP = RBP - framesize - We store rdi at RSP + caller_reg_area_offset + slot_index_of (register) * 8. + We store RDI (System V), RCX (Windows) at RSP + caller_reg_area_offset + slot_index_of (register) * 8. address: RBP - framesize + caller_reg_area_offset + 8*slot */ diff --git a/mono/mini/tramp-amd64.c b/mono/mini/tramp-amd64.c index d9737fb8c5..cf769a9e53 100644 --- a/mono/mini/tramp-amd64.c +++ b/mono/mini/tramp-amd64.c @@ -757,49 +757,72 @@ mono_arch_invalidate_method (MonoJitInfo *ji, void *func, gpointer func_arg) amd64_call_reg (code, AMD64_R11); } - -static void -handler_block_trampoline_helper (gpointer *ptr) +gpointer +mono_amd64_handler_block_trampoline_helper (void) { MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id); - *ptr = jit_tls->handler_block_return_address; + return jit_tls->handler_block_return_address; } gpointer mono_arch_create_handler_block_trampoline (MonoTrampInfo **info, gboolean aot) { - guint8 *tramp = mono_get_trampoline_code (MONO_TRAMPOLINE_HANDLER_BLOCK_GUARD); guint8 *code, *buf; int tramp_size = 64; MonoJumpInfo *ji = NULL; GSList *unwind_ops; - g_assert (!aot); - code = buf = (guint8 *)mono_global_codeman_reserve (tramp_size); unwind_ops = mono_arch_get_cie_program (); /* - This trampoline restore the call chain of the handler block then jumps into the code that deals with it. - */ - if (mono_get_jit_tls_offset () != -1) { - code = mono_amd64_emit_tls_get (code, MONO_AMD64_ARG_REG1, mono_get_jit_tls_offset ()); - amd64_mov_reg_membase (code, MONO_AMD64_ARG_REG1, MONO_AMD64_ARG_REG1, MONO_STRUCT_OFFSET (MonoJitTlsData, handler_block_return_address), 8); - /* Simulate a call */ - amd64_push_reg (code, AMD64_RAX); - mono_add_unwind_op_def_cfa_offset (unwind_ops, code, buf, 16); - amd64_jump_code (code, tramp); + * This trampoline restore the call chain of the handler block then jumps into the code that deals with it. + * We get here from the ret emitted by CEE_ENDFINALLY. + * The stack is misaligned. + */ + /* Align the stack before the call to mono_amd64_handler_block_trampoline_helper() */ +#ifdef TARGET_WIN32 + /* Also make room for the "register parameter stack area" as specified by the Windows x64 ABI (4 64-bit registers) */ + amd64_alu_reg_imm (code, X86_SUB, AMD64_RSP, 8 + 4 * 8); +#else + amd64_alu_reg_imm (code, X86_SUB, AMD64_RSP, 8); +#endif + if (aot) { + code = mono_arch_emit_load_aotconst (buf, code, &ji, MONO_PATCH_INFO_JIT_ICALL_ADDR, "mono_amd64_handler_block_trampoline_helper"); + amd64_call_reg (code, AMD64_R11); } else { - /*Slow path uses a c helper*/ - amd64_mov_reg_reg (code, MONO_AMD64_ARG_REG1, AMD64_RSP, 8); - amd64_mov_reg_imm (code, AMD64_RAX, tramp); - amd64_push_reg (code, AMD64_RAX); - mono_add_unwind_op_def_cfa_offset (unwind_ops, code, buf, 16); - amd64_push_reg (code, AMD64_RAX); - mono_add_unwind_op_def_cfa_offset (unwind_ops, code, buf, 24); - amd64_jump_code (code, handler_block_trampoline_helper); + amd64_mov_reg_imm (code, AMD64_RAX, mono_amd64_handler_block_trampoline_helper); + amd64_call_reg (code, AMD64_RAX); } + /* Undo stack alignment */ +#ifdef TARGET_WIN32 + amd64_alu_reg_imm (code, X86_ADD, AMD64_RSP, 8 + 4 * 8); +#else + amd64_alu_reg_imm (code, X86_ADD, AMD64_RSP, 8); +#endif + /* Save the result to the stack */ + amd64_push_reg (code, AMD64_RAX); +#ifdef TARGET_WIN32 + /* Make room for the "register parameter stack area" as specified by the Windows x64 ABI (4 64-bit registers) */ + amd64_alu_reg_imm (code, X86_SUB, AMD64_RSP, 4 * 8); +#endif + if (aot) { + char *name = g_strdup_printf ("trampoline_func_%d", MONO_TRAMPOLINE_HANDLER_BLOCK_GUARD); + code = mono_arch_emit_load_aotconst (buf, code, &ji, MONO_PATCH_INFO_JIT_ICALL_ADDR, name); + amd64_mov_reg_reg (code, AMD64_RAX, AMD64_R11, 8); + } else { + amd64_mov_reg_imm (code, AMD64_RAX, mono_get_trampoline_func (MONO_TRAMPOLINE_HANDLER_BLOCK_GUARD)); + } + /* The stack is aligned */ + amd64_call_reg (code, AMD64_RAX); +#ifdef TARGET_WIN32 + amd64_alu_reg_imm (code, X86_ADD, AMD64_RSP, 4 * 8); +#endif + /* Load return address */ + amd64_pop_reg (code, AMD64_RAX); + /* The stack is misaligned, thats what the code we branch to expects */ + amd64_jump_reg (code, AMD64_RAX); mono_arch_flush_icache (buf, code - buf); mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_HELPER, NULL); diff --git a/mono/mini/tramp-arm.c b/mono/mini/tramp-arm.c index d24ddf4a72..747163b176 100644 --- a/mono/mini/tramp-arm.c +++ b/mono/mini/tramp-arm.c @@ -778,15 +778,27 @@ mono_arch_create_sdb_trampoline (gboolean single_step, MonoTrampInfo **info, gbo ARM_MOV_REG_REG (code, ARMREG_R0, ARMREG_FP); /* call */ - // FIXME: AOT - ARM_LDR_IMM (code, ARMREG_IP, ARMREG_PC, 0); - ARM_B (code, 0); - if (single_step) - *(gpointer*)code = debugger_agent_single_step_from_context; - else - *(gpointer*)code = debugger_agent_breakpoint_from_context; - code += 4; - ARM_BLX_REG (code, ARMREG_IP); + if (aot) { + if (single_step) + ji = mono_patch_info_list_prepend (ji, code - buf, MONO_PATCH_INFO_JIT_ICALL_ADDR, "debugger_agent_single_step_from_context"); + else + ji = mono_patch_info_list_prepend (ji, code - buf, MONO_PATCH_INFO_JIT_ICALL_ADDR, "debugger_agent_breakpoint_from_context"); + ARM_LDR_IMM (code, ARMREG_IP, ARMREG_PC, 0); + ARM_B (code, 0); + *(gpointer*)code = NULL; + code += 4; + ARM_LDR_REG_REG (code, ARMREG_IP, ARMREG_PC, ARMREG_IP); + ARM_BLX_REG (code, ARMREG_IP); + } else { + ARM_LDR_IMM (code, ARMREG_IP, ARMREG_PC, 0); + ARM_B (code, 0); + if (single_step) + *(gpointer*)code = debugger_agent_single_step_from_context; + else + *(gpointer*)code = debugger_agent_breakpoint_from_context; + code += 4; + ARM_BLX_REG (code, ARMREG_IP); + } /* we're back; save ctx.eip and ctx.esp into the corresponding regs slots. */ ARM_LDR_IMM (code, ARMREG_R0, ARMREG_FP, MONO_STRUCT_OFFSET (MonoContext, pc)); @@ -864,13 +876,8 @@ mono_arch_get_call_target (guint8 *code) { guint32 ins = ((guint32*)(gpointer)code) [-1]; -#if MONOTOUCH /* Should be a 'bl' or a 'b' */ if (((ins >> 25) & 0x7) == 0x5) { -#else - /* Should be a 'bl' */ - if ((((ins >> 25) & 0x7) == 0x5) && (((ins >> 24) & 0x1) == 0x1)) { -#endif gint32 disp = ((((gint32)ins) & 0xffffff) << 8) >> 8; guint8 *target = code - 4 + 8 + (disp * 4); diff --git a/mono/mini/unwind.c b/mono/mini/unwind.c index ef3c65a7f2..a282429240 100644 --- a/mono/mini/unwind.c +++ b/mono/mini/unwind.c @@ -375,13 +375,15 @@ mono_unwind_ops_encode_full (GSList *unwind_ops, guint32 *out_len, gboolean enab while (op->when > loc) { if (op->when - loc > 65536) { *p ++ = DW_CFA_advance_loc4; - *(guint32*)p = (guint32)(op->when - loc); + guint32 v = (guint32)(op->when - loc); + memcpy (p, &v, 4); g_assert (read32 (p) == (guint32)(op->when - loc)); p += 4; loc = op->when; } else if (op->when - loc > 256) { *p ++ = DW_CFA_advance_loc2; - *(guint16*)p = (guint16)(op->when - loc); + guint16 v = (guint16)(op->when - loc); + memcpy (p, &v, 2); g_assert (read16 (p) == (guint32)(op->when - loc)); p += 2; loc = op->when; diff --git a/mono/mini/version.h b/mono/mini/version.h index 595d0c00b8..43fb80b19e 100644 --- a/mono/mini/version.h +++ b/mono/mini/version.h @@ -1 +1 @@ -#define FULL_VERSION "Stable 4.6.2.6/db69866" +#define FULL_VERSION "Stable 4.8.0.309/dea12ad" diff --git a/mono/profiler/Makefile.am b/mono/profiler/Makefile.am index 3d7eb62e40..4f6c4acb20 100644 --- a/mono/profiler/Makefile.am +++ b/mono/profiler/Makefile.am @@ -73,10 +73,10 @@ libmono_profiler_iomap_la_LDFLAGS = $(prof_ldflags) libmono_profiler_iomap_static_la_SOURCES = mono-profiler-iomap.c libmono_profiler_iomap_static_la_LDFLAGS = -static -libmono_profiler_log_la_SOURCES = proflog.c +libmono_profiler_log_la_SOURCES = mono-profiler-log.c libmono_profiler_log_la_LIBADD = $(monodir)/mono/mini/$(LIBMONO_LA) $(GLIB_LIBS) $(Z_LIBS) libmono_profiler_log_la_LDFLAGS = $(prof_ldflags) -libmono_profiler_log_static_la_SOURCES = proflog.c +libmono_profiler_log_static_la_SOURCES = mono-profiler-log.c libmono_profiler_log_static_la_LDFLAGS = -static if HAVE_VTUNE @@ -88,7 +88,7 @@ libmono_profiler_vtune_static_la_SOURCES = mono-profiler-vtune.c libmono_profiler_vtune_static_la_LDFLAGS = -static endif -mprof_report_SOURCES = decode.c +mprof_report_SOURCES = mprof-report.c mprof_report_LDADD = $(Z_LIBS) $(GLIB_LIBS) $(LIBICONV) PLOG_TESTS_SRC=test-alloc.cs test-busy.cs test-monitor.cs test-excleave.cs \ @@ -110,6 +110,7 @@ testlog: $(PLOG_TESTS) check-local: $(check_targets) -EXTRA_DIST=utils.c utils.h proflog.h \ - $(PLOG_TESTS_SRC) ptestrunner.pl \ +EXTRA_DIST=mono-profiler-log.h \ + $(PLOG_TESTS_SRC) \ + ptestrunner.pl \ $(suppression_DATA) diff --git a/mono/profiler/Makefile.in b/mono/profiler/Makefile.in index 853cb3ce88..8486b35bbb 100644 --- a/mono/profiler/Makefile.in +++ b/mono/profiler/Makefile.in @@ -180,7 +180,7 @@ libmono_profiler_iomap_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ @DISABLE_LIBRARIES_FALSE@@DISABLE_PROFILER_FALSE@@HOST_WIN32_FALSE@am_libmono_profiler_iomap_la_rpath = -rpath \ @DISABLE_LIBRARIES_FALSE@@DISABLE_PROFILER_FALSE@@HOST_WIN32_FALSE@ $(libdir) libmono_profiler_log_static_la_LIBADD = -am_libmono_profiler_log_static_la_OBJECTS = proflog.lo +am_libmono_profiler_log_static_la_OBJECTS = mono-profiler-log.lo libmono_profiler_log_static_la_OBJECTS = \ $(am_libmono_profiler_log_static_la_OBJECTS) libmono_profiler_log_static_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ @@ -192,7 +192,7 @@ libmono_profiler_log_static_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ libmono_profiler_log_la_DEPENDENCIES = \ $(monodir)/mono/mini/$(LIBMONO_LA) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) -am_libmono_profiler_log_la_OBJECTS = proflog.lo +am_libmono_profiler_log_la_OBJECTS = mono-profiler-log.lo libmono_profiler_log_la_OBJECTS = \ $(am_libmono_profiler_log_la_OBJECTS) libmono_profiler_log_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ @@ -228,7 +228,7 @@ libmono_profiler_vtune_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ @DISABLE_LIBRARIES_FALSE@@DISABLE_PROFILER_FALSE@@HAVE_VTUNE_TRUE@@HOST_WIN32_FALSE@am_libmono_profiler_vtune_la_rpath = -rpath \ @DISABLE_LIBRARIES_FALSE@@DISABLE_PROFILER_FALSE@@HAVE_VTUNE_TRUE@@HOST_WIN32_FALSE@ $(libdir) PROGRAMS = $(bin_PROGRAMS) -am_mprof_report_OBJECTS = decode.$(OBJEXT) +am_mprof_report_OBJECTS = mprof-report.$(OBJEXT) mprof_report_OBJECTS = $(am_mprof_report_OBJECTS) mprof_report_DEPENDENCIES = $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) @@ -308,6 +308,8 @@ DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AOT_BUILD_FLAGS = @AOT_BUILD_FLAGS@ +AOT_RUN_FLAGS = @AOT_RUN_FLAGS@ API_VER = @API_VER@ AR = @AR@ AS = @AS@ @@ -316,6 +318,11 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOEHM_DEFINES = @BOEHM_DEFINES@ +BTLS_ARCH = @BTLS_ARCH@ +BTLS_CFLAGS = @BTLS_CFLAGS@ +BTLS_CMAKE_ARGS = @BTLS_CMAKE_ARGS@ +BTLS_PLATFORM = @BTLS_PLATFORM@ +BTLS_ROOT = @BTLS_ROOT@ BUILD_EXEEXT = @BUILD_EXEEXT@ CC = @CC@ CCAS = @CCAS@ @@ -325,6 +332,7 @@ CCDEPMODE = @CCDEPMODE@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMAKE = @CMAKE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ @@ -345,7 +353,6 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_PERF_EVENTS = @ENABLE_PERF_EVENTS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDKX11 = @GDKX11@ @@ -360,10 +367,12 @@ HAVE_MSGFMT = @HAVE_MSGFMT@ HOST_CC = @HOST_CC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MOBILE_STATIC = @INSTALL_MOBILE_STATIC@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTL = @INTL@ +INVARIANT_AOT_OPTIONS = @INVARIANT_AOT_OPTIONS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBC = @LIBC@ @@ -410,6 +419,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ +PLATFORM_AOT_SUFFIX = @PLATFORM_AOT_SUFFIX@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -419,6 +429,7 @@ SHELL = @SHELL@ SQLITE = @SQLITE@ SQLITE3 = @SQLITE3@ STRIP = @STRIP@ +TEST_PROFILE = @TEST_PROFILE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VTUNE_CFLAGS = @VTUNE_CFLAGS@ @@ -549,10 +560,10 @@ libmono_profiler_iomap_la_LIBADD = $(monodir)/mono/mini/$(LIBMONO_LA) $(GLIB_LIB libmono_profiler_iomap_la_LDFLAGS = $(prof_ldflags) libmono_profiler_iomap_static_la_SOURCES = mono-profiler-iomap.c libmono_profiler_iomap_static_la_LDFLAGS = -static -libmono_profiler_log_la_SOURCES = proflog.c +libmono_profiler_log_la_SOURCES = mono-profiler-log.c libmono_profiler_log_la_LIBADD = $(monodir)/mono/mini/$(LIBMONO_LA) $(GLIB_LIBS) $(Z_LIBS) libmono_profiler_log_la_LDFLAGS = $(prof_ldflags) -libmono_profiler_log_static_la_SOURCES = proflog.c +libmono_profiler_log_static_la_SOURCES = mono-profiler-log.c libmono_profiler_log_static_la_LDFLAGS = -static @HAVE_VTUNE_TRUE@libmono_profiler_vtune_la_SOURCES = mono-profiler-vtune.c @HAVE_VTUNE_TRUE@libmono_profiler_vtune_la_CFLAGS = $(VTUNE_CFLAGS) @@ -560,7 +571,7 @@ libmono_profiler_log_static_la_LDFLAGS = -static @HAVE_VTUNE_TRUE@libmono_profiler_vtune_la_LDFLAGS = $(prof_ldflags) @HAVE_VTUNE_TRUE@libmono_profiler_vtune_static_la_SOURCES = mono-profiler-vtune.c @HAVE_VTUNE_TRUE@libmono_profiler_vtune_static_la_LDFLAGS = -static -mprof_report_SOURCES = decode.c +mprof_report_SOURCES = mprof-report.c mprof_report_LDADD = $(Z_LIBS) $(GLIB_LIBS) $(LIBICONV) PLOG_TESTS_SRC = test-alloc.cs test-busy.cs test-monitor.cs test-excleave.cs \ test-heapshot.cs test-traces.cs @@ -570,8 +581,9 @@ CLASS = $(mcs_topdir)/class/lib/$(DEFAULT_PROFILE) with_mono_path = MONO_PATH=$(CLASS) RUNTIME = $(with_mono_path) $(top_builddir)/runtime/mono-wrapper MCS = $(RUNTIME) $(mcs_topdir)/class/lib/build/mcs.exe -unsafe -nowarn:0162 -nowarn:0168 -nowarn:0219 -debug -EXTRA_DIST = utils.c utils.h proflog.h \ - $(PLOG_TESTS_SRC) ptestrunner.pl \ +EXTRA_DIST = mono-profiler-log.h \ + $(PLOG_TESTS_SRC) \ + ptestrunner.pl \ $(suppression_DATA) all: all-am @@ -727,12 +739,12 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/decode.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmono_profiler_vtune_la-mono-profiler-vtune.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mono-profiler-aot.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mono-profiler-iomap.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mono-profiler-log.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mono-profiler-vtune.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proflog.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mprof-report.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ diff --git a/mono/profiler/decode.c.REMOVED.git-id b/mono/profiler/decode.c.REMOVED.git-id deleted file mode 100644 index b2162e6edd..0000000000 --- a/mono/profiler/decode.c.REMOVED.git-id +++ /dev/null @@ -1 +0,0 @@ -b213528caaa35b55a02a43f0c8b2329a40eeab75 \ No newline at end of file diff --git a/mono/profiler/mono-profiler-log.c.REMOVED.git-id b/mono/profiler/mono-profiler-log.c.REMOVED.git-id new file mode 100644 index 0000000000..3804f4c486 --- /dev/null +++ b/mono/profiler/mono-profiler-log.c.REMOVED.git-id @@ -0,0 +1 @@ +b32d48ef2ce95d967e483b9952e3a5a00d884591 \ No newline at end of file diff --git a/mono/profiler/proflog.h b/mono/profiler/mono-profiler-log.h similarity index 99% rename from mono/profiler/proflog.h rename to mono/profiler/mono-profiler-log.h index 5649d8be76..99b5782db6 100644 --- a/mono/profiler/proflog.h +++ b/mono/profiler/mono-profiler-log.h @@ -4,8 +4,9 @@ #define BUF_ID 0x4D504C01 #define LOG_HEADER_ID 0x4D505A01 #define LOG_VERSION_MAJOR 1 -#define LOG_VERSION_MINOR 0 +#define LOG_VERSION_MINOR 1 #define LOG_DATA_VERSION 13 + /* * Changes in major/minor versions: * version 1.0: removed sysid field from header diff --git a/mono/profiler/mono-profiler-vtune.c b/mono/profiler/mono-profiler-vtune.c index 3f071a1087..78de58aaa0 100644 --- a/mono/profiler/mono-profiler-vtune.c +++ b/mono/profiler/mono-profiler-vtune.c @@ -109,7 +109,7 @@ method_jit_result (MonoProfiler *prof, MonoMethod *method, MonoJitInfo* jinfo, i sourceLoc = mono_debug_lookup_source_location (method, dmji->line_numbers[i].native_offset, mono_domain_get()); if (sourceLoc == NULL) { - free(vtuneMethod.line_number_table); + g_free (vtuneMethod.line_number_table); vtuneMethod.line_number_table = NULL; vtuneMethod.line_number_size = 0; break; @@ -126,9 +126,9 @@ method_jit_result (MonoProfiler *prof, MonoMethod *method, MonoJitInfo* jinfo, i iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, &vtuneMethod); if (vtuneMethod.source_file_name != NULL) - free(vtuneMethod.source_file_name); + g_free (vtuneMethod.source_file_name); if (vtuneMethod.line_number_table != NULL) - free(vtuneMethod.line_number_table); + g_free (vtuneMethod.line_number_table); g_free (signature); g_free (name); diff --git a/mono/profiler/mprof-report.c.REMOVED.git-id b/mono/profiler/mprof-report.c.REMOVED.git-id new file mode 100644 index 0000000000..56dcb1e774 --- /dev/null +++ b/mono/profiler/mprof-report.c.REMOVED.git-id @@ -0,0 +1 @@ +1017d1f8e6d4fb9e09b8f08fc4c7c8a976f35db6 \ No newline at end of file diff --git a/mono/profiler/proflog.c.REMOVED.git-id b/mono/profiler/proflog.c.REMOVED.git-id deleted file mode 100644 index af753270d8..0000000000 --- a/mono/profiler/proflog.c.REMOVED.git-id +++ /dev/null @@ -1 +0,0 @@ -874d8ba620ea8fa42ef506799e1dde438a2ecd10 \ No newline at end of file diff --git a/mono/profiler/utils.c b/mono/profiler/utils.c deleted file mode 100644 index c3e14e4af8..0000000000 --- a/mono/profiler/utils.c +++ /dev/null @@ -1,426 +0,0 @@ -/* - * utils.c: log profiler and reporter utils - * - * We have here the minimal needed portability functions: we can't depend - * on the ones provided by the runtime, since they are internal and, - * especially mprof-report is an external program. - * Note also that we don't take a glib/eglib dependency here for mostly - * the same reason (but also because we need tight control in the profiler - * over memory allocation, which needs to work with the world stopped). - * - * Author: - * Paolo Molaro (lupus@ximian.com) - * - * Copyright 2010 Novell, Inc (http://www.novell.com) - * Licensed under the MIT license. See LICENSE file in the project root for full license information. - */ -#include "utils.h" -#include -#include -#include -#include -#include -#ifdef HOST_WIN32 -#include -#else -#include -#include -#endif - - -#ifdef HAVE_SYS_TIME_H -#include -#endif -#if HAVE_SYS_MMAN_H -#include -#endif - -#if defined(__APPLE__) -#include -#include - -static mach_timebase_info_data_t timebase_info; -#endif - -#ifndef MAP_ANONYMOUS -#define MAP_ANONYMOUS MAP_ANON -#endif - -#define TICKS_PER_SEC 1000000000LL - -#if (defined(TARGET_X86) || defined(TARGET_AMD64)) && defined(__linux__) && defined(HAVE_SCHED_GETCPU) -#define HAVE_RDTSC 1 -#endif - -typedef struct { - unsigned int timer_count; - int last_cpu; - uint64_t last_rdtsc; - uint64_t last_time; -} TlsData; - -#ifdef HOST_WIN32 -static int tls_data; -#define DECL_TLS_DATA TlsData *tls; tls = (TlsData *) TlsGetValue (tls_data); if (tls == NULL) { tls = (TlsData *) calloc (sizeof (TlsData), 1); TlsSetValue (tls_data, tls); } -#define TLS_INIT(x) x = TlsAlloc() -#elif HAVE_KW_THREAD -static __thread TlsData tls_data; -#define DECL_TLS_DATA TlsData *tls = &tls_data -#define TLS_INIT(x) -#else -static pthread_key_t tls_data; -#define DECL_TLS_DATA TlsData *tls; tls = (TlsData *) pthread_getspecific (tls_data); if (tls == NULL) { tls = (TlsData *) calloc (sizeof (TlsData), 1); pthread_setspecific (tls_data, tls); } -#define TLS_INIT(x) pthread_key_create(&x, NULL) -#endif - -#ifdef HOST_WIN32 -static CRITICAL_SECTION log_lock; -static LARGE_INTEGER pcounter_freq; -#else -static pthread_mutex_t log_lock = PTHREAD_MUTEX_INITIALIZER; -#endif - -static int timer_overhead = 0; -static uint64_t time_inc = 0; -typedef uint64_t (*TimeFunc)(void); - -static TimeFunc time_func; - -static uint64_t -clock_time (void) -{ -#if defined(__APPLE__) - uint64_t time = mach_absolute_time (); - - time *= timebase_info.numer; - time /= timebase_info.denom; - - return time; -#elif defined(HOST_WIN32) - LARGE_INTEGER value; - QueryPerformanceCounter (&value); - return value.QuadPart * TICKS_PER_SEC / pcounter_freq.QuadPart; -#elif defined(CLOCK_MONOTONIC) - struct timespec tspec; - clock_gettime (CLOCK_MONOTONIC, &tspec); - return ((uint64_t)tspec.tv_sec * TICKS_PER_SEC + tspec.tv_nsec); -#else - struct timeval tv; - gettimeofday (&tv, NULL); - return ((uint64_t)tv.tv_sec * TICKS_PER_SEC + tv.tv_usec * 1000); -#endif -} - -/* must be power of two */ -#define TIME_ADJ 8 - -static uint64_t -fast_current_time (void) -{ - DECL_TLS_DATA; - if (tls->timer_count++ & (TIME_ADJ - 1)) { - tls->last_time += time_inc; - return tls->last_time; - } - tls->last_time = clock_time (); - return tls->last_time; -} - -#if HAVE_RDTSC - -#define rdtsc(low,high) \ - __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high)) - -static uint64_t -safe_rdtsc (int *cpu) -{ - unsigned int low, high; - int c1 = sched_getcpu (); - int c2; - rdtsc (low, high); - c2 = sched_getcpu (); - if (c1 != c2) { - *cpu = -1; - return 0; - } - *cpu = c1; - return (((uint64_t) high) << 32) + (uint64_t)low; -} - -static double cpu_freq; - -static int -have_rdtsc (void) { - char buf[256]; - int have_freq = 0; - int have_flag = 0; - float val; - FILE *cpuinfo; - int cpu = sched_getcpu (); - - if (cpu < 0) - return 0; - - if (!(cpuinfo = fopen ("/proc/cpuinfo", "r"))) - return 0; - while (fgets (buf, sizeof(buf), cpuinfo)) { - if (sscanf (buf, "cpu MHz : %f", &val) == 1) { - /*printf ("got mh: %f\n", val);*/ - have_freq = 1; - cpu_freq = val * 1000000; - } - if (strncmp (buf, "flags :", 5) == 0) { - if (strstr (buf, "constant_tsc")) { - have_flag = 1; - /*printf ("have tsc\n");*/ - } - } - } - fclose (cpuinfo); - return have_flag? have_freq: 0; -} - -static uint64_t -rdtsc_current_time (void) -{ - DECL_TLS_DATA; - if (tls->timer_count++ & (TIME_ADJ*8 - 1)) { - int cpu; - uint64_t tsc = safe_rdtsc (&cpu); - if (cpu != -1 && cpu == tls->last_cpu) { - int64_t diff = tsc - tls->last_rdtsc; - uint64_t nsecs; - if (diff > 0) { - nsecs = (double)diff/cpu_freq; - //printf ("%llu cycles: %llu nsecs\n", diff, nsecs); - return tls->last_time + nsecs; - } else { - printf ("tsc went backwards\n"); - } - } else { - //printf ("wrong cpu: %d\n", cpu); - } - } - tls->last_time = clock_time (); - tls->last_rdtsc = safe_rdtsc (&tls->last_cpu); - return tls->last_time; -} -#else -#define have_rdtsc() 0 -#define rdtsc_current_time fast_current_time -#endif - -static uint64_t -null_time (void) -{ - static uint64_t timer = 0; - return timer++; -} - -void -utils_init (int fast_time) -{ - int i; - uint64_t time_start, time_end; - TLS_INIT (tls_data); -#ifdef HOST_WIN32 - InitializeCriticalSection (&log_lock); - QueryPerformanceFrequency (&pcounter_freq); -#endif -#if defined (__APPLE__) - mach_timebase_info (&timebase_info); -#endif - - if (fast_time > 1) { - time_func = null_time; - } else if (fast_time) { - uint64_t timea; - uint64_t timeb; - clock_time (); - timea = clock_time (); - timeb = clock_time (); - time_inc = (timeb - timea) / TIME_ADJ; - /*printf ("time inc: %llu, timea: %llu, timeb: %llu, diff: %llu\n", time_inc, timea, timeb, timec-timeb);*/ - if (have_rdtsc ()) - time_func = rdtsc_current_time; - else - time_func = fast_current_time; - } else { - time_func = clock_time; - } - time_start = time_func (); - for (i = 0; i < 256; ++i) - time_func (); - time_end = time_func (); - timer_overhead = (time_end - time_start) / 256; -} - -int -get_timer_overhead (void) -{ - return timer_overhead; -} - -uint64_t -current_time (void) -{ - return time_func (); -} - -void* -alloc_buffer (int size) -{ - void *ptr; -#ifdef HOST_WIN32 - ptr = VirtualAlloc (NULL, size, MEM_COMMIT, PAGE_READWRITE); - return ptr; -#else - ptr = mmap (NULL, size, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); - if (ptr == MAP_FAILED) - return NULL; - return ptr; -#endif -} - -void -free_buffer (void *buf, int size) -{ -#ifdef HOST_WIN32 - VirtualFree (buf, 0, MEM_RELEASE); -#else - munmap (buf, size); -#endif -} - -void -take_lock (void) -{ -#ifdef HOST_WIN32 - EnterCriticalSection (&log_lock); -#else - pthread_mutex_lock (&log_lock); -#endif -} - -void -release_lock (void) -{ -#ifdef HOST_WIN32 - LeaveCriticalSection (&log_lock); -#else - pthread_mutex_unlock (&log_lock); -#endif -} - -void -encode_uleb128 (uint64_t value, uint8_t *buf, uint8_t **endbuf) -{ - uint8_t *p = buf; - - do { - uint8_t b = value & 0x7f; - value >>= 7; - if (value != 0) /* more bytes to come */ - b |= 0x80; - *p ++ = b; - } while (value); - - *endbuf = p; -} - -void -encode_sleb128 (intptr_t value, uint8_t *buf, uint8_t **endbuf) -{ - int more = 1; - int negative = (value < 0); - unsigned int size = sizeof (intptr_t) * 8; - uint8_t byte; - uint8_t *p = buf; - - while (more) { - byte = value & 0x7f; - value >>= 7; - /* the following is unnecessary if the - * implementation of >>= uses an arithmetic rather - * than logical shift for a signed left operand - */ - if (negative) - /* sign extend */ - value |= - ((intptr_t)1 <<(size - 7)); - /* sign bit of byte is second high order bit (0x40) */ - if ((value == 0 && !(byte & 0x40)) || - (value == -1 && (byte & 0x40))) - more = 0; - else - byte |= 0x80; - *p ++= byte; - } - - *endbuf = p; -} - -uint64_t -decode_uleb128 (uint8_t *buf, uint8_t **endbuf) -{ - uint64_t res = 0; - int shift = 0; - - while (1) { - uint8_t b = *buf++; - - res |= (((uint64_t)(b & 0x7f)) << shift); - if (!(b & 0x80)) - break; - shift += 7; - } - - *endbuf = buf; - - return res; -} - -intptr_t -decode_sleb128 (uint8_t *buf, uint8_t **endbuf) -{ - uint8_t *p = buf; - intptr_t res = 0; - int shift = 0; - - while (1) { - uint8_t b = *p; - p ++; - - res = res | (((intptr_t)(b & 0x7f)) << shift); - shift += 7; - if (!(b & 0x80)) { - if (shift < sizeof (intptr_t) * 8 && (b & 0x40)) - res |= - ((intptr_t)1 << shift); - break; - } - } - - *endbuf = p; - - return res; -} - -uintptr_t -thread_id (void) -{ -#ifdef HOST_WIN32 - return (uintptr_t)GetCurrentThreadId (); -#else - return (uintptr_t)pthread_self (); -#endif -} - -uintptr_t -process_id (void) -{ -#ifdef HOST_WIN32 - return GetCurrentProcessId (); -#else - return (uintptr_t)getpid (); -#endif -} - diff --git a/mono/profiler/utils.h b/mono/profiler/utils.h deleted file mode 100644 index 3af56d202c..0000000000 --- a/mono/profiler/utils.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef __MONO_MPLOG_UTILS_H__ -#define __MONO_MPLOG_UTILS_H__ - -#include "config.h" -#include "mono/utils/mono-publib.h" - -void utils_init (int fast_time); -int get_timer_overhead (void); -uint64_t current_time (void); -void* alloc_buffer (int size); -void free_buffer (void *buf, int size); -void take_lock (void); -void release_lock (void); -uintptr_t thread_id (void); -uintptr_t process_id (void); - -void encode_uleb128 (uint64_t value, uint8_t *buf, uint8_t **endbuf); -void encode_sleb128 (intptr_t value, uint8_t *buf, uint8_t **endbuf); -uint64_t decode_uleb128 (uint8_t *buf, uint8_t **endbuf); -intptr_t decode_sleb128 (uint8_t *buf, uint8_t **endbuf); - - -#endif /* __MONO_MPLOG_UTILS_H__ */ - diff --git a/mono/sgen/Makefile.in b/mono/sgen/Makefile.in index 31b3a40fdf..86603c8e1a 100644 --- a/mono/sgen/Makefile.in +++ b/mono/sgen/Makefile.in @@ -226,6 +226,8 @@ DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AOT_BUILD_FLAGS = @AOT_BUILD_FLAGS@ +AOT_RUN_FLAGS = @AOT_RUN_FLAGS@ API_VER = @API_VER@ AR = @AR@ AS = @AS@ @@ -234,6 +236,11 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOEHM_DEFINES = @BOEHM_DEFINES@ +BTLS_ARCH = @BTLS_ARCH@ +BTLS_CFLAGS = @BTLS_CFLAGS@ +BTLS_CMAKE_ARGS = @BTLS_CMAKE_ARGS@ +BTLS_PLATFORM = @BTLS_PLATFORM@ +BTLS_ROOT = @BTLS_ROOT@ BUILD_EXEEXT = @BUILD_EXEEXT@ CC = @CC@ CCAS = @CCAS@ @@ -243,6 +250,7 @@ CCDEPMODE = @CCDEPMODE@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMAKE = @CMAKE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ @@ -263,7 +271,6 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_PERF_EVENTS = @ENABLE_PERF_EVENTS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDKX11 = @GDKX11@ @@ -278,10 +285,12 @@ HAVE_MSGFMT = @HAVE_MSGFMT@ HOST_CC = @HOST_CC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MOBILE_STATIC = @INSTALL_MOBILE_STATIC@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTL = @INTL@ +INVARIANT_AOT_OPTIONS = @INVARIANT_AOT_OPTIONS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBC = @LIBC@ @@ -328,6 +337,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ +PLATFORM_AOT_SUFFIX = @PLATFORM_AOT_SUFFIX@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -337,6 +347,7 @@ SHELL = @SHELL@ SQLITE = @SQLITE@ SQLITE3 = @SQLITE3@ STRIP = @STRIP@ +TEST_PROFILE = @TEST_PROFILE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VTUNE_CFLAGS = @VTUNE_CFLAGS@ diff --git a/mono/sgen/sgen-archdep.h b/mono/sgen/sgen-archdep.h index da6aaf0182..d0314e8ccf 100644 --- a/mono/sgen/sgen-archdep.h +++ b/mono/sgen/sgen-archdep.h @@ -26,7 +26,13 @@ #elif defined(TARGET_AMD64) +#ifdef HOST_WIN32 +/* The Windows x64 ABI defines no "red zone". The ABI states: + "All memory beyond the current address of RSP is considered volatile" */ +#define REDZONE_SIZE 0 +#else #define REDZONE_SIZE 128 +#endif #elif defined(TARGET_POWERPC) diff --git a/mono/sgen/sgen-cardtable.c b/mono/sgen/sgen-cardtable.c index 05dfe7d907..50369b0a78 100644 --- a/mono/sgen/sgen-cardtable.c +++ b/mono/sgen/sgen-cardtable.c @@ -410,7 +410,7 @@ static void sgen_card_table_clear_cards (void) { /*XXX we could do this in 2 ways. using mincore or iterating over all sections/los objects */ - sgen_major_collector_iterate_live_block_ranges (clear_cards); + sgen_major_collector_iterate_block_ranges (clear_cards); sgen_los_iterate_live_block_ranges (clear_cards); } @@ -431,7 +431,7 @@ sgen_card_table_scan_remsets (ScanCopyContext ctx) #ifdef SGEN_HAVE_OVERLAPPING_CARDS /*FIXME we should have a bit on each block/los object telling if the object have marked cards.*/ /*First we copy*/ - sgen_major_collector_iterate_live_block_ranges (move_cards_to_shadow_table); + sgen_major_collector_iterate_block_ranges (move_cards_to_shadow_table); sgen_los_iterate_live_block_ranges (move_cards_to_shadow_table); /*Then we clear*/ diff --git a/mono/sgen/sgen-copy-object.h b/mono/sgen/sgen-copy-object.h index 016fc462e0..3579d09bae 100644 --- a/mono/sgen/sgen-copy-object.h +++ b/mono/sgen/sgen-copy-object.h @@ -8,6 +8,27 @@ * Licensed under the MIT license. See LICENSE file in the project root for full license information. */ +/* + * Defines + * + * GCObject* copy_object_no_checks (GCObject *obj, SgenGrayQueue *queue) + * + * which allocates new space for `obj`, copies it there, forwards `obj` to its new location, + * and enqueues the copy into `queue`. + * + * To be defined by the includer: + * + * COLLECTOR_SERIAL_ALLOC_FOR_PROMOTION(vt, obj, objsize, has_refs) + * + * Allocates space for promoting object `obj`, with size `objsize`, and initizializes the + * vtable with `vt`. `has_refs` indicates whether the object contains references. + * + * collector_pin_object(obj, queue) + * + * Called when no space for `obj` could be allocated. It must pin `obj` and enqueue it into + * `queue` for scanning. + */ + extern guint64 stat_copy_object_called_nursery; extern guint64 stat_objects_copied_nursery; @@ -73,3 +94,6 @@ copy_object_no_checks (GCObject *obj, SgenGrayQueue *queue) return (GCObject *)destination; } + +#undef COLLECTOR_SERIAL_ALLOC_FOR_PROMOTION +#undef collector_pin_object diff --git a/mono/sgen/sgen-debug.c b/mono/sgen/sgen-debug.c index 6daa9199df..cb2fbb7f7c 100644 --- a/mono/sgen/sgen-debug.c +++ b/mono/sgen/sgen-debug.c @@ -149,15 +149,16 @@ static gboolean missing_remsets; */ #undef HANDLE_PTR #define HANDLE_PTR(ptr,obj) do { \ - if (*(ptr) && sgen_ptr_in_nursery ((char*)*(ptr))) { \ - if (!sgen_get_remset ()->find_address ((char*)(ptr)) && !sgen_cement_lookup (*(ptr))) { \ - GCVTable __vt = SGEN_LOAD_VTABLE (obj); \ - SGEN_LOG (0, "Oldspace->newspace reference %p at offset %zd in object %p (%s.%s) not found in remsets.", *(ptr), (char*)(ptr) - (char*)(obj), (obj), sgen_client_vtable_get_namespace (__vt), sgen_client_vtable_get_name (__vt)); \ - binary_protocol_missing_remset ((obj), __vt, (int) ((char*)(ptr) - (char*)(obj)), *(ptr), (gpointer)LOAD_VTABLE(*(ptr)), object_is_pinned (*(ptr))); \ - if (!object_is_pinned (*(ptr))) \ - missing_remsets = TRUE; \ - } \ - } \ + if (*(ptr) && sgen_ptr_in_nursery ((char*)*(ptr))) { \ + if (!sgen_get_remset ()->find_address ((char*)(ptr)) && !sgen_cement_lookup (*(ptr))) { \ + GCVTable __vt = SGEN_LOAD_VTABLE (obj); \ + gboolean is_pinned = object_is_pinned (*(ptr)); \ + SGEN_LOG (0, "Oldspace->newspace reference %p at offset %zd in object %p (%s.%s) not found in remsets%s.", *(ptr), (char*)(ptr) - (char*)(obj), (obj), sgen_client_vtable_get_namespace (__vt), sgen_client_vtable_get_name (__vt), is_pinned ? ", but object is pinned" : ""); \ + binary_protocol_missing_remset ((obj), __vt, (int) ((char*)(ptr) - (char*)(obj)), *(ptr), (gpointer)LOAD_VTABLE(*(ptr)), is_pinned); \ + if (!is_pinned) \ + missing_remsets = TRUE; \ + } \ + } \ } while (0) /* @@ -181,7 +182,7 @@ check_consistency_callback (GCObject *obj, size_t size, void *dummy) * Assumes the world is stopped. */ void -sgen_check_consistency (void) +sgen_check_remset_consistency (void) { // Need to add more checks @@ -196,6 +197,8 @@ sgen_check_consistency (void) SGEN_LOG (1, "Heap consistency check done."); + if (missing_remsets) + binary_protocol_flush_buffers (TRUE); if (!binary_protocol_is_enabled ()) g_assert (!missing_remsets); } @@ -213,7 +216,7 @@ is_major_or_los_object_marked (GCObject *obj) #undef HANDLE_PTR #define HANDLE_PTR(ptr,obj) do { \ if (*(ptr) && !sgen_ptr_in_nursery ((char*)*(ptr)) && !is_major_or_los_object_marked ((GCObject*)*(ptr))) { \ - if (!sgen_get_remset ()->find_address_with_cards (start, cards, (char*)(ptr))) { \ + if (!cards || !sgen_get_remset ()->find_address_with_cards (start, cards, (char*)(ptr))) { \ GCVTable __vt = SGEN_LOAD_VTABLE (obj); \ SGEN_LOG (0, "major->major reference %p at offset %zd in object %p (%s.%s) not found in remsets.", *(ptr), (char*)(ptr) - (char*)(obj), (obj), sgen_client_vtable_get_namespace (__vt), sgen_client_vtable_get_name (__vt)); \ binary_protocol_missing_remset ((obj), __vt, (int) ((char*)(ptr) - (char*)(obj)), *(ptr), (gpointer)LOAD_VTABLE(*(ptr)), object_is_pinned (*(ptr))); \ @@ -240,8 +243,6 @@ check_mod_union_callback (GCObject *obj, size_t size, void *dummy) else cards = sgen_get_major_collector ()->get_cardtable_mod_union_for_reference (start); - SGEN_ASSERT (0, cards, "we must have mod union for marked major objects"); - #include "sgen-scan-object.h" } @@ -250,7 +251,7 @@ sgen_check_mod_union_consistency (void) { missing_remsets = FALSE; - major_collector.iterate_objects (ITERATE_OBJECTS_ALL, (IterateObjectCallbackFunc)check_mod_union_callback, (void*)FALSE); + major_collector.iterate_objects (ITERATE_OBJECTS_SWEEP_ALL, (IterateObjectCallbackFunc)check_mod_union_callback, (void*)FALSE); sgen_los_iterate_objects ((IterateObjectCallbackFunc)check_mod_union_callback, (void*)TRUE); @@ -426,15 +427,15 @@ missing_remset_spew (char *obj, char **slot) FIXME Flag missing remsets due to pinning as non fatal */ #undef HANDLE_PTR -#define HANDLE_PTR(ptr,obj) do { \ - if (*(char**)ptr) { \ +#define HANDLE_PTR(ptr,obj) do { \ + if (*(char**)ptr) { \ if (!is_valid_object_pointer (*(char**)ptr)) { \ - bad_pointer_spew ((char*)obj, (char**)ptr); \ - } else if (!sgen_ptr_in_nursery (obj) && sgen_ptr_in_nursery ((char*)*ptr)) { \ - if (!sgen_get_remset ()->find_address ((char*)(ptr)) && !sgen_cement_lookup (*(ptr)) && (!allow_missing_pinned || !SGEN_OBJECT_IS_PINNED (*(ptr)))) \ - missing_remset_spew ((char*)obj, (char**)ptr); \ - } \ - } \ + bad_pointer_spew ((char*)obj, (char**)ptr); \ + } else if (!sgen_ptr_in_nursery (obj) && sgen_ptr_in_nursery ((char*)*ptr)) { \ + if (!allow_missing_pinned && !SGEN_OBJECT_IS_PINNED (*(ptr)) && !sgen_get_remset ()->find_address ((char*)(ptr)) && !sgen_cement_lookup (*(ptr))) \ + missing_remset_spew ((char*)obj, (char**)ptr); \ + } \ + } \ } while (0) static void @@ -442,7 +443,7 @@ verify_object_pointers_callback (GCObject *obj, size_t size, void *data) { char *start = (char*)obj; gboolean allow_missing_pinned = (gboolean) (size_t) data; - SgenDescriptor desc = sgen_obj_get_descriptor (obj); + SgenDescriptor desc = sgen_obj_get_descriptor_safe (obj); #include "sgen-scan-object.h" } diff --git a/mono/sgen/sgen-gc.c.REMOVED.git-id b/mono/sgen/sgen-gc.c.REMOVED.git-id index d8e62c64f4..b1ed34fc46 100644 --- a/mono/sgen/sgen-gc.c.REMOVED.git-id +++ b/mono/sgen/sgen-gc.c.REMOVED.git-id @@ -1 +1 @@ -921c94696e63d97030b39de7cc7cb998792fc575 \ No newline at end of file +ff078a716739439b233abc2afa39189035ed8c24 \ No newline at end of file diff --git a/mono/sgen/sgen-gc.h b/mono/sgen/sgen-gc.h index 22e6a32847..dd5aef0392 100644 --- a/mono/sgen/sgen-gc.h +++ b/mono/sgen/sgen-gc.h @@ -116,16 +116,40 @@ extern guint64 stat_objects_copied_major; g_error (__VA_ARGS__); \ } } while (0) +#ifndef HOST_WIN32 +# define LOG_TIMESTAMP \ + do { \ + time_t t; \ + struct tm tod; \ + time(&t); \ + localtime_r(&t, &tod); \ + strftime(logTime, sizeof(logTime), "%Y-%m-%d %H:%M:%S", &tod); \ + } while (0) +#else +# define LOG_TIMESTAMP \ + do { \ + time_t t; \ + struct tm *tod; \ + time(&t); \ + tod = localtime(&t); \ + strftime(logTime, sizeof(logTime), "%F %T", tod); \ + } while (0) +#endif #define SGEN_LOG(level, format, ...) do { \ if (G_UNLIKELY ((level) <= SGEN_MAX_DEBUG_LEVEL && (level) <= gc_debug_level)) { \ - mono_gc_printf (gc_debug_file, format "\n", ##__VA_ARGS__); \ + char logTime[80]; \ + LOG_TIMESTAMP; \ + mono_gc_printf (gc_debug_file, "%s " format "\n", logTime, ##__VA_ARGS__); \ } } while (0) #define SGEN_COND_LOG(level, cond, format, ...) do { \ - if (G_UNLIKELY ((level) <= SGEN_MAX_DEBUG_LEVEL && (level) <= gc_debug_level)) { \ - if (cond) \ - mono_gc_printf (gc_debug_file, format "\n", ##__VA_ARGS__); \ + if (G_UNLIKELY ((level) <= SGEN_MAX_DEBUG_LEVEL && (level) <= gc_debug_level)) { \ + if (cond) { \ + char logTime[80]; \ + LOG_TIMESTAMP; \ + mono_gc_printf (gc_debug_file, "%s " format "\n", logTime, ##__VA_ARGS__); \ + } \ } } while (0) extern int gc_debug_level; @@ -263,6 +287,7 @@ sgen_get_nursery_end (void) List of what each bit on of the vtable gc bits means. */ enum { + // When the Java bridge has determined an object is "bridged", it uses these two bits to cache that information. SGEN_GC_BIT_BRIDGE_OBJECT = 1, SGEN_GC_BIT_BRIDGE_OPAQUE_OBJECT = 2, SGEN_GC_BIT_FINALIZER_AWARE = 4, @@ -428,9 +453,9 @@ void* sgen_alloc_internal_dynamic (size_t size, int type, gboolean assert_on_fai void sgen_free_internal_dynamic (void *addr, size_t size, int type); void sgen_pin_stats_enable (void); -void sgen_pin_stats_register_object (GCObject *obj, size_t size); +void sgen_pin_stats_register_object (GCObject *obj, int generation); void sgen_pin_stats_register_global_remset (GCObject *obj); -void sgen_pin_stats_print_class_stats (void); +void sgen_pin_stats_report (void); void sgen_sort_addresses (void **array, size_t size); void sgen_add_to_global_remset (gpointer ptr, GCObject *obj); @@ -568,12 +593,12 @@ sgen_update_reference (GCObject **p, GCObject *o, gboolean allow_null) typedef void (*sgen_cardtable_block_callback) (mword start, mword size); void sgen_major_collector_iterate_live_block_ranges (sgen_cardtable_block_callback callback); +void sgen_major_collector_iterate_block_ranges (sgen_cardtable_block_callback callback); typedef enum { ITERATE_OBJECTS_SWEEP = 1, ITERATE_OBJECTS_NON_PINNED = 2, ITERATE_OBJECTS_PINNED = 4, - ITERATE_OBJECTS_ALL = ITERATE_OBJECTS_NON_PINNED | ITERATE_OBJECTS_PINNED, ITERATE_OBJECTS_SWEEP_NON_PINNED = ITERATE_OBJECTS_SWEEP | ITERATE_OBJECTS_NON_PINNED, ITERATE_OBJECTS_SWEEP_PINNED = ITERATE_OBJECTS_SWEEP | ITERATE_OBJECTS_PINNED, ITERATE_OBJECTS_SWEEP_ALL = ITERATE_OBJECTS_SWEEP | ITERATE_OBJECTS_NON_PINNED | ITERATE_OBJECTS_PINNED @@ -622,6 +647,7 @@ struct _SgenMajorCollector { void (*pin_major_object) (GCObject *obj, SgenGrayQueue *queue); void (*scan_card_table) (CardTableScanType scan_type, ScanCopyContext ctx); void (*iterate_live_block_ranges) (sgen_cardtable_block_callback callback); + void (*iterate_block_ranges) (sgen_cardtable_block_callback callback); void (*update_cardtable_mod_union) (void); void (*init_to_space) (void); void (*sweep) (void); @@ -978,7 +1004,7 @@ GCObject* sgen_alloc_obj_mature (GCVTable vtable, size_t size); /* Debug support */ -void sgen_check_consistency (void); +void sgen_check_remset_consistency (void); void sgen_check_mod_union_consistency (void); void sgen_check_major_refs (void); void sgen_check_whole_heap (gboolean allow_missing_pinning); diff --git a/mono/sgen/sgen-gray.c b/mono/sgen/sgen-gray.c index 809215136f..9b5f92a195 100644 --- a/mono/sgen/sgen-gray.c +++ b/mono/sgen/sgen-gray.c @@ -38,6 +38,12 @@ guint64 stat_gray_queue_dequeue_slow_path; #define STATE_ASSERT(s,v) #endif +/* + * Whenever we dispose a gray queue, we save its free list. Then, in the next collection, + * we reuse that free list for the new gray queue. + */ +static GrayQueueSection *last_gray_queue_free_list; + void sgen_gray_object_alloc_queue_section (SgenGrayQueue *queue) { @@ -212,48 +218,40 @@ sgen_gray_object_queue_trim_free_list (SgenGrayQueue *queue) } void -sgen_gray_object_queue_init (SgenGrayQueue *queue, GrayQueueEnqueueCheckFunc enqueue_check_func) +sgen_gray_object_queue_init (SgenGrayQueue *queue, GrayQueueEnqueueCheckFunc enqueue_check_func, gboolean reuse_free_list) { - g_assert (sgen_gray_object_queue_is_empty (queue)); + memset (queue, 0, sizeof (SgenGrayQueue)); - queue->alloc_prepare_func = NULL; - queue->alloc_prepare_data = NULL; #ifdef SGEN_CHECK_GRAY_OBJECT_ENQUEUE queue->enqueue_check_func = enqueue_check_func; #endif + if (reuse_free_list) { + queue->free_list = last_gray_queue_free_list; + last_gray_queue_free_list = NULL; + } +} + +void +sgen_gray_object_queue_dispose (SgenGrayQueue *queue) +{ + SGEN_ASSERT (0, sgen_gray_object_queue_is_empty (queue), "Why are we disposing a gray queue that's not empty?"); + /* Free the extra sections allocated during the last collection */ sgen_gray_object_queue_trim_free_list (queue); -} -static void -invalid_prepare_func (SgenGrayQueue *queue) -{ - g_assert_not_reached (); + SGEN_ASSERT (0, !last_gray_queue_free_list, "Are we disposing two gray queues after another?"); + last_gray_queue_free_list = queue->free_list; + + /* just to make sure */ + memset (queue, 0, sizeof (SgenGrayQueue)); } void -sgen_gray_object_queue_init_invalid (SgenGrayQueue *queue) +sgen_gray_queue_set_alloc_prepare (SgenGrayQueue *queue, GrayQueueAllocPrepareFunc alloc_prepare_func) { - sgen_gray_object_queue_init (queue, NULL); - queue->alloc_prepare_func = invalid_prepare_func; - queue->alloc_prepare_data = NULL; -} - -void -sgen_gray_queue_set_alloc_prepare (SgenGrayQueue *queue, GrayQueueAllocPrepareFunc alloc_prepare_func, void *data) -{ - SGEN_ASSERT (0, !queue->alloc_prepare_func && !queue->alloc_prepare_data, "Can't set gray queue alloc-prepare twice"); + SGEN_ASSERT (0, !queue->alloc_prepare_func, "Can't set gray queue alloc-prepare twice"); queue->alloc_prepare_func = alloc_prepare_func; - queue->alloc_prepare_data = data; -} - -void -sgen_gray_object_queue_init_with_alloc_prepare (SgenGrayQueue *queue, GrayQueueEnqueueCheckFunc enqueue_check_func, - GrayQueueAllocPrepareFunc alloc_prepare_func, void *data) -{ - sgen_gray_object_queue_init (queue, enqueue_check_func); - sgen_gray_queue_set_alloc_prepare (queue, alloc_prepare_func, data); } void @@ -268,13 +266,6 @@ sgen_gray_object_queue_deinit (SgenGrayQueue *queue) } } -void -sgen_gray_object_queue_disable_alloc_prepare (SgenGrayQueue *queue) -{ - queue->alloc_prepare_func = NULL; - queue->alloc_prepare_data = NULL; -} - static void lock_section_queue (SgenSectionGrayQueue *queue) { diff --git a/mono/sgen/sgen-gray.h b/mono/sgen/sgen-gray.h index 019f44c927..2a872d7d2b 100644 --- a/mono/sgen/sgen-gray.h +++ b/mono/sgen/sgen-gray.h @@ -97,7 +97,6 @@ struct _SgenGrayQueue { #ifdef SGEN_CHECK_GRAY_OBJECT_ENQUEUE GrayQueueEnqueueCheckFunc enqueue_check_func; #endif - void *alloc_prepare_data; }; typedef struct _SgenSectionGrayQueue SgenSectionGrayQueue; @@ -130,13 +129,10 @@ GrayQueueEntry sgen_gray_object_dequeue (SgenGrayQueue *queue); GrayQueueSection* sgen_gray_object_dequeue_section (SgenGrayQueue *queue); void sgen_gray_object_enqueue_section (SgenGrayQueue *queue, GrayQueueSection *section); void sgen_gray_object_queue_trim_free_list (SgenGrayQueue *queue); -void sgen_gray_object_queue_init (SgenGrayQueue *queue, GrayQueueEnqueueCheckFunc enqueue_check_func); -void sgen_gray_object_queue_init_invalid (SgenGrayQueue *queue); -void sgen_gray_queue_set_alloc_prepare (SgenGrayQueue *queue, GrayQueueAllocPrepareFunc alloc_prepare_func, void *data); -void sgen_gray_object_queue_init_with_alloc_prepare (SgenGrayQueue *queue, GrayQueueEnqueueCheckFunc enqueue_check_func, - GrayQueueAllocPrepareFunc func, void *data); +void sgen_gray_object_queue_init (SgenGrayQueue *queue, GrayQueueEnqueueCheckFunc enqueue_check_func, gboolean reuse_free_list); +void sgen_gray_object_queue_dispose (SgenGrayQueue *queue); +void sgen_gray_queue_set_alloc_prepare (SgenGrayQueue *queue, GrayQueueAllocPrepareFunc alloc_prepare_func); void sgen_gray_object_queue_deinit (SgenGrayQueue *queue); -void sgen_gray_object_queue_disable_alloc_prepare (SgenGrayQueue *queue); void sgen_gray_object_alloc_queue_section (SgenGrayQueue *queue); void sgen_gray_object_free_queue_section (GrayQueueSection *section); diff --git a/mono/sgen/sgen-los.c b/mono/sgen/sgen-los.c index 4b52eefb3f..209c8d0e94 100644 --- a/mono/sgen/sgen-los.c +++ b/mono/sgen/sgen-los.c @@ -323,7 +323,7 @@ sgen_los_free_object (LOSObject *obj) los_num_objects--; #ifdef USE_MALLOC - free (obj); + g_free (obj); #else if (size > LOS_SECTION_OBJECT_LIMIT) { int pagesize = mono_pagesize (); @@ -379,7 +379,7 @@ sgen_los_alloc_large_inner (GCVTable vtable, size_t size) sgen_ensure_free_space (size, GENERATION_OLD); #ifdef USE_MALLOC - obj = malloc (size + sizeof (LOSObject)); + obj = g_malloc (size + sizeof (LOSObject)); memset (obj, 0, size + sizeof (LOSObject)); #else if (size > LOS_SECTION_OBJECT_LIMIT) { @@ -526,12 +526,14 @@ sgen_ptr_is_in_los (char *ptr, char **start) { LOSObject *obj; - *start = NULL; + if (start) + *start = NULL; for (obj = los_object_list; obj; obj = obj->next) { char *end = (char*)obj->data + sgen_los_object_size (obj); if (ptr >= (char*)obj->data && ptr < end) { - *start = (char*)obj->data; + if (start) + *start = (char*)obj->data; return TRUE; } } diff --git a/mono/sgen/sgen-marksweep-drain-gray-stack.h b/mono/sgen/sgen-marksweep-drain-gray-stack.h index ad2bb6fe27..3c96a2f010 100644 --- a/mono/sgen/sgen-marksweep-drain-gray-stack.h +++ b/mono/sgen/sgen-marksweep-drain-gray-stack.h @@ -117,7 +117,7 @@ COPY_OR_MARK_FUNCTION_NAME (GCObject **ptr, GCObject *obj, SgenGrayQueue *queue) MS_CALC_MARK_BIT (word, bit, obj); SGEN_ASSERT (9, !MS_MARK_BIT (block, word, bit), "object %p already marked", obj); MS_SET_MARK_BIT (block, word, bit); - binary_protocol_mark (obj, (gpointer)LOAD_VTABLE (obj), sgen_safe_object_get_size (obj)); + binary_protocol_mark (obj, (gpointer)SGEN_LOAD_VTABLE (obj), sgen_safe_object_get_size (obj)); return FALSE; #endif diff --git a/mono/sgen/sgen-marksweep.c b/mono/sgen/sgen-marksweep.c index 56dba1b0ee..d996be700e 100644 --- a/mono/sgen/sgen-marksweep.c +++ b/mono/sgen/sgen-marksweep.c @@ -194,16 +194,23 @@ static SgenArrayList allocated_blocks = SGEN_ARRAY_LIST_INIT (NULL, NULL, NULL, static void *empty_blocks = NULL; static size_t num_empty_blocks = 0; +/* + * We can iterate the block list also while sweep is in progress but we + * need to account for blocks that will be checked for sweeping and even + * freed in the process. + */ #define FOREACH_BLOCK_NO_LOCK(bl) { \ volatile gpointer *slot; \ - SGEN_ASSERT (0, !sweep_in_progress (), "Can't iterate blocks while sweep is in progress."); \ SGEN_ARRAY_LIST_FOREACH_SLOT (&allocated_blocks, slot) { \ - (bl) = BLOCK_UNTAG (*slot); + (bl) = BLOCK_UNTAG (*slot); \ + if (!(bl)) \ + continue; #define FOREACH_BLOCK_HAS_REFERENCES_NO_LOCK(bl,hr) { \ volatile gpointer *slot; \ - SGEN_ASSERT (0, !sweep_in_progress (), "Can't iterate blocks while sweep is in progress."); \ SGEN_ARRAY_LIST_FOREACH_SLOT (&allocated_blocks, slot) { \ (bl) = (MSBlockInfo *) (*slot); \ + if (!(bl)) \ + continue; \ (hr) = BLOCK_IS_TAGGED_HAS_REFERENCES ((bl)); \ (bl) = BLOCK_UNTAG ((bl)); #define END_FOREACH_BLOCK_NO_LOCK } SGEN_ARRAY_LIST_END_FOREACH_SLOT; } @@ -549,16 +556,6 @@ ms_alloc_block (int size_index, gboolean pinned, gboolean has_references) add_free_block (free_blocks, size_index, info); - /* - * Adding to the allocated_blocks array is racy with the removal of nulls when - * sweeping. We wait for sweep to finish to avoid that. - * - * The memory barrier here and in `sweep_job_func()` are required because we need - * `allocated_blocks` synchronized between this and the sweep thread. - */ - major_finish_sweep_checking (); - mono_memory_barrier (); - sgen_array_list_add (&allocated_blocks, BLOCK_TAG (info), 0, FALSE); SGEN_ATOMIC_ADD_P (num_major_sections, 1); @@ -566,17 +563,41 @@ ms_alloc_block (int size_index, gboolean pinned, gboolean has_references) } static gboolean -ptr_is_from_pinned_alloc (char *ptr) +ptr_is_in_major_block (char *ptr, char **start, gboolean *pinned) { MSBlockInfo *block; FOREACH_BLOCK_NO_LOCK (block) { - if (ptr >= MS_BLOCK_FOR_BLOCK_INFO (block) && ptr <= MS_BLOCK_FOR_BLOCK_INFO (block) + MS_BLOCK_SIZE) - return block->pinned; + if (ptr >= MS_BLOCK_FOR_BLOCK_INFO (block) && ptr <= MS_BLOCK_FOR_BLOCK_INFO (block) + MS_BLOCK_SIZE) { + int count = MS_BLOCK_FREE / block->obj_size; + int i; + + if (start) + *start = NULL; + for (i = 0; i <= count; ++i) { + if (ptr >= (char*)MS_BLOCK_OBJ (block, i) && ptr < (char*)MS_BLOCK_OBJ (block, i + 1)) { + if (start) + *start = (char *)MS_BLOCK_OBJ (block, i); + break; + } + } + if (pinned) + *pinned = block->pinned; + return TRUE; + } } END_FOREACH_BLOCK_NO_LOCK; return FALSE; } +static gboolean +ptr_is_from_pinned_alloc (char *ptr) +{ + gboolean pinned; + if (ptr_is_in_major_block (ptr, NULL, &pinned)) + return pinned; + return FALSE; +} + static void ensure_can_access_block_free_list (MSBlockInfo *block) { @@ -775,23 +796,9 @@ major_is_object_live (GCObject *obj) static gboolean major_ptr_is_in_non_pinned_space (char *ptr, char **start) { - MSBlockInfo *block; - - FOREACH_BLOCK_NO_LOCK (block) { - if (ptr >= MS_BLOCK_FOR_BLOCK_INFO (block) && ptr <= MS_BLOCK_FOR_BLOCK_INFO (block) + MS_BLOCK_SIZE) { - int count = MS_BLOCK_FREE / block->obj_size; - int i; - - *start = NULL; - for (i = 0; i <= count; ++i) { - if (ptr >= (char*)MS_BLOCK_OBJ (block, i) && ptr < (char*)MS_BLOCK_OBJ (block, i + 1)) { - *start = (char *)MS_BLOCK_OBJ (block, i); - break; - } - } - return !block->pinned; - } - } END_FOREACH_BLOCK_NO_LOCK; + gboolean pinned; + if (ptr_is_in_major_block (ptr, start, &pinned)) + return !pinned; return FALSE; } @@ -865,6 +872,7 @@ major_iterate_objects (IterateObjectsFlags flags, IterateObjectCallbackFunc call gboolean pinned = flags & ITERATE_OBJECTS_PINNED; MSBlockInfo *block; + /* No actual sweeping will take place if we are in the middle of a major collection. */ major_finish_sweep_checking (); FOREACH_BLOCK_NO_LOCK (block) { int count = MS_BLOCK_FREE / block->obj_size; @@ -874,26 +882,13 @@ major_iterate_objects (IterateObjectsFlags flags, IterateObjectCallbackFunc call continue; if (!block->pinned && !non_pinned) continue; - if (sweep && lazy_sweep) { + if (sweep && lazy_sweep && !block_is_swept_or_marking (block)) { sweep_block (block); SGEN_ASSERT (6, block->state == BLOCK_STATE_SWEPT, "Block must be swept after sweeping"); } for (i = 0; i < count; ++i) { void **obj = (void**) MS_BLOCK_OBJ (block, i); - /* - * We've finished sweep checking, but if we're sweeping lazily and - * the flags don't require us to sweep, the block might still need - * sweeping. In that case, we need to consult the mark bits to tell - * us whether an object slot is live. - */ - if (!block_is_swept_or_marking (block)) { - int word, bit; - SGEN_ASSERT (6, !sweep && block->state == BLOCK_STATE_NEED_SWEEPING, "Has sweeping not finished?"); - MS_CALC_MARK_BIT (word, bit, obj); - if (!MS_MARK_BIT (block, word, bit)) - continue; - } if (MS_OBJ_ALLOCED (obj, block)) callback ((GCObject*)obj, block->obj_size, data); } @@ -1084,19 +1079,6 @@ major_block_is_evacuating (MSBlockInfo *block) return FALSE; } -#define LOAD_VTABLE SGEN_LOAD_VTABLE - -#define MS_MARK_OBJECT_AND_ENQUEUE_CHECKED(obj,desc,block,queue) do { \ - int __word, __bit; \ - MS_CALC_MARK_BIT (__word, __bit, (obj)); \ - if (!MS_MARK_BIT ((block), __word, __bit) && MS_OBJ_ALLOCED ((obj), (block))) { \ - MS_SET_MARK_BIT ((block), __word, __bit); \ - if (sgen_gc_descr_has_references (desc)) \ - GRAY_OBJECT_ENQUEUE ((queue), (obj), (desc)); \ - binary_protocol_mark ((obj), (gpointer)LOAD_VTABLE ((obj)), sgen_safe_object_get_size ((obj))); \ - INC_NUM_MAJOR_OBJECTS_MARKED (); \ - } \ - } while (0) #define MS_MARK_OBJECT_AND_ENQUEUE(obj,desc,block,queue) do { \ int __word, __bit; \ MS_CALC_MARK_BIT (__word, __bit, (obj)); \ @@ -1105,7 +1087,7 @@ major_block_is_evacuating (MSBlockInfo *block) MS_SET_MARK_BIT ((block), __word, __bit); \ if (sgen_gc_descr_has_references (desc)) \ GRAY_OBJECT_ENQUEUE ((queue), (obj), (desc)); \ - binary_protocol_mark ((obj), (gpointer)LOAD_VTABLE ((obj)), sgen_safe_object_get_size ((obj))); \ + binary_protocol_mark ((obj), (gpointer)SGEN_LOAD_VTABLE ((obj)), sgen_safe_object_get_size ((obj))); \ INC_NUM_MAJOR_OBJECTS_MARKED (); \ } \ } while (0) @@ -1253,8 +1235,6 @@ mark_pinned_objects_in_block (MSBlockInfo *block, size_t first_entry, size_t las if (first_entry == last_entry) return; - block->has_pinned = TRUE; - entry = sgen_pinning_get_entry (first_entry); end = sgen_pinning_get_entry (last_entry); @@ -1265,9 +1245,19 @@ mark_pinned_objects_in_block (MSBlockInfo *block, size_t first_entry, size_t las if (index == last_index) continue; obj = MS_BLOCK_OBJ (block, index); - MS_MARK_OBJECT_AND_ENQUEUE_CHECKED (obj, sgen_obj_get_descriptor (obj), block, queue); + if (!MS_OBJ_ALLOCED (obj, block)) + continue; + MS_MARK_OBJECT_AND_ENQUEUE (obj, sgen_obj_get_descriptor (obj), block, queue); + sgen_pin_stats_register_object (obj, GENERATION_OLD); last_index = index; } + + /* + * There might have been potential pinning "pointers" into this block, but none of + * them pointed to occupied slots, in which case we don't have to pin the block. + */ + if (last_index >= 0) + block->has_pinned = TRUE; } static inline void @@ -1315,6 +1305,7 @@ set_block_state (MSBlockInfo *block, gint32 new_state, gint32 expected_state) { SGEN_ASSERT (6, block->state == expected_state, "Block state incorrect before set"); block->state = new_state; + binary_protocol_block_set_state (block, MS_BLOCK_SIZE, expected_state, new_state); } /* @@ -1428,6 +1419,8 @@ sweep_start (void) for (j = 0; j < num_block_obj_sizes; ++j) free_blocks [j] = NULL; } + + sgen_array_list_remove_nulls (&allocated_blocks); } static void sweep_finish (void); @@ -1588,9 +1581,12 @@ static void sweep_blocks_job_func (void *thread_data_untyped, SgenThreadPoolJob *job) { volatile gpointer *slot; + MSBlockInfo *bl; SGEN_ARRAY_LIST_FOREACH_SLOT (&allocated_blocks, slot) { - sweep_block (BLOCK_UNTAG (*slot)); + bl = BLOCK_UNTAG (*slot); + if (bl) + sweep_block (bl); } SGEN_ARRAY_LIST_END_FOREACH_SLOT; mono_memory_write_barrier (); @@ -1637,8 +1633,6 @@ sweep_job_func (void *thread_data_untyped, SgenThreadPoolJob *job) } } - sgen_array_list_remove_nulls (&allocated_blocks); - /* * Concurrently sweep all the blocks to reduce workload during minor * pauses where we need certain blocks to be swept. At the start of @@ -1717,7 +1711,7 @@ static int count_nonpinned_nonref; static void count_nonpinned_callback (GCObject *obj, size_t size, void *data) { - GCVTable vtable = LOAD_VTABLE (obj); + GCVTable vtable = SGEN_LOAD_VTABLE (obj); if (SGEN_VTABLE_HAS_REFERENCES (vtable)) ++count_nonpinned_ref; @@ -1728,7 +1722,7 @@ count_nonpinned_callback (GCObject *obj, size_t size, void *data) static void count_pinned_callback (GCObject *obj, size_t size, void *data) { - GCVTable vtable = LOAD_VTABLE (obj); + GCVTable vtable = SGEN_LOAD_VTABLE (obj); if (SGEN_VTABLE_HAS_REFERENCES (vtable)) ++count_pinned_ref; @@ -2227,6 +2221,18 @@ major_print_gc_param_usage (void) /* * This callback is used to clear cards, move cards to the shadow table and do counting. */ +static void +major_iterate_block_ranges (sgen_cardtable_block_callback callback) +{ + MSBlockInfo *block; + gboolean has_references; + + FOREACH_BLOCK_HAS_REFERENCES_NO_LOCK (block, has_references) { + if (has_references) + callback ((mword)MS_BLOCK_FOR_BLOCK_INFO (block), MS_BLOCK_SIZE); + } END_FOREACH_BLOCK_NO_LOCK; +} + static void major_iterate_live_block_ranges (sgen_cardtable_block_callback callback) { @@ -2426,12 +2432,15 @@ static void major_scan_card_table (CardTableScanType scan_type, ScanCopyContext ctx) { MSBlockInfo *block; - gboolean has_references; + gboolean has_references, was_sweeping, skip_scan; if (!concurrent_mark) g_assert (scan_type == CARDTABLE_SCAN_GLOBAL); - major_finish_sweep_checking (); + if (scan_type != CARDTABLE_SCAN_GLOBAL) + SGEN_ASSERT (0, !sweep_in_progress (), "Sweep should be finished when we scan mod union card table"); + was_sweeping = sweep_in_progress (); + binary_protocol_major_card_table_scan_start (sgen_timestamp (), scan_type & CARDTABLE_SCAN_MOD_UNION); FOREACH_BLOCK_HAS_REFERENCES_NO_LOCK (block, has_references) { #ifdef PREFETCH_CARDS @@ -2449,8 +2458,36 @@ major_scan_card_table (CardTableScanType scan_type, ScanCopyContext ctx) if (!has_references) continue; + skip_scan = FALSE; - scan_card_table_for_block (block, scan_type, ctx); + if (scan_type == CARDTABLE_SCAN_GLOBAL) { + gpointer *card_start = (gpointer*) sgen_card_table_get_card_scan_address ((mword)MS_BLOCK_FOR_BLOCK_INFO (block)); + gboolean has_dirty_cards = FALSE; + int i; + for (i = 0; i < CARDS_PER_BLOCK / sizeof(gpointer); i++) { + if (card_start [i]) { + has_dirty_cards = TRUE; + break; + } + } + if (!has_dirty_cards) { + skip_scan = TRUE; + } else { + /* + * After the start of the concurrent collections, blocks change state + * to marking. We should not sweep it in that case. We can't race with + * sweep start since we are in a nursery collection. Also avoid CAS-ing + */ + if (sweep_in_progress ()) { + skip_scan = !ensure_block_is_checked_for_sweeping (__index, TRUE, NULL); + } else if (was_sweeping) { + /* Recheck in case sweep finished after dereferencing the slot */ + skip_scan = *sgen_array_list_get_slot (&allocated_blocks, __index) == 0; + } + } + } + if (!skip_scan) + scan_card_table_for_block (block, scan_type, ctx); } END_FOREACH_BLOCK_NO_LOCK; binary_protocol_major_card_table_scan_end (sgen_timestamp (), scan_type & CARDTABLE_SCAN_MOD_UNION); } @@ -2587,6 +2624,7 @@ sgen_marksweep_init_internal (SgenMajorCollector *collector, gboolean is_concurr collector->pin_major_object = pin_major_object; collector->scan_card_table = major_scan_card_table; collector->iterate_live_block_ranges = major_iterate_live_block_ranges; + collector->iterate_block_ranges = major_iterate_block_ranges; if (is_concurrent) { collector->update_cardtable_mod_union = update_cardtable_mod_union; collector->get_cardtable_mod_union_for_reference = major_get_cardtable_mod_union_for_reference; diff --git a/mono/sgen/sgen-pinning-stats.c b/mono/sgen/sgen-pinning-stats.c index 26fcfd116a..ab00a56d66 100644 --- a/mono/sgen/sgen-pinning-stats.c +++ b/mono/sgen/sgen-pinning-stats.c @@ -37,6 +37,9 @@ static gboolean do_pin_stats = FALSE; static PinStatAddress *pin_stat_addresses = NULL; static size_t pinned_byte_counts [PIN_TYPE_MAX]; +static size_t pinned_bytes_in_generation [GENERATION_MAX]; +static int pinned_objects_in_generation [GENERATION_MAX]; + static SgenPointerQueue pinned_objects = SGEN_POINTER_QUEUE_INIT (INTERNAL_MEM_STATISTICS); static SgenHashTable pinned_class_hash_table = SGEN_HASH_TABLE_INIT (INTERNAL_MEM_STATISTICS, INTERNAL_MEM_STAT_PINNED_CLASS, sizeof (PinnedClassEntry), g_str_hash, g_str_equal); @@ -66,6 +69,10 @@ sgen_pin_stats_reset (void) pin_stat_addresses = NULL; for (i = 0; i < PIN_TYPE_MAX; ++i) pinned_byte_counts [i] = 0; + for (i = 0; i < GENERATION_MAX; ++i) { + pinned_bytes_in_generation [i] = 0; + pinned_objects_in_generation [i] = 0; + } sgen_pointer_queue_clear (&pinned_objects); sgen_hash_table_clean (&pinned_class_hash_table); sgen_hash_table_clean (&global_remset_class_hash_table); @@ -78,6 +85,8 @@ sgen_pin_stats_register_address (char *addr, int pin_type) PinStatAddress *node; int pin_type_bit = 1 << pin_type; + if (!do_pin_stats) + return; while (*node_ptr) { node = *node_ptr; if (addr == node->addr) { @@ -153,13 +162,23 @@ register_vtable (GCVTable vtable, int pin_types) } void -sgen_pin_stats_register_object (GCObject *obj, size_t size) +sgen_pin_stats_register_object (GCObject *obj, int generation) { int pin_types = 0; + size_t size = 0; + + if (binary_protocol_is_enabled ()) { + size = sgen_safe_object_get_size (obj); + pinned_bytes_in_generation [generation] += size; + ++pinned_objects_in_generation [generation]; + } if (!do_pin_stats) return; + if (!size) + size = sgen_safe_object_get_size (obj); + pin_stats_count_object_from_tree (obj, size, pin_stat_addresses, &pin_types); sgen_pointer_queue_add (&pinned_objects, obj); @@ -183,12 +202,15 @@ sgen_pin_stats_register_global_remset (GCObject *obj) } void -sgen_pin_stats_print_class_stats (void) +sgen_pin_stats_report (void) { char *name; PinnedClassEntry *pinned_entry; GlobalRemsetClassEntry *remset_entry; + binary_protocol_pin_stats (pinned_objects_in_generation [GENERATION_NURSERY], pinned_bytes_in_generation [GENERATION_NURSERY], + pinned_objects_in_generation [GENERATION_OLD], pinned_bytes_in_generation [GENERATION_OLD]); + if (!do_pin_stats) return; diff --git a/mono/sgen/sgen-protocol-def.h b/mono/sgen/sgen-protocol-def.h index 41b8b83829..e6f1f775c9 100644 --- a/mono/sgen/sgen-protocol-def.h +++ b/mono/sgen/sgen-protocol-def.h @@ -449,6 +449,13 @@ MATCH_INDEX (BINARY_PROTOCOL_MATCH) IS_VTABLE_MATCH (FALSE) END_PROTOCOL_ENTRY_FLUSH +BEGIN_PROTOCOL_ENTRY4 (binary_protocol_pin_stats, TYPE_INT, objects_pinned_in_nursery, TYPE_SIZE, bytes_pinned_in_nursery, TYPE_INT, objects_pinned_in_major, TYPE_SIZE, bytes_pinned_in_major) +DEFAULT_PRINT () +IS_ALWAYS_MATCH (TRUE) +MATCH_INDEX (BINARY_PROTOCOL_MATCH) +IS_VTABLE_MATCH (FALSE) +END_PROTOCOL_ENTRY + #undef BEGIN_PROTOCOL_ENTRY0 #undef BEGIN_PROTOCOL_ENTRY1 #undef BEGIN_PROTOCOL_ENTRY2 diff --git a/mono/sgen/sgen-protocol.c b/mono/sgen/sgen-protocol.c index 2e59b6359a..ce504201f6 100644 --- a/mono/sgen/sgen-protocol.c +++ b/mono/sgen/sgen-protocol.c @@ -262,27 +262,33 @@ binary_protocol_check_file_overflow (void) * * The protocol entries that do flush have `FLUSH()` in their definition. */ -void +gboolean binary_protocol_flush_buffers (gboolean force) { #ifdef HAVE_UNISTD_H int num_buffers = 0, i; + BinaryProtocolBuffer *header; BinaryProtocolBuffer *buf; BinaryProtocolBuffer **bufs; if (binary_protocol_file == -1) - return; + return FALSE; if (!force && !try_lock_exclusive ()) - return; + return FALSE; - for (buf = binary_protocol_buffers; buf != NULL; buf = buf->next) + header = binary_protocol_buffers; + for (buf = header; buf != NULL; buf = buf->next) ++num_buffers; bufs = (BinaryProtocolBuffer **)sgen_alloc_internal_dynamic (num_buffers * sizeof (BinaryProtocolBuffer*), INTERNAL_MEM_BINARY_PROTOCOL, TRUE); - for (buf = binary_protocol_buffers, i = 0; buf != NULL; buf = buf->next, i++) + for (buf = header, i = 0; buf != NULL; buf = buf->next, i++) bufs [i] = buf; SGEN_ASSERT (0, i == num_buffers, "Binary protocol buffer count error"); + /* + * This might be incorrect when forcing, but all bets are off in that case, anyway, + * because we're trying to figure out a bug in the debugger. + */ binary_protocol_buffers = NULL; for (i = num_buffers - 1; i >= 0; --i) { @@ -294,6 +300,8 @@ binary_protocol_flush_buffers (gboolean force) if (!force) unlock_exclusive (); + + return TRUE; #endif } diff --git a/mono/sgen/sgen-protocol.h b/mono/sgen/sgen-protocol.h index 1c10d29d5c..adefb98070 100644 --- a/mono/sgen/sgen-protocol.h +++ b/mono/sgen/sgen-protocol.h @@ -154,7 +154,7 @@ enum { void binary_protocol_init (const char *filename, long long limit); gboolean binary_protocol_is_enabled (void); -void binary_protocol_flush_buffers (gboolean force); +gboolean binary_protocol_flush_buffers (gboolean force); #define BEGIN_PROTOCOL_ENTRY0(method) \ void method (void); diff --git a/mono/sgen/sgen-workers.c b/mono/sgen/sgen-workers.c index adc600a090..dfdff8c906 100644 --- a/mono/sgen/sgen-workers.c +++ b/mono/sgen/sgen-workers.c @@ -77,7 +77,7 @@ state_is_working_or_enqueued (State state) return state == STATE_WORKING || state == STATE_WORK_ENQUEUED; } -void +static void sgen_workers_ensure_awake (void) { State old_state; @@ -177,7 +177,8 @@ static void init_private_gray_queue (WorkerData *data) { sgen_gray_object_queue_init (&data->private_gray_queue, - sgen_get_major_collector ()->is_concurrent ? concurrent_enqueue_check : NULL); + sgen_get_major_collector ()->is_concurrent ? concurrent_enqueue_check : NULL, + FALSE); } static void @@ -354,10 +355,29 @@ sgen_workers_are_working (void) return state_is_working_or_enqueued (workers_state); } -SgenSectionGrayQueue* -sgen_workers_get_distribute_section_gray_queue (void) +void +sgen_workers_assert_gray_queue_is_empty (void) { - return &workers_distribute_gray_queue; + SGEN_ASSERT (0, sgen_section_gray_queue_is_empty (&workers_distribute_gray_queue), "Why is the workers gray queue not empty?"); +} + +void +sgen_workers_take_from_queue_and_awake (SgenGrayQueue *queue) +{ + gboolean wake = FALSE; + + for (;;) { + GrayQueueSection *section = sgen_gray_object_dequeue_section (queue); + if (!section) + break; + sgen_section_gray_queue_enqueue (&workers_distribute_gray_queue, section); + wake = TRUE; + } + + if (wake) { + SGEN_ASSERT (0, sgen_concurrent_collection_in_progress (), "Why is there work to take when there's no concurrent collection in progress?"); + sgen_workers_ensure_awake (); + } } #endif diff --git a/mono/sgen/sgen-workers.h b/mono/sgen/sgen-workers.h index 780d2eb6df..1a66c79a48 100644 --- a/mono/sgen/sgen-workers.h +++ b/mono/sgen/sgen-workers.h @@ -20,7 +20,6 @@ struct _WorkerData { void sgen_workers_init (int num_workers); void sgen_workers_stop_all_workers (void); void sgen_workers_start_all_workers (SgenObjectOperations *object_ops, SgenThreadPoolJob *finish_job); -void sgen_workers_ensure_awake (void); void sgen_workers_init_distribute_gray_queue (void); void sgen_workers_enqueue_job (SgenThreadPoolJob *job, gboolean enqueue); void sgen_workers_wait_for_jobs_finished (void); @@ -30,6 +29,7 @@ void sgen_workers_join (void); gboolean sgen_workers_have_idle_work (void); gboolean sgen_workers_all_done (void); gboolean sgen_workers_are_working (void); -SgenSectionGrayQueue* sgen_workers_get_distribute_section_gray_queue (void); +void sgen_workers_assert_gray_queue_is_empty (void); +void sgen_workers_take_from_queue_and_awake (SgenGrayQueue *queue); #endif diff --git a/mono/tests/Makefile.am b/mono/tests/Makefile.am index cf5eada2f4..41e4a9b9a4 100644 --- a/mono/tests/Makefile.am +++ b/mono/tests/Makefile.am @@ -1,7 +1,13 @@ SUBDIRS = assemblyresolve gc-descriptors +if INSTALL_MOBILE_STATIC +FEATUREFUL_RUNTIME_TEST = +else +FEATUREFUL_RUNTIME_TEST = test-appdomain-unload +endif + check-local: assemblyresolve/test/asm.dll testjit test-generic-sharing test-type-load test-cattr-type-load test-reflection-load-with-context test_platform \ - test-console-output test-messages test-env-options test-unhandled-exception-2 test-appdomain-unload test-process-stress rm-empty-logs + test-console-output test-messages test-env-options test-unhandled-exception-2 $(FEATUREFUL_RUNTIME_TEST) test-process-stress rm-empty-logs check-full: test-sgen check-local check-parallel: compile-tests check-full @@ -22,6 +28,14 @@ JITTEST_PROG_RUN = MONO_CFG_DIR=$(mono_build_root)/runtime/etc $(LIBTOOL) --mode RUNTIME_ARGS=--config tests-config --optimize=all --debug +if HOST_WIN32 +TEST_RUNNER_ARGS=--config tests-config --runtime $(if $(MONO_EXECUTABLE),$(shell cygpath -w -a $(MONO_EXECUTABLE) | sed 's/\\/\\\\/g'),mono) +else +TEST_RUNNER_ARGS=--config tests-config --runtime $(if $(MONO_EXECUTABLE),$(MONO_EXECUTABLE),mono) +endif + +TEST_RUNNER_ARGS += $(if $(V), --verbose,) + CLASS=$(mcs_topdir)/class/lib/$(DEFAULT_PROFILE) with_mono_path = MONO_PATH=$(CLASS) @@ -32,16 +46,27 @@ MKBUNDLE = \ PKG_CONFIG_PATH=$(top_builddir):$(PKG_CONFIG_PATH) \ $(RUNTIME) $(CLASS)/mkbundle.exe +if INSTALL_MOBILE_STATIC +PROFILE_MCS_FLAGS = -d:MOBILE,MOBILE_STATIC,MOBILE_LEGACY +endif + MCS_NO_LIB = $(RUNTIME) $(mcs_topdir)/class/lib/build/mcs.exe -unsafe -debug \ -noconfig -nologo \ -nowarn:0162 -nowarn:0168 -nowarn:0219 -nowarn:0414 -nowarn:0618 \ -nowarn:0169 -nowarn:1690 -nowarn:0649 -nowarn:0612 -nowarn:3021 \ - -nowarn:0197 + -nowarn:0197 $(PROFILE_MCS_FLAGS) MCS = $(MCS_NO_LIB) -lib:$(CLASS) ILASM = $(RUNTIME) $(CLASS)/ilasm.exe +if INSTALL_MOBILE_STATIC +TEST_RUNNER = ./test-runner.exe --runtime $(top_builddir)/runtime/mono-wrapper --mono-path "$(CLASS)" --aot-run-flags "$(AOT_RUN_FLAGS)" --aot-build-flags "$(AOT_BUILD_FLAGS)" +else +TEST_RUNNER = ./test-runner.exe --runtime $(top_builddir)/runtime/mono-wrapper --mono-path "$(CLASS)" +endif + + BENCHSRC=fib.cs random.cs nested-loops.cs ackermann.cs tight-loop.cs sieve.cs STRESS_TESTS_SRC= \ @@ -59,9 +84,70 @@ STRESS_TESTS_SRC= \ process-stress.cs \ assembly-load-stress.cs +BASE_TEST_MOBILE_STATIC_NOT_SUPPORTED= \ + remoting4.cs # Needs remoting support \ + remoting1.cs # Needs remoting support \ + remoting2.cs # Needs remoting support \ + remoting3.cs # Needs remoting support \ + remoting5.cs # Needs remoting support \ + appdomain.cs # Needs appdomain support \ + appdomain-client.cs # Needs appdomain support \ + appdomain-unload.cs # Needs appdomain support \ + appdomain-async-invoke.cs # Needs appdomain support \ + appdomain-thread-abort.cs # Needs appdomain support \ + appdomain1.cs # Needs appdomain support \ + appdomain2.cs # Needs appdomain support \ + appdomain-exit.cs # Needs appdomain support \ + assemblyresolve_event2.2.cs # Needs appdomain support \ + appdomain-unload-callback.cs # Needs appdomain support \ + appdomain-unload-doesnot-raise-pending-events.cs # Needs appdomain support \ + unload-appdomain-on-shutdown.cs # Needs appdomain support \ + bug-47295.cs # Needs SRE \ + loader.cs # Needs SRE \ + pinvoke2.cs # Needs SRE \ + generic-type-builder.2.cs # Needs SRE \ + dynamic-generic-size.cs # Needs SRE \ + cominterop.cs # Needs COM \ + dynamic-method-access.2.cs # Need SRE \ + dynamic-method-finalize.2.cs # Need SRE \ + dynamic-method-stack-traces.cs # Need SRE\ + generic_type_definition.2.cs # Need SRE \ + bug-333798-tb.2.cs # Need SRE \ + bug-335131.2.cs # Need SRE \ + bug-322722_patch_bx.2.cs # Need SRE\ + bug-322722_dyn_method_throw.2.cs # Need SRE \ + bug-389886-2.cs # Need SRE \ + bug-349190.2.cs # Need SRE \ + bug-389886-sre-generic-interface-instances.cs # Need SRE \ + bug-462592.cs # Need SRE \ + bug-575941.cs # Need SRE \ + bug-389886-3.cs # Need SRE \ + constant-division.cs # Need SRE \ + dynamic-method-resurrection.cs # Need SRE \ + bug-80307.cs # Need System.Web \ + assembly_append_ordering.cs # Need SRE \ + bug-544446.cs # Needs AppDomains / TranparentProxy \ + bug-36848.cs # Needs AppDomains / TranparentProxy \ + generic-marshalbyref.2.cs # Needs AppDomains \ + stackframes-async.2.cs # Needs AppDomains \ + transparentproxy.cs # Needs AppDomains / TranparentProxy \ + bug-48015.cs # Needs AppDomains / TranparentProxy \ + delegate9.cs # Needs AppDomains \ + marshal-valuetypes.cs # Needs AppDomains \ + xdomain-threads.cs # Needs AppDomains \ + monitor.cs # Needs AppDomains \ + generic-xdomain.2.cs # Needs AppDomains \ + threadpool-exceptions7.cs # Needs AppDomains \ + cross-domain.cs # Needs AppDomains \ + generic-unloading.2.cs # Needs AppDomains \ + thread6.cs # On MOBILE, ThreadAbortException doesn't have necessary field for this test + # Disabled until ?mcs is fixed # bug-331958.cs -BASE_TEST_CS_SRC= \ +# Note: only add tests that are compatible with mobile_static to this category +BASE_TEST_CS_SRC_UNIVERSAL= \ + generic-unloading-sub.2.cs \ + create-instance.cs \ bug-2907.cs \ array-init.cs \ arraylist.cs \ @@ -71,7 +157,6 @@ BASE_TEST_CS_SRC= \ assemblyresolve_event4.cs \ checked.cs \ char-isnumber.cs \ - create-instance.cs \ field-layout.cs \ pack-layout.cs \ pack-bug.cs \ @@ -108,7 +193,6 @@ BASE_TEST_CS_SRC= \ typeof-ptr.cs \ static-constructor.cs \ pinvoke.cs \ - pinvoke2.cs \ pinvoke3.cs \ pinvoke11.cs \ pinvoke13.cs \ @@ -174,13 +258,6 @@ BASE_TEST_CS_SRC= \ jit-float.cs \ pop.cs \ time.cs \ - appdomain.cs \ - appdomain1.cs \ - appdomain2.cs \ - appdomain-client.cs \ - appdomain-unload.cs \ - appdomain-async-invoke.cs \ - loader.cs \ pointer.cs \ hashcode.cs \ delegate1.cs \ @@ -190,16 +267,10 @@ BASE_TEST_CS_SRC= \ delegate6.cs \ delegate7.cs \ delegate8.cs \ - delegate9.cs \ delegate10.cs \ delegate11.cs \ delegate12.cs \ delegate13.cs \ - remoting1.cs \ - remoting2.cs \ - remoting3.cs \ - remoting4.cs \ - remoting5.cs \ largeexp.cs \ largeexp2.cs \ marshalbyref1.cs \ @@ -220,11 +291,9 @@ BASE_TEST_CS_SRC= \ marshal8.cs \ marshal9.cs \ marshalbool.cs \ - marshal-valuetypes.cs \ test-byval-in-struct.cs \ thread.cs \ thread5.cs \ - thread6.cs \ thread-static.cs \ thread-static-init.cs \ context-static.cs \ @@ -244,12 +313,9 @@ BASE_TEST_CS_SRC= \ threadpool-exceptions4.cs \ threadpool-exceptions5.cs \ threadpool-exceptions6.cs \ - threadpool-exceptions7.cs \ base-definition.cs \ bug-27420.cs \ - bug-47295.cs \ bug-46781.cs \ - bug-48015.cs \ bug-42136.cs \ bug-59286.cs \ bug-70561.cs \ @@ -260,8 +326,6 @@ BASE_TEST_CS_SRC= \ bug-323114.cs \ bug-Xamarin-5278.cs \ interlocked.cs \ - cross-domain.cs \ - appdomain-exit.cs \ delegate-async-exit.cs \ delegate-delegate-exit.cs \ delegate-exit.cs \ @@ -278,16 +342,13 @@ BASE_TEST_CS_SRC= \ main-returns.cs \ subthread-exit.cs \ desweak.cs \ - cominterop.cs \ exists.cs \ handleref.cs \ - transparentproxy.cs \ dbnull-missing.cs \ test-type-ctor.cs \ soft-float-tests.cs \ thread-exit.cs \ finalize-parent.cs \ - assemblyresolve_event2.2.cs \ interlocked-2.2.cs \ pinvoke-2.2.cs \ bug-78431.2.cs \ @@ -295,7 +356,6 @@ BASE_TEST_CS_SRC= \ catch-generics.2.cs \ event-get.2.cs \ safehandle.2.cs \ - stackframes-async.2.cs \ module-cctor-loader.2.cs \ generics-invoke-byref.2.cs \ generic-signature-compare.2.cs \ @@ -317,14 +377,10 @@ BASE_TEST_CS_SRC= \ generic-virtual2.2.cs \ generic-valuetype-interface.2.cs \ generic-getgenericarguments.2.cs \ - generic-type-builder.2.cs \ generic-synchronized.2.cs \ generic-delegate-ctor.2.cs \ generic-array-iface-set.2.cs \ generic-typedef.2.cs \ - generic-marshalbyref.2.cs \ - generic-xdomain.2.cs \ - dynamic-generic-size.cs \ bug-431413.2.cs \ bug-459285.2.cs \ generic-virtual-invoke.2.cs \ @@ -340,27 +396,17 @@ BASE_TEST_CS_SRC= \ bug-479763.2.cs \ bug-616463.cs \ bug-80392.2.cs \ - dynamic-method-access.2.cs \ - dynamic-method-finalize.2.cs \ - dynamic-method-stack-traces.cs \ bug-82194.2.cs \ anonarray.2.cs \ ienumerator-interfaces.2.cs \ array-enumerator-ifaces.2.cs \ generic_type_definition_encoding.2.cs \ - generic_type_definition.2.cs \ bug-333798.2.cs \ - bug-333798-tb.2.cs \ - bug-335131.2.cs \ - bug-322722_patch_bx.2.cs \ bug-348522.2.cs \ bug-340662_bug.cs \ - bug-322722_dyn_method_throw.2.cs \ - bug-389886-2.cs \ bug-325283.2.cs \ thunks.cs \ winx64structs.cs \ - bug-349190.2.cs \ nullable_boxing.2.cs \ valuetype-equals.cs \ custom-modifiers.2.cs \ @@ -369,44 +415,30 @@ BASE_TEST_CS_SRC= \ bug-324535.cs \ modules.cs \ bug-81673.cs \ - bug-36848.cs \ bug-81691.cs \ - bug-80307.cs \ bug-415577.cs \ filter-stack.cs \ vararg2.cs \ - bug-389886-sre-generic-interface-instances.cs \ bug-461867.cs \ bug-461941.cs \ bug-461261.cs \ bug-400716.cs \ - bug-462592.cs \ bug-459094.cs \ - generic-unloading.2.cs \ - generic-unloading-sub.2.cs \ bug-467456.cs \ - appdomain-unload-callback.cs \ bug-508538.cs \ bug-472692.2.cs \ gchandles.cs \ interlocked-3.cs \ interlocked-4.2.cs \ - appdomain-thread-abort.cs \ - xdomain-threads.cs \ w32message.cs \ - bug-544446.cs \ gc-altstack.cs \ large-gc-bitmap.cs \ bug-561239.cs \ bug-562150.cs \ - bug-575941.cs \ bug-599469.cs \ - bug-389886-3.cs \ - monitor.cs \ monitor-resurrection.cs \ monitor-wait-abort.cs \ monitor-abort.cs \ - dynamic-method-resurrection.cs \ bug-666008.cs \ bug-685908.cs \ sgen-long-vtype.cs \ @@ -418,13 +450,10 @@ BASE_TEST_CS_SRC= \ bug-bxc-795.cs \ bug-3903.cs \ async-with-cb-throws.cs \ - appdomain-unload-doesnot-raise-pending-events.cs \ bug-6148.cs \ - assembly_append_ordering.cs \ bug-10127.cs \ bug-18026.cs \ allow-synchronous-major.cs \ - unload-appdomain-on-shutdown.cs \ block_guard_restore_aligment_on_exit.cs \ thread_static_gc_layout.cs \ sleep.cs \ @@ -436,7 +465,19 @@ BASE_TEST_CS_SRC= \ pinvoke_ppci.cs \ pinvoke_ppcf.cs \ pinvoke_ppcd.cs \ - bug-29585.cs + bug-29585.cs \ + priority.cs \ + abort-cctor.cs \ + reference-loader.cs + +if INSTALL_MOBILE_STATIC +BASE_TEST_CS_SRC= \ + $(BASE_TEST_CS_SRC_UNIVERSAL) +else +BASE_TEST_CS_SRC= \ + $(BASE_TEST_MOBILE_STATIC_NOT_SUPPORTED) \ + $(BASE_TEST_CS_SRC_UNIVERSAL) +endif TEST_CS_SRC_DIST= \ $(BASE_TEST_CS_SRC) \ @@ -591,6 +632,52 @@ else COOP_DISABLED_TESTS= endif +if INSTALL_MOBILE_STATIC +# Tests which rely on TypeLoadExceptions +# In full-aot mode, these cause the relevant methods to be not AOTed. +PROFILE_DISABLED_TESTS = \ + typeload-unaligned.exe \ + field-access.exe \ + invalid_generic_instantiation.exe \ + bug-481403.exe \ + array_ldelema.exe \ + array_load_exception.exe \ + bug445361.exe \ + generic-type-load-exception.2.exe \ + invalid-token.exe \ + call_missing_method.exe \ + call_missing_class.exe \ + ldfld_missing_field.exe \ + ldfld_missing_class.exe \ + vt-sync-method.exe + +# Tests which rely on remoting +PROFILE_DISABLED_TESTS += \ + context-static.exe \ + bug-415577.exe \ + generic-marshalbyref.2.exe \ + unhandled-exception-7.exe + +# Tests which use unsupported pinvoke+full aot +# functionality +PROFILE_DISABLED_TESTS += \ + marshal.exe \ + marshal2.exe \ + marshal6.exe \ + marshal7.exe \ + marshal8.exe \ + pinvoke-2.2.exe \ + pinvoke3.exe \ + thunks.exe + +# Tests which load assemblies which are not +# in the mobile_static profile +PROFILE_DISABLED_TESTS += \ + assembly-load-remap.exe +else +PROFILE_DISABLED_TESTS= +endif + # The two finalizer tests only work under sgen # gc-altstack.exe fails under boehm because it has no support for altstack # bug-459094.exe creates an extremely deep directory tree @@ -605,7 +692,8 @@ DISABLED_TESTS= \ bug-Xamarin-5278.exe \ $(PLATFORM_DISABLED_TESTS) \ $(EXTRA_DISABLED_TESTS) \ - $(COOP_DISABLED_TESTS) + $(COOP_DISABLED_TESTS) \ + $(PROFILE_DISABLED_TESTS) DISABLED_TESTS_WRENCH= \ $(DISABLED_TESTS) \ @@ -625,7 +713,14 @@ AOT_DISABLED_TESTS=constraints-load.exe TEST_CSC_SRC= \ vararg.cs -TEST_IL_SRC= \ +# constraints-load.il: +# Failed to load method 0x6000007 from '..../mono/tests/constraints-load.exe' due to +# Could not resolve type with token 01000002 assembly:mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 type:System.BrokenIComparable`1 member:. +IL_SRC_MOBILE_STATIC_NOT_SUPPORTED= \ + constraints-load.il \ + bug-515884.il + +TEST_IL_SRC_UNIVERSAL= \ field-access.il \ method-access.il \ ldftn-access.il \ @@ -684,40 +779,75 @@ TEST_IL_SRC= \ bug-463303.il \ bug469742.2.il \ bug-528055.il \ - constraints-load.il \ array_load_exception.il \ bug-481403.il \ interface-with-static-method.il \ - bug-515884.il \ bug-633291.il \ delegate-with-null-target.il \ bug-318677.il \ gsharing-valuetype-layout.il \ invalid_generic_instantiation.il +if INSTALL_MOBILE_STATIC +TEST_IL_SRC= \ + $(TEST_IL_SRC_UNIVERSAL) +else +TEST_IL_SRC= \ + $(TEST_IL_SRC_MOBILE_STATIC_NOT_SUPPORTED) \ + $(TEST_IL_SRC_UNIVERSAL) +endif # pre-requisite test sources: files that are not test themselves # but that need to be compiled PREREQ_IL_SRC=event-il.il module-cctor.il PREREQ_CS_SRC= -PREREQ_IL_DLL_SRC=event-il.il module-cctor.il -PREREQ_CS_DLL_SRC= +PREREQ_IL_DLL_SRC= +PREREQ_CS_DLL_SRC=TestingReferenceAssembly.cs TestingReferenceReferenceAssembly.cs -PREREQSI_IL=$(PREREQ_IL_SRC:.il=.exe) -PREREQSI_CS=$(PREREQ_CS_SRC:.cs=.exe) +PREREQSI_IL=$(PREREQ_IL_SRC:.il=.exe) \ + $(PREREQ_IL_DLL_SRC:.il=.dll) +PREREQSI_CS=$(PREREQ_CS_SRC:.cs=.exe) \ + $(PREREQ_CS_DLL_SRC:.cs=.dll) TESTSI_CS=$(TEST_CS_SRC:.cs=.exe) TESTSI_IL=$(TEST_IL_SRC:.il=.exe) TESTBS=$(BENCHSRC:.cs=.exe) STRESS_TESTS=$(STRESS_TESTS_SRC:.cs=.exe) +PREREQSI_IL_AOT=$(PREREQ_IL_SRC:.il=.exe$(PLATFORM_AOT_SUFFIX)) \ + $(PREREQ_IL_DLL_SRC:.il=.dll$(PLATFORM_AOT_SUFFIX)) +PREREQSI_CS_AOT=$(PREREQ_CS_SRC:.cs=.exe$(PLATFORM_AOT_SUFFIX)) \ + $(PREREQ_CS_DLL_SRC:.cs=.dll$(PLATFORM_AOT_SUFFIX)) + EXTRA_DIST=test-driver test-runner.cs $(TEST_CS_SRC_DIST) $(TEST_IL_SRC) \ $(BENCHSRC) $(STRESS_TESTS_SRC) stress-runner.pl $(PREREQ_IL_SRC) $(PREREQ_CS_SRC) %.exe: %.il $(ILASM) -out:$@ $< -%.exe: %.cs TestDriver.dll - $(MCS) -r:System.dll -r:System.Xml.dll -r:System.Core.dll -r:TestDriver.dll -r:Mono.Posix.dll -out:$@ $< +if !INSTALL_MOBILE_STATIC +TEST_DRIVER_HARD_KILL_FEATURE=-r:Mono.Posix.dll +endif + +if INSTALL_MOBILE_STATIC +TEST_DRIVER_DEPEND=TestDriver.dll$(PLATFORM_AOT_SUFFIX) +else +TEST_DRIVER_DEPEND=TestDriver.dll +endif + +%.exe: %.cs $(TEST_DRIVER_DEPEND) + $(MCS) -r:System.dll -r:System.Xml.dll -r:System.Core.dll -r:TestDriver.dll $(TEST_DRIVER_HARD_KILL_FEATURE) -out:$@ $< + +%.dll: %.cs + $(MCS) -r:System.dll -target:library -out:$@ $< + +TestingReferenceReferenceAssembly.dll: TestingReferenceReferenceAssembly.cs TestingReferenceAssembly.dll + $(MCS) -r:TestingReferenceAssembly.dll -target:library -out:$@ $< + +%.exe$(PLATFORM_AOT_SUFFIX): %.exe + $(RUNTIME) $(AOT_BUILD_FLAGS) $< + +%.dll$(PLATFORM_AOT_SUFFIX): %.dll + $(RUNTIME) $(AOT_BUILD_FLAGS) $< # mkbundle works on ppc, but the pkg-config POC doesn't when run with make test if POWERPC @@ -741,8 +871,22 @@ test_platform: test-eglib-remap endif endif +AOT_EXTRA_LIBS = \ +bug-382986-lib.dll$(PLATFORM_AOT_SUFFIX) \ +bug-324535-il.dll$(PLATFORM_AOT_SUFFIX) \ +bug-36848-a.dll$(PLATFORM_AOT_SUFFIX) \ +bug-81691-b.dll$(PLATFORM_AOT_SUFFIX) \ +bug-327438.2.exe$(PLATFORM_AOT_SUFFIX) \ +bug-81466-lib.dll$(PLATFORM_AOT_SUFFIX) + +if INSTALL_MOBILE_STATIC +prereqs: $(PREREQSI_IL_AOT) $(PREREQSI_CS_AOT) $(AOT_EXTRA_LIBS) +else +prereqs: $(PREREQSI_IL) $(PREREQSI_CS) +endif + # Target to precompile the test executables -tests: $(TESTSI_CS) $(TESTSI_IL) $(TESTBS) libtest.la $(PREREQSI_IL) $(PREREQSI_CS) $(GSHARED_TESTS) +tests: $(TESTSI_CS) $(TESTSI_IL) $(TESTBS) libtest.la prereqs $(GSHARED_TESTS) # # Test that no symbols are missed in eglib-remap.h @@ -780,11 +924,14 @@ test-sgen : sgen-tests # Precompile the test assemblies in parallel compile-tests: $(MAKE) -j4 $(TESTSI_CS) $(TESTSI_IL) $(TESTBS) libtest.la $(PREREQSI_IL) $(PREREQSI_CS) +if INSTALL_MOBILE_STATIC + $(MAKE) $(PREREQSI_IL_AOT) $(PREREQSI_CS_AOT) $(AOT_EXTRA_LIBS) +endif # Remove empty .stdout and .stderr files for wrench rm-empty-logs: @echo "Removing empty logs..." - @find . '(' -name "*.stdout" -o -name "*.stderr" ')' -empty -exec rm {} \; + find . '(' -name "*.stdout" -o -name "*.stderr" ')' -size 0 -exec rm {} \; assemblyresolve/test/asm.dll: $(MAKE) -C assemblyresolve prereq @@ -867,11 +1014,11 @@ runtest: $(TESTSI_CS) $(TESTSI_IL) $(TESTBS) libtest.la $(PREREQSI_IL) $(PREREQS runtest-managed: test-runner.exe $(TESTSI_CS) $(TESTSI_IL) $(TESTBS) libtest.la $(PREREQSI_IL) $(PREREQSI_CS) @if [ "x$$CI" = "x1" ]; then disabled_tests="$(DISABLED_TESTS_WRENCH)"; else disabled_tests="$(DISABLED_TESTS)"; fi; \ - $(RUNTIME) --debug ./test-runner.exe -j a --testsuite-name "runtime" --timeout 300 --disabled "$${disabled_tests}" $(TESTSI_CS) $(TESTBS) $(TESTSI_IL) + $(RUNTIME) --debug $(TEST_RUNNER) $(TEST_RUNNER_ARGS) -j a --testsuite-name "runtime" --timeout 300 --disabled "$${disabled_tests}" $(TESTSI_CS) $(TESTBS) $(TESTSI_IL) runtest-managed-serial: test-runner.exe $(TESTSI_CS) $(TESTSI_IL) $(TESTBS) libtest.la $(PREREQSI_IL) $(PREREQSI_CS) @if [ "x$$CI" = "x1" ]; then disabled_tests="$(DISABLED_TESTS_WRENCH)"; else disabled_tests="$(DISABLED_TESTS)"; fi; \ - $(RUNTIME) --debug ./test-runner.exe -j 1 --testsuite-name "runtime" --disabled "$${disabled_tests}" $(TESTSI_CS) $(TESTBS) $(TESTSI_IL) + $(RUNTIME) --debug $(TEST_RUNNER) $(TEST_RUNNER_ARGS) -j 1 --testsuite-name "runtime" --disabled "$${disabled_tests}" $(TESTSI_CS) $(TESTBS) $(TESTSI_IL) testjit: @if test x$(M) != x0; then $(MAKE) runtest-managed; else $(MAKE) runtest; fi @@ -921,7 +1068,7 @@ testbundle: console.exe @- rm -rf a.out EXTRA_DIST += load-missing.il t-missing.cs load-exceptions.cs -test-type-load: TestDriver.dll +test-type-load: $(TEST_DRIVER_DEPEND) @$(ILASM) /dll /output:load-missing.dll $(srcdir)/load-missing.il > /dev/null @$(MCS) -t:library -out:t.dll -d:FOUND $(srcdir)/t-missing.cs @$(MCS) -r:TestDriver.dll -r:load-missing.dll -r:t.dll -out:load-exceptions.exe $(srcdir)/load-exceptions.cs @@ -930,7 +1077,7 @@ test-type-load: TestDriver.dll @$(RUNTIME) load-exceptions.exe > load-exceptions.exe.stdout 2> load-exceptions.exe.stderr EXTRA_DIST += custom-attr-errors.cs custom-attr-errors-lib.cs -test-cattr-type-load: TestDriver.dll custom-attr-errors.cs custom-attr-errors-lib.cs +test-cattr-type-load: $(TEST_DRIVER_DEPEND) custom-attr-errors.cs custom-attr-errors-lib.cs $(MCS) -D:WITH_MEMBERS /t:library $(srcdir)/custom-attr-errors-lib.cs $(MCS) -r:TestDriver.dll -r:custom-attr-errors-lib.dll $(srcdir)/custom-attr-errors.cs $(MCS) /t:library $(srcdir)/custom-attr-errors-lib.cs @@ -964,13 +1111,15 @@ if !S390X $(MAKE) sgen-bridge2-tests endif -SGEN_REGULAR_TESTS = \ +SGEN_REGULAR_TESTS_MOBILE_STATIC_NOT_SUPPORTED = \ + sgen-domain-unload.exe \ + sgen-domain-unload-2.exe + +SGEN_REGULAR_TESTS_UNIVERSAL = \ finalizer-wait.exe \ critical-finalizers.exe \ sgen-descriptors.exe \ sgen-gshared-vtype.exe \ - sgen-domain-unload.exe \ - sgen-domain-unload-2.exe \ sgen-weakref-stress.exe \ sgen-cementing-stress.exe \ sgen-case-23400.exe \ @@ -979,6 +1128,15 @@ SGEN_REGULAR_TESTS = \ gc-graystack-stress.exe \ bug-17590.exe +if INSTALL_MOBILE_STATIC +SGEN_REGULAR_TESTS= \ + $(SGEN_REGULAR_TESTS_UNIVERSAL) +else +SGEN_REGULAR_TESTS= \ + $(SGEN_REGULAR_TESTS_MOBILE_STATIC_NOT_SUPPORTED) \ + $(SGEN_REGULAR_TESTS_UNIVERSAL) +endif + sgen-regular-tests: $(SGEN_REGULAR_TESTS) $(MAKE) sgen-regular-tests-plain $(MAKE) sgen-regular-tests-ms-conc @@ -990,21 +1148,21 @@ sgen-regular-tests: $(SGEN_REGULAR_TESTS) $(MAKE) sgen-regular-tests-ms-split-clear-at-gc sgen-regular-tests-plain: $(SGEN_REGULAR_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="" MONO_GC_PARAMS="" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_REGULAR_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="" MONO_GC_PARAMS="" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_REGULAR_TESTS) sgen-regular-tests-ms-conc: $(SGEN_REGULAR_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="" MONO_GC_PARAMS="major=marksweep-conc" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_REGULAR_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="" MONO_GC_PARAMS="major=marksweep-conc" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_REGULAR_TESTS) sgen-regular-tests-ms-conc-split: $(SGEN_REGULAR_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="" MONO_GC_PARAMS="major=marksweep-conc,minor=split" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_REGULAR_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="" MONO_GC_PARAMS="major=marksweep-conc,minor=split" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_REGULAR_TESTS) sgen-regular-tests-ms-split: $(SGEN_REGULAR_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="" MONO_GC_PARAMS="minor=split" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_REGULAR_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="" MONO_GC_PARAMS="minor=split" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_REGULAR_TESTS) sgen-regular-tests-ms-split-95: $(SGEN_REGULAR_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="" MONO_GC_PARAMS="minor=split,alloc-ratio=95" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_REGULAR_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="" MONO_GC_PARAMS="minor=split,alloc-ratio=95" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_REGULAR_TESTS) sgen-regular-tests-plain-clear-at-gc: $(SGEN_REGULAR_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="clear-at-gc" MONO_GC_PARAMS="" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_REGULAR_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="clear-at-gc" MONO_GC_PARAMS="" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_REGULAR_TESTS) sgen-regular-tests-ms-conc-clear-at-gc: $(SGEN_REGULAR_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="clear-at-gc" MONO_GC_PARAMS="major=marksweep-conc" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_REGULAR_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="clear-at-gc" MONO_GC_PARAMS="major=marksweep-conc" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_REGULAR_TESTS) sgen-regular-tests-ms-split-clear-at-gc: $(SGEN_REGULAR_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="clear-at-gc" MONO_GC_PARAMS="minor=split" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_REGULAR_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="clear-at-gc" MONO_GC_PARAMS="minor=split" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_REGULAR_TESTS) SGEN_TOGGLEREF_TESTS= \ sgen-toggleref.exe @@ -1020,21 +1178,21 @@ sgen-toggleref-tests: $(SGEN_TOGGLEREF_TESTS) $(MAKE) sgen-toggleref-tests-ms-split-clear-at-gc sgen-toggleref-tests-plain: $(SGEN_TOGGLEREF_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="" MONO_GC_PARAMS="toggleref-test" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_TOGGLEREF_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="" MONO_GC_PARAMS="toggleref-test" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_TOGGLEREF_TESTS) sgen-toggleref-tests-ms-conc: $(SGEN_TOGGLEREF_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="" MONO_GC_PARAMS="toggleref-test,major=marksweep-conc" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_TOGGLEREF_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="" MONO_GC_PARAMS="toggleref-test,major=marksweep-conc" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_TOGGLEREF_TESTS) sgen-toggleref-tests-ms-conc-split: $(SGEN_TOGGLEREF_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="" MONO_GC_PARAMS="toggleref-test,major=marksweep-conc,minor=split" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_TOGGLEREF_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="" MONO_GC_PARAMS="toggleref-test,major=marksweep-conc,minor=split" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_TOGGLEREF_TESTS) sgen-toggleref-tests-ms-split: $(SGEN_TOGGLEREF_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="" MONO_GC_PARAMS="toggleref-test,minor=split" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_TOGGLEREF_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="" MONO_GC_PARAMS="toggleref-test,minor=split" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_TOGGLEREF_TESTS) sgen-toggleref-tests-ms-split-95: $(SGEN_TOGGLEREF_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="" MONO_GC_PARAMS="toggleref-test,minor=split,alloc-ratio=95" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_TOGGLEREF_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="" MONO_GC_PARAMS="toggleref-test,minor=split,alloc-ratio=95" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_TOGGLEREF_TESTS) sgen-toggleref-tests-plain-clear-at-gc: $(SGEN_TOGGLEREF_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="clear-at-gc" MONO_GC_PARAMS="toggleref-test" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_TOGGLEREF_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="clear-at-gc" MONO_GC_PARAMS="toggleref-test" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_TOGGLEREF_TESTS) sgen-toggleref-tests-ms-conc-clear-at-gc: $(SGEN_TOGGLEREF_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="clear-at-gc" MONO_GC_PARAMS="toggleref-test,major=marksweep-conc" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_TOGGLEREF_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="clear-at-gc" MONO_GC_PARAMS="toggleref-test,major=marksweep-conc" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_TOGGLEREF_TESTS) sgen-toggleref-tests-ms-split-clear-at-gc: $(SGEN_TOGGLEREF_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="clear-at-gc" MONO_GC_PARAMS="toggleref-test,minor=split" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_TOGGLEREF_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="clear-at-gc" MONO_GC_PARAMS="toggleref-test,minor=split" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_TOGGLEREF_TESTS) SGEN_BRIDGE_TESTS= \ sgen-bridge.exe \ @@ -1051,21 +1209,21 @@ sgen-bridge-tests: $(SGEN_BRIDGE_TESTS) $(MAKE) sgen-bridge-tests-ms-split-tarjan-bridge sgen-bridge-tests-plain: $(SGEN_BRIDGE_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=Bridge" MONO_GC_PARAMS="" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=Bridge" MONO_GC_PARAMS="" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE_TESTS) sgen-bridge-tests-ms-conc: $(SGEN_BRIDGE_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=Bridge" MONO_GC_PARAMS="major=marksweep-conc" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=Bridge" MONO_GC_PARAMS="major=marksweep-conc" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE_TESTS) sgen-bridge-tests-ms-split: $(SGEN_BRIDGE_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=Bridge" MONO_GC_PARAMS="minor=split" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=Bridge" MONO_GC_PARAMS="minor=split" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE_TESTS) sgen-bridge-tests-plain-new-bridge: $(SGEN_BRIDGE_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=Bridge" MONO_GC_PARAMS="bridge-implementation=new" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=Bridge" MONO_GC_PARAMS="bridge-implementation=new" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE_TESTS) sgen-bridge-tests-ms-conc-new-bridge: $(SGEN_BRIDGE_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=Bridge" MONO_GC_PARAMS="bridge-implementation=new,major=marksweep-conc" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=Bridge" MONO_GC_PARAMS="bridge-implementation=new,major=marksweep-conc" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE_TESTS) sgen-bridge-tests-ms-split-new-bridge: $(SGEN_BRIDGE_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=Bridge" MONO_GC_PARAMS="bridge-implementation=new,minor=split" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=Bridge" MONO_GC_PARAMS="bridge-implementation=new,minor=split" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE_TESTS) sgen-bridge-tests-plain-tarjan-bridge: $(SGEN_BRIDGE_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=Bridge" MONO_GC_PARAMS="bridge-implementation=tarjan" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=Bridge" MONO_GC_PARAMS="bridge-implementation=tarjan" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE_TESTS) sgen-bridge-tests-ms-split-tarjan-bridge: $(SGEN_BRIDGE_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=Bridge" MONO_GC_PARAMS="bridge-implementation=tarjan,minor=split" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=Bridge" MONO_GC_PARAMS="bridge-implementation=tarjan,minor=split" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE_TESTS) SGEN_BRIDGE2_TESTS= \ sgen-bridge-xref.exe @@ -1081,22 +1239,21 @@ sgen-bridge2-tests: $(SGEN_BRIDGE2_TESTS) $(MAKE) sgen-bridge2-tests-ms-split-tarjan-bridge sgen-bridge2-tests-plain: $(SGEN_BRIDGE2_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=2Bridge" MONO_GC_PARAMS="" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE2_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=2Bridge" MONO_GC_PARAMS="" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE2_TESTS) sgen-bridge2-tests-ms-conc: $(SGEN_BRIDGE2_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=2Bridge" MONO_GC_PARAMS="major=marksweep-conc" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE2_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=2Bridge" MONO_GC_PARAMS="major=marksweep-conc" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE2_TESTS) sgen-bridge2-tests-ms-split: $(SGEN_BRIDGE2_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=2Bridge" MONO_GC_PARAMS="minor=split" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE2_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=2Bridge" MONO_GC_PARAMS="minor=split" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE2_TESTS) sgen-bridge2-tests-plain-new-bridge: $(SGEN_BRIDGE2_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=2Bridge" MONO_GC_PARAMS="bridge-implementation=new" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE2_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=2Bridge" MONO_GC_PARAMS="bridge-implementation=new" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE2_TESTS) sgen-bridge2-tests-ms-conc-new-bridge: $(SGEN_BRIDGE2_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=2Bridge" MONO_GC_PARAMS="bridge-implementation=new,major=marksweep-conc" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE2_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=2Bridge" MONO_GC_PARAMS="bridge-implementation=new,major=marksweep-conc" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE2_TESTS) sgen-bridge2-tests-ms-split-new-bridge: $(SGEN_BRIDGE2_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=2Bridge" MONO_GC_PARAMS="bridge-implementation=new,minor=split" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE2_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=2Bridge" MONO_GC_PARAMS="bridge-implementation=new,minor=split" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE2_TESTS) sgen-bridge2-tests-plain-tarjan-bridge: $(SGEN_BRIDGE2_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=2Bridge" MONO_GC_PARAMS="bridge-implementation=tarjan" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE2_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=2Bridge" MONO_GC_PARAMS="bridge-implementation=tarjan" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE2_TESTS) sgen-bridge2-tests-ms-split-tarjan-bridge: $(SGEN_BRIDGE2_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=2Bridge" MONO_GC_PARAMS="bridge-implementation=tarjan,minor=split" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE2_TESTS) - + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=2Bridge" MONO_GC_PARAMS="bridge-implementation=tarjan,minor=split" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE2_TESTS) SGEN_BRIDGE3_TESTS= \ sgen-bridge-gchandle.exe @@ -1112,21 +1269,21 @@ sgen-bridge3-tests: $(SGEN_BRIDGE3_TESTS) $(MAKE) sgen-bridge3-tests-ms-split-tarjan-bridge sgen-bridge3-tests-plain: $(SGEN_bridge3_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=3Bridge" MONO_GC_PARAMS="" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE3_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=3Bridge" MONO_GC_PARAMS="" $(RUNTIME) $(TEST_RUNNER) --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE3_TESTS) sgen-bridge3-tests-ms-conc: $(SGEN_BRIDGE3_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=3Bridge" MONO_GC_PARAMS="major=marksweep-conc" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE3_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=3Bridge" MONO_GC_PARAMS="major=marksweep-conc" $(RUNTIME) $(TEST_RUNNER) --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE3_TESTS) sgen-bridge3-tests-ms-split: $(SGEN_BRIDGE3_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=3Bridge" MONO_GC_PARAMS="minor=split" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE3_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=3Bridge" MONO_GC_PARAMS="minor=split" $(RUNTIME) $(TEST_RUNNER) --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE3_TESTS) sgen-bridge3-tests-plain-new-bridge: $(SGEN_BRIDGE3_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=3Bridge" MONO_GC_PARAMS="bridge-implementation=new" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE3_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=3Bridge" MONO_GC_PARAMS="bridge-implementation=new" $(RUNTIME) $(TEST_RUNNER) --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE3_TESTS) sgen-bridge3-tests-ms-conc-new-bridge: $(SGEN_BRIDGE3_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=3Bridge" MONO_GC_PARAMS="bridge-implementation=new,major=marksweep-conc" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE3_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=3Bridge" MONO_GC_PARAMS="bridge-implementation=new,major=marksweep-conc" $(RUNTIME) $(TEST_RUNNER) --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE3_TESTS) sgen-bridge3-tests-ms-split-new-bridge: $(SGEN_BRIDGE3_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=3Bridge" MONO_GC_PARAMS="bridge-implementation=new,minor=split" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE3_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=3Bridge" MONO_GC_PARAMS="bridge-implementation=new,minor=split" $(RUNTIME) $(TEST_RUNNER) --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE3_TESTS) sgen-bridge3-tests-plain-tarjan-bridge: $(SGEN_BRIDGE3_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=3Bridge" MONO_GC_PARAMS="bridge-implementation=tarjan" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE3_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=3Bridge" MONO_GC_PARAMS="bridge-implementation=tarjan" $(RUNTIME) $(TEST_RUNNER) --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE3_TESTS) sgen-bridge3-tests-ms-split-tarjan-bridge: $(SGEN_BRIDGE3_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=3Bridge" MONO_GC_PARAMS="bridge-implementation=tarjan,minor=split" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE3_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=3Bridge" MONO_GC_PARAMS="bridge-implementation=tarjan,minor=split" $(RUNTIME) $(TEST_RUNNER) --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE3_TESTS) AOT_CONFIGURATIONS= \ @@ -1170,19 +1327,23 @@ test-aot: # Generated tests for runtime invoke EXTRA_DIST += gen-runtime-invoke.cs -runtime-invoke.gen.exe: TestDriver.dll gen-runtime-invoke.exe +runtime-invoke.gen.exe: $(TEST_DRIVER_DEPEND) gen-runtime-invoke.exe $(RUNTIME) gen-runtime-invoke.exe > runtime-invoke.gen.cs $(MCS) -out:runtime-invoke.gen.exe -r:TestDriver.dll runtime-invoke.gen.cs EXTRA_DIST += make-imt-test.cs -imt_big_iface_test.exe: TestDriver.dll make-imt-test.exe +imt_big_iface_test.exe: $(TEST_DRIVER_DEPEND) make-imt-test.exe $(RUNTIME) make-imt-test.exe > imt_big_iface_test.cs $(MCS) -out:imt_big_iface_test.exe -r:TestDriver.dll imt_big_iface_test.cs EXTRA_DIST += test-inline-call-stack-library.cs test-inline-call-stack.cs -test-inline-call-stack-library.dll: TestDriver.dll $(srcdir)/test-inline-call-stack-library.cs +test-inline-call-stack-library.dll: $(TEST_DRIVER_DEPEND) $(srcdir)/test-inline-call-stack-library.cs $(MCS) -t:library -out:test-inline-call-stack-library.dll $(srcdir)/test-inline-call-stack-library.cs -test-inline-call-stack.exe: TestDriver.dll test-inline-call-stack-library.dll $(srcdir)/test-inline-call-stack.cs +if INSTALL_MOBILE_STATIC + $(RUNTIME) $(AOT_BUILD_FLAGS) $@ +endif + +test-inline-call-stack.exe: $(TEST_DRIVER_DEPEND) test-inline-call-stack-library.dll $(srcdir)/test-inline-call-stack.cs $(MCS) -r:TestDriver.dll -r:test-inline-call-stack-library.dll -out:test-inline-call-stack.exe $(srcdir)/test-inline-call-stack.cs EXTRA_DIST += unhandled-exception-base-configuration.config @@ -1225,12 +1386,18 @@ bug-81673.exe bug-81673-interface.dll: $(srcdir)/bug-81673.cs $(srcdir)/bug-8167 $(MCS) -target:library -out:bug-81673-interface.dll $(srcdir)/bug-81673-interface.cs $(MCS) -out:bug-81673.exe -r:bug-81673-interface.dll $(srcdir)/bug-81673.cs $(MCS) -define:WITH_STOP -target:library -out:bug-81673-interface.dll $(srcdir)/bug-81673-interface.cs +if INSTALL_MOBILE_STATIC + $(RUNTIME) $(AOT_BUILD_FLAGS) $@ +endif EXTRA_DIST += bug-36848-a.cs bug-36848.exe bug-36848-a.dll: $(srcdir)/bug-36848.cs $(srcdir)/bug-36848-a.cs $(MCS) -target:library -out:bug-36848-a.dll $(srcdir)/bug-36848-a.cs $(MCS) -r:bug-36848-a.dll -out:bug-36848.exe $(srcdir)/bug-36848.cs $(MCS) -target:library -out:bug-36848-a.dll $(srcdir)/bug-36848-a.cs /define:WITH_STOP +if INSTALL_MOBILE_STATIC + $(RUNTIME) $(AOT_BUILD_FLAGS) $@ +endif EXTRA_DIST += bug-81691-a.cs bug-81691-b.cs bug-81691.exe bug-81691-b.dll: $(srcdir)/bug-81691.cs $(srcdir)/bug-81691-a.cs $(srcdir)/bug-81691-b.cs @@ -1243,24 +1410,37 @@ bug-81691.exe: bug-81691-b.dll EXTRA_DIST += bug-81466-lib.il bug-81466-lib.dll: bug-81466-lib.il $(ILASM) /dll /output:bug-81466-lib.dll $(srcdir)/bug-81466-lib.il +if INSTALL_MOBILE_STATIC + $(RUNTIME) $(AOT_BUILD_FLAGS) $@ +endif bug-81466.exe: bug-81466.il bug-81466-lib.dll $(ILASM) /exe /output:bug-81466.exe $(srcdir)/bug-81466.il EXTRA_DIST += bug-324535-il.il bug-324535-il.dll : bug-324535-il.il $(ILASM) /dll /output:bug-324535-il.dll $(srcdir)/bug-324535-il.il +if INSTALL_MOBILE_STATIC + $(RUNTIME) $(AOT_BUILD_FLAGS) $@ +endif bug-324535.exe : bug-324535.cs bug-324535-il.dll $(MCS) -r:bug-324535-il.dll -out:bug-324535.exe $(srcdir)/bug-324535.cs EXTRA_DIST += custom-modifiers.2.cs custom-modifiers-lib.il custom-modifiers-lib.dll: custom-modifiers-lib.il $(ILASM) /dll /output:custom-modifiers-lib.dll $(srcdir)/custom-modifiers-lib.il +if INSTALL_MOBILE_STATIC + $(RUNTIME) $(AOT_BUILD_FLAGS) $@ +endif custom-modifiers.2.exe: custom-modifiers.2.cs custom-modifiers-lib.dll $(MCS) -r:custom-modifiers-lib.dll -out:custom-modifiers.2.exe $(srcdir)/custom-modifiers.2.cs EXTRA_DIST += bug-382986-lib.cs bug-382986-lib.dll: bug-382986-lib.cs $(MCS) -target:library -out:$@ $(srcdir)/bug-382986-lib.cs +if INSTALL_MOBILE_STATIC + $(RUNTIME) $(AOT_BUILD_FLAGS) $@ +endif + bug-382986.exe: bug-382986.cs bug-382986-lib.dll $(MCS) -out:$@ -r:bug-382986-lib.dll $(srcdir)/bug-382986.cs @@ -1284,10 +1464,16 @@ test-coreclr-security : coreclr-security.exe EXTRA_DIST += generic-unboxing.2.il generic-unboxing.2.dll : generic-unboxing.2.il $(ILASM) /dll /output:generic-unboxing.2.dll $(srcdir)/generic-unboxing.2.il +if INSTALL_MOBILE_STATIC + $(RUNTIME) $(AOT_BUILD_FLAGS) $@ +endif EXTRA_DIST += generic-boxing.2.il generic-boxing.2.dll : generic-boxing.2.il generic-unboxing.2.dll $(ILASM) /dll /output:generic-boxing.2.dll $(srcdir)/generic-boxing.2.il +if INSTALL_MOBILE_STATIC + $(RUNTIME) $(AOT_BUILD_FLAGS) $@ +endif EXTRA_DIST += generic-unbox.2.cs generic-unbox.2.exe : generic-unbox.2.cs generic-unboxing.2.dll @@ -1300,6 +1486,9 @@ generic-box.2.exe : generic-box.2.cs generic-unboxing.2.dll generic-boxing.2.dll EXTRA_DIST += generic-delegate2.2.cs generic-delegate2-lib.2.il generic-delegate2-lib.2.dll : generic-delegate2-lib.2.il $(ILASM) /dll /output:$@ $(srcdir)/generic-delegate2-lib.2.il +if INSTALL_MOBILE_STATIC + $(RUNTIME) $(AOT_BUILD_FLAGS) $@ +endif generic-delegate2.2.exe : generic-delegate2.2.cs generic-delegate2-lib.2.dll $(MCS) -r:generic-delegate2-lib.2.dll -out:$@ $(srcdir)/generic-delegate2.2.cs @@ -1311,7 +1500,10 @@ gshared: test-generic-sharing gshared-aot: @$(MAKE) AOT=1 gshared -GSHARED_TESTS = \ +GSHARED_TESTS_MOBILE_STATIC_NOT_SUPPORTED = \ + generic-type-builder.2.exe + +GSHARED_TESTS_UNIVERSAL = \ generics-sharing.2.exe shared-generic-methods.2.exe \ shared-generic-synchronized.2.exe generic-initobj.2.exe \ generics-sharing-other-exc.2.exe generic-box.2.exe \ @@ -1327,7 +1519,7 @@ GSHARED_TESTS = \ generic-exceptions.2.exe generic-delegate2.2.exe \ generic-virtual2.2.exe generic-valuetype-interface.2.exe \ generic-valuetype-newobj.2.exe generic-valuetype-newobj2.2.exe \ - generic-getgenericarguments.2.exe generic-type-builder.2.exe \ + generic-getgenericarguments.2.exe \ generic-synchronized.2.exe generic-delegate-ctor.2.exe \ generic-constrained.2.exe bug-431413.2.exe \ generic-virtual-invoke.2.exe generic-typedef.2.exe \ @@ -1339,6 +1531,15 @@ GSHARED_TESTS = \ generic-type-load-exception.2.exe bug-616463.exe \ bug-1147.exe +if INSTALL_MOBILE_STATIC +GSHARED_TESTS= \ + $(GSHARED_TESTS_UNIVERSAL) +else +GSHARED_TESTS= \ + $(GSHARED_TESTS_MOBILE_STATIC_NOT_SUPPORTED) \ + $(GSHARED_TESTS_UNIVERSAL) +endif + test-generic-sharing-normal: $(GSHARED_TESTS) @for fn in $+ ; do \ echo "Testing $$fn ..."; \ @@ -1350,7 +1551,7 @@ test-generic-sharing-normal: $(GSHARED_TESTS) done test-generic-sharing-managed: test-runner.exe $(GSHARED_TESTS) - @$(RUNTIME) ./test-runner.exe -j a --testsuite-name "gshared" --opt-sets "gshared gshared,shared gshared,-inline gshared,-inline,shared" $(GSHARED_TESTS) + @$(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) -j a --testsuite-name "gshared" --disabled "$(DISABLED_TESTS)" --opt-sets "gshared gshared,shared gshared,-inline gshared,-inline,shared" $(GSHARED_TESTS) if NACL_CODEGEN test-generic-sharing: @@ -1369,7 +1570,7 @@ test-async-exceptions : async-exceptions.exe EXTRA_DIST += modules.cs modules-m1.cs modules-m1.netmodule: modules-m1.cs $(MCS) -out:$@ /target:module $(srcdir)/modules-m1.cs -modules.exe: modules.cs modules-m1.netmodule TestDriver.dll +modules.exe: modules.cs modules-m1.netmodule $(TEST_DRIVER_DEPEND) $(MCS) -out:$@ /addmodule:modules-m1.netmodule -r:TestDriver.dll $(srcdir)/modules.cs # Useful if mono is compiled with --enable-shared=no @@ -1427,13 +1628,13 @@ test-unhandled-exception-2: $(UNHANDLED_EXCEPTION_1_TESTS) $(UNHANDLED_EXCEPTION $(MAKE) test-unhandled-exception-2-255-without-managed-handler test-unhandled-exception-2-1-with-managed-handler: $(UNHANDLED_EXCEPTION_1_TESTS) test-runner.exe - $(RUNTIME) ./test-runner.exe -j a --testsuite-name $@ --expected-exit-code 1 $(UNHANDLED_EXCEPTION_1_TESTS) + $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) -j a --testsuite-name $@ --disabled "$(DISABLED_TESTS)" --expected-exit-code 1 $(UNHANDLED_EXCEPTION_1_TESTS) test-unhandled-exception-2-1-without-managed-handler: $(UNHANDLED_EXCEPTION_1_TESTS) test-runner.exe - TEST_UNHANDLED_EXCEPTION_HANDLER=1 $(RUNTIME) ./test-runner.exe -j a --testsuite-name $@ --expected-exit-code 1 $(UNHANDLED_EXCEPTION_1_TESTS) + TEST_UNHANDLED_EXCEPTION_HANDLER=1 $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) -j a --testsuite-name $@ --disabled "$(DISABLED_TESTS)" --expected-exit-code 1 $(UNHANDLED_EXCEPTION_1_TESTS) test-unhandled-exception-2-255-with-managed-handler: $(UNHANDLED_EXCEPTION_255_TESTS) test-runner.exe - $(RUNTIME) ./test-runner.exe -j a --testsuite-name $@ --expected-exit-code 255 $(UNHANDLED_EXCEPTION_255_TESTS) + $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) -j a --testsuite-name $@ --disabled "$(DISABLED_TESTS)" --expected-exit-code 255 $(UNHANDLED_EXCEPTION_255_TESTS) test-unhandled-exception-2-255-without-managed-handler: $(UNHANDLED_EXCEPTION_255_TESTS) test-runner.exe - TEST_UNHANDLED_EXCEPTION_HANDLER=1 $(RUNTIME) ./test-runner.exe -j a --testsuite-name $@ --expected-exit-code 255 $(UNHANDLED_EXCEPTION_255_TESTS) + TEST_UNHANDLED_EXCEPTION_HANDLER=1 $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) -j a --testsuite-name $@ --disabled "$(DISABLED_TESTS)" --expected-exit-code 255 $(UNHANDLED_EXCEPTION_255_TESTS) endif @@ -1458,7 +1659,7 @@ PROCESS_STRESS_TESTS= \ process-leak.exe test-process-stress: $(PROCESS_STRESS_TESTS) test-runner.exe - $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 600 $(PROCESS_STRESS_TESTS) + $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 600 $(PROCESS_STRESS_TESTS) coreclr-gcstress: $(MAKE) -C $(mono_build_root)/acceptance-tests coreclr-gcstress diff --git a/mono/tests/Makefile.in b/mono/tests/Makefile.in index 62dba2054e..cb3b5164d0 100644 --- a/mono/tests/Makefile.in +++ b/mono/tests/Makefile.in @@ -228,6 +228,8 @@ am__relativize = \ ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AOT_BUILD_FLAGS = @AOT_BUILD_FLAGS@ +AOT_RUN_FLAGS = @AOT_RUN_FLAGS@ API_VER = @API_VER@ AR = @AR@ AS = @AS@ @@ -236,6 +238,11 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOEHM_DEFINES = @BOEHM_DEFINES@ +BTLS_ARCH = @BTLS_ARCH@ +BTLS_CFLAGS = @BTLS_CFLAGS@ +BTLS_CMAKE_ARGS = @BTLS_CMAKE_ARGS@ +BTLS_PLATFORM = @BTLS_PLATFORM@ +BTLS_ROOT = @BTLS_ROOT@ BUILD_EXEEXT = @BUILD_EXEEXT@ CC = @CC@ CCAS = @CCAS@ @@ -245,6 +252,7 @@ CCDEPMODE = @CCDEPMODE@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMAKE = @CMAKE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ @@ -265,7 +273,6 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_PERF_EVENTS = @ENABLE_PERF_EVENTS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDKX11 = @GDKX11@ @@ -280,10 +287,12 @@ HAVE_MSGFMT = @HAVE_MSGFMT@ HOST_CC = @HOST_CC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MOBILE_STATIC = @INSTALL_MOBILE_STATIC@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTL = @INTL@ +INVARIANT_AOT_OPTIONS = @INVARIANT_AOT_OPTIONS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBC = @LIBC@ @@ -330,6 +339,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ +PLATFORM_AOT_SUFFIX = @PLATFORM_AOT_SUFFIX@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -339,6 +349,7 @@ SHELL = @SHELL@ SQLITE = @SQLITE@ SQLITE3 = @SQLITE3@ STRIP = @STRIP@ +TEST_PROFILE = @TEST_PROFILE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VTUNE_CFLAGS = @VTUNE_CFLAGS@ @@ -428,11 +439,21 @@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = assemblyresolve gc-descriptors +@INSTALL_MOBILE_STATIC_FALSE@FEATUREFUL_RUNTIME_TEST = test-appdomain-unload +@INSTALL_MOBILE_STATIC_TRUE@FEATUREFUL_RUNTIME_TEST = TEST_PROG = ../interpreter/mint JITTEST_PROG = $(if $(VALGRIND), valgrind $(VALGRIND_ARGS),) $(if $(SGEN),$(top_builddir)/mono/mini/mono-sgen,$(top_builddir)/mono/mini/mono) TEST_PROG_RUN = MONO_CFG_DIR=$(mono_build_root)/runtime/etc $(LIBTOOL) --mode=execute $(TEST_PROG) JITTEST_PROG_RUN = MONO_CFG_DIR=$(mono_build_root)/runtime/etc $(LIBTOOL) --mode=execute $(JITTEST_PROG) RUNTIME_ARGS = --config tests-config --optimize=all --debug +@HOST_WIN32_FALSE@TEST_RUNNER_ARGS = --config tests-config --runtime \ +@HOST_WIN32_FALSE@ $(if \ +@HOST_WIN32_FALSE@ $(MONO_EXECUTABLE),$(MONO_EXECUTABLE),mono) \ +@HOST_WIN32_FALSE@ $(if $(V), --verbose,) +@HOST_WIN32_TRUE@TEST_RUNNER_ARGS = --config tests-config --runtime \ +@HOST_WIN32_TRUE@ $(if $(MONO_EXECUTABLE),$(shell cygpath -w -a \ +@HOST_WIN32_TRUE@ $(MONO_EXECUTABLE) | sed 's/\\/\\\\/g'),mono) \ +@HOST_WIN32_TRUE@ $(if $(V), --verbose,) CLASS = $(mcs_topdir)/class/lib/$(DEFAULT_PROFILE) with_mono_path = MONO_PATH=$(CLASS) RUNTIME = $(with_mono_path) $(top_builddir)/runtime/mono-wrapper @@ -440,14 +461,17 @@ MKBUNDLE = \ PKG_CONFIG_PATH=$(top_builddir):$(PKG_CONFIG_PATH) \ $(RUNTIME) $(CLASS)/mkbundle.exe +@INSTALL_MOBILE_STATIC_TRUE@PROFILE_MCS_FLAGS = -d:MOBILE,MOBILE_STATIC,MOBILE_LEGACY MCS_NO_LIB = $(RUNTIME) $(mcs_topdir)/class/lib/build/mcs.exe -unsafe -debug \ -noconfig -nologo \ -nowarn:0162 -nowarn:0168 -nowarn:0219 -nowarn:0414 -nowarn:0618 \ -nowarn:0169 -nowarn:1690 -nowarn:0649 -nowarn:0612 -nowarn:3021 \ - -nowarn:0197 + -nowarn:0197 $(PROFILE_MCS_FLAGS) MCS = $(MCS_NO_LIB) -lib:$(CLASS) ILASM = $(RUNTIME) $(CLASS)/ilasm.exe +@INSTALL_MOBILE_STATIC_FALSE@TEST_RUNNER = ./test-runner.exe --runtime $(top_builddir)/runtime/mono-wrapper --mono-path "$(CLASS)" +@INSTALL_MOBILE_STATIC_TRUE@TEST_RUNNER = ./test-runner.exe --runtime $(top_builddir)/runtime/mono-wrapper --mono-path "$(CLASS)" --aot-run-flags "$(AOT_RUN_FLAGS)" --aot-build-flags "$(AOT_BUILD_FLAGS)" BENCHSRC = fib.cs random.cs nested-loops.cs ackermann.cs tight-loop.cs sieve.cs STRESS_TESTS_SRC = \ abort-stress-1.cs \ @@ -464,10 +488,71 @@ STRESS_TESTS_SRC = \ process-stress.cs \ assembly-load-stress.cs +BASE_TEST_MOBILE_STATIC_NOT_SUPPORTED = \ + remoting4.cs # Needs remoting support \ + remoting1.cs # Needs remoting support \ + remoting2.cs # Needs remoting support \ + remoting3.cs # Needs remoting support \ + remoting5.cs # Needs remoting support \ + appdomain.cs # Needs appdomain support \ + appdomain-client.cs # Needs appdomain support \ + appdomain-unload.cs # Needs appdomain support \ + appdomain-async-invoke.cs # Needs appdomain support \ + appdomain-thread-abort.cs # Needs appdomain support \ + appdomain1.cs # Needs appdomain support \ + appdomain2.cs # Needs appdomain support \ + appdomain-exit.cs # Needs appdomain support \ + assemblyresolve_event2.2.cs # Needs appdomain support \ + appdomain-unload-callback.cs # Needs appdomain support \ + appdomain-unload-doesnot-raise-pending-events.cs # Needs appdomain support \ + unload-appdomain-on-shutdown.cs # Needs appdomain support \ + bug-47295.cs # Needs SRE \ + loader.cs # Needs SRE \ + pinvoke2.cs # Needs SRE \ + generic-type-builder.2.cs # Needs SRE \ + dynamic-generic-size.cs # Needs SRE \ + cominterop.cs # Needs COM \ + dynamic-method-access.2.cs # Need SRE \ + dynamic-method-finalize.2.cs # Need SRE \ + dynamic-method-stack-traces.cs # Need SRE\ + generic_type_definition.2.cs # Need SRE \ + bug-333798-tb.2.cs # Need SRE \ + bug-335131.2.cs # Need SRE \ + bug-322722_patch_bx.2.cs # Need SRE\ + bug-322722_dyn_method_throw.2.cs # Need SRE \ + bug-389886-2.cs # Need SRE \ + bug-349190.2.cs # Need SRE \ + bug-389886-sre-generic-interface-instances.cs # Need SRE \ + bug-462592.cs # Need SRE \ + bug-575941.cs # Need SRE \ + bug-389886-3.cs # Need SRE \ + constant-division.cs # Need SRE \ + dynamic-method-resurrection.cs # Need SRE \ + bug-80307.cs # Need System.Web \ + assembly_append_ordering.cs # Need SRE \ + bug-544446.cs # Needs AppDomains / TranparentProxy \ + bug-36848.cs # Needs AppDomains / TranparentProxy \ + generic-marshalbyref.2.cs # Needs AppDomains \ + stackframes-async.2.cs # Needs AppDomains \ + transparentproxy.cs # Needs AppDomains / TranparentProxy \ + bug-48015.cs # Needs AppDomains / TranparentProxy \ + delegate9.cs # Needs AppDomains \ + marshal-valuetypes.cs # Needs AppDomains \ + xdomain-threads.cs # Needs AppDomains \ + monitor.cs # Needs AppDomains \ + generic-xdomain.2.cs # Needs AppDomains \ + threadpool-exceptions7.cs # Needs AppDomains \ + cross-domain.cs # Needs AppDomains \ + generic-unloading.2.cs # Needs AppDomains \ + thread6.cs # On MOBILE, ThreadAbortException doesn't have necessary field for this test + # Disabled until ?mcs is fixed # bug-331958.cs -BASE_TEST_CS_SRC = \ +# Note: only add tests that are compatible with mobile_static to this category +BASE_TEST_CS_SRC_UNIVERSAL = \ + generic-unloading-sub.2.cs \ + create-instance.cs \ bug-2907.cs \ array-init.cs \ arraylist.cs \ @@ -477,7 +562,6 @@ BASE_TEST_CS_SRC = \ assemblyresolve_event4.cs \ checked.cs \ char-isnumber.cs \ - create-instance.cs \ field-layout.cs \ pack-layout.cs \ pack-bug.cs \ @@ -514,7 +598,6 @@ BASE_TEST_CS_SRC = \ typeof-ptr.cs \ static-constructor.cs \ pinvoke.cs \ - pinvoke2.cs \ pinvoke3.cs \ pinvoke11.cs \ pinvoke13.cs \ @@ -580,13 +663,6 @@ BASE_TEST_CS_SRC = \ jit-float.cs \ pop.cs \ time.cs \ - appdomain.cs \ - appdomain1.cs \ - appdomain2.cs \ - appdomain-client.cs \ - appdomain-unload.cs \ - appdomain-async-invoke.cs \ - loader.cs \ pointer.cs \ hashcode.cs \ delegate1.cs \ @@ -596,16 +672,10 @@ BASE_TEST_CS_SRC = \ delegate6.cs \ delegate7.cs \ delegate8.cs \ - delegate9.cs \ delegate10.cs \ delegate11.cs \ delegate12.cs \ delegate13.cs \ - remoting1.cs \ - remoting2.cs \ - remoting3.cs \ - remoting4.cs \ - remoting5.cs \ largeexp.cs \ largeexp2.cs \ marshalbyref1.cs \ @@ -626,11 +696,9 @@ BASE_TEST_CS_SRC = \ marshal8.cs \ marshal9.cs \ marshalbool.cs \ - marshal-valuetypes.cs \ test-byval-in-struct.cs \ thread.cs \ thread5.cs \ - thread6.cs \ thread-static.cs \ thread-static-init.cs \ context-static.cs \ @@ -650,12 +718,9 @@ BASE_TEST_CS_SRC = \ threadpool-exceptions4.cs \ threadpool-exceptions5.cs \ threadpool-exceptions6.cs \ - threadpool-exceptions7.cs \ base-definition.cs \ bug-27420.cs \ - bug-47295.cs \ bug-46781.cs \ - bug-48015.cs \ bug-42136.cs \ bug-59286.cs \ bug-70561.cs \ @@ -666,8 +731,6 @@ BASE_TEST_CS_SRC = \ bug-323114.cs \ bug-Xamarin-5278.cs \ interlocked.cs \ - cross-domain.cs \ - appdomain-exit.cs \ delegate-async-exit.cs \ delegate-delegate-exit.cs \ delegate-exit.cs \ @@ -684,16 +747,13 @@ BASE_TEST_CS_SRC = \ main-returns.cs \ subthread-exit.cs \ desweak.cs \ - cominterop.cs \ exists.cs \ handleref.cs \ - transparentproxy.cs \ dbnull-missing.cs \ test-type-ctor.cs \ soft-float-tests.cs \ thread-exit.cs \ finalize-parent.cs \ - assemblyresolve_event2.2.cs \ interlocked-2.2.cs \ pinvoke-2.2.cs \ bug-78431.2.cs \ @@ -701,7 +761,6 @@ BASE_TEST_CS_SRC = \ catch-generics.2.cs \ event-get.2.cs \ safehandle.2.cs \ - stackframes-async.2.cs \ module-cctor-loader.2.cs \ generics-invoke-byref.2.cs \ generic-signature-compare.2.cs \ @@ -723,14 +782,10 @@ BASE_TEST_CS_SRC = \ generic-virtual2.2.cs \ generic-valuetype-interface.2.cs \ generic-getgenericarguments.2.cs \ - generic-type-builder.2.cs \ generic-synchronized.2.cs \ generic-delegate-ctor.2.cs \ generic-array-iface-set.2.cs \ generic-typedef.2.cs \ - generic-marshalbyref.2.cs \ - generic-xdomain.2.cs \ - dynamic-generic-size.cs \ bug-431413.2.cs \ bug-459285.2.cs \ generic-virtual-invoke.2.cs \ @@ -746,27 +801,17 @@ BASE_TEST_CS_SRC = \ bug-479763.2.cs \ bug-616463.cs \ bug-80392.2.cs \ - dynamic-method-access.2.cs \ - dynamic-method-finalize.2.cs \ - dynamic-method-stack-traces.cs \ bug-82194.2.cs \ anonarray.2.cs \ ienumerator-interfaces.2.cs \ array-enumerator-ifaces.2.cs \ generic_type_definition_encoding.2.cs \ - generic_type_definition.2.cs \ bug-333798.2.cs \ - bug-333798-tb.2.cs \ - bug-335131.2.cs \ - bug-322722_patch_bx.2.cs \ bug-348522.2.cs \ bug-340662_bug.cs \ - bug-322722_dyn_method_throw.2.cs \ - bug-389886-2.cs \ bug-325283.2.cs \ thunks.cs \ winx64structs.cs \ - bug-349190.2.cs \ nullable_boxing.2.cs \ valuetype-equals.cs \ custom-modifiers.2.cs \ @@ -775,44 +820,30 @@ BASE_TEST_CS_SRC = \ bug-324535.cs \ modules.cs \ bug-81673.cs \ - bug-36848.cs \ bug-81691.cs \ - bug-80307.cs \ bug-415577.cs \ filter-stack.cs \ vararg2.cs \ - bug-389886-sre-generic-interface-instances.cs \ bug-461867.cs \ bug-461941.cs \ bug-461261.cs \ bug-400716.cs \ - bug-462592.cs \ bug-459094.cs \ - generic-unloading.2.cs \ - generic-unloading-sub.2.cs \ bug-467456.cs \ - appdomain-unload-callback.cs \ bug-508538.cs \ bug-472692.2.cs \ gchandles.cs \ interlocked-3.cs \ interlocked-4.2.cs \ - appdomain-thread-abort.cs \ - xdomain-threads.cs \ w32message.cs \ - bug-544446.cs \ gc-altstack.cs \ large-gc-bitmap.cs \ bug-561239.cs \ bug-562150.cs \ - bug-575941.cs \ bug-599469.cs \ - bug-389886-3.cs \ - monitor.cs \ monitor-resurrection.cs \ monitor-wait-abort.cs \ monitor-abort.cs \ - dynamic-method-resurrection.cs \ bug-666008.cs \ bug-685908.cs \ sgen-long-vtype.cs \ @@ -824,13 +855,10 @@ BASE_TEST_CS_SRC = \ bug-bxc-795.cs \ bug-3903.cs \ async-with-cb-throws.cs \ - appdomain-unload-doesnot-raise-pending-events.cs \ bug-6148.cs \ - assembly_append_ordering.cs \ bug-10127.cs \ bug-18026.cs \ allow-synchronous-major.cs \ - unload-appdomain-on-shutdown.cs \ block_guard_restore_aligment_on_exit.cs \ thread_static_gc_layout.cs \ sleep.cs \ @@ -842,7 +870,17 @@ BASE_TEST_CS_SRC = \ pinvoke_ppci.cs \ pinvoke_ppcf.cs \ pinvoke_ppcd.cs \ - bug-29585.cs + bug-29585.cs \ + priority.cs \ + abort-cctor.cs \ + reference-loader.cs + +@INSTALL_MOBILE_STATIC_FALSE@BASE_TEST_CS_SRC = \ +@INSTALL_MOBILE_STATIC_FALSE@ $(BASE_TEST_MOBILE_STATIC_NOT_SUPPORTED) \ +@INSTALL_MOBILE_STATIC_FALSE@ $(BASE_TEST_CS_SRC_UNIVERSAL) + +@INSTALL_MOBILE_STATIC_TRUE@BASE_TEST_CS_SRC = \ +@INSTALL_MOBILE_STATIC_TRUE@ $(BASE_TEST_CS_SRC_UNIVERSAL) TEST_CS_SRC_DIST = \ $(BASE_TEST_CS_SRC) \ @@ -946,6 +984,40 @@ TEST_CS_SRC_GEN = \ @S390X_TRUE@ $(am__append_2) @ENABLE_COOP_FALSE@COOP_DISABLED_TESTS = @ENABLE_COOP_TRUE@COOP_DISABLED_TESTS = thunks.exe +@INSTALL_MOBILE_STATIC_FALSE@PROFILE_DISABLED_TESTS = + +# Tests which rely on TypeLoadExceptions +# In full-aot mode, these cause the relevant methods to be not AOTed. + +# Tests which rely on remoting + +# Tests which use unsupported pinvoke+full aot +# functionality + +# Tests which load assemblies which are not +# in the mobile_static profile +@INSTALL_MOBILE_STATIC_TRUE@PROFILE_DISABLED_TESTS = \ +@INSTALL_MOBILE_STATIC_TRUE@ typeload-unaligned.exe \ +@INSTALL_MOBILE_STATIC_TRUE@ field-access.exe \ +@INSTALL_MOBILE_STATIC_TRUE@ invalid_generic_instantiation.exe \ +@INSTALL_MOBILE_STATIC_TRUE@ bug-481403.exe array_ldelema.exe \ +@INSTALL_MOBILE_STATIC_TRUE@ array_load_exception.exe \ +@INSTALL_MOBILE_STATIC_TRUE@ bug445361.exe \ +@INSTALL_MOBILE_STATIC_TRUE@ generic-type-load-exception.2.exe \ +@INSTALL_MOBILE_STATIC_TRUE@ invalid-token.exe \ +@INSTALL_MOBILE_STATIC_TRUE@ call_missing_method.exe \ +@INSTALL_MOBILE_STATIC_TRUE@ call_missing_class.exe \ +@INSTALL_MOBILE_STATIC_TRUE@ ldfld_missing_field.exe \ +@INSTALL_MOBILE_STATIC_TRUE@ ldfld_missing_class.exe \ +@INSTALL_MOBILE_STATIC_TRUE@ vt-sync-method.exe \ +@INSTALL_MOBILE_STATIC_TRUE@ context-static.exe bug-415577.exe \ +@INSTALL_MOBILE_STATIC_TRUE@ generic-marshalbyref.2.exe \ +@INSTALL_MOBILE_STATIC_TRUE@ unhandled-exception-7.exe \ +@INSTALL_MOBILE_STATIC_TRUE@ marshal.exe marshal2.exe \ +@INSTALL_MOBILE_STATIC_TRUE@ marshal6.exe marshal7.exe \ +@INSTALL_MOBILE_STATIC_TRUE@ marshal8.exe pinvoke-2.2.exe \ +@INSTALL_MOBILE_STATIC_TRUE@ pinvoke3.exe thunks.exe \ +@INSTALL_MOBILE_STATIC_TRUE@ assembly-load-remap.exe # The two finalizer tests only work under sgen # gc-altstack.exe fails under boehm because it has no support for altstack @@ -961,7 +1033,8 @@ DISABLED_TESTS = \ bug-Xamarin-5278.exe \ $(PLATFORM_DISABLED_TESTS) \ $(EXTRA_DISABLED_TESTS) \ - $(COOP_DISABLED_TESTS) + $(COOP_DISABLED_TESTS) \ + $(PROFILE_DISABLED_TESTS) DISABLED_TESTS_WRENCH = \ $(DISABLED_TESTS) \ @@ -981,7 +1054,15 @@ AOT_DISABLED_TESTS = constraints-load.exe TEST_CSC_SRC = \ vararg.cs -TEST_IL_SRC = \ + +# constraints-load.il: +# Failed to load method 0x6000007 from '..../mono/tests/constraints-load.exe' due to +# Could not resolve type with token 01000002 assembly:mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 type:System.BrokenIComparable`1 member:. +IL_SRC_MOBILE_STATIC_NOT_SUPPORTED = \ + constraints-load.il \ + bug-515884.il + +TEST_IL_SRC_UNIVERSAL = \ field-access.il \ method-access.il \ ldftn-access.il \ @@ -1040,30 +1121,45 @@ TEST_IL_SRC = \ bug-463303.il \ bug469742.2.il \ bug-528055.il \ - constraints-load.il \ array_load_exception.il \ bug-481403.il \ interface-with-static-method.il \ - bug-515884.il \ bug-633291.il \ delegate-with-null-target.il \ bug-318677.il \ gsharing-valuetype-layout.il \ invalid_generic_instantiation.il +@INSTALL_MOBILE_STATIC_FALSE@TEST_IL_SRC = \ +@INSTALL_MOBILE_STATIC_FALSE@ $(TEST_IL_SRC_MOBILE_STATIC_NOT_SUPPORTED) \ +@INSTALL_MOBILE_STATIC_FALSE@ $(TEST_IL_SRC_UNIVERSAL) + +@INSTALL_MOBILE_STATIC_TRUE@TEST_IL_SRC = \ +@INSTALL_MOBILE_STATIC_TRUE@ $(TEST_IL_SRC_UNIVERSAL) + # pre-requisite test sources: files that are not test themselves # but that need to be compiled PREREQ_IL_SRC = event-il.il module-cctor.il PREREQ_CS_SRC = -PREREQ_IL_DLL_SRC = event-il.il module-cctor.il -PREREQ_CS_DLL_SRC = -PREREQSI_IL = $(PREREQ_IL_SRC:.il=.exe) -PREREQSI_CS = $(PREREQ_CS_SRC:.cs=.exe) +PREREQ_IL_DLL_SRC = +PREREQ_CS_DLL_SRC = TestingReferenceAssembly.cs TestingReferenceReferenceAssembly.cs +PREREQSI_IL = $(PREREQ_IL_SRC:.il=.exe) \ + $(PREREQ_IL_DLL_SRC:.il=.dll) + +PREREQSI_CS = $(PREREQ_CS_SRC:.cs=.exe) \ + $(PREREQ_CS_DLL_SRC:.cs=.dll) + TESTSI_CS = $(TEST_CS_SRC:.cs=.exe) TESTSI_IL = $(TEST_IL_SRC:.il=.exe) TESTBS = $(BENCHSRC:.cs=.exe) STRESS_TESTS = $(STRESS_TESTS_SRC:.cs=.exe) +PREREQSI_IL_AOT = $(PREREQ_IL_SRC:.il=.exe$(PLATFORM_AOT_SUFFIX)) \ + $(PREREQ_IL_DLL_SRC:.il=.dll$(PLATFORM_AOT_SUFFIX)) + +PREREQSI_CS_AOT = $(PREREQ_CS_SRC:.cs=.exe$(PLATFORM_AOT_SUFFIX)) \ + $(PREREQ_CS_DLL_SRC:.cs=.dll$(PLATFORM_AOT_SUFFIX)) + # Generated tests for runtime invoke EXTRA_DIST = test-driver test-runner.cs $(TEST_CS_SRC_DIST) \ @@ -1098,18 +1194,31 @@ EXTRA_DIST = test-driver test-runner.cs $(TEST_CS_SRC_DIST) \ appdomain-tester.cs console-output.cs \ console-output.exe.stderr.expected \ console-output.exe.stdout.expected +@INSTALL_MOBILE_STATIC_FALSE@TEST_DRIVER_HARD_KILL_FEATURE = -r:Mono.Posix.dll +@INSTALL_MOBILE_STATIC_FALSE@TEST_DRIVER_DEPEND = TestDriver.dll +@INSTALL_MOBILE_STATIC_TRUE@TEST_DRIVER_DEPEND = TestDriver.dll$(PLATFORM_AOT_SUFFIX) +AOT_EXTRA_LIBS = \ +bug-382986-lib.dll$(PLATFORM_AOT_SUFFIX) \ +bug-324535-il.dll$(PLATFORM_AOT_SUFFIX) \ +bug-36848-a.dll$(PLATFORM_AOT_SUFFIX) \ +bug-81691-b.dll$(PLATFORM_AOT_SUFFIX) \ +bug-327438.2.exe$(PLATFORM_AOT_SUFFIX) \ +bug-81466-lib.dll$(PLATFORM_AOT_SUFFIX) + # # Test that no symbols are missed in eglib-remap.h # OK_G_SYMBOLS = 'g_list\|g_slist\|g_concat_dir_and_file\|g_Ctoc\' -SGEN_REGULAR_TESTS = \ +SGEN_REGULAR_TESTS_MOBILE_STATIC_NOT_SUPPORTED = \ + sgen-domain-unload.exe \ + sgen-domain-unload-2.exe + +SGEN_REGULAR_TESTS_UNIVERSAL = \ finalizer-wait.exe \ critical-finalizers.exe \ sgen-descriptors.exe \ sgen-gshared-vtype.exe \ - sgen-domain-unload.exe \ - sgen-domain-unload-2.exe \ sgen-weakref-stress.exe \ sgen-cementing-stress.exe \ sgen-case-23400.exe \ @@ -1118,6 +1227,13 @@ SGEN_REGULAR_TESTS = \ gc-graystack-stress.exe \ bug-17590.exe +@INSTALL_MOBILE_STATIC_FALSE@SGEN_REGULAR_TESTS = \ +@INSTALL_MOBILE_STATIC_FALSE@ $(SGEN_REGULAR_TESTS_MOBILE_STATIC_NOT_SUPPORTED) \ +@INSTALL_MOBILE_STATIC_FALSE@ $(SGEN_REGULAR_TESTS_UNIVERSAL) + +@INSTALL_MOBILE_STATIC_TRUE@SGEN_REGULAR_TESTS = \ +@INSTALL_MOBILE_STATIC_TRUE@ $(SGEN_REGULAR_TESTS_UNIVERSAL) + SGEN_TOGGLEREF_TESTS = \ sgen-toggleref.exe @@ -1135,7 +1251,10 @@ AOT_CONFIGURATIONS = \ "|regular" \ "--gc=boehm|boehm" -GSHARED_TESTS = \ +GSHARED_TESTS_MOBILE_STATIC_NOT_SUPPORTED = \ + generic-type-builder.2.exe + +GSHARED_TESTS_UNIVERSAL = \ generics-sharing.2.exe shared-generic-methods.2.exe \ shared-generic-synchronized.2.exe generic-initobj.2.exe \ generics-sharing-other-exc.2.exe generic-box.2.exe \ @@ -1151,7 +1270,7 @@ GSHARED_TESTS = \ generic-exceptions.2.exe generic-delegate2.2.exe \ generic-virtual2.2.exe generic-valuetype-interface.2.exe \ generic-valuetype-newobj.2.exe generic-valuetype-newobj2.2.exe \ - generic-getgenericarguments.2.exe generic-type-builder.2.exe \ + generic-getgenericarguments.2.exe \ generic-synchronized.2.exe generic-delegate-ctor.2.exe \ generic-constrained.2.exe bug-431413.2.exe \ generic-virtual-invoke.2.exe generic-typedef.2.exe \ @@ -1163,6 +1282,13 @@ GSHARED_TESTS = \ generic-type-load-exception.2.exe bug-616463.exe \ bug-1147.exe +@INSTALL_MOBILE_STATIC_FALSE@GSHARED_TESTS = \ +@INSTALL_MOBILE_STATIC_FALSE@ $(GSHARED_TESTS_MOBILE_STATIC_NOT_SUPPORTED) \ +@INSTALL_MOBILE_STATIC_FALSE@ $(GSHARED_TESTS_UNIVERSAL) + +@INSTALL_MOBILE_STATIC_TRUE@GSHARED_TESTS = \ +@INSTALL_MOBILE_STATIC_TRUE@ $(GSHARED_TESTS_UNIVERSAL) + OOM_TESTS = \ gc-oom-handling.exe \ gc-oom-handling2.exe @@ -1578,7 +1704,7 @@ uninstall-am: check-local: assemblyresolve/test/asm.dll testjit test-generic-sharing test-type-load test-cattr-type-load test-reflection-load-with-context test_platform \ - test-console-output test-messages test-env-options test-unhandled-exception-2 test-appdomain-unload test-process-stress rm-empty-logs + test-console-output test-messages test-env-options test-unhandled-exception-2 $(FEATUREFUL_RUNTIME_TEST) test-process-stress rm-empty-logs check-full: test-sgen check-local check-parallel: compile-tests check-full @@ -1593,8 +1719,20 @@ aotcheck: testaot gshared-aot %.exe: %.il $(ILASM) -out:$@ $< -%.exe: %.cs TestDriver.dll - $(MCS) -r:System.dll -r:System.Xml.dll -r:System.Core.dll -r:TestDriver.dll -r:Mono.Posix.dll -out:$@ $< +%.exe: %.cs $(TEST_DRIVER_DEPEND) + $(MCS) -r:System.dll -r:System.Xml.dll -r:System.Core.dll -r:TestDriver.dll $(TEST_DRIVER_HARD_KILL_FEATURE) -out:$@ $< + +%.dll: %.cs + $(MCS) -r:System.dll -target:library -out:$@ $< + +TestingReferenceReferenceAssembly.dll: TestingReferenceReferenceAssembly.cs TestingReferenceAssembly.dll + $(MCS) -r:TestingReferenceAssembly.dll -target:library -out:$@ $< + +%.exe$(PLATFORM_AOT_SUFFIX): %.exe + $(RUNTIME) $(AOT_BUILD_FLAGS) $< + +%.dll$(PLATFORM_AOT_SUFFIX): %.dll + $(RUNTIME) $(AOT_BUILD_FLAGS) $< # mkbundle works on ppc, but the pkg-config POC doesn't when run with make test @POWERPC_TRUE@test_platform: @@ -1607,8 +1745,11 @@ aotcheck: testaot gshared-aot @HOST_WIN32_FALSE@@X86_TRUE@test_platform: test-eglib-remap +@INSTALL_MOBILE_STATIC_TRUE@prereqs: $(PREREQSI_IL_AOT) $(PREREQSI_CS_AOT) $(AOT_EXTRA_LIBS) +@INSTALL_MOBILE_STATIC_FALSE@prereqs: $(PREREQSI_IL) $(PREREQSI_CS) + # Target to precompile the test executables -tests: $(TESTSI_CS) $(TESTSI_IL) $(TESTBS) libtest.la $(PREREQSI_IL) $(PREREQSI_CS) $(GSHARED_TESTS) +tests: $(TESTSI_CS) $(TESTSI_IL) $(TESTBS) libtest.la prereqs $(GSHARED_TESTS) @NACL_CODEGEN_TRUE@test-eglib-remap: @NACL_CODEGEN_FALSE@test-eglib-remap: @NACL_CODEGEN_FALSE@ @echo "Testing eglib remap..." @@ -1632,11 +1773,12 @@ test-sgen : sgen-tests # Precompile the test assemblies in parallel compile-tests: $(MAKE) -j4 $(TESTSI_CS) $(TESTSI_IL) $(TESTBS) libtest.la $(PREREQSI_IL) $(PREREQSI_CS) +@INSTALL_MOBILE_STATIC_TRUE@ $(MAKE) $(PREREQSI_IL_AOT) $(PREREQSI_CS_AOT) $(AOT_EXTRA_LIBS) # Remove empty .stdout and .stderr files for wrench rm-empty-logs: @echo "Removing empty logs..." - @find . '(' -name "*.stdout" -o -name "*.stderr" ')' -empty -exec rm {} \; + find . '(' -name "*.stdout" -o -name "*.stderr" ')' -size 0 -exec rm {} \; assemblyresolve/test/asm.dll: $(MAKE) -C assemblyresolve prereq @@ -1719,11 +1861,11 @@ runtest: $(TESTSI_CS) $(TESTSI_IL) $(TESTBS) libtest.la $(PREREQSI_IL) $(PREREQS runtest-managed: test-runner.exe $(TESTSI_CS) $(TESTSI_IL) $(TESTBS) libtest.la $(PREREQSI_IL) $(PREREQSI_CS) @if [ "x$$CI" = "x1" ]; then disabled_tests="$(DISABLED_TESTS_WRENCH)"; else disabled_tests="$(DISABLED_TESTS)"; fi; \ - $(RUNTIME) --debug ./test-runner.exe -j a --testsuite-name "runtime" --timeout 300 --disabled "$${disabled_tests}" $(TESTSI_CS) $(TESTBS) $(TESTSI_IL) + $(RUNTIME) --debug $(TEST_RUNNER) $(TEST_RUNNER_ARGS) -j a --testsuite-name "runtime" --timeout 300 --disabled "$${disabled_tests}" $(TESTSI_CS) $(TESTBS) $(TESTSI_IL) runtest-managed-serial: test-runner.exe $(TESTSI_CS) $(TESTSI_IL) $(TESTBS) libtest.la $(PREREQSI_IL) $(PREREQSI_CS) @if [ "x$$CI" = "x1" ]; then disabled_tests="$(DISABLED_TESTS_WRENCH)"; else disabled_tests="$(DISABLED_TESTS)"; fi; \ - $(RUNTIME) --debug ./test-runner.exe -j 1 --testsuite-name "runtime" --disabled "$${disabled_tests}" $(TESTSI_CS) $(TESTBS) $(TESTSI_IL) + $(RUNTIME) --debug $(TEST_RUNNER) $(TEST_RUNNER_ARGS) -j 1 --testsuite-name "runtime" --disabled "$${disabled_tests}" $(TESTSI_CS) $(TESTBS) $(TESTSI_IL) testjit: @if test x$(M) != x0; then $(MAKE) runtest-managed; else $(MAKE) runtest; fi @@ -1771,14 +1913,14 @@ testbundle: console.exe @$(MKBUNDLE) --static console.exe > mkbundle.stdout @$(with_mono_path) MONO_CFG_DIR=$(mono_cfg_dir) ./a.out >> mkbundle.stdout @- rm -rf a.out -test-type-load: TestDriver.dll +test-type-load: $(TEST_DRIVER_DEPEND) @$(ILASM) /dll /output:load-missing.dll $(srcdir)/load-missing.il > /dev/null @$(MCS) -t:library -out:t.dll -d:FOUND $(srcdir)/t-missing.cs @$(MCS) -r:TestDriver.dll -r:load-missing.dll -r:t.dll -out:load-exceptions.exe $(srcdir)/load-exceptions.cs @$(MCS) -t:library -out:t.dll $(srcdir)/t-missing.cs @echo "Testing load-exception.exe..." @$(RUNTIME) load-exceptions.exe > load-exceptions.exe.stdout 2> load-exceptions.exe.stderr -test-cattr-type-load: TestDriver.dll custom-attr-errors.cs custom-attr-errors-lib.cs +test-cattr-type-load: $(TEST_DRIVER_DEPEND) custom-attr-errors.cs custom-attr-errors-lib.cs $(MCS) -D:WITH_MEMBERS /t:library $(srcdir)/custom-attr-errors-lib.cs $(MCS) -r:TestDriver.dll -r:custom-attr-errors-lib.dll $(srcdir)/custom-attr-errors.cs $(MCS) /t:library $(srcdir)/custom-attr-errors-lib.cs @@ -1813,21 +1955,21 @@ sgen-regular-tests: $(SGEN_REGULAR_TESTS) $(MAKE) sgen-regular-tests-ms-split-clear-at-gc sgen-regular-tests-plain: $(SGEN_REGULAR_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="" MONO_GC_PARAMS="" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_REGULAR_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="" MONO_GC_PARAMS="" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_REGULAR_TESTS) sgen-regular-tests-ms-conc: $(SGEN_REGULAR_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="" MONO_GC_PARAMS="major=marksweep-conc" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_REGULAR_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="" MONO_GC_PARAMS="major=marksweep-conc" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_REGULAR_TESTS) sgen-regular-tests-ms-conc-split: $(SGEN_REGULAR_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="" MONO_GC_PARAMS="major=marksweep-conc,minor=split" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_REGULAR_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="" MONO_GC_PARAMS="major=marksweep-conc,minor=split" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_REGULAR_TESTS) sgen-regular-tests-ms-split: $(SGEN_REGULAR_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="" MONO_GC_PARAMS="minor=split" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_REGULAR_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="" MONO_GC_PARAMS="minor=split" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_REGULAR_TESTS) sgen-regular-tests-ms-split-95: $(SGEN_REGULAR_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="" MONO_GC_PARAMS="minor=split,alloc-ratio=95" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_REGULAR_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="" MONO_GC_PARAMS="minor=split,alloc-ratio=95" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_REGULAR_TESTS) sgen-regular-tests-plain-clear-at-gc: $(SGEN_REGULAR_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="clear-at-gc" MONO_GC_PARAMS="" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_REGULAR_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="clear-at-gc" MONO_GC_PARAMS="" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_REGULAR_TESTS) sgen-regular-tests-ms-conc-clear-at-gc: $(SGEN_REGULAR_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="clear-at-gc" MONO_GC_PARAMS="major=marksweep-conc" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_REGULAR_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="clear-at-gc" MONO_GC_PARAMS="major=marksweep-conc" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_REGULAR_TESTS) sgen-regular-tests-ms-split-clear-at-gc: $(SGEN_REGULAR_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="clear-at-gc" MONO_GC_PARAMS="minor=split" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_REGULAR_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="clear-at-gc" MONO_GC_PARAMS="minor=split" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_REGULAR_TESTS) sgen-toggleref-tests: $(SGEN_TOGGLEREF_TESTS) $(MAKE) sgen-toggleref-tests-plain @@ -1840,21 +1982,21 @@ sgen-toggleref-tests: $(SGEN_TOGGLEREF_TESTS) $(MAKE) sgen-toggleref-tests-ms-split-clear-at-gc sgen-toggleref-tests-plain: $(SGEN_TOGGLEREF_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="" MONO_GC_PARAMS="toggleref-test" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_TOGGLEREF_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="" MONO_GC_PARAMS="toggleref-test" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_TOGGLEREF_TESTS) sgen-toggleref-tests-ms-conc: $(SGEN_TOGGLEREF_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="" MONO_GC_PARAMS="toggleref-test,major=marksweep-conc" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_TOGGLEREF_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="" MONO_GC_PARAMS="toggleref-test,major=marksweep-conc" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_TOGGLEREF_TESTS) sgen-toggleref-tests-ms-conc-split: $(SGEN_TOGGLEREF_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="" MONO_GC_PARAMS="toggleref-test,major=marksweep-conc,minor=split" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_TOGGLEREF_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="" MONO_GC_PARAMS="toggleref-test,major=marksweep-conc,minor=split" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_TOGGLEREF_TESTS) sgen-toggleref-tests-ms-split: $(SGEN_TOGGLEREF_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="" MONO_GC_PARAMS="toggleref-test,minor=split" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_TOGGLEREF_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="" MONO_GC_PARAMS="toggleref-test,minor=split" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_TOGGLEREF_TESTS) sgen-toggleref-tests-ms-split-95: $(SGEN_TOGGLEREF_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="" MONO_GC_PARAMS="toggleref-test,minor=split,alloc-ratio=95" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_TOGGLEREF_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="" MONO_GC_PARAMS="toggleref-test,minor=split,alloc-ratio=95" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_TOGGLEREF_TESTS) sgen-toggleref-tests-plain-clear-at-gc: $(SGEN_TOGGLEREF_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="clear-at-gc" MONO_GC_PARAMS="toggleref-test" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_TOGGLEREF_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="clear-at-gc" MONO_GC_PARAMS="toggleref-test" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_TOGGLEREF_TESTS) sgen-toggleref-tests-ms-conc-clear-at-gc: $(SGEN_TOGGLEREF_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="clear-at-gc" MONO_GC_PARAMS="toggleref-test,major=marksweep-conc" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_TOGGLEREF_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="clear-at-gc" MONO_GC_PARAMS="toggleref-test,major=marksweep-conc" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_TOGGLEREF_TESTS) sgen-toggleref-tests-ms-split-clear-at-gc: $(SGEN_TOGGLEREF_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="clear-at-gc" MONO_GC_PARAMS="toggleref-test,minor=split" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_TOGGLEREF_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="clear-at-gc" MONO_GC_PARAMS="toggleref-test,minor=split" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_TOGGLEREF_TESTS) sgen-bridge-tests: $(SGEN_BRIDGE_TESTS) $(MAKE) sgen-bridge-tests-plain @@ -1867,21 +2009,21 @@ sgen-bridge-tests: $(SGEN_BRIDGE_TESTS) $(MAKE) sgen-bridge-tests-ms-split-tarjan-bridge sgen-bridge-tests-plain: $(SGEN_BRIDGE_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=Bridge" MONO_GC_PARAMS="" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=Bridge" MONO_GC_PARAMS="" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE_TESTS) sgen-bridge-tests-ms-conc: $(SGEN_BRIDGE_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=Bridge" MONO_GC_PARAMS="major=marksweep-conc" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=Bridge" MONO_GC_PARAMS="major=marksweep-conc" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE_TESTS) sgen-bridge-tests-ms-split: $(SGEN_BRIDGE_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=Bridge" MONO_GC_PARAMS="minor=split" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=Bridge" MONO_GC_PARAMS="minor=split" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE_TESTS) sgen-bridge-tests-plain-new-bridge: $(SGEN_BRIDGE_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=Bridge" MONO_GC_PARAMS="bridge-implementation=new" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=Bridge" MONO_GC_PARAMS="bridge-implementation=new" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE_TESTS) sgen-bridge-tests-ms-conc-new-bridge: $(SGEN_BRIDGE_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=Bridge" MONO_GC_PARAMS="bridge-implementation=new,major=marksweep-conc" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=Bridge" MONO_GC_PARAMS="bridge-implementation=new,major=marksweep-conc" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE_TESTS) sgen-bridge-tests-ms-split-new-bridge: $(SGEN_BRIDGE_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=Bridge" MONO_GC_PARAMS="bridge-implementation=new,minor=split" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=Bridge" MONO_GC_PARAMS="bridge-implementation=new,minor=split" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE_TESTS) sgen-bridge-tests-plain-tarjan-bridge: $(SGEN_BRIDGE_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=Bridge" MONO_GC_PARAMS="bridge-implementation=tarjan" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=Bridge" MONO_GC_PARAMS="bridge-implementation=tarjan" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE_TESTS) sgen-bridge-tests-ms-split-tarjan-bridge: $(SGEN_BRIDGE_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=Bridge" MONO_GC_PARAMS="bridge-implementation=tarjan,minor=split" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=Bridge" MONO_GC_PARAMS="bridge-implementation=tarjan,minor=split" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE_TESTS) sgen-bridge2-tests: $(SGEN_BRIDGE2_TESTS) $(MAKE) sgen-bridge2-tests-plain @@ -1894,21 +2036,21 @@ sgen-bridge2-tests: $(SGEN_BRIDGE2_TESTS) $(MAKE) sgen-bridge2-tests-ms-split-tarjan-bridge sgen-bridge2-tests-plain: $(SGEN_BRIDGE2_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=2Bridge" MONO_GC_PARAMS="" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE2_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=2Bridge" MONO_GC_PARAMS="" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE2_TESTS) sgen-bridge2-tests-ms-conc: $(SGEN_BRIDGE2_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=2Bridge" MONO_GC_PARAMS="major=marksweep-conc" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE2_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=2Bridge" MONO_GC_PARAMS="major=marksweep-conc" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE2_TESTS) sgen-bridge2-tests-ms-split: $(SGEN_BRIDGE2_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=2Bridge" MONO_GC_PARAMS="minor=split" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE2_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=2Bridge" MONO_GC_PARAMS="minor=split" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE2_TESTS) sgen-bridge2-tests-plain-new-bridge: $(SGEN_BRIDGE2_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=2Bridge" MONO_GC_PARAMS="bridge-implementation=new" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE2_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=2Bridge" MONO_GC_PARAMS="bridge-implementation=new" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE2_TESTS) sgen-bridge2-tests-ms-conc-new-bridge: $(SGEN_BRIDGE2_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=2Bridge" MONO_GC_PARAMS="bridge-implementation=new,major=marksweep-conc" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE2_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=2Bridge" MONO_GC_PARAMS="bridge-implementation=new,major=marksweep-conc" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE2_TESTS) sgen-bridge2-tests-ms-split-new-bridge: $(SGEN_BRIDGE2_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=2Bridge" MONO_GC_PARAMS="bridge-implementation=new,minor=split" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE2_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=2Bridge" MONO_GC_PARAMS="bridge-implementation=new,minor=split" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE2_TESTS) sgen-bridge2-tests-plain-tarjan-bridge: $(SGEN_BRIDGE2_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=2Bridge" MONO_GC_PARAMS="bridge-implementation=tarjan" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE2_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=2Bridge" MONO_GC_PARAMS="bridge-implementation=tarjan" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE2_TESTS) sgen-bridge2-tests-ms-split-tarjan-bridge: $(SGEN_BRIDGE2_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=2Bridge" MONO_GC_PARAMS="bridge-implementation=tarjan,minor=split" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE2_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=2Bridge" MONO_GC_PARAMS="bridge-implementation=tarjan,minor=split" $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE2_TESTS) sgen-bridge3-tests: $(SGEN_BRIDGE3_TESTS) $(MAKE) sgen-bridge3-tests-plain @@ -1921,21 +2063,21 @@ sgen-bridge3-tests: $(SGEN_BRIDGE3_TESTS) $(MAKE) sgen-bridge3-tests-ms-split-tarjan-bridge sgen-bridge3-tests-plain: $(SGEN_bridge3_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=3Bridge" MONO_GC_PARAMS="" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE3_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=3Bridge" MONO_GC_PARAMS="" $(RUNTIME) $(TEST_RUNNER) --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE3_TESTS) sgen-bridge3-tests-ms-conc: $(SGEN_BRIDGE3_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=3Bridge" MONO_GC_PARAMS="major=marksweep-conc" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE3_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=3Bridge" MONO_GC_PARAMS="major=marksweep-conc" $(RUNTIME) $(TEST_RUNNER) --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE3_TESTS) sgen-bridge3-tests-ms-split: $(SGEN_BRIDGE3_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=3Bridge" MONO_GC_PARAMS="minor=split" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE3_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=3Bridge" MONO_GC_PARAMS="minor=split" $(RUNTIME) $(TEST_RUNNER) --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE3_TESTS) sgen-bridge3-tests-plain-new-bridge: $(SGEN_BRIDGE3_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=3Bridge" MONO_GC_PARAMS="bridge-implementation=new" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE3_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=3Bridge" MONO_GC_PARAMS="bridge-implementation=new" $(RUNTIME) $(TEST_RUNNER) --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE3_TESTS) sgen-bridge3-tests-ms-conc-new-bridge: $(SGEN_BRIDGE3_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=3Bridge" MONO_GC_PARAMS="bridge-implementation=new,major=marksweep-conc" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE3_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=3Bridge" MONO_GC_PARAMS="bridge-implementation=new,major=marksweep-conc" $(RUNTIME) $(TEST_RUNNER) --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE3_TESTS) sgen-bridge3-tests-ms-split-new-bridge: $(SGEN_BRIDGE3_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=3Bridge" MONO_GC_PARAMS="bridge-implementation=new,minor=split" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE3_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=3Bridge" MONO_GC_PARAMS="bridge-implementation=new,minor=split" $(RUNTIME) $(TEST_RUNNER) --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE3_TESTS) sgen-bridge3-tests-plain-tarjan-bridge: $(SGEN_BRIDGE3_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=3Bridge" MONO_GC_PARAMS="bridge-implementation=tarjan" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE3_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=3Bridge" MONO_GC_PARAMS="bridge-implementation=tarjan" $(RUNTIME) $(TEST_RUNNER) --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE3_TESTS) sgen-bridge3-tests-ms-split-tarjan-bridge: $(SGEN_BRIDGE3_TESTS) test-runner.exe - MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=3Bridge" MONO_GC_PARAMS="bridge-implementation=tarjan,minor=split" $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE3_TESTS) + MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="bridge=3Bridge" MONO_GC_PARAMS="bridge-implementation=tarjan,minor=split" $(RUNTIME) $(TEST_RUNNER) --testsuite-name $@ --timeout 900 $(SGEN_BRIDGE3_TESTS) #LLVM crashes, got to fix it first. # "--llvm|llvm" \ @@ -1969,15 +2111,17 @@ test-aot: echo "$${passed} test(s) passed. $${failed} test(s) did not pass."; \ if [ $${failed} != 0 ]; then echo -e "\nFailed tests:\n"; \ for i in $${failed_tests}; do echo $${i}; done; exit 1; fi -runtime-invoke.gen.exe: TestDriver.dll gen-runtime-invoke.exe +runtime-invoke.gen.exe: $(TEST_DRIVER_DEPEND) gen-runtime-invoke.exe $(RUNTIME) gen-runtime-invoke.exe > runtime-invoke.gen.cs $(MCS) -out:runtime-invoke.gen.exe -r:TestDriver.dll runtime-invoke.gen.cs -imt_big_iface_test.exe: TestDriver.dll make-imt-test.exe +imt_big_iface_test.exe: $(TEST_DRIVER_DEPEND) make-imt-test.exe $(RUNTIME) make-imt-test.exe > imt_big_iface_test.cs $(MCS) -out:imt_big_iface_test.exe -r:TestDriver.dll imt_big_iface_test.cs -test-inline-call-stack-library.dll: TestDriver.dll $(srcdir)/test-inline-call-stack-library.cs +test-inline-call-stack-library.dll: $(TEST_DRIVER_DEPEND) $(srcdir)/test-inline-call-stack-library.cs $(MCS) -t:library -out:test-inline-call-stack-library.dll $(srcdir)/test-inline-call-stack-library.cs -test-inline-call-stack.exe: TestDriver.dll test-inline-call-stack-library.dll $(srcdir)/test-inline-call-stack.cs +@INSTALL_MOBILE_STATIC_TRUE@ $(RUNTIME) $(AOT_BUILD_FLAGS) $@ + +test-inline-call-stack.exe: $(TEST_DRIVER_DEPEND) test-inline-call-stack-library.dll $(srcdir)/test-inline-call-stack.cs $(MCS) -r:TestDriver.dll -r:test-inline-call-stack-library.dll -out:test-inline-call-stack.exe $(srcdir)/test-inline-call-stack.cs unhandled-exception-test-case.1.cs: unhandled-exception-test-case.2.cs cp unhandled-exception-test-case.2.cs unhandled-exception-test-case.1.cs @@ -2012,10 +2156,12 @@ bug-81673.exe bug-81673-interface.dll: $(srcdir)/bug-81673.cs $(srcdir)/bug-8167 $(MCS) -target:library -out:bug-81673-interface.dll $(srcdir)/bug-81673-interface.cs $(MCS) -out:bug-81673.exe -r:bug-81673-interface.dll $(srcdir)/bug-81673.cs $(MCS) -define:WITH_STOP -target:library -out:bug-81673-interface.dll $(srcdir)/bug-81673-interface.cs +@INSTALL_MOBILE_STATIC_TRUE@ $(RUNTIME) $(AOT_BUILD_FLAGS) $@ bug-36848.exe bug-36848-a.dll: $(srcdir)/bug-36848.cs $(srcdir)/bug-36848-a.cs $(MCS) -target:library -out:bug-36848-a.dll $(srcdir)/bug-36848-a.cs $(MCS) -r:bug-36848-a.dll -out:bug-36848.exe $(srcdir)/bug-36848.cs $(MCS) -target:library -out:bug-36848-a.dll $(srcdir)/bug-36848-a.cs /define:WITH_STOP +@INSTALL_MOBILE_STATIC_TRUE@ $(RUNTIME) $(AOT_BUILD_FLAGS) $@ bug-81691.exe bug-81691-b.dll: $(srcdir)/bug-81691.cs $(srcdir)/bug-81691-a.cs $(srcdir)/bug-81691-b.cs $(MCS) -target:library -out:bug-81691-a.dll $(srcdir)/bug-81691-a.cs $(MCS) -target:library -out:bug-81691-b.dll -r:bug-81691-a.dll $(srcdir)/bug-81691-b.cs @@ -2024,18 +2170,23 @@ bug-81691.exe bug-81691-b.dll: $(srcdir)/bug-81691.cs $(srcdir)/bug-81691-a.cs $ bug-81691.exe: bug-81691-b.dll bug-81466-lib.dll: bug-81466-lib.il $(ILASM) /dll /output:bug-81466-lib.dll $(srcdir)/bug-81466-lib.il +@INSTALL_MOBILE_STATIC_TRUE@ $(RUNTIME) $(AOT_BUILD_FLAGS) $@ bug-81466.exe: bug-81466.il bug-81466-lib.dll $(ILASM) /exe /output:bug-81466.exe $(srcdir)/bug-81466.il bug-324535-il.dll : bug-324535-il.il $(ILASM) /dll /output:bug-324535-il.dll $(srcdir)/bug-324535-il.il +@INSTALL_MOBILE_STATIC_TRUE@ $(RUNTIME) $(AOT_BUILD_FLAGS) $@ bug-324535.exe : bug-324535.cs bug-324535-il.dll $(MCS) -r:bug-324535-il.dll -out:bug-324535.exe $(srcdir)/bug-324535.cs custom-modifiers-lib.dll: custom-modifiers-lib.il $(ILASM) /dll /output:custom-modifiers-lib.dll $(srcdir)/custom-modifiers-lib.il +@INSTALL_MOBILE_STATIC_TRUE@ $(RUNTIME) $(AOT_BUILD_FLAGS) $@ custom-modifiers.2.exe: custom-modifiers.2.cs custom-modifiers-lib.dll $(MCS) -r:custom-modifiers-lib.dll -out:custom-modifiers.2.exe $(srcdir)/custom-modifiers.2.cs bug-382986-lib.dll: bug-382986-lib.cs $(MCS) -target:library -out:$@ $(srcdir)/bug-382986-lib.cs +@INSTALL_MOBILE_STATIC_TRUE@ $(RUNTIME) $(AOT_BUILD_FLAGS) $@ + bug-382986.exe: bug-382986.cs bug-382986-lib.dll $(MCS) -out:$@ -r:bug-382986-lib.dll $(srcdir)/bug-382986.cs bug-17537-helper.exe: bug-17537-helper.cs @@ -2053,14 +2204,17 @@ test-coreclr-security : coreclr-security.exe @$(RUNTIME_MOONLIGHT) --security=core-clr-test coreclr-security.exe generic-unboxing.2.dll : generic-unboxing.2.il $(ILASM) /dll /output:generic-unboxing.2.dll $(srcdir)/generic-unboxing.2.il +@INSTALL_MOBILE_STATIC_TRUE@ $(RUNTIME) $(AOT_BUILD_FLAGS) $@ generic-boxing.2.dll : generic-boxing.2.il generic-unboxing.2.dll $(ILASM) /dll /output:generic-boxing.2.dll $(srcdir)/generic-boxing.2.il +@INSTALL_MOBILE_STATIC_TRUE@ $(RUNTIME) $(AOT_BUILD_FLAGS) $@ generic-unbox.2.exe : generic-unbox.2.cs generic-unboxing.2.dll $(MCS) -r:generic-unboxing.2.dll -out:$@ $(srcdir)/generic-unbox.2.cs generic-box.2.exe : generic-box.2.cs generic-unboxing.2.dll generic-boxing.2.dll $(MCS) -r:generic-unboxing.2.dll,generic-boxing.2.dll -out:$@ $(srcdir)/generic-box.2.cs generic-delegate2-lib.2.dll : generic-delegate2-lib.2.il $(ILASM) /dll /output:$@ $(srcdir)/generic-delegate2-lib.2.il +@INSTALL_MOBILE_STATIC_TRUE@ $(RUNTIME) $(AOT_BUILD_FLAGS) $@ generic-delegate2.2.exe : generic-delegate2.2.cs generic-delegate2-lib.2.dll $(MCS) -r:generic-delegate2-lib.2.dll -out:$@ $(srcdir)/generic-delegate2.2.cs @@ -2083,7 +2237,7 @@ test-generic-sharing-normal: $(GSHARED_TESTS) done test-generic-sharing-managed: test-runner.exe $(GSHARED_TESTS) - @$(RUNTIME) ./test-runner.exe -j a --testsuite-name "gshared" --opt-sets "gshared gshared,shared gshared,-inline gshared,-inline,shared" $(GSHARED_TESTS) + @$(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) -j a --testsuite-name "gshared" --disabled "$(DISABLED_TESTS)" --opt-sets "gshared gshared,shared gshared,-inline gshared,-inline,shared" $(GSHARED_TESTS) @NACL_CODEGEN_TRUE@test-generic-sharing: @NACL_CODEGEN_FALSE@test-generic-sharing: @@ -2095,7 +2249,7 @@ test-async-exceptions : async-exceptions.exe for i in `echo 0 1 2 3 4 5 6 7 8 9 10`; do $(RUNTIME) --inject-async-exc Tests:bar $$i async-exceptions.exe || exit 1; done modules-m1.netmodule: modules-m1.cs $(MCS) -out:$@ /target:module $(srcdir)/modules-m1.cs -modules.exe: modules.cs modules-m1.netmodule TestDriver.dll +modules.exe: modules.cs modules-m1.netmodule $(TEST_DRIVER_DEPEND) $(MCS) -out:$@ /addmodule:modules-m1.netmodule -r:TestDriver.dll $(srcdir)/modules.cs # Useful if mono is compiled with --enable-shared=no @@ -2128,13 +2282,13 @@ test-oom: $(OOM_TESTS) @HOST_WIN32_FALSE@ $(MAKE) test-unhandled-exception-2-255-without-managed-handler @HOST_WIN32_FALSE@test-unhandled-exception-2-1-with-managed-handler: $(UNHANDLED_EXCEPTION_1_TESTS) test-runner.exe -@HOST_WIN32_FALSE@ $(RUNTIME) ./test-runner.exe -j a --testsuite-name $@ --expected-exit-code 1 $(UNHANDLED_EXCEPTION_1_TESTS) +@HOST_WIN32_FALSE@ $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) -j a --testsuite-name $@ --disabled "$(DISABLED_TESTS)" --expected-exit-code 1 $(UNHANDLED_EXCEPTION_1_TESTS) @HOST_WIN32_FALSE@test-unhandled-exception-2-1-without-managed-handler: $(UNHANDLED_EXCEPTION_1_TESTS) test-runner.exe -@HOST_WIN32_FALSE@ TEST_UNHANDLED_EXCEPTION_HANDLER=1 $(RUNTIME) ./test-runner.exe -j a --testsuite-name $@ --expected-exit-code 1 $(UNHANDLED_EXCEPTION_1_TESTS) +@HOST_WIN32_FALSE@ TEST_UNHANDLED_EXCEPTION_HANDLER=1 $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) -j a --testsuite-name $@ --disabled "$(DISABLED_TESTS)" --expected-exit-code 1 $(UNHANDLED_EXCEPTION_1_TESTS) @HOST_WIN32_FALSE@test-unhandled-exception-2-255-with-managed-handler: $(UNHANDLED_EXCEPTION_255_TESTS) test-runner.exe -@HOST_WIN32_FALSE@ $(RUNTIME) ./test-runner.exe -j a --testsuite-name $@ --expected-exit-code 255 $(UNHANDLED_EXCEPTION_255_TESTS) +@HOST_WIN32_FALSE@ $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) -j a --testsuite-name $@ --disabled "$(DISABLED_TESTS)" --expected-exit-code 255 $(UNHANDLED_EXCEPTION_255_TESTS) @HOST_WIN32_FALSE@test-unhandled-exception-2-255-without-managed-handler: $(UNHANDLED_EXCEPTION_255_TESTS) test-runner.exe -@HOST_WIN32_FALSE@ TEST_UNHANDLED_EXCEPTION_HANDLER=1 $(RUNTIME) ./test-runner.exe -j a --testsuite-name $@ --expected-exit-code 255 $(UNHANDLED_EXCEPTION_255_TESTS) +@HOST_WIN32_FALSE@ TEST_UNHANDLED_EXCEPTION_HANDLER=1 $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) -j a --testsuite-name $@ --disabled "$(DISABLED_TESTS)" --expected-exit-code 255 $(UNHANDLED_EXCEPTION_255_TESTS) test-appdomain-unload: appdomain-loader.exe appdomain-tester.exe $(RUNTIME) -O=gshared appdomain-loader.exe > appdomain-loader.exe.1.stdout || exit 1; $(RUNTIME) appdomain-loader.exe > appdomain-loader.exe.2.stdout || exit 1; @@ -2147,7 +2301,7 @@ test-console-output: console-output.exe && diff -w console-output.exe.stderr $(srcdir)/console-output.exe.stderr.expected test-process-stress: $(PROCESS_STRESS_TESTS) test-runner.exe - $(RUNTIME) ./test-runner.exe --testsuite-name $@ --timeout 600 $(PROCESS_STRESS_TESTS) + $(RUNTIME) $(TEST_RUNNER) $(TEST_RUNNER_ARGS) --testsuite-name $@ --timeout 600 $(PROCESS_STRESS_TESTS) coreclr-gcstress: $(MAKE) -C $(mono_build_root)/acceptance-tests coreclr-gcstress diff --git a/mono/tests/abort-cctor.cs b/mono/tests/abort-cctor.cs new file mode 100644 index 0000000000..34f87808da --- /dev/null +++ b/mono/tests/abort-cctor.cs @@ -0,0 +1,332 @@ +using System; +using System.Diagnostics; +using System.Threading; +using System.Runtime.CompilerServices; + +class Driver +{ + public static ManualResetEvent mre1 = new ManualResetEvent (false); + public static ManualResetEvent mre2 = new ManualResetEvent (false); + + class StaticConstructor1 + { + internal static bool gotToEnd, caughtException; + static StaticConstructor1 () + { + try { + Console.WriteLine ("StaticConstructor1.StaticConstructor1 (1)"); + Driver.mre1.Set (); + var sw = Stopwatch.StartNew (); + Thread.Sleep (1000); + sw.Stop (); + typeof (string).GetMethods (); + //XXX we assume that if we slept less than 900ms we got aborted + if (sw.ElapsedMilliseconds < 900) + throw new Exception ("Bad abort broke our sleep"); + Console.WriteLine ("StaticConstructor1.StaticConstructor1 (2) waited {0}", sw.ElapsedMilliseconds); + gotToEnd = true; + } catch (Exception e) { + caughtException = true; + throw; + } + } + + public static void Init () + { + Console.WriteLine ("StaticConstructor1.Init"); + } + } + + [MethodImplAttribute (MethodImplOptions.NoInlining)] + static void IsStaticConstructor1Viable () { + new StaticConstructor1 (); + Console.WriteLine ("Did it get to the end? {0} Did it catch an exception {1}", StaticConstructor1.gotToEnd, StaticConstructor1.caughtException); + if (!StaticConstructor1.gotToEnd) /* the TAE must not land during a .cctor */ + Environment.Exit (1); + if (StaticConstructor1.caughtException) + Environment.Exit (1); + + } + + static void Test1 () + { + Console.WriteLine ("Test 1:"); + + Driver.mre1.Reset (); + Driver.mre2.Reset (); + + Thread thread = new Thread (() => { + try { + StaticConstructor1.Init (); + } catch (Exception e) { + Console.WriteLine ("StaticConstructor1::init caught exception {0}", e); + + if (!(e is ThreadAbortException)) + throw; + } + }); + + thread.Start (); + + Driver.mre1.WaitOne (); + + // The ThreadAbortException should land while in + // the StaticConstructor1.cctor. The exception should + // be queued, and be rethrown when exiting the cctor. + thread.Abort (); + + thread.Join (); + + //is StaticConstructor1 viable? + try { + IsStaticConstructor1Viable (); + Console.WriteLine ("StaticConstructor1 is viable"); /* a TAE doesn't make a type unusable */ + } catch (TypeInitializationException e) { + Console.WriteLine ("StaticConstructor1 not viable"); + Environment.Exit (1); + } + } + + class StaticConstructor2Exception : Exception {} + + class StaticConstructor2 + { + static StaticConstructor2 () + { + Console.WriteLine ("StaticConstructor2.StaticConstructor2 (1)"); + Driver.mre1.Set (); + throw new StaticConstructor2Exception (); + /* Unreachable */ + Driver.mre2.Set (); + Console.WriteLine ("StaticConstructor2.StaticConstructor2 (2)"); + } + + public static void Init () + { + Console.WriteLine ("StaticConstructor2.Init"); + } + } + + [MethodImplAttribute (MethodImplOptions.NoInlining)] + static void IsStaticConstructor2Viable () { + new StaticConstructor2 (); + } + + + static void Test2 () + { + Console.WriteLine ("Test 2:"); + + Driver.mre1.Reset (); + Driver.mre2.Reset (); + + Thread thread = new Thread (() => { + try { + StaticConstructor2.Init (); + } catch (TypeInitializationException e) { + Console.WriteLine (e); + + if (!(e.InnerException is StaticConstructor2Exception)) + throw; + } + }); + + thread.Start (); + + Driver.mre1.WaitOne (); + + // A InvalidOperationException should be thrown while in + // the StaticConstructor2.cctor. The exception should + // be wrapped in a TypeInitializationException. + + if (Driver.mre2.WaitOne (500)) { + /* We shouldn't reach Driver.mre.Set () in StaticConstructor2.cctor */ + Environment.Exit (1); + } + + thread.Join (); + + //is StaticConstructor2 viable? + try { + IsStaticConstructor2Viable (); + Console.WriteLine ("StaticConstructor2 is viable"); + /* A regular exception escaping the .cctor makes the type not usable */ + Environment.Exit (1); + } catch (TypeInitializationException e) { + Console.WriteLine ("StaticConstructor2 not viable"); + } + + } + + class StaticConstructor3 + { + static StaticConstructor3 () + { + Console.WriteLine ("StaticConstructor3.StaticConstructor3 (1)"); + Driver.mre1.Set (); + Thread.CurrentThread.Abort (); + /* Unreachable */ + Driver.mre2.Set (); + Console.WriteLine ("StaticConstructor3.StaticConstructor3 (2)"); + Environment.Exit (1); + } + + public static void Init () + { + Console.WriteLine ("StaticConstructor3.Init"); + } + } + + [MethodImplAttribute (MethodImplOptions.NoInlining)] + static void IsStaticConstructor3Viable () { + new StaticConstructor3 (); + } + + static void Test3 () + { + Console.WriteLine ("Test 3:"); + + Driver.mre1.Reset (); + Driver.mre2.Reset (); + + Thread thread = new Thread (() => { + try { + StaticConstructor3.Init (); + Console.WriteLine ("cctor3 didn't throw?!?!"); + /* StaticConstructor3 self aborted */ + Environment.Exit (1); + } catch (ThreadAbortException e) { + Console.WriteLine ("TEST 3: aborted {0}", e); + } + }); + + thread.Start (); + + Driver.mre1.WaitOne (); + + // A InvalidOperationException should be thrown while in + // the StaticConstructor2.cctor. The exception should + // be wrapped in a TypeInitializationException. + + thread.Join (); + + //is StaticConstructor2 viable? + try { + IsStaticConstructor3Viable (); + Console.WriteLine ("StaticConstructor3 is viable"); + /* A regular exception escaping the .cctor makes the type not usable */ + Environment.Exit (1); + } catch (TypeInitializationException e) { + Console.WriteLine ("StaticConstructor3 not viable"); + } + } + + + + + + class StaticConstructor4 + { + internal static bool gotToEnd, caughtException; + + static StaticConstructor4 () + { + try { + Console.WriteLine ("StaticConstructor4.StaticConstructor4 (1)"); + Driver.mre1.Set (); + var sw = Stopwatch.StartNew (); + Thread.Sleep (1000); + sw.Stop (); + typeof (string).GetMethods (); + //XXX we assume that if we slept less than 900ms we got aborted + if (sw.ElapsedMilliseconds < 900) + throw new Exception ("Bad abort broke our sleep"); + Console.WriteLine ("StaticConstructor4.StaticConstructor4 (2) waited {0}", sw.ElapsedMilliseconds); + gotToEnd = true; + } catch (Exception e) { + caughtException = true; + throw; + } + } + + public static void Init () + { + Console.WriteLine ("StaticConstructor4.Init"); + } + } + + static bool got_to_the_end_of_the_finally = false; + + [MethodImplAttribute (MethodImplOptions.NoInlining)] + static void IsStaticConstructor4Viable () { + new StaticConstructor4 (); + Console.WriteLine ("IsStaticConstructor4Viable: Did it get to the end? {0} Did it catch an exception {1} and end of the finally block {2}", StaticConstructor4.gotToEnd, StaticConstructor4.caughtException, got_to_the_end_of_the_finally); + if (!StaticConstructor4.gotToEnd) /* the TAE must not land during a .cctor */ + Environment.Exit (1); + if (StaticConstructor4.caughtException) + Environment.Exit (1); + } + + static void Test4 () + { + Console.WriteLine ("Test 4:"); + + Driver.mre1.Reset (); + Driver.mre2.Reset (); + + Thread thread = new Thread (() => { + try { + + try { + } finally { + StaticConstructor4.Init (); + Console.WriteLine ("Test 4: After the cctor"); + got_to_the_end_of_the_finally = true; + } + } catch (Exception e) { + Console.WriteLine ("StaticConstructor4::init caught exception {0}", e); + if (!(e is ThreadAbortException)) + throw; + if (!got_to_the_end_of_the_finally) + throw new Exception ("Test 4: did not get to the end of the cctor"); + } + }); + + thread.Start (); + + Driver.mre1.WaitOne (); + + // The ThreadAbortException should land while in + // the StaticConstructor4.cctor. The exception should + // be queued, and be rethrown when exiting the cctor. + thread.Abort (); + + thread.Join (); + + if (!got_to_the_end_of_the_finally) { + Console.WriteLine ("Did not get to the end of test 4 cctor"); + Environment.Exit (1); + } + + //is StaticConstructor4viable? + try { + IsStaticConstructor4Viable (); + Console.WriteLine ("StaticConstructor4 is viable"); /* a TAE doesn't make a type unusable */ + } catch (TypeInitializationException e) { + Console.WriteLine ("StaticConstructor4 not viable"); + Environment.Exit (1); + } + } + + + + public static int Main () + { + Test1 (); + Test2 (); + Test3 (); + Test4 (); + Console.WriteLine ("done, all things good"); + return 0; + } +} \ No newline at end of file diff --git a/mono/tests/appdomain-async-invoke.cs b/mono/tests/appdomain-async-invoke.cs deleted file mode 100644 index 3e7894c06c..0000000000 --- a/mono/tests/appdomain-async-invoke.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System; -using System.Threading; -using System.Runtime.Remoting; - -public class Test : MarshalByRefObject { - delegate int GetIntDelegate (); - - static void async_callback (IAsyncResult ar) - { - Console.WriteLine ("Async Callback in domain " + AppDomain.CurrentDomain + " " + ar.AsyncState); - } - - ~Test () { - Console.WriteLine ("in test destructor"); - GetIntDelegate del = new GetIntDelegate (getInt); - AsyncCallback ac = new AsyncCallback (async_callback); - if (del.BeginInvoke (ac, "bla") == null) { - Console.WriteLine ("async result is null"); - Environment.Exit (1); - } - } - - public int getInt () { - Console.WriteLine ("getInt in " + AppDomain.CurrentDomain); - return 123; - } -} - -public class main { - public static int Main (string [] args) { - AppDomain domain = AppDomain.CreateDomain ("newdomain"); - int i; - - for (i = 0; i < 200; ++i) { - domain.CreateInstanceAndUnwrap (typeof (Test).Assembly.FullName, typeof (Test).FullName); - } - - Console.WriteLine ("unloading"); - AppDomain.Unload (domain); - Console.WriteLine ("unloaded"); - - GC.Collect (); - GC.WaitForPendingFinalizers (); - - Console.WriteLine ("done"); - - return 0; - } -} diff --git a/mono/tests/appdomain-client.cs b/mono/tests/appdomain-client.cs deleted file mode 100644 index 5cc311ee36..0000000000 --- a/mono/tests/appdomain-client.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -using System.Security.Policy; -using System.Threading; - -class Client { - - [LoaderOptimization (LoaderOptimization.SingleDomain)] - static int Main (string[] args) - { - int res = 0; - - foreach (string s in args) { - res += Convert.ToInt32 (s); - } - - Console.WriteLine ("(appdomain-client.exe) Sum: " + res); - return res; - } -} diff --git a/mono/tests/appdomain-exit.cs b/mono/tests/appdomain-exit.cs deleted file mode 100644 index 278909331f..0000000000 --- a/mono/tests/appdomain-exit.cs +++ /dev/null @@ -1,16 +0,0 @@ - -using System; - -public class foo { - public static int Main() { - Environment.ExitCode = 2; - AppDomain domain=AppDomain.CreateDomain("Other"); - Console.WriteLine("About to execute"); - domain.ExecuteAssembly("main-exit.exe"); - Console.WriteLine("Execute returns"); - AppDomain.Unload(domain); - Console.WriteLine("finished"); - return 1; - } -} - diff --git a/mono/tests/appdomain-thread-abort.cs b/mono/tests/appdomain-thread-abort.cs deleted file mode 100644 index 77015fb7b4..0000000000 --- a/mono/tests/appdomain-thread-abort.cs +++ /dev/null @@ -1,221 +0,0 @@ -using System; -using System.Threading; -using System.Runtime.Remoting; -using System.Reflection; - -public class JustSomeClass { -} - -public class Test2 : ContextBoundObject -{ - public void Run () { - Thread.CurrentThread.Abort (); - } -} - -public class Test1 : MarshalByRefObject -{ - public bool Run () { - AppDomain d = AppDomain.CreateDomain ("foo2"); - - var t2 = (Test2)d.CreateInstanceAndUnwrap (Assembly.GetExecutingAssembly().FullName, - "Test2"); - try { - t2.Run (); - } catch (ThreadAbortException ex) { - Thread.ResetAbort (); - return true; - } - - return false; - } -} - -public class Test : MarshalByRefObject { - ThreadAbortException exc; - public JustSomeClass other; - - public void doThrow (int n, object state) { - if (n <= 0) - Thread.CurrentThread.Abort (state); - else - doThrow (n - 1, state); - } - - public void abortProxy () { - doThrow (10, this); - } - - public void abortOther () { - other = new JustSomeClass (); - doThrow (10, other); - } - - public void abortString () { - try { - doThrow (10, "bla"); - } catch (ThreadAbortException e) { - exc = e; - } - } - - public void abortOtherIndirect (Test test) { - test.abortOther (); - } - - public object getState () { - return exc.ExceptionState; - } - - public int getInt () { - return 123; - } -} - -public class main { - public static int Main (string [] args) { - AppDomain domain = AppDomain.CreateDomain ("newdomain"); - Test test = (Test) domain.CreateInstanceAndUnwrap (typeof (Test).Assembly.FullName, typeof (Test).FullName); - bool didAbort; - Test testHere = new Test (); - - if (!RemotingServices.IsTransparentProxy (test)) { - Console.WriteLine ("test is no proxy"); - return 5; - } - - try { - test.abortOtherIndirect (testHere); - } catch (ThreadAbortException e) { - object state = e.ExceptionState; - Thread.ResetAbort (); - if ((JustSomeClass)state != testHere.other) { - Console.WriteLine ("other class not preserved in state"); - return 16; - } - } - - try { - didAbort = false; - test.abortString (); - } catch (ThreadAbortException e) { - object state; - state = e.ExceptionState; - Thread.ResetAbort (); - didAbort = true; - if (state == null) { - Console.WriteLine ("state is null"); - return 13; - } else { - if (RemotingServices.IsTransparentProxy (state)) { - Console.WriteLine ("state is proxy"); - return 1; - } - if (!((string)state).Equals ("bla")) { - Console.WriteLine ("state is wrong: " + (string)state); - return 2; - } - } - if (RemotingServices.IsTransparentProxy (e)) { - Console.WriteLine ("exception is proxy"); - return 3; - } - if (test.getState () != null) { - Console.WriteLine ("have state"); - return 12; - } - } - if (!didAbort) { - Console.WriteLine ("no abort"); - return 4; - } - - try { - didAbort = false; - test.abortProxy (); - } catch (ThreadAbortException e) { - object state; - state = e.ExceptionState; - Thread.ResetAbort (); - didAbort = true; - if (state == null) { - Console.WriteLine ("state is null"); - return 14; - } else { - if (!RemotingServices.IsTransparentProxy (state)) { - Console.WriteLine ("state is not proxy"); - return 6; - } - if (((Test)state).getInt () != 123) { - Console.WriteLine ("state doesn't work"); - return 15; - } - } - if (RemotingServices.IsTransparentProxy (e)) { - Console.WriteLine ("exception is proxy"); - return 7; - } - } - if (!didAbort) { - Console.WriteLine ("no abort"); - return 8; - } - - try { - didAbort = false; - test.abortOther (); - } catch (ThreadAbortException e) { - object state = null; - bool stateExc = false; - - didAbort = true; - - try { - state = e.ExceptionState; - Console.WriteLine ("have state"); - } catch (Exception) { - stateExc = true; - /* FIXME: if we put this after the try/catch, mono - quietly quits */ - Thread.ResetAbort (); - } - if (!stateExc) { - Console.WriteLine ("no state exception"); - return 9; - } - - if (RemotingServices.IsTransparentProxy (e)) { - Console.WriteLine ("exception is proxy"); - return 10; - } - } - if (!didAbort) { - Console.WriteLine ("no abort"); - return 11; - } - - // #539394 - // Calling Thread.Abort () from a remoting call throws a ThreadAbortException which - // cannot be caught because the exception handling code is confused by the domain - // transitions - bool res = false; - - Thread thread = new Thread (delegate () { - AppDomain d = AppDomain.CreateDomain ("foo"); - - var t = (Test1)d.CreateInstanceAndUnwrap (Assembly.GetExecutingAssembly().FullName, - "Test1"); - res = t.Run (); - }); - - thread.Start (); - thread.Join (); - - if (!res) - return 12; - - Console.WriteLine ("done"); - - return 0; - } -} diff --git a/mono/tests/appdomain-unload-callback.cs b/mono/tests/appdomain-unload-callback.cs deleted file mode 100644 index de44c923bf..0000000000 --- a/mono/tests/appdomain-unload-callback.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System; -using System.Threading; - -/* -This test checks if the AddDomain::DomainUnload event is processed with -a fully working domain. In special if the threadpool remains operational. -*/ -class Driver -{ - static void UnloadHook (object obj, EventArgs args) - { - ManualResetEvent evt = new ManualResetEvent (false); - Console.WriteLine ("On the UnloadHook"); - if (Environment.HasShutdownStarted) - throw new Exception ("Environment.HasShutdownStarted must not be true"); - Action f = (int x) => { - evt.WaitOne (1000); - evt.Set (); - }; - f.BeginInvoke (1, null, null); - evt.WaitOne (); - Console.WriteLine ("Hook done"); - } - - static void OtherDomain() - { - AppDomain app = AppDomain.CurrentDomain; - Console.WriteLine ("Now I'm on {0}", app); - app.DomainUnload += Driver.UnloadHook; - } - - static int Main () - { - AppDomain app = AppDomain.CreateDomain ("Foo"); - Console.WriteLine ("I'm on {0}", AppDomain.CurrentDomain); - app.DoCallBack (Driver.OtherDomain ); - - Thread.Sleep (1); - AppDomain.Unload (app); - Thread.Sleep (1); - return 0; - } -} - diff --git a/mono/tests/appdomain-unload-doesnot-raise-pending-events.cs b/mono/tests/appdomain-unload-doesnot-raise-pending-events.cs deleted file mode 100644 index 7884be7a6e..0000000000 --- a/mono/tests/appdomain-unload-doesnot-raise-pending-events.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using System.IO; -using System.Net; -using System.Net.Sockets; -using System.Threading; - - -class Driver { - static void AppDomainMethod () { - Console.WriteLine ("two"); - var socket = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); - IPEndPoint ep = new IPEndPoint(IPAddress.Any, 0); - socket.Bind (ep); - socket.Listen (10); - socket.BeginAccept ( delegate { - Console.WriteLine ("Delegate should not be called!"); - Environment.Exit (1); - }, socket); - } - - static int Main () { - var da = AppDomain.CreateDomain ("le domain"); - da.DoCallBack (delegate { AppDomainMethod ();}); - Console.WriteLine ("unloading"); - AppDomain.Unload (da); - Console.WriteLine ("done"); - return 0; - } -} diff --git a/mono/tests/appdomain-unload.cs b/mono/tests/appdomain-unload.cs deleted file mode 100644 index d4673c7958..0000000000 --- a/mono/tests/appdomain-unload.cs +++ /dev/null @@ -1,293 +0,0 @@ -using System; -using System.Threading; -using System.Reflection; -using System.Runtime.Remoting; - -[Serializable] -public class Foo { - - ~Foo () { - Console.WriteLine ("FINALIZING IN DOMAIN " + AppDomain.CurrentDomain.FriendlyName + ": " + AppDomain.CurrentDomain.IsFinalizingForUnload ()); - } -} - -public class Bar : MarshalByRefObject { - public int test (int x) { - Console.WriteLine ("in " + Thread.GetDomain ().FriendlyName); - return x + 1; - } -} - -[Serializable] -public class SlowFinalize { - - ~SlowFinalize () { - Console.WriteLine ("FINALIZE1."); - try { - Thread.Sleep (500); - } - catch (Exception ex) { - Console.WriteLine ("A: " + ex); - } - Console.WriteLine ("FINALIZE2."); - } -} - -[Serializable] -public class AThread { - - public AThread () { - new Thread (new ThreadStart (Run)).Start (); - } - - public void Run () { - try { - while (true) - Thread.Sleep (100); - } - catch (ThreadAbortException ex) { - Console.WriteLine ("Thread aborted correctly."); - } - } -} - -// A Thread which refuses to die -public class BThread : MarshalByRefObject { - - bool stop; - - public BThread () { - new Thread (new ThreadStart (Run)).Start (); - } - - public void Stop () { - stop = true; - } - - public void Run () { - try { - while (true) - Thread.Sleep (100); - } - catch (ThreadAbortException ex) { - while (!stop) - Thread.Sleep (100); - } - } -} - -public class UnloadThread { - - AppDomain domain; - - public UnloadThread (AppDomain domain) { - this.domain = domain; - } - - public void Run () { - Console.WriteLine ("UNLOAD1"); - AppDomain.Unload (domain); - Console.WriteLine ("UNLOAD2"); - } -} - -class CrossDomainTester : MarshalByRefObject -{ -} - -public class Tests -{ - public static int Main(string[] args) { - if (args.Length == 0) - return TestDriver.RunTests (typeof (Tests), new String[] { "-v" }); - else - return TestDriver.RunTests (typeof (Tests), args); - } - - public static int test_0_unload () { - for (int i = 0; i < 10; ++i) { - AppDomain appDomain = AppDomain.CreateDomain("Test-unload" + i); - - appDomain.CreateInstanceAndUnwrap ( - typeof (CrossDomainTester).Assembly.FullName, "CrossDomainTester"); - - AppDomain.Unload(appDomain); - } - - return 0; - } - - public static int test_0_unload_default () { - try { - AppDomain.Unload (Thread.GetDomain ()); - } - catch (CannotUnloadAppDomainException) { - return 0; - } - return 1; - } - - public static int test_0_unload_after_unload () { - AppDomain domain = AppDomain.CreateDomain ("Test2"); - AppDomain.Unload (domain); - - try { - AppDomain.Unload (domain); - } - catch (Exception) { - return 0; - } - - return 1; - } - - public static int test_0_is_finalizing () { - AppDomain domain = AppDomain.CreateDomain ("Test-is-finalizing"); - object o = domain.CreateInstanceFromAndUnwrap (typeof (Tests).Assembly.Location, "Foo"); - - if (domain.IsFinalizingForUnload ()) - return 1; - - AppDomain.Unload (domain); - - return 0; - } - - public static int test_0_unload_with_active_threads () { - AppDomain domain = AppDomain.CreateDomain ("Test3"); - object o = domain.CreateInstanceFromAndUnwrap (typeof (Tests).Assembly.Location, "AThread"); - Thread.Sleep (100); - - AppDomain.Unload (domain); - - return 0; - } - - /* In recent mono versions, there is no unload timeout */ - /* - public static int test_0_unload_with_active_threads_timeout () { - AppDomain domain = AppDomain.CreateDomain ("Test4"); - BThread o = (BThread)domain.CreateInstanceFromAndUnwrap (typeof (Tests).Assembly.Location, "BThread"); - Thread.Sleep (100); - - try { - AppDomain.Unload (domain); - } - catch (Exception) { - // Try again - o.Stop (); - AppDomain.Unload (domain); - return 0; - } - - return 1; - } - */ - - static void Worker (object x) { - Thread.Sleep (100000); - } - - public static void invoke_workers () { - for (int i = 0; i < 1; i ++) - ThreadPool.QueueUserWorkItem (Worker); - } - - public static int test_0_unload_with_threadpool () { - AppDomain domain = AppDomain.CreateDomain ("test_0_unload_with_threadpool"); - - domain.DoCallBack (new CrossAppDomainDelegate (invoke_workers)); - AppDomain.Unload (domain); - - return 0; - } - - /* - * This test is not very deterministic since the thread which enqueues - * the work item might or might not be inside the domain when the unload - * happens. So disable this for now. - */ - /* - public static void DoUnload (object state) { - AppDomain.Unload (AppDomain.CurrentDomain); - } - - public static void Callback () { - Console.WriteLine (AppDomain.CurrentDomain); - WaitCallback unloadDomainCallback = new WaitCallback (DoUnload); - ThreadPool.QueueUserWorkItem (unloadDomainCallback); - } - - public static int test_0_unload_inside_appdomain_async () { - AppDomain domain = AppDomain.CreateDomain ("Test3"); - - domain.DoCallBack (new CrossAppDomainDelegate (Callback)); - - return 0; - } - */ - - public static void SyncCallback () { - AppDomain.Unload (AppDomain.CurrentDomain); - } - - public static int test_0_unload_inside_appdomain_sync () { - AppDomain domain = AppDomain.CreateDomain ("Test3"); - - try { - domain.DoCallBack (new CrossAppDomainDelegate (SyncCallback)); - } - catch (Exception ex) { - /* Should throw a ThreadAbortException */ - Thread.ResetAbort (); - } - - return 0; - } - - public static int test_0_invoke_after_unload () { - AppDomain domain = AppDomain.CreateDomain ("DeadInvokeTest"); - Bar bar = (Bar)domain.CreateInstanceAndUnwrap (typeof (Tests).Assembly.FullName, "Bar"); - int x; - - if (!RemotingServices.IsTransparentProxy(bar)) - return 3; - - AppDomain.Unload (domain); - - try { - x = bar.test (123); - if (x == 124) - return 1; - return 2; - } catch (Exception e) { - return 0; - } - } - - // FIXME: This does not work yet, because the thread is finalized too - // early - /* - public static int test_0_unload_during_unload () { - AppDomain domain = AppDomain.CreateDomain ("Test3"); - object o = domain.CreateInstanceFromAndUnwrap (typeof (Tests).Assembly.Location, "SlowFinalize"); - - UnloadThread t = new UnloadThread (domain); - - // Start unloading in a separate thread - new Thread (new ThreadStart (t.Run)).Start (); - - Thread.Sleep (100); - - try { - AppDomain.Unload (domain); - } - catch (Exception) { - Console.WriteLine ("OK"); - } - - return 0; - } -*/ -} - diff --git a/mono/tests/appdomain.cs b/mono/tests/appdomain.cs deleted file mode 100644 index 577ab6e856..0000000000 --- a/mono/tests/appdomain.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; -using System.Security.Policy; -using System.Threading; - -class Container { - - [LoaderOptimization (LoaderOptimization.SingleDomain)] - static int arg_sum (string[] args) { - int res = 0; - foreach (string s in args) { - res += Convert.ToInt32 (s); - } - return res; - } - - static int Main () - { - int res; - - AppDomainSetup setup = new AppDomainSetup (); - setup.ApplicationBase = "."; - - Console.WriteLine (AppDomain.CurrentDomain.FriendlyName); - - AppDomain newDomain = AppDomain.CreateDomain ("NewDomain", null, setup); - - string[] args = { "1", "2", "3"}; - res = newDomain.ExecuteAssembly ("appdomain-client.exe", null, args); - if (res != arg_sum (args)) - return 1; - - Console.WriteLine ("test-ok"); - - return 0; - } -} diff --git a/mono/tests/appdomain1.cs b/mono/tests/appdomain1.cs deleted file mode 100644 index 23361c90e9..0000000000 --- a/mono/tests/appdomain1.cs +++ /dev/null @@ -1,99 +0,0 @@ -using System; -using System.Security.Policy; -using System.Runtime.Remoting; -using System.Threading; - -class Container { - - class MBRTest : MarshalByRefObject - { - public int Int { - get { - return (int) AppDomain.CurrentDomain.GetData("test_integer"); - } - } - - public string Str { - get { - return (string) AppDomain.CurrentDomain.GetData("test_string"); - } - } - - public bool Bool { - get { - return (bool) AppDomain.CurrentDomain.GetData("test_bool"); - } - } - - public int [] Arr { - get { - return (int []) AppDomain.CurrentDomain.GetData("test_array"); - } - } - } - - static int Main () - { - Console.WriteLine ("Friendly name: " + AppDomain.CurrentDomain.FriendlyName); - - AppDomain newDomain = AppDomain.CreateDomain ("NewDomain"); - - if (!RemotingServices.IsTransparentProxy(newDomain)) - return 1; - - // First test that this domain get's the right data from the other domain - newDomain.SetData ("test_string", "a"); - - object t = newDomain.GetData("test_string"); - if (t.GetType() != typeof(string)) - return 2; - - if ((string) newDomain.GetData ("test_string") != "a") - return 3; - - newDomain.SetData ("test_integer", 1); - if ((int) newDomain.GetData ("test_integer") != 1) - return 4; - - newDomain.SetData ("test_bool", true); - if ((bool)newDomain.GetData ("test_bool") != true) - return 5; - - newDomain.SetData ("test_bool", false); - if ((bool)newDomain.GetData ("test_bool") != false) - return 6; - - int [] ta = { 1, 2, 3 }; - newDomain.SetData ("test_array", ta); - - int [] ca = (int [])newDomain.GetData ("test_array"); - - if (ca [0] != 1 || ca [1] != 2 || ca [2] != 3) - return 7; - - // Creata a MBR object to test that the other domain has the correct info - MBRTest test = (MBRTest) newDomain.CreateInstanceAndUnwrap (typeof(MBRTest).Assembly.FullName, typeof(MBRTest).FullName); - - if (!RemotingServices.IsTransparentProxy(test)) - return 8; - - // Time to test that the newDomain also have the same info - if (test.Int != 1) - return 9; - - if (test.Str != "a") - return 10; - - if (test.Bool != false) - return 11; - - ca = test.Arr; - - if (ca [0] != 1 || ca [1] != 2 || ca [2] != 3) - return 12; - - Console.WriteLine("test-ok"); - - return 0; - } -} diff --git a/mono/tests/appdomain2.cs b/mono/tests/appdomain2.cs deleted file mode 100644 index e970a5364e..0000000000 --- a/mono/tests/appdomain2.cs +++ /dev/null @@ -1,73 +0,0 @@ -using System; -using System.IO; -using System.Security.Policy; -using System.Threading; -using System.Runtime.Serialization; - -class Container { - - [Serializable] - public struct c2 : ISerializable { - public int a; - public string s1; - - private c2 (SerializationInfo info, StreamingContext context) { - a = info.GetInt32("a"); - s1 = info.GetString("s1"); - } - - public void GetObjectData (SerializationInfo info, StreamingContext context) { - info.AddValue ("a", a); - if (s1 != null) - info.AddValue ("s1", s1); - else - info.AddValue ("s1", "(null)"); - } - } - - [Serializable] - public class c1 { - public int a = 1; - public int b = 2; - public string s1 = "TEST1"; - [NonSerialized] public string s2 = "TEST2"; - public c2 e1; - } - - static int Main () - { - Console.WriteLine ("Friendly name: " + AppDomain.CurrentDomain.FriendlyName); - - AppDomainSetup setup = new AppDomainSetup (); - setup.ApplicationBase = Directory.GetCurrentDirectory (); - - AppDomain newDomain = AppDomain.CreateDomain ("NewDomain", null, setup); - - c1 a1 = new c1 (); - a1.e1.a = 3; - a1.e1.s1 = "SS"; - - newDomain.SetData ("TEST", a1); - - c1 r1 = (c1)newDomain.GetData ("TEST"); - - if (r1.a != 1 || r1.b !=2) - return 1; - - if (r1.s1 != "TEST1") - return 2; - - if (r1.s2 != null) - return 3; - - if (r1.e1.a != 3) - return 4; - - if (r1.e1.s1 != "SS") - return 5; - - Console.WriteLine("test-ok"); - - return 0; - } -} diff --git a/mono/tests/assembly_append_ordering.cs b/mono/tests/assembly_append_ordering.cs deleted file mode 100644 index 6f0b471ed8..0000000000 --- a/mono/tests/assembly_append_ordering.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System; -using System.Linq; -using System.Reflection; -using System.Reflection.Emit; - -class Driver { - static int Main () { - var dyn = DefineDynamicAssembly (AppDomain.CurrentDomain); - var core = TriggerLoadingSystemCore (); - var asm = AppDomain.CurrentDomain.GetAssemblies (); - - if (asm [0] != typeof (object).Assembly) { - Console.WriteLine ("first assembly must be mscorlib, but it was {0}", asm [0]); - return 1; - } - - if (asm [1] != typeof (Driver).Assembly) { - Console.WriteLine ("second assembly must be test assembly, but it was {0}", asm [1]); - return 2; - } - - if (asm [2] != dyn) { - Console.WriteLine ("third assembly must be SRE, but it was {0}", asm [2]); - return 3; - } - - if (asm [3] != core) { - Console.WriteLine ("last assembly must be System.Core, but it was {0}", asm [3]); - return 4; - } - - return 0; - } - - static Assembly TriggerLoadingSystemCore () - { - int[] x = new int[] { 1,2,3}; - x.Where (v => v > 1); - return typeof (Enumerable).Assembly; - } - - - static Assembly DefineDynamicAssembly (AppDomain domain) - { - AssemblyName assemblyName = new AssemblyName (); - assemblyName.Name = "MyDynamicAssembly"; - - AssemblyBuilder assemblyBuilder = domain.DefineDynamicAssembly (assemblyName, AssemblyBuilderAccess.Run); - ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule ("MyDynamicModule"); - TypeBuilder typeBuilder = moduleBuilder.DefineType ("MyDynamicType", TypeAttributes.Public); - ConstructorBuilder constructorBuilder = typeBuilder.DefineConstructor (MethodAttributes.Public, CallingConventions.Standard, null); - ILGenerator ilGenerator = constructorBuilder.GetILGenerator (); - ilGenerator.EmitWriteLine ("MyDynamicType instantiated!"); - ilGenerator.Emit (OpCodes.Ret); - typeBuilder.CreateType (); - return assemblyBuilder; - } - -} \ No newline at end of file diff --git a/mono/tests/assemblyresolve/Makefile.am b/mono/tests/assemblyresolve/Makefile.am index dac89cabea..b198b75375 100644 --- a/mono/tests/assemblyresolve/Makefile.am +++ b/mono/tests/assemblyresolve/Makefile.am @@ -2,10 +2,14 @@ CLASS=$(mcs_topdir)/class/lib/$(DEFAULT_PROFILE) with_mono_path = MONO_PATH=$(CLASS) -RUNTIME = $(with_mono_path) $(top_builddir)/runtime/mono-wrapper --debug -MCS = $(RUNTIME) $(mcs_topdir)/class/lib/build/mcs.exe -debug:full -target:library +RUNTIME = $(top_builddir)/runtime/mono-wrapper --debug +MCS = $(with_mono_path) $(RUNTIME) $(mcs_topdir)/class/lib/build/mcs.exe -debug:full -target:library +if INSTALL_MOBILE_STATIC +prereq: aot +else prereq: test/asm.dll +endif test/.dirstamp deps/.dirstamp: -mkdir $(@D) @@ -27,3 +31,10 @@ EXTRA_DIST = asm.cs Test.cs TestBase.cs clean: rm -f deps/*.dll test/*.dll + +.PHONY: aot +aot: test/asm.dll + MONO_PATH="deps:$(CLASS)" $(RUNTIME) $(AOT_BUILD_FLAGS) deps/test.dll + MONO_PATH="deps:$(CLASS)" $(RUNTIME) $(AOT_BUILD_FLAGS) deps/TestBase.dll + MONO_PATH="deps:$(CLASS)" $(RUNTIME) $(AOT_BUILD_FLAGS) test/asm.dll + diff --git a/mono/tests/assemblyresolve/Makefile.in b/mono/tests/assemblyresolve/Makefile.in index babc0d80ab..0ffb82e2af 100644 --- a/mono/tests/assemblyresolve/Makefile.in +++ b/mono/tests/assemblyresolve/Makefile.in @@ -120,6 +120,8 @@ DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AOT_BUILD_FLAGS = @AOT_BUILD_FLAGS@ +AOT_RUN_FLAGS = @AOT_RUN_FLAGS@ API_VER = @API_VER@ AR = @AR@ AS = @AS@ @@ -128,6 +130,11 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOEHM_DEFINES = @BOEHM_DEFINES@ +BTLS_ARCH = @BTLS_ARCH@ +BTLS_CFLAGS = @BTLS_CFLAGS@ +BTLS_CMAKE_ARGS = @BTLS_CMAKE_ARGS@ +BTLS_PLATFORM = @BTLS_PLATFORM@ +BTLS_ROOT = @BTLS_ROOT@ BUILD_EXEEXT = @BUILD_EXEEXT@ CC = @CC@ CCAS = @CCAS@ @@ -137,6 +144,7 @@ CCDEPMODE = @CCDEPMODE@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMAKE = @CMAKE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ @@ -157,7 +165,6 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_PERF_EVENTS = @ENABLE_PERF_EVENTS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDKX11 = @GDKX11@ @@ -172,10 +179,12 @@ HAVE_MSGFMT = @HAVE_MSGFMT@ HOST_CC = @HOST_CC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MOBILE_STATIC = @INSTALL_MOBILE_STATIC@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTL = @INTL@ +INVARIANT_AOT_OPTIONS = @INVARIANT_AOT_OPTIONS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBC = @LIBC@ @@ -222,6 +231,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ +PLATFORM_AOT_SUFFIX = @PLATFORM_AOT_SUFFIX@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -231,6 +241,7 @@ SHELL = @SHELL@ SQLITE = @SQLITE@ SQLITE3 = @SQLITE3@ STRIP = @STRIP@ +TEST_PROFILE = @TEST_PROFILE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VTUNE_CFLAGS = @VTUNE_CFLAGS@ @@ -321,8 +332,8 @@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ CLASS = $(mcs_topdir)/class/lib/$(DEFAULT_PROFILE) with_mono_path = MONO_PATH=$(CLASS) -RUNTIME = $(with_mono_path) $(top_builddir)/runtime/mono-wrapper --debug -MCS = $(RUNTIME) $(mcs_topdir)/class/lib/build/mcs.exe -debug:full -target:library +RUNTIME = $(top_builddir)/runtime/mono-wrapper --debug +MCS = $(with_mono_path) $(RUNTIME) $(mcs_topdir)/class/lib/build/mcs.exe -debug:full -target:library EXTRA_DIST = asm.cs Test.cs TestBase.cs all: all-am @@ -513,7 +524,8 @@ uninstall-am: tags-am uninstall uninstall-am -prereq: test/asm.dll +@INSTALL_MOBILE_STATIC_TRUE@prereq: aot +@INSTALL_MOBILE_STATIC_FALSE@prereq: test/asm.dll test/.dirstamp deps/.dirstamp: -mkdir $(@D) @@ -534,6 +546,12 @@ deps/TestBase.dll: TestBase.cs clean: rm -f deps/*.dll test/*.dll +.PHONY: aot +aot: test/asm.dll + MONO_PATH="deps:$(CLASS)" $(RUNTIME) $(AOT_BUILD_FLAGS) deps/test.dll + MONO_PATH="deps:$(CLASS)" $(RUNTIME) $(AOT_BUILD_FLAGS) deps/TestBase.dll + MONO_PATH="deps:$(CLASS)" $(RUNTIME) $(AOT_BUILD_FLAGS) test/asm.dll + # 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/mono/tests/assemblyresolve_event2.2.cs b/mono/tests/assemblyresolve_event2.2.cs deleted file mode 100644 index 7f84525a48..0000000000 --- a/mono/tests/assemblyresolve_event2.2.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System; -using System.Reflection; - -public class App -{ - static bool[] expected_results = {false, false}; - static bool handler_fired; - - public static int Main () - { - AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += new ResolveEventHandler(MyReflectionResolveEventHandler); - - int i = 0; - handler_fired = false; - - try { - Assembly.ReflectionOnlyLoad ("SomeAssembly"); - } catch (Exception) { - } - if (expected_results [i] != handler_fired) - return 1; - - i++; - handler_fired = false; - try { - Assembly.ReflectionOnlyLoadFrom ("SomeAssembly"); - } catch (Exception) { - } - if (expected_results [i] != handler_fired) - return 2; - - return 0; - } - - static Assembly MyReflectionResolveEventHandler(object sender, ResolveEventArgs args) { - handler_fired = true; - return null; - } -} diff --git a/mono/tests/async-exc-compilation.cs b/mono/tests/async-exc-compilation.cs index d8cd583af0..dafb731f31 100644 --- a/mono/tests/async-exc-compilation.cs +++ b/mono/tests/async-exc-compilation.cs @@ -27,6 +27,7 @@ class MainClass Thread.Sleep (10000); } catch (ThreadAbortException) { + Thread.ResetAbort (); Console.WriteLine ("OK"); } } diff --git a/mono/tests/bug-30085.cs b/mono/tests/bug-30085.cs index 80c985b0a1..9fc03ba6ff 100644 --- a/mono/tests/bug-30085.cs +++ b/mono/tests/bug-30085.cs @@ -18,7 +18,7 @@ class Program static void ProbeCorlib () { Type good = System.Type.GetType("System.Nullable`1[[System.Int32, mscorlib]]"); - Type bad = System.Type.GetType("System.Nullable`1[[System.IO.Pipes.PipeOptions, System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]"); + Type bad = System.Type.GetType("System.Nullable`1[[System.IO.MemoryMappedFiles.MemoryMappedFile, System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]"); if (good.Assembly.FullName.Split (',') [0] != "mscorlib") throw new Exception ("Wrong assembly name"); diff --git a/mono/tests/bug-322722_dyn_method_throw.2.cs b/mono/tests/bug-322722_dyn_method_throw.2.cs deleted file mode 100644 index c9e0cf3c52..0000000000 --- a/mono/tests/bug-322722_dyn_method_throw.2.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using System.Reflection; -using System.Reflection.Emit; - -public class MyException : Exception { - -} - -class Driver { - public static int Main() - { - DynamicMethod method_builder = new DynamicMethod ("ThrowException" , typeof (void), new Type[0], typeof (Driver)); - ILGenerator ilg = method_builder.GetILGenerator (); - - - ilg.Emit (OpCodes.Newobj, typeof (MyException).GetConstructor (new Type[0])); - ilg.Emit (OpCodes.Throw); - - try { - method_builder.Invoke (null, null); - return 2; - } catch (TargetInvocationException tie) { - if(! (tie.InnerException is MyException)) - return 3; - } - - return 0; - } -} diff --git a/mono/tests/bug-322722_patch_bx.2.cs b/mono/tests/bug-322722_patch_bx.2.cs deleted file mode 100644 index 510affa064..0000000000 --- a/mono/tests/bug-322722_patch_bx.2.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using System.Reflection; -using System.Reflection.Emit; - - -class Driver { - public void AvoidInlining() - { - } - - public int Foo() - { - AvoidInlining(); - return -99; - } - - public static int Main() - { - - DynamicMethod method_builder = new DynamicMethod ("WriteHello" , typeof (int), new Type[] {typeof (Driver)}, typeof (Driver)); - ILGenerator ilg = method_builder.GetILGenerator (); - - ilg.Emit (OpCodes.Ldarg_0); - ilg.Emit (OpCodes.Call, typeof (Driver).GetMethod ("Foo")); - ilg.Emit (OpCodes.Ret); - - int res = (int) method_builder.Invoke (null, new object[] {new Driver()}); - return res == -99 ? 0 : 1; - } -} diff --git a/mono/tests/bug-333798-tb.2.cs b/mono/tests/bug-333798-tb.2.cs deleted file mode 100644 index 669163656f..0000000000 --- a/mono/tests/bug-333798-tb.2.cs +++ /dev/null @@ -1,64 +0,0 @@ -using System; -using System.Threading; -using System.Reflection; -using System.Reflection.Emit; -using System.IO; -using System.Security; -using System.Security.Permissions; -using System.Runtime.InteropServices; -using System.Collections.Generic; - -public class Gen { - public static Gen[] newSelfArr () { - return null; - } -} - -public class Driver { - public static void Test () { - Gen.newSelfArr (); - } -} - -public class GenericsTests -{ - static AssemblyBuilder assembly; - static ModuleBuilder module; - - static void SetUp () - { - AssemblyName assemblyName = new AssemblyName (); - assemblyName.Name = "TestAssembly"; - assembly = - Thread.GetDomain ().DefineDynamicAssembly ( - assemblyName, AssemblyBuilderAccess.RunAndSave, "."); - module = assembly.DefineDynamicModule ("module1", "TestModuleSS.dll"); - } - - public static int Main () { - SetUp (); - TypeBuilder tb = module.DefineType ("Gen", TypeAttributes.Public); - Type[] args = tb.DefineGenericParameters ("T"); - Type oi = tb.MakeGenericType (args); - - MethodBuilder mb = tb.DefineMethod ("Test", MethodAttributes.Public | MethodAttributes.Static, oi.MakeArrayType (), new Type [0]); - - ILGenerator il = mb.GetILGenerator(); - il.Emit (OpCodes.Ldnull); - il.Emit (OpCodes.Ret); - tb.CreateType (); - - TypeBuilder main = module.DefineType ("Driver", TypeAttributes.Public); - MethodBuilder mb2 = main.DefineMethod ("Test", MethodAttributes.Public | MethodAttributes.Static); - - il = mb2.GetILGenerator(); - il.Emit (OpCodes.Call, TypeBuilder.GetMethod (tb.MakeGenericType (typeof (int)), mb)); - il.Emit (OpCodes.Pop); - il.Emit (OpCodes.Ret); - Type tt = main.CreateType (); - - tt.GetMethod ("Test").Invoke (null, null); - //typeof (Driver).GetMethod ("Test").Invoke (null, null); - return 0; - } -} diff --git a/mono/tests/bug-335131.2.cs b/mono/tests/bug-335131.2.cs deleted file mode 100644 index 2452f96357..0000000000 --- a/mono/tests/bug-335131.2.cs +++ /dev/null @@ -1,79 +0,0 @@ -using System; -using System.Reflection; -using System.Reflection.Emit; - - -class Bla { - public T t; -} -public class Entry -{ - public static int Main() - { - Bla d = new Bla(); - d.t = 99; - Instance(); - - AppDomain domain = AppDomain.CreateDomain ("test"); - try { - domain.ExecuteAssembly ("Instance.exe"); - } catch (Exception e) { - Console.WriteLine ("assembly has thrown "+e); - return 1; - } - return 0; - } - - public static void Instance() - { - AssemblyName name = new AssemblyName("Instance"); - AssemblyBuilder asmbuild = System.Threading.Thread.GetDomain().DefineDynamicAssembly(name, AssemblyBuilderAccess.RunAndSave); - ModuleBuilder mod = asmbuild.DefineDynamicModule("Instance.exe"); - - TypeBuilder G = mod.DefineType("G", TypeAttributes.Public); - Type T = G.DefineGenericParameters("T")[0]; - Type GObj = G.MakeGenericType(new Type[] { typeof(object) }); - - ConstructorBuilder Ctor = G.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, null); - { - ILGenerator il = Ctor.GetILGenerator(); - il.Emit(OpCodes.Ldarg_0); - il.Emit(OpCodes.Call, typeof(object).GetConstructor(new Type[0])); - il.Emit(OpCodes.Ret); - } - - MethodBuilder Bar = G.DefineMethod("Bar", MethodAttributes.Public); - { - ILGenerator il = Bar.GetILGenerator(); - il.Emit(OpCodes.Ret); - } - - MethodBuilder Foo = G.DefineMethod("Foo", MethodAttributes.Public | MethodAttributes.Static ); - { - ILGenerator il = Foo.GetILGenerator(); - il.Emit(OpCodes.Newobj, Ctor); - il.Emit(OpCodes.Call, Bar); - il.Emit(OpCodes.Ret); - } - - TypeBuilder M = mod.DefineType("M", TypeAttributes.Public); - - - MethodBuilder main = M.DefineMethod("Main", MethodAttributes.Public | MethodAttributes.Static ); - { - ILGenerator il = main.GetILGenerator(); - il.Emit(OpCodes.Call, TypeBuilder.GetMethod (GObj, Foo)); - il.Emit(OpCodes.Ret); - } - - asmbuild.SetEntryPoint (main); - G.CreateType(); - M.CreateType(); - - asmbuild.Save("Instance.exe"); - - - Console.WriteLine("ok"); - } - -} diff --git a/mono/tests/bug-349190.2.cs b/mono/tests/bug-349190.2.cs deleted file mode 100644 index fb1ecef108..0000000000 --- a/mono/tests/bug-349190.2.cs +++ /dev/null @@ -1,130 +0,0 @@ -using System; -using System.Reflection; -using System.Reflection.Emit; -using System.Threading; -using System.IO; -using System.Collections.Generic; - - -public class Driver -{ - public static int Main () { - if (!TestOneAssembly ()) - return 1; - if (!TestTwoAssemblies ()) - return 2; - return 0; - } - - public static bool TestTwoAssemblies () - { - AssemblyBuilder assembly2 = Thread.GetDomain ().DefineDynamicAssembly (new AssemblyName ("res2"), AssemblyBuilderAccess.RunAndSave, Path.GetTempPath ()); - ModuleBuilder module2 = assembly2.DefineDynamicModule ("res2.dll"); - - TypeBuilder tb2 = module2.DefineType ("ExternalType", TypeAttributes.Public | TypeAttributes.Abstract); - - MethodBuilder m_2 = tb2.DefineMethod ("m_2", MethodAttributes.Public | MethodAttributes.Static); - Type[] gparams_m_2 = m_2.DefineGenericParameters ("T"); - m_2.SetReturnType (gparams_m_2[0]); - m_2.SetParameters (gparams_m_2[0]); - ILGenerator il = m_2.GetILGenerator (); - il.Emit (OpCodes.Ldarg_0); - il.Emit (OpCodes.Ret); - - - AssemblyBuilder assembly = Thread.GetDomain ().DefineDynamicAssembly (new AssemblyName ("res"), AssemblyBuilderAccess.RunAndSave, Path.GetTempPath ()); - ModuleBuilder module = assembly.DefineDynamicModule ("res.exe"); - - TypeBuilder tb = module.DefineType ("Mono.Rocks.IEnumerable", TypeAttributes.Public | TypeAttributes.Abstract); - - MethodBuilder mb = tb.DefineMethod ("NaturalSort", MethodAttributes.Public | MethodAttributes.Static); - Type[] gparams = mb.DefineGenericParameters ("T"); - mb.SetReturnType (typeof (IEnumerable<>).MakeGenericType (gparams)); - mb.SetParameters (typeof (IEnumerable<>).MakeGenericType (gparams)); - - il = mb.GetILGenerator (); - il.Emit (OpCodes.Ldftn, m_2); - il.Emit (OpCodes.Pop); - - il.Emit (OpCodes.Ldarg_0); - il.Emit (OpCodes.Ret); - - TypeBuilder driver = module.DefineType ("Driver", TypeAttributes.Public); - MethodBuilder main = tb.DefineMethod ("Main", MethodAttributes.Public | MethodAttributes.Static); - il = main.GetILGenerator (); - il.Emit (OpCodes.Ldnull); - il.Emit (OpCodes.Call, mb.MakeGenericMethod (typeof(int))); - il.Emit (OpCodes.Pop); - il.Emit (OpCodes.Ret); - - assembly.SetEntryPoint (main); - - Type t = tb.CreateType (); - tb2.CreateType (); - driver.CreateType (); - - - assembly2.Save ("res2.dll"); - assembly.Save ("res.exe"); - - IEnumerable en = new int[] { 1,2,3 }; - bool res = en == t.GetMethod ("NaturalSort").MakeGenericMethod (typeof (int)).Invoke (null, new object[] { en }); - - Thread.GetDomain ().ExecuteAssembly(Path.GetTempPath () + Path.DirectorySeparatorChar +"res.exe"); - return res; - } - - - - public static bool TestOneAssembly() - { - AssemblyBuilder assembly = Thread.GetDomain ().DefineDynamicAssembly (new AssemblyName ("ALAL"), AssemblyBuilderAccess.RunAndSave, Path.GetTempPath ()); - ModuleBuilder module = assembly.DefineDynamicModule ("res1.exe"); - - TypeBuilder tb = module.DefineType ("Mono.Rocks.IEnumerable", TypeAttributes.Public | TypeAttributes.Abstract); - - MethodBuilder m_2 = tb.DefineMethod ("m_2", MethodAttributes.Private | MethodAttributes.Static); - Type[] gparams_m_2 = m_2.DefineGenericParameters ("T"); - m_2.SetReturnType (gparams_m_2[0]); - m_2.SetParameters (gparams_m_2[0]); - - MethodBuilder mb = tb.DefineMethod ("NaturalSort", MethodAttributes.Public | MethodAttributes.Static); - Type[] gparams = mb.DefineGenericParameters ("T"); - mb.SetReturnType (typeof (IEnumerable<>).MakeGenericType (gparams)); - mb.SetParameters (typeof (IEnumerable<>).MakeGenericType (gparams)); - - ILGenerator il = mb.GetILGenerator (); - - il.Emit (OpCodes.Ldftn, m_2); - il.Emit (OpCodes.Pop); - - il.Emit (OpCodes.Ldarg_0); - il.Emit (OpCodes.Ret); - - il = m_2.GetILGenerator (); - il.Emit (OpCodes.Ldarg_0); - il.Emit (OpCodes.Ret); - - TypeBuilder driver = module.DefineType ("Driver", TypeAttributes.Public); - MethodBuilder main = tb.DefineMethod ("Main", MethodAttributes.Public | MethodAttributes.Static); - il = main.GetILGenerator (); - il.Emit (OpCodes.Ldnull); - il.Emit (OpCodes.Call, mb.MakeGenericMethod (typeof(int))); - il.Emit (OpCodes.Pop); - il.Emit (OpCodes.Ret); - - assembly.SetEntryPoint (main); - - - Type t = tb.CreateType (); - driver.CreateType (); - - IEnumerable en = new int[] { 1,2,3 }; - bool res = en == t.GetMethod ("NaturalSort").MakeGenericMethod (typeof (int)).Invoke (null, new object[] {en }); - assembly.Save ("res1.exe"); - res &= en == t.GetMethod ("NaturalSort").MakeGenericMethod (typeof (int)).Invoke (null, new object[] {en }); - - Thread.GetDomain ().ExecuteAssembly(Path.GetTempPath () + Path.DirectorySeparatorChar +"res1.exe"); - return res; - } -} diff --git a/mono/tests/bug-36848.cs b/mono/tests/bug-36848.cs deleted file mode 100644 index f91447a553..0000000000 --- a/mono/tests/bug-36848.cs +++ /dev/null @@ -1,52 +0,0 @@ -// Load an interface from an invalid DLL and ensure the failure is clean. -// Notice this is very similar to bug-81673, except the interface is loaded -// through a transparent proxy instead of directly. - -using System; -using System.Runtime.Remoting; -using System.Runtime.Remoting.Proxies; -using System.Runtime.Remoting.Messaging; - -namespace Application -{ - public class App - { - public static void Test () - { - RemoteProxy remote2 = new RemoteProxy (typeof(App).Assembly.GetType("Application.Remote")); - remote2.GetTransparentProxy (); - } - - public static int Main () - { - int numCaught = 0; - - for (int i = 0; i < 10; ++i) { - try { - Test (); - } catch (Exception) { - ++numCaught; - } - } - if (numCaught == 10) - return 0; - return 1; - } - } - - class Remote : MarshalByRefObject, IMyInterface { - public void Run () - { - } - } - - class RemoteProxy : RealProxy { - public RemoteProxy (Type t) : base (t) { - - } - - public override IMessage Invoke (IMessage request) { - return null; - } - } -} diff --git a/mono/tests/bug-389886-2.cs b/mono/tests/bug-389886-2.cs deleted file mode 100644 index f48c6e0145..0000000000 --- a/mono/tests/bug-389886-2.cs +++ /dev/null @@ -1,96 +0,0 @@ -using System; -using System.Threading; -using System.Reflection; -using System.Reflection.Emit; - -/*public delegate void FooDelegate ();*/ - -public class EmitTest -{ - static ConstructorBuilder ctor; - static MethodBuilder targetMethod; - static MethodBuilder testEvents; - static Type fooOpenInst; - static Type[] genericArgs; - - static void EmitCtor (TypeBuilder genericFoo) { - ConstructorBuilder mb = genericFoo.DefineConstructor (MethodAttributes.Public, CallingConventions.Standard, null); - ILGenerator il = mb.GetILGenerator (); - for (int i = 0; i < 20; ++i) - il.Emit (OpCodes.Nop); - - il.Emit (OpCodes.Ldarg_0); - il.Emit (OpCodes.Call, typeof (object).GetConstructors()[0]); - il.Emit (OpCodes.Ret); - - ctor = mb; - } - - static void EmitTestEvents (TypeBuilder genericFoo) { - MethodBuilder mb = genericFoo.DefineMethod ("TestEvents", MethodAttributes.Public, typeof (void), null); - ILGenerator il = mb.GetILGenerator (); - for (int i = 0; i < 20; ++i) - il.Emit (OpCodes.Nop); - - il.Emit (OpCodes.Ldarg_0); - il.Emit (OpCodes.Ldnull); - il.Emit (OpCodes.Callvirt, targetMethod); - - il.Emit (OpCodes.Ret); - - testEvents = mb; - } - - - static void EmitTargetMethod (TypeBuilder genericFoo) { - MethodBuilder mb = genericFoo.DefineMethod ("TargetMethod", MethodAttributes.Public, typeof (void), new Type[] {typeof (object) }); - ILGenerator il = mb.GetILGenerator (); - - for (int i = 0; i < 20; ++i) - il.Emit (OpCodes.Nop); - - il.Emit (OpCodes.Ldtoken, genericArgs [0]); - il.Emit (OpCodes.Call, typeof (Type).GetMethod ("GetTypeFromHandle")); - il.Emit (OpCodes.Call, typeof (Console).GetMethod ("WriteLine", new Type[] { typeof (object) })); - il.Emit (OpCodes.Ret); - - targetMethod = mb; - } - - public static int Main () { - AssemblyName assemblyName = new AssemblyName(); - assemblyName.Name = "customMod"; - assemblyName.Version = new Version (1, 2, 3, 4); - - AssemblyBuilder assembly - = Thread.GetDomain().DefineDynamicAssembly( - assemblyName, AssemblyBuilderAccess.RunAndSave); - - ModuleBuilder module = assembly.DefineDynamicModule("res.exe", "res.exe"); - - TypeBuilder genericFoo = module.DefineType ("GenericFoo", TypeAttributes.Public, typeof (object)); - genericArgs = genericFoo.DefineGenericParameters ("T"); - fooOpenInst = genericFoo.MakeGenericType (genericArgs); - - EmitCtor (genericFoo); - EmitTargetMethod (genericFoo); - EmitTestEvents (genericFoo); - - TypeBuilder moduletype = module.DefineType ("ModuleType", TypeAttributes.Public, typeof (object)); - MethodBuilder main = moduletype.DefineMethod ("Main", MethodAttributes.Public | MethodAttributes.Static, typeof (void), null); - ILGenerator il = main.GetILGenerator (); - - Type strInst = genericFoo.MakeGenericType (typeof (string)); - il.Emit (OpCodes.Newobj, TypeBuilder.GetConstructor (strInst, ctor)); - il.Emit (OpCodes.Callvirt, TypeBuilder.GetMethod (strInst, testEvents)); - il.Emit (OpCodes.Ret); - - genericFoo.CreateType (); - Type res = moduletype.CreateType (); - - res.GetMethod ("Main").Invoke (null, null); - return 0; - } - -} - diff --git a/mono/tests/bug-389886-3.cs b/mono/tests/bug-389886-3.cs deleted file mode 100644 index 33b401986b..0000000000 --- a/mono/tests/bug-389886-3.cs +++ /dev/null @@ -1,110 +0,0 @@ -using System; -using System.Threading; -using System.Reflection; -using System.Reflection.Emit; - -namespace TestApp -{ - class Program - { - static AssemblyBuilder assembly; - static ModuleBuilder module; - static Type[] args; - static ConstructorBuilder delegate_ctor; - static MethodBuilder invoke_mb; - static string ASSEMBLY_NAME = "MonoTests.System.Reflection.Emit.TypeBuilderTest"; - - static void SetUp () - { - AssemblyName assemblyName = new AssemblyName (); - assemblyName.Name = ASSEMBLY_NAME; - - assembly = - Thread.GetDomain ().DefineDynamicAssembly ( - assemblyName, AssemblyBuilderAccess.RunAndSave, "."); - - module = assembly.DefineDynamicModule ("module1", "bla.exe"); - } - - static TypeBuilder DefineDelegate () { - TypeBuilder typeBuilder = module.DefineType( "MyDelegate", - TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.Sealed, - typeof (object) ); - args = typeBuilder.DefineGenericParameters ("TIn", "TOut"); - - delegate_ctor = typeBuilder.DefineConstructor( - MethodAttributes.Public | MethodAttributes.HideBySig | - MethodAttributes.RTSpecialName | MethodAttributes.SpecialName, - CallingConventions.Standard, - new Type[] { typeof(Object), typeof (IntPtr) } ); - - delegate_ctor.SetImplementationFlags( MethodImplAttributes.Runtime | MethodImplAttributes.Managed ); - - invoke_mb = typeBuilder.DefineMethod( - "Invoke", - MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig, - args [1], - new Type[] { args [0] } ); - - invoke_mb.SetImplementationFlags( MethodImplAttributes.Runtime | MethodImplAttributes.Managed ); - - MethodBuilder mb = typeBuilder.DefineMethod( - "BeginInvoke", - MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig, - typeof (IAsyncResult), - new Type[] { args [0], typeof (AsyncCallback), typeof (object) } ); - - mb.SetImplementationFlags( MethodImplAttributes.Runtime | MethodImplAttributes.Managed ); - - mb = typeBuilder.DefineMethod( - "EndInvoke", - MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig, - args [1], - new Type[] { typeof (IAsyncResult) } ); - - mb.SetImplementationFlags( MethodImplAttributes.Runtime | MethodImplAttributes.Managed ); - - return typeBuilder; - } - - static int Main() - { - SetUp (); - - TypeBuilder tb = DefineDelegate (); - TypeBuilder main = module.DefineType ("Main", TypeAttributes.Public); - /* >>>move this to after the SetParent call and things will work<<< */ - Type inst = tb.MakeGenericType (new Type[] {typeof (double), typeof(int)}); - - tb.SetParent (typeof( System.MulticastDelegate)); - - ConstructorBuilder ctor = main.DefineDefaultConstructor (MethodAttributes.Public); - - MethodBuilder foo_mb = main.DefineMethod("Foo", MethodAttributes.Public, typeof (int), new Type[] { typeof (double) } ); - ILGenerator ig = foo_mb.GetILGenerator (); - ig.Emit (OpCodes.Ldc_I4_0); - ig.Emit (OpCodes.Ret); - - - MethodBuilder main_mb = main.DefineMethod ("Main", MethodAttributes.Public | MethodAttributes.Static, typeof (int), Type.EmptyTypes); - ig = main_mb.GetILGenerator (); - - ig.Emit (OpCodes.Newobj, ctor); - ig.Emit (OpCodes.Ldftn, foo_mb); - ig.Emit (OpCodes.Newobj, TypeBuilder.GetConstructor (inst, delegate_ctor)); - ig.Emit (OpCodes.Ldc_R8, 2.2); - ig.Emit (OpCodes.Callvirt, TypeBuilder.GetMethod (inst, invoke_mb)); - - ig.Emit (OpCodes.Ret); - - tb.CreateType (); - - Type t = main.CreateType (); - - MethodInfo method = t.GetMethod ("Main"); - method.Invoke (null, null); - - return 0; - } - } -} diff --git a/mono/tests/bug-389886-sre-generic-interface-instances.cs b/mono/tests/bug-389886-sre-generic-interface-instances.cs deleted file mode 100644 index cd9ca8c7ba..0000000000 --- a/mono/tests/bug-389886-sre-generic-interface-instances.cs +++ /dev/null @@ -1,116 +0,0 @@ -using System; -using System.Threading; -using System.Reflection; -using System.Reflection.Emit; - -namespace TestApp -{ - class Program - { - static AssemblyBuilder assembly; - static ModuleBuilder module; - static string ASSEMBLY_NAME = "MonoTests.System.Reflection.Emit.TypeBuilderTest"; - - static void SetUp () - { - AssemblyName assemblyName = new AssemblyName (); - assemblyName.Name = ASSEMBLY_NAME; - - assembly = - Thread.GetDomain ().DefineDynamicAssembly ( - assemblyName, AssemblyBuilderAccess.RunAndSave, "."); - - module = assembly.DefineDynamicModule ("module1", "Module1.dll"); - } - - static int Main() - { - SetUp (); - - TypeBuilder iface = module.DefineType ("IFace", TypeAttributes.Public | TypeAttributes.Interface | TypeAttributes.Abstract); - iface.DefineGenericParameters ("T"); - - TypeBuilder parent = module.DefineType ("Parent", TypeAttributes.Public); - - TypeBuilder child = module.DefineType ("Child", TypeAttributes.Public, parent); - - TypeBuilder main = module.DefineType ("Main", TypeAttributes.Public); - - child.AddInterfaceImplementation (iface.MakeGenericType (new Type [] { typeof(int) })); - - iface.DefineMethod ("Foo", MethodAttributes.Public | MethodAttributes.Abstract | MethodAttributes.Virtual, typeof(void), Type.EmptyTypes); - - ConstructorBuilder parent_constructor = parent.DefineDefaultConstructor (MethodAttributes.Public); - - ConstructorBuilder ctor = child.DefineConstructor (MethodAttributes.Public, CallingConventions.Standard, Type.EmptyTypes); - ILGenerator ig = ctor.GetILGenerator (); - ig.Emit (OpCodes.Ldarg_0); - ig.Emit (OpCodes.Call, parent_constructor); - ig.Emit (OpCodes.Ret); - - MethodBuilder foo_mb = child.DefineMethod ("Foo", MethodAttributes.Public | MethodAttributes.Virtual, typeof (void), Type.EmptyTypes); - foo_mb.GetILGenerator ().Emit (OpCodes.Ret); - - - MethodBuilder main_mb = main.DefineMethod ("Main", MethodAttributes.Public | MethodAttributes.Static, typeof (void), Type.EmptyTypes); - ig = main_mb.GetILGenerator (); - ig.Emit (OpCodes.Newobj, ctor); - ig.Emit (OpCodes.Callvirt, foo_mb); - ig.Emit (OpCodes.Ret); - - iface.CreateType (); - - parent.CreateType (); - - child.CreateType (); - - Type t = main.CreateType (); - - MethodInfo method = t.GetMethod ("Main"); - method.Invoke (null, null); - - /*Type gtd = typeof (A<>); - Type oi = gtd.MakeGenericType (gtd.GetGenericArguments ()); - - if (oi != gtd) { - Console.WriteLine ("fully open instantiation of static type not the same of the generic type definition"); - return 1; - } - - SetUp (); - TypeBuilder tb = module.DefineType ("Nullable`1", TypeAttributes.Public); - Type[] args = tb.DefineGenericParameters ("T"); - Type type = tb.MakeGenericType (args); - - if (type == tb) { - Console.WriteLine ("fully open instantiation of TypeBuilder is the same of the TypeBuilder"); - return 2; - } - - Type res = tb.CreateType (); - Type oires = res.MakeGenericType (res.GetGenericArguments ()); - - if (res != oires) { - Console.WriteLine ("fully open instantiation not the same of the generic type definition for the TypeBuilder created type"); - return 3; - } - - try { - type.GetConstructors (); - } catch (Exception e) { - Console.WriteLine ("fully open instantiation of TypeBuilder must have GetConstructors working {0}", e); - return 4; - } - - - try { - oires.GetConstructors (); - } catch (Exception e) { - Console.WriteLine ("fully open instantiation of the TypeBuilder created type must have GetConstructors working {0}", e); - return 5; - }*/ - - return 0; - } - } -} diff --git a/mono/tests/bug-461867.cs b/mono/tests/bug-461867.cs index eb2d89d63b..39290ab1ea 100644 --- a/mono/tests/bug-461867.cs +++ b/mono/tests/bug-461867.cs @@ -1,12 +1,18 @@ using System; using System.Runtime.InteropServices; +[AttributeUsage (AttributeTargets.Method)] +sealed class MonoPInvokeCallbackAttribute : Attribute { + public MonoPInvokeCallbackAttribute (Type t) {} +} + namespace TestApp { public delegate char MyDelegate(int x); class Driver { + [MonoPInvokeCallbackAttribute (typeof (MyDelegate))] static char Test (int x) { return (char)x; } static int Main() diff --git a/mono/tests/bug-462592.cs b/mono/tests/bug-462592.cs deleted file mode 100644 index e639ecaccc..0000000000 --- a/mono/tests/bug-462592.cs +++ /dev/null @@ -1,66 +0,0 @@ -using System; -using System.Threading; -using System.Reflection; -using System.Reflection.Emit; - -public class Test -{ - public virtual void Foo (int i) - { - } -} - -class Driver -{ - static AssemblyBuilder assembly; - static ModuleBuilder module; - static string ASSEMBLY_NAME = "MonoTests.System.Reflection.Emit.TypeBuilderTest"; - - static void SetUp () - { - AssemblyName assemblyName = new AssemblyName (); - assemblyName.Name = ASSEMBLY_NAME; - - assembly = - Thread.GetDomain ().DefineDynamicAssembly ( - assemblyName, AssemblyBuilderAccess.RunAndSave, "."); - - module = assembly.DefineDynamicModule ("repro", "bug-462592-result.exe"); - } - - static int Main() - { - SetUp (); - - MethodInfo foo = typeof (Test).GetMethod ("Foo"); - TypeBuilder type = module.DefineType ("TestType", TypeAttributes.Public, typeof (Test), Type.EmptyTypes); - - MethodBuilder mb = type.DefineMethod ("Foo", MethodAttributes.Public | MethodAttributes.Virtual, typeof (void), new Type[] { typeof (int) }); - mb.DefineGenericParameters ("T"); - - ILGenerator il = mb.GetILGenerator (); - il.Emit (OpCodes.Ldarg_0); - il.Emit (OpCodes.Ldc_I4, 0); - il.Emit (OpCodes.Call, foo); - il.Emit (OpCodes.Ret); - - type.DefineMethodOverride (mb, foo); - - MethodBuilder main = type.DefineMethod ("Main", MethodAttributes.Public | MethodAttributes.Static, typeof (void), Type.EmptyTypes); - il = main.GetILGenerator (); - il.Emit (OpCodes.Newobj, type.DefineDefaultConstructor (MethodAttributes.Public)); - il.Emit (OpCodes.Ldc_I4, 0); - il.Emit (OpCodes.Callvirt, mb.MakeGenericMethod (new Type[] { typeof (string) })); - il.Emit (OpCodes.Ret); - - type.CreateType (); - assembly.SetEntryPoint (main); - - assembly.Save ("bug-462592-result.exe"); - - Assembly res = Assembly.LoadFrom ("bug-462592-result.exe"); - res.EntryPoint.Invoke (null, new object[0]); - return 0; - } -} - diff --git a/mono/tests/bug-47295.cs b/mono/tests/bug-47295.cs deleted file mode 100644 index 4bb18ac0a3..0000000000 --- a/mono/tests/bug-47295.cs +++ /dev/null @@ -1,85 +0,0 @@ -// -// bug-47295.cs: -// -// Regression test for bug #47295. -// -// Test from Marcus Urban (mathpup@mylinuxisp.com) -// - -using System; -using System.Reflection; -using System.Reflection.Emit; -using System.Runtime.InteropServices; - - -public class Testing -{ - public static void Method(int value) - { - Console.WriteLine( "Method( {0} )", value ); - } - - - [StructLayout(LayoutKind.Sequential)] - internal struct DelegateList - { - internal Delegate del; - } - - - public static void Main() - { - // Create a dynamic assembly and module to contain the - // subclass of MulticastDelegate that we will create - - AssemblyName asmName = new AssemblyName(); - asmName.Name = "DynamicAssembly"; - - AssemblyBuilder asmBuilder = - AppDomain.CurrentDomain.DefineDynamicAssembly( - asmName, AssemblyBuilderAccess.Run ); - - ModuleBuilder modBuilder = asmBuilder.DefineDynamicModule -( "DynamicModule" ); - - TypeBuilder typeBuilder = modBuilder.DefineType( "MyType", - TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.Sealed, - typeof( System.MulticastDelegate ) ); - - ConstructorBuilder cb = typeBuilder.DefineConstructor( - MethodAttributes.Public | MethodAttributes.HideBySig | - MethodAttributes.RTSpecialName | MethodAttributes.SpecialName, - CallingConventions.Standard, - new Type[] { typeof(Object), typeof (IntPtr) } ); - - cb.SetImplementationFlags( MethodImplAttributes.Runtime | -MethodImplAttributes.Managed ); - - MethodBuilder mb = typeBuilder.DefineMethod( - "Invoke", - MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes. -HideBySig, - typeof(void), - new Type[] { typeof(int) } ); - - mb.SetImplementationFlags( MethodImplAttributes.Runtime | -MethodImplAttributes.Managed ); - ParameterBuilder pb = mb.DefineParameter (1, ParameterAttributes.HasFieldMarshal, "foo"); - pb.SetMarshal (UnmanagedMarshal.DefineUnmanagedMarshal (UnmanagedType.I2)); - - // Create an instance of the delegate type and invoke it -- just to test - - Type myDelegateType = typeBuilder.CreateType(); - Delegate d = Delegate.CreateDelegate( myDelegateType, typeof -( Testing ), "Method" ); - d.DynamicInvoke( new object[] { 8 } ); - - DelegateList delegateList = new DelegateList(); - delegateList.del = d; - IntPtr ptr = Marshal.AllocHGlobal( Marshal.SizeOf( delegateList ) ); - - // The execption seems to occur at this statement: - Marshal.StructureToPtr( delegateList, ptr, false ); - } - -} diff --git a/mono/tests/bug-48015.cs b/mono/tests/bug-48015.cs deleted file mode 100644 index c5e7c303ae..0000000000 --- a/mono/tests/bug-48015.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System; -using System.Collections; -using System.Runtime.Remoting; - -public class Foo : System.ContextBoundObject { -} - -public class Bar : System.ContextBoundObject { - - public void Test(Foo f) { - if (RemotingServices.IsTransparentProxy (f)) - Console.WriteLine ("Bar::Test(Foo) Is TP"); - else - Console.WriteLine ("Bar::Test(Foo) Is NOT a TP (error!)"); - - if (!f.Equals (f)) - Console.WriteLine ("Bar::Test(Foo) f.Equals (b) failed (error!)"); - else - Console.WriteLine ("Bar::Test(Foo) f.Equals (f) ok!"); - } -} - -public class Driver { - public static void Main (string[] args) { - Foo f = new Foo(); - Bar b = new Bar(); - - if (!b.Equals (b)) - Console.WriteLine ("b.Equals (b) failed (error!)"); - else - Console.WriteLine ("b.Equals (b) ok!"); - - if (RemotingServices.IsTransparentProxy (b)) - Console.WriteLine ("b is a TP"); - else - Console.WriteLine ("b is NOT a TP (error!)"); - - b.Test(f); - - if (!f.Equals (f)) - Console.WriteLine ("f.Equals (b) failed (error!)"); - else - Console.WriteLine ("f.Equals (f) ok!"); - - Console.WriteLine ("test end."); - } -} - diff --git a/mono/tests/bug-515884.il b/mono/tests/bug-515884.il deleted file mode 100644 index 7e4972aaf5..0000000000 --- a/mono/tests/bug-515884.il +++ /dev/null @@ -1,37 +0,0 @@ -.assembly extern mscorlib -{ - .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. - .ver 2:0:0:0 -} -.assembly ConsoleApplication1 -{ - .hash algorithm 0x00008004 - .ver 0:0:0:0 -} -.module ConsoleApplication1.exe - - -.class private auto ansi beforefieldinit ConsoleApplication1.Program extends [mscorlib]System.Object -{ - .method public hidebysig static int32 Main(string[] args) cil managed - { - .entrypoint - .maxstack 8 - .locals init (class [mscorlib]System.AppDomain V_0) - - ldstr "Test" - call class [mscorlib]System.AppDomain [mscorlib]System.AppDomain::CreateDomain(string) - call instance string [mscorlib]System.AppDomain::get_FriendlyName() - - ldstr "Test" - callvirt instance bool [mscorlib]System.Object::Equals (object) - brfalse END - - ldc.i4.0 - ret - -END: - ldc.i4.1 - ret - } -} diff --git a/mono/tests/bug-544446.cs b/mono/tests/bug-544446.cs deleted file mode 100644 index 80b8fe48ea..0000000000 --- a/mono/tests/bug-544446.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System; -using System.Runtime.Remoting; -using System.Runtime.Remoting.Messaging; -using System.Runtime.Remoting.Proxies; -using System.Collections.Generic; - -class MyProxy : RealProxy { - readonly MarshalByRefObject target; - - public MyProxy (MarshalByRefObject target) : base (target.GetType()) - { - this.target = target; - } - - public override IMessage Invoke (IMessage request) { - IMethodCallMessage call = (IMethodCallMessage)request; - return RemotingServices.ExecuteMessage (target, call); - } -} - -class R1 : MarshalByRefObject { - - public void foo (out Dictionary paramAssignmentStatus) { - - paramAssignmentStatus = new Dictionary (); - paramAssignmentStatus.Add ("One", 1); - } -} - -class Test { - static int Main () { - MyProxy real_proxy = new MyProxy (new R1 ()); - R1 o = (R1)real_proxy.GetTransparentProxy (); - - Dictionary i; - o.foo (out i); - if (1 == i["One"]) - return 0; - return 1; - } -} diff --git a/mono/tests/bug-575941.cs b/mono/tests/bug-575941.cs deleted file mode 100644 index c7535900ff..0000000000 --- a/mono/tests/bug-575941.cs +++ /dev/null @@ -1,58 +0,0 @@ -using System; -using System.Threading; -using System.Reflection; -using System.Reflection.Emit; - -public class Tests -{ - public static int Main (String[] args) { - AssemblyName assemblyName = new AssemblyName (); - assemblyName.Name = "foo"; - - AssemblyBuilder assembly = - Thread.GetDomain ().DefineDynamicAssembly ( - assemblyName, AssemblyBuilderAccess.RunAndSave); - - ModuleBuilder module = assembly.DefineDynamicModule ("foo.dll"); - - TypeBuilder if_tb = module.DefineType ("IF`1", TypeAttributes.Public|TypeAttributes.Abstract|TypeAttributes.Interface); - - GenericTypeParameterBuilder [] typeParams = if_tb.DefineGenericParameters ("T"); - - MethodBuilder if_mb = if_tb.DefineMethod ("foo", MethodAttributes.Public|MethodAttributes.Abstract|MethodAttributes.Virtual, typeParams [0], Type.EmptyTypes); - MethodBuilder if_mb2 = if_tb.DefineMethod ("foo2", MethodAttributes.Public|MethodAttributes.Abstract|MethodAttributes.Virtual, typeParams [0], Type.EmptyTypes); - - - TypeBuilder tb = module.DefineType ("Foo`1", TypeAttributes.Public, typeof (object)); - GenericTypeParameterBuilder [] tbTypeParams = tb.DefineGenericParameters ("T"); - - - Type inst = if_tb.MakeGenericType (tbTypeParams [0]); - - tb.AddInterfaceImplementation (inst); - - var mb0 = tb.DefineMethod ("foo", MethodAttributes.Public|MethodAttributes.Virtual, typeParams [0], Type.EmptyTypes); - mb0.GetILGenerator ().Emit (OpCodes.Ret); - - var mb = tb.DefineMethod ("__foo", MethodAttributes.Public|MethodAttributes.Virtual, typeParams [0],Type.EmptyTypes); - var gen = mb.GetILGenerator (); - var local = gen.DeclareLocal (typeParams [0], false); - gen.Emit (OpCodes.Ldloca, local); - gen.Emit (OpCodes.Initobj, typeParams [0]); - gen.Emit (OpCodes.Ldloc, local); - gen.Emit (OpCodes.Ret); - - tb.DefineMethodOverride (mb, TypeBuilder.GetMethod (inst, if_mb)); - tb.DefineMethodOverride (mb, TypeBuilder.GetMethod (inst, if_mb2)); - - var k = if_tb.CreateType (); - - Type t = tb.CreateType (); - object obj = Activator.CreateInstance (t.MakeGenericType (new Type [] { typeof (string)})); - var info = k.MakeGenericType (new Type [] { typeof (string) }).GetMethod ("foo"); - var res = info.Invoke (obj, null); - - return res == null ? 0 : 1; - } -} - diff --git a/mono/tests/bug-80307.cs b/mono/tests/bug-80307.cs deleted file mode 100644 index 06c51b2d7a..0000000000 --- a/mono/tests/bug-80307.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System; -using System.IO; -using System.Web; -using System.Web.Hosting; - -class TinyHost : MarshalByRefObject -{ - public static TinyHost CreateHost () - { - string path = Directory.GetCurrentDirectory (); - string bin = Path.Combine (path, "bin"); - string asm = Path.GetFileName (typeof (TinyHost).Assembly.Location); - - Directory.CreateDirectory (bin); - File.Copy (asm, Path.Combine (bin, asm), true); - - return (TinyHost) ApplicationHost.CreateApplicationHost ( - typeof (TinyHost), "/", path); - - } - - public void Execute (string page) - { - SimpleWorkerRequest req = new SimpleWorkerRequest ( - page, "", Console.Out); - HttpRuntime.ProcessRequest (req); - } - - static void Main () - { - TinyHost h = CreateHost (); - StreamWriter w = new StreamWriter ("page.aspx"); - w.WriteLine (@"<%@ Page Language=""C#"" %>"); - w.WriteLine (@"<% Console.WriteLine(""Hello""); %>"); - w.Close (); - h.Execute ("page.aspx"); - } -} diff --git a/mono/tests/cominterop.cs b/mono/tests/cominterop.cs deleted file mode 100644 index fbfdcbbb16..0000000000 --- a/mono/tests/cominterop.cs +++ /dev/null @@ -1,1309 +0,0 @@ -// -// cominterop.cs: -// -// Tests for COM Interop related features -// - -using System; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - - -public class Tests -{ - - [DllImport("libtest")] - public static extern int mono_test_marshal_bstr_in([MarshalAs(UnmanagedType.BStr)]string str); - - [DllImport("libtest")] - public static extern int mono_test_marshal_bstr_out([MarshalAs(UnmanagedType.BStr)] out string str); - - [DllImport("libtest")] - public static extern int mono_test_marshal_bstr_in_null([MarshalAs(UnmanagedType.BStr)]string str); - - [DllImport("libtest")] - public static extern int mono_test_marshal_bstr_out_null([MarshalAs(UnmanagedType.BStr)] out string str); - - [DllImport("libtest")] - public static extern int mono_test_marshal_variant_in_sbyte([MarshalAs(UnmanagedType.Struct)]object obj); - - [DllImport("libtest")] - public static extern int mono_test_marshal_variant_in_byte([MarshalAs(UnmanagedType.Struct)]object obj); - - [DllImport("libtest")] - public static extern int mono_test_marshal_variant_in_short([MarshalAs(UnmanagedType.Struct)]object obj); - - [DllImport("libtest")] - public static extern int mono_test_marshal_variant_in_ushort([MarshalAs(UnmanagedType.Struct)]object obj); - - [DllImport("libtest")] - public static extern int mono_test_marshal_variant_in_int([MarshalAs(UnmanagedType.Struct)]object obj); - - [DllImport("libtest")] - public static extern int mono_test_marshal_variant_in_uint([MarshalAs(UnmanagedType.Struct)]object obj); - - [DllImport("libtest")] - public static extern int mono_test_marshal_variant_in_long([MarshalAs(UnmanagedType.Struct)]object obj); - - [DllImport("libtest")] - public static extern int mono_test_marshal_variant_in_ulong([MarshalAs(UnmanagedType.Struct)]object obj); - - [DllImport("libtest")] - public static extern int mono_test_marshal_variant_in_float([MarshalAs(UnmanagedType.Struct)]object obj); - - [DllImport("libtest")] - public static extern int mono_test_marshal_variant_in_double([MarshalAs(UnmanagedType.Struct)]object obj); - - [DllImport("libtest")] - public static extern int mono_test_marshal_variant_in_bstr ([MarshalAs (UnmanagedType.Struct)]object obj); - - [DllImport ("libtest")] - public static extern int mono_test_marshal_variant_in_bool_true ([MarshalAs (UnmanagedType.Struct)]object obj); - - [DllImport ("libtest")] - public static extern int mono_test_marshal_variant_in_bool_false ([MarshalAs (UnmanagedType.Struct)]object obj); - - [DllImport("libtest")] - public static extern int mono_test_marshal_variant_out_sbyte([MarshalAs(UnmanagedType.Struct)]out object obj); - - [DllImport("libtest")] - public static extern int mono_test_marshal_variant_out_sbyte_byref([MarshalAs(UnmanagedType.Struct)]out object obj); - - [DllImport("libtest")] - public static extern int mono_test_marshal_variant_out_byte([MarshalAs(UnmanagedType.Struct)]out object obj); - - [DllImport("libtest")] - public static extern int mono_test_marshal_variant_out_byte_byref([MarshalAs(UnmanagedType.Struct)]out object obj); - - [DllImport("libtest")] - public static extern int mono_test_marshal_variant_out_short([MarshalAs(UnmanagedType.Struct)]out object obj); - - [DllImport("libtest")] - public static extern int mono_test_marshal_variant_out_short_byref([MarshalAs(UnmanagedType.Struct)]out object obj); - - [DllImport("libtest")] - public static extern int mono_test_marshal_variant_out_ushort([MarshalAs(UnmanagedType.Struct)]out object obj); - - [DllImport("libtest")] - public static extern int mono_test_marshal_variant_out_ushort_byref([MarshalAs(UnmanagedType.Struct)]out object obj); - - [DllImport("libtest")] - public static extern int mono_test_marshal_variant_out_int([MarshalAs(UnmanagedType.Struct)]out object obj); - - [DllImport("libtest")] - public static extern int mono_test_marshal_variant_out_int_byref([MarshalAs(UnmanagedType.Struct)]out object obj); - - [DllImport("libtest")] - public static extern int mono_test_marshal_variant_out_uint([MarshalAs(UnmanagedType.Struct)]out object obj); - - [DllImport("libtest")] - public static extern int mono_test_marshal_variant_out_uint_byref([MarshalAs(UnmanagedType.Struct)]out object obj); - - [DllImport("libtest")] - public static extern int mono_test_marshal_variant_out_long([MarshalAs(UnmanagedType.Struct)]out object obj); - - [DllImport("libtest")] - public static extern int mono_test_marshal_variant_out_long_byref([MarshalAs(UnmanagedType.Struct)]out object obj); - - [DllImport("libtest")] - public static extern int mono_test_marshal_variant_out_ulong([MarshalAs(UnmanagedType.Struct)]out object obj); - - [DllImport("libtest")] - public static extern int mono_test_marshal_variant_out_ulong_byref([MarshalAs(UnmanagedType.Struct)]out object obj); - - [DllImport("libtest")] - public static extern int mono_test_marshal_variant_out_float([MarshalAs(UnmanagedType.Struct)]out object obj); - - [DllImport("libtest")] - public static extern int mono_test_marshal_variant_out_float_byref([MarshalAs(UnmanagedType.Struct)]out object obj); - - [DllImport("libtest")] - public static extern int mono_test_marshal_variant_out_double([MarshalAs(UnmanagedType.Struct)]out object obj); - - [DllImport("libtest")] - public static extern int mono_test_marshal_variant_out_double_byref([MarshalAs(UnmanagedType.Struct)]out object obj); - - [DllImport("libtest")] - public static extern int mono_test_marshal_variant_out_bstr ([MarshalAs (UnmanagedType.Struct)]out object obj); - - [DllImport("libtest")] - public static extern int mono_test_marshal_variant_out_bstr_byref ([MarshalAs (UnmanagedType.Struct)]out object obj); - - [DllImport("libtest")] - public static extern int mono_test_marshal_variant_out_bool_true ([MarshalAs (UnmanagedType.Struct)]out object obj); - - [DllImport("libtest")] - public static extern int mono_test_marshal_variant_out_bool_true_byref ([MarshalAs (UnmanagedType.Struct)]out object obj); - - [DllImport ("libtest")] - public static extern int mono_test_marshal_variant_out_bool_false ([MarshalAs (UnmanagedType.Struct)]out object obj); - - [DllImport ("libtest")] - public static extern int mono_test_marshal_variant_out_bool_false_byref ([MarshalAs (UnmanagedType.Struct)]out object obj); - - - public delegate int VarFunc (VarEnum vt, [MarshalAs (UnmanagedType.Struct)] object obj); - - public delegate int VarRefFunc (VarEnum vt, [MarshalAs (UnmanagedType.Struct)] ref object obj); - - [DllImport ("libtest")] - public static extern int mono_test_marshal_variant_in_sbyte_unmanaged (VarFunc func); - - [DllImport ("libtest")] - public static extern int mono_test_marshal_variant_in_byte_unmanaged (VarFunc func); - - [DllImport ("libtest")] - public static extern int mono_test_marshal_variant_in_short_unmanaged (VarFunc func); - - [DllImport ("libtest")] - public static extern int mono_test_marshal_variant_in_ushort_unmanaged (VarFunc func); - - [DllImport ("libtest")] - public static extern int mono_test_marshal_variant_in_int_unmanaged (VarFunc func); - - [DllImport ("libtest")] - public static extern int mono_test_marshal_variant_in_uint_unmanaged (VarFunc func); - - [DllImport ("libtest")] - public static extern int mono_test_marshal_variant_in_long_unmanaged (VarFunc func); - - [DllImport ("libtest")] - public static extern int mono_test_marshal_variant_in_ulong_unmanaged (VarFunc func); - - [DllImport ("libtest")] - public static extern int mono_test_marshal_variant_in_float_unmanaged (VarFunc func); - - [DllImport ("libtest")] - public static extern int mono_test_marshal_variant_in_double_unmanaged (VarFunc func); - - [DllImport ("libtest")] - public static extern int mono_test_marshal_variant_in_bstr_unmanaged (VarFunc func); - - [DllImport ("libtest")] - public static extern int mono_test_marshal_variant_in_bool_true_unmanaged (VarFunc func); - - [DllImport ("libtest")] - public static extern int mono_test_marshal_variant_in_bool_false_unmanaged (VarFunc func); - - [DllImport ("libtest")] - public static extern int mono_test_marshal_variant_out_sbyte_unmanaged (VarRefFunc func); - - [DllImport ("libtest")] - public static extern int mono_test_marshal_variant_out_byte_unmanaged (VarRefFunc func); - - [DllImport ("libtest")] - public static extern int mono_test_marshal_variant_out_short_unmanaged (VarRefFunc func); - - [DllImport ("libtest")] - public static extern int mono_test_marshal_variant_out_ushort_unmanaged (VarRefFunc func); - - [DllImport ("libtest")] - public static extern int mono_test_marshal_variant_out_int_unmanaged (VarRefFunc func); - - [DllImport ("libtest")] - public static extern int mono_test_marshal_variant_out_uint_unmanaged (VarRefFunc func); - - [DllImport ("libtest")] - public static extern int mono_test_marshal_variant_out_long_unmanaged (VarRefFunc func); - - [DllImport ("libtest")] - public static extern int mono_test_marshal_variant_out_ulong_unmanaged (VarRefFunc func); - - [DllImport ("libtest")] - public static extern int mono_test_marshal_variant_out_float_unmanaged (VarRefFunc func); - - [DllImport ("libtest")] - public static extern int mono_test_marshal_variant_out_double_unmanaged (VarRefFunc func); - - [DllImport ("libtest")] - public static extern int mono_test_marshal_variant_out_bstr_unmanaged (VarRefFunc func); - - [DllImport ("libtest")] - public static extern int mono_test_marshal_variant_out_bool_true_unmanaged (VarRefFunc func); - - [DllImport ("libtest")] - public static extern int mono_test_marshal_variant_out_bool_false_unmanaged (VarRefFunc func); - - [DllImport ("libtest")] - public static extern int mono_test_marshal_com_object_create (out IntPtr pUnk); - - [DllImport ("libtest")] - public static extern int mono_test_marshal_com_object_same (out IntPtr pUnk); - - [DllImport ("libtest")] - public static extern int mono_test_marshal_com_object_destroy (IntPtr pUnk); - - [DllImport ("libtest")] - public static extern int mono_test_marshal_com_object_ref_count (IntPtr pUnk); - - [DllImport ("libtest")] - public static extern int mono_test_marshal_ccw_identity ([MarshalAs (UnmanagedType.Interface)]ITest itest); - - [DllImport ("libtest")] - public static extern int mono_test_marshal_ccw_reflexive ([MarshalAs (UnmanagedType.Interface)]ITest itest); - - [DllImport ("libtest")] - public static extern int mono_test_marshal_ccw_transitive ([MarshalAs (UnmanagedType.Interface)]ITest itest); - - [DllImport ("libtest")] - public static extern int mono_test_marshal_ccw_itest ([MarshalAs (UnmanagedType.Interface)]ITest itest); - - [DllImport ("libtest")] - public static extern int mono_test_marshal_ccw_itest ([MarshalAs (UnmanagedType.Interface)]ITestPresSig itest); - - [DllImport("libtest")] - public static extern int mono_test_marshal_safearray_out_1dim_vt_bstr_empty ([MarshalAs (UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)]out Array array); - - [DllImport("libtest")] - public static extern int mono_test_marshal_safearray_out_1dim_vt_bstr ([MarshalAs (UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)]out Array array); - - [DllImport("libtest")] - public static extern int mono_test_marshal_safearray_out_2dim_vt_i4 ([MarshalAs (UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)]out Array array); - - [DllImport("libtest")] - public static extern int mono_test_marshal_safearray_out_4dim_vt_i4 ([MarshalAs (UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)]out Array array); - - [DllImport("libtest")] - public static extern int mono_test_marshal_safearray_in_byval_1dim_empty ([In, MarshalAs (UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)] Array array); - - [DllImport("libtest")] - public static extern int mono_test_marshal_safearray_in_byval_1dim_vt_i4 ([In, MarshalAs (UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)] Array array); - - [DllImport("libtest")] - public static extern int mono_test_marshal_safearray_in_byval_1dim_vt_mixed ([In, MarshalAs (UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)] Array array); - - [DllImport("libtest")] - public static extern int mono_test_marshal_safearray_in_byval_2dim_vt_i4 ([In, MarshalAs (UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)] Array array); - - [DllImport("libtest")] - public static extern int mono_test_marshal_safearray_in_byval_3dim_vt_bstr ([In, MarshalAs (UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)] Array array); - - [DllImport("libtest")] - public static extern int mono_test_marshal_safearray_in_byref_3dim_vt_bstr ([In, MarshalAs (UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)] ref Array array); - - [DllImport("libtest")] - public static extern int mono_test_marshal_safearray_in_out_byref_1dim_empty ([In, Out, MarshalAs (UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)] ref Array array); - - [DllImport("libtest")] - public static extern int mono_test_marshal_safearray_in_out_byref_3dim_vt_bstr ([In, Out, MarshalAs (UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)] ref Array array); - - [DllImport("libtest")] - public static extern int mono_test_marshal_safearray_in_out_byref_1dim_vt_i4 ([In, Out, MarshalAs (UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)] ref Array array); - - [DllImport("libtest")] - public static extern int mono_test_marshal_safearray_in_out_byval_1dim_vt_i4 ([In, Out, MarshalAs (UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)] Array array); - - [DllImport("libtest")] - public static extern int mono_test_marshal_safearray_in_out_byval_3dim_vt_bstr ([In, Out, MarshalAs (UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)] Array array); - - [DllImport("libtest")] - public static extern int mono_test_marshal_safearray_mixed ( - [In, Out, MarshalAs (UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)] Array array1, - [MarshalAs (UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)] out Array array2, - [In, MarshalAs (UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)] Array array3, - [In, Out, MarshalAs (UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)] ref Array array4); - - [DllImport("libtest")] - public static extern bool mono_cominterop_is_supported (); - - public static int Main () - { - - bool isWindows = !(((int)Environment.OSVersion.Platform == 4) || - ((int)Environment.OSVersion.Platform == 128)); - - if (mono_cominterop_is_supported () || isWindows) - { - #region BSTR Tests - - string str; - if (mono_test_marshal_bstr_in ("mono_test_marshal_bstr_in") != 0) - return 1; - if (mono_test_marshal_bstr_out (out str) != 0 || str != "mono_test_marshal_bstr_out") - return 2; - if (mono_test_marshal_bstr_in_null (null) != 0) - return 1; - if (mono_test_marshal_bstr_out_null (out str) != 0 || str != null) - return 2; - - #endregion // BSTR Tests - - #region VARIANT Tests - - object obj; - if (mono_test_marshal_variant_in_sbyte ((sbyte)100) != 0) - return 13; - if (mono_test_marshal_variant_in_byte ((byte)100) != 0) - return 14; - if (mono_test_marshal_variant_in_short ((short)314) != 0) - return 15; - if (mono_test_marshal_variant_in_ushort ((ushort)314) != 0) - return 16; - if (mono_test_marshal_variant_in_int ((int)314) != 0) - return 17; - if (mono_test_marshal_variant_in_uint ((uint)314) != 0) - return 18; - if (mono_test_marshal_variant_in_long ((long)314) != 0) - return 19; - if (mono_test_marshal_variant_in_ulong ((ulong)314) != 0) - return 20; - if (mono_test_marshal_variant_in_float ((float)3.14) != 0) - return 21; - if (mono_test_marshal_variant_in_double ((double)3.14) != 0) - return 22; - if (mono_test_marshal_variant_in_bstr ("PI") != 0) - return 23; - if (mono_test_marshal_variant_out_sbyte (out obj) != 0 || (sbyte)obj != 100) - return 24; - if (mono_test_marshal_variant_out_byte (out obj) != 0 || (byte)obj != 100) - return 25; - if (mono_test_marshal_variant_out_short (out obj) != 0 || (short)obj != 314) - return 26; - if (mono_test_marshal_variant_out_ushort (out obj) != 0 || (ushort)obj != 314) - return 27; - if (mono_test_marshal_variant_out_int (out obj) != 0 || (int)obj != 314) - return 28; - if (mono_test_marshal_variant_out_uint (out obj) != 0 || (uint)obj != 314) - return 29; - if (mono_test_marshal_variant_out_long (out obj) != 0 || (long)obj != 314) - return 30; - if (mono_test_marshal_variant_out_ulong (out obj) != 0 || (ulong)obj != 314) - return 31; - if (mono_test_marshal_variant_out_float (out obj) != 0 || ((float)obj - 3.14) / 3.14 > .001) - return 32; - if (mono_test_marshal_variant_out_double (out obj) != 0 || ((double)obj - 3.14) / 3.14 > .001) - return 33; - if (mono_test_marshal_variant_out_bstr (out obj) != 0 || (string)obj != "PI") - return 34; - - VarFunc func = new VarFunc (mono_test_marshal_variant_in_callback); - if (mono_test_marshal_variant_in_sbyte_unmanaged (func) != 0) - return 35; - if (mono_test_marshal_variant_in_byte_unmanaged (func) != 0) - return 36; - if (mono_test_marshal_variant_in_short_unmanaged (func) != 0) - return 37; - if (mono_test_marshal_variant_in_ushort_unmanaged (func) != 0) - return 38; - if (mono_test_marshal_variant_in_int_unmanaged (func) != 0) - return 39; - if (mono_test_marshal_variant_in_uint_unmanaged (func) != 0) - return 40; - if (mono_test_marshal_variant_in_long_unmanaged (func) != 0) - return 41; - if (mono_test_marshal_variant_in_ulong_unmanaged (func) != 0) - return 42; - if (mono_test_marshal_variant_in_float_unmanaged (func) != 0) - return 43; - if (mono_test_marshal_variant_in_double_unmanaged (func) != 0) - return 44; - if (mono_test_marshal_variant_in_bstr_unmanaged (func) != 0) - return 45; - if (mono_test_marshal_variant_in_bool_true_unmanaged (func) != 0) - return 46; - - VarRefFunc reffunc = new VarRefFunc (mono_test_marshal_variant_out_callback); - if (mono_test_marshal_variant_out_sbyte_unmanaged (reffunc) != 0) - return 50; - if (mono_test_marshal_variant_out_byte_unmanaged (reffunc) != 0) - return 51; - if (mono_test_marshal_variant_out_short_unmanaged (reffunc) != 0) - return 52; - if (mono_test_marshal_variant_out_ushort_unmanaged (reffunc) != 0) - return 53; - if (mono_test_marshal_variant_out_int_unmanaged (reffunc) != 0) - return 54; - if (mono_test_marshal_variant_out_uint_unmanaged (reffunc) != 0) - return 55; - if (mono_test_marshal_variant_out_long_unmanaged (reffunc) != 0) - return 56; - if (mono_test_marshal_variant_out_ulong_unmanaged (reffunc) != 0) - return 57; - if (mono_test_marshal_variant_out_float_unmanaged (reffunc) != 0) - return 58; - if (mono_test_marshal_variant_out_double_unmanaged (reffunc) != 0) - return 59; - if (mono_test_marshal_variant_out_bstr_unmanaged (reffunc) != 0) - return 60; - if (mono_test_marshal_variant_out_bool_true_unmanaged (reffunc) != 0) - return 61; - - if (mono_test_marshal_variant_out_sbyte_byref (out obj) != 0 || (sbyte)obj != 100) - return 97; - if (mono_test_marshal_variant_out_byte_byref (out obj) != 0 || (byte)obj != 100) - return 98; - if (mono_test_marshal_variant_out_short_byref (out obj) != 0 || (short)obj != 314) - return 99; - if (mono_test_marshal_variant_out_ushort_byref (out obj) != 0 || (ushort)obj != 314) - return 100; - if (mono_test_marshal_variant_out_int_byref (out obj) != 0 || (int)obj != 314) - return 101; - if (mono_test_marshal_variant_out_uint_byref (out obj) != 0 || (uint)obj != 314) - return 102; - if (mono_test_marshal_variant_out_long_byref (out obj) != 0 || (long)obj != 314) - return 103; - if (mono_test_marshal_variant_out_ulong_byref (out obj) != 0 || (ulong)obj != 314) - return 104; - if (mono_test_marshal_variant_out_float_byref (out obj) != 0 || ((float)obj - 3.14) / 3.14 > .001) - return 105; - if (mono_test_marshal_variant_out_double_byref (out obj) != 0 || ((double)obj - 3.14) / 3.14 > .001) - return 106; - if (mono_test_marshal_variant_out_bstr_byref (out obj) != 0 || (string)obj != "PI") - return 107; - - #endregion // VARIANT Tests - - #region Runtime Callable Wrapper Tests - - IntPtr pUnk; - if (mono_test_marshal_com_object_create (out pUnk) != 0) - return 145; - - if (mono_test_marshal_com_object_ref_count (pUnk) != 1) - return 146; - - if (Marshal.AddRef (pUnk) != 2) - return 147; - - if (mono_test_marshal_com_object_ref_count (pUnk) != 2) - return 148; - - if (Marshal.Release (pUnk) != 1) - return 149; - - if (mono_test_marshal_com_object_ref_count (pUnk) != 1) - return 150; - - object com_obj = Marshal.GetObjectForIUnknown (pUnk); - - if (com_obj == null) - return 151; - - ITest itest = com_obj as ITest; - - if (itest == null) - return 152; - - IntPtr pUnk2; - if (mono_test_marshal_com_object_same (out pUnk2) != 0) - return 153; - - object com_obj2 = Marshal.GetObjectForIUnknown (pUnk2); - - if (com_obj != com_obj2) - return 154; - - if (!com_obj.Equals (com_obj2)) - return 155; - - IntPtr pUnk3; - if (mono_test_marshal_com_object_create (out pUnk3) != 0) - return 156; - - object com_obj3 = Marshal.GetObjectForIUnknown (pUnk3); - if (com_obj == com_obj3) - return 157; - - if (com_obj.Equals (com_obj3)) - return 158; - - // com_obj & com_obj2 share a RCW - if (Marshal.ReleaseComObject (com_obj2) != 1) - return 159; - - // com_obj3 should only have one RCW - if (Marshal.ReleaseComObject (com_obj3) != 0) - return 160; - - IntPtr iunknown = Marshal.GetIUnknownForObject (com_obj); - if (iunknown == IntPtr.Zero) - return 170; - - if (pUnk != iunknown) - return 171; - - if (TestITest (itest) != 0) - return 172; - - if (TestITestPresSig (itest as ITestPresSig) != 0) - return 173; - - if (TestITestDelegate (itest) != 0) - return 174; - - itest = new TestClass (); - - if (TestITest (itest) != 0) - return 175; - - itest = (ITest)System.Activator.CreateInstance (typeof(TestActivatorClass)); - - if (TestITest (itest) != 0) - return 176; - - #endregion // Runtime Callable Wrapper Tests - - #region COM Callable Wrapper Tests - - ManagedTest test = new ManagedTest (); - - mono_test_marshal_ccw_itest (test); - - if (test.Status != 0) - return 200; - - ManagedTestPresSig test_pres_sig = new ManagedTestPresSig (); - - mono_test_marshal_ccw_itest (test_pres_sig); - - #endregion // COM Callable Wrapper Tests - - #region SAFEARRAY tests - - if (isWindows) { - - /* out */ - - Array array; - if ((mono_test_marshal_safearray_out_1dim_vt_bstr_empty (out array) != 0) || (array.Rank != 1) || (array.Length != 0)) - return 62; - - if ((mono_test_marshal_safearray_out_1dim_vt_bstr (out array) != 0) || (array.Rank != 1) || (array.Length != 10)) - return 63; - for (int i = 0; i < 10; ++i) { - if (i != Convert.ToInt32 (array.GetValue (i))) - return 64; - } - - if ((mono_test_marshal_safearray_out_2dim_vt_i4 (out array) != 0) || (array.Rank != 2)) - return 65; - if ( (array.GetLowerBound (0) != 0) || (array.GetUpperBound (0) != 3) - || (array.GetLowerBound (1) != 0) || (array.GetUpperBound (1) != 2)) - return 66; - for (int i = array.GetLowerBound (0); i <= array.GetUpperBound (0); ++i) - { - for (int j = array.GetLowerBound (1); j <= array.GetUpperBound (1); ++j) { - if ((i + 1) * 10 + (j + 1) != (int)array.GetValue (new long[] { i, j })) - return 67; - } - } - - if ((mono_test_marshal_safearray_out_4dim_vt_i4 (out array) != 0) || (array.Rank != 4)) - return 68; - if ( (array.GetLowerBound (0) != 15) || (array.GetUpperBound (0) != 24) - || (array.GetLowerBound (1) != 20) || (array.GetUpperBound (1) != 22) - || (array.GetLowerBound (2) != 5) || (array.GetUpperBound (2) != 10) - || (array.GetLowerBound (3) != 12) || (array.GetUpperBound (3) != 18) ) - return 69; - - int index = 0; - for (int i = array.GetLowerBound (3); i <= array.GetUpperBound (3); ++i) { - for (int j = array.GetLowerBound (2); j <= array.GetUpperBound (2); ++j) { - for (int k = array.GetLowerBound (1); k <= array.GetUpperBound (1); ++k) { - for (int l = array.GetLowerBound (0); l <= array.GetUpperBound (0); ++l) { - if (index != (int)array.GetValue (new long[] { l, k, j, i })) - return 70; - ++index; - } - } - } - } - - /* in */ - - array = new object[] { }; - if (mono_test_marshal_safearray_in_byval_1dim_empty (array) != 0) - return 71; - - array = new object[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; - if (mono_test_marshal_safearray_in_byval_1dim_vt_i4 (array) != 0) - return 72; - - array = new object[] { 0, "1", 2, "3", 4, "5", 6, "7", 8, "9", 10, "11", 12 }; - if (mono_test_marshal_safearray_in_byval_1dim_vt_mixed (array) != 0) - return 73; - if ((int)array.GetValue (0) != 0) - return 74; - - array = new object[,] { { 11, 12, 13, 14 }, { 21, 22, 23, 24 } }; - if (mono_test_marshal_safearray_in_byval_2dim_vt_i4 (array) != 0) - return 75; - if ((int)array.GetValue (new int[] { 0, 0 }) != 11) - return 76; - - array = new object[,,] { { { "111", "112", "113" }, { "121", "122", "123" } }, { { "211", "212", "213" }, { "221", "222", "223" } } }; - if (mono_test_marshal_safearray_in_byval_3dim_vt_bstr (array) != 0) - return 77; - if ((string)array.GetValue (new int[] { 0, 0, 0 }) != "111") - return 78; - - array = new object[,,] { { { "111", "112", "113" }, { "121", "122", "123" } }, { { "211", "212", "213" }, { "221", "222", "223" } } }; - if ((mono_test_marshal_safearray_in_byref_3dim_vt_bstr (ref array) != 0) || (array.Rank != 3) || (array.Length != 12)) - return 79; - if ((string)array.GetValue (new int[] { 0, 0, 0 }) != "111") - return 80; - - /* in, out, byref */ - - array = new object[] { }; - if ((mono_test_marshal_safearray_in_out_byref_1dim_empty (ref array) != 0) || (array.Rank != 1) || (array.Length != 8)) - return 81; - for (int i = 0; i < 8; ++i) - { - if (i != Convert.ToInt32 (array.GetValue (i))) - return 82; - } - - array = new object[,,] { { { "111", "112", "113" }, { "121", "122", "123" } }, { { "211", "212", "213" }, { "221", "222", "223" } } }; - if ((mono_test_marshal_safearray_in_out_byref_3dim_vt_bstr (ref array) != 0) || (array.Rank != 1) || (array.Length != 8)) - return 83; - for (int i = 0; i < 8; ++i) - { - if (i != Convert.ToInt32 (array.GetValue (i))) - return 84; - } - - array = new object[] { 1 }; - if ((mono_test_marshal_safearray_in_out_byref_1dim_vt_i4 (ref array) != 0) || (array.Rank != 1) || (array.Length != 1)) - { - return 85; - } - if (Convert.ToInt32 (array.GetValue (0)) != -1) - return 86; - - /* in, out, byval */ - - array = new object[] { 1 }; - if ((mono_test_marshal_safearray_in_out_byval_1dim_vt_i4 (array) != 0) || (array.Rank != 1) || (array.Length != 1)) - { - return 87; - } - if (Convert.ToInt32 (array.GetValue (0)) != 12345) - return 88; - - array = new object[,,] { { { "111", "112", "113" }, { "121", "122", "123" } }, { { "211", "212", "213" }, { "221", "222", "223" } } }; - if ((mono_test_marshal_safearray_in_out_byval_3dim_vt_bstr (array) != 0) || (array.Rank != 3) || (array.Length != 12)) - { - return 89; - } - if (Convert.ToInt32 (array.GetValue (new int[] { 1, 1, 1 })) != 111) - return 90; - if (Convert.ToInt32 (array.GetValue (new int[] { 1, 1, 2 })) != 333) - return 91; - if (Convert.ToString(array.GetValue (new int[] { 0, 1, 0 })) != "ABCDEFG") - return 92; - - /* Multiple safearray parameters with various types and options */ - - Array array1 = new object[] { 1 }; - Array array2 = new object[,] { { 11, 12, 13, 14 }, { 21, 22, 23, 24 } }; - Array array3 = new object[] { 0, "1", 2, "3", 4, "5", 6, "7", 8, "9", 10, "11", 12 }; - Array array4 = new object[,,] { { { "111", "112", "113" }, { "121", "122", "123" } }, { { "211", "212", "213" }, { "221", "222", "223" } } }; - if ( (mono_test_marshal_safearray_mixed (array1, out array2, array3, ref array4) != 0) - || (array1.Rank != 1) || (array1.Length != 1) || (Convert.ToInt32 (array1.GetValue (0)) != 12345) - || (array2.Rank != 1) || (array2.Length != 10) - || (array4.Rank != 1) || (array4.Length != 8) - ) - { - return 93; - } - for (int i = 0; i < 10; ++i) - { - if (i != Convert.ToInt32 (array2.GetValue (i))) - return 94; - } - if ((int)array3.GetValue (0) != 0) - return 95; - for (int i = 0; i < 8; ++i) - { - if (i != Convert.ToInt32 (array4.GetValue (i))) - return 96; - } - } - #endregion // SafeArray Tests - - #region COM Visible Test - TestVisible test_vis = new TestVisible(); - IntPtr pDisp = Marshal.GetIDispatchForObject(test_vis); - if (pDisp == IntPtr.Zero) - return 200; - #endregion - } - - return 0; - } - - - [ComImport ()] - [Guid ("00000000-0000-0000-0000-000000000001")] - [InterfaceType (ComInterfaceType.InterfaceIsIUnknown)] - public interface ITest - { - // properties need to go first since mcs puts them there - ITest Test - { - [return: MarshalAs (UnmanagedType.Interface)] - [MethodImpl (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId (5242884)] - get; - } - - [MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] - void SByteIn (sbyte val); - [MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] - void ByteIn (byte val); - [MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] - void ShortIn (short val); - [MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] - void UShortIn (ushort val); - [MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] - void IntIn (int val); - [MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] - void UIntIn (uint val); - [MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] - void LongIn (long val); - [MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] - void ULongIn (ulong val); - [MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] - void FloatIn (float val); - [MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] - void DoubleIn (double val); - [MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] - void ITestIn ([MarshalAs (UnmanagedType.Interface)]ITest val); - [MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] - void ITestOut ([MarshalAs (UnmanagedType.Interface)]out ITest val); - } - - [ComImport ()] - [Guid ("00000000-0000-0000-0000-000000000001")] - [InterfaceType (ComInterfaceType.InterfaceIsIUnknown)] - public interface ITestPresSig - { - // properties need to go first since mcs puts them there - ITestPresSig Test - { - [return: MarshalAs (UnmanagedType.Interface)] - [MethodImpl (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId (5242884)] - get; - } - - [MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] - [PreserveSig ()] - int SByteIn (sbyte val); - [MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] - [PreserveSig ()] - int ByteIn (byte val); - [MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] - [PreserveSig ()] - int ShortIn (short val); - [MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] - [PreserveSig ()] - int UShortIn (ushort val); - [MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] - [PreserveSig ()] - int IntIn (int val); - [MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] - [PreserveSig ()] - int UIntIn (uint val); - [MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] - [PreserveSig ()] - int LongIn (long val); - [MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] - [PreserveSig ()] - int ULongIn (ulong val); - [MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] - [PreserveSig ()] - int FloatIn (float val); - [MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] - [PreserveSig ()] - int DoubleIn (double val); - [MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] - [PreserveSig ()] - int ITestIn ([MarshalAs (UnmanagedType.Interface)]ITestPresSig val); - [MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] - [PreserveSig ()] - int ITestOut ([MarshalAs (UnmanagedType.Interface)]out ITestPresSig val); - } - - [System.Runtime.InteropServices.GuidAttribute ("00000000-0000-0000-0000-000000000002")] - [System.Runtime.InteropServices.ComImportAttribute ()] - [System.Runtime.InteropServices.ClassInterfaceAttribute (ClassInterfaceType.None)] - public class _TestClass : ITest - { - // properties need to go first since mcs puts them there - public virtual extern ITest Test - { - [return: MarshalAs (UnmanagedType.Interface)] - [MethodImpl (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId (5242884)] - get; - } - - [MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] - public virtual extern void SByteIn (sbyte val); - [MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] - public virtual extern void ByteIn (byte val); - [MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] - public virtual extern void ShortIn (short val); - [MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] - public virtual extern void UShortIn (ushort val); - [MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] - public virtual extern void IntIn (int val); - [MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] - public virtual extern void UIntIn (uint val); - [MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] - public virtual extern void LongIn (long val); - [MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] - public virtual extern void ULongIn (ulong val); - [MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] - public virtual extern void FloatIn (float val); - [MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] - public virtual extern void DoubleIn (double val); - [MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] - public virtual extern void ITestIn ([MarshalAs (UnmanagedType.Interface)]ITest val); - [MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] - public virtual extern void ITestOut ([MarshalAs (UnmanagedType.Interface)]out ITest val); - } - - [System.Runtime.InteropServices.GuidAttribute ("00000000-0000-0000-0000-000000000002")] - public class TestClass : _TestClass - { - static TestClass () - { - ExtensibleClassFactory.RegisterObjectCreationCallback (new ObjectCreationDelegate (CreateObject)); ; - } - private static System.IntPtr CreateObject (System.IntPtr aggr) - { - IntPtr pUnk3; - mono_test_marshal_com_object_create (out pUnk3); - return pUnk3; - } - } - - [System.Runtime.InteropServices.GuidAttribute ("00000000-0000-0000-0000-000000000003")] - public class TestActivatorClass : _TestClass - { - static TestActivatorClass () - { - ExtensibleClassFactory.RegisterObjectCreationCallback (new ObjectCreationDelegate (CreateObject)); ; - } - private static System.IntPtr CreateObject (System.IntPtr aggr) - { - IntPtr pUnk3; - mono_test_marshal_com_object_create (out pUnk3); - return pUnk3; - } - } - - delegate void SByteInDelegate (sbyte val); - delegate void ByteInDelegate (byte val); - delegate void ShortInDelegate (short val); - delegate void UShortInDelegate (ushort val); - delegate void IntInDelegate (int val); - delegate void UIntInDelegate (uint val); - delegate void LongInDelegate (long val); - delegate void ULongInDelegate (ulong val); - delegate void FloatInDelegate (float val); - delegate void DoubleInDelegate (double val); - delegate void ITestInDelegate (ITest val); - delegate void ITestOutDelegate (out ITest val); - - public class ManagedTestPresSig : ITestPresSig - { // properties need to go first since mcs puts them there - public ITestPresSig Test - { - get - { - return new ManagedTestPresSig (); - } - } - - public int SByteIn (sbyte val) - { - if (val != -100) - return 1; - return 0; - } - - public int ByteIn (byte val) - { - if (val != 100) - return 2; - return 0; - } - - public int ShortIn (short val) - { - if (val != -100) - return 3; - return 0; - } - - public int UShortIn (ushort val) - { - if (val != 100) - return 4; - return 0; - } - - public int IntIn (int val) - { - if (val != -100) - return 5; - return 0; - } - - public int UIntIn (uint val) - { - if (val != 100) - return 6; - return 0; - } - - public int LongIn (long val) - { - if (val != -100) - return 7; - return 0; - } - - public int ULongIn (ulong val) - { - if (val != 100) - return 8; - return 0; - } - - public int FloatIn (float val) - { - if (Math.Abs (val - 3.14f) > .000001) - return 9; - return 0; - } - - public int DoubleIn (double val) - { - if (Math.Abs (val - 3.14f) > .000001) - return 10; - return 0; - } - - public int ITestIn ([MarshalAs (UnmanagedType.Interface)]ITestPresSig val) - { - if (val == null) - return 11; - if (null == val as ManagedTestPresSig) - return 12; - return 0; - } - - public int ITestOut ([MarshalAs (UnmanagedType.Interface)]out ITestPresSig val) - { - val = new ManagedTestPresSig (); - return 0; - } - } - - public class ManagedTest : ITest - { - private int status = 0; - public int Status - { - get { return status; } - } - public void SByteIn (sbyte val) - { - if (val != -100) - status = 1; - } - - public void ByteIn (byte val) - { - if (val != 100) - status = 2; - } - - public void ShortIn (short val) - { - if (val != -100) - status = 3; - } - - public void UShortIn (ushort val) - { - if (val != 100) - status = 4; - } - - public void IntIn (int val) - { - if (val != -100) - status = 5; - } - - public void UIntIn (uint val) - { - if (val != 100) - status = 6; - } - - public void LongIn (long val) - { - if (val != -100) - status = 7; - } - - public void ULongIn (ulong val) - { - if (val != 100) - status = 8; - } - - public void FloatIn (float val) - { - if (Math.Abs (val - 3.14f) > .000001) - status = 9; - } - - public void DoubleIn (double val) - { - if (Math.Abs (val - 3.14) > .000001) - status = 10; - } - - public void ITestIn (ITest val) - { - if (val == null) - status = 11; - if (null == val as ManagedTest) - status = 12; - } - - public void ITestOut (out ITest val) - { - val = new ManagedTest (); - } - - public ITest Test - { - get - { - return new ManagedTest (); - } - } - } - - public static int mono_test_marshal_variant_in_callback (VarEnum vt, object obj) - { - switch (vt) - { - case VarEnum.VT_I1: - if (obj.GetType () != typeof (sbyte)) - return 1; - if ((sbyte)obj != -100) - return 2; - break; - case VarEnum.VT_UI1: - if (obj.GetType () != typeof (byte)) - return 1; - if ((byte)obj != 100) - return 2; - break; - case VarEnum.VT_I2: - if (obj.GetType () != typeof (short)) - return 1; - if ((short)obj != -100) - return 2; - break; - case VarEnum.VT_UI2: - if (obj.GetType () != typeof (ushort)) - return 1; - if ((ushort)obj != 100) - return 2; - break; - case VarEnum.VT_I4: - if (obj.GetType () != typeof (int)) - return 1; - if ((int)obj != -100) - return 2; - break; - case VarEnum.VT_UI4: - if (obj.GetType () != typeof (uint)) - return 1; - if ((uint)obj != 100) - return 2; - break; - case VarEnum.VT_I8: - if (obj.GetType () != typeof (long)) - return 1; - if ((long)obj != -100) - return 2; - break; - case VarEnum.VT_UI8: - if (obj.GetType () != typeof (ulong)) - return 1; - if ((ulong)obj != 100) - return 2; - break; - case VarEnum.VT_R4: - if (obj.GetType () != typeof (float)) - return 1; - if (Math.Abs ((float)obj - 3.14f) > 1e-10) - return 2; - break; - case VarEnum.VT_R8: - if (obj.GetType () != typeof (double)) - return 1; - if (Math.Abs ((double)obj - 3.14) > 1e-10) - return 2; - break; - case VarEnum.VT_BSTR: - if (obj.GetType () != typeof (string)) - return 1; - if ((string)obj != "PI") - return 2; - break; - case VarEnum.VT_BOOL: - if (obj.GetType () != typeof (bool)) - return 1; - if ((bool)obj != true) - return 2; - break; - } - return 0; - } - - public static int mono_test_marshal_variant_out_callback (VarEnum vt, ref object obj) - { - switch (vt) { - case VarEnum.VT_I1: - obj = (sbyte)-100; - break; - case VarEnum.VT_UI1: - obj = (byte)100; - break; - case VarEnum.VT_I2: - obj = (short)-100; - break; - case VarEnum.VT_UI2: - obj = (ushort)100; - break; - case VarEnum.VT_I4: - obj = (int)-100; - break; - case VarEnum.VT_UI4: - obj = (uint)100; - break; - case VarEnum.VT_I8: - obj = (long)-100; - break; - case VarEnum.VT_UI8: - obj = (ulong)100; - break; - case VarEnum.VT_R4: - obj = (float)3.14f; - break; - case VarEnum.VT_R8: - obj = (double)3.14; - break; - case VarEnum.VT_BSTR: - obj = "PI"; - break; - case VarEnum.VT_BOOL: - obj = true; - break; - } - return 0; - } - - public static int TestITest (ITest itest) - { - try { - ITest itest2; - itest.SByteIn (-100); - itest.ByteIn (100); - itest.ShortIn (-100); - itest.UShortIn (100); - itest.IntIn (-100); - itest.UIntIn (100); - itest.LongIn (-100); - itest.ULongIn (100); - itest.FloatIn (3.14f); - itest.DoubleIn (3.14); - itest.ITestIn (itest); - itest.ITestOut (out itest2); - } - catch (Exception ex) { - return 1; - } - return 0; - } - - public static int TestITestPresSig (ITestPresSig itest) - { - ITestPresSig itest2; - if (itest.SByteIn (-100) != 0) - return 1000; - if (itest.ByteIn (100) != 0) - return 1001; - if (itest.ShortIn (-100) != 0) - return 1002; - if (itest.UShortIn (100) != 0) - return 1003; - if (itest.IntIn (-100) != 0) - return 1004; - if (itest.UIntIn (100) != 0) - return 1005; - if (itest.LongIn (-100) != 0) - return 1006; - if (itest.ULongIn (100) != 0) - return 1007; - if (itest.FloatIn (3.14f) != 0) - return 1008; - if (itest.DoubleIn (3.14) != 0) - return 1009; - if (itest.ITestIn (itest) != 0) - return 1010; - if (itest.ITestOut (out itest2) != 0) - return 1011; - return 0; - } - - public static int TestITestDelegate (ITest itest) - { - try { - ITest itest2; - - SByteInDelegate SByteInFcn= itest.SByteIn; - ByteInDelegate ByteInFcn = itest.ByteIn; - UShortInDelegate UShortInFcn = itest.UShortIn; - IntInDelegate IntInFcn = itest.IntIn; - UIntInDelegate UIntInFcn = itest.UIntIn; - LongInDelegate LongInFcn = itest.LongIn; - - ULongInDelegate ULongInFcn = itest.ULongIn; - FloatInDelegate FloatInFcn = itest.FloatIn; - DoubleInDelegate DoubleInFcn = itest.DoubleIn; - ITestInDelegate ITestInFcn = itest.ITestIn; - ITestOutDelegate ITestOutFcn = itest.ITestOut; - - SByteInFcn (-100); - ByteInFcn (100); - UShortInFcn (100); - IntInFcn (-100); - UIntInFcn (100); - LongInFcn (-100); - ULongInFcn (100); - FloatInFcn (3.14f); - DoubleInFcn (3.14); - ITestInFcn (itest); - ITestOutFcn (out itest2); - } - catch (Exception) { - return 1; - } - return 0; - } -} - -public class TestVisible -{ -} diff --git a/mono/tests/constraints-load.il b/mono/tests/constraints-load.il deleted file mode 100644 index 7b5b6e319a..0000000000 --- a/mono/tests/constraints-load.il +++ /dev/null @@ -1,212 +0,0 @@ -.assembly extern mscorlib -{ - .ver 2:0:0:0 - .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. -} -.assembly 'dd' -{ - .custom instance void class [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::'.ctor'() = ( - 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx - 63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) // ceptionThrows. - - .hash algorithm 0x00008004 - .ver 0:0:0:0 -} -.module dd.exe // GUID = {7278218D-519A-4CA2-B185-7B5A5A3F17E7} - - - .class public auto ansi beforefieldinit Foo`1<(class [mscorlib]System.BrokenIComparable`1) T> - extends [mscorlib]System.Object - { - - // method line 1 - .method public hidebysig specialname rtspecialname - instance default void '.ctor' () cil managed - { - // Method begins at RVA 0x20ec - // Code size 7 (0x7) - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: call instance void object::'.ctor'() - IL_0006: ret - } // end of method Foo`1::.ctor - - // method line 2 - .method public hidebysig - instance default string Test () cil managed - { - // Method begins at RVA 0x20f4 - // Code size 2 (0x2) - .maxstack 8 - IL_0000: ldnull - IL_0001: ret - } // end of method Foo`1::Test - - } // end of class Foo`1 - - .class public auto ansi beforefieldinit Foo - extends [mscorlib]System.Object - { - - // method line 3 - .method public hidebysig specialname rtspecialname - instance default void '.ctor' () cil managed - { - // Method begins at RVA 0x20f8 - // Code size 7 (0x7) - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: call instance void object::'.ctor'() - IL_0006: ret - } // end of method Foo::.ctor - - // method line 4 - .method public hidebysig - instance default string Test<(class [mscorlib]System.BrokenIComparable`1) T> () cil managed - { - // Method begins at RVA 0x2100 - // Code size 2 (0x2) - .maxstack 8 - IL_0000: ldnull - IL_0001: ret - } // end of method Foo::Test - - } // end of class Foo - - .class public auto ansi abstract sealed beforefieldinit Driver - extends [mscorlib]System.Object - { - - // method line 5 - .method private static hidebysig - default void UseBrokenMethod () cil managed - { - // Method begins at RVA 0x2104 - // Code size 12 (0xc) - .maxstack 8 - IL_0000: newobj instance void class Foo::'.ctor'() - IL_0005: callvirt instance string class Foo::Test () - IL_000a: pop - IL_000b: ret - } // end of method Driver::UseBrokenMethod - - // method line 6 - .method private static hidebysig - default void UseBrokenType () cil managed - { - // Method begins at RVA 0x2114 - // Code size 12 (0xc) - .maxstack 8 - IL_0000: newobj instance void class Foo`1::'.ctor'() - IL_0005: callvirt instance string class Foo`1::Test() - IL_000a: pop - IL_000b: ret - } // end of method Driver::UseBrokenType - - // method line 7 - .method private static hidebysig - default void TestMethod () cil managed - { - // Method begins at RVA 0x2124 - // Code size 47 (0x2f) - .maxstack 10 - .locals init ( - class [mscorlib]System.Type V_0, - class [mscorlib]System.Reflection.MethodInfo V_1, - class [mscorlib]System.Type V_2, - class [mscorlib]System.Type V_3) - IL_0000: ldtoken Foo - IL_0005: call class [mscorlib]System.Type class [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) - IL_000a: stloc.0 - IL_000b: ldloc.0 - IL_000c: ldstr "Test" - IL_0011: callvirt instance class [mscorlib]System.Reflection.MethodInfo class [mscorlib]System.Type::GetMethod(string) - IL_0016: stloc.1 - IL_0017: ldloc.1 - IL_0018: callvirt instance class [mscorlib]System.Type[] class [mscorlib]System.Reflection.MethodInfo::GetGenericArguments() - IL_001d: ldc.i4.0 - IL_001e: ldelem.ref - IL_001f: stloc.2 - IL_0020: ldloc.2 - IL_0021: callvirt instance class [mscorlib]System.Type[] class [mscorlib]System.Type::GetGenericParameterConstraints() - IL_0026: ldc.i4.0 - IL_0027: ldelem.ref - IL_0028: stloc.3 - IL_0029: call void class Driver::UseBrokenMethod() - IL_002e: ret - } // end of method Driver::TestMethod - - // method line 8 - .method private static hidebysig - default void TestClass () cil managed - { - // Method begins at RVA 0x2160 - // Code size 35 (0x23) - .maxstack 8 - .locals init ( - class [mscorlib]System.Type V_0, - class [mscorlib]System.Type V_1, - class [mscorlib]System.Type V_2) - IL_0000: ldtoken Foo`1 - IL_0005: call class [mscorlib]System.Type class [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) - IL_000a: stloc.0 - IL_000b: ldloc.0 - IL_000c: callvirt instance class [mscorlib]System.Type[] class [mscorlib]System.Type::GetGenericArguments() - IL_0011: ldc.i4.0 - IL_0012: ldelem.ref - IL_0013: stloc.1 - IL_0014: ldloc.1 - IL_0015: callvirt instance class [mscorlib]System.Type[] class [mscorlib]System.Type::GetGenericParameterConstraints() - IL_001a: ldc.i4.0 - IL_001b: ldelem.ref - IL_001c: stloc.2 - IL_001d: call void class Driver::UseBrokenType() - IL_0022: ret - } // end of method Driver::TestClass - - // method line 9 - .method public static hidebysig - default int32 Main () cil managed - { - // Method begins at RVA 0x2190 - .entrypoint - // Code size 50 (0x32) - .maxstack 4 - .locals init ( - int32 V_0) - .try { // 1 - IL_0000: call void class Driver::TestMethod() - IL_0005: ldc.i4.1 - IL_0006: stloc.0 - IL_0007: leave IL_0030 - - IL_000c: leave IL_0017 - - } // end .try 1 - catch class [mscorlib]System.TypeLoadException { // 1 - IL_0011: pop - IL_0012: leave IL_0017 - - } // end handler 1 - .try { // 0 - IL_0017: call void class Driver::TestClass() - IL_001c: ldc.i4.2 - IL_001d: stloc.0 - IL_001e: leave IL_0030 - - IL_0023: leave IL_002e - - } // end .try 0 - catch class [mscorlib]System.TypeLoadException { // 0 - IL_0028: pop - IL_0029: leave IL_002e - - } // end handler 0 - IL_002e: ldc.i4.0 - IL_002f: ret - IL_0030: ldloc.0 - IL_0031: ret - } // end of method Driver::Main - - } // end of class Driver - diff --git a/mono/tests/cross-domain.cs b/mono/tests/cross-domain.cs deleted file mode 100644 index 9e340acdb2..0000000000 --- a/mono/tests/cross-domain.cs +++ /dev/null @@ -1,278 +0,0 @@ -using System; -using System.Net; -using System.Runtime.Remoting; -using System.Runtime.InteropServices; -using System.Text; -using System.Runtime.Serialization; - -public class Test: MarshalByRefObject -{ - public static int Main (string[] args) - { - AppDomain domain = AppDomain.CreateDomain ("testdomain1"); - Test server = (Test) domain.CreateInstanceAndUnwrap(typeof(Test).Assembly.FullName, "Test"); - return server.RunTest (); - } - - public int RunTest () - { - try - { - object t = null; - string s = (string)t; - AppDomain domain = AppDomain.CreateDomain ("testdomain"); - Remo server = (Remo) domain.CreateInstanceAndUnwrap(typeof(Test).Assembly.FullName,"Remo"); - if (System.Threading.Thread.GetDomainID () == server.GetDomainId ()) - throw new TestException ("Object not created in new domain", 1); - - Dada d = new Dada (); - d.p = 22; - - server.Run (); - server.Run2 (88, "hola"); - server.Run3 (99, d, "adeu"); - - string r = server.Run4 (200, d, "que"); - CheckValue (r, "vist", 140); - - try { - server.Run5 (200, d, "que"); - throw new TestException ("Exception expected", 150); - } - catch (Exception ex) { - CheckValue (ex.Message, "peta", 151); - } - - Dada d2; - d = server.Run6 (99, out d2, "adeu"); - CheckValue (d.p, 987, 161); - CheckValue (d2.p, 987, 162); - - d.p = 22; - d2 = server.Run7 (d); - CheckValue (d.p, 22, 170); - CheckValue (d2.p, 33, 170); - - byte[] ba = new byte[5]; - for (byte n=0; n(); - - for (int i = 0; i < GenericSize.Iterations; i++) { - lst.Add (method.Invoke (null, null)); - if (i % 15 == 0) - GC.Collect(); - } - - return 0; - } - } -} diff --git a/mono/tests/dynamic-method-access.2.cs b/mono/tests/dynamic-method-access.2.cs deleted file mode 100644 index 0be531c782..0000000000 --- a/mono/tests/dynamic-method-access.2.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using System.Reflection; -using System.Reflection.Emit; - -class Host { - - static int Field = 42; -} - -class Program { - - delegate int Getter (); - - public static int Main () - { - DynamicMethod method = new DynamicMethod ("GetField", - typeof (int), new Type [0], Type.GetType ("Host")); - - ILGenerator il = method.GetILGenerator (); - il.Emit (OpCodes.Ldsfld, typeof (Host).GetField ( - "Field", BindingFlags.Static | -BindingFlags.NonPublic)); - il.Emit (OpCodes.Ret); - - Getter g = (Getter) method.CreateDelegate (typeof (Getter)); - - Console.WriteLine (g ()); - if (g () == 42) - return 0; - return 1; - } -} diff --git a/mono/tests/dynamic-method-finalize.2.cs b/mono/tests/dynamic-method-finalize.2.cs deleted file mode 100644 index bcc74ddb38..0000000000 --- a/mono/tests/dynamic-method-finalize.2.cs +++ /dev/null @@ -1,51 +0,0 @@ -using System; -using System.Reflection; -using System.Reflection.Emit; - -delegate int Getter (); - -class Host { - - static int Field = 42; - - Getter g; - - public Host (Getter g) { - this.g = g; - } - - ~Host () { - int d = g (); - Console.WriteLine (d); - } -} - -class Program { - - static Host h; - - public static int Main () - { - DynamicMethod method = new DynamicMethod ("GetField", - typeof (int), new Type [0], Type.GetType ("Host")); - - ILGenerator il = method.GetILGenerator (); - il.Emit (OpCodes.Ldsfld, typeof (Host).GetField ( - "Field", BindingFlags.Static | -BindingFlags.NonPublic)); - il.Emit (OpCodes.Ret); - - Getter g = (Getter) method.CreateDelegate (typeof (Getter)); - - /* - * Create an object whose finalizer calls a dynamic method which - * dies at the same time. - * Storing into a static guarantees that this is only finalized during - * shutdown. This is needed since the !shutdown case still doesn't - * work. - */ - h = new Host (g); - - return 0; - } -} diff --git a/mono/tests/dynamic-method-resurrection.cs b/mono/tests/dynamic-method-resurrection.cs deleted file mode 100644 index 2715dd4432..0000000000 --- a/mono/tests/dynamic-method-resurrection.cs +++ /dev/null @@ -1,69 +0,0 @@ -using System; -using System.Reflection; -using System.Reflection.Emit; -using System.Runtime.InteropServices; -using System.Runtime.CompilerServices; -using System.Threading; - -delegate int Getter (); - -class Host { - - static int Field = 42; - - Getter g; - - public Host (Getter g) { - this.g = g; - } - - ~Host () { - Console.WriteLine ("got finalizated"); - Program.resed = g; - } -} - - -class Program { - internal static Getter resed; - static int result; - static void DoStuff () - { - DynamicMethod method = new DynamicMethod ("GetField", - typeof (int), new Type [0], Type.GetType ("Host")); - - ILGenerator il = method.GetILGenerator (); - il.Emit (OpCodes.Ldsfld, typeof (Host).GetField ("Field", BindingFlags.Static | BindingFlags.NonPublic)); - il.Emit (OpCodes.Ret); - - var g = (Getter)method.CreateDelegate (typeof (Getter)); - new Host (g); - } - - static bool CheckStuff () { - if (resed == null) - return false; - Program.result = resed (); - resed = null; - return true; - } - - public static int Main () - { - int cnt = 5; - var t = new Thread (DoStuff); - t.Start (); - t.Join (); - do { - if (CheckStuff ()) - break; - GC.Collect (); - GC.WaitForPendingFinalizers (); - Thread.Sleep (10); - } while (cnt-- > 0); - GC.Collect (); - GC.WaitForPendingFinalizers (); - Console.WriteLine ("done with finalizers"); - return result == 42 ? 0 : 1; - } -} diff --git a/mono/tests/dynamic-method-stack-traces.cs b/mono/tests/dynamic-method-stack-traces.cs deleted file mode 100644 index 965c525ae8..0000000000 --- a/mono/tests/dynamic-method-stack-traces.cs +++ /dev/null @@ -1,86 +0,0 @@ -using System; -using System.Threading; -using System.Reflection; -using System.Reflection.Emit; -using System.Runtime.ExceptionServices; -using System.Diagnostics; - -public class A -{ - public static Exception Caught; - - public static void ThrowMe() - { - Exception e; - try - { - throw new Exception("test"); - } - catch (Exception e2) - { - e = e2; - } - - var edi = ExceptionDispatchInfo.Capture(e); - - edi.Throw(); - } - - public static void Handler(Exception e) - { - Caught = e; - } -} - -public class Example -{ - public static int Main() - { - TT(); - string expected = A.Caught.StackTrace.ToString (); - - for (int i = 0; i < 1000; ++i) { - Thread t = new Thread (delegate () { - TT (); - }); - t.Start (); - t.Join (); - GC.Collect (); - GC.WaitForPendingFinalizers (); - if (A.Caught.StackTrace != expected) { - Console.WriteLine ("FAILED"); - return 1; - } - } - return 0; - } - - static void TT() - { - DynamicMethod multiplyHidden = new DynamicMethod( - "", - typeof(void), new[] { typeof(int) }, typeof(Example)); - - ILGenerator ig = multiplyHidden.GetILGenerator(); - - ig.BeginExceptionBlock(); - - ig.Emit(OpCodes.Call, typeof(A).GetMethod("ThrowMe")); - - ig.BeginCatchBlock(typeof(Exception)); - - ig.Emit(OpCodes.Call, typeof(A).GetMethod("Handler")); - - ig.EndExceptionBlock(); - - ig.Emit(OpCodes.Ret); - - var invoke = (Action) - multiplyHidden.CreateDelegate( - typeof(Action) - - ); - - invoke(1); - } -} diff --git a/mono/tests/gc-descriptors/Makefile.in b/mono/tests/gc-descriptors/Makefile.in index 8a87789650..764fac8d49 100644 --- a/mono/tests/gc-descriptors/Makefile.in +++ b/mono/tests/gc-descriptors/Makefile.in @@ -120,6 +120,8 @@ DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AOT_BUILD_FLAGS = @AOT_BUILD_FLAGS@ +AOT_RUN_FLAGS = @AOT_RUN_FLAGS@ API_VER = @API_VER@ AR = @AR@ AS = @AS@ @@ -128,6 +130,11 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOEHM_DEFINES = @BOEHM_DEFINES@ +BTLS_ARCH = @BTLS_ARCH@ +BTLS_CFLAGS = @BTLS_CFLAGS@ +BTLS_CMAKE_ARGS = @BTLS_CMAKE_ARGS@ +BTLS_PLATFORM = @BTLS_PLATFORM@ +BTLS_ROOT = @BTLS_ROOT@ BUILD_EXEEXT = @BUILD_EXEEXT@ CC = @CC@ CCAS = @CCAS@ @@ -137,6 +144,7 @@ CCDEPMODE = @CCDEPMODE@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMAKE = @CMAKE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ @@ -157,7 +165,6 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_PERF_EVENTS = @ENABLE_PERF_EVENTS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDKX11 = @GDKX11@ @@ -172,10 +179,12 @@ HAVE_MSGFMT = @HAVE_MSGFMT@ HOST_CC = @HOST_CC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MOBILE_STATIC = @INSTALL_MOBILE_STATIC@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTL = @INTL@ +INVARIANT_AOT_OPTIONS = @INVARIANT_AOT_OPTIONS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBC = @LIBC@ @@ -222,6 +231,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ +PLATFORM_AOT_SUFFIX = @PLATFORM_AOT_SUFFIX@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -231,6 +241,7 @@ SHELL = @SHELL@ SQLITE = @SQLITE@ SQLITE3 = @SQLITE3@ STRIP = @STRIP@ +TEST_PROFILE = @TEST_PROFILE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VTUNE_CFLAGS = @VTUNE_CFLAGS@ diff --git a/mono/tests/gc-graystack-stress.cs b/mono/tests/gc-graystack-stress.cs index 7d711d9a25..79743cd249 100644 --- a/mono/tests/gc-graystack-stress.cs +++ b/mono/tests/gc-graystack-stress.cs @@ -33,7 +33,11 @@ class Program { if (args.Length > 0) width = Math.Max (width, Int32.Parse (args [0])); - int depth = 10000; + // Windows x64 only has 1 MB of stack per thread which is less than other x86 64-bit OSes. + // Using 10000 for depth will cause a stack overflow on Windows x64. 5000 will fit. + int platform = (int) Environment.OSVersion.Platform; + bool isWin64 = !(platform == 4 || platform == 128) && Environment.Is64BitProcess; + int depth = isWin64 ? 5000 : 10000; if (args.Length > 1) depth = Math.Max (depth, Int32.Parse (args [1])); diff --git a/mono/tests/generic-marshalbyref.2.cs b/mono/tests/generic-marshalbyref.2.cs deleted file mode 100644 index cba58400b0..0000000000 --- a/mono/tests/generic-marshalbyref.2.cs +++ /dev/null @@ -1,81 +0,0 @@ -using System; - -static class Program -{ - static int Main() - { - DocumentForm browseForm = new DocumentForm (); - if (browseForm.DoInit () != 248) - return 1; - - var domain = AppDomain.CreateDomain ("foo"); - var engine = Engine.CreateRemote (domain); - - if (engine.GetDomainName () != "foo") - return 2; - - return 0; - } -} - -public abstract class EntityBase -{ -} - -public class GenEntity : EntityBase -{ -} - -class DocumentForm -{ - internal int DoInit() - { - var g = new Grid1>(123); - var g2 = new Grid2>(123); - return g.num + g2.num; - } -} - -public class Grid1 : MarshalByRefObject -{ - public int num; - - public Grid1 (int i) - { - num = i + 1; - } -} - -public class Grid2 : MarshalByRefObject where TEntity : EntityBase, new() -{ - public int num; - - public Grid2 (int i) - { - num = i + 1; - } -} - -public class Engine : MarshalByRefObject -{ - public Engine () - { - } - - public string GetDomainName () - { - return AppDomain.CurrentDomain.FriendlyName; - } - - public string GetDomainName () - { - return AppDomain.CurrentDomain.FriendlyName; - } - - public static Engine CreateRemote (AppDomain domain) - { - return (Engine) domain.CreateInstanceAndUnwrap ( - typeof (Engine).Assembly.FullName, - typeof (Engine).FullName); - } -} diff --git a/mono/tests/generic-type-builder.2.cs b/mono/tests/generic-type-builder.2.cs deleted file mode 100644 index fc4df0dfae..0000000000 --- a/mono/tests/generic-type-builder.2.cs +++ /dev/null @@ -1,90 +0,0 @@ -/* This test case is taken verbatim from the corlib test suite. The - * reason we need it here, too, is that the corlib tests don't run - * with generic code sharing enabled for all code. Once that is - * enabled by default in Mono, this test should be removed from the - * runtime test suite. - */ - -using System; -using System.Threading; -using System.Reflection; -using System.Reflection.Emit; -using System.IO; - -public class main { - private static AssemblyBuilder assembly; - - private static ModuleBuilder module; - - static string ASSEMBLY_NAME = "MonoTests.System.Reflection.Emit.TypeBuilderTest"; - - protected static void SetUp () - { - AssemblyName assemblyName = new AssemblyName (); - assemblyName.Name = ASSEMBLY_NAME; - - assembly = - Thread.GetDomain ().DefineDynamicAssembly ( - assemblyName, AssemblyBuilderAccess.RunAndSave, Path.GetTempPath ()); - - module = assembly.DefineDynamicModule ("module1"); - } - - public static int GetField () - { - TypeBuilder tb = module.DefineType ("bla", TypeAttributes.Public); - GenericTypeParameterBuilder [] typeParams = tb.DefineGenericParameters ("T"); - - ConstructorBuilder cb = tb.DefineDefaultConstructor (MethodAttributes.Public); - - FieldBuilder fb1 = tb.DefineField ("field1", typeParams [0], FieldAttributes.Public); - - Type t = tb.MakeGenericType (typeof (int)); - - // Chect that calling MakeArrayType () does not initialize the class - // (bug #351172) - t.MakeArrayType (); - - // Check that the instantiation of a type builder contains live data - TypeBuilder.GetField (t, fb1); - FieldBuilder fb2 = tb.DefineField ("field2", typeParams [0], FieldAttributes.Public); - FieldInfo fi2 = TypeBuilder.GetField (t, fb1); - - MethodBuilder mb = tb.DefineMethod ("get_int", MethodAttributes.Public|MethodAttributes.Static, typeof (int), Type.EmptyTypes); - ILGenerator ilgen = mb.GetILGenerator (); - ilgen.Emit (OpCodes.Newobj, TypeBuilder.GetConstructor (t, cb)); - ilgen.Emit (OpCodes.Dup); - ilgen.Emit (OpCodes.Ldc_I4, 42); - ilgen.Emit (OpCodes.Stfld, fi2); - ilgen.Emit (OpCodes.Ldfld, fi2); - ilgen.Emit (OpCodes.Ret); - - // Check GetField on a type instantiated with type parameters - Type t3 = tb.MakeGenericType (typeParams [0]); - FieldBuilder fb3 = tb.DefineField ("field3", typeParams [0], FieldAttributes.Public); - FieldInfo fi3 = TypeBuilder.GetField (t3, fb3); - - MethodBuilder mb3 = tb.DefineMethod ("get_T", MethodAttributes.Public|MethodAttributes.Static, typeParams [0], Type.EmptyTypes); - ILGenerator ilgen3 = mb3.GetILGenerator (); - ilgen3.Emit (OpCodes.Newobj, TypeBuilder.GetConstructor (t3, cb)); - ilgen3.Emit (OpCodes.Ldfld, fi3); - ilgen3.Emit (OpCodes.Ret); - - Type created = tb.CreateType (); - - Type inst = created.MakeGenericType (typeof (object)); - - if ((int)(inst.GetMethod ("get_int").Invoke (null, null)) != 42) - return 1; - - if (inst.GetMethod ("get_T").Invoke (null, null) != null) - return 1; - - return 0; - } - - public static int Main () { - SetUp (); - return GetField (); - } -} diff --git a/mono/tests/generic-unloading.2.cs b/mono/tests/generic-unloading.2.cs deleted file mode 100644 index a965b5d379..0000000000 --- a/mono/tests/generic-unloading.2.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System; - -public class Gen {} - -public class main { - static object GenericFunc () { - return new Gen (); - } - - static void DoGenericStuff () { - Console.WriteLine ("doing generic stuff"); - GenericFunc (); - } - - static void DoOtherGenericStuff () { - Console.WriteLine ("doing other generic stuff"); - GenericFunc (); - } - - public static void Main () - { - // Create an Application Domain: - System.AppDomain newDomain = System.AppDomain.CreateDomain("NewApplicationDomain"); - - // Load and execute an assembly: - newDomain.ExecuteAssembly(@"generic-unloading-sub.2.exe"); - - DoGenericStuff (); - - // Unload the application domain: - System.AppDomain.Unload(newDomain); - - DoOtherGenericStuff (); - } -} diff --git a/mono/tests/generic-xdomain.2.cs b/mono/tests/generic-xdomain.2.cs deleted file mode 100644 index 7a08380515..0000000000 --- a/mono/tests/generic-xdomain.2.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System; -using System.ComponentModel; -using System.Runtime.Remoting; - -namespace Test { - public class Test { - static void Main () - { - AppDomain domain = AppDomain.CreateDomain ("new-domain"); - domain.DoCallBack (Run); - Type stType = typeof (Something); - Other st = (Other) domain.CreateInstanceAndUnwrap (stType.Assembly.FullName, stType.FullName); - Console.WriteLine ("in main int: {0}", st.getInt ()); - Console.WriteLine ("in main types: {0}", st.getTypeNames ()); - } - - public static void Run () - { - DoRun(new Something ()); - } - - public static void DoRun (Other some) - { - Console.WriteLine ("domain: {0}", AppDomain.CurrentDomain.FriendlyName); - Console.WriteLine ("This is null: {0}", some.Mappings == null); - Console.WriteLine ("int: {0}", some.getInt ()); - } - } - - public class Other : MarshalByRefObject { - public T2 Mappings { - get { return default(T2); } - } - - public virtual int getInt () { - return 123; - } - - public virtual string getTypeNames () { - return "error"; - } - } - - public class Something : Other { - public override int getInt () { - return 456; - } - - public override string getTypeNames () { - Console.WriteLine ("getTypeNames in {0}", AppDomain.CurrentDomain.FriendlyName); - return typeof(T1).ToString () + " " + typeof(T2).ToString () + " " + typeof (T3).ToString (); - } - } -} diff --git a/mono/tests/generic_type_definition.2.cs b/mono/tests/generic_type_definition.2.cs deleted file mode 100644 index afd6792178..0000000000 --- a/mono/tests/generic_type_definition.2.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System; -using System.Threading; -using System.Reflection; -using System.Reflection.Emit; - -namespace TestApp -{ - public class A { - public T fld; - } - - class Program - { - static AssemblyBuilder assembly; - static ModuleBuilder module; - static string ASSEMBLY_NAME = "MonoTests.System.Reflection.Emit.TypeBuilderTest"; - - static void SetUp () - { - AssemblyName assemblyName = new AssemblyName (); - assemblyName.Name = ASSEMBLY_NAME; - - assembly = - Thread.GetDomain ().DefineDynamicAssembly ( - assemblyName, AssemblyBuilderAccess.RunAndSave, "."); - - module = assembly.DefineDynamicModule ("module1", "Module1.dll"); - } - - static int Main() - { - Type gtd = typeof (A<>); - Type oi = gtd.MakeGenericType (gtd.GetGenericArguments ()); - - if (oi != gtd) { - Console.WriteLine ("fully open instantiation of static type not the same of the generic type definition"); - return 1; - } - - SetUp (); - TypeBuilder tb = module.DefineType ("Nullable`1", TypeAttributes.Public); - Type[] args = tb.DefineGenericParameters ("T"); - Type type = tb.MakeGenericType (args); - - if (type == tb) { - Console.WriteLine ("fully open instantiation of TypeBuilder is the same of the TypeBuilder"); - return 2; - } - - Type res = tb.CreateType (); - Type oires = res.MakeGenericType (res.GetGenericArguments ()); - - if (res != oires) { - Console.WriteLine ("fully open instantiation not the same of the generic type definition for the TypeBuilder created type"); - return 3; - } - - try { - oires.GetConstructors (); - } catch (Exception e) { - Console.WriteLine ("fully open instantiation of the TypeBuilder created type must have GetConstructors working {0}", e); - return 5; - } - - return 0; - } - } -} diff --git a/mono/tests/libtest.c.REMOVED.git-id b/mono/tests/libtest.c.REMOVED.git-id index b22755a4e0..3a78e29470 100644 --- a/mono/tests/libtest.c.REMOVED.git-id +++ b/mono/tests/libtest.c.REMOVED.git-id @@ -1 +1 @@ -650e7716e583d8af4318a59a900c7ad8b742780c \ No newline at end of file +d2a09a6d068a6290ca4045289e175b872061f7f8 \ No newline at end of file diff --git a/mono/tests/loader.cs b/mono/tests/loader.cs deleted file mode 100644 index caaec151ec..0000000000 --- a/mono/tests/loader.cs +++ /dev/null @@ -1,46 +0,0 @@ -// -// loader.cs: -// -// Tests for assembly loading -// - -using System; -using System.Reflection; -using System.Reflection.Emit; - -public class Tests { - - public static int Main (string[] args) - { - return TestDriver.RunTests (typeof (Tests), args); - } - - public static int test_0_load_partial_name () - { - if (Assembly.LoadWithPartialName ("mscorlib") == null) - return 1; - else - return 0; - } - - public static int test_0_load_dynamic () - { - // Check that dynamic assemblies are not loaded by Assembly.Load - AssemblyName an = new AssemblyName(); - an.Name = "NOT.EXISTS"; - - AssemblyBuilder ab = - AppDomain.CurrentDomain.DefineDynamicAssembly(an, - AssemblyBuilderAccess.RunAndSave); - - ModuleBuilder mb = ab.DefineDynamicModule("NOT.EXISTS"); - - Assembly b = Assembly.LoadWithPartialName ("NOT.EXISTS"); - if (b == null) - return 0; - else - return 1; - } -} - - diff --git a/mono/tests/marshal-valuetypes.cs b/mono/tests/marshal-valuetypes.cs deleted file mode 100644 index 7d4aa3e7de..0000000000 --- a/mono/tests/marshal-valuetypes.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; - -public class Test: MarshalByRefObject -{ - public DateTime Stamp = new DateTime (1968, 1, 2); - public double perc = 5.4; - - static int Main () - { - AppDomain d = AppDomain.CreateDomain ("foo"); - Test t = (Test) d.CreateInstanceAndUnwrap (typeof (Test).Assembly.FullName, typeof (Test).FullName); - if (t.Stamp != new DateTime (1968, 1, 2)) - return 1; - t.perc = 7.2; - if (t.perc != 7.2) - return 2; - return 0; - } -} diff --git a/mono/tests/marshal.cs b/mono/tests/marshal.cs index aadf7adf74..1213f8c5cb 100644 --- a/mono/tests/marshal.cs +++ b/mono/tests/marshal.cs @@ -8,12 +8,18 @@ using System.Runtime.InteropServices; public class Tests { + [AttributeUsage (AttributeTargets.Method)] + sealed class MonoPInvokeCallbackAttribute : Attribute { + public MonoPInvokeCallbackAttribute (Type t) {} + } + public static int Main (string[] args) { return TestDriver.RunTests (typeof (Tests), args); } public delegate int SimpleDelegate (int a); + [MonoPInvokeCallback (typeof (SimpleDelegate))] public static int delegate_test (int a) { return a + 1; diff --git a/mono/tests/marshal9.cs b/mono/tests/marshal9.cs index 7a22bbf404..f190594359 100644 --- a/mono/tests/marshal9.cs +++ b/mono/tests/marshal9.cs @@ -5,6 +5,11 @@ using System; using System.Runtime.InteropServices; +[AttributeUsage (AttributeTargets.Method)] +sealed class MonoPInvokeCallbackAttribute : Attribute { + public MonoPInvokeCallbackAttribute (Type t) {} +} + public class Marshal1 : ICustomMarshaler { int param; @@ -232,10 +237,12 @@ public class Tests [DllImport ("libtest")] private static extern int mono_test_marshal_pass_return_custom_null_in_delegate (pass_return_int_delegate del); + [MonoPInvokeCallback (typeof (pass_return_int_delegate))] private static object pass_return_int (object i) { return (int)i; } + [MonoPInvokeCallback (typeof (pass_return_int_delegate))] private static object pass_return_null (object i) { return (i == null) ? null : new Object (); } @@ -431,7 +438,8 @@ public class Tests return 0; } - + + [MonoPInvokeCallback (typeof (custom_out_param_delegate))] private static void custom_out_param (out object i) { i = new object(); diff --git a/mono/tests/marshalbool.cs b/mono/tests/marshalbool.cs index 263dd16a13..67cf196363 100644 --- a/mono/tests/marshalbool.cs +++ b/mono/tests/marshalbool.cs @@ -3,6 +3,11 @@ using System.Runtime.InteropServices; public class marshalbool { + [AttributeUsage (AttributeTargets.Method)] + sealed class MonoPInvokeCallbackAttribute : Attribute { + public MonoPInvokeCallbackAttribute (Type t) {} + } + [DllImport ("libtest")] static extern int mono_test_marshal_bool_in (int arg, uint expected, bool bDefaultMarsh, @@ -596,7 +601,7 @@ public class marshalbool public static int test_0_Default_In_Managed () { - MarshalBoolInDelegate fcn = new MarshalBoolInDelegate (new marshalbool ().MarshalBoolInHelper); + MarshalBoolInDelegate fcn = new MarshalBoolInDelegate (MarshalBoolInHelper); int ret; ret = mono_test_managed_marshal_bool_in (1, 0, 0, fcn); @@ -613,7 +618,7 @@ public class marshalbool public static int test_0_Bool_In_Managed () { - MarshalBoolInDelegate fcn = new MarshalBoolInDelegate (new marshalbool ().MarshalBoolInHelper); + MarshalBoolInDelegate fcn = new MarshalBoolInDelegate (MarshalBoolInHelper); int ret; ret = mono_test_managed_marshal_bool_in (2, 0, 0, fcn); @@ -630,7 +635,7 @@ public class marshalbool public static int test_0_I1_In_Managed () { - MarshalBoolInDelegate fcn = new MarshalBoolInDelegate (new marshalbool ().MarshalBoolInHelper); + MarshalBoolInDelegate fcn = new MarshalBoolInDelegate (MarshalBoolInHelper); int ret; ret = mono_test_managed_marshal_bool_in (3, 0, 0, fcn); @@ -647,7 +652,7 @@ public class marshalbool public static int test_0_U1_In_Managed () { - MarshalBoolInDelegate fcn = new MarshalBoolInDelegate (new marshalbool ().MarshalBoolInHelper); + MarshalBoolInDelegate fcn = new MarshalBoolInDelegate (MarshalBoolInHelper); int ret; ret = mono_test_managed_marshal_bool_in (4, 0, 0, fcn); @@ -664,7 +669,7 @@ public class marshalbool public static int test_0_VariantBool_In_Managed () { - MarshalBoolInDelegate fcn = new MarshalBoolInDelegate (new marshalbool ().MarshalBoolInHelper); + MarshalBoolInDelegate fcn = new MarshalBoolInDelegate (MarshalBoolInHelper); int ret; ret = mono_test_managed_marshal_bool_in (5, 0, 0, fcn); @@ -681,7 +686,7 @@ public class marshalbool public static int test_0_Default_Out_Managed () { - MarshalBoolOutDelegate fcn = new MarshalBoolOutDelegate (new marshalbool ().MarshalBoolOutHelper); + MarshalBoolOutDelegate fcn = new MarshalBoolOutDelegate (MarshalBoolOutHelper); int ret; ret = mono_test_managed_marshal_bool_out (1, 0, 0, fcn); @@ -698,7 +703,7 @@ public class marshalbool public static int test_0_Bool_Out_Managed () { - MarshalBoolOutDelegate fcn = new MarshalBoolOutDelegate (new marshalbool ().MarshalBoolOutHelper); + MarshalBoolOutDelegate fcn = new MarshalBoolOutDelegate (MarshalBoolOutHelper); int ret; ret = mono_test_managed_marshal_bool_out (2, 0, 0, fcn); @@ -715,7 +720,7 @@ public class marshalbool public static int test_0_I1_Out_Managed () { - MarshalBoolOutDelegate fcn = new MarshalBoolOutDelegate (new marshalbool ().MarshalBoolOutHelper); + MarshalBoolOutDelegate fcn = new MarshalBoolOutDelegate (MarshalBoolOutHelper); int ret; ret = mono_test_managed_marshal_bool_out (3, 0, 0, fcn); @@ -732,7 +737,7 @@ public class marshalbool public static int test_0_U1_Out_Managed () { - MarshalBoolOutDelegate fcn = new MarshalBoolOutDelegate (new marshalbool ().MarshalBoolOutHelper); + MarshalBoolOutDelegate fcn = new MarshalBoolOutDelegate (MarshalBoolOutHelper); int ret; ret = mono_test_managed_marshal_bool_out (4, 0, 0, fcn); @@ -749,7 +754,7 @@ public class marshalbool public static int test_0_VariantBool_Out_Managed () { - MarshalBoolOutDelegate fcn = new MarshalBoolOutDelegate (new marshalbool ().MarshalBoolOutHelper); + MarshalBoolOutDelegate fcn = new MarshalBoolOutDelegate (MarshalBoolOutHelper); int ret; ret = mono_test_managed_marshal_bool_out (5, 0, 0, fcn); @@ -766,7 +771,7 @@ public class marshalbool public static int test_0_Default_Ref_Managed () { - MarshalBoolRefDelegate fcn = new MarshalBoolRefDelegate (new marshalbool ().MarshalBoolRefHelper); + MarshalBoolRefDelegate fcn = new MarshalBoolRefDelegate (MarshalBoolRefHelper); int ret; ret = mono_test_managed_marshal_bool_ref (1, 0, 0, 0, 0, fcn); @@ -795,7 +800,7 @@ public class marshalbool public static int test_0_Bool_Ref_Managed () { - MarshalBoolRefDelegate fcn = new MarshalBoolRefDelegate (new marshalbool ().MarshalBoolRefHelper); + MarshalBoolRefDelegate fcn = new MarshalBoolRefDelegate (MarshalBoolRefHelper); int ret; ret = mono_test_managed_marshal_bool_ref (2, 0, 0, 0, 0, fcn); @@ -824,7 +829,7 @@ public class marshalbool public static int test_0_I1_Ref_Managed () { - MarshalBoolRefDelegate fcn = new MarshalBoolRefDelegate (new marshalbool ().MarshalBoolRefHelper); + MarshalBoolRefDelegate fcn = new MarshalBoolRefDelegate (MarshalBoolRefHelper); int ret; ret = mono_test_managed_marshal_bool_ref (3, 0, 0, 0, 0, fcn); @@ -853,7 +858,7 @@ public class marshalbool public static int test_0_U1_Ref_Managed () { - MarshalBoolRefDelegate fcn = new MarshalBoolRefDelegate (new marshalbool ().MarshalBoolRefHelper); + MarshalBoolRefDelegate fcn = new MarshalBoolRefDelegate (MarshalBoolRefHelper); int ret; ret = mono_test_managed_marshal_bool_ref (4, 0, 0, 0, 0, fcn); @@ -882,7 +887,7 @@ public class marshalbool public static int test_0_VariantBool_Ref_Managed () { - MarshalBoolRefDelegate fcn = new MarshalBoolRefDelegate (new marshalbool ().MarshalBoolRefHelper); + MarshalBoolRefDelegate fcn = new MarshalBoolRefDelegate (MarshalBoolRefHelper); int ret; ret = mono_test_managed_marshal_bool_ref (5, 0, 0, 0, 0, fcn); @@ -911,8 +916,9 @@ public class marshalbool /////////////////////////////////////////////////////////////////// - unsafe int MarshalBoolInHelper (int arg, uint expected, bool bDefaultMarsh, bool bBoolCustMarsh, bool bI1CustMarsh, - bool bU1CustMarsh, bool bVBCustMarsh) + [MonoPInvokeCallback (typeof (MarshalBoolInDelegate))] + unsafe static int MarshalBoolInHelper (int arg, uint expected, bool bDefaultMarsh, bool bBoolCustMarsh, bool bI1CustMarsh, + bool bU1CustMarsh, bool bVBCustMarsh) { bool* ptestVal; switch (arg) { @@ -947,8 +953,9 @@ public class marshalbool return 0; } - unsafe int MarshalBoolOutHelper (int arg, uint testVal, out bool bDefaultMarsh, out bool bBoolCustMarsh, - out bool bI1CustMarsh, out bool bU1CustMarsh, out bool bVBCustMarsh) + [MonoPInvokeCallback (typeof (MarshalBoolOutDelegate))] + unsafe static int MarshalBoolOutHelper (int arg, uint testVal, out bool bDefaultMarsh, out bool bBoolCustMarsh, + out bool bI1CustMarsh, out bool bU1CustMarsh, out bool bVBCustMarsh) { bDefaultMarsh = bBoolCustMarsh = bI1CustMarsh = bU1CustMarsh = bVBCustMarsh = false; switch (arg) { @@ -988,8 +995,9 @@ public class marshalbool return 0; } - unsafe int MarshalBoolRefHelper (int arg, uint expected, uint testVal, ref bool bDefaultMarsh, ref bool bBoolCustMarsh, - ref bool bI1CustMarsh, ref bool bU1CustMarsh, ref bool bVBCustMarsh) + [MonoPInvokeCallback (typeof (MarshalBoolRefDelegate))] + unsafe static int MarshalBoolRefHelper (int arg, uint expected, uint testVal, ref bool bDefaultMarsh, ref bool bBoolCustMarsh, + ref bool bI1CustMarsh, ref bool bU1CustMarsh, ref bool bVBCustMarsh) { switch (arg) { case 1: diff --git a/mono/tests/monitor.cs b/mono/tests/monitor.cs deleted file mode 100644 index 7b96860bbb..0000000000 --- a/mono/tests/monitor.cs +++ /dev/null @@ -1,77 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Runtime.InteropServices; -using System.Threading; - -public class Tests { - static void Main () - { - TestDriver.RunTests (typeof (Tests)); - } - - // Check that try-catch clauses are not enlarged to encompass a Monitor.Enter - public static int test_0_enter_catch_clause () { - try { - Monitor.Enter (null); - try { - Console.WriteLine (); - } catch (Exception ex) { - return 1; - } - } catch (Exception ex) { - return 0; - } - return 1; - } - - const int thread_count = 3; - - // #651546 - public static int test_0_enter_abort_race () { - AppDomain ad = AppDomain.CreateDomain ("foo"); - Thread t = new Thread (StartAppDomain); - t.Start (ad); - Thread.Sleep (thread_count * 100 * 2); - // This will abort the threads created by StartAppDomain - AppDomain.Unload (ad); - return 0; - } - - static void StartAppDomain (object dummy) - { - ((AppDomain) dummy).DoCallBack (Main2); - } - - static void Main2 () - { - Thread[] t = new Thread [thread_count]; - for (int i = 0; i < t.Length; i++) { - t[i] = new Thread (LockMe); - t[i].Start (i); - Thread.Sleep (100); // this is just so that gdb's [New Thread ...] message are properly coupled with our "Thread # entered" messages - } - Thread.Sleep ((int) (thread_count * 100 * 1.5)); - } - - static object the_lock = new object (); - - static void LockMe (object thread_id) - { - bool unlocked = false; - try { - Monitor.Enter (the_lock); - try { - Thread.Sleep (thread_count * 1000); - } finally { - unlocked = true; - Monitor.Exit (the_lock); - } - - } catch (Exception ex) { - if (!unlocked) { - } - } finally { - } - } -} diff --git a/mono/tests/pinvoke2.cs b/mono/tests/pinvoke2.cs deleted file mode 100644 index 5e0f474ec4..0000000000 --- a/mono/tests/pinvoke2.cs +++ /dev/null @@ -1,1901 +0,0 @@ -// -// Copyright 2011 Xamarin Inc (http://www.xamarin.com). -// Licensed under the MIT license. See LICENSE file in the project root for full license information. -// - -using System; -using System.Text; -using System.Runtime.InteropServices; -using System.Runtime.CompilerServices; -using System.Reflection.Emit; - -public class Tests { - - public int int_field; - - public static int delegate_test (int a) - { - if (a == 2) - return 0; - - return 1; - } - - public int delegate_test_instance (int a) - { - return int_field + a; - } - - [StructLayout (LayoutKind.Sequential)] - public struct SimpleStruct { - public bool a; - public bool b; - public bool c; - public string d; - [MarshalAs(UnmanagedType.LPWStr)] - public string d2; - } - - [StructLayout (LayoutKind.Sequential)] - public struct SimpleStructGen { - public bool a; - public bool b; - public bool c; - public string d; - [MarshalAs(UnmanagedType.LPWStr)] - public string d2; - } - - [StructLayout (LayoutKind.Sequential)] - public struct SimpleStruct2 { - public bool a; - public bool b; - public bool c; - public string d; - public byte e; - public double f; - public byte g; - public long h; - } - - [StructLayout (LayoutKind.Sequential, Size=0)] - public struct EmptyStruct { - } - - [StructLayout (LayoutKind.Sequential, Size=1)] - public struct EmptyStructCpp { - } - - [StructLayout (LayoutKind.Sequential)] - public struct DelegateStruct { - public int a; - public SimpleDelegate del; - [MarshalAs(UnmanagedType.FunctionPtr)] - public SimpleDelegate del2; - [MarshalAs(UnmanagedType.FunctionPtr)] - public SimpleDelegate del3; - } - - [StructLayout (LayoutKind.Sequential)] - public struct SingleDoubleStruct { - public double d; - } - - /* sparcv9 has complex conventions when passing structs with doubles in them - by value, some simple tests for them */ - [StructLayout (LayoutKind.Sequential)] - public struct Point { - public double x; - public double y; - } - - [StructLayout (LayoutKind.Sequential)] - public struct MixedPoint { - public int x; - public double y; - } - - [StructLayout (LayoutKind.Sequential)] - public struct TinyStruct { - public TinyStruct (int i) - { - this.i = i; - } - public int i; - } - - [StructLayout (LayoutKind.Sequential)] - public class SimpleClass { - public bool a; - public bool b; - public bool c; - public string d; - public byte e; - public double f; - public byte g; - public long h; - } - - [StructLayout (LayoutKind.Sequential)] - public class EmptyClass { - } - - [StructLayout (LayoutKind.Sequential)] - public struct LongAlignStruct { - public int a; - public long b; - public long c; - } - - [StructLayout(LayoutKind.Sequential)] - public class BlittableClass - { - public int a = 1; - public int b = 2; - } - - [StructLayout (LayoutKind.Sequential)] - class SimpleObj - { - public string str; - public int i; - } - - [StructLayout(LayoutKind.Sequential)] - struct AsAnyStruct - { - public int i; - public int j; - public int k; - public String s; - - public AsAnyStruct(int i, int j, int k, String s) { - this.i = i; - this.j = j; - this.k = k; - this.s = s; - } - } - - [StructLayout(LayoutKind.Sequential)] - class AsAnyClass - { - public int i; - public int j; - public int k; - public String s; - - public AsAnyClass(int i, int j, int k, String s) { - this.i = i; - this.j = j; - this.k = k; - } - } - - [DllImport ("libnot-found", EntryPoint="not_found")] - public static extern int mono_library_not_found (); - - [DllImport ("libtest", EntryPoint="not_found")] - public static extern int mono_entry_point_not_found (); - - [DllImport ("libtest.dll", EntryPoint="mono_test_marshal_char")] - public static extern int mono_test_marshal_char_2 (char a1); - - [DllImport ("test", EntryPoint="mono_test_marshal_char")] - public static extern int mono_test_marshal_char_3 (char a1); - - [DllImport ("libtest", EntryPoint="mono_test_marshal_char")] - public static extern int mono_test_marshal_char (char a1); - - [DllImport ("libtest", EntryPoint="mono_test_marshal_char_array", CharSet=CharSet.Unicode)] - public static extern int mono_test_marshal_char_array (char[] a1); - - [DllImport ("libtest", EntryPoint="mono_test_marshal_bool_byref")] - public static extern int mono_test_marshal_bool_byref (int a, ref bool b, int c); - - [DllImport ("libtest", EntryPoint="mono_test_marshal_bool_in_as_I1_U1")] - public static extern int mono_test_marshal_bool_in_as_I1 ([MarshalAs (UnmanagedType.I1)] bool bTrue, [MarshalAs (UnmanagedType.I1)] bool bFalse); - - [DllImport ("libtest", EntryPoint="mono_test_marshal_bool_in_as_I1_U1")] - public static extern int mono_test_marshal_bool_in_as_U1 ([MarshalAs (UnmanagedType.U1)] bool bTrue, [MarshalAs (UnmanagedType.U1)] bool bFalse); - - [DllImport ("libtest", EntryPoint="mono_test_marshal_bool_out_as_I1_U1")] - public static extern int mono_test_marshal_bool_out_as_I1 ([MarshalAs (UnmanagedType.I1)] out bool bTrue, [MarshalAs (UnmanagedType.I1)] out bool bFalse); - - [DllImport ("libtest", EntryPoint="mono_test_marshal_bool_out_as_I1_U1")] - public static extern int mono_test_marshal_bool_out_as_U1 ([MarshalAs (UnmanagedType.U1)] out bool bTrue, [MarshalAs (UnmanagedType.U1)] out bool bFalse); - - [DllImport ("libtest", EntryPoint="mono_test_marshal_bool_ref_as_I1_U1")] - public static extern int mono_test_marshal_bool_ref_as_I1 ([MarshalAs (UnmanagedType.I1)] ref bool bTrue, [MarshalAs (UnmanagedType.I1)] ref bool bFalse); - - [DllImport ("libtest", EntryPoint="mono_test_marshal_bool_ref_as_I1_U1")] - public static extern int mono_test_marshal_bool_ref_as_U1 ([MarshalAs (UnmanagedType.U1)] ref bool bTrue, [MarshalAs (UnmanagedType.U1)] ref bool bFalse); - - [DllImport ("libtest", EntryPoint="mono_test_marshal_array")] - public static extern int mono_test_marshal_array (int [] a1); - - [DllImport ("libtest", EntryPoint="mono_test_marshal_empty_string_array")] - public static extern int mono_test_marshal_empty_string_array (string [] a1); - - [DllImport ("libtest", EntryPoint="mono_test_marshal_string_array")] - public static extern int mono_test_marshal_string_array (string [] a1); - - [DllImport ("libtest", EntryPoint="mono_test_marshal_unicode_string_array", CharSet=CharSet.Unicode)] - public static extern int mono_test_marshal_unicode_string_array (string [] a1, [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStr)]string [] a2); - - [DllImport ("libtest", EntryPoint="mono_test_marshal_stringbuilder_array")] - public static extern int mono_test_marshal_stringbuilder_array (StringBuilder [] a1); - - [DllImport ("libtest", EntryPoint="mono_test_marshal_inout_array")] - public static extern int mono_test_marshal_inout_array ([In, Out] int [] a1); - - [DllImport ("libtest", EntryPoint="mono_test_marshal_out_array")] - public static extern int mono_test_marshal_out_array ([Out] [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] int [] a1, int n); - - [DllImport ("libtest", EntryPoint="mono_test_marshal_out_byref_array_out_size_param")] - public static extern int mono_test_marshal_out_byref_array_out_size_param ([Out] [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] out int [] a1, out int n); - - [DllImport ("libtest", EntryPoint="mono_test_marshal_out_lparray_out_size_param")] - public static extern int mono_test_marshal_out_lparray_out_size_param ([Out] [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] int [] a1, out int n); - - [DllImport ("libtest", EntryPoint="mono_test_marshal_inout_nonblittable_array", CharSet = CharSet.Unicode)] - public static extern int mono_test_marshal_inout_nonblittable_array ([In, Out] char [] a1); - - [DllImport ("libtest", EntryPoint="mono_test_marshal_struct")] - public static extern int mono_test_marshal_struct (SimpleStruct ss); - - [DllImport ("libtest", EntryPoint="mono_test_marshal_struct")] - public static extern int mono_test_marshal_struct_gen (SimpleStructGen ss); - - [DllImport ("libtest", EntryPoint="mono_test_marshal_struct2")] - public static extern int mono_test_marshal_struct2 (SimpleStruct2 ss); - - [DllImport ("libtest", EntryPoint="mono_test_marshal_struct2_2")] - public static extern int mono_test_marshal_struct2_2 (int i, int j, int k, SimpleStruct2 ss); - - [DllImport ("libtest", EntryPoint="mono_test_marshal_byref_struct")] - public static extern int mono_test_marshal_byref_struct (ref SimpleStruct ss, bool a, bool b, bool c, String d); - - [DllImport ("libtest", EntryPoint="mono_test_marshal_byref_struct")] - public static extern int mono_test_marshal_byref_struct_in ([In] ref SimpleStruct ss, bool a, bool b, bool c, String d); - - [DllImport ("libtest", EntryPoint="mono_test_marshal_byref_struct")] - public static extern int mono_test_marshal_byref_struct_inout ([In, Out] ref SimpleStruct ss, bool a, bool b, bool c, String d); - - [DllImport ("libtest", EntryPoint="mono_test_marshal_point")] - public static extern int mono_test_marshal_point (Point p); - - [DllImport ("libtest", EntryPoint="mono_test_marshal_mixed_point")] - public static extern int mono_test_marshal_mixed_point (MixedPoint p); - - [DllImport ("libtest", EntryPoint="mono_test_empty_struct")] - public static extern int mono_test_empty_struct (int a, EmptyStruct es, int b); - - [DllImport ("libtest", EntryPoint="mono_test_return_empty_struct")] - public static extern EmptyStruct mono_test_return_empty_struct (int a); - - [DllImport ("libtest", EntryPoint="mono_test_return_empty_struct")] - public static extern EmptyStructCpp mono_test_return_empty_struct_cpp (int a); - - [DllImport ("libtest", EntryPoint="mono_test_marshal_lpstruct")] - public static extern int mono_test_marshal_lpstruct ([In, MarshalAs(UnmanagedType.LPStruct)] SimpleStruct ss); - - [DllImport ("libtest", EntryPoint="mono_test_marshal_lpstruct_blittable")] - public static extern int mono_test_marshal_lpstruct_blittable ([In, MarshalAs(UnmanagedType.LPStruct)] Point p); - - [DllImport ("libtest", EntryPoint="mono_test_marshal_struct_array")] - public static extern int mono_test_marshal_struct_array (SimpleStruct2[] ss); - - [DllImport ("libtest", EntryPoint="mono_test_marshal_long_align_struct_array")] - public static extern int mono_test_marshal_long_align_struct_array (LongAlignStruct[] ss); - - [DllImport ("libtest", EntryPoint="mono_test_marshal_class")] - public static extern SimpleClass mono_test_marshal_class (int i, int j, int k, SimpleClass ss, int l); - - [DllImport ("libtest", EntryPoint="mono_test_marshal_byref_class")] - public static extern int mono_test_marshal_byref_class (ref SimpleClass ss); - - [DllImport ("libtest", EntryPoint="mono_test_marshal_delegate")] - public static extern int mono_test_marshal_delegate (SimpleDelegate d); - - [DllImport ("libtest", EntryPoint="mono_test_marshal_delegate_struct")] - public static extern DelegateStruct mono_test_marshal_delegate_struct (DelegateStruct d); - - [DllImport ("libtest", EntryPoint="mono_test_marshal_return_delegate")] - public static extern SimpleDelegate mono_test_marshal_return_delegate (SimpleDelegate d); - - [DllImport ("libtest", EntryPoint="mono_test_return_vtype")] - public static extern SimpleStruct mono_test_return_vtype (IntPtr i); - - [DllImport ("libtest", EntryPoint="mono_test_marshal_stringbuilder")] - public static extern void mono_test_marshal_stringbuilder (StringBuilder sb, int len); - - [DllImport ("libtest", EntryPoint="mono_test_marshal_stringbuilder_default")] - public static extern void mono_test_marshal_stringbuilder_default (StringBuilder sb, int len); - - [DllImport ("libtest", EntryPoint="mono_test_marshal_stringbuilder_append")] - public static extern void mono_test_marshal_stringbuilder_append (StringBuilder sb, int len); - - [DllImport ("libtest", EntryPoint="mono_test_marshal_stringbuilder_unicode", CharSet=CharSet.Unicode)] - public static extern void mono_test_marshal_stringbuilder_unicode (StringBuilder sb, int len); - - [DllImport ("libtest", EntryPoint="mono_test_marshal_stringbuilder_out")] - public static extern void mono_test_marshal_stringbuilder_out (out StringBuilder sb); - - [DllImport ("libtest", EntryPoint="mono_test_marshal_stringbuilder_ref")] - public static extern int mono_test_marshal_stringbuilder_ref (ref StringBuilder sb); - - [DllImport ("libtest", EntryPoint="mono_test_marshal_stringbuilder_out_unicode", CharSet=CharSet.Unicode)] - public static extern void mono_test_marshal_stringbuilder_out_unicode (out StringBuilder sb); - - [DllImport ("libtest", EntryPoint="mono_test_last_error", SetLastError=true)] - public static extern void mono_test_last_error (int err); - - [DllImport ("libtest", EntryPoint="mono_test_asany")] - public static extern int mono_test_asany ([MarshalAs (UnmanagedType.AsAny)] object o, int what); - - [DllImport ("libtest", EntryPoint="mono_test_asany", CharSet=CharSet.Unicode)] - public static extern int mono_test_asany_unicode ([MarshalAs (UnmanagedType.AsAny)] object o, int what); - - [DllImport("libtest", EntryPoint="mono_test_marshal_asany_in")] - static extern void mono_test_asany_in ([MarshalAs(UnmanagedType.AsAny)][In] object obj); - - [DllImport("libtest", EntryPoint="mono_test_marshal_asany_out")] - static extern void mono_test_asany_out ([MarshalAs(UnmanagedType.AsAny)][Out] object obj); - [DllImport("libtest", EntryPoint="mono_test_marshal_asany_inout")] - static extern void mono_test_asany_inout ([MarshalAs(UnmanagedType.AsAny)][In, Out] object obj); - - [DllImport ("libtest")] - static extern int class_marshal_test0 (SimpleObj obj); - - [DllImport ("libtest")] - static extern void class_marshal_test1 (out SimpleObj obj); - - [DllImport ("libtest")] - static extern int class_marshal_test4 (SimpleObj obj); - - [DllImport ("libtest")] - static extern int string_marshal_test0 (string str); - - [DllImport ("libtest")] - static extern void string_marshal_test1 (out string str); - - [DllImport ("libtest")] - static extern int string_marshal_test2 (ref string str); - - [DllImport ("libtest")] - static extern int string_marshal_test3 (string str); - - public delegate int SimpleDelegate (int a); - - public static int Main (string[] args) { - return TestDriver.RunTests (typeof (Tests), args); - } - - public static int test_0_marshal_char () { - return mono_test_marshal_char ('a'); - } - - public static int test_0_marshal_char_array () { - // a unicode char[] is implicitly marshalled as [Out] - char[] buf = new char [32]; - mono_test_marshal_char_array (buf); - string s = new string (buf); - if (s.StartsWith ("abcdef")) - return 0; - else - return 1; - } - - public static int test_1225_marshal_array () { - int [] a1 = new int [50]; - for (int i = 0; i < 50; i++) - a1 [i] = i; - - return mono_test_marshal_array (a1); - } - - public static int test_1225_marshal_inout_array () { - int [] a1 = new int [50]; - for (int i = 0; i < 50; i++) - a1 [i] = i; - - int res = mono_test_marshal_inout_array (a1); - - for (int i = 0; i < 50; i++) - if (a1 [i] != 50 - i) { - Console.WriteLine ("X: " + i + " " + a1 [i]); - return 2; - } - - return res; - } - - public static int test_0_marshal_out_array () { - int [] a1 = new int [50]; - - int res = mono_test_marshal_out_array (a1, 0); - - for (int i = 0; i < 50; i++) - if (a1 [i] != i) { - Console.WriteLine ("X: " + i + " " + a1 [i]); - return 2; - } - - return 0; - } - - public static int test_0_marshal_out_byref_array_out_size_param () { - int [] a1 = null; - int len; - - int res = mono_test_marshal_out_byref_array_out_size_param (out a1, out len); - if (len != 4) - return 1; - for (int i = 0; i < len; i++) - if (a1 [i] != i) - return 2; - return 0; - } - - public static int test_0_marshal_out_lparray_out_size_param () { - int [] a1 = null; - int len; - - a1 = new int [10]; - int res = mono_test_marshal_out_lparray_out_size_param (a1, out len); - // Check that a1 was not overwritten - a1.GetHashCode (); - if (len != 4) - return 1; - for (int i = 0; i < len; i++) - if (a1 [i] != i) - return 2; - return 0; - } - - public static int test_0_marshal_inout_nonblittable_array () { - char [] a1 = new char [10]; - for (int i = 0; i < 10; i++) - a1 [i] = "Hello, World" [i]; - - int res = mono_test_marshal_inout_nonblittable_array (a1); - - for (int i = 0; i < 10; i++) - if (a1 [i] != 'F') - return 2; - - return res; - } - - public static int test_0_marshal_struct () { - SimpleStruct ss = new SimpleStruct (); - ss.b = true; - ss.d = "TEST"; - - return mono_test_marshal_struct (ss); - } - - public static int test_0_marshal_struct_gen () { - SimpleStructGen ss = new SimpleStructGen (); - ss.b = true; - ss.d = "TEST"; - - return mono_test_marshal_struct_gen (ss); - } - - public static int test_0_marshal_struct2 () { - SimpleStruct2 ss2 = new SimpleStruct2 (); - ss2.b = true; - ss2.d = "TEST"; - ss2.e = 99; - ss2.f = 1.5; - ss2.g = 42; - ss2.h = 123L; - - return mono_test_marshal_struct2 (ss2); - } - - public static int test_0_marshal_struct3 () { - SimpleStruct2 ss2 = new SimpleStruct2 (); - ss2.b = true; - ss2.d = "TEST"; - ss2.e = 99; - ss2.f = 1.5; - ss2.g = 42; - ss2.h = 123L; - - return mono_test_marshal_struct2_2 (10, 11, 12, ss2); - } - - public static int test_0_marshal_empty_struct () { - EmptyStruct es = new EmptyStruct (); - - if (mono_test_empty_struct (1, es, 2) != 0) - return 1; - - mono_test_return_empty_struct (42); - - return 0; - } - - /* FIXME: This doesn't work on all platforms */ - /* - public static int test_0_marshal_empty_struct_cpp () { - EmptyStructCpp es = new EmptyStructCpp (); - - mono_test_return_empty_struct_cpp (42); - - return 0; - } - */ - - public static int test_0_marshal_lpstruct () { - SimpleStruct ss = new SimpleStruct (); - ss.b = true; - ss.d = "TEST"; - - return mono_test_marshal_lpstruct (ss); - } - - public static int test_0_marshal_lpstruct_blittable () { - Point p = new Point (); - p.x = 1.0; - p.y = 2.0; - - return mono_test_marshal_lpstruct_blittable (p); - } - - public static int test_0_marshal_struct_array () { - SimpleStruct2[] ss_arr = new SimpleStruct2 [2]; - - SimpleStruct2 ss2 = new SimpleStruct2 (); - ss2.b = true; - ss2.d = "TEST"; - ss2.e = 99; - ss2.f = 1.5; - ss2.g = 42; - ss2.h = 123L; - - ss_arr [0] = ss2; - - ss2.b = false; - ss2.d = "TEST2"; - ss2.e = 100; - ss2.f = 2.5; - ss2.g = 43; - ss2.h = 124L; - - ss_arr [1] = ss2; - - return mono_test_marshal_struct_array (ss_arr); - } - - public static int test_105_marshal_long_align_struct_array () { - LongAlignStruct[] ss_arr = new LongAlignStruct [2]; - - LongAlignStruct ss = new LongAlignStruct (); - ss.a = 5; - ss.b = 10; - ss.c = 15; - - ss_arr [0] = ss; - - ss.a = 20; - ss.b = 25; - ss.c = 30; - - ss_arr [1] = ss; - - return mono_test_marshal_long_align_struct_array (ss_arr); - } - - /* Test classes as arguments and return values */ - public static int test_0_marshal_class () { - SimpleClass ss = new SimpleClass (); - ss.b = true; - ss.d = "TEST"; - ss.e = 99; - ss.f = 1.5; - ss.g = 42; - ss.h = 123L; - - SimpleClass res = mono_test_marshal_class (10, 11, 12, ss, 14); - if (res == null) - return 1; - if (! (res.a == ss.a && res.b == ss.b && res.c == ss.c && - res.d == ss.d && res.e == ss.e && res.f == ss.f && - res.g == ss.g && res.h == ss.h)) - return 2; - - /* Test null arguments and results */ - res = mono_test_marshal_class (10, 11, 12, null, 14); - if (res != null) - return 3; - - return 0; - } - - public static int test_0_marshal_byref_class () { - SimpleClass ss = new SimpleClass (); - ss.b = true; - ss.d = "TEST"; - ss.e = 99; - ss.f = 1.5; - ss.g = 42; - ss.h = 123L; - - int res = mono_test_marshal_byref_class (ref ss); - if (ss.d != "TEST-RES") - return 1; - - return 0; - } - - public static int test_0_marshal_delegate () { - SimpleDelegate d = new SimpleDelegate (delegate_test); - - return mono_test_marshal_delegate (d); - } - - public static int test_34_marshal_instance_delegate () { - Tests t = new Tests (); - t.int_field = 32; - SimpleDelegate d = new SimpleDelegate (t.delegate_test_instance); - - return mono_test_marshal_delegate (d); - } - - /* Static delegates closed over their first argument */ - public static int closed_delegate (Tests t, int a) { - return t.int_field + a; - } - - public static int test_34_marshal_closed_static_delegate () { - Tests t = new Tests (); - t.int_field = 32; - SimpleDelegate d = (SimpleDelegate)Delegate.CreateDelegate (typeof (SimpleDelegate), t, typeof (Tests).GetMethod ("closed_delegate")); - - return mono_test_marshal_delegate (d); - } - - public static int test_0_marshal_return_delegate () { - SimpleDelegate d = new SimpleDelegate (delegate_test); - - SimpleDelegate d2 = mono_test_marshal_return_delegate (d); - - return d2 (2); - } - - public static int test_0_marshal_delegate_struct () { - DelegateStruct s = new DelegateStruct (); - - s.a = 2; - s.del = new SimpleDelegate (delegate_test); - s.del2 = new SimpleDelegate (delegate_test); - s.del3 = null; - - DelegateStruct res = mono_test_marshal_delegate_struct (s); - - if (res.a != 0) - return 1; - if (res.del (2) != 0) - return 2; - if (res.del2 (2) != 0) - return 3; - if (res.del3 != null) - return 4; - - return 0; - } - - [DllImport ("libtest", EntryPoint="mono_test_marshal_out_delegate")] - public static extern int mono_test_marshal_out_delegate (out SimpleDelegate d); - - public static int test_3_marshal_out_delegate () { - SimpleDelegate d = null; - - mono_test_marshal_out_delegate (out d); - - return d (2); - } - - public static int test_0_marshal_byref_struct () { - SimpleStruct s = new SimpleStruct (); - s.a = true; - s.b = false; - s.c = true; - s.d = "ABC"; - s.d2 = "DEF"; - - int res = mono_test_marshal_byref_struct (ref s, true, false, true, "ABC"); - if (res != 0) - return 1; - if (s.a != false || s.b != true || s.c != false || s.d != "DEF") - return 2; - return 0; - } - - public static int test_0_marshal_byref_struct_in () { - SimpleStruct s = new SimpleStruct (); - s.a = true; - s.b = false; - s.c = true; - s.d = "ABC"; - s.d2 = "DEF"; - - int res = mono_test_marshal_byref_struct_in (ref s, true, false, true, "ABC"); - if (res != 0) - return 1; - if (s.a != true || s.b != false || s.c != true || s.d != "ABC") - return 2; - return 0; - } - - public static int test_0_marshal_byref_struct_inout () { - SimpleStruct s = new SimpleStruct (); - s.a = true; - s.b = false; - s.c = true; - s.d = "ABC"; - s.d2 = "DEF"; - - int res = mono_test_marshal_byref_struct_inout (ref s, true, false, true, "ABC"); - if (res != 0) - return 1; - if (s.a != false || s.b != true || s.c != false || s.d != "DEF") - return 2; - return 0; - } - - public static int test_0_marshal_point () { - Point pt = new Point(); - pt.x = 1.25; - pt.y = 3.5; - - return mono_test_marshal_point(pt); - } - - public static int test_0_marshal_mixed_point () { - MixedPoint mpt = new MixedPoint(); - mpt.x = 5; - mpt.y = 6.75; - - return mono_test_marshal_mixed_point(mpt); - } - - public static int test_0_marshal_bool_byref () { - bool b = true; - if (mono_test_marshal_bool_byref (99, ref b, 100) != 1) - return 1; - b = false; - if (mono_test_marshal_bool_byref (99, ref b, 100) != 0) - return 12; - if (b != true) - return 13; - - return 0; - } - - public static int test_0_marshal_bool_as_I1 () { - - int ret; - bool bTrue, bFalse; - if ((ret = mono_test_marshal_bool_in_as_I1 (true, false)) != 0) - return ret; - - if ((ret = mono_test_marshal_bool_out_as_I1 (out bTrue, out bFalse)) != 0) - return ret; - - if(!bTrue) - return 10; - - if(bFalse) - return 11; - - if ((ret = mono_test_marshal_bool_ref_as_I1 (ref bTrue, ref bFalse)) != 0) - return ret; - - if(bTrue) - return 12; - - if(!bFalse) - return 13; - - return 0; - } - - public static int test_0_marshal_bool_as_U1 () { - - int ret; - bool bTrue, bFalse; - if ((ret = mono_test_marshal_bool_in_as_U1 (true, false)) != 0) - return ret; - - if ((ret = mono_test_marshal_bool_out_as_U1 (out bTrue, out bFalse)) != 0) - return ret; - - if(!bTrue) - return 10; - - if(bFalse) - return 11; - - if ((ret = mono_test_marshal_bool_ref_as_U1 (ref bTrue, ref bFalse)) != 0) - return ret; - - if(bTrue) - return 12; - - if(!bFalse) - return 13; - - return 0; - } - - public static int test_0_return_vtype () { - SimpleStruct ss = mono_test_return_vtype (new IntPtr (5)); - - if (!ss.a && ss.b && !ss.c && ss.d == "TEST" && ss.d2 == "TEST2") - return 0; - - return 1; - } - - public static int test_0_marshal_stringbuilder () { - StringBuilder sb = new StringBuilder(255); - sb.Append ("ABCD"); - mono_test_marshal_stringbuilder (sb, sb.Capacity); - String res = sb.ToString(); - - if (res != "This is my message. Isn't it nice?") - return 1; - - // Test StringBuilder with default capacity (16) - StringBuilder sb2 = new StringBuilder(); - mono_test_marshal_stringbuilder_default (sb2, sb2.Capacity); - if (sb2.ToString () != "This is my messa") - return 3; - - return 0; - } - - public static int test_0_marshal_stringbuilder_append () { - const String in_sentinel = "MONO_"; - const String out_sentinel = "CSHARP_"; - const int iterations = 100; - StringBuilder sb = new StringBuilder(255); - StringBuilder check = new StringBuilder(255); - - for (int i = 0; i < iterations; i++) { - sb.Append (in_sentinel[i % in_sentinel.Length]); - check.Append (out_sentinel[i % out_sentinel.Length]); - - mono_test_marshal_stringbuilder_append (sb, sb.Length); - - String res = sb.ToString(); - String checkRev = check.ToString(); - if (res != checkRev) - return 1; - } - - // Test StringBuilder with default capacity (16) - StringBuilder sb2 = new StringBuilder(); - mono_test_marshal_stringbuilder_default (sb2, sb2.Capacity); - if (sb2.ToString () != "This is my messa") - return 3; - - return 0; - } - - public static int test_0_marshal_stringbuilder_unicode () { - StringBuilder sb = new StringBuilder(255); - mono_test_marshal_stringbuilder_unicode (sb, sb.Capacity); - String res = sb.ToString(); - - if (res != "This is my message. Isn't it nice?") - return 1; - - // Test StringBuilder with default capacity (16) - StringBuilder sb2 = new StringBuilder(); - mono_test_marshal_stringbuilder_unicode (sb2, sb2.Capacity); - if (sb2.ToString () != "This is my messa") - return 2; - - return 0; - } - - public static int test_0_marshal_stringbuilder_out () { - StringBuilder sb; - mono_test_marshal_stringbuilder_out (out sb); - - if (sb.ToString () != "This is my message. Isn't it nice?") - return 1; - return 0; - } - - public static int test_0_marshal_stringbuilder_out_unicode () { - StringBuilder sb; - mono_test_marshal_stringbuilder_out_unicode (out sb); - - if (sb.ToString () != "This is my message. Isn't it nice?") - return 1; - return 0; - } - - public static int test_0_marshal_stringbuilder_ref () { - StringBuilder sb = new StringBuilder (); - sb.Append ("ABC"); - int res = mono_test_marshal_stringbuilder_ref (ref sb); - if (res != 0) - return 1; - - if (sb.ToString () != "This is my message. Isn't it nice?") - return 2; - return 0; - } - - public static int test_0_marshal_empty_string_array () { - return mono_test_marshal_empty_string_array (null); - } - - public static int test_0_marshal_string_array () { - return mono_test_marshal_string_array (new String [] { "ABC", "DEF" }); - } - - public static int test_0_marshal_unicode_string_array () { - return mono_test_marshal_unicode_string_array (new String [] { "ABC", "DEF" }, new String [] { "ABC", "DEF" }); - } - - public static int test_0_marshal_stringbuilder_array () { - StringBuilder sb1 = new StringBuilder ("ABC"); - StringBuilder sb2 = new StringBuilder ("DEF"); - - int res = mono_test_marshal_stringbuilder_array (new StringBuilder [] { sb1, sb2 }); - if (res != 0) - return res; - if (sb1.ToString () != "DEF") - return 5; - if (sb2.ToString () != "ABC") - return 6; - return 0; - } - - public static int test_0_last_error () { - mono_test_last_error (5); - if (Marshal.GetLastWin32Error () == 5) - return 0; - else - return 1; - } - - public static int test_0_entry_point_not_found () { - - try { - mono_entry_point_not_found (); - return 1; - } - catch (EntryPointNotFoundException) { - } - - return 0; - } - - public static int test_0_library_not_found () { - - try { - mono_library_not_found (); - return 1; - } - catch (DllNotFoundException) { - } - - return 0; - } - - /* Check that the runtime trims .dll from the library name */ - public static int test_0_trim_dll_from_name () { - - mono_test_marshal_char_2 ('A'); - - return 0; - } - - /* Check that the runtime adds lib to to the library name */ - public static int test_0_add_lib_to_name () { - - mono_test_marshal_char_3 ('A'); - - return 0; - } - - class C { - public int i; - } - - public static int test_0_asany () { - if (mono_test_asany (5, 1) != 0) - return 1; - - if (mono_test_asany ("ABC", 2) != 0) - return 2; - - SimpleStruct2 ss2 = new SimpleStruct2 (); - ss2.b = true; - ss2.d = "TEST"; - ss2.e = 99; - ss2.f = 1.5; - ss2.g = 42; - ss2.h = 123L; - - if (mono_test_asany (ss2, 3) != 0) - return 3; - - if (mono_test_asany_unicode ("ABC", 4) != 0) - return 4; - - try { - C c = new C (); - c.i = 5; - mono_test_asany (c, 0); - return 5; - } - catch (ArgumentException) { - } - - try { - mono_test_asany (new Object (), 0); - return 6; - } - catch (ArgumentException) { - } - - return 0; - } - - /* AsAny marshalling + [In, Out] */ - - public static int test_0_asany_in () { - // Struct - AsAnyStruct str = new AsAnyStruct(1,2,3, "ABC"); - mono_test_asany_in (str); - - // Formatted Class - AsAnyClass cls = new AsAnyClass(1,2,3, "ABC"); - mono_test_asany_in (cls); - if ((cls.i != 1) || (cls.j != 2) || (cls.k != 3)) - return 1; - - // Boxed Struct - object obj = new AsAnyStruct(1,2,3, "ABC"); - mono_test_asany_in (obj); - str = (AsAnyStruct)obj; - if ((str.i != 1) || (str.j != 2) || (str.k != 3)) - return 2; - - return 0; - } - - public static int test_0_asany_out () { - // Struct - AsAnyStruct str = new AsAnyStruct(1,2,3, "ABC"); - mono_test_asany_out (str); - - // Formatted Class - AsAnyClass cls = new AsAnyClass(1,2,3, "ABC"); - mono_test_asany_out (cls); - if ((cls.i != 10) || (cls.j != 20) || (cls.k != 30)) - return 1; - - // Boxed Struct - object obj = new AsAnyStruct(1,2,3, "ABC"); - mono_test_asany_out (obj); - str = (AsAnyStruct)obj; - if ((str.i != 10) || (str.j != 20) || (str.k != 30)) - return 2; - - return 0; - } - - public static int test_0_asany_inout () { - // Struct - AsAnyStruct str = new AsAnyStruct(1,2,3, "ABC"); - mono_test_asany_inout (str); - - // Formatted Class - AsAnyClass cls = new AsAnyClass(1,2,3, "ABC"); - mono_test_asany_inout (cls); - if ((cls.i != 10) || (cls.j != 20) || (cls.k != 30)) - return 1; - - // Boxed Struct - object obj = new AsAnyStruct(1,2,3, "ABC"); - mono_test_asany_inout (obj); - str = (AsAnyStruct)obj; - if ((str.i != 10) || (str.j != 20) || (str.k != 30)) - return 2; - - return 0; - } - - /* Byref String Array */ - - [DllImport ("libtest", EntryPoint="mono_test_marshal_byref_string_array")] - public static extern int mono_test_marshal_byref_string_array (ref string[] data); - - public static int test_0_byref_string_array () { - - string[] arr = null; - - if (mono_test_marshal_byref_string_array (ref arr) != 0) - return 1; - - arr = new string[] { "Alpha", "Beta", "Gamma" }; - - if (mono_test_marshal_byref_string_array (ref arr) != 1) - return 2; - - /* FIXME: Test returned array and out case */ - - return 0; - } - - /* - * AMD64 small structs-by-value tests. - */ - - /* TEST 1: 16 byte long INTEGER struct */ - - [StructLayout(LayoutKind.Sequential)] - public struct Amd64Struct1 { - public int i; - public int j; - public int k; - public int l; - } - - [DllImport ("libtest", EntryPoint="mono_test_marshal_amd64_pass_return_struct1")] - public static extern Amd64Struct1 mono_test_marshal_amd64_pass_return_struct1 (Amd64Struct1 s); - - [DllImport ("libtest", EntryPoint="mono_test_marshal_amd64_pass_return_struct1_many_args")] - public static extern Amd64Struct1 mono_test_marshal_amd64_pass_return_struct1_many_args (Amd64Struct1 s, int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8); - - public static int test_0_amd64_struct1 () { - Amd64Struct1 s = new Amd64Struct1 (); - s.i = 5; - s.j = -5; - s.k = 0xffffff; - s.l = 0xfffffff; - - Amd64Struct1 s2 = mono_test_marshal_amd64_pass_return_struct1 (s); - - return ((s2.i == 6) && (s2.j == -4) && (s2.k == 0x1000000) && (s2.l == 0x10000000)) ? 0 : 1; - } - - public static int test_0_amd64_struct1_many_args () { - Amd64Struct1 s = new Amd64Struct1 (); - s.i = 5; - s.j = -5; - s.k = 0xffffff; - s.l = 0xfffffff; - - Amd64Struct1 s2 = mono_test_marshal_amd64_pass_return_struct1_many_args (s, 1, 2, 3, 4, 5, 6, 7, 8); - - return ((s2.i == 6) && (s2.j == -4) && (s2.k == 0x1000000) && (s2.l == 0x10000000 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8)) ? 0 : 1; - } - - /* TEST 2: 8 byte long INTEGER struct */ - - [StructLayout(LayoutKind.Sequential)] - public struct Amd64Struct2 { - public int i; - public int j; - } - - [DllImport ("libtest", EntryPoint="mono_test_marshal_amd64_pass_return_struct2")] - public static extern Amd64Struct2 mono_test_marshal_amd64_pass_return_struct2 (Amd64Struct2 s); - - public static int test_0_amd64_struct2 () { - Amd64Struct2 s = new Amd64Struct2 (); - s.i = 5; - s.j = -5; - - Amd64Struct2 s2 = mono_test_marshal_amd64_pass_return_struct2 (s); - - return ((s2.i == 6) && (s2.j == -4)) ? 0 : 1; - } - - /* TEST 3: 4 byte long INTEGER struct */ - - [StructLayout(LayoutKind.Sequential)] - public struct Amd64Struct3 { - public int i; - } - - [DllImport ("libtest", EntryPoint="mono_test_marshal_amd64_pass_return_struct3")] - public static extern Amd64Struct3 mono_test_marshal_amd64_pass_return_struct3 (Amd64Struct3 s); - - public static int test_0_amd64_struct3 () { - Amd64Struct3 s = new Amd64Struct3 (); - s.i = -5; - - Amd64Struct3 s2 = mono_test_marshal_amd64_pass_return_struct3 (s); - - return (s2.i == -4) ? 0 : 1; - } - - /* Test 4: 16 byte long FLOAT struct */ - - [StructLayout(LayoutKind.Sequential)] - public struct Amd64Struct4 { - public double d1, d2; - } - - [DllImport ("libtest", EntryPoint="mono_test_marshal_amd64_pass_return_struct4")] - public static extern Amd64Struct4 mono_test_marshal_amd64_pass_return_struct4 (Amd64Struct4 s); - - public static int test_0_amd64_struct4 () { - Amd64Struct4 s = new Amd64Struct4 (); - s.d1 = 5.0; - s.d2 = -5.0; - - Amd64Struct4 s2 = mono_test_marshal_amd64_pass_return_struct4 (s); - - return (s2.d1 == 6.0 && s2.d2 == -4.0) ? 0 : 1; - } - - /* - * IA64 struct tests - */ - - /* Test 5: Float HFA */ - - [StructLayout(LayoutKind.Sequential)] - public struct TestStruct5 { - public float d1, d2; - } - - [DllImport ("libtest", EntryPoint="mono_test_marshal_ia64_pass_return_struct5")] - public static extern TestStruct5 mono_test_marshal_ia64_pass_return_struct5 (double d1, double d2, TestStruct5 s, int i, double f3, double f4); - - public static int test_0_ia64_struct5 () { - TestStruct5 s = new TestStruct5 (); - s.d1 = 5.0f; - s.d2 = -5.0f; - - TestStruct5 s2 = mono_test_marshal_ia64_pass_return_struct5 (1.0, 2.0, s, 5, 3.0, 4.0); - - return (s2.d1 == 13.0 && s2.d2 == 7.0) ? 0 : 1; - } - - /* Test 6: Double HFA */ - - [StructLayout(LayoutKind.Sequential)] - public struct TestStruct6 { - public double d1, d2; - } - - [DllImport ("libtest", EntryPoint="mono_test_marshal_ia64_pass_return_struct6")] - public static extern TestStruct6 mono_test_marshal_ia64_pass_return_struct6 (double d1, double d2, TestStruct6 s, int i, double f3, double f4); - - public static int test_0_ia64_struct6 () { - TestStruct6 s = new TestStruct6 (); - s.d1 = 6.0; - s.d2 = -6.0; - - TestStruct6 s2 = mono_test_marshal_ia64_pass_return_struct6 (1.0, 2.0, s, 3, 4.0, 5.0); - - return (s2.d1 == 12.0 && s2.d2 == 3.0) ? 0 : 1; - } - - /* Blittable class */ - [DllImport("libtest")] - private static extern BlittableClass TestBlittableClass (BlittableClass vl); - - public static int test_0_marshal_blittable_class () { - BlittableClass v1 = new BlittableClass (); - - /* Since it is blittable, it looks like it is passed as in/out */ - BlittableClass v2 = TestBlittableClass (v1); - - if (v1.a != 2 || v1.b != 3) - return 1; - - if (v2.a != 2 || v2.b != 3) - return 2; - - // Test null - BlittableClass v3 = TestBlittableClass (null); - - if (v3.a != 42 || v3.b != 43) - return 3; - - return 0; - } - - /* - * Generic structures - */ - - [StructLayout(LayoutKind.Sequential)] - public struct Amd64Struct1Gen { - public T i; - public T j; - public T k; - public T l; - } - - [DllImport ("libtest", EntryPoint="mono_test_marshal_amd64_pass_return_struct1")] - public static extern Amd64Struct1Gen mono_test_marshal_amd64_pass_return_struct1_gen (Amd64Struct1Gen s); - - public static int test_0_amd64_struct1_gen () { - Amd64Struct1Gen s = new Amd64Struct1Gen (); - s.i = 5; - s.j = -5; - s.k = 0xffffff; - s.l = 0xfffffff; - - Amd64Struct1Gen s2 = mono_test_marshal_amd64_pass_return_struct1_gen (s); - - return ((s2.i == 6) && (s2.j == -4) && (s2.k == 0x1000000) && (s2.l == 0x10000000)) ? 0 : 1; - } - - /* - * Other tests - */ - - public static int test_0_marshal_byval_class () { - SimpleObj obj0 = new SimpleObj (); - obj0.str = "T1"; - obj0.i = 4; - - if (class_marshal_test0 (obj0) != 0) - return 1; - - return 0; - } - - public static int test_0_marshal_byval_class_null () { - if (class_marshal_test4 (null) != 0) - return 1; - - return 0; - } - - public static int test_0_marshal_out_class () { - SimpleObj obj1; - - class_marshal_test1 (out obj1); - - if (obj1.str != "ABC") - return 1; - - if (obj1.i != 5) - return 2; - - return 0; - } - - public static int test_0_marshal_string () { - return string_marshal_test0 ("TEST0"); - } - - public static int test_0_marshal_out_string () { - string res; - - string_marshal_test1 (out res); - - if (res != "TEST1") - return 1; - - return 0; - } - - public static int test_0_marshal_byref_string () { - string res = "TEST1"; - - int r = string_marshal_test2 (ref res); - if (r != 0) - return 1; - if (res != "TEST2") - return 2; - return 0; - } - - public static int test_0_marshal_null_string () { - return string_marshal_test3 (null); - } - -#if FALSE - [DllImport ("libtest", EntryPoint="mono_test_stdcall_mismatch_1", CallingConvention=CallingConvention.StdCall)] - public static extern int mono_test_stdcall_mismatch_1 (int a, int b, int c); - - /* Test mismatched called conventions, the native function is cdecl */ - public static int test_0_stdcall_mismatch_1 () { - mono_test_stdcall_mismatch_1 (0, 1, 2); - return 0; - } - - [DllImport ("libtest", EntryPoint="mono_test_stdcall_mismatch_2", CallingConvention=CallingConvention.Cdecl)] - public static extern int mono_test_stdcall_mismatch_2 (int a, int b, int c); - - /* Test mismatched called conventions, the native function is stdcall */ - public static int test_0_stdcall_mismatch_2 () { - mono_test_stdcall_mismatch_2 (0, 1, 2); - return 0; - } -#endif - - [DllImport ("libtest", EntryPoint="mono_test_stdcall_name_mangling", CallingConvention=CallingConvention.StdCall)] - public static extern int mono_test_stdcall_name_mangling (int a, int b, int c); - - public static int test_0_stdcall_name_mangling () { - return mono_test_stdcall_name_mangling (0, 1, 2) == 3 ? 0 : 1; - } - - /* Float test */ - - [DllImport ("libtest", EntryPoint="mono_test_marshal_pass_return_float")] - public static extern float mono_test_marshal_pass_return_float (float f); - - public static int test_0_pass_return_float () { - float f = mono_test_marshal_pass_return_float (1.5f); - - return (f == 2.5f) ? 0 : 1; - } - - /* - * Pointers to structures can not be passed - */ - - /* This seems to be allowed by MS in some cases */ - /* - public struct CharInfo { - public char Character; - public short Attributes; - } - - [DllImport ("libtest", EntryPoint="mono_test_marshal_struct")] - public static unsafe extern int mono_test_marshal_ptr_to_struct (CharInfo *ptr); - - public static unsafe int test_0_marshal_ptr_to_struct () { - CharInfo [] buffer = new CharInfo [1]; - fixed (CharInfo *ptr = &buffer [0]) { - try { - mono_test_marshal_ptr_to_struct (ptr); - return 1; - } - catch (MarshalDirectiveException) { - return 0; - } - } - return 1; - } - */ - - /* - * LPWStr marshalling - */ - - [DllImport("libtest", EntryPoint="test_lpwstr_marshal")] - [return: MarshalAs(UnmanagedType.LPWStr)] - private static extern string mono_test_marshal_lpwstr_marshal( - [MarshalAs(UnmanagedType.LPWStr)] string s, - int length ); - - [DllImport("libtest", EntryPoint="test_lpwstr_marshal", CharSet=CharSet.Unicode)] - private static extern string mono_test_marshal_lpwstr_marshal2( - string s, - int length ); - - [DllImport("libtest", EntryPoint="test_lpwstr_marshal_out")] - private static extern void mono_test_marshal_lpwstr_out_marshal( - [MarshalAs(UnmanagedType.LPWStr)] out string s); - - [DllImport("libtest", EntryPoint="test_lpwstr_marshal_out", CharSet=CharSet.Unicode)] - private static extern void mono_test_marshal_lpwstr_out_marshal2( - out string s); - - public static int test_0_pass_return_lwpstr () { - string s; - - mono_test_marshal_lpwstr_out_marshal (out s); - - if (s != "ABC") - return 1; - - s = null; - mono_test_marshal_lpwstr_out_marshal2 (out s); - - if (s != "ABC") - return 2; - - return 0; - } - - public static int test_0_out_lwpstr () { - string s = "ABC"; - - string res = mono_test_marshal_lpwstr_marshal (s, s.Length); - - if (res != "ABC") - return 1; - - string res2 = mono_test_marshal_lpwstr_marshal2 (s, s.Length); - - if (res2 != "ABC") - return 2; - - return 0; - } - - /* - * Byref bool marshalling - */ - - [DllImport("libtest")] - extern static int marshal_test_ref_bool - ( - int i, - [MarshalAs(UnmanagedType.I1)] ref bool b1, - [MarshalAs(UnmanagedType.VariantBool)] ref bool b2, - ref bool b3 - ); - - public static int test_0_pass_byref_bool () { - for (int i = 0; i < 8; i++) - { - bool b1 = (i & 4) != 0; - bool b2 = (i & 2) != 0; - bool b3 = (i & 1) != 0; - bool orig_b1 = b1, orig_b2 = b2, orig_b3 = b3; - if (marshal_test_ref_bool(i, ref b1, ref b2, ref b3) != 0) - return 4 * i + 1; - if (b1 != !orig_b1) - return 4 * i + 2; - if (b2 != !orig_b2) - return 4 * i + 3; - if (b3 != !orig_b3) - return 4 * i + 4; - } - - return 0; - } - - /* - * Bool struct field marshalling - */ - - struct BoolStruct - { - public int i; - [MarshalAs(UnmanagedType.I1)] public bool b1; - [MarshalAs(UnmanagedType.VariantBool)] public bool b2; - public bool b3; - } - - [DllImport("libtest")] - extern static int marshal_test_bool_struct(ref BoolStruct s); - - public static int test_0_pass_bool_in_struct () { - for (int i = 0; i < 8; i++) - { - BoolStruct s = new BoolStruct(); - s.i = i; - s.b1 = (i & 4) != 0; - s.b2 = (i & 2) != 0; - s.b3 = (i & 1) != 0; - BoolStruct orig = s; - if (marshal_test_bool_struct(ref s) != 0) - return 4 * i + 33; - if (s.b1 != !orig.b1) - return 4 * i + 34; - if (s.b2 != !orig.b2) - return 4 * i + 35; - if (s.b3 != !orig.b3) - return 4 * i + 36; - } - - return 0; - } - - /* - * Alignment of structs containing longs - */ - - struct LongStruct2 { - public long l; - } - - struct LongStruct { - public int i; - public LongStruct2 l; - } - - [DllImport("libtest")] - extern static int mono_test_marshal_long_struct (ref LongStruct s); - - public static int test_47_pass_long_struct () { - LongStruct s = new LongStruct (); - s.i = 5; - s.l = new LongStruct2 (); - s.l.l = 42; - - return mono_test_marshal_long_struct (ref s); - } - - /* - * Invoking pinvoke methods through delegates - */ - - delegate int MyDelegate (string name); - - [DllImport ("libtest", EntryPoint="mono_test_puts_static")] - public static extern int puts_static (string name); - - public static int test_0_invoke_pinvoke_through_delegate () { - puts_static ("A simple Test for PInvoke 1"); - - MyDelegate d = new MyDelegate (puts_static); - d ("A simple Test for PInvoke 2"); - - object [] args = {"A simple Test for PInvoke 3"}; - d.DynamicInvoke (args); - - return 0; - } - - /* - * Missing virtual pinvoke methods - */ - - public class T { - - public virtual object MyClone () - { - return null; - } - } - - public class T2 : T { - [MethodImplAttribute(MethodImplOptions.InternalCall)] - public override extern object MyClone (); - } - - public static int test_0_missing_virtual_pinvoke_method () { - T2 t = new T2 (); - - try { - t.MyClone (); - } catch (Exception ex) { - return 0; - } - - return 1; - } - - /* - * Marshalling of type 'object' - */ - - [DllImport ("libtest", EntryPoint="mono_test_marshal_class")] - public static extern SimpleClass mono_test_marshal_object (int i, int j, int k, object ss, int l); - - public static int test_0_marshal_object () { - try { - mono_test_marshal_object (0, 0, 0, null, 0); - return 1; - } catch (Exception) { - return 0; - } - } - - /* - * Marshalling of DateTime to OLE DATE (double) - */ - [DllImport ("libtest", EntryPoint="mono_test_marshal_date_time")] - public static extern double mono_test_marshal_date_time (DateTime d, out DateTime d2); - - public static int test_0_marshal_date_time () { - DateTime d = new DateTime (2009, 12, 6); - DateTime d2; - double d3 = mono_test_marshal_date_time (d, out d2); - if (d3 != 40153.0) - return 1; - if (d2 != d) - return 2; - return 0; - } - - /* - * Calling pinvoke functions dynamically using calli - */ - - [DllImport("libtest")] - private static extern IntPtr mono_test_marshal_lookup_symbol (string fileName); - - delegate void CalliDel (IntPtr a, int[] f); - - public static int test_0_calli_dynamic () { - /* we need the cdecl version because the icall convention demands it under Windows */ - IntPtr func = mono_test_marshal_lookup_symbol ("mono_test_marshal_inout_array_cdecl"); - - DynamicMethod dm = new DynamicMethod ("calli", typeof (void), new Type [] { typeof (IntPtr), typeof (int[]) }); - - var il = dm.GetILGenerator (); - var signature = SignatureHelper.GetMethodSigHelper (CallingConvention.Cdecl, typeof (void)); - - il.Emit (OpCodes.Ldarg, 1); - signature.AddArgument (typeof (byte[])); - - il.Emit (OpCodes.Ldarg_0); - - il.Emit (OpCodes.Calli, signature); - il.Emit (OpCodes.Ret); - - var f = (CalliDel)dm.CreateDelegate (typeof (CalliDel)); - - int[] arr = new int [1000]; - for (int i = 0; i < 50; ++i) - arr [i] = (int)i; - f (func, arr); - if (arr.Length != 1000) - return 1; - for (int i = 0; i < 50; ++i) - if (arr [i] != 50 - i) - return 2; - - return 0; - } - - - /*char array marshaling */ - [DllImport ("libtest", EntryPoint="mono_test_marshal_ansi_char_array", CharSet=CharSet.Ansi)] - public static extern int mono_test_marshal_ansi_char_array (char[] a1); - - public static int test_0_marshal_ansi_char_array () { - char[] buf = new char [32]; - buf [0] = 'q'; - buf [1] = 'w'; - buf [2] = 'e'; - buf [3] = 'r'; - - if (mono_test_marshal_ansi_char_array (buf) != 0) - return 1; - - string s = new string (buf); - if (s.StartsWith ("qwer")) - return 0; - else - return 2; - } - - /*char array marshaling */ - [DllImport ("libtest", EntryPoint="mono_test_marshal_unicode_char_array", CharSet=CharSet.Unicode)] - public static extern int mono_test_marshal_unicode_char_array (char[] a1); - - public static int test_0_marshal_unicode_char_array () { - char[] buf = new char [32]; - buf [0] = 'q'; - buf [1] = 'w'; - buf [2] = 'e'; - buf [3] = 'r'; - - if (mono_test_marshal_unicode_char_array (buf) != 0) - return 1; - - string s = new string (buf); - if (s.StartsWith ("abcdef")) - return 0; - else - return 2; - } - - [DllImport ("libtest", EntryPoint="mono_test_marshal_lpstr")] - public static extern int mono_test_marshal_lpstr ([MarshalAs(UnmanagedType.LPStr)] string str); - - public static int test_0_mono_test_marshal_lpstr () { - string str = "ABC"; - - if (mono_test_marshal_lpstr (str) != 0) - return 1; - - return 0; - } - - [DllImport ("libtest", EntryPoint="mono_test_marshal_lpwstr")] - public static extern int mono_test_marshal_lpwstr ([MarshalAs(UnmanagedType.LPWStr)] string str); - - public static int test_0_mono_test_marshal_lpwstr () { - string str = "ABC"; - - if (mono_test_marshal_lpwstr (str) != 0) - return 1; - - return 0; - } - - - [method: DllImport ("libtest", EntryPoint="mono_test_marshal_return_lpstr")] - [return: MarshalAs(UnmanagedType.LPStr)] - public static extern string mono_test_marshal_return_lpstr (); - - public static int test_0_mono_test_marshal_return_lpstr () { - string str = mono_test_marshal_return_lpstr (); - if ("XYZ" == str) - return 0; - - return 1; - } - - [method: DllImport ("libtest", EntryPoint="mono_test_marshal_return_lpwstr")] - [return: MarshalAs(UnmanagedType.LPWStr)] - public static extern string mono_test_marshal_return_lpwstr (); - - public static int test_0_mono_test_marshal_return_lpwstr () { - string str = mono_test_marshal_return_lpwstr (); - if ("XYZ" == str) - return 0; - - return 1; - } - - [DllImport ("libtest", EntryPoint="mono_test_has_thiscall")] - public static extern int mono_test_has_thiscall (); - - [DllImport ("libtest", EntryPoint = "_mono_test_native_thiscall1", CallingConvention=CallingConvention.ThisCall)] - public static extern int mono_test_native_thiscall (int a); - - [DllImport ("libtest", EntryPoint = "_mono_test_native_thiscall2", CallingConvention=CallingConvention.ThisCall)] - public static extern int mono_test_native_thiscall (int a, int b); - - [DllImport ("libtest", EntryPoint = "_mono_test_native_thiscall3", CallingConvention=CallingConvention.ThisCall)] - public static extern int mono_test_native_thiscall (int a, int b, int c); - - [DllImport ("libtest", EntryPoint = "_mono_test_native_thiscall1", CallingConvention=CallingConvention.ThisCall)] - public static extern int mono_test_native_thiscall (TinyStruct a); - - [DllImport ("libtest", EntryPoint = "_mono_test_native_thiscall2", CallingConvention=CallingConvention.ThisCall)] - public static extern int mono_test_native_thiscall (TinyStruct a, int b); - - [DllImport ("libtest", EntryPoint = "_mono_test_native_thiscall3", CallingConvention=CallingConvention.ThisCall)] - public static extern int mono_test_native_thiscall (TinyStruct a, int b, int c); - - public static int test_0_native_thiscall () - { - if (mono_test_has_thiscall () == 0) - return 0; - - if (mono_test_native_thiscall (1968329802) != 1968329802) - return 1; - - if (mono_test_native_thiscall (268894549, 1212675791) != 1481570339) - return 2; - - if (mono_test_native_thiscall (1288082683, -421187449, -1733670329) != -866775098) - return 3; - - if (mono_test_native_thiscall (new TinyStruct(1968329802)) != 1968329802) - return 4; - - if (mono_test_native_thiscall (new TinyStruct(268894549), 1212675791) != 1481570339) - return 5; - - if (mono_test_native_thiscall (new TinyStruct(1288082683), -421187449, -1733670329) != -866775098) - return 6; - - return 0; - } - - [DllImport ("libtest", EntryPoint = "mono_test_marshal_return_single_double_struct")] - public static extern SingleDoubleStruct mono_test_marshal_return_single_double_struct (); - - public static int test_0_x86_single_double_struct_ret () { - double d = mono_test_marshal_return_single_double_struct ().d; - if (d != 3.0) - return 1; - else - return 0; - } -} - diff --git a/mono/tests/pinvoke3.cs b/mono/tests/pinvoke3.cs index 8d5cfb619f..075ef08bc4 100644 --- a/mono/tests/pinvoke3.cs +++ b/mono/tests/pinvoke3.cs @@ -746,6 +746,21 @@ public class Tests { return mono_test_marshal_array_delegate1 (null, 0, new ArrayDelegate1 (array_delegate2)); } + public delegate int ArrayDelegateBlittable (int i, string j, + [In, MarshalAs(UnmanagedType.LPArray, + ArraySubType=UnmanagedType.LPStr, SizeParamIndex=0)] int[] arr); + + [DllImport ("libtest", EntryPoint="mono_test_marshal_array_delegate")] + public static extern int mono_test_marshal_array_delegate1 (string[] arr, int len, ArrayDelegateBlittable d); + + public static int array_delegate_null_blittable (int i, string j, int[] arr) { + return (arr == null) ? 0 : 1; + } + + public static int test_0_marshal_array_delegate_null_blittable () { + return mono_test_marshal_array_delegate1 (null, 0, new ArrayDelegateBlittable (array_delegate_null_blittable)); + } + public delegate int ArrayDelegate3 (int i, string j, [In, MarshalAs(UnmanagedType.LPArray, diff --git a/mono/tests/priority.cs b/mono/tests/priority.cs new file mode 100644 index 0000000000..7956f23a4c --- /dev/null +++ b/mono/tests/priority.cs @@ -0,0 +1,131 @@ +using System; +using System.Threading; +using System.Runtime; +using System.Text; + +public class Tests +{ + private static int mainThreadId; + + public static int Main () + { + mainThreadId = Thread.CurrentThread.ManagedThreadId; + return TestDriver.RunTests (typeof (Tests)); + } + + public static void TestMethod() + { + Console.WriteLine("{0} with {1} priority", + Thread.CurrentThread.Name, + Thread.CurrentThread.Priority.ToString()); + Thread.Sleep(6000); + Console.WriteLine("{0} with {1} priority", + Thread.CurrentThread.Name, + Thread.CurrentThread.Priority.ToString()); + } + + public static int test_0_main_thread_priority () + { + Console.WriteLine("Testing main thread's priority"); + if (Thread.CurrentThread.ManagedThreadId != mainThreadId) + { + Console.WriteLine("test_0_main_thread_priority() must be run on the main thread"); + return 1; + } + + var before = Thread.CurrentThread.Priority; + Console.WriteLine("Priority: {0}", before); + if (before != ThreadPriority.Normal) + return 2; + + Console.WriteLine("Setting main thread's priority to AboveNormal"); + Thread.CurrentThread.Priority = ThreadPriority.AboveNormal; + var after = Thread.CurrentThread.Priority; + Console.WriteLine("Priority: {0} {1}", before, after); + if (after != ThreadPriority.AboveNormal) + return 3; + + before = after; + Console.WriteLine("Setting main thread's priority to BelowNormal"); + Thread.CurrentThread.Priority = ThreadPriority.BelowNormal; + after = Thread.CurrentThread.Priority; + Console.WriteLine("Priority: {0} {1}", before, after); + if (after != ThreadPriority.BelowNormal) + return 4; + + before = after; + Console.WriteLine("Setting main thread's priority to Normal"); + Thread.CurrentThread.Priority = ThreadPriority.Normal; + after = Thread.CurrentThread.Priority; + Console.WriteLine("Priority: {0} {1}", before, after); + if (after != ThreadPriority.Normal) + return 5; + + return 0; + } + + public static int test_0_thread_priority () + { + int res = 0; + + Thread Me = Thread.CurrentThread; + Thread TestThread = new Thread(new ThreadStart(TestMethod)); + + Console.WriteLine("Starting test thread with priority to AboveNormal"); + ThreadPriority before = TestThread.Priority; + TestThread.Priority = ThreadPriority.AboveNormal; + TestThread.Name = "TestMethod"; + TestThread.Start(); + ThreadPriority after = TestThread.Priority; + Console.WriteLine("Priority: {0} {1}",before,after); + if (before != ThreadPriority.Normal) + res = 1; + else if (after != ThreadPriority.AboveNormal) + res = 2; + else { + TestThread.Priority = ThreadPriority.Normal; + after = TestThread.Priority; + Console.WriteLine("Setting test thread priority to Normal"); + Thread.Sleep(1000); + Console.WriteLine("Priority: {0} {1}",before,after); + + if (after != ThreadPriority.Normal) + res = 3; + else { + Console.WriteLine("Setting test thread priority to AboveNormal"); + before = after; + TestThread.Priority=ThreadPriority.AboveNormal; + after = TestThread.Priority; + Thread.Sleep(1000); + Console.WriteLine("Priority: {0} {1}",before,after); + + if (after != ThreadPriority.AboveNormal) + res = 4; + else { + before = after; + Console.WriteLine("Setting test thread priority to BelowNormal"); + TestThread.Priority=ThreadPriority.BelowNormal; + after = TestThread.Priority; + Console.WriteLine("Priority: {0} {1}",before,after); + Thread.Sleep(1000); + + if (after != ThreadPriority.BelowNormal) + res = 5; + else { + before = after; + Console.WriteLine("Setting test thread priority back to Normal"); + TestThread.Priority=ThreadPriority.Normal; + after = TestThread.Priority; + Console.WriteLine("Priority: {0} {1}",before,after); + Thread.Sleep(1000); + + if (after != ThreadPriority.Normal) + res = 6; + } + } + } + } + TestThread.Join(); + return(res); + } +} diff --git a/mono/tests/reference-loader.cs b/mono/tests/reference-loader.cs new file mode 100644 index 0000000000..a66d3c5de1 --- /dev/null +++ b/mono/tests/reference-loader.cs @@ -0,0 +1,110 @@ +// +// reference-loader.cs: +// +// Test for reference assembly loading + +using System; +using System.IO; +using System.Reflection; + +public class Tests { + public static int Main (string[] args) + { + return TestDriver.RunTests (typeof (Tests), args); + } + + public static int test_0_loadFrom_reference () + { + // Check that loading a reference assembly by filename for execution is an error + try { + var a = Assembly.LoadFrom ("./TestingReferenceAssembly.dll"); + } catch (BadImageFormatException exn) { + // .NET Framework 4.6.2 throws BIFE here. + return 0; + } + return 1; + } + + public static int test_0_load_reference () + { + // Check that loading a reference assembly for execution is an error + try { + var an = new AssemblyName ("TestingReferenceAssembly"); + var a = Assembly.Load (an); + } catch (FileNotFoundException exn) { + return 0; + } catch (BadImageFormatException exn) { + // .NET Framework 4.6.2 throws BIFE here. + return 0; + } + return 1; + } + + public static int test_0_reflection_load_reference () + { + // Check that reflection-only loading a reference assembly is okay + var an = new AssemblyName ("TestingReferenceAssembly"); + var a = Assembly.ReflectionOnlyLoad (an.FullName); + var t = a.GetType ("X"); + var f = t.GetField ("Y"); + if (f.FieldType.Equals (typeof (Int32))) + return 0; + return 1; + } + + public static int test_0_load_reference_asm_via_reference () + { + // Check that loading an assembly that references a reference assembly doesn't succeed. + var an = new AssemblyName ("TestingReferenceReferenceAssembly"); + try { + var a = Assembly.Load (an); + var t = a.GetType ("Z"); + } catch (FileNotFoundException){ + return 0; + } + return 1; + } + + public static int test_0_reflection_load_reference_asm_via_reference () + { + // Check that reflection-only loading an assembly that + // references a reference assembly is okay. + var an = new AssemblyName ("TestingReferenceReferenceAssembly"); + var a = Assembly.ReflectionOnlyLoad (an.FullName); + var t = a.GetType ("Z"); + var f = t.GetField ("Y"); + if (f.FieldType.Equals (typeof (Int32))) + return 0; + return 1; + } + + + public static int test_0_load_reference_bytes () + { + // Check that loading a reference assembly from a byte array for execution is an error + byte[] bs = File.ReadAllBytes ("./TestingReferenceAssembly.dll"); + try { + var a = Assembly.Load (bs); + } catch (BadImageFormatException) { + return 0; + } catch (FileNotFoundException exn) { + Console.Error.WriteLine ("incorrect exn was {0}", exn); + return 2; + } + return 1; + } + + public static int test_0_reflection_load_reference_bytes () + { + // Check that loading a reference assembly from a byte + // array for reflection only is okay. + byte[] bs = File.ReadAllBytes ("./TestingReferenceAssembly.dll"); + var a = Assembly.ReflectionOnlyLoad (bs); + var t = a.GetType ("X"); + var f = t.GetField ("Y"); + if (f.FieldType.Equals (typeof (Int32))) + return 0; + return 1; + } + +} diff --git a/mono/tests/remoting1.cs b/mono/tests/remoting1.cs deleted file mode 100644 index ce9589469e..0000000000 --- a/mono/tests/remoting1.cs +++ /dev/null @@ -1,213 +0,0 @@ -using System; -using System.Threading; -using System.Runtime.InteropServices; -using System.Runtime.Remoting; -using System.Runtime.Remoting.Messaging; -using System.Runtime.Remoting.Proxies; - -class MyProxy : RealProxy { - readonly MarshalByRefObject target; - - public MyProxy (MarshalByRefObject target) : base (target.GetType()) - { - this.target = target; - } - - public override IMessage Invoke (IMessage request) { - IMethodCallMessage call = (IMethodCallMessage)request; - Console.WriteLine ("Invoke " + call.MethodName); - - Console.Write ("ARGS("); - for (int i = 0; i < call.ArgCount; i++) { - if (i != 0) - Console.Write (", "); - Console.Write (call.GetArgName (i) + " " + - call.GetArg (i)); - } - Console.WriteLine (")"); - Console.Write ("INARGS("); - for (int i = 0; i < call.InArgCount; i++) { - if (i != 0) - Console.Write (", "); - Console.Write (call.GetInArgName (i) + " " + - call.GetInArg (i)); - } - Console.WriteLine (")"); - - IMethodReturnMessage res = RemotingServices.ExecuteMessage (target, call); - - Console.Write ("RESARGS("); - for (int i = 0; i < res.ArgCount; i++) { - if (i != 0) - Console.Write (", "); - Console.Write (res.GetArgName (i) + " " + - res.GetArg (i)); - } - Console.WriteLine (")"); - - Console.Write ("RESOUTARGS("); - for (int i = 0; i < res.OutArgCount; i++) { - if (i != 0) - Console.Write (", "); - Console.Write (res.GetOutArgName (i) + " " + - res.GetOutArg (i)); - } - Console.WriteLine (")"); - - return res; - } -} - -public class EmptyProxy : RealProxy -{ - public EmptyProxy ( Type type ) : base( type ) - { - } - - public override IMessage Invoke( IMessage msg ) - { - IMethodCallMessage call = (IMethodCallMessage)msg; - - return new ReturnMessage( null, null, 0, null, call ); - } -} - -public struct MyStruct { - public int a; - public int b; - public int c; -} - -interface R2 { -} - -class R1 : MarshalByRefObject, R2 { - - public int test_field = 5; - public object null_test_field; - - public virtual MyStruct Add (int a, out int c, int b) { - Console.WriteLine ("ADD"); - c = a + b; - - MyStruct res = new MyStruct (); - - res.a = a; - res.b = b; - res.c = c; - - return res; - } - - public long nonvirtual_Add (int a, int b) { - Console.WriteLine ("nonvirtual_Add " + a + " + " + b); - return a + b; - } -} - -class R3 : MarshalByRefObject { - public object anObject; -} - -class Test { - - delegate MyStruct RemoteDelegate1 (int a, out int c, int b); - delegate long RemoteDelegate2 (int a, int b); - - static long test_call (R1 o) - { - return o.nonvirtual_Add (2, 3); - } - - static int Main () { - R1 myobj = new R1 (); - int res = 0; - long lres; - - MyProxy real_proxy = new MyProxy (myobj); - - R1 o = (R1)real_proxy.GetTransparentProxy (); - - if (RemotingServices.IsTransparentProxy (null)) - return 1; - - if (!RemotingServices.IsTransparentProxy (o)) - return 2; - - Console.WriteLine ("XXXXXXXXXXXX: " + RemotingServices.GetRealProxy (o)); - - if (o.GetType () != myobj.GetType ()) - return 3; - - MyStruct myres = o.Add (2, out res, 3); - - Console.WriteLine ("Result: " + myres.a + " " + - myres.b + " " + myres.c + " " + res); - - if (myres.a != 2) - return 4; - - if (myres.b != 3) - return 5; - - if (myres.c != 5) - return 6; - - if (res != 5) - return 7; - - R1 o2 = new R1 (); - - lres = test_call (o2); - - lres = test_call (o); - - Console.WriteLine ("Result: " + lres); - if (lres != 5) - return 8; - - lres = test_call (o); - - o.test_field = 2; - - Console.WriteLine ("test_field: " + o.test_field); - if (o.test_field != 2) - return 9; - - RemoteDelegate1 d1 = new RemoteDelegate1 (o.Add); - MyStruct myres2 = d1 (2, out res, 3); - - Console.WriteLine ("Result: " + myres2.a + " " + - myres2.b + " " + myres2.c + " " + res); - - if (myres2.a != 2) - return 10; - - if (myres2.b != 3) - return 11; - - if (myres2.c != 5) - return 12; - - if (res != 5) - return 13; - - RemoteDelegate2 d2 = new RemoteDelegate2 (o.nonvirtual_Add); - d2 (6, 7); - - if (!(real_proxy.GetTransparentProxy () is R2)) - return 14; - - /* Test what happens if the proxy doesn't return the required information */ - EmptyProxy handler = new EmptyProxy ( typeof (R3) ); - R3 o3 = (R3)handler.GetTransparentProxy(); - - if (o3.anObject != null) - return 15; - - if (o.null_test_field != null) - return 16; - - return 0; - } -} diff --git a/mono/tests/remoting2.cs b/mono/tests/remoting2.cs deleted file mode 100644 index eda80c6739..0000000000 --- a/mono/tests/remoting2.cs +++ /dev/null @@ -1,113 +0,0 @@ -using System; -using System.Threading; -using System.Runtime.InteropServices; -using System.Runtime.Remoting; -using System.Runtime.Remoting.Messaging; -using System.Runtime.Remoting.Proxies; - -class MyProxy : RealProxy { - readonly MarshalByRefObject target; - - public MyProxy (MarshalByRefObject target) : base (target.GetType()) - { - this.target = target; - } - - public override IMessage Invoke (IMessage request) { - IMethodCallMessage call = (IMethodCallMessage)request; - Console.WriteLine ("Invoke " + call.MethodName); - - Console.Write ("ARGS("); - for (int i = 0; i < call.ArgCount; i++) { - if (i != 0) - Console.Write (", "); - Console.Write (call.GetArgName (i) + " " + - call.GetArg (i)); - } - Console.WriteLine (")"); - Console.Write ("INARGS("); - for (int i = 0; i < call.InArgCount; i++) { - if (i != 0) - Console.Write (", "); - Console.Write (call.GetInArgName (i) + " " + - call.GetInArg (i)); - } - Console.WriteLine (")"); - - IMethodReturnMessage res = RemotingServices.ExecuteMessage (target, call); - - Console.Write ("RESARGS("); - for (int i = 0; i < res.ArgCount; i++) { - if (i != 0) - Console.Write (", "); - Console.Write (res.GetArgName (i) + " " + - res.GetArg (i)); - } - Console.WriteLine (")"); - - Console.Write ("RESOUTARGS("); - for (int i = 0; i < res.OutArgCount; i++) { - if (i != 0) - Console.Write (", "); - Console.Write (res.GetOutArgName (i) + " " + - res.GetOutArg (i)); - } - Console.WriteLine (")"); - - return res; - } -} - -public struct MyStruct { - public int a; - public int b; - public int c; -} - -class R1 : MarshalByRefObject { - - public int test_field = 5; - - public virtual MyStruct Add (int a, out int c, int b) { - Console.WriteLine ("ADD"); - c = a + b; - - MyStruct res = new MyStruct (); - - res.a = a; - res.b = b; - res.c = c; - - return res; - } - - public long nonvirtual_Add (int a, int b) { - Console.WriteLine ("nonvirtual_Add"); - return a + b; - } -} - -class Test { - - delegate long RemoteDelegate2 (int a, int b); - - - static int Main () { - R1 myobj = new R1 (); - long lres; - - MyProxy real_proxy = new MyProxy (myobj); - - R1 o = (R1)real_proxy.GetTransparentProxy (); - - RemoteDelegate2 d2 = new RemoteDelegate2 (o.nonvirtual_Add); - d2 (6, 7); - - IAsyncResult ar1 = d2.BeginInvoke (2, 4, null, null); - lres = d2.EndInvoke (ar1); - if (lres != 6) - return 1; - - return 0; - } -} diff --git a/mono/tests/remoting3.cs b/mono/tests/remoting3.cs deleted file mode 100644 index 77fb860e65..0000000000 --- a/mono/tests/remoting3.cs +++ /dev/null @@ -1,123 +0,0 @@ -using System; -using System.Threading; -using System.Runtime.InteropServices; -using System.Runtime.Remoting; -using System.Runtime.Remoting.Messaging; -using System.Runtime.Remoting.Proxies; - -class MyProxy : RealProxy { - readonly MarshalByRefObject target; - - public MyProxy (MarshalByRefObject target) : base (target.GetType()) - { - this.target = target; - } - - public override IMessage Invoke (IMessage request) { - IMethodCallMessage call = (IMethodCallMessage)request; - Console.WriteLine ("Invoke " + call.MethodName); - - Console.Write ("ARGS("); - for (int i = 0; i < call.ArgCount; i++) { - if (i != 0) - Console.Write (", "); - Console.Write (call.GetArgName (i) + " " + - call.GetArg (i)); - } - Console.WriteLine (")"); - Console.Write ("INARGS("); - for (int i = 0; i < call.InArgCount; i++) { - if (i != 0) - Console.Write (", "); - Console.Write (call.GetInArgName (i) + " " + - call.GetInArg (i)); - } - Console.WriteLine (")"); - - IMethodReturnMessage res = RemotingServices.ExecuteMessage (target, call); - - Console.Write ("RESARGS("); - for (int i = 0; i < res.ArgCount; i++) { - if (i != 0) - Console.Write (", "); - Console.Write (res.GetArgName (i) + " " + - res.GetArg (i)); - } - Console.WriteLine (")"); - - Console.Write ("RESOUTARGS("); - for (int i = 0; i < res.OutArgCount; i++) { - if (i != 0) - Console.Write (", "); - Console.Write (res.GetOutArgName (i) + " " + - res.GetOutArg (i)); - } - Console.WriteLine (")"); - - return res; - } -} - -public struct MyStruct { - public int a; - public int b; - public int c; -} - -class R1 : MarshalByRefObject { - - public int test_field = 5; - - public virtual MyStruct Add (int a, out int c, int b) { - Console.WriteLine ("ADD"); - c = a + b; - - MyStruct res = new MyStruct (); - - res.a = a; - res.b = b; - res.c = c; - - return res; - } - - public long nonvirtual_Add (int a, int b) { - Console.WriteLine ("nonvirtual_Add"); - return a + b; - } -} - -class Test { - - delegate MyStruct RemoteDelegate1 (int a, out int c, int b); - - static int Main () { - R1 myobj = new R1 (); - int res = 0; - - MyProxy real_proxy = new MyProxy (myobj); - - R1 o = (R1)real_proxy.GetTransparentProxy (); - - RemoteDelegate1 d1 = new RemoteDelegate1 (o.Add); - - IAsyncResult ar = d1.BeginInvoke (2, out res, 3, null, null); - MyStruct myres = d1.EndInvoke (out res, ar); - - Console.WriteLine ("Result: " + myres.a + " " + - myres.b + " " + myres.c + " " + res); - if (myres.a != 2) - return 1; - - if (myres.b != 3) - return 2; - - if (myres.c != 5) - return 3; - - if (res != 5) - return 4; - - return 0; - } -} diff --git a/mono/tests/remoting5.cs b/mono/tests/remoting5.cs deleted file mode 100644 index 223fd112f0..0000000000 --- a/mono/tests/remoting5.cs +++ /dev/null @@ -1,100 +0,0 @@ -using System; -using System.Threading; -using System.Runtime.InteropServices; -using System.Runtime.Remoting; -using System.Runtime.Remoting.Messaging; -using System.Runtime.Remoting.Proxies; - -class MyProxy : RealProxy { - readonly MarshalByRefObject target; - - public MyProxy (MarshalByRefObject target) : base (target.GetType()) - { - this.target = target; - } - - public override IMessage Invoke (IMessage request) { - IMethodCallMessage call = (IMethodCallMessage)request; - Console.WriteLine ("Invoke " + call.MethodName); - - Console.Write ("ARGS("); - for (int i = 0; i < call.ArgCount; i++) { - if (i != 0) - Console.Write (", "); - Console.Write (call.GetArgName (i) + " " + - call.GetArg (i)); - } - Console.WriteLine (")"); - Console.Write ("INARGS("); - for (int i = 0; i < call.InArgCount; i++) { - if (i != 0) - Console.Write (", "); - Console.Write (call.GetInArgName (i) + " " + - call.GetInArg (i)); - } - Console.WriteLine (")"); - - ((R1)target).test_field = 1; - - IMethodReturnMessage res = RemotingServices.ExecuteMessage (target, call); - - Console.Write ("RESARGS("); - for (int i = 0; i < res.ArgCount; i++) { - if (i != 0) - Console.Write (", "); - Console.Write (res.GetArgName (i) + " " + - res.GetArg (i)); - } - Console.WriteLine (")"); - - Console.Write ("RESOUTARGS("); - for (int i = 0; i < res.OutArgCount; i++) { - if (i != 0) - Console.Write (", "); - Console.Write (res.GetOutArgName (i) + " " + - res.GetOutArg (i)); - } - Console.WriteLine (")"); - - return res; - } -} - -public struct TestStruct { - public int F; -} - -class R1 : MarshalByRefObject { - - public TestStruct S; - - public int test_field = 5; - - public virtual int ldfield_test () { - - MyProxy real_proxy = new MyProxy (this); - R1 o = (R1)real_proxy.GetTransparentProxy (); - - if (o.test_field != 1) - return 1; - - if (test_field != 1) - return 1; - - return 0; - } -} - -class Test { - - static int Main () { - R1 myobj = new R1 (); - - // Test ldflda on MarshalByRefObjects - myobj.S.F = -1; - if (myobj.S.F != -1) - return 1; - - return myobj.ldfield_test (); - } -} diff --git a/mono/tests/stackframes-async.2.cs b/mono/tests/stackframes-async.2.cs deleted file mode 100644 index 61342fee15..0000000000 --- a/mono/tests/stackframes-async.2.cs +++ /dev/null @@ -1,58 +0,0 @@ -using System; -using System.Net; -using System.Diagnostics; - - class MainClass - { - static int frame_count = 0; - public static int Main(string[] args) - { - AsyncCallback cback = new AsyncCallback(ResolveCallback); - IAsyncResult res = Dns.BeginGetHostEntry("localhost", cback, null); - for (int i = 0; i < 100; ++i) { - if (frame_count != 0) - break; - System.Threading.Thread.Sleep(100); - } - /* - * seems to be broken - while (!res.IsCompleted) { - System.Threading.Thread.Sleep(20); - }; - IPHostEntry ip = Dns.EndGetHostEntry (res); - Console.WriteLine (ip);*/ - if (frame_count < 1) - return 1; - - // A test for #444383 - AppDomain.CreateDomain("1").CreateInstance(typeof (Class1).Assembly.GetName ().Name, "Class1"); - - return 0; - } - - public static void ResolveCallback(IAsyncResult ar) - { - Console.WriteLine("ResolveCallback()"); - StackTrace st = new StackTrace(); - frame_count = st.FrameCount; - for(int i = 0; i < st.FrameCount; i++) { - StackFrame sf = st.GetFrame(i); - Console.WriteLine("method: {0}", sf.GetMethod()); - } - Console.WriteLine("ResolveCallback() complete"); - } - } - -public class Class1 -{ - public Class1 () { - AppDomain.CreateDomain("2").CreateInstance(typeof (Class1).Assembly.GetName ().Name, "Class2"); - } -} - -public class Class2 -{ - public Class2 () { - new StackTrace(true); - } -} diff --git a/mono/tests/test-runner.cs b/mono/tests/test-runner.cs index baf0609a3b..53b4e92835 100644 --- a/mono/tests/test-runner.cs +++ b/mono/tests/test-runner.cs @@ -11,13 +11,16 @@ using System; using System.IO; using System.Threading; -using System.Text; using System.Diagnostics; using System.Collections.Generic; using System.Globalization; using System.Xml; +using System.Text; using System.Text.RegularExpressions; + +#if !MOBILE_STATIC using Mono.Unix.Native; +#endif // // This is a simple test runner with support for parallel execution @@ -27,6 +30,7 @@ public class TestRunner { const string TEST_TIME_FORMAT = "mm\\:ss\\.fff"; const string ENV_TIMEOUT = "TEST_DRIVER_TIMEOUT_SEC"; + const string MONO_PATH = "MONO_PATH"; class ProcessData { public string test; @@ -43,15 +47,19 @@ public class TestRunner int concurrency = 1; int timeout = 2 * 60; // in seconds int expectedExitCode = 0; + bool verbose = false; string testsuiteName = null; string inputFile = null; - // FIXME: Add support for runtime arguments + env variables - string disabled_tests = null; string runtime = "mono"; + string config = null; + string mono_path = null; var opt_sets = new List (); + string aot_run_flags = null; + string aot_build_flags = null; + // Process options int i = 0; while (i < args.Length) { @@ -87,6 +95,13 @@ public class TestRunner } runtime = args [i + 1]; i += 2; + } else if (args [i] == "--config") { + if (i + 1 >= args.Length) { + Console.WriteLine ("Missing argument to --config command line option."); + return 1; + } + config = args [i + 1]; + i += 2; } else if (args [i] == "--opt-sets") { if (i + 1 >= args.Length) { Console.WriteLine ("Missing argument to --opt-sets command line option."); @@ -116,6 +131,38 @@ public class TestRunner } inputFile = args [i + 1]; i += 2; + } else if (args [i] == "--runtime") { + if (i + 1 >= args.Length) { + Console.WriteLine ("Missing argument to --runtime command line option."); + return 1; + } + runtime = args [i + 1]; + i += 2; + } else if (args [i] == "--mono-path") { + if (i + 1 >= args.Length) { + Console.WriteLine ("Missing argument to --mono-path command line option."); + return 1; + } + mono_path = args [i + 1].Substring(0, args [i + 1].Length); + + i += 2; + } else if (args [i] == "--aot-run-flags") { + if (i + 1 >= args.Length) { + Console.WriteLine ("Missing argument to --aot-run-flags command line option."); + return 1; + } + aot_run_flags = args [i + 1].Substring(0, args [i + 1].Length); + i += 2; + } else if (args [i] == "--aot-build-flags") { + if (i + 1 >= args.Length) { + Console.WriteLine ("Missing argument to --aot-build-flags command line option."); + return 1; + } + aot_build_flags = args [i + 1].Substring(0, args [i + 1].Length); + i += 2; + } else if (args [i] == "--verbose") { + verbose = true; + i ++; } else { Console.WriteLine ("Unknown command line option: '" + args [i] + "'."); return 1; @@ -174,6 +221,65 @@ public class TestRunner output_width = Math.Min (120, ti.test.Length); } + if (aot_build_flags != null) { + Console.WriteLine("AOT compiling tests"); + + object aot_monitor = new object (); + var aot_queue = new Queue (tests); + + List build_threads = new List (concurrency); + + for (int j = 0; j < concurrency; ++j) { + Thread thread = new Thread (() => { + while (true) { + String test_name; + + lock (aot_monitor) { + if (aot_queue.Count == 0) + break; + test_name = aot_queue.Dequeue (); + } + + string test_bitcode_output = test_name + "_bitcode_tmp"; + string test_bitcode_arg = ",temp-path=" + test_bitcode_output; + string aot_args = aot_build_flags + test_bitcode_arg + " " + test_name; + + Directory.CreateDirectory(test_bitcode_output); + + ProcessStartInfo job = new ProcessStartInfo (runtime, aot_args); + job.UseShellExecute = false; + job.EnvironmentVariables[ENV_TIMEOUT] = timeout.ToString(); + job.EnvironmentVariables[MONO_PATH] = mono_path; + Process compiler = new Process (); + compiler.StartInfo = job; + + compiler.Start (); + + if (!compiler.WaitForExit (timeout * 1000)) { + try { + compiler.Kill (); + } catch { + } + throw new Exception(String.Format("Timeout AOT compiling tests, output in {0}", test_bitcode_output)); + } else if (compiler.ExitCode != 0) { + throw new Exception(String.Format("Error AOT compiling tests, output in {0}", test_bitcode_output)); + } else { + Directory.Delete (test_bitcode_output, true); + } + } + }); + + thread.Start (); + + build_threads.Add (thread); + } + + for (int j = 0; j < build_threads.Count; ++j) + build_threads [j].Join (); + + Console.WriteLine("Done compiling"); + } + List threads = new List (concurrency); DateTime test_start_time = DateTime.UtcNow; @@ -194,19 +300,35 @@ public class TestRunner string test = ti.test; string opt_set = ti.opt_set; - output.Write (String.Format ("{{0,-{0}}} ", output_width), test); + if (verbose) { + output.Write (String.Format ("{{0,-{0}}} ", output_width), test); + } else { + Console.Write ("."); + } + + string test_invoke; + + if (aot_run_flags != null) + test_invoke = aot_run_flags + " " + test; + else + test_invoke = test; /* Spawn a new process */ string process_args; if (opt_set == null) - process_args = test; + process_args = test_invoke; else - process_args = "-O=" + opt_set + " " + test; + process_args = "-O=" + opt_set + " " + test_invoke; + ProcessStartInfo info = new ProcessStartInfo (runtime, process_args); info.UseShellExecute = false; info.RedirectStandardOutput = true; info.RedirectStandardError = true; info.EnvironmentVariables[ENV_TIMEOUT] = timeout.ToString(); + if (config != null) + info.EnvironmentVariables["MONO_CONFIG"] = config; + if (mono_path != null) + info.EnvironmentVariables[MONO_PATH] = mono_path; Process p = new Process (); p.StartInfo = info; @@ -247,14 +369,18 @@ public class TestRunner timedout.Add (data); } +#if !MOBILE_STATIC // Force the process to print a thread dump try { Syscall.kill (p.Id, Signum.SIGQUIT); Thread.Sleep (1000); } catch { } +#endif - output.Write ($"timed out ({timeout}s)"); + if (verbose) { + output.Write ($"timed out ({timeout}s)"); + } try { p.Kill (); @@ -267,7 +393,8 @@ public class TestRunner failed.Add (data); } - output.Write ("failed, time: {0}, exit code: {1}", (end - start).ToString (TEST_TIME_FORMAT), p.ExitCode); + if (verbose) + output.Write ("failed, time: {0}, exit code: {1}", (end - start).ToString (TEST_TIME_FORMAT), p.ExitCode); } else { var end = DateTime.UtcNow; @@ -275,13 +402,15 @@ public class TestRunner passed.Add (data); } - output.Write ("passed, time: {0}", (end - start).ToString (TEST_TIME_FORMAT)); + if (verbose) + output.Write ("passed, time: {0}", (end - start).ToString (TEST_TIME_FORMAT)); } p.Close (); lock (monitor) { - Console.WriteLine (output.ToString ()); + if (verbose) + Console.WriteLine (output.ToString ()); } } }); @@ -303,7 +432,9 @@ public class TestRunner XmlWriterSettings xmlWriterSettings = new XmlWriterSettings (); xmlWriterSettings.NewLineOnAttributes = true; xmlWriterSettings.Indent = true; - using (XmlWriter writer = XmlWriter.Create (String.Format ("TestResult-{0}.xml", testsuiteName), xmlWriterSettings)) { + + string xmlPath = String.Format ("TestResult-{0}.xml", testsuiteName); + using (XmlWriter writer = XmlWriter.Create (xmlPath, xmlWriterSettings)) { // writer.WriteStartDocument (); // @@ -420,14 +551,29 @@ public class TestRunner // writer.WriteEndElement (); writer.WriteEndDocument (); + + string babysitterXmlList = Environment.GetEnvironmentVariable("MONO_BABYSITTER_NUNIT_XML_LIST_FILE"); + if (!String.IsNullOrEmpty(babysitterXmlList)) { + try { + string fullXmlPath = Path.GetFullPath(xmlPath); + File.AppendAllText(babysitterXmlList, fullXmlPath + Environment.NewLine); + } catch (Exception e) { + Console.WriteLine("Attempted to record XML path to file {0} but failed.", babysitterXmlList); + } + } } - Console.WriteLine (); - Console.WriteLine ("Time: {0}", test_time.ToString (TEST_TIME_FORMAT)); - Console.WriteLine (); - Console.WriteLine ("{0,4} test(s) passed", npassed); - Console.WriteLine ("{0,4} test(s) failed", nfailed); - Console.WriteLine ("{0,4} test(s) timed out", ntimedout); + if (verbose) { + Console.WriteLine (); + Console.WriteLine ("Time: {0}", test_time.ToString (TEST_TIME_FORMAT)); + Console.WriteLine (); + Console.WriteLine ("{0,4} test(s) passed", npassed); + Console.WriteLine ("{0,4} test(s) failed", nfailed); + Console.WriteLine ("{0,4} test(s) timed out", ntimedout); + } else { + Console.WriteLine (); + Console.WriteLine (String.Format ("{0} test(s) passed, {1} test(s) did not pass.", npassed, nfailed)); + } if (nfailed > 0) { Console.WriteLine (); diff --git a/mono/tests/tests-config.in b/mono/tests/tests-config.in index 2c86105e9a..d67011313f 100644 --- a/mono/tests/tests-config.in +++ b/mono/tests/tests-config.in @@ -1,5 +1,7 @@ + + diff --git a/mono/tests/thread6.cs b/mono/tests/thread6.cs deleted file mode 100644 index 9b0c5cf3f9..0000000000 --- a/mono/tests/thread6.cs +++ /dev/null @@ -1,253 +0,0 @@ -// -// thread6.cs: Thread abort tests -// -using System; -using System.Threading; - -public class Tests { - - public static int result = 0; - public static object started = new object (); - - public static void ThreadStart1 () { - Console.WriteLine("{0} started", - Thread.CurrentThread.Name); - - try { - try { - try { - lock (started) { - Monitor.Pulse (started); - } - int i = 0; - try { - while (true) { - Console.WriteLine ("Count: " + i++); - Thread.Sleep (100); - } - } - catch (ThreadAbortException e) { - Console.WriteLine ("cought exception level 3 "); - - // Check that the exception is only rethrown in - // the appropriate catch clauses - - // This doesn't work currently, see - // http://bugzilla.ximian.com/show_bug.cgi?id=68552 - - /* - try { - } - catch {} - try { - throw new DivideByZeroException (); - } - catch (Exception) { - } - */ - result |= 32; - - // Check that the exception is properly rethrown - } - result = 255; - } catch (ThreadAbortException e) { - Console.WriteLine ("cought exception level 2 " + e.ExceptionState); - Console.WriteLine (e); - if ((string)e.ExceptionState == "STATETEST") - result |= 1; - - Thread.ResetAbort (); - throw e; - } - } catch (ThreadAbortException e) { - Console.WriteLine ("cought exception level 1 " + e.ExceptionState); - Console.WriteLine (e); - if (e.ExceptionState == null) - result |= 2; - } - } catch (Exception e) { - Console.WriteLine ("cought exception level 0") -; Console.WriteLine (e); - Console.WriteLine (e.StackTrace); - result |= 4; - } - - try { - Thread.ResetAbort (); - } catch (System.Threading.ThreadStateException e) { - result |= 8; - } - - Console.WriteLine ("end"); - result |= 16; - } - - static string regress_78024 () - { - try { - Thread.CurrentThread.Abort (); - } catch (Exception e) { - return "Got exception: " + e.Message; - } finally { - } - return ""; - } - - public static int Main() { - return TestDriver.RunTests (typeof (Tests)); - } - - public static int test_0_abort_current () { - // Check aborting the current thread - bool aborted = false; - try { - Thread.CurrentThread.Abort (); - } - catch { - aborted = true; - Thread.ResetAbort (); - } - if (!aborted) - return 2; - - return 0; - } - - public static int test_0_test_1 () { - Thread t1 = null; - - lock (started) { - t1 = new Thread(new ThreadStart - (Tests.ThreadStart1)); - t1.Name = "Thread 1"; - - Thread.Sleep (100); - - t1.Start(); - - Monitor.Wait (started); - } - - Thread.Sleep (100); - - t1.Abort ("STATETEST"); - - t1.Join (); - - if (result != 59) { - Console.WriteLine ("Result: " + result); - return 1; - } - - return 0; - } - - public static int test_0_regress_68552 () { - try { - try { - Run (); - } catch (Exception ex) { - } - - return 2; - } - catch (ThreadAbortException ex) { - Thread.ResetAbort (); - } - - return 0; - } - - public static int test_0_regress_78024 () { - try { - regress_78024 (); - return 3; - } - catch (ThreadAbortException ex) { - Thread.ResetAbort (); - } - - return 0; - } - - public class CBO : ContextBoundObject { - public void Run () { - Thread.CurrentThread.Abort ("FOO"); - } - } - - public static int test_0_regress_539394 () { - // Check that a ThreadAbortException thrown through remoting retains its - // abort state - AppDomain d = AppDomain.CreateDomain ("test"); - CBO obj = (CBO)d.CreateInstanceFromAndUnwrap (typeof (Tests).Assembly.Location, "Tests/CBO"); - bool success = false; - - Thread t = new Thread (delegate () { - try { - obj.Run (); - } catch (ThreadAbortException ex) { - if ((string)ex.ExceptionState == "FOO") - success = true; - } - }); - - t.Start (); - t.Join (); - - return success ? 0 : 1; - } - - public static int test_0_regress_4413 () { - // Check that thread abort exceptions originating in another thread are not automatically rethrown - object o = new object (); - Thread t = null; - bool waiting = false; - Action a = delegate () { - t = Thread.CurrentThread; - while (true) { - lock (o) { - if (waiting) { - Monitor.Pulse (o); - break; - } - } - - Thread.Sleep (10); - } - while (true) { - Thread.Sleep (1000); - } - }; - var ar = a.BeginInvoke (null, null); - lock (o) { - waiting = true; - Monitor.Wait (o); - } - - t.Abort (); - - try { - try { - a.EndInvoke (ar); - } catch (ThreadAbortException) { - } - } catch (ThreadAbortException) { - // This will fail - Thread.ResetAbort (); - return 1; - } - - return 0; - } - - public static void Run () - { - try { - Thread.CurrentThread.Abort (); - } catch (Exception ex) { - throw new Exception ("other"); - } - } -} - diff --git a/mono/tests/threadpool-exceptions7.cs b/mono/tests/threadpool-exceptions7.cs deleted file mode 100644 index 942662ab97..0000000000 --- a/mono/tests/threadpool-exceptions7.cs +++ /dev/null @@ -1,31 +0,0 @@ - -using System; -using System.Threading; - -class Test { - static int Main () - { - AppDomain.CurrentDomain.UnhandledException += OnUnhandledException; - OtherDomain (); - return 0; - } - - static void OtherDomain () - { - AppDomain domain = AppDomain.CreateDomain ("test"); - ThreadPool.QueueUserWorkItem (unused => { - domain.DoCallBack (() => { - // This will get a ThreadAbortedException - Thread.Sleep (10000); - }); - }); - Thread.Sleep (1000); - AppDomain.Unload (domain); - } - - static void OnUnhandledException (object sender, UnhandledExceptionEventArgs e) - { - Environment.Exit (1); - } -} - diff --git a/mono/tests/transparentproxy.cs b/mono/tests/transparentproxy.cs deleted file mode 100644 index 048030fa74..0000000000 --- a/mono/tests/transparentproxy.cs +++ /dev/null @@ -1,4866 +0,0 @@ - -using System; -using System.Runtime.Remoting; -using System.Runtime.Remoting.Proxies; -using System.Runtime.Remoting.Messaging; -using System.Reflection; - -class MyRealProxy : RealProxy, IRemotingTypeInfo -{ - MBRO mbro; - bool can_cast_to_called = false; - - public MyRealProxy (MBRO mbro) - : base (typeof (MBRO)) { - this.mbro = mbro; - } - - public override System.Runtime.Remoting.Messaging.IMessage Invoke (System.Runtime.Remoting.Messaging.IMessage msg) { - IMethodCallMessage call = (IMethodCallMessage)msg; - - return new ReturnMessage (mbro.CallMe ((int)call.Args[0]), null, 0, null, call); - } - - public bool CanCastTo (Type fromType, object o) { - can_cast_to_called = true; - return true; - } - - public string TypeName { - get { - return ""; - } - set { - throw new Exception ("Should not be called"); - } - } - - public bool CanCastToCalled { - get { - return can_cast_to_called; - } - set { - can_cast_to_called = value; - } - } -} - -class MBRO : MarshalByRefObject -{ - public int CallMe (int a) { - return a; - } -} - -class MainClass -{ - static int Main (string[] args) { - int total = 0; - MyRealProxy mrp = new MyRealProxy (new MBRO ()); - object o = mrp.GetTransparentProxy (); - - mrp.CanCastToCalled = false; - I1 itf1 = (I1)o; - if (!mrp.CanCastToCalled) - return 1; - total += itf1.CallMe (1); - mrp.CanCastToCalled = false; - itf1 = (I1)o; - if (mrp.CanCastToCalled) - return 1; - total += itf1.CallMe (1); - - mrp.CanCastToCalled = false; - I2 itf2 = (I2)o; - if (!mrp.CanCastToCalled) - return 2; - total += itf2.CallMe (2); - mrp.CanCastToCalled = false; - itf2 = (I2)o; - if (mrp.CanCastToCalled) - return 2; - total += itf2.CallMe (2); - - mrp.CanCastToCalled = false; - I3 itf3 = (I3)o; - if (!mrp.CanCastToCalled) - return 3; - total += itf3.CallMe (3); - mrp.CanCastToCalled = false; - itf3 = (I3)o; - if (mrp.CanCastToCalled) - return 3; - total += itf3.CallMe (3); - - mrp.CanCastToCalled = false; - I4 itf4 = (I4)o; - if (!mrp.CanCastToCalled) - return 4; - total += itf4.CallMe (4); - mrp.CanCastToCalled = false; - itf4 = (I4)o; - if (mrp.CanCastToCalled) - return 4; - total += itf4.CallMe (4); - - mrp.CanCastToCalled = false; - I5 itf5 = (I5)o; - if (!mrp.CanCastToCalled) - return 5; - total += itf5.CallMe (5); - mrp.CanCastToCalled = false; - itf5 = (I5)o; - if (mrp.CanCastToCalled) - return 5; - total += itf5.CallMe (5); - - mrp.CanCastToCalled = false; - I6 itf6 = (I6)o; - if (!mrp.CanCastToCalled) - return 6; - total += itf6.CallMe (6); - mrp.CanCastToCalled = false; - itf6 = (I6)o; - if (mrp.CanCastToCalled) - return 6; - total += itf6.CallMe (6); - - mrp.CanCastToCalled = false; - I7 itf7 = (I7)o; - if (!mrp.CanCastToCalled) - return 7; - total += itf7.CallMe (7); - mrp.CanCastToCalled = false; - itf7 = (I7)o; - if (mrp.CanCastToCalled) - return 7; - total += itf7.CallMe (7); - - mrp.CanCastToCalled = false; - I8 itf8 = (I8)o; - if (!mrp.CanCastToCalled) - return 8; - total += itf8.CallMe (8); - mrp.CanCastToCalled = false; - itf8 = (I8)o; - if (mrp.CanCastToCalled) - return 8; - total += itf8.CallMe (8); - - mrp.CanCastToCalled = false; - I9 itf9 = (I9)o; - if (!mrp.CanCastToCalled) - return 9; - total += itf9.CallMe (9); - mrp.CanCastToCalled = false; - itf9 = (I9)o; - if (mrp.CanCastToCalled) - return 9; - total += itf9.CallMe (9); - - mrp.CanCastToCalled = false; - I10 itf10 = (I10)o; - if (!mrp.CanCastToCalled) - return 10; - total += itf10.CallMe (10); - mrp.CanCastToCalled = false; - itf10 = (I10)o; - if (mrp.CanCastToCalled) - return 10; - total += itf10.CallMe (10); - - mrp.CanCastToCalled = false; - I11 itf11 = (I11)o; - if (!mrp.CanCastToCalled) - return 11; - total += itf11.CallMe (11); - mrp.CanCastToCalled = false; - itf11 = (I11)o; - if (mrp.CanCastToCalled) - return 11; - total += itf11.CallMe (11); - - mrp.CanCastToCalled = false; - I12 itf12 = (I12)o; - if (!mrp.CanCastToCalled) - return 12; - total += itf12.CallMe (12); - mrp.CanCastToCalled = false; - itf12 = (I12)o; - if (mrp.CanCastToCalled) - return 12; - total += itf12.CallMe (12); - - mrp.CanCastToCalled = false; - I13 itf13 = (I13)o; - if (!mrp.CanCastToCalled) - return 13; - total += itf13.CallMe (13); - mrp.CanCastToCalled = false; - itf13 = (I13)o; - if (mrp.CanCastToCalled) - return 13; - total += itf13.CallMe (13); - - mrp.CanCastToCalled = false; - I14 itf14 = (I14)o; - if (!mrp.CanCastToCalled) - return 14; - total += itf14.CallMe (14); - mrp.CanCastToCalled = false; - itf14 = (I14)o; - if (mrp.CanCastToCalled) - return 14; - total += itf14.CallMe (14); - - mrp.CanCastToCalled = false; - I15 itf15 = (I15)o; - if (!mrp.CanCastToCalled) - return 15; - total += itf15.CallMe (15); - mrp.CanCastToCalled = false; - itf15 = (I15)o; - if (mrp.CanCastToCalled) - return 15; - total += itf15.CallMe (15); - - mrp.CanCastToCalled = false; - I16 itf16 = (I16)o; - if (!mrp.CanCastToCalled) - return 16; - total += itf16.CallMe (16); - mrp.CanCastToCalled = false; - itf16 = (I16)o; - if (mrp.CanCastToCalled) - return 16; - total += itf16.CallMe (16); - - mrp.CanCastToCalled = false; - I17 itf17 = (I17)o; - if (!mrp.CanCastToCalled) - return 17; - total += itf17.CallMe (17); - mrp.CanCastToCalled = false; - itf17 = (I17)o; - if (mrp.CanCastToCalled) - return 17; - total += itf17.CallMe (17); - - mrp.CanCastToCalled = false; - I18 itf18 = (I18)o; - if (!mrp.CanCastToCalled) - return 18; - total += itf18.CallMe (18); - mrp.CanCastToCalled = false; - itf18 = (I18)o; - if (mrp.CanCastToCalled) - return 18; - total += itf18.CallMe (18); - - mrp.CanCastToCalled = false; - I19 itf19 = (I19)o; - if (!mrp.CanCastToCalled) - return 19; - total += itf19.CallMe (19); - mrp.CanCastToCalled = false; - itf19 = (I19)o; - if (mrp.CanCastToCalled) - return 19; - total += itf19.CallMe (19); - - mrp.CanCastToCalled = false; - I20 itf20 = (I20)o; - if (!mrp.CanCastToCalled) - return 20; - total += itf20.CallMe (20); - mrp.CanCastToCalled = false; - itf20 = (I20)o; - if (mrp.CanCastToCalled) - return 20; - total += itf20.CallMe (20); - - mrp.CanCastToCalled = false; - I21 itf21 = (I21)o; - if (!mrp.CanCastToCalled) - return 21; - total += itf21.CallMe (21); - mrp.CanCastToCalled = false; - itf21 = (I21)o; - if (mrp.CanCastToCalled) - return 21; - total += itf21.CallMe (21); - - mrp.CanCastToCalled = false; - I22 itf22 = (I22)o; - if (!mrp.CanCastToCalled) - return 22; - total += itf22.CallMe (22); - mrp.CanCastToCalled = false; - itf22 = (I22)o; - if (mrp.CanCastToCalled) - return 22; - total += itf22.CallMe (22); - - mrp.CanCastToCalled = false; - I23 itf23 = (I23)o; - if (!mrp.CanCastToCalled) - return 23; - total += itf23.CallMe (23); - mrp.CanCastToCalled = false; - itf23 = (I23)o; - if (mrp.CanCastToCalled) - return 23; - total += itf23.CallMe (23); - - mrp.CanCastToCalled = false; - I24 itf24 = (I24)o; - if (!mrp.CanCastToCalled) - return 24; - total += itf24.CallMe (24); - mrp.CanCastToCalled = false; - itf24 = (I24)o; - if (mrp.CanCastToCalled) - return 24; - total += itf24.CallMe (24); - - mrp.CanCastToCalled = false; - I25 itf25 = (I25)o; - if (!mrp.CanCastToCalled) - return 25; - total += itf25.CallMe (25); - mrp.CanCastToCalled = false; - itf25 = (I25)o; - if (mrp.CanCastToCalled) - return 25; - total += itf25.CallMe (25); - - mrp.CanCastToCalled = false; - I26 itf26 = (I26)o; - if (!mrp.CanCastToCalled) - return 26; - total += itf26.CallMe (26); - mrp.CanCastToCalled = false; - itf26 = (I26)o; - if (mrp.CanCastToCalled) - return 26; - total += itf26.CallMe (26); - - mrp.CanCastToCalled = false; - I27 itf27 = (I27)o; - if (!mrp.CanCastToCalled) - return 27; - total += itf27.CallMe (27); - mrp.CanCastToCalled = false; - itf27 = (I27)o; - if (mrp.CanCastToCalled) - return 27; - total += itf27.CallMe (27); - - mrp.CanCastToCalled = false; - I28 itf28 = (I28)o; - if (!mrp.CanCastToCalled) - return 28; - total += itf28.CallMe (28); - mrp.CanCastToCalled = false; - itf28 = (I28)o; - if (mrp.CanCastToCalled) - return 28; - total += itf28.CallMe (28); - - mrp.CanCastToCalled = false; - I29 itf29 = (I29)o; - if (!mrp.CanCastToCalled) - return 29; - total += itf29.CallMe (29); - mrp.CanCastToCalled = false; - itf29 = (I29)o; - if (mrp.CanCastToCalled) - return 29; - total += itf29.CallMe (29); - - mrp.CanCastToCalled = false; - I30 itf30 = (I30)o; - if (!mrp.CanCastToCalled) - return 30; - total += itf30.CallMe (30); - mrp.CanCastToCalled = false; - itf30 = (I30)o; - if (mrp.CanCastToCalled) - return 30; - total += itf30.CallMe (30); - - mrp.CanCastToCalled = false; - I31 itf31 = (I31)o; - if (!mrp.CanCastToCalled) - return 31; - total += itf31.CallMe (31); - mrp.CanCastToCalled = false; - itf31 = (I31)o; - if (mrp.CanCastToCalled) - return 31; - total += itf31.CallMe (31); - - mrp.CanCastToCalled = false; - I32 itf32 = (I32)o; - if (!mrp.CanCastToCalled) - return 32; - total += itf32.CallMe (32); - mrp.CanCastToCalled = false; - itf32 = (I32)o; - if (mrp.CanCastToCalled) - return 32; - total += itf32.CallMe (32); - - mrp.CanCastToCalled = false; - I33 itf33 = (I33)o; - if (!mrp.CanCastToCalled) - return 33; - total += itf33.CallMe (33); - mrp.CanCastToCalled = false; - itf33 = (I33)o; - if (mrp.CanCastToCalled) - return 33; - total += itf33.CallMe (33); - - mrp.CanCastToCalled = false; - I34 itf34 = (I34)o; - if (!mrp.CanCastToCalled) - return 34; - total += itf34.CallMe (34); - mrp.CanCastToCalled = false; - itf34 = (I34)o; - if (mrp.CanCastToCalled) - return 34; - total += itf34.CallMe (34); - - mrp.CanCastToCalled = false; - I35 itf35 = (I35)o; - if (!mrp.CanCastToCalled) - return 35; - total += itf35.CallMe (35); - mrp.CanCastToCalled = false; - itf35 = (I35)o; - if (mrp.CanCastToCalled) - return 35; - total += itf35.CallMe (35); - - mrp.CanCastToCalled = false; - I36 itf36 = (I36)o; - if (!mrp.CanCastToCalled) - return 36; - total += itf36.CallMe (36); - mrp.CanCastToCalled = false; - itf36 = (I36)o; - if (mrp.CanCastToCalled) - return 36; - total += itf36.CallMe (36); - - mrp.CanCastToCalled = false; - I37 itf37 = (I37)o; - if (!mrp.CanCastToCalled) - return 37; - total += itf37.CallMe (37); - mrp.CanCastToCalled = false; - itf37 = (I37)o; - if (mrp.CanCastToCalled) - return 37; - total += itf37.CallMe (37); - - mrp.CanCastToCalled = false; - I38 itf38 = (I38)o; - if (!mrp.CanCastToCalled) - return 38; - total += itf38.CallMe (38); - mrp.CanCastToCalled = false; - itf38 = (I38)o; - if (mrp.CanCastToCalled) - return 38; - total += itf38.CallMe (38); - - mrp.CanCastToCalled = false; - I39 itf39 = (I39)o; - if (!mrp.CanCastToCalled) - return 39; - total += itf39.CallMe (39); - mrp.CanCastToCalled = false; - itf39 = (I39)o; - if (mrp.CanCastToCalled) - return 39; - total += itf39.CallMe (39); - - mrp.CanCastToCalled = false; - I40 itf40 = (I40)o; - if (!mrp.CanCastToCalled) - return 40; - total += itf40.CallMe (40); - mrp.CanCastToCalled = false; - itf40 = (I40)o; - if (mrp.CanCastToCalled) - return 40; - total += itf40.CallMe (40); - - mrp.CanCastToCalled = false; - I41 itf41 = (I41)o; - if (!mrp.CanCastToCalled) - return 41; - total += itf41.CallMe (41); - mrp.CanCastToCalled = false; - itf41 = (I41)o; - if (mrp.CanCastToCalled) - return 41; - total += itf41.CallMe (41); - - mrp.CanCastToCalled = false; - I42 itf42 = (I42)o; - if (!mrp.CanCastToCalled) - return 42; - total += itf42.CallMe (42); - mrp.CanCastToCalled = false; - itf42 = (I42)o; - if (mrp.CanCastToCalled) - return 42; - total += itf42.CallMe (42); - - mrp.CanCastToCalled = false; - I43 itf43 = (I43)o; - if (!mrp.CanCastToCalled) - return 43; - total += itf43.CallMe (43); - mrp.CanCastToCalled = false; - itf43 = (I43)o; - if (mrp.CanCastToCalled) - return 43; - total += itf43.CallMe (43); - - mrp.CanCastToCalled = false; - I44 itf44 = (I44)o; - if (!mrp.CanCastToCalled) - return 44; - total += itf44.CallMe (44); - mrp.CanCastToCalled = false; - itf44 = (I44)o; - if (mrp.CanCastToCalled) - return 44; - total += itf44.CallMe (44); - - mrp.CanCastToCalled = false; - I45 itf45 = (I45)o; - if (!mrp.CanCastToCalled) - return 45; - total += itf45.CallMe (45); - mrp.CanCastToCalled = false; - itf45 = (I45)o; - if (mrp.CanCastToCalled) - return 45; - total += itf45.CallMe (45); - - mrp.CanCastToCalled = false; - I46 itf46 = (I46)o; - if (!mrp.CanCastToCalled) - return 46; - total += itf46.CallMe (46); - mrp.CanCastToCalled = false; - itf46 = (I46)o; - if (mrp.CanCastToCalled) - return 46; - total += itf46.CallMe (46); - - mrp.CanCastToCalled = false; - I47 itf47 = (I47)o; - if (!mrp.CanCastToCalled) - return 47; - total += itf47.CallMe (47); - mrp.CanCastToCalled = false; - itf47 = (I47)o; - if (mrp.CanCastToCalled) - return 47; - total += itf47.CallMe (47); - - mrp.CanCastToCalled = false; - I48 itf48 = (I48)o; - if (!mrp.CanCastToCalled) - return 48; - total += itf48.CallMe (48); - mrp.CanCastToCalled = false; - itf48 = (I48)o; - if (mrp.CanCastToCalled) - return 48; - total += itf48.CallMe (48); - - mrp.CanCastToCalled = false; - I49 itf49 = (I49)o; - if (!mrp.CanCastToCalled) - return 49; - total += itf49.CallMe (49); - mrp.CanCastToCalled = false; - itf49 = (I49)o; - if (mrp.CanCastToCalled) - return 49; - total += itf49.CallMe (49); - - mrp.CanCastToCalled = false; - I50 itf50 = (I50)o; - if (!mrp.CanCastToCalled) - return 50; - total += itf50.CallMe (50); - mrp.CanCastToCalled = false; - itf50 = (I50)o; - if (mrp.CanCastToCalled) - return 50; - total += itf50.CallMe (50); - - mrp.CanCastToCalled = false; - I51 itf51 = (I51)o; - if (!mrp.CanCastToCalled) - return 51; - total += itf51.CallMe (51); - mrp.CanCastToCalled = false; - itf51 = (I51)o; - if (mrp.CanCastToCalled) - return 51; - total += itf51.CallMe (51); - - mrp.CanCastToCalled = false; - I52 itf52 = (I52)o; - if (!mrp.CanCastToCalled) - return 52; - total += itf52.CallMe (52); - mrp.CanCastToCalled = false; - itf52 = (I52)o; - if (mrp.CanCastToCalled) - return 52; - total += itf52.CallMe (52); - - mrp.CanCastToCalled = false; - I53 itf53 = (I53)o; - if (!mrp.CanCastToCalled) - return 53; - total += itf53.CallMe (53); - mrp.CanCastToCalled = false; - itf53 = (I53)o; - if (mrp.CanCastToCalled) - return 53; - total += itf53.CallMe (53); - - mrp.CanCastToCalled = false; - I54 itf54 = (I54)o; - if (!mrp.CanCastToCalled) - return 54; - total += itf54.CallMe (54); - mrp.CanCastToCalled = false; - itf54 = (I54)o; - if (mrp.CanCastToCalled) - return 54; - total += itf54.CallMe (54); - - mrp.CanCastToCalled = false; - I55 itf55 = (I55)o; - if (!mrp.CanCastToCalled) - return 55; - total += itf55.CallMe (55); - mrp.CanCastToCalled = false; - itf55 = (I55)o; - if (mrp.CanCastToCalled) - return 55; - total += itf55.CallMe (55); - - mrp.CanCastToCalled = false; - I56 itf56 = (I56)o; - if (!mrp.CanCastToCalled) - return 56; - total += itf56.CallMe (56); - mrp.CanCastToCalled = false; - itf56 = (I56)o; - if (mrp.CanCastToCalled) - return 56; - total += itf56.CallMe (56); - - mrp.CanCastToCalled = false; - I57 itf57 = (I57)o; - if (!mrp.CanCastToCalled) - return 57; - total += itf57.CallMe (57); - mrp.CanCastToCalled = false; - itf57 = (I57)o; - if (mrp.CanCastToCalled) - return 57; - total += itf57.CallMe (57); - - mrp.CanCastToCalled = false; - I58 itf58 = (I58)o; - if (!mrp.CanCastToCalled) - return 58; - total += itf58.CallMe (58); - mrp.CanCastToCalled = false; - itf58 = (I58)o; - if (mrp.CanCastToCalled) - return 58; - total += itf58.CallMe (58); - - mrp.CanCastToCalled = false; - I59 itf59 = (I59)o; - if (!mrp.CanCastToCalled) - return 59; - total += itf59.CallMe (59); - mrp.CanCastToCalled = false; - itf59 = (I59)o; - if (mrp.CanCastToCalled) - return 59; - total += itf59.CallMe (59); - - mrp.CanCastToCalled = false; - I60 itf60 = (I60)o; - if (!mrp.CanCastToCalled) - return 60; - total += itf60.CallMe (60); - mrp.CanCastToCalled = false; - itf60 = (I60)o; - if (mrp.CanCastToCalled) - return 60; - total += itf60.CallMe (60); - - mrp.CanCastToCalled = false; - I61 itf61 = (I61)o; - if (!mrp.CanCastToCalled) - return 61; - total += itf61.CallMe (61); - mrp.CanCastToCalled = false; - itf61 = (I61)o; - if (mrp.CanCastToCalled) - return 61; - total += itf61.CallMe (61); - - mrp.CanCastToCalled = false; - I62 itf62 = (I62)o; - if (!mrp.CanCastToCalled) - return 62; - total += itf62.CallMe (62); - mrp.CanCastToCalled = false; - itf62 = (I62)o; - if (mrp.CanCastToCalled) - return 62; - total += itf62.CallMe (62); - - mrp.CanCastToCalled = false; - I63 itf63 = (I63)o; - if (!mrp.CanCastToCalled) - return 63; - total += itf63.CallMe (63); - mrp.CanCastToCalled = false; - itf63 = (I63)o; - if (mrp.CanCastToCalled) - return 63; - total += itf63.CallMe (63); - - mrp.CanCastToCalled = false; - I64 itf64 = (I64)o; - if (!mrp.CanCastToCalled) - return 64; - total += itf64.CallMe (64); - mrp.CanCastToCalled = false; - itf64 = (I64)o; - if (mrp.CanCastToCalled) - return 64; - total += itf64.CallMe (64); - - mrp.CanCastToCalled = false; - I65 itf65 = (I65)o; - if (!mrp.CanCastToCalled) - return 65; - total += itf65.CallMe (65); - mrp.CanCastToCalled = false; - itf65 = (I65)o; - if (mrp.CanCastToCalled) - return 65; - total += itf65.CallMe (65); - - mrp.CanCastToCalled = false; - I66 itf66 = (I66)o; - if (!mrp.CanCastToCalled) - return 66; - total += itf66.CallMe (66); - mrp.CanCastToCalled = false; - itf66 = (I66)o; - if (mrp.CanCastToCalled) - return 66; - total += itf66.CallMe (66); - - mrp.CanCastToCalled = false; - I67 itf67 = (I67)o; - if (!mrp.CanCastToCalled) - return 67; - total += itf67.CallMe (67); - mrp.CanCastToCalled = false; - itf67 = (I67)o; - if (mrp.CanCastToCalled) - return 67; - total += itf67.CallMe (67); - - mrp.CanCastToCalled = false; - I68 itf68 = (I68)o; - if (!mrp.CanCastToCalled) - return 68; - total += itf68.CallMe (68); - mrp.CanCastToCalled = false; - itf68 = (I68)o; - if (mrp.CanCastToCalled) - return 68; - total += itf68.CallMe (68); - - mrp.CanCastToCalled = false; - I69 itf69 = (I69)o; - if (!mrp.CanCastToCalled) - return 69; - total += itf69.CallMe (69); - mrp.CanCastToCalled = false; - itf69 = (I69)o; - if (mrp.CanCastToCalled) - return 69; - total += itf69.CallMe (69); - - mrp.CanCastToCalled = false; - I70 itf70 = (I70)o; - if (!mrp.CanCastToCalled) - return 70; - total += itf70.CallMe (70); - mrp.CanCastToCalled = false; - itf70 = (I70)o; - if (mrp.CanCastToCalled) - return 70; - total += itf70.CallMe (70); - - mrp.CanCastToCalled = false; - I71 itf71 = (I71)o; - if (!mrp.CanCastToCalled) - return 71; - total += itf71.CallMe (71); - mrp.CanCastToCalled = false; - itf71 = (I71)o; - if (mrp.CanCastToCalled) - return 71; - total += itf71.CallMe (71); - - mrp.CanCastToCalled = false; - I72 itf72 = (I72)o; - if (!mrp.CanCastToCalled) - return 72; - total += itf72.CallMe (72); - mrp.CanCastToCalled = false; - itf72 = (I72)o; - if (mrp.CanCastToCalled) - return 72; - total += itf72.CallMe (72); - - mrp.CanCastToCalled = false; - I73 itf73 = (I73)o; - if (!mrp.CanCastToCalled) - return 73; - total += itf73.CallMe (73); - mrp.CanCastToCalled = false; - itf73 = (I73)o; - if (mrp.CanCastToCalled) - return 73; - total += itf73.CallMe (73); - - mrp.CanCastToCalled = false; - I74 itf74 = (I74)o; - if (!mrp.CanCastToCalled) - return 74; - total += itf74.CallMe (74); - mrp.CanCastToCalled = false; - itf74 = (I74)o; - if (mrp.CanCastToCalled) - return 74; - total += itf74.CallMe (74); - - mrp.CanCastToCalled = false; - I75 itf75 = (I75)o; - if (!mrp.CanCastToCalled) - return 75; - total += itf75.CallMe (75); - mrp.CanCastToCalled = false; - itf75 = (I75)o; - if (mrp.CanCastToCalled) - return 75; - total += itf75.CallMe (75); - - mrp.CanCastToCalled = false; - I76 itf76 = (I76)o; - if (!mrp.CanCastToCalled) - return 76; - total += itf76.CallMe (76); - mrp.CanCastToCalled = false; - itf76 = (I76)o; - if (mrp.CanCastToCalled) - return 76; - total += itf76.CallMe (76); - - mrp.CanCastToCalled = false; - I77 itf77 = (I77)o; - if (!mrp.CanCastToCalled) - return 77; - total += itf77.CallMe (77); - mrp.CanCastToCalled = false; - itf77 = (I77)o; - if (mrp.CanCastToCalled) - return 77; - total += itf77.CallMe (77); - - mrp.CanCastToCalled = false; - I78 itf78 = (I78)o; - if (!mrp.CanCastToCalled) - return 78; - total += itf78.CallMe (78); - mrp.CanCastToCalled = false; - itf78 = (I78)o; - if (mrp.CanCastToCalled) - return 78; - total += itf78.CallMe (78); - - mrp.CanCastToCalled = false; - I79 itf79 = (I79)o; - if (!mrp.CanCastToCalled) - return 79; - total += itf79.CallMe (79); - mrp.CanCastToCalled = false; - itf79 = (I79)o; - if (mrp.CanCastToCalled) - return 79; - total += itf79.CallMe (79); - - mrp.CanCastToCalled = false; - I80 itf80 = (I80)o; - if (!mrp.CanCastToCalled) - return 80; - total += itf80.CallMe (80); - mrp.CanCastToCalled = false; - itf80 = (I80)o; - if (mrp.CanCastToCalled) - return 80; - total += itf80.CallMe (80); - - mrp.CanCastToCalled = false; - I81 itf81 = (I81)o; - if (!mrp.CanCastToCalled) - return 81; - total += itf81.CallMe (81); - mrp.CanCastToCalled = false; - itf81 = (I81)o; - if (mrp.CanCastToCalled) - return 81; - total += itf81.CallMe (81); - - mrp.CanCastToCalled = false; - I82 itf82 = (I82)o; - if (!mrp.CanCastToCalled) - return 82; - total += itf82.CallMe (82); - mrp.CanCastToCalled = false; - itf82 = (I82)o; - if (mrp.CanCastToCalled) - return 82; - total += itf82.CallMe (82); - - mrp.CanCastToCalled = false; - I83 itf83 = (I83)o; - if (!mrp.CanCastToCalled) - return 83; - total += itf83.CallMe (83); - mrp.CanCastToCalled = false; - itf83 = (I83)o; - if (mrp.CanCastToCalled) - return 83; - total += itf83.CallMe (83); - - mrp.CanCastToCalled = false; - I84 itf84 = (I84)o; - if (!mrp.CanCastToCalled) - return 84; - total += itf84.CallMe (84); - mrp.CanCastToCalled = false; - itf84 = (I84)o; - if (mrp.CanCastToCalled) - return 84; - total += itf84.CallMe (84); - - mrp.CanCastToCalled = false; - I85 itf85 = (I85)o; - if (!mrp.CanCastToCalled) - return 85; - total += itf85.CallMe (85); - mrp.CanCastToCalled = false; - itf85 = (I85)o; - if (mrp.CanCastToCalled) - return 85; - total += itf85.CallMe (85); - - mrp.CanCastToCalled = false; - I86 itf86 = (I86)o; - if (!mrp.CanCastToCalled) - return 86; - total += itf86.CallMe (86); - mrp.CanCastToCalled = false; - itf86 = (I86)o; - if (mrp.CanCastToCalled) - return 86; - total += itf86.CallMe (86); - - mrp.CanCastToCalled = false; - I87 itf87 = (I87)o; - if (!mrp.CanCastToCalled) - return 87; - total += itf87.CallMe (87); - mrp.CanCastToCalled = false; - itf87 = (I87)o; - if (mrp.CanCastToCalled) - return 87; - total += itf87.CallMe (87); - - mrp.CanCastToCalled = false; - I88 itf88 = (I88)o; - if (!mrp.CanCastToCalled) - return 88; - total += itf88.CallMe (88); - mrp.CanCastToCalled = false; - itf88 = (I88)o; - if (mrp.CanCastToCalled) - return 88; - total += itf88.CallMe (88); - - mrp.CanCastToCalled = false; - I89 itf89 = (I89)o; - if (!mrp.CanCastToCalled) - return 89; - total += itf89.CallMe (89); - mrp.CanCastToCalled = false; - itf89 = (I89)o; - if (mrp.CanCastToCalled) - return 89; - total += itf89.CallMe (89); - - mrp.CanCastToCalled = false; - I90 itf90 = (I90)o; - if (!mrp.CanCastToCalled) - return 90; - total += itf90.CallMe (90); - mrp.CanCastToCalled = false; - itf90 = (I90)o; - if (mrp.CanCastToCalled) - return 90; - total += itf90.CallMe (90); - - mrp.CanCastToCalled = false; - I91 itf91 = (I91)o; - if (!mrp.CanCastToCalled) - return 91; - total += itf91.CallMe (91); - mrp.CanCastToCalled = false; - itf91 = (I91)o; - if (mrp.CanCastToCalled) - return 91; - total += itf91.CallMe (91); - - mrp.CanCastToCalled = false; - I92 itf92 = (I92)o; - if (!mrp.CanCastToCalled) - return 92; - total += itf92.CallMe (92); - mrp.CanCastToCalled = false; - itf92 = (I92)o; - if (mrp.CanCastToCalled) - return 92; - total += itf92.CallMe (92); - - mrp.CanCastToCalled = false; - I93 itf93 = (I93)o; - if (!mrp.CanCastToCalled) - return 93; - total += itf93.CallMe (93); - mrp.CanCastToCalled = false; - itf93 = (I93)o; - if (mrp.CanCastToCalled) - return 93; - total += itf93.CallMe (93); - - mrp.CanCastToCalled = false; - I94 itf94 = (I94)o; - if (!mrp.CanCastToCalled) - return 94; - total += itf94.CallMe (94); - mrp.CanCastToCalled = false; - itf94 = (I94)o; - if (mrp.CanCastToCalled) - return 94; - total += itf94.CallMe (94); - - mrp.CanCastToCalled = false; - I95 itf95 = (I95)o; - if (!mrp.CanCastToCalled) - return 95; - total += itf95.CallMe (95); - mrp.CanCastToCalled = false; - itf95 = (I95)o; - if (mrp.CanCastToCalled) - return 95; - total += itf95.CallMe (95); - - mrp.CanCastToCalled = false; - I96 itf96 = (I96)o; - if (!mrp.CanCastToCalled) - return 96; - total += itf96.CallMe (96); - mrp.CanCastToCalled = false; - itf96 = (I96)o; - if (mrp.CanCastToCalled) - return 96; - total += itf96.CallMe (96); - - mrp.CanCastToCalled = false; - I97 itf97 = (I97)o; - if (!mrp.CanCastToCalled) - return 97; - total += itf97.CallMe (97); - mrp.CanCastToCalled = false; - itf97 = (I97)o; - if (mrp.CanCastToCalled) - return 97; - total += itf97.CallMe (97); - - mrp.CanCastToCalled = false; - I98 itf98 = (I98)o; - if (!mrp.CanCastToCalled) - return 98; - total += itf98.CallMe (98); - mrp.CanCastToCalled = false; - itf98 = (I98)o; - if (mrp.CanCastToCalled) - return 98; - total += itf98.CallMe (98); - - mrp.CanCastToCalled = false; - I99 itf99 = (I99)o; - if (!mrp.CanCastToCalled) - return 99; - total += itf99.CallMe (99); - mrp.CanCastToCalled = false; - itf99 = (I99)o; - if (mrp.CanCastToCalled) - return 99; - total += itf99.CallMe (99); - - mrp.CanCastToCalled = false; - I100 itf100 = (I100)o; - if (!mrp.CanCastToCalled) - return 100; - total += itf100.CallMe (100); - mrp.CanCastToCalled = false; - itf100 = (I100)o; - if (mrp.CanCastToCalled) - return 100; - total += itf100.CallMe (100); - - mrp.CanCastToCalled = false; - I101 itf101 = (I101)o; - if (!mrp.CanCastToCalled) - return 101; - total += itf101.CallMe (101); - mrp.CanCastToCalled = false; - itf101 = (I101)o; - if (mrp.CanCastToCalled) - return 101; - total += itf101.CallMe (101); - - mrp.CanCastToCalled = false; - I102 itf102 = (I102)o; - if (!mrp.CanCastToCalled) - return 102; - total += itf102.CallMe (102); - mrp.CanCastToCalled = false; - itf102 = (I102)o; - if (mrp.CanCastToCalled) - return 102; - total += itf102.CallMe (102); - - mrp.CanCastToCalled = false; - I103 itf103 = (I103)o; - if (!mrp.CanCastToCalled) - return 103; - total += itf103.CallMe (103); - mrp.CanCastToCalled = false; - itf103 = (I103)o; - if (mrp.CanCastToCalled) - return 103; - total += itf103.CallMe (103); - - mrp.CanCastToCalled = false; - I104 itf104 = (I104)o; - if (!mrp.CanCastToCalled) - return 104; - total += itf104.CallMe (104); - mrp.CanCastToCalled = false; - itf104 = (I104)o; - if (mrp.CanCastToCalled) - return 104; - total += itf104.CallMe (104); - - mrp.CanCastToCalled = false; - I105 itf105 = (I105)o; - if (!mrp.CanCastToCalled) - return 105; - total += itf105.CallMe (105); - mrp.CanCastToCalled = false; - itf105 = (I105)o; - if (mrp.CanCastToCalled) - return 105; - total += itf105.CallMe (105); - - mrp.CanCastToCalled = false; - I106 itf106 = (I106)o; - if (!mrp.CanCastToCalled) - return 106; - total += itf106.CallMe (106); - mrp.CanCastToCalled = false; - itf106 = (I106)o; - if (mrp.CanCastToCalled) - return 106; - total += itf106.CallMe (106); - - mrp.CanCastToCalled = false; - I107 itf107 = (I107)o; - if (!mrp.CanCastToCalled) - return 107; - total += itf107.CallMe (107); - mrp.CanCastToCalled = false; - itf107 = (I107)o; - if (mrp.CanCastToCalled) - return 107; - total += itf107.CallMe (107); - - mrp.CanCastToCalled = false; - I108 itf108 = (I108)o; - if (!mrp.CanCastToCalled) - return 108; - total += itf108.CallMe (108); - mrp.CanCastToCalled = false; - itf108 = (I108)o; - if (mrp.CanCastToCalled) - return 108; - total += itf108.CallMe (108); - - mrp.CanCastToCalled = false; - I109 itf109 = (I109)o; - if (!mrp.CanCastToCalled) - return 109; - total += itf109.CallMe (109); - mrp.CanCastToCalled = false; - itf109 = (I109)o; - if (mrp.CanCastToCalled) - return 109; - total += itf109.CallMe (109); - - mrp.CanCastToCalled = false; - I110 itf110 = (I110)o; - if (!mrp.CanCastToCalled) - return 110; - total += itf110.CallMe (110); - mrp.CanCastToCalled = false; - itf110 = (I110)o; - if (mrp.CanCastToCalled) - return 110; - total += itf110.CallMe (110); - - mrp.CanCastToCalled = false; - I111 itf111 = (I111)o; - if (!mrp.CanCastToCalled) - return 111; - total += itf111.CallMe (111); - mrp.CanCastToCalled = false; - itf111 = (I111)o; - if (mrp.CanCastToCalled) - return 111; - total += itf111.CallMe (111); - - mrp.CanCastToCalled = false; - I112 itf112 = (I112)o; - if (!mrp.CanCastToCalled) - return 112; - total += itf112.CallMe (112); - mrp.CanCastToCalled = false; - itf112 = (I112)o; - if (mrp.CanCastToCalled) - return 112; - total += itf112.CallMe (112); - - mrp.CanCastToCalled = false; - I113 itf113 = (I113)o; - if (!mrp.CanCastToCalled) - return 113; - total += itf113.CallMe (113); - mrp.CanCastToCalled = false; - itf113 = (I113)o; - if (mrp.CanCastToCalled) - return 113; - total += itf113.CallMe (113); - - mrp.CanCastToCalled = false; - I114 itf114 = (I114)o; - if (!mrp.CanCastToCalled) - return 114; - total += itf114.CallMe (114); - mrp.CanCastToCalled = false; - itf114 = (I114)o; - if (mrp.CanCastToCalled) - return 114; - total += itf114.CallMe (114); - - mrp.CanCastToCalled = false; - I115 itf115 = (I115)o; - if (!mrp.CanCastToCalled) - return 115; - total += itf115.CallMe (115); - mrp.CanCastToCalled = false; - itf115 = (I115)o; - if (mrp.CanCastToCalled) - return 115; - total += itf115.CallMe (115); - - mrp.CanCastToCalled = false; - I116 itf116 = (I116)o; - if (!mrp.CanCastToCalled) - return 116; - total += itf116.CallMe (116); - mrp.CanCastToCalled = false; - itf116 = (I116)o; - if (mrp.CanCastToCalled) - return 116; - total += itf116.CallMe (116); - - mrp.CanCastToCalled = false; - I117 itf117 = (I117)o; - if (!mrp.CanCastToCalled) - return 117; - total += itf117.CallMe (117); - mrp.CanCastToCalled = false; - itf117 = (I117)o; - if (mrp.CanCastToCalled) - return 117; - total += itf117.CallMe (117); - - mrp.CanCastToCalled = false; - I118 itf118 = (I118)o; - if (!mrp.CanCastToCalled) - return 118; - total += itf118.CallMe (118); - mrp.CanCastToCalled = false; - itf118 = (I118)o; - if (mrp.CanCastToCalled) - return 118; - total += itf118.CallMe (118); - - mrp.CanCastToCalled = false; - I119 itf119 = (I119)o; - if (!mrp.CanCastToCalled) - return 119; - total += itf119.CallMe (119); - mrp.CanCastToCalled = false; - itf119 = (I119)o; - if (mrp.CanCastToCalled) - return 119; - total += itf119.CallMe (119); - - mrp.CanCastToCalled = false; - I120 itf120 = (I120)o; - if (!mrp.CanCastToCalled) - return 120; - total += itf120.CallMe (120); - mrp.CanCastToCalled = false; - itf120 = (I120)o; - if (mrp.CanCastToCalled) - return 120; - total += itf120.CallMe (120); - - mrp.CanCastToCalled = false; - I121 itf121 = (I121)o; - if (!mrp.CanCastToCalled) - return 121; - total += itf121.CallMe (121); - mrp.CanCastToCalled = false; - itf121 = (I121)o; - if (mrp.CanCastToCalled) - return 121; - total += itf121.CallMe (121); - - mrp.CanCastToCalled = false; - I122 itf122 = (I122)o; - if (!mrp.CanCastToCalled) - return 122; - total += itf122.CallMe (122); - mrp.CanCastToCalled = false; - itf122 = (I122)o; - if (mrp.CanCastToCalled) - return 122; - total += itf122.CallMe (122); - - mrp.CanCastToCalled = false; - I123 itf123 = (I123)o; - if (!mrp.CanCastToCalled) - return 123; - total += itf123.CallMe (123); - mrp.CanCastToCalled = false; - itf123 = (I123)o; - if (mrp.CanCastToCalled) - return 123; - total += itf123.CallMe (123); - - mrp.CanCastToCalled = false; - I124 itf124 = (I124)o; - if (!mrp.CanCastToCalled) - return 124; - total += itf124.CallMe (124); - mrp.CanCastToCalled = false; - itf124 = (I124)o; - if (mrp.CanCastToCalled) - return 124; - total += itf124.CallMe (124); - - mrp.CanCastToCalled = false; - I125 itf125 = (I125)o; - if (!mrp.CanCastToCalled) - return 125; - total += itf125.CallMe (125); - mrp.CanCastToCalled = false; - itf125 = (I125)o; - if (mrp.CanCastToCalled) - return 125; - total += itf125.CallMe (125); - - mrp.CanCastToCalled = false; - I126 itf126 = (I126)o; - if (!mrp.CanCastToCalled) - return 126; - total += itf126.CallMe (126); - mrp.CanCastToCalled = false; - itf126 = (I126)o; - if (mrp.CanCastToCalled) - return 126; - total += itf126.CallMe (126); - - mrp.CanCastToCalled = false; - I127 itf127 = (I127)o; - if (!mrp.CanCastToCalled) - return 127; - total += itf127.CallMe (127); - mrp.CanCastToCalled = false; - itf127 = (I127)o; - if (mrp.CanCastToCalled) - return 127; - total += itf127.CallMe (127); - - mrp.CanCastToCalled = false; - I128 itf128 = (I128)o; - if (!mrp.CanCastToCalled) - return 128; - total += itf128.CallMe (128); - mrp.CanCastToCalled = false; - itf128 = (I128)o; - if (mrp.CanCastToCalled) - return 128; - total += itf128.CallMe (128); - - mrp.CanCastToCalled = false; - I129 itf129 = (I129)o; - if (!mrp.CanCastToCalled) - return 129; - total += itf129.CallMe (129); - mrp.CanCastToCalled = false; - itf129 = (I129)o; - if (mrp.CanCastToCalled) - return 129; - total += itf129.CallMe (129); - - mrp.CanCastToCalled = false; - I130 itf130 = (I130)o; - if (!mrp.CanCastToCalled) - return 130; - total += itf130.CallMe (130); - mrp.CanCastToCalled = false; - itf130 = (I130)o; - if (mrp.CanCastToCalled) - return 130; - total += itf130.CallMe (130); - - mrp.CanCastToCalled = false; - I131 itf131 = (I131)o; - if (!mrp.CanCastToCalled) - return 131; - total += itf131.CallMe (131); - mrp.CanCastToCalled = false; - itf131 = (I131)o; - if (mrp.CanCastToCalled) - return 131; - total += itf131.CallMe (131); - - mrp.CanCastToCalled = false; - I132 itf132 = (I132)o; - if (!mrp.CanCastToCalled) - return 132; - total += itf132.CallMe (132); - mrp.CanCastToCalled = false; - itf132 = (I132)o; - if (mrp.CanCastToCalled) - return 132; - total += itf132.CallMe (132); - - mrp.CanCastToCalled = false; - I133 itf133 = (I133)o; - if (!mrp.CanCastToCalled) - return 133; - total += itf133.CallMe (133); - mrp.CanCastToCalled = false; - itf133 = (I133)o; - if (mrp.CanCastToCalled) - return 133; - total += itf133.CallMe (133); - - mrp.CanCastToCalled = false; - I134 itf134 = (I134)o; - if (!mrp.CanCastToCalled) - return 134; - total += itf134.CallMe (134); - mrp.CanCastToCalled = false; - itf134 = (I134)o; - if (mrp.CanCastToCalled) - return 134; - total += itf134.CallMe (134); - - mrp.CanCastToCalled = false; - I135 itf135 = (I135)o; - if (!mrp.CanCastToCalled) - return 135; - total += itf135.CallMe (135); - mrp.CanCastToCalled = false; - itf135 = (I135)o; - if (mrp.CanCastToCalled) - return 135; - total += itf135.CallMe (135); - - mrp.CanCastToCalled = false; - I136 itf136 = (I136)o; - if (!mrp.CanCastToCalled) - return 136; - total += itf136.CallMe (136); - mrp.CanCastToCalled = false; - itf136 = (I136)o; - if (mrp.CanCastToCalled) - return 136; - total += itf136.CallMe (136); - - mrp.CanCastToCalled = false; - I137 itf137 = (I137)o; - if (!mrp.CanCastToCalled) - return 137; - total += itf137.CallMe (137); - mrp.CanCastToCalled = false; - itf137 = (I137)o; - if (mrp.CanCastToCalled) - return 137; - total += itf137.CallMe (137); - - mrp.CanCastToCalled = false; - I138 itf138 = (I138)o; - if (!mrp.CanCastToCalled) - return 138; - total += itf138.CallMe (138); - mrp.CanCastToCalled = false; - itf138 = (I138)o; - if (mrp.CanCastToCalled) - return 138; - total += itf138.CallMe (138); - - mrp.CanCastToCalled = false; - I139 itf139 = (I139)o; - if (!mrp.CanCastToCalled) - return 139; - total += itf139.CallMe (139); - mrp.CanCastToCalled = false; - itf139 = (I139)o; - if (mrp.CanCastToCalled) - return 139; - total += itf139.CallMe (139); - - mrp.CanCastToCalled = false; - I140 itf140 = (I140)o; - if (!mrp.CanCastToCalled) - return 140; - total += itf140.CallMe (140); - mrp.CanCastToCalled = false; - itf140 = (I140)o; - if (mrp.CanCastToCalled) - return 140; - total += itf140.CallMe (140); - - mrp.CanCastToCalled = false; - I141 itf141 = (I141)o; - if (!mrp.CanCastToCalled) - return 141; - total += itf141.CallMe (141); - mrp.CanCastToCalled = false; - itf141 = (I141)o; - if (mrp.CanCastToCalled) - return 141; - total += itf141.CallMe (141); - - mrp.CanCastToCalled = false; - I142 itf142 = (I142)o; - if (!mrp.CanCastToCalled) - return 142; - total += itf142.CallMe (142); - mrp.CanCastToCalled = false; - itf142 = (I142)o; - if (mrp.CanCastToCalled) - return 142; - total += itf142.CallMe (142); - - mrp.CanCastToCalled = false; - I143 itf143 = (I143)o; - if (!mrp.CanCastToCalled) - return 143; - total += itf143.CallMe (143); - mrp.CanCastToCalled = false; - itf143 = (I143)o; - if (mrp.CanCastToCalled) - return 143; - total += itf143.CallMe (143); - - mrp.CanCastToCalled = false; - I144 itf144 = (I144)o; - if (!mrp.CanCastToCalled) - return 144; - total += itf144.CallMe (144); - mrp.CanCastToCalled = false; - itf144 = (I144)o; - if (mrp.CanCastToCalled) - return 144; - total += itf144.CallMe (144); - - mrp.CanCastToCalled = false; - I145 itf145 = (I145)o; - if (!mrp.CanCastToCalled) - return 145; - total += itf145.CallMe (145); - mrp.CanCastToCalled = false; - itf145 = (I145)o; - if (mrp.CanCastToCalled) - return 145; - total += itf145.CallMe (145); - - mrp.CanCastToCalled = false; - I146 itf146 = (I146)o; - if (!mrp.CanCastToCalled) - return 146; - total += itf146.CallMe (146); - mrp.CanCastToCalled = false; - itf146 = (I146)o; - if (mrp.CanCastToCalled) - return 146; - total += itf146.CallMe (146); - - mrp.CanCastToCalled = false; - I147 itf147 = (I147)o; - if (!mrp.CanCastToCalled) - return 147; - total += itf147.CallMe (147); - mrp.CanCastToCalled = false; - itf147 = (I147)o; - if (mrp.CanCastToCalled) - return 147; - total += itf147.CallMe (147); - - mrp.CanCastToCalled = false; - I148 itf148 = (I148)o; - if (!mrp.CanCastToCalled) - return 148; - total += itf148.CallMe (148); - mrp.CanCastToCalled = false; - itf148 = (I148)o; - if (mrp.CanCastToCalled) - return 148; - total += itf148.CallMe (148); - - mrp.CanCastToCalled = false; - I149 itf149 = (I149)o; - if (!mrp.CanCastToCalled) - return 149; - total += itf149.CallMe (149); - mrp.CanCastToCalled = false; - itf149 = (I149)o; - if (mrp.CanCastToCalled) - return 149; - total += itf149.CallMe (149); - - mrp.CanCastToCalled = false; - I150 itf150 = (I150)o; - if (!mrp.CanCastToCalled) - return 150; - total += itf150.CallMe (150); - mrp.CanCastToCalled = false; - itf150 = (I150)o; - if (mrp.CanCastToCalled) - return 150; - total += itf150.CallMe (150); - - mrp.CanCastToCalled = false; - I151 itf151 = (I151)o; - if (!mrp.CanCastToCalled) - return 151; - total += itf151.CallMe (151); - mrp.CanCastToCalled = false; - itf151 = (I151)o; - if (mrp.CanCastToCalled) - return 151; - total += itf151.CallMe (151); - - mrp.CanCastToCalled = false; - I152 itf152 = (I152)o; - if (!mrp.CanCastToCalled) - return 152; - total += itf152.CallMe (152); - mrp.CanCastToCalled = false; - itf152 = (I152)o; - if (mrp.CanCastToCalled) - return 152; - total += itf152.CallMe (152); - - mrp.CanCastToCalled = false; - I153 itf153 = (I153)o; - if (!mrp.CanCastToCalled) - return 153; - total += itf153.CallMe (153); - mrp.CanCastToCalled = false; - itf153 = (I153)o; - if (mrp.CanCastToCalled) - return 153; - total += itf153.CallMe (153); - - mrp.CanCastToCalled = false; - I154 itf154 = (I154)o; - if (!mrp.CanCastToCalled) - return 154; - total += itf154.CallMe (154); - mrp.CanCastToCalled = false; - itf154 = (I154)o; - if (mrp.CanCastToCalled) - return 154; - total += itf154.CallMe (154); - - mrp.CanCastToCalled = false; - I155 itf155 = (I155)o; - if (!mrp.CanCastToCalled) - return 155; - total += itf155.CallMe (155); - mrp.CanCastToCalled = false; - itf155 = (I155)o; - if (mrp.CanCastToCalled) - return 155; - total += itf155.CallMe (155); - - mrp.CanCastToCalled = false; - I156 itf156 = (I156)o; - if (!mrp.CanCastToCalled) - return 156; - total += itf156.CallMe (156); - mrp.CanCastToCalled = false; - itf156 = (I156)o; - if (mrp.CanCastToCalled) - return 156; - total += itf156.CallMe (156); - - mrp.CanCastToCalled = false; - I157 itf157 = (I157)o; - if (!mrp.CanCastToCalled) - return 157; - total += itf157.CallMe (157); - mrp.CanCastToCalled = false; - itf157 = (I157)o; - if (mrp.CanCastToCalled) - return 157; - total += itf157.CallMe (157); - - mrp.CanCastToCalled = false; - I158 itf158 = (I158)o; - if (!mrp.CanCastToCalled) - return 158; - total += itf158.CallMe (158); - mrp.CanCastToCalled = false; - itf158 = (I158)o; - if (mrp.CanCastToCalled) - return 158; - total += itf158.CallMe (158); - - mrp.CanCastToCalled = false; - I159 itf159 = (I159)o; - if (!mrp.CanCastToCalled) - return 159; - total += itf159.CallMe (159); - mrp.CanCastToCalled = false; - itf159 = (I159)o; - if (mrp.CanCastToCalled) - return 159; - total += itf159.CallMe (159); - - mrp.CanCastToCalled = false; - I160 itf160 = (I160)o; - if (!mrp.CanCastToCalled) - return 160; - total += itf160.CallMe (160); - mrp.CanCastToCalled = false; - itf160 = (I160)o; - if (mrp.CanCastToCalled) - return 160; - total += itf160.CallMe (160); - - mrp.CanCastToCalled = false; - I161 itf161 = (I161)o; - if (!mrp.CanCastToCalled) - return 161; - total += itf161.CallMe (161); - mrp.CanCastToCalled = false; - itf161 = (I161)o; - if (mrp.CanCastToCalled) - return 161; - total += itf161.CallMe (161); - - mrp.CanCastToCalled = false; - I162 itf162 = (I162)o; - if (!mrp.CanCastToCalled) - return 162; - total += itf162.CallMe (162); - mrp.CanCastToCalled = false; - itf162 = (I162)o; - if (mrp.CanCastToCalled) - return 162; - total += itf162.CallMe (162); - - mrp.CanCastToCalled = false; - I163 itf163 = (I163)o; - if (!mrp.CanCastToCalled) - return 163; - total += itf163.CallMe (163); - mrp.CanCastToCalled = false; - itf163 = (I163)o; - if (mrp.CanCastToCalled) - return 163; - total += itf163.CallMe (163); - - mrp.CanCastToCalled = false; - I164 itf164 = (I164)o; - if (!mrp.CanCastToCalled) - return 164; - total += itf164.CallMe (164); - mrp.CanCastToCalled = false; - itf164 = (I164)o; - if (mrp.CanCastToCalled) - return 164; - total += itf164.CallMe (164); - - mrp.CanCastToCalled = false; - I165 itf165 = (I165)o; - if (!mrp.CanCastToCalled) - return 165; - total += itf165.CallMe (165); - mrp.CanCastToCalled = false; - itf165 = (I165)o; - if (mrp.CanCastToCalled) - return 165; - total += itf165.CallMe (165); - - mrp.CanCastToCalled = false; - I166 itf166 = (I166)o; - if (!mrp.CanCastToCalled) - return 166; - total += itf166.CallMe (166); - mrp.CanCastToCalled = false; - itf166 = (I166)o; - if (mrp.CanCastToCalled) - return 166; - total += itf166.CallMe (166); - - mrp.CanCastToCalled = false; - I167 itf167 = (I167)o; - if (!mrp.CanCastToCalled) - return 167; - total += itf167.CallMe (167); - mrp.CanCastToCalled = false; - itf167 = (I167)o; - if (mrp.CanCastToCalled) - return 167; - total += itf167.CallMe (167); - - mrp.CanCastToCalled = false; - I168 itf168 = (I168)o; - if (!mrp.CanCastToCalled) - return 168; - total += itf168.CallMe (168); - mrp.CanCastToCalled = false; - itf168 = (I168)o; - if (mrp.CanCastToCalled) - return 168; - total += itf168.CallMe (168); - - mrp.CanCastToCalled = false; - I169 itf169 = (I169)o; - if (!mrp.CanCastToCalled) - return 169; - total += itf169.CallMe (169); - mrp.CanCastToCalled = false; - itf169 = (I169)o; - if (mrp.CanCastToCalled) - return 169; - total += itf169.CallMe (169); - - mrp.CanCastToCalled = false; - I170 itf170 = (I170)o; - if (!mrp.CanCastToCalled) - return 170; - total += itf170.CallMe (170); - mrp.CanCastToCalled = false; - itf170 = (I170)o; - if (mrp.CanCastToCalled) - return 170; - total += itf170.CallMe (170); - - mrp.CanCastToCalled = false; - I171 itf171 = (I171)o; - if (!mrp.CanCastToCalled) - return 171; - total += itf171.CallMe (171); - mrp.CanCastToCalled = false; - itf171 = (I171)o; - if (mrp.CanCastToCalled) - return 171; - total += itf171.CallMe (171); - - mrp.CanCastToCalled = false; - I172 itf172 = (I172)o; - if (!mrp.CanCastToCalled) - return 172; - total += itf172.CallMe (172); - mrp.CanCastToCalled = false; - itf172 = (I172)o; - if (mrp.CanCastToCalled) - return 172; - total += itf172.CallMe (172); - - mrp.CanCastToCalled = false; - I173 itf173 = (I173)o; - if (!mrp.CanCastToCalled) - return 173; - total += itf173.CallMe (173); - mrp.CanCastToCalled = false; - itf173 = (I173)o; - if (mrp.CanCastToCalled) - return 173; - total += itf173.CallMe (173); - - mrp.CanCastToCalled = false; - I174 itf174 = (I174)o; - if (!mrp.CanCastToCalled) - return 174; - total += itf174.CallMe (174); - mrp.CanCastToCalled = false; - itf174 = (I174)o; - if (mrp.CanCastToCalled) - return 174; - total += itf174.CallMe (174); - - mrp.CanCastToCalled = false; - I175 itf175 = (I175)o; - if (!mrp.CanCastToCalled) - return 175; - total += itf175.CallMe (175); - mrp.CanCastToCalled = false; - itf175 = (I175)o; - if (mrp.CanCastToCalled) - return 175; - total += itf175.CallMe (175); - - mrp.CanCastToCalled = false; - I176 itf176 = (I176)o; - if (!mrp.CanCastToCalled) - return 176; - total += itf176.CallMe (176); - mrp.CanCastToCalled = false; - itf176 = (I176)o; - if (mrp.CanCastToCalled) - return 176; - total += itf176.CallMe (176); - - mrp.CanCastToCalled = false; - I177 itf177 = (I177)o; - if (!mrp.CanCastToCalled) - return 177; - total += itf177.CallMe (177); - mrp.CanCastToCalled = false; - itf177 = (I177)o; - if (mrp.CanCastToCalled) - return 177; - total += itf177.CallMe (177); - - mrp.CanCastToCalled = false; - I178 itf178 = (I178)o; - if (!mrp.CanCastToCalled) - return 178; - total += itf178.CallMe (178); - mrp.CanCastToCalled = false; - itf178 = (I178)o; - if (mrp.CanCastToCalled) - return 178; - total += itf178.CallMe (178); - - mrp.CanCastToCalled = false; - I179 itf179 = (I179)o; - if (!mrp.CanCastToCalled) - return 179; - total += itf179.CallMe (179); - mrp.CanCastToCalled = false; - itf179 = (I179)o; - if (mrp.CanCastToCalled) - return 179; - total += itf179.CallMe (179); - - mrp.CanCastToCalled = false; - I180 itf180 = (I180)o; - if (!mrp.CanCastToCalled) - return 180; - total += itf180.CallMe (180); - mrp.CanCastToCalled = false; - itf180 = (I180)o; - if (mrp.CanCastToCalled) - return 180; - total += itf180.CallMe (180); - - mrp.CanCastToCalled = false; - I181 itf181 = (I181)o; - if (!mrp.CanCastToCalled) - return 181; - total += itf181.CallMe (181); - mrp.CanCastToCalled = false; - itf181 = (I181)o; - if (mrp.CanCastToCalled) - return 181; - total += itf181.CallMe (181); - - mrp.CanCastToCalled = false; - I182 itf182 = (I182)o; - if (!mrp.CanCastToCalled) - return 182; - total += itf182.CallMe (182); - mrp.CanCastToCalled = false; - itf182 = (I182)o; - if (mrp.CanCastToCalled) - return 182; - total += itf182.CallMe (182); - - mrp.CanCastToCalled = false; - I183 itf183 = (I183)o; - if (!mrp.CanCastToCalled) - return 183; - total += itf183.CallMe (183); - mrp.CanCastToCalled = false; - itf183 = (I183)o; - if (mrp.CanCastToCalled) - return 183; - total += itf183.CallMe (183); - - mrp.CanCastToCalled = false; - I184 itf184 = (I184)o; - if (!mrp.CanCastToCalled) - return 184; - total += itf184.CallMe (184); - mrp.CanCastToCalled = false; - itf184 = (I184)o; - if (mrp.CanCastToCalled) - return 184; - total += itf184.CallMe (184); - - mrp.CanCastToCalled = false; - I185 itf185 = (I185)o; - if (!mrp.CanCastToCalled) - return 185; - total += itf185.CallMe (185); - mrp.CanCastToCalled = false; - itf185 = (I185)o; - if (mrp.CanCastToCalled) - return 185; - total += itf185.CallMe (185); - - mrp.CanCastToCalled = false; - I186 itf186 = (I186)o; - if (!mrp.CanCastToCalled) - return 186; - total += itf186.CallMe (186); - mrp.CanCastToCalled = false; - itf186 = (I186)o; - if (mrp.CanCastToCalled) - return 186; - total += itf186.CallMe (186); - - mrp.CanCastToCalled = false; - I187 itf187 = (I187)o; - if (!mrp.CanCastToCalled) - return 187; - total += itf187.CallMe (187); - mrp.CanCastToCalled = false; - itf187 = (I187)o; - if (mrp.CanCastToCalled) - return 187; - total += itf187.CallMe (187); - - mrp.CanCastToCalled = false; - I188 itf188 = (I188)o; - if (!mrp.CanCastToCalled) - return 188; - total += itf188.CallMe (188); - mrp.CanCastToCalled = false; - itf188 = (I188)o; - if (mrp.CanCastToCalled) - return 188; - total += itf188.CallMe (188); - - mrp.CanCastToCalled = false; - I189 itf189 = (I189)o; - if (!mrp.CanCastToCalled) - return 189; - total += itf189.CallMe (189); - mrp.CanCastToCalled = false; - itf189 = (I189)o; - if (mrp.CanCastToCalled) - return 189; - total += itf189.CallMe (189); - - mrp.CanCastToCalled = false; - I190 itf190 = (I190)o; - if (!mrp.CanCastToCalled) - return 190; - total += itf190.CallMe (190); - mrp.CanCastToCalled = false; - itf190 = (I190)o; - if (mrp.CanCastToCalled) - return 190; - total += itf190.CallMe (190); - - mrp.CanCastToCalled = false; - I191 itf191 = (I191)o; - if (!mrp.CanCastToCalled) - return 191; - total += itf191.CallMe (191); - mrp.CanCastToCalled = false; - itf191 = (I191)o; - if (mrp.CanCastToCalled) - return 191; - total += itf191.CallMe (191); - - mrp.CanCastToCalled = false; - I192 itf192 = (I192)o; - if (!mrp.CanCastToCalled) - return 192; - total += itf192.CallMe (192); - mrp.CanCastToCalled = false; - itf192 = (I192)o; - if (mrp.CanCastToCalled) - return 192; - total += itf192.CallMe (192); - - mrp.CanCastToCalled = false; - I193 itf193 = (I193)o; - if (!mrp.CanCastToCalled) - return 193; - total += itf193.CallMe (193); - mrp.CanCastToCalled = false; - itf193 = (I193)o; - if (mrp.CanCastToCalled) - return 193; - total += itf193.CallMe (193); - - mrp.CanCastToCalled = false; - I194 itf194 = (I194)o; - if (!mrp.CanCastToCalled) - return 194; - total += itf194.CallMe (194); - mrp.CanCastToCalled = false; - itf194 = (I194)o; - if (mrp.CanCastToCalled) - return 194; - total += itf194.CallMe (194); - - mrp.CanCastToCalled = false; - I195 itf195 = (I195)o; - if (!mrp.CanCastToCalled) - return 195; - total += itf195.CallMe (195); - mrp.CanCastToCalled = false; - itf195 = (I195)o; - if (mrp.CanCastToCalled) - return 195; - total += itf195.CallMe (195); - - mrp.CanCastToCalled = false; - I196 itf196 = (I196)o; - if (!mrp.CanCastToCalled) - return 196; - total += itf196.CallMe (196); - mrp.CanCastToCalled = false; - itf196 = (I196)o; - if (mrp.CanCastToCalled) - return 196; - total += itf196.CallMe (196); - - mrp.CanCastToCalled = false; - I197 itf197 = (I197)o; - if (!mrp.CanCastToCalled) - return 197; - total += itf197.CallMe (197); - mrp.CanCastToCalled = false; - itf197 = (I197)o; - if (mrp.CanCastToCalled) - return 197; - total += itf197.CallMe (197); - - mrp.CanCastToCalled = false; - I198 itf198 = (I198)o; - if (!mrp.CanCastToCalled) - return 198; - total += itf198.CallMe (198); - mrp.CanCastToCalled = false; - itf198 = (I198)o; - if (mrp.CanCastToCalled) - return 198; - total += itf198.CallMe (198); - - mrp.CanCastToCalled = false; - I199 itf199 = (I199)o; - if (!mrp.CanCastToCalled) - return 199; - total += itf199.CallMe (199); - mrp.CanCastToCalled = false; - itf199 = (I199)o; - if (mrp.CanCastToCalled) - return 199; - total += itf199.CallMe (199); - - mrp.CanCastToCalled = false; - I200 itf200 = (I200)o; - if (!mrp.CanCastToCalled) - return 200; - total += itf200.CallMe (200); - mrp.CanCastToCalled = false; - itf200 = (I200)o; - if (mrp.CanCastToCalled) - return 200; - total += itf200.CallMe (200); - - mrp.CanCastToCalled = false; - I201 itf201 = (I201)o; - if (!mrp.CanCastToCalled) - return 201; - total += itf201.CallMe (201); - mrp.CanCastToCalled = false; - itf201 = (I201)o; - if (mrp.CanCastToCalled) - return 201; - total += itf201.CallMe (201); - - mrp.CanCastToCalled = false; - I202 itf202 = (I202)o; - if (!mrp.CanCastToCalled) - return 202; - total += itf202.CallMe (202); - mrp.CanCastToCalled = false; - itf202 = (I202)o; - if (mrp.CanCastToCalled) - return 202; - total += itf202.CallMe (202); - - mrp.CanCastToCalled = false; - I203 itf203 = (I203)o; - if (!mrp.CanCastToCalled) - return 203; - total += itf203.CallMe (203); - mrp.CanCastToCalled = false; - itf203 = (I203)o; - if (mrp.CanCastToCalled) - return 203; - total += itf203.CallMe (203); - - mrp.CanCastToCalled = false; - I204 itf204 = (I204)o; - if (!mrp.CanCastToCalled) - return 204; - total += itf204.CallMe (204); - mrp.CanCastToCalled = false; - itf204 = (I204)o; - if (mrp.CanCastToCalled) - return 204; - total += itf204.CallMe (204); - - mrp.CanCastToCalled = false; - I205 itf205 = (I205)o; - if (!mrp.CanCastToCalled) - return 205; - total += itf205.CallMe (205); - mrp.CanCastToCalled = false; - itf205 = (I205)o; - if (mrp.CanCastToCalled) - return 205; - total += itf205.CallMe (205); - - mrp.CanCastToCalled = false; - I206 itf206 = (I206)o; - if (!mrp.CanCastToCalled) - return 206; - total += itf206.CallMe (206); - mrp.CanCastToCalled = false; - itf206 = (I206)o; - if (mrp.CanCastToCalled) - return 206; - total += itf206.CallMe (206); - - mrp.CanCastToCalled = false; - I207 itf207 = (I207)o; - if (!mrp.CanCastToCalled) - return 207; - total += itf207.CallMe (207); - mrp.CanCastToCalled = false; - itf207 = (I207)o; - if (mrp.CanCastToCalled) - return 207; - total += itf207.CallMe (207); - - mrp.CanCastToCalled = false; - I208 itf208 = (I208)o; - if (!mrp.CanCastToCalled) - return 208; - total += itf208.CallMe (208); - mrp.CanCastToCalled = false; - itf208 = (I208)o; - if (mrp.CanCastToCalled) - return 208; - total += itf208.CallMe (208); - - mrp.CanCastToCalled = false; - I209 itf209 = (I209)o; - if (!mrp.CanCastToCalled) - return 209; - total += itf209.CallMe (209); - mrp.CanCastToCalled = false; - itf209 = (I209)o; - if (mrp.CanCastToCalled) - return 209; - total += itf209.CallMe (209); - - mrp.CanCastToCalled = false; - I210 itf210 = (I210)o; - if (!mrp.CanCastToCalled) - return 210; - total += itf210.CallMe (210); - mrp.CanCastToCalled = false; - itf210 = (I210)o; - if (mrp.CanCastToCalled) - return 210; - total += itf210.CallMe (210); - - mrp.CanCastToCalled = false; - I211 itf211 = (I211)o; - if (!mrp.CanCastToCalled) - return 211; - total += itf211.CallMe (211); - mrp.CanCastToCalled = false; - itf211 = (I211)o; - if (mrp.CanCastToCalled) - return 211; - total += itf211.CallMe (211); - - mrp.CanCastToCalled = false; - I212 itf212 = (I212)o; - if (!mrp.CanCastToCalled) - return 212; - total += itf212.CallMe (212); - mrp.CanCastToCalled = false; - itf212 = (I212)o; - if (mrp.CanCastToCalled) - return 212; - total += itf212.CallMe (212); - - mrp.CanCastToCalled = false; - I213 itf213 = (I213)o; - if (!mrp.CanCastToCalled) - return 213; - total += itf213.CallMe (213); - mrp.CanCastToCalled = false; - itf213 = (I213)o; - if (mrp.CanCastToCalled) - return 213; - total += itf213.CallMe (213); - - mrp.CanCastToCalled = false; - I214 itf214 = (I214)o; - if (!mrp.CanCastToCalled) - return 214; - total += itf214.CallMe (214); - mrp.CanCastToCalled = false; - itf214 = (I214)o; - if (mrp.CanCastToCalled) - return 214; - total += itf214.CallMe (214); - - mrp.CanCastToCalled = false; - I215 itf215 = (I215)o; - if (!mrp.CanCastToCalled) - return 215; - total += itf215.CallMe (215); - mrp.CanCastToCalled = false; - itf215 = (I215)o; - if (mrp.CanCastToCalled) - return 215; - total += itf215.CallMe (215); - - mrp.CanCastToCalled = false; - I216 itf216 = (I216)o; - if (!mrp.CanCastToCalled) - return 216; - total += itf216.CallMe (216); - mrp.CanCastToCalled = false; - itf216 = (I216)o; - if (mrp.CanCastToCalled) - return 216; - total += itf216.CallMe (216); - - mrp.CanCastToCalled = false; - I217 itf217 = (I217)o; - if (!mrp.CanCastToCalled) - return 217; - total += itf217.CallMe (217); - mrp.CanCastToCalled = false; - itf217 = (I217)o; - if (mrp.CanCastToCalled) - return 217; - total += itf217.CallMe (217); - - mrp.CanCastToCalled = false; - I218 itf218 = (I218)o; - if (!mrp.CanCastToCalled) - return 218; - total += itf218.CallMe (218); - mrp.CanCastToCalled = false; - itf218 = (I218)o; - if (mrp.CanCastToCalled) - return 218; - total += itf218.CallMe (218); - - mrp.CanCastToCalled = false; - I219 itf219 = (I219)o; - if (!mrp.CanCastToCalled) - return 219; - total += itf219.CallMe (219); - mrp.CanCastToCalled = false; - itf219 = (I219)o; - if (mrp.CanCastToCalled) - return 219; - total += itf219.CallMe (219); - - mrp.CanCastToCalled = false; - I220 itf220 = (I220)o; - if (!mrp.CanCastToCalled) - return 220; - total += itf220.CallMe (220); - mrp.CanCastToCalled = false; - itf220 = (I220)o; - if (mrp.CanCastToCalled) - return 220; - total += itf220.CallMe (220); - - mrp.CanCastToCalled = false; - I221 itf221 = (I221)o; - if (!mrp.CanCastToCalled) - return 221; - total += itf221.CallMe (221); - mrp.CanCastToCalled = false; - itf221 = (I221)o; - if (mrp.CanCastToCalled) - return 221; - total += itf221.CallMe (221); - - mrp.CanCastToCalled = false; - I222 itf222 = (I222)o; - if (!mrp.CanCastToCalled) - return 222; - total += itf222.CallMe (222); - mrp.CanCastToCalled = false; - itf222 = (I222)o; - if (mrp.CanCastToCalled) - return 222; - total += itf222.CallMe (222); - - mrp.CanCastToCalled = false; - I223 itf223 = (I223)o; - if (!mrp.CanCastToCalled) - return 223; - total += itf223.CallMe (223); - mrp.CanCastToCalled = false; - itf223 = (I223)o; - if (mrp.CanCastToCalled) - return 223; - total += itf223.CallMe (223); - - mrp.CanCastToCalled = false; - I224 itf224 = (I224)o; - if (!mrp.CanCastToCalled) - return 224; - total += itf224.CallMe (224); - mrp.CanCastToCalled = false; - itf224 = (I224)o; - if (mrp.CanCastToCalled) - return 224; - total += itf224.CallMe (224); - - mrp.CanCastToCalled = false; - I225 itf225 = (I225)o; - if (!mrp.CanCastToCalled) - return 225; - total += itf225.CallMe (225); - mrp.CanCastToCalled = false; - itf225 = (I225)o; - if (mrp.CanCastToCalled) - return 225; - total += itf225.CallMe (225); - - mrp.CanCastToCalled = false; - I226 itf226 = (I226)o; - if (!mrp.CanCastToCalled) - return 226; - total += itf226.CallMe (226); - mrp.CanCastToCalled = false; - itf226 = (I226)o; - if (mrp.CanCastToCalled) - return 226; - total += itf226.CallMe (226); - - mrp.CanCastToCalled = false; - I227 itf227 = (I227)o; - if (!mrp.CanCastToCalled) - return 227; - total += itf227.CallMe (227); - mrp.CanCastToCalled = false; - itf227 = (I227)o; - if (mrp.CanCastToCalled) - return 227; - total += itf227.CallMe (227); - - mrp.CanCastToCalled = false; - I228 itf228 = (I228)o; - if (!mrp.CanCastToCalled) - return 228; - total += itf228.CallMe (228); - mrp.CanCastToCalled = false; - itf228 = (I228)o; - if (mrp.CanCastToCalled) - return 228; - total += itf228.CallMe (228); - - mrp.CanCastToCalled = false; - I229 itf229 = (I229)o; - if (!mrp.CanCastToCalled) - return 229; - total += itf229.CallMe (229); - mrp.CanCastToCalled = false; - itf229 = (I229)o; - if (mrp.CanCastToCalled) - return 229; - total += itf229.CallMe (229); - - mrp.CanCastToCalled = false; - I230 itf230 = (I230)o; - if (!mrp.CanCastToCalled) - return 230; - total += itf230.CallMe (230); - mrp.CanCastToCalled = false; - itf230 = (I230)o; - if (mrp.CanCastToCalled) - return 230; - total += itf230.CallMe (230); - - mrp.CanCastToCalled = false; - I231 itf231 = (I231)o; - if (!mrp.CanCastToCalled) - return 231; - total += itf231.CallMe (231); - mrp.CanCastToCalled = false; - itf231 = (I231)o; - if (mrp.CanCastToCalled) - return 231; - total += itf231.CallMe (231); - - mrp.CanCastToCalled = false; - I232 itf232 = (I232)o; - if (!mrp.CanCastToCalled) - return 232; - total += itf232.CallMe (232); - mrp.CanCastToCalled = false; - itf232 = (I232)o; - if (mrp.CanCastToCalled) - return 232; - total += itf232.CallMe (232); - - mrp.CanCastToCalled = false; - I233 itf233 = (I233)o; - if (!mrp.CanCastToCalled) - return 233; - total += itf233.CallMe (233); - mrp.CanCastToCalled = false; - itf233 = (I233)o; - if (mrp.CanCastToCalled) - return 233; - total += itf233.CallMe (233); - - mrp.CanCastToCalled = false; - I234 itf234 = (I234)o; - if (!mrp.CanCastToCalled) - return 234; - total += itf234.CallMe (234); - mrp.CanCastToCalled = false; - itf234 = (I234)o; - if (mrp.CanCastToCalled) - return 234; - total += itf234.CallMe (234); - - mrp.CanCastToCalled = false; - I235 itf235 = (I235)o; - if (!mrp.CanCastToCalled) - return 235; - total += itf235.CallMe (235); - mrp.CanCastToCalled = false; - itf235 = (I235)o; - if (mrp.CanCastToCalled) - return 235; - total += itf235.CallMe (235); - - mrp.CanCastToCalled = false; - I236 itf236 = (I236)o; - if (!mrp.CanCastToCalled) - return 236; - total += itf236.CallMe (236); - mrp.CanCastToCalled = false; - itf236 = (I236)o; - if (mrp.CanCastToCalled) - return 236; - total += itf236.CallMe (236); - - mrp.CanCastToCalled = false; - I237 itf237 = (I237)o; - if (!mrp.CanCastToCalled) - return 237; - total += itf237.CallMe (237); - mrp.CanCastToCalled = false; - itf237 = (I237)o; - if (mrp.CanCastToCalled) - return 237; - total += itf237.CallMe (237); - - mrp.CanCastToCalled = false; - I238 itf238 = (I238)o; - if (!mrp.CanCastToCalled) - return 238; - total += itf238.CallMe (238); - mrp.CanCastToCalled = false; - itf238 = (I238)o; - if (mrp.CanCastToCalled) - return 238; - total += itf238.CallMe (238); - - mrp.CanCastToCalled = false; - I239 itf239 = (I239)o; - if (!mrp.CanCastToCalled) - return 239; - total += itf239.CallMe (239); - mrp.CanCastToCalled = false; - itf239 = (I239)o; - if (mrp.CanCastToCalled) - return 239; - total += itf239.CallMe (239); - - mrp.CanCastToCalled = false; - I240 itf240 = (I240)o; - if (!mrp.CanCastToCalled) - return 240; - total += itf240.CallMe (240); - mrp.CanCastToCalled = false; - itf240 = (I240)o; - if (mrp.CanCastToCalled) - return 240; - total += itf240.CallMe (240); - - mrp.CanCastToCalled = false; - I241 itf241 = (I241)o; - if (!mrp.CanCastToCalled) - return 241; - total += itf241.CallMe (241); - mrp.CanCastToCalled = false; - itf241 = (I241)o; - if (mrp.CanCastToCalled) - return 241; - total += itf241.CallMe (241); - - mrp.CanCastToCalled = false; - I242 itf242 = (I242)o; - if (!mrp.CanCastToCalled) - return 242; - total += itf242.CallMe (242); - mrp.CanCastToCalled = false; - itf242 = (I242)o; - if (mrp.CanCastToCalled) - return 242; - total += itf242.CallMe (242); - - mrp.CanCastToCalled = false; - I243 itf243 = (I243)o; - if (!mrp.CanCastToCalled) - return 243; - total += itf243.CallMe (243); - mrp.CanCastToCalled = false; - itf243 = (I243)o; - if (mrp.CanCastToCalled) - return 243; - total += itf243.CallMe (243); - - mrp.CanCastToCalled = false; - I244 itf244 = (I244)o; - if (!mrp.CanCastToCalled) - return 244; - total += itf244.CallMe (244); - mrp.CanCastToCalled = false; - itf244 = (I244)o; - if (mrp.CanCastToCalled) - return 244; - total += itf244.CallMe (244); - - mrp.CanCastToCalled = false; - I245 itf245 = (I245)o; - if (!mrp.CanCastToCalled) - return 245; - total += itf245.CallMe (245); - mrp.CanCastToCalled = false; - itf245 = (I245)o; - if (mrp.CanCastToCalled) - return 245; - total += itf245.CallMe (245); - - mrp.CanCastToCalled = false; - I246 itf246 = (I246)o; - if (!mrp.CanCastToCalled) - return 246; - total += itf246.CallMe (246); - mrp.CanCastToCalled = false; - itf246 = (I246)o; - if (mrp.CanCastToCalled) - return 246; - total += itf246.CallMe (246); - - mrp.CanCastToCalled = false; - I247 itf247 = (I247)o; - if (!mrp.CanCastToCalled) - return 247; - total += itf247.CallMe (247); - mrp.CanCastToCalled = false; - itf247 = (I247)o; - if (mrp.CanCastToCalled) - return 247; - total += itf247.CallMe (247); - - mrp.CanCastToCalled = false; - I248 itf248 = (I248)o; - if (!mrp.CanCastToCalled) - return 248; - total += itf248.CallMe (248); - mrp.CanCastToCalled = false; - itf248 = (I248)o; - if (mrp.CanCastToCalled) - return 248; - total += itf248.CallMe (248); - - mrp.CanCastToCalled = false; - I249 itf249 = (I249)o; - if (!mrp.CanCastToCalled) - return 249; - total += itf249.CallMe (249); - mrp.CanCastToCalled = false; - itf249 = (I249)o; - if (mrp.CanCastToCalled) - return 249; - total += itf249.CallMe (249); - - mrp.CanCastToCalled = false; - I250 itf250 = (I250)o; - if (!mrp.CanCastToCalled) - return 250; - total += itf250.CallMe (250); - mrp.CanCastToCalled = false; - itf250 = (I250)o; - if (mrp.CanCastToCalled) - return 250; - total += itf250.CallMe (250); - - mrp.CanCastToCalled = false; - I251 itf251 = (I251)o; - if (!mrp.CanCastToCalled) - return 251; - total += itf251.CallMe (251); - mrp.CanCastToCalled = false; - itf251 = (I251)o; - if (mrp.CanCastToCalled) - return 251; - total += itf251.CallMe (251); - - mrp.CanCastToCalled = false; - I252 itf252 = (I252)o; - if (!mrp.CanCastToCalled) - return 252; - total += itf252.CallMe (252); - mrp.CanCastToCalled = false; - itf252 = (I252)o; - if (mrp.CanCastToCalled) - return 252; - total += itf252.CallMe (252); - - mrp.CanCastToCalled = false; - I253 itf253 = (I253)o; - if (!mrp.CanCastToCalled) - return 253; - total += itf253.CallMe (253); - mrp.CanCastToCalled = false; - itf253 = (I253)o; - if (mrp.CanCastToCalled) - return 253; - total += itf253.CallMe (253); - - mrp.CanCastToCalled = false; - I254 itf254 = (I254)o; - if (!mrp.CanCastToCalled) - return 254; - total += itf254.CallMe (254); - mrp.CanCastToCalled = false; - itf254 = (I254)o; - if (mrp.CanCastToCalled) - return 254; - total += itf254.CallMe (254); - - mrp.CanCastToCalled = false; - I255 itf255 = (I255)o; - if (!mrp.CanCastToCalled) - return 255; - total += itf255.CallMe (255); - mrp.CanCastToCalled = false; - itf255 = (I255)o; - if (mrp.CanCastToCalled) - return 255; - total += itf255.CallMe (255); - - mrp.CanCastToCalled = false; - I256 itf256 = (I256)o; - if (!mrp.CanCastToCalled) - return 256; - total += itf256.CallMe (256); - mrp.CanCastToCalled = false; - itf256 = (I256)o; - if (mrp.CanCastToCalled) - return 256; - total += itf256.CallMe (256); - - mrp.CanCastToCalled = false; - I257 itf257 = (I257)o; - if (!mrp.CanCastToCalled) - return 257; - total += itf257.CallMe (257); - mrp.CanCastToCalled = false; - itf257 = (I257)o; - if (mrp.CanCastToCalled) - return 257; - total += itf257.CallMe (257); - - mrp.CanCastToCalled = false; - I258 itf258 = (I258)o; - if (!mrp.CanCastToCalled) - return 258; - total += itf258.CallMe (258); - mrp.CanCastToCalled = false; - itf258 = (I258)o; - if (mrp.CanCastToCalled) - return 258; - total += itf258.CallMe (258); - - mrp.CanCastToCalled = false; - I259 itf259 = (I259)o; - if (!mrp.CanCastToCalled) - return 259; - total += itf259.CallMe (259); - mrp.CanCastToCalled = false; - itf259 = (I259)o; - if (mrp.CanCastToCalled) - return 259; - total += itf259.CallMe (259); - - mrp.CanCastToCalled = false; - I260 itf260 = (I260)o; - if (!mrp.CanCastToCalled) - return 260; - total += itf260.CallMe (260); - mrp.CanCastToCalled = false; - itf260 = (I260)o; - if (mrp.CanCastToCalled) - return 260; - total += itf260.CallMe (260); - - mrp.CanCastToCalled = false; - I261 itf261 = (I261)o; - if (!mrp.CanCastToCalled) - return 261; - total += itf261.CallMe (261); - mrp.CanCastToCalled = false; - itf261 = (I261)o; - if (mrp.CanCastToCalled) - return 261; - total += itf261.CallMe (261); - - mrp.CanCastToCalled = false; - I262 itf262 = (I262)o; - if (!mrp.CanCastToCalled) - return 262; - total += itf262.CallMe (262); - mrp.CanCastToCalled = false; - itf262 = (I262)o; - if (mrp.CanCastToCalled) - return 262; - total += itf262.CallMe (262); - - mrp.CanCastToCalled = false; - I263 itf263 = (I263)o; - if (!mrp.CanCastToCalled) - return 263; - total += itf263.CallMe (263); - mrp.CanCastToCalled = false; - itf263 = (I263)o; - if (mrp.CanCastToCalled) - return 263; - total += itf263.CallMe (263); - - mrp.CanCastToCalled = false; - I264 itf264 = (I264)o; - if (!mrp.CanCastToCalled) - return 264; - total += itf264.CallMe (264); - mrp.CanCastToCalled = false; - itf264 = (I264)o; - if (mrp.CanCastToCalled) - return 264; - total += itf264.CallMe (264); - - mrp.CanCastToCalled = false; - I265 itf265 = (I265)o; - if (!mrp.CanCastToCalled) - return 265; - total += itf265.CallMe (265); - mrp.CanCastToCalled = false; - itf265 = (I265)o; - if (mrp.CanCastToCalled) - return 265; - total += itf265.CallMe (265); - - mrp.CanCastToCalled = false; - I266 itf266 = (I266)o; - if (!mrp.CanCastToCalled) - return 266; - total += itf266.CallMe (266); - mrp.CanCastToCalled = false; - itf266 = (I266)o; - if (mrp.CanCastToCalled) - return 266; - total += itf266.CallMe (266); - - mrp.CanCastToCalled = false; - I267 itf267 = (I267)o; - if (!mrp.CanCastToCalled) - return 267; - total += itf267.CallMe (267); - mrp.CanCastToCalled = false; - itf267 = (I267)o; - if (mrp.CanCastToCalled) - return 267; - total += itf267.CallMe (267); - - mrp.CanCastToCalled = false; - I268 itf268 = (I268)o; - if (!mrp.CanCastToCalled) - return 268; - total += itf268.CallMe (268); - mrp.CanCastToCalled = false; - itf268 = (I268)o; - if (mrp.CanCastToCalled) - return 268; - total += itf268.CallMe (268); - - mrp.CanCastToCalled = false; - I269 itf269 = (I269)o; - if (!mrp.CanCastToCalled) - return 269; - total += itf269.CallMe (269); - mrp.CanCastToCalled = false; - itf269 = (I269)o; - if (mrp.CanCastToCalled) - return 269; - total += itf269.CallMe (269); - - mrp.CanCastToCalled = false; - I270 itf270 = (I270)o; - if (!mrp.CanCastToCalled) - return 270; - total += itf270.CallMe (270); - mrp.CanCastToCalled = false; - itf270 = (I270)o; - if (mrp.CanCastToCalled) - return 270; - total += itf270.CallMe (270); - - mrp.CanCastToCalled = false; - I271 itf271 = (I271)o; - if (!mrp.CanCastToCalled) - return 271; - total += itf271.CallMe (271); - mrp.CanCastToCalled = false; - itf271 = (I271)o; - if (mrp.CanCastToCalled) - return 271; - total += itf271.CallMe (271); - - mrp.CanCastToCalled = false; - I272 itf272 = (I272)o; - if (!mrp.CanCastToCalled) - return 272; - total += itf272.CallMe (272); - mrp.CanCastToCalled = false; - itf272 = (I272)o; - if (mrp.CanCastToCalled) - return 272; - total += itf272.CallMe (272); - - mrp.CanCastToCalled = false; - I273 itf273 = (I273)o; - if (!mrp.CanCastToCalled) - return 273; - total += itf273.CallMe (273); - mrp.CanCastToCalled = false; - itf273 = (I273)o; - if (mrp.CanCastToCalled) - return 273; - total += itf273.CallMe (273); - - mrp.CanCastToCalled = false; - I274 itf274 = (I274)o; - if (!mrp.CanCastToCalled) - return 274; - total += itf274.CallMe (274); - mrp.CanCastToCalled = false; - itf274 = (I274)o; - if (mrp.CanCastToCalled) - return 274; - total += itf274.CallMe (274); - - mrp.CanCastToCalled = false; - I275 itf275 = (I275)o; - if (!mrp.CanCastToCalled) - return 275; - total += itf275.CallMe (275); - mrp.CanCastToCalled = false; - itf275 = (I275)o; - if (mrp.CanCastToCalled) - return 275; - total += itf275.CallMe (275); - - mrp.CanCastToCalled = false; - I276 itf276 = (I276)o; - if (!mrp.CanCastToCalled) - return 276; - total += itf276.CallMe (276); - mrp.CanCastToCalled = false; - itf276 = (I276)o; - if (mrp.CanCastToCalled) - return 276; - total += itf276.CallMe (276); - - mrp.CanCastToCalled = false; - I277 itf277 = (I277)o; - if (!mrp.CanCastToCalled) - return 277; - total += itf277.CallMe (277); - mrp.CanCastToCalled = false; - itf277 = (I277)o; - if (mrp.CanCastToCalled) - return 277; - total += itf277.CallMe (277); - - mrp.CanCastToCalled = false; - I278 itf278 = (I278)o; - if (!mrp.CanCastToCalled) - return 278; - total += itf278.CallMe (278); - mrp.CanCastToCalled = false; - itf278 = (I278)o; - if (mrp.CanCastToCalled) - return 278; - total += itf278.CallMe (278); - - mrp.CanCastToCalled = false; - I279 itf279 = (I279)o; - if (!mrp.CanCastToCalled) - return 279; - total += itf279.CallMe (279); - mrp.CanCastToCalled = false; - itf279 = (I279)o; - if (mrp.CanCastToCalled) - return 279; - total += itf279.CallMe (279); - - mrp.CanCastToCalled = false; - I280 itf280 = (I280)o; - if (!mrp.CanCastToCalled) - return 280; - total += itf280.CallMe (280); - mrp.CanCastToCalled = false; - itf280 = (I280)o; - if (mrp.CanCastToCalled) - return 280; - total += itf280.CallMe (280); - - mrp.CanCastToCalled = false; - I281 itf281 = (I281)o; - if (!mrp.CanCastToCalled) - return 281; - total += itf281.CallMe (281); - mrp.CanCastToCalled = false; - itf281 = (I281)o; - if (mrp.CanCastToCalled) - return 281; - total += itf281.CallMe (281); - - mrp.CanCastToCalled = false; - I282 itf282 = (I282)o; - if (!mrp.CanCastToCalled) - return 282; - total += itf282.CallMe (282); - mrp.CanCastToCalled = false; - itf282 = (I282)o; - if (mrp.CanCastToCalled) - return 282; - total += itf282.CallMe (282); - - mrp.CanCastToCalled = false; - I283 itf283 = (I283)o; - if (!mrp.CanCastToCalled) - return 283; - total += itf283.CallMe (283); - mrp.CanCastToCalled = false; - itf283 = (I283)o; - if (mrp.CanCastToCalled) - return 283; - total += itf283.CallMe (283); - - mrp.CanCastToCalled = false; - I284 itf284 = (I284)o; - if (!mrp.CanCastToCalled) - return 284; - total += itf284.CallMe (284); - mrp.CanCastToCalled = false; - itf284 = (I284)o; - if (mrp.CanCastToCalled) - return 284; - total += itf284.CallMe (284); - - mrp.CanCastToCalled = false; - I285 itf285 = (I285)o; - if (!mrp.CanCastToCalled) - return 285; - total += itf285.CallMe (285); - mrp.CanCastToCalled = false; - itf285 = (I285)o; - if (mrp.CanCastToCalled) - return 285; - total += itf285.CallMe (285); - - mrp.CanCastToCalled = false; - I286 itf286 = (I286)o; - if (!mrp.CanCastToCalled) - return 286; - total += itf286.CallMe (286); - mrp.CanCastToCalled = false; - itf286 = (I286)o; - if (mrp.CanCastToCalled) - return 286; - total += itf286.CallMe (286); - - mrp.CanCastToCalled = false; - I287 itf287 = (I287)o; - if (!mrp.CanCastToCalled) - return 287; - total += itf287.CallMe (287); - mrp.CanCastToCalled = false; - itf287 = (I287)o; - if (mrp.CanCastToCalled) - return 287; - total += itf287.CallMe (287); - - mrp.CanCastToCalled = false; - I288 itf288 = (I288)o; - if (!mrp.CanCastToCalled) - return 288; - total += itf288.CallMe (288); - mrp.CanCastToCalled = false; - itf288 = (I288)o; - if (mrp.CanCastToCalled) - return 288; - total += itf288.CallMe (288); - - mrp.CanCastToCalled = false; - I289 itf289 = (I289)o; - if (!mrp.CanCastToCalled) - return 289; - total += itf289.CallMe (289); - mrp.CanCastToCalled = false; - itf289 = (I289)o; - if (mrp.CanCastToCalled) - return 289; - total += itf289.CallMe (289); - - mrp.CanCastToCalled = false; - I290 itf290 = (I290)o; - if (!mrp.CanCastToCalled) - return 290; - total += itf290.CallMe (290); - mrp.CanCastToCalled = false; - itf290 = (I290)o; - if (mrp.CanCastToCalled) - return 290; - total += itf290.CallMe (290); - - mrp.CanCastToCalled = false; - I291 itf291 = (I291)o; - if (!mrp.CanCastToCalled) - return 291; - total += itf291.CallMe (291); - mrp.CanCastToCalled = false; - itf291 = (I291)o; - if (mrp.CanCastToCalled) - return 291; - total += itf291.CallMe (291); - - mrp.CanCastToCalled = false; - I292 itf292 = (I292)o; - if (!mrp.CanCastToCalled) - return 292; - total += itf292.CallMe (292); - mrp.CanCastToCalled = false; - itf292 = (I292)o; - if (mrp.CanCastToCalled) - return 292; - total += itf292.CallMe (292); - - mrp.CanCastToCalled = false; - I293 itf293 = (I293)o; - if (!mrp.CanCastToCalled) - return 293; - total += itf293.CallMe (293); - mrp.CanCastToCalled = false; - itf293 = (I293)o; - if (mrp.CanCastToCalled) - return 293; - total += itf293.CallMe (293); - - mrp.CanCastToCalled = false; - I294 itf294 = (I294)o; - if (!mrp.CanCastToCalled) - return 294; - total += itf294.CallMe (294); - mrp.CanCastToCalled = false; - itf294 = (I294)o; - if (mrp.CanCastToCalled) - return 294; - total += itf294.CallMe (294); - - mrp.CanCastToCalled = false; - I295 itf295 = (I295)o; - if (!mrp.CanCastToCalled) - return 295; - total += itf295.CallMe (295); - mrp.CanCastToCalled = false; - itf295 = (I295)o; - if (mrp.CanCastToCalled) - return 295; - total += itf295.CallMe (295); - - mrp.CanCastToCalled = false; - I296 itf296 = (I296)o; - if (!mrp.CanCastToCalled) - return 296; - total += itf296.CallMe (296); - mrp.CanCastToCalled = false; - itf296 = (I296)o; - if (mrp.CanCastToCalled) - return 296; - total += itf296.CallMe (296); - - mrp.CanCastToCalled = false; - I297 itf297 = (I297)o; - if (!mrp.CanCastToCalled) - return 297; - total += itf297.CallMe (297); - mrp.CanCastToCalled = false; - itf297 = (I297)o; - if (mrp.CanCastToCalled) - return 297; - total += itf297.CallMe (297); - - mrp.CanCastToCalled = false; - I298 itf298 = (I298)o; - if (!mrp.CanCastToCalled) - return 298; - total += itf298.CallMe (298); - mrp.CanCastToCalled = false; - itf298 = (I298)o; - if (mrp.CanCastToCalled) - return 298; - total += itf298.CallMe (298); - - mrp.CanCastToCalled = false; - I299 itf299 = (I299)o; - if (!mrp.CanCastToCalled) - return 299; - total += itf299.CallMe (299); - mrp.CanCastToCalled = false; - itf299 = (I299)o; - if (mrp.CanCastToCalled) - return 299; - total += itf299.CallMe (299); - - mrp.CanCastToCalled = false; - I300 itf300 = (I300)o; - if (!mrp.CanCastToCalled) - return 300; - total += itf300.CallMe (300); - mrp.CanCastToCalled = false; - itf300 = (I300)o; - if (mrp.CanCastToCalled) - return 300; - total += itf300.CallMe (300); - - Console.WriteLine ("finished"); - - return 0; - } -} - -interface I1 -{ - int CallMe (int a); -} - -interface I2 -{ - int CallMe (int a); -} - -interface I3 -{ - int CallMe (int a); -} - -interface I4 -{ - int CallMe (int a); -} - -interface I5 -{ - int CallMe (int a); -} - -interface I6 -{ - int CallMe (int a); -} - -interface I7 -{ - int CallMe (int a); -} - -interface I8 -{ - int CallMe (int a); -} - -interface I9 -{ - int CallMe (int a); -} - -interface I10 -{ - int CallMe (int a); -} - -interface I11 -{ - int CallMe (int a); -} - -interface I12 -{ - int CallMe (int a); -} - -interface I13 -{ - int CallMe (int a); -} - -interface I14 -{ - int CallMe (int a); -} - -interface I15 -{ - int CallMe (int a); -} - -interface I16 -{ - int CallMe (int a); -} - -interface I17 -{ - int CallMe (int a); -} - -interface I18 -{ - int CallMe (int a); -} - -interface I19 -{ - int CallMe (int a); -} - -interface I20 -{ - int CallMe (int a); -} - -interface I21 -{ - int CallMe (int a); -} - -interface I22 -{ - int CallMe (int a); -} - -interface I23 -{ - int CallMe (int a); -} - -interface I24 -{ - int CallMe (int a); -} - -interface I25 -{ - int CallMe (int a); -} - -interface I26 -{ - int CallMe (int a); -} - -interface I27 -{ - int CallMe (int a); -} - -interface I28 -{ - int CallMe (int a); -} - -interface I29 -{ - int CallMe (int a); -} - -interface I30 -{ - int CallMe (int a); -} - -interface I31 -{ - int CallMe (int a); -} - -interface I32 -{ - int CallMe (int a); -} - -interface I33 -{ - int CallMe (int a); -} - -interface I34 -{ - int CallMe (int a); -} - -interface I35 -{ - int CallMe (int a); -} - -interface I36 -{ - int CallMe (int a); -} - -interface I37 -{ - int CallMe (int a); -} - -interface I38 -{ - int CallMe (int a); -} - -interface I39 -{ - int CallMe (int a); -} - -interface I40 -{ - int CallMe (int a); -} - -interface I41 -{ - int CallMe (int a); -} - -interface I42 -{ - int CallMe (int a); -} - -interface I43 -{ - int CallMe (int a); -} - -interface I44 -{ - int CallMe (int a); -} - -interface I45 -{ - int CallMe (int a); -} - -interface I46 -{ - int CallMe (int a); -} - -interface I47 -{ - int CallMe (int a); -} - -interface I48 -{ - int CallMe (int a); -} - -interface I49 -{ - int CallMe (int a); -} - -interface I50 -{ - int CallMe (int a); -} - -interface I51 -{ - int CallMe (int a); -} - -interface I52 -{ - int CallMe (int a); -} - -interface I53 -{ - int CallMe (int a); -} - -interface I54 -{ - int CallMe (int a); -} - -interface I55 -{ - int CallMe (int a); -} - -interface I56 -{ - int CallMe (int a); -} - -interface I57 -{ - int CallMe (int a); -} - -interface I58 -{ - int CallMe (int a); -} - -interface I59 -{ - int CallMe (int a); -} - -interface I60 -{ - int CallMe (int a); -} - -interface I61 -{ - int CallMe (int a); -} - -interface I62 -{ - int CallMe (int a); -} - -interface I63 -{ - int CallMe (int a); -} - -interface I64 -{ - int CallMe (int a); -} - -interface I65 -{ - int CallMe (int a); -} - -interface I66 -{ - int CallMe (int a); -} - -interface I67 -{ - int CallMe (int a); -} - -interface I68 -{ - int CallMe (int a); -} - -interface I69 -{ - int CallMe (int a); -} - -interface I70 -{ - int CallMe (int a); -} - -interface I71 -{ - int CallMe (int a); -} - -interface I72 -{ - int CallMe (int a); -} - -interface I73 -{ - int CallMe (int a); -} - -interface I74 -{ - int CallMe (int a); -} - -interface I75 -{ - int CallMe (int a); -} - -interface I76 -{ - int CallMe (int a); -} - -interface I77 -{ - int CallMe (int a); -} - -interface I78 -{ - int CallMe (int a); -} - -interface I79 -{ - int CallMe (int a); -} - -interface I80 -{ - int CallMe (int a); -} - -interface I81 -{ - int CallMe (int a); -} - -interface I82 -{ - int CallMe (int a); -} - -interface I83 -{ - int CallMe (int a); -} - -interface I84 -{ - int CallMe (int a); -} - -interface I85 -{ - int CallMe (int a); -} - -interface I86 -{ - int CallMe (int a); -} - -interface I87 -{ - int CallMe (int a); -} - -interface I88 -{ - int CallMe (int a); -} - -interface I89 -{ - int CallMe (int a); -} - -interface I90 -{ - int CallMe (int a); -} - -interface I91 -{ - int CallMe (int a); -} - -interface I92 -{ - int CallMe (int a); -} - -interface I93 -{ - int CallMe (int a); -} - -interface I94 -{ - int CallMe (int a); -} - -interface I95 -{ - int CallMe (int a); -} - -interface I96 -{ - int CallMe (int a); -} - -interface I97 -{ - int CallMe (int a); -} - -interface I98 -{ - int CallMe (int a); -} - -interface I99 -{ - int CallMe (int a); -} - -interface I100 -{ - int CallMe (int a); -} - -interface I101 -{ - int CallMe (int a); -} - -interface I102 -{ - int CallMe (int a); -} - -interface I103 -{ - int CallMe (int a); -} - -interface I104 -{ - int CallMe (int a); -} - -interface I105 -{ - int CallMe (int a); -} - -interface I106 -{ - int CallMe (int a); -} - -interface I107 -{ - int CallMe (int a); -} - -interface I108 -{ - int CallMe (int a); -} - -interface I109 -{ - int CallMe (int a); -} - -interface I110 -{ - int CallMe (int a); -} - -interface I111 -{ - int CallMe (int a); -} - -interface I112 -{ - int CallMe (int a); -} - -interface I113 -{ - int CallMe (int a); -} - -interface I114 -{ - int CallMe (int a); -} - -interface I115 -{ - int CallMe (int a); -} - -interface I116 -{ - int CallMe (int a); -} - -interface I117 -{ - int CallMe (int a); -} - -interface I118 -{ - int CallMe (int a); -} - -interface I119 -{ - int CallMe (int a); -} - -interface I120 -{ - int CallMe (int a); -} - -interface I121 -{ - int CallMe (int a); -} - -interface I122 -{ - int CallMe (int a); -} - -interface I123 -{ - int CallMe (int a); -} - -interface I124 -{ - int CallMe (int a); -} - -interface I125 -{ - int CallMe (int a); -} - -interface I126 -{ - int CallMe (int a); -} - -interface I127 -{ - int CallMe (int a); -} - -interface I128 -{ - int CallMe (int a); -} - -interface I129 -{ - int CallMe (int a); -} - -interface I130 -{ - int CallMe (int a); -} - -interface I131 -{ - int CallMe (int a); -} - -interface I132 -{ - int CallMe (int a); -} - -interface I133 -{ - int CallMe (int a); -} - -interface I134 -{ - int CallMe (int a); -} - -interface I135 -{ - int CallMe (int a); -} - -interface I136 -{ - int CallMe (int a); -} - -interface I137 -{ - int CallMe (int a); -} - -interface I138 -{ - int CallMe (int a); -} - -interface I139 -{ - int CallMe (int a); -} - -interface I140 -{ - int CallMe (int a); -} - -interface I141 -{ - int CallMe (int a); -} - -interface I142 -{ - int CallMe (int a); -} - -interface I143 -{ - int CallMe (int a); -} - -interface I144 -{ - int CallMe (int a); -} - -interface I145 -{ - int CallMe (int a); -} - -interface I146 -{ - int CallMe (int a); -} - -interface I147 -{ - int CallMe (int a); -} - -interface I148 -{ - int CallMe (int a); -} - -interface I149 -{ - int CallMe (int a); -} - -interface I150 -{ - int CallMe (int a); -} - -interface I151 -{ - int CallMe (int a); -} - -interface I152 -{ - int CallMe (int a); -} - -interface I153 -{ - int CallMe (int a); -} - -interface I154 -{ - int CallMe (int a); -} - -interface I155 -{ - int CallMe (int a); -} - -interface I156 -{ - int CallMe (int a); -} - -interface I157 -{ - int CallMe (int a); -} - -interface I158 -{ - int CallMe (int a); -} - -interface I159 -{ - int CallMe (int a); -} - -interface I160 -{ - int CallMe (int a); -} - -interface I161 -{ - int CallMe (int a); -} - -interface I162 -{ - int CallMe (int a); -} - -interface I163 -{ - int CallMe (int a); -} - -interface I164 -{ - int CallMe (int a); -} - -interface I165 -{ - int CallMe (int a); -} - -interface I166 -{ - int CallMe (int a); -} - -interface I167 -{ - int CallMe (int a); -} - -interface I168 -{ - int CallMe (int a); -} - -interface I169 -{ - int CallMe (int a); -} - -interface I170 -{ - int CallMe (int a); -} - -interface I171 -{ - int CallMe (int a); -} - -interface I172 -{ - int CallMe (int a); -} - -interface I173 -{ - int CallMe (int a); -} - -interface I174 -{ - int CallMe (int a); -} - -interface I175 -{ - int CallMe (int a); -} - -interface I176 -{ - int CallMe (int a); -} - -interface I177 -{ - int CallMe (int a); -} - -interface I178 -{ - int CallMe (int a); -} - -interface I179 -{ - int CallMe (int a); -} - -interface I180 -{ - int CallMe (int a); -} - -interface I181 -{ - int CallMe (int a); -} - -interface I182 -{ - int CallMe (int a); -} - -interface I183 -{ - int CallMe (int a); -} - -interface I184 -{ - int CallMe (int a); -} - -interface I185 -{ - int CallMe (int a); -} - -interface I186 -{ - int CallMe (int a); -} - -interface I187 -{ - int CallMe (int a); -} - -interface I188 -{ - int CallMe (int a); -} - -interface I189 -{ - int CallMe (int a); -} - -interface I190 -{ - int CallMe (int a); -} - -interface I191 -{ - int CallMe (int a); -} - -interface I192 -{ - int CallMe (int a); -} - -interface I193 -{ - int CallMe (int a); -} - -interface I194 -{ - int CallMe (int a); -} - -interface I195 -{ - int CallMe (int a); -} - -interface I196 -{ - int CallMe (int a); -} - -interface I197 -{ - int CallMe (int a); -} - -interface I198 -{ - int CallMe (int a); -} - -interface I199 -{ - int CallMe (int a); -} - -interface I200 -{ - int CallMe (int a); -} - -interface I201 -{ - int CallMe (int a); -} - -interface I202 -{ - int CallMe (int a); -} - -interface I203 -{ - int CallMe (int a); -} - -interface I204 -{ - int CallMe (int a); -} - -interface I205 -{ - int CallMe (int a); -} - -interface I206 -{ - int CallMe (int a); -} - -interface I207 -{ - int CallMe (int a); -} - -interface I208 -{ - int CallMe (int a); -} - -interface I209 -{ - int CallMe (int a); -} - -interface I210 -{ - int CallMe (int a); -} - -interface I211 -{ - int CallMe (int a); -} - -interface I212 -{ - int CallMe (int a); -} - -interface I213 -{ - int CallMe (int a); -} - -interface I214 -{ - int CallMe (int a); -} - -interface I215 -{ - int CallMe (int a); -} - -interface I216 -{ - int CallMe (int a); -} - -interface I217 -{ - int CallMe (int a); -} - -interface I218 -{ - int CallMe (int a); -} - -interface I219 -{ - int CallMe (int a); -} - -interface I220 -{ - int CallMe (int a); -} - -interface I221 -{ - int CallMe (int a); -} - -interface I222 -{ - int CallMe (int a); -} - -interface I223 -{ - int CallMe (int a); -} - -interface I224 -{ - int CallMe (int a); -} - -interface I225 -{ - int CallMe (int a); -} - -interface I226 -{ - int CallMe (int a); -} - -interface I227 -{ - int CallMe (int a); -} - -interface I228 -{ - int CallMe (int a); -} - -interface I229 -{ - int CallMe (int a); -} - -interface I230 -{ - int CallMe (int a); -} - -interface I231 -{ - int CallMe (int a); -} - -interface I232 -{ - int CallMe (int a); -} - -interface I233 -{ - int CallMe (int a); -} - -interface I234 -{ - int CallMe (int a); -} - -interface I235 -{ - int CallMe (int a); -} - -interface I236 -{ - int CallMe (int a); -} - -interface I237 -{ - int CallMe (int a); -} - -interface I238 -{ - int CallMe (int a); -} - -interface I239 -{ - int CallMe (int a); -} - -interface I240 -{ - int CallMe (int a); -} - -interface I241 -{ - int CallMe (int a); -} - -interface I242 -{ - int CallMe (int a); -} - -interface I243 -{ - int CallMe (int a); -} - -interface I244 -{ - int CallMe (int a); -} - -interface I245 -{ - int CallMe (int a); -} - -interface I246 -{ - int CallMe (int a); -} - -interface I247 -{ - int CallMe (int a); -} - -interface I248 -{ - int CallMe (int a); -} - -interface I249 -{ - int CallMe (int a); -} - -interface I250 -{ - int CallMe (int a); -} - -interface I251 -{ - int CallMe (int a); -} - -interface I252 -{ - int CallMe (int a); -} - -interface I253 -{ - int CallMe (int a); -} - -interface I254 -{ - int CallMe (int a); -} - -interface I255 -{ - int CallMe (int a); -} - -interface I256 -{ - int CallMe (int a); -} - -interface I257 -{ - int CallMe (int a); -} - -interface I258 -{ - int CallMe (int a); -} - -interface I259 -{ - int CallMe (int a); -} - -interface I260 -{ - int CallMe (int a); -} - -interface I261 -{ - int CallMe (int a); -} - -interface I262 -{ - int CallMe (int a); -} - -interface I263 -{ - int CallMe (int a); -} - -interface I264 -{ - int CallMe (int a); -} - -interface I265 -{ - int CallMe (int a); -} - -interface I266 -{ - int CallMe (int a); -} - -interface I267 -{ - int CallMe (int a); -} - -interface I268 -{ - int CallMe (int a); -} - -interface I269 -{ - int CallMe (int a); -} - -interface I270 -{ - int CallMe (int a); -} - -interface I271 -{ - int CallMe (int a); -} - -interface I272 -{ - int CallMe (int a); -} - -interface I273 -{ - int CallMe (int a); -} - -interface I274 -{ - int CallMe (int a); -} - -interface I275 -{ - int CallMe (int a); -} - -interface I276 -{ - int CallMe (int a); -} - -interface I277 -{ - int CallMe (int a); -} - -interface I278 -{ - int CallMe (int a); -} - -interface I279 -{ - int CallMe (int a); -} - -interface I280 -{ - int CallMe (int a); -} - -interface I281 -{ - int CallMe (int a); -} - -interface I282 -{ - int CallMe (int a); -} - -interface I283 -{ - int CallMe (int a); -} - -interface I284 -{ - int CallMe (int a); -} - -interface I285 -{ - int CallMe (int a); -} - -interface I286 -{ - int CallMe (int a); -} - -interface I287 -{ - int CallMe (int a); -} - -interface I288 -{ - int CallMe (int a); -} - -interface I289 -{ - int CallMe (int a); -} - -interface I290 -{ - int CallMe (int a); -} - -interface I291 -{ - int CallMe (int a); -} - -interface I292 -{ - int CallMe (int a); -} - -interface I293 -{ - int CallMe (int a); -} - -interface I294 -{ - int CallMe (int a); -} - -interface I295 -{ - int CallMe (int a); -} - -interface I296 -{ - int CallMe (int a); -} - -interface I297 -{ - int CallMe (int a); -} - -interface I298 -{ - int CallMe (int a); -} - -interface I299 -{ - int CallMe (int a); -} - -interface I300 -{ - int CallMe (int a); -} diff --git a/mono/tests/unload-appdomain-on-shutdown.cs b/mono/tests/unload-appdomain-on-shutdown.cs deleted file mode 100644 index 9cb13a8b79..0000000000 --- a/mono/tests/unload-appdomain-on-shutdown.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System; -using System.Reflection; -using System.Threading; - - -class Driver { - public static void Bla () - { - //DoDomainUnload is invoked as part of the unload sequence, so let's pre jit it here to increase the likehood - //of hanging - var m = typeof (AppDomain).GetMethod ("DoDomainUnload", BindingFlags.Instance | BindingFlags.NonPublic); - if (m != null) - m.MethodHandle.GetFunctionPointer (); - } - - static AppDomain ad; - static ManualResetEvent evt = new ManualResetEvent (false); - - static void UnloadIt () - { - //AppDomain.Unload calls AppDomain::getDomainId () before calling into the runtime, so let's pre jit - //it here to increase the likehood of hanging - var x = ad.Id; - evt.Set (); - AppDomain.Unload (ad); - } - static int Main () - { - AppDomain.Unload (AppDomain.CreateDomain ("Warmup unload code")); - Console.WriteLine ("."); - ad = AppDomain.CreateDomain ("NewDomain"); - ad.DoCallBack (Bla); - var t = new Thread (UnloadIt); - t.IsBackground = true; - t.Start (); - evt.WaitOne (); - return 0; - } -} diff --git a/mono/tests/winx64structs.cs b/mono/tests/winx64structs.cs index 527c29be75..0148fb4a4d 100644 --- a/mono/tests/winx64structs.cs +++ b/mono/tests/winx64structs.cs @@ -1,6 +1,11 @@ using System; using System.Runtime.InteropServices; +[AttributeUsage (AttributeTargets.Method)] +sealed class MonoPInvokeCallbackAttribute : Attribute { + public MonoPInvokeCallbackAttribute (Type t) {} +} + [StructLayout (LayoutKind.Sequential)] struct winx64_struct1 { @@ -450,6 +455,7 @@ class winx64structs return 0; } + [MonoPInvokeCallback (typeof (managed_struct1_delegate))] public static int managed_struct1_test (winx64_struct1 var) { if (var.a != 5) @@ -458,6 +464,7 @@ class winx64structs return 0; } + [MonoPInvokeCallback (typeof (managed_struct5_delegate))] public static int managed_struct5_test (winx64_struct5 var) { if (var.a != 5) @@ -470,6 +477,7 @@ class winx64structs return 0; } + [MonoPInvokeCallback (typeof (managed_struct1_struct5_delegate))] public static int managed_struct1_struct5_test (winx64_struct1 var1, winx64_struct5 var2, winx64_struct1 var3, winx64_struct5 var4, winx64_struct1 var5, winx64_struct5 var6) @@ -487,11 +495,13 @@ class winx64structs return 0; } + [MonoPInvokeCallback (typeof (mono_test_Winx64_struct1_ret_delegate))] public static winx64_struct1 mono_test_Winx64_struct1_ret_test () { return new winx64_struct1 (0x45); } + [MonoPInvokeCallback (typeof (mono_test_Winx64_struct5_ret_delegate))] public static winx64_struct5 mono_test_Winx64_struct5_ret_test () { return new winx64_struct5 (0x12, 0x34, 0x56); diff --git a/mono/tests/xdomain-threads.cs b/mono/tests/xdomain-threads.cs deleted file mode 100644 index f2c5cd97fc..0000000000 --- a/mono/tests/xdomain-threads.cs +++ /dev/null @@ -1,74 +0,0 @@ -using System; -using System.Threading; -using System.Runtime.Remoting; - -// Does a foreign domain's thread object persist (in .NET) even if it -// hasn't been started? -// -// Insubstantial, because it can't be "moved" to another domain. - -// Can we start a foreign domain's thread (i.e. does the thread then -// switch to the foreign domain and execute the start method there)? -// -// No, we can't start it from another domain, because we can't bring -// to another domain. - -// What if we start a foreign domain's thread if the domain is gone? -// -// See above. - -public class Test : MarshalByRefObject { - public Thread thread; - public String str; - - public void setThread () { - Console.WriteLine ("setting thread"); - thread = Thread.CurrentThread; - thread.Name = "foo"; - } - - public void setStr (string s) { - Console.WriteLine ("setting str"); - str = s; - } - - public void callSetThread (Test t) { - Thread thread = new Thread (new ThreadStart (t.setThread)); - - thread.Start (); - thread.Join (); - - t.setStr ("a" + "b"); - } -} - -public class main { - public static int Main (string [] args) { - AppDomain domain = AppDomain.CreateDomain ("newdomain"); - Test myTest = new Test (); - Test otherTest = (Test) domain.CreateInstanceAndUnwrap (typeof (Test).Assembly.FullName, typeof (Test).FullName); - - otherTest.callSetThread (myTest); - - if (myTest.thread.GetType () == Thread.CurrentThread.GetType ()) - Console.WriteLine ("same type"); - else { - Console.WriteLine ("different type"); - return 1; - } - - AppDomain.Unload (domain); - - GC.Collect (); - GC.WaitForPendingFinalizers (); - - Console.WriteLine ("thread " + myTest.thread); - - Console.WriteLine ("str " + myTest.str); - - if (!myTest.thread.Name.Equals("foo")) - return 1; - - return 0; - } -} diff --git a/mono/unit-tests/Makefile.in b/mono/unit-tests/Makefile.in index 2ce265e1bd..d48fcc84a5 100644 --- a/mono/unit-tests/Makefile.in +++ b/mono/unit-tests/Makefile.in @@ -438,6 +438,8 @@ DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AOT_BUILD_FLAGS = @AOT_BUILD_FLAGS@ +AOT_RUN_FLAGS = @AOT_RUN_FLAGS@ API_VER = @API_VER@ AR = @AR@ AS = @AS@ @@ -446,6 +448,11 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOEHM_DEFINES = @BOEHM_DEFINES@ +BTLS_ARCH = @BTLS_ARCH@ +BTLS_CFLAGS = @BTLS_CFLAGS@ +BTLS_CMAKE_ARGS = @BTLS_CMAKE_ARGS@ +BTLS_PLATFORM = @BTLS_PLATFORM@ +BTLS_ROOT = @BTLS_ROOT@ BUILD_EXEEXT = @BUILD_EXEEXT@ CC = @CC@ CCAS = @CCAS@ @@ -455,6 +462,7 @@ CCDEPMODE = @CCDEPMODE@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMAKE = @CMAKE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ @@ -475,7 +483,6 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_PERF_EVENTS = @ENABLE_PERF_EVENTS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDKX11 = @GDKX11@ @@ -490,10 +497,12 @@ HAVE_MSGFMT = @HAVE_MSGFMT@ HOST_CC = @HOST_CC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MOBILE_STATIC = @INSTALL_MOBILE_STATIC@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTL = @INTL@ +INVARIANT_AOT_OPTIONS = @INVARIANT_AOT_OPTIONS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBC = @LIBC@ @@ -540,6 +549,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ +PLATFORM_AOT_SUFFIX = @PLATFORM_AOT_SUFFIX@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -549,6 +559,7 @@ SHELL = @SHELL@ SQLITE = @SQLITE@ SQLITE3 = @SQLITE3@ STRIP = @STRIP@ +TEST_PROFILE = @TEST_PROFILE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VTUNE_CFLAGS = @VTUNE_CFLAGS@ diff --git a/mono/unit-tests/test-conc-hashtable.c b/mono/unit-tests/test-conc-hashtable.c index 32d859c50d..abb24d9825 100644 --- a/mono/unit-tests/test-conc-hashtable.c +++ b/mono/unit-tests/test-conc-hashtable.c @@ -11,6 +11,7 @@ #include "utils/mono-threads.h" #include "utils/mono-conc-hashtable.h" #include "utils/checked-build.h" +#include "utils/w32handle.h" #include #include @@ -335,6 +336,9 @@ main (void) memset (&ticallbacks, 0, sizeof (ticallbacks)); ticallbacks.thread_state_init = thread_state_init; mono_threads_runtime_init (&ticallbacks); +#ifndef HOST_WIN32 + mono_w32handle_init (); +#endif mono_thread_info_attach ((gpointer)&cb); diff --git a/mono/unit-tests/test-mono-handle.c b/mono/unit-tests/test-mono-handle.c index 3438039a4b..95ebae349c 100644 --- a/mono/unit-tests/test-mono-handle.c +++ b/mono/unit-tests/test-mono-handle.c @@ -15,28 +15,8 @@ static void test2_arena_push_pop () { - MonoHandleArena *top = NULL; - - MonoHandleArena *new_arena1 = g_malloc0 (mono_handle_arena_size ()); - mono_handle_arena_stack_push (&top, new_arena1); - - MonoHandleArena *new_arena2 = g_malloc0 (mono_handle_arena_size ()); - - mono_handle_arena_stack_push (&top, new_arena2); - - g_assert (top == new_arena2); - - mono_handle_arena_stack_pop (&top, new_arena2); - - g_free (new_arena2); - - g_assert (top == new_arena1); - - mono_handle_arena_stack_pop (&top, new_arena1); - - g_assert (top == NULL); - - g_free (new_arena1); + HandleStack *h = mono_handle_stack_alloc (); + mono_handle_stack_free (h); } diff --git a/mono/utils/Makefile.am b/mono/utils/Makefile.am index ddff14f69e..3e29ab15df 100644 --- a/mono/utils/Makefile.am +++ b/mono/utils/Makefile.am @@ -27,6 +27,11 @@ monoutils_sources = \ mono-dl-darwin.c \ mono-dl-posix.c \ mono-dl.h \ + mono-log-windows.c \ + mono-log-common.c \ + mono-log-posix.c \ + mono-log-android.c \ + mono-log-darwin.c \ mono-internal-hash.c \ mono-internal-hash.h \ mono-io-portability.c \ @@ -109,6 +114,7 @@ monoutils_sources = \ mono-threads-windows.c \ mono-threads-linux.c \ mono-threads-freebsd.c \ + mono-threads-netbsd.c \ mono-threads-openbsd.c \ mono-threads-android.c \ mono-threads.h \ @@ -149,7 +155,9 @@ monoutils_sources = \ parse.c \ parse.h \ checked-build.c \ - checked-build.h + checked-build.h \ + w32handle.c \ + w32handle.h arch_sources = diff --git a/mono/utils/Makefile.in b/mono/utils/Makefile.in index ed8f2c552a..7bd6a513cc 100644 --- a/mono/utils/Makefile.in +++ b/mono/utils/Makefile.in @@ -122,20 +122,21 @@ am__libmonoutils_la_SOURCES_DIST = mono-md5.c mono-sha1.c \ mono-logger.c mono-logger-internals.h mono-codeman.c \ dlmalloc.h dlmalloc.c mono-counters.c mono-compiler.h \ mono-complex.h mono-dl.c mono-dl-windows.c mono-dl-darwin.c \ - mono-dl-posix.c mono-dl.h mono-internal-hash.c \ - mono-internal-hash.h mono-io-portability.c \ - mono-io-portability.h monobitset.c mono-filemap.c mono-math.c \ - mono-mmap.c mono-mmap.h mono-mmap-internals.h mono-os-mutex.h \ - mono-coop-mutex.h mono-once.h mono-lazy-init.h \ - mono-networkinterfaces.c mono-networkinterfaces.h \ - mono-proclib.c mono-proclib.h mono-publib.c mono-string.h \ - mono-time.c mono-time.h strenc.h strenc.c mono-uri.c \ - mono-poll.c mono-path.c mono-os-semaphore.h \ - mono-coop-semaphore.h mono-sigcontext.h mono-stdlib.c \ - mono-property-hash.h mono-property-hash.c mono-value-hash.h \ - mono-value-hash.c freebsd-elf_common.h freebsd-elf32.h \ - freebsd-elf64.h freebsd-dwarf.h dtrace.h gc_wrapper.h \ - mono-error.c mono-error-internals.h monobitset.h \ + mono-dl-posix.c mono-dl.h mono-log-windows.c mono-log-common.c \ + mono-log-posix.c mono-log-android.c mono-log-darwin.c \ + mono-internal-hash.c mono-internal-hash.h \ + mono-io-portability.c mono-io-portability.h monobitset.c \ + mono-filemap.c mono-math.c mono-mmap.c mono-mmap.h \ + mono-mmap-internals.h mono-os-mutex.h mono-coop-mutex.h \ + mono-once.h mono-lazy-init.h mono-networkinterfaces.c \ + mono-networkinterfaces.h mono-proclib.c mono-proclib.h \ + mono-publib.c mono-string.h mono-time.c mono-time.h strenc.h \ + strenc.c mono-uri.c mono-poll.c mono-path.c \ + mono-os-semaphore.h mono-coop-semaphore.h mono-sigcontext.h \ + mono-stdlib.c mono-property-hash.h mono-property-hash.c \ + mono-value-hash.h mono-value-hash.c freebsd-elf_common.h \ + freebsd-elf32.h freebsd-elf64.h freebsd-dwarf.h dtrace.h \ + gc_wrapper.h mono-error.c mono-error-internals.h monobitset.h \ mono-codeman.h mono-counters.h mono-digest.h mono-error.h \ mono-machine.h mono-math.h mono-membar.h mono-path.h \ mono-poll.h mono-uri.h mono-stdlib.h valgrind.h mach-support.c \ @@ -149,9 +150,9 @@ am__libmonoutils_la_SOURCES_DIST = mono-md5.c mono-sha1.c \ mono-threads-posix-signals.c mono-threads-posix-signals.h \ mono-threads-mach.c mono-threads-mach-helper.c \ mono-threads-windows.c mono-threads-linux.c \ - mono-threads-freebsd.c mono-threads-openbsd.c \ - mono-threads-android.c mono-threads.h mono-threads-api.h \ - mono-threads-coop.c mono-threads-coop.h \ + mono-threads-freebsd.c mono-threads-netbsd.c \ + mono-threads-openbsd.c mono-threads-android.c mono-threads.h \ + mono-threads-api.h mono-threads-coop.c mono-threads-coop.h \ mono-threads-mach-abort-syscall.c \ mono-threads-posix-abort-syscall.c \ mono-threads-windows-abort-syscall.c mono-tls.h mono-tls.c \ @@ -162,27 +163,30 @@ am__libmonoutils_la_SOURCES_DIST = mono-md5.c mono-sha1.c \ networking-posix.c networking-fallback.c networking-missing.c \ networking-windows.c networking.h mono-rand.c mono-rand.h \ memfuncs.c memfuncs.h parse.c parse.h checked-build.c \ - checked-build.h mach-support-x86.c mach-support-amd64.c \ - mach-support-arm.c mach-support-arm64.c mach-support-unknown.c \ - mono-hwcap-x86.c mono-hwcap-arm.c mono-hwcap-arm64.c \ - mono-hwcap-mips.c mono-hwcap-ppc.c mono-hwcap-sparc.c \ - mono-hwcap-ia64.c mono-hwcap-s390x.c mono-hwcap-cross.c + checked-build.h w32handle.c w32handle.h mach-support-x86.c \ + mach-support-amd64.c mach-support-arm.c mach-support-arm64.c \ + mach-support-unknown.c mono-hwcap-x86.c mono-hwcap-arm.c \ + mono-hwcap-arm64.c mono-hwcap-mips.c mono-hwcap-ppc.c \ + mono-hwcap-sparc.c mono-hwcap-ia64.c mono-hwcap-s390x.c \ + mono-hwcap-cross.c am__objects_1 = mono-md5.lo mono-sha1.lo mono-logger.lo \ mono-codeman.lo dlmalloc.lo mono-counters.lo mono-dl.lo \ mono-dl-windows.lo mono-dl-darwin.lo mono-dl-posix.lo \ - mono-internal-hash.lo mono-io-portability.lo monobitset.lo \ - mono-filemap.lo mono-math.lo mono-mmap.lo \ - mono-networkinterfaces.lo mono-proclib.lo mono-publib.lo \ - mono-time.lo strenc.lo mono-uri.lo mono-poll.lo mono-path.lo \ - mono-stdlib.lo mono-property-hash.lo mono-value-hash.lo \ - mono-error.lo mach-support.lo mono-context.lo \ - hazard-pointer.lo lock-free-queue.lo lock-free-alloc.lo \ - lock-free-array-queue.lo mono-linked-list-set.lo \ - mono-threads.lo mono-threads-state-machine.lo \ - mono-threads-posix.lo mono-threads-posix-signals.lo \ - mono-threads-mach.lo mono-threads-mach-helper.lo \ - mono-threads-windows.lo mono-threads-linux.lo \ - mono-threads-freebsd.lo mono-threads-openbsd.lo \ + mono-log-windows.lo mono-log-common.lo mono-log-posix.lo \ + mono-log-android.lo mono-log-darwin.lo mono-internal-hash.lo \ + mono-io-portability.lo monobitset.lo mono-filemap.lo \ + mono-math.lo mono-mmap.lo mono-networkinterfaces.lo \ + mono-proclib.lo mono-publib.lo mono-time.lo strenc.lo \ + mono-uri.lo mono-poll.lo mono-path.lo mono-stdlib.lo \ + mono-property-hash.lo mono-value-hash.lo mono-error.lo \ + mach-support.lo mono-context.lo hazard-pointer.lo \ + lock-free-queue.lo lock-free-alloc.lo lock-free-array-queue.lo \ + mono-linked-list-set.lo mono-threads.lo \ + mono-threads-state-machine.lo mono-threads-posix.lo \ + mono-threads-posix-signals.lo mono-threads-mach.lo \ + mono-threads-mach-helper.lo mono-threads-windows.lo \ + mono-threads-linux.lo mono-threads-freebsd.lo \ + mono-threads-netbsd.lo mono-threads-openbsd.lo \ mono-threads-android.lo mono-threads-coop.lo \ mono-threads-mach-abort-syscall.lo \ mono-threads-posix-abort-syscall.lo \ @@ -191,7 +195,7 @@ am__objects_1 = mono-md5.lo mono-sha1.lo mono-logger.lo \ json.lo networking.lo networking-posix.lo \ networking-fallback.lo networking-missing.lo \ networking-windows.lo mono-rand.lo memfuncs.lo parse.lo \ - checked-build.lo + checked-build.lo w32handle.lo @CROSS_COMPILE_FALSE@@X86_TRUE@am__objects_2 = mach-support-x86.lo @AMD64_TRUE@@CROSS_COMPILE_FALSE@am__objects_3 = \ @AMD64_TRUE@@CROSS_COMPILE_FALSE@ mach-support-amd64.lo @@ -314,6 +318,8 @@ DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AOT_BUILD_FLAGS = @AOT_BUILD_FLAGS@ +AOT_RUN_FLAGS = @AOT_RUN_FLAGS@ API_VER = @API_VER@ AR = @AR@ AS = @AS@ @@ -322,6 +328,11 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOEHM_DEFINES = @BOEHM_DEFINES@ +BTLS_ARCH = @BTLS_ARCH@ +BTLS_CFLAGS = @BTLS_CFLAGS@ +BTLS_CMAKE_ARGS = @BTLS_CMAKE_ARGS@ +BTLS_PLATFORM = @BTLS_PLATFORM@ +BTLS_ROOT = @BTLS_ROOT@ BUILD_EXEEXT = @BUILD_EXEEXT@ CC = @CC@ CCAS = @CCAS@ @@ -331,6 +342,7 @@ CCDEPMODE = @CCDEPMODE@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMAKE = @CMAKE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ @@ -351,7 +363,6 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_PERF_EVENTS = @ENABLE_PERF_EVENTS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDKX11 = @GDKX11@ @@ -366,10 +377,12 @@ HAVE_MSGFMT = @HAVE_MSGFMT@ HOST_CC = @HOST_CC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MOBILE_STATIC = @INSTALL_MOBILE_STATIC@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTL = @INTL@ +INVARIANT_AOT_OPTIONS = @INVARIANT_AOT_OPTIONS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBC = @LIBC@ @@ -416,6 +429,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ +PLATFORM_AOT_SUFFIX = @PLATFORM_AOT_SUFFIX@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -425,6 +439,7 @@ SHELL = @SHELL@ SQLITE = @SQLITE@ SQLITE3 = @SQLITE3@ STRIP = @STRIP@ +TEST_PROFILE = @TEST_PROFILE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VTUNE_CFLAGS = @VTUNE_CFLAGS@ @@ -532,6 +547,11 @@ monoutils_sources = \ mono-dl-darwin.c \ mono-dl-posix.c \ mono-dl.h \ + mono-log-windows.c \ + mono-log-common.c \ + mono-log-posix.c \ + mono-log-android.c \ + mono-log-darwin.c \ mono-internal-hash.c \ mono-internal-hash.h \ mono-io-portability.c \ @@ -614,6 +634,7 @@ monoutils_sources = \ mono-threads-windows.c \ mono-threads-linux.c \ mono-threads-freebsd.c \ + mono-threads-netbsd.c \ mono-threads-openbsd.c \ mono-threads-android.c \ mono-threads.h \ @@ -654,7 +675,9 @@ monoutils_sources = \ parse.c \ parse.h \ checked-build.c \ - checked-build.h + checked-build.h \ + w32handle.c \ + w32handle.h arch_sources = $(am__append_1) $(am__append_2) $(am__append_3) \ $(am__append_4) $(am__append_5) $(am__append_6) \ @@ -767,6 +790,11 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mono-internal-hash.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mono-io-portability.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mono-linked-list-set.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mono-log-android.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mono-log-common.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mono-log-darwin.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mono-log-posix.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mono-log-windows.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mono-logger.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mono-math.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mono-md5.Plo@am__quote@ @@ -787,6 +815,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mono-threads-mach-abort-syscall.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mono-threads-mach-helper.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mono-threads-mach.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mono-threads-netbsd.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mono-threads-openbsd.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mono-threads-posix-abort-syscall.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mono-threads-posix-signals.Plo@am__quote@ @@ -808,6 +837,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parse.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sha1.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strenc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/w32handle.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ diff --git a/mono/utils/checked-build.c b/mono/utils/checked-build.c index 6f5606bdb8..43a690c759 100644 --- a/mono/utils/checked-build.c +++ b/mono/utils/checked-build.c @@ -146,7 +146,7 @@ translate_backtrace (gpointer native_trace[], int size) g_string_append_printf (bt, "\tat %s\n", names [i]); } - free (names); + g_free (names); return g_string_free (bt, FALSE); } diff --git a/mono/utils/dlmalloc.c.REMOVED.git-id b/mono/utils/dlmalloc.c.REMOVED.git-id index ce4e3851c3..ff04ca3f0d 100644 --- a/mono/utils/dlmalloc.c.REMOVED.git-id +++ b/mono/utils/dlmalloc.c.REMOVED.git-id @@ -1 +1 @@ -2ce2a6ea95e4afb928e2bb91d7bd0df263c936ae \ No newline at end of file +3177f2d17a1194f5ebc59fbea7382990120a4db5 \ No newline at end of file diff --git a/mono/utils/lock-free-alloc.c b/mono/utils/lock-free-alloc.c index d5da389634..36d91ce726 100644 --- a/mono/utils/lock-free-alloc.c +++ b/mono/utils/lock-free-alloc.c @@ -246,7 +246,7 @@ desc_alloc (void) if (desc) return desc; - return calloc (1, sizeof (Descriptor)); + return g_calloc (1, sizeof (Descriptor)); } static void diff --git a/mono/utils/lock-free-alloc.h b/mono/utils/lock-free-alloc.h index f0420b492e..3e3dd5773f 100644 --- a/mono/utils/lock-free-alloc.h +++ b/mono/utils/lock-free-alloc.h @@ -27,8 +27,8 @@ #define __MONO_LOCKFREEALLOC_H__ #include - -#include "lock-free-queue.h" +#include +#include typedef struct { MonoLockFreeQueue partial; diff --git a/mono/utils/mono-codeman.c b/mono/utils/mono-codeman.c index 83c2bdcc69..7b6e1c93ba 100644 --- a/mono/utils/mono-codeman.c +++ b/mono/utils/mono-codeman.c @@ -234,7 +234,7 @@ free_chunklist (CodeChunk *chunk) dlfree (dead->data); } code_memory_used -= dead->size; - free (dead); + g_free (dead); } } @@ -249,7 +249,7 @@ mono_code_manager_destroy (MonoCodeManager *cman) { free_chunklist (cman->full); free_chunklist (cman->current); - free (cman); + g_free (cman); } /** @@ -398,7 +398,7 @@ new_codechunk (CodeChunk *last, int dynamic, int size) #endif } - chunk = (CodeChunk *) malloc (sizeof (CodeChunk)); + chunk = (CodeChunk *) g_malloc (sizeof (CodeChunk)); if (!chunk) { if (flags == CODE_FLAG_MALLOC) dlfree (ptr); diff --git a/mono/utils/mono-compiler.h b/mono/utils/mono-compiler.h index d03ba8051a..5c942e06fa 100644 --- a/mono/utils/mono-compiler.h +++ b/mono/utils/mono-compiler.h @@ -275,12 +275,6 @@ typedef SSIZE_T ssize_t; #define MONO_LLVM_INTERNAL #endif -#if HAVE_DEPRECATED -#define MONO_DEPRECATED __attribute__ ((deprecated)) -#else -#define MONO_DEPRECATED -#endif - #ifdef __GNUC__ #define MONO_ALWAYS_INLINE __attribute__((always_inline)) #elif defined(_MSC_VER) diff --git a/mono/utils/mono-context.h b/mono/utils/mono-context.h index 2704c8662a..907c62ee2e 100644 --- a/mono/utils/mono-context.h +++ b/mono/utils/mono-context.h @@ -264,15 +264,15 @@ typedef struct { "push {r0}\n" \ "push {r1}\n" \ "mov r0, %0\n" \ - "ldr r1, [sp, #4]\n" \ - "str r1, [r0]!\n" \ - "ldr r1, [sp, #0]\n" \ - "str r1, [r0]!\n" \ + "ldr r1, [sp, #4]\n" \ + "str r1, [r0], #4\n" \ + "ldr r1, [sp, #0]\n" \ + "str r1, [r0], #4\n" \ "stmia r0!, {r2-r12}\n" \ - "str sp, [r0]!\n" \ - "str lr, [r0]!\n" \ + "str sp, [r0], #4\n" \ + "str lr, [r0], #4\n" \ "mov r1, pc\n" \ - "str r1, [r0]!\n" \ + "str r1, [r0], #4\n" \ "pop {r1}\n" \ "pop {r0}\n" \ : \ diff --git a/mono/utils/mono-coop-mutex.h b/mono/utils/mono-coop-mutex.h index 92ae719d7b..1bd0a64605 100644 --- a/mono/utils/mono-coop-mutex.h +++ b/mono/utils/mono-coop-mutex.h @@ -23,16 +23,16 @@ struct _MonoCoopCond { mono_cond_t c; }; -static inline gint +static inline void mono_coop_mutex_init (MonoCoopMutex *mutex) { - return mono_os_mutex_init (&mutex->m); + mono_os_mutex_init (&mutex->m); } -static inline gint +static inline void mono_coop_mutex_init_recursive (MonoCoopMutex *mutex) { - return mono_os_mutex_init_recursive (&mutex->m); + mono_os_mutex_init_recursive (&mutex->m); } static inline gint @@ -41,22 +41,18 @@ mono_coop_mutex_destroy (MonoCoopMutex *mutex) return mono_os_mutex_destroy (&mutex->m); } -static inline gint +static inline void mono_coop_mutex_lock (MonoCoopMutex *mutex) { - gint res; - /* Avoid thread state switch if lock is not contended */ if (mono_os_mutex_trylock (&mutex->m) == 0) - return 0; + return; MONO_ENTER_GC_SAFE; - res = mono_os_mutex_lock (&mutex->m); + mono_os_mutex_lock (&mutex->m); MONO_EXIT_GC_SAFE; - - return res; } static inline gint @@ -65,16 +61,16 @@ mono_coop_mutex_trylock (MonoCoopMutex *mutex) return mono_os_mutex_trylock (&mutex->m); } -static inline gint +static inline void mono_coop_mutex_unlock (MonoCoopMutex *mutex) { - return mono_os_mutex_unlock (&mutex->m); + mono_os_mutex_unlock (&mutex->m); } -static inline gint +static inline void mono_coop_cond_init (MonoCoopCond *cond) { - return mono_os_cond_init (&cond->c); + mono_os_cond_init (&cond->c); } static inline gint @@ -83,18 +79,14 @@ mono_coop_cond_destroy (MonoCoopCond *cond) return mono_os_cond_destroy (&cond->c); } -static inline gint +static inline void mono_coop_cond_wait (MonoCoopCond *cond, MonoCoopMutex *mutex) { - gint res; - MONO_ENTER_GC_SAFE; - res = mono_os_cond_wait (&cond->c, &mutex->m); + mono_os_cond_wait (&cond->c, &mutex->m); MONO_EXIT_GC_SAFE; - - return res; } static inline gint @@ -111,16 +103,16 @@ mono_coop_cond_timedwait (MonoCoopCond *cond, MonoCoopMutex *mutex, guint32 time return res; } -static inline gint +static inline void mono_coop_cond_signal (MonoCoopCond *cond) { - return mono_os_cond_signal (&cond->c); + mono_os_cond_signal (&cond->c); } -static inline gint +static inline void mono_coop_cond_broadcast (MonoCoopCond *cond) { - return mono_os_cond_broadcast (&cond->c); + mono_os_cond_broadcast (&cond->c); } G_END_DECLS diff --git a/mono/utils/mono-coop-semaphore.h b/mono/utils/mono-coop-semaphore.h index 81c987ed74..29937c5b73 100644 --- a/mono/utils/mono-coop-semaphore.h +++ b/mono/utils/mono-coop-semaphore.h @@ -18,16 +18,16 @@ struct _MonoCoopSem { MonoSemType s; }; -static inline gint +static inline void mono_coop_sem_init (MonoCoopSem *sem, int value) { - return mono_os_sem_init (&sem->s, value); + mono_os_sem_init (&sem->s, value); } -static inline gint +static inline void mono_coop_sem_destroy (MonoCoopSem *sem) { - return mono_os_sem_destroy (&sem->s); + mono_os_sem_destroy (&sem->s); } static inline gint @@ -44,10 +44,10 @@ mono_coop_sem_wait (MonoCoopSem *sem, MonoSemFlags flags) return res; } -static inline gint +static inline MonoSemTimedwaitRet mono_coop_sem_timedwait (MonoCoopSem *sem, guint timeout_ms, MonoSemFlags flags) { - gint res; + MonoSemTimedwaitRet res; MONO_ENTER_GC_SAFE; @@ -58,10 +58,10 @@ mono_coop_sem_timedwait (MonoCoopSem *sem, guint timeout_ms, MonoSemFlags flags) return res; } -static inline gint +static inline void mono_coop_sem_post (MonoCoopSem *sem) { - return mono_os_sem_post (&sem->s); + mono_os_sem_post (&sem->s); } G_END_DECLS diff --git a/mono/utils/mono-counters.c b/mono/utils/mono-counters.c index 2ca19a8b3d..ae33b4a9f3 100644 --- a/mono/utils/mono-counters.c +++ b/mono/utils/mono-counters.c @@ -166,7 +166,7 @@ register_internal (const char *name, int type, void *addr, int size) } } - counter = (MonoCounter *) malloc (sizeof (MonoCounter)); + counter = (MonoCounter *) g_malloc (sizeof (MonoCounter)); if (!counter) { mono_os_mutex_unlock (&counters_mutex); return; @@ -648,8 +648,8 @@ mono_counters_cleanup (void) while (counter) { MonoCounter *tmp = counter; counter = counter->next; - free ((void*)tmp->name); - free (tmp); + g_free ((void*)tmp->name); + g_free (tmp); } mono_os_mutex_unlock (&counters_mutex); diff --git a/mono/utils/mono-dl.c b/mono/utils/mono-dl.c index 4311613030..6c0f582cf6 100644 --- a/mono/utils/mono-dl.c +++ b/mono/utils/mono-dl.c @@ -140,7 +140,7 @@ mono_dl_open (const char *name, int flags, char **error_msg) if (error_msg) *error_msg = NULL; - module = (MonoDl *) malloc (sizeof (MonoDl)); + module = (MonoDl *) g_malloc (sizeof (MonoDl)); if (!module) { if (error_msg) *error_msg = g_strdup ("Out of memory"); @@ -174,7 +174,7 @@ mono_dl_open (const char *name, int flags, char **error_msg) const char *ext; /* This platform does not support dlopen */ if (name == NULL) { - free (module); + g_free (module); return NULL; } @@ -193,7 +193,7 @@ mono_dl_open (const char *name, int flags, char **error_msg) if (error_msg) { *error_msg = mono_dl_current_error_string (); } - free (module); + g_free (module); return NULL; } } @@ -224,11 +224,11 @@ mono_dl_symbol (MonoDl *module, const char *name, void **symbol) } else { #if MONO_DL_NEED_USCORE { - char *usname = malloc (strlen (name) + 2); + char *usname = g_malloc (strlen (name) + 2); *usname = '_'; strcpy (usname + 1, name); sym = mono_dl_lookup_symbol (module, usname); - free (usname); + g_free (usname); } #else sym = mono_dl_lookup_symbol (module, name); @@ -264,7 +264,7 @@ mono_dl_close (MonoDl *module) } else mono_dl_close_handle (module); - free (module); + g_free (module); } /** diff --git a/mono/utils/mono-error-internals.h b/mono/utils/mono-error-internals.h index 63607a8fb8..e143901748 100644 --- a/mono/utils/mono-error-internals.h +++ b/mono/utils/mono-error-internals.h @@ -33,8 +33,8 @@ typedef struct { } MonoErrorInternal; #define error_init(error) do { \ - (error)->error_code = MONO_ERROR_NONE; \ - (error)->flags = 0; \ + ((MonoErrorInternal*)(error))->error_code = MONO_ERROR_NONE; \ + ((MonoErrorInternal*)(error))->flags = 0; \ } while (0); #define is_ok(error) ((error)->error_code == MONO_ERROR_NONE) @@ -113,6 +113,9 @@ mono_error_set_invalid_operation (MonoError *error, const char *msg_format, ...) void mono_error_set_exception_instance (MonoError *error, MonoException *exc); +void +mono_error_set_invalid_program (MonoError *oerror, const char *msg_format, ...); + MonoException* mono_error_prepare_exception (MonoError *error, MonoError *error_out); diff --git a/mono/utils/mono-error.c b/mono/utils/mono-error.c index 7488c9ca6c..4951b35e18 100644 --- a/mono/utils/mono-error.c +++ b/mono/utils/mono-error.c @@ -8,10 +8,12 @@ */ #include +#include #include "mono-error.h" #include "mono-error-internals.h" #include +#include #include #include @@ -287,7 +289,7 @@ mono_error_set_assembly_load_simple (MonoError *oerror, const char *assembly_nam if (refection_only) mono_error_set_assembly_load (oerror, assembly_name, "Cannot resolve dependency to assembly because it has not been preloaded. When using the ReflectionOnly APIs, dependent assemblies must be pre-loaded or loaded on demand through the ReflectionOnlyAssemblyResolve event."); else - mono_error_set_assembly_load (oerror, assembly_name, "Could not load file or assembly or one of its dependencies."); + mono_error_set_assembly_load (oerror, assembly_name, "Could not load file or assembly '%s' or one of its dependencies.", assembly_name); } void @@ -440,6 +442,17 @@ mono_error_set_invalid_operation (MonoError *oerror, const char *msg_format, ... va_end (args); } +void +mono_error_set_invalid_program (MonoError *oerror, const char *msg_format, ...) +{ + MonoErrorInternal *error = (MonoErrorInternal*)oerror; + + mono_error_prepare (error); + error->error_code = MONO_ERROR_INVALID_PROGRAM; + + set_error_message (); +} + void mono_error_set_exception_instance (MonoError *oerror, MonoException *exc) { @@ -562,7 +575,7 @@ mono_error_prepare_exception (MonoError *oerror, MonoError *error_out) break; } - exception = mono_exception_from_name_two_strings (mono_defaults.corlib, "System", "MissingMethodException", type_name, method_name); + exception = mono_exception_from_name_two_strings_checked (mono_defaults.corlib, "System", "MissingMethodException", type_name, method_name, error_out); if (exception) set_message_on_exception (exception, error, error_out); } else { @@ -582,7 +595,7 @@ mono_error_prepare_exception (MonoError *oerror, MonoError *error_out) break; } - exception = mono_exception_from_name_two_strings (mono_defaults.corlib, "System", "MissingFieldException", type_name, field_name); + exception = mono_exception_from_name_two_strings_checked (mono_defaults.corlib, "System", "MissingFieldException", type_name, field_name, error_out); if (exception) set_message_on_exception (exception, error, error_out); } else { @@ -604,8 +617,8 @@ mono_error_prepare_exception (MonoError *oerror, MonoError *error_out) } } - exception = mono_exception_from_name_two_strings (mono_get_corlib (), "System", "TypeLoadException", type_name, assembly_name); - if (exception) + exception = mono_exception_from_name_two_strings_checked (mono_get_corlib (), "System", "TypeLoadException", type_name, assembly_name, error_out); + if (exception && error->full_message != NULL && strcmp (error->full_message, "")) set_message_on_exception (exception, error, error_out); } else { exception = mono_exception_from_name_msg (mono_defaults.corlib, "System", "TypeLoadException", error->full_message); @@ -630,9 +643,9 @@ mono_error_prepare_exception (MonoError *oerror, MonoError *error_out) } if (error->error_code == MONO_ERROR_FILE_NOT_FOUND) - exception = mono_exception_from_name_two_strings (mono_get_corlib (), "System.IO", "FileNotFoundException", msg, assembly_name); + exception = mono_exception_from_name_two_strings_checked (mono_get_corlib (), "System.IO", "FileNotFoundException", msg, assembly_name, error_out); else - exception = mono_exception_from_name_two_strings (mono_defaults.corlib, "System", "BadImageFormatException", msg, assembly_name); + exception = mono_exception_from_name_two_strings_checked (mono_defaults.corlib, "System", "BadImageFormatException", msg, assembly_name, error_out); } else { if (error->error_code == MONO_ERROR_FILE_NOT_FOUND) exception = mono_exception_from_name_msg (mono_get_corlib (), "System.IO", "FileNotFoundException", error->full_message); @@ -687,6 +700,14 @@ mono_error_prepare_exception (MonoError *oerror, MonoError *error_out) case MONO_ERROR_CLEANUP_CALLED_SENTINEL: mono_error_set_execution_engine (error_out, "MonoError reused after mono_error_cleanup"); break; + + case MONO_ERROR_INVALID_PROGRAM: { + gboolean lacks_message = error->flags & MONO_ERROR_INCOMPLETE; + if (lacks_message) + return mono_exception_from_name_msg (mono_defaults.corlib, "System", "InvalidProgramException", ""); + else + return mono_exception_from_name_msg (mono_defaults.corlib, "System", "InvalidProgramException", error->full_message); + } default: mono_error_set_execution_engine (error_out, "Invalid error-code %d", error->error_code); } diff --git a/mono/utils/mono-error.h b/mono/utils/mono-error.h index 2a98d4839f..0aba0e1d61 100644 --- a/mono/utils/mono-error.h +++ b/mono/utils/mono-error.h @@ -26,6 +26,8 @@ enum { MONO_ERROR_ARGUMENT = 7, MONO_ERROR_ARGUMENT_NULL = 11, MONO_ERROR_NOT_VERIFIABLE = 8, + MONO_ERROR_INVALID_PROGRAM = 12, + /* * This is a generic error mechanism is you need to raise an arbitrary corlib exception. * You must pass the exception name otherwise prepare_exception will fail with internal execution. diff --git a/mono/utils/mono-log-android.c b/mono/utils/mono-log-android.c new file mode 100644 index 0000000000..fde2fd0c6b --- /dev/null +++ b/mono/utils/mono-log-android.c @@ -0,0 +1,92 @@ +/* + * mono-log-android.c: Android-specific interface to the logger + * + * This module contains the Android logcat logger interface + * + * Author: + * Marek Habersack + * + */ +#include + +#if defined (PLATFORM_ANDROID) + +#include +#include "mono-logger-internals.h" + +/** + * mono_log_open_logcat + * + * Open access to Android logcat (no-op) + * + * @path - Not used + * @userData - Not used + */ +void +mono_log_open_logcat (const char *path, void *userData) +{ + /* No-op on Android */ +} + +/** + * mono_log_write_logcat + * + * Write data to Android logcat. + * + * @domain - Identifier string + * @level - Logging level flags + * @format - Printf format string + * @vargs - Variable argument list + */ +void +mono_log_write_logcat (const char *log_domain, GLogLevelFlags level, mono_bool hdr, const char *message) +{ + android_LogPriority apriority; + + switch (level & G_LOG_LEVEL_MASK) + { + case G_LOG_LEVEL_ERROR: + apriority = ANDROID_LOG_FATAL; + break; + + case G_LOG_LEVEL_CRITICAL: + apriority = ANDROID_LOG_ERROR; + break; + + case G_LOG_LEVEL_WARNING: + apriority = ANDROID_LOG_WARN; + break; + + case G_LOG_LEVEL_MESSAGE: + apriority = ANDROID_LOG_INFO; + break; + + case G_LOG_LEVEL_INFO: + apriority = ANDROID_LOG_DEBUG; + break; + + case G_LOG_LEVEL_DEBUG: + apriority = ANDROID_LOG_VERBOSE; + break; + + default: + apriority = ANDROID_LOG_UNKNOWN; + break; + } + + __android_log_write (apriority, log_domain, message); + if (apriority == ANDROID_LOG_FATAL) + abort (); +} + +/** + * mono_log_close_logcat + * + * Close access to Android logcat (no-op) + */ +void +mono_log_close_logcat () +{ + /* No-op on Android */ +} +#endif diff --git a/mono/utils/mono-log-common.c b/mono/utils/mono-log-common.c new file mode 100644 index 0000000000..4948b91b80 --- /dev/null +++ b/mono/utils/mono-log-common.c @@ -0,0 +1,152 @@ +/* + * mono-log-common.c: Platform-independent interface to the logger + * + * This module contains the POSIX syslog logger interface + * + * Author: + * Neale Ferguson + * + */ +#include + +#ifdef HAVE_UNISTD_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#ifndef HOST_WIN32 +#include +#else +#include +#endif +#include "mono-logger-internals.h" + +static FILE *logFile = NULL; +static void *logUserData = NULL; + +/** + * mapSyslogLevel: + * + * @level - GLogLevelFlags value + * @returns The equivalent character identifier + */ +static inline char +mapLogFileLevel(GLogLevelFlags level) +{ + if (level & G_LOG_LEVEL_ERROR) + return ('E'); + if (level & G_LOG_LEVEL_CRITICAL) + return ('C'); + if (level & G_LOG_LEVEL_WARNING) + return ('W'); + if (level & G_LOG_LEVEL_MESSAGE) + return ('N'); + if (level & G_LOG_LEVEL_INFO) + return ('I'); + if (level & G_LOG_LEVEL_DEBUG) + return ('D'); + return ('I'); +} + +/** + * mono_log_open_logfile + * + * Open the logfile. If the path is not specified default to stdout. If the + * open fails issue a warning and use stdout as the log file destination. + * + * @path - Path for log file + * @userData - Not used + */ +void +mono_log_open_logfile(const char *path, void *userData) +{ + if (path == NULL) { + logFile = stdout; + } else { +#ifndef HOST_WIN32 + logFile = fopen(path, "w"); +#else + gunichar2 *wPath = g_utf8_to_utf16(path, -1, 0, 0, 0); + if (wPath != NULL) { + logFile = _wfopen((wchar_t *) wPath, L"w"); + g_free (wPath); + } +#endif + if (logFile == NULL) { + g_warning("opening of log file %s failed with %s - defaulting to stdout", + path, strerror(errno)); + logFile = stdout; + } + } + logUserData = userData; +} + +/** + * mono_log_write_logfile + * + * Write data to the log file. + * + * @domain - Identifier string + * @level - Logging level flags + * @format - Printf format string + * @vargs - Variable argument list + */ +void +mono_log_write_logfile (const char *log_domain, GLogLevelFlags level, mono_bool hdr, const char *message) +{ + time_t t; + + if (logFile == NULL) + logFile = stdout; + + if (hdr) { + pid_t pid; + char logTime [80]; + +#ifndef HOST_WIN32 + struct tm tod; + time(&t); + localtime_r(&t, &tod); + pid = getpid(); + strftime(logTime, sizeof(logTime), "%Y-%m-%d %H:%M:%S", &tod); +#else + struct tm *tod; + time(&t); + tod = localtime(&t); + pid = _getpid(); + strftime(logTime, sizeof(logTime), "%F %T", tod); +#endif + fprintf (logFile, "%s level[%c] mono[%d]: %s\n", logTime, mapLogFileLevel (level), pid, message); + } else { + fprintf (logFile, "%s%s%s\n", + log_domain != NULL ? log_domain : "", + log_domain != NULL ? ": " : "", + message); + } + + fflush(logFile); + + if (level & G_LOG_LEVEL_ERROR) + abort(); +} + +/** + * mono_log_close_logfile + * + * Close the log file + */ +void +mono_log_close_logfile() +{ + if (logFile) { + if (logFile != stdout) + fclose(logFile); + logFile = NULL; + } +} diff --git a/mono/utils/mono-log-darwin.c b/mono/utils/mono-log-darwin.c new file mode 100644 index 0000000000..12142913e4 --- /dev/null +++ b/mono/utils/mono-log-darwin.c @@ -0,0 +1,47 @@ +/* + * mono-log-darwin.c: Darwin-specific interface to the logger + * + */ +#include + +#if defined(HOST_IOS) + +#include +#include "mono-logger-internals.h" +static int +to_asl_priority (GLogLevelFlags log_level) +{ + switch (log_level & G_LOG_LEVEL_MASK) + { + case G_LOG_LEVEL_ERROR: return ASL_LEVEL_CRIT; + case G_LOG_LEVEL_CRITICAL: return ASL_LEVEL_ERR; + case G_LOG_LEVEL_WARNING: return ASL_LEVEL_WARNING; + case G_LOG_LEVEL_MESSAGE: return ASL_LEVEL_NOTICE; + case G_LOG_LEVEL_INFO: return ASL_LEVEL_INFO; + case G_LOG_LEVEL_DEBUG: return ASL_LEVEL_DEBUG; + } + return ASL_LEVEL_ERR; +} + +void +mono_log_open_asl (const char *path, void *userData) +{ +} + +void +mono_log_write_asl (const char *log_domain, GLogLevelFlags level, mono_bool hdr, const char *message) +{ + asl_log (NULL, NULL, to_asl_priority (level), "%s%s%s\n", + log_domain != NULL ? log_domain : "", + log_domain != NULL ? ": " : "", + message); + + if (level & G_LOG_LEVEL_ERROR) + abort(); +} + +void +mono_log_close_asl () +{ +} +#endif diff --git a/mono/utils/mono-log-posix.c b/mono/utils/mono-log-posix.c new file mode 100644 index 0000000000..6d25d3a611 --- /dev/null +++ b/mono/utils/mono-log-posix.c @@ -0,0 +1,101 @@ +/* + * mono-log-posix.c: POSIX interface to the logger + * + * This module contains the POSIX syslog logger routines + * + * Author: + * Neale Ferguson + * + */ +#include + +#ifdef HAVE_UNISTD_H +#include +#endif + +#if defined(_POSIX_VERSION) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mono-logger-internals.h" + +static void *logUserData = NULL; + +/** + * mapSyslogLevel: + * + * @level - GLogLevelFlags value + * @returns The equivalent syslog priority value + */ +static __inline__ int +mapSyslogLevel(GLogLevelFlags level) +{ + if (level & G_LOG_LEVEL_ERROR) + return (LOG_ERR); + if (level & G_LOG_LEVEL_CRITICAL) + return (LOG_CRIT); + if (level & G_LOG_LEVEL_WARNING) + return (LOG_WARNING); + if (level & G_LOG_LEVEL_MESSAGE) + return (LOG_NOTICE); + if (level & G_LOG_LEVEL_INFO) + return (LOG_INFO); + if (level & G_LOG_LEVEL_DEBUG) + return (LOG_DEBUG); + return (LOG_INFO); +} + +/** + * mono_log_open_logfile + * + * Open the syslog interface specifying that we want our PID recorded + * and that we're using the LOG_USER facility. + * + * @ident - Identifier: ignored + * @userData - Not used + */ +void +mono_log_open_syslog(const char *ident, void *userData) +{ + openlog("mono", LOG_PID, LOG_USER); + logUserData = userData; +} + +/** + * mono_log_write_syslog + * + * Write data to the log file. + * + * @domain - Identifier string + * @level - Logging level flags + * @format - Printf format string + * @vargs - Variable argument list + */ +void +mono_log_write_syslog(const char *domain, GLogLevelFlags level, mono_bool hdr, const char *message) +{ + syslog (mapSyslogLevel(level), "%s", message); + + if (level & G_LOG_LEVEL_ERROR) + abort(); +} + +/** + * mono_log_close_logfile + * + * Close the log file + */ +void +mono_log_close_syslog() +{ + closelog(); +} +#endif diff --git a/mono/utils/mono-log-windows.c b/mono/utils/mono-log-windows.c new file mode 100644 index 0000000000..f6cd987fbb --- /dev/null +++ b/mono/utils/mono-log-windows.c @@ -0,0 +1,124 @@ +/* + * mono-log-windows.c: Simplistic simulation of a syslog logger for Windows + * + * This module contains the Windows syslog logger interface + * + * Author: + * Neale Ferguson + * + */ +#include + +#ifdef HAVE_UNISTD_H +#include +#endif + +#ifdef HOST_WIN32 + +#include +#include +#include +#include +#include +#include +#include +#include +#include "mono-logger-internals.h" + +static FILE *logFile = NULL; +static void *logUserData = NULL; +static wchar_t *logFileName = L".//mono.log"; + +/** + * mapSyslogLevel: + * + * @level - GLogLevelFlags value + * @returns The equivalent character identifier + */ +static inline char +mapLogFileLevel(GLogLevelFlags level) +{ + if (level & G_LOG_LEVEL_ERROR) + return ('E'); + if (level & G_LOG_LEVEL_CRITICAL) + return ('C'); + if (level & G_LOG_LEVEL_WARNING) + return ('W'); + if (level & G_LOG_LEVEL_MESSAGE) + return ('N'); + if (level & G_LOG_LEVEL_INFO) + return ('I'); + if (level & G_LOG_LEVEL_DEBUG) + return ('D'); + return ('I'); +} + +/** + * mono_log_open_syslog + * + * Open the syslog file. If the open fails issue a warning and + * use stdout as the log file destination. + * + * @ident - Identifier: ignored + * @userData - Not used + */ +void +mono_log_open_syslog(const char *ident, void *userData) +{ + logFile = _wfopen(logFileName, L"w"); + if (logFile == NULL) { + g_warning("opening of log file %s failed with %s", + strerror(errno)); + logFile = stdout; + } + logUserData = userData; +} + +/** + * mono_log_write_syslog + * + * Write data to the syslog file. + * + * @domain - Identifier string + * @level - Logging level flags + * @format - Printf format string + * @vargs - Variable argument list + */ +void +mono_log_write_syslog(const char *domain, GLogLevelFlags level, mono_bool hdr, const char *message) +{ + time_t t; + pid_t pid; + char logTime [80]; + + if (logFile == NULL) + logFile = stdout; + + struct tm *tod; + time(&t); + tod = localtime(&t); + pid = _getpid(); + strftime(logTime, sizeof(logTime), "%F %T", tod); + + fprintf (logFile, "%s level[%c] mono[%d]: %s\n", logTime, mapLogFileLevel (level), pid, message); + + fflush(logFile); + + if (level & G_LOG_LEVEL_ERROR) + abort(); +} + +/** + * mono_log_close_syslog + * + * Close the syslog file + */ +void +mono_log_close_syslog() +{ + if (logFile) { + fclose(logFile); + logFile = NULL; + } +} +#endif diff --git a/mono/utils/mono-logger-internals.h b/mono/utils/mono-logger-internals.h index 89e9a01023..b10ad2236a 100644 --- a/mono/utils/mono-logger-internals.h +++ b/mono/utils/mono-logger-internals.h @@ -17,6 +17,7 @@ typedef enum { MONO_TRACE_THREADPOOL = (1<<7), MONO_TRACE_IO_THREADPOOL = (1<<8), MONO_TRACE_IO_LAYER = (1<<9), + MONO_TRACE_W32HANDLE = (1<<10), MONO_TRACE_ALL = MONO_TRACE_ASSEMBLY | MONO_TRACE_TYPE | MONO_TRACE_DLLIMPORT | @@ -26,7 +27,8 @@ typedef enum { MONO_TRACE_SECURITY | MONO_TRACE_THREADPOOL | MONO_TRACE_IO_THREADPOOL | - MONO_TRACE_IO_LAYER + MONO_TRACE_IO_LAYER | + MONO_TRACE_W32HANDLE } MonoTraceMask; extern GLogLevelFlags mono_internal_current_level; @@ -147,6 +149,44 @@ mono_trace_message(MonoTraceMask mask, const char *format, ...) #endif +/* Internal logging API */ +typedef void (*MonoLoggerOpen) (const char *, void *); +typedef void (*MonoLoggerWrite) (const char *, GLogLevelFlags, mono_bool, const char *); +typedef void (*MonoLoggerClose) (void); + +typedef struct _MonoLogCallParm_ { + MonoLoggerOpen opener; /* Routine to open logging */ + MonoLoggerWrite writer; /* Routine to write log data */ + MonoLoggerClose closer; /* Routine to close logging */ + char *dest; /* Log destination */ + void *user_data; /* User data from legacy handler */ + mono_bool header; /* Whether we want pid/time/date in log message */ +} MonoLogCallParm; + +void mono_trace_set_log_handler_internal (MonoLogCallParm *callback, void *user_data); +void mono_trace_set_logdest_string (const char *value); +void mono_trace_set_logheader_string (const char *value); + +void mono_log_open_syslog (const char *, void *); +void mono_log_write_syslog (const char *, GLogLevelFlags, mono_bool, const char *); +void mono_log_close_syslog (void); + +void mono_log_open_logfile (const char *, void *); +void mono_log_write_logfile (const char *, GLogLevelFlags, mono_bool, const char *); +void mono_log_close_logfile (void); + +#if PLATFORM_ANDROID +void mono_log_open_logcat (const char *path, void *userData); +void mono_log_write_logcat (const char *log_domain, GLogLevelFlags level, mono_bool hdr, const char *message); +void mono_log_close_logcat (void); +#endif + +#if defined(HOST_IOS) +void mono_log_open_asl (const char *path, void *userData); +void mono_log_write_asl (const char *log_domain, GLogLevelFlags level, mono_bool hdr, const char *message); +void mono_log_close_asl (void); + +#endif G_END_DECLS diff --git a/mono/utils/mono-logger.c b/mono/utils/mono-logger.c index 7d0c9ce12a..b4367a7336 100644 --- a/mono/utils/mono-logger.c +++ b/mono/utils/mono-logger.c @@ -11,13 +11,26 @@ typedef struct { MonoTraceMask mask; } MonoLogLevelEntry; -GLogLevelFlags mono_internal_current_level = INT_MAX; -MonoTraceMask mono_internal_current_mask = MONO_TRACE_ALL; +GLogLevelFlags mono_internal_current_level = INT_MAX; +MonoTraceMask mono_internal_current_mask = MONO_TRACE_ALL; +gboolean mono_trace_log_header = FALSE; static GQueue *level_stack = NULL; static const char *mono_log_domain = "Mono"; static MonoPrintCallback print_callback, printerr_callback; +static MonoLogCallParm logCallback = { + .opener = NULL, + .writer = NULL, + .closer = NULL, + .header = FALSE +}; + +typedef struct { + MonoLogCallback legacy_callback; + gpointer user_data; +} UserSuppliedLoggerUserData; + /** * mono_trace_init: * @@ -32,6 +45,8 @@ mono_trace_init (void) mono_trace_set_mask_string(g_getenv("MONO_LOG_MASK")); mono_trace_set_level_string(g_getenv("MONO_LOG_LEVEL")); + mono_trace_set_logheader_string(g_getenv("MONO_LOG_HEADER")); + mono_trace_set_logdest_string(g_getenv("MONO_LOG_DEST")); } } @@ -48,6 +63,7 @@ mono_trace_cleanup (void) g_free (g_queue_pop_head (level_stack)); } + logCallback.closer(); g_queue_free (level_stack); level_stack = NULL; } @@ -65,13 +81,19 @@ mono_trace_cleanup (void) void mono_tracev_inner (GLogLevelFlags level, MonoTraceMask mask, const char *format, va_list args) { + char *log_message; if (level_stack == NULL) { mono_trace_init (); if(level > mono_internal_current_level || !(mask & mono_internal_current_mask)) return; } - g_logv (mono_log_domain, level, format, args); + g_assert (logCallback.opener); // mono_trace_init should have provided us with one! + + if (g_vasprintf (&log_message, format, args) < 0) + return; + logCallback.writer (mono_log_domain, level, logCallback.header, log_message); + g_free (log_message); } /** @@ -107,7 +129,66 @@ mono_trace_set_mask (MonoTraceMask mask) if(level_stack == NULL) mono_trace_init(); - mono_internal_current_mask = mask; + mono_internal_current_mask = mask; +} + +/** + * mono_trace_set_logdest: + * + * @dest: Destination for logging + * + * Sets the current logging destination. This can be a file or, if supported, + * syslog. + */ +void +mono_trace_set_logdest_string (const char *dest) +{ + MonoLogCallParm logger; + + if(level_stack == NULL) + mono_trace_init(); + +#if PLATFORM_ANDROID + logger.opener = mono_log_open_logcat; + logger.writer = mono_log_write_logcat; + logger.closer = mono_log_close_logcat; + logger.dest = (char*) dest; +#elif defined (HOST_IOS) + logger.opener = mono_log_open_asl; + logger.writer = mono_log_write_asl; + logger.closer = mono_log_close_asl; + logger.dest = (char*) dest; +#else + if ((dest == NULL) || (strcmp("syslog", dest) != 0)) { + logger.opener = mono_log_open_logfile; + logger.writer = mono_log_write_logfile; + logger.closer = mono_log_close_logfile; + logger.dest = (char *) dest; + } else { + logger.opener = mono_log_open_syslog; + logger.writer = mono_log_write_syslog; + logger.closer = mono_log_close_syslog; + logger.dest = (char *) dest; + } +#endif + mono_trace_set_log_handler_internal(&logger, NULL); +} + +/** + * mono_trace_set_logheader: + * + * @head: Whether we want pid/date/time header on log messages + * + * Sets the current logging header option. + */ +void +mono_trace_set_logheader_string(const char *head) +{ + if (head == NULL) { + mono_trace_log_header = FALSE; + } else { + mono_trace_log_header = TRUE; + } } /** @@ -193,10 +274,11 @@ mono_trace_set_mask_string (const char *value) const char *tok; guint32 flags = 0; - const char *valid_flags[] = {"asm", "type", "dll", "gc", "cfg", "aot", "security", "threadpool", "io-threadpool", "io-layer", "all", NULL}; + const char *valid_flags[] = {"asm", "type", "dll", "gc", "cfg", "aot", "security", "threadpool", "io-threadpool", "io-layer", "w32handle", "all", NULL}; const MonoTraceMask valid_masks[] = {MONO_TRACE_ASSEMBLY, MONO_TRACE_TYPE, MONO_TRACE_DLLIMPORT, MONO_TRACE_GC, MONO_TRACE_CONFIG, MONO_TRACE_AOT, MONO_TRACE_SECURITY, - MONO_TRACE_THREADPOOL, MONO_TRACE_IO_THREADPOOL, MONO_TRACE_IO_LAYER, MONO_TRACE_ALL }; + MONO_TRACE_THREADPOOL, MONO_TRACE_IO_THREADPOOL, MONO_TRACE_IO_LAYER, + MONO_TRACE_W32HANDLE, MONO_TRACE_ALL }; if(!value) return; @@ -236,30 +318,120 @@ mono_trace_is_traced (GLogLevelFlags level, MonoTraceMask mask) return (level <= mono_internal_current_level && mask & mono_internal_current_mask); } -static MonoLogCallback log_callback; - -static const char* +/** + * log_level_get_name + * @log_level severity level + * + * Convert log level into a string for legacy log handlers + */ +static const char * log_level_get_name (GLogLevelFlags log_level) { - switch (log_level & G_LOG_LEVEL_MASK) { - case G_LOG_LEVEL_ERROR: return "error"; - case G_LOG_LEVEL_CRITICAL: return "critical"; - case G_LOG_LEVEL_WARNING: return "warning"; - case G_LOG_LEVEL_MESSAGE: return "message"; - case G_LOG_LEVEL_INFO: return "info"; - case G_LOG_LEVEL_DEBUG: return "debug"; - default: return "unknown"; - } -} - -static void -log_adapter (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data) -{ - log_callback (log_domain, log_level_get_name (log_level), message, log_level & G_LOG_LEVEL_ERROR, user_data); + switch (log_level & G_LOG_LEVEL_MASK) { + case G_LOG_LEVEL_ERROR: return "error"; + case G_LOG_LEVEL_CRITICAL: return "critical"; + case G_LOG_LEVEL_WARNING: return "warning"; + case G_LOG_LEVEL_MESSAGE: return "message"; + case G_LOG_LEVEL_INFO: return "info"; + case G_LOG_LEVEL_DEBUG: return "debug"; + default: return "unknown"; + } } /** - * mono_trace_set_log_handler: + * callback_adapter + * + * @log_domain Message prefix + * @log_level Severity + * @message Message to be written + * @fatal Fatal flag - write then abort + * @user_data Argument passed to @callback + * + * This adapts the old callback writer exposed by MonoCallback to the newer method of + * logging. We ignore the header request as legacy handlers never had headers. + */ +static void +callback_adapter (const char *domain, GLogLevelFlags level, mono_bool fatal, const char *message) +{ + UserSuppliedLoggerUserData *ll =logCallback.user_data; + + ll->legacy_callback (domain, log_level_get_name(level), message, fatal, ll->user_data); +} + +static void +eglib_log_adapter (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data) +{ + UserSuppliedLoggerUserData *ll = logCallback.user_data; + + ll->legacy_callback (log_domain, log_level_get_name (log_level), message, log_level & G_LOG_LEVEL_ERROR, ll->user_data); +} + +/** + * legacy_opener + * + * Dummy routine for older style loggers + */ +static void +legacy_opener(const char *path, void *user_data) +{ + /* nothing to do */ +} + +/** + * legacy_closer + * + * Cleanup routine for older style loggers + */ +static void +legacy_closer(void) +{ + if (logCallback.user_data != NULL) { + g_free (logCallback.user_data); /* This is a UserSuppliedLoggerUserData struct */ + logCallback.opener = NULL; + logCallback.writer = NULL; + logCallback.closer = NULL; + logCallback.user_data = NULL; + logCallback.header = FALSE; + } +} + +/** + * mono_trace_set_log_handler: + * + * @callback The callback that will replace the default logging handler + * @user_data Argument passed to @callback + * + * The log handler replaces the default runtime logger. All logging requests with be routed to it. + * If the fatal argument in the callback is true, the callback must abort the current process. The runtime expects that + * execution will not resume after a fatal error. + */ +void +mono_trace_set_log_handler (MonoLogCallback callback, void *user_data) +{ + g_assert (callback); + + if (logCallback.closer != NULL) + logCallback.closer(); + UserSuppliedLoggerUserData *ll = g_malloc (sizeof (UserSuppliedLoggerUserData)); + ll->legacy_callback = callback; + ll->user_data = user_data; + logCallback.opener = legacy_opener; + logCallback.writer = callback_adapter; + logCallback.closer = legacy_closer; + logCallback.user_data = ll; + logCallback.dest = NULL; + + g_log_set_default_handler (eglib_log_adapter, user_data); +} + +static void +structured_log_adapter (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data) +{ + logCallback.writer (log_domain, log_level, logCallback.header, message); +} + +/** + * mono_trace_set_log_handler_internal: * * @callback The callback that will replace the default logging handler * @user_data Argument passed to @callback @@ -269,11 +441,19 @@ log_adapter (const gchar *log_domain, GLogLevelFlags log_level, const gchar *mes * execution will not resume after a fatal error. */ void -mono_trace_set_log_handler (MonoLogCallback callback, void *user_data) +mono_trace_set_log_handler_internal (MonoLogCallParm *callback, void *user_data) { g_assert (callback); - log_callback = callback; - g_log_set_default_handler (log_adapter, user_data); + if (logCallback.closer != NULL) + logCallback.closer(); + logCallback.opener = callback->opener; + logCallback.writer = callback->writer; + logCallback.closer = callback->closer; + logCallback.header = mono_trace_log_header; + logCallback.dest = callback->dest; + logCallback.opener (logCallback.dest, user_data); + + g_log_set_default_handler (structured_log_adapter, user_data); } static void diff --git a/mono/utils/mono-logger.h b/mono/utils/mono-logger.h index 36f7714f2e..5f0943d5e1 100644 --- a/mono/utils/mono-logger.h +++ b/mono/utils/mono-logger.h @@ -10,8 +10,8 @@ mono_trace_set_level_string (const char *value); MONO_API void mono_trace_set_mask_string (const char *value); -typedef void (*MonoLogCallback) (const char *log_domain, const char *log_level, const char *message, mono_bool fatal, void *user_data); typedef void (*MonoPrintCallback) (const char *string, mono_bool is_stdout); +typedef void (*MonoLogCallback) (const char *log_domain, const char *log_level, const char *message, mono_bool fatal, void *user_data); MONO_API void mono_trace_set_log_handler (MonoLogCallback callback, void *user_data); @@ -22,7 +22,6 @@ mono_trace_set_print_handler (MonoPrintCallback callback); MONO_API void mono_trace_set_printerr_handler (MonoPrintCallback callback); - MONO_END_DECLS #endif /* __MONO_LOGGER_H__ */ diff --git a/mono/utils/mono-mmap.c b/mono/utils/mono-mmap.c index 7fa483ce59..76ca8d0d33 100644 --- a/mono/utils/mono-mmap.c +++ b/mono/utils/mono-mmap.c @@ -484,7 +484,7 @@ mono_pagesize (void) void* mono_valloc (void *addr, size_t length, int flags) { - return malloc (length); + return g_malloc (length); } void* @@ -498,7 +498,7 @@ mono_valloc_aligned (size_t length, size_t alignment, int flags) int mono_vfree (void *addr, size_t length) { - free (addr); + g_free (addr); return 0; } diff --git a/mono/utils/mono-os-mutex.h b/mono/utils/mono-os-mutex.h index 1317b0b462..52cef09d84 100644 --- a/mono/utils/mono-os-mutex.h +++ b/mono/utils/mono-os-mutex.h @@ -33,81 +33,123 @@ G_BEGIN_DECLS +#ifndef MONO_INFINITE_WAIT +#define MONO_INFINITE_WAIT ((guint32) 0xFFFFFFFF) +#endif + + #if !defined(HOST_WIN32) typedef pthread_mutex_t mono_mutex_t; typedef pthread_cond_t mono_cond_t; -static inline int +static inline void mono_os_mutex_init (mono_mutex_t *mutex) { - return pthread_mutex_init (mutex, NULL); + int res; + + res = pthread_mutex_init (mutex, NULL); + if (G_UNLIKELY (res != 0)) + g_error ("%s: pthread_mutex_init failed with \"%s\" (%d)", __func__, g_strerror (res), res); } -static inline int +static inline void mono_os_mutex_init_recursive (mono_mutex_t *mutex) { int res; pthread_mutexattr_t attr; - pthread_mutexattr_init (&attr); - pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE); - res = pthread_mutex_init (mutex, &attr); - pthread_mutexattr_destroy (&attr); + res = pthread_mutexattr_init (&attr); + if (G_UNLIKELY (res != 0)) + g_error ("%s: pthread_mutexattr_init failed with \"%s\" (%d)", __func__, g_strerror (res), res); - return res; + res = pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE); + if (G_UNLIKELY (res != 0)) + g_error ("%s: pthread_mutexattr_settype failed with \"%s\" (%d)", __func__, g_strerror (res), res); + + res = pthread_mutex_init (mutex, &attr); + if (G_UNLIKELY (res != 0)) + g_error ("%s: pthread_mutex_init failed with \"%s\" (%d)", __func__, g_strerror (res), res); + + res = pthread_mutexattr_destroy (&attr); + if (G_UNLIKELY (res != 0)) + g_error ("%s: pthread_mutexattr_destroy failed with \"%s\" (%d)", __func__, g_strerror (res), res); } static inline int mono_os_mutex_destroy (mono_mutex_t *mutex) { - return pthread_mutex_destroy (mutex); + int res; + + res = pthread_mutex_destroy (mutex); + if (G_UNLIKELY (res != 0 && res != EBUSY)) + g_error ("%s: pthread_mutex_destroy failed with \"%s\" (%d)", __func__, g_strerror (res), res); + + return res != 0 ? -1 : 0; } -static inline int +static inline void mono_os_mutex_lock (mono_mutex_t *mutex) { int res; res = pthread_mutex_lock (mutex); - g_assert (res != EINVAL); - - return res; + if (G_UNLIKELY (res != 0)) + g_error ("%s: pthread_mutex_lock failed with \"%s\" (%d)", __func__, g_strerror (res), res); } static inline int mono_os_mutex_trylock (mono_mutex_t *mutex) { - return pthread_mutex_trylock (mutex); + int res; + + res = pthread_mutex_trylock (mutex); + if (G_UNLIKELY (res != 0 && res != EBUSY)) + g_error ("%s: pthread_mutex_trylock failed with \"%s\" (%d)", __func__, g_strerror (res), res); + + return res != 0 ? -1 : 0; } -static inline int +static inline void mono_os_mutex_unlock (mono_mutex_t *mutex) { - return pthread_mutex_unlock (mutex); + int res; + + res = pthread_mutex_unlock (mutex); + if (G_UNLIKELY (res != 0)) + g_error ("%s: pthread_mutex_unlock failed with \"%s\" (%d)", __func__, g_strerror (res), res); } -static inline int +static inline void mono_os_cond_init (mono_cond_t *cond) { - return pthread_cond_init (cond, NULL); + int res; + + res = pthread_cond_init (cond, NULL); + if (G_UNLIKELY (res != 0)) + g_error ("%s: pthread_cond_init failed with \"%s\" (%d)", __func__, g_strerror (res), res); } static inline int mono_os_cond_destroy (mono_cond_t *cond) { - return pthread_cond_destroy (cond); + int res; + + res = pthread_cond_destroy (cond); + if (G_UNLIKELY (res != 0 && res != EBUSY)) + g_error ("%s: pthread_cond_destroy failed with \"%s\" (%d)", __func__, g_strerror (res), res); + + return res != 0 ? -1 : 0; } -static inline int +static inline void mono_os_cond_wait (mono_cond_t *cond, mono_mutex_t *mutex) { int res; res = pthread_cond_wait (cond, mutex); - g_assert (res != EINVAL); - - return res; + if (G_UNLIKELY (res != 0)) + g_error ("%s: pthread_cond_wait failed with \"%s\" (%d)", __func__, g_strerror (res), res); } static inline int @@ -118,12 +160,17 @@ mono_os_cond_timedwait (mono_cond_t *cond, mono_mutex_t *mutex, guint32 timeout_ gint64 usecs; int res; - if (timeout_ms == (guint32) 0xFFFFFFFF) - return mono_os_cond_wait (cond, mutex); + if (timeout_ms == MONO_INFINITE_WAIT) { + mono_os_cond_wait (cond, mutex); + return 0; + } /* ms = 10^-3, us = 10^-6, ns = 10^-9 */ - gettimeofday (&tv, NULL); + res = gettimeofday (&tv, NULL); + if (G_UNLIKELY (res != 0)) + g_error ("%s: gettimeofday failed with \"%s\" (%d)", __func__, g_strerror (errno), errno); + tv.tv_sec += timeout_ms / 1000; usecs = tv.tv_usec + ((timeout_ms % 1000) * 1000); if (usecs >= 1000000) { @@ -134,21 +181,30 @@ mono_os_cond_timedwait (mono_cond_t *cond, mono_mutex_t *mutex, guint32 timeout_ ts.tv_nsec = usecs * 1000; res = pthread_cond_timedwait (cond, mutex, &ts); - g_assert (res != EINVAL); + if (G_UNLIKELY (res != 0 && res != ETIMEDOUT)) + g_error ("%s: pthread_cond_timedwait failed with \"%s\" (%d)", __func__, g_strerror (res), res); - return res; + return res != 0 ? -1 : 0; } -static inline int +static inline void mono_os_cond_signal (mono_cond_t *cond) { - return pthread_cond_signal (cond); + int res; + + res = pthread_cond_signal (cond); + if (G_UNLIKELY (res != 0)) + g_error ("%s: pthread_cond_signal failed with \"%s\" (%d)", __func__, g_strerror (res), res); } -static inline int +static inline void mono_os_cond_broadcast (mono_cond_t *cond) { - return pthread_cond_broadcast (cond); + int res; + + res = pthread_cond_broadcast (cond); + if (G_UNLIKELY (res != 0)) + g_error ("%s: pthread_cond_broadcast failed with \"%s\" (%d)", __func__, g_strerror (res), res); } #else @@ -220,18 +276,24 @@ WINBASEAPI BOOL WINAPI InitializeCriticalSectionEx(LPCRITICAL_SECTION lpCritical typedef CRITICAL_SECTION mono_mutex_t; typedef CONDITION_VARIABLE mono_cond_t; -static inline int +static inline void mono_os_mutex_init (mono_mutex_t *mutex) { - InitializeCriticalSectionEx (mutex, 0, CRITICAL_SECTION_NO_DEBUG_INFO); - return 0; + BOOL res; + + res = InitializeCriticalSectionEx (mutex, 0, CRITICAL_SECTION_NO_DEBUG_INFO); + if (G_UNLIKELY (res == 0)) + g_error ("%s: InitializeCriticalSectionEx failed with error %d", __func__, GetLastError ()); } -static inline int +static inline void mono_os_mutex_init_recursive (mono_mutex_t *mutex) { - InitializeCriticalSectionEx (mutex, 0, CRITICAL_SECTION_NO_DEBUG_INFO); - return 0; + BOOL res; + + res = InitializeCriticalSectionEx (mutex, 0, CRITICAL_SECTION_NO_DEBUG_INFO); + if (G_UNLIKELY (res == 0)) + g_error ("%s: InitializeCriticalSectionEx failed with error %d", __func__, GetLastError ()); } static inline int @@ -241,31 +303,28 @@ mono_os_mutex_destroy (mono_mutex_t *mutex) return 0; } -static inline int +static inline void mono_os_mutex_lock (mono_mutex_t *mutex) { EnterCriticalSection (mutex); - return 0; } static inline int mono_os_mutex_trylock (mono_mutex_t *mutex) { - return TryEnterCriticalSection (mutex) != 0 ? 0 : 1; + return TryEnterCriticalSection (mutex) == 0 ? -1 : 0; } -static inline int +static inline void mono_os_mutex_unlock (mono_mutex_t *mutex) { LeaveCriticalSection (mutex); - return 0; } -static inline int +static inline void mono_os_cond_init (mono_cond_t *cond) { InitializeConditionVariable (cond); - return 0; } static inline int @@ -275,30 +334,38 @@ mono_os_cond_destroy (mono_cond_t *cond) return 0; } -static inline int +static inline void mono_os_cond_wait (mono_cond_t *cond, mono_mutex_t *mutex) { - return SleepConditionVariableCS (cond, mutex, INFINITE) ? 0 : 1; + BOOL res; + + res = SleepConditionVariableCS (cond, mutex, INFINITE); + if (G_UNLIKELY (res == 0)) + g_error ("%s: SleepConditionVariableCS failed with error %d", __func__, GetLastError ()); } static inline int mono_os_cond_timedwait (mono_cond_t *cond, mono_mutex_t *mutex, guint32 timeout_ms) { - return SleepConditionVariableCS (cond, mutex, timeout_ms) ? 0 : 1; + BOOL res; + + res = SleepConditionVariableCS (cond, mutex, timeout_ms); + if (G_UNLIKELY (res == 0 && GetLastError () != ERROR_TIMEOUT)) + g_error ("%s: SleepConditionVariableCS failed with error %d", __func__, GetLastError ()); + + return res == 0 ? -1 : 0; } -static inline int +static inline void mono_os_cond_signal (mono_cond_t *cond) { WakeConditionVariable (cond); - return 0; } -static inline int +static inline void mono_os_cond_broadcast (mono_cond_t *cond) { WakeAllConditionVariable (cond); - return 0; } #endif diff --git a/mono/utils/mono-os-semaphore.h b/mono/utils/mono-os-semaphore.h index 16e3d463b8..9f59ce1ea8 100644 --- a/mono/utils/mono-os-semaphore.h +++ b/mono/utils/mono-os-semaphore.h @@ -40,6 +40,10 @@ #define NSEC_PER_SEC (1000 * 1000 * 1000) #endif +#ifndef MONO_INFINITE_WAIT +#define MONO_INFINITE_WAIT ((guint32) 0xFFFFFFFF) +#endif + G_BEGIN_DECLS typedef enum { @@ -47,30 +51,45 @@ typedef enum { MONO_SEM_FLAGS_ALERTABLE = 1 << 0, } MonoSemFlags; +typedef enum { + MONO_SEM_TIMEDWAIT_RET_SUCCESS = 0, + MONO_SEM_TIMEDWAIT_RET_ALERTED = -1, + MONO_SEM_TIMEDWAIT_RET_TIMEDOUT = -2, +} MonoSemTimedwaitRet; + #if defined(USE_MACH_SEMA) typedef semaphore_t MonoSemType; -static inline int +static inline void mono_os_sem_init (MonoSemType *sem, int value) { - return semaphore_create (current_task (), sem, SYNC_POLICY_FIFO, value) != KERN_SUCCESS ? -1 : 0; + kern_return_t res; + + res = semaphore_create (current_task (), sem, SYNC_POLICY_FIFO, value); + if (G_UNLIKELY (res != KERN_SUCCESS)) + g_error ("%s: semaphore_create failed with error %d", __func__, res); } -static inline int +static inline void mono_os_sem_destroy (MonoSemType *sem) { - return semaphore_destroy (current_task (), *sem) != KERN_SUCCESS ? -1 : 0; + kern_return_t res; + + res = semaphore_destroy (current_task (), *sem); + if (G_UNLIKELY (res != KERN_SUCCESS)) + g_error ("%s: semaphore_destroy failed with error %d", __func__, res); } static inline int mono_os_sem_wait (MonoSemType *sem, MonoSemFlags flags) { - int res; + kern_return_t res; retry: res = semaphore_wait (*sem); - g_assert (res != KERN_INVALID_ARGUMENT); + if (G_UNLIKELY (res != KERN_SUCCESS && res != KERN_ABORTED)) + g_error ("%s: semaphore_wait failed with error %d", __func__, res); if (res == KERN_ABORTED && !(flags & MONO_SEM_FLAGS_ALERTABLE)) goto retry; @@ -78,15 +97,16 @@ retry: return res != KERN_SUCCESS ? -1 : 0; } -static inline int +static inline MonoSemTimedwaitRet mono_os_sem_timedwait (MonoSemType *sem, guint32 timeout_ms, MonoSemFlags flags) { + kern_return_t res; + int resint; mach_timespec_t ts, copy; struct timeval start, current; - int res = 0; - if (timeout_ms == (guint32) 0xFFFFFFFF) - return mono_os_sem_wait (sem, flags); + if (timeout_ms == MONO_INFINITE_WAIT) + return (MonoSemTimedwaitRet) mono_os_sem_wait (sem, flags); ts.tv_sec = timeout_ms / 1000; ts.tv_nsec = (timeout_ms % 1000) * 1000000; @@ -96,16 +116,22 @@ mono_os_sem_timedwait (MonoSemType *sem, guint32 timeout_ms, MonoSemFlags flags) } copy = ts; - gettimeofday (&start, NULL); + resint = gettimeofday (&start, NULL); + if (G_UNLIKELY (resint != 0)) + g_error ("%s: gettimeofday failed with \"%s\" (%d)", __func__, g_strerror (errno), errno); retry: res = semaphore_timedwait (*sem, ts); - g_assert (res != KERN_INVALID_ARGUMENT); + if (G_UNLIKELY (res != KERN_SUCCESS && res != KERN_ABORTED && res != KERN_OPERATION_TIMED_OUT)) + g_error ("%s: semaphore_timedwait failed with error %d", __func__, res); if (res == KERN_ABORTED && !(flags & MONO_SEM_FLAGS_ALERTABLE)) { ts = copy; - gettimeofday (¤t, NULL); + resint = gettimeofday (¤t, NULL); + if (G_UNLIKELY (resint != 0)) + g_error ("%s: gettimeofday failed with \"%s\" (%d)", __func__, g_strerror (errno), errno); + ts.tv_sec -= (current.tv_sec - start.tv_sec); ts.tv_nsec -= (current.tv_usec - start.tv_usec) * 1000; if (ts.tv_nsec < 0) { @@ -124,37 +150,54 @@ retry: goto retry; } - return res != KERN_SUCCESS ? -1 : 0; + switch (res) { + case KERN_SUCCESS: + return MONO_SEM_TIMEDWAIT_RET_SUCCESS; + case KERN_ABORTED: + return MONO_SEM_TIMEDWAIT_RET_ALERTED; + case KERN_OPERATION_TIMED_OUT: + return MONO_SEM_TIMEDWAIT_RET_TIMEDOUT; + default: + g_assert_not_reached (); + } } -static inline int +static inline void mono_os_sem_post (MonoSemType *sem) { - int res; + kern_return_t res; + retry: res = semaphore_signal (*sem); - g_assert (res != KERN_INVALID_ARGUMENT); + if (G_UNLIKELY (res != KERN_SUCCESS && res != KERN_ABORTED)) + g_error ("%s: semaphore_signal failed with error %d", __func__, res); if (res == KERN_ABORTED) goto retry; - - return res != KERN_SUCCESS ? -1 : 0; } #elif !defined(HOST_WIN32) && defined(HAVE_SEMAPHORE_H) typedef sem_t MonoSemType; -static inline int +static inline void mono_os_sem_init (MonoSemType *sem, int value) { - return sem_init (sem, 0, value); + int res; + + res = sem_init (sem, 0, value); + if (G_UNLIKELY (res != 0)) + g_error ("%s: sem_init failed with \"%s\" (%d)", __func__, g_strerror (errno), errno); } -static inline int +static inline void mono_os_sem_destroy (MonoSemType *sem) { - return sem_destroy (sem); + int res; + + res = sem_destroy (sem); + if (G_UNLIKELY (res != 0)) + g_error ("%s: sem_destroy failed with \"%s\" (%d)", __func__, g_strerror (errno), errno); } static inline int @@ -164,34 +207,44 @@ mono_os_sem_wait (MonoSemType *sem, MonoSemFlags flags) retry: res = sem_wait (sem); - if (res == -1) - g_assert (errno != EINVAL); + if (G_UNLIKELY (res != 0 && errno != EINTR)) + g_error ("%s: sem_wait failed with \"%s\" (%d)", __func__, g_strerror (errno), errno); - if (res == -1 && errno == EINTR && !(flags & MONO_SEM_FLAGS_ALERTABLE)) + if (res != 0 && errno == EINTR && !(flags & MONO_SEM_FLAGS_ALERTABLE)) goto retry; return res != 0 ? -1 : 0; } -static inline int +static inline MonoSemTimedwaitRet mono_os_sem_timedwait (MonoSemType *sem, guint32 timeout_ms, MonoSemFlags flags) { struct timespec ts, copy; struct timeval t; - int res = 0; + int res; if (timeout_ms == 0) { - res = sem_trywait (sem) != 0 ? -1 : 0; - if (res == -1) - g_assert (errno != EINVAL); + res = sem_trywait (sem); + if (G_UNLIKELY (res != 0 && errno != EINTR && errno != EAGAIN)) + g_error ("%s: sem_trywait failed with \"%s\" (%d)", __func__, g_strerror (errno), errno); - return res != 0 ? -1 : 0; + if (res == 0) + return MONO_SEM_TIMEDWAIT_RET_SUCCESS; + else if (errno == EINTR) + return MONO_SEM_TIMEDWAIT_RET_ALERTED; + else if (errno == EAGAIN) + return MONO_SEM_TIMEDWAIT_RET_TIMEDOUT; + else + g_assert_not_reached (); } - if (timeout_ms == (guint32) 0xFFFFFFFF) - return mono_os_sem_wait (sem, flags); + if (timeout_ms == MONO_INFINITE_WAIT) + return (MonoSemTimedwaitRet) mono_os_sem_wait (sem, flags); + + res = gettimeofday (&t, NULL); + if (G_UNLIKELY (res != 0)) + g_error ("%s: gettimeofday failed with \"%s\" (%d)", __func__, g_strerror (errno), errno); - gettimeofday (&t, NULL); ts.tv_sec = timeout_ms / 1000 + t.tv_sec; ts.tv_nsec = (timeout_ms % 1000) * 1000000 + t.tv_usec * 1000; while (ts.tv_nsec >= NSEC_PER_SEC) { @@ -202,75 +255,96 @@ mono_os_sem_timedwait (MonoSemType *sem, guint32 timeout_ms, MonoSemFlags flags) copy = ts; retry: -#if defined(__native_client__) && defined(USE_NEWLIB) - res = sem_trywait (sem); -#else res = sem_timedwait (sem, &ts); -#endif - if (res == -1) - g_assert (errno != EINVAL); + if (G_UNLIKELY (res != 0 && errno != EINTR && errno != ETIMEDOUT)) + g_error ("%s: sem_timedwait failed with \"%s\" (%d)", __func__, g_strerror (errno), errno); - if (res == -1 && errno == EINTR && !(flags & MONO_SEM_FLAGS_ALERTABLE)) { + if (res != 0 && errno == EINTR && !(flags & MONO_SEM_FLAGS_ALERTABLE)) { ts = copy; goto retry; } - return res != 0 ? -1 : 0; + if (res == 0) + return MONO_SEM_TIMEDWAIT_RET_SUCCESS; + else if (errno == EINTR) + return MONO_SEM_TIMEDWAIT_RET_ALERTED; + else if (errno == ETIMEDOUT) + return MONO_SEM_TIMEDWAIT_RET_TIMEDOUT; + else + g_assert_not_reached (); } -static inline int +static inline void mono_os_sem_post (MonoSemType *sem) { int res; res = sem_post (sem); - if (res == -1) - g_assert (errno != EINVAL); - - return res; + if (G_UNLIKELY (res != 0)) + g_error ("%s: sem_post failed with \"%s\" (%d)", __func__, g_strerror (errno), errno); } #else typedef HANDLE MonoSemType; -static inline int +static inline void mono_os_sem_init (MonoSemType *sem, int value) { *sem = CreateSemaphore (NULL, value, 0x7FFFFFFF, NULL); - return *sem == NULL ? -1 : 0; + if (G_UNLIKELY (*sem == NULL)) + g_error ("%s: CreateSemaphore failed with error %d", __func__, GetLastError ()); } -static inline int +static inline void mono_os_sem_destroy (MonoSemType *sem) { - return !CloseHandle (*sem) ? -1 : 0; + BOOL res; + + res = CloseHandle (*sem); + if (G_UNLIKELY (res == 0)) + g_error ("%s: CloseHandle failed with error %d", __func__, GetLastError ()); } -static inline int +static inline MonoSemTimedwaitRet mono_os_sem_timedwait (MonoSemType *sem, guint32 timeout_ms, MonoSemFlags flags) { - gboolean res; + BOOL res; retry: res = WaitForSingleObjectEx (*sem, timeout_ms, flags & MONO_SEM_FLAGS_ALERTABLE); + if (G_UNLIKELY (res != WAIT_OBJECT_0 && res != WAIT_IO_COMPLETION && res != WAIT_TIMEOUT)) + g_error ("%s: WaitForSingleObjectEx failed with error %d", __func__, GetLastError ()); if (res == WAIT_IO_COMPLETION && !(flags & MONO_SEM_FLAGS_ALERTABLE)) goto retry; - return res != WAIT_OBJECT_0 ? -1 : 0; + switch (res) { + case WAIT_OBJECT_0: + return MONO_SEM_TIMEDWAIT_RET_SUCCESS; + case WAIT_IO_COMPLETION: + return MONO_SEM_TIMEDWAIT_RET_ALERTED; + case WAIT_TIMEOUT: + return MONO_SEM_TIMEDWAIT_RET_TIMEDOUT; + default: + g_assert_not_reached (); + } } static inline int mono_os_sem_wait (MonoSemType *sem, MonoSemFlags flags) { - return mono_os_sem_timedwait (sem, INFINITE, flags); + return mono_os_sem_timedwait (sem, INFINITE, flags) != 0 ? -1 : 0; } -static inline int +static inline void mono_os_sem_post (MonoSemType *sem) { - return !ReleaseSemaphore (*sem, 1, NULL) ? -1 : 0; + BOOL res; + + res = ReleaseSemaphore (*sem, 1, NULL); + if (G_UNLIKELY (res == 0)) + g_error ("%s: ReleaseSemaphore failed with error %d", __func__, GetLastError ()); } #endif diff --git a/mono/utils/mono-proclib.c b/mono/utils/mono-proclib.c index efd732d6d5..79da32b451 100644 --- a/mono/utils/mono-proclib.c +++ b/mono/utils/mono-proclib.c @@ -48,6 +48,10 @@ # define kinfo_starttime_member kp_proc.p_starttime # define kinfo_pid_member kp_proc.p_pid # define kinfo_name_member kp_proc.p_comm +#elif defined(__NetBSD__) +# define kinfo_starttime_member p_ustart_sec +# define kinfo_pid_member p_pid +# define kinfo_name_member p_comm #elif defined(__OpenBSD__) // Can not figure out how to get the proc's start time on OpenBSD # undef kinfo_starttime_member @@ -76,7 +80,7 @@ mono_process_list (int *size) #ifdef KERN_PROC2 int mib [6]; size_t data_len = sizeof (struct kinfo_proc2) * 400; - struct kinfo_proc2 *processes = malloc (data_len); + struct kinfo_proc2 *processes = g_malloc (data_len); #else int mib [4]; size_t data_len = sizeof (struct kinfo_proc) * 16; @@ -101,7 +105,7 @@ mono_process_list (int *size) res = sysctl (mib, 6, processes, &data_len, NULL, 0); if (res < 0) { - free (processes); + g_free (processes); return NULL; } #else @@ -115,10 +119,10 @@ mono_process_list (int *size) res = sysctl (mib, 4, NULL, &data_len, NULL, 0); if (res) return NULL; - processes = (struct kinfo_proc *) malloc (data_len); + processes = (struct kinfo_proc *) g_malloc (data_len); res = sysctl (mib, 4, processes, &data_len, NULL, 0); if (res < 0) { - free (processes); + g_free (processes); if (errno != ENOMEM) return NULL; limit --; @@ -136,7 +140,7 @@ mono_process_list (int *size) buf = (void **) g_realloc (buf, res * sizeof (void*)); for (i = 0; i < res; ++i) buf [i] = GINT_TO_POINTER (processes [i].kinfo_pid_member); - free (processes); + g_free (processes); if (size) *size = res; return buf; @@ -317,8 +321,16 @@ mono_process_get_times (gpointer pid, gint64 *start_time, gint64 *user_time, gin { KINFO_PROC processi; - if (sysctl_kinfo_proc (pid, &processi)) + if (sysctl_kinfo_proc (pid, &processi)) { +#if defined(__NetBSD__) + struct timeval tv; + tv.tv_sec = processi.kinfo_starttime_member; + tv.tv_usec = processi.p_ustart_usec; + *start_time = mono_100ns_datetime_from_timeval(tv); +#else *start_time = mono_100ns_datetime_from_timeval (processi.kinfo_starttime_member); +#endif + } } #endif diff --git a/mono/utils/mono-publib.c b/mono/utils/mono-publib.c index 70271a57f8..927a933d54 100644 --- a/mono/utils/mono-publib.c +++ b/mono/utils/mono-publib.c @@ -8,3 +8,21 @@ mono_free (void *ptr) g_free (ptr); } + +/** + * mono_set_allocator_vtable + * + * Make the runtime use the functions in @vtable for allocating memory. + * The provided functions must have the same semantics of their libc's equivalents. + * + * @return TRUE is the vtable was installed. FALSE if the version is incompatible. + */ +mono_bool +mono_set_allocator_vtable (MonoAllocatorVTable* vtable) +{ + if (vtable->version != MONO_ALLOCATOR_VTABLE_VERSION) + return FALSE; + GMemVTable g_mem_vtable = { vtable->malloc, vtable->realloc, vtable->free, vtable->calloc}; + g_mem_set_vtable (&g_mem_vtable); + return TRUE; +} diff --git a/mono/utils/mono-publib.h b/mono/utils/mono-publib.h index 53d4aa3ea7..e2614388ce 100644 --- a/mono/utils/mono-publib.h +++ b/mono/utils/mono-publib.h @@ -53,6 +53,8 @@ typedef unsigned __int64 uint64_t; #endif /* end of compiler-specific stuff */ +#include + #if defined(MONO_DLL_EXPORT) #define MONO_API MONO_API_EXPORT #elif defined(MONO_DLL_IMPORT) @@ -71,6 +73,20 @@ typedef void (*MonoHFunc) (void* key, void* value, void* user_data); MONO_API void mono_free (void *); +#define MONO_ALLOCATOR_VTABLE_VERSION 1 + +typedef struct { + int version; + void *(*malloc) (size_t size); + void *(*realloc) (void *mem, size_t count); + void (*free) (void *mem); + void *(*calloc) (size_t count, size_t size); +} MonoAllocatorVTable; + +MONO_API mono_bool +mono_set_allocator_vtable (MonoAllocatorVTable* vtable); + + #define MONO_CONST_RETURN const /* @@ -100,6 +116,15 @@ MONO_API void mono_free (void *); #define MONO_RT_EXTERNAL_ONLY #endif /* MONO_INSIDE_RUNTIME */ +#ifdef __GNUC__ +#define _MONO_DEPRECATED __attribute__ ((deprecated)) +#elif defined (_MSC_VER) +#define _MONO_DEPRECATED __declspec (deprecated) +#else +#define _MONO_DEPRECATED +#endif + +#define MONO_DEPRECATED MONO_API MONO_RT_EXTERNAL_ONLY _MONO_DEPRECATED MONO_END_DECLS diff --git a/mono/utils/mono-rand.c b/mono/utils/mono-rand.c index 1e8297750b..0e5a853847 100644 --- a/mono/utils/mono-rand.c +++ b/mono/utils/mono-rand.c @@ -165,27 +165,27 @@ static void get_entropy_from_egd (const char *path, guchar *buffer, int buffer_size, MonoError *error) { struct sockaddr_un egd_addr; - gint file; + gint socket_fd; gint ret; guint offset = 0; int err = 0; mono_error_init (error); - file = socket (PF_UNIX, SOCK_STREAM, 0); - if (file < 0) { + socket_fd = socket (PF_UNIX, SOCK_STREAM, 0); + if (socket_fd < 0) { ret = -1; err = errno; } else { egd_addr.sun_family = AF_UNIX; strncpy (egd_addr.sun_path, path, sizeof (egd_addr.sun_path) - 1); egd_addr.sun_path [sizeof (egd_addr.sun_path) - 1] = '\0'; - ret = connect (file, (struct sockaddr*) &egd_addr, sizeof (egd_addr)); + ret = connect (socket_fd, (struct sockaddr*) &egd_addr, sizeof (egd_addr)); err = errno; } if (ret == -1) { - if (file >= 0) - close (file); + if (socket_fd >= 0) + close (socket_fd); g_warning ("Entropy problem! Can't create or connect to egd socket %s", path); mono_error_set_execution_engine (error, "Failed to open egd socket %s: %s", path, strerror (err)); return; @@ -199,14 +199,14 @@ get_entropy_from_egd (const char *path, guchar *buffer, int buffer_size, MonoErr request [0] = 2; request [1] = buffer_size < 255 ? buffer_size : 255; while (count < 2) { - int sent = write (file, request + count, 2 - count); + int sent = write (socket_fd, request + count, 2 - count); err = errno; if (sent >= 0) { count += sent; } else if (err == EINTR) { continue; } else { - close (file); + close (socket_fd); g_warning ("Send egd request failed %d", err); mono_error_set_execution_engine (error, "Failed to send request to egd socket: %s", strerror (err)); return; @@ -216,7 +216,7 @@ get_entropy_from_egd (const char *path, guchar *buffer, int buffer_size, MonoErr count = 0; while (count != request [1]) { int received; - received = read (file, buffer + offset, request [1] - count); + received = read (socket_fd, buffer + offset, request [1] - count); err = errno; if (received > 0) { count += received; @@ -224,7 +224,7 @@ get_entropy_from_egd (const char *path, guchar *buffer, int buffer_size, MonoErr } else if (received < 0 && err == EINTR) { continue; } else { - close (file); + close (socket_fd); g_warning ("Receive egd request failed %d", err); mono_error_set_execution_engine (error, "Failed to get response from egd socket: %s", strerror(err)); return; @@ -234,7 +234,7 @@ get_entropy_from_egd (const char *path, guchar *buffer, int buffer_size, MonoErr buffer_size -= request [1]; } - close (file); + close (socket_fd); } gboolean diff --git a/mono/utils/mono-threads-android.c b/mono/utils/mono-threads-android.c index fa82387f26..b5c0398576 100644 --- a/mono/utils/mono-threads-android.c +++ b/mono/utils/mono-threads-android.c @@ -37,7 +37,7 @@ slow_get_thread_bounds (guint8 *current, guint8 **staddr, size_t *stsize) } void -mono_threads_core_get_stack_bounds (guint8 **staddr, size_t *stsize) +mono_threads_platform_get_stack_bounds (guint8 **staddr, size_t *stsize) { pthread_attr_t attr; guint8 *current = (guint8*)&attr; diff --git a/mono/utils/mono-threads-coop.c b/mono/utils/mono-threads-coop.c index ddc3c6ebbe..9bfbdc5168 100644 --- a/mono/utils/mono-threads-coop.c +++ b/mono/utils/mono-threads-coop.c @@ -145,11 +145,14 @@ mono_threads_state_poll_with_info (MonoThreadInfo *info) } } -static void * -return_stack_ptr () +static volatile gpointer* dummy_global; + +static MONO_NEVER_INLINE +void* +return_stack_ptr (gpointer *i) { - gpointer i; - return &i; + dummy_global = i; + return i; } static void @@ -157,7 +160,8 @@ copy_stack_data (MonoThreadInfo *info, gpointer *stackdata_begin) { MonoThreadUnwindState *state; int stackdata_size; - void* stackdata_end = return_stack_ptr (); + gpointer dummy; + void* stackdata_end = return_stack_ptr (&dummy); SAVE_REGS_ON_STACK; @@ -413,7 +417,7 @@ mono_threads_is_coop_enabled (void) void -mono_threads_init_coop (void) +mono_threads_coop_init (void) { if (!mono_threads_is_coop_enabled ()) return; diff --git a/mono/utils/mono-threads-freebsd.c b/mono/utils/mono-threads-freebsd.c index cdee0ab406..e2e6355521 100644 --- a/mono/utils/mono-threads-freebsd.c +++ b/mono/utils/mono-threads-freebsd.c @@ -7,7 +7,7 @@ #include void -mono_threads_core_get_stack_bounds (guint8 **staddr, size_t *stsize) +mono_threads_platform_get_stack_bounds (guint8 **staddr, size_t *stsize) { pthread_attr_t attr; guint8 *current = (guint8*)&attr; diff --git a/mono/utils/mono-threads-linux.c b/mono/utils/mono-threads-linux.c index c5d6e8bab3..6ffec1ab60 100644 --- a/mono/utils/mono-threads-linux.c +++ b/mono/utils/mono-threads-linux.c @@ -6,7 +6,7 @@ #include void -mono_threads_core_get_stack_bounds (guint8 **staddr, size_t *stsize) +mono_threads_platform_get_stack_bounds (guint8 **staddr, size_t *stsize) { pthread_attr_t attr; diff --git a/mono/utils/mono-threads-mach-abort-syscall.c b/mono/utils/mono-threads-mach-abort-syscall.c index 559d2fa63c..eb43625f47 100644 --- a/mono/utils/mono-threads-mach-abort-syscall.c +++ b/mono/utils/mono-threads-mach-abort-syscall.c @@ -21,18 +21,18 @@ #if defined(HOST_WATCHOS) || defined(HOST_TVOS) void -mono_threads_init_abort_syscall (void) +mono_threads_abort_syscall_init (void) { } void -mono_threads_core_abort_syscall (MonoThreadInfo *info) +mono_threads_suspend_abort_syscall (MonoThreadInfo *info) { } gboolean -mono_threads_core_needs_abort_syscall (void) +mono_threads_suspend_needs_abort_syscall (void) { return FALSE; } @@ -40,12 +40,12 @@ mono_threads_core_needs_abort_syscall (void) #else void -mono_threads_init_abort_syscall (void) +mono_threads_abort_syscall_init (void) { } void -mono_threads_core_abort_syscall (MonoThreadInfo *info) +mono_threads_suspend_abort_syscall (MonoThreadInfo *info) { kern_return_t ret; @@ -79,7 +79,7 @@ mono_threads_core_abort_syscall (MonoThreadInfo *info) } gboolean -mono_threads_core_needs_abort_syscall (void) +mono_threads_suspend_needs_abort_syscall (void) { return TRUE; } diff --git a/mono/utils/mono-threads-mach.c b/mono/utils/mono-threads-mach.c index b23680759a..948804243c 100644 --- a/mono/utils/mono-threads-mach.c +++ b/mono/utils/mono-threads-mach.c @@ -25,7 +25,7 @@ #include void -mono_threads_init_platform (void) +mono_threads_suspend_init (void) { mono_threads_init_dead_letter (); } @@ -33,19 +33,19 @@ mono_threads_init_platform (void) #if defined(HOST_WATCHOS) || defined(HOST_TVOS) gboolean -mono_threads_core_begin_async_suspend (MonoThreadInfo *info, gboolean interrupt_kernel) +mono_threads_suspend_begin_async_suspend (MonoThreadInfo *info, gboolean interrupt_kernel) { g_assert_not_reached (); } gboolean -mono_threads_core_check_suspend_result (MonoThreadInfo *info) +mono_threads_suspend_check_suspend_result (MonoThreadInfo *info) { g_assert_not_reached (); } gboolean -mono_threads_core_begin_async_resume (MonoThreadInfo *info) +mono_threads_suspend_begin_async_resume (MonoThreadInfo *info) { g_assert_not_reached (); } @@ -53,7 +53,7 @@ mono_threads_core_begin_async_resume (MonoThreadInfo *info) #else /* defined(HOST_WATCHOS) || defined(HOST_TVOS) */ gboolean -mono_threads_core_begin_async_suspend (MonoThreadInfo *info, gboolean interrupt_kernel) +mono_threads_suspend_begin_async_suspend (MonoThreadInfo *info, gboolean interrupt_kernel) { kern_return_t ret; @@ -92,13 +92,13 @@ mono_threads_core_begin_async_suspend (MonoThreadInfo *info, gboolean interrupt_ } gboolean -mono_threads_core_check_suspend_result (MonoThreadInfo *info) +mono_threads_suspend_check_suspend_result (MonoThreadInfo *info) { return info->suspend_can_continue; } gboolean -mono_threads_core_begin_async_resume (MonoThreadInfo *info) +mono_threads_suspend_begin_async_resume (MonoThreadInfo *info) { kern_return_t ret; @@ -148,7 +148,7 @@ mono_threads_core_begin_async_resume (MonoThreadInfo *info) #endif /* defined(HOST_WATCHOS) || defined(HOST_TVOS) */ void -mono_threads_platform_register (MonoThreadInfo *info) +mono_threads_suspend_register (MonoThreadInfo *info) { char thread_name [64]; @@ -161,7 +161,7 @@ mono_threads_platform_register (MonoThreadInfo *info) } void -mono_threads_platform_free (MonoThreadInfo *info) +mono_threads_suspend_free (MonoThreadInfo *info) { mach_port_deallocate (current_task (), info->native_handle); } @@ -170,7 +170,7 @@ mono_threads_platform_free (MonoThreadInfo *info) #ifdef __MACH__ void -mono_threads_core_get_stack_bounds (guint8 **staddr, size_t *stsize) +mono_threads_platform_get_stack_bounds (guint8 **staddr, size_t *stsize) { *staddr = (guint8*)pthread_get_stackaddr_np (pthread_self()); *stsize = pthread_get_stacksize_np (pthread_self()); diff --git a/mono/utils/mono-threads-netbsd.c b/mono/utils/mono-threads-netbsd.c new file mode 100644 index 0000000000..c140148dbd --- /dev/null +++ b/mono/utils/mono-threads-netbsd.c @@ -0,0 +1,23 @@ +#include + +#if defined(__NetBSD__) + +#include +#include + +void +mono_threads_platform_get_stack_bounds (guint8 **staddr, size_t *stsize) +{ + pthread_attr_t attr; + + *staddr = NULL; + *stsize = (size_t)-1; + + pthread_attr_init (&attr); + pthread_attr_get_np (pthread_self (), &attr); + + pthread_attr_getstack (&attr, (void**)staddr, stsize); + pthread_attr_destroy (&attr); +} + +#endif diff --git a/mono/utils/mono-threads-openbsd.c b/mono/utils/mono-threads-openbsd.c index 96a962230e..7e2e0e21e2 100644 --- a/mono/utils/mono-threads-openbsd.c +++ b/mono/utils/mono-threads-openbsd.c @@ -6,7 +6,7 @@ #include void -mono_threads_core_get_stack_bounds (guint8 **staddr, size_t *stsize) +mono_threads_platform_get_stack_bounds (guint8 **staddr, size_t *stsize) { /* TODO : Determine if this code is actually still needed. It may already be covered by the case above. */ pthread_attr_t attr; diff --git a/mono/utils/mono-threads-posix-abort-syscall.c b/mono/utils/mono-threads-posix-abort-syscall.c index 7e836163d6..232161c273 100644 --- a/mono/utils/mono-threads-posix-abort-syscall.c +++ b/mono/utils/mono-threads-posix-abort-syscall.c @@ -20,13 +20,13 @@ #if defined(USE_POSIX_BACKEND) void -mono_threads_init_abort_syscall (void) +mono_threads_abort_syscall_init (void) { mono_threads_posix_init_signals (MONO_THREADS_POSIX_INIT_SIGNALS_ABORT); } void -mono_threads_core_abort_syscall (MonoThreadInfo *info) +mono_threads_suspend_abort_syscall (MonoThreadInfo *info) { /* We signal a thread to break it from the current syscall. * This signal should not be interpreted as a suspend request. */ @@ -36,7 +36,7 @@ mono_threads_core_abort_syscall (MonoThreadInfo *info) } gboolean -mono_threads_core_needs_abort_syscall (void) +mono_threads_suspend_needs_abort_syscall (void) { return TRUE; } diff --git a/mono/utils/mono-threads-posix.c b/mono/utils/mono-threads-posix.c index 0111d5fd90..ce2f58ad13 100644 --- a/mono/utils/mono-threads-posix.c +++ b/mono/utils/mono-threads-posix.c @@ -18,6 +18,7 @@ #include #include #include +#include #include @@ -31,81 +32,41 @@ extern int tkill (pid_t tid, int signal); #if defined(_POSIX_VERSION) || defined(__native_client__) +#include + #include #if defined(__native_client__) void nacl_shutdown_gc_thread(void); #endif -typedef struct { - void *(*start_routine)(void*); - void *arg; - int flags; - MonoCoopSem registered; - HANDLE handle; -} StartInfo; - -static void* -inner_start_thread (void *arg) +void +mono_threads_platform_register (MonoThreadInfo *info) { - StartInfo *start_info = (StartInfo *) arg; - void *t_arg = start_info->arg; - int res; - void *(*start_func)(void*) = start_info->start_routine; - guint32 flags = start_info->flags; - void *result; - HANDLE handle; - MonoThreadInfo *info; + gpointer thread_handle; - /* Register the thread with the io-layer */ - handle = wapi_create_thread_handle (); - if (!handle) { - res = mono_coop_sem_post (&(start_info->registered)); - g_assert (!res); - return NULL; - } - start_info->handle = handle; + info->owned_mutexes = g_ptr_array_new (); + info->priority = MONO_THREAD_PRIORITY_NORMAL; - info = mono_thread_info_attach (&result); + thread_handle = mono_w32handle_new (MONO_W32HANDLE_THREAD, NULL); + if (thread_handle == INVALID_HANDLE_VALUE) + g_error ("%s: failed to create handle", __func__); - info->runtime_thread = TRUE; - info->handle = handle; - - if (flags & CREATE_SUSPENDED) { - info->create_suspended = TRUE; - mono_coop_sem_init (&info->create_suspended_sem, 0); - } - - /* start_info is not valid after this */ - res = mono_coop_sem_post (&(start_info->registered)); - g_assert (!res); - start_info = NULL; - - if (flags & CREATE_SUSPENDED) { - res = mono_coop_sem_wait (&info->create_suspended_sem, MONO_SEM_FLAGS_NONE); - g_assert (res != -1); - - mono_coop_sem_destroy (&info->create_suspended_sem); - } - - /* Run the actual main function of the thread */ - result = start_func (t_arg); - - mono_threads_core_exit (GPOINTER_TO_UINT (result)); - g_assert_not_reached (); + g_assert (!info->handle); + info->handle = thread_handle; } -HANDLE -mono_threads_core_create_thread (LPTHREAD_START_ROUTINE start_routine, gpointer arg, guint32 stack_size, guint32 creation_flags, MonoNativeThreadId *out_tid) +int +mono_threads_platform_create_thread (MonoThreadStart thread_fn, gpointer thread_data, gsize stack_size, MonoNativeThreadId *out_tid) { pthread_attr_t attr; - int res; pthread_t thread; - StartInfo start_info; + gint res; res = pthread_attr_init (&attr); g_assert (!res); +#ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE if (stack_size == 0) { #if HAVE_VALGRIND_MEMCHECK_H if (RUNNING_ON_VALGRIND) @@ -122,91 +83,43 @@ mono_threads_core_create_thread (LPTHREAD_START_ROUTINE start_routine, gpointer stack_size = PTHREAD_STACK_MIN; #endif -#ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE res = pthread_attr_setstacksize (&attr, stack_size); g_assert (!res); -#endif - - memset (&start_info, 0, sizeof (StartInfo)); - start_info.start_routine = (void *(*)(void *)) start_routine; - start_info.arg = arg; - start_info.flags = creation_flags; - mono_coop_sem_init (&(start_info.registered), 0); +#endif /* HAVE_PTHREAD_ATTR_SETSTACKSIZE */ /* Actually start the thread */ - res = mono_gc_pthread_create (&thread, &attr, inner_start_thread, &start_info); - if (res) { - mono_coop_sem_destroy (&(start_info.registered)); - return NULL; - } - - /* Wait until the thread register itself in various places */ - res = mono_coop_sem_wait (&start_info.registered, MONO_SEM_FLAGS_NONE); - g_assert (res != -1); - - mono_coop_sem_destroy (&(start_info.registered)); + res = mono_gc_pthread_create (&thread, &attr, (gpointer (*)(gpointer)) thread_fn, thread_data); + if (res) + return -1; if (out_tid) *out_tid = thread; - return start_info.handle; -} - -/* - * mono_threads_core_resume_created: - * - * Resume a newly created thread created using CREATE_SUSPENDED. - */ -void -mono_threads_core_resume_created (MonoThreadInfo *info, MonoNativeThreadId tid) -{ - mono_coop_sem_post (&info->create_suspended_sem); + return 0; } gboolean -mono_threads_core_yield (void) +mono_threads_platform_yield (void) { return sched_yield () == 0; } void -mono_threads_core_exit (int exit_code) +mono_threads_platform_exit (int exit_code) { - MonoThreadInfo *current = mono_thread_info_current (); - #if defined(__native_client__) nacl_shutdown_gc_thread(); #endif - wapi_thread_handle_set_exited (current->handle, exit_code); - mono_thread_info_detach (); pthread_exit (NULL); } void -mono_threads_core_unregister (MonoThreadInfo *info) +mono_threads_platform_unregister (MonoThreadInfo *info) { - if (info->handle) { - wapi_thread_handle_set_exited (info->handle, 0); - info->handle = NULL; - } -} - -HANDLE -mono_threads_core_open_handle (void) -{ - MonoThreadInfo *info; - - info = mono_thread_info_current (); - g_assert (info); - - if (!info->handle) - info->handle = wapi_create_thread_handle (); - else - wapi_ref_thread_handle (info->handle); - return info->handle; + mono_threads_platform_set_exited (info); } int @@ -223,14 +136,28 @@ mono_threads_get_max_stack_size (void) return (int)lim.rlim_max; } -HANDLE -mono_threads_core_open_thread_handle (HANDLE handle, MonoNativeThreadId tid) +gpointer +mono_threads_platform_duplicate_handle (MonoThreadInfo *info) { - wapi_ref_thread_handle (handle); + g_assert (info->handle); + mono_w32handle_ref (info->handle); + return info->handle; +} + +HANDLE +mono_threads_platform_open_thread_handle (HANDLE handle, MonoNativeThreadId tid) +{ + mono_w32handle_ref (handle); return handle; } +void +mono_threads_platform_close_thread_handle (HANDLE handle) +{ + mono_w32handle_unref (handle); +} + int mono_threads_pthread_kill (MonoThreadInfo *info, int signum) { @@ -319,12 +246,191 @@ mono_native_thread_set_name (MonoNativeThreadId tid, const char *name) #endif } +gboolean +mono_native_thread_join (MonoNativeThreadId tid) +{ + void *res; + + return !pthread_join (tid, &res); +} + +void +mono_threads_platform_set_exited (MonoThreadInfo *info) +{ + gpointer mutex_handle; + int i, thr_ret; + pid_t pid; + pthread_t tid; + + g_assert (info->handle); + + if (mono_w32handle_issignalled (info->handle)) + g_error ("%s: handle %p thread %p has already exited, it's handle is signalled", __func__, info->handle, mono_thread_info_get_tid (info)); + if (mono_w32handle_get_type (info->handle) == MONO_W32HANDLE_UNUSED) + g_error ("%s: handle %p thread %p has already exited, it's handle type is 'unused'", __func__, info->handle, mono_thread_info_get_tid (info)); + + pid = wapi_getpid (); + tid = pthread_self (); + + for (i = 0; i < info->owned_mutexes->len; i++) { + mutex_handle = g_ptr_array_index (info->owned_mutexes, i); + wapi_mutex_abandon (mutex_handle, pid, tid); + mono_thread_info_disown_mutex (info, mutex_handle); + } + + g_ptr_array_free (info->owned_mutexes, TRUE); + + thr_ret = mono_w32handle_lock_handle (info->handle); + g_assert (thr_ret == 0); + + mono_w32handle_set_signal_state (info->handle, TRUE, TRUE); + + thr_ret = mono_w32handle_unlock_handle (info->handle); + g_assert (thr_ret == 0); + + /* The thread is no longer active, so unref it */ + mono_w32handle_unref (info->handle); + + info->handle = NULL; +} + +void +mono_threads_platform_describe (MonoThreadInfo *info, GString *text) +{ + int i; + + g_string_append_printf (text, "thread handle %p state : ", info->handle); + + mono_thread_info_describe_interrupt_token (info, text); + + g_string_append_printf (text, ", owns ("); + for (i = 0; i < info->owned_mutexes->len; i++) + g_string_append_printf (text, i > 0 ? ", %p" : "%p", g_ptr_array_index (info->owned_mutexes, i)); + g_string_append_printf (text, ")"); +} + +void +mono_threads_platform_own_mutex (MonoThreadInfo *info, gpointer mutex_handle) +{ + mono_w32handle_ref (mutex_handle); + + g_ptr_array_add (info->owned_mutexes, mutex_handle); +} + +void +mono_threads_platform_disown_mutex (MonoThreadInfo *info, gpointer mutex_handle) +{ + mono_w32handle_unref (mutex_handle); + + g_ptr_array_remove (info->owned_mutexes, mutex_handle); +} + +MonoThreadPriority +mono_threads_platform_get_priority (MonoThreadInfo *info) +{ + return info->priority; +} + +void +mono_threads_platform_set_priority (MonoThreadInfo *info, MonoThreadPriority priority) +{ + int policy; + struct sched_param param; + pthread_t tid; + gint res; + + g_assert (priority >= MONO_THREAD_PRIORITY_LOWEST); + g_assert (priority <= MONO_THREAD_PRIORITY_HIGHEST); + g_assert (MONO_THREAD_PRIORITY_LOWEST < MONO_THREAD_PRIORITY_HIGHEST); + + tid = mono_thread_info_get_tid (info); + + res = pthread_getschedparam (tid, &policy, ¶m); + if (res != 0) + g_error ("%s: pthread_getschedparam failed, error: \"%s\" (%d)", g_strerror (res), res); + +#ifdef _POSIX_PRIORITY_SCHEDULING + int max, min; + + /* Necessary to get valid priority range */ + + min = sched_get_priority_min (policy); + max = sched_get_priority_max (policy); + + if (max > 0 && min >= 0 && max > min) { + double srange, drange, sposition, dposition; + srange = MONO_THREAD_PRIORITY_HIGHEST - MONO_THREAD_PRIORITY_LOWEST; + drange = max - min; + sposition = priority - MONO_THREAD_PRIORITY_LOWEST; + dposition = (sposition / srange) * drange; + param.sched_priority = (int)(dposition + min); + } else +#endif + { + switch (policy) { + case SCHED_FIFO: + case SCHED_RR: + param.sched_priority = 50; + break; +#ifdef SCHED_BATCH + case SCHED_BATCH: +#endif + case SCHED_OTHER: + param.sched_priority = 0; + break; + default: + g_error ("%s: unknown policy %d", __func__, policy); + } + } + + res = pthread_setschedparam (tid, policy, ¶m); + if (res != 0) { + if (res == EPERM) { + g_warning ("%s: pthread_setschedparam failed, error: \"%s\" (%d)", g_strerror (res), res); + return; + } + g_error ("%s: pthread_setschedparam failed, error: \"%s\" (%d)", g_strerror (res), res); + } + + info->priority = priority; +} + +static const gchar* thread_typename (void) +{ + return "Thread"; +} + +static gsize thread_typesize (void) +{ + return 0; +} + +static MonoW32HandleOps thread_ops = { + NULL, /* close */ + NULL, /* signal */ + NULL, /* own */ + NULL, /* is_owned */ + NULL, /* special_wait */ + NULL, /* prewait */ + NULL, /* details */ + thread_typename, /* typename */ + thread_typesize, /* typesize */ +}; + +void +mono_threads_platform_init (void) +{ + mono_w32handle_register_ops (MONO_W32HANDLE_THREAD, &thread_ops); + + mono_w32handle_register_capabilities (MONO_W32HANDLE_THREAD, MONO_W32HANDLE_CAP_WAIT); +} + #endif /* defined(_POSIX_VERSION) || defined(__native_client__) */ #if defined(USE_POSIX_BACKEND) gboolean -mono_threads_core_begin_async_suspend (MonoThreadInfo *info, gboolean interrupt_kernel) +mono_threads_suspend_begin_async_suspend (MonoThreadInfo *info, gboolean interrupt_kernel) { int sig = interrupt_kernel ? mono_threads_posix_get_abort_signal () : mono_threads_posix_get_suspend_signal (); @@ -336,7 +442,7 @@ mono_threads_core_begin_async_suspend (MonoThreadInfo *info, gboolean interrupt_ } gboolean -mono_threads_core_check_suspend_result (MonoThreadInfo *info) +mono_threads_suspend_check_suspend_result (MonoThreadInfo *info) { return info->suspend_can_continue; } @@ -348,14 +454,14 @@ This begins async resume. This function must do the following: - Notify the target to resume. */ gboolean -mono_threads_core_begin_async_resume (MonoThreadInfo *info) +mono_threads_suspend_begin_async_resume (MonoThreadInfo *info) { mono_threads_add_to_pending_operation_set (info); return mono_threads_pthread_kill (info, mono_threads_posix_get_restart_signal ()) == 0; } void -mono_threads_platform_register (MonoThreadInfo *info) +mono_threads_suspend_register (MonoThreadInfo *info) { #if defined (PLATFORM_ANDROID) info->native_handle = gettid (); @@ -363,12 +469,12 @@ mono_threads_platform_register (MonoThreadInfo *info) } void -mono_threads_platform_free (MonoThreadInfo *info) +mono_threads_suspend_free (MonoThreadInfo *info) { } void -mono_threads_init_platform (void) +mono_threads_suspend_init (void) { mono_threads_posix_init_signals (MONO_THREADS_POSIX_INIT_SIGNALS_SUSPEND_RESTART); } diff --git a/mono/utils/mono-threads-windows-abort-syscall.c b/mono/utils/mono-threads-windows-abort-syscall.c index bf3cf242f6..19afe3e6b8 100644 --- a/mono/utils/mono-threads-windows-abort-syscall.c +++ b/mono/utils/mono-threads-windows-abort-syscall.c @@ -17,7 +17,7 @@ #include void -mono_threads_init_abort_syscall (void) +mono_threads_abort_syscall_init (void) { } @@ -27,7 +27,7 @@ abort_apc (ULONG_PTR param) } void -mono_threads_core_abort_syscall (MonoThreadInfo *info) +mono_threads_suspend_abort_syscall (MonoThreadInfo *info) { DWORD id = mono_thread_info_get_tid (info); HANDLE handle; @@ -41,7 +41,7 @@ mono_threads_core_abort_syscall (MonoThreadInfo *info) } gboolean -mono_threads_core_needs_abort_syscall (void) +mono_threads_suspend_needs_abort_syscall (void) { return TRUE; } diff --git a/mono/utils/mono-threads-windows.c b/mono/utils/mono-threads-windows.c index 2ec53e35bc..9763c94a55 100644 --- a/mono/utils/mono-threads-windows.c +++ b/mono/utils/mono-threads-windows.c @@ -16,7 +16,7 @@ void -mono_threads_init_platform (void) +mono_threads_suspend_init (void) { } @@ -26,7 +26,7 @@ interrupt_apc (ULONG_PTR param) } gboolean -mono_threads_core_begin_async_suspend (MonoThreadInfo *info, gboolean interrupt_kernel) +mono_threads_suspend_begin_async_suspend (MonoThreadInfo *info, gboolean interrupt_kernel) { DWORD id = mono_thread_info_get_tid (info); HANDLE handle; @@ -67,13 +67,13 @@ mono_threads_core_begin_async_suspend (MonoThreadInfo *info, gboolean interrupt_ } gboolean -mono_threads_core_check_suspend_result (MonoThreadInfo *info) +mono_threads_suspend_check_suspend_result (MonoThreadInfo *info) { return info->suspend_can_continue; } gboolean -mono_threads_core_begin_async_resume (MonoThreadInfo *info) +mono_threads_suspend_begin_async_resume (MonoThreadInfo *info) { DWORD id = mono_thread_info_get_tid (info); HANDLE handle; @@ -119,12 +119,12 @@ mono_threads_core_begin_async_resume (MonoThreadInfo *info) void -mono_threads_platform_register (MonoThreadInfo *info) +mono_threads_suspend_register (MonoThreadInfo *info) { } void -mono_threads_platform_free (MonoThreadInfo *info) +mono_threads_suspend_free (MonoThreadInfo *info) { } @@ -132,84 +132,40 @@ mono_threads_platform_free (MonoThreadInfo *info) #if defined (HOST_WIN32) -typedef struct { - LPTHREAD_START_ROUTINE start_routine; - void *arg; - MonoCoopSem registered; - gboolean suspend; - HANDLE suspend_event; -} ThreadStartInfo; - -static DWORD WINAPI -inner_start_thread (LPVOID arg) +void +mono_threads_platform_register (MonoThreadInfo *info) { - ThreadStartInfo *start_info = arg; - void *t_arg = start_info->arg; - int post_result; - LPTHREAD_START_ROUTINE start_func = start_info->start_routine; - DWORD result; - gboolean suspend = start_info->suspend; - HANDLE suspend_event = start_info->suspend_event; - MonoThreadInfo *info; + HANDLE thread_handle; - info = mono_thread_info_attach (&result); - info->runtime_thread = TRUE; - info->create_suspended = suspend; + thread_handle = GetCurrentThread (); + g_assert (thread_handle); - post_result = mono_coop_sem_post (&(start_info->registered)); - g_assert (!post_result); + /* The handle returned by GetCurrentThread () is a pseudo handle, so it can't + * be used to refer to the thread from other threads for things like aborting. */ + DuplicateHandle (GetCurrentProcess (), thread_handle, GetCurrentProcess (), &thread_handle, THREAD_ALL_ACCESS, TRUE, 0); - if (suspend) { - WaitForSingleObject (suspend_event, INFINITE); /* caller will suspend the thread before setting the event. */ - CloseHandle (suspend_event); - } - - result = start_func (t_arg); - - mono_thread_info_detach (); - - return result; + g_assert (!info->handle); + info->handle = thread_handle; } -HANDLE -mono_threads_core_create_thread (LPTHREAD_START_ROUTINE start_routine, gpointer arg, guint32 stack_size, guint32 creation_flags, MonoNativeThreadId *out_tid) +int +mono_threads_platform_create_thread (MonoThreadStart thread_fn, gpointer thread_data, gsize stack_size, MonoNativeThreadId *out_tid) { - ThreadStartInfo *start_info; HANDLE result; DWORD thread_id; - int res; - start_info = g_malloc0 (sizeof (ThreadStartInfo)); - if (!start_info) - return NULL; - mono_coop_sem_init (&(start_info->registered), 0); - start_info->arg = arg; - start_info->start_routine = start_routine; - start_info->suspend = creation_flags & CREATE_SUSPENDED; - creation_flags &= ~CREATE_SUSPENDED; - if (start_info->suspend) { - start_info->suspend_event = CreateEvent (NULL, TRUE, FALSE, NULL); - if (!start_info->suspend_event) - return NULL; - } + result = CreateThread (NULL, stack_size, (LPTHREAD_START_ROUTINE) thread_fn, thread_data, 0, &thread_id); + if (!result) + return -1; - result = CreateThread (NULL, stack_size, inner_start_thread, start_info, creation_flags, &thread_id); - if (result) { - res = mono_coop_sem_wait (&(start_info->registered), MONO_SEM_FLAGS_NONE); - g_assert (res != -1); + /* A new handle is open when attaching + * the thread, so we don't need this one */ + CloseHandle (result); - if (start_info->suspend) { - g_assert (SuspendThread (result) != (DWORD)-1); - SetEvent (start_info->suspend_event); - } - } else if (start_info->suspend) { - CloseHandle (start_info->suspend_event); - } if (out_tid) *out_tid = thread_id; - mono_coop_sem_destroy (&(start_info->registered)); - g_free (start_info); - return result; + + return 0; } @@ -231,15 +187,19 @@ mono_native_thread_create (MonoNativeThreadId *tid, gpointer func, gpointer arg) return CreateThread (NULL, 0, (func), (arg), 0, (tid)) != NULL; } -void -mono_threads_core_resume_created (MonoThreadInfo *info, MonoNativeThreadId tid) +gboolean +mono_native_thread_join (MonoNativeThreadId tid) { HANDLE handle; - handle = OpenThread (THREAD_ALL_ACCESS, TRUE, tid); - g_assert (handle); - ResumeThread (handle); + if (!(handle = OpenThread (THREAD_ALL_ACCESS, TRUE, tid))) + return FALSE; + + DWORD res = WaitForSingleObject (handle, INFINITE); + CloseHandle (handle); + + return res != WAIT_FAILED; } #if HAVE_DECL___READFSDWORD==0 @@ -255,7 +215,7 @@ __readfsdword (unsigned long offset) #endif void -mono_threads_core_get_stack_bounds (guint8 **staddr, size_t *stsize) +mono_threads_platform_get_stack_bounds (guint8 **staddr, size_t *stsize) { MEMORY_BASIC_INFORMATION meminfo; #ifdef _WIN64 @@ -283,38 +243,22 @@ mono_threads_core_get_stack_bounds (guint8 **staddr, size_t *stsize) } gboolean -mono_threads_core_yield (void) +mono_threads_platform_yield (void) { return SwitchToThread (); } void -mono_threads_core_exit (int exit_code) +mono_threads_platform_exit (int exit_code) { + mono_thread_info_detach (); ExitThread (exit_code); } void -mono_threads_core_unregister (MonoThreadInfo *info) +mono_threads_platform_unregister (MonoThreadInfo *info) { -} - -HANDLE -mono_threads_core_open_handle (void) -{ - HANDLE thread_handle; - - thread_handle = GetCurrentThread (); - g_assert (thread_handle); - - /* - * The handle returned by GetCurrentThread () is a pseudo handle, so it can't be used to - * refer to the thread from other threads for things like aborting. - */ - DuplicateHandle (GetCurrentProcess (), thread_handle, GetCurrentProcess (), &thread_handle, - THREAD_ALL_ACCESS, TRUE, 0); - - return thread_handle; + mono_threads_platform_set_exited (info); } int @@ -324,12 +268,29 @@ mono_threads_get_max_stack_size (void) return INT_MAX; } +gpointer +mono_threads_platform_duplicate_handle (MonoThreadInfo *info) +{ + HANDLE thread_handle; + + g_assert (info->handle); + DuplicateHandle (GetCurrentProcess (), info->handle, GetCurrentProcess (), &thread_handle, THREAD_ALL_ACCESS, TRUE, 0); + + return thread_handle; +} + HANDLE -mono_threads_core_open_thread_handle (HANDLE handle, MonoNativeThreadId tid) +mono_threads_platform_open_thread_handle (HANDLE handle, MonoNativeThreadId tid) { return OpenThread (THREAD_ALL_ACCESS, TRUE, tid); } +void +mono_threads_platform_close_thread_handle (HANDLE handle) +{ + CloseHandle (handle); +} + #if defined(_MSC_VER) const DWORD MS_VC_EXCEPTION=0x406D1388; #pragma pack(push,8) @@ -362,4 +323,55 @@ mono_native_thread_set_name (MonoNativeThreadId tid, const char *name) #endif } +void +mono_threads_platform_set_exited (MonoThreadInfo *info) +{ + g_assert (info->handle); + // No need to call CloseHandle() here since the InternalThread + // destructor will close the handle when the finalizer thread calls it + info->handle = NULL; +} + +void +mono_threads_platform_describe (MonoThreadInfo *info, GString *text) +{ + /* TODO */ +} + +void +mono_threads_platform_own_mutex (MonoThreadInfo *info, gpointer mutex_handle) +{ + g_assert_not_reached (); +} + +void +mono_threads_platform_disown_mutex (MonoThreadInfo *info, gpointer mutex_handle) +{ + g_assert_not_reached (); +} + +MonoThreadPriority +mono_threads_platform_get_priority (MonoThreadInfo *info) +{ + g_assert (info->handle); + return GetThreadPriority (info->handle) + 2; +} + +void +mono_threads_platform_set_priority (MonoThreadInfo *info, MonoThreadPriority priority) +{ + BOOL res; + + g_assert (info->handle); + + res = SetThreadPriority (info->handle, priority - 2); + if (!res) + g_error ("%s: SetThreadPriority failed, error %d", __func__, GetLastError ()); +} + +void +mono_threads_platform_init (void) +{ +} + #endif diff --git a/mono/utils/mono-threads.c b/mono/utils/mono-threads.c index 4eb18256b7..d0eedf683e 100644 --- a/mono/utils/mono-threads.c +++ b/mono/utils/mono-threads.c @@ -76,9 +76,12 @@ static gboolean unified_suspend_enabled; #define mono_thread_info_run_state(info) (((MonoThreadInfo*)info)->thread_state & THREAD_STATE_MASK) /*warn at 50 ms*/ -#define SLEEP_DURATION_BEFORE_WARNING (10) -/*abort at 1 sec*/ -#define SLEEP_DURATION_BEFORE_ABORT 200 +#define SLEEP_DURATION_BEFORE_WARNING (50) +/*never aborts */ +#define SLEEP_DURATION_BEFORE_ABORT MONO_INFINITE_WAIT + +static guint32 sleepWarnDuration = SLEEP_DURATION_BEFORE_WARNING, + sleepAbortDuration = SLEEP_DURATION_BEFORE_ABORT; static int suspend_posts, resume_posts, abort_posts, waits_done, pending_ops; @@ -115,7 +118,7 @@ begin_async_suspend (MonoThreadInfo *info, gboolean interrupt_kernel) return TRUE; } - return mono_threads_core_begin_async_suspend (info, interrupt_kernel); + return mono_threads_suspend_begin_async_suspend (info, interrupt_kernel); } static gboolean @@ -126,7 +129,7 @@ check_async_suspend (MonoThreadInfo *info) return TRUE; } - return mono_threads_core_check_suspend_result (info); + return mono_threads_suspend_check_suspend_result (info); } static void @@ -135,7 +138,7 @@ resume_async_suspended (MonoThreadInfo *info) if (mono_threads_is_coop_enabled ()) g_assert_not_reached (); - g_assert (mono_threads_core_begin_async_resume (info)); + g_assert (mono_threads_suspend_begin_async_resume (info)); } static void @@ -235,14 +238,14 @@ mono_threads_wait_pending_operations (void) for (i = 0; i < pending_suspends; ++i) { THREADS_SUSPEND_DEBUG ("[INITIATOR-WAIT-WAITING]\n"); InterlockedIncrement (&waits_done); - if (!mono_os_sem_timedwait (&suspend_semaphore, SLEEP_DURATION_BEFORE_ABORT, MONO_SEM_FLAGS_NONE)) + if (mono_os_sem_timedwait (&suspend_semaphore, sleepAbortDuration, MONO_SEM_FLAGS_NONE) == MONO_SEM_TIMEDWAIT_RET_SUCCESS) continue; mono_stopwatch_stop (&suspension_time); dump_threads (); MOSTLY_ASYNC_SAFE_PRINTF ("WAITING for %d threads, got %d suspended\n", (int)pending_suspends, i); - g_error ("suspend_thread suspend took %d ms, which is more than the allowed %d ms", (int)mono_stopwatch_elapsed_ms (&suspension_time), SLEEP_DURATION_BEFORE_ABORT); + g_error ("suspend_thread suspend took %d ms, which is more than the allowed %d ms", (int)mono_stopwatch_elapsed_ms (&suspension_time), sleepAbortDuration); } mono_stopwatch_stop (&suspension_time); THREADS_SUSPEND_DEBUG ("Suspending %d threads took %d ms.\n", (int)pending_suspends, (int)mono_stopwatch_elapsed_ms (&suspension_time)); @@ -276,7 +279,7 @@ If return non null Hazard Pointer 1 holds the return value. MonoThreadInfo* mono_thread_info_lookup (MonoNativeThreadId id) { - MonoThreadHazardPointers *hp = mono_hazard_pointer_get (); + MonoThreadHazardPointers *hp = mono_hazard_pointer_get (); if (!mono_lls_find (&thread_list, hp, (uintptr_t)id)) { mono_hazard_pointer_clear_all (hp, -1); @@ -319,7 +322,7 @@ free_thread_info (gpointer mem) MonoThreadInfo *info = (MonoThreadInfo *) mem; mono_os_sem_destroy (&info->resume_semaphore); - mono_threads_platform_free (info); + mono_threads_suspend_free (info); g_free (info); } @@ -356,6 +359,7 @@ register_thread (MonoThreadInfo *info, gpointer baseptr) if (threads_callbacks.thread_register) { if (threads_callbacks.thread_register (info, baseptr) == NULL) { // g_warning ("thread registation failed\n"); + mono_native_tls_set_value (thread_info_key, NULL); g_free (info); return NULL; } @@ -370,6 +374,7 @@ register_thread (MonoThreadInfo *info, gpointer baseptr) info->stackdata = g_byte_array_new (); mono_threads_platform_register (info); + mono_threads_suspend_register (info); /* Transition it before taking any locks or publishing itself to reduce the chance @@ -411,7 +416,7 @@ unregister_thread (void *arg) mono_native_tls_set_value (thread_exited_key, GUINT_TO_POINTER (1)); - mono_threads_core_unregister (info); + mono_threads_platform_unregister (info); /* * TLS destruction order is not reliable so small_id might be cleaned up @@ -655,6 +660,7 @@ mono_threads_init (MonoThreadInfoCallbacks *callbacks, size_t info_size) gboolean res; threads_callbacks = *callbacks; thread_info_size = info_size; + const char *sleepLimit; #ifdef HOST_WIN32 res = mono_native_tls_alloc (&thread_info_key, NULL); res = mono_native_tls_alloc (&thread_exited_key, NULL); @@ -671,15 +677,26 @@ mono_threads_init (MonoThreadInfoCallbacks *callbacks, size_t info_size) g_assert (res); unified_suspend_enabled = g_getenv ("MONO_ENABLE_UNIFIED_SUSPEND") != NULL || mono_threads_is_coop_enabled (); + + if ((sleepLimit = g_getenv ("MONO_SLEEP_ABORT_LIMIT")) != NULL) { + errno = 0; + long threshold = strtol(sleepLimit, NULL, 10); + if ((errno == 0) && (threshold >= 40)) { + sleepAbortDuration = threshold; + sleepWarnDuration = threshold / 20; + } else + g_warning("MONO_SLEEP_ABORT_LIMIT must be a number >= 40"); + } mono_os_sem_init (&global_suspend_semaphore, 1); mono_os_sem_init (&suspend_semaphore, 0); mono_lls_init (&thread_list, NULL); mono_thread_smr_init (); - mono_threads_init_platform (); - mono_threads_init_coop (); - mono_threads_init_abort_syscall (); + mono_threads_platform_init (); + mono_threads_suspend_init (); + mono_threads_coop_init (); + mono_threads_abort_syscall_init (); #if defined(__MACH__) mono_mach_init (thread_info_key); @@ -749,13 +766,6 @@ static gboolean mono_thread_info_core_resume (MonoThreadInfo *info) { gboolean res = FALSE; - if (info->create_suspended) { - MonoNativeThreadId tid = mono_thread_info_get_tid (info); - /* Have to special case this, as the normal suspend/resume pair are racy, they don't work if he resume is received before the suspend */ - info->create_suspended = FALSE; - mono_threads_core_resume_created (info, tid); - return TRUE; - } switch (mono_threads_transition_request_resume (info)) { case ResumeError: @@ -907,7 +917,7 @@ suspend_sync (MonoNativeThreadId tid, gboolean interrupt_kernel) break; case AsyncSuspendBlocking: if (interrupt_kernel) - mono_threads_core_abort_syscall (info); + mono_threads_suspend_abort_syscall (info); break; default: @@ -1065,7 +1075,7 @@ mono_thread_info_abort_socket_syscall_for_close (MonoNativeThreadId tid) MonoThreadHazardPointers *hp; MonoThreadInfo *info; - if (tid == mono_native_thread_id_get () || !mono_threads_core_needs_abort_syscall ()) + if (tid == mono_native_thread_id_get () || !mono_threads_suspend_needs_abort_syscall ()) return; hp = mono_hazard_pointer_get (); @@ -1081,7 +1091,7 @@ mono_thread_info_abort_socket_syscall_for_close (MonoNativeThreadId tid) mono_thread_info_suspend_lock (); mono_threads_begin_global_suspend (); - mono_threads_core_abort_syscall (info); + mono_threads_suspend_abort_syscall (info); mono_threads_wait_pending_operations (); mono_hazard_pointer_clear (hp, 1); @@ -1122,6 +1132,59 @@ mono_thread_info_is_async_context (void) return FALSE; } +typedef struct { + gint32 ref; + MonoThreadStart start_routine; + gpointer start_routine_arg; + gint32 priority; + MonoCoopSem registered; + gpointer handle; +} CreateThreadData; + +static gsize WINAPI +inner_start_thread (gpointer data) +{ + CreateThreadData *thread_data; + MonoThreadInfo *info; + MonoThreadStart start_routine; + gpointer start_routine_arg; + guint32 start_routine_res; + gint32 priority; + gsize dummy; + + thread_data = (CreateThreadData*) data; + g_assert (thread_data); + + start_routine = thread_data->start_routine; + start_routine_arg = thread_data->start_routine_arg; + + priority = thread_data->priority; + + info = mono_thread_info_attach (&dummy); + info->runtime_thread = TRUE; + + mono_threads_platform_set_priority (info, priority); + + thread_data->handle = mono_thread_info_duplicate_handle (info); + + mono_coop_sem_post (&thread_data->registered); + + if (InterlockedDecrement (&thread_data->ref) == 0) { + mono_coop_sem_destroy (&thread_data->registered); + g_free (thread_data); + } + + /* thread_data is not valid anymore */ + thread_data = NULL; + + /* Run the actual main function of the thread */ + start_routine_res = start_routine (start_routine_arg); + + mono_threads_platform_exit (start_routine_res); + + g_assert_not_reached (); +} + /* * mono_threads_create_thread: * @@ -1129,9 +1192,40 @@ mono_thread_info_is_async_context (void) * Returns: a windows or io-layer handle for the thread. */ HANDLE -mono_threads_create_thread (LPTHREAD_START_ROUTINE start, gpointer arg, guint32 stack_size, guint32 creation_flags, MonoNativeThreadId *out_tid) +mono_threads_create_thread (MonoThreadStart start, gpointer arg, MonoThreadParm *tp, MonoNativeThreadId *out_tid) { - return mono_threads_core_create_thread (start, arg, stack_size, creation_flags, out_tid); + CreateThreadData *thread_data; + gint res; + gpointer ret; + + thread_data = g_new0 (CreateThreadData, 1); + thread_data->ref = 2; + thread_data->start_routine = start; + thread_data->start_routine_arg = arg; + thread_data->priority = tp->priority; + mono_coop_sem_init (&thread_data->registered, 0); + + res = mono_threads_platform_create_thread (inner_start_thread, (gpointer) thread_data, tp->stack_size, out_tid); + if (res != 0) { + /* ref is not going to be decremented in inner_start_thread */ + InterlockedDecrement (&thread_data->ref); + ret = NULL; + goto done; + } + + res = mono_coop_sem_wait (&thread_data->registered, MONO_SEM_FLAGS_NONE); + g_assert (res == 0); + + ret = thread_data->handle; + g_assert (ret); + +done: + if (InterlockedDecrement (&thread_data->ref) == 0) { + mono_coop_sem_destroy (&thread_data->registered); + g_free (thread_data); + } + + return ret; } /* @@ -1144,7 +1238,7 @@ void mono_thread_info_get_stack_bounds (guint8 **staddr, size_t *stsize) { guint8 *current = (guint8 *)&stsize; - mono_threads_core_get_stack_bounds (staddr, stsize); + mono_threads_platform_get_stack_bounds (staddr, stsize); if (!*staddr) return; @@ -1158,7 +1252,7 @@ mono_thread_info_get_stack_bounds (guint8 **staddr, size_t *stsize) gboolean mono_thread_info_yield (void) { - return mono_threads_core_yield (); + return mono_threads_platform_yield (); } static mono_lazy_init_t sleep_init = MONO_LAZY_INIT_STATUS_NOT_INITIALIZED; static MonoCoopMutex sleep_mutex; @@ -1332,20 +1426,7 @@ mono_thread_info_tls_set (THREAD_INFO_TYPE *info, MonoTlsKey key, gpointer value void mono_thread_info_exit (void) { - mono_threads_core_exit (0); -} - -/* - * mono_thread_info_open_handle: - * - * Return a io-layer/win32 handle for the current thread. - * The handle need to be closed by calling CloseHandle () when it is no - * longer needed. - */ -HANDLE -mono_thread_info_open_handle (void) -{ - return mono_threads_core_open_handle (); + mono_threads_platform_exit (0); } /* @@ -1358,7 +1439,13 @@ mono_thread_info_open_handle (void) HANDLE mono_threads_open_thread_handle (HANDLE handle, MonoNativeThreadId tid) { - return mono_threads_core_open_thread_handle (handle, tid); + return mono_threads_platform_open_thread_handle (handle, tid); +} + +void +mono_threads_close_thread_handle (HANDLE handle) +{ + return mono_threads_platform_close_thread_handle (handle); } #define INTERRUPT_STATE ((MonoThreadInfoInterruptToken*) (size_t) -1) @@ -1566,3 +1653,47 @@ mono_thread_info_is_current (MonoThreadInfo *info) { return mono_thread_info_get_tid (info) == mono_native_thread_id_get (); } + +void +mono_thread_info_set_exited (THREAD_INFO_TYPE *info) +{ + g_assert (mono_thread_info_is_current (info)); + mono_threads_platform_set_exited (info); +} + +gpointer +mono_thread_info_duplicate_handle (MonoThreadInfo *info) +{ + g_assert (mono_thread_info_is_current (info)); + return mono_threads_platform_duplicate_handle (info); +} + +void +mono_thread_info_describe (MonoThreadInfo *info, GString *text) +{ + mono_threads_platform_describe (info, text); +} + +void +mono_thread_info_own_mutex (MonoThreadInfo *info, gpointer mutex_handle) +{ + mono_threads_platform_own_mutex (info, mutex_handle); +} + +void +mono_thread_info_disown_mutex (MonoThreadInfo *info, gpointer mutex_handle) +{ + mono_threads_platform_disown_mutex (info, mutex_handle); +} + +MonoThreadPriority +mono_thread_info_get_priority (MonoThreadInfo *info) +{ + return mono_threads_platform_get_priority (info); +} + +void +mono_thread_info_set_priority (MonoThreadInfo *info, MonoThreadPriority priority) +{ + mono_threads_platform_set_priority (info, priority); +} diff --git a/mono/utils/mono-threads.h b/mono/utils/mono-threads.h index 774520f600..a6ea7bd426 100644 --- a/mono/utils/mono-threads.h +++ b/mono/utils/mono-threads.h @@ -32,6 +32,8 @@ typedef DWORD mono_native_thread_return_t; #define MONO_NATIVE_THREAD_ID_TO_UINT(tid) (tid) #define MONO_UINT_TO_NATIVE_THREAD_ID(tid) ((MonoNativeThreadId)(tid)) +typedef LPTHREAD_START_ROUTINE MonoThreadStart; + #else #include @@ -56,6 +58,8 @@ typedef void* mono_native_thread_return_t; #define MONO_NATIVE_THREAD_ID_TO_UINT(tid) (gsize)(tid) #define MONO_UINT_TO_NATIVE_THREAD_ID(tid) (MonoNativeThreadId)(gsize)(tid) +typedef gsize (*MonoThreadStart)(gpointer); + #endif /* #ifdef HOST_WIN32 */ /* @@ -217,11 +221,6 @@ typedef struct { */ gboolean is_async_context; - gboolean create_suspended; - - /* Semaphore used to implement CREATE_SUSPENDED */ - MonoCoopSem create_suspended_sem; - /* * Values of TLS variables for this thread. * This can be used to obtain the values of TLS variable for threads @@ -237,8 +236,17 @@ typedef struct { MonoThreadInfoInterruptToken *interrupt_token; - /* MonoHandleArena for coop handles */ - gpointer handle_arena; + /* HandleStack for coop handles */ + gpointer handle_stack; + + /* Stack mark for targets that explicitly require one */ + gpointer stack_mark; + +#if defined(_POSIX_VERSION) || defined(__native_client__) + /* This is the data that was stored in the w32 handle */ + GPtrArray *owned_mutexes; + gint32 priority; +#endif } MonoThreadInfo; typedef struct { @@ -277,6 +285,23 @@ typedef enum { typedef SuspendThreadResult (*MonoSuspendThreadCallback) (THREAD_INFO_TYPE *info, gpointer user_data); +/* + * Parameters to pass for thread creation + */ +typedef struct { + int priority; + guint32 creation_flags; + guint32 stack_size; +} MonoThreadParm; + +typedef enum { + MONO_THREAD_PRIORITY_LOWEST = 0, + MONO_THREAD_PRIORITY_BELOW_NORMAL = 1, + MONO_THREAD_PRIORITY_NORMAL = 2, + MONO_THREAD_PRIORITY_ABOVE_NORMAL = 3, + MONO_THREAD_PRIORITY_HIGHEST = 4, +} MonoThreadPriority; + static inline gboolean mono_threads_filter_tools_threads (THREAD_INFO_TYPE *info) { @@ -410,8 +435,8 @@ mono_thread_info_tls_set (THREAD_INFO_TYPE *info, MonoTlsKey key, gpointer value void mono_thread_info_exit (void); -HANDLE -mono_thread_info_open_handle (void); +void +mono_thread_info_set_exited (THREAD_INFO_TYPE *info); void mono_thread_info_install_interrupt (void (*callback) (gpointer data), gpointer data, gboolean *interrupted); @@ -441,7 +466,7 @@ gboolean mono_thread_info_is_live (THREAD_INFO_TYPE *info); HANDLE -mono_threads_create_thread (LPTHREAD_START_ROUTINE start, gpointer arg, guint32 stack_size, guint32 creation_flags, MonoNativeThreadId *out_tid); +mono_threads_create_thread (MonoThreadStart start, gpointer arg, MonoThreadParm *tp, MonoNativeThreadId *out_tid); int mono_threads_get_max_stack_size (void); @@ -449,6 +474,9 @@ mono_threads_get_max_stack_size (void); HANDLE mono_threads_open_thread_handle (HANDLE handle, MonoNativeThreadId tid); +void +mono_threads_close_thread_handle (HANDLE handle); + MONO_API void mono_threads_attach_tools_thread (void); @@ -468,11 +496,13 @@ mono_threads_pthread_kill (THREAD_INFO_TYPE *info, int signum); This is called very early in the runtime, it cannot access any runtime facilities. */ -void mono_threads_init_platform (void); //ok +void mono_threads_suspend_init (void); //ok -void mono_threads_init_coop (void); +void mono_threads_platform_init (void); -void mono_threads_init_abort_syscall (void); +void mono_threads_coop_init (void); + +void mono_threads_abort_syscall_init (void); /* This begins async suspend. This function must do the following: @@ -483,7 +513,7 @@ This begins async suspend. This function must do the following: If begin suspend fails the thread must be left uninterrupted and resumed. */ -gboolean mono_threads_core_begin_async_suspend (THREAD_INFO_TYPE *info, gboolean interrupt_kernel); +gboolean mono_threads_suspend_begin_async_suspend (THREAD_INFO_TYPE *info, gboolean interrupt_kernel); /* This verifies the outcome of an async suspend operation. @@ -491,7 +521,7 @@ This verifies the outcome of an async suspend operation. Some targets, such as posix, verify suspend results assynchronously. Suspend results must be available (in a non blocking way) after mono_threads_wait_pending_operations completes. */ -gboolean mono_threads_core_check_suspend_result (THREAD_INFO_TYPE *info); +gboolean mono_threads_suspend_check_suspend_result (THREAD_INFO_TYPE *info); /* This begins async resume. This function must do the following: @@ -500,20 +530,28 @@ This begins async resume. This function must do the following: - Notify the target to resume. - Register the thread for pending ack with mono_threads_add_to_pending_operation_set if needed. */ -gboolean mono_threads_core_begin_async_resume (THREAD_INFO_TYPE *info); +gboolean mono_threads_suspend_begin_async_resume (THREAD_INFO_TYPE *info); -void mono_threads_platform_register (THREAD_INFO_TYPE *info); //ok -void mono_threads_platform_free (THREAD_INFO_TYPE *info); -void mono_threads_core_abort_syscall (THREAD_INFO_TYPE *info); -gboolean mono_threads_core_needs_abort_syscall (void); -HANDLE mono_threads_core_create_thread (LPTHREAD_START_ROUTINE start, gpointer arg, guint32 stack_size, guint32 creation_flags, MonoNativeThreadId *out_tid); -void mono_threads_core_resume_created (THREAD_INFO_TYPE *info, MonoNativeThreadId tid); -void mono_threads_core_get_stack_bounds (guint8 **staddr, size_t *stsize); -gboolean mono_threads_core_yield (void); -void mono_threads_core_exit (int exit_code); -void mono_threads_core_unregister (THREAD_INFO_TYPE *info); -HANDLE mono_threads_core_open_handle (void); -HANDLE mono_threads_core_open_thread_handle (HANDLE handle, MonoNativeThreadId tid); +void mono_threads_suspend_register (THREAD_INFO_TYPE *info); //ok +void mono_threads_suspend_free (THREAD_INFO_TYPE *info); +void mono_threads_suspend_abort_syscall (THREAD_INFO_TYPE *info); +gboolean mono_threads_suspend_needs_abort_syscall (void); + +void mono_threads_platform_register (THREAD_INFO_TYPE *info); +void mono_threads_platform_unregister (THREAD_INFO_TYPE *info); +int mono_threads_platform_create_thread (MonoThreadStart thread_fn, gpointer thread_data, gsize stack_size, MonoNativeThreadId *out_tid); +void mono_threads_platform_get_stack_bounds (guint8 **staddr, size_t *stsize); +gboolean mono_threads_platform_yield (void); +void mono_threads_platform_exit (int exit_code); +HANDLE mono_threads_platform_open_thread_handle (HANDLE handle, MonoNativeThreadId tid); +void mono_threads_platform_close_thread_handle (HANDLE handle); +void mono_threads_platform_set_exited (THREAD_INFO_TYPE *info); +void mono_threads_platform_describe (THREAD_INFO_TYPE *info, GString *text); +void mono_threads_platform_own_mutex (THREAD_INFO_TYPE *info, gpointer mutex_handle); +void mono_threads_platform_disown_mutex (THREAD_INFO_TYPE *info, gpointer mutex_handle); +MonoThreadPriority mono_threads_platform_get_priority (THREAD_INFO_TYPE *info); +void mono_threads_platform_set_priority (THREAD_INFO_TYPE *info, MonoThreadPriority priority); +gpointer mono_threads_platform_duplicate_handle (THREAD_INFO_TYPE *info); void mono_threads_coop_begin_global_suspend (void); void mono_threads_coop_end_global_suspend (void); @@ -521,15 +559,18 @@ void mono_threads_coop_end_global_suspend (void); MONO_API MonoNativeThreadId mono_native_thread_id_get (void); -gboolean +MONO_API gboolean mono_native_thread_id_equals (MonoNativeThreadId id1, MonoNativeThreadId id2); -gboolean +MONO_API gboolean mono_native_thread_create (MonoNativeThreadId *tid, gpointer func, gpointer arg); MONO_API void mono_native_thread_set_name (MonoNativeThreadId tid, const char *name); +MONO_API gboolean +mono_native_thread_join (MonoNativeThreadId tid); + /*Mach specific internals */ void mono_threads_init_dead_letter (void); void mono_threads_install_dead_letter (void); @@ -628,4 +669,22 @@ void mono_threads_end_global_suspend (void); gboolean mono_thread_info_is_current (THREAD_INFO_TYPE *info); +gpointer +mono_thread_info_duplicate_handle (THREAD_INFO_TYPE *info); + +void +mono_thread_info_describe (THREAD_INFO_TYPE *info, GString *text); + +void +mono_thread_info_own_mutex (THREAD_INFO_TYPE *info, gpointer mutex_handle); + +void +mono_thread_info_disown_mutex (THREAD_INFO_TYPE *info, gpointer mutex_handle); + +MonoThreadPriority +mono_thread_info_get_priority (THREAD_INFO_TYPE *info); + +void +mono_thread_info_set_priority (THREAD_INFO_TYPE *info, MonoThreadPriority priority); + #endif /* __MONO_THREADS_H__ */ diff --git a/mono/utils/mono-uri.c b/mono/utils/mono-uri.c index 7a2c4ac810..8ebc25a69b 100644 --- a/mono/utils/mono-uri.c +++ b/mono/utils/mono-uri.c @@ -36,7 +36,7 @@ mono_escape_uri_string (const gchar *string) #if TEST int main () { - char *s = malloc (256); + char *s = g_malloc (256); int i = 0; s [255] = 0; diff --git a/mono/utils/w32handle.c b/mono/utils/w32handle.c new file mode 100644 index 0000000000..5fd01a3db2 --- /dev/null +++ b/mono/utils/w32handle.c @@ -0,0 +1,1518 @@ +/* + * w32handle.c: Generic and internal operations on handles + * + * Author: + * Dick Porter (dick@ximian.com) + * Ludovic Henry (luhenry@microsoft.com) + * + * (C) 2002-2011 Novell, Inc. + * Copyright 2011 Xamarin Inc + * Licensed under the MIT license. See LICENSE file in the project root for full license information. + */ + +#include + +#if !defined(HOST_WIN32) + +#include +#include +#include +#include +#ifdef HAVE_SIGNAL_H +#include +#endif +#include +#include +#ifdef HAVE_SYS_SOCKET_H +# include +#endif +#ifdef HAVE_SYS_UN_H +# include +#endif +#ifdef HAVE_SYS_MMAN_H +# include +#endif +#ifdef HAVE_DIRENT_H +# include +#endif +#include +#ifdef HAVE_SYS_RESOURCE_H +# include +#endif + +#include "w32handle.h" + +#include "atomic.h" +#include "mono-logger-internals.h" +#include "mono-os-mutex.h" +#include "mono-proclib.h" +#include "mono-threads.h" +#include "mono-time.h" + +#undef DEBUG_REFS + +#define SLOT_MAX (1024 * 16) + +/* must be a power of 2 */ +#define HANDLE_PER_SLOT (256) + +#define INFINITE 0xFFFFFFFF + +typedef struct { + MonoW32HandleType type; + guint ref; + gboolean signalled; + mono_mutex_t signal_mutex; + mono_cond_t signal_cond; + gpointer specific; +} MonoW32HandleBase; + +static MonoW32HandleCapability handle_caps [MONO_W32HANDLE_COUNT]; +static MonoW32HandleOps *handle_ops [MONO_W32HANDLE_COUNT]; + +/* + * We can hold SLOT_MAX * HANDLE_PER_SLOT handles. + * If 4M handles are not enough... Oh, well... we will crash. + */ +#define SLOT_INDEX(x) (x / HANDLE_PER_SLOT) +#define SLOT_OFFSET(x) (x % HANDLE_PER_SLOT) + +static MonoW32HandleBase *private_handles [SLOT_MAX]; +static guint32 private_handles_count = 0; +static guint32 private_handles_slots_count = 0; + +guint32 mono_w32handle_fd_reserve; + +/* + * This is an internal handle which is used for handling waiting for multiple handles. + * Threads which wait for multiple handles wait on this one handle, and when a handle + * is signalled, this handle is signalled too. + */ +static mono_mutex_t global_signal_mutex; +static mono_cond_t global_signal_cond; + +static mono_mutex_t scan_mutex; + +static gboolean shutting_down = FALSE; + +static gboolean +type_is_fd (MonoW32HandleType type) +{ + switch (type) { + case MONO_W32HANDLE_FILE: + case MONO_W32HANDLE_CONSOLE: + case MONO_W32HANDLE_SOCKET: + case MONO_W32HANDLE_PIPE: + return TRUE; + default: + return FALSE; + } +} + +static gboolean +mono_w32handle_lookup_data (gpointer handle, MonoW32HandleBase **handle_data) +{ + gsize index, offset; + + g_assert (handle_data); + + index = SLOT_INDEX ((gsize) handle); + if (index >= SLOT_MAX) + return FALSE; + if (!private_handles [index]) + return FALSE; + + offset = SLOT_OFFSET ((gsize) handle); + if (private_handles [index][offset].type == MONO_W32HANDLE_UNUSED) + return FALSE; + + *handle_data = &private_handles [index][offset]; + return TRUE; +} + +MonoW32HandleType +mono_w32handle_get_type (gpointer handle) +{ + MonoW32HandleBase *handle_data; + + if (!mono_w32handle_lookup_data (handle, &handle_data)) + return MONO_W32HANDLE_UNUSED; /* An impossible type */ + + return handle_data->type; +} + +void +mono_w32handle_set_signal_state (gpointer handle, gboolean state, gboolean broadcast) +{ + MonoW32HandleBase *handle_data; + + if (!mono_w32handle_lookup_data (handle, &handle_data)) { + return; + } + +#ifdef DEBUG + g_message ("%s: setting state of %p to %s (broadcast %s)", __func__, + handle, state?"TRUE":"FALSE", broadcast?"TRUE":"FALSE"); +#endif + + if (state == TRUE) { + /* Tell everyone blocking on a single handle */ + + /* The condition the global signal cond is waiting on is the signalling of + * _any_ handle. So lock it before setting the signalled state. + */ + mono_os_mutex_lock (&global_signal_mutex); + + /* This function _must_ be called with + * handle->signal_mutex locked + */ + handle_data->signalled=state; + + if (broadcast == TRUE) { + mono_os_cond_broadcast (&handle_data->signal_cond); + } else { + mono_os_cond_signal (&handle_data->signal_cond); + } + + /* Tell everyone blocking on multiple handles that something + * was signalled + */ + mono_os_cond_broadcast (&global_signal_cond); + + mono_os_mutex_unlock (&global_signal_mutex); + } else { + handle_data->signalled=state; + } +} + +gboolean +mono_w32handle_issignalled (gpointer handle) +{ + MonoW32HandleBase *handle_data; + + if (!mono_w32handle_lookup_data (handle, &handle_data)) { + return(FALSE); + } + + return handle_data->signalled; +} + +static int +mono_w32handle_lock_signal_mutex (void) +{ +#ifdef DEBUG + g_message ("%s: lock global signal mutex", __func__); +#endif + + mono_os_mutex_lock (&global_signal_mutex); + + return 0; +} + +static int +mono_w32handle_unlock_signal_mutex (void) +{ +#ifdef DEBUG + g_message ("%s: unlock global signal mutex", __func__); +#endif + + mono_os_mutex_unlock (&global_signal_mutex); + + return 0; +} + +int +mono_w32handle_lock_handle (gpointer handle) +{ + MonoW32HandleBase *handle_data; + +#ifdef DEBUG + g_message ("%s: locking handle %p", __func__, handle); +#endif + + if (!mono_w32handle_lookup_data (handle, &handle_data)) { + return(0); + } + + mono_w32handle_ref (handle); + + mono_os_mutex_lock (&handle_data->signal_mutex); + + return 0; +} + +int +mono_w32handle_trylock_handle (gpointer handle) +{ + MonoW32HandleBase *handle_data; + int ret; + +#ifdef DEBUG + g_message ("%s: locking handle %p", __func__, handle); +#endif + + if (!mono_w32handle_lookup_data (handle, &handle_data)) { + return(0); + } + + mono_w32handle_ref (handle); + + ret = mono_os_mutex_trylock (&handle_data->signal_mutex); + if (ret != 0) { + mono_w32handle_unref (handle); + } + + return(ret); +} + +int +mono_w32handle_unlock_handle (gpointer handle) +{ + MonoW32HandleBase *handle_data; + +#ifdef DEBUG + g_message ("%s: unlocking handle %p", __func__, handle); +#endif + + if (!mono_w32handle_lookup_data (handle, &handle_data)) { + return(0); + } + + mono_os_mutex_unlock (&handle_data->signal_mutex); + + mono_w32handle_unref (handle); + + return 0; +} + +/* + * wapi_init: + * + * Initialize the io-layer. + */ +void +mono_w32handle_init (void) +{ + static gboolean initialized = FALSE; + + if (initialized) + return; + + g_assert ((sizeof (handle_ops) / sizeof (handle_ops[0])) + == MONO_W32HANDLE_COUNT); + + /* This is needed by the code in mono_w32handle_new_internal */ + mono_w32handle_fd_reserve = (eg_getdtablesize () + (HANDLE_PER_SLOT - 1)) & ~(HANDLE_PER_SLOT - 1); + + do { + /* + * The entries in private_handles reserved for fds are allocated lazily to + * save memory. + */ + + private_handles_count += HANDLE_PER_SLOT; + private_handles_slots_count ++; + } while(mono_w32handle_fd_reserve > private_handles_count); + + mono_os_mutex_init (&scan_mutex); + + mono_os_cond_init (&global_signal_cond); + mono_os_mutex_init (&global_signal_mutex); + + initialized = TRUE; +} + +static void mono_w32handle_unref_full (gpointer handle, gboolean ignore_private_busy_handles); + +void +mono_w32handle_cleanup (void) +{ + int i, j, k; + + g_assert (!shutting_down); + shutting_down = TRUE; + + /* Every shared handle we were using ought really to be closed + * by now, but to make sure just blow them all away. The + * exiting finalizer thread in particular races us to the + * program exit and doesn't always win, so it can be left + * cluttering up the shared file. Anything else left over is + * really a bug. + */ + for(i = SLOT_INDEX (0); private_handles[i] != NULL; i++) { + for(j = SLOT_OFFSET (0); j < HANDLE_PER_SLOT; j++) { + MonoW32HandleBase *handle_data = &private_handles[i][j]; + gpointer handle = GINT_TO_POINTER (i*HANDLE_PER_SLOT+j); + + for(k = handle_data->ref; k > 0; k--) { + mono_w32handle_unref_full (handle, TRUE); + } + } + } + + for (i = 0; i < SLOT_MAX; ++i) + g_free (private_handles [i]); +} + +static void mono_w32handle_init_handle (MonoW32HandleBase *handle, + MonoW32HandleType type, gpointer handle_specific) +{ + handle->type = type; + handle->signalled = FALSE; + handle->ref = 1; + + mono_os_cond_init (&handle->signal_cond); + mono_os_mutex_init (&handle->signal_mutex); + + if (handle_specific) + handle->specific = g_memdup (handle_specific, mono_w32handle_ops_typesize (type)); +} + +/* + * mono_w32handle_new_internal: + * @type: Init handle to this type + * + * Search for a free handle and initialize it. Return the handle on + * success and 0 on failure. This is only called from + * mono_w32handle_new, and scan_mutex must be held. + */ +static guint32 mono_w32handle_new_internal (MonoW32HandleType type, + gpointer handle_specific) +{ + guint32 i, k, count; + static guint32 last = 0; + gboolean retry = FALSE; + + /* A linear scan should be fast enough. Start from the last + * allocation, assuming that handles are allocated more often + * than they're freed. Leave the space reserved for file + * descriptors + */ + + if (last < mono_w32handle_fd_reserve) { + last = mono_w32handle_fd_reserve; + } else { + retry = TRUE; + } + +again: + count = last; + for(i = SLOT_INDEX (count); i < private_handles_slots_count; i++) { + if (private_handles [i]) { + for (k = SLOT_OFFSET (count); k < HANDLE_PER_SLOT; k++) { + MonoW32HandleBase *handle = &private_handles [i][k]; + + if(handle->type == MONO_W32HANDLE_UNUSED) { + last = count + 1; + + mono_w32handle_init_handle (handle, type, handle_specific); + return (count); + } + count++; + } + } + } + + if(retry && last > mono_w32handle_fd_reserve) { + /* Try again from the beginning */ + last = mono_w32handle_fd_reserve; + goto again; + } + + /* Will need to expand the array. The caller will sort it out */ + + return(0); +} + +gpointer +mono_w32handle_new (MonoW32HandleType type, gpointer handle_specific) +{ + guint32 handle_idx = 0; + gpointer handle; + + g_assert (!shutting_down); + + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: Creating new handle of type %s", __func__, + mono_w32handle_ops_typename (type)); + + g_assert(!type_is_fd(type)); + + mono_os_mutex_lock (&scan_mutex); + + while ((handle_idx = mono_w32handle_new_internal (type, handle_specific)) == 0) { + /* Try and expand the array, and have another go */ + int idx = SLOT_INDEX (private_handles_count); + if (idx >= SLOT_MAX) { + break; + } + + private_handles [idx] = g_new0 (MonoW32HandleBase, HANDLE_PER_SLOT); + + private_handles_count += HANDLE_PER_SLOT; + private_handles_slots_count ++; + } + + mono_os_mutex_unlock (&scan_mutex); + + if (handle_idx == 0) { + /* We ran out of slots */ + handle = INVALID_HANDLE_VALUE; + goto done; + } + + /* Make sure we left the space for fd mappings */ + g_assert (handle_idx >= mono_w32handle_fd_reserve); + + handle = GUINT_TO_POINTER (handle_idx); + + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: Allocated new handle %p", __func__, handle); + +done: + return(handle); +} + +gpointer mono_w32handle_new_fd (MonoW32HandleType type, int fd, + gpointer handle_specific) +{ + MonoW32HandleBase *handle_data; + int fd_index, fd_offset; + + g_assert (!shutting_down); + + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: Creating new handle of type %s", __func__, + mono_w32handle_ops_typename (type)); + + g_assert(type_is_fd(type)); + + if (fd >= mono_w32handle_fd_reserve) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: fd %d is too big", __func__, fd); + + return(GUINT_TO_POINTER (INVALID_HANDLE_VALUE)); + } + + fd_index = SLOT_INDEX (fd); + fd_offset = SLOT_OFFSET (fd); + + /* Initialize the array entries on demand */ + if (!private_handles [fd_index]) { + mono_os_mutex_lock (&scan_mutex); + + if (!private_handles [fd_index]) + private_handles [fd_index] = g_new0 (MonoW32HandleBase, HANDLE_PER_SLOT); + + mono_os_mutex_unlock (&scan_mutex); + } + + handle_data = &private_handles [fd_index][fd_offset]; + + if (handle_data->type != MONO_W32HANDLE_UNUSED) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: fd %d is already in use!", __func__, fd); + /* FIXME: clean up this handle? We can't do anything + * with the fd, cos thats the new one + */ + } + + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: Assigning new fd handle %p", __func__, (gpointer)(gsize)fd); + + mono_w32handle_init_handle (handle_data, type, handle_specific); + + return(GUINT_TO_POINTER(fd)); +} + +gboolean +mono_w32handle_lookup (gpointer handle, MonoW32HandleType type, + gpointer *handle_specific) +{ + MonoW32HandleBase *handle_data; + + g_assert (handle_specific); + + if (!mono_w32handle_lookup_data (handle, &handle_data)) { + return(FALSE); + } + + if (handle_data->type != type) { + return(FALSE); + } + + *handle_specific = handle_data->specific; + + return(TRUE); +} + +void +mono_w32handle_foreach (gboolean (*on_each)(gpointer handle, gpointer data, gpointer user_data), gpointer user_data) +{ + MonoW32HandleBase *handle_data = NULL; + gpointer handle; + guint32 i, k; + + mono_os_mutex_lock (&scan_mutex); + + for (i = SLOT_INDEX (0); i < private_handles_slots_count; i++) { + if (private_handles [i]) { + for (k = SLOT_OFFSET (0); k < HANDLE_PER_SLOT; k++) { + handle_data = &private_handles [i][k]; + if (handle_data->type == MONO_W32HANDLE_UNUSED) + continue; + handle = GUINT_TO_POINTER (i * HANDLE_PER_SLOT + k); + if (on_each (handle, handle_data->specific, user_data) == TRUE) + goto done; + } + } + } + +done: + mono_os_mutex_unlock (&scan_mutex); +} + +/* This might list some shared handles twice if they are already + * opened by this process, and the check function returns FALSE the + * first time. Shared handles that are created during the search are + * unreffed if the check function returns FALSE, so callers must not + * rely on the handle persisting (unless the check function returns + * TRUE) + * The caller owns the returned handle. + */ +gpointer mono_w32handle_search (MonoW32HandleType type, + gboolean (*check)(gpointer test, gpointer user), + gpointer user_data, + gpointer *handle_specific, + gboolean search_shared) +{ + MonoW32HandleBase *handle_data = NULL; + gpointer ret = NULL; + guint32 i, k; + gboolean found = FALSE; + + mono_os_mutex_lock (&scan_mutex); + + for (i = SLOT_INDEX (0); !found && i < private_handles_slots_count; i++) { + if (private_handles [i]) { + for (k = SLOT_OFFSET (0); k < HANDLE_PER_SLOT; k++) { + handle_data = &private_handles [i][k]; + + if (handle_data->type == type) { + ret = GUINT_TO_POINTER (i * HANDLE_PER_SLOT + k); + if (check (ret, user_data) == TRUE) { + mono_w32handle_ref (ret); + found = TRUE; + break; + } + } + } + } + } + + mono_os_mutex_unlock (&scan_mutex); + + if (!found) { + ret = NULL; + goto done; + } + + if(handle_specific != NULL) { + *handle_specific = handle_data->specific; + } + +done: + return(ret); +} + +void mono_w32handle_ref (gpointer handle) +{ + MonoW32HandleBase *handle_data; + + if (!mono_w32handle_lookup_data (handle, &handle_data)) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: Attempting to ref invalid private handle %p", __func__, handle); + return; + } + + InterlockedIncrement ((gint32 *)&handle_data->ref); + +#ifdef DEBUG_REFS + g_message ("%s: %s handle %p ref now %d", + __func__, mono_w32handle_ops_typename (handle_data->type), handle, handle_data->ref); +#endif +} + +static void (*_wapi_handle_ops_get_close_func (MonoW32HandleType type))(gpointer, gpointer); + +/* The handle must not be locked on entry to this function */ +static void mono_w32handle_unref_full (gpointer handle, gboolean ignore_private_busy_handles) +{ + MonoW32HandleBase *handle_data; + gboolean destroy = FALSE, early_exit = FALSE; + int thr_ret; + + if (!mono_w32handle_lookup_data (handle, &handle_data)) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: Attempting to unref invalid private handle %p", + __func__, handle); + return; + } + + /* Possible race condition here if another thread refs the + * handle between here and setting the type to UNUSED. I + * could lock a mutex, but I'm not sure that allowing a handle + * reference to reach 0 isn't an application bug anyway. + */ + destroy = (InterlockedDecrement ((gint32 *)&handle_data->ref) ==0); + +#ifdef DEBUG_REFS + g_message ("%s: %s handle %p ref now %d (destroy %s)", + __func__, mono_w32handle_ops_typename (handle_data->type), handle, handle_data->ref, destroy?"TRUE":"FALSE"); +#endif + + if(destroy==TRUE) { + /* Need to copy the handle info, reset the slot in the + * array, and _only then_ call the close function to + * avoid race conditions (eg file descriptors being + * closed, and another file being opened getting the + * same fd racing the memset()) + */ + MonoW32HandleType type; + gpointer handle_specific; + void (*close_func)(gpointer, gpointer); + + type = handle_data->type; + handle_specific = handle_data->specific; + + mono_os_mutex_lock (&scan_mutex); + + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: Destroying handle %p", __func__, handle); + + /* Destroy the mutex and cond var. We hope nobody + * tried to grab them between the handle unlock and + * now, but pthreads doesn't have a + * "unlock_and_destroy" atomic function. + */ + thr_ret = mono_os_mutex_destroy (&handle_data->signal_mutex); + /*WARNING gross hack to make cleanup not crash when exiting without the whole runtime teardown.*/ + if (thr_ret == EBUSY && ignore_private_busy_handles) { + early_exit = TRUE; + } else { + if (thr_ret != 0) + g_error ("Error destroying handle %p mutex due to %d\n", handle, thr_ret); + + thr_ret = mono_os_cond_destroy (&handle_data->signal_cond); + if (thr_ret == EBUSY && ignore_private_busy_handles) + early_exit = TRUE; + else if (thr_ret != 0) + g_error ("Error destroying handle %p cond var due to %d\n", handle, thr_ret); + } + + memset (handle_data, 0, sizeof (MonoW32HandleBase)); + + mono_os_mutex_unlock (&scan_mutex); + + if (early_exit) + return; + + close_func = _wapi_handle_ops_get_close_func (type); + if (close_func != NULL) { + close_func (handle, handle_specific); + } + + g_free (handle_specific); + } +} + +void mono_w32handle_unref (gpointer handle) +{ + mono_w32handle_unref_full (handle, FALSE); +} + +void +mono_w32handle_register_ops (MonoW32HandleType type, MonoW32HandleOps *ops) +{ + handle_ops [type] = ops; +} + +void mono_w32handle_register_capabilities (MonoW32HandleType type, + MonoW32HandleCapability caps) +{ + handle_caps[type] = caps; +} + +gboolean mono_w32handle_test_capabilities (gpointer handle, + MonoW32HandleCapability caps) +{ + MonoW32HandleBase *handle_data; + MonoW32HandleType type; + + if (!mono_w32handle_lookup_data (handle, &handle_data)) { + return(FALSE); + } + + type = handle_data->type; + + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: testing 0x%x against 0x%x (%d)", __func__, + handle_caps[type], caps, handle_caps[type] & caps); + + return((handle_caps[type] & caps) != 0); +} + +static void (*_wapi_handle_ops_get_close_func (MonoW32HandleType type))(gpointer, gpointer) +{ + if (handle_ops[type] != NULL && + handle_ops[type]->close != NULL) { + return (handle_ops[type]->close); + } + + return (NULL); +} + +void mono_w32handle_ops_close (gpointer handle, gpointer data) +{ + MonoW32HandleBase *handle_data; + MonoW32HandleType type; + + if (!mono_w32handle_lookup_data (handle, &handle_data)) { + return; + } + + type = handle_data->type; + + if (handle_ops[type] != NULL && + handle_ops[type]->close != NULL) { + handle_ops[type]->close (handle, data); + } +} + +void mono_w32handle_ops_details (MonoW32HandleType type, gpointer data) +{ + if (handle_ops[type] != NULL && + handle_ops[type]->details != NULL) { + handle_ops[type]->details (data); + } +} + +const gchar* mono_w32handle_ops_typename (MonoW32HandleType type) +{ + g_assert (handle_ops [type]); + g_assert (handle_ops [type]->typename); + return handle_ops [type]->typename (); +} + +gsize mono_w32handle_ops_typesize (MonoW32HandleType type) +{ + g_assert (handle_ops [type]); + g_assert (handle_ops [type]->typesize); + return handle_ops [type]->typesize (); +} + +void mono_w32handle_ops_signal (gpointer handle) +{ + MonoW32HandleBase *handle_data; + MonoW32HandleType type; + + if (!mono_w32handle_lookup_data (handle, &handle_data)) { + return; + } + + type = handle_data->type; + + if (handle_ops[type] != NULL && handle_ops[type]->signal != NULL) { + handle_ops[type]->signal (handle); + } +} + +gboolean mono_w32handle_ops_own (gpointer handle) +{ + MonoW32HandleBase *handle_data; + MonoW32HandleType type; + + if (!mono_w32handle_lookup_data (handle, &handle_data)) { + return(FALSE); + } + + type = handle_data->type; + + if (handle_ops[type] != NULL && handle_ops[type]->own_handle != NULL) { + return(handle_ops[type]->own_handle (handle)); + } else { + return(FALSE); + } +} + +gboolean mono_w32handle_ops_isowned (gpointer handle) +{ + MonoW32HandleBase *handle_data; + MonoW32HandleType type; + + if (!mono_w32handle_lookup_data (handle, &handle_data)) { + return(FALSE); + } + + type = handle_data->type; + + if (handle_ops[type] != NULL && handle_ops[type]->is_owned != NULL) { + return(handle_ops[type]->is_owned (handle)); + } else { + return(FALSE); + } +} + +guint32 mono_w32handle_ops_specialwait (gpointer handle, guint32 timeout, gboolean *alerted) +{ + MonoW32HandleBase *handle_data; + MonoW32HandleType type; + + if (!mono_w32handle_lookup_data (handle, &handle_data)) { + return(WAIT_FAILED); + } + + type = handle_data->type; + + if (handle_ops[type] != NULL && + handle_ops[type]->special_wait != NULL) { + return(handle_ops[type]->special_wait (handle, timeout, alerted)); + } else { + return(WAIT_FAILED); + } +} + +void mono_w32handle_ops_prewait (gpointer handle) +{ + MonoW32HandleBase *handle_data; + MonoW32HandleType type; + + if (!mono_w32handle_lookup_data (handle, &handle_data)) { + return; + } + + type = handle_data->type; + + if (handle_ops[type] != NULL && + handle_ops[type]->prewait != NULL) { + handle_ops[type]->prewait (handle); + } +} + +static void +spin (guint32 ms) +{ + struct timespec sleepytime; + + g_assert (ms < 1000); + + sleepytime.tv_sec = 0; + sleepytime.tv_nsec = ms * 1000000; + nanosleep (&sleepytime, NULL); +} + +static void +mono_w32handle_lock_handles (gpointer *handles, gsize numhandles) +{ + guint32 i, iter=0; + int thr_ret; + + /* Lock all the handles, with backoff */ +again: + for(i=0; isignal_cond; + mutex = &handle_data->signal_mutex; + + mono_os_mutex_lock (mutex); + mono_os_cond_broadcast (cond); + mono_os_mutex_unlock (mutex); + + mono_w32handle_unref (handle); +} + +static int +mono_w32handle_timedwait_signal_handle (gpointer handle, guint32 timeout, gboolean poll, gboolean *alerted) +{ + MonoW32HandleBase *handle_data; + int res; + + if (!mono_w32handle_lookup_data (handle, &handle_data)) + g_error ("cannot wait on unknown handle %p", handle); + + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: waiting for %p (type %s)", __func__, handle, + mono_w32handle_ops_typename (mono_w32handle_get_type (handle))); + + if (alerted) + *alerted = FALSE; + + if (alerted) { + mono_thread_info_install_interrupt (signal_handle_and_unref, handle, alerted); + if (*alerted) + return 0; + mono_w32handle_ref (handle); + } + + res = mono_w32handle_timedwait_signal_naked (&handle_data->signal_cond, &handle_data->signal_mutex, timeout, poll, alerted); + + if (alerted) { + mono_thread_info_uninstall_interrupt (alerted); + if (!*alerted) { + /* if it is alerted, then the handle is unref in the interrupt callback */ + mono_w32handle_unref (handle); + } + } + + return res; +} + +void mono_w32handle_dump (void) +{ + MonoW32HandleBase *handle_data; + guint32 i, k; + + mono_os_mutex_lock (&scan_mutex); + + for(i = SLOT_INDEX (0); i < private_handles_slots_count; i++) { + if (private_handles [i]) { + for (k = SLOT_OFFSET (0); k < HANDLE_PER_SLOT; k++) { + handle_data = &private_handles [i][k]; + + if (handle_data->type == MONO_W32HANDLE_UNUSED) { + continue; + } + + g_print ("%3x [%7s] %s %d ", + i * HANDLE_PER_SLOT + k, + mono_w32handle_ops_typename (handle_data->type), + handle_data->signalled?"Sg":"Un", + handle_data->ref); + mono_w32handle_ops_details (handle_data->type, handle_data->specific); + g_print ("\n"); + } + } + } + + mono_os_mutex_unlock (&scan_mutex); +} + +static gboolean +own_if_signalled (gpointer handle) +{ + if (!mono_w32handle_issignalled (handle)) + return FALSE; + + mono_w32handle_ops_own (handle); + return TRUE; +} + +static gboolean +own_if_owned( gpointer handle) +{ + if (!mono_w32handle_ops_isowned (handle)) + return FALSE; + + mono_w32handle_ops_own (handle); + return TRUE; +} + +MonoW32HandleWaitRet +mono_w32handle_wait_one (gpointer handle, guint32 timeout, gboolean alertable) +{ + MonoW32HandleWaitRet ret; + gboolean alerted; + gint64 start; + gint thr_ret; + + alerted = FALSE; + + if (mono_w32handle_test_capabilities (handle, MONO_W32HANDLE_CAP_SPECIAL_WAIT)) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: handle %p has special wait", + __func__, handle); + + switch (mono_w32handle_ops_specialwait (handle, timeout, alertable ? &alerted : NULL)) { + case WAIT_OBJECT_0: + ret = MONO_W32HANDLE_WAIT_RET_SUCCESS_0; + break; + case WAIT_IO_COMPLETION: + ret = MONO_W32HANDLE_WAIT_RET_ALERTED; + break; + case WAIT_TIMEOUT: + ret = MONO_W32HANDLE_WAIT_RET_TIMEOUT; + break; + case WAIT_FAILED: + ret = MONO_W32HANDLE_WAIT_RET_FAILED; + break; + default: + g_assert_not_reached (); + } + + if (alerted) + ret = MONO_W32HANDLE_WAIT_RET_ALERTED; + + return ret; + } + + if (!mono_w32handle_test_capabilities (handle, MONO_W32HANDLE_CAP_WAIT)) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: handle %p can't be waited for", + __func__, handle); + + return MONO_W32HANDLE_WAIT_RET_FAILED; + } + + thr_ret = mono_w32handle_lock_handle (handle); + g_assert (thr_ret == 0); + + if (mono_w32handle_test_capabilities (handle, MONO_W32HANDLE_CAP_OWN)) { + if (own_if_owned (handle)) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: handle %p already owned", + __func__, handle); + + ret = MONO_W32HANDLE_WAIT_RET_SUCCESS_0; + goto done; + } + } + + if (timeout != INFINITE) + start = mono_msec_ticks (); + + for (;;) { + gint waited; + + if (own_if_signalled (handle)) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: handle %p signalled", + __func__, handle); + + ret = MONO_W32HANDLE_WAIT_RET_SUCCESS_0; + goto done; + } + + mono_w32handle_ops_prewait (handle); + + if (timeout == INFINITE) { + waited = mono_w32handle_timedwait_signal_handle (handle, INFINITE, FALSE, alertable ? &alerted : NULL); + } else { + gint64 elapsed; + + elapsed = mono_msec_ticks () - start; + if (elapsed > timeout) { + ret = MONO_W32HANDLE_WAIT_RET_TIMEOUT; + goto done; + } + + waited = mono_w32handle_timedwait_signal_handle (handle, timeout - elapsed, FALSE, alertable ? &alerted : NULL); + } + + if (alerted) { + ret = MONO_W32HANDLE_WAIT_RET_ALERTED; + goto done; + } + + if (waited != 0) { + ret = MONO_W32HANDLE_WAIT_RET_TIMEOUT; + goto done; + } + } + +done: + thr_ret = mono_w32handle_unlock_handle (handle); + g_assert (thr_ret == 0); + + return ret; +} + +MonoW32HandleWaitRet +mono_w32handle_wait_multiple (gpointer *handles, gsize nhandles, gboolean waitall, guint32 timeout, gboolean alertable) +{ + MonoW32HandleWaitRet ret; + gboolean alerted, poll; + gint i, thr_ret; + gint64 start; + gpointer handles_sorted [MONO_W32HANDLE_MAXIMUM_WAIT_OBJECTS]; + + if (nhandles == 0) + return MONO_W32HANDLE_WAIT_RET_FAILED; + + if (nhandles == 1) + return mono_w32handle_wait_one (handles [0], timeout, alertable); + + alerted = FALSE; + + if (nhandles > MONO_W32HANDLE_MAXIMUM_WAIT_OBJECTS) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: too many handles: %d", + __func__, nhandles); + + return MONO_W32HANDLE_WAIT_RET_FAILED; + } + + for (i = 0; i < nhandles; ++i) { + if (!mono_w32handle_test_capabilities (handles[i], MONO_W32HANDLE_CAP_WAIT) + && !mono_w32handle_test_capabilities (handles[i], MONO_W32HANDLE_CAP_SPECIAL_WAIT)) + { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: handle %p can't be waited for", + __func__, handles [i]); + + return MONO_W32HANDLE_WAIT_RET_FAILED; + } + + handles_sorted [i] = handles [i]; + } + + qsort (handles_sorted, nhandles, sizeof (gpointer), g_direct_equal); + for (i = 1; i < nhandles; ++i) { + if (handles_sorted [i - 1] == handles_sorted [i]) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: handle %p is duplicated", + __func__, handles_sorted [i]); + + return MONO_W32HANDLE_WAIT_RET_FAILED; + } + } + + poll = FALSE; + for (i = 0; i < nhandles; ++i) { + if (mono_w32handle_get_type (handles [i]) == MONO_W32HANDLE_PROCESS) { + /* Can't wait for a process handle + another handle without polling */ + poll = TRUE; + } + } + + if (timeout != INFINITE) + start = mono_msec_ticks (); + + for (i = 0; i < nhandles; ++i) { + /* Add a reference, as we need to ensure the handle wont + * disappear from under us while we're waiting in the loop + * (not lock, as we don't want exclusive access here) */ + mono_w32handle_ref (handles [i]); + } + + for (;;) { + gsize count, lowest; + gboolean signalled; + gint waited; + + count = 0; + lowest = nhandles; + + mono_w32handle_lock_handles (handles, nhandles); + + for (i = 0; i < nhandles; i++) { + if ((mono_w32handle_test_capabilities (handles [i], MONO_W32HANDLE_CAP_OWN) && mono_w32handle_ops_isowned (handles [i])) + || mono_w32handle_issignalled (handles [i])) + { + count ++; + + if (i < lowest) + lowest = i; + } + } + + signalled = (waitall && count == nhandles) || (!waitall && count > 0); + + if (signalled) { + for (i = 0; i < nhandles; i++) + own_if_signalled (handles [i]); + } + + mono_w32handle_unlock_handles (handles, nhandles); + + if (signalled) { + ret = MONO_W32HANDLE_WAIT_RET_SUCCESS_0 + lowest; + goto done; + } + + for (i = 0; i < nhandles; i++) { + mono_w32handle_ops_prewait (handles[i]); + + if (mono_w32handle_test_capabilities (handles [i], MONO_W32HANDLE_CAP_SPECIAL_WAIT) + && !mono_w32handle_issignalled (handles [i])) + { + mono_w32handle_ops_specialwait (handles [i], 0, alertable ? &alerted : NULL); + } + } + + thr_ret = mono_w32handle_lock_signal_mutex (); + g_assert (thr_ret == 0); + + if (waitall) { + signalled = TRUE; + for (i = 0; i < nhandles; ++i) { + if (!mono_w32handle_issignalled (handles [i])) { + signalled = FALSE; + break; + } + } + } else { + signalled = FALSE; + for (i = 0; i < nhandles; ++i) { + if (mono_w32handle_issignalled (handles [i])) { + signalled = TRUE; + break; + } + } + } + + waited = 0; + + if (!signalled) { + if (timeout == INFINITE) { + waited = mono_w32handle_timedwait_signal (INFINITE, poll, alertable ? &alerted : NULL); + } else { + gint64 elapsed; + + elapsed = mono_msec_ticks () - start; + if (elapsed > timeout) { + ret = MONO_W32HANDLE_WAIT_RET_TIMEOUT; + + thr_ret = mono_w32handle_unlock_signal_mutex (); + g_assert (thr_ret == 0); + + goto done; + } + + waited = mono_w32handle_timedwait_signal (timeout - elapsed, poll, alertable ? &alerted : NULL); + } + } + + thr_ret = mono_w32handle_unlock_signal_mutex (); + g_assert (thr_ret == 0); + + if (alerted) { + ret = MONO_W32HANDLE_WAIT_RET_ALERTED; + goto done; + } + + if (waited != 0) { + ret = MONO_W32HANDLE_WAIT_RET_TIMEOUT; + goto done; + } + } + +done: + for (i = 0; i < nhandles; i++) { + /* Unref everything we reffed above */ + mono_w32handle_unref (handles [i]); + } + + return ret; +} + +MonoW32HandleWaitRet +mono_w32handle_signal_and_wait (gpointer signal_handle, gpointer wait_handle, guint32 timeout, gboolean alertable) +{ + MonoW32HandleWaitRet ret; + gint64 start; + gboolean alerted; + gint thr_ret; + + alerted = FALSE; + + if (!mono_w32handle_test_capabilities (signal_handle, MONO_W32HANDLE_CAP_SIGNAL)) + return MONO_W32HANDLE_WAIT_RET_FAILED; + if (!mono_w32handle_test_capabilities (wait_handle, MONO_W32HANDLE_CAP_WAIT)) + return MONO_W32HANDLE_WAIT_RET_FAILED; + + if (mono_w32handle_test_capabilities (wait_handle, MONO_W32HANDLE_CAP_SPECIAL_WAIT)) { + g_warning ("%s: handle %p has special wait, implement me!!", __func__, wait_handle); + return MONO_W32HANDLE_WAIT_RET_FAILED; + } + + thr_ret = mono_w32handle_lock_handle (wait_handle); + g_assert (thr_ret == 0); + + mono_w32handle_ops_signal (signal_handle); + + if (mono_w32handle_test_capabilities (wait_handle, MONO_W32HANDLE_CAP_OWN)) { + if (own_if_owned (wait_handle)) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: handle %p already owned", + __func__, wait_handle); + + ret = MONO_W32HANDLE_WAIT_RET_SUCCESS_0; + goto done; + } + } + + if (timeout != INFINITE) + start = mono_msec_ticks (); + + for (;;) { + gint waited; + + if (own_if_signalled (wait_handle)) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: handle %p signalled", + __func__, wait_handle); + + ret = MONO_W32HANDLE_WAIT_RET_SUCCESS_0; + goto done; + } + + mono_w32handle_ops_prewait (wait_handle); + + if (timeout == INFINITE) { + waited = mono_w32handle_timedwait_signal_handle (wait_handle, INFINITE, FALSE, alertable ? &alerted : NULL); + } else { + gint64 elapsed; + + elapsed = mono_msec_ticks () - start; + if (elapsed > timeout) { + ret = MONO_W32HANDLE_WAIT_RET_TIMEOUT; + goto done; + } + + waited = mono_w32handle_timedwait_signal_handle (wait_handle, timeout - elapsed, FALSE, alertable ? &alerted : NULL); + } + + if (alerted) { + ret = MONO_W32HANDLE_WAIT_RET_ALERTED; + goto done; + } + + if (waited != 0) { + ret = MONO_W32HANDLE_WAIT_RET_TIMEOUT; + goto done; + } + } + +done: + thr_ret = mono_w32handle_unlock_handle (wait_handle); + g_assert (thr_ret == 0); + + return ret; +} + +#endif /* !defined(HOST_WIN32) */ diff --git a/mono/utils/w32handle.h b/mono/utils/w32handle.h new file mode 100644 index 0000000000..27c403ce39 --- /dev/null +++ b/mono/utils/w32handle.h @@ -0,0 +1,183 @@ + +#ifndef _MONO_UTILS_W32HANDLE_H_ +#define _MONO_UTILS_W32HANDLE_H_ + +#include +#include + +#ifndef INVALID_HANDLE_VALUE +#define INVALID_HANDLE_VALUE (gpointer)-1 +#endif + +#define MONO_W32HANDLE_MAXIMUM_WAIT_OBJECTS 64 + +typedef enum { + MONO_W32HANDLE_UNUSED = 0, + MONO_W32HANDLE_FILE, + MONO_W32HANDLE_CONSOLE, + MONO_W32HANDLE_THREAD, + MONO_W32HANDLE_SEM, + MONO_W32HANDLE_MUTEX, + MONO_W32HANDLE_EVENT, + MONO_W32HANDLE_SOCKET, + MONO_W32HANDLE_FIND, + MONO_W32HANDLE_PROCESS, + MONO_W32HANDLE_PIPE, + MONO_W32HANDLE_NAMEDMUTEX, + MONO_W32HANDLE_NAMEDSEM, + MONO_W32HANDLE_NAMEDEVENT, + MONO_W32HANDLE_COUNT +} MonoW32HandleType; + +typedef struct +{ + void (*close)(gpointer handle, gpointer data); + + /* SignalObjectAndWait */ + void (*signal)(gpointer signal); + + /* Called by WaitForSingleObject and WaitForMultipleObjects, + * with the handle locked (shared handles aren't locked.) + * Returns TRUE if ownership was established, false otherwise. + */ + gboolean (*own_handle)(gpointer handle); + + /* Called by WaitForSingleObject and WaitForMultipleObjects, if the + * handle in question is "ownable" (ie mutexes), to see if the current + * thread already owns this handle + */ + gboolean (*is_owned)(gpointer handle); + + /* Called by WaitForSingleObject and WaitForMultipleObjects, + * if the handle in question needs a special wait function + * instead of using the normal handle signal mechanism. + * Returns the WaitForSingleObject return code. + */ + guint32 (*special_wait)(gpointer handle, guint32 timeout, gboolean *alerted); + + /* Called by WaitForSingleObject and WaitForMultipleObjects, + * if the handle in question needs some preprocessing before the + * signal wait. + */ + void (*prewait)(gpointer handle); + + /* Called when dumping the handles */ + void (*details)(gpointer data); + + /* Called to get the name of the handle type */ + const gchar* (*typename) (void); + + /* Called to get the size of the handle type */ + gsize (*typesize) (void); +} MonoW32HandleOps; + +typedef enum { + MONO_W32HANDLE_CAP_WAIT = 0x01, + MONO_W32HANDLE_CAP_SIGNAL = 0x02, + MONO_W32HANDLE_CAP_OWN = 0x04, + MONO_W32HANDLE_CAP_SPECIAL_WAIT = 0x08, +} MonoW32HandleCapability; + +extern guint32 mono_w32handle_fd_reserve; + +void +mono_w32handle_init (void); + +void +mono_w32handle_cleanup (void); + +void +mono_w32handle_register_ops (MonoW32HandleType type, MonoW32HandleOps *ops); + +gpointer +mono_w32handle_new (MonoW32HandleType type, gpointer handle_specific); + +gpointer +mono_w32handle_new_fd (MonoW32HandleType type, int fd, gpointer handle_specific); + +MonoW32HandleType +mono_w32handle_get_type (gpointer handle); + +gboolean +mono_w32handle_lookup (gpointer handle, MonoW32HandleType type, gpointer *handle_specific); + +gpointer +mono_w32handle_search (MonoW32HandleType type, gboolean (*check)(gpointer, gpointer), gpointer user_data, gpointer *handle_specific, gboolean search_shared); + +void +mono_w32handle_foreach (gboolean (*on_each)(gpointer handle, gpointer data, gpointer user_data), gpointer user_data); + +void +mono_w32handle_dump (void); + +void +mono_w32handle_ref (gpointer handle); + +void +mono_w32handle_unref (gpointer handle); + +void +mono_w32handle_register_capabilities (MonoW32HandleType type, MonoW32HandleCapability caps); + +gboolean +mono_w32handle_test_capabilities (gpointer handle, MonoW32HandleCapability caps); + +void +mono_w32handle_ops_close (gpointer handle, gpointer data); + +void +mono_w32handle_ops_signal (gpointer handle); + +gboolean +mono_w32handle_ops_own (gpointer handle); + +gboolean +mono_w32handle_ops_isowned (gpointer handle); + +guint32 +mono_w32handle_ops_specialwait (gpointer handle, guint32 timeout, gboolean *alerted); + +void +mono_w32handle_ops_prewait (gpointer handle); + +void +mono_w32handle_ops_details (MonoW32HandleType type, gpointer data); + +const gchar* +mono_w32handle_ops_typename (MonoW32HandleType type); + +gsize +mono_w32handle_ops_typesize (MonoW32HandleType type); + +void +mono_w32handle_set_signal_state (gpointer handle, gboolean state, gboolean broadcast); + +gboolean +mono_w32handle_issignalled (gpointer handle); + +int +mono_w32handle_lock_handle (gpointer handle); + +int +mono_w32handle_trylock_handle (gpointer handle); + +int +mono_w32handle_unlock_handle (gpointer handle); + +typedef enum { + MONO_W32HANDLE_WAIT_RET_SUCCESS_0 = 0, + MONO_W32HANDLE_WAIT_RET_ALERTED = -1, + MONO_W32HANDLE_WAIT_RET_TIMEOUT = -2, + MONO_W32HANDLE_WAIT_RET_FAILED = -3, +} MonoW32HandleWaitRet; + +MonoW32HandleWaitRet +mono_w32handle_wait_one (gpointer handle, guint32 timeout, gboolean alertable); + +MonoW32HandleWaitRet +mono_w32handle_wait_multiple (gpointer *handles, gsize nhandles, gboolean waitall, guint32 timeout, gboolean alertable); + +MonoW32HandleWaitRet +mono_w32handle_signal_and_wait (gpointer signal_handle, gpointer wait_handle, guint32 timeout, gboolean alertable); + +#endif /* _MONO_UTILS_W32HANDLE_H_ */ diff --git a/msvc/Makefile.in b/msvc/Makefile.in index fe49b7fbf7..b477b66814 100644 --- a/msvc/Makefile.in +++ b/msvc/Makefile.in @@ -120,6 +120,8 @@ DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AOT_BUILD_FLAGS = @AOT_BUILD_FLAGS@ +AOT_RUN_FLAGS = @AOT_RUN_FLAGS@ API_VER = @API_VER@ AR = @AR@ AS = @AS@ @@ -128,6 +130,11 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOEHM_DEFINES = @BOEHM_DEFINES@ +BTLS_ARCH = @BTLS_ARCH@ +BTLS_CFLAGS = @BTLS_CFLAGS@ +BTLS_CMAKE_ARGS = @BTLS_CMAKE_ARGS@ +BTLS_PLATFORM = @BTLS_PLATFORM@ +BTLS_ROOT = @BTLS_ROOT@ BUILD_EXEEXT = @BUILD_EXEEXT@ CC = @CC@ CCAS = @CCAS@ @@ -137,6 +144,7 @@ CCDEPMODE = @CCDEPMODE@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMAKE = @CMAKE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ @@ -157,7 +165,6 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_PERF_EVENTS = @ENABLE_PERF_EVENTS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDKX11 = @GDKX11@ @@ -172,10 +179,12 @@ HAVE_MSGFMT = @HAVE_MSGFMT@ HOST_CC = @HOST_CC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MOBILE_STATIC = @INSTALL_MOBILE_STATIC@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTL = @INTL@ +INVARIANT_AOT_OPTIONS = @INVARIANT_AOT_OPTIONS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBC = @LIBC@ @@ -222,6 +231,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ +PLATFORM_AOT_SUFFIX = @PLATFORM_AOT_SUFFIX@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -231,6 +241,7 @@ SHELL = @SHELL@ SQLITE = @SQLITE@ SQLITE3 = @SQLITE3@ STRIP = @STRIP@ +TEST_PROFILE = @TEST_PROFILE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VTUNE_CFLAGS = @VTUNE_CFLAGS@ diff --git a/msvc/build-all.vcxproj b/msvc/build-all.vcxproj new file mode 100644 index 0000000000..0626d25ff5 --- /dev/null +++ b/msvc/build-all.vcxproj @@ -0,0 +1,155 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {5362490B-8516-44EE-9987-014C015A080A} + buildall + 8.1 + + + + Utility + true + v140 + MultiByte + + + Utility + false + v140 + true + MultiByte + + + Utility + true + v140 + MultiByte + + + Utility + false + v140 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + + + + + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ + + + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ + + + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ + + + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ + + + + Level3 + Disabled + true + + + + + + + + + Level3 + Disabled + true + + + + + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + + + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + + + + + + + {92ae7622-5f58-4234-9a26-9ec71876b3f4} + + + + + + \ No newline at end of file diff --git a/msvc/build-init.vcxproj b/msvc/build-init.vcxproj new file mode 100644 index 0000000000..ee690bc78c --- /dev/null +++ b/msvc/build-init.vcxproj @@ -0,0 +1,148 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {92AE7622-5F58-4234-9A26-9EC71876B3F4} + buildinit + 8.1 + + + + Utility + true + v140 + MultiByte + + + Utility + false + v140 + true + MultiByte + + + Utility + true + v140 + MultiByte + + + Utility + false + v140 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + + + + + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ + + + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ + + + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ + + + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ + + + + Level3 + Disabled + true + + + winsetup.bat + + + + + Level3 + Disabled + true + + + winsetup.bat + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + winsetup.bat + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + winsetup.bat + + + + + + + + \ No newline at end of file diff --git a/msvc/build-install.vcxproj b/msvc/build-install.vcxproj new file mode 100644 index 0000000000..a50201f207 --- /dev/null +++ b/msvc/build-install.vcxproj @@ -0,0 +1,151 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {A9DC644B-9171-4FCD-BF21-2CC6D055FC40} + buildinstall + 8.1 + + + + Utility + true + v140 + MultiByte + + + Utility + false + v140 + true + MultiByte + + + Utility + true + v140 + MultiByte + + + Utility + false + v140 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + + + + + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ + + + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ + + + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ + + + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ + + + + Level3 + Disabled + true + + + .\install.bat $(Platform) $(Configuration) "$(MONO_BUILD_DIR_PREFIX)" "$(MONO_INSTALL_DIR_PREFIX)" -q + + + + + Level3 + Disabled + true + + + .\install.bat $(Platform) $(Configuration) "$(MONO_BUILD_DIR_PREFIX)" "$(MONO_INSTALL_DIR_PREFIX)" -q + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + .\install.bat $(Platform) $(Configuration) "$(MONO_BUILD_DIR_PREFIX)" "$(MONO_INSTALL_DIR_PREFIX)" -q + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + .\install.bat $(Platform) $(Configuration) "$(MONO_BUILD_DIR_PREFIX)" "$(MONO_INSTALL_DIR_PREFIX)" -q + + + + + {b6e563b8-7f57-4f7f-9439-f2405d4e2522} + + + + + + \ No newline at end of file diff --git a/msvc/build-package.vcxproj b/msvc/build-package.vcxproj new file mode 100644 index 0000000000..b4f6dab414 --- /dev/null +++ b/msvc/build-package.vcxproj @@ -0,0 +1,151 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {B6E563B8-7F57-4F7F-9439-F2405D4E2522} + buildpackage + 8.1 + + + + Utility + true + v140 + MultiByte + + + Utility + false + v140 + true + MultiByte + + + Utility + true + v140 + MultiByte + + + Utility + false + v140 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + + + + + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ + + + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ + + + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ + + + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ + + + + Level3 + Disabled + true + + + .\package.bat $(Platform) $(Configuration) "$(MONO_BUILD_DIR_PREFIX)" -q + + + + + Level3 + Disabled + true + + + .\package.bat $(Platform) $(Configuration) "$(MONO_BUILD_DIR_PREFIX)" -q + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + .\package.bat $(Platform) $(Configuration) "$(MONO_BUILD_DIR_PREFIX)" -q + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + .\package.bat $(Platform) $(Configuration) "$(MONO_BUILD_DIR_PREFIX)" -q + + + + + {5362490b-8516-44ee-9987-014c015a080a} + + + + + + \ No newline at end of file diff --git a/msvc/create-windef.pl b/msvc/create-windef.pl index 129314ca64..7d588b915d 100755 --- a/msvc/create-windef.pl +++ b/msvc/create-windef.pl @@ -30,7 +30,7 @@ push @symbols, "MonoFixupCorEE"; open (OUT, ">$outfile") || die "Cannot open '$outfile': $!\n"; print OUT "; file generated by create-windef.pl\n"; -print OUT "LIBRARY $dllname\nEXPORTS\n"; +print OUT "EXPORTS\n"; print OUT join ("\n", @symbols); print OUT "\n"; diff --git a/msvc/eglib.vcxproj b/msvc/eglib.vcxproj index b3d0229f79..94a7127d73 100644 --- a/msvc/eglib.vcxproj +++ b/msvc/eglib.vcxproj @@ -1,14 +1,6 @@ - - + + - - Debug - Win32 - - - Debug - x64 - Debug Win32 @@ -17,14 +9,6 @@ Debug x64 - - Release - Win32 - - - Release - x64 - Release Win32 @@ -38,233 +22,134 @@ {158073ED-99AE-4196-9EDC-DDB2344F8466} eglib Win32Proj + 8.1 StaticLibrary Unicode - v120 - - - StaticLibrary - Unicode - v120 + v140 StaticLibrary Unicode - v120 - - - StaticLibrary - Unicode - v120 + v140 StaticLibrary Unicode - v120 - - - StaticLibrary - Unicode - v120 + v140 StaticLibrary Unicode - v120 - - - StaticLibrary - Unicode - v120 + v140 - - - + - - - + - - - + - - - + <_ProjectFileVersion>10.0.30319.1 - $(Platform)\lib\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ - $(Platform)\lib\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ - $(Platform)\lib\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ - $(Platform)\lib\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ - $(Platform)\lib\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ - $(Platform)\lib\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ - $(Platform)\lib\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ - $(Platform)\lib\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ - winsetup.bat + + Disabled - ../eglib/src;../eglib;%(AdditionalIncludeDirectories) + $(MONO_EGLIB_SOURCE_DIR);$(MONO_EGLIB_INCLUDE_DIR);%(AdditionalIncludeDirectories) true EnableFastChecks - MultiThreadedDebugDLL Level4 - EditAndContinue - - - - - winsetup.bat - - - Disabled - ../eglib/src;../eglib;%(AdditionalIncludeDirectories) - true - EnableFastChecks - MultiThreadedDebugDLL - - - Level4 - EditAndContinue + ProgramDatabase + WIN32;WIN32_LEAN_AND_MEAN;_DEBUG;_LIB;%(PreprocessorDefinitions) + $(IntDir)$(TargetName).pdb - winsetup.bat + + MinSpace - ../eglib/src;../eglib;%(AdditionalIncludeDirectories) - MultiThreadedDLL - - - Level4 - ProgramDatabase - - - - - winsetup.bat - - - MinSpace - ../eglib/src;../eglib;%(AdditionalIncludeDirectories) - MultiThreadedDLL + $(MONO_EGLIB_SOURCE_DIR);$(MONO_EGLIB_INCLUDE_DIR);%(AdditionalIncludeDirectories) Level4 ProgramDatabase + WIN32;WIN32_LEAN_AND_MEAN;NDEBUG;_LIB;%(PreprocessorDefinitions) + $(IntDir)$(TargetName).pdb - winsetup.bat + + X64 Disabled - ../eglib/src;../eglib;%(AdditionalIncludeDirectories) + $(MONO_EGLIB_SOURCE_DIR);$(MONO_EGLIB_INCLUDE_DIR);%(AdditionalIncludeDirectories) true EnableFastChecks - MultiThreadedDebugDLL - - - Level4 - ProgramDatabase - - - - - winsetup.bat - - - X64 - - - Disabled - ../eglib/src;../eglib;%(AdditionalIncludeDirectories) - true - EnableFastChecks - MultiThreadedDebugDLL Level4 ProgramDatabase + WIN32;WIN32_LEAN_AND_MEAN;_DEBUG;_LIB;%(PreprocessorDefinitions) + $(IntDir)$(TargetName).pdb - winsetup.bat + + X64 MinSpace - ../eglib/src;../eglib;%(AdditionalIncludeDirectories) - MultiThreadedDLL + $(MONO_EGLIB_SOURCE_DIR);$(MONO_EGLIB_INCLUDE_DIR);%(AdditionalIncludeDirectories) Level4 ProgramDatabase + WIN32;WIN32_LEAN_AND_MEAN;NDEBUG;_LIB;%(PreprocessorDefinitions) + $(IntDir)$(TargetName).pdb - - - winsetup.bat - - - X64 - - - MinSpace - ../eglib/src;../eglib;%(AdditionalIncludeDirectories) - MultiThreadedDLL - - - Level4 - ProgramDatabase - - - - - - - - @@ -295,14 +180,18 @@ - + + + {92ae7622-5f58-4234-9a26-9ec71876b3f4} + + - \ No newline at end of file + diff --git a/msvc/genmdesc.vcxproj b/msvc/genmdesc.vcxproj index 001463f7af..7183d6f4a8 100644 --- a/msvc/genmdesc.vcxproj +++ b/msvc/genmdesc.vcxproj @@ -1,14 +1,6 @@  - + - - Debug - Win32 - - - Debug - x64 - Debug Win32 @@ -17,14 +9,6 @@ Debug x64 - - Release - Win32 - - - Release - x64 - Release Win32 @@ -34,106 +18,72 @@ x64 - {B7098DFA-31E6-4006-8A15-1C9A4E925149} genmdesc + 8.1 Application false Unicode - v120 - - - Application - false - Unicode - v120 + v140 Application false Unicode - v120 - - - Application - false - Unicode - v120 + v140 Application false Unicode - v120 - - - Application - false - Unicode - v120 + v140 Application false Unicode - v120 - - - Application - false - Unicode - v120 + v140 - - - + - - - + - - - + - - - + <_ProjectFileVersion>10.0.30319.1 - $(Platform)\bin\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ - $(Platform)\bin\ - $(Platform)\obj\$(ProjectName)\ - $(Platform)\bin\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ - $(Platform)\bin\ - $(Platform)\obj\$(ProjectName)\ - $(Platform)\bin\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ - $(Platform)\bin\ - $(Platform)\obj\$(ProjectName)\ - $(Platform)\bin\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ - $(Platform)\bin\ - $(Platform)\obj\$(ProjectName)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ + + + true + + + true @@ -147,16 +97,15 @@ Disabled - ..\libgc\include;..\;..\mono\;..\eglib\src;%(AdditionalIncludeDirectories) + $(MONO_DIR);$(MONO_INCLUDE_DIR);$(MONO_LIBGC_INCLUDE_DIR);$(MONO_EGLIB_SOURCE_DIR);%(AdditionalIncludeDirectories) _DEBUG;_CRT_SECURE_NO_DEPRECATE;_CONSOLE;%(PreprocessorDefinitions) true EnableFastChecks - MultiThreadedDebugDLL Level3 true - EditAndContinue + ProgramDatabase CompileAsC @@ -167,52 +116,9 @@ false - %(AdditionalDependencies) + eglib.lib;%(AdditionalDependencies) true - $(Platform)\lib;%(AdditionalLibraryDirectories) - true - Console - MachineX86 - - - runmdesc.bat "$(TargetPath)" $(Platform) - - - - - - - - - .\./VSDependancies/genmdesc___Win32_Debug/genmdesc.tlb - - - - - Disabled - ..\libgc\include;..\;..\mono\;..\eglib\src;%(AdditionalIncludeDirectories) - _DEBUG;_CRT_SECURE_NO_DEPRECATE;_CONSOLE;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebugDLL - - - Level3 - true - EditAndContinue - CompileAsC - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - - false - - - eglib.lib;libmonoutils.lib;%(AdditionalDependencies) - true - $(Platform)\lib;%(AdditionalLibraryDirectories) + %(AdditionalLibraryDirectories) true Console MachineX86 @@ -234,11 +140,10 @@ Disabled - ..\libgc\include;..\;..\mono\;..\eglib\src;%(AdditionalIncludeDirectories) + $(MONO_DIR);$(MONO_INCLUDE_DIR);$(MONO_LIBGC_INCLUDE_DIR);$(MONO_EGLIB_SOURCE_DIR);%(AdditionalIncludeDirectories) _DEBUG;__x86_64__;TARGET_AMD64;WIN64;_WIN64;WIN32;_WIN32;__WIN32__;_WINDOWS;WINDOWS;HOST_WIN32;TARGET_WIN32;_CRT_SECURE_NO_DEPRECATE;_CONSOLE;HAVE_CONFIG_H;WINVER=0x0600;_WIN32_WINNT=0x0600;_WIN32_IE=0x0501;WIN32_THREADS;FD_SETSIZE=1024;%(PreprocessorDefinitions) true EnableFastChecks - MultiThreadedDebugDLL Level3 @@ -254,53 +159,9 @@ false - %(AdditionalDependencies) + eglib.lib;%(AdditionalDependencies) true - $(Platform)\lib;%(AdditionalLibraryDirectories) - true - Console - MachineX64 - - - runmdesc.bat "$(TargetPath)" $(Platform) - - - - - - - - - X64 - .\./VSDependancies/genmdesc___Win32_Debug/genmdesc.tlb - - - - - Disabled - ..\libgc\include;..\;..\mono\;..\eglib\src;%(AdditionalIncludeDirectories) - _DEBUG;__x86_64__;TARGET_AMD64;WIN64;_WIN64;WIN32;_WIN32;__WIN32__;_WINDOWS;WINDOWS;HOST_WIN32;TARGET_WIN32;_CRT_SECURE_NO_DEPRECATE;_CONSOLE;HAVE_CONFIG_H;WINVER=0x0600;_WIN32_WINNT=0x0600;_WIN32_IE=0x0501;WIN32_THREADS;FD_SETSIZE=1024;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebugDLL - - - Level3 - true - ProgramDatabase - CompileAsC - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - - false - - - eglib.lib;libmonoutils.lib;%(AdditionalDependencies) - true - $(Platform)\lib;%(AdditionalLibraryDirectories) + %(AdditionalLibraryDirectories) true Console MachineX64 @@ -322,10 +183,9 @@ MinSpace OnlyExplicitInline - ..\libgc\include;..\;..\mono\;..\eglib\src;%(AdditionalIncludeDirectories) + $(MONO_DIR);$(MONO_INCLUDE_DIR);$(MONO_LIBGC_INCLUDE_DIR);$(MONO_EGLIB_SOURCE_DIR);%(AdditionalIncludeDirectories) NDEBUG;_CRT_SECURE_NO_DEPRECATE;_CONSOLE;%(PreprocessorDefinitions) true - MultiThreadedDLL true @@ -340,51 +200,9 @@ false - %(AdditionalDependencies) + eglib.lib;%(AdditionalDependencies) true - $(Platform)\lib;%(AdditionalLibraryDirectories) - Console - MachineX86 - true - - - runmdesc.bat "$(TargetPath)" $(Platform) - - - - - - - - - .\Release/genmdesc.tlb - - - - - MinSpace - OnlyExplicitInline - ..\libgc\include;..\;..\mono\;..\eglib\src;%(AdditionalIncludeDirectories) - NDEBUG;_CRT_SECURE_NO_DEPRECATE;_CONSOLE;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - - - Level3 - true - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - - false - - - eglib.lib;libmonoutils.lib;%(AdditionalDependencies) - true - $(Platform)\lib;%(AdditionalLibraryDirectories) + %(AdditionalLibraryDirectories) Console MachineX86 true @@ -407,10 +225,9 @@ MinSpace OnlyExplicitInline - ..\libgc\include;..\;..\mono\;..\eglib\src;%(AdditionalIncludeDirectories) + $(MONO_DIR);$(MONO_INCLUDE_DIR);$(MONO_LIBGC_INCLUDE_DIR);$(MONO_EGLIB_SOURCE_DIR);%(AdditionalIncludeDirectories) NDEBUG;__x86_64__;TARGET_AMD64;WIN64;_WIN64;WIN32;_WIN32;__WIN32__;_WINDOWS;WINDOWS;HOST_WIN32;TARGET_WIN32;_CRT_SECURE_NO_DEPRECATE;_CONSOLE;HAVE_CONFIG_H;WINVER=0x0600;_WIN32_WINNT=0x0600;_WIN32_IE=0x0501;WIN32_THREADS;FD_SETSIZE=1024;%(PreprocessorDefinitions) true - MultiThreadedDLL true @@ -426,53 +243,9 @@ false - %(AdditionalDependencies) + eglib.lib;%(AdditionalDependencies) true - $(Platform)\lib;%(AdditionalLibraryDirectories) - Console - MachineX64 - true - - - runmdesc.bat "$(TargetPath)" $(Platform) - - - - - - - - - X64 - .\Release/genmdesc.tlb - - - - - MinSpace - OnlyExplicitInline - ..\libgc\include;..\;..\mono\;..\eglib\src;%(AdditionalIncludeDirectories) - NDEBUG;__x86_64__;TARGET_AMD64;WIN64;_WIN64;WIN32;_WIN32;__WIN32__;_WINDOWS;WINDOWS;HOST_WIN32;TARGET_WIN32;_CRT_SECURE_NO_DEPRECATE;_CONSOLE;HAVE_CONFIG_H;WINVER=0x0600;_WIN32_WINNT=0x0600;_WIN32_IE=0x0501;WIN32_THREADS;FD_SETSIZE=1024;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - - - Level3 - true - CompileAsC - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - - false - - - eglib.lib;libmonoutils.lib;%(AdditionalDependencies) - true - $(Platform)\lib;%(AdditionalLibraryDirectories) + %(AdditionalLibraryDirectories) Console MachineX64 true @@ -488,37 +261,19 @@ true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - true %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - true %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - %(AdditionalIncludeDirectories) @@ -526,37 +281,19 @@ true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - true %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - true %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - %(AdditionalIncludeDirectories) @@ -564,37 +301,19 @@ true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - true %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - true %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - %(AdditionalIncludeDirectories) @@ -602,47 +321,24 @@ true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - true %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - true %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - {158073ed-99ae-4196-9edc-ddb2344f8466} - false - true - false - true - false diff --git a/msvc/libgc.vcxproj b/msvc/libgc.vcxproj index 2be0904f02..6999c3536b 100644 --- a/msvc/libgc.vcxproj +++ b/msvc/libgc.vcxproj @@ -1,14 +1,6 @@  - + - - Debug - Win32 - - - Debug - x64 - Debug Win32 @@ -17,14 +9,6 @@ Debug x64 - - Release - Win32 - - - Release - x64 - Release Win32 @@ -38,167 +22,92 @@ {EB56000B-C80B-4E8B-908D-D84D31B517D3} libgc Win32Proj + 8.1 StaticLibrary Unicode - v120 - - - StaticLibrary - Unicode - v120 + v140 StaticLibrary Unicode - v120 - - - StaticLibrary - Unicode - v120 + v140 StaticLibrary Unicode - v120 - - - StaticLibrary - Unicode - v120 + v140 StaticLibrary Unicode - v120 - - - StaticLibrary - Unicode - v120 + v140 - - - + - - - + - - - + - - - + <_ProjectFileVersion>10.0.30319.1 - $(Platform)\lib\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ - $(Platform)\lib\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ - $(Platform)\lib\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ - $(Platform)\lib\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ - $(Platform)\lib\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ - $(Platform)\lib\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ - $(Platform)\lib\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ - $(Platform)\lib\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ Disabled - ..\libgc\include;%(AdditionalIncludeDirectories) + $(MONO_LIBGC_INCLUDE_DIR);%(AdditionalIncludeDirectories) _DEBUG;__i386__;TARGET_X86;i386;WIN32;_WIN32;__WIN32__;_WINDOWS;WINDOWS;HOST_WIN32;TARGET_WIN32;_CRT_SECURE_NO_DEPRECATE;__STDC__;PACKAGE_NAME="libgc-mono";PACKAGE_TARNAME="libgc-mono";PACKAGE_VERSION="6.6";PACKAGE_STRING="libgc-mono 6.6";PACKAGE_BUGREPORT="Hans_Boehm%40hp.com";GC_WIN32_THREADS=1;NO_GETENV=1;GC_INSIDE_DLL=1;GC_NOT_DLL=1;STDC_HEADERS=1;HAVE_SYS_TYPES_H=1;HAVE_SYS_STAT_H=1;HAVE_STDLIB_H=1;HAVE_STRING_H=1;HAVE_MEMORY_H=1;HAVE_STRINGS_H=1;HAVE_INTTYPES_H=1;HAVE_STDINT_H=1;HAVE_UNISTD_H=1;SILENT=1;NO_SIGNALS=1;NO_EXECUTE_PERMISSION=1;JAVA_FINALIZATION=1;GC_GCJ_SUPPORT=1;ATOMIC_UNCOLLECTABLE=1;_IN_LIBGC=1;WINVER=0x0600;_WIN32_WINNT=0x0600;_WIN32_IE=0x0501;WIN32_THREADS;FD_SETSIZE=1024;%(PreprocessorDefinitions) true EnableFastChecks - MultiThreadedDebugDLL - true - $(OutDir)vc80.pdb ProgramDatabase CompileAsC 4311;4312;4996;4005;%(DisableSpecificWarnings) + Level1 + $(IntDir)$(TargetName).pdb - $(OutDir)libgc.lib - - - - - Disabled - ..\libgc\include;%(AdditionalIncludeDirectories) - _DEBUG;__i386__;TARGET_X86;i386;WIN32;_WIN32;__WIN32__;_WINDOWS;WINDOWS;HOST_WIN32;TARGET_WIN32;_CRT_SECURE_NO_DEPRECATE;__STDC__;PACKAGE_NAME="libgc-mono";PACKAGE_TARNAME="libgc-mono";PACKAGE_VERSION="6.6";PACKAGE_STRING="libgc-mono 6.6";PACKAGE_BUGREPORT="Hans_Boehm%40hp.com";GC_WIN32_THREADS=1;NO_GETENV=1;GC_INSIDE_DLL=1;GC_NOT_DLL=1;STDC_HEADERS=1;HAVE_SYS_TYPES_H=1;HAVE_SYS_STAT_H=1;HAVE_STDLIB_H=1;HAVE_STRING_H=1;HAVE_MEMORY_H=1;HAVE_STRINGS_H=1;HAVE_INTTYPES_H=1;HAVE_STDINT_H=1;HAVE_UNISTD_H=1;SILENT=1;NO_SIGNALS=1;NO_EXECUTE_PERMISSION=1;JAVA_FINALIZATION=1;GC_GCJ_SUPPORT=1;ATOMIC_UNCOLLECTABLE=1;_IN_LIBGC=1;WINVER=0x0600;_WIN32_WINNT=0x0600;_WIN32_IE=0x0501;WIN32_THREADS;FD_SETSIZE=1024;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebugDLL - true - - - $(OutDir)vc80.pdb - ProgramDatabase - CompileAsC - 4311;4312;4996;4005;%(DisableSpecificWarnings) - - - $(OutDir)libgc.lib + $(OutDir)$(TargetName)$(TargetExt) MinSpace - ..\libgc\include;%(AdditionalIncludeDirectories) + $(MONO_LIBGC_INCLUDE_DIR);%(AdditionalIncludeDirectories) NDEBUG;__i386__;TARGET_X86;i386;i386;WIN32;_WIN32;__WIN32__;_WINDOWS;WINDOWS;HOST_WIN32;TARGET_WIN32;_CRT_SECURE_NO_DEPRECATE;__STDC__;PACKAGE_NAME="libgc-mono";PACKAGE_TARNAME="libgc-mono";PACKAGE_VERSION="6.6";PACKAGE_STRING="libgc-mono 6.6";PACKAGE_BUGREPORT="Hans_Boehm%40hp.com";GC_WIN32_THREADS=1;NO_GETENV=1;GC_INSIDE_DLL=1;GC_NOT_DLL=1;STDC_HEADERS=1;HAVE_SYS_TYPES_H=1;HAVE_SYS_STAT_H=1;HAVE_STDLIB_H=1;HAVE_STRING_H=1;HAVE_MEMORY_H=1;HAVE_STRINGS_H=1;HAVE_INTTYPES_H=1;HAVE_STDINT_H=1;HAVE_UNISTD_H=1;SILENT=1;NO_SIGNALS=1;NO_EXECUTE_PERMISSION=1;JAVA_FINALIZATION=1;GC_GCJ_SUPPORT=1;ATOMIC_UNCOLLECTABLE=1;_IN_LIBGC=1;WINVER=0x0600;_WIN32_WINNT=0x0600;_WIN32_IE=0x0501;WIN32_THREADS;FD_SETSIZE=1024;%(PreprocessorDefinitions) - MultiThreadedDLL - true - $(OutDir)vc80.pdb ProgramDatabase CompileAsC + $(IntDir)$(TargetName).pdb - $(OutDir)libgc.lib - - - - - MinSpace - ..\libgc\include;%(AdditionalIncludeDirectories) - NDEBUG;__i386__;TARGET_X86;i386;i386;WIN32;_WIN32;__WIN32__;_WINDOWS;WINDOWS;HOST_WIN32;TARGET_WIN32;_CRT_SECURE_NO_DEPRECATE;__STDC__;PACKAGE_NAME="libgc-mono";PACKAGE_TARNAME="libgc-mono";PACKAGE_VERSION="6.6";PACKAGE_STRING="libgc-mono 6.6";PACKAGE_BUGREPORT="Hans_Boehm%40hp.com";GC_WIN32_THREADS=1;NO_GETENV=1;GC_INSIDE_DLL=1;GC_NOT_DLL=1;STDC_HEADERS=1;HAVE_SYS_TYPES_H=1;HAVE_SYS_STAT_H=1;HAVE_STDLIB_H=1;HAVE_STRING_H=1;HAVE_MEMORY_H=1;HAVE_STRINGS_H=1;HAVE_INTTYPES_H=1;HAVE_STDINT_H=1;HAVE_UNISTD_H=1;SILENT=1;NO_SIGNALS=1;NO_EXECUTE_PERMISSION=1;JAVA_FINALIZATION=1;GC_GCJ_SUPPORT=1;ATOMIC_UNCOLLECTABLE=1;_IN_LIBGC=1;WINVER=0x0600;_WIN32_WINNT=0x0600;_WIN32_IE=0x0501;WIN32_THREADS;FD_SETSIZE=1024;%(PreprocessorDefinitions) - MultiThreadedDLL - true - - - $(OutDir)vc80.pdb - ProgramDatabase - CompileAsC - - - $(OutDir)libgc.lib + $(OutDir)$(TargetName)$(TargetExt) @@ -207,44 +116,19 @@ Disabled - ..\libgc\include;%(AdditionalIncludeDirectories) + $(MONO_LIBGC_INCLUDE_DIR);%(AdditionalIncludeDirectories) _DEBUG;__x86_64__;WIN64;_WIN64;WIN32;_WIN32;__WIN32__;_WINDOWS;WINDOWS;HOST_WIN32;TARGET_WIN32;_CRT_SECURE_NO_DEPRECATE;__STDC__;PACKAGE_NAME="libgc-mono";PACKAGE_TARNAME="libgc-mono";PACKAGE_VERSION="6.6";PACKAGE_STRING="libgc-mono 6.6";PACKAGE_BUGREPORT="Hans_Boehm%40hp.com";GC_WIN32_THREADS=1;NO_GETENV=1;GC_INSIDE_DLL=1;GC_NOT_DLL=1;STDC_HEADERS=1;HAVE_SYS_TYPES_H=1;HAVE_SYS_STAT_H=1;HAVE_STDLIB_H=1;HAVE_STRING_H=1;HAVE_MEMORY_H=1;HAVE_STRINGS_H=1;HAVE_INTTYPES_H=1;HAVE_STDINT_H=1;HAVE_UNISTD_H=1;SILENT=1;NO_SIGNALS=1;NO_EXECUTE_PERMISSION=1;JAVA_FINALIZATION=1;GC_GCJ_SUPPORT=1;ATOMIC_UNCOLLECTABLE=1;_IN_LIBGC=1;WINVER=0x0600;_WIN32_WINNT=0x0600;_WIN32_IE=0x0501;WIN32_THREADS;FD_SETSIZE=1024 true EnableFastChecks - MultiThreadedDebugDLL - true - $(OutDir)vc80.pdb ProgramDatabase CompileAsC 4311;4312;4996;4005;%(DisableSpecificWarnings) + $(IntDir)$(TargetName).pdb - $(OutDir)libgc.lib - - - - - X64 - - - Disabled - ..\libgc\include;%(AdditionalIncludeDirectories) - _DEBUG;__x86_64__;WIN64;_WIN64;WIN32;_WIN32;__WIN32__;_WINDOWS;WINDOWS;HOST_WIN32;TARGET_WIN32;_CRT_SECURE_NO_DEPRECATE;__STDC__;PACKAGE_NAME="libgc-mono";PACKAGE_TARNAME="libgc-mono";PACKAGE_VERSION="6.6";PACKAGE_STRING="libgc-mono 6.6";PACKAGE_BUGREPORT="Hans_Boehm%40hp.com";GC_WIN32_THREADS=1;NO_GETENV=1;GC_INSIDE_DLL=1;GC_NOT_DLL=1;STDC_HEADERS=1;HAVE_SYS_TYPES_H=1;HAVE_SYS_STAT_H=1;HAVE_STDLIB_H=1;HAVE_STRING_H=1;HAVE_MEMORY_H=1;HAVE_STRINGS_H=1;HAVE_INTTYPES_H=1;HAVE_STDINT_H=1;HAVE_UNISTD_H=1;SILENT=1;NO_SIGNALS=1;NO_EXECUTE_PERMISSION=1;JAVA_FINALIZATION=1;GC_GCJ_SUPPORT=1;ATOMIC_UNCOLLECTABLE=1;_IN_LIBGC=1;WINVER=0x0600;_WIN32_WINNT=0x0600;_WIN32_IE=0x0501;WIN32_THREADS;FD_SETSIZE=1024 - true - EnableFastChecks - MultiThreadedDebugDLL - true - - - $(OutDir)vc80.pdb - ProgramDatabase - CompileAsC - 4311;4312;4996;4005;%(DisableSpecificWarnings) - - - $(OutDir)libgc.lib + $(OutDir)$(TargetName)$(TargetExt) @@ -253,38 +137,16 @@ MinSpace - ..\libgc\include;%(AdditionalIncludeDirectories) + $(MONO_LIBGC_INCLUDE_DIR);%(AdditionalIncludeDirectories) NDEBUG;__x86_64__;WIN64;_WIN64;WIN32;_WIN32;__WIN32__;_WINDOWS;WINDOWS;HOST_WIN32;TARGET_WIN32;_CRT_SECURE_NO_DEPRECATE;__STDC__;PACKAGE_NAME="libgc-mono";PACKAGE_TARNAME="libgc-mono";PACKAGE_VERSION="6.6";PACKAGE_STRING="libgc-mono 6.6";PACKAGE_BUGREPORT="Hans_Boehm%40hp.com";GC_WIN32_THREADS=1;NO_GETENV=1;GC_INSIDE_DLL=1;GC_NOT_DLL=1;STDC_HEADERS=1;HAVE_SYS_TYPES_H=1;HAVE_SYS_STAT_H=1;HAVE_STDLIB_H=1;HAVE_STRING_H=1;HAVE_MEMORY_H=1;HAVE_STRINGS_H=1;HAVE_INTTYPES_H=1;HAVE_STDINT_H=1;HAVE_UNISTD_H=1;SILENT=1;NO_SIGNALS=1;NO_EXECUTE_PERMISSION=1;JAVA_FINALIZATION=1;GC_GCJ_SUPPORT=1;ATOMIC_UNCOLLECTABLE=1;_IN_LIBGC=1;WINVER=0x0600;_WIN32_WINNT=0x0600;_WIN32_IE=0x0501;WIN32_THREADS;FD_SETSIZE=1024;%(PreprocessorDefinitions) - MultiThreadedDLL - true - $(OutDir)vc80.pdb ProgramDatabase CompileAsC + $(IntDir)$(TargetName).pdb - $(OutDir)libgc.lib - - - - - X64 - - - MinSpace - ..\libgc\include;%(AdditionalIncludeDirectories) - NDEBUG;__x86_64__;WIN64;_WIN64;WIN32;_WIN32;__WIN32__;_WINDOWS;WINDOWS;HOST_WIN32;TARGET_WIN32;_CRT_SECURE_NO_DEPRECATE;__STDC__;PACKAGE_NAME="libgc-mono";PACKAGE_TARNAME="libgc-mono";PACKAGE_VERSION="6.6";PACKAGE_STRING="libgc-mono 6.6";PACKAGE_BUGREPORT="Hans_Boehm%40hp.com";GC_WIN32_THREADS=1;NO_GETENV=1;GC_INSIDE_DLL=1;GC_NOT_DLL=1;STDC_HEADERS=1;HAVE_SYS_TYPES_H=1;HAVE_SYS_STAT_H=1;HAVE_STDLIB_H=1;HAVE_STRING_H=1;HAVE_MEMORY_H=1;HAVE_STRINGS_H=1;HAVE_INTTYPES_H=1;HAVE_STDINT_H=1;HAVE_UNISTD_H=1;SILENT=1;NO_SIGNALS=1;NO_EXECUTE_PERMISSION=1;JAVA_FINALIZATION=1;GC_GCJ_SUPPORT=1;ATOMIC_UNCOLLECTABLE=1;_IN_LIBGC=1;WINVER=0x0600;_WIN32_WINNT=0x0600;_WIN32_IE=0x0501;WIN32_THREADS;FD_SETSIZE=1024;%(PreprocessorDefinitions) - MultiThreadedDLL - true - - - $(OutDir)vc80.pdb - ProgramDatabase - CompileAsC - - - $(OutDir)libgc.lib + $(OutDir)$(TargetName)$(TargetExt) diff --git a/msvc/libgcmonosgen.vcxproj b/msvc/libgcmonosgen.vcxproj new file mode 100644 index 0000000000..e0979dbbee --- /dev/null +++ b/msvc/libgcmonosgen.vcxproj @@ -0,0 +1,223 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {C36612BD-22D3-4B95-85E2-7FDC4FC5D740} + Win32Proj + libmonosgen + 8.1 + libgcmonosgen + + + + StaticLibrary + true + Unicode + v140 + + + StaticLibrary + true + Unicode + v140 + + + StaticLibrary + false + Unicode + v140 + + + StaticLibrary + false + Unicode + v140 + + + + + + + + + + + + + + + + + + + + + + + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ + $(ProjectName) + + + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ + $(ProjectName) + + + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ + $(ProjectName) + + + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ + $(ProjectName) + + + + + + Level3 + Disabled + WIN32;$(SGEN_DEFINES);_DEBUG;_LIB;%(PreprocessorDefinitions) + $(MONO_DIR);$(MONO_INCLUDE_DIR);$(LIBGC_CPPFLAGS_INCLUDE);$(GLIB_CFLAGS_INCLUDE);%(AdditionalIncludeDirectories) + ProgramDatabase + $(IntDir)$(TargetName).pdb + + + Windows + true + + + + + + + Level3 + Disabled + WIN32;$(SGEN_DEFINES);_DEBUG;_LIB;%(PreprocessorDefinitions) + false + $(MONO_DIR);$(MONO_INCLUDE_DIR);$(LIBGC_CPPFLAGS_INCLUDE);$(GLIB_CFLAGS_INCLUDE);%(AdditionalIncludeDirectories) + ProgramDatabase + $(IntDir)$(TargetName).pdb + + + Windows + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;$(SGEN_DEFINES);NDEBUG;_LIB;%(PreprocessorDefinitions) + $(MONO_DIR);$(MONO_INCLUDE_DIR);$(LIBGC_CPPFLAGS_INCLUDE);$(GLIB_CFLAGS_INCLUDE);%(AdditionalIncludeDirectories) + $(IntDir)$(TargetName).pdb + + + Windows + true + true + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;$(SGEN_DEFINES);NDEBUG;_LIB;%(PreprocessorDefinitions) + $(MONO_DIR);$(MONO_INCLUDE_DIR);$(LIBGC_CPPFLAGS_INCLUDE);$(GLIB_CFLAGS_INCLUDE);%(AdditionalIncludeDirectories) + $(IntDir)$(TargetName).pdb + + + Windows + true + true + true + + + + + + \ No newline at end of file diff --git a/msvc/libmono-static.vcxproj b/msvc/libmono-static.vcxproj new file mode 100644 index 0000000000..5d638f1b8f --- /dev/null +++ b/msvc/libmono-static.vcxproj @@ -0,0 +1,339 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + true + true + + + true + true + + + true + true + + + true + true + + + + + true + true + + + true + true + + + + + + + + true + true + + + true + true + + + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + true + + + true + true + + + true + true + + + true + true + + + + + + + + + + + + + + + + + + + + + + + + {CB0D9E92-293C-439C-9AC7-C5F59B6E0772} + libmono-static + 8.1 + + + + StaticLibrary + Unicode + v140 + + + StaticLibrary + Unicode + v140 + + + StaticLibrary + Unicode + v140 + + + StaticLibrary + Unicode + v140 + + + + + + + + + + + + + + + + + + + + + + + $(ProjectName)$(MONO_TARGET_SUFFIX) + $(ProjectName)$(MONO_TARGET_SUFFIX) + $(ProjectName)$(MONO_TARGET_SUFFIX) + $(ProjectName)$(MONO_TARGET_SUFFIX) + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ + + + true + + + true + + + + + + + + /D /NODEFAULTLIB:LIBCD" " %(AdditionalOptions) + Disabled + $(MONO_DIR);$(LIBGC_CPPFLAGS_INCLUDE);$(GLIB_CFLAGS_INCLUDE);%(AdditionalIncludeDirectories) + WIN32;_DEBUG;%(PreprocessorDefinitions) + true + EnableFastChecks + + + false + ProgramDatabase + 4996;4018;4244;%(DisableSpecificWarnings) + $(IntDir)$(TargetName).pdb + + + Windows + + + .\libmono.bat "$(MONO_INCLUDE_DIR)" "$(SolutionDir)include\mono" -q + + + + + + + + + /D /NODEFAULTLIB:LIBCD" " %(AdditionalOptions) + Disabled + $(MONO_DIR);$(LIBGC_CPPFLAGS_INCLUDE);$(GLIB_CFLAGS_INCLUDE);%(AdditionalIncludeDirectories) + WIN32;WIN64;_DEBUG;%(PreprocessorDefinitions) + true + EnableFastChecks + + + false + ProgramDatabase + 4996;4018;4244;%(DisableSpecificWarnings) + $(IntDir)$(TargetName).pdb + + + Windows + + + .\libmono.bat "$(MONO_INCLUDE_DIR)" "$(SolutionDir)include\mono" -q + + + + + + + + + /D /NODEFAULTLIB:LIBCD" " %(AdditionalOptions) + MaxSpeed + true + $(MONO_DIR);$(LIBGC_CPPFLAGS_INCLUDE);$(GLIB_CFLAGS_INCLUDE);%(AdditionalIncludeDirectories) + WIN32;NDEBUG;%(PreprocessorDefinitions) + true + + + $(IntDir)$(TargetName).pdb + + + Windows + true + true + + + .\libmono.bat "$(MONO_INCLUDE_DIR)" "$(SolutionDir)include\mono" -q + + + + + + + + + /D /NODEFAULTLIB:LIBCD" " %(AdditionalOptions) + MaxSpeed + true + $(MONO_DIR);$(LIBGC_CPPFLAGS_INCLUDE);$(GLIB_CFLAGS_INCLUDE);%(AdditionalIncludeDirectories) + WIN32;WIN64;NDEBUG;%(PreprocessorDefinitions) + true + + + $(IntDir)$(TargetName).pdb + + + Windows + true + true + + + .\libmono.bat "$(MONO_INCLUDE_DIR)" "$(SolutionDir)include\mono" -q + + + + + true + true + + + true + true + + + + + {158073ed-99ae-4196-9edc-ddb2344f8466} + + + {b7098dfa-31e6-4006-8a15-1c9a4e925149} + + + {eb56000b-c80b-4e8b-908d-d84d31b517d3} + + + {c36612bd-22d3-4b95-85e2-7fdc4fc5d740} + + + {c36612bd-22d3-4b95-85e2-7fdc4fc5d739} + + + {8fc2b0c8-51ad-49df-851f-5d01a77a75e4} + + + + + + \ No newline at end of file diff --git a/msvc/libmono.vcxproj b/msvc/libmono.vcxproj index 68a0ff5568..82eff3379b 100644 --- a/msvc/libmono.vcxproj +++ b/msvc/libmono.vcxproj @@ -1,14 +1,6 @@  - + - - Debug_SGen - Win32 - - - Debug_SGen - x64 - Debug Win32 @@ -17,14 +9,6 @@ Debug x64 - - Release_SGen - Win32 - - - Release_SGen - x64 - Release Win32 @@ -34,273 +18,91 @@ x64 - - - - - - - true - true - true - true - - - true - true - true - true - - - true - true - true - true - - - true - true - true - true - - - - - true - true - true - true - - - true - true - true - true - - - - - - - - true - true - true - true - - - true - true - true - true - - - true - true - true - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - true - true - true - true - - - true - true - true - true - - - true - true - true - true - - - true - true - true - true - - - - - - - - - - - - - - - - - - - - - - {CB0D9E92-293C-439C-9AC7-C5F59B6E0771} libmono + 8.1 DynamicLibrary false Unicode - v120 - - - DynamicLibrary - false - Unicode - v120 + v140 DynamicLibrary false Unicode - v120 - - - DynamicLibrary - false - Unicode - v120 + v140 DynamicLibrary false Unicode - v120 - - - DynamicLibrary - false - Unicode - v120 + v140 DynamicLibrary false Unicode - v120 - - - DynamicLibrary - false - Unicode - v120 + v140 - - - + - - - + - - - + - - - + <_ProjectFileVersion>10.0.30319.1 - mono-2.0 - monosgen-2.0 - mono-2.0 - monosgen-2.0 - mono-2.0 - monosgen-2.0 - mono-2.0 - monosgen-2.0 - $(Platform)\bin\$(Configuration)\ - $(Platform)\bin\$(Configuration)\ - $(Platform)\bin\$(Configuration)\ - $(Platform)\bin\$(Configuration)\ - $(Platform)\bin\$(Configuration)\ - $(Platform)\bin\$(Configuration)\ - $(Platform)\bin\$(Configuration)\ - $(Platform)\bin\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ + mono-2.0$(MONO_TARGET_SUFFIX) + mono-2.0$(MONO_TARGET_SUFFIX) + mono-2.0$(MONO_TARGET_SUFFIX) + mono-2.0$(MONO_TARGET_SUFFIX) + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ + + + true + + + true - echo #define FULL_VERSION "Visual Studio built mono" > ..\mono\mini\version.h + + /D /NODEFAULTLIB:LIBCD" " %(AdditionalOptions) Disabled Default true - $(top_srcdir);$(LIBGC_CPPFLAGS_INCLUDE);$(GLIB_CFLAGS_INCLUDE) + $(MONO_DIR);$(LIBGC_CPPFLAGS_INCLUDE);$(GLIB_CFLAGS_INCLUDE);%(AdditionalIncludeDirectories) WIN32;_DEBUG;%(PreprocessorDefinitions) true EnableFastChecks - MultiThreadedDebugDLL @@ -315,85 +117,27 @@ 0x0409 - false + true - %(AdditionalDependencies) - $(Platform)\lib;%(AdditionalLibraryDirectories) - mono.def + eglib.lib;$(MONO_STATIC_LIBMONO_LIB);%(AdditionalDependencies) + %(AdditionalLibraryDirectories) + $(MONO_DEF) true false - $(Platform)\lib\$(Configuration)\$(TargetName).lib - $(TargetDir)$(TargetName).pdb + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\$(TargetName).lib + $(OutDir)$(TargetName).pdb - $(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\cil\opcode.def" "$(SolutionDir)include\mono\cil\" -$(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\mini\jit.h" "$(SolutionDir)include\mono\jit\" -$(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\metadata\*.h" "$(SolutionDir)include\mono\metadata\" -$(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\utils\mono-counters.h" "$(SolutionDir)include\mono\utils\" -$(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\utils\mono-dl-fallback.h" "$(SolutionDir)include\mono\utils\" -$(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\utils\mono-error.h" "$(SolutionDir)include\mono\utils\" -$(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\utils\mono-logger.h" "$(SolutionDir)include\mono\utils\" -$(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\utils\mono-publib.h" "$(SolutionDir)include\mono\utils\" - - - - - echo #define FULL_VERSION "Visual Studio built mono" > ..\mono\mini\version.h - - - /D /NODEFAULTLIB:LIBCD" " %(AdditionalOptions) - Disabled - Default - true - $(top_srcdir);$(LIBGC_CPPFLAGS_INCLUDE);$(GLIB_CFLAGS_INCLUDE) - WIN32;_DEBUG;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebugDLL - - - - - true - ProgramDatabase - CompileAsC - 4996;4018;4244;%(DisableSpecificWarnings) - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - - false - - - %(AdditionalDependencies) - $(Platform)\lib;%(AdditionalLibraryDirectories) - monosgen.def - true - false - - - $(Platform)\lib\$(Configuration)\$(TargetName).lib - $(TargetDir)$(TargetName).pdb - - - $(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\cil\opcode.def" "$(SolutionDir)include\mono\cil\" -$(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\mini\jit.h" "$(SolutionDir)include\mono\jit\" -$(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\metadata\*.h" "$(SolutionDir)include\mono\metadata\" -$(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\utils\mono-counters.h" "$(SolutionDir)include\mono\utils\" -$(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\utils\mono-dl-fallback.h" "$(SolutionDir)include\mono\utils\" -$(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\utils\mono-error.h" "$(SolutionDir)include\mono\utils\" -$(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\utils\mono-logger.h" "$(SolutionDir)include\mono\utils\" -$(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\utils\mono-publib.h" "$(SolutionDir)include\mono\utils\" + .\libmono.bat "$(MONO_INCLUDE_DIR)" "$(SolutionDir)include\mono" -q - echo #define FULL_VERSION "Visual Studio built mono" > ..\mono\mini\version.h + + X64 @@ -403,11 +147,10 @@ $(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\utils\mono-publib.h" "$(So Disabled Default true - $(top_srcdir);$(LIBGC_CPPFLAGS_INCLUDE);$(GLIB_CFLAGS_INCLUDE) + $(MONO_DIR);$(LIBGC_CPPFLAGS_INCLUDE);$(GLIB_CFLAGS_INCLUDE);%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;%(PreprocessorDefinitions) true EnableFastChecks - MultiThreadedDebugDLL @@ -422,92 +165,33 @@ $(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\utils\mono-publib.h" "$(So 0x0409 - false + true - %(AdditionalDependencies) - $(Platform)\lib;%(AdditionalLibraryDirectories) - mono.def + eglib.lib;$(MONO_STATIC_LIBMONO_LIB);%(AdditionalDependencies) + %(AdditionalLibraryDirectories) + $(MONO_DEF) true - $(Platform)\lib\$(Configuration)\$(TargetName).lib + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\$(TargetName).lib MachineX64 - $(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\cil\opcode.def" "$(SolutionDir)include\mono\cil\" -$(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\mini\jit.h" "$(SolutionDir)include\mono\jit\" -$(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\metadata\*.h" "$(SolutionDir)include\mono\metadata\" -$(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\utils\mono-counters.h" "$(SolutionDir)include\mono\utils\" -$(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\utils\mono-dl-fallback.h" "$(SolutionDir)include\mono\utils\" -$(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\utils\mono-error.h" "$(SolutionDir)include\mono\utils\" -$(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\utils\mono-logger.h" "$(SolutionDir)include\mono\utils\" -$(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\utils\mono-publib.h" "$(SolutionDir)include\mono\utils\" - - - - - echo #define FULL_VERSION "Visual Studio built mono" > ..\mono\mini\version.h - - - X64 - - - /D /NODEFAULTLIB:LIBCD" " %(AdditionalOptions) - Disabled - Default - true - $(top_srcdir);$(LIBGC_CPPFLAGS_INCLUDE);$(GLIB_CFLAGS_INCLUDE) - WIN32;WIN64;_DEBUG;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebugDLL - - - - - true - ProgramDatabase - CompileAsC - 4996;4018;4244;%(DisableSpecificWarnings) - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - - false - - - %(AdditionalDependencies) - $(Platform)\lib;%(AdditionalLibraryDirectories) - monosgen.def - true - $(Platform)\lib\$(Configuration)\$(TargetName).lib - MachineX64 - - - $(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\cil\opcode.def" "$(SolutionDir)include\mono\cil\" -$(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\mini\jit.h" "$(SolutionDir)include\mono\jit\" -$(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\metadata\*.h" "$(SolutionDir)include\mono\metadata\" -$(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\utils\mono-counters.h" "$(SolutionDir)include\mono\utils\" -$(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\utils\mono-dl-fallback.h" "$(SolutionDir)include\mono\utils\" -$(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\utils\mono-error.h" "$(SolutionDir)include\mono\utils\" -$(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\utils\mono-logger.h" "$(SolutionDir)include\mono\utils\" -$(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\utils\mono-publib.h" "$(SolutionDir)include\mono\utils\" + .\libmono.bat "$(MONO_INCLUDE_DIR)" "$(SolutionDir)include\mono" -q - echo #define FULL_VERSION "Visual Studio built mono" > ..\mono\mini\version.h + + /D /NODEFAULTLIB:LIBCD" " %(AdditionalOptions) MinSpace OnlyExplicitInline true - $(top_srcdir);$(LIBGC_CPPFLAGS_INCLUDE);$(GLIB_CFLAGS_INCLUDE) + $(MONO_DIR);$(LIBGC_CPPFLAGS_INCLUDE);$(GLIB_CFLAGS_INCLUDE);%(AdditionalIncludeDirectories) WIN32;NDEBUG;%(PreprocessorDefinitions) true - MultiThreadedDLL true @@ -520,81 +204,26 @@ $(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\utils\mono-publib.h" "$(So 0x0409 - false + true - %(AdditionalDependencies) - $(Platform)\lib;%(AdditionalLibraryDirectories) - mono.def + eglib.lib;$(MONO_STATIC_LIBMONO_LIB);%(AdditionalDependencies) + %(AdditionalLibraryDirectories) + $(MONO_DEF) false - $(Platform)\lib\$(Configuration)\$(TargetName).lib + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\$(TargetName).lib true - $(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\cil\opcode.def" "$(SolutionDir)include\mono\cil\" -$(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\mini\jit.h" "$(SolutionDir)include\mono\jit\" -$(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\metadata\*.h" "$(SolutionDir)include\mono\metadata\" -$(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\utils\mono-counters.h" "$(SolutionDir)include\mono\utils\" -$(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\utils\mono-dl-fallback.h" "$(SolutionDir)include\mono\utils\" -$(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\utils\mono-error.h" "$(SolutionDir)include\mono\utils\" -$(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\utils\mono-logger.h" "$(SolutionDir)include\mono\utils\" -$(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\utils\mono-publib.h" "$(SolutionDir)include\mono\utils\" - - - - - echo #define FULL_VERSION "Visual Studio built mono" > ..\mono\mini\version.h - - - /D /NODEFAULTLIB:LIBCD" " %(AdditionalOptions) - MinSpace - OnlyExplicitInline - true - $(top_srcdir);$(LIBGC_CPPFLAGS_INCLUDE);$(GLIB_CFLAGS_INCLUDE) - WIN32;NDEBUG;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - - - - - CompileAsC - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - - false - - - %(AdditionalDependencies) - $(Platform)\lib;%(AdditionalLibraryDirectories) - monosgen.def - false - - - $(Platform)\lib\$(Configuration)\$(TargetName).lib - true - $(TargetDir)$(TargetName).pdb - - - $(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\cil\opcode.def" "$(SolutionDir)include\mono\cil\" -$(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\mini\jit.h" "$(SolutionDir)include\mono\jit\" -$(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\metadata\*.h" "$(SolutionDir)include\mono\metadata\" -$(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\utils\mono-counters.h" "$(SolutionDir)include\mono\utils\" -$(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\utils\mono-dl-fallback.h" "$(SolutionDir)include\mono\utils\" -$(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\utils\mono-error.h" "$(SolutionDir)include\mono\utils\" -$(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\utils\mono-logger.h" "$(SolutionDir)include\mono\utils\" -$(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\utils\mono-publib.h" "$(SolutionDir)include\mono\utils\" + .\libmono.bat "$(MONO_INCLUDE_DIR)" "$(SolutionDir)include\mono" -q - echo #define FULL_VERSION "Visual Studio built mono" > ..\mono\mini\version.h + + X64 @@ -604,10 +233,9 @@ $(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\utils\mono-publib.h" "$(So MinSpace OnlyExplicitInline true - $(top_srcdir);$(LIBGC_CPPFLAGS_INCLUDE);$(GLIB_CFLAGS_INCLUDE) + $(MONO_DIR);$(LIBGC_CPPFLAGS_INCLUDE);$(GLIB_CFLAGS_INCLUDE);%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;%(PreprocessorDefinitions) true - MultiThreadedDLL true @@ -620,124 +248,59 @@ $(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\utils\mono-publib.h" "$(So 0x0409 - false + true - %(AdditionalDependencies) - $(Platform)\lib;%(AdditionalLibraryDirectories) - mono.def - $(Platform)\lib\$(Configuration)\$(TargetName).lib + eglib.lib;$(MONO_STATIC_LIBMONO_LIB);%(AdditionalDependencies) + %(AdditionalLibraryDirectories) + $(MONO_DEF) + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\$(TargetName).lib MachineX64 true - $(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\cil\opcode.def" "$(SolutionDir)include\mono\cil\" -$(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\mini\jit.h" "$(SolutionDir)include\mono\jit\" -$(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\metadata\*.h" "$(SolutionDir)include\mono\metadata\" -$(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\utils\mono-counters.h" "$(SolutionDir)include\mono\utils\" -$(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\utils\mono-dl-fallback.h" "$(SolutionDir)include\mono\utils\" -$(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\utils\mono-error.h" "$(SolutionDir)include\mono\utils\" -$(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\utils\mono-logger.h" "$(SolutionDir)include\mono\utils\" -$(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\utils\mono-publib.h" "$(SolutionDir)include\mono\utils\" - - - - - echo #define FULL_VERSION "Visual Studio built mono" > ..\mono\mini\version.h - - - X64 - - - /D /NODEFAULTLIB:LIBCD" " %(AdditionalOptions) - MinSpace - OnlyExplicitInline - true - $(top_srcdir);$(LIBGC_CPPFLAGS_INCLUDE);$(GLIB_CFLAGS_INCLUDE) - WIN32;WIN64;NDEBUG;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - - - - - CompileAsC - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - - false - - - %(AdditionalDependencies) - $(Platform)\lib;%(AdditionalLibraryDirectories) - monosgen.def - $(Platform)\lib\$(Configuration)\$(TargetName).lib - MachineX64 - true - - - $(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\cil\opcode.def" "$(SolutionDir)include\mono\cil\" -$(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\mini\jit.h" "$(SolutionDir)include\mono\jit\" -$(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\metadata\*.h" "$(SolutionDir)include\mono\metadata\" -$(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\utils\mono-counters.h" "$(SolutionDir)include\mono\utils\" -$(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\utils\mono-dl-fallback.h" "$(SolutionDir)include\mono\utils\" -$(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\utils\mono-error.h" "$(SolutionDir)include\mono\utils\" -$(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\utils\mono-logger.h" "$(SolutionDir)include\mono\utils\" -$(windir)\system32\xcopy /F /Y "$(SolutionDir)..\mono\utils\mono-publib.h" "$(SolutionDir)include\mono\utils\" + .\libmono.bat "$(MONO_INCLUDE_DIR)" "$(SolutionDir)include\mono" -q true - true true - true true - true true - true {158073ed-99ae-4196-9edc-ddb2344f8466} - false - true - false - true - false + + + {b7098dfa-31e6-4006-8a15-1c9a4e925149} {eb56000b-c80b-4e8b-908d-d84d31b517d3} - true - false - false - true - false + + + {c36612bd-22d3-4b95-85e2-7fdc4fc5d740} + + + {cb0d9e92-293c-439c-9ac7-c5f59b6e0772} {c36612bd-22d3-4b95-85e2-7fdc4fc5d739} - false - true - false - true - false {8fc2b0c8-51ad-49df-851f-5d01a77a75e4} - false - true - false - true - false + + + + + + diff --git a/msvc/libmonoruntime.vcxproj b/msvc/libmonoruntime.vcxproj index d8f354b760..41f6439154 100644 --- a/msvc/libmonoruntime.vcxproj +++ b/msvc/libmonoruntime.vcxproj @@ -1,14 +1,6 @@  - + - - Debug_SGen - Win32 - - - Debug_SGen - x64 - Debug Win32 @@ -17,14 +9,6 @@ Debug x64 - - Release_SGen - Win32 - - - Release_SGen - x64 - Release Win32 @@ -34,7 +18,6 @@ x64 - @@ -44,10 +27,13 @@ + + + @@ -87,48 +73,39 @@ + + - - - - - - - - - - - - - - - + + true + true + true + true + + + true + true + true + true + - - - - - - - - - - - + + + @@ -138,7 +115,6 @@ - @@ -147,11 +123,13 @@ + - + + @@ -159,7 +137,10 @@ + + + @@ -196,31 +177,16 @@ + + - - - - - - - - - - - - - - - - - - + @@ -229,123 +195,81 @@ + + + {158073ed-99ae-4196-9edc-ddb2344f8466} + + {C36612BD-22D3-4B95-85E2-7FDC4FC5D739} Win32Proj libmonoruntime + 8.1 StaticLibrary true Unicode - v120 - - - StaticLibrary - true - Unicode - v120 + v140 StaticLibrary true Unicode - v120 - - - StaticLibrary - true - Unicode - v120 + v140 StaticLibrary false Unicode - v120 - - - StaticLibrary - false - Unicode - v120 + v140 StaticLibrary false Unicode - v120 - - - StaticLibrary - false - Unicode - v120 + v140 - - - + - - - + - - - + - - - + - $(Platform)\lib\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ - - - $(Platform)\lib\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ - $(ProjectName)sgen + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ + $(ProjectName)$(MONO_TARGET_SUFFIX) - $(Platform)\lib\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ - - - $(Platform)\lib\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ - $(ProjectName)sgen + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ + $(ProjectName)$(MONO_TARGET_SUFFIX) - $(Platform)\lib\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ - - - $(Platform)\lib\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ - $(ProjectName)sgen + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ + $(ProjectName)$(MONO_TARGET_SUFFIX) - $(Platform)\lib\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ - - - $(Platform)\lib\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ - $(ProjectName)sgen + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ + $(ProjectName)$(MONO_TARGET_SUFFIX) @@ -353,28 +277,16 @@ Level3 Disabled - WIN32;$(BOEHM_DEFINES);_DEBUG;_LIB;%(PreprocessorDefinitions) - $(top_srcdir);$(top_srcdir)/mono;$(LIBGC_CPPFLAGS_INCLUDE);$(GLIB_CFLAGS_INCLUDE) - MultiThreadedDebugDLL - - - Windows - true - - - - - - - Level3 - Disabled - WIN32;$(SGEN_DEFINES);_DEBUG;_LIB;%(PreprocessorDefinitions) - $(top_srcdir);$(top_srcdir)/mono;$(LIBGC_CPPFLAGS_INCLUDE);$(GLIB_CFLAGS_INCLUDE) + WIN32;WIN32_LEAN_AND_MEAN;$(GC_DEFINES);_DEBUG;_LIB;%(PreprocessorDefinitions) + $(MONO_DIR);$(MONO_INCLUDE_DIR);$(LIBGC_CPPFLAGS_INCLUDE);$(GLIB_CFLAGS_INCLUDE);%(AdditionalIncludeDirectories) + ProgramDatabase + $(IntDir)$(TargetName).pdb Windows true + @@ -382,28 +294,16 @@ Level3 Disabled - WIN32;$(BOEHM_DEFINES);_DEBUG;_LIB;%(PreprocessorDefinitions) - $(top_srcdir);$(top_srcdir)/mono;$(LIBGC_CPPFLAGS_INCLUDE);$(GLIB_CFLAGS_INCLUDE) - - - Windows - true - - - - - - - Level3 - Disabled - WIN32;$(SGEN_DEFINES);_DEBUG;_LIB;%(PreprocessorDefinitions) - false - $(top_srcdir);$(LIBGC_CPPFLAGS_INCLUDE);$(GLIB_CFLAGS_INCLUDE);$(top_srcdir)\mono + WIN32;WIN32_LEAN_AND_MEAN;$(GC_DEFINES);_DEBUG;_LIB;%(PreprocessorDefinitions) + $(MONO_DIR);$(MONO_INCLUDE_DIR);$(LIBGC_CPPFLAGS_INCLUDE);$(GLIB_CFLAGS_INCLUDE);%(AdditionalIncludeDirectories) + ProgramDatabase + $(IntDir)$(TargetName).pdb Windows true + @@ -413,26 +313,9 @@ MaxSpeed true true - WIN32;$(BOEHM_DEFINES);NDEBUG;_LIB;%(PreprocessorDefinitions) - $(top_srcdir);$(top_srcdir)/mono;$(LIBGC_CPPFLAGS_INCLUDE);$(GLIB_CFLAGS_INCLUDE) - - - Windows - true - true - true - - - - - Level3 - - - MaxSpeed - true - true - WIN32;$(SGEN_DEFINES);NDEBUG;_LIB;%(PreprocessorDefinitions) - $(top_srcdir);$(top_srcdir)/mono;$(LIBGC_CPPFLAGS_INCLUDE);$(GLIB_CFLAGS_INCLUDE) + WIN32;WIN32_LEAN_AND_MEAN;$(GC_DEFINES);NDEBUG;_LIB;%(PreprocessorDefinitions) + $(MONO_DIR);$(MONO_INCLUDE_DIR);$(LIBGC_CPPFLAGS_INCLUDE);$(GLIB_CFLAGS_INCLUDE);%(AdditionalIncludeDirectories) + $(IntDir)$(TargetName).pdb Windows @@ -440,6 +323,7 @@ true true + @@ -449,26 +333,9 @@ MaxSpeed true true - WIN32;$(BOEHM_DEFINES);NDEBUG;_LIB;%(PreprocessorDefinitions) - $(top_srcdir);$(top_srcdir)/mono;$(LIBGC_CPPFLAGS_INCLUDE);$(GLIB_CFLAGS_INCLUDE) - - - Windows - true - true - true - - - - - Level3 - - - MaxSpeed - true - true - WIN32;$(SGEN_DEFINES);NDEBUG;_LIB;%(PreprocessorDefinitions) - $(top_srcdir);$(top_srcdir)/mono;$(LIBGC_CPPFLAGS_INCLUDE);$(GLIB_CFLAGS_INCLUDE) + WIN32;WIN32_LEAN_AND_MEAN;$(GC_DEFINES);NDEBUG;_LIB;%(PreprocessorDefinitions) + $(MONO_DIR);$(MONO_INCLUDE_DIR);$(LIBGC_CPPFLAGS_INCLUDE);$(GLIB_CFLAGS_INCLUDE);%(AdditionalIncludeDirectories) + $(IntDir)$(TargetName).pdb Windows @@ -476,8 +343,9 @@ true true + - + \ No newline at end of file diff --git a/msvc/libmonoutils.vcxproj b/msvc/libmonoutils.vcxproj index 5daad94726..ca9ce67c46 100644 --- a/msvc/libmonoutils.vcxproj +++ b/msvc/libmonoutils.vcxproj @@ -1,5 +1,5 @@  - + Debug @@ -18,7 +18,6 @@ x64 - @@ -26,10 +25,30 @@ - - - - + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + @@ -42,6 +61,8 @@ + + @@ -59,14 +80,39 @@ - - - + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + - - + + true + true + true + true + + + true + true + true + true + @@ -155,37 +201,45 @@ Document + true + true + + + {158073ed-99ae-4196-9edc-ddb2344f8466} + + {8FC2B0C8-51AD-49DF-851F-5D01A77A75E4} Win32Proj libmonoutils + 8.1 StaticLibrary true Unicode - v120 + v140 StaticLibrary true Unicode - v120 + v140 StaticLibrary false Unicode - v120 + v140 StaticLibrary false Unicode - v120 + v140 @@ -193,32 +247,36 @@ + + + + - $(Platform)\lib\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ - $(Platform)\lib\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ - $(Platform)\lib\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ - $(Platform)\lib\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ @@ -226,15 +284,18 @@ Level3 Disabled - WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - $(top_srcdir);$(top_srcdir)/mono;$(LIBGC_CPPFLAGS_INCLUDE);$(GLIB_CFLAGS_INCLUDE) + WIN32;WIN32_LEAN_AND_MEAN;_DEBUG;_LIB;%(PreprocessorDefinitions) + $(MONO_DIR);$(MONO_INCLUDE_DIR);$(LIBGC_CPPFLAGS_INCLUDE);$(GLIB_CFLAGS_INCLUDE);%(AdditionalIncludeDirectories) + ProgramDatabase + $(IntDir)$(TargetName).pdb Windows true - winsetup.bat + + @@ -243,15 +304,18 @@ Level3 Disabled - WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - $(top_srcdir);$(top_srcdir)/eglib/src;$(top_srcdir)/mono;$(LIBGC_CPPFLAGS_INCLUDE);$(GLIB_CFLAGS_INCLUDE) + WIN32;WIN32_LEAN_AND_MEAN;_DEBUG;_LIB;%(PreprocessorDefinitions) + $(MONO_DIR);$(MONO_INCLUDE_DIR);$(LIBGC_CPPFLAGS_INCLUDE);$(GLIB_CFLAGS_INCLUDE);%(AdditionalIncludeDirectories) + ProgramDatabase + $(IntDir)$(TargetName).pdb Windows true - winsetup.bat + + X64 @@ -265,8 +329,9 @@ MaxSpeed true true - WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - $(top_srcdir);$(top_srcdir)/mono;$(LIBGC_CPPFLAGS_INCLUDE);$(GLIB_CFLAGS_INCLUDE) + WIN32;WIN32_LEAN_AND_MEAN;NDEBUG;_LIB;%(PreprocessorDefinitions) + $(MONO_DIR);$(MONO_INCLUDE_DIR);$(LIBGC_CPPFLAGS_INCLUDE);$(GLIB_CFLAGS_INCLUDE);%(AdditionalIncludeDirectories) + $(IntDir)$(TargetName).pdb Windows @@ -275,7 +340,8 @@ true - winsetup.bat + + @@ -286,8 +352,9 @@ MaxSpeed true true - WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - $(top_srcdir);$(top_srcdir)/mono;$(LIBGC_CPPFLAGS_INCLUDE);$(GLIB_CFLAGS_INCLUDE) + WIN32;WIN32_LEAN_AND_MEAN;NDEBUG;_LIB;%(PreprocessorDefinitions) + $(MONO_DIR);$(MONO_INCLUDE_DIR);$(LIBGC_CPPFLAGS_INCLUDE);$(GLIB_CFLAGS_INCLUDE);%(AdditionalIncludeDirectories) + $(IntDir)$(TargetName).pdb Windows @@ -296,7 +363,8 @@ true - winsetup.bat + + X64 @@ -306,4 +374,4 @@ - + diff --git a/msvc/libtest.vcxproj b/msvc/libtest.vcxproj index 64aaae18a4..27a44e3ae8 100644 --- a/msvc/libtest.vcxproj +++ b/msvc/libtest.vcxproj @@ -1,5 +1,5 @@  - + Debug @@ -18,89 +18,92 @@ x64 - {5A435710-E6D2-4DD4-9B3F-A7239A32C6F4} libtest Win32Proj + 8.1 DynamicLibrary Unicode - v120 + v140 DynamicLibrary Unicode - v120 + v140 DynamicLibrary Unicode - v120 + v140 DynamicLibrary Unicode - v120 + v140 + + + + <_ProjectFileVersion>10.0.30319.1 - $(Platform)\bin\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ true - $(Platform)\bin\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ true - $(Platform)\bin\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ false - $(Platform)\bin\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ false Disabled - ..\eglib\src;..\;%(AdditionalIncludeDirectories) + $(MONO_DIR);$(MONO_EGLIB_SOURCE_DIR);%(AdditionalIncludeDirectories) WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBTEST_EXPORTS;%(PreprocessorDefinitions) true EnableFastChecks - MultiThreadedDebugDLL Level3 - EditAndContinue + ProgramDatabase false - Psapi.lib;%(AdditionalDependencies) - $(Platform)\lib;%(AdditionalLibraryDirectories) + eglib.lib;%(AdditionalDependencies) + %(AdditionalLibraryDirectories) true Windows false - $(Platform)\lib\$(Configuration)\$(TargetName).lib + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\$(TargetName).lib MachineX86 @@ -110,11 +113,10 @@ Disabled - ..\eglib\src;..\;%(AdditionalIncludeDirectories) + $(MONO_DIR);$(MONO_EGLIB_SOURCE_DIR);%(AdditionalIncludeDirectories) WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBTEST_EXPORTS;%(PreprocessorDefinitions) true EnableFastChecks - MultiThreadedDebugDLL Level3 @@ -124,20 +126,19 @@ false - Psapi.lib;%(AdditionalDependencies) - $(Platform)\lib;%(AdditionalLibraryDirectories) + eglib.lib;%(AdditionalDependencies) + %(AdditionalLibraryDirectories) true Windows - $(Platform)\lib\$(Configuration)\$(TargetName).lib + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\$(TargetName).lib MachineX64 MinSpace - ..\eglib\src;..\;%(AdditionalIncludeDirectories) + $(MONO_DIR);$(MONO_EGLIB_SOURCE_DIR);%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBTEST_EXPORTS;%(PreprocessorDefinitions) - MultiThreadedDLL Level3 @@ -147,8 +148,8 @@ false - Psapi.lib;%(AdditionalDependencies) - $(Platform)\lib;%(AdditionalLibraryDirectories) + eglib.lib;%(AdditionalDependencies) + %(AdditionalLibraryDirectories) true Windows true @@ -156,7 +157,7 @@ false - $(Platform)\lib\$(Configuration)\$(TargetName).lib + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\$(TargetName).lib MachineX86 @@ -166,9 +167,8 @@ MinSpace - ..\eglib\src;..\;%(AdditionalIncludeDirectories) + $(MONO_DIR);$(MONO_EGLIB_SOURCE_DIR);%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBTEST_EXPORTS;%(PreprocessorDefinitions) - MultiThreadedDLL Level3 @@ -178,13 +178,13 @@ false - Psapi.lib;%(AdditionalDependencies) - $(Platform)\lib;%(AdditionalLibraryDirectories) + eglib.lib;%(AdditionalDependencies) + %(AdditionalLibraryDirectories) true Windows true true - $(Platform)\lib\$(Configuration)\$(TargetName).lib + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\$(TargetName).lib MachineX64 @@ -194,11 +194,9 @@ {158073ed-99ae-4196-9edc-ddb2344f8466} - true - false - false - true - false + + + {cb0d9e92-293c-439c-9ac7-c5f59b6e0771} diff --git a/msvc/mono-full-aot-compile-test.vcxproj b/msvc/mono-full-aot-compile-test.vcxproj new file mode 100644 index 0000000000..1ccf4e7563 --- /dev/null +++ b/msvc/mono-full-aot-compile-test.vcxproj @@ -0,0 +1,203 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {C7D83158-4EB6-4409-8730-612AD45FAF6A} + monofullaotcompiletest + 8.1 + + + + Utility + true + Unicode + v140 + + + Utility + false + true + Unicode + v140 + + + Utility + true + Unicode + v140 + + + Utility + false + true + Unicode + v140 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ + + + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ + + + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ + + + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ + + + $(MONO_EXECUTABLE) + $(MONO_FULL_AOT_COMPILE_ARGS) + $(MONO_FULL_AOT_TEST_DIR) + WindowsLocalDebugger + $(MONO_PATH_ENV) +$(MONO_CFG_DIR_ENV) +$(MONO_TOOLCHAIN_PATH_ENV) +$(MONO_LOG_LEVEL_ENV) +$(MONO_LOG_MASK_ENV) +$(LocalDebuggerEnvironment) + + + $(MONO_EXECUTABLE) + $(MONO_FULL_AOT_COMPILE_ARGS) + $(MONO_FULL_AOT_TEST_DIR) + WindowsLocalDebugger + $(MONO_PATH_ENV) +$(MONO_CFG_DIR_ENV) +$(MONO_TOOLCHAIN_PATH_ENV) +$(MONO_LOG_LEVEL_ENV) +$(MONO_LOG_MASK_ENV) +$(LocalDebuggerEnvironment) + + + $(MONO_EXECUTABLE) + $(MONO_FULL_AOT_COMPILE_ARGS) + $(MONO_FULL_AOT_TEST_DIR) + WindowsLocalDebugger + $(MONO_PATH_ENV) +$(MONO_CFG_DIR_ENV) +$(MONO_TOOLCHAIN_PATH_ENV) +$(MONO_LOG_LEVEL_ENV) +$(MONO_LOG_MASK_ENV) +$(LocalDebuggerEnvironment) + + + $(MONO_EXECUTABLE) + $(MONO_FULL_AOT_COMPILE_ARGS) + $(MONO_FULL_AOT_TEST_DIR) + WindowsLocalDebugger + $(MONO_PATH_ENV) +$(MONO_CFG_DIR_ENV) +$(MONO_TOOLCHAIN_PATH_ENV) +$(MONO_LOG_LEVEL_ENV) +$(MONO_LOG_MASK_ENV) +$(LocalDebuggerEnvironment) + + + + Level3 + Disabled + true + + + + + Level3 + Disabled + true + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + + + {a0eddcd9-940f-432c-a28f-7ef322437d79} + + + + + + \ No newline at end of file diff --git a/msvc/mono-full-aot-run-test.vcxproj b/msvc/mono-full-aot-run-test.vcxproj new file mode 100644 index 0000000000..e16fcf235f --- /dev/null +++ b/msvc/mono-full-aot-run-test.vcxproj @@ -0,0 +1,203 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {6C64262B-077B-4E12-AF91-9409ECCB75F6} + monofullaotruntest + 8.1 + + + + Utility + true + Unicode + v140 + + + Utility + false + true + Unicode + v140 + + + Utility + true + Unicode + v140 + + + Utility + false + true + Unicode + v140 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ + + + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ + + + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ + + + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ + + + $(MONO_EXECUTABLE) + $(MONO_FULL_AOT_RUN_ARGS) + $(MONO_FULL_AOT_TEST_DIR) + WindowsLocalDebugger + $(MONO_PATH_ENV) +$(MONO_CFG_DIR_ENV) +$(MONO_TOOLCHAIN_PATH_ENV) +$(MONO_LOG_LEVEL_ENV) +$(MONO_LOG_MASK_ENV) +$(LocalDebuggerEnvironment) + + + $(MONO_EXECUTABLE) + $(MONO_FULL_AOT_RUN_ARGS) + $(MONO_FULL_AOT_TEST_DIR) + WindowsLocalDebugger + $(MONO_PATH_ENV) +$(MONO_CFG_DIR_ENV) +$(MONO_TOOLCHAIN_PATH_ENV) +$(MONO_LOG_LEVEL_ENV) +$(MONO_LOG_MASK_ENV) +$(LocalDebuggerEnvironment) + + + $(MONO_EXECUTABLE) + $(MONO_FULL_AOT_RUN_ARGS) + $(MONO_FULL_AOT_TEST_DIR) + WindowsLocalDebugger + $(MONO_PATH_ENV) +$(MONO_CFG_DIR_ENV) +$(MONO_TOOLCHAIN_PATH_ENV) +$(MONO_LOG_LEVEL_ENV) +$(MONO_LOG_MASK_ENV) +$(LocalDebuggerEnvironment) + + + $(MONO_EXECUTABLE) + $(MONO_FULL_AOT_RUN_ARGS) + $(MONO_FULL_AOT_TEST_DIR) + WindowsLocalDebugger + $(MONO_PATH_ENV) +$(MONO_CFG_DIR_ENV) +$(MONO_TOOLCHAIN_PATH_ENV) +$(MONO_LOG_LEVEL_ENV) +$(MONO_LOG_MASK_ENV) +$(LocalDebuggerEnvironment) + + + + Level3 + Disabled + true + + + + + Level3 + Disabled + true + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + + + {a0eddcd9-940f-432c-a28f-7ef322437d79} + + + + + + \ No newline at end of file diff --git a/msvc/mono-mini-regression-test.vcxproj b/msvc/mono-mini-regression-test.vcxproj new file mode 100644 index 0000000000..3b853a182a --- /dev/null +++ b/msvc/mono-mini-regression-test.vcxproj @@ -0,0 +1,204 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + {a0eddcd9-940f-432c-a28f-7ef322437d79} + + + + {3E0D229E-C39F-4EDA-9A6A-A33ECEA0322D} + monoregressiontest + 8.1 + mono-mini-regression-test + + + + Utility + true + v140 + Unicode + + + Utility + false + v140 + true + Unicode + + + Utility + true + v140 + Unicode + + + Utility + false + v140 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ + + + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ + + + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ + + + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ + + + $(MONO_EXECUTABLE) + $(MONO_MINI_REGRESSION_TEST_ARGS) + $(MONO_MINI_REGRESSION_TEST_DIR) + $(MONO_PATH_ENV) +$(MONO_CFG_DIR_ENV) +$(MONO_TOOLCHAIN_PATH_ENV) +$(MONO_LOG_LEVEL_ENV) +$(MONO_LOG_MASK_ENV) +$(LocalDebuggerEnvironment) + WindowsLocalDebugger + + + $(MONO_EXECUTABLE) + WindowsLocalDebugger + $(MONO_MINI_REGRESSION_TEST_ARGS) + $(MONO_MINI_REGRESSION_TEST_DIR) + $(MONO_PATH_ENV) +$(MONO_CFG_DIR_ENV) +$(MONO_TOOLCHAIN_PATH_ENV) +$(MONO_LOG_LEVEL_ENV) +$(MONO_LOG_MASK_ENV) +$(LocalDebuggerEnvironment) + + + $(MONO_EXECUTABLE) + WindowsLocalDebugger + $(MONO_MINI_REGRESSION_TEST_ARGS) + $(MONO_MINI_REGRESSION_TEST_DIR) + $(MONO_PATH_ENV) +$(MONO_CFG_DIR_ENV) +$(MONO_TOOLCHAIN_PATH_ENV) +$(MONO_LOG_LEVEL_ENV) +$(MONO_LOG_MASK_ENV) +$(LocalDebuggerEnvironment) + + + $(MONO_EXECUTABLE) + WindowsLocalDebugger + $(MONO_MINI_REGRESSION_TEST_ARGS) + $(MONO_MINI_REGRESSION_TEST_DIR) + $(MONO_PATH_ENV) +$(MONO_CFG_DIR_ENV) +$(MONO_TOOLCHAIN_PATH_ENV) +$(MONO_LOG_LEVEL_ENV) +$(MONO_LOG_MASK_ENV) +$(LocalDebuggerEnvironment) + + + + Level3 + Disabled + true + + + + + Level3 + Disabled + true + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + + + + \ No newline at end of file diff --git a/msvc/mono-nunit-test.vcxproj b/msvc/mono-nunit-test.vcxproj new file mode 100644 index 0000000000..0e9d6f8e6d --- /dev/null +++ b/msvc/mono-nunit-test.vcxproj @@ -0,0 +1,224 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + {a0eddcd9-940f-432c-a28f-7ef322437d79} + + + + {0046B994-40A8-4C64-AC9D-429DC9177B54} + Win32Proj + mononunittest + 8.1 + + + + Utility + true + v140 + Unicode + + + Utility + false + v140 + true + Unicode + + + Utility + true + v140 + Unicode + + + Utility + false + v140 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ + + + true + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ + + + false + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ + + + false + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ + + + $(MONO_EXECUTABLE) + $(MONO_NUNIT_RUN_ARGS) + $(MONO_NUNIT_TEST_DIR) + $(MONO_PATH_ENV) +$(MONO_CFG_DIR_ENV) +$(MONO_TOOLCHAIN_PATH_ENV) +$(MONO_LOG_LEVEL_ENV) +$(MONO_LOG_MASK_ENV) +$(LocalDebuggerEnvironment) + WindowsLocalDebugger + + + $(MONO_EXECUTABLE) + WindowsLocalDebugger + $(MONO_NUNIT_RUN_ARGS) + $(MONO_NUNIT_TEST_DIR) + $(MONO_PATH_ENV) +$(MONO_CFG_DIR_ENV) +$(MONO_TOOLCHAIN_PATH_ENV) +$(MONO_LOG_LEVEL_ENV) +$(MONO_LOG_MASK_ENV) +$(LocalDebuggerEnvironment) + + + $(MONO_EXECUTABLE) + WindowsLocalDebugger + $(MONO_NUNIT_RUN_ARGS) + $(MONO_NUNIT_TEST_DIR) + $(MONO_PATH_ENV) +$(MONO_CFG_DIR_ENV) +$(MONO_TOOLCHAIN_PATH_ENV) +$(MONO_LOG_LEVEL_ENV) +$(MONO_LOG_MASK_ENV) +$(LocalDebuggerEnvironment) + + + $(MONO_EXECUTABLE) + WindowsLocalDebugger + $(MONO_NUNIT_RUN_ARGS) + $(MONO_NUNIT_TEST_DIR) + $(MONO_PATH_ENV) +$(MONO_CFG_DIR_ENV) +$(MONO_TOOLCHAIN_PATH_ENV) +$(MONO_LOG_LEVEL_ENV) +$(MONO_LOG_MASK_ENV) +$(LocalDebuggerEnvironment) + + + + Level3 + Disabled + true + + + + + + + + + Level3 + Disabled + true + + + + + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + + + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + + + + + + + + \ No newline at end of file diff --git a/msvc/mono-testdriver-test.vcxproj b/msvc/mono-testdriver-test.vcxproj new file mode 100644 index 0000000000..fce7b4dfa2 --- /dev/null +++ b/msvc/mono-testdriver-test.vcxproj @@ -0,0 +1,220 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + {a0eddcd9-940f-432c-a28f-7ef322437d79} + + + + {7BECCFA0-28A0-4995-9856-558560F720E6} + Win32Proj + monotestdrivertest + 8.1 + + + + Utility + true + v140 + Unicode + + + Utility + false + v140 + true + Unicode + + + Utility + true + v140 + Unicode + + + Utility + false + v140 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ + + + true + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ + + + false + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ + + + false + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ + + + $(MONO_EXECUTABLE) + $(MONO_TESTDRIVER_RUN_ARGS) + $(MONO_TESTDRIVER_TEST_DIR) + $(MONO_PATH_ENV) +$(MONO_CFG_DIR_ENV) +$(MONO_TOOLCHAIN_PATH_ENV) +$(MONO_LOG_LEVEL_ENV) +$(MONO_LOG_MASK_ENV) +$(LocalDebuggerEnvironment) + WindowsLocalDebugger + + + $(MONO_EXECUTABLE) + WindowsLocalDebugger + $(MONO_TESTDRIVER_RUN_ARGS) + $(MONO_TESTDRIVER_TEST_DIR) + $(MONO_PATH_ENV) +$(MONO_CFG_DIR_ENV) +$(MONO_TOOLCHAIN_PATH_ENV) +$(MONO_LOG_LEVEL_ENV) +$(MONO_LOG_MASK_ENV) +$(LocalDebuggerEnvironment) + + + $(MONO_EXECUTABLE) + WindowsLocalDebugger + $(MONO_TESTDRIVER_RUN_ARGS) + $(MONO_TESTDRIVER_TEST_DIR) + $(MONO_PATH_ENV) +$(MONO_CFG_DIR_ENV) +$(MONO_TOOLCHAIN_PATH_ENV) +$(MONO_LOG_LEVEL_ENV) +$(MONO_LOG_MASK_ENV) +$(LocalDebuggerEnvironment) + + + $(MONO_EXECUTABLE) + WindowsLocalDebugger + $(MONO_TESTDRIVER_RUN_ARGS) + $(MONO_TESTDRIVER_TEST_DIR) + $(MONO_PATH_ENV) +$(MONO_CFG_DIR_ENV) +$(MONO_TOOLCHAIN_PATH_ENV) +$(MONO_LOG_LEVEL_ENV) +$(MONO_LOG_MASK_ENV) +$(LocalDebuggerEnvironment) + + + + Level3 + Disabled + true + + + test-config-setup.bat "$(MONO_CONFIG_PATH)" "$(MONO_EXECUTABLE_DIR)" x86 + + + + + Level3 + Disabled + true + + + test-config-setup.bat "$(MONO_CONFIG_PATH)" "$(MONO_EXECUTABLE_DIR)" x86-64 + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + test-config-setup.bat "$(MONO_CONFIG_PATH)" "$(MONO_EXECUTABLE_DIR)" x86 + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + test-config-setup.bat "$(MONO_CONFIG_PATH)" "$(MONO_EXECUTABLE_DIR)" x86-64 + + + + + + \ No newline at end of file diff --git a/msvc/mono.def b/msvc/mono.def index cec505f17e..f5a0e9ab98 100644 --- a/msvc/mono.def +++ b/msvc/mono.def @@ -1,5 +1,4 @@ ; file generated by create-windef.pl -LIBRARY mono-2.0.dll EXPORTS MonoFixupCorEE mono_add_internal_call @@ -242,6 +241,7 @@ mono_disasm_code mono_disasm_code_one mono_dl_fallback_register mono_dl_fallback_unregister +mono_dl_open mono_dllmap_insert mono_domain_add_class_static_data mono_domain_assembly_open @@ -424,6 +424,7 @@ mono_get_uint64_class mono_get_uintptr_class mono_get_void_class mono_guid_to_string +mono_guid_to_string_minimal mono_image_add_to_name_cache mono_image_addref mono_image_close @@ -495,6 +496,7 @@ mono_ldstr mono_ldtoken mono_load_remote_field mono_load_remote_field_new +mono_loader_register_module mono_lock_free_alloc mono_lock_free_allocator_check_consistency mono_lock_free_allocator_init_allocator @@ -506,6 +508,12 @@ mono_lock_free_queue_init mono_lock_free_queue_node_init mono_lock_free_queue_node_unpoison mono_locks_dump +mono_log_close_logfile +mono_log_close_syslog +mono_log_open_logfile +mono_log_open_syslog +mono_log_write_logfile +mono_log_write_syslog mono_lookup_icall_symbol mono_lookup_internal_call mono_lookup_pinvoke_call @@ -770,6 +778,7 @@ mono_security_core_clr_require_elevated_permissions mono_security_core_clr_set_options mono_security_enable_core_clr mono_security_set_core_clr_platform_callback +mono_set_allocator_vtable mono_set_assemblies_path mono_set_break_policy mono_set_config_dir @@ -853,14 +862,20 @@ mono_threads_attach_coop mono_threads_attach_tools_thread mono_threads_detach_coop mono_threads_enter_gc_safe_region +mono_threads_enter_gc_safe_region_unbalanced mono_threads_enter_gc_unsafe_region +mono_threads_enter_gc_unsafe_region_unbalanced mono_threads_exit_gc_safe_region +mono_threads_exit_gc_safe_region_unbalanced mono_threads_exit_gc_unsafe_region +mono_threads_exit_gc_unsafe_region_unbalanced mono_threads_get_default_stacksize mono_threads_request_thread_dump mono_threads_set_default_stacksize mono_trace_set_level_string mono_trace_set_log_handler +mono_trace_set_logdest_string +mono_trace_set_logheader_string mono_trace_set_mask_string mono_trace_set_print_handler mono_trace_set_printerr_handler diff --git a/msvc/mono.props b/msvc/mono.props index 23f0ec49c4..abc81a55ab 100644 --- a/msvc/mono.props +++ b/msvc/mono.props @@ -1,21 +1,106 @@ - + - - $(MSBuildProjectDirectory)\.. - $(top_srcdir)\libgc\include - $(top_srcdir)\eglib\src - HAVE_BOEHM_GC - HAVE_SGEN_GC;HAVE_MOVING_COLLECTOR;HAVE_WRITE_BARRIERS + + + $(MSBuildProjectDirectory)/./build/ + + $(MSBuildProjectDirectory)/./dist/ + + sgen + + true + + true + + false + + false + + $(MSBuildProjectDirectory)/.. + $(top_srcdir) + $(MONO_DIR)/mono + $(MONO_DIR)/eglib;$(MONO_DIR)/eglib/include;$(MONO_DIR)/eglib/test + $(MONO_DIR)/eglib/src + $(MONO_DIR)/libgc/include + $(MONO_DIR)/libgc/src + $(MONO_INCLUDE_DIR)/jit + $(MONO_INCLUDE_DIR)/jit + $(MONO_LIBGC_INCLUDE_DIR) + $(MONO_EGLIB_SOURCE_DIR) + + + MultiThreadedDebug + MultiThreaded + + + MultiThreadedDebugDLL + MultiThreadedDLL + + + HAVE_SGEN_GC;HAVE_MOVING_COLLECTOR;HAVE_WRITE_BARRIERS + $(SGEN_DEFINES) + libgcmonosgen.lib + monosgen.def + -sgen + $(MONO_BUILD_DIR_PREFIX)sgen/ + + + HAVE_BOEHM_GC + $(BOEHM_DEFINES) + libgc.lib + mono.def + -boehm + $(MONO_BUILD_DIR_PREFIX)boehm/ + + + libmonoutils.lib;libmonoruntime$(MONO_TARGET_SUFFIX).lib;$(GC_LIB) + libmono-static$(MONO_TARGET_SUFFIX).lib;$(MONO_RUNTIME_LIBS) + mono-2.0$(MONO_TARGET_SUFFIX).lib + + + $(MONO_STATIC_LIBMONO_LIB) + + + $(MONO_DYNAMIC_LIBMONO_LIB) + + + $(ProgramFiles)/Intel/VTune Amplifier XE 2013/include + + + + $(MONO_BUILD_DIR_PREFIX) + + + $(MONO_INSTALL_DIR_PREFIX) + + + $(MONO_TARGET_GC) + + + $(MONO_USE_TARGET_SUFFIX) + + + $(MONO_USE_SEPARATE_BUILD_DIR) + + + $(MONO_USE_STATIC_C_RUNTIME) + + + $(MONO_USE_STATIC_LIBMONO) + + MONO_DLL_EXPORT MONO_DLL_IMPORT - __default_codegen__;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;HAVE_CONFIG_H;GC_NOT_DLL;WIN32_THREADS;WINVER=0x0600;_WIN32_WINNT=0x0600;_WIN32_IE=0x0501;_UNICODE;UNICODE;WIN32_THREADS;FD_SETSIZE=1024;$(PreprocessorDefinitions);_WINSOCKAPI_ - 4273;4005 + __default_codegen__;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;HAVE_CONFIG_H;GC_NOT_DLL;WIN32_THREADS;WINVER=0x0600;_WIN32_WINNT=0x0600;_WIN32_IE=0x0501;_UNICODE;UNICODE;FD_SETSIZE=1024;%(PreprocessorDefinitions); + 4273;4005 + $(MONO_C_RUNTIME) - Mswsock.lib;ws2_32.lib;ole32.lib;oleaut32.lib;psapi.lib;version.lib;advapi32.lib;winmm.lib;kernel32.lib;$(AdditionalDependencies) + Mswsock.lib;ws2_32.lib;ole32.lib;oleaut32.lib;psapi.lib;version.lib;advapi32.lib;winmm.lib;kernel32.lib;%(AdditionalDependencies) + $(MONO_BUILD_DIR_PREFIX)$(Platform)/lib/$(Configuration) - - + + \ No newline at end of file diff --git a/msvc/mono.sln b/msvc/mono.sln index 17660be4ef..0dcd61f4c5 100644 --- a/msvc/mono.sln +++ b/msvc/mono.sln @@ -1,6 +1,8 @@ -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Embedded Samples", "Embedded Samples", "{5FE09AA5-C3C9-45EA-A323-36A11B653CEC}" +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25123.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "EmbeddedSamples", "EmbeddedSamples", "{5FE09AA5-C3C9-45EA-A323-36A11B653CEC}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools", "Tools", "{EE2CC761-9652-44AC-9204-7EB31194CAA6}" EndProject @@ -10,297 +12,423 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{ECA11C76 EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "genmdesc", "genmdesc.vcxproj", "{B7098DFA-31E6-4006-8A15-1C9A4E925149}" ProjectSection(ProjectDependencies) = postProject - {8FC2B0C8-51AD-49DF-851F-5D01A77A75E4} = {8FC2B0C8-51AD-49DF-851F-5D01A77A75E4} + {158073ED-99AE-4196-9EDC-DDB2344F8466} = {158073ED-99AE-4196-9EDC-DDB2344F8466} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libmono", "libmono.vcxproj", "{CB0D9E92-293C-439C-9AC7-C5F59B6E0771}" ProjectSection(ProjectDependencies) = postProject + {EB56000B-C80B-4E8B-908D-D84D31B517D3} = {EB56000B-C80B-4E8B-908D-D84D31B517D3} {C36612BD-22D3-4B95-85E2-7FDC4FC5D739} = {C36612BD-22D3-4B95-85E2-7FDC4FC5D739} {8FC2B0C8-51AD-49DF-851F-5D01A77A75E4} = {8FC2B0C8-51AD-49DF-851F-5D01A77A75E4} + {158073ED-99AE-4196-9EDC-DDB2344F8466} = {158073ED-99AE-4196-9EDC-DDB2344F8466} + {B7098DFA-31E6-4006-8A15-1C9A4E925149} = {B7098DFA-31E6-4006-8A15-1C9A4E925149} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test-invoke", "test-invoke.vcxproj", "{C5639B3F-288A-4A4B-A4A5-C0D85834221D}" + ProjectSection(ProjectDependencies) = postProject + {CB0D9E92-293C-439C-9AC7-C5F59B6E0771} = {CB0D9E92-293C-439C-9AC7-C5F59B6E0771} + {158073ED-99AE-4196-9EDC-DDB2344F8466} = {158073ED-99AE-4196-9EDC-DDB2344F8466} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "teste", "teste.vcxproj", "{6FDE4E5E-57D0-432F-A987-6C226A7827E4}" + ProjectSection(ProjectDependencies) = postProject + {CB0D9E92-293C-439C-9AC7-C5F59B6E0771} = {CB0D9E92-293C-439C-9AC7-C5F59B6E0771} + {158073ED-99AE-4196-9EDC-DDB2344F8466} = {158073ED-99AE-4196-9EDC-DDB2344F8466} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mono", "mono.vcxproj", "{A0EDDCD9-940F-432C-A28F-7EF322437D79}" + ProjectSection(ProjectDependencies) = postProject + {CB0D9E92-293C-439C-9AC7-C5F59B6E0771} = {CB0D9E92-293C-439C-9AC7-C5F59B6E0771} + {158073ED-99AE-4196-9EDC-DDB2344F8466} = {158073ED-99AE-4196-9EDC-DDB2344F8466} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgc", "libgc.vcxproj", "{EB56000B-C80B-4E8B-908D-D84D31B517D3}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "monodis", "monodis.vcxproj", "{37F50E5A-4818-46CF-81FE-4BB06DE5D42E}" + ProjectSection(ProjectDependencies) = postProject + {CB0D9E92-293C-439C-9AC7-C5F59B6E0771} = {CB0D9E92-293C-439C-9AC7-C5F59B6E0771} + {158073ED-99AE-4196-9EDC-DDB2344F8466} = {158073ED-99AE-4196-9EDC-DDB2344F8466} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pedump", "pedump.vcxproj", "{84C7DB50-D6F8-4C47-B22C-6BB203AEB4D3}" + ProjectSection(ProjectDependencies) = postProject + {CB0D9E92-293C-439C-9AC7-C5F59B6E0771} = {CB0D9E92-293C-439C-9AC7-C5F59B6E0771} + {158073ED-99AE-4196-9EDC-DDB2344F8466} = {158073ED-99AE-4196-9EDC-DDB2344F8466} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "monograph", "monograph.vcxproj", "{CA2A69D6-3B9D-45A5-8BF7-4E242E683122}" + ProjectSection(ProjectDependencies) = postProject + {CB0D9E92-293C-439C-9AC7-C5F59B6E0771} = {CB0D9E92-293C-439C-9AC7-C5F59B6E0771} + {158073ED-99AE-4196-9EDC-DDB2344F8466} = {158073ED-99AE-4196-9EDC-DDB2344F8466} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test-metadata", "test-metadata.vcxproj", "{C2EB666E-9146-4B7A-85F6-25F9EA313770}" + ProjectSection(ProjectDependencies) = postProject + {CB0D9E92-293C-439C-9AC7-C5F59B6E0771} = {CB0D9E92-293C-439C-9AC7-C5F59B6E0771} + {158073ED-99AE-4196-9EDC-DDB2344F8466} = {158073ED-99AE-4196-9EDC-DDB2344F8466} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "eglib", "eglib.vcxproj", "{158073ED-99AE-4196-9EDC-DDB2344F8466}" + ProjectSection(ProjectDependencies) = postProject + {92AE7622-5F58-4234-9A26-9EC71876B3F4} = {92AE7622-5F58-4234-9A26-9EC71876B3F4} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_eglib", "test_eglib.vcxproj", "{80A0620A-3478-4E1A-AA7C-0D2387B892AB}" + ProjectSection(ProjectDependencies) = postProject + {CB0D9E92-293C-439C-9AC7-C5F59B6E0771} = {CB0D9E92-293C-439C-9AC7-C5F59B6E0771} + {158073ED-99AE-4196-9EDC-DDB2344F8466} = {158073ED-99AE-4196-9EDC-DDB2344F8466} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libtest", "libtest.vcxproj", "{5A435710-E6D2-4DD4-9B3F-A7239A32C6F4}" + ProjectSection(ProjectDependencies) = postProject + {CB0D9E92-293C-439C-9AC7-C5F59B6E0771} = {CB0D9E92-293C-439C-9AC7-C5F59B6E0771} + {158073ED-99AE-4196-9EDC-DDB2344F8466} = {158073ED-99AE-4196-9EDC-DDB2344F8466} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "monoposixhelper", "monoposixhelper.vcxproj", "{33014734-0F46-4099-9A21-0C989E428681}" + ProjectSection(ProjectDependencies) = postProject + {158073ED-99AE-4196-9EDC-DDB2344F8466} = {158073ED-99AE-4196-9EDC-DDB2344F8466} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jay", "..\mcs\jay\jay.vcxproj", "{5D485D32-3B9F-4287-AB24-C8DA5B89F537}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Profilers", "Profilers", "{4CFD7702-60B2-4E82-BFAD-FCBB53EB4DA2}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "profiler-vtune", "profiler-vtune.vcxproj", "{F51017F9-B7FB-4F87-B7B5-12799D965783}" + ProjectSection(ProjectDependencies) = postProject + {CB0D9E92-293C-439C-9AC7-C5F59B6E0771} = {CB0D9E92-293C-439C-9AC7-C5F59B6E0771} + {158073ED-99AE-4196-9EDC-DDB2344F8466} = {158073ED-99AE-4196-9EDC-DDB2344F8466} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libmonoutils", "libmonoutils.vcxproj", "{8FC2B0C8-51AD-49DF-851F-5D01A77A75E4}" + ProjectSection(ProjectDependencies) = postProject + {158073ED-99AE-4196-9EDC-DDB2344F8466} = {158073ED-99AE-4196-9EDC-DDB2344F8466} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libmonoruntime", "libmonoruntime.vcxproj", "{C36612BD-22D3-4B95-85E2-7FDC4FC5D739}" + ProjectSection(ProjectDependencies) = postProject + {158073ED-99AE-4196-9EDC-DDB2344F8466} = {158073ED-99AE-4196-9EDC-DDB2344F8466} + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Runtime", "Runtime", "{DE3617B4-17A8-4E5F-A00F-BA43D956881F}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "BuildTargets", "BuildTargets", "{DC782E23-920A-4873-82A7-37F195FB92C1}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "build-all", "build-all.vcxproj", "{5362490B-8516-44EE-9987-014C015A080A}" + ProjectSection(ProjectDependencies) = postProject + {80A0620A-3478-4E1A-AA7C-0D2387B892AB} = {80A0620A-3478-4E1A-AA7C-0D2387B892AB} + {EB56000B-C80B-4E8B-908D-D84D31B517D3} = {EB56000B-C80B-4E8B-908D-D84D31B517D3} + {5A435710-E6D2-4DD4-9B3F-A7239A32C6F4} = {5A435710-E6D2-4DD4-9B3F-A7239A32C6F4} + {5D485D32-3B9F-4287-AB24-C8DA5B89F537} = {5D485D32-3B9F-4287-AB24-C8DA5B89F537} + {33014734-0F46-4099-9A21-0C989E428681} = {33014734-0F46-4099-9A21-0C989E428681} + {C5639B3F-288A-4A4B-A4A5-C0D85834221D} = {C5639B3F-288A-4A4B-A4A5-C0D85834221D} + {84C7DB50-D6F8-4C47-B22C-6BB203AEB4D3} = {84C7DB50-D6F8-4C47-B22C-6BB203AEB4D3} + {37F50E5A-4818-46CF-81FE-4BB06DE5D42E} = {37F50E5A-4818-46CF-81FE-4BB06DE5D42E} + {6FDE4E5E-57D0-432F-A987-6C226A7827E4} = {6FDE4E5E-57D0-432F-A987-6C226A7827E4} + {C2EB666E-9146-4B7A-85F6-25F9EA313770} = {C2EB666E-9146-4B7A-85F6-25F9EA313770} + {CB0D9E92-293C-439C-9AC7-C5F59B6E0771} = {CB0D9E92-293C-439C-9AC7-C5F59B6E0771} + {C36612BD-22D3-4B95-85E2-7FDC4FC5D739} = {C36612BD-22D3-4B95-85E2-7FDC4FC5D739} + {8FC2B0C8-51AD-49DF-851F-5D01A77A75E4} = {8FC2B0C8-51AD-49DF-851F-5D01A77A75E4} + {CA2A69D6-3B9D-45A5-8BF7-4E242E683122} = {CA2A69D6-3B9D-45A5-8BF7-4E242E683122} + {A0EDDCD9-940F-432C-A28F-7EF322437D79} = {A0EDDCD9-940F-432C-A28F-7EF322437D79} + {158073ED-99AE-4196-9EDC-DDB2344F8466} = {158073ED-99AE-4196-9EDC-DDB2344F8466} + {F51017F9-B7FB-4F87-B7B5-12799D965783} = {F51017F9-B7FB-4F87-B7B5-12799D965783} + {B7098DFA-31E6-4006-8A15-1C9A4E925149} = {B7098DFA-31E6-4006-8A15-1C9A4E925149} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "build-init", "build-init.vcxproj", "{92AE7622-5F58-4234-9A26-9EC71876B3F4}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "build-install", "build-install.vcxproj", "{A9DC644B-9171-4FCD-BF21-2CC6D055FC40}" + ProjectSection(ProjectDependencies) = postProject + {B6E563B8-7F57-4F7F-9439-F2405D4E2522} = {B6E563B8-7F57-4F7F-9439-F2405D4E2522} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "build-package", "build-package.vcxproj", "{B6E563B8-7F57-4F7F-9439-F2405D4E2522}" + ProjectSection(ProjectDependencies) = postProject + {5362490B-8516-44EE-9987-014C015A080A} = {5362490B-8516-44EE-9987-014C015A080A} + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "GC", "GC", "{21DF4C80-0EC9-4BFE-8552-2D47FCEF419A}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgcmonosgen", "libgcmonosgen.vcxproj", "{C36612BD-22D3-4B95-85E2-7FDC4FC5D740}" + ProjectSection(ProjectDependencies) = postProject + {92AE7622-5F58-4234-9A26-9EC71876B3F4} = {92AE7622-5F58-4234-9A26-9EC71876B3F4} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mono-mini-regression-test", "mono-mini-regression-test.vcxproj", "{3E0D229E-C39F-4EDA-9A6A-A33ECEA0322D}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "jit", "jit", "{A0068765-334B-414C-8E21-8376CD2EC9F6}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libmono-static", "libmono-static.vcxproj", "{CB0D9E92-293C-439C-9AC7-C5F59B6E0772}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "full-aot", "full-aot", "{BACF489E-EAEB-42BF-9E0A-C54D7CF455B4}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mono-full-aot-compile-test", "mono-full-aot-compile-test.vcxproj", "{C7D83158-4EB6-4409-8730-612AD45FAF6A}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mono-full-aot-run-test", "mono-full-aot-run-test.vcxproj", "{6C64262B-077B-4E12-AF91-9409ECCB75F6}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mono-testdriver-test", "mono-testdriver-test.vcxproj", "{7BECCFA0-28A0-4995-9856-558560F720E6}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mono-nunit-test", "mono-nunit-test.vcxproj", "{0046B994-40A8-4C64-AC9D-429DC9177B54}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug_SGen|Win32 = Debug_SGen|Win32 - Debug_SGen|x64 = Debug_SGen|x64 Debug|Win32 = Debug|Win32 Debug|x64 = Debug|x64 - Release_SGen|Win32 = Release_SGen|Win32 - Release_SGen|x64 = Release_SGen|x64 Release|Win32 = Release|Win32 Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {B7098DFA-31E6-4006-8A15-1C9A4E925149}.Debug_SGen|Win32.ActiveCfg = Debug|Win32 - {B7098DFA-31E6-4006-8A15-1C9A4E925149}.Debug_SGen|x64.ActiveCfg = Debug|x64 - {B7098DFA-31E6-4006-8A15-1C9A4E925149}.Debug_SGen|x64.Build.0 = Debug|x64 {B7098DFA-31E6-4006-8A15-1C9A4E925149}.Debug|Win32.ActiveCfg = Debug|Win32 {B7098DFA-31E6-4006-8A15-1C9A4E925149}.Debug|Win32.Build.0 = Debug|Win32 {B7098DFA-31E6-4006-8A15-1C9A4E925149}.Debug|x64.ActiveCfg = Debug|x64 {B7098DFA-31E6-4006-8A15-1C9A4E925149}.Debug|x64.Build.0 = Debug|x64 - {B7098DFA-31E6-4006-8A15-1C9A4E925149}.Release_SGen|Win32.ActiveCfg = Release|Win32 - {B7098DFA-31E6-4006-8A15-1C9A4E925149}.Release_SGen|Win32.Build.0 = Release|Win32 - {B7098DFA-31E6-4006-8A15-1C9A4E925149}.Release_SGen|x64.ActiveCfg = Release|x64 - {B7098DFA-31E6-4006-8A15-1C9A4E925149}.Release_SGen|x64.Build.0 = Release|x64 {B7098DFA-31E6-4006-8A15-1C9A4E925149}.Release|Win32.ActiveCfg = Release|Win32 {B7098DFA-31E6-4006-8A15-1C9A4E925149}.Release|Win32.Build.0 = Release|Win32 {B7098DFA-31E6-4006-8A15-1C9A4E925149}.Release|x64.ActiveCfg = Release|x64 {B7098DFA-31E6-4006-8A15-1C9A4E925149}.Release|x64.Build.0 = Release|x64 - {CB0D9E92-293C-439C-9AC7-C5F59B6E0771}.Debug_SGen|Win32.ActiveCfg = Debug_SGen|Win32 - {CB0D9E92-293C-439C-9AC7-C5F59B6E0771}.Debug_SGen|Win32.Build.0 = Debug_SGen|Win32 - {CB0D9E92-293C-439C-9AC7-C5F59B6E0771}.Debug_SGen|x64.ActiveCfg = Debug_SGen|x64 - {CB0D9E92-293C-439C-9AC7-C5F59B6E0771}.Debug_SGen|x64.Build.0 = Debug_SGen|x64 {CB0D9E92-293C-439C-9AC7-C5F59B6E0771}.Debug|Win32.ActiveCfg = Debug|Win32 {CB0D9E92-293C-439C-9AC7-C5F59B6E0771}.Debug|Win32.Build.0 = Debug|Win32 {CB0D9E92-293C-439C-9AC7-C5F59B6E0771}.Debug|x64.ActiveCfg = Debug|x64 {CB0D9E92-293C-439C-9AC7-C5F59B6E0771}.Debug|x64.Build.0 = Debug|x64 - {CB0D9E92-293C-439C-9AC7-C5F59B6E0771}.Release_SGen|Win32.ActiveCfg = Release_SGen|Win32 - {CB0D9E92-293C-439C-9AC7-C5F59B6E0771}.Release_SGen|Win32.Build.0 = Release_SGen|Win32 - {CB0D9E92-293C-439C-9AC7-C5F59B6E0771}.Release_SGen|x64.ActiveCfg = Release_SGen|x64 - {CB0D9E92-293C-439C-9AC7-C5F59B6E0771}.Release_SGen|x64.Build.0 = Release_SGen|x64 {CB0D9E92-293C-439C-9AC7-C5F59B6E0771}.Release|Win32.ActiveCfg = Release|Win32 {CB0D9E92-293C-439C-9AC7-C5F59B6E0771}.Release|Win32.Build.0 = Release|Win32 {CB0D9E92-293C-439C-9AC7-C5F59B6E0771}.Release|x64.ActiveCfg = Release|x64 {CB0D9E92-293C-439C-9AC7-C5F59B6E0771}.Release|x64.Build.0 = Release|x64 - {C5639B3F-288A-4A4B-A4A5-C0D85834221D}.Debug_SGen|Win32.ActiveCfg = Debug|Win32 - {C5639B3F-288A-4A4B-A4A5-C0D85834221D}.Debug_SGen|x64.ActiveCfg = Debug|x64 {C5639B3F-288A-4A4B-A4A5-C0D85834221D}.Debug|Win32.ActiveCfg = Debug|Win32 + {C5639B3F-288A-4A4B-A4A5-C0D85834221D}.Debug|Win32.Build.0 = Debug|Win32 {C5639B3F-288A-4A4B-A4A5-C0D85834221D}.Debug|x64.ActiveCfg = Debug|x64 - {C5639B3F-288A-4A4B-A4A5-C0D85834221D}.Release_SGen|Win32.ActiveCfg = Release|Win32 - {C5639B3F-288A-4A4B-A4A5-C0D85834221D}.Release_SGen|x64.ActiveCfg = Release|x64 + {C5639B3F-288A-4A4B-A4A5-C0D85834221D}.Debug|x64.Build.0 = Debug|x64 {C5639B3F-288A-4A4B-A4A5-C0D85834221D}.Release|Win32.ActiveCfg = Release|Win32 + {C5639B3F-288A-4A4B-A4A5-C0D85834221D}.Release|Win32.Build.0 = Release|Win32 {C5639B3F-288A-4A4B-A4A5-C0D85834221D}.Release|x64.ActiveCfg = Release|x64 - {6FDE4E5E-57D0-432F-A987-6C226A7827E4}.Debug_SGen|Win32.ActiveCfg = Debug|Win32 - {6FDE4E5E-57D0-432F-A987-6C226A7827E4}.Debug_SGen|x64.ActiveCfg = Debug|x64 + {C5639B3F-288A-4A4B-A4A5-C0D85834221D}.Release|x64.Build.0 = Release|x64 {6FDE4E5E-57D0-432F-A987-6C226A7827E4}.Debug|Win32.ActiveCfg = Debug|Win32 + {6FDE4E5E-57D0-432F-A987-6C226A7827E4}.Debug|Win32.Build.0 = Debug|Win32 {6FDE4E5E-57D0-432F-A987-6C226A7827E4}.Debug|x64.ActiveCfg = Debug|x64 - {6FDE4E5E-57D0-432F-A987-6C226A7827E4}.Release_SGen|Win32.ActiveCfg = Release|Win32 - {6FDE4E5E-57D0-432F-A987-6C226A7827E4}.Release_SGen|x64.ActiveCfg = Release|x64 + {6FDE4E5E-57D0-432F-A987-6C226A7827E4}.Debug|x64.Build.0 = Debug|x64 {6FDE4E5E-57D0-432F-A987-6C226A7827E4}.Release|Win32.ActiveCfg = Release|Win32 + {6FDE4E5E-57D0-432F-A987-6C226A7827E4}.Release|Win32.Build.0 = Release|Win32 {6FDE4E5E-57D0-432F-A987-6C226A7827E4}.Release|x64.ActiveCfg = Release|x64 - {A0EDDCD9-940F-432C-A28F-7EF322437D79}.Debug_SGen|Win32.ActiveCfg = Debug_SGen|Win32 - {A0EDDCD9-940F-432C-A28F-7EF322437D79}.Debug_SGen|Win32.Build.0 = Debug_SGen|Win32 - {A0EDDCD9-940F-432C-A28F-7EF322437D79}.Debug_SGen|x64.ActiveCfg = Debug_SGen|x64 - {A0EDDCD9-940F-432C-A28F-7EF322437D79}.Debug_SGen|x64.Build.0 = Debug_SGen|x64 + {6FDE4E5E-57D0-432F-A987-6C226A7827E4}.Release|x64.Build.0 = Release|x64 {A0EDDCD9-940F-432C-A28F-7EF322437D79}.Debug|Win32.ActiveCfg = Debug|Win32 {A0EDDCD9-940F-432C-A28F-7EF322437D79}.Debug|Win32.Build.0 = Debug|Win32 {A0EDDCD9-940F-432C-A28F-7EF322437D79}.Debug|x64.ActiveCfg = Debug|x64 {A0EDDCD9-940F-432C-A28F-7EF322437D79}.Debug|x64.Build.0 = Debug|x64 - {A0EDDCD9-940F-432C-A28F-7EF322437D79}.Release_SGen|Win32.ActiveCfg = Release_SGen|Win32 - {A0EDDCD9-940F-432C-A28F-7EF322437D79}.Release_SGen|Win32.Build.0 = Release_SGen|Win32 - {A0EDDCD9-940F-432C-A28F-7EF322437D79}.Release_SGen|x64.ActiveCfg = Release_SGen|x64 - {A0EDDCD9-940F-432C-A28F-7EF322437D79}.Release_SGen|x64.Build.0 = Release_SGen|x64 {A0EDDCD9-940F-432C-A28F-7EF322437D79}.Release|Win32.ActiveCfg = Release|Win32 {A0EDDCD9-940F-432C-A28F-7EF322437D79}.Release|Win32.Build.0 = Release|Win32 {A0EDDCD9-940F-432C-A28F-7EF322437D79}.Release|x64.ActiveCfg = Release|x64 {A0EDDCD9-940F-432C-A28F-7EF322437D79}.Release|x64.Build.0 = Release|x64 - {EB56000B-C80B-4E8B-908D-D84D31B517D3}.Debug_SGen|Win32.ActiveCfg = Debug|Win32 - {EB56000B-C80B-4E8B-908D-D84D31B517D3}.Debug_SGen|x64.ActiveCfg = Debug|x64 - {EB56000B-C80B-4E8B-908D-D84D31B517D3}.Debug_SGen|x64.Build.0 = Debug|x64 {EB56000B-C80B-4E8B-908D-D84D31B517D3}.Debug|Win32.ActiveCfg = Debug|Win32 {EB56000B-C80B-4E8B-908D-D84D31B517D3}.Debug|Win32.Build.0 = Debug|Win32 {EB56000B-C80B-4E8B-908D-D84D31B517D3}.Debug|x64.ActiveCfg = Debug|x64 {EB56000B-C80B-4E8B-908D-D84D31B517D3}.Debug|x64.Build.0 = Debug|x64 - {EB56000B-C80B-4E8B-908D-D84D31B517D3}.Release_SGen|Win32.ActiveCfg = Release|Win32 - {EB56000B-C80B-4E8B-908D-D84D31B517D3}.Release_SGen|Win32.Build.0 = Release|Win32 - {EB56000B-C80B-4E8B-908D-D84D31B517D3}.Release_SGen|x64.ActiveCfg = Release|x64 - {EB56000B-C80B-4E8B-908D-D84D31B517D3}.Release_SGen|x64.Build.0 = Release|x64 {EB56000B-C80B-4E8B-908D-D84D31B517D3}.Release|Win32.ActiveCfg = Release|Win32 {EB56000B-C80B-4E8B-908D-D84D31B517D3}.Release|Win32.Build.0 = Release|Win32 {EB56000B-C80B-4E8B-908D-D84D31B517D3}.Release|x64.ActiveCfg = Release|x64 {EB56000B-C80B-4E8B-908D-D84D31B517D3}.Release|x64.Build.0 = Release|x64 - {37F50E5A-4818-46CF-81FE-4BB06DE5D42E}.Debug_SGen|Win32.ActiveCfg = Debug|Win32 - {37F50E5A-4818-46CF-81FE-4BB06DE5D42E}.Debug_SGen|x64.ActiveCfg = Debug|x64 {37F50E5A-4818-46CF-81FE-4BB06DE5D42E}.Debug|Win32.ActiveCfg = Debug|Win32 + {37F50E5A-4818-46CF-81FE-4BB06DE5D42E}.Debug|Win32.Build.0 = Debug|Win32 {37F50E5A-4818-46CF-81FE-4BB06DE5D42E}.Debug|x64.ActiveCfg = Debug|x64 - {37F50E5A-4818-46CF-81FE-4BB06DE5D42E}.Release_SGen|Win32.ActiveCfg = Release|Win32 - {37F50E5A-4818-46CF-81FE-4BB06DE5D42E}.Release_SGen|x64.ActiveCfg = Release|x64 + {37F50E5A-4818-46CF-81FE-4BB06DE5D42E}.Debug|x64.Build.0 = Debug|x64 {37F50E5A-4818-46CF-81FE-4BB06DE5D42E}.Release|Win32.ActiveCfg = Release|Win32 + {37F50E5A-4818-46CF-81FE-4BB06DE5D42E}.Release|Win32.Build.0 = Release|Win32 {37F50E5A-4818-46CF-81FE-4BB06DE5D42E}.Release|x64.ActiveCfg = Release|x64 - {84C7DB50-D6F8-4C47-B22C-6BB203AEB4D3}.Debug_SGen|Win32.ActiveCfg = Debug|Win32 - {84C7DB50-D6F8-4C47-B22C-6BB203AEB4D3}.Debug_SGen|x64.ActiveCfg = Debug|x64 + {37F50E5A-4818-46CF-81FE-4BB06DE5D42E}.Release|x64.Build.0 = Release|x64 {84C7DB50-D6F8-4C47-B22C-6BB203AEB4D3}.Debug|Win32.ActiveCfg = Debug|Win32 + {84C7DB50-D6F8-4C47-B22C-6BB203AEB4D3}.Debug|Win32.Build.0 = Debug|Win32 {84C7DB50-D6F8-4C47-B22C-6BB203AEB4D3}.Debug|x64.ActiveCfg = Debug|x64 - {84C7DB50-D6F8-4C47-B22C-6BB203AEB4D3}.Release_SGen|Win32.ActiveCfg = Release|Win32 - {84C7DB50-D6F8-4C47-B22C-6BB203AEB4D3}.Release_SGen|x64.ActiveCfg = Release|x64 + {84C7DB50-D6F8-4C47-B22C-6BB203AEB4D3}.Debug|x64.Build.0 = Debug|x64 {84C7DB50-D6F8-4C47-B22C-6BB203AEB4D3}.Release|Win32.ActiveCfg = Release|Win32 + {84C7DB50-D6F8-4C47-B22C-6BB203AEB4D3}.Release|Win32.Build.0 = Release|Win32 {84C7DB50-D6F8-4C47-B22C-6BB203AEB4D3}.Release|x64.ActiveCfg = Release|x64 - {CA2A69D6-3B9D-45A5-8BF7-4E242E683122}.Debug_SGen|Win32.ActiveCfg = Debug|Win32 - {CA2A69D6-3B9D-45A5-8BF7-4E242E683122}.Debug_SGen|x64.ActiveCfg = Debug|x64 + {84C7DB50-D6F8-4C47-B22C-6BB203AEB4D3}.Release|x64.Build.0 = Release|x64 {CA2A69D6-3B9D-45A5-8BF7-4E242E683122}.Debug|Win32.ActiveCfg = Debug|Win32 + {CA2A69D6-3B9D-45A5-8BF7-4E242E683122}.Debug|Win32.Build.0 = Debug|Win32 {CA2A69D6-3B9D-45A5-8BF7-4E242E683122}.Debug|x64.ActiveCfg = Debug|x64 - {CA2A69D6-3B9D-45A5-8BF7-4E242E683122}.Release_SGen|Win32.ActiveCfg = Release|Win32 - {CA2A69D6-3B9D-45A5-8BF7-4E242E683122}.Release_SGen|x64.ActiveCfg = Release|x64 + {CA2A69D6-3B9D-45A5-8BF7-4E242E683122}.Debug|x64.Build.0 = Debug|x64 {CA2A69D6-3B9D-45A5-8BF7-4E242E683122}.Release|Win32.ActiveCfg = Release|Win32 + {CA2A69D6-3B9D-45A5-8BF7-4E242E683122}.Release|Win32.Build.0 = Release|Win32 {CA2A69D6-3B9D-45A5-8BF7-4E242E683122}.Release|x64.ActiveCfg = Release|x64 - {C2EB666E-9146-4B7A-85F6-25F9EA313770}.Debug_SGen|Win32.ActiveCfg = Debug|Win32 - {C2EB666E-9146-4B7A-85F6-25F9EA313770}.Debug_SGen|x64.ActiveCfg = Debug|x64 + {CA2A69D6-3B9D-45A5-8BF7-4E242E683122}.Release|x64.Build.0 = Release|x64 {C2EB666E-9146-4B7A-85F6-25F9EA313770}.Debug|Win32.ActiveCfg = Debug|Win32 + {C2EB666E-9146-4B7A-85F6-25F9EA313770}.Debug|Win32.Build.0 = Debug|Win32 {C2EB666E-9146-4B7A-85F6-25F9EA313770}.Debug|x64.ActiveCfg = Debug|x64 - {C2EB666E-9146-4B7A-85F6-25F9EA313770}.Release_SGen|Win32.ActiveCfg = Release|Win32 - {C2EB666E-9146-4B7A-85F6-25F9EA313770}.Release_SGen|x64.ActiveCfg = Release|x64 + {C2EB666E-9146-4B7A-85F6-25F9EA313770}.Debug|x64.Build.0 = Debug|x64 {C2EB666E-9146-4B7A-85F6-25F9EA313770}.Release|Win32.ActiveCfg = Release|Win32 + {C2EB666E-9146-4B7A-85F6-25F9EA313770}.Release|Win32.Build.0 = Release|Win32 {C2EB666E-9146-4B7A-85F6-25F9EA313770}.Release|x64.ActiveCfg = Release|x64 - {158073ED-99AE-4196-9EDC-DDB2344F8466}.Debug_SGen|Win32.ActiveCfg = Debug|Win32 - {158073ED-99AE-4196-9EDC-DDB2344F8466}.Debug_SGen|x64.ActiveCfg = Debug|x64 - {158073ED-99AE-4196-9EDC-DDB2344F8466}.Debug_SGen|x64.Build.0 = Debug|x64 + {C2EB666E-9146-4B7A-85F6-25F9EA313770}.Release|x64.Build.0 = Release|x64 {158073ED-99AE-4196-9EDC-DDB2344F8466}.Debug|Win32.ActiveCfg = Debug|Win32 {158073ED-99AE-4196-9EDC-DDB2344F8466}.Debug|Win32.Build.0 = Debug|Win32 {158073ED-99AE-4196-9EDC-DDB2344F8466}.Debug|x64.ActiveCfg = Debug|x64 {158073ED-99AE-4196-9EDC-DDB2344F8466}.Debug|x64.Build.0 = Debug|x64 - {158073ED-99AE-4196-9EDC-DDB2344F8466}.Release_SGen|Win32.ActiveCfg = Release|Win32 - {158073ED-99AE-4196-9EDC-DDB2344F8466}.Release_SGen|Win32.Build.0 = Release|Win32 - {158073ED-99AE-4196-9EDC-DDB2344F8466}.Release_SGen|x64.ActiveCfg = Release|x64 - {158073ED-99AE-4196-9EDC-DDB2344F8466}.Release_SGen|x64.Build.0 = Release|x64 {158073ED-99AE-4196-9EDC-DDB2344F8466}.Release|Win32.ActiveCfg = Release|Win32 {158073ED-99AE-4196-9EDC-DDB2344F8466}.Release|Win32.Build.0 = Release|Win32 {158073ED-99AE-4196-9EDC-DDB2344F8466}.Release|x64.ActiveCfg = Release|x64 {158073ED-99AE-4196-9EDC-DDB2344F8466}.Release|x64.Build.0 = Release|x64 - {80A0620A-3478-4E1A-AA7C-0D2387B892AB}.Debug_SGen|Win32.ActiveCfg = Debug|Win32 - {80A0620A-3478-4E1A-AA7C-0D2387B892AB}.Debug_SGen|x64.ActiveCfg = Debug|x64 {80A0620A-3478-4E1A-AA7C-0D2387B892AB}.Debug|Win32.ActiveCfg = Debug|Win32 + {80A0620A-3478-4E1A-AA7C-0D2387B892AB}.Debug|Win32.Build.0 = Debug|Win32 {80A0620A-3478-4E1A-AA7C-0D2387B892AB}.Debug|x64.ActiveCfg = Debug|x64 - {80A0620A-3478-4E1A-AA7C-0D2387B892AB}.Release_SGen|Win32.ActiveCfg = Release|Win32 - {80A0620A-3478-4E1A-AA7C-0D2387B892AB}.Release_SGen|x64.ActiveCfg = Release|x64 + {80A0620A-3478-4E1A-AA7C-0D2387B892AB}.Debug|x64.Build.0 = Debug|x64 {80A0620A-3478-4E1A-AA7C-0D2387B892AB}.Release|Win32.ActiveCfg = Release|Win32 + {80A0620A-3478-4E1A-AA7C-0D2387B892AB}.Release|Win32.Build.0 = Release|Win32 {80A0620A-3478-4E1A-AA7C-0D2387B892AB}.Release|x64.ActiveCfg = Release|x64 - {5A435710-E6D2-4DD4-9B3F-A7239A32C6F4}.Debug_SGen|Win32.ActiveCfg = Debug|Win32 - {5A435710-E6D2-4DD4-9B3F-A7239A32C6F4}.Debug_SGen|x64.ActiveCfg = Debug|x64 - {5A435710-E6D2-4DD4-9B3F-A7239A32C6F4}.Debug_SGen|x64.Build.0 = Debug|x64 + {80A0620A-3478-4E1A-AA7C-0D2387B892AB}.Release|x64.Build.0 = Release|x64 {5A435710-E6D2-4DD4-9B3F-A7239A32C6F4}.Debug|Win32.ActiveCfg = Debug|Win32 {5A435710-E6D2-4DD4-9B3F-A7239A32C6F4}.Debug|Win32.Build.0 = Debug|Win32 {5A435710-E6D2-4DD4-9B3F-A7239A32C6F4}.Debug|x64.ActiveCfg = Debug|x64 {5A435710-E6D2-4DD4-9B3F-A7239A32C6F4}.Debug|x64.Build.0 = Debug|x64 - {5A435710-E6D2-4DD4-9B3F-A7239A32C6F4}.Release_SGen|Win32.ActiveCfg = Release|Win32 - {5A435710-E6D2-4DD4-9B3F-A7239A32C6F4}.Release_SGen|Win32.Build.0 = Release|Win32 - {5A435710-E6D2-4DD4-9B3F-A7239A32C6F4}.Release_SGen|x64.ActiveCfg = Release|x64 - {5A435710-E6D2-4DD4-9B3F-A7239A32C6F4}.Release_SGen|x64.Build.0 = Release|x64 {5A435710-E6D2-4DD4-9B3F-A7239A32C6F4}.Release|Win32.ActiveCfg = Release|Win32 {5A435710-E6D2-4DD4-9B3F-A7239A32C6F4}.Release|Win32.Build.0 = Release|Win32 {5A435710-E6D2-4DD4-9B3F-A7239A32C6F4}.Release|x64.ActiveCfg = Release|x64 {5A435710-E6D2-4DD4-9B3F-A7239A32C6F4}.Release|x64.Build.0 = Release|x64 - {33014734-0F46-4099-9A21-0C989E428681}.Debug_SGen|Win32.ActiveCfg = Debug|Win32 - {33014734-0F46-4099-9A21-0C989E428681}.Debug_SGen|x64.ActiveCfg = Debug|x64 - {33014734-0F46-4099-9A21-0C989E428681}.Debug_SGen|x64.Build.0 = Debug|x64 {33014734-0F46-4099-9A21-0C989E428681}.Debug|Win32.ActiveCfg = Debug|Win32 {33014734-0F46-4099-9A21-0C989E428681}.Debug|Win32.Build.0 = Debug|Win32 {33014734-0F46-4099-9A21-0C989E428681}.Debug|x64.ActiveCfg = Debug|x64 {33014734-0F46-4099-9A21-0C989E428681}.Debug|x64.Build.0 = Debug|x64 - {33014734-0F46-4099-9A21-0C989E428681}.Release_SGen|Win32.ActiveCfg = Release|Win32 - {33014734-0F46-4099-9A21-0C989E428681}.Release_SGen|Win32.Build.0 = Release|Win32 - {33014734-0F46-4099-9A21-0C989E428681}.Release_SGen|x64.ActiveCfg = Release|x64 - {33014734-0F46-4099-9A21-0C989E428681}.Release_SGen|x64.Build.0 = Release|x64 {33014734-0F46-4099-9A21-0C989E428681}.Release|Win32.ActiveCfg = Release|Win32 {33014734-0F46-4099-9A21-0C989E428681}.Release|Win32.Build.0 = Release|Win32 {33014734-0F46-4099-9A21-0C989E428681}.Release|x64.ActiveCfg = Release|x64 {33014734-0F46-4099-9A21-0C989E428681}.Release|x64.Build.0 = Release|x64 - {5D485D32-3B9F-4287-AB24-C8DA5B89F537}.Debug_SGen|Win32.ActiveCfg = Debug|Win32 - {5D485D32-3B9F-4287-AB24-C8DA5B89F537}.Debug_SGen|Win32.Build.0 = Debug|Win32 - {5D485D32-3B9F-4287-AB24-C8DA5B89F537}.Debug_SGen|x64.ActiveCfg = Debug|Win32 {5D485D32-3B9F-4287-AB24-C8DA5B89F537}.Debug|Win32.ActiveCfg = Debug|Win32 {5D485D32-3B9F-4287-AB24-C8DA5B89F537}.Debug|Win32.Build.0 = Debug|Win32 {5D485D32-3B9F-4287-AB24-C8DA5B89F537}.Debug|x64.ActiveCfg = Debug|Win32 - {5D485D32-3B9F-4287-AB24-C8DA5B89F537}.Release_SGen|Win32.ActiveCfg = Release|Win32 - {5D485D32-3B9F-4287-AB24-C8DA5B89F537}.Release_SGen|Win32.Build.0 = Release|Win32 - {5D485D32-3B9F-4287-AB24-C8DA5B89F537}.Release_SGen|x64.ActiveCfg = Release|Win32 {5D485D32-3B9F-4287-AB24-C8DA5B89F537}.Release|Win32.ActiveCfg = Release|Win32 {5D485D32-3B9F-4287-AB24-C8DA5B89F537}.Release|Win32.Build.0 = Release|Win32 {5D485D32-3B9F-4287-AB24-C8DA5B89F537}.Release|x64.ActiveCfg = Release|Win32 - {F51017F9-B7FB-4F87-B7B5-12799D965783}.Debug_SGen|Win32.ActiveCfg = Debug|Win32 - {F51017F9-B7FB-4F87-B7B5-12799D965783}.Debug_SGen|x64.ActiveCfg = Debug|x64 {F51017F9-B7FB-4F87-B7B5-12799D965783}.Debug|Win32.ActiveCfg = Debug|Win32 {F51017F9-B7FB-4F87-B7B5-12799D965783}.Debug|x64.ActiveCfg = Debug|x64 - {F51017F9-B7FB-4F87-B7B5-12799D965783}.Release_SGen|Win32.ActiveCfg = Release|Win32 - {F51017F9-B7FB-4F87-B7B5-12799D965783}.Release_SGen|x64.ActiveCfg = Release|x64 {F51017F9-B7FB-4F87-B7B5-12799D965783}.Release|Win32.ActiveCfg = Release|Win32 {F51017F9-B7FB-4F87-B7B5-12799D965783}.Release|x64.ActiveCfg = Release|x64 - {8FC2B0C8-51AD-49DF-851F-5D01A77A75E4}.Debug_SGen|Win32.ActiveCfg = Debug|Win32 - {8FC2B0C8-51AD-49DF-851F-5D01A77A75E4}.Debug_SGen|Win32.Build.0 = Debug|Win32 - {8FC2B0C8-51AD-49DF-851F-5D01A77A75E4}.Debug_SGen|x64.ActiveCfg = Debug|x64 - {8FC2B0C8-51AD-49DF-851F-5D01A77A75E4}.Debug_SGen|x64.Build.0 = Debug|x64 {8FC2B0C8-51AD-49DF-851F-5D01A77A75E4}.Debug|Win32.ActiveCfg = Debug|Win32 {8FC2B0C8-51AD-49DF-851F-5D01A77A75E4}.Debug|Win32.Build.0 = Debug|Win32 {8FC2B0C8-51AD-49DF-851F-5D01A77A75E4}.Debug|x64.ActiveCfg = Debug|x64 {8FC2B0C8-51AD-49DF-851F-5D01A77A75E4}.Debug|x64.Build.0 = Debug|x64 - {8FC2B0C8-51AD-49DF-851F-5D01A77A75E4}.Release_SGen|Win32.ActiveCfg = Release|Win32 - {8FC2B0C8-51AD-49DF-851F-5D01A77A75E4}.Release_SGen|Win32.Build.0 = Release|Win32 - {8FC2B0C8-51AD-49DF-851F-5D01A77A75E4}.Release_SGen|x64.ActiveCfg = Release|x64 - {8FC2B0C8-51AD-49DF-851F-5D01A77A75E4}.Release_SGen|x64.Build.0 = Release|x64 {8FC2B0C8-51AD-49DF-851F-5D01A77A75E4}.Release|Win32.ActiveCfg = Release|Win32 {8FC2B0C8-51AD-49DF-851F-5D01A77A75E4}.Release|Win32.Build.0 = Release|Win32 {8FC2B0C8-51AD-49DF-851F-5D01A77A75E4}.Release|x64.ActiveCfg = Release|x64 {8FC2B0C8-51AD-49DF-851F-5D01A77A75E4}.Release|x64.Build.0 = Release|x64 - {C36612BD-22D3-4B95-85E2-7FDC4FC5D739}.Debug_SGen|Win32.ActiveCfg = Debug_SGen|Win32 - {C36612BD-22D3-4B95-85E2-7FDC4FC5D739}.Debug_SGen|Win32.Build.0 = Debug_SGen|Win32 - {C36612BD-22D3-4B95-85E2-7FDC4FC5D739}.Debug_SGen|x64.ActiveCfg = Debug_SGen|x64 - {C36612BD-22D3-4B95-85E2-7FDC4FC5D739}.Debug_SGen|x64.Build.0 = Debug_SGen|x64 {C36612BD-22D3-4B95-85E2-7FDC4FC5D739}.Debug|Win32.ActiveCfg = Debug|Win32 {C36612BD-22D3-4B95-85E2-7FDC4FC5D739}.Debug|Win32.Build.0 = Debug|Win32 {C36612BD-22D3-4B95-85E2-7FDC4FC5D739}.Debug|x64.ActiveCfg = Debug|x64 {C36612BD-22D3-4B95-85E2-7FDC4FC5D739}.Debug|x64.Build.0 = Debug|x64 - {C36612BD-22D3-4B95-85E2-7FDC4FC5D739}.Release_SGen|Win32.ActiveCfg = Release_SGen|Win32 - {C36612BD-22D3-4B95-85E2-7FDC4FC5D739}.Release_SGen|Win32.Build.0 = Release_SGen|Win32 - {C36612BD-22D3-4B95-85E2-7FDC4FC5D739}.Release_SGen|x64.ActiveCfg = Release_SGen|x64 - {C36612BD-22D3-4B95-85E2-7FDC4FC5D739}.Release_SGen|x64.Build.0 = Release_SGen|x64 {C36612BD-22D3-4B95-85E2-7FDC4FC5D739}.Release|Win32.ActiveCfg = Release|Win32 {C36612BD-22D3-4B95-85E2-7FDC4FC5D739}.Release|Win32.Build.0 = Release|Win32 {C36612BD-22D3-4B95-85E2-7FDC4FC5D739}.Release|x64.ActiveCfg = Release|x64 {C36612BD-22D3-4B95-85E2-7FDC4FC5D739}.Release|x64.Build.0 = Release|x64 + {5362490B-8516-44EE-9987-014C015A080A}.Debug|Win32.ActiveCfg = Debug|Win32 + {5362490B-8516-44EE-9987-014C015A080A}.Debug|x64.ActiveCfg = Debug|x64 + {5362490B-8516-44EE-9987-014C015A080A}.Release|Win32.ActiveCfg = Release|Win32 + {5362490B-8516-44EE-9987-014C015A080A}.Release|x64.ActiveCfg = Release|x64 + {92AE7622-5F58-4234-9A26-9EC71876B3F4}.Debug|Win32.ActiveCfg = Debug|Win32 + {92AE7622-5F58-4234-9A26-9EC71876B3F4}.Debug|Win32.Build.0 = Debug|Win32 + {92AE7622-5F58-4234-9A26-9EC71876B3F4}.Debug|x64.ActiveCfg = Debug|x64 + {92AE7622-5F58-4234-9A26-9EC71876B3F4}.Debug|x64.Build.0 = Debug|x64 + {92AE7622-5F58-4234-9A26-9EC71876B3F4}.Release|Win32.ActiveCfg = Release|Win32 + {92AE7622-5F58-4234-9A26-9EC71876B3F4}.Release|Win32.Build.0 = Release|Win32 + {92AE7622-5F58-4234-9A26-9EC71876B3F4}.Release|x64.ActiveCfg = Release|x64 + {92AE7622-5F58-4234-9A26-9EC71876B3F4}.Release|x64.Build.0 = Release|x64 + {A9DC644B-9171-4FCD-BF21-2CC6D055FC40}.Debug|Win32.ActiveCfg = Debug|Win32 + {A9DC644B-9171-4FCD-BF21-2CC6D055FC40}.Debug|x64.ActiveCfg = Debug|x64 + {A9DC644B-9171-4FCD-BF21-2CC6D055FC40}.Release|Win32.ActiveCfg = Release|Win32 + {A9DC644B-9171-4FCD-BF21-2CC6D055FC40}.Release|x64.ActiveCfg = Release|x64 + {B6E563B8-7F57-4F7F-9439-F2405D4E2522}.Debug|Win32.ActiveCfg = Debug|Win32 + {B6E563B8-7F57-4F7F-9439-F2405D4E2522}.Debug|x64.ActiveCfg = Debug|x64 + {B6E563B8-7F57-4F7F-9439-F2405D4E2522}.Release|Win32.ActiveCfg = Release|Win32 + {B6E563B8-7F57-4F7F-9439-F2405D4E2522}.Release|x64.ActiveCfg = Release|x64 + {C36612BD-22D3-4B95-85E2-7FDC4FC5D740}.Debug|Win32.ActiveCfg = Debug|Win32 + {C36612BD-22D3-4B95-85E2-7FDC4FC5D740}.Debug|Win32.Build.0 = Debug|Win32 + {C36612BD-22D3-4B95-85E2-7FDC4FC5D740}.Debug|x64.ActiveCfg = Debug|x64 + {C36612BD-22D3-4B95-85E2-7FDC4FC5D740}.Debug|x64.Build.0 = Debug|x64 + {C36612BD-22D3-4B95-85E2-7FDC4FC5D740}.Release|Win32.ActiveCfg = Release|Win32 + {C36612BD-22D3-4B95-85E2-7FDC4FC5D740}.Release|Win32.Build.0 = Release|Win32 + {C36612BD-22D3-4B95-85E2-7FDC4FC5D740}.Release|x64.ActiveCfg = Release|x64 + {C36612BD-22D3-4B95-85E2-7FDC4FC5D740}.Release|x64.Build.0 = Release|x64 + {3E0D229E-C39F-4EDA-9A6A-A33ECEA0322D}.Debug|Win32.ActiveCfg = Debug|Win32 + {3E0D229E-C39F-4EDA-9A6A-A33ECEA0322D}.Debug|Win32.Build.0 = Debug|Win32 + {3E0D229E-C39F-4EDA-9A6A-A33ECEA0322D}.Debug|x64.ActiveCfg = Debug|x64 + {3E0D229E-C39F-4EDA-9A6A-A33ECEA0322D}.Debug|x64.Build.0 = Debug|x64 + {3E0D229E-C39F-4EDA-9A6A-A33ECEA0322D}.Release|Win32.ActiveCfg = Release|Win32 + {3E0D229E-C39F-4EDA-9A6A-A33ECEA0322D}.Release|Win32.Build.0 = Release|Win32 + {3E0D229E-C39F-4EDA-9A6A-A33ECEA0322D}.Release|x64.ActiveCfg = Release|x64 + {3E0D229E-C39F-4EDA-9A6A-A33ECEA0322D}.Release|x64.Build.0 = Release|x64 + {CB0D9E92-293C-439C-9AC7-C5F59B6E0772}.Debug|Win32.ActiveCfg = Debug|Win32 + {CB0D9E92-293C-439C-9AC7-C5F59B6E0772}.Debug|Win32.Build.0 = Debug|Win32 + {CB0D9E92-293C-439C-9AC7-C5F59B6E0772}.Debug|x64.ActiveCfg = Debug|x64 + {CB0D9E92-293C-439C-9AC7-C5F59B6E0772}.Debug|x64.Build.0 = Debug|x64 + {CB0D9E92-293C-439C-9AC7-C5F59B6E0772}.Release|Win32.ActiveCfg = Release|Win32 + {CB0D9E92-293C-439C-9AC7-C5F59B6E0772}.Release|Win32.Build.0 = Release|Win32 + {CB0D9E92-293C-439C-9AC7-C5F59B6E0772}.Release|x64.ActiveCfg = Release|x64 + {CB0D9E92-293C-439C-9AC7-C5F59B6E0772}.Release|x64.Build.0 = Release|x64 + {C7D83158-4EB6-4409-8730-612AD45FAF6A}.Debug|Win32.ActiveCfg = Debug|Win32 + {C7D83158-4EB6-4409-8730-612AD45FAF6A}.Debug|Win32.Build.0 = Debug|Win32 + {C7D83158-4EB6-4409-8730-612AD45FAF6A}.Debug|x64.ActiveCfg = Debug|x64 + {C7D83158-4EB6-4409-8730-612AD45FAF6A}.Debug|x64.Build.0 = Debug|x64 + {C7D83158-4EB6-4409-8730-612AD45FAF6A}.Release|Win32.ActiveCfg = Release|Win32 + {C7D83158-4EB6-4409-8730-612AD45FAF6A}.Release|Win32.Build.0 = Release|Win32 + {C7D83158-4EB6-4409-8730-612AD45FAF6A}.Release|x64.ActiveCfg = Release|x64 + {C7D83158-4EB6-4409-8730-612AD45FAF6A}.Release|x64.Build.0 = Release|x64 + {6C64262B-077B-4E12-AF91-9409ECCB75F6}.Debug|Win32.ActiveCfg = Debug|Win32 + {6C64262B-077B-4E12-AF91-9409ECCB75F6}.Debug|Win32.Build.0 = Debug|Win32 + {6C64262B-077B-4E12-AF91-9409ECCB75F6}.Debug|x64.ActiveCfg = Debug|x64 + {6C64262B-077B-4E12-AF91-9409ECCB75F6}.Debug|x64.Build.0 = Debug|x64 + {6C64262B-077B-4E12-AF91-9409ECCB75F6}.Release|Win32.ActiveCfg = Release|Win32 + {6C64262B-077B-4E12-AF91-9409ECCB75F6}.Release|Win32.Build.0 = Release|Win32 + {6C64262B-077B-4E12-AF91-9409ECCB75F6}.Release|x64.ActiveCfg = Release|x64 + {6C64262B-077B-4E12-AF91-9409ECCB75F6}.Release|x64.Build.0 = Release|x64 + {7BECCFA0-28A0-4995-9856-558560F720E6}.Debug|Win32.ActiveCfg = Debug|Win32 + {7BECCFA0-28A0-4995-9856-558560F720E6}.Debug|Win32.Build.0 = Debug|Win32 + {7BECCFA0-28A0-4995-9856-558560F720E6}.Debug|x64.ActiveCfg = Debug|x64 + {7BECCFA0-28A0-4995-9856-558560F720E6}.Debug|x64.Build.0 = Debug|x64 + {7BECCFA0-28A0-4995-9856-558560F720E6}.Release|Win32.ActiveCfg = Release|Win32 + {7BECCFA0-28A0-4995-9856-558560F720E6}.Release|Win32.Build.0 = Release|Win32 + {7BECCFA0-28A0-4995-9856-558560F720E6}.Release|x64.ActiveCfg = Release|x64 + {7BECCFA0-28A0-4995-9856-558560F720E6}.Release|x64.Build.0 = Release|x64 + {0046B994-40A8-4C64-AC9D-429DC9177B54}.Debug|Win32.ActiveCfg = Debug|Win32 + {0046B994-40A8-4C64-AC9D-429DC9177B54}.Debug|Win32.Build.0 = Debug|Win32 + {0046B994-40A8-4C64-AC9D-429DC9177B54}.Debug|x64.ActiveCfg = Debug|x64 + {0046B994-40A8-4C64-AC9D-429DC9177B54}.Debug|x64.Build.0 = Debug|x64 + {0046B994-40A8-4C64-AC9D-429DC9177B54}.Release|Win32.ActiveCfg = Release|Win32 + {0046B994-40A8-4C64-AC9D-429DC9177B54}.Release|Win32.Build.0 = Release|Win32 + {0046B994-40A8-4C64-AC9D-429DC9177B54}.Release|x64.ActiveCfg = Release|x64 + {0046B994-40A8-4C64-AC9D-429DC9177B54}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution + {B7098DFA-31E6-4006-8A15-1C9A4E925149} = {EE2CC761-9652-44AC-9204-7EB31194CAA6} + {CB0D9E92-293C-439C-9AC7-C5F59B6E0771} = {DE3617B4-17A8-4E5F-A00F-BA43D956881F} {C5639B3F-288A-4A4B-A4A5-C0D85834221D} = {5FE09AA5-C3C9-45EA-A323-36A11B653CEC} {6FDE4E5E-57D0-432F-A987-6C226A7827E4} = {5FE09AA5-C3C9-45EA-A323-36A11B653CEC} - {C2EB666E-9146-4B7A-85F6-25F9EA313770} = {5FE09AA5-C3C9-45EA-A323-36A11B653CEC} - {B7098DFA-31E6-4006-8A15-1C9A4E925149} = {EE2CC761-9652-44AC-9204-7EB31194CAA6} + {A0EDDCD9-940F-432C-A28F-7EF322437D79} = {DE3617B4-17A8-4E5F-A00F-BA43D956881F} + {EB56000B-C80B-4E8B-908D-D84D31B517D3} = {21DF4C80-0EC9-4BFE-8552-2D47FCEF419A} {37F50E5A-4818-46CF-81FE-4BB06DE5D42E} = {EE2CC761-9652-44AC-9204-7EB31194CAA6} {84C7DB50-D6F8-4C47-B22C-6BB203AEB4D3} = {EE2CC761-9652-44AC-9204-7EB31194CAA6} {CA2A69D6-3B9D-45A5-8BF7-4E242E683122} = {EE2CC761-9652-44AC-9204-7EB31194CAA6} - {CB0D9E92-293C-439C-9AC7-C5F59B6E0771} = {0EBA83B7-0EB4-4C83-A900-77300A97E8B1} - {EB56000B-C80B-4E8B-908D-D84D31B517D3} = {0EBA83B7-0EB4-4C83-A900-77300A97E8B1} + {C2EB666E-9146-4B7A-85F6-25F9EA313770} = {5FE09AA5-C3C9-45EA-A323-36A11B653CEC} {158073ED-99AE-4196-9EDC-DDB2344F8466} = {0EBA83B7-0EB4-4C83-A900-77300A97E8B1} - {33014734-0F46-4099-9A21-0C989E428681} = {0EBA83B7-0EB4-4C83-A900-77300A97E8B1} - {8FC2B0C8-51AD-49DF-851F-5D01A77A75E4} = {0EBA83B7-0EB4-4C83-A900-77300A97E8B1} - {C36612BD-22D3-4B95-85E2-7FDC4FC5D739} = {0EBA83B7-0EB4-4C83-A900-77300A97E8B1} {80A0620A-3478-4E1A-AA7C-0D2387B892AB} = {ECA11C76-E192-4F67-A8FA-28B637D9716F} {5A435710-E6D2-4DD4-9B3F-A7239A32C6F4} = {ECA11C76-E192-4F67-A8FA-28B637D9716F} + {33014734-0F46-4099-9A21-0C989E428681} = {0EBA83B7-0EB4-4C83-A900-77300A97E8B1} + {5D485D32-3B9F-4287-AB24-C8DA5B89F537} = {EE2CC761-9652-44AC-9204-7EB31194CAA6} {F51017F9-B7FB-4F87-B7B5-12799D965783} = {4CFD7702-60B2-4E82-BFAD-FCBB53EB4DA2} + {8FC2B0C8-51AD-49DF-851F-5D01A77A75E4} = {0EBA83B7-0EB4-4C83-A900-77300A97E8B1} + {C36612BD-22D3-4B95-85E2-7FDC4FC5D739} = {0EBA83B7-0EB4-4C83-A900-77300A97E8B1} + {5362490B-8516-44EE-9987-014C015A080A} = {DC782E23-920A-4873-82A7-37F195FB92C1} + {92AE7622-5F58-4234-9A26-9EC71876B3F4} = {DC782E23-920A-4873-82A7-37F195FB92C1} + {A9DC644B-9171-4FCD-BF21-2CC6D055FC40} = {DC782E23-920A-4873-82A7-37F195FB92C1} + {B6E563B8-7F57-4F7F-9439-F2405D4E2522} = {DC782E23-920A-4873-82A7-37F195FB92C1} + {C36612BD-22D3-4B95-85E2-7FDC4FC5D740} = {21DF4C80-0EC9-4BFE-8552-2D47FCEF419A} + {3E0D229E-C39F-4EDA-9A6A-A33ECEA0322D} = {A0068765-334B-414C-8E21-8376CD2EC9F6} + {A0068765-334B-414C-8E21-8376CD2EC9F6} = {ECA11C76-E192-4F67-A8FA-28B637D9716F} + {CB0D9E92-293C-439C-9AC7-C5F59B6E0772} = {DE3617B4-17A8-4E5F-A00F-BA43D956881F} + {BACF489E-EAEB-42BF-9E0A-C54D7CF455B4} = {ECA11C76-E192-4F67-A8FA-28B637D9716F} + {C7D83158-4EB6-4409-8730-612AD45FAF6A} = {BACF489E-EAEB-42BF-9E0A-C54D7CF455B4} + {6C64262B-077B-4E12-AF91-9409ECCB75F6} = {BACF489E-EAEB-42BF-9E0A-C54D7CF455B4} + {7BECCFA0-28A0-4995-9856-558560F720E6} = {A0068765-334B-414C-8E21-8376CD2EC9F6} + {0046B994-40A8-4C64-AC9D-429DC9177B54} = {A0068765-334B-414C-8E21-8376CD2EC9F6} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution AMDCaProjectFile = C:\Users\Owner\Development\monogit\mono\msvc\CodeAnalyst\mono.caw diff --git a/msvc/mono.vcxproj b/msvc/mono.vcxproj index 66f1f0ef99..f277f33258 100644 --- a/msvc/mono.vcxproj +++ b/msvc/mono.vcxproj @@ -1,14 +1,6 @@  - + - - Debug_SGen - Win32 - - - Debug_SGen - x64 - Debug Win32 @@ -17,14 +9,6 @@ Debug x64 - - Release_SGen - Win32 - - - Release_SGen - x64 - Release Win32 @@ -34,113 +18,87 @@ x64 - {A0EDDCD9-940F-432C-A28F-7EF322437D79} mono Win32Proj + 8.1 Application Unicode - v120 - - - Application - Unicode - v120 + v140 Application Unicode - v120 - - - Application - Unicode - v120 + v140 Application Unicode - v120 - - - Application - Unicode - v120 + v140 Application Unicode - v120 - - - Application - Unicode - v120 + v140 - - - + - - - + - - - + - - - + <_ProjectFileVersion>10.0.30319.1 - $(Platform)\bin\$(Configuration)\ - $(Platform)\bin\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ - $(Platform)\bin\$(Configuration)\ - $(Platform)\bin\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ - $(Platform)\bin\$(Configuration)\ - $(Platform)\bin\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ - $(Platform)\bin\$(Configuration)\ - $(Platform)\bin\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ - $(ProjectName)-sgen - $(ProjectName)-sgen - $(ProjectName)-sgen - $(ProjectName)-sgen + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ + + + false + $(ProjectName)$(MONO_TARGET_SUFFIX) + + + false + $(ProjectName)$(MONO_TARGET_SUFFIX) + + + true + $(ProjectName)$(MONO_TARGET_SUFFIX) + + + true + $(ProjectName)$(MONO_TARGET_SUFFIX) Disabled - ..\libgc\include;..\;..\;..\jit;..\eglib\src;%(AdditionalIncludeDirectories) + $(MONO_DIR);$(MONO_INCLUDE_DIR);$(MONO_JIT_INCLUDE_DIR);$(MONO_LIBGC_SOURCE_DIR);$(MONO_EGLIB_SOURCE_DIR);%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true EnableFastChecks - MultiThreadedDebugDLL - true ProgramDatabase @@ -149,38 +107,8 @@ - %(AdditionalDependencies) - $(Platform)\lib;%(AdditionalLibraryDirectories) - true - Console - false - - - MachineX86 - - - false - - - - - Disabled - ..\libgc\include;..\;..\;..\jit;..\eglib\src;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebugDLL - true - - - ProgramDatabase - CompileAsC - 4996;%(DisableSpecificWarnings) - - - - %(AdditionalDependencies) - $(Platform)\lib;%(AdditionalLibraryDirectories) + eglib.lib;$(MONO_LIBMONO_LIB);%(AdditionalDependencies) + %(AdditionalLibraryDirectories) true Console false @@ -198,12 +126,10 @@ Disabled - ..\libgc\include;..\;..\;..\jit;..\eglib\src;%(AdditionalIncludeDirectories) + $(MONO_DIR);$(MONO_INCLUDE_DIR);$(MONO_JIT_INCLUDE_DIR);$(MONO_LIBGC_SOURCE_DIR);$(MONO_EGLIB_SOURCE_DIR);%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true EnableFastChecks - MultiThreadedDebugDLL - true ProgramDatabase @@ -214,48 +140,19 @@ false - %(AdditionalDependencies) - $(Platform)\lib;%(AdditionalLibraryDirectories) - true - Console - MachineX64 - - - - - X64 - - - Disabled - ..\libgc\include;..\;..\;..\jit;..\eglib\src;%(AdditionalIncludeDirectories) - WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebugDLL - true - - - ProgramDatabase - CompileAsC - 4996;%(DisableSpecificWarnings) - - - false - - - %(AdditionalDependencies) - $(Platform)\lib;%(AdditionalLibraryDirectories) + eglib.lib;$(MONO_LIBMONO_LIB);%(AdditionalDependencies) + %(AdditionalLibraryDirectories) true Console MachineX64 + + MinSpace - ..\libgc\include;..\;..\;..\jit;..\eglib\src;%(AdditionalIncludeDirectories) - MultiThreadedDLL - true + $(MONO_DIR);$(MONO_INCLUDE_DIR);$(MONO_JIT_INCLUDE_DIR);$(MONO_LIBGC_SOURCE_DIR);$(MONO_EGLIB_SOURCE_DIR);%(AdditionalIncludeDirectories) ProgramDatabase @@ -266,8 +163,8 @@ false - %(AdditionalDependencies) - $(Platform)\lib;%(AdditionalLibraryDirectories) + eglib.lib;$(MONO_LIBMONO_LIB);%(AdditionalDependencies) + %(AdditionalLibraryDirectories) Console true true @@ -278,44 +175,14 @@ true - - - MinSpace - ..\libgc\include;..\;..\;..\jit;..\eglib\src;%(AdditionalIncludeDirectories) - MultiThreadedDLL - true - - - ProgramDatabase - CompileAsC - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - false - - - %(AdditionalDependencies) - $(Platform)\lib;%(AdditionalLibraryDirectories) - true - Console - true - true - false - - - MachineX86 - - X64 MinSpace - ..\libgc\include;..\;..\;..\jit;..\eglib\src;%(AdditionalIncludeDirectories) + $(MONO_DIR);$(MONO_INCLUDE_DIR);$(MONO_JIT_INCLUDE_DIR);$(MONO_LIBGC_SOURCE_DIR);$(MONO_EGLIB_SOURCE_DIR);%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDLL - true ProgramDatabase @@ -325,36 +192,8 @@ false - %(AdditionalDependencies) - $(Platform)\lib;%(AdditionalLibraryDirectories) - true - Console - true - true - MachineX64 - - - - - X64 - - - MinSpace - ..\libgc\include;..\;..\;..\jit;..\eglib\src;%(AdditionalIncludeDirectories) - WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDLL - true - - - ProgramDatabase - CompileAsC - - - false - - - %(AdditionalDependencies) - $(Platform)\lib;%(AdditionalLibraryDirectories) + eglib.lib;$(MONO_LIBMONO_LIB);%(AdditionalDependencies) + %(AdditionalLibraryDirectories) true Console true @@ -368,19 +207,9 @@ {158073ed-99ae-4196-9edc-ddb2344f8466} - true - false - false - true - false {cb0d9e92-293c-439c-9ac7-c5f59b6e0771} - true - false - false - true - false diff --git a/msvc/monodis.vcxproj b/msvc/monodis.vcxproj index 9a739c622b..7f14c93115 100644 --- a/msvc/monodis.vcxproj +++ b/msvc/monodis.vcxproj @@ -1,5 +1,5 @@  - + Debug @@ -22,68 +22,83 @@ {37F50E5A-4818-46CF-81FE-4BB06DE5D42E} dis Win32Proj + 8.1 Application Unicode - v120 + v140 Application Unicode - v120 + v140 Application Unicode - v120 + v140 Application Unicode - v120 + v140 + + + + <_ProjectFileVersion>10.0.30319.1 - $(Platform)\bin\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ - false - $(Platform)\bin\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ + true + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ false - $(Platform)\bin\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ - false - $(Platform)\bin\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ + true + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ false + + $(ProjectName)$(MONO_TARGET_SUFFIX) + + + $(ProjectName)$(MONO_TARGET_SUFFIX) + + + $(ProjectName)$(MONO_TARGET_SUFFIX) + + + $(ProjectName)$(MONO_TARGET_SUFFIX) + Disabled - ..\;..\eglib\src;..\mono\;..\mono\jit;%(AdditionalIncludeDirectories) + $(MONO_DIR);$(MONO_INCLUDE_DIR);$(MONO_JIT_INCLUDE_DIR);$(MONO_EGLIB_SOURCE_DIR);%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;_WINDOWS;__WIN32__;HOST_WIN32;TARGET_WIN32;__i386__;TARGET_X86;%(PreprocessorDefinitions) true EnableFastChecks - MultiThreadedDebugDLL - true Level3 @@ -92,12 +107,11 @@ 4996;4018;4244;%(DisableSpecificWarnings) - true + false - - - $(Platform)_$(Configuration)/lib;%(AdditionalLibraryDirectories) + eglib.lib;$(MONO_RUNTIME_LIBS);%(AdditionalDependencies) + %(AdditionalLibraryDirectories) true Console false @@ -109,20 +123,18 @@ MinSpace - ..\;..\eglib\src;..\mono\;..\mono\jit;%(AdditionalIncludeDirectories) + $(MONO_DIR);$(MONO_INCLUDE_DIR);$(MONO_JIT_INCLUDE_DIR);$(MONO_EGLIB_SOURCE_DIR);%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDLL - true Level3 ProgramDatabase - true + false - $(Platform)_$(Configuration)/lib;%(AdditionalLibraryDirectories) + %(AdditionalLibraryDirectories) true Console true @@ -131,7 +143,7 @@ MachineX86 - %(AdditionalDependencies) + eglib.lib;$(MONO_RUNTIME_LIBS);%(AdditionalDependencies) @@ -140,12 +152,10 @@ Disabled - ..\;..\eglib\src;..\mono\;..\mono\jit;%(AdditionalIncludeDirectories) + $(MONO_DIR);$(MONO_INCLUDE_DIR);$(MONO_JIT_INCLUDE_DIR);$(MONO_EGLIB_SOURCE_DIR);%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;_WINDOWS;__WIN32__;HOST_WIN32;TARGET_WIN32;__i386__;TARGET_X86;%(PreprocessorDefinitions) true EnableFastChecks - MultiThreadedDebug - true Level3 @@ -154,15 +164,15 @@ 4996;4018;4244;%(DisableSpecificWarnings) - true + false - - - $(Platform)_$(Configuration)/lib;%(AdditionalLibraryDirectories) + eglib.lib;$(MONO_RUNTIME_LIBS);%(AdditionalDependencies) + %(AdditionalLibraryDirectories) true Console MachineX64 + NotSet @@ -171,26 +181,24 @@ MinSpace - ..\;..\eglib\src;..\mono\;..\mono\jit;%(AdditionalIncludeDirectories) + $(MONO_DIR);$(MONO_INCLUDE_DIR);$(MONO_JIT_INCLUDE_DIR);$(MONO_EGLIB_SOURCE_DIR);%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDLL - true Level3 ProgramDatabase - true + false - $(Platform)_$(Configuration)/lib;%(AdditionalLibraryDirectories) + %(AdditionalLibraryDirectories) true Console true true MachineX64 - %(AdditionalDependencies) + eglib.lib;$(MONO_RUNTIME_LIBS);%(AdditionalDependencies) @@ -214,11 +222,12 @@ {158073ed-99ae-4196-9edc-ddb2344f8466} - false - true - false - true - false + + + {eb56000b-c80b-4e8b-908d-d84d31b517d3} + + + {c36612bd-22d3-4b95-85e2-7fdc4fc5d740} {cb0d9e92-293c-439c-9ac7-c5f59b6e0771} diff --git a/msvc/monograph.vcxproj b/msvc/monograph.vcxproj index 962d5bacf5..ce3658dd42 100644 --- a/msvc/monograph.vcxproj +++ b/msvc/monograph.vcxproj @@ -1,5 +1,5 @@  - + Debug @@ -22,68 +22,83 @@ {CA2A69D6-3B9D-45A5-8BF7-4E242E683122} monograph Win32Proj + 8.1 Application Unicode - v120 + v140 Application Unicode - v120 + v140 Application Unicode - v120 + v140 Application Unicode - v120 + v140 + + + + <_ProjectFileVersion>10.0.30319.1 - $(Platform)\bin\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ - false - $(Platform)\bin\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ + true + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ false - $(Platform)\bin\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ - false - $(Platform)\bin\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ + true + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ false + + $(ProjectName)$(MONO_TARGET_SUFFIX) + + + $(ProjectName)$(MONO_TARGET_SUFFIX) + + + $(ProjectName)$(MONO_TARGET_SUFFIX) + + + $(ProjectName)$(MONO_TARGET_SUFFIX) + Disabled - ..\;..\eglib\src;..\mono\;..\mono\jit;%(AdditionalIncludeDirectories) + $(MONO_DIR);$(MONO_INCLUDE_DIR);$(MONO_JIT_INCLUDE_DIR);$(MONO_EGLIB_SOURCE_DIR);%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;_WINDOWS;__WIN32__;HOST_WIN32;TARGET_WIN32;__i386__;TARGET_X86;%(PreprocessorDefinitions) true EnableFastChecks - MultiThreadedDebugDLL - true Level3 @@ -95,8 +110,8 @@ false - ws2_32.lib;Psapi.lib;%(AdditionalDependencies) - $(Platform)_$(Configuration)/lib;%(AdditionalLibraryDirectories) + eglib.lib;$(MONO_LIBMONO_LIB);%(AdditionalDependencies) + %(AdditionalLibraryDirectories) true Console false @@ -108,10 +123,8 @@ MinSpace - ..\;..\eglib\src;..\mono\;..\mono\jit;%(AdditionalIncludeDirectories) + $(MONO_DIR);$(MONO_INCLUDE_DIR);$(MONO_JIT_INCLUDE_DIR);$(MONO_EGLIB_SOURCE_DIR);%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDLL - true Level3 @@ -121,7 +134,7 @@ false - $(Platform)_$(Configuration)/lib;%(AdditionalLibraryDirectories) + %(AdditionalLibraryDirectories) true Console true @@ -130,6 +143,7 @@ MachineX86 + eglib.lib;$(MONO_LIBMONO_LIB);%(AdditionalDependencies) @@ -138,12 +152,10 @@ Disabled - ..\;..\eglib\src;..\mono\;..\mono\jit;%(AdditionalIncludeDirectories) + $(MONO_DIR);$(MONO_INCLUDE_DIR);$(MONO_JIT_INCLUDE_DIR);$(MONO_EGLIB_SOURCE_DIR);%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;_WINDOWS;__WIN32__;HOST_WIN32;TARGET_WIN32;__i386__;TARGET_X86;%(PreprocessorDefinitions) true EnableFastChecks - MultiThreadedDebug - true Level3 @@ -155,8 +167,8 @@ false - ws2_32.lib;libmono.lib;Psapi.lib;%(AdditionalDependencies) - $(Platform)_$(Configuration)/lib;%(AdditionalLibraryDirectories) + eglib.lib;$(MONO_LIBMONO_LIB);%(AdditionalDependencies) + %(AdditionalLibraryDirectories) true Console MachineX64 @@ -168,10 +180,8 @@ MinSpace - ..\;..\eglib\src;..\mono\;..\mono\jit;%(AdditionalIncludeDirectories) + $(MONO_DIR);$(MONO_INCLUDE_DIR);$(MONO_JIT_INCLUDE_DIR);$(MONO_EGLIB_SOURCE_DIR);%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDLL - true Level3 @@ -181,12 +191,13 @@ false - $(Platform)_$(Configuration)/lib;%(AdditionalLibraryDirectories) + %(AdditionalLibraryDirectories) true Console true true MachineX64 + eglib.lib;$(MONO_LIBMONO_LIB);%(AdditionalDependencies) @@ -196,19 +207,9 @@ {158073ed-99ae-4196-9edc-ddb2344f8466} - false - true - false - true - false {cb0d9e92-293c-439c-9ac7-c5f59b6e0771} - false - true - false - true - false diff --git a/msvc/monoposixhelper.vcxproj b/msvc/monoposixhelper.vcxproj index df216b7622..83304969ab 100644 --- a/msvc/monoposixhelper.vcxproj +++ b/msvc/monoposixhelper.vcxproj @@ -1,5 +1,5 @@  - + Debug @@ -22,57 +22,62 @@ {33014734-0F46-4099-9A21-0C989E428681} monoposixhelper Win32Proj + 8.1 DynamicLibrary Unicode - v120 + v140 DynamicLibrary Unicode - v120 + v140 DynamicLibrary Unicode - v120 + v140 DynamicLibrary Unicode - v120 + v140 + + + + <_ProjectFileVersion>10.0.30319.1 - $(Platform)\bin\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ true - $(Platform)\bin\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ true - $(Platform)\bin\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ false - $(Platform)\bin\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ false MonoPosixHelper MonoPosixHelper @@ -82,19 +87,18 @@ Disabled - ..\eglib\src;..\;%(AdditionalIncludeDirectories) + $(MONO_DIR);$(MONO_EGLIB_SOURCE_DIR);%(AdditionalIncludeDirectories) _DEBUG;__i386__;TARGET_X86;_WIN32_WINNT=0x0600;WIN32;_WIN32;__WIN32__;_WINDOWS;WINDOWS;HOST_WIN32;TARGET_WIN32;_CRT_SECURE_NO_DEPRECATE;HAVE_CONFIG_H;%(PreprocessorDefinitions) true EnableFastChecks - MultiThreadedDebugDLL Level3 - EditAndContinue + ProgramDatabase CompileAsC - %(AdditionalDependencies) + eglib.lib;%(AdditionalDependencies) $(OutDir)$(TargetName)$(TargetExt) monoposixhelper.def true @@ -102,9 +106,13 @@ false - $(Platform)\lib\$(Configuration)\$(TargetName).lib + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\$(TargetName).lib MachineX86 + %(AdditionalLibraryDirectories) + + false + @@ -112,11 +120,10 @@ Disabled - ..\eglib\src;..\;%(AdditionalIncludeDirectories) + $(MONO_DIR);$(MONO_EGLIB_SOURCE_DIR);%(AdditionalIncludeDirectories) _DEBUG;__x86_64__;_WIN32_WINNT=0x0600;WIN64;_WIN64;WIN32;_WIN32;__WIN32__;_WINDOWS;WINDOWS;HOST_WIN32;TARGET_WIN32;_CRT_SECURE_NO_DEPRECATE;HAVE_CONFIG_H;%(PreprocessorDefinitions) true EnableFastChecks - MultiThreadedDebugDLL Level3 @@ -128,17 +135,20 @@ monoposixhelper.def true Windows - $(Platform)\lib\$(Configuration)\$(TargetName).lib + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\$(TargetName).lib MachineX64 - %(AdditionalDependencies) + eglib.lib;%(AdditionalDependencies) + %(AdditionalLibraryDirectories) + + false + MinSpace - ..\eglib\src;..\;%(AdditionalIncludeDirectories) + $(MONO_DIR);$(MONO_EGLIB_SOURCE_DIR);%(AdditionalIncludeDirectories) NDEBUG;__i386__;TARGET_X86;i386;_WIN32_WINNT=0x0600;WIN32;_WIN32;__WIN32__;_WINDOWS;WINDOWS;HOST_WIN32;TARGET_WIN32;_CRT_SECURE_NO_DEPRECATE;HAVE_CONFIG_H;%(PreprocessorDefinitions) - MultiThreadedDLL Level3 @@ -146,7 +156,7 @@ CompileAsC - %(AdditionalDependencies) + eglib.lib;%(AdditionalDependencies) $(OutDir)$(TargetName)$(TargetExt) monoposixhelper.def true @@ -156,9 +166,13 @@ false - $(Platform)\lib\$(Configuration)\$(TargetName).lib + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\$(TargetName).lib MachineX86 + %(AdditionalLibraryDirectories) + + false + @@ -166,9 +180,8 @@ MinSpace - ..\eglib\src;..\;%(AdditionalIncludeDirectories) + $(MONO_DIR);$(MONO_EGLIB_SOURCE_DIR);%(AdditionalIncludeDirectories) NDEBUG;__x86_64__;_WIN32_WINNT=0x0600;WIN64;_WIN64;WIN32;_WIN32;__WIN32__;_WINDOWS;WINDOWS;HOST_WIN32;TARGET_WIN32;_CRT_SECURE_NO_DEPRECATE;HAVE_CONFIG_H;%(PreprocessorDefinitions) - MultiThreadedDLL Level3 @@ -182,10 +195,14 @@ Windows true true - $(Platform)\lib\$(Configuration)\$(TargetName).lib + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\$(TargetName).lib MachineX64 - %(AdditionalDependencies) + eglib.lib;%(AdditionalDependencies) + %(AdditionalLibraryDirectories) + + false + @@ -227,10 +244,6 @@ {158073ed-99ae-4196-9edc-ddb2344f8466} - - {b7098dfa-31e6-4006-8a15-1c9a4e925149} - false - diff --git a/msvc/pedump.vcxproj b/msvc/pedump.vcxproj index 275e4c17c9..5a6e9116bd 100644 --- a/msvc/pedump.vcxproj +++ b/msvc/pedump.vcxproj @@ -1,5 +1,5 @@  - + Debug @@ -22,73 +22,87 @@ {84C7DB50-D6F8-4C47-B22C-6BB203AEB4D3} pedump Win32Proj + 8.1 Application Unicode - v120 + v140 Application Unicode - v120 + v140 Application Unicode - v120 + v140 Application Unicode - v120 + v140 + + + + <_ProjectFileVersion>10.0.30319.1 - $(Platform)\bin\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ - false - $(Platform)\bin\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ + true + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ false - $(Platform)\bin\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ - false - $(Platform)\bin\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ + true + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ false + + $(ProjectName)$(MONO_TARGET_SUFFIX) + + + $(ProjectName)$(MONO_TARGET_SUFFIX) + + + $(ProjectName)$(MONO_TARGET_SUFFIX) + + + $(ProjectName)$(MONO_TARGET_SUFFIX) + Disabled - $(SolutionDir)..\eglib\src\;$(SolutionDir)..\;$(SolutionDir)..\mono\;%(AdditionalIncludeDirectories) + $(MONO_DIR);$(MONO_INCLUDE_DIR);$(MONO_JIT_INCLUDE_DIR);$(MONO_EGLIB_SOURCE_DIR);%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;_WINDOWS;__WIN32__;HOST_WIN32;TARGET_WIN32;__i386__;TARGET_X86;GC_NOT_DLL;GC_GCJ_SUPPORT;GC_WIN32_THREADS;%(PreprocessorDefinitions) true EnableFastChecks - MultiThreadedDebugDLL - true - $(IntDir)pedump/ - $(IntDir)pedump/vc80.pdb - $(IntDir)pedump/ + $(IntDir) + $(IntDir) Level3 ProgramDatabase CompileAsC @@ -98,8 +112,8 @@ false - Psapi.lib;Ws2_32.lib;%(AdditionalDependencies) - $(Platform)_$(Configuration)/lib;%(AdditionalLibraryDirectories) + eglib.lib;libmonoruntime$(MONO_TARGET_SUFFIX).lib;libmonoutils.lib;$(GC_LIB);%(AdditionalDependencies) + %(AdditionalLibraryDirectories) true Console false @@ -112,20 +126,18 @@ MinSpace WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDLL - true Level3 ProgramDatabase - $(SolutionDir)..\eglib\src\;$(SolutionDir)..\;$(SolutionDir)..\mono\;%(AdditionalIncludeDirectories) + $(MONO_DIR);$(MONO_INCLUDE_DIR);$(MONO_JIT_INCLUDE_DIR);$(MONO_EGLIB_SOURCE_DIR);%(AdditionalIncludeDirectories) false - Psapi.lib;Ws2_32.lib;%(AdditionalDependencies) - $(Platform)_$(Configuration)/lib;%(AdditionalLibraryDirectories) + eglib.lib;libmonoruntime$(MONO_TARGET_SUFFIX).lib;libmonoutils.lib;$(GC_LIB);%(AdditionalDependencies) + %(AdditionalLibraryDirectories) true Console true @@ -142,17 +154,14 @@ Disabled - $(SolutionDir)..\eglib\src\;$(SolutionDir)..\;$(SolutionDir)..\mono\;%(AdditionalIncludeDirectories) + $(MONO_DIR);$(MONO_INCLUDE_DIR);$(MONO_JIT_INCLUDE_DIR);$(MONO_EGLIB_SOURCE_DIR);%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;_WINDOWS;__WIN32__;HOST_WIN32;TARGET_WIN32;__i386__;TARGET_X86;%(PreprocessorDefinitions) true EnableFastChecks - MultiThreadedDebug - true - $(IntDir)pedump/ - $(IntDir)pedump/vc80.pdb - $(IntDir)pedump/ + $(IntDir) + $(IntDir) Level3 ProgramDatabase CompileAsC @@ -162,8 +171,8 @@ false - Psapi.lib;Ws2_32.lib;%(AdditionalDependencies) - $(Platform)_$(Configuration)/lib;%(AdditionalLibraryDirectories) + eglib.lib;libmonoruntime$(MONO_TARGET_SUFFIX).lib;libmonoutils.lib;$(GC_LIB);%(AdditionalDependencies) + %(AdditionalLibraryDirectories) true Console MachineX64 @@ -176,20 +185,18 @@ MinSpace WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDLL - true Level3 ProgramDatabase - $(SolutionDir)..\eglib\src\;$(SolutionDir)..\;$(SolutionDir)..\mono\;%(AdditionalIncludeDirectories) + $(MONO_DIR);$(MONO_INCLUDE_DIR);$(MONO_JIT_INCLUDE_DIR);$(MONO_EGLIB_SOURCE_DIR);%(AdditionalIncludeDirectories) false - Psapi.lib;Ws2_32.lib;%(AdditionalDependencies) - $(Platform)_$(Configuration)/lib;%(AdditionalLibraryDirectories) + eglib.lib;libmonoruntime$(MONO_TARGET_SUFFIX).lib;libmonoutils.lib;$(GC_LIB);%(AdditionalDependencies) + %(AdditionalLibraryDirectories) true Console true @@ -218,7 +225,6 @@ - @@ -228,47 +234,20 @@ + {158073ed-99ae-4196-9edc-ddb2344f8466} - false - true - false - true - false {eb56000b-c80b-4e8b-908d-d84d31b517d3} - false - true - false - true - false + + + {c36612bd-22d3-4b95-85e2-7fdc4fc5d740} {cb0d9e92-293c-439c-9ac7-c5f59b6e0771} - true - false - false - true - false - - - {c36612bd-22d3-4b95-85e2-7fdc4fc5d739} - false - true - false - true - false - - - {8fc2b0c8-51ad-49df-851f-5d01a77a75e4} - false - true - false - true - false diff --git a/msvc/profiler-vtune.vcxproj b/msvc/profiler-vtune.vcxproj index dcdb2ba648..544a89d32a 100644 --- a/msvc/profiler-vtune.vcxproj +++ b/msvc/profiler-vtune.vcxproj @@ -1,5 +1,5 @@  - + Debug @@ -22,75 +22,79 @@ {F51017F9-B7FB-4F87-B7B5-12799D965783} profilervtune Win32Proj + 8.1 DynamicLibrary Unicode - v120 + v140 DynamicLibrary Unicode - v120 + v140 DynamicLibrary Unicode - v120 + v140 DynamicLibrary Unicode - v120 + v140 + + + + <_ProjectFileVersion>10.0.30319.1 - $(Platform)\bin\ - $(Platform)\bin\ - $(Platform)\obj\$(ProjectName)\ - $(Platform)\obj\$(ProjectName)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ true true - $(Platform)\bin\ - $(Platform)\bin\ - $(Platform)\obj\$(ProjectName)\ - $(Platform)\obj\$(ProjectName)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ false false - mono-profiler-vtune - mono-profiler-vtune - mono-profiler-vtune - mono-profiler-vtune + mono-profiler-vtune$(MONO_TARGET_SUFFIX) + mono-profiler-vtune$(MONO_TARGET_SUFFIX) + mono-profiler-vtune$(MONO_TARGET_SUFFIX) + mono-profiler-vtune$(MONO_TARGET_SUFFIX) MaxSpeed true WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - MultiThreadedDLL true Level3 ProgramDatabase - ..\libgc\include;..\;..\mono\;..\mono\jit;..\mono\eglib\src;..\..\mono\eglib\src;$(ProgramFiles)\Intel\VTune Amplifier XE 2013\include;%(AdditionalIncludeDirectories) + $(MONO_DIR);$(MONO_INCLUDE_DIR);$(MONO_LIBGC_INCLUDE_DIR);$(MONO_JIT_INCLUDE_DIR);$(MONO_EGLIB_SOURCE_DIR);$(VTUNE_INCLUDE_DIR);%(AdditionalIncludeDirectories) true @@ -99,22 +103,24 @@ true MachineX86 mono-profiler-vtune.def - mono-2.0.lib;libgc.lib;eglib.lib;jitprofiling.lib;%(AdditionalDependencies) - $(Platform)\lib;$(ProgramFiles)\Intel\VTune Amplifier XE 2013\lib32;%(AdditionalLibraryDirectories) + $(MONO_LIBMONO_LIB);$(GC_LIB);eglib.lib;jitprofiling.lib;%(AdditionalDependencies) + $(ProgramFiles)\Intel\VTune Amplifier XE 2013\lib32;%(AdditionalLibraryDirectories) + + false + MaxSpeed true WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - MultiThreadedDLL true Level3 ProgramDatabase - ..\libgc\include;..\;..\mono\;..\mono\jit;..\mono\eglib\src;..\..\mono\eglib\src;$(ProgramFiles)\Intel\VTune Amplifier XE 2011\include;%(AdditionalIncludeDirectories) + $(MONO_DIR);$(MONO_INCLUDE_DIR);$(MONO_LIBGC_INCLUDE_DIR);$(MONO_JIT_INCLUDE_DIR);$(MONO_EGLIB_SOURCE_DIR);$(VTUNE_INCLUDE_DIR);%(AdditionalIncludeDirectories) true @@ -122,51 +128,58 @@ true true mono-profiler-vtune.def - mono-2.0.lib;version.lib;libgc.lib;eglib.lib;ws2_32.lib;Psapi.lib;winmm.lib;%(AdditionalDependencies) - $(Platform)\lib;%(AdditionalLibraryDirectories) + $(MONO_LIBMONO_LIB);$(GC_LIB);eglib.lib;jitprofiling.lib;%(AdditionalDependencies) + $(ProgramFiles)\Intel\VTune Amplifier XE 2013\lib32;%(AdditionalLibraryDirectories) + + false + Disabled - ..\libgc\include;..\;..\mono\;..\mono\jit;..\mono\eglib\src;..\..\mono\eglib\src;$(ProgramFiles)\Intel\VTune Amplifier XE 2013\include;%(AdditionalIncludeDirectories) + $(MONO_DIR);$(MONO_INCLUDE_DIR);$(MONO_LIBGC_INCLUDE_DIR);$(MONO_JIT_INCLUDE_DIR);$(MONO_EGLIB_SOURCE_DIR);$(VTUNE_INCLUDE_DIR);%(AdditionalIncludeDirectories) WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) true EnableFastChecks - MultiThreadedDebugDLL - - - Level3 - EditAndContinue - - - mono-2.0.lib;libgc.lib;eglib.lib;jitprofiling.lib;%(AdditionalDependencies) - $(Platform)\lib;$(ProgramFiles)\Intel\VTune Amplifier XE 2013\lib32;%(AdditionalLibraryDirectories) - true - Windows - MachineX86 - mono-profiler-vtune.def - - - - - Disabled - ..\libgc\include;..\;..\mono\;..\mono\jit;..\mono\eglib\src;..\..\mono\eglib\src;$(ProgramFiles)\Intel\VTune Amplifier XE 2011\include;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL Level3 ProgramDatabase - mono-2.0.lib;version.lib;libgc.lib;eglib.lib;ws2_32.lib;Psapi.lib;winmm.lib;%(AdditionalDependencies) - $(Platform)\lib;%(AdditionalLibraryDirectories) + $(MONO_LIBMONO_LIB);$(GC_LIB);eglib.lib;jitprofiling.lib;%(AdditionalDependencies) + $(ProgramFiles)\Intel\VTune Amplifier XE 2013\lib32;%(AdditionalLibraryDirectories) + true + Windows + MachineX86 + mono-profiler-vtune.def + + + false + + + + + Disabled + $(MONO_DIR);$(MONO_INCLUDE_DIR);$(MONO_LIBGC_INCLUDE_DIR);$(MONO_JIT_INCLUDE_DIR);$(MONO_EGLIB_SOURCE_DIR);$(VTUNE_INCLUDE_DIR);%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + EnableFastChecks + + + Level3 + ProgramDatabase + + + $(MONO_LIBMONO_LIB);$(GC_LIB);eglib.lib;jitprofiling.lib;%(AdditionalDependencies) + $(ProgramFiles)\Intel\VTune Amplifier XE 2013\lib32;%(AdditionalLibraryDirectories) true Windows mono-profiler-vtune.def + + false + @@ -174,6 +187,20 @@ + + + {158073ed-99ae-4196-9edc-ddb2344f8466} + + + {eb56000b-c80b-4e8b-908d-d84d31b517d3} + + + {c36612bd-22d3-4b95-85e2-7fdc4fc5d740} + + + {cb0d9e92-293c-439c-9ac7-c5f59b6e0771} + + diff --git a/msvc/test-invoke.vcxproj b/msvc/test-invoke.vcxproj index 2088fa3f0a..f258fb673c 100644 --- a/msvc/test-invoke.vcxproj +++ b/msvc/test-invoke.vcxproj @@ -1,5 +1,5 @@  - + Debug @@ -22,73 +22,87 @@ {C5639B3F-288A-4A4B-A4A5-C0D85834221D} testinvoke Win32Proj + 8.1 Application Unicode - v120 + v140 Application Unicode - v120 + v140 Application Unicode - v120 + v140 Application Unicode - v120 + v140 + + + + <_ProjectFileVersion>10.0.30319.1 - $(Platform)\bin\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ - false - $(Platform)\bin\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ + true + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ false - $(Platform)\bin\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ - false - $(Platform)\bin\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ + true + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ false + + $(ProjectName)$(MONO_TARGET_SUFFIX) + + + $(ProjectName)$(MONO_TARGET_SUFFIX) + + + $(ProjectName)$(MONO_TARGET_SUFFIX) + + + $(ProjectName)$(MONO_TARGET_SUFFIX) + Disabled - $(SolutionDir)include;%(AdditionalIncludeDirectories) + $(MONO_DIR);$(SolutionDir)include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true EnableFastChecks - MultiThreadedDebug - true - $(IntDir)invoke/ - $(IntDir)invoke/vc80.pdb - $(IntDir)invoke/ + $(IntDir) + $(IntDir) Level3 ProgramDatabase CompileAsC @@ -97,8 +111,8 @@ false - ws2_32.lib;Psapi.lib;%(AdditionalDependencies) - $(Platform)_$(Configuration)/lib;%(AdditionalLibraryDirectories) + $(MONO_DYNAMIC_LIBMONO_LIB);%(AdditionalDependencies) + %(AdditionalLibraryDirectories) true Console false @@ -111,19 +125,17 @@ MinSpace WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDLL - true Level3 ProgramDatabase - $(SolutionDir)include;%(AdditionalIncludeDirectories) + $(MONO_DIR);$(SolutionDir)include;%(AdditionalIncludeDirectories) false - $(Platform)_$(Configuration)/lib;%(AdditionalLibraryDirectories) + %(AdditionalLibraryDirectories) true Console true @@ -132,6 +144,7 @@ MachineX86 + $(MONO_DYNAMIC_LIBMONO_LIB);%(AdditionalDependencies) @@ -140,17 +153,14 @@ Disabled - $(SolutionDir)include;%(AdditionalIncludeDirectories) + $(MONO_DIR);$(SolutionDir)include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true EnableFastChecks - MultiThreadedDebug - true - $(IntDir)invoke/ - $(IntDir)invoke/vc80.pdb - $(IntDir)invoke/ + $(IntDir) + $(IntDir) Level3 ProgramDatabase CompileAsC @@ -159,8 +169,8 @@ false - glib-2.0.lib;gmodule-2.0.lib;ws2_32.lib;gthread-2.0.lib;gobject-2.0.lib;libmono.lib;Psapi.lib;%(AdditionalDependencies) - $(Platform)_$(Configuration)/lib;%(AdditionalLibraryDirectories) + $(MONO_DYNAMIC_LIBMONO_LIB);%(AdditionalDependencies) + %(AdditionalLibraryDirectories) true Console MachineX64 @@ -173,37 +183,34 @@ MinSpace WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDLL - true Level3 ProgramDatabase - $(SolutionDir)include;%(AdditionalIncludeDirectories) + $(MONO_DIR);$(SolutionDir)include;%(AdditionalIncludeDirectories) false - $(Platform)_$(Configuration)/lib;%(AdditionalLibraryDirectories) + %(AdditionalLibraryDirectories) true Console true true MachineX64 + $(MONO_DYNAMIC_LIBMONO_LIB);%(AdditionalDependencies) + + {158073ed-99ae-4196-9edc-ddb2344f8466} + {cb0d9e92-293c-439c-9ac7-c5f59b6e0771} - false - false - false - true - false diff --git a/msvc/test-metadata.vcxproj b/msvc/test-metadata.vcxproj index 42a5bd68e0..810f82f82f 100644 --- a/msvc/test-metadata.vcxproj +++ b/msvc/test-metadata.vcxproj @@ -1,5 +1,5 @@  - + Debug @@ -22,73 +22,87 @@ {C2EB666E-9146-4B7A-85F6-25F9EA313770} testmetadata Win32Proj + 8.1 Application Unicode - v120 + v140 Application Unicode - v120 + v140 Application Unicode - v120 + v140 Application Unicode - v120 + v140 + + + + <_ProjectFileVersion>10.0.30319.1 - $(Platform)\bin\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ - false - $(Platform)\bin\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ + true + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ false - $(Platform)\bin\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ - false - $(Platform)\bin\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ + true + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ false + + $(ProjectName)$(MONO_TARGET_SUFFIX) + + + $(ProjectName)$(MONO_TARGET_SUFFIX) + + + $(ProjectName)$(MONO_TARGET_SUFFIX) + + + $(ProjectName)$(MONO_TARGET_SUFFIX) + Disabled - $(SolutionDir)..\eglib\src;$(SolutionDir)include;%(AdditionalIncludeDirectories) + $(MONO_DIR);$(MONO_EGLIB_SOURCE_DIR);$(SolutionDir)include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true EnableFastChecks - MultiThreadedDebug - true - $(IntDir)metadata/ - $(IntDir)metadata/vc80.pdb - $(IntDir)metadata/ + $(IntDir) + $(IntDir) Level3 ProgramDatabase CompileAsC @@ -97,8 +111,8 @@ false - ws2_32.lib;Psapi.lib;%(AdditionalDependencies) - $(Platform)_$(Configuration)/lib;%(AdditionalLibraryDirectories) + $(MONO_DYNAMIC_LIBMONO_LIB);%(AdditionalDependencies) + %(AdditionalLibraryDirectories) true Console false @@ -111,19 +125,17 @@ MinSpace WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDLL - true Level3 ProgramDatabase - $(SolutionDir)..\eglib\src;$(SolutionDir)include;%(AdditionalIncludeDirectories) + $(MONO_DIR);$(MONO_EGLIB_SOURCE_DIR);$(SolutionDir)include;%(AdditionalIncludeDirectories) false - $(Platform)_$(Configuration)/lib;%(AdditionalLibraryDirectories) + %(AdditionalLibraryDirectories) true Console true @@ -132,6 +144,7 @@ MachineX86 + $(MONO_DYNAMIC_LIBMONO_LIB);%(AdditionalDependencies) @@ -140,17 +153,14 @@ Disabled - $(SolutionDir)..\eglib\src;$(SolutionDir)include;%(AdditionalIncludeDirectories) + $(MONO_DIR);$(MONO_EGLIB_SOURCE_DIR);$(SolutionDir)include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true EnableFastChecks - MultiThreadedDebug - true - $(IntDir)metadata/ - $(IntDir)metadata/vc80.pdb - $(IntDir)metadata/ + $(IntDir) + $(IntDir) Level3 ProgramDatabase CompileAsC @@ -159,8 +169,8 @@ false - glib-2.0.lib;gmodule-2.0.lib;ws2_32.lib;gthread-2.0.lib;gobject-2.0.lib;libmono.lib;Psapi.lib;%(AdditionalDependencies) - $(Platform)_$(Configuration)/lib;%(AdditionalLibraryDirectories) + $(MONO_DYNAMIC_LIBMONO_LIB);%(AdditionalDependencies) + %(AdditionalLibraryDirectories) true Console MachineX64 @@ -173,37 +183,34 @@ MinSpace WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDLL - true Level3 ProgramDatabase - $(SolutionDir)..\eglib\src;$(SolutionDir)include;%(AdditionalIncludeDirectories) + $(MONO_DIR);$(MONO_EGLIB_SOURCE_DIR);$(SolutionDir)include;%(AdditionalIncludeDirectories) false - $(Platform)_$(Configuration)/lib;%(AdditionalLibraryDirectories) + %(AdditionalLibraryDirectories) true Console true true MachineX64 + $(MONO_DYNAMIC_LIBMONO_LIB);%(AdditionalDependencies) + + {158073ed-99ae-4196-9edc-ddb2344f8466} + {cb0d9e92-293c-439c-9ac7-c5f59b6e0771} - false - false - false - true - false diff --git a/msvc/test_eglib.vcxproj b/msvc/test_eglib.vcxproj index 6986e99de7..d5e0fc41cd 100644 --- a/msvc/test_eglib.vcxproj +++ b/msvc/test_eglib.vcxproj @@ -1,5 +1,5 @@  - + Debug @@ -22,75 +22,85 @@ {80A0620A-3478-4E1A-AA7C-0D2387B892AB} test_eglib Win32Proj + 8.1 Application Unicode - v120 + v140 Application Unicode - v120 + v140 Application Unicode - v120 + v140 Application Unicode - v120 + v140 + + + + <_ProjectFileVersion>10.0.30319.1 - $(Platform)\bin\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ - $(Platform)\bin\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ - $(Platform)\bin\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ - $(Platform)\bin\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ + + + true + + + true Disabled - ../eglib/src;../eglib/test;../eglib;../msvc;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_FORTIFY_SOURCE=2;%(PreprocessorDefinitions) + $(MONO_EGLIB_INCLUDE_DIR);$(MONO_EGLIB_SOURCE_DIR)%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBTEST_EGLIB_EXPORTS;%(PreprocessorDefinitions) true EnableFastChecks - MultiThreadedDebugDLL Level4 false - EditAndContinue + ProgramDatabase false - Ws2_32.lib;Psapi.lib;%(AdditionalDependencies) - $(Platform)\lib;%(AdditionalLibraryDirectories) + eglib.lib;%(AdditionalDependencies) + %(AdditionalLibraryDirectories) true false false @@ -102,9 +112,8 @@ MinSpace - ../eglib/src;../eglib/test;../eglib;../msvc;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_FORTIFY_SOURCE=2;%(PreprocessorDefinitions) - MultiThreadedDLL + $(MONO_EGLIB_INCLUDE_DIR);$(MONO_EGLIB_SOURCE_DIR)%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBTEST_EGLIB_EXPORTS;%(PreprocessorDefinitions) Level4 @@ -115,8 +124,8 @@ false - Ws2_32.lib;Psapi.lib;%(AdditionalDependencies) - $(Platform)\lib;%(AdditionalLibraryDirectories) + eglib.lib;%(AdditionalDependencies) + %(AdditionalLibraryDirectories) false @@ -128,11 +137,10 @@ Disabled - ../eglib/src;../eglib/test;../eglib;../msvc;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_FORTIFY_SOURCE=2;%(PreprocessorDefinitions) + $(MONO_EGLIB_INCLUDE_DIR);$(MONO_EGLIB_SOURCE_DIR)%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBTEST_EGLIB_EXPORTS;%(PreprocessorDefinitions) true EnableFastChecks - MultiThreadedDebugDLL Level4 @@ -143,8 +151,8 @@ false - Ws2_32.lib;Psapi.lib;%(AdditionalDependencies) - $(Platform)\lib;%(AdditionalLibraryDirectories) + eglib.lib;%(AdditionalDependencies) + %(AdditionalLibraryDirectories) true false false @@ -157,9 +165,8 @@ MinSpace - ../eglib/src;../eglib/test;../eglib;../msvc;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_FORTIFY_SOURCE=2;%(PreprocessorDefinitions) - MultiThreadedDLL + $(MONO_EGLIB_INCLUDE_DIR);$(MONO_EGLIB_SOURCE_DIR)%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBTEST_EGLIB_EXPORTS;%(PreprocessorDefinitions) Level4 @@ -170,8 +177,8 @@ false - Ws2_32.lib;Psapi.lib;%(AdditionalDependencies) - $(Platform)\lib;%(AdditionalLibraryDirectories) + eglib.lib;%(AdditionalDependencies) + %(AdditionalLibraryDirectories) MachineX64 @@ -214,11 +221,9 @@ {158073ed-99ae-4196-9edc-ddb2344f8466} - false - false - false - true - false + + + {cb0d9e92-293c-439c-9ac7-c5f59b6e0771} diff --git a/msvc/teste.vcxproj b/msvc/teste.vcxproj index 772dd3692c..5fac6d8ac2 100644 --- a/msvc/teste.vcxproj +++ b/msvc/teste.vcxproj @@ -1,5 +1,5 @@  - + Debug @@ -22,73 +22,87 @@ {6FDE4E5E-57D0-432F-A987-6C226A7827E4} teste Win32Proj + 8.1 Application Unicode - v120 + v140 Application Unicode - v120 + v140 Application Unicode - v120 + v140 Application Unicode - v120 + v140 + + + + <_ProjectFileVersion>10.0.30319.1 - $(Platform)\bin\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ - false - $(Platform)\bin\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ + true + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ false - $(Platform)\bin\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ - false - $(Platform)\bin\$(Configuration)\ - $(Platform)\obj\$(ProjectName)\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ + true + $(MONO_BUILD_DIR_PREFIX)$(Platform)\bin\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)$(MONO_TARGET_SUFFIX)\$(Configuration)\ false + + $(ProjectName)$(MONO_TARGET_SUFFIX) + + + $(ProjectName)$(MONO_TARGET_SUFFIX) + + + $(ProjectName)$(MONO_TARGET_SUFFIX) + + + $(ProjectName)$(MONO_TARGET_SUFFIX) + Disabled - $(SolutionDir)include;%(AdditionalIncludeDirectories) + $(MONO_DIR);$(SolutionDir)include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true EnableFastChecks - MultiThreadedDebug - true - $(IntDir)e/ - $(IntDir)e/vc80.pdb - $(IntDir)e/ + $(IntDir) + $(IntDir) Level3 ProgramDatabase CompileAsC @@ -97,8 +111,8 @@ false - ws2_32.lib;Psapi.lib;%(AdditionalDependencies) - $(Platform)_$(Configuration)/lib;%(AdditionalLibraryDirectories) + $(MONO_DYNAMIC_LIBMONO_LIB);%(AdditionalDependencies) + %(AdditionalLibraryDirectories) true Console false @@ -111,19 +125,17 @@ MinSpace WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDLL - true Level3 ProgramDatabase - $(SolutionDir)include;%(AdditionalIncludeDirectories) + $(MONO_DIR);$(SolutionDir)include;%(AdditionalIncludeDirectories) false - $(Platform)_$(Configuration)/lib;%(AdditionalLibraryDirectories) + %(AdditionalLibraryDirectories) true Console true @@ -132,6 +144,7 @@ MachineX86 + $(MONO_DYNAMIC_LIBMONO_LIB);%(AdditionalDependencies) @@ -140,17 +153,14 @@ Disabled - $(SolutionDir)include;%(AdditionalIncludeDirectories) + $(MONO_DIR);$(SolutionDir)include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true EnableFastChecks - MultiThreadedDebug - true - $(IntDir)e/ - $(IntDir)e/vc80.pdb - $(IntDir)e/ + $(IntDir) + $(IntDir) Level3 ProgramDatabase CompileAsC @@ -159,8 +169,8 @@ false - glib-2.0.lib;gmodule-2.0.lib;ws2_32.lib;gthread-2.0.lib;gobject-2.0.lib;libmono.lib;Psapi.lib;%(AdditionalDependencies) - $(Platform)_$(Configuration)/lib;%(AdditionalLibraryDirectories) + $(MONO_DYNAMIC_LIBMONO_LIB);%(AdditionalDependencies) + %(AdditionalLibraryDirectories) true Console MachineX64 @@ -173,37 +183,34 @@ MinSpace WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDLL - true Level3 ProgramDatabase - $(SolutionDir)include;%(AdditionalIncludeDirectories) + $(MONO_DIR);$(SolutionDir)include;%(AdditionalIncludeDirectories) false - $(Platform)_$(Configuration)/lib;%(AdditionalLibraryDirectories) + %(AdditionalLibraryDirectories) true Console true true MachineX64 + $(MONO_DYNAMIC_LIBMONO_LIB);%(AdditionalDependencies) + + {158073ed-99ae-4196-9edc-ddb2344f8466} + {cb0d9e92-293c-439c-9ac7-c5f59b6e0771} - false - false - false - true - false diff --git a/msvc/winsetup.bat b/msvc/winsetup.bat index 73f2a1b5cf..f25016fd5f 100755 --- a/msvc/winsetup.bat +++ b/msvc/winsetup.bat @@ -1,17 +1,55 @@ -@echo off -cd .. -if exist config.h if not exist cygconfig.h copy config.h cygconfig.h -if exist eglib\config.h if not exist eglib\cygconfig.h copy eglib\config.h eglib\cygconfig.h -copy winconfig.h config.h -copy eglib\winconfig.h eglib\config.h -%windir%\system32\WindowsPowerShell\v1.0\powershell.exe -Command "(Get-Content config.h) -replace '#MONO_VERSION#', (Select-String -path configure.ac -pattern 'AC_INIT\(mono, \[(.*)\]').Matches[0].Groups[1].Value | Set-Content config.h" -goto end -:error -echo fatal error: the VSDepenancies directory was not found in the "mono" directory -echo error: you must download and unzip that file -exit /b 100 -goto end -:ok -echo OK -:end -exit /b 0 +@ECHO off + +SET CONFIG_H=..\config.h +SET EGLIB_CONFIG_H=..\eglib\config.h +SET CYG_CONFIG_H=..\cygconfig.h +SET EGLIB_CYG_CONFIG_H=..\eglib\cygconfig.h +SET WIN_CONFIG_H=..\winconfig.h +SET EGLIB_WIN_CONFIG_H=..\eglib\winconfig.h +SET CONFIGURE_AC=..\configure.ac +SET VERSION_H=..\mono\mini\version.h + + +ECHO Setting up Mono configuration headers... + +IF EXIST %CONFIG_H% ( + IF NOT EXIST %CYG_CONFIG_H% ( + ECHO copy %CONFIG_H% %CYG_CONFIG_H% + copy %CONFIG_H% %CYG_CONFIG_H% + ) +) + +IF EXIST %EGLIB_CONFIG_H% ( + IF NOT EXIST %EGLIB_CYG_CONFIG_H% ( + ECHO copy %EGLIB_CONFIG_H% %EGLIB_CYG_CONFIG_H% + copy %EGLIB_CONFIG_H% %EGLIB_CYG_CONFIG_H% + ) +) + +%windir%\system32\WindowsPowerShell\v1.0\powershell.exe -executionpolicy bypass -NonInteractive -File compare-config-files.ps1 %WIN_CONFIG_H% %CONFIG_H% %CONFIGURE_AC% 2>&1 + +IF NOT %ERRORLEVEL% == 0 ( + ECHO copy %WIN_CONFIG_H% %CONFIG_H% + copy %WIN_CONFIG_H% %CONFIG_H% + %windir%\system32\WindowsPowerShell\v1.0\powershell.exe -NonInteractive -Command "(Get-Content %CONFIG_H%) -replace '#MONO_VERSION#', (Select-String -path %CONFIGURE_AC% -pattern 'AC_INIT\(mono, \[(.*)\]').Matches[0].Groups[1].Value | Set-Content %CONFIG_H%" 2>&1 +) + +%windir%\system32\WindowsPowerShell\v1.0\powershell.exe -executionpolicy bypass -NonInteractive -File compare-config-files.ps1 %EGLIB_WIN_CONFIG_H% %EGLIB_CONFIG_H% 2>&1 + +IF NOT %ERRORLEVEL% == 0 ( + ECHO copy %EGLIB_WIN_CONFIG_H% %EGLIB_CONFIG_H% + copy %EGLIB_WIN_CONFIG_H% %EGLIB_CONFIG_H% +) + +SET VERSION_CONTENT="#define FULL_VERSION \"Visual Studio built mono\"" +%windir%\system32\WindowsPowerShell\v1.0\powershell.exe -executionpolicy bypass -NonInteractive -File compare-config-content.ps1 %VERSION_CONTENT% %VERSION_H% 2>&1 + + +IF NOT %ERRORLEVEL% == 0 ( + ECHO Configure %VERSION_H% + ECHO #define FULL_VERSION "Visual Studio built mono"> %VERSION_H% +) + +ECHO Successfully setup Mono configuration headers. + +EXIT /b 0 diff --git a/po/Makefile.in b/po/Makefile.in index 9d715f32eb..7015eaf881 100644 --- a/po/Makefile.in +++ b/po/Makefile.in @@ -180,6 +180,8 @@ am__relativize = \ ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AOT_BUILD_FLAGS = @AOT_BUILD_FLAGS@ +AOT_RUN_FLAGS = @AOT_RUN_FLAGS@ API_VER = @API_VER@ AR = @AR@ AS = @AS@ @@ -188,6 +190,11 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOEHM_DEFINES = @BOEHM_DEFINES@ +BTLS_ARCH = @BTLS_ARCH@ +BTLS_CFLAGS = @BTLS_CFLAGS@ +BTLS_CMAKE_ARGS = @BTLS_CMAKE_ARGS@ +BTLS_PLATFORM = @BTLS_PLATFORM@ +BTLS_ROOT = @BTLS_ROOT@ BUILD_EXEEXT = @BUILD_EXEEXT@ CC = @CC@ CCAS = @CCAS@ @@ -197,6 +204,7 @@ CCDEPMODE = @CCDEPMODE@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMAKE = @CMAKE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ @@ -217,7 +225,6 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_PERF_EVENTS = @ENABLE_PERF_EVENTS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDKX11 = @GDKX11@ @@ -232,10 +239,12 @@ HAVE_MSGFMT = @HAVE_MSGFMT@ HOST_CC = @HOST_CC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MOBILE_STATIC = @INSTALL_MOBILE_STATIC@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTL = @INTL@ +INVARIANT_AOT_OPTIONS = @INVARIANT_AOT_OPTIONS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBC = @LIBC@ @@ -282,6 +291,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ +PLATFORM_AOT_SUFFIX = @PLATFORM_AOT_SUFFIX@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -291,6 +301,7 @@ SHELL = @SHELL@ SQLITE = @SQLITE@ SQLITE3 = @SQLITE3@ STRIP = @STRIP@ +TEST_PROFILE = @TEST_PROFILE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VTUNE_CFLAGS = @VTUNE_CFLAGS@ diff --git a/po/mcs/de.gmo b/po/mcs/de.gmo index ec3f8e748d..6a8e12f4cf 100644 Binary files a/po/mcs/de.gmo and b/po/mcs/de.gmo differ diff --git a/po/mcs/de.po.REMOVED.git-id b/po/mcs/de.po.REMOVED.git-id index a4d55d39d0..49000b636c 100644 --- a/po/mcs/de.po.REMOVED.git-id +++ b/po/mcs/de.po.REMOVED.git-id @@ -1 +1 @@ -fee7aafe68936fe6e60112c7aee544d951a9e8ba \ No newline at end of file +4b4c8c95c1fb9efeb02fa1c5f3c296ffc26f263e \ No newline at end of file diff --git a/po/mcs/es.gmo b/po/mcs/es.gmo index f080f60107..fb569f29bd 100644 Binary files a/po/mcs/es.gmo and b/po/mcs/es.gmo differ diff --git a/po/mcs/es.po.REMOVED.git-id b/po/mcs/es.po.REMOVED.git-id index b98d1f015b..4e0148bc65 100644 --- a/po/mcs/es.po.REMOVED.git-id +++ b/po/mcs/es.po.REMOVED.git-id @@ -1 +1 @@ -cb117604bb38e5972606741b5f2e06b1b17885d5 \ No newline at end of file +fbacc0386bed56cd426fa6d1519d7238d83e1658 \ No newline at end of file diff --git a/po/mcs/ja.gmo b/po/mcs/ja.gmo index 2927c7e4fd..a3f815606a 100644 Binary files a/po/mcs/ja.gmo and b/po/mcs/ja.gmo differ diff --git a/po/mcs/ja.po.REMOVED.git-id b/po/mcs/ja.po.REMOVED.git-id index bf1023fe9c..b25801e01f 100644 --- a/po/mcs/ja.po.REMOVED.git-id +++ b/po/mcs/ja.po.REMOVED.git-id @@ -1 +1 @@ -cd8f7f08a55a6b8b1540dc1471ed6207c8bfae03 \ No newline at end of file +40c5ac34c575e1d103e7012e5e11b3dabe35f4ca \ No newline at end of file diff --git a/po/mcs/mcs.pot b/po/mcs/mcs.pot index 2f47ef37f4..1f91fb62fc 100644 --- a/po/mcs/mcs.pot +++ b/po/mcs/mcs.pot @@ -6,9 +6,9 @@ #, fuzzy msgid "" msgstr "" -"Project-Id-Version: mono 4.6.2\n" +"Project-Id-Version: mono 4.8.0\n" "Report-Msgid-Bugs-To: http://www.mono-project.com/Bugs\n" -"POT-Creation-Date: 2016-11-02 14:17+0000\n" +"POT-Creation-Date: 2016-11-10 12:38+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -34,7 +34,7 @@ msgid "" "mismatch" msgstr "" -#: mcs/mcs/anonymous.cs:1054 mcs/mcs/ecore.cs:5893 +#: mcs/mcs/anonymous.cs:1054 mcs/mcs/ecore.cs:5853 #, csharp-format msgid "Delegate `{0}' does not take `{1}' arguments" msgstr "" @@ -502,114 +502,114 @@ msgstr "" msgid "Identifier expected: {0}" msgstr "" -#: mcs/mcs/cs-tokenizer.cs:2877 +#: mcs/mcs/cs-tokenizer.cs:2883 msgid "Integral constant is too large" msgstr "" -#: mcs/mcs/cs-tokenizer.cs:2882 +#: mcs/mcs/cs-tokenizer.cs:2888 msgid "Invalid preprocessor directive" msgstr "" -#: mcs/mcs/cs-tokenizer.cs:2889 +#: mcs/mcs/cs-tokenizer.cs:2895 #, csharp-format msgid "Unexpected processor directive ({0})" msgstr "" -#: mcs/mcs/cs-tokenizer.cs:2895 +#: mcs/mcs/cs-tokenizer.cs:2901 msgid "" "Cannot define or undefine preprocessor symbols after first token in file" msgstr "" -#: mcs/mcs/cs-tokenizer.cs:2901 +#: mcs/mcs/cs-tokenizer.cs:2907 msgid "" "Preprocessor directives must appear as the first non-whitespace character on " "a line" msgstr "" -#: mcs/mcs/cs-tokenizer.cs:2906 +#: mcs/mcs/cs-tokenizer.cs:2912 msgid "Single-line comment or end-of-line expected" msgstr "" -#: mcs/mcs/cs-tokenizer.cs:2951 mcs/mcs/cs-tokenizer.cs:4184 +#: mcs/mcs/cs-tokenizer.cs:2957 mcs/mcs/cs-tokenizer.cs:4190 msgid "Expected `#endif' directive" msgstr "" -#: mcs/mcs/cs-tokenizer.cs:2984 mcs/mcs/cs-tokenizer.cs:3005 -#: mcs/mcs/cs-tokenizer.cs:3036 mcs/mcs/cs-tokenizer.cs:4182 +#: mcs/mcs/cs-tokenizer.cs:2990 mcs/mcs/cs-tokenizer.cs:3011 +#: mcs/mcs/cs-tokenizer.cs:3042 mcs/mcs/cs-tokenizer.cs:4188 msgid "#endregion directive expected" msgstr "" -#: mcs/mcs/cs-tokenizer.cs:3085 +#: mcs/mcs/cs-tokenizer.cs:3091 msgid "Wrong preprocessor directive" msgstr "" -#: mcs/mcs/cs-tokenizer.cs:3097 +#: mcs/mcs/cs-tokenizer.cs:3103 #, csharp-format msgid "#error: '{0}'" msgstr "" -#: mcs/mcs/cs-tokenizer.cs:3115 +#: mcs/mcs/cs-tokenizer.cs:3121 msgid "The line number specified for #line directive is missing or invalid" msgstr "" -#: mcs/mcs/cs-tokenizer.cs:3169 mcs/mcs/cs-tokenizer.cs:3887 +#: mcs/mcs/cs-tokenizer.cs:3175 mcs/mcs/cs-tokenizer.cs:3893 msgid "Newline in constant" msgstr "" -#: mcs/mcs/cs-tokenizer.cs:3196 +#: mcs/mcs/cs-tokenizer.cs:3202 msgid "Unterminated string literal" msgstr "" -#: mcs/mcs/cs-tokenizer.cs:3240 mcs/mcs/cs-tokenizer.cs:3271 +#: mcs/mcs/cs-tokenizer.cs:3246 mcs/mcs/cs-tokenizer.cs:3277 #, csharp-format msgid "Unexpected character `\\{0}'" msgstr "" -#: mcs/mcs/cs-tokenizer.cs:3287 +#: mcs/mcs/cs-tokenizer.cs:3293 msgid "Identifier too long (limit is 512 chars)" msgstr "" -#: mcs/mcs/cs-tokenizer.cs:3632 +#: mcs/mcs/cs-tokenizer.cs:3638 msgid "A single-line comment may not be used in an interpolated string" msgstr "" -#: mcs/mcs/cs-tokenizer.cs:3702 +#: mcs/mcs/cs-tokenizer.cs:3708 msgid "End-of-file found, '*/' expected" msgstr "" -#: mcs/mcs/cs-tokenizer.cs:3799 +#: mcs/mcs/cs-tokenizer.cs:3805 msgid "Missing close delimiter `}' for interpolated expression" msgstr "" -#: mcs/mcs/cs-tokenizer.cs:3820 +#: mcs/mcs/cs-tokenizer.cs:3826 msgid "Keyword, identifier, or string expected after verbatim specifier: @" msgstr "" -#: mcs/mcs/cs-tokenizer.cs:3857 +#: mcs/mcs/cs-tokenizer.cs:3863 #, csharp-format msgid "Unexpected character `{0}'" msgstr "" -#: mcs/mcs/cs-tokenizer.cs:3882 +#: mcs/mcs/cs-tokenizer.cs:3888 msgid "Empty character literal" msgstr "" -#: mcs/mcs/cs-tokenizer.cs:3903 +#: mcs/mcs/cs-tokenizer.cs:3909 msgid "Too many characters in character literal" msgstr "" -#: mcs/mcs/cs-tokenizer.cs:4010 mcs/mcs/cs-tokenizer.cs:4073 +#: mcs/mcs/cs-tokenizer.cs:4016 mcs/mcs/cs-tokenizer.cs:4079 #, csharp-format msgid "" "A `{0}' character may only be escaped by doubling `{0}{0}' in an " "interpolated string" msgstr "" -#: mcs/mcs/cs-tokenizer.cs:4051 +#: mcs/mcs/cs-tokenizer.cs:4057 msgid "Empty interpolated expression format specifier" msgstr "" -#: mcs/mcs/cs-tokenizer.cs:4053 +#: mcs/mcs/cs-tokenizer.cs:4059 msgid "" "A interpolated expression format specifier may not contain trailing " "whitespace" @@ -654,452 +654,452 @@ msgid "" "modifiers" msgstr "" -#: mcs/mcs/class.cs:342 +#: mcs/mcs/class.cs:346 #, csharp-format msgid "" "Missing partial modifier on declaration of type `{0}'. Another partial " "declaration of this type exists" msgstr "" -#: mcs/mcs/class.cs:755 +#: mcs/mcs/class.cs:759 #, csharp-format msgid "" "`{0}': explicit interface declaration can only be declared in a class or " "struct" msgstr "" -#: mcs/mcs/class.cs:810 +#: mcs/mcs/class.cs:814 #, csharp-format msgid "Duplicate type parameter `{0}'" msgstr "" -#: mcs/mcs/class.cs:813 +#: mcs/mcs/class.cs:817 #, csharp-format msgid "The type `{0}' already contains a definition for `{1}'" msgstr "" -#: mcs/mcs/class.cs:905 +#: mcs/mcs/class.cs:909 msgid "" "Cannot specify the `DefaultMember' attribute on type containing an indexer" msgstr "" -#: mcs/mcs/class.cs:910 +#: mcs/mcs/class.cs:914 msgid "The RequiredAttribute attribute is not permitted on C# types" msgstr "" -#: mcs/mcs/class.cs:977 +#: mcs/mcs/class.cs:981 #, csharp-format msgid "'{0}': Structs cannot have instance property or field initializers" msgstr "" -#: mcs/mcs/class.cs:1167 +#: mcs/mcs/class.cs:1171 #, csharp-format msgid "Class `{0}' cannot derive from the dynamic type" msgstr "" -#: mcs/mcs/class.cs:1184 +#: mcs/mcs/class.cs:1188 #, csharp-format msgid "`{0}' is already listed in interface list" msgstr "" -#: mcs/mcs/class.cs:1192 +#: mcs/mcs/class.cs:1196 #, csharp-format msgid "" "Inconsistent accessibility: base interface `{0}' is less accessible than " "interface `{1}'" msgstr "" -#: mcs/mcs/class.cs:1198 +#: mcs/mcs/class.cs:1202 #, csharp-format msgid "Type `{0}' in interface list is not an interface" msgstr "" -#: mcs/mcs/class.cs:1200 +#: mcs/mcs/class.cs:1204 #, csharp-format msgid "`{0}': Classes cannot have multiple base classes (`{1}' and `{2}')" msgstr "" -#: mcs/mcs/class.cs:1203 +#: mcs/mcs/class.cs:1207 #, csharp-format msgid "`{0}': Base class `{1}' must be specified as first" msgstr "" -#: mcs/mcs/class.cs:1264 +#: mcs/mcs/class.cs:1268 #, csharp-format msgid "" "The operator `{0}' requires a matching operator `{1}' to also be defined" msgstr "" -#: mcs/mcs/class.cs:1531 +#: mcs/mcs/class.cs:1535 #, csharp-format msgid "Partial declarations of `{0}' must not specify different base classes" msgstr "" -#: mcs/mcs/class.cs:1566 +#: mcs/mcs/class.cs:1570 msgid "" "Only one part of a partial type can declare primary constructor parameters" msgstr "" -#: mcs/mcs/class.cs:1583 +#: mcs/mcs/class.cs:1587 #, csharp-format msgid "" "Inherited interface `{0}' causes a cycle in the interface hierarchy of `{1}'" msgstr "" -#: mcs/mcs/class.cs:1590 +#: mcs/mcs/class.cs:1594 #, csharp-format msgid "Circular base class dependency involving `{0}' and `{1}'" msgstr "" -#: mcs/mcs/class.cs:1600 +#: mcs/mcs/class.cs:1604 msgid "Implemented interfaces cannot have arguments" msgstr "" -#: mcs/mcs/class.cs:1912 +#: mcs/mcs/class.cs:1916 #, csharp-format msgid "`{0}': cannot implement a dynamic interface `{1}'" msgstr "" -#: mcs/mcs/class.cs:1927 +#: mcs/mcs/class.cs:1931 #, csharp-format msgid "" "`{0}' cannot implement both `{1}' and `{2}' because they may unify for some " "type parameter substitutions" msgstr "" -#: mcs/mcs/class.cs:1949 +#: mcs/mcs/class.cs:1953 #, csharp-format msgid "" "A generic type cannot derive from `{0}' because it is an attribute class" msgstr "" -#: mcs/mcs/class.cs:2044 +#: mcs/mcs/class.cs:2048 msgid "" "Two indexers have different names; the IndexerName attribute must be used " "with the same name on every indexer within a type" msgstr "" -#: mcs/mcs/class.cs:2302 +#: mcs/mcs/class.cs:2306 #, csharp-format msgid "A static member `{0}' cannot be marked as override, virtual or abstract" msgstr "" -#: mcs/mcs/class.cs:2309 +#: mcs/mcs/class.cs:2313 #, csharp-format msgid "A member `{0}' marked as override cannot be marked as new or virtual" msgstr "" -#: mcs/mcs/class.cs:2321 +#: mcs/mcs/class.cs:2325 #, csharp-format msgid "`{0}' cannot be both extern and abstract" msgstr "" -#: mcs/mcs/class.cs:2326 +#: mcs/mcs/class.cs:2330 #, csharp-format msgid "`{0}' cannot be both abstract and sealed" msgstr "" -#: mcs/mcs/class.cs:2331 +#: mcs/mcs/class.cs:2335 #, csharp-format msgid "The abstract method `{0}' cannot be marked virtual" msgstr "" -#: mcs/mcs/class.cs:2337 +#: mcs/mcs/class.cs:2341 #, csharp-format msgid "`{0}' is abstract but it is declared in the non-abstract class `{1}'" msgstr "" -#: mcs/mcs/class.cs:2345 +#: mcs/mcs/class.cs:2349 #, csharp-format msgid "`{0}': virtual or abstract members cannot be private" msgstr "" -#: mcs/mcs/class.cs:2352 +#: mcs/mcs/class.cs:2356 #, csharp-format msgid "`{0}' cannot be sealed because it is not an override" msgstr "" -#: mcs/mcs/class.cs:2401 +#: mcs/mcs/class.cs:2405 #, csharp-format msgid "`{0}': containing type does not implement interface `{1}'" msgstr "" -#: mcs/mcs/class.cs:2598 +#: mcs/mcs/class.cs:2602 #, csharp-format msgid "Type parameter `{0}' has same name as containing type, or method" msgstr "" -#: mcs/mcs/class.cs:2606 +#: mcs/mcs/class.cs:2610 #, csharp-format msgid "`{0}': member names cannot be the same as their enclosing type" msgstr "" -#: mcs/mcs/class.cs:2684 +#: mcs/mcs/class.cs:2688 #, csharp-format msgid "" "Primary constructor of type `{0}' has parameter of same name as containing " "type" msgstr "" -#: mcs/mcs/class.cs:2692 +#: mcs/mcs/class.cs:2696 #, csharp-format msgid "" "Primary constructor of type `{0}' has parameter of same name as type " "parameter `{1}'" msgstr "" -#: mcs/mcs/class.cs:2774 +#: mcs/mcs/class.cs:2778 msgid "" "The class System.Object cannot have a base class or implement an interface." msgstr "" -#: mcs/mcs/class.cs:2783 +#: mcs/mcs/class.cs:2787 #, csharp-format msgid "Attribute `{0}' is only valid on classes derived from System.Attribute" msgstr "" -#: mcs/mcs/class.cs:2788 +#: mcs/mcs/class.cs:2792 msgid "" "Attribute `System.Diagnostics.ConditionalAttribute' is only valid on methods " "or attribute classes" msgstr "" -#: mcs/mcs/class.cs:2817 +#: mcs/mcs/class.cs:2821 #, csharp-format msgid "`{0}': an abstract class cannot be sealed or static" msgstr "" -#: mcs/mcs/class.cs:2821 +#: mcs/mcs/class.cs:2825 #, csharp-format msgid "`{0}': a class cannot be both static and sealed" msgstr "" -#: mcs/mcs/class.cs:2826 +#: mcs/mcs/class.cs:2830 #, csharp-format msgid "`{0}': Static classes cannot have primary constructor" msgstr "" -#: mcs/mcs/class.cs:2832 +#: mcs/mcs/class.cs:2836 #, csharp-format msgid "`{0}': Static classes cannot contain user-defined operators" msgstr "" -#: mcs/mcs/class.cs:2837 +#: mcs/mcs/class.cs:2841 #, csharp-format msgid "`{0}': Static classes cannot contain destructor" msgstr "" -#: mcs/mcs/class.cs:2842 +#: mcs/mcs/class.cs:2846 #, csharp-format msgid "`{0}': cannot declare indexers in a static class" msgstr "" -#: mcs/mcs/class.cs:2850 +#: mcs/mcs/class.cs:2854 #, csharp-format msgid "`{0}': Static classes cannot have instance constructors" msgstr "" -#: mcs/mcs/class.cs:2854 +#: mcs/mcs/class.cs:2858 #, csharp-format msgid "`{0}': cannot declare instance members in a static class" msgstr "" -#: mcs/mcs/class.cs:2896 +#: mcs/mcs/class.cs:2900 #, csharp-format msgid "`{0}': Cannot derive from type parameter `{1}'" msgstr "" -#: mcs/mcs/class.cs:2900 +#: mcs/mcs/class.cs:2904 #, csharp-format msgid "`{0}': Cannot derive from static class `{1}'" msgstr "" -#: mcs/mcs/class.cs:2904 +#: mcs/mcs/class.cs:2908 #, csharp-format msgid "`{0}': cannot derive from sealed type `{1}'" msgstr "" -#: mcs/mcs/class.cs:2907 +#: mcs/mcs/class.cs:2911 #, csharp-format msgid "" "Static class `{0}' cannot derive from type `{1}'. Static classes must derive " "from object" msgstr "" -#: mcs/mcs/class.cs:2918 +#: mcs/mcs/class.cs:2922 #, csharp-format msgid "`{0}' cannot derive from special class `{1}'" msgstr "" -#: mcs/mcs/class.cs:2928 +#: mcs/mcs/class.cs:2932 #, csharp-format msgid "" "Inconsistent accessibility: base class `{0}' is less accessible than class " "`{1}'" msgstr "" -#: mcs/mcs/class.cs:2936 +#: mcs/mcs/class.cs:2940 #, csharp-format msgid "Static class `{0}' cannot implement interfaces" msgstr "" -#: mcs/mcs/class.cs:3047 mcs/mcs/class.cs:3061 +#: mcs/mcs/class.cs:3051 mcs/mcs/class.cs:3065 #, csharp-format msgid "Struct member `{0}' of type `{1}' causes a cycle in the struct layout" msgstr "" -#: mcs/mcs/class.cs:3352 +#: mcs/mcs/class.cs:3356 #, csharp-format msgid "Do not override `{0}'. Use destructor syntax instead" msgstr "" -#: mcs/mcs/class.cs:3355 +#: mcs/mcs/class.cs:3359 #, csharp-format msgid "`{0}' is marked as an override but no suitable {1} found to override" msgstr "" -#: mcs/mcs/class.cs:3361 +#: mcs/mcs/class.cs:3365 #, csharp-format msgid "`{0}': cannot override because `{1}' is not an event" msgstr "" -#: mcs/mcs/class.cs:3364 +#: mcs/mcs/class.cs:3368 #, csharp-format msgid "`{0}': cannot override because `{1}' is not a property" msgstr "" -#: mcs/mcs/class.cs:3367 +#: mcs/mcs/class.cs:3371 #, csharp-format msgid "`{0}': cannot override because `{1}' is not a method" msgstr "" -#: mcs/mcs/class.cs:3386 +#: mcs/mcs/class.cs:3390 #, csharp-format msgid "" "`{0}' cannot override inherited members `{1}' and `{2}' because they have " "the same signature when used in type `{3}'" msgstr "" -#: mcs/mcs/class.cs:3444 mcs/mcs/field.cs:203 +#: mcs/mcs/class.cs:3448 mcs/mcs/field.cs:203 #, csharp-format msgid "`{0}' hides inherited abstract member `{1}'" msgstr "" -#: mcs/mcs/class.cs:3470 +#: mcs/mcs/class.cs:3474 #, csharp-format msgid "" "`{0}': cannot override inherited member `{1}' because it is not marked " "virtual, abstract or override" msgstr "" -#: mcs/mcs/class.cs:3478 +#: mcs/mcs/class.cs:3482 #, csharp-format msgid "`{0}': cannot override inherited member `{1}' because it is sealed" msgstr "" -#: mcs/mcs/class.cs:3487 +#: mcs/mcs/class.cs:3491 #, csharp-format msgid "`{0}': type must be `{1}' to match overridden member `{2}'" msgstr "" -#: mcs/mcs/class.cs:3490 +#: mcs/mcs/class.cs:3494 #, csharp-format msgid "`{0}': return type must be `{1}' to match overridden member `{2}'" msgstr "" -#: mcs/mcs/class.cs:3558 +#: mcs/mcs/class.cs:3562 #, csharp-format msgid "A partial method `{0}' cannot explicitly implement an interface" msgstr "" -#: mcs/mcs/class.cs:3564 +#: mcs/mcs/class.cs:3568 #, csharp-format msgid "The type `{0}' in explicit interface declaration is not an interface" msgstr "" -#: mcs/mcs/class.cs:3599 -#, csharp-format -msgid "" -"Inconsistent accessibility: parameter type `{0}' is less accessible than " -"indexer `{1}'" -msgstr "" - #: mcs/mcs/class.cs:3603 #, csharp-format msgid "" "Inconsistent accessibility: parameter type `{0}' is less accessible than " -"operator `{1}'" +"indexer `{1}'" msgstr "" #: mcs/mcs/class.cs:3607 #, csharp-format msgid "" "Inconsistent accessibility: parameter type `{0}' is less accessible than " +"operator `{1}'" +msgstr "" + +#: mcs/mcs/class.cs:3611 +#, csharp-format +msgid "" +"Inconsistent accessibility: parameter type `{0}' is less accessible than " "method `{1}'" msgstr "" -#: mcs/mcs/class.cs:3667 +#: mcs/mcs/class.cs:3671 #, csharp-format msgid "" "`{0}': cannot change access modifiers when overriding `{1}' inherited member " "`{2}'" msgstr "" -#: mcs/mcs/class.cs:3676 +#: mcs/mcs/class.cs:3680 #, csharp-format msgid "`{0}': static types cannot be used as return types" msgstr "" -#: mcs/mcs/class.cs:3737 +#: mcs/mcs/class.cs:3741 #, csharp-format msgid "" "`{0}': Cannot specify constraints for overrides and explicit interface " "implementation methods" msgstr "" -#: mcs/mcs/class.cs:3804 +#: mcs/mcs/class.cs:3808 #, csharp-format msgid "New virtual member `{0}' is declared in a sealed class `{1}'" msgstr "" -#: mcs/mcs/class.cs:3819 +#: mcs/mcs/class.cs:3823 msgid "Inconsistent accessibility: property type `" msgstr "" -#: mcs/mcs/class.cs:3824 +#: mcs/mcs/class.cs:3828 msgid "Inconsistent accessibility: indexer return type `" msgstr "" -#: mcs/mcs/class.cs:3830 mcs/mcs/class.cs:3835 mcs/mcs/delegate.cs:180 +#: mcs/mcs/class.cs:3834 mcs/mcs/class.cs:3839 mcs/mcs/delegate.cs:180 msgid "Inconsistent accessibility: return type `" msgstr "" -#: mcs/mcs/class.cs:3840 +#: mcs/mcs/class.cs:3844 #, csharp-format msgid "" "Inconsistent accessibility: event type `{0}' is less accessible than event " "`{1}'" msgstr "" -#: mcs/mcs/class.cs:3844 +#: mcs/mcs/class.cs:3848 msgid "Inconsistent accessibility: field type `" msgstr "" -#: mcs/mcs/class.cs:3856 +#: mcs/mcs/class.cs:3860 #, csharp-format msgid "" "Parameters or local variables of type `{0}' cannot be declared in async " "methods or iterators" msgstr "" -#: mcs/mcs/class.cs:3860 +#: mcs/mcs/class.cs:3864 #, csharp-format msgid "" "Local variables of type `{0}' cannot be used inside anonymous methods, " "lambda expressions or query expressions" msgstr "" -#: mcs/mcs/class.cs:3864 +#: mcs/mcs/class.cs:3868 #, csharp-format msgid "Field or property cannot be of type `{0}'" msgstr "" @@ -1132,20 +1132,15 @@ msgid "" "to override)" msgstr "" -#: mcs/mcs/constant.cs:2154 -msgid "" -"An argument to nameof operator cannot be method group with type arguments" -msgstr "" - -#: mcs/mcs/constant.cs:2196 +#: mcs/mcs/constant.cs:2191 msgid "An alias-qualified name is not an expression" msgstr "" -#: mcs/mcs/constant.cs:2220 +#: mcs/mcs/constant.cs:2204 msgid "An argument to nameof operator cannot include sub-expression" msgstr "" -#: mcs/mcs/constant.cs:2228 +#: mcs/mcs/constant.cs:2212 msgid "Expression does not have a name" msgstr "" @@ -1293,304 +1288,309 @@ msgid "" "reference" msgstr "" -#: mcs/mcs/ecore.cs:243 +#: mcs/mcs/ecore.cs:244 #, csharp-format msgid "`{0}' is inaccessible due to its protection level" msgstr "" -#: mcs/mcs/ecore.cs:248 +#: mcs/mcs/ecore.cs:249 #, csharp-format msgid "The expression being assigned to `{0}' must be constant" msgstr "" -#: mcs/mcs/ecore.cs:253 +#: mcs/mcs/ecore.cs:254 #, csharp-format msgid "" "A constant `{0}' of reference type `{1}' can only be initialized with null" msgstr "" -#: mcs/mcs/ecore.cs:274 +#: mcs/mcs/ecore.cs:275 msgid "Keyword `void' cannot be used in this context" msgstr "" -#: mcs/mcs/ecore.cs:299 +#: mcs/mcs/ecore.cs:304 #, csharp-format msgid "Cannot convert type `{0}' to `{1}'" msgstr "" -#: mcs/mcs/ecore.cs:310 +#: mcs/mcs/ecore.cs:315 #, csharp-format msgid "" "Cannot implicitly convert type `{0}' to `{1}'. An explicit conversion exists " "(are you missing a cast?)" msgstr "" -#: mcs/mcs/ecore.cs:313 +#: mcs/mcs/ecore.cs:318 #, csharp-format msgid "Cannot implicitly convert type `{0}' to `{1}'" msgstr "" -#: mcs/mcs/ecore.cs:344 +#: mcs/mcs/ecore.cs:349 #, csharp-format msgid "The {0} `{1}' cannot be used with type arguments" msgstr "" -#: mcs/mcs/ecore.cs:356 +#: mcs/mcs/ecore.cs:361 #, csharp-format msgid "`{0}' does not contain a definition for `{1}'" msgstr "" -#: mcs/mcs/ecore.cs:365 +#: mcs/mcs/ecore.cs:370 msgid "A ref or out argument must be an assignable variable" msgstr "" -#: mcs/mcs/ecore.cs:367 +#: mcs/mcs/ecore.cs:372 msgid "" "The left-hand side of an assignment must be a variable, a property or an " "indexer" msgstr "" -#: mcs/mcs/ecore.cs:373 +#: mcs/mcs/ecore.cs:378 msgid "The operation in question is undefined on void pointers" msgstr "" -#: mcs/mcs/ecore.cs:524 mcs/mcs/statement.cs:3972 mcs/mcs/statement.cs:3974 +#: mcs/mcs/ecore.cs:529 mcs/mcs/statement.cs:3994 mcs/mcs/statement.cs:3996 #, csharp-format msgid "Internal compiler error: {0}" msgstr "" -#: mcs/mcs/ecore.cs:586 mcs/mcs/expression.cs:1840 mcs/mcs/expression.cs:7929 +#: mcs/mcs/ecore.cs:591 mcs/mcs/expression.cs:1840 mcs/mcs/expression.cs:7929 #: mcs/mcs/expression.cs:7937 msgid "A constant value is expected" msgstr "" -#: mcs/mcs/ecore.cs:598 +#: mcs/mcs/ecore.cs:603 msgid "" "An attribute argument must be a constant expression, typeof expression or " "array creation expression" msgstr "" -#: mcs/mcs/ecore.cs:601 +#: mcs/mcs/ecore.cs:606 #, csharp-format msgid "" "Attribute constructor parameter has type `{0}', which is not a valid " "attribute parameter type" msgstr "" -#: mcs/mcs/ecore.cs:790 +#: mcs/mcs/ecore.cs:795 #, csharp-format msgid "The class `{0}' has no constructors defined" msgstr "" -#: mcs/mcs/ecore.cs:1010 +#: mcs/mcs/ecore.cs:962 msgid "An element access expression cannot use named argument" msgstr "" -#: mcs/mcs/ecore.cs:1023 +#: mcs/mcs/ecore.cs:975 #, csharp-format msgid "The `{0}' operator cannot be applied to operand of type `{1}'" msgstr "" -#: mcs/mcs/ecore.cs:1029 +#: mcs/mcs/ecore.cs:981 msgid "An expression tree cannot contain an unsafe pointer operation" msgstr "" -#: mcs/mcs/ecore.cs:1034 +#: mcs/mcs/ecore.cs:986 msgid "An expression tree cannot contain a null propagating operator" msgstr "" -#: mcs/mcs/ecore.cs:1039 +#: mcs/mcs/ecore.cs:991 msgid "" "The left-hand side of an assignment cannot contain a null propagating " "operator" msgstr "" -#: mcs/mcs/ecore.cs:1135 +#: mcs/mcs/ecore.cs:1087 #, csharp-format msgid "`{0}' is a `{1}' but a `{2}' was expected" msgstr "" -#: mcs/mcs/ecore.cs:1168 +#: mcs/mcs/ecore.cs:1120 #, csharp-format msgid "Expression denotes a `{0}', where a `{1}' was expected" msgstr "" -#: mcs/mcs/ecore.cs:1178 +#: mcs/mcs/ecore.cs:1130 msgid "Pointers and fixed size buffers may only be used in an unsafe context" msgstr "" -#: mcs/mcs/ecore.cs:1231 +#: mcs/mcs/ecore.cs:1183 msgid "A pointer must be indexed by only one value" msgstr "" -#: mcs/mcs/ecore.cs:2712 +#: mcs/mcs/ecore.cs:2664 #, csharp-format msgid "The name `{0}' does not exist in the current context" msgstr "" -#: mcs/mcs/ecore.cs:2788 +#: mcs/mcs/ecore.cs:2740 #, csharp-format msgid "" "Dynamic keyword requires `{0}' to be defined. Are you missing System.Core." "dll assembly reference?" msgstr "" -#: mcs/mcs/ecore.cs:2869 +#: mcs/mcs/ecore.cs:2821 #, csharp-format msgid "" "A local variable `{0}' cannot be used before it is declared. Consider " "renaming the local variable when it hides the member `{1}'" msgstr "" -#: mcs/mcs/ecore.cs:2953 +#: mcs/mcs/ecore.cs:2905 #, csharp-format msgid "A local variable `{0}' cannot be used before it is declared" msgstr "" -#: mcs/mcs/ecore.cs:3106 +#: mcs/mcs/ecore.cs:3058 msgid "System.Void cannot be used from C#. Consider using `void'" msgstr "" -#: mcs/mcs/ecore.cs:3268 +#: mcs/mcs/ecore.cs:3220 #, csharp-format msgid "" "The type or namespace name `{0}' could not be found in the global namespace. " "Are you missing {1} assembly reference?" msgstr "" -#: mcs/mcs/ecore.cs:3272 +#: mcs/mcs/ecore.cs:3224 #, csharp-format msgid "" "The type or namespace name `{0}' does not exist in the namespace `{1}'. Are " "you missing {2} assembly reference?" msgstr "" -#: mcs/mcs/ecore.cs:3522 +#: mcs/mcs/ecore.cs:3474 #, csharp-format msgid "Cannot call an abstract base member `{0}'" msgstr "" -#: mcs/mcs/ecore.cs:3529 +#: mcs/mcs/ecore.cs:3481 #, csharp-format msgid "" "Cannot access protected member `{0}' via a qualifier of type `{1}'. The " "qualifier must be of type `{2}' or derived from it" msgstr "" -#: mcs/mcs/ecore.cs:3562 +#: mcs/mcs/ecore.cs:3514 #, csharp-format msgid "" "Fields of static readonly field `{0}' cannot be assigned to (except in a " "static constructor or a variable initializer)" msgstr "" -#: mcs/mcs/ecore.cs:3565 +#: mcs/mcs/ecore.cs:3517 #, csharp-format msgid "" "Members of readonly field `{0}' cannot be modified (except in a constructor " "or a variable initializer)" msgstr "" -#: mcs/mcs/ecore.cs:3574 +#: mcs/mcs/ecore.cs:3526 #, csharp-format msgid "" "Members of value type `{0}' cannot be assigned using a property `{1}' object " "initializer" msgstr "" -#: mcs/mcs/ecore.cs:3578 +#: mcs/mcs/ecore.cs:3530 #, csharp-format msgid "" "Cannot modify a value type return value of `{0}'. Consider storing the value " "in a temporary variable" msgstr "" -#: mcs/mcs/ecore.cs:3591 +#: mcs/mcs/ecore.cs:3543 #, csharp-format msgid "Cannot assign to members of `{0}' because it is a `{1}'" msgstr "" -#: mcs/mcs/ecore.cs:3614 +#: mcs/mcs/ecore.cs:3566 #, csharp-format msgid "" "Static member `{0}' cannot be accessed with an instance reference, qualify " "it with a type name instead" msgstr "" -#: mcs/mcs/ecore.cs:3629 +#: mcs/mcs/ecore.cs:3581 #, csharp-format msgid "" "A field initializer cannot reference the nonstatic field, method, or " "property `{0}'" msgstr "" -#: mcs/mcs/ecore.cs:3635 +#: mcs/mcs/ecore.cs:3587 msgid "Constructor initializer cannot access primary constructor parameters" msgstr "" -#: mcs/mcs/ecore.cs:3637 +#: mcs/mcs/ecore.cs:3589 #, csharp-format msgid "" "An object reference is required to access primary constructor parameter `{0}'" msgstr "" -#: mcs/mcs/ecore.cs:3642 +#: mcs/mcs/ecore.cs:3594 #, csharp-format msgid "An object reference is required to access non-static member `{0}'" msgstr "" -#: mcs/mcs/ecore.cs:3653 +#: mcs/mcs/ecore.cs:3605 #, csharp-format msgid "" "Cannot access a nonstatic member of outer type `{0}' via nested type `{1}'" msgstr "" -#: mcs/mcs/ecore.cs:3681 +#: mcs/mcs/ecore.cs:3633 msgid "Cannot modify the result of an unboxing conversion" msgstr "" -#: mcs/mcs/ecore.cs:3805 +#: mcs/mcs/ecore.cs:3762 msgid "An argument to nameof operator cannot be extension method group" msgstr "" -#: mcs/mcs/ecore.cs:3881 +#: mcs/mcs/ecore.cs:3820 #, csharp-format msgid "" "Type `{0}' does not contain a member `{1}' and the best extension method " "overload `{2}' requires an instance of type `{3}'" msgstr "" -#: mcs/mcs/ecore.cs:3885 +#: mcs/mcs/ecore.cs:3824 #, csharp-format msgid "" "Type `{0}' does not contain a member `{1}' and the best extension method " "overload `{2}' has some invalid arguments" msgstr "" -#: mcs/mcs/ecore.cs:4033 +#: mcs/mcs/ecore.cs:3972 msgid "An expression tree cannot contain an expression with method group" msgstr "" -#: mcs/mcs/ecore.cs:4039 +#: mcs/mcs/ecore.cs:3978 msgid "" "Partial methods with only a defining declaration or removed conditional " "methods cannot be used in an expression tree" msgstr "" -#: mcs/mcs/ecore.cs:4093 +#: mcs/mcs/ecore.cs:4032 #, csharp-format msgid "" "Cannot convert method group `{0}' to non-delegate type `{1}'. Consider using " "parentheses to invoke the method" msgstr "" -#: mcs/mcs/ecore.cs:4963 +#: mcs/mcs/ecore.cs:4170 +msgid "" +"An argument to nameof operator cannot be method group with type arguments" +msgstr "" + +#: mcs/mcs/ecore.cs:4923 #, csharp-format msgid "" "The type `{0}' does not contain a constructor that takes `{1}' arguments" msgstr "" -#: mcs/mcs/ecore.cs:5677 +#: mcs/mcs/ecore.cs:5637 #, csharp-format msgid "" "Type `{0}' does not contain a member `{1}' and the best extension method " @@ -1598,205 +1598,205 @@ msgid "" "without the extension method syntax" msgstr "" -#: mcs/mcs/ecore.cs:5716 +#: mcs/mcs/ecore.cs:5676 #, csharp-format msgid "" "The call is ambiguous between the following methods or properties: `{0}' and " "`{1}'" msgstr "" -#: mcs/mcs/ecore.cs:5777 +#: mcs/mcs/ecore.cs:5737 #, csharp-format msgid "" "The best overloaded collection initalizer method `{0}' cannot have `ref' or " "`out' modifier" msgstr "" -#: mcs/mcs/ecore.cs:5781 +#: mcs/mcs/ecore.cs:5741 #, csharp-format msgid "" "The best overloaded collection initalizer method `{0}' has some invalid " "arguments" msgstr "" -#: mcs/mcs/ecore.cs:5784 +#: mcs/mcs/ecore.cs:5744 #, csharp-format msgid "Delegate `{0}' has some invalid arguments" msgstr "" -#: mcs/mcs/ecore.cs:5788 +#: mcs/mcs/ecore.cs:5748 #, csharp-format msgid "The best overloaded method match for `{0}' has some invalid arguments" msgstr "" -#: mcs/mcs/ecore.cs:5797 +#: mcs/mcs/ecore.cs:5757 #, csharp-format msgid "" "Argument `#{0}' does not require `{1}' modifier. Consider removing `{1}' " "modifier" msgstr "" -#: mcs/mcs/ecore.cs:5800 +#: mcs/mcs/ecore.cs:5760 #, csharp-format msgid "Argument `#{0}' is missing `{1}' modifier" msgstr "" -#: mcs/mcs/ecore.cs:5817 +#: mcs/mcs/ecore.cs:5777 #, csharp-format msgid "Argument `#{0}' cannot convert `{1}' expression to type `{2}'" msgstr "" -#: mcs/mcs/ecore.cs:5869 +#: mcs/mcs/ecore.cs:5829 #, csharp-format msgid "" "The type arguments for method `{0}' cannot be inferred from the usage. Try " "specifying the type arguments explicitly" msgstr "" -#: mcs/mcs/ecore.cs:5898 +#: mcs/mcs/ecore.cs:5858 #, csharp-format msgid "No overload for method `{0}' takes `{1}' arguments" msgstr "" -#: mcs/mcs/ecore.cs:6001 +#: mcs/mcs/ecore.cs:5961 #, csharp-format msgid "The delegate `{0}' does not contain a parameter named `{1}'" msgstr "" -#: mcs/mcs/ecore.cs:6006 +#: mcs/mcs/ecore.cs:5966 #, csharp-format msgid "" "The best overloaded method match for `{0}' does not contain a parameter " "named `{1}'" msgstr "" -#: mcs/mcs/ecore.cs:6016 +#: mcs/mcs/ecore.cs:5976 #, csharp-format msgid "" "Named argument `{0}' cannot be used for a parameter which has positional " "argument specified" msgstr "" -#: mcs/mcs/ecore.cs:6391 +#: mcs/mcs/ecore.cs:6356 msgid "" "You cannot use fixed size buffers contained in unfixed expressions. Try " "using the fixed statement" msgstr "" -#: mcs/mcs/ecore.cs:6396 +#: mcs/mcs/ecore.cs:6361 #, csharp-format msgid "`{0}': Fixed size buffers can only be accessed through locals or fields" msgstr "" -#: mcs/mcs/ecore.cs:6476 +#: mcs/mcs/ecore.cs:6446 #, csharp-format msgid "" "A static readonly field `{0}' cannot be passed ref or out (except in a " "static constructor)" msgstr "" -#: mcs/mcs/ecore.cs:6479 +#: mcs/mcs/ecore.cs:6449 #, csharp-format msgid "" "A readonly field `{0}' cannot be passed ref or out (except in a constructor)" msgstr "" -#: mcs/mcs/ecore.cs:6493 +#: mcs/mcs/ecore.cs:6463 #, csharp-format msgid "" "Fields of static readonly field `{0}' cannot be passed ref or out (except in " "a static constructor)" msgstr "" -#: mcs/mcs/ecore.cs:6496 +#: mcs/mcs/ecore.cs:6466 #, csharp-format msgid "" "Members of readonly field `{0}' cannot be passed ref or out (except in a " "constructor)" msgstr "" -#: mcs/mcs/ecore.cs:6503 +#: mcs/mcs/ecore.cs:6473 #, csharp-format msgid "" "A static readonly field `{0}' cannot be assigned to (except in a static " "constructor or a variable initializer)" msgstr "" -#: mcs/mcs/ecore.cs:6506 +#: mcs/mcs/ecore.cs:6476 #, csharp-format msgid "" "A readonly field `{0}' cannot be assigned to (except in a constructor or a " "variable initializer)" msgstr "" -#: mcs/mcs/ecore.cs:6573 +#: mcs/mcs/ecore.cs:6543 #, csharp-format msgid "Use of possibly unassigned field `{0}'" msgstr "" -#: mcs/mcs/ecore.cs:6989 +#: mcs/mcs/ecore.cs:6959 #, csharp-format msgid "Property or event `{0}' is not supported by the C# language" msgstr "" -#: mcs/mcs/ecore.cs:7109 +#: mcs/mcs/ecore.cs:7079 #, csharp-format msgid "Use of possibly unassigned auto-implemented property `{0}'" msgstr "" -#: mcs/mcs/ecore.cs:7294 +#: mcs/mcs/ecore.cs:7272 #, csharp-format msgid "A range variable `{0}' may not be passes as `ref' or `out' parameter" msgstr "" -#: mcs/mcs/ecore.cs:7317 +#: mcs/mcs/ecore.cs:7295 #, csharp-format msgid "Property or indexer `{0}' cannot be assigned to (it is read-only)" msgstr "" -#: mcs/mcs/ecore.cs:7325 +#: mcs/mcs/ecore.cs:7303 #, csharp-format msgid "" "The property or indexer `{0}' cannot be used in this context because the set " "accessor is inaccessible" msgstr "" -#: mcs/mcs/ecore.cs:7405 +#: mcs/mcs/ecore.cs:7383 #, csharp-format msgid "" "The property or indexer `{0}' cannot be used in this context because it " "lacks the `get' accessor" msgstr "" -#: mcs/mcs/ecore.cs:7412 +#: mcs/mcs/ecore.cs:7390 #, csharp-format msgid "" "The property or indexer `{0}' cannot be used in this context because the get " "accessor is inaccessible" msgstr "" -#: mcs/mcs/ecore.cs:7594 +#: mcs/mcs/ecore.cs:7572 #, csharp-format msgid "" "The event `{0}' can only appear on the left hand side of `+=' or `-=' " "operator" msgstr "" -#: mcs/mcs/ecore.cs:7598 +#: mcs/mcs/ecore.cs:7576 #, csharp-format msgid "" "The event `{0}' can only appear on the left hand side of += or -= when used " "outside of the type `{1}'" msgstr "" -#: mcs/mcs/ecore.cs:7770 +#: mcs/mcs/ecore.cs:7753 #, csharp-format msgid "" "An implicitly typed local variable declaration cannot be initialized with " "`{0}'" msgstr "" -#: mcs/mcs/ecore.cs:7785 +#: mcs/mcs/ecore.cs:7768 msgid "" "The contextual keyword `var' may only appear within a local variable " "declaration" @@ -2201,98 +2201,98 @@ msgid "" "the dynamic arguments or eliminating the base access" msgstr "" -#: mcs/mcs/expression.cs:11006 +#: mcs/mcs/expression.cs:11015 msgid "An expression tree may not contain a base access" msgstr "" -#: mcs/mcs/expression.cs:11024 +#: mcs/mcs/expression.cs:11033 msgid "Keyword `base' is not available in a static method" msgstr "" -#: mcs/mcs/expression.cs:11026 +#: mcs/mcs/expression.cs:11035 msgid "Keyword `base' is not available in the current context" msgstr "" -#: mcs/mcs/expression.cs:11064 +#: mcs/mcs/expression.cs:11073 msgid "" "A property, indexer or dynamic member access may not be passed as `ref' or " "`out' parameter" msgstr "" -#: mcs/mcs/expression.cs:11410 +#: mcs/mcs/expression.cs:11419 #, csharp-format msgid "Array elements cannot be of type `{0}'" msgstr "" -#: mcs/mcs/expression.cs:11413 +#: mcs/mcs/expression.cs:11422 #, csharp-format msgid "Array elements cannot be of static type `{0}'" msgstr "" -#: mcs/mcs/expression.cs:11589 +#: mcs/mcs/expression.cs:11598 msgid "Cannot use a negative size with stackalloc" msgstr "" -#: mcs/mcs/expression.cs:11593 +#: mcs/mcs/expression.cs:11602 msgid "Cannot use stackalloc in finally or catch" msgstr "" -#: mcs/mcs/expression.cs:11752 +#: mcs/mcs/expression.cs:11761 #, csharp-format msgid "" "Member `{0}' cannot be initialized. An object initializer may only be used " "for fields, or properties" msgstr "" -#: mcs/mcs/expression.cs:11760 +#: mcs/mcs/expression.cs:11769 #, csharp-format msgid "" "Static field or property `{0}' cannot be assigned in an object initializer" msgstr "" -#: mcs/mcs/expression.cs:11831 +#: mcs/mcs/expression.cs:11840 msgid "" "An expression tree cannot contain a collection initializer with extension " "method" msgstr "" -#: mcs/mcs/expression.cs:11869 +#: mcs/mcs/expression.cs:11878 msgid "Expression tree cannot contain a dictionary initializer" msgstr "" -#: mcs/mcs/expression.cs:11994 +#: mcs/mcs/expression.cs:12003 #, csharp-format msgid "" "A field or property `{0}' cannot be initialized with a collection object " "initializer because type `{1}' does not implement `{2}' interface" msgstr "" -#: mcs/mcs/expression.cs:12005 +#: mcs/mcs/expression.cs:12014 #, csharp-format msgid "Inconsistent `{0}' member declaration" msgstr "" -#: mcs/mcs/expression.cs:12013 +#: mcs/mcs/expression.cs:12022 #, csharp-format msgid "" "An object initializer includes more than one member `{0}' initialization" msgstr "" -#: mcs/mcs/expression.cs:12031 +#: mcs/mcs/expression.cs:12040 #, csharp-format msgid "Cannot initialize object of type `{0}' with a collection initializer" msgstr "" -#: mcs/mcs/expression.cs:12176 +#: mcs/mcs/expression.cs:12185 msgid "" "Object and collection initializers cannot be used to instantiate a delegate" msgstr "" -#: mcs/mcs/expression.cs:12392 +#: mcs/mcs/expression.cs:12402 msgid "Anonymous types cannot be used in this expression" msgstr "" -#: mcs/mcs/expression.cs:12486 +#: mcs/mcs/expression.cs:12496 #, csharp-format msgid "An anonymous type property `{0}' cannot be initialized with `{1}'" msgstr "" @@ -2452,60 +2452,60 @@ msgstr "" msgid "The {2} type parameter `{0}' must be {3} valid on `{1}{4}'" msgstr "" -#: mcs/mcs/generic.cs:2247 +#: mcs/mcs/generic.cs:2274 #, csharp-format msgid "`{0}': static classes cannot be used as generic arguments" msgstr "" -#: mcs/mcs/generic.cs:2254 +#: mcs/mcs/generic.cs:2281 #, csharp-format msgid "The type `{0}' may not be used as a type argument" msgstr "" -#: mcs/mcs/generic.cs:2295 +#: mcs/mcs/generic.cs:2322 msgid "Unbound generic name is not valid in this context" msgstr "" -#: mcs/mcs/generic.cs:2355 +#: mcs/mcs/generic.cs:2382 msgid "Variant type parameters can only be used with interfaces and delegates" msgstr "" -#: mcs/mcs/generic.cs:2424 +#: mcs/mcs/generic.cs:2451 #, csharp-format msgid "" "Partial method declarations of `{0}' have inconsistent constraints for type " "parameter `{1}'" msgstr "" -#: mcs/mcs/generic.cs:2440 +#: mcs/mcs/generic.cs:2467 #, csharp-format msgid "" "Partial declarations of `{0}' have inconsistent constraints for type " "parameter `{1}'" msgstr "" -#: mcs/mcs/generic.cs:2627 +#: mcs/mcs/generic.cs:2654 #, csharp-format msgid "" "The type `{0}' must be a reference type in order to use it as type parameter " "`{1}' in the generic type or method `{2}'" msgstr "" -#: mcs/mcs/generic.cs:2637 +#: mcs/mcs/generic.cs:2664 #, csharp-format msgid "" "The type `{0}' must be a non-nullable value type in order to use it as type " "parameter `{1}' in the generic type or method `{2}'" msgstr "" -#: mcs/mcs/generic.cs:2698 +#: mcs/mcs/generic.cs:2725 #, csharp-format msgid "" "The type `{0}' must have a public parameterless constructor in order to use " "it as parameter `{1}' in the generic type or method `{2}'" msgstr "" -#: mcs/mcs/generic.cs:2754 +#: mcs/mcs/generic.cs:2781 #, csharp-format msgid "" "The type `{0}' cannot be used as type parameter `{1}' in the generic type or " @@ -2513,7 +2513,7 @@ msgid "" "`{3}'" msgstr "" -#: mcs/mcs/generic.cs:2760 +#: mcs/mcs/generic.cs:2787 #, csharp-format msgid "" "The type `{0}' cannot be used as type parameter `{1}' in the generic type or " @@ -2521,21 +2521,21 @@ msgid "" "`{3}'" msgstr "" -#: mcs/mcs/generic.cs:2764 +#: mcs/mcs/generic.cs:2791 #, csharp-format msgid "" "The type `{0}' cannot be used as type parameter `{1}' in the generic type or " "method `{2}'. The nullable type `{0}' does not satisfy constraint `{3}'" msgstr "" -#: mcs/mcs/generic.cs:2769 +#: mcs/mcs/generic.cs:2796 #, csharp-format msgid "" "The type `{0}' cannot be used as type parameter `{1}' in the generic type or " "method `{2}'. There is no boxing conversion from `{0}' to `{3}'" msgstr "" -#: mcs/mcs/generic.cs:2774 +#: mcs/mcs/generic.cs:2801 #, csharp-format msgid "" "The type `{0}' cannot be used as type parameter `{1}' in the generic type or " @@ -2558,48 +2558,48 @@ msgstr "" msgid "Cannot yield a value in the body of a catch clause" msgstr "" -#: mcs/mcs/iterators.cs:1191 +#: mcs/mcs/iterators.cs:1192 #, csharp-format msgid "" "The body of `{0}' cannot be an iterator block because `{1}' is not an " "iterator interface type" msgstr "" -#: mcs/mcs/iterators.cs:1204 +#: mcs/mcs/iterators.cs:1205 msgid "Iterators cannot have ref or out parameters" msgstr "" -#: mcs/mcs/iterators.cs:1210 +#: mcs/mcs/iterators.cs:1211 msgid "__arglist is not allowed in parameter list of iterators" msgstr "" -#: mcs/mcs/iterators.cs:1216 +#: mcs/mcs/iterators.cs:1217 msgid "Iterators cannot have unsafe parameters or yield types" msgstr "" -#: mcs/mcs/iterators.cs:1222 mcs/mcs/statement.cs:6327 +#: mcs/mcs/iterators.cs:1223 mcs/mcs/statement.cs:6349 msgid "Unsafe code may not appear in iterators" msgstr "" -#: mcs/mcs/ikvm.cs:286 +#: mcs/mcs/ikvm.cs:287 msgid "SDK path could not be resolved" msgstr "" -#: mcs/mcs/ikvm.cs:509 +#: mcs/mcs/ikvm.cs:512 #, csharp-format msgid "" "An assembly with the same name `{0}' has already been imported. Consider " "removing one of the references or sign the assembly" msgstr "" -#: mcs/mcs/ikvm.cs:518 +#: mcs/mcs/ikvm.cs:521 #, csharp-format msgid "" "An assembly `{0}' with the same identity has already been imported. Consider " "removing one of the references" msgstr "" -#: mcs/mcs/ikvm.cs:637 +#: mcs/mcs/ikvm.cs:640 #, csharp-format msgid "Error opening icon file `{0}'. {1}" msgstr "" @@ -2691,63 +2691,63 @@ msgid "" "suffix `{1}' to create a literal of this type" msgstr "" -#: mcs/mcs/membercache.cs:1446 +#: mcs/mcs/membercache.cs:1482 msgid "" "A partial method declaration and partial method implementation cannot differ " "on use of `params' modifier" msgstr "" -#: mcs/mcs/membercache.cs:1449 +#: mcs/mcs/membercache.cs:1485 msgid "" "A partial method declaration and partial method implementation must be both " "an extension method or neither" msgstr "" -#: mcs/mcs/membercache.cs:1453 +#: mcs/mcs/membercache.cs:1489 #, csharp-format msgid "" "Overloaded contructor `{0}' cannot differ on use of parameter modifiers only" msgstr "" -#: mcs/mcs/membercache.cs:1457 +#: mcs/mcs/membercache.cs:1493 #, csharp-format msgid "" "Overloaded method `{0}' cannot differ on use of parameter modifiers only" msgstr "" -#: mcs/mcs/membercache.cs:1489 +#: mcs/mcs/membercache.cs:1525 msgid "" "A partial method declaration and partial method implementation must be both " "`static' or neither" msgstr "" -#: mcs/mcs/membercache.cs:1495 +#: mcs/mcs/membercache.cs:1531 msgid "" "A partial method declaration and partial method implementation must be both " "`unsafe' or neither" msgstr "" -#: mcs/mcs/membercache.cs:1503 +#: mcs/mcs/membercache.cs:1539 #, csharp-format msgid "A partial method `{0}' declaration is already defined" msgstr "" -#: mcs/mcs/membercache.cs:1507 +#: mcs/mcs/membercache.cs:1543 #, csharp-format msgid "A partial method `{0}' implementation is already defined" msgstr "" -#: mcs/mcs/membercache.cs:1518 mcs/mcs/property.cs:81 +#: mcs/mcs/membercache.cs:1554 mcs/mcs/property.cs:81 #, csharp-format msgid "A member `{0}' is already reserved" msgstr "" -#: mcs/mcs/membercache.cs:1529 +#: mcs/mcs/membercache.cs:1565 #, csharp-format msgid "Duplicate user-defined conversion in type `{0}'" msgstr "" -#: mcs/mcs/membercache.cs:1535 +#: mcs/mcs/membercache.cs:1571 #, csharp-format msgid "" "A member `{0}' is already defined. Rename this member or use different " @@ -3363,19 +3363,19 @@ msgid "" "an explicit StructLayout attribute" msgstr "" -#: mcs/mcs/property.cs:1410 +#: mcs/mcs/property.cs:1409 #, csharp-format msgid "`{0}': event must be of a delegate type" msgstr "" -#: mcs/mcs/property.cs:1690 +#: mcs/mcs/property.cs:1689 #, csharp-format msgid "" "The `{0}' attribute is valid only on an indexer that is not an explicit " "interface member declaration" msgstr "" -#: mcs/mcs/property.cs:1694 +#: mcs/mcs/property.cs:1693 msgid "Cannot set the `IndexerName' attribute on an indexer marked override" msgstr "" @@ -3398,111 +3398,111 @@ msgstr "" msgid "Control cannot leave the body of a finally clause" msgstr "" -#: mcs/mcs/statement.cs:1163 +#: mcs/mcs/statement.cs:1173 #, csharp-format msgid "" "An object of a type convertible to `{0}' is required for the return statement" msgstr "" -#: mcs/mcs/statement.cs:1176 +#: mcs/mcs/statement.cs:1186 #, csharp-format msgid "" "`{0}': A return keyword must not be followed by any expression when method " "returns void" msgstr "" -#: mcs/mcs/statement.cs:1195 +#: mcs/mcs/statement.cs:1205 msgid "Cannot return an expression of type `void'" msgstr "" -#: mcs/mcs/statement.cs:1203 mcs/mcs/statement.cs:1236 +#: mcs/mcs/statement.cs:1213 mcs/mcs/statement.cs:1246 msgid "" "Anonymous function or lambda expression converted to a void returning " "delegate cannot return a value" msgstr "" -#: mcs/mcs/statement.cs:1213 +#: mcs/mcs/statement.cs:1223 msgid "" "Async lambda expression or anonymous method converted to a `Task' cannot " "return a value. Consider returning `Task'" msgstr "" -#: mcs/mcs/statement.cs:1216 +#: mcs/mcs/statement.cs:1226 #, csharp-format msgid "" "`{0}': A return keyword must not be followed by an expression when async " "method returns `Task'. Consider using `Task' return type" msgstr "" -#: mcs/mcs/statement.cs:1227 +#: mcs/mcs/statement.cs:1237 #, csharp-format msgid "" "`{0}': The return expression type of async method must be `{1}' rather than " "`Task<{1}>'" msgstr "" -#: mcs/mcs/statement.cs:1267 +#: mcs/mcs/statement.cs:1277 #, csharp-format msgid "" "Cannot convert `{0}' to delegate type `{1}' because some of the return types " "in the block are not implicitly convertible to the delegate return type" msgstr "" -#: mcs/mcs/statement.cs:1339 +#: mcs/mcs/statement.cs:1349 msgid "" "Cannot return a value from iterators. Use the yield return statement to " "return a value, or yield break to end the iteration" msgstr "" -#: mcs/mcs/statement.cs:1401 +#: mcs/mcs/statement.cs:1411 #, csharp-format msgid "" "The label `{0}:' could not be found within the scope of the goto statement" msgstr "" -#: mcs/mcs/statement.cs:1741 +#: mcs/mcs/statement.cs:1751 msgid "A goto case is only valid inside a switch statement" msgstr "" -#: mcs/mcs/statement.cs:1764 +#: mcs/mcs/statement.cs:1774 msgid "" "A throw statement with no arguments is not allowed outside of a catch clause" msgstr "" -#: mcs/mcs/statement.cs:1769 +#: mcs/mcs/statement.cs:1779 msgid "" "A throw statement with no arguments is not allowed inside of a finally " "clause nested inside of the innermost catch clause" msgstr "" -#: mcs/mcs/statement.cs:1787 mcs/mcs/statement.cs:6886 +#: mcs/mcs/statement.cs:1797 mcs/mcs/statement.cs:6908 msgid "The type caught or thrown must be derived from System.Exception" msgstr "" -#: mcs/mcs/statement.cs:1954 +#: mcs/mcs/statement.cs:1964 msgid "No enclosing loop out of which to break or continue" msgstr "" -#: mcs/mcs/statement.cs:2123 +#: mcs/mcs/statement.cs:2133 msgid "A fixed statement cannot use an implicitly typed local variable" msgstr "" -#: mcs/mcs/statement.cs:2128 +#: mcs/mcs/statement.cs:2138 msgid "An implicitly typed local variable cannot be a constant" msgstr "" -#: mcs/mcs/statement.cs:2133 +#: mcs/mcs/statement.cs:2143 msgid "" "An implicitly typed local variable declarator must include an initializer" msgstr "" -#: mcs/mcs/statement.cs:2138 +#: mcs/mcs/statement.cs:2148 msgid "" "An implicitly typed local variable declaration cannot include multiple " "declarators" msgstr "" -#: mcs/mcs/statement.cs:2792 +#: mcs/mcs/statement.cs:2802 #, csharp-format msgid "" "A local variable named `{0}' cannot be declared in this scope because it " @@ -3510,124 +3510,124 @@ msgid "" "scope to denote something else" msgstr "" -#: mcs/mcs/statement.cs:2804 +#: mcs/mcs/statement.cs:2814 #, csharp-format msgid "A local variable named `{0}' is already defined in this scope" msgstr "" -#: mcs/mcs/statement.cs:2811 +#: mcs/mcs/statement.cs:2821 #, csharp-format msgid "" "The type parameter name `{0}' is the same as local variable or parameter name" msgstr "" -#: mcs/mcs/statement.cs:3752 +#: mcs/mcs/statement.cs:3769 #, csharp-format msgid "" "The out parameter `{0}' must be assigned to before control leaves the " "current method" msgstr "" -#: mcs/mcs/statement.cs:4028 +#: mcs/mcs/statement.cs:4050 msgid "Async methods cannot have ref or out parameters" msgstr "" -#: mcs/mcs/statement.cs:4034 +#: mcs/mcs/statement.cs:4056 msgid "__arglist is not allowed in parameter list of async methods" msgstr "" -#: mcs/mcs/statement.cs:4040 +#: mcs/mcs/statement.cs:4062 msgid "Async methods cannot have unsafe parameters" msgstr "" -#: mcs/mcs/statement.cs:4237 +#: mcs/mcs/statement.cs:4259 #, csharp-format msgid "The label `{0}' is a duplicate" msgstr "" -#: mcs/mcs/statement.cs:4246 mcs/mcs/statement.cs:4257 +#: mcs/mcs/statement.cs:4268 mcs/mcs/statement.cs:4279 #, csharp-format msgid "" "The label `{0}' shadows another label by the same name in a contained scope" msgstr "" -#: mcs/mcs/statement.cs:4535 +#: mcs/mcs/statement.cs:4557 #, csharp-format msgid "`{0}': not all code paths return a value" msgstr "" -#: mcs/mcs/statement.cs:4667 +#: mcs/mcs/statement.cs:4689 #, csharp-format msgid "The label `{0}' already occurs in this switch statement" msgstr "" -#: mcs/mcs/statement.cs:4794 +#: mcs/mcs/statement.cs:4816 #, csharp-format msgid "" "Control cannot fall out of switch statement through final case label `{0}'" msgstr "" -#: mcs/mcs/statement.cs:4797 +#: mcs/mcs/statement.cs:4819 #, csharp-format msgid "Control cannot fall through from one case label `{0}' to another" msgstr "" -#: mcs/mcs/statement.cs:5234 +#: mcs/mcs/statement.cs:5256 #, csharp-format msgid "" "A switch expression of type `{0}' cannot be converted to an integral type, " "bool, char, string, enum or nullable type" msgstr "" -#: mcs/mcs/statement.cs:6093 +#: mcs/mcs/statement.cs:6115 #, csharp-format msgid "`{0}' is not a reference type as required by the lock statement" msgstr "" -#: mcs/mcs/statement.cs:6475 +#: mcs/mcs/statement.cs:6497 msgid "The type of locals declared in a fixed statement must be a pointer type" msgstr "" -#: mcs/mcs/statement.cs:6555 +#: mcs/mcs/statement.cs:6577 msgid "" "The right hand side of a fixed statement assignment may not be a cast " "expression" msgstr "" -#: mcs/mcs/statement.cs:6560 +#: mcs/mcs/statement.cs:6582 msgid "" "You cannot use the fixed statement to take the address of an already fixed " "expression" msgstr "" -#: mcs/mcs/statement.cs:6746 +#: mcs/mcs/statement.cs:6768 msgid "" "The `await' operator cannot be used in the filter expression of a catch " "clause" msgstr "" -#: mcs/mcs/statement.cs:7337 +#: mcs/mcs/statement.cs:7359 #, csharp-format msgid "" "A previous catch clause already catches all exceptions of this or a super " "type `{0}'" msgstr "" -#: mcs/mcs/statement.cs:7570 +#: mcs/mcs/statement.cs:7592 #, csharp-format msgid "" "`{0}': type used in a using statement must be implicitly convertible to " "`System.IDisposable'" msgstr "" -#: mcs/mcs/statement.cs:7986 +#: mcs/mcs/statement.cs:8008 #, csharp-format msgid "" "foreach statement requires that the return type `{0}' of `{1}' must have a " "suitable public MoveNext method and public Current property" msgstr "" -#: mcs/mcs/statement.cs:8030 +#: mcs/mcs/statement.cs:8052 #, csharp-format msgid "" "foreach statement cannot operate on variables of type `{0}' because it " @@ -3635,18 +3635,18 @@ msgid "" "implementation" msgstr "" -#: mcs/mcs/statement.cs:8052 +#: mcs/mcs/statement.cs:8074 #, csharp-format msgid "" "foreach statement cannot operate on variables of type `{0}' because it does " "not contain a definition for `{1}' or is inaccessible" msgstr "" -#: mcs/mcs/statement.cs:8290 +#: mcs/mcs/statement.cs:8312 msgid "Use of null is not valid in this context" msgstr "" -#: mcs/mcs/statement.cs:8302 +#: mcs/mcs/statement.cs:8324 #, csharp-format msgid "Foreach statement cannot operate on a `{0}'" msgstr "" diff --git a/po/mcs/pt_BR.gmo b/po/mcs/pt_BR.gmo index 1526a1fc07..08e3a30f36 100644 Binary files a/po/mcs/pt_BR.gmo and b/po/mcs/pt_BR.gmo differ diff --git a/po/mcs/pt_BR.po.REMOVED.git-id b/po/mcs/pt_BR.po.REMOVED.git-id index eea3d3f8db..7e01505895 100644 --- a/po/mcs/pt_BR.po.REMOVED.git-id +++ b/po/mcs/pt_BR.po.REMOVED.git-id @@ -1 +1 @@ -cf53000475e62765019bb7c49d2f7842dee456b2 \ No newline at end of file +7925e43a8725e46f8222cc890cff7acfbe7b709b \ No newline at end of file diff --git a/runtime/Makefile.am b/runtime/Makefile.am index 223b73852d..9ca3183465 100644 --- a/runtime/Makefile.am +++ b/runtime/Makefile.am @@ -109,10 +109,20 @@ cur_dir_cmd = pwd PLATFORM_PATH_SEPARATOR = : endif +if INSTALL_MOBILE_STATIC +# ILASM.exe has features which a mobile_static runtime will not support. +# It is invoked with an external mono when used in the runtime. +# We skip it here because otherwise it will fail to verify. +MOBILE_STATIC_FILTER=grep -v ilasm +else +MOBILE_STATIC_FILTER=echo +endif + # Compile all assemblies with the verifier turned on. Code must be valid but not verifiable. # TODO it would be nice to split assemblies without unsafe code to use the verifier with verifiable mode. # Skip binary_reference_assemblies because they contain metadata only mcs-compileall: mono-wrapper etc/mono/config + export verifiable_files=`ls "$(mcs_topdir)/class/lib/$$profile/" | grep -E '\.(dll|exe)$$' | $(MOBILE_STATIC_FILTER)` ; \ save_MONO_PATH=$$MONO_PATH; mcs_topdir=`cd $(mcs_topdir) && $(cur_dir_cmd)`; ok=:; \ for profile in $(test_profiles); do \ if [ "binary_reference_assemblies" = "$$profile" ]; then \ @@ -126,7 +136,9 @@ mcs-compileall: mono-wrapper etc/mono/config MONO_PATH="$$mcs_topdir/class/lib/$$profile$(PLATFORM_PATH_SEPARATOR)$$save_MONO_PATH"; \ fi; \ export MONO_PATH; \ - for i in $(mcs_topdir)/class/lib/$$profile/*.{dll,exe}; do \ + for stub in $$verifiable_files; do \ + i=$(mcs_topdir)/class/lib/$$profile/$$stub ; \ + echo $$i ; \ if [ ! -f $$i ] ; then \ continue ; \ fi ; \ @@ -153,10 +165,13 @@ CLEANFILES = etc/mono/config etc/mono/config: ../data/config Makefile $(symlinks) d=`cd ../support && pwd`; \ sed 's,target="$$mono_libdir/libMonoPosixHelper$(libsuffix)",target="'$$d'/libMonoPosixHelper.la",' ../data/config > $@t + d=`cd ../mono/btls/build-shared && pwd`; \ + sed 's,target="$$mono_libdir/libmono-btls-shared$(libsuffix)",target="'$$d'/libmono-btls-shared$(libsuffix)",' $@t > $@tt if test -z "$(libgdiplus_loc)"; then :; else \ - sed 's,target="$(libgdiplus_install_loc)",target="$(libgdiplus_loc)",' $@t > $@tt; \ - mv -f $@tt $@t; fi - mv -f $@t $@ + sed 's,target="$(libgdiplus_install_loc)",target="$(libgdiplus_loc)",' $@tt > $@ttt; \ + mv -f $@ttt $@tt; fi + mv -f $@tt $@ + rm -f $@t $(tmpinst)/bin/mono: mono-wrapper etc/mono/config $(mkinstalldirs) $(tmpinst)/bin diff --git a/runtime/Makefile.in b/runtime/Makefile.in index cb03139a24..747e6a3433 100644 --- a/runtime/Makefile.in +++ b/runtime/Makefile.in @@ -131,6 +131,8 @@ DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AOT_BUILD_FLAGS = @AOT_BUILD_FLAGS@ +AOT_RUN_FLAGS = @AOT_RUN_FLAGS@ API_VER = @API_VER@ AR = @AR@ AS = @AS@ @@ -139,6 +141,11 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOEHM_DEFINES = @BOEHM_DEFINES@ +BTLS_ARCH = @BTLS_ARCH@ +BTLS_CFLAGS = @BTLS_CFLAGS@ +BTLS_CMAKE_ARGS = @BTLS_CMAKE_ARGS@ +BTLS_PLATFORM = @BTLS_PLATFORM@ +BTLS_ROOT = @BTLS_ROOT@ BUILD_EXEEXT = @BUILD_EXEEXT@ CC = @CC@ CCAS = @CCAS@ @@ -148,6 +155,7 @@ CCDEPMODE = @CCDEPMODE@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMAKE = @CMAKE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ @@ -168,7 +176,6 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_PERF_EVENTS = @ENABLE_PERF_EVENTS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDKX11 = @GDKX11@ @@ -183,10 +190,12 @@ HAVE_MSGFMT = @HAVE_MSGFMT@ HOST_CC = @HOST_CC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MOBILE_STATIC = @INSTALL_MOBILE_STATIC@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTL = @INTL@ +INVARIANT_AOT_OPTIONS = @INVARIANT_AOT_OPTIONS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBC = @LIBC@ @@ -233,6 +242,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ +PLATFORM_AOT_SUFFIX = @PLATFORM_AOT_SUFFIX@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -242,6 +252,7 @@ SHELL = @SHELL@ SQLITE = @SQLITE@ SQLITE3 = @SQLITE3@ STRIP = @STRIP@ +TEST_PROFILE = @TEST_PROFILE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VTUNE_CFLAGS = @VTUNE_CFLAGS@ @@ -350,6 +361,12 @@ TEST_SUPPORT_FILES = $(tmpinst)/bin/mono $(tmpinst)/bin/ilasm $(tmpinst)/bin/mcs @CROSS_COMPILING_FALSE@@HOST_WIN32_TRUE@PLATFORM_PATH_SEPARATOR = ; @CROSS_COMPILING_TRUE@@HOST_WIN32_TRUE@PLATFORM_PATH_SEPARATOR = : @HOST_WIN32_FALSE@PLATFORM_PATH_SEPARATOR = : +@INSTALL_MOBILE_STATIC_FALSE@MOBILE_STATIC_FILTER = echo + +# ILASM.exe has features which a mobile_static runtime will not support. +# It is invoked with an external mono when used in the runtime. +# We skip it here because otherwise it will fail to verify. +@INSTALL_MOBILE_STATIC_TRUE@MOBILE_STATIC_FILTER = grep -v ilasm CLEANFILES = etc/mono/config # the 'cygnus' option also disables the default 'distdir:' target, which we _do_ want @@ -571,6 +588,7 @@ mcs-do-run-test-profiles: test-support-files # TODO it would be nice to split assemblies without unsafe code to use the verifier with verifiable mode. # Skip binary_reference_assemblies because they contain metadata only mcs-compileall: mono-wrapper etc/mono/config + export verifiable_files=`ls "$(mcs_topdir)/class/lib/$$profile/" | grep -E '\.(dll|exe)$$' | $(MOBILE_STATIC_FILTER)` ; \ save_MONO_PATH=$$MONO_PATH; mcs_topdir=`cd $(mcs_topdir) && $(cur_dir_cmd)`; ok=:; \ for profile in $(test_profiles); do \ if [ "binary_reference_assemblies" = "$$profile" ]; then \ @@ -584,7 +602,9 @@ mcs-compileall: mono-wrapper etc/mono/config MONO_PATH="$$mcs_topdir/class/lib/$$profile$(PLATFORM_PATH_SEPARATOR)$$save_MONO_PATH"; \ fi; \ export MONO_PATH; \ - for i in $(mcs_topdir)/class/lib/$$profile/*.{dll,exe}; do \ + for stub in $$verifiable_files; do \ + i=$(mcs_topdir)/class/lib/$$profile/$$stub ; \ + echo $$i ; \ if [ ! -f $$i ] ; then \ continue ; \ fi ; \ @@ -606,10 +626,13 @@ test: mcs-do-test-profiles etc/mono/config: ../data/config Makefile $(symlinks) d=`cd ../support && pwd`; \ sed 's,target="$$mono_libdir/libMonoPosixHelper$(libsuffix)",target="'$$d'/libMonoPosixHelper.la",' ../data/config > $@t + d=`cd ../mono/btls/build-shared && pwd`; \ + sed 's,target="$$mono_libdir/libmono-btls-shared$(libsuffix)",target="'$$d'/libmono-btls-shared$(libsuffix)",' $@t > $@tt if test -z "$(libgdiplus_loc)"; then :; else \ - sed 's,target="$(libgdiplus_install_loc)",target="$(libgdiplus_loc)",' $@t > $@tt; \ - mv -f $@tt $@t; fi - mv -f $@t $@ + sed 's,target="$(libgdiplus_install_loc)",target="$(libgdiplus_loc)",' $@tt > $@ttt; \ + mv -f $@ttt $@tt; fi + mv -f $@tt $@ + rm -f $@t $(tmpinst)/bin/mono: mono-wrapper etc/mono/config $(mkinstalldirs) $(tmpinst)/bin diff --git a/samples/Makefile.in b/samples/Makefile.in index 78a31db0b1..48185c2d27 100644 --- a/samples/Makefile.in +++ b/samples/Makefile.in @@ -120,6 +120,8 @@ DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AOT_BUILD_FLAGS = @AOT_BUILD_FLAGS@ +AOT_RUN_FLAGS = @AOT_RUN_FLAGS@ API_VER = @API_VER@ AR = @AR@ AS = @AS@ @@ -128,6 +130,11 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOEHM_DEFINES = @BOEHM_DEFINES@ +BTLS_ARCH = @BTLS_ARCH@ +BTLS_CFLAGS = @BTLS_CFLAGS@ +BTLS_CMAKE_ARGS = @BTLS_CMAKE_ARGS@ +BTLS_PLATFORM = @BTLS_PLATFORM@ +BTLS_ROOT = @BTLS_ROOT@ BUILD_EXEEXT = @BUILD_EXEEXT@ CC = @CC@ CCAS = @CCAS@ @@ -137,6 +144,7 @@ CCDEPMODE = @CCDEPMODE@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMAKE = @CMAKE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ @@ -157,7 +165,6 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_PERF_EVENTS = @ENABLE_PERF_EVENTS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDKX11 = @GDKX11@ @@ -172,10 +179,12 @@ HAVE_MSGFMT = @HAVE_MSGFMT@ HOST_CC = @HOST_CC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MOBILE_STATIC = @INSTALL_MOBILE_STATIC@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTL = @INTL@ +INVARIANT_AOT_OPTIONS = @INVARIANT_AOT_OPTIONS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBC = @LIBC@ @@ -222,6 +231,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ +PLATFORM_AOT_SUFFIX = @PLATFORM_AOT_SUFFIX@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -231,6 +241,7 @@ SHELL = @SHELL@ SQLITE = @SQLITE@ SQLITE3 = @SQLITE3@ STRIP = @STRIP@ +TEST_PROFILE = @TEST_PROFILE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VTUNE_CFLAGS = @VTUNE_CFLAGS@ diff --git a/samples/embed/teste.c b/samples/embed/teste.c index 2183ccbb50..6f727a00e1 100644 --- a/samples/embed/teste.c +++ b/samples/embed/teste.c @@ -1,5 +1,6 @@ #include #include +#include #include /* @@ -31,6 +32,13 @@ static void main_function (MonoDomain *domain, const char *file, int argc, char* mono_jit_exec (domain, assembly, argc, argv); } +static int malloc_count = 0; + +static void* custom_malloc(size_t bytes) +{ + ++malloc_count; + return malloc(bytes); +} int main(int argc, char* argv[]) { @@ -44,6 +52,9 @@ main(int argc, char* argv[]) { } file = argv [1]; + MonoAllocatorVTable mem_vtable = {custom_malloc}; + mono_set_allocator_vtable (&mem_vtable); + /* * Load the default Mono configuration file, this is needed * if you are planning on using the dllmaps defined on the @@ -66,6 +77,9 @@ main(int argc, char* argv[]) { retval = mono_environment_exitcode_get (); mono_jit_cleanup (domain); + + fprintf (stdout, "custom malloc calls = %d\n", malloc_count); + return retval; } diff --git a/scripts/Makefile.am b/scripts/Makefile.am index fa2d8378bb..3174ec4c3f 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -34,8 +34,9 @@ bin_SCRIPTS = \ $(MDOC_SUBCOMMANDS) \ $(MDOC_COMPAT) \ mono-test-install \ - peverify \ - mcs \ + peverify \ + mcs \ + mono-package-runtime \ mono-heapviz \ $(scripts_mono_configuration_crypto) @@ -72,6 +73,7 @@ scripts_4_0 = \ prj2make$(SCRIPT_SUFFIX) \ soapsuds$(SCRIPT_SUFFIX) \ caspol$(SCRIPT_SUFFIX) \ + btls-cert-sync$(SCRIPT_SUFFIX) \ cert-sync$(SCRIPT_SUFFIX) \ cert2spc$(SCRIPT_SUFFIX) \ certmgr$(SCRIPT_SUFFIX) \ diff --git a/scripts/Makefile.in b/scripts/Makefile.in index 25ff2e5ec3..a2c3120079 100644 --- a/scripts/Makefile.in +++ b/scripts/Makefile.in @@ -152,6 +152,8 @@ DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AOT_BUILD_FLAGS = @AOT_BUILD_FLAGS@ +AOT_RUN_FLAGS = @AOT_RUN_FLAGS@ API_VER = @API_VER@ AR = @AR@ AS = @AS@ @@ -160,6 +162,11 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOEHM_DEFINES = @BOEHM_DEFINES@ +BTLS_ARCH = @BTLS_ARCH@ +BTLS_CFLAGS = @BTLS_CFLAGS@ +BTLS_CMAKE_ARGS = @BTLS_CMAKE_ARGS@ +BTLS_PLATFORM = @BTLS_PLATFORM@ +BTLS_ROOT = @BTLS_ROOT@ BUILD_EXEEXT = @BUILD_EXEEXT@ CC = @CC@ CCAS = @CCAS@ @@ -169,6 +176,7 @@ CCDEPMODE = @CCDEPMODE@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMAKE = @CMAKE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ @@ -189,7 +197,6 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_PERF_EVENTS = @ENABLE_PERF_EVENTS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDKX11 = @GDKX11@ @@ -204,10 +211,12 @@ HAVE_MSGFMT = @HAVE_MSGFMT@ HOST_CC = @HOST_CC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MOBILE_STATIC = @INSTALL_MOBILE_STATIC@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTL = @INTL@ +INVARIANT_AOT_OPTIONS = @INVARIANT_AOT_OPTIONS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBC = @LIBC@ @@ -254,6 +263,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ +PLATFORM_AOT_SUFFIX = @PLATFORM_AOT_SUFFIX@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -263,6 +273,7 @@ SHELL = @SHELL@ SQLITE = @SQLITE@ SQLITE3 = @SQLITE3@ STRIP = @STRIP@ +TEST_PROFILE = @TEST_PROFILE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VTUNE_CFLAGS = @VTUNE_CFLAGS@ @@ -376,8 +387,8 @@ COMPAT_4_0_SUFFIX = 4$(SCRIPT_SUFFIX) bin_SCRIPTS = $(scripts_4_0_umask) $(scripts_defaults) $(scripts_2_0) \ $(scripts_service) $(scripts_nunit) $(scripts_rpmhelpers) \ $(MDOC_SUBCOMMANDS) $(MDOC_COMPAT) mono-test-install peverify \ - mcs mono-heapviz $(scripts_mono_configuration_crypto) \ - $(am__append_1) + mcs mono-package-runtime mono-heapviz \ + $(scripts_mono_configuration_crypto) $(am__append_1) scripts_4_0_umask = \ makecert$(SCRIPT_SUFFIX) \ sn$(SCRIPT_SUFFIX) @@ -405,6 +416,7 @@ scripts_4_0 = \ prj2make$(SCRIPT_SUFFIX) \ soapsuds$(SCRIPT_SUFFIX) \ caspol$(SCRIPT_SUFFIX) \ + btls-cert-sync$(SCRIPT_SUFFIX) \ cert-sync$(SCRIPT_SUFFIX) \ cert2spc$(SCRIPT_SUFFIX) \ certmgr$(SCRIPT_SUFFIX) \ diff --git a/scripts/submodules/versions.mk b/scripts/submodules/versions.mk index 728d381187..899e368877 100644 --- a/scripts/submodules/versions.mk +++ b/scripts/submodules/versions.mk @@ -67,7 +67,7 @@ test-$(1):: reset-$(1):: @if test -d $($(2)_PATH); then \ - if ! (cd $($(2)_PATH) && git show $(NEEDED_$(2)_VERSION) >/dev/null 2>&1 && git log -1 $(NEEDED_$(2)_REMOTE) >/dev/null 2>&1) ; then \ + if ! (cd $($(2)_PATH) && git show $(NEEDED_$(2)_VERSION) >/dev/null 2>&1 && git log -1 $(NEEDED_$(2)_REMOTE/NEEDED_$(2)_BRANCH) >/dev/null 2>&1) ; then \ echo "*** git fetch `basename $$($(2)_PATH)`" && (cd $($(2)_PATH) && git fetch); \ fi; \ else \ diff --git a/support/Makefile.in b/support/Makefile.in index 31fa1a98d1..09a07e660f 100644 --- a/support/Makefile.in +++ b/support/Makefile.in @@ -241,6 +241,8 @@ DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AOT_BUILD_FLAGS = @AOT_BUILD_FLAGS@ +AOT_RUN_FLAGS = @AOT_RUN_FLAGS@ API_VER = @API_VER@ AR = @AR@ AS = @AS@ @@ -249,6 +251,11 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOEHM_DEFINES = @BOEHM_DEFINES@ +BTLS_ARCH = @BTLS_ARCH@ +BTLS_CFLAGS = @BTLS_CFLAGS@ +BTLS_CMAKE_ARGS = @BTLS_CMAKE_ARGS@ +BTLS_PLATFORM = @BTLS_PLATFORM@ +BTLS_ROOT = @BTLS_ROOT@ BUILD_EXEEXT = @BUILD_EXEEXT@ CC = @CC@ CCAS = @CCAS@ @@ -258,6 +265,7 @@ CCDEPMODE = @CCDEPMODE@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMAKE = @CMAKE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ @@ -278,7 +286,6 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_PERF_EVENTS = @ENABLE_PERF_EVENTS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDKX11 = @GDKX11@ @@ -293,10 +300,12 @@ HAVE_MSGFMT = @HAVE_MSGFMT@ HOST_CC = @HOST_CC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MOBILE_STATIC = @INSTALL_MOBILE_STATIC@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTL = @INTL@ +INVARIANT_AOT_OPTIONS = @INVARIANT_AOT_OPTIONS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBC = @LIBC@ @@ -343,6 +352,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ +PLATFORM_AOT_SUFFIX = @PLATFORM_AOT_SUFFIX@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -352,6 +362,7 @@ SHELL = @SHELL@ SQLITE = @SQLITE@ SQLITE3 = @SQLITE3@ STRIP = @STRIP@ +TEST_PROFILE = @TEST_PROFILE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VTUNE_CFLAGS = @VTUNE_CFLAGS@ diff --git a/support/map.c.REMOVED.git-id b/support/map.c.REMOVED.git-id index 6e6a759281..1136ff9b46 100644 --- a/support/map.c.REMOVED.git-id +++ b/support/map.c.REMOVED.git-id @@ -1 +1 @@ -136f2b71878105b87fdcb5ccb5faa0f1cc943646 \ No newline at end of file +92fca755371d09ab6336dd25c5c131d014c47d7d \ No newline at end of file diff --git a/support/sys-mman.c b/support/sys-mman.c index 3973bd6614..1dd61bc372 100644 --- a/support/sys-mman.c +++ b/support/sys-mman.c @@ -22,6 +22,11 @@ #define __BSD_VISIBLE 1 #endif +#ifdef __NetBSD__ +/* For mincore () */ +#define _NETBSD_SOURCE +#endif + #include #include #include @@ -109,8 +114,15 @@ Mono_Posix_Syscall_mremap (void *old_address, mph_size_t old_size, if (Mono_Posix_FromMremapFlags (flags, &_flags) == -1) return MAP_FAILED; +#if defined(linux) return mremap (old_address, (size_t) old_size, (size_t) new_size, (unsigned long) _flags); +#elif defined(__NetBSD__) + return mremap (old_address, (size_t) old_size, old_address, + (size_t) new_size, (unsigned long) _flags); +#else +#error Port me +#endif } #endif /* def HAVE_MREMAP */ diff --git a/support/zlib-helper.c b/support/zlib-helper.c index f364a66095..9dcebc7e96 100644 --- a/support/zlib-helper.c +++ b/support/zlib-helper.c @@ -194,21 +194,22 @@ ReadZStream (ZStream *stream, guchar *buffer, gint length) while (zs->avail_out > 0) { if (zs->avail_in == 0) { n = stream->func (stream->buffer, BUFFER_SIZE, stream->gchandle); + n = n < 0 ? 0 : n; stream->total_in += n; - if (n <= 0) { - stream->eof = TRUE; - } zs->next_in = stream->buffer; - zs->avail_in = n < 0 ? 0 : n; + zs->avail_in = n; } - if (zs->avail_in == 0 && (zs->total_in == 0 || stream->total_in == zs->total_in)) - return Z_STREAM_END; + if (zs->avail_in == 0 && zs->total_in == 0) + return 0; status = inflate (stream->stream, Z_SYNC_FLUSH); if (status == Z_STREAM_END) { stream->eof = TRUE; break; + } else if (status == Z_BUF_ERROR && stream->total_in == zs->total_in) { + stream->eof = TRUE; + break; } else if (status != Z_OK) { return status; } diff --git a/tools/Makefile.am b/tools/Makefile.am index 3b30bc16f8..9aebe325e6 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -1,3 +1,3 @@ -SUBDIRS = locale-builder sgen monograph +SUBDIRS = locale-builder sgen monograph pedump diff --git a/tools/Makefile.in b/tools/Makefile.in index 6a03cb7c5f..aee368a076 100644 --- a/tools/Makefile.in +++ b/tools/Makefile.in @@ -180,6 +180,8 @@ am__relativize = \ ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AOT_BUILD_FLAGS = @AOT_BUILD_FLAGS@ +AOT_RUN_FLAGS = @AOT_RUN_FLAGS@ API_VER = @API_VER@ AR = @AR@ AS = @AS@ @@ -188,6 +190,11 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOEHM_DEFINES = @BOEHM_DEFINES@ +BTLS_ARCH = @BTLS_ARCH@ +BTLS_CFLAGS = @BTLS_CFLAGS@ +BTLS_CMAKE_ARGS = @BTLS_CMAKE_ARGS@ +BTLS_PLATFORM = @BTLS_PLATFORM@ +BTLS_ROOT = @BTLS_ROOT@ BUILD_EXEEXT = @BUILD_EXEEXT@ CC = @CC@ CCAS = @CCAS@ @@ -197,6 +204,7 @@ CCDEPMODE = @CCDEPMODE@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMAKE = @CMAKE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ @@ -217,7 +225,6 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_PERF_EVENTS = @ENABLE_PERF_EVENTS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDKX11 = @GDKX11@ @@ -232,10 +239,12 @@ HAVE_MSGFMT = @HAVE_MSGFMT@ HOST_CC = @HOST_CC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MOBILE_STATIC = @INSTALL_MOBILE_STATIC@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTL = @INTL@ +INVARIANT_AOT_OPTIONS = @INVARIANT_AOT_OPTIONS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBC = @LIBC@ @@ -282,6 +291,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ +PLATFORM_AOT_SUFFIX = @PLATFORM_AOT_SUFFIX@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -291,6 +301,7 @@ SHELL = @SHELL@ SQLITE = @SQLITE@ SQLITE3 = @SQLITE3@ STRIP = @STRIP@ +TEST_PROFILE = @TEST_PROFILE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VTUNE_CFLAGS = @VTUNE_CFLAGS@ @@ -379,7 +390,7 @@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -SUBDIRS = locale-builder sgen monograph +SUBDIRS = locale-builder sgen monograph pedump all: all-recursive .SUFFIXES: diff --git a/tools/locale-builder/Makefile.in b/tools/locale-builder/Makefile.in index 7b6a535115..6908179bd9 100644 --- a/tools/locale-builder/Makefile.in +++ b/tools/locale-builder/Makefile.in @@ -120,6 +120,8 @@ DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AOT_BUILD_FLAGS = @AOT_BUILD_FLAGS@ +AOT_RUN_FLAGS = @AOT_RUN_FLAGS@ API_VER = @API_VER@ AR = @AR@ AS = @AS@ @@ -128,6 +130,11 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOEHM_DEFINES = @BOEHM_DEFINES@ +BTLS_ARCH = @BTLS_ARCH@ +BTLS_CFLAGS = @BTLS_CFLAGS@ +BTLS_CMAKE_ARGS = @BTLS_CMAKE_ARGS@ +BTLS_PLATFORM = @BTLS_PLATFORM@ +BTLS_ROOT = @BTLS_ROOT@ BUILD_EXEEXT = @BUILD_EXEEXT@ CC = @CC@ CCAS = @CCAS@ @@ -137,6 +144,7 @@ CCDEPMODE = @CCDEPMODE@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMAKE = @CMAKE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ @@ -157,7 +165,6 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_PERF_EVENTS = @ENABLE_PERF_EVENTS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDKX11 = @GDKX11@ @@ -172,10 +179,12 @@ HAVE_MSGFMT = @HAVE_MSGFMT@ HOST_CC = @HOST_CC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MOBILE_STATIC = @INSTALL_MOBILE_STATIC@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTL = @INTL@ +INVARIANT_AOT_OPTIONS = @INVARIANT_AOT_OPTIONS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBC = @LIBC@ @@ -222,6 +231,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ +PLATFORM_AOT_SUFFIX = @PLATFORM_AOT_SUFFIX@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -231,6 +241,7 @@ SHELL = @SHELL@ SQLITE = @SQLITE@ SQLITE3 = @SQLITE3@ STRIP = @STRIP@ +TEST_PROFILE = @TEST_PROFILE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VTUNE_CFLAGS = @VTUNE_CFLAGS@ diff --git a/tools/monograph/Makefile.am b/tools/monograph/Makefile.am index 123d63d2fb..3c52afc663 100644 --- a/tools/monograph/Makefile.am +++ b/tools/monograph/Makefile.am @@ -6,18 +6,14 @@ endif if DISABLE_EXECUTABLES runtime_lib=$(top_builddir)/mono/mini/$(LIBMONO_LA) $(static_libs) else -if !SHARED_MONO static_libs= \ - $(top_builddir)/mono/metadata/libmonoruntime-static.la \ + $(top_builddir)/mono/metadata/libmonoruntimesgen-static.la \ $(top_builddir)/mono/io-layer/libwapi.la \ $(top_builddir)/mono/utils/libmonoutils.la \ $(GLIB_LIBS) $(LIBICONV) \ $(LIBGC_STATIC_LIBS) runtime_lib=$(top_builddir)/mono/mini/$(LIBMONO_LA) $(static_libs) -else -runtime_lib=$(top_builddir)/mono/mini/$(LIBMONO_LA) -endif endif if DISABLE_EXECUTABLES @@ -26,7 +22,7 @@ else if DISABLE_LIBRARIES bin_PROGRAMS = else -if SUPPORT_BOEHM +if SUPPORT_SGEN bin_PROGRAMS = monograph endif endif diff --git a/tools/monograph/Makefile.in b/tools/monograph/Makefile.in index d23caffdc5..98ded261c0 100644 --- a/tools/monograph/Makefile.in +++ b/tools/monograph/Makefile.in @@ -79,7 +79,7 @@ POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ -@DISABLE_EXECUTABLES_FALSE@@DISABLE_LIBRARIES_FALSE@@SUPPORT_BOEHM_TRUE@bin_PROGRAMS = monograph$(EXEEXT) +@DISABLE_EXECUTABLES_FALSE@@DISABLE_LIBRARIES_FALSE@@SUPPORT_SGEN_TRUE@bin_PROGRAMS = monograph$(EXEEXT) subdir = tools/monograph DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/mkinstalldirs $(top_srcdir)/depcomp @@ -103,15 +103,14 @@ PROGRAMS = $(bin_PROGRAMS) monograph_SOURCES = monograph.c monograph_OBJECTS = monograph.$(OBJEXT) am__DEPENDENCIES_1 = -@DISABLE_EXECUTABLES_FALSE@@SHARED_MONO_FALSE@am__DEPENDENCIES_2 = $(top_builddir)/mono/metadata/libmonoruntime-static.la \ -@DISABLE_EXECUTABLES_FALSE@@SHARED_MONO_FALSE@ $(top_builddir)/mono/io-layer/libwapi.la \ -@DISABLE_EXECUTABLES_FALSE@@SHARED_MONO_FALSE@ $(top_builddir)/mono/utils/libmonoutils.la \ -@DISABLE_EXECUTABLES_FALSE@@SHARED_MONO_FALSE@ $(am__DEPENDENCIES_1) \ -@DISABLE_EXECUTABLES_FALSE@@SHARED_MONO_FALSE@ $(am__DEPENDENCIES_1) \ -@DISABLE_EXECUTABLES_FALSE@@SHARED_MONO_FALSE@ $(am__DEPENDENCIES_1) -@DISABLE_EXECUTABLES_FALSE@@SHARED_MONO_FALSE@am__DEPENDENCIES_3 = $(top_builddir)/mono/mini/$(LIBMONO_LA) \ -@DISABLE_EXECUTABLES_FALSE@@SHARED_MONO_FALSE@ $(am__DEPENDENCIES_2) -@DISABLE_EXECUTABLES_FALSE@@SHARED_MONO_TRUE@am__DEPENDENCIES_3 = $(top_builddir)/mono/mini/$(LIBMONO_LA) +@DISABLE_EXECUTABLES_FALSE@am__DEPENDENCIES_2 = $(top_builddir)/mono/metadata/libmonoruntimesgen-static.la \ +@DISABLE_EXECUTABLES_FALSE@ $(top_builddir)/mono/io-layer/libwapi.la \ +@DISABLE_EXECUTABLES_FALSE@ $(top_builddir)/mono/utils/libmonoutils.la \ +@DISABLE_EXECUTABLES_FALSE@ $(am__DEPENDENCIES_1) \ +@DISABLE_EXECUTABLES_FALSE@ $(am__DEPENDENCIES_1) \ +@DISABLE_EXECUTABLES_FALSE@ $(am__DEPENDENCIES_1) +@DISABLE_EXECUTABLES_FALSE@am__DEPENDENCIES_3 = $(top_builddir)/mono/mini/$(LIBMONO_LA) \ +@DISABLE_EXECUTABLES_FALSE@ $(am__DEPENDENCIES_2) @DISABLE_EXECUTABLES_TRUE@am__DEPENDENCIES_3 = $(top_builddir)/mono/mini/$(LIBMONO_LA) \ @DISABLE_EXECUTABLES_TRUE@ $(am__DEPENDENCIES_2) monograph_DEPENDENCIES = $(am__DEPENDENCIES_3) $(am__DEPENDENCIES_1) \ @@ -183,6 +182,8 @@ DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AOT_BUILD_FLAGS = @AOT_BUILD_FLAGS@ +AOT_RUN_FLAGS = @AOT_RUN_FLAGS@ API_VER = @API_VER@ AR = @AR@ AS = @AS@ @@ -191,6 +192,11 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOEHM_DEFINES = @BOEHM_DEFINES@ +BTLS_ARCH = @BTLS_ARCH@ +BTLS_CFLAGS = @BTLS_CFLAGS@ +BTLS_CMAKE_ARGS = @BTLS_CMAKE_ARGS@ +BTLS_PLATFORM = @BTLS_PLATFORM@ +BTLS_ROOT = @BTLS_ROOT@ BUILD_EXEEXT = @BUILD_EXEEXT@ CC = @CC@ CCAS = @CCAS@ @@ -200,6 +206,7 @@ CCDEPMODE = @CCDEPMODE@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMAKE = @CMAKE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ @@ -220,7 +227,6 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_PERF_EVENTS = @ENABLE_PERF_EVENTS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDKX11 = @GDKX11@ @@ -235,10 +241,12 @@ HAVE_MSGFMT = @HAVE_MSGFMT@ HOST_CC = @HOST_CC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MOBILE_STATIC = @INSTALL_MOBILE_STATIC@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTL = @INTL@ +INVARIANT_AOT_OPTIONS = @INVARIANT_AOT_OPTIONS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBC = @LIBC@ @@ -285,6 +293,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ +PLATFORM_AOT_SUFFIX = @PLATFORM_AOT_SUFFIX@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -294,6 +303,7 @@ SHELL = @SHELL@ SQLITE = @SQLITE@ SQLITE3 = @SQLITE3@ STRIP = @STRIP@ +TEST_PROFILE = @TEST_PROFILE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VTUNE_CFLAGS = @VTUNE_CFLAGS@ @@ -382,15 +392,14 @@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -@DISABLE_EXECUTABLES_FALSE@@SHARED_MONO_FALSE@runtime_lib = $(top_builddir)/mono/mini/$(LIBMONO_LA) $(static_libs) -@DISABLE_EXECUTABLES_FALSE@@SHARED_MONO_TRUE@runtime_lib = $(top_builddir)/mono/mini/$(LIBMONO_LA) +@DISABLE_EXECUTABLES_FALSE@runtime_lib = $(top_builddir)/mono/mini/$(LIBMONO_LA) $(static_libs) @DISABLE_EXECUTABLES_TRUE@runtime_lib = $(top_builddir)/mono/mini/$(LIBMONO_LA) $(static_libs) -@DISABLE_EXECUTABLES_FALSE@@SHARED_MONO_FALSE@static_libs = \ -@DISABLE_EXECUTABLES_FALSE@@SHARED_MONO_FALSE@ $(top_builddir)/mono/metadata/libmonoruntime-static.la \ -@DISABLE_EXECUTABLES_FALSE@@SHARED_MONO_FALSE@ $(top_builddir)/mono/io-layer/libwapi.la \ -@DISABLE_EXECUTABLES_FALSE@@SHARED_MONO_FALSE@ $(top_builddir)/mono/utils/libmonoutils.la \ -@DISABLE_EXECUTABLES_FALSE@@SHARED_MONO_FALSE@ $(GLIB_LIBS) $(LIBICONV) \ -@DISABLE_EXECUTABLES_FALSE@@SHARED_MONO_FALSE@ $(LIBGC_STATIC_LIBS) +@DISABLE_EXECUTABLES_FALSE@static_libs = \ +@DISABLE_EXECUTABLES_FALSE@ $(top_builddir)/mono/metadata/libmonoruntimesgen-static.la \ +@DISABLE_EXECUTABLES_FALSE@ $(top_builddir)/mono/io-layer/libwapi.la \ +@DISABLE_EXECUTABLES_FALSE@ $(top_builddir)/mono/utils/libmonoutils.la \ +@DISABLE_EXECUTABLES_FALSE@ $(GLIB_LIBS) $(LIBICONV) \ +@DISABLE_EXECUTABLES_FALSE@ $(LIBGC_STATIC_LIBS) AM_CPPFLAGS = \ -I$(top_srcdir) \ diff --git a/tools/pedump/Makefile.am b/tools/pedump/Makefile.am new file mode 100644 index 0000000000..d329d1fa9b --- /dev/null +++ b/tools/pedump/Makefile.am @@ -0,0 +1,31 @@ + +AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/mono $(LIBGC_CPPFLAGS) $(GLIB_CFLAGS) $(SHARED_CFLAGS) + +if DISABLE_EXECUTABLES +bin_PROGRAMS = +else +if DISABLE_LIBRARIES +bin_PROGRAMS = +else +if SUPPORT_SGEN +bin_PROGRAMS = pedump +endif +endif +endif + +pedump_SOURCES = \ + pedump.c + +pedump_LDADD = \ + $(top_builddir)/mono/metadata/libmonoruntimesgen-static.la \ + $(top_builddir)/mono/sgen/libmonosgen-static.la \ + $(top_builddir)/mono/io-layer/libwapi.la \ + $(top_builddir)/mono/utils/libmonoutils.la \ + $(LLVM_LIBS) \ + $(LLVM_LDFLAGS) \ + $(GLIB_LIBS) \ + $(LIBICONV) + +if PLATFORM_DARWIN +pedump_LDFLAGS=-framework CoreFoundation -framework Foundation +endif diff --git a/tools/pedump/Makefile.in b/tools/pedump/Makefile.in new file mode 100644 index 0000000000..5fae7134a3 --- /dev/null +++ b/tools/pedump/Makefile.in @@ -0,0 +1,739 @@ +# Makefile.in generated by automake 1.14.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@DISABLE_EXECUTABLES_FALSE@@DISABLE_LIBRARIES_FALSE@@SUPPORT_SGEN_TRUE@bin_PROGRAMS = pedump$(EXEEXT) +subdir = tools/pedump +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(top_srcdir)/mkinstalldirs $(top_srcdir)/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/iconv.m4 \ + $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ + $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(bindir)" +PROGRAMS = $(bin_PROGRAMS) +am_pedump_OBJECTS = pedump.$(OBJEXT) +pedump_OBJECTS = $(am_pedump_OBJECTS) +am__DEPENDENCIES_1 = +pedump_DEPENDENCIES = \ + $(top_builddir)/mono/metadata/libmonoruntimesgen-static.la \ + $(top_builddir)/mono/sgen/libmonosgen-static.la \ + $(top_builddir)/mono/io-layer/libwapi.la \ + $(top_builddir)/mono/utils/libmonoutils.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +pedump_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(pedump_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(pedump_SOURCES) +DIST_SOURCES = $(pedump_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AOT_BUILD_FLAGS = @AOT_BUILD_FLAGS@ +AOT_RUN_FLAGS = @AOT_RUN_FLAGS@ +API_VER = @API_VER@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BOEHM_DEFINES = @BOEHM_DEFINES@ +BTLS_ARCH = @BTLS_ARCH@ +BTLS_CFLAGS = @BTLS_CFLAGS@ +BTLS_CMAKE_ARGS = @BTLS_CMAKE_ARGS@ +BTLS_PLATFORM = @BTLS_PLATFORM@ +BTLS_ROOT = @BTLS_ROOT@ +BUILD_EXEEXT = @BUILD_EXEEXT@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CC_FOR_BUILD = @CC_FOR_BUILD@ +CFLAGS = @CFLAGS@ +CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMAKE = @CMAKE@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFAULT_PROFILE = @DEFAULT_PROFILE@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOLT_BASH = @DOLT_BASH@ +DSYMUTIL = @DSYMUTIL@ +DTRACE = @DTRACE@ +DTRACEFLAGS = @DTRACEFLAGS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GDKX11 = @GDKX11@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_LIBS = @GLIB_LIBS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +GTKX11 = @GTKX11@ +HAVE_MSGFMT = @HAVE_MSGFMT@ +HOST_CC = @HOST_CC@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MOBILE_STATIC = @INSTALL_MOBILE_STATIC@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTL = @INTL@ +INVARIANT_AOT_OPTIONS = @INVARIANT_AOT_OPTIONS@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBC = @LIBC@ +LIBGC_CPPFLAGS = @LIBGC_CPPFLAGS@ +LIBGC_LIBS = @LIBGC_LIBS@ +LIBGC_STATIC_LIBS = @LIBGC_STATIC_LIBS@ +LIBICONV = @LIBICONV@ +LIBMONO_LA = @LIBMONO_LA@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LLVM_CFLAGS = @LLVM_CFLAGS@ +LLVM_CONFIG = @LLVM_CONFIG@ +LLVM_CXXFLAGS = @LLVM_CXXFLAGS@ +LLVM_LDFLAGS = @LLVM_LDFLAGS@ +LLVM_LIBS = @LLVM_LIBS@ +LN_S = @LN_S@ +LTCOMPILE = @LTCOMPILE@ +LTCXXCOMPILE = @LTCXXCOMPILE@ +LTLIBICONV = @LTLIBICONV@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MONO_DL_NEED_USCORE = @MONO_DL_NEED_USCORE@ +MONO_NACL_ALIGN_MASK_OFF = @MONO_NACL_ALIGN_MASK_OFF@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PLATFORM_AOT_SUFFIX = @PLATFORM_AOT_SUFFIX@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SGEN_DEFINES = @SGEN_DEFINES@ +SHARED_CFLAGS = @SHARED_CFLAGS@ +SHELL = @SHELL@ +SQLITE = @SQLITE@ +SQLITE3 = @SQLITE3@ +STRIP = @STRIP@ +TEST_PROFILE = @TEST_PROFILE@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +VTUNE_CFLAGS = @VTUNE_CFLAGS@ +VTUNE_LIBS = @VTUNE_LIBS@ +WERROR_CFLAGS = @WERROR_CFLAGS@ +X11 = @X11@ +XATTR_LIB = @XATTR_LIB@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +XINERAMA = @XINERAMA@ +XMKMF = @XMKMF@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +arch_target = @arch_target@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +docs_dir = @docs_dir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +export_ldflags = @export_ldflags@ +extra_runtime_ldflags = @extra_runtime_ldflags@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +ikvm_native_dir = @ikvm_native_dir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +libgc_dir = @libgc_dir@ +libgdiplus_install_loc = @libgdiplus_install_loc@ +libgdiplus_loc = @libgdiplus_loc@ +libmono_cflags = @libmono_cflags@ +libmono_ldflags = @libmono_ldflags@ +libsuffix = @libsuffix@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mcs_topdir = @mcs_topdir@ +mcs_topdir_from_srcdir = @mcs_topdir_from_srcdir@ +mkdir_p = @mkdir_p@ +mono_build_root = @mono_build_root@ +mono_cfg_dir = @mono_cfg_dir@ +mono_runtime = @mono_runtime@ +nacl_self_host = @nacl_self_host@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +reloc_libdir = @reloc_libdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/mono $(LIBGC_CPPFLAGS) $(GLIB_CFLAGS) $(SHARED_CFLAGS) +pedump_SOURCES = \ + pedump.c + +pedump_LDADD = \ + $(top_builddir)/mono/metadata/libmonoruntimesgen-static.la \ + $(top_builddir)/mono/sgen/libmonosgen-static.la \ + $(top_builddir)/mono/io-layer/libwapi.la \ + $(top_builddir)/mono/utils/libmonoutils.la \ + $(LLVM_LIBS) \ + $(LLVM_LDFLAGS) \ + $(GLIB_LIBS) \ + $(LIBICONV) + +@PLATFORM_DARWIN_TRUE@pedump_LDFLAGS = -framework CoreFoundation -framework Foundation +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tools/pedump/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign tools/pedump/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: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + || test -f $$p1 \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(bindir)" && rm -f $$files + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +pedump$(EXEEXT): $(pedump_OBJECTS) $(pedump_DEPENDENCIES) $(EXTRA_pedump_DEPENDENCIES) + @rm -f pedump$(EXEEXT) + $(AM_V_CCLD)$(pedump_LINK) $(pedump_OBJECTS) $(pedump_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pedump.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: + for dir in "$(DESTDIR)$(bindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +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-binPROGRAMS clean-generic clean-libtool 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 + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-binPROGRAMS + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -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-binPROGRAMS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \ + clean-binPROGRAMS clean-generic clean-libtool cscopelist-am \ + ctags ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-binPROGRAMS \ + 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-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am uninstall-binPROGRAMS + + +# 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/mono/metadata/pedump.c b/tools/pedump/pedump.c similarity index 99% rename from mono/metadata/pedump.c rename to tools/pedump/pedump.c index eac9bfba36..4bbcc69933 100644 --- a/mono/metadata/pedump.c +++ b/tools/pedump/pedump.c @@ -12,11 +12,11 @@ #include #include #include -#include "image.h" +#include #include -#include "cil-coff.h" -#include "mono-endian.h" -#include "verify.h" +#include +#include +#include #include #include #include diff --git a/tools/sgen/Makefile.am b/tools/sgen/Makefile.am index ac155b0ced..c14346f088 100644 --- a/tools/sgen/Makefile.am +++ b/tools/sgen/Makefile.am @@ -3,16 +3,17 @@ bin_PROGRAMS = sgen-grep-binprot AM_CPPFLAGS = $(GLIB_CFLAGS) -I$(top_srcdir) noinst_LIBRARIES = libsgen-grep-binprot.a libsgen-grep-binprot32p.a libsgen-grep-binprot64p.a -libsgen_grep_binprot_a_SOURCES = sgen-grep-binprot.c +libsgen_grep_binprot_a_SOURCES = sgen-grep-binprot.c sgen-grep-binprot.h libsgen_grep_binprot_a_CPPFLAGS = $(GLIB_CFLAGS) -I$(top_srcdir) -libsgen_grep_binprot32p_a_SOURCES = sgen-grep-binprot.c +libsgen_grep_binprot32p_a_SOURCES = sgen-grep-binprot.c sgen-grep-binprot.h libsgen_grep_binprot32p_a_CPPFLAGS = $(GLIB_CFLAGS) -I$(top_srcdir) -DBINPROT_SIZEOF_VOID_P=4 -DBINPROT_HAS_HEADER -libsgen_grep_binprot64p_a_SOURCES = sgen-grep-binprot.c +libsgen_grep_binprot64p_a_SOURCES = sgen-grep-binprot.c sgen-grep-binprot.h libsgen_grep_binprot64p_a_CPPFLAGS = $(GLIB_CFLAGS) -I$(top_srcdir) -DBINPROT_SIZEOF_VOID_P=8 -DBINPROT_HAS_HEADER sgen_grep_binprot_SOURCES = \ sgen-grep-binprot-main.c \ - sgen-entry-stream.c + sgen-entry-stream.c \ + sgen-entry-stream.h sgen_grep_binprot_LDADD = \ $(GLIB_LIBS) $(LIBICONV) libsgen-grep-binprot.a libsgen-grep-binprot32p.a libsgen-grep-binprot64p.a diff --git a/tools/sgen/Makefile.in b/tools/sgen/Makefile.in index 7d62fef9cc..ec512da41a 100644 --- a/tools/sgen/Makefile.in +++ b/tools/sgen/Makefile.in @@ -201,6 +201,8 @@ DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AOT_BUILD_FLAGS = @AOT_BUILD_FLAGS@ +AOT_RUN_FLAGS = @AOT_RUN_FLAGS@ API_VER = @API_VER@ AR = @AR@ AS = @AS@ @@ -209,6 +211,11 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOEHM_DEFINES = @BOEHM_DEFINES@ +BTLS_ARCH = @BTLS_ARCH@ +BTLS_CFLAGS = @BTLS_CFLAGS@ +BTLS_CMAKE_ARGS = @BTLS_CMAKE_ARGS@ +BTLS_PLATFORM = @BTLS_PLATFORM@ +BTLS_ROOT = @BTLS_ROOT@ BUILD_EXEEXT = @BUILD_EXEEXT@ CC = @CC@ CCAS = @CCAS@ @@ -218,6 +225,7 @@ CCDEPMODE = @CCDEPMODE@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMAKE = @CMAKE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ @@ -238,7 +246,6 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_PERF_EVENTS = @ENABLE_PERF_EVENTS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDKX11 = @GDKX11@ @@ -253,10 +260,12 @@ HAVE_MSGFMT = @HAVE_MSGFMT@ HOST_CC = @HOST_CC@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MOBILE_STATIC = @INSTALL_MOBILE_STATIC@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTL = @INTL@ +INVARIANT_AOT_OPTIONS = @INVARIANT_AOT_OPTIONS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBC = @LIBC@ @@ -303,6 +312,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ +PLATFORM_AOT_SUFFIX = @PLATFORM_AOT_SUFFIX@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -312,6 +322,7 @@ SHELL = @SHELL@ SQLITE = @SQLITE@ SQLITE3 = @SQLITE3@ STRIP = @STRIP@ +TEST_PROFILE = @TEST_PROFILE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VTUNE_CFLAGS = @VTUNE_CFLAGS@ @@ -402,15 +413,16 @@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = $(GLIB_CFLAGS) -I$(top_srcdir) noinst_LIBRARIES = libsgen-grep-binprot.a libsgen-grep-binprot32p.a libsgen-grep-binprot64p.a -libsgen_grep_binprot_a_SOURCES = sgen-grep-binprot.c +libsgen_grep_binprot_a_SOURCES = sgen-grep-binprot.c sgen-grep-binprot.h libsgen_grep_binprot_a_CPPFLAGS = $(GLIB_CFLAGS) -I$(top_srcdir) -libsgen_grep_binprot32p_a_SOURCES = sgen-grep-binprot.c +libsgen_grep_binprot32p_a_SOURCES = sgen-grep-binprot.c sgen-grep-binprot.h libsgen_grep_binprot32p_a_CPPFLAGS = $(GLIB_CFLAGS) -I$(top_srcdir) -DBINPROT_SIZEOF_VOID_P=4 -DBINPROT_HAS_HEADER -libsgen_grep_binprot64p_a_SOURCES = sgen-grep-binprot.c +libsgen_grep_binprot64p_a_SOURCES = sgen-grep-binprot.c sgen-grep-binprot.h libsgen_grep_binprot64p_a_CPPFLAGS = $(GLIB_CFLAGS) -I$(top_srcdir) -DBINPROT_SIZEOF_VOID_P=8 -DBINPROT_HAS_HEADER sgen_grep_binprot_SOURCES = \ sgen-grep-binprot-main.c \ - sgen-entry-stream.c + sgen-entry-stream.c \ + sgen-entry-stream.h sgen_grep_binprot_LDADD = \ $(GLIB_LIBS) $(LIBICONV) libsgen-grep-binprot.a libsgen-grep-binprot32p.a libsgen-grep-binprot64p.a diff --git a/tools/sgen/sgen-entry-stream.h b/tools/sgen/sgen-entry-stream.h new file mode 100644 index 0000000000..93dd2bf808 --- /dev/null +++ b/tools/sgen/sgen-entry-stream.h @@ -0,0 +1,20 @@ +/* + * sgen-entry-stream.h: EntryStream definitions + * + * Copyright (C) 2016 Xamarin Inc + * + * Licensed under the MIT license. See LICENSE file in the project root for full license information. + */ + +typedef struct { + int file; + char *buffer; + const char *end; + const char *pos; +} EntryStream; + +void init_stream (EntryStream *stream, int file); +void reset_stream (EntryStream *stream); +void close_stream (EntryStream *stream); +gboolean refill_stream (EntryStream *in, size_t size); +ssize_t read_stream (EntryStream *stream, void *out, size_t size); diff --git a/tools/sgen/sgen-grep-binprot.h b/tools/sgen/sgen-grep-binprot.h new file mode 100644 index 0000000000..9025c9aa4d --- /dev/null +++ b/tools/sgen/sgen-grep-binprot.h @@ -0,0 +1,12 @@ +typedef gboolean (*GrepEntriesFunction) (EntryStream *stream, int num_nums, long nums [], int num_vtables, long vtables [], + gboolean dump_all, gboolean pause_times, gboolean color_output, unsigned long long first_entry_to_consider); + +gboolean +sgen_binary_protocol_grep_entries (EntryStream *stream, int num_nums, long nums [], int num_vtables, long vtables [], + gboolean dump_all, gboolean pause_times, gboolean color_output, unsigned long long first_entry_to_consider); +gboolean +sgen_binary_protocol_grep_entries32p (EntryStream *stream, int num_nums, long nums [], int num_vtables, long vtables [], + gboolean dump_all, gboolean pause_times, gboolean color_output, unsigned long long first_entry_to_consider); +gboolean +sgen_binary_protocol_grep_entries64p (EntryStream *stream, int num_nums, long nums [], int num_vtables, long vtables [], + gboolean dump_all, gboolean pause_times, gboolean color_output, unsigned long long first_entry_to_consider);